From 94aa31c3cbae7c929b8a412768b74631f4a6b461 Mon Sep 17 00:00:00 2001 From: TakayukiMatsuo <62984531+TakayukiMatsuo@users.noreply.github.com> Date: Sat, 8 Aug 2020 07:58:14 +0900 Subject: [PATCH] Update wolfSSL to the latest version(v.4.4.0) (#186) * deleted old version wolfSSL before updating * updated wolfSSL to the latest version(v4.4.0) * updated wolfSSL to the latest version(v4.4.0) * added macros for timing resistance Co-authored-by: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Co-authored-by: Ming Yue --- .../FreeRTOS_Plus_WolfSSL.sln | 17 +- .../WIN32.vcxproj | 306 +- .../WIN32.vcxproj.filters | 533 +- .../ca-cert.pem | 56 +- .../server-cert.pem | 110 +- .../user_settings.h | 55 + FreeRTOS-Plus/Source/WolfSSL/ChangeLog.md | 2545 + FreeRTOS-Plus/Source/WolfSSL/INSTALL | 36 +- .../WolfSSL/{ChangeLog => IPP/.gitkeep} | 0 FreeRTOS-Plus/Source/WolfSSL/LICENSING | 6 +- .../Source/WolfSSL/LPCExpresso.cproject | 266 + .../Source/WolfSSL/LPCExpresso.project | 28 + FreeRTOS-Plus/Source/WolfSSL/Makefile.am | 170 +- FreeRTOS-Plus/Source/WolfSSL/Makefile.in | 5580 +- FreeRTOS-Plus/Source/WolfSSL/README | 1238 +- FreeRTOS-Plus/Source/WolfSSL/README.md | 1358 +- FreeRTOS-Plus/Source/WolfSSL/ReadMeFirst.url | 5 - FreeRTOS-Plus/Source/WolfSSL/aclocal.m4 | 214 +- .../Source/WolfSSL/build-aux/compile | 17 +- .../Source/WolfSSL/build-aux/config.guess | 977 +- .../Source/WolfSSL/build-aux/config.sub | 2750 +- .../Source/WolfSSL/build-aux/depcomp | 10 +- .../Source/WolfSSL/build-aux/install-sh | 398 +- .../Source/WolfSSL/build-aux/ltmain.sh | 5579 +- .../Source/WolfSSL/build-aux/missing | 16 +- .../Source/WolfSSL/build-aux/test-driver | 23 +- .../Source/WolfSSL/certs/1024/ca-cert.der | Bin 0 -> 953 bytes .../Source/WolfSSL/certs/1024/ca-cert.pem | 65 + .../Source/WolfSSL/certs/1024/ca-key.der | Bin 0 -> 610 bytes .../Source/WolfSSL/certs/1024/ca-key.pem | 15 + .../Source/WolfSSL/certs/1024/client-cert.der | Bin 969 -> 969 bytes .../Source/WolfSSL/certs/1024/client-cert.pem | 38 +- .../WolfSSL/certs/1024/client-keyPub.der | Bin 0 -> 162 bytes .../WolfSSL/certs/1024/dsa-pub-1024.pem | 12 + .../Source/WolfSSL/certs/1024/include.am | 17 +- .../Source/WolfSSL/certs/1024/server-cert.der | Bin 0 -> 941 bytes .../Source/WolfSSL/certs/1024/server-cert.pem | 130 + .../Source/WolfSSL/certs/1024/server-key.der | Bin 0 -> 609 bytes .../Source/WolfSSL/certs/1024/server-key.pem | 15 + .../Source/WolfSSL/certs/3072/client-cert.der | Bin 0 -> 1532 bytes .../Source/WolfSSL/certs/3072/client-cert.pem | 111 + .../Source/WolfSSL/certs/3072/client-key.der | Bin 0 -> 1768 bytes .../Source/WolfSSL/certs/3072/client-key.pem | 39 + .../WolfSSL/certs/3072/client-keyPub.der | Bin 0 -> 422 bytes .../Source/WolfSSL/certs/3072/include.am | 10 + .../Source/WolfSSL/certs/4096/client-cert.der | Bin 0 -> 1764 bytes .../Source/WolfSSL/certs/4096/client-cert.pem | 130 + .../Source/WolfSSL/certs/4096/client-key.der | Bin 0 -> 2348 bytes .../Source/WolfSSL/certs/4096/client-key.pem | 51 + .../WolfSSL/certs/4096/client-keyPub.der | Bin 0 -> 550 bytes .../Source/WolfSSL/certs/4096/include.am | 10 + .../Source/WolfSSL/certs/ca-cert-chain.der | Bin 0 -> 2151 bytes .../Source/WolfSSL/certs/ca-cert.der | Bin 1198 -> 1198 bytes .../Source/WolfSSL/certs/ca-cert.pem | 56 +- .../Source/WolfSSL/certs/ca-ecc-cert.der | Bin 0 -> 655 bytes .../Source/WolfSSL/certs/ca-ecc-cert.pem | 52 + .../Source/WolfSSL/certs/ca-ecc-key.der | Bin 0 -> 121 bytes .../Source/WolfSSL/certs/ca-ecc-key.pem | 5 + .../Source/WolfSSL/certs/ca-ecc384-cert.der | Bin 0 -> 715 bytes .../Source/WolfSSL/certs/ca-ecc384-cert.pem | 57 + .../Source/WolfSSL/certs/ca-ecc384-key.der | Bin 0 -> 167 bytes .../Source/WolfSSL/certs/ca-ecc384-key.pem | 6 + .../Source/WolfSSL/certs/client-ca.pem | 142 + .../Source/WolfSSL/certs/client-cert-ext.der | Bin 0 -> 1292 bytes .../Source/WolfSSL/certs/client-cert-ext.pem | 93 + .../Source/WolfSSL/certs/client-cert.der | Bin 1230 -> 1230 bytes .../Source/WolfSSL/certs/client-cert.pem | 56 +- .../Source/WolfSSL/certs/client-ecc-cert.der | Bin 0 -> 780 bytes .../Source/WolfSSL/certs/client-ecc-cert.pem | 29 +- .../Source/WolfSSL/certs/client-keyPub.der | Bin 0 -> 294 bytes .../WolfSSL/certs/client-relative-uri.pem | 90 + .../Source/WolfSSL/certs/client-uri-cert.pem | 89 + .../Source/WolfSSL/certs/crl/ca-int-ecc.pem | 10 + .../Source/WolfSSL/certs/crl/ca-int.pem | 14 + .../Source/WolfSSL/certs/crl/caEcc384Crl.pem | 29 + .../Source/WolfSSL/certs/crl/caEccCrl.pem | 26 + .../Source/WolfSSL/certs/crl/cliCrl.pem | 59 +- .../WolfSSL/certs/crl/client-int-ecc.pem | 10 + .../Source/WolfSSL/certs/crl/client-int.pem | 14 + .../Source/WolfSSL/certs/crl/crl.pem | 58 +- .../Source/WolfSSL/certs/crl/crl.revoked | 63 +- .../Source/WolfSSL/certs/crl/crl2.pem | 80 + .../Source/WolfSSL/certs/crl/eccCliCRL.pem | 28 +- .../Source/WolfSSL/certs/crl/eccSrvCRL.pem | 28 +- .../Source/WolfSSL/certs/crl/include.am | 15 +- .../WolfSSL/certs/crl/server-goodaltCrl.pem | 38 + .../certs/crl/server-goodaltwildCrl.pem | 38 + .../WolfSSL/certs/crl/server-goodcnCrl.pem | 38 + .../certs/crl/server-goodcnwildCrl.pem | 38 + .../WolfSSL/certs/crl/server-int-ecc.pem | 10 + .../Source/WolfSSL/certs/crl/server-int.pem | 14 + .../Source/WolfSSL/certs/crl/wolfssl.cnf | 110 + FreeRTOS-Plus/Source/WolfSSL/certs/dh3072.der | Bin 0 -> 396 bytes FreeRTOS-Plus/Source/WolfSSL/certs/dh3072.pem | 11 + FreeRTOS-Plus/Source/WolfSSL/certs/dh4096.der | Bin 0 -> 524 bytes FreeRTOS-Plus/Source/WolfSSL/certs/dh4096.pem | 13 + .../Source/WolfSSL/certs/dsa3072.der | Bin 0 -> 1243 bytes .../Source/WolfSSL/certs/dsaparams.pem | 9 + .../Source/WolfSSL/certs/ecc-client-key.der | Bin 0 -> 121 bytes .../WolfSSL/certs/ecc-client-keyPub.der | Bin 0 -> 91 bytes .../WolfSSL/certs/ecc-client-keyPub.pem | 4 + .../Source/WolfSSL/certs/ecc-keyPkcs8.der | Bin 0 -> 138 bytes .../Source/WolfSSL/certs/ecc-keyPkcs8Enc.der | Bin 0 -> 179 bytes .../Source/WolfSSL/certs/ecc-keyPkcs8Enc.pem | 6 + .../Source/WolfSSL/certs/ecc-keyPub.der | Bin 0 -> 91 bytes .../Source/WolfSSL/certs/ecc-privOnlyCert.pem | 9 + .../Source/WolfSSL/certs/ecc-privOnlyKey.pem | 4 + .../Source/WolfSSL/certs/ecc-privkey.pem | 4 + .../Source/WolfSSL/certs/ecc-privkeyPkcs8.der | Bin 0 -> 121 bytes .../Source/WolfSSL/certs/ecc-privkeyPkcs8.pem | 4 + .../Source/WolfSSL/certs/ecc-rsa-server.p12 | Bin 0 -> 2406 bytes .../Source/WolfSSL/certs/ecc/genecc.sh | 91 + .../Source/WolfSSL/certs/ecc/include.am | 8 + .../Source/WolfSSL/certs/ecc/wolfssl.cnf | 110 + .../Source/WolfSSL/certs/ecc/wolfssl_384.cnf | 110 + .../WolfSSL/certs/ed25519/ca-ed25519-key.der | Bin 0 -> 84 bytes .../WolfSSL/certs/ed25519/ca-ed25519-key.pem | 4 + .../WolfSSL/certs/ed25519/ca-ed25519-priv.der | Bin 0 -> 48 bytes .../WolfSSL/certs/ed25519/ca-ed25519-priv.pem | 3 + .../WolfSSL/certs/ed25519/ca-ed25519.der | Bin 0 -> 612 bytes .../WolfSSL/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-priv.der | Bin 0 -> 48 bytes .../certs/ed25519/client-ed25519-priv.pem | 3 + .../WolfSSL/certs/ed25519/client-ed25519.der | Bin 0 -> 604 bytes .../WolfSSL/certs/ed25519/client-ed25519.pem | 15 + .../Source/WolfSSL/certs/ed25519/include.am | 30 + .../certs/ed25519/root-ed25519-key.der | Bin 0 -> 84 bytes .../certs/ed25519/root-ed25519-key.pem | 4 + .../certs/ed25519/root-ed25519-priv.der | Bin 0 -> 48 bytes .../certs/ed25519/root-ed25519-priv.pem | 3 + .../WolfSSL/certs/ed25519/root-ed25519.der | Bin 0 -> 614 bytes .../WolfSSL/certs/ed25519/root-ed25519.pem | 15 + .../certs/ed25519/server-ed25519-cert.pem | 15 + .../certs/ed25519/server-ed25519-key.der | Bin 0 -> 84 bytes .../certs/ed25519/server-ed25519-key.pem | 4 + .../certs/ed25519/server-ed25519-priv.der | Bin 0 -> 48 bytes .../certs/ed25519/server-ed25519-priv.pem | 3 + .../WolfSSL/certs/ed25519/server-ed25519.der | Bin 0 -> 598 bytes .../WolfSSL/certs/ed25519/server-ed25519.pem | 30 + .../WolfSSL/certs/ed448/ca-ed448-key.der | Bin 0 -> 69 bytes .../WolfSSL/certs/ed448/ca-ed448-key.pem | 4 + .../WolfSSL/certs/ed448/ca-ed448-priv.der | Bin 0 -> 73 bytes .../WolfSSL/certs/ed448/ca-ed448-priv.pem | 4 + .../Source/WolfSSL/certs/ed448/ca-ed448.der | Bin 0 -> 659 bytes .../Source/WolfSSL/certs/ed448/ca-ed448.pem | 52 + .../WolfSSL/certs/ed448/client-ed448-key.der | Bin 0 -> 69 bytes .../WolfSSL/certs/ed448/client-ed448-key.pem | 4 + .../WolfSSL/certs/ed448/client-ed448-priv.der | Bin 0 -> 73 bytes .../WolfSSL/certs/ed448/client-ed448-priv.pem | 4 + .../WolfSSL/certs/ed448/client-ed448.der | Bin 0 -> 882 bytes .../WolfSSL/certs/ed448/client-ed448.pem | 60 + .../Source/WolfSSL/certs/ed448/include.am | 30 + .../WolfSSL/certs/ed448/root-ed448-key.der | Bin 0 -> 69 bytes .../WolfSSL/certs/ed448/root-ed448-key.pem | 4 + .../WolfSSL/certs/ed448/root-ed448-priv.der | Bin 0 -> 73 bytes .../WolfSSL/certs/ed448/root-ed448-priv.pem | 4 + .../Source/WolfSSL/certs/ed448/root-ed448.der | Bin 0 -> 680 bytes .../Source/WolfSSL/certs/ed448/root-ed448.pem | 54 + .../WolfSSL/certs/ed448/server-ed448-cert.pem | 57 + .../WolfSSL/certs/ed448/server-ed448-key.der | Bin 0 -> 69 bytes .../WolfSSL/certs/ed448/server-ed448-key.pem | 4 + .../WolfSSL/certs/ed448/server-ed448-priv.der | Bin 0 -> 73 bytes .../WolfSSL/certs/ed448/server-ed448-priv.pem | 4 + .../WolfSSL/certs/ed448/server-ed448.der | Bin 0 -> 700 bytes .../WolfSSL/certs/ed448/server-ed448.pem | 109 + .../external/baltimore-cybertrust-root.pem | 21 + .../WolfSSL/certs/external/ca-digicert-ev.pem | 23 + .../certs/external/ca-globalsign-root.pem | 42 + .../WolfSSL/certs/external/ca-google-root.pem | 22 + .../Source/WolfSSL/certs/external/include.am | 9 + FreeRTOS-Plus/Source/WolfSSL/certs/include.am | 73 +- .../certs/intermediate/ca-int-cert.der | Bin 0 -> 1051 bytes .../certs/intermediate/ca-int-cert.pem | 83 + .../certs/intermediate/ca-int-ecc-cert.der | Bin 0 -> 661 bytes .../certs/intermediate/ca-int-ecc-cert.pem | 52 + .../certs/intermediate/ca-int-ecc-key.der | Bin 0 -> 121 bytes .../certs/intermediate/ca-int-ecc-key.pem | 5 + .../WolfSSL/certs/intermediate/ca-int-key.der | Bin 0 -> 1194 bytes .../WolfSSL/certs/intermediate/ca-int-key.pem | 27 + .../intermediate/client-chain-alt-ecc.pem | 55 + .../certs/intermediate/client-chain-alt.pem | 71 + .../certs/intermediate/client-chain-ecc.der | Bin 0 -> 1375 bytes .../certs/intermediate/client-chain-ecc.pem | 33 + .../certs/intermediate/client-chain.der | Bin 0 -> 2153 bytes .../certs/intermediate/client-chain.pem | 49 + .../certs/intermediate/client-int-cert.der | Bin 0 -> 1102 bytes .../certs/intermediate/client-int-cert.pem | 88 + .../intermediate/client-int-ecc-cert.der | Bin 0 -> 714 bytes .../intermediate/client-int-ecc-cert.pem | 57 + .../WolfSSL/certs/intermediate/genintcerts.sh | 293 + .../WolfSSL/certs/intermediate/include.am | 34 + .../intermediate/server-chain-alt-ecc.pem | 59 + .../certs/intermediate/server-chain-alt.pem | 75 + .../certs/intermediate/server-chain-ecc.der | Bin 0 -> 1533 bytes .../certs/intermediate/server-chain-ecc.pem | 37 + .../certs/intermediate/server-chain.der | Bin 0 -> 2309 bytes .../certs/intermediate/server-chain.pem | 53 + .../certs/intermediate/server-int-cert.der | Bin 0 -> 1258 bytes .../certs/intermediate/server-int-cert.pem | 94 + .../intermediate/server-int-ecc-cert.der | Bin 0 -> 872 bytes .../intermediate/server-int-ecc-cert.pem | 63 + .../Source/WolfSSL/certs/ntru-cert.pem | 53 +- .../Source/WolfSSL/certs/ntru-key.raw | Bin 607 -> 607 bytes .../Source/WolfSSL/certs/ocsp/include.am | 35 + .../ocsp/index-ca-and-intermediate-cas.txt | 4 + .../index-ca-and-intermediate-cas.txt.attr | 1 + .../index-intermediate1-ca-issued-certs.txt | 2 + ...dex-intermediate1-ca-issued-certs.txt.attr | 1 + .../index-intermediate2-ca-issued-certs.txt | 2 + ...dex-intermediate2-ca-issued-certs.txt.attr | 1 + .../index-intermediate3-ca-issued-certs.txt | 1 + ...dex-intermediate3-ca-issued-certs.txt.attr | 1 + .../certs/ocsp/intermediate1-ca-cert.pem | 186 + .../certs/ocsp/intermediate1-ca-key.pem | 28 + .../certs/ocsp/intermediate2-ca-cert.pem | 186 + .../certs/ocsp/intermediate2-ca-key.pem | 28 + .../certs/ocsp/intermediate3-ca-cert.pem | 186 + .../certs/ocsp/intermediate3-ca-key.pem | 28 + .../certs/ocsp/ocsp-responder-cert.pem | 182 + .../WolfSSL/certs/ocsp/ocsp-responder-key.pem | 27 + .../Source/WolfSSL/certs/ocsp/openssl.cnf | 42 + .../WolfSSL/certs/ocsp/renewcerts-for-test.sh | 63 + .../WolfSSL/certs/ocsp/root-ca-cert.pem | 93 + .../Source/WolfSSL/certs/ocsp/root-ca-key.pem | 28 + .../WolfSSL/certs/ocsp/server1-cert.pem | 279 + .../Source/WolfSSL/certs/ocsp/server1-key.pem | 28 + .../WolfSSL/certs/ocsp/server2-cert.pem | 279 + .../Source/WolfSSL/certs/ocsp/server2-key.pem | 28 + .../WolfSSL/certs/ocsp/server3-cert.pem | 279 + .../Source/WolfSSL/certs/ocsp/server3-key.pem | 28 + .../WolfSSL/certs/ocsp/server4-cert.pem | 279 + .../Source/WolfSSL/certs/ocsp/server4-key.pem | 28 + .../WolfSSL/certs/ocsp/server5-cert.pem | 279 + .../Source/WolfSSL/certs/ocsp/server5-key.pem | 28 + .../Source/WolfSSL/certs/rsa-pub-2048.pem | 9 + .../Source/WolfSSL/certs/rsa3072.der | Bin 0 -> 1768 bytes .../WolfSSL/certs/server-cert-chain.der | Bin 0 -> 2384 bytes .../Source/WolfSSL/certs/server-cert.der | Bin 1186 -> 1186 bytes .../Source/WolfSSL/certs/server-cert.pem | 110 +- .../Source/WolfSSL/certs/server-ecc-comp.der | Bin 0 -> 807 bytes .../Source/WolfSSL/certs/server-ecc-comp.pem | 27 +- .../Source/WolfSSL/certs/server-ecc-rsa.der | Bin 0 -> 996 bytes .../Source/WolfSSL/certs/server-ecc-rsa.pem | 55 +- .../Source/WolfSSL/certs/server-ecc-self.der | Bin 0 -> 788 bytes .../Source/WolfSSL/certs/server-ecc-self.pem | 55 + .../Source/WolfSSL/certs/server-ecc.der | Bin 0 -> 852 bytes .../Source/WolfSSL/certs/server-ecc.pem | 68 +- .../Source/WolfSSL/certs/server-keyPkcs8.der | Bin 0 -> 1219 bytes .../WolfSSL/certs/server-keyPkcs8Enc.der | Bin 0 -> 1261 bytes .../WolfSSL/certs/server-revoked-cert.pem | 173 + .../WolfSSL/certs/server-revoked-key.pem | 27 + .../Source/WolfSSL/certs/taoCert.txt | 4 +- .../WolfSSL/certs/test-ber-exp02-05-2022.p7b | Bin 0 -> 2544 bytes .../Source/WolfSSL/certs/test-degenerate.p7b | Bin 0 -> 1279 bytes .../certs/test-pathlen/chainA-ICA1-key.pem | 27 + .../test-pathlen/chainA-ICA1-pathlen0.pem | 89 + .../certs/test-pathlen/chainA-assembled.pem | 175 + .../certs/test-pathlen/chainA-entity-key.pem | 27 + .../certs/test-pathlen/chainA-entity.pem | 86 + .../certs/test-pathlen/chainB-ICA1-key.pem | 27 + .../test-pathlen/chainB-ICA1-pathlen0.pem | 89 + .../certs/test-pathlen/chainB-ICA2-key.pem | 27 + .../test-pathlen/chainB-ICA2-pathlen1.pem | 89 + .../certs/test-pathlen/chainB-assembled.pem | 265 + .../certs/test-pathlen/chainB-entity-key.pem | 27 + .../certs/test-pathlen/chainB-entity.pem | 87 + .../certs/test-pathlen/chainC-ICA1-key.pem | 27 + .../test-pathlen/chainC-ICA1-pathlen1.pem | 89 + .../certs/test-pathlen/chainC-assembled.pem | 175 + .../certs/test-pathlen/chainC-entity-key.pem | 27 + .../certs/test-pathlen/chainC-entity.pem | 86 + .../certs/test-pathlen/chainD-ICA1-key.pem | 27 + .../test-pathlen/chainD-ICA1-pathlen127.pem | 89 + .../certs/test-pathlen/chainD-assembled.pem | 175 + .../certs/test-pathlen/chainD-entity-key.pem | 27 + .../certs/test-pathlen/chainD-entity.pem | 86 + .../certs/test-pathlen/chainE-ICA1-key.pem | 27 + .../test-pathlen/chainE-ICA1-pathlen128.pem | 89 + .../certs/test-pathlen/chainE-assembled.pem | 175 + .../certs/test-pathlen/chainE-entity-key.pem | 27 + .../certs/test-pathlen/chainE-entity.pem | 86 + .../certs/test-pathlen/chainF-ICA1-key.pem | 27 + .../test-pathlen/chainF-ICA1-pathlen1.pem | 89 + .../certs/test-pathlen/chainF-ICA2-key.pem | 27 + .../test-pathlen/chainF-ICA2-pathlen0.pem | 89 + .../certs/test-pathlen/chainF-assembled.pem | 265 + .../certs/test-pathlen/chainF-entity-key.pem | 27 + .../certs/test-pathlen/chainF-entity.pem | 87 + .../certs/test-pathlen/chainG-ICA1-key.pem | 27 + .../test-pathlen/chainG-ICA1-pathlen0.pem | 89 + .../certs/test-pathlen/chainG-ICA2-key.pem | 27 + .../test-pathlen/chainG-ICA2-pathlen1.pem | 89 + .../certs/test-pathlen/chainG-ICA3-key.pem | 27 + .../test-pathlen/chainG-ICA3-pathlen99.pem | 89 + .../certs/test-pathlen/chainG-ICA4-key.pem | 27 + .../test-pathlen/chainG-ICA4-pathlen5.pem | 89 + .../certs/test-pathlen/chainG-ICA5-key.pem | 27 + .../test-pathlen/chainG-ICA5-pathlen20.pem | 89 + .../certs/test-pathlen/chainG-ICA6-key.pem | 27 + .../test-pathlen/chainG-ICA6-pathlen10.pem | 89 + .../certs/test-pathlen/chainG-ICA7-key.pem | 27 + .../test-pathlen/chainG-ICA7-pathlen100.pem | 89 + .../certs/test-pathlen/chainG-assembled.pem | 710 + .../certs/test-pathlen/chainG-entity-key.pem | 27 + .../certs/test-pathlen/chainG-entity.pem | 87 + .../certs/test-pathlen/chainH-ICA1-key.pem | 27 + .../test-pathlen/chainH-ICA1-pathlen0.pem | 89 + .../certs/test-pathlen/chainH-ICA2-key.pem | 27 + .../test-pathlen/chainH-ICA2-pathlen2.pem | 89 + .../certs/test-pathlen/chainH-ICA3-key.pem | 27 + .../test-pathlen/chainH-ICA3-pathlen2.pem | 89 + .../certs/test-pathlen/chainH-ICA4-key.pem | 27 + .../test-pathlen/chainH-ICA4-pathlen2.pem | 89 + .../certs/test-pathlen/chainH-assembled.pem | 443 + .../certs/test-pathlen/chainH-entity-key.pem | 27 + .../certs/test-pathlen/chainH-entity.pem | 87 + .../certs/test-pathlen/chainI-ICA1-key.pem | 27 + .../test-pathlen/chainI-ICA1-no_pathlen.pem | 89 + .../certs/test-pathlen/chainI-ICA2-key.pem | 27 + .../test-pathlen/chainI-ICA2-no_pathlen.pem | 89 + .../certs/test-pathlen/chainI-ICA3-key.pem | 27 + .../test-pathlen/chainI-ICA3-pathlen2.pem | 89 + .../certs/test-pathlen/chainI-assembled.pem | 354 + .../certs/test-pathlen/chainI-entity-key.pem | 27 + .../certs/test-pathlen/chainI-entity.pem | 87 + .../certs/test-pathlen/chainJ-ICA1-key.pem | 27 + .../test-pathlen/chainJ-ICA1-no_pathlen.pem | 89 + .../certs/test-pathlen/chainJ-ICA2-key.pem | 27 + .../test-pathlen/chainJ-ICA2-no_pathlen.pem | 89 + .../certs/test-pathlen/chainJ-ICA3-key.pem | 27 + .../test-pathlen/chainJ-ICA3-no_pathlen.pem | 89 + .../certs/test-pathlen/chainJ-ICA4-key.pem | 27 + .../test-pathlen/chainJ-ICA4-pathlen2.pem | 89 + .../certs/test-pathlen/chainJ-assembled.pem | 443 + .../certs/test-pathlen/chainJ-entity-key.pem | 27 + .../certs/test-pathlen/chainJ-entity.pem | 87 + .../WolfSSL/certs/test-pathlen/include.am | 88 + .../Source/WolfSSL/certs/test-servercert.p12 | Bin 0 -> 5277 bytes .../Source/WolfSSL/certs/test/cert-ext-ia.cfg | 18 + .../Source/WolfSSL/certs/test/cert-ext-ia.der | Bin 0 -> 1022 bytes .../WolfSSL/certs/test/cert-ext-joi.pem | 76 + .../Source/WolfSSL/certs/test/cert-ext-nc.cfg | 22 + .../Source/WolfSSL/certs/test/cert-ext-nc.der | Bin 0 -> 1146 bytes .../WolfSSL/certs/test/cert-ext-nct.cfg | 18 + .../WolfSSL/certs/test/cert-ext-nct.der | Bin 0 -> 1054 bytes .../Source/WolfSSL/certs/test/cert-ext-ns.der | Bin 0 -> 4677 bytes .../Source/WolfSSL/certs/test/crit-cert.pem | 18 + .../Source/WolfSSL/certs/test/crit-key.pem | 9 + .../Source/WolfSSL/certs/test/dh1024.der | Bin 0 -> 138 bytes .../Source/WolfSSL/certs/test/dh1024.pem | 17 + .../Source/WolfSSL/certs/test/dh512.der | Bin 0 -> 72 bytes .../Source/WolfSSL/certs/test/dh512.pem | 12 + .../Source/WolfSSL/certs/test/digsigku.pem | 57 + .../WolfSSL/certs/test/expired/expired-ca.der | Bin 0 -> 857 bytes .../WolfSSL/certs/test/expired/expired-ca.pem | 69 + .../certs/test/expired/expired-cert.der | Bin 0 -> 857 bytes .../certs/test/expired/expired-cert.pem | 69 + .../WolfSSL/certs/test/gen-ext-certs.sh | 98 + .../WolfSSL/certs/test/gen-testcerts.sh | 205 + .../Source/WolfSSL/certs/test/include.am | 64 + .../WolfSSL/certs/test/server-badaltname.der | Bin 0 -> 939 bytes .../WolfSSL/certs/test/server-badaltname.pem | 75 + .../WolfSSL/certs/test/server-badaltnull.der | Bin 0 -> 972 bytes .../WolfSSL/certs/test/server-badaltnull.pem | 76 + .../WolfSSL/certs/test/server-badcn.der | Bin 0 -> 907 bytes .../WolfSSL/certs/test/server-badcn.pem | 71 + .../WolfSSL/certs/test/server-badcnnull.der | Bin 0 -> 973 bytes .../WolfSSL/certs/test/server-badcnnull.pem | 73 + .../certs/test/server-cert-ecc-badsig.der | Bin 0 -> 852 bytes .../certs/test/server-cert-ecc-badsig.pem | 62 + .../certs/test/server-cert-rsa-badsig.der | Bin 0 -> 1186 bytes .../certs/test/server-cert-rsa-badsig.pem | 172 + .../certs/test/server-duplicate-policy.pem | 182 + .../WolfSSL/certs/test/server-garbage.der | Bin 0 -> 917 bytes .../WolfSSL/certs/test/server-garbage.pem | 75 + .../WolfSSL/certs/test/server-goodalt.der | Bin 0 -> 933 bytes .../WolfSSL/certs/test/server-goodalt.pem | 75 + .../WolfSSL/certs/test/server-goodaltwild.der | Bin 0 -> 934 bytes .../WolfSSL/certs/test/server-goodaltwild.pem | 75 + .../WolfSSL/certs/test/server-goodcn.der | Bin 0 -> 893 bytes .../WolfSSL/certs/test/server-goodcn.pem | 71 + .../WolfSSL/certs/test/server-goodcnwild.der | Bin 0 -> 895 bytes .../WolfSSL/certs/test/server-goodcnwild.pem | 71 + .../WolfSSL/certs/test/server-localhost.der | Bin 0 -> 919 bytes .../WolfSSL/certs/test/server-localhost.pem | 75 + .../WolfSSL/certs/wolfssl-website-ca.pem | 126 +- FreeRTOS-Plus/Source/WolfSSL/config.in | 21 +- FreeRTOS-Plus/Source/WolfSSL/configure | 20666 ++-- FreeRTOS-Plus/Source/WolfSSL/configure.ac | 5018 +- .../Source/WolfSSL/ctaocrypt/src/misc.c | 8 +- .../WolfSSL/ctaocrypt/src/wolfcrypt_first.c | 13 +- .../WolfSSL/ctaocrypt/src/wolfcrypt_last.c | 13 +- .../Source/WolfSSL/cyassl/callbacks.h | 7 +- FreeRTOS-Plus/Source/WolfSSL/cyassl/crl.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/aes.h | 12 +- .../Source/WolfSSL/cyassl/ctaocrypt/arc4.h | 12 +- .../Source/WolfSSL/cyassl/ctaocrypt/asn.h | 11 +- .../WolfSSL/cyassl/ctaocrypt/asn_public.h | 7 +- .../WolfSSL/cyassl/ctaocrypt/blake2-impl.h | 9 +- .../WolfSSL/cyassl/ctaocrypt/blake2-int.h | 9 +- .../Source/WolfSSL/cyassl/ctaocrypt/blake2.h | 7 +- .../WolfSSL/cyassl/ctaocrypt/camellia.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/chacha.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/coding.h | 7 +- .../WolfSSL/cyassl/ctaocrypt/compress.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/des3.h | 13 +- .../Source/WolfSSL/cyassl/ctaocrypt/dh.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/dsa.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/ecc.h | 7 +- .../WolfSSL/cyassl/ctaocrypt/error-crypt.h | 7 +- .../WolfSSL/cyassl/ctaocrypt/fips_test.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/hc128.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/hmac.h | 13 +- .../Source/WolfSSL/cyassl/ctaocrypt/integer.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/logging.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/md2.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/md4.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/md5.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/memory.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/misc.h | 7 +- .../WolfSSL/cyassl/ctaocrypt/mpi_class.h | 7 +- .../WolfSSL/cyassl/ctaocrypt/mpi_superclass.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/pkcs7.h | 9 +- .../WolfSSL/cyassl/ctaocrypt/poly1305.h | 7 +- .../ctaocrypt/port/pic32/pic32mz-crypt.h | 7 +- .../WolfSSL/cyassl/ctaocrypt/pwdbased.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/rabbit.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/random.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/ripemd.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/rsa.h | 14 +- .../WolfSSL/cyassl/ctaocrypt/settings.h | 88 +- .../WolfSSL/cyassl/ctaocrypt/settings_comp.h | 22 +- .../Source/WolfSSL/cyassl/ctaocrypt/sha.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/sha256.h | 15 +- .../Source/WolfSSL/cyassl/ctaocrypt/sha512.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/tfm.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/types.h | 8 +- .../WolfSSL/cyassl/ctaocrypt/visibility.h | 7 +- .../Source/WolfSSL/cyassl/ctaocrypt/wc_port.h | 7 +- .../Source/WolfSSL/cyassl/error-ssl.h | 7 +- .../Source/WolfSSL/cyassl/include.am | 8 +- .../Source/WolfSSL/cyassl/internal.h | 7 +- FreeRTOS-Plus/Source/WolfSSL/cyassl/ocsp.h | 7 +- .../Source/WolfSSL/cyassl/openssl/des.h | 9 +- .../Source/WolfSSL/cyassl/openssl/dsa.h | 9 + .../Source/WolfSSL/cyassl/openssl/ec25519.h | 3 + .../Source/WolfSSL/cyassl/openssl/ec448.h | 3 + .../Source/WolfSSL/cyassl/openssl/ecdh.h | 3 + .../Source/WolfSSL/cyassl/openssl/ed25519.h | 3 + .../Source/WolfSSL/cyassl/openssl/ed448.h | 3 + .../Source/WolfSSL/cyassl/openssl/evp.h | 22 +- .../Source/WolfSSL/cyassl/openssl/hmac.h | 9 +- .../Source/WolfSSL/cyassl/openssl/include.am | 6 + .../Source/WolfSSL/cyassl/openssl/rsa.h | 9 + .../Source/WolfSSL/cyassl/openssl/ssl.h | 17 +- .../Source/WolfSSL/cyassl/openssl/ssl23.h | 3 + FreeRTOS-Plus/Source/WolfSSL/cyassl/options.h | 109 +- .../Source/WolfSSL/cyassl/options.h.in | 40 + FreeRTOS-Plus/Source/WolfSSL/cyassl/sniffer.h | 7 +- .../Source/WolfSSL/cyassl/sniffer_error.h | 7 +- FreeRTOS-Plus/Source/WolfSSL/cyassl/ssl.h | 35 +- FreeRTOS-Plus/Source/WolfSSL/cyassl/version.h | 7 +- FreeRTOS-Plus/Source/WolfSSL/doc/README.txt | 5 + FreeRTOS-Plus/Source/WolfSSL/doc/include.am | 16 + .../WolfSSL/examples/benchmark/include.am | 15 + .../WolfSSL/examples/benchmark/tls_bench.c | 1948 + .../WolfSSL/examples/benchmark/tls_bench.h | 30 + .../Source/WolfSSL/examples/client/client.c | 3275 +- .../Source/WolfSSL/examples/client/client.h | 14 +- .../WolfSSL/examples/client/client.vcproj | 12 +- .../WolfSSL/examples/client/client.vcxproj | 36 +- .../Source/WolfSSL/examples/client/include.am | 4 +- .../WolfSSL/examples/echoclient/echoclient.c | 261 +- .../WolfSSL/examples/echoclient/echoclient.h | 15 +- .../examples/echoclient/echoclient.vcproj | 12 +- .../examples/echoclient/echoclient.vcxproj | 38 +- .../WolfSSL/examples/echoclient/include.am | 4 +- .../WolfSSL/examples/echoserver/echoserver.c | 332 +- .../WolfSSL/examples/echoserver/echoserver.h | 15 +- .../examples/echoserver/echoserver.vcproj | 12 +- .../examples/echoserver/echoserver.vcxproj | 37 +- .../WolfSSL/examples/echoserver/include.am | 4 +- .../Source/WolfSSL/examples/include.am | 9 + .../Source/WolfSSL/examples/sctp/include.am | 38 + .../WolfSSL/examples/sctp/sctp-client-dtls.c | 130 + .../WolfSSL/examples/sctp/sctp-client.c | 72 + .../WolfSSL/examples/sctp/sctp-server-dtls.c | 128 + .../WolfSSL/examples/sctp/sctp-server.c | 77 + .../Source/WolfSSL/examples/server/include.am | 4 +- .../Source/WolfSSL/examples/server/server.c | 2546 +- .../Source/WolfSSL/examples/server/server.h | 19 +- .../WolfSSL/examples/server/server.vcproj | 12 +- .../WolfSSL/examples/server/server.vcxproj | 38 +- FreeRTOS-Plus/Source/WolfSSL/fips-hash.sh | 20 + FreeRTOS-Plus/Source/WolfSSL/gencertbuf.pl | 156 +- FreeRTOS-Plus/Source/WolfSSL/input | 4 +- .../Source/WolfSSL/m4/ax_add_am_macro.m4 | 4 +- .../Source/WolfSSL/m4/ax_am_jobserver.m4 | 9 +- .../Source/WolfSSL/m4/ax_am_macros.m4 | 6 +- .../WolfSSL/m4/ax_append_compile_flags.m4 | 20 +- .../Source/WolfSSL/m4/ax_append_flag.m4 | 34 +- .../Source/WolfSSL/m4/ax_append_to_file.m4 | 6 +- .../WolfSSL/m4/ax_check_compile_flag.m4 | 16 +- .../Source/WolfSSL/m4/ax_check_link_flag.m4 | 17 +- .../Source/WolfSSL/m4/ax_count_cpus.m4 | 106 +- .../WolfSSL/m4/ax_create_generic_config.m4 | 4 +- .../Source/WolfSSL/m4/ax_file_escapes.m4 | 4 +- .../WolfSSL/m4/ax_harden_compiler_flags.m4 | 10 +- .../Source/WolfSSL/m4/ax_print_to_file.m4 | 4 +- FreeRTOS-Plus/Source/WolfSSL/m4/ax_pthread.m4 | 397 +- .../Source/WolfSSL/m4/ax_require_defined.m4 | 37 + .../Source/WolfSSL/m4/ax_vcs_checkout.m4 | 7 +- FreeRTOS-Plus/Source/WolfSSL/m4/libtool.m4 | 2559 +- FreeRTOS-Plus/Source/WolfSSL/m4/ltoptions.m4 | 127 +- FreeRTOS-Plus/Source/WolfSSL/m4/ltsugar.m4 | 7 +- FreeRTOS-Plus/Source/WolfSSL/m4/ltversion.m4 | 12 +- .../Source/WolfSSL/m4/lt~obsolete.m4 | 7 +- FreeRTOS-Plus/Source/WolfSSL/m4/visibility.m4 | 6 +- .../Source/WolfSSL/m4/wolfssl_darwin_clang.m4 | 37 - .../Source/WolfSSL/mcapi/PIC32MZ-serial.h | 75 + FreeRTOS-Plus/Source/WolfSSL/mcapi/README | 79 + FreeRTOS-Plus/Source/WolfSSL/mcapi/crypto.c | 782 + FreeRTOS-Plus/Source/WolfSSL/mcapi/crypto.h | 273 + FreeRTOS-Plus/Source/WolfSSL/mcapi/include.am | 19 + .../Source/WolfSSL/mcapi/mcapi_test.c | 1510 + .../Source/WolfSSL/mcapi/user_settings.h | 386 + .../WolfSSL/mcapi/wolfcrypt_mcapi.X/Makefile | 108 + .../nbproject/configurations.xml | 196 + .../wolfcrypt_mcapi.X/nbproject/include.am | 11 + .../wolfcrypt_mcapi.X/nbproject/project.xml | 20 + .../WolfSSL/mcapi/wolfcrypt_test.X/Makefile | 108 + .../nbproject/configurations.xml | 212 + .../wolfcrypt_test.X/nbproject/include.am | 11 + .../wolfcrypt_test.X/nbproject/project.xml | 20 + .../Source/WolfSSL/mcapi/wolfssl.X/Makefile | 108 + .../wolfssl.X/nbproject/configurations.xml | 243 + .../mcapi/wolfssl.X/nbproject/include.am | 11 + .../mcapi/wolfssl.X/nbproject/project.xml | 17 + .../Source/WolfSSL/mcapi/zlib.X/Makefile | 108 + .../mcapi/zlib.X/nbproject/configurations.xml | 210 + .../WolfSSL/mcapi/zlib.X/nbproject/include.am | 10 + .../mcapi/zlib.X/nbproject/project.xml | 17 + .../Source/WolfSSL/mplabx/PIC32MZ-serial.h | 96 + FreeRTOS-Plus/Source/WolfSSL/mplabx/README | 66 + .../Source/WolfSSL/mplabx/benchmark_main.c | 79 + .../Source/WolfSSL/mplabx/include.am | 10 + .../Source/WolfSSL/mplabx/test_main.c | 99 + .../Source/WolfSSL/mplabx/user_settings.h | 386 + .../mplabx/wolfcrypt_benchmark.X/Makefile | 108 + .../nbproject/configurations.xml | 218 + .../nbproject/include.am | 11 + .../nbproject/project.xml | 19 + .../WolfSSL/mplabx/wolfcrypt_test.X/Makefile | 108 + .../nbproject/configurations.xml | 218 + .../wolfcrypt_test.X/nbproject/include.am | 11 + .../wolfcrypt_test.X/nbproject/project.xml | 19 + .../Source/WolfSSL/mplabx/wolfssl.X/Makefile | 108 + .../wolfssl.X/nbproject/configurations.xml | 265 + .../mplabx/wolfssl.X/nbproject/include.am | 10 + .../mplabx/wolfssl.X/nbproject/project.xml | 17 + FreeRTOS-Plus/Source/WolfSSL/mqx/README | 43 + .../Source/WolfSSL/mqx/util_lib/.cproject | 541 + .../Source/WolfSSL/mqx/util_lib/.project | 31 + .../WolfSSL/mqx/util_lib/Sources/include.am | 12 + .../WolfSSL/mqx/util_lib/Sources/util.c | 180 + .../WolfSSL/mqx/util_lib/Sources/util.h | 14 + .../WolfSSL/mqx/wolfcrypt_benchmark/.cproject | 698 + .../WolfSSL/mqx/wolfcrypt_benchmark/.project | 42 + .../wolfcrypt_benchmark/Debugger/K70FN1M0.mem | 43 + .../Debugger/init_kinetis.tcl | 71 + .../Debugger/mass_erase_kinetis.tcl | 31 + .../ReferencedRSESystems.xml | 296 + .../wolfcrypt_benchmark/Sources/include.am | 22 + .../mqx/wolfcrypt_benchmark/Sources/main.c | 94 + .../mqx/wolfcrypt_benchmark/Sources/main.h | 20 + ...Flash_DDRData_Debug_PnE_U-MultiLink.launch | 133 + ...ash_DDRData_Release_PnE_U-MultiLink.launch | 133 + ...120m_Int_Flash_SramData_Debug_JTrace.jlink | 34 + ...20m_Int_Flash_SramData_Debug_JTrace.launch | 182 + ...lash_SramData_Debug_PnE_U-MultiLink.launch | 182 + ...sh_SramData_Release_PnE_U-MultiLink.launch | 168 + .../WolfSSL/mqx/wolfcrypt_test/.cproject | 681 + .../WolfSSL/mqx/wolfcrypt_test/.project | 42 + .../mqx/wolfcrypt_test/Debugger/K70FN1M0.mem | 43 + .../wolfcrypt_test/Debugger/init_kinetis.tcl | 71 + .../Debugger/mass_erase_kinetis.tcl | 31 + .../wolfcrypt_test/ReferencedRSESystems.xml | 296 + .../mqx/wolfcrypt_test/Sources/include.am | 22 + .../WolfSSL/mqx/wolfcrypt_test/Sources/main.c | 94 + .../WolfSSL/mqx/wolfcrypt_test/Sources/main.h | 20 + ...Flash_DDRData_Debug_PnE_U-MultiLink.launch | 133 + ...ash_DDRData_Release_PnE_U-MultiLink.launch | 133 + ...120m_Int_Flash_SramData_Debug_JTrace.jlink | 34 + ...20m_Int_Flash_SramData_Debug_JTrace.launch | 182 + ...lash_SramData_Debug_PnE_U-MultiLink.launch | 182 + ...sh_SramData_Release_PnE_U-MultiLink.launch | 168 + .../Source/WolfSSL/mqx/wolfssl/.cproject | 1145 + .../Source/WolfSSL/mqx/wolfssl/.project | 48 + .../Source/WolfSSL/mqx/wolfssl/include.am | 11 + .../WolfSSL/mqx/wolfssl_client/.cproject | 681 + .../WolfSSL/mqx/wolfssl_client/.project | 35 + .../mqx/wolfssl_client/Debugger/K70FN1M0.mem | 43 + .../wolfssl_client/Debugger/init_kinetis.tcl | 71 + .../Debugger/mass_erase_kinetis.tcl | 31 + .../wolfssl_client/ReferencedRSESystems.xml | 296 + .../mqx/wolfssl_client/Sources/include.am | 22 + .../WolfSSL/mqx/wolfssl_client/Sources/main.c | 293 + .../WolfSSL/mqx/wolfssl_client/Sources/main.h | 60 + ...Flash_DDRData_Debug_PnE_U-MultiLink.launch | 133 + ...ash_DDRData_Release_PnE_U-MultiLink.launch | 133 + ...120m_Int_Flash_SramData_Debug_JTrace.jlink | 34 + ...20m_Int_Flash_SramData_Debug_JTrace.launch | 182 + ...lash_SramData_Debug_PnE_U-MultiLink.launch | 182 + ...sh_SramData_Release_PnE_U-MultiLink.launch | 168 + FreeRTOS-Plus/Source/WolfSSL/resource.h | 14 + FreeRTOS-Plus/Source/WolfSSL/rpm/spec.in | 174 +- .../Source/WolfSSL/scripts/benchmark.test | 115 + .../WolfSSL/scripts/cleanup_testfiles.sh | 14 + .../Source/WolfSSL/scripts/crl-revoked.test | 118 + .../Source/WolfSSL/scripts/dertoc.pl | 71 + .../Source/WolfSSL/scripts/external.test | 34 + .../Source/WolfSSL/scripts/google.test | 26 + .../Source/WolfSSL/scripts/include.am | 98 + .../Source/WolfSSL/scripts/memtest.sh | 24 + .../ocsp-stapling-with-ca-as-responder.test | 231 + .../Source/WolfSSL/scripts/ocsp-stapling.test | 314 + .../WolfSSL/scripts/ocsp-stapling2.test | 395 + .../Source/WolfSSL/scripts/ocsp.test | 92 + .../Source/WolfSSL/scripts/openssl.test | 327 + .../Source/WolfSSL/scripts/ping.test | 29 + .../Source/WolfSSL/scripts/pkcallbacks.test | 123 + FreeRTOS-Plus/Source/WolfSSL/scripts/psk.test | 148 + .../Source/WolfSSL/scripts/resume.test | 144 + .../Source/WolfSSL/scripts/sniffer-ipv6.pcap | Bin 0 -> 9484 bytes .../WolfSSL/scripts/sniffer-testsuite.test | 23 + .../WolfSSL/scripts/stm32l4-v4_0_1_build.sh | 199 + .../Source/WolfSSL/scripts/testsuite.pcap | Bin 0 -> 52480 bytes .../Source/WolfSSL/scripts/tls13.test | 203 + .../Source/WolfSSL/scripts/trusted_peer.test | 286 + FreeRTOS-Plus/Source/WolfSSL/src/bio.c | 1705 + FreeRTOS-Plus/Source/WolfSSL/src/crl.c | 655 +- FreeRTOS-Plus/Source/WolfSSL/src/include.am | 341 +- FreeRTOS-Plus/Source/WolfSSL/src/internal.c | 29846 ++++-- FreeRTOS-Plus/Source/WolfSSL/src/io.c | 1141 - FreeRTOS-Plus/Source/WolfSSL/src/keys.c | 2334 +- FreeRTOS-Plus/Source/WolfSSL/src/ocsp.c | 1135 +- FreeRTOS-Plus/Source/WolfSSL/src/sniffer.c | 2505 +- FreeRTOS-Plus/Source/WolfSSL/src/ssl.c | 46134 +++++++- FreeRTOS-Plus/Source/WolfSSL/src/tls.c | 11415 +- FreeRTOS-Plus/Source/WolfSSL/src/tls13.c | 9048 ++ FreeRTOS-Plus/Source/WolfSSL/src/wolfio.c | 2375 + .../WolfSSL/sslSniffer/sslSniffer.vcproj | 16 +- .../WolfSSL/sslSniffer/sslSniffer.vcxproj | 17 +- .../sslSniffer/sslSnifferTest/include.am | 2 +- .../sslSniffer/sslSnifferTest/snifftest.c | 345 +- .../Source/WolfSSL/support/wolfssl.pc | 2 +- FreeRTOS-Plus/Source/WolfSSL/swig/README | 5 +- FreeRTOS-Plus/Source/WolfSSL/swig/wolfssl.i | 17 +- .../Source/WolfSSL/swig/wolfssl_adds.c | 23 +- FreeRTOS-Plus/Source/WolfSSL/tests/api.c | 32086 +++++- FreeRTOS-Plus/Source/WolfSSL/tests/hash.c | 472 +- FreeRTOS-Plus/Source/WolfSSL/tests/include.am | 31 +- FreeRTOS-Plus/Source/WolfSSL/tests/srp.c | 838 + FreeRTOS-Plus/Source/WolfSSL/tests/suites.c | 829 +- .../Source/WolfSSL/tests/test-altchains.conf | 245 + .../Source/WolfSSL/tests/test-chains.conf | 384 + .../Source/WolfSSL/tests/test-dhprime.conf | 25 + .../Source/WolfSSL/tests/test-dtls-sha2.conf | 66 + .../Source/WolfSSL/tests/test-dtls.conf | 413 +- .../Source/WolfSSL/tests/test-ed25519.conf | 71 + .../Source/WolfSSL/tests/test-ed448.conf | 59 + .../Source/WolfSSL/tests/test-enckeys.conf | 42 + .../Source/WolfSSL/tests/test-fails.conf | 179 + .../WolfSSL/tests/test-maxfrag-dtls.conf | 215 + .../Source/WolfSSL/tests/test-maxfrag.conf | 179 + .../WolfSSL/tests/test-psk-no-id-sha2.conf | 87 + .../Source/WolfSSL/tests/test-psk-no-id.conf | 214 + .../Source/WolfSSL/tests/test-psk.conf | 7 + .../Source/WolfSSL/tests/test-qsh-sha2.conf | 303 + .../Source/WolfSSL/tests/test-qsh.conf | 1778 + .../Source/WolfSSL/tests/test-sctp-sha2.conf | 67 + .../Source/WolfSSL/tests/test-sctp.conf | 1042 + .../Source/WolfSSL/tests/test-sha2.conf | 403 + .../Source/WolfSSL/tests/test-sig.conf | 219 + .../Source/WolfSSL/tests/test-tls13-down.conf | 44 + .../Source/WolfSSL/tests/test-tls13-ecc.conf | 93 + .../Source/WolfSSL/tests/test-tls13-psk.conf | 31 + .../Source/WolfSSL/tests/test-tls13.conf | 211 + .../Source/WolfSSL/tests/test-trustpeer.conf | 99 + FreeRTOS-Plus/Source/WolfSSL/tests/test.conf | 2347 +- FreeRTOS-Plus/Source/WolfSSL/tests/unit.c | 98 +- FreeRTOS-Plus/Source/WolfSSL/tests/unit.h | 67 +- .../Source/WolfSSL/testsuite/include.am | 4 +- .../Source/WolfSSL/testsuite/testsuite.c | 202 +- .../Source/WolfSSL/testsuite/testsuite.vcproj | 12 +- .../WolfSSL/testsuite/testsuite.vcxproj | 38 +- FreeRTOS-Plus/Source/WolfSSL/tirtos/README | 17 + .../Source/WolfSSL/tirtos/include.am | 23 + .../packages/ti/net/wolfssl/package.bld | 65 + .../packages/ti/net/wolfssl/package.xdc | 6 + .../tirtos/packages/ti/net/wolfssl/package.xs | 12 + .../wolfcrypt/benchmark/TM4C1294NC.icf | 29 + .../wolfcrypt/benchmark/benchmark.cfg | 81 + .../EK_TM4C1294XL/wolfcrypt/benchmark/main.c | 106 + .../wolfcrypt/benchmark/package.bld.hide | 53 + .../wolfcrypt/benchmark/package.xdc | 6 + .../wolfcrypt/test/TM4C1294NC.icf | 29 + .../tests/EK_TM4C1294XL/wolfcrypt/test/main.c | 55 + .../wolfcrypt/test/package.bld.hide | 49 + .../EK_TM4C1294XL/wolfcrypt/test/package.xdc | 6 + .../EK_TM4C1294XL/wolfcrypt/test/test.cfg | 80 + .../Source/WolfSSL/tirtos/products.mak | 30 + .../Source/WolfSSL/tirtos/wolfssl.bld | 89 + .../Source/WolfSSL/tirtos/wolfssl.mak | 64 + .../WolfSSL/wolfcrypt/benchmark/README.md | 103 + .../WolfSSL/wolfcrypt/benchmark/benchmark.c | 6840 +- .../WolfSSL/wolfcrypt/benchmark/benchmark.h | 111 + .../WolfSSL/wolfcrypt/benchmark/benchmark.sln | 39 + .../wolfcrypt/benchmark/benchmark.vcproj | 10 +- .../WolfSSL/wolfcrypt/benchmark/include.am | 6 +- .../Source/WolfSSL/wolfcrypt/src/aes.c | 7729 +- .../Source/WolfSSL/wolfcrypt/src/aes_asm.S | 1338 + .../Source/WolfSSL/wolfcrypt/src/aes_asm.asm | 1019 +- .../Source/WolfSSL/wolfcrypt/src/aes_asm.s | 816 - .../WolfSSL/wolfcrypt/src/aes_gcm_asm.S | 8733 ++ .../Source/WolfSSL/wolfcrypt/src/arc4.c | 129 +- .../Source/WolfSSL/wolfcrypt/src/asm.c | 795 +- .../Source/WolfSSL/wolfcrypt/src/asn.c | 16928 ++- .../WolfSSL/{NEWS => wolfcrypt/src/async.c} | 0 .../Source/WolfSSL/wolfcrypt/src/blake2b.c | 43 +- .../Source/WolfSSL/wolfcrypt/src/blake2s.c | 446 + .../Source/WolfSSL/wolfcrypt/src/camellia.c | 84 +- .../Source/WolfSSL/wolfcrypt/src/chacha.c | 173 +- .../WolfSSL/wolfcrypt/src/chacha20_poly1305.c | 332 +- .../Source/WolfSSL/wolfcrypt/src/chacha_asm.S | 1420 + .../Source/WolfSSL/wolfcrypt/src/cmac.c | 215 + .../Source/WolfSSL/wolfcrypt/src/coding.c | 292 +- .../Source/WolfSSL/wolfcrypt/src/compress.c | 57 +- .../Source/WolfSSL/wolfcrypt/src/cpuid.c | 110 + .../Source/WolfSSL/wolfcrypt/src/cryptocb.c | 648 + .../Source/WolfSSL/wolfcrypt/src/curve25519.c | 463 +- .../Source/WolfSSL/wolfcrypt/src/curve448.c | 635 + .../Source/WolfSSL/wolfcrypt/src/des3.c | 2491 +- .../Source/WolfSSL/wolfcrypt/src/dh.c | 2561 +- .../Source/WolfSSL/wolfcrypt/src/dsa.c | 820 +- .../Source/WolfSSL/wolfcrypt/src/ecc.c | 10537 +- .../Source/WolfSSL/wolfcrypt/src/ed25519.c | 682 +- .../Source/WolfSSL/wolfcrypt/src/ed448.c | 917 + .../Source/WolfSSL/wolfcrypt/src/error.c | 227 +- .../Source/WolfSSL/wolfcrypt/src/evp.c | 6595 ++ .../Source/WolfSSL/wolfcrypt/src/fe_448.c | 2458 + .../Source/WolfSSL/wolfcrypt/src/fe_low_mem.c | 91 +- .../WolfSSL/wolfcrypt/src/fe_operations.c | 283 +- .../WolfSSL/wolfcrypt/src/fe_x25519_128.i | 625 + .../WolfSSL/wolfcrypt/src/fe_x25519_asm.S | 16542 +++ .../Source/WolfSSL/wolfcrypt/src/fips.c | 0 .../Source/WolfSSL/wolfcrypt/src/fips_test.c | 0 .../WolfSSL/wolfcrypt/src/fp_mont_small.i | 40 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_12.i | 35 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_17.i | 35 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_20.i | 33 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_24.i | 35 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_28.i | 35 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_3.i | 15 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_32.i | 37 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_4.i | 35 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_48.i | 35 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_6.i | 35 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_64.i | 35 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_7.i | 35 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_8.i | 35 +- .../WolfSSL/wolfcrypt/src/fp_mul_comba_9.i | 35 +- .../wolfcrypt/src/fp_mul_comba_small_set.i | 92 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_12.i | 30 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_17.i | 29 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_20.i | 33 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_24.i | 33 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_28.i | 33 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_3.i | 13 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_32.i | 33 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_4.i | 29 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_48.i | 33 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_6.i | 29 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_64.i | 33 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_7.i | 29 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_8.i | 33 +- .../WolfSSL/wolfcrypt/src/fp_sqr_comba_9.i | 29 +- .../wolfcrypt/src/fp_sqr_comba_small_set.i | 66 +- .../Source/WolfSSL/wolfcrypt/src/ge_448.c | 10780 ++ .../Source/WolfSSL/wolfcrypt/src/ge_low_mem.c | 473 +- .../WolfSSL/wolfcrypt/src/ge_operations.c | 8588 +- .../Source/WolfSSL/wolfcrypt/src/hash.c | 1675 +- .../Source/WolfSSL/wolfcrypt/src/hc128.c | 109 +- .../Source/WolfSSL/wolfcrypt/src/hmac.c | 1657 +- .../Source/WolfSSL/wolfcrypt/src/idea.c | 303 + .../Source/WolfSSL/wolfcrypt/src/include.am | 83 +- .../Source/WolfSSL/wolfcrypt/src/integer.c | 1466 +- .../Source/WolfSSL/wolfcrypt/src/logging.c | 779 +- .../Source/WolfSSL/wolfcrypt/src/md2.c | 10 +- .../Source/WolfSSL/wolfcrypt/src/md4.c | 31 +- .../Source/WolfSSL/wolfcrypt/src/md5.c | 771 +- .../Source/WolfSSL/wolfcrypt/src/memory.c | 1019 +- .../Source/WolfSSL/wolfcrypt/src/misc.c | 264 +- .../Source/WolfSSL/wolfcrypt/src/pkcs12.c | 2403 + .../Source/WolfSSL/wolfcrypt/src/pkcs7.c | 13025 ++- .../Source/WolfSSL/wolfcrypt/src/poly1305.c | 1080 +- .../WolfSSL/wolfcrypt/src/poly1305_asm.S | 1105 + .../wolfcrypt/src/port/Espressif/README.md | 109 + .../wolfcrypt/src/port/Espressif/esp32_aes.c | 299 + .../wolfcrypt/src/port/Espressif/esp32_mp.c | 514 + .../wolfcrypt/src/port/Espressif/esp32_sha.c | 434 + .../wolfcrypt/src/port/Espressif/esp32_util.c | 67 + .../wolfcrypt/src/port/Renesas/README.md | 176 + .../src/port/Renesas/renesas_tsip_aes.c | 156 + .../src/port/Renesas/renesas_tsip_sha.c | 274 + .../src/port/Renesas/renesas_tsip_util.c | 719 + .../wolfcrypt/src/port/af_alg/afalg_aes.c | 900 + .../wolfcrypt/src/port/af_alg/afalg_hash.c | 339 + .../wolfcrypt/src/port/af_alg/wc_afalg.c | 141 + .../src/port/arm/armv8-32-curve25519.S | 6012 ++ .../src/port/arm/armv8-32-curve25519.c | 5581 + .../src/port/arm/armv8-32-sha512-asm.S | 5335 + .../src/port/arm/armv8-32-sha512-asm.c | 4783 + .../wolfcrypt/src/port/arm/armv8-aes.c | 4653 + .../wolfcrypt/src/port/arm/armv8-chacha.c | 2857 + .../wolfcrypt/src/port/arm/armv8-curve25519.S | 6715 ++ .../wolfcrypt/src/port/arm/armv8-curve25519.c | 6725 ++ .../wolfcrypt/src/port/arm/armv8-poly1305.c | 1166 + .../wolfcrypt/src/port/arm/armv8-sha256.c | 1508 + .../wolfcrypt/src/port/arm/armv8-sha512-asm.S | 1046 + .../wolfcrypt/src/port/arm/armv8-sha512-asm.c | 1041 + .../wolfcrypt/src/port/arm/armv8-sha512.c | 715 + .../wolfcrypt/src/port/arm/cryptoCell.c | 309 + .../wolfcrypt/src/port/arm/cryptoCellHash.c | 134 + .../wolfcrypt/src/port/atmel/README.md | 94 + .../WolfSSL/wolfcrypt/src/port/atmel/atmel.c | 843 + .../wolfcrypt/src/port/caam/caam_aes.c | 649 + .../wolfcrypt/src/port/caam/caam_doc.pdf | Bin 0 -> 1107370 bytes .../wolfcrypt/src/port/caam/caam_driver.c | 1713 + .../wolfcrypt/src/port/caam/caam_init.c | 289 + .../wolfcrypt/src/port/caam/caam_sha.c | 397 + .../wolfcrypt/src/port/cavium/README.md | 3 + .../src/port/cavium/README_Octeon.md | 3 + .../wolfcrypt/src/port/cavium/cavium_nitrox.c | 0 .../src/port/cavium/cavium_octeon_sync.c | 879 + .../wolfcrypt/src/port/devcrypto/README.md | 43 + .../src/port/devcrypto/devcrypto_aes.c | 384 + .../src/port/devcrypto/devcrypto_hash.c | 248 + .../src/port/devcrypto/wc_devcrypto.c | 167 + .../wolfcrypt/src/port/intel/README.md | 3 + .../wolfcrypt/src/port/intel/quickassist.c | 0 .../src/port/intel/quickassist_mem.c | 0 .../src/port/intel/quickassist_sync.c | 2004 + .../wolfcrypt/src/port/mynewt/mynewt_port.c | 146 + .../Source/WolfSSL/wolfcrypt/src/port/nrf51.c | 220 + .../wolfcrypt/src/port/nxp/ksdk_port.c | 1731 + .../wolfcrypt/src/port/pic32/pic32mz-crypt.c | 804 + .../wolfcrypt/src/port/pic32/pic32mz-hash.c | 371 - .../WolfSSL/wolfcrypt/src/port/st/README.md | 132 + .../WolfSSL/wolfcrypt/src/port/st/stm32.c | 879 + .../WolfSSL/wolfcrypt/src/port/st/stsafe.c | 566 + .../WolfSSL/wolfcrypt/src/port/ti/ti-aes.c | 147 +- .../WolfSSL/wolfcrypt/src/port/ti/ti-ccm.c | 66 +- .../WolfSSL/wolfcrypt/src/port/ti/ti-des3.c | 65 +- .../WolfSSL/wolfcrypt/src/port/ti/ti-hash.c | 237 +- .../wolfcrypt/src/port/xilinx/xil-aesgcm.c | 202 + .../wolfcrypt/src/port/xilinx/xil-sha3.c | 158 + .../Source/WolfSSL/wolfcrypt/src/pwdbased.c | 827 +- .../Source/WolfSSL/wolfcrypt/src/rabbit.c | 56 +- .../Source/WolfSSL/wolfcrypt/src/random.c | 2571 +- .../Source/WolfSSL/wolfcrypt/src/ripemd.c | 60 +- .../Source/WolfSSL/wolfcrypt/src/rsa.c | 4449 +- .../Source/WolfSSL/wolfcrypt/src/selftest.c | 0 .../Source/WolfSSL/wolfcrypt/src/sha.c | 1126 +- .../Source/WolfSSL/wolfcrypt/src/sha256.c | 3206 +- .../Source/WolfSSL/wolfcrypt/src/sha256_asm.S | 22653 ++++ .../Source/WolfSSL/wolfcrypt/src/sha3.c | 1216 + .../Source/WolfSSL/wolfcrypt/src/sha512.c | 2528 +- .../Source/WolfSSL/wolfcrypt/src/sha512_asm.S | 10741 ++ .../Source/WolfSSL/wolfcrypt/src/signature.c | 559 + .../Source/WolfSSL/wolfcrypt/src/sp_arm32.c | 89057 ++++++++++++++++ .../Source/WolfSSL/wolfcrypt/src/sp_arm64.c | 42082 ++++++++ .../WolfSSL/wolfcrypt/src/sp_armthumb.c | 27863 +++++ .../Source/WolfSSL/wolfcrypt/src/sp_c32.c | 23857 +++++ .../Source/WolfSSL/wolfcrypt/src/sp_c64.c | 23220 ++++ .../Source/WolfSSL/wolfcrypt/src/sp_cortexm.c | 25687 +++++ .../Source/WolfSSL/wolfcrypt/src/sp_dsp32.c | 4908 + .../Source/WolfSSL/wolfcrypt/src/sp_int.c | 2203 + .../Source/WolfSSL/wolfcrypt/src/sp_x86_64.c | 29555 +++++ .../WolfSSL/wolfcrypt/src/sp_x86_64_asm.S | 41830 ++++++++ .../Source/WolfSSL/wolfcrypt/src/srp.c | 756 + .../Source/WolfSSL/wolfcrypt/src/tfm.c | 3657 +- .../Source/WolfSSL/wolfcrypt/src/wc_dsp.c | 327 + .../Source/WolfSSL/wolfcrypt/src/wc_encrypt.c | 660 + .../Source/WolfSSL/wolfcrypt/src/wc_pkcs11.c | 2546 + .../Source/WolfSSL/wolfcrypt/src/wc_port.c | 2708 +- .../WolfSSL/wolfcrypt/src/wolfcrypt_first.c | 0 .../WolfSSL/wolfcrypt/src/wolfcrypt_last.c | 0 .../Source/WolfSSL/wolfcrypt/src/wolfevent.c | 283 + .../Source/WolfSSL/wolfcrypt/src/wolfmath.c | 381 + .../Source/WolfSSL/wolfcrypt/test/README.md | 60 + .../Source/WolfSSL/wolfcrypt/test/include.am | 9 +- .../Source/WolfSSL/wolfcrypt/test/test.c | 27788 ++++- .../Source/WolfSSL/wolfcrypt/test/test.h | 20 +- .../Source/WolfSSL/wolfcrypt/test/test.sln | 39 + .../Source/WolfSSL/wolfcrypt/test/test.vcproj | 10 +- .../WolfSSL/wolfcrypt/user-crypto/Makefile.am | 9 + .../WolfSSL/wolfcrypt/user-crypto/README.txt | 78 + .../WolfSSL/wolfcrypt/user-crypto/autogen.sh | 23 + .../wolfcrypt/user-crypto/configure.ac | 44 + .../WolfSSL/wolfcrypt/user-crypto/include.am | 13 + .../wolfcrypt/user-crypto/include/user_rsa.h | 137 + .../wolfcrypt/user-crypto/lib/.gitkeep | 0 .../WolfSSL/wolfcrypt/user-crypto/src/rsa.c | 2790 + FreeRTOS-Plus/Source/WolfSSL/wolfssl-ntru.sln | 65 + .../Source/WolfSSL/wolfssl-ntru.vcproj | 349 + FreeRTOS-Plus/Source/WolfSSL/wolfssl.rc | Bin 0 -> 4918 bytes FreeRTOS-Plus/Source/WolfSSL/wolfssl.sln | 74 + FreeRTOS-Plus/Source/WolfSSL/wolfssl.vcproj | 406 + FreeRTOS-Plus/Source/WolfSSL/wolfssl.vcxproj | 372 + .../Source/WolfSSL/wolfssl/callbacks.h | 37 +- .../Source/WolfSSL/wolfssl/certs_test.h | 5148 +- FreeRTOS-Plus/Source/WolfSSL/wolfssl/crl.h | 11 +- .../Source/WolfSSL/wolfssl/error-ssl.h | 253 +- .../Source/WolfSSL/wolfssl/include.am | 11 +- .../Source/WolfSSL/wolfssl/internal.h | 3730 +- FreeRTOS-Plus/Source/WolfSSL/wolfssl/ocsp.h | 89 +- .../Source/WolfSSL/wolfssl/openssl/aes.h | 111 + .../Source/WolfSSL/wolfssl/openssl/asn1.h | 150 + .../Source/WolfSSL/wolfssl/openssl/asn1t.h | 30 + .../Source/WolfSSL/wolfssl/openssl/bio.h | 143 +- .../Source/WolfSSL/wolfssl/openssl/bn.h | 141 +- .../Source/WolfSSL/wolfssl/openssl/buffer.h | 47 + .../Source/WolfSSL/wolfssl/openssl/conf.h | 48 +- .../Source/WolfSSL/wolfssl/openssl/crypto.h | 71 +- .../Source/WolfSSL/wolfssl/openssl/des.h | 59 +- .../Source/WolfSSL/wolfssl/openssl/dh.h | 93 +- .../Source/WolfSSL/wolfssl/openssl/dsa.h | 82 +- .../Source/WolfSSL/wolfssl/openssl/ec.h | 321 + .../Source/WolfSSL/wolfssl/openssl/ec25519.h | 44 + .../Source/WolfSSL/wolfssl/openssl/ec448.h | 44 + .../Source/WolfSSL/wolfssl/openssl/ecdh.h | 49 + .../Source/WolfSSL/wolfssl/openssl/ecdsa.h | 73 + .../Source/WolfSSL/wolfssl/openssl/ed25519.h | 47 + .../Source/WolfSSL/wolfssl/openssl/ed448.h | 47 + .../Source/WolfSSL/wolfssl/openssl/engine.h | 3 + .../Source/WolfSSL/wolfssl/openssl/err.h | 55 +- .../Source/WolfSSL/wolfssl/openssl/evp.h | 769 +- .../Source/WolfSSL/wolfssl/openssl/hmac.h | 45 +- .../Source/WolfSSL/wolfssl/openssl/include.am | 18 +- .../Source/WolfSSL/wolfssl/openssl/md4.h | 63 +- .../Source/WolfSSL/wolfssl/openssl/md5.h | 51 +- .../Source/WolfSSL/wolfssl/openssl/obj_mac.h | 50 + .../Source/WolfSSL/wolfssl/openssl/objects.h | 63 + .../Source/WolfSSL/wolfssl/openssl/ocsp.h | 81 + .../Source/WolfSSL/wolfssl/openssl/opensslv.h | 37 +- .../Source/WolfSSL/wolfssl/openssl/ossl_typ.h | 32 +- .../Source/WolfSSL/wolfssl/openssl/pem.h | 243 +- .../Source/WolfSSL/wolfssl/openssl/pkcs12.h | 47 + .../Source/WolfSSL/wolfssl/openssl/pkcs7.h | 79 + .../Source/WolfSSL/wolfssl/openssl/rand.h | 23 + .../Source/WolfSSL/wolfssl/openssl/rc4.h | 59 + .../Source/WolfSSL/wolfssl/openssl/ripemd.h | 21 + .../Source/WolfSSL/wolfssl/openssl/rsa.h | 160 +- .../Source/WolfSSL/wolfssl/openssl/sha.h | 132 +- .../Source/WolfSSL/wolfssl/openssl/sha3.h | 150 + .../Source/WolfSSL/wolfssl/openssl/ssl.h | 1335 +- .../Source/WolfSSL/wolfssl/openssl/ssl23.h | 1 + .../Source/WolfSSL/wolfssl/openssl/stack.h | 59 +- .../Source/WolfSSL/wolfssl/openssl/tls1.h | 46 + .../Source/WolfSSL/wolfssl/openssl/x509.h | 23 + .../Source/WolfSSL/wolfssl/openssl/x509_vfy.h | 45 + .../Source/WolfSSL/wolfssl/openssl/x509v3.h | 116 +- .../Source/WolfSSL/wolfssl/options.h | 14 +- .../Source/WolfSSL/wolfssl/options.h.in | 14 +- .../Source/WolfSSL/wolfssl/sniffer.h | 163 +- .../Source/WolfSSL/wolfssl/sniffer_error.h | 31 +- .../Source/WolfSSL/wolfssl/sniffer_error.rc | 23 + FreeRTOS-Plus/Source/WolfSSL/wolfssl/ssl.h | 3166 +- FreeRTOS-Plus/Source/WolfSSL/wolfssl/test.h | 2967 +- .../Source/WolfSSL/wolfssl/version.h | 17 +- .../Source/WolfSSL/wolfssl/version.h.in | 13 +- .../Source/WolfSSL/wolfssl/wolfcrypt/aes.h | 395 +- .../Source/WolfSSL/wolfssl/wolfcrypt/arc4.h | 33 +- .../Source/WolfSSL/wolfssl/wolfcrypt/asn.h | 1100 +- .../WolfSSL/wolfssl/wolfcrypt/asn_public.h | 515 +- .../Source/WolfSSL/wolfssl/wolfcrypt/async.h | 0 .../WolfSSL/wolfssl/wolfcrypt/blake2-impl.h | 29 +- .../WolfSSL/wolfssl/wolfcrypt/blake2-int.h | 25 +- .../Source/WolfSSL/wolfssl/wolfcrypt/blake2.h | 43 +- .../WolfSSL/wolfssl/wolfcrypt/camellia.h | 19 +- .../Source/WolfSSL/wolfssl/wolfcrypt/chacha.h | 36 +- .../wolfssl/wolfcrypt/chacha20_poly1305.h | 76 +- .../Source/WolfSSL/wolfssl/wolfcrypt/cmac.h | 97 + .../Source/WolfSSL/wolfssl/wolfcrypt/coding.h | 34 +- .../WolfSSL/wolfssl/wolfcrypt/compress.h | 18 +- .../Source/WolfSSL/wolfssl/wolfcrypt/cpuid.h | 62 + .../WolfSSL/wolfssl/wolfcrypt/cryptocb.h | 299 + .../WolfSSL/wolfssl/wolfcrypt/curve25519.h | 83 +- .../WolfSSL/wolfssl/wolfcrypt/curve448.h | 139 + .../Source/WolfSSL/wolfssl/wolfcrypt/des3.h | 109 +- .../Source/WolfSSL/wolfssl/wolfcrypt/dh.h | 91 +- .../Source/WolfSSL/wolfssl/wolfcrypt/dsa.h | 58 +- .../Source/WolfSSL/wolfssl/wolfcrypt/ecc.h | 585 +- .../WolfSSL/wolfssl/wolfcrypt/ed25519.h | 105 +- .../Source/WolfSSL/wolfssl/wolfcrypt/ed448.h | 160 + .../WolfSSL/wolfssl/wolfcrypt/error-crypt.h | 116 +- .../Source/WolfSSL/wolfssl/wolfcrypt/fe_448.h | 116 + .../WolfSSL/wolfssl/wolfcrypt/fe_operations.h | 116 +- .../Source/WolfSSL/wolfssl/wolfcrypt/fips.h | 0 .../WolfSSL/wolfssl/wolfcrypt/fips_test.h | 19 +- .../Source/WolfSSL/wolfssl/wolfcrypt/ge_448.h | 86 + .../WolfSSL/wolfssl/wolfcrypt/ge_operations.h | 78 +- .../Source/WolfSSL/wolfssl/wolfcrypt/hash.h | 232 +- .../Source/WolfSSL/wolfssl/wolfcrypt/hc128.h | 17 +- .../Source/WolfSSL/wolfssl/wolfcrypt/hmac.h | 213 +- .../Source/WolfSSL/wolfssl/wolfcrypt/idea.h | 70 + .../WolfSSL/wolfssl/wolfcrypt/include.am | 86 +- .../WolfSSL/wolfssl/wolfcrypt/integer.h | 297 +- .../WolfSSL/wolfssl/wolfcrypt/logging.h | 150 +- .../Source/WolfSSL/wolfssl/wolfcrypt/md2.h | 13 +- .../Source/WolfSSL/wolfssl/wolfcrypt/md4.h | 11 +- .../Source/WolfSSL/wolfssl/wolfcrypt/md5.h | 101 +- .../WolfSSL/wolfssl/wolfcrypt/mem_track.h | 401 + .../Source/WolfSSL/wolfssl/wolfcrypt/memory.h | 205 +- .../Source/WolfSSL/wolfssl/wolfcrypt/misc.h | 46 +- .../WolfSSL/wolfssl/wolfcrypt/mpi_class.h | 9 +- .../wolfssl/wolfcrypt/mpi_superclass.h | 13 +- .../Source/WolfSSL/wolfssl/wolfcrypt/pkcs11.h | 537 + .../Source/WolfSSL/wolfssl/wolfcrypt/pkcs12.h | 72 + .../Source/WolfSSL/wolfssl/wolfcrypt/pkcs7.h | 474 +- .../WolfSSL/wolfssl/wolfcrypt/poly1305.h | 93 +- .../wolfcrypt/port/Espressif/esp32-crypt.h | 152 + .../port/Renesas/renesas-tsip-crypt.h | 153 + .../wolfcrypt/port/af_alg/afalg_hash.h | 50 + .../wolfssl/wolfcrypt/port/af_alg/wc_afalg.h | 53 + .../wolfssl/wolfcrypt/port/arm/cryptoCell.h | 117 + .../wolfssl/wolfcrypt/port/atmel/atmel.h | 134 + .../wolfssl/wolfcrypt/port/caam/caam_driver.h | 187 + .../wolfssl/wolfcrypt/port/caam/wolfcaam.h | 63 + .../wolfcrypt/port/caam/wolfcaam_sha.h | 88 + .../wolfcrypt/port/cavium/cavium_nitrox.h | 0 .../port/cavium/cavium_octeon_sync.h | 31 + .../wolfcrypt/port/devcrypto/wc_devcrypto.h | 53 + .../wolfcrypt/port/intel/quickassist.h | 0 .../wolfcrypt/port/intel/quickassist_mem.h | 0 .../wolfcrypt/port/intel/quickassist_sync.h | 53 + .../WolfSSL/wolfssl/wolfcrypt/port/nrf51.h | 44 + .../wolfssl/wolfcrypt/port/nxp/ksdk_port.h | 93 + .../wolfcrypt/port/pic32/pic32mz-crypt.h | 176 +- .../WolfSSL/wolfssl/wolfcrypt/port/st/stm32.h | 142 + .../wolfssl/wolfcrypt/port/st/stsafe.h | 99 + .../wolfssl/wolfcrypt/port/ti/ti-ccm.h | 21 +- .../wolfssl/wolfcrypt/port/ti/ti-hash.h | 49 +- .../wolfssl/wolfcrypt/port/xilinx/xil-sha3.h | 45 + .../WolfSSL/wolfssl/wolfcrypt/pwdbased.h | 40 +- .../Source/WolfSSL/wolfssl/wolfcrypt/rabbit.h | 15 +- .../Source/WolfSSL/wolfssl/wolfcrypt/random.h | 227 +- .../Source/WolfSSL/wolfssl/wolfcrypt/ripemd.h | 16 +- .../Source/WolfSSL/wolfssl/wolfcrypt/rsa.h | 330 +- .../WolfSSL/wolfssl/wolfcrypt/selftest.h | 48 + .../WolfSSL/wolfssl/wolfcrypt/settings.h | 1901 +- .../Source/WolfSSL/wolfssl/wolfcrypt/sha.h | 163 +- .../Source/WolfSSL/wolfssl/wolfcrypt/sha256.h | 224 +- .../Source/WolfSSL/wolfssl/wolfcrypt/sha3.h | 165 + .../Source/WolfSSL/wolfssl/wolfcrypt/sha512.h | 204 +- .../WolfSSL/wolfssl/wolfcrypt/signature.h | 87 + .../Source/WolfSSL/wolfssl/wolfcrypt/sp.h | 154 + .../Source/WolfSSL/wolfssl/wolfcrypt/sp_int.h | 287 + .../Source/WolfSSL/wolfssl/wolfcrypt/srp.h | 311 + .../Source/WolfSSL/wolfssl/wolfcrypt/tfm.h | 539 +- .../Source/WolfSSL/wolfssl/wolfcrypt/types.h | 1154 +- .../WolfSSL/wolfssl/wolfcrypt/visibility.h | 32 +- .../WolfSSL/wolfssl/wolfcrypt/wc_encrypt.h | 101 + .../WolfSSL/wolfssl/wolfcrypt/wc_pkcs11.h | 94 + .../WolfSSL/wolfssl/wolfcrypt/wc_port.h | 629 +- .../WolfSSL/wolfssl/wolfcrypt/wolfevent.h | 120 + .../WolfSSL/wolfssl/wolfcrypt/wolfmath.h | 97 + FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfio.h | 600 + FreeRTOS-Plus/Source/WolfSSL/wolfssl64.sln | 142 + .../Source/WolfSSL/wrapper/CSharp/include.am | 41 + .../CSharp/wolfSSL-DTLS-PSK-Server/App.config | 6 + .../Properties/AssemblyInfo.cs | 36 + .../wolfSSL-DTLS-PSK-Server.cs | 221 + .../wolfSSL-DTLS-PSK-Server.csproj | 87 + .../CSharp/wolfSSL-DTLS-Server/App.config | 6 + .../Properties/AssemblyInfo.cs | 36 + .../wolfSSL-DTLS-Server.cs | 181 + .../wolfSSL-DTLS-Server.csproj | 88 + .../wolfSSL-Example-IOCallbacks/App.config | 6 + .../Properties/AssemblyInfo.cs | 36 + .../wolfSSL-Example-IOCallbacks.cs | 280 + .../wolfSSL-Example-IOCallbacks.csproj | 84 + .../CSharp/wolfSSL-TLS-Client/App.config | 6 + .../Properties/AssemblyInfo.cs | 36 + .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 6 + .../wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs | 210 + .../wolfSSL-TLS-Client.csproj | 132 + .../CSharp/wolfSSL-TLS-PSK-Server/App.config | 6 + .../Properties/AssemblyInfo.cs | 36 + .../wolfSSL-TLS-PSK-Server.cs | 212 + .../wolfSSL-TLS-PSK-Server.csproj | 87 + .../CSharp/wolfSSL-TLS-Server/App.config | 6 + .../Properties/AssemblyInfo.cs | 36 + .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 6 + .../wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs | 173 + .../wolfSSL-TLS-Server.csproj | 132 + .../wolfSSL-TLS-ServerThreaded/App.config | 6 + .../Properties/AssemblyInfo.cs | 36 + .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 6 + .../wolfSSL-TLS-ServerThreaded.cs | 194 + .../wolfSSL-TLS-ServerThreaded.csproj | 132 + .../WolfSSL/wrapper/CSharp/wolfSSL_CSharp.sln | 173 + .../wolfSSL_CSharp/Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 63 + .../wolfSSL_CSharp/Properties/Resources.resx | 101 + .../wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs | 1889 + .../wolfSSL_CSharp/wolfSSL_CSharp.csproj | 80 + .../Source/WolfSSL/wrapper/include.am | 7 + .../wrapper/python/wolfcrypt/.gitignore | 18 + .../wrapper/python/wolfcrypt/LICENSING.rst | 23 + .../wrapper/python/wolfcrypt/MANIFEST.in | 1 + .../wrapper/python/wolfcrypt/README.rst | 144 + .../wrapper/python/wolfcrypt/docs/Makefile | 230 + .../python/wolfcrypt/docs/asymmetric.rst | 74 + .../wrapper/python/wolfcrypt/docs/conf.py | 299 + .../wrapper/python/wolfcrypt/docs/digest.rst | 71 + .../wrapper/python/wolfcrypt/docs/index.rst | 15 + .../wrapper/python/wolfcrypt/docs/mac.rst | 74 + .../wrapper/python/wolfcrypt/docs/random.rst | 30 + .../python/wolfcrypt/docs/symmetric.rst | 42 + .../wrapper/python/wolfcrypt/include.am | 30 + .../python/wolfcrypt/requirements-testing.txt | 3 + .../WolfSSL/wrapper/python/wolfcrypt/setup.py | 56 + .../python/wolfcrypt/test/test_ciphers.py | 192 + .../python/wolfcrypt/test/test_hashes.py | 150 + .../python/wolfcrypt/test/test_random.py | 39 + .../WolfSSL/wrapper/python/wolfcrypt/tox.ini | 7 + .../python/wolfcrypt/wolfcrypt/__about__.py | 46 + .../python/wolfcrypt/wolfcrypt/__init__.py | 22 + .../python/wolfcrypt/wolfcrypt/build_ffi.py | 128 + .../python/wolfcrypt/wolfcrypt/ciphers.py | 326 + .../python/wolfcrypt/wolfcrypt/exceptions.py | 24 + .../python/wolfcrypt/wolfcrypt/hashes.py | 303 + .../python/wolfcrypt/wolfcrypt/random.py | 73 + .../python/wolfcrypt/wolfcrypt/utils.py | 37 + .../python/wolfssl/.centos-provisioner.sh | 38 + .../WolfSSL/wrapper/python/wolfssl/.gitignore | 21 + .../python/wolfssl/.ubuntu-provisioner.sh | 36 + .../wrapper/python/wolfssl/LICENSING.rst | 23 + .../wrapper/python/wolfssl/MANIFEST.in | 2 + .../WolfSSL/wrapper/python/wolfssl/Makefile | 59 + .../WolfSSL/wrapper/python/wolfssl/README.rst | 96 + .../wrapper/python/wolfssl/Vagrantfile | 17 + .../wrapper/python/wolfssl/docs/Makefile | 60 + .../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 + .../python/wolfssl/docs/installation.rst | 1 + .../wrapper/python/wolfssl/docs/licensing.rst | 1 + .../python/wolfssl/docs/requirements.txt | 2 + .../wrapper/python/wolfssl/docs/usage.rst | 87 + .../wrapper/python/wolfssl/examples/client.py | 141 + .../wrapper/python/wolfssl/examples/server.py | 153 + .../WolfSSL/wrapper/python/wolfssl/include.am | 38 + .../python/wolfssl/requirements-testing.txt | 3 + .../WolfSSL/wrapper/python/wolfssl/setup.py | 88 + .../python/wolfssl/src/wolfssl/__about__.py | 50 + .../python/wolfssl/src/wolfssl/__init__.py | 678 + .../python/wolfssl/src/wolfssl/_memory.py | 35 + .../python/wolfssl/src/wolfssl/_methods.py | 83 + .../python/wolfssl/src/wolfssl/build_ffi.py | 80 + .../python/wolfssl/src/wolfssl/exceptions.py | 89 + .../python/wolfssl/src/wolfssl/utils.py | 39 + .../wrapper/python/wolfssl/test/conftest.py | 47 + .../python/wolfssl/test/test_client.py | 66 + .../python/wolfssl/test/test_context.py | 66 + .../python/wolfssl/test/test_methods.py | 59 + .../WolfSSL/wrapper/python/wolfssl/tox.ini | 7 + 1185 files changed, 837519 insertions(+), 72138 deletions(-) create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/user_settings.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/ChangeLog.md rename FreeRTOS-Plus/Source/WolfSSL/{ChangeLog => IPP/.gitkeep} (100%) create mode 100644 FreeRTOS-Plus/Source/WolfSSL/LPCExpresso.cproject create mode 100644 FreeRTOS-Plus/Source/WolfSSL/LPCExpresso.project delete mode 100644 FreeRTOS-Plus/Source/WolfSSL/ReadMeFirst.url create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/1024/client-keyPub.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/1024/dsa-pub-1024.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/1024/server-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/1024/server-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/1024/server-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/1024/server-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/3072/client-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/3072/client-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/3072/client-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/3072/client-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/3072/client-keyPub.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/3072/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-keyPub.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/4096/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ca-cert-chain.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/client-ca.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/client-cert-ext.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/client-cert-ext.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/client-ecc-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/client-keyPub.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/client-relative-uri.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/client-uri-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/ca-int-ecc.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/ca-int.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/caEcc384Crl.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/caEccCrl.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/client-int-ecc.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/client-int.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/crl2.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/server-goodaltCrl.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/server-goodaltwildCrl.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/server-goodcnCrl.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/server-goodcnwildCrl.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/server-int-ecc.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/server-int.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/crl/wolfssl.cnf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/dh3072.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/dh3072.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/dh4096.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/dh4096.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/dsa3072.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/dsaparams.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-client-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-client-keyPub.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-client-keyPub.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-keyPkcs8.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-keyPkcs8Enc.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-keyPkcs8Enc.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-keyPub.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privOnlyCert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privOnlyKey.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privkey.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privkeyPkcs8.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privkeyPkcs8.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc-rsa-server.p12 create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc/genecc.sh create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc/wolfssl.cnf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ecc/wolfssl_384.cnf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/ca-ed25519-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/ca-ed25519-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/ca-ed25519-priv.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/ca-ed25519-priv.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/ca-ed25519.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/ca-ed25519.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519-priv.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519-priv.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-priv.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-priv.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/server-ed25519-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/server-ed25519-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/server-ed25519-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/server-ed25519-priv.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/server-ed25519-priv.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/server-ed25519.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/server-ed25519.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/ca-ed448-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/ca-ed448-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/ca-ed448-priv.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/ca-ed448-priv.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/ca-ed448.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/ca-ed448.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/client-ed448-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/client-ed448-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/client-ed448-priv.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/client-ed448-priv.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/client-ed448.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/client-ed448.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448-priv.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448-priv.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-priv.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-priv.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/external/baltimore-cybertrust-root.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/external/ca-digicert-ev.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/external/ca-globalsign-root.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/external/ca-google-root.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/external/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-key.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-alt-ecc.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-alt.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-ecc.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-ecc.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-int-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-int-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-int-ecc-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-int-ecc-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/genintcerts.sh create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain-alt-ecc.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain-alt.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain-ecc.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain-ecc.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-int-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-int-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-int-ecc-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-int-ecc-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-ca-and-intermediate-cas.txt create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-ca-and-intermediate-cas.txt.attr create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate1-ca-issued-certs.txt create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate1-ca-issued-certs.txt.attr create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate2-ca-issued-certs.txt create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate2-ca-issued-certs.txt.attr create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate3-ca-issued-certs.txt create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate3-ca-issued-certs.txt.attr create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate1-ca-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate1-ca-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate2-ca-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate2-ca-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate3-ca-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate3-ca-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/ocsp-responder-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/ocsp-responder-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/openssl.cnf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/renewcerts-for-test.sh create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/root-ca-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/root-ca-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server1-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server1-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server2-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server2-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server3-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server3-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server4-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server4-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server5-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server5-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/rsa-pub-2048.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/rsa3072.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/server-cert-chain.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-comp.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-rsa.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-self.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-self.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/server-keyPkcs8.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/server-keyPkcs8Enc.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/server-revoked-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/server-revoked-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-ber-exp02-05-2022.p7b create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-degenerate.p7b create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-ICA1-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-ICA1-pathlen0.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-assembled.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-entity-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-entity.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA1-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA1-pathlen0.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA2-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA2-pathlen1.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-assembled.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-entity-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-entity.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-ICA1-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-ICA1-pathlen1.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-assembled.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-entity-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-entity.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-ICA1-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-ICA1-pathlen127.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-assembled.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-entity-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-entity.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-ICA1-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-ICA1-pathlen128.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-assembled.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-entity-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-entity.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA1-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA1-pathlen1.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA2-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA2-pathlen0.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-assembled.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-entity-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-entity.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA1-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA1-pathlen0.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA2-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA2-pathlen1.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA3-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA3-pathlen99.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA4-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA4-pathlen5.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA5-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA5-pathlen20.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA6-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA6-pathlen10.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA7-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA7-pathlen100.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-assembled.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-entity-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-entity.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA1-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA1-pathlen0.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA2-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA2-pathlen2.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA3-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA3-pathlen2.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA4-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA4-pathlen2.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-assembled.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-entity-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-entity.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA1-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA1-no_pathlen.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA2-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA2-no_pathlen.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA3-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA3-pathlen2.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-assembled.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-entity-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-entity.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA1-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA1-no_pathlen.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA2-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA2-no_pathlen.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA3-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA3-no_pathlen.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA4-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA4-pathlen2.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-assembled.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-entity-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-entity.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test-servercert.p12 create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-ia.cfg create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-ia.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-joi.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nc.cfg create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nc.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nct.cfg create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nct.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-ns.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/crit-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/crit-key.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/dh1024.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/dh1024.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/dh512.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/dh512.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/digsigku.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-ca.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-ca.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-cert.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-cert.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/gen-ext-certs.sh create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/gen-testcerts.sh create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badaltname.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badaltname.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badaltnull.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badaltnull.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badcn.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badcn.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badcnnull.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badcnnull.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-cert-ecc-badsig.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-cert-ecc-badsig.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-cert-rsa-badsig.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-cert-rsa-badsig.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-duplicate-policy.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-garbage.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-garbage.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodalt.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodalt.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodaltwild.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodaltwild.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcn.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcn.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcnwild.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcnwild.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-localhost.der create mode 100644 FreeRTOS-Plus/Source/WolfSSL/certs/test/server-localhost.pem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ec25519.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ec448.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ecdh.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ed25519.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ed448.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ssl23.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/cyassl/options.h.in create mode 100644 FreeRTOS-Plus/Source/WolfSSL/examples/benchmark/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/examples/benchmark/tls_bench.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/examples/benchmark/tls_bench.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/examples/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/examples/sctp/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-client-dtls.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-client.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-server-dtls.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-server.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/fips-hash.sh create mode 100644 FreeRTOS-Plus/Source/WolfSSL/m4/ax_require_defined.m4 delete mode 100644 FreeRTOS-Plus/Source/WolfSSL/m4/wolfssl_darwin_clang.m4 create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/PIC32MZ-serial.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/README create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/crypto.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/crypto.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/mcapi_test.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/user_settings.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/Makefile create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/nbproject/configurations.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/nbproject/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/nbproject/project.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/Makefile create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/nbproject/configurations.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/nbproject/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/nbproject/project.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/Makefile create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/nbproject/configurations.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/nbproject/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/nbproject/project.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/Makefile create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/nbproject/configurations.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/nbproject/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/nbproject/project.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/PIC32MZ-serial.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/README create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/benchmark_main.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/test_main.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/user_settings.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/Makefile create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/nbproject/configurations.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/nbproject/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/nbproject/project.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/Makefile create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/nbproject/configurations.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/nbproject/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/nbproject/project.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/Makefile create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/nbproject/configurations.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/nbproject/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/nbproject/project.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/README create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/.cproject create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/.project create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/Sources/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/Sources/util.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/Sources/util.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/.cproject create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/.project create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Debugger/K70FN1M0.mem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Debugger/init_kinetis.tcl create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Debugger/mass_erase_kinetis.tcl create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/ReferencedRSESystems.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Sources/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Sources/main.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Sources/main.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/.cproject create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/.project create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Debugger/K70FN1M0.mem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Debugger/init_kinetis.tcl create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Debugger/mass_erase_kinetis.tcl create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/ReferencedRSESystems.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Sources/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Sources/main.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Sources/main.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl/.cproject create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl/.project create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/.cproject create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/.project create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Debugger/K70FN1M0.mem create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Debugger/init_kinetis.tcl create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Debugger/mass_erase_kinetis.tcl create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/ReferencedRSESystems.xml create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Sources/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Sources/main.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Sources/main.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch create mode 100644 FreeRTOS-Plus/Source/WolfSSL/resource.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/benchmark.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/cleanup_testfiles.sh create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/crl-revoked.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/dertoc.pl create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/external.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/google.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/memtest.sh create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp-stapling-with-ca-as-responder.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp-stapling.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp-stapling2.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/openssl.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/ping.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/pkcallbacks.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/psk.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/resume.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/sniffer-ipv6.pcap create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/sniffer-testsuite.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/stm32l4-v4_0_1_build.sh create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/testsuite.pcap create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/tls13.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/scripts/trusted_peer.test create mode 100644 FreeRTOS-Plus/Source/WolfSSL/src/bio.c delete mode 100644 FreeRTOS-Plus/Source/WolfSSL/src/io.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/src/tls13.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/src/wolfio.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/srp.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-altchains.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-chains.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-dhprime.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-dtls-sha2.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-ed25519.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-ed448.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-enckeys.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-fails.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-maxfrag-dtls.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-maxfrag.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-psk-no-id-sha2.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-psk-no-id.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-psk.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-qsh-sha2.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-qsh.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-sctp-sha2.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-sctp.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-sha2.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-sig.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13-down.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13-ecc.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13-psk.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tests/test-trustpeer.conf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/README create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/package.bld create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/package.xdc create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/package.xs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/TM4C1294NC.icf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/benchmark.cfg create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/main.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/package.bld.hide create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/package.xdc create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/TM4C1294NC.icf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/main.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/package.bld.hide create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/package.xdc create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/test.cfg create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/products.mak create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/wolfssl.bld create mode 100644 FreeRTOS-Plus/Source/WolfSSL/tirtos/wolfssl.mak create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/README.md create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_asm.S delete mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_asm.s create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_gcm_asm.S rename FreeRTOS-Plus/Source/WolfSSL/{NEWS => wolfcrypt/src/async.c} (100%) create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/blake2s.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha_asm.S create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/cmac.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/cpuid.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/cryptocb.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/curve448.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ed448.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/evp.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_448.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_x25519_128.i create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_x25519_asm.S create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fips.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fips_test.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ge_448.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/idea.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/pkcs12.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/poly1305_asm.S create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/README.md create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_aes.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_mp.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_sha.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_util.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/README.md create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/renesas_tsip_util.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/af_alg/afalg_aes.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/af_alg/afalg_hash.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/af_alg/wc_afalg.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-curve25519.S create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-curve25519.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-sha512-asm.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-aes.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-chacha.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-curve25519.S create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-curve25519.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-poly1305.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha256.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha512-asm.S create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha512-asm.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha512.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/cryptoCell.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/cryptoCellHash.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/atmel/README.md create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/atmel/atmel.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_aes.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_doc.pdf create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_driver.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_init.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_sha.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/README.md create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/README_Octeon.md create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/cavium_nitrox.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/cavium_octeon_sync.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/README.md create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/devcrypto_aes.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/devcrypto_hash.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/wc_devcrypto.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/README.md create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/quickassist.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/quickassist_mem.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/quickassist_sync.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/mynewt/mynewt_port.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/nrf51.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/nxp/ksdk_port.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/pic32/pic32mz-crypt.c delete mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/pic32/pic32mz-hash.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/st/README.md create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/st/stm32.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/st/stsafe.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/xilinx/xil-aesgcm.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/xilinx/xil-sha3.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/selftest.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha256_asm.S create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha3.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha512_asm.S create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/signature.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_arm32.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_arm64.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_armthumb.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_c32.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_c64.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_cortexm.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_dsp32.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_int.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_x86_64.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_x86_64_asm.S create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/srp.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_dsp.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_encrypt.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_pkcs11.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfcrypt_first.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfcrypt_last.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfevent.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfmath.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/README.md create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/Makefile.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/README.txt create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/autogen.sh create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/configure.ac create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/include/user_rsa.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/lib/.gitkeep create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/src/rsa.c create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl-ntru.sln create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl-ntru.vcproj create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl.rc create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl.sln create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl.vcproj create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl.vcxproj create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/aes.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/asn1t.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/buffer.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ec25519.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ec448.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ecdh.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ed25519.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ed448.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/obj_mac.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/objects.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/pkcs7.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/rc4.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/sha3.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ssl23.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/tls1.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/x509_vfy.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/async.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/cmac.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/cpuid.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/cryptocb.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/curve448.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ed448.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fe_448.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fips.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ge_448.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/idea.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/mem_track.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pkcs11.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pkcs12.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/af_alg/afalg_hash.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/af_alg/wc_afalg.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/arm/cryptoCell.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/atmel/atmel.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/caam/caam_driver.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/caam/wolfcaam.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/intel/quickassist.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/intel/quickassist_mem.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/intel/quickassist_sync.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/nrf51.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/nxp/ksdk_port.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/st/stm32.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/st/stsafe.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/selftest.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha3.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/signature.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sp.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sp_int.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/srp.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wc_encrypt.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wc_pkcs11.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wolfevent.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wolfmath.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfio.h create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wolfssl64.sln create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/Properties/AssemblyInfo.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.csproj create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/App.config create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/Properties/AssemblyInfo.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.csproj create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/App.config create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/Properties/AssemblyInfo.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.csproj create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/App.config create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/Properties/AssemblyInfo.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/Properties/Settings.Designer.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/Properties/Settings.settings create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.csproj create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/App.config create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/Properties/AssemblyInfo.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.csproj create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/App.config create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/Properties/AssemblyInfo.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/Properties/Settings.Designer.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/Properties/Settings.settings create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.csproj create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/App.config create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/AssemblyInfo.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/Settings.Designer.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/Settings.settings create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.csproj create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp.sln create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/Properties/AssemblyInfo.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.Designer.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.resx create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/wolfSSL_CSharp.csproj create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/.gitignore create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/LICENSING.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/MANIFEST.in create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/README.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/Makefile create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/asymmetric.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/conf.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/digest.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/index.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/mac.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/random.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/symmetric.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/requirements-testing.txt create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/setup.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/test/test_ciphers.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/test/test_hashes.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/test/test_random.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/tox.ini create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/__about__.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/__init__.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/build_ffi.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/ciphers.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/exceptions.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/hashes.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/random.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/utils.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/.centos-provisioner.sh create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/.gitignore create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/.ubuntu-provisioner.sh create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/LICENSING.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/MANIFEST.in create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/Makefile create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/README.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/Vagrantfile create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/Makefile create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/api.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/conf.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/examples.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/index.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/installation.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/licensing.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/requirements.txt create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/usage.rst create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/examples/client.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/examples/server.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/include.am create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/requirements-testing.txt create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/setup.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/__about__.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/__init__.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/_memory.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/_methods.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/build_ffi.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/exceptions.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/utils.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/conftest.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/test_client.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/test_context.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/test_methods.py create mode 100644 FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/tox.ini diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/FreeRTOS_Plus_WolfSSL.sln b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/FreeRTOS_Plus_WolfSSL.sln index 3f819af17..bff8b7121 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/FreeRTOS_Plus_WolfSSL.sln +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/FreeRTOS_Plus_WolfSSL.sln @@ -1,20 +1,31 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WIN32", "WIN32.vcxproj", "{C686325E-3261-42F7-AEB1-DDE5280E1CEB}" +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2041 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTOSDemo", "WIN32.vcxproj", "{C686325E-3261-42F7-AEB1-DDE5280E1CEB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Debug|Win32.ActiveCfg = Debug|Win32 {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Debug|Win32.Build.0 = Debug|Win32 + {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Debug|x64.ActiveCfg = Debug|x64 + {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Debug|x64.Build.0 = Debug|x64 {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Release|Win32.ActiveCfg = Release|Win32 {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Release|Win32.Build.0 = Release|Win32 + {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Release|x64.ActiveCfg = Release|x64 + {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D6AB2785-448B-4D5A-8422-79D28929D7E4} + EndGlobalSection EndGlobal diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/WIN32.vcxproj b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/WIN32.vcxproj index 09a064877..173262091 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/WIN32.vcxproj +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/WIN32.vcxproj @@ -1,29 +1,52 @@  - + Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + {C686325E-3261-42F7-AEB1-DDE5280E1CEB} RTOSDemo + 10.0.17134.0 Application false MultiByte + v141 + + + Application + false + MultiByte + v141 Application false MultiByte + v141 + + + Application + false + MultiByte + v141 @@ -32,19 +55,29 @@ + + + + + + + + <_ProjectFileVersion>10.0.30319.1 .\Debug\ .\Debug\ true + true .\Release\ .\Release\ false + false @@ -55,7 +88,7 @@ Disabled ..\..\Source\wolfSSL;..\..\..\FreeRTOS\Source\include;..\..\..\FreeRTOS\Source\portable\MSVC-MingW;.;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0500;WINVER=0x400;_CRT_SECURE_NO_WARNINGS;SIZEOF_LONG_LONG=8;%(PreprocessorDefinitions) + WOLFSSL_USER_SETTINGS true EnableFastChecks MultiThreadedDebug @@ -74,7 +107,7 @@ 0x0c09 - .\Debug/RTOSDemo.exe + $(TargetDir)/$(TargetFileName) true true .\Debug/WIN32.pdb @@ -89,6 +122,47 @@ .\Debug/WIN32.bsc + + + .\Debug/WIN32.tlb + + + + + Disabled + ..\..\Source\wolfSSL;..\..\..\FreeRTOS\Source\include;..\..\..\FreeRTOS\Source\portable\MSVC-MingW;.;%(AdditionalIncludeDirectories) + WOLFSSL_USER_SETTINGS + EnableFastChecks + MultiThreadedDebug + .\Debug/WIN32.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level4 + true + false + ProgramDatabase + 4206;4214;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c09 + + + $(TargetDir)/$(TargetFileName) + true + true + .\Debug/WIN32.pdb + Console + %(AdditionalDependencies) + + + + + true + .\Debug/WIN32.bsc + + .\Release/WIN32.tlb @@ -98,7 +172,7 @@ MaxSpeed OnlyExplicitInline - _WINSOCKAPI_;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + WOLFSSL_USER_SETTINGS true MultiThreaded true @@ -115,7 +189,7 @@ 0x0c09 - .\Release/RTOSDemo.exe + $(TargetDir)/$(TargetFileName) true .\Release/WIN32.pdb Console @@ -128,71 +202,197 @@ .\Release/WIN32.bsc + + + .\Release/WIN32.tlb + + + + + MaxSpeed + OnlyExplicitInline + WOLFSSL_USER_SETTINGS + true + MultiThreaded + true + .\Release/WIN32.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + ..\..\Source\include;..\..\Source\portable\MSVC-MingW;..\Common\Include;.;%(AdditionalIncludeDirectories) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c09 + + + $(TargetDir)/$(TargetFileName) + true + .\Release/WIN32.pdb + Console + ..\Common\ethernet\lwip-1.4.0\ports\win32\WinPCap + wpcap.lib;%(AdditionalDependencies) + + + true + .\Release/WIN32.bsc + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + %(PreprocessorDefinitions) %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/WIN32.vcxproj.filters b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/WIN32.vcxproj.filters index de5048fb3..c140f9d5b 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/WIN32.vcxproj.filters +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/WIN32.vcxproj.filters @@ -51,160 +51,411 @@ FreeRTOS\Source - - FreeRTOS+\wolfSSL - - - FreeRTOS+\wolfSSL - - - FreeRTOS+\wolfSSL - - - FreeRTOS+\wolfSSL - - - FreeRTOS+\wolfSSL - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - - - FreeRTOS+\wolfSSL\wolfcrypt - Demo App Source Demo App Source - + FreeRTOS+\wolfSSL\wolfcrypt - + FreeRTOS+\wolfSSL\wolfcrypt + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL + + + FreeRTOS+\wolfSSL + + + FreeRTOS+\wolfSSL + + + FreeRTOS+\wolfSSL + + + FreeRTOS+\wolfSSL + + + FreeRTOS+\wolfSSL + + + FreeRTOS+\wolfSSL + + + FreeRTOS+\wolfSSL + + + FreeRTOS+\wolfSSL + + + FreeRTOS+\wolfSSL + Demo App Source + + FreeRTOS+\wolfSSL + - + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + FreeRTOS+\wolfSSL\wolfcrypt + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/ca-cert.pem b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/ca-cert.pem index 6eacbebd0..7a8a56385 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/ca-cert.pem +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/ca-cert.pem @@ -1,12 +1,12 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15672591315981621815 (0xd9803ac3d2f4da37) + Serial Number: 9727763710660753659 (0x86fff58e10deb8fb) 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: May 7 18:21:01 2015 GMT - Not After : Jan 31 18:21:01 2018 GMT + Not Before: Apr 13 15:23:09 2018 GMT + Not After : Jan 7 15:23:09 2021 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 @@ -37,32 +37,32 @@ Certificate: 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:D9:80:3A:C3:D2:F4:DA:37 + serial:86:FF:F5:8E:10:DE:B8:FB X509v3 Basic Constraints: CA:TRUE Signature Algorithm: sha256WithRSAEncryption - 7a:af:44:3b:aa:6f:53:42:b2:33:aa:43:5f:56:30:d3:b9:96: - 0b:9a:55:5a:39:2a:0b:4e:e4:2e:f1:95:66:c9:86:36:82:8d: - 63:7c:4d:a2:ee:48:ba:03:c7:90:d7:a7:c6:74:60:48:5f:31: - a2:f9:5e:3e:c3:82:e1:e5:2f:41:81:83:29:25:79:d1:53:00: - 69:3c:ed:0a:30:3b:41:1d:92:a1:2c:a8:9d:2c:e3:23:87:79: - e0:55:6e:91:a8:50:da:46:2f:c2:20:50:3e:2b:47:97:14:b0: - 7d:04:ba:45:51:d0:6e:e1:5a:a2:4b:84:9c:4d:cd:85:04:f9: - 28:31:82:93:bc:c7:59:49:91:03:e8:df:6a:e4:56:ad:6a:cb: - 1f:0d:37:e4:5e:bd:e7:9f:d5:ec:9d:3c:18:25:9b:f1:2f:50: - 7d:eb:31:cb:f1:63:22:9d:57:fc:f3:84:20:1a:c6:07:87:92: - 26:9e:15:18:59:33:06:dc:fb:b0:b6:76:5d:f1:c1:2f:c8:2f: - 62:9c:c0:d6:de:eb:65:77:f3:5c:a6:c3:88:27:96:75:b4:f4: - 54:cd:ff:2d:21:2e:96:f0:07:73:4b:e9:93:92:90:de:62:d9: - a3:3b:ac:6e:24:5f:27:4a:b3:94:70:ff:30:17:e7:7e:32:8f: - 65:b7:75:58 + 9e:28:88:72:00:ca:e6:e7:97:ca:c1:f1:1f:9e:12:b2:b8:c7: + 51:ea:28:e1:36:b5:2d:e6:2f:08:23:cb:a9:4a:87:25:c6:5d: + 89:45:ea:f5:00:98:ac:76:fb:1b:af:f0:ce:64:9e:da:08:bf: + b6:eb:b4:b5:0c:a0:e7:f6:47:59:1c:61:cf:2e:0e:58:a4:82: + ac:0f:3f:ec:c4:ae:80:f7:b0:8a:1e:85:41:e8:ff:fe:fe:4f: + 1a:24:d5:49:fa:fb:fe:5e:e5:d3:91:0e:4f:4e:0c:21:51:71: + 83:04:6b:62:7b:4f:59:76:48:81:1e:b4:f7:04:47:8a:91:57: + a3:11:a9:f2:20:b4:78:33:62:3d:b0:5e:0d:f9:86:38:82:da: + a1:98:8d:19:06:87:21:39:b7:02:f7:da:7d:58:ba:52:15:d8: + 3b:c9:7b:58:34:a0:c7:e2:7c:a9:83:13:e1:b6:ec:01:bf:52: + 33:0b:c4:fe:43:d3:c6:a4:8e:2f:87:7f:7a:44:ea:ca:53:6c: + 85:ed:65:76:73:31:03:4e:ea:bd:35:54:13:f3:64:87:6b:df: + 34:dd:34:a1:88:3b:db:4d:af:1b:64:90:92:71:30:8e:c8:cc: + e5:60:24:af:31:16:39:33:91:50:f9:ab:68:42:74:7a:35:d9: + dd:c8:c4:52 -----BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIJANmAOsPS9No3MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD +MIIEqjCCA5KgAwIBAgIJAIb/9Y4Q3rj7MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAe -Fw0xNTA1MDcxODIxMDFaFw0xODAxMzExODIxMDFaMIGUMQswCQYDVQQGEwJVUzEQ +Fw0xODA0MTMxNTIzMDlaFw0yMTAxMDcxNTIzMDlaMIGUMQswCQYDVQQGEwJVUzEQ MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwIU2F3 dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xmc3Ns LmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZI @@ -76,11 +76,11 @@ XDjNdyXvvYB1U5Q8PcpjW58VtdMdEy8Z0TzbdjrMuH3J5cLX2kBv2CHccxtCLVOc J45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYTAlVTMRAwDgYD VQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290 aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t -MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkA2YA6w9L02jcwDAYD -VR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAeq9EO6pvU0KyM6pDX1Yw07mW -C5pVWjkqC07kLvGVZsmGNoKNY3xNou5IugPHkNenxnRgSF8xovlePsOC4eUvQYGD -KSV50VMAaTztCjA7QR2SoSyonSzjI4d54FVukahQ2kYvwiBQPitHlxSwfQS6RVHQ -buFaokuEnE3NhQT5KDGCk7zHWUmRA+jfauRWrWrLHw035F6955/V7J08GCWb8S9Q -fesxy/FjIp1X/POEIBrGB4eSJp4VGFkzBtz7sLZ2XfHBL8gvYpzA1t7rZXfzXKbD -iCeWdbT0VM3/LSEulvAHc0vpk5KQ3mLZozusbiRfJ0qzlHD/MBfnfjKPZbd1WA== +MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1jhDeuPswDAYD +VR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAniiIcgDK5ueXysHxH54SsrjH +Ueoo4Ta1LeYvCCPLqUqHJcZdiUXq9QCYrHb7G6/wzmSe2gi/tuu0tQyg5/ZHWRxh +zy4OWKSCrA8/7MSugPewih6FQej//v5PGiTVSfr7/l7l05EOT04MIVFxgwRrYntP +WXZIgR609wRHipFXoxGp8iC0eDNiPbBeDfmGOILaoZiNGQaHITm3AvfafVi6UhXY +O8l7WDSgx+J8qYMT4bbsAb9SMwvE/kPTxqSOL4d/ekTqylNshe1ldnMxA07qvTVU +E/Nkh2vfNN00oYg7202vG2SQknEwjsjM5WAkrzEWOTORUPmraEJ0ejXZ3cjEUg== -----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/server-cert.pem b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/server-cert.pem index 95df724e7..c44ba3e64 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/server-cert.pem +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/server-cert.pem @@ -5,8 +5,8 @@ Certificate: 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: May 7 18:21:01 2015 GMT - Not After : Jan 31 18:21:01 2018 GMT + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT Subject: C=US, ST=Montana, L=Bozeman, O=wolfSSL, OU=Support, CN=www.wolfssl.com/emailAddress=info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -37,32 +37,32 @@ Certificate: 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:D9:80:3A:C3:D2:F4:DA:37 + serial:86:FF:F5:8E:10:DE:B8:FB X509v3 Basic Constraints: CA:TRUE Signature Algorithm: sha256WithRSAEncryption - 67:c0:2c:a9:43:47:e7:11:14:77:ae:cc:d8:e0:6b:23:82:91: - 63:e8:a8:0d:21:c5:c8:47:97:2f:d5:f3:86:fb:6c:ce:25:f9: - 7c:78:c8:3a:22:68:f2:16:1e:d2:d2:3f:24:04:87:f2:b7:c1: - 62:63:ba:c5:fa:ae:d2:20:81:1a:d2:0c:ae:26:6b:1b:2b:10: - d3:e1:9a:4e:64:6c:97:db:36:a8:8f:f8:05:63:bf:ba:0d:88: - 0b:87:46:c9:e4:64:e3:d7:bd:b8:2d:d5:c1:c3:c4:db:55:68: - dc:a3:7a:40:b9:a9:f6:04:4a:22:cf:98:76:1c:e4:a3:ff:79: - 19:96:57:63:07:6f:f6:32:77:16:50:9b:e3:34:18:d4:eb:be: - fd:b6:6f:e3:c7:f6:85:bf:ac:32:ad:98:57:be:13:92:44:10: - a5:f3:ae:e2:66:da:44:a9:94:71:3f:d0:2f:20:59:87:e4:5a: - 40:ee:d2:e4:0c:ce:25:94:dc:0f:fe:38:e0:41:52:34:5c:bb: - c3:db:c1:5f:76:c3:5d:0e:32:69:2b:9d:01:ed:50:1b:4f:77: - a9:a9:d8:71:30:cb:2e:2c:70:00:ab:78:4b:d7:15:d9:17:f8: - 64:b2:f7:3a:da:e1:0b:8b:0a:e1:4e:b1:03:46:14:ca:94:e3: - 44:77:d7:59 + b4:54:60:ad:a0:03:32:de:02:7f:21:4a:81:c6:ed:cd:cd:d8: + 12:8a:c0:ba:82:5b:75:ad:54:e3:7c:80:6a:ac:2e:6c:20:4e: + be:4d:82:a7:47:13:5c:f4:c6:6a:2b:10:99:58:de:ab:6b:7c: + 22:05:c1:83:9d:cb:ff:3c:e4:2d:57:6a:a6:96:df:d3:c1:68: + e3:d2:c6:83:4b:97:e2:c6:32:0e:be:c4:03:b9:07:8a:5b:b8: + 84:ba:c5:39:3f:1c:58:a7:55:d7:f0:9b:e8:d2:45:b9:e3:83: + 2e:ee:b6:71:56:b9:3a:ee:3f:27:d8:77:e8:fb:44:48:65:27: + 47:4c:fb:fe:72:c3:ac:05:7b:1d:cb:eb:5e:65:9a:ab:02:e4: + 88:5b:3b:8b:0b:c7:cc:a9:a6:8b:e1:87:b0:19:1a:0c:28:58: + 6f:99:52:7e:ed:b0:3a:68:3b:8c:0a:08:74:72:ab:b9:09:c5: + ed:04:7e:6f:0b:1c:09:21:d0:cd:7f:f9:c4:5e:27:20:e4:85: + 73:52:05:d2:ba:f8:d5:8f:41:cc:23:2e:12:6d:bc:31:98:e7: + 63:a3:8e:26:cd:e8:2b:88:ee:e2:fe:3a:74:52:34:0e:fd:12: + e5:5e:69:50:20:31:34:e4:31:f1:e7:e4:5b:03:13:da:ac:41: + 6c:e7:cf:2b -----BEGIN CERTIFICATE----- MIIEnjCCA4agAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz -bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTUwNTA3 -MTgyMTAxWhcNMTgwMTMxMTgyMTAxWjCBkDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgwNDEz +MTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBkDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xEDAOBgNVBAoMB3dvbGZTU0wxEDAO BgNVBAsMB1N1cHBvcnQxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqG SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP @@ -76,23 +76,23 @@ sxEyyZKYhOLJ+NA7bgNCyh8OjjwwgckGA1UdIwSBwTCBvoAUJ45nEXTDJh0/7TNj s6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5h MRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwK Q29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcN -AQkBFhBpbmZvQHdvbGZzc2wuY29tggkA2YA6w9L02jcwDAYDVR0TBAUwAwEB/zAN -BgkqhkiG9w0BAQsFAAOCAQEAZ8AsqUNH5xEUd67M2OBrI4KRY+ioDSHFyEeXL9Xz -hvtsziX5fHjIOiJo8hYe0tI/JASH8rfBYmO6xfqu0iCBGtIMriZrGysQ0+GaTmRs -l9s2qI/4BWO/ug2IC4dGyeRk49e9uC3VwcPE21Vo3KN6QLmp9gRKIs+Ydhzko/95 -GZZXYwdv9jJ3FlCb4zQY1Ou+/bZv48f2hb+sMq2YV74TkkQQpfOu4mbaRKmUcT/Q -LyBZh+RaQO7S5AzOJZTcD/444EFSNFy7w9vBX3bDXQ4yaSudAe1QG093qanYcTDL -LixwAKt4S9cV2Rf4ZLL3OtrhC4sK4U6xA0YUypTjRHfXWQ== +AQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1jhDeuPswDAYDVR0TBAUwAwEB/zAN +BgkqhkiG9w0BAQsFAAOCAQEAtFRgraADMt4CfyFKgcbtzc3YEorAuoJbda1U43yA +aqwubCBOvk2Cp0cTXPTGaisQmVjeq2t8IgXBg53L/zzkLVdqppbf08Fo49LGg0uX +4sYyDr7EA7kHilu4hLrFOT8cWKdV1/Cb6NJFueODLu62cVa5Ou4/J9h36PtESGUn +R0z7/nLDrAV7HcvrXmWaqwLkiFs7iwvHzKmmi+GHsBkaDChYb5lSfu2wOmg7jAoI +dHKruQnF7QR+bwscCSHQzX/5xF4nIOSFc1IF0rr41Y9BzCMuEm28MZjnY6OOJs3o +K4ju4v46dFI0Dv0S5V5pUCAxNOQx8efkWwMT2qxBbOfPKw== -----END CERTIFICATE----- Certificate: Data: Version: 3 (0x2) - Serial Number: 15672591315981621815 (0xd9803ac3d2f4da37) + Serial Number: 9727763710660753659 (0x86fff58e10deb8fb) 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: May 7 18:21:01 2015 GMT - Not After : Jan 31 18:21:01 2018 GMT + Not Before: Apr 13 15:23:09 2018 GMT + Not After : Jan 7 15:23:09 2021 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 @@ -123,32 +123,32 @@ Certificate: 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:D9:80:3A:C3:D2:F4:DA:37 + serial:86:FF:F5:8E:10:DE:B8:FB X509v3 Basic Constraints: CA:TRUE Signature Algorithm: sha256WithRSAEncryption - 7a:af:44:3b:aa:6f:53:42:b2:33:aa:43:5f:56:30:d3:b9:96: - 0b:9a:55:5a:39:2a:0b:4e:e4:2e:f1:95:66:c9:86:36:82:8d: - 63:7c:4d:a2:ee:48:ba:03:c7:90:d7:a7:c6:74:60:48:5f:31: - a2:f9:5e:3e:c3:82:e1:e5:2f:41:81:83:29:25:79:d1:53:00: - 69:3c:ed:0a:30:3b:41:1d:92:a1:2c:a8:9d:2c:e3:23:87:79: - e0:55:6e:91:a8:50:da:46:2f:c2:20:50:3e:2b:47:97:14:b0: - 7d:04:ba:45:51:d0:6e:e1:5a:a2:4b:84:9c:4d:cd:85:04:f9: - 28:31:82:93:bc:c7:59:49:91:03:e8:df:6a:e4:56:ad:6a:cb: - 1f:0d:37:e4:5e:bd:e7:9f:d5:ec:9d:3c:18:25:9b:f1:2f:50: - 7d:eb:31:cb:f1:63:22:9d:57:fc:f3:84:20:1a:c6:07:87:92: - 26:9e:15:18:59:33:06:dc:fb:b0:b6:76:5d:f1:c1:2f:c8:2f: - 62:9c:c0:d6:de:eb:65:77:f3:5c:a6:c3:88:27:96:75:b4:f4: - 54:cd:ff:2d:21:2e:96:f0:07:73:4b:e9:93:92:90:de:62:d9: - a3:3b:ac:6e:24:5f:27:4a:b3:94:70:ff:30:17:e7:7e:32:8f: - 65:b7:75:58 + 9e:28:88:72:00:ca:e6:e7:97:ca:c1:f1:1f:9e:12:b2:b8:c7: + 51:ea:28:e1:36:b5:2d:e6:2f:08:23:cb:a9:4a:87:25:c6:5d: + 89:45:ea:f5:00:98:ac:76:fb:1b:af:f0:ce:64:9e:da:08:bf: + b6:eb:b4:b5:0c:a0:e7:f6:47:59:1c:61:cf:2e:0e:58:a4:82: + ac:0f:3f:ec:c4:ae:80:f7:b0:8a:1e:85:41:e8:ff:fe:fe:4f: + 1a:24:d5:49:fa:fb:fe:5e:e5:d3:91:0e:4f:4e:0c:21:51:71: + 83:04:6b:62:7b:4f:59:76:48:81:1e:b4:f7:04:47:8a:91:57: + a3:11:a9:f2:20:b4:78:33:62:3d:b0:5e:0d:f9:86:38:82:da: + a1:98:8d:19:06:87:21:39:b7:02:f7:da:7d:58:ba:52:15:d8: + 3b:c9:7b:58:34:a0:c7:e2:7c:a9:83:13:e1:b6:ec:01:bf:52: + 33:0b:c4:fe:43:d3:c6:a4:8e:2f:87:7f:7a:44:ea:ca:53:6c: + 85:ed:65:76:73:31:03:4e:ea:bd:35:54:13:f3:64:87:6b:df: + 34:dd:34:a1:88:3b:db:4d:af:1b:64:90:92:71:30:8e:c8:cc: + e5:60:24:af:31:16:39:33:91:50:f9:ab:68:42:74:7a:35:d9: + dd:c8:c4:52 -----BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIJANmAOsPS9No3MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD +MIIEqjCCA5KgAwIBAgIJAIb/9Y4Q3rj7MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAe -Fw0xNTA1MDcxODIxMDFaFw0xODAxMzExODIxMDFaMIGUMQswCQYDVQQGEwJVUzEQ +Fw0xODA0MTMxNTIzMDlaFw0yMTAxMDcxNTIzMDlaMIGUMQswCQYDVQQGEwJVUzEQ MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwIU2F3 dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xmc3Ns LmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZI @@ -162,11 +162,11 @@ XDjNdyXvvYB1U5Q8PcpjW58VtdMdEy8Z0TzbdjrMuH3J5cLX2kBv2CHccxtCLVOc J45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYTAlVTMRAwDgYD VQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290 aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t -MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkA2YA6w9L02jcwDAYD -VR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAeq9EO6pvU0KyM6pDX1Yw07mW -C5pVWjkqC07kLvGVZsmGNoKNY3xNou5IugPHkNenxnRgSF8xovlePsOC4eUvQYGD -KSV50VMAaTztCjA7QR2SoSyonSzjI4d54FVukahQ2kYvwiBQPitHlxSwfQS6RVHQ -buFaokuEnE3NhQT5KDGCk7zHWUmRA+jfauRWrWrLHw035F6955/V7J08GCWb8S9Q -fesxy/FjIp1X/POEIBrGB4eSJp4VGFkzBtz7sLZ2XfHBL8gvYpzA1t7rZXfzXKbD -iCeWdbT0VM3/LSEulvAHc0vpk5KQ3mLZozusbiRfJ0qzlHD/MBfnfjKPZbd1WA== +MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1jhDeuPswDAYD +VR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAniiIcgDK5ueXysHxH54SsrjH +Ueoo4Ta1LeYvCCPLqUqHJcZdiUXq9QCYrHb7G6/wzmSe2gi/tuu0tQyg5/ZHWRxh +zy4OWKSCrA8/7MSugPewih6FQej//v5PGiTVSfr7/l7l05EOT04MIVFxgwRrYntP +WXZIgR609wRHipFXoxGp8iC0eDNiPbBeDfmGOILaoZiNGQaHITm3AvfafVi6UhXY +O8l7WDSgx+J8qYMT4bbsAb9SMwvE/kPTxqSOL4d/ekTqylNshe1ldnMxA07qvTVU +E/Nkh2vfNN00oYg7202vG2SQknEwjsjM5WAkrzEWOTORUPmraEJ0ejXZ3cjEUg== -----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/user_settings.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/user_settings.h new file mode 100644 index 000000000..f2d523b17 --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_WolfSSL_Windows_Simulator/user_settings.h @@ -0,0 +1,55 @@ +/* user_settings.h + * + * Copyright (C) 2006-2020 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 + */ + + + + +/*-- Cipher related definitions ----------------------------------------------- + * + * + *----------------------------------------------------------------------------*/ + + + #define HAVE_AESGCM + #define WOLFSSL_AES_128 + #define HAVE_AES_CBC + #define WOLFSSL_SHA512 + + #define HAVE_TLS_EXTENSIONS + #define HAVE_SUPPORTED_CURVES + #define HAVE_ECC + #define HAVE_CURVE25519 + #define CURVE25519_SMALL + #define HAVE_ED25519 + + #define WC_RSA_BLINDING + #define ECC_TIMING_RESISTANT + #define TFM_TIMING_RESISTANT + + +/*-- Debugging options ------------------------------------------------------ + * + * "DEBUG_WOLFSSL" definition enables log to output into stdout. + * Note: wolfSSL_Debugging_ON() must be called just after wolfSSL_Init(). + *----------------------------------------------------------------------------*/ + +/*#define DEBUG_WOLFSSL*/ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/ChangeLog.md b/FreeRTOS-Plus/Source/WolfSSL/ChangeLog.md new file mode 100644 index 000000000..94de8f63b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/ChangeLog.md @@ -0,0 +1,2545 @@ +# wolfSSL Release 4.4.0 (04/22/2020) + +If you have questions about this release, then feel free to contact us on our +info@ address. + +Release 4.4.0 of wolfSSL embedded TLS has bug fixes and new features including: + +## New Feature Additions + +* Hexagon support. +* DSP builds to offload ECC verify operations. +* Certificate Manager callback support. +* New APIs for running updates to ChaCha20/Poly1305 AEAD. +* Support for use with Apache. +* Add support for IBM s390x. +* PKCS8 support for ED25519. +* OpenVPN support. +* Add P384 curve support to SP. +* Add BIO and EVP API. +* Add AES-OFB mode. +* Add AES-CFB mode. +* Add Curve448, X448, and Ed448. +* Add Renesas Synergy S7G2 build and hardware acceleration. + +## Fixes + +* Fix for RSA public encrypt / private sign with RSA key sizes over 2048-bit. +* Correct misspellings. +* Secure renegotiation fix. +* Fix memory leak when using ATECC and non-SECP256R1 curves for sign, verify, + or shared secret. +* Fix for K64 MMCAU with `WOLFSSL_SMALL_STACK_CACHE`. +* Fix the RSA verify only build. +* Fix in SP C implementation for small stack. +* Fix using the auth key id extension is set, hash might not be present. +* Fix when flattening certificate structure to include the subject alt names. +* Fixes for building with ECC sign/verify only. +* Fix for ECC and no cache resistance. +* Fix memory leak in DSA. +* Fix build on minGW. +* Fix `PemToDer()` call in `ProcessBuffer()` to set more than ECC. +* Fix for using RSA without SHA-512. +* Add some close tags to the echoserver HTTP example output. +* Miscellaneous fixes and updates for static analysis reports. +* Fixes for time structure support. +* Fixes for VxWorks support. +* Fixes for Async crypto support. +* Fix cache resist compile to work with SP C code. +* Fixes for Curve25519 x64 asm. +* Fix for SP x64 div. +* Fix for DTLS edge case where CCS and Finished come out of order and the + retransmit pool gets flushed. +* Fix for infinite loop in SHA-1 with small inputs. Thanks to Peter W. +* Fix for FIPS Hmac where `wc_HmacInit()` isn't used. `wc_HmacSetKey()` needs + to initialize the Hmac structure. Type is set to NONE, and checked against + NONE, not 0. +* Fixes for SP RSA private operations. +* Fixes for Xilinx SDK and Zynq UltraScale+ MPSoC +* Fix leak when building with HAVE_AESGCM and NO_AES_DECRYPT. Thanks G.G. +* Fixes for building ECC without ASN. +* Fix for async TLSv1.3 issues. +* Fix `wc_KeyPemToDer()` with PKCS1 and empty key. +* Omit `-fomit-frame-pointer` from CFLAGS in configure.ac. + +## Improvements/Optimizations + +* Qt 5.12 and 5.13 support. +* Added more digest types to Cryptocell RSA sign/verify. +* Some memory usage improvements. +* Speed improvements for mp_rand. +* Improvements to CRL and OCSP support. +* Refactor Poly1305 AEAD/MAC to reduce duplicate code. +* Add blinding to RSA key gen. +* Improvements to blinding. +* Improvement and expansion of OpenSSL Compatibility Layer. +* Improvements to ChaCha20. +* Improvements to X.509 processing. +* Improvements to ECC support. +* Improvement in detecting 64-bit support. +* Refactor to combine duplicate ECC parameter parsing code. +* Improve keyFormat to be set by algId and let later key parsing produce fail. +* Add test cases for 3072-bit and 4096-bit RSA keys. +* Improve signature wrapper and DH test cases. +* Improvements to the configure.ac script. +* Added constant time RSA q modinv p. +* Improve performance of SP Intel 64-bit asm. +* Added a few more functions to the ABI list. +* Improve TLS bidirectional shutdown behavior. +* OpenSSH 8.1 support. +* Improve performance of RSA/DH operations on x64. +* Add support for PKCS7/CMS Enveloped data with fragmented encrypted content. +* Example linker description for FIPS builds to enforce object ordering. +* C# wrapper improvements. Added TLS client example and TLSv1.3 methods. +* Allow setting MTU in DTLS. +* Improve PKCS12 create for outputting encrypted bundles. +* Constant time EC map to affine for private operations. +* Improve performance of RSA public key ops with TFM. +* Smaller table version of AES encrypt/decrypt. +* Support IAR with position independent code (ROPI). +* Improve speed of AArch64 assembly. +* Support AES-CTR with AES-NI. +* Support AES-CTR on esp32. +* Add a no malloc option for small SP math. + +## This release of wolfSSL includes fixes for 2 security vulnerabilities. + +* For fast math, use a constant time modular inverse when mapping to affine + when operation involves a private key - keygen, calc shared secret, sign. + Thank you to Alejandro Cabrera Aldaya, Cesar Pereida García and + Billy Bob Brumley from the Network and Information Security Group (NISEC) + at Tampere University for the report. + +* Change constant time and cache resistant ECC mulmod. Ensure points being + operated on change to make constant time. Thank you to Pietro Borrello at + Sapienza University of Rome. + +For additional vulnerability information visit the vulnerability page at +https://www.wolfssl.com/docs/security-vulnerabilities/ + +See INSTALL file for build instructions. +More info can be found on-line at https://wolfssl.com/wolfSSL/Docs.html + + + +# wolfSSL Release 4.3.0 (12/20/2019) + +If you have questions about this release, then feel free to contact us on our info@ address. + +Release 4.3.0 of wolfSSL embedded TLS has bug fixes and new features including: + +##### New Feature Additions +* Add --enable-libwebsockets option for support of libwebsockets build +* Updated support for NGINX 1.15.0 and added support for 1.16.1 +* Add wc_scrypt_ex API which can take in iterations rather than cost +* Updates to RSA-PSS salt lengths. Macro WOLFSSL_PSS_SALT_LEN_DISCOVER allows for discovering the salt length. Passing RSA_PSS_SALT_LEN_DISCOVER value into wc_RsaPSS_Verify_ex attempts to discover salt length and can use larger salt lengths +* Additional OpenSSL compatibility API wolfSSL_CertManagerGetCerts and wolfSSL_X509_STORE_GetCerts for retrieving certificates +* Add support for 4096-bit RSA/DH operations to SP (single precision) build +* Update support for Google WebRTC to branch m79 +* Adds new FREESCALE_MQX_5_0 macro for MQX 5.0 support +* Adds a CMS/PKCS#7 callback for signing SignedData raw digests enabled with macro HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK and call to function wc_PKCS7_SetRsaSignRawDigestCb +* Add --disable-errorqueue feature to disable adding debug nodes to queue with --enable-opensslextra build +* After defining WOLFSSL_SHUTDOWNONCE macro the function wolfSSL_shutdown will return a specific error code of SSL_SHUTDOWN_ALREADY_DONE_E, to indicate to the application that the shutdown has already occurred +* Add AES-CCM decryption to benchmarking app bundled with wolfSSL + + +##### Fixes +* Fixes IAR warnings with IAR-EWARM 7.50.2 +* Alignment fixes for mmCAU with AES and hashing algorithms +* Fix check for plaintext length when using Encrypt-Then-MAC +* Fix for unit tests with NGINX and debug mode +* Fix for macro names in test cases (WOLFSSL_PUBLIC_MP) and pkcs7.c (HAVE_AESCCM) +* Fix for Apache want read case with BIO retry flag +* Fix for PKCS7 streaming mode that would error rather than verify bundle +* Fix for freeing mutex for X509 and wolfSSL_EVP_PKEY_free, applies to OPENSSL_EXTRA / --enable-opensslextra builds +* Fix for encrypt then MAC when re-handshaking, encrypted handshakes change over to ETM now +* Fix for curve25519 assembly optimizations with GCC + AVX2 +* Fix to hang onto certificate for retrieval if using secure renegotiation and session resumption +* Fixes case where the heap hint is created before WOLFSSL_CTX, when calling wc_LoadStaticMemory instead of wolfSSL_CTX_load_static_memory +* Fix for setting correct return value in PKCS12 parse error case +* Reset certificate extension policy count +* Fix for memcpy with TLS I/O buffers when using staticmemory pools and loading memory as WOLFMEM_IO_POOL_FIXED +* Fixes and updates for STM32 port, including additional mutex protection, AES-GCM decrypt auth tag, AES-CTR mode with CubeMX, update to OpenSTM32 project +* Fix for EVP CipherUpdate decrypt and add a test case +* DTLS fixes including; some DTLS sequence number issues in general where the sequence was incremented twice for each record and some offset values in the DTLS window checking +* Fix sp_add to handle carries properly (--enable-sp-math build) +* Additional sanity check on OCSP response decoder +* Fix for vasprintf with Solaris and AIX builds +* Fix for missing variable declaration with --enable-scep --with-libz build +* Fix for certificate date check with async build +* Sanity check on “out” length with Base64_Decode added +* Decode X.509 name - check input length for jurisdiction +* Additional sanity check on variable out index with DecodePolicyOID +* Fix for PKCS#12 PBKDF buffer size for buffer overflow +* TLS supported curve extension check curve name is in range before checking for disabled +* Sanity check for non TLS 1.3 cipher suite with TLS 1.3 connection +* Poly1305 AVX2 assembly optimization fix for carry with large input values +* Fixes for coverity report including null termination of test case strings and initialization of PKCS7 variables +* Fix for API visibility of wc_ed25519_check_key which resolves a wolfcrypt-py install issue +* Sanity check on max ALPN length accepted +* Additional sanity check when parsing CRL’s for copying the structure, fix for bounds checking +* Additional checks on error string length for debug mode and check for null termination +* ProcessPeerCerts allocating memory for exts with OPENSSL_EXTRA properly +* Clear the top bit when generating a serial number +* Sanity check that ASN date characters are valid ASCII characters +* Fix to add deterministic ECDSA and fix corner cases for add point. +* When getting the DH public key, initialize the P, G, and Pub pointers to NULL, then set that we own the DH parameters flag. This allows FreeSSL to correctly clean up the DH key. + +##### Improvements/Optimizations +* Added configure error report with using invalid build of --enable-opensslextra and --enable-opensslcoexist together +* Update PKCS11 for determining key type given the private key type +* Update DoVerifyCallback to check verify param hostName and ipasc (--enable-opensslextra builds) +* additional null sanity checks on input arguments with QSH and Cryptocell builds +* Additional checks on RSA key added to the function wc_CheckRsaKey +* Updates for EBSNET support, including fseek, revised macros in settings.h, and realloc support +* MISRA-C updates for SP math code +* Update to allow compiling for pwdbased/PBKDF2 with having NO_ASN defined +* Modify KeyShare and PreSharedKey TLS 1.3 extension linked list advancement to be easier for compilers to handle +* Optimization to parsing certificate extension name strings +* Adjustment to example server -x runtime behavior when encountering an unrecoverable error case +* Remove Blake2b support from HMAC +* Adds new hash wrapper init wc_HashInit_ex and Adds new PBKDF2 API wc_PBKDF2_ex for using heap hints for custom memory pools +* Adding script to cleanup generated test files, scripts/cleanup_testfiles.sh +* Support 20-byte serial numbers and disallow 0 +* sp_div improved to handle when a has less digits than d (--enable-sp-math build) +* When decoding a policy OID and turning it into a human readable string use snprintf() +* set the IV length of EVP AES GCM to 96-bits by default +* Allow adding CAs for root CA's over the wire that do not have the extended key usage cert_sign set +* Added logging messages for SendAlert call and update to send alert after verify certificate callback +* updates for synchronous OCTEON support in the Sniffer +* Rework BER to DER functions to not be recursive +* Updates to find CRL by AuthKeyId +* Add a check for subject name hash after matching AKID +* Enhancement to mp_invmod/fp_exptmod/sp_exptmod to handle more inputs +* Remove requirement for macro NO_SKID when CRL use is enabled +* Improvements on XFTELL return code and MAX_WOLFSSL_FILE_SIZE checking +* When checking if value is prime return NO in the case of the value 1 +* Improve Cortex-M RSA/DH assembly code performance +* Additional sanity checks on arrays and buffers with OCSP + + +##### This release of wolfSSL includes a fix for 6 security vulnerabilities. + + +A fix for having an additional sanity check when parsing certificate domain names was added. This fix checks that the domain name location index is not past the maximum value before setting it. The reported issue affects users that are parsing certificates and have --enable-opensslextra (macro OPENSSL_EXTRA), or build options that turn this on such as --enable-all, when building wolfSSL. The CVE associated with the fix is CVE-2019-18840. + +Fix to set a limit on the maximum size of DTLS handshake messages. By default the RFC allows for handshake message sizes of up to 2^24-1 bytes long but in typical field use cases the handshake messages are not this large. Setting a maximum size limit on the handshake message helps avoid a potential DoS attack due to memory being malloc’d. The new default max size is set to handle a certificate chain length of approximately 9, 2048 bit RSA certificates. This only effects builds that have DTLS turned on and have applications that are using DTLS. + +Fix for a potential hang when ECC caching is enabled (off by default) and --enable-fastmath is used. ECC caching is off by default and is turned on in builds that are using --enable-all or --enable-fpecc. This issue does not affect builds that are using the macro WOLFSSL_VALIDATE_ECC_IMPORT which turns on validating all ECC keys that are imported. To fix this potential hang case a sanity check on the input values to the internal invmod function was added. + + +To fix a potential fault injection attack on a wrapper function for wolfCrypt RSA signature generations an additional sanity check verifying the signature after it’s creation was added. This check is already done automatically in current versions of wolfSSL with TLS connections (internal function call of VerifyRsaSign during TLS state machine). The report only affects users making calls to the wolfCrypt function wc_SignatureGenerateHash and does not affect current TLS use cases. Thanks to Daniel Moghimi (@danielmgmi) from Worcester Polytechnic Institute for the report. + + +Blinding was added for DSA signing operations. The DSA signing uses the BEEA algorithm during modular inversion of the nonce which can potentially leak the nonce through side channels such as cache and power fluctuations. The fix of adding in blinding makes the DSA signing operation more resistant to side channel attacks. Users who have turned on DSA (disabled by default) and are performing signing operations should update. Note that DSA is not used in any TLS connections. Thanks to Daniel Moghimi (@danielmgmi) from Worcester Polytechnic Institute for the report. + + +Fix to add additional side channel cache attack resistance to the internal ECC function wc_ecc_mulmod_ex. This function by default is used with ECDSA signing operations. Users should update if performing ECDSA singing operations (server side ECC TLS connections, mutual authentication on client side) or calling wolfCrypt ECC sign functions and have the potential for outside users to perform sophisticated monitoring of the cache.Thanks to Daniel Moghimi (@danielmgmi) from Worcester Polytechnic Institute for the report. + + +For additional vulnerability information visit the vulnerability page at https://www.wolfssl.com/docs/security-vulnerabilities/ + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL Release 4.2.0 (10/22/2019) + +If you have questions about this release, then feel free to contact us on our info@ address. + +Release 4.2.0 of wolfSSL embedded TLS has bug fixes and new features including: + + +##### New Feature Additions +* Over 198 OpenSSL compatibility API’s added +* Apache port added for compiling with wolfSSL using --enable-apachehttpd +* Port for using wolfSSL with OpenVSwitch +* Port for Renesas TSIP added +* Visual Studio Solution for Azure Sphere Devices (MT3620 and MT3620-mini) added to the directory IDE/VS-AZURE-SPHERE +* Addition of Coldfire MCF5441X NetBurner example to the directory IDE/M68K/ +* Added support for prime checking to SP math build +* Addition of DYNAMIC_TYPE_BIGINT type for tracking mp_int allocations +* Addition of wc_ecc_get_curve_params API for getting ecc_set_type params for a curve +* Adding in TLS_SHA256_SHA256 and TLS_SHA384_SHA384 TLS1.3 cipher suites (null ciphers) +* Added in PKCS7 decryption callbacks for CMS operations +* Added handling for optional ECC parameters with PKCS7 KARI +* Addition to configure.ac for FIPS wolfRand builds +* Adding the flag WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY for ignoring certificate date checks with the functions wolfSSL_CTX_load_verify_buffer_ex and wolfSSL_CTX_load_verify_locations_ex +* Support for PKCS8 keys added to the function wolfSSL_CTX_use_PrivateKey_buffer +* Support for KECCAK hashing. Build with macro WOLFSSL_HASH_FLAGS and call wc_Sha3_SetFlags(&sha, WC_HASH_SHA3_KECCAK256) before the first SHA3 update +* Addition of setting secure renegotiation at CTX level +* Addition of KDS (NXP Kinetis Design Studio) example project to directory IDE/KDS/ +* Support for Encrypt-Then-MAC to TLS 1.2 and below +* Added a new build option for a TITAN session cache that can hold just over 2 million session entries (--enable-titancache) +* Synchronous Quick Assist Support for Sniffer +* Added Support for SiFive HiFive Unleashed board +* Support for Google WebRTC added in to compatibility layer build +* Additional Sniffer features; IPv6 sniffer support, Fragment chain input, Data store callback, Various statistics tweaks and other Sniffer fixes + + +##### Fixes +* Addition of internal content digest checks for PKCS7 SignedData message types that also have signed attributes present. Users could previously check the content digest against the messageDigest attribute, but this adds a default internal check. It’s advised that if users are not doing their own checks that they update wolfSSL version. +* A fix for BIO and base64 encoding/decoding +* A fix for memory management of CTX / WOLFSSL_METHOD pointer with staticmemory build +* A fix for detection of AES-NI support to read bit 25 from ECX +* A fix a DTLS handshake message retransmit bug corner case +* Additional fixes to coding style and uninitialized values using cppcheck tool +* Fixes for failing IAR builds, thanks to Joseph C. for the report +* Fixes for ARMv8 Poly1305 inline assembly code to compile with clang 3.5 +* Fixes for esp-idf build warnings +* A fix for XSNPRINTF with mingw32 builds +* Fixes for strncpy warnings when compiling with newer versions of GCC +* A fix for using IV of all 0’s as default case with AES-NI when no IV passed in +* Fixes for types with 16 bit systems, thanks to Ralf Schlatterbeck +* Fixes for build with devcrypto/afalg and aesccm, thanks to GitHub user cotequeiroz for the report +* Fixes for addressing handling of pathLen constraint when parsing certificate chains +* A DTLS fix for alert packet injection at end of handshake +* Fixes for Poly1305 AArch64 assembly code +* A fix for memory management in error cases when adding a CA, this resolves a coverity report +* A fix for SP math for precomputation tables to not include infinity field +* Fixes for checks on defines with AVX2 and Poly1305 build +* Fixes for CubeMX HAL v1.15 with STM32F7 +* A fix for TLS 1.3 to always send Key Share extension +* A fix for a potential buffer over read in TLS 1.3 DoTls13SupportedVersions, thanks to Artem for the report + + +##### Improvements/Optimizations +* Optimization to SP math, changing variables to const where possible. Thanks to Yair Poleg (yair.poleg@ayyeka.com) of Ayyeka for proposing static declaration of global constant variables in SP code +* Additional fuzz testing and fixes for TLS 1.3 use, including additional TLS 1.3 alert messages (PR#2440 for more information) +* Additional sanity check that ciphersuite from client hello is used in server hello response (check can be removed with the macro WOLFSSL_NO_STRICT_CIPHER_SUITE) +* Improved MMCAU performance: SHA-1 by 35%, SHA-256 by 20% and MD5 by 78% +* By default, disallow SHA-2 cipher suites from being used in TLS 1.0 and 1.1 handshakes (can be ignored with macro WOLFSSL_OLDTLS_SHA2_CIPHERSUITES) +* Optimization of export session buffer size with enable option --enable-sessionexport=nopeer +* Spelling fixes in comments and some cast warnings resolved +* Updates to abstract atoi to XATOI when used, this allows for better portability when making calls to the system function atoi for converting strings to integers +* Improvements to the STSAFE-A100 error code handling, providing better debug information +* Adding a sanity check on TLS 1.3 ticket encrypt callback +* Specialized implementations of mod exp when base is 2 + + + +##### This release of wolfSSL includes a fix for 5 security vulnerabilities. + +Fix for sanity check on reading TLS 1.3 pre-shared key extension. This fixes a potential for an invalid read when TLS 1.3 and pre-shared keys is enabled. Users without TLS 1.3 enabled are unaffected. Users with TLS 1.3 enabled and HAVE_SESSION_TICKET defined or NO_PSK not defined should update wolfSSL versions. Thanks to Robert Hoerr for the report. + +Fix for potential program hang when ocspstapling2 is enabled. This is a moderate level fix that affects users who have ocspstapling2 enabled(off by default) and are on the server side. In parsing a CSR2 (Certificate Status Request v2 ) on the server side, there was the potential for a malformed extension to cause a program hang. Thanks to Robert Hoerr for the report. + +Two moderate level fixes involving an ASN.1 over read by one byte. CVE-2019-15651 is for a fix that is due to a potential one byte over read when decoding certificate extensions. CVE-2019-16748 is for a fix on a potential one byte overread with checking certificate signatures. This affects builds that do certificate parsing and do not have the macro NO_SKID defined.Thanks to Yan Jia and the researcher team from Institute of Software, Chinese Academy of Sciences for the report. + +High level fix for DSA operations involving an attack on recovering DSA private keys. This fix affects users that have DSA enabled and are performing DSA operations (off by default). All users that have DSA enabled and are using DSA keys are advised to regenerate DSA keys and update wolfSSL version. ECDSA is NOT affected by this and TLS code is NOT affected by this issue. Thanks to Ján Jančár for the report. + + +For additional vulnerability information visit the vulnerability page at https://www.wolfssl.com/docs/security-vulnerabilities/ + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + + +# wolfSSL Release 4.1.0 (07/22/2019) + +Release 4.1.0 of wolfSSL embedded TLS has bug fixes and new features including: + +* A fix for the check on return value when verifying PKCS7 bundle signatures, all users with applications using the function wc_PKCS7_VerifySignedData should update +* Adding the function wc_PKCS7_GetSignerSID for PKCS7 firmware bundles as a getter function for the signers SID +* PKCS7 callback functions for unwrapping of CEK and for decryption +* Adding the error value PKCS7_SIGNEEDS_CHECK when no certificates are available in a PKCS7 bundle to verify the signature +* TLS 1.3 fixes including if major version is TLS Draft then it is now ignored and if version negotiation occurs but none were matched then an alert is now sent +* Addition of the WOLFSSL_PSK_ONE_ID macro for indicating that only one identity in TLS 1.3 PSK is available and will be cached +* Adding sanity checks on length of PSK identity from a TLS 1.3 pre-shared key extension +* Additional sanity checks and alert messages added for TLS 1.3 +* Adding XTIME_MS macro to simplify the tls13.c time requirement +* Improvements and refactoring of code related to parsing and creating TLS 1.3 client hello packets +* TLS 1.3 version renegotiation now happens before interpreting ClientHello message +* Chacha20 algorithm optimizations on the ARM architecture for performance increase +* Poly1305 algorithm performance enhancements for the ARM architecture using the SIMD NEON extension +* Curve25519 and Ed25519 optimized for ARM architecture for performance increase +* SHA-512/384 optimizations for performance with ARM architecture using the SIMD NEON extension +* Sniffer updates including adding support for the null cipher and static ECDH key exchange and new SSLWatchCb callback +* Cipher suite TLS_RSA_WITH_NULL_MD5 for use with the sniffer (off by default) +* Sniffer statistic print outs with the macro WOLFSSL_SNIFFER_STATS defined +* A fix for wolfSSL_DH_generate_key when WOLFSSL_SMALL_STACK is defined +* wolfSSL_BN_Init implementation for opensslextra builds +* Updates to the function wolfSSL_i2d_RSAPrivateKey and additional automated tests +* Fixes for EVP_CipherFinal edge cases to match behavior desired +* Check for appropriate private vs public flag with ECC key decode in wolfSSL_EC_KEY_LoadDer_ex, thanks to Eric Miller for the report +* Implementation of the function wolfSSL_PEM_write_DHparams +* wolfSSL_RAND_seed is called in wolfSSL_Init now when opensslextra is enabled +* CryptoCell-310 support on nRF52840 added +* Fixes for atmel_ecc_create_pms to free the used slot. +* Fixes for building ATECC with ATCAPRINTF or WOLFSSL_PUBLIC_MP +* Cortex-M code changes to support IAR compiler +* Improvements to STM32 AES-GCM performance +* Fixes for 16-bit systems including PK callbacks, ATECC and LowResTimer function ptoto. +* IAR-EWARM compiler warning fix +* Clean up of user_settings for CS+ port +* Updating Renesas example projects to the latest version +* Micrium updates adjusting STATIC macro name and added inline flag +* Fixes for building with WOLFSSL_CUSTOM_CURVES on Windows +* Updates and refactor to the default build settings with Arduino +* Fixes for visibility tags with Cygwin build +* STSAFE Improvements to support wolfSSL Crypto Callbacks +* Improvements to NetBSD builds and mutex use in test case +* Updating TI hardware offload with WOLFSSL_TI_CRYPT build +* Maintaining Xilinx FreeRTOS port by adjusting time.h include in wolfSSL +* SiFive HiFive E31 RISC‐V core family port +* Port for Telit IoT AppZone SDK +* OCSP Response signed by issuer with identical SKID fix +* Fix for sending revoked certificate with OCSP +* Honor the status sent over connection with peers and do not perform an internal OCSP lookup +* Adding the build flag `--enable-ecccustcurves=all` to enable all curve types +* Support add for Ed25519ctx and Ed25519ph sign/verify algorithms as per RFC 8032 +* Addition of the macro WOLFSSL_NO_SIGALG to disable signature algorithms extension +* wc_AesCtrEncrypt in place addition, where input and output buffer can be the same buffer +* Single shot API added for SHA3; wc_Sha3_224Hash, wc_Sha3_256Hash, wc_Sha3_384Hash, wc_Sha3_512Hash +* Function additions for JSSE support some of which are wolfSSL_get_ciphers_iana and wolfSSL_X509_verify along with expansion of the --enable-jni option +* Macro guards for more modular SHA3 build (i.e. support for 384 size only) +* Benchmarking -thread argument support for asynchronous crypto +* Blake2s support (--enable-blake2s), which provides 32-bit Blake2 support +* Macro SHA256_MANY_REGISTERS addition to potentially speed up SHA256 depending on architecture +* Additional TLS alert messages sent with the macro WOLFSSL_EXTRA_ALERTS defined +* Feature to fail resumption of a session if the session’s cipher suite is not in the client’s list, this can be overridden by defining the macro NO_RESUME_SUITE_CHECK +* Fallback SCSV (Signaling Cipher Suite Value) support on Server only (--enable-fallback-scsv) +* DTLS export state only (wolfSSL_dtls_export_state_only) which is a subset of the information exported from previous DTLS export function +* Function wc_DhCheckPubValue added to perform simple validity checks on DH keys +* Support for RSA SHA-224 signatures with TLS added +* Additional option “-print” to the benchmark app for printing out a brief summary after benchmarks are complete +* Adding (--disable-pkcs12) option and improvements for disabled sections in pwdbased.c, asn.c, rsa.c, pkcs12.c and wc_encrypt +* Added DES3 support to the wolfSSL crypto callbacks +* Compile time fixes for build case with SP math and RSA only +* Fixes for Coverity static analysis report including explicit initialization of reported stack variables some additional Coverity fixes added thanks to Martin +* Fixes for scan build warnings (i.e possible null dereference in ecc.c) +* Resetting verify send value with a call to wolfSSL_clear function +* Fix for extern with sp_ModExp_2048 when building with --cpp option +* Fix for typo issue with --enable-sp=cortexm +* Adding #pragma warning disable 4127 for tfm.c when building with Visual Studio +* Improvements to the maximum ECC signature calculations +* Improvements to TLS write handling in error cases which helps user application not go through with a wolfSSL_write attempt after a wolfSSL_read failure +* Fix for read directory functions with Windows (wc_ReadDirFirst and wc_ReadDirNext) +* Sanity check on index before accessing domain component buffer in call to wolfSSL_X509_NAME_get_entry +* Sending fatal alert from client side on version error +* Fix for static RSA cipher suite with PK callback and no loaded private key +* Fix for potential memory leak in error case with the function wc_DsaKeyToDer, thanks to Chris H. for the report +* Adjusting STRING_USER macro to remove includes of standard lib or +* Bug fix for checking wrong allocation assignment in the function wc_PBKDF2 and handling potential leak on allocation failure. This case is only hit when the specific call to malloc fails in the function wc_PBKDF2. Thanks to Robert Altnoeder (Linbit) for the report +* Improved length checks when parsing ASN.1 certificates +* extern "C" additions to header files that were missing them +* Improved checking of return values with TLS extension functions and error codes +* Removing redundant calls to the generate function when instantiating and reseeding DRBG +* Refactoring and improvements to autoconf code with consolidating AM_CONDITIONAL statements +* Improvements for handling error return codes when reading input from transport layer +* Improvements to efficiency of SNI extension parsing and error checking with ALPN parsing +* Macro WOLFSSL_DEBUG_TLS addition for printing out extension data being parsed during a TLS connection +* Adjustment of prime testing with --disable-fastmath builds + + +This release of wolfSSL includes a fix for 2 security vulnerabilities. + +There is a fix for a potential buffer overflow case with the TLSv1.3 PSK extension parsing. This affects users that are enabling TLSv1.3 (--enable-tls13). Thanks to Robert Hoerr for the report. The CVE associated with the report is CVE-2019-11873. + +There is a fix for the potential leak of nonce sizes when performing ECDSA signing operations. The leak is considered to be difficult to exploit but it could potentially be used maliciously to perform a lattice based timing attack against previous wolfSSL versions. ECC operations with --enable-sp and --enable-sp-asm are not affected, users with private ECC keys in other builds that are performing ECDSA signing operations should update versions of wolfSSL along with private ECC keys. Thanks to Ján Jančár from Masaryk University for the report. + + +# wolfSSL Release 4.0.0 (03/20/2019) + +Release 4.0.0 of wolfSSL embedded TLS has bug fixes and new features including: + +* Support for wolfCrypt FIPS v4.0.0, certificate #3389 +* FIPS Ready Initiative +* Compatibility fixes for secure renegotiation with Chrome +* Better size check for TLS record fragment reassembly +* Improvements to non-blocking and handshake message retry support for DTLS +* Improvements to OCSP with ECDSA signers +* Added TLS server side secure renegotiation +* Added TLS Trusted CA extension +* Add support for the Deos Safety Critical RTOS +* OCSP fixes for memory management and initializations +* Fixes for EVP Cipher decryption padding checks +* Removal of null terminators on `wolfSSL_X509_print` substrings +* `wolfSSL_sk_ASN1_OBJCET_pop` function renamed to `wolfSSL_sk_ASN1_OBJECT_pop` +* Adjustment to include path in compatibility layer for evp.h and objects.h +* Fixes for decoding BER encoded PKCS7 contents +* TLS handshake now supports using PKCS #11 for private keys +* PKCS #11 support of HMAC, AES-CBC and random seeding/generation +* Support for named FFDHE parameters in TLS 1.2 (RFC 7919) +* Port to Zephyr Project +* Move the TLS PRF to wolfCrypt. +* Update to CMS KARI support +* Added ESP32 WROOM support +* Fixes and additions to the OpenSSL compatibility layer +* Added WICED Studio Support +* MDK CMSIS RTOS v2 +* Xcode project file update +* Fixes for ATECC508A/ATECC608A +* Fixes issue with CA path length for self signed root CA's +* Fixes for Single Precision (SP) ASM when building sources directly +* Fixes for STM32 AES GCM +* Fixes for ECC sign with hardware to ensure the input is truncated +* Fixes for proper detection of PKCS7 buffer overflow case +* Fixes to handle degenerate PKCS 7 with BER encoding +* Fixes for TLS v1.3 handling of 6144 and 8192 bit keys +* Fixes for possible build issues with SafeRTOS +* Added `ECC_PUBLICKEY_TYPE` to the support PEM header types +* Added strict checking of the ECDSA signature DER encoding length +* Added ECDSA option to limit sig/algos in client_hello to key size with + `USE_ECDSA_KEYSZ_HASH_ALGO` +* Added Cortex-M support for Single Precision (SP) math +* Added wolfCrypt RSA non-blocking time support +* Added 16-bit compiler support using --enable-16bit option +* Improved Arduino sketch example +* Improved crypto callback features +* Improved TLS benchmark tool +* Added new wrapper for snprintf for use with certain Visual Studio builds, + thanks to David Parnell (Cambridge Consultants) + +This release of wolfSSL includes a fix for 1 security vulnerability. + +* Fixed a bug in tls_bench.c example test application unrelated to the crypto + or TLS portions of the library. (CVE-2019-6439) + + +# wolfSSL Release 3.15.7 (12/26/2018) + +Release 3.15.7 of wolfSSL embedded TLS has bug fixes and new features including: + +* Support for Espressif ESP-IDF development framework +* Fix for XCode build with iPhone simulator on i386 +* PKCS7 support for generating and verify bundles using a detached signature +* Fix for build disabling AES-CBC and enabling opensslextra compatibility layer +* Updates to sniffer for showing session information and handling split messages across records +* Port update for Micrium uC/OS-III +* Feature to adjust max fragment size post handshake when compiled with the macro WOLFSSL_ALLOW_MAX_FRAGMENT_ADJUST +* Adding the macro NO_MULTIBYTE_PRINT for compiling out special characters that embedded devices may have problems with +* Updates for Doxygen documentation, including PKCS #11 API and more +* Adding Intel QuickAssist v1.7 driver support for asynchronous crypto +* Adding Intel QuickAssist RSA key generation and SHA-3 support +* RSA verify only (--enable-rsavfy) and RSA public only (--enable-rsapub) builds added +* Enhancements to test cases for increased code coverage +* Updates to VxWorks port for use with Mongoose, including updates to the OpenSSL compatibility layer +* Yocto Project ease of use improvements along with many updates and build instructions added to the INSTALL file +* Maximum ticket nonce size was increased to 8 +* Updating --enable-armasm build for ease of use with autotools +* Updates to internal code checking TLS 1.3 version with a connection +* Removing unnecessary extended master secret from ServerHello if using TLS 1.3 +* Fix for TLS v1.3 HelloRetryRequest to be sent immediately and not grouped + + + +This release of wolfSSL includes a fix for 1 security vulnerability. + +Medium level fix for potential cache attack with a variant of Bleichenbacher’s attack. Earlier versions of wolfSSL leaked PKCS #1 v1.5 padding information during private key decryption that could lead to a potential padding oracle attack. It is recommended that users update to the latest version of wolfSSL if they have RSA cipher suites enabled and have the potential for malicious software to be ran on the same system that is performing RSA operations. Users that have only ECC cipher suites enabled and are not performing RSA PKCS #1 v1.5 Decryption operations are not vulnerable. Also users with TLS 1.3 only connections are not vulnerable to this attack. Thanks to Eyal Ronen (Weizmann Institute), Robert Gillham (University of Adelaide), Daniel Genkin (University of Michigan), Adi Shamir (Weizmann Institute), David Wong (NCC Group), and Yuval Yarom (University of Adelaide and Data61) for the report. + +The paper for further reading on the attack details can be found at http://cat.eyalro.net/cat.pdf. + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL Release 3.15.5 (11/07/2018) + +Release 3.15.5 of wolfSSL embedded TLS has bug fixes and new features including: + +* Fixes for GCC-8 warnings with strings +* Additional compatibility API’s added, including functions like wolfSSL_X509_CA_num and wolfSSL_PEM_read_X509_CRL +* Fixes for OCSP use with NGINX port +* Renamed the macro INLINE to WC_INLINE for inline functions +* Doxygen updates and formatting for documentation generation +* Added support for the STM32L4 with AES/SHA hardware acceleration +* Adds checking for critical extension with certificate Auth ID and the macro WOLFSSL_ALLOW_CRIT_SKID to override the check +* Added public key callbacks to ConfirmSignature function to expand public key callback support +* Added ECC and Curve25519 key generation callback support +* Fix for memory management with wolfSSL_BN_hex2bn function +* Added support for dynamic allocation of PKCS7 structure using wc_PKCS7_New and wc_PKCS7_Free +* Port to apache mynewt added in the directory wolfssl-3.15.5/IDE/mynewt/* +* OCSP stapling in TLS 1.3 additions +* Port for ASIO added with --enable-asio configure flag +* Contiki port added with macro WOLFSSL_CONTIKI +* Memory free optimizations with adding in earlier free’s where possible +* Made modifications to the primality testing so that the Miller-Rabin tests check against up to 40 random numbers rather than a fixed list of small primes +* Certificate validation time generation updated +* Fixes for MQX classic 4.0 with IAR-EWARM +* Fix for assembly optimized version of Curve25519 +* Make SOCKET_PEER_CLOSED_E consistent between read and write cases +* Relocate compatibility layer functions for OpenSSH port update +* Update to Intel® SGX port, files included by Windows version and macros defined when using WOLFSSL_SGX +* Updates to Nucleus version supported +* Stack size reduction with smallstack build +* Updates to Rowley-Crossworks settings for CMSIS 4 +* Added reference STSAFE-A100 public key callbacks for TLS support +* Added reference ATECC508A/ATECC608A public key callbacks for TLS support +* Updated support for latest CryptoAuthLib (10/25/2018) +* Added a wolfSSL static library project for Atollic TrueSTUDIO +* Flag to disable AES-CBC and have only AEAD cipher suites with TLS +* AF_ALG and cryptodev-linux crypto support added +* Update to IO callbacks with use of WOLFSSL_BIO +* Additional support for parsing certificate subject OIDs (businessCategory, jurisdiction of incorporation country, and jurisdiction of incorporation state) +* Added wc_ecc_ecport_ex and wc_export_inti API's for ECC hex string exporting +* Updates to XCODE build with wolfSSL +* Fix for guard on when to include sys/time.h header +* Updates and enhancements to the GCC-ARM example +* Fix for PKCS8 padding with encryption +* Updates for wolfcrypt JNI wrapper +* ALT_ECC_SIZE use with SP math +* PIC32MZ hardware acceleration buffer alignment fixes +* Renesas e2studio project files added +* Renesas RX example project added +* Fix for DH algorithm when using SP math with ARM assembly +* Fixes and enhancements for NXP K82 support +* Benchmark enhancements to print in CSV format and in Japanese +* Support for PKCS#11 added with --enable-pkcs11 +* Fixes for asynchronous crypto use with TLS 1.3 +* TLS 1.3 only build, allows for disabling TLS 1.2 and earlier protocols +* Fix for GCC warnings in function wolfSSL_ASN1_TIME_adj +* Added --enable-asn=nocrypt for certificate only parsing support +* Added support for parsing PIV format certificates with the function wc_ParseCertPIV and macro WOLFSSL_CERT_PIV +* Added APIs to support GZIP +* Updates to support Lighttpd +* Version resource added for Windows DLL builds +* Increased code coverage with additional testing +* Added support for constructed OCTET_STRING with PKCS#7 signed data +* Added DTLS either (server/client) side initialization setting +* Minor fixes for building with MINGW32 compiler +* Added support for generic ECC PEM header/footer with PKCS8 parsing +* Added Japanese output to example server and client with “-1 1” flag +* Added USE_ECDSA_KEYSZ_HASH_ALGO macro for building to use digest sizes that match ephemeral key size +* Expand PKCS#7 CMS support with KEKRI, PWRI and ORI +* Streaming capability for PKCS#7 decoding and sign verify added + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL Release 3.15.3 (6/20/2018) + +Release 3.15.3 of wolfSSL embedded TLS has bug fixes and new features including: + +* ECDSA blinding added for hardening against side channel attacks +* Fix for compatibility layer build with no server and no client defined +* Use of optimized Intel assembly instructions on compatible AMD processor +* wolfCrypt Nucleus port additions +* Fix added for MatchDomainName and additional tests added +* Fixes for building with ‘WOLFSSL_ATECC508A’ defined +* Fix for verifying a PKCS7 file in BER format with indefinite size + + +This release of wolfSSL fixes 2 security vulnerability fixes. + +Medium level fix for PRIME + PROBE attack combined with a variant of Lucky 13. Constant time hardening was done to avoid potential cache-based side channel attacks when verifying the MAC on a TLS packet. CBC cipher suites are susceptible on systems where an attacker could gain access and run a parallel program for inspecting caching. Only wolfSSL users that are using TLS/DTLS CBC cipher suites need to update. Users that have only AEAD and stream cipher suites set, or have built with WOLFSSL_MAX_STRENGTH (--enable-maxstrength), are not vulnerable. Thanks to Eyal Ronen, Kenny Paterson, and Adi Shamir for the report. + +Medium level fix for a ECDSA side channel attack. wolfSSL is one of over a dozen vendors mentioned in the recent Technical Advisory “ROHNP” by author Ryan Keegan. Only wolfSSL users with long term ECDSA private keys using our fastmath or normal math libraries on systems where attackers can get access to the machine using the ECDSA key need to update. An attacker gaining access to the system could mount a memory cache side channel attack that could recover the key within a few thousand signatures. wolfSSL users that are not using ECDSA private keys, that are using the single precision math library, or that are using ECDSA offloading do not need to update. (blog with more information https://www.wolfssl.com/wolfssh-and-rohnp/) + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + +# wolfSSL Release 3.15.0 (06/05/2018) + +Release 3.15.0 of wolfSSL embedded TLS has bug fixes and new features including: + +* Support for TLS 1.3 Draft versions 23, 26 and 28. +* Add FIPS SGX support! +* Single Precision assembly code added for ARM and 64-bit ARM to enhance performance. +* Improved performance for Single Precision maths on 32-bit. +* Improved downgrade support for the TLS 1.3 handshake. +* Improved TLS 1.3 support from interoperability testing. +* Added option to allow TLS 1.2 to be compiled out to reduce size and enhance security. +* Added option to support Ed25519 in TLS 1.2 and 1.3. +* Update wolfSSL_HMAC_Final() so the length parameter is optional. +* Various fixes for Coverity static analysis reports. +* Add define to use internal struct timeval (USE_WOLF_TIMEVAL_T). +* Switch LowResTimer() to call XTIME instead of time(0) for better portability. +* Expanded OpenSSL compatibility layer with a bevy of new functions. +* Added Renesas CS+ project files. +* Align DH support with NIST SP 800-56A, add wc_DhSetKey_ex() for q parameter. +* Add build option for CAVP self test build (--enable-selftest). +* Expose mp_toradix() when WOLFSSL_PUBLIC_MP is defined. +* Example certificate expiration dates and generation script updated. +* Additional optimizations to trim out unused strings depending on build options. +* Fix for DN tag strings to have “=” when returning the string value to users. +* Fix for wolfSSL_ERR_get_error_line_data return value if no more errors are in the queue. +* Fix for AES-CBC IV value with PIC32 hardware acceleration. +* Fix for wolfSSL_X509_print with ECC certificates. +* Fix for strict checking on URI absolute vs relative path. +* Added crypto device framework to handle PK RSA/ECC operations using callbacks, which adds new build option `./configure --enable-cryptodev` or `WOLF_CRYPTO_DEV`. +* Added devId support to ECC and PKCS7 for hardware based private key. +* Fixes in PKCS7 for handling possible memory leak in some error cases. +* Added test for invalid cert common name when set with `wolfSSL_check_domain_name`. +* Refactor of the cipher suite names to use single array, which contains internal name, IANA name and cipher suite bytes. +* Added new function `wolfSSL_get_cipher_name_from_suite` for getting IANA cipher suite name using bytes. +* Fixes for fsanitize reports. +* Fix for openssl compatibility function `wolfSSL_RSA_verify` to check returned size. +* Fixes and improvements for FreeRTOS AWS. +* Fixes for building openssl compatibility with FreeRTOS. +* Fix and new test for handling match on domain name that may have a null terminator inside. +* Cleanup of the socket close code used for examples, CRL/OCSP and BIO to use single macro `CloseSocket`. +* Refactor of the TLSX code to support returning error codes. +* Added new signature wrapper functions `wc_SignatureVerifyHash` and `wc_SignatureGenerateHash` to allow direct use of hash. +* Improvement to GCC-ARM IDE example. +* Enhancements and cleanups for the ASN date/time code including new API's `wc_GetDateInfo`, `wc_GetCertDates` and `wc_GetDateAsCalendarTime`. +* Fixes to resolve issues with C99 compliance. Added build option `WOLF_C99` to force C99. +* Added a new `--enable-opensslall` option to enable all openssl compatibility features. +* Added new `--enable-webclient` option for enabling a few HTTP API's. +* Added new `wc_OidGetHash` API for getting the hash type from a hash OID. +* Moved `wolfSSL_CertPemToDer`, `wolfSSL_KeyPemToDer`, `wolfSSL_PubKeyPemToDer` to asn.c and renamed to `wc_`. Added backwards compatibility macro for old function names. +* Added new `WC_MAX_SYM_KEY_SIZE` macro for helping determine max key size. +* Added `--enable-enckeys` or (`WOLFSSL_ENCRYPTED_KEYS`) to enable support for encrypted PEM private keys using password callback without having to use opensslextra. +* Added ForceZero on the password buffer after done using it. +* Refactor unique hash types to use same internal values (ex WC_MD5 == WC_HASH_TYPE_MD5). +* Refactor the Sha3 types to use `wc_` naming, while retaining old names for compatibility. +* Improvements to `wc_PBKDF1` to support more hash types and the non-standard extra data option. +* Fix TLS 1.3 with ECC disabled and CURVE25519 enabled. +* Added new define `NO_DEV_URANDOM` to disable the use of `/dev/urandom`. +* Added `WC_RNG_BLOCKING` to indicate block w/sleep(0) is okay. +* Fix for `HAVE_EXT_CACHE` callbacks not being available without `OPENSSL_EXTRA` defined. +* Fix for ECC max bits `MAX_ECC_BITS` not always calculating correctly due to macro order. +* Added support for building and using PKCS7 without RSA (assuming ECC is enabled). +* Fixes and additions for Cavium Nitrox V to support ECC, AES-GCM and HMAC (SHA-224 and SHA3). +* Enabled ECC, AES-GCM and SHA-512/384 by default in (Linux and Windows) +* Added `./configure --enable-base16` and `WOLFSSL_BASE16` configuration option to enable Base16 API's. +* Improvements to ATECC508A support for building without `WOLFSSL_ATMEL` defined. +* Refactor IO callback function names to use `_CTX_` to eliminate confusion about the first parameter. +* Added support for not loading a private key for server or client when `HAVE_PK_CALLBACK` is defined and the private PK callback is set. +* Added new ECC API `wc_ecc_sig_size_calc` to return max signature size for a key size. +* Cleanup ECC point import/export code and added new API `wc_ecc_import_unsigned`. +* Fixes for handling OCSP with non-blocking. +* Added new PK (Primary Key) callbacks for the VerifyRsaSign. The new callbacks API's are `wolfSSL_CTX_SetRsaVerifySignCb` and `wolfSSL_CTX_SetRsaPssVerifySignCb`. +* Added new ECC API `wc_ecc_rs_raw_to_sig` to take raw unsigned R and S and encodes them into ECDSA signature format. +* Added support for `WOLFSSL_STM32F1`. +* Cleanup of the ASN X509 header/footer and XSTRNCPY logic. +* Add copyright notice to autoconf files. (Thanks Brian Aker!) +* Updated the M4 files for autotools. (Thanks Brian Aker!) +* Add support for the cipher suite TLS_DH_anon_WITH_AES256_GCM_SHA384 with test cases. (Thanks Thivya Ashok!) +* Add the TLS alert message unknown_psk_identity (115) from RFC 4279, section 2. (Thanks Thivya Ashok!) +* Fix the case when using TCP with timeouts with TLS. wolfSSL shall be agnostic to network socket behavior for TLS. (DTLS is another matter.) The functions `wolfSSL_set_using_nonblock()` and `wolfSSL_get_using_nonblock()` are deprecated. +* Hush the AR warning when building the static library with autotools. +* Hush the “-pthread” warning when building in some environments. +* Added a dist-hook target to the Makefile to reset the default options.h file. +* Removed the need for the darwin-clang.m4 file with the updates provided by Brian A. +* Renamed the AES assembly file so GCC on the Mac will build it using the preprocessor. +* Add a disable option (--disable-optflags) to turn off the default optimization flags so user may supply their own custom flags. +* Correctly touch the dummy fips.h header. + +If you have questions on any of this, then email us at info@wolfssl.com. +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL Release 3.14.0 (03/02/2018) + +Release 3.14.0 of wolfSSL embedded TLS has bug fixes and new features including: + +* TLS 1.3 draft 22 and 23 support added +* Additional unit tests for; SHA3, AES-CMAC, Ed25519, ECC, RSA-PSS, AES-GCM +* Many additions to the OpenSSL compatibility layer were made in this release. Some of these being enhancements to PKCS12, WOLFSSL_X509 use, WOLFSSL_EVP_PKEY, and WOLFSSL_BIO operations +* AVX1 and AVX2 performance improvements with ChaCha20 and Poly1305 +* Added i.MX CAAM driver support with Integrity OS support +* Improvements to logging with debugging, including exposing more API calls and adding options to reduce debugging code size +* Fix for signature type detection with PKCS7 RSA SignedData +* Public key call back functions added for DH Agree +* RSA-PSS API added for operating on non inline buffers (separate input and output buffers) +* API added for importing and exporting raw DSA parameters +* Updated DSA key generation to be FIPS 186-4 compliant +* Fix for wolfSSL_check_private_key when comparing ECC keys +* Support for AES Cipher Feedback(CFB) mode added +* Updated RSA key generation to be FIPS 186-4 compliant +* Update added for the ARM CMSIS software pack +* WOLFSSL_IGNORE_FILE_WARN macro added for avoiding build warnings when not working with autotools +* Performance improvements for AES-GCM with AVX1 and AVX2 +* Fix for possible memory leak on error case with wc_RsaKeyToDer function +* Make wc_PKCS7_PadData function available +* Updates made to building SGX on Linux +* STM32 hashing algorithm improvements including clock/power optimizations and auto detection of if SHA2 is supported +* Update static memory feature for FREERTOS use +* Reverse the order that certificates are compared during PKCS12 parse to account for case where multiple certificates have the same matching private key +* Update NGINX port to version 1.13.8 +* Support for HMAC-SHA3 added +* Added stricter ASN checks to enforce RFC 5280 rules. 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. +* Option to have ecc_mul2add function public facing +* Getter function wc_PKCS7_GetAttributeValue added for PKCS7 attributes +* Macros NO_AES_128, NO_AES_192, NO_AES_256 added for AES key size selection at compile time +* Support for writing multiple organizations units (OU) and domain components (DC) with CSR and certificate creation +* Support for indefinite length BER encodings in PKCS7 +* Added API for additional validation of prime q in a public DH key +* Added support for RSA encrypt and decrypt without padding + + +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.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-tlsv10” 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: + +- Poly1305 Windows macros fix. Thanks to GitHub user Jay Satiro +- Compatibility layer expanded with multiple functions added +- Improve fp_copy performance with ALT_ECC_SIZE +- OCSP updates and improvements +- Fixes for IAR EWARM 8 compiler warnings +- Reduce stack usage with ECC_CACHE_CURVE disabled +- Added ECC export raw for public and private key +- Fix for NO_ASN_TIME build +- Supported curves extensions now populated by default +- Add DTLS build without big integer math +- Fix for static memory feature with wc_ecc_verify_hash_ex and not SHAMIR +- Added PSK interoperability testing to script bundled with wolfSSL +- Fix for Python wrapper random number generation. Compiler optimizations with Python could place the random number in same buffer location each time. Thanks to GitHub user Erik Bray (embray) +- Fix for tests on unaligned memory with static memory feature +- Add macro WOLFSSL_NO_OCSP_OPTIONAL_CERTS to skip optional OCSP certificates +- Sanity checks on NULL arguments added to wolfSSL_set_fd and wolfSSL_DTLS_SetCookieSecret +- mp_jacobi stack use reduced, thanks to Szabi Tolnai for providing a solution to reduce stack usage + + +This release of wolfSSL fixes 2 low and 1 medium level security vulnerability. + +Low level fix of buffer overflow for when loading in a malformed temporary DH file. Thanks to Yueh-Hsun Lin and Peng Li from KNOX Security, Samsung Research America for the report. + +Medium level fix for processing of OCSP response. If using OCSP without hard faults enforced and no alternate revocation checks like OCSP stapling then it is recommended to update. + +Low level fix for potential cache attack on RSA operations. If using wolfSSL RSA on a server that other users can have access to monitor the cache, then it is recommended to update wolfSSL. Thanks to Andreas Zankl, Johann Heyszl and Georg Sigl at Fraunhofer AISEC for the initial report. + +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.0 (12/21/2016) + +## Release 3.10.0 of wolfSSL has bug fixes and new features including: + +- Added support for SHA224 +- Added scrypt feature +- Build for Intel SGX use, added in directory IDE/WIN-SGX +- Fix for ChaCha20-Poly1305 ECDSA certificate type request +- Enhance PKCS#7 with ECC enveloped data and AES key wrap support +- Added support for RIOT OS +- Add support for parsing PKCS#12 files +- ECC performance increased with custom curves +- ARMv8 expanded to AArch32 and performance increased +- Added ANSI-X9.63-KDF support +- Port to STM32 F2/F4 CubeMX +- Port to Atmel ATECC508A board +- Removed fPIE by default when wolfSSL library is compiled +- Update to Python wrapper, dropping DES and adding wc_RSASetRNG +- Added support for NXP K82 hardware acceleration +- Added SCR client and server verify check +- Added a disable rng option with autoconf +- Added more tests vectors to test.c with AES-CTR +- Updated DTLS session export version number +- Updated DTLS for 64 bit sequence numbers +- Fix for memory management with TI and WOLFSSL_SMALL_STACK +- Hardening RSA CRT to be constant time +- Fix uninitialized warning with IAR compiler +- Fix for C# wrapper example IO hang on unexpected connection termination + + +This release of wolfSSL fixes a low level security vulnerability. The vulnerability reported was a potential cache attack on RSA operations. If using wolfSSL RSA on a server that other users can have access to monitor the cache, then it is recommended to update wolfSSL. Thanks to Andreas Zankl, Johann Heyszl and Georg Sigl at Fraunhofer AISEC for the report. More information will be available on our site: + +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.9.10 (9/23/2016) + +## Release 3.9.10 of wolfSSL has bug fixes and new features including: + +- Default configure option changes: + 1. DES3 disabled by default + 2. ECC Supported Curves Extension enabled by default + 3. New option Extended Master Secret enabled by default +- Added checking CA certificate path length, and new test certs +- Fix to DSA pre padding and sanity check on R/S values +- Added CTX level RNG for single-threaded builds +- Intel RDSEED enhancements +- ARMv8 hardware acceleration support for AES-CBC/CTR/GCM, SHA-256 +- Arduino support updates +- Added the Extended Master Secret TLS extension + 1. Enabled by default in configure options, API to disable + 2. Added support for Extended Master Secret to sniffer +- OCSP fix with issuer key hash, lookup refactor +- Added support for Frosted OS +- Added support for DTLS over SCTP +- Added support for static memory with wolfCrypt +- Fix to ECC Custom Curve support +- Support for asynchronous wolfCrypt RSA and TLS client +- Added distribution build configure option +- Update the test certificates + +This release of wolfSSL fixes medium level security vulnerabilities. Fixes for +potential AES, RSA, and ECC side channel leaks is included that a local user +monitoring the same CPU core cache could exploit. VM users, hyper-threading +users, and users where potential attackers have access to the CPU cache will +need to update if they utilize AES, RSA private keys, or ECC private keys. +Thanks to Gorka Irazoqui Apecechea and Xiaofei Guo from Intel Corporation for +the report. More information will be available on our site: + +https://wolfssl.com/wolfSSL/security/vulnerabilities.php + +See INSTALL file for build instructions. +More info can be found on-line at https://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.9.8 (7/29/2016) + +##Release 3.9.8 of wolfSSL has bug fixes and new features including: + +- Add support for custom ECC curves. +- Add cipher suite ECDHE-ECDSA-AES128-CCM. +- Add compkey enable option. This option is for compressed ECC keys. +- Add in the option to use test.h without gettimeofday function using the macro + WOLFSSL_USER_CURRTIME. +- Add RSA blinding for private key operations. Enable option of harden which is + on by default. This negates timing attacks. +- Add ECC and TLS support for all SECP, Koblitz and Brainpool curves. +- Add helper functions for static memory option to allow getting optimum buffer + sizes. +- Update DTLS behavior on bad MAC. DTLS silently drops packets with bad MACs now. +- Update fp_isprime function from libtom enhancement/cleanup repository. +- Update sanity checks on inputs and return values for AES-CMAC. +- Update wolfSSL for use with MYSQL v5.6.30. +- Update LPCXpresso eclipse project to not include misc.c when not needed. +- Fix retransmit of last DTLS flight with timeout notification. The last flight + is no longer retransmitted on timeout. +- Fixes to some code in math sections for compressed ECC keys. This includes + edge cases for buffer size on allocation and adjustments for compressed curves + build. The code and full list can be found on github with pull request #456. +- Fix function argument mismatch for build with secure renegotiation. +- X.509 bug fixes for reading in malformed certificates, reported by researchers + at Columbia University +- Fix GCC version 6 warning about hard tabs in poly1305.c. This was a warning + produced by GCC 6 trying to determine the intent of code. +- Fixes for static memory option. Including avoid potential race conditions with + counters, decrement handshake counter correctly. +- Fix anonymous cipher with Diffie Hellman on the server side. Was an issue of a + possible buffer corruption. For information and code see pull request #481. + + +- One high level security fix that requires an update for use with static RSA + cipher suites was submitted. This fix was the addition of RSA blinding for + private RSA operations. We recommend servers who allow static RSA cipher + suites to also generate new private RSA keys. Static RSA cipher suites are + turned off by default. + +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.9.6 (6/14/2016) + +##Release 3.9.6 of wolfSSL has bug fixes and new features including: + +- Add staticmemory feature +- Add public wc_GetTime API with base64encode feature +- Add AES CMAC algorithm +- Add DTLS sessionexport feature +- Add python wolfCrypt wrapper +- Add ECC encrypt/decrypt benchmarks +- Add dynamic session tickets +- Add eccshamir option +- Add Whitewood netRandom support --with-wnr +- Add embOS port +- Add minimum key size checks for RSA and ECC +- Add STARTTLS support to examples +- Add uTasker port +- Add asynchronous crypto and wolf event support +- Add compile check for misc.c with inline +- Add RNG benchmark +- Add reduction to stack usage with hash-based RNG +- Update STM32F2_CRYPTO port with additional algorithms supported +- Update MDK5 projects +- Update AES-NI +- Fix for STM32 with STM32F2_HASH defined +- Fix for building with MinGw +- Fix ECC math bugs with ALT_ECC_SIZE and key sizes over 256 bit (1) +- Fix certificate buffers github issue #422 +- Fix decrypt max size with RSA OAEP +- Fix DTLS sanity check with DTLS timeout notification +- Fix free of WOLFSSL_METHOD on failure to create CTX +- Fix memory leak in failure case with wc_RsaFunction (2) + +- No high level security fixes that requires an update though we always +recommend updating to the latest +- (1) Code changes for ECC fix can be found at pull requests #411, #416, and #428 +- (2) Builds using RSA with using normal math and not RSA_LOW_MEM should update + +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.9.0 (03/18/2016) + +##Release 3.9.0 of wolfSSL has bug fixes and new features including: + +- Add new leantls configuration +- Add RSA OAEP padding at wolfCrypt level +- Add Arduino port and example client +- Add fixed point DH operation +- Add CUSTOM_RAND_GENRATE_SEED_OS and CUSTOM_RAND_GENERATE_BLOCK +- Add ECDHE-PSK cipher suites +- Add PSK ChaCha20-Poly1305 cipher suites +- Add option for fail on no peer cert except PSK suites +- Add port for Nordic nRF51 +- Add additional ECC NIST test vectors for 256, 384 and 521 +- Add more granular ECC, Ed25519/Curve25519 and AES configs +- Update to ChaCha20-Poly1305 +- Update support for Freescale KSDK 1.3.0 +- Update DER buffer handling code, refactoring and reducing memory +- Fix to AESNI 192 bit key expansion +- Fix to C# wrapper character encoding +- Fix sequence number issue with DTLS epoch 0 messages +- Fix RNGA with K64 build +- Fix ASN.1 X509 V3 certificate policy extension parsing +- Fix potential free of uninitialized RSA key in asn.c +- Fix potential underflow when using ECC build with FP_ECC +- Fixes for warnings in Visual Studio 2015 build + +- No high level security fixes that requires an update though we always +recommend updating to the latest +- FP_ECC is off by default, users with it enabled should update for the zero +sized hash fix + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + +# wolfSSL (Formerly CyaSSL) Release 3.8.0 (12/30/2015) + +##Release 3.8.0 of wolfSSL has bug fixes and new features including: + +- Example client/server with VxWorks +- AESNI use with AES-GCM +- Stunnel compatibility enhancements +- Single shot hash and signature/verify API added +- Update cavium nitrox port +- LPCXpresso IDE support added +- C# wrapper to support wolfSSL use by a C# program +- (BETA version)OCSP stapling added +- Update OpenSSH compatibility +- Improve DTLS handshake when retransmitting finished message +- fix idea_mult() for 16 and 32bit systems +- fix LowResTimer on Microchip ports + +- No high level security fixes that requires an update though we always +recommend updating to the latest + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + +# wolfSSL (Formerly CyaSSL) Release 3.7.0 (10/26/2015) + +##Release 3.7.0 of wolfSSL has bug fixes and new features including: + +- ALPN extension support added for HTTP2 connections with --enable-alpn +- Change of example/client/client max fragment flag -L -> -F +- Throughput benchmarking, added scripts/benchmark.test +- Sniffer API ssl_FreeDecodeBuffer added +- Addition of AES_GCM to Sniffer +- Sniffer change to handle unlimited decrypt buffer size +- New option for the sniffer where it will try to pick up decoding after a + sequence number acknowldgement fault. Also includes some additional stats. +- JNI API setter and getter function for jobject added +- User RSA crypto plugin abstraction. An example placed in wolfcrypt/user-crypto +- fix to asn configuration bug +- AES-GCM/CCM fixes. +- Port for Rowley added +- Rowley Crossworks bare metal examples added +- MDK5-ARM project update +- FreeRTOS support updates. +- VXWorks support updates. +- Added the IDEA cipher and support in wolfSSL. +- Update wolfSSL website CA. +- CFLAGS is usable when configuring source. + +- No high level security fixes that requires an update though we always +recommend updating to the latest + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + +#wolfSSL (Formerly CyaSSL) Release 3.6.8 (09/17/2015) + +##Release 3.6.8 of wolfSSL fixes two high severity vulnerabilities. +##It also includes bug fixes and new features including: + +- Two High level security fixes, all users SHOULD update. + a) If using wolfSSL for DTLS on the server side of a publicly accessible + machine you MUST update. + b) If using wolfSSL for TLS on the server side with private RSA keys allowing + ephemeral key exchange without low memory optimziations you MUST update and + regenerate the private RSA keys. + + Please see https://www.wolfssl.com/wolfSSL/Blog/Blog.html for more details + +- No filesystem build fixes for various configurations +- Certificate generation now supports several extensions including KeyUsage, + SKID, AKID, and Ceritifcate Policies +- CRLs can be loaded from buffers as well as files now +- SHA-512 Ceritifcate Signing generation +- Fixes for sniffer reassembly processing + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + +#wolfSSL (Formerly CyaSSL) Release 3.6.6 (08/20/2015) + +##Release 3.6.6 of wolfSSL has bug fixes and new features including: + +- OpenSSH compatibility with --enable-openssh +- stunnel compatibility with --enable-stunnel +- lighttpd compatibility with --enable-lighty +- SSLv3 is now disabled by default, can be enabled with --enable-sslv3 +- Ephemeral key cipher suites only are now supported by default + To enable static ECDH cipher suites define WOLFSSL_STATIC_DH + To enable static RSA cipher suites define WOLFSSL_STATIC_RSA + To enable static PSK cipher suites define WOLFSSL_STATIC_PSK +- Added QSH (quantum-safe handshake) extension with --enable-ntru +- SRP is now part of wolfCrypt, enable with --enabe-srp +- Certificate handshake messages can now be sent fragmented if the record + size is smaller than the total message size, no user action required. +- DTLS duplicate message fixes +- Visual Studio project files now support DLL and static builds for 32/64bit. +- Support for new Freesacle I/O +- FreeRTOS FIPS support + +- No high level security fixes that requires an update though we always + recommend updating to the latest + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + + +#wolfSSL (Formerly CyaSSL) Release 3.6.0 (06/19/2015) + +##Release 3.6.0 of wolfSSL has bug fixes and new features including: + +- Max Strength build that only allows TLSv1.2, AEAD ciphers, and PFS (Perfect + Forward Secrecy). With --enable-maxstrength +- Server side session ticket support, the example server and echosever use the + example callback myTicketEncCb(), see wolfSSL_CTX_set_TicketEncCb() +- FIPS version submitted for iOS. +- TI Crypto Hardware Acceleration +- DTLS fragmentation fixes +- ECC key check validation with wc_ecc_check_key() +- 32bit code options to reduce memory for Curve25519 and Ed25519 +- wolfSSL JNI build switch with --enable-jni +- PicoTCP support improvements +- DH min ephemeral key size enforcement with wolfSSL_CTX_SetMinDhKey_Sz() +- KEEP_PEER_CERT and AltNames can now be used together +- ChaCha20 big endian fix +- SHA-512 signature algorithm support for key exchange and verify messages +- ECC make key crash fix on RNG failure, ECC users must update. +- Improvements to usage of time code. +- Improvements to VS solution files. +- GNU Binutils 2.24 ld has problems with some debug builds, to fix an ld error + add -fdebug-types-section to C_EXTRA_FLAGS + +- No high level security fixes that requires an update though we always + recommend updating to the latest (except note 14, ecc RNG failure) + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + + +#wolfSSL (Formerly CyaSSL) Release 3.4.8 (04/06/2015) + +##Release 3.4.8 of wolfSSL has bug fixes and new features including: + +- FIPS version submitted for iOS. +- Max Strength build that only allows TLSv1.2, AEAD ciphers, and PFS. +- Improvements to usage of time code. +- Improvements to VS solution files. + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + + +#wolfSSL (Formerly CyaSSL) Release 3.4.6 (03/30/2015) + +##Release 3.4.6 of wolfSSL has bug fixes and new features including: + +- Intel Assembly Speedups using instructions rdrand, rdseed, aesni, avx1/2, + rorx, mulx, adox, adcx . They can be enabled with --enable-intelasm. + These speedup the use of RNG, SHA2, and public key algorithms. +- Ed25519 support at the crypto level. Turn on with --enable-ed25519. Examples + in wolcrypt/test/test.c ed25519_test(). +- Post Handshake Memory reductions. wolfSSL can now hold less than 1,000 bytes + of memory per secure connection including cipher state. +- wolfSSL API and wolfCrypt API fixes, you can still include the cyassl and + ctaocrypt headers which will enable the compatibility APIs for the + foreseeable future +- INSTALL file to help direct users to build instructions for their environment +- For ECC users with the normal math library a fix that prevents a crash when + verify signature fails. Users of 3.4.0 with ECC and the normal math library + must update +- RC4 is now disabled by default in autoconf mode +- AES-GCM and ChaCha20/Poly1305 are now enabled by default to make AEAD ciphers + available without a switch +- External ChaCha-Poly AEAD API, thanks to Andrew Burks for the contribution +- DHE-PSK cipher suites can now be built without ASN or Cert support +- Fix some NO MD5 build issues with optional features +- Freescale CodeWarrior project updates +- ECC curves can be individually turned on/off at build time. +- Sniffer handles Cert Status message and other minor fixes +- SetMinVersion() at the wolfSSL Context level instead of just SSL session level + to allow minimum protocol version allowed at runtime +- RNG failure resource cleanup fix + +- No high level security fixes that requires an update though we always + recommend updating to the latest (except note 6 use case of ecc/normal math) + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + + +#wolfSSL (Formerly CyaSSL) Release 3.4.0 (02/23/2015) + +## Release 3.4.0 wolfSSL has bug fixes and new features including: + +- wolfSSL API and wolfCrypt API, you can still include the cyassl and ctaocrypt + headers which will enable the compatibility APIs for the foreseeable future +- Example use of the wolfCrypt API can be found in wolfcrypt/test/test.c +- Example use of the wolfSSL API can be found in examples/client/client.c +- Curve25519 now supported at the wolfCrypt level, wolfSSL layer coming soon +- Improvements in the build configuration under AIX +- Microchip Pic32 MZ updates +- TIRTOS updates +- PowerPC updates +- Xcode project update +- Bidirectional shutdown examples in client/server with -w (wait for full + shutdown) option +- Cycle counts on benchmarks for x86_64, more coming soon +- ALT_ECC_SIZE for reducing ecc heap use with fastmath when also using large RSA + keys +- Various compile warnings +- Scan-build warning fixes +- Changed a memcpy to memmove in the sniffer (if using sniffer please update) +- No high level security fixes that requires an update though we always + recommend updating to the latest + + +# CyaSSL Release 3.3.0 (12/05/2014) + +- Countermeasuers for Handshake message duplicates, CHANGE CIPHER without + FINISHED, and fast forward attempts. Thanks to Karthikeyan Bhargavan from + the Prosecco team at INRIA Paris-Rocquencourt for the report. +- FIPS version submitted +- Removes SSLv2 Client Hello processing, can be enabled with OLD_HELLO_ALLOWED +- User can set minimum downgrade version with CyaSSL_SetMinVersion() +- Small stack improvements at TLS/SSL layer +- TLS Master Secret generation and Key Expansion are now exposed +- Adds client side Secure Renegotiation, * not recommended * +- Client side session ticket support, not fully tested with Secure Renegotiation +- Allows up to 4096bit DHE at TLS Key Exchange layer +- Handles non standard SessionID sizes in Hello Messages +- PicoTCP Support +- Sniffer now supports SNI Virtual Hosts +- Sniffer now handles non HTTPS protocols using STARTTLS +- Sniffer can now parse records with multiple messages +- TI-RTOS updates +- Fix for ColdFire optimized fp_digit read only in explicit 32bit case +- ADH Cipher Suite ADH-AES128-SHA for EAP-FAST + +The CyaSSL manual is available at: +http://www.wolfssl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 3.2.0 (09/10/2014) + +#### Release 3.2.0 CyaSSL has bug fixes and new features including: + +- ChaCha20 and Poly1305 crypto and suites +- Small stack improvements for OCSP, CRL, TLS, DTLS +- NTRU Encrypt and Decrypt benchmarks +- Updated Visual Studio project files +- Updated Keil MDK5 project files +- Fix for DTLS sequence numbers with GCM/CCM +- Updated HashDRBG with more secure struct declaration +- TI-RTOS support and example Code Composer Studio project files +- Ability to get enabled cipher suites, CyaSSL_get_ciphers() +- AES-GCM/CCM/Direct support for Freescale mmCAU and CAU +- Sniffer improvement checking for decrypt key setup +- Support for raw ECC key import +- Ability to convert ecc_key to DER, EccKeyToDer() +- Security fix for RSA Padding check vulnerability reported by Intel Security + Advanced Threat Research team + +The CyaSSL manual is available at: +http://www.wolfssl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 3.1.0 (07/14/2014) + +#### Release 3.1.0 CyaSSL has bug fixes and new features including: + +- Fix for older versions of icc without 128-bit type +- Intel ASM syntax for AES-NI +- Updated NTRU support, keygen benchmark +- FIPS check for minimum required HMAC key length +- Small stack (--enable-smallstack) improvements for PKCS#7, ASN +- TLS extension support for DTLS +- Default I/O callbacks external to user +- Updated example client with bad clock test +- Ability to set optional ECC context info +- Ability to enable/disable DH separate from opensslextra +- Additional test key/cert buffers for CA and server +- Updated example certificates + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 3.0.2 (05/30/2014) + +#### Release 3.0.2 CyaSSL has bug fixes and new features including: + +- Added the following cipher suites: + * TLS_PSK_WITH_AES_128_GCM_SHA256 + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA384 + * TLS_PSK_WITH_NULL_SHA384 + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_NULL_SHA256 + * TLS_DHE_PSK_WITH_NULL_SHA384 + * TLS_DHE_PSK_WITH_AES_128_CCM + * TLS_DHE_PSK_WITH_AES_256_CCM +- Added AES-NI support for Microsoft Visual Studio builds. +- Changed small stack build to be disabled by default. +- Updated the Hash DRBG and provided a configure option to enable. + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 3.0.0 (04/29/2014) + +#### Release 3.0.0 CyaSSL has bug fixes and new features including: + +- FIPS release candidate +- X.509 improvements that address items reported by Suman Jana with security + researchers at UT Austin and UC Davis +- Small stack size improvements, --enable-smallstack. Offloads large local + variables to the heap. (Note this is not complete.) +- Updated AES-CCM-8 cipher suites to use approved suite numbers. + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 2.9.4 (04/09/2014) + +#### Release 2.9.4 CyaSSL has bug fixes and new features including: + +- Security fixes that address items reported by Ivan Fratric of the Google + Security Team +- X.509 Unknown critical extensions treated as errors, report by Suman Jana with + security researchers at UT Austin and UC Davis +- Sniffer fixes for corrupted packet length and Jumbo frames +- ARM thumb mode assembly fixes +- Xcode 5.1 support including new clang +- PIC32 MZ hardware support +- CyaSSL Object has enough room to read the Record Header now w/o allocs +- FIPS wrappers for AES, 3DES, SHA1, SHA256, SHA384, HMAC, and RSA. +- A sample I/O pool is demonstrated with --enable-iopool to overtake memory + handling and reduce memory fragmentation on I/O large sizes + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 2.9.0 (02/07/2014) + +#### Release 2.9.0 CyaSSL has bug fixes and new features including: +- Freescale Kinetis RNGB support +- Freescale Kinetis mmCAU support +- TLS Hello extensions + - ECC + - Secure Renegotiation (null) + - Truncated HMAC +- SCEP support + - PKCS #7 Enveloped data and signed data + - PKCS #10 Certificate Signing Request generation +- DTLS sliding window +- OCSP Improvements + - API change to integrate into Certificate Manager + - IPv4/IPv6 agnostic + - example client/server support for OCSP + - OCSP nonces are optional +- GMAC hashing +- Windows build additions +- Windows CYGWIN build fixes +- Updated test certificates +- Microchip MPLAB Harmony support +- Update autoconf scripts +- Additional X.509 inspection functions +- ECC encrypt/decrypt primitives +- ECC Certificate generation + +The Freescale Kinetis K53 RNGB documentation can be found in Chapter 33 of the +K53 Sub-Family Reference Manual: +http://cache.freescale.com/files/32bit/doc/ref_manual/K53P144M100SF2RM.pdf + +Freescale Kinetis K60 mmCAU (AES, DES, 3DES, MD5, SHA, SHA256) documentation +can be found in the "ColdFire/ColdFire+ CAU and Kinetis mmCAU Software Library +User Guide": +http://cache.freescale.com/files/32bit/doc/user_guide/CAUAPIUG.pdf + + +# CyaSSL Release 2.8.0 (8/30/2013) + +#### Release 2.8.0 CyaSSL has bug fixes and new features including: +- AES-GCM and AES-CCM use AES-NI +- NetX default IO callback handlers +- IPv6 fixes for DTLS Hello Cookies +- The ability to unload Certs/Keys after the handshake, CyaSSL_UnloadCertsKeys() +- SEP certificate extensions +- Callback getters for easier resource freeing +- External CYASSL_MAX_ERROR_SZ for correct error buffer sizing +- MacEncrypt and DecryptVerify Callbacks for User Atomic Record Layer Processing +- Public Key Callbacks for ECC and RSA +- Client now sends blank cert upon request if doesn't have one with TLS <= 1.2 + + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 2.7.0 (6/17/2013) + +#### Release 2.7.0 CyaSSL has bug fixes and new features including: +- SNI support for client and server +- KEIL MDK-ARM projects +- Wildcard check to domain name match, and Subject altnames are checked too +- Better error messages for certificate verification errors +- Ability to discard session during handshake verify +- More consistent error returns across all APIs +- Ability to unload CAs at the CTX or CertManager level +- Authority subject id support for Certificate matching +- Persistent session cache functionality +- Persistent CA cache functionality +- Client session table lookups to push serverID table to library level +- Camellia support to sniffer +- User controllable settings for DTLS timeout values +- Sniffer fixes for caching long lived sessions +- DTLS reliability enhancements for the handshake +- Better ThreadX support + +When compiling with Mingw, libtool may give the following warning due to +path conversion errors: + +``` +libtool: link: Could not determine host file name corresponding to ** +libtool: link: Continuing, but uninstalled executables may not work. +``` + +If so, examples and testsuite will have problems when run, showing an +error while loading shared libraries. To resolve, please run "make install". + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 2.6.0 (04/15/2013) + +#### Release 2.6.0 CyaSSL has bug fixes and new features including: +- DTLS 1.2 support including AEAD ciphers +- SHA-3 finalist Blake2 support, it's fast and uses little resources +- SHA-384 cipher suites including ECC ones +- HMAC now supports SHA-512 +- Track memory use for example client/server with -t option +- Better IPv6 examples with --enable-ipv6, before if ipv6 examples/tests were + turned on, localhost only was used. Now link-local (with scope ids) and ipv6 + hosts can be used as well. +- Xcode v4.6 project for iOS v6.1 update +- settings.h is now checked in all *.c files for true one file setting detection +- Better alignment at SSL layer for hardware crypto alignment needs + * Note, SSL itself isn't friendly to alignment with 5 byte TLS headers and + 13 bytes DTLS headers, but every effort is now made to align with the + CYASSL_GENERAL_ALIGNMENT flag which sets desired alignment requirement +- NO_64BIT flag to turn off 64bit data type accumulators in public key code + * Note, some systems are faster with 32bit accumulators +- --enable-stacksize for example client/server stack use + * Note, modern desktop Operating Systems may add bytes to each stack frame +- Updated compression/decompression with direct crypto access +- All ./configure options are now lowercase only for consistency +- ./configure builds default to fastmath option + * Note, if on ia32 and building in shared mode this may produce a problem + with a missing register being available because of PIC, there are at least + 6 solutions to this: + 1) --disable-fastmath , don't use fastmath + 2) --disable-shared, don't build a shared library + 3) C_EXTRA_FLAGS=-DTFM_NO_ASM , turn off assembly use + 4) use clang, it just seems to work + 5) play around with no PIC options to force all registers being open, + e.g., --without-pic + 6) if static lib is still a problem try removing fPIE +- Many new ./configure switches for option enable/disable for example + * rsa + * dh + * dsa + * md5 + * sha + * arc4 + * null (allow NULL ciphers) + * oldtls (only use TLS 1.2) + * asn (no certs or public keys allowed) +- ./configure generates cyassl/options.h which allows a header the user can + include in their app to make sure the same options are set at the app and + CyaSSL level. +- autoconf no longer needs serial-tests which lowers version requirements of + automake to 1.11 and autoconf to 2.63 + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.5.0 (02/04/2013) + +#### Release 2.5.0 CyaSSL has bug fixes and new features including: +- Fix for TLS CBC padding timing attack identified by Nadhem Alfardan and + Kenny Paterson: http://www.isg.rhul.ac.uk/tls/ +- Microchip PIC32 (MIPS16, MIPS32) support +- Microchip MPLAB X example projects for PIC32 Ethernet Starter Kit +- Updated CTaoCrypt benchmark app for embedded systems +- 1024-bit test certs/keys and cert/key buffers +- AES-CCM-8 crypto and cipher suites +- Camellia crypto and cipher suites +- Bumped minimum autoconf version to 2.65, automake version to 1.12 +- Addition of OCSP callbacks +- STM32F2 support with hardware crypto and RNG +- Cavium NITROX support + +CTaoCrypt now has support for the Microchip PIC32 and has been tested with +the Microchip PIC32 Ethernet Starter Kit, the XC32 compiler and +MPLAB X IDE in both MIPS16 and MIPS32 instruction set modes. See the README +located under the /mplabx directory for more details. + +To add Cavium NITROX support do: + +./configure --with-cavium=/home/user/cavium/software + +pointing to your licensed cavium/software directory. Since Cavium doesn't +build a library we pull in the cavium_common.o file which gives a libtool +warning about the portability of this. Also, if you're using the github source +tree you'll need to remove the -Wredundant-decls warning from the generated +Makefile because the cavium headers don't conform to this warning. Currently +CyaSSL supports Cavium RNG, AES, 3DES, RC4, HMAC, and RSA directly at the crypto +layer. Support at the SSL level is partial and currently just does AES, 3DES, +and RC4. RSA and HMAC are slower until the Cavium calls can be utilized in non +blocking mode. The example client turns on cavium support as does the crypto +test and benchmark. Please see the HAVE_CAVIUM define. + +CyaSSL is able to use the STM32F2 hardware-based cryptography and random number +generator through the STM32F2 Standard Peripheral Library. For necessary +defines, see the CYASSL_STM32F2 define in settings.h. Documentation for the +STM32F2 Standard Peripheral Library can be found in the following document: +http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/USER_MANUAL/DM00023896.pdf + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.4.6 (12/20/2012) + +#### Release 2.4.6 CyaSSL has bug fixes and a few new features including: +- ECC into main version +- Lean PSK build (reduced code size, RAM usage, and stack usage) +- FreeBSD CRL monitor support +- CyaSSL_peek() +- CyaSSL_send() and CyaSSL_recv() for I/O flag setting +- CodeWarrior Support +- MQX Support +- Freescale Kinetis support including Hardware RNG +- autoconf builds use jobserver +- cyassl-config +- Sniffer memory reductions + +Thanks to Brian Aker for the improved autoconf system, make rpm, cyassl-config, +warning system, and general good ideas for improving CyaSSL! + +The Freescale Kinetis K70 RNGA documentation can be found in Chapter 37 of the +K70 Sub-Family Reference Manual: +http://cache.freescale.com/files/microcontrollers/doc/ref_manual/K70P256M150SF3RM.pdf + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 2.4.0 (10/10/2012) + +#### Release 2.4.0 CyaSSL has bug fixes and a few new features including: +- DTLS reliability +- Reduced memory usage after handshake +- Updated build process + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.3.0 (8/10/2012) + +#### Release 2.3.0 CyaSSL has bug fixes and a few new features including: +- AES-GCM crypto and cipher suites +- make test cipher suite checks +- Subject AltName processing +- Command line support for client/server examples +- Sniffer SessionTicket support +- SHA-384 cipher suites +- Verify cipher suite validity when user overrides +- CRL dir monitoring +- DTLS Cookie support, reliability coming soon + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.2.0 (5/18/2012) + +#### Release 2.2.0 CyaSSL has bug fixes and a few new features including: +- Initial CRL support (--enable-crl) +- Initial OCSP support (--enable-ocsp) +- Add static ECDH suites +- SHA-384 support +- ECC client certificate support +- Add medium session cache size (1055 sessions) +- Updated unit tests +- Protection against mutex reinitialization + + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.0.8 (2/24/2012) + +#### Release 2.0.8 CyaSSL has bug fixes and a few new features including: +- A fix for malicious certificates pointed out by Remi Gacogne (thanks) + resulting in NULL pointer use. +- Respond to renegotiation attempt with no_renegoatation alert +- Add basic path support for load_verify_locations() +- Add set Temp EC-DHE key size +- Extra checks on rsa test when porting into + + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.0.6 (1/27/2012) + +#### Release 2.0.6 CyaSSL has bug fixes and a few new features including: +- Fixes for CA basis constraint check +- CTX reference counting +- Initial unit test additions +- Lean and Mean Windows fix +- ECC benchmarking +- SSMTP build support +- Ability to group handshake messages with set_group_messages(ctx/ssl) +- CA cache addition callback +- Export Base64_Encode for general use + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.0.2 (12/05/2011) + +#### Release 2.0.2 CyaSSL has bug fixes and a few new features including: +- CTaoCrypt Runtime library detection settings when directly using the crypto + library +- Default certificate generation now uses SHAwRSA and adds SHA256wRSA generation +- All test certificates now use 2048bit and SHA-1 for better modern browser + support +- Direct AES block access and AES-CTR (counter) mode +- Microchip pic32 support + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.0.0rc3 (9/28/2011) + +#### Release 2.0.0rc3 for CyaSSL has bug fixes and a few new features including: +- updated autoconf support +- better make install and uninstall (uses system directories) +- make test / make check +- CyaSSL headers now in +- CTaocrypt headers now in +- OpenSSL compatibility headers now in +- examples and tests all run from home directory so can use certs in ./certs + (see note 1) + +So previous applications that used the OpenSSL compatibility header + now need to include instead, no other +changes are required. + +Special Thanks to Brian Aker for his autoconf, install, and header patches. + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + +# CyaSSL Release 2.0.0rc2 (6/6/2011) + +#### Release 2.0.0rc2 for CyaSSL has bug fixes and a few new features including: +- bug fixes (Alerts, DTLS with DHE) +- FreeRTOS support +- lwIP support +- Wshadow warnings removed +- asn public header +- CTaoCrypt public headers now all have ctc_ prefix (the manual is still being + updated to reflect this change) +- and more. + +This is the 2nd and perhaps final release candidate for version 2. +Please send any comments or questions to support@yassl.com. + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + +# CyaSSL Release 2.0.0rc1 (5/2/2011) + +#### Release 2.0.0rc1 for CyaSSL has many new features including: +- bug fixes +- SHA-256 cipher suites +- Root Certificate Verification (instead of needing all certs in the chain) +- PKCS #8 private key encryption (supports PKCS #5 v1-v2 and PKCS #12) +- Serial number retrieval for x509 +- PBKDF2 and PKCS #12 PBKDF +- UID parsing for x509 +- SHA-256 certificate signatures +- Client and server can send chains (SSL_CTX_use_certificate_chain_file) +- CA loading can now parse multiple certificates per file +- Dynamic memory runtime hooks +- Runtime hooks for logging +- EDH on server side +- More informative error codes +- More informative logging messages +- Version downgrade more robust (use SSL_v23*) +- Shared build only by default through ./configure +- Compiler visibility is now used, internal functions not polluting namespace +- Single Makefile, no recursion, for faster and simpler building +- Turn on all warnings possible build option, warning fixes +- and more. + +Because of all the new features and the multiple OS, compiler, feature-set +options that CyaSSL allows, there may be some configuration fixes needed. +Please send any comments or questions to support@yassl.com. + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + +# CyaSSL Release 1.9.0 (3/2/2011) + +Release 1.9.0 for CyaSSL adds bug fixes, improved TLSv1.2 through testing and +better hash/sig algo ids, --enable-webServer for the yaSSL embedded web server, +improper AES key setup detection, user cert verify callback improvements, and +more. + +The CyaSSL manual offering is included in the doc/ directory. For build +instructions and comments about the new features please check the manual. + +Please send any comments or questions to support@yassl.com. + +# CyaSSL Release 1.8.0 (12/23/2010) + +Release 1.8.0 for CyaSSL adds bug fixes, x509 v3 CA signed certificate +generation, a C standard library abstraction layer, lower memory use, increased +portability through the os_settings.h file, and the ability to use NTRU cipher +suites when used in conjunction with an NTRU license and library. + +The initial CyaSSL manual offering is included in the doc/ directory. For +build instructions and comments about the new features please check the manual. + +Please send any comments or questions to support@yassl.com. + +Happy Holidays. + + +# CyaSSL Release 1.6.5 (9/9/2010) + +Release 1.6.5 for CyaSSL adds bug fixes and x509 v3 self signed certificate +generation. + +For general build instructions see doc/Building_CyaSSL.pdf. + +To enable certificate generation support add this option to ./configure +./configure --enable-certgen + +An example is included in ctaocrypt/test/test.c and documentation is provided +in doc/CyaSSL_Extensions_Reference.pdf item 11. + +# CyaSSL Release 1.6.0 (8/27/2010) + +Release 1.6.0 for CyaSSL adds bug fixes, RIPEMD-160, SHA-512, and RSA key +generation. + +For general build instructions see doc/Building_CyaSSL.pdf. + +To add RIPEMD-160 support add this option to ./configure +./configure --enable-ripemd + +To add SHA-512 support add this option to ./configure +./configure --enable-sha512 + +To add RSA key generation support add this option to ./configure +./configure --enable-keygen + +Please see ctaocrypt/test/test.c for examples and usage. + +For Windows, RIPEMD-160 and SHA-512 are enabled by default but key generation is +off by default. To turn key generation on add the define CYASSL_KEY_GEN to +CyaSSL. + + +# CyaSSL Release 1.5.6 (7/28/2010) + +Release 1.5.6 for CyaSSL adds bug fixes, compatibility for our JSSE provider, +and a fix for GCC builds on some systems. + +For general build instructions see doc/Building_CyaSSL.pdf. + +To add AES-NI support add this option to ./configure +./configure --enable-aesni + +You'll need GCC 4.4.3 or later to make use of the assembly. + +# CyaSSL Release 1.5.4 (7/7/2010) + +Release 1.5.4 for CyaSSL adds bug fixes, support for AES-NI, SHA1 speed +improvements from loop unrolling, and support for the Mongoose Web Server. + +For general build instructions see doc/Building_CyaSSL.pdf. + +To add AES-NI support add this option to ./configure +./configure --enable-aesni + +You'll need GCC 4.4.3 or later to make use of the assembly. + +# CyaSSL Release 1.5.0 (5/11/2010) + +Release 1.5.0 for CyaSSL adds bug fixes, GoAhead WebServer support, sniffer +support, and initial swig interface support. + +For general build instructions see doc/Building_CyaSSL.pdf. + +To add support for GoAhead WebServer either --enable-opensslExtra or if you +don't want all the features of opensslExtra you can just define GOAHEAD_WS +instead. GOAHEAD_WS can be added to ./configure with CFLAGS=-DGOAHEAD_WS or +you can define it yourself. + +To look at the sniffer support please see the sniffertest app in +sslSniffer/sslSnifferTest. Build with --enable-sniffer on *nix or use the +vcproj files on windows. You'll need to have pcap installed on *nix and +WinPcap on windows. + +A swig interface file is now located in the swig directory for using Python, +Java, Perl, and others with CyaSSL. This is initial support and experimental, +please send questions or comments to support@yassl.com. + +When doing load testing with CyaSSL, on the echoserver example say, the client +machine may run out of tcp ephemeral ports, they will end up in the TIME_WAIT +queue, and can't be reused by default. There are generally two ways to fix +this. + +1. Reduce the length sockets remain on the TIME_WAIT queue OR +2. Allow items on the TIME_WAIT queue to be reused. + + +To reduce the TIME_WAIT length in OS X to 3 seconds (3000 milliseconds) + +`sudo sysctl -w net.inet.tcp.msl=3000` + +In Linux + +`sudo sysctl -w net.ipv4.tcp_tw_reuse=1` + +allows reuse of sockets in TIME_WAIT + +`sudo sysctl -w net.ipv4.tcp_tw_recycle=1` + +works but seems to remove sockets from TIME_WAIT entirely? + +`sudo sysctl -w net.ipv4.tcp_fin_timeout=1` + +doesn't control TIME_WAIT, it controls FIN_WAIT(2) contrary to some posts + + +# CyaSSL Release 1.4.0 (2/18/2010) + +Release 1.3.0 for CyaSSL adds bug fixes, better multi TLS/SSL version support +through SSLv23_server_method(), and improved documentation in the doc/ folder. + +For general build instructions doc/Building_CyaSSL.pdf. + +# CyaSSL Release 1.3.0 (1/21/2010) + +Release 1.3.0 for CyaSSL adds bug fixes, a potential security problem fix, +better porting support, removal of assert()s, and a complete THREADX port. + +For general build instructions see rc1 below. + +# CyaSSL Release 1.2.0 (11/2/2009) + +Release 1.2.0 for CyaSSL adds bug fixes and session negotiation if first use is +read or write. + +For general build instructions see rc1 below. + +# CyaSSL Release 1.1.0 (9/2/2009) + +Release 1.1.0 for CyaSSL adds bug fixes, a check against malicious session +cache use, support for lighttpd, and TLS 1.2. + +To get TLS 1.2 support please use the client and server functions: + +```c +SSL_METHOD *TLSv1_2_server_method(void); +SSL_METHOD *TLSv1_2_client_method(void); +``` + +CyaSSL was tested against lighttpd 1.4.23. To build CyaSSL for use with +lighttpd use the following commands from the CyaSSL install dir : + +``` +./configure --disable-shared --enable-opensslExtra --enable-fastmath --without-zlib + +make +make openssl-links +``` + +Then to build lighttpd with CyaSSL use the following commands from the +lighttpd install dir: + +``` +./configure --with-openssl --with-openssl-includes=/include --with-openssl-libs=/lib LDFLAGS=-lm + +make +``` + +On some systems you may get a linker error about a duplicate symbol for +MD5_Init or other MD5 calls. This seems to be caused by the lighttpd src file +md5.c, which defines MD5_Init(), and is included in liblightcomp_la-md5.o. +When liblightcomp is linked with the SSL_LIBs the linker may complain about +the duplicate symbol. This can be fixed by editing the lighttpd src file md5.c +and adding this line to the beginning of the file: + +\#if 0 + +and this line to the end of the file + +\#endif + +Then from the lighttpd src dir do a: + +``` +make clean +make +``` + +If you get link errors about undefined symbols more than likely the actual +OpenSSL libraries are found by the linker before the CyaSSL openssl-links that +point to the CyaSSL library, causing the linker confusion. This can be fixed +by editing the Makefile in the lighttpd src directory and changing the line: + +`SSL_LIB = -lssl -lcrypto` + +to + +`SSL_LIB = -lcyassl` + +Then from the lighttpd src dir do a: + +``` +make clean +make +``` + +This should remove any confusion the linker may be having with missing symbols. + +For any questions or concerns please contact support@yassl.com . + +For general build instructions see rc1 below. + +# CyaSSL Release 1.0.6 (8/03/2009) + +Release 1.0.6 for CyaSSL adds bug fixes, an improved session cache, and faster +math with a huge code option. + +The session cache now defaults to a client mode, also good for embedded servers. +For servers not under heavy load (less than 200 new sessions per minute), define +BIG_SESSION_CACHE. If the server will be under heavy load, define +HUGE_SESSION_CACHE. + +There is now a fasthugemath option for configure. This enables fastmath plus +even faster math by greatly increasing the code size of the math library. Use +the benchmark utility to compare public key operations. + + +For general build instructions see rc1 below. + +# CyaSSL Release 1.0.3 (5/10/2009) + +Release 1.0.3 for CyaSSL adds bug fixes and add increased support for OpenSSL +compatibility when building other applications. + +Release 1.0.3 includes an alpha release of DTLS for both client and servers. +This is only for testing purposes at this time. Rebroadcast and reordering +aren't fully implemented at this time but will be for the next release. + +For general build instructions see rc1 below. + +# CyaSSL Release 1.0.2 (4/3/2009) + +Release 1.0.2 for CyaSSL adds bug fixes for a couple I/O issues. Some systems +will send a SIGPIPE on socket recv() at any time and this should be handled by +the application by turning off SIGPIPE through setsockopt() or returning from +the handler. + +Release 1.0.2 includes an alpha release of DTLS for both client and servers. +This is only for testing purposes at this time. Rebroadcast and reordering +aren't fully implemented at this time but will be for the next release. + +For general build instructions see rc1 below. + +## CyaSSL Release Candidate 3 rc3-1.0.0 (2/25/2009) + + +Release Candidate 3 for CyaSSL 1.0.0 adds bug fixes and adds a project file for +iPhone development with Xcode. cyassl-iphone.xcodeproj is located in the root +directory. This release also includes a fix for supporting other +implementations that bundle multiple messages at the record layer, this was +lost when cyassl i/o was re-implemented but is now fixed. + +For general build instructions see rc1 below. + +## CyaSSL Release Candidate 2 rc2-1.0.0 (1/21/2009) + + +Release Candidate 2 for CyaSSL 1.0.0 adds bug fixes and adds two new stream +ciphers along with their respective cipher suites. CyaSSL adds support for +HC-128 and RABBIT stream ciphers. The new suites are: + +``` +TLS_RSA_WITH_HC_128_SHA +TLS_RSA_WITH_RABBIT_SHA +``` + +And the corresponding cipher names are + +``` +HC128-SHA +RABBIT-SHA +``` + +CyaSSL also adds support for building with devkitPro for PPC by changing the +library proper to use libogc. The examples haven't been changed yet but if +there's interest they can be. Here's an example ./configure to build CyaSSL +for devkitPro: + +``` +./configure --disable-shared CC=/pathTo/devkitpro/devkitPPC/bin/powerpc-gekko-gcc --host=ppc --without-zlib --enable-singleThreaded RANLIB=/pathTo/devkitpro/devkitPPC/bin/powerpc-gekko-ranlib CFLAGS="-DDEVKITPRO -DGEKKO" +``` + +For linking purposes you'll need + +`LDFLAGS="-g -mrvl -mcpu=750 -meabi -mhard-float -Wl,-Map,$(notdir $@).map"` + +For general build instructions see rc1 below. + + +## CyaSSL Release Candidate 1 rc1-1.0.0 (12/17/2008) + + +Release Candidate 1 for CyaSSL 1.0.0 contains major internal changes. Several +areas have optimization improvements, less dynamic memory use, and the I/O +strategy has been refactored to allow alternate I/O handling or Library use. +Many thanks to Thierry Fournier for providing these ideas and most of the work. + +Because of these changes, this release is only a candidate since some problems +are probably inevitable on some platform with some I/O use. Please report any +problems and we'll try to resolve them as soon as possible. You can contact us +at support@yassl.com or todd@yassl.com. + +Using TomsFastMath by passing --enable-fastmath to ./configure now uses assembly +on some platforms. This is new so please report any problems as every compiler, +mode, OS combination hasn't been tested. On ia32 all of the registers need to +be available so be sure to pass these options to CFLAGS: + +`CFLAGS="-O3 -fomit-frame-pointer"` + +OS X will also need -mdynamic-no-pic added to CFLAGS + +Also if you're building in shared mode for ia32 you'll need to pass options to +LDFLAGS as well on OS X: + +`LDFLAGS=-Wl,-read_only_relocs,warning` + +This gives warnings for some symbols but seems to work. + + +#### To build on Linux, Solaris, *BSD, Mac OS X, or Cygwin: + + ./configure + make + + from the ./testsuite/ directory run ./testsuite + +#### To make a debug build: + + ./configure --enable-debug --disable-shared + make + + + +#### To build on Win32 + +Choose (Re)Build All from the project workspace + +Run the testsuite program + + + + + +# CyaSSL version 0.9.9 (7/25/2008) + +This release of CyaSSL adds bug fixes, Pre-Shared Keys, over-rideable memory +handling, and optionally TomsFastMath. Thanks to Moisés Guimarães for the +work on TomsFastMath. + +To optionally use TomsFastMath pass --enable-fastmath to ./configure +Or define USE_FAST_MATH in each project from CyaSSL for MSVC. + +Please use the benchmark routine before and after to see the performance +difference, on some platforms the gains will be little but RSA encryption +always seems to be faster. On x86-64 machines with GCC the normal math library +may outperform the fast one when using CFLAGS=-m64 because TomsFastMath can't +yet use -m64 because of GCCs inability to do 128bit division. + + *** UPDATE GCC 4.2.1 can now do 128bit division *** + +See notes below (0.2.0) for complete build instructions. + + +# CyaSSL version 0.9.8 (5/7/2008) + +This release of CyaSSL adds bug fixes, client side Diffie-Hellman, and better +socket handling. + +See notes below (0.2.0) for complete build instructions. + + +# CyaSSL version 0.9.6 (1/31/2008) + +This release of CyaSSL adds bug fixes, increased session management, and a fix +for gnutls. + +See notes below (0.2.0) for complete build instructions. + + +# CyaSSL version 0.9.0 (10/15/2007) + +This release of CyaSSL adds bug fixes, MSVC 2005 support, GCC 4.2 support, +IPV6 support and test, and new test certificates. + +See notes below (0.2.0) for complete build instructions. + + +# CyaSSL version 0.8.0 (1/10/2007) + +This release of CyaSSL adds increased socket support, for non-blocking writes, +connects, and interrupted system calls. + +See notes below (0.2.0) for complete build instructions. + + +# CyaSSL version 0.6.3 (10/30/2006) + +This release of CyaSSL adds debug logging to stderr to aid in the debugging of +CyaSSL on systems that may not provide the best support. + +If CyaSSL is built with debugging support then you need to call +CyaSSL_Debugging_ON() to turn logging on. + +On Unix use ./configure --enable-debug + +On Windows define DEBUG_CYASSL when building CyaSSL + + +To turn logging back off call CyaSSL_Debugging_OFF() + +See notes below (0.2.0) for complete build instructions. + + +# CyaSSL version 0.6.2 (10/29/2006) + +This release of CyaSSL adds TLS 1.1. + +Note that CyaSSL has certificate verification on by default, unlike OpenSSL. +To emulate OpenSSL behavior, you must call SSL_CTX_set_verify() with +SSL_VERIFY_NONE. In order to have full security you should never do this, +provide CyaSSL with the proper certificates to eliminate impostors and call +CyaSSL_check_domain_name() to prevent man in the middle attacks. + +See notes below (0.2.0) for build instructions. + +# CyaSSL version 0.6.0 (10/25/2006) + +This release of CyaSSL adds more SSL functions, better autoconf, nonblocking +I/O for accept, connect, and read. There is now an --enable-small configure +option that turns off TLS, AES, DES3, HMAC, and ERROR_STRINGS, see configure.in +for the defines. Note that TLS requires HMAC and AES requires TLS. + +See notes below (0.2.0) for build instructions. + + +# CyaSSL version 0.5.5 (09/27/2006) + +This mini release of CyaSSL adds better input processing through buffered input +and big message support. Added SSL_pending() and some sanity checks on user +settings. + +See notes below (0.2.0) for build instructions. + + +# CyaSSL version 0.5.0 (03/27/2006) + +This release of CyaSSL adds AES support and minor bug fixes. + +See notes below (0.2.0) for build instructions. + + +# CyaSSL version 0.4.0 (03/15/2006) + +This release of CyaSSL adds TLSv1 client/server support and libtool. + +See notes below for build instructions. + + +# CyaSSL version 0.3.0 (02/26/2006) + +This release of CyaSSL adds SSLv3 server support and session resumption. + +See notes below for build instructions. + + +# CyaSSL version 0.2.0 (02/19/2006) + + +This is the first release of CyaSSL and its crypt brother, CTaoCrypt. CyaSSL +is written in ANSI C with the idea of a small code size, footprint, and memory +usage in mind. CTaoCrypt can be as small as 32K, and the current client +version of CyaSSL can be as small as 12K. + + +The first release of CTaoCrypt supports MD5, SHA-1, 3DES, ARC4, Big Integer +Support, RSA, ASN parsing, and basic x509 (en/de)coding. + +The first release of CyaSSL supports normal client RSA mode SSLv3 connections +with support for SHA-1 and MD5 digests. Ciphers include 3DES and RC4. + + +#### To build on Linux, Solaris, *BSD, Mac OS X, or Cygwin: + + ./configure + make + + from the ./testsuite/ directory run ./testsuite + +#### to make a debug build: + + ./configure --enable-debug --disable-shared + make + + + +#### To build on Win32 + +Choose (Re)Build All from the project workspace + +Run the testsuite program + + + +*** The next release of CyaSSL will support a server and more OpenSSL +compatibility functions. + + +Please send questions or comments to todd@wolfssl.com diff --git a/FreeRTOS-Plus/Source/WolfSSL/INSTALL b/FreeRTOS-Plus/Source/WolfSSL/INSTALL index b9249c0e5..ad8cfdd74 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/INSTALL +++ b/FreeRTOS-Plus/Source/WolfSSL/INSTALL @@ -1,7 +1,7 @@ 0. Building on *nix from git repository - Run the autogen script to generate configure, you'll need the autoconf tools - installed, then proceed to step 1. + Run the autogen script to generate configure, then proceed to step 1. + Prerequisites: You'll need autoconf, automake and libtool installed. $ ./autogen.sh @@ -38,7 +38,37 @@ Please see the README in mqx -8. Porting to a new platform +8. Building with Rowley CrossWorks for ARM + + Use the CrossWorks project in IDE/ROWLEY-CROSSWORKS-ARM/wolfssl.hzp + There is a README.md in IDE/ROWLEY-CROSSWORKS-ARM with more information + +9. Building with Arduino + + Use the script IDE/ARDUINO/wolfssl-arduino.sh to reformat the wolfSSL + library for compatibility with the Arduino IDE. There is a README.md in + IDE/ARDUINO for detailed instructions. + +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. Building for Yocto Project or OpenEmbedded + + Please see the README in the "meta-wolfssl" repository. This repository + holds wolfSSL's Yocto and OpenEmbedded layer, which contains recipes + for wolfSSL, wolfSSH, wolfMQTT, wolfTPM, wolfCrypt examples, and OSS + project bbappend files. + + https://github.com/wolfssl/meta-wolfssl + + The wolfSSL recipe can also be found in the OpenEmbedded + "meta-openembedded/meta-networking/recipes-connectivity" layer: + + https://github.com/openembedded/meta-openembedded + +12. 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/FreeRTOS-Plus/Source/WolfSSL/ChangeLog b/FreeRTOS-Plus/Source/WolfSSL/IPP/.gitkeep similarity index 100% rename from FreeRTOS-Plus/Source/WolfSSL/ChangeLog rename to FreeRTOS-Plus/Source/WolfSSL/IPP/.gitkeep diff --git a/FreeRTOS-Plus/Source/WolfSSL/LICENSING b/FreeRTOS-Plus/Source/WolfSSL/LICENSING index e43bb9f39..9f50165fd 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/LICENSING +++ b/FreeRTOS-Plus/Source/WolfSSL/LICENSING @@ -1,7 +1,7 @@ -CyaSSL and wolfCrypt are either licensed for use under the GPLv2 or a -standard commercial license. For our users who cannot use CyaSSL under -GPLv2, a commercial license to CyaSSL and wolfCrypt is available. +wolfSSL (formerly known as CyaSSL) and wolfCrypt are either licensed for use +under the GPLv2 or a standard commercial license. For our users who cannot use +wolfSSL under GPLv2, a commercial license to wolfSSL and wolfCrypt is available. Please contact wolfSSL Inc. directly at: Email: licensing@wolfssl.com diff --git a/FreeRTOS-Plus/Source/WolfSSL/LPCExpresso.cproject b/FreeRTOS-Plus/Source/WolfSSL/LPCExpresso.cproject new file mode 100644 index 000000000..1db9a198e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/LPCExpresso.cproject @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <?xml version="1.0" encoding="UTF-8"?> +<TargetConfig> +<Properties property_0="" property_2="LPC18x7_43x7_2x512_BootA.cfx" property_3="NXP" property_4="LPC18S37" property_count="5" version="70200"/> +<infoList vendor="NXP"><info chip="LPC18S37" flash_driver="LPC18x7_43x7_2x512_BootA.cfx" match_id="0x0" name="LPC18S37" resetscript="LPC18LPC43InternalFLASHBootResetscript.scp" stub="crt_emu_lpc18_43_nxp"><chip><name>LPC18S37</name> +<family>LPC18xx</family> +<vendor>NXP (formerly Philips)</vendor> +<reset board="None" core="Real" sys="Real"/> +<clock changeable="TRUE" freq="20MHz" is_accurate="TRUE"/> +<memory can_program="true" id="Flash" is_ro="true" type="Flash"/> +<memory id="RAM" type="RAM"/> +<memory id="Periph" is_volatile="true" type="Peripheral"/> +<memoryInstance derived_from="Flash" id="MFlashA512" location="0x1a000000" size="0x80000"/> +<memoryInstance derived_from="Flash" id="MFlashB512" location="0x1b000000" size="0x80000"/> +<memoryInstance derived_from="RAM" id="RamLoc32" location="0x10000000" size="0x8000"/> +<memoryInstance derived_from="RAM" id="RamLoc40" location="0x10080000" size="0xa000"/> +<memoryInstance derived_from="RAM" id="RamAHB32" location="0x20000000" size="0x8000"/> +<memoryInstance derived_from="RAM" id="RamAHB16" location="0x20008000" size="0x4000"/> +<memoryInstance derived_from="RAM" id="RamAHB_ETB16" location="0x2000c000" size="0x4000"/> +<prog_flash blocksz="0x2000" location="0x1a000000" maxprgbuff="0x400" progwithcode="TRUE" size="0x10000"/> +<prog_flash blocksz="0x10000" location="0x1a010000" maxprgbuff="0x400" progwithcode="TRUE" size="0x70000"/> +<prog_flash blocksz="0x2000" location="0x1b000000" maxprgbuff="0x400" progwithcode="TRUE" size="0x10000"/> +<prog_flash blocksz="0x10000" location="0x1b010000" maxprgbuff="0x400" progwithcode="TRUE" size="0x70000"/> +<peripheralInstance derived_from="V7M_MPU" id="MPU" location="0xe000ed90"/> +<peripheralInstance derived_from="V7M_NVIC" id="NVIC" location="0xe000e000"/> +<peripheralInstance derived_from="V7M_DCR" id="DCR" location="0xe000edf0"/> +<peripheralInstance derived_from="V7M_ITM" id="ITM" location="0xe0000000"/> +<peripheralInstance derived_from="SCT" id="SCT" location="0x40000000"/> +<peripheralInstance derived_from="GPDMA" id="GPDMA" location="0x40002000"/> +<peripheralInstance derived_from="SPIFI" id="SPIFI" location="0x40003000"/> +<peripheralInstance derived_from="SDMMC" id="SDMMC" location="0x40004000"/> +<peripheralInstance derived_from="EMC" id="EMC" location="0x40005000"/> +<peripheralInstance derived_from="USB0" id="USB0" location="0x40006000"/> +<peripheralInstance derived_from="USB1" id="USB1" location="0x40007000"/> +<peripheralInstance derived_from="EEPROM" id="EEPROM" location="0x4000e000"/> +<peripheralInstance derived_from="ETHERNET" id="ETHERNET" location="0x40010000"/> +<peripheralInstance derived_from="ATIMER" id="ATIMER" location="0x40040000"/> +<peripheralInstance derived_from="REGFILE" id="REGFILE" location="0x40041000"/> +<peripheralInstance derived_from="PMC" id="PMC" location="0x40042000"/> +<peripheralInstance derived_from="CREG" id="CREG" location="0x40043000"/> +<peripheralInstance derived_from="EVENTROUTER" id="EVENTROUTER" location="0x40044000"/> +<peripheralInstance derived_from="RTC" id="RTC" location="0x40046000"/> +<peripheralInstance derived_from="CGU" id="CGU" location="0x40050000"/> +<peripheralInstance derived_from="CCU1" id="CCU1" location="0x40051000"/> +<peripheralInstance derived_from="CCU2" id="CCU2" location="0x40052000"/> +<peripheralInstance derived_from="RGU" id="RGU" location="0x40053000"/> +<peripheralInstance derived_from="WWDT" id="WWDT" location="0x40080000"/> +<peripheralInstance derived_from="USART0" id="USART0" location="0x40081000"/> +<peripheralInstance derived_from="USART2" id="USART2" location="0x400c1000"/> +<peripheralInstance derived_from="USART3" id="USART3" location="0x400c2000"/> +<peripheralInstance derived_from="UART1" id="UART1" location="0x40082000"/> +<peripheralInstance derived_from="SSP0" id="SSP0" location="0x40083000"/> +<peripheralInstance derived_from="SSP1" id="SSP1" location="0x400c5000"/> +<peripheralInstance derived_from="TIMER0" id="TIMER0" location="0x40084000"/> +<peripheralInstance derived_from="TIMER1" id="TIMER1" location="0x40085000"/> +<peripheralInstance derived_from="TIMER2" id="TIMER2" location="0x400c3000"/> +<peripheralInstance derived_from="TIMER3" id="TIMER3" location="0x400c4000"/> +<peripheralInstance derived_from="SCU" id="SCU" location="0x40086000"/> +<peripheralInstance derived_from="GPIO-PIN-INT" id="GPIO-PIN-INT" location="0x40087000"/> +<peripheralInstance derived_from="GPIO-GROUP-INT0" id="GPIO-GROUP-INT0" location="0x40088000"/> +<peripheralInstance derived_from="GPIO-GROUP-INT1" id="GPIO-GROUP-INT1" location="0x40089000"/> +<peripheralInstance derived_from="MCPWM" id="MCPWM" location="0x400a0000"/> +<peripheralInstance derived_from="I2C0" id="I2C0" location="0x400a1000"/> +<peripheralInstance derived_from="I2C1" id="I2C1" location="0x400e0000"/> +<peripheralInstance derived_from="I2S0" id="I2S0" location="0x400a2000"/> +<peripheralInstance derived_from="I2S1" id="I2S1" location="0x400a3000"/> +<peripheralInstance derived_from="C-CAN1" id="C-CAN1" location="0x400a4000"/> +<peripheralInstance derived_from="RITIMER" id="RITIMER" location="0x400c0000"/> +<peripheralInstance derived_from="QEI" id="QEI" location="0x400c6000"/> +<peripheralInstance derived_from="GIMA" id="GIMA" location="0x400c7000"/> +<peripheralInstance derived_from="DAC" id="DAC" location="0x400e1000"/> +<peripheralInstance derived_from="C-CAN0" id="C-CAN0" location="0x400e2000"/> +<peripheralInstance derived_from="ADC0" id="ADC0" location="0x400e3000"/> +<peripheralInstance derived_from="ADC1" id="ADC1" location="0x400e4000"/> +<peripheralInstance derived_from="GPIO-PORT" id="GPIO-PORT" location="0x400f4000"/> +</chip> +<processor><name gcc_name="cortex-m3">Cortex-M3</name> +<family>Cortex-M</family> +</processor> +<link href="nxp_lpc18xx_peripheral.xme" show="embed" type="simple"/> +</info> +</infoList> +</TargetConfig> + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/LPCExpresso.project b/FreeRTOS-Plus/Source/WolfSSL/LPCExpresso.project new file mode 100644 index 000000000..fc8bc2812 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/LPCExpresso.project @@ -0,0 +1,28 @@ + + + wolfssl + + + lpc_board_nxp_lpcxpresso_1837 + lpc_chip_18xx + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/Makefile.am b/FreeRTOS-Plus/Source/WolfSSL/Makefile.am index 5918a4dc5..37533fa23 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/Makefile.am +++ b/FreeRTOS-Plus/Source/WolfSSL/Makefile.am @@ -16,6 +16,9 @@ EXTRA_HEADERS = BUILT_SOURCES= EXTRA_DIST= dist_doc_DATA= +dist_noinst_SCRIPTS = +noinst_SCRIPTS = +check_SCRIPTS = #includes additional rules from aminclude.am @INC_AMINCLUDE@ @@ -30,13 +33,92 @@ CLEANFILES+= cert.der \ key.der \ key.pem \ ntru-cert.der \ + ecc-key-pkcs8.der \ ntru-cert.pem \ ntru-key.raw \ othercert.der \ othercert.pem \ pkcs7cert.der \ - pkcs7envelopedData.der \ - pkcs7signedData.der + pkcs7authEnvelopedDataAES128GCM.der \ + pkcs7authEnvelopedDataAES128GCM_ECDH_SHA1KDF.der \ + pkcs7authEnvelopedDataAES128GCM_KEKRI.der \ + pkcs7authEnvelopedDataAES128GCM_ORI.der \ + pkcs7authEnvelopedDataAES128GCM_PWRI.der \ + pkcs7authEnvelopedDataAES192GCM.der \ + pkcs7authEnvelopedDataAES256GCM.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_authAttribs.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_bothAttribs.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_fw_bothAttribs.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_unauthAttribs.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der \ + pkcs7authEnvelopedDataAES256GCM_firmwarePkgData.der \ + pkcs7authEnvelopedDataAES256GCM_IANDS.der \ + pkcs7authEnvelopedDataAES256GCM_SKID.der \ + pkcs7compressedData_data_zlib.der \ + pkcs7compressedData_firmwarePkgData_zlib.der \ + pkcs7encryptedDataAES128CBC.der \ + pkcs7encryptedDataAES192CBC.der \ + pkcs7encryptedDataAES256CBC_attribs.der \ + pkcs7encryptedDataAES256CBC.der \ + pkcs7encryptedDataAES256CBC_firmwarePkgData.der \ + pkcs7encryptedDataAES256CBC_multi_attribs.der \ + pkcs7encryptedDataDES3.der \ + pkcs7encryptedDataDES.der \ + pkcs7envelopedDataAES256CBC_ECDH.der \ + pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der \ + pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der \ + pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der \ + pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der \ + pkcs7envelopedDataDES3.der \ + pkcs7envelopedDataAES128CBC.der \ + pkcs7envelopedDataAES128CBC_KEKRI.der \ + pkcs7envelopedDataAES128CBC_PWRI.der \ + pkcs7envelopedDataAES128CBC_ORI.der \ + pkcs7envelopedDataAES192CBC.der \ + pkcs7envelopedDataAES256CBC.der \ + pkcs7envelopedDataAES256CBC_IANDS.der \ + pkcs7envelopedDataAES256CBC_SKID.der \ + pkcs7signedData_RSA_SHA.der \ + pkcs7signedData_RSA_SHA_noattr.der \ + pkcs7signedData_RSA_SHA224.der \ + pkcs7signedData_RSA_SHA256.der \ + pkcs7signedData_RSA_SHA256_firmwarePkgData.der \ + pkcs7signedData_RSA_SHA256_custom_contentType.der \ + pkcs7signedData_RSA_SHA256_with_ca_cert.der \ + pkcs7signedData_RSA_SHA256_SKID.der \ + pkcs7signedData_RSA_SHA256_detachedSig.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_SHA256_firmwarePkgData.der \ + pkcs7signedData_ECDSA_SHA256_custom_contentType.der \ + pkcs7signedData_ECDSA_SHA256_SKID.der \ + pkcs7signedData_ECDSA_SHA384.der \ + pkcs7signedData_ECDSA_SHA512.der \ + pkcs7signedFirmwarePkgData_ECDSA_SHA256.der \ + pkcs7signedFirmwarePkgData_ECDSA_SHA256_SKID.der \ + pkcs7signedFirmwarePkgData_ECDSA_SHA256_noattr.der \ + pkcs7signedFirmwarePkgData_RSA_SHA256.der \ + pkcs7signedFirmwarePkgData_RSA_SHA256_SKID.der \ + pkcs7signedFirmwarePkgData_RSA_SHA256_noattr.der \ + pkcs7signedFirmwarePkgData_RSA_SHA256_with_ca_cert.der \ + pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256.der \ + pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der \ + pkcs7signedCompressedFirmwarePkgData_RSA_SHA256.der \ + pkcs7signedCompressedFirmwarePkgData_RSA_SHA256_noattr.der \ + pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256.der \ + pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256_noattr.der \ + pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256.der \ + pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256_noattr.der \ + pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256.der \ + pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der \ + pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256.der \ + pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256_noattr.der exampledir = $(docdir)/example dist_example_DATA= @@ -45,51 +127,64 @@ ACLOCAL_AMFLAGS= -I m4 EXTRA_DIST+= lib/dummy -EXTRA_DIST+= cyassl-ntru.vcproj -EXTRA_DIST+= cyassl.vcproj -EXTRA_DIST+= cyassl.vcxproj -EXTRA_DIST+= cyassl-iphone.xcodeproj/project.pbxproj -EXTRA_DIST+= cyassl-ios.xcodeproj/project.pbxproj -EXTRA_DIST+= cyassl-ntru.sln -EXTRA_DIST+= cyassl.sln -EXTRA_DIST+= cyassl64.sln +EXTRA_DIST+= wolfssl-ntru.vcproj +EXTRA_DIST+= wolfssl.vcproj +EXTRA_DIST+= wolfssl.vcxproj +EXTRA_DIST+= wolfssl-ntru.sln +EXTRA_DIST+= wolfssl.sln +EXTRA_DIST+= wolfssl64.sln EXTRA_DIST+= valgrind-error.sh +EXTRA_DIST+= fips-hash.sh EXTRA_DIST+= gencertbuf.pl -EXTRA_DIST+= IDE +EXTRA_DIST+= README.md +EXTRA_DIST+= README +EXTRA_DIST+= ChangeLog.md +EXTRA_DIST+= LICENSING +EXTRA_DIST+= INSTALL +EXTRA_DIST+= IPP +EXTRA_DIST+= LPCExpresso.cproject +EXTRA_DIST+= LPCExpresso.project +EXTRA_DIST+= resource.h wolfssl.rc +include wrapper/include.am include cyassl/include.am +include wolfssl/include.am include certs/include.am -include certs/1024/include.am -include certs/crl/include.am include doc/include.am include swig/include.am include src/include.am include support/include.am -include ctaocrypt/benchmark/include.am -include ctaocrypt/src/include.am -include ctaocrypt/test/include.am -include examples/client/include.am -include examples/server/include.am -include examples/echoclient/include.am -include examples/echoserver/include.am +include wolfcrypt/user-crypto/include.am +include wolfcrypt/benchmark/include.am +include wolfcrypt/src/include.am +include wolfcrypt/test/include.am +include examples/include.am include testsuite/include.am include tests/include.am include sslSniffer/sslSnifferTest/include.am include rpm/include.am -include mqx/ctaocrypt_test/Sources/include.am -include mqx/cyassl/include.am -include mqx/cyassl_client/Sources/include.am + +# Exclude references to non-DFSG sources from build files +if !BUILD_DISTRO include mqx/util_lib/Sources/include.am +include mqx/wolfcrypt_benchmark/Sources/include.am +include mqx/wolfcrypt_test/Sources/include.am +include mqx/wolfssl/include.am +include mqx/wolfssl_client/Sources/include.am include mplabx/include.am -include mplabx/ctaocrypt_benchmark.X/nbproject/include.am -include mplabx/ctaocrypt_test.X/nbproject/include.am -include mplabx/cyassl.X/nbproject/include.am +include mplabx/wolfcrypt_benchmark.X/nbproject/include.am +include mplabx/wolfcrypt_test.X/nbproject/include.am +include mplabx/wolfssl.X/nbproject/include.am include mcapi/include.am -include mcapi/ctaocrypt_mcapi.X/nbproject/include.am -include mcapi/ctaocrypt_test.X/nbproject/include.am -include mcapi/cyassl.X/nbproject/include.am +include mcapi/wolfcrypt_mcapi.X/nbproject/include.am +include mcapi/wolfcrypt_test.X/nbproject/include.am +include mcapi/wolfssl.X/nbproject/include.am include mcapi/zlib.X/nbproject/include.am +include tirtos/include.am +include IDE/include.am +endif +include scripts/include.am if USE_VALGRIND TESTS_ENVIRONMENT=./valgrind-error.sh @@ -97,13 +192,15 @@ endif TEST_EXTENSIONS=.test TESTS += $(check_PROGRAMS) + +check_SCRIPTS+= $(dist_noinst_SCRIPTS) +TESTS += $(check_SCRIPTS) + test: check tests/unit.log: testsuite/testsuite.log DISTCLEANFILES+= cyassl-config -# fips files shouldn't be left after make distclean -DISTCLEANFILES+= ctaocrypt/src/fips.c -DISTCLEANFILES+= ctaocrypt/src/fips_test.c +DISTCLEANFILES+= wolfssl-config maintainer-clean-local: -rm Makefile.in @@ -126,7 +223,7 @@ maintainer-clean-local: -rm m4/ltsugar.m4 -rm m4/ltversion.m4 -rm m4/lt~obsolete.m4 - -rm support/cyassl.pc + -rm support/wolfssl.pc find . -type f -name '*~' -exec rm -f '{}' \; -rm -f @PACKAGE@-*.tar.gz -rm -f @PACKAGE@-*.rpm @@ -138,9 +235,9 @@ egs: $(MAKE) examples/server/server; \ $(MAKE) examples/echoserver/echoserver; -ctc: - $(MAKE) ctaocrypt/test/testctaocrypt; \ - $(MAKE) ctaocrypt/benchmark/benchmark; +wc_egs: + $(MAKE) wolfcrypt/test/testwolfcrypt; \ + $(MAKE) wolfcrypt/benchmark/benchmark; install-exec-local: install-generic-config @@ -162,3 +259,4 @@ merge-clean: @find ./ | $(GREP) \.OTHER | xargs rm -f @find ./ | $(GREP) \.BASE | xargs rm -f @find ./ | $(GREP) \~$$ | xargs rm -f + diff --git a/FreeRTOS-Plus/Source/WolfSSL/Makefile.in b/FreeRTOS-Plus/Source/WolfSSL/Makefile.in index fa6cbfb77..13b97faa1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/Makefile.in +++ b/FreeRTOS-Plus/Source/WolfSSL/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -14,6 +14,18 @@ @SET_MAKE@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + # vim:ft=automake # All paths should be given relative to the root # @@ -28,6 +40,56 @@ # All paths should be given relative to the root # +# vim:ft=automake +# All paths should be given relative to the root + +# vim:ft=automake +# All paths should be given relative to the root + +# vim:ft=automake +# All paths should be given relative to the root +# + +# vim:ft=automake +# All paths should be given relative to the root +# + +# vim:ft=automake +# All paths should be given relative to the root +# + +# vim:ft=automake +# All paths should be given relative to the root +# + +# vim:ft=automake +# All paths should be given relative to the root +# + +# vim:ft=automake +# All paths should be given relative to the root +# + +# vim:ft=automake +# All paths should be given relative to the root +# + +# vim:ft=automake +# All paths should be given relative to the root +# + +# vim:ft=automake +# All paths should be given relative to the root +# + +# vim:ft=automake +# All paths should be given relative to the root +# + +# vim:ft=automake +# All paths should be given relative to the root +# + # vim:ft=automake # All paths should be given relative to the root # @@ -67,6 +129,17 @@ # included from Top Level Makefile.am # All paths should be given relative to the root +# vim:ft=automake +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + # vim:ft=automake # included from Top Level Makefile.am # All paths should be given relative to the root @@ -121,6 +194,10 @@ # All paths should be given relative to the root # +# vim:ft=automake +# All paths should be given relative to the root +# + # vim:ft=automake # included from Top Level Makefile.am # All paths should be given relative to the root @@ -141,11 +218,162 @@ # All paths should be given relative to the root # +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + + VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -209,106 +437,592 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = -noinst_PROGRAMS = ctaocrypt/benchmark/benchmark$(EXEEXT) \ - ctaocrypt/test/testctaocrypt$(EXEEXT) $(am__EXEEXT_3) \ - $(am__EXEEXT_4) $(am__EXEEXT_2) -check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) -DIST_COMMON = $(srcdir)/cyassl/include.am \ - $(srcdir)/cyassl/ctaocrypt/include.am \ - $(srcdir)/cyassl/openssl/include.am $(srcdir)/certs/include.am \ - $(srcdir)/certs/1024/include.am $(srcdir)/certs/crl/include.am \ - $(srcdir)/doc/include.am $(srcdir)/swig/include.am \ - $(srcdir)/src/include.am $(srcdir)/support/include.am \ - $(srcdir)/ctaocrypt/benchmark/include.am \ - $(srcdir)/ctaocrypt/src/include.am \ - $(srcdir)/ctaocrypt/test/include.am \ - $(srcdir)/examples/client/include.am \ - $(srcdir)/examples/server/include.am \ - $(srcdir)/examples/echoclient/include.am \ - $(srcdir)/examples/echoserver/include.am \ - $(srcdir)/testsuite/include.am $(srcdir)/tests/include.am \ - $(srcdir)/sslSniffer/sslSnifferTest/include.am \ - $(srcdir)/rpm/include.am \ - $(srcdir)/mqx/ctaocrypt_test/Sources/include.am \ - $(srcdir)/mqx/cyassl/include.am \ - $(srcdir)/mqx/cyassl_client/Sources/include.am \ - $(srcdir)/mqx/util_lib/Sources/include.am \ - $(srcdir)/mplabx/include.am \ - $(srcdir)/mplabx/ctaocrypt_benchmark.X/nbproject/include.am \ - $(srcdir)/mplabx/ctaocrypt_test.X/nbproject/include.am \ - $(srcdir)/mplabx/cyassl.X/nbproject/include.am \ - $(srcdir)/mcapi/include.am \ - $(srcdir)/mcapi/ctaocrypt_mcapi.X/nbproject/include.am \ - $(srcdir)/mcapi/ctaocrypt_test.X/nbproject/include.am \ - $(srcdir)/mcapi/cyassl.X/nbproject/include.am \ - $(srcdir)/mcapi/zlib.X/nbproject/include.am \ - $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/configure $(am__configure_deps) \ - $(srcdir)/config.in $(srcdir)/stamp-h.in \ - $(top_srcdir)/cyassl/version.h.in \ - $(top_srcdir)/cyassl/options.h.in \ - $(top_srcdir)/support/cyassl.pc.in $(top_srcdir)/rpm/spec.in \ - $(top_srcdir)/build-aux/depcomp $(dist_doc_DATA) \ - $(dist_example_DATA) $(include_HEADERS) \ - $(nobase_include_HEADERS) $(am__noinst_HEADERS_DIST) \ - $(top_srcdir)/build-aux/test-driver AUTHORS COPYING ChangeLog \ - NEWS README build-aux/compile build-aux/config.guess \ - build-aux/config.sub build-aux/depcomp build-aux/install-sh \ - build-aux/missing build-aux/ltmain.sh \ - $(top_srcdir)/build-aux/compile \ - $(top_srcdir)/build-aux/config.guess \ - $(top_srcdir)/build-aux/config.sub \ - $(top_srcdir)/build-aux/install-sh \ - $(top_srcdir)/build-aux/ltmain.sh \ - $(top_srcdir)/build-aux/missing -@BUILD_FIPS_TRUE@am__append_1 = ctaocrypt/src/wolfcrypt_first.c -@BUILD_MEMORY_TRUE@am__append_2 = ctaocrypt/src/memory.c -@BUILD_RSA_TRUE@am__append_3 = ctaocrypt/src/rsa.c -@BUILD_DH_TRUE@am__append_4 = ctaocrypt/src/dh.c -@BUILD_ASN_TRUE@am__append_5 = ctaocrypt/src/asn.c -@BUILD_FIPS_TRUE@am__append_6 = ctaocrypt/src/fips.c \ -@BUILD_FIPS_TRUE@ ctaocrypt/src/fips_test.c -@BUILD_CODING_TRUE@am__append_7 = ctaocrypt/src/coding.c -@BUILD_AES_TRUE@am__append_8 = ctaocrypt/src/aes.c -@BUILD_DES3_TRUE@am__append_9 = ctaocrypt/src/des3.c -@BUILD_SHA_TRUE@am__append_10 = ctaocrypt/src/sha.c -@BUILD_RC4_TRUE@am__append_11 = ctaocrypt/src/arc4.c -@BUILD_MD4_TRUE@am__append_12 = ctaocrypt/src/md4.c -@BUILD_MD5_TRUE@am__append_13 = ctaocrypt/src/md5.c -@BUILD_PWDBASED_TRUE@am__append_14 = ctaocrypt/src/pwdbased.c -@BUILD_DSA_TRUE@am__append_15 = ctaocrypt/src/dsa.c -@BUILD_AESNI_TRUE@am__append_16 = ctaocrypt/src/aes_asm.s -@BUILD_CAMELLIA_TRUE@am__append_17 = ctaocrypt/src/camellia.c -@BUILD_MD2_TRUE@am__append_18 = ctaocrypt/src/md2.c -@BUILD_RIPEMD_TRUE@am__append_19 = ctaocrypt/src/ripemd.c -@BUILD_SHA512_TRUE@am__append_20 = ctaocrypt/src/sha512.c -@BUILD_BLAKE2_TRUE@am__append_21 = ctaocrypt/src/blake2b.c -@BUILD_SNIFFER_TRUE@am__append_22 = src/sniffer.c -@BUILD_HC128_TRUE@am__append_23 = ctaocrypt/src/hc128.c -@BUILD_RABBIT_TRUE@am__append_24 = ctaocrypt/src/rabbit.c -@BUILD_INLINE_FALSE@am__append_25 = ctaocrypt/src/misc.c -@BUILD_FASTMATH_TRUE@am__append_26 = ctaocrypt/src/tfm.c -@BUILD_SLOWMATH_TRUE@am__append_27 = ctaocrypt/src/integer.c -@BUILD_ECC_TRUE@am__append_28 = ctaocrypt/src/ecc.c -@BUILD_OCSP_TRUE@am__append_29 = src/ocsp.c -@BUILD_CRL_TRUE@am__append_30 = src/crl.c -@BUILD_LIBZ_TRUE@am__append_31 = ctaocrypt/src/compress.c -@BUILD_PKCS7_TRUE@am__append_32 = ctaocrypt/src/pkcs7.c -@BUILD_FIPS_TRUE@am__append_33 = ctaocrypt/src/wolfcrypt_last.c -@BUILD_EXAMPLES_TRUE@am__append_34 = examples/client/client \ -@BUILD_EXAMPLES_TRUE@ examples/server/server \ -@BUILD_EXAMPLES_TRUE@ examples/echoclient/echoclient \ -@BUILD_EXAMPLES_TRUE@ examples/echoserver/echoserver \ -@BUILD_EXAMPLES_TRUE@ testsuite/testsuite.test tests/unit.test -@BUILD_EXAMPLES_TRUE@am__append_35 = examples/client/client.h \ -@BUILD_EXAMPLES_TRUE@ examples/server/server.h \ -@BUILD_EXAMPLES_TRUE@ examples/echoclient/echoclient.h \ -@BUILD_EXAMPLES_TRUE@ examples/echoserver/echoserver.h -@BUILD_EXAMPLES_TRUE@am__append_36 = testsuite/testsuite.test \ -@BUILD_EXAMPLES_TRUE@ tests/unit.test -@BUILD_SNIFFTEST_TRUE@am__append_37 = sslSniffer/sslSnifferTest/snifftest -@BUILD_MCAPI_TRUE@am__append_38 = mcapi/test -@BUILD_MCAPI_TRUE@am__append_39 = mcapi/test +noinst_PROGRAMS = $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \ + $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_9) \ + $(am__EXEEXT_2) $(am__EXEEXT_10) $(am__EXEEXT_3) +check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) + +# For distro build don't install options.h. +# It depends on the architecture and conflicts with Multi-Arch. +@BUILD_DISTRO_TRUE@am__append_1 = cyassl/options.h +@BUILD_DISTRO_FALSE@am__append_2 = cyassl/options.h +@BUILD_CRYPTOAUTHLIB_TRUE@am__append_3 = wolfssl/wolfcrypt/port/atmel/atmel.h +@BUILD_AFALG_TRUE@am__append_4 = \ +@BUILD_AFALG_TRUE@ wolfssl/wolfcrypt/port/af_alg/afalg_hash.h \ +@BUILD_AFALG_TRUE@ wolfssl/wolfcrypt/port/af_alg/wc_afalg.h +@BUILD_DEVCRYPTO_TRUE@am__append_5 = wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h +@BUILD_ASYNCCRYPT_TRUE@am__append_6 = wolfssl/wolfcrypt/async.h +@BUILD_PKCS11_TRUE@am__append_7 = wolfssl/wolfcrypt/wc_pkcs11.h \ +@BUILD_PKCS11_TRUE@ wolfssl/wolfcrypt/pkcs11.h +@BUILD_CAVIUM_TRUE@am__append_8 = wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h +@BUILD_OCTEON_SYNC_TRUE@am__append_9 = wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h +@BUILD_INTEL_QA_TRUE@am__append_10 = wolfssl/wolfcrypt/port/intel/quickassist.h \ +@BUILD_INTEL_QA_TRUE@ wolfssl/wolfcrypt/port/intel/quickassist_mem.h +@BUILD_INTEL_QA_SYNC_TRUE@am__append_11 = wolfssl/wolfcrypt/port/intel/quickassist_sync.h +@BUILD_SP_TRUE@am__append_12 = wolfssl/wolfcrypt/sp.h \ +@BUILD_SP_TRUE@ wolfssl/wolfcrypt/sp_int.h +@BUILD_SELFTEST_TRUE@am__append_13 = wolfssl/wolfcrypt/selftest.h +@BUILD_FIPS_V2_TRUE@am__append_14 = wolfssl/wolfcrypt/fips.h +@BUILD_FIPS_RAND_TRUE@am__append_15 = wolfssl/wolfcrypt/fips.h + +# For distro build don't install options.h. +# It depends on the architecture and conflicts with Multi-Arch. +@BUILD_DISTRO_TRUE@am__append_16 = wolfssl/options.h +@BUILD_DISTRO_FALSE@am__append_17 = wolfssl/options.h + +# install the packaged IPP libraries + +# Link needed IPP libraries +@BUILD_FAST_RSA_TRUE@am__append_18 = IPP_links +@BUILD_FAST_RSA_TRUE@am__append_19 = $(IPPHEADERS) \ +@BUILD_FAST_RSA_TRUE@ wolfcrypt/user-crypto/include/user_rsa.h + +# fips first file +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@am__append_20 = ctaocrypt/src/wolfcrypt_first.c \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@ ctaocrypt/src/hmac.c \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@ ctaocrypt/src/random.c \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@ ctaocrypt/src/sha256.c +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@@BUILD_RSA_TRUE@am__append_21 = ctaocrypt/src/rsa.c +@BUILD_AES_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@am__append_22 = ctaocrypt/src/aes.c +@BUILD_DES3_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@am__append_23 = ctaocrypt/src/des3.c +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@@BUILD_SHA_TRUE@am__append_24 = ctaocrypt/src/sha.c +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@@BUILD_SHA512_TRUE@am__append_25 = ctaocrypt/src/sha512.c + +# fips last file +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@am__append_26 = \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@ ctaocrypt/src/fips.c \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@ ctaocrypt/src/fips_test.c \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@ ctaocrypt/src/wolfcrypt_last.c + +# FIPSv2 first file +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__append_27 = wolfcrypt/src/wolfcrypt_first.c \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@ wolfcrypt/src/hmac.c \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@ wolfcrypt/src/random.c \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@ wolfcrypt/src/sha256.c +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_RSA_TRUE@am__append_28 = wolfcrypt/src/rsa.c +@BUILD_ECC_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__append_29 = wolfcrypt/src/ecc.c +@BUILD_AES_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__append_30 = wolfcrypt/src/aes.c +@BUILD_AESNI_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__append_31 = wolfcrypt/src/aes_asm.S +@BUILD_AESNI_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_INTELASM_TRUE@am__append_32 = wolfcrypt/src/aes_gcm_asm.S +@BUILD_DES3_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__append_33 = wolfcrypt/src/des3.c +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_SHA_TRUE@am__append_34 = wolfcrypt/src/sha.c +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_INTELASM_TRUE@@BUILD_SHA_TRUE@am__append_35 = wolfcrypt/src/sha256_asm.S +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_SHA512_TRUE@am__append_36 = wolfcrypt/src/sha512.c +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_INTELASM_TRUE@@BUILD_SHA512_TRUE@am__append_37 = wolfcrypt/src/sha512_asm.S +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_SHA3_TRUE@am__append_38 = wolfcrypt/src/sha3.c +@BUILD_DH_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__append_39 = wolfcrypt/src/dh.c +@BUILD_CMAC_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__append_40 = wolfcrypt/src/cmac.c + +# fips last file +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__append_41 = \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@ wolfcrypt/src/fips.c \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@ wolfcrypt/src/fips_test.c \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@ wolfcrypt/src/wolfcrypt_last.c +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@am__append_42 = \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/wolfcrypt_first.c \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/hmac.c \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/random.c \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/sha256.c \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/sha256_asm.S \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/fips.c \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/fips_test.c \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/wolfcrypt_last.c + + +# For wolfRand, exclude everything else. + +# For FIPSV2, exclude the wolfCrypt files included above. +# For wolfRand, exclude just a couple files. +# For old FIPS, keep the wolfCrypt versions of the +# CtaoCrypt files included above. +@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__append_43 = wolfcrypt/src/hmac.c + +# CAVP self test +@BUILD_FIPS_RAND_FALSE@@BUILD_SELFTEST_TRUE@am__append_44 = wolfcrypt/src/selftest.c +@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_RNG_TRUE@am__append_45 = wolfcrypt/src/random.c +@BUILD_ARMASM_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__append_46 = wolfcrypt/src/port/arm/armv8-sha256.c +@BUILD_ARMASM_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__append_47 = wolfcrypt/src/sha256.c +@BUILD_ARMASM_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_INTELASM_TRUE@am__append_48 = wolfcrypt/src/sha256_asm.S +@BUILD_AFALG_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_49 = wolfcrypt/src/port/af_alg/afalg_hash.c +@BUILD_FIPS_RAND_FALSE@@BUILD_WOLFEVENT_TRUE@am__append_50 = wolfcrypt/src/wolfevent.c +@BUILD_ASYNCCRYPT_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_51 = wolfcrypt/src/async.c +@BUILD_FAST_RSA_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_RSA_TRUE@@BUILD_USER_RSA_FALSE@am__append_52 = wolfcrypt/user-crypto/src/rsa.c +@BUILD_FAST_RSA_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_RSA_TRUE@@BUILD_USER_RSA_FALSE@am__append_53 = wolfcrypt/src/rsa.c +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_C_TRUE@@BUILD_SP_TRUE@am__append_54 = wolfcrypt/src/sp_c32.c \ +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_C_TRUE@@BUILD_SP_TRUE@ wolfcrypt/src/sp_c64.c +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_TRUE@@BUILD_SP_X86_64_TRUE@am__append_55 = wolfcrypt/src/sp_x86_64.c \ +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_TRUE@@BUILD_SP_X86_64_TRUE@ wolfcrypt/src/sp_x86_64_asm.S +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_ARM32_TRUE@@BUILD_SP_TRUE@am__append_56 = wolfcrypt/src/sp_arm32.c +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_ARM_THUMB_TRUE@@BUILD_SP_TRUE@am__append_57 = wolfcrypt/src/sp_armthumb.c +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_ARM64_TRUE@@BUILD_SP_TRUE@am__append_58 = wolfcrypt/src/sp_arm64.c +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_INT_TRUE@@BUILD_SP_TRUE@am__append_59 = wolfcrypt/src/sp_int.c +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_ARM_CORTEX_TRUE@@BUILD_SP_TRUE@am__append_60 = wolfcrypt/src/sp_cortexm.c +@BUILD_AES_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__append_61 = wolfcrypt/src/aes.c +@BUILD_AES_TRUE@@BUILD_ARMASM_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__append_62 = wolfcrypt/src/port/arm/armv8-aes.c +@BUILD_AES_TRUE@@BUILD_AFALG_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__append_63 = wolfcrypt/src/port/af_alg/afalg_aes.c +@BUILD_CMAC_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__append_64 = wolfcrypt/src/cmac.c +@BUILD_DES3_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__append_65 = wolfcrypt/src/des3.c +@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_SHA_TRUE@am__append_66 = wolfcrypt/src/sha.c +@BUILD_ARMASM_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_SHA512_TRUE@am__append_67 = wolfcrypt/src/port/arm/armv8-sha512.c \ +@BUILD_ARMASM_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_SHA512_TRUE@ wolfcrypt/src/port/arm/armv8-sha512-asm.S \ +@BUILD_ARMASM_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_SHA512_TRUE@ wolfcrypt/src/port/arm/armv8-32-sha512-asm.S +@BUILD_ARMASM_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_SHA512_TRUE@am__append_68 = wolfcrypt/src/sha512.c +@BUILD_ARMASM_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_INTELASM_TRUE@@BUILD_SHA512_TRUE@am__append_69 = wolfcrypt/src/sha512_asm.S +@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_SHA3_TRUE@am__append_70 = wolfcrypt/src/sha3.c +@BUILD_FIPS_RAND_FALSE@am__append_71 = \ +@BUILD_FIPS_RAND_FALSE@ wolfcrypt/src/wc_encrypt.c \ +@BUILD_FIPS_RAND_FALSE@ wolfcrypt/src/signature.c \ +@BUILD_FIPS_RAND_FALSE@ wolfcrypt/src/wolfmath.c + +@BUILD_MEMORY_TRUE@am__append_72 = wolfcrypt/src/memory.c +@BUILD_DH_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__append_73 = wolfcrypt/src/dh.c +@BUILD_ASN_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_74 = wolfcrypt/src/asn.c +@BUILD_CODING_TRUE@am__append_75 = wolfcrypt/src/coding.c +@BUILD_ARMASM_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_POLY1305_TRUE@am__append_76 = wolfcrypt/src/port/arm/armv8-poly1305.c +@BUILD_FIPS_RAND_FALSE@@BUILD_POLY1305_TRUE@am__append_77 = wolfcrypt/src/poly1305.c +@BUILD_FIPS_RAND_FALSE@@BUILD_INTELASM_TRUE@@BUILD_POLY1305_TRUE@am__append_78 = wolfcrypt/src/poly1305_asm.S +@BUILD_FIPS_RAND_FALSE@@BUILD_RC4_TRUE@am__append_79 = wolfcrypt/src/arc4.c +@BUILD_FIPS_RAND_FALSE@@BUILD_MD4_TRUE@am__append_80 = wolfcrypt/src/md4.c +@BUILD_FIPS_RAND_FALSE@@BUILD_MD5_TRUE@am__append_81 = wolfcrypt/src/md5.c +@BUILD_FIPS_RAND_FALSE@@BUILD_PWDBASED_TRUE@am__append_82 = wolfcrypt/src/pwdbased.c \ +@BUILD_FIPS_RAND_FALSE@@BUILD_PWDBASED_TRUE@ wolfcrypt/src/pkcs12.c +@BUILD_DSA_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_83 = wolfcrypt/src/dsa.c +@BUILD_AESNI_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__append_84 = wolfcrypt/src/aes_asm.S \ +@BUILD_AESNI_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@ wolfcrypt/src/aes_gcm_asm.S +@BUILD_CAMELLIA_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_85 = wolfcrypt/src/camellia.c +@BUILD_FIPS_RAND_FALSE@@BUILD_MD2_TRUE@am__append_86 = wolfcrypt/src/md2.c +@BUILD_FIPS_RAND_FALSE@@BUILD_RIPEMD_TRUE@am__append_87 = wolfcrypt/src/ripemd.c +@BUILD_BLAKE2_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_88 = wolfcrypt/src/blake2b.c +@BUILD_BLAKE2S_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_89 = wolfcrypt/src/blake2s.c +@BUILD_FIPS_RAND_FALSE@@BUILD_HC128_TRUE@am__append_90 = wolfcrypt/src/hc128.c +@BUILD_FIPS_RAND_FALSE@@BUILD_RABBIT_TRUE@am__append_91 = wolfcrypt/src/rabbit.c +@BUILD_ARMASM_TRUE@@BUILD_CHACHA_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_92 = wolfcrypt/src/port/arm/armv8-chacha.c +@BUILD_ARMASM_FALSE@@BUILD_CHACHA_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_93 = wolfcrypt/src/chacha.c +@BUILD_ARMASM_FALSE@@BUILD_CHACHA_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_INTELASM_TRUE@am__append_94 = wolfcrypt/src/chacha_asm.S +@BUILD_CHACHA_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_POLY1305_TRUE@am__append_95 = wolfcrypt/src/chacha20_poly1305.c +@BUILD_FIPS_RAND_FALSE@@BUILD_INLINE_FALSE@am__append_96 = wolfcrypt/src/misc.c +@BUILD_FASTMATH_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_97 = wolfcrypt/src/tfm.c +@BUILD_FIPS_RAND_FALSE@@BUILD_SLOWMATH_TRUE@am__append_98 = wolfcrypt/src/integer.c +@BUILD_ECC_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__append_99 = wolfcrypt/src/ecc.c +@BUILD_CURVE25519_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_100 = wolfcrypt/src/curve25519.c +@BUILD_ED25519_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_101 = wolfcrypt/src/ed25519.c +@BUILD_CURVE25519_SMALL_TRUE@@BUILD_FEMATH_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_102 = wolfcrypt/src/fe_low_mem.c +@BUILD_CURVE25519_SMALL_FALSE@@BUILD_FEMATH_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_INTELASM_TRUE@am__append_103 = wolfcrypt/src/fe_x25519_asm.S +@BUILD_ARMASM_TRUE@@BUILD_CURVE25519_SMALL_FALSE@@BUILD_FEMATH_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_INTELASM_FALSE@am__append_104 = wolfcrypt/src/port/arm/armv8-32-curve25519.S \ +@BUILD_ARMASM_TRUE@@BUILD_CURVE25519_SMALL_FALSE@@BUILD_FEMATH_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_INTELASM_FALSE@ wolfcrypt/src/port/arm/armv8-curve25519.S +@BUILD_ARMASM_FALSE@@BUILD_CURVE25519_SMALL_FALSE@@BUILD_FEMATH_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_INTELASM_FALSE@am__append_105 = wolfcrypt/src/fe_operations.c +@BUILD_ED25519_SMALL_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_GEMATH_TRUE@am__append_106 = wolfcrypt/src/ge_low_mem.c +@BUILD_ED25519_SMALL_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_GEMATH_TRUE@am__append_107 = wolfcrypt/src/ge_operations.c +@BUILD_ED25519_SMALL_FALSE@@BUILD_FEMATH_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_GEMATH_TRUE@@BUILD_INTELASM_TRUE@am__append_108 = wolfcrypt/src/fe_x25519_asm.S +@BUILD_ARMASM_TRUE@@BUILD_ED25519_SMALL_FALSE@@BUILD_FEMATH_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_GEMATH_TRUE@@BUILD_INTELASM_FALSE@am__append_109 = wolfcrypt/src/port/arm/armv8-curve25519.S +@BUILD_ARMASM_FALSE@@BUILD_ED25519_SMALL_FALSE@@BUILD_FEMATH_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_GEMATH_TRUE@@BUILD_INTELASM_FALSE@am__append_110 = wolfcrypt/src/fe_operations.c +@BUILD_CURVE448_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_111 = wolfcrypt/src/curve448.c +@BUILD_ED448_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_112 = wolfcrypt/src/ed448.c +@BUILD_FE448_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_113 = wolfcrypt/src/fe_448.c +@BUILD_FIPS_RAND_FALSE@@BUILD_GE448_TRUE@am__append_114 = wolfcrypt/src/ge_448.c +@BUILD_FE448_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_GE448_TRUE@am__append_115 = wolfcrypt/src/fe_448.c +@BUILD_FIPS_RAND_FALSE@@BUILD_LIBZ_TRUE@am__append_116 = wolfcrypt/src/compress.c +@BUILD_FIPS_RAND_FALSE@@BUILD_PKCS7_TRUE@am__append_117 = wolfcrypt/src/pkcs7.c +@BUILD_FIPS_RAND_FALSE@@BUILD_SRP_TRUE@am__append_118 = wolfcrypt/src/srp.c +@BUILD_FIPS_RAND_FALSE@@BUILD_IDEA_TRUE@am__append_119 = wolfcrypt/src/idea.c +@BUILD_AFALG_TRUE@@BUILD_FIPS_RAND_FALSE@am__append_120 = wolfcrypt/src/port/af_alg/wc_afalg.c + +# ssl files +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@am__append_121 = \ +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@ src/internal.c \ +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@ src/wolfio.c \ +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@ src/keys.c \ +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@ src/ssl.c \ +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@ src/tls.c + +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_TLS13_TRUE@am__append_122 = src/tls13.c +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_OCSP_TRUE@am__append_123 = src/ocsp.c +@BUILD_CRL_TRUE@@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@am__append_124 = src/crl.c +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_SNIFFER_TRUE@am__append_125 = src/sniffer.c +@BUILD_WOLFCRYPT_TESTS_TRUE@am__append_126 = \ +@BUILD_WOLFCRYPT_TESTS_TRUE@ wolfcrypt/benchmark/benchmark \ +@BUILD_WOLFCRYPT_TESTS_TRUE@ wolfcrypt/test/testwolfcrypt \ +@BUILD_WOLFCRYPT_TESTS_TRUE@ wolfcrypt/test/testwolfcrypt +@BUILD_WOLFCRYPT_TESTS_TRUE@am__append_127 = \ +@BUILD_WOLFCRYPT_TESTS_TRUE@ wolfcrypt/benchmark/benchmark.h \ +@BUILD_WOLFCRYPT_TESTS_TRUE@ wolfcrypt/test/test.h +@BUILD_CRYPTOCB_TRUE@am__append_128 = wolfcrypt/src/cryptocb.c +@BUILD_PKCS11_TRUE@am__append_129 = wolfcrypt/src/wc_pkcs11.c +@BUILD_DEVCRYPTO_TRUE@am__append_130 = wolfcrypt/src/port/devcrypto/devcrypto_hash.c \ +@BUILD_DEVCRYPTO_TRUE@ wolfcrypt/src/port/devcrypto/devcrypto_aes.c \ +@BUILD_DEVCRYPTO_TRUE@ wolfcrypt/src/port/devcrypto/wc_devcrypto.c +@BUILD_CAVIUM_TRUE@am__append_131 = wolfcrypt/src/port/cavium/cavium_nitrox.c +@BUILD_OCTEON_SYNC_TRUE@am__append_132 = wolfcrypt/src/port/cavium/cavium_octeon_sync.c +@BUILD_INTEL_QA_TRUE@am__append_133 = \ +@BUILD_INTEL_QA_TRUE@ wolfcrypt/src/port/intel/quickassist.c \ +@BUILD_INTEL_QA_TRUE@ wolfcrypt/src/port/intel/quickassist_mem.c +@BUILD_INTEL_QA_SYNC_TRUE@am__append_134 = wolfcrypt/src/port/intel/quickassist_sync.c +@BUILD_CRYPTOAUTHLIB_TRUE@am__append_135 = wolfcrypt/src/port/atmel/atmel.c +@BUILD_CRYPTONLY_TRUE@@BUILD_WOLFCRYPT_TESTS_TRUE@am__append_136 = wolfcrypt/test/testwolfcrypt +@BUILD_THREADED_EXAMPLES_TRUE@am__append_137 = examples/benchmark/tls_bench +@BUILD_THREADED_EXAMPLES_TRUE@am__append_138 = examples/benchmark/tls_bench.h +@BUILD_EXAMPLE_CLIENTS_TRUE@am__append_139 = examples/client/client \ +@BUILD_EXAMPLE_CLIENTS_TRUE@ examples/echoclient/echoclient +@BUILD_EXAMPLE_CLIENTS_TRUE@am__append_140 = examples/client/client.h \ +@BUILD_EXAMPLE_CLIENTS_TRUE@ examples/echoclient/echoclient.h +@BUILD_EXAMPLE_SERVERS_TRUE@am__append_141 = \ +@BUILD_EXAMPLE_SERVERS_TRUE@ examples/echoserver/echoserver \ +@BUILD_EXAMPLE_SERVERS_TRUE@ examples/server/server +@BUILD_EXAMPLE_SERVERS_TRUE@am__append_142 = \ +@BUILD_EXAMPLE_SERVERS_TRUE@ examples/echoserver/echoserver.h \ +@BUILD_EXAMPLE_SERVERS_TRUE@ examples/server/server.h +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@am__append_143 = \ +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@ examples/sctp/sctp-server \ +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@ examples/sctp/sctp-server-dtls + +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@am__append_144 = \ +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@ examples/sctp/sctp-client \ +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@ examples/sctp/sctp-client-dtls + +@BUILD_TESTS_TRUE@am__append_145 = testsuite/testsuite.test \ +@BUILD_TESTS_TRUE@ tests/unit.test +@BUILD_TESTS_TRUE@am__append_146 = testsuite/testsuite.test \ +@BUILD_TESTS_TRUE@ tests/unit.test +@BUILD_SNIFFTEST_TRUE@am__append_147 = sslSniffer/sslSnifferTest/snifftest +@BUILD_DISTRO_FALSE@am__append_148 = mqx/util_lib/.cproject \ +@BUILD_DISTRO_FALSE@ mqx/util_lib/.project \ +@BUILD_DISTRO_FALSE@ mqx/util_lib/Sources/util.c \ +@BUILD_DISTRO_FALSE@ mqx/util_lib/Sources/util.h \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/.cproject \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/.project \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/Debugger/K70FN1M0.mem \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/Debugger/init_kinetis.tcl \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/Debugger/mass_erase_kinetis.tcl \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/ReferencedRSESystems.xml \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/Sources/main.c \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_benchmark/Sources/main.h \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/.cproject \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/.project \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/Debugger/K70FN1M0.mem \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/Debugger/init_kinetis.tcl \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/Debugger/mass_erase_kinetis.tcl \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/ReferencedRSESystems.xml \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/Sources/main.c \ +@BUILD_DISTRO_FALSE@ mqx/wolfcrypt_test/Sources/main.h \ +@BUILD_DISTRO_FALSE@ mqx/README mqx/wolfssl/.cproject \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl/.project \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/.cproject \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/.project \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/Debugger/K70FN1M0.mem \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/Debugger/init_kinetis.tcl \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/Debugger/mass_erase_kinetis.tcl \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/ReferencedRSESystems.xml \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/Sources/main.c \ +@BUILD_DISTRO_FALSE@ mqx/wolfssl_client/Sources/main.h \ +@BUILD_DISTRO_FALSE@ mplabx/README mplabx/benchmark_main.c \ +@BUILD_DISTRO_FALSE@ mplabx/test_main.c mplabx/PIC32MZ-serial.h \ +@BUILD_DISTRO_FALSE@ mplabx/user_settings.h \ +@BUILD_DISTRO_FALSE@ mplabx/wolfcrypt_benchmark.X/Makefile \ +@BUILD_DISTRO_FALSE@ mplabx/wolfcrypt_benchmark.X/nbproject/configurations.xml \ +@BUILD_DISTRO_FALSE@ mplabx/wolfcrypt_benchmark.X/nbproject/project.xml \ +@BUILD_DISTRO_FALSE@ mplabx/wolfcrypt_test.X/Makefile \ +@BUILD_DISTRO_FALSE@ mplabx/wolfcrypt_test.X/nbproject/configurations.xml \ +@BUILD_DISTRO_FALSE@ mplabx/wolfcrypt_test.X/nbproject/project.xml \ +@BUILD_DISTRO_FALSE@ mplabx/wolfssl.X/Makefile \ +@BUILD_DISTRO_FALSE@ mplabx/wolfssl.X/nbproject/configurations.xml \ +@BUILD_DISTRO_FALSE@ mplabx/wolfssl.X/nbproject/project.xml \ +@BUILD_DISTRO_FALSE@ mcapi/README mcapi/PIC32MZ-serial.h \ +@BUILD_DISTRO_FALSE@ mcapi/user_settings.h \ +@BUILD_DISTRO_FALSE@ mcapi/wolfcrypt_mcapi.X/Makefile \ +@BUILD_DISTRO_FALSE@ mcapi/wolfcrypt_mcapi.X/nbproject/configurations.xml \ +@BUILD_DISTRO_FALSE@ mcapi/wolfcrypt_mcapi.X/nbproject/project.xml \ +@BUILD_DISTRO_FALSE@ mcapi/wolfcrypt_test.X/Makefile \ +@BUILD_DISTRO_FALSE@ mcapi/wolfcrypt_test.X/nbproject/configurations.xml \ +@BUILD_DISTRO_FALSE@ mcapi/wolfcrypt_test.X/nbproject/project.xml \ +@BUILD_DISTRO_FALSE@ mcapi/wolfssl.X/Makefile \ +@BUILD_DISTRO_FALSE@ mcapi/wolfssl.X/nbproject/configurations.xml \ +@BUILD_DISTRO_FALSE@ mcapi/wolfssl.X/nbproject/project.xml \ +@BUILD_DISTRO_FALSE@ mcapi/zlib.X/Makefile \ +@BUILD_DISTRO_FALSE@ mcapi/zlib.X/nbproject/configurations.xml \ +@BUILD_DISTRO_FALSE@ mcapi/zlib.X/nbproject/project.xml \ +@BUILD_DISTRO_FALSE@ tirtos/README tirtos/wolfssl.bld \ +@BUILD_DISTRO_FALSE@ tirtos/wolfssl.mak tirtos/products.mak \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/package.bld \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/package.xdc \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/package.xs \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/package.bld.hide \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/package.xdc \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/test.cfg \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/TM4C1294NC.icf \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/main.c \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/package.bld.hide \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/package.xdc \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/benchmark.cfg \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/TM4C1294NC.icf \ +@BUILD_DISTRO_FALSE@ tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/main.c \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/README.md \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/wolfssl-FIPS.xcodeproj/project.pbxproj \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/wolfssl.xcodeproj/project.pbxproj \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/wolfssl.xcworkspace \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/wolfssl_testsuite.xcodeproj \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/build-for-i386.sh \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/Benchmark/wolfBench.xcodeproj/project.pbxproj \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/Benchmark/wolfBench/AppDelegate.h \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/Benchmark/wolfBench/AppDelegate.m \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/Benchmark/wolfBench/Info.plist \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/Benchmark/wolfBench/main.m \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/Benchmark/wolfBench/ViewController.h \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/Benchmark/wolfBench/ViewController.m \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/Benchmark/wolfBench/Assets.xcassets/AppIcon.appiconset/Contents.json \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/Benchmark/wolfBench/Base.lproj/LaunchScreen.storyboard \ +@BUILD_DISTRO_FALSE@ IDE/XCODE/Benchmark/wolfBench/Base.lproj/Main.storyboard \ +@BUILD_DISTRO_FALSE@ IDE/WIN/README.txt IDE/WIN/test.vcxproj \ +@BUILD_DISTRO_FALSE@ IDE/WIN/wolfssl-fips.sln \ +@BUILD_DISTRO_FALSE@ IDE/WIN/wolfssl-fips.vcxproj \ +@BUILD_DISTRO_FALSE@ IDE/WIN/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/WIN10/README.txt \ +@BUILD_DISTRO_FALSE@ IDE/WIN10/test.vcxproj \ +@BUILD_DISTRO_FALSE@ IDE/WIN10/wolfssl-fips.sln \ +@BUILD_DISTRO_FALSE@ IDE/WIN10/wolfssl-fips.vcxproj \ +@BUILD_DISTRO_FALSE@ IDE/WIN10/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/WIN-SGX/ReadMe.txt \ +@BUILD_DISTRO_FALSE@ IDE/WIN-SGX/wolfSSL_SGX.edl \ +@BUILD_DISTRO_FALSE@ IDE/WIN-SGX/wolfSSL_SGX.sln \ +@BUILD_DISTRO_FALSE@ IDE/WIN-SGX/wolfSSL_SGX.vcxproj \ +@BUILD_DISTRO_FALSE@ IDE/WIN-SGX/wolfSSL_SGX.vcxproj.filters \ +@BUILD_DISTRO_FALSE@ IDE/LINUX-SGX/README.md \ +@BUILD_DISTRO_FALSE@ IDE/LINUX-SGX/sgx_t_static.mk \ +@BUILD_DISTRO_FALSE@ IDE/LINUX-SGX/build.sh \ +@BUILD_DISTRO_FALSE@ IDE/LINUX-SGX/clean.sh \ +@BUILD_DISTRO_FALSE@ IDE/WORKBENCH/README.md \ +@BUILD_DISTRO_FALSE@ IDE/ROWLEY-CROSSWORKS-ARM/arm_startup.c \ +@BUILD_DISTRO_FALSE@ IDE/ROWLEY-CROSSWORKS-ARM/benchmark_main.c \ +@BUILD_DISTRO_FALSE@ IDE/ROWLEY-CROSSWORKS-ARM/hw.h \ +@BUILD_DISTRO_FALSE@ IDE/ROWLEY-CROSSWORKS-ARM/kinetis_hw.c \ +@BUILD_DISTRO_FALSE@ IDE/ROWLEY-CROSSWORKS-ARM/Kinetis_FlashPlacement.xml \ +@BUILD_DISTRO_FALSE@ IDE/ROWLEY-CROSSWORKS-ARM/README.md \ +@BUILD_DISTRO_FALSE@ IDE/ROWLEY-CROSSWORKS-ARM/test_main.c \ +@BUILD_DISTRO_FALSE@ IDE/ROWLEY-CROSSWORKS-ARM/retarget.c \ +@BUILD_DISTRO_FALSE@ IDE/ROWLEY-CROSSWORKS-ARM/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/ROWLEY-CROSSWORKS-ARM/wolfssl.hzp \ +@BUILD_DISTRO_FALSE@ IDE/ROWLEY-CROSSWORKS-ARM/wolfssl_ltc.hzp \ +@BUILD_DISTRO_FALSE@ IDE/TRUESTUDIO/README \ +@BUILD_DISTRO_FALSE@ IDE/TRUESTUDIO/wolfssl/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/TRUESTUDIO/wolfssl/.project \ +@BUILD_DISTRO_FALSE@ IDE/TRUESTUDIO/wolfssl/.settings/com.atollic.truestudio.debug.hardware_device.prefs \ +@BUILD_DISTRO_FALSE@ IDE/TRUESTUDIO/wolfssl/.settings/language.settings.xml \ +@BUILD_DISTRO_FALSE@ IDE/TRUESTUDIO/wolfssl/.settings/org.eclipse.cdt.managedbuilder.core.prefs \ +@BUILD_DISTRO_FALSE@ IDE/TRUESTUDIO/wolfssl/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/ARDUINO/README.md \ +@BUILD_DISTRO_FALSE@ IDE/ARDUINO/sketches/wolfssl_client/wolfssl_client.ino \ +@BUILD_DISTRO_FALSE@ IDE/ARDUINO/sketches/wolfssl_server/wolfssl_server.ino \ +@BUILD_DISTRO_FALSE@ IDE/ARDUINO/wolfssl-arduino.sh \ +@BUILD_DISTRO_FALSE@ IDE/INTIME-RTOS/README.md \ +@BUILD_DISTRO_FALSE@ IDE/INTIME-RTOS/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/INTIME-RTOS/libwolfssl.c \ +@BUILD_DISTRO_FALSE@ IDE/INTIME-RTOS/libwolfssl.vcxproj \ +@BUILD_DISTRO_FALSE@ IDE/INTIME-RTOS/wolfExamples.c \ +@BUILD_DISTRO_FALSE@ IDE/INTIME-RTOS/wolfExamples.h \ +@BUILD_DISTRO_FALSE@ IDE/INTIME-RTOS/wolfExamples.vcxproj \ +@BUILD_DISTRO_FALSE@ IDE/INTIME-RTOS/wolfExamples.sln \ +@BUILD_DISTRO_FALSE@ IDE/OPENSTM32/README.md \ +@BUILD_DISTRO_FALSE@ IDE/OPENSTM32/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/OPENSTM32/.project \ +@BUILD_DISTRO_FALSE@ IDE/OPENSTM32/wolfSTM32.cfg \ +@BUILD_DISTRO_FALSE@ IDE/OPENSTM32/wolfSTM32.ioc \ +@BUILD_DISTRO_FALSE@ IDE/OPENSTM32/wolfSTM32.xml \ +@BUILD_DISTRO_FALSE@ IDE/OPENSTM32/Src/main.c \ +@BUILD_DISTRO_FALSE@ IDE/OPENSTM32/Src/wolfssl_example.c \ +@BUILD_DISTRO_FALSE@ IDE/OPENSTM32/Inc/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/OPENSTM32/Inc/wolfssl_example.h \ +@BUILD_DISTRO_FALSE@ IDE/VS-ARM/README.md \ +@BUILD_DISTRO_FALSE@ IDE/VS-ARM/wolfssl.sln \ +@BUILD_DISTRO_FALSE@ IDE/VS-ARM/wolfssl.vcxproj \ +@BUILD_DISTRO_FALSE@ IDE/VS-ARM/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/README.md \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/wolfssl.sln \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/wolfssl.vcxproj \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/client/app_manifest.json \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/client/client.c \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/client/client.h \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/client/client.vcxproj \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/server/app_manifest.json \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/server/server.c \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/server/server.h \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/server/server.vcxproj \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/wolfcrypt_test/app_manifest.json \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/wolfcrypt_test/wolfcrypt_test.vcxproj \ +@BUILD_DISTRO_FALSE@ IDE/VS-AZURE-SPHERE/shared/util.h \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/Header/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/Source/armtarget.c \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/Source/wolf_main.c \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/Source/benchmark_main.c \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/Source/test_main.c \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/Source/tls_client.c \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/linker.ld \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/linker_fips.ld \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/Makefile \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/Makefile.bench \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/Makefile.client \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/Makefile.common \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/Makefile.test \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/Makefile.static \ +@BUILD_DISTRO_FALSE@ IDE/GCC-ARM/README.md IDE/CSBENCH/.project \ +@BUILD_DISTRO_FALSE@ IDE/CSBENCH/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/CSBENCH/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/DEOS/README.md \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/DEOS/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/DEOS/tls_wolfssl.h \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/DEOS/tls_wolfssl.c \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/DEOS/deos_malloc.c \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/MICRIUM/README.md \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/MICRIUM/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/MICRIUM/client_wolfssl.h \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/MICRIUM/server_wolfssl.h \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/MICRIUM/client_wolfssl.c \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/MICRIUM/server_wolfssl.c \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/MICRIUM/wolfsslRunTests.c \ +@BUILD_DISTRO_FALSE@ IDE/ECLIPSE/SIFIVE/README.md \ +@BUILD_DISTRO_FALSE@ IDE/mynewt/README.md \ +@BUILD_DISTRO_FALSE@ IDE/mynewt/apps.wolfcrypttest.pkg.yml \ +@BUILD_DISTRO_FALSE@ IDE/mynewt/crypto.wolfssl.pkg.yml \ +@BUILD_DISTRO_FALSE@ IDE/mynewt/crypto.wolfssl.syscfg.yml \ +@BUILD_DISTRO_FALSE@ IDE/mynewt/setup.sh \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/README.md \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/wolfssl-template-project/.project \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/wolfssl-template-project/configuration.xml \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/wolfcrypttest-template/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/wolfcrypttest-template/.project \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/wolfcrypttest-template/src/app_entry.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/example_server-template/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/example_server-template/.project \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/example_server-template/src/app_entry.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/benchmark-template/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/benchmark-template/.project \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/DK-S7G2/benchmark-template/src/app_entry.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/README \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/wolfssl_lib/wolfssl_lib.mtpj \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/test/test.mtpj \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/test/test_main.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/common/wolfssl_dummy.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/common/strings.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/common/unistd.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/common/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/t4_demo/README_en.txt \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/t4_demo/README_jp.txt \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/t4_demo/wolf_client.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/t4_demo/wolf_server.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/t4_demo/wolf_main.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/t4_demo/wolf_demo.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/cs+/Projects/t4_demo/t4_demo.mtpj \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/README \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/wolfssl/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/wolfssl/.project \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/test/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/test/.project \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/test/src/test_main.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/test/src/key_data.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/test/src/key_data.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/test/src/wolf_client.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/test/src/wolf_server.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/test/src/wolfssl_demo.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/common/wolfssl_dummy.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/common/strings.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/common/unistd.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/Projects/common/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/benchmark-wolfcrypt/src/wolfssl_thread_entry.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/benchmark-wolfcrypt/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/benchmark-wolfcrypt/.project \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/client-wolfssl/src/wolfssl_thread_entry.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/client-wolfssl/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/client-wolfssl/.project \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/client-wolfssl/wolfssl_thread_entry.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/common/ra6m3g/README.md \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/common/src/freertos_tcp_port.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/common/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/common/util.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/server-wolfssl/src/wolfssl_thread_entry.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/server-wolfssl/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/server-wolfssl/.project \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/server-wolfssl/wolfssl_thread_entry.h \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/test-wolfcrypt/src/wolfssl_thread_entry.c \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/test-wolfcrypt/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/test-wolfcrypt/.project \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/wolfssl/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/wolfssl/.project \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/wolfssl/configuration.xml \ +@BUILD_DISTRO_FALSE@ IDE/Renesas/e2studio/RA6M3G/README.md \ +@BUILD_DISTRO_FALSE@ IDE/WICED-STUDIO/README \ +@BUILD_DISTRO_FALSE@ IDE/WICED-STUDIO/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/CRYPTOCELL/README.md \ +@BUILD_DISTRO_FALSE@ IDE/CRYPTOCELL/main.c \ +@BUILD_DISTRO_FALSE@ IDE/CRYPTOCELL/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/M68K/README.md IDE/M68K/Makefile \ +@BUILD_DISTRO_FALSE@ IDE/M68K/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/M68K/testwolfcrypt/main.cpp \ +@BUILD_DISTRO_FALSE@ IDE/M68K/testwolfcrypt/Makefile \ +@BUILD_DISTRO_FALSE@ IDE/M68K/benchmark/main.cpp \ +@BUILD_DISTRO_FALSE@ IDE/M68K/benchmark/Makefile \ +@BUILD_DISTRO_FALSE@ IDE/HEXAGON/Makefile \ +@BUILD_DISTRO_FALSE@ IDE/HEXAGON/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/HEXAGON/README.md IDE/HEXAGON/build.sh \ +@BUILD_DISTRO_FALSE@ IDE/HEXAGON/ecc-verify.c \ +@BUILD_DISTRO_FALSE@ IDE/HEXAGON/ecc-verify-benchmark.c \ +@BUILD_DISTRO_FALSE@ IDE/HEXAGON/DSP/Makefile \ +@BUILD_DISTRO_FALSE@ IDE/HEXAGON/DSP/wolfssl_dsp.idl \ +@BUILD_DISTRO_FALSE@ IDE/RISCV/SIFIVE-HIFIVE1/README.md \ +@BUILD_DISTRO_FALSE@ IDE/RISCV/SIFIVE-HIFIVE1/main.c \ +@BUILD_DISTRO_FALSE@ IDE/RISCV/SIFIVE-HIFIVE1/Makefile \ +@BUILD_DISTRO_FALSE@ IDE/RISCV/SIFIVE-HIFIVE1/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/RISCV/SIFIVE-UNLEASHED/README.md \ +@BUILD_DISTRO_FALSE@ IDE/XilinxSDK/README.md \ +@BUILD_DISTRO_FALSE@ IDE/XilinxSDK/user_settings.h \ +@BUILD_DISTRO_FALSE@ IDE/XilinxSDK/wolfssl_example.c \ +@BUILD_DISTRO_FALSE@ IDE/XilinxSDK/lscript.ld \ +@BUILD_DISTRO_FALSE@ IDE/XilinxSDK/.cproject \ +@BUILD_DISTRO_FALSE@ IDE/XilinxSDK/.project IDE/IAR-EWARM \ +@BUILD_DISTRO_FALSE@ IDE/MDK-ARM IDE/MDK5-ARM IDE/MYSQL \ +@BUILD_DISTRO_FALSE@ IDE/LPCXPRESSO IDE/HEXIWEAR IDE/Espressif \ +@BUILD_DISTRO_FALSE@ IDE/zephyr +@BUILD_DISTRO_FALSE@@BUILD_MCAPI_TRUE@am__append_149 = mcapi/test +@BUILD_DISTRO_FALSE@@BUILD_MCAPI_TRUE@am__append_150 = mcapi/test +@BUILD_DISTRO_FALSE@am__append_151 = mcapi/crypto.h +@BUILD_SNIFFTEST_TRUE@am__append_152 = scripts/sniffer-testsuite.test +@BUILD_EXAMPLE_SERVERS_TRUE@am__append_153 = scripts/resume.test +@BUILD_EXAMPLE_SERVERS_TRUE@am__append_154 = scripts/benchmark.test \ +@BUILD_EXAMPLE_SERVERS_TRUE@ scripts/memtest.sh + +# The CRL and OCSP tests use RSA certificates. + +# make revoked test rely on completion of resume test +@BUILD_CRL_TRUE@@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_RSA_TRUE@am__append_155 = scripts/crl-revoked.test +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_TRUE@@BUILD_RSA_TRUE@am__append_156 = scripts/ocsp-stapling.test \ +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_TRUE@@BUILD_RSA_TRUE@ scripts/ocsp-stapling-with-ca-as-responder.test +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_V2_TRUE@@BUILD_RSA_TRUE@am__append_157 = scripts/ocsp-stapling2.test +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_PSK_TRUE@am__append_158 = scripts/psk.test +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_TRUST_PEER_CERT_TRUE@am__append_159 = scripts/trusted_peer.test +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_PKCALLBACKS_TRUE@am__append_160 = scripts/pkcallbacks.test +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_TLS13_TRUE@am__append_161 = scripts/tls13.test +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_IPV6_FALSE@am__append_162 = scripts/external.test \ +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_IPV6_FALSE@ scripts/google.test \ +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_IPV6_FALSE@ scripts/openssl.test +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_IPV6_FALSE@@BUILD_OCSP_TRUE@am__append_163 = scripts/ocsp.test subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_add_am_macro.m4 \ @@ -325,24 +1039,52 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_add_am_macro.m4 \ $(top_srcdir)/m4/ax_file_escapes.m4 \ $(top_srcdir)/m4/ax_harden_compiler_flags.m4 \ $(top_srcdir)/m4/ax_print_to_file.m4 \ - $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/ax_tls.m4 \ - $(top_srcdir)/m4/ax_vcs_checkout.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_require_defined.m4 \ + $(top_srcdir)/m4/ax_tls.m4 $(top_srcdir)/m4/ax_vcs_checkout.m4 \ $(top_srcdir)/m4/hexversion.m4 \ $(top_srcdir)/m4/lib_socket_nsl.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/m4/visibility.m4 \ - $(top_srcdir)/m4/wolfssl_darwin_clang.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__dist_noinst_SCRIPTS_DIST) \ + $(dist_doc_DATA) $(dist_example_DATA) \ + $(am__include_HEADERS_DIST) $(am__nobase_include_HEADERS_DIST) \ + $(am__noinst_HEADERS_DIST) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h -CONFIG_CLEAN_FILES = stamp-h cyassl/version.h cyassl/options.h \ - support/cyassl.pc rpm/spec +CONFIG_CLEAN_FILES = stamp-h wolfssl/version.h wolfssl/options.h \ + cyassl/options.h support/wolfssl.pc rpm/spec CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" \ + "$(DESTDIR)$(docdir)" "$(DESTDIR)$(exampledir)" \ + "$(DESTDIR)$(ippdir)" "$(DESTDIR)$(pkgconfigdir)" \ + "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)" +@BUILD_CRYPTONLY_TRUE@@BUILD_WOLFCRYPT_TESTS_TRUE@am__EXEEXT_1 = wolfcrypt/test/testwolfcrypt$(EXEEXT) +@BUILD_TESTS_TRUE@am__EXEEXT_2 = testsuite/testsuite.test$(EXEEXT) \ +@BUILD_TESTS_TRUE@ tests/unit.test$(EXEEXT) +@BUILD_DISTRO_FALSE@@BUILD_MCAPI_TRUE@am__EXEEXT_3 = \ +@BUILD_DISTRO_FALSE@@BUILD_MCAPI_TRUE@ mcapi/test$(EXEEXT) +@BUILD_WOLFCRYPT_TESTS_TRUE@am__EXEEXT_4 = wolfcrypt/benchmark/benchmark$(EXEEXT) \ +@BUILD_WOLFCRYPT_TESTS_TRUE@ wolfcrypt/test/testwolfcrypt$(EXEEXT) \ +@BUILD_WOLFCRYPT_TESTS_TRUE@ wolfcrypt/test/testwolfcrypt$(EXEEXT) +@BUILD_THREADED_EXAMPLES_TRUE@am__EXEEXT_5 = examples/benchmark/tls_bench$(EXEEXT) +@BUILD_EXAMPLE_CLIENTS_TRUE@am__EXEEXT_6 = \ +@BUILD_EXAMPLE_CLIENTS_TRUE@ examples/client/client$(EXEEXT) \ +@BUILD_EXAMPLE_CLIENTS_TRUE@ examples/echoclient/echoclient$(EXEEXT) +@BUILD_EXAMPLE_SERVERS_TRUE@am__EXEEXT_7 = examples/echoserver/echoserver$(EXEEXT) \ +@BUILD_EXAMPLE_SERVERS_TRUE@ examples/server/server$(EXEEXT) +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@am__EXEEXT_8 = examples/sctp/sctp-server$(EXEEXT) \ +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@ examples/sctp/sctp-server-dtls$(EXEEXT) +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@am__EXEEXT_9 = examples/sctp/sctp-client$(EXEEXT) \ +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@ examples/sctp/sctp-client-dtls$(EXEEXT) +@BUILD_SNIFFTEST_TRUE@am__EXEEXT_10 = sslSniffer/sslSnifferTest/snifftest$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -370,97 +1112,228 @@ am__uninstall_files_from_dir = { \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } -am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ - "$(DESTDIR)$(docdir)" "$(DESTDIR)$(exampledir)" \ - "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)" \ - "$(DESTDIR)$(includedir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = -src_libcyassl_la_DEPENDENCIES = $(am__DEPENDENCIES_1) -am__src_libcyassl_la_SOURCES_DIST = ctaocrypt/src/wolfcrypt_first.c \ - src/internal.c src/io.c src/keys.c src/ssl.c src/tls.c \ +src_libwolfssl_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am__src_libwolfssl_la_SOURCES_DIST = ctaocrypt/src/wolfcrypt_first.c \ ctaocrypt/src/hmac.c ctaocrypt/src/random.c \ - ctaocrypt/src/sha256.c ctaocrypt/src/logging.c \ - ctaocrypt/src/wc_port.c ctaocrypt/src/error.c \ - ctaocrypt/src/memory.c ctaocrypt/src/rsa.c ctaocrypt/src/dh.c \ - ctaocrypt/src/asn.c ctaocrypt/src/fips.c \ - ctaocrypt/src/fips_test.c ctaocrypt/src/coding.c \ - ctaocrypt/src/aes.c ctaocrypt/src/des3.c ctaocrypt/src/sha.c \ - ctaocrypt/src/arc4.c ctaocrypt/src/md4.c ctaocrypt/src/md5.c \ - ctaocrypt/src/pwdbased.c ctaocrypt/src/dsa.c \ - ctaocrypt/src/aes_asm.s ctaocrypt/src/camellia.c \ - ctaocrypt/src/md2.c ctaocrypt/src/ripemd.c \ - ctaocrypt/src/sha512.c ctaocrypt/src/blake2b.c src/sniffer.c \ - ctaocrypt/src/hc128.c ctaocrypt/src/rabbit.c \ - ctaocrypt/src/misc.c ctaocrypt/src/tfm.c \ - ctaocrypt/src/integer.c ctaocrypt/src/ecc.c src/ocsp.c \ - src/crl.c ctaocrypt/src/compress.c ctaocrypt/src/pkcs7.c \ - ctaocrypt/src/wolfcrypt_last.c + ctaocrypt/src/sha256.c ctaocrypt/src/rsa.c ctaocrypt/src/aes.c \ + ctaocrypt/src/des3.c ctaocrypt/src/sha.c \ + ctaocrypt/src/sha512.c ctaocrypt/src/fips.c \ + ctaocrypt/src/fips_test.c ctaocrypt/src/wolfcrypt_last.c \ + wolfcrypt/src/wolfcrypt_first.c wolfcrypt/src/hmac.c \ + wolfcrypt/src/random.c wolfcrypt/src/sha256.c \ + wolfcrypt/src/rsa.c wolfcrypt/src/ecc.c wolfcrypt/src/aes.c \ + wolfcrypt/src/aes_asm.S wolfcrypt/src/aes_gcm_asm.S \ + wolfcrypt/src/des3.c wolfcrypt/src/sha.c \ + wolfcrypt/src/sha256_asm.S wolfcrypt/src/sha512.c \ + wolfcrypt/src/sha512_asm.S wolfcrypt/src/sha3.c \ + wolfcrypt/src/dh.c wolfcrypt/src/cmac.c wolfcrypt/src/fips.c \ + wolfcrypt/src/fips_test.c wolfcrypt/src/wolfcrypt_last.c \ + wolfcrypt/src/selftest.c wolfcrypt/src/hash.c \ + wolfcrypt/src/cpuid.c wolfcrypt/src/port/arm/armv8-sha256.c \ + wolfcrypt/src/port/af_alg/afalg_hash.c \ + wolfcrypt/src/wolfevent.c wolfcrypt/src/async.c \ + wolfcrypt/user-crypto/src/rsa.c wolfcrypt/src/sp_c32.c \ + wolfcrypt/src/sp_c64.c wolfcrypt/src/sp_x86_64.c \ + wolfcrypt/src/sp_x86_64_asm.S wolfcrypt/src/sp_arm32.c \ + wolfcrypt/src/sp_armthumb.c wolfcrypt/src/sp_arm64.c \ + wolfcrypt/src/sp_int.c wolfcrypt/src/sp_cortexm.c \ + wolfcrypt/src/port/arm/armv8-aes.c \ + wolfcrypt/src/port/af_alg/afalg_aes.c \ + wolfcrypt/src/port/arm/armv8-sha512.c \ + wolfcrypt/src/port/arm/armv8-sha512-asm.S \ + wolfcrypt/src/port/arm/armv8-32-sha512-asm.S \ + wolfcrypt/src/logging.c wolfcrypt/src/wc_port.c \ + wolfcrypt/src/error.c wolfcrypt/src/wc_encrypt.c \ + wolfcrypt/src/signature.c wolfcrypt/src/wolfmath.c \ + wolfcrypt/src/memory.c wolfcrypt/src/asn.c \ + wolfcrypt/src/coding.c wolfcrypt/src/port/arm/armv8-poly1305.c \ + wolfcrypt/src/poly1305.c wolfcrypt/src/poly1305_asm.S \ + wolfcrypt/src/arc4.c wolfcrypt/src/md4.c wolfcrypt/src/md5.c \ + wolfcrypt/src/pwdbased.c wolfcrypt/src/pkcs12.c \ + wolfcrypt/src/dsa.c wolfcrypt/src/camellia.c \ + wolfcrypt/src/md2.c wolfcrypt/src/ripemd.c \ + wolfcrypt/src/blake2b.c wolfcrypt/src/blake2s.c \ + wolfcrypt/src/hc128.c wolfcrypt/src/rabbit.c \ + wolfcrypt/src/port/arm/armv8-chacha.c wolfcrypt/src/chacha.c \ + wolfcrypt/src/chacha_asm.S wolfcrypt/src/chacha20_poly1305.c \ + wolfcrypt/src/misc.c wolfcrypt/src/tfm.c \ + wolfcrypt/src/integer.c wolfcrypt/src/curve25519.c \ + wolfcrypt/src/ed25519.c wolfcrypt/src/fe_low_mem.c \ + wolfcrypt/src/fe_x25519_asm.S \ + wolfcrypt/src/port/arm/armv8-32-curve25519.S \ + wolfcrypt/src/port/arm/armv8-curve25519.S \ + wolfcrypt/src/fe_operations.c wolfcrypt/src/ge_low_mem.c \ + wolfcrypt/src/ge_operations.c wolfcrypt/src/curve448.c \ + wolfcrypt/src/ed448.c wolfcrypt/src/fe_448.c \ + wolfcrypt/src/ge_448.c wolfcrypt/src/compress.c \ + wolfcrypt/src/pkcs7.c wolfcrypt/src/srp.c wolfcrypt/src/idea.c \ + wolfcrypt/src/port/af_alg/wc_afalg.c src/internal.c \ + src/wolfio.c src/keys.c src/ssl.c src/tls.c src/tls13.c \ + src/ocsp.c src/crl.c src/sniffer.c wolfcrypt/src/cryptocb.c \ + wolfcrypt/src/wc_pkcs11.c \ + wolfcrypt/src/port/devcrypto/devcrypto_hash.c \ + wolfcrypt/src/port/devcrypto/devcrypto_aes.c \ + wolfcrypt/src/port/devcrypto/wc_devcrypto.c \ + wolfcrypt/src/port/cavium/cavium_nitrox.c \ + wolfcrypt/src/port/cavium/cavium_octeon_sync.c \ + wolfcrypt/src/port/intel/quickassist.c \ + wolfcrypt/src/port/intel/quickassist_mem.c \ + wolfcrypt/src/port/intel/quickassist_sync.c \ + wolfcrypt/src/port/atmel/atmel.c am__dirstamp = $(am__leading_dot)dirstamp -@BUILD_FIPS_TRUE@am__objects_1 = ctaocrypt/src/src_libcyassl_la-wolfcrypt_first.lo -@BUILD_MEMORY_TRUE@am__objects_2 = \ -@BUILD_MEMORY_TRUE@ ctaocrypt/src/src_libcyassl_la-memory.lo -@BUILD_RSA_TRUE@am__objects_3 = ctaocrypt/src/src_libcyassl_la-rsa.lo -@BUILD_DH_TRUE@am__objects_4 = ctaocrypt/src/src_libcyassl_la-dh.lo -@BUILD_ASN_TRUE@am__objects_5 = ctaocrypt/src/src_libcyassl_la-asn.lo -@BUILD_FIPS_TRUE@am__objects_6 = \ -@BUILD_FIPS_TRUE@ ctaocrypt/src/src_libcyassl_la-fips.lo \ -@BUILD_FIPS_TRUE@ ctaocrypt/src/src_libcyassl_la-fips_test.lo -@BUILD_CODING_TRUE@am__objects_7 = \ -@BUILD_CODING_TRUE@ ctaocrypt/src/src_libcyassl_la-coding.lo -@BUILD_AES_TRUE@am__objects_8 = ctaocrypt/src/src_libcyassl_la-aes.lo -@BUILD_DES3_TRUE@am__objects_9 = \ -@BUILD_DES3_TRUE@ ctaocrypt/src/src_libcyassl_la-des3.lo -@BUILD_SHA_TRUE@am__objects_10 = \ -@BUILD_SHA_TRUE@ ctaocrypt/src/src_libcyassl_la-sha.lo -@BUILD_RC4_TRUE@am__objects_11 = \ -@BUILD_RC4_TRUE@ ctaocrypt/src/src_libcyassl_la-arc4.lo -@BUILD_MD4_TRUE@am__objects_12 = \ -@BUILD_MD4_TRUE@ ctaocrypt/src/src_libcyassl_la-md4.lo -@BUILD_MD5_TRUE@am__objects_13 = \ -@BUILD_MD5_TRUE@ ctaocrypt/src/src_libcyassl_la-md5.lo -@BUILD_PWDBASED_TRUE@am__objects_14 = ctaocrypt/src/src_libcyassl_la-pwdbased.lo -@BUILD_DSA_TRUE@am__objects_15 = \ -@BUILD_DSA_TRUE@ ctaocrypt/src/src_libcyassl_la-dsa.lo -@BUILD_AESNI_TRUE@am__objects_16 = ctaocrypt/src/aes_asm.lo -@BUILD_CAMELLIA_TRUE@am__objects_17 = ctaocrypt/src/src_libcyassl_la-camellia.lo -@BUILD_MD2_TRUE@am__objects_18 = \ -@BUILD_MD2_TRUE@ ctaocrypt/src/src_libcyassl_la-md2.lo -@BUILD_RIPEMD_TRUE@am__objects_19 = \ -@BUILD_RIPEMD_TRUE@ ctaocrypt/src/src_libcyassl_la-ripemd.lo -@BUILD_SHA512_TRUE@am__objects_20 = \ -@BUILD_SHA512_TRUE@ ctaocrypt/src/src_libcyassl_la-sha512.lo -@BUILD_BLAKE2_TRUE@am__objects_21 = \ -@BUILD_BLAKE2_TRUE@ ctaocrypt/src/src_libcyassl_la-blake2b.lo -@BUILD_SNIFFER_TRUE@am__objects_22 = src/src_libcyassl_la-sniffer.lo -@BUILD_HC128_TRUE@am__objects_23 = \ -@BUILD_HC128_TRUE@ ctaocrypt/src/src_libcyassl_la-hc128.lo -@BUILD_RABBIT_TRUE@am__objects_24 = \ -@BUILD_RABBIT_TRUE@ ctaocrypt/src/src_libcyassl_la-rabbit.lo -@BUILD_INLINE_FALSE@am__objects_25 = \ -@BUILD_INLINE_FALSE@ ctaocrypt/src/src_libcyassl_la-misc.lo -@BUILD_FASTMATH_TRUE@am__objects_26 = \ -@BUILD_FASTMATH_TRUE@ ctaocrypt/src/src_libcyassl_la-tfm.lo -@BUILD_SLOWMATH_TRUE@am__objects_27 = ctaocrypt/src/src_libcyassl_la-integer.lo -@BUILD_ECC_TRUE@am__objects_28 = \ -@BUILD_ECC_TRUE@ ctaocrypt/src/src_libcyassl_la-ecc.lo -@BUILD_OCSP_TRUE@am__objects_29 = src/src_libcyassl_la-ocsp.lo -@BUILD_CRL_TRUE@am__objects_30 = src/src_libcyassl_la-crl.lo -@BUILD_LIBZ_TRUE@am__objects_31 = \ -@BUILD_LIBZ_TRUE@ ctaocrypt/src/src_libcyassl_la-compress.lo -@BUILD_PKCS7_TRUE@am__objects_32 = \ -@BUILD_PKCS7_TRUE@ ctaocrypt/src/src_libcyassl_la-pkcs7.lo -@BUILD_FIPS_TRUE@am__objects_33 = ctaocrypt/src/src_libcyassl_la-wolfcrypt_last.lo -am_src_libcyassl_la_OBJECTS = $(am__objects_1) \ - src/src_libcyassl_la-internal.lo src/src_libcyassl_la-io.lo \ - src/src_libcyassl_la-keys.lo src/src_libcyassl_la-ssl.lo \ - src/src_libcyassl_la-tls.lo \ - ctaocrypt/src/src_libcyassl_la-hmac.lo \ - ctaocrypt/src/src_libcyassl_la-random.lo \ - ctaocrypt/src/src_libcyassl_la-sha256.lo \ - ctaocrypt/src/src_libcyassl_la-logging.lo \ - ctaocrypt/src/src_libcyassl_la-wc_port.lo \ - ctaocrypt/src/src_libcyassl_la-error.lo $(am__objects_2) \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@am__objects_1 = ctaocrypt/src/src_libwolfssl_la-wolfcrypt_first.lo \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@ ctaocrypt/src/src_libwolfssl_la-hmac.lo \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@ ctaocrypt/src/src_libwolfssl_la-random.lo \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@ ctaocrypt/src/src_libwolfssl_la-sha256.lo +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@@BUILD_RSA_TRUE@am__objects_2 = ctaocrypt/src/src_libwolfssl_la-rsa.lo +@BUILD_AES_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@am__objects_3 = ctaocrypt/src/src_libwolfssl_la-aes.lo +@BUILD_DES3_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@am__objects_4 = ctaocrypt/src/src_libwolfssl_la-des3.lo +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@@BUILD_SHA_TRUE@am__objects_5 = ctaocrypt/src/src_libwolfssl_la-sha.lo +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@@BUILD_SHA512_TRUE@am__objects_6 = ctaocrypt/src/src_libwolfssl_la-sha512.lo +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@am__objects_7 = ctaocrypt/src/src_libwolfssl_la-fips.lo \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@ ctaocrypt/src/src_libwolfssl_la-fips_test.lo \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V1_TRUE@ ctaocrypt/src/src_libwolfssl_la-wolfcrypt_last.lo +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__objects_8 = wolfcrypt/src/src_libwolfssl_la-wolfcrypt_first.lo \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@ wolfcrypt/src/src_libwolfssl_la-hmac.lo \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@ wolfcrypt/src/src_libwolfssl_la-random.lo \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@ wolfcrypt/src/src_libwolfssl_la-sha256.lo +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_RSA_TRUE@am__objects_9 = wolfcrypt/src/src_libwolfssl_la-rsa.lo +@BUILD_ECC_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__objects_10 = wolfcrypt/src/src_libwolfssl_la-ecc.lo +@BUILD_AES_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__objects_11 = wolfcrypt/src/src_libwolfssl_la-aes.lo +@BUILD_AESNI_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__objects_12 = wolfcrypt/src/src_libwolfssl_la-aes_asm.lo +@BUILD_AESNI_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_INTELASM_TRUE@am__objects_13 = wolfcrypt/src/src_libwolfssl_la-aes_gcm_asm.lo +@BUILD_DES3_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__objects_14 = wolfcrypt/src/src_libwolfssl_la-des3.lo +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_SHA_TRUE@am__objects_15 = wolfcrypt/src/src_libwolfssl_la-sha.lo +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_INTELASM_TRUE@@BUILD_SHA_TRUE@am__objects_16 = wolfcrypt/src/src_libwolfssl_la-sha256_asm.lo +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_SHA512_TRUE@am__objects_17 = wolfcrypt/src/src_libwolfssl_la-sha512.lo +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_INTELASM_TRUE@@BUILD_SHA512_TRUE@am__objects_18 = wolfcrypt/src/src_libwolfssl_la-sha512_asm.lo +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@@BUILD_SHA3_TRUE@am__objects_19 = wolfcrypt/src/src_libwolfssl_la-sha3.lo +@BUILD_DH_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__objects_20 = wolfcrypt/src/src_libwolfssl_la-dh.lo +@BUILD_CMAC_TRUE@@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__objects_21 = wolfcrypt/src/src_libwolfssl_la-cmac.lo +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@am__objects_22 = wolfcrypt/src/src_libwolfssl_la-fips.lo \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@ wolfcrypt/src/src_libwolfssl_la-fips_test.lo \ +@BUILD_FIPS_TRUE@@BUILD_FIPS_V2_TRUE@ wolfcrypt/src/src_libwolfssl_la-wolfcrypt_last.lo +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@am__objects_23 = wolfcrypt/src/src_libwolfssl_la-wolfcrypt_first.lo \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/src_libwolfssl_la-hmac.lo \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/src_libwolfssl_la-random.lo \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/src_libwolfssl_la-sha256.lo \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/src_libwolfssl_la-sha256_asm.lo \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/src_libwolfssl_la-fips.lo \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/src_libwolfssl_la-fips_test.lo \ +@BUILD_FIPS_RAND_TRUE@@BUILD_FIPS_TRUE@ wolfcrypt/src/src_libwolfssl_la-wolfcrypt_last.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__objects_24 = wolfcrypt/src/src_libwolfssl_la-hmac.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_SELFTEST_TRUE@am__objects_25 = wolfcrypt/src/src_libwolfssl_la-selftest.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_RNG_TRUE@am__objects_26 = wolfcrypt/src/src_libwolfssl_la-random.lo +@BUILD_ARMASM_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__objects_27 = wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha256.lo +@BUILD_ARMASM_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__objects_28 = wolfcrypt/src/src_libwolfssl_la-sha256.lo +@BUILD_ARMASM_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_INTELASM_TRUE@am__objects_29 = wolfcrypt/src/src_libwolfssl_la-sha256_asm.lo +@BUILD_AFALG_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_30 = wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_hash.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_WOLFEVENT_TRUE@am__objects_31 = wolfcrypt/src/src_libwolfssl_la-wolfevent.lo +@BUILD_ASYNCCRYPT_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_32 = wolfcrypt/src/src_libwolfssl_la-async.lo +@BUILD_FAST_RSA_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_RSA_TRUE@@BUILD_USER_RSA_FALSE@am__objects_33 = wolfcrypt/user-crypto/src/src_libwolfssl_la-rsa.lo +@BUILD_FAST_RSA_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_RSA_TRUE@@BUILD_USER_RSA_FALSE@am__objects_34 = wolfcrypt/src/src_libwolfssl_la-rsa.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_C_TRUE@@BUILD_SP_TRUE@am__objects_35 = wolfcrypt/src/src_libwolfssl_la-sp_c32.lo \ +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_C_TRUE@@BUILD_SP_TRUE@ wolfcrypt/src/src_libwolfssl_la-sp_c64.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_TRUE@@BUILD_SP_X86_64_TRUE@am__objects_36 = wolfcrypt/src/src_libwolfssl_la-sp_x86_64.lo \ +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_TRUE@@BUILD_SP_X86_64_TRUE@ wolfcrypt/src/src_libwolfssl_la-sp_x86_64_asm.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_ARM32_TRUE@@BUILD_SP_TRUE@am__objects_37 = wolfcrypt/src/src_libwolfssl_la-sp_arm32.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_ARM_THUMB_TRUE@@BUILD_SP_TRUE@am__objects_38 = wolfcrypt/src/src_libwolfssl_la-sp_armthumb.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_ARM64_TRUE@@BUILD_SP_TRUE@am__objects_39 = wolfcrypt/src/src_libwolfssl_la-sp_arm64.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_INT_TRUE@@BUILD_SP_TRUE@am__objects_40 = wolfcrypt/src/src_libwolfssl_la-sp_int.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_SP_ARM_CORTEX_TRUE@@BUILD_SP_TRUE@am__objects_41 = wolfcrypt/src/src_libwolfssl_la-sp_cortexm.lo +@BUILD_AES_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__objects_42 = wolfcrypt/src/src_libwolfssl_la-aes.lo +@BUILD_AES_TRUE@@BUILD_ARMASM_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__objects_43 = wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-aes.lo +@BUILD_AES_TRUE@@BUILD_AFALG_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__objects_44 = wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_aes.lo +@BUILD_CMAC_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__objects_45 = wolfcrypt/src/src_libwolfssl_la-cmac.lo +@BUILD_DES3_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__objects_46 = wolfcrypt/src/src_libwolfssl_la-des3.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_SHA_TRUE@am__objects_47 = wolfcrypt/src/src_libwolfssl_la-sha.lo +@BUILD_ARMASM_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_SHA512_TRUE@am__objects_48 = wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512.lo \ +@BUILD_ARMASM_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_SHA512_TRUE@ wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512-asm.lo \ +@BUILD_ARMASM_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_SHA512_TRUE@ wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-sha512-asm.lo +@BUILD_ARMASM_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_SHA512_TRUE@am__objects_49 = wolfcrypt/src/src_libwolfssl_la-sha512.lo +@BUILD_ARMASM_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_INTELASM_TRUE@@BUILD_SHA512_TRUE@am__objects_50 = wolfcrypt/src/src_libwolfssl_la-sha512_asm.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@@BUILD_SHA3_TRUE@am__objects_51 = wolfcrypt/src/src_libwolfssl_la-sha3.lo +@BUILD_FIPS_RAND_FALSE@am__objects_52 = wolfcrypt/src/src_libwolfssl_la-wc_encrypt.lo \ +@BUILD_FIPS_RAND_FALSE@ wolfcrypt/src/src_libwolfssl_la-signature.lo \ +@BUILD_FIPS_RAND_FALSE@ wolfcrypt/src/src_libwolfssl_la-wolfmath.lo +@BUILD_MEMORY_TRUE@am__objects_53 = \ +@BUILD_MEMORY_TRUE@ wolfcrypt/src/src_libwolfssl_la-memory.lo +@BUILD_DH_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__objects_54 = wolfcrypt/src/src_libwolfssl_la-dh.lo +@BUILD_ASN_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_55 = wolfcrypt/src/src_libwolfssl_la-asn.lo +@BUILD_CODING_TRUE@am__objects_56 = \ +@BUILD_CODING_TRUE@ wolfcrypt/src/src_libwolfssl_la-coding.lo +@BUILD_ARMASM_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_POLY1305_TRUE@am__objects_57 = wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-poly1305.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_POLY1305_TRUE@am__objects_58 = wolfcrypt/src/src_libwolfssl_la-poly1305.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_INTELASM_TRUE@@BUILD_POLY1305_TRUE@am__objects_59 = wolfcrypt/src/src_libwolfssl_la-poly1305_asm.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_RC4_TRUE@am__objects_60 = wolfcrypt/src/src_libwolfssl_la-arc4.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_MD4_TRUE@am__objects_61 = wolfcrypt/src/src_libwolfssl_la-md4.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_MD5_TRUE@am__objects_62 = wolfcrypt/src/src_libwolfssl_la-md5.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_PWDBASED_TRUE@am__objects_63 = wolfcrypt/src/src_libwolfssl_la-pwdbased.lo \ +@BUILD_FIPS_RAND_FALSE@@BUILD_PWDBASED_TRUE@ wolfcrypt/src/src_libwolfssl_la-pkcs12.lo +@BUILD_DSA_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_64 = wolfcrypt/src/src_libwolfssl_la-dsa.lo +@BUILD_AESNI_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__objects_65 = wolfcrypt/src/src_libwolfssl_la-aes_asm.lo \ +@BUILD_AESNI_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@ wolfcrypt/src/src_libwolfssl_la-aes_gcm_asm.lo +@BUILD_CAMELLIA_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_66 = wolfcrypt/src/src_libwolfssl_la-camellia.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_MD2_TRUE@am__objects_67 = wolfcrypt/src/src_libwolfssl_la-md2.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_RIPEMD_TRUE@am__objects_68 = wolfcrypt/src/src_libwolfssl_la-ripemd.lo +@BUILD_BLAKE2_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_69 = wolfcrypt/src/src_libwolfssl_la-blake2b.lo +@BUILD_BLAKE2S_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_70 = wolfcrypt/src/src_libwolfssl_la-blake2s.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_HC128_TRUE@am__objects_71 = wolfcrypt/src/src_libwolfssl_la-hc128.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_RABBIT_TRUE@am__objects_72 = wolfcrypt/src/src_libwolfssl_la-rabbit.lo +@BUILD_ARMASM_TRUE@@BUILD_CHACHA_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_73 = wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-chacha.lo +@BUILD_ARMASM_FALSE@@BUILD_CHACHA_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_74 = wolfcrypt/src/src_libwolfssl_la-chacha.lo +@BUILD_ARMASM_FALSE@@BUILD_CHACHA_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_INTELASM_TRUE@am__objects_75 = wolfcrypt/src/src_libwolfssl_la-chacha_asm.lo +@BUILD_CHACHA_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_POLY1305_TRUE@am__objects_76 = wolfcrypt/src/src_libwolfssl_la-chacha20_poly1305.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_INLINE_FALSE@am__objects_77 = wolfcrypt/src/src_libwolfssl_la-misc.lo +@BUILD_FASTMATH_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_78 = wolfcrypt/src/src_libwolfssl_la-tfm.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_SLOWMATH_TRUE@am__objects_79 = wolfcrypt/src/src_libwolfssl_la-integer.lo +@BUILD_ECC_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_FIPS_V2_FALSE@am__objects_80 = wolfcrypt/src/src_libwolfssl_la-ecc.lo +@BUILD_CURVE25519_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_81 = wolfcrypt/src/src_libwolfssl_la-curve25519.lo +@BUILD_ED25519_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_82 = wolfcrypt/src/src_libwolfssl_la-ed25519.lo +@BUILD_CURVE25519_SMALL_TRUE@@BUILD_FEMATH_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_83 = wolfcrypt/src/src_libwolfssl_la-fe_low_mem.lo +@BUILD_CURVE25519_SMALL_FALSE@@BUILD_FEMATH_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_INTELASM_TRUE@am__objects_84 = wolfcrypt/src/src_libwolfssl_la-fe_x25519_asm.lo +@BUILD_ARMASM_TRUE@@BUILD_CURVE25519_SMALL_FALSE@@BUILD_FEMATH_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_INTELASM_FALSE@am__objects_85 = wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-curve25519.lo \ +@BUILD_ARMASM_TRUE@@BUILD_CURVE25519_SMALL_FALSE@@BUILD_FEMATH_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_INTELASM_FALSE@ wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-curve25519.lo +@BUILD_ARMASM_FALSE@@BUILD_CURVE25519_SMALL_FALSE@@BUILD_FEMATH_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_INTELASM_FALSE@am__objects_86 = wolfcrypt/src/src_libwolfssl_la-fe_operations.lo +@BUILD_ED25519_SMALL_TRUE@@BUILD_FIPS_RAND_FALSE@@BUILD_GEMATH_TRUE@am__objects_87 = wolfcrypt/src/src_libwolfssl_la-ge_low_mem.lo +@BUILD_ED25519_SMALL_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_GEMATH_TRUE@am__objects_88 = wolfcrypt/src/src_libwolfssl_la-ge_operations.lo +@BUILD_ED25519_SMALL_FALSE@@BUILD_FEMATH_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_GEMATH_TRUE@@BUILD_INTELASM_TRUE@am__objects_89 = wolfcrypt/src/src_libwolfssl_la-fe_x25519_asm.lo +@BUILD_ARMASM_TRUE@@BUILD_ED25519_SMALL_FALSE@@BUILD_FEMATH_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_GEMATH_TRUE@@BUILD_INTELASM_FALSE@am__objects_90 = wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-curve25519.lo +@BUILD_ARMASM_FALSE@@BUILD_ED25519_SMALL_FALSE@@BUILD_FEMATH_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_GEMATH_TRUE@@BUILD_INTELASM_FALSE@am__objects_91 = wolfcrypt/src/src_libwolfssl_la-fe_operations.lo +@BUILD_CURVE448_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_92 = wolfcrypt/src/src_libwolfssl_la-curve448.lo +@BUILD_ED448_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_93 = wolfcrypt/src/src_libwolfssl_la-ed448.lo +@BUILD_FE448_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_94 = wolfcrypt/src/src_libwolfssl_la-fe_448.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_GE448_TRUE@am__objects_95 = wolfcrypt/src/src_libwolfssl_la-ge_448.lo +@BUILD_FE448_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_GE448_TRUE@am__objects_96 = wolfcrypt/src/src_libwolfssl_la-fe_448.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_LIBZ_TRUE@am__objects_97 = wolfcrypt/src/src_libwolfssl_la-compress.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_PKCS7_TRUE@am__objects_98 = wolfcrypt/src/src_libwolfssl_la-pkcs7.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_SRP_TRUE@am__objects_99 = wolfcrypt/src/src_libwolfssl_la-srp.lo +@BUILD_FIPS_RAND_FALSE@@BUILD_IDEA_TRUE@am__objects_100 = wolfcrypt/src/src_libwolfssl_la-idea.lo +@BUILD_AFALG_TRUE@@BUILD_FIPS_RAND_FALSE@am__objects_101 = wolfcrypt/src/port/af_alg/src_libwolfssl_la-wc_afalg.lo +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@am__objects_102 = src/libwolfssl_la-internal.lo \ +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@ src/libwolfssl_la-wolfio.lo \ +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@ src/libwolfssl_la-keys.lo \ +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@ src/libwolfssl_la-ssl.lo \ +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@ src/libwolfssl_la-tls.lo +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_TLS13_TRUE@am__objects_103 = src/libwolfssl_la-tls13.lo +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_OCSP_TRUE@am__objects_104 = src/libwolfssl_la-ocsp.lo +@BUILD_CRL_TRUE@@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@am__objects_105 = src/libwolfssl_la-crl.lo +@BUILD_CRYPTONLY_FALSE@@BUILD_FIPS_RAND_FALSE@@BUILD_SNIFFER_TRUE@am__objects_106 = src/libwolfssl_la-sniffer.lo +@BUILD_CRYPTOCB_TRUE@am__objects_107 = wolfcrypt/src/src_libwolfssl_la-cryptocb.lo +@BUILD_PKCS11_TRUE@am__objects_108 = wolfcrypt/src/src_libwolfssl_la-wc_pkcs11.lo +@BUILD_DEVCRYPTO_TRUE@am__objects_109 = wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_hash.lo \ +@BUILD_DEVCRYPTO_TRUE@ wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_aes.lo \ +@BUILD_DEVCRYPTO_TRUE@ wolfcrypt/src/port/devcrypto/src_libwolfssl_la-wc_devcrypto.lo +@BUILD_CAVIUM_TRUE@am__objects_110 = wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_nitrox.lo +@BUILD_OCTEON_SYNC_TRUE@am__objects_111 = wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_octeon_sync.lo +@BUILD_INTEL_QA_TRUE@am__objects_112 = wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist.lo \ +@BUILD_INTEL_QA_TRUE@ wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_mem.lo +@BUILD_INTEL_QA_SYNC_TRUE@am__objects_113 = wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_sync.lo +@BUILD_CRYPTOAUTHLIB_TRUE@am__objects_114 = wolfcrypt/src/port/atmel/src_libwolfssl_la-atmel.lo +am_src_libwolfssl_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ $(am__objects_3) $(am__objects_4) $(am__objects_5) \ $(am__objects_6) $(am__objects_7) $(am__objects_8) \ $(am__objects_9) $(am__objects_10) $(am__objects_11) \ @@ -468,61 +1341,99 @@ am_src_libcyassl_la_OBJECTS = $(am__objects_1) \ $(am__objects_15) $(am__objects_16) $(am__objects_17) \ $(am__objects_18) $(am__objects_19) $(am__objects_20) \ $(am__objects_21) $(am__objects_22) $(am__objects_23) \ - $(am__objects_24) $(am__objects_25) $(am__objects_26) \ + $(am__objects_24) $(am__objects_25) \ + wolfcrypt/src/src_libwolfssl_la-hash.lo \ + wolfcrypt/src/src_libwolfssl_la-cpuid.lo $(am__objects_26) \ $(am__objects_27) $(am__objects_28) $(am__objects_29) \ $(am__objects_30) $(am__objects_31) $(am__objects_32) \ - $(am__objects_33) -src_libcyassl_la_OBJECTS = $(am_src_libcyassl_la_OBJECTS) + $(am__objects_33) $(am__objects_34) $(am__objects_35) \ + $(am__objects_36) $(am__objects_37) $(am__objects_38) \ + $(am__objects_39) $(am__objects_40) $(am__objects_41) \ + $(am__objects_42) $(am__objects_43) $(am__objects_44) \ + $(am__objects_45) $(am__objects_46) $(am__objects_47) \ + $(am__objects_48) $(am__objects_49) $(am__objects_50) \ + $(am__objects_51) wolfcrypt/src/src_libwolfssl_la-logging.lo \ + wolfcrypt/src/src_libwolfssl_la-wc_port.lo \ + wolfcrypt/src/src_libwolfssl_la-error.lo $(am__objects_52) \ + $(am__objects_53) $(am__objects_54) $(am__objects_55) \ + $(am__objects_56) $(am__objects_57) $(am__objects_58) \ + $(am__objects_59) $(am__objects_60) $(am__objects_61) \ + $(am__objects_62) $(am__objects_63) $(am__objects_64) \ + $(am__objects_65) $(am__objects_66) $(am__objects_67) \ + $(am__objects_68) $(am__objects_69) $(am__objects_70) \ + $(am__objects_71) $(am__objects_72) $(am__objects_73) \ + $(am__objects_74) $(am__objects_75) $(am__objects_76) \ + $(am__objects_77) $(am__objects_78) $(am__objects_79) \ + $(am__objects_80) $(am__objects_81) $(am__objects_82) \ + $(am__objects_83) $(am__objects_84) $(am__objects_85) \ + $(am__objects_86) $(am__objects_87) $(am__objects_88) \ + $(am__objects_89) $(am__objects_90) $(am__objects_91) \ + $(am__objects_92) $(am__objects_93) $(am__objects_94) \ + $(am__objects_95) $(am__objects_96) $(am__objects_97) \ + $(am__objects_98) $(am__objects_99) $(am__objects_100) \ + $(am__objects_101) $(am__objects_102) $(am__objects_103) \ + $(am__objects_104) $(am__objects_105) $(am__objects_106) \ + $(am__objects_107) $(am__objects_108) $(am__objects_109) \ + $(am__objects_110) $(am__objects_111) $(am__objects_112) \ + $(am__objects_113) $(am__objects_114) +src_libwolfssl_la_OBJECTS = $(am_src_libwolfssl_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = -src_libcyassl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ +src_libwolfssl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(src_libcyassl_la_CFLAGS) $(CFLAGS) \ - $(src_libcyassl_la_LDFLAGS) $(LDFLAGS) -o $@ -@BUILD_EXAMPLES_TRUE@am__EXEEXT_1 = testsuite/testsuite.test$(EXEEXT) \ -@BUILD_EXAMPLES_TRUE@ tests/unit.test$(EXEEXT) -@BUILD_MCAPI_TRUE@am__EXEEXT_2 = mcapi/test$(EXEEXT) -@BUILD_EXAMPLES_TRUE@am__EXEEXT_3 = examples/client/client$(EXEEXT) \ -@BUILD_EXAMPLES_TRUE@ examples/server/server$(EXEEXT) \ -@BUILD_EXAMPLES_TRUE@ examples/echoclient/echoclient$(EXEEXT) \ -@BUILD_EXAMPLES_TRUE@ examples/echoserver/echoserver$(EXEEXT) \ -@BUILD_EXAMPLES_TRUE@ testsuite/testsuite.test$(EXEEXT) \ -@BUILD_EXAMPLES_TRUE@ tests/unit.test$(EXEEXT) -@BUILD_SNIFFTEST_TRUE@am__EXEEXT_4 = sslSniffer/sslSnifferTest/snifftest$(EXEEXT) -PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) -am_ctaocrypt_benchmark_benchmark_OBJECTS = \ - ctaocrypt/benchmark/benchmark.$(OBJEXT) -ctaocrypt_benchmark_benchmark_OBJECTS = \ - $(am_ctaocrypt_benchmark_benchmark_OBJECTS) -am_ctaocrypt_test_testctaocrypt_OBJECTS = \ - ctaocrypt/test/test.$(OBJEXT) -ctaocrypt_test_testctaocrypt_OBJECTS = \ - $(am_ctaocrypt_test_testctaocrypt_OBJECTS) + $(src_libwolfssl_la_CFLAGS) $(CFLAGS) \ + $(src_libwolfssl_la_LDFLAGS) $(LDFLAGS) -o $@ +am__examples_benchmark_tls_bench_SOURCES_DIST = \ + examples/benchmark/tls_bench.c +@BUILD_THREADED_EXAMPLES_TRUE@am_examples_benchmark_tls_bench_OBJECTS = examples/benchmark/tls_bench.$(OBJEXT) +examples_benchmark_tls_bench_OBJECTS = \ + $(am_examples_benchmark_tls_bench_OBJECTS) am__examples_client_client_SOURCES_DIST = examples/client/client.c -@BUILD_EXAMPLES_TRUE@am_examples_client_client_OBJECTS = \ -@BUILD_EXAMPLES_TRUE@ examples/client/client.$(OBJEXT) +@BUILD_EXAMPLE_CLIENTS_TRUE@am_examples_client_client_OBJECTS = \ +@BUILD_EXAMPLE_CLIENTS_TRUE@ examples/client/client.$(OBJEXT) examples_client_client_OBJECTS = $(am_examples_client_client_OBJECTS) am__examples_echoclient_echoclient_SOURCES_DIST = \ examples/echoclient/echoclient.c -@BUILD_EXAMPLES_TRUE@am_examples_echoclient_echoclient_OBJECTS = \ -@BUILD_EXAMPLES_TRUE@ examples/echoclient/echoclient.$(OBJEXT) +@BUILD_EXAMPLE_CLIENTS_TRUE@am_examples_echoclient_echoclient_OBJECTS = examples/echoclient/echoclient.$(OBJEXT) examples_echoclient_echoclient_OBJECTS = \ $(am_examples_echoclient_echoclient_OBJECTS) am__examples_echoserver_echoserver_SOURCES_DIST = \ examples/echoserver/echoserver.c -@BUILD_EXAMPLES_TRUE@am_examples_echoserver_echoserver_OBJECTS = \ -@BUILD_EXAMPLES_TRUE@ examples/echoserver/echoserver.$(OBJEXT) +@BUILD_EXAMPLE_SERVERS_TRUE@am_examples_echoserver_echoserver_OBJECTS = examples/echoserver/echoserver.$(OBJEXT) examples_echoserver_echoserver_OBJECTS = \ $(am_examples_echoserver_echoserver_OBJECTS) +am__examples_sctp_sctp_client_SOURCES_DIST = \ + examples/sctp/sctp-client.c +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@am_examples_sctp_sctp_client_OBJECTS = examples/sctp/sctp-client.$(OBJEXT) +examples_sctp_sctp_client_OBJECTS = \ + $(am_examples_sctp_sctp_client_OBJECTS) +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@examples_sctp_sctp_client_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__examples_sctp_sctp_client_dtls_SOURCES_DIST = \ + examples/sctp/sctp-client-dtls.c +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@am_examples_sctp_sctp_client_dtls_OBJECTS = examples/sctp/sctp-client-dtls.$(OBJEXT) +examples_sctp_sctp_client_dtls_OBJECTS = \ + $(am_examples_sctp_sctp_client_dtls_OBJECTS) +am__examples_sctp_sctp_server_SOURCES_DIST = \ + examples/sctp/sctp-server.c +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@am_examples_sctp_sctp_server_OBJECTS = examples/sctp/sctp-server.$(OBJEXT) +examples_sctp_sctp_server_OBJECTS = \ + $(am_examples_sctp_sctp_server_OBJECTS) +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@examples_sctp_sctp_server_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__examples_sctp_sctp_server_dtls_SOURCES_DIST = \ + examples/sctp/sctp-server-dtls.c +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@am_examples_sctp_sctp_server_dtls_OBJECTS = examples/sctp/sctp-server-dtls.$(OBJEXT) +examples_sctp_sctp_server_dtls_OBJECTS = \ + $(am_examples_sctp_sctp_server_dtls_OBJECTS) am__examples_server_server_SOURCES_DIST = examples/server/server.c -@BUILD_EXAMPLES_TRUE@am_examples_server_server_OBJECTS = \ -@BUILD_EXAMPLES_TRUE@ examples/server/server.$(OBJEXT) +@BUILD_EXAMPLE_SERVERS_TRUE@am_examples_server_server_OBJECTS = \ +@BUILD_EXAMPLE_SERVERS_TRUE@ examples/server/server.$(OBJEXT) examples_server_server_OBJECTS = $(am_examples_server_server_OBJECTS) am__mcapi_test_SOURCES_DIST = mcapi/crypto.c mcapi/mcapi_test.c -@BUILD_MCAPI_TRUE@am_mcapi_test_OBJECTS = mcapi/crypto.$(OBJEXT) \ -@BUILD_MCAPI_TRUE@ mcapi/mcapi_test.$(OBJEXT) +@BUILD_DISTRO_FALSE@@BUILD_MCAPI_TRUE@am_mcapi_test_OBJECTS = \ +@BUILD_DISTRO_FALSE@@BUILD_MCAPI_TRUE@ mcapi/crypto.$(OBJEXT) \ +@BUILD_DISTRO_FALSE@@BUILD_MCAPI_TRUE@ mcapi/mcapi_test.$(OBJEXT) mcapi_test_OBJECTS = $(am_mcapi_test_OBJECTS) am__sslSniffer_sslSnifferTest_snifftest_SOURCES_DIST = \ sslSniffer/sslSnifferTest/snifftest.c @@ -530,36 +1441,56 @@ am__sslSniffer_sslSnifferTest_snifftest_SOURCES_DIST = \ sslSniffer_sslSnifferTest_snifftest_OBJECTS = \ $(am_sslSniffer_sslSnifferTest_snifftest_OBJECTS) am__tests_unit_test_SOURCES_DIST = tests/unit.c tests/api.c \ - tests/suites.c tests/hash.c examples/client/client.c \ - examples/server/server.c -@BUILD_EXAMPLES_TRUE@am_tests_unit_test_OBJECTS = \ -@BUILD_EXAMPLES_TRUE@ tests/tests_unit_test-unit.$(OBJEXT) \ -@BUILD_EXAMPLES_TRUE@ tests/tests_unit_test-api.$(OBJEXT) \ -@BUILD_EXAMPLES_TRUE@ tests/tests_unit_test-suites.$(OBJEXT) \ -@BUILD_EXAMPLES_TRUE@ tests/tests_unit_test-hash.$(OBJEXT) \ -@BUILD_EXAMPLES_TRUE@ examples/client/tests_unit_test-client.$(OBJEXT) \ -@BUILD_EXAMPLES_TRUE@ examples/server/tests_unit_test-server.$(OBJEXT) + tests/suites.c tests/hash.c tests/srp.c \ + examples/client/client.c examples/server/server.c +@BUILD_TESTS_TRUE@am_tests_unit_test_OBJECTS = \ +@BUILD_TESTS_TRUE@ tests/unit_test-unit.$(OBJEXT) \ +@BUILD_TESTS_TRUE@ tests/unit_test-api.$(OBJEXT) \ +@BUILD_TESTS_TRUE@ tests/unit_test-suites.$(OBJEXT) \ +@BUILD_TESTS_TRUE@ tests/unit_test-hash.$(OBJEXT) \ +@BUILD_TESTS_TRUE@ tests/unit_test-srp.$(OBJEXT) \ +@BUILD_TESTS_TRUE@ examples/client/tests_unit_test-client.$(OBJEXT) \ +@BUILD_TESTS_TRUE@ examples/server/tests_unit_test-server.$(OBJEXT) tests_unit_test_OBJECTS = $(am_tests_unit_test_OBJECTS) tests_unit_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_unit_test_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -am__testsuite_testsuite_test_SOURCES_DIST = ctaocrypt/test/test.c \ +am__testsuite_testsuite_test_SOURCES_DIST = wolfcrypt/test/test.c \ examples/client/client.c examples/echoclient/echoclient.c \ examples/echoserver/echoserver.c examples/server/server.c \ testsuite/testsuite.c -@BUILD_EXAMPLES_TRUE@am_testsuite_testsuite_test_OBJECTS = ctaocrypt/test/testsuite_testsuite_test-test.$(OBJEXT) \ -@BUILD_EXAMPLES_TRUE@ examples/client/testsuite_testsuite_test-client.$(OBJEXT) \ -@BUILD_EXAMPLES_TRUE@ examples/echoclient/testsuite_testsuite_test-echoclient.$(OBJEXT) \ -@BUILD_EXAMPLES_TRUE@ examples/echoserver/testsuite_testsuite_test-echoserver.$(OBJEXT) \ -@BUILD_EXAMPLES_TRUE@ examples/server/testsuite_testsuite_test-server.$(OBJEXT) \ -@BUILD_EXAMPLES_TRUE@ testsuite/testsuite_testsuite_test-testsuite.$(OBJEXT) +@BUILD_TESTS_TRUE@am_testsuite_testsuite_test_OBJECTS = wolfcrypt/test/testsuite_testsuite_test-test.$(OBJEXT) \ +@BUILD_TESTS_TRUE@ examples/client/testsuite_testsuite_test-client.$(OBJEXT) \ +@BUILD_TESTS_TRUE@ examples/echoclient/testsuite_testsuite_test-echoclient.$(OBJEXT) \ +@BUILD_TESTS_TRUE@ examples/echoserver/testsuite_testsuite_test-echoserver.$(OBJEXT) \ +@BUILD_TESTS_TRUE@ examples/server/testsuite_testsuite_test-server.$(OBJEXT) \ +@BUILD_TESTS_TRUE@ testsuite/testsuite_test-testsuite.$(OBJEXT) testsuite_testsuite_test_OBJECTS = \ $(am_testsuite_testsuite_test_OBJECTS) testsuite_testsuite_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ +am__wolfcrypt_benchmark_benchmark_SOURCES_DIST = \ + wolfcrypt/benchmark/benchmark.c +@BUILD_WOLFCRYPT_TESTS_TRUE@am_wolfcrypt_benchmark_benchmark_OBJECTS = wolfcrypt/benchmark/benchmark.$(OBJEXT) +wolfcrypt_benchmark_benchmark_OBJECTS = \ + $(am_wolfcrypt_benchmark_benchmark_OBJECTS) +am__wolfcrypt_test_testwolfcrypt_SOURCES_DIST = wolfcrypt/test/test.c +@BUILD_WOLFCRYPT_TESTS_TRUE@am_wolfcrypt_test_testwolfcrypt_OBJECTS = \ +@BUILD_WOLFCRYPT_TESTS_TRUE@ wolfcrypt/test/test.$(OBJEXT) +wolfcrypt_test_testwolfcrypt_OBJECTS = \ + $(am_wolfcrypt_test_testwolfcrypt_OBJECTS) +am__dist_noinst_SCRIPTS_DIST = scripts/sniffer-testsuite.test \ + scripts/resume.test scripts/crl-revoked.test \ + scripts/ocsp-stapling.test \ + scripts/ocsp-stapling-with-ca-as-responder.test \ + scripts/ocsp-stapling2.test scripts/psk.test \ + scripts/trusted_peer.test scripts/pkcallbacks.test \ + scripts/tls13.test scripts/external.test scripts/google.test \ + scripts/openssl.test scripts/ocsp.test +SCRIPTS = $(dist_noinst_SCRIPTS) $(noinst_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -574,8 +1505,169 @@ am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = \ + ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Plo \ + ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Plo \ + ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Plo \ + ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Plo \ + ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Plo \ + ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Plo \ + ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo \ + ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Plo \ + ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Plo \ + ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Plo \ + ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Plo \ + ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Plo \ + examples/benchmark/$(DEPDIR)/tls_bench.Po \ + examples/client/$(DEPDIR)/client.Po \ + examples/client/$(DEPDIR)/tests_unit_test-client.Po \ + examples/client/$(DEPDIR)/testsuite_testsuite_test-client.Po \ + examples/echoclient/$(DEPDIR)/echoclient.Po \ + examples/echoclient/$(DEPDIR)/testsuite_testsuite_test-echoclient.Po \ + examples/echoserver/$(DEPDIR)/echoserver.Po \ + examples/echoserver/$(DEPDIR)/testsuite_testsuite_test-echoserver.Po \ + examples/sctp/$(DEPDIR)/sctp-client-dtls.Po \ + examples/sctp/$(DEPDIR)/sctp-client.Po \ + examples/sctp/$(DEPDIR)/sctp-server-dtls.Po \ + examples/sctp/$(DEPDIR)/sctp-server.Po \ + examples/server/$(DEPDIR)/server.Po \ + examples/server/$(DEPDIR)/tests_unit_test-server.Po \ + examples/server/$(DEPDIR)/testsuite_testsuite_test-server.Po \ + mcapi/$(DEPDIR)/crypto.Po mcapi/$(DEPDIR)/mcapi_test.Po \ + src/$(DEPDIR)/libwolfssl_la-crl.Plo \ + src/$(DEPDIR)/libwolfssl_la-internal.Plo \ + src/$(DEPDIR)/libwolfssl_la-keys.Plo \ + src/$(DEPDIR)/libwolfssl_la-ocsp.Plo \ + src/$(DEPDIR)/libwolfssl_la-sniffer.Plo \ + src/$(DEPDIR)/libwolfssl_la-ssl.Plo \ + src/$(DEPDIR)/libwolfssl_la-tls.Plo \ + src/$(DEPDIR)/libwolfssl_la-tls13.Plo \ + src/$(DEPDIR)/libwolfssl_la-wolfio.Plo \ + sslSniffer/sslSnifferTest/$(DEPDIR)/snifftest.Po \ + tests/$(DEPDIR)/unit_test-api.Po \ + tests/$(DEPDIR)/unit_test-hash.Po \ + tests/$(DEPDIR)/unit_test-srp.Po \ + tests/$(DEPDIR)/unit_test-suites.Po \ + tests/$(DEPDIR)/unit_test-unit.Po \ + testsuite/$(DEPDIR)/testsuite_test-testsuite.Po \ + wolfcrypt/benchmark/$(DEPDIR)/benchmark.Po \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_asm.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_gcm_asm.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-arc4.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-asn.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-async.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2b.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2s.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-camellia.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha20_poly1305.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha_asm.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cmac.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-coding.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-compress.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cpuid.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cryptocb.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve25519.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve448.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dh.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dsa.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ecc.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed25519.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed448.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-error.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_448.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_low_mem.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_operations.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_x25519_asm.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_448.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_low_mem.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_operations.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hash.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hc128.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-idea.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-integer.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-logging.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md2.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md4.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md5.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-memory.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-misc.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs12.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs7.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305_asm.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pwdbased.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rabbit.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ripemd.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-selftest.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256_asm.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha3.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512_asm.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-signature.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm32.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm64.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_armthumb.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c32.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c64.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_cortexm.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_int.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64_asm.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-srp.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-tfm.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_encrypt.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_pkcs11.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_port.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfevent.Plo \ + wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfmath.Plo \ + wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_aes.Plo \ + wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_hash.Plo \ + wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-wc_afalg.Plo \ + wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-curve25519.Plo \ + wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-sha512-asm.Plo \ + wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-aes.Plo \ + wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-chacha.Plo \ + wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-curve25519.Plo \ + wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-poly1305.Plo \ + wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha256.Plo \ + wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512-asm.Plo \ + wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512.Plo \ + wolfcrypt/src/port/atmel/$(DEPDIR)/src_libwolfssl_la-atmel.Plo \ + wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_nitrox.Plo \ + wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_octeon_sync.Plo \ + wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_aes.Plo \ + wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_hash.Plo \ + wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-wc_devcrypto.Plo \ + wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist.Plo \ + wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_mem.Plo \ + wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_sync.Plo \ + wolfcrypt/test/$(DEPDIR)/test.Po \ + wolfcrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Po \ + wolfcrypt/user-crypto/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo am__mv = mv -f +CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) +LTCPPASCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CCASFLAGS) $(CCASFLAGS) +AM_V_CPPAS = $(am__v_CPPAS_@AM_V@) +am__v_CPPAS_ = $(am__v_CPPAS_@AM_DEFAULT_V@) +am__v_CPPAS_0 = @echo " CPPAS " $@; +am__v_CPPAS_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ @@ -594,48 +1686,192 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -CCASCOMPILE = $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS) -LTCCASCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(AM_CCASFLAGS) \ - $(CCASFLAGS) -AM_V_CCAS = $(am__v_CCAS_@AM_V@) -am__v_CCAS_ = $(am__v_CCAS_@AM_DEFAULT_V@) -am__v_CCAS_0 = @echo " CCAS " $@; -am__v_CCAS_1 = -SOURCES = $(src_libcyassl_la_SOURCES) \ - $(ctaocrypt_benchmark_benchmark_SOURCES) \ - $(ctaocrypt_test_testctaocrypt_SOURCES) \ +SOURCES = $(src_libwolfssl_la_SOURCES) \ + $(examples_benchmark_tls_bench_SOURCES) \ $(examples_client_client_SOURCES) \ $(examples_echoclient_echoclient_SOURCES) \ $(examples_echoserver_echoserver_SOURCES) \ + $(examples_sctp_sctp_client_SOURCES) \ + $(examples_sctp_sctp_client_dtls_SOURCES) \ + $(examples_sctp_sctp_server_SOURCES) \ + $(examples_sctp_sctp_server_dtls_SOURCES) \ $(examples_server_server_SOURCES) $(mcapi_test_SOURCES) \ $(sslSniffer_sslSnifferTest_snifftest_SOURCES) \ - $(tests_unit_test_SOURCES) $(testsuite_testsuite_test_SOURCES) -DIST_SOURCES = $(am__src_libcyassl_la_SOURCES_DIST) \ - $(ctaocrypt_benchmark_benchmark_SOURCES) \ - $(ctaocrypt_test_testctaocrypt_SOURCES) \ + $(tests_unit_test_SOURCES) $(testsuite_testsuite_test_SOURCES) \ + $(wolfcrypt_benchmark_benchmark_SOURCES) \ + $(wolfcrypt_test_testwolfcrypt_SOURCES) +DIST_SOURCES = $(am__src_libwolfssl_la_SOURCES_DIST) \ + $(am__examples_benchmark_tls_bench_SOURCES_DIST) \ $(am__examples_client_client_SOURCES_DIST) \ $(am__examples_echoclient_echoclient_SOURCES_DIST) \ $(am__examples_echoserver_echoserver_SOURCES_DIST) \ + $(am__examples_sctp_sctp_client_SOURCES_DIST) \ + $(am__examples_sctp_sctp_client_dtls_SOURCES_DIST) \ + $(am__examples_sctp_sctp_server_SOURCES_DIST) \ + $(am__examples_sctp_sctp_server_dtls_SOURCES_DIST) \ $(am__examples_server_server_SOURCES_DIST) \ $(am__mcapi_test_SOURCES_DIST) \ $(am__sslSniffer_sslSnifferTest_snifftest_SOURCES_DIST) \ $(am__tests_unit_test_SOURCES_DIST) \ - $(am__testsuite_testsuite_test_SOURCES_DIST) + $(am__testsuite_testsuite_test_SOURCES_DIST) \ + $(am__wolfcrypt_benchmark_benchmark_SOURCES_DIST) \ + $(am__wolfcrypt_test_testwolfcrypt_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac -DATA = $(dist_doc_DATA) $(dist_example_DATA) $(pkgconfig_DATA) -am__noinst_HEADERS_DIST = cyassl/internal.h ctaocrypt/test/test.h \ - examples/client/client.h examples/server/server.h \ +DATA = $(dist_doc_DATA) $(dist_example_DATA) $(ipp_DATA) \ + $(pkgconfig_DATA) +am__include_HEADERS_DIST = @IPPHEADERS@ \ + wolfcrypt/user-crypto/include/user_rsa.h +am__nobase_include_HEADERS_DIST = cyassl/ctaocrypt/aes.h \ + cyassl/ctaocrypt/arc4.h cyassl/ctaocrypt/asn.h \ + cyassl/ctaocrypt/asn_public.h cyassl/ctaocrypt/poly1305.h \ + cyassl/ctaocrypt/camellia.h cyassl/ctaocrypt/coding.h \ + cyassl/ctaocrypt/compress.h cyassl/ctaocrypt/des3.h \ + cyassl/ctaocrypt/dh.h cyassl/ctaocrypt/dsa.h \ + cyassl/ctaocrypt/ecc.h cyassl/ctaocrypt/error-crypt.h \ + cyassl/ctaocrypt/fips_test.h cyassl/ctaocrypt/hc128.h \ + cyassl/ctaocrypt/hmac.h cyassl/ctaocrypt/integer.h \ + cyassl/ctaocrypt/md2.h cyassl/ctaocrypt/md4.h \ + cyassl/ctaocrypt/md5.h cyassl/ctaocrypt/misc.h \ + cyassl/ctaocrypt/pkcs7.h cyassl/ctaocrypt/wc_port.h \ + cyassl/ctaocrypt/pwdbased.h cyassl/ctaocrypt/rabbit.h \ + cyassl/ctaocrypt/chacha.h cyassl/ctaocrypt/random.h \ + cyassl/ctaocrypt/ripemd.h cyassl/ctaocrypt/rsa.h \ + cyassl/ctaocrypt/settings.h cyassl/ctaocrypt/settings_comp.h \ + cyassl/ctaocrypt/sha256.h cyassl/ctaocrypt/sha512.h \ + cyassl/ctaocrypt/sha.h cyassl/ctaocrypt/blake2.h \ + cyassl/ctaocrypt/blake2-int.h cyassl/ctaocrypt/blake2-impl.h \ + cyassl/ctaocrypt/tfm.h cyassl/ctaocrypt/types.h \ + cyassl/ctaocrypt/visibility.h cyassl/ctaocrypt/logging.h \ + cyassl/ctaocrypt/memory.h cyassl/ctaocrypt/mpi_class.h \ + cyassl/ctaocrypt/mpi_superclass.h cyassl/openssl/asn1.h \ + cyassl/openssl/bio.h cyassl/openssl/bn.h cyassl/openssl/conf.h \ + cyassl/openssl/crypto.h cyassl/openssl/des.h \ + cyassl/openssl/dh.h cyassl/openssl/dsa.h \ + cyassl/openssl/ecdsa.h cyassl/openssl/ecdh.h \ + cyassl/openssl/ec.h cyassl/openssl/ec25519.h \ + cyassl/openssl/ed25519.h cyassl/openssl/ec448.h \ + cyassl/openssl/ed448.h cyassl/openssl/engine.h \ + cyassl/openssl/err.h cyassl/openssl/evp.h \ + cyassl/openssl/hmac.h cyassl/openssl/lhash.h \ + cyassl/openssl/md4.h cyassl/openssl/md5.h \ + cyassl/openssl/ripemd.h cyassl/openssl/ocsp.h \ + cyassl/openssl/opensslconf.h cyassl/openssl/opensslv.h \ + cyassl/openssl/ossl_typ.h cyassl/openssl/pem.h \ + cyassl/openssl/pkcs12.h 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 \ + cyassl/openssl/x509.h cyassl/openssl/x509v3.h \ + cyassl/error-ssl.h cyassl/ssl.h cyassl/sniffer_error.h \ + cyassl/sniffer.h cyassl/callbacks.h cyassl/certs_test.h \ + cyassl/test.h cyassl/version.h cyassl/ocsp.h cyassl/crl.h \ + cyassl/options.h wolfssl/wolfcrypt/aes.h \ + wolfssl/wolfcrypt/arc4.h wolfssl/wolfcrypt/asn.h \ + wolfssl/wolfcrypt/asn_public.h wolfssl/wolfcrypt/poly1305.h \ + wolfssl/wolfcrypt/camellia.h wolfssl/wolfcrypt/cmac.h \ + wolfssl/wolfcrypt/coding.h wolfssl/wolfcrypt/compress.h \ + wolfssl/wolfcrypt/des3.h wolfssl/wolfcrypt/dh.h \ + wolfssl/wolfcrypt/dsa.h wolfssl/wolfcrypt/ecc.h \ + wolfssl/wolfcrypt/curve25519.h wolfssl/wolfcrypt/ed25519.h \ + wolfssl/wolfcrypt/fe_operations.h \ + wolfssl/wolfcrypt/ge_operations.h wolfssl/wolfcrypt/curve448.h \ + wolfssl/wolfcrypt/ed448.h wolfssl/wolfcrypt/fe_448.h \ + wolfssl/wolfcrypt/ge_448.h wolfssl/wolfcrypt/error-crypt.h \ + wolfssl/wolfcrypt/fips_test.h wolfssl/wolfcrypt/hash.h \ + wolfssl/wolfcrypt/hc128.h wolfssl/wolfcrypt/hmac.h \ + wolfssl/wolfcrypt/integer.h wolfssl/wolfcrypt/md2.h \ + wolfssl/wolfcrypt/md4.h wolfssl/wolfcrypt/md5.h \ + wolfssl/wolfcrypt/misc.h wolfssl/wolfcrypt/pkcs7.h \ + wolfssl/wolfcrypt/wc_encrypt.h wolfssl/wolfcrypt/wc_port.h \ + wolfssl/wolfcrypt/pwdbased.h wolfssl/wolfcrypt/rabbit.h \ + wolfssl/wolfcrypt/chacha.h \ + wolfssl/wolfcrypt/chacha20_poly1305.h \ + wolfssl/wolfcrypt/random.h wolfssl/wolfcrypt/ripemd.h \ + wolfssl/wolfcrypt/rsa.h wolfssl/wolfcrypt/settings.h \ + wolfssl/wolfcrypt/sha256.h wolfssl/wolfcrypt/sha512.h \ + wolfssl/wolfcrypt/sha.h wolfssl/wolfcrypt/signature.h \ + wolfssl/wolfcrypt/blake2.h wolfssl/wolfcrypt/blake2-int.h \ + wolfssl/wolfcrypt/blake2-impl.h wolfssl/wolfcrypt/tfm.h \ + wolfssl/wolfcrypt/srp.h wolfssl/wolfcrypt/idea.h \ + wolfssl/wolfcrypt/types.h wolfssl/wolfcrypt/visibility.h \ + wolfssl/wolfcrypt/logging.h wolfssl/wolfcrypt/memory.h \ + wolfssl/wolfcrypt/mpi_class.h \ + wolfssl/wolfcrypt/mpi_superclass.h \ + wolfssl/wolfcrypt/mem_track.h wolfssl/wolfcrypt/wolfevent.h \ + wolfssl/wolfcrypt/pkcs12.h wolfssl/wolfcrypt/wolfmath.h \ + wolfssl/wolfcrypt/sha3.h wolfssl/wolfcrypt/cpuid.h \ + wolfssl/wolfcrypt/cryptocb.h \ + wolfssl/wolfcrypt/port/atmel/atmel.h \ + wolfssl/wolfcrypt/port/af_alg/afalg_hash.h \ + wolfssl/wolfcrypt/port/af_alg/wc_afalg.h \ + wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h \ + wolfssl/wolfcrypt/async.h wolfssl/wolfcrypt/wc_pkcs11.h \ + wolfssl/wolfcrypt/pkcs11.h \ + wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h \ + wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h \ + wolfssl/wolfcrypt/port/intel/quickassist.h \ + wolfssl/wolfcrypt/port/intel/quickassist_mem.h \ + wolfssl/wolfcrypt/port/intel/quickassist_sync.h \ + wolfssl/wolfcrypt/sp.h wolfssl/wolfcrypt/sp_int.h \ + wolfssl/wolfcrypt/selftest.h wolfssl/wolfcrypt/fips.h \ + wolfssl/openssl/asn1.h wolfssl/openssl/asn1t.h \ + wolfssl/openssl/aes.h wolfssl/openssl/bio.h \ + wolfssl/openssl/bn.h wolfssl/openssl/buffer.h \ + wolfssl/openssl/conf.h wolfssl/openssl/crypto.h \ + wolfssl/openssl/des.h wolfssl/openssl/dh.h \ + wolfssl/openssl/dsa.h wolfssl/openssl/ecdsa.h \ + wolfssl/openssl/ecdh.h wolfssl/openssl/ec.h \ + wolfssl/openssl/ec25519.h wolfssl/openssl/ed25519.h \ + wolfssl/openssl/ec448.h wolfssl/openssl/ed448.h \ + wolfssl/openssl/engine.h wolfssl/openssl/err.h \ + wolfssl/openssl/evp.h wolfssl/openssl/hmac.h \ + wolfssl/openssl/lhash.h wolfssl/openssl/md4.h \ + wolfssl/openssl/md5.h wolfssl/openssl/ripemd.h \ + wolfssl/openssl/obj_mac.h wolfssl/openssl/objects.h \ + wolfssl/openssl/ocsp.h wolfssl/openssl/opensslconf.h \ + wolfssl/openssl/opensslv.h wolfssl/openssl/ossl_typ.h \ + wolfssl/openssl/pem.h wolfssl/openssl/pkcs12.h \ + wolfssl/openssl/pkcs7.h wolfssl/openssl/rand.h \ + wolfssl/openssl/rsa.h wolfssl/openssl/sha.h \ + wolfssl/openssl/sha3.h wolfssl/openssl/ssl23.h \ + wolfssl/openssl/ssl.h wolfssl/openssl/stack.h \ + wolfssl/openssl/tls1.h wolfssl/openssl/ui.h \ + wolfssl/openssl/x509.h wolfssl/openssl/x509_vfy.h \ + wolfssl/openssl/x509v3.h wolfssl/openssl/rc4.h \ + wolfssl/error-ssl.h wolfssl/ssl.h wolfssl/sniffer_error.h \ + wolfssl/sniffer.h wolfssl/callbacks.h wolfssl/certs_test.h \ + wolfssl/test.h wolfssl/version.h wolfssl/ocsp.h wolfssl/crl.h \ + wolfssl/wolfio.h wolfssl/options.h +am__noinst_HEADERS_DIST = cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h \ + cyassl/internal.h cyassl/options.h \ + wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \ + wolfssl/wolfcrypt/port/ti/ti-hash.h \ + wolfssl/wolfcrypt/port/ti/ti-ccm.h \ + wolfssl/wolfcrypt/port/nrf51.h \ + wolfssl/wolfcrypt/port/nxp/ksdk_port.h \ + wolfssl/wolfcrypt/port/xilinx/xil-sha3.h \ + wolfssl/wolfcrypt/port/caam/caam_driver.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h \ + wolfssl/wolfcrypt/port/st/stm32.h \ + wolfssl/wolfcrypt/port/st/stsafe.h \ + wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h \ + wolfssl/wolfcrypt/port/arm/cryptoCell.h \ + wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h \ + wolfssl/internal.h wolfssl/options.h \ + wolfcrypt/benchmark/benchmark.h wolfcrypt/test/test.h \ + examples/benchmark/tls_bench.h examples/client/client.h \ examples/echoclient/echoclient.h \ - examples/echoserver/echoserver.h mcapi/crypto.h + examples/echoserver/echoserver.h examples/server/server.h \ + mcapi/crypto.h HEADERS = $(include_HEADERS) $(nobase_include_HEADERS) \ $(noinst_HEADERS) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ - $(LISP)config.in +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ + config.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. @@ -831,6 +2067,104 @@ TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/IDE/ARDUINO/include.am \ + $(srcdir)/IDE/CRYPTOCELL/include.am \ + $(srcdir)/IDE/CSBENCH/include.am \ + $(srcdir)/IDE/ECLIPSE/DEOS/include.am \ + $(srcdir)/IDE/ECLIPSE/MICRIUM/include.am \ + $(srcdir)/IDE/ECLIPSE/SIFIVE/include.am \ + $(srcdir)/IDE/GCC-ARM/include.am \ + $(srcdir)/IDE/HEXAGON/include.am \ + $(srcdir)/IDE/INTIME-RTOS/include.am \ + $(srcdir)/IDE/LINUX-SGX/include.am \ + $(srcdir)/IDE/M68K/include.am \ + $(srcdir)/IDE/OPENSTM32/include.am \ + $(srcdir)/IDE/RISCV/SIFIVE-HIFIVE1/include.am \ + $(srcdir)/IDE/RISCV/SIFIVE-UNLEASHED/include.am \ + $(srcdir)/IDE/RISCV/include.am \ + $(srcdir)/IDE/ROWLEY-CROSSWORKS-ARM/include.am \ + $(srcdir)/IDE/Renesas/cs+/Projects/include.am \ + $(srcdir)/IDE/Renesas/e2studio/DK-S7G2/include.am \ + $(srcdir)/IDE/Renesas/e2studio/Projects/include.am \ + $(srcdir)/IDE/Renesas/e2studio/RA6M3G/include.am \ + $(srcdir)/IDE/TRUESTUDIO/include.am \ + $(srcdir)/IDE/VS-ARM/include.am \ + $(srcdir)/IDE/VS-AZURE-SPHERE/include.am \ + $(srcdir)/IDE/WICED-STUDIO/include.am \ + $(srcdir)/IDE/WIN-SGX/include.am $(srcdir)/IDE/WIN/include.am \ + $(srcdir)/IDE/WIN10/include.am \ + $(srcdir)/IDE/WORKBENCH/include.am \ + $(srcdir)/IDE/XCODE/Benchmark/include.am \ + $(srcdir)/IDE/XCODE/include.am \ + $(srcdir)/IDE/XilinxSDK/include.am $(srcdir)/IDE/include.am \ + $(srcdir)/IDE/mynewt/include.am $(srcdir)/Makefile.in \ + $(srcdir)/certs/1024/include.am \ + $(srcdir)/certs/3072/include.am \ + $(srcdir)/certs/4096/include.am $(srcdir)/certs/crl/include.am \ + $(srcdir)/certs/ecc/include.am \ + $(srcdir)/certs/ed25519/include.am \ + $(srcdir)/certs/ed448/include.am \ + $(srcdir)/certs/external/include.am $(srcdir)/certs/include.am \ + $(srcdir)/certs/intermediate/include.am \ + $(srcdir)/certs/ocsp/include.am \ + $(srcdir)/certs/test-pathlen/include.am \ + $(srcdir)/certs/test/include.am $(srcdir)/config.in \ + $(srcdir)/cyassl/ctaocrypt/include.am \ + $(srcdir)/cyassl/include.am \ + $(srcdir)/cyassl/openssl/include.am $(srcdir)/doc/include.am \ + $(srcdir)/examples/benchmark/include.am \ + $(srcdir)/examples/client/include.am \ + $(srcdir)/examples/echoclient/include.am \ + $(srcdir)/examples/echoserver/include.am \ + $(srcdir)/examples/include.am \ + $(srcdir)/examples/sctp/include.am \ + $(srcdir)/examples/server/include.am \ + $(srcdir)/mcapi/include.am \ + $(srcdir)/mcapi/wolfcrypt_mcapi.X/nbproject/include.am \ + $(srcdir)/mcapi/wolfcrypt_test.X/nbproject/include.am \ + $(srcdir)/mcapi/wolfssl.X/nbproject/include.am \ + $(srcdir)/mcapi/zlib.X/nbproject/include.am \ + $(srcdir)/mplabx/include.am \ + $(srcdir)/mplabx/wolfcrypt_benchmark.X/nbproject/include.am \ + $(srcdir)/mplabx/wolfcrypt_test.X/nbproject/include.am \ + $(srcdir)/mplabx/wolfssl.X/nbproject/include.am \ + $(srcdir)/mqx/util_lib/Sources/include.am \ + $(srcdir)/mqx/wolfcrypt_benchmark/Sources/include.am \ + $(srcdir)/mqx/wolfcrypt_test/Sources/include.am \ + $(srcdir)/mqx/wolfssl/include.am \ + $(srcdir)/mqx/wolfssl_client/Sources/include.am \ + $(srcdir)/rpm/include.am $(srcdir)/scripts/include.am \ + $(srcdir)/src/include.am \ + $(srcdir)/sslSniffer/sslSnifferTest/include.am \ + $(srcdir)/stamp-h.in $(srcdir)/support/include.am \ + $(srcdir)/swig/include.am $(srcdir)/tests/include.am \ + $(srcdir)/testsuite/include.am $(srcdir)/tirtos/include.am \ + $(srcdir)/wolfcrypt/benchmark/include.am \ + $(srcdir)/wolfcrypt/src/include.am \ + $(srcdir)/wolfcrypt/test/include.am \ + $(srcdir)/wolfcrypt/user-crypto/include.am \ + $(srcdir)/wolfssl/include.am \ + $(srcdir)/wolfssl/openssl/include.am \ + $(srcdir)/wolfssl/wolfcrypt/include.am \ + $(srcdir)/wrapper/CSharp/include.am \ + $(srcdir)/wrapper/include.am \ + $(srcdir)/wrapper/python/wolfcrypt/include.am \ + $(srcdir)/wrapper/python/wolfssl/include.am \ + $(top_srcdir)/build-aux/compile \ + $(top_srcdir)/build-aux/config.guess \ + $(top_srcdir)/build-aux/config.sub \ + $(top_srcdir)/build-aux/depcomp \ + $(top_srcdir)/build-aux/install-sh \ + $(top_srcdir)/build-aux/ltmain.sh \ + $(top_srcdir)/build-aux/missing \ + $(top_srcdir)/build-aux/test-driver \ + $(top_srcdir)/cyassl/options.h.in $(top_srcdir)/rpm/spec.in \ + $(top_srcdir)/support/wolfssl.pc.in \ + $(top_srcdir)/wolfssl/options.h.in \ + $(top_srcdir)/wolfssl/version.h.in AUTHORS COPYING INSTALL \ + README build-aux/compile build-aux/config.guess \ + build-aux/config.sub build-aux/depcomp build-aux/install-sh \ + build-aux/ltmain.sh build-aux/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -851,11 +2185,13 @@ distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMINCLUDE = @AMINCLUDE@ AMTAR = @AMTAR@ +AM_CCASFLAGS = @AM_CCASFLAGS@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ AR = @AR@ +AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ @@ -869,11 +2205,6 @@ CFLAGS = @CFLAGS@ CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYASSL_LIBRARY_VERSION = @CYASSL_LIBRARY_VERSION@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ @@ -898,15 +2229,21 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPPHEADERS = @IPPHEADERS@ +IPPLIBS = @IPPLIBS@ +IPPLINK = @IPPLINK@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ +LIB_ADD = @LIB_ADD@ +LIB_STATIC_ADD = @LIB_STATIC_ADD@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MCHECK = @MCHECK@ @@ -934,13 +2271,13 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ +WOLFSSL_LIBRARY_VERSION = @WOLFSSL_LIBRARY_VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ @@ -991,125 +2328,709 @@ top_srcdir = @top_srcdir@ # includes append to these: SUFFIXES = -TESTS = $(check_PROGRAMS) +TESTS = $(check_PROGRAMS) $(check_SCRIPTS) CLEANFILES = cert.der cert.pem certecc.der certecc.pem certreq.der \ - certreq.pem key.der key.pem ntru-cert.der ntru-cert.pem \ - ntru-key.raw othercert.der othercert.pem pkcs7cert.der \ - pkcs7envelopedData.der pkcs7signedData.der -# fips files shouldn't be left after make distclean -DISTCLEANFILES = aminclude.am ctaocrypt/benchmark/.libs/benchmark \ - ctaocrypt/test/.libs/testctaocrypt \ - examples/client/.libs/client examples/server/.libs/server \ + certreq.pem key.der key.pem ntru-cert.der ecc-key-pkcs8.der \ + ntru-cert.pem ntru-key.raw othercert.der othercert.pem \ + pkcs7cert.der pkcs7authEnvelopedDataAES128GCM.der \ + pkcs7authEnvelopedDataAES128GCM_ECDH_SHA1KDF.der \ + pkcs7authEnvelopedDataAES128GCM_KEKRI.der \ + pkcs7authEnvelopedDataAES128GCM_ORI.der \ + pkcs7authEnvelopedDataAES128GCM_PWRI.der \ + pkcs7authEnvelopedDataAES192GCM.der \ + pkcs7authEnvelopedDataAES256GCM.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_authAttribs.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_bothAttribs.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_fw_bothAttribs.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_unauthAttribs.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der \ + pkcs7authEnvelopedDataAES256GCM_firmwarePkgData.der \ + pkcs7authEnvelopedDataAES256GCM_IANDS.der \ + pkcs7authEnvelopedDataAES256GCM_SKID.der \ + pkcs7compressedData_data_zlib.der \ + pkcs7compressedData_firmwarePkgData_zlib.der \ + pkcs7encryptedDataAES128CBC.der \ + pkcs7encryptedDataAES192CBC.der \ + pkcs7encryptedDataAES256CBC_attribs.der \ + pkcs7encryptedDataAES256CBC.der \ + pkcs7encryptedDataAES256CBC_firmwarePkgData.der \ + pkcs7encryptedDataAES256CBC_multi_attribs.der \ + pkcs7encryptedDataDES3.der pkcs7encryptedDataDES.der \ + pkcs7envelopedDataAES256CBC_ECDH.der \ + pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der \ + pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der \ + pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der \ + pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der \ + pkcs7envelopedDataDES3.der pkcs7envelopedDataAES128CBC.der \ + pkcs7envelopedDataAES128CBC_KEKRI.der \ + pkcs7envelopedDataAES128CBC_PWRI.der \ + pkcs7envelopedDataAES128CBC_ORI.der \ + pkcs7envelopedDataAES192CBC.der \ + pkcs7envelopedDataAES256CBC.der \ + pkcs7envelopedDataAES256CBC_IANDS.der \ + pkcs7envelopedDataAES256CBC_SKID.der \ + pkcs7signedData_RSA_SHA.der pkcs7signedData_RSA_SHA_noattr.der \ + pkcs7signedData_RSA_SHA224.der pkcs7signedData_RSA_SHA256.der \ + pkcs7signedData_RSA_SHA256_firmwarePkgData.der \ + pkcs7signedData_RSA_SHA256_custom_contentType.der \ + pkcs7signedData_RSA_SHA256_with_ca_cert.der \ + pkcs7signedData_RSA_SHA256_SKID.der \ + pkcs7signedData_RSA_SHA256_detachedSig.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_SHA256_firmwarePkgData.der \ + pkcs7signedData_ECDSA_SHA256_custom_contentType.der \ + pkcs7signedData_ECDSA_SHA256_SKID.der \ + pkcs7signedData_ECDSA_SHA384.der \ + pkcs7signedData_ECDSA_SHA512.der \ + pkcs7signedFirmwarePkgData_ECDSA_SHA256.der \ + pkcs7signedFirmwarePkgData_ECDSA_SHA256_SKID.der \ + pkcs7signedFirmwarePkgData_ECDSA_SHA256_noattr.der \ + pkcs7signedFirmwarePkgData_RSA_SHA256.der \ + pkcs7signedFirmwarePkgData_RSA_SHA256_SKID.der \ + pkcs7signedFirmwarePkgData_RSA_SHA256_noattr.der \ + pkcs7signedFirmwarePkgData_RSA_SHA256_with_ca_cert.der \ + pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256.der \ + pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der \ + pkcs7signedCompressedFirmwarePkgData_RSA_SHA256.der \ + pkcs7signedCompressedFirmwarePkgData_RSA_SHA256_noattr.der \ + pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256.der \ + pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256_noattr.der \ + pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256.der \ + pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256_noattr.der \ + pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256.der \ + pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der \ + pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256.der \ + pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256_noattr.der +DISTCLEANFILES = aminclude.am wolfcrypt/benchmark/.libs/benchmark \ + wolfcrypt/test/.libs/testwolfcrypt \ + examples/benchmark/.libs/tls_bench \ + examples/client/.libs/client \ examples/echoclient/.libs/echoclient \ examples/echoserver/.libs/echoserver \ + examples/server/.libs/server examples/sctp/.libs/sctp-server \ + examples/sctp/.libs/sctp-server-dtls \ + examples/sctp/.libs/sctp-client \ + examples/sctp/.libs/sctp-client-dtls \ testsuite/.libs/testsuite.test tests/.libs/unit.test \ sslSniffer/sslSnifferTest/.libs/snifftest cyassl-config \ - ctaocrypt/src/fips.c ctaocrypt/src/fips_test.c -noinst_HEADERS = cyassl/internal.h ctaocrypt/test/test.h \ - $(am__append_35) mcapi/crypto.h -lib_LTLIBRARIES = src/libcyassl.la + wolfssl-config +noinst_HEADERS = cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h \ + cyassl/internal.h $(am__append_1) \ + wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \ + wolfssl/wolfcrypt/port/ti/ti-hash.h \ + wolfssl/wolfcrypt/port/ti/ti-ccm.h \ + wolfssl/wolfcrypt/port/nrf51.h \ + wolfssl/wolfcrypt/port/nxp/ksdk_port.h \ + wolfssl/wolfcrypt/port/xilinx/xil-sha3.h \ + wolfssl/wolfcrypt/port/caam/caam_driver.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h \ + wolfssl/wolfcrypt/port/st/stm32.h \ + wolfssl/wolfcrypt/port/st/stsafe.h \ + wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h \ + wolfssl/wolfcrypt/port/arm/cryptoCell.h \ + wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h \ + wolfssl/internal.h $(am__append_16) $(am__append_127) \ + $(am__append_138) $(am__append_140) $(am__append_142) \ + $(am__append_151) +lib_LTLIBRARIES = src/libwolfssl.la man_MANS = noinst_LTLIBRARIES = -include_HEADERS = +include_HEADERS = $(am__append_19) nobase_include_HEADERS = cyassl/ctaocrypt/aes.h \ cyassl/ctaocrypt/arc4.h cyassl/ctaocrypt/asn.h \ - cyassl/ctaocrypt/asn_public.h cyassl/ctaocrypt/camellia.h \ - cyassl/ctaocrypt/coding.h cyassl/ctaocrypt/compress.h \ - cyassl/ctaocrypt/des3.h cyassl/ctaocrypt/dh.h \ - cyassl/ctaocrypt/dsa.h cyassl/ctaocrypt/ecc.h \ - cyassl/ctaocrypt/error-crypt.h cyassl/ctaocrypt/fips_test.h \ - cyassl/ctaocrypt/hc128.h cyassl/ctaocrypt/hmac.h \ - cyassl/ctaocrypt/integer.h cyassl/ctaocrypt/md2.h \ - cyassl/ctaocrypt/md4.h cyassl/ctaocrypt/md5.h \ - cyassl/ctaocrypt/misc.h cyassl/ctaocrypt/pkcs7.h \ - cyassl/ctaocrypt/wc_port.h cyassl/ctaocrypt/pwdbased.h \ - cyassl/ctaocrypt/rabbit.h cyassl/ctaocrypt/random.h \ + cyassl/ctaocrypt/asn_public.h cyassl/ctaocrypt/poly1305.h \ + cyassl/ctaocrypt/camellia.h cyassl/ctaocrypt/coding.h \ + cyassl/ctaocrypt/compress.h cyassl/ctaocrypt/des3.h \ + cyassl/ctaocrypt/dh.h cyassl/ctaocrypt/dsa.h \ + cyassl/ctaocrypt/ecc.h cyassl/ctaocrypt/error-crypt.h \ + cyassl/ctaocrypt/fips_test.h cyassl/ctaocrypt/hc128.h \ + cyassl/ctaocrypt/hmac.h cyassl/ctaocrypt/integer.h \ + cyassl/ctaocrypt/md2.h cyassl/ctaocrypt/md4.h \ + cyassl/ctaocrypt/md5.h cyassl/ctaocrypt/misc.h \ + cyassl/ctaocrypt/pkcs7.h cyassl/ctaocrypt/wc_port.h \ + cyassl/ctaocrypt/pwdbased.h cyassl/ctaocrypt/rabbit.h \ + cyassl/ctaocrypt/chacha.h cyassl/ctaocrypt/random.h \ cyassl/ctaocrypt/ripemd.h cyassl/ctaocrypt/rsa.h \ - cyassl/ctaocrypt/settings.h cyassl/ctaocrypt/sha256.h \ - cyassl/ctaocrypt/sha512.h cyassl/ctaocrypt/sha.h \ - cyassl/ctaocrypt/blake2.h cyassl/ctaocrypt/blake2-int.h \ - cyassl/ctaocrypt/blake2-impl.h cyassl/ctaocrypt/tfm.h \ - cyassl/ctaocrypt/types.h cyassl/ctaocrypt/visibility.h \ - cyassl/ctaocrypt/logging.h cyassl/ctaocrypt/memory.h \ - cyassl/ctaocrypt/mpi_class.h cyassl/ctaocrypt/mpi_superclass.h \ - cyassl/openssl/asn1.h cyassl/openssl/bio.h cyassl/openssl/bn.h \ - cyassl/openssl/conf.h cyassl/openssl/crypto.h \ - cyassl/openssl/des.h cyassl/openssl/dh.h cyassl/openssl/dsa.h \ - cyassl/openssl/ecdsa.h cyassl/openssl/ec.h \ - cyassl/openssl/engine.h cyassl/openssl/err.h \ - cyassl/openssl/evp.h cyassl/openssl/hmac.h \ - cyassl/openssl/lhash.h cyassl/openssl/md4.h \ - cyassl/openssl/md5.h cyassl/openssl/ripemd.h \ - cyassl/openssl/ocsp.h cyassl/openssl/opensslconf.h \ - cyassl/openssl/opensslv.h cyassl/openssl/ossl_typ.h \ - cyassl/openssl/pem.h cyassl/openssl/pkcs12.h \ - cyassl/openssl/rand.h cyassl/openssl/rsa.h \ - cyassl/openssl/sha.h cyassl/openssl/ssl.h \ + cyassl/ctaocrypt/settings.h cyassl/ctaocrypt/settings_comp.h \ + cyassl/ctaocrypt/sha256.h cyassl/ctaocrypt/sha512.h \ + cyassl/ctaocrypt/sha.h cyassl/ctaocrypt/blake2.h \ + cyassl/ctaocrypt/blake2-int.h cyassl/ctaocrypt/blake2-impl.h \ + cyassl/ctaocrypt/tfm.h cyassl/ctaocrypt/types.h \ + cyassl/ctaocrypt/visibility.h cyassl/ctaocrypt/logging.h \ + cyassl/ctaocrypt/memory.h cyassl/ctaocrypt/mpi_class.h \ + cyassl/ctaocrypt/mpi_superclass.h cyassl/openssl/asn1.h \ + cyassl/openssl/bio.h cyassl/openssl/bn.h cyassl/openssl/conf.h \ + cyassl/openssl/crypto.h cyassl/openssl/des.h \ + cyassl/openssl/dh.h cyassl/openssl/dsa.h \ + cyassl/openssl/ecdsa.h cyassl/openssl/ecdh.h \ + cyassl/openssl/ec.h cyassl/openssl/ec25519.h \ + cyassl/openssl/ed25519.h cyassl/openssl/ec448.h \ + cyassl/openssl/ed448.h cyassl/openssl/engine.h \ + cyassl/openssl/err.h cyassl/openssl/evp.h \ + cyassl/openssl/hmac.h cyassl/openssl/lhash.h \ + cyassl/openssl/md4.h cyassl/openssl/md5.h \ + cyassl/openssl/ripemd.h cyassl/openssl/ocsp.h \ + cyassl/openssl/opensslconf.h cyassl/openssl/opensslv.h \ + cyassl/openssl/ossl_typ.h cyassl/openssl/pem.h \ + cyassl/openssl/pkcs12.h 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 \ cyassl/openssl/x509.h cyassl/openssl/x509v3.h \ cyassl/error-ssl.h cyassl/ssl.h cyassl/sniffer_error.h \ cyassl/sniffer.h cyassl/callbacks.h cyassl/certs_test.h \ - cyassl/test.h cyassl/version.h cyassl/options.h cyassl/ocsp.h \ - cyassl/crl.h + cyassl/test.h cyassl/version.h cyassl/ocsp.h cyassl/crl.h \ + $(am__append_2) wolfssl/wolfcrypt/aes.h \ + wolfssl/wolfcrypt/arc4.h wolfssl/wolfcrypt/asn.h \ + wolfssl/wolfcrypt/asn_public.h wolfssl/wolfcrypt/poly1305.h \ + wolfssl/wolfcrypt/camellia.h wolfssl/wolfcrypt/cmac.h \ + wolfssl/wolfcrypt/coding.h wolfssl/wolfcrypt/compress.h \ + wolfssl/wolfcrypt/des3.h wolfssl/wolfcrypt/dh.h \ + wolfssl/wolfcrypt/dsa.h wolfssl/wolfcrypt/ecc.h \ + wolfssl/wolfcrypt/curve25519.h wolfssl/wolfcrypt/ed25519.h \ + wolfssl/wolfcrypt/fe_operations.h \ + wolfssl/wolfcrypt/ge_operations.h wolfssl/wolfcrypt/curve448.h \ + wolfssl/wolfcrypt/ed448.h wolfssl/wolfcrypt/fe_448.h \ + wolfssl/wolfcrypt/ge_448.h wolfssl/wolfcrypt/error-crypt.h \ + wolfssl/wolfcrypt/fips_test.h wolfssl/wolfcrypt/hash.h \ + wolfssl/wolfcrypt/hc128.h wolfssl/wolfcrypt/hmac.h \ + wolfssl/wolfcrypt/integer.h wolfssl/wolfcrypt/md2.h \ + wolfssl/wolfcrypt/md4.h wolfssl/wolfcrypt/md5.h \ + wolfssl/wolfcrypt/misc.h wolfssl/wolfcrypt/pkcs7.h \ + wolfssl/wolfcrypt/wc_encrypt.h wolfssl/wolfcrypt/wc_port.h \ + wolfssl/wolfcrypt/pwdbased.h wolfssl/wolfcrypt/rabbit.h \ + wolfssl/wolfcrypt/chacha.h \ + wolfssl/wolfcrypt/chacha20_poly1305.h \ + wolfssl/wolfcrypt/random.h wolfssl/wolfcrypt/ripemd.h \ + wolfssl/wolfcrypt/rsa.h wolfssl/wolfcrypt/settings.h \ + wolfssl/wolfcrypt/sha256.h wolfssl/wolfcrypt/sha512.h \ + wolfssl/wolfcrypt/sha.h wolfssl/wolfcrypt/signature.h \ + wolfssl/wolfcrypt/blake2.h wolfssl/wolfcrypt/blake2-int.h \ + wolfssl/wolfcrypt/blake2-impl.h wolfssl/wolfcrypt/tfm.h \ + wolfssl/wolfcrypt/srp.h wolfssl/wolfcrypt/idea.h \ + wolfssl/wolfcrypt/types.h wolfssl/wolfcrypt/visibility.h \ + wolfssl/wolfcrypt/logging.h wolfssl/wolfcrypt/memory.h \ + wolfssl/wolfcrypt/mpi_class.h \ + wolfssl/wolfcrypt/mpi_superclass.h \ + wolfssl/wolfcrypt/mem_track.h wolfssl/wolfcrypt/wolfevent.h \ + wolfssl/wolfcrypt/pkcs12.h wolfssl/wolfcrypt/wolfmath.h \ + wolfssl/wolfcrypt/sha3.h wolfssl/wolfcrypt/cpuid.h \ + wolfssl/wolfcrypt/cryptocb.h $(am__append_3) $(am__append_4) \ + $(am__append_5) $(am__append_6) $(am__append_7) \ + $(am__append_8) $(am__append_9) $(am__append_10) \ + $(am__append_11) $(am__append_12) $(am__append_13) \ + $(am__append_14) $(am__append_15) wolfssl/openssl/asn1.h \ + wolfssl/openssl/asn1t.h wolfssl/openssl/aes.h \ + wolfssl/openssl/bio.h wolfssl/openssl/bn.h \ + wolfssl/openssl/buffer.h wolfssl/openssl/conf.h \ + wolfssl/openssl/crypto.h wolfssl/openssl/des.h \ + wolfssl/openssl/dh.h wolfssl/openssl/dsa.h \ + wolfssl/openssl/ecdsa.h wolfssl/openssl/ecdh.h \ + wolfssl/openssl/ec.h wolfssl/openssl/ec25519.h \ + wolfssl/openssl/ed25519.h wolfssl/openssl/ec448.h \ + wolfssl/openssl/ed448.h wolfssl/openssl/engine.h \ + wolfssl/openssl/err.h wolfssl/openssl/evp.h \ + wolfssl/openssl/hmac.h wolfssl/openssl/lhash.h \ + wolfssl/openssl/md4.h wolfssl/openssl/md5.h \ + wolfssl/openssl/ripemd.h wolfssl/openssl/obj_mac.h \ + wolfssl/openssl/objects.h wolfssl/openssl/ocsp.h \ + wolfssl/openssl/opensslconf.h wolfssl/openssl/opensslv.h \ + wolfssl/openssl/ossl_typ.h wolfssl/openssl/pem.h \ + wolfssl/openssl/pkcs12.h wolfssl/openssl/pkcs7.h \ + wolfssl/openssl/rand.h wolfssl/openssl/rsa.h \ + wolfssl/openssl/sha.h wolfssl/openssl/sha3.h \ + wolfssl/openssl/ssl23.h wolfssl/openssl/ssl.h \ + wolfssl/openssl/stack.h wolfssl/openssl/tls1.h \ + wolfssl/openssl/ui.h wolfssl/openssl/x509.h \ + wolfssl/openssl/x509_vfy.h wolfssl/openssl/x509v3.h \ + wolfssl/openssl/rc4.h wolfssl/error-ssl.h wolfssl/ssl.h \ + wolfssl/sniffer_error.h wolfssl/sniffer.h wolfssl/callbacks.h \ + wolfssl/certs_test.h wolfssl/test.h wolfssl/version.h \ + wolfssl/ocsp.h wolfssl/crl.h wolfssl/wolfio.h $(am__append_17) EXTRA_HEADERS = BUILT_SOURCES = -EXTRA_DIST = lib/dummy cyassl-ntru.vcproj cyassl.vcproj cyassl.vcxproj \ - cyassl-iphone.xcodeproj/project.pbxproj \ - cyassl-ios.xcodeproj/project.pbxproj cyassl-ntru.sln \ - cyassl.sln cyassl64.sln valgrind-error.sh gencertbuf.pl IDE \ - cyassl/sniffer_error.rc certs/ca-cert.pem certs/ca-key.pem \ - certs/client-cert.pem certs/client-keyEnc.pem \ - certs/client-key.pem certs/ecc-key.pem certs/ecc-keyPkcs8.pem \ - certs/ecc-client-key.pem certs/client-ecc-cert.pem \ - certs/ntru-cert.pem certs/dh2048.pem certs/server-cert.pem \ - certs/server-ecc.pem certs/server-ecc-rsa.pem \ - certs/server-keyEnc.pem certs/server-key.pem \ + +# wolfSSL CSharp wrapper files + +# ECC CA prime256v1 + +# ECC CA SECP384R1 + +# Intermediate cert CRL's + +# The certs/server-cert with the last byte (signature byte) changed + +# user crypto plug in example + +# leave openssl.test as extra until non bash works + +# for use with wolfssl-x.x.x-commercial-fips-stm32l4-v2 +EXTRA_DIST = lib/dummy wolfssl-ntru.vcproj wolfssl.vcproj \ + wolfssl.vcxproj wolfssl-ntru.sln wolfssl.sln wolfssl64.sln \ + valgrind-error.sh fips-hash.sh gencertbuf.pl README.md README \ + ChangeLog.md LICENSING INSTALL IPP LPCExpresso.cproject \ + LPCExpresso.project resource.h wolfssl.rc \ + wrapper/python/wolfcrypt/.gitignore \ + wrapper/python/wolfcrypt/docs/asymmetric.rst \ + wrapper/python/wolfcrypt/docs/conf.py \ + wrapper/python/wolfcrypt/docs/digest.rst \ + wrapper/python/wolfcrypt/docs/index.rst \ + wrapper/python/wolfcrypt/docs/mac.rst \ + wrapper/python/wolfcrypt/docs/Makefile \ + wrapper/python/wolfcrypt/docs/random.rst \ + wrapper/python/wolfcrypt/docs/symmetric.rst \ + wrapper/python/wolfcrypt/LICENSING.rst \ + wrapper/python/wolfcrypt/MANIFEST.in \ + wrapper/python/wolfcrypt/README.rst \ + wrapper/python/wolfcrypt/requirements-testing.txt \ + wrapper/python/wolfcrypt/setup.py \ + wrapper/python/wolfcrypt/test/test_ciphers.py \ + wrapper/python/wolfcrypt/test/test_hashes.py \ + wrapper/python/wolfcrypt/test/test_random.py \ + wrapper/python/wolfcrypt/tox.ini \ + wrapper/python/wolfcrypt/wolfcrypt/__about__.py \ + wrapper/python/wolfcrypt/wolfcrypt/__init__.py \ + wrapper/python/wolfcrypt/wolfcrypt/build_ffi.py \ + wrapper/python/wolfcrypt/wolfcrypt/ciphers.py \ + wrapper/python/wolfcrypt/wolfcrypt/exceptions.py \ + wrapper/python/wolfcrypt/wolfcrypt/hashes.py \ + wrapper/python/wolfcrypt/wolfcrypt/random.py \ + wrapper/python/wolfcrypt/wolfcrypt/utils.py \ + wrapper/python/wolfssl/.gitignore \ + wrapper/python/wolfssl/docs/api.rst \ + wrapper/python/wolfssl/docs/conf.py \ + wrapper/python/wolfssl/docs/examples.rst \ + wrapper/python/wolfssl/docs/index.rst \ + wrapper/python/wolfssl/docs/installation.rst \ + wrapper/python/wolfssl/docs/Makefile \ + wrapper/python/wolfssl/docs/licensing.rst \ + wrapper/python/wolfssl/docs/requirements.txt \ + wrapper/python/wolfssl/docs/usage.rst \ + wrapper/python/wolfssl/examples/client.py \ + wrapper/python/wolfssl/examples/server.py \ + wrapper/python/wolfssl/test/conftest.py \ + wrapper/python/wolfssl/test/test_client.py \ + wrapper/python/wolfssl/test/test_context.py \ + wrapper/python/wolfssl/test/test_methods.py \ + wrapper/python/wolfssl/src/wolfssl/__about__.py \ + wrapper/python/wolfssl/src/wolfssl/__init__.py \ + wrapper/python/wolfssl/src/wolfssl/build_ffi.py \ + wrapper/python/wolfssl/src/wolfssl/_memory.py \ + wrapper/python/wolfssl/src/wolfssl/_methods.py \ + wrapper/python/wolfssl/src/wolfssl/exceptions.py \ + wrapper/python/wolfssl/src/wolfssl/utils.py \ + wrapper/python/wolfssl/LICENSING.rst \ + wrapper/python/wolfssl/Makefile \ + wrapper/python/wolfssl/MANIFEST.in \ + wrapper/python/wolfssl/README.rst \ + wrapper/python/wolfssl/requirements-testing.txt \ + wrapper/python/wolfssl/setup.py wrapper/python/wolfssl/tox.ini \ + wrapper/python/wolfssl/Vagrantfile \ + wrapper/python/wolfssl/.centos-provisioner.sh \ + wrapper/python/wolfssl/.ubuntu-provisioner.sh \ + wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config \ + wrapper/CSharp/wolfSSL-DTLS-PSK-Server/Properties/AssemblyInfo.cs \ + wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.cs \ + wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.csproj \ + wrapper/CSharp/wolfSSL-DTLS-Server/App.config \ + wrapper/CSharp/wolfSSL-DTLS-Server/Properties/AssemblyInfo.cs \ + wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.cs \ + wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.csproj \ + wrapper/CSharp/wolfSSL-TLS-PSK-Server/App.config \ + wrapper/CSharp/wolfSSL-TLS-PSK-Server/Properties/AssemblyInfo.cs \ + wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.cs \ + wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.csproj \ + wrapper/CSharp/wolfSSL-TLS-Server/App.config \ + wrapper/CSharp/wolfSSL-TLS-Server/Properties/AssemblyInfo.cs \ + wrapper/CSharp/wolfSSL-TLS-Server/Properties/Settings.Designer.cs \ + wrapper/CSharp/wolfSSL-TLS-Server/Properties/Settings.settings \ + wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs \ + wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.csproj \ + wrapper/CSharp/wolfSSL-TLS-ServerThreaded/App.config \ + wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/AssemblyInfo.cs \ + wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/Settings.Designer.cs \ + wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/Settings.settings \ + wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.cs \ + wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.csproj \ + wrapper/CSharp/wolfSSL-Example-IOCallbacks/App.config \ + wrapper/CSharp/wolfSSL-Example-IOCallbacks/Properties/AssemblyInfo.cs \ + wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs \ + wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.csproj \ + wrapper/CSharp/wolfSSL_CSharp.sln \ + wrapper/CSharp/wolfSSL_CSharp/Properties/AssemblyInfo.cs \ + wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.Designer.cs \ + wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.resx \ + wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs \ + wrapper/CSharp/wolfSSL_CSharp/wolfSSL_CSharp.csproj \ + wrapper/CSharp/wolfSSL-TLS-Client/App.config \ + wrapper/CSharp/wolfSSL-TLS-Client/Properties/AssemblyInfo.cs \ + wrapper/CSharp/wolfSSL-TLS-Client/Properties/Settings.Designer.cs \ + wrapper/CSharp/wolfSSL-TLS-Client/Properties/Settings.settings \ + wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs \ + wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.csproj \ + ctaocrypt/src/misc.c cyassl/sniffer_error.rc \ + wolfssl/sniffer_error.rc certs/ca-cert-chain.der \ + certs/ca-cert.pem certs/ca-key.pem certs/client-cert.pem \ + certs/client-keyEnc.pem certs/client-key.pem \ + certs/client-uri-cert.pem certs/client-relative-uri.pem \ + certs/ecc-key.pem certs/ecc-privkey.pem \ + certs/ecc-privkeyPkcs8.der certs/ecc-privkeyPkcs8.pem \ + certs/ecc-keyPkcs8Enc.pem certs/ecc-keyPkcs8Enc.der \ + certs/ecc-key-comp.pem certs/ecc-keyPkcs8.pem \ + certs/ecc-keyPkcs8.der certs/ecc-client-key.pem \ + certs/ecc-client-keyPub.pem certs/client-ecc-cert.pem \ + certs/client-ca.pem certs/ntru-cert.pem certs/dh2048.pem \ + certs/server-cert.pem certs/server-ecc.pem \ + certs/server-ecc-self.pem certs/server-ecc-comp.pem \ + certs/server-ecc-rsa.pem certs/server-keyEnc.pem \ + certs/server-key.pem certs/server-keyPkcs8.der \ certs/server-keyPkcs8Enc12.pem certs/server-keyPkcs8Enc2.pem \ - certs/server-keyPkcs8Enc.pem certs/server-keyPkcs8.pem \ - certs/ca-key.der certs/ca-cert.der certs/client-cert.der \ - certs/client-key.der certs/dh2048.der certs/rsa2048.der \ - certs/dsa2048.der certs/ecc-key.der certs/server-key.der \ - certs/server-cert.der certs/ntru-key.raw \ + certs/server-keyPkcs8Enc.pem certs/server-keyPkcs8Enc.der \ + certs/server-keyPkcs8.pem certs/server-revoked-cert.pem \ + certs/server-revoked-key.pem certs/wolfssl-website-ca.pem \ + certs/test-degenerate.p7b certs/test-ber-exp02-05-2022.p7b \ + certs/test-servercert.p12 certs/ecc-rsa-server.p12 \ + certs/dsaparams.pem certs/ecc-privOnlyKey.pem \ + certs/ecc-privOnlyCert.pem certs/dh3072.pem certs/dh4096.pem \ + certs/client-cert-ext.pem certs/ca-key.der certs/ca-cert.der \ + certs/client-cert.der certs/client-key.der \ + certs/client-ecc-cert.der certs/client-keyPub.der \ + certs/dh2048.der certs/dh3072.der certs/dh4096.der \ + certs/rsa2048.der certs/rsa-pub-2048.pem certs/rsa3072.der \ + certs/dsa2048.der certs/dsa3072.der certs/ecc-client-key.der \ + certs/ecc-client-keyPub.der certs/ecc-key.der \ + certs/ecc-keyPub.der certs/server-key.der \ + certs/server-cert.der certs/server-ecc-comp.der \ + certs/server-ecc.der certs/server-ecc-self.der \ + certs/server-ecc-rsa.der certs/server-cert-chain.der \ + certs/client-cert-ext.der certs/ca-ecc-cert.der \ + certs/ca-ecc-cert.pem certs/ca-ecc-key.der \ + certs/ca-ecc-key.pem certs/ca-ecc384-cert.der \ + certs/ca-ecc384-cert.pem certs/ca-ecc384-key.der \ + certs/ca-ecc384-key.pem certs/ntru-key.raw \ + certs/1024/ca-cert.pem certs/1024/ca-key.pem \ certs/1024/client-cert.pem certs/1024/client-key.pem \ certs/1024/dh1024.pem certs/1024/dsa1024.pem \ - certs/1024/client-cert.der certs/1024/client-key.der \ + certs/1024/dsa-pub-1024.pem certs/1024/server-cert.pem \ + certs/1024/server-key.pem certs/1024/ca-cert.der \ + certs/1024/ca-key.der certs/1024/client-cert.der \ + certs/1024/client-key.der certs/1024/client-keyPub.der \ certs/1024/dh1024.der certs/1024/dsa1024.der \ - certs/1024/rsa1024.der certs/crl/crl.pem certs/crl/cliCrl.pem \ - certs/crl/eccSrvCRL.pem certs/crl/eccCliCRL.pem \ - certs/crl/crl.revoked swig/PythonBuild.sh swig/README \ - swig/cyassl.i swig/cyassl_adds.c swig/python_cyassl.vcproj \ - swig/rsasign.py swig/runme.py support/cyassl.pc \ - ctaocrypt/benchmark/benchmark.sln \ - ctaocrypt/benchmark/benchmark.vcproj ctaocrypt/src/misc.c \ - ctaocrypt/src/asm.c ctaocrypt/src/aes_asm.asm \ - ctaocrypt/src/ecc_fp.c ctaocrypt/src/fp_mont_small.i \ - ctaocrypt/src/fp_mul_comba_12.i \ - ctaocrypt/src/fp_mul_comba_17.i \ - ctaocrypt/src/fp_mul_comba_20.i \ - ctaocrypt/src/fp_mul_comba_24.i \ - ctaocrypt/src/fp_mul_comba_28.i \ - ctaocrypt/src/fp_mul_comba_32.i ctaocrypt/src/fp_mul_comba_3.i \ - ctaocrypt/src/fp_mul_comba_48.i ctaocrypt/src/fp_mul_comba_4.i \ - ctaocrypt/src/fp_mul_comba_64.i ctaocrypt/src/fp_mul_comba_6.i \ - ctaocrypt/src/fp_mul_comba_7.i ctaocrypt/src/fp_mul_comba_8.i \ - ctaocrypt/src/fp_mul_comba_9.i \ - ctaocrypt/src/fp_mul_comba_small_set.i \ - ctaocrypt/src/fp_sqr_comba_12.i \ - ctaocrypt/src/fp_sqr_comba_17.i \ - ctaocrypt/src/fp_sqr_comba_20.i \ - ctaocrypt/src/fp_sqr_comba_24.i \ - ctaocrypt/src/fp_sqr_comba_28.i \ - ctaocrypt/src/fp_sqr_comba_32.i ctaocrypt/src/fp_sqr_comba_3.i \ - ctaocrypt/src/fp_sqr_comba_48.i ctaocrypt/src/fp_sqr_comba_4.i \ - ctaocrypt/src/fp_sqr_comba_64.i ctaocrypt/src/fp_sqr_comba_6.i \ - ctaocrypt/src/fp_sqr_comba_7.i ctaocrypt/src/fp_sqr_comba_8.i \ - ctaocrypt/src/fp_sqr_comba_9.i \ - ctaocrypt/src/fp_sqr_comba_small_set.i ctaocrypt/test/test.sln \ - ctaocrypt/test/test.vcproj examples/client/client.sln \ - examples/client/client-ntru.vcproj \ + certs/1024/rsa1024.der certs/1024/server-cert.der \ + certs/1024/server-key.der certs/3072/client-cert.der \ + certs/3072/client-cert.pem certs/3072/client-key.der \ + certs/3072/client-key.pem certs/3072/client-keyPub.der \ + certs/4096/client-cert.pem certs/4096/client-key.pem \ + certs/4096/client-cert.der certs/4096/client-key.der \ + certs/4096/client-keyPub.der certs/crl/crl.pem \ + certs/crl/cliCrl.pem certs/crl/eccSrvCRL.pem \ + certs/crl/eccCliCRL.pem certs/crl/crl2.pem \ + certs/crl/caEccCrl.pem certs/crl/caEcc384Crl.pem \ + certs/crl/wolfssl.cnf certs/crl/crl.revoked \ + certs/crl/ca-int.pem certs/crl/client-int.pem \ + certs/crl/server-int.pem certs/crl/ca-int-ecc.pem \ + certs/crl/client-int-ecc.pem certs/crl/server-int-ecc.pem \ + certs/ecc/genecc.sh certs/ecc/wolfssl.cnf \ + certs/ecc/wolfssl_384.cnf certs/ed25519/ca-ed25519.der \ + certs/ed25519/ca-ed25519.pem certs/ed25519/ca-ed25519-key.der \ + certs/ed25519/ca-ed25519-key.pem \ + certs/ed25519/ca-ed25519-priv.der \ + certs/ed25519/ca-ed25519-priv.pem \ + certs/ed25519/client-ed25519.der \ + certs/ed25519/client-ed25519.pem \ + certs/ed25519/client-ed25519-key.der \ + certs/ed25519/client-ed25519-key.pem \ + certs/ed25519/client-ed25519-priv.der \ + certs/ed25519/client-ed25519-priv.pem \ + certs/ed25519/root-ed25519.der certs/ed25519/root-ed25519.pem \ + certs/ed25519/root-ed25519-key.der \ + certs/ed25519/root-ed25519-key.pem \ + certs/ed25519/root-ed25519-priv.der \ + certs/ed25519/root-ed25519-priv.pem \ + certs/ed25519/server-ed25519.der \ + certs/ed25519/server-ed25519.pem \ + certs/ed25519/server-ed25519-cert.pem \ + certs/ed25519/server-ed25519-key.der \ + certs/ed25519/server-ed25519-key.pem \ + certs/ed25519/server-ed25519-priv.der \ + certs/ed25519/server-ed25519-priv.pem certs/ed448/ca-ed448.der \ + certs/ed448/ca-ed448.pem certs/ed448/ca-ed448-key.der \ + certs/ed448/ca-ed448-key.pem certs/ed448/ca-ed448-priv.der \ + certs/ed448/ca-ed448-priv.pem certs/ed448/client-ed448.der \ + certs/ed448/client-ed448.pem certs/ed448/client-ed448-key.der \ + certs/ed448/client-ed448-key.pem \ + certs/ed448/client-ed448-priv.der \ + certs/ed448/client-ed448-priv.pem certs/ed448/root-ed448.der \ + certs/ed448/root-ed448.pem certs/ed448/root-ed448-key.der \ + certs/ed448/root-ed448-key.pem certs/ed448/root-ed448-priv.der \ + certs/ed448/root-ed448-priv.pem certs/ed448/server-ed448.der \ + certs/ed448/server-ed448.pem certs/ed448/server-ed448-cert.pem \ + certs/ed448/server-ed448-key.der \ + certs/ed448/server-ed448-key.pem \ + certs/ed448/server-ed448-priv.der \ + certs/ed448/server-ed448-priv.pem \ + certs/external/ca-globalsign-root.pem \ + certs/external/ca-google-root.pem \ + certs/external/ca-digicert-ev.pem \ + certs/external/baltimore-cybertrust-root.pem \ + certs/ocsp/index-ca-and-intermediate-cas.txt \ + certs/ocsp/index-ca-and-intermediate-cas.txt.attr \ + certs/ocsp/index-intermediate1-ca-issued-certs.txt \ + certs/ocsp/index-intermediate1-ca-issued-certs.txt.attr \ + certs/ocsp/index-intermediate2-ca-issued-certs.txt \ + certs/ocsp/index-intermediate2-ca-issued-certs.txt.attr \ + certs/ocsp/index-intermediate3-ca-issued-certs.txt \ + certs/ocsp/index-intermediate3-ca-issued-certs.txt.attr \ + certs/ocsp/openssl.cnf certs/ocsp/renewcerts-for-test.sh \ + certs/ocsp/intermediate1-ca-key.pem \ + certs/ocsp/intermediate1-ca-cert.pem \ + certs/ocsp/intermediate2-ca-key.pem \ + certs/ocsp/intermediate2-ca-cert.pem \ + certs/ocsp/intermediate3-ca-key.pem \ + certs/ocsp/intermediate3-ca-cert.pem \ + certs/ocsp/ocsp-responder-key.pem \ + certs/ocsp/ocsp-responder-cert.pem certs/ocsp/server1-key.pem \ + certs/ocsp/server1-cert.pem certs/ocsp/server2-key.pem \ + certs/ocsp/server2-cert.pem certs/ocsp/server3-key.pem \ + certs/ocsp/server3-cert.pem certs/ocsp/server4-key.pem \ + certs/ocsp/server4-cert.pem certs/ocsp/server5-key.pem \ + certs/ocsp/server5-cert.pem certs/ocsp/root-ca-key.pem \ + certs/ocsp/root-ca-cert.pem certs/test/cert-ext-ia.cfg \ + certs/test/cert-ext-ia.der certs/test/cert-ext-nc.cfg \ + certs/test/cert-ext-nc.der certs/test/cert-ext-nct.cfg \ + certs/test/cert-ext-nct.der certs/test/cert-ext-ns.der \ + certs/test/gen-ext-certs.sh \ + certs/test/server-duplicate-policy.pem \ + certs/test/cert-ext-joi.pem \ + certs/test/server-cert-rsa-badsig.der \ + certs/test/server-cert-rsa-badsig.pem \ + certs/test/server-cert-ecc-badsig.der \ + certs/test/server-cert-ecc-badsig.pem \ + certs/test/gen-testcerts.sh certs/test/server-garbage.der \ + certs/test/server-garbage.pem certs/test/server-goodcn.pem \ + certs/test/server-goodcn.der certs/test/server-goodalt.pem \ + certs/test/server-goodalt.der certs/test/server-goodcnwild.pem \ + certs/test/server-goodcnwild.der \ + certs/test/server-goodaltwild.pem \ + certs/test/server-goodaltwild.der \ + certs/test/server-badcnnull.pem \ + certs/test/server-badcnnull.der certs/test/server-badcn.pem \ + certs/test/server-badcn.der certs/test/server-badaltnull.pem \ + certs/test/server-badaltnull.der \ + certs/test/server-badaltname.der \ + certs/test/server-badaltname.pem \ + certs/test/server-localhost.der \ + certs/test/server-localhost.pem \ + certs/crl/server-goodaltCrl.pem certs/crl/server-goodcnCrl.pem \ + certs/crl/server-goodaltwildCrl.pem \ + certs/crl/server-goodcnwildCrl.pem certs/test/crit-cert.pem \ + certs/test/crit-key.pem certs/test/dh1024.der \ + certs/test/dh1024.pem certs/test/dh512.der \ + certs/test/dh512.pem certs/test/digsigku.pem \ + certs/test/expired/expired-ca.pem \ + certs/test/expired/expired-ca.der \ + certs/test/expired/expired-cert.pem \ + certs/test/expired/expired-cert.der \ + certs/test-pathlen/chainA-ICA1-key.pem \ + certs/test-pathlen/chainA-ICA1-pathlen0.pem \ + certs/test-pathlen/chainA-assembled.pem \ + certs/test-pathlen/chainA-entity-key.pem \ + certs/test-pathlen/chainA-entity.pem \ + certs/test-pathlen/chainB-ICA1-key.pem \ + certs/test-pathlen/chainB-ICA1-pathlen0.pem \ + certs/test-pathlen/chainB-ICA2-key.pem \ + certs/test-pathlen/chainB-ICA2-pathlen1.pem \ + certs/test-pathlen/chainB-assembled.pem \ + certs/test-pathlen/chainB-entity-key.pem \ + certs/test-pathlen/chainB-entity.pem \ + certs/test-pathlen/chainC-ICA1-key.pem \ + certs/test-pathlen/chainC-ICA1-pathlen1.pem \ + certs/test-pathlen/chainC-assembled.pem \ + certs/test-pathlen/chainC-entity-key.pem \ + certs/test-pathlen/chainC-entity.pem \ + certs/test-pathlen/chainD-ICA1-key.pem \ + certs/test-pathlen/chainD-ICA1-pathlen127.pem \ + certs/test-pathlen/chainD-assembled.pem \ + certs/test-pathlen/chainD-entity-key.pem \ + certs/test-pathlen/chainD-entity.pem \ + certs/test-pathlen/chainE-ICA1-key.pem \ + certs/test-pathlen/chainE-ICA1-pathlen128.pem \ + certs/test-pathlen/chainE-assembled.pem \ + certs/test-pathlen/chainE-entity-key.pem \ + certs/test-pathlen/chainE-entity.pem \ + certs/test-pathlen/chainF-ICA1-key.pem \ + certs/test-pathlen/chainF-ICA1-pathlen1.pem \ + certs/test-pathlen/chainF-ICA2-key.pem \ + certs/test-pathlen/chainF-ICA2-pathlen0.pem \ + certs/test-pathlen/chainF-assembled.pem \ + certs/test-pathlen/chainF-entity-key.pem \ + certs/test-pathlen/chainF-entity.pem \ + certs/test-pathlen/chainG-ICA1-key.pem \ + certs/test-pathlen/chainG-ICA1-pathlen0.pem \ + certs/test-pathlen/chainG-ICA2-key.pem \ + certs/test-pathlen/chainG-ICA2-pathlen1.pem \ + certs/test-pathlen/chainG-ICA3-key.pem \ + certs/test-pathlen/chainG-ICA3-pathlen99.pem \ + certs/test-pathlen/chainG-ICA4-key.pem \ + certs/test-pathlen/chainG-ICA4-pathlen5.pem \ + certs/test-pathlen/chainG-ICA5-key.pem \ + certs/test-pathlen/chainG-ICA5-pathlen20.pem \ + certs/test-pathlen/chainG-ICA6-key.pem \ + certs/test-pathlen/chainG-ICA6-pathlen10.pem \ + certs/test-pathlen/chainG-ICA7-key.pem \ + certs/test-pathlen/chainG-ICA7-pathlen100.pem \ + certs/test-pathlen/chainG-assembled.pem \ + certs/test-pathlen/chainG-entity-key.pem \ + certs/test-pathlen/chainG-entity.pem \ + certs/test-pathlen/chainH-ICA1-key.pem \ + certs/test-pathlen/chainH-ICA1-pathlen0.pem \ + certs/test-pathlen/chainH-ICA2-key.pem \ + certs/test-pathlen/chainH-ICA2-pathlen2.pem \ + certs/test-pathlen/chainH-ICA3-key.pem \ + certs/test-pathlen/chainH-ICA3-pathlen2.pem \ + certs/test-pathlen/chainH-ICA4-key.pem \ + certs/test-pathlen/chainH-ICA4-pathlen2.pem \ + certs/test-pathlen/chainH-assembled.pem \ + certs/test-pathlen/chainH-entity-key.pem \ + certs/test-pathlen/chainH-entity.pem \ + certs/test-pathlen/chainI-ICA1-key.pem \ + certs/test-pathlen/chainI-ICA1-no_pathlen.pem \ + certs/test-pathlen/chainI-ICA2-key.pem \ + certs/test-pathlen/chainI-ICA2-no_pathlen.pem \ + certs/test-pathlen/chainI-ICA3-key.pem \ + certs/test-pathlen/chainI-ICA3-pathlen2.pem \ + certs/test-pathlen/chainI-assembled.pem \ + certs/test-pathlen/chainI-entity-key.pem \ + certs/test-pathlen/chainI-entity.pem \ + certs/test-pathlen/chainJ-ICA1-key.pem \ + certs/test-pathlen/chainJ-ICA1-no_pathlen.pem \ + certs/test-pathlen/chainJ-ICA2-key.pem \ + certs/test-pathlen/chainJ-ICA2-no_pathlen.pem \ + certs/test-pathlen/chainJ-ICA3-key.pem \ + certs/test-pathlen/chainJ-ICA3-no_pathlen.pem \ + certs/test-pathlen/chainJ-ICA4-key.pem \ + certs/test-pathlen/chainJ-ICA4-pathlen2.pem \ + certs/test-pathlen/chainJ-assembled.pem \ + certs/test-pathlen/chainJ-entity-key.pem \ + certs/test-pathlen/chainJ-entity.pem \ + certs/intermediate/genintcerts.sh \ + certs/intermediate/ca-int-cert.der \ + certs/intermediate/ca-int-cert.pem \ + certs/intermediate/ca-int-ecc-cert.der \ + certs/intermediate/ca-int-ecc-cert.pem \ + certs/intermediate/ca-int-ecc-key.der \ + certs/intermediate/ca-int-ecc-key.pem \ + certs/intermediate/ca-int-key.der \ + certs/intermediate/ca-int-key.pem \ + certs/intermediate/client-chain-alt-ecc.pem \ + certs/intermediate/client-chain-alt.pem \ + certs/intermediate/client-chain-ecc.der \ + certs/intermediate/client-chain-ecc.pem \ + certs/intermediate/client-chain.der \ + certs/intermediate/client-chain.pem \ + certs/intermediate/client-int-cert.der \ + certs/intermediate/client-int-cert.pem \ + certs/intermediate/client-int-ecc-cert.der \ + certs/intermediate/client-int-ecc-cert.pem \ + certs/intermediate/server-chain-alt-ecc.pem \ + certs/intermediate/server-chain-alt.pem \ + certs/intermediate/server-chain-ecc.der \ + certs/intermediate/server-chain-ecc.pem \ + certs/intermediate/server-chain.der \ + certs/intermediate/server-chain.pem \ + certs/intermediate/server-int-cert.der \ + certs/intermediate/server-int-cert.pem \ + certs/intermediate/server-int-ecc-cert.der \ + certs/intermediate/server-int-ecc-cert.pem swig/PythonBuild.sh \ + swig/README swig/wolfssl.i swig/wolfssl_adds.c \ + swig/python_wolfssl.vcproj swig/rsasign.py swig/runme.py \ + support/wolfssl.pc wolfcrypt/user-crypto/configure.ac \ + wolfcrypt/user-crypto/autogen.sh \ + wolfcrypt/user-crypto/include/user_rsa.h \ + wolfcrypt/user-crypto/src/rsa.c \ + wolfcrypt/user-crypto/lib/.gitkeep \ + wolfcrypt/user-crypto/README.txt \ + wolfcrypt/user-crypto/Makefile.am \ + wolfcrypt/benchmark/benchmark.sln \ + wolfcrypt/benchmark/benchmark.vcproj \ + wolfcrypt/benchmark/README.md src/bio.c wolfcrypt/src/misc.c \ + wolfcrypt/src/evp.c wolfcrypt/src/asm.c \ + wolfcrypt/src/aes_asm.asm wolfcrypt/src/wc_dsp.c \ + wolfcrypt/src/sp_dsp32.c wolfcrypt/src/ecc_fp.c \ + wolfcrypt/src/fp_mont_small.i wolfcrypt/src/fp_mul_comba_12.i \ + wolfcrypt/src/fp_mul_comba_17.i \ + wolfcrypt/src/fp_mul_comba_20.i \ + wolfcrypt/src/fp_mul_comba_24.i \ + wolfcrypt/src/fp_mul_comba_28.i \ + wolfcrypt/src/fp_mul_comba_32.i wolfcrypt/src/fp_mul_comba_3.i \ + wolfcrypt/src/fp_mul_comba_48.i wolfcrypt/src/fp_mul_comba_4.i \ + wolfcrypt/src/fp_mul_comba_64.i wolfcrypt/src/fp_mul_comba_6.i \ + wolfcrypt/src/fp_mul_comba_7.i wolfcrypt/src/fp_mul_comba_8.i \ + wolfcrypt/src/fp_mul_comba_9.i \ + wolfcrypt/src/fp_mul_comba_small_set.i \ + wolfcrypt/src/fp_sqr_comba_12.i \ + wolfcrypt/src/fp_sqr_comba_17.i \ + wolfcrypt/src/fp_sqr_comba_20.i \ + wolfcrypt/src/fp_sqr_comba_24.i \ + wolfcrypt/src/fp_sqr_comba_28.i \ + wolfcrypt/src/fp_sqr_comba_32.i wolfcrypt/src/fp_sqr_comba_3.i \ + wolfcrypt/src/fp_sqr_comba_48.i wolfcrypt/src/fp_sqr_comba_4.i \ + wolfcrypt/src/fp_sqr_comba_64.i wolfcrypt/src/fp_sqr_comba_6.i \ + 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/fe_x25519_128.i 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-crypt.c \ + wolfcrypt/src/port/nrf51.c wolfcrypt/src/port/arm/armv8-aes.c \ + wolfcrypt/src/port/arm/armv8-sha256.c \ + wolfcrypt/src/port/arm/armv8-chacha.c \ + wolfcrypt/src/port/arm/armv8-curve25519.c \ + wolfcrypt/src/port/arm/armv8-32-curve25519.c \ + wolfcrypt/src/port/arm/armv8-sha512-asm.c \ + wolfcrypt/src/port/arm/armv8-32-sha512-asm.c \ + wolfcrypt/src/port/nxp/ksdk_port.c \ + wolfcrypt/src/port/atmel/README.md \ + wolfcrypt/src/port/xilinx/xil-sha3.c \ + wolfcrypt/src/port/xilinx/xil-aesgcm.c \ + wolfcrypt/src/port/caam/caam_aes.c \ + wolfcrypt/src/port/caam/caam_driver.c \ + wolfcrypt/src/port/caam/caam_init.c \ + wolfcrypt/src/port/caam/caam_sha.c \ + wolfcrypt/src/port/caam/caam_doc.pdf \ + wolfcrypt/src/port/st/stm32.c wolfcrypt/src/port/st/stsafe.c \ + wolfcrypt/src/port/st/README.md \ + wolfcrypt/src/port/af_alg/afalg_aes.c \ + wolfcrypt/src/port/af_alg/afalg_hash.c \ + wolfcrypt/src/port/devcrypto/devcrypto_hash.c \ + wolfcrypt/src/port/devcrypto/wc_devcrypto.c \ + wolfcrypt/src/port/devcrypto/README.md \ + wolfcrypt/src/port/mynewt/mynewt_port.c \ + wolfcrypt/src/port/Espressif/esp32_aes.c \ + wolfcrypt/src/port/Espressif/esp32_sha.c \ + wolfcrypt/src/port/Espressif/esp32_util.c \ + wolfcrypt/src/port/Espressif/esp32_mp.c \ + wolfcrypt/src/port/Espressif/README.md \ + wolfcrypt/src/port/arm/cryptoCell.c \ + wolfcrypt/src/port/arm/cryptoCellHash.c \ + wolfcrypt/src/port/Renesas/renesas_tsip_aes.c \ + wolfcrypt/src/port/Renesas/renesas_tsip_sha.c \ + wolfcrypt/src/port/Renesas/renesas_tsip_util.c \ + wolfcrypt/src/port/Renesas/README.md \ + wolfcrypt/src/port/cavium/README.md \ + wolfcrypt/src/port/cavium/README_Octeon.md \ + wolfcrypt/src/port/intel/README.md wolfcrypt/test/test.sln \ + wolfcrypt/test/test.vcproj wolfcrypt/test/README.md \ + examples/client/client.sln examples/client/client-ntru.vcproj \ examples/client/client.vcproj examples/client/client.vcxproj \ - examples/server/server.sln examples/server/server-ntru.vcproj \ - examples/server/server.vcproj examples/server/server.vcxproj \ examples/echoclient/echoclient.sln \ examples/echoclient/echoclient-ntru.vcproj \ examples/echoclient/echoclient.vcproj \ @@ -1117,133 +3038,167 @@ EXTRA_DIST = lib/dummy cyassl-ntru.vcproj cyassl.vcproj cyassl.vcxproj \ examples/echoserver/echoserver.sln \ examples/echoserver/echoserver-ntru.vcproj \ examples/echoserver/echoserver.vcproj \ - examples/echoserver/echoserver.vcxproj testsuite/testsuite.sln \ - testsuite/testsuite-ntru.vcproj testsuite/testsuite.vcproj \ - testsuite/testsuite.vcxproj input quit tests/unit.h \ - tests/test.conf tests/test-dtls.conf \ + examples/echoserver/echoserver.vcxproj \ + examples/server/server.sln examples/server/server-ntru.vcproj \ + examples/server/server.vcproj examples/server/server.vcxproj \ + testsuite/testsuite.sln testsuite/testsuite-ntru.vcproj \ + testsuite/testsuite.vcproj testsuite/testsuite.vcxproj input \ + quit tests/unit.h tests/test.conf tests/test-sha2.conf \ + tests/test-tls13.conf tests/test-tls13-down.conf \ + tests/test-tls13-ecc.conf tests/test-tls13-psk.conf \ + tests/test-qsh.conf tests/test-qsh-sha2.conf \ + tests/test-psk.conf tests/test-psk-no-id.conf \ + tests/test-psk-no-id-sha2.conf tests/test-dtls.conf \ + tests/test-dtls-sha2.conf tests/test-sctp.conf \ + tests/test-sctp-sha2.conf tests/test-sig.conf \ + tests/test-ed25519.conf tests/test-ed448.conf \ + tests/test-enckeys.conf tests/test-maxfrag.conf \ + tests/test-maxfrag-dtls.conf tests/test-fails.conf \ + tests/test-chains.conf tests/test-altchains.conf \ + tests/test-trustpeer.conf tests/test-dhprime.conf \ sslSniffer/sslSniffer.vcproj sslSniffer/sslSniffer.vcxproj \ sslSniffer/sslSnifferTest/sslSniffTest.vcproj \ - mqx/ctaocrypt_test/.cproject mqx/ctaocrypt_test/.project \ - mqx/ctaocrypt_test/ReferencedRSESystems.xml \ - mqx/ctaocrypt_test/ctaocrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch \ - mqx/ctaocrypt_test/ctaocrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch \ - mqx/ctaocrypt_test/Sources/main.c \ - mqx/ctaocrypt_test/Sources/main.h mqx/README \ - mqx/cyassl/.cproject mqx/cyassl/.project \ - mqx/cyassl_client/.cproject mqx/cyassl_client/.project \ - mqx/cyassl_client/ReferencedRSESystems.xml \ - mqx/cyassl_client/cyassl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch \ - mqx/cyassl_client/cyassl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch \ - mqx/cyassl_client/Sources/main.c \ - mqx/cyassl_client/Sources/main.h mqx/util_lib/.cproject \ - mqx/util_lib/.project mqx/util_lib/Sources/util.c \ - mqx/util_lib/Sources/util.h mplabx/PIC32MZ-serial.h \ - mplabx/README mplabx/benchmark_main.c mplabx/test_main.c \ - mplabx/ctaocrypt_benchmark.X/Makefile \ - mplabx/ctaocrypt_benchmark.X/nbproject/configurations.xml \ - mplabx/ctaocrypt_benchmark.X/nbproject/project.xml \ - mplabx/ctaocrypt_test.X/Makefile \ - mplabx/ctaocrypt_test.X/nbproject/configurations.xml \ - mplabx/ctaocrypt_test.X/nbproject/project.xml \ - mplabx/cyassl.X/Makefile \ - mplabx/cyassl.X/nbproject/configurations.xml \ - mplabx/cyassl.X/nbproject/project.xml mcapi/README \ - mcapi/PIC32MZ-serial.h mcapi/ctaocrypt_mcapi.X/Makefile \ - mcapi/ctaocrypt_mcapi.X/nbproject/configurations.xml \ - mcapi/ctaocrypt_mcapi.X/nbproject/project.xml \ - mcapi/ctaocrypt_test.X/Makefile \ - mcapi/ctaocrypt_test.X/nbproject/configurations.xml \ - mcapi/ctaocrypt_test.X/nbproject/project.xml \ - mcapi/cyassl.X/Makefile \ - mcapi/cyassl.X/nbproject/configurations.xml \ - mcapi/cyassl.X/nbproject/project.xml mcapi/zlib.X/Makefile \ - mcapi/zlib.X/nbproject/configurations.xml \ - mcapi/zlib.X/nbproject/project.xml + $(am__append_148) $(am__append_154) scripts/testsuite.pcap \ + scripts/sniffer-ipv6.pcap scripts/ping.test \ + scripts/openssl.test scripts/dertoc.pl \ + scripts/stm32l4-v4_0_1_build.sh scripts/cleanup_testfiles.sh dist_doc_DATA = certs/taoCert.txt doc/README.txt +dist_noinst_SCRIPTS = $(am__append_152) $(am__append_153) \ + $(am__append_155) $(am__append_156) $(am__append_157) \ + $(am__append_158) $(am__append_159) $(am__append_160) \ + $(am__append_161) $(am__append_162) $(am__append_163) +noinst_SCRIPTS = $(am__append_18) +check_SCRIPTS = $(dist_noinst_SCRIPTS) exampledir = $(docdir)/example -dist_example_DATA = examples/client/client.c examples/server/server.c \ - examples/echoclient/echoclient.c \ - examples/echoserver/echoserver.c +dist_example_DATA = examples/benchmark/tls_bench.c \ + examples/client/client.c examples/echoclient/echoclient.c \ + examples/echoserver/echoserver.c examples/server/server.c \ + examples/sctp/sctp-server.c examples/sctp/sctp-server-dtls.c \ + examples/sctp/sctp-client.c examples/sctp/sctp-client-dtls.c ACLOCAL_AMFLAGS = -I m4 -src_libcyassl_la_SOURCES = $(am__append_1) src/internal.c src/io.c \ - src/keys.c src/ssl.c src/tls.c ctaocrypt/src/hmac.c \ - ctaocrypt/src/random.c ctaocrypt/src/sha256.c \ - ctaocrypt/src/logging.c ctaocrypt/src/wc_port.c \ - ctaocrypt/src/error.c $(am__append_2) $(am__append_3) \ - $(am__append_4) $(am__append_5) $(am__append_6) \ - $(am__append_7) $(am__append_8) $(am__append_9) \ - $(am__append_10) $(am__append_11) $(am__append_12) \ - $(am__append_13) $(am__append_14) $(am__append_15) \ - $(am__append_16) $(am__append_17) $(am__append_18) \ - $(am__append_19) $(am__append_20) $(am__append_21) \ +src_libwolfssl_la_SOURCES = $(am__append_20) $(am__append_21) \ $(am__append_22) $(am__append_23) $(am__append_24) \ $(am__append_25) $(am__append_26) $(am__append_27) \ $(am__append_28) $(am__append_29) $(am__append_30) \ - $(am__append_31) $(am__append_32) $(am__append_33) -src_libcyassl_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${CYASSL_LIBRARY_VERSION} -src_libcyassl_la_LIBADD = $(LIBM) -src_libcyassl_la_CFLAGS = -DBUILDING_CYASSL $(AM_CFLAGS) -src_libcyassl_la_CPPFLAGS = -DBUILDING_CYASSL $(AM_CPPFLAGS) + $(am__append_31) $(am__append_32) $(am__append_33) \ + $(am__append_34) $(am__append_35) $(am__append_36) \ + $(am__append_37) $(am__append_38) $(am__append_39) \ + $(am__append_40) $(am__append_41) $(am__append_42) \ + $(am__append_43) $(am__append_44) wolfcrypt/src/hash.c \ + wolfcrypt/src/cpuid.c $(am__append_45) $(am__append_46) \ + $(am__append_47) $(am__append_48) $(am__append_49) \ + $(am__append_50) $(am__append_51) $(am__append_52) \ + $(am__append_53) $(am__append_54) $(am__append_55) \ + $(am__append_56) $(am__append_57) $(am__append_58) \ + $(am__append_59) $(am__append_60) $(am__append_61) \ + $(am__append_62) $(am__append_63) $(am__append_64) \ + $(am__append_65) $(am__append_66) $(am__append_67) \ + $(am__append_68) $(am__append_69) $(am__append_70) \ + wolfcrypt/src/logging.c wolfcrypt/src/wc_port.c \ + wolfcrypt/src/error.c $(am__append_71) $(am__append_72) \ + $(am__append_73) $(am__append_74) $(am__append_75) \ + $(am__append_76) $(am__append_77) $(am__append_78) \ + $(am__append_79) $(am__append_80) $(am__append_81) \ + $(am__append_82) $(am__append_83) $(am__append_84) \ + $(am__append_85) $(am__append_86) $(am__append_87) \ + $(am__append_88) $(am__append_89) $(am__append_90) \ + $(am__append_91) $(am__append_92) $(am__append_93) \ + $(am__append_94) $(am__append_95) $(am__append_96) \ + $(am__append_97) $(am__append_98) $(am__append_99) \ + $(am__append_100) $(am__append_101) $(am__append_102) \ + $(am__append_103) $(am__append_104) $(am__append_105) \ + $(am__append_106) $(am__append_107) $(am__append_108) \ + $(am__append_109) $(am__append_110) $(am__append_111) \ + $(am__append_112) $(am__append_113) $(am__append_114) \ + $(am__append_115) $(am__append_116) $(am__append_117) \ + $(am__append_118) $(am__append_119) $(am__append_120) \ + $(am__append_121) $(am__append_122) $(am__append_123) \ + $(am__append_124) $(am__append_125) $(am__append_128) \ + $(am__append_129) $(am__append_130) $(am__append_131) \ + $(am__append_132) $(am__append_133) $(am__append_134) \ + $(am__append_135) +src_libwolfssl_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${WOLFSSL_LIBRARY_VERSION} +src_libwolfssl_la_LIBADD = $(LIBM) $(LIB_ADD) $(LIB_STATIC_ADD) +src_libwolfssl_la_CFLAGS = -DBUILDING_WOLFSSL $(AM_CFLAGS) +src_libwolfssl_la_CPPFLAGS = -DBUILDING_WOLFSSL $(AM_CPPFLAGS) +@BUILD_FAST_RSA_TRUE@ippdir = $(libdir) +@BUILD_FAST_RSA_TRUE@ipp_DATA = $(IPPLIBS) pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = support/cyassl.pc -ctaocrypt_benchmark_benchmark_SOURCES = ctaocrypt/benchmark/benchmark.c -ctaocrypt_benchmark_benchmark_LDADD = src/libcyassl.la -ctaocrypt_benchmark_benchmark_DEPENDENCIES = src/libcyassl.la -ctaocrypt_test_testctaocrypt_SOURCES = ctaocrypt/test/test.c -ctaocrypt_test_testctaocrypt_LDADD = src/libcyassl.la -ctaocrypt_test_testctaocrypt_DEPENDENCIES = src/libcyassl.la -@BUILD_EXAMPLES_TRUE@examples_client_client_SOURCES = examples/client/client.c -@BUILD_EXAMPLES_TRUE@examples_client_client_LDADD = src/libcyassl.la -@BUILD_EXAMPLES_TRUE@examples_client_client_DEPENDENCIES = src/libcyassl.la -@BUILD_EXAMPLES_TRUE@examples_server_server_SOURCES = examples/server/server.c -@BUILD_EXAMPLES_TRUE@examples_server_server_LDADD = src/libcyassl.la -@BUILD_EXAMPLES_TRUE@examples_server_server_DEPENDENCIES = src/libcyassl.la -@BUILD_EXAMPLES_TRUE@examples_echoclient_echoclient_SOURCES = examples/echoclient/echoclient.c -@BUILD_EXAMPLES_TRUE@examples_echoclient_echoclient_LDADD = src/libcyassl.la -@BUILD_EXAMPLES_TRUE@examples_echoclient_echoclient_DEPENDENCIES = src/libcyassl.la -@BUILD_EXAMPLES_TRUE@examples_echoserver_echoserver_SOURCES = examples/echoserver/echoserver.c -@BUILD_EXAMPLES_TRUE@examples_echoserver_echoserver_LDADD = src/libcyassl.la -@BUILD_EXAMPLES_TRUE@examples_echoserver_echoserver_DEPENDENCIES = src/libcyassl.la -@BUILD_EXAMPLES_TRUE@testsuite_testsuite_test_SOURCES = \ -@BUILD_EXAMPLES_TRUE@ ctaocrypt/test/test.c \ -@BUILD_EXAMPLES_TRUE@ examples/client/client.c \ -@BUILD_EXAMPLES_TRUE@ examples/echoclient/echoclient.c \ -@BUILD_EXAMPLES_TRUE@ examples/echoserver/echoserver.c \ -@BUILD_EXAMPLES_TRUE@ examples/server/server.c \ -@BUILD_EXAMPLES_TRUE@ testsuite/testsuite.c +pkgconfig_DATA = support/wolfssl.pc +@BUILD_WOLFCRYPT_TESTS_TRUE@wolfcrypt_benchmark_benchmark_SOURCES = wolfcrypt/benchmark/benchmark.c +@BUILD_WOLFCRYPT_TESTS_TRUE@wolfcrypt_benchmark_benchmark_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +@BUILD_WOLFCRYPT_TESTS_TRUE@wolfcrypt_benchmark_benchmark_DEPENDENCIES = src/libwolfssl.la +@BUILD_WOLFCRYPT_TESTS_TRUE@wolfcrypt_test_testwolfcrypt_SOURCES = wolfcrypt/test/test.c +@BUILD_WOLFCRYPT_TESTS_TRUE@wolfcrypt_test_testwolfcrypt_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +@BUILD_WOLFCRYPT_TESTS_TRUE@wolfcrypt_test_testwolfcrypt_DEPENDENCIES = src/libwolfssl.la +@BUILD_THREADED_EXAMPLES_TRUE@examples_benchmark_tls_bench_SOURCES = examples/benchmark/tls_bench.c +@BUILD_THREADED_EXAMPLES_TRUE@examples_benchmark_tls_bench_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +@BUILD_THREADED_EXAMPLES_TRUE@examples_benchmark_tls_bench_DEPENDENCIES = src/libwolfssl.la +@BUILD_EXAMPLE_CLIENTS_TRUE@examples_client_client_SOURCES = examples/client/client.c +@BUILD_EXAMPLE_CLIENTS_TRUE@examples_client_client_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +@BUILD_EXAMPLE_CLIENTS_TRUE@examples_client_client_DEPENDENCIES = src/libwolfssl.la +@BUILD_EXAMPLE_CLIENTS_TRUE@examples_echoclient_echoclient_SOURCES = examples/echoclient/echoclient.c +@BUILD_EXAMPLE_CLIENTS_TRUE@examples_echoclient_echoclient_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +@BUILD_EXAMPLE_CLIENTS_TRUE@examples_echoclient_echoclient_DEPENDENCIES = src/libwolfssl.la +@BUILD_EXAMPLE_SERVERS_TRUE@examples_echoserver_echoserver_SOURCES = examples/echoserver/echoserver.c +@BUILD_EXAMPLE_SERVERS_TRUE@examples_echoserver_echoserver_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +@BUILD_EXAMPLE_SERVERS_TRUE@examples_echoserver_echoserver_DEPENDENCIES = src/libwolfssl.la +@BUILD_EXAMPLE_SERVERS_TRUE@examples_server_server_SOURCES = examples/server/server.c +@BUILD_EXAMPLE_SERVERS_TRUE@examples_server_server_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +@BUILD_EXAMPLE_SERVERS_TRUE@examples_server_server_DEPENDENCIES = src/libwolfssl.la +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@examples_sctp_sctp_server_SOURCES = examples/sctp/sctp-server.c +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@examples_sctp_sctp_server_LDADD = $(LIB_STATIC_ADD) +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@examples_sctp_sctp_server_dtls_SOURCES = examples/sctp/sctp-server-dtls.c +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@examples_sctp_sctp_server_dtls_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_SCTP_TRUE@examples_sctp_sctp_server_dtls_DEPENDENCIES = src/libwolfssl.la +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@examples_sctp_sctp_client_SOURCES = examples/sctp/sctp-client.c +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@examples_sctp_sctp_client_LDADD = $(LIB_STATIC_ADD) +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@examples_sctp_sctp_client_dtls_SOURCES = examples/sctp/sctp-client-dtls.c +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@examples_sctp_sctp_client_dtls_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +@BUILD_EXAMPLE_CLIENTS_TRUE@@BUILD_SCTP_TRUE@examples_sctp_sctp_client_dtls_DEPENDENCIES = src/libwolfssl.la +@BUILD_TESTS_TRUE@testsuite_testsuite_test_SOURCES = \ +@BUILD_TESTS_TRUE@ wolfcrypt/test/test.c \ +@BUILD_TESTS_TRUE@ examples/client/client.c \ +@BUILD_TESTS_TRUE@ examples/echoclient/echoclient.c \ +@BUILD_TESTS_TRUE@ examples/echoserver/echoserver.c \ +@BUILD_TESTS_TRUE@ examples/server/server.c \ +@BUILD_TESTS_TRUE@ testsuite/testsuite.c -@BUILD_EXAMPLES_TRUE@testsuite_testsuite_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) -@BUILD_EXAMPLES_TRUE@testsuite_testsuite_test_LDADD = src/libcyassl.la -@BUILD_EXAMPLES_TRUE@testsuite_testsuite_test_DEPENDENCIES = src/libcyassl.la -@BUILD_EXAMPLES_TRUE@tests_unit_test_SOURCES = \ -@BUILD_EXAMPLES_TRUE@ tests/unit.c \ -@BUILD_EXAMPLES_TRUE@ tests/api.c \ -@BUILD_EXAMPLES_TRUE@ tests/suites.c \ -@BUILD_EXAMPLES_TRUE@ tests/hash.c \ -@BUILD_EXAMPLES_TRUE@ examples/client/client.c \ -@BUILD_EXAMPLES_TRUE@ examples/server/server.c +@BUILD_TESTS_TRUE@testsuite_testsuite_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) +@BUILD_TESTS_TRUE@testsuite_testsuite_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +@BUILD_TESTS_TRUE@testsuite_testsuite_test_DEPENDENCIES = src/libwolfssl.la +@BUILD_TESTS_TRUE@tests_unit_test_SOURCES = \ +@BUILD_TESTS_TRUE@ tests/unit.c \ +@BUILD_TESTS_TRUE@ tests/api.c \ +@BUILD_TESTS_TRUE@ tests/suites.c \ +@BUILD_TESTS_TRUE@ tests/hash.c \ +@BUILD_TESTS_TRUE@ tests/srp.c \ +@BUILD_TESTS_TRUE@ examples/client/client.c \ +@BUILD_TESTS_TRUE@ examples/server/server.c -@BUILD_EXAMPLES_TRUE@tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) -@BUILD_EXAMPLES_TRUE@tests_unit_test_LDADD = src/libcyassl.la -@BUILD_EXAMPLES_TRUE@tests_unit_test_DEPENDENCIES = src/libcyassl.la +@BUILD_TESTS_TRUE@tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) +@BUILD_TESTS_TRUE@tests_unit_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +@BUILD_TESTS_TRUE@tests_unit_test_DEPENDENCIES = src/libwolfssl.la @BUILD_SNIFFTEST_TRUE@sslSniffer_sslSnifferTest_snifftest_SOURCES = sslSniffer/sslSnifferTest/snifftest.c -@BUILD_SNIFFTEST_TRUE@sslSniffer_sslSnifferTest_snifftest_LDADD = src/libcyassl.la -lpcap -@BUILD_SNIFFTEST_TRUE@sslSniffer_sslSnifferTest_snifftest_DEPENDENCIES = src/libcyassl.la -@BUILD_MCAPI_TRUE@mcapi_test_SOURCES = mcapi/crypto.c \ -@BUILD_MCAPI_TRUE@ mcapi/mcapi_test.c +@BUILD_SNIFFTEST_TRUE@sslSniffer_sslSnifferTest_snifftest_LDADD = src/libwolfssl.la -lpcap $(LIB_STATIC_ADD) +@BUILD_SNIFFTEST_TRUE@sslSniffer_sslSnifferTest_snifftest_DEPENDENCIES = src/libwolfssl.la +@BUILD_DISTRO_FALSE@@BUILD_MCAPI_TRUE@mcapi_test_SOURCES = mcapi/crypto.c \ +@BUILD_DISTRO_FALSE@@BUILD_MCAPI_TRUE@ mcapi/mcapi_test.c -@BUILD_MCAPI_TRUE@mcapi_test_LDADD = src/libcyassl.la -@BUILD_MCAPI_TRUE@mcapi_test_DEPENDENCIES = src/libcyassl.la +@BUILD_DISTRO_FALSE@@BUILD_MCAPI_TRUE@mcapi_test_LDADD = src/libwolfssl.la +@BUILD_DISTRO_FALSE@@BUILD_MCAPI_TRUE@mcapi_test_DEPENDENCIES = src/libwolfssl.la + +# Exclude references to non-DFSG sources from build files @USE_VALGRIND_TRUE@TESTS_ENVIRONMENT = ./valgrind-error.sh TEST_EXTENSIONS = .test all: $(BUILT_SOURCES) config.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: -.SUFFIXES: .c .lo .log .o .obj .s .test .test$(EXEEXT) .trs +.SUFFIXES: .S .c .lo .log .o .obj .test .test$(EXEEXT) .trs am--refresh: Makefile @: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/cyassl/include.am $(srcdir)/cyassl/ctaocrypt/include.am $(srcdir)/cyassl/openssl/include.am $(srcdir)/certs/include.am $(srcdir)/certs/1024/include.am $(srcdir)/certs/crl/include.am $(srcdir)/doc/include.am $(srcdir)/swig/include.am $(srcdir)/src/include.am $(srcdir)/support/include.am $(srcdir)/ctaocrypt/benchmark/include.am $(srcdir)/ctaocrypt/src/include.am $(srcdir)/ctaocrypt/test/include.am $(srcdir)/examples/client/include.am $(srcdir)/examples/server/include.am $(srcdir)/examples/echoclient/include.am $(srcdir)/examples/echoserver/include.am $(srcdir)/testsuite/include.am $(srcdir)/tests/include.am $(srcdir)/sslSniffer/sslSnifferTest/include.am $(srcdir)/rpm/include.am $(srcdir)/mqx/ctaocrypt_test/Sources/include.am $(srcdir)/mqx/cyassl/include.am $(srcdir)/mqx/cyassl_client/Sources/include.am $(srcdir)/mqx/util_lib/Sources/include.am $(srcdir)/mplabx/include.am $(srcdir)/mplabx/ctaocrypt_benchmark.X/nbproject/include.am $(srcdir)/mplabx/ctaocrypt_test.X/nbproject/include.am $(srcdir)/mplabx/cyassl.X/nbproject/include.am $(srcdir)/mcapi/include.am $(srcdir)/mcapi/ctaocrypt_mcapi.X/nbproject/include.am $(srcdir)/mcapi/ctaocrypt_test.X/nbproject/include.am $(srcdir)/mcapi/cyassl.X/nbproject/include.am $(srcdir)/mcapi/zlib.X/nbproject/include.am $(am__configure_deps) +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/wrapper/include.am $(srcdir)/wrapper/python/wolfcrypt/include.am $(srcdir)/wrapper/python/wolfssl/include.am $(srcdir)/wrapper/CSharp/include.am $(srcdir)/cyassl/include.am $(srcdir)/cyassl/ctaocrypt/include.am $(srcdir)/cyassl/openssl/include.am $(srcdir)/wolfssl/include.am $(srcdir)/wolfssl/wolfcrypt/include.am $(srcdir)/wolfssl/openssl/include.am $(srcdir)/certs/include.am $(srcdir)/certs/1024/include.am $(srcdir)/certs/3072/include.am $(srcdir)/certs/4096/include.am $(srcdir)/certs/crl/include.am $(srcdir)/certs/ecc/include.am $(srcdir)/certs/ed25519/include.am $(srcdir)/certs/ed448/include.am $(srcdir)/certs/external/include.am $(srcdir)/certs/ocsp/include.am $(srcdir)/certs/test/include.am $(srcdir)/certs/test-pathlen/include.am $(srcdir)/certs/intermediate/include.am $(srcdir)/doc/include.am $(srcdir)/swig/include.am $(srcdir)/src/include.am $(srcdir)/support/include.am $(srcdir)/wolfcrypt/user-crypto/include.am $(srcdir)/wolfcrypt/benchmark/include.am $(srcdir)/wolfcrypt/src/include.am $(srcdir)/wolfcrypt/test/include.am $(srcdir)/examples/include.am $(srcdir)/examples/benchmark/include.am $(srcdir)/examples/client/include.am $(srcdir)/examples/echoclient/include.am $(srcdir)/examples/echoserver/include.am $(srcdir)/examples/server/include.am $(srcdir)/examples/sctp/include.am $(srcdir)/testsuite/include.am $(srcdir)/tests/include.am $(srcdir)/sslSniffer/sslSnifferTest/include.am $(srcdir)/rpm/include.am $(srcdir)/mqx/util_lib/Sources/include.am $(srcdir)/mqx/wolfcrypt_benchmark/Sources/include.am $(srcdir)/mqx/wolfcrypt_test/Sources/include.am $(srcdir)/mqx/wolfssl/include.am $(srcdir)/mqx/wolfssl_client/Sources/include.am $(srcdir)/mplabx/include.am $(srcdir)/mplabx/wolfcrypt_benchmark.X/nbproject/include.am $(srcdir)/mplabx/wolfcrypt_test.X/nbproject/include.am $(srcdir)/mplabx/wolfssl.X/nbproject/include.am $(srcdir)/mcapi/include.am $(srcdir)/mcapi/wolfcrypt_mcapi.X/nbproject/include.am $(srcdir)/mcapi/wolfcrypt_test.X/nbproject/include.am $(srcdir)/mcapi/wolfssl.X/nbproject/include.am $(srcdir)/mcapi/zlib.X/nbproject/include.am $(srcdir)/tirtos/include.am $(srcdir)/IDE/include.am $(srcdir)/IDE/XCODE/include.am $(srcdir)/IDE/XCODE/Benchmark/include.am $(srcdir)/IDE/WIN/include.am $(srcdir)/IDE/WIN10/include.am $(srcdir)/IDE/WIN-SGX/include.am $(srcdir)/IDE/LINUX-SGX/include.am $(srcdir)/IDE/WORKBENCH/include.am $(srcdir)/IDE/ROWLEY-CROSSWORKS-ARM/include.am $(srcdir)/IDE/TRUESTUDIO/include.am $(srcdir)/IDE/ARDUINO/include.am $(srcdir)/IDE/INTIME-RTOS/include.am $(srcdir)/IDE/OPENSTM32/include.am $(srcdir)/IDE/VS-ARM/include.am $(srcdir)/IDE/VS-AZURE-SPHERE/include.am $(srcdir)/IDE/GCC-ARM/include.am $(srcdir)/IDE/CSBENCH/include.am $(srcdir)/IDE/ECLIPSE/DEOS/include.am $(srcdir)/IDE/ECLIPSE/MICRIUM/include.am $(srcdir)/IDE/ECLIPSE/SIFIVE/include.am $(srcdir)/IDE/mynewt/include.am $(srcdir)/IDE/Renesas/e2studio/DK-S7G2/include.am $(srcdir)/IDE/Renesas/cs+/Projects/include.am $(srcdir)/IDE/Renesas/e2studio/Projects/include.am $(srcdir)/IDE/Renesas/e2studio/RA6M3G/include.am $(srcdir)/IDE/WICED-STUDIO/include.am $(srcdir)/IDE/CRYPTOCELL/include.am $(srcdir)/IDE/M68K/include.am $(srcdir)/IDE/HEXAGON/include.am $(srcdir)/IDE/RISCV/include.am $(srcdir)/IDE/RISCV/SIFIVE-HIFIVE1/include.am $(srcdir)/IDE/RISCV/SIFIVE-UNLEASHED/include.am $(srcdir)/IDE/XilinxSDK/include.am $(srcdir)/scripts/include.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -1256,17 +3211,16 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/cyassl/include.am $(srcd echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; -$(srcdir)/cyassl/include.am $(srcdir)/cyassl/ctaocrypt/include.am $(srcdir)/cyassl/openssl/include.am $(srcdir)/certs/include.am $(srcdir)/certs/1024/include.am $(srcdir)/certs/crl/include.am $(srcdir)/doc/include.am $(srcdir)/swig/include.am $(srcdir)/src/include.am $(srcdir)/support/include.am $(srcdir)/ctaocrypt/benchmark/include.am $(srcdir)/ctaocrypt/src/include.am $(srcdir)/ctaocrypt/test/include.am $(srcdir)/examples/client/include.am $(srcdir)/examples/server/include.am $(srcdir)/examples/echoclient/include.am $(srcdir)/examples/echoserver/include.am $(srcdir)/testsuite/include.am $(srcdir)/tests/include.am $(srcdir)/sslSniffer/sslSnifferTest/include.am $(srcdir)/rpm/include.am $(srcdir)/mqx/ctaocrypt_test/Sources/include.am $(srcdir)/mqx/cyassl/include.am $(srcdir)/mqx/cyassl_client/Sources/include.am $(srcdir)/mqx/util_lib/Sources/include.am $(srcdir)/mplabx/include.am $(srcdir)/mplabx/ctaocrypt_benchmark.X/nbproject/include.am $(srcdir)/mplabx/ctaocrypt_test.X/nbproject/include.am $(srcdir)/mplabx/cyassl.X/nbproject/include.am $(srcdir)/mcapi/include.am $(srcdir)/mcapi/ctaocrypt_mcapi.X/nbproject/include.am $(srcdir)/mcapi/ctaocrypt_test.X/nbproject/include.am $(srcdir)/mcapi/cyassl.X/nbproject/include.am $(srcdir)/mcapi/zlib.X/nbproject/include.am: +$(srcdir)/wrapper/include.am $(srcdir)/wrapper/python/wolfcrypt/include.am $(srcdir)/wrapper/python/wolfssl/include.am $(srcdir)/wrapper/CSharp/include.am $(srcdir)/cyassl/include.am $(srcdir)/cyassl/ctaocrypt/include.am $(srcdir)/cyassl/openssl/include.am $(srcdir)/wolfssl/include.am $(srcdir)/wolfssl/wolfcrypt/include.am $(srcdir)/wolfssl/openssl/include.am $(srcdir)/certs/include.am $(srcdir)/certs/1024/include.am $(srcdir)/certs/3072/include.am $(srcdir)/certs/4096/include.am $(srcdir)/certs/crl/include.am $(srcdir)/certs/ecc/include.am $(srcdir)/certs/ed25519/include.am $(srcdir)/certs/ed448/include.am $(srcdir)/certs/external/include.am $(srcdir)/certs/ocsp/include.am $(srcdir)/certs/test/include.am $(srcdir)/certs/test-pathlen/include.am $(srcdir)/certs/intermediate/include.am $(srcdir)/doc/include.am $(srcdir)/swig/include.am $(srcdir)/src/include.am $(srcdir)/support/include.am $(srcdir)/wolfcrypt/user-crypto/include.am $(srcdir)/wolfcrypt/benchmark/include.am $(srcdir)/wolfcrypt/src/include.am $(srcdir)/wolfcrypt/test/include.am $(srcdir)/examples/include.am $(srcdir)/examples/benchmark/include.am $(srcdir)/examples/client/include.am $(srcdir)/examples/echoclient/include.am $(srcdir)/examples/echoserver/include.am $(srcdir)/examples/server/include.am $(srcdir)/examples/sctp/include.am $(srcdir)/testsuite/include.am $(srcdir)/tests/include.am $(srcdir)/sslSniffer/sslSnifferTest/include.am $(srcdir)/rpm/include.am $(srcdir)/mqx/util_lib/Sources/include.am $(srcdir)/mqx/wolfcrypt_benchmark/Sources/include.am $(srcdir)/mqx/wolfcrypt_test/Sources/include.am $(srcdir)/mqx/wolfssl/include.am $(srcdir)/mqx/wolfssl_client/Sources/include.am $(srcdir)/mplabx/include.am $(srcdir)/mplabx/wolfcrypt_benchmark.X/nbproject/include.am $(srcdir)/mplabx/wolfcrypt_test.X/nbproject/include.am $(srcdir)/mplabx/wolfssl.X/nbproject/include.am $(srcdir)/mcapi/include.am $(srcdir)/mcapi/wolfcrypt_mcapi.X/nbproject/include.am $(srcdir)/mcapi/wolfcrypt_test.X/nbproject/include.am $(srcdir)/mcapi/wolfssl.X/nbproject/include.am $(srcdir)/mcapi/zlib.X/nbproject/include.am $(srcdir)/tirtos/include.am $(srcdir)/IDE/include.am $(srcdir)/IDE/XCODE/include.am $(srcdir)/IDE/XCODE/Benchmark/include.am $(srcdir)/IDE/WIN/include.am $(srcdir)/IDE/WIN10/include.am $(srcdir)/IDE/WIN-SGX/include.am $(srcdir)/IDE/LINUX-SGX/include.am $(srcdir)/IDE/WORKBENCH/include.am $(srcdir)/IDE/ROWLEY-CROSSWORKS-ARM/include.am $(srcdir)/IDE/TRUESTUDIO/include.am $(srcdir)/IDE/ARDUINO/include.am $(srcdir)/IDE/INTIME-RTOS/include.am $(srcdir)/IDE/OPENSTM32/include.am $(srcdir)/IDE/VS-ARM/include.am $(srcdir)/IDE/VS-AZURE-SPHERE/include.am $(srcdir)/IDE/GCC-ARM/include.am $(srcdir)/IDE/CSBENCH/include.am $(srcdir)/IDE/ECLIPSE/DEOS/include.am $(srcdir)/IDE/ECLIPSE/MICRIUM/include.am $(srcdir)/IDE/ECLIPSE/SIFIVE/include.am $(srcdir)/IDE/mynewt/include.am $(srcdir)/IDE/Renesas/e2studio/DK-S7G2/include.am $(srcdir)/IDE/Renesas/cs+/Projects/include.am $(srcdir)/IDE/Renesas/e2studio/Projects/include.am $(srcdir)/IDE/Renesas/e2studio/RA6M3G/include.am $(srcdir)/IDE/WICED-STUDIO/include.am $(srcdir)/IDE/CRYPTOCELL/include.am $(srcdir)/IDE/M68K/include.am $(srcdir)/IDE/HEXAGON/include.am $(srcdir)/IDE/RISCV/include.am $(srcdir)/IDE/RISCV/SIFIVE-HIFIVE1/include.am $(srcdir)/IDE/RISCV/SIFIVE-UNLEASHED/include.am $(srcdir)/IDE/XilinxSDK/include.am $(srcdir)/scripts/include.am $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck @@ -1293,185 +3247,16 @@ distclean-hdr: -rm -f config.h stamp-h1 stamp-h: $(top_builddir)/config.status $(srcdir)/stamp-h.in cd $(top_builddir) && $(SHELL) ./config.status $@ -cyassl/version.h: $(top_builddir)/config.status $(top_srcdir)/cyassl/version.h.in +wolfssl/version.h: $(top_builddir)/config.status $(top_srcdir)/wolfssl/version.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +wolfssl/options.h: $(top_builddir)/config.status $(top_srcdir)/wolfssl/options.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ cyassl/options.h: $(top_builddir)/config.status $(top_srcdir)/cyassl/options.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ -support/cyassl.pc: $(top_builddir)/config.status $(top_srcdir)/support/cyassl.pc.in +support/wolfssl.pc: $(top_builddir)/config.status $(top_srcdir)/support/wolfssl.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ rpm/spec: $(top_builddir)/config.status $(top_srcdir)/rpm/spec.in cd $(top_builddir) && $(SHELL) ./config.status $@ - -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - list2=; for p in $$list; do \ - if test -f $$p; then \ - list2="$$list2 $$p"; \ - else :; fi; \ - done; \ - test -z "$$list2" || { \ - echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ - } - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ - done - -clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - @list='$(lib_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } -ctaocrypt/src/$(am__dirstamp): - @$(MKDIR_P) ctaocrypt/src - @: > ctaocrypt/src/$(am__dirstamp) -ctaocrypt/src/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) ctaocrypt/src/$(DEPDIR) - @: > ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-wolfcrypt_first.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -src/$(am__dirstamp): - @$(MKDIR_P) src - @: > src/$(am__dirstamp) -src/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/$(DEPDIR) - @: > src/$(DEPDIR)/$(am__dirstamp) -src/src_libcyassl_la-internal.lo: src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/src_libcyassl_la-io.lo: src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/src_libcyassl_la-keys.lo: src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/src_libcyassl_la-ssl.lo: src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/src_libcyassl_la-tls.lo: src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-hmac.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-random.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-sha256.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-logging.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-wc_port.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-error.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-memory.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-rsa.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-dh.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-asn.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-fips.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-fips_test.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-coding.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-aes.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-des3.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-sha.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-arc4.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-md4.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-md5.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-pwdbased.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-dsa.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/aes_asm.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-camellia.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-md2.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-ripemd.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-sha512.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-blake2b.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -src/src_libcyassl_la-sniffer.lo: src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-hc128.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-rabbit.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-misc.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-tfm.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-integer.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-ecc.lo: ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -src/src_libcyassl_la-ocsp.lo: src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/src_libcyassl_la-crl.lo: src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-compress.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-pkcs7.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/src/src_libcyassl_la-wolfcrypt_last.lo: \ - ctaocrypt/src/$(am__dirstamp) \ - ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) - -src/libcyassl.la: $(src_libcyassl_la_OBJECTS) $(src_libcyassl_la_DEPENDENCIES) $(EXTRA_src_libcyassl_la_DEPENDENCIES) src/$(am__dirstamp) - $(AM_V_CCLD)$(src_libcyassl_la_LINK) -rpath $(libdir) $(src_libcyassl_la_OBJECTS) $(src_libcyassl_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ @@ -1539,31 +3324,476 @@ clean-noinstPROGRAMS: list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list -ctaocrypt/benchmark/$(am__dirstamp): - @$(MKDIR_P) ctaocrypt/benchmark - @: > ctaocrypt/benchmark/$(am__dirstamp) -ctaocrypt/benchmark/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) ctaocrypt/benchmark/$(DEPDIR) - @: > ctaocrypt/benchmark/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/benchmark/benchmark.$(OBJEXT): \ - ctaocrypt/benchmark/$(am__dirstamp) \ - ctaocrypt/benchmark/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/benchmark/benchmark$(EXEEXT): $(ctaocrypt_benchmark_benchmark_OBJECTS) $(ctaocrypt_benchmark_benchmark_DEPENDENCIES) $(EXTRA_ctaocrypt_benchmark_benchmark_DEPENDENCIES) ctaocrypt/benchmark/$(am__dirstamp) - @rm -f ctaocrypt/benchmark/benchmark$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(ctaocrypt_benchmark_benchmark_OBJECTS) $(ctaocrypt_benchmark_benchmark_LDADD) $(LIBS) -ctaocrypt/test/$(am__dirstamp): - @$(MKDIR_P) ctaocrypt/test - @: > ctaocrypt/test/$(am__dirstamp) -ctaocrypt/test/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) ctaocrypt/test/$(DEPDIR) - @: > ctaocrypt/test/$(DEPDIR)/$(am__dirstamp) -ctaocrypt/test/test.$(OBJEXT): ctaocrypt/test/$(am__dirstamp) \ - ctaocrypt/test/$(DEPDIR)/$(am__dirstamp) +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } -ctaocrypt/test/testctaocrypt$(EXEEXT): $(ctaocrypt_test_testctaocrypt_OBJECTS) $(ctaocrypt_test_testctaocrypt_DEPENDENCIES) $(EXTRA_ctaocrypt_test_testctaocrypt_DEPENDENCIES) ctaocrypt/test/$(am__dirstamp) - @rm -f ctaocrypt/test/testctaocrypt$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(ctaocrypt_test_testctaocrypt_OBJECTS) $(ctaocrypt_test_testctaocrypt_LDADD) $(LIBS) +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +ctaocrypt/src/$(am__dirstamp): + @$(MKDIR_P) ctaocrypt/src + @: > ctaocrypt/src/$(am__dirstamp) +ctaocrypt/src/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ctaocrypt/src/$(DEPDIR) + @: > ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +ctaocrypt/src/src_libwolfssl_la-wolfcrypt_first.lo: \ + ctaocrypt/src/$(am__dirstamp) \ + ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +ctaocrypt/src/src_libwolfssl_la-hmac.lo: \ + ctaocrypt/src/$(am__dirstamp) \ + ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +ctaocrypt/src/src_libwolfssl_la-random.lo: \ + ctaocrypt/src/$(am__dirstamp) \ + ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +ctaocrypt/src/src_libwolfssl_la-sha256.lo: \ + ctaocrypt/src/$(am__dirstamp) \ + ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +ctaocrypt/src/src_libwolfssl_la-rsa.lo: ctaocrypt/src/$(am__dirstamp) \ + ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +ctaocrypt/src/src_libwolfssl_la-aes.lo: ctaocrypt/src/$(am__dirstamp) \ + ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +ctaocrypt/src/src_libwolfssl_la-des3.lo: \ + ctaocrypt/src/$(am__dirstamp) \ + ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +ctaocrypt/src/src_libwolfssl_la-sha.lo: ctaocrypt/src/$(am__dirstamp) \ + ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +ctaocrypt/src/src_libwolfssl_la-sha512.lo: \ + ctaocrypt/src/$(am__dirstamp) \ + ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +ctaocrypt/src/src_libwolfssl_la-fips.lo: \ + ctaocrypt/src/$(am__dirstamp) \ + ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +ctaocrypt/src/src_libwolfssl_la-fips_test.lo: \ + ctaocrypt/src/$(am__dirstamp) \ + ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +ctaocrypt/src/src_libwolfssl_la-wolfcrypt_last.lo: \ + ctaocrypt/src/$(am__dirstamp) \ + ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src + @: > wolfcrypt/src/$(am__dirstamp) +wolfcrypt/src/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/$(DEPDIR) + @: > wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-wolfcrypt_first.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-hmac.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-random.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sha256.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-rsa.lo: wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-ecc.lo: wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-aes.lo: wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-aes_asm.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-aes_gcm_asm.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-des3.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sha.lo: wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sha256_asm.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sha512.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sha512_asm.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sha3.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-dh.lo: wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-cmac.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-fips.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-fips_test.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-wolfcrypt_last.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-selftest.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-hash.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-cpuid.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/arm/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/port/arm + @: > wolfcrypt/src/port/arm/$(am__dirstamp) +wolfcrypt/src/port/arm/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/port/arm/$(DEPDIR) + @: > wolfcrypt/src/port/arm/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha256.lo: \ + wolfcrypt/src/port/arm/$(am__dirstamp) \ + wolfcrypt/src/port/arm/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/af_alg/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/port/af_alg + @: > wolfcrypt/src/port/af_alg/$(am__dirstamp) +wolfcrypt/src/port/af_alg/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/port/af_alg/$(DEPDIR) + @: > wolfcrypt/src/port/af_alg/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_hash.lo: \ + wolfcrypt/src/port/af_alg/$(am__dirstamp) \ + wolfcrypt/src/port/af_alg/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-wolfevent.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-async.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/user-crypto/src/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/user-crypto/src + @: > wolfcrypt/user-crypto/src/$(am__dirstamp) +wolfcrypt/user-crypto/src/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/user-crypto/src/$(DEPDIR) + @: > wolfcrypt/user-crypto/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/user-crypto/src/src_libwolfssl_la-rsa.lo: \ + wolfcrypt/user-crypto/src/$(am__dirstamp) \ + wolfcrypt/user-crypto/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sp_c32.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sp_c64.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sp_x86_64.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sp_x86_64_asm.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sp_arm32.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sp_armthumb.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sp_arm64.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sp_int.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-sp_cortexm.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-aes.lo: \ + wolfcrypt/src/port/arm/$(am__dirstamp) \ + wolfcrypt/src/port/arm/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_aes.lo: \ + wolfcrypt/src/port/af_alg/$(am__dirstamp) \ + wolfcrypt/src/port/af_alg/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512.lo: \ + wolfcrypt/src/port/arm/$(am__dirstamp) \ + wolfcrypt/src/port/arm/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512-asm.lo: \ + wolfcrypt/src/port/arm/$(am__dirstamp) \ + wolfcrypt/src/port/arm/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-sha512-asm.lo: \ + wolfcrypt/src/port/arm/$(am__dirstamp) \ + wolfcrypt/src/port/arm/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-logging.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-wc_port.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-error.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-wc_encrypt.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-signature.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-wolfmath.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-memory.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-asn.lo: wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-coding.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-poly1305.lo: \ + wolfcrypt/src/port/arm/$(am__dirstamp) \ + wolfcrypt/src/port/arm/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-poly1305.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-poly1305_asm.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-arc4.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-md4.lo: wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-md5.lo: wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-pwdbased.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-pkcs12.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-dsa.lo: wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-camellia.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-md2.lo: wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-ripemd.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-blake2b.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-blake2s.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-hc128.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-rabbit.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-chacha.lo: \ + wolfcrypt/src/port/arm/$(am__dirstamp) \ + wolfcrypt/src/port/arm/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-chacha.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-chacha_asm.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-chacha20_poly1305.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-misc.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-tfm.lo: wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-integer.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-curve25519.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-ed25519.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-fe_low_mem.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-fe_x25519_asm.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-curve25519.lo: \ + wolfcrypt/src/port/arm/$(am__dirstamp) \ + wolfcrypt/src/port/arm/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-curve25519.lo: \ + wolfcrypt/src/port/arm/$(am__dirstamp) \ + wolfcrypt/src/port/arm/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-fe_operations.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-ge_low_mem.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-ge_operations.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-curve448.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-ed448.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-fe_448.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-ge_448.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-compress.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-pkcs7.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-srp.lo: wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-idea.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/af_alg/src_libwolfssl_la-wc_afalg.lo: \ + wolfcrypt/src/port/af_alg/$(am__dirstamp) \ + wolfcrypt/src/port/af_alg/$(DEPDIR)/$(am__dirstamp) +src/$(am__dirstamp): + @$(MKDIR_P) src + @: > src/$(am__dirstamp) +src/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/$(DEPDIR) + @: > src/$(DEPDIR)/$(am__dirstamp) +src/libwolfssl_la-internal.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libwolfssl_la-wolfio.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libwolfssl_la-keys.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libwolfssl_la-ssl.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libwolfssl_la-tls.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libwolfssl_la-tls13.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libwolfssl_la-ocsp.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libwolfssl_la-crl.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libwolfssl_la-sniffer.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-cryptocb.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/src_libwolfssl_la-wc_pkcs11.lo: \ + wolfcrypt/src/$(am__dirstamp) \ + wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/devcrypto/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/port/devcrypto + @: > wolfcrypt/src/port/devcrypto/$(am__dirstamp) +wolfcrypt/src/port/devcrypto/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/port/devcrypto/$(DEPDIR) + @: > wolfcrypt/src/port/devcrypto/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_hash.lo: \ + wolfcrypt/src/port/devcrypto/$(am__dirstamp) \ + wolfcrypt/src/port/devcrypto/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_aes.lo: \ + wolfcrypt/src/port/devcrypto/$(am__dirstamp) \ + wolfcrypt/src/port/devcrypto/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/devcrypto/src_libwolfssl_la-wc_devcrypto.lo: \ + wolfcrypt/src/port/devcrypto/$(am__dirstamp) \ + wolfcrypt/src/port/devcrypto/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/cavium/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/port/cavium + @: > wolfcrypt/src/port/cavium/$(am__dirstamp) +wolfcrypt/src/port/cavium/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/port/cavium/$(DEPDIR) + @: > wolfcrypt/src/port/cavium/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_nitrox.lo: \ + wolfcrypt/src/port/cavium/$(am__dirstamp) \ + wolfcrypt/src/port/cavium/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_octeon_sync.lo: \ + wolfcrypt/src/port/cavium/$(am__dirstamp) \ + wolfcrypt/src/port/cavium/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/intel/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/port/intel + @: > wolfcrypt/src/port/intel/$(am__dirstamp) +wolfcrypt/src/port/intel/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/port/intel/$(DEPDIR) + @: > wolfcrypt/src/port/intel/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist.lo: \ + wolfcrypt/src/port/intel/$(am__dirstamp) \ + wolfcrypt/src/port/intel/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_mem.lo: \ + wolfcrypt/src/port/intel/$(am__dirstamp) \ + wolfcrypt/src/port/intel/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_sync.lo: \ + wolfcrypt/src/port/intel/$(am__dirstamp) \ + wolfcrypt/src/port/intel/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/atmel/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/port/atmel + @: > wolfcrypt/src/port/atmel/$(am__dirstamp) +wolfcrypt/src/port/atmel/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/src/port/atmel/$(DEPDIR) + @: > wolfcrypt/src/port/atmel/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/src/port/atmel/src_libwolfssl_la-atmel.lo: \ + wolfcrypt/src/port/atmel/$(am__dirstamp) \ + wolfcrypt/src/port/atmel/$(DEPDIR)/$(am__dirstamp) + +src/libwolfssl.la: $(src_libwolfssl_la_OBJECTS) $(src_libwolfssl_la_DEPENDENCIES) $(EXTRA_src_libwolfssl_la_DEPENDENCIES) src/$(am__dirstamp) + $(AM_V_CCLD)$(src_libwolfssl_la_LINK) -rpath $(libdir) $(src_libwolfssl_la_OBJECTS) $(src_libwolfssl_la_LIBADD) $(LIBS) +examples/benchmark/$(am__dirstamp): + @$(MKDIR_P) examples/benchmark + @: > examples/benchmark/$(am__dirstamp) +examples/benchmark/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) examples/benchmark/$(DEPDIR) + @: > examples/benchmark/$(DEPDIR)/$(am__dirstamp) +examples/benchmark/tls_bench.$(OBJEXT): \ + examples/benchmark/$(am__dirstamp) \ + examples/benchmark/$(DEPDIR)/$(am__dirstamp) + +examples/benchmark/tls_bench$(EXEEXT): $(examples_benchmark_tls_bench_OBJECTS) $(examples_benchmark_tls_bench_DEPENDENCIES) $(EXTRA_examples_benchmark_tls_bench_DEPENDENCIES) examples/benchmark/$(am__dirstamp) + @rm -f examples/benchmark/tls_bench$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(examples_benchmark_tls_bench_OBJECTS) $(examples_benchmark_tls_bench_LDADD) $(LIBS) examples/client/$(am__dirstamp): @$(MKDIR_P) examples/client @: > examples/client/$(am__dirstamp) @@ -1602,6 +3832,38 @@ examples/echoserver/echoserver.$(OBJEXT): \ examples/echoserver/echoserver$(EXEEXT): $(examples_echoserver_echoserver_OBJECTS) $(examples_echoserver_echoserver_DEPENDENCIES) $(EXTRA_examples_echoserver_echoserver_DEPENDENCIES) examples/echoserver/$(am__dirstamp) @rm -f examples/echoserver/echoserver$(EXEEXT) $(AM_V_CCLD)$(LINK) $(examples_echoserver_echoserver_OBJECTS) $(examples_echoserver_echoserver_LDADD) $(LIBS) +examples/sctp/$(am__dirstamp): + @$(MKDIR_P) examples/sctp + @: > examples/sctp/$(am__dirstamp) +examples/sctp/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) examples/sctp/$(DEPDIR) + @: > examples/sctp/$(DEPDIR)/$(am__dirstamp) +examples/sctp/sctp-client.$(OBJEXT): examples/sctp/$(am__dirstamp) \ + examples/sctp/$(DEPDIR)/$(am__dirstamp) + +examples/sctp/sctp-client$(EXEEXT): $(examples_sctp_sctp_client_OBJECTS) $(examples_sctp_sctp_client_DEPENDENCIES) $(EXTRA_examples_sctp_sctp_client_DEPENDENCIES) examples/sctp/$(am__dirstamp) + @rm -f examples/sctp/sctp-client$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(examples_sctp_sctp_client_OBJECTS) $(examples_sctp_sctp_client_LDADD) $(LIBS) +examples/sctp/sctp-client-dtls.$(OBJEXT): \ + examples/sctp/$(am__dirstamp) \ + examples/sctp/$(DEPDIR)/$(am__dirstamp) + +examples/sctp/sctp-client-dtls$(EXEEXT): $(examples_sctp_sctp_client_dtls_OBJECTS) $(examples_sctp_sctp_client_dtls_DEPENDENCIES) $(EXTRA_examples_sctp_sctp_client_dtls_DEPENDENCIES) examples/sctp/$(am__dirstamp) + @rm -f examples/sctp/sctp-client-dtls$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(examples_sctp_sctp_client_dtls_OBJECTS) $(examples_sctp_sctp_client_dtls_LDADD) $(LIBS) +examples/sctp/sctp-server.$(OBJEXT): examples/sctp/$(am__dirstamp) \ + examples/sctp/$(DEPDIR)/$(am__dirstamp) + +examples/sctp/sctp-server$(EXEEXT): $(examples_sctp_sctp_server_OBJECTS) $(examples_sctp_sctp_server_DEPENDENCIES) $(EXTRA_examples_sctp_sctp_server_DEPENDENCIES) examples/sctp/$(am__dirstamp) + @rm -f examples/sctp/sctp-server$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(examples_sctp_sctp_server_OBJECTS) $(examples_sctp_sctp_server_LDADD) $(LIBS) +examples/sctp/sctp-server-dtls.$(OBJEXT): \ + examples/sctp/$(am__dirstamp) \ + examples/sctp/$(DEPDIR)/$(am__dirstamp) + +examples/sctp/sctp-server-dtls$(EXEEXT): $(examples_sctp_sctp_server_dtls_OBJECTS) $(examples_sctp_sctp_server_dtls_DEPENDENCIES) $(EXTRA_examples_sctp_sctp_server_dtls_DEPENDENCIES) examples/sctp/$(am__dirstamp) + @rm -f examples/sctp/sctp-server-dtls$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(examples_sctp_sctp_server_dtls_OBJECTS) $(examples_sctp_sctp_server_dtls_LDADD) $(LIBS) examples/server/$(am__dirstamp): @$(MKDIR_P) examples/server @: > examples/server/$(am__dirstamp) @@ -1647,13 +3909,15 @@ tests/$(am__dirstamp): tests/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tests/$(DEPDIR) @: > tests/$(DEPDIR)/$(am__dirstamp) -tests/tests_unit_test-unit.$(OBJEXT): tests/$(am__dirstamp) \ +tests/unit_test-unit.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) -tests/tests_unit_test-api.$(OBJEXT): tests/$(am__dirstamp) \ +tests/unit_test-api.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) -tests/tests_unit_test-suites.$(OBJEXT): tests/$(am__dirstamp) \ +tests/unit_test-suites.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) -tests/tests_unit_test-hash.$(OBJEXT): tests/$(am__dirstamp) \ +tests/unit_test-hash.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) +tests/unit_test-srp.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) examples/client/tests_unit_test-client.$(OBJEXT): \ examples/client/$(am__dirstamp) \ @@ -1665,9 +3929,15 @@ examples/server/tests_unit_test-server.$(OBJEXT): \ tests/unit.test$(EXEEXT): $(tests_unit_test_OBJECTS) $(tests_unit_test_DEPENDENCIES) $(EXTRA_tests_unit_test_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/unit.test$(EXEEXT) $(AM_V_CCLD)$(tests_unit_test_LINK) $(tests_unit_test_OBJECTS) $(tests_unit_test_LDADD) $(LIBS) -ctaocrypt/test/testsuite_testsuite_test-test.$(OBJEXT): \ - ctaocrypt/test/$(am__dirstamp) \ - ctaocrypt/test/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/test/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/test + @: > wolfcrypt/test/$(am__dirstamp) +wolfcrypt/test/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/test/$(DEPDIR) + @: > wolfcrypt/test/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/test/testsuite_testsuite_test-test.$(OBJEXT): \ + wolfcrypt/test/$(am__dirstamp) \ + wolfcrypt/test/$(DEPDIR)/$(am__dirstamp) examples/client/testsuite_testsuite_test-client.$(OBJEXT): \ examples/client/$(am__dirstamp) \ examples/client/$(DEPDIR)/$(am__dirstamp) @@ -1686,22 +3956,41 @@ testsuite/$(am__dirstamp): testsuite/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) testsuite/$(DEPDIR) @: > testsuite/$(DEPDIR)/$(am__dirstamp) -testsuite/testsuite_testsuite_test-testsuite.$(OBJEXT): \ +testsuite/testsuite_test-testsuite.$(OBJEXT): \ testsuite/$(am__dirstamp) testsuite/$(DEPDIR)/$(am__dirstamp) testsuite/testsuite.test$(EXEEXT): $(testsuite_testsuite_test_OBJECTS) $(testsuite_testsuite_test_DEPENDENCIES) $(EXTRA_testsuite_testsuite_test_DEPENDENCIES) testsuite/$(am__dirstamp) @rm -f testsuite/testsuite.test$(EXEEXT) $(AM_V_CCLD)$(testsuite_testsuite_test_LINK) $(testsuite_testsuite_test_OBJECTS) $(testsuite_testsuite_test_LDADD) $(LIBS) +wolfcrypt/benchmark/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/benchmark + @: > wolfcrypt/benchmark/$(am__dirstamp) +wolfcrypt/benchmark/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) wolfcrypt/benchmark/$(DEPDIR) + @: > wolfcrypt/benchmark/$(DEPDIR)/$(am__dirstamp) +wolfcrypt/benchmark/benchmark.$(OBJEXT): \ + wolfcrypt/benchmark/$(am__dirstamp) \ + wolfcrypt/benchmark/$(DEPDIR)/$(am__dirstamp) + +wolfcrypt/benchmark/benchmark$(EXEEXT): $(wolfcrypt_benchmark_benchmark_OBJECTS) $(wolfcrypt_benchmark_benchmark_DEPENDENCIES) $(EXTRA_wolfcrypt_benchmark_benchmark_DEPENDENCIES) wolfcrypt/benchmark/$(am__dirstamp) + @rm -f wolfcrypt/benchmark/benchmark$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(wolfcrypt_benchmark_benchmark_OBJECTS) $(wolfcrypt_benchmark_benchmark_LDADD) $(LIBS) +wolfcrypt/test/test.$(OBJEXT): wolfcrypt/test/$(am__dirstamp) \ + wolfcrypt/test/$(DEPDIR)/$(am__dirstamp) + +wolfcrypt/test/testwolfcrypt$(EXEEXT): $(wolfcrypt_test_testwolfcrypt_OBJECTS) $(wolfcrypt_test_testwolfcrypt_DEPENDENCIES) $(EXTRA_wolfcrypt_test_testwolfcrypt_DEPENDENCIES) wolfcrypt/test/$(am__dirstamp) + @rm -f wolfcrypt/test/testwolfcrypt$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(wolfcrypt_test_testwolfcrypt_OBJECTS) $(wolfcrypt_test_testwolfcrypt_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) - -rm -f ctaocrypt/benchmark/*.$(OBJEXT) -rm -f ctaocrypt/src/*.$(OBJEXT) -rm -f ctaocrypt/src/*.lo - -rm -f ctaocrypt/test/*.$(OBJEXT) + -rm -f examples/benchmark/*.$(OBJEXT) -rm -f examples/client/*.$(OBJEXT) -rm -f examples/echoclient/*.$(OBJEXT) -rm -f examples/echoserver/*.$(OBJEXT) + -rm -f examples/sctp/*.$(OBJEXT) -rm -f examples/server/*.$(OBJEXT) -rm -f mcapi/*.$(OBJEXT) -rm -f src/*.$(OBJEXT) @@ -1709,75 +3998,293 @@ mostlyclean-compile: -rm -f sslSniffer/sslSnifferTest/*.$(OBJEXT) -rm -f tests/*.$(OBJEXT) -rm -f testsuite/*.$(OBJEXT) + -rm -f wolfcrypt/benchmark/*.$(OBJEXT) + -rm -f wolfcrypt/src/*.$(OBJEXT) + -rm -f wolfcrypt/src/*.lo + -rm -f wolfcrypt/src/port/af_alg/*.$(OBJEXT) + -rm -f wolfcrypt/src/port/af_alg/*.lo + -rm -f wolfcrypt/src/port/arm/*.$(OBJEXT) + -rm -f wolfcrypt/src/port/arm/*.lo + -rm -f wolfcrypt/src/port/atmel/*.$(OBJEXT) + -rm -f wolfcrypt/src/port/atmel/*.lo + -rm -f wolfcrypt/src/port/cavium/*.$(OBJEXT) + -rm -f wolfcrypt/src/port/cavium/*.lo + -rm -f wolfcrypt/src/port/devcrypto/*.$(OBJEXT) + -rm -f wolfcrypt/src/port/devcrypto/*.lo + -rm -f wolfcrypt/src/port/intel/*.$(OBJEXT) + -rm -f wolfcrypt/src/port/intel/*.lo + -rm -f wolfcrypt/test/*.$(OBJEXT) + -rm -f wolfcrypt/user-crypto/src/*.$(OBJEXT) + -rm -f wolfcrypt/user-crypto/src/*.lo distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/benchmark/$(DEPDIR)/benchmark.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-aes.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-arc4.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-asn.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-blake2b.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-camellia.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-coding.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-compress.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-des3.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-dh.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-dsa.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-ecc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-error.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-fips.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-fips_test.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-hc128.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-hmac.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-integer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-logging.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-md2.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-md4.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-md5.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-memory.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-misc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-pkcs7.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-pwdbased.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-rabbit.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-random.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-ripemd.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-rsa.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-sha.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-sha256.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-sha512.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-tfm.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-wc_port.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-wolfcrypt_first.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-wolfcrypt_last.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/test/$(DEPDIR)/test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@examples/client/$(DEPDIR)/client.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@examples/client/$(DEPDIR)/tests_unit_test-client.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@examples/client/$(DEPDIR)/testsuite_testsuite_test-client.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@examples/echoclient/$(DEPDIR)/echoclient.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@examples/echoclient/$(DEPDIR)/testsuite_testsuite_test-echoclient.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@examples/echoserver/$(DEPDIR)/echoserver.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@examples/echoserver/$(DEPDIR)/testsuite_testsuite_test-echoserver.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@examples/server/$(DEPDIR)/server.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@examples/server/$(DEPDIR)/tests_unit_test-server.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@examples/server/$(DEPDIR)/testsuite_testsuite_test-server.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@mcapi/$(DEPDIR)/crypto.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@mcapi/$(DEPDIR)/mcapi_test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/src_libcyassl_la-crl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/src_libcyassl_la-internal.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/src_libcyassl_la-io.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/src_libcyassl_la-keys.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/src_libcyassl_la-ocsp.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/src_libcyassl_la-sniffer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/src_libcyassl_la-ssl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/src_libcyassl_la-tls.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@sslSniffer/sslSnifferTest/$(DEPDIR)/snifftest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_unit_test-api.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_unit_test-hash.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_unit_test-suites.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_unit_test-unit.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@testsuite/$(DEPDIR)/testsuite_testsuite_test-testsuite.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/benchmark/$(DEPDIR)/tls_bench.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/client/$(DEPDIR)/client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/client/$(DEPDIR)/tests_unit_test-client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/client/$(DEPDIR)/testsuite_testsuite_test-client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/echoclient/$(DEPDIR)/echoclient.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/echoclient/$(DEPDIR)/testsuite_testsuite_test-echoclient.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/echoserver/$(DEPDIR)/echoserver.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/echoserver/$(DEPDIR)/testsuite_testsuite_test-echoserver.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/sctp/$(DEPDIR)/sctp-client-dtls.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/sctp/$(DEPDIR)/sctp-client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/sctp/$(DEPDIR)/sctp-server-dtls.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/sctp/$(DEPDIR)/sctp-server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/server/$(DEPDIR)/server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/server/$(DEPDIR)/tests_unit_test-server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@examples/server/$(DEPDIR)/testsuite_testsuite_test-server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@mcapi/$(DEPDIR)/crypto.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@mcapi/$(DEPDIR)/mcapi_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwolfssl_la-crl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwolfssl_la-internal.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwolfssl_la-keys.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwolfssl_la-ocsp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwolfssl_la-sniffer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwolfssl_la-ssl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwolfssl_la-tls.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwolfssl_la-tls13.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwolfssl_la-wolfio.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@sslSniffer/sslSnifferTest/$(DEPDIR)/snifftest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/unit_test-api.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/unit_test-hash.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/unit_test-srp.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/unit_test-suites.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/unit_test-unit.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@testsuite/$(DEPDIR)/testsuite_test-testsuite.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/benchmark/$(DEPDIR)/benchmark.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_asm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_gcm_asm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-arc4.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-asn.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-async.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2b.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2s.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-camellia.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha20_poly1305.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha_asm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cmac.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-coding.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-compress.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cpuid.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cryptocb.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve25519.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve448.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dsa.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ecc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed25519.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed448.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-error.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_448.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_low_mem.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_operations.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_x25519_asm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_448.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_low_mem.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_operations.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hash.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hc128.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-idea.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-integer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-logging.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md2.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md4.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md5.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-memory.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-misc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs12.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs7.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305_asm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pwdbased.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rabbit.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ripemd.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-selftest.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256_asm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha3.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512_asm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-signature.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm32.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm64.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_armthumb.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c32.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c64.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_cortexm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_int.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64_asm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-srp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-tfm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_encrypt.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_pkcs11.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_port.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfevent.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfmath.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_aes.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_hash.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-wc_afalg.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-curve25519.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-sha512-asm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-aes.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-chacha.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-curve25519.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-poly1305.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha256.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512-asm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/atmel/$(DEPDIR)/src_libwolfssl_la-atmel.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_nitrox.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_octeon_sync.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_aes.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_hash.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-wc_devcrypto.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_mem.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_sync.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/test/$(DEPDIR)/test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@wolfcrypt/user-crypto/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.S.o: +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ $< + +.S.obj: +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.S.lo: +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCCAS_TRUE@ $(LTCPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LTCPPASCOMPILE) -c -o $@ $< + +wolfcrypt/src/src_libwolfssl_la-aes_asm.lo: wolfcrypt/src/aes_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-aes_asm.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_asm.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-aes_asm.lo `test -f 'wolfcrypt/src/aes_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/aes_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_asm.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_asm.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='wolfcrypt/src/aes_asm.S' object='wolfcrypt/src/src_libwolfssl_la-aes_asm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-aes_asm.lo `test -f 'wolfcrypt/src/aes_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/aes_asm.S + +wolfcrypt/src/src_libwolfssl_la-aes_gcm_asm.lo: wolfcrypt/src/aes_gcm_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-aes_gcm_asm.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_gcm_asm.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-aes_gcm_asm.lo `test -f 'wolfcrypt/src/aes_gcm_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/aes_gcm_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_gcm_asm.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_gcm_asm.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='wolfcrypt/src/aes_gcm_asm.S' object='wolfcrypt/src/src_libwolfssl_la-aes_gcm_asm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-aes_gcm_asm.lo `test -f 'wolfcrypt/src/aes_gcm_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/aes_gcm_asm.S + +wolfcrypt/src/src_libwolfssl_la-sha256_asm.lo: wolfcrypt/src/sha256_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sha256_asm.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256_asm.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sha256_asm.lo `test -f 'wolfcrypt/src/sha256_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/sha256_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256_asm.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256_asm.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='wolfcrypt/src/sha256_asm.S' object='wolfcrypt/src/src_libwolfssl_la-sha256_asm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sha256_asm.lo `test -f 'wolfcrypt/src/sha256_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/sha256_asm.S + +wolfcrypt/src/src_libwolfssl_la-sha512_asm.lo: wolfcrypt/src/sha512_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sha512_asm.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512_asm.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sha512_asm.lo `test -f 'wolfcrypt/src/sha512_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/sha512_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512_asm.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512_asm.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='wolfcrypt/src/sha512_asm.S' object='wolfcrypt/src/src_libwolfssl_la-sha512_asm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sha512_asm.lo `test -f 'wolfcrypt/src/sha512_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/sha512_asm.S + +wolfcrypt/src/src_libwolfssl_la-sp_x86_64_asm.lo: wolfcrypt/src/sp_x86_64_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sp_x86_64_asm.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64_asm.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sp_x86_64_asm.lo `test -f 'wolfcrypt/src/sp_x86_64_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/sp_x86_64_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64_asm.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64_asm.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='wolfcrypt/src/sp_x86_64_asm.S' object='wolfcrypt/src/src_libwolfssl_la-sp_x86_64_asm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sp_x86_64_asm.lo `test -f 'wolfcrypt/src/sp_x86_64_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/sp_x86_64_asm.S + +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512-asm.lo: wolfcrypt/src/port/arm/armv8-sha512-asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512-asm.lo -MD -MP -MF wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512-asm.Tpo -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512-asm.lo `test -f 'wolfcrypt/src/port/arm/armv8-sha512-asm.S' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-sha512-asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512-asm.Tpo wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512-asm.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='wolfcrypt/src/port/arm/armv8-sha512-asm.S' object='wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512-asm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512-asm.lo `test -f 'wolfcrypt/src/port/arm/armv8-sha512-asm.S' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-sha512-asm.S + +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-sha512-asm.lo: wolfcrypt/src/port/arm/armv8-32-sha512-asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-sha512-asm.lo -MD -MP -MF wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-sha512-asm.Tpo -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-sha512-asm.lo `test -f 'wolfcrypt/src/port/arm/armv8-32-sha512-asm.S' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-32-sha512-asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-sha512-asm.Tpo wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-sha512-asm.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='wolfcrypt/src/port/arm/armv8-32-sha512-asm.S' object='wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-sha512-asm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-sha512-asm.lo `test -f 'wolfcrypt/src/port/arm/armv8-32-sha512-asm.S' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-32-sha512-asm.S + +wolfcrypt/src/src_libwolfssl_la-poly1305_asm.lo: wolfcrypt/src/poly1305_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-poly1305_asm.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305_asm.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-poly1305_asm.lo `test -f 'wolfcrypt/src/poly1305_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/poly1305_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305_asm.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305_asm.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='wolfcrypt/src/poly1305_asm.S' object='wolfcrypt/src/src_libwolfssl_la-poly1305_asm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-poly1305_asm.lo `test -f 'wolfcrypt/src/poly1305_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/poly1305_asm.S + +wolfcrypt/src/src_libwolfssl_la-chacha_asm.lo: wolfcrypt/src/chacha_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-chacha_asm.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha_asm.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-chacha_asm.lo `test -f 'wolfcrypt/src/chacha_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/chacha_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha_asm.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha_asm.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='wolfcrypt/src/chacha_asm.S' object='wolfcrypt/src/src_libwolfssl_la-chacha_asm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-chacha_asm.lo `test -f 'wolfcrypt/src/chacha_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/chacha_asm.S + +wolfcrypt/src/src_libwolfssl_la-fe_x25519_asm.lo: wolfcrypt/src/fe_x25519_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-fe_x25519_asm.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_x25519_asm.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-fe_x25519_asm.lo `test -f 'wolfcrypt/src/fe_x25519_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/fe_x25519_asm.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_x25519_asm.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_x25519_asm.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='wolfcrypt/src/fe_x25519_asm.S' object='wolfcrypt/src/src_libwolfssl_la-fe_x25519_asm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-fe_x25519_asm.lo `test -f 'wolfcrypt/src/fe_x25519_asm.S' || echo '$(srcdir)/'`wolfcrypt/src/fe_x25519_asm.S + +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-curve25519.lo: wolfcrypt/src/port/arm/armv8-32-curve25519.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-curve25519.lo -MD -MP -MF wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-curve25519.Tpo -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-curve25519.lo `test -f 'wolfcrypt/src/port/arm/armv8-32-curve25519.S' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-32-curve25519.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-curve25519.Tpo wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-curve25519.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='wolfcrypt/src/port/arm/armv8-32-curve25519.S' object='wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-curve25519.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-32-curve25519.lo `test -f 'wolfcrypt/src/port/arm/armv8-32-curve25519.S' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-32-curve25519.S + +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-curve25519.lo: wolfcrypt/src/port/arm/armv8-curve25519.S +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-curve25519.lo -MD -MP -MF wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-curve25519.Tpo -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-curve25519.lo `test -f 'wolfcrypt/src/port/arm/armv8-curve25519.S' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-curve25519.S +@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-curve25519.Tpo wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-curve25519.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='wolfcrypt/src/port/arm/armv8-curve25519.S' object='wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-curve25519.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-curve25519.lo `test -f 'wolfcrypt/src/port/arm/armv8-curve25519.S' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-curve25519.S .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -1803,369 +4310,859 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< -ctaocrypt/src/src_libcyassl_la-wolfcrypt_first.lo: ctaocrypt/src/wolfcrypt_first.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-wolfcrypt_first.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-wolfcrypt_first.Tpo -c -o ctaocrypt/src/src_libcyassl_la-wolfcrypt_first.lo `test -f 'ctaocrypt/src/wolfcrypt_first.c' || echo '$(srcdir)/'`ctaocrypt/src/wolfcrypt_first.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-wolfcrypt_first.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-wolfcrypt_first.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/wolfcrypt_first.c' object='ctaocrypt/src/src_libcyassl_la-wolfcrypt_first.lo' libtool=yes @AMDEPBACKSLASH@ +ctaocrypt/src/src_libwolfssl_la-wolfcrypt_first.lo: ctaocrypt/src/wolfcrypt_first.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libwolfssl_la-wolfcrypt_first.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Tpo -c -o ctaocrypt/src/src_libwolfssl_la-wolfcrypt_first.lo `test -f 'ctaocrypt/src/wolfcrypt_first.c' || echo '$(srcdir)/'`ctaocrypt/src/wolfcrypt_first.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Tpo ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/wolfcrypt_first.c' object='ctaocrypt/src/src_libwolfssl_la-wolfcrypt_first.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-wolfcrypt_first.lo `test -f 'ctaocrypt/src/wolfcrypt_first.c' || echo '$(srcdir)/'`ctaocrypt/src/wolfcrypt_first.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libwolfssl_la-wolfcrypt_first.lo `test -f 'ctaocrypt/src/wolfcrypt_first.c' || echo '$(srcdir)/'`ctaocrypt/src/wolfcrypt_first.c -src/src_libcyassl_la-internal.lo: src/internal.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT src/src_libcyassl_la-internal.lo -MD -MP -MF src/$(DEPDIR)/src_libcyassl_la-internal.Tpo -c -o src/src_libcyassl_la-internal.lo `test -f 'src/internal.c' || echo '$(srcdir)/'`src/internal.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/src_libcyassl_la-internal.Tpo src/$(DEPDIR)/src_libcyassl_la-internal.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/internal.c' object='src/src_libcyassl_la-internal.lo' libtool=yes @AMDEPBACKSLASH@ +ctaocrypt/src/src_libwolfssl_la-hmac.lo: ctaocrypt/src/hmac.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libwolfssl_la-hmac.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Tpo -c -o ctaocrypt/src/src_libwolfssl_la-hmac.lo `test -f 'ctaocrypt/src/hmac.c' || echo '$(srcdir)/'`ctaocrypt/src/hmac.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Tpo ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/hmac.c' object='ctaocrypt/src/src_libwolfssl_la-hmac.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o src/src_libcyassl_la-internal.lo `test -f 'src/internal.c' || echo '$(srcdir)/'`src/internal.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libwolfssl_la-hmac.lo `test -f 'ctaocrypt/src/hmac.c' || echo '$(srcdir)/'`ctaocrypt/src/hmac.c -src/src_libcyassl_la-io.lo: src/io.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT src/src_libcyassl_la-io.lo -MD -MP -MF src/$(DEPDIR)/src_libcyassl_la-io.Tpo -c -o src/src_libcyassl_la-io.lo `test -f 'src/io.c' || echo '$(srcdir)/'`src/io.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/src_libcyassl_la-io.Tpo src/$(DEPDIR)/src_libcyassl_la-io.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/io.c' object='src/src_libcyassl_la-io.lo' libtool=yes @AMDEPBACKSLASH@ +ctaocrypt/src/src_libwolfssl_la-random.lo: ctaocrypt/src/random.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libwolfssl_la-random.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Tpo -c -o ctaocrypt/src/src_libwolfssl_la-random.lo `test -f 'ctaocrypt/src/random.c' || echo '$(srcdir)/'`ctaocrypt/src/random.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Tpo ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/random.c' object='ctaocrypt/src/src_libwolfssl_la-random.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o src/src_libcyassl_la-io.lo `test -f 'src/io.c' || echo '$(srcdir)/'`src/io.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libwolfssl_la-random.lo `test -f 'ctaocrypt/src/random.c' || echo '$(srcdir)/'`ctaocrypt/src/random.c -src/src_libcyassl_la-keys.lo: src/keys.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT src/src_libcyassl_la-keys.lo -MD -MP -MF src/$(DEPDIR)/src_libcyassl_la-keys.Tpo -c -o src/src_libcyassl_la-keys.lo `test -f 'src/keys.c' || echo '$(srcdir)/'`src/keys.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/src_libcyassl_la-keys.Tpo src/$(DEPDIR)/src_libcyassl_la-keys.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/keys.c' object='src/src_libcyassl_la-keys.lo' libtool=yes @AMDEPBACKSLASH@ +ctaocrypt/src/src_libwolfssl_la-sha256.lo: ctaocrypt/src/sha256.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libwolfssl_la-sha256.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Tpo -c -o ctaocrypt/src/src_libwolfssl_la-sha256.lo `test -f 'ctaocrypt/src/sha256.c' || echo '$(srcdir)/'`ctaocrypt/src/sha256.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Tpo ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/sha256.c' object='ctaocrypt/src/src_libwolfssl_la-sha256.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o src/src_libcyassl_la-keys.lo `test -f 'src/keys.c' || echo '$(srcdir)/'`src/keys.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libwolfssl_la-sha256.lo `test -f 'ctaocrypt/src/sha256.c' || echo '$(srcdir)/'`ctaocrypt/src/sha256.c -src/src_libcyassl_la-ssl.lo: src/ssl.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT src/src_libcyassl_la-ssl.lo -MD -MP -MF src/$(DEPDIR)/src_libcyassl_la-ssl.Tpo -c -o src/src_libcyassl_la-ssl.lo `test -f 'src/ssl.c' || echo '$(srcdir)/'`src/ssl.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/src_libcyassl_la-ssl.Tpo src/$(DEPDIR)/src_libcyassl_la-ssl.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ssl.c' object='src/src_libcyassl_la-ssl.lo' libtool=yes @AMDEPBACKSLASH@ +ctaocrypt/src/src_libwolfssl_la-rsa.lo: ctaocrypt/src/rsa.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libwolfssl_la-rsa.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Tpo -c -o ctaocrypt/src/src_libwolfssl_la-rsa.lo `test -f 'ctaocrypt/src/rsa.c' || echo '$(srcdir)/'`ctaocrypt/src/rsa.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Tpo ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/rsa.c' object='ctaocrypt/src/src_libwolfssl_la-rsa.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o src/src_libcyassl_la-ssl.lo `test -f 'src/ssl.c' || echo '$(srcdir)/'`src/ssl.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libwolfssl_la-rsa.lo `test -f 'ctaocrypt/src/rsa.c' || echo '$(srcdir)/'`ctaocrypt/src/rsa.c -src/src_libcyassl_la-tls.lo: src/tls.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT src/src_libcyassl_la-tls.lo -MD -MP -MF src/$(DEPDIR)/src_libcyassl_la-tls.Tpo -c -o src/src_libcyassl_la-tls.lo `test -f 'src/tls.c' || echo '$(srcdir)/'`src/tls.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/src_libcyassl_la-tls.Tpo src/$(DEPDIR)/src_libcyassl_la-tls.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/tls.c' object='src/src_libcyassl_la-tls.lo' libtool=yes @AMDEPBACKSLASH@ +ctaocrypt/src/src_libwolfssl_la-aes.lo: ctaocrypt/src/aes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libwolfssl_la-aes.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Tpo -c -o ctaocrypt/src/src_libwolfssl_la-aes.lo `test -f 'ctaocrypt/src/aes.c' || echo '$(srcdir)/'`ctaocrypt/src/aes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Tpo ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/aes.c' object='ctaocrypt/src/src_libwolfssl_la-aes.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o src/src_libcyassl_la-tls.lo `test -f 'src/tls.c' || echo '$(srcdir)/'`src/tls.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libwolfssl_la-aes.lo `test -f 'ctaocrypt/src/aes.c' || echo '$(srcdir)/'`ctaocrypt/src/aes.c -ctaocrypt/src/src_libcyassl_la-hmac.lo: ctaocrypt/src/hmac.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-hmac.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-hmac.Tpo -c -o ctaocrypt/src/src_libcyassl_la-hmac.lo `test -f 'ctaocrypt/src/hmac.c' || echo '$(srcdir)/'`ctaocrypt/src/hmac.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-hmac.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-hmac.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/hmac.c' object='ctaocrypt/src/src_libcyassl_la-hmac.lo' libtool=yes @AMDEPBACKSLASH@ +ctaocrypt/src/src_libwolfssl_la-des3.lo: ctaocrypt/src/des3.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libwolfssl_la-des3.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Tpo -c -o ctaocrypt/src/src_libwolfssl_la-des3.lo `test -f 'ctaocrypt/src/des3.c' || echo '$(srcdir)/'`ctaocrypt/src/des3.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Tpo ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/des3.c' object='ctaocrypt/src/src_libwolfssl_la-des3.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-hmac.lo `test -f 'ctaocrypt/src/hmac.c' || echo '$(srcdir)/'`ctaocrypt/src/hmac.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libwolfssl_la-des3.lo `test -f 'ctaocrypt/src/des3.c' || echo '$(srcdir)/'`ctaocrypt/src/des3.c -ctaocrypt/src/src_libcyassl_la-random.lo: ctaocrypt/src/random.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-random.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-random.Tpo -c -o ctaocrypt/src/src_libcyassl_la-random.lo `test -f 'ctaocrypt/src/random.c' || echo '$(srcdir)/'`ctaocrypt/src/random.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-random.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-random.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/random.c' object='ctaocrypt/src/src_libcyassl_la-random.lo' libtool=yes @AMDEPBACKSLASH@ +ctaocrypt/src/src_libwolfssl_la-sha.lo: ctaocrypt/src/sha.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libwolfssl_la-sha.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Tpo -c -o ctaocrypt/src/src_libwolfssl_la-sha.lo `test -f 'ctaocrypt/src/sha.c' || echo '$(srcdir)/'`ctaocrypt/src/sha.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Tpo ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/sha.c' object='ctaocrypt/src/src_libwolfssl_la-sha.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-random.lo `test -f 'ctaocrypt/src/random.c' || echo '$(srcdir)/'`ctaocrypt/src/random.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libwolfssl_la-sha.lo `test -f 'ctaocrypt/src/sha.c' || echo '$(srcdir)/'`ctaocrypt/src/sha.c -ctaocrypt/src/src_libcyassl_la-sha256.lo: ctaocrypt/src/sha256.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-sha256.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-sha256.Tpo -c -o ctaocrypt/src/src_libcyassl_la-sha256.lo `test -f 'ctaocrypt/src/sha256.c' || echo '$(srcdir)/'`ctaocrypt/src/sha256.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-sha256.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-sha256.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/sha256.c' object='ctaocrypt/src/src_libcyassl_la-sha256.lo' libtool=yes @AMDEPBACKSLASH@ +ctaocrypt/src/src_libwolfssl_la-sha512.lo: ctaocrypt/src/sha512.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libwolfssl_la-sha512.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Tpo -c -o ctaocrypt/src/src_libwolfssl_la-sha512.lo `test -f 'ctaocrypt/src/sha512.c' || echo '$(srcdir)/'`ctaocrypt/src/sha512.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Tpo ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/sha512.c' object='ctaocrypt/src/src_libwolfssl_la-sha512.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-sha256.lo `test -f 'ctaocrypt/src/sha256.c' || echo '$(srcdir)/'`ctaocrypt/src/sha256.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libwolfssl_la-sha512.lo `test -f 'ctaocrypt/src/sha512.c' || echo '$(srcdir)/'`ctaocrypt/src/sha512.c -ctaocrypt/src/src_libcyassl_la-logging.lo: ctaocrypt/src/logging.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-logging.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-logging.Tpo -c -o ctaocrypt/src/src_libcyassl_la-logging.lo `test -f 'ctaocrypt/src/logging.c' || echo '$(srcdir)/'`ctaocrypt/src/logging.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-logging.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-logging.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/logging.c' object='ctaocrypt/src/src_libcyassl_la-logging.lo' libtool=yes @AMDEPBACKSLASH@ +ctaocrypt/src/src_libwolfssl_la-fips.lo: ctaocrypt/src/fips.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libwolfssl_la-fips.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Tpo -c -o ctaocrypt/src/src_libwolfssl_la-fips.lo `test -f 'ctaocrypt/src/fips.c' || echo '$(srcdir)/'`ctaocrypt/src/fips.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Tpo ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/fips.c' object='ctaocrypt/src/src_libwolfssl_la-fips.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-logging.lo `test -f 'ctaocrypt/src/logging.c' || echo '$(srcdir)/'`ctaocrypt/src/logging.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libwolfssl_la-fips.lo `test -f 'ctaocrypt/src/fips.c' || echo '$(srcdir)/'`ctaocrypt/src/fips.c -ctaocrypt/src/src_libcyassl_la-wc_port.lo: ctaocrypt/src/wc_port.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-wc_port.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-wc_port.Tpo -c -o ctaocrypt/src/src_libcyassl_la-wc_port.lo `test -f 'ctaocrypt/src/wc_port.c' || echo '$(srcdir)/'`ctaocrypt/src/wc_port.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-wc_port.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-wc_port.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/wc_port.c' object='ctaocrypt/src/src_libcyassl_la-wc_port.lo' libtool=yes @AMDEPBACKSLASH@ +ctaocrypt/src/src_libwolfssl_la-fips_test.lo: ctaocrypt/src/fips_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libwolfssl_la-fips_test.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Tpo -c -o ctaocrypt/src/src_libwolfssl_la-fips_test.lo `test -f 'ctaocrypt/src/fips_test.c' || echo '$(srcdir)/'`ctaocrypt/src/fips_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Tpo ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/fips_test.c' object='ctaocrypt/src/src_libwolfssl_la-fips_test.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-wc_port.lo `test -f 'ctaocrypt/src/wc_port.c' || echo '$(srcdir)/'`ctaocrypt/src/wc_port.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libwolfssl_la-fips_test.lo `test -f 'ctaocrypt/src/fips_test.c' || echo '$(srcdir)/'`ctaocrypt/src/fips_test.c -ctaocrypt/src/src_libcyassl_la-error.lo: ctaocrypt/src/error.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-error.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-error.Tpo -c -o ctaocrypt/src/src_libcyassl_la-error.lo `test -f 'ctaocrypt/src/error.c' || echo '$(srcdir)/'`ctaocrypt/src/error.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-error.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-error.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/error.c' object='ctaocrypt/src/src_libcyassl_la-error.lo' libtool=yes @AMDEPBACKSLASH@ +ctaocrypt/src/src_libwolfssl_la-wolfcrypt_last.lo: ctaocrypt/src/wolfcrypt_last.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libwolfssl_la-wolfcrypt_last.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Tpo -c -o ctaocrypt/src/src_libwolfssl_la-wolfcrypt_last.lo `test -f 'ctaocrypt/src/wolfcrypt_last.c' || echo '$(srcdir)/'`ctaocrypt/src/wolfcrypt_last.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Tpo ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/wolfcrypt_last.c' object='ctaocrypt/src/src_libwolfssl_la-wolfcrypt_last.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-error.lo `test -f 'ctaocrypt/src/error.c' || echo '$(srcdir)/'`ctaocrypt/src/error.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libwolfssl_la-wolfcrypt_last.lo `test -f 'ctaocrypt/src/wolfcrypt_last.c' || echo '$(srcdir)/'`ctaocrypt/src/wolfcrypt_last.c -ctaocrypt/src/src_libcyassl_la-memory.lo: ctaocrypt/src/memory.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-memory.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-memory.Tpo -c -o ctaocrypt/src/src_libcyassl_la-memory.lo `test -f 'ctaocrypt/src/memory.c' || echo '$(srcdir)/'`ctaocrypt/src/memory.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-memory.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-memory.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/memory.c' object='ctaocrypt/src/src_libcyassl_la-memory.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-wolfcrypt_first.lo: wolfcrypt/src/wolfcrypt_first.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-wolfcrypt_first.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-wolfcrypt_first.lo `test -f 'wolfcrypt/src/wolfcrypt_first.c' || echo '$(srcdir)/'`wolfcrypt/src/wolfcrypt_first.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/wolfcrypt_first.c' object='wolfcrypt/src/src_libwolfssl_la-wolfcrypt_first.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-memory.lo `test -f 'ctaocrypt/src/memory.c' || echo '$(srcdir)/'`ctaocrypt/src/memory.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-wolfcrypt_first.lo `test -f 'wolfcrypt/src/wolfcrypt_first.c' || echo '$(srcdir)/'`wolfcrypt/src/wolfcrypt_first.c -ctaocrypt/src/src_libcyassl_la-rsa.lo: ctaocrypt/src/rsa.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-rsa.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-rsa.Tpo -c -o ctaocrypt/src/src_libcyassl_la-rsa.lo `test -f 'ctaocrypt/src/rsa.c' || echo '$(srcdir)/'`ctaocrypt/src/rsa.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-rsa.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-rsa.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/rsa.c' object='ctaocrypt/src/src_libcyassl_la-rsa.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-hmac.lo: wolfcrypt/src/hmac.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-hmac.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-hmac.lo `test -f 'wolfcrypt/src/hmac.c' || echo '$(srcdir)/'`wolfcrypt/src/hmac.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/hmac.c' object='wolfcrypt/src/src_libwolfssl_la-hmac.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-rsa.lo `test -f 'ctaocrypt/src/rsa.c' || echo '$(srcdir)/'`ctaocrypt/src/rsa.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-hmac.lo `test -f 'wolfcrypt/src/hmac.c' || echo '$(srcdir)/'`wolfcrypt/src/hmac.c -ctaocrypt/src/src_libcyassl_la-dh.lo: ctaocrypt/src/dh.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-dh.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-dh.Tpo -c -o ctaocrypt/src/src_libcyassl_la-dh.lo `test -f 'ctaocrypt/src/dh.c' || echo '$(srcdir)/'`ctaocrypt/src/dh.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-dh.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-dh.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/dh.c' object='ctaocrypt/src/src_libcyassl_la-dh.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-random.lo: wolfcrypt/src/random.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-random.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-random.lo `test -f 'wolfcrypt/src/random.c' || echo '$(srcdir)/'`wolfcrypt/src/random.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/random.c' object='wolfcrypt/src/src_libwolfssl_la-random.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-dh.lo `test -f 'ctaocrypt/src/dh.c' || echo '$(srcdir)/'`ctaocrypt/src/dh.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-random.lo `test -f 'wolfcrypt/src/random.c' || echo '$(srcdir)/'`wolfcrypt/src/random.c -ctaocrypt/src/src_libcyassl_la-asn.lo: ctaocrypt/src/asn.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-asn.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-asn.Tpo -c -o ctaocrypt/src/src_libcyassl_la-asn.lo `test -f 'ctaocrypt/src/asn.c' || echo '$(srcdir)/'`ctaocrypt/src/asn.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-asn.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-asn.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/asn.c' object='ctaocrypt/src/src_libcyassl_la-asn.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-sha256.lo: wolfcrypt/src/sha256.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sha256.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sha256.lo `test -f 'wolfcrypt/src/sha256.c' || echo '$(srcdir)/'`wolfcrypt/src/sha256.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/sha256.c' object='wolfcrypt/src/src_libwolfssl_la-sha256.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-asn.lo `test -f 'ctaocrypt/src/asn.c' || echo '$(srcdir)/'`ctaocrypt/src/asn.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sha256.lo `test -f 'wolfcrypt/src/sha256.c' || echo '$(srcdir)/'`wolfcrypt/src/sha256.c -ctaocrypt/src/src_libcyassl_la-fips.lo: ctaocrypt/src/fips.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-fips.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-fips.Tpo -c -o ctaocrypt/src/src_libcyassl_la-fips.lo `test -f 'ctaocrypt/src/fips.c' || echo '$(srcdir)/'`ctaocrypt/src/fips.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-fips.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-fips.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/fips.c' object='ctaocrypt/src/src_libcyassl_la-fips.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-rsa.lo: wolfcrypt/src/rsa.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-rsa.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-rsa.lo `test -f 'wolfcrypt/src/rsa.c' || echo '$(srcdir)/'`wolfcrypt/src/rsa.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/rsa.c' object='wolfcrypt/src/src_libwolfssl_la-rsa.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-fips.lo `test -f 'ctaocrypt/src/fips.c' || echo '$(srcdir)/'`ctaocrypt/src/fips.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-rsa.lo `test -f 'wolfcrypt/src/rsa.c' || echo '$(srcdir)/'`wolfcrypt/src/rsa.c -ctaocrypt/src/src_libcyassl_la-fips_test.lo: ctaocrypt/src/fips_test.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-fips_test.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-fips_test.Tpo -c -o ctaocrypt/src/src_libcyassl_la-fips_test.lo `test -f 'ctaocrypt/src/fips_test.c' || echo '$(srcdir)/'`ctaocrypt/src/fips_test.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-fips_test.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-fips_test.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/fips_test.c' object='ctaocrypt/src/src_libcyassl_la-fips_test.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-ecc.lo: wolfcrypt/src/ecc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-ecc.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ecc.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-ecc.lo `test -f 'wolfcrypt/src/ecc.c' || echo '$(srcdir)/'`wolfcrypt/src/ecc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ecc.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ecc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/ecc.c' object='wolfcrypt/src/src_libwolfssl_la-ecc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-fips_test.lo `test -f 'ctaocrypt/src/fips_test.c' || echo '$(srcdir)/'`ctaocrypt/src/fips_test.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-ecc.lo `test -f 'wolfcrypt/src/ecc.c' || echo '$(srcdir)/'`wolfcrypt/src/ecc.c -ctaocrypt/src/src_libcyassl_la-coding.lo: ctaocrypt/src/coding.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-coding.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-coding.Tpo -c -o ctaocrypt/src/src_libcyassl_la-coding.lo `test -f 'ctaocrypt/src/coding.c' || echo '$(srcdir)/'`ctaocrypt/src/coding.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-coding.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-coding.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/coding.c' object='ctaocrypt/src/src_libcyassl_la-coding.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-aes.lo: wolfcrypt/src/aes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-aes.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-aes.lo `test -f 'wolfcrypt/src/aes.c' || echo '$(srcdir)/'`wolfcrypt/src/aes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/aes.c' object='wolfcrypt/src/src_libwolfssl_la-aes.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-coding.lo `test -f 'ctaocrypt/src/coding.c' || echo '$(srcdir)/'`ctaocrypt/src/coding.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-aes.lo `test -f 'wolfcrypt/src/aes.c' || echo '$(srcdir)/'`wolfcrypt/src/aes.c -ctaocrypt/src/src_libcyassl_la-aes.lo: ctaocrypt/src/aes.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-aes.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-aes.Tpo -c -o ctaocrypt/src/src_libcyassl_la-aes.lo `test -f 'ctaocrypt/src/aes.c' || echo '$(srcdir)/'`ctaocrypt/src/aes.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-aes.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-aes.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/aes.c' object='ctaocrypt/src/src_libcyassl_la-aes.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-des3.lo: wolfcrypt/src/des3.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-des3.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-des3.lo `test -f 'wolfcrypt/src/des3.c' || echo '$(srcdir)/'`wolfcrypt/src/des3.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/des3.c' object='wolfcrypt/src/src_libwolfssl_la-des3.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-aes.lo `test -f 'ctaocrypt/src/aes.c' || echo '$(srcdir)/'`ctaocrypt/src/aes.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-des3.lo `test -f 'wolfcrypt/src/des3.c' || echo '$(srcdir)/'`wolfcrypt/src/des3.c -ctaocrypt/src/src_libcyassl_la-des3.lo: ctaocrypt/src/des3.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-des3.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-des3.Tpo -c -o ctaocrypt/src/src_libcyassl_la-des3.lo `test -f 'ctaocrypt/src/des3.c' || echo '$(srcdir)/'`ctaocrypt/src/des3.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-des3.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-des3.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/des3.c' object='ctaocrypt/src/src_libcyassl_la-des3.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-sha.lo: wolfcrypt/src/sha.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sha.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sha.lo `test -f 'wolfcrypt/src/sha.c' || echo '$(srcdir)/'`wolfcrypt/src/sha.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/sha.c' object='wolfcrypt/src/src_libwolfssl_la-sha.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-des3.lo `test -f 'ctaocrypt/src/des3.c' || echo '$(srcdir)/'`ctaocrypt/src/des3.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sha.lo `test -f 'wolfcrypt/src/sha.c' || echo '$(srcdir)/'`wolfcrypt/src/sha.c -ctaocrypt/src/src_libcyassl_la-sha.lo: ctaocrypt/src/sha.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-sha.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-sha.Tpo -c -o ctaocrypt/src/src_libcyassl_la-sha.lo `test -f 'ctaocrypt/src/sha.c' || echo '$(srcdir)/'`ctaocrypt/src/sha.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-sha.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-sha.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/sha.c' object='ctaocrypt/src/src_libcyassl_la-sha.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-sha512.lo: wolfcrypt/src/sha512.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sha512.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sha512.lo `test -f 'wolfcrypt/src/sha512.c' || echo '$(srcdir)/'`wolfcrypt/src/sha512.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/sha512.c' object='wolfcrypt/src/src_libwolfssl_la-sha512.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-sha.lo `test -f 'ctaocrypt/src/sha.c' || echo '$(srcdir)/'`ctaocrypt/src/sha.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sha512.lo `test -f 'wolfcrypt/src/sha512.c' || echo '$(srcdir)/'`wolfcrypt/src/sha512.c -ctaocrypt/src/src_libcyassl_la-arc4.lo: ctaocrypt/src/arc4.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-arc4.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-arc4.Tpo -c -o ctaocrypt/src/src_libcyassl_la-arc4.lo `test -f 'ctaocrypt/src/arc4.c' || echo '$(srcdir)/'`ctaocrypt/src/arc4.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-arc4.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-arc4.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/arc4.c' object='ctaocrypt/src/src_libcyassl_la-arc4.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-sha3.lo: wolfcrypt/src/sha3.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sha3.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha3.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sha3.lo `test -f 'wolfcrypt/src/sha3.c' || echo '$(srcdir)/'`wolfcrypt/src/sha3.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha3.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha3.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/sha3.c' object='wolfcrypt/src/src_libwolfssl_la-sha3.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-arc4.lo `test -f 'ctaocrypt/src/arc4.c' || echo '$(srcdir)/'`ctaocrypt/src/arc4.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sha3.lo `test -f 'wolfcrypt/src/sha3.c' || echo '$(srcdir)/'`wolfcrypt/src/sha3.c -ctaocrypt/src/src_libcyassl_la-md4.lo: ctaocrypt/src/md4.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-md4.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-md4.Tpo -c -o ctaocrypt/src/src_libcyassl_la-md4.lo `test -f 'ctaocrypt/src/md4.c' || echo '$(srcdir)/'`ctaocrypt/src/md4.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-md4.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-md4.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/md4.c' object='ctaocrypt/src/src_libcyassl_la-md4.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-dh.lo: wolfcrypt/src/dh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-dh.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dh.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-dh.lo `test -f 'wolfcrypt/src/dh.c' || echo '$(srcdir)/'`wolfcrypt/src/dh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dh.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/dh.c' object='wolfcrypt/src/src_libwolfssl_la-dh.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-md4.lo `test -f 'ctaocrypt/src/md4.c' || echo '$(srcdir)/'`ctaocrypt/src/md4.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-dh.lo `test -f 'wolfcrypt/src/dh.c' || echo '$(srcdir)/'`wolfcrypt/src/dh.c -ctaocrypt/src/src_libcyassl_la-md5.lo: ctaocrypt/src/md5.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-md5.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-md5.Tpo -c -o ctaocrypt/src/src_libcyassl_la-md5.lo `test -f 'ctaocrypt/src/md5.c' || echo '$(srcdir)/'`ctaocrypt/src/md5.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-md5.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-md5.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/md5.c' object='ctaocrypt/src/src_libcyassl_la-md5.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-cmac.lo: wolfcrypt/src/cmac.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-cmac.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cmac.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-cmac.lo `test -f 'wolfcrypt/src/cmac.c' || echo '$(srcdir)/'`wolfcrypt/src/cmac.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cmac.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cmac.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/cmac.c' object='wolfcrypt/src/src_libwolfssl_la-cmac.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-md5.lo `test -f 'ctaocrypt/src/md5.c' || echo '$(srcdir)/'`ctaocrypt/src/md5.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-cmac.lo `test -f 'wolfcrypt/src/cmac.c' || echo '$(srcdir)/'`wolfcrypt/src/cmac.c -ctaocrypt/src/src_libcyassl_la-pwdbased.lo: ctaocrypt/src/pwdbased.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-pwdbased.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-pwdbased.Tpo -c -o ctaocrypt/src/src_libcyassl_la-pwdbased.lo `test -f 'ctaocrypt/src/pwdbased.c' || echo '$(srcdir)/'`ctaocrypt/src/pwdbased.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-pwdbased.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-pwdbased.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/pwdbased.c' object='ctaocrypt/src/src_libcyassl_la-pwdbased.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-fips.lo: wolfcrypt/src/fips.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-fips.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-fips.lo `test -f 'wolfcrypt/src/fips.c' || echo '$(srcdir)/'`wolfcrypt/src/fips.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/fips.c' object='wolfcrypt/src/src_libwolfssl_la-fips.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-pwdbased.lo `test -f 'ctaocrypt/src/pwdbased.c' || echo '$(srcdir)/'`ctaocrypt/src/pwdbased.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-fips.lo `test -f 'wolfcrypt/src/fips.c' || echo '$(srcdir)/'`wolfcrypt/src/fips.c -ctaocrypt/src/src_libcyassl_la-dsa.lo: ctaocrypt/src/dsa.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-dsa.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-dsa.Tpo -c -o ctaocrypt/src/src_libcyassl_la-dsa.lo `test -f 'ctaocrypt/src/dsa.c' || echo '$(srcdir)/'`ctaocrypt/src/dsa.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-dsa.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-dsa.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/dsa.c' object='ctaocrypt/src/src_libcyassl_la-dsa.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-fips_test.lo: wolfcrypt/src/fips_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-fips_test.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-fips_test.lo `test -f 'wolfcrypt/src/fips_test.c' || echo '$(srcdir)/'`wolfcrypt/src/fips_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/fips_test.c' object='wolfcrypt/src/src_libwolfssl_la-fips_test.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-dsa.lo `test -f 'ctaocrypt/src/dsa.c' || echo '$(srcdir)/'`ctaocrypt/src/dsa.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-fips_test.lo `test -f 'wolfcrypt/src/fips_test.c' || echo '$(srcdir)/'`wolfcrypt/src/fips_test.c -ctaocrypt/src/src_libcyassl_la-camellia.lo: ctaocrypt/src/camellia.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-camellia.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-camellia.Tpo -c -o ctaocrypt/src/src_libcyassl_la-camellia.lo `test -f 'ctaocrypt/src/camellia.c' || echo '$(srcdir)/'`ctaocrypt/src/camellia.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-camellia.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-camellia.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/camellia.c' object='ctaocrypt/src/src_libcyassl_la-camellia.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-wolfcrypt_last.lo: wolfcrypt/src/wolfcrypt_last.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-wolfcrypt_last.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-wolfcrypt_last.lo `test -f 'wolfcrypt/src/wolfcrypt_last.c' || echo '$(srcdir)/'`wolfcrypt/src/wolfcrypt_last.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/wolfcrypt_last.c' object='wolfcrypt/src/src_libwolfssl_la-wolfcrypt_last.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-camellia.lo `test -f 'ctaocrypt/src/camellia.c' || echo '$(srcdir)/'`ctaocrypt/src/camellia.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-wolfcrypt_last.lo `test -f 'wolfcrypt/src/wolfcrypt_last.c' || echo '$(srcdir)/'`wolfcrypt/src/wolfcrypt_last.c -ctaocrypt/src/src_libcyassl_la-md2.lo: ctaocrypt/src/md2.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-md2.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-md2.Tpo -c -o ctaocrypt/src/src_libcyassl_la-md2.lo `test -f 'ctaocrypt/src/md2.c' || echo '$(srcdir)/'`ctaocrypt/src/md2.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-md2.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-md2.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/md2.c' object='ctaocrypt/src/src_libcyassl_la-md2.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-selftest.lo: wolfcrypt/src/selftest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-selftest.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-selftest.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-selftest.lo `test -f 'wolfcrypt/src/selftest.c' || echo '$(srcdir)/'`wolfcrypt/src/selftest.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-selftest.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-selftest.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/selftest.c' object='wolfcrypt/src/src_libwolfssl_la-selftest.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-md2.lo `test -f 'ctaocrypt/src/md2.c' || echo '$(srcdir)/'`ctaocrypt/src/md2.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-selftest.lo `test -f 'wolfcrypt/src/selftest.c' || echo '$(srcdir)/'`wolfcrypt/src/selftest.c -ctaocrypt/src/src_libcyassl_la-ripemd.lo: ctaocrypt/src/ripemd.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-ripemd.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-ripemd.Tpo -c -o ctaocrypt/src/src_libcyassl_la-ripemd.lo `test -f 'ctaocrypt/src/ripemd.c' || echo '$(srcdir)/'`ctaocrypt/src/ripemd.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-ripemd.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-ripemd.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/ripemd.c' object='ctaocrypt/src/src_libcyassl_la-ripemd.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-hash.lo: wolfcrypt/src/hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-hash.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hash.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-hash.lo `test -f 'wolfcrypt/src/hash.c' || echo '$(srcdir)/'`wolfcrypt/src/hash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hash.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hash.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/hash.c' object='wolfcrypt/src/src_libwolfssl_la-hash.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-ripemd.lo `test -f 'ctaocrypt/src/ripemd.c' || echo '$(srcdir)/'`ctaocrypt/src/ripemd.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-hash.lo `test -f 'wolfcrypt/src/hash.c' || echo '$(srcdir)/'`wolfcrypt/src/hash.c -ctaocrypt/src/src_libcyassl_la-sha512.lo: ctaocrypt/src/sha512.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-sha512.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-sha512.Tpo -c -o ctaocrypt/src/src_libcyassl_la-sha512.lo `test -f 'ctaocrypt/src/sha512.c' || echo '$(srcdir)/'`ctaocrypt/src/sha512.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-sha512.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-sha512.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/sha512.c' object='ctaocrypt/src/src_libcyassl_la-sha512.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-cpuid.lo: wolfcrypt/src/cpuid.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-cpuid.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cpuid.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-cpuid.lo `test -f 'wolfcrypt/src/cpuid.c' || echo '$(srcdir)/'`wolfcrypt/src/cpuid.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cpuid.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cpuid.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/cpuid.c' object='wolfcrypt/src/src_libwolfssl_la-cpuid.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-sha512.lo `test -f 'ctaocrypt/src/sha512.c' || echo '$(srcdir)/'`ctaocrypt/src/sha512.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-cpuid.lo `test -f 'wolfcrypt/src/cpuid.c' || echo '$(srcdir)/'`wolfcrypt/src/cpuid.c -ctaocrypt/src/src_libcyassl_la-blake2b.lo: ctaocrypt/src/blake2b.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-blake2b.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-blake2b.Tpo -c -o ctaocrypt/src/src_libcyassl_la-blake2b.lo `test -f 'ctaocrypt/src/blake2b.c' || echo '$(srcdir)/'`ctaocrypt/src/blake2b.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-blake2b.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-blake2b.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/blake2b.c' object='ctaocrypt/src/src_libcyassl_la-blake2b.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha256.lo: wolfcrypt/src/port/arm/armv8-sha256.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha256.lo -MD -MP -MF wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha256.Tpo -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha256.lo `test -f 'wolfcrypt/src/port/arm/armv8-sha256.c' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-sha256.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha256.Tpo wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha256.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/arm/armv8-sha256.c' object='wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha256.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-blake2b.lo `test -f 'ctaocrypt/src/blake2b.c' || echo '$(srcdir)/'`ctaocrypt/src/blake2b.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha256.lo `test -f 'wolfcrypt/src/port/arm/armv8-sha256.c' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-sha256.c -src/src_libcyassl_la-sniffer.lo: src/sniffer.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT src/src_libcyassl_la-sniffer.lo -MD -MP -MF src/$(DEPDIR)/src_libcyassl_la-sniffer.Tpo -c -o src/src_libcyassl_la-sniffer.lo `test -f 'src/sniffer.c' || echo '$(srcdir)/'`src/sniffer.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/src_libcyassl_la-sniffer.Tpo src/$(DEPDIR)/src_libcyassl_la-sniffer.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/sniffer.c' object='src/src_libcyassl_la-sniffer.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_hash.lo: wolfcrypt/src/port/af_alg/afalg_hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_hash.lo -MD -MP -MF wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_hash.Tpo -c -o wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_hash.lo `test -f 'wolfcrypt/src/port/af_alg/afalg_hash.c' || echo '$(srcdir)/'`wolfcrypt/src/port/af_alg/afalg_hash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_hash.Tpo wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_hash.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/af_alg/afalg_hash.c' object='wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_hash.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o src/src_libcyassl_la-sniffer.lo `test -f 'src/sniffer.c' || echo '$(srcdir)/'`src/sniffer.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_hash.lo `test -f 'wolfcrypt/src/port/af_alg/afalg_hash.c' || echo '$(srcdir)/'`wolfcrypt/src/port/af_alg/afalg_hash.c -ctaocrypt/src/src_libcyassl_la-hc128.lo: ctaocrypt/src/hc128.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-hc128.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-hc128.Tpo -c -o ctaocrypt/src/src_libcyassl_la-hc128.lo `test -f 'ctaocrypt/src/hc128.c' || echo '$(srcdir)/'`ctaocrypt/src/hc128.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-hc128.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-hc128.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/hc128.c' object='ctaocrypt/src/src_libcyassl_la-hc128.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-wolfevent.lo: wolfcrypt/src/wolfevent.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-wolfevent.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfevent.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-wolfevent.lo `test -f 'wolfcrypt/src/wolfevent.c' || echo '$(srcdir)/'`wolfcrypt/src/wolfevent.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfevent.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfevent.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/wolfevent.c' object='wolfcrypt/src/src_libwolfssl_la-wolfevent.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-hc128.lo `test -f 'ctaocrypt/src/hc128.c' || echo '$(srcdir)/'`ctaocrypt/src/hc128.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-wolfevent.lo `test -f 'wolfcrypt/src/wolfevent.c' || echo '$(srcdir)/'`wolfcrypt/src/wolfevent.c -ctaocrypt/src/src_libcyassl_la-rabbit.lo: ctaocrypt/src/rabbit.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-rabbit.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-rabbit.Tpo -c -o ctaocrypt/src/src_libcyassl_la-rabbit.lo `test -f 'ctaocrypt/src/rabbit.c' || echo '$(srcdir)/'`ctaocrypt/src/rabbit.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-rabbit.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-rabbit.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/rabbit.c' object='ctaocrypt/src/src_libcyassl_la-rabbit.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-async.lo: wolfcrypt/src/async.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-async.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-async.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-async.lo `test -f 'wolfcrypt/src/async.c' || echo '$(srcdir)/'`wolfcrypt/src/async.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-async.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-async.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/async.c' object='wolfcrypt/src/src_libwolfssl_la-async.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-rabbit.lo `test -f 'ctaocrypt/src/rabbit.c' || echo '$(srcdir)/'`ctaocrypt/src/rabbit.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-async.lo `test -f 'wolfcrypt/src/async.c' || echo '$(srcdir)/'`wolfcrypt/src/async.c -ctaocrypt/src/src_libcyassl_la-misc.lo: ctaocrypt/src/misc.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-misc.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-misc.Tpo -c -o ctaocrypt/src/src_libcyassl_la-misc.lo `test -f 'ctaocrypt/src/misc.c' || echo '$(srcdir)/'`ctaocrypt/src/misc.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-misc.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-misc.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/misc.c' object='ctaocrypt/src/src_libcyassl_la-misc.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/user-crypto/src/src_libwolfssl_la-rsa.lo: wolfcrypt/user-crypto/src/rsa.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/user-crypto/src/src_libwolfssl_la-rsa.lo -MD -MP -MF wolfcrypt/user-crypto/src/$(DEPDIR)/src_libwolfssl_la-rsa.Tpo -c -o wolfcrypt/user-crypto/src/src_libwolfssl_la-rsa.lo `test -f 'wolfcrypt/user-crypto/src/rsa.c' || echo '$(srcdir)/'`wolfcrypt/user-crypto/src/rsa.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/user-crypto/src/$(DEPDIR)/src_libwolfssl_la-rsa.Tpo wolfcrypt/user-crypto/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/user-crypto/src/rsa.c' object='wolfcrypt/user-crypto/src/src_libwolfssl_la-rsa.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-misc.lo `test -f 'ctaocrypt/src/misc.c' || echo '$(srcdir)/'`ctaocrypt/src/misc.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/user-crypto/src/src_libwolfssl_la-rsa.lo `test -f 'wolfcrypt/user-crypto/src/rsa.c' || echo '$(srcdir)/'`wolfcrypt/user-crypto/src/rsa.c -ctaocrypt/src/src_libcyassl_la-tfm.lo: ctaocrypt/src/tfm.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-tfm.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-tfm.Tpo -c -o ctaocrypt/src/src_libcyassl_la-tfm.lo `test -f 'ctaocrypt/src/tfm.c' || echo '$(srcdir)/'`ctaocrypt/src/tfm.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-tfm.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-tfm.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/tfm.c' object='ctaocrypt/src/src_libcyassl_la-tfm.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-sp_c32.lo: wolfcrypt/src/sp_c32.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sp_c32.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c32.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sp_c32.lo `test -f 'wolfcrypt/src/sp_c32.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_c32.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c32.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/sp_c32.c' object='wolfcrypt/src/src_libwolfssl_la-sp_c32.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-tfm.lo `test -f 'ctaocrypt/src/tfm.c' || echo '$(srcdir)/'`ctaocrypt/src/tfm.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sp_c32.lo `test -f 'wolfcrypt/src/sp_c32.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_c32.c -ctaocrypt/src/src_libcyassl_la-integer.lo: ctaocrypt/src/integer.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-integer.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-integer.Tpo -c -o ctaocrypt/src/src_libcyassl_la-integer.lo `test -f 'ctaocrypt/src/integer.c' || echo '$(srcdir)/'`ctaocrypt/src/integer.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-integer.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-integer.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/integer.c' object='ctaocrypt/src/src_libcyassl_la-integer.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-sp_c64.lo: wolfcrypt/src/sp_c64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sp_c64.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c64.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sp_c64.lo `test -f 'wolfcrypt/src/sp_c64.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_c64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c64.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c64.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/sp_c64.c' object='wolfcrypt/src/src_libwolfssl_la-sp_c64.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-integer.lo `test -f 'ctaocrypt/src/integer.c' || echo '$(srcdir)/'`ctaocrypt/src/integer.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sp_c64.lo `test -f 'wolfcrypt/src/sp_c64.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_c64.c -ctaocrypt/src/src_libcyassl_la-ecc.lo: ctaocrypt/src/ecc.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-ecc.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-ecc.Tpo -c -o ctaocrypt/src/src_libcyassl_la-ecc.lo `test -f 'ctaocrypt/src/ecc.c' || echo '$(srcdir)/'`ctaocrypt/src/ecc.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-ecc.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-ecc.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/ecc.c' object='ctaocrypt/src/src_libcyassl_la-ecc.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-sp_x86_64.lo: wolfcrypt/src/sp_x86_64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sp_x86_64.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sp_x86_64.lo `test -f 'wolfcrypt/src/sp_x86_64.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_x86_64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/sp_x86_64.c' object='wolfcrypt/src/src_libwolfssl_la-sp_x86_64.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-ecc.lo `test -f 'ctaocrypt/src/ecc.c' || echo '$(srcdir)/'`ctaocrypt/src/ecc.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sp_x86_64.lo `test -f 'wolfcrypt/src/sp_x86_64.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_x86_64.c -src/src_libcyassl_la-ocsp.lo: src/ocsp.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT src/src_libcyassl_la-ocsp.lo -MD -MP -MF src/$(DEPDIR)/src_libcyassl_la-ocsp.Tpo -c -o src/src_libcyassl_la-ocsp.lo `test -f 'src/ocsp.c' || echo '$(srcdir)/'`src/ocsp.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/src_libcyassl_la-ocsp.Tpo src/$(DEPDIR)/src_libcyassl_la-ocsp.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ocsp.c' object='src/src_libcyassl_la-ocsp.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-sp_arm32.lo: wolfcrypt/src/sp_arm32.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sp_arm32.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm32.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sp_arm32.lo `test -f 'wolfcrypt/src/sp_arm32.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_arm32.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm32.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/sp_arm32.c' object='wolfcrypt/src/src_libwolfssl_la-sp_arm32.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o src/src_libcyassl_la-ocsp.lo `test -f 'src/ocsp.c' || echo '$(srcdir)/'`src/ocsp.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sp_arm32.lo `test -f 'wolfcrypt/src/sp_arm32.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_arm32.c -src/src_libcyassl_la-crl.lo: src/crl.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT src/src_libcyassl_la-crl.lo -MD -MP -MF src/$(DEPDIR)/src_libcyassl_la-crl.Tpo -c -o src/src_libcyassl_la-crl.lo `test -f 'src/crl.c' || echo '$(srcdir)/'`src/crl.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/src_libcyassl_la-crl.Tpo src/$(DEPDIR)/src_libcyassl_la-crl.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/crl.c' object='src/src_libcyassl_la-crl.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-sp_armthumb.lo: wolfcrypt/src/sp_armthumb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sp_armthumb.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_armthumb.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sp_armthumb.lo `test -f 'wolfcrypt/src/sp_armthumb.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_armthumb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_armthumb.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_armthumb.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/sp_armthumb.c' object='wolfcrypt/src/src_libwolfssl_la-sp_armthumb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o src/src_libcyassl_la-crl.lo `test -f 'src/crl.c' || echo '$(srcdir)/'`src/crl.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sp_armthumb.lo `test -f 'wolfcrypt/src/sp_armthumb.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_armthumb.c -ctaocrypt/src/src_libcyassl_la-compress.lo: ctaocrypt/src/compress.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-compress.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-compress.Tpo -c -o ctaocrypt/src/src_libcyassl_la-compress.lo `test -f 'ctaocrypt/src/compress.c' || echo '$(srcdir)/'`ctaocrypt/src/compress.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-compress.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-compress.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/compress.c' object='ctaocrypt/src/src_libcyassl_la-compress.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-sp_arm64.lo: wolfcrypt/src/sp_arm64.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sp_arm64.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm64.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sp_arm64.lo `test -f 'wolfcrypt/src/sp_arm64.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_arm64.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm64.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm64.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/sp_arm64.c' object='wolfcrypt/src/src_libwolfssl_la-sp_arm64.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-compress.lo `test -f 'ctaocrypt/src/compress.c' || echo '$(srcdir)/'`ctaocrypt/src/compress.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sp_arm64.lo `test -f 'wolfcrypt/src/sp_arm64.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_arm64.c -ctaocrypt/src/src_libcyassl_la-pkcs7.lo: ctaocrypt/src/pkcs7.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-pkcs7.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-pkcs7.Tpo -c -o ctaocrypt/src/src_libcyassl_la-pkcs7.lo `test -f 'ctaocrypt/src/pkcs7.c' || echo '$(srcdir)/'`ctaocrypt/src/pkcs7.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-pkcs7.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-pkcs7.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/pkcs7.c' object='ctaocrypt/src/src_libcyassl_la-pkcs7.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-sp_int.lo: wolfcrypt/src/sp_int.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sp_int.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_int.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sp_int.lo `test -f 'wolfcrypt/src/sp_int.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_int.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_int.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_int.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/sp_int.c' object='wolfcrypt/src/src_libwolfssl_la-sp_int.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-pkcs7.lo `test -f 'ctaocrypt/src/pkcs7.c' || echo '$(srcdir)/'`ctaocrypt/src/pkcs7.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sp_int.lo `test -f 'wolfcrypt/src/sp_int.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_int.c -ctaocrypt/src/src_libcyassl_la-wolfcrypt_last.lo: ctaocrypt/src/wolfcrypt_last.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -MT ctaocrypt/src/src_libcyassl_la-wolfcrypt_last.lo -MD -MP -MF ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-wolfcrypt_last.Tpo -c -o ctaocrypt/src/src_libcyassl_la-wolfcrypt_last.lo `test -f 'ctaocrypt/src/wolfcrypt_last.c' || echo '$(srcdir)/'`ctaocrypt/src/wolfcrypt_last.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-wolfcrypt_last.Tpo ctaocrypt/src/$(DEPDIR)/src_libcyassl_la-wolfcrypt_last.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/src/wolfcrypt_last.c' object='ctaocrypt/src/src_libcyassl_la-wolfcrypt_last.lo' libtool=yes @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-sp_cortexm.lo: wolfcrypt/src/sp_cortexm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-sp_cortexm.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_cortexm.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-sp_cortexm.lo `test -f 'wolfcrypt/src/sp_cortexm.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_cortexm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_cortexm.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_cortexm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/sp_cortexm.c' object='wolfcrypt/src/src_libwolfssl_la-sp_cortexm.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libcyassl_la_CPPFLAGS) $(CPPFLAGS) $(src_libcyassl_la_CFLAGS) $(CFLAGS) -c -o ctaocrypt/src/src_libcyassl_la-wolfcrypt_last.lo `test -f 'ctaocrypt/src/wolfcrypt_last.c' || echo '$(srcdir)/'`ctaocrypt/src/wolfcrypt_last.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-sp_cortexm.lo `test -f 'wolfcrypt/src/sp_cortexm.c' || echo '$(srcdir)/'`wolfcrypt/src/sp_cortexm.c -tests/tests_unit_test-unit.o: tests/unit.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/tests_unit_test-unit.o -MD -MP -MF tests/$(DEPDIR)/tests_unit_test-unit.Tpo -c -o tests/tests_unit_test-unit.o `test -f 'tests/unit.c' || echo '$(srcdir)/'`tests/unit.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_unit_test-unit.Tpo tests/$(DEPDIR)/tests_unit_test-unit.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/unit.c' object='tests/tests_unit_test-unit.o' libtool=no @AMDEPBACKSLASH@ +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-aes.lo: wolfcrypt/src/port/arm/armv8-aes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-aes.lo -MD -MP -MF wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-aes.Tpo -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-aes.lo `test -f 'wolfcrypt/src/port/arm/armv8-aes.c' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-aes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-aes.Tpo wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-aes.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/arm/armv8-aes.c' object='wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-aes.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/tests_unit_test-unit.o `test -f 'tests/unit.c' || echo '$(srcdir)/'`tests/unit.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-aes.lo `test -f 'wolfcrypt/src/port/arm/armv8-aes.c' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-aes.c -tests/tests_unit_test-unit.obj: tests/unit.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/tests_unit_test-unit.obj -MD -MP -MF tests/$(DEPDIR)/tests_unit_test-unit.Tpo -c -o tests/tests_unit_test-unit.obj `if test -f 'tests/unit.c'; then $(CYGPATH_W) 'tests/unit.c'; else $(CYGPATH_W) '$(srcdir)/tests/unit.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_unit_test-unit.Tpo tests/$(DEPDIR)/tests_unit_test-unit.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/unit.c' object='tests/tests_unit_test-unit.obj' libtool=no @AMDEPBACKSLASH@ +wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_aes.lo: wolfcrypt/src/port/af_alg/afalg_aes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_aes.lo -MD -MP -MF wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_aes.Tpo -c -o wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_aes.lo `test -f 'wolfcrypt/src/port/af_alg/afalg_aes.c' || echo '$(srcdir)/'`wolfcrypt/src/port/af_alg/afalg_aes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_aes.Tpo wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_aes.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/af_alg/afalg_aes.c' object='wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_aes.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/tests_unit_test-unit.obj `if test -f 'tests/unit.c'; then $(CYGPATH_W) 'tests/unit.c'; else $(CYGPATH_W) '$(srcdir)/tests/unit.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/af_alg/src_libwolfssl_la-afalg_aes.lo `test -f 'wolfcrypt/src/port/af_alg/afalg_aes.c' || echo '$(srcdir)/'`wolfcrypt/src/port/af_alg/afalg_aes.c -tests/tests_unit_test-api.o: tests/api.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/tests_unit_test-api.o -MD -MP -MF tests/$(DEPDIR)/tests_unit_test-api.Tpo -c -o tests/tests_unit_test-api.o `test -f 'tests/api.c' || echo '$(srcdir)/'`tests/api.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_unit_test-api.Tpo tests/$(DEPDIR)/tests_unit_test-api.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/api.c' object='tests/tests_unit_test-api.o' libtool=no @AMDEPBACKSLASH@ +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512.lo: wolfcrypt/src/port/arm/armv8-sha512.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512.lo -MD -MP -MF wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512.Tpo -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512.lo `test -f 'wolfcrypt/src/port/arm/armv8-sha512.c' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-sha512.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512.Tpo wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/arm/armv8-sha512.c' object='wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/tests_unit_test-api.o `test -f 'tests/api.c' || echo '$(srcdir)/'`tests/api.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-sha512.lo `test -f 'wolfcrypt/src/port/arm/armv8-sha512.c' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-sha512.c -tests/tests_unit_test-api.obj: tests/api.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/tests_unit_test-api.obj -MD -MP -MF tests/$(DEPDIR)/tests_unit_test-api.Tpo -c -o tests/tests_unit_test-api.obj `if test -f 'tests/api.c'; then $(CYGPATH_W) 'tests/api.c'; else $(CYGPATH_W) '$(srcdir)/tests/api.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_unit_test-api.Tpo tests/$(DEPDIR)/tests_unit_test-api.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/api.c' object='tests/tests_unit_test-api.obj' libtool=no @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-logging.lo: wolfcrypt/src/logging.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-logging.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-logging.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-logging.lo `test -f 'wolfcrypt/src/logging.c' || echo '$(srcdir)/'`wolfcrypt/src/logging.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-logging.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-logging.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/logging.c' object='wolfcrypt/src/src_libwolfssl_la-logging.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/tests_unit_test-api.obj `if test -f 'tests/api.c'; then $(CYGPATH_W) 'tests/api.c'; else $(CYGPATH_W) '$(srcdir)/tests/api.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-logging.lo `test -f 'wolfcrypt/src/logging.c' || echo '$(srcdir)/'`wolfcrypt/src/logging.c -tests/tests_unit_test-suites.o: tests/suites.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/tests_unit_test-suites.o -MD -MP -MF tests/$(DEPDIR)/tests_unit_test-suites.Tpo -c -o tests/tests_unit_test-suites.o `test -f 'tests/suites.c' || echo '$(srcdir)/'`tests/suites.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_unit_test-suites.Tpo tests/$(DEPDIR)/tests_unit_test-suites.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/suites.c' object='tests/tests_unit_test-suites.o' libtool=no @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-wc_port.lo: wolfcrypt/src/wc_port.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-wc_port.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_port.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-wc_port.lo `test -f 'wolfcrypt/src/wc_port.c' || echo '$(srcdir)/'`wolfcrypt/src/wc_port.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_port.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_port.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/wc_port.c' object='wolfcrypt/src/src_libwolfssl_la-wc_port.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/tests_unit_test-suites.o `test -f 'tests/suites.c' || echo '$(srcdir)/'`tests/suites.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-wc_port.lo `test -f 'wolfcrypt/src/wc_port.c' || echo '$(srcdir)/'`wolfcrypt/src/wc_port.c -tests/tests_unit_test-suites.obj: tests/suites.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/tests_unit_test-suites.obj -MD -MP -MF tests/$(DEPDIR)/tests_unit_test-suites.Tpo -c -o tests/tests_unit_test-suites.obj `if test -f 'tests/suites.c'; then $(CYGPATH_W) 'tests/suites.c'; else $(CYGPATH_W) '$(srcdir)/tests/suites.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_unit_test-suites.Tpo tests/$(DEPDIR)/tests_unit_test-suites.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/suites.c' object='tests/tests_unit_test-suites.obj' libtool=no @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-error.lo: wolfcrypt/src/error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-error.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-error.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-error.lo `test -f 'wolfcrypt/src/error.c' || echo '$(srcdir)/'`wolfcrypt/src/error.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-error.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-error.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/error.c' object='wolfcrypt/src/src_libwolfssl_la-error.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/tests_unit_test-suites.obj `if test -f 'tests/suites.c'; then $(CYGPATH_W) 'tests/suites.c'; else $(CYGPATH_W) '$(srcdir)/tests/suites.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-error.lo `test -f 'wolfcrypt/src/error.c' || echo '$(srcdir)/'`wolfcrypt/src/error.c -tests/tests_unit_test-hash.o: tests/hash.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/tests_unit_test-hash.o -MD -MP -MF tests/$(DEPDIR)/tests_unit_test-hash.Tpo -c -o tests/tests_unit_test-hash.o `test -f 'tests/hash.c' || echo '$(srcdir)/'`tests/hash.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_unit_test-hash.Tpo tests/$(DEPDIR)/tests_unit_test-hash.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/hash.c' object='tests/tests_unit_test-hash.o' libtool=no @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-wc_encrypt.lo: wolfcrypt/src/wc_encrypt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-wc_encrypt.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_encrypt.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-wc_encrypt.lo `test -f 'wolfcrypt/src/wc_encrypt.c' || echo '$(srcdir)/'`wolfcrypt/src/wc_encrypt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_encrypt.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_encrypt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/wc_encrypt.c' object='wolfcrypt/src/src_libwolfssl_la-wc_encrypt.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/tests_unit_test-hash.o `test -f 'tests/hash.c' || echo '$(srcdir)/'`tests/hash.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-wc_encrypt.lo `test -f 'wolfcrypt/src/wc_encrypt.c' || echo '$(srcdir)/'`wolfcrypt/src/wc_encrypt.c -tests/tests_unit_test-hash.obj: tests/hash.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/tests_unit_test-hash.obj -MD -MP -MF tests/$(DEPDIR)/tests_unit_test-hash.Tpo -c -o tests/tests_unit_test-hash.obj `if test -f 'tests/hash.c'; then $(CYGPATH_W) 'tests/hash.c'; else $(CYGPATH_W) '$(srcdir)/tests/hash.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_unit_test-hash.Tpo tests/$(DEPDIR)/tests_unit_test-hash.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/hash.c' object='tests/tests_unit_test-hash.obj' libtool=no @AMDEPBACKSLASH@ +wolfcrypt/src/src_libwolfssl_la-signature.lo: wolfcrypt/src/signature.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-signature.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-signature.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-signature.lo `test -f 'wolfcrypt/src/signature.c' || echo '$(srcdir)/'`wolfcrypt/src/signature.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-signature.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-signature.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/signature.c' object='wolfcrypt/src/src_libwolfssl_la-signature.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/tests_unit_test-hash.obj `if test -f 'tests/hash.c'; then $(CYGPATH_W) 'tests/hash.c'; else $(CYGPATH_W) '$(srcdir)/tests/hash.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-signature.lo `test -f 'wolfcrypt/src/signature.c' || echo '$(srcdir)/'`wolfcrypt/src/signature.c + +wolfcrypt/src/src_libwolfssl_la-wolfmath.lo: wolfcrypt/src/wolfmath.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-wolfmath.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfmath.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-wolfmath.lo `test -f 'wolfcrypt/src/wolfmath.c' || echo '$(srcdir)/'`wolfcrypt/src/wolfmath.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfmath.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfmath.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/wolfmath.c' object='wolfcrypt/src/src_libwolfssl_la-wolfmath.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-wolfmath.lo `test -f 'wolfcrypt/src/wolfmath.c' || echo '$(srcdir)/'`wolfcrypt/src/wolfmath.c + +wolfcrypt/src/src_libwolfssl_la-memory.lo: wolfcrypt/src/memory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-memory.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-memory.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-memory.lo `test -f 'wolfcrypt/src/memory.c' || echo '$(srcdir)/'`wolfcrypt/src/memory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-memory.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-memory.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/memory.c' object='wolfcrypt/src/src_libwolfssl_la-memory.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-memory.lo `test -f 'wolfcrypt/src/memory.c' || echo '$(srcdir)/'`wolfcrypt/src/memory.c + +wolfcrypt/src/src_libwolfssl_la-asn.lo: wolfcrypt/src/asn.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-asn.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-asn.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-asn.lo `test -f 'wolfcrypt/src/asn.c' || echo '$(srcdir)/'`wolfcrypt/src/asn.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-asn.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-asn.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/asn.c' object='wolfcrypt/src/src_libwolfssl_la-asn.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-asn.lo `test -f 'wolfcrypt/src/asn.c' || echo '$(srcdir)/'`wolfcrypt/src/asn.c + +wolfcrypt/src/src_libwolfssl_la-coding.lo: wolfcrypt/src/coding.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-coding.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-coding.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-coding.lo `test -f 'wolfcrypt/src/coding.c' || echo '$(srcdir)/'`wolfcrypt/src/coding.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-coding.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-coding.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/coding.c' object='wolfcrypt/src/src_libwolfssl_la-coding.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-coding.lo `test -f 'wolfcrypt/src/coding.c' || echo '$(srcdir)/'`wolfcrypt/src/coding.c + +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-poly1305.lo: wolfcrypt/src/port/arm/armv8-poly1305.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-poly1305.lo -MD -MP -MF wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-poly1305.Tpo -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-poly1305.lo `test -f 'wolfcrypt/src/port/arm/armv8-poly1305.c' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-poly1305.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-poly1305.Tpo wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-poly1305.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/arm/armv8-poly1305.c' object='wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-poly1305.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-poly1305.lo `test -f 'wolfcrypt/src/port/arm/armv8-poly1305.c' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-poly1305.c + +wolfcrypt/src/src_libwolfssl_la-poly1305.lo: wolfcrypt/src/poly1305.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-poly1305.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-poly1305.lo `test -f 'wolfcrypt/src/poly1305.c' || echo '$(srcdir)/'`wolfcrypt/src/poly1305.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/poly1305.c' object='wolfcrypt/src/src_libwolfssl_la-poly1305.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-poly1305.lo `test -f 'wolfcrypt/src/poly1305.c' || echo '$(srcdir)/'`wolfcrypt/src/poly1305.c + +wolfcrypt/src/src_libwolfssl_la-arc4.lo: wolfcrypt/src/arc4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-arc4.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-arc4.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-arc4.lo `test -f 'wolfcrypt/src/arc4.c' || echo '$(srcdir)/'`wolfcrypt/src/arc4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-arc4.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-arc4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/arc4.c' object='wolfcrypt/src/src_libwolfssl_la-arc4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-arc4.lo `test -f 'wolfcrypt/src/arc4.c' || echo '$(srcdir)/'`wolfcrypt/src/arc4.c + +wolfcrypt/src/src_libwolfssl_la-md4.lo: wolfcrypt/src/md4.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-md4.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md4.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-md4.lo `test -f 'wolfcrypt/src/md4.c' || echo '$(srcdir)/'`wolfcrypt/src/md4.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md4.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/md4.c' object='wolfcrypt/src/src_libwolfssl_la-md4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-md4.lo `test -f 'wolfcrypt/src/md4.c' || echo '$(srcdir)/'`wolfcrypt/src/md4.c + +wolfcrypt/src/src_libwolfssl_la-md5.lo: wolfcrypt/src/md5.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-md5.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md5.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-md5.lo `test -f 'wolfcrypt/src/md5.c' || echo '$(srcdir)/'`wolfcrypt/src/md5.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md5.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md5.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/md5.c' object='wolfcrypt/src/src_libwolfssl_la-md5.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-md5.lo `test -f 'wolfcrypt/src/md5.c' || echo '$(srcdir)/'`wolfcrypt/src/md5.c + +wolfcrypt/src/src_libwolfssl_la-pwdbased.lo: wolfcrypt/src/pwdbased.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-pwdbased.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pwdbased.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-pwdbased.lo `test -f 'wolfcrypt/src/pwdbased.c' || echo '$(srcdir)/'`wolfcrypt/src/pwdbased.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pwdbased.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pwdbased.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/pwdbased.c' object='wolfcrypt/src/src_libwolfssl_la-pwdbased.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-pwdbased.lo `test -f 'wolfcrypt/src/pwdbased.c' || echo '$(srcdir)/'`wolfcrypt/src/pwdbased.c + +wolfcrypt/src/src_libwolfssl_la-pkcs12.lo: wolfcrypt/src/pkcs12.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-pkcs12.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs12.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-pkcs12.lo `test -f 'wolfcrypt/src/pkcs12.c' || echo '$(srcdir)/'`wolfcrypt/src/pkcs12.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs12.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs12.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/pkcs12.c' object='wolfcrypt/src/src_libwolfssl_la-pkcs12.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-pkcs12.lo `test -f 'wolfcrypt/src/pkcs12.c' || echo '$(srcdir)/'`wolfcrypt/src/pkcs12.c + +wolfcrypt/src/src_libwolfssl_la-dsa.lo: wolfcrypt/src/dsa.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-dsa.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dsa.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-dsa.lo `test -f 'wolfcrypt/src/dsa.c' || echo '$(srcdir)/'`wolfcrypt/src/dsa.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dsa.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dsa.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/dsa.c' object='wolfcrypt/src/src_libwolfssl_la-dsa.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-dsa.lo `test -f 'wolfcrypt/src/dsa.c' || echo '$(srcdir)/'`wolfcrypt/src/dsa.c + +wolfcrypt/src/src_libwolfssl_la-camellia.lo: wolfcrypt/src/camellia.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-camellia.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-camellia.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-camellia.lo `test -f 'wolfcrypt/src/camellia.c' || echo '$(srcdir)/'`wolfcrypt/src/camellia.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-camellia.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-camellia.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/camellia.c' object='wolfcrypt/src/src_libwolfssl_la-camellia.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-camellia.lo `test -f 'wolfcrypt/src/camellia.c' || echo '$(srcdir)/'`wolfcrypt/src/camellia.c + +wolfcrypt/src/src_libwolfssl_la-md2.lo: wolfcrypt/src/md2.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-md2.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md2.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-md2.lo `test -f 'wolfcrypt/src/md2.c' || echo '$(srcdir)/'`wolfcrypt/src/md2.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md2.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/md2.c' object='wolfcrypt/src/src_libwolfssl_la-md2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-md2.lo `test -f 'wolfcrypt/src/md2.c' || echo '$(srcdir)/'`wolfcrypt/src/md2.c + +wolfcrypt/src/src_libwolfssl_la-ripemd.lo: wolfcrypt/src/ripemd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-ripemd.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ripemd.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-ripemd.lo `test -f 'wolfcrypt/src/ripemd.c' || echo '$(srcdir)/'`wolfcrypt/src/ripemd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ripemd.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ripemd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/ripemd.c' object='wolfcrypt/src/src_libwolfssl_la-ripemd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-ripemd.lo `test -f 'wolfcrypt/src/ripemd.c' || echo '$(srcdir)/'`wolfcrypt/src/ripemd.c + +wolfcrypt/src/src_libwolfssl_la-blake2b.lo: wolfcrypt/src/blake2b.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-blake2b.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2b.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-blake2b.lo `test -f 'wolfcrypt/src/blake2b.c' || echo '$(srcdir)/'`wolfcrypt/src/blake2b.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2b.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2b.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/blake2b.c' object='wolfcrypt/src/src_libwolfssl_la-blake2b.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-blake2b.lo `test -f 'wolfcrypt/src/blake2b.c' || echo '$(srcdir)/'`wolfcrypt/src/blake2b.c + +wolfcrypt/src/src_libwolfssl_la-blake2s.lo: wolfcrypt/src/blake2s.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-blake2s.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2s.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-blake2s.lo `test -f 'wolfcrypt/src/blake2s.c' || echo '$(srcdir)/'`wolfcrypt/src/blake2s.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2s.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2s.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/blake2s.c' object='wolfcrypt/src/src_libwolfssl_la-blake2s.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-blake2s.lo `test -f 'wolfcrypt/src/blake2s.c' || echo '$(srcdir)/'`wolfcrypt/src/blake2s.c + +wolfcrypt/src/src_libwolfssl_la-hc128.lo: wolfcrypt/src/hc128.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-hc128.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hc128.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-hc128.lo `test -f 'wolfcrypt/src/hc128.c' || echo '$(srcdir)/'`wolfcrypt/src/hc128.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hc128.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hc128.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/hc128.c' object='wolfcrypt/src/src_libwolfssl_la-hc128.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-hc128.lo `test -f 'wolfcrypt/src/hc128.c' || echo '$(srcdir)/'`wolfcrypt/src/hc128.c + +wolfcrypt/src/src_libwolfssl_la-rabbit.lo: wolfcrypt/src/rabbit.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-rabbit.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rabbit.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-rabbit.lo `test -f 'wolfcrypt/src/rabbit.c' || echo '$(srcdir)/'`wolfcrypt/src/rabbit.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rabbit.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rabbit.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/rabbit.c' object='wolfcrypt/src/src_libwolfssl_la-rabbit.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-rabbit.lo `test -f 'wolfcrypt/src/rabbit.c' || echo '$(srcdir)/'`wolfcrypt/src/rabbit.c + +wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-chacha.lo: wolfcrypt/src/port/arm/armv8-chacha.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-chacha.lo -MD -MP -MF wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-chacha.Tpo -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-chacha.lo `test -f 'wolfcrypt/src/port/arm/armv8-chacha.c' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-chacha.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-chacha.Tpo wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-chacha.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/arm/armv8-chacha.c' object='wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-chacha.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/arm/src_libwolfssl_la-armv8-chacha.lo `test -f 'wolfcrypt/src/port/arm/armv8-chacha.c' || echo '$(srcdir)/'`wolfcrypt/src/port/arm/armv8-chacha.c + +wolfcrypt/src/src_libwolfssl_la-chacha.lo: wolfcrypt/src/chacha.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-chacha.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-chacha.lo `test -f 'wolfcrypt/src/chacha.c' || echo '$(srcdir)/'`wolfcrypt/src/chacha.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/chacha.c' object='wolfcrypt/src/src_libwolfssl_la-chacha.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-chacha.lo `test -f 'wolfcrypt/src/chacha.c' || echo '$(srcdir)/'`wolfcrypt/src/chacha.c + +wolfcrypt/src/src_libwolfssl_la-chacha20_poly1305.lo: wolfcrypt/src/chacha20_poly1305.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-chacha20_poly1305.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha20_poly1305.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-chacha20_poly1305.lo `test -f 'wolfcrypt/src/chacha20_poly1305.c' || echo '$(srcdir)/'`wolfcrypt/src/chacha20_poly1305.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha20_poly1305.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha20_poly1305.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/chacha20_poly1305.c' object='wolfcrypt/src/src_libwolfssl_la-chacha20_poly1305.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-chacha20_poly1305.lo `test -f 'wolfcrypt/src/chacha20_poly1305.c' || echo '$(srcdir)/'`wolfcrypt/src/chacha20_poly1305.c + +wolfcrypt/src/src_libwolfssl_la-misc.lo: wolfcrypt/src/misc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-misc.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-misc.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-misc.lo `test -f 'wolfcrypt/src/misc.c' || echo '$(srcdir)/'`wolfcrypt/src/misc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-misc.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-misc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/misc.c' object='wolfcrypt/src/src_libwolfssl_la-misc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-misc.lo `test -f 'wolfcrypt/src/misc.c' || echo '$(srcdir)/'`wolfcrypt/src/misc.c + +wolfcrypt/src/src_libwolfssl_la-tfm.lo: wolfcrypt/src/tfm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-tfm.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-tfm.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-tfm.lo `test -f 'wolfcrypt/src/tfm.c' || echo '$(srcdir)/'`wolfcrypt/src/tfm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-tfm.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-tfm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/tfm.c' object='wolfcrypt/src/src_libwolfssl_la-tfm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-tfm.lo `test -f 'wolfcrypt/src/tfm.c' || echo '$(srcdir)/'`wolfcrypt/src/tfm.c + +wolfcrypt/src/src_libwolfssl_la-integer.lo: wolfcrypt/src/integer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-integer.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-integer.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-integer.lo `test -f 'wolfcrypt/src/integer.c' || echo '$(srcdir)/'`wolfcrypt/src/integer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-integer.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-integer.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/integer.c' object='wolfcrypt/src/src_libwolfssl_la-integer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-integer.lo `test -f 'wolfcrypt/src/integer.c' || echo '$(srcdir)/'`wolfcrypt/src/integer.c + +wolfcrypt/src/src_libwolfssl_la-curve25519.lo: wolfcrypt/src/curve25519.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-curve25519.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve25519.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-curve25519.lo `test -f 'wolfcrypt/src/curve25519.c' || echo '$(srcdir)/'`wolfcrypt/src/curve25519.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve25519.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve25519.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/curve25519.c' object='wolfcrypt/src/src_libwolfssl_la-curve25519.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-curve25519.lo `test -f 'wolfcrypt/src/curve25519.c' || echo '$(srcdir)/'`wolfcrypt/src/curve25519.c + +wolfcrypt/src/src_libwolfssl_la-ed25519.lo: wolfcrypt/src/ed25519.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-ed25519.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed25519.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-ed25519.lo `test -f 'wolfcrypt/src/ed25519.c' || echo '$(srcdir)/'`wolfcrypt/src/ed25519.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed25519.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed25519.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/ed25519.c' object='wolfcrypt/src/src_libwolfssl_la-ed25519.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-ed25519.lo `test -f 'wolfcrypt/src/ed25519.c' || echo '$(srcdir)/'`wolfcrypt/src/ed25519.c + +wolfcrypt/src/src_libwolfssl_la-fe_low_mem.lo: wolfcrypt/src/fe_low_mem.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-fe_low_mem.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_low_mem.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-fe_low_mem.lo `test -f 'wolfcrypt/src/fe_low_mem.c' || echo '$(srcdir)/'`wolfcrypt/src/fe_low_mem.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_low_mem.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_low_mem.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/fe_low_mem.c' object='wolfcrypt/src/src_libwolfssl_la-fe_low_mem.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-fe_low_mem.lo `test -f 'wolfcrypt/src/fe_low_mem.c' || echo '$(srcdir)/'`wolfcrypt/src/fe_low_mem.c + +wolfcrypt/src/src_libwolfssl_la-fe_operations.lo: wolfcrypt/src/fe_operations.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-fe_operations.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_operations.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-fe_operations.lo `test -f 'wolfcrypt/src/fe_operations.c' || echo '$(srcdir)/'`wolfcrypt/src/fe_operations.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_operations.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_operations.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/fe_operations.c' object='wolfcrypt/src/src_libwolfssl_la-fe_operations.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-fe_operations.lo `test -f 'wolfcrypt/src/fe_operations.c' || echo '$(srcdir)/'`wolfcrypt/src/fe_operations.c + +wolfcrypt/src/src_libwolfssl_la-ge_low_mem.lo: wolfcrypt/src/ge_low_mem.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-ge_low_mem.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_low_mem.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-ge_low_mem.lo `test -f 'wolfcrypt/src/ge_low_mem.c' || echo '$(srcdir)/'`wolfcrypt/src/ge_low_mem.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_low_mem.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_low_mem.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/ge_low_mem.c' object='wolfcrypt/src/src_libwolfssl_la-ge_low_mem.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-ge_low_mem.lo `test -f 'wolfcrypt/src/ge_low_mem.c' || echo '$(srcdir)/'`wolfcrypt/src/ge_low_mem.c + +wolfcrypt/src/src_libwolfssl_la-ge_operations.lo: wolfcrypt/src/ge_operations.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-ge_operations.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_operations.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-ge_operations.lo `test -f 'wolfcrypt/src/ge_operations.c' || echo '$(srcdir)/'`wolfcrypt/src/ge_operations.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_operations.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_operations.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/ge_operations.c' object='wolfcrypt/src/src_libwolfssl_la-ge_operations.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-ge_operations.lo `test -f 'wolfcrypt/src/ge_operations.c' || echo '$(srcdir)/'`wolfcrypt/src/ge_operations.c + +wolfcrypt/src/src_libwolfssl_la-curve448.lo: wolfcrypt/src/curve448.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-curve448.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve448.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-curve448.lo `test -f 'wolfcrypt/src/curve448.c' || echo '$(srcdir)/'`wolfcrypt/src/curve448.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve448.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve448.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/curve448.c' object='wolfcrypt/src/src_libwolfssl_la-curve448.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-curve448.lo `test -f 'wolfcrypt/src/curve448.c' || echo '$(srcdir)/'`wolfcrypt/src/curve448.c + +wolfcrypt/src/src_libwolfssl_la-ed448.lo: wolfcrypt/src/ed448.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-ed448.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed448.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-ed448.lo `test -f 'wolfcrypt/src/ed448.c' || echo '$(srcdir)/'`wolfcrypt/src/ed448.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed448.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed448.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/ed448.c' object='wolfcrypt/src/src_libwolfssl_la-ed448.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-ed448.lo `test -f 'wolfcrypt/src/ed448.c' || echo '$(srcdir)/'`wolfcrypt/src/ed448.c + +wolfcrypt/src/src_libwolfssl_la-fe_448.lo: wolfcrypt/src/fe_448.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-fe_448.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_448.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-fe_448.lo `test -f 'wolfcrypt/src/fe_448.c' || echo '$(srcdir)/'`wolfcrypt/src/fe_448.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_448.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_448.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/fe_448.c' object='wolfcrypt/src/src_libwolfssl_la-fe_448.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-fe_448.lo `test -f 'wolfcrypt/src/fe_448.c' || echo '$(srcdir)/'`wolfcrypt/src/fe_448.c + +wolfcrypt/src/src_libwolfssl_la-ge_448.lo: wolfcrypt/src/ge_448.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-ge_448.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_448.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-ge_448.lo `test -f 'wolfcrypt/src/ge_448.c' || echo '$(srcdir)/'`wolfcrypt/src/ge_448.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_448.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_448.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/ge_448.c' object='wolfcrypt/src/src_libwolfssl_la-ge_448.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-ge_448.lo `test -f 'wolfcrypt/src/ge_448.c' || echo '$(srcdir)/'`wolfcrypt/src/ge_448.c + +wolfcrypt/src/src_libwolfssl_la-compress.lo: wolfcrypt/src/compress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-compress.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-compress.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-compress.lo `test -f 'wolfcrypt/src/compress.c' || echo '$(srcdir)/'`wolfcrypt/src/compress.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-compress.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-compress.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/compress.c' object='wolfcrypt/src/src_libwolfssl_la-compress.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-compress.lo `test -f 'wolfcrypt/src/compress.c' || echo '$(srcdir)/'`wolfcrypt/src/compress.c + +wolfcrypt/src/src_libwolfssl_la-pkcs7.lo: wolfcrypt/src/pkcs7.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-pkcs7.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs7.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-pkcs7.lo `test -f 'wolfcrypt/src/pkcs7.c' || echo '$(srcdir)/'`wolfcrypt/src/pkcs7.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs7.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs7.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/pkcs7.c' object='wolfcrypt/src/src_libwolfssl_la-pkcs7.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-pkcs7.lo `test -f 'wolfcrypt/src/pkcs7.c' || echo '$(srcdir)/'`wolfcrypt/src/pkcs7.c + +wolfcrypt/src/src_libwolfssl_la-srp.lo: wolfcrypt/src/srp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-srp.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-srp.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-srp.lo `test -f 'wolfcrypt/src/srp.c' || echo '$(srcdir)/'`wolfcrypt/src/srp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-srp.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-srp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/srp.c' object='wolfcrypt/src/src_libwolfssl_la-srp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-srp.lo `test -f 'wolfcrypt/src/srp.c' || echo '$(srcdir)/'`wolfcrypt/src/srp.c + +wolfcrypt/src/src_libwolfssl_la-idea.lo: wolfcrypt/src/idea.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-idea.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-idea.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-idea.lo `test -f 'wolfcrypt/src/idea.c' || echo '$(srcdir)/'`wolfcrypt/src/idea.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-idea.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-idea.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/idea.c' object='wolfcrypt/src/src_libwolfssl_la-idea.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-idea.lo `test -f 'wolfcrypt/src/idea.c' || echo '$(srcdir)/'`wolfcrypt/src/idea.c + +wolfcrypt/src/port/af_alg/src_libwolfssl_la-wc_afalg.lo: wolfcrypt/src/port/af_alg/wc_afalg.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/af_alg/src_libwolfssl_la-wc_afalg.lo -MD -MP -MF wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-wc_afalg.Tpo -c -o wolfcrypt/src/port/af_alg/src_libwolfssl_la-wc_afalg.lo `test -f 'wolfcrypt/src/port/af_alg/wc_afalg.c' || echo '$(srcdir)/'`wolfcrypt/src/port/af_alg/wc_afalg.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-wc_afalg.Tpo wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-wc_afalg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/af_alg/wc_afalg.c' object='wolfcrypt/src/port/af_alg/src_libwolfssl_la-wc_afalg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/af_alg/src_libwolfssl_la-wc_afalg.lo `test -f 'wolfcrypt/src/port/af_alg/wc_afalg.c' || echo '$(srcdir)/'`wolfcrypt/src/port/af_alg/wc_afalg.c + +src/libwolfssl_la-internal.lo: src/internal.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT src/libwolfssl_la-internal.lo -MD -MP -MF src/$(DEPDIR)/libwolfssl_la-internal.Tpo -c -o src/libwolfssl_la-internal.lo `test -f 'src/internal.c' || echo '$(srcdir)/'`src/internal.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwolfssl_la-internal.Tpo src/$(DEPDIR)/libwolfssl_la-internal.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/internal.c' object='src/libwolfssl_la-internal.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o src/libwolfssl_la-internal.lo `test -f 'src/internal.c' || echo '$(srcdir)/'`src/internal.c + +src/libwolfssl_la-wolfio.lo: src/wolfio.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT src/libwolfssl_la-wolfio.lo -MD -MP -MF src/$(DEPDIR)/libwolfssl_la-wolfio.Tpo -c -o src/libwolfssl_la-wolfio.lo `test -f 'src/wolfio.c' || echo '$(srcdir)/'`src/wolfio.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwolfssl_la-wolfio.Tpo src/$(DEPDIR)/libwolfssl_la-wolfio.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/wolfio.c' object='src/libwolfssl_la-wolfio.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o src/libwolfssl_la-wolfio.lo `test -f 'src/wolfio.c' || echo '$(srcdir)/'`src/wolfio.c + +src/libwolfssl_la-keys.lo: src/keys.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT src/libwolfssl_la-keys.lo -MD -MP -MF src/$(DEPDIR)/libwolfssl_la-keys.Tpo -c -o src/libwolfssl_la-keys.lo `test -f 'src/keys.c' || echo '$(srcdir)/'`src/keys.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwolfssl_la-keys.Tpo src/$(DEPDIR)/libwolfssl_la-keys.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/keys.c' object='src/libwolfssl_la-keys.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o src/libwolfssl_la-keys.lo `test -f 'src/keys.c' || echo '$(srcdir)/'`src/keys.c + +src/libwolfssl_la-ssl.lo: src/ssl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT src/libwolfssl_la-ssl.lo -MD -MP -MF src/$(DEPDIR)/libwolfssl_la-ssl.Tpo -c -o src/libwolfssl_la-ssl.lo `test -f 'src/ssl.c' || echo '$(srcdir)/'`src/ssl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwolfssl_la-ssl.Tpo src/$(DEPDIR)/libwolfssl_la-ssl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ssl.c' object='src/libwolfssl_la-ssl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o src/libwolfssl_la-ssl.lo `test -f 'src/ssl.c' || echo '$(srcdir)/'`src/ssl.c + +src/libwolfssl_la-tls.lo: src/tls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT src/libwolfssl_la-tls.lo -MD -MP -MF src/$(DEPDIR)/libwolfssl_la-tls.Tpo -c -o src/libwolfssl_la-tls.lo `test -f 'src/tls.c' || echo '$(srcdir)/'`src/tls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwolfssl_la-tls.Tpo src/$(DEPDIR)/libwolfssl_la-tls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/tls.c' object='src/libwolfssl_la-tls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o src/libwolfssl_la-tls.lo `test -f 'src/tls.c' || echo '$(srcdir)/'`src/tls.c + +src/libwolfssl_la-tls13.lo: src/tls13.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT src/libwolfssl_la-tls13.lo -MD -MP -MF src/$(DEPDIR)/libwolfssl_la-tls13.Tpo -c -o src/libwolfssl_la-tls13.lo `test -f 'src/tls13.c' || echo '$(srcdir)/'`src/tls13.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwolfssl_la-tls13.Tpo src/$(DEPDIR)/libwolfssl_la-tls13.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/tls13.c' object='src/libwolfssl_la-tls13.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o src/libwolfssl_la-tls13.lo `test -f 'src/tls13.c' || echo '$(srcdir)/'`src/tls13.c + +src/libwolfssl_la-ocsp.lo: src/ocsp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT src/libwolfssl_la-ocsp.lo -MD -MP -MF src/$(DEPDIR)/libwolfssl_la-ocsp.Tpo -c -o src/libwolfssl_la-ocsp.lo `test -f 'src/ocsp.c' || echo '$(srcdir)/'`src/ocsp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwolfssl_la-ocsp.Tpo src/$(DEPDIR)/libwolfssl_la-ocsp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ocsp.c' object='src/libwolfssl_la-ocsp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o src/libwolfssl_la-ocsp.lo `test -f 'src/ocsp.c' || echo '$(srcdir)/'`src/ocsp.c + +src/libwolfssl_la-crl.lo: src/crl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT src/libwolfssl_la-crl.lo -MD -MP -MF src/$(DEPDIR)/libwolfssl_la-crl.Tpo -c -o src/libwolfssl_la-crl.lo `test -f 'src/crl.c' || echo '$(srcdir)/'`src/crl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwolfssl_la-crl.Tpo src/$(DEPDIR)/libwolfssl_la-crl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/crl.c' object='src/libwolfssl_la-crl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o src/libwolfssl_la-crl.lo `test -f 'src/crl.c' || echo '$(srcdir)/'`src/crl.c + +src/libwolfssl_la-sniffer.lo: src/sniffer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT src/libwolfssl_la-sniffer.lo -MD -MP -MF src/$(DEPDIR)/libwolfssl_la-sniffer.Tpo -c -o src/libwolfssl_la-sniffer.lo `test -f 'src/sniffer.c' || echo '$(srcdir)/'`src/sniffer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwolfssl_la-sniffer.Tpo src/$(DEPDIR)/libwolfssl_la-sniffer.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/sniffer.c' object='src/libwolfssl_la-sniffer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o src/libwolfssl_la-sniffer.lo `test -f 'src/sniffer.c' || echo '$(srcdir)/'`src/sniffer.c + +wolfcrypt/src/src_libwolfssl_la-cryptocb.lo: wolfcrypt/src/cryptocb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-cryptocb.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cryptocb.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-cryptocb.lo `test -f 'wolfcrypt/src/cryptocb.c' || echo '$(srcdir)/'`wolfcrypt/src/cryptocb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cryptocb.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cryptocb.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/cryptocb.c' object='wolfcrypt/src/src_libwolfssl_la-cryptocb.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-cryptocb.lo `test -f 'wolfcrypt/src/cryptocb.c' || echo '$(srcdir)/'`wolfcrypt/src/cryptocb.c + +wolfcrypt/src/src_libwolfssl_la-wc_pkcs11.lo: wolfcrypt/src/wc_pkcs11.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/src_libwolfssl_la-wc_pkcs11.lo -MD -MP -MF wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_pkcs11.Tpo -c -o wolfcrypt/src/src_libwolfssl_la-wc_pkcs11.lo `test -f 'wolfcrypt/src/wc_pkcs11.c' || echo '$(srcdir)/'`wolfcrypt/src/wc_pkcs11.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_pkcs11.Tpo wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_pkcs11.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/wc_pkcs11.c' object='wolfcrypt/src/src_libwolfssl_la-wc_pkcs11.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/src_libwolfssl_la-wc_pkcs11.lo `test -f 'wolfcrypt/src/wc_pkcs11.c' || echo '$(srcdir)/'`wolfcrypt/src/wc_pkcs11.c + +wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_hash.lo: wolfcrypt/src/port/devcrypto/devcrypto_hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_hash.lo -MD -MP -MF wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_hash.Tpo -c -o wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_hash.lo `test -f 'wolfcrypt/src/port/devcrypto/devcrypto_hash.c' || echo '$(srcdir)/'`wolfcrypt/src/port/devcrypto/devcrypto_hash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_hash.Tpo wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_hash.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/devcrypto/devcrypto_hash.c' object='wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_hash.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_hash.lo `test -f 'wolfcrypt/src/port/devcrypto/devcrypto_hash.c' || echo '$(srcdir)/'`wolfcrypt/src/port/devcrypto/devcrypto_hash.c + +wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_aes.lo: wolfcrypt/src/port/devcrypto/devcrypto_aes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_aes.lo -MD -MP -MF wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_aes.Tpo -c -o wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_aes.lo `test -f 'wolfcrypt/src/port/devcrypto/devcrypto_aes.c' || echo '$(srcdir)/'`wolfcrypt/src/port/devcrypto/devcrypto_aes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_aes.Tpo wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_aes.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/devcrypto/devcrypto_aes.c' object='wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_aes.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/devcrypto/src_libwolfssl_la-devcrypto_aes.lo `test -f 'wolfcrypt/src/port/devcrypto/devcrypto_aes.c' || echo '$(srcdir)/'`wolfcrypt/src/port/devcrypto/devcrypto_aes.c + +wolfcrypt/src/port/devcrypto/src_libwolfssl_la-wc_devcrypto.lo: wolfcrypt/src/port/devcrypto/wc_devcrypto.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/devcrypto/src_libwolfssl_la-wc_devcrypto.lo -MD -MP -MF wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-wc_devcrypto.Tpo -c -o wolfcrypt/src/port/devcrypto/src_libwolfssl_la-wc_devcrypto.lo `test -f 'wolfcrypt/src/port/devcrypto/wc_devcrypto.c' || echo '$(srcdir)/'`wolfcrypt/src/port/devcrypto/wc_devcrypto.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-wc_devcrypto.Tpo wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-wc_devcrypto.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/devcrypto/wc_devcrypto.c' object='wolfcrypt/src/port/devcrypto/src_libwolfssl_la-wc_devcrypto.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/devcrypto/src_libwolfssl_la-wc_devcrypto.lo `test -f 'wolfcrypt/src/port/devcrypto/wc_devcrypto.c' || echo '$(srcdir)/'`wolfcrypt/src/port/devcrypto/wc_devcrypto.c + +wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_nitrox.lo: wolfcrypt/src/port/cavium/cavium_nitrox.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_nitrox.lo -MD -MP -MF wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_nitrox.Tpo -c -o wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_nitrox.lo `test -f 'wolfcrypt/src/port/cavium/cavium_nitrox.c' || echo '$(srcdir)/'`wolfcrypt/src/port/cavium/cavium_nitrox.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_nitrox.Tpo wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_nitrox.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/cavium/cavium_nitrox.c' object='wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_nitrox.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_nitrox.lo `test -f 'wolfcrypt/src/port/cavium/cavium_nitrox.c' || echo '$(srcdir)/'`wolfcrypt/src/port/cavium/cavium_nitrox.c + +wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_octeon_sync.lo: wolfcrypt/src/port/cavium/cavium_octeon_sync.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_octeon_sync.lo -MD -MP -MF wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_octeon_sync.Tpo -c -o wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_octeon_sync.lo `test -f 'wolfcrypt/src/port/cavium/cavium_octeon_sync.c' || echo '$(srcdir)/'`wolfcrypt/src/port/cavium/cavium_octeon_sync.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_octeon_sync.Tpo wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_octeon_sync.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/cavium/cavium_octeon_sync.c' object='wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_octeon_sync.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/cavium/src_libwolfssl_la-cavium_octeon_sync.lo `test -f 'wolfcrypt/src/port/cavium/cavium_octeon_sync.c' || echo '$(srcdir)/'`wolfcrypt/src/port/cavium/cavium_octeon_sync.c + +wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist.lo: wolfcrypt/src/port/intel/quickassist.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist.lo -MD -MP -MF wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist.Tpo -c -o wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist.lo `test -f 'wolfcrypt/src/port/intel/quickassist.c' || echo '$(srcdir)/'`wolfcrypt/src/port/intel/quickassist.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist.Tpo wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/intel/quickassist.c' object='wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist.lo `test -f 'wolfcrypt/src/port/intel/quickassist.c' || echo '$(srcdir)/'`wolfcrypt/src/port/intel/quickassist.c + +wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_mem.lo: wolfcrypt/src/port/intel/quickassist_mem.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_mem.lo -MD -MP -MF wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_mem.Tpo -c -o wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_mem.lo `test -f 'wolfcrypt/src/port/intel/quickassist_mem.c' || echo '$(srcdir)/'`wolfcrypt/src/port/intel/quickassist_mem.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_mem.Tpo wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_mem.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/intel/quickassist_mem.c' object='wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_mem.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_mem.lo `test -f 'wolfcrypt/src/port/intel/quickassist_mem.c' || echo '$(srcdir)/'`wolfcrypt/src/port/intel/quickassist_mem.c + +wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_sync.lo: wolfcrypt/src/port/intel/quickassist_sync.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_sync.lo -MD -MP -MF wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_sync.Tpo -c -o wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_sync.lo `test -f 'wolfcrypt/src/port/intel/quickassist_sync.c' || echo '$(srcdir)/'`wolfcrypt/src/port/intel/quickassist_sync.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_sync.Tpo wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_sync.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/intel/quickassist_sync.c' object='wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_sync.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/intel/src_libwolfssl_la-quickassist_sync.lo `test -f 'wolfcrypt/src/port/intel/quickassist_sync.c' || echo '$(srcdir)/'`wolfcrypt/src/port/intel/quickassist_sync.c + +wolfcrypt/src/port/atmel/src_libwolfssl_la-atmel.lo: wolfcrypt/src/port/atmel/atmel.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -MT wolfcrypt/src/port/atmel/src_libwolfssl_la-atmel.lo -MD -MP -MF wolfcrypt/src/port/atmel/$(DEPDIR)/src_libwolfssl_la-atmel.Tpo -c -o wolfcrypt/src/port/atmel/src_libwolfssl_la-atmel.lo `test -f 'wolfcrypt/src/port/atmel/atmel.c' || echo '$(srcdir)/'`wolfcrypt/src/port/atmel/atmel.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/src/port/atmel/$(DEPDIR)/src_libwolfssl_la-atmel.Tpo wolfcrypt/src/port/atmel/$(DEPDIR)/src_libwolfssl_la-atmel.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/src/port/atmel/atmel.c' object='wolfcrypt/src/port/atmel/src_libwolfssl_la-atmel.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libwolfssl_la_CPPFLAGS) $(CPPFLAGS) $(src_libwolfssl_la_CFLAGS) $(CFLAGS) -c -o wolfcrypt/src/port/atmel/src_libwolfssl_la-atmel.lo `test -f 'wolfcrypt/src/port/atmel/atmel.c' || echo '$(srcdir)/'`wolfcrypt/src/port/atmel/atmel.c + +tests/unit_test-unit.o: tests/unit.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/unit_test-unit.o -MD -MP -MF tests/$(DEPDIR)/unit_test-unit.Tpo -c -o tests/unit_test-unit.o `test -f 'tests/unit.c' || echo '$(srcdir)/'`tests/unit.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/unit_test-unit.Tpo tests/$(DEPDIR)/unit_test-unit.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/unit.c' object='tests/unit_test-unit.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/unit_test-unit.o `test -f 'tests/unit.c' || echo '$(srcdir)/'`tests/unit.c + +tests/unit_test-unit.obj: tests/unit.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/unit_test-unit.obj -MD -MP -MF tests/$(DEPDIR)/unit_test-unit.Tpo -c -o tests/unit_test-unit.obj `if test -f 'tests/unit.c'; then $(CYGPATH_W) 'tests/unit.c'; else $(CYGPATH_W) '$(srcdir)/tests/unit.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/unit_test-unit.Tpo tests/$(DEPDIR)/unit_test-unit.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/unit.c' object='tests/unit_test-unit.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/unit_test-unit.obj `if test -f 'tests/unit.c'; then $(CYGPATH_W) 'tests/unit.c'; else $(CYGPATH_W) '$(srcdir)/tests/unit.c'; fi` + +tests/unit_test-api.o: tests/api.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/unit_test-api.o -MD -MP -MF tests/$(DEPDIR)/unit_test-api.Tpo -c -o tests/unit_test-api.o `test -f 'tests/api.c' || echo '$(srcdir)/'`tests/api.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/unit_test-api.Tpo tests/$(DEPDIR)/unit_test-api.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/api.c' object='tests/unit_test-api.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/unit_test-api.o `test -f 'tests/api.c' || echo '$(srcdir)/'`tests/api.c + +tests/unit_test-api.obj: tests/api.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/unit_test-api.obj -MD -MP -MF tests/$(DEPDIR)/unit_test-api.Tpo -c -o tests/unit_test-api.obj `if test -f 'tests/api.c'; then $(CYGPATH_W) 'tests/api.c'; else $(CYGPATH_W) '$(srcdir)/tests/api.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/unit_test-api.Tpo tests/$(DEPDIR)/unit_test-api.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/api.c' object='tests/unit_test-api.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/unit_test-api.obj `if test -f 'tests/api.c'; then $(CYGPATH_W) 'tests/api.c'; else $(CYGPATH_W) '$(srcdir)/tests/api.c'; fi` + +tests/unit_test-suites.o: tests/suites.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/unit_test-suites.o -MD -MP -MF tests/$(DEPDIR)/unit_test-suites.Tpo -c -o tests/unit_test-suites.o `test -f 'tests/suites.c' || echo '$(srcdir)/'`tests/suites.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/unit_test-suites.Tpo tests/$(DEPDIR)/unit_test-suites.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/suites.c' object='tests/unit_test-suites.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/unit_test-suites.o `test -f 'tests/suites.c' || echo '$(srcdir)/'`tests/suites.c + +tests/unit_test-suites.obj: tests/suites.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/unit_test-suites.obj -MD -MP -MF tests/$(DEPDIR)/unit_test-suites.Tpo -c -o tests/unit_test-suites.obj `if test -f 'tests/suites.c'; then $(CYGPATH_W) 'tests/suites.c'; else $(CYGPATH_W) '$(srcdir)/tests/suites.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/unit_test-suites.Tpo tests/$(DEPDIR)/unit_test-suites.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/suites.c' object='tests/unit_test-suites.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/unit_test-suites.obj `if test -f 'tests/suites.c'; then $(CYGPATH_W) 'tests/suites.c'; else $(CYGPATH_W) '$(srcdir)/tests/suites.c'; fi` + +tests/unit_test-hash.o: tests/hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/unit_test-hash.o -MD -MP -MF tests/$(DEPDIR)/unit_test-hash.Tpo -c -o tests/unit_test-hash.o `test -f 'tests/hash.c' || echo '$(srcdir)/'`tests/hash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/unit_test-hash.Tpo tests/$(DEPDIR)/unit_test-hash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/hash.c' object='tests/unit_test-hash.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/unit_test-hash.o `test -f 'tests/hash.c' || echo '$(srcdir)/'`tests/hash.c + +tests/unit_test-hash.obj: tests/hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/unit_test-hash.obj -MD -MP -MF tests/$(DEPDIR)/unit_test-hash.Tpo -c -o tests/unit_test-hash.obj `if test -f 'tests/hash.c'; then $(CYGPATH_W) 'tests/hash.c'; else $(CYGPATH_W) '$(srcdir)/tests/hash.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/unit_test-hash.Tpo tests/$(DEPDIR)/unit_test-hash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/hash.c' object='tests/unit_test-hash.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/unit_test-hash.obj `if test -f 'tests/hash.c'; then $(CYGPATH_W) 'tests/hash.c'; else $(CYGPATH_W) '$(srcdir)/tests/hash.c'; fi` + +tests/unit_test-srp.o: tests/srp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/unit_test-srp.o -MD -MP -MF tests/$(DEPDIR)/unit_test-srp.Tpo -c -o tests/unit_test-srp.o `test -f 'tests/srp.c' || echo '$(srcdir)/'`tests/srp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/unit_test-srp.Tpo tests/$(DEPDIR)/unit_test-srp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/srp.c' object='tests/unit_test-srp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/unit_test-srp.o `test -f 'tests/srp.c' || echo '$(srcdir)/'`tests/srp.c + +tests/unit_test-srp.obj: tests/srp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT tests/unit_test-srp.obj -MD -MP -MF tests/$(DEPDIR)/unit_test-srp.Tpo -c -o tests/unit_test-srp.obj `if test -f 'tests/srp.c'; then $(CYGPATH_W) 'tests/srp.c'; else $(CYGPATH_W) '$(srcdir)/tests/srp.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/unit_test-srp.Tpo tests/$(DEPDIR)/unit_test-srp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/srp.c' object='tests/unit_test-srp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o tests/unit_test-srp.obj `if test -f 'tests/srp.c'; then $(CYGPATH_W) 'tests/srp.c'; else $(CYGPATH_W) '$(srcdir)/tests/srp.c'; fi` examples/client/tests_unit_test-client.o: examples/client/client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -MT examples/client/tests_unit_test-client.o -MD -MP -MF examples/client/$(DEPDIR)/tests_unit_test-client.Tpo -c -o examples/client/tests_unit_test-client.o `test -f 'examples/client/client.c' || echo '$(srcdir)/'`examples/client/client.c @@ -2195,19 +5192,19 @@ examples/server/tests_unit_test-server.obj: examples/server/server.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_unit_test_CFLAGS) $(CFLAGS) -c -o examples/server/tests_unit_test-server.obj `if test -f 'examples/server/server.c'; then $(CYGPATH_W) 'examples/server/server.c'; else $(CYGPATH_W) '$(srcdir)/examples/server/server.c'; fi` -ctaocrypt/test/testsuite_testsuite_test-test.o: ctaocrypt/test/test.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -MT ctaocrypt/test/testsuite_testsuite_test-test.o -MD -MP -MF ctaocrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Tpo -c -o ctaocrypt/test/testsuite_testsuite_test-test.o `test -f 'ctaocrypt/test/test.c' || echo '$(srcdir)/'`ctaocrypt/test/test.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Tpo ctaocrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/test/test.c' object='ctaocrypt/test/testsuite_testsuite_test-test.o' libtool=no @AMDEPBACKSLASH@ +wolfcrypt/test/testsuite_testsuite_test-test.o: wolfcrypt/test/test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -MT wolfcrypt/test/testsuite_testsuite_test-test.o -MD -MP -MF wolfcrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Tpo -c -o wolfcrypt/test/testsuite_testsuite_test-test.o `test -f 'wolfcrypt/test/test.c' || echo '$(srcdir)/'`wolfcrypt/test/test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Tpo wolfcrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/test/test.c' object='wolfcrypt/test/testsuite_testsuite_test-test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -c -o ctaocrypt/test/testsuite_testsuite_test-test.o `test -f 'ctaocrypt/test/test.c' || echo '$(srcdir)/'`ctaocrypt/test/test.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -c -o wolfcrypt/test/testsuite_testsuite_test-test.o `test -f 'wolfcrypt/test/test.c' || echo '$(srcdir)/'`wolfcrypt/test/test.c -ctaocrypt/test/testsuite_testsuite_test-test.obj: ctaocrypt/test/test.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -MT ctaocrypt/test/testsuite_testsuite_test-test.obj -MD -MP -MF ctaocrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Tpo -c -o ctaocrypt/test/testsuite_testsuite_test-test.obj `if test -f 'ctaocrypt/test/test.c'; then $(CYGPATH_W) 'ctaocrypt/test/test.c'; else $(CYGPATH_W) '$(srcdir)/ctaocrypt/test/test.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ctaocrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Tpo ctaocrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ctaocrypt/test/test.c' object='ctaocrypt/test/testsuite_testsuite_test-test.obj' libtool=no @AMDEPBACKSLASH@ +wolfcrypt/test/testsuite_testsuite_test-test.obj: wolfcrypt/test/test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -MT wolfcrypt/test/testsuite_testsuite_test-test.obj -MD -MP -MF wolfcrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Tpo -c -o wolfcrypt/test/testsuite_testsuite_test-test.obj `if test -f 'wolfcrypt/test/test.c'; then $(CYGPATH_W) 'wolfcrypt/test/test.c'; else $(CYGPATH_W) '$(srcdir)/wolfcrypt/test/test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) wolfcrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Tpo wolfcrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wolfcrypt/test/test.c' object='wolfcrypt/test/testsuite_testsuite_test-test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -c -o ctaocrypt/test/testsuite_testsuite_test-test.obj `if test -f 'ctaocrypt/test/test.c'; then $(CYGPATH_W) 'ctaocrypt/test/test.c'; else $(CYGPATH_W) '$(srcdir)/ctaocrypt/test/test.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -c -o wolfcrypt/test/testsuite_testsuite_test-test.obj `if test -f 'wolfcrypt/test/test.c'; then $(CYGPATH_W) 'wolfcrypt/test/test.c'; else $(CYGPATH_W) '$(srcdir)/wolfcrypt/test/test.c'; fi` examples/client/testsuite_testsuite_test-client.o: examples/client/client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -MT examples/client/testsuite_testsuite_test-client.o -MD -MP -MF examples/client/$(DEPDIR)/testsuite_testsuite_test-client.Tpo -c -o examples/client/testsuite_testsuite_test-client.o `test -f 'examples/client/client.c' || echo '$(srcdir)/'`examples/client/client.c @@ -2265,46 +5262,47 @@ examples/server/testsuite_testsuite_test-server.obj: examples/server/server.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -c -o examples/server/testsuite_testsuite_test-server.obj `if test -f 'examples/server/server.c'; then $(CYGPATH_W) 'examples/server/server.c'; else $(CYGPATH_W) '$(srcdir)/examples/server/server.c'; fi` -testsuite/testsuite_testsuite_test-testsuite.o: testsuite/testsuite.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -MT testsuite/testsuite_testsuite_test-testsuite.o -MD -MP -MF testsuite/$(DEPDIR)/testsuite_testsuite_test-testsuite.Tpo -c -o testsuite/testsuite_testsuite_test-testsuite.o `test -f 'testsuite/testsuite.c' || echo '$(srcdir)/'`testsuite/testsuite.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) testsuite/$(DEPDIR)/testsuite_testsuite_test-testsuite.Tpo testsuite/$(DEPDIR)/testsuite_testsuite_test-testsuite.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testsuite/testsuite.c' object='testsuite/testsuite_testsuite_test-testsuite.o' libtool=no @AMDEPBACKSLASH@ +testsuite/testsuite_test-testsuite.o: testsuite/testsuite.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -MT testsuite/testsuite_test-testsuite.o -MD -MP -MF testsuite/$(DEPDIR)/testsuite_test-testsuite.Tpo -c -o testsuite/testsuite_test-testsuite.o `test -f 'testsuite/testsuite.c' || echo '$(srcdir)/'`testsuite/testsuite.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) testsuite/$(DEPDIR)/testsuite_test-testsuite.Tpo testsuite/$(DEPDIR)/testsuite_test-testsuite.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testsuite/testsuite.c' object='testsuite/testsuite_test-testsuite.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -c -o testsuite/testsuite_testsuite_test-testsuite.o `test -f 'testsuite/testsuite.c' || echo '$(srcdir)/'`testsuite/testsuite.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -c -o testsuite/testsuite_test-testsuite.o `test -f 'testsuite/testsuite.c' || echo '$(srcdir)/'`testsuite/testsuite.c -testsuite/testsuite_testsuite_test-testsuite.obj: testsuite/testsuite.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -MT testsuite/testsuite_testsuite_test-testsuite.obj -MD -MP -MF testsuite/$(DEPDIR)/testsuite_testsuite_test-testsuite.Tpo -c -o testsuite/testsuite_testsuite_test-testsuite.obj `if test -f 'testsuite/testsuite.c'; then $(CYGPATH_W) 'testsuite/testsuite.c'; else $(CYGPATH_W) '$(srcdir)/testsuite/testsuite.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) testsuite/$(DEPDIR)/testsuite_testsuite_test-testsuite.Tpo testsuite/$(DEPDIR)/testsuite_testsuite_test-testsuite.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testsuite/testsuite.c' object='testsuite/testsuite_testsuite_test-testsuite.obj' libtool=no @AMDEPBACKSLASH@ +testsuite/testsuite_test-testsuite.obj: testsuite/testsuite.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -MT testsuite/testsuite_test-testsuite.obj -MD -MP -MF testsuite/$(DEPDIR)/testsuite_test-testsuite.Tpo -c -o testsuite/testsuite_test-testsuite.obj `if test -f 'testsuite/testsuite.c'; then $(CYGPATH_W) 'testsuite/testsuite.c'; else $(CYGPATH_W) '$(srcdir)/testsuite/testsuite.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) testsuite/$(DEPDIR)/testsuite_test-testsuite.Tpo testsuite/$(DEPDIR)/testsuite_test-testsuite.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testsuite/testsuite.c' object='testsuite/testsuite_test-testsuite.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -c -o testsuite/testsuite_testsuite_test-testsuite.obj `if test -f 'testsuite/testsuite.c'; then $(CYGPATH_W) 'testsuite/testsuite.c'; else $(CYGPATH_W) '$(srcdir)/testsuite/testsuite.c'; fi` - -.s.o: - $(AM_V_CCAS)$(CCASCOMPILE) -c -o $@ $< - -.s.obj: - $(AM_V_CCAS)$(CCASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.s.lo: - $(AM_V_CCAS)$(LTCCASCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testsuite_testsuite_test_CFLAGS) $(CFLAGS) -c -o testsuite/testsuite_test-testsuite.obj `if test -f 'testsuite/testsuite.c'; then $(CYGPATH_W) 'testsuite/testsuite.c'; else $(CYGPATH_W) '$(srcdir)/testsuite/testsuite.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs - -rm -rf ctaocrypt/benchmark/.libs ctaocrypt/benchmark/_libs -rm -rf ctaocrypt/src/.libs ctaocrypt/src/_libs - -rm -rf ctaocrypt/test/.libs ctaocrypt/test/_libs + -rm -rf examples/benchmark/.libs examples/benchmark/_libs -rm -rf examples/client/.libs examples/client/_libs -rm -rf examples/echoclient/.libs examples/echoclient/_libs -rm -rf examples/echoserver/.libs examples/echoserver/_libs + -rm -rf examples/sctp/.libs examples/sctp/_libs -rm -rf examples/server/.libs examples/server/_libs -rm -rf mcapi/.libs mcapi/_libs -rm -rf src/.libs src/_libs -rm -rf sslSniffer/sslSnifferTest/.libs sslSniffer/sslSnifferTest/_libs -rm -rf tests/.libs tests/_libs -rm -rf testsuite/.libs testsuite/_libs + -rm -rf wolfcrypt/benchmark/.libs wolfcrypt/benchmark/_libs + -rm -rf wolfcrypt/src/.libs wolfcrypt/src/_libs + -rm -rf wolfcrypt/src/port/af_alg/.libs wolfcrypt/src/port/af_alg/_libs + -rm -rf wolfcrypt/src/port/arm/.libs wolfcrypt/src/port/arm/_libs + -rm -rf wolfcrypt/src/port/atmel/.libs wolfcrypt/src/port/atmel/_libs + -rm -rf wolfcrypt/src/port/cavium/.libs wolfcrypt/src/port/cavium/_libs + -rm -rf wolfcrypt/src/port/devcrypto/.libs wolfcrypt/src/port/devcrypto/_libs + -rm -rf wolfcrypt/src/port/intel/.libs wolfcrypt/src/port/intel/_libs + -rm -rf wolfcrypt/test/.libs wolfcrypt/test/_libs + -rm -rf wolfcrypt/user-crypto/src/.libs wolfcrypt/user-crypto/src/_libs distclean-libtool: -rm -f libtool config.lt @@ -2350,6 +5348,27 @@ uninstall-dist_exampleDATA: @list='$(dist_example_DATA)'; test -n "$(exampledir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(exampledir)'; $(am__uninstall_files_from_dir) +install-ippDATA: $(ipp_DATA) + @$(NORMAL_INSTALL) + @list='$(ipp_DATA)'; test -n "$(ippdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(ippdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(ippdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(ippdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(ippdir)" || exit $$?; \ + done + +uninstall-ippDATA: + @$(NORMAL_UNINSTALL) + @list='$(ipp_DATA)'; test -n "$(ippdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(ippdir)'; $(am__uninstall_files_from_dir) install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ @@ -2506,7 +5525,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ - else \ + elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ @@ -2596,7 +5615,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) fi; \ $$success || exit 1 -check-TESTS: +check-TESTS: $(check_PROGRAMS) $(check_SCRIPTS) @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @@ -2606,7 +5625,7 @@ check-TESTS: log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; -recheck: all $(check_PROGRAMS) +recheck: all $(check_PROGRAMS) $(check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ @@ -2617,6 +5636,13 @@ recheck: all $(check_PROGRAMS) am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? +wolfcrypt/test/testwolfcrypt.log: wolfcrypt/test/testwolfcrypt$(EXEEXT) + @p='wolfcrypt/test/testwolfcrypt$(EXEEXT)'; \ + b='wolfcrypt/test/testwolfcrypt'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) mcapi/test.log: mcapi/test$(EXEEXT) @p='mcapi/test$(EXEEXT)'; \ b='mcapi/test'; \ @@ -2639,7 +5665,10 @@ mcapi/test.log: mcapi/test$(EXEEXT) @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -2679,7 +5708,7 @@ distdir: $(DISTFILES) ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir @@ -2694,18 +5723,22 @@ dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + dist-tarZ: distdir - @echo WARNING: "Support for shar distribution archives is" \ - "deprecated." >&2 + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir - @echo WARNING: "Support for distribution archives compressed with" \ - "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -2723,7 +5756,7 @@ dist dist-all: distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -2733,23 +5766,25 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) - mkdir $(distdir)/_build $(distdir)/_inst + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ - --srcdir=.. --prefix="$$dc_install_base" \ + --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ @@ -2803,16 +5838,16 @@ distcleancheck: distclean $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am - $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am -all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS) \ - config.h +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(SCRIPTS) $(DATA) \ + $(HEADERS) config.h install-binPROGRAMS: install-libLTLIBRARIES installdirs: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(exampledir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)"; do \ + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(exampledir)" "$(DESTDIR)$(ippdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) @@ -2846,18 +5881,18 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -rm -f ctaocrypt/benchmark/$(DEPDIR)/$(am__dirstamp) - -rm -f ctaocrypt/benchmark/$(am__dirstamp) -rm -f ctaocrypt/src/$(DEPDIR)/$(am__dirstamp) -rm -f ctaocrypt/src/$(am__dirstamp) - -rm -f ctaocrypt/test/$(DEPDIR)/$(am__dirstamp) - -rm -f ctaocrypt/test/$(am__dirstamp) + -rm -f examples/benchmark/$(DEPDIR)/$(am__dirstamp) + -rm -f examples/benchmark/$(am__dirstamp) -rm -f examples/client/$(DEPDIR)/$(am__dirstamp) -rm -f examples/client/$(am__dirstamp) -rm -f examples/echoclient/$(DEPDIR)/$(am__dirstamp) -rm -f examples/echoclient/$(am__dirstamp) -rm -f examples/echoserver/$(DEPDIR)/$(am__dirstamp) -rm -f examples/echoserver/$(am__dirstamp) + -rm -f examples/sctp/$(DEPDIR)/$(am__dirstamp) + -rm -f examples/sctp/$(am__dirstamp) -rm -f examples/server/$(DEPDIR)/$(am__dirstamp) -rm -f examples/server/$(am__dirstamp) -rm -f mcapi/$(DEPDIR)/$(am__dirstamp) @@ -2870,6 +5905,26 @@ distclean-generic: -rm -f tests/$(am__dirstamp) -rm -f testsuite/$(DEPDIR)/$(am__dirstamp) -rm -f testsuite/$(am__dirstamp) + -rm -f wolfcrypt/benchmark/$(DEPDIR)/$(am__dirstamp) + -rm -f wolfcrypt/benchmark/$(am__dirstamp) + -rm -f wolfcrypt/src/$(DEPDIR)/$(am__dirstamp) + -rm -f wolfcrypt/src/$(am__dirstamp) + -rm -f wolfcrypt/src/port/af_alg/$(DEPDIR)/$(am__dirstamp) + -rm -f wolfcrypt/src/port/af_alg/$(am__dirstamp) + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/$(am__dirstamp) + -rm -f wolfcrypt/src/port/arm/$(am__dirstamp) + -rm -f wolfcrypt/src/port/atmel/$(DEPDIR)/$(am__dirstamp) + -rm -f wolfcrypt/src/port/atmel/$(am__dirstamp) + -rm -f wolfcrypt/src/port/cavium/$(DEPDIR)/$(am__dirstamp) + -rm -f wolfcrypt/src/port/cavium/$(am__dirstamp) + -rm -f wolfcrypt/src/port/devcrypto/$(DEPDIR)/$(am__dirstamp) + -rm -f wolfcrypt/src/port/devcrypto/$(am__dirstamp) + -rm -f wolfcrypt/src/port/intel/$(DEPDIR)/$(am__dirstamp) + -rm -f wolfcrypt/src/port/intel/$(am__dirstamp) + -rm -f wolfcrypt/test/$(DEPDIR)/$(am__dirstamp) + -rm -f wolfcrypt/test/$(am__dirstamp) + -rm -f wolfcrypt/user-crypto/src/$(DEPDIR)/$(am__dirstamp) + -rm -f wolfcrypt/user-crypto/src/$(am__dirstamp) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @@ -2879,12 +5934,162 @@ maintainer-clean-generic: clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ - clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \ - clean-noinstPROGRAMS mostlyclean-am + clean-libLTLIBRARIES clean-libtool clean-local \ + clean-noinstLTLIBRARIES clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf ctaocrypt/benchmark/$(DEPDIR) ctaocrypt/src/$(DEPDIR) ctaocrypt/test/$(DEPDIR) examples/client/$(DEPDIR) examples/echoclient/$(DEPDIR) examples/echoserver/$(DEPDIR) examples/server/$(DEPDIR) mcapi/$(DEPDIR) src/$(DEPDIR) sslSniffer/sslSnifferTest/$(DEPDIR) tests/$(DEPDIR) testsuite/$(DEPDIR) + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Plo + -rm -f examples/benchmark/$(DEPDIR)/tls_bench.Po + -rm -f examples/client/$(DEPDIR)/client.Po + -rm -f examples/client/$(DEPDIR)/tests_unit_test-client.Po + -rm -f examples/client/$(DEPDIR)/testsuite_testsuite_test-client.Po + -rm -f examples/echoclient/$(DEPDIR)/echoclient.Po + -rm -f examples/echoclient/$(DEPDIR)/testsuite_testsuite_test-echoclient.Po + -rm -f examples/echoserver/$(DEPDIR)/echoserver.Po + -rm -f examples/echoserver/$(DEPDIR)/testsuite_testsuite_test-echoserver.Po + -rm -f examples/sctp/$(DEPDIR)/sctp-client-dtls.Po + -rm -f examples/sctp/$(DEPDIR)/sctp-client.Po + -rm -f examples/sctp/$(DEPDIR)/sctp-server-dtls.Po + -rm -f examples/sctp/$(DEPDIR)/sctp-server.Po + -rm -f examples/server/$(DEPDIR)/server.Po + -rm -f examples/server/$(DEPDIR)/tests_unit_test-server.Po + -rm -f examples/server/$(DEPDIR)/testsuite_testsuite_test-server.Po + -rm -f mcapi/$(DEPDIR)/crypto.Po + -rm -f mcapi/$(DEPDIR)/mcapi_test.Po + -rm -f src/$(DEPDIR)/libwolfssl_la-crl.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-internal.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-keys.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-ocsp.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-sniffer.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-ssl.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-tls.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-tls13.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-wolfio.Plo + -rm -f sslSniffer/sslSnifferTest/$(DEPDIR)/snifftest.Po + -rm -f tests/$(DEPDIR)/unit_test-api.Po + -rm -f tests/$(DEPDIR)/unit_test-hash.Po + -rm -f tests/$(DEPDIR)/unit_test-srp.Po + -rm -f tests/$(DEPDIR)/unit_test-suites.Po + -rm -f tests/$(DEPDIR)/unit_test-unit.Po + -rm -f testsuite/$(DEPDIR)/testsuite_test-testsuite.Po + -rm -f wolfcrypt/benchmark/$(DEPDIR)/benchmark.Po + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_gcm_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-arc4.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-asn.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-async.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2b.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2s.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-camellia.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha20_poly1305.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cmac.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-coding.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-compress.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cpuid.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cryptocb.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve25519.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve448.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dh.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dsa.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ecc.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed25519.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed448.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-error.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_448.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_low_mem.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_operations.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_x25519_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_448.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_low_mem.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_operations.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hash.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hc128.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-idea.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-integer.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-logging.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md2.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md4.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md5.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-memory.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-misc.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs12.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs7.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pwdbased.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rabbit.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ripemd.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-selftest.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha3.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-signature.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm32.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm64.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_armthumb.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c32.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c64.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_cortexm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_int.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-srp.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-tfm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_encrypt.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_pkcs11.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_port.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfevent.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfmath.Plo + -rm -f wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_aes.Plo + -rm -f wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_hash.Plo + -rm -f wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-wc_afalg.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-curve25519.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-sha512-asm.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-aes.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-chacha.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-curve25519.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-poly1305.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha256.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512-asm.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512.Plo + -rm -f wolfcrypt/src/port/atmel/$(DEPDIR)/src_libwolfssl_la-atmel.Plo + -rm -f wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_nitrox.Plo + -rm -f wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_octeon_sync.Plo + -rm -f wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_aes.Plo + -rm -f wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_hash.Plo + -rm -f wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-wc_devcrypto.Plo + -rm -f wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist.Plo + -rm -f wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_mem.Plo + -rm -f wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_sync.Plo + -rm -f wolfcrypt/test/$(DEPDIR)/test.Po + -rm -f wolfcrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Po + -rm -f wolfcrypt/user-crypto/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags @@ -2902,8 +6107,8 @@ info: info-am info-am: install-data-am: install-dist_docDATA install-dist_exampleDATA \ - install-includeHEADERS install-nobase_includeHEADERS \ - install-pkgconfigDATA + install-includeHEADERS install-ippDATA \ + install-nobase_includeHEADERS install-pkgconfigDATA install-dvi: install-dvi-am @@ -2935,7 +6140,157 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf ctaocrypt/benchmark/$(DEPDIR) ctaocrypt/src/$(DEPDIR) ctaocrypt/test/$(DEPDIR) examples/client/$(DEPDIR) examples/echoclient/$(DEPDIR) examples/echoserver/$(DEPDIR) examples/server/$(DEPDIR) mcapi/$(DEPDIR) src/$(DEPDIR) sslSniffer/sslSnifferTest/$(DEPDIR) tests/$(DEPDIR) testsuite/$(DEPDIR) + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Plo + -rm -f ctaocrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Plo + -rm -f examples/benchmark/$(DEPDIR)/tls_bench.Po + -rm -f examples/client/$(DEPDIR)/client.Po + -rm -f examples/client/$(DEPDIR)/tests_unit_test-client.Po + -rm -f examples/client/$(DEPDIR)/testsuite_testsuite_test-client.Po + -rm -f examples/echoclient/$(DEPDIR)/echoclient.Po + -rm -f examples/echoclient/$(DEPDIR)/testsuite_testsuite_test-echoclient.Po + -rm -f examples/echoserver/$(DEPDIR)/echoserver.Po + -rm -f examples/echoserver/$(DEPDIR)/testsuite_testsuite_test-echoserver.Po + -rm -f examples/sctp/$(DEPDIR)/sctp-client-dtls.Po + -rm -f examples/sctp/$(DEPDIR)/sctp-client.Po + -rm -f examples/sctp/$(DEPDIR)/sctp-server-dtls.Po + -rm -f examples/sctp/$(DEPDIR)/sctp-server.Po + -rm -f examples/server/$(DEPDIR)/server.Po + -rm -f examples/server/$(DEPDIR)/tests_unit_test-server.Po + -rm -f examples/server/$(DEPDIR)/testsuite_testsuite_test-server.Po + -rm -f mcapi/$(DEPDIR)/crypto.Po + -rm -f mcapi/$(DEPDIR)/mcapi_test.Po + -rm -f src/$(DEPDIR)/libwolfssl_la-crl.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-internal.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-keys.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-ocsp.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-sniffer.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-ssl.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-tls.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-tls13.Plo + -rm -f src/$(DEPDIR)/libwolfssl_la-wolfio.Plo + -rm -f sslSniffer/sslSnifferTest/$(DEPDIR)/snifftest.Po + -rm -f tests/$(DEPDIR)/unit_test-api.Po + -rm -f tests/$(DEPDIR)/unit_test-hash.Po + -rm -f tests/$(DEPDIR)/unit_test-srp.Po + -rm -f tests/$(DEPDIR)/unit_test-suites.Po + -rm -f tests/$(DEPDIR)/unit_test-unit.Po + -rm -f testsuite/$(DEPDIR)/testsuite_test-testsuite.Po + -rm -f wolfcrypt/benchmark/$(DEPDIR)/benchmark.Po + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-aes_gcm_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-arc4.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-asn.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-async.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2b.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-blake2s.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-camellia.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha20_poly1305.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-chacha_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cmac.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-coding.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-compress.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cpuid.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-cryptocb.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve25519.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-curve448.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-des3.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dh.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-dsa.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ecc.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed25519.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ed448.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-error.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_448.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_low_mem.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_operations.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fe_x25519_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-fips_test.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_448.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_low_mem.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ge_operations.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hash.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hc128.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-hmac.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-idea.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-integer.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-logging.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md2.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md4.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-md5.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-memory.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-misc.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs12.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pkcs7.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-poly1305_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-pwdbased.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rabbit.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-random.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-ripemd.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-selftest.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha256_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha3.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sha512_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-signature.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm32.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_arm64.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_armthumb.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c32.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_c64.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_cortexm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_int.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-sp_x86_64_asm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-srp.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-tfm.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_encrypt.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_pkcs11.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wc_port.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_first.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfcrypt_last.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfevent.Plo + -rm -f wolfcrypt/src/$(DEPDIR)/src_libwolfssl_la-wolfmath.Plo + -rm -f wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_aes.Plo + -rm -f wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-afalg_hash.Plo + -rm -f wolfcrypt/src/port/af_alg/$(DEPDIR)/src_libwolfssl_la-wc_afalg.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-curve25519.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-32-sha512-asm.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-aes.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-chacha.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-curve25519.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-poly1305.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha256.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512-asm.Plo + -rm -f wolfcrypt/src/port/arm/$(DEPDIR)/src_libwolfssl_la-armv8-sha512.Plo + -rm -f wolfcrypt/src/port/atmel/$(DEPDIR)/src_libwolfssl_la-atmel.Plo + -rm -f wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_nitrox.Plo + -rm -f wolfcrypt/src/port/cavium/$(DEPDIR)/src_libwolfssl_la-cavium_octeon_sync.Plo + -rm -f wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_aes.Plo + -rm -f wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-devcrypto_hash.Plo + -rm -f wolfcrypt/src/port/devcrypto/$(DEPDIR)/src_libwolfssl_la-wc_devcrypto.Plo + -rm -f wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist.Plo + -rm -f wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_mem.Plo + -rm -f wolfcrypt/src/port/intel/$(DEPDIR)/src_libwolfssl_la-quickassist_sync.Plo + -rm -f wolfcrypt/test/$(DEPDIR)/test.Po + -rm -f wolfcrypt/test/$(DEPDIR)/testsuite_testsuite_test-test.Po + -rm -f wolfcrypt/user-crypto/src/$(DEPDIR)/src_libwolfssl_la-rsa.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic \ maintainer-clean-local @@ -2955,25 +6310,27 @@ ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-dist_docDATA \ uninstall-dist_exampleDATA uninstall-includeHEADERS \ - uninstall-libLTLIBRARIES uninstall-local \ + uninstall-ippDATA uninstall-libLTLIBRARIES uninstall-local \ uninstall-nobase_includeHEADERS uninstall-pkgconfigDATA .MAKE: all check check-am install install-am install-strip -.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-TESTS \ - check-am clean clean-binPROGRAMS clean-checkPROGRAMS \ - clean-cscope clean-generic clean-libLTLIBRARIES clean-libtool \ +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles am--refresh check \ + check-TESTS check-am clean clean-binPROGRAMS \ + clean-checkPROGRAMS clean-cscope clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-local \ clean-noinstLTLIBRARIES clean-noinstPROGRAMS cscope \ cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ - distcheck distclean distclean-compile distclean-generic \ - distclean-hdr distclean-libtool distclean-tags distcleancheck \ - distdir distuninstallcheck dvi dvi-am html html-am info \ - info-am install install-am install-binPROGRAMS install-data \ - install-data-am install-dist_docDATA install-dist_exampleDATA \ - install-dvi install-dvi-am install-exec install-exec-am \ - install-exec-local install-html install-html-am \ - install-includeHEADERS install-info install-info-am \ + dist-zstd distcheck distclean distclean-compile \ + distclean-generic distclean-hdr distclean-libtool \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am \ + install-dist_docDATA install-dist_exampleDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-exec-local \ + install-html install-html-am install-includeHEADERS \ + install-info install-info-am install-ippDATA \ install-libLTLIBRARIES install-man \ install-nobase_includeHEADERS install-pdf install-pdf-am \ install-pkgconfigDATA install-ps install-ps-am install-strip \ @@ -2983,13 +6340,33 @@ uninstall-am: uninstall-binPROGRAMS uninstall-dist_docDATA \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-dist_docDATA \ uninstall-dist_exampleDATA uninstall-includeHEADERS \ - uninstall-libLTLIBRARIES uninstall-local \ + uninstall-ippDATA uninstall-libLTLIBRARIES uninstall-local \ uninstall-nobase_includeHEADERS uninstall-pkgconfigDATA +.PRECIOUS: Makefile + #includes additional rules from aminclude.am @INC_AMINCLUDE@ +dox-pdf: + echo "Generating PDF" + cd doc && ./generate_documentation.sh -install -pdf || (echo "HTML generation failed $$?"; exit 1) + +dox-html: + echo "Generating HTML" + cd doc && ./generate_documentation.sh -install -html || (echo "HTML generation failed $$?"; exit 1) + +dox: dox-html dox-pdf + +clean-local: + -rm -rf doc/build/ + -rm -rf doc/html/ + -rm -f doc/refman.pdf + -rm -f doc/doxygen_warnings +@BUILD_FAST_RSA_TRUE@IPP_links: +@BUILD_FAST_RSA_TRUE@ @$(IPPLINK) + rpm-build: rpm/spec dist @rm -f *.rpm @rm -f ~/rpmbuild/RPMS/x86_64/$(PACKAGE)-$(VERSION)*.rpm @@ -3024,6 +6401,21 @@ release: rpm-sign auto-rpmbuild: @auto-br-rpmbuild -ba rpm/spec +@BUILD_CRL_TRUE@@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_RSA_TRUE@scripts/crl-revoked.log: scripts/resume.log +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_TRUE@@BUILD_RSA_TRUE@scripts/ocsp-stapling.log: tests/unit.log +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_TRUE@@BUILD_RSA_TRUE@scripts/ocsp-stapling.log: scripts/ocsp.log +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_TRUE@@BUILD_RSA_TRUE@scripts/ocsp-stapling-with-ca-as-responder.log: tests/unit.log +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_TRUE@@BUILD_RSA_TRUE@scripts/ocsp-stapling-with-ca-as-responder.log: scripts/ocsp.log +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_TRUE@@BUILD_RSA_TRUE@scripts/ocsp-stapling-with-ca-as-responder.log: scripts/ocsp-stapling.log + +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_TRUE@@BUILD_OCSP_STAPLING_V2_TRUE@@BUILD_RSA_TRUE@scripts/ocsp-stapling2.log: tests/unit.log +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_TRUE@@BUILD_OCSP_STAPLING_V2_TRUE@@BUILD_RSA_TRUE@scripts/ocsp-stapling2.log: scripts/ocsp.log +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_TRUE@@BUILD_OCSP_STAPLING_V2_TRUE@@BUILD_RSA_TRUE@scripts/ocsp-stapling2.log: scripts/ocsp-stapling.log +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_TRUE@@BUILD_OCSP_STAPLING_V2_TRUE@@BUILD_RSA_TRUE@scripts/ocsp-stapling2.log: scripts/ocsp-stapling-with-ca-as-responder.log +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_FALSE@@BUILD_OCSP_STAPLING_V2_TRUE@@BUILD_RSA_TRUE@scripts/ocsp-stapling2.log: tests/unit.log +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_OCSP_STAPLING_FALSE@@BUILD_OCSP_STAPLING_V2_TRUE@@BUILD_RSA_TRUE@scripts/ocsp-stapling2.log: scripts/ocsp.log +@BUILD_EXAMPLE_SERVERS_TRUE@@BUILD_PKCALLBACKS_TRUE@scripts/pkcallbacks.log: scripts/resume.log + test: check tests/unit.log: testsuite/testsuite.log @@ -3048,7 +6440,7 @@ maintainer-clean-local: -rm m4/ltsugar.m4 -rm m4/ltversion.m4 -rm m4/lt~obsolete.m4 - -rm support/cyassl.pc + -rm support/wolfssl.pc find . -type f -name '*~' -exec rm -f '{}' \; -rm -f @PACKAGE@-*.tar.gz -rm -f @PACKAGE@-*.rpm @@ -3060,9 +6452,9 @@ egs: $(MAKE) examples/server/server; \ $(MAKE) examples/echoserver/echoserver; -ctc: - $(MAKE) ctaocrypt/test/testctaocrypt; \ - $(MAKE) ctaocrypt/benchmark/benchmark; +wc_egs: + $(MAKE) wolfcrypt/test/testwolfcrypt; \ + $(MAKE) wolfcrypt/benchmark/benchmark; install-exec-local: install-generic-config diff --git a/FreeRTOS-Plus/Source/WolfSSL/README b/FreeRTOS-Plus/Source/WolfSSL/README index e2da67459..db1b54488 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/README +++ b/FreeRTOS-Plus/Source/WolfSSL/README @@ -1,1044 +1,222 @@ +*** Description *** + +The wolfSSL embedded SSL library (formerly CyaSSL) is a lightweight SSL/TLS +library written in ANSI C and targeted for embedded, RTOS, and +resource-constrained environments - primarily because of its small size, speed, +and feature set. It is commonly used in standard operating environments as well +because of its royalty-free pricing and excellent cross platform support. +wolfSSL supports industry standards up to the current TLS 1.3 and DTLS 1.2 +levels, is up to 20 times smaller than OpenSSL, and offers progressive ciphers +such as ChaCha20, Curve25519, NTRU, and Blake2b. User benchmarking and feedback +reports dramatically better performance when using wolfSSL over OpenSSL. + +wolfSSL is powered by the wolfCrypt library. Two versions of the wolfCrypt +cryptography library have been FIPS 140-2 validated (Certificate #2425 and +certificate #3389). For additional information, visit the wolfCrypt FIPS FAQ +(https://www.wolfssl.com/license/fips/) or contact fips@wolfssl.com + +*** Why choose wolfSSL? *** + +There are many reasons to choose wolfSSL as your embedded SSL solution. Some of +the top reasons include size (typical footprint sizes range from 20-100 kB), +support for the newest standards (SSL 3.0, TLS 1.0, TLS 1.1, TLS 1.2, TLS 1.3, +DTLS 1.0, and DTLS 1.2), current and progressive cipher support (including +stream ciphers), multi-platform, royalty free, and an OpenSSL compatibility API +to ease porting into existing applications which have previously used the +OpenSSL package. For a complete feature list, see chapter 4 of the wolfSSL +manual. (https://www.wolfssl.com/docs/wolfssl-manual/ch4/) + *** Notes, Please read *** Note 1) -CyaSSL now needs all examples and tests to be run from the CyaSSL home -directory. This is because it finds certs and keys from ./certs/. Trying to -maintain the ability to run each program from its own directory, the testsuite -directory, the main directory (for make check/test), and for the various -different project layouts (with or without config) was becoming harder and -harder. Now to run testsuite just do: +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), or +enable ECC (ECC is on by default), or you must enable static key cipher suites +with -./testsuite/testsuite + WOLFSSL_STATIC_DH + WOLFSSL_STATIC_RSA + or + WOLFSSL_STATIC_PSK -or - -make check (when using autoconf) - -On *nix or Windows the examples and testsuite will check to see if the current -directory is the source directory and if so, attempt to change to the CyaSSL -home directory. This should work in most setup cases, if not, just follow the -beginning of the note and specify the full path. +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 +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 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. Note 2) -CyaSSL takes a different approach to certificate verification than OpenSSL does. -The default policy for the client is to verify the server, this means that if -you don't load CAs to verify the server you'll get a connect error, no signer -error to confirm failure (-188). If you want to mimic OpenSSL behavior of -having SSL_connect succeed even if verifying the server fails and reducing -security you can do this by calling: +wolfSSL takes a different approach to certificate verification than OpenSSL +does. The default policy for the client is to verify the server, this means +that if you don't load CAs to verify the server you'll get a connect error, +no signer error to confirm failure (-188). -SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); +If you want to mimic OpenSSL behavior of having SSL_connect succeed even if +verifying the server fails and reducing security you can do this by calling: -before calling SSL_new(); Though it's not recommended. + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); + +before calling wolfSSL_new();. Though it's not recommended. + +Note 3) +The enum values SHA, SHA256, SHA384, SHA512 are no longer available when +wolfSSL is built with --enable-opensslextra (OPENSSL_EXTRA) or with the macro +NO_OLD_SHA_NAMES. These names get mapped to the OpenSSL API for a single call +hash function. Instead the name WC_SHA, WC_SHA256, WC_SHA384 and WC_SHA512 +should be used for the enum name. *** end Notes *** -CyaSSL Release 3.1.0 (07/14/2014) - -Release 3.1.0 CyaSSL has bug fixes and new features including: - -- Fix for older versions of icc without 128-bit type -- Intel ASM syntax for AES-NI -- Updated NTRU support, keygen benchmark -- FIPS check for minimum required HMAC key length -- Small stack (--enable-smallstack) improvements for PKCS#7, ASN -- TLS extension support for DTLS -- Default I/O callbacks external to user -- Updated example client with bad clock test -- Ability to set optional ECC context info -- Ability to enable/disable DH separate from opensslextra -- Additional test key/cert buffers for CA and server -- Updated example certificates - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -************ CyaSSL Release 3.0.2 (05/30/2014) - -Release 3.0.2 CyaSSL has bug fixes and new features including: - -- Added the following cipher suites: - * TLS_PSK_WITH_AES_128_GCM_SHA256 - * TLS_PSK_WITH_AES_256_GCM_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA384 - * TLS_PSK_WITH_NULL_SHA384 - * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 - * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_NULL_SHA256 - * TLS_DHE_PSK_WITH_NULL_SHA384 - * TLS_DHE_PSK_WITH_AES_128_CCM - * TLS_DHE_PSK_WITH_AES_256_CCM -- Added AES-NI support for Microsoft Visual Studio builds. -- Changed small stack build to be disabled by default. -- Updated the Hash DRBG and provided a configure option to enable. - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -************ CyaSSL Release 3.0.0 (04/29/2014) - -Release 3.0.0 CyaSSL has bug fixes and new features including: - -- FIPS release candidate -- X.509 improvements that address items reported by Suman Jana with security - researchers at UT Austin and UC Davis -- Small stack size improvements, --enable-smallstack. Offloads large local - variables to the heap. (Note this is not complete.) -- Updated AES-CCM-8 cipher suites to use approved suite numbers. - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -************ CyaSSL Release 2.9.4 (04/09/2014) - -Release 2.9.4 CyaSSL has bug fixes and new features including: - -- Security fixes that address items reported by Ivan Fratric of the Google - Security Team -- X.509 Unknown critical extensions treated as errors, report by Suman Jana with - security researchers at UT Austin and UC Davis -- Sniffer fixes for corrupted packet length and Jumbo frames -- ARM thumb mode assembly fixes -- Xcode 5.1 support including new clang -- PIC32 MZ hardware support -- CyaSSL Object has enough room to read the Record Header now w/o allocs -- FIPS wrappers for AES, 3DES, SHA1, SHA256, SHA384, HMAC, and RSA. -- A sample I/O pool is demonstrated with --enable-iopool to overtake memory - handling and reduce memory fragmentation on I/O large sizes - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -************ CyaSSL Release 2.9.0 (02/07/2014) - -Release 2.9.0 CyaSSL has bug fixes and new features including: -- Freescale Kinetis RNGB support -- Freescale Kinetis mmCAU support -- TLS Hello extensions - - ECC - - Secure Renegotiation (null) - - Truncated HMAC -- SCEP support - - PKCS #7 Enveloped data and signed data - - PKCS #10 Certificate Signing Request generation -- DTLS sliding window -- OCSP Improvements - - API change to integrate into Certificate Manager - - IPv4/IPv6 agnostic - - example client/server support for OCSP - - OCSP nonces are optional -- GMAC hashing -- Windows build additions -- Windows CYGWIN build fixes -- Updated test certificates -- Microchip MPLAB Harmony support -- Update autoconf scripts -- Additional X.509 inspection functions -- ECC encrypt/decrypt primitives -- ECC Certificate generation - -The Freescale Kinetis K53 RNGB documentation can be found in Chapter 33 of the -K53 Sub-Family Reference Manual: -http://cache.freescale.com/files/32bit/doc/ref_manual/K53P144M100SF2RM.pdf - -Freescale Kinetis K60 mmCAU (AES, DES, 3DES, MD5, SHA, SHA256) documentation -can be found in the "ColdFire/ColdFire+ CAU and Kinetis mmCAU Software Library -User Guide": -http://cache.freescale.com/files/32bit/doc/user_guide/CAUAPIUG.pdf - - -*****************CyaSSL Release 2.8.0 (8/30/2013) - -Release 2.8.0 CyaSSL has bug fixes and new features including: -- AES-GCM and AES-CCM use AES-NI -- NetX default IO callback handlers -- IPv6 fixes for DTLS Hello Cookies -- The ability to unload Certs/Keys after the handshake, CyaSSL_UnloadCertsKeys() -- SEP certificate extensions -- Callback getters for easier resource freeing -- External CYASSL_MAX_ERROR_SZ for correct error buffer sizing -- MacEncrypt and DecryptVerify Callbacks for User Atomic Record Layer Processing -- Public Key Callbacks for ECC and RSA -- Client now sends blank cert upon request if doesn't have one with TLS <= 1.2 - - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -*****************CyaSSL Release 2.7.0 (6/17/2013) - -Release 2.7.0 CyaSSL has bug fixes and new features including: -- SNI support for client and server -- KEIL MDK-ARM projects -- Wildcard check to domain name match, and Subject altnames are checked too -- Better error messages for certificate verification errors -- Ability to discard session during handshake verify -- More consistent error returns across all APIs -- Ability to unload CAs at the CTX or CertManager level -- Authority subject id support for Certificate matching -- Persistent session cache functionality -- Persistent CA cache functionality -- Client session table lookups to push serverID table to library level -- Camellia support to sniffer -- User controllable settings for DTLS timeout values -- Sniffer fixes for caching long lived sessions -- DTLS reliability enhancements for the handshake -- Better ThreadX support - -When compiling with Mingw, libtool may give the following warning due to -path conversion errors: - -libtool: link: Could not determine host file name corresponding to ** -libtool: link: Continuing, but uninstalled executables may not work. - -If so, examples and testsuite will have problems when run, showing an -error while loading shared libraries. To resolve, please run "make install". - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -************** CyaSSL Release 2.6.0 (04/15/2013) - -Release 2.6.0 CyaSSL has bug fixes and new features including: -- DTLS 1.2 support including AEAD ciphers -- SHA-3 finalist Blake2 support, it's fast and uses little resources -- SHA-384 cipher suites including ECC ones -- HMAC now supports SHA-512 -- Track memory use for example client/server with -t option -- Better IPv6 examples with --enable-ipv6, before if ipv6 examples/tests were - turned on, localhost only was used. Now link-local (with scope ids) and ipv6 - hosts can be used as well. -- Xcode v4.6 project for iOS v6.1 update -- settings.h is now checked in all *.c files for true one file setting detection -- Better alignment at SSL layer for hardware crypto alignment needs - * Note, SSL itself isn't friendly to alignment with 5 byte TLS headers and - 13 bytes DTLS headers, but every effort is now made to align with the - CYASSL_GENERAL_ALIGNMENT flag which sets desired alignment requirement -- NO_64BIT flag to turn off 64bit data type accumulators in public key code - * Note, some systems are faster with 32bit accumulators -- --enable-stacksize for example client/server stack use - * Note, modern desktop Operating Systems may add bytes to each stack frame -- Updated compression/decompression with direct crypto access -- All ./configure options are now lowercase only for consistency -- ./configure builds default to fastmath option - * Note, if on ia32 and building in shared mode this may produce a problem - with a missing register being available because of PIC, there are at least - 5 solutions to this: - 1) --disable-fastmath , don't use fastmath - 2) --disable-shared, don't build a shared library - 3) C_EXTRA_FLAGS=-DTFM_NO_ASM , turn off assembly use - 4) use clang, it just seems to work - 5) play around with no PIC options to force all registers being open -- Many new ./configure switches for option enable/disable for example - * rsa - * dh - * dsa - * md5 - * sha - * arc4 - * null (allow NULL ciphers) - * oldtls (only use TLS 1.2) - * asn (no certs or public keys allowed) -- ./configure generates cyassl/options.h which allows a header the user can - include in their app to make sure the same options are set at the app and - CyaSSL level. -- autoconf no longer needs serial-tests which lowers version requirements of - automake to 1.11 and autoconf to 2.63 - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -************** CyaSSL Release 2.5.0 (02/04/2013) - -Release 2.5.0 CyaSSL has bug fixes and new features including: -- Fix for TLS CBC padding timing attack identified by Nadhem Alfardan and - Kenny Paterson: http://www.isg.rhul.ac.uk/tls/ -- Microchip PIC32 (MIPS16, MIPS32) support -- Microchip MPLAB X example projects for PIC32 Ethernet Starter Kit -- Updated CTaoCrypt benchmark app for embedded systems -- 1024-bit test certs/keys and cert/key buffers -- AES-CCM-8 crypto and cipher suites -- Camellia crypto and cipher suites -- Bumped minimum autoconf version to 2.65, automake version to 1.12 -- Addition of OCSP callbacks -- STM32F2 support with hardware crypto and RNG -- Cavium NITROX support - -CTaoCrypt now has support for the Microchip PIC32 and has been tested with -the Microchip PIC32 Ethernet Starter Kit, the XC32 compiler and -MPLAB X IDE in both MIPS16 and MIPS32 instruction set modes. See the README -located under the /mplabx directory for more details. - -To add Cavium NITROX support do: - -./configure --with-cavium=/home/user/cavium/software - -pointing to your licensed cavium/software directory. Since Cavium doesn't -build a library we pull in the cavium_common.o file which gives a libtool -warning about the portability of this. Also, if you're using the github source -tree you'll need to remove the -Wredundant-decls warning from the generated -Makefile because the cavium headers don't conform to this warning. Currently -CyaSSL supports Cavium RNG, AES, 3DES, RC4, HMAC, and RSA directly at the crypto -layer. Support at the SSL level is partial and currently just does AES, 3DES, -and RC4. RSA and HMAC are slower until the Cavium calls can be utilized in non -blocking mode. The example client turns on cavium support as does the crypto -test and benchmark. Please see the HAVE_CAVIUM define. - -CyaSSL is able to use the STM32F2 hardware-based cryptography and random number -generator through the STM32F2 Standard Peripheral Library. For necessary -defines, see the CYASSL_STM32F2 define in settings.h. Documentation for the -STM32F2 Standard Peripheral Library can be found in the following document: -http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/USER_MANUAL/DM00023896.pdf - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -*************** CyaSSL Release 2.4.6 (12/20/2012) - -Release 2.4.6 CyaSSL has bug fixes and a few new features including: -- ECC into main version -- Lean PSK build (reduced code size, RAM usage, and stack usage) -- FreeBSD CRL monitor support -- CyaSSL_peek() -- CyaSSL_send() and CyaSSL_recv() for I/O flag setting -- CodeWarrior Support -- MQX Support -- Freescale Kinetis support including Hardware RNG -- autoconf builds use jobserver -- cyassl-config -- Sniffer memory reductions - -Thanks to Brian Aker for the improved autoconf system, make rpm, cyassl-config, -warning system, and general good ideas for improving CyaSSL! - -The Freescale Kinetis K70 RNGA documentation can be found in Chapter 37 of the -K70 Sub-Family Reference Manual: -http://cache.freescale.com/files/microcontrollers/doc/ref_manual/K70P256M150SF3RM.pdf - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -*************** CyaSSL Release 2.4.0 (10/10/2012) - -Release 2.4.0 CyaSSL has bug fixes and a few new features including: -- DTLS reliability -- Reduced memory usage after handshake -- Updated build process - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -*************** CyaSSL Release 2.3.0 (8/10/2012) - -Release 2.3.0 CyaSSL has bug fixes and a few new features including: -- AES-GCM crypto and cipher suites -- make test cipher suite checks -- Subject AltName processing -- Command line support for client/server examples -- Sniffer SessionTicket support -- SHA-384 cipher suites -- Verify cipher suite validity when user overrides -- CRL dir monitoring -- DTLS Cookie support, reliability coming soon - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -***************CyaSSL Release 2.2.0 (5/18/2012) - -Release 2.2.0 CyaSSL has bug fixes and a few new features including: -- Initial CRL support (--enable-crl) -- Initial OCSP support (--enable-ocsp) -- Add static ECDH suites -- SHA-384 support -- ECC client certificate support -- Add medium session cache size (1055 sessions) -- Updated unit tests -- Protection against mutex reinitialization - - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -***************CyaSSL Release 2.0.8 (2/24/2012) - -Release 2.0.8 CyaSSL has bug fixes and a few new features including: -- A fix for malicious certificates pointed out by Remi Gacogne (thanks) - resulting in NULL pointer use. -- Respond to renegotiation attempt with no_renegoatation alert -- Add basic path support for load_verify_locations() -- Add set Temp EC-DHE key size -- Extra checks on rsa test when porting into - - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -************* CyaSSL Release 2.0.6 (1/27/2012) - -Release 2.0.6 CyaSSL has bug fixes and a few new features including: -- Fixes for CA basis constraint check -- CTX reference counting -- Initial unit test additions -- Lean and Mean Windows fix -- ECC benchmarking -- SSMTP build support -- Ability to group handshake messages with set_group_messages(ctx/ssl) -- CA cache addition callback -- Export Base64_Encode for general use - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -************* CyaSSL Release 2.0.2 (12/05/2011) - -Release 2.0.2 CyaSSL has bug fixes and a few new features including: -- CTaoCrypt Runtime library detection settings when directly using the crypto - library -- Default certificate generation now uses SHAwRSA and adds SHA256wRSA generation -- All test certificates now use 2048bit and SHA-1 for better modern browser - support -- Direct AES block access and AES-CTR (counter) mode -- Microchip pic32 support - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -************* CyaSSL Release 2.0.0rc3 (9/28/2011) - -Release 2.0.0rc3 for CyaSSL has bug fixes and a few new features including: -- updated autoconf support -- better make install and uninstall (uses system directories) -- make test / make check -- CyaSSL headers now in -- CTaocrypt headers now in -- OpenSSL compatibility headers now in -- examples and tests all run from home directory so can use certs in ./certs - (see note 1) - -So previous applications that used the OpenSSL compatibility header - now need to include instead, no other -changes are required. - -Special Thanks to Brian Aker for his autoconf, install, and header patches. - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - -************CyaSSL Release 2.0.0rc2 (6/6/2011) - -Release 2.0.0rc2 for CyaSSL has bug fixes and a few new features including: -- bug fixes (Alerts, DTLS with DHE) -- FreeRTOS support -- lwIP support -- Wshadow warnings removed -- asn public header -- CTaoCrypt public headers now all have ctc_ prefix (the manual is still being - updated to reflect this change) -- and more. - -This is the 2nd and perhaps final release candidate for version 2. -Please send any comments or questions to support@yassl.com. - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - -***********CyaSSL Release 2.0.0rc1 (5/2/2011) - -Release 2.0.0rc1 for CyaSSL has many new features including: -- bug fixes -- SHA-256 cipher suites -- Root Certificate Verification (instead of needing all certs in the chain) -- PKCS #8 private key encryption (supports PKCS #5 v1-v2 and PKCS #12) -- Serial number retrieval for x509 -- PBKDF2 and PKCS #12 PBKDF -- UID parsing for x509 -- SHA-256 certificate signatures -- Client and server can send chains (SSL_CTX_use_certificate_chain_file) -- CA loading can now parse multiple certificates per file -- Dynamic memory runtime hooks -- Runtime hooks for logging -- EDH on server side -- More informative error codes -- More informative logging messages -- Version downgrade more robust (use SSL_v23*) -- Shared build only by default through ./configure -- Compiler visibility is now used, internal functions not polluting namespace -- Single Makefile, no recursion, for faster and simpler building -- Turn on all warnings possible build option, warning fixes -- and more. - -Because of all the new features and the multiple OS, compiler, feature-set -options that CyaSSL allows, there may be some configuration fixes needed. -Please send any comments or questions to support@yassl.com. - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - -****************** CyaSSL Release 1.9.0 (3/2/2011) - -Release 1.9.0 for CyaSSL adds bug fixes, improved TLSv1.2 through testing and -better hash/sig algo ids, --enable-webServer for the yaSSL embedded web server, -improper AES key setup detection, user cert verify callback improvements, and -more. - -The CyaSSL manual offering is included in the doc/ directory. For build -instructions and comments about the new features please check the manual. - -Please send any comments or questions to support@yassl.com. - -****************** CyaSSL Release 1.8.0 (12/23/2010) - -Release 1.8.0 for CyaSSL adds bug fixes, x509 v3 CA signed certificate -generation, a C standard library abstraction layer, lower memory use, increased -portability through the os_settings.h file, and the ability to use NTRU cipher -suites when used in conjunction with an NTRU license and library. - -The initial CyaSSL manual offering is included in the doc/ directory. For -build instructions and comments about the new features please check the manual. - -Please send any comments or questions to support@yassl.com. - -Happy Holidays. - - -********************* CyaSSL Release 1.6.5 (9/9/2010) - -Release 1.6.5 for CyaSSL adds bug fixes and x509 v3 self signed certificate -generation. - -For general build instructions see doc/Building_CyaSSL.pdf. - -To enable certificate generation support add this option to ./configure -./configure --enable-certgen - -An example is included in ctaocrypt/test/test.c and documentation is provided -in doc/CyaSSL_Extensions_Reference.pdf item 11. - -********************** CyaSSL Release 1.6.0 (8/27/2010) - -Release 1.6.0 for CyaSSL adds bug fixes, RIPEMD-160, SHA-512, and RSA key -generation. - -For general build instructions see doc/Building_CyaSSL.pdf. - -To add RIPEMD-160 support add this option to ./configure -./configure --enable-ripemd - -To add SHA-512 support add this option to ./configure -./configure --enable-sha512 - -To add RSA key generation support add this option to ./configure -./configure --enable-keygen - -Please see ctaocrypt/test/test.c for examples and usage. - -For Windows, RIPEMD-160 and SHA-512 are enabled by default but key generation is -off by default. To turn key generation on add the define CYASSL_KEY_GEN to -CyaSSL. - - -************* CyaSSL Release 1.5.6 (7/28/2010) - -Release 1.5.6 for CyaSSL adds bug fixes, compatibility for our JSSE provider, -and a fix for GCC builds on some systems. - -For general build instructions see doc/Building_CyaSSL.pdf. - -To add AES-NI support add this option to ./configure -./configure --enable-aesni - -You'll need GCC 4.4.3 or later to make use of the assembly. - -************** CyaSSL Release 1.5.4 (7/7/2010) - -Release 1.5.4 for CyaSSL adds bug fixes, support for AES-NI, SHA1 speed -improvements from loop unrolling, and support for the Mongoose Web Server. - -For general build instructions see doc/Building_CyaSSL.pdf. - -To add AES-NI support add this option to ./configure -./configure --enable-aesni - -You'll need GCC 4.4.3 or later to make use of the assembly. - -*************** CyaSSL Release 1.5.0 (5/11/2010) - -Release 1.5.0 for CyaSSL adds bug fixes, GoAhead WebServer support, sniffer -support, and initial swig interface support. - -For general build instructions see doc/Building_CyaSSL.pdf. - -To add support for GoAhead WebServer either --enable-opensslExtra or if you -don't want all the features of opensslExtra you can just define GOAHEAD_WS -instead. GOAHEAD_WS can be added to ./configure with CFLAGS=-DGOAHEAD_WS or -you can define it yourself. - -To look at the sniffer support please see the sniffertest app in -sslSniffer/sslSnifferTest. Build with --enable-sniffer on *nix or use the -vcproj files on windows. You'll need to have pcap installed on *nix and -WinPcap on windows. - -A swig interface file is now located in the swig directory for using Python, -Java, Perl, and others with CyaSSL. This is initial support and experimental, -please send questions or comments to support@yassl.com. - -When doing load testing with CyaSSL, on the echoserver example say, the client -machine may run out of tcp ephemeral ports, they will end up in the TIME_WAIT -queue, and can't be reused by default. There are generally two ways to fix -this. 1) Reduce the length sockets remain on the TIME_WAIT queue or 2) Allow -items on the TIME_WAIT queue to be reused. - - -To reduce the TIME_WAIT length in OS X to 3 seconds (3000 milliseconds) - -sudo sysctl -w net.inet.tcp.msl=3000 - -In Linux - -sudo sysctl -w net.ipv4.tcp_tw_reuse=1 - -allows reuse of sockets in TIME_WAIT - -sudo sysctl -w net.ipv4.tcp_tw_recycle=1 - -works but seems to remove sockets from TIME_WAIT entirely? - -sudo sysctl -w net.ipv4.tcp_fin_timeout=1 - -doen't control TIME_WAIT, it controls FIN_WAIT(2) contrary to some posts - - -******************** CyaSSL Release 1.4.0 (2/18/2010) - -Release 1.3.0 for CyaSSL adds bug fixes, better multi TLS/SSL version support -through SSLv23_server_method(), and improved documentation in the doc/ folder. - -For general build instructions doc/Building_CyaSSL.pdf. - -******************** CyaSSL Release 1.3.0 (1/21/2010) - -Release 1.3.0 for CyaSSL adds bug fixes, a potential security problem fix, -better porting support, removal of assert()s, and a complete THREADX port. - -For general build instructions see rc1 below. - -******************** CyaSSL Release 1.2.0 (11/2/2009) - -Release 1.2.0 for CyaSSL adds bug fixes and session negotiation if first use is -read or write. - -For general build instructions see rc1 below. - -******************** CyaSSL Release 1.1.0 (9/2/2009) - -Release 1.1.0 for CyaSSL adds bug fixes, a check against malicious session -cache use, support for lighttpd, and TLS 1.2. - -To get TLS 1.2 support please use the client and server functions: - -SSL_METHOD *TLSv1_2_server_method(void); -SSL_METHOD *TLSv1_2_client_method(void); - -CyaSSL was tested against lighttpd 1.4.23. To build CyaSSL for use with -lighttpd use the following commands from the CyaSSL install dir : - -./configure --disable-shared --enable-opensslExtra --enable-fastmath --without-zlib - -make -make openssl-links - -Then to build lighttpd with CyaSSL use the following commands from the -lighttpd install dir: - -./configure --with-openssl --with-openssl-includes=/include --with-openssl-libs=/lib LDFLAGS=-lm - -make - -On some systems you may get a linker error about a duplicate symbol for -MD5_Init or other MD5 calls. This seems to be caused by the lighttpd src file -md5.c, which defines MD5_Init(), and is included in liblightcomp_la-md5.o. -When liblightcomp is linked with the SSL_LIBs the linker may complain about -the duplicate symbol. This can be fixed by editing the lighttpd src file md5.c -and adding this line to the beginning of the file: - -#if 0 - -and this line to the end of the file - -#endif - -Then from the lighttpd src dir do a: - -make clean -make - - -If you get link errors about undefined symbols more than likely the actual -OpenSSL libraries are found by the linker before the CyaSSL openssl-links that -point to the CyaSSL library, causing the linker confusion. This can be fixed -by editing the Makefile in the lighttpd src directory and changing the line: - -SSL_LIB = -lssl -lcrypto - -to - -SSL_LIB = -lcyassl - -Then from the lighttpd src dir do a: - -make clean -make - -This should remove any confusion the linker may be having with missing symbols. - -For any questions or concerns please contact support@yassl.com . - -For general build instructions see rc1 below. - -******************CyaSSL Release 1.0.6 (8/03/2009) - -Release 1.0.6 for CyaSSL adds bug fixes, an improved session cache, and faster -math with a huge code option. - -The session cache now defaults to a client mode, also good for embedded servers. -For servers not under heavy load (less than 200 new sessions per minute), define -BIG_SESSION_CACHE. If the server will be under heavy load, define -HUGE_SESSION_CACHE. - -There is now a fasthugemath option for configure. This enables fastmath plus -even faster math by greatly increasing the code size of the math library. Use -the benchmark utility to compare public key operations. - - -For general build instructions see rc1 below. - -******************CyaSSL Release 1.0.3 (5/10/2009) - -Release 1.0.3 for CyaSSL adds bug fixes and add increased support for OpenSSL -compatibility when building other applications. - -Release 1.0.3 includes an alpha release of DTLS for both client and servers. -This is only for testing purposes at this time. Rebroadcast and reordering -aren't fully implemented at this time but will be for the next release. - -For general build instructions see rc1 below. - -******************CyaSSL Release 1.0.2 (4/3/2009) - -Release 1.0.2 for CyaSSL adds bug fixes for a couple I/O issues. Some systems -will send a SIGPIPE on socket recv() at any time and this should be handled by -the application by turning off SIGPIPE through setsockopt() or returning from -the handler. - -Release 1.0.2 includes an alpha release of DTLS for both client and servers. -This is only for testing purposes at this time. Rebroadcast and reordering -aren't fully implemented at this time but will be for the next release. - -For general build instructions see rc1 below. - -*****************CyaSSL Release Candidiate 3 rc3-1.0.0 (2/25/2009) - - -Release Candidate 3 for CyaSSL 1.0.0 adds bug fixes and adds a project file for -iPhone development with Xcode. cyassl-iphone.xcodeproj is located in the root -directory. This release also includes a fix for supporting other -implementations that bundle multiple messages at the record layer, this was -lost when cyassl i/o was re-implemented but is now fixed. - -For general build instructions see rc1 below. - -*****************CyaSSL Release Candidiate 2 rc2-1.0.0 (1/21/2009) - - -Release Candidate 2 for CyaSSL 1.0.0 adds bug fixes and adds two new stream -ciphers along with their respective cipher suites. CyaSSL adds support for -HC-128 and RABBIT stream ciphers. The new suites are: - -TLS_RSA_WITH_HC_128_SHA -TLS_RSA_WITH_RABBIT_SHA - -And the corresponding cipher names are - -HC128-SHA -RABBIT-SHA - -CyaSSL also adds support for building with devkitPro for PPC by changing the -library proper to use libogc. The examples haven't been changed yet but if -there's interest they can be. Here's an example ./configure to build CyaSSL -for devkitPro: - -./configure --disable-shared CC=/pathTo/devkitpro/devkitPPC/bin/powerpc-gekko-gcc --host=ppc --without-zlib --enable-singleThreaded RANLIB=/pathTo/devkitpro/devkitPPC/bin/powerpc-gekko-ranlib CFLAGS="-DDEVKITPRO -DGEKKO" - -For linking purposes you'll need - -LDFLAGS="-g -mrvl -mcpu=750 -meabi -mhard-float -Wl,-Map,$(notdir $@).map" - -For general build instructions see rc1 below. - - -********************CyaSSL Release Candidiate 1 rc1-1.0.0 (12/17/2008) - - -Release Candidate 1 for CyaSSL 1.0.0 contains major internal changes. Several -areas have optimization improvements, less dynamic memory use, and the I/O -strategy has been refactored to allow alternate I/O handling or Library use. -Many thanks to Thierry Fournier for providing these ideas and most of the work. - -Because of these changes, this release is only a candidate since some problems -are probably inevitable on some platform with some I/O use. Please report any -problems and we'll try to resolve them as soon as possible. You can contact us -at support@yassl.com or todd@yassl.com. - -Using TomsFastMath by passing --enable-fastmath to ./configure now uses assembly -on some platforms. This is new so please report any problems as every compiler, -mode, OS combination hasn't been tested. On ia32 all of the registers need to -be available so be sure to pass these options to CFLAGS: - -CFLAGS="-O3 -fomit-frame-pointer" - -OS X will also need -mdynamic-no-pic added to CFLAGS - -Also if you're building in shared mode for ia32 you'll need to pass options to -LDFLAGS as well on OS X: - -LDFLAGS=-Wl,-read_only_relocs,warning - -This gives warnings for some symbols but seems to work. - - ---To build on Linux, Solaris, *BSD, Mac OS X, or Cygwin: - - ./configure - make - - from the ./testsuite/ directory run ./testsuite - -to make a debug build: - - ./configure --enable-debug --disable-shared - make - - - ---To build on Win32 - -Choose (Re)Build All from the project workspace - -Run the testsuite program - - - - - -*************************CyaSSL version 0.9.9 (7/25/2008) - -This release of CyaSSL adds bug fixes, Pre-Shared Keys, over-rideable memory -handling, and optionally TomsFastMath. Thanks to Moisés Guimarães for the -work on TomsFastMath. - -To optionally use TomsFastMath pass --enable-fastmath to ./configure -Or define USE_FAST_MATH in each project from CyaSSL for MSVC. - -Please use the benchmark routine before and after to see the performance -difference, on some platforms the gains will be little but RSA encryption -always seems to be faster. On x86-64 machines with GCC the normal math library -may outperform the fast one when using CFLAGS=-m64 because TomsFastMath can't -yet use -m64 because of GCCs inability to do 128bit division. - - **** UPDATE GCC 4.2.1 can now do 128bit division *** - -See notes below (0.2.0) for complete build instructions. - - -****************CyaSSL version 0.9.8 (5/7/2008) - -This release of CyaSSL adds bug fixes, client side Diffie-Hellman, and better -socket handling. - -See notes below (0.2.0) for complete build instructions. - - -****************CyaSSL version 0.9.6 (1/31/2008) - -This release of CyaSSL adds bug fixes, increased session management, and a fix -for gnutls. - -See notes below (0.2.0) for complete build instructions. - - -****************CyaSSL version 0.9.0 (10/15/2007) - -This release of CyaSSL adds bug fixes, MSVC 2005 support, GCC 4.2 support, -IPV6 support and test, and new test certificates. - -See notes below (0.2.0) for complete build instructions. - - -****************CyaSSL version 0.8.0 (1/10/2007) - -This release of CyaSSL adds increased socket support, for non-blocking writes, -connects, and interrupted system calls. - -See notes below (0.2.0) for complete build instructions. - - -****************CyaSSL version 0.6.3 (10/30/2006) - -This release of CyaSSL adds debug logging to stderr to aid in the debugging of -CyaSSL on systems that may not provide the best support. - -If CyaSSL is built with debugging support then you need to call -CyaSSL_Debugging_ON() to turn logging on. - -On Unix use ./configure --enable-debug - -On Windows define DEBUG_CYASSL when building CyaSSL - - -To turn logging back off call CyaSSL_Debugging_OFF() - -See notes below (0.2.0) for complete build instructions. - - -*****************CyaSSL version 0.6.2 (10/29/2006) - -This release of CyaSSL adds TLS 1.1. - -Note that CyaSSL has certificate verification on by default, unlike OpenSSL. -To emulate OpenSSL behavior, you must call SSL_CTX_set_verify() with -SSL_VERIFY_NONE. In order to have full security you should never do this, -provide CyaSSL with the proper certificates to eliminate impostors and call -CyaSSL_check_domain_name() to prevent man in the middle attacks. - -See notes below (0.2.0) for build instructions. - -*****************CyaSSL version 0.6.0 (10/25/2006) - -This release of CyaSSL adds more SSL functions, better autoconf, nonblocking -I/O for accept, connect, and read. There is now an --enable-small configure -option that turns off TLS, AES, DES3, HMAC, and ERROR_STRINGS, see configure.in -for the defines. Note that TLS requires HMAC and AES requires TLS. - -See notes below (0.2.0) for build instructions. - - -*****************CyaSSL version 0.5.5 (09/27/2006) - -This mini release of CyaSSL adds better input processing through buffered input -and big message support. Added SSL_pending() and some sanity checks on user -settings. - -See notes below (0.2.0) for build instructions. - - -*****************CyaSSL version 0.5.0 (03/27/2006) - -This release of CyaSSL adds AES support and minor bug fixes. - -See notes below (0.2.0) for build instructions. - - -*****************CyaSSL version 0.4.0 (03/15/2006) - -This release of CyaSSL adds TLSv1 client/server support and libtool. - -See notes below for build instructions. - - -*****************CyaSSL version 0.3.0 (02/26/2006) - -This release of CyaSSL adds SSLv3 server support and session resumption. - -See notes below for build instructions. - - -*****************CyaSSL version 0.2.0 (02/19/2006) - - -This is the first release of CyaSSL and its crypt brother, CTaoCrypt. CyaSSL -is written in ANSI C with the idea of a small code size, footprint, and memory -usage in mind. CTaoCrypt can be as small as 32K, and the current client -version of CyaSSL can be as small as 12K. - - -The first release of CTaoCrypt supports MD5, SHA-1, 3DES, ARC4, Big Integer -Support, RSA, ASN parsing, and basic x509 (en/de)coding. - -The first release of CyaSSL supports normal client RSA mode SSLv3 connections -with support for SHA-1 and MD5 digests. Ciphers include 3DES and RC4. - - ---To build on Linux, Solaris, *BSD, Mac OS X, or Cygwin: - - ./configure - make - - from the ./testsuite/ directory run ./testsuite - -to make a debug build: - - ./configure --enable-debug --disable-shared - make - - - ---To build on Win32 - -Choose (Re)Build All from the project workspace - -Run the testsuite program - - - -*** The next release of CyaSSL will support a server and more OpenSSL -compatibility functions. - - -Please send questions or comments to todd@yassl.com - +# wolfSSL Release 4.4.0 (04/22/2020) + +If you have questions about this release, feel free to contact us on our +info@ address. + +Release 4.4.0 of wolfSSL embedded TLS has bug fixes and new features including: + +## New Feature Additions + +* Hexagon support. +* DSP builds to offload ECC verify operations. +* Certificate Manager callback support. +* New APIs for running updates to ChaCha20/Poly1305 AEAD. +* Support for use with Apache. +* Add support for IBM s390x. +* PKCS8 support for ED25519. +* OpenVPN support. +* Add P384 curve support to SP. +* Add BIO and EVP API. +* Add AES-OFB mode. +* Add AES-CFB mode. +* Add Curve448, X448, and Ed448. +* Add Renesas Synergy S7G2 build and hardware acceleration. + +## Fixes + +* Fix for RSA public encrypt / private sign with RSA key sizes over 2048-bit. +* Correct misspellings. +* Secure renegotiation fix. +* Fix memory leak when using ATECC and non-SECP256R1 curves for sign, verify, + or shared secret. +* Fix for K64 MMCAU with `WOLFSSL_SMALL_STACK_CACHE`. +* Fix the RSA verify only build. +* Fix in SP C implementation for small stack. +* Fix using the auth key id extension is set, hash might not be present. +* Fix when flattening certificate structure to include the subject alt names. +* Fixes for building with ECC sign/verify only. +* Fix for ECC and no cache resistance. +* Fix memory leak in DSA. +* Fix build on minGW. +* Fix `PemToDer()` call in `ProcessBuffer()` to set more than ECC. +* Fix for using RSA without SHA-512. +* Add some close tags to the echoserver HTTP example output. +* Miscellaneous fixes and updates for static analysis reports. +* Fixes for time structure support. +* Fixes for VxWorks support. +* Fixes for Async crypto support. +* Fix cache resist compile to work with SP C code. +* Fixes for Curve25519 x64 asm. +* Fix for SP x64 div. +* Fix for DTLS edge case where CCS and Finished come out of order and the + retransmit pool gets flushed. +* Fix for infinite loop in SHA-1 with small inputs. Thanks to Peter W. +* Fix for FIPS Hmac where `wc_HmacInit()` isn't used. `wc_HmacSetKey()` needs + to initialize the Hmac structure. Type is set to NONE, and checked against + NONE, not 0. +* Fixes for SP RSA private operations. +* Fixes for Xilinx SDK and Zynq UltraScale+ MPSoC +* Fix leak when building with HAVE_AESGCM and NO_AES_DECRYPT. Thanks G.G. +* Fixes for building ECC without ASN. +* Fix for async TLSv1.3 issues. +* Fix `wc_KeyPemToDer()` with PKCS1 and empty key. +* Omit `-fomit-frame-pointer` from CFLAGS in configure.ac. + +## Improvements/Optimizations + +* Qt 5.12 and 5.13 support. +* Added more digest types to Cryptocell RSA sign/verify. +* Some memory usage improvements. +* Speed improvements for mp_rand. +* Improvements to CRL and OCSP support. +* Refactor Poly1305 AEAD/MAC to reduce duplicate code. +* Add blinding to RSA key gen. +* Improvements to blinding. +* Improvement and expansion of OpenSSL Compatibility Layer. +* Improvements to ChaCha20. +* Improvements to X.509 processing. +* Improvements to ECC support. +* Improvement in detecting 64-bit support. +* Refactor to combine duplicate ECC parameter parsing code. +* Improve keyFormat to be set by algId and let later key parsing produce fail. +* Add test cases for 3072-bit and 4096-bit RSA keys. +* Improve signature wrapper and DH test cases. +* Improvements to the configure.ac script. +* Added constant time RSA q modinv p. +* Improve performance of SP Intel 64-bit asm. +* Added a few more functions to the ABI list. +* Improve TLS bidirectional shutdown behavior. +* OpenSSH 8.1 support. +* Improve performance of RSA/DH operations on x64. +* Add support for PKCS7/CMS Enveloped data with fragmented encrypted content. +* Example linker description for FIPS builds to enforce object ordering. +* C# wrapper improvements. Added TLS client example and TLSv1.3 methods. +* Allow setting MTU in DTLS. +* Improve PKCS12 create for outputting encrypted bundles. +* Constant time EC map to affine for private operations. +* Improve performance of RSA public key ops with TFM. +* Smaller table version of AES encrypt/decrypt. +* Support IAR with position independent code (ROPI). +* Improve speed of AArch64 assembly. +* Support AES-CTR with AES-NI. +* Support AES-CTR on esp32. +* Add a no malloc option for small SP math. + +## This release of wolfSSL includes fixes for 2 security vulnerabilities. + +* For fast math, use a constant time modular inverse when mapping to affine + when operation involves a private key - keygen, calc shared secret, sign. + Thank you to Alejandro Cabrera Aldaya, Cesar Pereida García and + Billy Bob Brumley from the Network and Information Security Group (NISEC) + at Tampere University for the report. + +* Change constant time and cache resistant ECC mulmod. Ensure points being + operated on change to make constant time. Thank you to Pietro Borrello at + Sapienza University of Rome. + +For additional vulnerability information visit the vulnerability page at +https://www.wolfssl.com/docs/security-vulnerabilities/ + +See INSTALL file for build instructions. +More info can be found on-line at https://wolfssl.com/wolfSSL/Docs.html + + + +*** Resources *** + + +[wolfSSL Website](https://www.wolfssl.com/) + +[wolfSSL Wiki](https://github.com/wolfSSL/wolfssl/wiki) + +[FIPS FAQ](https://wolfssl.com/license/fips) + +[wolfSSL Documents](https://wolfssl.com/wolfSSL/Docs.html) + +[wolfSSL Manual](https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-toc.html) + +[wolfSSL API Reference] +(https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-17-wolfssl-api-reference.html) + +[wolfCrypt API Reference] +(https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-18-wolfcrypt-api-reference.html) + +[TLS 1.3](https://www.wolfssl.com/docs/tls13/) + +[wolfSSL Vulnerabilities] +(https://www.wolfssl.com/docs/security-vulnerabilities/) diff --git a/FreeRTOS-Plus/Source/WolfSSL/README.md b/FreeRTOS-Plus/Source/WolfSSL/README.md index a490ac2ff..db1b54488 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/README.md +++ b/FreeRTOS-Plus/Source/WolfSSL/README.md @@ -1,1194 +1,222 @@ -# Notes - Please read +*** Description *** -## Note 1 -``` -wolfSSL now needs all examples and tests to be run from the wolfSSL home -directory. This is because it finds certs and keys from ./certs/. Trying to -maintain the ability to run each program from its own directory, the testsuite -directory, the main directory (for make check/test), and for the various -different project layouts (with or without config) was becoming harder and -harder. Now to run testsuite just do: +The wolfSSL embedded SSL library (formerly CyaSSL) is a lightweight SSL/TLS +library written in ANSI C and targeted for embedded, RTOS, and +resource-constrained environments - primarily because of its small size, speed, +and feature set. It is commonly used in standard operating environments as well +because of its royalty-free pricing and excellent cross platform support. +wolfSSL supports industry standards up to the current TLS 1.3 and DTLS 1.2 +levels, is up to 20 times smaller than OpenSSL, and offers progressive ciphers +such as ChaCha20, Curve25519, NTRU, and Blake2b. User benchmarking and feedback +reports dramatically better performance when using wolfSSL over OpenSSL. -./testsuite/testsuite +wolfSSL is powered by the wolfCrypt library. Two versions of the wolfCrypt +cryptography library have been FIPS 140-2 validated (Certificate #2425 and +certificate #3389). For additional information, visit the wolfCrypt FIPS FAQ +(https://www.wolfssl.com/license/fips/) or contact fips@wolfssl.com -or +*** Why choose wolfSSL? *** -make check (when using autoconf) +There are many reasons to choose wolfSSL as your embedded SSL solution. Some of +the top reasons include size (typical footprint sizes range from 20-100 kB), +support for the newest standards (SSL 3.0, TLS 1.0, TLS 1.1, TLS 1.2, TLS 1.3, +DTLS 1.0, and DTLS 1.2), current and progressive cipher support (including +stream ciphers), multi-platform, royalty free, and an OpenSSL compatibility API +to ease porting into existing applications which have previously used the +OpenSSL package. For a complete feature list, see chapter 4 of the wolfSSL +manual. (https://www.wolfssl.com/docs/wolfssl-manual/ch4/) -On *nix or Windows the examples and testsuite will check to see if the current -directory is the source directory and if so, attempt to change to the wolfSSL -home directory. This should work in most setup cases, if not, just follow the -beginning of the note and specify the full path. -``` +*** Notes, Please read *** -## Note 2 -``` +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), or +enable ECC (ECC is on by default), or you must enable static key cipher suites +with + + WOLFSSL_STATIC_DH + WOLFSSL_STATIC_RSA + or + 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 +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 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. + +Note 2) wolfSSL takes a different approach to certificate verification than OpenSSL -does. The default policy for the client is to verify the server, this means +does. The default policy for the client is to verify the server, this means that if you don't load CAs to verify the server you'll get a connect error, -no signer error to confirm failure (-188). If you want to mimic OpenSSL -behavior of having SSL_connect succeed even if verifying the server fails and -reducing security you can do this by calling: +no signer error to confirm failure (-188). -wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); +If you want to mimic OpenSSL behavior of having SSL_connect succeed even if +verifying the server fails and reducing security you can do this by calling: -before calling wolfSSL_new(); Though it's not recommended. -``` + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); -- GNU Binutils 2.24 ld has problems with some debug builds, to fix an ld error - add -fdebug-types-section to C_EXTRA_FLAGS +before calling wolfSSL_new();. Though it's not recommended. -#wolfSSL (Formerly CyaSSL) Release 3.4.8 (04/06/2015) +Note 3) +The enum values SHA, SHA256, SHA384, SHA512 are no longer available when +wolfSSL is built with --enable-opensslextra (OPENSSL_EXTRA) or with the macro +NO_OLD_SHA_NAMES. These names get mapped to the OpenSSL API for a single call +hash function. Instead the name WC_SHA, WC_SHA256, WC_SHA384 and WC_SHA512 +should be used for the enum name. -##Release 3.4.8 of wolfSSL has bug fixes and new features including: +*** end Notes *** -- FIPS version submitted for iOS. -- Max Strength build that only allows TLSv1.2, AEAD ciphers, and PFS. -- Improvements to usage of time code. -- Improvements to VS solution files. + +# wolfSSL Release 4.4.0 (04/22/2020) + +If you have questions about this release, feel free to contact us on our +info@ address. + +Release 4.4.0 of wolfSSL embedded TLS has bug fixes and new features including: + +## New Feature Additions + +* Hexagon support. +* DSP builds to offload ECC verify operations. +* Certificate Manager callback support. +* New APIs for running updates to ChaCha20/Poly1305 AEAD. +* Support for use with Apache. +* Add support for IBM s390x. +* PKCS8 support for ED25519. +* OpenVPN support. +* Add P384 curve support to SP. +* Add BIO and EVP API. +* Add AES-OFB mode. +* Add AES-CFB mode. +* Add Curve448, X448, and Ed448. +* Add Renesas Synergy S7G2 build and hardware acceleration. + +## Fixes + +* Fix for RSA public encrypt / private sign with RSA key sizes over 2048-bit. +* Correct misspellings. +* Secure renegotiation fix. +* Fix memory leak when using ATECC and non-SECP256R1 curves for sign, verify, + or shared secret. +* Fix for K64 MMCAU with `WOLFSSL_SMALL_STACK_CACHE`. +* Fix the RSA verify only build. +* Fix in SP C implementation for small stack. +* Fix using the auth key id extension is set, hash might not be present. +* Fix when flattening certificate structure to include the subject alt names. +* Fixes for building with ECC sign/verify only. +* Fix for ECC and no cache resistance. +* Fix memory leak in DSA. +* Fix build on minGW. +* Fix `PemToDer()` call in `ProcessBuffer()` to set more than ECC. +* Fix for using RSA without SHA-512. +* Add some close tags to the echoserver HTTP example output. +* Miscellaneous fixes and updates for static analysis reports. +* Fixes for time structure support. +* Fixes for VxWorks support. +* Fixes for Async crypto support. +* Fix cache resist compile to work with SP C code. +* Fixes for Curve25519 x64 asm. +* Fix for SP x64 div. +* Fix for DTLS edge case where CCS and Finished come out of order and the + retransmit pool gets flushed. +* Fix for infinite loop in SHA-1 with small inputs. Thanks to Peter W. +* Fix for FIPS Hmac where `wc_HmacInit()` isn't used. `wc_HmacSetKey()` needs + to initialize the Hmac structure. Type is set to NONE, and checked against + NONE, not 0. +* Fixes for SP RSA private operations. +* Fixes for Xilinx SDK and Zynq UltraScale+ MPSoC +* Fix leak when building with HAVE_AESGCM and NO_AES_DECRYPT. Thanks G.G. +* Fixes for building ECC without ASN. +* Fix for async TLSv1.3 issues. +* Fix `wc_KeyPemToDer()` with PKCS1 and empty key. +* Omit `-fomit-frame-pointer` from CFLAGS in configure.ac. + +## Improvements/Optimizations + +* Qt 5.12 and 5.13 support. +* Added more digest types to Cryptocell RSA sign/verify. +* Some memory usage improvements. +* Speed improvements for mp_rand. +* Improvements to CRL and OCSP support. +* Refactor Poly1305 AEAD/MAC to reduce duplicate code. +* Add blinding to RSA key gen. +* Improvements to blinding. +* Improvement and expansion of OpenSSL Compatibility Layer. +* Improvements to ChaCha20. +* Improvements to X.509 processing. +* Improvements to ECC support. +* Improvement in detecting 64-bit support. +* Refactor to combine duplicate ECC parameter parsing code. +* Improve keyFormat to be set by algId and let later key parsing produce fail. +* Add test cases for 3072-bit and 4096-bit RSA keys. +* Improve signature wrapper and DH test cases. +* Improvements to the configure.ac script. +* Added constant time RSA q modinv p. +* Improve performance of SP Intel 64-bit asm. +* Added a few more functions to the ABI list. +* Improve TLS bidirectional shutdown behavior. +* OpenSSH 8.1 support. +* Improve performance of RSA/DH operations on x64. +* Add support for PKCS7/CMS Enveloped data with fragmented encrypted content. +* Example linker description for FIPS builds to enforce object ordering. +* C# wrapper improvements. Added TLS client example and TLSv1.3 methods. +* Allow setting MTU in DTLS. +* Improve PKCS12 create for outputting encrypted bundles. +* Constant time EC map to affine for private operations. +* Improve performance of RSA public key ops with TFM. +* Smaller table version of AES encrypt/decrypt. +* Support IAR with position independent code (ROPI). +* Improve speed of AArch64 assembly. +* Support AES-CTR with AES-NI. +* Support AES-CTR on esp32. +* Add a no malloc option for small SP math. + +## This release of wolfSSL includes fixes for 2 security vulnerabilities. + +* For fast math, use a constant time modular inverse when mapping to affine + when operation involves a private key - keygen, calc shared secret, sign. + Thank you to Alejandro Cabrera Aldaya, Cesar Pereida García and + Billy Bob Brumley from the Network and Information Security Group (NISEC) + at Tampere University for the report. + +* Change constant time and cache resistant ECC mulmod. Ensure points being + operated on change to make constant time. Thank you to Pietro Borrello at + Sapienza University of Rome. + +For additional vulnerability information visit the vulnerability page at +https://www.wolfssl.com/docs/security-vulnerabilities/ See INSTALL file for build instructions. -More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html +More info can be found on-line at https://wolfssl.com/wolfSSL/Docs.html -#wolfSSL (Formerly CyaSSL) Release 3.4.6 (03/30/2015) -##Release 3.4.6 of wolfSSL has bug fixes and new features including: +*** Resources *** -- Intel Assembly Speedups using instructions rdrand, rdseed, aesni, avx1/2, - rorx, mulx, adox, adcx . They can be enabled with --enable-intelasm. - These speedup the use of RNG, SHA2, and public key algorithms. -- Ed25519 support at the crypto level. Turn on with --enable-ed25519. Examples - in wolcrypt/test/test.c ed25519_test(). -- Post Handshake Memory reductions. wolfSSL can now hold less than 1,000 bytes - of memory per secure connection including cipher state. -- wolfSSL API and wolfCrypt API fixes, you can still include the cyassl and - ctaocrypt headers which will enable the compatibility APIs for the - foreseeable future -- INSTALL file to help direct users to build instructions for their environment -- For ECC users with the normal math library a fix that prevents a crash when - verify signature fails. Users of 3.4.0 with ECC and the normal math library - must update -- RC4 is now disabled by default in autoconf mode -- AES-GCM and ChaCha20/Poly1305 are now enabled by default to make AEAD ciphers - available without a switch -- External ChaCha-Poly AEAD API, thanks to Andrew Burks for the contribution -- DHE-PSK cipher suites can now be built without ASN or Cert support -- Fix some NO MD5 build issues with optional features -- Freescale CodeWarrior project updates -- ECC curves can be individually turned on/off at build time. -- Sniffer handles Cert Status message and other minor fixes -- SetMinVersion() at the wolfSSL Context level instead of just SSL session level - to allow minimum protocol version allowed at runtime -- RNG failure resource cleanup fix -- No high level security fixes that requires an update though we always - recommend updating to the latest (except note 6 use case of ecc/normal math) +[wolfSSL Website](https://www.wolfssl.com/) -See INSTALL file for build instructions. -More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html +[wolfSSL Wiki](https://github.com/wolfSSL/wolfssl/wiki) +[FIPS FAQ](https://wolfssl.com/license/fips) -#wolfSSL (Formerly CyaSSL) Release 3.4.0 (02/23/2015) +[wolfSSL Documents](https://wolfssl.com/wolfSSL/Docs.html) -## Release 3.4.0 wolfSSL has bug fixes and new features including: +[wolfSSL Manual](https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-toc.html) -- wolfSSL API and wolfCrypt API, you can still include the cyassl and ctaocrypt - headers which will enable the compatibility APIs for the foreseeable future -- Example use of the wolfCrypt API can be found in wolfcrypt/test/test.c -- Example use of the wolfSSL API can be found in examples/client/client.c -- Curve25519 now supported at the wolfCrypt level, wolfSSL layer coming soon -- Improvements in the build configuration under AIX -- Microchip Pic32 MZ updates -- TIRTOS updates -- PowerPC updates -- Xcode project update -- Bidirectional shutdown examples in client/server with -w (wait for full - shutdown) option -- Cycle counts on benchmarks for x86_64, more coming soon -- ALT_ECC_SIZE for reducing ecc heap use with fastmath when also using large RSA - keys -- Various compile warnings -- Scan-build warning fixes -- Changed a memcpy to memmove in the sniffer (if using sniffer please update) -- No high level security fixes that requires an update though we always - recommend updating to the latest +[wolfSSL API Reference] +(https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-17-wolfssl-api-reference.html) +[wolfCrypt API Reference] +(https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-18-wolfcrypt-api-reference.html) -# CyaSSL Release 3.3.0 (12/05/2014) +[TLS 1.3](https://www.wolfssl.com/docs/tls13/) -- Countermeasuers for Handshake message duplicates, CHANGE CIPHER without - FINISHED, and fast forward attempts. Thanks to Karthikeyan Bhargavan from - the Prosecco team at INRIA Paris-Rocquencourt for the report. -- FIPS version submitted -- Removes SSLv2 Client Hello processing, can be enabled with OLD_HELLO_ALLOWED -- User can set mimimum downgrade version with CyaSSL_SetMinVersion() -- Small stack improvements at TLS/SSL layer -- TLS Master Secret generation and Key Expansion are now exposed -- Adds client side Secure Renegotiation, * not recommended * -- Client side session ticket support, not fully tested with Secure Renegotiation -- Allows up to 4096bit DHE at TLS Key Exchange layer -- Handles non standard SessionID sizes in Hello Messages -- PicoTCP Support -- Sniffer now supports SNI Virtual Hosts -- Sniffer now handles non HTTPS protocols using STARTTLS -- Sniffer can now parse records with multiple messages -- TI-RTOS updates -- Fix for ColdFire optimized fp_digit read only in explicit 32bit case -- ADH Cipher Suite ADH-AES128-SHA for EAP-FAST - -The CyaSSL manual is available at: -http://www.wolfssl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -# CyaSSL Release 3.2.0 (09/10/2014) - -#### Release 3.2.0 CyaSSL has bug fixes and new features including: - -- ChaCha20 and Poly1305 crypto and suites -- Small stack improvements for OCSP, CRL, TLS, DTLS -- NTRU Encrypt and Decrypt benchmarks -- Updated Visual Studio project files -- Updated Keil MDK5 project files -- Fix for DTLS sequence numbers with GCM/CCM -- Updated HashDRBG with more secure struct declaration -- TI-RTOS support and example Code Composer Studio project files -- Ability to get enabled cipher suites, CyaSSL_get_ciphers() -- AES-GCM/CCM/Direct support for Freescale mmCAU and CAU -- Sniffer improvement checking for decrypt key setup -- Support for raw ECC key import -- Ability to convert ecc_key to DER, EccKeyToDer() -- Security fix for RSA Padding check vulnerability reported by Intel Security - Advanced Threat Research team - -The CyaSSL manual is available at: -http://www.wolfssl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -# CyaSSL Release 3.1.0 (07/14/2014) - -#### Release 3.1.0 CyaSSL has bug fixes and new features including: - -- Fix for older versions of icc without 128-bit type -- Intel ASM syntax for AES-NI -- Updated NTRU support, keygen benchmark -- FIPS check for minimum required HMAC key length -- Small stack (--enable-smallstack) improvements for PKCS#7, ASN -- TLS extension support for DTLS -- Default I/O callbacks external to user -- Updated example client with bad clock test -- Ability to set optional ECC context info -- Ability to enable/disable DH separate from opensslextra -- Additional test key/cert buffers for CA and server -- Updated example certificates - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -# CyaSSL Release 3.0.2 (05/30/2014) - -#### Release 3.0.2 CyaSSL has bug fixes and new features including: - -- Added the following cipher suites: - * TLS_PSK_WITH_AES_128_GCM_SHA256 - * TLS_PSK_WITH_AES_256_GCM_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA384 - * TLS_PSK_WITH_NULL_SHA384 - * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 - * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_NULL_SHA256 - * TLS_DHE_PSK_WITH_NULL_SHA384 - * TLS_DHE_PSK_WITH_AES_128_CCM - * TLS_DHE_PSK_WITH_AES_256_CCM -- Added AES-NI support for Microsoft Visual Studio builds. -- Changed small stack build to be disabled by default. -- Updated the Hash DRBG and provided a configure option to enable. - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -# CyaSSL Release 3.0.0 (04/29/2014) - -#### Release 3.0.0 CyaSSL has bug fixes and new features including: - -- FIPS release candidate -- X.509 improvements that address items reported by Suman Jana with security - researchers at UT Austin and UC Davis -- Small stack size improvements, --enable-smallstack. Offloads large local - variables to the heap. (Note this is not complete.) -- Updated AES-CCM-8 cipher suites to use approved suite numbers. - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -# CyaSSL Release 2.9.4 (04/09/2014) - -#### Release 2.9.4 CyaSSL has bug fixes and new features including: - -- Security fixes that address items reported by Ivan Fratric of the Google - Security Team -- X.509 Unknown critical extensions treated as errors, report by Suman Jana with - security researchers at UT Austin and UC Davis -- Sniffer fixes for corrupted packet length and Jumbo frames -- ARM thumb mode assembly fixes -- Xcode 5.1 support including new clang -- PIC32 MZ hardware support -- CyaSSL Object has enough room to read the Record Header now w/o allocs -- FIPS wrappers for AES, 3DES, SHA1, SHA256, SHA384, HMAC, and RSA. -- A sample I/O pool is demonstrated with --enable-iopool to overtake memory - handling and reduce memory fragmentation on I/O large sizes - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -# CyaSSL Release 2.9.0 (02/07/2014) - -#### Release 2.9.0 CyaSSL has bug fixes and new features including: -- Freescale Kinetis RNGB support -- Freescale Kinetis mmCAU support -- TLS Hello extensions - - ECC - - Secure Renegotiation (null) - - Truncated HMAC -- SCEP support - - PKCS #7 Enveloped data and signed data - - PKCS #10 Certificate Signing Request generation -- DTLS sliding window -- OCSP Improvements - - API change to integrate into Certificate Manager - - IPv4/IPv6 agnostic - - example client/server support for OCSP - - OCSP nonces are optional -- GMAC hashing -- Windows build additions -- Windows CYGWIN build fixes -- Updated test certificates -- Microchip MPLAB Harmony support -- Update autoconf scripts -- Additional X.509 inspection functions -- ECC encrypt/decrypt primitives -- ECC Certificate generation - -The Freescale Kinetis K53 RNGB documentation can be found in Chapter 33 of the -K53 Sub-Family Reference Manual: -http://cache.freescale.com/files/32bit/doc/ref_manual/K53P144M100SF2RM.pdf - -Freescale Kinetis K60 mmCAU (AES, DES, 3DES, MD5, SHA, SHA256) documentation -can be found in the "ColdFire/ColdFire+ CAU and Kinetis mmCAU Software Library -User Guide": -http://cache.freescale.com/files/32bit/doc/user_guide/CAUAPIUG.pdf - - -# CyaSSL Release 2.8.0 (8/30/2013) - -#### Release 2.8.0 CyaSSL has bug fixes and new features including: -- AES-GCM and AES-CCM use AES-NI -- NetX default IO callback handlers -- IPv6 fixes for DTLS Hello Cookies -- The ability to unload Certs/Keys after the handshake, CyaSSL_UnloadCertsKeys() -- SEP certificate extensions -- Callback getters for easier resource freeing -- External CYASSL_MAX_ERROR_SZ for correct error buffer sizing -- MacEncrypt and DecryptVerify Callbacks for User Atomic Record Layer Processing -- Public Key Callbacks for ECC and RSA -- Client now sends blank cert upon request if doesn't have one with TLS <= 1.2 - - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -# CyaSSL Release 2.7.0 (6/17/2013) - -#### Release 2.7.0 CyaSSL has bug fixes and new features including: -- SNI support for client and server -- KEIL MDK-ARM projects -- Wildcard check to domain name match, and Subject altnames are checked too -- Better error messages for certificate verification errors -- Ability to discard session during handshake verify -- More consistent error returns across all APIs -- Ability to unload CAs at the CTX or CertManager level -- Authority subject id support for Certificate matching -- Persistent session cache functionality -- Persistent CA cache functionality -- Client session table lookups to push serverID table to library level -- Camellia support to sniffer -- User controllable settings for DTLS timeout values -- Sniffer fixes for caching long lived sessions -- DTLS reliability enhancements for the handshake -- Better ThreadX support - -When compiling with Mingw, libtool may give the following warning due to -path conversion errors: - -``` -libtool: link: Could not determine host file name corresponding to ** -libtool: link: Continuing, but uninstalled executables may not work. -``` - -If so, examples and testsuite will have problems when run, showing an -error while loading shared libraries. To resolve, please run "make install". - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -# CyaSSL Release 2.6.0 (04/15/2013) - -#### Release 2.6.0 CyaSSL has bug fixes and new features including: -- DTLS 1.2 support including AEAD ciphers -- SHA-3 finalist Blake2 support, it's fast and uses little resources -- SHA-384 cipher suites including ECC ones -- HMAC now supports SHA-512 -- Track memory use for example client/server with -t option -- Better IPv6 examples with --enable-ipv6, before if ipv6 examples/tests were - turned on, localhost only was used. Now link-local (with scope ids) and ipv6 - hosts can be used as well. -- Xcode v4.6 project for iOS v6.1 update -- settings.h is now checked in all *.c files for true one file setting detection -- Better alignment at SSL layer for hardware crypto alignment needs - * Note, SSL itself isn't friendly to alignment with 5 byte TLS headers and - 13 bytes DTLS headers, but every effort is now made to align with the - CYASSL_GENERAL_ALIGNMENT flag which sets desired alignment requirement -- NO_64BIT flag to turn off 64bit data type accumulators in public key code - * Note, some systems are faster with 32bit accumulators -- --enable-stacksize for example client/server stack use - * Note, modern desktop Operating Systems may add bytes to each stack frame -- Updated compression/decompression with direct crypto access -- All ./configure options are now lowercase only for consistency -- ./configure builds default to fastmath option - * Note, if on ia32 and building in shared mode this may produce a problem - with a missing register being available because of PIC, there are at least - 5 solutions to this: - 1) --disable-fastmath , don't use fastmath - 2) --disable-shared, don't build a shared library - 3) C_EXTRA_FLAGS=-DTFM_NO_ASM , turn off assembly use - 4) use clang, it just seems to work - 5) play around with no PIC options to force all registers being open -- Many new ./configure switches for option enable/disable for example - * rsa - * dh - * dsa - * md5 - * sha - * arc4 - * null (allow NULL ciphers) - * oldtls (only use TLS 1.2) - * asn (no certs or public keys allowed) -- ./configure generates cyassl/options.h which allows a header the user can - include in their app to make sure the same options are set at the app and - CyaSSL level. -- autoconf no longer needs serial-tests which lowers version requirements of - automake to 1.11 and autoconf to 2.63 - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -# CyaSSL Release 2.5.0 (02/04/2013) - -#### Release 2.5.0 CyaSSL has bug fixes and new features including: -- Fix for TLS CBC padding timing attack identified by Nadhem Alfardan and - Kenny Paterson: http://www.isg.rhul.ac.uk/tls/ -- Microchip PIC32 (MIPS16, MIPS32) support -- Microchip MPLAB X example projects for PIC32 Ethernet Starter Kit -- Updated CTaoCrypt benchmark app for embedded systems -- 1024-bit test certs/keys and cert/key buffers -- AES-CCM-8 crypto and cipher suites -- Camellia crypto and cipher suites -- Bumped minimum autoconf version to 2.65, automake version to 1.12 -- Addition of OCSP callbacks -- STM32F2 support with hardware crypto and RNG -- Cavium NITROX support - -CTaoCrypt now has support for the Microchip PIC32 and has been tested with -the Microchip PIC32 Ethernet Starter Kit, the XC32 compiler and -MPLAB X IDE in both MIPS16 and MIPS32 instruction set modes. See the README -located under the /mplabx directory for more details. - -To add Cavium NITROX support do: - -./configure --with-cavium=/home/user/cavium/software - -pointing to your licensed cavium/software directory. Since Cavium doesn't -build a library we pull in the cavium_common.o file which gives a libtool -warning about the portability of this. Also, if you're using the github source -tree you'll need to remove the -Wredundant-decls warning from the generated -Makefile because the cavium headers don't conform to this warning. Currently -CyaSSL supports Cavium RNG, AES, 3DES, RC4, HMAC, and RSA directly at the crypto -layer. Support at the SSL level is partial and currently just does AES, 3DES, -and RC4. RSA and HMAC are slower until the Cavium calls can be utilized in non -blocking mode. The example client turns on cavium support as does the crypto -test and benchmark. Please see the HAVE_CAVIUM define. - -CyaSSL is able to use the STM32F2 hardware-based cryptography and random number -generator through the STM32F2 Standard Peripheral Library. For necessary -defines, see the CYASSL_STM32F2 define in settings.h. Documentation for the -STM32F2 Standard Peripheral Library can be found in the following document: -http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/USER_MANUAL/DM00023896.pdf - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -# CyaSSL Release 2.4.6 (12/20/2012) - -#### Release 2.4.6 CyaSSL has bug fixes and a few new features including: -- ECC into main version -- Lean PSK build (reduced code size, RAM usage, and stack usage) -- FreeBSD CRL monitor support -- CyaSSL_peek() -- CyaSSL_send() and CyaSSL_recv() for I/O flag setting -- CodeWarrior Support -- MQX Support -- Freescale Kinetis support including Hardware RNG -- autoconf builds use jobserver -- cyassl-config -- Sniffer memory reductions - -Thanks to Brian Aker for the improved autoconf system, make rpm, cyassl-config, -warning system, and general good ideas for improving CyaSSL! - -The Freescale Kinetis K70 RNGA documentation can be found in Chapter 37 of the -K70 Sub-Family Reference Manual: -http://cache.freescale.com/files/microcontrollers/doc/ref_manual/K70P256M150SF3RM.pdf - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - -# CyaSSL Release 2.4.0 (10/10/2012) - -#### Release 2.4.0 CyaSSL has bug fixes and a few new features including: -- DTLS reliability -- Reduced memory usage after handshake -- Updated build process - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -# CyaSSL Release 2.3.0 (8/10/2012) - -#### Release 2.3.0 CyaSSL has bug fixes and a few new features including: -- AES-GCM crypto and cipher suites -- make test cipher suite checks -- Subject AltName processing -- Command line support for client/server examples -- Sniffer SessionTicket support -- SHA-384 cipher suites -- Verify cipher suite validity when user overrides -- CRL dir monitoring -- DTLS Cookie support, reliability coming soon - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -# CyaSSL Release 2.2.0 (5/18/2012) - -#### Release 2.2.0 CyaSSL has bug fixes and a few new features including: -- Initial CRL support (--enable-crl) -- Initial OCSP support (--enable-ocsp) -- Add static ECDH suites -- SHA-384 support -- ECC client certificate support -- Add medium session cache size (1055 sessions) -- Updated unit tests -- Protection against mutex reinitialization - - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -# CyaSSL Release 2.0.8 (2/24/2012) - -#### Release 2.0.8 CyaSSL has bug fixes and a few new features including: -- A fix for malicious certificates pointed out by Remi Gacogne (thanks) - resulting in NULL pointer use. -- Respond to renegotiation attempt with no_renegoatation alert -- Add basic path support for load_verify_locations() -- Add set Temp EC-DHE key size -- Extra checks on rsa test when porting into - - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -# CyaSSL Release 2.0.6 (1/27/2012) - -#### Release 2.0.6 CyaSSL has bug fixes and a few new features including: -- Fixes for CA basis constraint check -- CTX reference counting -- Initial unit test additions -- Lean and Mean Windows fix -- ECC benchmarking -- SSMTP build support -- Ability to group handshake messages with set_group_messages(ctx/ssl) -- CA cache addition callback -- Export Base64_Encode for general use - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -# CyaSSL Release 2.0.2 (12/05/2011) - -#### Release 2.0.2 CyaSSL has bug fixes and a few new features including: -- CTaoCrypt Runtime library detection settings when directly using the crypto - library -- Default certificate generation now uses SHAwRSA and adds SHA256wRSA generation -- All test certificates now use 2048bit and SHA-1 for better modern browser - support -- Direct AES block access and AES-CTR (counter) mode -- Microchip pic32 support - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - - - -# CyaSSL Release 2.0.0rc3 (9/28/2011) - -#### Release 2.0.0rc3 for CyaSSL has bug fixes and a few new features including: -- updated autoconf support -- better make install and uninstall (uses system directories) -- make test / make check -- CyaSSL headers now in -- CTaocrypt headers now in -- OpenSSL compatibility headers now in -- examples and tests all run from home directory so can use certs in ./certs - (see note 1) - -So previous applications that used the OpenSSL compatibility header - now need to include instead, no other -changes are required. - -Special Thanks to Brian Aker for his autoconf, install, and header patches. - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - -# CyaSSL Release 2.0.0rc2 (6/6/2011) - -#### Release 2.0.0rc2 for CyaSSL has bug fixes and a few new features including: -- bug fixes (Alerts, DTLS with DHE) -- FreeRTOS support -- lwIP support -- Wshadow warnings removed -- asn public header -- CTaoCrypt public headers now all have ctc_ prefix (the manual is still being - updated to reflect this change) -- and more. - -This is the 2nd and perhaps final release candidate for version 2. -Please send any comments or questions to support@yassl.com. - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - -# CyaSSL Release 2.0.0rc1 (5/2/2011) - -#### Release 2.0.0rc1 for CyaSSL has many new features including: -- bug fixes -- SHA-256 cipher suites -- Root Certificate Verification (instead of needing all certs in the chain) -- PKCS #8 private key encryption (supports PKCS #5 v1-v2 and PKCS #12) -- Serial number retrieval for x509 -- PBKDF2 and PKCS #12 PBKDF -- UID parsing for x509 -- SHA-256 certificate signatures -- Client and server can send chains (SSL_CTX_use_certificate_chain_file) -- CA loading can now parse multiple certificates per file -- Dynamic memory runtime hooks -- Runtime hooks for logging -- EDH on server side -- More informative error codes -- More informative logging messages -- Version downgrade more robust (use SSL_v23*) -- Shared build only by default through ./configure -- Compiler visibility is now used, internal functions not polluting namespace -- Single Makefile, no recursion, for faster and simpler building -- Turn on all warnings possible build option, warning fixes -- and more. - -Because of all the new features and the multiple OS, compiler, feature-set -options that CyaSSL allows, there may be some configuration fixes needed. -Please send any comments or questions to support@yassl.com. - -The CyaSSL manual is available at: -http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions -and comments about the new features please check the manual. - -# CyaSSL Release 1.9.0 (3/2/2011) - -Release 1.9.0 for CyaSSL adds bug fixes, improved TLSv1.2 through testing and -better hash/sig algo ids, --enable-webServer for the yaSSL embedded web server, -improper AES key setup detection, user cert verify callback improvements, and -more. - -The CyaSSL manual offering is included in the doc/ directory. For build -instructions and comments about the new features please check the manual. - -Please send any comments or questions to support@yassl.com. - -# CyaSSL Release 1.8.0 (12/23/2010) - -Release 1.8.0 for CyaSSL adds bug fixes, x509 v3 CA signed certificate -generation, a C standard library abstraction layer, lower memory use, increased -portability through the os_settings.h file, and the ability to use NTRU cipher -suites when used in conjunction with an NTRU license and library. - -The initial CyaSSL manual offering is included in the doc/ directory. For -build instructions and comments about the new features please check the manual. - -Please send any comments or questions to support@yassl.com. - -Happy Holidays. - - -# CyaSSL Release 1.6.5 (9/9/2010) - -Release 1.6.5 for CyaSSL adds bug fixes and x509 v3 self signed certificate -generation. - -For general build instructions see doc/Building_CyaSSL.pdf. - -To enable certificate generation support add this option to ./configure -./configure --enable-certgen - -An example is included in ctaocrypt/test/test.c and documentation is provided -in doc/CyaSSL_Extensions_Reference.pdf item 11. - -# CyaSSL Release 1.6.0 (8/27/2010) - -Release 1.6.0 for CyaSSL adds bug fixes, RIPEMD-160, SHA-512, and RSA key -generation. - -For general build instructions see doc/Building_CyaSSL.pdf. - -To add RIPEMD-160 support add this option to ./configure -./configure --enable-ripemd - -To add SHA-512 support add this option to ./configure -./configure --enable-sha512 - -To add RSA key generation support add this option to ./configure -./configure --enable-keygen - -Please see ctaocrypt/test/test.c for examples and usage. - -For Windows, RIPEMD-160 and SHA-512 are enabled by default but key generation is -off by default. To turn key generation on add the define CYASSL_KEY_GEN to -CyaSSL. - - -# CyaSSL Release 1.5.6 (7/28/2010) - -Release 1.5.6 for CyaSSL adds bug fixes, compatibility for our JSSE provider, -and a fix for GCC builds on some systems. - -For general build instructions see doc/Building_CyaSSL.pdf. - -To add AES-NI support add this option to ./configure -./configure --enable-aesni - -You'll need GCC 4.4.3 or later to make use of the assembly. - -# CyaSSL Release 1.5.4 (7/7/2010) - -Release 1.5.4 for CyaSSL adds bug fixes, support for AES-NI, SHA1 speed -improvements from loop unrolling, and support for the Mongoose Web Server. - -For general build instructions see doc/Building_CyaSSL.pdf. - -To add AES-NI support add this option to ./configure -./configure --enable-aesni - -You'll need GCC 4.4.3 or later to make use of the assembly. - -# CyaSSL Release 1.5.0 (5/11/2010) - -Release 1.5.0 for CyaSSL adds bug fixes, GoAhead WebServer support, sniffer -support, and initial swig interface support. - -For general build instructions see doc/Building_CyaSSL.pdf. - -To add support for GoAhead WebServer either --enable-opensslExtra or if you -don't want all the features of opensslExtra you can just define GOAHEAD_WS -instead. GOAHEAD_WS can be added to ./configure with CFLAGS=-DGOAHEAD_WS or -you can define it yourself. - -To look at the sniffer support please see the sniffertest app in -sslSniffer/sslSnifferTest. Build with --enable-sniffer on *nix or use the -vcproj files on windows. You'll need to have pcap installed on *nix and -WinPcap on windows. - -A swig interface file is now located in the swig directory for using Python, -Java, Perl, and others with CyaSSL. This is initial support and experimental, -please send questions or comments to support@yassl.com. - -When doing load testing with CyaSSL, on the echoserver example say, the client -machine may run out of tcp ephemeral ports, they will end up in the TIME_WAIT -queue, and can't be reused by default. There are generally two ways to fix -this. - -1. Reduce the length sockets remain on the TIME_WAIT queue OR -2. Allow items on the TIME_WAIT queue to be reused. - - -To reduce the TIME_WAIT length in OS X to 3 seconds (3000 milliseconds) - -`sudo sysctl -w net.inet.tcp.msl=3000` - -In Linux - -`sudo sysctl -w net.ipv4.tcp_tw_reuse=1` - -allows reuse of sockets in TIME_WAIT - -`sudo sysctl -w net.ipv4.tcp_tw_recycle=1` - -works but seems to remove sockets from TIME_WAIT entirely? - -`sudo sysctl -w net.ipv4.tcp_fin_timeout=1` - -doen't control TIME_WAIT, it controls FIN_WAIT(2) contrary to some posts - - -# CyaSSL Release 1.4.0 (2/18/2010) - -Release 1.3.0 for CyaSSL adds bug fixes, better multi TLS/SSL version support -through SSLv23_server_method(), and improved documentation in the doc/ folder. - -For general build instructions doc/Building_CyaSSL.pdf. - -# CyaSSL Release 1.3.0 (1/21/2010) - -Release 1.3.0 for CyaSSL adds bug fixes, a potential security problem fix, -better porting support, removal of assert()s, and a complete THREADX port. - -For general build instructions see rc1 below. - -# CyaSSL Release 1.2.0 (11/2/2009) - -Release 1.2.0 for CyaSSL adds bug fixes and session negotiation if first use is -read or write. - -For general build instructions see rc1 below. - -# CyaSSL Release 1.1.0 (9/2/2009) - -Release 1.1.0 for CyaSSL adds bug fixes, a check against malicious session -cache use, support for lighttpd, and TLS 1.2. - -To get TLS 1.2 support please use the client and server functions: - -```c -SSL_METHOD *TLSv1_2_server_method(void); -SSL_METHOD *TLSv1_2_client_method(void); -``` - -CyaSSL was tested against lighttpd 1.4.23. To build CyaSSL for use with -lighttpd use the following commands from the CyaSSL install dir : - -``` -./configure --disable-shared --enable-opensslExtra --enable-fastmath --without-zlib - -make -make openssl-links -``` - -Then to build lighttpd with CyaSSL use the following commands from the -lighttpd install dir: - -``` -./configure --with-openssl --with-openssl-includes=/include --with-openssl-libs=/lib LDFLAGS=-lm - -make -``` - -On some systems you may get a linker error about a duplicate symbol for -MD5_Init or other MD5 calls. This seems to be caused by the lighttpd src file -md5.c, which defines MD5_Init(), and is included in liblightcomp_la-md5.o. -When liblightcomp is linked with the SSL_LIBs the linker may complain about -the duplicate symbol. This can be fixed by editing the lighttpd src file md5.c -and adding this line to the beginning of the file: - -\#if 0 - -and this line to the end of the file - -\#endif - -Then from the lighttpd src dir do a: - -``` -make clean -make -``` - -If you get link errors about undefined symbols more than likely the actual -OpenSSL libraries are found by the linker before the CyaSSL openssl-links that -point to the CyaSSL library, causing the linker confusion. This can be fixed -by editing the Makefile in the lighttpd src directory and changing the line: - -`SSL_LIB = -lssl -lcrypto` - -to - -`SSL_LIB = -lcyassl` - -Then from the lighttpd src dir do a: - -``` -make clean -make -``` - -This should remove any confusion the linker may be having with missing symbols. - -For any questions or concerns please contact support@yassl.com . - -For general build instructions see rc1 below. - -# CyaSSL Release 1.0.6 (8/03/2009) - -Release 1.0.6 for CyaSSL adds bug fixes, an improved session cache, and faster -math with a huge code option. - -The session cache now defaults to a client mode, also good for embedded servers. -For servers not under heavy load (less than 200 new sessions per minute), define -BIG_SESSION_CACHE. If the server will be under heavy load, define -HUGE_SESSION_CACHE. - -There is now a fasthugemath option for configure. This enables fastmath plus -even faster math by greatly increasing the code size of the math library. Use -the benchmark utility to compare public key operations. - - -For general build instructions see rc1 below. - -# CyaSSL Release 1.0.3 (5/10/2009) - -Release 1.0.3 for CyaSSL adds bug fixes and add increased support for OpenSSL -compatibility when building other applications. - -Release 1.0.3 includes an alpha release of DTLS for both client and servers. -This is only for testing purposes at this time. Rebroadcast and reordering -aren't fully implemented at this time but will be for the next release. - -For general build instructions see rc1 below. - -# CyaSSL Release 1.0.2 (4/3/2009) - -Release 1.0.2 for CyaSSL adds bug fixes for a couple I/O issues. Some systems -will send a SIGPIPE on socket recv() at any time and this should be handled by -the application by turning off SIGPIPE through setsockopt() or returning from -the handler. - -Release 1.0.2 includes an alpha release of DTLS for both client and servers. -This is only for testing purposes at this time. Rebroadcast and reordering -aren't fully implemented at this time but will be for the next release. - -For general build instructions see rc1 below. - -## CyaSSL Release Candidiate 3 rc3-1.0.0 (2/25/2009) - - -Release Candidate 3 for CyaSSL 1.0.0 adds bug fixes and adds a project file for -iPhone development with Xcode. cyassl-iphone.xcodeproj is located in the root -directory. This release also includes a fix for supporting other -implementations that bundle multiple messages at the record layer, this was -lost when cyassl i/o was re-implemented but is now fixed. - -For general build instructions see rc1 below. - -## CyaSSL Release Candidiate 2 rc2-1.0.0 (1/21/2009) - - -Release Candidate 2 for CyaSSL 1.0.0 adds bug fixes and adds two new stream -ciphers along with their respective cipher suites. CyaSSL adds support for -HC-128 and RABBIT stream ciphers. The new suites are: - -``` -TLS_RSA_WITH_HC_128_SHA -TLS_RSA_WITH_RABBIT_SHA -``` - -And the corresponding cipher names are - -``` -HC128-SHA -RABBIT-SHA -``` - -CyaSSL also adds support for building with devkitPro for PPC by changing the -library proper to use libogc. The examples haven't been changed yet but if -there's interest they can be. Here's an example ./configure to build CyaSSL -for devkitPro: - -``` -./configure --disable-shared CC=/pathTo/devkitpro/devkitPPC/bin/powerpc-gekko-gcc --host=ppc --without-zlib --enable-singleThreaded RANLIB=/pathTo/devkitpro/devkitPPC/bin/powerpc-gekko-ranlib CFLAGS="-DDEVKITPRO -DGEKKO" -``` - -For linking purposes you'll need - -`LDFLAGS="-g -mrvl -mcpu=750 -meabi -mhard-float -Wl,-Map,$(notdir $@).map"` - -For general build instructions see rc1 below. - - -## CyaSSL Release Candidiate 1 rc1-1.0.0 (12/17/2008) - - -Release Candidate 1 for CyaSSL 1.0.0 contains major internal changes. Several -areas have optimization improvements, less dynamic memory use, and the I/O -strategy has been refactored to allow alternate I/O handling or Library use. -Many thanks to Thierry Fournier for providing these ideas and most of the work. - -Because of these changes, this release is only a candidate since some problems -are probably inevitable on some platform with some I/O use. Please report any -problems and we'll try to resolve them as soon as possible. You can contact us -at support@yassl.com or todd@yassl.com. - -Using TomsFastMath by passing --enable-fastmath to ./configure now uses assembly -on some platforms. This is new so please report any problems as every compiler, -mode, OS combination hasn't been tested. On ia32 all of the registers need to -be available so be sure to pass these options to CFLAGS: - -`CFLAGS="-O3 -fomit-frame-pointer"` - -OS X will also need -mdynamic-no-pic added to CFLAGS - -Also if you're building in shared mode for ia32 you'll need to pass options to -LDFLAGS as well on OS X: - -`LDFLAGS=-Wl,-read_only_relocs,warning` - -This gives warnings for some symbols but seems to work. - - -#### To build on Linux, Solaris, *BSD, Mac OS X, or Cygwin: - - ./configure - make - - from the ./testsuite/ directory run ./testsuite - -#### To make a debug build: - - ./configure --enable-debug --disable-shared - make - - - -#### To build on Win32 - -Choose (Re)Build All from the project workspace - -Run the testsuite program - - - - - -# CyaSSL version 0.9.9 (7/25/2008) - -This release of CyaSSL adds bug fixes, Pre-Shared Keys, over-rideable memory -handling, and optionally TomsFastMath. Thanks to Moisés Guimarães for the -work on TomsFastMath. - -To optionally use TomsFastMath pass --enable-fastmath to ./configure -Or define USE_FAST_MATH in each project from CyaSSL for MSVC. - -Please use the benchmark routine before and after to see the performance -difference, on some platforms the gains will be little but RSA encryption -always seems to be faster. On x86-64 machines with GCC the normal math library -may outperform the fast one when using CFLAGS=-m64 because TomsFastMath can't -yet use -m64 because of GCCs inability to do 128bit division. - - *** UPDATE GCC 4.2.1 can now do 128bit division *** - -See notes below (0.2.0) for complete build instructions. - - -# CyaSSL version 0.9.8 (5/7/2008) - -This release of CyaSSL adds bug fixes, client side Diffie-Hellman, and better -socket handling. - -See notes below (0.2.0) for complete build instructions. - - -# CyaSSL version 0.9.6 (1/31/2008) - -This release of CyaSSL adds bug fixes, increased session management, and a fix -for gnutls. - -See notes below (0.2.0) for complete build instructions. - - -# CyaSSL version 0.9.0 (10/15/2007) - -This release of CyaSSL adds bug fixes, MSVC 2005 support, GCC 4.2 support, -IPV6 support and test, and new test certificates. - -See notes below (0.2.0) for complete build instructions. - - -# CyaSSL version 0.8.0 (1/10/2007) - -This release of CyaSSL adds increased socket support, for non-blocking writes, -connects, and interrupted system calls. - -See notes below (0.2.0) for complete build instructions. - - -# CyaSSL version 0.6.3 (10/30/2006) - -This release of CyaSSL adds debug logging to stderr to aid in the debugging of -CyaSSL on systems that may not provide the best support. - -If CyaSSL is built with debugging support then you need to call -CyaSSL_Debugging_ON() to turn logging on. - -On Unix use ./configure --enable-debug - -On Windows define DEBUG_CYASSL when building CyaSSL - - -To turn logging back off call CyaSSL_Debugging_OFF() - -See notes below (0.2.0) for complete build instructions. - - -# CyaSSL version 0.6.2 (10/29/2006) - -This release of CyaSSL adds TLS 1.1. - -Note that CyaSSL has certificate verification on by default, unlike OpenSSL. -To emulate OpenSSL behavior, you must call SSL_CTX_set_verify() with -SSL_VERIFY_NONE. In order to have full security you should never do this, -provide CyaSSL with the proper certificates to eliminate impostors and call -CyaSSL_check_domain_name() to prevent man in the middle attacks. - -See notes below (0.2.0) for build instructions. - -# CyaSSL version 0.6.0 (10/25/2006) - -This release of CyaSSL adds more SSL functions, better autoconf, nonblocking -I/O for accept, connect, and read. There is now an --enable-small configure -option that turns off TLS, AES, DES3, HMAC, and ERROR_STRINGS, see configure.in -for the defines. Note that TLS requires HMAC and AES requires TLS. - -See notes below (0.2.0) for build instructions. - - -# CyaSSL version 0.5.5 (09/27/2006) - -This mini release of CyaSSL adds better input processing through buffered input -and big message support. Added SSL_pending() and some sanity checks on user -settings. - -See notes below (0.2.0) for build instructions. - - -# CyaSSL version 0.5.0 (03/27/2006) - -This release of CyaSSL adds AES support and minor bug fixes. - -See notes below (0.2.0) for build instructions. - - -# CyaSSL version 0.4.0 (03/15/2006) - -This release of CyaSSL adds TLSv1 client/server support and libtool. - -See notes below for build instructions. - - -# CyaSSL version 0.3.0 (02/26/2006) - -This release of CyaSSL adds SSLv3 server support and session resumption. - -See notes below for build instructions. - - -# CyaSSL version 0.2.0 (02/19/2006) - - -This is the first release of CyaSSL and its crypt brother, CTaoCrypt. CyaSSL -is written in ANSI C with the idea of a small code size, footprint, and memory -usage in mind. CTaoCrypt can be as small as 32K, and the current client -version of CyaSSL can be as small as 12K. - - -The first release of CTaoCrypt supports MD5, SHA-1, 3DES, ARC4, Big Integer -Support, RSA, ASN parsing, and basic x509 (en/de)coding. - -The first release of CyaSSL supports normal client RSA mode SSLv3 connections -with support for SHA-1 and MD5 digests. Ciphers include 3DES and RC4. - - -#### To build on Linux, Solaris, *BSD, Mac OS X, or Cygwin: - - ./configure - make - - from the ./testsuite/ directory run ./testsuite - -#### to make a debug build: - - ./configure --enable-debug --disable-shared - make - - - -#### To build on Win32 - -Choose (Re)Build All from the project workspace - -Run the testsuite program - - - -*** The next release of CyaSSL will support a server and more OpenSSL -compatibility functions. - - -Please send questions or comments to todd@yassl.com +[wolfSSL Vulnerabilities] +(https://www.wolfssl.com/docs/security-vulnerabilities/) diff --git a/FreeRTOS-Plus/Source/WolfSSL/ReadMeFirst.url b/FreeRTOS-Plus/Source/WolfSSL/ReadMeFirst.url deleted file mode 100644 index 19432f5a1..000000000 --- a/FreeRTOS-Plus/Source/WolfSSL/ReadMeFirst.url +++ /dev/null @@ -1,5 +0,0 @@ -[InternetShortcut] -URL=http://www.freertos.org/ssl -IDList= -[{000214A0-0000-0000-C000-000000000046}] -Prop3=19,2 diff --git a/FreeRTOS-Plus/Source/WolfSSL/aclocal.m4 b/FreeRTOS-Plus/Source/WolfSSL/aclocal.m4 index 64fd2c65b..538172dd9 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/aclocal.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.14.1 -*- Autoconf -*- +# generated automatically by aclocal 1.16.2 -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -20,7 +20,7 @@ You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -# Copyright (C) 2002-2013 Free Software Foundation, Inc. +# Copyright (C) 2002-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -32,10 +32,10 @@ To do so, use the procedure documented by the package, typically 'autoreconf'.]) # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.14' +[am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.14.1], [], +m4_if([$1], [1.16.2], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -51,14 +51,14 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.14.1])dnl +[AM_AUTOMAKE_VERSION([1.16.2])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # Figure out how to run the assembler. -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -78,7 +78,7 @@ _AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -123,15 +123,14 @@ _AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], -[dnl Rely on autoconf to set up CDPATH properly. -AC_PREREQ([2.50])dnl -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2013 Free Software Foundation, Inc. +# Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -162,7 +161,7 @@ AC_CONFIG_COMMANDS_PRE( Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -353,13 +352,12 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. - # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], @@ -367,49 +365,43 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? done + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE="gmake" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS @@ -418,18 +410,17 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each '.P' file that we will -# need in order to bootstrap the dependency handling code. +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll need in +# order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -516,11 +507,11 @@ AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: -# -# +# +# AC_SUBST([mkdir_p], ['$(MKDIR_P)']) -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl @@ -584,7 +575,7 @@ END Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . +that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM @@ -593,7 +584,11 @@ to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi -fi]) +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further @@ -622,7 +617,7 @@ for _am_header in $config_headers :; do done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -633,7 +628,7 @@ echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_co # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -643,7 +638,7 @@ if test x"${install_sh}" != xset; then fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2013 Free Software Foundation, Inc. +# Copyright (C) 2003-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -664,7 +659,7 @@ AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -672,49 +667,42 @@ AC_SUBST([am__leading_dot])]) # AM_MAKE_INCLUDE() # ----------------- -# Check to see how make treats includes. +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .PHONY: am__doit END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2013 Free Software Foundation, Inc. +# Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -753,7 +741,7 @@ fi # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -782,7 +770,7 @@ AC_DEFUN([_AM_SET_OPTIONS], AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -829,7 +817,7 @@ AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -848,7 +836,7 @@ AC_DEFUN([AM_RUN_LOG], # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -929,7 +917,7 @@ AC_CONFIG_COMMANDS_PRE( rm -f conftest.file ]) -# Copyright (C) 2009-2013 Free Software Foundation, Inc. +# Copyright (C) 2009-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -989,7 +977,7 @@ AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1017,7 +1005,7 @@ fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2013 Free Software Foundation, Inc. +# Copyright (C) 2006-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1036,7 +1024,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2013 Free Software Foundation, Inc. +# Copyright (C) 2004-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1182,6 +1170,7 @@ m4_include([m4/ax_file_escapes.m4]) m4_include([m4/ax_harden_compiler_flags.m4]) m4_include([m4/ax_print_to_file.m4]) m4_include([m4/ax_pthread.m4]) +m4_include([m4/ax_require_defined.m4]) m4_include([m4/ax_tls.m4]) m4_include([m4/ax_vcs_checkout.m4]) m4_include([m4/hexversion.m4]) @@ -1192,4 +1181,3 @@ m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) m4_include([m4/visibility.m4]) -m4_include([m4/wolfssl_darwin_clang.m4]) diff --git a/FreeRTOS-Plus/Source/WolfSSL/build-aux/compile b/FreeRTOS-Plus/Source/WolfSSL/build-aux/compile index 531136b06..23fcba011 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/build-aux/compile +++ b/FreeRTOS-Plus/Source/WolfSSL/build-aux/compile @@ -1,9 +1,9 @@ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. -scriptversion=2012-10-14.11; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ scriptversion=2012-10-14.11; # UTC # 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, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -53,7 +53,7 @@ func_file_conv () MINGW*) file_conv=mingw ;; - CYGWIN*) + CYGWIN* | MSYS*) file_conv=cygwin ;; *) @@ -67,7 +67,7 @@ func_file_conv () mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; - cygwin/*) + cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) @@ -255,7 +255,8 @@ EOF echo "compile $scriptversion" exit $? ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac @@ -339,9 +340,9 @@ exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/FreeRTOS-Plus/Source/WolfSSL/build-aux/config.guess b/FreeRTOS-Plus/Source/WolfSSL/build-aux/config.guess index 9afd67620..45001cfec 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/build-aux/config.guess +++ b/FreeRTOS-Plus/Source/WolfSSL/build-aux/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2013 Free Software Foundation, Inc. +# Copyright 1992-2020 Free Software Foundation, Inc. -timestamp='2013-11-29' +timestamp='2020-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2013-11-29' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -24,12 +24,12 @@ timestamp='2013-11-29' # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # -# Originally written by Per Bothner. +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # -# Please send patches with a ChangeLog entry to config-patches@gnu.org. +# Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` @@ -39,7 +39,7 @@ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2013 Free Software Foundation, Inc. +Copyright 1992-2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -84,8 +84,6 @@ if test $# != 0; then exit 1 fi -trap 'exit 1' 1 2 15 - # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a @@ -96,34 +94,40 @@ trap 'exit 1' 1 2 15 # Portable tmp directory creation inspired by the Autoconf team. -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + # prevent multiple calls if $tmp is already set + test "$tmp" && return 0 + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$driver" + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then +if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi @@ -132,14 +136,14 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -case "${UNAME_SYSTEM}" in +case "$UNAME_SYSTEM" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu - eval $set_cc_for_build - cat <<-EOF > $dummy.c + set_cc_for_build + cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc @@ -149,13 +153,20 @@ Linux|GNU|GNU/*) LIBC=gnu #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi ;; esac # Note: order is significant - the case branches are not exclusive. -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -168,21 +179,31 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build + set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -197,43 +218,72 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in os=netbsd ;; esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in + case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "$machine-${os}${release}${abi-}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" + exit ;; + *:OS108:*:*) + echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Twizzler:*:*) + echo "$UNAME_MACHINE"-unknown-twizzler + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in @@ -251,63 +301,54 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos + echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos + echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition @@ -319,7 +360,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} + echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos @@ -346,38 +387,38 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} + echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" + set_cc_for_build + SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then - SUN_ARCH="x86_64" + SUN_ARCH=x86_64 fi fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in @@ -386,25 +427,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) - echo sparc-sun-sunos${UNAME_RELEASE} + echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} + echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not @@ -415,44 +456,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} + echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} + echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} + echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} + echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} + echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} + echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} + echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} + echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -461,23 +502,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} + echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax @@ -503,17 +544,17 @@ EOF AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] then - echo m88k-dg-dgux${UNAME_RELEASE} + echo m88k-dg-dgux"$UNAME_RELEASE" else - echo m88k-dg-dguxbcs${UNAME_RELEASE} + echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else - echo i586-dg-dgux${UNAME_RELEASE} + echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) @@ -530,7 +571,7 @@ EOF echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id @@ -542,14 +583,14 @@ EOF if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #include main() @@ -560,7 +601,7 @@ EOF exit(0); } EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else @@ -574,26 +615,27 @@ EOF exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx @@ -608,28 +650,28 @@ EOF echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + if [ "$HP_ARCH" = "" ]; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include @@ -662,13 +704,13 @@ EOF exit (0); } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if [ "$HP_ARCH" = hppa2.0w ] then - eval $set_cc_for_build + set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -679,23 +721,23 @@ EOF # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #include int main () @@ -720,11 +762,11 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -733,7 +775,7 @@ EOF *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) @@ -741,9 +783,9 @@ EOF exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk + echo "$UNAME_MACHINE"-unknown-osf1mk else - echo ${UNAME_MACHINE}-unknown-osf1 + echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) @@ -768,130 +810,123 @@ EOF echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} + echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" + exit ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi + else + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf + fi exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in + case "$UNAME_PROCESSOR" in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin + echo "$UNAME_MACHINE"-pc-cygwin exit ;; *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 + echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 + echo "$UNAME_MACHINE"-pc-mingw32 exit ;; - i*:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 + echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) - case ${UNAME_MACHINE} in + case "$UNAME_MACHINE" in x86) - echo i586-pc-interix${UNAME_RELEASE} + echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} + echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) - echo ia64-unknown-interix${UNAME_RELEASE} + echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin + echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin + echo x86_64-pc-cygwin exit ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix + *:Minix:*:*) + echo "$UNAME_MACHINE"-unknown-minix exit ;; aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; @@ -901,129 +936,169 @@ EOF EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) - eval $set_cc_for_build + set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 + sed 's/^ //' << EOF > "$dummy.c" #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el + MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} + MIPS_ENDIAN= #else - CPU= + MIPS_ENDIAN= #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; - or1k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} + echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} + echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} + echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} + echo powerpc-unknown-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} + echo powerpc64le-unknown-linux-"$LIBC" exit ;; ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. @@ -1037,34 +1112,34 @@ EOF # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx + echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop + echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos + echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable + echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} + echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp + echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) @@ -1074,12 +1149,12 @@ EOF *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1089,9 +1164,9 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv32 + echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) @@ -1099,7 +1174,7 @@ EOF # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that + # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; @@ -1111,9 +1186,9 @@ EOF exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) @@ -1133,9 +1208,9 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; @@ -1144,28 +1219,28 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} + echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} + echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} + echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} + echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} + echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 @@ -1176,7 +1251,7 @@ EOF *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 + echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi @@ -1196,23 +1271,23 @@ EOF exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos + echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} + echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv"$UNAME_RELEASE" else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. @@ -1231,77 +1306,94 @@ EOF echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} + echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} + echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} + echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} + echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} + echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} + echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc + UNAME_PROCESSOR=`uname -p` + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build fi - if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then - # Avoid executing cc on OS X 10.9, as it ships with a stub - # that puts up a graphical alert prompting to install - # developer tools. Any system running Mac OS X 10.7 or - # later (Darwin 11 and later) is required to have a 64-bit - # processor. This is not true of the ARM version of Darwin - # that Apple uses in portable devices. - UNAME_PROCESSOR=x86_64 + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} + echo nse-tandem-nsk"$UNAME_RELEASE" exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux @@ -1310,18 +1402,19 @@ EOF echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + # shellcheck disable=SC2154 + if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi - echo ${UNAME_MACHINE}-unknown-plan9 + echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 @@ -1342,14 +1435,14 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in + case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; @@ -1358,24 +1451,39 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos + echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros + echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; + *:Unleashed:*:*) + echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" exit ;; esac -eval $set_cc_for_build -cat >$dummy.c < "$dummy.c" < -# include +#include +#include +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include +#if defined(_SIZE_T_) || defined(SIGLOST) +#include +#endif +#endif #endif main () { @@ -1388,22 +1496,14 @@ main () #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 - "4" + "4" #else - "" + "" #endif - ); exit (0); + ); exit (0); #endif #endif -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" @@ -1443,39 +1543,54 @@ main () #endif #if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); + struct utsname un; + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif +#if !defined (ultrix) +#include +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif #endif #if defined (alliant) && defined (i860) @@ -1486,54 +1601,38 @@ main () } EOF -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. +test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } +echo "$0: unable to guess system type" >&2 -# Convex versions that predate uname can use getsysinfo(1) +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp @@ -1552,16 +1651,16 @@ hostinfo = `(hostinfo) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" EOF exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/FreeRTOS-Plus/Source/WolfSSL/build-aux/config.sub b/FreeRTOS-Plus/Source/WolfSSL/build-aux/config.sub index 61cb4bc22..f02d43ad5 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/build-aux/config.sub +++ b/FreeRTOS-Plus/Source/WolfSSL/build-aux/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2013 Free Software Foundation, Inc. +# Copyright 1992-2020 Free Software Foundation, Inc. -timestamp='2013-10-01' +timestamp='2020-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2013-10-01' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -25,7 +25,7 @@ timestamp='2013-10-01' # of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches with a ChangeLog entry to config-patches@gnu.org. +# Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. @@ -33,7 +33,7 @@ timestamp='2013-10-01' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -53,12 +53,11 @@ timestamp='2013-10-01' me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -68,7 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2013 Free Software Foundation, Inc. +Copyright 1992-2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -90,12 +89,12 @@ while test $# -gt 0 ; do - ) # Use stdin as input. break ;; -* ) - echo "$me: invalid option $1$help" + echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. - echo $1 + echo "$1" exit ;; * ) @@ -111,1211 +110,1164 @@ case $# in exit 1;; esac -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac +# Split fields of configuration type +# shellcheck disable=SC2162 +IFS="-" read field1 field2 field3 field4 <&2 + exit 1 ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 + *-*-*-*) + basic_machine=$field1-$field2 + os=$field3-$field4 ;; - -bluegene*) - os=-cnk + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \ + | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova*) + basic_machine=$field1 + os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + os=linux-android + ;; + *) + basic_machine=$field1-$field2 + os=$field3 + ;; + esac ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 + *-*) + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + os= + ;; + *) + basic_machine=$field1 + os=$field2 + ;; + esac + ;; + esac ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + os=bsd + ;; + a29khif) + basic_machine=a29k-amd + os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=scout + ;; + alliant) + basic_machine=fx80-alliant + os= + ;; + altos | altos3068) + basic_machine=m68k-altos + os= + ;; + am29k) + basic_machine=a29k-none + os=bsd + ;; + amdahl) + basic_machine=580-amdahl + os=sysv + ;; + amiga) + basic_machine=m68k-unknown + os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=bsd + ;; + aros) + basic_machine=i386-pc + os=aros + ;; + aux) + basic_machine=m68k-apple + os=aux + ;; + balance) + basic_machine=ns32k-sequent + os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=linux + ;; + cegcc) + basic_machine=arm-unknown + os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=bsd + ;; + convex-c2) + basic_machine=c2-convex + os=bsd + ;; + convex-c32) + basic_machine=c32-convex + os=bsd + ;; + convex-c34) + basic_machine=c34-convex + os=bsd + ;; + convex-c38) + basic_machine=c38-convex + os=bsd + ;; + cray) + basic_machine=j90-cray + os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + os= + ;; + da30) + basic_machine=m68k-da30 + os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + os= + ;; + delta88) + basic_machine=m88k-motorola + os=sysv3 + ;; + dicos) + basic_machine=i686-pc + os=dicos + ;; + djgpp) + basic_machine=i586-pc + os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=ose + ;; + gmicro) + basic_machine=tron-gmicro + os=sysv + ;; + go32) + basic_machine=i386-pc + os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=hms + ;; + harris) + basic_machine=m88k-harris + os=sysv3 + ;; + hp300 | hp300hpux) + basic_machine=m68k-hp + os=hpux + ;; + hp300bsd) + basic_machine=m68k-hp + os=bsd + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=proelf + ;; + i386mach) + basic_machine=i386-mach + os=mach + ;; + isi68 | isi) + basic_machine=m68k-isi + os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + os=sysv + ;; + merlin) + basic_machine=ns32k-utek + os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + os=coff + ;; + morphos) + basic_machine=powerpc-unknown + os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=moxiebox + ;; + msdos) + basic_machine=i386-pc + os=msdos + ;; + msys) + basic_machine=i686-pc + os=msys + ;; + mvs) + basic_machine=i370-ibm + os=mvs + ;; + nacl) + basic_machine=le32-unknown + os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=newsos + ;; + news1000) + basic_machine=m68030-sony + os=newsos + ;; + necv70) + basic_machine=v70-nec + os=sysv + ;; + nh3000) + basic_machine=m68k-harris + os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=cxux + ;; + nindy960) + basic_machine=i960-intel + os=nindy + ;; + mon960) + basic_machine=i960-intel + os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=ose + ;; + os68k) + basic_machine=m68k-none + os=os68k + ;; + paragon) + basic_machine=i860-intel + os=osf + ;; + parisc) + basic_machine=hppa-unknown + os=linux + ;; + pw32) + basic_machine=i586-unknown + os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=rdos + ;; + rdos32) + basic_machine=i386-pc + os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=coff + ;; + sa29200) + basic_machine=a29k-amd + os=udi + ;; + sei) + basic_machine=mips-sei + os=seiux + ;; + sequent) + basic_machine=i386-sequent + os= + ;; + sps7) + basic_machine=m68k-bull + os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + os= + ;; + stratus) + basic_machine=i860-stratus + os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + os= + ;; + sun2os3) + basic_machine=m68000-sun + os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + os= + ;; + sun3os3) + basic_machine=m68k-sun + os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + os= + ;; + sun4os3) + basic_machine=sparc-sun + os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + os= + ;; + sv1) + basic_machine=sv1-cray + os=unicos + ;; + symmetry) + basic_machine=i386-sequent + os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=unicos + ;; + t90) + basic_machine=t90-cray + os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + os=tpf + ;; + udi29k) + basic_machine=a29k-amd + os=udi + ;; + ultra3) + basic_machine=a29k-nyu + os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=none + ;; + vaxv) + basic_machine=vax-dec + os=sysv + ;; + vms) + basic_machine=vax-dec + os=vms + ;; + vsta) + basic_machine=i386-pc + os=vsta + ;; + vxworks960) + basic_machine=i960-wrs + os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=vxworks + ;; + xbox) + basic_machine=i686-pc + os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + os=unicos + ;; + *) + basic_machine=$1 + os= + ;; + esac ;; esac -# Decode aliases for certain CPU-COMPANY combinations. +# Decode 1-component or ad-hoc basic machines case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 \ - | or1k | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond ;; - c54x) - basic_machine=tic54x-unknown + op50n) + cpu=hppa1.1 + vendor=oki ;; - c55x) - basic_machine=tic55x-unknown + op60c) + cpu=hppa1.1 + vendor=oki ;; - c6x) - basic_machine=tic6x-unknown + ibm*) + cpu=i370 + vendor=ibm ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=-none + orion105) + cpu=clipper + vendor=highlevel ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple ;; - ms1) - basic_machine=mt-unknown + pmac | pmac-mpw) + cpu=powerpc + vendor=apple ;; - strongarm | thumb | xscale) - basic_machine=arm-unknown + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + cpu=m68000 + vendor=att ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none + 3b*) + cpu=we32k + vendor=att ;; - xscaleeb) - basic_machine=armeb-unknown + bluegene*) + cpu=powerpc + vendor=ibm + os=cnk + ;; + decsystem10* | dec10*) + cpu=pdp10 + vendor=dec + os=tops10 + ;; + decsystem20* | dec20*) + cpu=pdp10 + vendor=dec + os=tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + cpu=m68k + vendor=motorola + ;; + dpx2*) + cpu=m68k + vendor=bull + os=sysv3 + ;; + encore | umax | mmax) + cpu=ns32k + vendor=encore + ;; + elxsi) + cpu=elxsi + vendor=elxsi + os=${os:-bsd} + ;; + fx2800) + cpu=i860 + vendor=alliant + ;; + genix) + cpu=ns32k + vendor=ns + ;; + h3050r* | hiux*) + cpu=hppa1.1 + vendor=hitachi + os=hiuxwe2 + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + cpu=m68000 + vendor=hp + ;; + hp9k3[2-9][0-9]) + cpu=m68k + vendor=hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + i*86v32) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=sysv32 + ;; + i*86v4*) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=sysv4 + ;; + i*86v) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=sysv + ;; + i*86sol2) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=solaris2 + ;; + j90 | j90-cray) + cpu=j90 + vendor=cray + os=${os:-unicos} + ;; + iris | iris4d) + cpu=mips + vendor=sgi + case $os in + irix*) + ;; + *) + os=irix4 + ;; + esac + ;; + miniframe) + cpu=m68000 + vendor=convergent + ;; + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + os=mint + ;; + news-3600 | risc-news) + cpu=mips + vendor=sony + os=newsos + ;; + next | m*-next) + cpu=m68k + vendor=next + case $os in + openstep*) + ;; + nextstep*) + ;; + ns2*) + os=nextstep2 + ;; + *) + os=nextstep3 + ;; + esac + ;; + np1) + cpu=np1 + vendor=gould + ;; + op50n-* | op60c-*) + cpu=hppa1.1 + vendor=oki + os=proelf + ;; + pa-hitachi) + cpu=hppa1.1 + vendor=hitachi + os=hiuxwe2 + ;; + pbd) + cpu=sparc + vendor=tti + ;; + pbb) + cpu=m68k + vendor=tti + ;; + pc532) + cpu=ns32k + vendor=pc532 + ;; + pn) + cpu=pn + vendor=gould + ;; + power) + cpu=power + vendor=ibm + ;; + ps2) + cpu=i386 + vendor=ibm + ;; + rm[46]00) + cpu=mips + vendor=siemens + ;; + rtpc | rtpc-*) + cpu=romp + vendor=ibm + ;; + sde) + cpu=mipsisa32 + vendor=sde + os=${os:-elf} + ;; + simso-wrs) + cpu=sparclite + vendor=wrs + os=vxworks + ;; + tower | tower-32) + cpu=m68k + vendor=ncr + ;; + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu + ;; + w65) + cpu=w65 + vendor=wdc + ;; + w89k-*) + cpu=hppa1.1 + vendor=winbond + os=proelf + ;; + none) + cpu=none + vendor=none + ;; + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine + ;; + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; - xscaleel) - basic_machine=armel-unknown + *-*) + # shellcheck disable=SC2162 + IFS="-" read cpu vendor <&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i686-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 + cpu=$basic_machine + vendor=pc ;; + # These rules are duplicated from below for sake of the special case above; + # i.e. things that normalized to x86 arches should also default to "pc" pc98) - basic_machine=i386-pc + cpu=i386 + vendor=pc ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + x64 | amd64) + cpu=x86_64 + vendor=pc ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc + # Recognize the basic CPU types without company name. + *) + cpu=$basic_machine + vendor=unknown ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc +esac + +unset -v basic_machine + +# Decode basic machines in the full and proper CPU-Company form. +case $cpu-$vendor in + # Here we handle the default manufacturer of certain CPU types in canonical form. It is in + # some cases the only manufacturer, in others, it is the most popular. + craynv-unknown) + vendor=cray + os=${os:-unicosmp} ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc + c90-unknown | c90-cray) + vendor=cray + os=${os:-unicos} ;; - pentium4) - basic_machine=i786-pc + fx80-unknown) + vendor=alliant ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + romp-unknown) + vendor=ibm ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + mmix-unknown) + vendor=knuth ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + microblaze-unknown | microblazeel-unknown) + vendor=xilinx ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + rs6000-unknown) + vendor=ibm ;; - pn) - basic_machine=pn-gould + vax-unknown) + vendor=dec ;; - power) basic_machine=power-ibm + pdp11-unknown) + vendor=dec ;; - ppc | ppcbe) basic_machine=powerpc-unknown + we32k-unknown) + vendor=att ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + cydra-unknown) + vendor=cydrome ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown + i370-ibm*) + vendor=ibm ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + orion-unknown) + vendor=highlevel ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos - ;; - rdos32) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none + xps-unknown | xps100-unknown) + cpu=xps100 + vendor=honeywell ;; -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond + # Here we normalize CPU types with a missing or matching vendor + dpx20-unknown | dpx20-bull) + cpu=rs6000 + vendor=bull + os=${os:-bosx} ;; - op50n) - basic_machine=hppa1.1-oki + + # Here we normalize CPU types irrespective of the vendor + amd64-*) + cpu=x86_64 ;; - op60c) - basic_machine=hppa1.1-oki + blackfin-*) + cpu=bfin + os=linux ;; - romp) - basic_machine=romp-ibm + c54x-*) + cpu=tic54x ;; - mmix) - basic_machine=mmix-knuth + c55x-*) + cpu=tic55x ;; - rs6000) - basic_machine=rs6000-ibm + c6x-*) + cpu=tic6x ;; - vax) - basic_machine=vax-dec + e500v[12]-*) + cpu=powerpc + os=$os"spe" ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown + mips3*-*) + cpu=mips64 ;; - pdp11) - basic_machine=pdp11-dec + ms1-*) + cpu=mt ;; - we32k) - basic_machine=we32k-att + m68knommu-*) + cpu=m68k + os=linux ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown + m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*) + cpu=s12z ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun + openrisc-*) + cpu=or32 ;; - cydra) - basic_machine=cydra-cydrome + parisc-*) + cpu=hppa + os=linux ;; - orion) - basic_machine=orion-highlevel + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + cpu=i586 ;; - orion105) - basic_machine=clipper-highlevel + pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) + cpu=i686 ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + cpu=i686 ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple + pentium4-*) + cpu=i786 ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. + pc98-*) + cpu=i386 ;; + ppc-* | ppcbe-*) + cpu=powerpc + ;; + ppcle-* | powerpclittle-*) + cpu=powerpcle + ;; + ppc64-*) + cpu=powerpc64 + ;; + ppc64le-* | powerpc64little-*) + cpu=powerpc64le + ;; + sb1-*) + cpu=mipsisa64sb1 + ;; + sb1el-*) + cpu=mipsisa64sb1el + ;; + sh5e[lb]-*) + cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'` + ;; + spur-*) + cpu=spur + ;; + strongarm-* | thumb-*) + cpu=arm + ;; + tx39-*) + cpu=mipstx39 + ;; + tx39el-*) + cpu=mipstx39el + ;; + x64-*) + cpu=x86_64 + ;; + xscale-* | xscalee[bl]-*) + cpu=`echo "$cpu" | sed 's/^xscale/arm/'` + ;; + + # Recognize the canonical CPU Types that limit and/or modify the + # company names they are paired with. + cr16-*) + os=${os:-elf} + ;; + crisv32-* | etraxfs*-*) + cpu=crisv32 + vendor=axis + ;; + cris-* | etrax*-*) + cpu=cris + vendor=axis + ;; + crx-*) + os=${os:-elf} + ;; + neo-tandem) + cpu=neo + vendor=tandem + ;; + nse-tandem) + cpu=nse + vendor=tandem + ;; + nsr-tandem) + cpu=nsr + vendor=tandem + ;; + nsv-tandem) + cpu=nsv + vendor=tandem + ;; + nsx-tandem) + cpu=nsx + vendor=tandem + ;; + s390-*) + cpu=s390 + vendor=ibm + ;; + s390x-*) + cpu=s390x + vendor=ibm + ;; + tile*-*) + os=${os:-linux-gnu} + ;; + *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 + # Recognize the canonical CPU types that are allowed with any + # company name. + case $cpu in + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ + | alphapca5[67] | alpha64pca5[67] \ + | am33_2.0 \ + | amdgcn \ + | arc | arceb \ + | arm | arm[lb]e | arme[lb] | armv* \ + | avr | avr32 \ + | asmjs \ + | ba \ + | be32 | be64 \ + | bfin | bpf | bs2000 \ + | c[123]* | c30 | [cjt]90 | c4x \ + | c8051 | clipper | craynv | csky | cydra \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64eb | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | none | np1 | ns16k | ns32k | nvptx \ + | open8 \ + | or1k* \ + | or32 \ + | orion \ + | picochip \ + | pdp10 | pdp11 | pj | pjl | pn | power \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv64 \ + | rl78 | romp | rs6000 | rx \ + | score \ + | sh | shl \ + | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ + | tahoe \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ + | ubicom32 \ + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ + | visium \ + | w65 \ + | wasm32 | wasm64 \ + | we32k \ + | x86 | x86_64 | xc16x | xgate | xps100 \ + | xstormy16 | xtensa* \ + | ymp \ + | z8k | z80) + ;; + + *) + echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + exit 1 + ;; + esac ;; esac # Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` +case $vendor in + digital*) + vendor=dec ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + commodore*) + vendor=cbm ;; *) ;; @@ -1323,197 +1275,244 @@ esac # Decode manufacturer-specific aliases for certain operating systems. -if [ x"$os" != x"" ] +if [ x$os != x ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux + # First match some system type aliases that might get confused + # with valid system types. + # solaris* is a basic system type, with this one exception. + auroraux) + os=auroraux ;; - -solaris1 | -solaris1.*) + bluegene*) + os=cnk + ;; + solaris1 | solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; - -solaris) - os=-solaris2 + solaris) + os=solaris2 ;; - -svr4*) - os=-sysv4 + unixware*) + os=sysv4.2uw ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) + gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # es1800 is here to avoid being matched by es* (a different OS) + es1800*) + os=ose + ;; + # Some version numbers need modification + chorusos*) + os=chorusos + ;; + isc) + os=isc2.2 + ;; + sco6) + os=sco5v6 + ;; + sco5) + os=sco3.2v5 + ;; + sco4) + os=sco3.2v4 + ;; + sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + ;; + sco3.2v[4-9]* | sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + ;; + scout) + # Don't match below + ;; + sco*) + os=sco3.2v2 + ;; + psos*) + os=psos + ;; + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Each alternative MUST end in a * to match a version number. + # sysv* is not here because it comes later, after sysvr4. + gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ + | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | kopensolaris* | plan9* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* | twizzler* \ + | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ + | knetbsd* | mirbsd* | netbsd* \ + | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \ + | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \ + | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ + | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \ + | chorusrdb* | cegcc* | glidix* \ + | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \ + | linux-newlib* | linux-musl* | linux-uclibc* \ + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ + | interix* | uwin* | mks* | rhapsody* | darwin* \ + | openstep* | oskit* | conix* | pw32* | nonstopux* \ + | storm-chaos* | tops10* | tenex* | tops20* | its* \ + | os2* | vos* | palmos* | uclinux* | nucleus* \ + | morphos* | superux* | rtmk* | windiss* \ + | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ + | nsk* | powerunix) # Remember, each alternative MUST END IN *, to match a version number. ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) + qnx*) + case $cpu in + x86 | i*86) ;; *) - os=-nto$os + os=nto-$os ;; esac ;; - -nto-qnx*) + hiux*) + os=hiuxwe2 ;; - -nto*) + nto-qnx*) + ;; + nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + sim | xray | os68k* | v88r* \ + | windows* | osx | abug | netware* | os9* \ + | macos* | mpw* | magic* | mmixware* | mon960* | lnews*) ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` + linux-dietlibc) + os=linux-dietlibc ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) + linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` + lynx*178) + os=lynxos178 ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` + lynx*5) + os=lynxos5 ;; - -opened*) - os=-openedition + lynx*) + os=lynxos ;; - -os400*) - os=-os400 + mac*) + os=`echo "$os" | sed -e 's|mac|macos|'` ;; - -wince*) - os=-wince + opened*) + os=openedition ;; - -osfrose*) - os=-osfrose + os400*) + os=os400 ;; - -osf*) - os=-osf + sunos5*) + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; - -utek*) - os=-bsd + sunos6*) + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; - -dynix*) - os=-bsd + wince*) + os=wince ;; - -acis*) - os=-aos + utek*) + os=bsd ;; - -atheos*) - os=-atheos + dynix*) + os=bsd ;; - -syllable*) - os=-syllable + acis*) + os=aos ;; - -386bsd) - os=-bsd + atheos*) + os=atheos ;; - -ctix* | -uts*) - os=-sysv + syllable*) + os=syllable ;; - -nova*) - os=-rtmk-nova + 386bsd) + os=bsd ;; - -ns2 ) - os=-nextstep2 + ctix* | uts*) + os=sysv ;; - -nsk*) - os=-nsk + nova*) + os=rtmk-nova + ;; + ns2) + os=nextstep2 ;; # Preserve the version number of sinix5. - -sinix5.*) + sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; - -sinix*) - os=-sysv4 + sinix*) + os=sysv4 ;; - -tpf*) - os=-tpf + tpf*) + os=tpf ;; - -triton*) - os=-sysv3 + triton*) + os=sysv3 ;; - -oss*) - os=-sysv3 + oss*) + os=sysv3 ;; - -svr4) - os=-sysv4 + svr4*) + os=sysv4 ;; - -svr3) - os=-sysv3 + svr3) + os=sysv3 ;; - -sysvr4) - os=-sysv4 + sysvr4) + os=sysv4 ;; - # This must come after -sysvr4. - -sysv*) + # This must come after sysvr4. + sysv*) ;; - -ose*) - os=-ose + ose*) + os=ose ;; - -es1800*) - os=-ose + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) + os=mint ;; - -xenix) - os=-xenix + zvmoe) + os=zvmoe ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint + dicos*) + os=dicos ;; - -aros*) - os=-aros + pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $cpu in + arm*) + os=eabi + ;; + *) + os=elf + ;; + esac ;; - -zvmoe) - os=-zvmoe + nacl*) ;; - -dicos*) - os=-dicos + ios) ;; - -nacl*) + none) ;; - -none) + *-eabi) ;; *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac @@ -1529,264 +1528,265 @@ else # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. -case $basic_machine in +case $cpu-$vendor in score-*) - os=-elf + os=elf ;; spu-*) - os=-elf + os=elf ;; *-acorn) - os=-riscix1.2 + os=riscix1.2 ;; arm*-rebel) - os=-linux + os=linux ;; arm*-semi) - os=-aout + os=aout ;; c4x-* | tic4x-*) - os=-coff + os=coff ;; c8051-*) - os=-elf + os=elf + ;; + clipper-intergraph) + os=clix ;; hexagon-*) - os=-elf + os=elf ;; tic54x-*) - os=-coff + os=coff ;; tic55x-*) - os=-coff + os=coff ;; tic6x-*) - os=-coff + os=coff ;; # This must come before the *-dec entry. pdp10-*) - os=-tops20 + os=tops20 ;; pdp11-*) - os=-none + os=none ;; *-dec | vax-*) - os=-ultrix4.2 + os=ultrix4.2 ;; m68*-apollo) - os=-domain + os=domain ;; i386-sun) - os=-sunos4.0.2 + os=sunos4.0.2 ;; m68000-sun) - os=-sunos3 + os=sunos3 ;; m68*-cisco) - os=-aout + os=aout ;; mep-*) - os=-elf + os=elf ;; mips*-cisco) - os=-elf + os=elf ;; mips*-*) - os=-elf - ;; - or1k-*) - os=-elf + os=elf ;; or32-*) - os=-coff + os=coff ;; *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 + os=sysv3 ;; sparc-* | *-sun) - os=-sunos4.1.1 + os=sunos4.1.1 + ;; + pru-*) + os=elf ;; *-be) - os=-beos - ;; - *-haiku) - os=-haiku + os=beos ;; *-ibm) - os=-aix + os=aix ;; *-knuth) - os=-mmixware + os=mmixware ;; *-wec) - os=-proelf + os=proelf ;; *-winbond) - os=-proelf + os=proelf ;; *-oki) - os=-proelf + os=proelf ;; *-hp) - os=-hpux + os=hpux ;; *-hitachi) - os=-hiux + os=hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv + os=sysv ;; *-cbm) - os=-amigaos + os=amigaos ;; *-dg) - os=-dgux + os=dgux ;; *-dolphin) - os=-sysv3 + os=sysv3 ;; m68k-ccur) - os=-rtu + os=rtu ;; m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs + os=luna ;; *-next) - os=-nextstep3 + os=nextstep + ;; + *-sequent) + os=ptx + ;; + *-crds) + os=unos + ;; + *-ns) + os=genix + ;; + i370-*) + os=mvs ;; *-gould) - os=-sysv + os=sysv ;; *-highlevel) - os=-bsd + os=bsd ;; *-encore) - os=-bsd + os=bsd ;; *-sgi) - os=-irix + os=irix ;; *-siemens) - os=-sysv4 + os=sysv4 ;; *-masscomp) - os=-rtu + os=rtu ;; f30[01]-fujitsu | f700-fujitsu) - os=-uxpv + os=uxpv ;; *-rom68k) - os=-coff + os=coff ;; *-*bug) - os=-coff + os=coff ;; *-apple) - os=-macos + os=macos ;; *-atari*) - os=-mint + os=mint + ;; + *-wrs) + os=vxworks ;; *) - os=-none + os=none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) +case $vendor in + unknown) case $os in - -riscix*) + riscix*) vendor=acorn ;; - -sunos*) + sunos*) vendor=sun ;; - -cnk*|-aix*) + cnk*|-aix*) vendor=ibm ;; - -beos*) + beos*) vendor=be ;; - -hpux*) + hpux*) vendor=hp ;; - -mpeix*) + mpeix*) vendor=hp ;; - -hiux*) + hiux*) vendor=hitachi ;; - -unos*) + unos*) vendor=crds ;; - -dgux*) + dgux*) vendor=dg ;; - -luna*) + luna*) vendor=omron ;; - -genix*) + genix*) vendor=ns ;; - -mvs* | -opened*) + clix*) + vendor=intergraph + ;; + mvs* | opened*) vendor=ibm ;; - -os400*) + os400*) vendor=ibm ;; - -ptx*) + ptx*) vendor=sequent ;; - -tpf*) + tpf*) vendor=ibm ;; - -vxsim* | -vxworks* | -windiss*) + vxsim* | vxworks* | windiss*) vendor=wrs ;; - -aux*) + aux*) vendor=apple ;; - -hms*) + hms*) vendor=hitachi ;; - -mpw* | -macos*) + mpw* | macos*) vendor=apple ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) vendor=atari ;; - -vos*) + vos*) vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os +echo "$cpu-$vendor-$os" exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/FreeRTOS-Plus/Source/WolfSSL/build-aux/depcomp b/FreeRTOS-Plus/Source/WolfSSL/build-aux/depcomp index 4ebd5b3a2..6b391623c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/build-aux/depcomp +++ b/FreeRTOS-Plus/Source/WolfSSL/build-aux/depcomp @@ -1,9 +1,9 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2013-05-30.07; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ scriptversion=2013-05-30.07; # UTC # 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, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -783,9 +783,9 @@ exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/FreeRTOS-Plus/Source/WolfSSL/build-aux/install-sh b/FreeRTOS-Plus/Source/WolfSSL/build-aux/install-sh index 377bb8687..20d8b2eae 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/build-aux/install-sh +++ b/FreeRTOS-Plus/Source/WolfSSL/build-aux/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2011-11-20.07; # UTC +scriptversion=2018-03-11.20; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -41,19 +41,15 @@ scriptversion=2011-11-20.07; # UTC # This script is compatible with the BSD install script, but was written # from scratch. +tab=' ' nl=' ' -IFS=" "" $nl" +IFS=" $tab$nl" -# set DOITPROG to echo to test this script +# Set DOITPROG to "echo" to test this script. -# Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi +doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. @@ -68,17 +64,6 @@ mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - posix_mkdir= # Desired mode of installed file. @@ -97,7 +82,7 @@ dir_arg= dst_arg= copy_on_change=false -no_target_directory= +is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE @@ -137,46 +122,57 @@ while test $# -ne 0; do -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" - shift;; + shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; -o) chowncmd="$chownprog $2" - shift;; + shift;; -s) stripcmd=$stripprog;; - -t) dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; - -T) no_target_directory=true;; + -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; - --) shift - break;; + --) shift + break;; - -*) echo "$0: invalid option: $1" >&2 - exit 1;; + -*) echo "$0: invalid option: $1" >&2 + exit 1;; *) break;; esac shift done +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. @@ -207,6 +203,15 @@ if test $# -eq 0; then exit 0 fi +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 @@ -223,16 +228,16 @@ if test -z "$dir_arg"; then *[0-7]) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw='% 200' + u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw=,u+rw + u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac @@ -266,122 +271,113 @@ do fi dst=$dst_arg - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. + # If destination is a directory, append the input filename. if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 fi dstdir=$dst - dst=$dstdir/`basename "$src"` + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac dstdir_status=0 else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - + dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac + obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + # Note that $RANDOM variable is not portable (e.g. dash); Use it + # here however when possible just to lower collision chance. + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + + # Because "mkdir -p" follows existing symlinks and we likely work + # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directory is successfully created first before we actually test + # 'mkdir -p' feature. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; esac if $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else @@ -391,53 +387,51 @@ do # directory the slow way, step by step, checking for races as we go. case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; esac - eval "$initialize_posix_glob" - oIFS=$IFS IFS=/ - $posix_glob set -f + set -f set fnord $dstdir shift - $posix_glob set +f + set +f IFS=$oIFS prefixes= for d do - test X"$d" = X && continue + test X"$d" = X && continue - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ done if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true fi fi fi @@ -450,14 +444,25 @@ do else # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + (umask $cp_umask && + { test -z "$stripcmd" || { + # Create $dsttmp read-write so that cp doesn't create it read-only, + # which would cause strip to fail. + if test -z "$doit"; then + : >"$dsttmp" # No need to fork-exec 'touch'. + else + $doit touch "$dsttmp" + fi + } + } && + $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # @@ -472,15 +477,12 @@ do # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - + set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then @@ -493,24 +495,24 @@ do # to itself, or perhaps because mv is so ancient that it does not # support -f. { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 @@ -519,9 +521,9 @@ do done # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/FreeRTOS-Plus/Source/WolfSSL/build-aux/ltmain.sh b/FreeRTOS-Plus/Source/WolfSSL/build-aux/ltmain.sh index 9ae038c24..0f0a2da3f 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/build-aux/ltmain.sh +++ b/FreeRTOS-Plus/Source/WolfSSL/build-aux/ltmain.sh @@ -1,9 +1,12 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 -# libtool (GNU libtool) 2.4.2 +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, -# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +# Copyright (C) 1996-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -23,166 +26,670 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, -# or obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# along with this program. If not, see . -# Usage: $progname [OPTION]... [MODE-ARG]... -# -# Provide generalized library-building support services. -# -# --config show all configuration variables -# --debug enable verbose shell tracing -# -n, --dry-run display commands without modifying any files -# --features display basic configuration information and exit -# --mode=MODE use operation mode MODE -# --preserve-dup-deps don't remove duplicate dependency libraries -# --quiet, --silent don't print informational messages -# --no-quiet, --no-silent -# print informational messages (default) -# --no-warn don't display warning messages -# --tag=TAG use configuration variables from tag TAG -# -v, --verbose print more informational messages than default -# --no-verbose don't print the extra informational messages -# --version print version information -# -h, --help, --help-all print short, long, or detailed help message -# -# MODE must be one of the following: -# -# clean remove files from the build directory -# compile compile a source file into a libtool object -# execute automatically set library path, then run a program -# finish complete the installation of libtool libraries -# install install libraries or executables -# link create a library or an executable -# uninstall remove libraries from an installed directory -# -# MODE-ARGS vary depending on the MODE. When passed as first option, -# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. -# Try `$progname --help --mode=MODE' for a more detailed description of MODE. -# -# When reporting a bug, please describe a test case to reproduce it and -# include the following information: -# -# host-triplet: $host -# shell: $SHELL -# compiler: $LTCC -# compiler flags: $LTCFLAGS -# linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.4.2 -# automake: $automake_version -# autoconf: $autoconf_version -# -# Report bugs to . -# GNU libtool home page: . -# General help using GNU software: . PROGRAM=libtool PACKAGE=libtool -VERSION=2.4.2 -TIMESTAMP="" -package_revision=1.3337 +VERSION=2.4.6 +package_revision=2.4.6 -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program 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 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES 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, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - -# NLS nuisances: We save the old values to restore during execute mode. -lt_user_locale= -lt_safe_locale= -for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do - eval "if test \"\${$lt_var+set}\" = set; then - save_$lt_var=\$$lt_var - $lt_var=C - export $lt_var - lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" - lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done -LC_ALL=C -LANGUAGE=C -export LANGUAGE LC_ALL -$lt_unset CDPATH +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. -progpath="$0" +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac +## ----------------- ## +## Standard options. ## +## ----------------- ## -: ${CP="cp -f"} -test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} -: ${MAKE="make"} -: ${MKDIR="mkdir"} -: ${MV="mv -f"} -: ${RM="rm -f"} -: ${SHELL="${CONFIG_SHELL-/bin/sh}"} -: ${Xsed="$SED -e 1s/^X//"} +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. -# Global variables: -EXIT_SUCCESS=0 -EXIT_FAILURE=1 -EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. -EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. +opt_dry_run=false +opt_quiet=false +opt_verbose=false -exit_status=$EXIT_SUCCESS +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= -# Make sure IFS has a sensible default -lt_nl=' -' -IFS=" $lt_nl" +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue -dirname="s,/[^/]*$,," -basename="s,^.*/,," +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all -# func_dirname file append nondir_replacement + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. -func_dirname () +eval 'func_dirname () { - func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} # func_dirname may be replaced by extended shell implementation + $debug_cmd + + '"$_d"' +}' -# func_basename file -func_basename () -{ - func_basename_result=`$ECHO "${1}" | $SED "$basename"` -} # func_basename may be replaced by extended shell implementation - - -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result @@ -190,263 +697,327 @@ func_basename () # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () { - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" fi - func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` -} # func_dirname_and_basename may be replaced by extended shell implementation +} -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () { - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; - esac -} # func_stripname may be replaced by extended shell implementation + $debug_cmd + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} -# These SED scripts presuppose an absolute path with a trailing slash. -pathcar='s,^/\([^/]*\).*$,\1,' -pathcdr='s,^/[^/]*,,' -removedotparts=':dotsl - s@/\./@/@g - t dotsl - s,/\.$,/,' -collapseslashes='s@/\{1,\}@/@g' -finalslash='s,/*$,/,' # func_normal_abspath PATH +# ------------------------ # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. -# value returned in "$func_normal_abspath_result" func_normal_abspath () { - # Start from root dir and reassemble the path. - func_normal_abspath_result= - func_normal_abspath_tpath=$1 - func_normal_abspath_altnamespace= - case $func_normal_abspath_tpath in - "") - # Empty path, that just means $cwd. - func_stripname '' '/' "`pwd`" - func_normal_abspath_result=$func_stripname_result - return - ;; - # The next three entries are used to spot a run of precisely - # two leading slashes without using negated character classes; - # we take advantage of case's first-match behaviour. - ///*) - # Unusual form of absolute path, do nothing. - ;; - //*) - # Not necessarily an ordinary path; POSIX reserves leading '//' - # and for example Cygwin uses it to access remote file shares - # over CIFS/SMB, so we conserve a leading double slash if found. - func_normal_abspath_altnamespace=/ - ;; - /*) - # Absolute path, do nothing. - ;; - *) - # Relative path, prepend $cwd. - func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath - ;; - esac - # Cancel out all the simple stuff to save iterations. We also want - # the path to end with a slash for ease of parsing, so make sure - # there is one (and only one) here. - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` - while :; do - # Processed it all yet? - if test "$func_normal_abspath_tpath" = / ; then - # If we ascended to the root using ".." the result may be empty now. - if test -z "$func_normal_abspath_result" ; then - func_normal_abspath_result=/ - fi - break - fi - func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcar"` - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcdr"` - # Figure out what to do with it - case $func_normal_abspath_tcomponent in + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in "") - # Trailing empty path component, ignore it. - ;; - ..) - # Parent dir; strip last assembled component from result. - func_dirname "$func_normal_abspath_result" - func_normal_abspath_result=$func_dirname_result - ;; - *) - # Actual path component, append it. - func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent - ;; - esac - done - # Restore leading double-slash if one was found on entry. - func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result -} - -# func_relative_path SRCDIR DSTDIR -# generates a relative path from SRCDIR to DSTDIR, with a trailing -# slash if non-empty, suitable for immediately appending a filename -# without needing to append a separator. -# value returned in "$func_relative_path_result" -func_relative_path () -{ - func_relative_path_result= - func_normal_abspath "$1" - func_relative_path_tlibdir=$func_normal_abspath_result - func_normal_abspath "$2" - func_relative_path_tbindir=$func_normal_abspath_result - - # Ascend the tree starting from libdir - while :; do - # check if we have found a prefix of bindir - case $func_relative_path_tbindir in - $func_relative_path_tlibdir) - # found an exact match - func_relative_path_tcancelled= - break + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return ;; - $func_relative_path_tlibdir*) - # found a matching prefix - func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" - func_relative_path_tcancelled=$func_stripname_result - if test -z "$func_relative_path_result"; then - func_relative_path_result=. - fi - break + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. ;; *) - func_dirname $func_relative_path_tlibdir - func_relative_path_tlibdir=${func_dirname_result} - if test "x$func_relative_path_tlibdir" = x ; then - # Have to descend all the way to the root! - func_relative_path_result=../$func_relative_path_result - func_relative_path_tcancelled=$func_relative_path_tbindir - break - fi - func_relative_path_result=../$func_relative_path_result + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac - done - # Now calculate path; take care to avoid doubling-up slashes. - func_stripname '' '/' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - func_stripname '/' '/' "$func_relative_path_tcancelled" - if test "x$func_stripname_result" != x ; then - func_relative_path_result=${func_relative_path_result}/${func_stripname_result} - fi - - # Normalisation. If bindir is libdir, return empty string, - # else relative path ending with a slash; either way, target - # file name can be directly appended. - if test ! -z "$func_relative_path_result"; then - func_stripname './' '' "$func_relative_path_result/" - func_relative_path_result=$func_stripname_result - fi + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } -# The name of this program: -func_dirname_and_basename "$progpath" -progname=$func_basename_result -# Make sure we have an absolute path for reexecution: -case $progpath in - [\\/]*|[A-Za-z]:\\*) ;; - *[\\/]*) - progdir=$func_dirname_result - progdir=`cd "$progdir" && pwd` - progpath="$progdir/$progname" - ;; - *) - save_IFS="$IFS" - IFS=${PATH_SEPARATOR-:} - for progdir in $PATH; do - IFS="$save_IFS" - test -x "$progdir/$progname" && break - done - IFS="$save_IFS" - test -n "$progdir" || progdir=`pwd` - progpath="$progdir/$progname" - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed="${SED}"' -e 1s/^X//' -sed_quote_subst='s/\([`"$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution that turns a string into a regex matching for the -# string literally. -sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' - -# Sed substitution that converts a w32 file name or path -# which contains forward slashes, into one that contains -# (escaped) backslashes. A very naive implementation. -lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' - -# Re-`\' parameter expansions in output of double_quote_subst that were -# `\'-ed in input to the same. If an odd number of `\' preceded a '$' -# in input to double_quote_subst, that '$' was protected from expansion. -# Since each input `\' is now two `\'s, look for any number of runs of -# four `\'s followed by two `\'s and then a '$'. `\' that '$'. -bs='\\' -bs2='\\\\' -bs4='\\\\\\\\' -dollar='\$' -sed_double_backslash="\ - s/$bs4/&\\ -/g - s/^$bs2$dollar/$bs&/ - s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g - s/\n//g" - -# Standard options: -opt_dry_run=false -opt_help=false -opt_quiet=false -opt_verbose=false -opt_warning=: - -# func_echo arg... -# Echo program name prefixed message, along with the current mode -# name if it has been set yet. -func_echo () +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () { - $ECHO "$progname: ${opt_mode+$opt_mode: }$*" -} + $debug_cmd -# func_verbose arg... -# Echo program name prefixed message in verbose mode only. -func_verbose () -{ - $opt_verbose && func_echo ${1+"$@"} + $opt_quiet || func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to @@ -454,450 +1025,1113 @@ func_verbose () : } -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} -# func_error arg... -# Echo program name prefixed message to standard error. -func_error () +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () { - $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 -} + $debug_cmd -# func_warning arg... -# Echo program name prefixed warning message to standard error. -func_warning () -{ - $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. - # bash bug again: : } -# func_fatal_error arg... -# Echo program name prefixed message to standard error, and exit. -func_fatal_error () -{ - func_error ${1+"$@"} - exit $EXIT_FAILURE -} -# func_fatal_help arg... -# Echo program name prefixed message to standard error, followed by -# a help hint, and exit. -func_fatal_help () -{ - func_error ${1+"$@"} - func_fatal_error "$help" -} -help="Try \`$progname --help' for more information." ## default - - -# func_grep expression filename -# Check whether EXPRESSION matches any line of FILENAME, without output. -func_grep () -{ - $GREP "$1" "$2" >/dev/null 2>&1 -} - - -# func_mkdir_p directory-path -# Make sure the entire path to DIRECTORY-PATH is available. -func_mkdir_p () -{ - my_directory_path="$1" - my_dir_list= - - if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then - - # Protect directory names starting with `-' - case $my_directory_path in - -*) my_directory_path="./$my_directory_path" ;; - esac - - # While some portion of DIR does not yet exist... - while test ! -d "$my_directory_path"; do - # ...make a list in topmost first order. Use a colon delimited - # list incase some portion of path contains whitespace. - my_dir_list="$my_directory_path:$my_dir_list" - - # If the last portion added has no slash in it, the list is done - case $my_directory_path in */*) ;; *) break ;; esac - - # ...otherwise throw away the child directory and loop - my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` - done - my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` - - save_mkdir_p_IFS="$IFS"; IFS=':' - for my_dir in $my_dir_list; do - IFS="$save_mkdir_p_IFS" - # mkdir can fail with a `File exist' error if two processes - # try to create one of the directories concurrently. Don't - # stop in that case! - $MKDIR "$my_dir" 2>/dev/null || : - done - IFS="$save_mkdir_p_IFS" - - # Bail out if we (or some other process) failed to create a directory. - test -d "$my_directory_path" || \ - func_fatal_error "Failed to create \`$1'" - fi -} - - -# func_mktempdir [string] -# Make a temporary directory that won't clash with other running -# libtool processes, and avoids race conditions if possible. If -# given, STRING is the basename for that directory. -func_mktempdir () -{ - my_template="${TMPDIR-/tmp}/${1-$progname}" - - if test "$opt_dry_run" = ":"; then - # Return a directory name, but don't create it in dry-run mode - my_tmpdir="${my_template}-$$" - else - - # If mktemp works, use that first and foremost - my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` - - if test ! -d "$my_tmpdir"; then - # Failing that, at least try and use $RANDOM to avoid a race - my_tmpdir="${my_template}-${RANDOM-0}$$" - - save_mktempdir_umask=`umask` - umask 0077 - $MKDIR "$my_tmpdir" - umask $save_mktempdir_umask - fi - - # If we're not in dry-run mode, bomb out on failure - test -d "$my_tmpdir" || \ - func_fatal_error "cannot create temporary directory \`$my_tmpdir'" - fi - - $ECHO "$my_tmpdir" -} - - -# func_quote_for_eval arg -# Aesthetically quote ARG to be evaled later. -# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT -# is double-quoted, suitable for a subsequent eval, whereas -# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters -# which are still active within double quotes backslashified. +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. func_quote_for_eval () { - case $1 in - *[\\\`\"\$]*) - func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; - *) - func_quote_for_eval_unquoted_result="$1" ;; - esac + $debug_cmd - case $func_quote_for_eval_unquoted_result in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and and variable - # expansion for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" - ;; - *) - func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" - esac + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done } -# func_quote_for_expand arg +# func_quote_for_expand ARG +# ------------------------- # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { + $debug_cmd + case $1 in *[\\\`\"]*) - my_arg=`$ECHO "$1" | $SED \ - -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; *) - my_arg="$1" ;; + _G_arg=$1 ;; esac - case $my_arg in + case $_G_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - my_arg="\"$my_arg\"" + _G_arg=\"$_G_arg\" ;; esac - func_quote_for_expand_result="$my_arg" + func_quote_for_expand_result=$_G_arg } -# func_show_eval cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { - my_cmd="$1" - my_fail_exp="${2-:}" + $debug_cmd - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } + _G_cmd=$1 + _G_fail_exp=${2-':'} - if ${opt_dry_run-false}; then :; else - eval "$my_cmd" - my_status=$? - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" fi - fi + } } -# func_show_eval_locale cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { - my_cmd="$1" - my_fail_exp="${2-:}" + $debug_cmd - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" eval "func_echo $func_quote_for_expand_result" } - if ${opt_dry_run-false}; then :; else - eval "$lt_user_locale - $my_cmd" - my_status=$? - eval "$lt_safe_locale" - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" fi - fi + } } + # func_tr_sh +# ---------- # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { - case $1 in - [0-9]* | *[!a-zA-Z0-9_]*) - func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` - ;; - * ) - func_tr_sh_result=$1 - ;; - esac + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac } -# func_version -# Echo version message to standard output and exit. -func_version () +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () { - $opt_debug + $debug_cmd - $SED -n '/(C)/!b go - :more - /\./!{ - N - s/\n# / / - b more - } - :go - /^# '$PROGRAM' (GNU /,/# warranty; / { - s/^# // - s/^# *$// - s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ - p - }' < "$progpath" - exit $? + $opt_verbose && func_echo "$*" + + : } -# func_usage -# Echo short help message to standard output and exit. -func_usage () + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () { - $opt_debug + $debug_cmd - $SED -n '/^# Usage:/,/^# *.*--help/ { - s/^# // - s/^# *$// - s/\$progname/'$progname'/ - p - }' < "$progpath" - echo - $ECHO "run \`$progname --help | more' for full usage" - exit $? + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 } -# func_help [NOEXIT] -# Echo long help message to standard output and exit, -# unless 'noexit' is passed as argument. + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program 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 3 of the License, or +# (at your option) any later version. + +# This program 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, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. func_help () { - $opt_debug + $debug_cmd - $SED -n '/^# Usage:/,/# Report bugs to/ { - :print - s/^# // - s/^# *$// - s*\$progname*'$progname'* - s*\$host*'"$host"'* - s*\$SHELL*'"$SHELL"'* - s*\$LTCC*'"$LTCC"'* - s*\$LTCFLAGS*'"$LTCFLAGS"'* - s*\$LD*'"$LD"'* - s/\$with_gnu_ld/'"$with_gnu_ld"'/ - s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ - s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ - p - d - } - /^# .* home page:/b print - /^# General help using/b print - ' < "$progpath" - ret=$? - if test -z "$1"; then - exit $ret - fi + func_usage_message + $ECHO "$long_help_message" + exit 0 } -# func_missing_arg argname + +# func_missing_arg ARGNAME +# ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { - $opt_debug + $debug_cmd - func_error "missing argument for $1." + func_error "Missing argument for '$1'." exit_cmd=exit } -# func_split_short_opt shortopt +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. -func_split_short_opt () +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () { - my_sed_short_opt='1s/^\(..\).*$/\1/;q' - my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + $debug_cmd - func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` - func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` -} # func_split_short_opt may be replaced by extended shell implementation + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} -# func_split_long_opt longopt -# Set func_split_long_opt_name and func_split_long_opt_arg shell -# variables after splitting LONGOPT at the `=' sign. -func_split_long_opt () +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () { - my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' - my_sed_long_arg='1s/^--[^=]*=//' + $debug_cmd - func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` - func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` -} # func_split_long_opt may be replaced by extended shell implementation - -exit_cmd=: + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} - - - -magic="%%%MAGIC variable%%%" -magic_exe="%%%MAGIC EXE variable%%%" - -# Global variables. -nonopt= -preserve_args= -lo2o="s/\\.lo\$/.${objext}/" -o2lo="s/\\.${objext}\$/.lo/" -extracted_archives= -extracted_serial=0 - -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () { - eval "${1}=\$${1}\${2}" -} # func_append may be replaced by extended shell implementation + $debug_cmd -# func_append_quoted var value -# Quote VALUE and append to the end of shell variable VAR, separated -# by a space. -func_append_quoted () + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () { - func_quote_for_eval "${2}" - eval "${1}=\$${1}\\ \$func_quote_for_eval_result" -} # func_append_quoted may be replaced by extended shell implementation + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} -# func_arith arithmetic-term... -func_arith () +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () { - func_arith_result=`expr "${@}"` -} # func_arith may be replaced by extended shell implementation + $debug_cmd + + $warning_func ${1+"$@"} +} -# func_len string -# STRING may not start with a hyphen. -func_len () +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () { - func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` -} # func_len may be replaced by extended shell implementation + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname (GNU libtool) 2.4.6 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} -# func_lo2o object -func_lo2o () -{ - func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` -} # func_lo2o may be replaced by extended shell implementation +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` -} # func_xform may be replaced by extended shell implementation - - -# func_fatal_configuration arg... +# func_fatal_configuration ARG... +# ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { - func_error ${1+"$@"} - func_error "See the $PACKAGE documentation for more information." - func_fatal_error "Fatal configuration error." + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." } # func_config +# ----------- # Display the configuration for all the tags in this script. func_config () { @@ -915,17 +2149,19 @@ func_config () exit $? } + # func_features +# ------------- # Display the features supported by this script. func_features () { echo "host: $host" - if test "$build_libtool_libs" = yes; then + if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi - if test "$build_old_libs" = yes; then + if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" @@ -934,314 +2170,350 @@ func_features () exit $? } -# func_enable_tag tagname + +# func_enable_tag TAGNAME +# ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { - # Global variable: - tagname="$1" + # Global variable: + tagname=$1 - re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" - re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" - sed_extractcf="/$re_begincf/,/$re_endcf/p" + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p - # Validate tagname. - case $tagname in - *[!-_A-Za-z0-9,/]*) - func_fatal_error "invalid tag name: $tagname" - ;; - esac + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac - # Don't test for the "default" C tag, as we know it's - # there but not specially marked. - case $tagname in - CC) ;; + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; *) - if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then - taglist="$taglist $tagname" + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" - # Evaluate the configuration. Be careful to quote the path - # and the sed script, to avoid splitting on whitespace, but - # also don't use non-portable quotes within backquotes within - # quotes we have to do it in 2 steps: - extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` - eval "$extractedcf" - else - func_error "ignoring unknown tag $tagname" - fi - ;; - esac + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac } + # func_check_version_match +# ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { - if test "$package_revision" != "$macro_revision"; then - if test "$VERSION" != "$macro_version"; then - if test -z "$macro_version"; then - cat >&2 <<_LT_EOF + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF - else - cat >&2 <<_LT_EOF + else + cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF - fi - else - cat >&2 <<_LT_EOF + fi + else + cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF - fi + fi - exit $EXIT_MISMATCH - fi + exit $EXIT_MISMATCH + fi } -# Shorthand for --mode=foo, only valid as the first argument -case $1 in -clean|clea|cle|cl) - shift; set dummy --mode clean ${1+"$@"}; shift - ;; -compile|compil|compi|comp|com|co|c) - shift; set dummy --mode compile ${1+"$@"}; shift - ;; -execute|execut|execu|exec|exe|ex|e) - shift; set dummy --mode execute ${1+"$@"}; shift - ;; -finish|finis|fini|fin|fi|f) - shift; set dummy --mode finish ${1+"$@"}; shift - ;; -install|instal|insta|inst|ins|in|i) - shift; set dummy --mode install ${1+"$@"}; shift - ;; -link|lin|li|l) - shift; set dummy --mode link ${1+"$@"}; shift - ;; -uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) - shift; set dummy --mode uninstall ${1+"$@"}; shift - ;; -esac - - - -# Option defaults: -opt_debug=: -opt_dry_run=false -opt_config=false -opt_preserve_dup_deps=false -opt_features=false -opt_finish=false -opt_help=false -opt_help_all=false -opt_silent=: -opt_warning=: -opt_verbose=: -opt_silent=false -opt_verbose=false - - -# Parse options once, thoroughly. This comes as soon as possible in the -# script to make things like `--version' happen as quickly as we can. +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () { - # this just eases exit handling - while test $# -gt 0; do - opt="$1" - shift - case $opt in - --debug|-x) opt_debug='set -x' - func_echo "enabling shell trace mode" - $opt_debug - ;; - --dry-run|--dryrun|-n) - opt_dry_run=: - ;; - --config) - opt_config=: -func_config - ;; - --dlopen|-dlopen) - optarg="$1" - opt_dlopen="${opt_dlopen+$opt_dlopen -}$optarg" - shift - ;; - --preserve-dup-deps) - opt_preserve_dup_deps=: - ;; - --features) - opt_features=: -func_features - ;; - --finish) - opt_finish=: -set dummy --mode finish ${1+"$@"}; shift - ;; - --help) - opt_help=: - ;; - --help-all) - opt_help_all=: -opt_help=': help-all' - ;; - --mode) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_mode="$optarg" -case $optarg in - # Valid mode arguments: - clean|compile|execute|finish|install|link|relink|uninstall) ;; + $debug_mode - # Catch anything else as an error - *) func_error "invalid argument for $opt" - exit_cmd=exit - break - ;; -esac - shift - ;; - --no-silent|--no-quiet) - opt_silent=false -func_append preserve_args " $opt" - ;; - --no-warning|--no-warn) - opt_warning=false -func_append preserve_args " $opt" - ;; - --no-verbose) - opt_verbose=false -func_append preserve_args " $opt" - ;; - --silent|--quiet) - opt_silent=: -func_append preserve_args " $opt" - opt_verbose=false - ;; - --verbose|-v) - opt_verbose=: -func_append preserve_args " $opt" -opt_silent=false - ;; - --tag) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_tag="$optarg" -func_append preserve_args " $opt $optarg" -func_enable_tag "$optarg" - shift - ;; + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false - -\?|-h) func_usage ;; - --help) func_help ;; - --version) func_version ;; + nonopt= + preserve_args= - # Separate optargs to long options: - --*=*) - func_split_long_opt "$opt" - set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} - shift - ;; - - # Separate non-argument short options: - -\?*|-h*|-n*|-v*) - func_split_short_opt "$opt" - set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - --) break ;; - -*) func_fatal_help "unrecognized option \`$opt'" ;; - *) set dummy "$opt" ${1+"$@"}; shift; break ;; + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; esac - done - # Validate options: - - # save first non-option argument - if test "$#" -gt 0; then - nonopt="$opt" - shift - fi - - # preserve --debug - test "$opt_debug" = : || func_append preserve_args " --debug" - - case $host in - *cygwin* | *mingw* | *pw32* | *cegcc*) - # don't eliminate duplications in $postdeps and $predeps - opt_duplicate_compiler_generated_deps=: - ;; - *) - opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps - ;; - esac - - $opt_help || { - # Sanity checks first: - func_check_version_match - - if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then - func_fatal_configuration "not configured to build any kind of library" - fi - - # Darwin sucks - eval std_shrext=\"$shrext_cmds\" - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$opt_dlopen" && test "$opt_mode" != execute; then - func_error "unrecognized option \`-dlopen'" - $ECHO "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$progname --help --mode=$opt_mode' for more information." - } - - - # Bail if the options were screwed - $exit_cmd $EXIT_FAILURE + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result } +func_add_hook func_options_prep libtool_options_prep +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + ## ----------- ## ## Main. ## ## ----------- ## +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + # func_lalib_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. +# True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && - $SED -e 4q "$1" 2>/dev/null \ - | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. +# True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be -# fatal anyway. Works if `file' does not exist. +# fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no @@ -1249,13 +2521,13 @@ func_lalib_unsafe_p () for lalib_p_l in 1 2 3 4 do read lalib_p_line - case "$lalib_p_line" in + case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi - test "$lalib_p" = yes + test yes = "$lalib_p" } # func_ltwrapper_script_p file @@ -1264,7 +2536,8 @@ func_lalib_unsafe_p () # determined imposters. func_ltwrapper_script_p () { - func_lalib_p "$1" + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file @@ -1289,7 +2562,7 @@ func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" - func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file @@ -1308,11 +2581,13 @@ func_ltwrapper_p () # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { - $opt_debug + $debug_cmd + save_ifs=$IFS; IFS='~' for cmd in $1; do - IFS=$save_ifs + IFS=$sp$nl eval cmd=\"$cmd\" + IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs @@ -1324,10 +2599,11 @@ func_execute_cmds () # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing -# `FILE.' does not work on cygwin managed mounts. +# 'FILE.' does not work on cygwin managed mounts. func_source () { - $opt_debug + $debug_cmd + case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; @@ -1354,10 +2630,10 @@ func_resolve_sysroot () # store the result into func_replace_sysroot_result. func_replace_sysroot () { - case "$lt_sysroot:$1" in + case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" - func_replace_sysroot_result="=$func_stripname_result" + func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. @@ -1374,7 +2650,8 @@ func_replace_sysroot () # arg is usually of the form 'gcc ...' func_infer_tag () { - $opt_debug + $debug_cmd + if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do @@ -1393,7 +2670,7 @@ func_infer_tag () for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. @@ -1418,7 +2695,7 @@ func_infer_tag () # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" - func_fatal_error "specify a tag with \`--tag'" + func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi @@ -1434,15 +2711,15 @@ func_infer_tag () # but don't create it if we're doing a dry run. func_write_libtool_object () { - write_libobj=${1} - if test "$build_libtool_libs" = yes; then - write_lobj=\'${2}\' + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' else write_lobj=none fi - if test "$build_old_libs" = yes; then - write_oldobj=\'${3}\' + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' else write_oldobj=none fi @@ -1450,7 +2727,7 @@ func_write_libtool_object () $opt_dry_run || { cat >${write_libobj}T </dev/null` - if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | - $SED -e "$lt_sed_naive_backslashify"` + $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi @@ -1514,18 +2792,19 @@ func_convert_core_file_wine_to_w32 () # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { - $opt_debug + $debug_cmd + # unfortunately, winepath doesn't convert paths, only file names - func_convert_core_path_wine_to_w32_result="" + func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" - if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then - func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi @@ -1554,7 +2833,8 @@ func_convert_core_path_wine_to_w32 () # environment variable; do not put it in $PATH. func_cygpath () { - $opt_debug + $debug_cmd + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then @@ -1563,7 +2843,7 @@ func_cygpath () fi else func_cygpath_result= - func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath @@ -1574,10 +2854,11 @@ func_cygpath () # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { - $opt_debug + $debug_cmd + # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | - $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 @@ -1588,13 +2869,14 @@ func_convert_core_msys_to_w32 () # func_to_host_file_result to ARG1). func_convert_file_check () { - $opt_debug - if test -z "$2" && test -n "$1" ; then + $debug_cmd + + if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" - func_error " \`$1'" + func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: - func_to_host_file_result="$1" + func_to_host_file_result=$1 fi } # end func_convert_file_check @@ -1606,10 +2888,11 @@ func_convert_file_check () # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { - $opt_debug + $debug_cmd + if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" - func_error " \`$3'" + func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. @@ -1618,7 +2901,7 @@ func_convert_path_check () func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else - func_to_host_path_result="$3" + func_to_host_path_result=$3 fi fi } @@ -1630,9 +2913,10 @@ func_convert_path_check () # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { - $opt_debug + $debug_cmd + case $4 in - $1 ) func_to_host_path_result="$3$func_to_host_path_result" + $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in @@ -1646,7 +2930,7 @@ func_convert_path_front_back_pathsep () ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## -# invoked via `$to_host_file_cmd ARG' +# invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. @@ -1657,7 +2941,8 @@ func_convert_path_front_back_pathsep () # in func_to_host_file_result. func_to_host_file () { - $opt_debug + $debug_cmd + $to_host_file_cmd "$1" } # end func_to_host_file @@ -1669,7 +2954,8 @@ func_to_host_file () # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { - $opt_debug + $debug_cmd + case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 @@ -1687,7 +2973,7 @@ func_to_tool_file () # Copy ARG to func_to_host_file_result. func_convert_file_noop () { - func_to_host_file_result="$1" + func_to_host_file_result=$1 } # end func_convert_file_noop @@ -1698,11 +2984,12 @@ func_convert_file_noop () # func_to_host_file_result. func_convert_file_msys_to_w32 () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" - func_to_host_file_result="$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -1714,8 +3001,9 @@ func_convert_file_msys_to_w32 () # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. @@ -1731,11 +3019,12 @@ func_convert_file_cygwin_to_w32 () # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" - func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -1747,12 +3036,13 @@ func_convert_file_nix_to_w32 () # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" - func_to_host_file_result="$func_cygpath_result" + func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -1765,13 +3055,14 @@ func_convert_file_msys_to_cygwin () # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { - $opt_debug - func_to_host_file_result="$1" + $debug_cmd + + func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" - func_to_host_file_result="$func_cygpath_result" + func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -1781,7 +3072,7 @@ func_convert_file_nix_to_cygwin () ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# -# invoked via `$to_host_path_cmd ARG' +# invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. @@ -1805,10 +3096,11 @@ func_convert_file_nix_to_cygwin () to_host_path_cmd= func_init_to_host_path_cmd () { - $opt_debug + $debug_cmd + if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" - to_host_path_cmd="func_convert_path_${func_stripname_result}" + to_host_path_cmd=func_convert_path_$func_stripname_result fi } @@ -1818,7 +3110,8 @@ func_init_to_host_path_cmd () # in func_to_host_path_result. func_to_host_path () { - $opt_debug + $debug_cmd + func_init_to_host_path_cmd $to_host_path_cmd "$1" } @@ -1829,7 +3122,7 @@ func_to_host_path () # Copy ARG to func_to_host_path_result. func_convert_path_noop () { - func_to_host_path_result="$1" + func_to_host_path_result=$1 } # end func_convert_path_noop @@ -1840,8 +3133,9 @@ func_convert_path_noop () # func_to_host_path_result. func_convert_path_msys_to_w32 () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; @@ -1849,7 +3143,7 @@ func_convert_path_msys_to_w32 () func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" @@ -1863,8 +3157,9 @@ func_convert_path_msys_to_w32 () # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" @@ -1883,14 +3178,15 @@ func_convert_path_cygwin_to_w32 () # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" @@ -1904,15 +3200,16 @@ func_convert_path_nix_to_w32 () # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" - func_to_host_path_result="$func_cygpath_result" + func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" @@ -1927,8 +3224,9 @@ func_convert_path_msys_to_cygwin () # func_to_host_file_result. func_convert_path_nix_to_cygwin () { - $opt_debug - func_to_host_path_result="$1" + $debug_cmd + + func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them @@ -1937,7 +3235,7 @@ func_convert_path_nix_to_cygwin () func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" - func_to_host_path_result="$func_cygpath_result" + func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" @@ -1946,13 +3244,31 @@ func_convert_path_nix_to_cygwin () # end func_convert_path_nix_to_cygwin +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + # func_mode_compile arg... func_mode_compile () { - $opt_debug + $debug_cmd + # Get the compilation command and the source file. base_compile= - srcfile="$nonopt" # always keep a non-empty value in "srcfile" + srcfile=$nonopt # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal @@ -1965,12 +3281,12 @@ func_mode_compile () case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile - lastarg="$arg" + lastarg=$arg arg_mode=normal ;; target ) - libobj="$arg" + libobj=$arg arg_mode=normal continue ;; @@ -1980,7 +3296,7 @@ func_mode_compile () case $arg in -o) test -n "$libobj" && \ - func_fatal_error "you cannot specify \`-o' more than once" + func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; @@ -2009,12 +3325,12 @@ func_mode_compile () func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= - save_ifs="$IFS"; IFS=',' + save_ifs=$IFS; IFS=, for arg in $args; do - IFS="$save_ifs" + IFS=$save_ifs func_append_quoted lastarg "$arg" done - IFS="$save_ifs" + IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result @@ -2027,8 +3343,8 @@ func_mode_compile () # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # - lastarg="$srcfile" - srcfile="$arg" + lastarg=$srcfile + srcfile=$arg ;; esac # case $arg ;; @@ -2043,13 +3359,13 @@ func_mode_compile () func_fatal_error "you must specify an argument for -Xcompile" ;; target) - func_fatal_error "you must specify a target with \`-o'" + func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" - libobj="$func_basename_result" + libobj=$func_basename_result } ;; esac @@ -2069,7 +3385,7 @@ func_mode_compile () case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) - func_fatal_error "cannot determine name of library object from \`$libobj'" + func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac @@ -2078,8 +3394,8 @@ func_mode_compile () for arg in $later; do case $arg in -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; @@ -2105,17 +3421,17 @@ func_mode_compile () func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ - && func_warning "libobj name \`$libobj' may not contain shell special characters." + && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" - objname="$func_basename_result" - xdir="$func_dirname_result" - lobj=${xdir}$objdir/$objname + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. - if test "$build_old_libs" = yes; then + if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" @@ -2127,16 +3443,16 @@ func_mode_compile () pic_mode=default ;; esac - if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c - if test "$compiler_c_o" = no; then - output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} - lockfile="$output_obj.lock" + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock else output_obj= need_locks=no @@ -2145,12 +3461,12 @@ func_mode_compile () # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file - if test "$need_locks" = yes; then + if test yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done - elif test "$need_locks" = warn; then + elif test warn = "$need_locks"; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: @@ -2158,7 +3474,7 @@ func_mode_compile () This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you +your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." @@ -2180,11 +3496,11 @@ compiler." qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. - if test "$build_libtool_libs" = yes; then + if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile - if test "$pic_mode" != no; then + if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code @@ -2201,7 +3517,7 @@ compiler." func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' - if test "$need_locks" = warn && + if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: @@ -2212,7 +3528,7 @@ $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you +your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." @@ -2228,20 +3544,20 @@ compiler." fi # Allow error messages only from the first compilation. - if test "$suppress_opt" = yes; then + if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. - if test "$build_old_libs" = yes; then - if test "$pic_mode" != yes; then + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi - if test "$compiler_c_o" = yes; then + if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi @@ -2250,7 +3566,7 @@ compiler." func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' - if test "$need_locks" = warn && + if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: @@ -2261,7 +3577,7 @@ $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you +your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." @@ -2281,7 +3597,7 @@ compiler." func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked - if test "$need_locks" != no; then + if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi @@ -2291,7 +3607,7 @@ compiler." } $opt_help || { - test "$opt_mode" = compile && func_mode_compile ${1+"$@"} + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () @@ -2311,7 +3627,7 @@ func_mode_help () Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated @@ -2330,16 +3646,16 @@ This mode accepts the following additional options: -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only - -shared do not build a \`.o' file suitable for static linking - -static only build a \`.o' file suitable for static linking + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler -COMPILE-COMMAND is a command to be used in creating a \`standard' object file +COMPILE-COMMAND is a command to be used in creating a 'standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix \`.c' with the -library object suffix, \`.lo'." +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." ;; execute) @@ -2352,7 +3668,7 @@ This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path -This mode sets the library path environment variable according to \`-dlopen' +This mode sets the library path environment variable according to '-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated @@ -2371,7 +3687,7 @@ Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use -the \`--dry-run' option if you just want to see what would be executed." +the '--dry-run' option if you just want to see what would be executed." ;; install) @@ -2381,7 +3697,7 @@ the \`--dry-run' option if you just want to see what would be executed." Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be -either the \`install' or \`cp' program. +either the 'install' or 'cp' program. The following components of INSTALL-COMMAND are treated specially: @@ -2407,7 +3723,7 @@ The following components of LINK-COMMAND are treated specially: -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) - -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE @@ -2421,7 +3737,8 @@ The following components of LINK-COMMAND are treated specially: -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE Use a list of object files found in FILE to specify objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information @@ -2441,20 +3758,20 @@ The following components of LINK-COMMAND are treated specially: -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) -All other options (arguments beginning with \`-') are ignored. +All other options (arguments beginning with '-') are ignored. -Every other argument is treated as a filename. Files ending in \`.la' are +Every other argument is treated as a filename. Files ending in '.la' are treated as uninstalled libtool libraries, other files are standard or library object files. -If the OUTPUT-FILE ends in \`.la', then a libtool library is created, -only library objects (\`.lo' files) may be specified, and \`-rpath' is +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is required, except when creating a convenience library. -If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created -using \`ar' and \`ranlib', or on Windows using \`lib'. +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. -If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file is created, otherwise an executable program is created." ;; @@ -2465,7 +3782,7 @@ is created, otherwise an executable program is created." Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. @@ -2473,17 +3790,17 @@ Otherwise, only FILE itself is deleted using RM." ;; *) - func_fatal_help "invalid operation mode \`$opt_mode'" + func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo - $ECHO "Try \`$progname --help' for more information about other modes." + $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then - if test "$opt_help" = :; then + if test : = "$opt_help"; then func_mode_help else { @@ -2491,7 +3808,7 @@ if $opt_help; then for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done - } | sed -n '1p; 2,$s/^Usage:/ or: /p' + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do @@ -2499,7 +3816,7 @@ if $opt_help; then func_mode_help done } | - sed '1d + $SED '1d /^When reporting/,/^Report/{ H d @@ -2516,16 +3833,17 @@ fi # func_mode_execute arg... func_mode_execute () { - $opt_debug + $debug_cmd + # The first argument is the command name. - cmd="$nonopt" + cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ - || func_fatal_help "\`$file' is not a file" + || func_fatal_help "'$file' is not a file" dir= case $file in @@ -2535,7 +3853,7 @@ func_mode_execute () # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$lib' is not a valid libtool archive" + || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= @@ -2546,18 +3864,18 @@ func_mode_execute () if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ - func_warning "\`$file' was not linked with \`-export-dynamic'" + func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." - dir="$func_dirname_result" + dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then - func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; @@ -2565,18 +3883,18 @@ func_mode_execute () *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." - dir="$func_dirname_result" + dir=$func_dirname_result ;; *) - func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir="$absdir" + test -n "$absdir" && dir=$absdir # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then @@ -2588,7 +3906,7 @@ func_mode_execute () # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. - libtool_execute_magic="$magic" + libtool_execute_magic=$magic # Check if any of the arguments is a wrapper script. args= @@ -2601,12 +3919,12 @@ func_mode_execute () if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. - file="$progdir/$program" + file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. - file="$progdir/$program" + file=$progdir/$program fi ;; esac @@ -2614,7 +3932,15 @@ func_mode_execute () func_append_quoted args "$file" done - if test "X$opt_dry_run" = Xfalse; then + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" @@ -2631,25 +3957,18 @@ func_mode_execute () done # Now prepare to actually exec the command. - exec_cmd="\$cmd$args" - else - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" - echo "export $shlibpath_var" - fi - $ECHO "$cmd$args" - exit $EXIT_SUCCESS + exec_cmd=\$cmd$args fi } -test "$opt_mode" = execute && func_mode_execute ${1+"$@"} +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { - $opt_debug + $debug_cmd + libs= libdirs= admincmds= @@ -2663,11 +3982,11 @@ func_mode_finish () if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else - func_warning "\`$opt' is not a valid libtool archive" + func_warning "'$opt' is not a valid libtool archive" fi else - func_fatal_error "invalid argument \`$opt'" + func_fatal_error "invalid argument '$opt'" fi done @@ -2682,12 +4001,12 @@ func_mode_finish () # Remove sysroot references if $opt_dry_run; then for lib in $libs; do - echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do - sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done @@ -2712,7 +4031,7 @@ func_mode_finish () fi # Exit here if they wanted silent mode. - $opt_silent && exit $EXIT_SUCCESS + $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" @@ -2723,27 +4042,27 @@ func_mode_finish () echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" - echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then - echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " - add LIBDIR to the '$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then - echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " - add LIBDIR to the '$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" - $ECHO " - use the \`$flag' linker flag" + $ECHO " - use the '$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then - echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" fi echo @@ -2762,18 +4081,20 @@ func_mode_finish () exit $EXIT_SUCCESS } -test "$opt_mode" = finish && func_mode_finish ${1+"$@"} +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { - $opt_debug + $debug_cmd + # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). - if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. - case $nonopt in *shtool*) :;; *) false;; esac; then + case $nonopt in *shtool*) :;; *) false;; esac + then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " @@ -2800,7 +4121,7 @@ func_mode_install () opts= prev= install_type= - isdir=no + isdir=false stripme= no_mode=: for arg @@ -2813,7 +4134,7 @@ func_mode_install () fi case $arg in - -d) isdir=yes ;; + -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg @@ -2831,7 +4152,7 @@ func_mode_install () *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then - if test "x$prev" = x-m && test -n "$install_override_mode"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi @@ -2856,7 +4177,7 @@ func_mode_install () func_fatal_help "you must specify an install program" test -n "$prev" && \ - func_fatal_help "the \`$prev' option requires an argument" + func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else @@ -2878,19 +4199,19 @@ func_mode_install () dest=$func_stripname_result # Check to see that the destination is a directory. - test -d "$dest" && isdir=yes - if test "$isdir" = yes; then - destdir="$dest" + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." - destdir="$func_dirname_result" - destname="$func_basename_result" + destdir=$func_dirname_result + destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ - func_fatal_help "\`$dest' is not a directory" + func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; @@ -2899,7 +4220,7 @@ func_mode_install () case $file in *.lo) ;; *) - func_fatal_help "\`$destdir' must be an absolute directory name" + func_fatal_help "'$destdir' must be an absolute directory name" ;; esac done @@ -2908,7 +4229,7 @@ func_mode_install () # This variable tells wrapper scripts just to set variables rather # than running their programs. - libtool_install_magic="$magic" + libtool_install_magic=$magic staticlibs= future_libdirs= @@ -2928,7 +4249,7 @@ func_mode_install () # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$file' is not a valid libtool archive" + || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= @@ -2950,7 +4271,7 @@ func_mode_install () fi func_dirname "$file" "/" "" - dir="$func_dirname_result" + dir=$func_dirname_result func_append dir "$objdir" if test -n "$relink_command"; then @@ -2964,7 +4285,7 @@ func_mode_install () # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ - func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. @@ -2973,29 +4294,36 @@ func_mode_install () relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi - func_warning "relinking \`$file'" + func_warning "relinking '$file'" func_show_eval "$relink_command" \ - 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then - realname="$1" + realname=$1 shift - srcname="$realname" - test -n "$relink_command" && srcname="$realname"T + srcname=$realname + test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' - tstripme="$stripme" + tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) - tstripme="" + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= ;; esac ;; @@ -3006,7 +4334,7 @@ func_mode_install () if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. - # Try `ln -sf' first, because the `ln' binary might depend on + # Try 'ln -sf' first, because the 'ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname @@ -3017,14 +4345,14 @@ func_mode_install () fi # Do each command in the postinstall commands. - lib="$destdir/$realname" + lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" - name="$func_basename_result" - instname="$dir/$name"i + name=$func_basename_result + instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. @@ -3036,11 +4364,11 @@ func_mode_install () # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then - destfile="$destdir/$destname" + destfile=$destdir/$destname else func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" + destfile=$func_basename_result + destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. @@ -3050,11 +4378,11 @@ func_mode_install () staticdest=$func_lo2o_result ;; *.$objext) - staticdest="$destfile" + staticdest=$destfile destfile= ;; *) - func_fatal_help "cannot copy a libtool object to \`$destfile'" + func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac @@ -3063,7 +4391,7 @@ func_mode_install () func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. - if test "$build_old_libs" = yes; then + if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result @@ -3075,23 +4403,23 @@ func_mode_install () *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then - destfile="$destdir/$destname" + destfile=$destdir/$destname else func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" + destfile=$func_basename_result + destfile=$destdir/$destfile fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install - stripped_ext="" + stripped_ext= case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result - stripped_ext=".exe" + stripped_ext=.exe fi ;; esac @@ -3119,19 +4447,19 @@ func_mode_install () # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ - func_fatal_error "invalid libtool wrapper script \`$wrapper'" + func_fatal_error "invalid libtool wrapper script '$wrapper'" - finalize=yes + finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi - libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then - func_warning "\`$lib' has not been installed in \`$libdir'" - finalize=no + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false fi done @@ -3139,29 +4467,29 @@ func_mode_install () func_source "$wrapper" outputname= - if test "$fast_install" = no && test -n "$relink_command"; then + if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { - if test "$finalize" = yes; then + if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" - file="$func_basename_result" - outputname="$tmpdir/$file" + file=$func_basename_result + outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` - $opt_silent || { + $opt_quiet || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else - func_error "error: relink \`$file' with the above command before installing it" + func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi - file="$outputname" + file=$outputname else - func_warning "cannot relink \`$file'" + func_warning "cannot relink '$file'" fi } else @@ -3198,10 +4526,10 @@ func_mode_install () for file in $staticlibs; do func_basename "$file" - name="$func_basename_result" + name=$func_basename_result # Set up the ranlib parameters. - oldlib="$destdir/$name" + oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result @@ -3216,18 +4544,18 @@ func_mode_install () done test -n "$future_libdirs" && \ - func_warning "remember to run \`$progname --finish$future_libdirs'" + func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } -test "$opt_mode" = install && func_mode_install ${1+"$@"} +test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p @@ -3235,16 +4563,17 @@ test "$opt_mode" = install && func_mode_install ${1+"$@"} # a dlpreopen symbol table. func_generate_dlsyms () { - $opt_debug - my_outputname="$1" - my_originator="$2" - my_pic_p="${3-no}" - my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then - my_dlsyms="${my_outputname}S.c" + my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi @@ -3255,7 +4584,7 @@ func_generate_dlsyms () "") ;; *.c) # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${my_outputname}.nm" + nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" @@ -3263,34 +4592,36 @@ func_generate_dlsyms () func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ -/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ -/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif -#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST -#elif defined(__osf__) +#elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + /* External symbol declarations for the compiler. */\ " - if test "$dlself" = yes; then - func_verbose "generating symbol list for \`$output'" + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" @@ -3298,7 +4629,7 @@ extern \"C\" { progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 - func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done @@ -3318,10 +4649,10 @@ extern \"C\" { # Prepare the list of exported symbols if test -z "$export_symbols"; then - export_symbols="$output_objdir/$outputname.exp" + export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols - eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' @@ -3331,7 +4662,7 @@ extern \"C\" { } else $opt_dry_run || { - eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in @@ -3345,22 +4676,22 @@ extern \"C\" { fi for dlprefile in $dlprefiles; do - func_verbose "extracting global C symbols from \`$dlprefile'" + func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" - name="$func_basename_result" + name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" - dlprefile_dlbasename="" + dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` - if test -n "$dlprefile_dlname" ; then + if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" - dlprefile_dlbasename="$func_basename_result" + dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" @@ -3368,7 +4699,7 @@ extern \"C\" { fi fi $opt_dry_run || { - if test -n "$dlprefile_dlbasename" ; then + if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" @@ -3424,6 +4755,11 @@ extern \"C\" { echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ @@ -3432,11 +4768,30 @@ typedef struct { void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[]; +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = -{\ - { \"$my_originator\", (void *) 0 }," +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi case $need_lib_prefix in no) @@ -3478,9 +4833,7 @@ static const void *lt_preloaded_setup() { *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) - if test "X$my_pic_p" != Xno; then - pic_flag_for_symtable=" $pic_flag" - fi + $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; @@ -3497,10 +4850,10 @@ static const void *lt_preloaded_setup() { func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. - func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. - symfileobj="$output_objdir/${my_outputname}S.$objext" + symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then @@ -3518,7 +4871,7 @@ static const void *lt_preloaded_setup() { esac ;; *) - func_fatal_error "unknown suffix for \`$my_dlsyms'" + func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else @@ -3532,6 +4885,32 @@ static const void *lt_preloaded_setup() { fi } +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + # func_win32_libid arg # return the library type of file 'arg' # @@ -3541,8 +4920,9 @@ static const void *lt_preloaded_setup() { # Despite the name, also deal with 64 bit binaries. func_win32_libid () { - $opt_debug - win32_libid_type="unknown" + $debug_cmd + + win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import @@ -3552,16 +4932,29 @@ func_win32_libid () # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then - func_to_tool_file "$1" func_convert_file_msys_to_w32 - win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | - $SED -n -e ' + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' 1,100{ / I /{ - s,.*,import, + s|.*|import| p q } }'` + ;; + esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; @@ -3593,7 +4986,8 @@ func_win32_libid () # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { - $opt_debug + $debug_cmd + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } @@ -3610,7 +5004,8 @@ func_cygming_dll_for_implib () # specified import library. func_cygming_dll_for_implib_fallback_core () { - $opt_debug + $debug_cmd + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ @@ -3646,8 +5041,8 @@ func_cygming_dll_for_implib_fallback_core () /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the - # archive which possess that section. Heuristic: eliminate - # all those which have a first or second character that is + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually @@ -3658,30 +5053,6 @@ func_cygming_dll_for_implib_fallback_core () $SED -e '/^\./d;/^.\./d;q' } -# func_cygming_gnu_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is a GNU/binutils-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_gnu_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` - test -n "$func_cygming_gnu_implib_tmp" -} - -# func_cygming_ms_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is an MS-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_ms_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` - test -n "$func_cygming_ms_implib_tmp" -} - # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified @@ -3695,16 +5066,17 @@ func_cygming_ms_implib_p () # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { - $opt_debug - if func_cygming_gnu_implib_p "$1" ; then + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` - elif func_cygming_ms_implib_p "$1" ; then + elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown - sharedlib_from_linklib_result="" + sharedlib_from_linklib_result= fi } @@ -3712,10 +5084,11 @@ func_cygming_dll_for_implib_fallback () # func_extract_an_archive dir oldlib func_extract_an_archive () { - $opt_debug - f_ex_an_ar_dir="$1"; shift - f_ex_an_ar_oldlib="$1" - if test "$lock_old_archive_extraction" = yes; then + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" @@ -3724,7 +5097,7 @@ func_extract_an_archive () fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' - if test "$lock_old_archive_extraction" = yes; then + if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then @@ -3738,22 +5111,23 @@ func_extract_an_archive () # func_extract_archives gentop oldlib ... func_extract_archives () { - $opt_debug - my_gentop="$1"; shift + $debug_cmd + + my_gentop=$1; shift my_oldlibs=${1+"$@"} - my_oldobjs="" - my_xlib="" - my_xabs="" - my_xdir="" + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in - [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" - my_xlib="$func_basename_result" + my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in @@ -3765,7 +5139,7 @@ func_extract_archives () esac done extracted_archives="$extracted_archives $my_xlib_u" - my_xdir="$my_gentop/$my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" @@ -3778,22 +5152,23 @@ func_extract_archives () cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` - darwin_base_archive=`basename "$darwin_archive"` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" - for darwin_arch in $darwin_arches ; do - func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" - $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" - cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" - func_extract_an_archive "`pwd`" "${darwin_base_archive}" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" - $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) - darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do @@ -3815,7 +5190,7 @@ func_extract_archives () my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done - func_extract_archives_result="$my_oldobjs" + func_extract_archives_result=$my_oldobjs } @@ -3830,7 +5205,7 @@ func_extract_archives () # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script -# will assume that the directory in which it is stored is +# will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () @@ -3841,7 +5216,7 @@ func_emit_wrapper () #! $SHELL # $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. @@ -3898,9 +5273,9 @@ _LTECHO_EOF' # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ which is used only on +# /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" -# (application programs are unlikely to have options which match +# (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and @@ -3933,7 +5308,7 @@ func_parse_lt_options () # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then - echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } @@ -3944,7 +5319,7 @@ func_lt_dump_args () lt_dump_args_N=1; for lt_arg do - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } @@ -3958,7 +5333,7 @@ func_exec_program_core () *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} @@ -3968,7 +5343,7 @@ func_exec_program_core () *) $ECHO "\ if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} @@ -4043,13 +5418,13 @@ func_exec_program () test -n \"\$absdir\" && thisdir=\"\$absdir\" " - if test "$fast_install" = yes; then + if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" @@ -4066,7 +5441,7 @@ func_exec_program () if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else - $ECHO \"\$relink_command_output\" >&2 + \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi @@ -4101,7 +5476,7 @@ func_exec_program () fi # Export our shlibpath_var if we have one. - if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" @@ -4121,7 +5496,7 @@ func_exec_program () fi else # The program doesn't exist. - \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 @@ -4140,7 +5515,7 @@ func_emit_cwrapperexe_src () cat < #include +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + /* declarations of non-ANSI functions */ -#if defined(__MINGW32__) +#if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif -#elif defined(__CYGWIN__) +#elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif -/* #elif defined (other platforms) ... */ +/* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ -#if defined(_MSC_VER) +#if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC -# ifndef _INTPTR_T_DEFINED -# define _INTPTR_T_DEFINED -# define intptr_t int -# endif -#elif defined(__MINGW32__) +#elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv -#elif defined(__CYGWIN__) +#elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" -/* #elif defined (other platforms) ... */ +/* #elif defined other platforms ... */ #endif -#if defined(PATH_MAX) +#if defined PATH_MAX # define LT_PATHMAX PATH_MAX -#elif defined(MAXPATHLEN) +#elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 @@ -4234,8 +5607,8 @@ int setenv (const char *, const char *, int); # define PATH_SEPARATOR ':' #endif -#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ - defined (__OS2__) +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 @@ -4268,10 +5641,10 @@ int setenv (const char *, const char *, int); #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ - if (stale) { free ((void *) stale); stale = 0; } \ + if (stale) { free (stale); stale = 0; } \ } while (0) -#if defined(LT_DEBUGWRAPPER) +#if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; @@ -4300,11 +5673,16 @@ void lt_dump_script (FILE *f); EOF cat < 0) && IS_PATH_SEPARATOR (new_value[len-1])) + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { - new_value[len-1] = '\0'; + new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); @@ -5082,27 +6460,47 @@ EOF # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { - $opt_debug + $debug_cmd + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + # func_mode_link arg... func_mode_link () { - $opt_debug + $debug_cmd + case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out - # which system we are compiling for in order to pass an extra + # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying - # to make a dll which has undefined symbols, in which case not + # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. @@ -5146,10 +6544,11 @@ func_mode_link () module=no no_install=no objs= + os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no - preload=no + preload=false prev= prevarg= release= @@ -5161,7 +6560,7 @@ func_mode_link () vinfo= vinfo_number=no weak_libs= - single_module="${wl}-single_module" + single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. @@ -5169,15 +6568,15 @@ func_mode_link () do case $arg in -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) - if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then @@ -5210,7 +6609,7 @@ func_mode_link () # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do - arg="$1" + arg=$1 shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result @@ -5227,21 +6626,21 @@ func_mode_link () case $prev in bindir) - bindir="$arg" + bindir=$arg prev= continue ;; dlfiles|dlprefiles) - if test "$preload" = no; then + $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" - preload=yes - fi + preload=: + } case $arg in *.la | *.lo) ;; # We handle these cases below. force) - if test "$dlself" = no; then + if test no = "$dlself"; then dlself=needless export_dynamic=yes fi @@ -5249,9 +6648,9 @@ func_mode_link () continue ;; self) - if test "$prev" = dlprefiles; then + if test dlprefiles = "$prev"; then dlself=yes - elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless @@ -5261,7 +6660,7 @@ func_mode_link () continue ;; *) - if test "$prev" = dlfiles; then + if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" @@ -5272,14 +6671,14 @@ func_mode_link () esac ;; expsyms) - export_symbols="$arg" + export_symbols=$arg test -f "$arg" \ - || func_fatal_error "symbol file \`$arg' does not exist" + || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) - export_symbols_regex="$arg" + export_symbols_regex=$arg prev= continue ;; @@ -5297,7 +6696,13 @@ func_mode_link () continue ;; inst_prefix) - inst_prefix_dir="$arg" + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. prev= continue ;; @@ -5321,21 +6726,21 @@ func_mode_link () if test -z "$pic_object" || test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir="$func_dirname_result" + xdir=$func_dirname_result - if test "$pic_object" != none; then + if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" + pic_object=$xdir$pic_object - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue @@ -5346,7 +6751,7 @@ func_mode_link () fi # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then + if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= @@ -5354,23 +6759,23 @@ func_mode_link () # A PIC object. func_append libobjs " $pic_object" - arg="$pic_object" + arg=$pic_object fi # Non-PIC object. - if test "$non_pic_object" != none; then + if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" + non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" + non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else @@ -5378,7 +6783,7 @@ func_mode_link () if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir="$func_dirname_result" + xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result @@ -5386,24 +6791,29 @@ func_mode_link () func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else - func_fatal_error "\`$arg' is not a valid libtool object" + func_fatal_error "'$arg' is not a valid libtool object" fi fi done else - func_fatal_error "link input file \`$arg' does not exist" + func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; precious_regex) - precious_files_regex="$arg" + precious_files_regex=$arg prev= continue ;; release) - release="-$arg" + release=-$arg prev= continue ;; @@ -5415,7 +6825,7 @@ func_mode_link () func_fatal_error "only absolute run-paths are allowed" ;; esac - if test "$prev" = rpath; then + if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; @@ -5430,7 +6840,7 @@ func_mode_link () continue ;; shrext) - shrext_cmds="$arg" + shrext_cmds=$arg prev= continue ;; @@ -5470,7 +6880,7 @@ func_mode_link () esac fi # test -n "$prev" - prevarg="$arg" + prevarg=$arg case $arg in -all-static) @@ -5484,7 +6894,7 @@ func_mode_link () -allow-undefined) # FIXME: remove this flag sometime in the future. - func_fatal_error "\`-allow-undefined' must not be used because it is the default" + func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) @@ -5516,7 +6926,7 @@ func_mode_link () if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi - if test "X$arg" = "X-export-symbols"; then + if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex @@ -5550,9 +6960,9 @@ func_mode_link () func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then - func_fatal_error "require no space between \`-L' and \`$1'" + func_fatal_error "require no space between '-L' and '$1'" else - func_fatal_error "need path for \`-L' option" + func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" @@ -5563,8 +6973,8 @@ func_mode_link () *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ - func_fatal_error "cannot determine absolute directory name of \`$dir'" - dir="$absdir" + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir ;; esac case "$deplibs " in @@ -5599,7 +7009,7 @@ func_mode_link () ;; -l*) - if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) @@ -5607,11 +7017,11 @@ func_mode_link () ;; *-*-os2*) # These systems don't actually have a C library (as such) - test "X$arg" = "X-lc" && continue + test X-lc = "X$arg" && continue ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc due to us having libc/libc_r. - test "X$arg" = "X-lc" && continue + test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework @@ -5620,16 +7030,16 @@ func_mode_link () ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype - test "X$arg" = "X-lc" && continue + test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work - test "X$arg" = "X-lc" && continue + test X-lc = "X$arg" && continue ;; esac - elif test "X$arg" = "X-lc_r"; then + elif test X-lc_r = "X$arg"; then case $host in - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc_r directly, use -pthread flag. continue ;; @@ -5639,6 +7049,11 @@ func_mode_link () continue ;; + -mllvm) + prev=mllvm + continue + ;; + -module) module=yes continue @@ -5668,7 +7083,7 @@ func_mode_link () ;; -multi_module) - single_module="${wl}-multi_module" + single_module=$wl-multi_module continue ;; @@ -5682,8 +7097,8 @@ func_mode_link () *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. - func_warning "\`-no-install' is ignored for $host" - func_warning "assuming \`-no-fast-install' instead" + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; @@ -5701,6 +7116,11 @@ func_mode_link () continue ;; + -os2dllname) + prev=os2dllname + continue + ;; + -o) prev=output ;; -precious-files-regex) @@ -5788,14 +7208,14 @@ func_mode_link () func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= - save_ifs="$IFS"; IFS=',' + save_ifs=$IFS; IFS=, for flag in $args; do - IFS="$save_ifs" + IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done - IFS="$save_ifs" + IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; @@ -5804,15 +7224,15 @@ func_mode_link () func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= - save_ifs="$IFS"; IFS=',' + save_ifs=$IFS; IFS=, for flag in $args; do - IFS="$save_ifs" + IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done - IFS="$save_ifs" + IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; @@ -5835,7 +7255,7 @@ func_mode_link () # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" + arg=$func_quote_for_eval_result ;; # Flags to be passed through unchanged, with rationale: @@ -5847,26 +7267,46 @@ func_mode_link () # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support - # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -stdlib=* select c++ std lib with clang -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-flto*|-fwhopr*|-fuse-linker-plugin|-stdlib=*) + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" + arg=$func_quote_for_eval_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" + arg=$func_quote_for_eval_result ;; *.$objext) @@ -5887,21 +7327,21 @@ func_mode_link () if test -z "$pic_object" || test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir="$func_dirname_result" + xdir=$func_dirname_result - if test "$pic_object" != none; then + test none = "$pic_object" || { # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" + pic_object=$xdir$pic_object - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue @@ -5912,7 +7352,7 @@ func_mode_link () fi # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then + if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= @@ -5920,23 +7360,23 @@ func_mode_link () # A PIC object. func_append libobjs " $pic_object" - arg="$pic_object" - fi + arg=$pic_object + } # Non-PIC object. - if test "$non_pic_object" != none; then + if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" + non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" + non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else @@ -5944,7 +7384,7 @@ func_mode_link () if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir="$func_dirname_result" + xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result @@ -5952,7 +7392,7 @@ func_mode_link () func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else - func_fatal_error "\`$arg' is not a valid libtool object" + func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; @@ -5968,11 +7408,11 @@ func_mode_link () # A libtool-controlled library. func_resolve_sysroot "$arg" - if test "$prev" = dlfiles; then + if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= - elif test "$prev" = dlprefiles; then + elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= @@ -5987,7 +7427,7 @@ func_mode_link () # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" + arg=$func_quote_for_eval_result ;; esac # arg @@ -5999,9 +7439,9 @@ func_mode_link () done # argument parsing loop test -n "$prev" && \ - func_fatal_help "the \`$prevarg' option requires an argument" + func_fatal_help "the '$prevarg' option requires an argument" - if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" @@ -6010,20 +7450,23 @@ func_mode_link () oldlibs= # calculate the name of the file, without its directory func_basename "$output" - outputname="$func_basename_result" - libobjs_save="$libobjs" + outputname=$func_basename_result + libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + func_dirname "$output" "/" "" - output_objdir="$func_dirname_result$objdir" + output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. @@ -6046,7 +7489,7 @@ func_mode_link () # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do - if $opt_preserve_dup_deps ; then + if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac @@ -6054,7 +7497,7 @@ func_mode_link () func_append libs " $deplib" done - if test "$linkmode" = lib; then + if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps @@ -6086,7 +7529,7 @@ func_mode_link () case $file in *.la) ;; *) - func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done @@ -6094,7 +7537,7 @@ func_mode_link () prog) compile_deplibs= finalize_deplibs= - alldeplibs=no + alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" @@ -6106,29 +7549,29 @@ func_mode_link () for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... - if test "$linkmode,$pass" = "lib,link"; then + if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done - deplibs="$tmp_deplibs" + deplibs=$tmp_deplibs fi - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan"; then - libs="$deplibs" + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs deplibs= fi - if test "$linkmode" = prog; then + if test prog = "$linkmode"; then case $pass in - dlopen) libs="$dlfiles" ;; - dlpreopen) libs="$dlprefiles" ;; + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi - if test "$linkmode,$pass" = "lib,dlpreopen"; then + if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs @@ -6149,26 +7592,26 @@ func_mode_link () esac done done - libs="$dlprefiles" + libs=$dlprefiles fi - if test "$pass" = dlopen; then + if test dlopen = "$pass"; then # Collect dlpreopened libraries - save_deplibs="$deplibs" + save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= - found=no + found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - if test "$linkmode,$pass" = "prog,link"; then + if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" - if test "$linkmode" = lib ; then + if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; @@ -6178,13 +7621,13 @@ func_mode_link () continue ;; -l*) - if test "$linkmode" != lib && test "$linkmode" != prog; then - func_warning "\`-l' is ignored for archives/objects" + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result - if test "$linkmode" = lib; then + if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" @@ -6192,31 +7635,22 @@ func_mode_link () for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library - lib="$searchdir/lib${name}${search_ext}" + lib=$searchdir/lib$name$search_ext if test -f "$lib"; then - if test "$search_ext" = ".la"; then - found=yes + if test .la = "$search_ext"; then + found=: else - found=no + found=false fi break 2 fi done done - if test "$found" != yes; then - # deplib doesn't seem to be a libtool library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - else # deplib is a libtool library + if $found; then + # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then @@ -6224,19 +7658,19 @@ func_mode_link () old_library= func_source "$lib" for l in $old_library $library_names; do - ll="$l" + ll=$l done - if test "X$ll" = "X$old_library" ; then # only static version available - found=no + if test "X$ll" = "X$old_library"; then # only static version available + found=false func_dirname "$lib" "" "." - ladir="$func_dirname_result" + ladir=$func_dirname_result lib=$ladir/$old_library - if test "$linkmode,$pass" = "prog,link"; then + if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi @@ -6245,15 +7679,25 @@ func_mode_link () *) ;; esac fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue fi ;; # -l *.ltframework) - if test "$linkmode,$pass" = "prog,link"; then + if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" - if test "$linkmode" = lib ; then + if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; @@ -6266,18 +7710,18 @@ func_mode_link () case $linkmode in lib) deplibs="$deplib $deplibs" - test "$pass" = conv && continue + test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) - if test "$pass" = conv; then + if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi - if test "$pass" = scan; then + if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" @@ -6288,13 +7732,13 @@ func_mode_link () func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) - func_warning "\`-L' is ignored for archives/objects" + func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) - if test "$pass" = link; then + if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result @@ -6312,7 +7756,7 @@ func_mode_link () lib=$func_resolve_sysroot_result ;; *.$libext) - if test "$pass" = conv; then + if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi @@ -6323,21 +7767,26 @@ func_mode_link () case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) - valid_a_lib=no + valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then - valid_a_lib=yes + valid_a_lib=: fi ;; pass_all) - valid_a_lib=yes + valid_a_lib=: ;; esac - if test "$valid_a_lib" != yes; then + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" @@ -6345,18 +7794,13 @@ func_mode_link () echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." - else - echo - $ECHO "*** Warning: Linking the shared library $output against the" - $ECHO "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) - if test "$pass" != link; then + if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" @@ -6367,10 +7811,10 @@ func_mode_link () esac # linkmode ;; # *.$libext *.lo | *.$objext) - if test "$pass" = conv; then + if test conv = "$pass"; then deplibs="$deplib $deplibs" - elif test "$linkmode" = prog; then - if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" @@ -6383,22 +7827,20 @@ func_mode_link () continue ;; %DEPLIBS%) - alldeplibs=yes + alldeplibs=: continue ;; esac # case $deplib - if test "$found" = yes || test -f "$lib"; then : - else - func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" - fi + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ - || func_fatal_error "\`$lib' is not a valid libtool archive" + || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." - ladir="$func_dirname_result" + ladir=$func_dirname_result dlname= dlopen= @@ -6428,30 +7870,30 @@ func_mode_link () done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan" || - { test "$linkmode" != prog && test "$linkmode" != lib; }; then + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi - if test "$pass" = conv; then + if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then - func_fatal_error "cannot find name of link library for \`$lib'" + func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" - elif test "$linkmode" != prog && test "$linkmode" != lib; then - func_fatal_error "\`$lib' is not a convenience library" + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps ; then + if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac @@ -6465,26 +7907,26 @@ func_mode_link () # Get the name of the library we link against. linklib= if test -n "$old_library" && - { test "$prefer_static_libs" = yes || - test "$prefer_static_libs,$installed" = "built,no"; }; then + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do - linklib="$l" + linklib=$l done fi if test -z "$linklib"; then - func_fatal_error "cannot find name of link library for \`$lib'" + func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. - if test "$pass" = dlopen; then - if test -z "$libdir"; then - func_fatal_error "cannot -dlopen a convenience library: \`$lib'" - fi + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || - test "$dlopen_support" != yes || - test "$build_libtool_libs" = no; then + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't @@ -6498,40 +7940,40 @@ func_mode_link () # We need an absolute path. case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then - func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" - abs_ladir="$ladir" + abs_ladir=$ladir fi ;; esac func_basename "$lib" - laname="$func_basename_result" + laname=$func_basename_result # Find the relevant object directory and library name. - if test "X$installed" = Xyes; then + if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - func_warning "library \`$lib' was moved." - dir="$ladir" - absdir="$abs_ladir" - libdir="$abs_ladir" + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir else - dir="$lt_sysroot$libdir" - absdir="$lt_sysroot$libdir" + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir fi - test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then - dir="$ladir" - absdir="$abs_ladir" + dir=$ladir + absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else - dir="$ladir/$objdir" - absdir="$abs_ladir/$objdir" + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi @@ -6540,11 +7982,11 @@ func_mode_link () name=$func_stripname_result # This library was specified with -dlpreopen. - if test "$pass" = dlpreopen; then - if test -z "$libdir" && test "$linkmode" = prog; then - func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi - case "$host" in + case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both @@ -6588,9 +8030,9 @@ func_mode_link () if test -z "$libdir"; then # Link the convenience library - if test "$linkmode" = lib; then + if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" - elif test "$linkmode,$pass" = "prog,link"; then + elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else @@ -6600,14 +8042,14 @@ func_mode_link () fi - if test "$linkmode" = prog && test "$pass" != link; then + if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" - linkalldeplibs=no - if test "$link_all_deplibs" != no || test -z "$library_names" || - test "$build_libtool_libs" = no; then - linkalldeplibs=yes + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: fi tmp_libs= @@ -6619,14 +8061,14 @@ func_mode_link () ;; esac # Need to link against all dependency_libs? - if test "$linkalldeplibs" = yes; then + if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi - if $opt_preserve_dup_deps ; then + if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac @@ -6636,15 +8078,15 @@ func_mode_link () continue fi # $linkmode = prog... - if test "$linkmode,$pass" = "prog,link"; then + if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && - { { test "$prefer_static_libs" = no || - test "$prefer_static_libs,$installed" = "built,yes"; } || + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path - if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. - case "$temp_rpath:" in + case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac @@ -6673,9 +8115,9 @@ func_mode_link () esac fi # $linkmode,$pass = prog,link... - if test "$alldeplibs" = yes && - { test "$deplibs_check_method" = pass_all || - { test "$build_libtool_libs" = yes && + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue @@ -6684,19 +8126,19 @@ func_mode_link () link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs - if test "$use_static_libs" = built && test "$installed" = yes; then + if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && - { test "$use_static_libs" = no || test -z "$old_library"; }; then + { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in - *cygwin* | *mingw* | *cegcc*) + *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) - if test "$installed" = no; then + if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi @@ -6706,24 +8148,24 @@ func_mode_link () # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! - dlopenmodule="" + dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then - dlopenmodule="$dlpremoduletest" + dlopenmodule=$dlpremoduletest break fi done - if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo - if test "$linkmode" = prog; then + if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi - if test "$linkmode" = lib && - test "$hardcode_into_libs" = yes; then + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. @@ -6751,43 +8193,43 @@ func_mode_link () # figure out the soname set dummy $library_names shift - realname="$1" + realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then - soname="$dlname" + soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in - *cygwin* | mingw* | *cegcc*) + *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result - versuffix="-$major" + versuffix=-$major ;; esac eval soname=\"$soname_spec\" else - soname="$realname" + soname=$realname fi # Make a new name for the extract_expsyms_cmds to use - soroot="$soname" + soroot=$soname func_basename "$soroot" - soname="$func_basename_result" + soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else - func_verbose "extracting exported symbol list from \`$soname'" + func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else - func_verbose "generating import library for \`$soname'" + func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library @@ -6795,58 +8237,58 @@ func_mode_link () linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" - if test "$linkmode" = prog || test "$opt_mode" != relink; then + if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) - if test "$hardcode_direct" = no; then - add="$dir/$linklib" + if test no = "$hardcode_direct"; then + add=$dir/$linklib case $host in - *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; - *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ - *-*-unixware7*) add_dir="-L$dir" ;; + *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) - # if the lib is a (non-dlopened) module then we can not + # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | - $GREP ": [^:]* bundle" >/dev/null ; then + $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" - if test -z "$old_library" ; then + if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else - add="$dir/$old_library" + add=$dir/$old_library fi elif test -n "$old_library"; then - add="$dir/$old_library" + add=$dir/$old_library fi fi esac - elif test "$hardcode_minus_L" = no; then + elif test no = "$hardcode_minus_L"; then case $host in - *-*-sunos*) add_shlibpath="$dir" ;; + *-*-sunos*) add_shlibpath=$dir ;; esac - add_dir="-L$dir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = no; then - add_shlibpath="$dir" - add="-l$name" + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name else lib_linked=no fi ;; relink) - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$dir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$absdir" + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in @@ -6855,10 +8297,10 @@ func_mode_link () ;; esac fi - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - add_shlibpath="$dir" - add="-l$name" + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name else lib_linked=no fi @@ -6866,7 +8308,7 @@ func_mode_link () *) lib_linked=no ;; esac - if test "$lib_linked" != yes; then + if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi @@ -6876,15 +8318,15 @@ func_mode_link () *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi - if test "$linkmode" = prog; then + if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" - if test "$hardcode_direct" != yes && - test "$hardcode_minus_L" != yes && - test "$hardcode_shlibpath_var" = yes; then + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; @@ -6893,33 +8335,33 @@ func_mode_link () fi fi - if test "$linkmode" = prog || test "$opt_mode" = relink; then + if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$libdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$libdir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac - add="-l$name" - elif test "$hardcode_automatic" = yes; then + add=-l$name + elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && - test -f "$inst_prefix_dir$libdir/$linklib" ; then - add="$inst_prefix_dir$libdir/$linklib" + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib else - add="$libdir/$linklib" + add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. - add_dir="-L$libdir" + add_dir=-L$libdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in @@ -6928,10 +8370,10 @@ func_mode_link () ;; esac fi - add="-l$name" + add=-l$name fi - if test "$linkmode" = prog; then + if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else @@ -6939,43 +8381,43 @@ func_mode_link () test -n "$add" && deplibs="$add $deplibs" fi fi - elif test "$linkmode" = prog; then + elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. - if test "$hardcode_direct" != unsupported; then - test -n "$old_library" && linklib="$old_library" + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi - elif test "$build_libtool_libs" = yes; then + elif test yes = "$build_libtool_libs"; then # Not a shared library - if test "$deplibs_check_method" != pass_all; then + if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo - $ECHO "*** Warning: This system can not link to static lib archive $lib." + $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." - if test "$module" = yes; then + if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." + echo "*** 'nm' from GNU binutils and a full rebuild may help." fi - if test "$build_old_libs" = no; then + if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else @@ -6988,11 +8430,11 @@ func_mode_link () fi fi # link shared/static library? - if test "$linkmode" = lib; then + if test lib = "$linkmode"; then if test -n "$dependency_libs" && - { test "$hardcode_into_libs" != yes || - test "$build_old_libs" = yes || - test "$link_static" = yes; }; then + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do @@ -7006,12 +8448,12 @@ func_mode_link () *) func_append temp_deplibs " $libdir";; esac done - dependency_libs="$temp_deplibs" + dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library - test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do @@ -7021,7 +8463,7 @@ func_mode_link () func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac - if $opt_preserve_dup_deps ; then + if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; @@ -7030,12 +8472,12 @@ func_mode_link () func_append tmp_libs " $func_resolve_sysroot_result" done - if test "$link_all_deplibs" != no; then + if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in - -L*) path="$deplib" ;; + -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result @@ -7043,12 +8485,12 @@ func_mode_link () dir=$func_dirname_result # We need an absolute path. case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then - func_warning "cannot determine absolute directory name of \`$dir'" - absdir="$dir" + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir fi ;; esac @@ -7056,35 +8498,35 @@ func_mode_link () case $host in *-*-darwin*) depdepl= - eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names" ; then - for tmp in $deplibrary_names ; do + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do depdepl=$tmp done - if test -f "$absdir/$objdir/$depdepl" ; then - depdepl="$absdir/$objdir/$depdepl" - darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then - darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi - func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" - func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) - path="-L$absdir/$objdir" + path=-L$absdir/$objdir ;; esac else - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" + func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ - func_warning "\`$deplib' seems to be moved" + func_warning "'$deplib' seems to be moved" - path="-L$absdir" + path=-L$absdir fi ;; esac @@ -7096,23 +8538,23 @@ func_mode_link () fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs - if test "$pass" = link; then - if test "$linkmode" = "prog"; then + if test link = "$pass"; then + if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi - dependency_libs="$newdependency_libs" - if test "$pass" = dlpreopen; then + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi - if test "$pass" != dlopen; then - if test "$pass" != conv; then + if test dlopen != "$pass"; then + test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do @@ -7122,12 +8564,12 @@ func_mode_link () esac done newlib_search_path= - fi + } - if test "$linkmode,$pass" != "prog,link"; then - vars="deplibs" - else + if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" + else + vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order @@ -7185,62 +8627,93 @@ func_mode_link () eval $var=\"$tmp_libs\" done # for var fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= - for i in $dependency_libs ; do + for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) - i="" + i= ;; esac - if test -n "$i" ; then + if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass - if test "$linkmode" = prog; then - dlfiles="$newdlfiles" + if test prog = "$linkmode"; then + dlfiles=$newdlfiles fi - if test "$linkmode" = prog || test "$linkmode" = lib; then - dlprefiles="$newdlprefiles" + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles fi case $linkmode in oldlib) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for archives" + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for archives" ;; + func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for archives" + func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ - func_warning "\`-R' is ignored for archives" + func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for archives" + func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ - func_warning "\`-release' is ignored for archives" + func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ - func_warning "\`-export-symbols' is ignored for archives" + func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no - oldlibs="$output" + oldlibs=$output func_append objs "$old_deplibs" ;; lib) - # Make sure we only generate libraries of the form `libNAME.la'. + # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" @@ -7249,10 +8722,10 @@ func_mode_link () eval libname=\"$libname_spec\" ;; *) - test "$module" = no && \ - func_fatal_help "libtool library \`$output' must begin with \`lib'" + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" - if test "$need_lib_prefix" != no; then + if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result @@ -7266,8 +8739,8 @@ func_mode_link () esac if test -n "$objs"; then - if test "$deplibs_check_method" != pass_all; then - func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" @@ -7276,21 +8749,21 @@ func_mode_link () fi fi - test "$dlself" != no && \ - func_warning "\`-dlopen self' is ignored for libtool libraries" + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift - test "$#" -gt 1 && \ - func_warning "ignoring multiple \`-rpath's for a libtool library" + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" - install_libdir="$1" + install_libdir=$1 oldlibs= if test -z "$rpath"; then - if test "$build_libtool_libs" = yes; then + if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. - # Some compilers have problems with a `.al' extension so + # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" @@ -7299,20 +8772,20 @@ func_mode_link () fi test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ - func_warning "\`-release' is ignored for convenience libraries" + func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. - save_ifs="$IFS"; IFS=':' + save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift - IFS="$save_ifs" + IFS=$save_ifs test -n "$7" && \ - func_fatal_help "too many parameters to \`-version-info'" + func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts @@ -7320,42 +8793,42 @@ func_mode_link () case $vinfo_number in yes) - number_major="$1" - number_minor="$2" - number_revision="$3" + number_major=$1 + number_minor=$2 + number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix - # which has an extra 1 added just for fun + # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor - darwin|linux|osf|windows|none) + darwin|freebsd-elf|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result - age="$number_minor" - revision="$number_revision" + age=$number_minor + revision=$number_revision ;; - freebsd-aout|freebsd-elf|qnx|sunos) - current="$number_major" - revision="$number_minor" - age="0" + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result - age="$number_minor" - revision="$number_minor" + age=$number_minor + revision=$number_minor lt_irix_increment=no ;; esac ;; no) - current="$1" - revision="$2" - age="$3" + current=$1 + revision=$2 + age=$3 ;; esac @@ -7363,30 +8836,30 @@ func_mode_link () case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - func_error "CURRENT \`$current' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - func_error "REVISION \`$revision' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - func_error "AGE \`$age' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then - func_error "AGE \`$age' is greater than the current interface number \`$current'" - func_fatal_error "\`$vinfo' is not valid version information" + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. @@ -7401,26 +8874,36 @@ func_mode_link () # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result - versuffix="$major.$age.$revision" + versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result - xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac ;; freebsd-aout) - major=".$current" - versuffix=".$current.$revision"; + major=.$current + versuffix=.$current.$revision ;; freebsd-elf) - major=".$current" - versuffix=".$current" + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision ;; irix | nonstopux) - if test "X$lt_irix_increment" = "Xno"; then + if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 @@ -7431,69 +8914,74 @@ func_mode_link () nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac - verstring="$verstring_prefix$major.$revision" + verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision - while test "$loop" -ne 0; do + while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result - verstring="$verstring_prefix$major.$iface:$verstring" + verstring=$verstring_prefix$major.$iface:$verstring done - # Before this point, $major must not contain `.'. + # Before this point, $major must not contain '.'. major=.$major - versuffix="$major.$revision" + versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result - versuffix="$major.$age.$revision" + versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result - versuffix=".$current.$age.$revision" - verstring="$current.$age.$revision" + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age - while test "$loop" -ne 0; do + while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result - verstring="$verstring:${iface}.0" + verstring=$verstring:$iface.0 done # Make executables depend on our current version. - func_append verstring ":${current}.0" + func_append verstring ":$current.0" ;; qnx) - major=".$current" - versuffix=".$current" + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current ;; sunos) - major=".$current" - versuffix=".$current.$revision" + major=.$current + versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 filesystems. + # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result - versuffix="-$major" + versuffix=-$major ;; *) - func_fatal_configuration "unknown library version type \`$version_type'" + func_fatal_configuration "unknown library version type '$version_type'" ;; esac @@ -7507,42 +8995,45 @@ func_mode_link () verstring= ;; *) - verstring="0.0" + verstring=0.0 ;; esac - if test "$need_version" = no; then + if test no = "$need_version"; then versuffix= else - versuffix=".0.0" + versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided - if test "$avoid_version" = yes && test "$need_version" = no; then + if test yes,no = "$avoid_version,$need_version"; then major= versuffix= - verstring="" + verstring= fi # Check to see if the archive will have undefined symbols. - if test "$allow_undefined" = yes; then - if test "$allow_undefined_flag" = unsupported; then - func_warning "undefined symbols not allowed in $host shared libraries" - build_libtool_libs=no - build_old_libs=yes + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi fi else # Don't allow undefined symbols. - allow_undefined_flag="$no_undefined_flag" + allow_undefined_flag=$no_undefined_flag fi fi - func_generate_dlsyms "$libname" "$libname" "yes" + func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" - test "X$libobjs" = "X " && libobjs= + test " " = "$libobjs" && libobjs= - if test "$opt_mode" != relink; then + if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= @@ -7551,8 +9042,8 @@ func_mode_link () case $p in *.$objext | *.gcno) ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) - if test "X$precious_files_regex" != "X"; then + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue @@ -7568,11 +9059,11 @@ func_mode_link () fi # Now set the variables for building old libraries. - if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. @@ -7593,13 +9084,13 @@ func_mode_link () *) func_append finalize_rpath " $libdir" ;; esac done - if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles="$dlfiles" + old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in @@ -7609,7 +9100,7 @@ func_mode_link () done # Make sure dlprefiles contains only unique files - old_dlprefiles="$dlprefiles" + old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in @@ -7618,7 +9109,7 @@ func_mode_link () esac done - if test "$build_libtool_libs" = yes; then + if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) @@ -7642,7 +9133,7 @@ func_mode_link () ;; *) # Add libc to deplibs on all other systems if necessary. - if test "$build_libtool_need_lc" = "yes"; then + if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; @@ -7658,9 +9149,9 @@ func_mode_link () # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? - release="" - versuffix="" - major="" + release= + versuffix= + major= newdeplibs= droppeddeps=no case $deplibs_check_method in @@ -7689,20 +9180,20 @@ EOF -l*) func_stripname -l '' "$i" name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $i "*) func_append newdeplibs " $i" - i="" + i= ;; esac fi - if test -n "$i" ; then + if test -n "$i"; then libname=`eval "\\$ECHO \"$libname_spec\""` deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` set dummy $deplib_matches; shift deplib_match=$1 - if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then func_append newdeplibs " $i" else droppeddeps=yes @@ -7732,20 +9223,20 @@ EOF $opt_dry_run || $RM conftest if $LTCC $LTCFLAGS -o conftest conftest.c $i; then ldd_output=`ldd conftest` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $i "*) func_append newdeplibs " $i" - i="" + i= ;; esac fi - if test -n "$i" ; then + if test -n "$i"; then libname=`eval "\\$ECHO \"$libname_spec\""` deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` set dummy $deplib_matches; shift deplib_match=$1 - if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then func_append newdeplibs " $i" else droppeddeps=yes @@ -7782,24 +9273,24 @@ EOF -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" - a_deplib="" + a_deplib= ;; esac fi - if test -n "$a_deplib" ; then + if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` if test -n "$file_magic_glob"; then libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob` else libnameglob=$libname fi - test "$want_nocaseglob" = yes && nocaseglob=`shopt -p nocaseglob` + test yes = "$want_nocaseglob" && nocaseglob=`shopt -p nocaseglob` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - if test "$want_nocaseglob" = yes; then + if test yes = "$want_nocaseglob"; then shopt -s nocaseglob potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` $nocaseglob @@ -7817,25 +9308,25 @@ EOF # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? - potlib="$potent_lib" + potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" - a_deplib="" + a_deplib= break 2 fi done done fi - if test -n "$a_deplib" ; then + if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." @@ -7843,7 +9334,7 @@ EOF echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then + if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" @@ -7866,30 +9357,30 @@ EOF -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" - a_deplib="" + a_deplib= ;; esac fi - if test -n "$a_deplib" ; then + if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do - potlib="$potent_lib" # see symlink-check above in file_magic test + potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" - a_deplib="" + a_deplib= break 2 fi done done fi - if test -n "$a_deplib" ; then + if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." @@ -7897,7 +9388,7 @@ EOF echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then + if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" @@ -7913,18 +9404,18 @@ EOF done # Gone through all deplibs. ;; none | unknown | *) - newdeplibs="" + newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - for i in $predeps $postdeps ; do + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo - if test "X$deplibs_check_method" = "Xnone"; then + if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." @@ -7948,8 +9439,8 @@ EOF ;; esac - if test "$droppeddeps" = yes; then - if test "$module" = yes; then + if test yes = "$droppeddeps"; then + if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" @@ -7958,12 +9449,12 @@ EOF if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." + echo "*** 'nm' from GNU binutils and a full rebuild may help." fi - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else @@ -7974,14 +9465,14 @@ EOF echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." - if test "$allow_undefined" = no; then + if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else @@ -8027,7 +9518,7 @@ EOF *) func_append new_libs " $deplib" ;; esac done - deplibs="$new_libs" + deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= @@ -8035,25 +9526,25 @@ EOF dlname= # Test again, we may have decided not to build it any more - if test "$build_libtool_libs" = yes; then - # Remove ${wl} instances when linking with ld. + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac - if test "$hardcode_into_libs" = yes; then + if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= - rpath="$finalize_rpath" - test "$opt_mode" != relink && rpath="$compile_rpath$rpath" + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" + hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in @@ -8078,7 +9569,7 @@ EOF # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" + libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then @@ -8092,8 +9583,8 @@ EOF test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi - shlibpath="$finalize_shlibpath" - test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi @@ -8103,19 +9594,19 @@ EOF eval library_names=\"$library_names_spec\" set dummy $library_names shift - realname="$1" + realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else - soname="$realname" + soname=$realname fi if test -z "$dlname"; then dlname=$soname fi - lib="$output_objdir/$realname" + lib=$output_objdir/$realname linknames= for link do @@ -8129,7 +9620,7 @@ EOF delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" - export_symbols="$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi @@ -8138,31 +9629,31 @@ EOF cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile - if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. - orig_export_symbols="$export_symbols" + orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes - fi + } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then - if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds - save_ifs="$IFS"; IFS='~' + save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do - IFS="$save_ifs" + IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in @@ -8176,7 +9667,7 @@ EOF try_normal_branch=no ;; esac - if test "$try_normal_branch" = yes \ + if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then @@ -8187,7 +9678,7 @@ EOF output_la=$func_basename_result save_libobjs=$libobjs save_output=$output - output=${output_objdir}/${output_la}.nm + output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" @@ -8210,8 +9701,8 @@ EOF break fi done - IFS="$save_ifs" - if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi @@ -8219,16 +9710,16 @@ EOF fi if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi - if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine + # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. @@ -8247,11 +9738,11 @@ EOF ;; esac done - deplibs="$tmp_deplibs" + deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && - test "$compiler_needs_object" = yes && + test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. @@ -8262,7 +9753,7 @@ EOF eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience @@ -8271,18 +9762,18 @@ EOF fi fi - if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking - if test "$opt_mode" = relink; then + if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then + if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds @@ -8300,7 +9791,7 @@ EOF fi fi - if test "X$skipped_export" != "X:" && + if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then @@ -8333,8 +9824,8 @@ EOF last_robj= k=1 - if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then - output=${output_objdir}/${output_la}.lnkscript + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs @@ -8346,14 +9837,14 @@ EOF func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result - elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then - output=${output_objdir}/${output_la}.lnk + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= - if test "$compiler_needs_object" = yes; then + if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi @@ -8368,7 +9859,7 @@ EOF else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." - output=$output_objdir/$output_la-${k}.$objext + output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result @@ -8380,13 +9871,13 @@ EOF func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result - if test "X$objlist" = X || + if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. - if test "$k" -eq 1 ; then + if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" @@ -8396,10 +9887,10 @@ EOF reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi - last_robj=$output_objdir/$output_la-${k}.$objext + last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result - output=$output_objdir/$output_la-${k}.$objext + output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result @@ -8411,9 +9902,9 @@ EOF # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" - eval concat_cmds=\"\${concat_cmds}$reload_cmds\" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then - eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" @@ -8421,9 +9912,9 @@ EOF output= fi - if ${skipped_export-false}; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. @@ -8432,16 +9923,16 @@ EOF if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi - fi + } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. - save_ifs="$IFS"; IFS='~' + save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do - IFS="$save_ifs" - $opt_silent || { + IFS=$save_ifs + $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } @@ -8449,7 +9940,7 @@ EOF lt_exit=$? # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then + if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) @@ -8458,7 +9949,7 @@ EOF exit $lt_exit } done - IFS="$save_ifs" + IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' @@ -8466,18 +9957,18 @@ EOF fi fi - if ${skipped_export-false}; then + ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine + # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. @@ -8486,7 +9977,7 @@ EOF export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi - fi + } libobjs=$output # Restore the value of output. @@ -8500,7 +9991,7 @@ EOF # value of $libobjs for piecewise linking. # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then + if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else @@ -8522,7 +10013,7 @@ EOF # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles @@ -8530,11 +10021,12 @@ EOF test "X$libobjs" = "X " && libobjs= fi - save_ifs="$IFS"; IFS='~' + save_ifs=$IFS; IFS='~' for cmd in $cmds; do - IFS="$save_ifs" + IFS=$sp$nl eval cmd=\"$cmd\" - $opt_silent || { + IFS=$save_ifs + $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } @@ -8542,7 +10034,7 @@ EOF lt_exit=$? # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then + if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) @@ -8551,10 +10043,10 @@ EOF exit $lt_exit } done - IFS="$save_ifs" + IFS=$save_ifs # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then + if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then @@ -8574,39 +10066,39 @@ EOF done # If -module or -export-dynamic was specified, set the dlname. - if test "$module" = yes || test "$export_dynamic" = yes; then + if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. - dlname="$soname" + dlname=$soname fi fi ;; obj) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for objects" + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for objects" ;; + func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for objects" + func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ - func_warning "\`-R' is ignored for objects" + func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for objects" + func_warning "'-version-info' is ignored for objects" test -n "$release" && \ - func_warning "\`-release' is ignored for objects" + func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ - func_fatal_error "cannot build library object \`$output' from non-libtool objects" + func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" @@ -8614,7 +10106,7 @@ EOF ;; *) libobj= - obj="$output" + obj=$output ;; esac @@ -8627,17 +10119,19 @@ EOF # the extraction. reload_conv_objs= gentop= - # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec and hope we can get by with - # turning comma into space.. - wl= - + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else - gentop="$output_objdir/${obj}x" + gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience @@ -8646,12 +10140,12 @@ EOF fi # If we're not building shared, we need to use non_pic_objs - test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. - reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs - output="$obj" + output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. @@ -8663,7 +10157,7 @@ EOF exit $EXIT_SUCCESS fi - if test "$build_libtool_libs" != yes; then + test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi @@ -8673,12 +10167,12 @@ EOF # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS - fi + } - if test -n "$pic_flag" || test "$pic_mode" != default; then + if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" - output="$libobj" + output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi @@ -8695,16 +10189,14 @@ EOF output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for programs" + func_warning "'-version-info' is ignored for programs" test -n "$release" && \ - func_warning "\`-release' is ignored for programs" + func_warning "'-release' is ignored for programs" - test "$preload" = yes \ - && test "$dlopen_support" = unknown \ - && test "$dlopen_self" = unknown \ - && test "$dlopen_self_static" = unknown && \ - func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) @@ -8718,11 +10210,11 @@ EOF *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). - if test "$tagname" = CXX ; then + if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) - func_append compile_command " ${wl}-bind_at_load" - func_append finalize_command " ${wl}-bind_at_load" + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" ;; esac fi @@ -8758,7 +10250,7 @@ EOF *) func_append new_libs " $deplib" ;; esac done - compile_deplibs="$new_libs" + compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" @@ -8782,7 +10274,7 @@ EOF if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" + hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in @@ -8805,7 +10297,7 @@ EOF fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; @@ -8822,10 +10314,10 @@ EOF # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" + libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi - compile_rpath="$rpath" + compile_rpath=$rpath rpath= hardcode_libdirs= @@ -8833,7 +10325,7 @@ EOF if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" + hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in @@ -8858,45 +10350,43 @@ EOF # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" + libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi - finalize_rpath="$rpath" + finalize_rpath=$rpath - if test -n "$libobjs" && test "$build_old_libs" = yes; then + if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi - func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi - wrappers_required=yes + wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. - wrappers_required=no + wrappers_required=false ;; *cygwin* | *mingw* ) - if test "$build_libtool_libs" != yes; then - wrappers_required=no - fi + test yes = "$build_libtool_libs" || wrappers_required=false ;; *) - if test "$need_relink" = no || test "$build_libtool_libs" != yes; then - wrappers_required=no + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false fi ;; esac - if test "$wrappers_required" = no; then + $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - link_command="$compile_command$compile_rpath" + link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 @@ -8909,12 +10399,12 @@ EOF fi # Delete the generated files. - if test -f "$output_objdir/${outputname}S.${objext}"; then - func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status - fi + } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" @@ -8944,9 +10434,9 @@ EOF fi fi - if test "$no_install" = yes; then + if test yes = "$no_install"; then # We don't need to create a wrapper script. - link_command="$compile_var$compile_command$compile_rpath" + link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. @@ -8963,27 +10453,28 @@ EOF exit $EXIT_SUCCESS fi - if test "$hardcode_action" = relink; then - # Fast installation is not supported - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath - func_warning "this platform does not like uninstalled shared libraries" - func_warning "\`$output' will be relinked during installation" - else - if test "$fast_install" != no; then - link_command="$finalize_var$compile_command$finalize_rpath" - if test "$fast_install" = yes; then - relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` - else - # fast_install is set to needless - relink_command= - fi - else - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - fi - fi + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` @@ -9040,8 +10531,8 @@ EOF func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result - cwrappersource="$output_path/$objdir/lt-$output_name.c" - cwrapper="$output_path/$output_name.exe" + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 @@ -9062,7 +10553,7 @@ EOF trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. - if test "x$build" = "x$host" ; then + if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result @@ -9085,25 +10576,27 @@ EOF # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do - if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save $symfileobj" - addlibs="$convenience" - build_libtool_libs=no - else - if test "$build_libtool_libs" = module; then - oldobjs="$libobjs_save" + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience build_libtool_libs=no - else + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) oldobjs="$old_deplibs $non_pic_objects" - if test "$preload" = yes && test -f "$symfileobj"; then - func_append oldobjs " $symfileobj" - fi - fi - addlibs="$old_convenience" - fi + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac if test -n "$addlibs"; then - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs @@ -9111,13 +10604,13 @@ EOF fi # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles @@ -9138,7 +10631,7 @@ EOF : else echo "copying selected object files to avoid basename conflicts..." - gentop="$output_objdir/${outputname}x" + gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs @@ -9147,7 +10640,7 @@ EOF for obj in $save_oldobjs do func_basename "$obj" - objbase="$func_basename_result" + objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) @@ -9216,18 +10709,18 @@ EOF else # the above command should be used before it gets too long oldobjs=$objlist - if test "$obj" = "$last_oldobj" ; then + if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist - if test "X$oldobjs" = "X" ; then + if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" @@ -9244,7 +10737,7 @@ EOF case $output in *.la) old_library= - test "$build_old_libs" = yes && old_library="$libname.$libext" + test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior @@ -9259,31 +10752,31 @@ EOF fi done # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - if test "$hardcode_automatic" = yes ; then + if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do - if test "$installed" = yes; then + if test yes = "$installed"; then if test -z "$install_libdir"; then break fi - output="$output_objdir/$outputname"i + output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" - name="$func_basename_result" + name=$func_basename_result func_resolve_sysroot "$deplib" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" + func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) @@ -9299,23 +10792,23 @@ EOF *) func_append newdependency_libs " $deplib" ;; esac done - dependency_libs="$newdependency_libs" + dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" + func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done - dlfiles="$newdlfiles" + dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in @@ -9325,34 +10818,34 @@ EOF # didn't already link the preopened objects directly into # the library: func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" + func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done - dlprefiles="$newdlprefiles" + dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done - dlfiles="$newdlfiles" + dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done - dlprefiles="$newdlprefiles" + dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin @@ -9368,10 +10861,9 @@ EOF case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. - if test "x$bindir" != x ; - then + if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" - tdlname=$func_relative_path_result$dlname + tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname @@ -9380,7 +10872,7 @@ EOF esac $ECHO > $output "\ # $outputname - a libtool library file -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. @@ -9394,7 +10886,7 @@ library_names='$library_names' # The name of the static archive. old_library='$old_library' -# Linker flags that can not go in dependency_libs. +# Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. @@ -9420,7 +10912,7 @@ dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" - if test "$installed" = no && test "$need_relink" = yes; then + if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi @@ -9435,27 +10927,29 @@ relink_command=\"$relink_command\"" exit $EXIT_SUCCESS } -{ test "$opt_mode" = link || test "$opt_mode" = relink; } && - func_mode_link ${1+"$@"} +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi # func_mode_uninstall arg... func_mode_uninstall () { - $opt_debug - RM="$nonopt" + $debug_cmd + + RM=$nonopt files= - rmforce= + rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. - libtool_install_magic="$magic" + libtool_install_magic=$magic for arg do case $arg in - -f) func_append RM " $arg"; rmforce=yes ;; + -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac @@ -9468,18 +10962,18 @@ func_mode_uninstall () for file in $files; do func_dirname "$file" "" "." - dir="$func_dirname_result" - if test "X$dir" = X.; then - odir="$objdir" + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir else - odir="$dir/$objdir" + odir=$dir/$objdir fi func_basename "$file" - name="$func_basename_result" - test "$opt_mode" = uninstall && odir="$dir" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates - if test "$opt_mode" = clean; then + if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; @@ -9494,11 +10988,11 @@ func_mode_uninstall () elif test -d "$file"; then exit_status=1 continue - elif test "$rmforce" = yes; then + elif $rmforce; then continue fi - rmfiles="$file" + rmfiles=$file case $name in *.la) @@ -9512,7 +11006,7 @@ func_mode_uninstall () done test -n "$old_library" && func_append rmfiles " $odir/$old_library" - case "$opt_mode" in + case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; @@ -9523,12 +11017,12 @@ func_mode_uninstall () uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. - func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. - func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; @@ -9544,21 +11038,19 @@ func_mode_uninstall () func_source $dir/$name # Add PIC object to the list of files to remove. - if test -n "$pic_object" && - test "$pic_object" != none; then + if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" && - test "$non_pic_object" != none; then + if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) - if test "$opt_mode" = clean ; then + if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) @@ -9585,12 +11077,12 @@ func_mode_uninstall () # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles - func_append rmfiles " $odir/$name $odir/${name}S.${objext}" - if test "$fast_install" = yes && test -n "$relink_command"; then + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi - if test "X$noexename" != "X$name" ; then - func_append rmfiles " $odir/lt-${noexename}.c" + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" fi fi fi @@ -9599,7 +11091,7 @@ func_mode_uninstall () func_show_eval "$RM $rmfiles" 'exit_status=1' done - # Try to remove the ${objdir}s in the directories where we deleted files + # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" @@ -9609,16 +11101,17 @@ func_mode_uninstall () exit $exit_status } -{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && - func_mode_uninstall ${1+"$@"} +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi test -z "$opt_mode" && { - help="$generic_help" + help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ - func_fatal_help "invalid operation mode \`$opt_mode'" + func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" @@ -9629,7 +11122,7 @@ exit $exit_status # The TAGs below are defined such that we never get into a situation -# in which we disable both kinds of libraries. Given conflicting +# where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support @@ -9652,5 +11145,3 @@ build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # mode:shell-script # sh-indentation:2 # End: -# vi:sw=2 - diff --git a/FreeRTOS-Plus/Source/WolfSSL/build-aux/missing b/FreeRTOS-Plus/Source/WolfSSL/build-aux/missing index db98974ff..8d0eaad25 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/build-aux/missing +++ b/FreeRTOS-Plus/Source/WolfSSL/build-aux/missing @@ -1,9 +1,9 @@ #! /bin/sh # Common wrapper for a few potentially missing GNU programs. -scriptversion=2013-10-28.13; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ scriptversion=2013-10-28.13; # UTC # 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, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -101,9 +101,9 @@ else exit $st fi -perl_URL=http://www.perl.org/ -flex_URL=http://flex.sourceforge.net/ -gnu_software_URL=http://www.gnu.org/software +perl_URL=https://www.perl.org/ +flex_URL=https://github.com/westes/flex +gnu_software_URL=https://www.gnu.org/software program_details () { @@ -207,9 +207,9 @@ give_advice "$1" | sed -e '1s/^/WARNING: /' \ exit $st # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/FreeRTOS-Plus/Source/WolfSSL/build-aux/test-driver b/FreeRTOS-Plus/Source/WolfSSL/build-aux/test-driver index d30605660..89dba1e07 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/build-aux/test-driver +++ b/FreeRTOS-Plus/Source/WolfSSL/build-aux/test-driver @@ -1,9 +1,9 @@ #! /bin/sh # test-driver - basic testsuite driver script. -scriptversion=2013-07-13.22; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 2011-2013 Free Software Foundation, Inc. +# Copyright (C) 2011-2020 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ scriptversion=2013-07-13.22; # UTC # 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, see . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -106,11 +106,14 @@ trap "st=143; $do_exit" 15 # Test script is run here. "$@" >$log_file 2>&1 estatus=$? + if test $enable_hard_errors = no && test $estatus -eq 99; then - estatus=1 + tweaked_estatus=1 +else + tweaked_estatus=$estatus fi -case $estatus:$expect_failure in +case $tweaked_estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; @@ -119,6 +122,12 @@ case $estatus:$expect_failure in *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + # Report outcome to console. echo "${col}${res}${std}: $test_name" @@ -131,9 +140,9 @@ echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-cert.der b/FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-cert.der new file mode 100644 index 0000000000000000000000000000000000000000..6a2b06e40268f9a4a902399dc3fadcdde7aa9ce0 GIT binary patch literal 953 zcmXqLV%}=d#4NXfnTe5!iId^h?=0Sb=V!Yc@Un4gwRyCC=VfH%W@RvFoN35yz{$oO z%EBhh6dG(OV893BaPYAE=I50p<|V>J*m>BU@~cvF6Y~rO4fsK7xOg~%6U$5T^Gh-e zB@DzsLfkz3&iQ%8r8y;;dFk`IvTR0iT z1Tyo|@*R*A7|4n98d?~b7#bUz8W|fJM2Yhn85$TGm_xaP+U^=s%nV10M_?cqY(lbg(}WcRNyXgmj!S7vEEX3%)J0jrvYjq{f@&Kb9Y2E<=6A29tqm$PXENeX5I8QuHP&COQi2f2HrmVNYLWolDT24-DB?U zdaZsx_e7o5UcK2`Yn800uKc9IyyxkgGoLuFoY24h>bG8ySdSCalE_>i<1Mo;6?@6e Izj>k=0NE`z?*IS* literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-cert.pem new file mode 100644 index 000000000..6f8a188f3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-cert.pem @@ -0,0 +1,65 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 15779322327764802375 (0xdafb6a0dfecf9b47) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting_1024, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting_1024, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:cd:ac:dd:47:ec:be:b7:24:c3:63:1b:54:98:79: + e1:c7:31:16:59:d6:9d:77:9d:8d:e2:8b:ed:04:17: + b2:c6:eb:e4:9b:91:be:31:50:62:97:58:b5:7f:29: + de:b3:71:24:0b:bf:97:09:7f:26:dc:2d:ec:a8:2e: + b2:64:2b:7a:2b:35:19:2d:a2:80:cb:99:fd:94:71: + 1b:23:8d:54:db:2e:62:8d:81:08:2d:f4:24:72:27: + 6c:f9:c9:8e:db:4c:75:ba:9b:01:f8:3f:18:f4:e6: + 7f:fb:57:94:92:cc:88:c4:b4:00:c2:aa:d4:e5:88: + 18:b3:11:2f:73:c0:d6:29:09 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D3:22:8F:28:2C:E0:05:EE:D3:ED:C3:71:3D:C9:B2:36:3A:1D:BF:A8 + X509v3 Authority Key Identifier: + keyid:D3:22:8F:28:2C:E0:05:EE:D3:ED:C3:71:3D:C9:B2:36:3A:1D:BF:A8 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting_1024/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:DA:FB:6A:0D:FE:CF:9B:47 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 1d:48:f6:40:41:04:06:f2:e4:72:2f:ea:ff:c1:67:6b:15:bb: + 0a:28:23:28:07:c6:d7:13:2c:be:00:00:ac:1d:f7:f4:92:d3: + 2b:af:23:eb:9f:1a:e2:11:3c:2d:97:f2:0f:ac:ae:97:86:0a: + fb:a8:4f:74:1b:de:19:51:db:cd:e2:11:38:c1:a4:9d:56:ab: + 47:5c:de:ba:eb:27:df:6d:c8:7e:3a:bd:2e:9b:2a:ad:22:3b: + 95:a9:f2:28:03:bc:e5:ec:cc:f2:08:d4:c8:2f:db:ea:fb:2e: + 52:16:8c:42:02:a4:59:6d:4c:33:b4:9a:d2:73:4a:1e:9f:d9: + c8:83 +-----BEGIN CERTIFICATE----- +MIIDtTCCAx6gAwIBAgIJANr7ag3+z5tHMA0GCSqGSIb3DQEBCwUAMIGZMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G +A1UECgwIU2F3dG9vdGgxGDAWBgNVBAsMD0NvbnN1bHRpbmdfMTAyNDEYMBYGA1UE +AwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE4MDQxMzE1MjMxMFoXDTIxMDEwNzE1MjMxMFowgZkxCzAJBgNVBAYT +AlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQK +DAhTYXd0b290aDEYMBYGA1UECwwPQ29uc3VsdGluZ18xMDI0MRgwFgYDVQQDDA93 +d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20w +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM2s3Ufsvrckw2MbVJh54ccxFlnW +nXedjeKL7QQXssbr5JuRvjFQYpdYtX8p3rNxJAu/lwl/Jtwt7KgusmQreis1GS2i +gMuZ/ZRxGyONVNsuYo2BCC30JHInbPnJjttMdbqbAfg/GPTmf/tXlJLMiMS0AMKq +1OWIGLMRL3PA1ikJAgMBAAGjggEBMIH+MB0GA1UdDgQWBBTTIo8oLOAF7tPtw3E9 +ybI2Oh2/qDCBzgYDVR0jBIHGMIHDgBTTIo8oLOAF7tPtw3E9ybI2Oh2/qKGBn6SB +nDCBmTELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0Jv +emVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRgwFgYDVQQLDA9Db25zdWx0aW5nXzEw +MjQxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5m +b0B3b2xmc3NsLmNvbYIJANr7ag3+z5tHMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN +AQELBQADgYEAHUj2QEEEBvLkci/q/8FnaxW7CigjKAfG1xMsvgAArB339JLTK68j +658a4hE8LZfyD6yul4YK+6hPdBveGVHbzeIROMGknVarR1zeuusn323Ifjq9Lpsq +rSI7lanyKAO85ezM8gjUyC/b6vsuUhaMQgKkWW1MM7Sa0nNKHp/ZyIM= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-key.der b/FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-key.der new file mode 100644 index 0000000000000000000000000000000000000000..00f0f5b6a4d7a3b84bf70c5623581a0d1290f1f0 GIT binary patch literal 610 zcmV-o0-gOZf&yLw0RRGlfdI{{-AC-cw=F0y1RdMh;>h{Uu2!m8Beh#0dGFLS`wDG34t0RRC4fq+sq zJpn1Cl__zXWNIwK(zU*B6P%B>CfIgsy`WZ}~BVzW{EH0}e18&@VUee!^tG?n~(X z0zm-bnTspfpXqj&pKEI)9?$9(uGM8i<>hq9twWx6G~YhE`)Zb8)jV@zxu!zPLS ziK8Dt?O!XNriJNAZrqpZ@OLAO2rY8D4Me+dkO=}o0FmS_%8UwWFJj_iJEe_UELJ{$ wXF`$^l3(+e-QlT!tu8I}N>{Ub5WUyr>}m)h>GDQN(rHJEAWQPGQiH2+5G)uYO#lD@ literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-key.pem new file mode 100644 index 000000000..de4c756ae --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/1024/ca-key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDNrN1H7L63JMNjG1SYeeHHMRZZ1p13nY3ii+0EF7LG6+Sbkb4x +UGKXWLV/Kd6zcSQLv5cJfybcLeyoLrJkK3orNRktooDLmf2UcRsjjVTbLmKNgQgt +9CRyJ2z5yY7bTHW6mwH4Pxj05n/7V5SSzIjEtADCqtTliBizES9zwNYpCQIDAQAB +AoGAUjU9ASmklSlxm2RqLMPStb5uE5yPtibYdmu9YbxjLdVNu8zGO4nIznubl+dR +Z2HaqYN7yET1cF4+0H5RuW4TVwhc4WdPYV6lCewR3eS4tPTgYzRM2jIgH4VBXbzb +JMWvvgJfIvF8zAVWpqY3muv/Ui2/MEuaHe6rnCziwbidyTECQQDpiRbNrC7yTWYX +vXgSEo2OhCTeLVBBhYw0Cfr7bYdRTBMo8GARhj3CpM9exW9bETIKtSjQgkdEJpLi +eFm0CLP9AkEA4XW0arWMEfvMQgLF2kjOKUMUAZoss6TLc+uhNVettRYXgANfMje+ +om/5MYS/AG6NAw4wHNAvN/B+wmS/7kvo/QJBAOGZiyvYn+l2l59rayiaP6FjSnJO +9+6z4kMLOSfWIRiKEyBDRaroMZVsvN7if7ZLoDnz05/JmqrdUJvyg0WF+skCQQCv +sMd8+ChEw1Dyh7KiXWW6JblrXjdDbkHU/WNMbBzDJon9iaMfQO1fK56mhelJbtyX +6vB3I4wILXK6DUS7b5AJAkEAkeQuyowKaS9i4mI7pY1aLFY+f2dCkhKSX/OX3eGp +f60uLfRKV7N6EL3X5OxqCCHp8kZJ0mlHiiBL8rFSg6tvEA== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/1024/client-cert.der b/FreeRTOS-Plus/Source/WolfSSL/certs/1024/client-cert.der index c2bd6df8fe58e67cfaf20cb20bce0bd93a31726b..0195f9de9d05d0118c36b91ff5ad38cbf63b1aae 100644 GIT binary patch delta 212 zcmX@fev)0npo#e?5bG^qW@2Pw;$+x;S%CT3Tn*-l5?iG$3``7-4NZ-V4J@O?d5sJW z3=Pbo+{rae3paN%PG{tRX_&0RtXSVN^X60YBQCY)Gw^i$q!e@ySSF+VMRb@PH3Tl7O6V2gX6}pu7SJAobg`3tzElmEOar>#~`;UAx zrg3g%iNC@%yKDU=L;0ys`B$9Xy-+u0!}fRX%Oh?czrA77?p5b^bg@M9&$oMU$th@W I>~cmA09H0!mjD0& delta 212 zcmX@fev)0npo#e?5bG^qW@2Pw;$(PyeZjA?`&z#yN^F%jH83?WH?%M^G%$=3=QXr2 zFf=xVawpd?E!^D6IGvFLreU%MvtqsM_Nz4yH{Ljq9=r8&$MXQq!sPxlYVyXMq0X~c zACum5oN=nuuha*B=e*A6;um?dRsW8R!QG(gS7bODj4k3%uMq1O+`i*N+QSfy&-VMX z^2&LNQUS;PxJJHQxhL_uih1nTBj&xk(l@AjV;&OzcFpatFqm1bn8WUX9_i`g+3G6A6n4y z?`P>lCT2zk#>Gv*gwXg882-$mvV1IJEFw2;Okb7oDes%}=a=RL&V$ce#OBu+G@b*= zE3-5nGiW^AAaYr$Uqj~s>$}Tu4;R{=++=1YyMM*P#`#Mc=M3gl)Wpef>vtCKzw@)* z4R}EQ5oTdEU}j|ej~qw9oWKl>9PY#Gom*29pRbP6lHR0wH7&zMDmU$q?Z%EbOC2TB zlT4PxoygDPp#jJX6iKXFENz8!Y#Ly|9LRiJyG6G7qY)x(|^RhxGO3T E0Mu(QVgLXD literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/1024/server-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/1024/server-cert.pem new file mode 100644 index 000000000..4b432fbbf --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/1024/server-cert.pem @@ -0,0 +1,130 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting_1024, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=wolfSSL, OU=Support_1024, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:aa:3e:a5:9c:d3:17:49:65:43:de:d0:f3:4b:1c: + db:49:0c:fc:7a:65:05:6d:de:6a:c4:e4:73:2c:8a: + 96:82:8f:23:a5:06:71:1c:06:3e:2f:92:8d:0b:29: + 34:45:59:e9:a9:bc:61:d7:24:37:5d:b5:c4:37:8d: + ba:67:b2:ef:03:27:fa:c1:b4:cd:6b:00:66:b4:d6: + 73:70:1f:08:3a:cc:77:ad:e9:f9:34:d4:f3:a0:2d: + a9:e7:58:a9:c0:61:84:b6:ec:3d:0a:ad:fd:5c:86: + 73:aa:6b:47:d8:8b:2e:58:4b:69:12:82:26:55:e6: + 14:bf:55:70:88:fe:f9:75:e1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D9:3C:35:EA:74:0E:23:BE:9C:FC:FA:29:90:09:C1:E7:84:16:9F:7C + X509v3 Authority Key Identifier: + keyid:D3:22:8F:28:2C:E0:05:EE:D3:ED:C3:71:3D:C9:B2:36:3A:1D:BF:A8 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting_1024/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:DA:FB:6A:0D:FE:CF:9B:47 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 0b:c3:af:43:85:64:61:e7:ab:5a:2a:1b:b2:29:d5:66:68:44: + 1a:6d:66:fc:3d:b1:88:ec:a5:41:18:67:62:34:a4:5e:c9:69: + cd:40:c8:56:7e:bf:eb:bc:61:1f:33:34:58:be:57:fd:e6:98: + dd:51:27:7c:b7:2c:bc:c9:39:e5:e5:95:82:e1:3f:d9:b9:97: + 30:4e:33:2c:ef:f8:db:b4:ee:35:75:9e:7a:3f:22:8f:a5:71: + d4:01:64:6c:f2:85:f7:72:99:2c:80:0f:a4:31:1d:d4:0b:1e: + a5:0f:e7:53:0a:de:15:0d:b2:d0:6b:f4:d6:2f:e2:0b:a3:8a: + 5a:6e +-----BEGIN CERTIFICATE----- +MIIDqTCCAxKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRgwFgYDVQQLDA9Db25zdWx0aW5nXzEwMjQxGDAWBgNVBAMMD3d3dy53 +b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0x +ODA0MTMxNTIzMTBaFw0yMTAxMDcxNTIzMTBaMIGVMQswCQYDVQQGEwJVUzEQMA4G +A1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEQMA4GA1UECgwHd29sZlNT +TDEVMBMGA1UECwwMU3VwcG9ydF8xMDI0MRgwFgYDVQQDDA93d3cud29sZnNzbC5j +b20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wgZ8wDQYJKoZIhvcN +AQEBBQADgY0AMIGJAoGBAKo+pZzTF0llQ97Q80sc20kM/HplBW3easTkcyyKloKP +I6UGcRwGPi+SjQspNEVZ6am8YdckN121xDeNumey7wMn+sG0zWsAZrTWc3AfCDrM +d63p+TTU86AtqedYqcBhhLbsPQqt/VyGc6prR9iLLlhLaRKCJlXmFL9VcIj++XXh +AgMBAAGjggEBMIH+MB0GA1UdDgQWBBTZPDXqdA4jvpz8+imQCcHnhBaffDCBzgYD +VR0jBIHGMIHDgBTTIo8oLOAF7tPtw3E9ybI2Oh2/qKGBn6SBnDCBmTELMAkGA1UE +BhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNV +BAoMCFNhd3Rvb3RoMRgwFgYDVQQLDA9Db25zdWx0aW5nXzEwMjQxGDAWBgNVBAMM +D3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv +bYIJANr7ag3+z5tHMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEAC8Ov +Q4VkYeerWiobsinVZmhEGm1m/D2xiOylQRhnYjSkXslpzUDIVn6/67xhHzM0WL5X +/eaY3VEnfLcsvMk55eWVguE/2bmXME4zLO/427TuNXWeej8ij6Vx1AFkbPKF93KZ +LIAPpDEd1AsepQ/nUwreFQ2y0Gv01i/iC6OKWm4= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 15779322327764802375 (0xdafb6a0dfecf9b47) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting_1024, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting_1024, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:cd:ac:dd:47:ec:be:b7:24:c3:63:1b:54:98:79: + e1:c7:31:16:59:d6:9d:77:9d:8d:e2:8b:ed:04:17: + b2:c6:eb:e4:9b:91:be:31:50:62:97:58:b5:7f:29: + de:b3:71:24:0b:bf:97:09:7f:26:dc:2d:ec:a8:2e: + b2:64:2b:7a:2b:35:19:2d:a2:80:cb:99:fd:94:71: + 1b:23:8d:54:db:2e:62:8d:81:08:2d:f4:24:72:27: + 6c:f9:c9:8e:db:4c:75:ba:9b:01:f8:3f:18:f4:e6: + 7f:fb:57:94:92:cc:88:c4:b4:00:c2:aa:d4:e5:88: + 18:b3:11:2f:73:c0:d6:29:09 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D3:22:8F:28:2C:E0:05:EE:D3:ED:C3:71:3D:C9:B2:36:3A:1D:BF:A8 + X509v3 Authority Key Identifier: + keyid:D3:22:8F:28:2C:E0:05:EE:D3:ED:C3:71:3D:C9:B2:36:3A:1D:BF:A8 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting_1024/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:DA:FB:6A:0D:FE:CF:9B:47 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 1d:48:f6:40:41:04:06:f2:e4:72:2f:ea:ff:c1:67:6b:15:bb: + 0a:28:23:28:07:c6:d7:13:2c:be:00:00:ac:1d:f7:f4:92:d3: + 2b:af:23:eb:9f:1a:e2:11:3c:2d:97:f2:0f:ac:ae:97:86:0a: + fb:a8:4f:74:1b:de:19:51:db:cd:e2:11:38:c1:a4:9d:56:ab: + 47:5c:de:ba:eb:27:df:6d:c8:7e:3a:bd:2e:9b:2a:ad:22:3b: + 95:a9:f2:28:03:bc:e5:ec:cc:f2:08:d4:c8:2f:db:ea:fb:2e: + 52:16:8c:42:02:a4:59:6d:4c:33:b4:9a:d2:73:4a:1e:9f:d9: + c8:83 +-----BEGIN CERTIFICATE----- +MIIDtTCCAx6gAwIBAgIJANr7ag3+z5tHMA0GCSqGSIb3DQEBCwUAMIGZMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G +A1UECgwIU2F3dG9vdGgxGDAWBgNVBAsMD0NvbnN1bHRpbmdfMTAyNDEYMBYGA1UE +AwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE4MDQxMzE1MjMxMFoXDTIxMDEwNzE1MjMxMFowgZkxCzAJBgNVBAYT +AlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQK +DAhTYXd0b290aDEYMBYGA1UECwwPQ29uc3VsdGluZ18xMDI0MRgwFgYDVQQDDA93 +d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20w +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM2s3Ufsvrckw2MbVJh54ccxFlnW +nXedjeKL7QQXssbr5JuRvjFQYpdYtX8p3rNxJAu/lwl/Jtwt7KgusmQreis1GS2i +gMuZ/ZRxGyONVNsuYo2BCC30JHInbPnJjttMdbqbAfg/GPTmf/tXlJLMiMS0AMKq +1OWIGLMRL3PA1ikJAgMBAAGjggEBMIH+MB0GA1UdDgQWBBTTIo8oLOAF7tPtw3E9 +ybI2Oh2/qDCBzgYDVR0jBIHGMIHDgBTTIo8oLOAF7tPtw3E9ybI2Oh2/qKGBn6SB +nDCBmTELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0Jv +emVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRgwFgYDVQQLDA9Db25zdWx0aW5nXzEw +MjQxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5m +b0B3b2xmc3NsLmNvbYIJANr7ag3+z5tHMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN +AQELBQADgYEAHUj2QEEEBvLkci/q/8FnaxW7CigjKAfG1xMsvgAArB339JLTK68j +658a4hE8LZfyD6yul4YK+6hPdBveGVHbzeIROMGknVarR1zeuusn323Ifjq9Lpsq +rSI7lanyKAO85ezM8gjUyC/b6vsuUhaMQgKkWW1MM7Sa0nNKHp/ZyIM= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/1024/server-key.der b/FreeRTOS-Plus/Source/WolfSSL/certs/1024/server-key.der new file mode 100644 index 0000000000000000000000000000000000000000..9f7a9c3dfce2369025c15a7b17830cd81ba83fc5 GIT binary patch literal 609 zcmV-n0-pUaf&yIv0RRGlfdHyLrJU0jNo7Oc(DO?i+er-kdSwM|-fG0;b1aIMf{!Dm z25}q)J};7u3n?^3S?Q^~Vb>%#UA4qFjk;&D?*k|L!L-e50A{q-b8sIBI?Q*i>G?F& z^PnxM=UA!0VT88qJqoS;T!wS1Ye(3NE?7%x5`rdG<`lnGaESi-b>RX70RRC4fq)83 z!TwA0Be6;Xrw0{`;jpK9v`3wAv(oV&K}=Augmdh+QqPGgl^-{M}Vfbg#tkU$Z-ufN8x)REfFo1 zF2~Te(|lZ$JX<2=;EQcX`4kVH2pdzY3aR9OK-1r1bP%HcgCEaTX6s$WgSzaW(zOPy z0zm+`Xc?!+`SF_FT_=&jPkmBnwsxTnJ&_}@v-e4c?cl}ZqX`84iQ>f?ZcBH)1H*f^ zY+drN2$ZP$B)w*F^{zz%KowHaksJ7g+}5gzD&e~*9SaJh-j)F@2|$Jvt{-(??qRzqe3aB+LaR7y8ZN}cNekwR-Nn$fQ362#sf(wn?ykER%X0EiBAv6};6OJB v)qfdSfN*(fncrd!A*qCXCE&b@Un4gwRyCC=VfH% zW@RvFoM*^wz{$oO%EBhh6dG(OV893BaPYAE=I50p<|V>J*m>BU@~cvF6Y~s34TM2z zxOjNV^K;UIgMH$S4a|)UB@M(u!rVLp0Y&-gMTxn&nR)5DU?~X$F_0894}W=ixgJPY zadD1ba(=F%yn!s-L7a?Y0-1Sf`3^`54CKUljSLJ7jf@OTO$|*fqJUf@Ljyw#D0lFC zpowu2a-cJ^GB7tW_A?kXF?KOEF*Y)+u?)!QulOM_J7e1AhjYR*q8yVRZ+6@e+91B6 zLu~eg=_T<_mBmi?Cx2cw_nmJ3sy*rxS`Ne>f8+ToCQY_rPH@bwg_|Qz+V#yYvdv>+ zVwjT}*0fk@3rD=x`}?ylJU5I~i{_R|PW*p0(@2u7j^DwiO76s;h@6yl0=6rZ|My9q z%4&M_lQBhS`U0uW1tpiau?l`lV)M}Yo_6kF>%&XxuTBXqojBd@&lI-Ezyr^Px3yQt zUpf$`A1BLnSWxHwcg9$z9_!j!#yU1L%JV<0FFUSrEA0LLJ8Gs5`_>+}Si6L6&8ZiGuMhml zVA7erP-M@K#J1~U*NeZb-kqg*xkG8o^ZfdWPx+2GvHTEG}l1ExmiP+2|}F%}Wqi!F!NZ&2{uQ_}8ev3l2~ zD?E!=7&P7k$t$xoUNdOC+<;Zh!p0>_8W#@wblHTxc;Er~Pnd<(fSHl;KRDOQ3bODU z@HTO$RwU*YIuP>}+yK1Sc^6ZY^xgN9H zZGEyYw!i8^28M&a^e~c3mWr)iL>$>Z6#eyI#zFe?6m&b&`kVB*Dr<{{%gK zuU+gnl8Lu=)Zy4vlq&PIjcLl}xdyi)ofdA8W0*8Kk5~Qt{Tt`C&z|o2zcs&kk~%{~ zHYfCG#&MqdDaA{@Uw>4ew)JObw)VE9 z>sGuDsULXnO)S6iZMSf>S7?8oXKJUp8>{{Vkz!t5xg}S2`{iohs?00qxEHT}M_J@{ z^>Zd+z2j3PKiBFV>B`*obyw1%j;*JUPg>OVI8z|+=#EVSb=!CfwGO{5(J?*MNu09XY{`Tzg` literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/3072/client-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/3072/client-cert.pem new file mode 100644 index 000000000..4359a8817 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/3072/client-cert.pem @@ -0,0 +1,111 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 2f:06:07:a8:b6:f4:ee:10:91:43:de:e1:46:99:c4:90:79:e6:f1:d1 + 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: Jan 22 05:51:48 2020 GMT + Not After : Oct 18 05:51:48 2022 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 + RSA Public-Key: (3072 bit) + Modulus: + 00:ac:39:50:68:8f:78:f8:10:9b:68:96:d3:e1:9c: + 56:68:5a:41:62:e3:b3:41:b0:55:80:17:b0:88:16: + 9b:e0:97:74:5f:42:79:73:42:df:93:f3:aa:9d:ee: + 2d:6f:aa:bc:27:90:84:c0:5d:c7:ec:49:ea:5c:66: + 1d:70:9c:53:5c:ba:a1:b3:58:c9:3e:8e:9b:72:3d: + 6e:02:02:00:9c:65:56:82:a3:22:b4:08:5f:2a:ef: + df:9a:d0:e7:31:59:26:5b:0b:1c:63:61:ff:d5:69: + 32:19:06:7e:0f:40:3c:7a:1e:c8:fc:58:6c:64:ae: + 10:3d:a8:23:ff:8e:1a:ca:6a:82:e2:f9:01:64:2c: + 97:a0:1a:89:a0:74:d3:b6:05:11:f2:62:06:48:2a: + f7:66:ce:c1:85:e1:d2:27:ea:ca:12:a5:91:97:3e: + fc:94:06:59:51:c0:e7:13:b6:87:7b:5f:d2:c0:56: + 2f:5e:1d:02:c3:11:2c:df:f7:01:da:bd:85:54:35: + 32:5f:c5:c8:f9:7a:9f:89:f7:03:0e:7e:79:5d:04: + 82:35:10:fe:6d:9b:bf:b8:ee:e2:62:87:26:5e:2f: + 50:2f:78:0c:e8:73:4f:88:6a:d6:26:a4:c9:fc:fa: + 1e:8a:b0:f4:32:cf:57:cd:a1:58:8a:49:0f:bb:a9: + 1d:86:ab:b9:8f:8d:57:19:b2:5a:7e:a4:ea:cc:b7: + 96:7a:3b:38:cd:de:e0:61:fc:c9:06:8f:93:5a:ce: + ad:2a:e3:2d:3e:39:5d:41:83:01:1f:0f:e1:7f:76: + c7:28:da:56:ef:bf:dc:26:35:40:be:ad:c7:38:ad: + a4:06:ac:ca:e8:51:eb:c0:f8:68:02:2c:9b:a1:14: + bc:f8:61:86:d7:56:d7:73:f4:ab:bb:6a:21:d3:88: + 22:b4:e7:6f:7f:91:e5:0e:c6:08:49:de:ea:13:58: + 72:a0:aa:3a:f9:36:03:45:57:5e:87:d2:73:65:c4: + 8c:a3:ee:c9:d6:73:7c:96:41:93 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 3D:D1:84:C2:AF:B0:20:49:BC:74:87:41:38:AB:BA:D2:D4:0C:A3:A8 + X509v3 Authority Key Identifier: + keyid:3D:D1:84:C2:AF:B0:20:49:BC:74:87:41:38:AB:BA:D2:D4:0C:A3:A8 + DirName:/C=US/ST=Montana/L=Bozeman/O=wolfSSL_3072/OU=Programming-3072/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:2F:06:07:A8:B6:F4:EE:10:91:43:DE:E1:46:99:C4:90:79:E6:F1:D1 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Alternative Name: + DNS:example.com + Signature Algorithm: sha256WithRSAEncryption + 04:f5:e0:e5:75:6b:cf:ee:19:ef:3c:b5:b6:78:ce:b2:c3:f2: + 3e:0d:3f:b7:6d:59:7d:b6:7e:6a:91:0f:85:ac:ca:56:30:3c: + 3f:5d:30:10:7c:5e:7f:98:b2:9d:95:04:e1:ee:c0:9e:1b:01: + 39:cb:02:05:b9:9b:02:88:eb:d0:ad:06:d5:39:2d:24:e6:dc: + 4e:ce:8c:36:7d:b6:8e:1d:e8:b7:ef:ff:b4:17:c1:a5:d8:fa: + 34:dd:99:3d:30:4b:45:a2:14:6a:88:93:ca:25:e2:5c:d5:ba: + e8:9d:ef:d7:68:76:05:92:48:19:92:11:79:c2:fe:11:49:4d: + d6:d1:8f:32:1c:5f:3b:41:2c:08:b2:72:65:1c:e5:86:02:94: + b3:9d:30:da:59:42:a1:b0:1e:00:92:93:6e:0d:27:cf:df:d8: + cf:2b:cd:cb:8c:ff:b5:6f:83:92:27:00:58:59:a2:0b:91:b0: + 39:ca:a8:78:fd:83:56:4f:a1:6e:c3:e0:2b:ae:ef:3c:09:04: + f0:9b:5b:00:d3:ed:b6:06:f6:9c:da:af:61:68:8f:e3:2a:c3: + 85:20:66:2c:ac:dd:65:37:36:c2:2f:ba:b8:90:66:6e:9e:58: + a2:4b:d6:a7:30:c8:c9:6c:bd:13:40:a0:ca:59:7c:c5:86:9c: + 55:c5:68:c7:0c:7f:94:73:a5:4b:eb:f1:27:96:b5:f9:69:6b: + 2b:b6:62:d7:3a:0d:40:65:f0:0d:de:91:77:d4:f6:bb:13:7b: + 4a:55:8f:7e:49:65:89:37:46:05:2f:90:14:73:0d:2d:1e:a4: + d4:bb:4e:6d:29:da:79:6e:73:08:de:5f:27:dc:23:14:db:7b: + e7:02:13:2e:c7:94:19:f3:7d:2e:c4:8a:69:ba:f5:ba:62:c2: + 88:b5:cb:c7:92:a2:8a:e3:69:10:6e:c5:b8:b2:10:7e:b6:0c: + 71:2a:c3:e9:71:0c:a2:8b:9a:1d:2c:4e:21:68:53:51:6d:0c: + d2:b4:4b:50:4b:0a +-----BEGIN CERTIFICATE----- +MIIF+DCCBGCgAwIBAgIULwYHqLb07hCRQ97hRpnEkHnm8dEwDQYJKoZIhvcNAQEL +BQAwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC +b3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzMwNzIxGTAXBgNVBAsMEFByb2dyYW1t +aW5nLTMwNzIxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJ +ARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0yMDAxMjIwNTUxNDhaFw0yMjEwMTgwNTUx +NDhaMIGeMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwH +Qm96ZW1hbjEVMBMGA1UECgwMd29sZlNTTF8zMDcyMRkwFwYDVQQLDBBQcm9ncmFt +bWluZy0zMDcyMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0B +CQEWEGluZm9Ad29sZnNzbC5jb20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGK +AoIBgQCsOVBoj3j4EJtoltPhnFZoWkFi47NBsFWAF7CIFpvgl3RfQnlzQt+T86qd +7i1vqrwnkITAXcfsSepcZh1wnFNcuqGzWMk+jptyPW4CAgCcZVaCoyK0CF8q79+a +0OcxWSZbCxxjYf/VaTIZBn4PQDx6Hsj8WGxkrhA9qCP/jhrKaoLi+QFkLJegGomg +dNO2BRHyYgZIKvdmzsGF4dIn6soSpZGXPvyUBllRwOcTtod7X9LAVi9eHQLDESzf +9wHavYVUNTJfxcj5ep+J9wMOfnldBII1EP5tm7+47uJihyZeL1AveAzoc0+IatYm +pMn8+h6KsPQyz1fNoViKSQ+7qR2Gq7mPjVcZslp+pOrMt5Z6OzjN3uBh/MkGj5Na +zq0q4y0+OV1BgwEfD+F/dsco2lbvv9wmNUC+rcc4raQGrMroUevA+GgCLJuhFLz4 +YYbXVtdz9Ku7aiHTiCK0529/keUOxghJ3uoTWHKgqjr5NgNFV16H0nNlxIyj7snW +c3yWQZMCAwEAAaOCASowggEmMB0GA1UdDgQWBBQ90YTCr7AgSbx0h0E4q7rS1Ayj +qDCB3gYDVR0jBIHWMIHTgBQ90YTCr7AgSbx0h0E4q7rS1AyjqKGBpKSBoTCBnjEL +MAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4x +FTATBgNVBAoMDHdvbGZTU0xfMzA3MjEZMBcGA1UECwwQUHJvZ3JhbW1pbmctMzA3 +MjEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tghQvBgeotvTuEJFD3uFGmcSQeebx0TAMBgNVHRMEBTADAQH/ +MBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4IBgQAE9eDl +dWvP7hnvPLW2eM6yw/I+DT+3bVl9tn5qkQ+FrMpWMDw/XTAQfF5/mLKdlQTh7sCe +GwE5ywIFuZsCiOvQrQbVOS0k5txOzow2fbaOHei37/+0F8Gl2Po03Zk9MEtFohRq +iJPKJeJc1brone/XaHYFkkgZkhF5wv4RSU3W0Y8yHF87QSwIsnJlHOWGApSznTDa +WUKhsB4AkpNuDSfP39jPK83LjP+1b4OSJwBYWaILkbA5yqh4/YNWT6Fuw+Arru88 +CQTwm1sA0+22Bvac2q9haI/jKsOFIGYsrN1lNzbCL7q4kGZunliiS9anMMjJbL0T +QKDKWXzFhpxVxWjHDH+Uc6VL6/EnlrX5aWsrtmLXOg1AZfAN3pF31Pa7E3tKVY9+ +SWWJN0YFL5AUcw0tHqTUu05tKdp5bnMI3l8n3CMU23vnAhMux5QZ830uxIppuvW6 +YsKItcvHkqKK42kQbsW4shB+tgxxKsPpcQyii5odLE4haFNRbQzStEtQSwo= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/3072/client-key.der b/FreeRTOS-Plus/Source/WolfSSL/certs/3072/client-key.der new file mode 100644 index 0000000000000000000000000000000000000000..be253d2f009f91cda20f85d30285f793b7faccf3 GIT binary patch literal 1768 zcmVxL9kVT7qEyHo8Xsp zUqX3vLf@0~s-5mFZ>qc}kc7Zp$LvY!TxK0`oKsx7p|e=YK8~AmJ#GR50Gwr3f}*d;`sq&ESI1f ziJ)}TwgnOLVg^Vm_h!z)h2hdC>dF$Ok(WOFlm=N*z~>XThkIYrz*a9_9RkA zu=Fy|SIwbVib)Tw7?2ua@R6IgPfsyg{L14UO}hthLp#Ehfv$<}jxmO+yO0|5X50)hd6KpAw~ z^~y*|rVZa!Ec;6hyUFTIWkY49?C#_}LTvHEZ3U-r9DW~2slYDRp8=S{KG%a0HP%}b zhpwzL_};b%B~Dqo3GBv~1cm66#=8T0lps4NhiW!KeAV=U91A(?6sM*EH&95`##fpf z0RkU@G(`#KzcCrN;kw%E8nDgvrjcW;DCCdoe)bAVaUrGga19&TaAb5>FQ4qxlNQJB z_`si1N*}G=K$uf#`re`hpd+F74#H-_Y^%JZyyDw_23X*)8how9t_*cNG{7Yq}~7 z@sgd^1O>J@!r-SZWcc3+JOIJj4LZFq}gH0)fE**+cd$cqY>46{iY_UfV6N#;I>}h&yTsAN7E>E-8z0 z_%+BQ7#s}_ID)%dFSJ}vBn78Tc}R(k932WQ{@Iz|C5kQh>o3|HW8uvSmt+*H>I>N7 zs48PMknVr#&ZX~vtA|IMMKzk*jP%or3!CQZlDh@rtUfi{?PVRdlItmX_&>r}Kr&{B zR#5-HKE3IbzcIdtE$?I=4re-?l-gSij6Lq1&63_g0%bPI8})up2ef|_4g)TR@I_zT zqUgti0)fE*%I&2;S*%R0t0MxHfS|867u)B5azQLyv_pkPbDvo0K#T0K?}kh<-pFip zb)ws4^ial`qHx}}BEkU`NfV&rAb3RVA40Pw3C?vBbv6-4EIbt-@Kn_pu3-nPJ%dIA zjK53nto@2eXU-?I;3Q2IW0)fD9#`Heg zt@g2I#bUVFJYgH&)Jp%LW*FWFJ2EwdgJC!f6!%+x%ICP6KtK)P)Fka1!9m(7N3~?Y z!u$F>KTTJyqmq?Q!gj90%V)-TdB@z&bGzu6W&T!=vh-r4U|@hriZ;LAa(=PX^&Mmv zCgnY6vI>itCj?}gl>8lYCc{?w?kkyPrO0#kXM?;emR~mH%DvzuG}cH|R;{DsJr}&Q z<|O`5#xKjXugB=!mWG|Qe;XzNGl$!1fA*TU!IbL)fx!TwG3HcMX+T9J=q-pQBl%3F)A5UV=*1X=1Q)})9K;wJmDWO zrh2{3;?iQ$TIqJFe5)A~hmECSrZ!iHJ7ig%x}RrqYKDZS2r)s^NC`V$Y+qJYf31GP zC+>>zH&ORVfTLw}5#6W0`dE8uw8EM-FTR9MEM{9cZ%4f_L<$0|jJakW6fKZ(LK3$Q zI*Y}aW&Mv+fq&%LSPu26Ipkpifx!T?l#eU@gf4?ZhE{&H_&mi7%e^uT*Q%$m>7;7W z0o#Wv_uuTo16@_9W^;L|tG%yjH~vAjQ?s(bv4Aw@;d`!U$MaYI61;e-bq%a}kQ7P& zYfRe_WaGXG8qPb4?sM69?1My zY-FwwJ*Xr9jvC5pg5voBWGt7U8i}BE)3yZ>@?r)^D)(m2!G+<{C+f-)rID9D{FDY+ zQNZUDwugIP(!f?PUL69%5iH;L0ouKVR5dbR#mM=3pNaPa4t{xE1cEgX{%xDTxbEU& zhbCSxP%n54=yOkqYSt#C$^7~rim>!D&sWW%Sc*vxyQv+9tGSPjR~fQeex&Nmx0ZT4 zIL+SRVf@JkkCR%?tt#U!J~>@Mg8?58;eU3=DB4!%jPE z0xX-M6ukIhhSyftbM&jbY9Z5zBDCjkf05-5#t2E?>JwOUpsG6gHUmXhUWd|iWyFl5 Q?#b43e3n6z0s{d60lVABH2?qr literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/3072/include.am b/FreeRTOS-Plus/Source/WolfSSL/certs/3072/include.am new file mode 100644 index 000000000..5606dcce9 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/3072/include.am @@ -0,0 +1,10 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + certs/3072/client-cert.der \ + certs/3072/client-cert.pem \ + certs/3072/client-key.der \ + certs/3072/client-key.pem \ + certs/3072/client-keyPub.der diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-cert.der b/FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-cert.der new file mode 100644 index 0000000000000000000000000000000000000000..c31698f65563655baadeecc0e895fd7c7f2803a1 GIT binary patch literal 1764 zcmXqLVtZiF#ByQ*GZP~dlZZb5YUMqPMc5~@g_<%Z*E{X~{mI#YmyJ`a&7=SQdU}~=H?LyD9TSSO3cm8%uCk=OGy}rfuxvu_{+=7^+39c zi*xjn^K%X54P@aC;$##P$jnR2cR*5LAScdiXlY<>U}<1%U}j(xCC+PPWMBe>5bogj zKogS^a-cJ^GB7tW@iQ1SF>x_9F)=cHy%0I`Z2K;g33m0lD?0r1j z%lMW5O>yB|kIeg#f*ee9*J~d)*vE6H{YsP&r*iDWvZy3;x03hFth?oMHA{2!=Cen|bEdG&0nFO)l%t{q$+z}4UeqHYv!!zfBE+NS(ODF7cj4R%>32<;5uOZ2}Zr+e)inZ6&o`{ZC>0}qR;ZbOtFzmlofm)5s|H&*BNFS1r)$ZLEg zS9WcUq0sHmee4VGb$VGQlpkI7G4L7N$Ejgj5Bnw=%>NhRvc~Px-&ucF$S%AbYVOtj zXO8iY<%u4SHFL`Czcwh>I&Zn!!F96qx{IW5c@8(1=PDWfYf&!C+>y36Q;KD z(pEAqC|*ky=C=F&pXK$=)}1$QX!ys7Pg@+g?_Vvqw1G{DEAz70j_8Pvhv%9~ioykBc{Kx}|s>|!1FwI`I*U!_v=w+|4ZpdtgI$jOtDmPJ?Un9L2&@-4Uh@#%cF=xQcrMh3>kO^iYY zO^kfN+`t?v%f}+dBJwMwGyQ4&c0-3(f1iI_d@L$VY-yfB<2{hPGE3t%gT~7ZSk)|S zT(YEb;h@hKP1uVk9+3ZpSy&C285#d0=Nn*Q11?g@yodOb~Qw)2Mc*e`+Q?Z(^_@?TtT@|9XOIli`HQpYQp1HquBKGAGa>t0RfqYS zl-Ux2?62-KOe>h$F}HvHJ{!N|aiOBN@=tW{oLsza{V$glkG|aRJNr|hzPs&AuIt2! z{*Ny#zjU*Y^VpBq&-aQ;UVARJ)S~&n%@(Ym)jK6OYEE3Ssc7|M&KDdP?6*AC)cIytnD<3mA=Jb{f5Ys%AMflJ zmtC&g%6RS4rm(OX#;tF^E&gU#{e^i+MBmZq)oCyIO~iGL%?f#T+^l%c_UD%W!e6&b z&b?|?|5>_nZ9rSzD@I01UJb9eZ2M9RHnF+siG|+}J>GXVdTpAC??dG!|M;RqB*C+A^a2JJi^B$jGw|n-c@5Szg)fK5`_rr_kInC(; E01jNT`~Uy| literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-cert.pem new file mode 100644 index 000000000..57e303920 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-cert.pem @@ -0,0 +1,130 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 2f:0f:ab:23:bc:a3:14:07:91:06:55:35:01:63:7f:42:bd:fb:f2:43 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_4096, OU = Programming-4096, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Validity + Not Before: Jul 9 03:06:02 2019 GMT + Not After : Apr 4 03:06:02 2022 GMT + Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_4096, OU = Programming-4096, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (4096 bit) + Modulus: + 00:f5:d0:31:e4:71:59:58:b3:07:50:dd:16:79:fc: + c6:95:50:fc:46:0e:57:12:86:71:8d:e3:9b:4a:33: + ea:4f:d9:17:13:6d:48:69:df:59:11:08:02:9d:af: + 2b:c7:30:be:0c:dc:87:d4:5a:12:09:23:5d:e1:76: + 5a:62:37:46:74:ef:03:05:bb:1e:6d:29:75:6c:2e: + 9d:87:0d:8f:87:cb:14:95:9b:be:17:6b:51:d1:4c: + da:d7:91:66:c5:36:eb:e0:07:1a:76:4d:b0:fb:c1: + f5:5e:05:db:ba:cb:25:d9:99:13:1c:c0:35:dc:40: + e9:36:cd:c4:d5:7a:41:70:0f:36:eb:a5:4e:17:05: + d5:75:1b:64:62:7a:3f:0d:28:48:6a:e3:ac:9c:a8: + 8f:e9:ed:f7:cd:24:a0:b1:a0:03:ac:e3:03:f5:3f: + d1:96:ff:2a:7e:08:b1:d3:e0:18:14:ec:65:37:50: + 43:c2:6a:8c:f4:5b:fe:c4:cb:8d:3f:81:02:f7:c2: + dd:e4:c1:8e:80:0c:04:25:2d:80:5a:2e:0f:22:35: + 4a:f4:85:ed:51:d8:ab:6d:8f:a2:3b:24:00:6e:81: + e2:1e:76:d6:ac:31:12:db:f3:8e:07:a1:de:89:4a: + 39:60:77:c5:aa:f1:51:e6:06:f1:95:56:2a:e1:8e: + 92:30:9f:fe:58:44:ac:46:f2:fd:9a:fc:a8:1d:a1: + d3:55:37:4a:8b:fc:9c:33:f8:a7:61:48:41:7c:9c: + 77:3f:f5:80:23:7d:43:b4:d5:88:0a:c9:75:d7:44: + 19:4d:77:6c:0b:0a:49:aa:1c:2f:d6:5a:44:a6:47: + 4d:e5:36:96:40:99:2c:56:26:b1:f2:92:31:59:d7: + 2c:d4:b4:21:d6:65:13:0b:3e:fb:ff:04:eb:b9:85: + b9:d8:d8:28:4f:5c:17:96:a3:51:be:fe:7d:0b:1b: + 48:40:25:76:94:dc:41:fb:bf:73:76:da:eb:b3:62: + e7:c1:c8:54:6a:93:e1:8d:31:e8:3e:3e:df:bc:87: + 02:30:22:57:c4:e0:18:7a:d3:ae:e4:02:9b:aa:bd: + 4e:49:47:72:e9:8d:13:2d:54:9b:00:a7:91:61:71: + c9:cc:48:4f:ee:df:5e:1b:1a:df:67:d3:20:e6:44: + 45:98:7e:e7:0e:63:16:83:c9:26:5d:90:c1:e5:2a: + 5c:45:54:13:b2:81:18:06:20:2e:2e:66:5a:b5:7b: + 6e:d6:0c:4e:89:01:56:70:bb:ae:de:e9:99:5e:d1: + b9:3a:b7:6c:17:b6:03:a9:08:dd:9c:f4:14:c9:c9: + 59:39:72:d4:7e:02:37:31:cd:0e:a7:3d:f8:f2:cf: + 6b:15:ab + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + FA:54:89:67:E5:5F:B7:31:40:EA:FD:E7:F6:A3:C6:5A:56:16:A5:6E + X509v3 Authority Key Identifier: + keyid:FA:54:89:67:E5:5F:B7:31:40:EA:FD:E7:F6:A3:C6:5A:56:16:A5:6E + DirName:/C=US/ST=Montana/L=Bozeman/O=wolfSSL_4096/OU=Programming-4096/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:2F:0F:AB:23:BC:A3:14:07:91:06:55:35:01:63:7F:42:BD:FB:F2:43 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 57:0d:97:98:78:bf:2a:31:9a:39:41:38:33:46:d5:50:47:e8: + 19:62:a8:36:1e:b7:fd:d1:bc:50:5c:3a:eb:96:1a:9b:43:b0: + 67:5d:f4:51:77:87:33:0b:90:6f:e8:d3:82:4d:1a:aa:93:5f: + 7d:78:b1:e0:7b:ee:88:01:e7:b3:fa:7e:0b:76:9c:9e:81:36: + e4:a3:c1:41:62:a4:0a:7e:24:d0:ab:9f:ba:d8:1e:38:ad:f1: + 12:52:0d:f2:96:8a:0b:25:a2:49:3f:88:5b:ea:23:87:26:22: + 7a:b9:60:6b:d6:7a:88:37:ac:64:9b:18:51:07:ea:df:00:96: + 70:95:88:9d:8f:af:be:3c:4e:c7:5e:55:15:3d:1f:e4:2d:dc: + c9:a3:ae:af:fa:44:a8:e2:f4:df:8e:cd:f9:10:7f:8b:86:cc: + 6d:45:91:91:4f:e3:d0:a7:d2:d9:8e:09:c6:f8:eb:e7:bd:17: + 19:d6:e7:1a:b8:ca:4d:ec:34:07:7d:2d:e8:23:9d:82:e9:f7: + 47:03:ab:5f:7c:f5:41:6f:70:11:cb:24:d8:23:c2:65:31:b7: + 0b:8f:0a:26:5b:0f:f6:9b:11:7f:9a:8d:94:6d:5a:9c:5e:73: + 35:15:7b:e3:09:e8:08:d0:3f:b4:e5:29:2c:f6:3e:71:6e:f4: + 1b:20:55:34:40:2f:b0:9b:dd:f1:dc:bf:17:1d:a7:2d:85:01: + d6:d2:b2:56:56:98:33:85:ed:f6:a3:f6:3e:7b:f4:03:a4:58: + 8e:c5:5b:ab:66:e8:0f:34:17:2d:33:36:71:0c:b8:d9:78:e7: + 06:fc:da:4f:a1:fa:db:74:ce:ea:85:27:f9:75:a9:ad:50:86: + 6e:ea:01:01:19:0d:28:4a:ed:06:be:65:70:b2:06:46:2e:16: + 57:df:55:c7:8e:cd:5b:ad:66:28:b8:74:87:bf:c4:c7:08:3f: + 37:a3:23:84:9f:4e:e8:48:6c:8d:54:9f:fb:e0:fb:53:a3:41: + e1:68:8a:94:c9:f5:ee:3e:15:46:d2:62:33:86:86:06:34:b4: + e4:2f:da:28:2e:2f:c0:bd:75:e8:2c:3f:e2:a5:43:7d:02:eb: + 25:b9:ef:87:8a:d7:57:61:16:e8:9e:83:65:f9:10:f4:5e:5f: + 1c:7a:25:d6:47:bd:29:c5:4f:8b:b9:6a:48:7a:9b:1e:6d:77: + 8e:72:6c:0c:07:fe:4c:c5:cf:55:0e:cb:4b:ad:16:e1:e2:54: + b8:9d:34:03:d1:8d:b7:37:9b:e3:5a:32:60:03:7f:61:0f:50: + 0b:72:54:8b:0d:c7:97:7e:bb:9b:b2:f7:73:47:71:7b:78:65: + 36:df:57:72:9e:42:9c:8a +-----BEGIN CERTIFICATE----- +MIIG4DCCBMigAwIBAgIULw+rI7yjFAeRBlU1AWN/Qr378kMwDQYJKoZIhvcNAQEL +BQAwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC +b3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzQwOTYxGTAXBgNVBAsMEFByb2dyYW1t +aW5nLTQwOTYxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJ +ARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0xOTA3MDkwMzA2MDJaFw0yMjA0MDQwMzA2 +MDJaMIGeMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwH +Qm96ZW1hbjEVMBMGA1UECgwMd29sZlNTTF80MDk2MRkwFwYDVQQLDBBQcm9ncmFt +bWluZy00MDk2MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0B +CQEWEGluZm9Ad29sZnNzbC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQD10DHkcVlYswdQ3RZ5/MaVUPxGDlcShnGN45tKM+pP2RcTbUhp31kRCAKd +ryvHML4M3IfUWhIJI13hdlpiN0Z07wMFux5tKXVsLp2HDY+HyxSVm74Xa1HRTNrX +kWbFNuvgBxp2TbD7wfVeBdu6yyXZmRMcwDXcQOk2zcTVekFwDzbrpU4XBdV1G2Ri +ej8NKEhq46ycqI/p7ffNJKCxoAOs4wP1P9GW/yp+CLHT4BgU7GU3UEPCaoz0W/7E +y40/gQL3wt3kwY6ADAQlLYBaLg8iNUr0he1R2Kttj6I7JABugeIedtasMRLb844H +od6JSjlgd8Wq8VHmBvGVVirhjpIwn/5YRKxG8v2a/KgdodNVN0qL/Jwz+KdhSEF8 +nHc/9YAjfUO01YgKyXXXRBlNd2wLCkmqHC/WWkSmR03lNpZAmSxWJrHykjFZ1yzU +tCHWZRMLPvv/BOu5hbnY2ChPXBeWo1G+/n0LG0hAJXaU3EH7v3N22uuzYufByFRq +k+GNMeg+Pt+8hwIwIlfE4Bh6067kApuqvU5JR3LpjRMtVJsAp5FhccnMSE/u314b +Gt9n0yDmREWYfucOYxaDySZdkMHlKlxFVBOygRgGIC4uZlq1e27WDE6JAVZwu67e +6Zle0bk6t2wXtgOpCN2c9BTJyVk5ctR+AjcxzQ6nPfjyz2sVqwIDAQABo4IBEjCC +AQ4wHQYDVR0OBBYEFPpUiWflX7cxQOr95/ajxlpWFqVuMIHeBgNVHSMEgdYwgdOA +FPpUiWflX7cxQOr95/ajxlpWFqVuoYGkpIGhMIGeMQswCQYDVQQGEwJVUzEQMA4G +A1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEVMBMGA1UECgwMd29sZlNT +TF80MDk2MRkwFwYDVQQLDBBQcm9ncmFtbWluZy00MDk2MRgwFgYDVQQDDA93d3cu +d29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CFC8P +qyO8oxQHkQZVNQFjf0K9+/JDMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQAD +ggIBAFcNl5h4vyoxmjlBODNG1VBH6BliqDYet/3RvFBcOuuWGptDsGdd9FF3hzML +kG/o04JNGqqTX314seB77ogB57P6fgt2nJ6BNuSjwUFipAp+JNCrn7rYHjit8RJS +DfKWigslokk/iFvqI4cmInq5YGvWeog3rGSbGFEH6t8AlnCViJ2Pr748TsdeVRU9 +H+Qt3Mmjrq/6RKji9N+OzfkQf4uGzG1FkZFP49Cn0tmOCcb46+e9FxnW5xq4yk3s +NAd9LegjnYLp90cDq1989UFvcBHLJNgjwmUxtwuPCiZbD/abEX+ajZRtWpxeczUV +e+MJ6AjQP7TlKSz2PnFu9BsgVTRAL7Cb3fHcvxcdpy2FAdbSslZWmDOF7faj9j57 +9AOkWI7FW6tm6A80Fy0zNnEMuNl45wb82k+h+tt0zuqFJ/l1qa1Qhm7qAQEZDShK +7Qa+ZXCyBkYuFlffVceOzVutZii4dIe/xMcIPzejI4SfTuhIbI1Un/vg+1OjQeFo +ipTJ9e4+FUbSYjOGhgY0tOQv2iguL8C9degsP+KlQ30C6yW574eK11dhFuieg2X5 +EPReXxx6JdZHvSnFT4u5akh6mx5td45ybAwH/kzFz1UOy0utFuHiVLidNAPRjbc3 +m+NaMmADf2EPUAtyVIsNx5d+u5uy93NHcXt4ZTbfV3KeQpyK +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-key.der b/FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-key.der new file mode 100644 index 0000000000000000000000000000000000000000..34a6f1b7cca4bd8196453bf92cb5b0982af2bd56 GIT binary patch literal 2348 zcmV+{3Dfp4f(a-B0RRGm0s#Q^&@tq3Sy;0NP~8@J{Kl0~{6-E}5{7Y&QC7h z6KzOo-&qj|0-dib$1uJO+=tX!5(y(+;dWYLH%4^t0|mPtZ7FqZE}e%BkB7??m7Bg7 zYf;fm+Sie0#Ww5U2O4%wu=~OFUIp8_%O%;F6CA)b+(79z&BWDuL2wT?>!nT?1=V#M zWMXSfH&8>uYK-(-{>00T zKY;@G!rkP-j(`jVB`ttjE)OC#O7w;8QP`_(kD@yy0B(We9(LBOF%sMJjt8OMiAp(O zcg3plQRW8ml~yX@j*>8+{#Zn;M)Lid{HPtF(^WT0i~O83_@`k=L42HdKlOkkeM7X> zhziMd*F+gjcWes^Nva$#)>=fSM@{86mOz;-Rwl9Xk}+A=EY!3i)@2h5KKuU!>$!!w z*w`pfTo;z3QNI3t3mZs4C3ckDLHoaRcG~N+V&}ogRBDsqjWOsxKHt2D0x%+1#NZfu z)2`$Ko2tD|Nk?+&jT0?Yn*gVgVR6aKNKfwHUK<+UXVW0&L`9f>=MG~QgUKdckiq3D zTt!q9vVj-|ATBOuTD5y_)(lRG0akFkuHNaHUeUQaw`>=-1E~nzob(jQ$yqsa)P4dt zG0hIAJ^1p^YZa>k0|5X50)heo0L6A!eeq}-j>coT7NaZS!gT5q#MVJ|YNpnn8h@3{ zO40PQCnl9zkqP8L6Gf4qpeyLZ+*|g248jko>2+9r>eWq>KKyhjhrvC$A(Blff`q7| z5tH(aDI6L2Z9gYbwJoE^C>_N7n3Sl{|L_mo`R%i!w(SjHzj$2Nuf3!1hUrme+fp}2 zf9YR5l!GnkoHOxk>GP(S{-?i9n;_LM-lPV*?q*4A^$>-hgj!NQ44_I(+5yF4F|q9U z-J?6sK{^t7`IlPkd@Wmq*nrJK?Rj!VZ?vCtUMx9_%G8ZUW#7Qb3K9$Aa_C5E-&#}VE zcKAKM^ke)g0B@P5wyibp-o@aT#&hm7ps4&zkMfLR`vV!F=oe1oAz04-@?X2%Pxlzh zHCNr`P%3*G=@RmK5wSzLa0d*JX}RU4$>JN9bP@HHxmduxH~T0my@atVXF`I*l~qO6 z>cfgcIzty;&C=@p-)HRMY^VbnvK>laPv_I%hQ%5X!wAytg_8(T1*SI@GQDhbV*y=T zPiow49aWJb(+~;8*^I3^WOA*RHIWZX$-PfyN2V?7KjN8kW)kh| z(tQ6qAU7)0Wl@{Msu-~!Zk<3!q#uHt+fZwUFZ(|+xq%S`6k~=@Kq~e5e4%(56VOpn z4|#}<6r?7y*~Ksn zSlG9<>=dj)WNqZeS^X3RU}f0EghYNDw4@ew!6%lo8P+*ez?1XWAI%%z_!5W|pO^(l zMsa~`-;wWAI-<)%2p=6uljBhoV;fy3i{g<3ce1Lla^$V|}pvP~y5h0Qv2gKL6V+28K<)9L;k z?*XyD;$Cy%oBgW z1`>>Kmr#3*fx{ye>u?8-p$8sW`Vh)~58}J-h9(|WxtL~!>?g(9V~tUFs-QMiGY}zO z>_=yD(XaeIQ1!mnlIIHof&l;_e2T=zDOG5vt=$D>WAOY2rb2L!S64P_k+TI>oXMKu zi`RcopQa5#70HAx4Pzw&V^z>*{F~XTK}MFUFK8?mG$3El(U;d%#=$5u;S5nMUGYPsi?%95-7t z5Z?>Kxkthy!yF9lZ{h zv3LqTC$09uUul$l1JANv8VA$*@{4tnaQ^<9-+>P_T}8aO{g2OGgb?nUe^(jx7u?yX24+e3e9{IBgRGk#~eOLtO(L0Sj7AD_QWnvA1Cx zZ2Y0>y&Rh441SkCamJ^V9fA_p=iHU>)Hg z&M|NoIm>odY*l-ZAiO!UThSsnq6==m0)RiruC%kpM92W3 S|B~tfMTyZ){!J@O80OAj1bPqv literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-key.pem new file mode 100644 index 000000000..cbe8090b4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-key.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEA9dAx5HFZWLMHUN0WefzGlVD8Rg5XEoZxjeObSjPqT9kXE21I +ad9ZEQgCna8rxzC+DNyH1FoSCSNd4XZaYjdGdO8DBbsebSl1bC6dhw2Ph8sUlZu+ +F2tR0Uza15FmxTbr4Acadk2w+8H1XgXbussl2ZkTHMA13EDpNs3E1XpBcA8266VO +FwXVdRtkYno/DShIauOsnKiP6e33zSSgsaADrOMD9T/Rlv8qfgix0+AYFOxlN1BD +wmqM9Fv+xMuNP4EC98Ld5MGOgAwEJS2AWi4PIjVK9IXtUdirbY+iOyQAboHiHnbW +rDES2/OOB6HeiUo5YHfFqvFR5gbxlVYq4Y6SMJ/+WESsRvL9mvyoHaHTVTdKi/yc +M/inYUhBfJx3P/WAI31DtNWICsl110QZTXdsCwpJqhwv1lpEpkdN5TaWQJksViax +8pIxWdcs1LQh1mUTCz77/wTruYW52NgoT1wXlqNRvv59CxtIQCV2lNxB+79zdtrr +s2LnwchUapPhjTHoPj7fvIcCMCJXxOAYetOu5AKbqr1OSUdy6Y0TLVSbAKeRYXHJ +zEhP7t9eGxrfZ9Mg5kRFmH7nDmMWg8kmXZDB5SpcRVQTsoEYBiAuLmZatXtu1gxO +iQFWcLuu3umZXtG5OrdsF7YDqQjdnPQUyclZOXLUfgI3Mc0Opz348s9rFasCAwEA +AQKCAgEAxXZXffFoGo7GY7kWoyvhwnTqEsTWQXVqptaeGn+VzErR9LMnJpVakQnk +QBNFkZ+gK+jD3Fv2fQzCD6npdVh96tVNkj78dCiHwT25IZJNKIKEqKIRk/KMKRwZ ++G0/J1G1LaPHKB3E/JiUqND/8A/c+e2zorbtDV+/eFzXr72j74bpUWbbUjdHf+lf +PJSDLeicM/Fs6fOml/6nv02bINUv3qQGu+5mSWv1EIWfhFpSPgygSkzaAcViMbHs ++N2jO85BOhJ5+ZdbB5WfhtYEc2zoj0xMSB2FxOfO3hYx9lw3VI5VvK8uR+isA7Ck ++ZCYmaTcbpgIXAe7CJOvYY10qPjEiWQQ4ebAzR05INZaiYP8N+ISZqgSzHK7Hvtq +43xxfrkujoRm4bnQJZpvnRnmfujY8MUjFppoLB1Vro6Q7o7sXkadYFIyFyhZxEkq +ID6Vxd/2PffFz7HCyXb4Pb70Y/wqAG+ZpratNe7exeCXxnPuM6Co/EyP8oxh+wMZ +oegXTuMhWM7+8l+73U/3GMs1V93lUCp7GukS8noRsUO5cAcMj2m55aXJ4huWdBH1 +lblYwL03+ygqvYSxK2dCgsOVVUXV6sOKQjpDF17N0ur832fs4WyoAxmyHUpfT+fT +4IbFGhDDCNLthZMIUQWmNxUyvWxzYwFdW09q3G0dVZEh5I638IECggEBAP0nyP52 +XIkyy4oih2FIkUoFraRcispcAoh+UcVmkCyj7adDGQuiQrTg4EW//qDydQuOfZ1z +Z9MQCcXZjK06ZHKtljWRD0vJvU9lR6Yt6z/imXJmEu3r0nz/OiA3KtNlUZvDqhix +H26dQEekH4Kb21Brhi/7PzG5gREEFGOGT0Aq9fl8oXgZE9BRUQ95iI0Uo962MylC +uehZdvdDGram3wrBQsc/HH5cLJFLHvhGkR/uVrMOyNAx0z3tPdnFMAxY2Le17BSs +QWRt5MZZ/RQFYGXYxIREfhu0pBZ1wSeWshnWOVTAk/PXH80b3/gSiBSfmAVHRnGB +bN+R71PjxbGJL+ECggEBAPiTSih3lO/pxArD6FJZth2NzhTnQ8btCSdd844Iahlr +LJebiFMr2v5LlGaE1anOpUNw+wFab8330Z1R7qDcRvV9p+6ghreD/yGLdgV93sQm +Nry0ikjDBpCX5aY4w+Z80Pgj0jMfgcPjfYVaOBAD5ojbyEzQ97JNJzOFzTp0g2uC +WNnf7vXT6f4c7wYSFtFMrlRLDRq94s9Ws3S+RE+kcwqYjWGEOEbclc8/a+dlhwK/ +S1fiPcQrHIIdzBN/wAYSjG+XUHuMgcMjFetwB46hBx5Z+hDKfg/iu+6GJh5VuZhm +hewnxdljjVF3qqA2VTMQIV7sR2dx0a/8PlD1vtaS5wsCggEAIXyKxMYpVWinrd0F +ZWPw/AamQnCPV1c2apGzBVacyZrhi9d/T5+mDUEVyYQtDWMlAmNV0Gb8m9mqQUaW +qi9oLBc0IF/Q0yibZw4xnRTD4o55170S0e/4xtoH+Uzy2EW1ttH6BQwg6UPZxeA6 +3s75ArlGZcBpSo2MOhD9FXEluIo2QUswHK/MhCjNfSuJWYgaaRJW0CVobAixiOGS +fgiyxjxsNejuPvS4XHvAW/0Ro1SmmUbiX0/H7pAcN1szEN8Lw7lHwjBK8hrrQSWU +KXrQlohG7mwU9ls9vU7UPwVbB7njmYdjysRxC3Ode7YP1BKMTF5yPf9txGEMdF9T +vjk0YQKCAQBf8vKwFiCOTsyWXzKA/xH17HO8y9v0oDBlWrWVgJf7wcvPpYCEoiwA +9omM3P9gcVyHYMfyqMb5WQw3TpXuz7gwMFWvHZWCptfHSf6/deuUCTAdvQ6XsXgK +Piet9sFfaZR8A8+yXhoH0/ryi3WScP7+mt+BDzRdRby4/Y/PXYQQ7pp/Vxn1F9x9 +cwusazUViyTLcsDXLq6q28ufZ4YUu+SQFXyVRKU4bRMCkXeENUNdAxwBC1pOK1nw +u7G3YRts/KHqvRya5Ax+lz9xxqeUHYIS7CZDbvYkCaADHRL/qJVgR0qwclXDaNL2 +vFtHRlGyySooasnRGzUWWiZvt7v3NXMrAoIBAFa62ALXSzBeGx4v8w288QVqaErh +6rPeYYyJRLpjXt8FJDJxZRo2L7wHdaPOnlKSlU0/yQa8oRQzN5WrmusE9hXDmxBW +U6Io8mjafZdSY6ybVqmrLh6eAXD/K20MS6bDOrPRp0teSS6V1mquWBNmjy+T5G6L ++pQwPuyWq0YgPsUwtOtBADlgHeEgzjFwFznLdlZsVXuQILw5slvRKG8MT0VrgsRX +Iww/Py2Dsz2O+Rrad1Qu/hYuupndyrPR2LuH4dCp1OaP6AA+SYrdpjKRADExIZgY +lMktJwW3mwkuu12/Z+gO0UR1gB0KIY+VdrD8GTz/kuoBRYnRTv5NK0sY5s4= +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-keyPub.der b/FreeRTOS-Plus/Source/WolfSSL/certs/4096/client-keyPub.der new file mode 100644 index 0000000000000000000000000000000000000000..5944acfc59da2923ed0d2c9220ae7fb9fda38618 GIT binary patch literal 550 zcmV+>0@?jAf&wBi4F(A+hDe6@4FLfG1potr0uKN%f&vNxf&u{m_0TcoaamZi2T zdHlweQ2a&?R}zMCjpLh2GwM&-7ZYtrY2R592m+n2E5|Ut4BUs*S`rB(UEy|GVmC%~ z?*j$99&IUgY%ZOL4UdP*6qTF47i&?`Oxo9xX2mw^;0GFZO|bjH^gxHtVHM7X{UI8)Ra7KMg2IYU8Y&sE_IG_st}rv7iI2;{)|S(U$)z zeh9JC;20F_Wj9bm!fK54TmHn$jX!|`_rl%e!H$3o1SKtiS}qSFHA?h_?NQjPZI7Zm zBmi!K;vRO^tT7VX^Nt6h-ib;%V0Xo;@loam@s(C8;f|6ppZ-`xtVZ(vn*698q0?12 zN{jrQGx(=rNI`s@cR%%jBYi`()rbnob=O20O?PYy3Q4LQFVPhXODnSH$2Ldeg4t0-LJ6PDw{{>5UUDRGR>&kzsMk%t%k}-(DLU z-)GYx=0ru9e&-Hj7K6zqU68@$DqKZW6S9FA1|TjjW?Hp-Zq^J=i2+t{yRP2pnO@Pk oI=5^WwgagM-JJ9k$;nwca@2kTH!;l)r#<-c&ubN{0s{d60Y~xuhyVZp literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/4096/include.am b/FreeRTOS-Plus/Source/WolfSSL/certs/4096/include.am new file mode 100644 index 000000000..ec3777aaa --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/4096/include.am @@ -0,0 +1,10 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + certs/4096/client-cert.pem \ + certs/4096/client-key.pem \ + certs/4096/client-cert.der \ + certs/4096/client-key.der \ + certs/4096/client-keyPub.der diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ca-cert-chain.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ca-cert-chain.der new file mode 100644 index 0000000000000000000000000000000000000000..3e6982de80cde983e8b96cc4ba57c3552dd05277 GIT binary patch literal 2151 zcmXqLV%}=d#4NXfnTe5!iId^h?=0Sb=V!Yc@Un4gwRyCC=VfH%W@RvFoN35yz{$oO z%EBhh6dG(OV893BaPYAE=I50p<|V>J*m>BU@~cvF6Y~rO4fsK7xOg~%6U$5T^Gh-e zB@DzsLfkz3&iQ%8r8y;;dFk`IvTR0iT z1Tyo|@*R*A7|4n98d?~b7#bUz8W|fJM2Yhn85$TGm_xaP+U^=s%nV10M_?cqY(lbg(}WcRNyXgmj!S7vEEX3%)J0jrvYjq{f@&Kb9Y2E<=6A29tqm$PXENeX5I8QuHP&COQi2f2HrmVNYLWolDT24-DB?U zdaZsx_e7o5UcK2`Yn800uKc9IyyxkgGoLuFoY24h>bG8ySdSCalE_>i<1Mo;6?@6e zzj>nBpowJ_Fyl^wW!$#^U;6~^?f8x6RD;GTRLQu)27-``%Z13eRLiplmMD1^$Q`WC zZemnI4q#AzZDQnSFlb`rVghCqhW$LJbVWAFwKzqewUGDvd}wgNnz6O z)AN@II8I&5HT&_>0~;uXw?sQ}cHDqN-jCO_?>v-+ro@x?yTlt!IqI*>ctQ zdmBoFr`Xt@N{*f{y7jWGu)gF)o7-hpXLi({e0u2mErk z#JHFHrZWT?rYrl+cpK;{yOZT6_nR9Uo4xnGHLHXa8I6Ao8h;{{80vlLf+dI5WbNM? zCvRSIL)PHwi>n5WC!rao~P*H>Q|W~?duExrE3xs-XgIQDOQ zy=5!Ug6H4dBV`iL>+wY_XQw+6(oAY`eb#4$%5mLYF0K2Kiu|)aet68_mO|jmya#!({Hb@a(Q(sIH&b(YFV)% zv)`+|rXj+gQ`)odo7^>7*kOI!cfEAVgh_=4eJ9R5O;A~HC}wFqG2rLw45yMR)0=ls H90>vdWAo;c literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ca-cert.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ca-cert.der index d0eab7a3ce08847c4bc6c9160c266eaa3289778b..8c0c64445846c7bfcdd5509b956f5df03536e0cb 100644 GIT binary patch delta 335 zcmV-V0kHnA39bnkFoFcCFoFY;paTK{0s;vDhX3`B5Z<`^kr=BQI50FZGch$XGcY+? z7Y#BoFflMUF*PzXFgdZ^rveCu|MiX#-njddi~}Nno+yZN0Ltd)m&(EMAD$AjxW`fI zDB(7>E#@x>Bg?5uhb6{ciAC!50GOY zw(J4FQZoz0{zKEoq>e9#e|kjf%2RBG?PYdzF#}HOy){%5^JIr>-!$Dcp@=)%O|Khd hkdkpQj>ydAU?i_G7CAGKQ2DE9LUejH+1C3()8Llkr=BQH83?WH!(OeF)%S& z7Y#8uFflVRF*q_YFfp;+rveDsfI7p{^x8L*i~}Nndapz~s&7+5vNNhfUsf>Fxt0r> zRa!YJ3r^%N@s(!DhBktYV|-1b?nt@=$B@^j#&lpvUooQjUOvNu;pHzufrBX}dC^k< zX*}%;FgrmVlA$c9oh;)chk4*tZjq=^+D0$JAW%LlN0$_^eFVBiQP6JTTB1vYoK4Mz z1ooLpmVt%QIT&BZ_Czf@z^i<9NEg>$J@CS2C h>64O>-eTFKJFIRbUnfellyLtr7w3L5k7c(4by)j5mWBWT diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ca-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ca-cert.pem index 6eacbebd0..7a8a56385 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/certs/ca-cert.pem +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ca-cert.pem @@ -1,12 +1,12 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15672591315981621815 (0xd9803ac3d2f4da37) + Serial Number: 9727763710660753659 (0x86fff58e10deb8fb) 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: May 7 18:21:01 2015 GMT - Not After : Jan 31 18:21:01 2018 GMT + Not Before: Apr 13 15:23:09 2018 GMT + Not After : Jan 7 15:23:09 2021 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 @@ -37,32 +37,32 @@ Certificate: 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:D9:80:3A:C3:D2:F4:DA:37 + serial:86:FF:F5:8E:10:DE:B8:FB X509v3 Basic Constraints: CA:TRUE Signature Algorithm: sha256WithRSAEncryption - 7a:af:44:3b:aa:6f:53:42:b2:33:aa:43:5f:56:30:d3:b9:96: - 0b:9a:55:5a:39:2a:0b:4e:e4:2e:f1:95:66:c9:86:36:82:8d: - 63:7c:4d:a2:ee:48:ba:03:c7:90:d7:a7:c6:74:60:48:5f:31: - a2:f9:5e:3e:c3:82:e1:e5:2f:41:81:83:29:25:79:d1:53:00: - 69:3c:ed:0a:30:3b:41:1d:92:a1:2c:a8:9d:2c:e3:23:87:79: - e0:55:6e:91:a8:50:da:46:2f:c2:20:50:3e:2b:47:97:14:b0: - 7d:04:ba:45:51:d0:6e:e1:5a:a2:4b:84:9c:4d:cd:85:04:f9: - 28:31:82:93:bc:c7:59:49:91:03:e8:df:6a:e4:56:ad:6a:cb: - 1f:0d:37:e4:5e:bd:e7:9f:d5:ec:9d:3c:18:25:9b:f1:2f:50: - 7d:eb:31:cb:f1:63:22:9d:57:fc:f3:84:20:1a:c6:07:87:92: - 26:9e:15:18:59:33:06:dc:fb:b0:b6:76:5d:f1:c1:2f:c8:2f: - 62:9c:c0:d6:de:eb:65:77:f3:5c:a6:c3:88:27:96:75:b4:f4: - 54:cd:ff:2d:21:2e:96:f0:07:73:4b:e9:93:92:90:de:62:d9: - a3:3b:ac:6e:24:5f:27:4a:b3:94:70:ff:30:17:e7:7e:32:8f: - 65:b7:75:58 + 9e:28:88:72:00:ca:e6:e7:97:ca:c1:f1:1f:9e:12:b2:b8:c7: + 51:ea:28:e1:36:b5:2d:e6:2f:08:23:cb:a9:4a:87:25:c6:5d: + 89:45:ea:f5:00:98:ac:76:fb:1b:af:f0:ce:64:9e:da:08:bf: + b6:eb:b4:b5:0c:a0:e7:f6:47:59:1c:61:cf:2e:0e:58:a4:82: + ac:0f:3f:ec:c4:ae:80:f7:b0:8a:1e:85:41:e8:ff:fe:fe:4f: + 1a:24:d5:49:fa:fb:fe:5e:e5:d3:91:0e:4f:4e:0c:21:51:71: + 83:04:6b:62:7b:4f:59:76:48:81:1e:b4:f7:04:47:8a:91:57: + a3:11:a9:f2:20:b4:78:33:62:3d:b0:5e:0d:f9:86:38:82:da: + a1:98:8d:19:06:87:21:39:b7:02:f7:da:7d:58:ba:52:15:d8: + 3b:c9:7b:58:34:a0:c7:e2:7c:a9:83:13:e1:b6:ec:01:bf:52: + 33:0b:c4:fe:43:d3:c6:a4:8e:2f:87:7f:7a:44:ea:ca:53:6c: + 85:ed:65:76:73:31:03:4e:ea:bd:35:54:13:f3:64:87:6b:df: + 34:dd:34:a1:88:3b:db:4d:af:1b:64:90:92:71:30:8e:c8:cc: + e5:60:24:af:31:16:39:33:91:50:f9:ab:68:42:74:7a:35:d9: + dd:c8:c4:52 -----BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIJANmAOsPS9No3MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD +MIIEqjCCA5KgAwIBAgIJAIb/9Y4Q3rj7MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAe -Fw0xNTA1MDcxODIxMDFaFw0xODAxMzExODIxMDFaMIGUMQswCQYDVQQGEwJVUzEQ +Fw0xODA0MTMxNTIzMDlaFw0yMTAxMDcxNTIzMDlaMIGUMQswCQYDVQQGEwJVUzEQ MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwIU2F3 dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xmc3Ns LmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZI @@ -76,11 +76,11 @@ XDjNdyXvvYB1U5Q8PcpjW58VtdMdEy8Z0TzbdjrMuH3J5cLX2kBv2CHccxtCLVOc J45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYTAlVTMRAwDgYD VQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290 aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t -MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkA2YA6w9L02jcwDAYD -VR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAeq9EO6pvU0KyM6pDX1Yw07mW -C5pVWjkqC07kLvGVZsmGNoKNY3xNou5IugPHkNenxnRgSF8xovlePsOC4eUvQYGD -KSV50VMAaTztCjA7QR2SoSyonSzjI4d54FVukahQ2kYvwiBQPitHlxSwfQS6RVHQ -buFaokuEnE3NhQT5KDGCk7zHWUmRA+jfauRWrWrLHw035F6955/V7J08GCWb8S9Q -fesxy/FjIp1X/POEIBrGB4eSJp4VGFkzBtz7sLZ2XfHBL8gvYpzA1t7rZXfzXKbD -iCeWdbT0VM3/LSEulvAHc0vpk5KQ3mLZozusbiRfJ0qzlHD/MBfnfjKPZbd1WA== +MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1jhDeuPswDAYD +VR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAniiIcgDK5ueXysHxH54SsrjH +Ueoo4Ta1LeYvCCPLqUqHJcZdiUXq9QCYrHb7G6/wzmSe2gi/tuu0tQyg5/ZHWRxh +zy4OWKSCrA8/7MSugPewih6FQej//v5PGiTVSfr7/l7l05EOT04MIVFxgwRrYntP +WXZIgR609wRHipFXoxGp8iC0eDNiPbBeDfmGOILaoZiNGQaHITm3AvfafVi6UhXY +O8l7WDSgx+J8qYMT4bbsAb9SMwvE/kPTxqSOL4d/ekTqylNshe1ldnMxA07qvTVU +E/Nkh2vfNN00oYg7202vG2SQknEwjsjM5WAkrzEWOTORUPmraEJ0ejXZ3cjEUg== -----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc-cert.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc-cert.der new file mode 100644 index 0000000000000000000000000000000000000000..b3f2f1ef5a54437d12c680b23759c50af22c31a2 GIT binary patch literal 655 zcmXqLV(K<%Vlr63%*4pV#L4iNPg61Nw8vrtE;bIWHji_*EX+&>jnfUe4LI4DLs{5_ znL>jNg$)Ej91b3?@WkSb%)IoH{5(Se13r)-I}dwsYGO%APAW`h|wL3#aGY?@?d^beF%lv@K=tJtKRFN}( literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc-key.pem new file mode 100644 index 000000000..39c761c80 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc-key.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgAuEzmHeXrEpZbSib +bqCTmwdxi01gY4WZ5rsWcOkK9oChRANCAAQC09lu1gGORci5kDHlwEzjnq0pOJi6 +ENbpCSqAqS4XKrmKvzODRuOVC+R3QLU7Q0UzD2FTfDdEwcv8gMroQ+qn +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-cert.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-cert.der new file mode 100644 index 0000000000000000000000000000000000000000..756876f9e5c1b1aacca05f8254ccb49e759cfe55 GIT binary patch literal 715 zcmXqLVmfZn#N@kxnTe5!iId@vCCd`Nr8(^eTx=X#Z64=rS(up(8mAj_8*s8QhqAB< zGld2l3L6N5I2=4&;fci=nR)3Y`FVx{27Dkvb{_WN)WnjKoK%V&Sw0pq7LnBt4y*Y{Tq)XpsikKQ7we=3q2M3`d62X+3ou$5 zuq)sPDG+94{LjK_zzn3oF)zyx5?}$Qqc-Hk!<@ljkjiAh%a!!|nbp6-8`>^Ur<<^> z?BSZ(v0$(KhWk?@)pu(j)7rNrQ~Lb$3N4Lk?{-~jcm2y`$Z()oGOa9b{^HbD$M@T- oZIg3n6wb__b9+TxaNdFp!PGq!B^sH>Q|5Mjx^c)>let+L0L#$g2LJ#7 literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-cert.pem new file mode 100644 index 000000000..b17122ad7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-cert.pem @@ -0,0 +1,57 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 18174562873897217159 (0xfc3904a40ea56c87) + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Development, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 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: (384 bit) + pub: + 04:ee:82:d4:39:9a:b1:27:82:f4:d7:ea:c6:bc:03: + 1d:4d:83:61:f4:03:ae:7e:bd:d8:5a:a5:b9:f0:8e: + a2:a5:da:ce:87:3b:5a:ab:44:16:9c:f5:9f:62:dd: + f6:20:cd:9c:76:3c:40:b1:3f:97:17:df:59:f6:cd: + de:cd:46:35:c0:ed:5e:2e:48:b6:66:91:71:74:b7: + 0c:3f:b9:9a:b7:83:bd:93:3f:5f:50:2d:70:3f:de: + 35:25:e1:90:3b:86:e0 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Key Identifier: + AB:E0:C3:26:4C:18:D4:72:BB:D2:84:8C:9C:0A:05:92:80:12:53:52 + 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 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:30:0d:0a:62:fb:e6:3a:fe:71:d8:2b:44:e5:97:34: + 04:a9:8c:0a:99:88:a0:bd:1f:b0:df:94:59:27:bb:2b:c6:2a: + be:a4:69:1b:cf:97:78:2a:28:96:ee:ba:d4:87:45:fd:02:31: + 00:c0:73:19:66:76:5e:9f:a3:65:85:41:ef:b7:7b:3d:63:6d: + 98:71:99:6f:9c:db:a8:5e:53:6e:a0:68:11:65:bc:78:74:28: + 69:c7:64:9d:88:f2:d8:c2:3d:29:03:83:23 +-----BEGIN CERTIFICATE----- +MIICxzCCAk2gAwIBAgIJAPw5BKQOpWyHMAoGCCqGSM49BAMDMIGXMQswCQYDVQQG +EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEQMA4G +A1UECgwHd29sZlNTTDEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAe +Fw0xODA0MTMxNTIzMTBaFw0yMTAxMDcxNTIzMTBaMIGXMQswCQYDVQQGEwJVUzET +MBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEQMA4GA1UECgwH +d29sZlNTTDEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTB2MBAGByqG +SM49AgEGBSuBBAAiA2IABO6C1DmasSeC9NfqxrwDHU2DYfQDrn692FqlufCOoqXa +zoc7WqtEFpz1n2Ld9iDNnHY8QLE/lxffWfbN3s1GNcDtXi5ItmaRcXS3DD+5mreD +vZM/X1AtcD/eNSXhkDuG4KNjMGEwHQYDVR0OBBYEFKvgwyZMGNRyu9KEjJwKBZKA +ElNSMB8GA1UdIwQYMBaAFKvgwyZMGNRyu9KEjJwKBZKAElNSMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMA0KYvvmOv5x +2CtE5Zc0BKmMCpmIoL0fsN+UWSe7K8YqvqRpG8+XeCoolu661IdF/QIxAMBzGWZ2 +Xp+jZYVB77d7PWNtmHGZb5zbqF5TbqBoEWW8eHQoacdknYjy2MI9KQODIw== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-key.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-key.der new file mode 100644 index 0000000000000000000000000000000000000000..073ddfdd6e28e3b2dc11293a7e409e81f077917a GIT binary patch literal 167 zcmV;Y09gMpfusTf0R%967UR~^fs|~D-Kco($9}WL(c3Qb?G8wVvGU=1Iaa{&ViFHE zw>i9=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/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ca-ecc384-key.pem new file mode 100644 index 000000000..7201cd5ee --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/certs/client-ca.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/client-ca.pem new file mode 100644 index 000000000..795d5f7ab --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/client-ca.pem @@ -0,0 +1,142 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 12305170416376042871 (0xaac4bf4c50bd5577) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Montana, L=Bozeman, O=wolfSSL_2048, OU=Programming-2048, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:09 2018 GMT + Not After : Jan 7 15:23:09 2021 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=wolfSSL_2048, OU=Programming-2048, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c3:03:d1:2b:fe:39:a4:32:45:3b:53:c8:84:2b: + 2a:7c:74:9a:bd:aa:2a:52:07:47:d6:a6:36:b2:07: + 32:8e:d0:ba:69:7b:c6:c3:44:9e:d4:81:48:fd:2d: + 68:a2:8b:67:bb:a1:75:c8:36:2c:4a:d2:1b:f7:8b: + ba:cf:0d:f9:ef:ec:f1:81:1e:7b:9b:03:47:9a:bf: + 65:cc:7f:65:24:69:a6:e8:14:89:5b:e4:34:f7:c5: + b0:14:93:f5:67:7b:3a:7a:78:e1:01:56:56:91:a6: + 13:42:8d:d2:3c:40:9c:4c:ef:d1:86:df:37:51:1b: + 0c:a1:3b:f5:f1:a3:4a:35:e4:e1:ce:96:df:1b:7e: + bf:4e:97:d0:10:e8:a8:08:30:81:af:20:0b:43:14: + c5:74:67:b4:32:82:6f:8d:86:c2:88:40:99:36:83: + ba:1e:40:72:22:17:d7:52:65:24:73:b0:ce:ef:19: + cd:ae:ff:78:6c:7b:c0:12:03:d4:4e:72:0d:50:6d: + 3b:a3:3b:a3:99:5e:9d:c8:d9:0c:85:b3:d9:8a:d9: + 54:26:db:6d:fa:ac:bb:ff:25:4c:c4:d1:79:f4:71: + d3:86:40:18:13:b0:63:b5:72:4e:30:c4:97:84:86: + 2d:56:2f:d7:15:f7:7f:c0:ae:f5:fc:5b:e5:fb:a1: + ba:d3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 33:D8:45:66:D7:68:87:18:7E:54:0D:70:27:91:C7:26:D7:85:65:C0 + X509v3 Authority Key Identifier: + keyid:33:D8:45:66:D7:68:87:18:7E:54:0D:70:27:91:C7:26:D7:85:65:C0 + DirName:/C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:AA:C4:BF:4C:50:BD:55:77 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 80:52:54:61:2a:77:80:53:44:a9:80:6d:45:ff:0d:25:7d:1a: + 8f:23:93:53:74:35:12:6f:f0:2e:20:ea:ed:80:63:69:88:e6: + 0c:a1:49:30:e0:82:db:68:0f:7e:84:ac:ff:ff:7b:42:fa:7e: + 2f:b2:52:9f:d2:79:5e:35:12:27:36:bc:df:96:58:44:96:55: + c8:4a:94:02:5f:4a:9d:dc:d3:3a:f7:6d:ac:8b:79:6e:fc:be: + 8f:23:58:6a:8a:f5:38:0a:42:f6:98:74:88:53:2e:02:af:e1: + 0e:be:6f:cc:74:33:7c:ec:b4:cb:a7:49:6d:82:42:4f:eb:73: + 29:c3:32:00:2b:15:f8:88:7a:8f:6d:20:1b:ae:65:5f:c5:d0: + 8a:d1:e2:64:6d:a3:a8:fe:64:e1:a9:5b:e6:d0:23:d6:02:72: + 5a:ec:03:8e:87:67:19:8d:e4:a8:99:15:c1:3d:91:48:99:8d: + fe:ae:1c:bf:f6:28:1b:45:be:ad:ef:72:83:9a:f6:c7:3b:51: + a3:6e:7a:73:bd:83:aa:97:fd:63:b4:f4:6b:1c:14:81:9a:ef: + 14:24:d3:e1:8b:f4:04:04:84:54:0f:61:a2:a8:f2:50:37:0c: + 17:0c:bc:e0:c2:84:85:f4:0b:ae:00:ca:9f:27:e2:44:4f:15: + 0b:8b:1d:b4 +-----BEGIN CERTIFICATE----- +MIIEyjCCA7KgAwIBAgIJAKrEv0xQvVV3MA0GCSqGSIb3DQEBCwUAMIGeMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEVMBMG +A1UECgwMd29sZlNTTF8yMDQ4MRkwFwYDVQQLDBBQcm9ncmFtbWluZy0yMDQ4MRgw +FgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s +ZnNzbC5jb20wHhcNMTgwNDEzMTUyMzA5WhcNMjEwMTA3MTUyMzA5WjCBnjELMAkG +A1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFTAT +BgNVBAoMDHdvbGZTU0xfMjA0ODEZMBcGA1UECwwQUHJvZ3JhbW1pbmctMjA0ODEY +MBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwwPRK/45 +pDJFO1PIhCsqfHSavaoqUgdH1qY2sgcyjtC6aXvGw0Se1IFI/S1oootnu6F1yDYs +StIb94u6zw357+zxgR57mwNHmr9lzH9lJGmm6BSJW+Q098WwFJP1Z3s6enjhAVZW +kaYTQo3SPECcTO/Rht83URsMoTv18aNKNeThzpbfG36/TpfQEOioCDCBryALQxTF +dGe0MoJvjYbCiECZNoO6HkByIhfXUmUkc7DO7xnNrv94bHvAEgPUTnINUG07ozuj +mV6dyNkMhbPZitlUJttt+qy7/yVMxNF59HHThkAYE7BjtXJOMMSXhIYtVi/XFfd/ +wK71/Fvl+6G60wIDAQABo4IBBzCCAQMwHQYDVR0OBBYEFDPYRWbXaIcYflQNcCeR +xybXhWXAMIHTBgNVHSMEgcswgciAFDPYRWbXaIcYflQNcCeRxybXhWXAoYGkpIGh +MIGeMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96 +ZW1hbjEVMBMGA1UECgwMd29sZlNTTF8yMDQ4MRkwFwYDVQQLDBBQcm9ncmFtbWlu +Zy0yMDQ4MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEW +EGluZm9Ad29sZnNzbC5jb22CCQCqxL9MUL1VdzAMBgNVHRMEBTADAQH/MA0GCSqG +SIb3DQEBCwUAA4IBAQCAUlRhKneAU0SpgG1F/w0lfRqPI5NTdDUSb/AuIOrtgGNp +iOYMoUkw4ILbaA9+hKz//3tC+n4vslKf0nleNRInNrzfllhEllXISpQCX0qd3NM6 +922si3lu/L6PI1hqivU4CkL2mHSIUy4Cr+EOvm/MdDN87LTLp0ltgkJP63MpwzIA +KxX4iHqPbSAbrmVfxdCK0eJkbaOo/mThqVvm0CPWAnJa7AOOh2cZjeSomRXBPZFI +mY3+rhy/9igbRb6t73KDmvbHO1GjbnpzvYOql/1jtPRrHBSBmu8UJNPhi/QEBIRU +D2GiqPJQNwwXDLzgwoSF9AuuAMqfJ+JETxULix20 +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 10646345548447194541 (0x93bf6ade9b419dad) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: C=US, ST=Oregon, L=Salem, O=Client ECC, OU=Fast, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Oregon, L=Salem, O=Client ECC, OU=Fast, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:55:bf:f4:0f:44:50:9a:3d:ce:9b:b7:f0:c5:4d: + f5:70:7b:d4:ec:24:8e:19:80:ec:5a:4c:a2:24:03: + 62:2c:9b:da:ef:a2:35:12:43:84:76:16:c6:56:95: + 06:cc:01:a9:bd:f6:75:1a:42:f7:bd:a9:b2:36:22: + 5f:c7:5d:7f:b4 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Subject Key Identifier: + EB:D4:4B:59:6B:95:61:3F:51:57:B6:04:4D:89:41:88:44:5C:AB:F2 + X509v3 Authority Key Identifier: + keyid:EB:D4:4B:59:6B:95:61:3F:51:57:B6:04:4D:89:41:88:44:5C:AB:F2 + DirName:/C=US/ST=Oregon/L=Salem/O=Client ECC/OU=Fast/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:93:BF:6A:DE:9B:41:9D:AD + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: ecdsa-with-SHA256 + 30:44:02:20:61:bc:9d:4d:88:64:86:b8:71:aa:35:59:68:b8: + ee:2c:f3:23:b5:1a:b9:ba:41:50:a8:c6:c3:58:eb:58:bd:60: + 02:20:61:aa:eb:b5:73:0d:01:db:69:8f:52:f5:72:6d:37:42: + b5:fd:94:b6:6e:b1:c4:25:2e:96:96:f3:39:b2:5d:ea +-----BEGIN CERTIFICATE----- +MIIDCDCCAq+gAwIBAgIJAJO/at6bQZ2tMAoGCCqGSM49BAMCMIGNMQswCQYDVQQG +EwJVUzEPMA0GA1UECAwGT3JlZ29uMQ4wDAYDVQQHDAVTYWxlbTETMBEGA1UECgwK +Q2xpZW50IEVDQzENMAsGA1UECwwERmFzdDEYMBYGA1UEAwwPd3d3LndvbGZzc2wu +Y29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MDQxMzE1 +MjMxMFoXDTIxMDEwNzE1MjMxMFowgY0xCzAJBgNVBAYTAlVTMQ8wDQYDVQQIDAZP +cmVnb24xDjAMBgNVBAcMBVNhbGVtMRMwEQYDVQQKDApDbGllbnQgRUNDMQ0wCwYD +VQQLDARGYXN0MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0B +CQEWEGluZm9Ad29sZnNzbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARV +v/QPRFCaPc6bt/DFTfVwe9TsJI4ZgOxaTKIkA2Ism9rvojUSQ4R2FsZWlQbMAam9 +9nUaQve9qbI2Il/HXX+0o4H1MIHyMB0GA1UdDgQWBBTr1EtZa5VhP1FXtgRNiUGI +RFyr8jCBwgYDVR0jBIG6MIG3gBTr1EtZa5VhP1FXtgRNiUGIRFyr8qGBk6SBkDCB +jTELMAkGA1UEBhMCVVMxDzANBgNVBAgMBk9yZWdvbjEOMAwGA1UEBwwFU2FsZW0x +EzARBgNVBAoMCkNsaWVudCBFQ0MxDTALBgNVBAsMBEZhc3QxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJ +AJO/at6bQZ2tMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgYbydTYhk +hrhxqjVZaLjuLPMjtRq5ukFQqMbDWOtYvWACIGGq67VzDQHbaY9S9XJtN0K1/ZS2 +brHEJS6WlvM5sl3q +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/client-cert-ext.der b/FreeRTOS-Plus/Source/WolfSSL/certs/client-cert-ext.der new file mode 100644 index 0000000000000000000000000000000000000000..d58a1dbf33744db35bd898c13de4ad04341f6998 GIT binary patch literal 1292 zcmXqLV&yPsV*apznTe5!Nu=)oF(?1#Zh5J>e)_xA=TE=>=+$ZiUN%mxHjlRNyo`+8 ztPBQ?^9;ESIN6v(S=fY`LW2zj4ER7C4jy*j{JfIHyhNA?I}f{4epPC2VxFO>fiOr7 z7Y|Q)eok6&uur^^fr*8oq=7g{n43o+peR4RC^0uTGcR2iEG1ze29jdt;V&;Q*8}M) zF3!`q*KYc~=@e{_18d>Q3Liu=IqPj@KpW@7=r3^ZtDQ=3}E=^=xMMS^HDZ z)TgRsE_)%;8U4iM`_T;|lfR}{TUAv&WDElL`2MUIxFZ!v1h?`=EO;V{#zd6%3+k&^iJpj4IO z4d>oVo?Z99BB%O*5c3tkBHn;p>&4cKXU5Gvag(QY^UbcCA!@gCf34a5U)ATx#mX;* zm)jg9gf}E_E%GxsGQFiuH%$M!==b^q>%RVpe)@aiuFFi!j0}v6n;5NtAz}th4a}jk zd@N!tBE~md)2?T)*@)hujWvZQh0pidV~ z*s~`O$bZ5ttOm@CjQ_#8Mplr8-+;G?JGCM)w;(4Klxx6wRF)s8f`tW`)!UHM7cf%; z(-$Ly+o7e)j9NBiFgxBezjb(rTcMTVDya{R8i(1<6UA!H`-1}qtg00>23We2515CcI>HBfH^Lh~1r+7Q|Lrf3Mic1YvM(t90|67BD z*D$!n_OI-upQ5)IYZMBuZsUDr^|5ur#>3kS6;3lNeeQqC$@QzwW)Cp(k=i@cPqp^SgN4riixvGUA^gaZ&faSXcz7>O{pum%r7W@La`k zJ@NS5OUfJTr){Xr>*lo37k=n5ZHucP`y=mkr=fbI50FZGch$XGcY+? z7Y#BoFflMUF*PzXFgaS11EI5t0UQDc#J@~Xy;XOUtOFu{fKpUpDtCZWM5%ynMgI*Y zeHxD=lT&mx5^wM>AnNUaV`+%y453Ld;DXy|4}OHK|NnbJ`hG96QlHX!UNsUYHoV`K zSVWdp$V!v~UrL?a(>nKUtc!VW{JxJPSZa#(I0{1cm~@C!E&{LN4!&>9bTfSHw9BVS zZGu8i>vJi8!!iIX75IpHk8L0uu4P}v(2CLGWNo9U{$$~)TjtOs)&g=`>;sO6XBmy; zsF@YPJ&{P6jsC72zxF5_MZT@?a)X-o$2(D@ZhCXQgQ}PPW3=>Z929|??-V4{;fwSH l1cX!%VWOz=P&W)047}jNgoX4At^mrPC*nj;6$^_39kk%)mTCY1 delta 339 zcmV-Z0j&Pc3C;-^FoFciFoFZJpaTK{0s;vDswcC>sd8=&kr=fbH83?WH!(OeF)%S& z7Y#8uFflVRF*q_YFfm$^1EI5t0UQDcC$q(=a&8TitOFu{QI@A1CS4qm#xkFl74jYD zlboz|R+arAaH~aX39$3>1E|~FFT5XzdZW~j)k&9rJXEZ)eL)s?~e*6v#AIA)w5{B&eIci~(&@&XqRXeuN zfLn}1??XfjJd-)2P8HD$Uxb()&7Y}9>pNC3wsw-iNMF2_uuvLR$WCHMhg4(?o00lM lvnfcv<`V1UM8;C&K*ocW8>eL_X>%{gpiO_i>YHZ*vU`M*nVkRt diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/client-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/client-cert.pem index 569cdddac..9b6a8190d 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/certs/client-cert.pem +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/client-cert.pem @@ -1,12 +1,12 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 12260966172072242701 (0xaa27b3c5a9726e0d) + Serial Number: 12305170416376042871 (0xaac4bf4c50bd5577) Signature Algorithm: sha256WithRSAEncryption Issuer: C=US, ST=Montana, L=Bozeman, O=wolfSSL_2048, OU=Programming-2048, CN=www.wolfssl.com/emailAddress=info@wolfssl.com Validity - Not Before: May 7 18:21:01 2015 GMT - Not After : Jan 31 18:21:01 2018 GMT + Not Before: Apr 13 15:23:09 2018 GMT + Not After : Jan 7 15:23:09 2021 GMT Subject: C=US, ST=Montana, L=Bozeman, O=wolfSSL_2048, OU=Programming-2048, CN=www.wolfssl.com/emailAddress=info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -37,32 +37,32 @@ Certificate: X509v3 Authority Key Identifier: keyid:33:D8:45:66:D7:68:87:18:7E:54:0D:70:27:91:C7:26:D7:85:65:C0 DirName:/C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048/CN=www.wolfssl.com/emailAddress=info@wolfssl.com - serial:AA:27:B3:C5:A9:72:6E:0D + serial:AA:C4:BF:4C:50:BD:55:77 X509v3 Basic Constraints: CA:TRUE Signature Algorithm: sha256WithRSAEncryption - 51:96:a7:1c:26:5d:1c:90:c6:32:9f:96:15:f2:1d:e7:93:9c: - ac:75:56:95:fd:20:70:ab:45:6a:09:b0:f3:f2:03:a8:db:dc: - 2f:bc:1f:87:7a:a3:d4:8f:d5:49:97:7e:3c:54:ac:b1:e3:f0: - 39:0d:fe:09:9a:23:f6:32:a6:41:59:bd:60:e8:bd:de:00:36: - 6f:3e:e9:41:6f:a9:63:c7:aa:d5:7b:f3:e4:39:48:9e:f6:60: - c6:c6:86:d5:72:86:23:cd:f5:6a:63:53:a4:f8:fc:51:6a:cd: - 60:74:8e:a3:86:61:01:34:78:f7:29:97:b3:a7:34:b6:0a:de: - b5:71:7a:09:a6:3e:d6:82:58:89:67:9c:c5:68:62:ba:06:d6: - 39:bb:cb:3a:c0:e0:63:1f:c7:0c:9c:12:86:ec:f7:39:6a:61: - 93:d0:33:14:c6:55:3b:b6:cf:80:5b:8c:43:ef:43:44:0b:3c: - 93:39:a3:4e:15:d1:0b:5f:84:98:1d:cd:9f:a9:47:eb:3b:56: - 30:b6:76:92:c1:48:5f:bc:95:b0:50:1a:55:c8:4e:62:47:87: - 54:64:0c:9b:91:fa:43:b3:29:48:be:e6:12:eb:e3:44:c6:52: - e4:40:c6:83:95:1b:a7:65:27:69:73:2f:c8:a0:4d:7f:be:ea: - 9b:67:b2:7b + 80:52:54:61:2a:77:80:53:44:a9:80:6d:45:ff:0d:25:7d:1a: + 8f:23:93:53:74:35:12:6f:f0:2e:20:ea:ed:80:63:69:88:e6: + 0c:a1:49:30:e0:82:db:68:0f:7e:84:ac:ff:ff:7b:42:fa:7e: + 2f:b2:52:9f:d2:79:5e:35:12:27:36:bc:df:96:58:44:96:55: + c8:4a:94:02:5f:4a:9d:dc:d3:3a:f7:6d:ac:8b:79:6e:fc:be: + 8f:23:58:6a:8a:f5:38:0a:42:f6:98:74:88:53:2e:02:af:e1: + 0e:be:6f:cc:74:33:7c:ec:b4:cb:a7:49:6d:82:42:4f:eb:73: + 29:c3:32:00:2b:15:f8:88:7a:8f:6d:20:1b:ae:65:5f:c5:d0: + 8a:d1:e2:64:6d:a3:a8:fe:64:e1:a9:5b:e6:d0:23:d6:02:72: + 5a:ec:03:8e:87:67:19:8d:e4:a8:99:15:c1:3d:91:48:99:8d: + fe:ae:1c:bf:f6:28:1b:45:be:ad:ef:72:83:9a:f6:c7:3b:51: + a3:6e:7a:73:bd:83:aa:97:fd:63:b4:f4:6b:1c:14:81:9a:ef: + 14:24:d3:e1:8b:f4:04:04:84:54:0f:61:a2:a8:f2:50:37:0c: + 17:0c:bc:e0:c2:84:85:f4:0b:ae:00:ca:9f:27:e2:44:4f:15: + 0b:8b:1d:b4 -----BEGIN CERTIFICATE----- -MIIEyjCCA7KgAwIBAgIJAKons8Wpcm4NMA0GCSqGSIb3DQEBCwUAMIGeMQswCQYD +MIIEyjCCA7KgAwIBAgIJAKrEv0xQvVV3MA0GCSqGSIb3DQEBCwUAMIGeMQswCQYD VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEVMBMG A1UECgwMd29sZlNTTF8yMDQ4MRkwFwYDVQQLDBBQcm9ncmFtbWluZy0yMDQ4MRgw FgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s -ZnNzbC5jb20wHhcNMTUwNTA3MTgyMTAxWhcNMTgwMTMxMTgyMTAxWjCBnjELMAkG +ZnNzbC5jb20wHhcNMTgwNDEzMTUyMzA5WhcNMjEwMTA3MTUyMzA5WjCBnjELMAkG A1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFTAT BgNVBAoMDHdvbGZTU0xfMjA0ODEZMBcGA1UECwwQUHJvZ3JhbW1pbmctMjA0ODEY MBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv @@ -77,11 +77,11 @@ xybXhWXAMIHTBgNVHSMEgcswgciAFDPYRWbXaIcYflQNcCeRxybXhWXAoYGkpIGh MIGeMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96 ZW1hbjEVMBMGA1UECgwMd29sZlNTTF8yMDQ4MRkwFwYDVQQLDBBQcm9ncmFtbWlu Zy0yMDQ4MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEW -EGluZm9Ad29sZnNzbC5jb22CCQCqJ7PFqXJuDTAMBgNVHRMEBTADAQH/MA0GCSqG -SIb3DQEBCwUAA4IBAQBRlqccJl0ckMYyn5YV8h3nk5ysdVaV/SBwq0VqCbDz8gOo -29wvvB+HeqPUj9VJl348VKyx4/A5Df4JmiP2MqZBWb1g6L3eADZvPulBb6ljx6rV -e/PkOUie9mDGxobVcoYjzfVqY1Ok+PxRas1gdI6jhmEBNHj3KZezpzS2Ct61cXoJ -pj7WgliJZ5zFaGK6BtY5u8s6wOBjH8cMnBKG7Pc5amGT0DMUxlU7ts+AW4xD70NE -CzyTOaNOFdELX4SYHc2fqUfrO1YwtnaSwUhfvJWwUBpVyE5iR4dUZAybkfpDsylI -vuYS6+NExlLkQMaDlRunZSdpcy/IoE1/vuqbZ7J7 +EGluZm9Ad29sZnNzbC5jb22CCQCqxL9MUL1VdzAMBgNVHRMEBTADAQH/MA0GCSqG +SIb3DQEBCwUAA4IBAQCAUlRhKneAU0SpgG1F/w0lfRqPI5NTdDUSb/AuIOrtgGNp +iOYMoUkw4ILbaA9+hKz//3tC+n4vslKf0nleNRInNrzfllhEllXISpQCX0qd3NM6 +922si3lu/L6PI1hqivU4CkL2mHSIUy4Cr+EOvm/MdDN87LTLp0ltgkJP63MpwzIA +KxX4iHqPbSAbrmVfxdCK0eJkbaOo/mThqVvm0CPWAnJa7AOOh2cZjeSomRXBPZFI +mY3+rhy/9igbRb6t73KDmvbHO1GjbnpzvYOql/1jtPRrHBSBmu8UJNPhi/QEBIRU +D2GiqPJQNwwXDLzgwoSF9AuuAMqfJ+JETxULix20 -----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/client-ecc-cert.der b/FreeRTOS-Plus/Source/WolfSSL/certs/client-ecc-cert.der new file mode 100644 index 0000000000000000000000000000000000000000..d6c5dbba9d7431740b1d2d880662fedba5fa2028 GIT binary patch literal 780 zcmXqLV&*VtVp_j|nTe5!iIZXS{;Yem9p|n!;9}#@YV$Z}%fifL(AaCpZNSOK9LmBb z%oG}I$Zx<4;&AY=`4^?8=jR#n8SsDv*m+ok6LV5?4TTK^L3}PAF6W%g)VvY}S7&EK zUIT8BAU6+-TVipEp@e}Lh|A2wUtV6WSDv4fR$QE;mz|cC!?4^ zW?ovp1Cjy*IdNV?3j-5FV?$FTV?%=|ab6=s149FID0k4gH_||ujU61COpMTAWoBe& zc4A-&-T#H(C195Ax!K!49QFNLP<`c%N}puIn<$?}D$Gebvv0j$WGdv`QYLmRY%1Fs z#+7@&l}b5%-@9^?nNs}m*!nGt8^0PfegcLUbEqsIix`W@>nq-o*;5nk1H-qm_;xyW zxWugfWYBmBB(KcUxXYk%djnQA3mYddX`C?FLaqrZL4s14tS}3!0W%}xf8^xJ?9O1| z!laP6XRdEYO52XYRi=>{JKpJhR^BSLbC+YlierZ(UPtUr0IFE^dTTK+0ondAf&n5h4F(A+hDe6@4FLfG1potr0S^E$f&mHwf&l>l!voPP{yC&FMLSc- zgexk1beg@YDpChW)}}VH2QrS(x@mjH!$h9cfk^!=XrhZ}yPv6rYi9D-pq0NhdaV;R$G*1zN1; z064ytbb(VS@U7pqha7SjPV4}YBC6zw*Y!Og0~0MA``%e-t>71-?v2d9{?8;r?IztR z&`x4Jg*F>sYDb76FxV9r{;E3LdJJ@tB{#|!tBWy zN<8!tbti+pp2CkKt5QbdQeBz^!xbNCoN{SdQq*ZZ8Fw}%uLp60-nS%Rf@*TR?Y4HV ze!P7zb4vsk)ui(SCj0Zvdv|_(jb*N-+-&1;(kW~5>vqZIMi>%TuvMje%|VkUnfIl| zG`?AR-U?S=A^4b5@GpB;ww?Syrd9i|*%q51PpG2{1W4m|BE-yB6f>gmn&T3^|8k4& qQuE1K!lG-Xbx2Wy4toFoLCt()(o?7r1GxhS{$@B|qCT7(0s#VD1iqmF literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/dh3072.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/dh3072.pem new file mode 100644 index 000000000..b7a8a2b33 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/certs/dh4096.der b/FreeRTOS-Plus/Source/WolfSSL/certs/dh4096.der new file mode 100644 index 0000000000000000000000000000000000000000..34eaab8487d3bbc2d737a3e3c40c3e6194d92bb8 GIT binary patch literal 524 zcmV+n0`vVaf&vHvf&u{m=?*@5Psy^NvD+^mBq5MoP^2{5nUJjazb^qxtcP&A?9pW2 z1j_vRQE48xnc}n!+g*4#I6(#IXGmpKam>l8l^)c;yvkj|oSuGOlv^)ga_#F>3`i>> zbWJw|S}%(vO55)Gsgx6sQc4@H=E#4U2_uAw>84YHwgYWAT`ubj@aC$qi&6a66Z;^` z-+7nYRdm83=-Z5Hl`T<`r=dKX@AX5hrfJS*T-CAoy3~dxDJ~8p1=@Uk!h6WId4z3f zErLolpWF^(D_CDNeyDTKL{kyt+eZ32!`fq|WmcJ`ktf#Y-!1Q;fwl)a#=$G0I&`$@ z;V)||NR zY0Mn;mfXHzUN`R4W0p~umJ~c;zf-CtwIo|6XRQKfxYGr0q>o0CorI<=M4v4fFLR~k z#Mw{TpY_1SNa!On#7fTpI~Iq9r5_@w3z3&3l?TXk(y#&eAgQZsad{;3d9|AW_4%$N ztm@%Nh$vIw$aX2NJ|&+V#fpYA0wJrV5by^ZR*%j6hn_CbM3_XGv%(b4*puqff;<~Z z=x+qF^{<;ZedXX*>FxknB^D#Yj_|qSm|gNuT*D_SXMIEVHg?o3eines@dwRSvNz|Rr#`ghm z(uj~9U@)5soFm%cbVggpK|oyDdcJtdN%bvz*S}{Cgebe6!mA?&C=8fJL(XrW(CH5I zelT6rMMQfHdUK|gWvYwVb!ri_5PVm!&c0js$o@j3cee{YX0-@(B6KF^+m7#}nXU^$ zj9-38=^2oyHL3ha4am6U8Vn}K8XyAeaxRqC88kUnPW)3y*bs@KZX!8x6{ZuscS%#r z7E4w=2%>Qg1`Imhg23PBmRHw5Yw)hoIJjGbcZ=&Q+BnEesYp`TK?Bnf9A=*0$#`1f zd+Kl2%4#nGvV%7z*__m{A=!_n_|_qUy9i_`4h$ydrD@9fT7-p1B40A`zt3vb@I z-DrQEXjyAj*;4^~8XS$kufVYsp23Yi9{WJ~ZAe4SZ0Ni^d^J2}ZJ;HGzwDb5bV$hL zzf)63c-fm8r3Xe87Sc15%t4#CBHstya>g2)lIJo6tCWDfSn@RjApn})m>O^DwTsDU z7=h$W{fZ>f?(NDVH<2CzkTxI#9CPVV{-~~O#Tf`yf zu>$MzsRmxR8^PFyH0^|m&d$PPcxU*-s(c(-GURunHZlH7oS4o5RbkE}t`B}Bi&To_ z%Z}W7luY?N_-AOHdV-;#0mmDSpukfelgEY<(-zz)pwSH;LYm7}j3R$Q!^sr#uydhJ za{Y+5-sSK-I(}$Af>>b9v^nbvj)hb;0bd9omU zZ^6Ypuuwm8rB~yyVio~5B$;|L~m{3{>=f&qa5 zrBaVm@VQS0xyZCoq&d10l65CTs4%JWD#nv0JdB^BZ&TS6t3Lq75fhMVLh_xXk1;Yv zbEA`2U3NuDY`yBQs@GV6FU|*mF*1U%Dvx8rJTO+UAf6jDgJnD{T2Yiq9rQ; literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-client-keyPub.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-client-keyPub.pem new file mode 100644 index 000000000..5c673f755 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-client-keyPub.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVb/0D0RQmj3Om7fwxU31cHvU7CSO +GYDsWkyiJANiLJva76I1EkOEdhbGVpUGzAGpvfZ1GkL3vamyNiJfx11/tA== +-----END PUBLIC KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-keyPkcs8.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-keyPkcs8.der new file mode 100644 index 0000000000000000000000000000000000000000..71034c5486ec7bc2e96018e9ebf70899acbe5fdb GIT binary patch literal 138 zcmV;50CoQ`frkPC05B5<2P%e0&OHJF1_&yKNX|V20S5$aFlzz<0R$jLwrK)$oNR@m zI9qb)=*O(Y1C3KP1o~_!+%%2hs0oarL<2$q1iLe=OeauE#!96G!#v)fHrsM7&Xnpa s`pX~*IV=|FVFKx|P16FCnlW3Kk|BTa&luW~5dt)Z=pa}#3xG6<*o<&AJpcdz literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-keyPkcs8Enc.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-keyPkcs8Enc.der new file mode 100644 index 0000000000000000000000000000000000000000..c325ffa6a3261a068d6bce6557e9ca2df64fcf83 GIT binary patch literal 179 zcmV;k08IZdfv_+e1_>&LNQU@4lI3fA~ literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privOnlyCert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privOnlyCert.pem new file mode 100644 index 000000000..e6034bed8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privOnlyCert.pem @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE----- +MIIBIzCBygIJAIQV31BIhAeYMAoGCCqGSM49BAMCMBoxCzAJBgNVBAoMAldSMQsw +CQYDVQQDDAJERTAeFw0xODA0MTMxNTIzMTBaFw0yMTAxMDcxNTIzMTBaMBoxCzAJ +BgNVBAoMAldSMQswCQYDVQQDDAJERTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BCXA/Ra4K/K4Ch7drM5iUnxYCmB9V3XavRHB1SrqVGt25j02991Rl2uoJv57pr2W +VYVQnZp+aQHYQ0WJ2f5KKyYwCgYIKoZIzj0EAwIDSAAwRQIhAJvs7Y00EWq/Yv9A +ymP/fVWsxz8/fhbZKi09eq2eqV/gAiBW9u61nV2snwijm5r6EWrnlGKoNb9niPCD +qg/y+r8d1A== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privOnlyKey.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privOnlyKey.pem new file mode 100644 index 000000000..952a90951 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privOnlyKey.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCBmlE/nixmHCpmplUopbqNEo+jJE40p +wfkxzH01tAWqcQ== +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privkey.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privkey.pem new file mode 100644 index 000000000..1d46e903d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privkey.pem @@ -0,0 +1,4 @@ +-----BEGIN EC PRIVATE KEY----- +MDECAQEEIEW2aQJznGyFoThbcujox6zEA41TNQT6bCjcNI3hqAmMoAoGCCqGSM49 +AwEH +-----END EC PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privkeyPkcs8.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc-privkeyPkcs8.der new file mode 100644 index 0000000000000000000000000000000000000000..a88d141e08cceb829f2bc756ffcabd7d8e8c0b79 GIT binary patch literal 121 zcmV-<0EYiCcLD(c1RzDWX##VcY=xmXTXN{=$E?HyjZ-xQ`fMoNG>ze?35=i$1_&yK zNX|V20SBQ(13~}x++j1?=l*0Ru3C2`B~$Duzgg_YDCD0ic2j83cj}6)=Jc5io)X2L=f$hDe6@ z4FLxRpn?bZFoFm40s#Opf(Pve2`Yw2hW8Bt2LUh~1_~;MNQUBFC(gPb(fN1ikr{Mi!>w43dG`hE)Zc{+)$7tR<8Mm#i z-bJFa1AMJ38>^58>=VWa>rmsi6I5WmDWmUg2&o765m4sh&0Z|PB)%lwTInCkEphf4 z1$u_#QVeos*0NBjJ?r(pC!HGXkqB;U&)61RDM3x=bW9i!bP$@OSF5AOprvw-xVnH$ zz!ZX7BT!e4-(CpfAB6FuCJ)+`X?8B)<(OBkH} zFrw^rPLq_1_vmpRh_$U$Wt|Fv{;uq?F0UCv!SubR_ZqgY2mE@>l1L{2babdX4dTt- z7R$?nPnJdi`ocfF?YDFh4dk-?5fs&Ew_K4u_5KAU>(j0|QH<@RM`H4awfwNt{ zJXilKxWJ>>bA@fso!;x_mUZW3&gq#T;$9%8t~dvMA8$-9iA^GG0;*OHLbjLoqJtpV zlqQYu#ACnQAZCGh0yE+3Wxx6XhDSYy3*w*#Sct<+!_uv>SB(j7GT>rDsK}WbiwW-F zQ~%`v*cSr}i38UL%(1~ZzLHY+E8eXdcQVG#1}=WxCCpMe`z;8z+L1xfec$_LG}(oW zpBXi}s-6L`ZQIDLvQ8-d3>Mnif=GqpwyW%hZc{(y7JjPRa-d5I1WclpW8Q(2&F26k z97~lBw29(-;y5>XoMD4Q@L04(zQHsTDFD=>3pixwTV@#zUbL1g{nXwm zdkAgG+1w5k8IFlrVe01mS^3fQ=cphM%^G2d*=++b3}1B72X4Wza}J0Bri}pn)kCn( zdK`g0q)0D(k_-CEF2Vl3LL9Q?a#9Xz(ZK2oB^OsxW zBEwiqc=U8I<7=%BB?gkk?E#(_j@KCevzM)1_IXO&bYMUX=^k{=sa&TOUXaY6%M*P( z|JB*mCQBhUN0?^l2cI9z9JA-}xEE1oc;M_=kpssL;{mld|8~D~Cwl$_0Cyh`Fjgku z2d-$@*i$4amYWRH?@0W}V=1Mr&L4*B@d>Q6Y|kDjGIWM()liwVoJH8}dFQ?DB>a+9 z)#Yy!T1#6yHRr_KT%6bAL_%ayhHwI>ogcO$KS@L8C@nZqv&iez|zvnguWJBRjd9}dQ8qH>zgz!BI)qLO*} zY053i%nQz09w3QoVh8Z=y!Y;LWw{1=oMB%RD7t|`g&$v8j?N5G5dzxq{uV%1S;XmP z7Ou`dQq%2y9n~@7zj3>Fu$CS!H-hca&3=~V(+P4jO$;%PTO0#j^J&uoPcHETy@x+m zu>bqUGHmN9O=LB?z?qZI(Fcw5dx09mRoLt#^4O<4{$`yI78k4Kss9kI@c^CP;@Czr z3169Z(!VLs6~6{t&Kf9d>3jdIa^A$dDX9T+#iW}|$XW5Qu;6Ed(o!Ys!3zS%?!M>| zwOl2|ya0ly(F(h#ruBrUCLSpBR?+{NrD$2$&NGM{Stc?&I*XNkn9lR2WvmgOLA{GB zTnm@{eFAtAdhnfY>LkH4J`&+auHr%`+Ix7qPq{;1BC47qR+At8D>3Qv;CwR}`s4aj zs1vw2Bun(l(nf%}fBUmmsn?4e?JDl$$PlRoPiVs{X7P1_#C+%ZKTycvm}W z1pC_FpFPMZ9~ST<(ZbU(X!~2J`(hok&S&bAxHX3=su@xh+cBm67SeV75J z2<5&&<&`w^>)6h^`xJ{h2_(H@(#-lZ*)Uq4A{f931=}vGR&3652IHyp3JVd<+J9EcrT` zuu$;cUJd+hQ=z~{=Uh=)s$ktEFoFRB1_>&LNQU4NH1xJB}GK8{IA)CKYBOed4x8p z^gXMj9c>~N=FGXArU@<8;sh*!`6BZYa2}qx&HRk9h}jS^B`_lf2`Yw2hW8Bt2^BFG z1Qg1sR#=3zkwyQQ+aeDAwhbGs%bzeYFd;Ar1_dh)0|FWa00b1W91*ub=e1aE`#?GA YETDAE+^44m2t`socgqoVw*mqP0Gm{T-T(jq literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ecc/genecc.sh b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc/genecc.sh new file mode 100644 index 000000000..2efb033c9 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc/genecc.sh @@ -0,0 +1,91 @@ +#!/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 + +# Gen CA 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 + + + +# 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 + + + +# generate ECC 384-bit CA +openssl ecparam -out ./certs/ca-ecc384-key.par -name secp384r1 +openssl req -config ./certs/ecc/wolfssl_384.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 + +# Gen CA CRL +openssl ca -config ./certs/ecc/wolfssl_384.cnf -gencrl -crldays 1000 -out ./certs/crl/caEcc384Crl.pem -keyfile ./certs/ca-ecc384-key.pem -cert ./certs/ca-ecc384-cert.pem + + + +# Generate ECC 384-bit server cert +openssl ecparam -out ./certs/server-ecc384-key.par -name secp384r1 +openssl req -config ./certs/ecc/wolfssl_384.cnf -sha384 -x509 -nodes -newkey ec:./certs/server-ecc384-key.par -keyout ./certs/server-ecc384-key.pem -out ./certs/server-ecc384-req.pem \ + -subj "/C=US/ST=Washington/L=Seattle/O=Eliptic/OU=ECC384Srv/CN=www.wolfssl.com/emailAddress=info@wolfssl.com/" +openssl req -config ./certs/ecc/wolfssl_384.cnf -sha384 -new -key ./certs/server-ecc384-key.pem -out ./certs/server-ecc384-req.pem \ + -subj "/C=US/ST=Washington/L=Seattle/O=Eliptic/OU=ECC384Srv/CN=www.wolfssl.com/emailAddress=info@wolfssl.com/" +openssl ec -in ./certs/server-ecc384-key.pem -inform PEM -out ./certs/server-ecc384-key.der -outform DER + +# Sign server certificate +openssl ca -config ./certs/ecc/wolfssl_384.cnf -extensions server_cert -days 10950 -notext -md sha384 -in ./certs/server-ecc384-req.pem -out ./certs/server-ecc384-cert.pem +openssl x509 -in ./certs/server-ecc384-cert.pem -outform der -out ./certs/server-ecc384-cert.der + +rm ./certs/server-ecc384-req.pem +rm ./certs/server-ecc384-key.par + +# Generate ECC 384-bit client cert +openssl ecparam -out ./certs/client-ecc384-key.par -name secp384r1 +openssl req -config ./certs/ecc/wolfssl_384.cnf -sha384 -x509 -nodes -newkey ec:./certs/client-ecc384-key.par -keyout ./certs/client-ecc384-key.pem -out ./certs/client-ecc384-req.pem \ + -subj "/C=US/ST=Washington/L=Seattle/O=Eliptic/OU=ECC384Cli/CN=www.wolfssl.com/emailAddress=info@wolfssl.com/" +openssl req -config ./certs/ecc/wolfssl_384.cnf -sha384 -new -key ./certs/client-ecc384-key.pem -out ./certs/client-ecc384-req.pem \ + -subj "/C=US/ST=Washington/L=Seattle/O=Eliptic/OU=ECC384Clit/CN=www.wolfssl.com/emailAddress=info@wolfssl.com/" +openssl ec -in ./certs/client-ecc384-key.pem -inform PEM -out ./certs/client-ecc384-key.der -outform DER + +# Sign client certificate +openssl ca -config ./certs/ecc/wolfssl_384.cnf -extensions usr_cert -days 10950 -notext -md sha384 -in ./certs/client-ecc384-req.pem -out ./certs/client-ecc384-cert.pem +openssl x509 -in ./certs/client-ecc384-cert.pem -outform der -out ./certs/client-ecc384-cert.der + +rm ./certs/client-ecc384-req.pem +rm ./certs/client-ecc384-key.par + + +# 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/FreeRTOS-Plus/Source/WolfSSL/certs/ecc/include.am b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc/include.am new file mode 100644 index 000000000..b9897c1c2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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 \ + certs/ecc/wolfssl_384.cnf diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ecc/wolfssl.cnf b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc/wolfssl.cnf new file mode 100644 index 000000000..a974aeb35 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc/wolfssl.cnf @@ -0,0 +1,110 @@ +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations relevant to where the script is executing +dir = . +certs = $dir/certs +new_certs_dir = $dir/certs +database = $dir/certs/ecc/index.txt +serial = $dir/certs/ecc/serial +# This should come from the system disregard local pathing +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/FreeRTOS-Plus/Source/WolfSSL/certs/ecc/wolfssl_384.cnf b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc/wolfssl_384.cnf new file mode 100644 index 000000000..7cb35f709 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ecc/wolfssl_384.cnf @@ -0,0 +1,110 @@ +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations relevant to where the script is executing +dir = . +certs = $dir/certs +new_certs_dir = $dir/certs +database = $dir/certs/ecc/index.txt +serial = $dir/certs/ecc/serial +# This should come from the system disregard local pathing +RANDFILE = $dir/private/.rand + +# The root key and root certificate. +private_key = $dir/certs/ca-ecc384-key.pem +certificate = $dir/certs/ca-ecc384-cert.pem + +# For certificate revocation lists. +crlnumber = $dir/certs/ecc/crlnumber +crl_extensions = crl_ext +default_crl_days = 1000 + +# SHA-384 is default +default_md = sha384 + +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-384 is default +default_md = sha384 + +# 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/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/ca-ed25519-key.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/ca-ed25519-key.der new file mode 100644 index 0000000000000000000000000000000000000000..fd4449c86dcd70c749cb4c84f0dae1052112a32f GIT binary patch literal 84 zcmXpAVq#=4U}a<0PAy?pWMd9x zVH0Kw4K@@o-~(|uc-VdO^GXu)5@90jJnT;SRjIj&d4{|O+#oe9JS;)^`6Vy~Ts-XM z`8jF9!9Fk%ZXR}57b8mW*+|X@^U?py5iy-z2y8{LwN&PHcqWJkGAi; zjGT;O0-1Sf`3^`543s4JjSLJe3``7-49$#;49%lJ0!D@gh6d(_reFbs#<`^X0_trR z9wui;n2TxU2Q6rDGb=KruBvBU!eX-E)mr(LZ69vb7u{dUC%nKSO)c)Vhe3mf=i&r| zI0GJFV95%zuo^HkGX4h!5Rk{mBE}*z$$nZ9)2~Ds#oUg&ukYH-7C$n7yMa7NTA2kH z#0?_<7~Sggwe4g!dP2UnKtk literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519-key.pem new file mode 100644 index 000000000..fa3c91922 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN EDDSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEICejNCo11Lu44dzY7A/BoNGiXPkG8ERdO5dNvd9KO6NO +oSIEIKLxJkCbolna2+YVf5oRtUhfVbpe7Ub3mGe+DJPjpI4Y +-----END EDDSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519-priv.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519-priv.der new file mode 100644 index 0000000000000000000000000000000000000000..6ca194a933fb8e812f0cd15c613a80cf7dc3bbda GIT binary patch literal 48 zcmV-00MGw0E&>4nFa-t!D`jv5A_O2Oqckct)VsLh+}P|7!JyHiT=@p@L|r?VO}*br GJEKl)dJ_)- literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519-priv.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519-priv.pem new file mode 100644 index 000000000..0104b1620 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519-priv.pem @@ -0,0 +1,3 @@ +-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VwBCIEICejNCo11Lu44dzY7A/BoNGiXPkG8ERdO5dNvd9KO6NO +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519.der new file mode 100644 index 0000000000000000000000000000000000000000..0fab773cabc2badda008310eee18370c413a3196 GIT binary patch literal 604 zcmXqLVu~0UC3@r>y42=xUjEoG;qd)>ih6aWP=7y$Vfg#}!Eoh)K zD>5wlsOB(xQRJ=L&qV8I32ya>58V~_*6sU@^nE;&A1~>XSR7;!01Ou9P+2|}F&2@3 zjBfS$+IBJ<@*ke@Wm5g_%Qba}fjmfBnFScI4cHZcVp5i$k?}tZ3o{ej0hsNM44U6E zAMGp_x|s61|7CXK?f93=lX3()9UC6M_$z-wc->Tn_20`MDjBVH^S@K~Z{40Q`Dt9Y R=AWD#q%N_c`_{fjP5}NSs!ad@ literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519.pem new file mode 100644 index 000000000..5cc566714 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/client-ed25519.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICWDCCAgqgAwIBAgIQAI8vNbJTvU+S0f8dS0ClSTAFBgMrZXAwgaExCzAJBgNV +BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMQ8wDQYD +VQQEDAZjbGllbnQxEDAOBgNVBAoMB3dvbGZTU0wxEDAOBgNVBAsMB0VEMjU1MTkx +GDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3 +b2xmc3NsLmNvbTAiGA8yMDE4MDQxMjE2MjIxN1oYDzIwMjEwMTA3MTUyMjE3WjCB +oTELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVt +YW4xDzANBgNVBAQMBmNsaWVudDEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwH +RUQyNTUxOTEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkB +FhBpbmZvQHdvbGZzc2wuY29tMCowBQYDK2VwAyEAovEmQJuiWdrb5hV/mhG1SF9V +ul7tRveYZ74Mk+OkjhijUjBQMB0GA1UdDgQWBBT+AUZ/bys+HLBv4cxNAiX3TQqV +uDAfBgNVHSMEGDAWgBT+AUZ/bys+HLBv4cxNAiX3TQqVuDAOBgNVHQ8BAf8EBAMC +BsAwBQYDK2VwA0EAKfZp4rlzEtFk64/pa2HbX+mnYmwQiUGA4+j9H9ATrpUAr/d3 +4SIyrUZP3H7+rryKH5YK2p/Jk1InGLCL2r6BCQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/include.am b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/include.am new file mode 100644 index 000000000..ad2897684 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/include.am @@ -0,0 +1,30 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + certs/ed25519/ca-ed25519.der \ + certs/ed25519/ca-ed25519.pem \ + certs/ed25519/ca-ed25519-key.der \ + certs/ed25519/ca-ed25519-key.pem \ + certs/ed25519/ca-ed25519-priv.der \ + certs/ed25519/ca-ed25519-priv.pem \ + certs/ed25519/client-ed25519.der \ + certs/ed25519/client-ed25519.pem \ + certs/ed25519/client-ed25519-key.der \ + certs/ed25519/client-ed25519-key.pem \ + certs/ed25519/client-ed25519-priv.der \ + certs/ed25519/client-ed25519-priv.pem \ + certs/ed25519/root-ed25519.der \ + certs/ed25519/root-ed25519.pem \ + certs/ed25519/root-ed25519-key.der \ + certs/ed25519/root-ed25519-key.pem \ + certs/ed25519/root-ed25519-priv.der \ + certs/ed25519/root-ed25519-priv.pem \ + certs/ed25519/server-ed25519.der \ + certs/ed25519/server-ed25519.pem \ + certs/ed25519/server-ed25519-cert.pem \ + certs/ed25519/server-ed25519-key.der \ + certs/ed25519/server-ed25519-key.pem \ + certs/ed25519/server-ed25519-priv.der \ + certs/ed25519/server-ed25519-priv.pem diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-key.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-key.der new file mode 100644 index 0000000000000000000000000000000000000000..f4990b312640e3f1333ed609f74924345b0fb1cd GIT binary patch literal 84 zcmV-a0IUBnQUU=0Fa-t!D`jv5A_O2Oqckct)VsLh+}P|7!JyHiT=@p@L|r?VO}*br qJEKmaA_O3!@g_idP2UnKtk literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-key.pem new file mode 100644 index 000000000..fa3c91922 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN EDDSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEICejNCo11Lu44dzY7A/BoNGiXPkG8ERdO5dNvd9KO6NO +oSIEIKLxJkCbolna2+YVf5oRtUhfVbpe7Ub3mGe+DJPjpI4Y +-----END EDDSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-priv.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-priv.der new file mode 100644 index 0000000000000000000000000000000000000000..6ca194a933fb8e812f0cd15c613a80cf7dc3bbda GIT binary patch literal 48 zcmV-00MGw0E&>4nFa-t!D`jv5A_O2Oqckct)VsLh+}P|7!JyHiT=@p@L|r?VO}*br GJEKl)dJ_)- literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-priv.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-priv.pem new file mode 100644 index 000000000..0104b1620 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519-priv.pem @@ -0,0 +1,3 @@ +-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VwBCIEICejNCo11Lu44dzY7A/BoNGiXPkG8ERdO5dNvd9KO6NO +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/root-ed25519.der new file mode 100644 index 0000000000000000000000000000000000000000..c1675faf0bcdc7d4e39e9b291935f5a14cb7d1c5 GIT binary patch literal 614 zcmXqLVoEY-ViH-v%*4pVB*4(GZ@MXXum7Zr|7E=$mU?pWMd9x zVH0Kw4K@@o-~(|uc-VdO^GXu)5@90jJnT;SRjIj&d4{|O+#oe9JS;)^`6Vy~Ts-XM z`8jF9!9Fk%ZXR}57b8mW*+|X@^U?py5iy-z2y8{LwN&PHcqWJkGAi; zjGT;O0-1Sf`3^`543s4JjSLJe3``7-49$#;49%lJ0!D@gh6d(_reJ{~;0rBifHNyH zEc&SCFndwtt=rE;>t_jW^@tDM75CQd`;7E`Jd+62KTU=U}(0}L)%VHQ>cW=6*U zz#szh_*lePME)_l)#q#5$!y4fc*d7W^}8?E)Ex%$AZcY5U?4YOR{)ArS$?2NEG)p} za17=aM+UczdJ3h*wN*jUcf!@mbLQ5TeOMsvX7fAYoA_O2|UF^3-lgWg8Xdy~X^aP8&&1_vgw_+?UCBq^~$cFMS?jpMY literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/server-ed25519-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/server-ed25519-key.pem new file mode 100644 index 000000000..60d9106c1 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/server-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN EDDSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEIAIvxf+6jtDSvwOOdo/IhoBxh5cx4kCs37uQFVJuJKE5 +oSIEIGFd7LdFk8mEe2ghSk30BIu9zWxdPbdiLC0lwyJJyIby +-----END EDDSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/server-ed25519-priv.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed25519/server-ed25519-priv.der new file mode 100644 index 0000000000000000000000000000000000000000..2245c976d7fb955535195698835545bab2c05cde GIT binary patch literal 48 zcmXreV`5}5U}a<0PAy7Vq#gq%*4pVB*1X?lm5Ot?7w!WGC%tNDr=?zD;u+RYJoxHTtjXHPB!LH z7B*p~&|pIW13nOkgNNNWKd&S)FA*lf&cp7MUzM7hmlJPIUWWN2V$U~Xs%7BFa>4|5Xne&99W204j^ zhs7r~F%9NsTKPf?8r;l^42iLCw!2O~*;1XM=;ix`rF-w$oLJlKNjkc!hm|}}w0&9} zWDo!h6y{J_J{B<+5#tjY$vt1f-^pz_E+kae)nH(CTEIXaB(2N>4AusbN%qr;Z8hHW1C literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/ca-ed448-priv.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/ca-ed448-priv.pem new file mode 100644 index 000000000..6bb628e7f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/ca-ed448-priv.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MEcCAQAwBQYDK2VxBDsEOQ0MPBFXhJUxmYnuqZQxWjxEvbqS7lm1D8fdInwsP7Sl +ZUr4yoXSFWuuzJapAjBD/+b8nl7xUB+h9g== +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/ca-ed448.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/ca-ed448.der new file mode 100644 index 0000000000000000000000000000000000000000..e63ce3e3cee37cbc09cf6fa068a484805626496a GIT binary patch literal 659 zcmXqLV(K?&V&Y%G%*4pV#K>sC%EqjnT4>NX(~#SMlZ`o)g-w_#G}utUfDgps;9>X8 z&nrpHON5EA^RPSRSEc4A<{63^h=9~^@$i=C=cEM(`^3AZn3z}?3L6N5#JPF6g7WiA zbRmKg24WyVW*+|X@^U?phT`HJz2y8{LwN&PHcqWJkGAi;jGT;O0-1Sf`3^`54CKUl zjSLKo42=y8jZIBVqJUf@Lqh{gDA%BIIyKy$3U<4o0YAj;9L|oq5FrX&?hFlHW-A81 zM_bCCUOIEgyLyA>zDd6iug_dMWmkd9i^cCxB+t6LY<+~Y1&hiDfrDOq7g#{Vp=2FyST9J{joAORL&N@#<*vzTGQ zl!Ny^)H`hIDF6Pw`j*pX`)@|!D_=U+2L{W0j=NfZ{a5HuzL3{9viqw)r zPRriz)W;2L)y}Pas+bxX^W3F$@ztZc1qL3WWhoJNmu8jQJat>T42irQF fG|}oRw+nkQ!Mn2;zL01J@_`V!txJd*gys94Aw?kU literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/client-ed448-priv.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/client-ed448-priv.pem new file mode 100644 index 000000000..ac2c00c6e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/client-ed448-priv.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MEcCAQAwBQYDK2VxBDsEOeKh6lG5syIN7WHlIePnstcOgeEy+yHkTLEH2zqcNNHq +KrcLezHBu7MXvpBoBvKBELmtS4gZhOX7nQ== +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/client-ed448.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/client-ed448.der new file mode 100644 index 0000000000000000000000000000000000000000..667cabab0f8858bfd49747b7bef2e2d866ec44c9 GIT binary patch literal 882 zcmXqLV$L&YVtTiLnTe5!Nkpn_+v>C7_wI%l&Z}B~Ax}Z#-us^htZdBMsf7lOvkkco zIN6v(S=fY`LW2zj4ER7C4jy*j{JfIHyhNA?I}f{4epPC2VxFOxfe1(q7Y}cFeok6& zuuptyiiwGZp{Ri{NSvF8$2li6HLpY$A}nDb1`=lG;V&;Q*8^!OF3!Nj{S=2hDW z>z`SonbYvTVQ~|qxC)WgOii2APc_%ZxeTFMPhD2 zPAVul!9u&3p}TXIgZWact_Q0wEx)HVw`E_S)B5Yb#j2~HFnO|XGR&R5)cka8cl_3c zxo@Y&E@z8AYWVH*id0E01|7HBy)|J?jQ!TC78j=POZ|{>^pERituWR-`UcB9%=dF` dzHV{qL(2{AFWq5A>MMUd%DOd6?XUszXc*Lm({qCHfP bjR>#HxI>gsUFB0^X~=bgrd~wKOIr&7!igQ? literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448-key.pem new file mode 100644 index 000000000..95630424c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448-key.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAC2QmKM+1RpvuP+o79WZ6MtT+ffiAX1hXbNd57maiPVSPjQiv +y7hDlFBd5VNiach1gqZeRMpLWwsA +-----END PUBLIC KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448-priv.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448-priv.der new file mode 100644 index 0000000000000000000000000000000000000000..41480571fc6e9011ca5af4b57bd0c47ce8fce139 GIT binary patch literal 73 zcmV-P0Ji@yM*;x=Fa-t!D`jy6I|MllUuErqkpxHW#!opfg@tSqpcS)vC~nuTqVYyp fvUN7P{fsRkRy^>#k2ilnWP_rRNJYgOGN}a0frcDT literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448-priv.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448-priv.pem new file mode 100644 index 000000000..0b28472a5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448-priv.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MEcCAQAwBQYDK2VxBDsEOQxfZe2BkQRH7cZPOS+FhWwSoBWzeihu166i8UZYsnU2 +uv2MLSFWPPC7jzd/QGSDopBIRcUaMqkEyg== +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448.der new file mode 100644 index 0000000000000000000000000000000000000000..181a58397f85b15c5504a59cffad1ebd73c9e4ec GIT binary patch literal 680 zcmXqLVp?L*#H6x-nTe5!NyO*v{InOxz8uPp-E&Li`^&^hzk6>Ou(C00rxqGC&NSpU z;ACSCWnmL$3Jo?CFyI4mIC$87^Ycm)^Aceq>^$sF`Bka8iFt-%1|lFeTs*wx`8jF9 z!9MY>DJCWshQbDdAaQOUuAuz<5?zR(gn<}HkeP?Syu4fwq@lPtM=v=)*HGR-mW@-Z z&70bmd>|kB0b&@SN+F@6s08hV=JxtUtZOc}hU+)8M4c6Qxbd z;#^L7M{_eQPBusch7oh9EFX&)i^#3a87I}eN`FVj1ksn^2hABoX2yA`;7+Ue=vk1~By z_@eM@g=+qtpGUT@*=LzyJukw`>2S%T(7i4p4iYt24BYdBnHx?j1}uFkukPX$f9}fi yCHv#78QNs}mV5bot0c?(@nf@G&r;h`pSJSJ%jdhcx4%%Yk-8dcTeo+D0RsT(Ceon* literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448.pem new file mode 100644 index 000000000..8cfaf623f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/root-ed448.pem @@ -0,0 +1,54 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 4c:ed:9f:66:e8:c6:f4:c2:6d:5d:bc:da:14:f7:e9:61:92:fb:8d:d8 + Signature Algorithm: ED448 + Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_Ed448, OU = Root-Ed448, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Validity + Not Before: Feb 13 01:35:44 2020 GMT + Not After : Nov 9 01:35:44 2022 GMT + Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_Ed448, OU = Root-Ed448, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: ED448 + ED448 Public-Key: + pub: + 0b:64:26:28:cf:b5:46:9b:ee:3f:ea:3b:f5:66:7a: + 32:d4:fe:7d:f8:80:5f:58:57:6c:d7:79:ee:66:a2: + 3d:54:8f:8d:08:af:cb:b8:43:94:50:5d:e5:53:62: + 69:c8:75:82:a6:5e:44:ca:4b:5b:0b:00 + X509v3 extensions: + X509v3 Subject Key Identifier: + DA:69:98:C9:26:4A:75:FB:59:5E:53:9A:63:4B:0C:B8:88:0B:0F:1E + X509v3 Authority Key Identifier: + keyid:DA:69:98:C9:26:4A:75:FB:59:5E:53:9A:63:4B:0C:B8:88:0B:0F:1E + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: ED448 + 32:f2:95:d6:56:9f:c4:5c:2a:36:da:51:b7:96:cb:97:f7:c5: + 02:f2:20:f4:20:fa:a8:25:6f:dc:f9:c4:b7:ac:be:39:68:3b: + 9e:58:4a:42:c3:74:e2:55:bd:44:54:40:18:7c:d4:30:47:6f: + 53:03:80:c9:21:50:a5:e9:1f:27:44:42:5f:ce:d4:a7:a4:bf: + 5e:3b:00:86:1c:8e:a7:4a:4f:4b:24:63:1c:fc:4e:06:39:af: + 04:7d:84:7f:66:a9:e4:e9:e7:ba:b7:87:e8:27:7c:1a:d5:55: + 3d:7e:bd:90:30:00 +-----BEGIN CERTIFICATE----- +MIICpDCCAiSgAwIBAgIUTO2fZujG9MJtXbzaFPfpYZL7jdgwBQYDK2VxMIGZMQsw +CQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEW +MBQGA1UECgwNd29sZlNTTF9FZDQ0ODETMBEGA1UECwwKUm9vdC1FZDQ0ODEYMBYG +A1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tMB4XDTIwMDIxMzAxMzU0NFoXDTIyMTEwOTAxMzU0NFowgZkxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRYwFAYD +VQQKDA13b2xmU1NMX0VkNDQ4MRMwEQYDVQQLDApSb290LUVkNDQ4MRgwFgYDVQQD +DA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b20wQzAFBgMrZXEDOgALZCYoz7VGm+4/6jv1Znoy1P59+IBfWFds13nuZqI9VI+N +CK/LuEOUUF3lU2JpyHWCpl5EyktbCwCjYzBhMB0GA1UdDgQWBBTaaZjJJkp1+1le +U5pjSwy4iAsPHjAfBgNVHSMEGDAWgBTaaZjJJkp1+1leU5pjSwy4iAsPHjAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAFBgMrZXEDcwAy8pXWVp/EXCo2 +2lG3lsuX98UC8iD0IPqoJW/c+cS3rL45aDueWEpCw3TiVb1EVEAYfNQwR29TA4DJ +IVCl6R8nREJfztSnpL9eOwCGHI6nSk9LJGMc/E4GOa8EfYR/Zqnk6ee6t4foJ3wa +1VU9fr2QMAA= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-cert.pem new file mode 100644 index 000000000..c239c13db --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-cert.pem @@ -0,0 +1,57 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: ED448 + Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed448, OU = CA-ed448, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Validity + Not Before: Feb 13 01:35:44 2020 GMT + Not After : Nov 9 01:35:44 2022 GMT + Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed448, OU = Server-ed448, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: ED448 + ED448 Public-Key: + pub: + 54:81:39:01:eb:37:d9:a9:07:cd:01:bc:9d:70:16: + c2:2c:2b:75:5b:63:db:ee:3a:2d:44:92:46:b4:7b: + 07:03:4f:a2:ae:86:86:dc:8b:4b:2c:7f:e8:6b:14: + 8d:58:dd:6d:e7:6f:3a:05:95:a8:ef:00 + X509v3 extensions: + X509v3 Subject Key Identifier: + 7C:AB:5C:12:A9:68:D8:18:10:28:7D:92:C5:4A:B8:4C:4C:76:0E:DB + X509v3 Authority Key Identifier: + keyid:38:59:45:E8:DD:44:2C:B5:7D:A5:25:D6:0B:CC:39:F0:72:C0:94:63 + + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Key Agreement + X509v3 Extended Key Usage: + TLS Web Server Authentication + Netscape Cert Type: + SSL Server + Signature Algorithm: ED448 + 91:15:fc:8e:a6:00:50:bf:8e:44:4e:14:39:a3:91:29:12:25: + a5:8b:42:5b:85:a0:c3:d7:b3:6a:1b:4c:d9:4f:20:5a:92:5b: + 58:2a:f4:86:21:35:0b:d6:a5:b1:ca:98:6a:cb:09:c7:98:a5: + 22:b6:00:a2:ef:81:19:4f:4d:28:4e:80:47:6a:3c:82:88:84: + 8b:03:99:48:5b:cc:c4:75:98:b2:70:b1:93:6c:24:a7:8e:01: + 6a:2f:15:53:25:c2:45:5c:b6:25:db:17:93:fb:9c:1d:0f:c6: + a6:88:70:44:2e:00 +-----BEGIN CERTIFICATE----- +MIICuDCCAjigAwIBAgIBATAFBgMrZXEwgZcxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRYwFAYDVQQKDA13b2xmU1NMX2Vk +NDQ4MREwDwYDVQQLDAhDQS1lZDQ0ODEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t +MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIwMDIxMzAxMzU0 +NFoXDTIyMTEwOTAxMzU0NFowgZsxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250 +YW5hMRAwDgYDVQQHDAdCb3plbWFuMRYwFAYDVQQKDA13b2xmU1NMX2VkNDQ4MRUw +EwYDVQQLDAxTZXJ2ZXItZWQ0NDgxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEf +MB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTBDMAUGAytlcQM6AFSBOQHr +N9mpB80BvJ1wFsIsK3VbY9vuOi1Ekka0ewcDT6Kuhobci0ssf+hrFI1Y3W3nbzoF +lajvAKOBiTCBhjAdBgNVHQ4EFgQUfKtcEqlo2BgQKH2SxUq4TEx2DtswHwYDVR0j +BBgwFoAUOFlF6N1ELLV9pSXWC8w58HLAlGMwDAYDVR0TAQH/BAIwADAOBgNVHQ8B +Af8EBAMCA6gwEwYDVR0lBAwwCgYIKwYBBQUHAwEwEQYJYIZIAYb4QgEBBAQDAgZA +MAUGAytlcQNzAJEV/I6mAFC/jkROFDmjkSkSJaWLQluFoMPXs2obTNlPIFqSW1gq +9IYhNQvWpbHKmGrLCceYpSK2AKLvgRlPTShOgEdqPIKIhIsDmUhbzMR1mLJwsZNs +JKeOAWovFVMlwkVctiXbF5P7nB0PxqaIcEQuAA== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-key.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-key.der new file mode 100644 index 0000000000000000000000000000000000000000..4804c53be3e4e31726f53d83466aca90b53bd484 GIT binary patch literal 69 zcmV-L0J{G$Lofvf11n{513CayfjI%|H`%EN%>lffa2CQWD|K6A+wM9oM3P3ddj|tg bqOOL9+>1*rf9Puzjac1n=WjX%m8kCkPDvYw literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-key.pem new file mode 100644 index 000000000..efb1224ec --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-key.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAVIE5Aes32akHzQG8nXAWwiwrdVtj2+46LUSSRrR7BwNPoq6G +htyLSyx/6GsUjVjdbedvOgWVqO8A +-----END PUBLIC KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-priv.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-priv.der new file mode 100644 index 0000000000000000000000000000000000000000..53514f5697be027ff1de378cb55ef154d187f909 GIT binary patch literal 73 zcmV-P0Ji@yM*;x=Fa-t!D`jy6I|MnH<3=bgqNMhJbddNg8FPkGFBySHN-tI*Smq;; fl8?3EP7)>aVJs8Aztf!-T+7oEezf+g`XQCSfWsZ3 literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-priv.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-priv.pem new file mode 100644 index 000000000..9be220d0e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448-priv.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MEcCAQAwBQYDK2VxBDsEOZjjRigtoqT2f3SQ+CwZc4ZSLxmBR0ovViBY5iOQko+1 +4E4SJfNhLBO+v9OdFlzL0xJ+tPaq+iGVvw== +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448.der b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448.der new file mode 100644 index 0000000000000000000000000000000000000000..c9971b413037bc0add36d48b3549da9f876c3d11 GIT binary patch literal 700 zcmXqLV%lNQ#ALC6nTe5!iILHOm5o_Dwa}n(x*@j#CmVAp3!5-gXt1Gx0UwCN!NcyG zpI4HYmk1MK=V5osuS(5L%rg`-5CN&-;^8gN&q)go_K8nTF)^_)6g1!miF5OCI6LY> zgd_~aKtjws{N?54dLZS+#W{M(`MHMj2C{6NT5TR}-+3818N~!L^V0GikQ5lmiSrs6 z7#JBE8yFg!nwUfZxkiSD29{8+LE~)dxm?sh7~*oC;MAhB)FR4V?+guKW-Eq}MoY%m z<~LWepJm)Lw?OQWj&^Bu^6ht4x-OI4wp6n-`!8D8)^?}cTc`d-wn%Tp-Q4H-R;*K3 zyk}V4*lEz%1`H?WP+2|}F&2@U)iFXVGj2!-Xw*(R>b1kir;P8mfjmfBnFScq4I&ni zt}pJo=xnWBs(Ow4jOB--15=U>ct8q-85#exFc~m_qgR$6#A9J*VqO9ExU4D*j{z4O zhc+7{D=RxQqk$kBXF{6?W7`iWMn;f2HV2q@iWw$~{^?uB5U{_`#ZSa?@kC7_)ur7| z(X9&(U*DW1?Q_##A!<@|gw~ffMN{r;OE;dHk#(B$_>84W+ZYzTZ7C1sf;ls4VYe%+ePPRz2hzvrYB3_~hSnWciOR>nL#1V*mhz$;CVX literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448.pem new file mode 100644 index 000000000..6dfa73000 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ed448/server-ed448.pem @@ -0,0 +1,109 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: ED448 + Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed448, OU = CA-ed448, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Validity + Not Before: Feb 13 01:35:44 2020 GMT + Not After : Nov 9 01:35:44 2022 GMT + Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed448, OU = Server-ed448, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: ED448 + ED448 Public-Key: + pub: + 54:81:39:01:eb:37:d9:a9:07:cd:01:bc:9d:70:16: + c2:2c:2b:75:5b:63:db:ee:3a:2d:44:92:46:b4:7b: + 07:03:4f:a2:ae:86:86:dc:8b:4b:2c:7f:e8:6b:14: + 8d:58:dd:6d:e7:6f:3a:05:95:a8:ef:00 + X509v3 extensions: + X509v3 Subject Key Identifier: + 7C:AB:5C:12:A9:68:D8:18:10:28:7D:92:C5:4A:B8:4C:4C:76:0E:DB + X509v3 Authority Key Identifier: + keyid:38:59:45:E8:DD:44:2C:B5:7D:A5:25:D6:0B:CC:39:F0:72:C0:94:63 + + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Key Agreement + X509v3 Extended Key Usage: + TLS Web Server Authentication + Netscape Cert Type: + SSL Server + Signature Algorithm: ED448 + 91:15:fc:8e:a6:00:50:bf:8e:44:4e:14:39:a3:91:29:12:25: + a5:8b:42:5b:85:a0:c3:d7:b3:6a:1b:4c:d9:4f:20:5a:92:5b: + 58:2a:f4:86:21:35:0b:d6:a5:b1:ca:98:6a:cb:09:c7:98:a5: + 22:b6:00:a2:ef:81:19:4f:4d:28:4e:80:47:6a:3c:82:88:84: + 8b:03:99:48:5b:cc:c4:75:98:b2:70:b1:93:6c:24:a7:8e:01: + 6a:2f:15:53:25:c2:45:5c:b6:25:db:17:93:fb:9c:1d:0f:c6: + a6:88:70:44:2e:00 +-----BEGIN CERTIFICATE----- +MIICuDCCAjigAwIBAgIBATAFBgMrZXEwgZcxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRYwFAYDVQQKDA13b2xmU1NMX2Vk +NDQ4MREwDwYDVQQLDAhDQS1lZDQ0ODEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t +MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIwMDIxMzAxMzU0 +NFoXDTIyMTEwOTAxMzU0NFowgZsxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250 +YW5hMRAwDgYDVQQHDAdCb3plbWFuMRYwFAYDVQQKDA13b2xmU1NMX2VkNDQ4MRUw +EwYDVQQLDAxTZXJ2ZXItZWQ0NDgxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEf +MB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTBDMAUGAytlcQM6AFSBOQHr +N9mpB80BvJ1wFsIsK3VbY9vuOi1Ekka0ewcDT6Kuhobci0ssf+hrFI1Y3W3nbzoF +lajvAKOBiTCBhjAdBgNVHQ4EFgQUfKtcEqlo2BgQKH2SxUq4TEx2DtswHwYDVR0j +BBgwFoAUOFlF6N1ELLV9pSXWC8w58HLAlGMwDAYDVR0TAQH/BAIwADAOBgNVHQ8B +Af8EBAMCA6gwEwYDVR0lBAwwCgYIKwYBBQUHAwEwEQYJYIZIAYb4QgEBBAQDAgZA +MAUGAytlcQNzAJEV/I6mAFC/jkROFDmjkSkSJaWLQluFoMPXs2obTNlPIFqSW1gq +9IYhNQvWpbHKmGrLCceYpSK2AKLvgRlPTShOgEdqPIKIhIsDmUhbzMR1mLJwsZNs +JKeOAWovFVMlwkVctiXbF5P7nB0PxqaIcEQuAA== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: ED448 + Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_Ed448, OU = Root-Ed448, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Validity + Not Before: Feb 13 01:35:44 2020 GMT + Not After : Nov 9 01:35:44 2022 GMT + Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_ed448, OU = CA-ed448, CN = www.wolfssl.com, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: ED448 + ED448 Public-Key: + pub: + 0e:e2:b4:76:e5:d2:cc:c2:4b:7b:b0:29:be:92:fb: + c3:af:69:a5:94:ba:70:24:e8:a3:ef:c8:63:9a:dd: + a6:af:58:43:38:04:24:f0:10:91:be:a7:01:91:54: + f3:cf:69:85:4c:b9:97:8c:a4:37:aa:00 + X509v3 extensions: + X509v3 Subject Key Identifier: + 38:59:45:E8:DD:44:2C:B5:7D:A5:25:D6:0B:CC:39:F0:72:C0:94:63 + X509v3 Authority Key Identifier: + keyid:DA:69:98:C9:26:4A:75:FB:59:5E:53:9A:63:4B:0C:B8:88:0B:0F:1E + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: ED448 + a0:94:c1:de:f0:7f:40:b2:88:77:f7:f7:7b:da:42:b3:3f:f6: + 32:57:a9:e9:41:7f:51:53:1c:f3:5e:d5:77:d7:fa:55:f9:0e: + 54:eb:d8:6b:4e:bc:e9:0d:38:ea:da:c4:81:23:2c:84:bd:8b: + 65:e3:80:ad:26:ce:a9:e5:21:65:59:5c:e7:44:75:a3:d5:c5: + 2d:70:30:48:55:76:64:58:dd:a5:6a:77:3c:e5:46:aa:54:49: + a9:cd:48:f7:7b:ac:36:01:4a:61:aa:f3:3b:0b:fe:9f:56:5a: + ba:51:e4:33:2e:00 +-----BEGIN CERTIFICATE----- +MIICjzCCAg+gAwIBAgIBATAFBgMrZXEwgZkxCzAJBgNVBAYTAlVTMRAwDgYDVQQI +DAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRYwFAYDVQQKDA13b2xmU1NMX0Vk +NDQ4MRMwEQYDVQQLDApSb290LUVkNDQ4MRgwFgYDVQQDDA93d3cud29sZnNzbC5j +b20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjAwMjEzMDEz +NTQ0WhcNMjIxMTA5MDEzNTQ0WjCBlzELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01v +bnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFjAUBgNVBAoMDXdvbGZTU0xfZWQ0NDgx +ETAPBgNVBAsMCENBLWVkNDQ4MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAd +BgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wQzAFBgMrZXEDOgAO4rR25dLM +wkt7sCm+kvvDr2mllLpwJOij78hjmt2mr1hDOAQk8BCRvqcBkVTzz2mFTLmXjKQ3 +qgCjYzBhMB0GA1UdDgQWBBQ4WUXo3UQstX2lJdYLzDnwcsCUYzAfBgNVHSMEGDAW +gBTaaZjJJkp1+1leU5pjSwy4iAsPHjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBhjAFBgMrZXEDcwCglMHe8H9Asoh39/d72kKzP/YyV6npQX9RUxzzXtV3 +1/pV+Q5U69hrTrzpDTjq2sSBIyyEvYtl44CtJs6p5SFlWVznRHWj1cUtcDBIVXZk +WN2lanc85UaqVEmpzUj3e6w2AUphqvM7C/6fVlq6UeQzLgA= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/external/baltimore-cybertrust-root.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/external/baltimore-cybertrust-root.pem new file mode 100644 index 000000000..519028c63 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/external/baltimore-cybertrust-root.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/external/ca-digicert-ev.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/external/ca-digicert-ev.pem new file mode 100644 index 000000000..9e6810ab7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/external/ca-digicert-ev.pem @@ -0,0 +1,23 @@ +-----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----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/external/ca-globalsign-root.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/external/ca-globalsign-root.pem new file mode 100644 index 000000000..48e3e7cc8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/external/ca-globalsign-root.pem @@ -0,0 +1,42 @@ +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/external/ca-google-root.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/external/ca-google-root.pem new file mode 100644 index 000000000..6f0f8db0d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/external/ca-google-root.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/external/include.am b/FreeRTOS-Plus/Source/WolfSSL/certs/external/include.am new file mode 100644 index 000000000..3ab9650e6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/external/include.am @@ -0,0 +1,9 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + certs/external/ca-globalsign-root.pem \ + certs/external/ca-google-root.pem\ + certs/external/ca-digicert-ev.pem \ + certs/external/baltimore-cybertrust-root.pem diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/include.am b/FreeRTOS-Plus/Source/WolfSSL/certs/include.am index b5192043e..45193b5ae 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/certs/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/include.am @@ -3,42 +3,111 @@ # EXTRA_DIST += \ + certs/ca-cert-chain.der \ certs/ca-cert.pem \ certs/ca-key.pem \ certs/client-cert.pem \ certs/client-keyEnc.pem \ certs/client-key.pem \ + certs/client-uri-cert.pem \ + certs/client-relative-uri.pem \ certs/ecc-key.pem \ + certs/ecc-privkey.pem \ + certs/ecc-privkeyPkcs8.der \ + certs/ecc-privkeyPkcs8.pem \ + certs/ecc-keyPkcs8Enc.pem \ + certs/ecc-keyPkcs8Enc.der \ certs/ecc-key-comp.pem \ certs/ecc-keyPkcs8.pem \ + certs/ecc-keyPkcs8.der \ certs/ecc-client-key.pem \ + certs/ecc-client-keyPub.pem \ certs/client-ecc-cert.pem \ + certs/client-ca.pem \ certs/ntru-cert.pem \ certs/dh2048.pem \ certs/server-cert.pem \ certs/server-ecc.pem \ + certs/server-ecc-self.pem \ certs/server-ecc-comp.pem \ certs/server-ecc-rsa.pem \ certs/server-keyEnc.pem \ certs/server-key.pem \ + certs/server-keyPkcs8.der \ certs/server-keyPkcs8Enc12.pem \ certs/server-keyPkcs8Enc2.pem \ certs/server-keyPkcs8Enc.pem \ + certs/server-keyPkcs8Enc.der \ certs/server-keyPkcs8.pem \ - certs/wolfssl-website-ca.pem + certs/server-revoked-cert.pem \ + certs/server-revoked-key.pem \ + certs/wolfssl-website-ca.pem \ + certs/test-degenerate.p7b \ + certs/test-ber-exp02-05-2022.p7b \ + certs/test-servercert.p12 \ + certs/ecc-rsa-server.p12 \ + certs/dsaparams.pem \ + certs/ecc-privOnlyKey.pem \ + certs/ecc-privOnlyCert.pem \ + certs/dh3072.pem \ + certs/dh4096.pem \ + certs/client-cert-ext.pem + EXTRA_DIST += \ certs/ca-key.der \ certs/ca-cert.der \ certs/client-cert.der \ certs/client-key.der \ + certs/client-ecc-cert.der \ + certs/client-keyPub.der \ certs/dh2048.der \ + certs/dh3072.der \ + certs/dh4096.der \ certs/rsa2048.der \ + certs/rsa-pub-2048.pem \ + certs/rsa3072.der \ certs/dsa2048.der \ + certs/dsa3072.der \ + certs/ecc-client-key.der \ + certs/ecc-client-keyPub.der \ certs/ecc-key.der \ + certs/ecc-keyPub.der \ certs/server-key.der \ - certs/server-cert.der + certs/server-cert.der \ + certs/server-ecc-comp.der \ + certs/server-ecc.der \ + certs/server-ecc-self.der \ + certs/server-ecc-rsa.der \ + certs/server-cert-chain.der \ + certs/client-cert-ext.der + +# ECC CA prime256v1 +EXTRA_DIST += \ + certs/ca-ecc-cert.der \ + certs/ca-ecc-cert.pem \ + certs/ca-ecc-key.der \ + certs/ca-ecc-key.pem + +# ECC CA SECP384R1 +EXTRA_DIST += \ + certs/ca-ecc384-cert.der \ + certs/ca-ecc384-cert.pem \ + certs/ca-ecc384-key.der \ + certs/ca-ecc384-key.pem dist_doc_DATA+= certs/taoCert.txt EXTRA_DIST+= certs/ntru-key.raw +include certs/1024/include.am +include certs/3072/include.am +include certs/4096/include.am +include certs/crl/include.am +include certs/ecc/include.am +include certs/ed25519/include.am +include certs/ed448/include.am +include certs/external/include.am +include certs/ocsp/include.am +include certs/test/include.am +include certs/test-pathlen/include.am +include certs/intermediate/include.am diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-cert.der b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-cert.der new file mode 100644 index 0000000000000000000000000000000000000000..d7c9a71d676c3a0867c558771533eff16b1ae6fc GIT binary patch literal 1051 zcmXqLVi7lJV*0;;nTe5!iAjLLfR~L^tIebBJ1-+6H!Fid;}k<~15P&PP!={}rqEzR z0Ruh|hl7XRH$Sf=F)tA&!p_6)lwXyao0w-PXuuCr!^Oi9oLF9xpI?$;C~P1I65{6J za?Z~yF3l;)%u6?vFc1R?GV}14mzV36=jWsq7w70D=jR&A8_2?)!O18lkeQd3?|`Jh zKu(<3(8AEj$k5Q-)WpCbN}Sgi$Tc*Bat#{iqdFUEKL-z2cw%t|(DIV}JS3L~rzVz^ zmIVj<7>XDOK^)HQl3JFUlV6aVnpa||U?2x^xj0mvf@fYyYEf=#N@ik7 zs)Dm4VIMRxDj|n8BP#=Q6C*!^K@%evQxhX2!{J56v5H9w=d21XmQUGzyPZWQN_w6* zuidF1OTY7G-BF&Pl%*Y!?4^)AJ{j0w{`ZbwIn*?d5U3!`lnsV)~x1)7vbKU_# zzC49PV#Tiw{&TwRetzZ{vx}qPv4c5g`d&XLhMtOuGvA>hV9@C>t^9mJ+LF-UncUBB zZZb~2U1U|hUEA}|wzCley{lK9c5p3cvXt1|Z_MaX9bT75mv=w^7ha+btCPbOwY2FAr{1}VU#z#J;e z$0Eie@;>vy_p7qcX1=+Td*S<|oiQne&87zOAZcY5U}9yGSr`Yr@->TfH{HZ0uu$CI~A~gZ{caSTSET< DC`oy^ literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-cert.pem new file mode 100644 index 000000000..e2ccd52d7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-cert.pem @@ -0,0 +1,83 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + 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: Dec 21 17:54:00 2018 GMT + Not After : Dec 16 17:54:00 2038 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Development, CN=wolfSSL Intermediate CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c3:a2:73:5d:21:62:20:ce:3a:71:38:a7:94:bb: + db:87:04:1c:5a:1b:9e:4b:0d:3e:ca:f8:a5:f7:0d: + 6a:dc:23:90:22:6a:2b:58:63:4a:28:6a:48:a8:e7: + 73:1f:a2:55:d8:4d:02:3b:e2:cb:6b:e2:83:c9:51: + 8f:77:fd:dc:2d:5d:23:b7:23:9a:7e:b6:29:68:e8: + 2a:4e:a9:fe:32:70:31:9e:f0:ef:ee:f8:8d:e3:fc: + f3:d7:28:dd:7a:1d:9e:ad:23:2b:f1:a6:7f:34:52: + 29:66:d2:e5:64:55:64:d6:dd:4b:41:3b:55:83:6e: + c0:11:0e:6e:20:c2:16:73:eb:30:ff:09:46:bb:e7: + cc:c6:03:44:41:11:c6:c1:6c:36:2f:4a:f9:91:55: + ca:58:5e:37:b8:28:10:30:89:40:96:77:cf:70:66: + a4:55:fb:69:0b:e7:d9:b2:33:65:db:72:3a:77:b7: + 2b:49:fc:b6:cd:58:10:8d:ab:aa:cb:40:45:77:02: + 39:18:b3:8f:33:01:48:77:50:be:8e:73:a7:de:36: + a0:49:8e:2c:16:af:b9:fb:42:2d:35:6a:db:34:37: + d5:14:59:7d:65:72:e5:8b:65:55:4b:20:5e:47:f9: + f8:3a:d3:6c:d9:3a:f5:c7:01:46:31:c3:79:9a:18: + be:49 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EF:69:E0:F7:D5:1D:E6:99:EC:DC:6D:D0:F7:E2:B9:5C:64:71:83:35 + 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 + + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 5e:cd:30:ce:13:06:a8:a3:25:6d:85:68:bf:88:3b:68:12:6a: + 5e:5f:22:82:51:4a:fd:b1:ae:b2:c2:3e:a1:e4:73:97:6f:77: + 1f:5e:0a:a6:3e:8a:20:93:4c:3f:68:64:69:a8:d7:ae:3e:a5: + 58:e4:d0:45:e4:7a:5f:cc:68:23:3d:7b:df:8d:33:8d:ba:0b: + 73:dd:97:41:99:1a:26:7f:17:87:c4:76:bb:3b:b5:15:24:b0: + 82:4f:2e:0a:c3:fe:ab:75:c9:4d:59:74:1a:c7:33:e7:4f:14: + 45:5b:f4:d3:c3:a9:9d:34:a8:e1:2a:33:ea:10:07:db:9e:33: + 83:60:f0:dd:7c:27:0d:6b:92:ef:90:cc:35:b3:4e:e3:fa:ca: + 87:55:31:e8:7b:8c:c2:35:19:41:6a:76:6c:6c:7a:d0:6a:d1: + 2d:a8:a6:97:40:73:52:9c:3c:43:a7:4b:f1:b7:04:af:e0:d1: + 32:3c:ac:df:a7:4a:15:fb:2e:56:d8:5c:4c:99:9d:3c:f0:6d: + a0:20:25:96:c9:24:fc:84:4c:dc:de:1d:29:e8:d4:e1:ff:ca: + 06:2f:39:ed:24:dc:79:f9:2a:18:00:ae:d2:8b:44:eb:2a:94: + fb:c8:02:86:0d:7e:1f:65:c7:20:06:5e:ca:50:af:bd:71:cb: + 06:da:12:ff +-----BEGIN CERTIFICATE----- +MIIEFzCCAv+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT +MRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhT +YXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MTIy +MTE3NTQwMFoXDTM4MTIxNjE3NTQwMFowgZ8xCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM +MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEgMB4GA1UEAwwXd29sZlNTTCBJbnRlcm1l +ZGlhdGUgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDonNdIWIgzjpxOKeUu9uHBBxaG55L +DT7K+KX3DWrcI5AiaitYY0ooakio53MfolXYTQI74str4oPJUY93/dwtXSO3I5p+ +tilo6CpOqf4ycDGe8O/u+I3j/PPXKN16HZ6tIyvxpn80Uilm0uVkVWTW3UtBO1WD +bsARDm4gwhZz6zD/CUa758zGA0RBEcbBbDYvSvmRVcpYXje4KBAwiUCWd89wZqRV ++2kL59myM2Xbcjp3tytJ/LbNWBCNq6rLQEV3AjkYs48zAUh3UL6Oc6feNqBJjiwW +r7n7Qi01ats0N9UUWX1lcuWLZVVLIF5H+fg602zZOvXHAUYxw3maGL5JAgMBAAGj +ZjBkMB0GA1UdDgQWBBTvaeD31R3mmezcbdD34rlcZHGDNTAfBgNVHSMEGDAWgBQn +jmcRdMMmHT/tM2OzpNgdMOXo1TASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB +/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAXs0wzhMGqKMlbYVov4g7aBJqXl8i +glFK/bGussI+oeRzl293H14Kpj6KIJNMP2hkaajXrj6lWOTQReR6X8xoIz17340z +jboLc92XQZkaJn8Xh8R2uzu1FSSwgk8uCsP+q3XJTVl0Gscz508URVv008OpnTSo +4Soz6hAH254zg2Dw3XwnDWuS75DMNbNO4/rKh1Ux6HuMwjUZQWp2bGx60GrRLaim +l0BzUpw8Q6dL8bcEr+DRMjys36dKFfsuVthcTJmdPPBtoCAllskk/IRM3N4dKejU +4f/KBi857STcefkqGACu0otE6yqU+8gChg1+H2XHIAZeylCvvXHLBtoS/w== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-cert.der b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-cert.der new file mode 100644 index 0000000000000000000000000000000000000000..171c86b1d5b5b84d6b3df34ba163663c1baefd27 GIT binary patch literal 661 zcmXqLVwz~s#ALC6nTe5!iAjLjfQyYotIgw_EekV~LF05oZUas>=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@pH5k)ffvsfmGMlsK<3kZWiL6L$ zHr;qEvh47|Eo*&UBoyRg)BlRf=Bhpv-&lC6mHES^^^R$7X1T8%Py3(ny09RzXK|WA z3NQ?rLuL6`#8^b8%O)IdSBjjSAm6fOrc8(L{#$Z+2J#?jWfov8G>C-t%{u(S>7K++ z*U-G5lh408{CTM&IL>5+85#exa2T)wDJDh+a9qpsgT#Odgs}}dxiGsk7`QMgDD>{# z!_gI_uzJsjDLgh7bLJh82%a*fKHOHcuQa}=sgg;-!H!>j){9-Uzsx*eXqIvDtzn4y S3qA7-^E_9oR~}?G2><}JU%oQ{ literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-cert.pem new file mode 100644 index 000000000..885ebf484 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-cert.pem @@ -0,0 +1,52 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4099 (0x1003) + 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: Dec 21 17:54:01 2018 GMT + Not After : Dec 16 17:54:01 2038 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Development, CN=wolfSSL Intermediate CA ECC/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:95:df:1c:b2:9e:20:a9:1d:a2:5b:ab:5c:9b:a8: + 66:06:29:e6:b2:d8:e3:14:a6:c3:c1:b4:ad:4d:44: + 18:20:1e:5d:67:fd:15:1d:6d:25:e1:17:b1:71:ca: + 85:03:f0:d2:af:41:66:46:36:6d:ea:41:cb:4f:c8: + 4a:d0:a0:61:8c + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Subject Key Identifier: + 97:1D:60:C3:87:22:59:9B:60:1F:84:B4:99:1C:88:4D:BF:DA:1E:6E + 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, pathlen:0 + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: ecdsa-with-SHA256 + 30:44:02:20:20:8d:bd:bc:08:8a:52:20:ab:bc:f0:94:0c:3c: + 38:9c:9e:c0:18:53:94:94:7f:57:3d:15:8e:75:5f:8c:82:79: + 02:20:40:3e:0f:27:9a:e8:ba:9b:f4:99:cf:71:36:68:d1:ed: + 31:54:37:e8:2e:37:d0:9e:49:a9:27:79:c1:03:34:50 +-----BEGIN CERTIFICATE----- +MIICkTCCAjigAwIBAgICEAMwCgYIKoZIzj0EAwIwgZcxCzAJBgNVBAYTAlVTMRMw +EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3 +b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MTIy +MTE3NTQwMVoXDTM4MTIxNjE3NTQwMVowgaMxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM +MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEkMCIGA1UEAwwbd29sZlNTTCBJbnRlcm1l +ZGlhdGUgQ0EgRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMFkw +EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEld8csp4gqR2iW6tcm6hmBinmstjjFKbD +wbStTUQYIB5dZ/0VHW0l4RexccqFA/DSr0FmRjZt6kHLT8hK0KBhjKNmMGQwHQYD +VR0OBBYEFJcdYMOHIlmbYB+EtJkciE2/2h5uMB8GA1UdIwQYMBaAFFaOmsPwQt4Y +uUVVbvmTz+rD86UhMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGG +MAoGCCqGSM49BAMCA0cAMEQCICCNvbwIilIgq7zwlAw8OJyewBhTlJR/Vz0VjnVf +jIJ5AiBAPg8nmui6m/SZz3E2aNHtMVQ36C430J5JqSd5wQM0UA== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-key.der b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-key.der new file mode 100644 index 0000000000000000000000000000000000000000..7917cfccf5df29dbed4aa9d36056e0d38cb3d33f GIT binary patch literal 121 zcmV-<0EYiCcLD(c1RyhpUK$z~kb|fE((dVM*%Qb8X~!0=pJzn=yd|B};@6-G1_&yK zNX|V20SBQ(13~}M3*U1$9j9c?Ay b7qM~5g#+-?uR&%;Hf`!b%TLHk(4b+AR}D4= literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-key.pem new file mode 100644 index 000000000..47215bd06 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-ecc-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIDOGXhoaF5CDp/zS7ulq2RPH/WnHFq2fZ0T+vCWd0+LXoAoGCCqGSM49 +AwEHoUQDQgAEld8csp4gqR2iW6tcm6hmBinmstjjFKbDwbStTUQYIB5dZ/0VHW0l +4RexccqFA/DSr0FmRjZt6kHLT8hK0KBhjA== +-----END EC PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-key.der b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-key.der new file mode 100644 index 0000000000000000000000000000000000000000..be3ed6b871ad7d086aa1a0f72f0dd866379ff24f GIT binary patch literal 1194 zcmV;b1XcSmf&``l0RRGm0RaHRqH|p#Vj#{saX6=xyW58Z99kQmOAS8C_@(y^YTP4` zB5EsGV@fD$NT}y?AEH&*O#(aO%WL9;$x)AY{oE~GBex@(ezqxS=qgUB{xWbep78JP z_>JTI^VcZddL5pvBP;Qye>74lX42(kRbRr_fR=h?C|W!rK(ceg7^{I<;2XUGokrq)QC3q7)o1p)EH7QecE{?4PgE3yksp`kpa64$x;N@n~|T&Q`R* zHhwRek}u)hi53V)QdA$}x<3)Br%Ru^r(Be<95fJwqR=g&WQ$vNdxwJ8@BDZnr^AyG z)-hx;V3vzFltgThE4sEcmhE%q;A*6uF#>^s0J1hT8e1Z}v}mZr1`m3U_zIOOFL|Q^ zovB!8wiKcNX?oF5>AA^nW1gur)gPtY+SixDPi{-ZgEPU7_;!R9TWH>}dWoIbBt<6x z`MQeX^XG>*G>kl-&E%}*4VjrLhy)!O?S4o#y-pJq)D!F7t{aO}0n}?Ow(JfAY;kLY zAp(Jc0E!PZH9Z0JNAk#UmBer50ND5S4)47P39Ze^W|`s1+#QJW9<$VZ<5kJ%r4X5* z)v)SfXg1}8SBlQ+uNq!0OwvYflJhLmn?nm~J*l{ud`FU57R@XY!l7P4`vw{n^}~Ns zTewZ?kmzGSxPa20AuT@%FVY-knd1xdjqo&^kph8%0I6sN5OwSWjKx~P=TVDVWkWjl z+uz?CFO`EHb3TuhBN5W}=CyJ5FzmzJtcpkEjXUi1N6_hY2#*V^M~xwcY60Y-ioJC= ztnd7G&BnV?8yaaehu2cE;JK1~5&v{6M4{fS)A@%m$axkTJn7`4hGC+Qw(&tg9hV5T I0fpXCe@8V=-T(jq literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-key.pem new file mode 100644 index 000000000..0b050b6b8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/ca-int-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpgIBAAKCAQEAw6JzXSFiIM46cTinlLvbhwQcWhueSw0+yvil9w1q3COQImor +WGNKKGpIqOdzH6JV2E0CO+LLa+KDyVGPd/3cLV0jtyOafrYpaOgqTqn+MnAxnvDv +7viN4/zz1yjdeh2erSMr8aZ/NFIpZtLlZFVk1t1LQTtVg27AEQ5uIMIWc+sw/wlG +u+fMxgNEQRHGwWw2L0r5kVXKWF43uCgQMIlAlnfPcGakVftpC+fZsjNl23I6d7cr +Sfy2zVgQjauqy0BFdwI5GLOPMwFId1C+jnOn3jagSY4sFq+5+0ItNWrbNDfVFFl9 +ZXLli2VVSyBeR/n4OtNs2Tr1xwFGMcN5mhi+SQIDAQABAoIBAQCwoB1pyrcOiULI +b+8U4Jpthq+WRvMeLYIwvFcS+uEsiUsbVyF1NoeAf5zEKdqNiAHbPIO0z6j66VI0 +U1elbOP5bOrO8O0OU6aFWX7A8MdYgGS8bCkjZvKsEPeRnQqAsvdMt8F39etIsJlC +hUunz1UwjDDiXxBwjnAHtjCFkNW2pt6LscUgqSPr/dYIM6H5ZdSINvUYd9v6xvYz +KQhOZSyikO2sqs/d+tTl1/Onca3HWxynhT4HCe47RQnxaCk+6qa25nrXCIHS+cNh +Ro79iBqkSsG43nYtZ14ZRsPh4jeie0myP1CzYL94fTNuc9wRXJ/dOIjZu3uCHDxt +opSopKSBAoGBAPH4m7hf4DbFtBQCXq3sQw2FqQB4WeEiOSGoZLhivAcarc6gUNZ0 +7/eVUJJJ+pW3UlDtZ5aF1yewBXTNackI/pNvHQziSf/hzRzDdsk4ei3cMnctshMk +XM6oHxw1MyR9g3YhYcAvzmDlevwYj/k2ABhnUva2yM3gD77ao0hjwIyZAoGBAM76 +Gr3ZwT3hh/CzO8GDZuzwLPahLTcBUmCEb+yfr9ELjPH++p4xOw7QZybxaHKlzla0 +wDZ+L5mSL+HciRYIR1JUH+K6PxGqp0ufu6dclLAcNBCEotAtoWSLW3Z7h4LX7/x4 +IafDkxHWMWQxYJaLN5REbJArurY0lu1z5uBqpJ0xAoGBALI2NBpbIru0aKjEBg96 +jvgKlSoveaMCnalYaLYUof9petFP6bnJbmOeqTTVH6Xc2teXwk9uS8SDM8GO+HaE +FVto3rB6iZ3YJEUnAPm6iuHz54c3NIw8n83krOUNmZkqiAQdGe1+SDW9ThMV1BPr +3a4bi1MB1GsstuwOA2xxa4MhAoGBAIoPNDU9AfRH8shwlcRv5QDY9/UO770ICa3N +yWaZ4cncHYjyHrPUfONVyeilEJmg1bDqYmg25YNXis7qrxpeLUzSRm6S8yzSm0ML +aj2puJh8R5JZFs0sEsKhXkH7BhoV9cN/Ulu4TeqQ6GM/uIDSniEtPwkv0hxlmeML +843wNJuRAoGBAKloBRB17AOMxVrB51GLWmVDOvbb398bL5WDHnM+j5QjEdL25rVx +9jDsw9ysikfkjTvs9UfQ6XUIjwurR40hhWoB5KGKvXU3rO/8ds3Gu1EbGmk0h9dS +seC5knwR/3QrRKHerNP5hzDIeRYaPOnko4Zhoo+28UFAHZcItQGF3lF/ +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-alt-ecc.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-alt-ecc.pem new file mode 100644 index 000000000..58bb755f0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-alt-ecc.pem @@ -0,0 +1,55 @@ +-----BEGIN CERTIFICATE----- +MIICxjCCAmygAwIBAgICEAUwCgYIKoZIzj0EAwIwgaMxCzAJBgNVBAYTAlVTMRMw +EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3 +b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEkMCIGA1UEAwwbd29sZlNTTCBJ +bnRlcm1lZGlhdGUgQ0EgRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE4MTIyMTE3NTQwMVoXDTI4MTIxODE3NTQwMVowgaAxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYD +VQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEhMB8GA1UEAwwYd29s +ZlNTTCBDbGllbnQgQ2hhaW4gRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVb/0D0RQmj3Om7fwxU31 +cHvU7CSOGYDsWkyiJANiLJva76I1EkOEdhbGVpUGzAGpvfZ1GkL3vamyNiJfx11/ +tKOBkDCBjTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAdBgNVHQ4EFgQU +69RLWWuVYT9RV7YETYlBiERcq/IwHwYDVR0jBBgwFoAUlx1gw4ciWZtgH4S0mRyI +Tb/aHm4wDgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEF +BQcDBDAKBggqhkjOPQQDAgNIADBFAiBe6My62YzVR/EAn/a2IjlFpCektOZbCnJ0 +wFB0KiilZQIhAKofLu9dYlzn5JMB77wMijSohui3fABOA7QX43L+ZYHf +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICkTCCAjigAwIBAgICEAMwCgYIKoZIzj0EAwIwgZcxCzAJBgNVBAYTAlVTMRMw +EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3 +b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MTIy +MTE3NTQwMVoXDTM4MTIxNjE3NTQwMVowgaMxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM +MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEkMCIGA1UEAwwbd29sZlNTTCBJbnRlcm1l +ZGlhdGUgQ0EgRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMFkw +EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEld8csp4gqR2iW6tcm6hmBinmstjjFKbD +wbStTUQYIB5dZ/0VHW0l4RexccqFA/DSr0FmRjZt6kHLT8hK0KBhjKNmMGQwHQYD +VR0OBBYEFJcdYMOHIlmbYB+EtJkciE2/2h5uMB8GA1UdIwQYMBaAFFaOmsPwQt4Y +uUVVbvmTz+rD86UhMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGG +MAoGCCqGSM49BAMCA0cAMEQCICCNvbwIilIgq7zwlAw8OJyewBhTlJR/Vz0VjnVf +jIJ5AiBAPg8nmui6m/SZz3E2aNHtMVQ36C430J5JqSd5wQM0UA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-alt.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-alt.pem new file mode 100644 index 000000000..6ace19174 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-alt.pem @@ -0,0 +1,71 @@ +-----BEGIN CERTIFICATE----- +MIIESjCCAzKgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwgZ8xCzAJBgNVBAYTAlVT +MRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQK +DAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEgMB4GA1UEAwwXd29sZlNT +TCBJbnRlcm1lZGlhdGUgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b20wHhcNMTgxMjIxMTc1NDAwWhcNMjgxMjE4MTc1NDAwWjCBnDELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNV +BAoMB3dvbGZTU0wxFDASBgNVBAsMC0RldmVsb3BtZW50MR0wGwYDVQQDDBR3b2xm +U1NMIENsaWVudCBDaGFpbjEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMMD0Sv+OaQyRTtTyIQr +Knx0mr2qKlIHR9amNrIHMo7Quml7xsNEntSBSP0taKKLZ7uhdcg2LErSG/eLus8N ++e/s8YEee5sDR5q/Zcx/ZSRppugUiVvkNPfFsBST9Wd7Onp44QFWVpGmE0KN0jxA +nEzv0YbfN1EbDKE79fGjSjXk4c6W3xt+v06X0BDoqAgwga8gC0MUxXRntDKCb42G +wohAmTaDuh5AciIX11JlJHOwzu8Zza7/eGx7wBID1E5yDVBtO6M7o5lencjZDIWz +2YrZVCbbbfqsu/8lTMTRefRx04ZAGBOwY7VyTjDEl4SGLVYv1xX3f8Cu9fxb5fuh +utMCAwEAAaOBkDCBjTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAdBgNV +HQ4EFgQUM9hFZtdohxh+VA1wJ5HHJteFZcAwHwYDVR0jBBgwFoAU72ng99Ud5pns +3G3Q9+K5XGRxgzUwDgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMC +BggrBgEFBQcDBDANBgkqhkiG9w0BAQsFAAOCAQEAiIEheKwEinl+zaW6O/5SYeic +XSiRymhyMZnVFXiZ0QP/thNZI0iekpTMkQGT3Bk2aNdIU6uZ2CP8KJhD8+uf4i/E +TLMcSDWSbVNGXcEgIQdxJaE3iRqb7PXj0RWg/hAuzWfVPW7WufU4jToSyS754anI +b9YEBWbfPDpp16prXnEN41M4PYdKHseIeByHWiG9D4b0fIa9UX2cy/KypkF6+LsI +EWdqMZ9I9tEHojaHg3NoO8kRXquj0GGa341SuYp50vNdsD0Vae6jtcK+tD8RsAbT +uLQyRZX/dkjrYwsdeQ9VldZ8htRhIPkPooKkH7EQU9joyCezvZh7CsRbgtBszw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEFzCCAv+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT +MRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhT +YXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MTIy +MTE3NTQwMFoXDTM4MTIxNjE3NTQwMFowgZ8xCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM +MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEgMB4GA1UEAwwXd29sZlNTTCBJbnRlcm1l +ZGlhdGUgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDonNdIWIgzjpxOKeUu9uHBBxaG55L +DT7K+KX3DWrcI5AiaitYY0ooakio53MfolXYTQI74str4oPJUY93/dwtXSO3I5p+ +tilo6CpOqf4ycDGe8O/u+I3j/PPXKN16HZ6tIyvxpn80Uilm0uVkVWTW3UtBO1WD +bsARDm4gwhZz6zD/CUa758zGA0RBEcbBbDYvSvmRVcpYXje4KBAwiUCWd89wZqRV ++2kL59myM2Xbcjp3tytJ/LbNWBCNq6rLQEV3AjkYs48zAUh3UL6Oc6feNqBJjiwW +r7n7Qi01ats0N9UUWX1lcuWLZVVLIF5H+fg602zZOvXHAUYxw3maGL5JAgMBAAGj +ZjBkMB0GA1UdDgQWBBTvaeD31R3mmezcbdD34rlcZHGDNTAfBgNVHSMEGDAWgBQn +jmcRdMMmHT/tM2OzpNgdMOXo1TASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB +/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAXs0wzhMGqKMlbYVov4g7aBJqXl8i +glFK/bGussI+oeRzl293H14Kpj6KIJNMP2hkaajXrj6lWOTQReR6X8xoIz17340z +jboLc92XQZkaJn8Xh8R2uzu1FSSwgk8uCsP+q3XJTVl0Gscz508URVv008OpnTSo +4Soz6hAH254zg2Dw3XwnDWuS75DMNbNO4/rKh1Ux6HuMwjUZQWp2bGx60GrRLaim +l0BzUpw8Q6dL8bcEr+DRMjys36dKFfsuVthcTJmdPPBtoCAllskk/IRM3N4dKejU +4f/KBi857STcefkqGACu0otE6yqU+8gChg1+H2XHIAZeylCvvXHLBtoS/w== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-ecc.der b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-ecc.der new file mode 100644 index 0000000000000000000000000000000000000000..b067fe290fe67213e5b538a7b3cf025e458a0905 GIT binary patch literal 1375 zcmXqLVmfBf#FVpunTe5!iAjLffQyYotIgw_EekV~LE~aWZUas>=1>+kVW!YvLtz6! z5Ql?@D?G6{BQr0(BtOqkz<>`V$j-waoSIltl9LJ(;o@O0&(BE<4)!q=F%SZ&;pX9X zNi9pw$uG!F%_}ifF;D`DGV@47)hT%9m82Hsrlw>jmZT~;J1V$3I~&Ry$g*()oz(W7 zmywfEOdvBaE#Cp8p}06lFF8NgKu(<3(8AEj$k5Q-)WpCrN}SgS$OQ^PxCV_2XzB|^ z19^xqBw)U9&dCINPr*4OF*A=iFGLy$v$2DNorw_|{>+T*%uWm}q5Hq^y9CU#JvV#% zhoin<3#zZYQR$OxcoXHbNQF5`XZEf4i%f-_Tgt?ag-vBU!?<$qw^Avm?|WBnGE<5_ z9$UXmRb&dda7u^=ZgW)B7fS0;tH7iV_e?78axkzxL~ZAzA| zOVpQac^1u8RB|AoL`!37Dw86^DtW#4u}Lw{pG;rup;4d#P*F#F2Q0g^(1k{=8HXT>8ig zgAyo*0UMBFVq`!~w2W=Y$%WaS!N7${L7{i=9*(Xch1GjLOyRMym^1HyMDUa;_2IUn ueWmd|O_fXv4tD(NvtI0){blC)LbHsEZw*7tU+9@%nCH1tz49QlNdN$@9fm6a literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-ecc.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-ecc.pem new file mode 100644 index 000000000..5138cf271 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain-ecc.pem @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIICxjCCAmygAwIBAgICEAUwCgYIKoZIzj0EAwIwgaMxCzAJBgNVBAYTAlVTMRMw +EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3 +b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEkMCIGA1UEAwwbd29sZlNTTCBJ +bnRlcm1lZGlhdGUgQ0EgRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE4MTIyMTE3NTQwMVoXDTI4MTIxODE3NTQwMVowgaAxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYD +VQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEhMB8GA1UEAwwYd29s +ZlNTTCBDbGllbnQgQ2hhaW4gRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVb/0D0RQmj3Om7fwxU31 +cHvU7CSOGYDsWkyiJANiLJva76I1EkOEdhbGVpUGzAGpvfZ1GkL3vamyNiJfx11/ +tKOBkDCBjTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAdBgNVHQ4EFgQU +69RLWWuVYT9RV7YETYlBiERcq/IwHwYDVR0jBBgwFoAUlx1gw4ciWZtgH4S0mRyI +Tb/aHm4wDgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEF +BQcDBDAKBggqhkjOPQQDAgNIADBFAiBe6My62YzVR/EAn/a2IjlFpCektOZbCnJ0 +wFB0KiilZQIhAKofLu9dYlzn5JMB77wMijSohui3fABOA7QX43L+ZYHf +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICkTCCAjigAwIBAgICEAMwCgYIKoZIzj0EAwIwgZcxCzAJBgNVBAYTAlVTMRMw +EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3 +b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MTIy +MTE3NTQwMVoXDTM4MTIxNjE3NTQwMVowgaMxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM +MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEkMCIGA1UEAwwbd29sZlNTTCBJbnRlcm1l +ZGlhdGUgQ0EgRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMFkw +EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEld8csp4gqR2iW6tcm6hmBinmstjjFKbD +wbStTUQYIB5dZ/0VHW0l4RexccqFA/DSr0FmRjZt6kHLT8hK0KBhjKNmMGQwHQYD +VR0OBBYEFJcdYMOHIlmbYB+EtJkciE2/2h5uMB8GA1UdIwQYMBaAFFaOmsPwQt4Y +uUVVbvmTz+rD86UhMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGG +MAoGCCqGSM49BAMCA0cAMEQCICCNvbwIilIgq7zwlAw8OJyewBhTlJR/Vz0VjnVf +jIJ5AiBAPg8nmui6m/SZz3E2aNHtMVQ36C430J5JqSd5wQM0UA== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain.der b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain.der new file mode 100644 index 0000000000000000000000000000000000000000..0097d2b2ca424f9a709f04a5b5e0e50807a6c6dd GIT binary patch literal 2153 zcmXqLV(~I)Vm4a9%*4pV#3aCEz{|#|)#lOmotKf3o0Y+!alRq90Vf-CC<~h~Q)sZE zuz?_m!@-ibnU`LYpJymwzy}g!=V1>{O)M$NNrj1U@vxWY=cEM(`xuHC2!Yga z^KiSQmZj$87v!eql^7}*$bm$edBmaW6g=}vQj2m^Q!*1vQWcyX4do4F;V$B26cfnI zOUrivDK0L~(M!(HHINhMHMB4^GBPwYH#IRZh!W>D0&;;u5UxSv9Gdz-)<7EK0}+@H zoO3dPUQ=++NX*P5?EEH1CFC$?WMyD(V&rEqXkz4IYGPz$ILv%e`=8|!BUkI-6D`_W zH6^q5uF?u(cfYpGY!kat--TV7)yEFI%)8R)@mDuvQFr?8g{3FVbi6J}fA8LPp7-bb zHy<12s%JC1&)T1Qrao0AbJ+`#&gds5-;Zt(nfx`q+N!GJA!AtB#AU)xy_akp=J>q7 z*mmDMP?~3<_1BM!y-c4xJU8vWblrZx=@$fEtl%(cT(7|GEON9YeTz|3es9~M4u_d$ z&Aa3rij>5!2c@bMZ#ef}^6a|*6*<)hgqW}R74Zh-S}(R?aiyxis>A-o}ZYmuM9k?AdMx?%d)MZeb{Soif$^wZx9cU@*;W@KPo z+&ICYu@{^UWrbOo3>bi^kTappgR$+06C)!F3o{ez0$@5}4wdC&5n~ZCzTuj7J)>Qs zE`+y0ed2Mo>#eB=4CF!5$}AEFVhtkiGar1vD*J5an>)D|zCYR-lTz4h3Qoha{EUqM z!R9@Hn5W7jW+1}Gq0Pp~%F52n1ZS}zM;b7r03(f&p`%f;Vhu}IW!>4OyR82OCBB#w zt1vntD+S%FEan%CLF2kF>lh8GZPsn-;p%Sxb6|Wdgcw~KN>TfKfj*;NdJh> zW*HCDNx8vpu?H0t*$Y({ns-Xge)IM5MbQQS1oY0PU$xD;;y zzs%!xGPi6cf9TX}HEmZC6@KzBYFZ+{Q6TunixcXb_s*#1IuhMdmzV1yl@NsUAZ8I_3@Sp*;6=!wF9ZpeB8!S+ z6_XUsSru9=pR)UQJBv(|^gM4~yHh`we&@})qdY+=OFJUjOC!r;#q(nMMWHu*nXDh3 z&VJNb7ZSywLJn`Om1paNdXa?|$??{`2{|#@#B}d25xmKQ5~` z3DQiv^fV4GJP)nx788YgdFazobO>5Hr2T1-|LR7!9dumLG1 zMh4W9gRu=Q)q{(MxU&Z5gxOXsR?ThA*xzBDA(RytuhbOi^>^dCO^56jJ}I7_UoIcV zwal(dVX}{XMoQ+2>+9^6Mm)LT`lKrUOop;;_5EJs-d)_qcc(kflv1k~Z$DDD+j^_0 z%7!L?J+8z5R+paijVzHmZv5O|#5MZM<-;rInyh%JW&BEj{q{WL=7bM-Yt(tOC%vC= z#&oma<6o!RLk(Y4_Z%{nbj&Kt$*H=Kby0W4vgr=RL33=JmwSKQ&a(c&MI)Ov_m_K# z{?-e-5#uv+uFZ$s1q!OuPOAKA@wszPR`bP`hyPEp>07>4xl{R5OM+qDrEZtkT2p?X aU~1#7lTSUaz!rBZVEx|0(`>hd{sRE-^#pPN literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain.pem new file mode 100644 index 000000000..9404a453e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-chain.pem @@ -0,0 +1,49 @@ +-----BEGIN CERTIFICATE----- +MIIESjCCAzKgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwgZ8xCzAJBgNVBAYTAlVT +MRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQK +DAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEgMB4GA1UEAwwXd29sZlNT +TCBJbnRlcm1lZGlhdGUgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b20wHhcNMTgxMjIxMTc1NDAwWhcNMjgxMjE4MTc1NDAwWjCBnDELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNV +BAoMB3dvbGZTU0wxFDASBgNVBAsMC0RldmVsb3BtZW50MR0wGwYDVQQDDBR3b2xm +U1NMIENsaWVudCBDaGFpbjEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMMD0Sv+OaQyRTtTyIQr +Knx0mr2qKlIHR9amNrIHMo7Quml7xsNEntSBSP0taKKLZ7uhdcg2LErSG/eLus8N ++e/s8YEee5sDR5q/Zcx/ZSRppugUiVvkNPfFsBST9Wd7Onp44QFWVpGmE0KN0jxA +nEzv0YbfN1EbDKE79fGjSjXk4c6W3xt+v06X0BDoqAgwga8gC0MUxXRntDKCb42G +wohAmTaDuh5AciIX11JlJHOwzu8Zza7/eGx7wBID1E5yDVBtO6M7o5lencjZDIWz +2YrZVCbbbfqsu/8lTMTRefRx04ZAGBOwY7VyTjDEl4SGLVYv1xX3f8Cu9fxb5fuh +utMCAwEAAaOBkDCBjTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAdBgNV +HQ4EFgQUM9hFZtdohxh+VA1wJ5HHJteFZcAwHwYDVR0jBBgwFoAU72ng99Ud5pns +3G3Q9+K5XGRxgzUwDgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMC +BggrBgEFBQcDBDANBgkqhkiG9w0BAQsFAAOCAQEAiIEheKwEinl+zaW6O/5SYeic +XSiRymhyMZnVFXiZ0QP/thNZI0iekpTMkQGT3Bk2aNdIU6uZ2CP8KJhD8+uf4i/E +TLMcSDWSbVNGXcEgIQdxJaE3iRqb7PXj0RWg/hAuzWfVPW7WufU4jToSyS754anI +b9YEBWbfPDpp16prXnEN41M4PYdKHseIeByHWiG9D4b0fIa9UX2cy/KypkF6+LsI +EWdqMZ9I9tEHojaHg3NoO8kRXquj0GGa341SuYp50vNdsD0Vae6jtcK+tD8RsAbT +uLQyRZX/dkjrYwsdeQ9VldZ8htRhIPkPooKkH7EQU9joyCezvZh7CsRbgtBszw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEFzCCAv+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT +MRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhT +YXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MTIy +MTE3NTQwMFoXDTM4MTIxNjE3NTQwMFowgZ8xCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM +MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEgMB4GA1UEAwwXd29sZlNTTCBJbnRlcm1l +ZGlhdGUgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDonNdIWIgzjpxOKeUu9uHBBxaG55L +DT7K+KX3DWrcI5AiaitYY0ooakio53MfolXYTQI74str4oPJUY93/dwtXSO3I5p+ +tilo6CpOqf4ycDGe8O/u+I3j/PPXKN16HZ6tIyvxpn80Uilm0uVkVWTW3UtBO1WD +bsARDm4gwhZz6zD/CUa758zGA0RBEcbBbDYvSvmRVcpYXje4KBAwiUCWd89wZqRV ++2kL59myM2Xbcjp3tytJ/LbNWBCNq6rLQEV3AjkYs48zAUh3UL6Oc6feNqBJjiwW +r7n7Qi01ats0N9UUWX1lcuWLZVVLIF5H+fg602zZOvXHAUYxw3maGL5JAgMBAAGj +ZjBkMB0GA1UdDgQWBBTvaeD31R3mmezcbdD34rlcZHGDNTAfBgNVHSMEGDAWgBQn +jmcRdMMmHT/tM2OzpNgdMOXo1TASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB +/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAXs0wzhMGqKMlbYVov4g7aBJqXl8i +glFK/bGussI+oeRzl293H14Kpj6KIJNMP2hkaajXrj6lWOTQReR6X8xoIz17340z +jboLc92XQZkaJn8Xh8R2uzu1FSSwgk8uCsP+q3XJTVl0Gscz508URVv008OpnTSo +4Soz6hAH254zg2Dw3XwnDWuS75DMNbNO4/rKh1Ux6HuMwjUZQWp2bGx60GrRLaim +l0BzUpw8Q6dL8bcEr+DRMjys36dKFfsuVthcTJmdPPBtoCAllskk/IRM3N4dKejU +4f/KBi857STcefkqGACu0otE6yqU+8gChg1+H2XHIAZeylCvvXHLBtoS/w== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-int-cert.der b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/client-int-cert.der new file mode 100644 index 0000000000000000000000000000000000000000..e61086695d9a0913bd6993d349190f07ab4fab77 GIT binary patch literal 1102 zcmXqLV(~I)Vm4a9%*4pV#3aCEz{|#|)#lOmotKf3o0Y+!alRq90Vf-CC<~h~Q)sZE zuz?_m!@-ibnU`LYpJymwzy}g!=V1>{O)M$NNrj1U@vxWY=cEM(`xuHC2!Yga z^KiSQmZj$87v!eql^7}*$bm$edBmaW6g=}vQj2m^Q!*1vQWcyX4do4F;V$B26cfnI zOUrivDK0L~(M!(HHINhMHMB4^GBPwYH#IRZh!W>D0&;;u5UxSv9Gdz-)<7EK0}+@H zoO3dPUQ=++NX*P5?EEH1CFC$?WMyD(V&rEqXkz4IYGPz$ILv%e`=8|!BUkI-6D`_W zH6^q5uF?u(cfYpGY!kat--TV7)yEFI%)8R)@mDuvQFr?8g{3FVbi6J}fA8LPp7-bb zHy<12s%JC1&)T1Qrao0AbJ+`#&gds5-;Zt(nfx`q+N!GJA!AtB#AU)xy_akp=J>q7 z*mmDMP?~3<_1BM!y-c4xJU8vWblrZx=@$fEtl%(cT(7|GEON9YeTz|3es9~M4u_d$ z&Aa3rij>5!2c@bMZ#ef}^6a|*6*<)hgqW}R74Zh-S}(R?aiyxis>A-o}ZYmuM9k?AdMx?%d)MZeb{Soif$^wZx9cU@*;W@KPo z+&ICYu@{^UWrbOo3>bi^kTappgR$+06C)!F3o{ez0$@5}4wdC&5n~ZCzTuj7J)>Qs zE`+y0ed2Mo>#eB=4CF!5$}AEFVhtkiGar1vD*J5an>)D|zCYR-lTz4h3Qoha{EUqM z!R9@Hn5W7jW+1}Gq0Pp~%F52n1ZS}zM;b7r03(f&p`%f;Vhu}IW!>4OyR82OCBB#w zt1vntD+S%FEan%CLF2kF>lh8GZPsn-;p%Sxb6|Wdgcw~KN>TfKfj*;NdJh> zW*HCDNx8vpu?H0t*$Y({ns-Xge)IM5MbQQS1oY0PU$xD;;y vzs%!xGPi6cf9TX}HEmZC6@KzBYFZ+{Q6TunixcXb_s*#1IuhM=1>+kVW!YvLtz6! z5Ql?@D?G6{BQr0(BtOqkz<>`V$j-waoSIltl9LJ(;o@O0&(BE<4)!q=F%SZ&;pX9X zNi9pw$uG!F%_}ifF;D`DGV@47)hT%9m82Hsrlw>jmZT~;J1V$3I~&Ry$g*()oz(W7 zmywfEOdvBaE#Cp8p}06lFF8NgKu(<3(8AEj$k5Q-)WpCrN}SgS$OQ^PxCV_2XzB|^ z19^xqBw)U9&dCINPr*4OF*A=iFGLy$v$2DNorw_|{>+T*%uWm}q5Hq^y9CU#JvV#% zhoin<3#zZYQR$OxcoXHbNQF5`XZEf4i%f-_Tgt?ag-vBU!?<$qw^Avm?|WBnGE<5_ z9$UXmRb&dda7u^=ZgW)B7fS0;tH7iV_e?78axkzxL~ZAzA| zOVpQac^1u8RB|AoL`!37Dw86^DtW#4u}Lw{pG; "$1" + echo "[ ca ]" >> "$1" + echo "default_ca = CA_default" >> "$1" + echo "" >> "$1" + echo "[ CA_default ]" >> "$1" + echo "certs = $dir/certs/intermediate" >> "$1" + echo "new_certs_dir = $dir/certs/intermediate/new_certs">> "$1" + echo "database = $dir/certs/intermediate/index.txt">> "$1" + echo "serial = $dir/certs/intermediate/serial" >> "$1" + echo "RANDFILE = $dir/private/.rand" >> "$1" + echo "" >> "$1" + echo "private_key = $dir/$2" >> "$1" + echo "certificate = $dir/$3" >> "$1" + echo "" >> "$1" + echo "crlnumber = $dir/certs/intermediate/crlnumber">> "$1" + echo "crl_extensions = crl_ext" >> "$1" + echo "default_crl_days = 1000" >> "$1" + echo "default_md = sha256" >> "$1" + echo "" >> "$1" + echo "name_opt = ca_default" >> "$1" + echo "cert_opt = ca_default" >> "$1" + echo "default_days = 3650" >> "$1" + echo "preserve = no" >> "$1" + echo "policy = policy_loose" >> "$1" + echo "" >> "$1" + echo "[ policy_strict ]" >> "$1" + echo "countryName = match" >> "$1" + echo "stateOrProvinceName = match" >> "$1" + echo "organizationName = match" >> "$1" + echo "organizationalUnitName = optional" >> "$1" + echo "commonName = supplied" >> "$1" + echo "emailAddress = optional" >> "$1" + echo "" >> "$1" + echo "[ policy_loose ]" >> "$1" + echo "countryName = optional" >> "$1" + echo "stateOrProvinceName = optional" >> "$1" + echo "localityName = optional" >> "$1" + echo "organizationName = optional" >> "$1" + echo "organizationalUnitName = optional" >> "$1" + echo "commonName = supplied" >> "$1" + echo "emailAddress = optional" >> "$1" + echo "" >> "$1" + echo "[ req ]" >> "$1" + echo "default_bits = 2048" >> "$1" + echo "distinguished_name = req_distinguished_name" >> "$1" + echo "string_mask = utf8only" >> "$1" + echo "default_md = sha256" >> "$1" + echo "x509_extensions = v3_ca" >> "$1" + echo "" >> "$1" + echo "[ req_distinguished_name ]" >> "$1" + echo "countryName = US" >> "$1" + echo "stateOrProvinceName = Washington" >> "$1" + echo "localityName = Seattle" >> "$1" + echo "organizationName = wolfSSL" >> "$1" + echo "organizationalUnitName = Development" >> "$1" + echo "commonName = www.wolfssl.com" >> "$1" + echo "emailAddress = info@wolfssl.com" >> "$1" + echo "" >> "$1" + echo "[ v3_ca ]" >> "$1" + echo "subjectKeyIdentifier = hash" >> "$1" + echo "authorityKeyIdentifier = keyid:always,issuer" >> "$1" + echo "basicConstraints = critical, CA:true" >> "$1" + echo "keyUsage = critical, digitalSignature, cRLSign, keyCertSign">> "$1" + echo "" >> "$1" + echo "[ v3_intermediate_ca ]" >> "$1" + echo "subjectKeyIdentifier = hash" >> "$1" + echo "authorityKeyIdentifier = keyid:always,issuer" >> "$1" + echo "basicConstraints = critical, CA:true, pathlen:0" >> "$1" + echo "keyUsage = critical, digitalSignature, cRLSign, keyCertSign">> "$1" + echo "" >> "$1" + echo "[ usr_cert ]" >> "$1" + echo "basicConstraints = CA:FALSE" >> "$1" + echo "nsCertType = client, email" >> "$1" + echo "subjectKeyIdentifier = hash" >> "$1" + echo "authorityKeyIdentifier = keyid,issuer" >> "$1" + echo "keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment">> "$1" + echo "extendedKeyUsage = clientAuth, emailProtection" >> "$1" + echo "" >> "$1" + echo "[ server_cert ]" >> "$1" + echo "basicConstraints = CA:FALSE" >> "$1" + echo "nsCertType = server" >> "$1" + echo "subjectKeyIdentifier = hash" >> "$1" + echo "authorityKeyIdentifier = keyid,issuer:always" >> "$1" + echo "keyUsage = critical, digitalSignature, keyEncipherment, keyAgreement">> "$1" + echo "extendedKeyUsage = serverAuth" >> "$1" + echo "" >> "$1" + echo "[ crl_ext ]" >> "$1" + echo "authorityKeyIdentifier=keyid:always" >> "$1" +} + +# Args: 1=reqcnf, 2=signcnf, 3=keyfile, 4=certfile, 5=ext, 6=subj, 7=days +create_cert() { + openssl req -config ./certs/intermediate/$1.cnf -new -sha256 \ + -key $3 \ + -out ./certs/intermediate/tmp.csr \ + -subj "/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Development/CN=$6/emailAddress=info@wolfssl.com" + check_result $? + openssl ca -config ./certs/intermediate/$2.cnf -extensions $5 -days $7 -notext -md sha256 \ + -in ./certs/intermediate/tmp.csr -out ./certs/intermediate/$4.pem -batch + check_result $? + rm ./certs/intermediate/tmp.csr + + # Convert Cert to DER + openssl x509 -in ./certs/intermediate/$4.pem -inform PEM -out ./certs/intermediate/$4.der -outform DER + check_result $? + + # Add text to cert PEM file + openssl x509 -in ./certs/intermediate/$4.pem -text > ./certs/intermediate/tmp.pem + check_result $? + mv ./certs/intermediate/tmp.pem ./certs/intermediate/$4.pem +} + +if [ "$1" == "clean" ]; then + echo "Cleaning temp files" + cleanup_files +fi +if [ "$1" == "cleanall" ]; then + echo "Cleaning all files" + rm -f ./certs/intermediate/*.pem + rm -f ./certs/intermediate/*.der + rm -f ./certs/intermediate/*.csr + cleanup_files +fi + +# Make sure required CA files exist and are populated +rm -f ./certs/intermediate/index.* +touch ./certs/intermediate/index.txt +if [ ! -f ./certs/intermediate/serial ]; then + echo 1000 > ./certs/intermediate/serial +fi +if [ ! -f ./certs/intermediate/crlnumber ]; then + echo 2000 > ./certs/intermediate/crlnumber +fi +if [ ! -d ./certs/intermediate/new_certs ]; then + mkdir ./certs/intermediate/new_certs +fi + + +# RSA +echo "Creating RSA CA configuration cnf files" +create_ca_config ./certs/intermediate/wolfssl_root.cnf certs/ca-key.pem certs/ca-cert.pem +create_ca_config ./certs/intermediate/wolfssl_int.cnf certs/intermediate/ca-int-key.pem certs/intermediate/ca-int-cert.pem + +if [ ! -f ./certs/intermediate/ca-int-key.pem ]; then + echo "Make Intermediate RSA CA Key" + openssl genrsa -out ./certs/intermediate/ca-int-key.pem 2048 + check_result $? + openssl rsa -in ./certs/intermediate/ca-int-key.pem -inform PEM -out ./certs/intermediate/ca-int-key.der -outform DER + check_result $? +fi + +echo "Create RSA Intermediate CA signed by root" +create_cert wolfssl_int wolfssl_root ./certs/intermediate/ca-int-key.pem ca-int-cert v3_intermediate_ca "wolfSSL Intermediate CA" 7300 + +echo "Create RSA Server Certificate signed by intermediate" +create_cert wolfssl_int wolfssl_int ./certs/server-key.pem server-int-cert server_cert "wolfSSL Server Chain" 3650 + +echo "Create RSA Client Certificate signed by intermediate" +create_cert wolfssl_int wolfssl_int ./certs/client-key.pem client-int-cert usr_cert "wolfSSL Client Chain" 3650 + +echo "Generate CRLs for new certificates" +openssl ca -config ./certs/intermediate/wolfssl_root.cnf -gencrl -crldays 1000 -out ./certs/crl/ca-int.pem -keyfile ./certs/intermediate/ca-int-key.pem -cert ./certs/intermediate/ca-int-cert.pem +check_result $? +openssl ca -config ./certs/intermediate/wolfssl_int.cnf -gencrl -crldays 1000 -out ./certs/crl/server-int.pem -keyfile ./certs/server-key.pem -cert ./certs/intermediate/server-int-cert.pem +check_result $? +openssl ca -config ./certs/intermediate/wolfssl_int.cnf -gencrl -crldays 1000 -out ./certs/crl/client-int.pem -keyfile ./certs/client-key.pem -cert ./certs/intermediate/client-int-cert.pem +check_result $? + +echo "Assemble test chains - peer first, then intermediate" +openssl x509 -in ./certs/intermediate/server-int-cert.pem > ./certs/intermediate/server-chain.pem +openssl x509 -in ./certs/intermediate/ca-int-cert.pem >> ./certs/intermediate/server-chain.pem +cat ./certs/intermediate/server-int-cert.der ./certs/intermediate/ca-int-cert.der > ./certs/intermediate/server-chain.der + +openssl x509 -in ./certs/intermediate/client-int-cert.pem > ./certs/intermediate/client-chain.pem +openssl x509 -in ./certs/intermediate/ca-int-cert.pem >> ./certs/intermediate/client-chain.pem +cat ./certs/intermediate/client-int-cert.der ./certs/intermediate/ca-int-cert.der > ./certs/intermediate/client-chain.der + +echo "Assemble cert chain with extra cert for testing alternate chains" +cp ./certs/intermediate/server-chain.pem ./certs/intermediate/server-chain-alt.pem +cp ./certs/intermediate/client-chain.pem ./certs/intermediate/client-chain-alt.pem +openssl x509 -in ./certs/external/ca-google-root.pem >> ./certs/intermediate/server-chain-alt.pem +openssl x509 -in ./certs/external/ca-google-root.pem >> ./certs/intermediate/client-chain-alt.pem + + +# ECC +echo "Creating ECC CA configuration cnf files" +create_ca_config ./certs/intermediate/wolfssl_root_ecc.cnf certs/ca-ecc-key.pem certs/ca-ecc-cert.pem +create_ca_config ./certs/intermediate/wolfssl_int_ecc.cnf certs/intermediate/ca-int-ecc-key.pem certs/intermediate/ca-int-ecc-cert.pem + +if [ ! -f ./certs/intermediate/ca-int-ecc-key.pem ]; then + echo "Make Intermediate ECC CA Key" + openssl ecparam -name prime256v1 -genkey -noout -out ./certs/intermediate/ca-int-ecc-key.pem + check_result $? + openssl ec -in ./certs/intermediate/ca-int-ecc-key.pem -inform PEM -out ./certs/intermediate/ca-int-ecc-key.der -outform DER + check_result $? +fi + +echo "Create ECC Intermediate CA signed by root" +create_cert wolfssl_int_ecc wolfssl_root_ecc ./certs/intermediate/ca-int-ecc-key.pem ca-int-ecc-cert v3_intermediate_ca "wolfSSL Intermediate CA ECC" 7300 + +echo "Create ECC Server Certificate signed by intermediate" +create_cert wolfssl_int_ecc wolfssl_int_ecc ./certs/ecc-key.pem server-int-ecc-cert server_cert "wolfSSL Server Chain ECC" 3650 + +echo "Create ECC Client Certificate signed by intermediate" +create_cert wolfssl_int_ecc wolfssl_int_ecc ./certs/ecc-client-key.pem client-int-ecc-cert usr_cert "wolfSSL Client Chain ECC" 3650 + +echo "Generate CRLs for new certificates" +openssl ca -config ./certs/intermediate/wolfssl_root_ecc.cnf -gencrl -crldays 1000 -out ./certs/crl/ca-int-ecc.pem -keyfile ./certs/intermediate/ca-int-ecc-key.pem -cert ./certs/intermediate/ca-int-ecc-cert.pem +check_result $? +openssl ca -config ./certs/intermediate/wolfssl_int_ecc.cnf -gencrl -crldays 1000 -out ./certs/crl/server-int-ecc.pem -keyfile ./certs/ecc-key.pem -cert ./certs/intermediate/server-int-ecc-cert.pem +check_result $? +openssl ca -config ./certs/intermediate/wolfssl_int_ecc.cnf -gencrl -crldays 1000 -out ./certs/crl/client-int-ecc.pem -keyfile ./certs/ecc-client-key.pem -cert ./certs/intermediate/client-int-ecc-cert.pem +check_result $? + +echo "Assemble test chains - peer first, then intermediate" +openssl x509 -in ./certs/intermediate/server-int-ecc-cert.pem > ./certs/intermediate/server-chain-ecc.pem +openssl x509 -in ./certs/intermediate/ca-int-ecc-cert.pem >> ./certs/intermediate/server-chain-ecc.pem +cat ./certs/intermediate/server-int-ecc-cert.der ./certs/intermediate/ca-int-ecc-cert.der > ./certs/intermediate/server-chain-ecc.der + +openssl x509 -in ./certs/intermediate/client-int-ecc-cert.pem > ./certs/intermediate/client-chain-ecc.pem +openssl x509 -in ./certs/intermediate/ca-int-ecc-cert.pem >> ./certs/intermediate/client-chain-ecc.pem +cat ./certs/intermediate/client-int-ecc-cert.der ./certs/intermediate/ca-int-ecc-cert.der > ./certs/intermediate/client-chain-ecc.der + +echo "Assemble cert chain with extra untrusted cert for testing alternate chains" +cp ./certs/intermediate/server-chain-ecc.pem ./certs/intermediate/server-chain-alt-ecc.pem +cp ./certs/intermediate/client-chain-ecc.pem ./certs/intermediate/client-chain-alt-ecc.pem +openssl x509 -in ./certs/external/ca-google-root.pem >> ./certs/intermediate/server-chain-alt-ecc.pem +openssl x509 -in ./certs/external/ca-google-root.pem >> ./certs/intermediate/client-chain-alt-ecc.pem diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/include.am b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/include.am new file mode 100644 index 000000000..183f96c33 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/include.am @@ -0,0 +1,34 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + certs/intermediate/genintcerts.sh \ + certs/intermediate/ca-int-cert.der \ + certs/intermediate/ca-int-cert.pem \ + certs/intermediate/ca-int-ecc-cert.der \ + certs/intermediate/ca-int-ecc-cert.pem \ + certs/intermediate/ca-int-ecc-key.der \ + certs/intermediate/ca-int-ecc-key.pem \ + certs/intermediate/ca-int-key.der \ + certs/intermediate/ca-int-key.pem \ + certs/intermediate/client-chain-alt-ecc.pem \ + certs/intermediate/client-chain-alt.pem \ + certs/intermediate/client-chain-ecc.der \ + certs/intermediate/client-chain-ecc.pem \ + certs/intermediate/client-chain.der \ + certs/intermediate/client-chain.pem \ + certs/intermediate/client-int-cert.der \ + certs/intermediate/client-int-cert.pem \ + certs/intermediate/client-int-ecc-cert.der \ + certs/intermediate/client-int-ecc-cert.pem \ + certs/intermediate/server-chain-alt-ecc.pem \ + certs/intermediate/server-chain-alt.pem \ + certs/intermediate/server-chain-ecc.der \ + certs/intermediate/server-chain-ecc.pem \ + certs/intermediate/server-chain.der \ + certs/intermediate/server-chain.pem \ + certs/intermediate/server-int-cert.der \ + certs/intermediate/server-int-cert.pem \ + certs/intermediate/server-int-ecc-cert.der \ + certs/intermediate/server-int-ecc-cert.pem diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain-alt-ecc.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain-alt-ecc.pem new file mode 100644 index 000000000..6655c17f3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain-alt-ecc.pem @@ -0,0 +1,59 @@ +-----BEGIN CERTIFICATE----- +MIIDZDCCAwugAwIBAgICEAQwCgYIKoZIzj0EAwIwgaMxCzAJBgNVBAYTAlVTMRMw +EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3 +b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEkMCIGA1UEAwwbd29sZlNTTCBJ +bnRlcm1lZGlhdGUgQ0EgRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE4MTIyMTE3NTQwMVoXDTI4MTIxODE3NTQwMVowgaAxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYD +VQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEhMB8GA1UEAwwYd29s +ZlNTTCBTZXJ2ZXIgQ2hhaW4gRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuzOsTCdQSsZKpQTDPN6f +NttyLc6U6iv6yyAJOSwW6GEC6a9N0wKTmjFbl5Ihf/DPGNqREQI0huggWDMLgDSJ +2KOCAS4wggEqMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMB0GA1UdDgQW +BBRdXSbvrH42+Zt2FStKJQIj77KJMDCBxQYDVR0jBIG9MIG6gBSXHWDDhyJZm2Af +hLSZHIhNv9oebqGBnaSBmjCBlzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hp +bmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZTU0wxFDASBgNV +BAsMC0RldmVsb3BtZW50MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkq +hkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CAhADMA4GA1UdDwEB/wQEAwIDqDAT +BgNVHSUEDDAKBggrBgEFBQcDATAKBggqhkjOPQQDAgNHADBEAiB0XGkL2vHYzyG8 +gayx5cWzOHL5nPFQLTEmSVjD3svlfQIgeJ0/W+ISuxstPSXbK6j0dgKQeySoHUmW +RVZXi7tZVPo= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICkTCCAjigAwIBAgICEAMwCgYIKoZIzj0EAwIwgZcxCzAJBgNVBAYTAlVTMRMw +EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3 +b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MTIy +MTE3NTQwMVoXDTM4MTIxNjE3NTQwMVowgaMxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM +MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEkMCIGA1UEAwwbd29sZlNTTCBJbnRlcm1l +ZGlhdGUgQ0EgRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMFkw +EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEld8csp4gqR2iW6tcm6hmBinmstjjFKbD +wbStTUQYIB5dZ/0VHW0l4RexccqFA/DSr0FmRjZt6kHLT8hK0KBhjKNmMGQwHQYD +VR0OBBYEFJcdYMOHIlmbYB+EtJkciE2/2h5uMB8GA1UdIwQYMBaAFFaOmsPwQt4Y +uUVVbvmTz+rD86UhMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGG +MAoGCCqGSM49BAMCA0cAMEQCICCNvbwIilIgq7zwlAw8OJyewBhTlJR/Vz0VjnVf +jIJ5AiBAPg8nmui6m/SZz3E2aNHtMVQ36C430J5JqSd5wQM0UA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain-alt.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain-alt.pem new file mode 100644 index 000000000..73118091b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain-alt.pem @@ -0,0 +1,75 @@ +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgZ8xCzAJBgNVBAYTAlVT +MRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQK +DAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEgMB4GA1UEAwwXd29sZlNT +TCBJbnRlcm1lZGlhdGUgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b20wHhcNMTgxMjIxMTc1NDAwWhcNMjgxMjE4MTc1NDAwWjCBnDELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNV +BAoMB3dvbGZTU0wxFDASBgNVBAsMC0RldmVsb3BtZW50MR0wGwYDVQQDDBR3b2xm +U1NMIFNlcnZlciBDaGFpbjEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEn +AWXGRa7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX +/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBj +xfZ/C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9 +ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIj +laF3uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBP +rdcCAwEAAaOCASswggEnMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMB0G +A1UdDgQWBBSzETLJkpiE4sn40DtuA0LKHw6OPDCBwgYDVR0jBIG6MIG3gBTvaeD3 +1R3mmezcbdD34rlcZHGDNaGBmqSBlzCBlDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM +B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMw +EQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAd +BgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CAhAAMA4GA1UdDwEB/wQEAwID +qDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAQEAPbWNZn6F +oIfMU6THyWNr1MREx0XQce8vWJJgfcg37WTqsasAG1b+93d4dv1kY314/9SuWBvw +FOnnvUvsNm80y5GwQyVmi8BZ0ertJQ1ccoop3orId1G51cTlJlAMvdeh6/qT7D02 +j8/utmtcqE8bccZNLK/S2iDIifP824TCqfaXYqyqp2v7OyFRhXpzVTSCm/iZy5aJ +otM5X7MNX46eRkpVV6veEc+AHyXJ7G9I/c5b0gUHa078DRCgioL75Hc6J+AODPtD +ZF+QjiYSlNuXGOwZlBtWXLm7JpscFVwH39EtnUGWwCpaSp5fnmaajGz/bMqhfbYS +o9QzCwAeul09eg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEFzCCAv+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT +MRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhT +YXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZz +c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MTIy +MTE3NTQwMFoXDTM4MTIxNjE3NTQwMFowgZ8xCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM +MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEgMB4GA1UEAwwXd29sZlNTTCBJbnRlcm1l +ZGlhdGUgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDonNdIWIgzjpxOKeUu9uHBBxaG55L +DT7K+KX3DWrcI5AiaitYY0ooakio53MfolXYTQI74str4oPJUY93/dwtXSO3I5p+ +tilo6CpOqf4ycDGe8O/u+I3j/PPXKN16HZ6tIyvxpn80Uilm0uVkVWTW3UtBO1WD +bsARDm4gwhZz6zD/CUa758zGA0RBEcbBbDYvSvmRVcpYXje4KBAwiUCWd89wZqRV ++2kL59myM2Xbcjp3tytJ/LbNWBCNq6rLQEV3AjkYs48zAUh3UL6Oc6feNqBJjiwW +r7n7Qi01ats0N9UUWX1lcuWLZVVLIF5H+fg602zZOvXHAUYxw3maGL5JAgMBAAGj +ZjBkMB0GA1UdDgQWBBTvaeD31R3mmezcbdD34rlcZHGDNTAfBgNVHSMEGDAWgBQn +jmcRdMMmHT/tM2OzpNgdMOXo1TASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB +/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAXs0wzhMGqKMlbYVov4g7aBJqXl8i +glFK/bGussI+oeRzl293H14Kpj6KIJNMP2hkaajXrj6lWOTQReR6X8xoIz17340z +jboLc92XQZkaJn8Xh8R2uzu1FSSwgk8uCsP+q3XJTVl0Gscz508URVv008OpnTSo +4Soz6hAH254zg2Dw3XwnDWuS75DMNbNO4/rKh1Ux6HuMwjUZQWp2bGx60GrRLaim +l0BzUpw8Q6dL8bcEr+DRMjys36dKFfsuVthcTJmdPPBtoCAllskk/IRM3N4dKejU +4f/KBi857STcefkqGACu0otE6yqU+8gChg1+H2XHIAZeylCvvXHLBtoS/w== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain-ecc.der b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-chain-ecc.der new file mode 100644 index 0000000000000000000000000000000000000000..2e1c7742d58e0ac50fa5d5faae35f634498662bc GIT binary patch literal 1533 zcmXqLVoot=V&-1J%*4pV#3aCCz{SR))#h=|mW7$gpmDJww*e;`b0`a&FjHu-p|F7< zh{M6d6`oj}k(rlXlAmWNV890wWanWIPE9N+$w`HYaPhF0=jWsa2m2U`7zlyXaPx4x zq?V=TJ&WlN>Yn*Q&Tb%OHvh_9Ti-ioekv;WZ5`@PHOwk z%gD(nCXktzmhS-4P+Xj&mzcEVK#Pfuro12!=IUvo!N)_*uJaciO=lS$hPg$QHr z29wSki<=nr44N3Vz|klx%)(^A0E|S=gf|OaABz}^NNlXy z`!#iDKWCSTYI~_NDZk&;X<*QJ6eO?A(zw^4aaV)LblHT%?Mjie6XaXA%#`Wy-G56i zZ(-xyC5^KT8mH4Vuq6z{Ac4(aUS6(;lnMwYlO`qsW^hWC+ z14{MUY>cd|?97bFIe^)n!N7${p(G}g`_{)B=N0!fuG#qX=w^$epL0G2=o+edMjXC( z`e`kbLd9JB=tn}krFCspZ)>mkQpPl)T4jZ-=QP)_@b2A_A-@com?i?T1uUO2Bik}~ z0}V^wG6v->GkD$_5+wxg>^1ei%%*t?D`gi&ua23$B8^S+*`^zhMV1{txMi)ci-dw) zZ2DhO*<96!;u{N3wK9LWwB9kz%`Eqo<7xjBUKbW5_AE{_NI}Xx*fIvVcmU=dVA5?6 z3G176_=D3uiJh*Yc|Rwge|7ltQblmtC@Ty~l^h0aK#GZx0X3yEwjn1MXrff;-MfdQ zD@bAWo)1%aY%J!?J0KA}WlDXxt!Q6qd{0v)lY)aCzxu2fyJmlxdA`srCQ7Un zl}c_MAuzox}Osr2Pq;=b5>kmk zL)paQv3_iZSj=aSb=2`#iHOhf^IJeA0d3_B4v%wZN3i*#wF0(KOr?N{$}S48_hpVU zUnpjW3)n0kL(HbQxloM&`Rj?)AYCF)$Pqa!hhdm+$rK5|L_Gp^Ce_-SO0~DO0bqq5 z!CFx&TB9Y1KKj3IKn4b*8<55}@MDKZu)`^CTn110^W#gQ$=}{Nq=G<6Ax#93Lh48< z1R+Wfs&*`Mc^@XoZ}f06gV>cGIq!?7fU5`VtQOt-Xt<+z^!Vk_G_!R^@HIFBl_;fItzPoTNr*m#s zPZK4{?0)CBNr&2!aiZjo}70)J{?(v4B->UZ0-qRou}uVP#cX>2>CMO?P`>oxIiB z_+YxEP^U2k?hG`k4k47!T9t9>JkQlt?Rkr8F^!VvKRN5n%ZiR?jF=mZ$&c>W`5QIjfkQiqLDJVKw1FefDj3-pz!wt8{t8i&rLufbjTf594o2d<*VYbeS&3mo%rp z{O3UL9J@WYUtb9gkog#dRW6*K+xUQTbLWS_)@@~{Kc=icdnPM%z;TlA_DGm+BR$f8 zs3v*mi954`^9aF-sq?((%d#J8-QH?sQr#=^9I9K{sDce$G)N$(#Y+dCN*v4{Yv2dm zSiyS}O|_F+Q}lbsCmAdaC@3;LVmK}U`>0{YF_+|0^A%pH!Ks|XyZOU>dHSX++9#W6 zIK;%lz&VjXiq->C=luDt(LA0ed8c<5nl zBhWbC`0(Z{)3`n6i%x&GUQ11V`{s3j!jr)d%~RVW$*JdzE#75ru~{;W)7ZtLv+lKf zyExKggr!;@zja9unj%{k%Oi$WyZTS|XhF&@OF$;&k2If&teV zwjr%H_IF9kH?hOJcCqQ+l%U@}^*h|*-*@=C3YteP-*8y}+Wb+&aRBQZfBnc!z-Uxo z3W01TnI*2#5|^8jonFzHc^NHa(A9Hyos&C=VIC1^rvu&NMaPEo;f$3a$tcIm&KDc=gd9j|FquY zX=HFM*LY6UqXb$)Ar5X&aXB=>bc|-cmAOupw z&BN`IT9%rVUyz%cS7NAOAO{j<<`IXgQ}E0yNiE7vP036wNmX!mG?X`xg}aE8QA{8+ zFD>5zq`0^^M=v=)*Fa93*U-Yy$jH#p+||3OD$4x&PdG6BkcSpMkVAhXJlnyZerwTFlb`rVrpV!WH>OD<6*etr^4Lrms}my z8B>qBuKTn{#bC$ObNYVQzR7g#shR(KMSA_em^p!^-@8t+KR4Cyf4H~$fPT&DlojHC zPQ_O5dZ75UNH1Tn?Z(vNTWh3)cgEXam*iFTf0&#c*v*|{zt(xjQkfW&&FdHzBp>}& z&mEajQM{~2VkJ}V`oofpdOHLjA3Ni)C3CTxab|nok=^3UKEJrTws=pqzT(!uX@NX@ zLpDFmjhES@Tzrv}xl`nlz|NGzS{D{h^V;+9id6LR1qTi$SMa--8yHP%FjAhnuzZ*B zrRl|wVpUIO@gBBJSh8h9rjrxr%Nrbfj1@LVC@o+0`pCm)iOokZO}l^dg8$m$K|1W;_wtIezbVPJ75}fSi;(^x^78p!?>A=oCZ{KEa8^z0J`j2F)mv5G zn4&JtdtE2W19x6M@>DH=XYcieuYXN`V{6ub{@u3hm=*rgg~xn#)?d1%aH8|`pW7{m zR(_kFv}V=v?BCXkfvr`=p(ahUf6P2Rt#i?3%lOT_@qP2$yh6iQ-xECFAg_AzO}@w9 zbJ3Sr*|Yur@Cq#GYWn@8+)DicAJ1>+l=umKYC=J&WlN>Yn*Q&Tb%OHvh_9Ti-ioekv;WZ5`@PHOwk z%gD(nCXktzmhS-4P+Xj&mzcEVK#Pfuro12!=IUvo!N)_*uJaciO=lS$hPg$QHr z29wSki<=nr44N3Vz|klx%)(^A0E|S=gf|OaABz}^NNlXy z`!#iDKWCSTYI~_NDZk&;X<*QJ6eO?A(zw^4aaV)LblHT%?Mjie6XaXA%#`Wy-G56i zZ(-xyC5^KT8mH4Vuq6z{Ac4(aUS6(;lnMwYlO`qsW^hWC+ z14{MUY>cd|?97bFIe^)n!N7${p(G}g`_{)B=N0!fuG#qX=w^$epL0G2=o+edMjXC( q`e`kbLd9JB=tn}krFCspZ)>mkQpPl)T4jZ-=QP)_@b2A_A-@0!1MW2d literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-int-ecc-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-int-ecc-cert.pem new file mode 100644 index 000000000..8b19fcd0e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/intermediate/server-int-ecc-cert.pem @@ -0,0 +1,63 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4100 (0x1004) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Development, CN=wolfSSL Intermediate CA ECC/emailAddress=info@wolfssl.com + Validity + Not Before: Dec 21 17:54:01 2018 GMT + Not After : Dec 18 17:54:01 2028 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Development, CN=wolfSSL Server Chain ECC/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 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:97:1D:60:C3:87:22:59:9B:60:1F:84:B4:99:1C:88:4D:BF:DA:1E:6E + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Development/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:10:03 + + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Key Agreement + X509v3 Extended Key Usage: + TLS Web Server Authentication + Signature Algorithm: ecdsa-with-SHA256 + 30:44:02:20:74:5c:69:0b:da:f1:d8:cf:21:bc:81:ac:b1:e5: + c5:b3:38:72:f9:9c:f1:50:2d:31:26:49:58:c3:de:cb:e5:7d: + 02:20:78:9d:3f:5b:e2:12:bb:1b:2d:3d:25:db:2b:a8:f4:76: + 02:90:7b:24:a8:1d:49:96:45:56:57:8b:bb:59:54:fa +-----BEGIN CERTIFICATE----- +MIIDZDCCAwugAwIBAgICEAQwCgYIKoZIzj0EAwIwgaMxCzAJBgNVBAYTAlVTMRMw +EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3 +b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEkMCIGA1UEAwwbd29sZlNTTCBJ +bnRlcm1lZGlhdGUgQ0EgRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE4MTIyMTE3NTQwMVoXDTI4MTIxODE3NTQwMVowgaAxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYD +VQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEhMB8GA1UEAwwYd29s +ZlNTTCBTZXJ2ZXIgQ2hhaW4gRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuzOsTCdQSsZKpQTDPN6f +NttyLc6U6iv6yyAJOSwW6GEC6a9N0wKTmjFbl5Ihf/DPGNqREQI0huggWDMLgDSJ +2KOCAS4wggEqMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMB0GA1UdDgQW +BBRdXSbvrH42+Zt2FStKJQIj77KJMDCBxQYDVR0jBIG9MIG6gBSXHWDDhyJZm2Af +hLSZHIhNv9oebqGBnaSBmjCBlzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hp +bmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZTU0wxFDASBgNV +BAsMC0RldmVsb3BtZW50MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkq +hkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CAhADMA4GA1UdDwEB/wQEAwIDqDAT +BgNVHSUEDDAKBggrBgEFBQcDATAKBggqhkjOPQQDAgNHADBEAiB0XGkL2vHYzyG8 +gayx5cWzOHL5nPFQLTEmSVjD3svlfQIgeJ0/W+ISuxstPSXbK6j0dgKQeySoHUmW +RVZXi7tZVPo= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ntru-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ntru-cert.pem index 4e8aa3e6b..47677f70b 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/certs/ntru-cert.pem +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ntru-cert.pem @@ -1,28 +1,29 @@ -----BEGIN CERTIFICATE----- -MIIEzzCCA7egAwIBAgIIAazu2er3DUMwDQYJKoZIhvcNAQEFBQAwgZQxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYD -VQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3 -LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMCIY -DzIwMTUwMjA0MDYzMzI5WhgPMjAxNjA2MTkwNzMzMjlaMIGKMQswCQYDVQQGEwJV -UzELMAkGA1UECAwCT1IxETAPBgNVBAcMCFBvcnRsYW5kMQ4wDAYDVQQKDAV5YVNT -TDEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxFjAUBgNVBAMMDXd3dy55YXNzbC5jb20x -HTAbBgkqhkiG9w0BCQEWDmluZm9AeWFzc2wuY29tMIICTTAaBgsrBgEEAcEWAQEB -AQYLKwYBBAHBFgEBAi4DggItAASCAiifDYOsBu8WQqIuom5HpD+jF7bvqvyO7LN4 -p7dOUfyBBX2zFc7fbhVoLcLw62Ye0i54UXMI/rglgOxEisVXPo0//Cs2rl3zwjho -fnEvEMpDU4mvqYTV8+N7FYoaUSEhMWTS0GMCJdK9aTvAz8l7F8gKP6MtgIv7Ght/ -r6JclP7fh12KMy9hiM/Tv3wqr+KhR8xFRfpL+paEIroidfpExFWbFB+xxA6KxGk4 -OEs/nus4rQl4w+6z5uf1cYfxKVRMFWLScEDQ3TdPcHz0+7fl/L7LYyCbK9z9LYVZ -5qZR1V27Iwx4H3d2w2D/3GGZpML/Uv8eBBHtODBbJC54U+bVh1ned28N1Y8I/bm8 -xRRCppfCJ3o+WxlsqHtyjIo/hi75SgUHknnbZ4hEuye1XhBBhUVhN2zybADMi1bv -S1RL/HAWsOO8qzBx5vkbVlDShsF+EccNUaNQyM98VE3FrUBbk4JxnyHBK5pA7aQ5 -7LOm83WkX2uR+ucR5en2TZIGVL+cJiTly+W7W8J83KEf5HJIUqnxFlgsre/0pMfe -7RqGer5Q4itWE+XWaPsDCUZnHy8a/CGdWlmdiGuw/0UvDqKQ4NRerbMgpo2Fl182 -fIQxfohhnm7iM0dAroIglkNBLM89A30d+73ZnUKgg4mRaqC5C29Me6LqpXjEUCiT -/s3g24IooqTj+8i8osRY5Zp4MQTmb3NrWVAWoOTtbFxDkhkwgqALupC8opUSIwAw -DQYJKoZIhvcNAQEFBQADggEBAHPi6MLfKV3ILr4wVgktXWNrPVgbqzUfoHhZhuhU -OgoT1KjiGQTpMrszGXyNKWTV+TpL2RmsBsXwI+lCl9nQMk5nkHAELShwXmgBpR+r -2dQTUy6C5xze8ZqPhsIjUjHyaagX8QY42SlSGOCChOEYshqO+QouPL2XOf2Hp4nJ -fgx4Mo2APTxGJ8TLYBCu4QzglCkKl7g1JRKBVA8Q4bkb1NWOnTgRQfIVv3N9DMn0 -ELw4uHkS2bXlzzbKRpwIMms0MIdWrVKFycQIp9Z2/7RsrIidZdGgsDeJLpItMZB8 -UM5Fz1UyZTy54Keoto4nBsU9ZJxzsTihT+Oq+/n1WaMEn+I= +MIIE8DCCA9igAwIBAgIQAJRoi3ieHovpl5HPgCG/LTANBgkqhkiG9w0BAQUFADCB +lDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVt +YW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYD +VQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wIhgPMjAxODA0MTIxNjIzMDJaGA8yMDIxMDEwNzE1MjMwMlowgaMxCzAJ +BgNVBAYTAlVTMQ8wDQYDVQQIDAZPcmdlb24xETAPBgNVBAcMCFBvcnRsYW5kMQ0w +CwYDVQQEDARUZXN0MRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9w +bWVudDEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBp +bmZvQHdvbGZzc2wuY29tMIICTTAaBgsrBgEEAcEWAQEBAQYLKwYBBAHBFgEBAi4D +ggItAASCAiiZEHm4vGsXiO64RwVglZIonsSRfqdQno0pBIk93shwAryAnF7ufVJf +4+Bhb9E4GJap88Kof6kSF8FsyWYU3xly0ZSitmGCHXpF7pqQ2V5n1n6mnvYcV4Ql +WR0tPe+1CEkxYsdQaIr7QXLW5ZW4rmZGmL42uioCro4k13x/YhWBsmHuo1C3vnj8 +t5D215pZ6FOD1SMcWIwEzQVncLzvMIous804sY5WYvGzJAkmSv+hgWY52+CoYxUU +LlYA81m5VksOLV8DxsNRvRIOYiUkBqKxzXMcuoOO/TzS/POYoyZ/DupuveP8fNFn +GuvpFwApCFEfVSz3uwHctziuQUnXvpstRY6mmdqbipISrddXwxfTgIp//M4JlV8X +wC3PrfoGx4xR6xmu0iUaJuBmwx1D4l0m4dPXFLKrMV+evZVo5rlYPBbNot7c9BeN +yE9nqnsKFT2PphPM1JlSEQHTZoVYGopAVRES/L+wBiy023gjU3Q9/HrQy5TWwkwH +RhyhvP1WTumNCB6Z+cofi02e7CJr20BX0+T9Q6xkOiX2rZ7bii4j68lxITcs7mWk +FHvlgWk+sdxZ0CPm+V4VmU7kRouZVmXuTE8lZuXByayKiDEUcB7fC7uynV7Vd+UR +XaXw2iU6ytK1qPw2i5O3cCO+BSjDYyVDHrvaJOfyi+1WfzZLJav3ogm5FtaUmr/+ +tAe/4sxscqwUmmPjgab5y+WL9AMXNEuUJnBGG4R3MwAwDQYJKoZIhvcNAQEFBQAD +ggEBAKFpalpswsMwzjLbT2UL/TpR8CpQ5tdN0OmDvW6Rr70RgFp8FDT50+H9b+Db +OdoT8CI5dlTK47sN/R/Q1IoABUr8ymW4oFwSmyNgEK4RdQg4MN9PEeChR0V1TLKM +p77IMksd9RZpiDsrmZl+rOTwGDkt+7INZmyvrJqurjmxYYZs4UsgEivUPZqA48xF +LbwLdfifLe0O+2tDixiiVPdL5RarT90SVB1yyU7EMHUmI4Mv6dssn9qd0Wou1fVf +bL66woDcr/vkV9O94RqlKsWKSnHNKQxmItHM3yO5yWWpTcITQLokyVPBxl1e3cT0 +Hln0y5owdmjr0+rPnvUZoZROfto= -----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ntru-key.raw b/FreeRTOS-Plus/Source/WolfSSL/certs/ntru-key.raw index 740bd340eb074e5921b2acba8427cb2132bd4e6d..725f6c82a2b37606d558da21c9fd54fcb5d7848a 100644 GIT binary patch literal 607 zcmV-l0-*f@0{{XLnGkunylWST?zl$-~ZS-DnA4lQ2; z#=}v)5)NV|BnG0f&2t>OgO2??(){z7qb7e2>TbQ`{Cv@88tds704WGjA5|>(y8+y{ zIIclS*S?!AMUJMK+M9}!60O%)!xz(lihumh36)Wzpw@@wA*+iQ*=H2deF<1*1}8&MjWBM{Z>xtjR+o@`N|)QO`hx`Yui9q)8zd_ ztYkVR_N|`ViY_DT$#Ee!Ebe8b6no`?X+E*sSfu{M(<%{$K7c@(hCU8a@gm*IlGR?pR5L@(E t^^%%vYNEh?xWQgvk_m#iS3ZqD{3|xDUGu^?Xnt`o5XwVSiLa@I)$`+f6^a^B zAt5nj($Hf9CDOfVJHXG$dl$$GKcg*xi~AZIf3Kokl>Xm`U5Ya=VTjMuzkDjM;-N>( zMMe5c`j&(ux*~P@M8s8_6d$p~4vNHSI5~ou)m^(I40s=RcEe!*++mrd!v9kL9t08XI51lz zE_hSs)rVQ$cW({Vj|ly_yu}nkrkBDedOlkjY^Zy3jEX;oF8N9Y2a zL4`$OH*E530L+V4?@Lrm{BRbq|$j^LKO~tK1Ta$uu zpCQ33nn3NOIqb8h^L3FoK{9x{$o0l@cQWW(MYB>y9=Q t^A-h3sCuFWeIZMoRY3tI^bIjZNJrAqT||;9I5Eal8MAQ^s#?Zz7Qh-aDv1C9 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/include.am b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/include.am new file mode 100644 index 000000000..73c5f285d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/include.am @@ -0,0 +1,35 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + certs/ocsp/index-ca-and-intermediate-cas.txt \ + certs/ocsp/index-ca-and-intermediate-cas.txt.attr \ + certs/ocsp/index-intermediate1-ca-issued-certs.txt \ + certs/ocsp/index-intermediate1-ca-issued-certs.txt.attr \ + certs/ocsp/index-intermediate2-ca-issued-certs.txt \ + certs/ocsp/index-intermediate2-ca-issued-certs.txt.attr \ + certs/ocsp/index-intermediate3-ca-issued-certs.txt \ + certs/ocsp/index-intermediate3-ca-issued-certs.txt.attr \ + certs/ocsp/openssl.cnf \ + certs/ocsp/renewcerts-for-test.sh \ + certs/ocsp/intermediate1-ca-key.pem \ + certs/ocsp/intermediate1-ca-cert.pem \ + certs/ocsp/intermediate2-ca-key.pem \ + certs/ocsp/intermediate2-ca-cert.pem \ + certs/ocsp/intermediate3-ca-key.pem \ + certs/ocsp/intermediate3-ca-cert.pem \ + certs/ocsp/ocsp-responder-key.pem \ + certs/ocsp/ocsp-responder-cert.pem \ + certs/ocsp/server1-key.pem \ + certs/ocsp/server1-cert.pem \ + certs/ocsp/server2-key.pem \ + certs/ocsp/server2-cert.pem \ + certs/ocsp/server3-key.pem \ + certs/ocsp/server3-cert.pem \ + certs/ocsp/server4-key.pem \ + certs/ocsp/server4-cert.pem \ + certs/ocsp/server5-key.pem \ + certs/ocsp/server5-cert.pem \ + certs/ocsp/root-ca-key.pem \ + certs/ocsp/root-ca-cert.pem diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-ca-and-intermediate-cas.txt b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-ca-and-intermediate-cas.txt new file mode 100644 index 000000000..256b8ab58 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-ca-and-intermediate-cas.txt @@ -0,0 +1,4 @@ +V 161213070133Z 63 unknown /C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com +V 161213070133Z 01 unknown /C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL intermediate CA 1/emailAddress=info@wolfssl.com +V 161213070133Z 02 unknown /C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL intermediate CA 2/emailAddress=info@wolfssl.com +R 161213070133Z 151201070133Z 03 unknown /C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL REVOKED intermediate CA/emailAddress=info@wolfssl.com diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-ca-and-intermediate-cas.txt.attr b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-ca-and-intermediate-cas.txt.attr new file mode 100644 index 000000000..3a7e39e6e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-ca-and-intermediate-cas.txt.attr @@ -0,0 +1 @@ +unique_subject = no diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate1-ca-issued-certs.txt b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate1-ca-issued-certs.txt new file mode 100644 index 000000000..a49ec58a3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate1-ca-issued-certs.txt @@ -0,0 +1,2 @@ +V 161213070133Z 05 unknown /C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=www1.wolfssl.com/emailAddress=info@wolfssl.com +R 161213070133Z 151201070133Z 06 unknown /C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=www2.wolfssl.com/emailAddress=info@wolfssl.com diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate1-ca-issued-certs.txt.attr b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate1-ca-issued-certs.txt.attr new file mode 100644 index 000000000..3a7e39e6e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate1-ca-issued-certs.txt.attr @@ -0,0 +1 @@ +unique_subject = no diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate2-ca-issued-certs.txt b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate2-ca-issued-certs.txt new file mode 100644 index 000000000..0a163f7b6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate2-ca-issued-certs.txt @@ -0,0 +1,2 @@ +V 161213070133Z 07 unknown /C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=www3.wolfssl.com/emailAddress=info@wolfssl.com +R 161213070133Z 151201070133Z 08 unknown /C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=www4.wolfssl.com/emailAddress=info@wolfssl.com diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate2-ca-issued-certs.txt.attr b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate2-ca-issued-certs.txt.attr new file mode 100644 index 000000000..3a7e39e6e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate2-ca-issued-certs.txt.attr @@ -0,0 +1 @@ +unique_subject = no diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate3-ca-issued-certs.txt b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate3-ca-issued-certs.txt new file mode 100644 index 000000000..eb6d3c048 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate3-ca-issued-certs.txt @@ -0,0 +1 @@ +V 161213070133Z 09 unknown /C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=www5.wolfssl.com/emailAddress=info@wolfssl.com diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate3-ca-issued-certs.txt.attr b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate3-ca-issued-certs.txt.attr new file mode 100644 index 000000000..3a7e39e6e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/index-intermediate3-ca-issued-certs.txt.attr @@ -0,0 +1 @@ +unique_subject = no diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate1-ca-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate1-ca-cert.pem new file mode 100644 index 000000000..a0593b2f7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate1-ca-cert.pem @@ -0,0 +1,186 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL intermediate CA 1/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:de:b4:c8:5c:77:e0:2d:b1:f5:b9:ad:16:47:35: + a0:35:65:65:c6:e1:40:ab:1e:b4:b9:13:b7:cb:8c: + bb:77:a5:76:da:6d:87:87:f6:4a:4d:13:e4:26:3e: + 27:87:ee:5b:c7:6a:3f:45:30:61:55:5c:f6:35:d1: + 65:fa:98:11:a3:a7:55:d5:be:91:82:4b:fc:be:90: + d6:50:53:63:9a:2c:22:e1:35:11:dc:78:02:97:8a: + e4:46:92:9c:53:08:76:de:1f:53:b6:b8:ca:77:3e: + 79:6e:bc:d0:e3:0d:30:5b:4c:f6:94:0d:30:29:64: + 9f:04:e5:db:fb:89:60:67:bb:af:26:83:51:77:24: + 2f:2b:0b:a1:94:81:10:98:e8:eb:26:a8:1e:7c:e4: + c4:6c:67:06:95:55:4a:dd:52:f4:f2:60:6d:01:2b: + 19:91:35:6d:a4:08:47:06:71:24:00:d9:de:c6:56: + f3:8b:53:2c:e2:9a:96:a5:f3:62:e5:c4:e3:23:f2: + d2:fc:21:ea:0f:62:76:8d:d5:99:48:ce:dc:58:c4: + bb:7f:da:94:2c:80:74:83:c5:e0:b0:15:7e:41:fd: + 0e:f2:f4:f0:78:76:7b:ad:26:0d:aa:48:96:17:2f: + 21:e3:95:2b:26:37:f9:aa:80:2f:fe:de:f6:5e:bc: + 97:7f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 83:C6:3A:89:2C:81:F4:02:D7:9D:4C:E2:2A:C0:71:82:64:44:DA:0E + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 18:a3:09:fe:c3:53:c7:ce:11:f0:36:86:43:9c:46:9b:43:42: + a0:20:6e:b6:32:29:34:22:fa:27:a1:00:0c:e5:51:c3:35:7b: + 2f:ce:2c:48:7f:47:cf:1b:45:f9:30:b2:d0:17:15:a0:c3:a8: + 3a:e4:5f:a4:96:e4:25:ea:4e:80:90:2e:8d:f5:19:98:ae:2a: + 6d:39:f0:06:8f:e6:0b:c4:2b:dd:07:4a:ad:3d:34:11:79:3d: + 15:db:65:c6:33:60:6b:2f:2d:47:26:bb:91:53:28:35:5c:fd: + 57:3b:27:1b:a1:85:03:24:74:84:f4:f2:b2:e3:53:41:83:9c: + 6b:5a:0c:0f:3b:c4:5f:a7:4b:8b:04:f2:0d:f5:81:aa:16:33: + d2:f4:f5:8d:83:c1:10:2d:57:55:f8:d3:16:62:27:50:b2:57: + 20:1d:a3:07:0c:b8:8d:c5:5a:2f:d9:d3:c4:6a:c3:1e:51:10: + de:7e:60:cf:d0:78:2c:00:d4:da:df:de:de:ee:ed:1d:25:da: + 6c:9f:57:69:2a:f1:a2:6c:8a:fe:72:c0:57:9f:f8:6e:b7:47: + f1:4f:f6:4b:9c:a2:2a:d2:10:9c:4e:bc:b4:8a:a2:8e:51:5a: + c1:e7:9c:f1:7c:9c:f9:7d:d7:9c:8f:ed:e9:57:91:0a:6c:4b: + b4:ac:6f:30 +-----BEGIN CERTIFICATE----- +MIIE8DCCA9igAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBoTELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSIwIAYDVQQDDBl3b2xmU1NMIGludGVy +bWVkaWF0ZSBDQSAxMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3rTIXHfgLbH1ua0WRzWgNWVl +xuFAqx60uRO3y4y7d6V22m2Hh/ZKTRPkJj4nh+5bx2o/RTBhVVz2NdFl+pgRo6dV +1b6Rgkv8vpDWUFNjmiwi4TUR3HgCl4rkRpKcUwh23h9TtrjKdz55brzQ4w0wW0z2 +lA0wKWSfBOXb+4lgZ7uvJoNRdyQvKwuhlIEQmOjrJqgefOTEbGcGlVVK3VL08mBt +ASsZkTVtpAhHBnEkANnexlbzi1Ms4pqWpfNi5cTjI/LS/CHqD2J2jdWZSM7cWMS7 +f9qULIB0g8XgsBV+Qf0O8vTweHZ7rSYNqkiWFy8h45UrJjf5qoAv/t72XryXfwID +AQABo4IBOTCCATUwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUg8Y6iSyB9ALXnUzi +KsBxgmRE2g4wgcQGA1UdIwSBvDCBuYAUc7AcpC+Cy89HpTjXsASCOn5yFSGhgZ2k +gZowgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEYMBYGA1UEAwwPd29sZlNTTCByb290IENBMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tggFjMAsGA1UdDwQEAwIBBjAyBggrBgEFBQcBAQQmMCQwIgYI +KwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjAwDQYJKoZIhvcNAQELBQAD +ggEBABijCf7DU8fOEfA2hkOcRptDQqAgbrYyKTQi+iehAAzlUcM1ey/OLEh/R88b +RfkwstAXFaDDqDrkX6SW5CXqToCQLo31GZiuKm058AaP5gvEK90HSq09NBF5PRXb +ZcYzYGsvLUcmu5FTKDVc/Vc7JxuhhQMkdIT08rLjU0GDnGtaDA87xF+nS4sE8g31 +gaoWM9L09Y2DwRAtV1X40xZiJ1CyVyAdowcMuI3FWi/Z08Rqwx5REN5+YM/QeCwA +1Nrf3t7u7R0l2myfV2kq8aJsiv5ywFef+G63R/FP9kucoirSEJxOvLSKoo5RWsHn +nPF8nPl915yP7elXkQpsS7SsbzA= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 99 (0x63) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:2c:b4:2f:1d:06:09:ef:4e:29:86:84:7e:cc: + bf:a6:79:7c:f0:c0:c1:64:25:8c:75:b7:10:05:ca: + 48:27:0c:0e:32:1c:b0:fe:99:85:39:b6:b9:a2:f7: + 27:ff:6d:3c:8c:16:73:29:21:7f:8b:a6:54:71:90: + ad:cc:05:b9:9f:15:c7:0a:3f:5f:69:f4:0a:5f:8c: + 71:b5:2c:bf:66:e2:03:9a:32:f4:d2:ec:2a:89:4b: + f9:35:88:14:33:47:4e:2e:05:79:01:ed:64:36:76: + b9:f8:85:cd:01:88:ac:c5:b2:b1:59:b8:cd:5a:f4: + 09:09:38:9b:da:5a:cf:ce:78:99:1f:49:3d:41:d6: + 06:7c:52:99:c8:97:d1:b3:80:3a:a2:4f:36:c4:c5: + 96:30:77:31:38:c8:70:cc:e1:67:06:b3:2b:2f:93: + b5:69:cf:83:7e:88:53:9b:0f:46:21:4c:d6:05:36: + 44:99:60:68:47:e5:32:01:12:d4:10:73:ae:9a:34: + 94:fa:6e:b8:58:4f:7b:5b:8a:92:97:ad:fd:97:b9: + 75:ca:c2:d4:45:7d:17:6b:cd:2f:f3:63:7a:0e:30: + b5:0b:a9:d9:a6:7c:74:60:9d:cc:09:03:43:f1:0f: + 90:d3:b7:fe:6c:9f:d9:cd:78:4b:15:ae:8c:5b:f9: + 99:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 6b:10:b1:f8:cb:77:ef:72:f5:f8:fc:70:6d:18:dc:34:fe:d7: + 95:d8:fd:85:8e:ca:4b:f3:be:1f:eb:14:08:dc:23:34:78:98: + 39:d7:9f:c3:52:f6:14:3d:e9:de:5c:c2:d8:b1:4b:a8:4c:5b: + 91:42:66:da:7f:3c:e9:03:20:5e:08:0f:76:79:b9:21:10:89: + b7:73:46:44:7e:6e:28:0c:00:e4:f4:3e:65:aa:f5:c6:27:57: + 2c:bb:1d:ae:e5:94:57:a3:73:9e:6b:44:00:35:4a:f3:c7:34: + 9c:a2:a7:aa:62:9f:1d:ef:a8:6c:be:07:ad:ef:ae:ee:93:0b: + ba:c3:59:4e:90:40:2d:00:5e:f0:0f:0a:de:18:2a:b3:97:31: + 63:84:ff:18:1c:b6:d8:7d:ee:33:ed:99:f0:f5:7f:88:58:b3: + 0d:90:db:eb:44:7e:06:37:61:d4:34:b9:f6:fd:3e:8d:07:e4: + b5:b0:ae:09:ce:98:e4:b0:1b:d5:7b:53:94:dd:8a:b2:20:d6: + b0:72:f8:b1:bc:76:df:16:86:39:7b:e4:a9:15:47:57:ae:ca: + 41:d6:3a:ba:15:d1:c0:b5:38:66:0b:0f:80:8b:a2:07:b4:fc: + 80:1f:a3:4c:1f:d2:65:97:c1:2c:ae:46:31:61:49:0d:d7:5f: + ac:d2:a6:05 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIBYzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBlzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NMIHJvb3Qg +Q0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCrLLQvHQYJ704phoR+zL+meXzwwMFkJYx1txAF +ykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRxkK3MBbmfFccKP19p9ApfjHG1 +LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4hc0BiKzFsrFZuM1a9AkJOJva +Ws/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4yHDM4WcGsysvk7Vpz4N+iFOb +D0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tbipKXrf2XuXXKwtRFfRdrzS/z +Y3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsVroxb+ZmBAgMBAAGjggE5MIIB +NTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRzsBykL4LLz0elONewBII6fnIVITCB +xAYDVR0jBIG8MIG5gBRzsBykL4LLz0elONewBII6fnIVIaGBnaSBmjCBlzELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +EDAOBgNVBAoMB3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQD +DA93b2xmU1NMIHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b22CAWMwCwYDVR0PBAQDAgEGMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW +aHR0cDovLzEyNy4wLjAuMToyMjIyMDANBgkqhkiG9w0BAQsFAAOCAQEAaxCx+Mt3 +73L1+PxwbRjcNP7Xldj9hY7KS/O+H+sUCNwjNHiYOdefw1L2FD3p3lzC2LFLqExb +kUJm2n886QMgXggPdnm5IRCJt3NGRH5uKAwA5PQ+Zar1xidXLLsdruWUV6NznmtE +ADVK88c0nKKnqmKfHe+obL4Hre+u7pMLusNZTpBALQBe8A8K3hgqs5cxY4T/GBy2 +2H3uM+2Z8PV/iFizDZDb60R+Bjdh1DS59v0+jQfktbCuCc6Y5LAb1XtTlN2KsiDW +sHL4sbx23xaGOXvkqRVHV67KQdY6uhXRwLU4ZgsPgIuiB7T8gB+jTB/SZZfBLK5G +MWFJDddfrNKmBQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate1-ca-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate1-ca-key.pem new file mode 100644 index 000000000..7147c9b0b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate1-ca-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDetMhcd+AtsfW5 +rRZHNaA1ZWXG4UCrHrS5E7fLjLt3pXbabYeH9kpNE+QmPieH7lvHaj9FMGFVXPY1 +0WX6mBGjp1XVvpGCS/y+kNZQU2OaLCLhNRHceAKXiuRGkpxTCHbeH1O2uMp3Pnlu +vNDjDTBbTPaUDTApZJ8E5dv7iWBnu68mg1F3JC8rC6GUgRCY6OsmqB585MRsZwaV +VUrdUvTyYG0BKxmRNW2kCEcGcSQA2d7GVvOLUyzimpal82LlxOMj8tL8IeoPYnaN +1ZlIztxYxLt/2pQsgHSDxeCwFX5B/Q7y9PB4dnutJg2qSJYXLyHjlSsmN/mqgC/+ +3vZevJd/AgMBAAECggEBAJC4sitEyy1mo+QREpUbyAxq5ASlhDyvK4nJwnpH7dsG +b4HqA1TbO9Vyw6QGZ/HxdzrTVGJF2jp6upSmirqZ73yF1UWdHTmq34eG3347clJR +tCjdL8oxQp3v5//kbimXKoeVm/T1iLyMoKTRlny1qWLrVKFJIK8FcEDijl2bHEbL +fdlPSJTN+y0zWoS3urRi/IPrsob23B4ILj0n+yUR4eOK25I3trqgsqcfTyMhX8tH +eyD4C+ir0j5evnmBhsKL0cUgGxGj8aVdOgab8dlKlDNi7HH5fe/FTMAQ344uege8 +D5dytc1H4wWq3le1PsvCh56lyPx7P4BamNzuJ85OnWECgYEA8xSw544oIe6RzMxh +51pYLyf1aU8zd9w0ISkXnXQ4RxcNubbFHLu/S/vSlbE5qqSf128H3XkAP6HT6UJe +JS/WqJbUcdWkzULjj7fLXJ2oer3hrVXq2L9Me1l0XrYoBvRuap15AtQ/cxafxMUZ +HpEWam0EPxoTkTp4EUWi++U09yMCgYEA6org2l1qdqChHw3ihlfl3rKMY/DT+f1b +uMnbMKNhqgyV3ItSh7MnVJurvJ56CQVuVay+T11qfyo3cKzxNYLYTGLvAtBeK/aC +B/hdCvxMBpXd71Vlnz0w6qJi0mkGNNTFGzxwqwPByqP0NyKStPN3W98HwFhiqKmU +y8wpv5ZeUfUCgYEAx1Ba8bLdc10zzbJ0QIgSsK/aCXx4njo/wET6aQ/HqXrctT+J +BlNnur0EYduMhkAwFCylTVMPAh4GLUhO+7zrDReHoMNmOywyfUBeDlXztJkHd+Jw +C0NoSegChDpmPbWk5+SxOcGhORP+8xAN1cNvltpG1hrimn1PwBHSXysEr/MCgYEA +hLVUCPp2dOzqfcHDfLRbcqigWyQ3LOo4bdR5W4n2httcKFAEwJeUF4GFqNIaxuP1 +zDBT9mArFAz1FaIlUVvZu073YiY4QrPWW2AidUbQVaGS1AsD1xguh3SeaePXCSmi +5YhLT9huXJRsaI39aLmhva/ymNjp6fkaIj5BGRCiCckCgYEAkZjADCg9gcqJo5oc +RDMpHT8C6SjE6+W0+00AnH1rSK0ev7uAGb6/rOpsShRiGubo7Ekil1MyMuOFmLPK +9K5oi4KKmVfTaPMfm2UnVCC2Dv2nMXkmYdQKiGgwbAhYfu/wGQXj682r2YYD4Xsa +qz7cWosuOKihAVhA52vZ7YacW2c= +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate2-ca-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate2-ca-cert.pem new file mode 100644 index 000000000..7305fe0e1 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate2-ca-cert.pem @@ -0,0 +1,186 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL intermediate CA 2/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d0:20:3c:35:19:6f:2c:44:b4:7e:42:c7:75:b4: + 6a:2b:a9:23:85:bf:87:b4:ee:ca:d7:4b:1f:31:d7: + 11:02:a1:ab:58:3d:fb:dc:51:ca:3a:1d:1f:95:a6: + 56:82:f7:8f:ff:6b:50:bb:ea:10:e1:47:1d:35:77: + 2e:4b:28:c5:53:46:23:2b:82:fd:5a:d3:f4:21:db: + 0e:e0:f2:76:33:47:b3:00:be:3a:b1:23:98:53:eb: + ea:a0:de:1b:cc:05:4e:ee:63:a8:2c:93:24:d6:98: + 78:74:03:e4:c8:89:43:61:f1:25:b8:cd:3b:87:c1: + 31:25:fd:ba:4c:fc:29:94:45:9e:69:d7:67:0a:8a: + 8e:d5:52:93:30:a2:0e:dd:6a:1c:b0:94:77:db:52: + 52:b7:89:21:be:96:75:24:cb:e9:49:df:81:9d:9d: + f8:55:7d:01:2a:eb:78:03:12:e2:20:6e:db:63:35: + cd:a1:96:f0:f8:8c:20:35:69:87:01:ca:b4:54:36: + a0:15:e0:23:7d:b9:fb:be:99:05:50:f0:bf:ec:7f: + 12:e1:3d:75:15:4e:c8:c2:30:e6:8b:fe:e5:8b:55: + f8:44:5e:e5:e3:56:e0:66:2d:6f:42:5a:45:6b:96: + aa:c7:5d:41:08:5f:ce:d7:dc:9f:20:e4:46:78:ff: + d9:99 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 05:D1:BA:86:00:A2:EE:2A:05:24:B7:11:AD:2D:60:F1:90:14:8F:17 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 92:6e:c1:af:88:af:46:f2:6e:8a:8c:27:06:8e:b4:38:35:9b: + 47:92:24:20:e5:a5:13:d8:35:d3:2e:37:ca:74:47:e5:16:a3: + 03:63:16:b4:28:2b:d9:04:ab:ee:e4:0a:e5:87:da:d4:00:3a: + 53:c6:c9:25:6a:8f:49:d2:2e:34:f2:40:65:6e:02:fc:b9:42: + 3f:ef:cb:8c:79:84:03:84:dc:a0:68:1e:c7:c7:36:8c:60:14: + 55:f2:5f:f9:c1:3f:2b:f6:a2:1e:34:1f:83:ba:73:bc:b7:62: + bc:97:66:84:09:b9:2d:76:71:c8:91:fd:e2:e1:39:cf:dd:ec: + 98:a8:49:69:89:a8:18:2a:42:e7:fc:ab:2c:cf:13:ab:63:fe: + b0:19:ea:1a:38:22:16:11:31:34:43:fc:50:c6:ec:19:97:03: + db:e8:07:28:48:88:3a:e5:35:a2:fd:83:12:df:55:70:72:61: + 0d:f8:66:18:52:58:c9:46:97:86:31:9e:a2:43:0c:b9:0f:d3: + eb:35:c9:e5:19:4e:b4:8b:d2:ac:ea:bf:83:2a:48:9d:20:a0: + 08:45:60:92:8a:27:06:93:77:74:bb:0e:22:8e:54:17:f2:d4: + e7:7f:f3:90:4d:cc:75:e7:16:c5:9c:4a:cf:dc:f2:19:18:12: + f5:72:8e:2e +-----BEGIN CERTIFICATE----- +MIIE8DCCA9igAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBoTELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSIwIAYDVQQDDBl3b2xmU1NMIGludGVy +bWVkaWF0ZSBDQSAyMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0CA8NRlvLES0fkLHdbRqK6kj +hb+HtO7K10sfMdcRAqGrWD373FHKOh0flaZWgveP/2tQu+oQ4UcdNXcuSyjFU0Yj +K4L9WtP0IdsO4PJ2M0ezAL46sSOYU+vqoN4bzAVO7mOoLJMk1ph4dAPkyIlDYfEl +uM07h8ExJf26TPwplEWeaddnCoqO1VKTMKIO3WocsJR321JSt4khvpZ1JMvpSd+B +nZ34VX0BKut4AxLiIG7bYzXNoZbw+IwgNWmHAcq0VDagFeAjfbn7vpkFUPC/7H8S +4T11FU7IwjDmi/7li1X4RF7l41bgZi1vQlpFa5aqx11BCF/O19yfIORGeP/ZmQID +AQABo4IBOTCCATUwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUBdG6hgCi7ioFJLcR +rS1g8ZAUjxcwgcQGA1UdIwSBvDCBuYAUc7AcpC+Cy89HpTjXsASCOn5yFSGhgZ2k +gZowgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEYMBYGA1UEAwwPd29sZlNTTCByb290IENBMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tggFjMAsGA1UdDwQEAwIBBjAyBggrBgEFBQcBAQQmMCQwIgYI +KwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjAwDQYJKoZIhvcNAQELBQAD +ggEBAJJuwa+Ir0byboqMJwaOtDg1m0eSJCDlpRPYNdMuN8p0R+UWowNjFrQoK9kE +q+7kCuWH2tQAOlPGySVqj0nSLjTyQGVuAvy5Qj/vy4x5hAOE3KBoHsfHNoxgFFXy +X/nBPyv2oh40H4O6c7y3YryXZoQJuS12cciR/eLhOc/d7JioSWmJqBgqQuf8qyzP +E6tj/rAZ6ho4IhYRMTRD/FDG7BmXA9voByhIiDrlNaL9gxLfVXByYQ34ZhhSWMlG +l4YxnqJDDLkP0+s1yeUZTrSL0qzqv4MqSJ0goAhFYJKKJwaTd3S7DiKOVBfy1Od/ +85BNzHXnFsWcSs/c8hkYEvVyji4= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 99 (0x63) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:2c:b4:2f:1d:06:09:ef:4e:29:86:84:7e:cc: + bf:a6:79:7c:f0:c0:c1:64:25:8c:75:b7:10:05:ca: + 48:27:0c:0e:32:1c:b0:fe:99:85:39:b6:b9:a2:f7: + 27:ff:6d:3c:8c:16:73:29:21:7f:8b:a6:54:71:90: + ad:cc:05:b9:9f:15:c7:0a:3f:5f:69:f4:0a:5f:8c: + 71:b5:2c:bf:66:e2:03:9a:32:f4:d2:ec:2a:89:4b: + f9:35:88:14:33:47:4e:2e:05:79:01:ed:64:36:76: + b9:f8:85:cd:01:88:ac:c5:b2:b1:59:b8:cd:5a:f4: + 09:09:38:9b:da:5a:cf:ce:78:99:1f:49:3d:41:d6: + 06:7c:52:99:c8:97:d1:b3:80:3a:a2:4f:36:c4:c5: + 96:30:77:31:38:c8:70:cc:e1:67:06:b3:2b:2f:93: + b5:69:cf:83:7e:88:53:9b:0f:46:21:4c:d6:05:36: + 44:99:60:68:47:e5:32:01:12:d4:10:73:ae:9a:34: + 94:fa:6e:b8:58:4f:7b:5b:8a:92:97:ad:fd:97:b9: + 75:ca:c2:d4:45:7d:17:6b:cd:2f:f3:63:7a:0e:30: + b5:0b:a9:d9:a6:7c:74:60:9d:cc:09:03:43:f1:0f: + 90:d3:b7:fe:6c:9f:d9:cd:78:4b:15:ae:8c:5b:f9: + 99:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 6b:10:b1:f8:cb:77:ef:72:f5:f8:fc:70:6d:18:dc:34:fe:d7: + 95:d8:fd:85:8e:ca:4b:f3:be:1f:eb:14:08:dc:23:34:78:98: + 39:d7:9f:c3:52:f6:14:3d:e9:de:5c:c2:d8:b1:4b:a8:4c:5b: + 91:42:66:da:7f:3c:e9:03:20:5e:08:0f:76:79:b9:21:10:89: + b7:73:46:44:7e:6e:28:0c:00:e4:f4:3e:65:aa:f5:c6:27:57: + 2c:bb:1d:ae:e5:94:57:a3:73:9e:6b:44:00:35:4a:f3:c7:34: + 9c:a2:a7:aa:62:9f:1d:ef:a8:6c:be:07:ad:ef:ae:ee:93:0b: + ba:c3:59:4e:90:40:2d:00:5e:f0:0f:0a:de:18:2a:b3:97:31: + 63:84:ff:18:1c:b6:d8:7d:ee:33:ed:99:f0:f5:7f:88:58:b3: + 0d:90:db:eb:44:7e:06:37:61:d4:34:b9:f6:fd:3e:8d:07:e4: + b5:b0:ae:09:ce:98:e4:b0:1b:d5:7b:53:94:dd:8a:b2:20:d6: + b0:72:f8:b1:bc:76:df:16:86:39:7b:e4:a9:15:47:57:ae:ca: + 41:d6:3a:ba:15:d1:c0:b5:38:66:0b:0f:80:8b:a2:07:b4:fc: + 80:1f:a3:4c:1f:d2:65:97:c1:2c:ae:46:31:61:49:0d:d7:5f: + ac:d2:a6:05 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIBYzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBlzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NMIHJvb3Qg +Q0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCrLLQvHQYJ704phoR+zL+meXzwwMFkJYx1txAF +ykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRxkK3MBbmfFccKP19p9ApfjHG1 +LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4hc0BiKzFsrFZuM1a9AkJOJva +Ws/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4yHDM4WcGsysvk7Vpz4N+iFOb +D0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tbipKXrf2XuXXKwtRFfRdrzS/z +Y3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsVroxb+ZmBAgMBAAGjggE5MIIB +NTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRzsBykL4LLz0elONewBII6fnIVITCB +xAYDVR0jBIG8MIG5gBRzsBykL4LLz0elONewBII6fnIVIaGBnaSBmjCBlzELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +EDAOBgNVBAoMB3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQD +DA93b2xmU1NMIHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b22CAWMwCwYDVR0PBAQDAgEGMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW +aHR0cDovLzEyNy4wLjAuMToyMjIyMDANBgkqhkiG9w0BAQsFAAOCAQEAaxCx+Mt3 +73L1+PxwbRjcNP7Xldj9hY7KS/O+H+sUCNwjNHiYOdefw1L2FD3p3lzC2LFLqExb +kUJm2n886QMgXggPdnm5IRCJt3NGRH5uKAwA5PQ+Zar1xidXLLsdruWUV6NznmtE +ADVK88c0nKKnqmKfHe+obL4Hre+u7pMLusNZTpBALQBe8A8K3hgqs5cxY4T/GBy2 +2H3uM+2Z8PV/iFizDZDb60R+Bjdh1DS59v0+jQfktbCuCc6Y5LAb1XtTlN2KsiDW +sHL4sbx23xaGOXvkqRVHV67KQdY6uhXRwLU4ZgsPgIuiB7T8gB+jTB/SZZfBLK5G +MWFJDddfrNKmBQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate2-ca-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate2-ca-key.pem new file mode 100644 index 000000000..61cec0879 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate2-ca-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDQIDw1GW8sRLR+ +Qsd1tGorqSOFv4e07srXSx8x1xECoatYPfvcUco6HR+VplaC94//a1C76hDhRx01 +dy5LKMVTRiMrgv1a0/Qh2w7g8nYzR7MAvjqxI5hT6+qg3hvMBU7uY6gskyTWmHh0 +A+TIiUNh8SW4zTuHwTEl/bpM/CmURZ5p12cKio7VUpMwog7dahywlHfbUlK3iSG+ +lnUky+lJ34GdnfhVfQEq63gDEuIgbttjNc2hlvD4jCA1aYcByrRUNqAV4CN9ufu+ +mQVQ8L/sfxLhPXUVTsjCMOaL/uWLVfhEXuXjVuBmLW9CWkVrlqrHXUEIX87X3J8g +5EZ4/9mZAgMBAAECggEAR2vofWhfCFgDgJi2DiR9ksIWWJ2jmmmf3kX/TIE7ayXD +wSJ0PeUresnnvtk4MvV1yvcu2221oTlgQqrFjjFNlggppZLsErFNxBiCgJt0CKEA +Qq8FQSiv64y4FcBi1Z60uYYlfjZ4m9Py8g0sA81m/ENe6I41cZ7QmPL7bdPTCPhE +cGwPKjkw1xwDn6EeK5x5sscfCrlKXsH4zhXH67r2iwQ7x5+t4pWApdT15rMX+r0E +HzBoj4wjhR7yo9nZDqhBZiOJF/zQGTCkj6J451Rj47s42fLTYgVyW5D1DO9wBvQQ +i7AwwDuimVqKNGW7J/oRjhiBAKFr2IOGcAFJJbM3SQKBgQD1JRO9umdNfqj38kw5 +DMeydVITvhYjSfc+F2R1hldX9kSdowttJ3GwArnjsZLSfttj7/gnRVPJC+OWvJGm +AmegmCXJGl/mtDAlN+MDJw2/KEdcC4CHMqRokrNNF3zafbTDIDq24kAMx1wef46k +8+9F3IPY+arD50LSkS5+gUUk1wKBgQDZV4R9yCeAE8o+ejks7lBC8kk5CxZKbXPA +o4vPHGKOknmZGqfKJY9Auk7nk4g56K9GxlotlsjwCwuSBdkqjDkqMypHG9odh6s8 +8iFjVGvJvY6x+PXONW6cjG2K6Lif0o0/bx+C+2Sy05koV1eYY4+EskafqTxbQgSa +0t85a6u3DwKBgGK4g7KsFl3G3BS9pqRy2Ris1ljM++1KJB8FHJeXeiUaL5eryTYz +5DyVXHatVAsguwkL4ksuSAd2mjhhx+WqokCyBMVvsZ8egST71Je4anjIp7QRjbjk +VAEo0rwA8W6roNfTatGrW0/KGPbPN4qGEZ14qEAAixxJTUeu36JiPI4RAoGASK43 +pEh2zSHRFCuTSy82r+yOCAFpJuKLPvRyIISBgOQCvexoB/WffinPkSmI+LSTSLu0 +FGLEN2G6MM673LqfszkA/l6WBiIEZZEjETB+CyzUtzdmG9tKbheX2kgQ1YF3sqra +gtbGyfZw1UjABjnlGJ71dxcFFA9zssKp223iMokCgYAEBpHy/x90qWR6d9ApXZnC +PMvcZCa2EgQWBabOkyxF7Ao8mIu0K4rqRM9XBlboRRBQdEP3qL7whJ2voZ7frZYH +E9hcwnH4F6rBki9PHbEaU80FfTUplKr+qMJavhQ8O1zGhWr7JSF6ByqTQDYWI8BX +3Q6DAbgdQeeCKFpi4256AA== +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate3-ca-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate3-ca-cert.pem new file mode 100644 index 000000000..365426bb5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate3-ca-cert.pem @@ -0,0 +1,186 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL REVOKED intermediate CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:de:c5:04:10:7d:c2:21:e9:12:45:da:d5:ba:28: + fd:a6:f4:30:44:a0:df:f9:70:5e:17:26:97:59:5c: + 31:eb:13:70:ea:4a:dd:58:3e:4f:33:14:66:59:69: + 7a:aa:90:e0:7c:c4:b2:36:c1:0a:f4:df:3e:34:6c: + 1a:e9:2b:f1:a5:92:7e:a9:68:70:ba:a4:68:88:f3: + ec:10:40:64:a5:64:7d:d9:1e:51:49:9d:7f:c8:cc: + 2b:6d:71:2a:06:ff:e6:1f:84:28:8a:c1:ed:a8:52: + f4:89:a5:c0:77:d8:13:66:c2:65:a5:63:03:98:b0: + 4b:05:4f:0c:84:a0:f4:2d:72:73:6b:fa:0d:e1:cf: + 45:27:ed:a3:8c:02:d7:ee:99:e2:a1:f0:e3:a0:ad: + 69:ed:59:e4:27:41:8f:ef:fa:83:73:8f:5f:2b:68: + 89:13:46:26:dc:f6:28:6b:3b:b2:b8:9b:52:2a:17: + 1b:dc:72:45:73:da:75:24:35:8b:00:5e:23:37:64: + 6a:16:74:b8:ee:fe:b7:11:71:be:0a:73:c8:54:c2: + d9:04:d2:1b:f5:53:ac:8d:2a:4f:fe:33:79:e6:5e: + e7:f3:86:d3:dc:bb:4b:d7:39:7f:5b:3c:67:fe:5e: + 88:51:05:96:f2:b4:9a:45:09:4c:51:f0:6a:4d:88: + 2a:17 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + BB:15:9E:32:4D:E0:F8:AA:8A:B0:2E:0C:17:2B:5A:41:74:4B:06:45 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 63:bf:90:58:0c:44:08:57:7d:94:7e:eb:fd:9d:90:f6:1d:a5: + 91:2a:32:38:a7:f7:39:c2:c0:9c:93:26:bc:f4:4b:81:0a:0f: + 07:2d:4f:a9:20:9a:3e:2c:24:0c:30:10:d7:be:96:ab:ee:1f: + 2c:f8:71:7c:1a:c1:ae:b7:64:e1:7e:18:53:c3:ae:d5:04:16: + f7:e5:34:c2:d1:a3:31:d4:9b:f4:b7:c1:96:1f:a7:3c:3a:bf: + fd:06:be:76:f4:da:95:f9:6f:be:4f:24:a7:0f:b0:2c:12:4d: + d6:55:ea:f8:0a:30:91:32:4f:a3:14:6d:ec:cd:85:12:1f:da: + 78:8a:b1:9a:74:fb:fd:00:45:4a:30:83:45:16:a0:8f:b7:7f: + 23:33:91:c6:81:ac:f3:9b:cd:53:6b:9a:fa:36:9b:5d:3c:72: + a8:73:4f:1e:b5:da:ba:08:3d:9b:ca:7a:d6:c2:bf:6e:9f:a5: + 9e:db:61:bc:a5:42:a7:d4:92:4a:7e:a3:3d:1b:aa:d3:c2:93: + ad:ce:3b:0e:2b:61:44:1e:3c:61:54:0d:6a:26:21:54:c6:e0: + ed:3d:da:27:cd:89:5a:f8:1f:0f:46:80:c1:f2:80:cc:52:f1: + 7f:ce:10:68:66:3f:ee:90:25:45:d4:f8:87:f9:5d:5d:74:3d: + aa:3d:43:1c +-----BEGIN CERTIFICATE----- +MIIE9jCCA96gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBpzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSgwJgYDVQQDDB93b2xmU1NMIFJFVk9L +RUQgaW50ZXJtZWRpYXRlIENBMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3sUEEH3CIekSRdrV +uij9pvQwRKDf+XBeFyaXWVwx6xNw6krdWD5PMxRmWWl6qpDgfMSyNsEK9N8+NGwa +6SvxpZJ+qWhwuqRoiPPsEEBkpWR92R5RSZ1/yMwrbXEqBv/mH4QoisHtqFL0iaXA +d9gTZsJlpWMDmLBLBU8MhKD0LXJza/oN4c9FJ+2jjALX7pniofDjoK1p7VnkJ0GP +7/qDc49fK2iJE0Ym3PYoazuyuJtSKhcb3HJFc9p1JDWLAF4jN2RqFnS47v63EXG+ +CnPIVMLZBNIb9VOsjSpP/jN55l7n84bT3LtL1zl/Wzxn/l6IUQWW8rSaRQlMUfBq +TYgqFwIDAQABo4IBOTCCATUwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUuxWeMk3g ++KqKsC4MFytaQXRLBkUwgcQGA1UdIwSBvDCBuYAUc7AcpC+Cy89HpTjXsASCOn5y +FSGhgZ2kgZowgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAw +DgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdp +bmVlcmluZzEYMBYGA1UEAwwPd29sZlNTTCByb290IENBMR8wHQYJKoZIhvcNAQkB +FhBpbmZvQHdvbGZzc2wuY29tggFjMAsGA1UdDwQEAwIBBjAyBggrBgEFBQcBAQQm +MCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjAwDQYJKoZIhvcN +AQELBQADggEBAGO/kFgMRAhXfZR+6/2dkPYdpZEqMjin9znCwJyTJrz0S4EKDwct +T6kgmj4sJAwwENe+lqvuHyz4cXwawa63ZOF+GFPDrtUEFvflNMLRozHUm/S3wZYf +pzw6v/0Gvnb02pX5b75PJKcPsCwSTdZV6vgKMJEyT6MUbezNhRIf2niKsZp0+/0A +RUowg0UWoI+3fyMzkcaBrPObzVNrmvo2m108cqhzTx612roIPZvKetbCv26fpZ7b +YbylQqfUkkp+oz0bqtPCk63OOw4rYUQePGFUDWomIVTG4O092ifNiVr4Hw9GgMHy +gMxS8X/OEGhmP+6QJUXU+If5XV10Pao9Qxw= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 99 (0x63) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:2c:b4:2f:1d:06:09:ef:4e:29:86:84:7e:cc: + bf:a6:79:7c:f0:c0:c1:64:25:8c:75:b7:10:05:ca: + 48:27:0c:0e:32:1c:b0:fe:99:85:39:b6:b9:a2:f7: + 27:ff:6d:3c:8c:16:73:29:21:7f:8b:a6:54:71:90: + ad:cc:05:b9:9f:15:c7:0a:3f:5f:69:f4:0a:5f:8c: + 71:b5:2c:bf:66:e2:03:9a:32:f4:d2:ec:2a:89:4b: + f9:35:88:14:33:47:4e:2e:05:79:01:ed:64:36:76: + b9:f8:85:cd:01:88:ac:c5:b2:b1:59:b8:cd:5a:f4: + 09:09:38:9b:da:5a:cf:ce:78:99:1f:49:3d:41:d6: + 06:7c:52:99:c8:97:d1:b3:80:3a:a2:4f:36:c4:c5: + 96:30:77:31:38:c8:70:cc:e1:67:06:b3:2b:2f:93: + b5:69:cf:83:7e:88:53:9b:0f:46:21:4c:d6:05:36: + 44:99:60:68:47:e5:32:01:12:d4:10:73:ae:9a:34: + 94:fa:6e:b8:58:4f:7b:5b:8a:92:97:ad:fd:97:b9: + 75:ca:c2:d4:45:7d:17:6b:cd:2f:f3:63:7a:0e:30: + b5:0b:a9:d9:a6:7c:74:60:9d:cc:09:03:43:f1:0f: + 90:d3:b7:fe:6c:9f:d9:cd:78:4b:15:ae:8c:5b:f9: + 99:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 6b:10:b1:f8:cb:77:ef:72:f5:f8:fc:70:6d:18:dc:34:fe:d7: + 95:d8:fd:85:8e:ca:4b:f3:be:1f:eb:14:08:dc:23:34:78:98: + 39:d7:9f:c3:52:f6:14:3d:e9:de:5c:c2:d8:b1:4b:a8:4c:5b: + 91:42:66:da:7f:3c:e9:03:20:5e:08:0f:76:79:b9:21:10:89: + b7:73:46:44:7e:6e:28:0c:00:e4:f4:3e:65:aa:f5:c6:27:57: + 2c:bb:1d:ae:e5:94:57:a3:73:9e:6b:44:00:35:4a:f3:c7:34: + 9c:a2:a7:aa:62:9f:1d:ef:a8:6c:be:07:ad:ef:ae:ee:93:0b: + ba:c3:59:4e:90:40:2d:00:5e:f0:0f:0a:de:18:2a:b3:97:31: + 63:84:ff:18:1c:b6:d8:7d:ee:33:ed:99:f0:f5:7f:88:58:b3: + 0d:90:db:eb:44:7e:06:37:61:d4:34:b9:f6:fd:3e:8d:07:e4: + b5:b0:ae:09:ce:98:e4:b0:1b:d5:7b:53:94:dd:8a:b2:20:d6: + b0:72:f8:b1:bc:76:df:16:86:39:7b:e4:a9:15:47:57:ae:ca: + 41:d6:3a:ba:15:d1:c0:b5:38:66:0b:0f:80:8b:a2:07:b4:fc: + 80:1f:a3:4c:1f:d2:65:97:c1:2c:ae:46:31:61:49:0d:d7:5f: + ac:d2:a6:05 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIBYzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBlzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NMIHJvb3Qg +Q0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCrLLQvHQYJ704phoR+zL+meXzwwMFkJYx1txAF +ykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRxkK3MBbmfFccKP19p9ApfjHG1 +LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4hc0BiKzFsrFZuM1a9AkJOJva +Ws/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4yHDM4WcGsysvk7Vpz4N+iFOb +D0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tbipKXrf2XuXXKwtRFfRdrzS/z +Y3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsVroxb+ZmBAgMBAAGjggE5MIIB +NTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRzsBykL4LLz0elONewBII6fnIVITCB +xAYDVR0jBIG8MIG5gBRzsBykL4LLz0elONewBII6fnIVIaGBnaSBmjCBlzELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +EDAOBgNVBAoMB3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQD +DA93b2xmU1NMIHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b22CAWMwCwYDVR0PBAQDAgEGMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW +aHR0cDovLzEyNy4wLjAuMToyMjIyMDANBgkqhkiG9w0BAQsFAAOCAQEAaxCx+Mt3 +73L1+PxwbRjcNP7Xldj9hY7KS/O+H+sUCNwjNHiYOdefw1L2FD3p3lzC2LFLqExb +kUJm2n886QMgXggPdnm5IRCJt3NGRH5uKAwA5PQ+Zar1xidXLLsdruWUV6NznmtE +ADVK88c0nKKnqmKfHe+obL4Hre+u7pMLusNZTpBALQBe8A8K3hgqs5cxY4T/GBy2 +2H3uM+2Z8PV/iFizDZDb60R+Bjdh1DS59v0+jQfktbCuCc6Y5LAb1XtTlN2KsiDW +sHL4sbx23xaGOXvkqRVHV67KQdY6uhXRwLU4ZgsPgIuiB7T8gB+jTB/SZZfBLK5G +MWFJDddfrNKmBQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate3-ca-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate3-ca-key.pem new file mode 100644 index 000000000..03ebd4154 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/intermediate3-ca-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDexQQQfcIh6RJF +2tW6KP2m9DBEoN/5cF4XJpdZXDHrE3DqSt1YPk8zFGZZaXqqkOB8xLI2wQr03z40 +bBrpK/Glkn6paHC6pGiI8+wQQGSlZH3ZHlFJnX/IzCttcSoG/+YfhCiKwe2oUvSJ +pcB32BNmwmWlYwOYsEsFTwyEoPQtcnNr+g3hz0Un7aOMAtfumeKh8OOgrWntWeQn +QY/v+oNzj18raIkTRibc9ihrO7K4m1IqFxvcckVz2nUkNYsAXiM3ZGoWdLju/rcR +cb4Kc8hUwtkE0hv1U6yNKk/+M3nmXufzhtPcu0vXOX9bPGf+XohRBZbytJpFCUxR +8GpNiCoXAgMBAAECggEAFkESRd96TE7vT2EsJru/kzUjuUdk+JM8Iw3s4rVuGzDG +//DYqd8XpF+uVdJOucldU7mGoCeqw4mlujDug0qrikHXO28+i7au5rePZpQ4ObmP +ROhdcIA2asXStM0wSKC5yX43Wp1C86TN3w5a6t4AGizjYKFCk7dQ10ftVTaLDhsI +I4uuEZAHA7ruKmQp1DbE+/696kY4GUh2SXYQxee1zb/yYDvA6lGhuDW2Jev+4v4l ++1LZq8E2bE4GsmiLEALiHAdGvOrkZ5MUkiHVTnhGz7THK0OMj/4dJlNCwusyO+O5 +4Zr2LJQ2rnAtVGdtKuVsgwHwQBPpV9bJPkDXEzlXUQKBgQD38kxnjJ5nv0plMA+E +QViItp0qgQeXX18YTlh8yicqVe+t9kKnHm1tqZx/djvvR/51p0SkMfWNvMn8JYXa +dfT3ZX0djrzR9o6FgR8rL+LmPg6jyIn71wBqmMf7A6WQVYuG7fQk3IJNtx52BKcS +f8r2tsdPX8d/FBsCn3m/ZxaEyQKBgQDmAV5xxTbJKdea5pfH33BOCp6HTqSYgf4Y +/5GEO0YLmQoBXAKbX+zcAeiaOt5WvLQgw7LfkznitPlxCkpHr9VcgVarlEjXHa7y +SeJfik5cIFbMZtXqaQ/DIUvOTgnb/ngLxEdrzX4JUnlv/z1BEhWvEYaHn0asEsc4 +zbbcKoEH3wKBgQDRisobcPGmSDm9TmKuqPMDhyFH/IfH2+foCL4rqER1OO84G7i0 +t7hPR1plNizsyfE4yUXvZfFZ+cTR/Xwj5jBCrFiSlEDrSO2l0jvfKbceUi/ZJu/G +ECvf6oKHlstjMYibXZpJVLoip7Fsl/4CWlHTMyE56X4V3Y3+J3yiz6JuUQKBgDPS +byMXGibs5IUkG2KPN1B+GAXIdFFgSI39Vx4B9OA8FQMFZhj33fgb/fpx9RJ55ePT +9ANnuo0X1XPgq6fHOD1lbs+t01OUfoxclUKNeOZM6wGW0e/EyCZg5CGRd6s3hHiy +Op1RaWpUSMQxL+3vUy9ktXjtLBEtEfH8d4zXjsblAoGBAMPAdSskbG+upEYcNR2O +++R9X8BkWhaTDqkAuygsGJDomIgH89wROdlTnsi5LXe/r3uCocRC+M1ChRXm7Zqs +81QjVdls6HVZu5rG82S8itqdXHOXCajb1ls+lNiu7/9tPJVmpYfjfjD4/QHV0vF/ +FqdfthIOUXePjrAKccJDiJIk +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/ocsp-responder-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/ocsp-responder-cert.pem new file mode 100644 index 000000000..447bc0f77 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/ocsp-responder-cert.pem @@ -0,0 +1,182 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4 (0x4) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL OCSP Responder/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b8:ba:23:b4:f6:c3:7b:14:c3:a4:f5:1d:61:a1: + f5:1e:63:b9:85:23:34:50:6d:f8:7c:a2:8a:04:8b: + d5:75:5c:2d:f7:63:88:d1:07:7a:ea:0b:45:35:2b: + eb:1f:b1:22:b4:94:41:38:e2:9d:74:d6:8b:30:22: + 10:51:c5:db:ca:3f:46:2b:fe:e5:5a:3f:41:74:67: + 75:95:a9:94:d5:c3:ee:42:f8:8d:eb:92:95:e1:d9: + 65:b7:43:c4:18:de:16:80:90:ce:24:35:21:c4:55: + ac:5a:51:e0:2e:2d:b3:0a:5a:4f:4a:73:31:50:ee: + 4a:16:bd:39:8b:ad:05:48:87:b1:99:e2:10:a7:06: + 72:67:ca:5c:d1:97:bd:c8:f1:76:f8:e0:4a:ec:bc: + 93:f4:66:4c:28:71:d1:d8:66:03:b4:90:30:bb:17: + b0:fe:97:f5:1e:e8:c7:5d:9b:8b:11:19:12:3c:ab: + 82:71:78:ff:ae:3f:32:b2:08:71:b2:1b:8c:27:ac: + 11:b8:d8:43:49:cf:b0:70:b1:f0:8c:ae:da:24:87: + 17:3b:d8:04:65:6c:00:76:50:ef:15:08:d7:b4:73: + 68:26:14:87:95:c3:5f:6e:61:b8:87:84:fa:80:1a: + 0a:8b:98:f3:e3:ff:4e:44:1c:65:74:7c:71:54:65: + e5:39 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Key Identifier: + 32:67:E1:B1:79:D2:81:FC:9F:23:0C:70:40:50:B5:46:56:B8:30:36 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Extended Key Usage: + OCSP Signing + Signature Algorithm: sha256WithRSAEncryption + 9b:56:c5:5f:b9:b2:00:30:ca:05:2a:e8:c6:96:ba:aa:23:40: + 40:89:6d:a2:7a:93:f2:c9:8a:6f:0e:5d:5f:6f:ce:5e:4b:38: + a9:d2:ab:97:78:e3:73:3d:3d:27:e9:00:ce:16:d9:c5:c5:06: + a8:eb:c6:e5:76:4c:f7:60:1a:69:ae:35:d6:f8:0f:da:9c:83: + c6:fb:74:a6:12:e5:c7:64:ae:e7:2c:b6:d3:62:1f:f3:20:11: + 2e:09:9b:14:f0:a3:17:d0:2c:be:4a:39:3a:55:58:2f:90:37: + 04:c5:54:27:9d:0e:51:97:da:21:df:05:ec:ca:79:a8:ca:02: + ca:cf:b7:05:ef:04:fa:f9:81:20:10:c1:7d:4a:a7:93:13:28: + 1e:98:a7:3e:4c:01:13:c3:6b:14:e1:87:37:5f:3a:d3:7d:b6: + d4:d9:0d:56:93:7f:1d:e9:c2:35:c7:11:7f:42:d0:d5:3d:5f: + f6:fc:23:24:e3:45:7f:4f:9e:18:df:7b:41:80:fa:bb:bd:16: + e1:eb:c5:78:52:88:cd:82:c7:92:3a:ce:cb:c6:07:05:ec:70: + 0e:e8:db:44:8f:3b:f3:41:de:b2:19:b0:f6:e0:5a:06:48:d9: + b9:e2:2b:0f:ec:ec:1f:fb:83:4d:80:d4:6e:34:ed:78:a1:be: + a2:cb:07:ab +-----BEGIN CERTIFICATE----- +MIIEvjCCA6agAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBnjELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMR8wHQYDVQQDDBZ3b2xmU1NMIE9DU1Ag +UmVzcG9uZGVyMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuLojtPbDexTDpPUdYaH1HmO5hSM0 +UG34fKKKBIvVdVwt92OI0Qd66gtFNSvrH7EitJRBOOKddNaLMCIQUcXbyj9GK/7l +Wj9BdGd1lamU1cPuQviN65KV4dllt0PEGN4WgJDOJDUhxFWsWlHgLi2zClpPSnMx +UO5KFr05i60FSIexmeIQpwZyZ8pc0Ze9yPF2+OBK7LyT9GZMKHHR2GYDtJAwuxew +/pf1HujHXZuLERkSPKuCcXj/rj8ysghxshuMJ6wRuNhDSc+wcLHwjK7aJIcXO9gE +ZWwAdlDvFQjXtHNoJhSHlcNfbmG4h4T6gBoKi5jz4/9ORBxldHxxVGXlOQIDAQAB +o4IBCjCCAQYwCQYDVR0TBAIwADAdBgNVHQ4EFgQUMmfhsXnSgfyfIwxwQFC1Rla4 +MDYwgcQGA1UdIwSBvDCBuYAUc7AcpC+Cy89HpTjXsASCOn5yFSGhgZ2kgZowgZcx +CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0 +dGxlMRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEYMBYG +A1UEAwwPd29sZlNTTCByb290IENBMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tggFjMBMGA1UdJQQMMAoGCCsGAQUFBwMJMA0GCSqGSIb3DQEBCwUAA4IB +AQCbVsVfubIAMMoFKujGlrqqI0BAiW2iepPyyYpvDl1fb85eSzip0quXeONzPT0n +6QDOFtnFxQao68bldkz3YBpprjXW+A/anIPG+3SmEuXHZK7nLLbTYh/zIBEuCZsU +8KMX0Cy+Sjk6VVgvkDcExVQnnQ5Rl9oh3wXsynmoygLKz7cF7wT6+YEgEMF9SqeT +EygemKc+TAETw2sU4Yc3XzrTfbbU2Q1Wk38d6cI1xxF/QtDVPV/2/CMk40V/T54Y +33tBgPq7vRbh68V4UojNgseSOs7LxgcF7HAO6NtEjzvzQd6yGbD24FoGSNm54isP +7Owf+4NNgNRuNO14ob6iywer +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 99 (0x63) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:2c:b4:2f:1d:06:09:ef:4e:29:86:84:7e:cc: + bf:a6:79:7c:f0:c0:c1:64:25:8c:75:b7:10:05:ca: + 48:27:0c:0e:32:1c:b0:fe:99:85:39:b6:b9:a2:f7: + 27:ff:6d:3c:8c:16:73:29:21:7f:8b:a6:54:71:90: + ad:cc:05:b9:9f:15:c7:0a:3f:5f:69:f4:0a:5f:8c: + 71:b5:2c:bf:66:e2:03:9a:32:f4:d2:ec:2a:89:4b: + f9:35:88:14:33:47:4e:2e:05:79:01:ed:64:36:76: + b9:f8:85:cd:01:88:ac:c5:b2:b1:59:b8:cd:5a:f4: + 09:09:38:9b:da:5a:cf:ce:78:99:1f:49:3d:41:d6: + 06:7c:52:99:c8:97:d1:b3:80:3a:a2:4f:36:c4:c5: + 96:30:77:31:38:c8:70:cc:e1:67:06:b3:2b:2f:93: + b5:69:cf:83:7e:88:53:9b:0f:46:21:4c:d6:05:36: + 44:99:60:68:47:e5:32:01:12:d4:10:73:ae:9a:34: + 94:fa:6e:b8:58:4f:7b:5b:8a:92:97:ad:fd:97:b9: + 75:ca:c2:d4:45:7d:17:6b:cd:2f:f3:63:7a:0e:30: + b5:0b:a9:d9:a6:7c:74:60:9d:cc:09:03:43:f1:0f: + 90:d3:b7:fe:6c:9f:d9:cd:78:4b:15:ae:8c:5b:f9: + 99:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 6b:10:b1:f8:cb:77:ef:72:f5:f8:fc:70:6d:18:dc:34:fe:d7: + 95:d8:fd:85:8e:ca:4b:f3:be:1f:eb:14:08:dc:23:34:78:98: + 39:d7:9f:c3:52:f6:14:3d:e9:de:5c:c2:d8:b1:4b:a8:4c:5b: + 91:42:66:da:7f:3c:e9:03:20:5e:08:0f:76:79:b9:21:10:89: + b7:73:46:44:7e:6e:28:0c:00:e4:f4:3e:65:aa:f5:c6:27:57: + 2c:bb:1d:ae:e5:94:57:a3:73:9e:6b:44:00:35:4a:f3:c7:34: + 9c:a2:a7:aa:62:9f:1d:ef:a8:6c:be:07:ad:ef:ae:ee:93:0b: + ba:c3:59:4e:90:40:2d:00:5e:f0:0f:0a:de:18:2a:b3:97:31: + 63:84:ff:18:1c:b6:d8:7d:ee:33:ed:99:f0:f5:7f:88:58:b3: + 0d:90:db:eb:44:7e:06:37:61:d4:34:b9:f6:fd:3e:8d:07:e4: + b5:b0:ae:09:ce:98:e4:b0:1b:d5:7b:53:94:dd:8a:b2:20:d6: + b0:72:f8:b1:bc:76:df:16:86:39:7b:e4:a9:15:47:57:ae:ca: + 41:d6:3a:ba:15:d1:c0:b5:38:66:0b:0f:80:8b:a2:07:b4:fc: + 80:1f:a3:4c:1f:d2:65:97:c1:2c:ae:46:31:61:49:0d:d7:5f: + ac:d2:a6:05 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIBYzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBlzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NMIHJvb3Qg +Q0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCrLLQvHQYJ704phoR+zL+meXzwwMFkJYx1txAF +ykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRxkK3MBbmfFccKP19p9ApfjHG1 +LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4hc0BiKzFsrFZuM1a9AkJOJva +Ws/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4yHDM4WcGsysvk7Vpz4N+iFOb +D0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tbipKXrf2XuXXKwtRFfRdrzS/z +Y3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsVroxb+ZmBAgMBAAGjggE5MIIB +NTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRzsBykL4LLz0elONewBII6fnIVITCB +xAYDVR0jBIG8MIG5gBRzsBykL4LLz0elONewBII6fnIVIaGBnaSBmjCBlzELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +EDAOBgNVBAoMB3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQD +DA93b2xmU1NMIHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b22CAWMwCwYDVR0PBAQDAgEGMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW +aHR0cDovLzEyNy4wLjAuMToyMjIyMDANBgkqhkiG9w0BAQsFAAOCAQEAaxCx+Mt3 +73L1+PxwbRjcNP7Xldj9hY7KS/O+H+sUCNwjNHiYOdefw1L2FD3p3lzC2LFLqExb +kUJm2n886QMgXggPdnm5IRCJt3NGRH5uKAwA5PQ+Zar1xidXLLsdruWUV6NznmtE +ADVK88c0nKKnqmKfHe+obL4Hre+u7pMLusNZTpBALQBe8A8K3hgqs5cxY4T/GBy2 +2H3uM+2Z8PV/iFizDZDb60R+Bjdh1DS59v0+jQfktbCuCc6Y5LAb1XtTlN2KsiDW +sHL4sbx23xaGOXvkqRVHV67KQdY6uhXRwLU4ZgsPgIuiB7T8gB+jTB/SZZfBLK5G +MWFJDddfrNKmBQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/ocsp-responder-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/ocsp-responder-key.pem new file mode 100644 index 000000000..61c5616a9 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/ocsp-responder-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAuLojtPbDexTDpPUdYaH1HmO5hSM0UG34fKKKBIvVdVwt92OI +0Qd66gtFNSvrH7EitJRBOOKddNaLMCIQUcXbyj9GK/7lWj9BdGd1lamU1cPuQviN +65KV4dllt0PEGN4WgJDOJDUhxFWsWlHgLi2zClpPSnMxUO5KFr05i60FSIexmeIQ +pwZyZ8pc0Ze9yPF2+OBK7LyT9GZMKHHR2GYDtJAwuxew/pf1HujHXZuLERkSPKuC +cXj/rj8ysghxshuMJ6wRuNhDSc+wcLHwjK7aJIcXO9gEZWwAdlDvFQjXtHNoJhSH +lcNfbmG4h4T6gBoKi5jz4/9ORBxldHxxVGXlOQIDAQABAoIBAGI2tR1VxYD+/TYL +DGAIV+acZtqeaQYKMf8x++eG4SrQo6/QP8HDFFqzO0yV2SC0cRtJZ5PzCHxCRSaG +Nd8EL2NMWOazUwW0c/yLtTypOPSeg2Mf+3SwLvgxOZ9CbFQ8YAJi+vbNOPLGCijL +N0HWEkcC1P1kWWgKCWIloR7eEt0IQOb5PPSCu3buq/rForb6qUf+L+ESpWed6bnc +uhIrHDuQ/PopW05fW1r61zI286wKdLRyatQsljNqPvVdFVhtCKqCqMHdIzMg2cbh +q9DJMWc/KLjzBk6YPMZKm/4k4RXj+IwS+iITbpUNrhYj2TMevBMPW3AIRobD823D +ehQv+rECgYEA3CWL+G9zJ5PXRDAdQ69lN+CE/Uf9444CN5idMO+qRQ+QE8hWYT/U +PFH/aUgd1k3WJZseR/GTWx29VsRPSDWZXzwzLfUNKnqvp0b2oZe/EdYiRSo8OCPp +kF07HbTKe4Cyma7HdgDkNkS+UW5JujnuLcuee+wTq6xU0289juwFBc8CgYEA1s/d +VtwXqBf3qMxfi+eMa77fqxptAFGtZNKNkYwX42Ow6Hehj8EnoPqYEF+9MzKn/BFh +ROnQ76axKBN8mkRUjpv7d2+zMlDnGrWul8q6VrfGiU2P7jd4L6GY/V1MYktnIBsd +Ld/jW8P0FFfI2RIREPWdrATxBhQpTJfXd/7rLncCgYB1wrvyBCQUSrg/KIGvADbj +wf1Bw23jeMZk2QVU9Q8e7ClE+8iBMvSj47T9q28SgQaJjUWQdIA/oFP1AwPp+4n0 +cK5r6gbF72Tg1Uv+ur6hmuswFlyqJ0O8TrLdvCUIFZr0LJNT4zwwb2tjAdz8ehqX +crFvVqRbE884XuwN9ODm7wKBgQDIEnKlI/kkpq4UmcWkGNXAxNauFr7PPUOyVCln +FoRpVcC/xCzGJ7ExTjWzing950BulgFynhPsIeV+3id/x4S6Dq34YCEXDCMzzWQA +HOHRQvm3iHY1+ZQHSQulb/Bk3LYAQUC8KXspTSlYiSqYgytCEIH6Zd/XOY/9tq8J +JHUHoQKBgHYIB2mRCuDK5C3dCspdPVeAUqptK1nnXxWY/MXA6v+M4wFsIxV7Iwg7 +HEjeD5yKH4619syPCFz3jrCxL0oJqVTD2tnrbLf8idEt2eaV/3o2mUGFjvWpTywg +F8DewhrGh6z7FWHp4cMrxpq1hkdi6k+481T1GKBJ1zBSTzskTHQB +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/openssl.cnf b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/openssl.cnf new file mode 100644 index 000000000..c518d33a5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/openssl.cnf @@ -0,0 +1,42 @@ +# +# openssl configuration file for OCSP certificates +# + +# Extensions to add to a certificate request (intermediate1-ca) +[ v3_req1 ] +basicConstraints = CA:false +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +authorityInfoAccess = OCSP;URI:http://127.0.0.1:22221 + +# Extensions to add to a certificate request (intermediate2-ca) +[ v3_req2 ] +basicConstraints = CA:false +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +authorityInfoAccess = OCSP;URI:http://127.0.0.1:22222 + +# Extensions to add to a certificate request (intermediate3-ca) +[ v3_req3 ] +basicConstraints = CA:false +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +authorityInfoAccess = OCSP;URI:http://127.0.0.1:22223 + +# Extensions for a typical CA +[ v3_ca ] +basicConstraints = CA:true +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = keyCertSign, cRLSign +authorityInfoAccess = OCSP;URI:http://127.0.0.1:22220 + +# OCSP extensions. +[ v3_ocsp ] +basicConstraints = CA:false +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +extendedKeyUsage = OCSPSigning diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/renewcerts-for-test.sh b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/renewcerts-for-test.sh new file mode 100644 index 000000000..7bae1005d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/renewcerts-for-test.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +# $1 cert, $2 name, $3 ca, $4 extensions, $5 serial +update_cert(){ + + openssl req \ + -new \ + -key $1-key.pem \ + -out $1-cert.csr \ + -subj "/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=$2/emailAddress=info@wolfssl.com" + + openssl x509 \ + -req -in $1-cert.csr \ + -extfile $6 \ + -extensions $4 \ + -days 1000 \ + -CA $3-cert.pem \ + -CAkey $3-key.pem \ + -set_serial $5 \ + -out $1-cert.pem \ + -sha256 + + rm $1-cert.csr + openssl x509 -in $1-cert.pem -text > $1_tmp.pem + mv $1_tmp.pem $1-cert.pem + cat $3-cert.pem >> $1-cert.pem +} + + + +printf '%s\n' "Using CNF: $1" + +openssl req \ + -new \ + -key root-ca-key.pem \ + -out root-ca-cert.csr \ + -subj "/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com" + +openssl x509 \ + -req -in root-ca-cert.csr \ + -extfile $1 \ + -extensions v3_ca \ + -days 1000 \ + -signkey root-ca-key.pem \ + -set_serial 99 \ + -out root-ca-cert.pem \ + -sha256 + +rm root-ca-cert.csr +openssl x509 -in root-ca-cert.pem -text > tmp.pem +mv tmp.pem root-ca-cert.pem + +update_cert intermediate1-ca "wolfSSL intermediate CA 1" root-ca v3_ca 01 $1 +update_cert intermediate2-ca "wolfSSL intermediate CA 2" root-ca v3_ca 02 $1 +update_cert intermediate3-ca "wolfSSL REVOKED intermediate CA" root-ca v3_ca 03 $1 # REVOKED + +update_cert ocsp-responder "wolfSSL OCSP Responder" root-ca v3_ocsp 04 $1 + +update_cert server1 "www1.wolfssl.com" intermediate1-ca v3_req1 05 $1 +update_cert server2 "www2.wolfssl.com" intermediate1-ca v3_req1 06 $1 # REVOKED +update_cert server3 "www3.wolfssl.com" intermediate2-ca v3_req2 07 $1 +update_cert server4 "www4.wolfssl.com" intermediate2-ca v3_req2 08 $1 # REVOKED +update_cert server5 "www5.wolfssl.com" intermediate3-ca v3_req3 09 $1 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/root-ca-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/root-ca-cert.pem new file mode 100644 index 000000000..a6fb14512 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/root-ca-cert.pem @@ -0,0 +1,93 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 99 (0x63) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:2c:b4:2f:1d:06:09:ef:4e:29:86:84:7e:cc: + bf:a6:79:7c:f0:c0:c1:64:25:8c:75:b7:10:05:ca: + 48:27:0c:0e:32:1c:b0:fe:99:85:39:b6:b9:a2:f7: + 27:ff:6d:3c:8c:16:73:29:21:7f:8b:a6:54:71:90: + ad:cc:05:b9:9f:15:c7:0a:3f:5f:69:f4:0a:5f:8c: + 71:b5:2c:bf:66:e2:03:9a:32:f4:d2:ec:2a:89:4b: + f9:35:88:14:33:47:4e:2e:05:79:01:ed:64:36:76: + b9:f8:85:cd:01:88:ac:c5:b2:b1:59:b8:cd:5a:f4: + 09:09:38:9b:da:5a:cf:ce:78:99:1f:49:3d:41:d6: + 06:7c:52:99:c8:97:d1:b3:80:3a:a2:4f:36:c4:c5: + 96:30:77:31:38:c8:70:cc:e1:67:06:b3:2b:2f:93: + b5:69:cf:83:7e:88:53:9b:0f:46:21:4c:d6:05:36: + 44:99:60:68:47:e5:32:01:12:d4:10:73:ae:9a:34: + 94:fa:6e:b8:58:4f:7b:5b:8a:92:97:ad:fd:97:b9: + 75:ca:c2:d4:45:7d:17:6b:cd:2f:f3:63:7a:0e:30: + b5:0b:a9:d9:a6:7c:74:60:9d:cc:09:03:43:f1:0f: + 90:d3:b7:fe:6c:9f:d9:cd:78:4b:15:ae:8c:5b:f9: + 99:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 6b:10:b1:f8:cb:77:ef:72:f5:f8:fc:70:6d:18:dc:34:fe:d7: + 95:d8:fd:85:8e:ca:4b:f3:be:1f:eb:14:08:dc:23:34:78:98: + 39:d7:9f:c3:52:f6:14:3d:e9:de:5c:c2:d8:b1:4b:a8:4c:5b: + 91:42:66:da:7f:3c:e9:03:20:5e:08:0f:76:79:b9:21:10:89: + b7:73:46:44:7e:6e:28:0c:00:e4:f4:3e:65:aa:f5:c6:27:57: + 2c:bb:1d:ae:e5:94:57:a3:73:9e:6b:44:00:35:4a:f3:c7:34: + 9c:a2:a7:aa:62:9f:1d:ef:a8:6c:be:07:ad:ef:ae:ee:93:0b: + ba:c3:59:4e:90:40:2d:00:5e:f0:0f:0a:de:18:2a:b3:97:31: + 63:84:ff:18:1c:b6:d8:7d:ee:33:ed:99:f0:f5:7f:88:58:b3: + 0d:90:db:eb:44:7e:06:37:61:d4:34:b9:f6:fd:3e:8d:07:e4: + b5:b0:ae:09:ce:98:e4:b0:1b:d5:7b:53:94:dd:8a:b2:20:d6: + b0:72:f8:b1:bc:76:df:16:86:39:7b:e4:a9:15:47:57:ae:ca: + 41:d6:3a:ba:15:d1:c0:b5:38:66:0b:0f:80:8b:a2:07:b4:fc: + 80:1f:a3:4c:1f:d2:65:97:c1:2c:ae:46:31:61:49:0d:d7:5f: + ac:d2:a6:05 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIBYzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBlzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NMIHJvb3Qg +Q0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCrLLQvHQYJ704phoR+zL+meXzwwMFkJYx1txAF +ykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRxkK3MBbmfFccKP19p9ApfjHG1 +LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4hc0BiKzFsrFZuM1a9AkJOJva +Ws/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4yHDM4WcGsysvk7Vpz4N+iFOb +D0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tbipKXrf2XuXXKwtRFfRdrzS/z +Y3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsVroxb+ZmBAgMBAAGjggE5MIIB +NTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRzsBykL4LLz0elONewBII6fnIVITCB +xAYDVR0jBIG8MIG5gBRzsBykL4LLz0elONewBII6fnIVIaGBnaSBmjCBlzELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +EDAOBgNVBAoMB3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQD +DA93b2xmU1NMIHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b22CAWMwCwYDVR0PBAQDAgEGMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW +aHR0cDovLzEyNy4wLjAuMToyMjIyMDANBgkqhkiG9w0BAQsFAAOCAQEAaxCx+Mt3 +73L1+PxwbRjcNP7Xldj9hY7KS/O+H+sUCNwjNHiYOdefw1L2FD3p3lzC2LFLqExb +kUJm2n886QMgXggPdnm5IRCJt3NGRH5uKAwA5PQ+Zar1xidXLLsdruWUV6NznmtE +ADVK88c0nKKnqmKfHe+obL4Hre+u7pMLusNZTpBALQBe8A8K3hgqs5cxY4T/GBy2 +2H3uM+2Z8PV/iFizDZDb60R+Bjdh1DS59v0+jQfktbCuCc6Y5LAb1XtTlN2KsiDW +sHL4sbx23xaGOXvkqRVHV67KQdY6uhXRwLU4ZgsPgIuiB7T8gB+jTB/SZZfBLK5G +MWFJDddfrNKmBQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/root-ca-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/root-ca-key.pem new file mode 100644 index 000000000..a7cbcbb60 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/root-ca-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCrLLQvHQYJ704p +hoR+zL+meXzwwMFkJYx1txAFykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRx +kK3MBbmfFccKP19p9ApfjHG1LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4 +hc0BiKzFsrFZuM1a9AkJOJvaWs/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4 +yHDM4WcGsysvk7Vpz4N+iFObD0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tb +ipKXrf2XuXXKwtRFfRdrzS/zY3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsV +roxb+ZmBAgMBAAECggEAd0Qjm3wOfBeYD0jhwnOoyTZ2vkyfssaS0mYlrNMfaM12 +iqYBELQo5miReaHZ5ZfYCweNX8guVUAkMCiNX81RYy3KTDKRqYJXQ/HYPFMcXXP2 +7Ja6jMfub1FXJ1xULtJs/5XilVwxad1ZgHbBu2LedrUl6wzfUJMeRKWDuiVyCzpK +J2+F1iVH+whBI/eN8qopHM4JeR0W9k7rFJayQZ9iAIfrl2In1hTay9S7HCEdmWz/ +BVI818QXsgCuulR9G2erS0gS181P090YcZeuzh5YfvAnzn7m8BTboJojix5pkfQt +gM5E7YD4nYU1V796P2cfAaMJoQyCW4NSn+kwgLT5rQKBgQDXnHvs/fk+gxFiBt/U +tRfU+iUoiMofrcAZswMBvOZVy40RbtxuNXwnGo9+Bko7XVKekVO6TGUyPSpv1VXR +QCjlk+PsXyx0DD2+Hb3r69wXJ3Wfxe0K+p6CHIuspJUmNrHdpJOBTO8GbHNxuaD/ +kDJvBq+ZkXEKUm9a5BeU5WiwMwKBgQDLPUkr+Mm2pJIIEBF8z3Lr3bWIbZsinxhM +ErQRAQC0J+oBj1kuUoXYoh1hzQK/E90bM2fRUMhgVGIBvwDMv0c+Z2Fb6zK0r3mP +dOLYGOrfavl/f7zhd4TjzPkAF1fbbYbciFQIWW3//q8PXY68eKvwrhGqT+CCwLef +tWC3xrpLewKBgQC7Ht7abgxa+UsjxQ2Kv+O//Zw0EotAdP2sEBUC9Br+yJpUT99U +cmyeT0nLONBBtxtV7JA6tcR5lmX3CrHg2Yrku7XqVSrySBFppsxGLLslCSTnFdJE +Xf8ksntxyKB8uqkgz40IgWlMLOEACPc19MIgYzAQ2g29xI9J1Xy1x2dUywKBgBFo +HVU7yKLw82TnY2gKKHCVG5Akuw27DIyvaWavbE0BwiQCEARMoxQLxnJy6ZJN9Dj5 +LSIbRh4h/AbkQgBHPaXVmtwRh9U71jB4NVmGwM8DzXyjBx1UbDhKfOUKGsc7WTqY +HoJcjnRHbtzlCW2Q9ED316F7l+H6+X8fPLpgteHzAoGARc6B/pWJWkUVM87ObGmr +hiA5YByyC6Rq8HyFEeXiS2fiQPfQF0UC9Qxq9/CBkezb8v+Yb/UT4ieL26c270s5 +JkyYqMoBLgkOKG6nPDD4hxoR24cFmC090RNQOhwwHskh+KjVmf3c/m9wNBSdHTpt +URu+xdmbaoKaH9dIJMUKasc= +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server1-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server1-cert.pem new file mode 100644 index 000000000..f41c534f5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server1-cert.pem @@ -0,0 +1,279 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 5 (0x5) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL intermediate CA 1/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=www1.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:e6:96:55:75:cf:8a:97:68:8c:b6:38:f6:7a:05: + be:33:b6:51:47:37:8a:f7:db:91:be:92:6b:b7:00: + 8c:f2:c5:24:6e:18:e9:92:00:81:01:dc:b3:4c:28: + a9:b7:80:f1:96:cf:23:7a:2f:ae:f8:e3:0f:2d:d3: + 5e:23:e7:db:4c:b2:5d:89:16:17:be:be:81:db:fb: + 12:6d:28:4b:10:a0:12:04:27:c1:c9:d0:79:95:ef: + e8:8d:8c:59:9b:4e:72:7d:bc:49:2b:22:4e:f8:4f: + e2:0c:f1:e9:e9:97:f9:df:8c:5a:0a:aa:38:1d:43: + 04:a3:a7:89:a1:e2:83:a4:4b:b5:4e:45:88:a6:22: + 5d:ac:a9:58:67:88:c1:d5:61:ef:bd:11:05:27:94: + 47:bb:33:a5:8a:ca:ee:1f:8d:c0:6e:24:af:cd:ca: + bf:80:47:71:95:ac:a9:f1:5d:23:6c:f5:4b:b4:a9: + e1:c4:66:fb:e5:c4:a1:9f:a7:51:d1:78:cd:2e:b4: + 3f:2e:e2:82:f3:7f:c4:a7:f4:31:cf:76:27:3f:db: + 2e:d2:6e:c3:47:23:82:a3:48:40:8c:a7:c1:13:f0: + 63:50:54:43:f6:71:12:e1:6f:a5:7a:58:26:f7:fd: + 8b:3b:70:18:a0:43:ba:01:6b:b3:f8:d5:be:05:13: + 64:31 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Key Identifier: + CC:55:15:00:E2:44:89:92:63:6D:10:5D:B9:9E:73:B6:5D:3A:19:CA + X509v3 Authority Key Identifier: + keyid:83:C6:3A:89:2C:81:F4:02:D7:9D:4C:E2:2A:C0:71:82:64:44:DA:0E + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:01 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Authority Information Access: + OCSP - URI:http://127.0.0.1:22221 + + Signature Algorithm: sha256WithRSAEncryption + 13:fc:55:34:0b:04:b3:16:06:81:b7:11:e8:ec:b4:37:3e:52: + 21:50:8a:48:3f:9b:3d:80:04:8e:d1:8e:b2:0f:84:f8:0a:8c: + 79:6e:65:e3:33:5f:29:9c:39:2b:3c:20:80:96:94:ee:87:2e: + 4a:05:7e:a7:30:8f:d8:ea:56:6d:ce:4b:e5:23:34:80:b1:cb: + 37:11:39:ad:60:3d:ce:87:d1:af:96:3c:53:03:5e:50:c9:70: + ab:d1:38:ba:ea:53:d8:17:03:59:42:f3:cf:8f:68:98:31:4b: + 6b:8f:e6:67:b6:42:d1:9d:24:b5:ab:d3:40:81:bd:6d:d4:d7: + 8a:0d:49:11:eb:b6:be:27:d2:bb:f2:6d:3c:7e:e4:f4:d4:f1: + 03:88:57:8b:25:ce:3e:6e:62:2c:01:9d:1f:c1:11:15:ab:37: + 5a:56:1f:75:aa:5a:70:ac:57:d1:8a:38:c1:e5:a1:b0:1f:33: + e3:84:7d:6b:f9:1a:f2:0a:9c:fa:ed:10:41:ad:56:57:9d:76: + d0:d8:3d:ac:fd:f5:13:3d:01:8e:a3:2c:8f:bd:ab:4d:a9:39: + 52:c9:76:a2:80:49:18:20:8b:4b:85:86:11:1e:19:d1:26:6c: + 92:72:2c:28:eb:38:67:ce:a0:d3:4f:7c:f7:a8:fe:1a:3f:17: + 83:2b:b6:9a +-----BEGIN CERTIFICATE----- +MIIE7jCCA9agAwIBAgIBBTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSIwIAYDVQQDDBl3b2xmU1NM +IGludGVybWVkaWF0ZSBDQSAxMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE4MDQxMzE1MjMxMFoXDTIxMDEwNzE1MjMxMFowgZgxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYD +VQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEZMBcGA1UEAwwQd3d3 +MS53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOaWVXXPipdojLY49noFvjO2 +UUc3ivfbkb6Sa7cAjPLFJG4Y6ZIAgQHcs0woqbeA8ZbPI3ovrvjjDy3TXiPn20yy +XYkWF76+gdv7Em0oSxCgEgQnwcnQeZXv6I2MWZtOcn28SSsiTvhP4gzx6emX+d+M +WgqqOB1DBKOniaHig6RLtU5FiKYiXaypWGeIwdVh770RBSeUR7szpYrK7h+NwG4k +r83Kv4BHcZWsqfFdI2z1S7Sp4cRm++XEoZ+nUdF4zS60Py7igvN/xKf0Mc92Jz/b +LtJuw0cjgqNIQIynwRPwY1BUQ/ZxEuFvpXpYJvf9iztwGKBDugFrs/jVvgUTZDEC +AwEAAaOCATYwggEyMAkGA1UdEwQCMAAwHQYDVR0OBBYEFMxVFQDiRImSY20QXbme +c7ZdOhnKMIHEBgNVHSMEgbwwgbmAFIPGOoksgfQC151M4irAcYJkRNoOoYGdpIGa +MIGXMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwH +U2VhdHRsZTEQMA4GA1UECgwHd29sZlNTTDEUMBIGA1UECwwLRW5naW5lZXJpbmcx +GDAWBgNVBAMMD3dvbGZTU0wgcm9vdCBDQTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3 +b2xmc3NsLmNvbYIBATALBgNVHQ8EBAMCBeAwMgYIKwYBBQUHAQEEJjAkMCIGCCsG +AQUFBzABhhZodHRwOi8vMTI3LjAuMC4xOjIyMjIxMA0GCSqGSIb3DQEBCwUAA4IB +AQAT/FU0CwSzFgaBtxHo7LQ3PlIhUIpIP5s9gASO0Y6yD4T4Cox5bmXjM18pnDkr +PCCAlpTuhy5KBX6nMI/Y6lZtzkvlIzSAscs3ETmtYD3Oh9GvljxTA15QyXCr0Ti6 +6lPYFwNZQvPPj2iYMUtrj+ZntkLRnSS1q9NAgb1t1NeKDUkR67a+J9K78m08fuT0 +1PEDiFeLJc4+bmIsAZ0fwREVqzdaVh91qlpwrFfRijjB5aGwHzPjhH1r+RryCpz6 +7RBBrVZXnXbQ2D2s/fUTPQGOoyyPvatNqTlSyXaigEkYIItLhYYRHhnRJmySciwo +6zhnzqDTT3z3qP4aPxeDK7aa +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL intermediate CA 1/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:de:b4:c8:5c:77:e0:2d:b1:f5:b9:ad:16:47:35: + a0:35:65:65:c6:e1:40:ab:1e:b4:b9:13:b7:cb:8c: + bb:77:a5:76:da:6d:87:87:f6:4a:4d:13:e4:26:3e: + 27:87:ee:5b:c7:6a:3f:45:30:61:55:5c:f6:35:d1: + 65:fa:98:11:a3:a7:55:d5:be:91:82:4b:fc:be:90: + d6:50:53:63:9a:2c:22:e1:35:11:dc:78:02:97:8a: + e4:46:92:9c:53:08:76:de:1f:53:b6:b8:ca:77:3e: + 79:6e:bc:d0:e3:0d:30:5b:4c:f6:94:0d:30:29:64: + 9f:04:e5:db:fb:89:60:67:bb:af:26:83:51:77:24: + 2f:2b:0b:a1:94:81:10:98:e8:eb:26:a8:1e:7c:e4: + c4:6c:67:06:95:55:4a:dd:52:f4:f2:60:6d:01:2b: + 19:91:35:6d:a4:08:47:06:71:24:00:d9:de:c6:56: + f3:8b:53:2c:e2:9a:96:a5:f3:62:e5:c4:e3:23:f2: + d2:fc:21:ea:0f:62:76:8d:d5:99:48:ce:dc:58:c4: + bb:7f:da:94:2c:80:74:83:c5:e0:b0:15:7e:41:fd: + 0e:f2:f4:f0:78:76:7b:ad:26:0d:aa:48:96:17:2f: + 21:e3:95:2b:26:37:f9:aa:80:2f:fe:de:f6:5e:bc: + 97:7f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 83:C6:3A:89:2C:81:F4:02:D7:9D:4C:E2:2A:C0:71:82:64:44:DA:0E + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 18:a3:09:fe:c3:53:c7:ce:11:f0:36:86:43:9c:46:9b:43:42: + a0:20:6e:b6:32:29:34:22:fa:27:a1:00:0c:e5:51:c3:35:7b: + 2f:ce:2c:48:7f:47:cf:1b:45:f9:30:b2:d0:17:15:a0:c3:a8: + 3a:e4:5f:a4:96:e4:25:ea:4e:80:90:2e:8d:f5:19:98:ae:2a: + 6d:39:f0:06:8f:e6:0b:c4:2b:dd:07:4a:ad:3d:34:11:79:3d: + 15:db:65:c6:33:60:6b:2f:2d:47:26:bb:91:53:28:35:5c:fd: + 57:3b:27:1b:a1:85:03:24:74:84:f4:f2:b2:e3:53:41:83:9c: + 6b:5a:0c:0f:3b:c4:5f:a7:4b:8b:04:f2:0d:f5:81:aa:16:33: + d2:f4:f5:8d:83:c1:10:2d:57:55:f8:d3:16:62:27:50:b2:57: + 20:1d:a3:07:0c:b8:8d:c5:5a:2f:d9:d3:c4:6a:c3:1e:51:10: + de:7e:60:cf:d0:78:2c:00:d4:da:df:de:de:ee:ed:1d:25:da: + 6c:9f:57:69:2a:f1:a2:6c:8a:fe:72:c0:57:9f:f8:6e:b7:47: + f1:4f:f6:4b:9c:a2:2a:d2:10:9c:4e:bc:b4:8a:a2:8e:51:5a: + c1:e7:9c:f1:7c:9c:f9:7d:d7:9c:8f:ed:e9:57:91:0a:6c:4b: + b4:ac:6f:30 +-----BEGIN CERTIFICATE----- +MIIE8DCCA9igAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBoTELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSIwIAYDVQQDDBl3b2xmU1NMIGludGVy +bWVkaWF0ZSBDQSAxMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3rTIXHfgLbH1ua0WRzWgNWVl +xuFAqx60uRO3y4y7d6V22m2Hh/ZKTRPkJj4nh+5bx2o/RTBhVVz2NdFl+pgRo6dV +1b6Rgkv8vpDWUFNjmiwi4TUR3HgCl4rkRpKcUwh23h9TtrjKdz55brzQ4w0wW0z2 +lA0wKWSfBOXb+4lgZ7uvJoNRdyQvKwuhlIEQmOjrJqgefOTEbGcGlVVK3VL08mBt +ASsZkTVtpAhHBnEkANnexlbzi1Ms4pqWpfNi5cTjI/LS/CHqD2J2jdWZSM7cWMS7 +f9qULIB0g8XgsBV+Qf0O8vTweHZ7rSYNqkiWFy8h45UrJjf5qoAv/t72XryXfwID +AQABo4IBOTCCATUwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUg8Y6iSyB9ALXnUzi +KsBxgmRE2g4wgcQGA1UdIwSBvDCBuYAUc7AcpC+Cy89HpTjXsASCOn5yFSGhgZ2k +gZowgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEYMBYGA1UEAwwPd29sZlNTTCByb290IENBMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tggFjMAsGA1UdDwQEAwIBBjAyBggrBgEFBQcBAQQmMCQwIgYI +KwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjAwDQYJKoZIhvcNAQELBQAD +ggEBABijCf7DU8fOEfA2hkOcRptDQqAgbrYyKTQi+iehAAzlUcM1ey/OLEh/R88b +RfkwstAXFaDDqDrkX6SW5CXqToCQLo31GZiuKm058AaP5gvEK90HSq09NBF5PRXb +ZcYzYGsvLUcmu5FTKDVc/Vc7JxuhhQMkdIT08rLjU0GDnGtaDA87xF+nS4sE8g31 +gaoWM9L09Y2DwRAtV1X40xZiJ1CyVyAdowcMuI3FWi/Z08Rqwx5REN5+YM/QeCwA +1Nrf3t7u7R0l2myfV2kq8aJsiv5ywFef+G63R/FP9kucoirSEJxOvLSKoo5RWsHn +nPF8nPl915yP7elXkQpsS7SsbzA= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 99 (0x63) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:2c:b4:2f:1d:06:09:ef:4e:29:86:84:7e:cc: + bf:a6:79:7c:f0:c0:c1:64:25:8c:75:b7:10:05:ca: + 48:27:0c:0e:32:1c:b0:fe:99:85:39:b6:b9:a2:f7: + 27:ff:6d:3c:8c:16:73:29:21:7f:8b:a6:54:71:90: + ad:cc:05:b9:9f:15:c7:0a:3f:5f:69:f4:0a:5f:8c: + 71:b5:2c:bf:66:e2:03:9a:32:f4:d2:ec:2a:89:4b: + f9:35:88:14:33:47:4e:2e:05:79:01:ed:64:36:76: + b9:f8:85:cd:01:88:ac:c5:b2:b1:59:b8:cd:5a:f4: + 09:09:38:9b:da:5a:cf:ce:78:99:1f:49:3d:41:d6: + 06:7c:52:99:c8:97:d1:b3:80:3a:a2:4f:36:c4:c5: + 96:30:77:31:38:c8:70:cc:e1:67:06:b3:2b:2f:93: + b5:69:cf:83:7e:88:53:9b:0f:46:21:4c:d6:05:36: + 44:99:60:68:47:e5:32:01:12:d4:10:73:ae:9a:34: + 94:fa:6e:b8:58:4f:7b:5b:8a:92:97:ad:fd:97:b9: + 75:ca:c2:d4:45:7d:17:6b:cd:2f:f3:63:7a:0e:30: + b5:0b:a9:d9:a6:7c:74:60:9d:cc:09:03:43:f1:0f: + 90:d3:b7:fe:6c:9f:d9:cd:78:4b:15:ae:8c:5b:f9: + 99:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 6b:10:b1:f8:cb:77:ef:72:f5:f8:fc:70:6d:18:dc:34:fe:d7: + 95:d8:fd:85:8e:ca:4b:f3:be:1f:eb:14:08:dc:23:34:78:98: + 39:d7:9f:c3:52:f6:14:3d:e9:de:5c:c2:d8:b1:4b:a8:4c:5b: + 91:42:66:da:7f:3c:e9:03:20:5e:08:0f:76:79:b9:21:10:89: + b7:73:46:44:7e:6e:28:0c:00:e4:f4:3e:65:aa:f5:c6:27:57: + 2c:bb:1d:ae:e5:94:57:a3:73:9e:6b:44:00:35:4a:f3:c7:34: + 9c:a2:a7:aa:62:9f:1d:ef:a8:6c:be:07:ad:ef:ae:ee:93:0b: + ba:c3:59:4e:90:40:2d:00:5e:f0:0f:0a:de:18:2a:b3:97:31: + 63:84:ff:18:1c:b6:d8:7d:ee:33:ed:99:f0:f5:7f:88:58:b3: + 0d:90:db:eb:44:7e:06:37:61:d4:34:b9:f6:fd:3e:8d:07:e4: + b5:b0:ae:09:ce:98:e4:b0:1b:d5:7b:53:94:dd:8a:b2:20:d6: + b0:72:f8:b1:bc:76:df:16:86:39:7b:e4:a9:15:47:57:ae:ca: + 41:d6:3a:ba:15:d1:c0:b5:38:66:0b:0f:80:8b:a2:07:b4:fc: + 80:1f:a3:4c:1f:d2:65:97:c1:2c:ae:46:31:61:49:0d:d7:5f: + ac:d2:a6:05 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIBYzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBlzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NMIHJvb3Qg +Q0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCrLLQvHQYJ704phoR+zL+meXzwwMFkJYx1txAF +ykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRxkK3MBbmfFccKP19p9ApfjHG1 +LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4hc0BiKzFsrFZuM1a9AkJOJva +Ws/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4yHDM4WcGsysvk7Vpz4N+iFOb +D0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tbipKXrf2XuXXKwtRFfRdrzS/z +Y3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsVroxb+ZmBAgMBAAGjggE5MIIB +NTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRzsBykL4LLz0elONewBII6fnIVITCB +xAYDVR0jBIG8MIG5gBRzsBykL4LLz0elONewBII6fnIVIaGBnaSBmjCBlzELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +EDAOBgNVBAoMB3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQD +DA93b2xmU1NMIHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b22CAWMwCwYDVR0PBAQDAgEGMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW +aHR0cDovLzEyNy4wLjAuMToyMjIyMDANBgkqhkiG9w0BAQsFAAOCAQEAaxCx+Mt3 +73L1+PxwbRjcNP7Xldj9hY7KS/O+H+sUCNwjNHiYOdefw1L2FD3p3lzC2LFLqExb +kUJm2n886QMgXggPdnm5IRCJt3NGRH5uKAwA5PQ+Zar1xidXLLsdruWUV6NznmtE +ADVK88c0nKKnqmKfHe+obL4Hre+u7pMLusNZTpBALQBe8A8K3hgqs5cxY4T/GBy2 +2H3uM+2Z8PV/iFizDZDb60R+Bjdh1DS59v0+jQfktbCuCc6Y5LAb1XtTlN2KsiDW +sHL4sbx23xaGOXvkqRVHV67KQdY6uhXRwLU4ZgsPgIuiB7T8gB+jTB/SZZfBLK5G +MWFJDddfrNKmBQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server1-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server1-key.pem new file mode 100644 index 000000000..e44f63129 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server1-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDmllV1z4qXaIy2 +OPZ6Bb4ztlFHN4r325G+kmu3AIzyxSRuGOmSAIEB3LNMKKm3gPGWzyN6L6744w8t +014j59tMsl2JFhe+voHb+xJtKEsQoBIEJ8HJ0HmV7+iNjFmbTnJ9vEkrIk74T+IM +8enpl/nfjFoKqjgdQwSjp4mh4oOkS7VORYimIl2sqVhniMHVYe+9EQUnlEe7M6WK +yu4fjcBuJK/Nyr+AR3GVrKnxXSNs9Uu0qeHEZvvlxKGfp1HReM0utD8u4oLzf8Sn +9DHPdic/2y7SbsNHI4KjSECMp8ET8GNQVEP2cRLhb6V6WCb3/Ys7cBigQ7oBa7P4 +1b4FE2QxAgMBAAECggEBAMcAl2DFbOae5FGfd5h3vF8EycCcvuKKLI4775pQb1RV +r8sU1P+cT7o7rsHblh04u0dcHVImNOu3ijISaPyz7R+UEAVve66y23/uf0iVrbL7 +cpEDfsudkFFGa30901elrEm3Za5EPcMvrfdeEHH5Jz02876giS032ZkjzjRYOSRg +TuFhiqjRTMfE6AB63KSRWcb6AYEocHV/jF+IEQcz9ctsv6XKKKJtge4+Y3+gQU4N +ALUE6OjBsD5KpMVuMYBSfTucYi5g2eOK05PoCOR8lTqgvsbof+ALj+84zEpG20aK +p0KdMVwiMolXaYcvKBOGPxZKt7sQaIMitbs0iuErMQECgYEA+cLVZh4qkRnsjPVc +/27qC/VLeWo2QAL7TWC7YgkY0MgNtZXRkJZdKOlzYWo/iJmuxHj7eUFLkoHpPNV2 +X6WG+CGHD1qq/BqLQNlJKS/MtI2VNzOjBJ/J3SktOGo3BwL+Q5uSRNHukQip0YnD +c9GCU4UhfBHr/UNitMBH6N5aPqUCgYEA7FjjTGomVseF5wNbfw2xLjBmRuQ2DDgJ +/OvCtV6it+OiVU9R+cYcz/hVl1QLIkGBHt5hb8O6np4tW5ehKd5LNTtolIO+/BLL +2xPZCLY7U+LES5dgUTC/wb5t5igAmPuOMi9qNQ1kYxbKYJVLRUdwfOM8FNE4gjZF +kj2BIb6OxZ0CgYEAmuXXvWZ2FdmTGHTPwWdDZjkyHtHdZWO0AXA9pnZn2oxH3FdX +SinHCymFsmPXlVtixV0W8UOqn+lMAruMl5MsGtWIUuBzbLj1pjlcI1wOw+ePJFY1 +AxgqdKwl7HgLOqEDmmBwnZfpMi/CSj77ZegIwM2vT6g5yK+zFtCtiGHmbDUCgYBf +L2VLbyzFolGBOk7tGnyTF5b5UguaXC9ZlzGxjc2Gtby5Etr29xy/fUorSgO55hu0 +bOdc9b0BCL9HtgeILyim5ag2t+CA8Kj9MD8mTQ4TuK5Jq0t1J2bzBliIau/irN0V +xRbHCv+1EIas4zOPUTgyc+nMkH5roqPeQ7rv9ijV2QKBgQDJiNmAJv3dlie2x+bj +rX5RDF1Q/egVVGx41jPyuzh0oFLwEQG2lSHEAKgF+gWt0ZMwNzPB9oue2LBSpNFl +7ZdpFCpzD+3OcaxnWYEGT+qNhczbf0PvVNBOzOI33Trr7maktWi0Mh9qmXqoNuwG +uCnrEriJlBk2MV88tIG/ZJ+bvQ== +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server2-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server2-cert.pem new file mode 100644 index 000000000..455d18de5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server2-cert.pem @@ -0,0 +1,279 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 6 (0x6) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL intermediate CA 1/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=www2.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c6:35:8a:e8:aa:bd:33:c9:5e:84:43:67:42:65: + 2a:3c:e3:89:b4:a6:67:a1:3b:ee:6d:85:d1:d3:2b: + 6e:b1:62:d4:f1:22:43:a0:d5:b7:a5:7d:b5:f5:6c: + 09:06:7c:8c:ef:87:af:4f:34:ce:27:eb:f3:4a:37: + 57:c3:d7:d8:ee:e4:a0:77:65:2c:a7:c2:10:65:6b: + 7b:48:c4:d8:28:fe:4c:4e:4f:7e:2f:20:c4:49:5b: + 71:38:40:0d:36:a3:57:b3:44:da:be:cd:54:14:15: + 66:0f:d3:05:08:f2:2e:03:67:2e:5c:5d:e1:b0:e6: + c0:25:8f:58:77:5b:d3:d7:a8:22:ea:56:d3:0e:01: + 6d:38:34:56:47:aa:12:c4:ba:2a:ef:ec:18:f5:d4: + db:b9:fa:6f:dc:50:eb:ee:10:a2:14:b5:9a:12:e1: + e3:85:0f:79:14:b8:70:6d:0d:1c:1d:38:57:85:6a: + 82:0c:d6:bd:2c:bf:20:f1:28:2e:f6:34:80:a7:0d: + 32:82:35:4f:c1:b1:e5:9e:26:d5:f8:b9:39:57:43: + ef:ed:f1:10:5c:3e:32:ba:d9:e4:9e:40:cd:28:ea: + 26:46:9b:a9:34:8d:9f:b9:fd:45:7d:14:f7:ce:ca: + 3b:85:87:a7:64:74:9c:65:29:18:b3:f5:b1:ad:92: + 62:39 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Key Identifier: + 7D:6D:FD:F6:0B:4F:3F:4A:62:91:F5:F3:13:60:51:86:C3:5A:9F:D6 + X509v3 Authority Key Identifier: + keyid:83:C6:3A:89:2C:81:F4:02:D7:9D:4C:E2:2A:C0:71:82:64:44:DA:0E + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:01 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Authority Information Access: + OCSP - URI:http://127.0.0.1:22221 + + Signature Algorithm: sha256WithRSAEncryption + 1d:d0:b5:1d:a1:ae:ef:5e:36:00:36:b3:ae:22:13:32:37:22: + 00:24:b6:b9:c2:b3:a2:55:e5:de:e1:82:83:e9:78:5c:a1:50: + 62:c3:ca:92:2f:21:aa:85:d9:26:56:b1:b0:a1:3c:1f:41:ca: + e6:1a:a3:b0:c1:b1:4c:d2:c0:ab:55:dc:fa:e9:d6:46:63:83: + 2f:8e:c5:ec:28:0e:a9:e5:1b:d9:de:2b:8a:5d:58:56:3a:f8: + 88:bd:99:c4:3a:33:6a:83:4a:26:aa:e3:74:40:a4:82:5a:b2: + 26:23:3b:6d:aa:09:bc:c0:78:2c:c4:75:74:f1:19:e9:ad:39: + 74:53:11:6d:ad:33:b2:f8:45:51:06:f5:5b:19:fd:a7:26:d1: + 11:77:09:f4:c5:07:97:a1:fe:36:3a:6a:fb:64:f1:ed:9b:c4: + 4c:64:cd:6a:bf:17:b8:5b:3f:b7:36:20:4a:cc:34:3e:ec:f5: + a2:68:ae:8d:87:e5:4e:e3:c0:d8:70:67:6a:3c:41:04:0a:36: + 07:40:52:6c:97:15:52:d3:13:a0:fb:c5:b7:f1:c9:40:03:40: + e6:1e:fb:b0:11:77:80:fa:ec:17:24:88:ca:e6:17:1b:b4:f3: + b2:38:bc:bf:c2:98:ec:69:14:c9:2e:75:99:6c:16:78:cc:c5: + 36:d9:0f:f0 +-----BEGIN CERTIFICATE----- +MIIE7jCCA9agAwIBAgIBBjANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSIwIAYDVQQDDBl3b2xmU1NM +IGludGVybWVkaWF0ZSBDQSAxMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE4MDQxMzE1MjMxMFoXDTIxMDEwNzE1MjMxMFowgZgxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYD +VQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEZMBcGA1UEAwwQd3d3 +Mi53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMY1iuiqvTPJXoRDZ0JlKjzj +ibSmZ6E77m2F0dMrbrFi1PEiQ6DVt6V9tfVsCQZ8jO+Hr080zifr80o3V8PX2O7k +oHdlLKfCEGVre0jE2Cj+TE5Pfi8gxElbcThADTajV7NE2r7NVBQVZg/TBQjyLgNn +Llxd4bDmwCWPWHdb09eoIupW0w4BbTg0VkeqEsS6Ku/sGPXU27n6b9xQ6+4QohS1 +mhLh44UPeRS4cG0NHB04V4VqggzWvSy/IPEoLvY0gKcNMoI1T8Gx5Z4m1fi5OVdD +7+3xEFw+MrrZ5J5AzSjqJkabqTSNn7n9RX0U987KO4WHp2R0nGUpGLP1sa2SYjkC +AwEAAaOCATYwggEyMAkGA1UdEwQCMAAwHQYDVR0OBBYEFH1t/fYLTz9KYpH18xNg +UYbDWp/WMIHEBgNVHSMEgbwwgbmAFIPGOoksgfQC151M4irAcYJkRNoOoYGdpIGa +MIGXMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwH +U2VhdHRsZTEQMA4GA1UECgwHd29sZlNTTDEUMBIGA1UECwwLRW5naW5lZXJpbmcx +GDAWBgNVBAMMD3dvbGZTU0wgcm9vdCBDQTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3 +b2xmc3NsLmNvbYIBATALBgNVHQ8EBAMCBeAwMgYIKwYBBQUHAQEEJjAkMCIGCCsG +AQUFBzABhhZodHRwOi8vMTI3LjAuMC4xOjIyMjIxMA0GCSqGSIb3DQEBCwUAA4IB +AQAd0LUdoa7vXjYANrOuIhMyNyIAJLa5wrOiVeXe4YKD6XhcoVBiw8qSLyGqhdkm +VrGwoTwfQcrmGqOwwbFM0sCrVdz66dZGY4MvjsXsKA6p5RvZ3iuKXVhWOviIvZnE +OjNqg0omquN0QKSCWrImIzttqgm8wHgsxHV08RnprTl0UxFtrTOy+EVRBvVbGf2n +JtERdwn0xQeXof42Omr7ZPHtm8RMZM1qvxe4Wz+3NiBKzDQ+7PWiaK6Nh+VO48DY +cGdqPEEECjYHQFJslxVS0xOg+8W38clAA0DmHvuwEXeA+uwXJIjK5hcbtPOyOLy/ +wpjsaRTJLnWZbBZ4zMU22Q/w +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL intermediate CA 1/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:de:b4:c8:5c:77:e0:2d:b1:f5:b9:ad:16:47:35: + a0:35:65:65:c6:e1:40:ab:1e:b4:b9:13:b7:cb:8c: + bb:77:a5:76:da:6d:87:87:f6:4a:4d:13:e4:26:3e: + 27:87:ee:5b:c7:6a:3f:45:30:61:55:5c:f6:35:d1: + 65:fa:98:11:a3:a7:55:d5:be:91:82:4b:fc:be:90: + d6:50:53:63:9a:2c:22:e1:35:11:dc:78:02:97:8a: + e4:46:92:9c:53:08:76:de:1f:53:b6:b8:ca:77:3e: + 79:6e:bc:d0:e3:0d:30:5b:4c:f6:94:0d:30:29:64: + 9f:04:e5:db:fb:89:60:67:bb:af:26:83:51:77:24: + 2f:2b:0b:a1:94:81:10:98:e8:eb:26:a8:1e:7c:e4: + c4:6c:67:06:95:55:4a:dd:52:f4:f2:60:6d:01:2b: + 19:91:35:6d:a4:08:47:06:71:24:00:d9:de:c6:56: + f3:8b:53:2c:e2:9a:96:a5:f3:62:e5:c4:e3:23:f2: + d2:fc:21:ea:0f:62:76:8d:d5:99:48:ce:dc:58:c4: + bb:7f:da:94:2c:80:74:83:c5:e0:b0:15:7e:41:fd: + 0e:f2:f4:f0:78:76:7b:ad:26:0d:aa:48:96:17:2f: + 21:e3:95:2b:26:37:f9:aa:80:2f:fe:de:f6:5e:bc: + 97:7f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 83:C6:3A:89:2C:81:F4:02:D7:9D:4C:E2:2A:C0:71:82:64:44:DA:0E + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 18:a3:09:fe:c3:53:c7:ce:11:f0:36:86:43:9c:46:9b:43:42: + a0:20:6e:b6:32:29:34:22:fa:27:a1:00:0c:e5:51:c3:35:7b: + 2f:ce:2c:48:7f:47:cf:1b:45:f9:30:b2:d0:17:15:a0:c3:a8: + 3a:e4:5f:a4:96:e4:25:ea:4e:80:90:2e:8d:f5:19:98:ae:2a: + 6d:39:f0:06:8f:e6:0b:c4:2b:dd:07:4a:ad:3d:34:11:79:3d: + 15:db:65:c6:33:60:6b:2f:2d:47:26:bb:91:53:28:35:5c:fd: + 57:3b:27:1b:a1:85:03:24:74:84:f4:f2:b2:e3:53:41:83:9c: + 6b:5a:0c:0f:3b:c4:5f:a7:4b:8b:04:f2:0d:f5:81:aa:16:33: + d2:f4:f5:8d:83:c1:10:2d:57:55:f8:d3:16:62:27:50:b2:57: + 20:1d:a3:07:0c:b8:8d:c5:5a:2f:d9:d3:c4:6a:c3:1e:51:10: + de:7e:60:cf:d0:78:2c:00:d4:da:df:de:de:ee:ed:1d:25:da: + 6c:9f:57:69:2a:f1:a2:6c:8a:fe:72:c0:57:9f:f8:6e:b7:47: + f1:4f:f6:4b:9c:a2:2a:d2:10:9c:4e:bc:b4:8a:a2:8e:51:5a: + c1:e7:9c:f1:7c:9c:f9:7d:d7:9c:8f:ed:e9:57:91:0a:6c:4b: + b4:ac:6f:30 +-----BEGIN CERTIFICATE----- +MIIE8DCCA9igAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBoTELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSIwIAYDVQQDDBl3b2xmU1NMIGludGVy +bWVkaWF0ZSBDQSAxMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3rTIXHfgLbH1ua0WRzWgNWVl +xuFAqx60uRO3y4y7d6V22m2Hh/ZKTRPkJj4nh+5bx2o/RTBhVVz2NdFl+pgRo6dV +1b6Rgkv8vpDWUFNjmiwi4TUR3HgCl4rkRpKcUwh23h9TtrjKdz55brzQ4w0wW0z2 +lA0wKWSfBOXb+4lgZ7uvJoNRdyQvKwuhlIEQmOjrJqgefOTEbGcGlVVK3VL08mBt +ASsZkTVtpAhHBnEkANnexlbzi1Ms4pqWpfNi5cTjI/LS/CHqD2J2jdWZSM7cWMS7 +f9qULIB0g8XgsBV+Qf0O8vTweHZ7rSYNqkiWFy8h45UrJjf5qoAv/t72XryXfwID +AQABo4IBOTCCATUwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUg8Y6iSyB9ALXnUzi +KsBxgmRE2g4wgcQGA1UdIwSBvDCBuYAUc7AcpC+Cy89HpTjXsASCOn5yFSGhgZ2k +gZowgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEYMBYGA1UEAwwPd29sZlNTTCByb290IENBMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tggFjMAsGA1UdDwQEAwIBBjAyBggrBgEFBQcBAQQmMCQwIgYI +KwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjAwDQYJKoZIhvcNAQELBQAD +ggEBABijCf7DU8fOEfA2hkOcRptDQqAgbrYyKTQi+iehAAzlUcM1ey/OLEh/R88b +RfkwstAXFaDDqDrkX6SW5CXqToCQLo31GZiuKm058AaP5gvEK90HSq09NBF5PRXb +ZcYzYGsvLUcmu5FTKDVc/Vc7JxuhhQMkdIT08rLjU0GDnGtaDA87xF+nS4sE8g31 +gaoWM9L09Y2DwRAtV1X40xZiJ1CyVyAdowcMuI3FWi/Z08Rqwx5REN5+YM/QeCwA +1Nrf3t7u7R0l2myfV2kq8aJsiv5ywFef+G63R/FP9kucoirSEJxOvLSKoo5RWsHn +nPF8nPl915yP7elXkQpsS7SsbzA= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 99 (0x63) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:2c:b4:2f:1d:06:09:ef:4e:29:86:84:7e:cc: + bf:a6:79:7c:f0:c0:c1:64:25:8c:75:b7:10:05:ca: + 48:27:0c:0e:32:1c:b0:fe:99:85:39:b6:b9:a2:f7: + 27:ff:6d:3c:8c:16:73:29:21:7f:8b:a6:54:71:90: + ad:cc:05:b9:9f:15:c7:0a:3f:5f:69:f4:0a:5f:8c: + 71:b5:2c:bf:66:e2:03:9a:32:f4:d2:ec:2a:89:4b: + f9:35:88:14:33:47:4e:2e:05:79:01:ed:64:36:76: + b9:f8:85:cd:01:88:ac:c5:b2:b1:59:b8:cd:5a:f4: + 09:09:38:9b:da:5a:cf:ce:78:99:1f:49:3d:41:d6: + 06:7c:52:99:c8:97:d1:b3:80:3a:a2:4f:36:c4:c5: + 96:30:77:31:38:c8:70:cc:e1:67:06:b3:2b:2f:93: + b5:69:cf:83:7e:88:53:9b:0f:46:21:4c:d6:05:36: + 44:99:60:68:47:e5:32:01:12:d4:10:73:ae:9a:34: + 94:fa:6e:b8:58:4f:7b:5b:8a:92:97:ad:fd:97:b9: + 75:ca:c2:d4:45:7d:17:6b:cd:2f:f3:63:7a:0e:30: + b5:0b:a9:d9:a6:7c:74:60:9d:cc:09:03:43:f1:0f: + 90:d3:b7:fe:6c:9f:d9:cd:78:4b:15:ae:8c:5b:f9: + 99:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 6b:10:b1:f8:cb:77:ef:72:f5:f8:fc:70:6d:18:dc:34:fe:d7: + 95:d8:fd:85:8e:ca:4b:f3:be:1f:eb:14:08:dc:23:34:78:98: + 39:d7:9f:c3:52:f6:14:3d:e9:de:5c:c2:d8:b1:4b:a8:4c:5b: + 91:42:66:da:7f:3c:e9:03:20:5e:08:0f:76:79:b9:21:10:89: + b7:73:46:44:7e:6e:28:0c:00:e4:f4:3e:65:aa:f5:c6:27:57: + 2c:bb:1d:ae:e5:94:57:a3:73:9e:6b:44:00:35:4a:f3:c7:34: + 9c:a2:a7:aa:62:9f:1d:ef:a8:6c:be:07:ad:ef:ae:ee:93:0b: + ba:c3:59:4e:90:40:2d:00:5e:f0:0f:0a:de:18:2a:b3:97:31: + 63:84:ff:18:1c:b6:d8:7d:ee:33:ed:99:f0:f5:7f:88:58:b3: + 0d:90:db:eb:44:7e:06:37:61:d4:34:b9:f6:fd:3e:8d:07:e4: + b5:b0:ae:09:ce:98:e4:b0:1b:d5:7b:53:94:dd:8a:b2:20:d6: + b0:72:f8:b1:bc:76:df:16:86:39:7b:e4:a9:15:47:57:ae:ca: + 41:d6:3a:ba:15:d1:c0:b5:38:66:0b:0f:80:8b:a2:07:b4:fc: + 80:1f:a3:4c:1f:d2:65:97:c1:2c:ae:46:31:61:49:0d:d7:5f: + ac:d2:a6:05 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIBYzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBlzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NMIHJvb3Qg +Q0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCrLLQvHQYJ704phoR+zL+meXzwwMFkJYx1txAF +ykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRxkK3MBbmfFccKP19p9ApfjHG1 +LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4hc0BiKzFsrFZuM1a9AkJOJva +Ws/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4yHDM4WcGsysvk7Vpz4N+iFOb +D0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tbipKXrf2XuXXKwtRFfRdrzS/z +Y3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsVroxb+ZmBAgMBAAGjggE5MIIB +NTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRzsBykL4LLz0elONewBII6fnIVITCB +xAYDVR0jBIG8MIG5gBRzsBykL4LLz0elONewBII6fnIVIaGBnaSBmjCBlzELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +EDAOBgNVBAoMB3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQD +DA93b2xmU1NMIHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b22CAWMwCwYDVR0PBAQDAgEGMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW +aHR0cDovLzEyNy4wLjAuMToyMjIyMDANBgkqhkiG9w0BAQsFAAOCAQEAaxCx+Mt3 +73L1+PxwbRjcNP7Xldj9hY7KS/O+H+sUCNwjNHiYOdefw1L2FD3p3lzC2LFLqExb +kUJm2n886QMgXggPdnm5IRCJt3NGRH5uKAwA5PQ+Zar1xidXLLsdruWUV6NznmtE +ADVK88c0nKKnqmKfHe+obL4Hre+u7pMLusNZTpBALQBe8A8K3hgqs5cxY4T/GBy2 +2H3uM+2Z8PV/iFizDZDb60R+Bjdh1DS59v0+jQfktbCuCc6Y5LAb1XtTlN2KsiDW +sHL4sbx23xaGOXvkqRVHV67KQdY6uhXRwLU4ZgsPgIuiB7T8gB+jTB/SZZfBLK5G +MWFJDddfrNKmBQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server2-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server2-key.pem new file mode 100644 index 000000000..e4b6181e8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server2-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDGNYroqr0zyV6E +Q2dCZSo844m0pmehO+5thdHTK26xYtTxIkOg1belfbX1bAkGfIzvh69PNM4n6/NK +N1fD19ju5KB3ZSynwhBla3tIxNgo/kxOT34vIMRJW3E4QA02o1ezRNq+zVQUFWYP +0wUI8i4DZy5cXeGw5sAlj1h3W9PXqCLqVtMOAW04NFZHqhLEuirv7Bj11Nu5+m/c +UOvuEKIUtZoS4eOFD3kUuHBtDRwdOFeFaoIM1r0svyDxKC72NICnDTKCNU/BseWe +JtX4uTlXQ+/t8RBcPjK62eSeQM0o6iZGm6k0jZ+5/UV9FPfOyjuFh6dkdJxlKRiz +9bGtkmI5AgMBAAECggEAL6rWwke1gsvNyD8xiR0tQEF0b5aJW5Q/LeW95WwPjed3 +0Jnt67MaHFmUNfaKYR35Au39si2/2of7FYEjwTyatjETikMxrxKTwOBNYN2+InWt +wjOJ5CmcKwwruVxmERrNT5aiiLp2mvHefrXAAzvC5xycYKhPS6zizuWfX+0ckEM5 +yJnl8TRTjfqExxHS1ciTY4B1w8nfWdYY/xiQW23sCPZ8toqsqAuHJjREmMcj+oer +z8Md1tZNa0ujDy0ejSovCnqzWIi4Umg3SndhRDYKNRAFGPNQmYRM+EWEqQufMaXP +ghD+Heb5RUPSkNW98KdjDGK4WiIeqF45tb+YQ4AvgQKBgQDt2X+FMHG/s7FAEAxA +x6TzIcDedqwEKtO3JbaC+Q0FKwRTGwP1tGOnyqbVrw4cSlza5EvUnK8CZK9I2HFd +qfbP3rtFCtHl9/bpVZPNkaVImzqkfmzmGJIREsCDIPu8THFNyxL2TC27VKCNsSmZ +ui2tuxRJ6/O0DroGdvdnFL89SQKBgQDVVaZjiA5Cr1e5Eo6q3dNNeMSBfTuI90Ja +W1OmVovp2yWYjfFFTW2B9vb4RDaRvIuykGhHgAnGKGmHtv7f0GlY7n6Qr0czvyn5 +6s+fRVIcPzEaTVnxC1g20+XHc41XdqnIOcaUjUz7oqC6g7+Y56WKdvvKitV0Lb98 +ua7ZOM6tcQKBgGWtRMY7H2VD+9HXCmXm8qy9ESYItSBS7o6soIj8zoQXD5I3SkoP +A0sHZqqSWwXdBDTOw1vwXyA2ynfpjwzrS4cxP/0T0wbsKbE11ClcybtwIHGRWhxD +BK4nxgRIZVTpmMYYudJwXlxmoPvxcEc3P6+0+cdgBp5CbWO2F60JQXeBAoGAHxLs +u46z1Q7JTlHfqg/JmX0/0kS1iUvKxHKNCquMkbG0FjaGsDuI+edJLfxxnmTCTG4w +YknKIqz8QiJrmZo33hZPJTACxQzRRm/nciGcxjSGKHif4zZt0P6od5bjPZwxOtL/ +k9/JGNYlZ0WNgO4s9LBEGMqEMPoA7F/3kfhuUmECgYEA6WzFZjs31OqTLE0vnCfL +/b/wPeozaAyjtR/24TNkAFwP/LrBAA5gFOoL8p94ce87yXdm80x3bK6OGbNmor7c +qT/OJgnXV1wTrKYSkFUu7LTC7DihpYy2MqyGg8xGxB4kK1IR+ROB4v3c5RkIqaGF +lTSpXFge771NjCimucIOl/Y= +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server3-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server3-cert.pem new file mode 100644 index 000000000..34cc27c12 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server3-cert.pem @@ -0,0 +1,279 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7 (0x7) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL intermediate CA 2/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=www3.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:be:19:65:1e:17:39:d4:33:fc:97:64:69:80:51: + fb:6c:7c:ca:e1:ba:2a:ab:d2:dd:30:61:f3:2e:47: + c1:d4:33:c0:ff:53:21:ba:2d:14:a6:b9:7c:66:ca: + 45:7b:1c:7d:8f:fc:75:f3:9a:69:f1:6c:25:46:a0: + 92:5d:00:93:e3:22:a6:60:b9:97:05:37:7f:a1:aa: + cd:22:81:72:b1:22:47:3d:7c:8d:46:55:bc:32:4d: + d2:84:43:5c:15:43:07:22:70:36:39:93:1b:e8:a1: + 46:bb:02:85:ba:1d:31:ac:b1:3c:84:5b:eb:8f:1f: + 62:8a:71:52:9e:0b:63:b6:e6:d6:46:cc:19:06:d6: + bb:06:81:e4:0b:25:14:6c:63:94:70:1a:27:37:95: + 24:40:07:30:f5:24:73:c3:bd:f9:0e:5f:b6:cd:4f: + 18:88:f0:d7:a3:9b:f5:b0:1e:fe:04:03:a5:8d:73: + f7:6b:31:74:85:fd:61:fa:9e:53:37:75:90:e6:f8: + b5:98:66:e8:52:4d:4a:4c:39:05:65:c1:34:f9:c6: + 95:27:b0:07:c1:51:96:a8:82:1b:22:cf:41:df:de: + b4:94:b7:0d:ba:61:fb:f4:40:7c:a1:fc:a2:29:a3: + 47:4d:b4:94:9d:7b:51:ec:e4:13:fb:cd:e9:26:ca: + a7:93 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Key Identifier: + C1:CD:C0:2C:34:F4:3B:BB:E3:CA:98:35:7D:6A:15:33:94:5C:11:3A + X509v3 Authority Key Identifier: + keyid:05:D1:BA:86:00:A2:EE:2A:05:24:B7:11:AD:2D:60:F1:90:14:8F:17 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:02 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Authority Information Access: + OCSP - URI:http://127.0.0.1:22222 + + Signature Algorithm: sha256WithRSAEncryption + 4e:22:d8:3b:f8:92:f0:1a:0d:6f:94:a6:88:d8:27:b8:28:a4: + 86:4a:2f:4e:6e:ed:38:62:8e:6d:d8:de:33:e9:9d:c8:b1:a8: + f2:0a:66:b8:17:f0:34:79:c0:bf:4a:0b:fe:00:c3:38:db:c0: + 40:1b:84:22:58:b1:e6:60:87:c8:28:f7:52:5c:2b:02:cf:3d: + d4:28:84:3c:cb:74:8a:5a:da:4b:50:ce:95:81:ef:df:c8:dd: + 45:f0:8d:a0:62:3e:4a:b3:d8:0b:3d:d9:75:d5:0d:43:65:01: + fc:f4:70:92:ae:f9:30:6c:21:7c:17:d4:b6:00:1d:97:7b:e6: + 1d:c4:9f:a7:d5:00:87:e7:bd:5a:80:ba:14:9f:56:fc:f1:b5: + f8:ed:14:61:1c:24:7f:ac:39:03:41:dc:c2:da:b2:2e:df:06: + 70:6a:81:1d:6d:a6:e4:cf:f1:5a:c8:80:8d:ea:13:f3:3b:73: + 17:41:87:f2:fa:25:c8:47:73:86:d5:ba:e3:8f:ab:f7:f0:b1: + 1f:b7:33:57:0f:76:01:5c:59:55:fe:13:05:69:2c:e1:02:85: + ac:28:72:48:f7:2d:8c:6b:da:72:fa:95:d5:8f:23:1d:d0:37: + 5d:70:97:af:53:aa:37:11:5d:9e:c3:79:da:bf:c2:01:f3:32: + a2:e4:b0:bd +-----BEGIN CERTIFICATE----- +MIIE7jCCA9agAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSIwIAYDVQQDDBl3b2xmU1NM +IGludGVybWVkaWF0ZSBDQSAyMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE4MDQxMzE1MjMxMFoXDTIxMDEwNzE1MjMxMFowgZgxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYD +VQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEZMBcGA1UEAwwQd3d3 +My53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL4ZZR4XOdQz/JdkaYBR+2x8 +yuG6KqvS3TBh8y5HwdQzwP9TIbotFKa5fGbKRXscfY/8dfOaafFsJUagkl0Ak+Mi +pmC5lwU3f6GqzSKBcrEiRz18jUZVvDJN0oRDXBVDByJwNjmTG+ihRrsChbodMayx +PIRb648fYopxUp4LY7bm1kbMGQbWuwaB5AslFGxjlHAaJzeVJEAHMPUkc8O9+Q5f +ts1PGIjw16Ob9bAe/gQDpY1z92sxdIX9YfqeUzd1kOb4tZhm6FJNSkw5BWXBNPnG +lSewB8FRlqiCGyLPQd/etJS3Dbph+/RAfKH8oimjR020lJ17UezkE/vN6SbKp5MC +AwEAAaOCATYwggEyMAkGA1UdEwQCMAAwHQYDVR0OBBYEFMHNwCw09Du748qYNX1q +FTOUXBE6MIHEBgNVHSMEgbwwgbmAFAXRuoYAou4qBSS3Ea0tYPGQFI8XoYGdpIGa +MIGXMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwH +U2VhdHRsZTEQMA4GA1UECgwHd29sZlNTTDEUMBIGA1UECwwLRW5naW5lZXJpbmcx +GDAWBgNVBAMMD3dvbGZTU0wgcm9vdCBDQTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3 +b2xmc3NsLmNvbYIBAjALBgNVHQ8EBAMCBeAwMgYIKwYBBQUHAQEEJjAkMCIGCCsG +AQUFBzABhhZodHRwOi8vMTI3LjAuMC4xOjIyMjIyMA0GCSqGSIb3DQEBCwUAA4IB +AQBOItg7+JLwGg1vlKaI2Ce4KKSGSi9Obu04Yo5t2N4z6Z3IsajyCma4F/A0ecC/ +Sgv+AMM428BAG4QiWLHmYIfIKPdSXCsCzz3UKIQ8y3SKWtpLUM6Vge/fyN1F8I2g +Yj5Ks9gLPdl11Q1DZQH89HCSrvkwbCF8F9S2AB2Xe+YdxJ+n1QCH571agLoUn1b8 +8bX47RRhHCR/rDkDQdzC2rIu3wZwaoEdbabkz/FayICN6hPzO3MXQYfy+iXIR3OG +1brjj6v38LEftzNXD3YBXFlV/hMFaSzhAoWsKHJI9y2Ma9py+pXVjyMd0DddcJev +U6o3EV2ew3nav8IB8zKi5LC9 +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL intermediate CA 2/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d0:20:3c:35:19:6f:2c:44:b4:7e:42:c7:75:b4: + 6a:2b:a9:23:85:bf:87:b4:ee:ca:d7:4b:1f:31:d7: + 11:02:a1:ab:58:3d:fb:dc:51:ca:3a:1d:1f:95:a6: + 56:82:f7:8f:ff:6b:50:bb:ea:10:e1:47:1d:35:77: + 2e:4b:28:c5:53:46:23:2b:82:fd:5a:d3:f4:21:db: + 0e:e0:f2:76:33:47:b3:00:be:3a:b1:23:98:53:eb: + ea:a0:de:1b:cc:05:4e:ee:63:a8:2c:93:24:d6:98: + 78:74:03:e4:c8:89:43:61:f1:25:b8:cd:3b:87:c1: + 31:25:fd:ba:4c:fc:29:94:45:9e:69:d7:67:0a:8a: + 8e:d5:52:93:30:a2:0e:dd:6a:1c:b0:94:77:db:52: + 52:b7:89:21:be:96:75:24:cb:e9:49:df:81:9d:9d: + f8:55:7d:01:2a:eb:78:03:12:e2:20:6e:db:63:35: + cd:a1:96:f0:f8:8c:20:35:69:87:01:ca:b4:54:36: + a0:15:e0:23:7d:b9:fb:be:99:05:50:f0:bf:ec:7f: + 12:e1:3d:75:15:4e:c8:c2:30:e6:8b:fe:e5:8b:55: + f8:44:5e:e5:e3:56:e0:66:2d:6f:42:5a:45:6b:96: + aa:c7:5d:41:08:5f:ce:d7:dc:9f:20:e4:46:78:ff: + d9:99 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 05:D1:BA:86:00:A2:EE:2A:05:24:B7:11:AD:2D:60:F1:90:14:8F:17 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 92:6e:c1:af:88:af:46:f2:6e:8a:8c:27:06:8e:b4:38:35:9b: + 47:92:24:20:e5:a5:13:d8:35:d3:2e:37:ca:74:47:e5:16:a3: + 03:63:16:b4:28:2b:d9:04:ab:ee:e4:0a:e5:87:da:d4:00:3a: + 53:c6:c9:25:6a:8f:49:d2:2e:34:f2:40:65:6e:02:fc:b9:42: + 3f:ef:cb:8c:79:84:03:84:dc:a0:68:1e:c7:c7:36:8c:60:14: + 55:f2:5f:f9:c1:3f:2b:f6:a2:1e:34:1f:83:ba:73:bc:b7:62: + bc:97:66:84:09:b9:2d:76:71:c8:91:fd:e2:e1:39:cf:dd:ec: + 98:a8:49:69:89:a8:18:2a:42:e7:fc:ab:2c:cf:13:ab:63:fe: + b0:19:ea:1a:38:22:16:11:31:34:43:fc:50:c6:ec:19:97:03: + db:e8:07:28:48:88:3a:e5:35:a2:fd:83:12:df:55:70:72:61: + 0d:f8:66:18:52:58:c9:46:97:86:31:9e:a2:43:0c:b9:0f:d3: + eb:35:c9:e5:19:4e:b4:8b:d2:ac:ea:bf:83:2a:48:9d:20:a0: + 08:45:60:92:8a:27:06:93:77:74:bb:0e:22:8e:54:17:f2:d4: + e7:7f:f3:90:4d:cc:75:e7:16:c5:9c:4a:cf:dc:f2:19:18:12: + f5:72:8e:2e +-----BEGIN CERTIFICATE----- +MIIE8DCCA9igAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBoTELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSIwIAYDVQQDDBl3b2xmU1NMIGludGVy +bWVkaWF0ZSBDQSAyMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0CA8NRlvLES0fkLHdbRqK6kj +hb+HtO7K10sfMdcRAqGrWD373FHKOh0flaZWgveP/2tQu+oQ4UcdNXcuSyjFU0Yj +K4L9WtP0IdsO4PJ2M0ezAL46sSOYU+vqoN4bzAVO7mOoLJMk1ph4dAPkyIlDYfEl +uM07h8ExJf26TPwplEWeaddnCoqO1VKTMKIO3WocsJR321JSt4khvpZ1JMvpSd+B +nZ34VX0BKut4AxLiIG7bYzXNoZbw+IwgNWmHAcq0VDagFeAjfbn7vpkFUPC/7H8S +4T11FU7IwjDmi/7li1X4RF7l41bgZi1vQlpFa5aqx11BCF/O19yfIORGeP/ZmQID +AQABo4IBOTCCATUwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUBdG6hgCi7ioFJLcR +rS1g8ZAUjxcwgcQGA1UdIwSBvDCBuYAUc7AcpC+Cy89HpTjXsASCOn5yFSGhgZ2k +gZowgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEYMBYGA1UEAwwPd29sZlNTTCByb290IENBMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tggFjMAsGA1UdDwQEAwIBBjAyBggrBgEFBQcBAQQmMCQwIgYI +KwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjAwDQYJKoZIhvcNAQELBQAD +ggEBAJJuwa+Ir0byboqMJwaOtDg1m0eSJCDlpRPYNdMuN8p0R+UWowNjFrQoK9kE +q+7kCuWH2tQAOlPGySVqj0nSLjTyQGVuAvy5Qj/vy4x5hAOE3KBoHsfHNoxgFFXy +X/nBPyv2oh40H4O6c7y3YryXZoQJuS12cciR/eLhOc/d7JioSWmJqBgqQuf8qyzP +E6tj/rAZ6ho4IhYRMTRD/FDG7BmXA9voByhIiDrlNaL9gxLfVXByYQ34ZhhSWMlG +l4YxnqJDDLkP0+s1yeUZTrSL0qzqv4MqSJ0goAhFYJKKJwaTd3S7DiKOVBfy1Od/ +85BNzHXnFsWcSs/c8hkYEvVyji4= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 99 (0x63) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:2c:b4:2f:1d:06:09:ef:4e:29:86:84:7e:cc: + bf:a6:79:7c:f0:c0:c1:64:25:8c:75:b7:10:05:ca: + 48:27:0c:0e:32:1c:b0:fe:99:85:39:b6:b9:a2:f7: + 27:ff:6d:3c:8c:16:73:29:21:7f:8b:a6:54:71:90: + ad:cc:05:b9:9f:15:c7:0a:3f:5f:69:f4:0a:5f:8c: + 71:b5:2c:bf:66:e2:03:9a:32:f4:d2:ec:2a:89:4b: + f9:35:88:14:33:47:4e:2e:05:79:01:ed:64:36:76: + b9:f8:85:cd:01:88:ac:c5:b2:b1:59:b8:cd:5a:f4: + 09:09:38:9b:da:5a:cf:ce:78:99:1f:49:3d:41:d6: + 06:7c:52:99:c8:97:d1:b3:80:3a:a2:4f:36:c4:c5: + 96:30:77:31:38:c8:70:cc:e1:67:06:b3:2b:2f:93: + b5:69:cf:83:7e:88:53:9b:0f:46:21:4c:d6:05:36: + 44:99:60:68:47:e5:32:01:12:d4:10:73:ae:9a:34: + 94:fa:6e:b8:58:4f:7b:5b:8a:92:97:ad:fd:97:b9: + 75:ca:c2:d4:45:7d:17:6b:cd:2f:f3:63:7a:0e:30: + b5:0b:a9:d9:a6:7c:74:60:9d:cc:09:03:43:f1:0f: + 90:d3:b7:fe:6c:9f:d9:cd:78:4b:15:ae:8c:5b:f9: + 99:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 6b:10:b1:f8:cb:77:ef:72:f5:f8:fc:70:6d:18:dc:34:fe:d7: + 95:d8:fd:85:8e:ca:4b:f3:be:1f:eb:14:08:dc:23:34:78:98: + 39:d7:9f:c3:52:f6:14:3d:e9:de:5c:c2:d8:b1:4b:a8:4c:5b: + 91:42:66:da:7f:3c:e9:03:20:5e:08:0f:76:79:b9:21:10:89: + b7:73:46:44:7e:6e:28:0c:00:e4:f4:3e:65:aa:f5:c6:27:57: + 2c:bb:1d:ae:e5:94:57:a3:73:9e:6b:44:00:35:4a:f3:c7:34: + 9c:a2:a7:aa:62:9f:1d:ef:a8:6c:be:07:ad:ef:ae:ee:93:0b: + ba:c3:59:4e:90:40:2d:00:5e:f0:0f:0a:de:18:2a:b3:97:31: + 63:84:ff:18:1c:b6:d8:7d:ee:33:ed:99:f0:f5:7f:88:58:b3: + 0d:90:db:eb:44:7e:06:37:61:d4:34:b9:f6:fd:3e:8d:07:e4: + b5:b0:ae:09:ce:98:e4:b0:1b:d5:7b:53:94:dd:8a:b2:20:d6: + b0:72:f8:b1:bc:76:df:16:86:39:7b:e4:a9:15:47:57:ae:ca: + 41:d6:3a:ba:15:d1:c0:b5:38:66:0b:0f:80:8b:a2:07:b4:fc: + 80:1f:a3:4c:1f:d2:65:97:c1:2c:ae:46:31:61:49:0d:d7:5f: + ac:d2:a6:05 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIBYzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBlzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NMIHJvb3Qg +Q0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCrLLQvHQYJ704phoR+zL+meXzwwMFkJYx1txAF +ykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRxkK3MBbmfFccKP19p9ApfjHG1 +LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4hc0BiKzFsrFZuM1a9AkJOJva +Ws/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4yHDM4WcGsysvk7Vpz4N+iFOb +D0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tbipKXrf2XuXXKwtRFfRdrzS/z +Y3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsVroxb+ZmBAgMBAAGjggE5MIIB +NTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRzsBykL4LLz0elONewBII6fnIVITCB +xAYDVR0jBIG8MIG5gBRzsBykL4LLz0elONewBII6fnIVIaGBnaSBmjCBlzELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +EDAOBgNVBAoMB3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQD +DA93b2xmU1NMIHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b22CAWMwCwYDVR0PBAQDAgEGMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW +aHR0cDovLzEyNy4wLjAuMToyMjIyMDANBgkqhkiG9w0BAQsFAAOCAQEAaxCx+Mt3 +73L1+PxwbRjcNP7Xldj9hY7KS/O+H+sUCNwjNHiYOdefw1L2FD3p3lzC2LFLqExb +kUJm2n886QMgXggPdnm5IRCJt3NGRH5uKAwA5PQ+Zar1xidXLLsdruWUV6NznmtE +ADVK88c0nKKnqmKfHe+obL4Hre+u7pMLusNZTpBALQBe8A8K3hgqs5cxY4T/GBy2 +2H3uM+2Z8PV/iFizDZDb60R+Bjdh1DS59v0+jQfktbCuCc6Y5LAb1XtTlN2KsiDW +sHL4sbx23xaGOXvkqRVHV67KQdY6uhXRwLU4ZgsPgIuiB7T8gB+jTB/SZZfBLK5G +MWFJDddfrNKmBQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server3-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server3-key.pem new file mode 100644 index 000000000..30e108011 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server3-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC+GWUeFznUM/yX +ZGmAUftsfMrhuiqr0t0wYfMuR8HUM8D/UyG6LRSmuXxmykV7HH2P/HXzmmnxbCVG +oJJdAJPjIqZguZcFN3+hqs0igXKxIkc9fI1GVbwyTdKEQ1wVQwcicDY5kxvooUa7 +AoW6HTGssTyEW+uPH2KKcVKeC2O25tZGzBkG1rsGgeQLJRRsY5RwGic3lSRABzD1 +JHPDvfkOX7bNTxiI8Nejm/WwHv4EA6WNc/drMXSF/WH6nlM3dZDm+LWYZuhSTUpM +OQVlwTT5xpUnsAfBUZaoghsiz0Hf3rSUtw26Yfv0QHyh/KIpo0dNtJSde1Hs5BP7 +zekmyqeTAgMBAAECggEARDViddCJnF1m5X9O548C8qM4PJQK2YoYeVK76cAviQ9k +0XgnouCoB0aIn202Tv0jBHXmcJjYKJrQKS5WNe6OIbJ+FjihOmr2bbCWWCowV+Rf +wW0eV71NgJMx1OlCchKRzcaLfk8NdYPgmBtIlkYBW+BgQXGl7L2rIteUeEbH6Yj9 +yCn7ORQeFSbhZJTn2WdXhK3GWjV+1GyHyUyL2SSa2+G2LZ54Ifquq/F6rMGYB9lY +2K6Q6DB18aVxd/I/OYKeyBZcmJ9COgPUW7/fg0He73aduYdVvWZCRP1ygGdqSZFr +oqLVe34bEVFANUKylzRplRJdC4oKSUyTSubiOMKZ+QKBgQDf0mk3PolyvsfE2YGb +9/DsURIxZg14o9Pysp3yD1vvIYNz6WaddtJaj5OM7NzN8spu3wJSoeVgL6KYI6ah +ZTIYqy4ehOGPKBVL7SvLF+7q/QBMTdfllpdK7GLTtjBnz92TZl9bS/rBc9dCnnBC +EDkPPrc3nbk5/ADWd+K4RPG3HwKBgQDZbdiQCKY2ulppRcwjcAEIjhrFpShV21P6 +JNKt17HDBqULIAn+G9T/Gg/6yHWeY1DUgVBu1avb4L3jdnMPe2O+1jeaDzNRo6Xj +9v6PgGsiv4q7gfz7XqVwylUWIY7O52Ox/q+/QJBfwE0qe+E0t4syb44W4QvD9+k7 +fv77R7dFDQKBgQCe0SfVimtvX05TMN9V87YhiVk2ciqm6uDO+s02YI2kfgxPqFMm +8pRKrExPmBcJj/jyeQ2l4rjm6oYeHFX1ed/1PyoHf9SphxCtgoornzzpw0J94lKK +17Nc96Ucgs+QKiAYonCRULWKpY8d91zCk85ZMfBB54nySg2yIPlgNZOqkwKBgFO/ +Xqnj2vm7f7WKv91qd8tuyNsWCVpAl7EC2+8/5GVlOs71MUQiPkFgLYWADuXKBUlE +4dE/FeokP5/McPcmpL3Nzy7U6gRpDy2mZlipsxp4QpyErge4Zery1CEpHdOOBrV5 +jwIQgUuQS2iwvIbMp53uoAEp/5kk9T4IZXguIGZFAoGAMA/j0kHArT7FINf+O6R4 +3EyUTR139emLKHU2OlH/HfHVRZhHo4AmfUYksf+Njb81A6MKFd1XVmNnaumBIfq+ +6Ohoz1VMoO6aUiMMqbmBGaTHc30FVEtAQIRq2C8UDrEN67Sx3O/ngl0Br7lNri29 +LMSCe8fxf8+Kq0k+6tcsht4= +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server4-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server4-cert.pem new file mode 100644 index 000000000..95eb15a0a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server4-cert.pem @@ -0,0 +1,279 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8 (0x8) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL intermediate CA 2/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=www4.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:9c:ef:8a:7e:84:4d:58:7a:b1:91:c8:cb:68:76: + df:fe:0a:29:fe:7f:74:35:d5:c3:fd:43:be:d7:89: + fc:59:51:5a:30:e9:50:14:84:24:d0:c8:72:7d:d6: + 75:42:12:8b:16:ad:5a:e8:d3:84:a7:07:2b:9e:12: + ef:6a:cd:3e:83:14:b7:26:a2:53:7b:3d:6c:96:7f: + 9c:c5:09:08:0e:55:08:19:b7:5a:1c:46:32:09:da: + 44:b2:ca:fd:4a:e4:be:d0:02:c9:c9:48:03:13:a5: + ad:3e:7b:21:cf:05:3a:b9:25:f5:c1:b8:4e:4d:eb: + 33:99:d1:50:4a:eb:f7:1a:08:6b:d0:5c:9d:48:eb: + 98:fd:dc:89:0f:aa:74:d3:7f:03:1b:59:65:f5:86: + e1:d9:53:ab:e4:53:ab:85:3c:79:8b:45:39:7b:fd: + e9:a2:10:b9:fa:92:71:0e:68:36:66:6e:8c:fb:e2: + 8a:5d:5f:72:66:b0:47:2d:c5:b4:93:ce:61:7f:90: + 1a:64:02:dd:57:9d:f1:f1:e8:75:21:e2:af:44:e3: + 96:f5:1c:e3:73:87:dc:b7:05:12:ad:a5:8f:0c:d8: + 2c:b4:90:b3:d9:e7:13:e1:e5:5e:4c:9b:24:89:08: + 07:9e:aa:6b:9f:64:01:da:ec:95:05:45:84:d9:a9: + db:c7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Key Identifier: + 9A:D6:EF:4E:0A:7B:8B:74:E6:14:EC:35:9A:05:2A:94:68:09:61:58 + X509v3 Authority Key Identifier: + keyid:05:D1:BA:86:00:A2:EE:2A:05:24:B7:11:AD:2D:60:F1:90:14:8F:17 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:02 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Authority Information Access: + OCSP - URI:http://127.0.0.1:22222 + + Signature Algorithm: sha256WithRSAEncryption + 18:72:41:57:9a:c3:fa:b0:30:f4:bc:16:81:bf:3a:38:99:d2: + ac:24:b9:80:24:57:d2:9b:e6:29:ad:5d:7c:7c:f7:50:dd:9d: + 0b:0f:90:b5:cb:96:a1:19:3f:5b:6d:28:52:ee:a4:bb:28:3e: + 38:54:73:bb:9a:13:91:3d:f5:57:cf:bc:a8:21:64:dc:5c:d1: + 19:94:a6:8a:80:f8:92:e4:10:f9:19:c2:2b:b3:78:6b:2c:3d: + 81:9c:e9:3d:61:78:01:34:dd:f1:be:54:db:31:54:ed:ef:67: + a3:9b:c1:a1:5b:9b:ce:be:23:3a:6b:ab:92:34:1b:a1:d6:0b: + 1d:65:8a:cd:e2:f3:d1:ce:a9:c5:bf:19:a9:25:15:e6:98:f5: + 3f:3f:fa:22:72:48:a6:65:64:06:74:0c:49:bd:fe:7d:4e:5b: + 23:20:a8:a7:18:0e:7a:39:7e:d2:1f:a6:03:c2:31:6e:ce:49: + de:81:3c:7d:9f:1c:39:bb:df:8b:5c:58:8f:7a:08:77:f7:f8: + e3:f0:fe:14:73:0f:40:35:6a:1c:5a:46:79:b8:8b:4e:dd:75: + e0:55:89:57:d9:19:43:91:ca:66:39:00:7e:9b:0d:b2:3d:fc: + 35:7e:15:74:ed:36:61:94:7b:37:e2:17:37:4a:43:63:2e:24: + a7:e6:01:cb +-----BEGIN CERTIFICATE----- +MIIE7jCCA9agAwIBAgIBCDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSIwIAYDVQQDDBl3b2xmU1NM +IGludGVybWVkaWF0ZSBDQSAyMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE4MDQxMzE1MjMxMFoXDTIxMDEwNzE1MjMxMFowgZgxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYD +VQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEZMBcGA1UEAwwQd3d3 +NC53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJzvin6ETVh6sZHIy2h23/4K +Kf5/dDXVw/1DvteJ/FlRWjDpUBSEJNDIcn3WdUISixatWujThKcHK54S72rNPoMU +tyaiU3s9bJZ/nMUJCA5VCBm3WhxGMgnaRLLK/UrkvtACyclIAxOlrT57Ic8FOrkl +9cG4Tk3rM5nRUErr9xoIa9BcnUjrmP3ciQ+qdNN/AxtZZfWG4dlTq+RTq4U8eYtF +OXv96aIQufqScQ5oNmZujPviil1fcmawRy3FtJPOYX+QGmQC3Ved8fHodSHir0Tj +lvUc43OH3LcFEq2ljwzYLLSQs9nnE+HlXkybJIkIB56qa59kAdrslQVFhNmp28cC +AwEAAaOCATYwggEyMAkGA1UdEwQCMAAwHQYDVR0OBBYEFJrW704Ke4t05hTsNZoF +KpRoCWFYMIHEBgNVHSMEgbwwgbmAFAXRuoYAou4qBSS3Ea0tYPGQFI8XoYGdpIGa +MIGXMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwH +U2VhdHRsZTEQMA4GA1UECgwHd29sZlNTTDEUMBIGA1UECwwLRW5naW5lZXJpbmcx +GDAWBgNVBAMMD3dvbGZTU0wgcm9vdCBDQTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3 +b2xmc3NsLmNvbYIBAjALBgNVHQ8EBAMCBeAwMgYIKwYBBQUHAQEEJjAkMCIGCCsG +AQUFBzABhhZodHRwOi8vMTI3LjAuMC4xOjIyMjIyMA0GCSqGSIb3DQEBCwUAA4IB +AQAYckFXmsP6sDD0vBaBvzo4mdKsJLmAJFfSm+YprV18fPdQ3Z0LD5C1y5ahGT9b +bShS7qS7KD44VHO7mhORPfVXz7yoIWTcXNEZlKaKgPiS5BD5GcIrs3hrLD2BnOk9 +YXgBNN3xvlTbMVTt72ejm8GhW5vOviM6a6uSNBuh1gsdZYrN4vPRzqnFvxmpJRXm +mPU/P/oickimZWQGdAxJvf59TlsjIKinGA56OX7SH6YDwjFuzknegTx9nxw5u9+L +XFiPegh39/jj8P4Ucw9ANWocWkZ5uItO3XXgVYlX2RlDkcpmOQB+mw2yPfw1fhV0 +7TZhlHs34hc3SkNjLiSn5gHL +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL intermediate CA 2/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d0:20:3c:35:19:6f:2c:44:b4:7e:42:c7:75:b4: + 6a:2b:a9:23:85:bf:87:b4:ee:ca:d7:4b:1f:31:d7: + 11:02:a1:ab:58:3d:fb:dc:51:ca:3a:1d:1f:95:a6: + 56:82:f7:8f:ff:6b:50:bb:ea:10:e1:47:1d:35:77: + 2e:4b:28:c5:53:46:23:2b:82:fd:5a:d3:f4:21:db: + 0e:e0:f2:76:33:47:b3:00:be:3a:b1:23:98:53:eb: + ea:a0:de:1b:cc:05:4e:ee:63:a8:2c:93:24:d6:98: + 78:74:03:e4:c8:89:43:61:f1:25:b8:cd:3b:87:c1: + 31:25:fd:ba:4c:fc:29:94:45:9e:69:d7:67:0a:8a: + 8e:d5:52:93:30:a2:0e:dd:6a:1c:b0:94:77:db:52: + 52:b7:89:21:be:96:75:24:cb:e9:49:df:81:9d:9d: + f8:55:7d:01:2a:eb:78:03:12:e2:20:6e:db:63:35: + cd:a1:96:f0:f8:8c:20:35:69:87:01:ca:b4:54:36: + a0:15:e0:23:7d:b9:fb:be:99:05:50:f0:bf:ec:7f: + 12:e1:3d:75:15:4e:c8:c2:30:e6:8b:fe:e5:8b:55: + f8:44:5e:e5:e3:56:e0:66:2d:6f:42:5a:45:6b:96: + aa:c7:5d:41:08:5f:ce:d7:dc:9f:20:e4:46:78:ff: + d9:99 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 05:D1:BA:86:00:A2:EE:2A:05:24:B7:11:AD:2D:60:F1:90:14:8F:17 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 92:6e:c1:af:88:af:46:f2:6e:8a:8c:27:06:8e:b4:38:35:9b: + 47:92:24:20:e5:a5:13:d8:35:d3:2e:37:ca:74:47:e5:16:a3: + 03:63:16:b4:28:2b:d9:04:ab:ee:e4:0a:e5:87:da:d4:00:3a: + 53:c6:c9:25:6a:8f:49:d2:2e:34:f2:40:65:6e:02:fc:b9:42: + 3f:ef:cb:8c:79:84:03:84:dc:a0:68:1e:c7:c7:36:8c:60:14: + 55:f2:5f:f9:c1:3f:2b:f6:a2:1e:34:1f:83:ba:73:bc:b7:62: + bc:97:66:84:09:b9:2d:76:71:c8:91:fd:e2:e1:39:cf:dd:ec: + 98:a8:49:69:89:a8:18:2a:42:e7:fc:ab:2c:cf:13:ab:63:fe: + b0:19:ea:1a:38:22:16:11:31:34:43:fc:50:c6:ec:19:97:03: + db:e8:07:28:48:88:3a:e5:35:a2:fd:83:12:df:55:70:72:61: + 0d:f8:66:18:52:58:c9:46:97:86:31:9e:a2:43:0c:b9:0f:d3: + eb:35:c9:e5:19:4e:b4:8b:d2:ac:ea:bf:83:2a:48:9d:20:a0: + 08:45:60:92:8a:27:06:93:77:74:bb:0e:22:8e:54:17:f2:d4: + e7:7f:f3:90:4d:cc:75:e7:16:c5:9c:4a:cf:dc:f2:19:18:12: + f5:72:8e:2e +-----BEGIN CERTIFICATE----- +MIIE8DCCA9igAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBoTELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSIwIAYDVQQDDBl3b2xmU1NMIGludGVy +bWVkaWF0ZSBDQSAyMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0CA8NRlvLES0fkLHdbRqK6kj +hb+HtO7K10sfMdcRAqGrWD373FHKOh0flaZWgveP/2tQu+oQ4UcdNXcuSyjFU0Yj +K4L9WtP0IdsO4PJ2M0ezAL46sSOYU+vqoN4bzAVO7mOoLJMk1ph4dAPkyIlDYfEl +uM07h8ExJf26TPwplEWeaddnCoqO1VKTMKIO3WocsJR321JSt4khvpZ1JMvpSd+B +nZ34VX0BKut4AxLiIG7bYzXNoZbw+IwgNWmHAcq0VDagFeAjfbn7vpkFUPC/7H8S +4T11FU7IwjDmi/7li1X4RF7l41bgZi1vQlpFa5aqx11BCF/O19yfIORGeP/ZmQID +AQABo4IBOTCCATUwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUBdG6hgCi7ioFJLcR +rS1g8ZAUjxcwgcQGA1UdIwSBvDCBuYAUc7AcpC+Cy89HpTjXsASCOn5yFSGhgZ2k +gZowgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmlu +ZzEYMBYGA1UEAwwPd29sZlNTTCByb290IENBMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QHdvbGZzc2wuY29tggFjMAsGA1UdDwQEAwIBBjAyBggrBgEFBQcBAQQmMCQwIgYI +KwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjAwDQYJKoZIhvcNAQELBQAD +ggEBAJJuwa+Ir0byboqMJwaOtDg1m0eSJCDlpRPYNdMuN8p0R+UWowNjFrQoK9kE +q+7kCuWH2tQAOlPGySVqj0nSLjTyQGVuAvy5Qj/vy4x5hAOE3KBoHsfHNoxgFFXy +X/nBPyv2oh40H4O6c7y3YryXZoQJuS12cciR/eLhOc/d7JioSWmJqBgqQuf8qyzP +E6tj/rAZ6ho4IhYRMTRD/FDG7BmXA9voByhIiDrlNaL9gxLfVXByYQ34ZhhSWMlG +l4YxnqJDDLkP0+s1yeUZTrSL0qzqv4MqSJ0goAhFYJKKJwaTd3S7DiKOVBfy1Od/ +85BNzHXnFsWcSs/c8hkYEvVyji4= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 99 (0x63) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:2c:b4:2f:1d:06:09:ef:4e:29:86:84:7e:cc: + bf:a6:79:7c:f0:c0:c1:64:25:8c:75:b7:10:05:ca: + 48:27:0c:0e:32:1c:b0:fe:99:85:39:b6:b9:a2:f7: + 27:ff:6d:3c:8c:16:73:29:21:7f:8b:a6:54:71:90: + ad:cc:05:b9:9f:15:c7:0a:3f:5f:69:f4:0a:5f:8c: + 71:b5:2c:bf:66:e2:03:9a:32:f4:d2:ec:2a:89:4b: + f9:35:88:14:33:47:4e:2e:05:79:01:ed:64:36:76: + b9:f8:85:cd:01:88:ac:c5:b2:b1:59:b8:cd:5a:f4: + 09:09:38:9b:da:5a:cf:ce:78:99:1f:49:3d:41:d6: + 06:7c:52:99:c8:97:d1:b3:80:3a:a2:4f:36:c4:c5: + 96:30:77:31:38:c8:70:cc:e1:67:06:b3:2b:2f:93: + b5:69:cf:83:7e:88:53:9b:0f:46:21:4c:d6:05:36: + 44:99:60:68:47:e5:32:01:12:d4:10:73:ae:9a:34: + 94:fa:6e:b8:58:4f:7b:5b:8a:92:97:ad:fd:97:b9: + 75:ca:c2:d4:45:7d:17:6b:cd:2f:f3:63:7a:0e:30: + b5:0b:a9:d9:a6:7c:74:60:9d:cc:09:03:43:f1:0f: + 90:d3:b7:fe:6c:9f:d9:cd:78:4b:15:ae:8c:5b:f9: + 99:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 6b:10:b1:f8:cb:77:ef:72:f5:f8:fc:70:6d:18:dc:34:fe:d7: + 95:d8:fd:85:8e:ca:4b:f3:be:1f:eb:14:08:dc:23:34:78:98: + 39:d7:9f:c3:52:f6:14:3d:e9:de:5c:c2:d8:b1:4b:a8:4c:5b: + 91:42:66:da:7f:3c:e9:03:20:5e:08:0f:76:79:b9:21:10:89: + b7:73:46:44:7e:6e:28:0c:00:e4:f4:3e:65:aa:f5:c6:27:57: + 2c:bb:1d:ae:e5:94:57:a3:73:9e:6b:44:00:35:4a:f3:c7:34: + 9c:a2:a7:aa:62:9f:1d:ef:a8:6c:be:07:ad:ef:ae:ee:93:0b: + ba:c3:59:4e:90:40:2d:00:5e:f0:0f:0a:de:18:2a:b3:97:31: + 63:84:ff:18:1c:b6:d8:7d:ee:33:ed:99:f0:f5:7f:88:58:b3: + 0d:90:db:eb:44:7e:06:37:61:d4:34:b9:f6:fd:3e:8d:07:e4: + b5:b0:ae:09:ce:98:e4:b0:1b:d5:7b:53:94:dd:8a:b2:20:d6: + b0:72:f8:b1:bc:76:df:16:86:39:7b:e4:a9:15:47:57:ae:ca: + 41:d6:3a:ba:15:d1:c0:b5:38:66:0b:0f:80:8b:a2:07:b4:fc: + 80:1f:a3:4c:1f:d2:65:97:c1:2c:ae:46:31:61:49:0d:d7:5f: + ac:d2:a6:05 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIBYzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBlzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NMIHJvb3Qg +Q0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCrLLQvHQYJ704phoR+zL+meXzwwMFkJYx1txAF +ykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRxkK3MBbmfFccKP19p9ApfjHG1 +LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4hc0BiKzFsrFZuM1a9AkJOJva +Ws/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4yHDM4WcGsysvk7Vpz4N+iFOb +D0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tbipKXrf2XuXXKwtRFfRdrzS/z +Y3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsVroxb+ZmBAgMBAAGjggE5MIIB +NTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRzsBykL4LLz0elONewBII6fnIVITCB +xAYDVR0jBIG8MIG5gBRzsBykL4LLz0elONewBII6fnIVIaGBnaSBmjCBlzELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +EDAOBgNVBAoMB3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQD +DA93b2xmU1NMIHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b22CAWMwCwYDVR0PBAQDAgEGMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW +aHR0cDovLzEyNy4wLjAuMToyMjIyMDANBgkqhkiG9w0BAQsFAAOCAQEAaxCx+Mt3 +73L1+PxwbRjcNP7Xldj9hY7KS/O+H+sUCNwjNHiYOdefw1L2FD3p3lzC2LFLqExb +kUJm2n886QMgXggPdnm5IRCJt3NGRH5uKAwA5PQ+Zar1xidXLLsdruWUV6NznmtE +ADVK88c0nKKnqmKfHe+obL4Hre+u7pMLusNZTpBALQBe8A8K3hgqs5cxY4T/GBy2 +2H3uM+2Z8PV/iFizDZDb60R+Bjdh1DS59v0+jQfktbCuCc6Y5LAb1XtTlN2KsiDW +sHL4sbx23xaGOXvkqRVHV67KQdY6uhXRwLU4ZgsPgIuiB7T8gB+jTB/SZZfBLK5G +MWFJDddfrNKmBQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server4-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server4-key.pem new file mode 100644 index 000000000..39a93b209 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server4-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCc74p+hE1YerGR +yMtodt/+Cin+f3Q11cP9Q77XifxZUVow6VAUhCTQyHJ91nVCEosWrVro04SnByue +Eu9qzT6DFLcmolN7PWyWf5zFCQgOVQgZt1ocRjIJ2kSyyv1K5L7QAsnJSAMTpa0+ +eyHPBTq5JfXBuE5N6zOZ0VBK6/caCGvQXJ1I65j93IkPqnTTfwMbWWX1huHZU6vk +U6uFPHmLRTl7/emiELn6knEOaDZmboz74opdX3JmsEctxbSTzmF/kBpkAt1XnfHx +6HUh4q9E45b1HONzh9y3BRKtpY8M2Cy0kLPZ5xPh5V5MmySJCAeeqmufZAHa7JUF +RYTZqdvHAgMBAAECggEAMmlQF6vwHIftGmNh08C72yLwsmvGrLRqLKTiXOJaSWa0 +jhmkO7LnEJoTDREiwYKrYzF0jm3DotPO0wxKFAiyF/FDlAl4v5HPm9iKR1DLYa82 +1uvq6kIyOLAAeV5zVud7093Ra/LR6jHCINv01EddwbPL6dqGbMks3jA6lpaN3bJt +85VSy3h6rC2pIZrGddJxDV5jR2gm4N4j8GJoPWpYIGZa/i+GhFmx0OJfUAWTBsGQ +flt4HxtxoR0OkAQ1MnBbBLqadQQiJ3tt47vD5Ma98GGkuq/l9y2rCuJ/t7sjY7+1 +1dnXrMj4VHKTNYEIkmpNti9lblT55P9v5HAYj4SoIQKBgQDP6/Tf1sf12XKZoQvi +qwww32brRqMnj7xpiK9PfsPdnBvq1u8aApQ2XRsHLkH/aq7S91DdLKhn+5fX9TZq +fGtix0V5/JVB11+0Y8hB6YonKtmTxGPScSKQdsSdnvo27yuBfSSp2QuSqYsAqKdV +dU/F++jAeNJFr5lg+X3zo+7gMwKBgQDBOXB3cO6Xjr1vzkxdtxpbKYTVYK5XGFpy +lGDJ9QasDMD6iX8EsTzp0/3CRtITnfYFBiBDXSFDwoUm7TqjdlDh9ahFcvkre/33 +6SmXqHshn/RBl+JCAKYolw7cJmuWAFrJNZPbnbfiuqDNg8wkD3P2VTVkKWjsDpxA +f+99Xm2yHQKBgBBlWvoLxdjtPMxAlt9Y/a0c8NC80UDdZM4tqSVrqaZgGRN7v38d +lPJ0hR0b2Lh7gS3Bsu6+BsmsXVz6SUA8b3tqm1/zOxHmGfXvqGsKL4rHJkEwy25c +3Yzm0LpdPv31/khHxgxewTrfg8aZhhiHF7NVGhWTcYFtR3sOMZB07PFhAoGAf9to +RkDeQD9druwNsD2HHSeeFCvDcTJWN1djrH+MiLBvydjNyecV7YwvcCy4ue5eavig +xLKNXm8K+LUlhiC2aK7LSBlKM7H6Xd9VfFsqDxfu4rCEMTSIvncmiBqMOlfFuzrO +uhXlJgxkd1ls7bej/i5oA/06xmjsj+mYKZcgcykCgYAbONjSKF28CILSDKLepNqx +euRSnKaSgTjcu8B5C6ZWUY8+EsD3Lw6VK2Xn+PPPSS2+Pw7dgLdYybyCgPOLXV+9 +we3d0OyuIPiLiRpfnHVTXdYQBc7qa8khw12LZpodkXwKT85St8jdwJzL1KTZAWqf +N2KyjDHPGPz8paCzS8LfuQ== +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server5-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server5-cert.pem new file mode 100644 index 000000000..1a6b81c67 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server5-cert.pem @@ -0,0 +1,279 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 9 (0x9) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL REVOKED intermediate CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=www5.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ac:73:6d:e9:fa:8c:36:72:3e:89:3b:52:29:bd: + 14:70:a2:00:b4:08:58:b6:c6:c0:bf:80:6a:1f:a5: + f0:15:fc:f4:19:a2:67:f9:6a:5d:22:69:2e:9c:29: + 53:1e:5a:4a:d1:27:d5:b8:3b:65:37:8a:a2:eb:1b: + d4:5d:90:11:35:11:af:e3:d1:8c:24:5b:b5:90:c0: + bf:de:cb:7a:05:71:1b:ef:76:d7:9d:43:47:85:dc: + 24:b8:b8:54:fc:53:bf:c3:fd:e1:12:c6:fc:1b:6f: + 95:aa:cf:bb:8e:22:af:83:bd:4e:6b:66:fe:7e:7e: + 98:6f:b1:b9:fc:f9:8a:8a:18:92:9a:4c:27:5d:78: + 6b:e9:d0:14:1c:ed:69:6d:29:4c:4e:52:e6:92:24: + 53:b0:2e:c3:a4:94:8f:20:1c:29:5c:97:70:1a:32: + 85:90:71:f7:d7:a5:99:4f:48:c7:3d:fc:3d:a7:e1: + f9:96:ea:c1:6b:ea:31:e0:9b:fb:68:3e:4b:ad:a4: + 2b:06:90:c2:b4:27:ea:f3:a3:3e:6e:32:75:aa:70: + 6a:e3:33:29:fb:42:09:94:79:a5:eb:3c:4e:89:02: + 77:08:fd:da:ba:fc:14:c6:8e:c1:5e:db:6d:d0:07: + 4f:02:79:60:e7:95:c3:c8:f4:54:83:21:12:79:03: + 7f:e1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Key Identifier: + 2A:48:B6:8B:00:F0:4B:35:73:94:07:87:52:A3:69:5E:E6:D8:42:87 + X509v3 Authority Key Identifier: + keyid:BB:15:9E:32:4D:E0:F8:AA:8A:B0:2E:0C:17:2B:5A:41:74:4B:06:45 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:03 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Authority Information Access: + OCSP - URI:http://127.0.0.1:22223 + + Signature Algorithm: sha256WithRSAEncryption + ba:fe:ad:1d:d4:33:69:13:86:4d:1a:ea:fc:a0:61:00:9a:bd: + 83:7d:53:3d:b5:63:a9:c8:c2:b6:10:4d:fb:5f:f2:e5:b1:e4: + 1a:9b:85:36:8f:3c:d3:09:98:4c:c5:3e:10:ed:a3:74:a5:3c: + fc:d9:b2:80:38:6c:be:f4:8b:52:40:0e:45:e8:fd:a2:29:d8: + 5c:f9:1d:14:76:3d:8d:41:74:3c:56:05:d2:a3:2e:14:5b:35: + 95:97:cf:c1:01:cf:a2:26:38:0b:76:12:bd:c4:68:f2:f5:49: + ed:7e:eb:4e:08:73:fe:82:06:8e:ce:c4:22:d5:16:ef:0e:62: + d5:f1:08:b8:2e:02:75:23:52:04:cf:cb:aa:1c:ce:77:b6:3a: + e9:78:53:c4:37:d4:cc:7f:96:5d:97:89:35:da:a6:23:77:87: + 60:4a:a8:f8:b6:e6:1a:00:c5:74:98:88:b2:01:fd:23:81:05: + f5:bb:96:60:55:ae:3b:9f:bf:c9:82:e1:24:d6:1d:1f:5d:9c: + f7:1b:cb:37:3e:4f:c8:ca:65:c1:33:69:75:62:83:bb:87:45: + 47:bd:b2:b6:55:ef:8f:7c:5f:fd:14:75:96:4f:3e:19:d8:88: + 67:5d:75:ae:77:8f:38:3f:a2:7e:f6:f8:b8:c8:57:28:10:9d: + 1e:cd:c3:5c +-----BEGIN CERTIFICATE----- +MIIE9DCCA9ygAwIBAgIBCTANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSgwJgYDVQQDDB93b2xmU1NM +IFJFVk9LRUQgaW50ZXJtZWRpYXRlIENBMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tMB4XDTE4MDQxMzE1MjMxMFoXDTIxMDEwNzE1MjMxMFowgZgxCzAJ +BgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxl +MRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEZMBcGA1UE +AwwQd3d3NS53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKxzben6jDZyPok7 +Uim9FHCiALQIWLbGwL+Aah+l8BX89BmiZ/lqXSJpLpwpUx5aStEn1bg7ZTeKousb +1F2QETURr+PRjCRbtZDAv97LegVxG+92151DR4XcJLi4VPxTv8P94RLG/BtvlarP +u44ir4O9Tmtm/n5+mG+xufz5iooYkppMJ114a+nQFBztaW0pTE5S5pIkU7Auw6SU +jyAcKVyXcBoyhZBx99elmU9Ixz38Pafh+ZbqwWvqMeCb+2g+S62kKwaQwrQn6vOj +Pm4ydapwauMzKftCCZR5pes8TokCdwj92rr8FMaOwV7bbdAHTwJ5YOeVw8j0VIMh +EnkDf+ECAwEAAaOCATYwggEyMAkGA1UdEwQCMAAwHQYDVR0OBBYEFCpItosA8Es1 +c5QHh1KjaV7m2EKHMIHEBgNVHSMEgbwwgbmAFLsVnjJN4PiqirAuDBcrWkF0SwZF +oYGdpIGaMIGXMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4G +A1UEBwwHU2VhdHRsZTEQMA4GA1UECgwHd29sZlNTTDEUMBIGA1UECwwLRW5naW5l +ZXJpbmcxGDAWBgNVBAMMD3dvbGZTU0wgcm9vdCBDQTEfMB0GCSqGSIb3DQEJARYQ +aW5mb0B3b2xmc3NsLmNvbYIBAzALBgNVHQ8EBAMCBeAwMgYIKwYBBQUHAQEEJjAk +MCIGCCsGAQUFBzABhhZodHRwOi8vMTI3LjAuMC4xOjIyMjIzMA0GCSqGSIb3DQEB +CwUAA4IBAQC6/q0d1DNpE4ZNGur8oGEAmr2DfVM9tWOpyMK2EE37X/LlseQam4U2 +jzzTCZhMxT4Q7aN0pTz82bKAOGy+9ItSQA5F6P2iKdhc+R0Udj2NQXQ8VgXSoy4U +WzWVl8/BAc+iJjgLdhK9xGjy9UntfutOCHP+ggaOzsQi1RbvDmLV8Qi4LgJ1I1IE +z8uqHM53tjrpeFPEN9TMf5Zdl4k12qYjd4dgSqj4tuYaAMV0mIiyAf0jgQX1u5Zg +Va47n7/JguEk1h0fXZz3G8s3Pk/IymXBM2l1YoO7h0VHvbK2Ve+PfF/9FHWWTz4Z +2IhnXXWud484P6J+9vi4yFcoEJ0ezcNc +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL REVOKED intermediate CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:de:c5:04:10:7d:c2:21:e9:12:45:da:d5:ba:28: + fd:a6:f4:30:44:a0:df:f9:70:5e:17:26:97:59:5c: + 31:eb:13:70:ea:4a:dd:58:3e:4f:33:14:66:59:69: + 7a:aa:90:e0:7c:c4:b2:36:c1:0a:f4:df:3e:34:6c: + 1a:e9:2b:f1:a5:92:7e:a9:68:70:ba:a4:68:88:f3: + ec:10:40:64:a5:64:7d:d9:1e:51:49:9d:7f:c8:cc: + 2b:6d:71:2a:06:ff:e6:1f:84:28:8a:c1:ed:a8:52: + f4:89:a5:c0:77:d8:13:66:c2:65:a5:63:03:98:b0: + 4b:05:4f:0c:84:a0:f4:2d:72:73:6b:fa:0d:e1:cf: + 45:27:ed:a3:8c:02:d7:ee:99:e2:a1:f0:e3:a0:ad: + 69:ed:59:e4:27:41:8f:ef:fa:83:73:8f:5f:2b:68: + 89:13:46:26:dc:f6:28:6b:3b:b2:b8:9b:52:2a:17: + 1b:dc:72:45:73:da:75:24:35:8b:00:5e:23:37:64: + 6a:16:74:b8:ee:fe:b7:11:71:be:0a:73:c8:54:c2: + d9:04:d2:1b:f5:53:ac:8d:2a:4f:fe:33:79:e6:5e: + e7:f3:86:d3:dc:bb:4b:d7:39:7f:5b:3c:67:fe:5e: + 88:51:05:96:f2:b4:9a:45:09:4c:51:f0:6a:4d:88: + 2a:17 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + BB:15:9E:32:4D:E0:F8:AA:8A:B0:2E:0C:17:2B:5A:41:74:4B:06:45 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 63:bf:90:58:0c:44:08:57:7d:94:7e:eb:fd:9d:90:f6:1d:a5: + 91:2a:32:38:a7:f7:39:c2:c0:9c:93:26:bc:f4:4b:81:0a:0f: + 07:2d:4f:a9:20:9a:3e:2c:24:0c:30:10:d7:be:96:ab:ee:1f: + 2c:f8:71:7c:1a:c1:ae:b7:64:e1:7e:18:53:c3:ae:d5:04:16: + f7:e5:34:c2:d1:a3:31:d4:9b:f4:b7:c1:96:1f:a7:3c:3a:bf: + fd:06:be:76:f4:da:95:f9:6f:be:4f:24:a7:0f:b0:2c:12:4d: + d6:55:ea:f8:0a:30:91:32:4f:a3:14:6d:ec:cd:85:12:1f:da: + 78:8a:b1:9a:74:fb:fd:00:45:4a:30:83:45:16:a0:8f:b7:7f: + 23:33:91:c6:81:ac:f3:9b:cd:53:6b:9a:fa:36:9b:5d:3c:72: + a8:73:4f:1e:b5:da:ba:08:3d:9b:ca:7a:d6:c2:bf:6e:9f:a5: + 9e:db:61:bc:a5:42:a7:d4:92:4a:7e:a3:3d:1b:aa:d3:c2:93: + ad:ce:3b:0e:2b:61:44:1e:3c:61:54:0d:6a:26:21:54:c6:e0: + ed:3d:da:27:cd:89:5a:f8:1f:0f:46:80:c1:f2:80:cc:52:f1: + 7f:ce:10:68:66:3f:ee:90:25:45:d4:f8:87:f9:5d:5d:74:3d: + aa:3d:43:1c +-----BEGIN CERTIFICATE----- +MIIE9jCCA96gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBpzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMSgwJgYDVQQDDB93b2xmU1NMIFJFVk9L +RUQgaW50ZXJtZWRpYXRlIENBMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3sUEEH3CIekSRdrV +uij9pvQwRKDf+XBeFyaXWVwx6xNw6krdWD5PMxRmWWl6qpDgfMSyNsEK9N8+NGwa +6SvxpZJ+qWhwuqRoiPPsEEBkpWR92R5RSZ1/yMwrbXEqBv/mH4QoisHtqFL0iaXA +d9gTZsJlpWMDmLBLBU8MhKD0LXJza/oN4c9FJ+2jjALX7pniofDjoK1p7VnkJ0GP +7/qDc49fK2iJE0Ym3PYoazuyuJtSKhcb3HJFc9p1JDWLAF4jN2RqFnS47v63EXG+ +CnPIVMLZBNIb9VOsjSpP/jN55l7n84bT3LtL1zl/Wzxn/l6IUQWW8rSaRQlMUfBq +TYgqFwIDAQABo4IBOTCCATUwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUuxWeMk3g ++KqKsC4MFytaQXRLBkUwgcQGA1UdIwSBvDCBuYAUc7AcpC+Cy89HpTjXsASCOn5y +FSGhgZ2kgZowgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAw +DgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtFbmdp +bmVlcmluZzEYMBYGA1UEAwwPd29sZlNTTCByb290IENBMR8wHQYJKoZIhvcNAQkB +FhBpbmZvQHdvbGZzc2wuY29tggFjMAsGA1UdDwQEAwIBBjAyBggrBgEFBQcBAQQm +MCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly8xMjcuMC4wLjE6MjIyMjAwDQYJKoZIhvcN +AQELBQADggEBAGO/kFgMRAhXfZR+6/2dkPYdpZEqMjin9znCwJyTJrz0S4EKDwct +T6kgmj4sJAwwENe+lqvuHyz4cXwawa63ZOF+GFPDrtUEFvflNMLRozHUm/S3wZYf +pzw6v/0Gvnb02pX5b75PJKcPsCwSTdZV6vgKMJEyT6MUbezNhRIf2niKsZp0+/0A +RUowg0UWoI+3fyMzkcaBrPObzVNrmvo2m108cqhzTx612roIPZvKetbCv26fpZ7b +YbylQqfUkkp+oz0bqtPCk63OOw4rYUQePGFUDWomIVTG4O092ifNiVr4Hw9GgMHy +gMxS8X/OEGhmP+6QJUXU+If5XV10Pao9Qxw= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 99 (0x63) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Validity + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Washington, L=Seattle, O=wolfSSL, OU=Engineering, CN=wolfSSL root CA/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ab:2c:b4:2f:1d:06:09:ef:4e:29:86:84:7e:cc: + bf:a6:79:7c:f0:c0:c1:64:25:8c:75:b7:10:05:ca: + 48:27:0c:0e:32:1c:b0:fe:99:85:39:b6:b9:a2:f7: + 27:ff:6d:3c:8c:16:73:29:21:7f:8b:a6:54:71:90: + ad:cc:05:b9:9f:15:c7:0a:3f:5f:69:f4:0a:5f:8c: + 71:b5:2c:bf:66:e2:03:9a:32:f4:d2:ec:2a:89:4b: + f9:35:88:14:33:47:4e:2e:05:79:01:ed:64:36:76: + b9:f8:85:cd:01:88:ac:c5:b2:b1:59:b8:cd:5a:f4: + 09:09:38:9b:da:5a:cf:ce:78:99:1f:49:3d:41:d6: + 06:7c:52:99:c8:97:d1:b3:80:3a:a2:4f:36:c4:c5: + 96:30:77:31:38:c8:70:cc:e1:67:06:b3:2b:2f:93: + b5:69:cf:83:7e:88:53:9b:0f:46:21:4c:d6:05:36: + 44:99:60:68:47:e5:32:01:12:d4:10:73:ae:9a:34: + 94:fa:6e:b8:58:4f:7b:5b:8a:92:97:ad:fd:97:b9: + 75:ca:c2:d4:45:7d:17:6b:cd:2f:f3:63:7a:0e:30: + b5:0b:a9:d9:a6:7c:74:60:9d:cc:09:03:43:f1:0f: + 90:d3:b7:fe:6c:9f:d9:cd:78:4b:15:ae:8c:5b:f9: + 99:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + X509v3 Authority Key Identifier: + keyid:73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL/OU=Engineering/CN=wolfSSL root CA/emailAddress=info@wolfssl.com + serial:63 + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://127.0.0.1:22220 + + Signature Algorithm: sha256WithRSAEncryption + 6b:10:b1:f8:cb:77:ef:72:f5:f8:fc:70:6d:18:dc:34:fe:d7: + 95:d8:fd:85:8e:ca:4b:f3:be:1f:eb:14:08:dc:23:34:78:98: + 39:d7:9f:c3:52:f6:14:3d:e9:de:5c:c2:d8:b1:4b:a8:4c:5b: + 91:42:66:da:7f:3c:e9:03:20:5e:08:0f:76:79:b9:21:10:89: + b7:73:46:44:7e:6e:28:0c:00:e4:f4:3e:65:aa:f5:c6:27:57: + 2c:bb:1d:ae:e5:94:57:a3:73:9e:6b:44:00:35:4a:f3:c7:34: + 9c:a2:a7:aa:62:9f:1d:ef:a8:6c:be:07:ad:ef:ae:ee:93:0b: + ba:c3:59:4e:90:40:2d:00:5e:f0:0f:0a:de:18:2a:b3:97:31: + 63:84:ff:18:1c:b6:d8:7d:ee:33:ed:99:f0:f5:7f:88:58:b3: + 0d:90:db:eb:44:7e:06:37:61:d4:34:b9:f6:fd:3e:8d:07:e4: + b5:b0:ae:09:ce:98:e4:b0:1b:d5:7b:53:94:dd:8a:b2:20:d6: + b0:72:f8:b1:bc:76:df:16:86:39:7b:e4:a9:15:47:57:ae:ca: + 41:d6:3a:ba:15:d1:c0:b5:38:66:0b:0f:80:8b:a2:07:b4:fc: + 80:1f:a3:4c:1f:d2:65:97:c1:2c:ae:46:31:61:49:0d:d7:5f: + ac:d2:a6:05 +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIBYzANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoM +B3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NM +IHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgw +NDEzMTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBlzELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dvbGZT +U0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQDDA93b2xmU1NMIHJvb3Qg +Q0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCrLLQvHQYJ704phoR+zL+meXzwwMFkJYx1txAF +ykgnDA4yHLD+mYU5trmi9yf/bTyMFnMpIX+LplRxkK3MBbmfFccKP19p9ApfjHG1 +LL9m4gOaMvTS7CqJS/k1iBQzR04uBXkB7WQ2drn4hc0BiKzFsrFZuM1a9AkJOJva +Ws/OeJkfST1B1gZ8UpnIl9GzgDqiTzbExZYwdzE4yHDM4WcGsysvk7Vpz4N+iFOb +D0YhTNYFNkSZYGhH5TIBEtQQc66aNJT6brhYT3tbipKXrf2XuXXKwtRFfRdrzS/z +Y3oOMLULqdmmfHRgncwJA0PxD5DTt/5sn9nNeEsVroxb+ZmBAgMBAAGjggE5MIIB +NTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRzsBykL4LLz0elONewBII6fnIVITCB +xAYDVR0jBIG8MIG5gBRzsBykL4LLz0elONewBII6fnIVIaGBnaSBmjCBlzELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +EDAOBgNVBAoMB3dvbGZTU0wxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRgwFgYDVQQD +DA93b2xmU1NMIHJvb3QgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b22CAWMwCwYDVR0PBAQDAgEGMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW +aHR0cDovLzEyNy4wLjAuMToyMjIyMDANBgkqhkiG9w0BAQsFAAOCAQEAaxCx+Mt3 +73L1+PxwbRjcNP7Xldj9hY7KS/O+H+sUCNwjNHiYOdefw1L2FD3p3lzC2LFLqExb +kUJm2n886QMgXggPdnm5IRCJt3NGRH5uKAwA5PQ+Zar1xidXLLsdruWUV6NznmtE +ADVK88c0nKKnqmKfHe+obL4Hre+u7pMLusNZTpBALQBe8A8K3hgqs5cxY4T/GBy2 +2H3uM+2Z8PV/iFizDZDb60R+Bjdh1DS59v0+jQfktbCuCc6Y5LAb1XtTlN2KsiDW +sHL4sbx23xaGOXvkqRVHV67KQdY6uhXRwLU4ZgsPgIuiB7T8gB+jTB/SZZfBLK5G +MWFJDddfrNKmBQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server5-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server5-key.pem new file mode 100644 index 000000000..a45a1c6e9 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/ocsp/server5-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCsc23p+ow2cj6J +O1IpvRRwogC0CFi2xsC/gGofpfAV/PQZomf5al0iaS6cKVMeWkrRJ9W4O2U3iqLr +G9RdkBE1Ea/j0YwkW7WQwL/ey3oFcRvvdtedQ0eF3CS4uFT8U7/D/eESxvwbb5Wq +z7uOIq+DvU5rZv5+fphvsbn8+YqKGJKaTCddeGvp0BQc7WltKUxOUuaSJFOwLsOk +lI8gHClcl3AaMoWQcffXpZlPSMc9/D2n4fmW6sFr6jHgm/toPkutpCsGkMK0J+rz +oz5uMnWqcGrjMyn7QgmUeaXrPE6JAncI/dq6/BTGjsFe223QB08CeWDnlcPI9FSD +IRJ5A3/hAgMBAAECggEABz5+EoMc2rin2dntFKXFswmLIATtvRfSRvkc/CFbWYEb +u+vvlDGcofJrK9IslKzUUb7romaUVOX0/A1aOWfw4RrSGa7WxTw4/1CpfrFreckL +lF6YphmKapwZysyrfUIDXzdN+hzzwC9KyTcauNjKKK2OGsLj0+p7es2rc24EHNLj +vFpNj5TC84qsibATY1ny3tcL7SBcNLtiHsm+0JDagGqlW3ptT0oErrzH6jtUAI9j +LLm87mxwJyp4rBZvnP3s4jnOLLCJH40QyrCPKR6L4bAzSaA9kEnBUu+y1y1PyUP7 +goWIPJmfclDFqgB2U7K/QbbfPFpt8pFB9SmbsoIlMQKBgQDgvgf/pdc6q9jAL9UQ +sTYa+iJJIFcjQKA95aCRoUeUjWvjA+2ROmYgLcMi7pxfNyFvYkaOXjBTL+aqSEWI +wQVbnGK4aqG16w2o/P+bWUatpMMWNbwsZGAkXpcgdrg+SbNjrQ2lY35EdmPc025G +Fqx5ouOk7wDlKWQolIwWDh3WNQKBgQDEb47VbrIo8BNnO/xxVjAsU7uQIYZkr/GR +6V5oN+kIXrttReZnY/bUVrV84r49E3cNfoZXlfZa7fAEVb9GWbZMk+9M/s78aU5M +xeFNj7HBfbgG3I+1SZQZaAEK6BZuq8GRCLV2JKOn9iInVQQL57/qz6APjC/a52zJ +asNmmcdIfQKBgBmEWgIjwUEvG8gOZkGj7UG43sWwv1QIVWlRth5y0l7Cg9pdqs6P +c+L5byt7LhP9fXVZEiu98/yt9qGk3Qg+6i3Rnr/Tk5LFImLqftcTltvGVkQiS8A6 +kVPvzXbpI9gmpBCQKHl7x21ch9AdzWp1zpVs8i3a2R4ryex1mUYzyh11AoGAWhKZ +WS7IDNOA4i50Y/fUYQ8IC2AEAvlWeMScoIc6mLbvlHyf2LrSvK0BzUEfYFwjlBF3 +QoQmEa3XB/XVnkmWuOiAqzqP6NfUqol19R21sXaXQrYyQzt46GlzSPABEUA6oulu +Y70LOgI3yPdHwrnCm8YWq+ppKyRBEt6cuNg8s/UCgYEAl3J4fMTYcDjt4H/OTgba +IjKLPV0LuBUfx/PTA0oi81x1c11fM8a/ZeD0QkXDjjrjXM33mbkR0lzFEl7ZOCnh +sRDkkM8MvOsq4KMGnBLQBN0QvKSgsuYDqIEUmFdMHiyckBjuwntMVXnfKYtEJ1Q9 +zYHlJn4e4/2VqGK9PWrgAtA= +-----END PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/rsa-pub-2048.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/rsa-pub-2048.pem new file mode 100644 index 000000000..95daf3389 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/rsa-pub-2048.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuwQ1KqA3hewLXsG9fHD7 +UI3fQu5ylQiDeRWEwsFovmiDfDNo7P/VuByvQmVR30p3GzNnZdMsj8jVlLD/Wny1 +nU/O2T00KQ95SJhiEGGCVWirRf/7F1KrFGP7HuiQ76FQwqtRxBDQw3QOm2PXp20E +pyzGdYpY13EkY6n0FLumWoJxL+2gTW0ECyLulxXFK9wXCNWnY+ji5V8VwDfkXk7W +XYzMawnFnKNiSJ99jkfJ28lo+Ba8LAfvHM6ygeudWndri6pGkA/R0Z3knca6yz5Y +JCMph5AKgj9beOaLsIWEbdbmZA7fzuu8QhBK6cjvjUbS6iPVDEfBnI6TOpGPJxvW +NwIDAQAB +-----END PUBLIC KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/rsa3072.der b/FreeRTOS-Plus/Source/WolfSSL/certs/rsa3072.der new file mode 100644 index 0000000000000000000000000000000000000000..0db1ea3d1abf1d645a6d4a9387c5cfb695b8cdaa GIT binary patch literal 1768 zcmVl9q2|h<)jLE; zd1q2@+U;|Td^6e?mgu69JXhVxE&+6hGoTWDyZKY}#4$)y%ey>6LkxO*xGMbIaMffM zbf|#d7T~gM1V?Norhl|^Nxbu}fD!o515h=_ZGeAxw_9gJI z0v1T^9N5W{FI%s=+h86J;boDQ_Hyn#iYF?R3ab}c`T#2Jq#Dvxe< z%-~(HhGzb9*#^QA^|cv^a|`>N&pZ) z0X-GFRgr+c*wb0euzXhc|KKP<0<)NkR8nB23zbubYos;G1jqXd$emgdK=)t=v9m(9 zfRE%Q$>_X}Aq_{*xHk!}zbrHfBEoJB1~7mgrHV!^+*j0Bf@%>00|5X50)hd70Iiv? z&rv`wwJe;!->6M|TEX7fcy%y?O*Cx67Z-OI{)%(Viqz_qkfTB9%|3PpxtyYXlFX3J zr%e-VG%b?rfslHQY;bZ>JI&EBfHMak_c+eG*Wq2*&z`nbO@bn(!KK+snpfuBH*FKz|0627G15zY^8%3eC_R`w_CrOktC1DQ#E_gm z+SDKtvf(RM;y5y#=BXY2rS8{KwBzJu>Oq~MPm=v-z?o3+AUl#TT z>GL_##W7PVIqf=4D#1*Lg2u|v^_p=fuKWJbX4|R*7EAB6D67xDn^@1JSc1|wjOsmg zO$$bP1m5v(y92-Xj^^~5;mRf~K?toOr@}z>oZYL%T1@ojno#|!N7kkXC9+GL9gw0* znBWD9T+uARDA9yGa{q(su>yg?0QjI^B`za#Ft(Sk27Yc)-PWw^g6Lw{L;ZIT z93v8u9R8Cmhf=?md0skNGbkrNAS|;c;tfQpFFAXAt)n5*e>{m}-4n4c)-?MngDK~V zh}WYyJVRoSY5GeQwf0$%VtvmY-AO|;mZ|r4pX3d09O@Wby%g=E3Q$lPiT}ys#&Jrk|Fq^!Y#pKRv z2;CjEAMtOt$6LpRsk3sDd zmE|$>YlcDqzpBPv9;T2C@f+wl`>3j3`EqpJf5S|Hv$Rcn#xL?W#{;_?=p4j{W5yrS*2y9LX{E!)`ZViF3Ls|0ZKBl*`wPHAbuZc_g-Lb4_WwGlTB2- zH_%ahy=U;H3CWuDA0ASj^`<4ig&m>s*u6OraaS2Y^PzX(i%zqVgcS_&SW?;LnAK*L zoEeRzV_d(*GlA`XlS`Ux>@Ge}0)fCZ_}_HK!Px_wJ5w3!L&T~cbK?^wG6W)dN(b-; zIK5Zq0W*y80?aflU^1j49S%8btM|^^r^DEyJ8&_PXt}@Op*ev5N10Y_c90kKXF)_K z5C@n|OjFbq+zKz?gD4`6VLRlG<>w@r8K|S}a9IY1cEU@`7sYoH2e_*mk^FLwx3T7Q z-93`0-fV8mP(&}RnfEqLV#ln`eJ07$PD$5}W^BPz-!ZEtHOkh+qo$vJJuMnUF+G8i KxHbqULY@eTz+d

q#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 z*#|j{H-0-eJbS`pZqUTC3Rpr-f|O85Ava7)s=-;n5-P3s^PJKZ*(BHE6n)l0-s_WZ zsldl=rt|Ngs%4&WdCfiMw0Bw`Z)~W|V-MjLn4##~a9T*=`5FIvuC*tN%8g!~ny@=F zNPt;?#pkIF&1abRp0MzC=H%sV|yw&dcNq^%d*1yk{4}mmsy?JQG4>~q3gFC@^2{K zDVBE94W9E)>QC+JDl_{T_gZRL)6ZpzShTPF*t0d`bVhxlg7()1$zQ|t7pq;`p1(0l z{JO^I|WpsVaomYdvfZfI=w-uu?95_@Tdtt1** zr4`>~4;QbZX$gg@O)GUyB}9MfusbhU5+&$$=jM%X5jw1w!*0IpH-Fz}XZ>HvjN#Oc zN7L+=UwkWnuWG~fezU!fp>kJtwpq8UW|}5=Tze8V<=moQ1r}yUTDN#B|0|rQf1B<2 z);WqF>}p<5{1Ly$m~vkL)j z0tklx^^OqUxcifU10sL4RA8;312WzMe<4bN#_i3`*b<7sx`JDEtyJTDfNHERY#>g) zO@gOK6I}GhYAX<#Sl+8^d?E$GgPqI&Jmf7`YNnRo)4^!t(#C^Jm*U1U4!*<#xd)0{ zxP-dJIX@g&r&ZVRo9NO-x#NQ_?zVAOxjODYC)juB`$R}(Cr5uw`~GsntOa`=%j;fc znyUijh+8|03&+fr3mgd{(9M7O z#9k*LcD-;Wqk^lez delta 318 zcmV-E0m1&F38D#*yB;+#H83|ZI5IIXFm~vkL)j z0tnfFI>XZR+BcJc10sKCz$~dlN9Pd~cdpFX;Ae0?*S)wc)xpEW+f``Xqk2HOsrCd)BF~t19OR?_c^Q9}S7Qfn_A+-CP@Cg4 z7}V>&{kCu8$M%K4tTL^bSH2UHL=dI(uHt6eM5&Z6WKadD0wP|8r=K$eXY=$^Lkyo{WT zVgi|YY55LF3Jm1Lc?~TLObm?;O^u8V4Wh((jSLM84a}k3q2L8e17S9HaF{bOLIa9ApOo(^%!o literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-comp.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-comp.pem index 50b74f85b..1f40a07a8 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-comp.pem +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-comp.pem @@ -1,12 +1,12 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 17764616133298603308 (0xf6889840946fc52c) + Serial Number: 9257370821982864771 (0x8078c9b7065ac583) Signature Algorithm: ecdsa-with-SHA256 Issuer: C=US, ST=Montana, L=Bozeman, O=Elliptic - comp, OU=Server ECC-comp, CN=www.wolfssl.com/emailAddress=info@wolfssl.com Validity - Not Before: May 7 18:21:01 2015 GMT - Not After : Jan 31 18:21:01 2018 GMT + Not Before: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT Subject: C=US, ST=Montana, L=Bozeman, O=Elliptic - comp, OU=Server ECC-comp, CN=www.wolfssl.com/emailAddress=info@wolfssl.com Subject Public Key Info: Public Key Algorithm: id-ecPublicKey @@ -16,27 +16,28 @@ Certificate: 9f:36:db:72:2d:ce:94:ea:2b:fa:cb:20:09:39:2c: 16:e8:61 ASN1 OID: prime256v1 + NIST CURVE: P-256 X509v3 extensions: X509v3 Subject Key Identifier: 8C:38:3A:6B:B8:24:B7:DF:6E:F4:59:AC:56:4E:AA:E2:58:A6:5A:18 X509v3 Authority Key Identifier: keyid:8C:38:3A:6B:B8:24:B7:DF:6E:F4:59:AC:56:4E:AA:E2:58:A6:5A:18 DirName:/C=US/ST=Montana/L=Bozeman/O=Elliptic - comp/OU=Server ECC-comp/CN=www.wolfssl.com/emailAddress=info@wolfssl.com - serial:F6:88:98:40:94:6F:C5:2C + serial:80:78:C9:B7:06:5A:C5:83 X509v3 Basic Constraints: CA:TRUE Signature Algorithm: ecdsa-with-SHA256 - 30:46:02:21:00:9c:f8:3e:f6:5e:cd:da:b1:08:fe:e2:bd:78: - 14:b5:33:b3:29:69:d0:a0:de:19:05:ec:c3:46:29:01:8c:4c: - 56:02:21:00:e2:e7:ea:37:c1:08:f6:15:73:0c:92:4f:25:63: - f6:53:96:31:4c:9f:1d:1a:1f:c0:a0:a3:48:bd:71:ce:13:11 + 30:44:02:20:31:44:d0:4e:d7:c4:b4:96:a3:e6:25:fd:fa:d6: + 28:a8:67:51:72:90:95:31:f9:cd:10:bf:11:e4:ec:b7:42:5b: + 02:20:45:db:45:0a:24:58:8e:2e:e6:ea:0c:6c:bc:72:4f:0a: + 1b:f3:2d:97:e9:c2:19:f9:97:3a:60:dd:08:d3:52:3e -----BEGIN CERTIFICATE----- -MIIDJTCCAsqgAwIBAgIJAPaImECUb8UsMAoGCCqGSM49BAMCMIGgMQswCQYDVQQG +MIIDIzCCAsqgAwIBAgIJAIB4ybcGWsWDMAoGCCqGSM49BAMCMIGgMQswCQYDVQQG EwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEYMBYGA1UE CgwPRWxsaXB0aWMgLSBjb21wMRgwFgYDVQQLDA9TZXJ2ZXIgRUNDLWNvbXAxGDAW BgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm -c3NsLmNvbTAeFw0xNTA1MDcxODIxMDFaFw0xODAxMzExODIxMDFaMIGgMQswCQYD +c3NsLmNvbTAeFw0xODA0MTMxNTIzMTBaFw0yMTAxMDcxNTIzMTBaMIGgMQswCQYD VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEYMBYG A1UECgwPRWxsaXB0aWMgLSBjb21wMRgwFgYDVQQLDA9TZXJ2ZXIgRUNDLWNvbXAx GDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3 @@ -46,7 +47,7 @@ bvRZrFZOquJYploYMIHVBgNVHSMEgc0wgcqAFIw4Omu4JLffbvRZrFZOquJYploY oYGmpIGjMIGgMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UE BwwHQm96ZW1hbjEYMBYGA1UECgwPRWxsaXB0aWMgLSBjb21wMRgwFgYDVQQLDA9T ZXJ2ZXIgRUNDLWNvbXAxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqG -SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAPaImECUb8UsMAwGA1UdEwQFMAMB -Af8wCgYIKoZIzj0EAwIDSQAwRgIhAJz4PvZezdqxCP7ivXgUtTOzKWnQoN4ZBezD -RikBjExWAiEA4ufqN8EI9hVzDJJPJWP2U5YxTJ8dGh/AoKNIvXHOExE= +SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIB4ybcGWsWDMAwGA1UdEwQFMAMB +Af8wCgYIKoZIzj0EAwIDRwAwRAIgMUTQTtfEtJaj5iX9+tYoqGdRcpCVMfnNEL8R +5Oy3QlsCIEXbRQokWI4u5uoMbLxyTwob8y2X6cIZ+Zc6YN0I01I+ -----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-rsa.der b/FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-rsa.der new file mode 100644 index 0000000000000000000000000000000000000000..82aba2a5d3bd9dd5cb296d77439c0c477fbfbcb3 GIT binary patch literal 996 zcmXqLVt!!I#B^c-GZP~d6C}?^zfLP~TIz_sNMw4s-uE)og93YoZ{NN!tsB2xIOBlg=B9 z8~+$I{se{}bEqsIix`VYY^>V*HFah`XP1d;d#N%hzu(kpV93b%!p2!k8mAA^1kl9E(DwgppTNBxzYTamUJ+(tHDG3B z{EwD?nVT3H8F+T5@BMQ&IOn%t#EDlylU_eLu_v6LL*Yd8hO4i_)%Rvh{5`X!S9G3# z|B=%si3cKuW}j#hxA31A%&|CAPyfIc{Y8EPDI3@q26D(w3|>?js^FMvYR7HC7|ztA z`h2y2cjSk+eO{v6M!&1NnO@C(xcUhDnOppe#cuaS@0qq*V8=bq?(e6USEPwQR?Q2a zE1XyzDs{i#Qq<2$iJ|pKAb0k%^aHpz^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/FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-self.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-self.pem new file mode 100644 index 000000000..06c0e913f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc-self.pem @@ -0,0 +1,55 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 13895948352942430886 (0xc0d85367324edaa6) + 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: Jul 18 17:12:20 2019 GMT + Not After : Apr 13 17:12:20 2022 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:C0:D8:53:67:32:4E:DA:A6 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:20:01:0e:83:d8:81:53:76:e4:ce:4b:51:69:a4:bc: + 50:2e:46:02:e1:27:d6:04:e4:76:36:e9:fe:4a:ed:87:d1:72: + 02:21:00:97:87:68:62:34:53:45:41:7a:e1:a9:f1:80:c4:51: + 27:e0:e4:6a:0e:54:c4:22:39:ec:85:c0:54:b5:57:62:8c +-----BEGIN CERTIFICATE----- +MIIDDzCCArWgAwIBAgIJAMDYU2cyTtqmMAoGCCqGSM49BAMCMIGPMQswCQYDVQQG +EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEQMA4G +A1UECgwHRWxpcHRpYzEMMAoGA1UECwwDRUNDMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkwNzE4 +MTcxMjIwWhcNMjIwNDEzMTcxMjIwWjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB0VsaXB0aWMx +DDAKBgNVBAsMA0VDQzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZI +hvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD +QgAEuzOsTCdQSsZKpQTDPN6fNttyLc6U6iv6yyAJOSwW6GEC6a9N0wKTmjFbl5Ih +f/DPGNqREQI0huggWDMLgDSJ2KOB9zCB9DAdBgNVHQ4EFgQUXV0m76x+NvmbdhUr +SiUCI++yiTAwgcQGA1UdIwSBvDCBuYAUXV0m76x+NvmbdhUrSiUCI++yiTChgZWk +gZIwgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRAwDgYDVQQKDAdFbGlwdGljMQwwCgYDVQQLDANFQ0MxGDAWBgNV +BAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns +LmNvbYIJAMDYU2cyTtqmMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIg +AQ6D2IFTduTOS1FppLxQLkYC4SfWBOR2Nun+Su2H0XICIQCXh2hiNFNFQXrhqfGA +xFEn4ORqDlTEIjnshcBUtVdijA== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc.der b/FreeRTOS-Plus/Source/WolfSSL/certs/server-ecc.der new file mode 100644 index 0000000000000000000000000000000000000000..837396770bfa64addfc687845b37ede5a8268774 GIT binary patch literal 852 zcmXqLVh%89V*0v(nTe5!iAjLLfQyYotIgw_EekV~LF05oZUas>=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(#d&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/FreeRTOS-Plus/Source/WolfSSL/certs/server-keyPkcs8Enc.der b/FreeRTOS-Plus/Source/WolfSSL/certs/server-keyPkcs8Enc.der new file mode 100644 index 0000000000000000000000000000000000000000..c098580ba0c6508b478977239e7e4a363de2591a GIT binary patch literal 1261 zcmV8wLp~hDe6@4FLrMFb)I=uW&NF`kxgP0s;sC1cC&}^(^ZEo1&{q zm`q2__p{#j$Dd~@>dn{Zt-;T|;bMRMy?aRhttbrBse!Bd)AM_*%(>C|=-j!M)Bc3{ zLwGX^AD9%kmYrEujmn!a^6Fgqy}@YUV1ke3`gNx)$P_q~Q=og0VucOS^}?-nD&5pU zO2A>R-lW4Dwxdm(q?w5Exf-d+dXGDki95WP#B+h{9_&b>G9?hClII}B!G|KjWepe(hb_#3!%l#-W|%(d$&f6eaZG_tUqrd}glH><>I>qg2j zu8q?y<+egqXW#{S(_&F6W1D`=JAN;wGczuu7+9m91}MW&zzJ-cx;EICzAM zN%_=1#pw8BCR-cYC)%hjpvU{s_SR2%~u4v5+6-49^756t2%SebwzH? zSAwyXL_&Iko^M726i{XesR*m5nikM?Q6q@1p(x!qkMJ}MNI%@#lLj&R^|94e;SEs< zegkI2G;a~HemLy@h>)M`4W977q-XwU3vtf!9>#QYQ&Kchb{_>$&m|gOSN)sqCJO9n$?iaA z0CDkxdhjqaw7$T?i8>A`22 zjTs8I;dOtD>fU3ED!=0EId3t06yR8}n);tqX7#@wc;fo^e81}BHwyI0aWk9c8kUH7 z6M|=-c;}QuPu*4v#5jes+bV%VVakXeKF}eCAsiGraBEDYi;7#OvNRs3Xi4iVHsw+& zb$bjCRh7OcGl3M%VmD=Uf@mEFZ=@jrg$+?hdgQo+=ZQO}Bw3gWc;7at?UANdAl+v; zDV)2VEwc$MSV095`5Zr7a?Tp}5m1-{foE{E>E`jlwb`KPpj~RdH2mR40mj1^HT8pa z#1bx}9&EHPEc-KX@DV5)G7K}Z%MdQVurP$=)P)Vn_?I4CLP9aIggE>vfFX1^<2*xT zN>Gw_Tf{r*VAt{mZ&z)cy@Mv6fkNMZRI%t5o#}O+>-UlN)9OToCTY-h%QlT@^BBoP zlvYqHHD%3QYT(WSA0+}hZ0NvoO|9B2=o4GnV2A`hOIS9Ht^t~+%e|Ea`JS=5mpr&l z#N2pEqFIAQiX$-5O`2=Y4X+Fecb1wx)6}c#5jp@Ot~!}3Wli)heIqGop7&YXID%p# z8wvS@iXqTRRv#g#h(-vebs9GFSz XyXMHxX=O#T67ubgL?_Eb5SCj>W7cdg literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/server-revoked-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/server-revoked-cert.pem new file mode 100644 index 000000000..09dbb1dd0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/server-revoked-cert.pem @@ -0,0 +1,173 @@ +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: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=wolfSSL_revoked, OU=Support_revoked, CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b0:14:16:3a:43:dd:e1:50:45:4f:cf:80:b3:dd: + 66:96:c7:e9:f4:dc:de:b6:6b:24:1b:76:48:ac:c6: + 23:a5:a7:e4:05:19:bd:b7:f6:de:fa:ff:ed:5b:3c: + 79:8a:a9:d5:f1:fb:eb:c8:b1:e4:b2:ab:52:72:89: + 93:22:5c:ba:cd:8a:36:2a:2c:d1:40:ec:a8:66:0e: + c3:76:cd:e7:b3:a3:0a:1e:dd:4a:07:82:17:81:ba: + de:57:ce:b6:32:81:c7:bd:11:bb:e9:15:22:4e:e2: + 16:ac:e3:d4:c0:68:88:6c:11:fc:c2:bd:1b:db:1d: + fd:e6:43:c7:1b:33:b8:f4:e5:1b:59:39:12:38:4d: + 2d:9b:64:68:98:fc:8d:72:12:91:f2:24:25:6c:4c: + 4a:48:57:92:00:cc:7e:d8:d4:3d:b8:1d:f2:9e:ea: + b2:23:0f:51:0f:11:41:1c:f5:27:00:1b:08:7a:12: + 3a:05:5b:03:24:fe:b1:7b:20:fa:e4:a8:58:c6:ca: + ce:7f:be:95:01:12:9d:05:e6:39:13:1b:c0:3e:56: + 2e:2b:9f:76:37:de:de:9b:e0:0d:7a:63:0d:a7:22: + 58:db:31:c7:f7:b4:46:5c:ba:b6:4b:48:b1:18:9a: + 68:b3:63:47:fd:af:12:5f:2f:fe:10:cb:58:2b:33: + 68:85 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D8:09:2B:59:E1:2A:EE:D9:EE:40:AA:9C:AB:F0:5D:28:09:4F:22:BB + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 41:29:ba:25:3f:17:70:85:1e:5c:e2:2c:8c:8d:16:1b:d5:1f: + d6:05:e8:e8:8b:43:a0:5b:62:e8:19:7d:d1:1c:60:26:2f:3a: + 6f:7a:3f:ec:ad:96:c6:9a:cc:53:3f:12:d9:12:14:ee:2a:f0: + a5:2c:31:c7:ae:5c:12:9a:80:3f:ef:de:f3:be:bc:9d:0e:d6: + c6:8b:e2:8c:58:4e:15:78:4f:16:2e:20:ef:f8:c9:57:6e:a3: + d2:d0:03:32:47:72:84:59:af:5a:46:dd:65:54:d4:9b:7c:42: + 5d:9d:86:eb:21:e8:fc:0f:f7:37:ae:95:43:75:6d:f2:12:f3: + a5:e5:10:25:7c:63:ee:03:ce:8f:48:c8:ab:a5:74:2d:1c:dd: + d4:28:9a:eb:c6:94:fa:ed:57:31:aa:7e:d9:44:40:69:9f:44: + f6:b3:9f:0e:d3:d8:58:66:d4:fc:c0:83:67:a7:85:ae:03:f7: + 83:b4:45:3b:0f:a9:3d:4f:f8:07:31:b0:8a:50:6d:80:f4:36: + be:86:df:ae:da:7c:f5:bc:e2:fc:d3:ed:da:18:7a:f4:f0:ac: + 84:1f:6a:73:00:41:42:71:d4:19:3f:d7:d3:29:9e:b1:94:fd: + 49:d8:a5:e6:1d:a9:40:b5:1d:c4:28:42:a9:24:b7:54:c2:94: + 5d:16:05:c0 +-----BEGIN CERTIFICATE----- +MIIErjCCA5agAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgwNDEz +MTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBoDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM +B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xGDAWBgNVBAoMD3dvbGZTU0xfcmV2 +b2tlZDEYMBYGA1UECwwPU3VwcG9ydF9yZXZva2VkMRgwFgYDVQQDDA93d3cud29s +ZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwFBY6Q93hUEVPz4Cz3WaWx+n03N62 +ayQbdkisxiOlp+QFGb239t76/+1bPHmKqdXx++vIseSyq1JyiZMiXLrNijYqLNFA +7KhmDsN2zeezowoe3UoHgheBut5XzrYygce9EbvpFSJO4has49TAaIhsEfzCvRvb +Hf3mQ8cbM7j05RtZORI4TS2bZGiY/I1yEpHyJCVsTEpIV5IAzH7Y1D24HfKe6rIj +D1EPEUEc9ScAGwh6EjoFWwMk/rF7IPrkqFjGys5/vpUBEp0F5jkTG8A+Vi4rn3Y3 +3t6b4A16Yw2nIljbMcf3tEZcurZLSLEYmmizY0f9rxJfL/4Qy1grM2iFAgMBAAGj +gfwwgfkwHQYDVR0OBBYEFNgJK1nhKu7Z7kCqnKvwXSgJTyK7MIHJBgNVHSMEgcEw +gb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJVUzEQ +MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwIU2F3 +dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xmc3Ns +LmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q3rj7 +MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEEpuiU/F3CFHlziLIyN +FhvVH9YF6OiLQ6BbYugZfdEcYCYvOm96P+ytlsaazFM/EtkSFO4q8KUsMceuXBKa +gD/v3vO+vJ0O1saL4oxYThV4TxYuIO/4yVduo9LQAzJHcoRZr1pG3WVU1Jt8Ql2d +hush6PwP9zeulUN1bfIS86XlECV8Y+4Dzo9IyKuldC0c3dQomuvGlPrtVzGqftlE +QGmfRPaznw7T2Fhm1PzAg2enha4D94O0RTsPqT1P+AcxsIpQbYD0Nr6G367afPW8 +4vzT7doYevTwrIQfanMAQUJx1Bk/19MpnrGU/UnYpeYdqUC1HcQoQqkkt1TClF0W +BcA= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 9727763710660753659 (0x86fff58e10deb8fb) + 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: Apr 13 15:23:09 2018 GMT + Not After : Jan 7 15:23:09 2021 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 9e:28:88:72:00:ca:e6:e7:97:ca:c1:f1:1f:9e:12:b2:b8:c7: + 51:ea:28:e1:36:b5:2d:e6:2f:08:23:cb:a9:4a:87:25:c6:5d: + 89:45:ea:f5:00:98:ac:76:fb:1b:af:f0:ce:64:9e:da:08:bf: + b6:eb:b4:b5:0c:a0:e7:f6:47:59:1c:61:cf:2e:0e:58:a4:82: + ac:0f:3f:ec:c4:ae:80:f7:b0:8a:1e:85:41:e8:ff:fe:fe:4f: + 1a:24:d5:49:fa:fb:fe:5e:e5:d3:91:0e:4f:4e:0c:21:51:71: + 83:04:6b:62:7b:4f:59:76:48:81:1e:b4:f7:04:47:8a:91:57: + a3:11:a9:f2:20:b4:78:33:62:3d:b0:5e:0d:f9:86:38:82:da: + a1:98:8d:19:06:87:21:39:b7:02:f7:da:7d:58:ba:52:15:d8: + 3b:c9:7b:58:34:a0:c7:e2:7c:a9:83:13:e1:b6:ec:01:bf:52: + 33:0b:c4:fe:43:d3:c6:a4:8e:2f:87:7f:7a:44:ea:ca:53:6c: + 85:ed:65:76:73:31:03:4e:ea:bd:35:54:13:f3:64:87:6b:df: + 34:dd:34:a1:88:3b:db:4d:af:1b:64:90:92:71:30:8e:c8:cc: + e5:60:24:af:31:16:39:33:91:50:f9:ab:68:42:74:7a:35:d9: + dd:c8:c4:52 +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIJAIb/9Y4Q3rj7MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G +A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAe +Fw0xODA0MTMxNTIzMDlaFw0yMTAxMDcxNTIzMDlaMIGUMQswCQYDVQQGEwJVUzEQ +MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwIU2F3 +dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xmc3Ns +LmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL8Myi0Ush6EQlvNOB9K8k11EPG2NZ/fyn0D +mNOs3gNm7irx2LB9bgdUCxCYIU2AyxIg58xP3kV9yXJ3MurKkLtpUhADL6jzlcXx +i2JWG+9nb6QQQZWtCpvjpcCw0nB2UDBbqOgILHztp6J6jTgpHKzH7fJ8lbCVgn1J +XDjNdyXvvYB1U5Q8PcpjW58VtdMdEy8Z0TzbdjrMuH3J5cLX2kBv2CHccxtCLVOc +/hr8fat6Nj+Y3oR8BWfOahQ4h6nxjLVoy2h/cSAr9aBj9VYvoybSt2+xWhfXOJkI +/pNYb/7DE0kIFgunTWcAUjFnI06Y7VFFHbkE2Qvs2CizS73tNnkCAwEAAaOB/DCB ++TAdBgNVHQ4EFgQUJ45nEXTDJh0/7TNjs6TYHTDl6NUwgckGA1UdIwSBwTCBvoAU +J45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290 +aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t +MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1jhDeuPswDAYD +VR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAniiIcgDK5ueXysHxH54SsrjH +Ueoo4Ta1LeYvCCPLqUqHJcZdiUXq9QCYrHb7G6/wzmSe2gi/tuu0tQyg5/ZHWRxh +zy4OWKSCrA8/7MSugPewih6FQej//v5PGiTVSfr7/l7l05EOT04MIVFxgwRrYntP +WXZIgR609wRHipFXoxGp8iC0eDNiPbBeDfmGOILaoZiNGQaHITm3AvfafVi6UhXY +O8l7WDSgx+J8qYMT4bbsAb9SMwvE/kPTxqSOL4d/ekTqylNshe1ldnMxA07qvTVU +E/Nkh2vfNN00oYg7202vG2SQknEwjsjM5WAkrzEWOTORUPmraEJ0ejXZ3cjEUg== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/server-revoked-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/server-revoked-key.pem new file mode 100644 index 000000000..3cf5640ec --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/server-revoked-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAsBQWOkPd4VBFT8+As91mlsfp9NzetmskG3ZIrMYjpafkBRm9 +t/be+v/tWzx5iqnV8fvryLHksqtScomTIly6zYo2KizRQOyoZg7Dds3ns6MKHt1K +B4IXgbreV862MoHHvRG76RUiTuIWrOPUwGiIbBH8wr0b2x395kPHGzO49OUbWTkS +OE0tm2RomPyNchKR8iQlbExKSFeSAMx+2NQ9uB3ynuqyIw9RDxFBHPUnABsIehI6 +BVsDJP6xeyD65KhYxsrOf76VARKdBeY5ExvAPlYuK592N97em+ANemMNpyJY2zHH +97RGXLq2S0ixGJpos2NH/a8SXy/+EMtYKzNohQIDAQABAoIBAQCfamBBekZ9gxZt +ztmgfvgt1WutZPdCwzgaoPnlazLE/X9FWuvYjeuN5n44V0VXVLK99q6fsufzF4d6 +6bHLr5b1Fog5oQAHPvysAfvYKU345sj37rPinla3/r7lUuLEUZnMRS0TNy4rqyiK +eW+akEnLRnHIwjxhIwNIId83cpmnJfE7ZV7svZvk6Ctc//prFa/Y2AwkZcM2j2iG +xc4kOXr0Y8DE4FYQEZgdJCoYfVDihcwtVXUGm+ZMBNhLzK/KuSxdjL6ySzdCSE9M +mS4ZJPManR9LOIGsKlFsJrGWnFOm/GOMkzdBSLoEqRogHhYsvn7oDnLMHqPA/gE0 +M85ytBkVAoGBAOO/tTCd94kDfkXar+5+KvcYwQbwnMIbrN0TiIudpaSnE0dBFqU3 +oNC2K+PoGBgwEsEr2ThZCMAbz7NQJYmmNlNlSMNBzeud59F3BqMk3J6k62E0+Fnt +C8OFfZ8V0vbdGehmeArEqHDcRJZBFsrUWb2/9/j4OYpnsozkp6H1pWQrAoGBAMXr +jouX1qXLfKvYEpOKaSf+yjfULjT33ib885Nw2xlRzI6wkjHFsb8DERK36PA3CakU +cdXb923tMMlLoCvSdDd6Qnx1TLRbYaJSFaOLt2we94AvjHtijM6vO7ftd1XvRWer +/Ip9NT9X1NZxP/NTyUL3DgRmXE4L32fr2FFQEJ4PAoGBAKr2QeFY83RatvNhEigJ +dd8/Kcc337SmacEa5KlJkgpjkMkwRvuHIqUJ2zCeDVg63hk7/TebPkJXnjaQt1z4 +9Fbt9Qz93MI+KsLGgqj9Bs/gJQE3biazFt2S25YMH+1IVCZspTgQIBF4h9Py0FU5 +ypPyAwdV7nvDE/lHu76MU7c5AoGBALUxR5ioc0vplMNF1wvXpRmGet7Nk1fOrESJ +QvzyTsNJTbo8EDscv/Mc/Z5jXA++c0uleenNrSGoCgffAk3cJ6U6em+ye3yKREH0 +X/cPy+ZiGzfxT+0NddcqOcPS1HOJz8Jvg43Nvte0sxd3KpK7W//AacbBZzPUTry2 +/5zBbdUlAoGAYglAtoHIC0mQxAe6PXy/QRmgj87fPGsbVFOUwBf8Il2UKpfX9blv +0rHb0kenc/DP7ZHZTgdc5qGgRyg0d3+O7W2rWTv1MiX85rUE03TCcyC2l1+M+iyx +6IdHDjYwa4Kt0nT1JxEMjJxe1uhzJfgYJlcz5Iy4ff0xb8/aH0veedc= +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/taoCert.txt b/FreeRTOS-Plus/Source/WolfSSL/certs/taoCert.txt index 3c954a772..0973defb2 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/certs/taoCert.txt +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/taoCert.txt @@ -23,7 +23,7 @@ same as self signed, use ca prefix instead of client 1) openssl req -newkey rsa:1024 -sha1 -days 1000 -nodes -keyout server-key.pem > server-req.pem -* note if using exisitng key do: -new -key keyName +* note if using existing key do: -new -key keyName 2) copy ca-key.pem ca-cert.srl (why ????) @@ -106,7 +106,7 @@ to use PKCS#12 instead use -v1 witch a 12 algo like openssl pkcs8 -nocrypt -in server-keyPkcs8.pem -out server-key.pem -*** DH paramters *** +*** DH parameters *** openssl dhparam 2048 > dh2048.param diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-ber-exp02-05-2022.p7b b/FreeRTOS-Plus/Source/WolfSSL/certs/test-ber-exp02-05-2022.p7b new file mode 100644 index 0000000000000000000000000000000000000000..4fc8671e7c1d8a9507f2e585dbfd391d3a0a1da2 GIT binary patch literal 2544 zcmchZ`9IX_7r^K988Z_z_I-&+b(;~NF~*WhGGr9RjO^>Htd|*~i=<|TB!!w%;_@Ao z<hKzd4yL`aG*CR2FsdMw*PAFJ*EiT-}ICg1PT9e4FCw30F%K$Zj2qx_xDxc+Pt%^ zaT~RLpT2Nc$0aP_-sPpf+X%z*h;myO%WTY*$lKu;L<_EA70QM(&dJ$QN%pu#;6G)WL$?02?~tE61DE>)7M~8+(_;l8>{uy0v$U`kt2^! zROE#}l_uJu35hLR!vY{FzkzrR{w&69ZzDxI$A|xu2)ybn4`IUXO70 z7X?{t1Tc4`p*0NCMBKTAQ3f&NWgYG9e(*N{F}rK8-^dZmR>wj~+wIFKZ(HM?0&?9R z%1v&hB<;}YN3sl+*W2$?^`5Y%3Rm>sru+1Ix0)MOl*{7gkG-EX7tU^x#RfGc7&Ys2 zFa?^!0~spm@K)OcxjrtxYTxyiy}zzQ4M+Rp&W2O37tNxVKAEVPXhi|k6qRQisdBZs zi;_w~iM}z9B;!U(#{*tvM%s*W;OC~!PqkfvE4kDgPhHUztR;>3jCM74Omg({_a~mf zNQ(5s6SJI{@7zL5rjn7^1Ka!2jjGS-A|#!#h_QS)+2;AcOsC$~BQ z<0*%8rH7MK9+tHie}3uGIzthJyp(7)4q0T1(JSAaAVoHQ#(rJh{Wklnv063KUU@#X z_%OxN>kB!$w7jHj9@ta&d=x4Fiy?XiD>pq%$t~}FOi4j##*4&@(=aJ<4@c_)6!sudx4H zd}LX0YlsCBIdBjFK|p9Lj0isU0sn0Re1egZ;Bo4oIB&zCtm(8cFPhh%8WaX)N482}s+9+oWNw4s0V#j)1hORWkT8EA{}Wze{&d=ogQvs%=pp`L zk&v>iFkTf)4j8LKyZ2lr6`)n)B(T2{-8EBWXEr^5&#`Uay<4)+d+K-h&W8 zh-3`Jw&hrUEL611x~MPY(Ra2lbmDi?w30Su1mSUd)k`|4MZSbml2aY%y4h0|a;mAQ zC(}YtBX(8xcnR^iGqIgbFWKZ zodfxE6H6sY#I9Sydw0K~H4u&+r-XXn_!$2zw_l)+cP}Y)PjlykkeIc@Y^wxEtCiKB zc8S4zp(Zv9C?~f=1~VoZV)HP;ZU8iB3SHLu@{6e(%&vth%2>ng0pS1)*qR}JvG6kl zz>H%GjZTks*npP2Q)f4Q*kVKAi_5R_dt}ygMw-J`gUPQQGMQM6hW&=u&2B_&_pHTK zM{sqaf?oA}fDi{&?yxb@=V+x-l&h$z{Tgrnvus}A;6!=1dW|K~lLsWH6rU7CHPb>SPh_H~D5u9@iVjyd;< zQwuKXPnHK2u5*nVRyfrcEHX=RS4Uo@_BkfTSu>*)TcWFXg+^CA;zS+Ddbz#mGz^Ak zf$4mtZt*85ME@s?_8Y!`4QvkoH6U@MkY^kjh+8!W1VKDp5+M9d1^=dkAh{m{SP+g! z{}50Br1V1&MBqjFd>Z@@NIs#?(2gyqBk&ReVsmeB{%qF7$KNicU{}!Cmu9ANYcaW5{MANlz50hBARWj&~JYW765x%f1tie zs=!k7*j}iD_qlDnDB8lF!II8YN-8X~M=kB*OnWpCJQfaHsU2Cy2D7_6;}>f_%+l2A zceX)|7k%?@UOQM2A-xGUNT*=6h!K`io}}Q!qbL9%$~dbBs*;mQi8E-In8oOs@o=hG zf$N6rY7oxA-KhBW{#rdry6%+`KMNm&!u(}J*R+Q#W8+a&qR-$t&B~`$?Oo0B`MK1A ztklhTe?;I;h$vbmiW-Y($nj;wRPGOBC~}+j-HpsIafD;#O{Ilyu~yZJFEuzOWVOod wOR_$HC%D4J~=ly%&01UMe3+o+3 zVdr6Y%CAbzP0TYCH4p}=;o{*b&(BE<4)%#RGBB|)lr#_r33KxZ1Qg|`7bWKAX6B{q zf~6!3#6VKaJpAS5<$54p#l<;#$@#g4@&>YS2XQir31sG_9Sk(GhDiIJbdpox)-sfm%1;V|<>?SGa_j9jgQ zPqb)j)s)QIyGkpF-Tm4!vrX(qeHV6RRv$a;GVe;G$6wuyMcwJU7nYtd)A70_{k?nF zdETGz-+XM8tDep5K5KvKnfg?f%w;b`I-{SMd_THDWb)VaYOAV>hm2ui6PF1)^(alHb!v&hks^eskB`Mqt2 zIvi%2HSdyhC{hx?9+aw5yy4t?$+PSJSL9S55MsXKSHv5TYrWWd@yxinCvNhzZob)d zGeqrn?yohw|Eu~Oxmfw7@N%1jgz$#stwnwYN2a&5>4xcF7yVv;VBOb0(NBLb+;y3W znUR5UaT6muFhrPvsew6EmXAe@Ma1}qYufdUc8R(W-U9WB$JMU4rXDb8ybO|8W@$Wa z(0HN&tD1$4OO`Y)9Q5g;2`NwVfIKD4!fL?G$oL;Qu>f-@FtIQ)Gz5htYLzzxyR2-; zb^Xt)S}WDBJUO_;R4D(0p2DlQ4au1u&v+Jk8a!yaoxxw%vgZH)YNuay`kR90U#g5V z6;e0bbAMWd%e2rFUQ?Ljz2@GzZ1p{NO?PG9pMCwx5m{YdEx4S%%_!*z)?-@#kZ)i9 znG)lgH(O3G_snf_@_${ddDw_STl7aqRe!F6^t#meqZhg^K1#`5yy9QV!%O(`i<)PBJ8m7gIIpUBZ}Y0@f0MU- z$(9jmob_Hrlf~I45#L+KXUOGzyAOL literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-ICA1-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-ICA1-key.pem new file mode 100644 index 000000000..8cd09c8d1 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-ICA1-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAsiuhP77AWL06vA0ZrMp/uTvwjDD/BLE0fiaGljZrUy5EHaH0 +vFF5VQXKu6CnnTMBk5YUZ+z0wy5mJ9FBaDSsjWRj2FWGnWIkme23/8tNnUBU1eOq +Raam2/5zQpRCwdAyXMQhrpyTALdKH56VpihtS9jAZefto23KGLP638lnGnUjYIOl +A19hveXWjZ0FRyN+oI3Rf0JOOKzOcLy/ewVbD4ICsJqNwBTK0EVelxDRoeEj2txp +nM5TzGiJxkBNabyrT8cRXmKi3+KlNHw5NidnNBEELCqzFtuO/dd7HZNfM8LKliIq +Q4KKSEYHE/9sHLC6C/DNP0zcNBePInBpnSLXxwIDAQABAoIBAH+tbFw14bi1wgVI +jgGZC3Y+Ud7krZs7MZbFHOVAEiEFoqJpkOvyprQa9nEGa5bnGlYc0nq2/59u/J3E +As8eEBkyu6onf9QApKH6DEUt92yc0S6Fe1t2VVSJPyeS/1PMUorPsiNi6KU2s9N8 +3Vi417nmldlxHoZjAtQ5BaqgtVXrMMIS05Q3bySULdOXYNu8hBGvGkR99tSyKQ1S +qVfJWi7dHrjiRPbYSW7aOaYID3QjB3GIqkcoUMWXTzdogE/EPKZL52CL+hBBw8C2 +4Q/8o0Wy60Futj/1Hdax6o/sVPDmoypDzYbbQ5IVcGM+SWykDn2+tNJDvfFp1T6k ++az1H0ECgYEA41cCvONXUQQ9PWSeNutdxS49c+tr0UN5/F09Yy6vVEWkjKuUwYzj +9RMxH6Hf0t6k3Qvm4x0m9jWFWTiUQVGDg9EU9AWSGeQ73TZN9gUaI5meWUQnZoiL +kJqkKvdiXfCSBwCRQuW3vrKyi8miLYTVTeBewjoUbZnkVkIN3+f0Vb8CgYEAyKHD +P0JE4UegsTB3r0VZtXHF+en2TcJ0kl4tc09O+R3FOmslmXpaG7ZMx+KVVCrmTlPl +pzScv1kNEhQYSJPIfbc1YxLOQNUf96oiTeG4RsCMm+zSIgYQKe5VKvEPrw4OfOQW +bqUyHGHfm4NSxmTZgi6ukgZqpTcD5KUyajZaz/kCgYBeWLfcKAUOrFG17tHyPM+X +i08ZknQWToiLgS5+wNsmgBiAAJ0ljhD0nlheplE7NAb7bXsOegS3XRLQKjjsuqV3 +yQeHFeDCOgPWFDlahleIurIKncw0MyqogmTrJ+t8zN/tZADk4GzXCVYrySwy89OK +FDl/JZdgvOMUISmc6KhwBQKBgGWOrJya2O8IKOlIVW0dN7nG66YDri/SXNuyXGNg +I+OqFCnsDs5Pxsj8UIVlxp0iUg4YHcmzshyR4THjhh9G31fzo0yROmJK/7GIJ3Ew +7uyxjvtmtz+NviTbhbUE7SF5hg/mDQzZBjKjwGKh6QaQCiIBq1Aze0xCOvBERu7I +sNNRAoGBAN5bKB0JoskQcd5uJTgwTrATrY4FNBPs2s/I8XIBYCLuvhGyiR95B7Uy +nZobhWFx2xwWWHksrJ8CKXodQuojtQPEC+JnoKeUvzEs95KvHwdxNGH74VMT8bqg +Q3qKoHsd8dkclcJbIPI3KCkpuaimqNits4ma+oVTuB0JyYFXEg+X +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-ICA1-pathlen0.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-ICA1-pathlen0.pem new file mode 100644 index 000000000..f4e62b953 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-ICA1-pathlen0.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainA-ICA1-pathlen0, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b2:2b:a1:3f:be:c0:58:bd:3a:bc:0d:19:ac:ca: + 7f:b9:3b:f0:8c:30:ff:04:b1:34:7e:26:86:96:36: + 6b:53:2e:44:1d:a1:f4:bc:51:79:55:05:ca:bb:a0: + a7:9d:33:01:93:96:14:67:ec:f4:c3:2e:66:27:d1: + 41:68:34:ac:8d:64:63:d8:55:86:9d:62:24:99:ed: + b7:ff:cb:4d:9d:40:54:d5:e3:aa:45:a6:a6:db:fe: + 73:42:94:42:c1:d0:32:5c:c4:21:ae:9c:93:00:b7: + 4a:1f:9e:95:a6:28:6d:4b:d8:c0:65:e7:ed:a3:6d: + ca:18:b3:fa:df:c9:67:1a:75:23:60:83:a5:03:5f: + 61:bd:e5:d6:8d:9d:05:47:23:7e:a0:8d:d1:7f:42: + 4e:38:ac:ce:70:bc:bf:7b:05:5b:0f:82:02:b0:9a: + 8d:c0:14:ca:d0:45:5e:97:10:d1:a1:e1:23:da:dc: + 69:9c:ce:53:cc:68:89:c6:40:4d:69:bc:ab:4f:c7: + 11:5e:62:a2:df:e2:a5:34:7c:39:36:27:67:34:11: + 04:2c:2a:b3:16:db:8e:fd:d7:7b:1d:93:5f:33:c2: + ca:96:22:2a:43:82:8a:48:46:07:13:ff:6c:1c:b0: + ba:0b:f0:cd:3f:4c:dc:34:17:8f:22:70:69:9d:22: + d7:c7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + A8:10:EA:C8:EF:4F:00:CD:E3:79:C3:EB:DF:F6:C8:86:9D:44:6C:26 + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:0 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 2a:15:34:be:88:ed:0b:5d:97:b4:c0:9e:f7:45:a2:ba:bb:a0: + 7f:a0:b3:93:15:79:38:27:36:25:91:5d:73:10:bb:d0:f9:f3: + e9:5f:98:c6:9b:6b:da:08:60:48:3e:26:17:2b:ae:22:08:ac: + 10:ed:a1:28:65:96:7f:94:75:c8:da:6c:c9:f6:4c:4c:b1:a3: + 45:4b:74:c7:de:49:f6:c1:1c:2c:eb:41:3c:2d:56:52:75:5b: + 7c:13:c0:dc:41:34:02:c0:e5:5e:79:71:65:ac:d1:f3:36:f7: + 55:d5:13:8f:0a:42:49:d9:fc:7f:5c:a4:cb:ad:7b:72:2f:98: + e2:56:92:9e:11:1a:b2:9d:5b:b9:2c:14:1e:51:f5:c5:b7:2c: + c2:39:52:90:0f:4e:04:5e:59:23:6f:d8:f9:75:2b:54:b0:6e: + 98:0a:54:3a:45:fd:9a:63:31:ce:a3:a8:ae:7b:be:03:81:a5: + 18:d3:00:51:a4:29:d4:f7:8d:53:31:72:85:80:c0:62:71:06: + 2b:07:b6:0a:b2:12:cf:2b:bd:99:34:6b:5e:ea:94:0c:1a:e8: + 2b:ee:e5:d6:3d:cb:7a:f6:f8:6e:e4:e2:f4:25:07:13:11:b1: + 18:b3:75:29:40:dc:bc:31:57:37:71:7c:09:bb:74:1c:9e:b4: + 3e:1d:47:20 +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA4WhcNMjIwNzA3MDAyODA4WjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluQS1JQ0Ex +LXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsiuhP77AWL06vA0ZrMp/uTvwjDD/ +BLE0fiaGljZrUy5EHaH0vFF5VQXKu6CnnTMBk5YUZ+z0wy5mJ9FBaDSsjWRj2FWG +nWIkme23/8tNnUBU1eOqRaam2/5zQpRCwdAyXMQhrpyTALdKH56VpihtS9jAZeft +o23KGLP638lnGnUjYIOlA19hveXWjZ0FRyN+oI3Rf0JOOKzOcLy/ewVbD4ICsJqN +wBTK0EVelxDRoeEj2txpnM5TzGiJxkBNabyrT8cRXmKi3+KlNHw5NidnNBEELCqz +FtuO/dd7HZNfM8LKliIqQ4KKSEYHE/9sHLC6C/DNP0zcNBePInBpnSLXxwIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFKgQ6sjvTwDN43nD69/2yIadRGwmMIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQAwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQAqFTS+iO0LXZe0wJ73RaK6u6B/oLOTFXk4JzYlkV1zELvQ+fPpX5jGm2va +CGBIPiYXK64iCKwQ7aEoZZZ/lHXI2mzJ9kxMsaNFS3TH3kn2wRws60E8LVZSdVt8 +E8DcQTQCwOVeeXFlrNHzNvdV1ROPCkJJ2fx/XKTLrXtyL5jiVpKeERqynVu5LBQe +UfXFtyzCOVKQD04EXlkjb9j5dStUsG6YClQ6Rf2aYzHOo6iue74DgaUY0wBRpCnU +941TMXKFgMBicQYrB7YKshLPK72ZNGte6pQMGugr7uXWPct69vhu5OL0JQcTEbEY +s3UpQNy8MVc3cXwJu3QcnrQ+HUcg +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-assembled.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-assembled.pem new file mode 100644 index 000000000..0661644ff --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-assembled.pem @@ -0,0 +1,175 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainA-ICA1-pathlen0, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainA-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d0:7a:d8:c8:6c:4f:a5:cd:72:25:87:ff:12:a3: + 65:0e:1d:1f:78:b2:d7:1a:65:a1:e7:4e:bd:05:b5: + 05:3e:39:3e:85:ad:90:c7:5b:a5:81:42:b5:01:00: + 57:87:29:a3:45:ce:f4:02:fa:80:8f:3b:8e:99:40: + 2c:fc:c8:b0:8b:2b:19:c3:20:c6:af:db:a0:d9:d5: + 70:32:6d:66:c3:ca:c4:ea:63:fb:08:0e:35:bc:50: + 7f:85:c7:62:f4:e2:85:e4:89:59:52:71:f2:e3:d1: + 63:3e:1d:08:6d:ff:86:cb:e5:eb:bc:1f:de:13:f0: + b2:f8:92:ee:23:9d:64:e7:b0:49:6f:26:a2:64:bc: + 9c:18:8a:f3:c6:db:83:a4:6c:b0:56:23:16:40:57: + b0:95:5e:1b:3d:c5:3f:10:7a:84:e0:3e:bb:78:e8: + 7d:c1:63:f3:fe:ee:af:16:db:ce:28:02:21:df:8b: + ca:f3:c3:1e:d1:47:c0:59:5f:1c:48:ec:50:6a:e3: + cc:fb:b6:16:45:40:c8:50:cf:dc:3e:2d:2d:cb:cd: + 19:2a:17:74:41:7f:bc:26:4d:cd:97:b2:2b:67:57: + 8e:6e:75:b5:d8:ec:6b:69:ab:09:3d:95:85:2c:0f: + d7:8d:29:75:1f:9b:88:56:bc:e8:11:a3:c8:65:e5: + 2b:23 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D6:56:A1:9C:F1:66:E4:05:17:36:32:74:BA:72:97:50:13:58:B3:3D + X509v3 Authority Key Identifier: + keyid:A8:10:EA:C8:EF:4F:00:CD:E3:79:C3:EB:DF:F6:C8:86:9D:44:6C:26 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 72:8d:c5:a7:a8:d5:4a:bc:d9:72:ef:46:79:53:5c:e8:32:10: + f5:29:ee:b0:6c:ef:68:80:a3:f6:0f:fe:ba:73:ce:a9:c4:93: + 01:ba:78:eb:a9:4a:f3:32:e2:4c:74:6c:f7:23:c9:70:44:a1: + d1:f7:59:d7:fd:34:12:ab:81:91:16:20:60:59:dd:ff:d5:6f: + 1f:d6:25:d9:95:85:7f:9d:dc:18:49:39:44:43:03:03:98:db: + 2e:03:a8:88:27:13:d2:a5:52:0e:15:a0:e5:5d:15:81:2b:3d: + 1c:cb:41:58:46:d3:4f:37:be:ae:45:eb:7d:9c:52:91:50:98: + a5:c1:e6:7b:1a:60:e0:d6:61:7e:88:19:b7:ec:8a:33:07:24: + 04:9f:78:89:50:97:9c:a4:1e:15:fc:ef:bf:29:4d:c3:8c:19: + d7:59:68:30:d2:08:d8:80:d8:7e:32:31:2b:ee:cf:7f:b4:47: + a4:bb:7d:cf:b6:64:9d:55:5c:e9:44:0a:43:ed:3b:c2:ae:1d: + 34:1c:bf:7e:5b:91:8c:26:76:fb:68:d9:3e:6b:68:22:ae:60: + 56:d3:4e:f3:b7:d1:de:da:47:03:2e:22:74:85:ea:52:de:22: + fd:90:55:21:8d:b2:e4:35:c3:15:44:f6:1a:01:3c:0a:56:f8: + 89:98:59:4a +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluQS1JQ0ExLXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOFoXDTIyMDcwNzAwMjgwOFowgZoxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRYwFAYDVQQD +DA1jaGFpbkEtZW50aXR5MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0HrYyGxPpc1yJYf/EqNl +Dh0feLLXGmWh5069BbUFPjk+ha2Qx1ulgUK1AQBXhymjRc70AvqAjzuOmUAs/Miw +iysZwyDGr9ug2dVwMm1mw8rE6mP7CA41vFB/hcdi9OKF5IlZUnHy49FjPh0Ibf+G +y+XrvB/eE/Cy+JLuI51k57BJbyaiZLycGIrzxtuDpGywViMWQFewlV4bPcU/EHqE +4D67eOh9wWPz/u6vFtvOKAIh34vK88Me0UfAWV8cSOxQauPM+7YWRUDIUM/cPi0t +y80ZKhd0QX+8Jk3Nl7IrZ1eObnW12OxraasJPZWFLA/XjSl1H5uIVrzoEaPIZeUr +IwIDAQABo4HxMIHuMB0GA1UdDgQWBBTWVqGc8WbkBRc2MnS6cpdQE1izPTCBwQYD +VR0jBIG5MIG2gBSoEOrI708AzeN5w+vf9siGnURsJqGBmqSBlzCBlDELMAkGA1UE +BhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNV +BAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cu +d29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CAWQw +CQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAco3Fp6jVSrzZcu9GeVNc6DIQ +9SnusGzvaICj9g/+unPOqcSTAbp466lK8zLiTHRs9yPJcESh0fdZ1/00EquBkRYg +YFnd/9VvH9Yl2ZWFf53cGEk5REMDA5jbLgOoiCcT0qVSDhWg5V0VgSs9HMtBWEbT +Tze+rkXrfZxSkVCYpcHmexpg4NZhfogZt+yKMwckBJ94iVCXnKQeFfzvvylNw4wZ +11loMNII2IDYfjIxK+7Pf7RHpLt9z7ZknVVc6UQKQ+07wq4dNBy/fluRjCZ2+2jZ +PmtoIq5gVtNO87fR3tpHAy4idIXqUt4i/ZBVIY2y5DXDFUT2GgE8Clb4iZhZSg== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainA-ICA1-pathlen0, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b2:2b:a1:3f:be:c0:58:bd:3a:bc:0d:19:ac:ca: + 7f:b9:3b:f0:8c:30:ff:04:b1:34:7e:26:86:96:36: + 6b:53:2e:44:1d:a1:f4:bc:51:79:55:05:ca:bb:a0: + a7:9d:33:01:93:96:14:67:ec:f4:c3:2e:66:27:d1: + 41:68:34:ac:8d:64:63:d8:55:86:9d:62:24:99:ed: + b7:ff:cb:4d:9d:40:54:d5:e3:aa:45:a6:a6:db:fe: + 73:42:94:42:c1:d0:32:5c:c4:21:ae:9c:93:00:b7: + 4a:1f:9e:95:a6:28:6d:4b:d8:c0:65:e7:ed:a3:6d: + ca:18:b3:fa:df:c9:67:1a:75:23:60:83:a5:03:5f: + 61:bd:e5:d6:8d:9d:05:47:23:7e:a0:8d:d1:7f:42: + 4e:38:ac:ce:70:bc:bf:7b:05:5b:0f:82:02:b0:9a: + 8d:c0:14:ca:d0:45:5e:97:10:d1:a1:e1:23:da:dc: + 69:9c:ce:53:cc:68:89:c6:40:4d:69:bc:ab:4f:c7: + 11:5e:62:a2:df:e2:a5:34:7c:39:36:27:67:34:11: + 04:2c:2a:b3:16:db:8e:fd:d7:7b:1d:93:5f:33:c2: + ca:96:22:2a:43:82:8a:48:46:07:13:ff:6c:1c:b0: + ba:0b:f0:cd:3f:4c:dc:34:17:8f:22:70:69:9d:22: + d7:c7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + A8:10:EA:C8:EF:4F:00:CD:E3:79:C3:EB:DF:F6:C8:86:9D:44:6C:26 + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:0 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 2a:15:34:be:88:ed:0b:5d:97:b4:c0:9e:f7:45:a2:ba:bb:a0: + 7f:a0:b3:93:15:79:38:27:36:25:91:5d:73:10:bb:d0:f9:f3: + e9:5f:98:c6:9b:6b:da:08:60:48:3e:26:17:2b:ae:22:08:ac: + 10:ed:a1:28:65:96:7f:94:75:c8:da:6c:c9:f6:4c:4c:b1:a3: + 45:4b:74:c7:de:49:f6:c1:1c:2c:eb:41:3c:2d:56:52:75:5b: + 7c:13:c0:dc:41:34:02:c0:e5:5e:79:71:65:ac:d1:f3:36:f7: + 55:d5:13:8f:0a:42:49:d9:fc:7f:5c:a4:cb:ad:7b:72:2f:98: + e2:56:92:9e:11:1a:b2:9d:5b:b9:2c:14:1e:51:f5:c5:b7:2c: + c2:39:52:90:0f:4e:04:5e:59:23:6f:d8:f9:75:2b:54:b0:6e: + 98:0a:54:3a:45:fd:9a:63:31:ce:a3:a8:ae:7b:be:03:81:a5: + 18:d3:00:51:a4:29:d4:f7:8d:53:31:72:85:80:c0:62:71:06: + 2b:07:b6:0a:b2:12:cf:2b:bd:99:34:6b:5e:ea:94:0c:1a:e8: + 2b:ee:e5:d6:3d:cb:7a:f6:f8:6e:e4:e2:f4:25:07:13:11:b1: + 18:b3:75:29:40:dc:bc:31:57:37:71:7c:09:bb:74:1c:9e:b4: + 3e:1d:47:20 +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA4WhcNMjIwNzA3MDAyODA4WjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluQS1JQ0Ex +LXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsiuhP77AWL06vA0ZrMp/uTvwjDD/ +BLE0fiaGljZrUy5EHaH0vFF5VQXKu6CnnTMBk5YUZ+z0wy5mJ9FBaDSsjWRj2FWG +nWIkme23/8tNnUBU1eOqRaam2/5zQpRCwdAyXMQhrpyTALdKH56VpihtS9jAZeft +o23KGLP638lnGnUjYIOlA19hveXWjZ0FRyN+oI3Rf0JOOKzOcLy/ewVbD4ICsJqN +wBTK0EVelxDRoeEj2txpnM5TzGiJxkBNabyrT8cRXmKi3+KlNHw5NidnNBEELCqz +FtuO/dd7HZNfM8LKliIqQ4KKSEYHE/9sHLC6C/DNP0zcNBePInBpnSLXxwIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFKgQ6sjvTwDN43nD69/2yIadRGwmMIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQAwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQAqFTS+iO0LXZe0wJ73RaK6u6B/oLOTFXk4JzYlkV1zELvQ+fPpX5jGm2va +CGBIPiYXK64iCKwQ7aEoZZZ/lHXI2mzJ9kxMsaNFS3TH3kn2wRws60E8LVZSdVt8 +E8DcQTQCwOVeeXFlrNHzNvdV1ROPCkJJ2fx/XKTLrXtyL5jiVpKeERqynVu5LBQe +UfXFtyzCOVKQD04EXlkjb9j5dStUsG6YClQ6Rf2aYzHOo6iue74DgaUY0wBRpCnU +941TMXKFgMBicQYrB7YKshLPK72ZNGte6pQMGugr7uXWPct69vhu5OL0JQcTEbEY +s3UpQNy8MVc3cXwJu3QcnrQ+HUcg +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-entity-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-entity-key.pem new file mode 100644 index 000000000..59730e1a2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-entity-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA0HrYyGxPpc1yJYf/EqNlDh0feLLXGmWh5069BbUFPjk+ha2Q +x1ulgUK1AQBXhymjRc70AvqAjzuOmUAs/MiwiysZwyDGr9ug2dVwMm1mw8rE6mP7 +CA41vFB/hcdi9OKF5IlZUnHy49FjPh0Ibf+Gy+XrvB/eE/Cy+JLuI51k57BJbyai +ZLycGIrzxtuDpGywViMWQFewlV4bPcU/EHqE4D67eOh9wWPz/u6vFtvOKAIh34vK +88Me0UfAWV8cSOxQauPM+7YWRUDIUM/cPi0ty80ZKhd0QX+8Jk3Nl7IrZ1eObnW1 +2OxraasJPZWFLA/XjSl1H5uIVrzoEaPIZeUrIwIDAQABAoIBAQCpeFMkiTctlpYF +gEmOwxfwoyfkG6zTnm4/8zegnggHDs2OKQsZo5wkOS+eAsMj8mrw4kxk53D9/fHr +DcoEKreoSX8FqW0ZozVcHi64L0psOjZcOq3jXHm9/MnM28nLOyCQKD5d0JcbLii4 +Yy1pDWBr+xjnshf6qZ0yh23hsZ5G3wUadf4CwFfEeTdUFw4vOAZRPdKQqGooR6NW +u7C6NWcrcoilX3tpcz6W+5TFfth0Uuyd10K9oBiGoQIx/qQcGg4wHVi+Si8PkRbX +9cRxOeJ6ozmoNikfTB6RUcAnCWJC3CtFZQHUX+CpBXc1pbQMKRGyo5WhqX32BI/s +8CE9pVYRAoGBAOfDlJMe6rPeP8e0s0Zc/tV2NCOZzhO8WLlPSnt731PXVooRjfPy +65gq6v7Wg6vdoniFC+NxVmeTTrTAPSuts8tqCKXq59CSoGkj1rxEsCgnEZJXtjZU +HUrukCyTPksnEjsOSR1obh7NUABut4ZVFMs6s2DSadyV4a9dw7y2zbrvAoGBAOZH +8Nt1OlCxJ2lmbADHRQCNW48oiWNB05xQkii0ZdOMKWHBbKkJa0JW67ru6issvzTe +RbzVcBQsipECTGFTmeJShTWs9yZPeOObIMHo8mEuzRf0n6W3O2AdB/XqGjO1idR/ +VyBiuP8Ttc5ofVyGg7tpPfYPcJ9s2MVi56MhXCMNAoGAWaafJ1XTRiaXl2G/41z/ +uoTR4F+ThrDZxTz1u9SL6/ulXx0xQwdZuPAJHPDP2ECQo3wbwCxMVx51WJfwUaAM +p4fptnyqlVTStjkFzKfpWG7cbjZ9poBdIGot3QBMHXgMpkl9YOHPjxyucKxjU5Q/ +yel4D+D00D4uIc7sc2hnJoMCgYEAhJsKxKVF1m+dPWGgcfZN8tpzzgVO0Bx46buv +3sa7GE3PCp7inphw7nu1NSkdKY2T8bLJP8s8xjE7/fLv3t/QbnaMhPM8QxBikdaj +z2YAJRxZOCFCyZ+xDlDJY7/SJNK2Muq9VkXjN+e2usyK2/wN4Z7h8k7D0NpSHaAt +uU+digUCgYEAiU2KYqosro3lzNh5vLc5ad/ZsE4m9RHf5AixXb3cf8CnAavczkPr +/X2k81+7Vbq7nv6WD9kMtaAfaYUU5tkqzlLO4i51IYXfzgyUNW4//wSMYqPDvhEt +M7+tIdaUTubZ8IhrCwgqHbs7VHejoWnFfIA2kgvWtR5m0UrXg0hGAmM= +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-entity.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-entity.pem new file mode 100644 index 000000000..277c4a644 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainA-entity.pem @@ -0,0 +1,86 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainA-ICA1-pathlen0, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainA-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d0:7a:d8:c8:6c:4f:a5:cd:72:25:87:ff:12:a3: + 65:0e:1d:1f:78:b2:d7:1a:65:a1:e7:4e:bd:05:b5: + 05:3e:39:3e:85:ad:90:c7:5b:a5:81:42:b5:01:00: + 57:87:29:a3:45:ce:f4:02:fa:80:8f:3b:8e:99:40: + 2c:fc:c8:b0:8b:2b:19:c3:20:c6:af:db:a0:d9:d5: + 70:32:6d:66:c3:ca:c4:ea:63:fb:08:0e:35:bc:50: + 7f:85:c7:62:f4:e2:85:e4:89:59:52:71:f2:e3:d1: + 63:3e:1d:08:6d:ff:86:cb:e5:eb:bc:1f:de:13:f0: + b2:f8:92:ee:23:9d:64:e7:b0:49:6f:26:a2:64:bc: + 9c:18:8a:f3:c6:db:83:a4:6c:b0:56:23:16:40:57: + b0:95:5e:1b:3d:c5:3f:10:7a:84:e0:3e:bb:78:e8: + 7d:c1:63:f3:fe:ee:af:16:db:ce:28:02:21:df:8b: + ca:f3:c3:1e:d1:47:c0:59:5f:1c:48:ec:50:6a:e3: + cc:fb:b6:16:45:40:c8:50:cf:dc:3e:2d:2d:cb:cd: + 19:2a:17:74:41:7f:bc:26:4d:cd:97:b2:2b:67:57: + 8e:6e:75:b5:d8:ec:6b:69:ab:09:3d:95:85:2c:0f: + d7:8d:29:75:1f:9b:88:56:bc:e8:11:a3:c8:65:e5: + 2b:23 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D6:56:A1:9C:F1:66:E4:05:17:36:32:74:BA:72:97:50:13:58:B3:3D + X509v3 Authority Key Identifier: + keyid:A8:10:EA:C8:EF:4F:00:CD:E3:79:C3:EB:DF:F6:C8:86:9D:44:6C:26 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 72:8d:c5:a7:a8:d5:4a:bc:d9:72:ef:46:79:53:5c:e8:32:10: + f5:29:ee:b0:6c:ef:68:80:a3:f6:0f:fe:ba:73:ce:a9:c4:93: + 01:ba:78:eb:a9:4a:f3:32:e2:4c:74:6c:f7:23:c9:70:44:a1: + d1:f7:59:d7:fd:34:12:ab:81:91:16:20:60:59:dd:ff:d5:6f: + 1f:d6:25:d9:95:85:7f:9d:dc:18:49:39:44:43:03:03:98:db: + 2e:03:a8:88:27:13:d2:a5:52:0e:15:a0:e5:5d:15:81:2b:3d: + 1c:cb:41:58:46:d3:4f:37:be:ae:45:eb:7d:9c:52:91:50:98: + a5:c1:e6:7b:1a:60:e0:d6:61:7e:88:19:b7:ec:8a:33:07:24: + 04:9f:78:89:50:97:9c:a4:1e:15:fc:ef:bf:29:4d:c3:8c:19: + d7:59:68:30:d2:08:d8:80:d8:7e:32:31:2b:ee:cf:7f:b4:47: + a4:bb:7d:cf:b6:64:9d:55:5c:e9:44:0a:43:ed:3b:c2:ae:1d: + 34:1c:bf:7e:5b:91:8c:26:76:fb:68:d9:3e:6b:68:22:ae:60: + 56:d3:4e:f3:b7:d1:de:da:47:03:2e:22:74:85:ea:52:de:22: + fd:90:55:21:8d:b2:e4:35:c3:15:44:f6:1a:01:3c:0a:56:f8: + 89:98:59:4a +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluQS1JQ0ExLXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOFoXDTIyMDcwNzAwMjgwOFowgZoxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRYwFAYDVQQD +DA1jaGFpbkEtZW50aXR5MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0HrYyGxPpc1yJYf/EqNl +Dh0feLLXGmWh5069BbUFPjk+ha2Qx1ulgUK1AQBXhymjRc70AvqAjzuOmUAs/Miw +iysZwyDGr9ug2dVwMm1mw8rE6mP7CA41vFB/hcdi9OKF5IlZUnHy49FjPh0Ibf+G +y+XrvB/eE/Cy+JLuI51k57BJbyaiZLycGIrzxtuDpGywViMWQFewlV4bPcU/EHqE +4D67eOh9wWPz/u6vFtvOKAIh34vK88Me0UfAWV8cSOxQauPM+7YWRUDIUM/cPi0t +y80ZKhd0QX+8Jk3Nl7IrZ1eObnW12OxraasJPZWFLA/XjSl1H5uIVrzoEaPIZeUr +IwIDAQABo4HxMIHuMB0GA1UdDgQWBBTWVqGc8WbkBRc2MnS6cpdQE1izPTCBwQYD +VR0jBIG5MIG2gBSoEOrI708AzeN5w+vf9siGnURsJqGBmqSBlzCBlDELMAkGA1UE +BhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNV +BAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cu +d29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CAWQw +CQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAco3Fp6jVSrzZcu9GeVNc6DIQ +9SnusGzvaICj9g/+unPOqcSTAbp466lK8zLiTHRs9yPJcESh0fdZ1/00EquBkRYg +YFnd/9VvH9Yl2ZWFf53cGEk5REMDA5jbLgOoiCcT0qVSDhWg5V0VgSs9HMtBWEbT +Tze+rkXrfZxSkVCYpcHmexpg4NZhfogZt+yKMwckBJ94iVCXnKQeFfzvvylNw4wZ +11loMNII2IDYfjIxK+7Pf7RHpLt9z7ZknVVc6UQKQ+07wq4dNBy/fluRjCZ2+2jZ +PmtoIq5gVtNO87fR3tpHAy4idIXqUt4i/ZBVIY2y5DXDFUT2GgE8Clb4iZhZSg== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA1-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA1-key.pem new file mode 100644 index 000000000..ee660fb61 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA1-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAsveqrpHRJEFSoSLg05eb4AyUnErks4WuqUOf7HoF3Yhc5RlS +UzmGirLihierA5q+xFRnr7msZeJhl3hmYCmQYghikaCWKw8wbNo9cDVSqKfVhUkl +alZZvGtFkcM3/AYNoqlG4imCG3emSTX7V18zApLla2fCYeI3nBJctSybKqWFlyJz +PTZQVRpqWdnarC0/5mqxHWBSAwVAX88GaPAyhlpvtQJj5i4enwmCjAMYGeR51TVu +2RefPMHZO5X5b/MZ0dO4XXyTN8N8O6BYx/vlLfVY05ty80N6Kexr9IaByOZgiyvF +rVnlpKAFlwkCAKdV3Fvv5IuDGu7IHLW25mFr0QIDAQABAoIBAAqE3BdeorhKzpyB +/EzzgEnu810sWbzjgpyYSPIRSf73YN5mWpxhqTLFyOKxui+ADO5lN6Lwet2SLMJG +ZV4Jk17vtztwAOOPBP2g5jOOLsmS883dusFBSgz1ESW8H7JEeNCyumPYpLkQk0mC +Tr+X7Nud3rYtZxNxxGr7+U78zDH5Z3G7CErHyZ27+wks/IjxZhvnjVByEjAo+wkK +wVm40vDj8QmdTG8z+1OSqCM5lY/k0VibuZyvQ9gbsXIpzPqxsd2HnrJSf4gShtBR +L6OV2QQFW923PxWCwG26rPdT4vVSDlBuPQ6BjFKsvjnsonxZYnNTSMAKFM+E0OSV +C6EmRwECgYEA2sY94Dt6FoYWPBYGioiNlDJ20lUal1s64yjrNjA209V1s1FYJIhN +utMQNqq+DwkQoLcy7TV/cleRs5lPp1nM++w+6HoMLqUUzPhygmLcvh9f7r/VLpUm ++8encqEOcUsr6V0fVt2s/Wj7611rzR1tXVklxEbWwke4libinDT//HkCgYEA0Wtx +3VIDLXqj5Z1pIX1ZBXgHdgsJvbJ6qrQ+1gnK3vnOixsz0HrTMh10IcC5J0XWKIHk +ldC6bt0+ZhvP0Jdu6yx19cYeIFkgATd7duicllFqn05RPwAmM2LcUj95gew/rHKY +9hJ+Mqb3x+eL5maO2ij6Wi6qEDQiOuffUZM25BkCgYEAwE5SRbECeJoVIWwbA9tU +2Fgjqm+0mCdRdCyb1V48U6jndWCjojlOWlL9hZBA0Oae/ycKVQkZpmDjaoPxSKHf +VfMsuR3PZ5Ek36fkwEg20ciygyONOQ1S3y95OYHpOB1j1BZPXgQt8/M8vn+4Ku0b +HVsnn4jFbrGsyBAWUkkkW8ECgYAljymq0gyz2W0Pv32dfge7TV25NB2ZIiuR9iXW +6YazGwaKOGTAnWbHdDTh4NjUTFguh61hmT/2pkOMuKw68w33q8+0NsYscw+kaDkC +iJGc/BktXTSBIhu316FANxYp0R9SZHM+nu53Uy7ZcZPLzNUOF49fIUNrCI6jFfcd +gFO18QKBgQCJL8qVYFIh5A8IicIM1fD17QiKPHI06f0KOXqQU33VLdGLRGwYruTh +NTlcvzevFMxEDyS7rhZk30PmNP9XpAVtoFYIdhJbA0Xnf2H8R1sN+zYZV/YgU1Og +E+pE9ay8jKsrmr1mvVVomPAtz0/yvZLsEt6ymL2tQm1A5CraeVhMTA== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA1-pathlen0.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA1-pathlen0.pem new file mode 100644 index 000000000..138560784 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA1-pathlen0.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainB-ICA2-pathlen1, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainB-ICA1-pathlen0, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b2:f7:aa:ae:91:d1:24:41:52:a1:22:e0:d3:97: + 9b:e0:0c:94:9c:4a:e4:b3:85:ae:a9:43:9f:ec:7a: + 05:dd:88:5c:e5:19:52:53:39:86:8a:b2:e2:86:27: + ab:03:9a:be:c4:54:67:af:b9:ac:65:e2:61:97:78: + 66:60:29:90:62:08:62:91:a0:96:2b:0f:30:6c:da: + 3d:70:35:52:a8:a7:d5:85:49:25:6a:56:59:bc:6b: + 45:91:c3:37:fc:06:0d:a2:a9:46:e2:29:82:1b:77: + a6:49:35:fb:57:5f:33:02:92:e5:6b:67:c2:61:e2: + 37:9c:12:5c:b5:2c:9b:2a:a5:85:97:22:73:3d:36: + 50:55:1a:6a:59:d9:da:ac:2d:3f:e6:6a:b1:1d:60: + 52:03:05:40:5f:cf:06:68:f0:32:86:5a:6f:b5:02: + 63:e6:2e:1e:9f:09:82:8c:03:18:19:e4:79:d5:35: + 6e:d9:17:9f:3c:c1:d9:3b:95:f9:6f:f3:19:d1:d3: + b8:5d:7c:93:37:c3:7c:3b:a0:58:c7:fb:e5:2d:f5: + 58:d3:9b:72:f3:43:7a:29:ec:6b:f4:86:81:c8:e6: + 60:8b:2b:c5:ad:59:e5:a4:a0:05:97:09:02:00:a7: + 55:dc:5b:ef:e4:8b:83:1a:ee:c8:1c:b5:b6:e6:61: + 6b:d1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D7:90:E4:86:59:24:F9:2B:B8:06:8E:B1:8F:33:E5:2C:63:F1:03:16 + X509v3 Authority Key Identifier: + keyid:EE:59:9D:56:0B:7C:0A:45:44:E3:15:57:E2:B2:F3:1D:64:6F:AF:7A + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:0 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + cd:0b:7e:66:b9:1d:a8:14:81:a8:e0:b3:74:d9:79:8a:c1:e5: + 15:cf:6a:a7:a3:ca:d2:ad:f8:f6:9f:c2:be:67:ee:cf:9a:3c: + 1c:a3:c4:db:2b:c8:a9:b1:55:94:a1:9e:e3:c2:6c:3a:95:90: + 7e:8f:29:56:c6:99:d2:e5:3b:8f:f3:9a:11:4a:97:22:07:d9: + e2:e5:f8:3e:0f:08:50:43:ea:66:13:6c:20:2e:71:95:10:07: + 88:89:2d:30:9c:96:b1:7e:42:5f:63:c3:8b:71:c6:1d:00:ee: + 83:d7:80:1b:fa:f4:fe:f5:b1:29:f8:c1:ca:1d:89:9b:7c:2a: + 84:00:e4:f5:04:2d:35:be:12:c1:fa:78:cb:bc:c9:04:8a:bf: + 87:57:99:3a:9f:0a:88:a5:e8:94:db:2b:8f:ba:5f:b4:75:7f: + ac:56:75:b4:db:7f:57:24:17:cb:89:f8:cb:8b:c4:b2:44:4a: + d9:57:82:fb:ce:0c:84:e2:2b:a5:f2:90:63:aa:b3:c5:e1:00: + 22:60:8f:23:1f:a8:97:4b:49:f7:f7:cb:92:f7:94:80:52:5b: + 8d:4a:c1:f1:d1:3e:9f:28:96:61:af:8e:72:8d:b6:9e:14:ed: + 14:db:ea:f0:fc:50:39:ca:c8:ab:1e:49:c3:9e:97:0a:d7:1c: + 6f:b2:17:9a +-----BEGIN CERTIFICATE----- +MIIExjCCA66gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluQi1JQ0EyLXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOFoXDTIyMDcwNzAwMjgwOFowgaExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR0wGwYDVQQD +DBRjaGFpbkItSUNBMS1wYXRobGVuMDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm +c3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALL3qq6R0SRB +UqEi4NOXm+AMlJxK5LOFrqlDn+x6Bd2IXOUZUlM5hoqy4oYnqwOavsRUZ6+5rGXi +YZd4ZmApkGIIYpGglisPMGzaPXA1Uqin1YVJJWpWWbxrRZHDN/wGDaKpRuIpght3 +pkk1+1dfMwKS5WtnwmHiN5wSXLUsmyqlhZcicz02UFUaalnZ2qwtP+ZqsR1gUgMF +QF/PBmjwMoZab7UCY+YuHp8JgowDGBnkedU1btkXnzzB2TuV+W/zGdHTuF18kzfD +fDugWMf75S31WNObcvNDeinsa/SGgcjmYIsrxa1Z5aSgBZcJAgCnVdxb7+SLgxru +yBy1tuZha9ECAwEAAaOCAQUwggEBMB0GA1UdDgQWBBTXkOSGWST5K7gGjrGPM+Us +Y/EDFjCBwQYDVR0jBIG5MIG2gBTuWZ1WC3wKRUTjFVfisvMdZG+veqGBmqSBlzCB +lDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVt +YW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYD +VQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb22CAWQwDwYDVR0TBAgwBgEB/wIBADALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN +AQELBQADggEBAM0Lfma5HagUgajgs3TZeYrB5RXPaqejytKt+Pafwr5n7s+aPByj +xNsryKmxVZShnuPCbDqVkH6PKVbGmdLlO4/zmhFKlyIH2eLl+D4PCFBD6mYTbCAu +cZUQB4iJLTCclrF+Ql9jw4txxh0A7oPXgBv69P71sSn4wcodiZt8KoQA5PUELTW+ +EsH6eMu8yQSKv4dXmTqfCoil6JTbK4+6X7R1f6xWdbTbf1ckF8uJ+MuLxLJEStlX +gvvODITiK6XykGOqs8XhACJgjyMfqJdLSff3y5L3lIBSW41KwfHRPp8olmGvjnKN +tp4U7RTb6vD8UDnKyKseScOelwrXHG+yF5o= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA2-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA2-key.pem new file mode 100644 index 000000000..14062373a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA2-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA0H+CBZ1bxEngPh+HbhcF6+IK0dGl9cy+HUbYzahuIs49XDlx +pA0D+nh+u2zoUeWY76ZeYtIw+juPIV+3X5i3n6hWejnKwt+hVv6Vl1ZeW/502fIu +yn7bUHda0ZDcItb+S8BXocY7SrqtBRTJJGh2teIm1ctQ/dB3DowMuV73pJpFNWxi +yuk41BCaXDClTyZHAwNzVoWMvvXQwAkGPg7o5X3QGVTtV+xRz7yVFZHP0JqE3YpQ +fDPCGmFwMZoZFyizjNpfuNIGa4I/tmooKYa0IMulr3Nm5Dc2gfA/rb8FuNsuxCLi +60aH9GDRpn/unEGn86rpN93a1vDNSKxR0XeNoQIDAQABAoIBAQCGBNAA5+squwnn +JMEa5LWrr/qgcBArdVXm37lQSKmyubr7YvlHKA6cm4Nq2lBjBCBQOzKEdvOAhXQ1 +UZ8/VZ0ChWRA4JESvkio8LAbPSseGuvlhCTLiMtUZ8P63RCDXIrNCm/JzvAh0uiQ +UZIRUwyrURkBZ9VBsRQ2R5OOPBsWs+FpVbx9w7Zvkq2shFDbqTm8bCPbM9huCNZb +Z01Zp9+j5MfxzK4tgkKct3fbNOKzKGmOivloMQFY1fABWHg6dsvT/EprqBYcuRfy +gf1a4wJM22Zkv6+7rN3qmly0bEriVLlkw+dbGawEScCnI9+ormrQG9B22ynUFj0c +nK+odMk5AoGBAPhxZ5jZI9APgXcdWhgThSCtzmm9sHyUEBEkVYWqtc4qnBGREB9e +cuDDOTCppc8fJvDo+MnrEHxIIhBdMCMAg1JIEOXgDNzgBPb7y/43qQLV9bYfHJ7P +jvYeZ/S7PASK0lYjFq+1BlTa7m47ajwA/fwgW1Z6aga4dEm+LOpwaAw3AoGBANbX +Dpw/lHOgLOa/Zz/AUHmdQcXwiZbGJSdRI2yKOaE6TUvOman/WrDy4UQyej3gT4M8 +3pUYl34Cn/gl8K3QpRMHT7C11iF1IX4vS/eSvxf7fwCwG+3MaP4LEuOiJ84a2ILo +8WM20/L8unGb1+0WlzV0TJFTe97RtYViHHG3G7jnAoGAGWkH7oMu/YXIeRVgdJvy +ftAoD3qeRW+jYQ11TdGS/L4w7j8HBh5T45c0Dz0av19xTSyW3ZgUPJHoIgJV/Q59 +X/oM+GX9Cs5C07wXNi4dNDQMCI+QDtItzhB4E3je/5vvPW4jUN9UAXPO9SlQiUiU +safhj6u/kmZlRnGUCHpsuesCgYBIUbpkVG63gWq7/iBWcHlmhs42QGNActDc7E49 +YkZGBKcyZoiJliDEQe4ck9VccN6zMdFHZTDRxTZuRO9Aw2ReBG8J8Bv1xUUSAf/T +hf13qDw3UhEEunN5WObx44r8sULCxoFDQZiVSgfE6I4GDD24S77eiLjA59zv2nfy +u43EbwKBgQDpH5SnH3GEqWAyDpehK2gK2f5Ho7ZPANo5Z0lllv7Ic+7aHWBAEiiq +vtRTvtl4GXzjvOuhcb3hPYft+YPTj8L8V1a2Bac4Ohxq73diwbTFgS1D4owJ/1jc +0mnPyANCeoe85znU1D1FGveQfBYqUSRiX9iEQsN42C1GPR/xBhm6oQ== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA2-pathlen1.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA2-pathlen1.pem new file mode 100644 index 000000000..5197a077d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-ICA2-pathlen1.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainB-ICA2-pathlen1, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d0:7f:82:05:9d:5b:c4:49:e0:3e:1f:87:6e:17: + 05:eb:e2:0a:d1:d1:a5:f5:cc:be:1d:46:d8:cd:a8: + 6e:22:ce:3d:5c:39:71:a4:0d:03:fa:78:7e:bb:6c: + e8:51:e5:98:ef:a6:5e:62:d2:30:fa:3b:8f:21:5f: + b7:5f:98:b7:9f:a8:56:7a:39:ca:c2:df:a1:56:fe: + 95:97:56:5e:5b:fe:74:d9:f2:2e:ca:7e:db:50:77: + 5a:d1:90:dc:22:d6:fe:4b:c0:57:a1:c6:3b:4a:ba: + ad:05:14:c9:24:68:76:b5:e2:26:d5:cb:50:fd:d0: + 77:0e:8c:0c:b9:5e:f7:a4:9a:45:35:6c:62:ca:e9: + 38:d4:10:9a:5c:30:a5:4f:26:47:03:03:73:56:85: + 8c:be:f5:d0:c0:09:06:3e:0e:e8:e5:7d:d0:19:54: + ed:57:ec:51:cf:bc:95:15:91:cf:d0:9a:84:dd:8a: + 50:7c:33:c2:1a:61:70:31:9a:19:17:28:b3:8c:da: + 5f:b8:d2:06:6b:82:3f:b6:6a:28:29:86:b4:20:cb: + a5:af:73:66:e4:37:36:81:f0:3f:ad:bf:05:b8:db: + 2e:c4:22:e2:eb:46:87:f4:60:d1:a6:7f:ee:9c:41: + a7:f3:aa:e9:37:dd:da:d6:f0:cd:48:ac:51:d1:77: + 8d:a1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EE:59:9D:56:0B:7C:0A:45:44:E3:15:57:E2:B2:F3:1D:64:6F:AF:7A + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:1 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + ab:c7:2b:9d:15:73:97:47:e0:88:32:9d:10:71:81:53:62:97: + dc:c4:72:73:49:3e:50:50:10:03:1e:22:58:82:e0:b3:da:ca: + 89:92:70:c8:54:0d:8e:a6:44:a0:26:5d:5d:52:d2:fb:63:e4: + 13:7e:30:9a:13:25:4e:c8:34:a1:c9:e6:69:24:64:98:e3:88: + 9c:86:18:62:53:70:ae:f0:d9:ed:f3:0c:e8:ec:5b:e5:27:85: + 16:d0:b0:f6:bd:5d:9a:62:41:26:25:31:88:70:fe:25:97:48: + f1:e6:21:1c:78:f7:68:03:59:21:db:f1:c5:92:96:24:b8:23: + fc:ab:52:95:70:6a:52:16:4d:fc:36:6b:5f:58:4f:3f:c9:f4: + e7:6e:52:41:42:99:41:07:c2:75:74:db:c2:49:84:7c:3f:c1: + ac:bd:d4:d5:8f:d0:73:95:18:8a:5d:f0:8d:dd:2d:f0:b7:61: + 8d:8a:ef:14:9f:fd:30:ba:10:e8:57:d3:1b:8e:2d:9b:74:b3: + 63:0d:0e:8c:f9:a2:f7:42:c8:e6:5e:83:6f:0f:9a:85:3b:6e: + 66:48:b9:a7:a8:fc:da:19:47:0c:90:26:0d:ce:15:fe:6a:1e: + 47:5a:49:f8:76:0f:3a:a8:68:cd:a6:38:4c:a6:ca:b2:b0:9b: + c7:46:43:cd +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA4WhcNMjIwNzA3MDAyODA4WjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluQi1JQ0Ey +LXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0H+CBZ1bxEngPh+HbhcF6+IK0dGl +9cy+HUbYzahuIs49XDlxpA0D+nh+u2zoUeWY76ZeYtIw+juPIV+3X5i3n6hWejnK +wt+hVv6Vl1ZeW/502fIuyn7bUHda0ZDcItb+S8BXocY7SrqtBRTJJGh2teIm1ctQ +/dB3DowMuV73pJpFNWxiyuk41BCaXDClTyZHAwNzVoWMvvXQwAkGPg7o5X3QGVTt +V+xRz7yVFZHP0JqE3YpQfDPCGmFwMZoZFyizjNpfuNIGa4I/tmooKYa0IMulr3Nm +5Dc2gfA/rb8FuNsuxCLi60aH9GDRpn/unEGn86rpN93a1vDNSKxR0XeNoQIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFO5ZnVYLfApFROMVV+Ky8x1kb696MIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQEwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQCrxyudFXOXR+CIMp0QcYFTYpfcxHJzST5QUBADHiJYguCz2sqJknDIVA2O +pkSgJl1dUtL7Y+QTfjCaEyVOyDShyeZpJGSY44ichhhiU3Cu8Nnt8wzo7FvlJ4UW +0LD2vV2aYkEmJTGIcP4ll0jx5iEcePdoA1kh2/HFkpYkuCP8q1KVcGpSFk38Nmtf +WE8/yfTnblJBQplBB8J1dNvCSYR8P8GsvdTVj9BzlRiKXfCN3S3wt2GNiu8Un/0w +uhDoV9Mbji2bdLNjDQ6M+aL3QsjmXoNvD5qFO25mSLmnqPzaGUcMkCYNzhX+ah5H +Wkn4dg86qGjNpjhMpsqysJvHRkPN +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-assembled.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-assembled.pem new file mode 100644 index 000000000..7f83c5f55 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-assembled.pem @@ -0,0 +1,265 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainB-ICA1-pathlen0, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainB-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d7:5f:d9:3d:d7:5b:11:aa:3e:53:31:d0:32:78: + 87:fb:c0:8e:80:6d:fc:68:73:1f:9c:77:66:16:35: + fc:2f:d7:e4:ca:ba:2a:73:5f:14:94:12:f0:48:31: + a2:40:ad:b4:e3:07:0c:02:47:b4:0a:07:69:d5:d2: + 85:bf:c8:bc:14:8c:c7:87:ba:5f:87:c5:07:f4:df: + a4:46:1e:b7:13:0f:9d:7e:f6:1a:7b:29:09:55:4c: + 17:ee:c8:b0:9d:39:0c:89:6e:18:9c:06:7f:5d:95: + d2:4c:71:b3:1f:ea:5d:d2:f6:2c:69:a8:16:15:59: + e5:7d:03:d7:bd:1a:34:e3:f1:27:e3:b9:7d:68:e0: + 39:3f:35:62:2f:20:20:fa:19:62:37:1a:30:47:6c: + a3:f9:8e:9c:f3:67:2e:bb:38:4c:2e:0a:21:9b:70: + b6:97:a2:1b:b3:98:0d:5b:74:97:33:f0:b8:6c:4e: + ad:b4:1f:48:62:c9:9a:af:2d:a6:a1:06:ae:98:30: + 54:5e:cb:dd:23:77:d5:ee:5c:fb:81:f0:2b:ad:6f: + fa:e3:b1:0e:98:bd:3e:0b:f4:7c:c5:e3:50:bf:08: + 9b:bf:be:f8:6a:d9:db:78:36:84:f2:7e:7b:7d:5e: + a7:8f:42:81:5f:41:f4:77:5c:30:51:f5:3f:2d:25: + 95:4d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 7F:17:7E:8E:A8:2C:AD:9C:C7:22:7E:A6:C6:90:9E:63:C4:5F:33:9E + X509v3 Authority Key Identifier: + keyid:D7:90:E4:86:59:24:F9:2B:B8:06:8E:B1:8F:33:E5:2C:63:F1:03:16 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainB-ICA2-pathlen1/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 1f:ee:5c:85:ed:4e:3b:39:6b:29:a2:ef:65:b9:f3:c7:47:85: + 8e:79:a0:35:1b:aa:0e:98:67:a8:df:03:9c:2b:81:24:ed:cb: + cc:c0:42:49:76:bf:78:7b:b9:39:ca:f6:06:35:76:dd:e3:59: + c5:70:3b:b3:cf:62:0a:09:1d:07:90:96:c4:0e:0a:38:97:f7: + 31:1d:ad:44:f9:03:f9:30:22:b6:68:01:00:38:23:3d:f6:e7: + 71:5a:e4:d4:59:52:4f:80:86:ec:8f:ca:92:1d:9b:07:93:fe: + 34:22:ac:9a:a2:aa:9e:fe:f5:7b:99:fd:72:32:40:98:88:d8: + 42:1d:33:59:4c:38:2e:97:f2:9d:a2:fc:b7:33:cd:84:c1:c6: + ef:f5:c5:d9:be:32:ba:44:66:06:62:5c:55:31:38:b4:25:1a: + 6a:64:de:14:39:b4:38:74:1b:d7:c4:ec:81:fc:3a:13:4b:e1: + d1:b1:5f:3c:8e:25:bc:63:7f:30:78:04:4e:79:3a:83:97:52: + f6:00:6a:9e:d8:b5:c6:06:21:97:4a:98:ee:cf:e8:83:94:23: + 11:6c:00:d7:e9:35:1f:89:77:85:9a:d7:8f:29:90:c6:61:14: + e5:7d:55:5b:66:65:60:44:79:8a:1b:58:88:b9:0f:5f:a6:5f: + 7a:ca:6b:0c +-----BEGIN CERTIFICATE----- +MIIEtzCCA5+gAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluQi1JQ0ExLXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOFoXDTIyMDcwNzAwMjgwOFowgZoxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRYwFAYDVQQD +DA1jaGFpbkItZW50aXR5MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA11/ZPddbEao+UzHQMniH ++8COgG38aHMfnHdmFjX8L9fkyroqc18UlBLwSDGiQK204wcMAke0Cgdp1dKFv8i8 +FIzHh7pfh8UH9N+kRh63Ew+dfvYaeykJVUwX7siwnTkMiW4YnAZ/XZXSTHGzH+pd +0vYsaagWFVnlfQPXvRo04/En47l9aOA5PzViLyAg+hliNxowR2yj+Y6c82cuuzhM +Lgohm3C2l6Ibs5gNW3SXM/C4bE6ttB9IYsmary2moQaumDBUXsvdI3fV7lz7gfAr +rW/647EOmL0+C/R8xeNQvwibv774atnbeDaE8n57fV6nj0KBX0H0d1wwUfU/LSWV +TQIDAQABo4H+MIH7MB0GA1UdDgQWBBR/F36OqCytnMcifqbGkJ5jxF8znjCBzgYD +VR0jBIHGMIHDgBTXkOSGWST5K7gGjrGPM+UsY/EDFqGBp6SBpDCBoTELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNV +BAMMFGNoYWluQi1JQ0EyLXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tggFkMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAB/uXIXt +Tjs5aymi72W588dHhY55oDUbqg6YZ6jfA5wrgSTty8zAQkl2v3h7uTnK9gY1dt3j +WcVwO7PPYgoJHQeQlsQOCjiX9zEdrUT5A/kwIrZoAQA4Iz3253Fa5NRZUk+AhuyP +ypIdmweT/jQirJqiqp7+9XuZ/XIyQJiI2EIdM1lMOC6X8p2i/LczzYTBxu/1xdm+ +MrpEZgZiXFUxOLQlGmpk3hQ5tDh0G9fE7IH8OhNL4dGxXzyOJbxjfzB4BE55OoOX +UvYAap7YtcYGIZdKmO7P6IOUIxFsANfpNR+Jd4Wa148pkMZhFOV9VVtmZWBEeYob +WIi5D1+mX3rKaww= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainB-ICA2-pathlen1, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainB-ICA1-pathlen0, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b2:f7:aa:ae:91:d1:24:41:52:a1:22:e0:d3:97: + 9b:e0:0c:94:9c:4a:e4:b3:85:ae:a9:43:9f:ec:7a: + 05:dd:88:5c:e5:19:52:53:39:86:8a:b2:e2:86:27: + ab:03:9a:be:c4:54:67:af:b9:ac:65:e2:61:97:78: + 66:60:29:90:62:08:62:91:a0:96:2b:0f:30:6c:da: + 3d:70:35:52:a8:a7:d5:85:49:25:6a:56:59:bc:6b: + 45:91:c3:37:fc:06:0d:a2:a9:46:e2:29:82:1b:77: + a6:49:35:fb:57:5f:33:02:92:e5:6b:67:c2:61:e2: + 37:9c:12:5c:b5:2c:9b:2a:a5:85:97:22:73:3d:36: + 50:55:1a:6a:59:d9:da:ac:2d:3f:e6:6a:b1:1d:60: + 52:03:05:40:5f:cf:06:68:f0:32:86:5a:6f:b5:02: + 63:e6:2e:1e:9f:09:82:8c:03:18:19:e4:79:d5:35: + 6e:d9:17:9f:3c:c1:d9:3b:95:f9:6f:f3:19:d1:d3: + b8:5d:7c:93:37:c3:7c:3b:a0:58:c7:fb:e5:2d:f5: + 58:d3:9b:72:f3:43:7a:29:ec:6b:f4:86:81:c8:e6: + 60:8b:2b:c5:ad:59:e5:a4:a0:05:97:09:02:00:a7: + 55:dc:5b:ef:e4:8b:83:1a:ee:c8:1c:b5:b6:e6:61: + 6b:d1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D7:90:E4:86:59:24:F9:2B:B8:06:8E:B1:8F:33:E5:2C:63:F1:03:16 + X509v3 Authority Key Identifier: + keyid:EE:59:9D:56:0B:7C:0A:45:44:E3:15:57:E2:B2:F3:1D:64:6F:AF:7A + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:0 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + cd:0b:7e:66:b9:1d:a8:14:81:a8:e0:b3:74:d9:79:8a:c1:e5: + 15:cf:6a:a7:a3:ca:d2:ad:f8:f6:9f:c2:be:67:ee:cf:9a:3c: + 1c:a3:c4:db:2b:c8:a9:b1:55:94:a1:9e:e3:c2:6c:3a:95:90: + 7e:8f:29:56:c6:99:d2:e5:3b:8f:f3:9a:11:4a:97:22:07:d9: + e2:e5:f8:3e:0f:08:50:43:ea:66:13:6c:20:2e:71:95:10:07: + 88:89:2d:30:9c:96:b1:7e:42:5f:63:c3:8b:71:c6:1d:00:ee: + 83:d7:80:1b:fa:f4:fe:f5:b1:29:f8:c1:ca:1d:89:9b:7c:2a: + 84:00:e4:f5:04:2d:35:be:12:c1:fa:78:cb:bc:c9:04:8a:bf: + 87:57:99:3a:9f:0a:88:a5:e8:94:db:2b:8f:ba:5f:b4:75:7f: + ac:56:75:b4:db:7f:57:24:17:cb:89:f8:cb:8b:c4:b2:44:4a: + d9:57:82:fb:ce:0c:84:e2:2b:a5:f2:90:63:aa:b3:c5:e1:00: + 22:60:8f:23:1f:a8:97:4b:49:f7:f7:cb:92:f7:94:80:52:5b: + 8d:4a:c1:f1:d1:3e:9f:28:96:61:af:8e:72:8d:b6:9e:14:ed: + 14:db:ea:f0:fc:50:39:ca:c8:ab:1e:49:c3:9e:97:0a:d7:1c: + 6f:b2:17:9a +-----BEGIN CERTIFICATE----- +MIIExjCCA66gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluQi1JQ0EyLXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOFoXDTIyMDcwNzAwMjgwOFowgaExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR0wGwYDVQQD +DBRjaGFpbkItSUNBMS1wYXRobGVuMDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm +c3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALL3qq6R0SRB +UqEi4NOXm+AMlJxK5LOFrqlDn+x6Bd2IXOUZUlM5hoqy4oYnqwOavsRUZ6+5rGXi +YZd4ZmApkGIIYpGglisPMGzaPXA1Uqin1YVJJWpWWbxrRZHDN/wGDaKpRuIpght3 +pkk1+1dfMwKS5WtnwmHiN5wSXLUsmyqlhZcicz02UFUaalnZ2qwtP+ZqsR1gUgMF +QF/PBmjwMoZab7UCY+YuHp8JgowDGBnkedU1btkXnzzB2TuV+W/zGdHTuF18kzfD +fDugWMf75S31WNObcvNDeinsa/SGgcjmYIsrxa1Z5aSgBZcJAgCnVdxb7+SLgxru +yBy1tuZha9ECAwEAAaOCAQUwggEBMB0GA1UdDgQWBBTXkOSGWST5K7gGjrGPM+Us +Y/EDFjCBwQYDVR0jBIG5MIG2gBTuWZ1WC3wKRUTjFVfisvMdZG+veqGBmqSBlzCB +lDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVt +YW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYD +VQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb22CAWQwDwYDVR0TBAgwBgEB/wIBADALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN +AQELBQADggEBAM0Lfma5HagUgajgs3TZeYrB5RXPaqejytKt+Pafwr5n7s+aPByj +xNsryKmxVZShnuPCbDqVkH6PKVbGmdLlO4/zmhFKlyIH2eLl+D4PCFBD6mYTbCAu +cZUQB4iJLTCclrF+Ql9jw4txxh0A7oPXgBv69P71sSn4wcodiZt8KoQA5PUELTW+ +EsH6eMu8yQSKv4dXmTqfCoil6JTbK4+6X7R1f6xWdbTbf1ckF8uJ+MuLxLJEStlX +gvvODITiK6XykGOqs8XhACJgjyMfqJdLSff3y5L3lIBSW41KwfHRPp8olmGvjnKN +tp4U7RTb6vD8UDnKyKseScOelwrXHG+yF5o= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainB-ICA2-pathlen1, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d0:7f:82:05:9d:5b:c4:49:e0:3e:1f:87:6e:17: + 05:eb:e2:0a:d1:d1:a5:f5:cc:be:1d:46:d8:cd:a8: + 6e:22:ce:3d:5c:39:71:a4:0d:03:fa:78:7e:bb:6c: + e8:51:e5:98:ef:a6:5e:62:d2:30:fa:3b:8f:21:5f: + b7:5f:98:b7:9f:a8:56:7a:39:ca:c2:df:a1:56:fe: + 95:97:56:5e:5b:fe:74:d9:f2:2e:ca:7e:db:50:77: + 5a:d1:90:dc:22:d6:fe:4b:c0:57:a1:c6:3b:4a:ba: + ad:05:14:c9:24:68:76:b5:e2:26:d5:cb:50:fd:d0: + 77:0e:8c:0c:b9:5e:f7:a4:9a:45:35:6c:62:ca:e9: + 38:d4:10:9a:5c:30:a5:4f:26:47:03:03:73:56:85: + 8c:be:f5:d0:c0:09:06:3e:0e:e8:e5:7d:d0:19:54: + ed:57:ec:51:cf:bc:95:15:91:cf:d0:9a:84:dd:8a: + 50:7c:33:c2:1a:61:70:31:9a:19:17:28:b3:8c:da: + 5f:b8:d2:06:6b:82:3f:b6:6a:28:29:86:b4:20:cb: + a5:af:73:66:e4:37:36:81:f0:3f:ad:bf:05:b8:db: + 2e:c4:22:e2:eb:46:87:f4:60:d1:a6:7f:ee:9c:41: + a7:f3:aa:e9:37:dd:da:d6:f0:cd:48:ac:51:d1:77: + 8d:a1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EE:59:9D:56:0B:7C:0A:45:44:E3:15:57:E2:B2:F3:1D:64:6F:AF:7A + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:1 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + ab:c7:2b:9d:15:73:97:47:e0:88:32:9d:10:71:81:53:62:97: + dc:c4:72:73:49:3e:50:50:10:03:1e:22:58:82:e0:b3:da:ca: + 89:92:70:c8:54:0d:8e:a6:44:a0:26:5d:5d:52:d2:fb:63:e4: + 13:7e:30:9a:13:25:4e:c8:34:a1:c9:e6:69:24:64:98:e3:88: + 9c:86:18:62:53:70:ae:f0:d9:ed:f3:0c:e8:ec:5b:e5:27:85: + 16:d0:b0:f6:bd:5d:9a:62:41:26:25:31:88:70:fe:25:97:48: + f1:e6:21:1c:78:f7:68:03:59:21:db:f1:c5:92:96:24:b8:23: + fc:ab:52:95:70:6a:52:16:4d:fc:36:6b:5f:58:4f:3f:c9:f4: + e7:6e:52:41:42:99:41:07:c2:75:74:db:c2:49:84:7c:3f:c1: + ac:bd:d4:d5:8f:d0:73:95:18:8a:5d:f0:8d:dd:2d:f0:b7:61: + 8d:8a:ef:14:9f:fd:30:ba:10:e8:57:d3:1b:8e:2d:9b:74:b3: + 63:0d:0e:8c:f9:a2:f7:42:c8:e6:5e:83:6f:0f:9a:85:3b:6e: + 66:48:b9:a7:a8:fc:da:19:47:0c:90:26:0d:ce:15:fe:6a:1e: + 47:5a:49:f8:76:0f:3a:a8:68:cd:a6:38:4c:a6:ca:b2:b0:9b: + c7:46:43:cd +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA4WhcNMjIwNzA3MDAyODA4WjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluQi1JQ0Ey +LXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0H+CBZ1bxEngPh+HbhcF6+IK0dGl +9cy+HUbYzahuIs49XDlxpA0D+nh+u2zoUeWY76ZeYtIw+juPIV+3X5i3n6hWejnK +wt+hVv6Vl1ZeW/502fIuyn7bUHda0ZDcItb+S8BXocY7SrqtBRTJJGh2teIm1ctQ +/dB3DowMuV73pJpFNWxiyuk41BCaXDClTyZHAwNzVoWMvvXQwAkGPg7o5X3QGVTt +V+xRz7yVFZHP0JqE3YpQfDPCGmFwMZoZFyizjNpfuNIGa4I/tmooKYa0IMulr3Nm +5Dc2gfA/rb8FuNsuxCLi60aH9GDRpn/unEGn86rpN93a1vDNSKxR0XeNoQIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFO5ZnVYLfApFROMVV+Ky8x1kb696MIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQEwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQCrxyudFXOXR+CIMp0QcYFTYpfcxHJzST5QUBADHiJYguCz2sqJknDIVA2O +pkSgJl1dUtL7Y+QTfjCaEyVOyDShyeZpJGSY44ichhhiU3Cu8Nnt8wzo7FvlJ4UW +0LD2vV2aYkEmJTGIcP4ll0jx5iEcePdoA1kh2/HFkpYkuCP8q1KVcGpSFk38Nmtf +WE8/yfTnblJBQplBB8J1dNvCSYR8P8GsvdTVj9BzlRiKXfCN3S3wt2GNiu8Un/0w +uhDoV9Mbji2bdLNjDQ6M+aL3QsjmXoNvD5qFO25mSLmnqPzaGUcMkCYNzhX+ah5H +Wkn4dg86qGjNpjhMpsqysJvHRkPN +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-entity-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-entity-key.pem new file mode 100644 index 000000000..1c4206298 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-entity-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA11/ZPddbEao+UzHQMniH+8COgG38aHMfnHdmFjX8L9fkyroq +c18UlBLwSDGiQK204wcMAke0Cgdp1dKFv8i8FIzHh7pfh8UH9N+kRh63Ew+dfvYa +eykJVUwX7siwnTkMiW4YnAZ/XZXSTHGzH+pd0vYsaagWFVnlfQPXvRo04/En47l9 +aOA5PzViLyAg+hliNxowR2yj+Y6c82cuuzhMLgohm3C2l6Ibs5gNW3SXM/C4bE6t +tB9IYsmary2moQaumDBUXsvdI3fV7lz7gfArrW/647EOmL0+C/R8xeNQvwibv774 +atnbeDaE8n57fV6nj0KBX0H0d1wwUfU/LSWVTQIDAQABAoIBAH2lLB5YuYc3sz5j +rBsVl/c1oayo/XyN1N46BbNlcScUIyRlsQg3atDrr4PeeNKUxBdB8C6QWCcVpheY +xnBZEehHLMww3TRerMKdib9igdk73dzIhDBfg1NgngGu0OIX+wld0juLytf05Ie2 +ORKgbnX5KXXGGoQAOtJQ4JYwaLSk1Ccz/Oa9LrYKPNqoDT90EagCSlie+/McEbu5 +oX/Wn4cmK2TF0XXGpcFzvZ5r1Humzvb7cbPl+HAYHdceTzS6nUREokCC37j3x+ks +6gRgYGR78uk+oayKBk7PFK6KW5T4U/TFpMkiJ9iEYprMap74P8L/rdqgLot+VIFM +/5y70CECgYEA9dJA/cCuIEDKMDaS1SwhigPZOqMw1iGflDjZbZw2nd5Vo7EcLghS +G4+YDMOj/ATd/2Ukb0/uoeZqz6qg/8RePrgRs+yafYI1r5MJqV4TXAX2OZm0H9Fa +Bcih7FWZFM7Y0BhYQAD9x816jq0fvq6mt/g95q9PAiZNp9mug1BSjQkCgYEA4Era +Rsqhrg3OVW64RTL6iRbG5JnyWPRbclYHBubGR7adV0SFYmPNdLhlONfe1dsXtrS5 +R/2nKCSBJJKE6Mgd0iTD+BDvi7PgQhxu4SIjm3RstYDNg4LfIg3eEVChzQHG8lrZ +23zPJAUt6rFW6EfYnPZWFF4nLeJvv8yxgxqtWyUCgYEAiePI5Q5iHmF5iRXzw3Qf +1CVYgxXrXRI7S4+gF2YbFO8Upt/AaOnt9NvVdMOBhurMBGkdyPrTZymzHI4gBZiH +LTNfasf72Q9jQft+3eyRe3s0pRbc/UQX9UqX2dQiLJPi9sfRKQXlVWCjsMjYF8Qs +bOHpBy+raA9IXDE1PR+fTtECgYEAz6m+KukVhNdXgJYAmmE2wZKLF8DJNz8XI+cu +nl8wmdkkGFZiwNPyt+y6G0UTFiHB9PGi0lqxV2NlBn15/SS7J4POxXC4uToTmmJE +7sDzAs1qkSnuHaMgAKGiR5nGFM9eaalgJ+2Iw6rf9nm3I1zR25Hf5P+/eqY6HPTi +LaaXdtkCgYBgvU/odZK0iBhqBsAxDfbk7BhnV9jKQOvkm7T6NupjmxhPmLQaFnWG +d7KyYH052MpHR4+sTGo+LqFT7PGSo2FQDpRRUJ7NjocFr9jVi2LU3B3bDpQU7vKi +Odovr+9RuHqcTiwnULPMlPeeXFIlWFT3tz2v6jodGjf8ejzv3IbH5g== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-entity.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-entity.pem new file mode 100644 index 000000000..cca6f6697 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainB-entity.pem @@ -0,0 +1,87 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainB-ICA1-pathlen0, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainB-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d7:5f:d9:3d:d7:5b:11:aa:3e:53:31:d0:32:78: + 87:fb:c0:8e:80:6d:fc:68:73:1f:9c:77:66:16:35: + fc:2f:d7:e4:ca:ba:2a:73:5f:14:94:12:f0:48:31: + a2:40:ad:b4:e3:07:0c:02:47:b4:0a:07:69:d5:d2: + 85:bf:c8:bc:14:8c:c7:87:ba:5f:87:c5:07:f4:df: + a4:46:1e:b7:13:0f:9d:7e:f6:1a:7b:29:09:55:4c: + 17:ee:c8:b0:9d:39:0c:89:6e:18:9c:06:7f:5d:95: + d2:4c:71:b3:1f:ea:5d:d2:f6:2c:69:a8:16:15:59: + e5:7d:03:d7:bd:1a:34:e3:f1:27:e3:b9:7d:68:e0: + 39:3f:35:62:2f:20:20:fa:19:62:37:1a:30:47:6c: + a3:f9:8e:9c:f3:67:2e:bb:38:4c:2e:0a:21:9b:70: + b6:97:a2:1b:b3:98:0d:5b:74:97:33:f0:b8:6c:4e: + ad:b4:1f:48:62:c9:9a:af:2d:a6:a1:06:ae:98:30: + 54:5e:cb:dd:23:77:d5:ee:5c:fb:81:f0:2b:ad:6f: + fa:e3:b1:0e:98:bd:3e:0b:f4:7c:c5:e3:50:bf:08: + 9b:bf:be:f8:6a:d9:db:78:36:84:f2:7e:7b:7d:5e: + a7:8f:42:81:5f:41:f4:77:5c:30:51:f5:3f:2d:25: + 95:4d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 7F:17:7E:8E:A8:2C:AD:9C:C7:22:7E:A6:C6:90:9E:63:C4:5F:33:9E + X509v3 Authority Key Identifier: + keyid:D7:90:E4:86:59:24:F9:2B:B8:06:8E:B1:8F:33:E5:2C:63:F1:03:16 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainB-ICA2-pathlen1/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 1f:ee:5c:85:ed:4e:3b:39:6b:29:a2:ef:65:b9:f3:c7:47:85: + 8e:79:a0:35:1b:aa:0e:98:67:a8:df:03:9c:2b:81:24:ed:cb: + cc:c0:42:49:76:bf:78:7b:b9:39:ca:f6:06:35:76:dd:e3:59: + c5:70:3b:b3:cf:62:0a:09:1d:07:90:96:c4:0e:0a:38:97:f7: + 31:1d:ad:44:f9:03:f9:30:22:b6:68:01:00:38:23:3d:f6:e7: + 71:5a:e4:d4:59:52:4f:80:86:ec:8f:ca:92:1d:9b:07:93:fe: + 34:22:ac:9a:a2:aa:9e:fe:f5:7b:99:fd:72:32:40:98:88:d8: + 42:1d:33:59:4c:38:2e:97:f2:9d:a2:fc:b7:33:cd:84:c1:c6: + ef:f5:c5:d9:be:32:ba:44:66:06:62:5c:55:31:38:b4:25:1a: + 6a:64:de:14:39:b4:38:74:1b:d7:c4:ec:81:fc:3a:13:4b:e1: + d1:b1:5f:3c:8e:25:bc:63:7f:30:78:04:4e:79:3a:83:97:52: + f6:00:6a:9e:d8:b5:c6:06:21:97:4a:98:ee:cf:e8:83:94:23: + 11:6c:00:d7:e9:35:1f:89:77:85:9a:d7:8f:29:90:c6:61:14: + e5:7d:55:5b:66:65:60:44:79:8a:1b:58:88:b9:0f:5f:a6:5f: + 7a:ca:6b:0c +-----BEGIN CERTIFICATE----- +MIIEtzCCA5+gAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluQi1JQ0ExLXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOFoXDTIyMDcwNzAwMjgwOFowgZoxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRYwFAYDVQQD +DA1jaGFpbkItZW50aXR5MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA11/ZPddbEao+UzHQMniH ++8COgG38aHMfnHdmFjX8L9fkyroqc18UlBLwSDGiQK204wcMAke0Cgdp1dKFv8i8 +FIzHh7pfh8UH9N+kRh63Ew+dfvYaeykJVUwX7siwnTkMiW4YnAZ/XZXSTHGzH+pd +0vYsaagWFVnlfQPXvRo04/En47l9aOA5PzViLyAg+hliNxowR2yj+Y6c82cuuzhM +Lgohm3C2l6Ibs5gNW3SXM/C4bE6ttB9IYsmary2moQaumDBUXsvdI3fV7lz7gfAr +rW/647EOmL0+C/R8xeNQvwibv774atnbeDaE8n57fV6nj0KBX0H0d1wwUfU/LSWV +TQIDAQABo4H+MIH7MB0GA1UdDgQWBBR/F36OqCytnMcifqbGkJ5jxF8znjCBzgYD +VR0jBIHGMIHDgBTXkOSGWST5K7gGjrGPM+UsY/EDFqGBp6SBpDCBoTELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNV +BAMMFGNoYWluQi1JQ0EyLXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tggFkMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAB/uXIXt +Tjs5aymi72W588dHhY55oDUbqg6YZ6jfA5wrgSTty8zAQkl2v3h7uTnK9gY1dt3j +WcVwO7PPYgoJHQeQlsQOCjiX9zEdrUT5A/kwIrZoAQA4Iz3253Fa5NRZUk+AhuyP +ypIdmweT/jQirJqiqp7+9XuZ/XIyQJiI2EIdM1lMOC6X8p2i/LczzYTBxu/1xdm+ +MrpEZgZiXFUxOLQlGmpk3hQ5tDh0G9fE7IH8OhNL4dGxXzyOJbxjfzB4BE55OoOX +UvYAap7YtcYGIZdKmO7P6IOUIxFsANfpNR+Jd4Wa148pkMZhFOV9VVtmZWBEeYob +WIi5D1+mX3rKaww= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-ICA1-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-ICA1-key.pem new file mode 100644 index 000000000..63826260e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-ICA1-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuxpswb27mynKNT1joynNpmXEnqPFUJmtUZAKmpuDzr4Gu2ZP +7x4xJTRvX5iuAUnDYxeEuXptwNj9DP+aAkxBN0nwGGMbT/w3Jk5UedcXOVB5bqMp +mQetnVzY4QLnM37k2qQFvGID059qkZJm3SnQlfsvP/BZuHBbJVR7oAqfMwlk7fvU +HC2WVEXjUJj/sX+axs8Jo9rpV60dBY8edXXn0gcz3tp9QtgOlP6ux5vDtZ7zayGf +dMSzMnwoTg+8FTO6nAk8wUAGeLuxID9hFfYeSXNRiZUtlb801sKp0TQdjSFtT6Nu +7/wjonb80CVTDkN2O+2C7NgjyzPvPJ2h3uZ6rQIDAQABAoIBAQCBojJeHbYBMHgg +YRNKtij9NB+BhpisWn2COFmQe1Vchb6mUqHpW7LTQzwzMNbGn7PXUTEtTU0Dw5O4 +UNQE6Y553ymRzADdbzNKwBS5gjReCorIBBZLJ827bNv7Moa74Bxx/BjZR9O86QPu +LlBExbb2Y11+YGnZZ0dPWvR4k0NwGM+zsEVfJQcRR7JXaQ720123sg+7TuTk30X/ +mgayttEyJhLt7UqulYagTethwKLY18fdvHTOGdES5Xiw+bWC7PKa/FePX8YXnFVN +Cz3t4l4Us/xs22nYo4IG2lu1LSxy2IxPV92w4KX4XcrwTW3+eH8+tfPByp3gFTdP +ZetlWehBAoGBAOLoOMIwLLSN5S0tJ4vwQaxn0YqEwJsEaSx85SUujhbsbjgyeVF6 +iN/v6TTb2EYliZvtQirkC7GMnS313AxzpUFO7+V/xf3jYDK7t+UJ1ap3zUU3vUOb +F4FKorNbfoxYd/vtZ7wt/KvuCKvDTszv8NhUNzFhXeIEzFhf+S4SDqFdAoGBANMX +uAZoLngBmAyw2zYcWTW5U9armeycTDpfxDpM4PjbxOs17/hK0G4IXqzCfQ2Hi0bl +fW6KeO5FqD9d5klIYo0278w4n5FpvA3yxqVlHoqXCtSYedSWsXN/sl7Ak1d2VngW +ecytOdrBxvQy9wqnmk3lhJby5DNWiuiUafudlxmRAoGAbFPhhRPqw+haWU8Nakmx +kNWfvDnUmi1o6MxXuYCYZWlK1ZmDQdr2LbMj6xBqGFMjd0W2KTPmQUWYZLDT9T3g +z2UYMsDljWhYLOBh0v72+wNnBHyv5u7MMfWn52ju6aHy5ltZAwYRcyOZECeWH1EN +8rmCABkz8QvJYweutsf4JCECgYEAz6B7zCl602TV9l2aL/3wLSyNbw+4RYdyXtRF +QQbPHVekt6mE0BZeLmwjGw/tSnpwnpopJqoiylJPa4xjbt84uCc59AgZw0BZzOpn +QtVUFgL8jyEua9CQ18bZXeNSyWtHH7UTtiMITcfddeIPJTa3Sjkfkg10MZ7E4IDi +Qa++qFECgYBRM+cS7jwo5oulYJ7Sqs8n1pj8MNGSLEcPQaTOxMUWqtkaN9iVQLx7 +lI/FYusedOReZ/+UDUrwZDdMXYrnL4/f8STXidDsY2+LOilaT2XggdBABe0bCjbf +r/Pknwx2VkwWFbDN6h/U9tKU47allf64kCQqzgoZtzMXTefZiAxLrw== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-ICA1-pathlen1.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-ICA1-pathlen1.pem new file mode 100644 index 000000000..64cbc0c6b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-ICA1-pathlen1.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainC-ICA1-pathlen1, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bb:1a:6c:c1:bd:bb:9b:29:ca:35:3d:63:a3:29: + cd:a6:65:c4:9e:a3:c5:50:99:ad:51:90:0a:9a:9b: + 83:ce:be:06:bb:66:4f:ef:1e:31:25:34:6f:5f:98: + ae:01:49:c3:63:17:84:b9:7a:6d:c0:d8:fd:0c:ff: + 9a:02:4c:41:37:49:f0:18:63:1b:4f:fc:37:26:4e: + 54:79:d7:17:39:50:79:6e:a3:29:99:07:ad:9d:5c: + d8:e1:02:e7:33:7e:e4:da:a4:05:bc:62:03:d3:9f: + 6a:91:92:66:dd:29:d0:95:fb:2f:3f:f0:59:b8:70: + 5b:25:54:7b:a0:0a:9f:33:09:64:ed:fb:d4:1c:2d: + 96:54:45:e3:50:98:ff:b1:7f:9a:c6:cf:09:a3:da: + e9:57:ad:1d:05:8f:1e:75:75:e7:d2:07:33:de:da: + 7d:42:d8:0e:94:fe:ae:c7:9b:c3:b5:9e:f3:6b:21: + 9f:74:c4:b3:32:7c:28:4e:0f:bc:15:33:ba:9c:09: + 3c:c1:40:06:78:bb:b1:20:3f:61:15:f6:1e:49:73: + 51:89:95:2d:95:bf:34:d6:c2:a9:d1:34:1d:8d:21: + 6d:4f:a3:6e:ef:fc:23:a2:76:fc:d0:25:53:0e:43: + 76:3b:ed:82:ec:d8:23:cb:33:ef:3c:9d:a1:de:e6: + 7a:ad + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 94:1D:2E:07:37:C6:2F:52:C1:EC:79:6B:13:CE:09:90:5F:F4:C4:51 + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:1 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 65:d2:6a:a3:a2:98:ac:5a:53:e4:b4:02:66:8e:9c:64:fa:53: + 88:a7:31:09:fa:31:4d:27:7a:17:7a:1c:8f:13:2a:e5:60:e4: + f2:0f:6a:e6:a6:48:ed:e4:17:0e:cb:57:77:66:98:c0:37:2f: + 00:26:1e:1a:a8:e4:ad:9e:c9:47:4d:6c:c5:57:75:79:97:be: + 0f:82:92:aa:b0:df:0d:f4:25:49:fd:c6:6f:e7:70:f1:f0:0d: + e7:13:81:ed:a1:1e:69:f3:10:3d:3e:3c:5b:c0:71:fb:44:47: + e2:bc:51:62:6c:21:7a:ea:ad:74:f5:46:35:63:93:ab:f9:89: + 31:e6:01:5f:eb:ca:df:d3:93:86:3d:8b:0a:88:79:f1:b1:47: + df:1f:2e:a0:7e:34:f6:80:30:7d:bd:e5:70:43:0d:76:2a:fc: + fe:38:4f:3a:bc:58:52:81:37:5e:e9:3b:26:f4:8d:20:5f:f2: + 44:56:e8:b8:cc:42:7a:5e:67:28:34:c3:8f:a9:08:87:92:4b: + bc:1d:3b:d1:1a:d8:79:20:eb:4a:6f:87:b3:3b:ef:2f:a6:98: + 34:48:a6:43:ba:d4:fa:65:6f:54:9b:28:a1:e1:77:fe:0e:91: + 0b:4f:f5:95:3e:b3:c9:4e:2d:17:67:37:5b:d5:dd:83:ef:a4: + b4:41:53:36 +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA4WhcNMjIwNzA3MDAyODA4WjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluQy1JQ0Ex +LXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuxpswb27mynKNT1joynNpmXEnqPF +UJmtUZAKmpuDzr4Gu2ZP7x4xJTRvX5iuAUnDYxeEuXptwNj9DP+aAkxBN0nwGGMb +T/w3Jk5UedcXOVB5bqMpmQetnVzY4QLnM37k2qQFvGID059qkZJm3SnQlfsvP/BZ +uHBbJVR7oAqfMwlk7fvUHC2WVEXjUJj/sX+axs8Jo9rpV60dBY8edXXn0gcz3tp9 +QtgOlP6ux5vDtZ7zayGfdMSzMnwoTg+8FTO6nAk8wUAGeLuxID9hFfYeSXNRiZUt +lb801sKp0TQdjSFtT6Nu7/wjonb80CVTDkN2O+2C7NgjyzPvPJ2h3uZ6rQIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFJQdLgc3xi9Swex5axPOCZBf9MRRMIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQEwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQBl0mqjopisWlPktAJmjpxk+lOIpzEJ+jFNJ3oXehyPEyrlYOTyD2rmpkjt +5BcOy1d3ZpjANy8AJh4aqOStnslHTWzFV3V5l74PgpKqsN8N9CVJ/cZv53Dx8A3n +E4HtoR5p8xA9PjxbwHH7REfivFFibCF66q109UY1Y5Or+Ykx5gFf68rf05OGPYsK +iHnxsUffHy6gfjT2gDB9veVwQw12Kvz+OE86vFhSgTde6Tsm9I0gX/JEVui4zEJ6 +XmcoNMOPqQiHkku8HTvRGth5IOtKb4ezO+8vppg0SKZDutT6ZW9Umyih4Xf+DpEL +T/WVPrPJTi0XZzdb1d2D76S0QVM2 +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-assembled.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-assembled.pem new file mode 100644 index 000000000..0fae68780 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-assembled.pem @@ -0,0 +1,175 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainC-ICA1-pathlen1, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainC-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bf:34:e1:1c:2c:2d:a4:93:b5:c4:fc:65:40:fa: + 94:68:74:24:ff:52:a4:df:3e:f1:7c:92:14:f0:f0: + 91:ed:9c:7e:a0:7e:b1:07:20:38:b2:c4:a2:b8:09: + d1:06:ee:fa:c6:7e:4d:79:be:dd:83:18:cf:e8:a7: + 78:88:cd:44:ce:3a:40:05:7a:6e:c5:c9:e4:84:64: + e0:01:7d:4f:f9:87:d2:94:91:e9:c8:21:bc:71:2e: + ef:f6:61:23:46:6b:da:5f:32:23:a1:86:9c:c6:9a: + b4:98:35:6d:36:b8:34:14:fd:9d:63:2f:75:7e:58: + f2:08:f9:e3:32:2a:a6:d2:b1:49:05:d3:8c:d4:48: + 5c:c2:57:07:62:4e:7a:05:23:c2:4f:ca:d5:a8:38: + 32:92:c2:21:3b:74:3e:2d:b1:6b:57:96:81:a3:2d: + ce:6e:9c:d9:ce:1f:e9:42:f8:2c:bb:fe:07:57:c6: + c8:93:6e:89:d3:fc:d2:83:4b:c1:2c:ea:5e:41:c9: + 7c:be:6c:23:01:89:75:1b:1f:57:ac:83:dc:da:e1: + 63:55:d8:94:fc:2d:a6:99:15:d1:71:88:a5:1b:f5: + 6f:39:0a:bd:ec:09:02:09:77:a7:5d:da:78:f8:8f: + b1:5d:a7:83:12:10:5f:89:ae:72:c2:88:bf:3e:80: + 98:c3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 91:79:7C:91:A7:A0:BC:E1:7B:77:9E:51:6E:5C:A7:7A:D9:3F:18:A0 + X509v3 Authority Key Identifier: + keyid:94:1D:2E:07:37:C6:2F:52:C1:EC:79:6B:13:CE:09:90:5F:F4:C4:51 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + b7:d0:5e:86:77:76:45:77:c3:f8:5c:cd:9b:84:52:b7:8b:d6: + 84:ed:d3:1b:fa:7f:27:d1:24:05:11:9d:bf:74:eb:14:93:ee: + 08:2c:16:0a:d8:00:46:31:e3:43:f1:95:64:b1:72:93:49:fa: + fe:73:e8:be:2a:02:95:e8:3a:56:f3:aa:8b:fa:cb:3a:f5:06: + a2:00:ae:19:36:86:be:93:79:3f:58:f7:95:de:a8:e2:12:89: + 52:2f:a0:be:09:3e:18:69:19:d5:96:7c:94:9a:ee:ab:f1:2b: + 74:54:c9:1c:0a:5f:aa:d1:62:34:24:33:f8:5e:b2:43:9c:c9: + e6:8c:fa:b5:89:a7:3e:6b:51:00:a6:e3:d5:c4:f9:ac:78:a5: + 4d:85:7c:e3:7d:f9:b5:e8:ad:3e:32:56:fb:99:bf:f9:3b:a4: + 98:04:72:cd:ea:95:08:af:7e:62:2d:74:e4:25:48:43:25:ba: + 07:7c:00:c9:31:41:6f:59:ff:da:bb:ac:08:06:18:1a:0a:3d: + 1d:2e:ad:98:2c:06:72:51:f2:75:7c:87:ef:e0:37:f6:80:70: + aa:8d:d9:a8:13:e5:31:91:3c:e3:0f:21:33:0a:15:91:1c:4d: + 3a:1b:35:f6:4c:f5:5f:70:34:b2:dc:ed:10:5d:37:58:16:e4: + e0:83:12:90 +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluQy1JQ0ExLXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOFoXDTIyMDcwNzAwMjgwOFowgZoxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRYwFAYDVQQD +DA1jaGFpbkMtZW50aXR5MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvzThHCwtpJO1xPxlQPqU +aHQk/1Kk3z7xfJIU8PCR7Zx+oH6xByA4ssSiuAnRBu76xn5Neb7dgxjP6Kd4iM1E +zjpABXpuxcnkhGTgAX1P+YfSlJHpyCG8cS7v9mEjRmvaXzIjoYacxpq0mDVtNrg0 +FP2dYy91fljyCPnjMiqm0rFJBdOM1EhcwlcHYk56BSPCT8rVqDgyksIhO3Q+LbFr +V5aBoy3ObpzZzh/pQvgsu/4HV8bIk26J0/zSg0vBLOpeQcl8vmwjAYl1Gx9XrIPc +2uFjVdiU/C2mmRXRcYilG/VvOQq97AkCCXenXdp4+I+xXaeDEhBfia5ywoi/PoCY +wwIDAQABo4HxMIHuMB0GA1UdDgQWBBSReXyRp6C84Xt3nlFuXKd62T8YoDCBwQYD +VR0jBIG5MIG2gBSUHS4HN8YvUsHseWsTzgmQX/TEUaGBmqSBlzCBlDELMAkGA1UE +BhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNV +BAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cu +d29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CAWQw +CQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAt9Behnd2RXfD+FzNm4RSt4vW +hO3TG/p/J9EkBRGdv3TrFJPuCCwWCtgARjHjQ/GVZLFyk0n6/nPovioCleg6VvOq +i/rLOvUGogCuGTaGvpN5P1j3ld6o4hKJUi+gvgk+GGkZ1ZZ8lJruq/ErdFTJHApf +qtFiNCQz+F6yQ5zJ5oz6tYmnPmtRAKbj1cT5rHilTYV84335teitPjJW+5m/+Tuk +mARyzeqVCK9+Yi105CVIQyW6B3wAyTFBb1n/2rusCAYYGgo9HS6tmCwGclHydXyH +7+A39oBwqo3ZqBPlMZE84w8hMwoVkRxNOhs19kz1X3A0stztEF03WBbk4IMSkA== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainC-ICA1-pathlen1, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bb:1a:6c:c1:bd:bb:9b:29:ca:35:3d:63:a3:29: + cd:a6:65:c4:9e:a3:c5:50:99:ad:51:90:0a:9a:9b: + 83:ce:be:06:bb:66:4f:ef:1e:31:25:34:6f:5f:98: + ae:01:49:c3:63:17:84:b9:7a:6d:c0:d8:fd:0c:ff: + 9a:02:4c:41:37:49:f0:18:63:1b:4f:fc:37:26:4e: + 54:79:d7:17:39:50:79:6e:a3:29:99:07:ad:9d:5c: + d8:e1:02:e7:33:7e:e4:da:a4:05:bc:62:03:d3:9f: + 6a:91:92:66:dd:29:d0:95:fb:2f:3f:f0:59:b8:70: + 5b:25:54:7b:a0:0a:9f:33:09:64:ed:fb:d4:1c:2d: + 96:54:45:e3:50:98:ff:b1:7f:9a:c6:cf:09:a3:da: + e9:57:ad:1d:05:8f:1e:75:75:e7:d2:07:33:de:da: + 7d:42:d8:0e:94:fe:ae:c7:9b:c3:b5:9e:f3:6b:21: + 9f:74:c4:b3:32:7c:28:4e:0f:bc:15:33:ba:9c:09: + 3c:c1:40:06:78:bb:b1:20:3f:61:15:f6:1e:49:73: + 51:89:95:2d:95:bf:34:d6:c2:a9:d1:34:1d:8d:21: + 6d:4f:a3:6e:ef:fc:23:a2:76:fc:d0:25:53:0e:43: + 76:3b:ed:82:ec:d8:23:cb:33:ef:3c:9d:a1:de:e6: + 7a:ad + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 94:1D:2E:07:37:C6:2F:52:C1:EC:79:6B:13:CE:09:90:5F:F4:C4:51 + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:1 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 65:d2:6a:a3:a2:98:ac:5a:53:e4:b4:02:66:8e:9c:64:fa:53: + 88:a7:31:09:fa:31:4d:27:7a:17:7a:1c:8f:13:2a:e5:60:e4: + f2:0f:6a:e6:a6:48:ed:e4:17:0e:cb:57:77:66:98:c0:37:2f: + 00:26:1e:1a:a8:e4:ad:9e:c9:47:4d:6c:c5:57:75:79:97:be: + 0f:82:92:aa:b0:df:0d:f4:25:49:fd:c6:6f:e7:70:f1:f0:0d: + e7:13:81:ed:a1:1e:69:f3:10:3d:3e:3c:5b:c0:71:fb:44:47: + e2:bc:51:62:6c:21:7a:ea:ad:74:f5:46:35:63:93:ab:f9:89: + 31:e6:01:5f:eb:ca:df:d3:93:86:3d:8b:0a:88:79:f1:b1:47: + df:1f:2e:a0:7e:34:f6:80:30:7d:bd:e5:70:43:0d:76:2a:fc: + fe:38:4f:3a:bc:58:52:81:37:5e:e9:3b:26:f4:8d:20:5f:f2: + 44:56:e8:b8:cc:42:7a:5e:67:28:34:c3:8f:a9:08:87:92:4b: + bc:1d:3b:d1:1a:d8:79:20:eb:4a:6f:87:b3:3b:ef:2f:a6:98: + 34:48:a6:43:ba:d4:fa:65:6f:54:9b:28:a1:e1:77:fe:0e:91: + 0b:4f:f5:95:3e:b3:c9:4e:2d:17:67:37:5b:d5:dd:83:ef:a4: + b4:41:53:36 +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA4WhcNMjIwNzA3MDAyODA4WjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluQy1JQ0Ex +LXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuxpswb27mynKNT1joynNpmXEnqPF +UJmtUZAKmpuDzr4Gu2ZP7x4xJTRvX5iuAUnDYxeEuXptwNj9DP+aAkxBN0nwGGMb +T/w3Jk5UedcXOVB5bqMpmQetnVzY4QLnM37k2qQFvGID059qkZJm3SnQlfsvP/BZ +uHBbJVR7oAqfMwlk7fvUHC2WVEXjUJj/sX+axs8Jo9rpV60dBY8edXXn0gcz3tp9 +QtgOlP6ux5vDtZ7zayGfdMSzMnwoTg+8FTO6nAk8wUAGeLuxID9hFfYeSXNRiZUt +lb801sKp0TQdjSFtT6Nu7/wjonb80CVTDkN2O+2C7NgjyzPvPJ2h3uZ6rQIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFJQdLgc3xi9Swex5axPOCZBf9MRRMIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQEwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQBl0mqjopisWlPktAJmjpxk+lOIpzEJ+jFNJ3oXehyPEyrlYOTyD2rmpkjt +5BcOy1d3ZpjANy8AJh4aqOStnslHTWzFV3V5l74PgpKqsN8N9CVJ/cZv53Dx8A3n +E4HtoR5p8xA9PjxbwHH7REfivFFibCF66q109UY1Y5Or+Ykx5gFf68rf05OGPYsK +iHnxsUffHy6gfjT2gDB9veVwQw12Kvz+OE86vFhSgTde6Tsm9I0gX/JEVui4zEJ6 +XmcoNMOPqQiHkku8HTvRGth5IOtKb4ezO+8vppg0SKZDutT6ZW9Umyih4Xf+DpEL +T/WVPrPJTi0XZzdb1d2D76S0QVM2 +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-entity-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-entity-key.pem new file mode 100644 index 000000000..1043ec961 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-entity-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpgIBAAKCAQEAvzThHCwtpJO1xPxlQPqUaHQk/1Kk3z7xfJIU8PCR7Zx+oH6x +ByA4ssSiuAnRBu76xn5Neb7dgxjP6Kd4iM1EzjpABXpuxcnkhGTgAX1P+YfSlJHp +yCG8cS7v9mEjRmvaXzIjoYacxpq0mDVtNrg0FP2dYy91fljyCPnjMiqm0rFJBdOM +1EhcwlcHYk56BSPCT8rVqDgyksIhO3Q+LbFrV5aBoy3ObpzZzh/pQvgsu/4HV8bI +k26J0/zSg0vBLOpeQcl8vmwjAYl1Gx9XrIPc2uFjVdiU/C2mmRXRcYilG/VvOQq9 +7AkCCXenXdp4+I+xXaeDEhBfia5ywoi/PoCYwwIDAQABAoIBAQCSlHYyQ8flz/rb +/WWeD7sv7EHknjWYk0dLaS22m6YzUvJcFWOfA9uTaF0Z2ySsPQ5wlqjMOT7VXnMc +dy5XKY2iz1L/ICHFbQXLXQ3A9pEVyULs9IMVEo/E8OeyqDsDpHDu46AfFvQe6MCj +oumLtmDu6pH6VIqtBoDd0ruSXNIw17a99b7kdCsGq4cobwbPmQtqc4+bpEd1+5si +EErSmHA+x1u/M2B1xJo9KPFAHKifGTBpU7t/uSPAmGmA/oq1fkhAkqYmBlxbLi72 +E6T7BoXpZ42dzaZnKXRU1M2uo3hocaZaZdZ4eRWrJcjpAnL12HyfpotOKFUJbNZY +ILZlVIMpAoGBAOMr6kz51tfSTLj/vcp/U/zelSE6J9VGlhGoeW8fkyI1rZ2scOo1 +kHQgOcaOwptAatNmclJuAChc3cwflN232egbRLEMWDdUXTwydSH/Aldjj0SZkgqz +n4wlOmXW05faInU8DeIHq8m1IoTcjciH5QLc/Gq24dBElSsXLFOS7mdNAoGBANd4 +k1dPyoYkGPjEO89E6rSnwv2pGvj+Eu9EANpCtkx6o341yxWCou6GDTxiepZe18Ed +RGV/QWQCYPRQXJf+XwTrmxMJ3VN8+jHN8kd/iZPbIgti4Tn68Svkjq97yEBMcAjH +sYyMo2Iuo6e8kWGJJJe+5JuLflu8YjZQglANfZhPAoGBAIls4ZqbcUqyX9Nycn/z +sv1AMXseUUaGIvafsoZ01W9Whabi0JP+v1pgvFLPvg5pU7Z7PSF8hf/k3hBD8qyG +Mf5lsJJiY2NlV9m4tH9SYzo2ck8Pj/eFXjlLtB4zbWFphnrhT4yzE0s8lptFSUhM +XU/0G4b7B3QUaSDeLeSI+EvpAoGBANXlak7IdMGI4AlDtCPjxCKmTxlEX/RBNEa0 ++SuyAgoVzGsjt4CY+GlURZtmH09aw09/YEBpfV5sRhcCF4kDCQx3XrAdoMqaTDxY +t2RmpQpUBI3NEMxf4j2yXDqz5Gx/9M+ifQyLKD31Ep0WwjNS0zKYW5RVe5BRiCVm +8pXJbp5dAoGBAJiN8lryCqG+0VZ+SKU8UI9paR6G64IFO3A2SjBJf7YrQ8fivhOk +gEdB/Aph2ztx0AZP56b38y7EievsKW95kg1LhGi0bhlKygVuZRWJa4Kj9DaTlAss +2ufqrz1VGK7o0elCrNnNp0F/ocWMAvVFBPOA90WMKd2z97HpcgvzXGj6 +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-entity.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-entity.pem new file mode 100644 index 000000000..34f198f2e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainC-entity.pem @@ -0,0 +1,86 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainC-ICA1-pathlen1, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:08 2019 GMT + Not After : Jul 7 00:28:08 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainC-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bf:34:e1:1c:2c:2d:a4:93:b5:c4:fc:65:40:fa: + 94:68:74:24:ff:52:a4:df:3e:f1:7c:92:14:f0:f0: + 91:ed:9c:7e:a0:7e:b1:07:20:38:b2:c4:a2:b8:09: + d1:06:ee:fa:c6:7e:4d:79:be:dd:83:18:cf:e8:a7: + 78:88:cd:44:ce:3a:40:05:7a:6e:c5:c9:e4:84:64: + e0:01:7d:4f:f9:87:d2:94:91:e9:c8:21:bc:71:2e: + ef:f6:61:23:46:6b:da:5f:32:23:a1:86:9c:c6:9a: + b4:98:35:6d:36:b8:34:14:fd:9d:63:2f:75:7e:58: + f2:08:f9:e3:32:2a:a6:d2:b1:49:05:d3:8c:d4:48: + 5c:c2:57:07:62:4e:7a:05:23:c2:4f:ca:d5:a8:38: + 32:92:c2:21:3b:74:3e:2d:b1:6b:57:96:81:a3:2d: + ce:6e:9c:d9:ce:1f:e9:42:f8:2c:bb:fe:07:57:c6: + c8:93:6e:89:d3:fc:d2:83:4b:c1:2c:ea:5e:41:c9: + 7c:be:6c:23:01:89:75:1b:1f:57:ac:83:dc:da:e1: + 63:55:d8:94:fc:2d:a6:99:15:d1:71:88:a5:1b:f5: + 6f:39:0a:bd:ec:09:02:09:77:a7:5d:da:78:f8:8f: + b1:5d:a7:83:12:10:5f:89:ae:72:c2:88:bf:3e:80: + 98:c3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 91:79:7C:91:A7:A0:BC:E1:7B:77:9E:51:6E:5C:A7:7A:D9:3F:18:A0 + X509v3 Authority Key Identifier: + keyid:94:1D:2E:07:37:C6:2F:52:C1:EC:79:6B:13:CE:09:90:5F:F4:C4:51 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + b7:d0:5e:86:77:76:45:77:c3:f8:5c:cd:9b:84:52:b7:8b:d6: + 84:ed:d3:1b:fa:7f:27:d1:24:05:11:9d:bf:74:eb:14:93:ee: + 08:2c:16:0a:d8:00:46:31:e3:43:f1:95:64:b1:72:93:49:fa: + fe:73:e8:be:2a:02:95:e8:3a:56:f3:aa:8b:fa:cb:3a:f5:06: + a2:00:ae:19:36:86:be:93:79:3f:58:f7:95:de:a8:e2:12:89: + 52:2f:a0:be:09:3e:18:69:19:d5:96:7c:94:9a:ee:ab:f1:2b: + 74:54:c9:1c:0a:5f:aa:d1:62:34:24:33:f8:5e:b2:43:9c:c9: + e6:8c:fa:b5:89:a7:3e:6b:51:00:a6:e3:d5:c4:f9:ac:78:a5: + 4d:85:7c:e3:7d:f9:b5:e8:ad:3e:32:56:fb:99:bf:f9:3b:a4: + 98:04:72:cd:ea:95:08:af:7e:62:2d:74:e4:25:48:43:25:ba: + 07:7c:00:c9:31:41:6f:59:ff:da:bb:ac:08:06:18:1a:0a:3d: + 1d:2e:ad:98:2c:06:72:51:f2:75:7c:87:ef:e0:37:f6:80:70: + aa:8d:d9:a8:13:e5:31:91:3c:e3:0f:21:33:0a:15:91:1c:4d: + 3a:1b:35:f6:4c:f5:5f:70:34:b2:dc:ed:10:5d:37:58:16:e4: + e0:83:12:90 +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluQy1JQ0ExLXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOFoXDTIyMDcwNzAwMjgwOFowgZoxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRYwFAYDVQQD +DA1jaGFpbkMtZW50aXR5MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvzThHCwtpJO1xPxlQPqU +aHQk/1Kk3z7xfJIU8PCR7Zx+oH6xByA4ssSiuAnRBu76xn5Neb7dgxjP6Kd4iM1E +zjpABXpuxcnkhGTgAX1P+YfSlJHpyCG8cS7v9mEjRmvaXzIjoYacxpq0mDVtNrg0 +FP2dYy91fljyCPnjMiqm0rFJBdOM1EhcwlcHYk56BSPCT8rVqDgyksIhO3Q+LbFr +V5aBoy3ObpzZzh/pQvgsu/4HV8bIk26J0/zSg0vBLOpeQcl8vmwjAYl1Gx9XrIPc +2uFjVdiU/C2mmRXRcYilG/VvOQq97AkCCXenXdp4+I+xXaeDEhBfia5ywoi/PoCY +wwIDAQABo4HxMIHuMB0GA1UdDgQWBBSReXyRp6C84Xt3nlFuXKd62T8YoDCBwQYD +VR0jBIG5MIG2gBSUHS4HN8YvUsHseWsTzgmQX/TEUaGBmqSBlzCBlDELMAkGA1UE +BhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNV +BAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cu +d29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CAWQw +CQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAt9Behnd2RXfD+FzNm4RSt4vW +hO3TG/p/J9EkBRGdv3TrFJPuCCwWCtgARjHjQ/GVZLFyk0n6/nPovioCleg6VvOq +i/rLOvUGogCuGTaGvpN5P1j3ld6o4hKJUi+gvgk+GGkZ1ZZ8lJruq/ErdFTJHApf +qtFiNCQz+F6yQ5zJ5oz6tYmnPmtRAKbj1cT5rHilTYV84335teitPjJW+5m/+Tuk +mARyzeqVCK9+Yi105CVIQyW6B3wAyTFBb1n/2rusCAYYGgo9HS6tmCwGclHydXyH +7+A39oBwqo3ZqBPlMZE84w8hMwoVkRxNOhs19kz1X3A0stztEF03WBbk4IMSkA== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-ICA1-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-ICA1-key.pem new file mode 100644 index 000000000..5898278a3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-ICA1-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA14F4qRmZEtHPPVFUHdMUlO0+3v/gI+T3I/xcSSTYNpPmKu6n +q8aNya1ARclEBkdMDWUJ3dvi8L3NeRzs0Y3e8v9m9bK9Q8xYfx3bS5elg1yHXptz +h8gdK0eSVeTbvlHV63bCqllye/YnL77A29w88uIZybAwuy6ilUgGvY6dvYxrXsaa +c0tssCCWR0TTCWtqK/qGXx0Lp2IictVWHKqXjM5Xow/mvM1jVFVgh1Dr+ozpFXCz +XE0OJ2D9B26M7D+gJcUBWaP8LYBLhEwQtcina7HlxcGasNZLMCG6QmXgP1nPf0lL +O89iBvSJrluBXRVj+3wpprXP87W1ZgZPo9pnOQIDAQABAoIBAFEIoxlawb9c20Ng +SHPqggu55fEuX9a/atrCMuViEFb9aAfus2eZAom6NrfHBWgi+Qr0WjBtVTlW9WM8 +KCRn51SSCuIKcraCqSgrTuFuxVLOwSwm4dtFuQokIHdh1esLlJe0kWBCwBSyq2t9 +m8FQYC6oLDA1qy1HTOU7LyWp8dBqwnbplTSUax9ske3hQ51uLVI3ESWIHwoC2t9D +fCAPQII7CIIOAO9hmi5324Z06Pi8LkuRY/ayiZ+CxMn2gSG3HuE2yg8fbbbVwN5u +w6Luwc0qPh8CmBDWXFftLjgY7u+PJOlYDz8GKYSaykVAvyjl9YeAMXKVo+dgER/H +4nBrWvECgYEA/Q+k2BIwr5gyE8dWoY7nVUQY/UlOX3WIQG13GCJBiUh23rZui3YQ ++tCTi1CRdoLkbyN2gPorMBxEjaQ+tKGhd/fSXeeftWMAIrQuKdxlYwBIG3xNCG69 +heL9Bcv9HKYtTWjEw9cR8OaXj9G3ExCqrdeJ2oA3Ow9xNTexSidT7o0CgYEA2gIs +rRzYtqIxgCML1iMUU5BwMeO7kqtQD9pl8jsoMgTFD83C3pS8iZcm3A53vmBi+l5a +ELljofTq4Sx9PLFLKITRjyMXZI0HJg7gaZRKcR8W8K38gIVTYT+KIp4fTsa51jKD +u7VWxKwCsTSRr50cvhUtW2kydgxrOShOiWz3Nl0CgYEAkdrLaxII55wz+LxizRk9 +ciKeuJXgyxpF3sR46PsNhN+0S6cgTddN8BH5iEl2nbTRjtEEw0/tRnx0cqLg1WF3 +XFsE78TJg1U9RcNN/CigcxA9f0IEcEDLkXiD1yx8hV+uKrig+DNkjtGJN4ZrG1z2 +0t2xAbP2oV7EJCUmVRQXxx0CgYEAw2erj8cJYDnk0IuZMmji8TvHtJABMqem7W6+ +be4kSyEHWPD/N+5tR45Z4Gh/X/6Y+PzVEaR571LNrOLpphrr2Pejtf6oGxJlU/GF +qFyolNhfAX+RkcjvQX1oXTsJqNxq+djxRrB1g3cCOr95zcSvXJkyvHqAJltfSC4e +pwMqWmkCgYBsEbkdUr9thcGrDeb+g4ZefnhkVwt9c80zwPFpfFsdp7en2c4isjZw +UyCA0qQPXBG+ChbtL3mRd/sAt10vFzBfTwjhU55rDBNjLUljEBkGpOQM1Hgi6IdY +A/J9/DoRY6Tg66bgQxu7iqwkCWTEnSjyRyeTDrem7zED/B/CNpbTtA== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-ICA1-pathlen127.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-ICA1-pathlen127.pem new file mode 100644 index 000000000..97ad8d4f5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-ICA1-pathlen127.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainD-ICA1-pathlen127, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d7:81:78:a9:19:99:12:d1:cf:3d:51:54:1d:d3: + 14:94:ed:3e:de:ff:e0:23:e4:f7:23:fc:5c:49:24: + d8:36:93:e6:2a:ee:a7:ab:c6:8d:c9:ad:40:45:c9: + 44:06:47:4c:0d:65:09:dd:db:e2:f0:bd:cd:79:1c: + ec:d1:8d:de:f2:ff:66:f5:b2:bd:43:cc:58:7f:1d: + db:4b:97:a5:83:5c:87:5e:9b:73:87:c8:1d:2b:47: + 92:55:e4:db:be:51:d5:eb:76:c2:aa:59:72:7b:f6: + 27:2f:be:c0:db:dc:3c:f2:e2:19:c9:b0:30:bb:2e: + a2:95:48:06:bd:8e:9d:bd:8c:6b:5e:c6:9a:73:4b: + 6c:b0:20:96:47:44:d3:09:6b:6a:2b:fa:86:5f:1d: + 0b:a7:62:22:72:d5:56:1c:aa:97:8c:ce:57:a3:0f: + e6:bc:cd:63:54:55:60:87:50:eb:fa:8c:e9:15:70: + b3:5c:4d:0e:27:60:fd:07:6e:8c:ec:3f:a0:25:c5: + 01:59:a3:fc:2d:80:4b:84:4c:10:b5:c8:a7:6b:b1: + e5:c5:c1:9a:b0:d6:4b:30:21:ba:42:65:e0:3f:59: + cf:7f:49:4b:3b:cf:62:06:f4:89:ae:5b:81:5d:15: + 63:fb:7c:29:a6:b5:cf:f3:b5:b5:66:06:4f:a3:da: + 67:39 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 67:78:F9:AD:1C:53:41:1F:46:BD:49:9B:73:2E:7C:DC:5C:2D:0B:FB + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:127 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 12:87:4f:82:bb:5a:21:b0:95:f6:b5:2b:95:53:a5:10:fc:f6: + fe:7e:03:9c:fa:cf:d7:d5:a1:72:1d:33:69:1b:0e:07:07:62: + 74:9b:0c:2b:46:d2:b8:80:b1:72:f3:c1:83:13:62:fd:dd:17: + 15:14:0b:64:57:26:db:70:e5:3d:44:88:05:f9:91:b0:9a:4a: + c0:f9:87:3c:70:16:d6:1c:58:51:d9:b9:b8:ac:11:d2:4d:94: + 58:cf:fd:9e:74:51:28:b0:4f:ed:7d:88:25:ce:6b:eb:5e:ca: + e8:f9:ce:31:e1:b9:2d:e6:d9:0c:13:ff:3f:24:1f:fa:25:e8: + cd:cd:25:88:e7:98:dc:b5:f8:cd:21:d2:a8:71:d1:b9:18:dd: + 18:5d:0b:97:a7:82:04:d5:e8:36:29:4b:dc:7f:d9:42:85:55: + 81:dc:da:f9:ca:58:38:f3:2c:df:b4:2c:23:65:d3:17:01:ed: + f4:8b:f6:9b:0b:b5:32:ea:28:cb:c2:fb:16:2a:fe:3d:3d:0b: + e6:f3:bf:8f:43:75:a7:d1:b8:c9:04:31:4f:60:3a:3a:4a:b0: + 1b:16:7d:24:b8:78:be:be:7a:80:a5:81:8c:77:7c:aa:79:75: + 4d:3f:a2:14:36:5a:81:1f:6c:44:7d:d1:9a:db:a6:f6:e3:48: + d3:bb:ea:9c +-----BEGIN CERTIFICATE----- +MIIEwzCCA6ugAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA5WhcNMjIwNzA3MDAyODA5WjCBozELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNoYWluRC1JQ0Ex +LXBhdGhsZW4xMjcxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXgXipGZkS0c89UVQd0xSU7T7e +/+Aj5Pcj/FxJJNg2k+Yq7qerxo3JrUBFyUQGR0wNZQnd2+Lwvc15HOzRjd7y/2b1 +sr1DzFh/HdtLl6WDXIdem3OHyB0rR5JV5Nu+UdXrdsKqWXJ79icvvsDb3Dzy4hnJ +sDC7LqKVSAa9jp29jGtexppzS2ywIJZHRNMJa2or+oZfHQunYiJy1VYcqpeMzlej +D+a8zWNUVWCHUOv6jOkVcLNcTQ4nYP0HbozsP6AlxQFZo/wtgEuETBC1yKdrseXF +wZqw1kswIbpCZeA/Wc9/SUs7z2IG9ImuW4FdFWP7fCmmtc/ztbVmBk+j2mc5AgMB +AAGjggENMIIBCTAdBgNVHQ4EFgQUZ3j5rRxTQR9GvUmbcy583FwtC/swgckGA1Ud +IwSBwTCBvoAUJ45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYT +AlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQK +DAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1 +jhDeuPswDwYDVR0TBAgwBgEB/wIBfzALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEL +BQADggEBABKHT4K7WiGwlfa1K5VTpRD89v5+A5z6z9fVoXIdM2kbDgcHYnSbDCtG +0riAsXLzwYMTYv3dFxUUC2RXJttw5T1EiAX5kbCaSsD5hzxwFtYcWFHZubisEdJN +lFjP/Z50USiwT+19iCXOa+teyuj5zjHhuS3m2QwT/z8kH/ol6M3NJYjnmNy1+M0h +0qhx0bkY3RhdC5enggTV6DYpS9x/2UKFVYHc2vnKWDjzLN+0LCNl0xcB7fSL9psL +tTLqKMvC+xYq/j09C+bzv49DdafRuMkEMU9gOjpKsBsWfSS4eL6+eoClgYx3fKp5 +dU0/ohQ2WoEfbER90ZrbpvbjSNO76pw= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-assembled.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-assembled.pem new file mode 100644 index 000000000..28cc30acd --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-assembled.pem @@ -0,0 +1,175 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainD-ICA1-pathlen127, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainD-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:e2:5d:f4:bd:06:b6:a1:21:3a:2d:7f:cc:f2:5a: + 15:36:28:0a:f2:bb:16:b5:ec:f9:e7:5b:92:ec:17: + 75:76:89:f4:1b:7c:a9:79:cb:62:4b:55:8a:ca:cc: + f9:f0:a9:a2:05:61:ee:d8:8b:d0:5d:c5:49:bc:7d: + 28:26:7d:3a:22:cc:20:71:55:4c:3a:f7:24:d7:95: + ac:ce:18:7d:0d:7b:20:4f:11:a9:7b:02:08:09:e6: + 85:91:e4:4e:80:b9:a4:76:0f:28:cc:07:f6:f2:be: + c1:54:63:d2:b7:81:59:09:0b:c1:bd:0d:27:70:55: + c7:5f:bc:54:ee:73:16:7e:d2:b4:4c:df:a8:a9:81: + cc:e3:a6:8c:eb:e3:98:49:84:0b:a0:da:f3:e1:5f: + 32:69:6a:b0:50:69:4f:96:72:04:3f:e7:1c:80:b1: + 2c:6f:7d:ff:41:f2:bb:0b:17:b7:b5:ce:21:ea:e6: + c2:bd:cd:28:08:40:43:04:e5:40:e2:7d:41:35:b5: + 51:bf:e8:20:01:99:85:a2:38:f1:6e:69:40:da:6e: + 9f:d3:40:63:89:19:de:4d:49:d2:79:10:b6:2a:bb: + 6f:66:fa:25:5f:96:c1:e8:38:96:e3:e5:28:28:b4: + ca:3c:21:1c:95:cd:b5:5e:50:f1:c9:3e:c2:4c:f2: + cb:33 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 58:92:0B:B2:E4:12:D8:A3:31:37:D9:89:F2:9E:6E:62:22:40:42:82 + X509v3 Authority Key Identifier: + keyid:67:78:F9:AD:1C:53:41:1F:46:BD:49:9B:73:2E:7C:DC:5C:2D:0B:FB + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 58:fd:0d:2f:47:32:d2:11:b4:b5:a5:b5:ea:26:23:66:85:cc: + 46:b5:42:fc:63:98:57:14:84:ca:2a:02:30:9e:a0:64:d4:24: + cb:42:2e:53:a3:0f:d7:24:46:cb:37:0c:ba:d9:73:50:11:15: + d0:4a:4a:f5:10:15:db:c9:e5:e6:a2:c3:91:89:70:c8:df:59: + c3:2f:c3:94:a4:50:5b:f5:d8:71:e8:ba:fa:85:ee:aa:f4:b1: + 64:29:54:62:08:cc:89:a3:41:be:df:03:d3:75:f8:92:41:95: + 4b:06:cc:95:30:ef:a8:6f:01:9a:2e:bc:a0:7e:4c:08:4e:d4: + f0:91:fe:b4:a3:67:0f:9c:5d:4d:7d:ad:04:d7:cf:e4:79:d8: + b2:18:78:33:fd:a3:cb:14:d3:50:1b:50:62:ef:9d:1b:88:8d: + 7b:42:76:ce:c7:88:70:58:40:f4:bf:7c:1e:c5:26:8c:23:b7: + 7e:d2:85:67:c7:fe:ae:59:98:06:60:54:43:1e:31:74:25:c9: + 1e:4c:05:d2:6d:01:3e:33:ac:5d:42:c5:47:c4:20:9f:04:30: + ca:c7:22:63:bd:8e:16:0a:42:4c:5b:2c:3b:b4:77:3c:b4:43: + bb:6d:4d:40:d6:ed:30:df:29:a4:3e:e2:78:c3:4f:11:a4:53: + 65:33:e0:c9 +-----BEGIN CERTIFICATE----- +MIIErDCCA5SgAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluRC1JQ0ExLXBhdGhsZW4xMjcxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMDAyODA5WhcNMjIwNzA3MDAyODA5WjCBmjELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxFjAUBgNV +BAMMDWNoYWluRC1lbnRpdHkxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDiXfS9BrahITotf8zy +WhU2KAryuxa17PnnW5LsF3V2ifQbfKl5y2JLVYrKzPnwqaIFYe7Yi9BdxUm8fSgm +fToizCBxVUw69yTXlazOGH0NeyBPEal7AggJ5oWR5E6AuaR2DyjMB/byvsFUY9K3 +gVkJC8G9DSdwVcdfvFTucxZ+0rRM36ipgczjpozr45hJhAug2vPhXzJparBQaU+W +cgQ/5xyAsSxvff9B8rsLF7e1ziHq5sK9zSgIQEME5UDifUE1tVG/6CABmYWiOPFu +aUDabp/TQGOJGd5NSdJ5ELYqu29m+iVflsHoOJbj5SgotMo8IRyVzbVeUPHJPsJM +8sszAgMBAAGjgfEwge4wHQYDVR0OBBYEFFiSC7LkEtijMTfZifKebmIiQEKCMIHB +BgNVHSMEgbkwgbaAFGd4+a0cU0EfRr1Jm3MufNxcLQv7oYGapIGXMIGUMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G +A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIB +ZDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQBY/Q0vRzLSEbS1pbXqJiNm +hcxGtUL8Y5hXFITKKgIwnqBk1CTLQi5Tow/XJEbLNwy62XNQERXQSkr1EBXbyeXm +osORiXDI31nDL8OUpFBb9dhx6Lr6he6q9LFkKVRiCMyJo0G+3wPTdfiSQZVLBsyV +MO+obwGaLrygfkwITtTwkf60o2cPnF1Nfa0E18/kediyGHgz/aPLFNNQG1Bi750b +iI17QnbOx4hwWED0v3wexSaMI7d+0oVnx/6uWZgGYFRDHjF0JckeTAXSbQE+M6xd +QsVHxCCfBDDKxyJjvY4WCkJMWyw7tHc8tEO7bU1A1u0w3ymkPuJ4w08RpFNlM+DJ +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainD-ICA1-pathlen127, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d7:81:78:a9:19:99:12:d1:cf:3d:51:54:1d:d3: + 14:94:ed:3e:de:ff:e0:23:e4:f7:23:fc:5c:49:24: + d8:36:93:e6:2a:ee:a7:ab:c6:8d:c9:ad:40:45:c9: + 44:06:47:4c:0d:65:09:dd:db:e2:f0:bd:cd:79:1c: + ec:d1:8d:de:f2:ff:66:f5:b2:bd:43:cc:58:7f:1d: + db:4b:97:a5:83:5c:87:5e:9b:73:87:c8:1d:2b:47: + 92:55:e4:db:be:51:d5:eb:76:c2:aa:59:72:7b:f6: + 27:2f:be:c0:db:dc:3c:f2:e2:19:c9:b0:30:bb:2e: + a2:95:48:06:bd:8e:9d:bd:8c:6b:5e:c6:9a:73:4b: + 6c:b0:20:96:47:44:d3:09:6b:6a:2b:fa:86:5f:1d: + 0b:a7:62:22:72:d5:56:1c:aa:97:8c:ce:57:a3:0f: + e6:bc:cd:63:54:55:60:87:50:eb:fa:8c:e9:15:70: + b3:5c:4d:0e:27:60:fd:07:6e:8c:ec:3f:a0:25:c5: + 01:59:a3:fc:2d:80:4b:84:4c:10:b5:c8:a7:6b:b1: + e5:c5:c1:9a:b0:d6:4b:30:21:ba:42:65:e0:3f:59: + cf:7f:49:4b:3b:cf:62:06:f4:89:ae:5b:81:5d:15: + 63:fb:7c:29:a6:b5:cf:f3:b5:b5:66:06:4f:a3:da: + 67:39 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 67:78:F9:AD:1C:53:41:1F:46:BD:49:9B:73:2E:7C:DC:5C:2D:0B:FB + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:127 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 12:87:4f:82:bb:5a:21:b0:95:f6:b5:2b:95:53:a5:10:fc:f6: + fe:7e:03:9c:fa:cf:d7:d5:a1:72:1d:33:69:1b:0e:07:07:62: + 74:9b:0c:2b:46:d2:b8:80:b1:72:f3:c1:83:13:62:fd:dd:17: + 15:14:0b:64:57:26:db:70:e5:3d:44:88:05:f9:91:b0:9a:4a: + c0:f9:87:3c:70:16:d6:1c:58:51:d9:b9:b8:ac:11:d2:4d:94: + 58:cf:fd:9e:74:51:28:b0:4f:ed:7d:88:25:ce:6b:eb:5e:ca: + e8:f9:ce:31:e1:b9:2d:e6:d9:0c:13:ff:3f:24:1f:fa:25:e8: + cd:cd:25:88:e7:98:dc:b5:f8:cd:21:d2:a8:71:d1:b9:18:dd: + 18:5d:0b:97:a7:82:04:d5:e8:36:29:4b:dc:7f:d9:42:85:55: + 81:dc:da:f9:ca:58:38:f3:2c:df:b4:2c:23:65:d3:17:01:ed: + f4:8b:f6:9b:0b:b5:32:ea:28:cb:c2:fb:16:2a:fe:3d:3d:0b: + e6:f3:bf:8f:43:75:a7:d1:b8:c9:04:31:4f:60:3a:3a:4a:b0: + 1b:16:7d:24:b8:78:be:be:7a:80:a5:81:8c:77:7c:aa:79:75: + 4d:3f:a2:14:36:5a:81:1f:6c:44:7d:d1:9a:db:a6:f6:e3:48: + d3:bb:ea:9c +-----BEGIN CERTIFICATE----- +MIIEwzCCA6ugAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA5WhcNMjIwNzA3MDAyODA5WjCBozELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNoYWluRC1JQ0Ex +LXBhdGhsZW4xMjcxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXgXipGZkS0c89UVQd0xSU7T7e +/+Aj5Pcj/FxJJNg2k+Yq7qerxo3JrUBFyUQGR0wNZQnd2+Lwvc15HOzRjd7y/2b1 +sr1DzFh/HdtLl6WDXIdem3OHyB0rR5JV5Nu+UdXrdsKqWXJ79icvvsDb3Dzy4hnJ +sDC7LqKVSAa9jp29jGtexppzS2ywIJZHRNMJa2or+oZfHQunYiJy1VYcqpeMzlej +D+a8zWNUVWCHUOv6jOkVcLNcTQ4nYP0HbozsP6AlxQFZo/wtgEuETBC1yKdrseXF +wZqw1kswIbpCZeA/Wc9/SUs7z2IG9ImuW4FdFWP7fCmmtc/ztbVmBk+j2mc5AgMB +AAGjggENMIIBCTAdBgNVHQ4EFgQUZ3j5rRxTQR9GvUmbcy583FwtC/swgckGA1Ud +IwSBwTCBvoAUJ45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYT +AlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQK +DAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1 +jhDeuPswDwYDVR0TBAgwBgEB/wIBfzALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEL +BQADggEBABKHT4K7WiGwlfa1K5VTpRD89v5+A5z6z9fVoXIdM2kbDgcHYnSbDCtG +0riAsXLzwYMTYv3dFxUUC2RXJttw5T1EiAX5kbCaSsD5hzxwFtYcWFHZubisEdJN +lFjP/Z50USiwT+19iCXOa+teyuj5zjHhuS3m2QwT/z8kH/ol6M3NJYjnmNy1+M0h +0qhx0bkY3RhdC5enggTV6DYpS9x/2UKFVYHc2vnKWDjzLN+0LCNl0xcB7fSL9psL +tTLqKMvC+xYq/j09C+bzv49DdafRuMkEMU9gOjpKsBsWfSS4eL6+eoClgYx3fKp5 +dU0/ohQ2WoEfbER90ZrbpvbjSNO76pw= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-entity-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-entity-key.pem new file mode 100644 index 000000000..28c6fd2a8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-entity-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA4l30vQa2oSE6LX/M8loVNigK8rsWtez551uS7Bd1don0G3yp +ectiS1WKysz58KmiBWHu2IvQXcVJvH0oJn06IswgcVVMOvck15Wszhh9DXsgTxGp +ewIICeaFkeROgLmkdg8ozAf28r7BVGPSt4FZCQvBvQ0ncFXHX7xU7nMWftK0TN+o +qYHM46aM6+OYSYQLoNrz4V8yaWqwUGlPlnIEP+ccgLEsb33/QfK7Cxe3tc4h6ubC +vc0oCEBDBOVA4n1BNbVRv+ggAZmFojjxbmlA2m6f00BjiRneTUnSeRC2KrtvZvol +X5bB6DiW4+UoKLTKPCEclc21XlDxyT7CTPLLMwIDAQABAoIBAA0VeSvj03KExSQU +Gvh3FHrI3bkh7zIcvGUO+fMDeBqd5qogDnunscrA6wDF0DyE0YSWIIQLsMN6v8RR +R5zR6CZSvh1O3NUbq9l6IT7YU4IP99IaJz2g5G4OEPJZy9/M2yCnx6fjXfax5+LE +0k0hANBxCYWv2PO5QYjbDd2qcUZrM4Sepm7jX7ZhQGQI4q5fumfGqLZprvvxaOWF +lpLyxUO2C/FD/eNFglpe6XWhYRDTgsT5dfglzYMnbzVlXDyfS1p3tNPIGxcNJUis +qbzP4h67PyZXZParZwPIFzFN0L9LQG2RXWqI7NZaOjkEoMJydx/KSFCpTFl5MM4s +pLOEuuECgYEA8T76XF7sx5u8u3nVauc2ViB4QBde334Clh7HG+XVvde1rWM/ctcC +Ku9shZpW7xBqsg6F2YUFB6CNRX67jEJNKXtGtI9oj8svXVMzToXXcqrLlm7fEyOt +bOS9eIxBHXIk3igZa5B73qEgnY4NnMxPw9I44GcMQeNdryoQeYgVPs0CgYEA8DYH +JycMDyocuQd1zKgnz3yHbw2xBgli6MvSlYMaxhqn3F+ty3yuRVPKV7xAvJpEGzcx +Z6BVIBHxAYXaqN4f3+v3LU77cxL8YcPxMuSs6QrHrJAAUEG3NbigJ4zGzrYnwH9d +albr5K2cZT82TyPy1zlsawVJW4EQTTUdVGHUMf8CgYAjd5HRMLd45SGLIm9I5zMq +2F01dvogu2Lf9ShqppCU93ijRBsY5BlSfJ6kybsMLIqzIMV25EKIC4eZdvdVuI2l +kpUjiI3jzghpnQjG+5BgMFH8DNLI+o7NmpdseJo+HQDklFqgYL6FTYUBBNhle/gi +Hu7zttKrgSTN0s5XP7V35QKBgQCA3gtSVuFiVU5ZeYYaCHBrILyruGWq/mggyhAs +g8xeUTiSwoXDcB0yNjSMgwMb64r0KtUHaf2hGd742S2ogJoLEFVn6kJ9xsa9UFha +3FFjKJRcoFh6tfarDGRnM2AIz7Jd1DZycTVWVklcC+B/7qI+EqF2fLyRKZlsQj18 +4orrUwKBgCe+cDVeBCwxCfRehb6niIQE3lkGxIHRFzBM4eSURUKoVIHof8nuESf2 +HDe5PYLU4Zq0RIeuIqIVIp0kh554j6GQZsJt3mWd7MxjF8Y4N4MtPsoOBrZygdrm +9lXqawKwYMawlGb6n/D+KjjneKDtOVUKMuJk5FiMjWwi+BSeheHG +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-entity.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-entity.pem new file mode 100644 index 000000000..640b8394e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainD-entity.pem @@ -0,0 +1,86 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainD-ICA1-pathlen127, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainD-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:e2:5d:f4:bd:06:b6:a1:21:3a:2d:7f:cc:f2:5a: + 15:36:28:0a:f2:bb:16:b5:ec:f9:e7:5b:92:ec:17: + 75:76:89:f4:1b:7c:a9:79:cb:62:4b:55:8a:ca:cc: + f9:f0:a9:a2:05:61:ee:d8:8b:d0:5d:c5:49:bc:7d: + 28:26:7d:3a:22:cc:20:71:55:4c:3a:f7:24:d7:95: + ac:ce:18:7d:0d:7b:20:4f:11:a9:7b:02:08:09:e6: + 85:91:e4:4e:80:b9:a4:76:0f:28:cc:07:f6:f2:be: + c1:54:63:d2:b7:81:59:09:0b:c1:bd:0d:27:70:55: + c7:5f:bc:54:ee:73:16:7e:d2:b4:4c:df:a8:a9:81: + cc:e3:a6:8c:eb:e3:98:49:84:0b:a0:da:f3:e1:5f: + 32:69:6a:b0:50:69:4f:96:72:04:3f:e7:1c:80:b1: + 2c:6f:7d:ff:41:f2:bb:0b:17:b7:b5:ce:21:ea:e6: + c2:bd:cd:28:08:40:43:04:e5:40:e2:7d:41:35:b5: + 51:bf:e8:20:01:99:85:a2:38:f1:6e:69:40:da:6e: + 9f:d3:40:63:89:19:de:4d:49:d2:79:10:b6:2a:bb: + 6f:66:fa:25:5f:96:c1:e8:38:96:e3:e5:28:28:b4: + ca:3c:21:1c:95:cd:b5:5e:50:f1:c9:3e:c2:4c:f2: + cb:33 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 58:92:0B:B2:E4:12:D8:A3:31:37:D9:89:F2:9E:6E:62:22:40:42:82 + X509v3 Authority Key Identifier: + keyid:67:78:F9:AD:1C:53:41:1F:46:BD:49:9B:73:2E:7C:DC:5C:2D:0B:FB + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 58:fd:0d:2f:47:32:d2:11:b4:b5:a5:b5:ea:26:23:66:85:cc: + 46:b5:42:fc:63:98:57:14:84:ca:2a:02:30:9e:a0:64:d4:24: + cb:42:2e:53:a3:0f:d7:24:46:cb:37:0c:ba:d9:73:50:11:15: + d0:4a:4a:f5:10:15:db:c9:e5:e6:a2:c3:91:89:70:c8:df:59: + c3:2f:c3:94:a4:50:5b:f5:d8:71:e8:ba:fa:85:ee:aa:f4:b1: + 64:29:54:62:08:cc:89:a3:41:be:df:03:d3:75:f8:92:41:95: + 4b:06:cc:95:30:ef:a8:6f:01:9a:2e:bc:a0:7e:4c:08:4e:d4: + f0:91:fe:b4:a3:67:0f:9c:5d:4d:7d:ad:04:d7:cf:e4:79:d8: + b2:18:78:33:fd:a3:cb:14:d3:50:1b:50:62:ef:9d:1b:88:8d: + 7b:42:76:ce:c7:88:70:58:40:f4:bf:7c:1e:c5:26:8c:23:b7: + 7e:d2:85:67:c7:fe:ae:59:98:06:60:54:43:1e:31:74:25:c9: + 1e:4c:05:d2:6d:01:3e:33:ac:5d:42:c5:47:c4:20:9f:04:30: + ca:c7:22:63:bd:8e:16:0a:42:4c:5b:2c:3b:b4:77:3c:b4:43: + bb:6d:4d:40:d6:ed:30:df:29:a4:3e:e2:78:c3:4f:11:a4:53: + 65:33:e0:c9 +-----BEGIN CERTIFICATE----- +MIIErDCCA5SgAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluRC1JQ0ExLXBhdGhsZW4xMjcxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMDAyODA5WhcNMjIwNzA3MDAyODA5WjCBmjELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxFjAUBgNV +BAMMDWNoYWluRC1lbnRpdHkxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDiXfS9BrahITotf8zy +WhU2KAryuxa17PnnW5LsF3V2ifQbfKl5y2JLVYrKzPnwqaIFYe7Yi9BdxUm8fSgm +fToizCBxVUw69yTXlazOGH0NeyBPEal7AggJ5oWR5E6AuaR2DyjMB/byvsFUY9K3 +gVkJC8G9DSdwVcdfvFTucxZ+0rRM36ipgczjpozr45hJhAug2vPhXzJparBQaU+W +cgQ/5xyAsSxvff9B8rsLF7e1ziHq5sK9zSgIQEME5UDifUE1tVG/6CABmYWiOPFu +aUDabp/TQGOJGd5NSdJ5ELYqu29m+iVflsHoOJbj5SgotMo8IRyVzbVeUPHJPsJM +8sszAgMBAAGjgfEwge4wHQYDVR0OBBYEFFiSC7LkEtijMTfZifKebmIiQEKCMIHB +BgNVHSMEgbkwgbaAFGd4+a0cU0EfRr1Jm3MufNxcLQv7oYGapIGXMIGUMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G +A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIB +ZDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQBY/Q0vRzLSEbS1pbXqJiNm +hcxGtUL8Y5hXFITKKgIwnqBk1CTLQi5Tow/XJEbLNwy62XNQERXQSkr1EBXbyeXm +osORiXDI31nDL8OUpFBb9dhx6Lr6he6q9LFkKVRiCMyJo0G+3wPTdfiSQZVLBsyV +MO+obwGaLrygfkwITtTwkf60o2cPnF1Nfa0E18/kediyGHgz/aPLFNNQG1Bi750b +iI17QnbOx4hwWED0v3wexSaMI7d+0oVnx/6uWZgGYFRDHjF0JckeTAXSbQE+M6xd +QsVHxCCfBDDKxyJjvY4WCkJMWyw7tHc8tEO7bU1A1u0w3ymkPuJ4w08RpFNlM+DJ +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-ICA1-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-ICA1-key.pem new file mode 100644 index 000000000..c7d2f61f8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-ICA1-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA1vNvuNsQ34nfO9kuesE0GlaXbHME/BVQBJNmyxe6+/koudbO +fvV4u7FPqkv4gDXZrv6ZdffNeQvPytrLWJpum5Eh9Bf9Vrg6z8/t95Bqc2wGme8O +j2Xc0Ojbe8HoTW1hnsxaIN6GOliB+rHUXzx0Q0VhNiz+pDWu4jnH/d2zg9YX3PWZ +P2cOwWDRaY08+WLpg65mEKpAkWMLKuXBqB+OipsRn7+mRfsWcO1sGxSYgGkEw70T +IufZM0idimwPnDkIKZKDe3Oj2obWSgAPp8J7v6wPKmKWWzvvn+EIu0S6xJlPoLle +Tctzc/7ugmlPr8dZWjaBRMbjUDu/jRTvfpbvwQIDAQABAoIBABqvTgdc6tNVgmkj +pSmIIrfCWDoWbV/+JVjsE67S21u8qtmnWStZvgtPD9zMYaVJCiU3ZkXG5bNJTBqa +3vO4+FJHyjdLYyAI7wQthBVf0FdT6d3iV6RluOwWfGj4waYbFitooyfBeFh19Gzy +9rJ8BtLzIgZfv50TLQrYsYNKqqaLC0NGAWaAnW/hj98Em1heFJapt+qalMrnR3iF +CpIgFAXK8dh2msQDLynoHTfG7ErZy4gtZcDC2hN07aU9ljVNqm8Z97MxrG5Xzj3W +ZfHRpNx0TbTk/wgpAj71jPvkxGoQmwTrOmMynrF8zl/0IktbJ815gZwNyv3hl9yN +HsjD3YECgYEA+L6eujveySdena54FnA5twGFdw4udkwOm2l1JLCIeaYjFlov+vM6 +v0JJmpXx6rWWfVByAssn735QTv5+JKhVbi3a3IGhUvVfkVrtgOPNYdz9eIYIh/2j +sSe2VKQFcXzatFHupKS00i5XwhozlNlbdd9na4gUDh3QOtqd/vreJeUCgYEA3Th6 +d+sNTuZPvWde1JHtIb7gvAavKP85LQ5TEIh/emck7NEAFjjje0UQ11Ak0Po0wEb2 +DB8X7QhSIu5AHzg8NyijDII2AluUn6CkL1tBKY1P35pzGsoVxucum2BxXnYnqn0p +5cLbqvW/V84T7bODMwDvVX/NCrKnP0fUeYRkxK0CgYEAzA91H8rl5ZeKo0jx81Z1 +wpBY8WaM7zdN9Gj7VPINw95rgnbSTckkNKsovsyr/aSipINORMRtKqgxMdzNlz0R +eKXdmnAt7GSn1hMGLGq1nscwmaM7dHS7ySWPCrjUTlnjAXMFl8QXIyYpkG72SfJW +ecigizLDYSFMJjwayYb8n5ECgYBgRB6PJpsw9WpHyr7qk+H0KGMVj3cTyRSxdaVR +8YQ/2Lip0T1PbkwXrXNprveGdQsVjQuvNKytukw75R/ENi2F90oUvGkSV5XybO5l +qTlPAq56aHSkeMJHPvz6IlrTN2mFeFgOIuCCodQ1OnlTnCWAwWxk8Wtht2KuV+yv +QJy1NQKBgQCWk7epAmek0e7fSE/otqqtW6XZHwj1pjTUHRxmw+5Xv73a2bdCBrh/ +GIcaxPaC2KwGTPqJikgxqRThnDlh3n1ArW8vmoDOYpanQzjrY/vEhIcFQPCyNHfX +i+yiFo5fa/EkqBQvmt/fKabXV6ICwDNdiR7/5vBB3qhknrI1w97YKQ== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-ICA1-pathlen128.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-ICA1-pathlen128.pem new file mode 100644 index 000000000..da10c86f7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-ICA1-pathlen128.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainE-ICA1-pathlen128, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d6:f3:6f:b8:db:10:df:89:df:3b:d9:2e:7a:c1: + 34:1a:56:97:6c:73:04:fc:15:50:04:93:66:cb:17: + ba:fb:f9:28:b9:d6:ce:7e:f5:78:bb:b1:4f:aa:4b: + f8:80:35:d9:ae:fe:99:75:f7:cd:79:0b:cf:ca:da: + cb:58:9a:6e:9b:91:21:f4:17:fd:56:b8:3a:cf:cf: + ed:f7:90:6a:73:6c:06:99:ef:0e:8f:65:dc:d0:e8: + db:7b:c1:e8:4d:6d:61:9e:cc:5a:20:de:86:3a:58: + 81:fa:b1:d4:5f:3c:74:43:45:61:36:2c:fe:a4:35: + ae:e2:39:c7:fd:dd:b3:83:d6:17:dc:f5:99:3f:67: + 0e:c1:60:d1:69:8d:3c:f9:62:e9:83:ae:66:10:aa: + 40:91:63:0b:2a:e5:c1:a8:1f:8e:8a:9b:11:9f:bf: + a6:45:fb:16:70:ed:6c:1b:14:98:80:69:04:c3:bd: + 13:22:e7:d9:33:48:9d:8a:6c:0f:9c:39:08:29:92: + 83:7b:73:a3:da:86:d6:4a:00:0f:a7:c2:7b:bf:ac: + 0f:2a:62:96:5b:3b:ef:9f:e1:08:bb:44:ba:c4:99: + 4f:a0:b9:5e:4d:cb:73:73:fe:ee:82:69:4f:af:c7: + 59:5a:36:81:44:c6:e3:50:3b:bf:8d:14:ef:7e:96: + ef:c1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 44:7B:00:7C:9C:1C:97:9F:97:AA:6B:F2:5E:E6:81:7C:0E:AE:E6:2B + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:128 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 81:17:73:e0:8e:30:5f:5e:a7:25:a8:c0:89:f0:2a:c5:cc:72: + 30:0a:55:f2:c8:13:34:de:3c:7c:5e:e1:56:5e:72:04:10:8b: + 4b:05:3b:14:3c:37:0e:48:68:23:a1:2c:f5:72:f0:36:57:79: + fa:6f:ee:b0:17:83:f0:8a:1f:f0:6b:88:3b:57:c8:b2:57:c9: + 4e:35:14:a8:d7:31:db:68:74:8c:30:24:b3:9d:c9:8d:8c:36: + 34:30:0e:f3:4e:74:bd:14:77:c8:13:7f:bc:d3:21:34:e8:87: + e7:a3:80:62:ea:20:4b:40:ef:f5:97:db:c7:63:6b:e4:06:12: + 1a:b7:55:da:5a:34:32:95:59:c4:68:85:2c:87:dd:77:5f:ff: + 28:cf:95:c3:68:f8:c4:32:af:8e:c6:2c:39:6b:bd:3a:dd:18: + 16:a8:a7:0e:9d:93:6d:8e:77:b1:0e:86:55:0d:a4:aa:e6:3f: + f5:69:1d:d5:c0:5e:1a:b1:bc:ab:5f:eb:1f:76:6a:c5:22:57: + a9:f1:ee:55:56:37:61:9e:49:e6:bc:8b:e9:9d:6b:11:6f:90: + cb:d6:18:3c:81:f2:c8:4c:92:e4:4d:73:d1:a1:be:8d:fe:d7: + 54:20:d4:df:43:7d:e7:57:f1:dd:9f:a0:6d:cd:e3:ab:30:fa: + cc:29:0b:01 +-----BEGIN CERTIFICATE----- +MIIExDCCA6ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA5WhcNMjIwNzA3MDAyODA5WjCBozELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNoYWluRS1JQ0Ex +LXBhdGhsZW4xMjgxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDW82+42xDfid872S56wTQaVpds +cwT8FVAEk2bLF7r7+Si51s5+9Xi7sU+qS/iANdmu/pl19815C8/K2stYmm6bkSH0 +F/1WuDrPz+33kGpzbAaZ7w6PZdzQ6Nt7wehNbWGezFog3oY6WIH6sdRfPHRDRWE2 +LP6kNa7iOcf93bOD1hfc9Zk/Zw7BYNFpjTz5YumDrmYQqkCRYwsq5cGoH46KmxGf +v6ZF+xZw7WwbFJiAaQTDvRMi59kzSJ2KbA+cOQgpkoN7c6PahtZKAA+nwnu/rA8q +YpZbO++f4Qi7RLrEmU+guV5Ny3Nz/u6CaU+vx1laNoFExuNQO7+NFO9+lu/BAgMB +AAGjggEOMIIBCjAdBgNVHQ4EFgQURHsAfJwcl5+XqmvyXuaBfA6u5iswgckGA1Ud +IwSBwTCBvoAUJ45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYT +AlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQK +DAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1 +jhDeuPswEAYDVR0TBAkwBwEB/wICAIAwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEB +CwUAA4IBAQCBF3PgjjBfXqclqMCJ8CrFzHIwClXyyBM03jx8XuFWXnIEEItLBTsU +PDcOSGgjoSz1cvA2V3n6b+6wF4Pwih/wa4g7V8iyV8lONRSo1zHbaHSMMCSzncmN +jDY0MA7zTnS9FHfIE3+80yE06Ifno4Bi6iBLQO/1l9vHY2vkBhIat1XaWjQylVnE +aIUsh913X/8oz5XDaPjEMq+Oxiw5a7063RgWqKcOnZNtjnexDoZVDaSq5j/1aR3V +wF4asbyrX+sfdmrFIlep8e5VVjdhnknmvIvpnWsRb5DL1hg8gfLITJLkTXPRob6N +/tdUINTfQ33nV/Hdn6BtzeOrMPrMKQsB +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-assembled.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-assembled.pem new file mode 100644 index 000000000..be49ab5be --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-assembled.pem @@ -0,0 +1,175 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainE-ICA1-pathlen128, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainE-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d8:6f:49:bb:56:ea:34:4c:25:a6:8c:44:f6:c9: + 75:8f:6b:83:b8:8b:ec:c6:f6:d3:c7:40:e2:d1:b2: + d8:77:92:e9:97:c4:b6:57:ad:10:c8:cb:e7:0a:40: + ef:3c:a8:38:dc:94:22:08:e7:53:2a:c8:7a:26:90: + 41:43:6f:7b:8f:4e:58:74:69:20:92:9f:12:aa:6a: + c5:cf:7f:24:d1:d0:89:2f:6c:5e:62:31:0a:20:23: + 6b:07:c2:a0:7d:4d:ed:05:6d:2c:b1:9a:85:e6:41: + 61:12:6c:85:d3:d4:be:7e:cf:23:d9:79:b1:46:23: + d7:1a:f7:d6:f4:97:43:a5:08:03:7a:51:0d:b0:e7: + 56:62:86:37:07:81:e8:21:f1:10:63:41:b6:82:6d: + f2:cd:d9:7f:80:6f:a7:4b:77:10:15:54:02:9c:7a: + d0:6e:b8:29:98:72:34:08:7b:ce:d7:24:91:48:a6: + c3:f2:9d:77:fc:aa:73:13:70:60:f9:8f:37:4c:d7: + 34:5c:fa:51:b1:c0:d5:25:e1:75:b2:e2:cd:23:97: + c9:a6:bf:d3:5e:21:4b:12:f5:b2:d0:df:92:7f:4c: + a8:b2:21:43:2c:f9:3e:fb:14:99:1f:ed:76:2c:87: + 5a:df:72:d3:85:a3:a8:92:1a:ad:66:19:50:44:8a: + 05:e1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 26:FC:70:E0:8F:A1:3D:52:82:76:6B:CB:C7:0F:89:9D:2B:86:69:F5 + X509v3 Authority Key Identifier: + keyid:44:7B:00:7C:9C:1C:97:9F:97:AA:6B:F2:5E:E6:81:7C:0E:AE:E6:2B + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 1a:af:fd:cb:5e:63:ed:ac:39:c5:e1:0f:32:2c:6e:f2:0b:23: + 1d:d8:61:e4:39:d6:a6:e6:69:a3:df:f7:3b:80:84:22:72:58: + 0e:bc:ef:92:10:65:93:16:20:e4:69:d7:d1:58:0b:33:f2:68: + a2:6b:76:36:d0:f0:36:3c:61:31:dc:44:a0:00:e2:80:9e:62: + d5:fe:cc:08:66:ca:23:88:b3:e0:48:32:be:d8:dd:d2:a6:f9: + 20:13:1a:1f:a0:65:80:8d:d8:c5:c6:c5:3f:1a:ec:ae:2a:a5: + ac:de:97:eb:56:96:c7:55:16:ee:5f:e2:74:e2:03:1f:91:69: + 70:b8:fb:5a:42:26:7a:fa:5e:8d:19:eb:5a:2e:32:09:c9:95: + be:9e:34:d4:90:88:42:7e:ad:70:8b:cf:7d:5d:d0:a8:91:aa: + 93:1a:d1:15:7c:2d:a7:af:c2:d2:d7:65:20:5e:8b:3d:b1:df: + 98:5f:56:ad:ed:57:ca:53:ac:0e:f7:86:a4:80:d2:ea:f2:01: + e6:b0:5f:6f:4f:12:17:31:7c:8e:24:43:ac:94:06:aa:6d:a4: + eb:eb:43:b6:64:ed:76:24:bf:73:d8:7c:56:7e:d5:8b:66:f6: + cb:09:0d:f7:44:34:a3:93:d8:e7:36:1a:5f:0f:51:22:09:79: + 24:dd:31:9e +-----BEGIN CERTIFICATE----- +MIIErDCCA5SgAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluRS1JQ0ExLXBhdGhsZW4xMjgxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMDAyODA5WhcNMjIwNzA3MDAyODA5WjCBmjELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxFjAUBgNV +BAMMDWNoYWluRS1lbnRpdHkxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDYb0m7Vuo0TCWmjET2 +yXWPa4O4i+zG9tPHQOLRsth3kumXxLZXrRDIy+cKQO88qDjclCII51MqyHomkEFD +b3uPTlh0aSCSnxKqasXPfyTR0IkvbF5iMQogI2sHwqB9Te0FbSyxmoXmQWESbIXT +1L5+zyPZebFGI9ca99b0l0OlCAN6UQ2w51ZihjcHgegh8RBjQbaCbfLN2X+Ab6dL +dxAVVAKcetBuuCmYcjQIe87XJJFIpsPynXf8qnMTcGD5jzdM1zRc+lGxwNUl4XWy +4s0jl8mmv9NeIUsS9bLQ35J/TKiyIUMs+T77FJkf7XYsh1rfctOFo6iSGq1mGVBE +igXhAgMBAAGjgfEwge4wHQYDVR0OBBYEFCb8cOCPoT1SgnZry8cPiZ0rhmn1MIHB +BgNVHSMEgbkwgbaAFER7AHycHJefl6pr8l7mgXwOruYroYGapIGXMIGUMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G +A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIB +ZDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAar/3LXmPtrDnF4Q8yLG7y +CyMd2GHkOdam5mmj3/c7gIQiclgOvO+SEGWTFiDkadfRWAsz8miia3Y20PA2PGEx +3ESgAOKAnmLV/swIZsojiLPgSDK+2N3SpvkgExofoGWAjdjFxsU/GuyuKqWs3pfr +VpbHVRbuX+J04gMfkWlwuPtaQiZ6+l6NGetaLjIJyZW+njTUkIhCfq1wi899XdCo +kaqTGtEVfC2nr8LS12UgXos9sd+YX1at7VfKU6wO94akgNLq8gHmsF9vTxIXMXyO +JEOslAaqbaTr60O2ZO12JL9z2HxWftWLZvbLCQ33RDSjk9jnNhpfD1EiCXkk3TGe +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainE-ICA1-pathlen128, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d6:f3:6f:b8:db:10:df:89:df:3b:d9:2e:7a:c1: + 34:1a:56:97:6c:73:04:fc:15:50:04:93:66:cb:17: + ba:fb:f9:28:b9:d6:ce:7e:f5:78:bb:b1:4f:aa:4b: + f8:80:35:d9:ae:fe:99:75:f7:cd:79:0b:cf:ca:da: + cb:58:9a:6e:9b:91:21:f4:17:fd:56:b8:3a:cf:cf: + ed:f7:90:6a:73:6c:06:99:ef:0e:8f:65:dc:d0:e8: + db:7b:c1:e8:4d:6d:61:9e:cc:5a:20:de:86:3a:58: + 81:fa:b1:d4:5f:3c:74:43:45:61:36:2c:fe:a4:35: + ae:e2:39:c7:fd:dd:b3:83:d6:17:dc:f5:99:3f:67: + 0e:c1:60:d1:69:8d:3c:f9:62:e9:83:ae:66:10:aa: + 40:91:63:0b:2a:e5:c1:a8:1f:8e:8a:9b:11:9f:bf: + a6:45:fb:16:70:ed:6c:1b:14:98:80:69:04:c3:bd: + 13:22:e7:d9:33:48:9d:8a:6c:0f:9c:39:08:29:92: + 83:7b:73:a3:da:86:d6:4a:00:0f:a7:c2:7b:bf:ac: + 0f:2a:62:96:5b:3b:ef:9f:e1:08:bb:44:ba:c4:99: + 4f:a0:b9:5e:4d:cb:73:73:fe:ee:82:69:4f:af:c7: + 59:5a:36:81:44:c6:e3:50:3b:bf:8d:14:ef:7e:96: + ef:c1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 44:7B:00:7C:9C:1C:97:9F:97:AA:6B:F2:5E:E6:81:7C:0E:AE:E6:2B + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:128 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 81:17:73:e0:8e:30:5f:5e:a7:25:a8:c0:89:f0:2a:c5:cc:72: + 30:0a:55:f2:c8:13:34:de:3c:7c:5e:e1:56:5e:72:04:10:8b: + 4b:05:3b:14:3c:37:0e:48:68:23:a1:2c:f5:72:f0:36:57:79: + fa:6f:ee:b0:17:83:f0:8a:1f:f0:6b:88:3b:57:c8:b2:57:c9: + 4e:35:14:a8:d7:31:db:68:74:8c:30:24:b3:9d:c9:8d:8c:36: + 34:30:0e:f3:4e:74:bd:14:77:c8:13:7f:bc:d3:21:34:e8:87: + e7:a3:80:62:ea:20:4b:40:ef:f5:97:db:c7:63:6b:e4:06:12: + 1a:b7:55:da:5a:34:32:95:59:c4:68:85:2c:87:dd:77:5f:ff: + 28:cf:95:c3:68:f8:c4:32:af:8e:c6:2c:39:6b:bd:3a:dd:18: + 16:a8:a7:0e:9d:93:6d:8e:77:b1:0e:86:55:0d:a4:aa:e6:3f: + f5:69:1d:d5:c0:5e:1a:b1:bc:ab:5f:eb:1f:76:6a:c5:22:57: + a9:f1:ee:55:56:37:61:9e:49:e6:bc:8b:e9:9d:6b:11:6f:90: + cb:d6:18:3c:81:f2:c8:4c:92:e4:4d:73:d1:a1:be:8d:fe:d7: + 54:20:d4:df:43:7d:e7:57:f1:dd:9f:a0:6d:cd:e3:ab:30:fa: + cc:29:0b:01 +-----BEGIN CERTIFICATE----- +MIIExDCCA6ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA5WhcNMjIwNzA3MDAyODA5WjCBozELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNoYWluRS1JQ0Ex +LXBhdGhsZW4xMjgxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDW82+42xDfid872S56wTQaVpds +cwT8FVAEk2bLF7r7+Si51s5+9Xi7sU+qS/iANdmu/pl19815C8/K2stYmm6bkSH0 +F/1WuDrPz+33kGpzbAaZ7w6PZdzQ6Nt7wehNbWGezFog3oY6WIH6sdRfPHRDRWE2 +LP6kNa7iOcf93bOD1hfc9Zk/Zw7BYNFpjTz5YumDrmYQqkCRYwsq5cGoH46KmxGf +v6ZF+xZw7WwbFJiAaQTDvRMi59kzSJ2KbA+cOQgpkoN7c6PahtZKAA+nwnu/rA8q +YpZbO++f4Qi7RLrEmU+guV5Ny3Nz/u6CaU+vx1laNoFExuNQO7+NFO9+lu/BAgMB +AAGjggEOMIIBCjAdBgNVHQ4EFgQURHsAfJwcl5+XqmvyXuaBfA6u5iswgckGA1Ud +IwSBwTCBvoAUJ45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYT +AlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQK +DAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1 +jhDeuPswEAYDVR0TBAkwBwEB/wICAIAwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEB +CwUAA4IBAQCBF3PgjjBfXqclqMCJ8CrFzHIwClXyyBM03jx8XuFWXnIEEItLBTsU +PDcOSGgjoSz1cvA2V3n6b+6wF4Pwih/wa4g7V8iyV8lONRSo1zHbaHSMMCSzncmN +jDY0MA7zTnS9FHfIE3+80yE06Ifno4Bi6iBLQO/1l9vHY2vkBhIat1XaWjQylVnE +aIUsh913X/8oz5XDaPjEMq+Oxiw5a7063RgWqKcOnZNtjnexDoZVDaSq5j/1aR3V +wF4asbyrX+sfdmrFIlep8e5VVjdhnknmvIvpnWsRb5DL1hg8gfLITJLkTXPRob6N +/tdUINTfQ33nV/Hdn6BtzeOrMPrMKQsB +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-entity-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-entity-key.pem new file mode 100644 index 000000000..a896306eb --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-entity-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA2G9Ju1bqNEwlpoxE9sl1j2uDuIvsxvbTx0Di0bLYd5Lpl8S2 +V60QyMvnCkDvPKg43JQiCOdTKsh6JpBBQ297j05YdGkgkp8SqmrFz38k0dCJL2xe +YjEKICNrB8KgfU3tBW0ssZqF5kFhEmyF09S+fs8j2XmxRiPXGvfW9JdDpQgDelEN +sOdWYoY3B4HoIfEQY0G2gm3yzdl/gG+nS3cQFVQCnHrQbrgpmHI0CHvO1ySRSKbD +8p13/KpzE3Bg+Y83TNc0XPpRscDVJeF1suLNI5fJpr/TXiFLEvWy0N+Sf0yosiFD +LPk++xSZH+12LIda33LThaOokhqtZhlQRIoF4QIDAQABAoIBAQCWY23WMKR4Rlj7 +Cwh4eq+nQku6le+mqKerEhkJIL5tB7YscNFKxsSc4aHebBRQD4vDKWMk0KfnWHoY +BbBzjSlMAGJSMSIi/0lXBO4CKhSJfd91BlXm4LBqeHHMaJ5fsx/4301o8zgLMG6l +AKdU88SSFJiSao6VcB3tbTz9o4WrS0jQjRClC+f2LWbn8ua/JhP0q1Tfji10fdLR +dVc5dzB8R59f4CuA0dIuACwV021E2sL0wRWCb4FV6IQBDD3hFgQjhJOTTkVOHsxq +nAwWQTJO2N2aODC33+ZTAQsMBnFhXjBUk0UWJHLAWVbN+q4O8o6J5fk4VSQG9/u4 +PMjvK0GJAoGBAPTF4AbmG8vAVCMRE6K2pq1Hqw79XWd22le4jvwahle7F+CgUeiO +Nj2HOgzZwUg9diXxjjYpRuW0x2HgyvC07NRXPNDeb08W3z35pv/SJFj6uiy/Itwi +W7527KfRoVz1kWzIs4Erod+a+W0dJCZsFYqlc4Yl2JdKDGQhcZFmc/2HAoGBAOJc +qlDioL5gAnHtUD9b0KkMafnQ8KzI+YPeLvxxP/9P8lVTMno0JpByNrxkpKx9JUBc +DdOCXUj0dkynuNEfRfKydCez6oThLJHHfxvFniX+3Xm32j9+gj7SqLtpGiHuP9nj +UInKsKDokPZLQLF7KNjNfBjjc29MPP+cmRPg+XtXAoGATjVbW1jy0KtnNr0iFP9f +SkZ39ZYm3gQvx4+EwDCJdEanXnJbOX8W/ZnThn+dLkPVGFKSKeQObx7QBgoZTcfB +VCd7mxE3Z4HbWqYGIf829edGzT1VGhkwTy8YdpaYhGdCTAvkrwUN97BAughxoIUw +bNhojRhSmCRkySmWa+rcbMkCgYEAlfiG7qf3j6nUdN6huBiAmj+bRuPjUNamWXOu +9ZmiqOiyyU0huE0s7658DT0wzQbs00Mp9eP9IgS1C/xjOknZ8f3BbzyIOBlnif3+ +fMvlB49f9PCWLFMIv86Z8/CiW7CZpSYxidk8RJ9Qy5z3856BZYJeoa6wICEGmOOL +l9wJ7mkCgYEAkJAteZKula8p1kNvI3hfzpCSjm8JJId8S58T3U0Lql9FT3M50xSx +81Aoxn0sAcTihtcjjTTQVFPAxs6g/W4WcpR8EbTb1XJ+jdCywZZkCZCMm1D2RF8b +kJ0w2xuBUDwgUsaLMzxPpEY6SIwStAmTbWOAYXdx8Zg4sUwroE9F/YU= +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-entity.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-entity.pem new file mode 100644 index 000000000..a4b979416 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainE-entity.pem @@ -0,0 +1,86 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainE-ICA1-pathlen128, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainE-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d8:6f:49:bb:56:ea:34:4c:25:a6:8c:44:f6:c9: + 75:8f:6b:83:b8:8b:ec:c6:f6:d3:c7:40:e2:d1:b2: + d8:77:92:e9:97:c4:b6:57:ad:10:c8:cb:e7:0a:40: + ef:3c:a8:38:dc:94:22:08:e7:53:2a:c8:7a:26:90: + 41:43:6f:7b:8f:4e:58:74:69:20:92:9f:12:aa:6a: + c5:cf:7f:24:d1:d0:89:2f:6c:5e:62:31:0a:20:23: + 6b:07:c2:a0:7d:4d:ed:05:6d:2c:b1:9a:85:e6:41: + 61:12:6c:85:d3:d4:be:7e:cf:23:d9:79:b1:46:23: + d7:1a:f7:d6:f4:97:43:a5:08:03:7a:51:0d:b0:e7: + 56:62:86:37:07:81:e8:21:f1:10:63:41:b6:82:6d: + f2:cd:d9:7f:80:6f:a7:4b:77:10:15:54:02:9c:7a: + d0:6e:b8:29:98:72:34:08:7b:ce:d7:24:91:48:a6: + c3:f2:9d:77:fc:aa:73:13:70:60:f9:8f:37:4c:d7: + 34:5c:fa:51:b1:c0:d5:25:e1:75:b2:e2:cd:23:97: + c9:a6:bf:d3:5e:21:4b:12:f5:b2:d0:df:92:7f:4c: + a8:b2:21:43:2c:f9:3e:fb:14:99:1f:ed:76:2c:87: + 5a:df:72:d3:85:a3:a8:92:1a:ad:66:19:50:44:8a: + 05:e1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 26:FC:70:E0:8F:A1:3D:52:82:76:6B:CB:C7:0F:89:9D:2B:86:69:F5 + X509v3 Authority Key Identifier: + keyid:44:7B:00:7C:9C:1C:97:9F:97:AA:6B:F2:5E:E6:81:7C:0E:AE:E6:2B + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 1a:af:fd:cb:5e:63:ed:ac:39:c5:e1:0f:32:2c:6e:f2:0b:23: + 1d:d8:61:e4:39:d6:a6:e6:69:a3:df:f7:3b:80:84:22:72:58: + 0e:bc:ef:92:10:65:93:16:20:e4:69:d7:d1:58:0b:33:f2:68: + a2:6b:76:36:d0:f0:36:3c:61:31:dc:44:a0:00:e2:80:9e:62: + d5:fe:cc:08:66:ca:23:88:b3:e0:48:32:be:d8:dd:d2:a6:f9: + 20:13:1a:1f:a0:65:80:8d:d8:c5:c6:c5:3f:1a:ec:ae:2a:a5: + ac:de:97:eb:56:96:c7:55:16:ee:5f:e2:74:e2:03:1f:91:69: + 70:b8:fb:5a:42:26:7a:fa:5e:8d:19:eb:5a:2e:32:09:c9:95: + be:9e:34:d4:90:88:42:7e:ad:70:8b:cf:7d:5d:d0:a8:91:aa: + 93:1a:d1:15:7c:2d:a7:af:c2:d2:d7:65:20:5e:8b:3d:b1:df: + 98:5f:56:ad:ed:57:ca:53:ac:0e:f7:86:a4:80:d2:ea:f2:01: + e6:b0:5f:6f:4f:12:17:31:7c:8e:24:43:ac:94:06:aa:6d:a4: + eb:eb:43:b6:64:ed:76:24:bf:73:d8:7c:56:7e:d5:8b:66:f6: + cb:09:0d:f7:44:34:a3:93:d8:e7:36:1a:5f:0f:51:22:09:79: + 24:dd:31:9e +-----BEGIN CERTIFICATE----- +MIIErDCCA5SgAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluRS1JQ0ExLXBhdGhsZW4xMjgxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMDAyODA5WhcNMjIwNzA3MDAyODA5WjCBmjELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxFjAUBgNV +BAMMDWNoYWluRS1lbnRpdHkxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDYb0m7Vuo0TCWmjET2 +yXWPa4O4i+zG9tPHQOLRsth3kumXxLZXrRDIy+cKQO88qDjclCII51MqyHomkEFD +b3uPTlh0aSCSnxKqasXPfyTR0IkvbF5iMQogI2sHwqB9Te0FbSyxmoXmQWESbIXT +1L5+zyPZebFGI9ca99b0l0OlCAN6UQ2w51ZihjcHgegh8RBjQbaCbfLN2X+Ab6dL +dxAVVAKcetBuuCmYcjQIe87XJJFIpsPynXf8qnMTcGD5jzdM1zRc+lGxwNUl4XWy +4s0jl8mmv9NeIUsS9bLQ35J/TKiyIUMs+T77FJkf7XYsh1rfctOFo6iSGq1mGVBE +igXhAgMBAAGjgfEwge4wHQYDVR0OBBYEFCb8cOCPoT1SgnZry8cPiZ0rhmn1MIHB +BgNVHSMEgbkwgbaAFER7AHycHJefl6pr8l7mgXwOruYroYGapIGXMIGUMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G +A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIB +ZDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAar/3LXmPtrDnF4Q8yLG7y +CyMd2GHkOdam5mmj3/c7gIQiclgOvO+SEGWTFiDkadfRWAsz8miia3Y20PA2PGEx +3ESgAOKAnmLV/swIZsojiLPgSDK+2N3SpvkgExofoGWAjdjFxsU/GuyuKqWs3pfr +VpbHVRbuX+J04gMfkWlwuPtaQiZ6+l6NGetaLjIJyZW+njTUkIhCfq1wi899XdCo +kaqTGtEVfC2nr8LS12UgXos9sd+YX1at7VfKU6wO94akgNLq8gHmsF9vTxIXMXyO +JEOslAaqbaTr60O2ZO12JL9z2HxWftWLZvbLCQ33RDSjk9jnNhpfD1EiCXkk3TGe +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA1-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA1-key.pem new file mode 100644 index 000000000..efe224d61 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA1-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA4BPJsI6dP4jUMEq06BEhk1wgRQj4epG5LK3/YKoWnxy7iLg9 +CjnBial2yo5scnJ+bnSmNixp3zPW6WZwZX+6KkQXYp8zRhLmA6Wm4lwJB8+8jXb+ +oP3XckqUyMovlZGcCnd/giO+cicpRc1Bz+zhhM9n0BiYuTG+yf6YXT+q0oN2RYWr +CIZjWFuz5UpDPaGZ4oDRK7IG4/AQhfmmNrhSK51zOzQjUT3+Vi/pObJoBz5vUnv0 +QNRy+mkZyv8iyEWVBV6RCD8nLUHRdKUGnPNAvbv8ZWOG7YAiUMH2T9yPQ0xe+7/Z +bR+0hA8e6MZdxVPVLMl/a5iTp101mhdikS4gwQIDAQABAoIBAQC8aacToDc0rxbM +LGUFJTJ4N+SiZ7KXTWTI3t13KE2xKHW/tjsNGBdWa3oJQ8yIRyFsOwVvU9UJ6wrw +YkRr9ARTecG4GWkBqO5jbqxudTjaqqA+yym7sPWxkmiclPWB7FeqrWQ3x1phnfAk +UzzdWq8d/0+pOKViQyPLsRnofppiOril9LTJnklrBMDkf7wE9X6gpbpRfM7fd8nH +5mekM3pxKUi2v03yCyAJT15L5f7f7BIgXaz+QCXZpT6O+6c4D7neI3ne6b8JHgvT +XGXRXyvwC38wENCbsvBIsPAF1UDMS//F7oLK5qysCeoStPYX0uIbtTLwlfOHL//g +rYtnskmpAoGBAPyHWs11M7Xr1AWX0cgStgF8lkzu9YjxDr/HvWr+1Jr03YYKTOMj +XY/PKDRbjn/FXZ2Dw0WjmsKhsgnHsWfARHMLrZ7eQzhuhd2w6NsaAiREA7zh0FUF +D0+K8m5L4cob3OU7/sLS7+ubvGrIWuvVs1GAo4+/Q5MPJ9h+WOrZC4rTAoGBAOMo +UBxFWKpaDu7cekWcLDxqK3d77gDG0Xo4bDtRVTa7fn+jdqqMNuLG2D+8t/Cqjr2z +CNvTTdTohzsHsCay5u6RX3GSe9z3jdXu8CFNMnDVceYY/uxQio9biq4pXIKtfobn +2orzAOmqN9LeR76fME4WYwXTCPQVVcQzQN55WMGbAoGAGrLw3cIjent5ijHYAzA/ +P/79IRsuqJDb/1jN5Q8WSV/UQAS8xlMJ5FeBp696bHXghPPWZHl8tlFEMpaDYjXI +xuUYMTDMqJ2+14aJyAiC63SpdIHndeW4Da/iG9k4ARdbDn1+XPjSVvW7QQr32fFZ +KSfRozQUn+q9Sr1pB0N1XfMCgYEA3UL7JU522xf1y7x+bSd9/yr7Q9s3LRJ8IKys +3+qNMk7XHMTAZcdF/wboxMyx7n5zo1usmVLtUSFd96W5czh3sJFxglLIy6dmRKgE +xqtHIpkF5LccOFsLXDAymQo4ziDoSce1G/svPGtNDNzuzUKJ7sXnlljFM9tEO2Qh +H5LbXVkCgYBYzArfIhOCL1pGBSh5ocpyXG16Dn7dd6HmWPsD0kVwftlW+gJAmnXY +3cFzrQSacqe1Z76OqtmFfUGKE4pw50ayshkO9PG0DFi+b9SZgQX0yrDY1lHHS74v +MbuiJNOxHZugawEd2LUYQzry4PKNqYg31VuxpIQKjHrUvGivCyTALA== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA1-pathlen1.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA1-pathlen1.pem new file mode 100644 index 000000000..580610852 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA1-pathlen1.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainF-ICA2-pathlen0, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainF-ICA1-pathlen1, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:e0:13:c9:b0:8e:9d:3f:88:d4:30:4a:b4:e8:11: + 21:93:5c:20:45:08:f8:7a:91:b9:2c:ad:ff:60:aa: + 16:9f:1c:bb:88:b8:3d:0a:39:c1:89:a9:76:ca:8e: + 6c:72:72:7e:6e:74:a6:36:2c:69:df:33:d6:e9:66: + 70:65:7f:ba:2a:44:17:62:9f:33:46:12:e6:03:a5: + a6:e2:5c:09:07:cf:bc:8d:76:fe:a0:fd:d7:72:4a: + 94:c8:ca:2f:95:91:9c:0a:77:7f:82:23:be:72:27: + 29:45:cd:41:cf:ec:e1:84:cf:67:d0:18:98:b9:31: + be:c9:fe:98:5d:3f:aa:d2:83:76:45:85:ab:08:86: + 63:58:5b:b3:e5:4a:43:3d:a1:99:e2:80:d1:2b:b2: + 06:e3:f0:10:85:f9:a6:36:b8:52:2b:9d:73:3b:34: + 23:51:3d:fe:56:2f:e9:39:b2:68:07:3e:6f:52:7b: + f4:40:d4:72:fa:69:19:ca:ff:22:c8:45:95:05:5e: + 91:08:3f:27:2d:41:d1:74:a5:06:9c:f3:40:bd:bb: + fc:65:63:86:ed:80:22:50:c1:f6:4f:dc:8f:43:4c: + 5e:fb:bf:d9:6d:1f:b4:84:0f:1e:e8:c6:5d:c5:53: + d5:2c:c9:7f:6b:98:93:a7:5d:35:9a:17:62:91:2e: + 20:c1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 75:32:21:05:2B:60:FE:44:17:AF:18:65:86:85:19:82:3F:F9:64:83 + X509v3 Authority Key Identifier: + keyid:4A:53:4A:B7:30:78:35:91:B4:CB:DD:C8:22:74:89:AF:80:0F:7F:68 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:1 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 6a:e9:07:00:56:3b:70:9a:2b:3d:42:e9:93:ad:76:a9:43:82: + a9:44:2a:35:a2:c7:56:d4:1e:cd:26:7c:d4:3f:49:19:3a:1e: + 88:ed:f7:3d:b5:88:65:41:b4:69:81:59:fd:bd:93:b3:5c:ba: + ae:60:b9:0b:e7:4b:60:a7:e4:b1:fa:ec:85:09:2b:e8:ff:84: + 77:71:75:63:c2:8a:10:51:76:7a:c9:6f:9a:a3:8b:10:b4:ed: + 9d:75:18:52:f5:a9:8a:ed:e0:0c:a4:23:96:f8:39:f6:fd:ce: + 58:21:54:2c:b1:a2:a1:73:eb:9f:93:99:0c:12:1e:9a:bb:3d: + 1e:91:da:df:b3:66:6a:cb:44:33:a8:d2:5d:31:76:d5:96:30: + 51:dd:d0:12:e9:7b:9b:9f:98:ac:35:03:0f:6f:2d:b5:b6:e1: + 30:14:50:31:2e:4c:fd:65:f5:d2:20:7b:8d:1d:a3:7f:6c:4f: + 47:d6:c8:97:26:cf:28:65:d8:a0:19:d1:ca:2e:e8:f7:11:cb: + ab:a6:32:2b:82:4d:c1:df:0a:c5:e5:9e:00:39:65:20:7e:55: + ad:81:ac:14:b1:f9:f3:88:96:94:26:e1:66:44:96:68:1b:1a: + 8d:db:f3:b9:e7:b8:9b:50:0b:03:19:53:70:c8:58:75:70:1f: + 0e:a4:bb:9f +-----BEGIN CERTIFICATE----- +MIIExjCCA66gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluRi1JQ0EyLXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgaExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR0wGwYDVQQD +DBRjaGFpbkYtSUNBMS1wYXRobGVuMTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm +c3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOATybCOnT+I +1DBKtOgRIZNcIEUI+HqRuSyt/2CqFp8cu4i4PQo5wYmpdsqObHJyfm50pjYsad8z +1ulmcGV/uipEF2KfM0YS5gOlpuJcCQfPvI12/qD913JKlMjKL5WRnAp3f4IjvnIn +KUXNQc/s4YTPZ9AYmLkxvsn+mF0/qtKDdkWFqwiGY1hbs+VKQz2hmeKA0SuyBuPw +EIX5pja4Uiudczs0I1E9/lYv6TmyaAc+b1J79EDUcvppGcr/IshFlQVekQg/Jy1B +0XSlBpzzQL27/GVjhu2AIlDB9k/cj0NMXvu/2W0ftIQPHujGXcVT1SzJf2uYk6dd +NZoXYpEuIMECAwEAAaOCAQUwggEBMB0GA1UdDgQWBBR1MiEFK2D+RBevGGWGhRmC +P/lkgzCBwQYDVR0jBIG5MIG2gBRKU0q3MHg1kbTL3cgidImvgA9/aKGBmqSBlzCB +lDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVt +YW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYD +VQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb22CAWQwDwYDVR0TBAgwBgEB/wIBATALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN +AQELBQADggEBAGrpBwBWO3CaKz1C6ZOtdqlDgqlEKjWix1bUHs0mfNQ/SRk6Hojt +9z21iGVBtGmBWf29k7Ncuq5guQvnS2Cn5LH67IUJK+j/hHdxdWPCihBRdnrJb5qj +ixC07Z11GFL1qYrt4AykI5b4Ofb9zlghVCyxoqFz65+TmQwSHpq7PR6R2t+zZmrL +RDOo0l0xdtWWMFHd0BLpe5ufmKw1Aw9vLbW24TAUUDEuTP1l9dIge40do39sT0fW +yJcmzyhl2KAZ0cou6PcRy6umMiuCTcHfCsXlngA5ZSB+Va2BrBSx+fOIlpQm4WZE +lmgbGo3b87nnuJtQCwMZU3DIWHVwHw6ku58= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA2-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA2-key.pem new file mode 100644 index 000000000..07b4753b3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA2-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA2joiZfhtHLcch90n9Nd1qnwcNzG01qU0SzZA6lUIcqD/WOJd +JhH1uG7e18O7JlHI0DYUAHZCTQNz74i5N/TonWFFluGObHhY4fbPRorWpXlNR4jK +bGlOKNSNhKjhbB3TNn4j42TVCqP8NomQCv9+i/ouZvvHM0SS3w9DsuskfiuusEOp +rVOC+N4XGSZfyoysDB8kvRXtT12C6hDrBXBPA2DZI20hB00SnPNk7nb7nfnD2Bo7 +bqmCey0usHS3E9ZligbyJXTCJulxZlRh/io0JwfJje+gooaTQUdzCAEHzE3s/oCI +k/uutJEW+oOWhGZTzfNS2tQl4QkVIOIQ6t057wIDAQABAoIBAFHY4/XiyumuM+Ex +LT9DYDpk+iApYG3w4EAlRQuegOCdSagInm8c5VAbJTE/k/23Rt3wqmfR8uP3m5AH +c5BtJqGATh1c05ITQSLe8ra+c+r0J+vgfitTA6GEtt8+h+2I8iLKBKPQuaaYAoxh +48h8MvZFCwpM/FVaLsvCad29G57GCh4oMK8Q4loQhA4xIKDZkW1djjqckJcGwZnk +ST4+QcFt3gVNW8Ceezws4K7BBe7+bcpiWuFFILyv3lYrazzCeLPa/hOCPWSZ31Wq +cH4OTRaiTCnMxAdNXFPFNKjXV5oADUe226whk7G1Bp8oEWisi3r/ctSnl5bhqO0W +eRxMwWECgYEA7NXGKuQPA4GKLLQzE2DppSfDYJKsE1LmMMe2Y+ys9QURKedezgS3 +ri91KugHfOW7ZZ3TGI68WPFY7h6OvV2F334rOa3dCJ1SH3kgvZNQ2kQx5cPnqNb7 +NmlbD59Ph3lV8SykuCaJe/ZAxCqjeW+TYJ5PWivI6UMr0LPxmEE6JPsCgYEA6+Lh +qF7aFXPhvtTg0FQzZXiYTWQ//dwPv3FniNychkf4Sa0rRFNBaFDpyJbPmOHGVnhu +0y7p2ahRXfXnyzfGko/MXp9VOedVX4MzVAI2QvahXoSoYZGfZ6nKOQUAUTFaTvmv +HpeNHMEjnnbnUJtdd6tXAa5kzZE6dmOHzH6/5J0CgYAoh0CdMF+9WtqZYdDnvQre +n1pY2WCnAeWwbUyx9tt2JoLUZ+qaWMZSAX8Mc55saifScNqh9jMXCV4NiZ8lmq6B +G2csPKt5gOp/xkurBV2trEPZrNek1f0xR4A0wS9r4ICrf9dESBv44aAdsao96rEO +tKihpqKAAGWsFk7+nhLkJwKBgQDT5o+iifrNVLlRjbibTViSagAfXdRif2KiLwS8 +HLp7ooF35hk9GrFiPXWWXWwGQaPDoBKmobkvbxYRG0tr8iHvHUCRK/8KsjauQ5VD +fW0zQIz79J2ycHfLTuq7yDNdvMEMux3GlIwOba5KtzPa5IbVbtUNTJV/WVw0Z/rh +CGfnvQKBgQCRJpXicdarhdf5iHmZJ5SEgxfKk7nIXUq3mIadSHnD1ar8vZ83Lv6y +wXVfGVytjd4k8ezcpKHNoeBUBnFLfUJkkBOXWghWi+TkX5f8Ci33ffgIie8RPZtO +8EP3Q7yOI//JCEcgIiuqUZOug45m8UCCcky6dOCFLSH1a1Fj1doCWA== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA2-pathlen0.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA2-pathlen0.pem new file mode 100644 index 000000000..128b32370 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-ICA2-pathlen0.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainF-ICA2-pathlen0, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:da:3a:22:65:f8:6d:1c:b7:1c:87:dd:27:f4:d7: + 75:aa:7c:1c:37:31:b4:d6:a5:34:4b:36:40:ea:55: + 08:72:a0:ff:58:e2:5d:26:11:f5:b8:6e:de:d7:c3: + bb:26:51:c8:d0:36:14:00:76:42:4d:03:73:ef:88: + b9:37:f4:e8:9d:61:45:96:e1:8e:6c:78:58:e1:f6: + cf:46:8a:d6:a5:79:4d:47:88:ca:6c:69:4e:28:d4: + 8d:84:a8:e1:6c:1d:d3:36:7e:23:e3:64:d5:0a:a3: + fc:36:89:90:0a:ff:7e:8b:fa:2e:66:fb:c7:33:44: + 92:df:0f:43:b2:eb:24:7e:2b:ae:b0:43:a9:ad:53: + 82:f8:de:17:19:26:5f:ca:8c:ac:0c:1f:24:bd:15: + ed:4f:5d:82:ea:10:eb:05:70:4f:03:60:d9:23:6d: + 21:07:4d:12:9c:f3:64:ee:76:fb:9d:f9:c3:d8:1a: + 3b:6e:a9:82:7b:2d:2e:b0:74:b7:13:d6:65:8a:06: + f2:25:74:c2:26:e9:71:66:54:61:fe:2a:34:27:07: + c9:8d:ef:a0:a2:86:93:41:47:73:08:01:07:cc:4d: + ec:fe:80:88:93:fb:ae:b4:91:16:fa:83:96:84:66: + 53:cd:f3:52:da:d4:25:e1:09:15:20:e2:10:ea:dd: + 39:ef + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 4A:53:4A:B7:30:78:35:91:B4:CB:DD:C8:22:74:89:AF:80:0F:7F:68 + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:0 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 1a:93:21:25:ab:3a:1a:d6:18:60:81:26:16:9c:d6:4b:2f:62: + 3e:57:e2:e7:a8:59:77:fc:22:33:8b:0d:bd:14:79:80:cf:95: + 8a:d5:4f:3c:92:a0:eb:65:42:76:81:80:10:aa:03:21:ea:68: + 5d:72:98:ce:e3:01:65:f8:b2:1a:e8:8d:a9:d6:0a:2b:22:cf: + 11:22:fb:d0:7c:9f:d2:bb:04:4a:34:07:b4:4d:71:31:48:5b: + a0:08:83:ec:96:6d:5e:9a:fb:e3:da:63:32:b6:83:87:37:cb: + 67:dc:8e:7f:9d:a7:83:5c:13:bc:af:82:a0:9a:d2:b2:b7:1e: + 38:38:5c:e5:64:75:37:10:4a:82:a0:4d:f6:f8:5e:bf:36:f3: + 68:01:1a:0a:6b:e3:03:50:79:d6:14:da:26:48:d9:b6:8e:23: + 28:8a:a7:6e:c9:b0:54:c3:0b:48:25:7b:bf:e6:9f:be:f3:f0: + b9:1d:c2:30:11:e4:fc:5f:90:96:69:d9:c0:cd:89:89:58:51: + 43:8b:4c:d9:2a:d0:90:04:fc:db:21:32:c0:32:50:e4:4b:88: + 4c:42:9c:d5:2a:ba:30:6e:5e:49:87:a1:c7:03:9e:6c:45:cc: + bb:cf:d2:4a:af:1d:18:1c:9e:cb:66:50:e9:f9:b8:0b:08:bf: + 39:95:bb:62 +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA5WhcNMjIwNzA3MDAyODA5WjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluRi1JQ0Ey +LXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2joiZfhtHLcch90n9Nd1qnwcNzG0 +1qU0SzZA6lUIcqD/WOJdJhH1uG7e18O7JlHI0DYUAHZCTQNz74i5N/TonWFFluGO +bHhY4fbPRorWpXlNR4jKbGlOKNSNhKjhbB3TNn4j42TVCqP8NomQCv9+i/ouZvvH +M0SS3w9DsuskfiuusEOprVOC+N4XGSZfyoysDB8kvRXtT12C6hDrBXBPA2DZI20h +B00SnPNk7nb7nfnD2Bo7bqmCey0usHS3E9ZligbyJXTCJulxZlRh/io0JwfJje+g +ooaTQUdzCAEHzE3s/oCIk/uutJEW+oOWhGZTzfNS2tQl4QkVIOIQ6t057wIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFEpTSrcweDWRtMvdyCJ0ia+AD39oMIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQAwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQAakyElqzoa1hhggSYWnNZLL2I+V+LnqFl3/CIziw29FHmAz5WK1U88kqDr +ZUJ2gYAQqgMh6mhdcpjO4wFl+LIa6I2p1gorIs8RIvvQfJ/SuwRKNAe0TXExSFug +CIPslm1emvvj2mMytoOHN8tn3I5/naeDXBO8r4KgmtKytx44OFzlZHU3EEqCoE32 ++F6/NvNoARoKa+MDUHnWFNomSNm2jiMoiqduybBUwwtIJXu/5p++8/C5HcIwEeT8 +X5CWadnAzYmJWFFDi0zZKtCQBPzbITLAMlDkS4hMQpzVKrowbl5Jh6HHA55sRcy7 +z9JKrx0YHJ7LZlDp+bgLCL85lbti +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-assembled.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-assembled.pem new file mode 100644 index 000000000..14b0e0b25 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-assembled.pem @@ -0,0 +1,265 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainF-ICA1-pathlen1, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainF-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:c9:f8:2c:ad:25:a9:65:3b:72:13:5d:aa:7f:5b: + 71:f5:e0:43:c4:3a:b3:36:0d:34:61:35:86:77:a0: + 2a:81:de:2c:7c:7d:01:fb:f4:c3:00:b0:17:b9:49: + 93:1d:c2:1b:6f:40:ee:86:e0:a7:f3:5e:ad:23:43: + 99:5f:34:38:c8:58:02:9b:cc:9e:59:da:81:5b:b1: + 40:74:ca:c1:b8:67:14:ba:3f:71:16:d9:ba:a9:cd: + f1:96:1b:52:e2:d2:07:6d:6a:d6:cf:e7:a8:c8:e0: + 4f:eb:35:64:bc:aa:1a:17:af:98:de:d0:9b:08:73: + 72:d8:fe:e2:e5:4e:7e:97:37:37:58:9e:5c:65:91: + b9:5d:38:da:ba:db:00:c0:f6:4a:6f:9c:86:23:ad: + b0:c4:ff:b7:dd:d6:9a:b0:de:8d:15:87:e2:4b:04: + 85:6d:5d:cc:5f:65:6f:e1:ae:22:44:80:18:ba:c2: + 95:a4:a3:28:c5:3f:7b:4c:85:6c:0f:11:14:56:d2: + d5:a7:f7:03:e9:f7:ce:ef:d9:18:02:f0:f2:6e:81: + ef:ac:50:87:0e:b0:46:9f:ae:c0:77:8f:03:28:8a: + 9d:6e:87:50:8f:37:46:b3:29:57:a4:c2:ef:25:cd: + 23:1a:ef:1a:03:c9:59:69:cd:45:5f:39:3f:76:d4: + 79:53 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + E9:27:36:DA:64:81:70:89:C9:C1:F9:E3:92:7A:67:11:07:01:4A:49 + X509v3 Authority Key Identifier: + keyid:75:32:21:05:2B:60:FE:44:17:AF:18:65:86:85:19:82:3F:F9:64:83 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainF-ICA2-pathlen0/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 24:20:aa:3a:98:e1:d4:42:a1:0f:7b:58:10:83:72:da:d4:ed: + e2:e6:08:0d:d2:fb:c0:ff:5b:97:72:03:b1:20:fa:b1:88:60: + 29:af:44:64:82:51:44:75:a7:cb:90:0d:af:63:a3:93:6f:a8: + 12:18:16:60:2f:58:37:ec:be:23:64:1b:06:ad:a7:d6:fa:cf: + 34:06:3d:99:21:19:d4:27:24:19:a0:00:8a:28:80:7b:8a:48: + ea:61:63:20:4f:14:f2:60:a0:a3:3a:5a:45:4a:b1:24:1d:46: + 69:84:76:0e:ff:29:5b:4b:74:a2:75:2c:f1:4b:ba:dc:c5:4b: + dd:b3:52:b9:fd:45:8d:fd:71:68:78:71:f8:3e:7c:62:50:a2: + 8d:07:df:45:a7:39:9c:df:df:9d:78:de:a4:9e:ef:e6:0a:7a: + 53:42:0c:9e:7e:4a:bf:9c:70:66:a7:08:ab:bf:b5:f8:b3:3b: + 99:28:2c:73:f4:6f:da:4d:21:59:35:82:58:f4:5e:59:25:1e: + d6:7a:0a:c8:7f:4a:74:33:16:86:b4:bb:65:2e:9b:32:e5:78: + 53:95:33:38:a4:8a:04:36:eb:fa:51:d5:46:94:72:7d:d7:16: + c9:e7:e3:45:94:ab:ec:08:b6:87:e4:3a:34:7c:ca:dd:f9:27: + 65:21:c5:5f +-----BEGIN CERTIFICATE----- +MIIEtzCCA5+gAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluRi1JQ0ExLXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgZoxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRYwFAYDVQQD +DA1jaGFpbkYtZW50aXR5MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyfgsrSWpZTtyE12qf1tx +9eBDxDqzNg00YTWGd6Aqgd4sfH0B+/TDALAXuUmTHcIbb0DuhuCn816tI0OZXzQ4 +yFgCm8yeWdqBW7FAdMrBuGcUuj9xFtm6qc3xlhtS4tIHbWrWz+eoyOBP6zVkvKoa +F6+Y3tCbCHNy2P7i5U5+lzc3WJ5cZZG5XTjautsAwPZKb5yGI62wxP+33daasN6N +FYfiSwSFbV3MX2Vv4a4iRIAYusKVpKMoxT97TIVsDxEUVtLVp/cD6ffO79kYAvDy +boHvrFCHDrBGn67Ad48DKIqdbodQjzdGsylXpMLvJc0jGu8aA8lZac1FXzk/dtR5 +UwIDAQABo4H+MIH7MB0GA1UdDgQWBBTpJzbaZIFwicnB+eOSemcRBwFKSTCBzgYD +VR0jBIHGMIHDgBR1MiEFK2D+RBevGGWGhRmCP/lkg6GBp6SBpDCBoTELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNV +BAMMFGNoYWluRi1JQ0EyLXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tggFkMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBACQgqjqY +4dRCoQ97WBCDctrU7eLmCA3S+8D/W5dyA7Eg+rGIYCmvRGSCUUR1p8uQDa9jo5Nv +qBIYFmAvWDfsviNkGwatp9b6zzQGPZkhGdQnJBmgAIoogHuKSOphYyBPFPJgoKM6 +WkVKsSQdRmmEdg7/KVtLdKJ1LPFLutzFS92zUrn9RY39cWh4cfg+fGJQoo0H30Wn +OZzf35143qSe7+YKelNCDJ5+Sr+ccGanCKu/tfizO5koLHP0b9pNIVk1glj0Xlkl +HtZ6Csh/SnQzFoa0u2UumzLleFOVMzikigQ26/pR1UaUcn3XFsnn40WUq+wItofk +OjR8yt35J2UhxV8= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainF-ICA2-pathlen0, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainF-ICA1-pathlen1, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:e0:13:c9:b0:8e:9d:3f:88:d4:30:4a:b4:e8:11: + 21:93:5c:20:45:08:f8:7a:91:b9:2c:ad:ff:60:aa: + 16:9f:1c:bb:88:b8:3d:0a:39:c1:89:a9:76:ca:8e: + 6c:72:72:7e:6e:74:a6:36:2c:69:df:33:d6:e9:66: + 70:65:7f:ba:2a:44:17:62:9f:33:46:12:e6:03:a5: + a6:e2:5c:09:07:cf:bc:8d:76:fe:a0:fd:d7:72:4a: + 94:c8:ca:2f:95:91:9c:0a:77:7f:82:23:be:72:27: + 29:45:cd:41:cf:ec:e1:84:cf:67:d0:18:98:b9:31: + be:c9:fe:98:5d:3f:aa:d2:83:76:45:85:ab:08:86: + 63:58:5b:b3:e5:4a:43:3d:a1:99:e2:80:d1:2b:b2: + 06:e3:f0:10:85:f9:a6:36:b8:52:2b:9d:73:3b:34: + 23:51:3d:fe:56:2f:e9:39:b2:68:07:3e:6f:52:7b: + f4:40:d4:72:fa:69:19:ca:ff:22:c8:45:95:05:5e: + 91:08:3f:27:2d:41:d1:74:a5:06:9c:f3:40:bd:bb: + fc:65:63:86:ed:80:22:50:c1:f6:4f:dc:8f:43:4c: + 5e:fb:bf:d9:6d:1f:b4:84:0f:1e:e8:c6:5d:c5:53: + d5:2c:c9:7f:6b:98:93:a7:5d:35:9a:17:62:91:2e: + 20:c1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 75:32:21:05:2B:60:FE:44:17:AF:18:65:86:85:19:82:3F:F9:64:83 + X509v3 Authority Key Identifier: + keyid:4A:53:4A:B7:30:78:35:91:B4:CB:DD:C8:22:74:89:AF:80:0F:7F:68 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:1 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 6a:e9:07:00:56:3b:70:9a:2b:3d:42:e9:93:ad:76:a9:43:82: + a9:44:2a:35:a2:c7:56:d4:1e:cd:26:7c:d4:3f:49:19:3a:1e: + 88:ed:f7:3d:b5:88:65:41:b4:69:81:59:fd:bd:93:b3:5c:ba: + ae:60:b9:0b:e7:4b:60:a7:e4:b1:fa:ec:85:09:2b:e8:ff:84: + 77:71:75:63:c2:8a:10:51:76:7a:c9:6f:9a:a3:8b:10:b4:ed: + 9d:75:18:52:f5:a9:8a:ed:e0:0c:a4:23:96:f8:39:f6:fd:ce: + 58:21:54:2c:b1:a2:a1:73:eb:9f:93:99:0c:12:1e:9a:bb:3d: + 1e:91:da:df:b3:66:6a:cb:44:33:a8:d2:5d:31:76:d5:96:30: + 51:dd:d0:12:e9:7b:9b:9f:98:ac:35:03:0f:6f:2d:b5:b6:e1: + 30:14:50:31:2e:4c:fd:65:f5:d2:20:7b:8d:1d:a3:7f:6c:4f: + 47:d6:c8:97:26:cf:28:65:d8:a0:19:d1:ca:2e:e8:f7:11:cb: + ab:a6:32:2b:82:4d:c1:df:0a:c5:e5:9e:00:39:65:20:7e:55: + ad:81:ac:14:b1:f9:f3:88:96:94:26:e1:66:44:96:68:1b:1a: + 8d:db:f3:b9:e7:b8:9b:50:0b:03:19:53:70:c8:58:75:70:1f: + 0e:a4:bb:9f +-----BEGIN CERTIFICATE----- +MIIExjCCA66gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluRi1JQ0EyLXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgaExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR0wGwYDVQQD +DBRjaGFpbkYtSUNBMS1wYXRobGVuMTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm +c3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOATybCOnT+I +1DBKtOgRIZNcIEUI+HqRuSyt/2CqFp8cu4i4PQo5wYmpdsqObHJyfm50pjYsad8z +1ulmcGV/uipEF2KfM0YS5gOlpuJcCQfPvI12/qD913JKlMjKL5WRnAp3f4IjvnIn +KUXNQc/s4YTPZ9AYmLkxvsn+mF0/qtKDdkWFqwiGY1hbs+VKQz2hmeKA0SuyBuPw +EIX5pja4Uiudczs0I1E9/lYv6TmyaAc+b1J79EDUcvppGcr/IshFlQVekQg/Jy1B +0XSlBpzzQL27/GVjhu2AIlDB9k/cj0NMXvu/2W0ftIQPHujGXcVT1SzJf2uYk6dd +NZoXYpEuIMECAwEAAaOCAQUwggEBMB0GA1UdDgQWBBR1MiEFK2D+RBevGGWGhRmC +P/lkgzCBwQYDVR0jBIG5MIG2gBRKU0q3MHg1kbTL3cgidImvgA9/aKGBmqSBlzCB +lDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVt +YW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYD +VQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb22CAWQwDwYDVR0TBAgwBgEB/wIBATALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN +AQELBQADggEBAGrpBwBWO3CaKz1C6ZOtdqlDgqlEKjWix1bUHs0mfNQ/SRk6Hojt +9z21iGVBtGmBWf29k7Ncuq5guQvnS2Cn5LH67IUJK+j/hHdxdWPCihBRdnrJb5qj +ixC07Z11GFL1qYrt4AykI5b4Ofb9zlghVCyxoqFz65+TmQwSHpq7PR6R2t+zZmrL +RDOo0l0xdtWWMFHd0BLpe5ufmKw1Aw9vLbW24TAUUDEuTP1l9dIge40do39sT0fW +yJcmzyhl2KAZ0cou6PcRy6umMiuCTcHfCsXlngA5ZSB+Va2BrBSx+fOIlpQm4WZE +lmgbGo3b87nnuJtQCwMZU3DIWHVwHw6ku58= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainF-ICA2-pathlen0, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:da:3a:22:65:f8:6d:1c:b7:1c:87:dd:27:f4:d7: + 75:aa:7c:1c:37:31:b4:d6:a5:34:4b:36:40:ea:55: + 08:72:a0:ff:58:e2:5d:26:11:f5:b8:6e:de:d7:c3: + bb:26:51:c8:d0:36:14:00:76:42:4d:03:73:ef:88: + b9:37:f4:e8:9d:61:45:96:e1:8e:6c:78:58:e1:f6: + cf:46:8a:d6:a5:79:4d:47:88:ca:6c:69:4e:28:d4: + 8d:84:a8:e1:6c:1d:d3:36:7e:23:e3:64:d5:0a:a3: + fc:36:89:90:0a:ff:7e:8b:fa:2e:66:fb:c7:33:44: + 92:df:0f:43:b2:eb:24:7e:2b:ae:b0:43:a9:ad:53: + 82:f8:de:17:19:26:5f:ca:8c:ac:0c:1f:24:bd:15: + ed:4f:5d:82:ea:10:eb:05:70:4f:03:60:d9:23:6d: + 21:07:4d:12:9c:f3:64:ee:76:fb:9d:f9:c3:d8:1a: + 3b:6e:a9:82:7b:2d:2e:b0:74:b7:13:d6:65:8a:06: + f2:25:74:c2:26:e9:71:66:54:61:fe:2a:34:27:07: + c9:8d:ef:a0:a2:86:93:41:47:73:08:01:07:cc:4d: + ec:fe:80:88:93:fb:ae:b4:91:16:fa:83:96:84:66: + 53:cd:f3:52:da:d4:25:e1:09:15:20:e2:10:ea:dd: + 39:ef + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 4A:53:4A:B7:30:78:35:91:B4:CB:DD:C8:22:74:89:AF:80:0F:7F:68 + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:0 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 1a:93:21:25:ab:3a:1a:d6:18:60:81:26:16:9c:d6:4b:2f:62: + 3e:57:e2:e7:a8:59:77:fc:22:33:8b:0d:bd:14:79:80:cf:95: + 8a:d5:4f:3c:92:a0:eb:65:42:76:81:80:10:aa:03:21:ea:68: + 5d:72:98:ce:e3:01:65:f8:b2:1a:e8:8d:a9:d6:0a:2b:22:cf: + 11:22:fb:d0:7c:9f:d2:bb:04:4a:34:07:b4:4d:71:31:48:5b: + a0:08:83:ec:96:6d:5e:9a:fb:e3:da:63:32:b6:83:87:37:cb: + 67:dc:8e:7f:9d:a7:83:5c:13:bc:af:82:a0:9a:d2:b2:b7:1e: + 38:38:5c:e5:64:75:37:10:4a:82:a0:4d:f6:f8:5e:bf:36:f3: + 68:01:1a:0a:6b:e3:03:50:79:d6:14:da:26:48:d9:b6:8e:23: + 28:8a:a7:6e:c9:b0:54:c3:0b:48:25:7b:bf:e6:9f:be:f3:f0: + b9:1d:c2:30:11:e4:fc:5f:90:96:69:d9:c0:cd:89:89:58:51: + 43:8b:4c:d9:2a:d0:90:04:fc:db:21:32:c0:32:50:e4:4b:88: + 4c:42:9c:d5:2a:ba:30:6e:5e:49:87:a1:c7:03:9e:6c:45:cc: + bb:cf:d2:4a:af:1d:18:1c:9e:cb:66:50:e9:f9:b8:0b:08:bf: + 39:95:bb:62 +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA5WhcNMjIwNzA3MDAyODA5WjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluRi1JQ0Ey +LXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2joiZfhtHLcch90n9Nd1qnwcNzG0 +1qU0SzZA6lUIcqD/WOJdJhH1uG7e18O7JlHI0DYUAHZCTQNz74i5N/TonWFFluGO +bHhY4fbPRorWpXlNR4jKbGlOKNSNhKjhbB3TNn4j42TVCqP8NomQCv9+i/ouZvvH +M0SS3w9DsuskfiuusEOprVOC+N4XGSZfyoysDB8kvRXtT12C6hDrBXBPA2DZI20h +B00SnPNk7nb7nfnD2Bo7bqmCey0usHS3E9ZligbyJXTCJulxZlRh/io0JwfJje+g +ooaTQUdzCAEHzE3s/oCIk/uutJEW+oOWhGZTzfNS2tQl4QkVIOIQ6t057wIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFEpTSrcweDWRtMvdyCJ0ia+AD39oMIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQAwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQAakyElqzoa1hhggSYWnNZLL2I+V+LnqFl3/CIziw29FHmAz5WK1U88kqDr +ZUJ2gYAQqgMh6mhdcpjO4wFl+LIa6I2p1gorIs8RIvvQfJ/SuwRKNAe0TXExSFug +CIPslm1emvvj2mMytoOHN8tn3I5/naeDXBO8r4KgmtKytx44OFzlZHU3EEqCoE32 ++F6/NvNoARoKa+MDUHnWFNomSNm2jiMoiqduybBUwwtIJXu/5p++8/C5HcIwEeT8 +X5CWadnAzYmJWFFDi0zZKtCQBPzbITLAMlDkS4hMQpzVKrowbl5Jh6HHA55sRcy7 +z9JKrx0YHJ7LZlDp+bgLCL85lbti +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-entity-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-entity-key.pem new file mode 100644 index 000000000..6c7d78071 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-entity-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAyfgsrSWpZTtyE12qf1tx9eBDxDqzNg00YTWGd6Aqgd4sfH0B ++/TDALAXuUmTHcIbb0DuhuCn816tI0OZXzQ4yFgCm8yeWdqBW7FAdMrBuGcUuj9x +Ftm6qc3xlhtS4tIHbWrWz+eoyOBP6zVkvKoaF6+Y3tCbCHNy2P7i5U5+lzc3WJ5c +ZZG5XTjautsAwPZKb5yGI62wxP+33daasN6NFYfiSwSFbV3MX2Vv4a4iRIAYusKV +pKMoxT97TIVsDxEUVtLVp/cD6ffO79kYAvDyboHvrFCHDrBGn67Ad48DKIqdbodQ +jzdGsylXpMLvJc0jGu8aA8lZac1FXzk/dtR5UwIDAQABAoIBAEnbhYr0ANRSPs8y +K41TRYNitaVmye50Oblqt3e7jI/dTWtg037t7Pmta5+IdlIlj57JofCU6xYmgy4o +JEgacsFg3eNXmnjFXRTI5wdOtjTXDU9mr9ZpXMeH1lbMOy1THQA4V8HDt4dt8AvV +hLcxhUUwI7knk+otPcx4uUSdxdFJ6uAGsBOqHRQNvZ+UQKWPu4wcbhOyIhPAVHmg +jc4mRSixY48rWCjfHu4eL4vIVotaqHMKl1p5Z/i9umEMnJu9i4Nw7ZfWFlPUcg3B +oC/2AsQZ7O2PNy1fMW15da1RZ7aXedMersHb7sX9ZTd9vqIUXVdXSHc9N13zd9pS +GjHGgtECgYEA+XhITJiF82ldFOBamngzBCYy7BHq5ZJKaUcOSTrVDIG2CVi4tXEw +FE1Y1d4aelLkDzR3Qo17YAVpMFkp8AnMAb6+89JON1TOq+hyrMeQpjo8KV9P+O29 +5Tg2KZSxp5io33ENX0QncI7TtIIMSNfxDFw7b4hgjkcIp2Ii3QtxjaUCgYEAz0GW +g7zJSCP7X4H+VeZ8drg/QdYci23RJC7GBFozFUzt8BlA8g7FyYheyn0COwObL0xz +rRrzNB8JVv3LJ9ggfBksVRq7NnufeJaEq5rZFGa52nk5KS3ukbi1FCzmO+E+OIEH +KEGGvVF5WCPQaa0WhkQcXvo/mRb83p2ipv94qZcCgYEAg0Lhr8O0/11aB6kAozRJ +i45ZztKiqMZvdrNXdfqJrPn3ATX4giebJ6OG8Yjan7BLpSBy+8abuus97J2NrmpJ +OEXYDUyDsSNjVxqIdBbRKlWL4CzxVEYrW5dXEEvXqhpuCJtgcNbYdaYBCIJA2ncc +suc4sresLlB74i6Fr47c4a0CgYEAm6eipyXt9aQwcjZrEZCdAXy25Xcs0PqVDBuk +1Df6DZFNUfllcWXu3cDxkBn6xt+aeRdt+SA4b3ivxwmsvivvmcQ+K1x8JhsKVcKV +uVv+lPfhtVc9utOoTQDv3ksqTuaHmGAvQ+iSjTTXcX7UU8mPFR+qPxqrEQrWt0qk +kc9ki9kCgYBxdSt1rwvIEHnQUeRPQqFcIcMhjSDhHArzqnOo2EZkZBcB5U6qcjZH +EBgZKOcNVIBMlmjVHJIAQz8rog8zv0xZjW0W9ijzV93zUq2K0p9uDhDkpFhpNa+0 +UStzpcOI+NZMbwlxYcgAAjOBapsvriqzSeGq93BmW9B6mu5fTet6/w== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-entity.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-entity.pem new file mode 100644 index 000000000..27bd2dcd7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainF-entity.pem @@ -0,0 +1,87 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainF-ICA1-pathlen1, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainF-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:c9:f8:2c:ad:25:a9:65:3b:72:13:5d:aa:7f:5b: + 71:f5:e0:43:c4:3a:b3:36:0d:34:61:35:86:77:a0: + 2a:81:de:2c:7c:7d:01:fb:f4:c3:00:b0:17:b9:49: + 93:1d:c2:1b:6f:40:ee:86:e0:a7:f3:5e:ad:23:43: + 99:5f:34:38:c8:58:02:9b:cc:9e:59:da:81:5b:b1: + 40:74:ca:c1:b8:67:14:ba:3f:71:16:d9:ba:a9:cd: + f1:96:1b:52:e2:d2:07:6d:6a:d6:cf:e7:a8:c8:e0: + 4f:eb:35:64:bc:aa:1a:17:af:98:de:d0:9b:08:73: + 72:d8:fe:e2:e5:4e:7e:97:37:37:58:9e:5c:65:91: + b9:5d:38:da:ba:db:00:c0:f6:4a:6f:9c:86:23:ad: + b0:c4:ff:b7:dd:d6:9a:b0:de:8d:15:87:e2:4b:04: + 85:6d:5d:cc:5f:65:6f:e1:ae:22:44:80:18:ba:c2: + 95:a4:a3:28:c5:3f:7b:4c:85:6c:0f:11:14:56:d2: + d5:a7:f7:03:e9:f7:ce:ef:d9:18:02:f0:f2:6e:81: + ef:ac:50:87:0e:b0:46:9f:ae:c0:77:8f:03:28:8a: + 9d:6e:87:50:8f:37:46:b3:29:57:a4:c2:ef:25:cd: + 23:1a:ef:1a:03:c9:59:69:cd:45:5f:39:3f:76:d4: + 79:53 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + E9:27:36:DA:64:81:70:89:C9:C1:F9:E3:92:7A:67:11:07:01:4A:49 + X509v3 Authority Key Identifier: + keyid:75:32:21:05:2B:60:FE:44:17:AF:18:65:86:85:19:82:3F:F9:64:83 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainF-ICA2-pathlen0/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 24:20:aa:3a:98:e1:d4:42:a1:0f:7b:58:10:83:72:da:d4:ed: + e2:e6:08:0d:d2:fb:c0:ff:5b:97:72:03:b1:20:fa:b1:88:60: + 29:af:44:64:82:51:44:75:a7:cb:90:0d:af:63:a3:93:6f:a8: + 12:18:16:60:2f:58:37:ec:be:23:64:1b:06:ad:a7:d6:fa:cf: + 34:06:3d:99:21:19:d4:27:24:19:a0:00:8a:28:80:7b:8a:48: + ea:61:63:20:4f:14:f2:60:a0:a3:3a:5a:45:4a:b1:24:1d:46: + 69:84:76:0e:ff:29:5b:4b:74:a2:75:2c:f1:4b:ba:dc:c5:4b: + dd:b3:52:b9:fd:45:8d:fd:71:68:78:71:f8:3e:7c:62:50:a2: + 8d:07:df:45:a7:39:9c:df:df:9d:78:de:a4:9e:ef:e6:0a:7a: + 53:42:0c:9e:7e:4a:bf:9c:70:66:a7:08:ab:bf:b5:f8:b3:3b: + 99:28:2c:73:f4:6f:da:4d:21:59:35:82:58:f4:5e:59:25:1e: + d6:7a:0a:c8:7f:4a:74:33:16:86:b4:bb:65:2e:9b:32:e5:78: + 53:95:33:38:a4:8a:04:36:eb:fa:51:d5:46:94:72:7d:d7:16: + c9:e7:e3:45:94:ab:ec:08:b6:87:e4:3a:34:7c:ca:dd:f9:27: + 65:21:c5:5f +-----BEGIN CERTIFICATE----- +MIIEtzCCA5+gAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluRi1JQ0ExLXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgZoxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRYwFAYDVQQD +DA1jaGFpbkYtZW50aXR5MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyfgsrSWpZTtyE12qf1tx +9eBDxDqzNg00YTWGd6Aqgd4sfH0B+/TDALAXuUmTHcIbb0DuhuCn816tI0OZXzQ4 +yFgCm8yeWdqBW7FAdMrBuGcUuj9xFtm6qc3xlhtS4tIHbWrWz+eoyOBP6zVkvKoa +F6+Y3tCbCHNy2P7i5U5+lzc3WJ5cZZG5XTjautsAwPZKb5yGI62wxP+33daasN6N +FYfiSwSFbV3MX2Vv4a4iRIAYusKVpKMoxT97TIVsDxEUVtLVp/cD6ffO79kYAvDy +boHvrFCHDrBGn67Ad48DKIqdbodQjzdGsylXpMLvJc0jGu8aA8lZac1FXzk/dtR5 +UwIDAQABo4H+MIH7MB0GA1UdDgQWBBTpJzbaZIFwicnB+eOSemcRBwFKSTCBzgYD +VR0jBIHGMIHDgBR1MiEFK2D+RBevGGWGhRmCP/lkg6GBp6SBpDCBoTELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNV +BAMMFGNoYWluRi1JQ0EyLXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tggFkMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBACQgqjqY +4dRCoQ97WBCDctrU7eLmCA3S+8D/W5dyA7Eg+rGIYCmvRGSCUUR1p8uQDa9jo5Nv +qBIYFmAvWDfsviNkGwatp9b6zzQGPZkhGdQnJBmgAIoogHuKSOphYyBPFPJgoKM6 +WkVKsSQdRmmEdg7/KVtLdKJ1LPFLutzFS92zUrn9RY39cWh4cfg+fGJQoo0H30Wn +OZzf35143qSe7+YKelNCDJ5+Sr+ccGanCKu/tfizO5koLHP0b9pNIVk1glj0Xlkl +HtZ6Csh/SnQzFoa0u2UumzLleFOVMzikigQ26/pR1UaUcn3XFsnn40WUq+wItofk +OjR8yt35J2UhxV8= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA1-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA1-key.pem new file mode 100644 index 000000000..dd86a5a55 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA1-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA0ia+UZhC4B+u/MLLutUPRDsLYNhJ7ANDawbO8igZ+0icC1x/ +AKMin7zpKlvk4RbYnLnDCzDjHIN9wLmkP9o47Is4vkXEpx3BaBgoGbDykwY6vSNn +qgWJMTvCtF6zEss785zW30zty0IbJYAtq8Rnj6X/2mzxGP2hmIzYH2dsKMfLTruw +J+olsV1z0CrpRFC59WVk5s89ktjAbe2WjuLThHDQ2/5wY0T6+Ns10ZWtGJUhZM7i +I35ebC/vp2P+gkrLzCPPnSalZu2cBn5wdgNymdv6vqXDOItAJMFr15y7J4YiqWLg +sr3nteSB6mTbGBYkYoFsqPKDP687tf2w2ISyIQIDAQABAoIBAFOyFHhAsNm8JKAM +IMGPG15sOZLfcUlq303fz0nISNi4SVWJCBfD4QVHYoF5ScWPqMN6hECPvtPbVpkM +FmtLyQIETJwTA0gfZKjFfisFOwbtIzWyxRWE0Ofnyhq14JHqmTzjyPv0EnyyHkeo +LghL14bxcN2YJ8lxMgukhGq1cPEoL7Te9MorQ3pgI2CV5iR8iriXp50RS2xyCO8L +3TL4/tkZ2/RF7+9KNDP5ViYJOmfU9bOxLT7gxIAjjL8uCDk/r1RgT03+jLpoEZSi +o1Sa06fogqV02Y7bkJLXtu5jxAeIcWG0iF6FdC291TcQaM7hv4HwLuxZnxJcgc4I +AxnOuAECgYEA/prt+B7DQ2qWyrATnMP3ScKAMQ3yuE8K7z/u533eZ1TTCmueKjbg +4pmMVCt+E3pSB5WbzTdAx4Gm5ACHkobJnmRb7Y2gjaD27W4Vn+jd/+U3GbHNQDIa +srSxkTBjQakSckqI/KucYAcF+MtXPAeXJp/IklXDxFoGpcwaisMlSuECgYEA0014 +PDe4Ujglay4utpxkyL6d/nlzFseZn+7BJ9ClJiBKCJBF3mlqVArxmwv5fCn+be05 +Ikfljvt7sCUzYseccCYKe5zPa6v7622ERIn8jkTUo43Tm47WzBZsXasNeLdYAu7p +pEjn0AP7w5kRruHI3xqOZScXDhtrrQuogU9Zj0ECgYBWshLOJkt/LVBjfElxXBlc +eGqGSaWYtPGYPkDveqC8ttmV9sdIwJ8bCgYKszSfFUvRYVRIMMRSKwfVI4kGj/cf +hDT5UvyUvXbXqmCarwTJGhgFG9I0RdtpdrXwJnXl6dhqKo8y2ozI9htGeJcfzcXe +VRJLIgEjXzRcSH/ROFn+gQKBgEr/WyacbEqabQWOvbvI5Kivp2oz9xplu+wdFOep +0YQnv78sXfAkID42KCzs4h8k1I51vWqidCL8tZj+iy+LQ8Y2alAXhzNjNqYIGAMv +qrlgSszGQQ4cc7a6WrogRUbMZGueGsVZrxWQ5GI3SSR2NRKi3Vmftzoll2EzGxrS +bCpBAoGBAI/msQiuFLzbbxbtOLmjbh4iptOM8kJY2PpxZAKIxUqwEuOuoF6yY6G7 +jN0QBoN8RtP2syWpoY8G4YqX/zNWOOuL7p/uWRiatGrAc/qUWjNB8yO5Z/LVkOEU +QOcdeEvBUkgVc0qSkDgAAQ0Vktoba4X+Xc6MsD8F3xTJQOe5oToP +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA1-pathlen0.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA1-pathlen0.pem new file mode 100644 index 000000000..ad1f9456c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA1-pathlen0.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA2-pathlen1, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA1-pathlen0, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d2:26:be:51:98:42:e0:1f:ae:fc:c2:cb:ba:d5: + 0f:44:3b:0b:60:d8:49:ec:03:43:6b:06:ce:f2:28: + 19:fb:48:9c:0b:5c:7f:00:a3:22:9f:bc:e9:2a:5b: + e4:e1:16:d8:9c:b9:c3:0b:30:e3:1c:83:7d:c0:b9: + a4:3f:da:38:ec:8b:38:be:45:c4:a7:1d:c1:68:18: + 28:19:b0:f2:93:06:3a:bd:23:67:aa:05:89:31:3b: + c2:b4:5e:b3:12:cb:3b:f3:9c:d6:df:4c:ed:cb:42: + 1b:25:80:2d:ab:c4:67:8f:a5:ff:da:6c:f1:18:fd: + a1:98:8c:d8:1f:67:6c:28:c7:cb:4e:bb:b0:27:ea: + 25:b1:5d:73:d0:2a:e9:44:50:b9:f5:65:64:e6:cf: + 3d:92:d8:c0:6d:ed:96:8e:e2:d3:84:70:d0:db:fe: + 70:63:44:fa:f8:db:35:d1:95:ad:18:95:21:64:ce: + e2:23:7e:5e:6c:2f:ef:a7:63:fe:82:4a:cb:cc:23: + cf:9d:26:a5:66:ed:9c:06:7e:70:76:03:72:99:db: + fa:be:a5:c3:38:8b:40:24:c1:6b:d7:9c:bb:27:86: + 22:a9:62:e0:b2:bd:e7:b5:e4:81:ea:64:db:18:16: + 24:62:81:6c:a8:f2:83:3f:af:3b:b5:fd:b0:d8:84: + b2:21 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 47:C0:19:4B:ED:C4:DA:97:B1:60:EA:5A:0A:42:6D:A5:D3:D8:25:31 + X509v3 Authority Key Identifier: + keyid:E1:E6:9B:28:CF:FD:AB:45:C1:B7:A7:C4:C9:58:FC:41:E3:1A:5C:74 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainG-ICA3-pathlen99/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:0 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 56:81:8e:f1:e8:5f:b2:9f:ab:8f:2e:ec:79:c7:3d:0d:af:f2: + 18:f7:d2:2e:07:2c:d0:1d:2a:90:c7:c1:fc:ac:aa:0d:86:f0: + 78:6d:33:43:81:02:70:3b:e6:d9:75:db:2e:ca:4a:61:4d:20: + cb:a9:3e:0c:a9:b3:ca:ff:bb:52:cb:06:14:2d:53:b5:68:9f: + a7:02:83:90:3d:f8:b6:a2:46:e4:2b:c5:48:ed:50:7f:ea:27: + cf:7b:9d:88:1f:1c:5d:16:b7:21:0a:42:95:0b:67:6c:29:34: + 64:61:c0:f5:00:6f:36:dc:e9:68:e3:81:bd:07:a6:bc:6c:9d: + f0:61:b0:50:14:d5:89:46:1f:34:b0:90:42:a0:c3:09:64:6e: + a4:46:13:c6:6a:86:98:63:c7:8e:79:d3:a2:d6:73:23:68:a9: + 8d:ac:b0:93:b0:89:f5:ee:08:cc:47:14:95:3b:1f:d3:eb:42: + 3f:68:b8:6b:80:11:8d:85:8c:90:39:29:e8:5d:7d:e5:c1:c2: + 5c:e7:92:8c:ab:79:17:74:60:a5:ee:fe:52:ff:4a:78:62:5c: + 1b:4b:f8:44:41:8c:05:c7:11:e7:5a:c9:a1:a1:d3:6b:82:36: + c3:1f:23:19:ce:68:9d:c3:80:d5:08:8d:68:d2:49:52:95:44: + 3f:1b:50:9d +-----BEGIN CERTIFICATE----- +MIIE1DCCA7ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluRy1JQ0EyLXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgaExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR0wGwYDVQQD +DBRjaGFpbkctSUNBMS1wYXRobGVuMDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm +c3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANImvlGYQuAf +rvzCy7rVD0Q7C2DYSewDQ2sGzvIoGftInAtcfwCjIp+86Spb5OEW2Jy5wwsw4xyD +fcC5pD/aOOyLOL5FxKcdwWgYKBmw8pMGOr0jZ6oFiTE7wrResxLLO/Oc1t9M7ctC +GyWALavEZ4+l/9ps8Rj9oZiM2B9nbCjHy067sCfqJbFdc9Aq6URQufVlZObPPZLY +wG3tlo7i04Rw0Nv+cGNE+vjbNdGVrRiVIWTO4iN+Xmwv76dj/oJKy8wjz50mpWbt +nAZ+cHYDcpnb+r6lwziLQCTBa9ecuyeGIqli4LK957Xkgepk2xgWJGKBbKjygz+v +O7X9sNiEsiECAwEAAaOCARMwggEPMB0GA1UdDgQWBBRHwBlL7cTal7Fg6loKQm2l +09glMTCBzwYDVR0jBIHHMIHEgBTh5psoz/2rRcG3p8TJWPxB4xpcdKGBqKSBpTCB +ojELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1Nl +YXR0bGUxFTATBgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJp +bmcxHjAcBgNVBAMMFWNoYWluRy1JQ0EzLXBhdGhsZW45OTEfMB0GCSqGSIb3DQEJ +ARYQaW5mb0B3b2xmc3NsLmNvbYIBZDAPBgNVHRMECDAGAQH/AgEAMAsGA1UdDwQE +AwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAVoGO8ehfsp+rjy7secc9Da/yGPfSLgcs +0B0qkMfB/KyqDYbweG0zQ4ECcDvm2XXbLspKYU0gy6k+DKmzyv+7UssGFC1TtWif +pwKDkD34tqJG5CvFSO1Qf+onz3udiB8cXRa3IQpClQtnbCk0ZGHA9QBvNtzpaOOB +vQemvGyd8GGwUBTViUYfNLCQQqDDCWRupEYTxmqGmGPHjnnTotZzI2ipjaywk7CJ +9e4IzEcUlTsf0+tCP2i4a4ARjYWMkDkp6F195cHCXOeSjKt5F3Rgpe7+Uv9KeGJc +G0v4REGMBccR51rJoaHTa4I2wx8jGc5oncOA1QiNaNJJUpVEPxtQnQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA2-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA2-key.pem new file mode 100644 index 000000000..c0558a0d3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA2-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA1z7eufmp1456S/LxjPk7HM5ZMUxXDC6KD5Dw3CdVCxDDoui5 +OXUX0Z2ZQ5Sy8VZ2a7lGprg1laHS0OyOvpXceBcKQaEj38uyh8suHQJ9xP569nrY +pY21ERrka9JmAQEDpzuVSZJdwcdJ8BrvAHE3mVqHCkDeVQ5oidznoRS/nXKTfkgp +5OqmTwp6paE5bCGEOo/KejULCs0SZzxWBvWdJMmOSoIjyDh/rJi2slfcgmKEABN7 +6nOAJkqbwbQK8fz/RliWoCGhyY/ZmXRBC9BtMaerh5J2UULviJXMLPKbzNUpoPeq +a+GrMhbNVcQVgGmAkdh4LAcV/cICpPQTdVC4KwIDAQABAoIBAQCeaP6yEDQXGByZ +WKq8/Y+rm5G43l4R8Q5admlNHQVRp3zToELxLmPhOQNa4UzwoJl2nlyIxnlpLjdg +2zgSu2gOWaaKtnUYd2lk1vuRDgxRtpf4XmCjNq9Tb188mxPHGV/+67Lq+nVV771S +n//Va31nt2A7A5KdNoVpMNKnkgWTcS3dJ07znTsHbabcttA58mu2DPXaNVUKystz ++0YF1I/Lp+3tWGfSM2MKqQTaFy219N+xhUtIj2/TOo55Kkz8lAGyctrIfFZZPUY6 +I1YIzxFlC8XNd1DzW2i7qVANM0vzuB85nv8D5RREbBjJ/IHwJgjWp3G2K8o8+kDZ +ZOukmpzBAoGBAO4t4l3rVSaBbmP5F0U/JdZSqoUmGNggkGcyR3vpNT+ZEzhyzJ7d +A1fqzdrrbxXXGVHAqDdEb/tKAuUZmv52OdKlL76ylje1DdDsvw+zzZXYTSz4nMo1 +9jIBXskDeypu4w5zE3WY4FxaDMVbpcJW3fQ1u3aLSCswmOlyKrH3t90PAoGBAOdZ +tjJrOyYD1FELv/BD5fOVInq/3EGFZFZKXSBtLtzYDzLebUPPwrGjwCkq7VIK8BUK +8+IxGlx3KrQL9omUrpb2DuoKjOgeVvsXEL0a1uykkVbkk8O+VBtfdcsJLZimJqhl +kVxXKnPHAp1+cVDt+MvbdCKiE0kwaVqnkUM1H+slAoGASiHB6RWMJTX30+n9kjH7 +Zt/H7zVSWkKYb2Y41ZpaVncggltI0NFdbwnIFLFem9+dI9LhCIKmkAITMJdtpHHL +wYJkf+g51RDnQfXN6ec+v7rZGnwu4Mk23Y2LoOkSdryYszCiB+ITQutMOkkyKHC9 +GHt444aqabbwgQhlvYqqkYUCgYA3/1/5bjkf53dhsp1f0596SRPScFQoy9fQhylp +auQX8ngjUPFTo5s1kjQ2Arz0yc742PDVRBtkXDfK4sZm4MUtpxtPDQS0PnvBRQD5 +NODm4KKJTMRzccM76OxDG9Kci0L6KbN4jWSqJ3Z7lpppA2DgPxsqMt7GLWCi38Jq +aRZzvQKBgFbcHMmGAjgszC+ZSMZP3EhNwMQLAdeCVoEqfZAItO6q2NwB54YhYK9l +nvYieUYGRvFc+jdbyfqPG98BZXcgt2PuB17gA8jdajCZJFeQtCo1GKwWkSYB/2MF +jOJmAGkTZ40jffKgngJKQ8Zs360vjhvPYr51Gr0pZ1/8NT4/yueZ +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA2-pathlen1.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA2-pathlen1.pem new file mode 100644 index 000000000..1592a0143 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA2-pathlen1.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA3-pathlen99, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA2-pathlen1, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d7:3e:de:b9:f9:a9:d7:8e:7a:4b:f2:f1:8c:f9: + 3b:1c:ce:59:31:4c:57:0c:2e:8a:0f:90:f0:dc:27: + 55:0b:10:c3:a2:e8:b9:39:75:17:d1:9d:99:43:94: + b2:f1:56:76:6b:b9:46:a6:b8:35:95:a1:d2:d0:ec: + 8e:be:95:dc:78:17:0a:41:a1:23:df:cb:b2:87:cb: + 2e:1d:02:7d:c4:fe:7a:f6:7a:d8:a5:8d:b5:11:1a: + e4:6b:d2:66:01:01:03:a7:3b:95:49:92:5d:c1:c7: + 49:f0:1a:ef:00:71:37:99:5a:87:0a:40:de:55:0e: + 68:89:dc:e7:a1:14:bf:9d:72:93:7e:48:29:e4:ea: + a6:4f:0a:7a:a5:a1:39:6c:21:84:3a:8f:ca:7a:35: + 0b:0a:cd:12:67:3c:56:06:f5:9d:24:c9:8e:4a:82: + 23:c8:38:7f:ac:98:b6:b2:57:dc:82:62:84:00:13: + 7b:ea:73:80:26:4a:9b:c1:b4:0a:f1:fc:ff:46:58: + 96:a0:21:a1:c9:8f:d9:99:74:41:0b:d0:6d:31:a7: + ab:87:92:76:51:42:ef:88:95:cc:2c:f2:9b:cc:d5: + 29:a0:f7:aa:6b:e1:ab:32:16:cd:55:c4:15:80:69: + 80:91:d8:78:2c:07:15:fd:c2:02:a4:f4:13:75:50: + b8:2b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + E1:E6:9B:28:CF:FD:AB:45:C1:B7:A7:C4:C9:58:FC:41:E3:1A:5C:74 + X509v3 Authority Key Identifier: + keyid:C1:CD:1F:81:13:82:24:3B:CF:64:51:7A:4C:E3:65:2E:75:1E:01:23 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainG-ICA4-pathlen5/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:1 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 3b:e4:43:62:32:48:75:cf:da:f6:fa:38:4f:1b:b2:25:84:5b: + 79:8f:ce:9c:19:10:ef:ab:b4:b5:f0:2b:d1:16:77:f6:cc:f6: + 43:c7:1f:ca:92:f9:d7:69:3c:82:02:02:19:55:a4:a1:d0:1c: + 7c:e8:b8:8f:4c:7b:42:6c:68:0d:0c:b0:05:ad:39:29:7c:45: + 8e:e2:b3:54:e7:98:84:95:21:3d:73:26:33:5e:5b:59:59:f2: + 03:13:28:86:e1:2c:da:a8:37:7e:2e:93:5e:e1:41:9c:6d:03: + 16:0f:8a:b2:4d:67:b6:1b:65:8a:cb:30:b5:ed:ad:e7:9f:81: + 21:a7:6d:39:f7:af:93:82:1c:89:55:ae:0d:e8:88:be:a5:27: + 60:56:7b:f3:5c:1d:57:49:36:c2:9f:cc:50:62:a7:82:54:61: + 36:10:01:2f:cf:85:b2:dd:d7:56:cc:18:7e:85:5d:f1:b7:b7: + b6:c3:04:6b:01:5e:b8:68:28:9a:6b:fc:83:33:b7:28:64:55: + 38:ee:a4:5a:d5:87:ef:89:07:c4:60:9d:8a:25:d5:71:94:5b: + 96:3f:a4:3f:1d:80:3e:ef:97:9e:c4:25:f1:82:01:27:40:27: + cc:61:e6:67:e0:58:33:e9:9f:35:65:89:40:17:6a:a7:6c:d9: + 70:2c:59:a1 +-----BEGIN CERTIFICATE----- +MIIE1DCCA7ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBojELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHjAcBgNVBAMMFWNo +YWluRy1JQ0EzLXBhdGhsZW45OTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns +LmNvbTAeFw0xOTEwMTEwMDI4MDlaFw0yMjA3MDcwMDI4MDlaMIGhMQswCQYDVQQG +EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEVMBMG +A1UECgwMd29sZlNTTCBJbmMuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEdMBsGA1UE +AwwUY2hhaW5HLUlDQTItcGF0aGxlbjExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s +ZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXPt65+anX +jnpL8vGM+TsczlkxTFcMLooPkPDcJ1ULEMOi6Lk5dRfRnZlDlLLxVnZruUamuDWV +odLQ7I6+ldx4FwpBoSPfy7KHyy4dAn3E/nr2etiljbURGuRr0mYBAQOnO5VJkl3B +x0nwGu8AcTeZWocKQN5VDmiJ3OehFL+dcpN+SCnk6qZPCnqloTlsIYQ6j8p6NQsK +zRJnPFYG9Z0kyY5KgiPIOH+smLayV9yCYoQAE3vqc4AmSpvBtArx/P9GWJagIaHJ +j9mZdEEL0G0xp6uHknZRQu+Ilcws8pvM1Smg96pr4asyFs1VxBWAaYCR2HgsBxX9 +wgKk9BN1ULgrAgMBAAGjggESMIIBDjAdBgNVHQ4EFgQU4eabKM/9q0XBt6fEyVj8 +QeMaXHQwgc4GA1UdIwSBxjCBw4AUwc0fgROCJDvPZFF6TONlLnUeASOhgaekgaQw +gaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdT +ZWF0dGxlMRUwEwYDVQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVy +aW5nMR0wGwYDVQQDDBRjaGFpbkctSUNBNC1wYXRobGVuNTEfMB0GCSqGSIb3DQEJ +ARYQaW5mb0B3b2xmc3NsLmNvbYIBZDAPBgNVHRMECDAGAQH/AgEBMAsGA1UdDwQE +AwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAO+RDYjJIdc/a9vo4TxuyJYRbeY/OnBkQ +76u0tfAr0RZ39sz2Q8cfypL512k8ggICGVWkodAcfOi4j0x7QmxoDQywBa05KXxF +juKzVOeYhJUhPXMmM15bWVnyAxMohuEs2qg3fi6TXuFBnG0DFg+Ksk1nthtlissw +te2t55+BIadtOfevk4IciVWuDeiIvqUnYFZ781wdV0k2wp/MUGKnglRhNhABL8+F +st3XVswYfoVd8be3tsMEawFeuGgommv8gzO3KGRVOO6kWtWH74kHxGCdiiXVcZRb +lj+kPx2APu+XnsQl8YIBJ0AnzGHmZ+BYM+mfNWWJQBdqp2zZcCxZoQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA3-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA3-key.pem new file mode 100644 index 000000000..357c8f061 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA3-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEArPE5Zfecnfbw0rcYFiSBMrelKdb3TjE4p1TW6weXJ6GS4ME6 +tZMGF++ndPibQpcM1tPUNslh75JMPsR0CNYZKs2b8W/oyGefKFSZzmMah1aZNjFl +BcXWl89R5C09dBQx08MF/A58k1fN98SX11xldec1hYEn65qf16K8KEGozpI6ELk1 +KIPcsCfMbiADYBMjIrQ8JViuobIk0SGLufAohK7mAMzLm3iM+kvtc3qRBfn7bjQ7 +fq/5RZ6g1WK72M2VnqKQcifgPrmwXgqy5FWVAwymZkRl2wqfkFrTgcfiPvKwmuAF +HN5kBMJ+yn7fofYY5ZTTdPulHy13zW5eVaOAywIDAQABAoIBAQCTPWlF9DPGlbjh +XftG1tucx5f58EhrrSJz7JpyTesWVczMSBdpAfzdIjArOYJOhnXq7TyvTHNyWddK +VU4JO+b/d0B+pW3GOdrapnSwr9WlRkh5SEKfUJnsdBlfsFiy3IKzrUYKHHdZpxb4 +DMvOEp9ba3c47AaF5AaUu7uAdq5298erL6/viPCwbT5am1U+d3tDGdj9PYPRlzIa +o7QenU8tZcfW+m/6Ogut3kpFQtXRpmzS2ArtG0uAkS6oVzDrDvGu908VvbTyAZ/f +PsYNK972RxO5QEBGsrSl5AQaeoOKOonUa0TWjKq0Q/wWkRZXdNQjKCQll96Izie4 +Ij4pYCh5AoGBANo9u4jDu5HT70U489e585NmAsNWejeQjB8GvLkSXoWqnVO0Dl/p +VsMVwK2hQaD6D4UKHY+3f/Ino3/5nShCgaRZDIOD7ZMW0kqCJOJUNTkDZfigJhfd ++zuQ2fytT4gcvJAwF1vjRril156yQY74k6xMJR2Xm1Px47s2fWYXM9z/AoGBAMrd +IP8Pce4qfSTDK3ukhffdcmiaR0GR2R+gcQYMbkuWmMj9lbKAFKrPHP40bepn1Pqf +SfZE5kIXuWv1QlfROfCqpub3/yYiv7dgKfgOqS8ThZSdtiFcVfsd6huPuXFcDYDw +4O0VTZzEbNb4mXUgBGTPFCUlEIoQ1ZU7Xk1EWUA1AoGAKOBVJsmacTbj4vBG48oF +cD80F0g0PgIJ7KnDYVqqb5jEPPBFnPtEb+e8HglNFIyhqYZ6gPeatE1uV0L2h5rl +U1YGfP+R2PH2U1RK+kVRbqtPRyEf4WqHauG3opcHhXP0cYFAbsqD7YPKfgPfOZsf +da8RaJiD1FZDFEaheCSyZxsCgYBYFtF/MAu+6cBRuFYnaHer/AL0HRoYBOcNbrPl +dnxmYkyR6luYmTlgOnNShx27jb7T3VtWjvCVfovLr0JRs86/DLtQzBuFSc2KKT3Q +Mz2P7aAxupIdxmSnmIPR2AUkjl5mwTJKgNek3T6N0oGAdJiz1Z/fyUp3SXwVQyRd +1PIUiQKBgG+HlGVGmDTssZYpPMsf/qeFD/mzTfnjZJwoxYK+qCKsiwjg9KQPNg+N +ET+Ou3rnIhjJGB8d82TuXzIvlpRVIw7WaPQDTIsTNC2x8W7CURkSTyAzefOpz4tK +wziwYJTC9N3eQwHpSNReyuIyAxgzeYuaZuIFofoQSLfCDYeC6d0j +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA3-pathlen99.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA3-pathlen99.pem new file mode 100644 index 000000000..9c6429cff --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA3-pathlen99.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA4-pathlen5, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA3-pathlen99, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:ac:f1:39:65:f7:9c:9d:f6:f0:d2:b7:18:16:24: + 81:32:b7:a5:29:d6:f7:4e:31:38:a7:54:d6:eb:07: + 97:27:a1:92:e0:c1:3a:b5:93:06:17:ef:a7:74:f8: + 9b:42:97:0c:d6:d3:d4:36:c9:61:ef:92:4c:3e:c4: + 74:08:d6:19:2a:cd:9b:f1:6f:e8:c8:67:9f:28:54: + 99:ce:63:1a:87:56:99:36:31:65:05:c5:d6:97:cf: + 51:e4:2d:3d:74:14:31:d3:c3:05:fc:0e:7c:93:57: + cd:f7:c4:97:d7:5c:65:75:e7:35:85:81:27:eb:9a: + 9f:d7:a2:bc:28:41:a8:ce:92:3a:10:b9:35:28:83: + dc:b0:27:cc:6e:20:03:60:13:23:22:b4:3c:25:58: + ae:a1:b2:24:d1:21:8b:b9:f0:28:84:ae:e6:00:cc: + cb:9b:78:8c:fa:4b:ed:73:7a:91:05:f9:fb:6e:34: + 3b:7e:af:f9:45:9e:a0:d5:62:bb:d8:cd:95:9e:a2: + 90:72:27:e0:3e:b9:b0:5e:0a:b2:e4:55:95:03:0c: + a6:66:44:65:db:0a:9f:90:5a:d3:81:c7:e2:3e:f2: + b0:9a:e0:05:1c:de:64:04:c2:7e:ca:7e:df:a1:f6: + 18:e5:94:d3:74:fb:a5:1f:2d:77:cd:6e:5e:55:a3: + 80:cb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + C1:CD:1F:81:13:82:24:3B:CF:64:51:7A:4C:E3:65:2E:75:1E:01:23 + X509v3 Authority Key Identifier: + keyid:D4:92:AE:BD:3B:1C:66:4B:17:88:18:15:F8:27:AB:38:CC:07:5A:65 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainG-ICA5-pathlen20/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:99 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 77:4b:04:d7:e6:fd:c1:bb:55:0c:2d:23:bf:90:a3:20:af:cd: + 54:11:34:97:fb:06:55:c1:11:ee:c5:bc:fe:5c:34:73:08:f9: + e9:c3:81:b8:0d:fa:6b:44:cd:ed:4a:d0:3b:40:6d:96:e5:cf: + 96:7d:aa:0d:65:fa:d7:6d:f7:3d:c9:9d:e5:e1:5e:be:34:7d: + b8:62:0c:22:e1:88:c8:02:b8:90:89:9f:1c:1d:18:5c:2d:01: + c9:95:f4:19:01:a6:5b:7a:26:6a:38:71:16:87:88:19:3f:60: + 35:99:71:4c:79:90:db:f9:9b:73:0d:74:45:87:b1:4f:e5:63: + a2:21:b4:38:32:d2:78:f0:15:a6:3a:ac:50:2a:a1:b2:41:f9: + 2b:0a:5c:5b:9a:94:17:42:88:44:41:fa:aa:d3:17:49:c1:31: + eb:a2:89:1f:c7:e7:b2:b0:71:98:64:4e:d6:de:b9:c2:5d:de: + 0e:86:68:1d:9c:ea:7c:b0:72:ee:2a:fa:26:26:1a:21:99:60: + 03:a2:01:67:0e:7d:4a:00:d9:23:2e:c2:c8:c8:3d:04:7a:78: + 08:81:f7:e4:0d:dc:e2:db:b6:1f:8a:33:ab:6f:a1:0d:5f:86: + cd:b7:c9:e1:35:a3:c8:81:da:15:3c:de:39:30:b7:d3:ec:4f: + d3:44:fe:dc +-----BEGIN CERTIFICATE----- +MIIE1TCCA72gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluRy1JQ0E0LXBhdGhsZW41MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgaIxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR4wHAYDVQQD +DBVjaGFpbkctSUNBMy1wYXRobGVuOTkxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s +ZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs8Tll95yd +9vDStxgWJIEyt6Up1vdOMTinVNbrB5cnoZLgwTq1kwYX76d0+JtClwzW09Q2yWHv +kkw+xHQI1hkqzZvxb+jIZ58oVJnOYxqHVpk2MWUFxdaXz1HkLT10FDHTwwX8DnyT +V833xJfXXGV15zWFgSfrmp/XorwoQajOkjoQuTUog9ywJ8xuIANgEyMitDwlWK6h +siTRIYu58CiEruYAzMubeIz6S+1zepEF+ftuNDt+r/lFnqDVYrvYzZWeopByJ+A+ +ubBeCrLkVZUDDKZmRGXbCp+QWtOBx+I+8rCa4AUc3mQEwn7Kft+h9hjllNN0+6Uf +LXfNbl5Vo4DLAgMBAAGjggETMIIBDzAdBgNVHQ4EFgQUwc0fgROCJDvPZFF6TONl +LnUeASMwgc8GA1UdIwSBxzCBxIAU1JKuvTscZksXiBgV+CerOMwHWmWhgaikgaUw +gaIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdT +ZWF0dGxlMRUwEwYDVQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVy +aW5nMR4wHAYDVQQDDBVjaGFpbkctSUNBNS1wYXRobGVuMjAxHzAdBgkqhkiG9w0B +CQEWEGluZm9Ad29sZnNzbC5jb22CAWQwDwYDVR0TBAgwBgEB/wIBYzALBgNVHQ8E +BAMCAQYwDQYJKoZIhvcNAQELBQADggEBAHdLBNfm/cG7VQwtI7+QoyCvzVQRNJf7 +BlXBEe7FvP5cNHMI+enDgbgN+mtEze1K0DtAbZblz5Z9qg1l+tdt9z3JneXhXr40 +fbhiDCLhiMgCuJCJnxwdGFwtAcmV9BkBplt6Jmo4cRaHiBk/YDWZcUx5kNv5m3MN +dEWHsU/lY6IhtDgy0njwFaY6rFAqobJB+SsKXFualBdCiERB+qrTF0nBMeuiiR/H +57KwcZhkTtbeucJd3g6GaB2c6nywcu4q+iYmGiGZYAOiAWcOfUoA2SMuwsjIPQR6 +eAiB9+QN3OLbth+KM6tvoQ1fhs23yeE1o8iB2hU83jkwt9PsT9NE/tw= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA4-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA4-key.pem new file mode 100644 index 000000000..fba2bbcdb --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA4-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAyUugd7hCQ5bh9I0dpizYEqJASRHrX/tsHRU+r907x/3JYUOZ +jse8Y7xbkyTz5WbIPjqcfQ4bwWyEjJCwEaojLXiZFz7pa6CMZP0Qe2bttD6wlu82 +Hy1txJY8WtyDwunNZNNfx+rbhC4kDHfR/YzP13ivW5jpxP1m+nYdesPDZDKtuYta +TILtOv4HRCATiN8CLNmXIaQ5pvN+i+LAzIZrWiUw1/m6Ke8bLvY/wX2xDJWOwM5z +QUcc7DNEYEadsHUHUMgZvx6CyMM92OIZHgs2nTSVh+qgH+iAYKWxlEIeV8ig5q34 +c8iC5DiE05f8hcTe0sDFbcce6x3B8d6XJ8q+SwIDAQABAoIBAQChoV8dIk/a07ll +UzY+a32oIK37vi7AKDLce2WVctAAuvBLcCtJ8Wl8sA7b7O0GA2zAQvHKnFx/CHK6 +J6eo13NdnJtYhgSJjiWNJYJpg/FULI5A850Clciw9G1MDAqkpHVvAybCcPuIfEAn +3sI3lCyDeH1d0D/NFCfu7o6nN6+ZsIW0FNrNEhmSMLVEXxJvjZboXD6bMC//a9db +/XMZPwah/HxaZebBwZGMOVtNVIAKAMwG1DfT0conX4b+xVJtz/o+dVqBv1KZ0NnQ +KZzVeRpwP/4L4fWhicnOxUFP1h50MOmpB0BmBn7zcjlBG+D8Xhunwa1igZOTh9ft ++UuyCPFBAoGBAPhg3Brlvw3P4xZb64nQykxpFXpP4HRC6pRby/Hyn6RjwDEd7SdC +MQRXv9BkrOSq3WBxu6F/u+zBjFnkj6lENz65cmAijOrXCkDuMRSX9mM5uHzZFpo2 +QKt595HvGGScysG8/6G+cv/0hu5hVMNlSjwvitXlhX0nOgb0PUpjr4fhAoGBAM94 +5/78sFUlG/cdOFfaFe8HR2ddiT3ofoMzdNqP7UR1oLPwT02vjrWjZLEXoSaaCjr4 +CUu3WVV5UndaA8OW4RgplkutMAxBggSBeoC4tGau31J4755ae5HwekE59Jh/XfO9 +vc1DEf49WDzL21mBd8yMY2k739vf52Qxqa27/lurAoGALWYu9S+nU1P7UxvsGp2y +THMsvNWa1kVg8UsyJQBPE9Iz0AaDUZi0svGDGwk73PQqULWZMTTS2byq9cdkRvE0 +E9/7uvy1uzshIasoB3abT5m+UfuwOPHPskgx61fDoqhSG0V7iEnyZTyB6VKbFrgN +8KBUBTLVyoGABsNf7Jf5/qECgYBugL1ASKI6l2tPsRaDZDrudvgHDAC/IofPpaaF +iscbAXO4ozP58pmWERLeZ/GDN+RfCCEbXOqN5fKQczcyA7icP/o3EGVZAcMYV0ZC +LR6Y2mdD6/nkY9kRH/5do1qtppkJ63OeUizRNyc6KnIIODbwkY2ZTTSsTZNXAESZ +rlmJxQKBgDJRGNWNx9WFaKx0WSX9qIvtrpJ3p7Flx8IbqvLCqWY799EXROKxbCNx +0SZMdqs0ebc1h+sEDsGfJs8NPqTdt22C1LQjt9eJIx5eU8lBeR1gTcZ3gdQitSNv +YJr6+6t/C1gvHsvxFWlBG0DPWgJUwqAxvYcGh4aTj9GHuNtvvLDl +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA4-pathlen5.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA4-pathlen5.pem new file mode 100644 index 000000000..8467d9f36 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA4-pathlen5.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA5-pathlen20, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA4-pathlen5, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:c9:4b:a0:77:b8:42:43:96:e1:f4:8d:1d:a6:2c: + d8:12:a2:40:49:11:eb:5f:fb:6c:1d:15:3e:af:dd: + 3b:c7:fd:c9:61:43:99:8e:c7:bc:63:bc:5b:93:24: + f3:e5:66:c8:3e:3a:9c:7d:0e:1b:c1:6c:84:8c:90: + b0:11:aa:23:2d:78:99:17:3e:e9:6b:a0:8c:64:fd: + 10:7b:66:ed:b4:3e:b0:96:ef:36:1f:2d:6d:c4:96: + 3c:5a:dc:83:c2:e9:cd:64:d3:5f:c7:ea:db:84:2e: + 24:0c:77:d1:fd:8c:cf:d7:78:af:5b:98:e9:c4:fd: + 66:fa:76:1d:7a:c3:c3:64:32:ad:b9:8b:5a:4c:82: + ed:3a:fe:07:44:20:13:88:df:02:2c:d9:97:21:a4: + 39:a6:f3:7e:8b:e2:c0:cc:86:6b:5a:25:30:d7:f9: + ba:29:ef:1b:2e:f6:3f:c1:7d:b1:0c:95:8e:c0:ce: + 73:41:47:1c:ec:33:44:60:46:9d:b0:75:07:50:c8: + 19:bf:1e:82:c8:c3:3d:d8:e2:19:1e:0b:36:9d:34: + 95:87:ea:a0:1f:e8:80:60:a5:b1:94:42:1e:57:c8: + a0:e6:ad:f8:73:c8:82:e4:38:84:d3:97:fc:85:c4: + de:d2:c0:c5:6d:c7:1e:eb:1d:c1:f1:de:97:27:ca: + be:4b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D4:92:AE:BD:3B:1C:66:4B:17:88:18:15:F8:27:AB:38:CC:07:5A:65 + X509v3 Authority Key Identifier: + keyid:1D:51:80:B6:9A:A7:AC:DD:80:7B:4B:A2:0B:62:BE:E4:87:30:C7:CA + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainG-ICA6-pathlen10/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:5 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + ab:ff:d4:87:51:61:f9:a5:68:8d:4e:fd:01:0c:e3:75:9a:c5: + 16:f2:c4:1e:d8:bd:d4:ce:9e:b9:bd:72:db:f2:89:2b:7a:46: + b4:6c:16:e5:dc:5a:eb:d0:3f:63:a8:98:82:0e:df:c6:1a:40: + a2:1a:a0:d5:49:10:a6:f4:ae:10:61:0a:2e:91:0d:bc:cf:e9: + bf:9e:98:23:38:30:f2:00:e3:ca:47:df:ad:46:e8:7b:b2:ae: + 1e:af:fd:c7:2e:b7:7d:b7:46:df:cd:bf:06:77:19:29:2b:fc: + 7c:f9:f7:2f:59:ce:90:a6:9e:70:33:58:b6:72:a4:ed:63:9b: + 50:62:6c:38:01:73:63:48:4e:6b:34:3f:c4:d5:de:45:09:a9: + 27:d1:78:36:59:1e:21:ad:a9:a3:1f:14:25:d1:ce:ab:90:3f: + c0:82:7a:54:fe:6b:48:fc:52:e1:f4:69:2d:84:2e:1c:7b:6f: + 42:4a:7b:05:91:70:0d:f3:ae:b3:d6:bc:7a:fa:9c:c8:0a:e8: + f1:a0:fa:ee:f3:fe:1d:34:0e:31:79:d8:80:57:53:23:af:65: + 92:94:ef:16:de:e0:9f:0a:5a:17:ba:e8:81:90:e1:e4:24:97: + b4:73:82:4c:38:4c:45:2f:82:75:55:4b:af:b8:58:b3:b1:d1: + 60:ab:53:5f +-----BEGIN CERTIFICATE----- +MIIE1TCCA72gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBojELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHjAcBgNVBAMMFWNo +YWluRy1JQ0E1LXBhdGhsZW4yMDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns +LmNvbTAeFw0xOTEwMTEwMDI4MDlaFw0yMjA3MDcwMDI4MDlaMIGhMQswCQYDVQQG +EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEVMBMG +A1UECgwMd29sZlNTTCBJbmMuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEdMBsGA1UE +AwwUY2hhaW5HLUlDQTQtcGF0aGxlbjUxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s +ZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJS6B3uEJD +luH0jR2mLNgSokBJEetf+2wdFT6v3TvH/clhQ5mOx7xjvFuTJPPlZsg+Opx9DhvB +bISMkLARqiMteJkXPulroIxk/RB7Zu20PrCW7zYfLW3Eljxa3IPC6c1k01/H6tuE +LiQMd9H9jM/XeK9bmOnE/Wb6dh16w8NkMq25i1pMgu06/gdEIBOI3wIs2ZchpDmm +836L4sDMhmtaJTDX+bop7xsu9j/BfbEMlY7AznNBRxzsM0RgRp2wdQdQyBm/HoLI +wz3Y4hkeCzadNJWH6qAf6IBgpbGUQh5XyKDmrfhzyILkOITTl/yFxN7SwMVtxx7r +HcHx3pcnyr5LAgMBAAGjggETMIIBDzAdBgNVHQ4EFgQU1JKuvTscZksXiBgV+Cer +OMwHWmUwgc8GA1UdIwSBxzCBxIAUHVGAtpqnrN2Ae0uiC2K+5Icwx8qhgaikgaUw +gaIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdT +ZWF0dGxlMRUwEwYDVQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVy +aW5nMR4wHAYDVQQDDBVjaGFpbkctSUNBNi1wYXRobGVuMTAxHzAdBgkqhkiG9w0B +CQEWEGluZm9Ad29sZnNzbC5jb22CAWQwDwYDVR0TBAgwBgEB/wIBBTALBgNVHQ8E +BAMCAQYwDQYJKoZIhvcNAQELBQADggEBAKv/1IdRYfmlaI1O/QEM43WaxRbyxB7Y +vdTOnrm9ctvyiSt6RrRsFuXcWuvQP2OomIIO38YaQKIaoNVJEKb0rhBhCi6RDbzP +6b+emCM4MPIA48pH361G6Huyrh6v/ccut323Rt/NvwZ3GSkr/Hz59y9ZzpCmnnAz +WLZypO1jm1BibDgBc2NITms0P8TV3kUJqSfReDZZHiGtqaMfFCXRzquQP8CCelT+ +a0j8UuH0aS2ELhx7b0JKewWRcA3zrrPWvHr6nMgK6PGg+u7z/h00DjF52IBXUyOv +ZZKU7xbe4J8KWhe66IGQ4eQkl7Rzgkw4TEUvgnVVS6+4WLOx0WCrU18= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA5-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA5-key.pem new file mode 100644 index 000000000..e3e23ae9d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA5-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAvp2YokHKZB+iNNxRfUkr9/h6/BoijToXjgCcdAYYDybR6B1V +Sz67bphtZctvvsWYQGUd4R2vrbx8sPq2Ksuv39VSmOYBATEBP8cWBkSSVUNv3Um+ +qlLSgMo60HLzCn5Zyyx0fFsZPXWdPto1RUmLDTaEgEG3znD8qNBNC9TzTnOH2y4Y +IEVw81rRz0/4eK18S5c88Q+K9myPejrJeYItv66A+IsdeRebdjSXsXldefowc3j8 +nO7rYiCV8aivHkqRzB40kMeJIUFBkAkQUt0hdRURqs/Y5Gx9lsjWzZDr+t+G5z02 +cxjzhsWZDg735AmPjCnxrRXpgslsh/wAe0su8QIDAQABAoIBAFM+piLuUoIpYoBt +W1U4uHAB30vr6fz9Sr4kPC9bXfR4AqG49b/3tIlXHiefkbyhtJ0iy8q9WTSppVbx +Fs9XxwYctoa5o+SuTxpYSqEQH0wHOHpOs2rU4sOGDets2AFULsjRMEoCyuIRVEvX +pf4NYSGzFmigyrHonB7pYUxygpNWlb+gPdnclhTj4psk1RP4cekFcLDHVxa2aq9K +STmHna7EE8XhbS2VeJ0+C9eRxXjcpjIMod1D9MycKjomuZMB0ElDp8lFgPvyNwf+ +I6Luv31YkRX7gi7l7HaPSnwnXgYfl7gcMCjgn8q3GHxiz7L40RBqCfdTE7of2ZJi +Yxlq2+UCgYEA62KTMYRCX3fP9+6m0LSPLX+mYVjxzgowcEZ0wbpgTRExONDvzfB/ +JgdwrSVSXhvbmoXs9LtdOWWpISpadh+c2vkx9w8ZP5DWk0h3g3FonP8pz85/OlnR +JaPzXvo+DuUfEG8VK4WneineOp74ZhXHoMbpKyg4zpNwloDYdWaA9dMCgYEAz09F +0Q+tmGfkQ76ECKQcQGsvbVDUED/Fk74VE7T/6d+EJ8RiPo6OQp8j3ObRKnlxm5n2 +XRG8nDyygAlscIZKlHDNaH6Qxvh+MFt378d3ziKuXkpKe147duRkBloQjnxEl5EM +u5bhaIR1EMhXrPjWbbxBA3jubiJ8hK9HDrgJOasCgYBJ4xuJQ5cCGL3zebprcQIw +qg00KZNdtd0WoUctOK/aATeOOifMYV3INjWsZDbCy8PXcYq8F8RfrAW3H3Bd+/Zk +1ixU/SxTw8dXXDwHyqWoAoDBdnSBgIgiZKCUg8DPNCTYJ8ZhbwbvVg0oIZaflN6h +HU87+Ng8IBQLak6IK7D3eQKBgA6OqH5ntW7wTK0dIbRhocI8RJZOiLWjZMJdJKm/ +mgDYOzV3qtZtuDuhZSlL5AAxivK8OvqKFk56TKaFAuJb67zEtwfRa2Utad8HbUKf +JSCKeugQG27STSaqHwP7KxJ2U3K5MsWxcJ6gPoAxMUbqKlSGVaJiyYteTJQcosa7 +0ZoFAoGBAOrSClY4sWV488+X/KFMkpXYdZCVbfGXqPLpaAFEOtOyNZw7PWF3ZfC6 +l3aqPxLBP1P55+KEcxz3dEEXZerr9OWfD5GOdz5/ep/Amrs0x/3ismZFQgXLa8Pm +NKt26anSXny8DfJMMe0W+6PQ2JUjrgp4bWF3OoQzsGLMHQBVFw+u +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA5-pathlen20.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA5-pathlen20.pem new file mode 100644 index 000000000..f9c3486bb --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA5-pathlen20.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA6-pathlen10, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA5-pathlen20, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:be:9d:98:a2:41:ca:64:1f:a2:34:dc:51:7d:49: + 2b:f7:f8:7a:fc:1a:22:8d:3a:17:8e:00:9c:74:06: + 18:0f:26:d1:e8:1d:55:4b:3e:bb:6e:98:6d:65:cb: + 6f:be:c5:98:40:65:1d:e1:1d:af:ad:bc:7c:b0:fa: + b6:2a:cb:af:df:d5:52:98:e6:01:01:31:01:3f:c7: + 16:06:44:92:55:43:6f:dd:49:be:aa:52:d2:80:ca: + 3a:d0:72:f3:0a:7e:59:cb:2c:74:7c:5b:19:3d:75: + 9d:3e:da:35:45:49:8b:0d:36:84:80:41:b7:ce:70: + fc:a8:d0:4d:0b:d4:f3:4e:73:87:db:2e:18:20:45: + 70:f3:5a:d1:cf:4f:f8:78:ad:7c:4b:97:3c:f1:0f: + 8a:f6:6c:8f:7a:3a:c9:79:82:2d:bf:ae:80:f8:8b: + 1d:79:17:9b:76:34:97:b1:79:5d:79:fa:30:73:78: + fc:9c:ee:eb:62:20:95:f1:a8:af:1e:4a:91:cc:1e: + 34:90:c7:89:21:41:41:90:09:10:52:dd:21:75:15: + 11:aa:cf:d8:e4:6c:7d:96:c8:d6:cd:90:eb:fa:df: + 86:e7:3d:36:73:18:f3:86:c5:99:0e:0e:f7:e4:09: + 8f:8c:29:f1:ad:15:e9:82:c9:6c:87:fc:00:7b:4b: + 2e:f1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1D:51:80:B6:9A:A7:AC:DD:80:7B:4B:A2:0B:62:BE:E4:87:30:C7:CA + X509v3 Authority Key Identifier: + keyid:14:07:E8:A7:3A:A2:9C:DD:4C:30:B0:4D:F0:00:C4:88:C4:39:DF:73 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainG-ICA7-pathlen100/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:20 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + a4:e7:16:a9:20:7b:9c:89:49:48:94:e7:58:31:71:34:10:35: + d5:b6:91:5f:5e:2d:63:66:48:ff:45:7f:d4:dc:53:39:6f:7b: + 13:0a:de:37:7c:c1:43:e9:f9:b2:71:b8:93:22:12:7f:50:9b: + b9:0c:e4:3a:47:7a:95:bc:a4:08:41:73:f0:a3:9a:88:98:7e: + d0:7c:bb:76:ab:5c:ad:3c:41:73:78:5b:b1:0d:06:ae:46:d2: + 81:af:9a:53:f7:d2:45:66:99:45:5e:2e:05:48:47:78:49:b4: + 27:c9:76:5f:93:be:d4:f7:3d:a7:16:39:ef:dc:a1:57:7f:78: + ca:d3:33:94:87:cb:dd:aa:88:07:0b:62:fa:eb:f0:c9:5f:d8: + 3f:a3:6d:d5:dc:ea:a0:b9:c6:dc:7f:08:46:9e:ed:41:52:46: + d2:7a:96:20:37:f6:69:ef:85:23:43:fa:a8:27:1c:2b:70:37: + 7d:50:ce:48:4b:f7:ce:2d:6a:08:3d:45:f3:a3:e4:1f:ef:1f: + 0e:72:e2:f2:f1:e7:5f:72:1f:84:53:1b:d6:b4:2b:e4:4a:3d: + 39:db:a7:02:6a:02:5e:de:3a:43:05:32:de:16:e9:5e:cf:12: + b2:0e:60:36:e1:47:12:ab:98:ce:ef:c4:76:d5:30:b6:72:ae: + af:13:14:17 +-----BEGIN CERTIFICATE----- +MIIE1zCCA7+gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBojELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHjAcBgNVBAMMFWNo +YWluRy1JQ0E2LXBhdGhsZW4xMDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns +LmNvbTAeFw0xOTEwMTEwMDI4MDlaFw0yMjA3MDcwMDI4MDlaMIGiMQswCQYDVQQG +EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEVMBMG +A1UECgwMd29sZlNTTCBJbmMuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEeMBwGA1UE +AwwVY2hhaW5HLUlDQTUtcGF0aGxlbjIwMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvp2YokHK +ZB+iNNxRfUkr9/h6/BoijToXjgCcdAYYDybR6B1VSz67bphtZctvvsWYQGUd4R2v +rbx8sPq2Ksuv39VSmOYBATEBP8cWBkSSVUNv3Um+qlLSgMo60HLzCn5Zyyx0fFsZ +PXWdPto1RUmLDTaEgEG3znD8qNBNC9TzTnOH2y4YIEVw81rRz0/4eK18S5c88Q+K +9myPejrJeYItv66A+IsdeRebdjSXsXldefowc3j8nO7rYiCV8aivHkqRzB40kMeJ +IUFBkAkQUt0hdRURqs/Y5Gx9lsjWzZDr+t+G5z02cxjzhsWZDg735AmPjCnxrRXp +gslsh/wAe0su8QIDAQABo4IBFDCCARAwHQYDVR0OBBYEFB1RgLaap6zdgHtLogti +vuSHMMfKMIHQBgNVHSMEgcgwgcWAFBQH6Kc6opzdTDCwTfAAxIjEOd9zoYGppIGm +MIGjMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwH +U2VhdHRsZTEVMBMGA1UECgwMd29sZlNTTCBJbmMuMRQwEgYDVQQLDAtFbmdpbmVl +cmluZzEfMB0GA1UEAwwWY2hhaW5HLUlDQTctcGF0aGxlbjEwMDEfMB0GCSqGSIb3 +DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIBZDAPBgNVHRMECDAGAQH/AgEUMAsGA1Ud +DwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEApOcWqSB7nIlJSJTnWDFxNBA11baR +X14tY2ZI/0V/1NxTOW97EwreN3zBQ+n5snG4kyISf1CbuQzkOkd6lbykCEFz8KOa +iJh+0Hy7dqtcrTxBc3hbsQ0GrkbSga+aU/fSRWaZRV4uBUhHeEm0J8l2X5O+1Pc9 +pxY579yhV394ytMzlIfL3aqIBwti+uvwyV/YP6Nt1dzqoLnG3H8IRp7tQVJG0nqW +IDf2ae+FI0P6qCccK3A3fVDOSEv3zi1qCD1F86PkH+8fDnLi8vHnX3IfhFMb1rQr +5Eo9OdunAmoCXt46QwUy3hbpXs8Ssg5gNuFHEquYzu/EdtUwtnKurxMUFw== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA6-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA6-key.pem new file mode 100644 index 000000000..c86bf08cc --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA6-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA4U/J5zDqBv9lyyts8ais9s8Qa4B6r15CCg1hvm8UPJ9kbpZG +d+JkoA7XVkH8W+b+SYYfjyDMS+w68UZ0Gn4z2arV4ngJ3Qw5IH4yEpbNltsQAei3 +quPhJ10Kj5lu7y3YyMh2qtkAnUjZzxIIlzFZwE+j4O5coTXvlHzGBKo+NKZD4Mjt +PZFTU54ZA46/MP3ZtUvzUQtg7Sfisd0VPLBfJQ8pm1+qMWRePYMuuCBmudqntSJA +GT0kXcPn3bZrFsNnI10xZTvLctGnyLDguaLLkIYw1s5/nLOxwzRiY8a5ZjNrW6YA +u0XuAweWpdcvHvHS8l7C0qE2JfB6cMs9HaRvYQIDAQABAoIBAE1NR7NHR/PQqkcT +hhQ/T+B52GNZuD30s+mo/7ELgUDvWtDKRDEbfnSfwue4SfHqBbKKDsfXc+BUk0B2 +cJ0qUXXLtAg4MQIjEHKCeYGBNdYdIJfXFTTPbE9KD7aG6NWswCTbCkPBogFUnk36 +HPJqnyVo7Yvdm/A/hgxG5tVw51i+Udw/LFi3AznJyr/if3FW64LxJaiL5HGDgHQS +Qvs+VuP13vR//BsM2oQPeiPIXpjscTtudFMrawKQiXMSWyD45snNR4AUuBcvXhpE +j+0sBqDWU1N6IeoZAhdTwJU/iDTbrE64VFr2f6U6bE6lI6h392/InKnoVXn6wyvR +s9MxXRUCgYEA8ZcFayiF74z/o37yhHcTEITAngmk1D9d9NKyzTPuXhbBwSTwjPwY +hP6f0KV/mlc+UQp00ULluE2oeM9mA69mD1/eSFqqA6nm5MvNOZsuEzqsmNN+gxk6 +XLuCOFfC7cG5uyodiJq0ooi4X2TXy186XJIZ3eNZ2gm7A0evHXat4T8CgYEA7sA0 +jt6G+oU4ojKn083qxrWNUZfyH3RT1EJv+2S/eZyzrww1kMfZZX3ZbP77iRJSFNaD +w+m709/5mKmZ8JIpcI2P/w5189680YUM+r9dqr4m4DW10vRQshQv/xExoLcXf7ue +dBrXpkSO7wNRaAjE+ljBFK3TBQ3ZY+mmNZ2i518CgYEA20A4zbCAJRAsbN/oDqnW +JnakLIkKCwnbJjYVyT9pBADZJIV2viyHwCMpPP0Fmje1OW0o6UUyIBpyW/m1VoDX +OfrCS53kj+CgyGHhRXd80Dy+qQ+/0BCUM9aEbsfPA2F+QssM9I2ag6ta0FA/u7UX +zS1WxlXvlH6iN27WEQJE+ZcCgYEA2hSZLZNYKgd8ZrPslsy10lJNxqULVe31EKKr +FS++ssAPZSq61welrU4aR7RVYKxqa3xSmaarmeoxXGA3LAbmcVftmyXDWkIvqRZm +d7hLP8Y3Tn/hGNNvzmogOVWkRlBX16YyI43NQ6PGB865ElVIUAC4RUJNyYUP+HKZ +Dspx3fMCgYBUBcxQgh8XOt8lb0zs9mZCXPkbkV401brucO0JqhyYvzGLWC4uYQEw +BuhSW3DKSBcaXMddiuGapuMSwS9A8T6EwGZHZ4PBcndJ2ak1xS2wSr4n/+ttlFWh +dHn8IrPC6E+gZa34CPza2LQzI1Xu3WAVUxijMNpURtC8lNWSzKXoXw== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA6-pathlen10.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA6-pathlen10.pem new file mode 100644 index 000000000..8de172a62 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA6-pathlen10.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA7-pathlen100, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA6-pathlen10, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:e1:4f:c9:e7:30:ea:06:ff:65:cb:2b:6c:f1:a8: + ac:f6:cf:10:6b:80:7a:af:5e:42:0a:0d:61:be:6f: + 14:3c:9f:64:6e:96:46:77:e2:64:a0:0e:d7:56:41: + fc:5b:e6:fe:49:86:1f:8f:20:cc:4b:ec:3a:f1:46: + 74:1a:7e:33:d9:aa:d5:e2:78:09:dd:0c:39:20:7e: + 32:12:96:cd:96:db:10:01:e8:b7:aa:e3:e1:27:5d: + 0a:8f:99:6e:ef:2d:d8:c8:c8:76:aa:d9:00:9d:48: + d9:cf:12:08:97:31:59:c0:4f:a3:e0:ee:5c:a1:35: + ef:94:7c:c6:04:aa:3e:34:a6:43:e0:c8:ed:3d:91: + 53:53:9e:19:03:8e:bf:30:fd:d9:b5:4b:f3:51:0b: + 60:ed:27:e2:b1:dd:15:3c:b0:5f:25:0f:29:9b:5f: + aa:31:64:5e:3d:83:2e:b8:20:66:b9:da:a7:b5:22: + 40:19:3d:24:5d:c3:e7:dd:b6:6b:16:c3:67:23:5d: + 31:65:3b:cb:72:d1:a7:c8:b0:e0:b9:a2:cb:90:86: + 30:d6:ce:7f:9c:b3:b1:c3:34:62:63:c6:b9:66:33: + 6b:5b:a6:00:bb:45:ee:03:07:96:a5:d7:2f:1e:f1: + d2:f2:5e:c2:d2:a1:36:25:f0:7a:70:cb:3d:1d:a4: + 6f:61 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 14:07:E8:A7:3A:A2:9C:DD:4C:30:B0:4D:F0:00:C4:88:C4:39:DF:73 + X509v3 Authority Key Identifier: + keyid:12:E4:A4:19:85:AE:85:B7:D6:EB:63:04:D5:B9:B0:7E:57:5F:0C:16 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:10 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 70:24:57:3f:1a:0c:94:f9:64:14:2e:20:81:bf:02:ba:bb:a5: + 21:02:2b:c0:09:0b:9e:8a:e3:c8:b2:39:4d:05:c1:34:62:44: + 62:5c:d5:ae:0f:17:cf:c0:ab:71:f8:5c:d5:74:8d:3d:eb:90: + d5:d6:a5:97:b8:c1:ab:d7:9c:e7:ca:4f:ee:8f:f2:5d:c7:81: + 22:fc:2e:b0:2d:f2:ff:e3:1a:c5:85:31:21:49:3f:38:f9:5b: + 55:e6:f3:f8:5c:63:fc:9a:c8:76:f0:3d:87:d2:fb:06:6d:5e: + f4:f4:e9:8c:3a:99:7b:1c:8f:29:fb:f6:c3:0c:23:9a:2c:1e: + f4:97:4f:b8:48:37:33:b4:aa:15:a6:5a:75:09:e9:c4:d5:44: + c6:e8:4e:a2:f0:70:a8:9f:10:91:56:55:59:f4:4a:b6:36:4a: + fc:b9:3a:60:01:e6:6e:61:58:f3:b0:ac:cd:02:38:97:bd:eb: + d3:6b:9e:b5:a6:58:ee:ce:86:c2:1b:cf:12:b3:1b:78:00:df: + 5f:da:77:5d:9c:8e:a5:ca:f1:77:87:c1:ed:ad:fd:cf:ea:05: + 53:f9:7e:34:e7:95:23:de:36:36:65:59:08:76:11:6f:d9:6e: + 55:17:af:33:1f:9e:0b:fe:fb:53:5c:67:1a:4d:8a:83:7f:5b: + ca:ff:e4:94 +-----BEGIN CERTIFICATE----- +MIIEyTCCA7GgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluRy1JQ0E3LXBhdGhsZW4xMDAxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMDAyODA5WhcNMjIwNzA3MDAyODA5WjCBojELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHjAcBgNV +BAMMFWNoYWluRy1JQ0E2LXBhdGhsZW4xMDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3 +b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOFPyecw +6gb/ZcsrbPGorPbPEGuAeq9eQgoNYb5vFDyfZG6WRnfiZKAO11ZB/Fvm/kmGH48g +zEvsOvFGdBp+M9mq1eJ4Cd0MOSB+MhKWzZbbEAHot6rj4SddCo+Zbu8t2MjIdqrZ +AJ1I2c8SCJcxWcBPo+DuXKE175R8xgSqPjSmQ+DI7T2RU1OeGQOOvzD92bVL81EL +YO0n4rHdFTywXyUPKZtfqjFkXj2DLrggZrnap7UiQBk9JF3D5922axbDZyNdMWU7 +y3LRp8iw4Lmiy5CGMNbOf5yzscM0YmPGuWYza1umALtF7gMHlqXXLx7x0vJewtKh +NiXwenDLPR2kb2ECAwEAAaOCAQUwggEBMB0GA1UdDgQWBBQUB+inOqKc3UwwsE3w +AMSIxDnfczCBwQYDVR0jBIG5MIG2gBQS5KQZha6Ft9brYwTVubB+V18MFqGBmqSB +lzCBlDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0Jv +emVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgw +FgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s +ZnNzbC5jb22CAWQwDwYDVR0TBAgwBgEB/wIBCjALBgNVHQ8EBAMCAQYwDQYJKoZI +hvcNAQELBQADggEBAHAkVz8aDJT5ZBQuIIG/Arq7pSECK8AJC56K48iyOU0FwTRi +RGJc1a4PF8/Aq3H4XNV0jT3rkNXWpZe4wavXnOfKT+6P8l3HgSL8LrAt8v/jGsWF +MSFJPzj5W1Xm8/hcY/yayHbwPYfS+wZtXvT06Yw6mXscjyn79sMMI5osHvSXT7hI +NzO0qhWmWnUJ6cTVRMboTqLwcKifEJFWVVn0SrY2Svy5OmAB5m5hWPOwrM0COJe9 +69NrnrWmWO7OhsIbzxKzG3gA31/ad12cjqXK8XeHwe2t/c/qBVP5fjTnlSPeNjZl +WQh2EW/ZblUXrzMfngv++1NcZxpNioN/W8r/5JQ= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA7-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA7-key.pem new file mode 100644 index 000000000..cebaccc16 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA7-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA1ozWxCkgYJ0VPQwq+yQvOIntN8T8V2cqUNjr4mocWQbybT65 +T/5JxSHAFvgpb1EM6njXDhVB2lrLC+BU1oP9D+hOMP/kRMOyAvN9OsZcToaGLHTU +IYXB/k6LBzxUG1Se7Fqlle1aNeAIxoR85q5xEtL9wf0WCjq4xyNLr+DNEl6fT2IT +8Mjk4qgB0zewCCHTD2zk2MEEUelMxbFtzGMjlzDu8B6rbeqTyq1Wbx7tGq6MG5EE +6qudGztWp8HMLzkvs7qMFv1eEBCeJOpAl3S2tOUcwNNfeSwEQzqO9LFWvcclY1w0 +UE29LfEIvYw+0m/65AShUevQ0JCRl3tGxhCSrwIDAQABAoIBAFn8IguN8D11RLYh +B1nj+EYvWyX74ZZK962G/ZAtzwvr5Pu6xgBt98TNfgJkPQSqKs+gtRn8Am2xjN3D +TfHW0+m7Fiho+vV4Wo3wT8K59Xcd5uJ4cYxJzG57xMXZILGB0VHyRubV8PMNrsCM +StJ5sYUipzmYi4jozhz/ibwPfhNIhbD7N7SQZe3J+Uq86fME4pSbStQpaeE8ORyN +LeCdYt6KSY6qGDs4IM8+EJmsjsoxjWci79LVPDEqhGQ9g/cpajh9tsVKluufMt+J +eTQ926YwjnlbY5pogpRoZlEPTlXJx2Ac9YeUs0pTLWZaQyR2XLvs5oNywO3pyR7X +LhVEPLkCgYEA8zpW+VN8LNRPkiHehk6E/2RLdDzMYoD5XRdgB3j8Vn/0NiyvZjLd +p+81/OLg7Yga6IFvU+3iisTefZvnZTqEKrtxyMbGL+LqAQFKGVm6eCZdX15dck4M +V1CwGtdVUl3V5yHuWvwosWV45n4UcDGxQ23VYdY4ypaPICNJevqKWaUCgYEA4dD9 +kwo6th35cn1P19UGFRT2Bo/ArliYvXb0stHGHse1Mz7hAf5epZ7rnJH1jbxtqZMu +OkoDK0Grulnt1AUYZm+6+y9YSbIeVFtOyKDEQeP6yH8VEQSaIScUFOYID8OpLuOq +wzRAz41vnU+957r3kt3DaYopInC02UP8LdMfAsMCgYAb3kJa3OLsbAMV9kV90/9P +F9nBXrn4S1jG/sek84rOCmkbz/Dk380f0bu41vH4pVCX9UShNC9xwO7RK4zOv26n +SsTVwVix4ej35oLr9qjz3UlzhOdmEmU9l+QlnyiKgG/ixLN/v0aWVM8OccG7vSXX +WP1K8XWeWLPbdc+UhKJXdQKBgGpqNlUoqOpRzc+qRgoMFUWyDw6gh8ihb7k5aa8r +NBYlPrrbkuWBndCmx5mNHw6gEX2sIkjNwBiOZgL3hiA4FnuPg6oDcbOpAKn4LXRW +bqYubWw2lxLh/FBLPidrD7l+FyhFmZ9L7I7itAqKHZAqh6jqYMBHn4LfYhpQ83IU +37RJAoGBAKqp3j4JNrhiwq0mBJL4GxFVy7eEjoqg6golGeIVE/5ApdOkQgLQaoeC +RrzNgjjQ3P08+XXXOQJVJRreX5ZVVjnxl/l1ixm0Hc/+SUXog7d4f+0kWWIqDAsC +YNW8MFqvNAN1f+TCKbSfR7oNfyUaoVCV5T5T875Q0et0DjkPTRc8 +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA7-pathlen100.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA7-pathlen100.pem new file mode 100644 index 000000000..5382cbae0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-ICA7-pathlen100.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA7-pathlen100, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d6:8c:d6:c4:29:20:60:9d:15:3d:0c:2a:fb:24: + 2f:38:89:ed:37:c4:fc:57:67:2a:50:d8:eb:e2:6a: + 1c:59:06:f2:6d:3e:b9:4f:fe:49:c5:21:c0:16:f8: + 29:6f:51:0c:ea:78:d7:0e:15:41:da:5a:cb:0b:e0: + 54:d6:83:fd:0f:e8:4e:30:ff:e4:44:c3:b2:02:f3: + 7d:3a:c6:5c:4e:86:86:2c:74:d4:21:85:c1:fe:4e: + 8b:07:3c:54:1b:54:9e:ec:5a:a5:95:ed:5a:35:e0: + 08:c6:84:7c:e6:ae:71:12:d2:fd:c1:fd:16:0a:3a: + b8:c7:23:4b:af:e0:cd:12:5e:9f:4f:62:13:f0:c8: + e4:e2:a8:01:d3:37:b0:08:21:d3:0f:6c:e4:d8:c1: + 04:51:e9:4c:c5:b1:6d:cc:63:23:97:30:ee:f0:1e: + ab:6d:ea:93:ca:ad:56:6f:1e:ed:1a:ae:8c:1b:91: + 04:ea:ab:9d:1b:3b:56:a7:c1:cc:2f:39:2f:b3:ba: + 8c:16:fd:5e:10:10:9e:24:ea:40:97:74:b6:b4:e5: + 1c:c0:d3:5f:79:2c:04:43:3a:8e:f4:b1:56:bd:c7: + 25:63:5c:34:50:4d:bd:2d:f1:08:bd:8c:3e:d2:6f: + fa:e4:04:a1:51:eb:d0:d0:90:91:97:7b:46:c6:10: + 92:af + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 12:E4:A4:19:85:AE:85:B7:D6:EB:63:04:D5:B9:B0:7E:57:5F:0C:16 + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:100 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + ae:bd:d0:c5:e1:4f:80:0f:85:0d:d2:e0:b5:c3:dc:73:99:94: + 90:19:01:f2:23:66:83:da:92:f2:e8:14:dc:70:e0:20:14:26: + c5:63:88:6a:1b:b3:f3:2f:5c:28:39:1e:6b:a7:40:9b:02:12: + ac:88:06:1e:c6:dd:9d:d4:6a:b8:22:cb:b7:aa:7a:9c:77:9a: + 37:0a:62:54:23:f3:e7:b9:4f:e0:8a:41:bd:74:21:69:be:7c: + 19:50:7d:d1:93:98:7c:4a:06:60:64:72:f0:09:71:6e:86:43: + 2f:89:dc:38:4a:c1:e4:cc:bc:72:6f:c2:b1:c1:9c:38:ff:98: + 87:92:3b:a6:f2:b5:2d:0a:41:38:0d:e7:b5:41:cf:c1:6d:96: + 34:98:9e:97:c8:87:a9:9e:4b:bb:73:bb:34:d6:bd:61:ef:36: + c8:45:f3:c9:31:36:2c:f1:11:68:4b:a0:f8:b6:9d:c4:a6:8a: + dc:e3:fc:60:f7:50:d2:d4:98:d4:e5:f9:76:ca:4a:3c:74:9a: + bb:95:ce:3c:29:ce:be:b5:9e:07:55:e2:c4:a1:1f:b4:0d:eb: + 87:03:1d:79:1b:e2:fc:f3:aa:4b:df:3e:24:72:56:00:b9:b4: + a0:fc:48:80:6a:76:84:1b:79:ea:03:95:32:42:bc:9d:7a:83: + 87:be:51:d2 +-----BEGIN CERTIFICATE----- +MIIEwzCCA6ugAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA5WhcNMjIwNzA3MDAyODA5WjCBozELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNoYWluRy1JQ0E3 +LXBhdGhsZW4xMDAxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWjNbEKSBgnRU9DCr7JC84ie03 +xPxXZypQ2OviahxZBvJtPrlP/knFIcAW+ClvUQzqeNcOFUHaWssL4FTWg/0P6E4w +/+REw7IC8306xlxOhoYsdNQhhcH+TosHPFQbVJ7sWqWV7Vo14AjGhHzmrnES0v3B +/RYKOrjHI0uv4M0SXp9PYhPwyOTiqAHTN7AIIdMPbOTYwQRR6UzFsW3MYyOXMO7w +Hqtt6pPKrVZvHu0arowbkQTqq50bO1anwcwvOS+zuowW/V4QEJ4k6kCXdLa05RzA +0195LARDOo70sVa9xyVjXDRQTb0t8Qi9jD7Sb/rkBKFR69DQkJGXe0bGEJKvAgMB +AAGjggENMIIBCTAdBgNVHQ4EFgQUEuSkGYWuhbfW62ME1bmwfldfDBYwgckGA1Ud +IwSBwTCBvoAUJ45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYT +AlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQK +DAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1 +jhDeuPswDwYDVR0TBAgwBgEB/wIBZDALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEL +BQADggEBAK690MXhT4APhQ3S4LXD3HOZlJAZAfIjZoPakvLoFNxw4CAUJsVjiGob +s/MvXCg5HmunQJsCEqyIBh7G3Z3Uargiy7eqepx3mjcKYlQj8+e5T+CKQb10IWm+ +fBlQfdGTmHxKBmBkcvAJcW6GQy+J3DhKweTMvHJvwrHBnDj/mIeSO6bytS0KQTgN +57VBz8FtljSYnpfIh6meS7tzuzTWvWHvNshF88kxNizxEWhLoPi2ncSmitzj/GD3 +UNLUmNTl+XbKSjx0mruVzjwpzr61ngdV4sShH7QN64cDHXkb4vzzqkvfPiRyVgC5 +tKD8SIBqdoQbeeoDlTJCvJ16g4e+UdI= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-assembled.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-assembled.pem new file mode 100644 index 000000000..39ee469f7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-assembled.pem @@ -0,0 +1,710 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA1-pathlen0, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bb:7b:82:23:a2:34:e7:cb:89:4e:64:cc:f2:98: + c8:65:8f:e2:69:55:54:4b:3c:8b:c0:1f:67:37:7f: + 09:cb:9e:df:5e:75:f6:99:83:12:ac:15:23:cf:64: + a4:10:16:a5:10:af:28:86:00:20:4e:f3:4d:fd:08: + fb:a1:a7:18:4c:13:1e:4d:90:2e:e6:9a:e3:28:03: + b4:f4:83:ce:fd:a2:a9:86:56:02:62:33:9f:6e:98: + 7e:0f:cc:06:71:31:8a:93:d2:d9:a3:1d:08:7a:92: + f8:7e:bf:90:5f:a1:e6:2b:64:58:bb:a6:9a:c9:19: + 97:fd:c9:a9:f7:08:27:8a:f3:be:e2:db:88:25:84: + 91:13:06:e2:63:bc:e1:37:82:7e:6f:5a:da:f0:e2: + eb:a1:2a:8f:5d:52:11:af:e2:f5:89:42:79:83:b8: + c0:a5:95:dc:42:c6:1c:90:51:1e:33:f3:f1:c2:e4: + d2:7b:87:c3:64:90:b7:5f:9b:38:ef:d2:d0:4f:d5: + 51:aa:e0:3a:d1:c3:01:03:e7:32:b1:27:c6:48:5a: + c0:ac:26:8d:94:61:76:f8:98:ff:30:6d:aa:55:c3: + 63:fd:a4:a4:1b:3c:6b:e8:05:75:41:17:5d:ad:c9: + 17:9b:c3:4d:6e:9f:7d:7d:36:fe:c0:a3:99:d6:e5: + 92:ad + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 21:3A:72:3B:95:38:DF:99:DE:62:25:21:D0:14:81:6E:CA:AA:FB:A1 + X509v3 Authority Key Identifier: + keyid:47:C0:19:4B:ED:C4:DA:97:B1:60:EA:5A:0A:42:6D:A5:D3:D8:25:31 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainG-ICA2-pathlen1/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 06:c8:08:8c:cc:5d:4e:b5:81:35:06:f3:e5:9d:4e:c8:38:3f: + ec:87:8b:55:3c:fc:6e:4c:f8:3c:78:7d:46:03:33:a7:49:55: + 6c:13:37:e9:11:d5:dd:8c:51:70:2c:28:18:6a:01:63:9b:35: + 04:ba:79:49:95:10:ed:31:4b:70:5f:be:a4:67:d4:8d:2f:95: + 45:f7:1f:3d:a0:fc:29:db:55:65:8d:98:ae:79:ad:ce:c7:b9: + 97:54:9d:69:ca:fa:87:01:fb:0d:9b:57:67:b8:44:f6:91:14: + e5:31:b5:c1:d8:96:b7:1d:7a:05:ed:53:d5:04:8a:8b:8e:74: + f1:13:3d:93:d6:16:10:17:d7:de:b1:4e:13:e8:72:ae:83:91: + 1f:46:3e:86:bd:49:79:9c:99:a9:aa:67:ff:cf:7c:34:b1:2c: + d8:bf:e5:3a:22:c2:70:97:47:db:d0:05:77:e9:46:09:f0:c1: + 06:1c:61:df:8b:8f:6d:a6:5b:d5:ae:9a:52:71:ed:5e:9e:38: + e3:8c:9a:52:cf:8a:8f:20:e9:f1:e4:a3:11:bd:b9:ff:a9:1e: + b7:f9:83:26:18:a8:0b:7b:2b:74:f5:c5:3a:58:e1:0b:71:0a: + 3d:ef:15:ee:2c:28:b3:ba:0e:59:3c:a4:46:24:d3:b7:14:b5: + 4a:8f:c1:25 +-----BEGIN CERTIFICATE----- +MIIEtzCCA5+gAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluRy1JQ0ExLXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgZoxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRYwFAYDVQQD +DA1jaGFpbkctZW50aXR5MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu3uCI6I058uJTmTM8pjI +ZY/iaVVUSzyLwB9nN38Jy57fXnX2mYMSrBUjz2SkEBalEK8ohgAgTvNN/Qj7oacY +TBMeTZAu5prjKAO09IPO/aKphlYCYjOfbph+D8wGcTGKk9LZox0IepL4fr+QX6Hm +K2RYu6aayRmX/cmp9wgnivO+4tuIJYSREwbiY7zhN4J+b1ra8OLroSqPXVIRr+L1 +iUJ5g7jApZXcQsYckFEeM/PxwuTSe4fDZJC3X5s479LQT9VRquA60cMBA+cysSfG +SFrArCaNlGF2+Jj/MG2qVcNj/aSkGzxr6AV1QRddrckXm8NNbp99fTb+wKOZ1uWS +rQIDAQABo4H+MIH7MB0GA1UdDgQWBBQhOnI7lTjfmd5iJSHQFIFuyqr7oTCBzgYD +VR0jBIHGMIHDgBRHwBlL7cTal7Fg6loKQm2l09glMaGBp6SBpDCBoTELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNV +BAMMFGNoYWluRy1JQ0EyLXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tggFkMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAAbICIzM +XU61gTUG8+WdTsg4P+yHi1U8/G5M+Dx4fUYDM6dJVWwTN+kR1d2MUXAsKBhqAWOb +NQS6eUmVEO0xS3BfvqRn1I0vlUX3Hz2g/CnbVWWNmK55rc7HuZdUnWnK+ocB+w2b +V2e4RPaRFOUxtcHYlrcdegXtU9UEiouOdPETPZPWFhAX196xThPocq6DkR9GPoa9 +SXmcmamqZ//PfDSxLNi/5ToiwnCXR9vQBXfpRgnwwQYcYd+Lj22mW9WumlJx7V6e +OOOMmlLPio8g6fHkoxG9uf+pHrf5gyYYqAt7K3T1xTpY4QtxCj3vFe4sKLO6Dlk8 +pEYk07cUtUqPwSU= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA2-pathlen1, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA1-pathlen0, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d2:26:be:51:98:42:e0:1f:ae:fc:c2:cb:ba:d5: + 0f:44:3b:0b:60:d8:49:ec:03:43:6b:06:ce:f2:28: + 19:fb:48:9c:0b:5c:7f:00:a3:22:9f:bc:e9:2a:5b: + e4:e1:16:d8:9c:b9:c3:0b:30:e3:1c:83:7d:c0:b9: + a4:3f:da:38:ec:8b:38:be:45:c4:a7:1d:c1:68:18: + 28:19:b0:f2:93:06:3a:bd:23:67:aa:05:89:31:3b: + c2:b4:5e:b3:12:cb:3b:f3:9c:d6:df:4c:ed:cb:42: + 1b:25:80:2d:ab:c4:67:8f:a5:ff:da:6c:f1:18:fd: + a1:98:8c:d8:1f:67:6c:28:c7:cb:4e:bb:b0:27:ea: + 25:b1:5d:73:d0:2a:e9:44:50:b9:f5:65:64:e6:cf: + 3d:92:d8:c0:6d:ed:96:8e:e2:d3:84:70:d0:db:fe: + 70:63:44:fa:f8:db:35:d1:95:ad:18:95:21:64:ce: + e2:23:7e:5e:6c:2f:ef:a7:63:fe:82:4a:cb:cc:23: + cf:9d:26:a5:66:ed:9c:06:7e:70:76:03:72:99:db: + fa:be:a5:c3:38:8b:40:24:c1:6b:d7:9c:bb:27:86: + 22:a9:62:e0:b2:bd:e7:b5:e4:81:ea:64:db:18:16: + 24:62:81:6c:a8:f2:83:3f:af:3b:b5:fd:b0:d8:84: + b2:21 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 47:C0:19:4B:ED:C4:DA:97:B1:60:EA:5A:0A:42:6D:A5:D3:D8:25:31 + X509v3 Authority Key Identifier: + keyid:E1:E6:9B:28:CF:FD:AB:45:C1:B7:A7:C4:C9:58:FC:41:E3:1A:5C:74 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainG-ICA3-pathlen99/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:0 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 56:81:8e:f1:e8:5f:b2:9f:ab:8f:2e:ec:79:c7:3d:0d:af:f2: + 18:f7:d2:2e:07:2c:d0:1d:2a:90:c7:c1:fc:ac:aa:0d:86:f0: + 78:6d:33:43:81:02:70:3b:e6:d9:75:db:2e:ca:4a:61:4d:20: + cb:a9:3e:0c:a9:b3:ca:ff:bb:52:cb:06:14:2d:53:b5:68:9f: + a7:02:83:90:3d:f8:b6:a2:46:e4:2b:c5:48:ed:50:7f:ea:27: + cf:7b:9d:88:1f:1c:5d:16:b7:21:0a:42:95:0b:67:6c:29:34: + 64:61:c0:f5:00:6f:36:dc:e9:68:e3:81:bd:07:a6:bc:6c:9d: + f0:61:b0:50:14:d5:89:46:1f:34:b0:90:42:a0:c3:09:64:6e: + a4:46:13:c6:6a:86:98:63:c7:8e:79:d3:a2:d6:73:23:68:a9: + 8d:ac:b0:93:b0:89:f5:ee:08:cc:47:14:95:3b:1f:d3:eb:42: + 3f:68:b8:6b:80:11:8d:85:8c:90:39:29:e8:5d:7d:e5:c1:c2: + 5c:e7:92:8c:ab:79:17:74:60:a5:ee:fe:52:ff:4a:78:62:5c: + 1b:4b:f8:44:41:8c:05:c7:11:e7:5a:c9:a1:a1:d3:6b:82:36: + c3:1f:23:19:ce:68:9d:c3:80:d5:08:8d:68:d2:49:52:95:44: + 3f:1b:50:9d +-----BEGIN CERTIFICATE----- +MIIE1DCCA7ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluRy1JQ0EyLXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgaExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR0wGwYDVQQD +DBRjaGFpbkctSUNBMS1wYXRobGVuMDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm +c3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANImvlGYQuAf +rvzCy7rVD0Q7C2DYSewDQ2sGzvIoGftInAtcfwCjIp+86Spb5OEW2Jy5wwsw4xyD +fcC5pD/aOOyLOL5FxKcdwWgYKBmw8pMGOr0jZ6oFiTE7wrResxLLO/Oc1t9M7ctC +GyWALavEZ4+l/9ps8Rj9oZiM2B9nbCjHy067sCfqJbFdc9Aq6URQufVlZObPPZLY +wG3tlo7i04Rw0Nv+cGNE+vjbNdGVrRiVIWTO4iN+Xmwv76dj/oJKy8wjz50mpWbt +nAZ+cHYDcpnb+r6lwziLQCTBa9ecuyeGIqli4LK957Xkgepk2xgWJGKBbKjygz+v +O7X9sNiEsiECAwEAAaOCARMwggEPMB0GA1UdDgQWBBRHwBlL7cTal7Fg6loKQm2l +09glMTCBzwYDVR0jBIHHMIHEgBTh5psoz/2rRcG3p8TJWPxB4xpcdKGBqKSBpTCB +ojELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1Nl +YXR0bGUxFTATBgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJp +bmcxHjAcBgNVBAMMFWNoYWluRy1JQ0EzLXBhdGhsZW45OTEfMB0GCSqGSIb3DQEJ +ARYQaW5mb0B3b2xmc3NsLmNvbYIBZDAPBgNVHRMECDAGAQH/AgEAMAsGA1UdDwQE +AwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAVoGO8ehfsp+rjy7secc9Da/yGPfSLgcs +0B0qkMfB/KyqDYbweG0zQ4ECcDvm2XXbLspKYU0gy6k+DKmzyv+7UssGFC1TtWif +pwKDkD34tqJG5CvFSO1Qf+onz3udiB8cXRa3IQpClQtnbCk0ZGHA9QBvNtzpaOOB +vQemvGyd8GGwUBTViUYfNLCQQqDDCWRupEYTxmqGmGPHjnnTotZzI2ipjaywk7CJ +9e4IzEcUlTsf0+tCP2i4a4ARjYWMkDkp6F195cHCXOeSjKt5F3Rgpe7+Uv9KeGJc +G0v4REGMBccR51rJoaHTa4I2wx8jGc5oncOA1QiNaNJJUpVEPxtQnQ== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA3-pathlen99, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA2-pathlen1, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d7:3e:de:b9:f9:a9:d7:8e:7a:4b:f2:f1:8c:f9: + 3b:1c:ce:59:31:4c:57:0c:2e:8a:0f:90:f0:dc:27: + 55:0b:10:c3:a2:e8:b9:39:75:17:d1:9d:99:43:94: + b2:f1:56:76:6b:b9:46:a6:b8:35:95:a1:d2:d0:ec: + 8e:be:95:dc:78:17:0a:41:a1:23:df:cb:b2:87:cb: + 2e:1d:02:7d:c4:fe:7a:f6:7a:d8:a5:8d:b5:11:1a: + e4:6b:d2:66:01:01:03:a7:3b:95:49:92:5d:c1:c7: + 49:f0:1a:ef:00:71:37:99:5a:87:0a:40:de:55:0e: + 68:89:dc:e7:a1:14:bf:9d:72:93:7e:48:29:e4:ea: + a6:4f:0a:7a:a5:a1:39:6c:21:84:3a:8f:ca:7a:35: + 0b:0a:cd:12:67:3c:56:06:f5:9d:24:c9:8e:4a:82: + 23:c8:38:7f:ac:98:b6:b2:57:dc:82:62:84:00:13: + 7b:ea:73:80:26:4a:9b:c1:b4:0a:f1:fc:ff:46:58: + 96:a0:21:a1:c9:8f:d9:99:74:41:0b:d0:6d:31:a7: + ab:87:92:76:51:42:ef:88:95:cc:2c:f2:9b:cc:d5: + 29:a0:f7:aa:6b:e1:ab:32:16:cd:55:c4:15:80:69: + 80:91:d8:78:2c:07:15:fd:c2:02:a4:f4:13:75:50: + b8:2b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + E1:E6:9B:28:CF:FD:AB:45:C1:B7:A7:C4:C9:58:FC:41:E3:1A:5C:74 + X509v3 Authority Key Identifier: + keyid:C1:CD:1F:81:13:82:24:3B:CF:64:51:7A:4C:E3:65:2E:75:1E:01:23 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainG-ICA4-pathlen5/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:1 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 3b:e4:43:62:32:48:75:cf:da:f6:fa:38:4f:1b:b2:25:84:5b: + 79:8f:ce:9c:19:10:ef:ab:b4:b5:f0:2b:d1:16:77:f6:cc:f6: + 43:c7:1f:ca:92:f9:d7:69:3c:82:02:02:19:55:a4:a1:d0:1c: + 7c:e8:b8:8f:4c:7b:42:6c:68:0d:0c:b0:05:ad:39:29:7c:45: + 8e:e2:b3:54:e7:98:84:95:21:3d:73:26:33:5e:5b:59:59:f2: + 03:13:28:86:e1:2c:da:a8:37:7e:2e:93:5e:e1:41:9c:6d:03: + 16:0f:8a:b2:4d:67:b6:1b:65:8a:cb:30:b5:ed:ad:e7:9f:81: + 21:a7:6d:39:f7:af:93:82:1c:89:55:ae:0d:e8:88:be:a5:27: + 60:56:7b:f3:5c:1d:57:49:36:c2:9f:cc:50:62:a7:82:54:61: + 36:10:01:2f:cf:85:b2:dd:d7:56:cc:18:7e:85:5d:f1:b7:b7: + b6:c3:04:6b:01:5e:b8:68:28:9a:6b:fc:83:33:b7:28:64:55: + 38:ee:a4:5a:d5:87:ef:89:07:c4:60:9d:8a:25:d5:71:94:5b: + 96:3f:a4:3f:1d:80:3e:ef:97:9e:c4:25:f1:82:01:27:40:27: + cc:61:e6:67:e0:58:33:e9:9f:35:65:89:40:17:6a:a7:6c:d9: + 70:2c:59:a1 +-----BEGIN CERTIFICATE----- +MIIE1DCCA7ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBojELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHjAcBgNVBAMMFWNo +YWluRy1JQ0EzLXBhdGhsZW45OTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns +LmNvbTAeFw0xOTEwMTEwMDI4MDlaFw0yMjA3MDcwMDI4MDlaMIGhMQswCQYDVQQG +EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEVMBMG +A1UECgwMd29sZlNTTCBJbmMuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEdMBsGA1UE +AwwUY2hhaW5HLUlDQTItcGF0aGxlbjExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s +ZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXPt65+anX +jnpL8vGM+TsczlkxTFcMLooPkPDcJ1ULEMOi6Lk5dRfRnZlDlLLxVnZruUamuDWV +odLQ7I6+ldx4FwpBoSPfy7KHyy4dAn3E/nr2etiljbURGuRr0mYBAQOnO5VJkl3B +x0nwGu8AcTeZWocKQN5VDmiJ3OehFL+dcpN+SCnk6qZPCnqloTlsIYQ6j8p6NQsK +zRJnPFYG9Z0kyY5KgiPIOH+smLayV9yCYoQAE3vqc4AmSpvBtArx/P9GWJagIaHJ +j9mZdEEL0G0xp6uHknZRQu+Ilcws8pvM1Smg96pr4asyFs1VxBWAaYCR2HgsBxX9 +wgKk9BN1ULgrAgMBAAGjggESMIIBDjAdBgNVHQ4EFgQU4eabKM/9q0XBt6fEyVj8 +QeMaXHQwgc4GA1UdIwSBxjCBw4AUwc0fgROCJDvPZFF6TONlLnUeASOhgaekgaQw +gaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdT +ZWF0dGxlMRUwEwYDVQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVy +aW5nMR0wGwYDVQQDDBRjaGFpbkctSUNBNC1wYXRobGVuNTEfMB0GCSqGSIb3DQEJ +ARYQaW5mb0B3b2xmc3NsLmNvbYIBZDAPBgNVHRMECDAGAQH/AgEBMAsGA1UdDwQE +AwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAO+RDYjJIdc/a9vo4TxuyJYRbeY/OnBkQ +76u0tfAr0RZ39sz2Q8cfypL512k8ggICGVWkodAcfOi4j0x7QmxoDQywBa05KXxF +juKzVOeYhJUhPXMmM15bWVnyAxMohuEs2qg3fi6TXuFBnG0DFg+Ksk1nthtlissw +te2t55+BIadtOfevk4IciVWuDeiIvqUnYFZ781wdV0k2wp/MUGKnglRhNhABL8+F +st3XVswYfoVd8be3tsMEawFeuGgommv8gzO3KGRVOO6kWtWH74kHxGCdiiXVcZRb +lj+kPx2APu+XnsQl8YIBJ0AnzGHmZ+BYM+mfNWWJQBdqp2zZcCxZoQ== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA4-pathlen5, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA3-pathlen99, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:ac:f1:39:65:f7:9c:9d:f6:f0:d2:b7:18:16:24: + 81:32:b7:a5:29:d6:f7:4e:31:38:a7:54:d6:eb:07: + 97:27:a1:92:e0:c1:3a:b5:93:06:17:ef:a7:74:f8: + 9b:42:97:0c:d6:d3:d4:36:c9:61:ef:92:4c:3e:c4: + 74:08:d6:19:2a:cd:9b:f1:6f:e8:c8:67:9f:28:54: + 99:ce:63:1a:87:56:99:36:31:65:05:c5:d6:97:cf: + 51:e4:2d:3d:74:14:31:d3:c3:05:fc:0e:7c:93:57: + cd:f7:c4:97:d7:5c:65:75:e7:35:85:81:27:eb:9a: + 9f:d7:a2:bc:28:41:a8:ce:92:3a:10:b9:35:28:83: + dc:b0:27:cc:6e:20:03:60:13:23:22:b4:3c:25:58: + ae:a1:b2:24:d1:21:8b:b9:f0:28:84:ae:e6:00:cc: + cb:9b:78:8c:fa:4b:ed:73:7a:91:05:f9:fb:6e:34: + 3b:7e:af:f9:45:9e:a0:d5:62:bb:d8:cd:95:9e:a2: + 90:72:27:e0:3e:b9:b0:5e:0a:b2:e4:55:95:03:0c: + a6:66:44:65:db:0a:9f:90:5a:d3:81:c7:e2:3e:f2: + b0:9a:e0:05:1c:de:64:04:c2:7e:ca:7e:df:a1:f6: + 18:e5:94:d3:74:fb:a5:1f:2d:77:cd:6e:5e:55:a3: + 80:cb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + C1:CD:1F:81:13:82:24:3B:CF:64:51:7A:4C:E3:65:2E:75:1E:01:23 + X509v3 Authority Key Identifier: + keyid:D4:92:AE:BD:3B:1C:66:4B:17:88:18:15:F8:27:AB:38:CC:07:5A:65 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainG-ICA5-pathlen20/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:99 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 77:4b:04:d7:e6:fd:c1:bb:55:0c:2d:23:bf:90:a3:20:af:cd: + 54:11:34:97:fb:06:55:c1:11:ee:c5:bc:fe:5c:34:73:08:f9: + e9:c3:81:b8:0d:fa:6b:44:cd:ed:4a:d0:3b:40:6d:96:e5:cf: + 96:7d:aa:0d:65:fa:d7:6d:f7:3d:c9:9d:e5:e1:5e:be:34:7d: + b8:62:0c:22:e1:88:c8:02:b8:90:89:9f:1c:1d:18:5c:2d:01: + c9:95:f4:19:01:a6:5b:7a:26:6a:38:71:16:87:88:19:3f:60: + 35:99:71:4c:79:90:db:f9:9b:73:0d:74:45:87:b1:4f:e5:63: + a2:21:b4:38:32:d2:78:f0:15:a6:3a:ac:50:2a:a1:b2:41:f9: + 2b:0a:5c:5b:9a:94:17:42:88:44:41:fa:aa:d3:17:49:c1:31: + eb:a2:89:1f:c7:e7:b2:b0:71:98:64:4e:d6:de:b9:c2:5d:de: + 0e:86:68:1d:9c:ea:7c:b0:72:ee:2a:fa:26:26:1a:21:99:60: + 03:a2:01:67:0e:7d:4a:00:d9:23:2e:c2:c8:c8:3d:04:7a:78: + 08:81:f7:e4:0d:dc:e2:db:b6:1f:8a:33:ab:6f:a1:0d:5f:86: + cd:b7:c9:e1:35:a3:c8:81:da:15:3c:de:39:30:b7:d3:ec:4f: + d3:44:fe:dc +-----BEGIN CERTIFICATE----- +MIIE1TCCA72gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluRy1JQ0E0LXBhdGhsZW41MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgaIxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR4wHAYDVQQD +DBVjaGFpbkctSUNBMy1wYXRobGVuOTkxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s +ZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs8Tll95yd +9vDStxgWJIEyt6Up1vdOMTinVNbrB5cnoZLgwTq1kwYX76d0+JtClwzW09Q2yWHv +kkw+xHQI1hkqzZvxb+jIZ58oVJnOYxqHVpk2MWUFxdaXz1HkLT10FDHTwwX8DnyT +V833xJfXXGV15zWFgSfrmp/XorwoQajOkjoQuTUog9ywJ8xuIANgEyMitDwlWK6h +siTRIYu58CiEruYAzMubeIz6S+1zepEF+ftuNDt+r/lFnqDVYrvYzZWeopByJ+A+ +ubBeCrLkVZUDDKZmRGXbCp+QWtOBx+I+8rCa4AUc3mQEwn7Kft+h9hjllNN0+6Uf +LXfNbl5Vo4DLAgMBAAGjggETMIIBDzAdBgNVHQ4EFgQUwc0fgROCJDvPZFF6TONl +LnUeASMwgc8GA1UdIwSBxzCBxIAU1JKuvTscZksXiBgV+CerOMwHWmWhgaikgaUw +gaIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdT +ZWF0dGxlMRUwEwYDVQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVy +aW5nMR4wHAYDVQQDDBVjaGFpbkctSUNBNS1wYXRobGVuMjAxHzAdBgkqhkiG9w0B +CQEWEGluZm9Ad29sZnNzbC5jb22CAWQwDwYDVR0TBAgwBgEB/wIBYzALBgNVHQ8E +BAMCAQYwDQYJKoZIhvcNAQELBQADggEBAHdLBNfm/cG7VQwtI7+QoyCvzVQRNJf7 +BlXBEe7FvP5cNHMI+enDgbgN+mtEze1K0DtAbZblz5Z9qg1l+tdt9z3JneXhXr40 +fbhiDCLhiMgCuJCJnxwdGFwtAcmV9BkBplt6Jmo4cRaHiBk/YDWZcUx5kNv5m3MN +dEWHsU/lY6IhtDgy0njwFaY6rFAqobJB+SsKXFualBdCiERB+qrTF0nBMeuiiR/H +57KwcZhkTtbeucJd3g6GaB2c6nywcu4q+iYmGiGZYAOiAWcOfUoA2SMuwsjIPQR6 +eAiB9+QN3OLbth+KM6tvoQ1fhs23yeE1o8iB2hU83jkwt9PsT9NE/tw= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA5-pathlen20, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA4-pathlen5, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:c9:4b:a0:77:b8:42:43:96:e1:f4:8d:1d:a6:2c: + d8:12:a2:40:49:11:eb:5f:fb:6c:1d:15:3e:af:dd: + 3b:c7:fd:c9:61:43:99:8e:c7:bc:63:bc:5b:93:24: + f3:e5:66:c8:3e:3a:9c:7d:0e:1b:c1:6c:84:8c:90: + b0:11:aa:23:2d:78:99:17:3e:e9:6b:a0:8c:64:fd: + 10:7b:66:ed:b4:3e:b0:96:ef:36:1f:2d:6d:c4:96: + 3c:5a:dc:83:c2:e9:cd:64:d3:5f:c7:ea:db:84:2e: + 24:0c:77:d1:fd:8c:cf:d7:78:af:5b:98:e9:c4:fd: + 66:fa:76:1d:7a:c3:c3:64:32:ad:b9:8b:5a:4c:82: + ed:3a:fe:07:44:20:13:88:df:02:2c:d9:97:21:a4: + 39:a6:f3:7e:8b:e2:c0:cc:86:6b:5a:25:30:d7:f9: + ba:29:ef:1b:2e:f6:3f:c1:7d:b1:0c:95:8e:c0:ce: + 73:41:47:1c:ec:33:44:60:46:9d:b0:75:07:50:c8: + 19:bf:1e:82:c8:c3:3d:d8:e2:19:1e:0b:36:9d:34: + 95:87:ea:a0:1f:e8:80:60:a5:b1:94:42:1e:57:c8: + a0:e6:ad:f8:73:c8:82:e4:38:84:d3:97:fc:85:c4: + de:d2:c0:c5:6d:c7:1e:eb:1d:c1:f1:de:97:27:ca: + be:4b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D4:92:AE:BD:3B:1C:66:4B:17:88:18:15:F8:27:AB:38:CC:07:5A:65 + X509v3 Authority Key Identifier: + keyid:1D:51:80:B6:9A:A7:AC:DD:80:7B:4B:A2:0B:62:BE:E4:87:30:C7:CA + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainG-ICA6-pathlen10/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:5 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + ab:ff:d4:87:51:61:f9:a5:68:8d:4e:fd:01:0c:e3:75:9a:c5: + 16:f2:c4:1e:d8:bd:d4:ce:9e:b9:bd:72:db:f2:89:2b:7a:46: + b4:6c:16:e5:dc:5a:eb:d0:3f:63:a8:98:82:0e:df:c6:1a:40: + a2:1a:a0:d5:49:10:a6:f4:ae:10:61:0a:2e:91:0d:bc:cf:e9: + bf:9e:98:23:38:30:f2:00:e3:ca:47:df:ad:46:e8:7b:b2:ae: + 1e:af:fd:c7:2e:b7:7d:b7:46:df:cd:bf:06:77:19:29:2b:fc: + 7c:f9:f7:2f:59:ce:90:a6:9e:70:33:58:b6:72:a4:ed:63:9b: + 50:62:6c:38:01:73:63:48:4e:6b:34:3f:c4:d5:de:45:09:a9: + 27:d1:78:36:59:1e:21:ad:a9:a3:1f:14:25:d1:ce:ab:90:3f: + c0:82:7a:54:fe:6b:48:fc:52:e1:f4:69:2d:84:2e:1c:7b:6f: + 42:4a:7b:05:91:70:0d:f3:ae:b3:d6:bc:7a:fa:9c:c8:0a:e8: + f1:a0:fa:ee:f3:fe:1d:34:0e:31:79:d8:80:57:53:23:af:65: + 92:94:ef:16:de:e0:9f:0a:5a:17:ba:e8:81:90:e1:e4:24:97: + b4:73:82:4c:38:4c:45:2f:82:75:55:4b:af:b8:58:b3:b1:d1: + 60:ab:53:5f +-----BEGIN CERTIFICATE----- +MIIE1TCCA72gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBojELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHjAcBgNVBAMMFWNo +YWluRy1JQ0E1LXBhdGhsZW4yMDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns +LmNvbTAeFw0xOTEwMTEwMDI4MDlaFw0yMjA3MDcwMDI4MDlaMIGhMQswCQYDVQQG +EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEVMBMG +A1UECgwMd29sZlNTTCBJbmMuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEdMBsGA1UE +AwwUY2hhaW5HLUlDQTQtcGF0aGxlbjUxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s +ZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJS6B3uEJD +luH0jR2mLNgSokBJEetf+2wdFT6v3TvH/clhQ5mOx7xjvFuTJPPlZsg+Opx9DhvB +bISMkLARqiMteJkXPulroIxk/RB7Zu20PrCW7zYfLW3Eljxa3IPC6c1k01/H6tuE +LiQMd9H9jM/XeK9bmOnE/Wb6dh16w8NkMq25i1pMgu06/gdEIBOI3wIs2ZchpDmm +836L4sDMhmtaJTDX+bop7xsu9j/BfbEMlY7AznNBRxzsM0RgRp2wdQdQyBm/HoLI +wz3Y4hkeCzadNJWH6qAf6IBgpbGUQh5XyKDmrfhzyILkOITTl/yFxN7SwMVtxx7r +HcHx3pcnyr5LAgMBAAGjggETMIIBDzAdBgNVHQ4EFgQU1JKuvTscZksXiBgV+Cer +OMwHWmUwgc8GA1UdIwSBxzCBxIAUHVGAtpqnrN2Ae0uiC2K+5Icwx8qhgaikgaUw +gaIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdT +ZWF0dGxlMRUwEwYDVQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVy +aW5nMR4wHAYDVQQDDBVjaGFpbkctSUNBNi1wYXRobGVuMTAxHzAdBgkqhkiG9w0B +CQEWEGluZm9Ad29sZnNzbC5jb22CAWQwDwYDVR0TBAgwBgEB/wIBBTALBgNVHQ8E +BAMCAQYwDQYJKoZIhvcNAQELBQADggEBAKv/1IdRYfmlaI1O/QEM43WaxRbyxB7Y +vdTOnrm9ctvyiSt6RrRsFuXcWuvQP2OomIIO38YaQKIaoNVJEKb0rhBhCi6RDbzP +6b+emCM4MPIA48pH361G6Huyrh6v/ccut323Rt/NvwZ3GSkr/Hz59y9ZzpCmnnAz +WLZypO1jm1BibDgBc2NITms0P8TV3kUJqSfReDZZHiGtqaMfFCXRzquQP8CCelT+ +a0j8UuH0aS2ELhx7b0JKewWRcA3zrrPWvHr6nMgK6PGg+u7z/h00DjF52IBXUyOv +ZZKU7xbe4J8KWhe66IGQ4eQkl7Rzgkw4TEUvgnVVS6+4WLOx0WCrU18= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA6-pathlen10, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA5-pathlen20, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:be:9d:98:a2:41:ca:64:1f:a2:34:dc:51:7d:49: + 2b:f7:f8:7a:fc:1a:22:8d:3a:17:8e:00:9c:74:06: + 18:0f:26:d1:e8:1d:55:4b:3e:bb:6e:98:6d:65:cb: + 6f:be:c5:98:40:65:1d:e1:1d:af:ad:bc:7c:b0:fa: + b6:2a:cb:af:df:d5:52:98:e6:01:01:31:01:3f:c7: + 16:06:44:92:55:43:6f:dd:49:be:aa:52:d2:80:ca: + 3a:d0:72:f3:0a:7e:59:cb:2c:74:7c:5b:19:3d:75: + 9d:3e:da:35:45:49:8b:0d:36:84:80:41:b7:ce:70: + fc:a8:d0:4d:0b:d4:f3:4e:73:87:db:2e:18:20:45: + 70:f3:5a:d1:cf:4f:f8:78:ad:7c:4b:97:3c:f1:0f: + 8a:f6:6c:8f:7a:3a:c9:79:82:2d:bf:ae:80:f8:8b: + 1d:79:17:9b:76:34:97:b1:79:5d:79:fa:30:73:78: + fc:9c:ee:eb:62:20:95:f1:a8:af:1e:4a:91:cc:1e: + 34:90:c7:89:21:41:41:90:09:10:52:dd:21:75:15: + 11:aa:cf:d8:e4:6c:7d:96:c8:d6:cd:90:eb:fa:df: + 86:e7:3d:36:73:18:f3:86:c5:99:0e:0e:f7:e4:09: + 8f:8c:29:f1:ad:15:e9:82:c9:6c:87:fc:00:7b:4b: + 2e:f1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1D:51:80:B6:9A:A7:AC:DD:80:7B:4B:A2:0B:62:BE:E4:87:30:C7:CA + X509v3 Authority Key Identifier: + keyid:14:07:E8:A7:3A:A2:9C:DD:4C:30:B0:4D:F0:00:C4:88:C4:39:DF:73 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainG-ICA7-pathlen100/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:20 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + a4:e7:16:a9:20:7b:9c:89:49:48:94:e7:58:31:71:34:10:35: + d5:b6:91:5f:5e:2d:63:66:48:ff:45:7f:d4:dc:53:39:6f:7b: + 13:0a:de:37:7c:c1:43:e9:f9:b2:71:b8:93:22:12:7f:50:9b: + b9:0c:e4:3a:47:7a:95:bc:a4:08:41:73:f0:a3:9a:88:98:7e: + d0:7c:bb:76:ab:5c:ad:3c:41:73:78:5b:b1:0d:06:ae:46:d2: + 81:af:9a:53:f7:d2:45:66:99:45:5e:2e:05:48:47:78:49:b4: + 27:c9:76:5f:93:be:d4:f7:3d:a7:16:39:ef:dc:a1:57:7f:78: + ca:d3:33:94:87:cb:dd:aa:88:07:0b:62:fa:eb:f0:c9:5f:d8: + 3f:a3:6d:d5:dc:ea:a0:b9:c6:dc:7f:08:46:9e:ed:41:52:46: + d2:7a:96:20:37:f6:69:ef:85:23:43:fa:a8:27:1c:2b:70:37: + 7d:50:ce:48:4b:f7:ce:2d:6a:08:3d:45:f3:a3:e4:1f:ef:1f: + 0e:72:e2:f2:f1:e7:5f:72:1f:84:53:1b:d6:b4:2b:e4:4a:3d: + 39:db:a7:02:6a:02:5e:de:3a:43:05:32:de:16:e9:5e:cf:12: + b2:0e:60:36:e1:47:12:ab:98:ce:ef:c4:76:d5:30:b6:72:ae: + af:13:14:17 +-----BEGIN CERTIFICATE----- +MIIE1zCCA7+gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBojELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHjAcBgNVBAMMFWNo +YWluRy1JQ0E2LXBhdGhsZW4xMDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns +LmNvbTAeFw0xOTEwMTEwMDI4MDlaFw0yMjA3MDcwMDI4MDlaMIGiMQswCQYDVQQG +EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEVMBMG +A1UECgwMd29sZlNTTCBJbmMuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEeMBwGA1UE +AwwVY2hhaW5HLUlDQTUtcGF0aGxlbjIwMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvp2YokHK +ZB+iNNxRfUkr9/h6/BoijToXjgCcdAYYDybR6B1VSz67bphtZctvvsWYQGUd4R2v +rbx8sPq2Ksuv39VSmOYBATEBP8cWBkSSVUNv3Um+qlLSgMo60HLzCn5Zyyx0fFsZ +PXWdPto1RUmLDTaEgEG3znD8qNBNC9TzTnOH2y4YIEVw81rRz0/4eK18S5c88Q+K +9myPejrJeYItv66A+IsdeRebdjSXsXldefowc3j8nO7rYiCV8aivHkqRzB40kMeJ +IUFBkAkQUt0hdRURqs/Y5Gx9lsjWzZDr+t+G5z02cxjzhsWZDg735AmPjCnxrRXp +gslsh/wAe0su8QIDAQABo4IBFDCCARAwHQYDVR0OBBYEFB1RgLaap6zdgHtLogti +vuSHMMfKMIHQBgNVHSMEgcgwgcWAFBQH6Kc6opzdTDCwTfAAxIjEOd9zoYGppIGm +MIGjMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwH +U2VhdHRsZTEVMBMGA1UECgwMd29sZlNTTCBJbmMuMRQwEgYDVQQLDAtFbmdpbmVl +cmluZzEfMB0GA1UEAwwWY2hhaW5HLUlDQTctcGF0aGxlbjEwMDEfMB0GCSqGSIb3 +DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIBZDAPBgNVHRMECDAGAQH/AgEUMAsGA1Ud +DwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEApOcWqSB7nIlJSJTnWDFxNBA11baR +X14tY2ZI/0V/1NxTOW97EwreN3zBQ+n5snG4kyISf1CbuQzkOkd6lbykCEFz8KOa +iJh+0Hy7dqtcrTxBc3hbsQ0GrkbSga+aU/fSRWaZRV4uBUhHeEm0J8l2X5O+1Pc9 +pxY579yhV394ytMzlIfL3aqIBwti+uvwyV/YP6Nt1dzqoLnG3H8IRp7tQVJG0nqW +IDf2ae+FI0P6qCccK3A3fVDOSEv3zi1qCD1F86PkH+8fDnLi8vHnX3IfhFMb1rQr +5Eo9OdunAmoCXt46QwUy3hbpXs8Ssg5gNuFHEquYzu/EdtUwtnKurxMUFw== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA7-pathlen100, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA6-pathlen10, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:e1:4f:c9:e7:30:ea:06:ff:65:cb:2b:6c:f1:a8: + ac:f6:cf:10:6b:80:7a:af:5e:42:0a:0d:61:be:6f: + 14:3c:9f:64:6e:96:46:77:e2:64:a0:0e:d7:56:41: + fc:5b:e6:fe:49:86:1f:8f:20:cc:4b:ec:3a:f1:46: + 74:1a:7e:33:d9:aa:d5:e2:78:09:dd:0c:39:20:7e: + 32:12:96:cd:96:db:10:01:e8:b7:aa:e3:e1:27:5d: + 0a:8f:99:6e:ef:2d:d8:c8:c8:76:aa:d9:00:9d:48: + d9:cf:12:08:97:31:59:c0:4f:a3:e0:ee:5c:a1:35: + ef:94:7c:c6:04:aa:3e:34:a6:43:e0:c8:ed:3d:91: + 53:53:9e:19:03:8e:bf:30:fd:d9:b5:4b:f3:51:0b: + 60:ed:27:e2:b1:dd:15:3c:b0:5f:25:0f:29:9b:5f: + aa:31:64:5e:3d:83:2e:b8:20:66:b9:da:a7:b5:22: + 40:19:3d:24:5d:c3:e7:dd:b6:6b:16:c3:67:23:5d: + 31:65:3b:cb:72:d1:a7:c8:b0:e0:b9:a2:cb:90:86: + 30:d6:ce:7f:9c:b3:b1:c3:34:62:63:c6:b9:66:33: + 6b:5b:a6:00:bb:45:ee:03:07:96:a5:d7:2f:1e:f1: + d2:f2:5e:c2:d2:a1:36:25:f0:7a:70:cb:3d:1d:a4: + 6f:61 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 14:07:E8:A7:3A:A2:9C:DD:4C:30:B0:4D:F0:00:C4:88:C4:39:DF:73 + X509v3 Authority Key Identifier: + keyid:12:E4:A4:19:85:AE:85:B7:D6:EB:63:04:D5:B9:B0:7E:57:5F:0C:16 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:10 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 70:24:57:3f:1a:0c:94:f9:64:14:2e:20:81:bf:02:ba:bb:a5: + 21:02:2b:c0:09:0b:9e:8a:e3:c8:b2:39:4d:05:c1:34:62:44: + 62:5c:d5:ae:0f:17:cf:c0:ab:71:f8:5c:d5:74:8d:3d:eb:90: + d5:d6:a5:97:b8:c1:ab:d7:9c:e7:ca:4f:ee:8f:f2:5d:c7:81: + 22:fc:2e:b0:2d:f2:ff:e3:1a:c5:85:31:21:49:3f:38:f9:5b: + 55:e6:f3:f8:5c:63:fc:9a:c8:76:f0:3d:87:d2:fb:06:6d:5e: + f4:f4:e9:8c:3a:99:7b:1c:8f:29:fb:f6:c3:0c:23:9a:2c:1e: + f4:97:4f:b8:48:37:33:b4:aa:15:a6:5a:75:09:e9:c4:d5:44: + c6:e8:4e:a2:f0:70:a8:9f:10:91:56:55:59:f4:4a:b6:36:4a: + fc:b9:3a:60:01:e6:6e:61:58:f3:b0:ac:cd:02:38:97:bd:eb: + d3:6b:9e:b5:a6:58:ee:ce:86:c2:1b:cf:12:b3:1b:78:00:df: + 5f:da:77:5d:9c:8e:a5:ca:f1:77:87:c1:ed:ad:fd:cf:ea:05: + 53:f9:7e:34:e7:95:23:de:36:36:65:59:08:76:11:6f:d9:6e: + 55:17:af:33:1f:9e:0b:fe:fb:53:5c:67:1a:4d:8a:83:7f:5b: + ca:ff:e4:94 +-----BEGIN CERTIFICATE----- +MIIEyTCCA7GgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluRy1JQ0E3LXBhdGhsZW4xMDAxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMDAyODA5WhcNMjIwNzA3MDAyODA5WjCBojELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHjAcBgNV +BAMMFWNoYWluRy1JQ0E2LXBhdGhsZW4xMDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3 +b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOFPyecw +6gb/ZcsrbPGorPbPEGuAeq9eQgoNYb5vFDyfZG6WRnfiZKAO11ZB/Fvm/kmGH48g +zEvsOvFGdBp+M9mq1eJ4Cd0MOSB+MhKWzZbbEAHot6rj4SddCo+Zbu8t2MjIdqrZ +AJ1I2c8SCJcxWcBPo+DuXKE175R8xgSqPjSmQ+DI7T2RU1OeGQOOvzD92bVL81EL +YO0n4rHdFTywXyUPKZtfqjFkXj2DLrggZrnap7UiQBk9JF3D5922axbDZyNdMWU7 +y3LRp8iw4Lmiy5CGMNbOf5yzscM0YmPGuWYza1umALtF7gMHlqXXLx7x0vJewtKh +NiXwenDLPR2kb2ECAwEAAaOCAQUwggEBMB0GA1UdDgQWBBQUB+inOqKc3UwwsE3w +AMSIxDnfczCBwQYDVR0jBIG5MIG2gBQS5KQZha6Ft9brYwTVubB+V18MFqGBmqSB +lzCBlDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0Jv +emVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgw +FgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29s +ZnNzbC5jb22CAWQwDwYDVR0TBAgwBgEB/wIBCjALBgNVHQ8EBAMCAQYwDQYJKoZI +hvcNAQELBQADggEBAHAkVz8aDJT5ZBQuIIG/Arq7pSECK8AJC56K48iyOU0FwTRi +RGJc1a4PF8/Aq3H4XNV0jT3rkNXWpZe4wavXnOfKT+6P8l3HgSL8LrAt8v/jGsWF +MSFJPzj5W1Xm8/hcY/yayHbwPYfS+wZtXvT06Yw6mXscjyn79sMMI5osHvSXT7hI +NzO0qhWmWnUJ6cTVRMboTqLwcKifEJFWVVn0SrY2Svy5OmAB5m5hWPOwrM0COJe9 +69NrnrWmWO7OhsIbzxKzG3gA31/ad12cjqXK8XeHwe2t/c/qBVP5fjTnlSPeNjZl +WQh2EW/ZblUXrzMfngv++1NcZxpNioN/W8r/5JQ= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA7-pathlen100, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d6:8c:d6:c4:29:20:60:9d:15:3d:0c:2a:fb:24: + 2f:38:89:ed:37:c4:fc:57:67:2a:50:d8:eb:e2:6a: + 1c:59:06:f2:6d:3e:b9:4f:fe:49:c5:21:c0:16:f8: + 29:6f:51:0c:ea:78:d7:0e:15:41:da:5a:cb:0b:e0: + 54:d6:83:fd:0f:e8:4e:30:ff:e4:44:c3:b2:02:f3: + 7d:3a:c6:5c:4e:86:86:2c:74:d4:21:85:c1:fe:4e: + 8b:07:3c:54:1b:54:9e:ec:5a:a5:95:ed:5a:35:e0: + 08:c6:84:7c:e6:ae:71:12:d2:fd:c1:fd:16:0a:3a: + b8:c7:23:4b:af:e0:cd:12:5e:9f:4f:62:13:f0:c8: + e4:e2:a8:01:d3:37:b0:08:21:d3:0f:6c:e4:d8:c1: + 04:51:e9:4c:c5:b1:6d:cc:63:23:97:30:ee:f0:1e: + ab:6d:ea:93:ca:ad:56:6f:1e:ed:1a:ae:8c:1b:91: + 04:ea:ab:9d:1b:3b:56:a7:c1:cc:2f:39:2f:b3:ba: + 8c:16:fd:5e:10:10:9e:24:ea:40:97:74:b6:b4:e5: + 1c:c0:d3:5f:79:2c:04:43:3a:8e:f4:b1:56:bd:c7: + 25:63:5c:34:50:4d:bd:2d:f1:08:bd:8c:3e:d2:6f: + fa:e4:04:a1:51:eb:d0:d0:90:91:97:7b:46:c6:10: + 92:af + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 12:E4:A4:19:85:AE:85:B7:D6:EB:63:04:D5:B9:B0:7E:57:5F:0C:16 + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:100 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + ae:bd:d0:c5:e1:4f:80:0f:85:0d:d2:e0:b5:c3:dc:73:99:94: + 90:19:01:f2:23:66:83:da:92:f2:e8:14:dc:70:e0:20:14:26: + c5:63:88:6a:1b:b3:f3:2f:5c:28:39:1e:6b:a7:40:9b:02:12: + ac:88:06:1e:c6:dd:9d:d4:6a:b8:22:cb:b7:aa:7a:9c:77:9a: + 37:0a:62:54:23:f3:e7:b9:4f:e0:8a:41:bd:74:21:69:be:7c: + 19:50:7d:d1:93:98:7c:4a:06:60:64:72:f0:09:71:6e:86:43: + 2f:89:dc:38:4a:c1:e4:cc:bc:72:6f:c2:b1:c1:9c:38:ff:98: + 87:92:3b:a6:f2:b5:2d:0a:41:38:0d:e7:b5:41:cf:c1:6d:96: + 34:98:9e:97:c8:87:a9:9e:4b:bb:73:bb:34:d6:bd:61:ef:36: + c8:45:f3:c9:31:36:2c:f1:11:68:4b:a0:f8:b6:9d:c4:a6:8a: + dc:e3:fc:60:f7:50:d2:d4:98:d4:e5:f9:76:ca:4a:3c:74:9a: + bb:95:ce:3c:29:ce:be:b5:9e:07:55:e2:c4:a1:1f:b4:0d:eb: + 87:03:1d:79:1b:e2:fc:f3:aa:4b:df:3e:24:72:56:00:b9:b4: + a0:fc:48:80:6a:76:84:1b:79:ea:03:95:32:42:bc:9d:7a:83: + 87:be:51:d2 +-----BEGIN CERTIFICATE----- +MIIEwzCCA6ugAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA5WhcNMjIwNzA3MDAyODA5WjCBozELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNoYWluRy1JQ0E3 +LXBhdGhsZW4xMDAxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWjNbEKSBgnRU9DCr7JC84ie03 +xPxXZypQ2OviahxZBvJtPrlP/knFIcAW+ClvUQzqeNcOFUHaWssL4FTWg/0P6E4w +/+REw7IC8306xlxOhoYsdNQhhcH+TosHPFQbVJ7sWqWV7Vo14AjGhHzmrnES0v3B +/RYKOrjHI0uv4M0SXp9PYhPwyOTiqAHTN7AIIdMPbOTYwQRR6UzFsW3MYyOXMO7w +Hqtt6pPKrVZvHu0arowbkQTqq50bO1anwcwvOS+zuowW/V4QEJ4k6kCXdLa05RzA +0195LARDOo70sVa9xyVjXDRQTb0t8Qi9jD7Sb/rkBKFR69DQkJGXe0bGEJKvAgMB +AAGjggENMIIBCTAdBgNVHQ4EFgQUEuSkGYWuhbfW62ME1bmwfldfDBYwgckGA1Ud +IwSBwTCBvoAUJ45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYT +AlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQK +DAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1 +jhDeuPswDwYDVR0TBAgwBgEB/wIBZDALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEL +BQADggEBAK690MXhT4APhQ3S4LXD3HOZlJAZAfIjZoPakvLoFNxw4CAUJsVjiGob +s/MvXCg5HmunQJsCEqyIBh7G3Z3Uargiy7eqepx3mjcKYlQj8+e5T+CKQb10IWm+ +fBlQfdGTmHxKBmBkcvAJcW6GQy+J3DhKweTMvHJvwrHBnDj/mIeSO6bytS0KQTgN +57VBz8FtljSYnpfIh6meS7tzuzTWvWHvNshF88kxNizxEWhLoPi2ncSmitzj/GD3 +UNLUmNTl+XbKSjx0mruVzjwpzr61ngdV4sShH7QN64cDHXkb4vzzqkvfPiRyVgC5 +tKD8SIBqdoQbeeoDlTJCvJ16g4e+UdI= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-entity-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-entity-key.pem new file mode 100644 index 000000000..1a169591c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-entity-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAu3uCI6I058uJTmTM8pjIZY/iaVVUSzyLwB9nN38Jy57fXnX2 +mYMSrBUjz2SkEBalEK8ohgAgTvNN/Qj7oacYTBMeTZAu5prjKAO09IPO/aKphlYC +YjOfbph+D8wGcTGKk9LZox0IepL4fr+QX6HmK2RYu6aayRmX/cmp9wgnivO+4tuI +JYSREwbiY7zhN4J+b1ra8OLroSqPXVIRr+L1iUJ5g7jApZXcQsYckFEeM/PxwuTS +e4fDZJC3X5s479LQT9VRquA60cMBA+cysSfGSFrArCaNlGF2+Jj/MG2qVcNj/aSk +Gzxr6AV1QRddrckXm8NNbp99fTb+wKOZ1uWSrQIDAQABAoIBAFw5+p/q2Fm6b1YI +EiW48MO9TyR/3FKSezDMgerz7G6lPb5rCx8jMllCoPYRzP85FIQrliStBTexSokS +FS7FUxeBRCPlrJy2Ts5NXIP4Hyf4D6rMvqluOZyfGUxOElE2jLQBQhySWKxrhiBb +vfq9Wsu3tkrBP11z4Kfwv1KNSV55h2g/xDPl443d3VqwiLFAY6YESHsy3eXdWKYT +AiCddq7FQo+nHHUpVoUtHr23LLyanVcgu9j9fNusQn7GGVSFKvPLuSpZwMuggAtX +K7t93ItX7nhSx5jvWn2xxrDBV/3Xj6N4+uaZCI/5kuzEdM9NDEEJPxHKg8LNltnE +8su+8CECgYEA58PPdmPLtPrllVBtuasoIMoKPg4DDCe6BnrS2eEXoiu9vYVsbRYk +OPbSnlZ50uoex+tKogynFeDVYW0dM4xWSFyd5DmuLnA0Ivbt/mKhTbizg/Lnphlb ++ICseYkOikrNzbhDZUCthzPgw7R5QW20D3CDOI3KxEC1zcrTHG6vJvUCgYEAzxZJ +hM/lQKg5/KfXOynZGZ1XzZtDN9s+QAqbrQPxzcsFZxeXhBVv0GVPAp1OiTAYFopY +whFPTwjxpAsu4BYVpc6vGBRCHoG1JOYYF9F2bCoCNQ8PDeJOcyD2mIRD+FJt2lin +qyb63Jieq9xtLuOZGNwPzyqmo6zCaznmRk8dOdkCgYAeGhCYD94lY3DuM8QMmW5c +0+EArlE3AvHmZY19Pv8S0RuTwgCTKo0J2QUCC7lG66GT1bub0IjjDpCoVsO0LkYG +oADh45v77BbZc7j1kVnh/ltSh/oOWLzZSd0c6/A3hf+0+HnIbN4c8WAACzC0jssU +NkjUz5XGZ6E1WWKSDs4xAQKBgG+uhVerBugn0Z4ApoKxvvOhd4jbAxVMl/XRwsM8 +LVve8br3bi89oF+zQzkVvRUfat49HkELNMpa+HaP0WfogSQ6oxNJWZ86NIcB0FyI +CmWrAiW7SVMjiUttq4/1RPLXAYeP6FzVWNU/OdNVvUxcUmSlyaDgT55VvUQ2pYml +gQ2BAoGAYNysHrNKaBB57C2QX+WYpvrPmsLm70Zy8SeHaFBGdmFx3lZsUufJNfyt +kLzfSbZZ2X5Ab94U43mZoDcxZLGB3JKIWTUe6ubECVcV3IblgdzqdV26a3wde119 +IlmOeskz7C48fZ4sO6KTcoNEUU+28L8noIn6nYHVJ2Q/FGlOx38= +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-entity.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-entity.pem new file mode 100644 index 000000000..d563eef64 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainG-entity.pem @@ -0,0 +1,87 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-ICA1-pathlen0, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainG-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bb:7b:82:23:a2:34:e7:cb:89:4e:64:cc:f2:98: + c8:65:8f:e2:69:55:54:4b:3c:8b:c0:1f:67:37:7f: + 09:cb:9e:df:5e:75:f6:99:83:12:ac:15:23:cf:64: + a4:10:16:a5:10:af:28:86:00:20:4e:f3:4d:fd:08: + fb:a1:a7:18:4c:13:1e:4d:90:2e:e6:9a:e3:28:03: + b4:f4:83:ce:fd:a2:a9:86:56:02:62:33:9f:6e:98: + 7e:0f:cc:06:71:31:8a:93:d2:d9:a3:1d:08:7a:92: + f8:7e:bf:90:5f:a1:e6:2b:64:58:bb:a6:9a:c9:19: + 97:fd:c9:a9:f7:08:27:8a:f3:be:e2:db:88:25:84: + 91:13:06:e2:63:bc:e1:37:82:7e:6f:5a:da:f0:e2: + eb:a1:2a:8f:5d:52:11:af:e2:f5:89:42:79:83:b8: + c0:a5:95:dc:42:c6:1c:90:51:1e:33:f3:f1:c2:e4: + d2:7b:87:c3:64:90:b7:5f:9b:38:ef:d2:d0:4f:d5: + 51:aa:e0:3a:d1:c3:01:03:e7:32:b1:27:c6:48:5a: + c0:ac:26:8d:94:61:76:f8:98:ff:30:6d:aa:55:c3: + 63:fd:a4:a4:1b:3c:6b:e8:05:75:41:17:5d:ad:c9: + 17:9b:c3:4d:6e:9f:7d:7d:36:fe:c0:a3:99:d6:e5: + 92:ad + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 21:3A:72:3B:95:38:DF:99:DE:62:25:21:D0:14:81:6E:CA:AA:FB:A1 + X509v3 Authority Key Identifier: + keyid:47:C0:19:4B:ED:C4:DA:97:B1:60:EA:5A:0A:42:6D:A5:D3:D8:25:31 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainG-ICA2-pathlen1/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 06:c8:08:8c:cc:5d:4e:b5:81:35:06:f3:e5:9d:4e:c8:38:3f: + ec:87:8b:55:3c:fc:6e:4c:f8:3c:78:7d:46:03:33:a7:49:55: + 6c:13:37:e9:11:d5:dd:8c:51:70:2c:28:18:6a:01:63:9b:35: + 04:ba:79:49:95:10:ed:31:4b:70:5f:be:a4:67:d4:8d:2f:95: + 45:f7:1f:3d:a0:fc:29:db:55:65:8d:98:ae:79:ad:ce:c7:b9: + 97:54:9d:69:ca:fa:87:01:fb:0d:9b:57:67:b8:44:f6:91:14: + e5:31:b5:c1:d8:96:b7:1d:7a:05:ed:53:d5:04:8a:8b:8e:74: + f1:13:3d:93:d6:16:10:17:d7:de:b1:4e:13:e8:72:ae:83:91: + 1f:46:3e:86:bd:49:79:9c:99:a9:aa:67:ff:cf:7c:34:b1:2c: + d8:bf:e5:3a:22:c2:70:97:47:db:d0:05:77:e9:46:09:f0:c1: + 06:1c:61:df:8b:8f:6d:a6:5b:d5:ae:9a:52:71:ed:5e:9e:38: + e3:8c:9a:52:cf:8a:8f:20:e9:f1:e4:a3:11:bd:b9:ff:a9:1e: + b7:f9:83:26:18:a8:0b:7b:2b:74:f5:c5:3a:58:e1:0b:71:0a: + 3d:ef:15:ee:2c:28:b3:ba:0e:59:3c:a4:46:24:d3:b7:14:b5: + 4a:8f:c1:25 +-----BEGIN CERTIFICATE----- +MIIEtzCCA5+gAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluRy1JQ0ExLXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgZoxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRYwFAYDVQQD +DA1jaGFpbkctZW50aXR5MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu3uCI6I058uJTmTM8pjI +ZY/iaVVUSzyLwB9nN38Jy57fXnX2mYMSrBUjz2SkEBalEK8ohgAgTvNN/Qj7oacY +TBMeTZAu5prjKAO09IPO/aKphlYCYjOfbph+D8wGcTGKk9LZox0IepL4fr+QX6Hm +K2RYu6aayRmX/cmp9wgnivO+4tuIJYSREwbiY7zhN4J+b1ra8OLroSqPXVIRr+L1 +iUJ5g7jApZXcQsYckFEeM/PxwuTSe4fDZJC3X5s479LQT9VRquA60cMBA+cysSfG +SFrArCaNlGF2+Jj/MG2qVcNj/aSkGzxr6AV1QRddrckXm8NNbp99fTb+wKOZ1uWS +rQIDAQABo4H+MIH7MB0GA1UdDgQWBBQhOnI7lTjfmd5iJSHQFIFuyqr7oTCBzgYD +VR0jBIHGMIHDgBRHwBlL7cTal7Fg6loKQm2l09glMaGBp6SBpDCBoTELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNV +BAMMFGNoYWluRy1JQ0EyLXBhdGhsZW4xMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tggFkMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBAAbICIzM +XU61gTUG8+WdTsg4P+yHi1U8/G5M+Dx4fUYDM6dJVWwTN+kR1d2MUXAsKBhqAWOb +NQS6eUmVEO0xS3BfvqRn1I0vlUX3Hz2g/CnbVWWNmK55rc7HuZdUnWnK+ocB+w2b +V2e4RPaRFOUxtcHYlrcdegXtU9UEiouOdPETPZPWFhAX196xThPocq6DkR9GPoa9 +SXmcmamqZ//PfDSxLNi/5ToiwnCXR9vQBXfpRgnwwQYcYd+Lj22mW9WumlJx7V6e +OOOMmlLPio8g6fHkoxG9uf+pHrf5gyYYqAt7K3T1xTpY4QtxCj3vFe4sKLO6Dlk8 +pEYk07cUtUqPwSU= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA1-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA1-key.pem new file mode 100644 index 000000000..adc22e260 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA1-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAx/SmfvLLT24EGNNT1c+/fpfRdJT+261hPxIgZ/MQg3tRQ6MM +ILc1Y/EK7ll0gnL70dQScewOj2nJ+6+nL8Q7LGY0q6yAwm1KDlT+9j46ACWEp8tC +1ehHBJTkaMP1Mq0hidhe+Yjufc6Roxb8h3YfLx1MsS89TfQKbAT9Sc9RiEnEA2Vj +HsjxNB1ENFiv9eyQKoypOHvc+l/tAO0IU033NhDtcUGq47/oXe5ONjlXfvT9w/eK +Ug/xN3IrrpB3ANZ87OzujfhL+zkKRUmBMUE/qbt7HIrPMQnHlKdwStS76mE9mqGO +G4sCOx8fxIXpf2MM6uWRg6hbJTR8qGjrl290mQIDAQABAoIBAASHGa4OOWRXDWiy +gFd7GM75CRkmto6q4mTXODyiWGFhzXlGm+Oxwle9AY5cIDND/0fFEZXazomYz6YP +WC3Qt7ZNqiupAFFmwCKK8isJRa7zKonSJHVLiTAlXvawWUEIgpXofF4SJ7RZlRqo +TpeSqSob87yfYTf+qq2/fyzIsQPw/WBIoB6z3tDRQ61j60KG1P8ILoOiu4znzxUn +DTquyJ+zVmqDJCTcLZWWz+tam70iFEE+Khx3MKlEXpIFRXlQdPIe7F0CW9MZb5vY +JyJunI9T+wqdklWJBVFUBm/KINdgp86snE0X5eeGeensBhWkW+EeZCEULHfdd6Lk +nor0CAECgYEA+N3WRBxpW5GJF4BKCmDxtpRoth5u+RtQAkmAAR/ts1gEr6y8Q4e3 +KUE+T6CEYgDGwZyIII1zJjIWZuicnC0U0u/tg94yj9JIk2roGR4KLGRhIilN9EC5 +x6cQDe27Le4+LcYmyHzjvRq9pdWG1WYjGXOJuD1kqKk4OS6aZsoLPEECgYEAza/o +wUgRWXvsaahlemDd83xn/t0c5rGhg7yT8uQFTRlllGRWtrZfRKwlCfELXmvtIgzL +/Prmbnp8OlsGkp5KlumzFdMvKlANqxMA+prZZ89D25t/n8AfNKeqvtv3om0LDS99 +tXSHAvu+YbbFHXi99qlWzaKtASQEoUHe1OtPAlkCgYBaSxKMj8piIMGetzsl3NqW +Je5/9TbKRvCWg9hfkBgMM+kvW/rKfZkk7LkQ5uphLGrwoDx7oxaeSxn5qHf56hle +FxMT/zBVIjSW1/jx9AY46Qqc/GN+NWWyXJjklNaO6ZvBu90ibL2sROF+I6TSFEaz +20migRPeZdcyWAhJNxEwgQKBgG7y31M645joPqrzmeF8VNzdE1+nt8o8sMnVs9yF +4NIoy+FSim++Sf9J+CS3sBE7mEsQqgwI7rlTOqVjqlT2K3fiEabJJpzlV6oa8yE6 +2+CiLZFM/HeYc3y8oF6ZWqdzuE1he6agd59FWfltVEBEe/uMdnUvtbBy1EiDtoYV +c6XpAoGBALacGB7IEzI0DkP+WdzXnZ0Dhgqg+RwEQgzJl2Aq/qLxOr3Ci6Qzc5/1 +MWFEdKcoDPLC9VvIMu9YeNGE7GGZs4XKftiqyL3ZCg4TWDFkDrUt9rcmmmnqTtPl +r4zF4TPZyCygAFmlhaW6SyMp8Wgl/ysAqwlnlZBnxVLT+J5B0Rfz +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA1-pathlen0.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA1-pathlen0.pem new file mode 100644 index 000000000..974ddd46a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA1-pathlen0.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA2-pathlen2, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:10 2019 GMT + Not After : Jul 7 00:28:10 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA1-pathlen0, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:c7:f4:a6:7e:f2:cb:4f:6e:04:18:d3:53:d5:cf: + bf:7e:97:d1:74:94:fe:db:ad:61:3f:12:20:67:f3: + 10:83:7b:51:43:a3:0c:20:b7:35:63:f1:0a:ee:59: + 74:82:72:fb:d1:d4:12:71:ec:0e:8f:69:c9:fb:af: + a7:2f:c4:3b:2c:66:34:ab:ac:80:c2:6d:4a:0e:54: + fe:f6:3e:3a:00:25:84:a7:cb:42:d5:e8:47:04:94: + e4:68:c3:f5:32:ad:21:89:d8:5e:f9:88:ee:7d:ce: + 91:a3:16:fc:87:76:1f:2f:1d:4c:b1:2f:3d:4d:f4: + 0a:6c:04:fd:49:cf:51:88:49:c4:03:65:63:1e:c8: + f1:34:1d:44:34:58:af:f5:ec:90:2a:8c:a9:38:7b: + dc:fa:5f:ed:00:ed:08:53:4d:f7:36:10:ed:71:41: + aa:e3:bf:e8:5d:ee:4e:36:39:57:7e:f4:fd:c3:f7: + 8a:52:0f:f1:37:72:2b:ae:90:77:00:d6:7c:ec:ec: + ee:8d:f8:4b:fb:39:0a:45:49:81:31:41:3f:a9:bb: + 7b:1c:8a:cf:31:09:c7:94:a7:70:4a:d4:bb:ea:61: + 3d:9a:a1:8e:1b:8b:02:3b:1f:1f:c4:85:e9:7f:63: + 0c:ea:e5:91:83:a8:5b:25:34:7c:a8:68:eb:97:6f: + 74:99 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 48:80:87:28:EF:E6:28:0F:03:9B:DF:33:48:10:A0:E5:20:B3:69:50 + X509v3 Authority Key Identifier: + keyid:80:49:61:8C:1D:13:08:56:B5:42:68:D5:B2:EA:89:2C:B4:8B:05:87 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainH-ICA3-pathlen2/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:0 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 5f:77:d6:d2:55:4e:25:be:4b:f4:9f:9d:a8:ff:92:ac:4d:19: + 1f:0b:50:5b:51:01:7f:b8:a2:56:0d:cd:0c:c8:66:7a:08:bf: + 1e:07:6a:a5:6d:ad:68:c4:bb:da:99:d7:f3:62:bb:b5:28:de: + 47:dc:e2:b0:e1:27:cd:14:4b:7d:1c:7d:1a:60:eb:37:6f:fc: + ff:4e:1f:9f:ce:52:da:b4:a7:f4:6c:92:b5:65:b5:8f:53:1b: + d8:bd:7d:f6:a8:7e:23:9f:7d:b6:09:18:f2:a3:17:55:aa:fe: + 57:87:3d:a9:18:52:76:6e:fe:7c:ed:2a:85:45:63:d3:4d:7b: + f2:5e:ff:0f:a7:ae:24:ef:5f:71:66:25:29:31:9e:4a:12:a0: + 56:5b:39:2c:79:64:d0:1a:fb:97:99:df:42:9c:23:b4:f1:1d: + be:fc:da:41:16:b1:a0:fc:3a:b8:6e:a7:cf:3c:21:ea:22:7c: + f6:d2:a1:25:96:1e:b9:2f:eb:bf:61:c2:ee:58:c6:a1:7e:d0: + 73:e3:fd:58:62:ca:44:95:2b:b1:a8:d0:f8:1a:0d:40:9a:fb: + b1:27:4b:fc:57:4c:32:b5:09:5e:6e:ac:1d:dc:bc:77:f5:1b: + 27:88:40:df:70:da:f7:28:32:ef:8f:2e:53:41:78:69:e9:3e: + 7b:64:da:e4 +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluSC1JQ0EyLXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgxMFoXDTIyMDcwNzAwMjgxMFowgaExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR0wGwYDVQQD +DBRjaGFpbkgtSUNBMS1wYXRobGVuMDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm +c3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMf0pn7yy09u +BBjTU9XPv36X0XSU/tutYT8SIGfzEIN7UUOjDCC3NWPxCu5ZdIJy+9HUEnHsDo9p +yfuvpy/EOyxmNKusgMJtSg5U/vY+OgAlhKfLQtXoRwSU5GjD9TKtIYnYXvmI7n3O +kaMW/Id2Hy8dTLEvPU30CmwE/UnPUYhJxANlYx7I8TQdRDRYr/XskCqMqTh73Ppf +7QDtCFNN9zYQ7XFBquO/6F3uTjY5V370/cP3ilIP8TdyK66QdwDWfOzs7o34S/s5 +CkVJgTFBP6m7exyKzzEJx5SncErUu+phPZqhjhuLAjsfH8SF6X9jDOrlkYOoWyU0 +fKho65dvdJkCAwEAAaOCARIwggEOMB0GA1UdDgQWBBRIgIco7+YoDwOb3zNIEKDl +ILNpUDCBzgYDVR0jBIHGMIHDgBSASWGMHRMIVrVCaNWy6okstIsFh6GBp6SBpDCB +oTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1Nl +YXR0bGUxFTATBgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJp +bmcxHTAbBgNVBAMMFGNoYWluSC1JQ0EzLXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkB +FhBpbmZvQHdvbGZzc2wuY29tggFkMA8GA1UdEwQIMAYBAf8CAQAwCwYDVR0PBAQD +AgEGMA0GCSqGSIb3DQEBCwUAA4IBAQBfd9bSVU4lvkv0n52o/5KsTRkfC1BbUQF/ +uKJWDc0MyGZ6CL8eB2qlba1oxLvamdfzYru1KN5H3OKw4SfNFEt9HH0aYOs3b/z/ +Th+fzlLatKf0bJK1ZbWPUxvYvX32qH4jn322CRjyoxdVqv5Xhz2pGFJ2bv587SqF +RWPTTXvyXv8Pp64k719xZiUpMZ5KEqBWWzkseWTQGvuXmd9CnCO08R2+/NpBFrGg +/Dq4bqfPPCHqInz20qEllh65L+u/YcLuWMahftBz4/1YYspElSuxqND4Gg1Amvux +J0v8V0wytQlebqwd3Lx39RsniEDfcNr3KDLvjy5TQXhp6T57ZNrk +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA2-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA2-key.pem new file mode 100644 index 000000000..74120de90 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA2-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA2bWvS7qDAyPfUCiowgws8ATLLQSbHvX0aLzUjrTNRgSi9RSe +PjPWdi1U+dVBtXpHkxpUgKQ9i52A6hw6OrvR1Lbx8qO9nl24hQHXyKAn9mdBlMWV +kRHLlvyVqby1vlh3XCub6SR+i24Qp9U6+gUhJxTY0l+iWBK02b2IGvHnTJ1gMQsf +P4uvOtnKz9RzG7iwPdWWXU6jYo9W6z1M8CFP9IzHVd2m3NkVoRLbc02/GIlCkg6D +vk+q7o+o76EnAXMWKcDojCPI/5VozVNnSeVzsexiYFEg6KZJKPUrFjDoi6Yv9Lc3 +mYwyMJddFr9rXro0H9YbLvx58ABhqqB6L3vSgwIDAQABAoIBAHOkqqTTQdxdJbXy +oxHQXd5w7WvQUoWzqEwqYc4cBB35QIZmmVf5OSY1FjpPKUQ42+QrzE847uhGlb/F +lri0I9WWCBcXGxYQOn+MZw7O4+tjFdbszXHtvfNJ4EX1U6T0YRK4p2zEUePGZ1p/ +TYCZUO7th+7Xleiqpx4yKyYE8RQkWbHCknAOpgYDAQKFdMn1y6oVTihP0QH5FnLK +xnqea9I/U3qEnpSzvDHTMZqAmEPke6//ie44el6vw2Ai93kP3Ct0J6E2uD4xK2tH +tzmNiLUF/3fCSA/WD2FMAaONi6OQGWmVBfoexa8sxY/E3pO1OOY39Eu4ET9h70TB +LS0oPIECgYEA7IISCRoeTsKvIX7YTPBMb5274fl+v9VGQZr4MrPbD4n58/fRlx0T +el5t53LQSk0theSu388Df4u9ft7EJGAqPruYfwJHOwobm0zuYcYl568STmkRkC2Z +P/IyJz+HRA6VGZrihqe5TKF5065yRjsT49O6wYjV6xgJgtLjwTgphfECgYEA66b/ +4USR5SgAuPvAS1rKqcGJzdJ1Expf4HwecQ8G/botXDFscmXVMJ50GUmwLU/eOca8 +MhXQTEc+R3tUNAwYiGWYfZ522wydeLHCdH0YRpodMyII0zkFN6K/0Qq0POjgC4sN +ygrDKTqd9TW/jX/8OxfUcPK+tyV6sI2Mhry+27MCgYBnHQp5924xToYGZ4QsfzQE +EdQhYKKXRof8AHGnwWyHqNNWP7ycUqv0VQk7uH4Bdwaa8qofn+TZjfZPQxZm+ZpR +gX6qGTcvEWgZ3H+uFzLdgSHNF9f1cTv4ekLNg9AYpvbwk+uhY6zRMTGpTcw6vHUe +hmhNCrihZ/h1ljaAPlk0MQKBgQChX0AUtE8wXN95zbRWJftomkdS8g8IIOSNJpH2 +HDNOZ0MOwi2gfUmrvKaGdqa1sN7eM9DGf5ef1J26d6Mm7S2Tofb19yEvSglAEIK4 +IL4SAxGB5Ymjk4WWHtY6QZlBqLtcTEIKHKqevixTMhZVwNIqaVwqaKDfbEQDSTt1 +PSV57wKBgDDcqeUafap/pJlUyISHxb06etZnvAmpt5N7POaCcZ9uYBE/eya9alGA +18tMB0TcBXnmuXmP+GPVlZrc/uu7psC+Fs7a2/d1dnpGmzAP9KD+riC8/ILBXaoh +Izs5E2WMKU8uV9cTG89P/qK8NXCa+m35RuBMDAYO7aAVQkBn17JC +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA2-pathlen2.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA2-pathlen2.pem new file mode 100644 index 000000000..31230193c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA2-pathlen2.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA3-pathlen2, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA2-pathlen2, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d9:b5:af:4b:ba:83:03:23:df:50:28:a8:c2:0c: + 2c:f0:04:cb:2d:04:9b:1e:f5:f4:68:bc:d4:8e:b4: + cd:46:04:a2:f5:14:9e:3e:33:d6:76:2d:54:f9:d5: + 41:b5:7a:47:93:1a:54:80:a4:3d:8b:9d:80:ea:1c: + 3a:3a:bb:d1:d4:b6:f1:f2:a3:bd:9e:5d:b8:85:01: + d7:c8:a0:27:f6:67:41:94:c5:95:91:11:cb:96:fc: + 95:a9:bc:b5:be:58:77:5c:2b:9b:e9:24:7e:8b:6e: + 10:a7:d5:3a:fa:05:21:27:14:d8:d2:5f:a2:58:12: + b4:d9:bd:88:1a:f1:e7:4c:9d:60:31:0b:1f:3f:8b: + af:3a:d9:ca:cf:d4:73:1b:b8:b0:3d:d5:96:5d:4e: + a3:62:8f:56:eb:3d:4c:f0:21:4f:f4:8c:c7:55:dd: + a6:dc:d9:15:a1:12:db:73:4d:bf:18:89:42:92:0e: + 83:be:4f:aa:ee:8f:a8:ef:a1:27:01:73:16:29:c0: + e8:8c:23:c8:ff:95:68:cd:53:67:49:e5:73:b1:ec: + 62:60:51:20:e8:a6:49:28:f5:2b:16:30:e8:8b:a6: + 2f:f4:b7:37:99:8c:32:30:97:5d:16:bf:6b:5e:ba: + 34:1f:d6:1b:2e:fc:79:f0:00:61:aa:a0:7a:2f:7b: + d2:83 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 80:49:61:8C:1D:13:08:56:B5:42:68:D5:B2:EA:89:2C:B4:8B:05:87 + X509v3 Authority Key Identifier: + keyid:56:54:36:BE:23:2F:20:89:6D:A6:BA:9A:45:A4:88:0E:40:35:FD:F5 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainH-ICA4-pathlen2/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:2 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 16:6f:a3:cd:f6:de:87:1c:86:f8:b4:b8:e6:e0:dc:11:2f:f3: + bb:f1:57:34:ec:1a:59:8a:81:63:40:01:df:53:24:a7:50:b0: + 6d:3d:29:2a:41:e7:08:71:0f:37:4b:10:b5:95:ae:a0:81:ba: + ba:b5:3e:72:48:be:6b:9e:be:34:3b:0d:15:f8:8f:9d:24:68: + 01:0c:d4:4a:0d:86:d5:b3:71:b6:d6:8e:71:44:16:7e:e3:db: + ba:7d:0e:5f:b3:2f:e2:60:f9:ff:bc:91:a6:ae:3c:ba:30:e4: + f5:55:bf:1e:72:0b:cc:5e:b4:7e:1f:09:aa:b4:52:bd:8c:2c: + 37:d0:0d:82:b4:ec:ff:c1:cf:91:a2:43:24:b8:b4:c0:ac:f2: + 29:eb:84:1d:49:ef:a4:8f:65:b3:06:01:2f:23:cf:a6:27:42: + cd:99:17:b9:69:40:1d:df:99:f6:f8:c4:61:cc:4a:a1:f0:38: + ce:4e:c4:27:f6:8f:d2:ae:74:5f:39:93:66:77:55:b2:25:8d: + 7e:7f:7d:b4:2b:f1:ee:83:9e:7b:f5:31:3f:d7:27:53:e6:21: + bd:69:a5:ca:0e:d8:6e:54:67:56:bf:f3:ec:e8:e1:aa:a4:76: + fa:0d:42:d4:7d:26:bd:f5:e5:25:ee:81:c4:ed:59:eb:0a:54: + d3:c9:18:30 +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluSC1JQ0EzLXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgaExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR0wGwYDVQQD +DBRjaGFpbkgtSUNBMi1wYXRobGVuMjEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm +c3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANm1r0u6gwMj +31AoqMIMLPAEyy0Emx719Gi81I60zUYEovUUnj4z1nYtVPnVQbV6R5MaVICkPYud +gOocOjq70dS28fKjvZ5duIUB18igJ/ZnQZTFlZERy5b8lam8tb5Yd1wrm+kkfotu +EKfVOvoFIScU2NJfolgStNm9iBrx50ydYDELHz+LrzrZys/Ucxu4sD3Vll1Oo2KP +Vus9TPAhT/SMx1XdptzZFaES23NNvxiJQpIOg75Pqu6PqO+hJwFzFinA6IwjyP+V +aM1TZ0nlc7HsYmBRIOimSSj1KxYw6IumL/S3N5mMMjCXXRa/a166NB/WGy78efAA +Yaqgei970oMCAwEAAaOCARIwggEOMB0GA1UdDgQWBBSASWGMHRMIVrVCaNWy6oks +tIsFhzCBzgYDVR0jBIHGMIHDgBRWVDa+Iy8giW2muppFpIgOQDX99aGBp6SBpDCB +oTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1Nl +YXR0bGUxFTATBgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJp +bmcxHTAbBgNVBAMMFGNoYWluSC1JQ0E0LXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkB +FhBpbmZvQHdvbGZzc2wuY29tggFkMA8GA1UdEwQIMAYBAf8CAQIwCwYDVR0PBAQD +AgEGMA0GCSqGSIb3DQEBCwUAA4IBAQAWb6PN9t6HHIb4tLjm4NwRL/O78Vc07BpZ +ioFjQAHfUySnULBtPSkqQecIcQ83SxC1la6ggbq6tT5ySL5rnr40Ow0V+I+dJGgB +DNRKDYbVs3G21o5xRBZ+49u6fQ5fsy/iYPn/vJGmrjy6MOT1Vb8ecgvMXrR+Hwmq +tFK9jCw30A2CtOz/wc+RokMkuLTArPIp64QdSe+kj2WzBgEvI8+mJ0LNmRe5aUAd +35n2+MRhzEqh8DjOTsQn9o/SrnRfOZNmd1WyJY1+f320K/Hug5579TE/1ydT5iG9 +aaXKDthuVGdWv/Ps6OGqpHb6DULUfSa99eUl7oHE7VnrClTTyRgw +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA3-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA3-key.pem new file mode 100644 index 000000000..8128e7d32 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA3-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAt7MaG0qAG6LllRS8VeR33PN7ip80fJPbycnQi7iHRWXToX1G +83CSqddm7zu0qBaw8L5ncKpFewm8ynfbV6QkVAsa2l+tZKPxSYO8n13EtNpDBKrM +w7BNwvFzyTgNTMmr298Js1wVC2Z5rWxj0TjMpi1Gg84ZHcELbvw4t9iMom8ph5sh +zbBr4PgfA9uCHY2YYxa2dEdDIPKhSxaLZ/28c3ib+d26SdlgqbeFZn+kKgXILZOg +m6q/pjHh8sjTG3t50bZsrjtrAC5urhDcbIjcG5PoVpmNRn5JOoegswDMLjuD4Ws5 +FnFHRzBta2ycn+bO7CAvj8Fd79OEMmylzHj+oQIDAQABAoIBABWgBOu/inM2avZw +2Xb3DVE6bIm2EjS0J0SK+HzqPSpjQVWabNbNosZRsDFrguniufOtRnoR4VoJnGrt +TynzDb/DCuc4Ki5VylrQIk1UeYqcwxTykmZbA9x2Fh5S9eXbO9sHV5oAtg2Ag8Rx +pRKFMDpDzDBJ+9Tv28u172tdF7krT7mDQ+Qtiw8XaGIfudutgz16j+QEy/7G+elo +9ZyAtvUENTy+8/ds5hjwuSUUf7krIgJYj3UibYVHgZepJ7skkc8gMGEFCRYgI9p1 +SheBWQvVZUYHw7WJ/QOsCWPRVS++OtcS0LWQ5MSilbGjlDlWLL2Qxhd4Zh15l+yf +2gz26U0CgYEA58tbPKbyOJ9J4IvwZpQaJlZLCJzKyk6JAAI9gSnGUhfBCQ7VOprK +QWMDFQKTSd9THZcdQZ4MeO5jGvBm9b5PUdq+fuAVr6eYBFOAUZEDY9qJELHmQb9X +9hAH/1Oe/MZ2hTC0DlYkJLS7KwmD6arGmQ092WtmTLk2supqFTyLd48CgYEAyuIC +3BxxLTrDZgD9dTb7Kb8W9P+Do4qbg1drRdsftUra54i1Uhy6/PiiHqLZLhIxjIJE +zbJD90osUm9cV+3FKRHhFTf8DTNzAsXFcxsd7FouAwgL3eJYHOQvGGbS9gbdKlCQ +rtYl+BTaHzw0fdX0X9JKgas5iKxRto/9TK1+js8CgYEAys2F2h9HNntHrAtEHrvd +1UUTCUoFs9Pa0gMjxOrD9feKkV5E+a2M4IC8pZlHPQ8ELZOVqV+bEgOg+mTz8Ha9 +96Qnn+J3luRPgRl939+805TU76J3D3dWgpesJ50GMauC7y2ZnCGKJgNq71C39a3R +bP/E6YGqU96JGSk3/7SlYckCgYAKGeyohuX/qYBXEM+NyXoB3xjGg/5K4zjQ9kZK +CRnwDdUOWBknCHUq6ToxKkyD5bX/1/CTCUAnDNNeG1tOqXD6lYBObSYohhpA1hX5 +oC0COo816W2l04ItlhLeNShlxXu3gqFhgxoK2wbtLTMz3LY5GyBIinzn2CSNYWfs +LGszswKBgQCtvS5okoPtkuhxb4T93fCtBbP1EJVSNaHPtBN42iY++hr9vfQo8VpN +p/pWrC7NQGjqvEzI2sKZbQZVsqvKGjLWB0i4CiFURXgm7hsp3syrpQ1InNKgV1dk +PAib3V9HdSDF/kxRuqppICK3r3qXYBBmtggHV96wzggHhHklSrSCHg== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA3-pathlen2.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA3-pathlen2.pem new file mode 100644 index 000000000..7f4dd677b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA3-pathlen2.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA4-pathlen2, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA3-pathlen2, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b7:b3:1a:1b:4a:80:1b:a2:e5:95:14:bc:55:e4: + 77:dc:f3:7b:8a:9f:34:7c:93:db:c9:c9:d0:8b:b8: + 87:45:65:d3:a1:7d:46:f3:70:92:a9:d7:66:ef:3b: + b4:a8:16:b0:f0:be:67:70:aa:45:7b:09:bc:ca:77: + db:57:a4:24:54:0b:1a:da:5f:ad:64:a3:f1:49:83: + bc:9f:5d:c4:b4:da:43:04:aa:cc:c3:b0:4d:c2:f1: + 73:c9:38:0d:4c:c9:ab:db:df:09:b3:5c:15:0b:66: + 79:ad:6c:63:d1:38:cc:a6:2d:46:83:ce:19:1d:c1: + 0b:6e:fc:38:b7:d8:8c:a2:6f:29:87:9b:21:cd:b0: + 6b:e0:f8:1f:03:db:82:1d:8d:98:63:16:b6:74:47: + 43:20:f2:a1:4b:16:8b:67:fd:bc:73:78:9b:f9:dd: + ba:49:d9:60:a9:b7:85:66:7f:a4:2a:05:c8:2d:93: + a0:9b:aa:bf:a6:31:e1:f2:c8:d3:1b:7b:79:d1:b6: + 6c:ae:3b:6b:00:2e:6e:ae:10:dc:6c:88:dc:1b:93: + e8:56:99:8d:46:7e:49:3a:87:a0:b3:00:cc:2e:3b: + 83:e1:6b:39:16:71:47:47:30:6d:6b:6c:9c:9f:e6: + ce:ec:20:2f:8f:c1:5d:ef:d3:84:32:6c:a5:cc:78: + fe:a1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 56:54:36:BE:23:2F:20:89:6D:A6:BA:9A:45:A4:88:0E:40:35:FD:F5 + X509v3 Authority Key Identifier: + keyid:18:6D:44:83:EE:1F:EC:B4:22:F0:9C:EB:54:1E:4A:15:58:01:AA:13 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:2 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 2a:35:ca:d5:dd:97:31:4d:29:21:90:67:ba:68:ef:2a:56:b0: + 08:0a:c5:a2:cc:30:11:71:59:1b:59:2b:ca:c4:cc:22:52:d7: + f3:a7:d2:14:c5:fc:e4:c5:6f:9d:45:ce:7f:d0:dd:ec:5f:6b: + c3:d1:78:7a:29:bb:73:98:b6:15:9b:41:37:7a:50:b3:04:1d: + 72:90:9b:e9:f2:4b:68:f3:60:e9:bb:34:6e:2a:6c:6c:50:a6: + 38:ac:61:bc:ca:25:23:f5:f5:70:3a:8a:33:94:cf:97:1c:5c: + a3:76:b0:7b:88:35:8a:6e:18:44:01:e6:80:23:e9:14:ea:66: + 56:34:9a:0b:ca:1a:37:c8:e7:00:03:39:7d:73:e5:13:cb:be: + 9e:df:c6:87:c3:24:a7:7f:39:1d:cc:ca:1f:e7:14:38:fe:3d: + 06:7a:2f:95:f3:9a:79:49:e9:9c:f3:72:e5:b4:b5:fb:87:13: + 83:4f:9f:76:2f:41:8f:a4:55:1d:e4:74:2f:0a:0f:cd:ee:a8: + 50:06:1e:a7:9e:25:9f:f3:9d:b2:c1:44:de:c5:44:3e:42:64: + e1:75:16:33:56:a7:93:68:bb:fa:96:46:33:de:58:c1:81:42: + ca:1c:28:4f:09:71:db:60:e1:88:ac:d6:0d:37:3a:63:8d:50: + b7:35:2d:e5 +-----BEGIN CERTIFICATE----- +MIIExjCCA66gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluSC1JQ0E0LXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgaExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR0wGwYDVQQD +DBRjaGFpbkgtSUNBMy1wYXRobGVuMjEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm +c3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALezGhtKgBui +5ZUUvFXkd9zze4qfNHyT28nJ0Iu4h0Vl06F9RvNwkqnXZu87tKgWsPC+Z3CqRXsJ +vMp321ekJFQLGtpfrWSj8UmDvJ9dxLTaQwSqzMOwTcLxc8k4DUzJq9vfCbNcFQtm +ea1sY9E4zKYtRoPOGR3BC278OLfYjKJvKYebIc2wa+D4HwPbgh2NmGMWtnRHQyDy +oUsWi2f9vHN4m/nduknZYKm3hWZ/pCoFyC2ToJuqv6Yx4fLI0xt7edG2bK47awAu +bq4Q3GyI3BuT6FaZjUZ+STqHoLMAzC47g+FrORZxR0cwbWtsnJ/mzuwgL4/BXe/T +hDJspcx4/qECAwEAAaOCAQUwggEBMB0GA1UdDgQWBBRWVDa+Iy8giW2muppFpIgO +QDX99TCBwQYDVR0jBIG5MIG2gBQYbUSD7h/stCLwnOtUHkoVWAGqE6GBmqSBlzCB +lDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVt +YW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYD +VQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb22CAWQwDwYDVR0TBAgwBgEB/wIBAjALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN +AQELBQADggEBACo1ytXdlzFNKSGQZ7po7ypWsAgKxaLMMBFxWRtZK8rEzCJS1/On +0hTF/OTFb51Fzn/Q3exfa8PReHopu3OYthWbQTd6ULMEHXKQm+nyS2jzYOm7NG4q +bGxQpjisYbzKJSP19XA6ijOUz5ccXKN2sHuINYpuGEQB5oAj6RTqZlY0mgvKGjfI +5wADOX1z5RPLvp7fxofDJKd/OR3Myh/nFDj+PQZ6L5XzmnlJ6ZzzcuW0tfuHE4NP +n3YvQY+kVR3kdC8KD83uqFAGHqeeJZ/znbLBRN7FRD5CZOF1FjNWp5Nou/qWRjPe +WMGBQsocKE8Jcdtg4Yis1g03OmONULc1LeU= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA4-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA4-key.pem new file mode 100644 index 000000000..91ef6cf8f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA4-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAu/Mvis2eh/EB86TALWY21xEuZAjo8Zn6ppz0vTtHctIOWJ0+ +Uufao0N4w8OT5gTTq1GKGiQOemJZqsZCnmbBYV4xsU3cN6kYdo3+ywlUP0+7X6u6 +cOm0oV6gaX5FP8DMeOnydGR5wmoW0JgwgkRKs5ksZjCsmYIEKr8PYIkENvop0whW +YWqoM0CaU30gqFFvm6DZPtyaix03nq3J/VOnBNwfNj7TZVKEJGHQTuJBYL/7/bIE +sz/rFJlevOh96WXRP/4ESeW7oy3j25bf2YGgMtcBubgCjrmiHwrUJBc6GQ9tOhBf +XH24VoLHf0DwLYdjwbHYZMc8JxNKY4IhsfI56QIDAQABAoIBAFR1/Vhn/KTkdlcS +I1aDh4NwciN8KYphAtWa1RSwrfP4V4AU8av6CzOxH3UBz9XfN2vWkbQbnfH7foYS +4F8kmCR0WuptrdfJgnfMacK+J4DoCLD+kCMrswONbZLarq3uqzRvFYiemmT2ndgR +fEMeA1/gJqapmvbFCbBX+cYM7LrzPIt7vsgg1u9hyNPVznWqKlukfCtQD1cmjeyr +qG54AWvhD9sQPCtLsoC7D0mPn5Yh37gbT6A724BevSsSfSZSzqOxvl+NLZpk7vRW +dH4ZmdY6We7fVRZUY48bsjVK8k44aMhu8Xlj4vhDOxEiLStthdOnyNEulddJ/tH0 +QfDyiZ0CgYEA8UXWpgMnO3TWIQz2d3FUfHx1q21aefyHjNW0KFeUMWpI0rgTYkqi +HdFXYFsAD5t8MJaBbUHk3Czze9xSfgRnvku7fFaKmtrwFSzSccxXu9Mlm87ilpyo +EuNHJOoWSbq6oEG7F9JKg8so0V0vmWr1fI1VZarMiypcnEK2MezoPe8CgYEAx2wd +8jkUn9O/3/HdfKLUTcbJIVrxIdd0N9WyHASc7Oh2vOSrc+y3UhN35FRywaqwKf52 +pV86Uy6GFbHZkE/OHBOphtpRKkufWblZ4T89YYmHIl3gFmyIH/djQcNiwhAGG7l/ +hEMXz/aWfhRA3chYKEQAjEYUdtGVU5RsHMkuXacCgYBiDHibhIKIBgYS7lqm1ZZ4 +9Hc5UDpJgpdvY1VQY67kmgW4JHg0JJJXPcCddr3CmfRRJoi4ZuPjmhzkw/d+ILos +OkiZ0e2H2ttgL5PiDSHGQZtyAxRQEp+29UfvN3YRRmIbSDsJBjuj7YbL9mumlDHp +COKga1WuZGu4UOALz/PdXwKBgFgyAKx3gh+NTnaESSgt+ybKm3kc9ze4SbXH1JV/ +lMdRp/GyUAFc11Z9NbDNiFMOYgqwd1h73Reco8BEf6vLH6RbLcZuFydVeov75Tww +87yHTjRswAYqyakZh9Q1zR92Zr0sNLER2x4mODhaTLXJPPPR30wqUjKaTihAo++3 +KcJRAoGBAJGLpOLNckpY2tzOmFRPjCrIRa1b3f4PzNPJ15p+g6jVcnzjnIraJ+4M +R3ELPL7a/jhJJ5JsqQrg2BcSfPQitxgflaU/qsiUR0WFckPO4BQ4qx1X0bSgNxhO +bh9fipjlH39U+UV4N9CR7Bkw+p1wLUF4ZR4ElAHAzgrh6WdZZGEX +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA4-pathlen2.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA4-pathlen2.pem new file mode 100644 index 000000000..df74193db --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-ICA4-pathlen2.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA4-pathlen2, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bb:f3:2f:8a:cd:9e:87:f1:01:f3:a4:c0:2d:66: + 36:d7:11:2e:64:08:e8:f1:99:fa:a6:9c:f4:bd:3b: + 47:72:d2:0e:58:9d:3e:52:e7:da:a3:43:78:c3:c3: + 93:e6:04:d3:ab:51:8a:1a:24:0e:7a:62:59:aa:c6: + 42:9e:66:c1:61:5e:31:b1:4d:dc:37:a9:18:76:8d: + fe:cb:09:54:3f:4f:bb:5f:ab:ba:70:e9:b4:a1:5e: + a0:69:7e:45:3f:c0:cc:78:e9:f2:74:64:79:c2:6a: + 16:d0:98:30:82:44:4a:b3:99:2c:66:30:ac:99:82: + 04:2a:bf:0f:60:89:04:36:fa:29:d3:08:56:61:6a: + a8:33:40:9a:53:7d:20:a8:51:6f:9b:a0:d9:3e:dc: + 9a:8b:1d:37:9e:ad:c9:fd:53:a7:04:dc:1f:36:3e: + d3:65:52:84:24:61:d0:4e:e2:41:60:bf:fb:fd:b2: + 04:b3:3f:eb:14:99:5e:bc:e8:7d:e9:65:d1:3f:fe: + 04:49:e5:bb:a3:2d:e3:db:96:df:d9:81:a0:32:d7: + 01:b9:b8:02:8e:b9:a2:1f:0a:d4:24:17:3a:19:0f: + 6d:3a:10:5f:5c:7d:b8:56:82:c7:7f:40:f0:2d:87: + 63:c1:b1:d8:64:c7:3c:27:13:4a:63:82:21:b1:f2: + 39:e9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 18:6D:44:83:EE:1F:EC:B4:22:F0:9C:EB:54:1E:4A:15:58:01:AA:13 + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:2 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 61:c0:d8:c4:02:cd:b4:54:d3:44:e9:06:78:0b:a2:16:b5:4a: + b6:b5:09:f1:d1:fc:9f:be:e5:12:0b:6c:61:8d:66:3f:ce:8f: + 95:98:24:ea:d2:99:3a:4f:89:e3:2d:a9:f7:69:cb:05:9e:90: + af:5a:f1:93:ac:ee:fe:78:f8:e3:22:fa:69:7f:e4:71:1d:c9: + 1e:ac:61:81:8d:93:33:bc:b2:e4:67:75:97:9d:af:0a:db:ab: + 24:3f:8d:1d:16:c6:05:c6:89:a7:5f:cf:2d:73:39:de:8f:40: + 94:4b:7a:a4:ea:35:1e:70:ce:3a:f5:75:76:e5:ab:e4:8a:9a: + a4:a1:ec:49:59:3d:b7:23:fa:3c:af:dd:09:d7:aa:47:60:11: + 07:07:f4:8b:a1:40:b2:d9:bb:0f:88:b8:d1:a5:e2:88:22:76: + 8b:45:d6:96:2c:45:11:98:04:85:22:99:1f:49:a7:30:b0:b0: + 74:c3:ea:1a:a6:53:ed:c9:48:40:1a:d8:02:a8:fb:35:3a:f7: + 69:42:b2:75:dd:98:41:30:a9:e3:b1:ec:c6:66:f1:61:16:5b: + f6:e3:bc:31:8e:46:66:fa:39:34:66:cc:95:1d:69:15:12:41: + 16:ce:e6:a6:d4:4c:eb:f4:99:b4:6d:66:99:76:ae:5a:e8:24: + 92:a7:ef:45 +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA5WhcNMjIwNzA3MDAyODA5WjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluSC1JQ0E0 +LXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu/Mvis2eh/EB86TALWY21xEuZAjo +8Zn6ppz0vTtHctIOWJ0+Uufao0N4w8OT5gTTq1GKGiQOemJZqsZCnmbBYV4xsU3c +N6kYdo3+ywlUP0+7X6u6cOm0oV6gaX5FP8DMeOnydGR5wmoW0JgwgkRKs5ksZjCs +mYIEKr8PYIkENvop0whWYWqoM0CaU30gqFFvm6DZPtyaix03nq3J/VOnBNwfNj7T +ZVKEJGHQTuJBYL/7/bIEsz/rFJlevOh96WXRP/4ESeW7oy3j25bf2YGgMtcBubgC +jrmiHwrUJBc6GQ9tOhBfXH24VoLHf0DwLYdjwbHYZMc8JxNKY4IhsfI56QIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFBhtRIPuH+y0IvCc61QeShVYAaoTMIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQBhwNjEAs20VNNE6QZ4C6IWtUq2tQnx0fyfvuUSC2xhjWY/zo+VmCTq0pk6 +T4njLan3acsFnpCvWvGTrO7+ePjjIvppf+RxHckerGGBjZMzvLLkZ3WXna8K26sk +P40dFsYFxomnX88tcznej0CUS3qk6jUecM469XV25avkipqkoexJWT23I/o8r90J +16pHYBEHB/SLoUCy2bsPiLjRpeKIInaLRdaWLEURmASFIpkfSacwsLB0w+oaplPt +yUhAGtgCqPs1OvdpQrJ13ZhBMKnjsezGZvFhFlv247wxjkZm+jk0ZsyVHWkVEkEW +zuam1Ezr9Jm0bWaZdq5a6CSSp+9F +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-assembled.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-assembled.pem new file mode 100644 index 000000000..bbf203142 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-assembled.pem @@ -0,0 +1,443 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA1-pathlen0, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:10 2019 GMT + Not After : Jul 7 00:28:10 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:ba:ed:ab:c0:0d:92:6c:10:e4:50:9f:7c:98:cc: + 87:fd:28:34:77:c0:58:28:52:2c:28:97:80:ec:78: + 02:4f:f4:ca:60:f8:1d:e7:6a:04:52:2e:75:85:42: + 74:76:00:e4:70:84:b8:51:8e:29:2e:7f:b6:ad:df: + 6d:09:b4:4f:11:54:1e:88:16:e2:0e:af:30:f0:3d: + a7:da:9f:4e:0d:94:5b:05:51:9c:cc:05:65:8d:6b: + 1e:3c:79:5b:26:7e:cb:ae:e9:9a:71:69:92:41:9b: + 1a:cd:b4:53:0b:fb:2e:40:c4:e3:b1:5e:b8:8b:f8: + cf:0a:ec:5f:07:10:18:54:f8:8a:7d:35:97:7a:7a: + 98:ea:93:2d:1b:e6:44:16:3f:cc:a7:4c:b9:cf:b5: + 0b:09:47:b3:b8:8e:02:1a:56:69:37:b7:49:a4:59: + 90:a3:20:88:f3:87:77:e8:39:0d:39:36:a5:56:b3: + ec:4b:f3:5e:8b:c2:cd:47:0c:d9:56:ce:32:f7:71: + 33:db:7f:7d:c6:1e:7e:71:c1:01:06:98:9e:52:98: + 9d:d7:9d:4a:32:94:3c:5a:42:66:00:ca:e2:a3:35: + db:b7:f3:27:0b:9c:fa:1b:99:4b:51:fa:6c:25:90: + f5:76:8c:d9:0d:80:8c:ac:61:eb:4d:92:12:6d:5f: + 12:e5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + ED:62:FB:8F:91:CB:DE:B0:C8:89:CE:BA:B5:80:A8:47:F1:72:16:05 + X509v3 Authority Key Identifier: + keyid:48:80:87:28:EF:E6:28:0F:03:9B:DF:33:48:10:A0:E5:20:B3:69:50 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainH-ICA2-pathlen2/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + bc:fc:a7:c3:c9:a4:57:9e:37:9d:f7:71:eb:5b:7c:a2:1a:0d: + 24:97:12:92:18:fd:0f:5e:5b:f9:27:c9:98:2c:9a:06:bd:77: + 85:63:3c:a4:ed:90:92:3a:79:41:82:c3:54:66:f6:c6:a0:d3: + ba:a3:19:93:d9:5f:54:90:fc:2b:37:d1:96:88:ba:be:e1:71: + 8c:a2:24:d7:ce:d8:7c:5e:87:9f:4f:f2:52:51:1c:82:5b:2c: + 8b:b4:5d:7e:d6:03:95:a0:e9:29:68:5e:76:18:2b:93:6f:a1: + 58:a6:f6:35:8b:37:b9:6b:82:5d:3a:8c:bc:a6:bd:18:ca:2f: + ea:0c:4d:36:7a:58:80:52:9c:b3:fa:a4:2b:0e:97:e6:0f:fc: + 41:62:6d:45:19:15:6d:3e:16:e5:bc:81:ce:c0:34:d3:b5:d4: + 0c:54:a5:62:a6:55:57:ad:e8:6f:94:58:cb:31:ff:0f:1c:13: + 63:82:91:1f:a3:68:f5:9f:9c:d9:dd:54:e0:d0:36:ea:ad:2a: + 9d:4e:66:be:c7:2f:1a:16:70:be:b4:1b:c5:2d:b2:1b:0c:87: + 64:10:4d:db:8b:79:5b:2e:10:a4:95:25:7b:be:b2:21:26:47: + e9:d2:74:c8:34:b1:e3:7b:73:8c:93:7a:82:ce:50:d4:46:34: + ab:11:71:c0 +-----BEGIN CERTIFICATE----- +MIIEtzCCA5+gAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluSC1JQ0ExLXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgxMFoXDTIyMDcwNzAwMjgxMFowgZoxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRYwFAYDVQQD +DA1jaGFpbkgtZW50aXR5MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuu2rwA2SbBDkUJ98mMyH +/Sg0d8BYKFIsKJeA7HgCT/TKYPgd52oEUi51hUJ0dgDkcIS4UY4pLn+2rd9tCbRP +EVQeiBbiDq8w8D2n2p9ODZRbBVGczAVljWsePHlbJn7LrumacWmSQZsazbRTC/su +QMTjsV64i/jPCuxfBxAYVPiKfTWXenqY6pMtG+ZEFj/Mp0y5z7ULCUezuI4CGlZp +N7dJpFmQoyCI84d36DkNOTalVrPsS/Nei8LNRwzZVs4y93Ez2399xh5+ccEBBpie +Upid151KMpQ8WkJmAMriozXbt/MnC5z6G5lLUfpsJZD1dozZDYCMrGHrTZISbV8S +5QIDAQABo4H+MIH7MB0GA1UdDgQWBBTtYvuPkcvesMiJzrq1gKhH8XIWBTCBzgYD +VR0jBIHGMIHDgBRIgIco7+YoDwOb3zNIEKDlILNpUKGBp6SBpDCBoTELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNV +BAMMFGNoYWluSC1JQ0EyLXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tggFkMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBALz8p8PJ +pFeeN533cetbfKIaDSSXEpIY/Q9eW/knyZgsmga9d4VjPKTtkJI6eUGCw1Rm9sag +07qjGZPZX1SQ/Cs30ZaIur7hcYyiJNfO2Hxeh59P8lJRHIJbLIu0XX7WA5Wg6Slo +XnYYK5NvoVim9jWLN7lrgl06jLymvRjKL+oMTTZ6WIBSnLP6pCsOl+YP/EFibUUZ +FW0+FuW8gc7ANNO11AxUpWKmVVet6G+UWMsx/w8cE2OCkR+jaPWfnNndVODQNuqt +Kp1OZr7HLxoWcL60G8UtshsMh2QQTduLeVsuEKSVJXu+siEmR+nSdMg0seN7c4yT +eoLOUNRGNKsRccA= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA2-pathlen2, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:10 2019 GMT + Not After : Jul 7 00:28:10 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA1-pathlen0, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:c7:f4:a6:7e:f2:cb:4f:6e:04:18:d3:53:d5:cf: + bf:7e:97:d1:74:94:fe:db:ad:61:3f:12:20:67:f3: + 10:83:7b:51:43:a3:0c:20:b7:35:63:f1:0a:ee:59: + 74:82:72:fb:d1:d4:12:71:ec:0e:8f:69:c9:fb:af: + a7:2f:c4:3b:2c:66:34:ab:ac:80:c2:6d:4a:0e:54: + fe:f6:3e:3a:00:25:84:a7:cb:42:d5:e8:47:04:94: + e4:68:c3:f5:32:ad:21:89:d8:5e:f9:88:ee:7d:ce: + 91:a3:16:fc:87:76:1f:2f:1d:4c:b1:2f:3d:4d:f4: + 0a:6c:04:fd:49:cf:51:88:49:c4:03:65:63:1e:c8: + f1:34:1d:44:34:58:af:f5:ec:90:2a:8c:a9:38:7b: + dc:fa:5f:ed:00:ed:08:53:4d:f7:36:10:ed:71:41: + aa:e3:bf:e8:5d:ee:4e:36:39:57:7e:f4:fd:c3:f7: + 8a:52:0f:f1:37:72:2b:ae:90:77:00:d6:7c:ec:ec: + ee:8d:f8:4b:fb:39:0a:45:49:81:31:41:3f:a9:bb: + 7b:1c:8a:cf:31:09:c7:94:a7:70:4a:d4:bb:ea:61: + 3d:9a:a1:8e:1b:8b:02:3b:1f:1f:c4:85:e9:7f:63: + 0c:ea:e5:91:83:a8:5b:25:34:7c:a8:68:eb:97:6f: + 74:99 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 48:80:87:28:EF:E6:28:0F:03:9B:DF:33:48:10:A0:E5:20:B3:69:50 + X509v3 Authority Key Identifier: + keyid:80:49:61:8C:1D:13:08:56:B5:42:68:D5:B2:EA:89:2C:B4:8B:05:87 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainH-ICA3-pathlen2/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:0 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 5f:77:d6:d2:55:4e:25:be:4b:f4:9f:9d:a8:ff:92:ac:4d:19: + 1f:0b:50:5b:51:01:7f:b8:a2:56:0d:cd:0c:c8:66:7a:08:bf: + 1e:07:6a:a5:6d:ad:68:c4:bb:da:99:d7:f3:62:bb:b5:28:de: + 47:dc:e2:b0:e1:27:cd:14:4b:7d:1c:7d:1a:60:eb:37:6f:fc: + ff:4e:1f:9f:ce:52:da:b4:a7:f4:6c:92:b5:65:b5:8f:53:1b: + d8:bd:7d:f6:a8:7e:23:9f:7d:b6:09:18:f2:a3:17:55:aa:fe: + 57:87:3d:a9:18:52:76:6e:fe:7c:ed:2a:85:45:63:d3:4d:7b: + f2:5e:ff:0f:a7:ae:24:ef:5f:71:66:25:29:31:9e:4a:12:a0: + 56:5b:39:2c:79:64:d0:1a:fb:97:99:df:42:9c:23:b4:f1:1d: + be:fc:da:41:16:b1:a0:fc:3a:b8:6e:a7:cf:3c:21:ea:22:7c: + f6:d2:a1:25:96:1e:b9:2f:eb:bf:61:c2:ee:58:c6:a1:7e:d0: + 73:e3:fd:58:62:ca:44:95:2b:b1:a8:d0:f8:1a:0d:40:9a:fb: + b1:27:4b:fc:57:4c:32:b5:09:5e:6e:ac:1d:dc:bc:77:f5:1b: + 27:88:40:df:70:da:f7:28:32:ef:8f:2e:53:41:78:69:e9:3e: + 7b:64:da:e4 +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluSC1JQ0EyLXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgxMFoXDTIyMDcwNzAwMjgxMFowgaExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR0wGwYDVQQD +DBRjaGFpbkgtSUNBMS1wYXRobGVuMDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm +c3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMf0pn7yy09u +BBjTU9XPv36X0XSU/tutYT8SIGfzEIN7UUOjDCC3NWPxCu5ZdIJy+9HUEnHsDo9p +yfuvpy/EOyxmNKusgMJtSg5U/vY+OgAlhKfLQtXoRwSU5GjD9TKtIYnYXvmI7n3O +kaMW/Id2Hy8dTLEvPU30CmwE/UnPUYhJxANlYx7I8TQdRDRYr/XskCqMqTh73Ppf +7QDtCFNN9zYQ7XFBquO/6F3uTjY5V370/cP3ilIP8TdyK66QdwDWfOzs7o34S/s5 +CkVJgTFBP6m7exyKzzEJx5SncErUu+phPZqhjhuLAjsfH8SF6X9jDOrlkYOoWyU0 +fKho65dvdJkCAwEAAaOCARIwggEOMB0GA1UdDgQWBBRIgIco7+YoDwOb3zNIEKDl +ILNpUDCBzgYDVR0jBIHGMIHDgBSASWGMHRMIVrVCaNWy6okstIsFh6GBp6SBpDCB +oTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1Nl +YXR0bGUxFTATBgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJp +bmcxHTAbBgNVBAMMFGNoYWluSC1JQ0EzLXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkB +FhBpbmZvQHdvbGZzc2wuY29tggFkMA8GA1UdEwQIMAYBAf8CAQAwCwYDVR0PBAQD +AgEGMA0GCSqGSIb3DQEBCwUAA4IBAQBfd9bSVU4lvkv0n52o/5KsTRkfC1BbUQF/ +uKJWDc0MyGZ6CL8eB2qlba1oxLvamdfzYru1KN5H3OKw4SfNFEt9HH0aYOs3b/z/ +Th+fzlLatKf0bJK1ZbWPUxvYvX32qH4jn322CRjyoxdVqv5Xhz2pGFJ2bv587SqF +RWPTTXvyXv8Pp64k719xZiUpMZ5KEqBWWzkseWTQGvuXmd9CnCO08R2+/NpBFrGg +/Dq4bqfPPCHqInz20qEllh65L+u/YcLuWMahftBz4/1YYspElSuxqND4Gg1Amvux +J0v8V0wytQlebqwd3Lx39RsniEDfcNr3KDLvjy5TQXhp6T57ZNrk +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA3-pathlen2, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA2-pathlen2, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d9:b5:af:4b:ba:83:03:23:df:50:28:a8:c2:0c: + 2c:f0:04:cb:2d:04:9b:1e:f5:f4:68:bc:d4:8e:b4: + cd:46:04:a2:f5:14:9e:3e:33:d6:76:2d:54:f9:d5: + 41:b5:7a:47:93:1a:54:80:a4:3d:8b:9d:80:ea:1c: + 3a:3a:bb:d1:d4:b6:f1:f2:a3:bd:9e:5d:b8:85:01: + d7:c8:a0:27:f6:67:41:94:c5:95:91:11:cb:96:fc: + 95:a9:bc:b5:be:58:77:5c:2b:9b:e9:24:7e:8b:6e: + 10:a7:d5:3a:fa:05:21:27:14:d8:d2:5f:a2:58:12: + b4:d9:bd:88:1a:f1:e7:4c:9d:60:31:0b:1f:3f:8b: + af:3a:d9:ca:cf:d4:73:1b:b8:b0:3d:d5:96:5d:4e: + a3:62:8f:56:eb:3d:4c:f0:21:4f:f4:8c:c7:55:dd: + a6:dc:d9:15:a1:12:db:73:4d:bf:18:89:42:92:0e: + 83:be:4f:aa:ee:8f:a8:ef:a1:27:01:73:16:29:c0: + e8:8c:23:c8:ff:95:68:cd:53:67:49:e5:73:b1:ec: + 62:60:51:20:e8:a6:49:28:f5:2b:16:30:e8:8b:a6: + 2f:f4:b7:37:99:8c:32:30:97:5d:16:bf:6b:5e:ba: + 34:1f:d6:1b:2e:fc:79:f0:00:61:aa:a0:7a:2f:7b: + d2:83 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 80:49:61:8C:1D:13:08:56:B5:42:68:D5:B2:EA:89:2C:B4:8B:05:87 + X509v3 Authority Key Identifier: + keyid:56:54:36:BE:23:2F:20:89:6D:A6:BA:9A:45:A4:88:0E:40:35:FD:F5 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainH-ICA4-pathlen2/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:2 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 16:6f:a3:cd:f6:de:87:1c:86:f8:b4:b8:e6:e0:dc:11:2f:f3: + bb:f1:57:34:ec:1a:59:8a:81:63:40:01:df:53:24:a7:50:b0: + 6d:3d:29:2a:41:e7:08:71:0f:37:4b:10:b5:95:ae:a0:81:ba: + ba:b5:3e:72:48:be:6b:9e:be:34:3b:0d:15:f8:8f:9d:24:68: + 01:0c:d4:4a:0d:86:d5:b3:71:b6:d6:8e:71:44:16:7e:e3:db: + ba:7d:0e:5f:b3:2f:e2:60:f9:ff:bc:91:a6:ae:3c:ba:30:e4: + f5:55:bf:1e:72:0b:cc:5e:b4:7e:1f:09:aa:b4:52:bd:8c:2c: + 37:d0:0d:82:b4:ec:ff:c1:cf:91:a2:43:24:b8:b4:c0:ac:f2: + 29:eb:84:1d:49:ef:a4:8f:65:b3:06:01:2f:23:cf:a6:27:42: + cd:99:17:b9:69:40:1d:df:99:f6:f8:c4:61:cc:4a:a1:f0:38: + ce:4e:c4:27:f6:8f:d2:ae:74:5f:39:93:66:77:55:b2:25:8d: + 7e:7f:7d:b4:2b:f1:ee:83:9e:7b:f5:31:3f:d7:27:53:e6:21: + bd:69:a5:ca:0e:d8:6e:54:67:56:bf:f3:ec:e8:e1:aa:a4:76: + fa:0d:42:d4:7d:26:bd:f5:e5:25:ee:81:c4:ed:59:eb:0a:54: + d3:c9:18:30 +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluSC1JQ0EzLXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgaExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR0wGwYDVQQD +DBRjaGFpbkgtSUNBMi1wYXRobGVuMjEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm +c3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANm1r0u6gwMj +31AoqMIMLPAEyy0Emx719Gi81I60zUYEovUUnj4z1nYtVPnVQbV6R5MaVICkPYud +gOocOjq70dS28fKjvZ5duIUB18igJ/ZnQZTFlZERy5b8lam8tb5Yd1wrm+kkfotu +EKfVOvoFIScU2NJfolgStNm9iBrx50ydYDELHz+LrzrZys/Ucxu4sD3Vll1Oo2KP +Vus9TPAhT/SMx1XdptzZFaES23NNvxiJQpIOg75Pqu6PqO+hJwFzFinA6IwjyP+V +aM1TZ0nlc7HsYmBRIOimSSj1KxYw6IumL/S3N5mMMjCXXRa/a166NB/WGy78efAA +Yaqgei970oMCAwEAAaOCARIwggEOMB0GA1UdDgQWBBSASWGMHRMIVrVCaNWy6oks +tIsFhzCBzgYDVR0jBIHGMIHDgBRWVDa+Iy8giW2muppFpIgOQDX99aGBp6SBpDCB +oTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1Nl +YXR0bGUxFTATBgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJp +bmcxHTAbBgNVBAMMFGNoYWluSC1JQ0E0LXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkB +FhBpbmZvQHdvbGZzc2wuY29tggFkMA8GA1UdEwQIMAYBAf8CAQIwCwYDVR0PBAQD +AgEGMA0GCSqGSIb3DQEBCwUAA4IBAQAWb6PN9t6HHIb4tLjm4NwRL/O78Vc07BpZ +ioFjQAHfUySnULBtPSkqQecIcQ83SxC1la6ggbq6tT5ySL5rnr40Ow0V+I+dJGgB +DNRKDYbVs3G21o5xRBZ+49u6fQ5fsy/iYPn/vJGmrjy6MOT1Vb8ecgvMXrR+Hwmq +tFK9jCw30A2CtOz/wc+RokMkuLTArPIp64QdSe+kj2WzBgEvI8+mJ0LNmRe5aUAd +35n2+MRhzEqh8DjOTsQn9o/SrnRfOZNmd1WyJY1+f320K/Hug5579TE/1ydT5iG9 +aaXKDthuVGdWv/Ps6OGqpHb6DULUfSa99eUl7oHE7VnrClTTyRgw +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA4-pathlen2, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA3-pathlen2, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b7:b3:1a:1b:4a:80:1b:a2:e5:95:14:bc:55:e4: + 77:dc:f3:7b:8a:9f:34:7c:93:db:c9:c9:d0:8b:b8: + 87:45:65:d3:a1:7d:46:f3:70:92:a9:d7:66:ef:3b: + b4:a8:16:b0:f0:be:67:70:aa:45:7b:09:bc:ca:77: + db:57:a4:24:54:0b:1a:da:5f:ad:64:a3:f1:49:83: + bc:9f:5d:c4:b4:da:43:04:aa:cc:c3:b0:4d:c2:f1: + 73:c9:38:0d:4c:c9:ab:db:df:09:b3:5c:15:0b:66: + 79:ad:6c:63:d1:38:cc:a6:2d:46:83:ce:19:1d:c1: + 0b:6e:fc:38:b7:d8:8c:a2:6f:29:87:9b:21:cd:b0: + 6b:e0:f8:1f:03:db:82:1d:8d:98:63:16:b6:74:47: + 43:20:f2:a1:4b:16:8b:67:fd:bc:73:78:9b:f9:dd: + ba:49:d9:60:a9:b7:85:66:7f:a4:2a:05:c8:2d:93: + a0:9b:aa:bf:a6:31:e1:f2:c8:d3:1b:7b:79:d1:b6: + 6c:ae:3b:6b:00:2e:6e:ae:10:dc:6c:88:dc:1b:93: + e8:56:99:8d:46:7e:49:3a:87:a0:b3:00:cc:2e:3b: + 83:e1:6b:39:16:71:47:47:30:6d:6b:6c:9c:9f:e6: + ce:ec:20:2f:8f:c1:5d:ef:d3:84:32:6c:a5:cc:78: + fe:a1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 56:54:36:BE:23:2F:20:89:6D:A6:BA:9A:45:A4:88:0E:40:35:FD:F5 + X509v3 Authority Key Identifier: + keyid:18:6D:44:83:EE:1F:EC:B4:22:F0:9C:EB:54:1E:4A:15:58:01:AA:13 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE, pathlen:2 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 2a:35:ca:d5:dd:97:31:4d:29:21:90:67:ba:68:ef:2a:56:b0: + 08:0a:c5:a2:cc:30:11:71:59:1b:59:2b:ca:c4:cc:22:52:d7: + f3:a7:d2:14:c5:fc:e4:c5:6f:9d:45:ce:7f:d0:dd:ec:5f:6b: + c3:d1:78:7a:29:bb:73:98:b6:15:9b:41:37:7a:50:b3:04:1d: + 72:90:9b:e9:f2:4b:68:f3:60:e9:bb:34:6e:2a:6c:6c:50:a6: + 38:ac:61:bc:ca:25:23:f5:f5:70:3a:8a:33:94:cf:97:1c:5c: + a3:76:b0:7b:88:35:8a:6e:18:44:01:e6:80:23:e9:14:ea:66: + 56:34:9a:0b:ca:1a:37:c8:e7:00:03:39:7d:73:e5:13:cb:be: + 9e:df:c6:87:c3:24:a7:7f:39:1d:cc:ca:1f:e7:14:38:fe:3d: + 06:7a:2f:95:f3:9a:79:49:e9:9c:f3:72:e5:b4:b5:fb:87:13: + 83:4f:9f:76:2f:41:8f:a4:55:1d:e4:74:2f:0a:0f:cd:ee:a8: + 50:06:1e:a7:9e:25:9f:f3:9d:b2:c1:44:de:c5:44:3e:42:64: + e1:75:16:33:56:a7:93:68:bb:fa:96:46:33:de:58:c1:81:42: + ca:1c:28:4f:09:71:db:60:e1:88:ac:d6:0d:37:3a:63:8d:50: + b7:35:2d:e5 +-----BEGIN CERTIFICATE----- +MIIExjCCA66gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluSC1JQ0E0LXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgwOVoXDTIyMDcwNzAwMjgwOVowgaExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR0wGwYDVQQD +DBRjaGFpbkgtSUNBMy1wYXRobGVuMjEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm +c3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALezGhtKgBui +5ZUUvFXkd9zze4qfNHyT28nJ0Iu4h0Vl06F9RvNwkqnXZu87tKgWsPC+Z3CqRXsJ +vMp321ekJFQLGtpfrWSj8UmDvJ9dxLTaQwSqzMOwTcLxc8k4DUzJq9vfCbNcFQtm +ea1sY9E4zKYtRoPOGR3BC278OLfYjKJvKYebIc2wa+D4HwPbgh2NmGMWtnRHQyDy +oUsWi2f9vHN4m/nduknZYKm3hWZ/pCoFyC2ToJuqv6Yx4fLI0xt7edG2bK47awAu +bq4Q3GyI3BuT6FaZjUZ+STqHoLMAzC47g+FrORZxR0cwbWtsnJ/mzuwgL4/BXe/T +hDJspcx4/qECAwEAAaOCAQUwggEBMB0GA1UdDgQWBBRWVDa+Iy8giW2muppFpIgO +QDX99TCBwQYDVR0jBIG5MIG2gBQYbUSD7h/stCLwnOtUHkoVWAGqE6GBmqSBlzCB +lDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVt +YW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYD +VQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb22CAWQwDwYDVR0TBAgwBgEB/wIBAjALBgNVHQ8EBAMCAQYwDQYJKoZIhvcN +AQELBQADggEBACo1ytXdlzFNKSGQZ7po7ypWsAgKxaLMMBFxWRtZK8rEzCJS1/On +0hTF/OTFb51Fzn/Q3exfa8PReHopu3OYthWbQTd6ULMEHXKQm+nyS2jzYOm7NG4q +bGxQpjisYbzKJSP19XA6ijOUz5ccXKN2sHuINYpuGEQB5oAj6RTqZlY0mgvKGjfI +5wADOX1z5RPLvp7fxofDJKd/OR3Myh/nFDj+PQZ6L5XzmnlJ6ZzzcuW0tfuHE4NP +n3YvQY+kVR3kdC8KD83uqFAGHqeeJZ/znbLBRN7FRD5CZOF1FjNWp5Nou/qWRjPe +WMGBQsocKE8Jcdtg4Yis1g03OmONULc1LeU= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 00:28:09 2019 GMT + Not After : Jul 7 00:28:09 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA4-pathlen2, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bb:f3:2f:8a:cd:9e:87:f1:01:f3:a4:c0:2d:66: + 36:d7:11:2e:64:08:e8:f1:99:fa:a6:9c:f4:bd:3b: + 47:72:d2:0e:58:9d:3e:52:e7:da:a3:43:78:c3:c3: + 93:e6:04:d3:ab:51:8a:1a:24:0e:7a:62:59:aa:c6: + 42:9e:66:c1:61:5e:31:b1:4d:dc:37:a9:18:76:8d: + fe:cb:09:54:3f:4f:bb:5f:ab:ba:70:e9:b4:a1:5e: + a0:69:7e:45:3f:c0:cc:78:e9:f2:74:64:79:c2:6a: + 16:d0:98:30:82:44:4a:b3:99:2c:66:30:ac:99:82: + 04:2a:bf:0f:60:89:04:36:fa:29:d3:08:56:61:6a: + a8:33:40:9a:53:7d:20:a8:51:6f:9b:a0:d9:3e:dc: + 9a:8b:1d:37:9e:ad:c9:fd:53:a7:04:dc:1f:36:3e: + d3:65:52:84:24:61:d0:4e:e2:41:60:bf:fb:fd:b2: + 04:b3:3f:eb:14:99:5e:bc:e8:7d:e9:65:d1:3f:fe: + 04:49:e5:bb:a3:2d:e3:db:96:df:d9:81:a0:32:d7: + 01:b9:b8:02:8e:b9:a2:1f:0a:d4:24:17:3a:19:0f: + 6d:3a:10:5f:5c:7d:b8:56:82:c7:7f:40:f0:2d:87: + 63:c1:b1:d8:64:c7:3c:27:13:4a:63:82:21:b1:f2: + 39:e9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 18:6D:44:83:EE:1F:EC:B4:22:F0:9C:EB:54:1E:4A:15:58:01:AA:13 + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:2 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 61:c0:d8:c4:02:cd:b4:54:d3:44:e9:06:78:0b:a2:16:b5:4a: + b6:b5:09:f1:d1:fc:9f:be:e5:12:0b:6c:61:8d:66:3f:ce:8f: + 95:98:24:ea:d2:99:3a:4f:89:e3:2d:a9:f7:69:cb:05:9e:90: + af:5a:f1:93:ac:ee:fe:78:f8:e3:22:fa:69:7f:e4:71:1d:c9: + 1e:ac:61:81:8d:93:33:bc:b2:e4:67:75:97:9d:af:0a:db:ab: + 24:3f:8d:1d:16:c6:05:c6:89:a7:5f:cf:2d:73:39:de:8f:40: + 94:4b:7a:a4:ea:35:1e:70:ce:3a:f5:75:76:e5:ab:e4:8a:9a: + a4:a1:ec:49:59:3d:b7:23:fa:3c:af:dd:09:d7:aa:47:60:11: + 07:07:f4:8b:a1:40:b2:d9:bb:0f:88:b8:d1:a5:e2:88:22:76: + 8b:45:d6:96:2c:45:11:98:04:85:22:99:1f:49:a7:30:b0:b0: + 74:c3:ea:1a:a6:53:ed:c9:48:40:1a:d8:02:a8:fb:35:3a:f7: + 69:42:b2:75:dd:98:41:30:a9:e3:b1:ec:c6:66:f1:61:16:5b: + f6:e3:bc:31:8e:46:66:fa:39:34:66:cc:95:1d:69:15:12:41: + 16:ce:e6:a6:d4:4c:eb:f4:99:b4:6d:66:99:76:ae:5a:e8:24: + 92:a7:ef:45 +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MDAyODA5WhcNMjIwNzA3MDAyODA5WjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluSC1JQ0E0 +LXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu/Mvis2eh/EB86TALWY21xEuZAjo +8Zn6ppz0vTtHctIOWJ0+Uufao0N4w8OT5gTTq1GKGiQOemJZqsZCnmbBYV4xsU3c +N6kYdo3+ywlUP0+7X6u6cOm0oV6gaX5FP8DMeOnydGR5wmoW0JgwgkRKs5ksZjCs +mYIEKr8PYIkENvop0whWYWqoM0CaU30gqFFvm6DZPtyaix03nq3J/VOnBNwfNj7T +ZVKEJGHQTuJBYL/7/bIEsz/rFJlevOh96WXRP/4ESeW7oy3j25bf2YGgMtcBubgC +jrmiHwrUJBc6GQ9tOhBfXH24VoLHf0DwLYdjwbHYZMc8JxNKY4IhsfI56QIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFBhtRIPuH+y0IvCc61QeShVYAaoTMIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQBhwNjEAs20VNNE6QZ4C6IWtUq2tQnx0fyfvuUSC2xhjWY/zo+VmCTq0pk6 +T4njLan3acsFnpCvWvGTrO7+ePjjIvppf+RxHckerGGBjZMzvLLkZ3WXna8K26sk +P40dFsYFxomnX88tcznej0CUS3qk6jUecM469XV25avkipqkoexJWT23I/o8r90J +16pHYBEHB/SLoUCy2bsPiLjRpeKIInaLRdaWLEURmASFIpkfSacwsLB0w+oaplPt +yUhAGtgCqPs1OvdpQrJ13ZhBMKnjsezGZvFhFlv247wxjkZm+jk0ZsyVHWkVEkEW +zuam1Ezr9Jm0bWaZdq5a6CSSp+9F +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-entity-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-entity-key.pem new file mode 100644 index 000000000..4b374bc49 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-entity-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAuu2rwA2SbBDkUJ98mMyH/Sg0d8BYKFIsKJeA7HgCT/TKYPgd +52oEUi51hUJ0dgDkcIS4UY4pLn+2rd9tCbRPEVQeiBbiDq8w8D2n2p9ODZRbBVGc +zAVljWsePHlbJn7LrumacWmSQZsazbRTC/suQMTjsV64i/jPCuxfBxAYVPiKfTWX +enqY6pMtG+ZEFj/Mp0y5z7ULCUezuI4CGlZpN7dJpFmQoyCI84d36DkNOTalVrPs +S/Nei8LNRwzZVs4y93Ez2399xh5+ccEBBpieUpid151KMpQ8WkJmAMriozXbt/Mn +C5z6G5lLUfpsJZD1dozZDYCMrGHrTZISbV8S5QIDAQABAoIBAE9VKz05BVmD2cI1 +zcVzmItiktH3+fIy3bbkhbzWOfUBKRr6coaSQf825H2H9LFYM5tlWGyUbvnjDf7B +Ah/KPHxYPRT40Tv2MkjjgeeREKlGu1KIjokwCSd5vL1hq8OssHktf3R+n6nkT/3Z +eB1vnvOyHAhc8OnG0OgL5VC0Df+ROj1gT8wgU2HUcMQj4A+TaSsEC6DHfHpASLZ+ +prpLyrAiNStQqGmt3hZhgnCaezeQkEAHUSIvqQ9KLBXjgwzXRgEWk5JZSv00z8RA +dK3pJAlyVDhC7Lz5eSs8GWIPMmfM9DTFDICdBOnaCCGeBiWVKu7LQxWTCYZbYGjJ +Txurx4kCgYEA4gG6oTgI1CRwcVfOpVCX/Il5F3Lsro20/MmXjCl1DXZA18eEjLHd +v5AZuGybGUhXq4AtM5CdeUw0Jw0+lASm94sjhK7+S+Slb1SpVAzrkbPuzBuvMtqT +63x/RVX9WX3GkGcdsB05/f6mBPGwSYin8ruvST5o/dcBQgQEAbXLcZMCgYEA07xO +5pvVHwIvJ0NqGsX94cQO4jZRbx0wNFu9ztx6vkHxNtBtO86+Sb68b0KBxZuIlsK9 +3HwUDpov1eIv+Mb3qHf8uEb8XmxrFBLyl+nF60JTUrteBWDj7e9nYGA1VYoYdrAC +kiQt4dGGJwfRv8P/JpbNa0egX9yj9DAeIJNllKcCgYBcvdLkx0awLwfJKvwMUGcd +5RfArJM9Cb9kICFFDdoPnR/8q83TokVZj3tOd5qppEr9gEqMJ2LHXKLmB4RPXx1Y +5Uq87sZBRGEyry4Q5IBiONDcBtw85P7gGiVrwV6GM5ugs/+1vjiG5tEfpEHv2tj4 +PVYvmyGgUHMesOEoBn6mawKBgFtnu5gKReLxCnIkxDVyq7s+7D3zvQv+ycSQpkwb +GlHwHbXQHJfpFHS5hpdxWpx4HGsY/uWkGvSC04u97X+0RU3RHqRe4KvSmhc8ZsX2 +AZ8iLt5UTK59uWgKJdKRNfULfKwgJ7v3KmeGECfhVEc40XlTOLLLZQx9L7pG23qs +pvmZAoGAdIcADYC134Bqz9MSVKT3sZHeK12Bw8t3v3nIWB4+wAjz8960/j3ODRkI +KaJxVhbLFq8tZQ3jHy60rF6SE3491YUvV/ilVWzsd8oyhJL3K+Zw18vE/PwhanQn +xtW8pUplONwot++5iZFrUv51f2AnQWgMEk1wEQN8UrgFE1SvuxY= +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-entity.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-entity.pem new file mode 100644 index 000000000..b125341e5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainH-entity.pem @@ -0,0 +1,87 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-ICA1-pathlen0, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 00:28:10 2019 GMT + Not After : Jul 7 00:28:10 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainH-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:ba:ed:ab:c0:0d:92:6c:10:e4:50:9f:7c:98:cc: + 87:fd:28:34:77:c0:58:28:52:2c:28:97:80:ec:78: + 02:4f:f4:ca:60:f8:1d:e7:6a:04:52:2e:75:85:42: + 74:76:00:e4:70:84:b8:51:8e:29:2e:7f:b6:ad:df: + 6d:09:b4:4f:11:54:1e:88:16:e2:0e:af:30:f0:3d: + a7:da:9f:4e:0d:94:5b:05:51:9c:cc:05:65:8d:6b: + 1e:3c:79:5b:26:7e:cb:ae:e9:9a:71:69:92:41:9b: + 1a:cd:b4:53:0b:fb:2e:40:c4:e3:b1:5e:b8:8b:f8: + cf:0a:ec:5f:07:10:18:54:f8:8a:7d:35:97:7a:7a: + 98:ea:93:2d:1b:e6:44:16:3f:cc:a7:4c:b9:cf:b5: + 0b:09:47:b3:b8:8e:02:1a:56:69:37:b7:49:a4:59: + 90:a3:20:88:f3:87:77:e8:39:0d:39:36:a5:56:b3: + ec:4b:f3:5e:8b:c2:cd:47:0c:d9:56:ce:32:f7:71: + 33:db:7f:7d:c6:1e:7e:71:c1:01:06:98:9e:52:98: + 9d:d7:9d:4a:32:94:3c:5a:42:66:00:ca:e2:a3:35: + db:b7:f3:27:0b:9c:fa:1b:99:4b:51:fa:6c:25:90: + f5:76:8c:d9:0d:80:8c:ac:61:eb:4d:92:12:6d:5f: + 12:e5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + ED:62:FB:8F:91:CB:DE:B0:C8:89:CE:BA:B5:80:A8:47:F1:72:16:05 + X509v3 Authority Key Identifier: + keyid:48:80:87:28:EF:E6:28:0F:03:9B:DF:33:48:10:A0:E5:20:B3:69:50 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainH-ICA2-pathlen2/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + bc:fc:a7:c3:c9:a4:57:9e:37:9d:f7:71:eb:5b:7c:a2:1a:0d: + 24:97:12:92:18:fd:0f:5e:5b:f9:27:c9:98:2c:9a:06:bd:77: + 85:63:3c:a4:ed:90:92:3a:79:41:82:c3:54:66:f6:c6:a0:d3: + ba:a3:19:93:d9:5f:54:90:fc:2b:37:d1:96:88:ba:be:e1:71: + 8c:a2:24:d7:ce:d8:7c:5e:87:9f:4f:f2:52:51:1c:82:5b:2c: + 8b:b4:5d:7e:d6:03:95:a0:e9:29:68:5e:76:18:2b:93:6f:a1: + 58:a6:f6:35:8b:37:b9:6b:82:5d:3a:8c:bc:a6:bd:18:ca:2f: + ea:0c:4d:36:7a:58:80:52:9c:b3:fa:a4:2b:0e:97:e6:0f:fc: + 41:62:6d:45:19:15:6d:3e:16:e5:bc:81:ce:c0:34:d3:b5:d4: + 0c:54:a5:62:a6:55:57:ad:e8:6f:94:58:cb:31:ff:0f:1c:13: + 63:82:91:1f:a3:68:f5:9f:9c:d9:dd:54:e0:d0:36:ea:ad:2a: + 9d:4e:66:be:c7:2f:1a:16:70:be:b4:1b:c5:2d:b2:1b:0c:87: + 64:10:4d:db:8b:79:5b:2e:10:a4:95:25:7b:be:b2:21:26:47: + e9:d2:74:c8:34:b1:e3:7b:73:8c:93:7a:82:ce:50:d4:46:34: + ab:11:71:c0 +-----BEGIN CERTIFICATE----- +MIIEtzCCA5+gAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluSC1JQ0ExLXBhdGhsZW4wMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTAwMjgxMFoXDTIyMDcwNzAwMjgxMFowgZoxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRYwFAYDVQQD +DA1jaGFpbkgtZW50aXR5MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuu2rwA2SbBDkUJ98mMyH +/Sg0d8BYKFIsKJeA7HgCT/TKYPgd52oEUi51hUJ0dgDkcIS4UY4pLn+2rd9tCbRP +EVQeiBbiDq8w8D2n2p9ODZRbBVGczAVljWsePHlbJn7LrumacWmSQZsazbRTC/su +QMTjsV64i/jPCuxfBxAYVPiKfTWXenqY6pMtG+ZEFj/Mp0y5z7ULCUezuI4CGlZp +N7dJpFmQoyCI84d36DkNOTalVrPsS/Nei8LNRwzZVs4y93Ez2399xh5+ccEBBpie +Upid151KMpQ8WkJmAMriozXbt/MnC5z6G5lLUfpsJZD1dozZDYCMrGHrTZISbV8S +5QIDAQABo4H+MIH7MB0GA1UdDgQWBBTtYvuPkcvesMiJzrq1gKhH8XIWBTCBzgYD +VR0jBIHGMIHDgBRIgIco7+YoDwOb3zNIEKDlILNpUKGBp6SBpDCBoTELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNV +BAMMFGNoYWluSC1JQ0EyLXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tggFkMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBALz8p8PJ +pFeeN533cetbfKIaDSSXEpIY/Q9eW/knyZgsmga9d4VjPKTtkJI6eUGCw1Rm9sag +07qjGZPZX1SQ/Cs30ZaIur7hcYyiJNfO2Hxeh59P8lJRHIJbLIu0XX7WA5Wg6Slo +XnYYK5NvoVim9jWLN7lrgl06jLymvRjKL+oMTTZ6WIBSnLP6pCsOl+YP/EFibUUZ +FW0+FuW8gc7ANNO11AxUpWKmVVet6G+UWMsx/w8cE2OCkR+jaPWfnNndVODQNuqt +Kp1OZr7HLxoWcL60G8UtshsMh2QQTduLeVsuEKSVJXu+siEmR+nSdMg0seN7c4yT +eoLOUNRGNKsRccA= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA1-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA1-key.pem new file mode 100644 index 000000000..6b05b9f49 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA1-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpgIBAAKCAQEAu7oGrRPP2vvRy2X+JlhJagEUpniyLB26utC9JzhmfKAbKAg8 +av34h75Jou048kywi5P/0sU/zQPFFHnodmN6qqdUHg4nvRu+6D8rVUDwWSPYP+gF +Ggtx8P0k2fkLmSXar5Y07uGRy/yPoEGPnOFPV1+21lVpb8NkwxGpaUCF3/OaWbXu +kMAi7nIoLtPaZSc7ukLAnnO6ovJFE3rFHTClt9t1XW/MCHeAZ40YKsoCjY7TnCr6 +t48bfe9id6T6tthaPmacPhNFqM9h+/9BRRQh4mOsgU1liePVcSABGXbspBam7zy8 +8qJWKwcxZw3ll4jo28tNmMuZ5uC9YkgrsQQSBwIDAQABAoIBAQCiKVvC/q46l/Tu +IricHv+r1iskcnZWrYe0AMSksI+3cAaFWjf2pFSfzbyGRS1AAQcwSzRduY4XZv5D +ZdttCRnZeJmtLMUfEmyi6o5gIqx8E/6llaNykBho+ANxVzSxooV5z+MBx1DOSOk4 +oemQtwB2lXO3Sii+JqdP6l3RUa9Td/khmGLGCo0/8Htlw5a+lWYRzkGK4DbTxFxM +V6Nk58ZjWv/rM4rsRlStfvhNlKKP74tTromI37/Znx3QH1FugZ5u3fd1LDCLsxLU +d684plIKNZE6QiG7zQ+viyviFEvJ6PPo3Tc/x8bAQ/SS23e9obRzqqU4nRbXfSrU +rnHNrWlBAoGBAPlzL3Od/5/3GKvx7EJGU1v46kIxJwog8zGHvTSloz5b18+UVHBo +3YuyfDlq7OL61H+2+wE05o9uo/FrZi7VS2XK/Qofv39hAVxlz/BiigEcggSzLXs9 +k9QFqXBvJ/TylmVU25GPisF2mP2tKKbL6P98J6jGKo2cEF24tM1gLq6fAoGBAMCn +7xBKSsed/J/TM+fFM2TeZMKvo3fbLJFFy1k95DYgsoIIncyaJrZy9KmomSp6SAhh +lqeqKCeqOTF9asLrUotbbQPcJQucyLqKnX3Zq2E338JALDJxSjg97DG3KxKLS7PI +3Fk3uK35PkPUctOjC/Ep0DVwosAxePrZcuzilyuZAoGBAJ5rdaZSoGZiEgwZHzdT +3FrbsUKKXsXC+U/qadIGo67VuzA8fofJQXIXz2bTrk/UhqH5fl1c0FQlKv8GeyWh +Fjo2eQ817HMkEy4wBqgenJBqH3SGqorLJ5gOZHZgUZrxeWwvQSanZ7LH9A+fKeMM +OxQOME2yVJIMnCQ5SrHntJ33AoGBAKWQbImCXwt3gT/U4JmAxm8cFFmfWYtKRt29 +rkjOQI4nwWCwiPPpUfWfixU2eBKiLb9OJouGVqXnyuj2EEbctv5eHqyfhxKYtYRi +VYBvDLIqs1gbkB/1bkQxKwd6k0CHhxJFPuBJW6PfO5xNOjUYvM2PEoiqeKNUoNRr +BTIAdMuZAoGBAMlyqDi5jbcZ53PE9PrwSepUOaOVIKlCAUwQlol+aAtlGGQksYM0 +HPoYXZsx+XzHBtXed5E+OvOY6zxfgtkal03RrleUQo7rJArL3cxOunPODzjemEJq +qysAp0Dnk+PenIabUfv9McAFQ9Sr8WG4K6xZTgedeTU194ZQw2BJeq8E +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA1-no_pathlen.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA1-no_pathlen.pem new file mode 100644 index 000000000..0013267db --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA1-no_pathlen.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-ICA2-no_pathlen, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-ICA1-no_pathlen, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bb:ba:06:ad:13:cf:da:fb:d1:cb:65:fe:26:58: + 49:6a:01:14:a6:78:b2:2c:1d:ba:ba:d0:bd:27:38: + 66:7c:a0:1b:28:08:3c:6a:fd:f8:87:be:49:a2:ed: + 38:f2:4c:b0:8b:93:ff:d2:c5:3f:cd:03:c5:14:79: + e8:76:63:7a:aa:a7:54:1e:0e:27:bd:1b:be:e8:3f: + 2b:55:40:f0:59:23:d8:3f:e8:05:1a:0b:71:f0:fd: + 24:d9:f9:0b:99:25:da:af:96:34:ee:e1:91:cb:fc: + 8f:a0:41:8f:9c:e1:4f:57:5f:b6:d6:55:69:6f:c3: + 64:c3:11:a9:69:40:85:df:f3:9a:59:b5:ee:90:c0: + 22:ee:72:28:2e:d3:da:65:27:3b:ba:42:c0:9e:73: + ba:a2:f2:45:13:7a:c5:1d:30:a5:b7:db:75:5d:6f: + cc:08:77:80:67:8d:18:2a:ca:02:8d:8e:d3:9c:2a: + fa:b7:8f:1b:7d:ef:62:77:a4:fa:b6:d8:5a:3e:66: + 9c:3e:13:45:a8:cf:61:fb:ff:41:45:14:21:e2:63: + ac:81:4d:65:89:e3:d5:71:20:01:19:76:ec:a4:16: + a6:ef:3c:bc:f2:a2:56:2b:07:31:67:0d:e5:97:88: + e8:db:cb:4d:98:cb:99:e6:e0:bd:62:48:2b:b1:04: + 12:07 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 9E:54:B6:95:EA:89:07:A6:C9:E4:82:E8:D0:34:64:5D:08:CD:56:A0 + X509v3 Authority Key Identifier: + keyid:D1:BA:FB:FF:1D:29:41:8A:6A:5F:B2:F3:A7:41:05:47:09:1F:48:42 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainI-ICA3-pathlen2/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + b3:b8:b9:c2:44:3a:36:0a:cf:fd:da:80:8c:81:54:c1:cd:a6: + 52:a8:60:b1:f8:fd:62:01:fc:d9:85:89:15:9a:df:45:f0:68: + 3e:bb:fe:f3:94:dc:1c:69:3c:7c:47:df:04:0c:7b:2f:4f:3f: + 56:58:9a:fa:1a:4c:16:21:cf:f2:21:a5:f9:d9:49:1b:69:b4: + 4d:df:d0:c2:d7:2c:fa:0f:23:d6:45:61:12:cd:2a:5a:06:db: + 22:6f:99:7a:a0:fc:17:ba:05:bc:02:79:db:f8:cd:ec:a0:98: + 7c:7f:6b:d6:ca:5c:cd:07:89:b6:0d:3e:0b:d3:d7:7f:7c:6b: + 73:7b:b9:28:69:d2:5f:27:1c:13:60:a0:50:23:16:00:d1:cb: + 7a:1d:62:7c:a1:c2:63:1d:c9:0b:0f:d7:5c:91:af:7a:5b:93: + 7e:e5:12:36:f0:3b:fa:59:7b:a8:88:f7:bf:11:19:4b:6a:81: + 61:77:54:61:a3:73:b6:54:64:92:49:22:c9:6a:19:73:33:6d: + 01:4c:5a:9c:0a:fa:ce:a1:34:50:b1:54:de:0b:7b:ce:fe:e0: + 00:fa:8e:7f:48:36:58:ed:98:42:ce:8d:a4:a0:67:c9:88:1c: + 7f:58:df:fb:62:0f:ee:4b:7d:5a:c7:52:2f:9f:2d:13:13:0b: + 72:bd:a0:2e +-----BEGIN CERTIFICATE----- +MIIE1DCCA7ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluSS1JQ0EyLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBozELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNV +BAMMFmNoYWluSS1JQ0ExLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9A +d29sZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7ugat +E8/a+9HLZf4mWElqARSmeLIsHbq60L0nOGZ8oBsoCDxq/fiHvkmi7TjyTLCLk//S +xT/NA8UUeeh2Y3qqp1QeDie9G77oPytVQPBZI9g/6AUaC3Hw/STZ+QuZJdqvljTu +4ZHL/I+gQY+c4U9XX7bWVWlvw2TDEalpQIXf85pZte6QwCLucigu09plJzu6QsCe +c7qi8kUTesUdMKW323Vdb8wId4BnjRgqygKNjtOcKvq3jxt972J3pPq22Fo+Zpw+ +E0Woz2H7/0FFFCHiY6yBTWWJ49VxIAEZduykFqbvPLzyolYrBzFnDeWXiOjby02Y +y5nm4L1iSCuxBBIHAgMBAAGjggEPMIIBCzAdBgNVHQ4EFgQUnlS2leqJB6bJ5ILo +0DRkXQjNVqAwgc4GA1UdIwSBxjCBw4AU0br7/x0pQYpqX7Lzp0EFRwkfSEKhgaek +gaQwgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRUwEwYDVQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2lu +ZWVyaW5nMR0wGwYDVQQDDBRjaGFpbkktSUNBMy1wYXRobGVuMjEfMB0GCSqGSIb3 +DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIBZDAMBgNVHRMEBTADAQH/MAsGA1UdDwQE +AwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAs7i5wkQ6NgrP/dqAjIFUwc2mUqhgsfj9 +YgH82YWJFZrfRfBoPrv+85TcHGk8fEffBAx7L08/Vlia+hpMFiHP8iGl+dlJG2m0 +Td/Qwtcs+g8j1kVhEs0qWgbbIm+ZeqD8F7oFvAJ52/jN7KCYfH9r1spczQeJtg0+ +C9PXf3xrc3u5KGnSXyccE2CgUCMWANHLeh1ifKHCYx3JCw/XXJGveluTfuUSNvA7 ++ll7qIj3vxEZS2qBYXdUYaNztlRkkkkiyWoZczNtAUxanAr6zqE0ULFU3gt7zv7g +APqOf0g2WO2YQs6NpKBnyYgcf1jf+2IP7kt9WsdSL58tExMLcr2gLg== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA2-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA2-key.pem new file mode 100644 index 000000000..1e7788141 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA2-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEoQIBAAKCAQEA3h4IZhL+IAcQG6EnDfkiMIGbzmKxpm1J1O24LUuXdx6UUT1z +KxbpBelMG4KtR50zMFO1m9It6XvWY/NhIBsjbkcJi8DVCYWm4uQ6TbP53cZ8mkIH +ItV7Zxg4xPzqjQmAoLBEM/3BqoucmOOVw3RxO3G4s4C/MGOFCSeLErWGsAuZ/5dC +UqCssjg4jROW2db6j8SJFAacHwqjOqL3H4PYrkFEniGyW7eiGelGWN7loqsHepqa +YLwU7c9NQvxcKOpC0a7McX5SXYSI3rZ9cm6rc0sNq5KfEbRR2hRUmg7srEL8cYdb +VDgJLPBdhgw0t5IzXD4ZsU2gYpu0aDY2OOwpswIDAQABAoH/VQcqL+kVXy1U/T6z +tKWqcOcsvdUKLKupl9lop+5IDVGndXIQpG4gxiKI//8GVmPXNKjW3M+Yw8ikSZ7h +j2jUJ2MKRHWNGBgRysmTiCtde4iAKo0cLjmLA+xBzycCovsAQoM3mK+Lc73+NIjq +y+fHcPoXup+OkPeH9fktQ/w5kyonK0Qz7nyb6P9FjFG/f3+WbTaA1FgchELqX00g +bA6nMHEnhm9MoKKsVZbZKG9gIUCtejrd+YaOBHHWVG47QQI+iFCDrSk2dn8CJq8j +8w1VD2QkBSWeW1K5QTbQyOwShYKfmpPthy2LAAfC5TNSpeEBRf2uwzi9Vzqa89cX +UPMBAoGBAPQWwv283d72JaGOEQ+AL32Q5KEydtrzMLzBSHRrb2NhEvq4tev6/Ihl +jklZ+KuPkxtV/dI0bz/x7JikbQvT3a76zqwv2LbpYJdz8CLqh52dOAhfdkYOCapP +2FnlHcwWt35kXC11Srb1jnJ40VNxDq3DNYNgGQohrEjVCMNfrb7BAoGBAOj0y3Wz +TnPhrDzBYmh6+D5/ZVBCnPhkWMV4yYimidAWE0TB7DvEKqQ7gbHmpiOzaWefoRs6 +8qHu02l0EHW6TJUJqSWBMFiEkwnZStEKAw2LCqjLW/xFH/7Yw6Hkpb7Fp9kumh3r +tkdNZSdT3ETvyFjKrUX7QFYXOLQ+bAdWhrlzAoGAPnZwscQaNwtgd+ZGIWRZQtXI +XCPw3HjtWPBRXVF88L6Pv89y5o+U/kaW0diPVT/pkk5AJQG8Em4TcMBrE2LFURjn +uJKJ78zrJfbKVfUUfVYVV7cuKiE/gfDq2Z5TML4DePmvyQZB924BZPPcBXFiIz9Y +O2VlIv2Y/A5gLrcWXEECgYBTReZRDaaWr+4EzdAirwp8NMf/l8BK3nwJIvNPwNB0 +rN94baXHe4kOqiLjeCKdkm20WBCcDkdbcWbrREz5+H2VrR1kxbiFe+af16fx75VF +yxUlX4RjOkaEr/HGtlg1SKyGay02UuMWu+jT1RthHSHN861a3cSSwbxIWiP9v4Vr +VwKBgQDkjIEnH1yzKsAIdxa4Nb3OG3vBIplB3d/PaRzCXNfcrwIj58KcEDKGOSlj +LKcH42K2wJrpyRH+n87NH5Nt73fRLEQ7IBkb4gA918BPMp6Q5OU99CBld5WO3/F0 +LWDySahHuH4ymEeM45Y+1lZQjc4cQb9/Sbzi1fZsvTQRen3yWw== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA2-no_pathlen.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA2-no_pathlen.pem new file mode 100644 index 000000000..4e39c84b6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA2-no_pathlen.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-ICA3-pathlen2, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-ICA2-no_pathlen, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:de:1e:08:66:12:fe:20:07:10:1b:a1:27:0d:f9: + 22:30:81:9b:ce:62:b1:a6:6d:49:d4:ed:b8:2d:4b: + 97:77:1e:94:51:3d:73:2b:16:e9:05:e9:4c:1b:82: + ad:47:9d:33:30:53:b5:9b:d2:2d:e9:7b:d6:63:f3: + 61:20:1b:23:6e:47:09:8b:c0:d5:09:85:a6:e2:e4: + 3a:4d:b3:f9:dd:c6:7c:9a:42:07:22:d5:7b:67:18: + 38:c4:fc:ea:8d:09:80:a0:b0:44:33:fd:c1:aa:8b: + 9c:98:e3:95:c3:74:71:3b:71:b8:b3:80:bf:30:63: + 85:09:27:8b:12:b5:86:b0:0b:99:ff:97:42:52:a0: + ac:b2:38:38:8d:13:96:d9:d6:fa:8f:c4:89:14:06: + 9c:1f:0a:a3:3a:a2:f7:1f:83:d8:ae:41:44:9e:21: + b2:5b:b7:a2:19:e9:46:58:de:e5:a2:ab:07:7a:9a: + 9a:60:bc:14:ed:cf:4d:42:fc:5c:28:ea:42:d1:ae: + cc:71:7e:52:5d:84:88:de:b6:7d:72:6e:ab:73:4b: + 0d:ab:92:9f:11:b4:51:da:14:54:9a:0e:ec:ac:42: + fc:71:87:5b:54:38:09:2c:f0:5d:86:0c:34:b7:92: + 33:5c:3e:19:b1:4d:a0:62:9b:b4:68:36:36:38:ec: + 29:b3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D1:BA:FB:FF:1D:29:41:8A:6A:5F:B2:F3:A7:41:05:47:09:1F:48:42 + X509v3 Authority Key Identifier: + keyid:EE:37:A6:F2:40:D0:EF:FD:22:C7:A3:B4:6C:57:47:40:B9:99:F9:8D + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 8f:9b:f7:bd:1a:90:58:f0:ab:0f:1d:45:b2:29:10:66:2d:cc: + 96:d6:3c:f4:3c:a8:49:e2:cf:db:17:16:8c:e8:76:de:79:c9: + 42:10:a7:ad:b7:c3:c2:82:93:6b:19:3e:56:af:be:c8:d7:dd: + ee:87:1d:5f:1d:ad:6a:02:8d:14:22:9f:54:58:d7:d8:16:79: + 64:4d:eb:55:88:74:74:f6:59:2c:40:9f:d0:f4:a8:36:ea:c9: + 4f:9c:2b:3a:72:5f:20:2d:25:b3:b2:fb:c1:03:11:ab:57:57: + d0:55:13:b9:f5:10:09:9e:56:a2:0d:95:3c:16:3e:59:f3:71: + 60:50:06:53:45:ff:0f:e2:f8:61:5b:d2:fc:0a:65:59:dc:ee: + 6f:c6:26:c4:7d:27:69:4d:76:55:2f:07:01:3f:30:ea:17:3d: + bb:8a:f0:df:ae:c8:47:70:0e:b4:28:c9:e9:7b:8c:8a:22:a0: + ea:32:9b:f8:1e:35:a4:f0:a5:09:81:dc:9a:a4:d1:63:34:9e: + 3c:32:2f:f3:b1:f0:43:3b:f1:31:9b:8b:99:bf:c2:b4:eb:78: + 39:a3:e7:d8:2c:e6:6c:f2:8b:2f:21:83:c3:28:1b:77:f3:75: + 9b:79:f7:f0:73:a0:a2:47:af:93:32:0b:d2:88:04:14:3a:cd: + 48:7f:58:32 +-----BEGIN CERTIFICATE----- +MIIExDCCA6ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluSS1JQ0EzLXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTE4MzAzMFoXDTIyMDcwNzE4MzAzMFowgaMxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR8wHQYDVQQD +DBZjaGFpbkktSUNBMi1ub19wYXRobGVuMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3h4IZhL+ +IAcQG6EnDfkiMIGbzmKxpm1J1O24LUuXdx6UUT1zKxbpBelMG4KtR50zMFO1m9It +6XvWY/NhIBsjbkcJi8DVCYWm4uQ6TbP53cZ8mkIHItV7Zxg4xPzqjQmAoLBEM/3B +qoucmOOVw3RxO3G4s4C/MGOFCSeLErWGsAuZ/5dCUqCssjg4jROW2db6j8SJFAac +HwqjOqL3H4PYrkFEniGyW7eiGelGWN7loqsHepqaYLwU7c9NQvxcKOpC0a7McX5S +XYSI3rZ9cm6rc0sNq5KfEbRR2hRUmg7srEL8cYdbVDgJLPBdhgw0t5IzXD4ZsU2g +Ypu0aDY2OOwpswIDAQABo4IBATCB/jAdBgNVHQ4EFgQU0br7/x0pQYpqX7Lzp0EF +RwkfSEIwgcEGA1UdIwSBuTCBtoAU7jem8kDQ7/0ix6O0bFdHQLmZ+Y2hgZqkgZcw +gZQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3pl +bWFuMREwDwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYG +A1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tggFkMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEB +CwUAA4IBAQCPm/e9GpBY8KsPHUWyKRBmLcyW1jz0PKhJ4s/bFxaM6HbeeclCEKet +t8PCgpNrGT5Wr77I193uhx1fHa1qAo0UIp9UWNfYFnlkTetViHR09lksQJ/Q9Kg2 +6slPnCs6cl8gLSWzsvvBAxGrV1fQVRO59RAJnlaiDZU8Fj5Z83FgUAZTRf8P4vhh +W9L8CmVZ3O5vxibEfSdpTXZVLwcBPzDqFz27ivDfrshHcA60KMnpe4yKIqDqMpv4 +HjWk8KUJgdyapNFjNJ48Mi/zsfBDO/Exm4uZv8K063g5o+fYLOZs8osvIYPDKBt3 +83Wbeffwc6CiR6+TMgvSiAQUOs1If1gy +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA3-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA3-key.pem new file mode 100644 index 000000000..47df99a7f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA3-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuDYMZqkGzqzgfIahaZ2+KM+jgfO03F/Ikp3yB8BeBNPldBn8 +z4V/95GM1Vh8AkyI8U1D4we9Kk7fUYcpdMUkZx3xb4sHdTmJcCqcAOAubHx0Jxg0 +/SmYQ4PW4VGzE0EcvCnciy+TCJWLkCJL5Jj11nAqm4tk5kkGYqQjCGBol4mpssCU +jk85HCU7D+TFHX2JiV7GAmlo/BNVtYBrd/dZVwscfsbtRsZw+zShKByCscKrpsHw +Ext9C7waOSM85x3uyO4vaV+hMT8aL5hdU9dCk9tJrNZ6Ei6dDcmw70DRpAJeUuj7 +1JIHmLF22RYP5Ive3Ihl4P1SHYvi4+0IN9AR9wIDAQABAoIBAFDLI9VC/UFYgX0c +b18rWGP97fDpOsINIKNtsuHDdXkYluK9IyzBmMa0h9hq3rkDaGytPsEse8M6pKfV +aFFWxgiUEXiiubqoaadQiOu5Z6MdUrRy4YrH24iBIpXgh3JCdJ/ynFBPpWV2cafd +4vt4Oxq6R3XBRZfbH3nUE6lw327Wqox7I/t4rYdAVTnyCcSo3MX35K37/xnplLos +ehyeDMJok+C/y2+jeICs/A89FcTAA6JrNqznE5ZWNBORSKOMJQcscNHWBGZ5vmpH +jW8WPpMPhtA4q26fz/XI2BwrHRKwsEKsVyULd3bfAEBLQbktuwMMylWsnrw/wzRN +aD+dbwECgYEA8ZJb0syBWlJD1/+p+1wgtteJ9RSZyXFHLRDglAYUKjVoZqhczSP2 +M/wkkTk71gI54lQBejNAKU+eH+IAsXCQDx3ePxlAlu3JSMaXd8KzgZwBd2rr3iNJ +grAUoYj9sr237oi2Lyc+vKMS+IUrbkYZKbAtn/D6bp5GkxWscmWt7UcCgYEAwzak +4J7ZsFWeuomlRfR/FNMidGUBc+J/7wo3NXwTH3PPZisrPv38smD7bc1zi/c7MS7+ +ptJpHApnjqqXf85vBHmH2hkyuIAJ+UYuNs29iAcvu1E9XmE4wz/GdrzxvhdCW/PW +qFPQAsNCYB/NQi0YQSwABkEIDPTq1F11aXV1TdECgYBcHD9w8FN+OhHuYWjSFD3R +Gfxbe8Br5AqMr3vCVVMJCRZG1nmUKtss1T6oNReQsYaauwdZLgOP/PDBHW7AObhk +WzIsAxfytLZkTnzgyFej2vVgMF/BctkLwNINCewaZGamyHAXKLKuQMvyAO0ffhEI +KUosSzliRm2IleIMOKMJ7wKBgQCJWML8fwcud68sE3hDFdjrr/lH52D0ReI5LvjV +Gqzhrju36JuOwGiwoGeGQ80OJy5wVl44xUXKws9Fo2TgOUAG5/LbUmtLQFrEFcqi +KHM3Z8b/hhMlekXTqeVa2WlEk1zPEWpwGDf8GaFzvCxQaSXthKWnwM2HQDKQpAjd +4BReYQKBgQCmJllIBUfS61JNstfV++kK3aEP7heGeUdYmFu255DK6UlsDmDx1TJ3 +NacApBE5y/xUEg7hZB3gBpn2PFZO6uVEJX+vrIoOzsOXMQSgWbeCOTe3BLZn+mF3 +tpfeW+xALGvvEajlv1/xUd2o/9DmgEIIIQWKPOKVjb6H5B1WnHa19Q== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA3-pathlen2.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA3-pathlen2.pem new file mode 100644 index 000000000..44e10332d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-ICA3-pathlen2.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-ICA3-pathlen2, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b8:36:0c:66:a9:06:ce:ac:e0:7c:86:a1:69:9d: + be:28:cf:a3:81:f3:b4:dc:5f:c8:92:9d:f2:07:c0: + 5e:04:d3:e5:74:19:fc:cf:85:7f:f7:91:8c:d5:58: + 7c:02:4c:88:f1:4d:43:e3:07:bd:2a:4e:df:51:87: + 29:74:c5:24:67:1d:f1:6f:8b:07:75:39:89:70:2a: + 9c:00:e0:2e:6c:7c:74:27:18:34:fd:29:98:43:83: + d6:e1:51:b3:13:41:1c:bc:29:dc:8b:2f:93:08:95: + 8b:90:22:4b:e4:98:f5:d6:70:2a:9b:8b:64:e6:49: + 06:62:a4:23:08:60:68:97:89:a9:b2:c0:94:8e:4f: + 39:1c:25:3b:0f:e4:c5:1d:7d:89:89:5e:c6:02:69: + 68:fc:13:55:b5:80:6b:77:f7:59:57:0b:1c:7e:c6: + ed:46:c6:70:fb:34:a1:28:1c:82:b1:c2:ab:a6:c1: + f0:13:1b:7d:0b:bc:1a:39:23:3c:e7:1d:ee:c8:ee: + 2f:69:5f:a1:31:3f:1a:2f:98:5d:53:d7:42:93:db: + 49:ac:d6:7a:12:2e:9d:0d:c9:b0:ef:40:d1:a4:02: + 5e:52:e8:fb:d4:92:07:98:b1:76:d9:16:0f:e4:8b: + de:dc:88:65:e0:fd:52:1d:8b:e2:e3:ed:08:37:d0: + 11:f7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EE:37:A6:F2:40:D0:EF:FD:22:C7:A3:B4:6C:57:47:40:B9:99:F9:8D + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:2 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 5a:8e:b7:fa:c9:b8:f9:a7:1e:fd:16:5b:75:4d:5e:b6:f2:6e: + c0:48:f3:7f:3e:61:59:25:64:8e:6a:e5:19:fb:03:20:93:de: + 0c:d9:88:68:e6:c3:9c:ad:b8:b1:08:a4:74:ef:e7:5c:1e:ea: + 3b:9f:0a:64:40:74:ff:d8:9d:14:38:d8:c7:68:f4:8c:b2:76: + cb:77:40:c4:55:23:b6:42:4c:82:16:47:a4:97:31:12:f0:ac: + e8:b9:aa:72:d8:e7:e5:5f:6c:92:0e:07:d7:9f:df:4b:53:85: + e5:d3:8b:74:ad:b3:58:09:d0:cf:2f:66:a3:28:8c:86:3a:5a: + c8:39:f5:03:35:42:72:8b:b8:fc:28:51:37:b0:31:f6:29:c4: + ab:f3:4f:ff:42:de:48:6d:bd:94:cd:3c:5a:bf:f3:a5:d2:13: + 2c:7b:81:d8:0d:2f:f0:49:bf:c2:07:25:a5:2a:ae:3c:9f:4a: + 3e:74:03:70:36:a9:67:68:1a:e8:72:18:2d:79:7e:65:2c:95: + 3a:5c:9d:46:50:d0:9a:fd:c1:7a:6d:cd:d6:6c:83:f2:cb:aa: + 19:c2:03:7c:2e:95:30:40:88:25:47:3c:d2:7a:ad:ac:a1:12: + 25:42:17:d0:17:00:53:4b:32:ae:70:a4:08:7b:9b:fc:bc:93: + 08:e6:b1:7a +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluSS1JQ0Ez +LXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuDYMZqkGzqzgfIahaZ2+KM+jgfO0 +3F/Ikp3yB8BeBNPldBn8z4V/95GM1Vh8AkyI8U1D4we9Kk7fUYcpdMUkZx3xb4sH +dTmJcCqcAOAubHx0Jxg0/SmYQ4PW4VGzE0EcvCnciy+TCJWLkCJL5Jj11nAqm4tk +5kkGYqQjCGBol4mpssCUjk85HCU7D+TFHX2JiV7GAmlo/BNVtYBrd/dZVwscfsbt +RsZw+zShKByCscKrpsHwExt9C7waOSM85x3uyO4vaV+hMT8aL5hdU9dCk9tJrNZ6 +Ei6dDcmw70DRpAJeUuj71JIHmLF22RYP5Ive3Ihl4P1SHYvi4+0IN9AR9wIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFO43pvJA0O/9IsejtGxXR0C5mfmNMIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQBajrf6ybj5px79Flt1TV628m7ASPN/PmFZJWSOauUZ+wMgk94M2Yho5sOc +rbixCKR07+dcHuo7nwpkQHT/2J0UONjHaPSMsnbLd0DEVSO2QkyCFkeklzES8Kzo +uapy2OflX2ySDgfXn99LU4Xl04t0rbNYCdDPL2ajKIyGOlrIOfUDNUJyi7j8KFE3 +sDH2KcSr80//Qt5Ibb2UzTxav/Ol0hMse4HYDS/wSb/CByWlKq48n0o+dANwNqln +aBrochgteX5lLJU6XJ1GUNCa/cF6bc3WbIPyy6oZwgN8LpUwQIglRzzSeq2soRIl +QhfQFwBTSzKucKQIe5v8vJMI5rF6 +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-assembled.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-assembled.pem new file mode 100644 index 000000000..baf1cdcf0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-assembled.pem @@ -0,0 +1,354 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-ICA1-no_pathlen, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:f3:ac:32:8f:52:af:a9:cf:9e:23:a4:96:8e:e9: + e8:0a:3a:b7:6a:7b:ba:70:85:68:e2:52:f3:38:39: + cf:c8:f1:8a:f6:55:1e:59:fa:97:fe:e7:9b:07:2a: + b6:80:2a:92:d9:39:95:9e:0c:1f:d7:ad:1f:74:4d: + 8e:61:6f:64:24:4c:d4:95:03:8f:d3:f2:3d:6e:d8: + d8:d5:aa:64:7d:82:ee:74:07:16:68:fa:95:17:9b: + 35:8f:c3:6c:47:88:3e:40:de:93:36:ed:62:f4:cc: + 67:45:ee:ea:45:9f:fc:f1:63:6d:b7:fa:f8:c3:e0: + 6f:c7:4a:3e:04:49:04:37:8b:3a:99:e8:64:0a:86: + 43:ab:5b:34:1e:6c:33:a2:a4:26:7c:c7:6c:48:99: + 7d:85:f5:1f:c1:9c:a9:c7:8f:51:6b:8a:86:8d:1c: + b0:d2:82:ba:a4:a7:09:29:8b:0a:20:d1:7c:b1:67: + 0c:61:cd:88:33:5e:38:ab:08:78:0b:80:0b:ce:63: + 03:b9:40:7b:67:3e:a8:ac:4e:44:92:09:4c:3f:e0: + 3d:55:cb:aa:5a:bc:17:9c:4e:9e:40:5c:82:fc:3b: + 3a:54:40:90:f9:22:3c:f4:00:5f:95:13:72:49:29: + ae:5f:31:22:30:04:05:6a:7b:b5:0a:0a:a6:5e:72: + 4d:5f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EB:B5:A2:7B:24:95:03:11:6B:56:CB:13:3E:A8:B2:8F:B1:CF:5D:C4 + X509v3 Authority Key Identifier: + keyid:9E:54:B6:95:EA:89:07:A6:C9:E4:82:E8:D0:34:64:5D:08:CD:56:A0 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainI-ICA2-no_pathlen/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 78:f3:ac:4b:db:c6:63:c3:f5:67:97:b8:99:f4:72:6f:b2:07: + 3b:99:ce:85:e7:5c:59:c1:80:bf:06:92:a8:34:be:1b:74:d1: + 61:b6:75:07:18:0e:2e:77:7f:77:c7:e9:5d:cc:1e:7b:b5:04: + 95:5b:99:a1:15:2e:b6:2b:67:13:09:0f:b7:6e:62:04:dd:01: + 27:fd:18:f3:d9:b2:d7:8f:6e:bb:b3:1d:57:76:91:42:dd:78: + 77:22:b3:ed:79:10:63:94:40:c5:88:09:bb:bf:fd:fe:6e:60: + 23:53:30:8e:11:e2:b7:3d:39:24:96:f2:86:cc:59:eb:83:07: + ad:7a:2e:85:63:be:70:15:92:f8:f2:2b:f1:6f:5f:c2:4d:3a: + 7d:c6:b9:9d:c4:82:6a:fe:b2:7e:ec:5d:eb:b3:ba:82:09:04: + f9:7e:47:37:a9:8a:e2:2a:4f:30:7d:b7:dd:1f:c2:f4:db:61: + f3:b1:81:5d:10:8c:41:22:76:93:5b:a3:b9:b2:69:85:88:3a: + eb:ae:42:0f:16:e7:2f:f3:cd:03:4c:08:65:90:a9:4f:dd:89: + 23:d7:56:bd:e9:d7:cf:9f:bf:0f:a2:11:5b:e1:89:2c:d4:76: + 16:1f:83:5c:e9:8c:f6:93:7c:b5:f2:f1:ef:d3:07:35:2f:93: + 33:16:9c:63 +-----BEGIN CERTIFICATE----- +MIIEvDCCA6SgAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluSS1JQ0ExLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBmjELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxFjAUBgNV +BAMMDWNoYWluSS1lbnRpdHkxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDzrDKPUq+pz54jpJaO +6egKOrdqe7pwhWjiUvM4Oc/I8Yr2VR5Z+pf+55sHKraAKpLZOZWeDB/XrR90TY5h +b2QkTNSVA4/T8j1u2NjVqmR9gu50BxZo+pUXmzWPw2xHiD5A3pM27WL0zGdF7upF +n/zxY223+vjD4G/HSj4ESQQ3izqZ6GQKhkOrWzQebDOipCZ8x2xImX2F9R/BnKnH +j1FrioaNHLDSgrqkpwkpiwog0XyxZwxhzYgzXjirCHgLgAvOYwO5QHtnPqisTkSS +CUw/4D1Vy6pavBecTp5AXIL8OzpUQJD5Ijz0AF+VE3JJKa5fMSIwBAVqe7UKCqZe +ck1fAgMBAAGjggEAMIH9MB0GA1UdDgQWBBTrtaJ7JJUDEWtWyxM+qLKPsc9dxDCB +0AYDVR0jBIHIMIHFgBSeVLaV6okHpsnkgujQNGRdCM1WoKGBqaSBpjCBozELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +FTATBgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAd +BgNVBAMMFmNoYWluSS1JQ0EyLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGlu +Zm9Ad29sZnNzbC5jb22CAWQwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA +ePOsS9vGY8P1Z5e4mfRyb7IHO5nOhedcWcGAvwaSqDS+G3TRYbZ1BxgOLnd/d8fp +Xcwee7UElVuZoRUutitnEwkPt25iBN0BJ/0Y89my149uu7MdV3aRQt14dyKz7XkQ +Y5RAxYgJu7/9/m5gI1MwjhHitz05JJbyhsxZ64MHrXouhWO+cBWS+PIr8W9fwk06 +fca5ncSCav6yfuxd67O6ggkE+X5HN6mK4ipPMH233R/C9Nth87GBXRCMQSJ2k1uj +ubJphYg6665CDxbnL/PNA0wIZZCpT92JI9dWvenXz5+/D6IRW+GJLNR2Fh+DXOmM +9pN8tfLx79MHNS+TMxacYw== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-ICA2-no_pathlen, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-ICA1-no_pathlen, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bb:ba:06:ad:13:cf:da:fb:d1:cb:65:fe:26:58: + 49:6a:01:14:a6:78:b2:2c:1d:ba:ba:d0:bd:27:38: + 66:7c:a0:1b:28:08:3c:6a:fd:f8:87:be:49:a2:ed: + 38:f2:4c:b0:8b:93:ff:d2:c5:3f:cd:03:c5:14:79: + e8:76:63:7a:aa:a7:54:1e:0e:27:bd:1b:be:e8:3f: + 2b:55:40:f0:59:23:d8:3f:e8:05:1a:0b:71:f0:fd: + 24:d9:f9:0b:99:25:da:af:96:34:ee:e1:91:cb:fc: + 8f:a0:41:8f:9c:e1:4f:57:5f:b6:d6:55:69:6f:c3: + 64:c3:11:a9:69:40:85:df:f3:9a:59:b5:ee:90:c0: + 22:ee:72:28:2e:d3:da:65:27:3b:ba:42:c0:9e:73: + ba:a2:f2:45:13:7a:c5:1d:30:a5:b7:db:75:5d:6f: + cc:08:77:80:67:8d:18:2a:ca:02:8d:8e:d3:9c:2a: + fa:b7:8f:1b:7d:ef:62:77:a4:fa:b6:d8:5a:3e:66: + 9c:3e:13:45:a8:cf:61:fb:ff:41:45:14:21:e2:63: + ac:81:4d:65:89:e3:d5:71:20:01:19:76:ec:a4:16: + a6:ef:3c:bc:f2:a2:56:2b:07:31:67:0d:e5:97:88: + e8:db:cb:4d:98:cb:99:e6:e0:bd:62:48:2b:b1:04: + 12:07 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 9E:54:B6:95:EA:89:07:A6:C9:E4:82:E8:D0:34:64:5D:08:CD:56:A0 + X509v3 Authority Key Identifier: + keyid:D1:BA:FB:FF:1D:29:41:8A:6A:5F:B2:F3:A7:41:05:47:09:1F:48:42 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainI-ICA3-pathlen2/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + b3:b8:b9:c2:44:3a:36:0a:cf:fd:da:80:8c:81:54:c1:cd:a6: + 52:a8:60:b1:f8:fd:62:01:fc:d9:85:89:15:9a:df:45:f0:68: + 3e:bb:fe:f3:94:dc:1c:69:3c:7c:47:df:04:0c:7b:2f:4f:3f: + 56:58:9a:fa:1a:4c:16:21:cf:f2:21:a5:f9:d9:49:1b:69:b4: + 4d:df:d0:c2:d7:2c:fa:0f:23:d6:45:61:12:cd:2a:5a:06:db: + 22:6f:99:7a:a0:fc:17:ba:05:bc:02:79:db:f8:cd:ec:a0:98: + 7c:7f:6b:d6:ca:5c:cd:07:89:b6:0d:3e:0b:d3:d7:7f:7c:6b: + 73:7b:b9:28:69:d2:5f:27:1c:13:60:a0:50:23:16:00:d1:cb: + 7a:1d:62:7c:a1:c2:63:1d:c9:0b:0f:d7:5c:91:af:7a:5b:93: + 7e:e5:12:36:f0:3b:fa:59:7b:a8:88:f7:bf:11:19:4b:6a:81: + 61:77:54:61:a3:73:b6:54:64:92:49:22:c9:6a:19:73:33:6d: + 01:4c:5a:9c:0a:fa:ce:a1:34:50:b1:54:de:0b:7b:ce:fe:e0: + 00:fa:8e:7f:48:36:58:ed:98:42:ce:8d:a4:a0:67:c9:88:1c: + 7f:58:df:fb:62:0f:ee:4b:7d:5a:c7:52:2f:9f:2d:13:13:0b: + 72:bd:a0:2e +-----BEGIN CERTIFICATE----- +MIIE1DCCA7ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluSS1JQ0EyLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBozELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNV +BAMMFmNoYWluSS1JQ0ExLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9A +d29sZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7ugat +E8/a+9HLZf4mWElqARSmeLIsHbq60L0nOGZ8oBsoCDxq/fiHvkmi7TjyTLCLk//S +xT/NA8UUeeh2Y3qqp1QeDie9G77oPytVQPBZI9g/6AUaC3Hw/STZ+QuZJdqvljTu +4ZHL/I+gQY+c4U9XX7bWVWlvw2TDEalpQIXf85pZte6QwCLucigu09plJzu6QsCe +c7qi8kUTesUdMKW323Vdb8wId4BnjRgqygKNjtOcKvq3jxt972J3pPq22Fo+Zpw+ +E0Woz2H7/0FFFCHiY6yBTWWJ49VxIAEZduykFqbvPLzyolYrBzFnDeWXiOjby02Y +y5nm4L1iSCuxBBIHAgMBAAGjggEPMIIBCzAdBgNVHQ4EFgQUnlS2leqJB6bJ5ILo +0DRkXQjNVqAwgc4GA1UdIwSBxjCBw4AU0br7/x0pQYpqX7Lzp0EFRwkfSEKhgaek +gaQwgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRUwEwYDVQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2lu +ZWVyaW5nMR0wGwYDVQQDDBRjaGFpbkktSUNBMy1wYXRobGVuMjEfMB0GCSqGSIb3 +DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIBZDAMBgNVHRMEBTADAQH/MAsGA1UdDwQE +AwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAs7i5wkQ6NgrP/dqAjIFUwc2mUqhgsfj9 +YgH82YWJFZrfRfBoPrv+85TcHGk8fEffBAx7L08/Vlia+hpMFiHP8iGl+dlJG2m0 +Td/Qwtcs+g8j1kVhEs0qWgbbIm+ZeqD8F7oFvAJ52/jN7KCYfH9r1spczQeJtg0+ +C9PXf3xrc3u5KGnSXyccE2CgUCMWANHLeh1ifKHCYx3JCw/XXJGveluTfuUSNvA7 ++ll7qIj3vxEZS2qBYXdUYaNztlRkkkkiyWoZczNtAUxanAr6zqE0ULFU3gt7zv7g +APqOf0g2WO2YQs6NpKBnyYgcf1jf+2IP7kt9WsdSL58tExMLcr2gLg== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-ICA3-pathlen2, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-ICA2-no_pathlen, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:de:1e:08:66:12:fe:20:07:10:1b:a1:27:0d:f9: + 22:30:81:9b:ce:62:b1:a6:6d:49:d4:ed:b8:2d:4b: + 97:77:1e:94:51:3d:73:2b:16:e9:05:e9:4c:1b:82: + ad:47:9d:33:30:53:b5:9b:d2:2d:e9:7b:d6:63:f3: + 61:20:1b:23:6e:47:09:8b:c0:d5:09:85:a6:e2:e4: + 3a:4d:b3:f9:dd:c6:7c:9a:42:07:22:d5:7b:67:18: + 38:c4:fc:ea:8d:09:80:a0:b0:44:33:fd:c1:aa:8b: + 9c:98:e3:95:c3:74:71:3b:71:b8:b3:80:bf:30:63: + 85:09:27:8b:12:b5:86:b0:0b:99:ff:97:42:52:a0: + ac:b2:38:38:8d:13:96:d9:d6:fa:8f:c4:89:14:06: + 9c:1f:0a:a3:3a:a2:f7:1f:83:d8:ae:41:44:9e:21: + b2:5b:b7:a2:19:e9:46:58:de:e5:a2:ab:07:7a:9a: + 9a:60:bc:14:ed:cf:4d:42:fc:5c:28:ea:42:d1:ae: + cc:71:7e:52:5d:84:88:de:b6:7d:72:6e:ab:73:4b: + 0d:ab:92:9f:11:b4:51:da:14:54:9a:0e:ec:ac:42: + fc:71:87:5b:54:38:09:2c:f0:5d:86:0c:34:b7:92: + 33:5c:3e:19:b1:4d:a0:62:9b:b4:68:36:36:38:ec: + 29:b3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + D1:BA:FB:FF:1D:29:41:8A:6A:5F:B2:F3:A7:41:05:47:09:1F:48:42 + X509v3 Authority Key Identifier: + keyid:EE:37:A6:F2:40:D0:EF:FD:22:C7:A3:B4:6C:57:47:40:B9:99:F9:8D + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 8f:9b:f7:bd:1a:90:58:f0:ab:0f:1d:45:b2:29:10:66:2d:cc: + 96:d6:3c:f4:3c:a8:49:e2:cf:db:17:16:8c:e8:76:de:79:c9: + 42:10:a7:ad:b7:c3:c2:82:93:6b:19:3e:56:af:be:c8:d7:dd: + ee:87:1d:5f:1d:ad:6a:02:8d:14:22:9f:54:58:d7:d8:16:79: + 64:4d:eb:55:88:74:74:f6:59:2c:40:9f:d0:f4:a8:36:ea:c9: + 4f:9c:2b:3a:72:5f:20:2d:25:b3:b2:fb:c1:03:11:ab:57:57: + d0:55:13:b9:f5:10:09:9e:56:a2:0d:95:3c:16:3e:59:f3:71: + 60:50:06:53:45:ff:0f:e2:f8:61:5b:d2:fc:0a:65:59:dc:ee: + 6f:c6:26:c4:7d:27:69:4d:76:55:2f:07:01:3f:30:ea:17:3d: + bb:8a:f0:df:ae:c8:47:70:0e:b4:28:c9:e9:7b:8c:8a:22:a0: + ea:32:9b:f8:1e:35:a4:f0:a5:09:81:dc:9a:a4:d1:63:34:9e: + 3c:32:2f:f3:b1:f0:43:3b:f1:31:9b:8b:99:bf:c2:b4:eb:78: + 39:a3:e7:d8:2c:e6:6c:f2:8b:2f:21:83:c3:28:1b:77:f3:75: + 9b:79:f7:f0:73:a0:a2:47:af:93:32:0b:d2:88:04:14:3a:cd: + 48:7f:58:32 +-----BEGIN CERTIFICATE----- +MIIExDCCA6ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluSS1JQ0EzLXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTE4MzAzMFoXDTIyMDcwNzE4MzAzMFowgaMxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR8wHQYDVQQD +DBZjaGFpbkktSUNBMi1ub19wYXRobGVuMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3h4IZhL+ +IAcQG6EnDfkiMIGbzmKxpm1J1O24LUuXdx6UUT1zKxbpBelMG4KtR50zMFO1m9It +6XvWY/NhIBsjbkcJi8DVCYWm4uQ6TbP53cZ8mkIHItV7Zxg4xPzqjQmAoLBEM/3B +qoucmOOVw3RxO3G4s4C/MGOFCSeLErWGsAuZ/5dCUqCssjg4jROW2db6j8SJFAac +HwqjOqL3H4PYrkFEniGyW7eiGelGWN7loqsHepqaYLwU7c9NQvxcKOpC0a7McX5S +XYSI3rZ9cm6rc0sNq5KfEbRR2hRUmg7srEL8cYdbVDgJLPBdhgw0t5IzXD4ZsU2g +Ypu0aDY2OOwpswIDAQABo4IBATCB/jAdBgNVHQ4EFgQU0br7/x0pQYpqX7Lzp0EF +RwkfSEIwgcEGA1UdIwSBuTCBtoAU7jem8kDQ7/0ix6O0bFdHQLmZ+Y2hgZqkgZcw +gZQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3pl +bWFuMREwDwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYG +A1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tggFkMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEB +CwUAA4IBAQCPm/e9GpBY8KsPHUWyKRBmLcyW1jz0PKhJ4s/bFxaM6HbeeclCEKet +t8PCgpNrGT5Wr77I193uhx1fHa1qAo0UIp9UWNfYFnlkTetViHR09lksQJ/Q9Kg2 +6slPnCs6cl8gLSWzsvvBAxGrV1fQVRO59RAJnlaiDZU8Fj5Z83FgUAZTRf8P4vhh +W9L8CmVZ3O5vxibEfSdpTXZVLwcBPzDqFz27ivDfrshHcA60KMnpe4yKIqDqMpv4 +HjWk8KUJgdyapNFjNJ48Mi/zsfBDO/Exm4uZv8K063g5o+fYLOZs8osvIYPDKBt3 +83Wbeffwc6CiR6+TMgvSiAQUOs1If1gy +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-ICA3-pathlen2, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b8:36:0c:66:a9:06:ce:ac:e0:7c:86:a1:69:9d: + be:28:cf:a3:81:f3:b4:dc:5f:c8:92:9d:f2:07:c0: + 5e:04:d3:e5:74:19:fc:cf:85:7f:f7:91:8c:d5:58: + 7c:02:4c:88:f1:4d:43:e3:07:bd:2a:4e:df:51:87: + 29:74:c5:24:67:1d:f1:6f:8b:07:75:39:89:70:2a: + 9c:00:e0:2e:6c:7c:74:27:18:34:fd:29:98:43:83: + d6:e1:51:b3:13:41:1c:bc:29:dc:8b:2f:93:08:95: + 8b:90:22:4b:e4:98:f5:d6:70:2a:9b:8b:64:e6:49: + 06:62:a4:23:08:60:68:97:89:a9:b2:c0:94:8e:4f: + 39:1c:25:3b:0f:e4:c5:1d:7d:89:89:5e:c6:02:69: + 68:fc:13:55:b5:80:6b:77:f7:59:57:0b:1c:7e:c6: + ed:46:c6:70:fb:34:a1:28:1c:82:b1:c2:ab:a6:c1: + f0:13:1b:7d:0b:bc:1a:39:23:3c:e7:1d:ee:c8:ee: + 2f:69:5f:a1:31:3f:1a:2f:98:5d:53:d7:42:93:db: + 49:ac:d6:7a:12:2e:9d:0d:c9:b0:ef:40:d1:a4:02: + 5e:52:e8:fb:d4:92:07:98:b1:76:d9:16:0f:e4:8b: + de:dc:88:65:e0:fd:52:1d:8b:e2:e3:ed:08:37:d0: + 11:f7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EE:37:A6:F2:40:D0:EF:FD:22:C7:A3:B4:6C:57:47:40:B9:99:F9:8D + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:2 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 5a:8e:b7:fa:c9:b8:f9:a7:1e:fd:16:5b:75:4d:5e:b6:f2:6e: + c0:48:f3:7f:3e:61:59:25:64:8e:6a:e5:19:fb:03:20:93:de: + 0c:d9:88:68:e6:c3:9c:ad:b8:b1:08:a4:74:ef:e7:5c:1e:ea: + 3b:9f:0a:64:40:74:ff:d8:9d:14:38:d8:c7:68:f4:8c:b2:76: + cb:77:40:c4:55:23:b6:42:4c:82:16:47:a4:97:31:12:f0:ac: + e8:b9:aa:72:d8:e7:e5:5f:6c:92:0e:07:d7:9f:df:4b:53:85: + e5:d3:8b:74:ad:b3:58:09:d0:cf:2f:66:a3:28:8c:86:3a:5a: + c8:39:f5:03:35:42:72:8b:b8:fc:28:51:37:b0:31:f6:29:c4: + ab:f3:4f:ff:42:de:48:6d:bd:94:cd:3c:5a:bf:f3:a5:d2:13: + 2c:7b:81:d8:0d:2f:f0:49:bf:c2:07:25:a5:2a:ae:3c:9f:4a: + 3e:74:03:70:36:a9:67:68:1a:e8:72:18:2d:79:7e:65:2c:95: + 3a:5c:9d:46:50:d0:9a:fd:c1:7a:6d:cd:d6:6c:83:f2:cb:aa: + 19:c2:03:7c:2e:95:30:40:88:25:47:3c:d2:7a:ad:ac:a1:12: + 25:42:17:d0:17:00:53:4b:32:ae:70:a4:08:7b:9b:fc:bc:93: + 08:e6:b1:7a +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluSS1JQ0Ez +LXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuDYMZqkGzqzgfIahaZ2+KM+jgfO0 +3F/Ikp3yB8BeBNPldBn8z4V/95GM1Vh8AkyI8U1D4we9Kk7fUYcpdMUkZx3xb4sH +dTmJcCqcAOAubHx0Jxg0/SmYQ4PW4VGzE0EcvCnciy+TCJWLkCJL5Jj11nAqm4tk +5kkGYqQjCGBol4mpssCUjk85HCU7D+TFHX2JiV7GAmlo/BNVtYBrd/dZVwscfsbt +RsZw+zShKByCscKrpsHwExt9C7waOSM85x3uyO4vaV+hMT8aL5hdU9dCk9tJrNZ6 +Ei6dDcmw70DRpAJeUuj71JIHmLF22RYP5Ive3Ihl4P1SHYvi4+0IN9AR9wIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFO43pvJA0O/9IsejtGxXR0C5mfmNMIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQBajrf6ybj5px79Flt1TV628m7ASPN/PmFZJWSOauUZ+wMgk94M2Yho5sOc +rbixCKR07+dcHuo7nwpkQHT/2J0UONjHaPSMsnbLd0DEVSO2QkyCFkeklzES8Kzo +uapy2OflX2ySDgfXn99LU4Xl04t0rbNYCdDPL2ajKIyGOlrIOfUDNUJyi7j8KFE3 +sDH2KcSr80//Qt5Ibb2UzTxav/Ol0hMse4HYDS/wSb/CByWlKq48n0o+dANwNqln +aBrochgteX5lLJU6XJ1GUNCa/cF6bc3WbIPyy6oZwgN8LpUwQIglRzzSeq2soRIl +QhfQFwBTSzKucKQIe5v8vJMI5rF6 +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-entity-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-entity-key.pem new file mode 100644 index 000000000..e0a823b0c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-entity-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA86wyj1Kvqc+eI6SWjunoCjq3anu6cIVo4lLzODnPyPGK9lUe +WfqX/uebByq2gCqS2TmVngwf160fdE2OYW9kJEzUlQOP0/I9btjY1apkfYLudAcW +aPqVF5s1j8NsR4g+QN6TNu1i9MxnRe7qRZ/88WNtt/r4w+Bvx0o+BEkEN4s6mehk +CoZDq1s0HmwzoqQmfMdsSJl9hfUfwZypx49Ra4qGjRyw0oK6pKcJKYsKINF8sWcM +Yc2IM144qwh4C4ALzmMDuUB7Zz6orE5EkglMP+A9VcuqWrwXnE6eQFyC/Ds6VECQ ++SI89ABflRNySSmuXzEiMAQFanu1CgqmXnJNXwIDAQABAoIBACx9nmWo1UYOEHO1 +k3/YmXN0sRSSLsJouXPJbXswow2vfI3pkLchGCuEoju2wse3/kQHTZgj4pSAmaOk +nYCQ1BoEpTPoCJTMQAdDNKQejmaUR3GL8b2NMzeyMR9ksRqGd8dkXEDFKzJDN//+ +1WuNAKQaYWgcPNuW2RHsLlKd+lUhjYR/Qe6pj+Jzxhh9Kbt5GHAyj1BTXQzkv5O5 +FpshP331WryxI0r/Q4lwKHrthBXm2PgKUEeh5M7dokAMCaBZmN0ZTbI644tvNsi5 +FR9rTqRHhxtwmk5sMKEavncISY85T+R63XKfUHTQZkWXEiPB3DJoJAbsDVpBb+BI +j3Ton2ECgYEA/WDYGonfKB7x8wwZgBVnnvoMGOqSm8mj42kw3cAaXqtIrJOF+iL8 +kKMq5YJ2W+GlbdNF1oawG+I9gWK9THOcp0JnRXedGNWlfKrW7HHeugT6OR9D8ZiX +4O0M7QJqIdWWN9QpVHhPfySdzF+PopT73o38MtnEF28cIck3ptFqQpcCgYEA9jGl +DSxfFXjoPKinHf6QWkyKeOqHIWYEuIxv2tQ+KpsvTzZ6hEdS2ZeiWcGRCxvlGNxu +/e7sCVUOCVs+FYyb3kN0TW9Hx+0l8H02Lnt3ar7lQmfp4fDw2HsRm6ONTUPZnXCV +2Odpi7PlnHOSR4j2kta4HQL7l2pZJ3n6wPasTHkCgYEA+2UbBTnGMAiEBqH6qxqR +tSpi1lXnIKrv8LJtyZbQkx1e/dthEs2jyd4asZy/0moPuOfmYvM/yGqwm69cIn6S +72DzFfmX5QwVJZxboj1YvzgxDHv47bx49LI+IOpEY02HvdzDJQw50+yApEYsPSOU +wzwc/lcSOC4Fu3/pt5oP1AECgYEA52eCW/944BXlNB7R9b9wr2+COGU43oulpFFc +UbNtO17h+PKb9fmURjHgx7zJOEff7p5DNSt9cMghiWnZ0Sd42lFM3/vY3HJrVsBa +TRaACDWmB+TkURrHRrNmuYPhLN65jOJl9pqM+mL9TzDSLarvGNX5+Er1cDzlz9U3 +fGhfSwECgYEAzUUcI9nvFvh4XQWCbJVDr3iQrupozRCfYmFjuJpx8KHm+Z01lY50 +uTJ+NOBJHCgS6Ikyz4VIkqpbw4AbxlWN0Se7FjlaoiUkj9KAl1ifM5cl70KN13az +1i3a0a8yrIdCAxDenm9UCQH2NIfL4NdFlI2BZglB6PI/HwQ/NwZAkEc= +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-entity.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-entity.pem new file mode 100644 index 000000000..1e7564198 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainI-entity.pem @@ -0,0 +1,87 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-ICA1-no_pathlen, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainI-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:f3:ac:32:8f:52:af:a9:cf:9e:23:a4:96:8e:e9: + e8:0a:3a:b7:6a:7b:ba:70:85:68:e2:52:f3:38:39: + cf:c8:f1:8a:f6:55:1e:59:fa:97:fe:e7:9b:07:2a: + b6:80:2a:92:d9:39:95:9e:0c:1f:d7:ad:1f:74:4d: + 8e:61:6f:64:24:4c:d4:95:03:8f:d3:f2:3d:6e:d8: + d8:d5:aa:64:7d:82:ee:74:07:16:68:fa:95:17:9b: + 35:8f:c3:6c:47:88:3e:40:de:93:36:ed:62:f4:cc: + 67:45:ee:ea:45:9f:fc:f1:63:6d:b7:fa:f8:c3:e0: + 6f:c7:4a:3e:04:49:04:37:8b:3a:99:e8:64:0a:86: + 43:ab:5b:34:1e:6c:33:a2:a4:26:7c:c7:6c:48:99: + 7d:85:f5:1f:c1:9c:a9:c7:8f:51:6b:8a:86:8d:1c: + b0:d2:82:ba:a4:a7:09:29:8b:0a:20:d1:7c:b1:67: + 0c:61:cd:88:33:5e:38:ab:08:78:0b:80:0b:ce:63: + 03:b9:40:7b:67:3e:a8:ac:4e:44:92:09:4c:3f:e0: + 3d:55:cb:aa:5a:bc:17:9c:4e:9e:40:5c:82:fc:3b: + 3a:54:40:90:f9:22:3c:f4:00:5f:95:13:72:49:29: + ae:5f:31:22:30:04:05:6a:7b:b5:0a:0a:a6:5e:72: + 4d:5f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EB:B5:A2:7B:24:95:03:11:6B:56:CB:13:3E:A8:B2:8F:B1:CF:5D:C4 + X509v3 Authority Key Identifier: + keyid:9E:54:B6:95:EA:89:07:A6:C9:E4:82:E8:D0:34:64:5D:08:CD:56:A0 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainI-ICA2-no_pathlen/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 78:f3:ac:4b:db:c6:63:c3:f5:67:97:b8:99:f4:72:6f:b2:07: + 3b:99:ce:85:e7:5c:59:c1:80:bf:06:92:a8:34:be:1b:74:d1: + 61:b6:75:07:18:0e:2e:77:7f:77:c7:e9:5d:cc:1e:7b:b5:04: + 95:5b:99:a1:15:2e:b6:2b:67:13:09:0f:b7:6e:62:04:dd:01: + 27:fd:18:f3:d9:b2:d7:8f:6e:bb:b3:1d:57:76:91:42:dd:78: + 77:22:b3:ed:79:10:63:94:40:c5:88:09:bb:bf:fd:fe:6e:60: + 23:53:30:8e:11:e2:b7:3d:39:24:96:f2:86:cc:59:eb:83:07: + ad:7a:2e:85:63:be:70:15:92:f8:f2:2b:f1:6f:5f:c2:4d:3a: + 7d:c6:b9:9d:c4:82:6a:fe:b2:7e:ec:5d:eb:b3:ba:82:09:04: + f9:7e:47:37:a9:8a:e2:2a:4f:30:7d:b7:dd:1f:c2:f4:db:61: + f3:b1:81:5d:10:8c:41:22:76:93:5b:a3:b9:b2:69:85:88:3a: + eb:ae:42:0f:16:e7:2f:f3:cd:03:4c:08:65:90:a9:4f:dd:89: + 23:d7:56:bd:e9:d7:cf:9f:bf:0f:a2:11:5b:e1:89:2c:d4:76: + 16:1f:83:5c:e9:8c:f6:93:7c:b5:f2:f1:ef:d3:07:35:2f:93: + 33:16:9c:63 +-----BEGIN CERTIFICATE----- +MIIEvDCCA6SgAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluSS1JQ0ExLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBmjELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxFjAUBgNV +BAMMDWNoYWluSS1lbnRpdHkxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDzrDKPUq+pz54jpJaO +6egKOrdqe7pwhWjiUvM4Oc/I8Yr2VR5Z+pf+55sHKraAKpLZOZWeDB/XrR90TY5h +b2QkTNSVA4/T8j1u2NjVqmR9gu50BxZo+pUXmzWPw2xHiD5A3pM27WL0zGdF7upF +n/zxY223+vjD4G/HSj4ESQQ3izqZ6GQKhkOrWzQebDOipCZ8x2xImX2F9R/BnKnH +j1FrioaNHLDSgrqkpwkpiwog0XyxZwxhzYgzXjirCHgLgAvOYwO5QHtnPqisTkSS +CUw/4D1Vy6pavBecTp5AXIL8OzpUQJD5Ijz0AF+VE3JJKa5fMSIwBAVqe7UKCqZe +ck1fAgMBAAGjggEAMIH9MB0GA1UdDgQWBBTrtaJ7JJUDEWtWyxM+qLKPsc9dxDCB +0AYDVR0jBIHIMIHFgBSeVLaV6okHpsnkgujQNGRdCM1WoKGBqaSBpjCBozELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +FTATBgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAd +BgNVBAMMFmNoYWluSS1JQ0EyLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGlu +Zm9Ad29sZnNzbC5jb22CAWQwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA +ePOsS9vGY8P1Z5e4mfRyb7IHO5nOhedcWcGAvwaSqDS+G3TRYbZ1BxgOLnd/d8fp +Xcwee7UElVuZoRUutitnEwkPt25iBN0BJ/0Y89my149uu7MdV3aRQt14dyKz7XkQ +Y5RAxYgJu7/9/m5gI1MwjhHitz05JJbyhsxZ64MHrXouhWO+cBWS+PIr8W9fwk06 +fca5ncSCav6yfuxd67O6ggkE+X5HN6mK4ipPMH233R/C9Nth87GBXRCMQSJ2k1uj +ubJphYg6665CDxbnL/PNA0wIZZCpT92JI9dWvenXz5+/D6IRW+GJLNR2Fh+DXOmM +9pN8tfLx79MHNS+TMxacYw== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA1-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA1-key.pem new file mode 100644 index 000000000..e67a06832 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA1-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAp29EwhHMLPQqpagIU0sOzZYjuxVKKt35pxkrkSjoc6NXtEk6 +N4KPFThaqq+tciYuhMIN3vzwvjuiEakSINQ93mKFhZEIYNvASruJtvSRHlGjsvcI +md9ISlmE0aoJNg3NaKWuQcjXGtjqSYcgIif5RVQ+x8gARH40cqqNLU1qPnWJ4tQX +V/nNK9C3FGpUG2Gvm2gisRZz6wVsQertEE68gwRoyDrhAxKtKFwkTBmhftjvG4Dk +DkkMaYb2HucB+ypvVhttCq3pKT8xu0goQHkrtfOq7OkJTIL8lygZozrA0l6jipjI +irfSxJC8/8xHE5CtAKuK7PeUNQlgEDWfMsUAGwIDAQABAoIBAD9XZ8Knav+Cq3OZ ++vRPy9zYtNG8vx8ydJTTf9jdifrdS3unzD9dw/V6KUqzRUGO0kBlDUxTklvVQX2+ +4V3MDU/JI8wgzvOdjsR26CVvpkq7BdvZesaDYtzFuup6khuB4zh4nVDDwySj9RY1 +6WEikDm7IjkAH6HJwNu0S85coBnaTs7Sxi+LcAwFlHybEZfb5hz0MdLcLlJ3E7Oz +6Ni/W/SsFBPsO7u7BlNB37tvBlxwpws1sKgpN1EHaDhctQxGODkfAK66PPbG75lO +vqROQWdFc7e3IKQ//A3ORXjNGfCYs8kV/VLA2RjjDPrVb3d7OHxufaAXUxNN5+N1 +7chonQECgYEA00PYedTkZiY2ljJBQB5vxoCZt9wGMe91u/SjWUfLMs2upBgGWDCx +5loZybzUMkBXRK+TSy0kdJndNSPWFxnSmOEFE6Im99MBFJu2iuy7HyHjSTlUEQp1 +Y1CbSzQRCXMNsdJjWnTEz9y8r6gQMhbhMB1Gn5MK3cSmrfv1LwTOvIECgYEAyuN8 +jLWMVfBTN9B/hWTLMLQF7fHhxT53ZBzA9+xnMo+TCDTqZABeyyO1/9jVIvcF4PEO +tmGFaQYaGlxP9fMJyuEEcmYXU8pSqFmK/HHvaHL+MDBjRPudz9En9visBtcoVyYq +z6oRFKsNCjcctxZ9/N20gfaYCrgzFTCTkPWh3psCgYAQKBwiFRnyhfGewvEiijFa +KPOYkAcZQorqeOcVKNxtYjV87yltDSxNxY47U2mW/jyuUA8frLAhCrNUIQ16bssg +TfUpbzkzsrtebBolvb0BwIG1U+EN/JLFqaB2u+ChrF7bvo9Cl7OFgggcFupGKmHG +YDbKdWBbXXKx05cIpYF6AQKBgH4pobyZ9E9IZ2cwxut7NwLtHzbMj7ko0/M0EibZ +IX8GWsbiqNJQjKHDbhxPiJH6i/RJ0f1FfUFGoxq7RpnJbNB0xmAg7eaTzHyVWeEL +NHV99GSg4kn2MTcWd8SS8945EwPGXx7NQVvZ1f0BMmEDooqIjwO2BOu9iT5m+4xL +wkF7AoGADQdu9lCbE0oFa4Ys9p7F7nAh7CCMvKGGIWZzQZBUf3Xr0RuZYRBaeUs2 +U7R/dXpUEOdxcDxSvfsnOz4yJ5++ixj0GaETgxHfHJd4JbBVW3ziCjPNSLj7Slgf +EmHy80ElH+97Z1nK5dHZNAi6m4u+eNjpnv/zbaWsLXsglPuzmsg= +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA1-no_pathlen.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA1-no_pathlen.pem new file mode 100644 index 000000000..302d2c78d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA1-no_pathlen.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA2-no_pathlen, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA1-no_pathlen, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:a7:6f:44:c2:11:cc:2c:f4:2a:a5:a8:08:53:4b: + 0e:cd:96:23:bb:15:4a:2a:dd:f9:a7:19:2b:91:28: + e8:73:a3:57:b4:49:3a:37:82:8f:15:38:5a:aa:af: + ad:72:26:2e:84:c2:0d:de:fc:f0:be:3b:a2:11:a9: + 12:20:d4:3d:de:62:85:85:91:08:60:db:c0:4a:bb: + 89:b6:f4:91:1e:51:a3:b2:f7:08:99:df:48:4a:59: + 84:d1:aa:09:36:0d:cd:68:a5:ae:41:c8:d7:1a:d8: + ea:49:87:20:22:27:f9:45:54:3e:c7:c8:00:44:7e: + 34:72:aa:8d:2d:4d:6a:3e:75:89:e2:d4:17:57:f9: + cd:2b:d0:b7:14:6a:54:1b:61:af:9b:68:22:b1:16: + 73:eb:05:6c:41:ea:ed:10:4e:bc:83:04:68:c8:3a: + e1:03:12:ad:28:5c:24:4c:19:a1:7e:d8:ef:1b:80: + e4:0e:49:0c:69:86:f6:1e:e7:01:fb:2a:6f:56:1b: + 6d:0a:ad:e9:29:3f:31:bb:48:28:40:79:2b:b5:f3: + aa:ec:e9:09:4c:82:fc:97:28:19:a3:3a:c0:d2:5e: + a3:8a:98:c8:8a:b7:d2:c4:90:bc:ff:cc:47:13:90: + ad:00:ab:8a:ec:f7:94:35:09:60:10:35:9f:32:c5: + 00:1b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 9C:7B:3A:10:B3:08:99:05:00:AF:3E:E0:A4:5D:D9:AF:82:BC:4D:C0 + X509v3 Authority Key Identifier: + keyid:A3:F5:71:8A:60:80:3C:93:64:17:D9:2E:B5:C0:CE:A9:C1:14:17:C4 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainJ-ICA3-no_pathlen/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 1c:0b:c0:44:10:dc:db:df:b9:3e:a0:95:09:d7:13:63:81:f7: + 32:57:19:84:72:2d:8e:60:66:0e:78:f3:35:7d:71:f8:95:88: + bc:90:52:e1:e2:4e:fe:4a:f7:bd:66:fe:b7:73:84:7f:96:ee: + ba:93:97:31:01:af:74:4f:60:40:74:d2:b5:a1:2f:e0:79:1a: + e2:67:08:ee:d4:60:43:1d:bc:79:9d:61:ae:fe:5e:9b:c8:b3: + 69:4e:d0:2b:2b:61:7a:51:1a:c9:bf:8c:b5:ff:ee:ee:42:eb: + ad:e4:90:53:1c:ed:a6:6f:27:51:1f:bf:b1:e3:0e:28:70:46: + 36:91:2e:72:82:b8:05:ee:42:c0:bd:17:0a:38:96:da:13:a4: + d5:a3:9d:bd:82:c3:aa:9f:ff:a8:cd:28:38:ae:18:44:a6:e3: + 60:eb:e0:4c:bd:1f:9e:99:e9:47:38:86:08:29:61:64:d6:6a: + 55:a0:eb:5a:62:24:d5:48:36:5b:51:5c:7f:5f:94:21:ea:d4: + 5e:7d:ee:ec:e7:3f:5b:35:59:8f:84:b9:00:53:80:3e:6a:a0: + db:de:a9:36:9e:f2:1e:48:77:cb:df:94:af:4c:a8:cc:93:c4: + 03:74:ca:ec:d8:86:a3:b9:49:76:b7:af:44:b3:b4:51:ca:a8: + 8b:78:73:f5 +-----BEGIN CERTIFICATE----- +MIIE1jCCA76gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluSi1JQ0EyLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBozELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNV +BAMMFmNoYWluSi1JQ0ExLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9A +d29sZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnb0TC +Ecws9CqlqAhTSw7NliO7FUoq3fmnGSuRKOhzo1e0STo3go8VOFqqr61yJi6Ewg3e +/PC+O6IRqRIg1D3eYoWFkQhg28BKu4m29JEeUaOy9wiZ30hKWYTRqgk2Dc1opa5B +yNca2OpJhyAiJ/lFVD7HyABEfjRyqo0tTWo+dYni1BdX+c0r0LcUalQbYa+baCKx +FnPrBWxB6u0QTryDBGjIOuEDEq0oXCRMGaF+2O8bgOQOSQxphvYe5wH7Km9WG20K +rekpPzG7SChAeSu186rs6QlMgvyXKBmjOsDSXqOKmMiKt9LEkLz/zEcTkK0Aq4rs +95Q1CWAQNZ8yxQAbAgMBAAGjggERMIIBDTAdBgNVHQ4EFgQUnHs6ELMImQUArz7g +pF3Zr4K8TcAwgdAGA1UdIwSByDCBxYAUo/VximCAPJNkF9kutcDOqcEUF8Shgamk +gaYwgaMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRUwEwYDVQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2lu +ZWVyaW5nMR8wHQYDVQQDDBZjaGFpbkotSUNBMy1ub19wYXRobGVuMR8wHQYJKoZI +hvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggFkMAwGA1UdEwQFMAMBAf8wCwYDVR0P +BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQAcC8BEENzb37k+oJUJ1xNjgfcyVxmE +ci2OYGYOePM1fXH4lYi8kFLh4k7+Sve9Zv63c4R/lu66k5cxAa90T2BAdNK1oS/g +eRriZwju1GBDHbx5nWGu/l6byLNpTtArK2F6URrJv4y1/+7uQuut5JBTHO2mbydR +H7+x4w4ocEY2kS5ygrgF7kLAvRcKOJbaE6TVo529gsOqn/+ozSg4rhhEpuNg6+BM +vR+emelHOIYIKWFk1mpVoOtaYiTVSDZbUVx/X5Qh6tRefe7s5z9bNVmPhLkAU4A+ +aqDb3qk2nvIeSHfL35SvTKjMk8QDdMrs2IajuUl2t69Es7RRyqiLeHP1 +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA2-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA2-key.pem new file mode 100644 index 000000000..fa3f5aef5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA2-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuyn9iaqC4B0EeGnsYVhRUoR+a1VpLPQj1h/Y7asZljh7xojX +fYWTADVAC8Cp/2YPnqEdiG6pivGtR7RxyRVQxg81npVKZtO9Gzh73GeFlxuzY8ly +1kNa8V419gWWx0C8I6uUNIJZArIz0OZ/GVdlaDwEYVDvIpVP7xi/FbFNjs2noJgi +9RwFAWtLNb+Iw0fDJCm0RcuVoawWHd24aKxROSQnar4x8ewGEFW+RAJP6BJ71v4y +yUg3ayBoy1P1STquSsdDwa/mUxHZ+HEaotY3xytFUElRT1VsPx5pe1gSOn5ZoFed +KJyKbYLnExU7BI/igg8vz9kl2WWjPAPAzbZR1QIDAQABAoIBAFvaUK5WOyKHuyDp +QvPHJynrEivU3+gK7Odx+8EwHj+F+uDFWZQlkK4idAsQg51u1i2QfnDtdlFVKCgv +m0QHLPv2jOcF91ydf4ozXz4cpAgztQc83xneNmyMQsk5lvS0hWCwHOzkJ5DWKe3U +oP2r0X2lLrUfxixfwLnjmCuqNxjkZlx1sB+rb5wafmW6GOx2kUS+jr02RG20wNIT +lPgCLYyRyn636F7eBSTDd2ogwwpugk0cqBWFnqzvJfltIFQd47bhSyQ4ot12rTrH +GzQ764Ll6pxuNmBYo9ys3HHhFs8A66vIpC7ITZRUWa7aHFzQn+rzJGeJ4+USJvCf +fCbyS4ECgYEA+B0tCuWCK6qiszfFdPAwTnQFTcdKBH9wnwI1f6gdgqOofYfSKJ/3 +6rgtuYv3/MPZ0wXTNP6QxYKjD3Zfa2oclxO/5JRejiahKYBNPrON1CbN3bMESZj4 +5Br5SxjLcDN8OFEKExn9U13lD7wfF2AVVUMkflkfao9ajziBkZUE1TUCgYEAwRzi +XJ7wOQgAAuz2rG9Kw70oQ8ry3VyU5L4xqEJsVIMBpxCQ+LfvWNMuR/awFECVnrxG +UpUgvzrY+JJ3EVDRD3bbCZW7TtglLi9vi7VomFv5S2tPPl+abktY9zPe76nF/bWg +joLTfWrla6OAUldaCBJPvmBlmsqEOJTMDM0kPiECgYBJI5ieiK9JngBeIkejxBYJ +Wmwh1Gh+UO7rAKSyn+UrGIFXl80cyqMzXt2jv533teglK6dqDMyyXGMi8LsKF/qb +kmfTwuTotHx3lmmu3REnA9VV0CqoY16jJ0xrlcCKr7Kji0gT/2pMw/X9IHBt3JYN +T0CXuj/nkqCYbYjMWIhXLQKBgQCYdtOIyLtka5qGtMu0LFHc5FUL4QmKF3Q+fKL7 +8yVQO/ZsDjpHBAFmIaUij/NIqgz2vDLRNIgcMrvm1MxI0YOdL/uTP7IYd7IzGqR4 +qwsfb04Na3WvCxAEEFz3Hu7eTS3SNznCCiwrkt/68aV4XRrp0HtBFR5i7Y0ilufb +G4OHwQKBgQCd0TSu7ntTRmQBddjtAylB5tP7BTxgdV39IrBs9AyZnEti8hVLn3bs +AuENwmUX2KGRkH9xmA3hf8QHYFWz2n7NiygZ60yjIvpQhd4z2eCEpmqrRVV44QtT +z/NoqKUN6ywGoDu60LV1PmoYpiWXM1qTxdKJhcUhdkuVSH22tKoVeQ== +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA2-no_pathlen.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA2-no_pathlen.pem new file mode 100644 index 000000000..92fa68dc2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA2-no_pathlen.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA3-no_pathlen, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA2-no_pathlen, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bb:29:fd:89:aa:82:e0:1d:04:78:69:ec:61:58: + 51:52:84:7e:6b:55:69:2c:f4:23:d6:1f:d8:ed:ab: + 19:96:38:7b:c6:88:d7:7d:85:93:00:35:40:0b:c0: + a9:ff:66:0f:9e:a1:1d:88:6e:a9:8a:f1:ad:47:b4: + 71:c9:15:50:c6:0f:35:9e:95:4a:66:d3:bd:1b:38: + 7b:dc:67:85:97:1b:b3:63:c9:72:d6:43:5a:f1:5e: + 35:f6:05:96:c7:40:bc:23:ab:94:34:82:59:02:b2: + 33:d0:e6:7f:19:57:65:68:3c:04:61:50:ef:22:95: + 4f:ef:18:bf:15:b1:4d:8e:cd:a7:a0:98:22:f5:1c: + 05:01:6b:4b:35:bf:88:c3:47:c3:24:29:b4:45:cb: + 95:a1:ac:16:1d:dd:b8:68:ac:51:39:24:27:6a:be: + 31:f1:ec:06:10:55:be:44:02:4f:e8:12:7b:d6:fe: + 32:c9:48:37:6b:20:68:cb:53:f5:49:3a:ae:4a:c7: + 43:c1:af:e6:53:11:d9:f8:71:1a:a2:d6:37:c7:2b: + 45:50:49:51:4f:55:6c:3f:1e:69:7b:58:12:3a:7e: + 59:a0:57:9d:28:9c:8a:6d:82:e7:13:15:3b:04:8f: + e2:82:0f:2f:cf:d9:25:d9:65:a3:3c:03:c0:cd:b6: + 51:d5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + A3:F5:71:8A:60:80:3C:93:64:17:D9:2E:B5:C0:CE:A9:C1:14:17:C4 + X509v3 Authority Key Identifier: + keyid:CD:97:49:78:F7:31:61:ED:2F:71:1A:68:E9:45:2C:40:78:51:93:5B + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainJ-ICA4-pathlen2/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 5b:56:cd:5e:fc:3a:fb:2b:be:7c:63:ad:a7:7b:e4:9a:00:78: + cb:d8:e6:00:41:3d:3d:e3:f6:43:78:75:d7:c9:07:61:0c:2b: + 43:46:8f:12:a3:5a:f0:3d:22:f4:72:ea:27:1a:70:57:48:c5: + ec:7d:00:dd:5d:83:a6:71:f7:90:ec:69:bd:2e:86:97:06:dc: + 9c:be:4e:a8:4c:9f:db:93:5e:fd:d8:ba:ae:89:55:65:16:cf: + ab:a5:a4:4e:ae:21:ce:5e:e0:91:e1:77:de:e3:b4:3d:ba:d2: + 12:f3:54:c0:50:94:16:e5:b2:62:71:58:03:2c:d1:f4:1f:ce: + 9d:a5:ce:2a:57:9f:f7:19:41:b0:4d:e8:27:5d:f2:e6:c8:44: + 1b:c3:57:51:76:d4:15:1a:05:31:61:c3:02:db:56:81:1e:24: + f2:23:04:a9:5a:31:ee:08:1d:08:1f:49:d7:2c:ba:1e:00:5a: + e5:57:8b:fd:aa:a4:2f:6a:d7:93:19:09:92:30:7d:95:68:3b: + b7:ce:a3:f2:b9:e4:e4:e4:48:a4:22:6b:00:33:91:56:28:fc: + 50:f7:1d:f6:70:5b:83:a8:99:98:2d:7a:6c:aa:9b:5a:a5:56: + 5b:89:95:a8:50:27:68:ce:63:5e:d3:84:cb:80:1b:ae:3e:a2: + 5c:13:9b:ff +-----BEGIN CERTIFICATE----- +MIIE1DCCA7ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluSi1JQ0EzLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBozELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNV +BAMMFmNoYWluSi1JQ0EyLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9A +d29sZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7Kf2J +qoLgHQR4aexhWFFShH5rVWks9CPWH9jtqxmWOHvGiNd9hZMANUALwKn/Zg+eoR2I +bqmK8a1HtHHJFVDGDzWelUpm070bOHvcZ4WXG7NjyXLWQ1rxXjX2BZbHQLwjq5Q0 +glkCsjPQ5n8ZV2VoPARhUO8ilU/vGL8VsU2OzaegmCL1HAUBa0s1v4jDR8MkKbRF +y5WhrBYd3bhorFE5JCdqvjHx7AYQVb5EAk/oEnvW/jLJSDdrIGjLU/VJOq5Kx0PB +r+ZTEdn4cRqi1jfHK0VQSVFPVWw/Hml7WBI6flmgV50onIptgucTFTsEj+KCDy/P +2SXZZaM8A8DNtlHVAgMBAAGjggEPMIIBCzAdBgNVHQ4EFgQUo/VximCAPJNkF9ku +tcDOqcEUF8Qwgc4GA1UdIwSBxjCBw4AUzZdJePcxYe0vcRpo6UUsQHhRk1uhgaek +gaQwgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRUwEwYDVQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2lu +ZWVyaW5nMR0wGwYDVQQDDBRjaGFpbkotSUNBNC1wYXRobGVuMjEfMB0GCSqGSIb3 +DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIBZDAMBgNVHRMEBTADAQH/MAsGA1UdDwQE +AwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAW1bNXvw6+yu+fGOtp3vkmgB4y9jmAEE9 +PeP2Q3h118kHYQwrQ0aPEqNa8D0i9HLqJxpwV0jF7H0A3V2DpnH3kOxpvS6Glwbc +nL5OqEyf25Ne/di6rolVZRbPq6WkTq4hzl7gkeF33uO0PbrSEvNUwFCUFuWyYnFY +AyzR9B/OnaXOKlef9xlBsE3oJ13y5shEG8NXUXbUFRoFMWHDAttWgR4k8iMEqVox +7ggdCB9J1yy6HgBa5VeL/aqkL2rXkxkJkjB9lWg7t86j8rnk5ORIpCJrADORVij8 +UPcd9nBbg6iZmC16bKqbWqVWW4mVqFAnaM5jXtOEy4Abrj6iXBOb/w== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA3-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA3-key.pem new file mode 100644 index 000000000..af221fe25 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA3-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA2Kr2BZVwWlPHZhCqkHk7y3gq719DInF8bUeZp4s54edOSClI +JeG19SXfZHvq7aofiw3n6/UvripaPVDH++8Li0QLY5S+xtdjRS6FlgBcvn4QCbPQ +qnzeIPh1OSOF7oQTiFQqlvUWJ5+LsKYq9J0TjHEcDKZZU+z5CyvJRRPWEu850Y6c +nq48u7bYEKy3WUlbcwC+r5IhFFSj+rYXrrbcsfFh8HUHQ15I+ueAVs/frUZShUL7 +p3BTFMa3Ufoj8PVL0bs/m/w1ytKF8aB3AgZ8eZkTtWi0FkdCiPe863iy6BEvYvba ++e8b4J+11TJltU7kvjZrZWUalqJHtT6fsA1jQQIDAQABAoIBAFxbg8Odj+bxD25S +bGJpSzPQZXzj/poQBhoPC1B/6IyDLLtV3YtIS2fUXQVYTSxB+HAt3U6XlVuIci7w +4E5j92fF+ZTZMvlPluFGk2r9fIs28V8xZyFFWOp0/oL8wXqKkkjql70BfBAn0kPa +kTT0QAD9thcuUaWUvhQk9gacDgTDa824zjrJmU/st0XkAL238VGZitW0n3FuIO/G +FLg3wPE6VJRvbdg5KT7UplvP1gj37tIWZmRtOxwGcr5NGhHiceGD99ubFAvkZPLe +RfRrQB/0vJ0TQLrVBhWtnRsrHuywUllrhLDUcJTnylrK/CMimmtvx03geDjo9jso +J+RaYAECgYEA9WJzlwjAR/a5K+6b/Wds1Oqsq3KVfRPLas5DENDCAfoabVQadJWh +DG/PtAoOWaK6Kvjg6qZyjlaB3gVVmUt7aflGYW2Ik7hpDlHY5D7tD7gOrhYzU/X9 +gnH0I9jRD9KhyRKIxMcgtQwMUX8EksfJsNm2uSbgvdLtWAad8uNg2zECgYEA4gp7 +PgBzfXq+2kt0qTbXG/+UCNXFUUChr/SrSb3g+gM/AMqmNVuRPJ3hNSEnHWt7g9Pi +3lIKFsQel5HZZR7o/H6GOtmIBD53ropX6foSMuJ8WlDEf1+44WvfpntESED9C1Hq +cEHTFKMWek5b8izfQBR/OzWmB33nh0AXHeBM5RECgYAw5kGqo2/N53jXLGGhie7C +L1HhiKAJoNw0mI38190Rj8mcZ9otyXOiitWVRzu82RTIY3hOyoShoNOYbu+z8LrT +T32bBLzm0yT8WYsjUPbk3wTt5DauUKMIT7UbP6XJxWvAKhVfQV9fNNtvkiRTK8Uh +nQEwvHKk4Vey5v6q3Gz8wQKBgF2X+W+ywB80s9GvbJ6kFm2BZcpCuXDrUgeJR2NB +O+ZJccziG+/7+icfOCDHmWqVFo9/LHDhh0vl6MTZnyo/ojjqKqozaB5ZvzSGE+DN +qrtnDBZZWwNinyq3f+NvJtbEEgKd6HSSzNO+s4/w4iFkcwwVcJkTnat8dmGKKAg2 +16ABAoGBAMiKDbjbCoiCHfUDjozrEuXL7IF0sUgctVBRl/llmvFjXwOY+yE+Fchj +bcPJw25UVJAcSvRn0U/0/eqsZCFEcrDCSlU+wU+3JDSMrf6nNFpgCYSU5a8juHXA +tI5ofONIJ72Dt7QARgP+jpV7QZSKrsh2vZe+6uaXNgCENkSr3XrV +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA3-no_pathlen.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA3-no_pathlen.pem new file mode 100644 index 000000000..7c1bfed06 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA3-no_pathlen.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA4-pathlen2, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA3-no_pathlen, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d8:aa:f6:05:95:70:5a:53:c7:66:10:aa:90:79: + 3b:cb:78:2a:ef:5f:43:22:71:7c:6d:47:99:a7:8b: + 39:e1:e7:4e:48:29:48:25:e1:b5:f5:25:df:64:7b: + ea:ed:aa:1f:8b:0d:e7:eb:f5:2f:ae:2a:5a:3d:50: + c7:fb:ef:0b:8b:44:0b:63:94:be:c6:d7:63:45:2e: + 85:96:00:5c:be:7e:10:09:b3:d0:aa:7c:de:20:f8: + 75:39:23:85:ee:84:13:88:54:2a:96:f5:16:27:9f: + 8b:b0:a6:2a:f4:9d:13:8c:71:1c:0c:a6:59:53:ec: + f9:0b:2b:c9:45:13:d6:12:ef:39:d1:8e:9c:9e:ae: + 3c:bb:b6:d8:10:ac:b7:59:49:5b:73:00:be:af:92: + 21:14:54:a3:fa:b6:17:ae:b6:dc:b1:f1:61:f0:75: + 07:43:5e:48:fa:e7:80:56:cf:df:ad:46:52:85:42: + fb:a7:70:53:14:c6:b7:51:fa:23:f0:f5:4b:d1:bb: + 3f:9b:fc:35:ca:d2:85:f1:a0:77:02:06:7c:79:99: + 13:b5:68:b4:16:47:42:88:f7:bc:eb:78:b2:e8:11: + 2f:62:f6:da:f9:ef:1b:e0:9f:b5:d5:32:65:b5:4e: + e4:be:36:6b:65:65:1a:96:a2:47:b5:3e:9f:b0:0d: + 63:41 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + CD:97:49:78:F7:31:61:ED:2F:71:1A:68:E9:45:2C:40:78:51:93:5B + X509v3 Authority Key Identifier: + keyid:FC:18:13:52:BB:33:4A:DB:1C:5B:D1:80:98:3E:40:86:95:58:72:F9 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 38:56:e6:30:a8:f8:db:32:4c:53:e0:8f:c5:08:98:3f:ce:bf: + b1:04:b0:52:24:63:6a:14:86:41:08:13:78:aa:98:7e:07:9b: + 1d:22:9e:61:b6:69:fb:f9:24:a3:8e:4b:f2:1f:39:6a:0b:a1: + ff:1f:9b:65:7c:7f:85:8c:d8:ce:3d:83:93:4c:00:4e:7f:d0: + 44:53:b1:a8:7d:bf:43:f1:d7:f2:2c:86:20:b8:cf:11:39:bb: + 7e:21:28:ca:20:4b:0a:46:97:d3:c6:82:2c:4e:25:8a:e4:92: + 84:da:c2:9b:15:3a:5c:8b:fc:a1:b7:76:f9:e8:80:79:1f:fc: + 4f:d4:18:f1:17:fa:19:87:4d:3c:81:e1:82:ce:e2:5c:d2:c0: + cd:e8:44:5a:dd:f1:41:5f:a2:df:27:a9:d4:4e:f7:2c:7a:8c: + 5f:dd:f2:3e:e3:c5:1f:7b:5f:0e:6f:9c:9a:c8:eb:63:0f:98: + eb:7e:e6:89:56:d9:c7:f4:6d:20:d9:0f:a5:81:82:90:90:95: + 53:62:80:9d:e3:93:44:4c:33:00:1e:b9:c8:b2:13:53:d2:a3: + 18:96:86:40:92:74:bf:a9:8e:77:ff:a8:3b:7f:c6:92:c8:b4: + 4e:6c:17:7f:36:9d:f6:64:11:f9:26:5e:55:09:36:fe:8c:84: + 81:08:0e:a3 +-----BEGIN CERTIFICATE----- +MIIExDCCA6ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluSi1JQ0E0LXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTE4MzAzMFoXDTIyMDcwNzE4MzAzMFowgaMxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR8wHQYDVQQD +DBZjaGFpbkotSUNBMy1ub19wYXRobGVuMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Kr2BZVw +WlPHZhCqkHk7y3gq719DInF8bUeZp4s54edOSClIJeG19SXfZHvq7aofiw3n6/Uv +ripaPVDH++8Li0QLY5S+xtdjRS6FlgBcvn4QCbPQqnzeIPh1OSOF7oQTiFQqlvUW +J5+LsKYq9J0TjHEcDKZZU+z5CyvJRRPWEu850Y6cnq48u7bYEKy3WUlbcwC+r5Ih +FFSj+rYXrrbcsfFh8HUHQ15I+ueAVs/frUZShUL7p3BTFMa3Ufoj8PVL0bs/m/w1 +ytKF8aB3AgZ8eZkTtWi0FkdCiPe863iy6BEvYvba+e8b4J+11TJltU7kvjZrZWUa +lqJHtT6fsA1jQQIDAQABo4IBATCB/jAdBgNVHQ4EFgQUzZdJePcxYe0vcRpo6UUs +QHhRk1swgcEGA1UdIwSBuTCBtoAU/BgTUrszStscW9GAmD5AhpVYcvmhgZqkgZcw +gZQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3pl +bWFuMREwDwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYG +A1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tggFkMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEB +CwUAA4IBAQA4VuYwqPjbMkxT4I/FCJg/zr+xBLBSJGNqFIZBCBN4qph+B5sdIp5h +tmn7+SSjjkvyHzlqC6H/H5tlfH+FjNjOPYOTTABOf9BEU7Gofb9D8dfyLIYguM8R +Obt+ISjKIEsKRpfTxoIsTiWK5JKE2sKbFTpci/yht3b56IB5H/xP1BjxF/oZh008 +geGCzuJc0sDN6ERa3fFBX6LfJ6nUTvcseoxf3fI+48Ufe18Ob5yayOtjD5jrfuaJ +VtnH9G0g2Q+lgYKQkJVTYoCd45NETDMAHrnIshNT0qMYloZAknS/qY53/6g7f8aS +yLRObBd/Np32ZBH5Jl5VCTb+jISBCA6j +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA4-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA4-key.pem new file mode 100644 index 000000000..f795822c3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA4-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAnUrua/+27IghI4QDtoi7PloblQMvJFMtVz8ROF0SHUBrENvC +0+TdgHd0e4hEZeDPUsWKQuVut2qrUKAuKcL+utXH2muRJo/8HgYX8N5Yh+8eppES +OWilBfOMZ8nlmRik/JA/vabK8qbdteaTyxSJgzyIWjGr42YqG4fFhQNFsM7hD8EP +knDXrGXqqAnB/h3bt+fdmNPGsRa0VFjBqrqhzxkUp+RVptq7H57RhQDgjUrE0oYI +df3YHoUhbCePGNVEc1irlHVKNj2NTcZ6hp0A28W6vnACg79u2DGJs/IWmL4n9hRa +6dRyZ42p33YnvxmsIFkoWxtC2dVbbftuol7T6QIDAQABAoIBAFOs+QkbEATkpjxu +jksckf+pj+LFvt5kIUq4kkCZwnktO8fMIOj4Z51f7ueIplpMLf6qd9L+mteYN2q8 +y9ILmddqwta/QohxMH4IX9QTdKVb38JcioVf1epElfzguvOm2J5DXqVVhcFwY6HQ +9+6hDkZyfVb99aMTRnM+1yTbiMd1cTV/hee0cCaS/A4WjJicldbLMUQ9GFlfoaNa +z7Vik0XnQZoAJKLFIqo+r3At1x4HQ6CTeIKLrUUCiIJp2AKTw1ZddSS+n1ELb7ms +MavRWChI5aYk9IhVTIzjFgsY5SWj5z2ta5dCngX0miTtr3CegUH8r7BAHTosezAW +CALcj8ECgYEA0S2AMpTdv2LdzTB9KLCGhHHbZSGgf/RBqvtkY2vCOKUSnZ3eT6Vy +wdVsRumbwMzmgzDP91SPsb7h0kq8VvplAyREsIm7lo+C1rZOjefBXRTMbZezjkPA ++OIA7DauyRpeICjhraMC3a5VDJgHPYb21juJZLf6wmA79uiye4ElbqcCgYEAwIBD +85yw4N7zH+0h9h9aJH7JU9CAQQ0EETJyDgCRqk5eSepoQEG3WpJw2tuP1cQpvJS8 +WCo1/k5eeyawOVHtkXoSXmsJF4QcGkyK/bbrlqpqzqB9hWw2s0XY8yY22PWOV64H +ugxTAr59G4Fp1LthyzL0Si4c/u5O3iSV9eJWCu8CgYBYPTd9HutEFvK14iSKC51T +Nax1RvAryeABvrakcgqmVow5zSTAuGxmdB+O8nDvrf/3i5nPHe7X7kvYqAo3Lr15 +y8zmI9PsOXHaHWGZ3w/ksidie8IU22QGGWCGRLMKxoK6UkSRONi2pxndjCxRuiNa +UBcvU6UGZg4lpBfWna4qtQKBgCaOyo2WOhugrKQddGr/FqguuRbPsZDWEZV8PDov +xP2O2vYFPMJ6J0a+BFriFapks1Nxm1QxiEUa33PdaPjiPyqff+RnnheWv6ZI5KIz +LHcuRVyD6wB5j29TM0RoyB2m+c74LdYHN+1ZyGdlAZS5v7nax/G/0NEDXMrEG0F4 +B3IDAoGBAKi0u0aMsVKOY1X9AR/4PWwe2zD6JWIT9oGWXGmp3CjXH+RxoSCTtYYr +1eLmgVkKA0dYrJO4QqZ26pLst3FZ0trAH0zhbn5y7NWy2AdDFMFClk5D8a+VEm1S +ejTDoNtohKlDFgaGC15mrHpv6JfpKGlBpRuTH8DRuCpaoqLQ9bOO +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA4-pathlen2.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA4-pathlen2.pem new file mode 100644 index 000000000..0d3e8258a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-ICA4-pathlen2.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA4-pathlen2, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:9d:4a:ee:6b:ff:b6:ec:88:21:23:84:03:b6:88: + bb:3e:5a:1b:95:03:2f:24:53:2d:57:3f:11:38:5d: + 12:1d:40:6b:10:db:c2:d3:e4:dd:80:77:74:7b:88: + 44:65:e0:cf:52:c5:8a:42:e5:6e:b7:6a:ab:50:a0: + 2e:29:c2:fe:ba:d5:c7:da:6b:91:26:8f:fc:1e:06: + 17:f0:de:58:87:ef:1e:a6:91:12:39:68:a5:05:f3: + 8c:67:c9:e5:99:18:a4:fc:90:3f:bd:a6:ca:f2:a6: + dd:b5:e6:93:cb:14:89:83:3c:88:5a:31:ab:e3:66: + 2a:1b:87:c5:85:03:45:b0:ce:e1:0f:c1:0f:92:70: + d7:ac:65:ea:a8:09:c1:fe:1d:db:b7:e7:dd:98:d3: + c6:b1:16:b4:54:58:c1:aa:ba:a1:cf:19:14:a7:e4: + 55:a6:da:bb:1f:9e:d1:85:00:e0:8d:4a:c4:d2:86: + 08:75:fd:d8:1e:85:21:6c:27:8f:18:d5:44:73:58: + ab:94:75:4a:36:3d:8d:4d:c6:7a:86:9d:00:db:c5: + ba:be:70:02:83:bf:6e:d8:31:89:b3:f2:16:98:be: + 27:f6:14:5a:e9:d4:72:67:8d:a9:df:76:27:bf:19: + ac:20:59:28:5b:1b:42:d9:d5:5b:6d:fb:6e:a2:5e: + d3:e9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + FC:18:13:52:BB:33:4A:DB:1C:5B:D1:80:98:3E:40:86:95:58:72:F9 + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:2 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 0d:bc:87:df:e4:68:a5:56:54:d2:89:42:d8:b4:1b:45:6f:88: + b2:39:d1:ad:38:f4:0b:68:5e:e1:3e:88:60:4f:69:be:a8:ee: + 1d:14:08:69:86:ee:6a:08:42:35:6e:44:4f:5f:be:13:00:81: + ca:41:a7:70:d3:48:9f:60:03:14:a4:4b:7f:35:7e:6d:94:0b: + cf:63:00:fe:8e:54:2c:4c:ac:fb:ef:4c:68:91:9a:0f:45:3e: + 07:12:f2:74:e6:83:36:8e:61:49:f9:03:17:e2:16:72:eb:6b: + c3:c1:7b:95:37:31:1f:10:b9:fc:7b:e4:54:d4:4f:81:a0:f8: + 0e:be:99:43:50:dd:19:7e:f9:41:8b:0d:2e:b2:e5:2c:ec:9b: + 20:42:f4:3a:da:03:99:bc:c1:c2:6c:69:4e:8e:6e:ad:22:57: + dc:2c:1a:e3:4f:15:c4:b3:b4:5d:2d:be:d8:62:0a:a4:c9:62: + fb:9a:53:26:ee:8f:8e:43:a6:e2:77:9b:1f:1f:4f:86:b5:65: + 22:3c:0d:f7:75:ab:24:2d:5b:6f:96:3f:26:22:b0:de:b2:4e: + 37:fd:f9:9a:22:81:15:91:c5:b0:54:f2:ee:f0:e9:7f:23:ab: + 43:1c:43:e1:e4:bf:61:20:13:f3:4f:b6:71:77:a3:23:89:fb: + 02:c2:24:5e +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluSi1JQ0E0 +LXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnUrua/+27IghI4QDtoi7PloblQMv +JFMtVz8ROF0SHUBrENvC0+TdgHd0e4hEZeDPUsWKQuVut2qrUKAuKcL+utXH2muR +Jo/8HgYX8N5Yh+8eppESOWilBfOMZ8nlmRik/JA/vabK8qbdteaTyxSJgzyIWjGr +42YqG4fFhQNFsM7hD8EPknDXrGXqqAnB/h3bt+fdmNPGsRa0VFjBqrqhzxkUp+RV +ptq7H57RhQDgjUrE0oYIdf3YHoUhbCePGNVEc1irlHVKNj2NTcZ6hp0A28W6vnAC +g79u2DGJs/IWmL4n9hRa6dRyZ42p33YnvxmsIFkoWxtC2dVbbftuol7T6QIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFPwYE1K7M0rbHFvRgJg+QIaVWHL5MIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQANvIff5GilVlTSiULYtBtFb4iyOdGtOPQLaF7hPohgT2m+qO4dFAhphu5q +CEI1bkRPX74TAIHKQadw00ifYAMUpEt/NX5tlAvPYwD+jlQsTKz770xokZoPRT4H +EvJ05oM2jmFJ+QMX4hZy62vDwXuVNzEfELn8e+RU1E+BoPgOvplDUN0ZfvlBiw0u +suUs7JsgQvQ62gOZvMHCbGlOjm6tIlfcLBrjTxXEs7RdLb7YYgqkyWL7mlMm7o+O +Q6bid5sfH0+GtWUiPA33daskLVtvlj8mIrDesk43/fmaIoEVkcWwVPLu8Ol/I6tD +HEPh5L9hIBPzT7Zxd6MjifsCwiRe +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-assembled.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-assembled.pem new file mode 100644 index 000000000..4e93b51f6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-assembled.pem @@ -0,0 +1,443 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA1-no_pathlen, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b3:fb:51:a0:ac:69:8b:35:06:bf:7a:ee:b4:a1: + 8a:7e:ae:31:75:ad:e7:45:7b:e6:d9:bb:7c:e9:73: + 0e:de:cf:05:74:df:37:a4:37:33:a6:6f:59:06:c8: + 9f:19:35:c3:94:f7:05:ba:52:eb:3e:92:29:61:48: + 88:fa:6d:42:b4:30:de:ce:df:94:ed:92:88:60:c8: + 55:36:50:ee:36:b5:ed:35:6f:95:01:f4:88:4b:7b: + 3e:fe:b5:9c:64:c0:72:be:8c:74:6a:8c:f5:e4:65: + 66:87:52:9d:7b:b0:20:f6:d8:c3:de:76:b9:70:7c: + 01:82:6e:fc:fa:1b:e7:c4:c1:5f:38:ce:50:dc:3a: + 22:87:bc:19:9a:45:d5:8a:7a:93:f9:78:59:c7:0a: + f9:8f:eb:c3:79:eb:b5:ee:36:f0:5e:5d:2f:8f:46: + e8:63:c2:31:82:fc:fb:5d:8c:ca:01:b1:bb:72:2b: + e7:2f:82:3c:a6:24:a6:3f:58:7e:69:5b:4a:00:b4: + 25:b3:b3:c3:b3:b0:c2:3f:a3:d7:ee:04:12:1d:ab: + 0b:bb:02:b0:6c:0b:36:64:56:a9:5d:37:e5:0a:28: + 44:5e:15:e4:f5:ab:73:98:0a:b3:28:90:1d:30:f2: + 8c:e7:db:13:6a:0f:b4:cb:8d:06:15:86:ce:35:12: + e3:a9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 13:92:E0:30:5E:36:4F:BF:D5:E3:0D:5D:40:0B:64:95:EC:8E:77:4E + X509v3 Authority Key Identifier: + keyid:9C:7B:3A:10:B3:08:99:05:00:AF:3E:E0:A4:5D:D9:AF:82:BC:4D:C0 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainJ-ICA2-no_pathlen/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 10:a0:e0:ea:4b:df:4c:5b:92:da:6b:13:5a:4b:e9:46:1a:17: + 48:42:5e:08:c8:28:e4:ce:69:46:25:55:70:57:bd:4e:b2:0b: + a4:75:22:b6:5b:d7:e0:54:3f:31:14:99:09:c1:3b:6f:b7:59: + 5a:52:67:46:0c:4f:ec:fa:31:4a:6e:59:04:50:99:60:1e:74: + ed:3a:ac:4d:cd:98:31:4d:b1:54:07:3e:76:bb:92:e2:1d:53: + 65:08:38:e3:4d:b0:d8:74:14:5f:00:94:e7:d2:c9:9d:80:23: + f5:9e:3d:8c:22:72:b3:20:5a:01:a3:02:f2:9c:cc:b8:1d:73: + db:eb:cc:cb:27:4f:75:17:1d:23:68:07:4f:15:be:00:cc:a9: + 2a:14:82:2c:0e:e3:92:40:dc:62:ac:d9:61:24:99:19:43:d5: + 3e:85:ca:e5:6d:e1:76:9a:4e:01:ef:34:98:7a:1b:ca:8b:c3: + de:99:22:75:28:11:0c:17:7a:58:7b:44:33:22:58:61:24:8c: + 96:a5:a7:63:19:31:6d:61:83:1c:5f:50:66:48:29:b4:2d:8e: + 5e:f3:63:85:e8:9c:d8:6e:93:4a:4d:ff:b1:d5:60:96:d0:9f: + 4e:3f:6f:c9:b4:e1:04:b8:ef:55:c2:77:c1:e1:50:d0:a7:b8: + 9d:a3:81:71 +-----BEGIN CERTIFICATE----- +MIIEvDCCA6SgAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluSi1JQ0ExLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBmjELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxFjAUBgNV +BAMMDWNoYWluSi1lbnRpdHkxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz+1GgrGmLNQa/eu60 +oYp+rjF1redFe+bZu3zpcw7ezwV03zekNzOmb1kGyJ8ZNcOU9wW6Uus+kilhSIj6 +bUK0MN7O35TtkohgyFU2UO42te01b5UB9IhLez7+tZxkwHK+jHRqjPXkZWaHUp17 +sCD22MPedrlwfAGCbvz6G+fEwV84zlDcOiKHvBmaRdWKepP5eFnHCvmP68N567Xu +NvBeXS+PRuhjwjGC/PtdjMoBsbtyK+cvgjymJKY/WH5pW0oAtCWzs8OzsMI/o9fu +BBIdqwu7ArBsCzZkVqldN+UKKEReFeT1q3OYCrMokB0w8ozn2xNqD7TLjQYVhs41 +EuOpAgMBAAGjggEAMIH9MB0GA1UdDgQWBBQTkuAwXjZPv9XjDV1AC2SV7I53TjCB +0AYDVR0jBIHIMIHFgBScezoQswiZBQCvPuCkXdmvgrxNwKGBqaSBpjCBozELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +FTATBgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAd +BgNVBAMMFmNoYWluSi1JQ0EyLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGlu +Zm9Ad29sZnNzbC5jb22CAWQwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA +EKDg6kvfTFuS2msTWkvpRhoXSEJeCMgo5M5pRiVVcFe9TrILpHUitlvX4FQ/MRSZ +CcE7b7dZWlJnRgxP7PoxSm5ZBFCZYB507TqsTc2YMU2xVAc+druS4h1TZQg4402w +2HQUXwCU59LJnYAj9Z49jCJysyBaAaMC8pzMuB1z2+vMyydPdRcdI2gHTxW+AMyp +KhSCLA7jkkDcYqzZYSSZGUPVPoXK5W3hdppOAe80mHobyovD3pkidSgRDBd6WHtE +MyJYYSSMlqWnYxkxbWGDHF9QZkgptC2OXvNjheic2G6TSk3/sdVgltCfTj9vybTh +BLjvVcJ3weFQ0Ke4naOBcQ== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA2-no_pathlen, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA1-no_pathlen, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:a7:6f:44:c2:11:cc:2c:f4:2a:a5:a8:08:53:4b: + 0e:cd:96:23:bb:15:4a:2a:dd:f9:a7:19:2b:91:28: + e8:73:a3:57:b4:49:3a:37:82:8f:15:38:5a:aa:af: + ad:72:26:2e:84:c2:0d:de:fc:f0:be:3b:a2:11:a9: + 12:20:d4:3d:de:62:85:85:91:08:60:db:c0:4a:bb: + 89:b6:f4:91:1e:51:a3:b2:f7:08:99:df:48:4a:59: + 84:d1:aa:09:36:0d:cd:68:a5:ae:41:c8:d7:1a:d8: + ea:49:87:20:22:27:f9:45:54:3e:c7:c8:00:44:7e: + 34:72:aa:8d:2d:4d:6a:3e:75:89:e2:d4:17:57:f9: + cd:2b:d0:b7:14:6a:54:1b:61:af:9b:68:22:b1:16: + 73:eb:05:6c:41:ea:ed:10:4e:bc:83:04:68:c8:3a: + e1:03:12:ad:28:5c:24:4c:19:a1:7e:d8:ef:1b:80: + e4:0e:49:0c:69:86:f6:1e:e7:01:fb:2a:6f:56:1b: + 6d:0a:ad:e9:29:3f:31:bb:48:28:40:79:2b:b5:f3: + aa:ec:e9:09:4c:82:fc:97:28:19:a3:3a:c0:d2:5e: + a3:8a:98:c8:8a:b7:d2:c4:90:bc:ff:cc:47:13:90: + ad:00:ab:8a:ec:f7:94:35:09:60:10:35:9f:32:c5: + 00:1b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 9C:7B:3A:10:B3:08:99:05:00:AF:3E:E0:A4:5D:D9:AF:82:BC:4D:C0 + X509v3 Authority Key Identifier: + keyid:A3:F5:71:8A:60:80:3C:93:64:17:D9:2E:B5:C0:CE:A9:C1:14:17:C4 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainJ-ICA3-no_pathlen/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 1c:0b:c0:44:10:dc:db:df:b9:3e:a0:95:09:d7:13:63:81:f7: + 32:57:19:84:72:2d:8e:60:66:0e:78:f3:35:7d:71:f8:95:88: + bc:90:52:e1:e2:4e:fe:4a:f7:bd:66:fe:b7:73:84:7f:96:ee: + ba:93:97:31:01:af:74:4f:60:40:74:d2:b5:a1:2f:e0:79:1a: + e2:67:08:ee:d4:60:43:1d:bc:79:9d:61:ae:fe:5e:9b:c8:b3: + 69:4e:d0:2b:2b:61:7a:51:1a:c9:bf:8c:b5:ff:ee:ee:42:eb: + ad:e4:90:53:1c:ed:a6:6f:27:51:1f:bf:b1:e3:0e:28:70:46: + 36:91:2e:72:82:b8:05:ee:42:c0:bd:17:0a:38:96:da:13:a4: + d5:a3:9d:bd:82:c3:aa:9f:ff:a8:cd:28:38:ae:18:44:a6:e3: + 60:eb:e0:4c:bd:1f:9e:99:e9:47:38:86:08:29:61:64:d6:6a: + 55:a0:eb:5a:62:24:d5:48:36:5b:51:5c:7f:5f:94:21:ea:d4: + 5e:7d:ee:ec:e7:3f:5b:35:59:8f:84:b9:00:53:80:3e:6a:a0: + db:de:a9:36:9e:f2:1e:48:77:cb:df:94:af:4c:a8:cc:93:c4: + 03:74:ca:ec:d8:86:a3:b9:49:76:b7:af:44:b3:b4:51:ca:a8: + 8b:78:73:f5 +-----BEGIN CERTIFICATE----- +MIIE1jCCA76gAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluSi1JQ0EyLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBozELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNV +BAMMFmNoYWluSi1JQ0ExLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9A +d29sZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnb0TC +Ecws9CqlqAhTSw7NliO7FUoq3fmnGSuRKOhzo1e0STo3go8VOFqqr61yJi6Ewg3e +/PC+O6IRqRIg1D3eYoWFkQhg28BKu4m29JEeUaOy9wiZ30hKWYTRqgk2Dc1opa5B +yNca2OpJhyAiJ/lFVD7HyABEfjRyqo0tTWo+dYni1BdX+c0r0LcUalQbYa+baCKx +FnPrBWxB6u0QTryDBGjIOuEDEq0oXCRMGaF+2O8bgOQOSQxphvYe5wH7Km9WG20K +rekpPzG7SChAeSu186rs6QlMgvyXKBmjOsDSXqOKmMiKt9LEkLz/zEcTkK0Aq4rs +95Q1CWAQNZ8yxQAbAgMBAAGjggERMIIBDTAdBgNVHQ4EFgQUnHs6ELMImQUArz7g +pF3Zr4K8TcAwgdAGA1UdIwSByDCBxYAUo/VximCAPJNkF9kutcDOqcEUF8Shgamk +gaYwgaMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRUwEwYDVQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2lu +ZWVyaW5nMR8wHQYDVQQDDBZjaGFpbkotSUNBMy1ub19wYXRobGVuMR8wHQYJKoZI +hvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggFkMAwGA1UdEwQFMAMBAf8wCwYDVR0P +BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQAcC8BEENzb37k+oJUJ1xNjgfcyVxmE +ci2OYGYOePM1fXH4lYi8kFLh4k7+Sve9Zv63c4R/lu66k5cxAa90T2BAdNK1oS/g +eRriZwju1GBDHbx5nWGu/l6byLNpTtArK2F6URrJv4y1/+7uQuut5JBTHO2mbydR +H7+x4w4ocEY2kS5ygrgF7kLAvRcKOJbaE6TVo529gsOqn/+ozSg4rhhEpuNg6+BM +vR+emelHOIYIKWFk1mpVoOtaYiTVSDZbUVx/X5Qh6tRefe7s5z9bNVmPhLkAU4A+ +aqDb3qk2nvIeSHfL35SvTKjMk8QDdMrs2IajuUl2t69Es7RRyqiLeHP1 +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA3-no_pathlen, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA2-no_pathlen, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bb:29:fd:89:aa:82:e0:1d:04:78:69:ec:61:58: + 51:52:84:7e:6b:55:69:2c:f4:23:d6:1f:d8:ed:ab: + 19:96:38:7b:c6:88:d7:7d:85:93:00:35:40:0b:c0: + a9:ff:66:0f:9e:a1:1d:88:6e:a9:8a:f1:ad:47:b4: + 71:c9:15:50:c6:0f:35:9e:95:4a:66:d3:bd:1b:38: + 7b:dc:67:85:97:1b:b3:63:c9:72:d6:43:5a:f1:5e: + 35:f6:05:96:c7:40:bc:23:ab:94:34:82:59:02:b2: + 33:d0:e6:7f:19:57:65:68:3c:04:61:50:ef:22:95: + 4f:ef:18:bf:15:b1:4d:8e:cd:a7:a0:98:22:f5:1c: + 05:01:6b:4b:35:bf:88:c3:47:c3:24:29:b4:45:cb: + 95:a1:ac:16:1d:dd:b8:68:ac:51:39:24:27:6a:be: + 31:f1:ec:06:10:55:be:44:02:4f:e8:12:7b:d6:fe: + 32:c9:48:37:6b:20:68:cb:53:f5:49:3a:ae:4a:c7: + 43:c1:af:e6:53:11:d9:f8:71:1a:a2:d6:37:c7:2b: + 45:50:49:51:4f:55:6c:3f:1e:69:7b:58:12:3a:7e: + 59:a0:57:9d:28:9c:8a:6d:82:e7:13:15:3b:04:8f: + e2:82:0f:2f:cf:d9:25:d9:65:a3:3c:03:c0:cd:b6: + 51:d5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + A3:F5:71:8A:60:80:3C:93:64:17:D9:2E:B5:C0:CE:A9:C1:14:17:C4 + X509v3 Authority Key Identifier: + keyid:CD:97:49:78:F7:31:61:ED:2F:71:1A:68:E9:45:2C:40:78:51:93:5B + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainJ-ICA4-pathlen2/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 5b:56:cd:5e:fc:3a:fb:2b:be:7c:63:ad:a7:7b:e4:9a:00:78: + cb:d8:e6:00:41:3d:3d:e3:f6:43:78:75:d7:c9:07:61:0c:2b: + 43:46:8f:12:a3:5a:f0:3d:22:f4:72:ea:27:1a:70:57:48:c5: + ec:7d:00:dd:5d:83:a6:71:f7:90:ec:69:bd:2e:86:97:06:dc: + 9c:be:4e:a8:4c:9f:db:93:5e:fd:d8:ba:ae:89:55:65:16:cf: + ab:a5:a4:4e:ae:21:ce:5e:e0:91:e1:77:de:e3:b4:3d:ba:d2: + 12:f3:54:c0:50:94:16:e5:b2:62:71:58:03:2c:d1:f4:1f:ce: + 9d:a5:ce:2a:57:9f:f7:19:41:b0:4d:e8:27:5d:f2:e6:c8:44: + 1b:c3:57:51:76:d4:15:1a:05:31:61:c3:02:db:56:81:1e:24: + f2:23:04:a9:5a:31:ee:08:1d:08:1f:49:d7:2c:ba:1e:00:5a: + e5:57:8b:fd:aa:a4:2f:6a:d7:93:19:09:92:30:7d:95:68:3b: + b7:ce:a3:f2:b9:e4:e4:e4:48:a4:22:6b:00:33:91:56:28:fc: + 50:f7:1d:f6:70:5b:83:a8:99:98:2d:7a:6c:aa:9b:5a:a5:56: + 5b:89:95:a8:50:27:68:ce:63:5e:d3:84:cb:80:1b:ae:3e:a2: + 5c:13:9b:ff +-----BEGIN CERTIFICATE----- +MIIE1DCCA7ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluSi1JQ0EzLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBozELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNV +BAMMFmNoYWluSi1JQ0EyLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9A +d29sZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7Kf2J +qoLgHQR4aexhWFFShH5rVWks9CPWH9jtqxmWOHvGiNd9hZMANUALwKn/Zg+eoR2I +bqmK8a1HtHHJFVDGDzWelUpm070bOHvcZ4WXG7NjyXLWQ1rxXjX2BZbHQLwjq5Q0 +glkCsjPQ5n8ZV2VoPARhUO8ilU/vGL8VsU2OzaegmCL1HAUBa0s1v4jDR8MkKbRF +y5WhrBYd3bhorFE5JCdqvjHx7AYQVb5EAk/oEnvW/jLJSDdrIGjLU/VJOq5Kx0PB +r+ZTEdn4cRqi1jfHK0VQSVFPVWw/Hml7WBI6flmgV50onIptgucTFTsEj+KCDy/P +2SXZZaM8A8DNtlHVAgMBAAGjggEPMIIBCzAdBgNVHQ4EFgQUo/VximCAPJNkF9ku +tcDOqcEUF8Qwgc4GA1UdIwSBxjCBw4AUzZdJePcxYe0vcRpo6UUsQHhRk1uhgaek +gaQwgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH +DAdTZWF0dGxlMRUwEwYDVQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2lu +ZWVyaW5nMR0wGwYDVQQDDBRjaGFpbkotSUNBNC1wYXRobGVuMjEfMB0GCSqGSIb3 +DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIBZDAMBgNVHRMEBTADAQH/MAsGA1UdDwQE +AwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAW1bNXvw6+yu+fGOtp3vkmgB4y9jmAEE9 +PeP2Q3h118kHYQwrQ0aPEqNa8D0i9HLqJxpwV0jF7H0A3V2DpnH3kOxpvS6Glwbc +nL5OqEyf25Ne/di6rolVZRbPq6WkTq4hzl7gkeF33uO0PbrSEvNUwFCUFuWyYnFY +AyzR9B/OnaXOKlef9xlBsE3oJ13y5shEG8NXUXbUFRoFMWHDAttWgR4k8iMEqVox +7ggdCB9J1yy6HgBa5VeL/aqkL2rXkxkJkjB9lWg7t86j8rnk5ORIpCJrADORVij8 +UPcd9nBbg6iZmC16bKqbWqVWW4mVqFAnaM5jXtOEy4Abrj6iXBOb/w== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA4-pathlen2, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA3-no_pathlen, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:d8:aa:f6:05:95:70:5a:53:c7:66:10:aa:90:79: + 3b:cb:78:2a:ef:5f:43:22:71:7c:6d:47:99:a7:8b: + 39:e1:e7:4e:48:29:48:25:e1:b5:f5:25:df:64:7b: + ea:ed:aa:1f:8b:0d:e7:eb:f5:2f:ae:2a:5a:3d:50: + c7:fb:ef:0b:8b:44:0b:63:94:be:c6:d7:63:45:2e: + 85:96:00:5c:be:7e:10:09:b3:d0:aa:7c:de:20:f8: + 75:39:23:85:ee:84:13:88:54:2a:96:f5:16:27:9f: + 8b:b0:a6:2a:f4:9d:13:8c:71:1c:0c:a6:59:53:ec: + f9:0b:2b:c9:45:13:d6:12:ef:39:d1:8e:9c:9e:ae: + 3c:bb:b6:d8:10:ac:b7:59:49:5b:73:00:be:af:92: + 21:14:54:a3:fa:b6:17:ae:b6:dc:b1:f1:61:f0:75: + 07:43:5e:48:fa:e7:80:56:cf:df:ad:46:52:85:42: + fb:a7:70:53:14:c6:b7:51:fa:23:f0:f5:4b:d1:bb: + 3f:9b:fc:35:ca:d2:85:f1:a0:77:02:06:7c:79:99: + 13:b5:68:b4:16:47:42:88:f7:bc:eb:78:b2:e8:11: + 2f:62:f6:da:f9:ef:1b:e0:9f:b5:d5:32:65:b5:4e: + e4:be:36:6b:65:65:1a:96:a2:47:b5:3e:9f:b0:0d: + 63:41 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + CD:97:49:78:F7:31:61:ED:2F:71:1A:68:E9:45:2C:40:78:51:93:5B + X509v3 Authority Key Identifier: + keyid:FC:18:13:52:BB:33:4A:DB:1C:5B:D1:80:98:3E:40:86:95:58:72:F9 + DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 38:56:e6:30:a8:f8:db:32:4c:53:e0:8f:c5:08:98:3f:ce:bf: + b1:04:b0:52:24:63:6a:14:86:41:08:13:78:aa:98:7e:07:9b: + 1d:22:9e:61:b6:69:fb:f9:24:a3:8e:4b:f2:1f:39:6a:0b:a1: + ff:1f:9b:65:7c:7f:85:8c:d8:ce:3d:83:93:4c:00:4e:7f:d0: + 44:53:b1:a8:7d:bf:43:f1:d7:f2:2c:86:20:b8:cf:11:39:bb: + 7e:21:28:ca:20:4b:0a:46:97:d3:c6:82:2c:4e:25:8a:e4:92: + 84:da:c2:9b:15:3a:5c:8b:fc:a1:b7:76:f9:e8:80:79:1f:fc: + 4f:d4:18:f1:17:fa:19:87:4d:3c:81:e1:82:ce:e2:5c:d2:c0: + cd:e8:44:5a:dd:f1:41:5f:a2:df:27:a9:d4:4e:f7:2c:7a:8c: + 5f:dd:f2:3e:e3:c5:1f:7b:5f:0e:6f:9c:9a:c8:eb:63:0f:98: + eb:7e:e6:89:56:d9:c7:f4:6d:20:d9:0f:a5:81:82:90:90:95: + 53:62:80:9d:e3:93:44:4c:33:00:1e:b9:c8:b2:13:53:d2:a3: + 18:96:86:40:92:74:bf:a9:8e:77:ff:a8:3b:7f:c6:92:c8:b4: + 4e:6c:17:7f:36:9d:f6:64:11:f9:26:5e:55:09:36:fe:8c:84: + 81:08:0e:a3 +-----BEGIN CERTIFICATE----- +MIIExDCCA6ygAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNo +YWluSi1JQ0E0LXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu +Y29tMB4XDTE5MTAxMTE4MzAzMFoXDTIyMDcwNzE4MzAzMFowgaMxCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRUwEwYD +VQQKDAx3b2xmU1NMIEluYy4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMR8wHQYDVQQD +DBZjaGFpbkotSUNBMy1ub19wYXRobGVuMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Kr2BZVw +WlPHZhCqkHk7y3gq719DInF8bUeZp4s54edOSClIJeG19SXfZHvq7aofiw3n6/Uv +ripaPVDH++8Li0QLY5S+xtdjRS6FlgBcvn4QCbPQqnzeIPh1OSOF7oQTiFQqlvUW +J5+LsKYq9J0TjHEcDKZZU+z5CyvJRRPWEu850Y6cnq48u7bYEKy3WUlbcwC+r5Ih +FFSj+rYXrrbcsfFh8HUHQ15I+ueAVs/frUZShUL7p3BTFMa3Ufoj8PVL0bs/m/w1 +ytKF8aB3AgZ8eZkTtWi0FkdCiPe863iy6BEvYvba+e8b4J+11TJltU7kvjZrZWUa +lqJHtT6fsA1jQQIDAQABo4IBATCB/jAdBgNVHQ4EFgQUzZdJePcxYe0vcRpo6UUs +QHhRk1swgcEGA1UdIwSBuTCBtoAU/BgTUrszStscW9GAmD5AhpVYcvmhgZqkgZcw +gZQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3pl +bWFuMREwDwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYG +A1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tggFkMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEB +CwUAA4IBAQA4VuYwqPjbMkxT4I/FCJg/zr+xBLBSJGNqFIZBCBN4qph+B5sdIp5h +tmn7+SSjjkvyHzlqC6H/H5tlfH+FjNjOPYOTTABOf9BEU7Gofb9D8dfyLIYguM8R +Obt+ISjKIEsKRpfTxoIsTiWK5JKE2sKbFTpci/yht3b56IB5H/xP1BjxF/oZh008 +geGCzuJc0sDN6ERa3fFBX6LfJ6nUTvcseoxf3fI+48Ufe18Ob5yayOtjD5jrfuaJ +VtnH9G0g2Q+lgYKQkJVTYoCd45NETDMAHrnIshNT0qMYloZAknS/qY53/6g7f8aS +yLRObBd/Np32ZBH5Jl5VCTb+jISBCA6j +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 100 (0x64) + 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: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA4-pathlen2, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:9d:4a:ee:6b:ff:b6:ec:88:21:23:84:03:b6:88: + bb:3e:5a:1b:95:03:2f:24:53:2d:57:3f:11:38:5d: + 12:1d:40:6b:10:db:c2:d3:e4:dd:80:77:74:7b:88: + 44:65:e0:cf:52:c5:8a:42:e5:6e:b7:6a:ab:50:a0: + 2e:29:c2:fe:ba:d5:c7:da:6b:91:26:8f:fc:1e:06: + 17:f0:de:58:87:ef:1e:a6:91:12:39:68:a5:05:f3: + 8c:67:c9:e5:99:18:a4:fc:90:3f:bd:a6:ca:f2:a6: + dd:b5:e6:93:cb:14:89:83:3c:88:5a:31:ab:e3:66: + 2a:1b:87:c5:85:03:45:b0:ce:e1:0f:c1:0f:92:70: + d7:ac:65:ea:a8:09:c1:fe:1d:db:b7:e7:dd:98:d3: + c6:b1:16:b4:54:58:c1:aa:ba:a1:cf:19:14:a7:e4: + 55:a6:da:bb:1f:9e:d1:85:00:e0:8d:4a:c4:d2:86: + 08:75:fd:d8:1e:85:21:6c:27:8f:18:d5:44:73:58: + ab:94:75:4a:36:3d:8d:4d:c6:7a:86:9d:00:db:c5: + ba:be:70:02:83:bf:6e:d8:31:89:b3:f2:16:98:be: + 27:f6:14:5a:e9:d4:72:67:8d:a9:df:76:27:bf:19: + ac:20:59:28:5b:1b:42:d9:d5:5b:6d:fb:6e:a2:5e: + d3:e9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + FC:18:13:52:BB:33:4A:DB:1C:5B:D1:80:98:3E:40:86:95:58:72:F9 + 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE, pathlen:2 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 0d:bc:87:df:e4:68:a5:56:54:d2:89:42:d8:b4:1b:45:6f:88: + b2:39:d1:ad:38:f4:0b:68:5e:e1:3e:88:60:4f:69:be:a8:ee: + 1d:14:08:69:86:ee:6a:08:42:35:6e:44:4f:5f:be:13:00:81: + ca:41:a7:70:d3:48:9f:60:03:14:a4:4b:7f:35:7e:6d:94:0b: + cf:63:00:fe:8e:54:2c:4c:ac:fb:ef:4c:68:91:9a:0f:45:3e: + 07:12:f2:74:e6:83:36:8e:61:49:f9:03:17:e2:16:72:eb:6b: + c3:c1:7b:95:37:31:1f:10:b9:fc:7b:e4:54:d4:4f:81:a0:f8: + 0e:be:99:43:50:dd:19:7e:f9:41:8b:0d:2e:b2:e5:2c:ec:9b: + 20:42:f4:3a:da:03:99:bc:c1:c2:6c:69:4e:8e:6e:ad:22:57: + dc:2c:1a:e3:4f:15:c4:b3:b4:5d:2d:be:d8:62:0a:a4:c9:62: + fb:9a:53:26:ee:8f:8e:43:a6:e2:77:9b:1f:1f:4f:86:b5:65: + 22:3c:0d:f7:75:ab:24:2d:5b:6f:96:3f:26:22:b0:de:b2:4e: + 37:fd:f9:9a:22:81:15:91:c5:b0:54:f2:ee:f0:e9:7f:23:ab: + 43:1c:43:e1:e4:bf:61:20:13:f3:4f:b6:71:77:a3:23:89:fb: + 02:c2:24:5e +-----BEGIN CERTIFICATE----- +MIIEwTCCA6mgAwIBAgIBZDANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTkxMDEx +MTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBoTELMAkGA1UEBhMCVVMxEzARBgNVBAgM +Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoMDHdvbGZTU0wg +SW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHTAbBgNVBAMMFGNoYWluSi1JQ0E0 +LXBhdGhsZW4yMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnUrua/+27IghI4QDtoi7PloblQMv +JFMtVz8ROF0SHUBrENvC0+TdgHd0e4hEZeDPUsWKQuVut2qrUKAuKcL+utXH2muR +Jo/8HgYX8N5Yh+8eppESOWilBfOMZ8nlmRik/JA/vabK8qbdteaTyxSJgzyIWjGr +42YqG4fFhQNFsM7hD8EPknDXrGXqqAnB/h3bt+fdmNPGsRa0VFjBqrqhzxkUp+RV +ptq7H57RhQDgjUrE0oYIdf3YHoUhbCePGNVEc1irlHVKNj2NTcZ6hp0A28W6vnAC +g79u2DGJs/IWmL4n9hRa6dRyZ42p33YnvxmsIFkoWxtC2dVbbftuol7T6QIDAQAB +o4IBDTCCAQkwHQYDVR0OBBYEFPwYE1K7M0rbHFvRgJg+QIaVWHL5MIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MA8GA1UdEwQIMAYBAf8CAQIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQANvIff5GilVlTSiULYtBtFb4iyOdGtOPQLaF7hPohgT2m+qO4dFAhphu5q +CEI1bkRPX74TAIHKQadw00ifYAMUpEt/NX5tlAvPYwD+jlQsTKz770xokZoPRT4H +EvJ05oM2jmFJ+QMX4hZy62vDwXuVNzEfELn8e+RU1E+BoPgOvplDUN0ZfvlBiw0u +suUs7JsgQvQ62gOZvMHCbGlOjm6tIlfcLBrjTxXEs7RdLb7YYgqkyWL7mlMm7o+O +Q6bid5sfH0+GtWUiPA33daskLVtvlj8mIrDesk43/fmaIoEVkcWwVPLu8Ol/I6tD +HEPh5L9hIBPzT7Zxd6MjifsCwiRe +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-entity-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-entity-key.pem new file mode 100644 index 000000000..f935b9046 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-entity-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAs/tRoKxpizUGv3rutKGKfq4xda3nRXvm2bt86XMO3s8FdN83 +pDczpm9ZBsifGTXDlPcFulLrPpIpYUiI+m1CtDDezt+U7ZKIYMhVNlDuNrXtNW+V +AfSIS3s+/rWcZMByvox0aoz15GVmh1Kde7Ag9tjD3na5cHwBgm78+hvnxMFfOM5Q +3Doih7wZmkXVinqT+XhZxwr5j+vDeeu17jbwXl0vj0boY8Ixgvz7XYzKAbG7civn +L4I8piSmP1h+aVtKALQls7PDs7DCP6PX7gQSHasLuwKwbAs2ZFapXTflCihEXhXk +9atzmAqzKJAdMPKM59sTag+0y40GFYbONRLjqQIDAQABAoIBABmsC2SjsxpMIf5G +Bq51LFANgLiMaaSbm74K5DJYWxKk7N5SyJj/1royv7wb+bWa2Z7x7Ts6gJuYNZbO +xdsSoqUZI27WrWOFtzY23RC2UoQzRvaMR/DTdG1v0vh55yjn2nYbiq94E8rUO9+p +hRUTdmA/YxDkVmcZCQ4VzrfOKy0BOr6SnC3U0QghQ+UGPFeFRvd8vnBk76U8+XMV +xUybnbU17hoEB2p9nle6h0G0GtXI9dnJ0BD2RJMIhvs1cfrOkW/s8dkAXsokH4UU +XRIyRESkb+lVMWv8n8qcHZ3rjH+mxjkTxKdlnNy9qTfPoGJiaDb3LMfyd2xWReAq +VdirDVECgYEA5B0Cy5WrjuQ8aWPOoQbV24mDZGqhAb66oJ9yMkbzQ5DHZdZrt7s9 +k/dBMWOD4tc7w5WPwjYSxY7QOBSq1TETYIafOK1NqR9lnLJnOKiMYp49O9nAfK/y +6AgXQo9fqIIYhmmqEQYl9MSgQjEa5d9CdDg4mh6YzhaVoXn06UF+H4cCgYEAyfv9 +nZT2PBasmZWZdFRG4l78WsQO0+/00HnhPXs0Dn31N9A9aQDj5O4wJoiRDJPYkO0o +9wANtibayIvUoB72L9gc+8KIEU8Xuda+JtB+oPVi88Limxw3iBwrBUF9QA8Jjmrk +KtNOm5IrSpYpTEvOQkZFlskhQajey4Kys69Pz08CgYEAouqtUmVEr7sGAmcL7imJ +l0+xDYiyESL8+zalQo81si22m172c7RAmGrgnrtqOBpsTpWEpLol0f7baxInqDdy +lV/QW5Q6gO0xjyZDXk3SZaSKKzKrrOGk5F7S7fCj6x9vEKBqm9n+RcAgjOWxRjeb +qJF2q2vqylWK7FbDucvSngUCgYAOFa5XwL1y7znV8+KhhAb1Xh5GzgkiqkbuCrG0 +MdUtdYcV/0Vo/xDlM97TsQ48TEr7wC3tG2nZW9hBx85p4/7S00UiISyP2G4VHW5h +EoTiAHqH+P0IR+1vZldxpGFxiBrofXevrNB8dLLkHph+o4KciH3tx9Sz2Wy/0DtZ +4E22bQKBgCOb2dGVVS7fmM81Mg1Al9k9USVxp4wnS1iIHK1c/rBB61TPEyblhiqF +aveFoCse8SparMJ9utkqSqA7zQ3qwoPJZJ9p4T2pI0xp8yu15yBLeYgO0R7kriEC +XIapznOZvvC0/vSUT3kTOX27HlIcPqNOPnpYjsfdZ10okplrXnKB +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-entity.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-entity.pem new file mode 100644 index 000000000..35c5f6367 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/chainJ-entity.pem @@ -0,0 +1,87 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-ICA1-no_pathlen, emailAddress = info@wolfssl.com + Validity + Not Before: Oct 11 18:30:30 2019 GMT + Not After : Jul 7 18:30:30 2022 GMT + Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL Inc., OU = Engineering, CN = chainJ-entity, emailAddress = info@wolfssl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b3:fb:51:a0:ac:69:8b:35:06:bf:7a:ee:b4:a1: + 8a:7e:ae:31:75:ad:e7:45:7b:e6:d9:bb:7c:e9:73: + 0e:de:cf:05:74:df:37:a4:37:33:a6:6f:59:06:c8: + 9f:19:35:c3:94:f7:05:ba:52:eb:3e:92:29:61:48: + 88:fa:6d:42:b4:30:de:ce:df:94:ed:92:88:60:c8: + 55:36:50:ee:36:b5:ed:35:6f:95:01:f4:88:4b:7b: + 3e:fe:b5:9c:64:c0:72:be:8c:74:6a:8c:f5:e4:65: + 66:87:52:9d:7b:b0:20:f6:d8:c3:de:76:b9:70:7c: + 01:82:6e:fc:fa:1b:e7:c4:c1:5f:38:ce:50:dc:3a: + 22:87:bc:19:9a:45:d5:8a:7a:93:f9:78:59:c7:0a: + f9:8f:eb:c3:79:eb:b5:ee:36:f0:5e:5d:2f:8f:46: + e8:63:c2:31:82:fc:fb:5d:8c:ca:01:b1:bb:72:2b: + e7:2f:82:3c:a6:24:a6:3f:58:7e:69:5b:4a:00:b4: + 25:b3:b3:c3:b3:b0:c2:3f:a3:d7:ee:04:12:1d:ab: + 0b:bb:02:b0:6c:0b:36:64:56:a9:5d:37:e5:0a:28: + 44:5e:15:e4:f5:ab:73:98:0a:b3:28:90:1d:30:f2: + 8c:e7:db:13:6a:0f:b4:cb:8d:06:15:86:ce:35:12: + e3:a9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 13:92:E0:30:5E:36:4F:BF:D5:E3:0D:5D:40:0B:64:95:EC:8E:77:4E + X509v3 Authority Key Identifier: + keyid:9C:7B:3A:10:B3:08:99:05:00:AF:3E:E0:A4:5D:D9:AF:82:BC:4D:C0 + DirName:/C=US/ST=Washington/L=Seattle/O=wolfSSL Inc./OU=Engineering/CN=chainJ-ICA2-no_pathlen/emailAddress=info@wolfssl.com + serial:64 + + X509v3 Basic Constraints: + CA:FALSE + Signature Algorithm: sha256WithRSAEncryption + 10:a0:e0:ea:4b:df:4c:5b:92:da:6b:13:5a:4b:e9:46:1a:17: + 48:42:5e:08:c8:28:e4:ce:69:46:25:55:70:57:bd:4e:b2:0b: + a4:75:22:b6:5b:d7:e0:54:3f:31:14:99:09:c1:3b:6f:b7:59: + 5a:52:67:46:0c:4f:ec:fa:31:4a:6e:59:04:50:99:60:1e:74: + ed:3a:ac:4d:cd:98:31:4d:b1:54:07:3e:76:bb:92:e2:1d:53: + 65:08:38:e3:4d:b0:d8:74:14:5f:00:94:e7:d2:c9:9d:80:23: + f5:9e:3d:8c:22:72:b3:20:5a:01:a3:02:f2:9c:cc:b8:1d:73: + db:eb:cc:cb:27:4f:75:17:1d:23:68:07:4f:15:be:00:cc:a9: + 2a:14:82:2c:0e:e3:92:40:dc:62:ac:d9:61:24:99:19:43:d5: + 3e:85:ca:e5:6d:e1:76:9a:4e:01:ef:34:98:7a:1b:ca:8b:c3: + de:99:22:75:28:11:0c:17:7a:58:7b:44:33:22:58:61:24:8c: + 96:a5:a7:63:19:31:6d:61:83:1c:5f:50:66:48:29:b4:2d:8e: + 5e:f3:63:85:e8:9c:d8:6e:93:4a:4d:ff:b1:d5:60:96:d0:9f: + 4e:3f:6f:c9:b4:e1:04:b8:ef:55:c2:77:c1:e1:50:d0:a7:b8: + 9d:a3:81:71 +-----BEGIN CERTIFICATE----- +MIIEvDCCA6SgAwIBAgIBZTANBgkqhkiG9w0BAQsFADCBozELMAkGA1UEBhMCVVMx +EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTATBgNVBAoM +DHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFmNo +YWluSi1JQ0ExLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz +bC5jb20wHhcNMTkxMDExMTgzMDMwWhcNMjIwNzA3MTgzMDMwWjCBmjELMAkGA1UE +BhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFTAT +BgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxFjAUBgNV +BAMMDWNoYWluSi1lbnRpdHkxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz+1GgrGmLNQa/eu60 +oYp+rjF1redFe+bZu3zpcw7ezwV03zekNzOmb1kGyJ8ZNcOU9wW6Uus+kilhSIj6 +bUK0MN7O35TtkohgyFU2UO42te01b5UB9IhLez7+tZxkwHK+jHRqjPXkZWaHUp17 +sCD22MPedrlwfAGCbvz6G+fEwV84zlDcOiKHvBmaRdWKepP5eFnHCvmP68N567Xu +NvBeXS+PRuhjwjGC/PtdjMoBsbtyK+cvgjymJKY/WH5pW0oAtCWzs8OzsMI/o9fu +BBIdqwu7ArBsCzZkVqldN+UKKEReFeT1q3OYCrMokB0w8ozn2xNqD7TLjQYVhs41 +EuOpAgMBAAGjggEAMIH9MB0GA1UdDgQWBBQTkuAwXjZPv9XjDV1AC2SV7I53TjCB +0AYDVR0jBIHIMIHFgBScezoQswiZBQCvPuCkXdmvgrxNwKGBqaSBpjCBozELMAkG +A1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUx +FTATBgNVBAoMDHdvbGZTU0wgSW5jLjEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAd +BgNVBAMMFmNoYWluSi1JQ0EyLW5vX3BhdGhsZW4xHzAdBgkqhkiG9w0BCQEWEGlu +Zm9Ad29sZnNzbC5jb22CAWQwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEA +EKDg6kvfTFuS2msTWkvpRhoXSEJeCMgo5M5pRiVVcFe9TrILpHUitlvX4FQ/MRSZ +CcE7b7dZWlJnRgxP7PoxSm5ZBFCZYB507TqsTc2YMU2xVAc+druS4h1TZQg4402w +2HQUXwCU59LJnYAj9Z49jCJysyBaAaMC8pzMuB1z2+vMyydPdRcdI2gHTxW+AMyp +KhSCLA7jkkDcYqzZYSSZGUPVPoXK5W3hdppOAe80mHobyovD3pkidSgRDBd6WHtE +MyJYYSSMlqWnYxkxbWGDHF9QZkgptC2OXvNjheic2G6TSk3/sdVgltCfTj9vybTh +BLjvVcJ3weFQ0Ke4naOBcQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/include.am b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/include.am new file mode 100644 index 000000000..adaa02511 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test-pathlen/include.am @@ -0,0 +1,88 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + certs/test-pathlen/chainA-ICA1-key.pem \ + certs/test-pathlen/chainA-ICA1-pathlen0.pem \ + certs/test-pathlen/chainA-assembled.pem \ + certs/test-pathlen/chainA-entity-key.pem \ + certs/test-pathlen/chainA-entity.pem \ + certs/test-pathlen/chainB-ICA1-key.pem \ + certs/test-pathlen/chainB-ICA1-pathlen0.pem \ + certs/test-pathlen/chainB-ICA2-key.pem \ + certs/test-pathlen/chainB-ICA2-pathlen1.pem \ + certs/test-pathlen/chainB-assembled.pem \ + certs/test-pathlen/chainB-entity-key.pem \ + certs/test-pathlen/chainB-entity.pem \ + certs/test-pathlen/chainC-ICA1-key.pem \ + certs/test-pathlen/chainC-ICA1-pathlen1.pem \ + certs/test-pathlen/chainC-assembled.pem \ + certs/test-pathlen/chainC-entity-key.pem \ + certs/test-pathlen/chainC-entity.pem \ + certs/test-pathlen/chainD-ICA1-key.pem \ + certs/test-pathlen/chainD-ICA1-pathlen127.pem \ + certs/test-pathlen/chainD-assembled.pem \ + certs/test-pathlen/chainD-entity-key.pem \ + certs/test-pathlen/chainD-entity.pem \ + certs/test-pathlen/chainE-ICA1-key.pem \ + certs/test-pathlen/chainE-ICA1-pathlen128.pem \ + certs/test-pathlen/chainE-assembled.pem \ + certs/test-pathlen/chainE-entity-key.pem \ + certs/test-pathlen/chainE-entity.pem \ + certs/test-pathlen/chainF-ICA1-key.pem \ + certs/test-pathlen/chainF-ICA1-pathlen1.pem \ + certs/test-pathlen/chainF-ICA2-key.pem \ + certs/test-pathlen/chainF-ICA2-pathlen0.pem \ + certs/test-pathlen/chainF-assembled.pem \ + certs/test-pathlen/chainF-entity-key.pem \ + certs/test-pathlen/chainF-entity.pem \ + certs/test-pathlen/chainG-ICA1-key.pem \ + certs/test-pathlen/chainG-ICA1-pathlen0.pem \ + certs/test-pathlen/chainG-ICA2-key.pem \ + certs/test-pathlen/chainG-ICA2-pathlen1.pem \ + certs/test-pathlen/chainG-ICA3-key.pem \ + certs/test-pathlen/chainG-ICA3-pathlen99.pem \ + certs/test-pathlen/chainG-ICA4-key.pem \ + certs/test-pathlen/chainG-ICA4-pathlen5.pem \ + certs/test-pathlen/chainG-ICA5-key.pem \ + certs/test-pathlen/chainG-ICA5-pathlen20.pem \ + certs/test-pathlen/chainG-ICA6-key.pem \ + certs/test-pathlen/chainG-ICA6-pathlen10.pem \ + certs/test-pathlen/chainG-ICA7-key.pem \ + certs/test-pathlen/chainG-ICA7-pathlen100.pem \ + certs/test-pathlen/chainG-assembled.pem \ + certs/test-pathlen/chainG-entity-key.pem \ + certs/test-pathlen/chainG-entity.pem \ + certs/test-pathlen/chainH-ICA1-key.pem \ + certs/test-pathlen/chainH-ICA1-pathlen0.pem \ + certs/test-pathlen/chainH-ICA2-key.pem \ + certs/test-pathlen/chainH-ICA2-pathlen2.pem \ + certs/test-pathlen/chainH-ICA3-key.pem \ + certs/test-pathlen/chainH-ICA3-pathlen2.pem \ + certs/test-pathlen/chainH-ICA4-key.pem \ + certs/test-pathlen/chainH-ICA4-pathlen2.pem \ + certs/test-pathlen/chainH-assembled.pem \ + certs/test-pathlen/chainH-entity-key.pem \ + certs/test-pathlen/chainH-entity.pem \ + certs/test-pathlen/chainI-ICA1-key.pem \ + certs/test-pathlen/chainI-ICA1-no_pathlen.pem \ + certs/test-pathlen/chainI-ICA2-key.pem \ + certs/test-pathlen/chainI-ICA2-no_pathlen.pem \ + certs/test-pathlen/chainI-ICA3-key.pem \ + certs/test-pathlen/chainI-ICA3-pathlen2.pem \ + certs/test-pathlen/chainI-assembled.pem \ + certs/test-pathlen/chainI-entity-key.pem \ + certs/test-pathlen/chainI-entity.pem \ + certs/test-pathlen/chainJ-ICA1-key.pem \ + certs/test-pathlen/chainJ-ICA1-no_pathlen.pem \ + certs/test-pathlen/chainJ-ICA2-key.pem \ + certs/test-pathlen/chainJ-ICA2-no_pathlen.pem \ + certs/test-pathlen/chainJ-ICA3-key.pem \ + certs/test-pathlen/chainJ-ICA3-no_pathlen.pem \ + certs/test-pathlen/chainJ-ICA4-key.pem \ + certs/test-pathlen/chainJ-ICA4-pathlen2.pem \ + certs/test-pathlen/chainJ-assembled.pem \ + certs/test-pathlen/chainJ-entity-key.pem \ + certs/test-pathlen/chainJ-entity.pem + diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test-servercert.p12 b/FreeRTOS-Plus/Source/WolfSSL/certs/test-servercert.p12 new file mode 100644 index 0000000000000000000000000000000000000000..c85fdd27920792f450a379f825e30978dc693687 GIT binary patch literal 5277 zcmZXXWl$6hqlH;w$px3CQ5vK}Kw=4Lq(f;Cq!C2Am+qxY8bMk>U?rtN>5ip4L}2My z>b~#Hz4yB__t%+u&dm9FW*+_!vP?_>7JmrYJ0L!1gmT0c2!IPH2qDwL4k1(f2P^Z3 z5I_E>0v3c2AOC|6Faa3<#P)w00RK}U!GA9h{j*4njmLU4ElO}`FpG(ahY=J)+;qzM zUQ{pq02!1UuHQ7#;oI?DD3d#dN>3ZcKobZ1)FNKQZ2p7h_hNz$-Nyzr)3f*E$ErXy z`+hHO&4)m@_J5y2eev#fET%&pi3Nv*_8LUw^NxgdU;k433-)Nb9E=>E7E)Sx9!p{wK4JY z*iDn-$jC1QIU_>SaU{XTsrA>yU__x?!)!KFgPR+>(l@T>XfjtupTNG%YSAYk^fp{sQxk%I6iLJmZqm-1z%k)?KnJR6{ZjHVhg4f%OYgmS_lzwS80A7JUX*3A zuV(mW9sX>@QJdI4fi31ay@M&|Q_&NC6Ph4fgg+Ax8wN?=_T{JHtrVhctjsUjX(eYg zw#n(?r}}gAhPsj4!$Q?pSkKz>yRArDGrVHwf2+Fj@!|zMzSih14YUIsN0y2>3?xrQ zMpT+nqfVHW6yg`B<~85VVB3pNi{n~E2$faezGH0ooh=OelBT5V>hGM5O)m}V<}(X! zZN(qIm9agDX4~r$oo~V!0kwAN zA+THyY&K$Wu)_s*ahM}Vmkwv0eHJ*Sw-Otb2E&KHbjV40*Eg)y?K`PeKifm12!hE~ z1cwPYzZiz>#u_pT%4uLx({bg1An*~FNoqep@eBO3`odpw<-qF0So_*xud{3q4jPsoqe) z(c8xK1}1+$%EhUwRAr5B+u65Yub%xvEpAI?tGwn9`KAl?i&5X2wPi!0*hR13=(<^%;+eS+5r}^njh4htDs@2h|ri2}lfGJsk za6tL!;2BK(O3^r6e-VM!`M@5Hn7lGoLH~}{Kdj{@x%k8N=_sLXTjQw0@pf=I_QMrH zyF4$y){sPfBeO{C`#%(uQB0DZ-#cCp>Y2j1dUG&Hk`~&}dxUcEv?`x&O;p?u-3@)9 zr2e(=!fny_4r>nJ|D~E>%0k}gH9l@8`CO-|KAAY6MzZsyf1C-1Vk*M%KH7`0 z9aw%|TB+D^+v+D9HXC-m*~+M%5=Ty8^JNF!2iXRF2H_kAA5nczx_OiZ)?F(JQRYO- z7|u^1gg1zqvA$ZY1G2?6aGRN5k7G7o>^XiInZyKts~maLxRj`hS?ttYSm|~8ZY(F8LFV#n5 z5|7j{_tNJKpLob!RlKNv`m>1{0FwRJh53ErE~t2vSfKG7C$*DGFLV@st&nS8rIfr0 zjq}*!4mA5U#>OkuI;#{f(-vhm35iaVLgG(6mya^0G0vUIIHtUAHQ#C2+i(`vtl7@h z2#nOP+I&eoxhWo1;5{fkHfqLd`6&nF&=lxSvAB}h#_yj`2X{!IOPBTXxdUEfJz#ub z?c3#joU)Vo&Tu4e6PGce0UDgVgiMO8@D5G(CHfL@Mwe#nP7s)tmy zmYo|?+6apcD!ME`5K;PEk-bWcbNvbv$ZOU#EjQd}5HW}Cu^uJV5XsAATF|u#%rxbA1=LI(O@J-XLY`&Yuy#&c@h>Ig7UcA)%*D(L z{dZF{yjd0;;X9`M(aETa;su~d(c<#@CZSH;3Q6>Us|C0UYa{=&AQ#bS)9Fk(2I@8S?&?3-Z#S~F&AHiJE+e6EC|p`sIWm`2fv)O zTqg3?=Hci02#@>n?)ZtUsNEWbcyp{ad)8R!MA)WR*U+_A`_kz3p!(7f!b-fR&peQC zd6apwXkC(-Eb2AAn9<|){@_q2MO6b|s^Zl;Ogq~H36hcGiRD(xeX`X{!fvyPesi#th!$af?uOPLPReCi=BMG?5^TH9@uMZ$w8>tBQ-h~?@ayaKcVMM@my{|oQV*6gKz5XLw9CD z`d{6Y=A3xjyUZF+0zQhF+7vKz&GWOL<*$>~U^TKW_(b1G#o|Qfmp%63*+3X-X26xM zX%DEjdiP1t$I;*29*EZ{-^W>N2)mJK0_Cxm^D0kgSRGLWEvinf7sKPglYm5`N|IP6 zIbPWA0r0+CImKdjnF3@@d6>TUGe7}9_r_6*0`GJnNK_<8Vr|(gIs)hSp(+mZuv~pJ z+%^2!4zTJEm&MQx(c7IsC(>JAGr;bOQ4*M?Uf#e9yF~e|hJ=FeHqTmz5qL{GeG{YN z&3;fOp$#mU63i3BCFF_3w@&TrQb+M-Q z(>byan8_sr%3^lMT(ETkhMjw0u$sk054}M3NYt+^rsHn(ROP0@_*D%HQO+t++ zb_Sk0l>mIj6XBcp!7X6bvHsw=5m$&^qSZ*Z0`i93Z3#cAqc8yfRDJBqhVM-Z@?$O= z9rHzWbt*zKRPJ9HF<MTIB+NtS;#Xkm2p z#)aNH+Cg%DbZMK%9(>OF6?rs|5t{ygT6IbzHCoU8CIDBKUtl~xh~h5Oy;MVrEt(o` zL?geg0YD{gGep}0^qaU?0yD89t)~wgTa{l{>X%H;lKH5f<&KqO`f5SoEv^i6*my@t zBKx4p)Qp4Jo*9OIy4rqj%e=_l)9(o^TE{=W8ZGzF1E$2m%c@i%bm_v1p~gRXGC`co zcdUXM62zORM%YNjlb3`(+`d!VL&*=!35;%a9_v4Iq79?I7pTD-6JI)YfW<7>Rtmn} z80@u*s^woQpXw8H2S`Az94FYdF5x(zW>xqKj|`bjnf-i!(Ywsz>Kn>_SD(oo_sN4B z2N=TdcJ~-rA~jd1ke`2QrKz1Hh3-BxJgYjG$kUquDTO8f>=0wwkt%LSS?N%X91Jlh z9@A4dc5QLmqMRHz#KlgaC}K!k*ovzYNBmg1Y&!zOgCV7se2uXPrm5Lcs?rHJKen~} zp#>eYCJGPzAze!%n>FOPAsyVDR~S;+Pi?G_xz2P;;q+_;+^ZbASZR3mCB=R|#Mk2J zT7p7$`g|0=k~r*%Y=7PS8v26!(x#e3QSm2G=N!#NF=W{S(CPHTRN$o_Kv z>-~s3hA*7s726=2W%t1t4|5y8l?niQ+r#+BGJ0w&9!c=wGMzTZC zvbyvtZUTM#o02!K{+#YbPc2ATS#UfFUBenli&5Wog+#;M%~p(P8%JbNCgh!N8n<*( z&?-Ks-_lc1+E%L;nIsUay{IZtd?j@ulWomLqWRvxd2g@_|Zv|{SitMi_^^t_q1dj*y$LYo}S;^Z$$lER}`EQz)isPv<2T0~5i zE~WSp_9M7_m!WvIsem4{N8pbvFM+}(wp(R%?U8#P(!wvH{ZoIoPY={Dw}%5B6J_O* zA_t^QL?n>vg-PMfU^GcdffvtIGq>Gq;2jvM4F z??+SaLi72Hd5OHazK)5_=@}?KEzw#$(v8g%f`k1BT3|FBlJBgyAs?PkeFmi*vT|K2 zG2oP~Nzx;NR+}e8Vn2JGNU$P>?@XtO?DHARV2>-_DjUg2v*_yOj z9JfZZt(=-bg>JK=RQka9F&-v8?r57ujI{7_J)$4l#2O(at_h!@6g;#5*!nqB{+woQ ze-?>nzYuG40DF;K46)L-O^$DAtauy=9jHSXMx4iMuW)^jztpT}ClcrVRx#A@{{i zEL7?5qs)|%bt>_&6eO+v{$$1Cj9XSp5I@5Fjc1I#oC@dGOxB6$qd+T9Owfyq1&uzP zAeH_x>K9RcM2w57w+gBZP}liFfth?}%9|y2=RL3LH`x;>A{iHZhktn>K+oI_y$qE%QXQC!X0z-Y zZEl~gFg(Nc$`h#|=$~y4B5dT6Vxa4hXtw|kE((laxswl5T{M2xoNl0X$no8RSIN5u za#1GRJ&YZ^jGYV<<3fF%jpcV^sSQp_w_NK;nFb7|;mDs% z?zoL?TT@XJCi;V4wT+4=E2rEt4{KtlzV*T0YcY4O-t^;K#obO^;>07vY_d|lKgsGv fX6_wMlUMEGVDgf!o+4~Kq~w&=sN}lwzc2Y;nU(@B literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-ia.cfg b/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-ia.cfg new file mode 100644 index 000000000..44be1126a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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@wolfsssl.com + +[ v3_ca ] +inhibitAnyPolicy = critical,1 +nsComment = "Testing inhibit any" + diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-ia.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-ia.der new file mode 100644 index 0000000000000000000000000000000000000000..a6fb6508c60523319dbcd1e7e08bf407ed2af2e6 GIT binary patch literal 1022 zcmXqLV*X{&#PnzZGZP~d6DPxw=oPQd^ZaKs;AP{~YV&CO&dbQi&B|cVxWJIxfRl|m zl!Z;0$uZPW*gz1(;o#v4EKN<#E6z#GOEDBQ;0Fn^^Kdv7WfmtT=A{~n7zlxcxOlkB z^K;UIgMAb{^O9kr+&tW_dFh#Xsi{SodFh4{24Wz!%sl+%<>h)H^~J?Gddc~@hROzt zaOZF`iis4L78K+cl{i4uKol9siSrs-7?>Cu8=4v!8yZB3^BNf%7#f&ExkJGVO^iy& z0nfh&tTBR$i>ve$jESDD#ycc$4`a1+b_8~sxzh@b6xjokBY&Lsps_lu6>i~ z*i$qA_lorTe=&0cOTTxWVt;O`-~VuL^#T2w)hR2)|D1}g-t|E7X^~#OUfYeS#kbZ- z2k(rxzb?tE>i;k~Ik1~M#eS{xj-@g&CY#qWEJ!~3t)4qFqoR0OkHku*-1Ubg8TEDu zJU({DVN2#>H{;Cqyd%5CmwkS5cWv>WYJJ76f71ea_J(YJm>Vy%N4fYSCv&IBC4rqO zhqW#&oaVLX;T5Uq;|mTPOs?Q}F*h)p)?lPObz%7~;Y-ttAH}Mk%;G(4nXqKbhD;|X z&X+eh_82Q{j!;^@>h+O_&k~!DUYd6Q<^}(?*O{0Z85kFv8W;mZi8)l(jFIs_3ozj_ z8Yr=GCbW4lw*7Eo8tmt4_SjR@$8m}T)BJq+p910Zcf>J(>7~M z>O7{h1b0KFpFLcA%f(N|?=KKcesQrc+%h*WDYduFb58HNlfgS{(z+ABm^|=)Bz1IY z%k3K*bu?!j-*Avef9o{sPX?>*xmKyIeE#5_$FwuWq2>uU*j_8h=RaP{lD+9mcN`ZJU>DlG~S4!)@p2d0^`SrPCrU+jaT(WTnP!^<=$Lwz#BT JR$-D~IsnQ*g3|y1 literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-joi.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-joi.pem new file mode 100644 index 000000000..7ec57286e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-joi.pem @@ -0,0 +1,76 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 13085343280838917500 (0xb5987a628272bd7c) + Signature Algorithm: sha256WithRSAEncryption + Issuer: O=Example Ltd/businessCategory=Private/serialNumber=5157550/jurisdictionC=US/jurisdictionST=California, C=US/street=123 My Street, ST=California, CN=example.com/subjectAltName=DNS.1=example.com, DNS.2=www.example.com, DNS.3=billing.example.com + Validity + Not Before: Aug 10 15:20:25 2018 GMT + Not After : May 6 15:20:25 2021 GMT + Subject: O=Example Ltd/businessCategory=Private/serialNumber=5157550/jurisdictionC=US/jurisdictionST=California, C=US/street=123 My Street, ST=California, CN=example.com/subjectAltName=DNS.1=example.com, DNS.2=www.example.com, DNS.3=billing.example.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) + Signature Algorithm: sha256WithRSAEncryption + ac:5a:d1:a9:e8:ed:75:8e:87:13:38:39:c5:d7:43:fd:72:31: + 34:4d:c3:41:f4:6a:d8:64:a2:ce:cf:d8:ab:81:9f:2c:26:4d: + 69:35:42:63:f8:53:c4:c5:f6:00:15:29:4d:3b:5e:bf:2c:8b: + a8:ad:54:22:c0:93:78:34:9c:e7:79:c1:d0:fe:7c:bf:87:b9: + 21:dd:d6:f9:35:ae:17:94:90:55:99:48:c8:d3:47:b1:be:1b: + 1f:62:31:0c:3a:e5:8e:b3:93:e6:93:02:36:e9:97:1e:7f:6c: + 55:6a:b8:9a:d1:d1:36:52:cb:3f:9f:5e:95:c4:0f:03:d5:a1: + 4c:d1:7e:8a:dd:58:ec:a1:17:c7:68:fe:91:b6:e7:66:8b:f7: + b3:a8:25:ad:2d:e9:c9:55:02:a2:39:16:cc:b0:aa:65:bf:21: + b5:dc:0a:d3:92:36:ae:84:d8:a3:d3:35:ba:b9:bc:b8:7d:2e: + 64:58:db:d7:ec:86:51:a2:44:7d:ba:98:30:c2:c5:4f:3c:ea: + 9f:1d:b0:1e:87:dc:49:4f:bf:42:70:c8:a3:3e:ad:6c:47:e3: + d3:ff:17:1c:37:c1:fa:34:b5:7b:e7:07:b6:c2:66:3a:89:57: + 44:1a:f5:6e:e0:cd:93:c0:c2:13:2e:e2:67:e7:8b:27:57:c1: + 16:f3:ad:eb +-----BEGIN CERTIFICATE----- +MIIElDCCA3wCCQC1mHpignK9fDANBgkqhkiG9w0BAQsFADCCAQoxFDASBgNVBAoM +C0V4YW1wbGUgTHRkMRAwDgYDVQQPDAdQcml2YXRlMRAwDgYDVQQFEwc1MTU3NTUw +MRMwEQYLKwYBBAGCNzwCAQMMAlVTMRswGQYLKwYBBAGCNzwCAQIMCkNhbGlmb3Ju +aWExCzAJBgNVBAYTAlVTMRYwFAYDVQQJDA0xMjMgTXkgU3RyZWV0MRMwEQYDVQQI +DApDYWxpZm9ybmlhMRQwEgYDVQQDDAtleGFtcGxlLmNvbTFMMEoGA1UdEQxDRE5T +LjE9ZXhhbXBsZS5jb20sIEROUy4yPXd3dy5leGFtcGxlLmNvbSwgRE5TLjM9Ymls +bGluZy5leGFtcGxlLmNvbTAeFw0xODA4MTAxNTIwMjVaFw0yMTA1MDYxNTIwMjVa +MIIBCjEUMBIGA1UECgwLRXhhbXBsZSBMdGQxEDAOBgNVBA8MB1ByaXZhdGUxEDAO +BgNVBAUTBzUxNTc1NTAxEzARBgsrBgEEAYI3PAIBAwwCVVMxGzAZBgsrBgEEAYI3 +PAIBAgwKQ2FsaWZvcm5pYTELMAkGA1UEBhMCVVMxFjAUBgNVBAkMDTEyMyBNeSBT +dHJlZXQxEzARBgNVBAgMCkNhbGlmb3JuaWExFDASBgNVBAMMC2V4YW1wbGUuY29t +MUwwSgYDVR0RDENETlMuMT1leGFtcGxlLmNvbSwgRE5TLjI9d3d3LmV4YW1wbGUu +Y29tLCBETlMuMz1iaWxsaW5nLmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAwJUI4VdB8nFtt9JFQScBZcZFrvK8JDC4lc4vTtb2HIi8 +fJ/7qGd//lycUXX3isoH5zUvj+G9e8AvfKtkqBf8yl17uuAh5XIuby6G2JVz2qwb +U7lfP9cZDSVP4WNjUYsLZD+tQ7ilHFw0s64AoGPF9n8LWWh4c6aMGKkCba/DGQEu +uBDjxsxAtGmjRjNph27Euxem8+jdrXO8ey8htf1mUQy9VLPhbV8cvCNz0QkDiRTS +ELlkwyrQoZZKvOHUGlvHoMDBY3gPRDcwMpaAMiOVoXe6E9KXc+JdJclqDcM5YKS0 +sGlCQgnp2Ai8MyCzWCKnquvE4eZhg8XSlt/Z0E+t1wIDAQABMA0GCSqGSIb3DQEB +CwUAA4IBAQCsWtGp6O11jocTODnF10P9cjE0TcNB9GrYZKLOz9irgZ8sJk1pNUJj ++FPExfYAFSlNO16/LIuorVQiwJN4NJznecHQ/ny/h7kh3db5Na4XlJBVmUjI00ex +vhsfYjEMOuWOs5PmkwI26Zcef2xVaria0dE2Uss/n16VxA8D1aFM0X6K3VjsoRfH +aP6Rtudmi/ezqCWtLenJVQKiORbMsKplvyG13ArTkjauhNij0zW6uby4fS5kWNvX +7IZRokR9upgwwsVPPOqfHbAeh9xJT79CcMijPq1sR+PT/xccN8H6NLV75we2wmY6 +iVdEGvVu4M2TwMITLuJn54snV8EW863r +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nc.cfg b/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nc.cfg new file mode 100644 index 000000000..9e8ff6be5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nc.cfg @@ -0,0 +1,22 @@ +[ 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@wolfsssl.com + +[ v3_ca ] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign +nameConstraints = critical,permitted;email:.wolfssl.com +nsComment = "Testing name constraints" + diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nc.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nc.der new file mode 100644 index 0000000000000000000000000000000000000000..10438666b3d551d97f78837611b4634dde0ac363 GIT binary patch literal 1146 zcmXqLVkt9dVvbwD%*4pV#L3W}6{OQt6~k@7%f_kI=F#?@mywa1mBFBKfg!g6CmVAp z3!5;LW2m99fgp&(!NV0;nwpwdoRgTBVkl_94-#bO;czO-EKW+yOEnZR5CREt@o<;t z=cEM(`zUzkCBsCydAMEk(lhf?Q;Rb5(hVgH#6W79dHBoA%k@C&i;HvglJj#7l?@c( z&f#Pf6Dck&D9A4=ae%0SC^C=}=QXr2FflYXG&M3dG>8)CH8M0XG%$y9hk_TH7?qF% zo{^P-xrvdV!Jvtei>Zl`k>S8pj)&onp9*ugUvhO+XG}fjy6)2+6@wj9&*}SJ`zF(| zr)K`|73uZ=V&(*ve(yTP{@hf*|KZ;11Nt?qQ&x!oITc&I>w)6aBE5XQwi{E6Z>^CI z-WhLyU6NPT|6y`+U^jP){aWW8OJ!nAHm_q?kbLx8J$GbAMe(v8iIq&b>kmsZ>g^DC zeC&+FmdwR&#+mJTM|O)Z`~2eW+TuOc`ifisrUmls4cYuKH(q9sa`8n@=1!4I0y|R< zYh744&1=uYD^k(N7aTa4T*2>RZeTR6!AN=P!t!0hm!=m#id8+C#e3K?Vab*anNCie zFK=+{F;>_dp|pI}>mv`JB{mbMKo*!*WcgUcSVT4p z8l9Xpqvg@b9~Z3in4M0^^Yz&n$b+PnS%7J(0lNZFx|9`WWc<&3xh_&{R( zATbtTerPk01M%fRd|*0WAYj1P$b+0N4b<5<6WTl&+kQAP^0G*YNra>pmjF|;LSABS zszP#pUU5lLVrE`RF><5=a}zL985t(Bf6v@Db(vSH+mr;3m+Dh~_**}(4%~BG3q85$Yhx5InYZPz4e>!j4zx}(fvza(b&b&EWdPAx9qF5!1 z%V%FQv9rBNUwLT4!ukm}4<{!ITob%LUE!$e!-S=CmI|C_iaokgFLQa)*>^wnifSZI z&;G$OL0?d3y6cl;Ow|$J@(&znkNeoN^oL@$w}f{lYiaD%6)H(D9UMPR!MjfbHXRuJ8{ZUZUA7#o+khR literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nct.cfg b/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nct.cfg new file mode 100644 index 000000000..fde389bf4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nct.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@wolfsssl.com + +[ v3_ca ] +nsCertType = critical,server +nsComment = "Testing Netscape Certificate Type" + diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nct.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-nct.der new file mode 100644 index 0000000000000000000000000000000000000000..febf458ba67b2a4833a91db415bbeba712c45d24 GIT binary patch literal 1054 zcmXqLVv#avVrE*v%*4pVBvPcjI4(5%#OI7ZESH?kR?Ln+(`#nH%f_kI=F#?@mywa1 zmBFBKfg!g6CmVAp3!5;LW2m99fgp&(!NV0;nwpwdoRgTBVkl_94-#bO;czO-EKW+y zOEnZR5CREt@o<;t=cEM(`zUzkCBsCydAMEk(lhf?Q;Rb5(hVgH#6W79dHBoA%k@C& zi;HvglJj#7l?@c(&f#Pf6Dck&D9A4=ae%0SC^C=}=QT1gFgCO_Ffy_`?N>J zV8_&R`hM5G$#m?gng4r5di}qcIf13$yH2q`H`VWdxVQR%e$DEX72% zFJG_i#?<0lYovpB#@k<)5n4BEg&7ESu)_KQLnHZDJ>lhX!AN^L(9hp&4ysSrJ zB~$MD!;*}8I|LpdJL9k=bFrIoW_#X|-QvqWzqq@$cu%#y;?}=ufjoOdHb2abm)WCS ze36s6Q{BWy?RZnK| z9=1$avSmZ2lN0C58ytI#6*fmGEnoHe$irue%||ayyMOb7|Jv(J%!~|-i@gjy3`E#C z6WTl&+kQAP0>OV47G@?k2Ll6yC@+h$m|{q3aS1SGDfp$96elMZq$)V47L{bCWhN(< zq$-3|7NjDFHZYk3Lz|I-SyGat>x<;|qbi2C*EGD+V(n5(v*cM6b*Ni$*^}K;FBJEC zPTXeMzx}1n%#1{R!&_xL{?8Dfnxtm##g|jR{mmhUTqj(*0W0O)2sj?r-MTP literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-ns.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/cert-ext-ns.der new file mode 100644 index 0000000000000000000000000000000000000000..10cc65520e28756aac740d91ca77f231ed67529b GIT binary patch literal 4677 zcmds4dvH|M8PDcLcqE`9Kq!<;3K$41=ia;b^$CS!6CR;}k^~Tq;XcELB%AJTkbq(d zLaU6VXrXqdAShOc!KN*PNGa1+ajb}C5NojkN~chmf?z39=mYyZo3|u0t^c*lW%uNq z^L^)g{(k2M-AF9tg={nCQa=HoLNjKzj`&{--AFVPt|dVha@k60e0&REC~+epvs#!} zUt_tE&i#Bz)X6c)5y@~#Qb}{j)yc9bV3H(~qLb~AZIfz|%qQb2OG1^kW~@Hq3i;KQ z;YcX9tcHZ>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/FreeRTOS-Plus/Source/WolfSSL/certs/test/crit-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/crit-cert.pem new file mode 100644 index 000000000..e2c370f54 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/crit-cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC7DCCApagAwIBAgIJAKBIQJVDXWL5MA0GCSqGSIb3DQEBBAUAMIHHMQswCQYD +VQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEm +MCQGA1UECgwdSm9obidzIFNvZnR3YXJlIFBsdW1iaW5nLCBMTEMxFDASBgNVBAsM +C0VuZ2luZWVyaW5nMSkwJwYDVQQDDCBlbmdpbmVlcmluZy5zb2Z0d2FyZXBsdW1i +aW5nLmJpejEoMCYGCSqGSIb3DQEJARYZam9obkBzb2Z0d2FyZXBsdW1iaW5nLmJp +ejAeFw0xNDAzMTMxNjUyMzRaFw0xNjEyMDcxNjUyMzRaMIHHMQswCQYDVQQGEwJV +UzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEmMCQGA1UE +CgwdSm9obidzIFNvZnR3YXJlIFBsdW1iaW5nLCBMTEMxFDASBgNVBAsMC0VuZ2lu +ZWVyaW5nMSkwJwYDVQQDDCBlbmdpbmVlcmluZy5zb2Z0d2FyZXBsdW1iaW5nLmJp +ejEoMCYGCSqGSIb3DQEJARYZam9obkBzb2Z0d2FyZXBsdW1iaW5nLmJpejBcMA0G +CSqGSIb3DQEBAQUAA0sAMEgCQQDicEBO1u+ysy7iakWAewKMYPKwzY6Oaq+FUopr +SIjgrX8JIV5gnnvT0HrV/Ju2t4sBy41rZc50cqOdOj9yZctRAgMBAAGjYzBhMB0G +A1UdDgQWBBQYkZqEi8LDLWrQZjw5usbSedJdAzAfBgNVHSMEGDAWgBQYkZqEi8LD +LWrQZjw5usbSedJdAzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIF4DAN +BgkqhkiG9w0BAQQFAANBAEU0nmhsV0h59xJIHESZPqGj7LYEoSnyZ8/vs+KBJmhm +A8XaCALu1m2CWCrW5wjqSGbbqQfy9vFqsnNX+Qt9KiU= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/crit-key.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/crit-key.pem new file mode 100644 index 000000000..893f07eb1 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/crit-key.pem @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOQIBAAJBAOJwQE7W77KzLuJqRYB7Aoxg8rDNjo5qr4VSimtIiOCtfwkhXmCe +e9PQetX8m7a3iwHLjWtlznRyo506P3Jly1ECAwEAAQJAG21BPMtn6Rsu+JmqpW9A +1cQAYU3kkHd3nwxqW6hDfAMNY8qZCkGsrBxSAgvIItQwytV7zn+F8FPDwViVz1xQ +gQIhAPWkmZGz7sRIuZB4JQiXzVJvUprsfgpg6ODfpWl+cabJAiEA6/xdEuMqbiY+ +g7xG1MMOe2zstDB+vvxT5pEQxGklXEkCIBo9qC4Zc6NCRZh6TTJ6zPNGcyObqec/ +7QDAw3HekROJAiBm+N7QIAniuJNsvloV+us11kjPM54KzmX55PDxE4R26QIgU5DH +iIm5DKbAJqgaXOXo35v/PUqYZmJUc2bPF158+vg= +-----END RSA PRIVATE KEY----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/dh1024.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/dh1024.der new file mode 100644 index 0000000000000000000000000000000000000000..1a3ff399f733d01722161352eee93f06dae5dcd6 GIT binary patch literal 138 zcmV;50CoQ`frkQtfdKAvrjx#@xL;DaoYbffjrp)sDXAp}4wc>YiO6dSu9O^NH3d1V zZAQhiqWz%Zx&fsCPk%(^bb*UHF8b>J_QMzv%Kh$(oSqFDT32^;W0B`kyKQ-s;Po5jROJ!0@7(i9smFU literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/dh1024.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/dh1024.pem new file mode 100644 index 000000000..82d14e766 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/dh1024.pem @@ -0,0 +1,17 @@ + DH Parameters: (1024 bit) + prime: + 00:ee:73:a6:93:be:a9:b8:5f:52:b9:9c:d4:a8:0f: + 8d:f9:b0:53:29:a9:25:06:0e:95:dd:f5:89:c8:6b: + 09:ae:94:1c:62:35:05:39:ab:6d:46:c5:b2:a2:fd: + a0:e1:ba:01:a5:00:4f:7f:44:e5:74:81:8b:3a:2e: + fa:ea:fe:f6:c3:18:11:ca:fd:ee:8b:9c:9e:0d:1a: + 5a:57:77:74:63:91:e7:51:bb:6d:79:93:e2:b4:5c: + fa:21:21:ff:5d:b3:e7:5c:92:08:ca:cb:4e:e7:8c: + f3:1c:21:8c:44:8c:6d:31:60:7a:e6:37:15:79:1b: + 1d:5d:c3:56:c3:a0:4a:8d:03 + generator: 2 (0x2) +-----BEGIN DH PARAMETERS----- +MIGHAoGBAO5zppO+qbhfUrmc1KgPjfmwUympJQYOld31ichrCa6UHGI1BTmrbUbF +sqL9oOG6AaUAT39E5XSBizou+ur+9sMYEcr97oucng0aWld3dGOR51G7bXmT4rRc ++iEh/12z51ySCMrLTueM8xwhjESMbTFgeuY3FXkbHV3DVsOgSo0DAgEC +-----END DH PARAMETERS----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/dh512.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/dh512.der new file mode 100644 index 0000000000000000000000000000000000000000..f743db4219b6080049fd58d208f515c65f32584c GIT binary patch literal 72 zcmV-O0Jr}zMglvy9j e>P-WL+1Ivew%t*eX2EynYwa14Ma3tx0s#V_tRchz literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/dh512.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/dh512.pem new file mode 100644 index 000000000..d1fef9243 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/dh512.pem @@ -0,0 +1,12 @@ + DH Parameters: (512 bit) + prime: + 00:87:76:23:99:e1:df:db:6a:43:8e:30:2b:4f:63: + 53:05:77:ce:80:02:8e:b1:a8:44:4f:30:d8:c9:45: + d9:cd:65:e3:4b:2d:b6:eb:77:a3:26:ea:4d:03:84: + d9:d7:b6:6a:b6:dd:51:97:66:c1:77:e6:6b:ed:19: + 91:45:c5:27:b3 + generator: 2 (0x2) +-----BEGIN DH PARAMETERS----- +MEYCQQCHdiOZ4d/bakOOMCtPY1MFd86AAo6xqERPMNjJRdnNZeNLLbbrd6Mm6k0D +hNnXtmq23VGXZsF35mvtGZFFxSezAgEC +-----END DH PARAMETERS----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/digsigku.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/digsigku.pem new file mode 100644 index 000000000..5086b7d7c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/digsigku.pem @@ -0,0 +1,57 @@ +Certificate: + Data: + Version: 3 (0x2) + 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: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 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 + 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=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:45:02:21:00:fb:11:b6:9b:9a:26:b0:36:ad:ad:5a:5e:34: + 75:58:3a:93:01:af:f7:b7:00:25:85:8b:0d:4b:35:6e:43:13: + ec:02:20:14:8b:f5:04:a0:99:75:91:cd:76:1b:6a:3e:14:fc: + 96:13:fe:dd:d1:82:4a:3a:83:2b:2f:f0:a6:a6:c5:a5:bb +-----BEGIN CERTIFICATE----- +MIIDKDCCAs+gAwIBAgIJAOOBS0ilcGFwMAkGByqGSM49BAEwgZExCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMREwDwYD +VQQKDAhGb29mYXJhaDEUMBIGA1UECwwLQXJnbGViYXJnbGUxEjAQBgNVBAMMCWZv +b2JhcmJhejEeMBwGCSqGSIb3DQEJARYPaW5mb0B3b3Jsc3MuY29tMB4XDTE4MDQx +MzE1MjMxMFoXDTIxMDEwNzE1MjMxMFowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMREwDwYDVQQKDAhGb29mYXJh +aDEUMBIGA1UECwwLQXJnbGViYXJnbGUxEjAQBgNVBAMMCWZvb2JhcmJhejEeMBwG +CSqGSIb3DQEJARYPaW5mb0B3b3Jsc3MuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D +AQcDQgAEuzOsTCdQSsZKpQTDPN6fNttyLc6U6iv6yyAJOSwW6GEC6a9N0wKTmjFb +l5Ihf/DPGNqREQI0huggWDMLgDSJ2KOCAQ0wggEJMB0GA1UdDgQWBBRdXSbvrH42 ++Zt2FStKJQIj77KJMDCBxgYDVR0jBIG+MIG7gBRdXSbvrH42+Zt2FStKJQIj77KJ +MKGBl6SBlDCBkTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAO +BgNVBAcMB1NlYXR0bGUxETAPBgNVBAoMCEZvb2ZhcmFoMRQwEgYDVQQLDAtBcmds +ZWJhcmdsZTESMBAGA1UEAwwJZm9vYmFyYmF6MR4wHAYJKoZIhvcNAQkBFg9pbmZv +QHdvcmxzcy5jb22CCQDjgUtIpXBhcDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIFYDAJBgcqhkjOPQQBA0gAMEUCIQD7EbabmiawNq2tWl40dVg6kwGv97cA +JYWLDUs1bkMT7AIgFIv1BKCZdZHNdhtqPhT8lhP+3dGCSjqDKy/wpqbFpbs= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-ca.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-ca.der new file mode 100644 index 0000000000000000000000000000000000000000..df9dd7508965942a5d8fc83c32ce8c1beebdc9ff GIT binary patch literal 857 zcmXqLVh%NEVzOmo5@0akW#iOp^Jx3d%gD&h%3x4nC}AMR#vIDR%)?(^UanW3pOaQx zoTHbVpKB;!zz34y;9>X8&nrpHOEly*-~@@V2{VNT8_FBV!p-7j6cfnIOUrja)-Pfp z1X9h-!|j@vo|%`LT9lcWZXhSYYh++(VPI}-XaEFJP_BhBh-VNr04{1`R6-6GMpg#q zCPsb+gC<5UrY1&4hW$LJbVWAFwKzqewUGDvd}wgNnz6O)AN@II8I&5 zHT&_>0~;uXw?sQ}cHDqN-jCO_?>v-+ro@x?yTlt!IqI*>ctQdmBoFr`Xt@ zN{*f{y7jWGu)gF)o7-hpXLi({e0u2mErk#JHFHrZWT? zrYrl+cpK;{yOZT6_nR9Uo4xnGHLGM|W@KPQ4k2K|0frDGL(uvb0gmQbmWNnljQ=cK zP;)NBmfdIMdaOQVo51;3;w4vZvgH-V@;VeLvR5i3Zx+3} z{h8FY3xZM!^^GrQXKqRNd!!_#KR3(f)>M;~`?W=W{ZlM{ep0elM`ZqdJRrzr8!Y?PwPM|0C?J2&=y*`%mL+ z`@hF(|7WvYb!#}7UGn#tgov#5F`;xmx!%SjE9XSM(>!}VblIL@;V*%Ewr>UiY3@aC literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-ca.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-ca.pem new file mode 100644 index 000000000..d4f6716c7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-ca.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN = www.wolfssl.com, ST = Montana, C = US, emailAddress = info@wolfssl.com, OU = Engineering + Validity + Not Before: Jul 31 00:00:00 2018 GMT + Not After : Aug 30 00:00:00 2018 GMT + Subject: CN = www.wolfssl.com, ST = Montana, C = US, emailAddress = info@wolfssl.com, OU = Engineering + 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) + Signature Algorithm: sha256WithRSAEncryption + 52:af:84:10:08:83:9a:39:c2:05:5c:33:fc:a6:a0:7c:ce:68: + 34:fa:cc:05:9f:8a:33:79:64:07:da:6c:17:85:91:ab:1d:be: + 32:45:c6:7f:54:b6:10:cf:ea:17:74:d4:d9:06:6e:71:5d:0d: + 40:72:21:07:79:20:63:b3:15:d5:b7:e6:1a:d6:d0:11:1a:60: + 7f:81:e9:9b:69:b4:67:4e:e2:22:1a:2f:9d:6a:3c:da:95:34: + a9:bf:2b:14:fa:fe:21:73:e7:c9:19:7d:2c:14:9f:9f:33:c1: + 83:35:9c:94:95:0e:e4:3e:29:17:95:a2:85:e3:ad:70:5f:6a: + ff:2d:8a:92:fb:58:f6:fe:46:2b:d0:e4:9d:9b:0d:d9:e4:39: + 0a:c5:e2:3d:17:de:95:cc:a4:1c:33:a1:75:02:ec:98:66:47: + b9:ce:e4:8f:7e:32:cd:38:ff:6f:3d:be:7a:44:bf:47:61:7a: + b7:5a:09:fa:1e:bf:3d:63:68:b3:15:00:87:fd:8d:b8:f6:b8: + 83:13:ff:f8:56:ed:14:05:4f:49:07:f9:33:6b:3f:fd:c6:7d: + ff:6b:04:d5:46:80:c1:6b:74:fd:e6:18:14:1d:3b:c6:12:67: + 0e:1e:8d:81:c4:a9:9c:59:ee:29:cd:cf:55:a6:bc:53:13:f4: + 51:bc:b7:b3 +-----BEGIN CERTIFICATE----- +MIIDVTCCAj0CAhAAMA0GCSqGSIb3DQEBCwUAMHAxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEQMA4GA1UECAwHTW9udGFuYTELMAkGA1UEBhMCVVMxHzAdBgkqhkiG +9w0BCQEWEGluZm9Ad29sZnNzbC5jb20xFDASBgNVBAsMC0VuZ2luZWVyaW5nMB4Y +DTIwMTgwNzMxMDAwMFoYDTIwMTgwODMwMDAwMFowcDEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMRAwDgYDVQQIDAdNb250YW5hMQswCQYDVQQGEwJVUzEfMB0GCSqG +SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTEUMBIGA1UECwwLRW5naW5lZXJpbmcw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/DMotFLIehEJbzTgfSvJN +dRDxtjWf38p9A5jTrN4DZu4q8diwfW4HVAsQmCFNgMsSIOfMT95FfclydzLqypC7 +aVIQAy+o85XF8YtiVhvvZ2+kEEGVrQqb46XAsNJwdlAwW6joCCx87aeieo04KRys +x+3yfJWwlYJ9SVw4zXcl772AdVOUPD3KY1ufFbXTHRMvGdE823Y6zLh9yeXC19pA +b9gh3HMbQi1TnP4a/H2rejY/mN6EfAVnzmoUOIep8Yy1aMtof3EgK/WgY/VWL6Mm +0rdvsVoX1ziZCP6TWG/+wxNJCBYLp01nAFIxZyNOmO1RRR25BNkL7Ngos0u97TZ5 +AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFKvhBAIg5o5wgVcM/ymoHzOaDT6zAWf +ijN5ZAfabBeFkasdvjJFxn9UthDP6hd01NkGbnFdDUByIQd5IGOzFdW35hrW0BEa +YH+B6ZtptGdO4iIaL51qPNqVNKm/KxT6/iFz58kZfSwUn58zwYM1nJSVDuQ+KReV +ooXjrXBfav8tipL7WPb+RivQ5J2bDdnkOQrF4j0X3pXMpBwzoXUC7JhmR7nO5I9+ +Ms04/289vnpEv0dherdaCfoevz1jaLMVAIf9jbj2uIMT//hW7RQFT0kH+TNrP/3G +ff9rBNVGgMFrdP3mGBQdO8YSZw4ejYHEqZxZ7inNz1WmvFMT9FG8t7M= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-cert.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-cert.der new file mode 100644 index 0000000000000000000000000000000000000000..32a1c4a43105f07efa5563332a00a769d547cfa7 GIT binary patch literal 857 zcmXqLVh%NEVzOmo5@0akW#iOp^Jx3d%gD&h%3x4nC}AMR#vIDR%)?(^UanW3pOaQx zoTHbVpKB;!zz34y;9>X8&nrpHOEly*-~@@V2{VNT8_FBV!p-7j6cfnIOUrja)-Pfp z1X9h-!|j@vo|%`LT9lcWZXhSYYh++(VPI}-XaEFJP_BhBh-VNr04{1`R6-6GMpg#q zCPsb+gC<5UrY1&4h67VM9)>%9D$Lz}$<sd-#mjmmRx;(TKP<_pw?p9Zu`>=^ zG8elUXSU}Z*)6{8^NYJ{i}zIPD{lRp7Ra+VWb?z^c$q!Q#TPl5J4G%D>`XbVbz$K& zuRRa1NJSrCaNuBa1;2~Afzh-EBju?J%XbN1nqK@UR`p~S?_tY?C0jORIyrH^yuq=@ zSYdO7((+ZWk34*q*nITTwEH(N_^-Xr#LURRh#W$|gaZsAMh4p*FYhq>^Hjc#-TK0H z=9YQ?X5Z{sm2*$dB(lp}#*(LML9NQc-jGYFldeRYp1$|T{NKiOg%lR9e$K-4m&Nq% zD4(d&D>4mvb2&L`Zt`TOZAIz*4b54PFR#^Tck{^$yTr6ULT@GC1NLPfBkqbfsekme z?kUgbn0Axp#2XW(r5j&*ushnUl6!KqRJw4l|C_kK+AeyHXL~ksJi9mhQR2yW&fnM1 z)ch5YsWroWXM|h0oUUehU}ws^PrF2Zf8TW{p zp6cRX6574$|5-db;?QAb;6y(Zr=us}q{p?$zzzc0ypah1BIk07aHg A&;S4c literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-cert.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-cert.pem new file mode 100644 index 000000000..cc21c2b53 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/expired/expired-cert.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN = www.wolfssl.com, ST = Montana, C = US, emailAddress = info@wolfssl.com, OU = Engineering + Validity + Not Before: Jul 31 00:00:00 2018 GMT + Not After : Aug 30 00:00:00 2018 GMT + Subject: CN = www.wolfssl.com, ST = Montana, C = US, emailAddress = info@wolfssl.com, OU = Engineering + 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) + Signature Algorithm: sha256WithRSAEncryption + 3d:b8:e9:dc:03:4f:0c:79:ed:5d:b5:e8:45:99:b4:9e:fe:9b: + d9:88:aa:6c:de:1e:34:59:8a:4b:1c:39:0c:7a:a0:7d:24:c1: + 8d:54:d2:65:92:d4:5b:35:cb:de:fc:37:fe:b1:67:20:64:04: + 0a:8f:09:71:cf:d3:16:2e:dc:23:c8:7c:2e:72:35:54:ec:d3: + 63:5a:9d:63:93:42:b6:72:67:8f:80:83:6a:e3:d3:ad:28:87: + 46:4c:6e:56:d2:02:af:58:2e:a9:0e:e0:07:a6:f1:58:dd:17: + 82:27:f1:49:3b:8c:77:6f:08:96:d9:04:c8:ec:34:22:a5:b1: + e9:48:07:41:3c:aa:1e:e4:d9:75:1b:71:bd:4f:ec:5e:fd:2b: + 44:2e:81:cd:8c:b1:08:e6:de:9b:e2:61:c9:ee:43:f7:af:99: + 29:fa:50:69:2a:98:47:b9:58:46:57:1e:2d:29:77:51:89:64: + ee:f2:ba:14:fb:f7:ba:dc:68:d6:34:bc:28:eb:17:f4:37:6a: + 91:a9:cf:d5:46:e8:6e:8f:2f:e7:f2:e0:b1:ca:8a:0f:a4:55: + 8b:b9:c2:89:d0:29:82:b7:11:47:af:8b:96:92:e5:a3:da:11: + 0f:76:db:15:61:a5:5a:ab:60:83:06:de:7e:bf:b6:c8:10:ab: + 38:1a:d3:c2 +-----BEGIN CERTIFICATE----- +MIIDVTCCAj0CAhAAMA0GCSqGSIb3DQEBCwUAMHAxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEQMA4GA1UECAwHTW9udGFuYTELMAkGA1UEBhMCVVMxHzAdBgkqhkiG +9w0BCQEWEGluZm9Ad29sZnNzbC5jb20xFDASBgNVBAsMC0VuZ2luZWVyaW5nMB4Y +DTIwMTgwNzMxMDAwMFoYDTIwMTgwODMwMDAwMFowcDEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMRAwDgYDVQQIDAdNb250YW5hMQswCQYDVQQGEwJVUzEfMB0GCSqG +SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTEUMBIGA1UECwwLRW5naW5lZXJpbmcw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAlQjhV0HycW230kVBJwFl +xkWu8rwkMLiVzi9O1vYciLx8n/uoZ3/+XJxRdfeKygfnNS+P4b17wC98q2SoF/zK +XXu64CHlci5vLobYlXParBtTuV8/1xkNJU/hY2NRiwtkP61DuKUcXDSzrgCgY8X2 +fwtZaHhzpowYqQJtr8MZAS64EOPGzEC0aaNGM2mHbsS7F6bz6N2tc7x7LyG1/WZR +DL1Us+FtXxy8I3PRCQOJFNIQuWTDKtChlkq84dQaW8egwMFjeA9ENzAyloAyI5Wh +d7oT0pdz4l0lyWoNwzlgpLSwaUJCCenYCLwzILNYIqeq68Th5mGDxdKW39nQT63X +AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAD246dwDTwx57V216EWZtJ7+m9mIqmze +HjRZikscOQx6oH0kwY1U0mWS1Fs1y978N/6xZyBkBAqPCXHP0xYu3CPIfC5yNVTs +02NanWOTQrZyZ4+Ag2rj060oh0ZMblbSAq9YLqkO4Aem8VjdF4In8Uk7jHdvCJbZ +BMjsNCKlselIB0E8qh7k2XUbcb1P7F79K0Qugc2MsQjm3pviYcnuQ/evmSn6UGkq +mEe5WEZXHi0pd1GJZO7yuhT797rcaNY0vCjrF/Q3apGpz9VG6G6PL+fy4LHKig+k +VYu5wonQKYK3EUevi5aS5aPaEQ922xVhpVqrYIMG3n6/tsgQqzga08I= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/gen-ext-certs.sh b/FreeRTOS-Plus/Source/WolfSSL/certs/test/gen-ext-certs.sh new file mode 100644 index 000000000..10b887133 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/gen-ext-certs.sh @@ -0,0 +1,98 @@ +#!/bin/sh + +TMP="/tmp/`basename $0`" + +gen_cert() { + openssl req -x509 -keyform DER -key certs/server-key.der \ + -days 1000 -new -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 <$CONFIG < "$1".conf + echo "" >> "$1".conf + echo "[ ca ]" >> "$1".conf + echo "default_ca = CA_default" >> "$1".conf + echo "[ CA_default ]" >> "$1".conf + echo "certificate = ../ca-cert.pem" >> "$1".conf + echo "database = ./index.txt" >> "$1".conf + echo "new_certs_dir = ./certs" >> "$1".conf + echo "private_key = ./private/cakey.pem" >> "$1".conf + echo "serial = ./serial" >> "$1".conf + echo "default_md = sha256" >> "$1".conf + echo "default_days = 1000" >> "$1".conf + echo "policy = default_ca_policy" >> "$1".conf + echo "" >> "$1".conf + echo "[ default_ca_policy ]" >> "$1".conf + echo "commonName = supplied" >> "$1".conf + echo "stateOrProvinceName = supplied" >> "$1".conf + echo "countryName = supplied" >> "$1".conf + echo "emailAddress = supplied" >> "$1".conf + echo "organizationName = optional" >> "$1".conf + echo "organizationalUnitName = optional" >> "$1".conf + echo "" >> "$1".conf + echo "[ req ]" >> "$1".conf + echo "prompt = no" >> "$1".conf + echo "default_bits = 2048" >> "$1".conf + echo "distinguished_name = req_distinguished_name" >> "$1".conf + if [ -n "$3" ]; then + echo "req_extensions = req_ext" >> "$1".conf + fi + if [ -n "$4" ]; then + echo "basicConstraints=CA:true,pathlen:0" >> "$1".conf + echo "" >> "$1".conf + fi + echo "" >> "$1".conf + echo "[ req_distinguished_name ]" >> "$1".conf + echo "C = US" >> "$1".conf + echo "ST = Montana" >> "$1".conf + echo "L = Bozeman" >> "$1".conf + echo "OU = Engineering" >> "$1".conf + echo "CN = $2" >> "$1".conf + echo "emailAddress = info@wolfssl.com" >> "$1".conf + echo "" >> "$1".conf + if [ -n "$3" ]; then + echo "[ req_ext ]" >> "$1".conf + if [ "$3" != *"DER"* ]; then + echo "subjectAltName = @alt_names" >> "$1".conf + echo "[alt_names]" >> "$1".conf + echo "DNS.1 = $3" >> "$1".conf + else + echo "subjectAltName = $3" >> "$1".conf + fi + fi +} + +# Args: 1=FileName +generate_test_cert() { + rm "$1".der + rm "$1".pem + + echo "step 1 create configuration" + build_test_cert_conf "$1" "$2" "$3" + check_result $? + + echo "step 2 create csr" + openssl req -new -sha256 -out "$1".csr -key ../server-key.pem -config "$1".conf + check_result $? + + echo "step 3 check csr" + openssl req -text -noout -in "$1".csr -config "$1".conf + check_result $? + + echo "step 4 create cert" + if [ "$3" = "" ]; then + openssl x509 -req -days 1000 -sha256 \ + -in "$1".csr -signkey ../server-key.pem \ + -out "$1".pem -extfile "$1".conf + else + openssl x509 -req -days 1000 -sha256 \ + -in "$1".csr -signkey ../server-key.pem \ + -out "$1".pem -extensions req_ext -extfile "$1".conf + fi + check_result $? + rm "$1".conf + rm "$1".csr + + if [ -n "$4" ]; then + echo "step 5 generate crl" + mkdir ../crl/demoCA + touch ../crl/demoCA/index.txt + touch ../crl/demoCA/index.txt.attr + echo "01" > ../crl/crlnumber + openssl ca -config ../renewcerts/wolfssl.cnf -gencrl -crldays 1000 \ + -out crl.revoked -keyfile ../server-key.pem -cert "$1".pem + check_result $? + rm ../crl/"$1"Crl.pem + openssl crl -in crl.revoked -text > tmp.pem + check_result $? + mv tmp.pem ../crl/"$1"Crl.pem + rm crl.revoked + rm -rf ../crl/demoCA #cleans up index.txt and index.txt.attr + rm ../crl/crlnumber* + fi + + echo "step 6 add cert text information to pem" + openssl x509 -inform pem -in "$1".pem -text > tmp.pem + check_result $? + mv tmp.pem "$1".pem + + echo "step 7 make binary der version" + openssl x509 -inform pem -in "$1".pem -outform der -out "$1".der + check_result $? +} + +generate_expired_certs() { + rm "$1".der + rm "$1".pem + + mkdir -p certs + touch ./index.txt + touch ./index.txt.attr + echo 1000 > ./serial + + echo "step 1 create configuration" + build_test_cert_conf "$1" www.wolfssl.com 0 "$3" + check_result $? + + echo "step 2 create csr" + openssl req -new -sha256 -out "$1".csr -key "$2" -config "$1".conf + check_result $? + + echo "step 3 check csr" + openssl req -text -noout -in "$1".csr -config "$1".conf + check_result $? + + echo "step 4 create cert" + openssl ca -config ../renewcerts/wolfssl.cnf -selfsign -config "$1".conf \ + -keyfile "$2" -in "$1".csr -out "$1".pem \ + -startdate 20180731000000Z -enddate 20180830000000Z -batch + check_result $? + rm "$1".conf + rm "$1".csr + + echo "step 5 add cert text information to pem" + openssl x509 -inform pem -in "$1".pem -text > tmp.pem + check_result $? + mv tmp.pem "$1".pem + + echo "step 7 make binary der version" + openssl x509 -inform pem -in "$1".pem -outform der -out "$1".der + check_result $? + + rm -rf certs + rm ./index.txt* + rm ./serial* +} + +# Generate Good CN=localhost, Alt=None +generate_test_cert server-goodcn localhost "" 1 + +# Generate Good CN=www.nomatch.com, Alt=localhost +generate_test_cert server-goodalt www.nomatch.com localhost 1 + +# Generate Good CN=*localhost, Alt=None +# Surround "*localhost" with quotes to prevent shell expansion to wildcard +generate_test_cert server-goodcnwild "*localhost" "" 1 + +# Generate Good CN=www.nomatch.com, Alt=*localhost +# Surround "*localhost" with quotes to prevent shell expansion to wildcard +generate_test_cert server-goodaltwild www.nomatch.com "*localhost" 1 + +# Generate Bad CN=localhost\0h, Alt=None +# DG: Have not found a way to properly encode null in common name +generate_test_cert server-badcnnull DER:30:0d:82:0b:6c:6f:63:61:6c:68:6f:73:74:00:68 + +# Generate Bad Name CN=www.nomatch.com, Alt=None +generate_test_cert server-badcn www.nomatch.com + +# Generate Bad Alt CN=www.nomatch.com, Alt=localhost\0h +generate_test_cert server-badaltnull www.nomatch.com DER:30:0d:82:0b:6c:6f:63:61:6c:68:6f:73:74:00:68 + +# Generate Bad Alt Name CN=www.nomatch.com, Alt=www.nomatch.com +generate_test_cert server-badaltname www.nomatch.com www.nomatch.com + +# Generate Good Alt Name CN=localhost, Alt=localhost +generate_test_cert server-localhost localhost localhost + +# Generate Bad Alt Name CN=localhost, Alt=garbage +generate_test_cert server-garbage localhost garbage + + +# Generate Expired Certificates +generate_expired_certs expired/expired-ca ../ca-key.pem 1 +generate_expired_certs expired/expired-cert ../server-key.pem diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/include.am b/FreeRTOS-Plus/Source/WolfSSL/certs/test/include.am new file mode 100644 index 000000000..6f37df6d2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/include.am @@ -0,0 +1,64 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + certs/test/cert-ext-ia.cfg \ + certs/test/cert-ext-ia.der \ + certs/test/cert-ext-nc.cfg \ + certs/test/cert-ext-nc.der \ + certs/test/cert-ext-nct.cfg \ + certs/test/cert-ext-nct.der \ + certs/test/cert-ext-ns.der \ + certs/test/gen-ext-certs.sh \ + certs/test/server-duplicate-policy.pem \ + certs/test/cert-ext-joi.pem + +# The certs/server-cert with the last byte (signature byte) changed +EXTRA_DIST += \ + certs/test/server-cert-rsa-badsig.der \ + certs/test/server-cert-rsa-badsig.pem \ + certs/test/server-cert-ecc-badsig.der \ + certs/test/server-cert-ecc-badsig.pem + +EXTRA_DIST += \ + certs/test/gen-testcerts.sh \ + certs/test/server-garbage.der \ + certs/test/server-garbage.pem \ + certs/test/server-goodcn.pem \ + certs/test/server-goodcn.der \ + certs/test/server-goodalt.pem \ + certs/test/server-goodalt.der \ + certs/test/server-goodcnwild.pem \ + certs/test/server-goodcnwild.der \ + certs/test/server-goodaltwild.pem \ + certs/test/server-goodaltwild.der \ + certs/test/server-badcnnull.pem \ + certs/test/server-badcnnull.der \ + certs/test/server-badcn.pem \ + certs/test/server-badcn.der \ + certs/test/server-badaltnull.pem \ + certs/test/server-badaltnull.der \ + certs/test/server-badaltname.der \ + certs/test/server-badaltname.pem \ + certs/test/server-localhost.der \ + certs/test/server-localhost.pem \ + certs/crl/server-goodaltCrl.pem \ + certs/crl/server-goodcnCrl.pem \ + certs/crl/server-goodaltwildCrl.pem \ + certs/crl/server-goodcnwildCrl.pem + +EXTRA_DIST += \ + certs/test/crit-cert.pem \ + certs/test/crit-key.pem \ + certs/test/dh1024.der \ + certs/test/dh1024.pem \ + certs/test/dh512.der \ + certs/test/dh512.pem \ + certs/test/digsigku.pem + +EXTRA_DIST += \ + certs/test/expired/expired-ca.pem \ + certs/test/expired/expired-ca.der \ + certs/test/expired/expired-cert.pem \ + certs/test/expired/expired-cert.der diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badaltname.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badaltname.der new file mode 100644 index 0000000000000000000000000000000000000000..998b44a6046d652b4ea60c3c0597b2121c4e9fef GIT binary patch literal 939 zcmXqLVqR|0#MHllnTe5!iIZW|#@KYZz4oUKc-c6$+C196^D;7WvoaVoHW_joaI!In zvaks=g$5f681R8O96ap4`FSOYd5JI)b{=-8{HoO4#5_Y010j$aZXRyey!6bx)YPKP zymUhe12K>&GY@}xdAVL*er{q(a)w@Vey*Xsfh^ooPDU|-%)GRGhw}WKwBq6%kOBia zab80U14~0oBSRoGi4x~EGBhwVG=*{pha;O9m5>9Ek(GhDiIJbdpox)-sfm%1;lNam zhvAN&3Ujw#a&=T^Og-kh?$aI>gB?@P>HA&#CeyK}X8!LL>Gl6&<^-00?>fc)+*H5+ z;oj;4`ZcRlR*3&O6#x^f|7uP&? zxccx-&y<9Zle+|Vuei&T)0xrp>2dJl2*v2y)tf%mNU`$=()A04Z)xYH4$nz`zVjPZ?G>zb!V zO66Zuf5Kd)nkL3ntNr_bUz4=I&b3pCVjQbn_*a!#7qu(iT@h>X=Qy*C7gs}-9{{nr BTu=Z2 literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badaltname.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badaltname.pem new file mode 100644 index 000000000..849e6600b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badaltname.pem @@ -0,0 +1,75 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + b2:b1:5d:67:1e:bd:3f:cb + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com + Validity + Not Before: Sep 19 21:21:24 2018 GMT + Not After : Jun 15 21:21:24 2021 GMT + Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.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 Alternative Name: + DNS:www.nomatch.com + Signature Algorithm: sha256WithRSAEncryption + b3:a6:46:25:12:aa:40:b8:db:4e:7f:c5:06:ae:76:51:67:cc: + a1:58:bf:47:37:1f:59:99:e8:3e:2d:c8:38:84:19:18:f5:c1: + d3:2d:c5:82:11:e7:94:c4:0f:f1:d1:e6:30:d2:9a:20:07:33: + 3c:e9:8d:a3:7c:e3:40:d5:e1:ec:8c:94:60:f1:93:8a:10:bb: + a8:dd:0c:6c:89:68:8c:f2:e3:53:a3:58:21:5b:7d:ab:b2:f2: + 7c:1a:06:8f:2d:fd:89:75:1f:9f:92:24:9b:f9:1e:a0:dd:01: + 08:a4:2c:58:40:29:c6:b9:46:42:66:4f:d6:21:db:42:24:47: + 1b:74:94:99:d2:14:84:5b:75:49:03:92:f3:51:7b:c5:53:68: + 04:98:a6:0c:08:86:91:28:c8:d4:86:5f:3d:0e:05:54:bd:05: + a6:99:2e:94:c9:db:e0:5e:19:94:6d:4a:a2:81:73:e7:d3:8f: + e4:ec:f3:fe:22:26:ae:8a:86:01:e2:c6:7c:38:dc:88:54:25: + 69:aa:d4:1c:33:d8:9a:ae:83:95:59:1a:6f:d6:27:e4:03:7a: + 25:66:16:02:7d:2b:fb:ff:8e:82:1b:4f:2c:d6:ca:61:16:08: + aa:44:0f:aa:76:3b:72:87:21:dd:a8:5d:38:fc:c7:03:3c:4a: + 0a:80:7a:4e +-----BEGIN CERTIFICATE----- +MIIDpzCCAo+gAwIBAgIJALKxXWcevT/LMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIG +A1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMMD3d3dy5ub21hdGNoLmNvbTEfMB0G +CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0xODA5MTkyMTIxMjRaFw0y +MTA2MTUyMTIxMjRaMIGCMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQ +MA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMM +D3d3dy5ub21hdGNoLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEn +AWXGRa7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX +/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBj +xfZ/C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9 +ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIj +laF3uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBP +rdcCAwEAAaMeMBwwGgYDVR0RBBMwEYIPd3d3Lm5vbWF0Y2guY29tMA0GCSqGSIb3 +DQEBCwUAA4IBAQCzpkYlEqpAuNtOf8UGrnZRZ8yhWL9HNx9Zmeg+Lcg4hBkY9cHT +LcWCEeeUxA/x0eYw0pogBzM86Y2jfONA1eHsjJRg8ZOKELuo3QxsiWiM8uNTo1gh +W32rsvJ8GgaPLf2JdR+fkiSb+R6g3QEIpCxYQCnGuUZCZk/WIdtCJEcbdJSZ0hSE +W3VJA5LzUXvFU2gEmKYMCIaRKMjUhl89DgVUvQWmmS6UydvgXhmUbUqigXPn04/k +7PP+IiauioYB4sZ8ONyIVCVpqtQcM9iaroOVWRpv1ifkA3olZhYCfSv7/46CG08s +1sphFgiqRA+qdjtyhyHdqF04/McDPEoKgHpO +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badaltnull.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badaltnull.der new file mode 100644 index 0000000000000000000000000000000000000000..551c1dbe29df09405552ebfac883ec277a5e928e GIT binary patch literal 972 zcmXqLVm@Ke#I#`nGZP~d6DPw2CONw)%x&rhylk9WZ60mkc^MhGSs4r(n+&-PIN6v( zS=fY`LW2zj4ER7C4jy*j{JfIHyhNA?I}f{4epPC2VxFOhfe=UyHxIXKUV3I;YHCqt zUb>-#ffz`XnTNl;yj(9YKR2-?IYTcwKi5#+Ko)K(C!?4^W?ovpLwSBqT5)j>NP&Tz zIIp3Ffu*6Pks%P8M2Yhn85)=wnnJmQ!;wvlO2~o7$jZRn#K_NJ(8S2a)Wpcha9}FO z!*It>g}K`=xjL#drXF)$_i2xc!H%it^!=`Vlj+z~GynIB^!k4>a{^1hcb#H?ZmQq^ zaBuYi{hHM&E5!etiml%DK=EmjUcO%2jj6@A)<_5MjJLlo$*b!BFgZD}n>)pRt@Dnh zGBGBb*D)+eKKiYmJ2Io9cv+9cN~YZPhb0;Hb_hH^cE({#=3+PF%=Ww^yTzA%esOng z@t$gZ#jStS0(tg^Y<`#C%u7uy@y8dw9#nj2f0n^+kbSeaQM2Qe^x0)v>5q275y*X~DpH$UEQ&g~3N-H@5XU|_mg z#m3Gdp=Q&&GY@}xdAVL*er{q(a)w@Vey*Xsfh^ooPDU|-%)GRGhw}WKwBq6%kOBia zab80U14~0oBSRoGi4x~EGBhwVG=*{pha;O9m5>9Ek(GhDiIJbdpox)-sfm%1;lNam zhvAN&3Ujw#a&=T^Og-kh?$aI>gB?@P>HA&#CeyK}X8!LL>Gl6&<^-00?>fc)+*H5+ z;oj;4`ZcRlR*3&O6zO+k-_`&x&uOH>pusd3f<6my;k3>3rB9%XxOsWd|##2Pdu^koc&$ lMJdTP{HI%rF4}ZbK`Sr008_|L;oxES&Ce@I%u9rcu=B7x*=DP0F9uzyIOh>I3>Ut5a5p|2Y*~z3YME(;~fm zy|x=ui*K!w4&E7We_fJS)&F5~a$q-iiv3#W9ZO|mOg67$Sde`5TRnGVMn&ca9}!k4BOKZ;d7nZ@il@9HF#))$1bo22J^vn}QFC_OgO;S6-#F-TxurYJB=j^ZSU-y125av6cS$nEtc1!+- z<0n0C=^fW|kq{L>r=0w2-R@hwMZccSyvndURKB|S)>^aY&bJkso;I(n_x$u&tylTg ztp&4We`N`+IQfFHz1wnv-OsI`%-*)ggywE{Fo`_PlE-%JgSTOzYQXVD@e6iw<^L9D ze6J|6K4q@uj*YYVdrgGYoEHT8HmU!Ryz@u%nr58R&M&u~AJCHFsk+I3nqz^Z1GE2W O76q*@5BARf6$}6}-(=kY literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badcnnull.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badcnnull.pem new file mode 100644 index 000000000..41f31480a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-badcnnull.pem @@ -0,0 +1,73 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + c8:aa:6e:e3:4e:bf:ed:34 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = DER:30:0d:82:0b:6c:6f:63:61:6c:68:6f:73:74:00:68, emailAddress = info@wolfssl.com + Validity + Not Before: Sep 19 21:21:24 2018 GMT + Not After : Jun 15 21:21:24 2021 GMT + Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = DER:30:0d:82:0b:6c:6f:63:61:6c:68:6f:73:74:00:68, 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) + Signature Algorithm: sha256WithRSAEncryption + 59:58:d4:6f:58:56:b5:a8:93:1c:32:3c:be:f1:e2:e8:93:c9: + 64:69:b3:8e:87:66:20:62:27:23:ff:3a:99:73:4b:56:27:27: + 9f:2a:17:56:d9:6d:01:a1:f5:e7:50:aa:ff:23:fb:4e:3d:35: + fe:60:d4:ba:fd:01:1a:5b:99:c8:72:e8:19:bc:82:92:26:c8: + 02:09:6a:5b:50:b1:69:ab:49:9b:f5:07:f5:bd:f1:70:13:0e: + c7:69:7d:ca:78:9b:84:6f:b0:c7:c9:48:da:2e:c7:2e:44:18: + 15:17:ce:23:63:fa:ae:bb:da:0d:72:fa:e6:99:d5:00:bb:55: + 1f:7b:73:da:ad:36:e7:43:db:20:82:e5:83:a9:7f:49:f2:e3: + 26:8d:23:ea:da:a0:9a:1d:fa:6a:12:a8:c9:e8:01:87:8b:39: + 90:3e:f9:b5:f2:36:ed:87:5c:55:6d:b7:40:34:59:cb:04:6e: + 06:c6:f0:4b:31:51:25:50:c7:a2:5f:a0:ba:0a:6f:fb:13:01: + ef:21:18:af:64:9d:39:b8:b1:9b:0f:8d:34:12:26:43:a0:51: + 4d:82:27:f8:19:dc:fc:29:d6:29:5e:22:b9:f4:da:e7:c0:2a: + 1c:0c:7a:d9:0f:cb:08:a0:41:40:03:4f:cb:04:20:2a:f4:e0: + bd:9b:fa:53 +-----BEGIN CERTIFICATE----- +MIIDyTCCArGgAwIBAgIJAMiqbuNOv+00MA0GCSqGSIb3DQEBCwUAMIGjMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIG +A1UECwwLRW5naW5lZXJpbmcxOTA3BgNVBAMMMERFUjozMDowZDo4MjowYjo2Yzo2 +Zjo2Mzo2MTo2Yzo2ODo2Zjo3Mzo3NDowMDo2ODEfMB0GCSqGSIb3DQEJARYQaW5m +b0B3b2xmc3NsLmNvbTAeFw0xODA5MTkyMTIxMjRaFw0yMTA2MTUyMTIxMjRaMIGj +MQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1h +bjEUMBIGA1UECwwLRW5naW5lZXJpbmcxOTA3BgNVBAMMMERFUjozMDowZDo4Mjow +Yjo2Yzo2Zjo2Mzo2MTo2Yzo2ODo2Zjo3Mzo3NDowMDo2ODEfMB0GCSqGSIb3DQEJ +ARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAMCVCOFXQfJxbbfSRUEnAWXGRa7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF1 +94rKB+c1L4/hvXvAL3yrZKgX/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+Fj +Y1GLC2Q/rUO4pRxcNLOuAKBjxfZ/C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0Yz +aYduxLsXpvPo3a1zvHsvIbX9ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh +1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMg +s1gip6rrxOHmYYPF0pbf2dBPrdcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAWVjU +b1hWtaiTHDI8vvHi6JPJZGmzjodmIGInI/86mXNLVicnnyoXVtltAaH151Cq/yP7 +Tj01/mDUuv0BGluZyHLoGbyCkibIAglqW1CxaatJm/UH9b3xcBMOx2l9ynibhG+w +x8lI2i7HLkQYFRfOI2P6rrvaDXL65pnVALtVH3tz2q0250PbIILlg6l/SfLjJo0j +6tqgmh36ahKoyegBh4s5kD75tfI27YdcVW23QDRZywRuBsbwSzFRJVDHol+gugpv ++xMB7yEYr2SdObixmw+NNBImQ6BRTYIn+Bnc/CnWKV4iufTa58AqHAx62Q/LCKBB +QANPywQgKvTgvZv6Uw== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-cert-ecc-badsig.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-cert-ecc-badsig.der new file mode 100644 index 0000000000000000000000000000000000000000..8defd007914897484d335ff870c4b77c6273bd0e GIT binary patch literal 852 zcmXqLVh%89V*0v(nTe5!iAjLLfQyYotIgw_EekV~LF05oZUas>=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&7;v-}HxGMoX+c4L zQ3)kZZemnI4qQf72IeM4eg=akMlPl%Mn;AMQ#l@nJANw6-G0f{QJpdMnCrSvdsGZ| zOg*RXckP=@$DW$`zgMK!|BIOuSo*!|6#H{i{r-o0s}JbctWH@W{^wL|^{xksPmA>O z_1bPsExxrzI(TQi{dGxRRsV;{$${P6DfVlfcPy2OG15l{hJoZvo~b(!`yh8J<7!w zIhi{}E(z>RIjnVI;WV#353fi?A760bU~&b&i@AZ(v<4&PsSC?@316CC{3urSWESsX z%Y-FcHe@MFJZR9kuR%n;FI}+Yu$rv> zTjS)-OK!*-JbiI>VdJbNjnfBd@@?W|X#4-QPvG8;-v&G&uL!fS8Za|5{zpzAz}yE+ zAdC!KLK4<4U^cqPRIljOcrB^6 zh_>$LK7MB9vhIiN8ziN8G$Qh62GzaYV3lFr!^Kfjw0bA!(YGvh`P?#`iWkn-|2z_> zuJEL_IEeMqt{+$X9nUE13FYoFobfz)ai7}R7up@~9{sZ_2{PgPEA%ujGeE)6S8K%z1uZ8vqO5t2+Py literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-cert-rsa-badsig.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-cert-rsa-badsig.pem new file mode 100644 index 000000000..addafbad3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-cert-rsa-badsig.pem @@ -0,0 +1,172 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + 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: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=wolfSSL, OU=Support, 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + b4:54:60:ad:a0:03:32:de:02:7f:21:4a:81:c6:ed:cd:cd:d8: + 12:8a:c0:ba:82:5b:75:ad:54:e3:7c:80:6a:ac:2e:6c:20:4e: + be:4d:82:a7:47:13:5c:f4:c6:6a:2b:10:99:58:de:ab:6b:7c: + 22:05:c1:83:9d:cb:ff:3c:e4:2d:57:6a:a6:96:df:d3:c1:68: + e3:d2:c6:83:4b:97:e2:c6:32:0e:be:c4:03:b9:07:8a:5b:b8: + 84:ba:c5:39:3f:1c:58:a7:55:d7:f0:9b:e8:d2:45:b9:e3:83: + 2e:ee:b6:71:56:b9:3a:ee:3f:27:d8:77:e8:fb:44:48:65:27: + 47:4c:fb:fe:72:c3:ac:05:7b:1d:cb:eb:5e:65:9a:ab:02:e4: + 88:5b:3b:8b:0b:c7:cc:a9:a6:8b:e1:87:b0:19:1a:0c:28:58: + 6f:99:52:7e:ed:b0:3a:68:3b:8c:0a:08:74:72:ab:b9:09:c5: + ed:04:7e:6f:0b:1c:09:21:d0:cd:7f:f9:c4:5e:27:20:e4:85: + 73:52:05:d2:ba:f8:d5:8f:41:cc:23:2e:12:6d:bc:31:98:e7: + 63:a3:8e:26:cd:e8:2b:88:ee:e2:fe:3a:74:52:34:0e:fd:12: + e5:5e:69:50:20:31:34:e4:31:f1:e7:e4:5b:03:13:da:ac:41: + 6c:e7:cf:2b +-----BEGIN CERTIFICATE----- +MIIEnjCCA4agAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgwNDEz +MTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBkDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM +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 +AQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1jhDeuPswDAYDVR0TBAUwAwEB/zAN +BgkqhkiG9w0BAQsFAAOCAQEAtFRgraADMt4CfyFKgcbtzc3YEorAuoJbda1U43yA +aqwubCBOvk2Cp0cTXPTGaisQmVjeq2t8IgXBg53L/zzkLVdqppbf08Fo49LGg0uX +4sYyDr7EA7kHilu4hLrFOT8cWKdV1/Cb6NJFueODLu62cVa5Ou4/J9h36PtESGUn +R0z7/nLDrAV7HcvrXmWaqwLkiFs7iwvHzKmmi+GHsBkaDChYb5lSfu2wOmg7jAoI +dHKruQnF7QR+bwscCSHQzX/5xF4nIOSFc1IF0rr41Y9BzCMuEm28MZjnY6OOJs3o +K4ju4v46dFI0Dv0S5V5pUCAxNOQx8efkWwMT2qxBbOfPKw== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 9727763710660753659 (0x86fff58e10deb8fb) + 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: Apr 13 15:23:09 2018 GMT + Not After : Jan 7 15:23:09 2021 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 9e:28:88:72:00:ca:e6:e7:97:ca:c1:f1:1f:9e:12:b2:b8:c7: + 51:ea:28:e1:36:b5:2d:e6:2f:08:23:cb:a9:4a:87:25:c6:5d: + 89:45:ea:f5:00:98:ac:76:fb:1b:af:f0:ce:64:9e:da:08:bf: + b6:eb:b4:b5:0c:a0:e7:f6:47:59:1c:61:cf:2e:0e:58:a4:82: + ac:0f:3f:ec:c4:ae:80:f7:b0:8a:1e:85:41:e8:ff:fe:fe:4f: + 1a:24:d5:49:fa:fb:fe:5e:e5:d3:91:0e:4f:4e:0c:21:51:71: + 83:04:6b:62:7b:4f:59:76:48:81:1e:b4:f7:04:47:8a:91:57: + a3:11:a9:f2:20:b4:78:33:62:3d:b0:5e:0d:f9:86:38:82:da: + a1:98:8d:19:06:87:21:39:b7:02:f7:da:7d:58:ba:52:15:d8: + 3b:c9:7b:58:34:a0:c7:e2:7c:a9:83:13:e1:b6:ec:01:bf:52: + 33:0b:c4:fe:43:d3:c6:a4:8e:2f:87:7f:7a:44:ea:ca:53:6c: + 85:ed:65:76:73:31:03:4e:ea:bd:35:54:13:f3:64:87:6b:df: + 34:dd:34:a1:88:3b:db:4d:af:1b:64:90:92:71:30:8e:c8:cc: + e5:60:24:af:31:16:39:33:91:50:f9:ab:68:42:74:7a:35:d9: + dd:c8:c4:52 +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIJAIb/9Y4Q3rj7MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G +A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAe +Fw0xODA0MTMxNTIzMDlaFw0yMTAxMDcxNTIzMDlaMIGUMQswCQYDVQQGEwJVUzEQ +MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwIU2F3 +dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xmc3Ns +LmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL8Myi0Ush6EQlvNOB9K8k11EPG2NZ/fyn0D +mNOs3gNm7irx2LB9bgdUCxCYIU2AyxIg58xP3kV9yXJ3MurKkLtpUhADL6jzlcXx +i2JWG+9nb6QQQZWtCpvjpcCw0nB2UDBbqOgILHztp6J6jTgpHKzH7fJ8lbCVgn1J +XDjNdyXvvYB1U5Q8PcpjW58VtdMdEy8Z0TzbdjrMuH3J5cLX2kBv2CHccxtCLVOc +/hr8fat6Nj+Y3oR8BWfOahQ4h6nxjLVoy2h/cSAr9aBj9VYvoybSt2+xWhfXOJkI +/pNYb/7DE0kIFgunTWcAUjFnI06Y7VFFHbkE2Qvs2CizS73tNnkCAwEAAaOB/DCB ++TAdBgNVHQ4EFgQUJ45nEXTDJh0/7TNjs6TYHTDl6NUwgckGA1UdIwSBwTCBvoAU +J45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290 +aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t +MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1jhDeuPswDAYD +VR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAniiIcgDK5ueXysHxH54SsrjH +Ueoo4Ta1LeYvCCPLqUqHJcZdiUXq9QCYrHb7G6/wzmSe2gi/tuu0tQyg5/ZHWRxh +zy4OWKSCrA8/7MSugPewih6FQej//v5PGiTVSfr7/l7l05EOT04MIVFxgwRrYntP +WXZIgR609wRHipFXoxGp8iC0eDNiPbBeDfmGOILaoZiNGQaHITm3AvfafVi6UhXY +O8l7WDSgx+J8qYMT4bbsAb9SMwvE/kPTxqSOL4d/ekTqylNshe1ldnMxA07qvTVU +E/Nkh2vfNN00oYg7202vG2SQknEwjsjM5WAkrzEWOTORUPmraEJ0ejXZ3cjExg== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-duplicate-policy.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-duplicate-policy.pem new file mode 100644 index 000000000..bdc9af911 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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: Apr 13 15:23:10 2018 GMT + Not After : Jan 7 15:23:10 2021 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:86:FF:F5:8E:10:DE:B8:FB + + 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 + a0:b0:d4:b9:0b:bb:1e:3a:50:21:43:6a:e0:99:61:7e:46:cb: + d6:d3:5a:84:47:4c:9b:e9:13:c8:d4:44:b5:17:1f:52:29:a8: + 3d:e1:33:50:4a:4a:9c:a4:8d:86:99:83:72:7e:87:ba:04:b0: + bc:9b:39:ce:73:15:49:99:03:f1:e1:b5:ef:cb:85:bc:45:5e: + a8:fd:f6:82:f2:45:80:31:e9:cd:56:9b:cc:84:ff:6c:36:ee: + a6:e0:7f:a7:f1:49:0d:b6:ed:12:5b:34:05:b8:c5:4d:e2:ec: + 5b:25:dd:9c:3a:1a:4b:dc:cf:8e:41:a4:dd:ca:83:6a:cc:bc: + cd:4d:75:92:1f:45:8a:b0:6d:e4:72:8d:2c:18:12:26:b2:dc: + 3f:47:bd:76:c1:cb:da:9e:bd:58:10:6c:3e:57:22:9b:34:3e: + 6f:88:d7:e3:fd:4f:f5:97:a2:d2:9f:1d:58:fc:36:fa:94:dd: + 4e:13:e6:57:35:1c:5c:a5:69:6a:ce:3d:d3:21:51:1a:1a:3e: + cf:89:a4:c1:a0:9e:c4:0f:a1:d1:39:ac:31:1e:5e:e7:2f:d0: + 22:c3:9f:4d:57:90:ab:d6:f8:3d:dc:7f:9d:71:94:5d:95:48: + 9d:01:66:13:3a:26:0f:76:cc:c2:63:7d:0c:c8:0c:88:6b:84: + 01:c7:0a:a4 +-----BEGIN CERTIFICATE----- +MIIFJjCCBA6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh +d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMTgwNDEz +MTUyMzEwWhcNMjEwMTA3MTUyMzEwWjCBoTELMAkGA1UEBhMCVVMxEDAOBgNVBAgM +B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xEDAOBgNVBAoMB3dvbGZTU0wxITAf +BgNVBAsMGHRlc3RpbmcgZHVwbGljYXRlIHBvbGljeTEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJUI4VdB8nFtt9JFQScBZcZFrvK8 +JDC4lc4vTtb2HIi8fJ/7qGd//lycUXX3isoH5zUvj+G9e8AvfKtkqBf8yl17uuAh +5XIuby6G2JVz2qwbU7lfP9cZDSVP4WNjUYsLZD+tQ7ilHFw0s64AoGPF9n8LWWh4 +c6aMGKkCba/DGQEuuBDjxsxAtGmjRjNph27Euxem8+jdrXO8ey8htf1mUQy9VLPh +bV8cvCNz0QkDiRTSELlkwyrQoZZKvOHUGlvHoMDBY3gPRDcwMpaAMiOVoXe6E9KX +c+JdJclqDcM5YKS0sGlCQgnp2Ai8MyCzWCKnquvE4eZhg8XSlt/Z0E+t1wIDAQAB +o4IBcjCCAW4wHQYDVR0OBBYEFLMRMsmSmITiyfjQO24DQsofDo48MIHJBgNVHSME +gcEwgb6AFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYDVQQGEwJV +UzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwI +U2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xm +c3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIJAIb/9Y4Q +3rj7MAkGA1UdEwQCMAAwdgYDVR0gBG8wbTAFBgMqAwQwZAYDKgMEMF0wGwYIKwYB +BQUHAgEWD3d3dy53b2xmc3NsLmNvbTA+BggrBgEFBQcCAjAyGjBUZXN0IG9mIGR1 +cGxpY2F0ZSBPSURzIHdpdGggZGlmZmVyZW50IHF1YWxpZmllcnMwDQYJKoZIhvcN +AQELBQADggEBAKCw1LkLux46UCFDauCZYX5Gy9bTWoRHTJvpE8jURLUXH1IpqD3h +M1BKSpykjYaZg3J+h7oEsLybOc5zFUmZA/Hhte/LhbxFXqj99oLyRYAx6c1Wm8yE +/2w27qbgf6fxSQ227RJbNAW4xU3i7Fsl3Zw6Gkvcz45BpN3Kg2rMvM1NdZIfRYqw +beRyjSwYEiay3D9HvXbBy9qevVgQbD5XIps0Pm+I1+P9T/WXotKfHVj8NvqU3U4T +5lc1HFylaWrOPdMhURoaPs+JpMGgnsQPodE5rDEeXucv0CLDn01XkKvW+D3cf51x +lF2VSJ0BZhM6Jg92zMJjfQzIDIhrhAHHCqQ= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 9727763710660753659 (0x86fff58e10deb8fb) + 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: Apr 13 15:23:09 2018 GMT + Not After : Jan 7 15:23:09 2021 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:86:FF:F5:8E:10:DE:B8:FB + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 9e:28:88:72:00:ca:e6:e7:97:ca:c1:f1:1f:9e:12:b2:b8:c7: + 51:ea:28:e1:36:b5:2d:e6:2f:08:23:cb:a9:4a:87:25:c6:5d: + 89:45:ea:f5:00:98:ac:76:fb:1b:af:f0:ce:64:9e:da:08:bf: + b6:eb:b4:b5:0c:a0:e7:f6:47:59:1c:61:cf:2e:0e:58:a4:82: + ac:0f:3f:ec:c4:ae:80:f7:b0:8a:1e:85:41:e8:ff:fe:fe:4f: + 1a:24:d5:49:fa:fb:fe:5e:e5:d3:91:0e:4f:4e:0c:21:51:71: + 83:04:6b:62:7b:4f:59:76:48:81:1e:b4:f7:04:47:8a:91:57: + a3:11:a9:f2:20:b4:78:33:62:3d:b0:5e:0d:f9:86:38:82:da: + a1:98:8d:19:06:87:21:39:b7:02:f7:da:7d:58:ba:52:15:d8: + 3b:c9:7b:58:34:a0:c7:e2:7c:a9:83:13:e1:b6:ec:01:bf:52: + 33:0b:c4:fe:43:d3:c6:a4:8e:2f:87:7f:7a:44:ea:ca:53:6c: + 85:ed:65:76:73:31:03:4e:ea:bd:35:54:13:f3:64:87:6b:df: + 34:dd:34:a1:88:3b:db:4d:af:1b:64:90:92:71:30:8e:c8:cc: + e5:60:24:af:31:16:39:33:91:50:f9:ab:68:42:74:7a:35:d9: + dd:c8:c4:52 +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIJAIb/9Y4Q3rj7MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G +A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAe +Fw0xODA0MTMxNTIzMDlaFw0yMTAxMDcxNTIzMDlaMIGUMQswCQYDVQQGEwJVUzEQ +MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8GA1UECgwIU2F3 +dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3dy53b2xmc3Ns +LmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL8Myi0Ush6EQlvNOB9K8k11EPG2NZ/fyn0D +mNOs3gNm7irx2LB9bgdUCxCYIU2AyxIg58xP3kV9yXJ3MurKkLtpUhADL6jzlcXx +i2JWG+9nb6QQQZWtCpvjpcCw0nB2UDBbqOgILHztp6J6jTgpHKzH7fJ8lbCVgn1J +XDjNdyXvvYB1U5Q8PcpjW58VtdMdEy8Z0TzbdjrMuH3J5cLX2kBv2CHccxtCLVOc +/hr8fat6Nj+Y3oR8BWfOahQ4h6nxjLVoy2h/cSAr9aBj9VYvoybSt2+xWhfXOJkI +/pNYb/7DE0kIFgunTWcAUjFnI06Y7VFFHbkE2Qvs2CizS73tNnkCAwEAAaOB/DCB ++TAdBgNVHQ4EFgQUJ45nEXTDJh0/7TNjs6TYHTDl6NUwgckGA1UdIwSBwTCBvoAU +J45nEXTDJh0/7TNjs6TYHTDl6NWhgZqkgZcwgZQxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290 +aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t +MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggkAhv/1jhDeuPswDAYD +VR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAniiIcgDK5ueXysHxH54SsrjH +Ueoo4Ta1LeYvCCPLqUqHJcZdiUXq9QCYrHb7G6/wzmSe2gi/tuu0tQyg5/ZHWRxh +zy4OWKSCrA8/7MSugPewih6FQej//v5PGiTVSfr7/l7l05EOT04MIVFxgwRrYntP +WXZIgR609wRHipFXoxGp8iC0eDNiPbBeDfmGOILaoZiNGQaHITm3AvfafVi6UhXY +O8l7WDSgx+J8qYMT4bbsAb9SMwvE/kPTxqSOL4d/ekTqylNshe1ldnMxA07qvTVU +E/Nkh2vfNN00oYg7202vG2SQknEwjsjM5WAkrzEWOTORUPmraEJ0ejXZ3cjEUg== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-garbage.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-garbage.der new file mode 100644 index 0000000000000000000000000000000000000000..1877226d361df64d599fc2d336c592a14b620748 GIT binary patch literal 917 zcmXqLVxDNw#8kO}nTe5!iId^D>y;PglX=$~@Un4gwRyCC=VfH%W@Rv_G2}MjWMd9x zVH0Kw4K@@o-~(|uc-VdO^GXu)5@90jJnT;SRjIj&d4?heLLfEVJlw8%>6v+{sYRK2 z>4riE0w7Ul9?qQn`IvZJdl^0-1Sf`3~jzIcdekIeN+Yxdw9LyoMGA zmWGx_hCpZ%CC+PPXkcb&3gr&4>zWvqkb{enm4Ug5k)Oe!iIIz`iII`vz*LTh;f|jQ zbGKh|byR0eJ?6UZ(;gLr9aGQg`(67c)3K*!{_hp(_5Wh#1eSj9I>r9nRKNe>-s%JT zHLFuri2peiTfOUn;?p9%e7&|CQ;Tn{kq+J&Z+~5qSJnSva&lldcZ&U5=N(IBVoWx# zV_1-U^jkf5WJX2tvL1<*Ou6e1OET*15O{p-jKh}9#csx#?RiIbi!b~9;_lkwJ=OY( zTmPm7^6U-S{4h6OW{-05MNZ~UkxK$QQx0ogSUAmV&%-NH(Z?4YIG9|)?_zFXG_Ao% zdFsOQUBZ{97e9(sJ(eAVkC51%DAAH6i~{>=;i zYp*jgGcqtP7Bhe(2w6cEU{Y#gPfsjLN=#2h4mn^#1BM(UgZ*rV&O3byReg(Po_hIL zmA$@j+BnzX$A)?bom&&!7<@E(^YZ_wIyYR7bXfL6ntz3=@SB|nChvXE>ACgKRM|4V zZFN(8ud$poD|#vWYLZ9bhQuoqF3)uNFm>Mvx5Y{-CO3jY&8Myxc=Pu2Vzp(`0tz;Z zVv;2sCw@PDV8NU2Xw}fOi!SP%;6Ab6=MQ)5mVwF99D6UHo!OxI z*Mg}lwfUvshLu^$sF`Bka8iFt-120|b;+&tW_dFh#Xsi{So zdFh4{24WylW*+|X@^Zbr{M^Kn7H>MWfS|c62Gv5BXB(JLf!{p?^ZtfKOwaz=1 z%EXv#UdON?`RKQL?#PUa;$=M&E17cFAC_d)+ad7y*cpc{nTy?wGu!iy>=s}4`NiF} z#e1st6}SFP3*^}wviV_dyv!cu;)|Tjog$Y6cBUNGy0CDX*Pe%0q@s^6IB+nzg5Sm5 zz-U^7k@D1q<-3G0O)q{Ft9mkv_poKck}VrDot!vd-r(3{tgtykY5A(xM;<;)Y(9Ev z+Wngs{MTM*VrFDuTntPF1|q<8AS=kiYrx&anUkNKn3IuTT!I{Sz=Q`3J4S}MS-Gzw za#!a4I=)-1Hum)NkkkGzET%q^&Uv-g`}C`b@b7x8C&OodJi~lYvqo5~zv9w?R}$-g z$e#bAnqz$S#%vA6BX>XC7bq5Zt7mX9STsQX=Z|Z*Mbg$TTV7GO&@JHWd3MF;#!pml zNL-RXRddbt;%$ACb%`6LSpClJ+U^m*op&DNhq%8V4H9@G^Q3QX*Az9pvG0z)@>gL$ zm)E*{LG$WtYgaB<-@zr?b6W6@%9iZ))=Qr>g$rLirBb>fc>j(!g^i0_R&M{d+fcf5 z%D#zWchjZQq$?XGZDcj&9^A3#&f|T`&E>4|GxK^?sLtbR{q1QcZ#BOj&E*Wd!H^kl JVxsnWI{?p|UK9WT literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodalt.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodalt.pem new file mode 100644 index 000000000..3902608e4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodalt.pem @@ -0,0 +1,75 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + cd:00:d2:2e:bb:c5:a6:5d + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com + Validity + Not Before: Sep 19 21:21:24 2018 GMT + Not After : Jun 15 21:21:24 2021 GMT + Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.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 Alternative Name: + DNS:localhost + Signature Algorithm: sha256WithRSAEncryption + 5e:9a:6d:ea:58:6d:a9:6e:fa:c7:bb:16:7d:5d:cb:97:54:cb: + 4f:e8:38:95:e2:1b:6c:ea:ad:4b:cb:ea:58:57:f7:2e:05:c9: + 57:9b:f1:cc:03:c1:29:7c:13:16:8f:78:d2:c0:ea:18:af:f8: + 1d:cf:f4:25:6c:33:cd:d8:9b:28:21:c4:dd:f0:df:10:73:10: + ed:2e:30:c1:53:15:50:1f:f9:f8:d6:db:14:66:ad:a6:a7:78: + 7e:a1:46:50:f5:cf:07:21:e7:33:e4:25:d8:18:d2:1f:ca:7c: + d6:45:d1:db:2f:34:ae:61:b1:1a:05:4e:ce:ba:b7:48:5f:b7: + 0d:9e:01:f0:5e:fd:f1:30:60:0d:59:6e:1b:d9:b7:29:15:31: + d8:be:dc:2f:23:f5:13:4e:44:eb:2d:0e:52:9e:7e:3d:7d:a9: + a0:af:88:0a:15:8c:cb:11:dc:24:b4:6b:af:3b:a5:e4:82:57: + 13:d1:ca:24:75:b0:53:bf:b8:ec:71:81:a3:84:a9:b7:fe:bb: + 31:1b:89:94:be:91:16:dd:67:1b:66:1b:79:81:19:3c:1d:29: + 1e:e0:dc:3f:0b:6e:0d:e5:0b:0a:43:28:f9:69:d7:7a:55:2c: + e3:7b:2f:b7:66:34:ed:29:f5:c5:6d:09:51:d8:00:69:57:34: + 34:26:f3:b7 +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgIJAM0A0i67xaZdMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIG +A1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMMD3d3dy5ub21hdGNoLmNvbTEfMB0G +CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0xODA5MTkyMTIxMjRaFw0y +MTA2MTUyMTIxMjRaMIGCMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQ +MA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMM +D3d3dy5ub21hdGNoLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEn +AWXGRa7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX +/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBj +xfZ/C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9 +ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIj +laF3uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBP +rdcCAwEAAaMYMBYwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUA +A4IBAQBemm3qWG2pbvrHuxZ9XcuXVMtP6DiV4hts6q1Ly+pYV/cuBclXm/HMA8Ep +fBMWj3jSwOoYr/gdz/QlbDPN2JsoIcTd8N8QcxDtLjDBUxVQH/n41tsUZq2mp3h+ +oUZQ9c8HIecz5CXYGNIfynzWRdHbLzSuYbEaBU7OurdIX7cNngHwXv3xMGANWW4b +2bcpFTHYvtwvI/UTTkTrLQ5Snn49famgr4gKFYzLEdwktGuvO6XkglcT0cokdbBT +v7jscYGjhKm3/rsxG4mUvpEW3WcbZht5gRk8HSke4Nw/C24N5QsKQyj5add6VSzj +ey+3ZjTtKfXFbQlR2ABpVzQ0JvO3 +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodaltwild.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodaltwild.der new file mode 100644 index 0000000000000000000000000000000000000000..6ec2b54d76db178f5b44088b2ce4f19c7e572137 GIT binary patch literal 934 zcmXqLVqRp>#MHHbnTe5!iIbsm)wK?X7)3_|UN%mxHjlRNyo`+8tPBQ?O@`bCoNUaY zENsF|p}~d%27Dk62M@b%eqKppULs6{orm2izbZ91G0#xMKnSFUn}^#qFFi9aHMJ-+ zFWpeWKnx_x%)?(^UapsypPN{coS~PTpKB;@APcvYlTl0{GcPUQp*%k)t++S`q`*K< zoY&C8z|zpt$PfrkqQrTP3=PZ-O`+Vu;m9UNCFH`?N>JV8_&R`hM5G$#m?gng4r5di}qcIf13$yH2q`H`VWd zxVQR%e$DEX72%FJG_i#?<0lYovpB#@k<)5n4BEg&7ESu)_KQL znHZDJ>lhX!AN^L(9hp&4ysSrJB~$MD!;*}8I|LpdJL9k=bFrIoW_#X|-QvqWzqq@$ zcu%#y;?}=ufjoOdHb2abm)WCSe36s6Q{BWy?RZnK|9=1$avSmZ2lN0C58ytI#6*fmGEnoHe$irue%||ay zyMOb7|Jv(J%!~|-izN-j4Mc(IKvs~2&w!_iODiWoIWZ?AzqkZB@PH`~7Re3?NLN~v5#$bfJpVUko>2TnT)nK?&=vl zekf|XtT#HqXogYQKS_=M0gsNvJ>Q3TAq?@8Rp7RQ!jvR$|B7X`2LNn)`1}aurB;eEVShl#M=3*KSv_ KZtSlpF$Dm}RbM** literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodaltwild.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodaltwild.pem new file mode 100644 index 000000000..a16fbf280 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodaltwild.pem @@ -0,0 +1,75 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 81:aa:d6:88:40:5c:21:41 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.com, emailAddress = info@wolfssl.com + Validity + Not Before: Sep 19 21:21:24 2018 GMT + Not After : Jun 15 21:21:24 2021 GMT + Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = www.nomatch.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 Alternative Name: + DNS:*localhost + Signature Algorithm: sha256WithRSAEncryption + 79:9c:b3:8c:52:fe:d2:38:36:4c:70:80:ee:36:db:cc:68:5f: + a3:fb:c5:3e:a3:77:18:80:e9:88:69:da:39:69:bc:40:8b:2c: + 5c:c3:d0:4c:8b:17:05:12:a9:f1:d5:b7:9a:6a:6d:f7:19:09: + 20:22:dc:7f:11:b2:4e:df:7d:a2:1a:4d:fd:86:b9:bc:ee:e0: + a0:94:47:fd:4d:5c:45:4c:47:a7:d8:95:22:1b:2c:be:88:b0: + a1:94:15:31:34:bd:3a:01:3f:eb:67:ce:80:c0:1f:d5:9d:0e: + be:9f:90:a1:15:45:ed:0f:27:50:6e:52:6c:2b:81:22:00:99: + 2c:71:2d:86:e2:58:87:73:4c:3d:6b:50:14:7b:96:54:6f:e5: + 19:69:01:3d:d8:dd:2e:30:e3:e1:15:35:a6:8d:5b:50:32:98: + 32:76:fe:19:28:ff:50:e2:c4:5e:e7:b7:60:ad:7a:f2:9f:62: + 4b:c8:22:d3:0f:e0:4a:48:5e:d5:c9:75:41:d5:ce:c2:4a:a2: + 5f:d2:75:a3:d3:d6:95:f2:be:e0:5e:da:87:2c:02:70:99:49: + 87:bc:0e:8b:92:73:fc:05:7d:18:b8:ed:96:b2:11:5c:83:8f: + da:92:45:10:60:e3:db:c1:5f:94:b1:4c:82:d6:db:7a:05:b1: + 8f:78:74:35 +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIJAIGq1ohAXCFBMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIG +A1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMMD3d3dy5ub21hdGNoLmNvbTEfMB0G +CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0xODA5MTkyMTIxMjRaFw0y +MTA2MTUyMTIxMjRaMIGCMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQ +MA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECwwLRW5naW5lZXJpbmcxGDAWBgNVBAMM +D3d3dy5ub21hdGNoLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEn +AWXGRa7yvCQwuJXOL07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX +/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBj +xfZ/C1loeHOmjBipAm2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9 +ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIj +laF3uhPSl3PiXSXJag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBP +rdcCAwEAAaMZMBcwFQYDVR0RBA4wDIIKKmxvY2FsaG9zdDANBgkqhkiG9w0BAQsF +AAOCAQEAeZyzjFL+0jg2THCA7jbbzGhfo/vFPqN3GIDpiGnaOWm8QIssXMPQTIsX +BRKp8dW3mmpt9xkJICLcfxGyTt99ohpN/Ya5vO7goJRH/U1cRUxHp9iVIhssvoiw +oZQVMTS9OgE/62fOgMAf1Z0Ovp+QoRVF7Q8nUG5SbCuBIgCZLHEthuJYh3NMPWtQ +FHuWVG/lGWkBPdjdLjDj4RU1po1bUDKYMnb+GSj/UOLEXue3YK168p9iS8gi0w/g +Skhe1cl1QdXOwkqiX9J1o9PWlfK+4F7ahywCcJlJh7wOi5Jz/AV9GLjtlrIRXIOP +2pJFEGDj28FflLFMgtbbegWxj3h0NQ== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcn.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcn.der new file mode 100644 index 0000000000000000000000000000000000000000..d8dffb33ae8be976610fe0d2707e8085885c11b3 GIT binary patch literal 893 zcmXqLVy-l3VoF@V%*4pV#K~~z#q_(!|E;`Yz{|#|)#lOmotKf3o0Y+!#*o{9lZ`o) zg-w_#G}utUfDgps;9>X8&nrpHON5EA^RPSRSEc4A<{63@2!Yga^KiT7rDx`)rWR%9 zr5g$v2!KSHc{p?OlM{0?@{3Ch_Fu4`gcLJlrQRtDxKMt%l^CPpr%CPqev15-I3hC6;L z%-w#;)lr=>^_c6rPkU4hc1%5|?|1E+Ovj#@`M+1B*Z+%|6IlAa>lFKQQ~myjd#exV z*Q`!iA^zu7Z1t`OicgF5^7YzoOf9~(Mml(By!~}aURD2x$;pA;+$r{Jop&sii80x{ zj$uLa(QozKkr@@m%X%bMGUcv6EXk<1L*VhTGY(ra7rPl}w&xw$ExzpYi@R%!_f+dE zZvC4U$g?+O^TXVDnLWzI7de?bMJ@^KOgXG|Vc|5dJrA!)MIT>q;9znEzl*tn(X<95 z<*5tHcL`sbUi>Il^<)Q>oJbaeeeDu<^`!_H6 zuf5L1%*eoq974bZ1q>lZ1~rW>oT*CvMzIk+4*&D(()Q*6&kt=Eh1zzb$1g zY!ja4Ee~^@#yp{?!)Vg~2{$)i(704%@~zD3OyRHJ8W%NtyNlOduX&wp!q^aD_u+c9 zxc9Af@ue3hIkH|pAhqcDjx{$5IDTEd>L)Joo{eSIJkcF5SZ@a=>rOqqJ}V@(<@|y= z6BqM8(I#U!&F#{6SGPI4+)bh(Z;`hC@h8v!ZM4~9 zTexfXomQ`1?T6Qj3OwRkd-(PXPsR2ftREI>#!hs-TO2GfrORLH(c$)LHSawe9>vzI fXX_7{Vio(o*W?Ok!0Nc!)V>`hfy literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcn.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcn.pem new file mode 100644 index 000000000..ec7a6a4f1 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcn.pem @@ -0,0 +1,71 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + c2:e8:97:dd:c7:fe:a9:d4 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = localhost, emailAddress = info@wolfssl.com + Validity + Not Before: Sep 19 21:21:24 2018 GMT + Not After : Jun 15 21:21:24 2021 GMT + Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = localhost, 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) + Signature Algorithm: sha256WithRSAEncryption + 26:28:b4:09:65:22:8f:32:5d:58:8c:40:ff:6f:7e:66:bf:6f: + b5:69:4e:ee:ad:4e:f2:63:69:b1:79:21:4e:b4:76:84:06:90: + e6:6e:a7:56:45:96:03:90:8c:88:32:92:ff:90:d9:b3:d0:28: + d2:7c:34:f6:76:3a:cc:71:fa:fb:28:d1:29:8d:8b:73:ae:d7: + 7c:eb:63:34:01:80:58:3e:f0:d7:5b:17:4b:da:ae:5f:75:d1: + 92:41:05:d3:c0:1a:a2:c7:b8:ac:d8:70:08:fa:d5:d5:4e:17: + 18:ef:06:04:aa:9e:15:b8:e8:05:db:51:63:2d:95:c3:af:6a: + 54:65:84:cf:a0:7e:34:44:37:fc:5b:34:5e:2a:c9:a7:9c:a0: + f1:c5:89:32:f1:71:df:91:b1:28:e8:e8:15:42:3b:0b:44:8e: + dd:2d:83:6b:77:46:18:80:6e:a2:2b:2f:c7:e4:e7:fe:b1:3c: + b4:3d:71:ba:9b:dc:85:4a:ba:87:c3:ad:15:10:e2:0a:ad:c3: + db:e8:49:21:87:b8:05:f0:a2:29:5d:91:45:dd:73:53:10:94: + 8a:4f:1a:e2:c3:87:7b:26:4b:bc:b0:e2:5d:7c:af:06:8f:54: + 94:3a:5d:ef:8d:34:d4:09:50:ab:5e:9b:3b:12:51:b3:18:1f: + 35:b7:8d:49 +-----BEGIN CERTIFICATE----- +MIIDeTCCAmGgAwIBAgIJAMLol93H/qnUMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYD +VQQLDAtFbmdpbmVlcmluZzESMBAGA1UEAwwJbG9jYWxob3N0MR8wHQYJKoZIhvcN +AQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MDkxOTIxMjEyNFoXDTIxMDYxNTIx +MjEyNFowfDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcM +B0JvemVtYW4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRIwEAYDVQQDDAlsb2NhbGhv +c3QxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDAlQjhV0HycW230kVBJwFlxkWu8rwkMLiVzi9O +1vYciLx8n/uoZ3/+XJxRdfeKygfnNS+P4b17wC98q2SoF/zKXXu64CHlci5vLobY +lXParBtTuV8/1xkNJU/hY2NRiwtkP61DuKUcXDSzrgCgY8X2fwtZaHhzpowYqQJt +r8MZAS64EOPGzEC0aaNGM2mHbsS7F6bz6N2tc7x7LyG1/WZRDL1Us+FtXxy8I3PR +CQOJFNIQuWTDKtChlkq84dQaW8egwMFjeA9ENzAyloAyI5Whd7oT0pdz4l0lyWoN +wzlgpLSwaUJCCenYCLwzILNYIqeq68Th5mGDxdKW39nQT63XAgMBAAEwDQYJKoZI +hvcNAQELBQADggEBACYotAllIo8yXViMQP9vfma/b7VpTu6tTvJjabF5IU60doQG +kOZup1ZFlgOQjIgykv+Q2bPQKNJ8NPZ2Osxx+vso0SmNi3Ou13zrYzQBgFg+8Ndb +F0varl910ZJBBdPAGqLHuKzYcAj61dVOFxjvBgSqnhW46AXbUWMtlcOvalRlhM+g +fjREN/xbNF4qyaecoPHFiTLxcd+RsSjo6BVCOwtEjt0tg2t3RhiAbqIrL8fk5/6x +PLQ9cbqb3IVKuofDrRUQ4gqtw9voSSGHuAXwoildkUXdc1MQlIpPGuLDh3smS7yw +4l18rwaPVJQ6Xe+NNNQJUKtemzsSUbMYHzW3jUk= +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcnwild.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcnwild.der new file mode 100644 index 0000000000000000000000000000000000000000..3ab2636d5a891afb318ecca60a151c4e40cfe123 GIT binary patch literal 895 zcmXqLVy-r5VoF}X%*4pV#L4h{?Mf?`gLNJTylk9WZ60mkc^MhGSs4s!4Y>_C*_cCF z*o2uvgAD}?_&^*E9(LdSypqJcM3@LW54%%-RcdZxo}q|=5J(L-54USxdS+f~YEfoh zx}mUvAV`#%hf6CbKRGccBfq%BP~JcmZXGA1m_TM;TE0Vheok6(agJVcey)L>IIp3F zfu*6Pks%P8M2Yhn85)=wnnJk)?Yt&NCFB5OWMyD(V&rEqXkz4IYGPz$I53stVYuU` z!rbkbTpiUJQ;)f>`?N>JV8_&R`hM5G$#m?gng4r5di}qcIf13$yH2q`H`VWdxVQR% ze$DEX72%FJG_i#?<0lYovpB#@k<)5n4BEg&7ESu)_KQLnHZDJ z>lhX!AN^L(9hp&4ysSrJB~$MD!;*}8I|LpdJL9k=bFrIoW_#X|-QvqWzqq@$cu%#y z;?}=ufjoOdHb2abm)WCSe36s6Q{BWy?RZnK|9=1$avSmZ2lN0C58ytI#6*fmGEnoHe$irue%||ayyMOb7 z|Jv(J%!~|-$RPwwQos;mWLU~9oA1e>d32IUzjgnrm-5^Gel&`by6bKBwOQWv!K$e_ z`8)sqWD&Su{O8eAQ6HATsU_tXu3i@2DJFHBX@26-!V8WKpJn%c<2Q&pv;V<%r7HbE zH-(#@kGi*-$G~(?K z^#1mfW8ue%q2|K8w?v zE%#I+XZ|^R|HD3)FJ=FZM6s@0`ZcgVKqvh8)Ey7kcBxyQ`;{SnVSjO2G@I`419hf* gmKMC}UFG`qpMn14h4V|lU33#UY8DjfnW1k70E*XCiU0rr literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcnwild.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcnwild.pem new file mode 100644 index 000000000..3971fc78b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-goodcnwild.pem @@ -0,0 +1,71 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + e7:ad:a9:3a:44:c1:7e:48 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = *localhost, emailAddress = info@wolfssl.com + Validity + Not Before: Sep 19 21:21:24 2018 GMT + Not After : Jun 15 21:21:24 2021 GMT + Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = *localhost, 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) + Signature Algorithm: sha256WithRSAEncryption + a5:03:1d:6f:49:00:29:c5:92:14:8f:3b:8f:aa:e9:1f:b6:fd: + f1:32:5a:1a:dd:4b:36:f5:83:1f:45:e0:aa:95:6c:6f:b9:fd: + f9:04:10:df:73:fc:e2:e5:15:4c:04:51:95:74:77:d0:d5:d3: + 13:b9:16:1a:db:02:9f:61:c5:71:d0:41:80:f3:1d:bd:f6:0f: + 30:5a:cc:bf:e0:b7:22:7a:2f:51:46:20:d9:f3:c6:ea:0a:0b: + 23:69:a1:b9:96:3b:7d:af:bd:f0:1a:b2:b3:05:4a:fd:b2:71: + 3e:e7:24:8a:57:69:17:0c:18:3a:3a:84:a1:28:37:45:7b:8f: + c7:c6:28:5f:3f:c2:8d:51:2c:0b:77:61:c3:78:a2:c0:1f:0b: + 0f:23:5a:a9:1d:e6:2b:67:9a:0e:fa:f9:d7:de:73:53:e9:96: + b0:e6:5a:ef:3f:21:58:86:a4:df:9a:17:db:39:04:9f:04:42: + ec:b4:de:24:59:99:fc:cd:df:f0:be:44:f4:76:fe:c4:5a:05: + ae:a5:f5:51:7f:50:2c:57:c7:95:b8:e1:ad:8a:27:39:ce:fa: + 68:17:d0:bf:73:66:5b:06:2d:fb:c0:7e:35:bc:a5:70:ec:8d: + aa:45:f5:fe:30:2f:e3:a1:9f:75:f6:d1:46:14:c5:36:52:59: + 49:68:2f:3e +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIJAOetqTpEwX5IMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYD +VQQLDAtFbmdpbmVlcmluZzETMBEGA1UEAwwKKmxvY2FsaG9zdDEfMB0GCSqGSIb3 +DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0xODA5MTkyMTIxMjRaFw0yMTA2MTUy +MTIxMjRaMH0xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQH +DAdCb3plbWFuMRQwEgYDVQQLDAtFbmdpbmVlcmluZzETMBEGA1UEAwwKKmxvY2Fs +aG9zdDEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMCVCOFXQfJxbbfSRUEnAWXGRa7yvCQwuJXO +L07W9hyIvHyf+6hnf/5cnFF194rKB+c1L4/hvXvAL3yrZKgX/Mpde7rgIeVyLm8u +htiVc9qsG1O5Xz/XGQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBjxfZ/C1loeHOmjBip +Am2vwxkBLrgQ48bMQLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9ZlEMvVSz4W1fHLwj +c9EJA4kU0hC5ZMMq0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3uhPSl3PiXSXJ +ag3DOWCktLBpQkIJ6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBPrdcCAwEAATANBgkq +hkiG9w0BAQsFAAOCAQEApQMdb0kAKcWSFI87j6rpH7b98TJaGt1LNvWDH0XgqpVs +b7n9+QQQ33P84uUVTARRlXR30NXTE7kWGtsCn2HFcdBBgPMdvfYPMFrMv+C3Inov +UUYg2fPG6goLI2mhuZY7fa+98BqyswVK/bJxPuckildpFwwYOjqEoSg3RXuPx8Yo +Xz/CjVEsC3dhw3iiwB8LDyNaqR3mK2eaDvr5195zU+mWsOZa7z8hWIak35oX2zkE +nwRC7LTeJFmZ/M3f8L5E9Hb+xFoFrqX1UX9QLFfHlbjhrYonOc76aBfQv3NmWwYt ++8B+NbylcOyNqkX1/jAv46GfdfbRRhTFNlJZSWgvPg== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-localhost.der b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-localhost.der new file mode 100644 index 0000000000000000000000000000000000000000..77eb5ac8b7d38fd68e9ed6b083a65e9f7c2b22d9 GIT binary patch literal 919 zcmXqLVxDZ!#8kb2nTe5!iId@G&h;~2<{yYS+c+7;1Tyo|@*T?abJB{7bM%t)a}DIgc?~TL zEDbG<41v%jN}Sio(7?>l6v`c7*EKOJAqN*DD+6;ABR_*d6C)Q>6C)$TfvFr1!yP{r z=5D{_>Zs0`ddzj*r#&hLJEoq~_q+B@rejad{NF3m>;J{f2`v5Ib&CDDseb>%z10Ww zYgVVM5dU*3wtCkC#ivDj`Fd?PrWW5?BOSam-u}8Iud4sU7GL)H#oe{Vd#d#n zxBg8F+*S6Cp!apQpe)i)m3Snd|xpF5%W_=K=Gg{Oc0505FypRV_# yEk|P(U*^s?U-J8}9`c?N{-)&ZhyAk;t>fbt5Qv|*_@E{8rDYQW7T>oEy9)pl% literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-localhost.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-localhost.pem new file mode 100644 index 000000000..c34c9e0fd --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/test/server-localhost.pem @@ -0,0 +1,75 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + d9:6c:d7:cc:f4:9f:c5:18 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = localhost, emailAddress = info@wolfssl.com + Validity + Not Before: Sep 19 21:21:24 2018 GMT + Not After : Jun 15 21:21:24 2021 GMT + Subject: C = US, ST = Montana, L = Bozeman, OU = Engineering, CN = localhost, 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 Alternative Name: + DNS:localhost + Signature Algorithm: sha256WithRSAEncryption + 3a:16:c1:b1:05:65:32:fc:65:4b:09:5a:05:4a:c0:9c:ec:07: + f5:f0:01:41:7c:cf:20:c7:55:80:81:6a:df:65:f2:44:37:02: + b0:8f:7b:7b:0a:3d:a3:44:0f:e4:73:55:ee:cc:3a:d5:b0:8f: + 62:a5:65:73:dd:6c:b2:11:2a:76:3c:94:3a:8b:ea:32:a0:ea: + 41:05:a5:78:af:27:d2:9e:e9:b9:c3:9d:11:2a:3e:d3:d5:bf: + 72:46:b6:7b:8d:5f:6a:b9:25:78:c7:60:1a:60:5d:26:d6:45: + 06:b7:4d:b0:a1:20:bb:62:94:64:92:98:f6:a7:62:3d:06:70: + d5:7e:51:72:92:3e:97:81:20:d3:8a:fe:43:7b:a2:c6:4f:89: + a0:c5:e6:c5:a8:a4:e3:4c:a2:dc:52:de:61:fe:99:7e:c4:f3: + 2e:f0:81:c3:34:07:d6:2b:b5:cf:21:a3:8a:71:82:de:28:57: + 20:a0:1c:08:d8:c0:1f:d5:ec:48:d6:04:dd:72:df:9d:90:73: + c7:90:56:ec:71:cb:fa:ff:57:5c:74:6f:97:2e:f8:86:6c:28: + 9a:0e:69:b9:ec:f4:6f:8f:d5:c2:4b:94:57:ec:74:ed:f0:bf: + 9b:c2:ae:0e:0f:10:10:5f:9e:a3:c1:39:03:d2:a6:90:50:a3: + df:3e:56:dd +-----BEGIN CERTIFICATE----- +MIIDkzCCAnugAwIBAgIJANls18z0n8UYMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYD +VQQLDAtFbmdpbmVlcmluZzESMBAGA1UEAwwJbG9jYWxob3N0MR8wHQYJKoZIhvcN +AQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTE4MDkxOTIxMjEyNFoXDTIxMDYxNTIx +MjEyNFowfDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcM +B0JvemVtYW4xFDASBgNVBAsMC0VuZ2luZWVyaW5nMRIwEAYDVQQDDAlsb2NhbGhv +c3QxHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDAlQjhV0HycW230kVBJwFlxkWu8rwkMLiVzi9O +1vYciLx8n/uoZ3/+XJxRdfeKygfnNS+P4b17wC98q2SoF/zKXXu64CHlci5vLobY +lXParBtTuV8/1xkNJU/hY2NRiwtkP61DuKUcXDSzrgCgY8X2fwtZaHhzpowYqQJt +r8MZAS64EOPGzEC0aaNGM2mHbsS7F6bz6N2tc7x7LyG1/WZRDL1Us+FtXxy8I3PR +CQOJFNIQuWTDKtChlkq84dQaW8egwMFjeA9ENzAyloAyI5Whd7oT0pdz4l0lyWoN +wzlgpLSwaUJCCenYCLwzILNYIqeq68Th5mGDxdKW39nQT63XAgMBAAGjGDAWMBQG +A1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAOhbBsQVlMvxl +SwlaBUrAnOwH9fABQXzPIMdVgIFq32XyRDcCsI97ewo9o0QP5HNV7sw61bCPYqVl +c91sshEqdjyUOovqMqDqQQWleK8n0p7pucOdESo+09W/cka2e41farkleMdgGmBd +JtZFBrdNsKEgu2KUZJKY9qdiPQZw1X5RcpI+l4Eg04r+Q3uixk+JoMXmxaik40yi +3FLeYf6ZfsTzLvCBwzQH1iu1zyGjinGC3ihXIKAcCNjAH9XsSNYE3XLfnZBzx5BW +7HHL+v9XXHRvly74hmwomg5puez0b4/VwkuUV+x07fC/m8KuDg8QEF+eo8E5A9Km +kFCj3z5W3Q== +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/certs/wolfssl-website-ca.pem b/FreeRTOS-Plus/Source/WolfSSL/certs/wolfssl-website-ca.pem index 704a29fb3..e7bbd0731 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/certs/wolfssl-website-ca.pem +++ b/FreeRTOS-Plus/Source/WolfSSL/certs/wolfssl-website-ca.pem @@ -1,62 +1,49 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 0 (0x0) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority - Validity - Not Before: Jun 29 17:06:20 2004 GMT - Not After : Jun 29 17:06:20 2034 GMT - Subject: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:de:9d:d7:ea:57:18:49:a1:5b:eb:d7:5f:48:86: - ea:be:dd:ff:e4:ef:67:1c:f4:65:68:b3:57:71:a0: - 5e:77:bb:ed:9b:49:e9:70:80:3d:56:18:63:08:6f: - da:f2:cc:d0:3f:7f:02:54:22:54:10:d8:b2:81:d4: - c0:75:3d:4b:7f:c7:77:c3:3e:78:ab:1a:03:b5:20: - 6b:2f:6a:2b:b1:c5:88:7e:c4:bb:1e:b0:c1:d8:45: - 27:6f:aa:37:58:f7:87:26:d7:d8:2d:f6:a9:17:b7: - 1f:72:36:4e:a6:17:3f:65:98:92:db:2a:6e:5d:a2: - fe:88:e0:0b:de:7f:e5:8d:15:e1:eb:cb:3a:d5:e2: - 12:a2:13:2d:d8:8e:af:5f:12:3d:a0:08:05:08:b6: - 5c:a5:65:38:04:45:99:1e:a3:60:60:74:c5:41:a5: - 72:62:1b:62:c5:1f:6f:5f:1a:42:be:02:51:65:a8: - ae:23:18:6a:fc:78:03:a9:4d:7f:80:c3:fa:ab:5a: - fc:a1:40:a4:ca:19:16:fe:b2:c8:ef:5e:73:0d:ee: - 77:bd:9a:f6:79:98:bc:b1:07:67:a2:15:0d:dd:a0: - 58:c6:44:7b:0a:3e:62:28:5f:ba:41:07:53:58:cf: - 11:7e:38:74:c5:f8:ff:b5:69:90:8f:84:74:ea:97: - 1b:af - Exponent: 3 (0x3) - X509v3 extensions: - X509v3 Subject Key Identifier: - D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3 - X509v3 Authority Key Identifier: - keyid:D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3 - DirName:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority - serial:00 - - X509v3 Basic Constraints: - CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 32:4b:f3:b2:ca:3e:91:fc:12:c6:a1:07:8c:8e:77:a0:33:06: - 14:5c:90:1e:18:f7:08:a6:3d:0a:19:f9:87:80:11:6e:69:e4: - 96:17:30:ff:34:91:63:72:38:ee:cc:1c:01:a3:1d:94:28:a4: - 31:f6:7a:c4:54:d7:f6:e5:31:58:03:a2:cc:ce:62:db:94:45: - 73:b5:bf:45:c9:24:b5:d5:82:02:ad:23:79:69:8d:b8:b6:4d: - ce:cf:4c:ca:33:23:e8:1c:88:aa:9d:8b:41:6e:16:c9:20:e5: - 89:9e:cd:3b:da:70:f7:7e:99:26:20:14:54:25:ab:6e:73:85: - e6:9b:21:9d:0a:6c:82:0e:a8:f8:c2:0c:fa:10:1e:6c:96:ef: - 87:0d:c4:0f:61:8b:ad:ee:83:2b:95:f8:8e:92:84:72:39:eb: - 20:ea:83:ed:83:cd:97:6e:08:bc:eb:4e:26:b6:73:2b:e4:d3: - f6:4c:fe:26:71:e2:61:11:74:4a:ff:57:1a:87:0f:75:48:2e: - cf:51:69:17:a0:02:12:61:95:d5:d1:40:b2:10:4c:ee:c4:ac: - 10:43:a6:a5:9e:0a:d5:95:62:9a:0d:cf:88:82:c5:32:0c:e4: - 2b:9f:45:e6:0d:9f:28:9c:b1:b9:2a:5a:57:ad:37:0f:af:1d: - 7f:db:bd:9f +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE @@ -81,3 +68,24 @@ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf ReYNnyicsbkqWletNw+vHX/bvZ8= -----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- diff --git a/FreeRTOS-Plus/Source/WolfSSL/config.in b/FreeRTOS-Plus/Source/WolfSSL/config.in index e040f3662..a71ac70bc 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/config.in +++ b/FreeRTOS-Plus/Source/WolfSSL/config.in @@ -3,6 +3,9 @@ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD +/* User RSA is being defined */ +#undef BUILD_USER_RSA + /* Define to 1 to enable debugging code. */ #undef DEBUG @@ -27,12 +30,18 @@ /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R + /* Define to 1 if you have the `inet_ntoa' function. */ #undef HAVE_INET_NTOA /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have the header file. */ +#undef HAVE_IPPCP_H + /* Define to 1 if you have the `network' library (-lnetwork). */ #undef HAVE_LIBNETWORK @@ -106,13 +115,9 @@ /* Define to 1 if the system has the type `__uint128_t'. */ #undef HAVE___UINT128_T -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ +/* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -#undef NO_MINUS_C_MINUS_O - /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT @@ -141,6 +146,9 @@ /* The size of `long long', as computed by sizeof. */ #undef SIZEOF_LONG_LONG +/* The size of `time_t', as computed by sizeof. */ +#undef SIZEOF_TIME_T + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS @@ -153,6 +161,9 @@ /* VCS system */ #undef VCS_SYSTEM +/* Use __declspec(dllexport) when building library */ +#undef WOLFSSL_DLL + /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD diff --git a/FreeRTOS-Plus/Source/WolfSSL/configure b/FreeRTOS-Plus/Source/WolfSSL/configure index 6523b8c4e..424032bf8 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/configure +++ b/FreeRTOS-Plus/Source/WolfSSL/configure @@ -1,9 +1,11 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for wolfssl 3.6.0. +# Generated by GNU Autoconf 2.69 for wolfssl 4.4.0. # # Report bugs to . # +# Copyright (C) 2006-2020 wolfSSL Inc. +# # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # @@ -590,10 +592,10 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='wolfssl' PACKAGE_TARNAME='wolfssl' -PACKAGE_VERSION='3.6.0' -PACKAGE_STRING='wolfssl 3.6.0' +PACKAGE_VERSION='4.4.0' +PACKAGE_STRING='wolfssl 4.4.0' PACKAGE_BUGREPORT='https://github.com/wolfssl/wolfssl/issues' -PACKAGE_URL='http://www.wolfssl.com' +PACKAGE_URL='https://www.wolfssl.com' # Factoring default headers for most tests. ac_includes_default="\ @@ -638,36 +640,109 @@ LIBOBJS INC_AMINCLUDE AMINCLUDE GENERIC_CONFIG +LIB_STATIC_ADD +LIB_ADD +AM_CCASFLAGS AM_LDFLAGS AM_CFLAGS AM_CPPFLAGS HEX_VERSION -IS_VCS_CHECKOUT_FALSE -IS_VCS_CHECKOUT_TRUE +BUILD_HASHFLAGS_FALSE +BUILD_HASHFLAGS_TRUE +BUILD_PKCS7_FALSE +BUILD_PKCS7_TRUE +BUILD_DES3_FALSE +BUILD_DES3_TRUE +BUILD_PKI_FALSE +BUILD_PKI_TRUE +BUILD_TRUST_PEER_CERT_FALSE +BUILD_TRUST_PEER_CERT_TRUE +BUILD_PSK_FALSE +BUILD_PSK_TRUE +BUILD_CRYPTOCB_FALSE +BUILD_CRYPTOCB_TRUE +BUILD_WOLFEVENT_FALSE +BUILD_WOLFEVENT_TRUE +BUILD_ASYNCCRYPT_FALSE +BUILD_ASYNCCRYPT_TRUE BUILD_MCAPI_FALSE BUILD_MCAPI_TRUE +BUILD_FAST_RSA_FALSE +BUILD_FAST_RSA_TRUE +BUILD_SP_INT_FALSE +BUILD_SP_INT_TRUE +BUILD_SP_X86_64_FALSE +BUILD_SP_X86_64_TRUE +BUILD_SP_ARM_CORTEX_FALSE +BUILD_SP_ARM_CORTEX_TRUE +BUILD_SP_ARM_THUMB_FALSE +BUILD_SP_ARM_THUMB_TRUE +BUILD_SP_ARM32_FALSE +BUILD_SP_ARM32_TRUE +BUILD_SP_ARM64_FALSE +BUILD_SP_ARM64_TRUE +BUILD_SP_C_FALSE +BUILD_SP_C_TRUE +BUILD_SP_FALSE +BUILD_SP_TRUE +BUILD_INTEL_QA_SYNC_FALSE +BUILD_INTEL_QA_SYNC_TRUE +BUILD_INTEL_QA_FALSE +BUILD_INTEL_QA_TRUE +BUILD_OCTEON_SYNC_FALSE +BUILD_OCTEON_SYNC_TRUE +BUILD_CAVIUM_V_FALSE +BUILD_CAVIUM_V_TRUE +BUILD_CAVIUM_FALSE +BUILD_CAVIUM_TRUE +BUILD_PKCS12_FALSE +BUILD_PKCS12_TRUE +BUILD_PKCS11_FALSE +BUILD_PKCS11_TRUE BUILD_LIBZ_FALSE BUILD_LIBZ_TRUE -BUILD_EXAMPLES_FALSE -BUILD_EXAMPLES_TRUE +BUILD_WOLFCRYPT_TESTS_FALSE +BUILD_WOLFCRYPT_TESTS_TRUE +BUILD_THREADED_EXAMPLES_FALSE +BUILD_THREADED_EXAMPLES_TRUE +BUILD_TESTS_FALSE +BUILD_TESTS_TRUE +BUILD_EXAMPLE_CLIENTS_FALSE +BUILD_EXAMPLE_CLIENTS_TRUE +BUILD_EXAMPLE_SERVERS_FALSE +BUILD_EXAMPLE_SERVERS_TRUE BUILD_SLOWMATH_FALSE BUILD_SLOWMATH_TRUE BUILD_FASTMATH_FALSE BUILD_FASTMATH_TRUE +BUILD_CRYPTONLY_FALSE +BUILD_CRYPTONLY_TRUE +BUILD_SCRYPT_FALSE +BUILD_SCRYPT_TRUE BUILD_PWDBASED_FALSE BUILD_PWDBASED_TRUE +BUILD_MD4_FALSE +BUILD_MD4_TRUE USE_VALGRIND_FALSE USE_VALGRIND_TRUE -HAVE_VALGRIND -BUILD_PKCS7_FALSE -BUILD_PKCS7_TRUE +BUILD_SRP_FALSE +BUILD_SRP_TRUE +BUILD_WNR_FALSE +BUILD_WNR_TRUE BUILD_NTRU_FALSE BUILD_NTRU_TRUE +BUILD_USER_CRYPTO_FALSE +BUILD_USER_CRYPTO_TRUE +BUILD_USER_RSA_FALSE +BUILD_USER_RSA_TRUE BUILD_CRL_MONITOR_FALSE BUILD_CRL_MONITOR_TRUE BUILD_CRL_FALSE BUILD_CRL_TRUE -HAVE_OPENSSL_CMD +BUILD_OCSP_STAPLING_V2_FALSE +BUILD_OCSP_STAPLING_V2_TRUE +BUILD_OCSP_STAPLING_FALSE +BUILD_OCSP_STAPLING_TRUE BUILD_OCSP_FALSE BUILD_OCSP_TRUE BUILD_INLINE_FALSE @@ -676,22 +751,34 @@ BUILD_CHACHA_FALSE BUILD_CHACHA_TRUE BUILD_POLY1305_FALSE BUILD_POLY1305_TRUE +BUILD_SHA3_FALSE +BUILD_SHA3_TRUE +BUILD_SHA224_FALSE +BUILD_SHA224_TRUE +BUILD_SELFTEST_FALSE +BUILD_SELFTEST_TRUE +BUILD_CMAC_FALSE +BUILD_CMAC_TRUE +BUILD_FIPS_RAND_FALSE +BUILD_FIPS_RAND_TRUE +BUILD_FIPS_V2_FALSE +BUILD_FIPS_V2_TRUE +BUILD_FIPS_V1_FALSE +BUILD_FIPS_V1_TRUE BUILD_FIPS_FALSE BUILD_FIPS_TRUE BUILD_RABBIT_FALSE BUILD_RABBIT_TRUE BUILD_HC128_FALSE BUILD_HC128_TRUE -BUILD_MD4_FALSE -BUILD_MD4_TRUE BUILD_SHA_FALSE BUILD_SHA_TRUE BUILD_MD5_FALSE BUILD_MD5_TRUE BUILD_RC4_FALSE BUILD_RC4_TRUE -BUILD_DES3_FALSE -BUILD_DES3_TRUE +BUILD_IDEA_FALSE +BUILD_IDEA_TRUE BUILD_CODING_FALSE BUILD_CODING_TRUE BUILD_AES_FALSE @@ -704,22 +791,38 @@ BUILD_RSA_FALSE BUILD_RSA_TRUE BUILD_MEMORY_FALSE BUILD_MEMORY_TRUE +BUILD_CURVE448_SMALL_FALSE +BUILD_CURVE448_SMALL_TRUE +BUILD_CURVE448_FALSE +BUILD_CURVE448_TRUE +BUILD_GE448_FALSE +BUILD_GE448_TRUE +BUILD_FE448_FALSE +BUILD_FE448_TRUE +BUILD_ED448_SMALL_FALSE +BUILD_ED448_SMALL_TRUE +BUILD_ED448_FALSE +BUILD_ED448_TRUE +BUILD_CURVE25519_SMALL_FALSE +BUILD_CURVE25519_SMALL_TRUE +BUILD_CURVE25519_FALSE +BUILD_CURVE25519_TRUE BUILD_GEMATH_FALSE BUILD_GEMATH_TRUE BUILD_FEMATH_FALSE BUILD_FEMATH_TRUE -BUILD_CURVED25519_SMALL_FALSE -BUILD_CURVED25519_SMALL_TRUE +BUILD_ED25519_SMALL_FALSE +BUILD_ED25519_SMALL_TRUE BUILD_ED25519_FALSE BUILD_ED25519_TRUE -BUILD_CURVE25519_FALSE -BUILD_CURVE25519_TRUE BUILD_ECC_FALSE BUILD_ECC_TRUE BUILD_DSA_FALSE BUILD_DSA_TRUE BUILD_SHA512_FALSE BUILD_SHA512_TRUE +BUILD_BLAKE2S_FALSE +BUILD_BLAKE2S_TRUE BUILD_BLAKE2_FALSE BUILD_BLAKE2_TRUE BUILD_RIPEMD_FALSE @@ -728,8 +831,18 @@ BUILD_MD2_FALSE BUILD_MD2_TRUE BUILD_CAMELLIA_FALSE BUILD_CAMELLIA_TRUE +BUILD_DEVCRYPTO_FALSE +BUILD_DEVCRYPTO_TRUE +BUILD_AFALG_FALSE +BUILD_AFALG_TRUE +BUILD_INTELASM_FALSE +BUILD_INTELASM_TRUE BUILD_AESNI_FALSE BUILD_AESNI_TRUE +BUILD_XILINX_FALSE +BUILD_XILINX_TRUE +BUILD_ARMASM_FALSE +BUILD_ARMASM_TRUE BUILD_AESCCM_FALSE BUILD_AESCCM_TRUE BUILD_AESGCM_FALSE @@ -738,10 +851,37 @@ BUILD_SNIFFTEST_FALSE BUILD_SNIFFTEST_TRUE BUILD_SNIFFER_FALSE BUILD_SNIFFER_TRUE +BUILD_CRYPTOAUTHLIB_FALSE +BUILD_CRYPTOAUTHLIB_TRUE +BUILD_PKCALLBACKS_FALSE +BUILD_PKCALLBACKS_TRUE +BUILD_LOWMEM_FALSE +BUILD_LOWMEM_TRUE +BUILD_LEANTLS_FALSE +BUILD_LEANTLS_TRUE BUILD_LEANPSK_FALSE BUILD_LEANPSK_TRUE BUILD_IPV6_FALSE BUILD_IPV6_TRUE +BUILD_MCAST_FALSE +BUILD_MCAST_TRUE +BUILD_SCTP_FALSE +BUILD_SCTP_TRUE +BUILD_RNG_FALSE +BUILD_RNG_TRUE +BUILD_TLS13_FALSE +BUILD_TLS13_TRUE +BUILD_ALL_FALSE +BUILD_ALL_TRUE +BUILD_DISTRO_FALSE +BUILD_DISTRO_TRUE +IS_VCS_CHECKOUT_FALSE +IS_VCS_CHECKOUT_TRUE +IPPLINK +IPPHEADERS +IPPLIBS +HAVE_VALGRIND +HAVE_OPENSSL_CMD PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CC @@ -757,14 +897,9 @@ CCASFLAGS CCAS HAVE_VISIBILITY CFLAG_VISIBILITY -CXXCPP -am__fastdepCXX_FALSE -am__fastdepCXX_TRUE -CXXDEPMODE -ac_ct_CXX -CXXFLAGS -CXX +WOLFSSL_LIBRARY_VERSION CPP +LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO @@ -774,8 +909,6 @@ MANIFEST_TOOL RANLIB ac_ct_AR AR -DLLTOOL -OBJDUMP LN_S NM ac_ct_DUMPBIN @@ -785,6 +918,14 @@ FGREP EGREP GREP SED +LIBTOOL +OBJDUMP +DLLTOOL +AS +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE @@ -792,22 +933,8 @@ am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE -am__quote am__include DEPDIR -OBJEXT -EXEEXT -ac_ct_CC -CPPFLAGS -LDFLAGS -CFLAGS -CC -LIBTOOL -WOLFSSL_LIBRARY_VERSION -AM_BACKSLASH -AM_DEFAULT_VERBOSITY -AM_DEFAULT_V -AM_V am__untar am__tar AMTAR @@ -839,6 +966,13 @@ build_os build_vendor build_cpu build +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC target_alias host_alias build_alias @@ -876,110 +1010,235 @@ PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR -SHELL' +SHELL +am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking +enable_dependency_tracking enable_silent_rules enable_static enable_shared with_pic enable_fast_install -enable_dependency_tracking +with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock enable_debug +enable_distro +enable_all +enable_32bit +enable_16bit +enable_asm enable_singlethreaded enable_dtls +enable_dtls_mtu +enable_tls13_draft18 +enable_tls13_draft22 +enable_tls13_draft23 +enable_tls13_draft26 +enable_tls13_draft28 +enable_tls13 +enable_postauth +enable_hrrcookie +enable_rng +enable_sctp +enable_mcast +enable_openssh +enable_openvpn +enable_nginx +enable_haproxy +enable_wpas +enable_wpas_dpp +enable_fortress +enable_libwebsockets +enable_qt +enable_bump +enable_sniffer +enable_signal +enable_opensslcoexist +enable_opensslall enable_opensslextra enable_maxstrength +enable_harden enable_ipv6 -enable_fortress -enable_bump enable_leanpsk -enable_bigcache +enable_leantls +enable_lowresource +enable_titancache enable_hugecache +enable_bigcache enable_smallcache enable_savesession enable_savecert +enable_writedup enable_atomicuser enable_pkcallbacks -enable_sniffer +with_cryptoauthlib +enable_aescbc enable_aesgcm enable_aesccm +enable_aesctr +enable_aesofb +enable_aescfb +enable_armasm +enable_xilinx enable_aesni enable_intelasm +enable_intelrand +enable_afalg +enable_devcrypto enable_camellia enable_md2 enable_nullcipher enable_ripemd enable_blake2 +enable_blake2s enable_sha512 +enable_sha384 enable_sessioncerts enable_keygen enable_certgen enable_certreq +enable_certext +enable_certgencache enable_sep enable_hkdf +enable_x963kdf enable_dsa +enable_eccshamir enable_ecc +enable_ecccustcurves +enable_compkey enable_curve25519 enable_ed25519 +enable_curve448 +enable_ed448 enable_fpecc enable_eccencrypt enable_psk +enable_psk_one_id enable_errorstrings +enable_errorqueue enable_oldtls +enable_tlsv12 +enable_tlsv10 +enable_sslv3 enable_stacksize enable_memory +enable_trackmemory +enable_memorylog +enable_stacklog +enable_qt_test enable_rsa +enable_oaep +enable_rsapub +enable_rsavfy +enable_rsapss enable_dh enable_anon enable_asn enable_aes enable_coding +enable_base64encode +enable_base16 enable_des3 +enable_idea enable_arc4 enable_md5 enable_sha -enable_md4 +enable_cmac +enable_xts enable_webserver +enable_webclient enable_hc128 enable_rabbit enable_fips +enable_selftest +enable_sha224 +enable_sha3 +enable_shake256 enable_poly1305 enable_chacha enable_hashdrbg enable_filesystem enable_inline enable_ocsp +enable_ocspstapling +enable_ocspstapling2 enable_crl enable_crl_monitor +with_user_crypto with_ntru +enable_qsh +with_wnr enable_sni enable_maxfragment +enable_alpn +enable_trustedca enable_truncatedhmac enable_renegotiation_indication enable_secure_renegotiation +enable_fallback_scsv enable_supportedcurves +enable_ffdhe_only enable_session_ticket +enable_extended_master enable_tlsx +enable_earlydata enable_pkcs7 +enable_ssh enable_scep +enable_srp +enable_indef +enable_smallstackcache enable_smallstack enable_valgrind enable_testcert enable_iopool enable_certservice +enable_jni +enable_lighty +enable_asio +enable_apachehttpd +enable_enc_then_mac +enable_stunnel +enable_md4 +enable_enckeys enable_pwdbased +enable_scrypt +enable_cryptonly enable_fastmath enable_fasthugemath enable_examples +enable_crypttests with_libz +enable_pkcs11 +enable_pkcs12 with_cavium +with_cavium_v +with_octeon_sync +with_intelqa +with_intelqa_sync +enable_sp +enable_sp_asm +enable_sp_math +enable_fast_rsa +enable_staticmemory enable_mcapi -enable_jni +enable_asynccrypt +enable_asyncthreads +enable_cryptodev +enable_cryptocb +enable_sessionexport +enable_aeskeywrap +enable_oldnames +enable_memtest +enable_hashflags +enable_defaultdhparams +enable_usersettings +enable_optflags enable_jobserver ' ac_precious_vars='build_alias @@ -990,11 +1249,8 @@ CFLAGS LDFLAGS LIBS CPPFLAGS +LT_SYS_LIBRARY_PATH CPP -CXX -CXXFLAGS -CCC -CXXCPP CCAS CCASFLAGS' @@ -1537,7 +1793,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures wolfssl 3.6.0 to adapt to many kinds of systems. +\`configure' configures wolfssl 4.4.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1607,7 +1863,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of wolfssl 3.6.0:";; + short | recursive ) echo "Configuration of wolfssl 4.4.0:";; esac cat <<\_ACEOF @@ -1615,112 +1871,272 @@ Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-static[=PKGS] build static libraries [default=no] --enable-shared[=PKGS] build shared libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] - --enable-dependency-tracking - do not reject slow dependency extractors - --disable-dependency-tracking - speeds up one-time build --disable-libtool-lock avoid locking (might break parallel builds) --enable-debug Add debug code/turns off optimizations (yes|no) [default=no] + --enable-distro Enable wolfSSL distro build (default: disabled) + --enable-all Enable all wolfSSL features, except SSLv3 (default: + disabled) + --enable-32bit Enables 32-bit support (default: disabled) + --enable-16bit Enables 16-bit support (default: disabled) + --enable-asm Enables option for assembly (default: enabled) --enable-singlethreaded Enable wolfSSL single threaded (default: disabled) --enable-dtls Enable wolfSSL DTLS (default: disabled) - --enable-opensslextra Enable extra OpenSSL API, size+ (default: disabled) - --enable-maxstrength Enable Max Strengh build, allows TLSv1.2-AEAD-PFS - ciphers only (default: disabled) - --enable-ipv6 Enable testing of IPV6 (default: disabled) + --enable-dtls-mtu Enable setting the MTU size for wolfSSL DTLS + (default: disabled) + --enable-tls13-draft18 Enable wolfSSL TLS v1.3 Draft 18 (default: disabled) + --enable-tls13-draft22 Enable wolfSSL TLS v1.3 Draft 22 (default: disabled) + --enable-tls13-draft23 Enable wolfSSL TLS v1.3 Draft 23 (default: disabled) + --enable-tls13-draft26 Enable wolfSSL TLS v1.3 Draft 26 (default: disabled) + --enable-tls13-draft28 Enable wolfSSL TLS v1.3 Draft 28 (default: disabled) + --enable-tls13 Enable wolfSSL TLS v1.3 (default: disabled) + --enable-postauth Enable wolfSSL Post-handshake Authentication + (default: disabled) + --enable-hrrcookie Enable the server to send Cookie Extension in HRR + with state (default: disabled) + --enable-rng Enable compiling and using RNG (default: enabled) + --enable-sctp Enable wolfSSL DTLS-SCTP support (default: disabled) + --enable-mcast Enable wolfSSL DTLS multicast support (default: + disabled) + --enable-openssh Enable OpenSSH compatibility build (default: + disabled) + --enable-openvpn Enable OpenVPN compatibility build (default: + disabled) + --enable-nginx Enable nginx (default: disabled) + --enable-haproxy Enable haproxy (default: disabled) + --enable-wpas Enable wpa_supplicant support (default: disabled) + --enable-wpas-dpp Enable wpa_supplicant support with dpp (default: + disabled) --enable-fortress Enable SSL fortress build (default: disabled) + --enable-libwebsockets Enable libwebsockets (default: disabled) + --enable-qt Enable qt (default: disabled) --enable-bump Enable SSL Bump build (default: disabled) + --enable-sniffer Enable wolfSSL sniffer support (default: disabled) + --enable-signal Enable signal (default: disabled) + --enable-opensslcoexist Enable coexistence of wolfssl/openssl (default: + disabled) + --enable-opensslall Enable all OpenSSL API, size++ (default: disabled) + --enable-opensslextra Enable extra OpenSSL API, size+ (default: disabled) + --enable-maxstrength Enable Max Strength build, allows TLSv1.2-AEAD-PFS + ciphers only (default: disabled) + --enable-harden Enable Hardened build, Enables Timing Resistance and + Blinding (default: enabled) + --enable-ipv6 Enable testing of IPV6 (default: disabled) --enable-leanpsk Enable Lean PSK build (default: disabled) - --enable-bigcache Enable big session cache (default: disabled) + --enable-leantls Enable Lean TLS build (default: disabled) + --enable-lowresource Enable low resource options for memory/flash + (default: disabled) + --enable-titancache Enable titan session cache (default: disabled) --enable-hugecache Enable huge session cache (default: disabled) + --enable-bigcache Enable big session cache (default: disabled) --enable-smallcache Enable small session cache (default: disabled) --enable-savesession Enable persistent session cache (default: disabled) --enable-savecert Enable persistent cert cache (default: disabled) + --enable-writedup Enable write duplication of WOLFSSL objects + (default: disabled) --enable-atomicuser Enable Atomic User Record Layer (default: disabled) --enable-pkcallbacks Enable Public Key Callbacks (default: disabled) - --enable-sniffer Enable wolfSSL sniffer support (default: disabled) + --enable-aescbc Enable wolfSSL AES-CBC support (default: enabled) --enable-aesgcm Enable wolfSSL AES-GCM support (default: enabled) --enable-aesccm Enable wolfSSL AES-CCM support (default: disabled) + --enable-aesctr Enable wolfSSL AES-CTR support (default: disabled) + --enable-aesofb Enable wolfSSL AES-OFB support (default: disabled) + --enable-aescfb Enable wolfSSL AES-CFB support (default: disabled) + --enable-armasm Enable wolfSSL ARMv8 ASM support (default: disabled) + --enable-xilinx Enable wolfSSL support for Xilinx hardened + crypto(default: disabled) --enable-aesni Enable wolfSSL AES-NI support (default: disabled) --enable-intelasm Enable All Intel ASM speedups (default: disabled) + --enable-intelrand Enable Intel rdrand as preferred RNG source + (default: disabled) + --enable-afalg Enable Linux af_alg use for crypto (default: + disabled) + --enable-devcrypto Enable Linux dev crypto calls: all | aes (all aes + support) | hash (all hash algos) | cbc (aes-cbc + only) (default: disabled) --enable-camellia Enable wolfSSL Camellia support (default: disabled) --enable-md2 Enable wolfSSL MD2 support (default: disabled) - --enable-nullcipher Enable wolfSSL NULL cipher support (default: disabled) - --enable-ripemd Enable wolfSSL RIPEMD-160 support (default: disabled) - --enable-blake2 Enable wolfSSL BLAKE2 support (default: disabled) - --enable-sha512 Enable wolfSSL SHA-512 support (default: enabled on - x86_64) + --enable-nullcipher Enable wolfSSL NULL cipher support (default: + disabled) + --enable-ripemd Enable wolfSSL RIPEMD-160 support (default: + disabled) + --enable-blake2 Enable wolfSSL BLAKE2b support (default: disabled) + --enable-blake2s Enable wolfSSL BLAKE2s support (default: disabled) + --enable-sha512 Enable wolfSSL SHA-512 support (default: enabled) + --enable-sha384 Enable wolfSSL SHA-384 support (default: enabled) --enable-sessioncerts Enable session cert storing (default: disabled) --enable-keygen Enable key generation (default: disabled) --enable-certgen Enable cert generation (default: disabled) --enable-certreq Enable cert request generation (default: disabled) + --enable-certext Enable cert request extensions (default: disabled) + --enable-certgencache Enable decoded cert caching (default: disabled) --enable-sep Enable sep extensions (default: disabled) --enable-hkdf Enable HKDF (HMAC-KDF) support (default: disabled) + --enable-x963kdf Enable X9.63 KDF support (default: disabled) --enable-dsa Enable DSA (default: disabled) - --enable-ecc Enable ECC (default: enabled on x86_64) + --enable-eccshamir Enable ECC Shamir (default: enabled) + --enable-ecc Enable ECC (default: enabled) + --enable-ecccustcurves Enable ECC custom curves (default: disabled) + --enable-compkey Enable compressed keys support (default: disabled) --enable-curve25519 Enable Curve25519 (default: disabled) --enable-ed25519 Enable ED25519 (default: disabled) + --enable-curve448 Enable Curve448 (default: disabled) + --enable-ed448 Enable ED448 (default: disabled) --enable-fpecc Enable Fixed Point cache ECC (default: disabled) --enable-eccencrypt Enable ECC encrypt (default: disabled) --enable-psk Enable PSK (default: disabled) + --enable-psk-one-id Enable PSK (default: disabled) --enable-errorstrings Enable error strings table (default: enabled) + --disable-errorqueue Disables adding nodes to error queue when compiled + with OPENSSL_EXTRA (default: enabled) --enable-oldtls Enable old TLS versions < 1.2 (default: enabled) - --enable-stacksize Enable stack size info on examples (default: disabled) + --enable-tlsv12 Enable TLS versions 1.2 (default: enabled) + --enable-tlsv10 Enable old TLS versions 1.0 (default: disabled) + --enable-sslv3 Enable SSL version 3.0 (default: disabled) + --enable-stacksize Enable stack size info on examples (default: + disabled) --enable-memory Enable memory callbacks (default: enabled) + --enable-trackmemory Enable memory use info on wolfCrypt and wolfSSL + cleanup (default: disabled) + --enable-memorylog Enable dynamic memory logging (default: disabled) + --enable-stacklog Enable stack logging (default: disabled) + --enable-qt-test Enable qt tests (default: disabled) --enable-rsa Enable RSA (default: enabled) + --enable-oaep Enable RSA OAEP (default: enabled) + --enable-rsapub Enable RSA Public Only (default: disabled) + --enable-rsavfy Enable RSA Verify Inline Only (default: disabled) + --enable-rsapss Enable RSA-PSS (default: disabled) --enable-dh Enable DH (default: enabled) --enable-anon Enable Anonymous (default: disabled) --enable-asn Enable ASN (default: enabled) --enable-aes Enable AES (default: enabled) --enable-coding Enable Coding base 16/64 (default: enabled) - --enable-des3 Enable DES3 (default: enabled) + --enable-base64encode Enable Base64 encoding (default: enabled on x86_64) + --enable-base16 Enable Base16 encoding/decoding (default: disabled) + --enable-des3 Enable DES3 (default: disabled) + --enable-idea Enable IDEA Cipher (default: disabled) --enable-arc4 Enable ARC4 (default: disabled) --enable-md5 Enable MD5 (default: enabled) --enable-sha Enable SHA (default: enabled) - --enable-md4 Enable MD4 (default: disabled) + --enable-cmac Enable CMAC (default: disabled) + --enable-xts Enable XTS (default: disabled) --enable-webserver Enable Web Server (default: disabled) + --enable-webclient Enable Web Client (HTTP) (default: disabled) --enable-hc128 Enable HC-128 (default: disabled) --enable-rabbit Enable RABBIT (default: disabled) --enable-fips Enable FIPS 140-2, Will NOT work w/o FIPS license (default: disabled) + --enable-selftest Enable selftest, Will NOT work w/o CAVP selftest + license (default: disabled) + --enable-sha224 Enable wolfSSL SHA-224 support (default: enabled on + x86_64/aarch64) + --enable-sha3 Enable wolfSSL SHA-3 support (default: enabled on + x86_64/aarch64) + --enable-shake256 Enable wolfSSL SHAKE256 support (default: enabled on + x86_64/aarch64) --enable-poly1305 Enable wolfSSL POLY1305 support (default: enabled) - --enable-chacha Enable CHACHA (default: enabled) + --enable-chacha Enable CHACHA (default: enabled). Use `=noasm` to + disable ASM AVX/AVX2 speedups --enable-hashdrbg Enable Hash DRBG support (default: enabled) --enable-filesystem Enable Filesystem support (default: enabled) --enable-inline Enable inline functions (default: enabled) --enable-ocsp Enable OCSP (default: disabled) + --enable-ocspstapling Enable OCSP Stapling (default: disabled) + --enable-ocspstapling2 Enable OCSP Stapling v2 (default: disabled) --enable-crl Enable CRL (default: disabled) --enable-crl-monitor Enable CRL Monitor (default: disabled) + --enable-qsh Enable QSH (default: disabled) --enable-sni Enable SNI (default: disabled) --enable-maxfragment Enable Maximum Fragment Length (default: disabled) + --enable-alpn Enable ALPN (default: disabled) + --enable-trustedca Enable Trusted CA Indication (default: disabled) --enable-truncatedhmac Enable Truncated HMAC (default: disabled) --enable-renegotiation-indication Enable Renegotiation Indication (default: disabled) --enable-secure-renegotiation Enable Secure Renegotiation (default: disabled) + --enable-fallback-scsv Enable Fallback SCSV (default: disabled) --enable-supportedcurves - Enable Supported Elliptic Curves (default: disabled) + Enable Supported Elliptic Curves (default: enabled) + --enable-ffdhe-only Enable using only FFDHE in client (default: + disabled) --enable-session-ticket Enable Session Ticket (default: disabled) + --enable-extended-master + Enable Extended Master Secret (default: enabled) --enable-tlsx Enable all TLS Extensions (default: disabled) + --enable-earlydata Enable Early Data handshake with wolfSSL TLS v1.3 + (default: disabled) --enable-pkcs7 Enable PKCS7 (default: disabled) + --enable-ssh Enable wolfSSH options (default: disabled) --enable-scep Enable wolfSCEP (default: disabled) + --enable-srp Enable Secure Remote Password (default: disabled) + --enable-indef Enable parsing of indefinite length encoded msgs + (default: disabled) + --enable-smallstackcache + Enable Small Stack Usage Caching (default: disabled) --enable-smallstack Enable Small Stack Usage (default: disabled) --enable-valgrind Enable valgrind for unit tests (default: disabled) --enable-testcert Enable Test Cert (default: disabled) --enable-iopool Enable I/O Pool example (default: disabled) --enable-certservice Enable cert service (default: disabled) - --enable-pwdbased Enable PWDBASED (default: disabled) - --enable-fastmath Enable fast math ops (default: enabled on x86_64) - --enable-fasthugemath Enable fast math + huge code (default: disabled) - --enable-examples Enable Examples (default: enabled) - --enable-mcapi Enable Microchip API (default: disabled) --enable-jni Enable wolfSSL JNI (default: disabled) + --enable-lighty Enable lighttpd/lighty (default: disabled) + --enable-asio Enable asio (default: disabled) + --enable-apachehttpd Enable Apache httpd (default: disabled) + --enable-enc-then-mac Enable Encryptr-Then-Mac extension (default: + enabled) + --enable-stunnel Enable stunnel (default: disabled) + --enable-md4 Enable MD4 (default: disabled) + --enable-enckeys Enable PEM encrypted private key support (default: + disabled) + --enable-pwdbased Enable PWDBASED (default: disabled) + --enable-scrypt Enable SCRYPT (default: disabled) + --enable-cryptonly Enable wolfCrypt Only build (default: disabled) + --enable-fastmath Enable fast math ops (default: enabled on + x86_64/aarch64) + --enable-fasthugemath Enable fast math + huge code (default: disabled) + --enable-examples Enable Examples (default: enabled) + --enable-crypttests Enable Crypt Bench/Test (default: enabled) + --enable-pkcs11 Enable pkcs11 access (default: disabled) + --enable-pkcs12 Enable pkcs12 (default: enabled) + --enable-sp Enable Single Precision maths implementation + (default: disabled) + --enable-sp-asm Enable Single Precision assembly implementation + (default: disabled) + --enable-sp-math Enable Single Precision math implementation only + (default: disabled) + --enable-fast-rsa Enable RSA using Intel IPP (default: disabled) + --enable-staticmemory Enable static memory use (default: disabled) + --enable-mcapi Enable Microchip API (default: disabled) + --enable-asynccrypt Enable Asynchronous Crypto (default: disabled) + --enable-asyncthreads Enable Asynchronous Threading (default: enabled) + --enable-cryptodev DEPRECATED, use cryptocb instead + --enable-cryptocb Enable crypto callbacks (default: disabled) + --enable-sessionexport Enable export and import of sessions (default: + disabled) + --enable-aeskeywrap Enable AES key wrap support (default: disabled) + --enable-oldnames Keep backwards compat with old names (default: + enabled) + --enable-memtest Memory testing option, for internal use (default: + disabled) + --enable-hashflags Enable support for hash flags (default: disabled) + --enable-dhdefaultparams + Enables option for default dh parameters (default: + disabled) + --enable-usersettings Use your own user_settings.h and do not add Makefile + CFLAGS (default: disabled) + --enable-optflags Enable default optimization CFLAGS for the compiler + (default: enabled) --enable-jobserver[=no/yes/#] default=yes Enable up to # make jobs yes: enable one more than CPU count @@ -1731,12 +2147,25 @@ Optional Packages: --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] - --with-sysroot=DIR Search for dependent libraries within DIR - (or the compiler's sysroot if not specified). + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --with-cryptoauthlib=PATH + PATH to CryptoAuthLib install (default /usr/) + --with-user-crypto=PATH Path to USER_CRYPTO install (default /usr/local) --with-ntru=PATH Path to NTRU install (default /usr/) + --with-wnr=PATH Path to Whitewood netRandom install (default + /usr/local) --with-libz=PATH PATH to libz install (default /usr/) --with-cavium=PATH PATH to cavium/software dir + --with-cavium-v=PATH PATH to Cavium V/software dir + --with-octeon-sync=PATH PATH to Cavium Octeon SDK dir (sync) + --with-intelqa=PATH PATH to Intel QuickAssist (QAT) driver dir + --with-intelqa-sync=PATH + PATH to Intel QuickAssist (QAT) driver dir (sync) Some influential environment variables: CC C compiler command @@ -1746,10 +2175,9 @@ Some influential environment variables: LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. CPP C preprocessor - CXX C++ compiler command - CXXFLAGS C++ compiler flags - CXXCPP C++ preprocessor CCAS assembler compiler command (defaults to CC) CCASFLAGS assembler compiler flags (defaults to CFLAGS) @@ -1757,7 +2185,7 @@ Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . -wolfssl home page: . +wolfssl home page: . _ACEOF ac_status=$? fi @@ -1820,12 +2248,14 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -wolfssl configure 3.6.0 +wolfssl configure 4.4.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. + +Copyright (C) 2006-2020 wolfSSL Inc. _ACEOF exit fi @@ -2095,218 +2525,6 @@ $as_echo "$ac_res" >&6; } } # ac_fn_c_check_func -# ac_fn_cxx_try_compile LINENO -# ---------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_compile - -# ac_fn_cxx_try_cpp LINENO -# ------------------------ -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { - test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_cpp - -# ac_fn_cxx_try_link LINENO -# ------------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - test -x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_link - -# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists, giving a warning if it cannot be compiled using -# the include files in INCLUDES and setting the cache variable VAR -# accordingly. -ac_fn_c_check_header_mongrel () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if eval \${$3+:} false; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -else - # Is the header compilable? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 -$as_echo_n "checking $2 usability... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_header_compiler=yes -else - ac_header_compiler=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 -$as_echo "$ac_header_compiler" >&6; } - -# Is the header present? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 -$as_echo_n "checking $2 presence... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <$2> -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - ac_header_preproc=yes -else - ac_header_preproc=no -fi -rm -f conftest.err conftest.i conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 -$as_echo "$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( - yes:no: ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 -$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; - no:yes:* ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 -$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 -$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 -$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 -$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( $as_echo "## -------------------------------------------------------- ## -## Report this to https://github.com/wolfssl/wolfssl/issues ## -## -------------------------------------------------------- ##" - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=\$ac_header_compiler" -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_header_mongrel - # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes @@ -2544,6 +2762,97 @@ $as_echo "$ac_res" >&6; } } # ac_fn_c_check_type +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## -------------------------------------------------------- ## +## Report this to https://github.com/wolfssl/wolfssl/issues ## +## -------------------------------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + # ac_fn_c_find_uintX_t LINENO BITS VAR # ------------------------------------ # Finds an unsigned integer type with width BITS, setting cache variable VAR @@ -2601,7 +2910,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by wolfssl $as_me 3.6.0, which was +It was created by wolfssl $as_me 4.4.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2949,7 +3258,6 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu - ac_aux_dir= for ac_dir in build-aux "$srcdir"/build-aux; do if test -f "$ac_dir/install-sh"; then @@ -2980,950 +3288,18 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if ${ac_cv_build+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` -test "x$ac_build_alias" = x && - as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if ${ac_cv_host+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build -else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - - - - -am__api_version='1.14' - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -# Reject install programs that cannot install multiple files. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 -$as_echo_n "checking for a BSD-compatible install... " >&6; } -if test -z "$INSTALL"; then -if ${ac_cv_path_install+:} false; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in #(( - ./ | .// | /[cC]/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - rm -rf conftest.one conftest.two conftest.dir - echo one > conftest.one - echo two > conftest.two - mkdir conftest.dir - if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && - test -s conftest.one && test -s conftest.two && - test -s conftest.dir/conftest.one && - test -s conftest.dir/conftest.two - then - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - fi - done - done - ;; -esac - - done -IFS=$as_save_IFS - -rm -rf conftest.one conftest.two conftest.dir - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. Don't cache a - # value for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - INSTALL=$ac_install_sh - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 -$as_echo "$INSTALL" >&6; } - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 -$as_echo_n "checking whether build environment is sane... " >&6; } -# Reject unsafe characters in $srcdir or the absolute working directory -# name. Accept space and tab only in the latter. -am_lf=' -' -case `pwd` in - *[\\\"\#\$\&\'\`$am_lf]*) - as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; -esac -case $srcdir in - *[\\\"\#\$\&\'\`$am_lf\ \ ]*) - as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; -esac - -# Do 'set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - am_has_slept=no - for am_try in 1 2; do - echo "timestamp, slept: $am_has_slept" > conftest.file - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - if test "$*" != "X $srcdir/configure conftest.file" \ - && test "$*" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - as_fn_error $? "ls -t appears to fail. Make sure there is not a broken - alias in your environment" "$LINENO" 5 - fi - if test "$2" = conftest.file || test $am_try -eq 2; then - break - fi - # Just in case. - sleep 1 - am_has_slept=yes - done - test "$2" = conftest.file - ) -then - # Ok. - : -else - as_fn_error $? "newly created file is older than distributed files! -Check your system clock" "$LINENO" 5 -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -# If we didn't sleep, we still need to ensure time stamps of config.status and -# generated files are strictly newer. -am_sleep_pid= -if grep 'slept: no' conftest.file >/dev/null 2>&1; then - ( sleep 1 ) & - am_sleep_pid=$! -fi - -rm -f conftest.file - -test "$program_prefix" != NONE && - program_transform_name="s&^&$program_prefix&;$program_transform_name" -# Use a double $ so make ignores it. -test "$program_suffix" != NONE && - program_transform_name="s&\$&$program_suffix&;$program_transform_name" -# Double any \ or $. -# By default was `s,x,x', remove it if useless. -ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' -program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` - -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` - -if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac -fi -# Use eval to expand $SHELL -if eval "$MISSING --is-lightweight"; then - am_missing_run="$MISSING " -else - am_missing_run= - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 -$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} -fi - -if test x"${install_sh}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; - *) - install_sh="\${SHELL} $am_aux_dir/install-sh" - esac -fi - -# Installed binaries are usually stripped using 'strip' when the user -# run "make install-strip". However 'strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the 'STRIP' environment variable to overrule this program. -if test "$cross_compiling" != no; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 -$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } -if test -z "$MKDIR_P"; then - if ${ac_cv_path_mkdir+:} false; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in mkdir gmkdir; do - for ac_exec_ext in '' $ac_executable_extensions; do - as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue - case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( - 'mkdir (GNU coreutils) '* | \ - 'mkdir (coreutils) '* | \ - 'mkdir (fileutils) '4.1*) - ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext - break 3;; - esac - done - done - done -IFS=$as_save_IFS - -fi - - test -d ./--version && rmdir ./--version - if test "${ac_cv_path_mkdir+set}" = set; then - MKDIR_P="$ac_cv_path_mkdir -p" - else - # As a last resort, use the slow shell script. Don't cache a - # value for MKDIR_P within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - MKDIR_P="$ac_install_sh -d" - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 -$as_echo "$MKDIR_P" >&6; } - -for ac_prog in gawk mawk nawk awk -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AWK+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AWK="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AWK=$ac_cv_prog_AWK -if test -n "$AWK"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 -$as_echo "$AWK" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$AWK" && break -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } -set x ${MAKE-make} -ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat >conftest.make <<\_ACEOF -SHELL = /bin/sh -all: - @echo '@@@%%%=$(MAKE)=@@@%%%' -_ACEOF -# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. -case `${MAKE-make} -f conftest.make 2>/dev/null` in - *@@@%%%=?*=@@@%%%*) - eval ac_cv_prog_make_${ac_make}_set=yes;; - *) - eval ac_cv_prog_make_${ac_make}_set=no;; -esac -rm -f conftest.make -fi -if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - SET_MAKE= -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - SET_MAKE="MAKE=${MAKE-make}" -fi - -rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null - -# Check whether --enable-silent-rules was given. -if test "${enable_silent_rules+set}" = set; then : - enableval=$enable_silent_rules; -fi - -case $enable_silent_rules in # ((( - yes) AM_DEFAULT_VERBOSITY=0;; - no) AM_DEFAULT_VERBOSITY=1;; - *) AM_DEFAULT_VERBOSITY=1;; -esac -am_make=${MAKE-make} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 -$as_echo_n "checking whether $am_make supports nested variables... " >&6; } -if ${am_cv_make_support_nested_variables+:} false; then : - $as_echo_n "(cached) " >&6 -else - if $as_echo 'TRUE=$(BAR$(V)) -BAR0=false -BAR1=true -V=1 -am__doit: - @$(TRUE) -.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then - am_cv_make_support_nested_variables=yes -else - am_cv_make_support_nested_variables=no -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 -$as_echo "$am_cv_make_support_nested_variables" >&6; } -if test $am_cv_make_support_nested_variables = yes; then - AM_V='$(V)' - AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' -else - AM_V=$AM_DEFAULT_VERBOSITY - AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY -fi -AM_BACKSLASH='\' - -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - am__isrc=' -I$(srcdir)' - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi - - -# Define the identity of the package. - PACKAGE='wolfssl' - VERSION='3.6.0' - - -# Some tools Automake needs. - -ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} - - -AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} - - -AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} - - -AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} - - -MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} - -# For better backward compatibility. To be removed once Automake 1.9.x -# dies out for good. For more background, see: -# -# -mkdir_p='$(MKDIR_P)' - -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -# Always define AMTAR for backward compatibility. Yes, it's still used -# in the wild :-( We should find a proper way to deprecate it ... -AMTAR='$${TAR-tar}' - - -# We'll loop over all known methods to create a tar archive until one works. -_am_tools='gnutar plaintar pax cpio none' - -# The POSIX 1988 'ustar' format is defined with fixed-size fields. - # There is notably a 21 bits limit for the UID and the GID. In fact, - # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 - # and bug#13588). - am_max_uid=2097151 # 2^21 - 1 - am_max_gid=$am_max_uid - # The $UID and $GID variables are not portable, so we need to resort - # to the POSIX-mandated id(1) utility. Errors in the 'id' calls - # below are definitely unexpected, so allow the users to see them - # (that is, avoid stderr redirection). - am_uid=`id -u || echo unknown` - am_gid=`id -g || echo unknown` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 -$as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } - if test $am_uid -le $am_max_uid; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - _am_tools=none - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 -$as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } - if test $am_gid -le $am_max_gid; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - _am_tools=none - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 -$as_echo_n "checking how to create a ustar tar archive... " >&6; } - - # Go ahead even if we have the value already cached. We do so because we - # need to set the values for the 'am__tar' and 'am__untar' variables. - _am_tools=${am_cv_prog_tar_ustar-$_am_tools} - - for _am_tool in $_am_tools; do - case $_am_tool in - gnutar) - for _am_tar in tar gnutar gtar; do - { echo "$as_me:$LINENO: $_am_tar --version" >&5 - ($_am_tar --version) >&5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && break - done - am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' - am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' - am__untar="$_am_tar -xf -" - ;; - plaintar) - # Must skip GNU tar: if it does not support --format= it doesn't create - # ustar tarball either. - (tar --version) >/dev/null 2>&1 && continue - am__tar='tar chf - "$$tardir"' - am__tar_='tar chf - "$tardir"' - am__untar='tar xf -' - ;; - pax) - am__tar='pax -L -x ustar -w "$$tardir"' - am__tar_='pax -L -x ustar -w "$tardir"' - am__untar='pax -r' - ;; - cpio) - am__tar='find "$$tardir" -print | cpio -o -H ustar -L' - am__tar_='find "$tardir" -print | cpio -o -H ustar -L' - am__untar='cpio -i -H ustar -d' - ;; - none) - am__tar=false - am__tar_=false - am__untar=false - ;; - esac - - # If the value was cached, stop now. We just wanted to have am__tar - # and am__untar set. - test -n "${am_cv_prog_tar_ustar}" && break - - # tar/untar a dummy directory, and stop if the command works. - rm -rf conftest.dir - mkdir conftest.dir - echo GrepMe > conftest.dir/file - { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 - (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - rm -rf conftest.dir - if test -s conftest.tar; then - { echo "$as_me:$LINENO: $am__untar &5 - ($am__untar &5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 - (cat conftest.dir/file) >&5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - grep GrepMe conftest.dir/file >/dev/null 2>&1 && break - fi - done - rm -rf conftest.dir - - if ${am_cv_prog_tar_ustar+:} false; then : - $as_echo_n "(cached) " >&6 -else - am_cv_prog_tar_ustar=$_am_tool -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 -$as_echo "$am_cv_prog_tar_ustar" >&6; } - - - - - - -# POSIX will say in a future version that running "rm -f" with no argument -# is OK; and we want to be able to make that assumption in our Makefile -# recipes. So use an aggressive probe to check that the usage we want is -# actually supported "in the wild" to an acceptable degree. -# See automake bug#10828. -# To make any issue more visible, cause the running configure to be aborted -# by default if the 'rm' program in use doesn't match our expectations; the -# user can still override this though. -if rm -f && rm -fr && rm -rf; then : OK; else - cat >&2 <<'END' -Oops! - -Your 'rm' program seems unable to run without file operands specified -on the command line, even when the '-f' option is present. This is contrary -to the behaviour of most rm programs out there, and not conforming with -the upcoming POSIX standard: - -Please tell bug-automake@gnu.org about your system, including the value -of your $PATH and any error possibly output before this message. This -can help us improve future automake versions. - -END - if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then - echo 'Configuration will proceed anyway, since you have set the' >&2 - echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 - echo >&2 - else - cat >&2 <<'END' -Aborting the configuration process, to ensure you take notice of the issue. - -You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . - -If you want to complete the configuration process using your problematic -'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM -to "yes", and re-run configure. - -END - as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 - fi -fi - - - - -#PROTECT_AC_USE_SYSTEM_EXTENSIONS - - - -ac_config_headers="$ac_config_headers config.h:config.in" - -#shared library versioning -WOLFSSL_LIBRARY_VERSION=0:2:0 -# | | | -# +------+ | +---+ -# | | | -# current:revision:age -# | | | -# | | +- increment if interfaces have been added -# | | set to zero if interfaces have been removed -# | | or changed -# | +- increment if source code has changed -# | set to zero if current is incremented -# +- increment if interfaces have been added, removed or changed - - -# capture user C_EXTRA_FLAGS from ./configure line, CFLAGS may hold -g -O2 even -# if user doesn't override, no way to tell -USER_C_EXTRA_FLAGS="$C_EXTRA_FLAGS" - - -case `pwd` in - *\ * | *\ *) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 -$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; -esac - - - -macro_version='2.4.2' -macro_revision='1.3337' - - - - - - - - - - - - - -ltmain="$ac_aux_dir/ltmain.sh" - -# Backslashify metacharacters that are still active within -# double-quoted strings. -sed_quote_subst='s/\(["`$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 -$as_echo_n "checking how to print strings... " >&6; } -# Test print first, because it will be a builtin if present. -if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ - test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='print -r --' -elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='printf %s\n' -else - # Use this function as a fallback that always works. - func_fallback_echo () - { - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' - } - ECHO='func_fallback_echo' -fi - -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "" -} - -case "$ECHO" in - printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 -$as_echo "printf" >&6; } ;; - print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 -$as_echo "print -r" >&6; } ;; - *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 -$as_echo "cat" >&6; } ;; -esac - - - - - - - - - - - - - - -DEPDIR="${am__leading_dot}deps" - -ac_config_commands="$ac_config_commands depfiles" - - -am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo this is the am__doit target -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 -$as_echo_n "checking for style of include used by $am_make... " >&6; } -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD +# The following sets CFLAGS to empty if unset on command line. We do not +# want the default "-g -O2" that AC_PROG_CC sets automatically. +: ${CFLAGS=""} + +# Test ar for the "U" option. Should be checked before the libtool macros. +xxx_ar_flags=$(ar --help 2>&1) +case $xxx_ar_flags in #( + *'use actual timestamps and uids/gids'*) : + : ${AR_FLAGS="Ucru"} ;; #( + *) : ;; - esac -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 -$as_echo "$_am_result" >&6; } -rm -f confinc confmf - -# Check whether --enable-dependency-tracking was given. -if test "${enable_dependency_tracking+set}" = set; then : - enableval=$enable_dependency_tracking; -fi - -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' - am__nodep='_no' -fi - if test "x$enable_dependency_tracking" != xno; then - AMDEP_TRUE= - AMDEP_FALSE='#' -else - AMDEP_TRUE='#' - AMDEP_FALSE= -fi - +esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -4714,6 +4090,9 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -4773,6 +4152,783 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + + +am__api_version='1.16' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } +cat > confinc.mk << 'END' +am__doit: + @echo this is the am__doit target >confinc.out +.PHONY: am__doit +END +am__include="#" +am__quote= +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 + (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + case $?:`cat confinc.out 2>/dev/null` in #( + '0:this is the am__doit target') : + case $s in #( + BSD) : + am__include='.include' am__quote='"' ;; #( + *) : + am__include='include' am__quote='' ;; +esac ;; #( + *) : + ;; +esac + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +$as_echo "${_am_result}" >&6; } + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='wolfssl' + VERSION='4.4.0' + + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar plaintar pax cpio none' + +# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 +$as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } + if test $am_uid -le $am_max_uid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 +$as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } + if test $am_gid -le $am_max_gid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 +$as_echo_n "checking how to create a ustar tar archive... " >&6; } + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_ustar-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + { echo "$as_me:$LINENO: $_am_tar --version" >&5 + ($_am_tar --version) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && break + done + am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x ustar -w "$$tardir"' + am__tar_='pax -L -x ustar -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H ustar -L' + am__tar_='find "$tardir" -print | cpio -o -H ustar -L' + am__untar='cpio -i -H ustar -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_ustar}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 + (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + rm -rf conftest.dir + if test -s conftest.tar; then + { echo "$as_me:$LINENO: $am__untar &5 + ($am__untar &5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 + (cat conftest.dir/file) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + if ${am_cv_prog_tar_ustar+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_prog_tar_ustar=$_am_tool +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 +$as_echo "$am_cv_prog_tar_ustar" >&6; } + + + + + depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 @@ -4901,6 +5057,189 @@ else fi + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + + + + +ac_config_headers="$ac_config_headers config.h:config.in" + + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : @@ -5202,19 +5541,19 @@ test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld -if test "$GCC" = yes; then +if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw + # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; @@ -5228,7 +5567,7 @@ $as_echo_n "checking for ld used by $CC... " >&6; } while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done - test -z "$LD" && LD="$ac_prog" + test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. @@ -5239,7 +5578,7 @@ $as_echo_n "checking for ld used by $CC... " >&6; } with_gnu_ld=unknown ;; esac -elif test "$with_gnu_ld" = yes; then +elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else @@ -5250,32 +5589,32 @@ if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" + lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } @@ -5318,33 +5657,38 @@ if ${lt_cv_path_NM+:} false; then : else if test -n "$NM"; then # Let the user override the test. - lt_cv_path_NM="$NM" + lt_cv_path_NM=$NM else - lt_nm_to_check="${ac_tool_prefix}nm" + lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" - break + break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" - break + break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but @@ -5355,15 +5699,15 @@ else esac fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } -if test "$lt_cv_path_NM" != "no"; then - NM="$lt_cv_path_NM" +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : @@ -5469,9 +5813,9 @@ esac fi fi - case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) - DUMPBIN="$DUMPBIN -symbols" + DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: @@ -5479,8 +5823,8 @@ fi esac fi - if test "$DUMPBIN" != ":"; then - NM="$DUMPBIN" + if test : != "$DUMPBIN"; then + NM=$DUMPBIN fi fi test -z "$NM" && NM=nm @@ -5531,7 +5875,7 @@ if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 - teststring="ABCD" + teststring=ABCD case $build_os in msdosdjgpp*) @@ -5571,7 +5915,7 @@ else lt_cv_sys_max_cmd_len=8192; ;; - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` @@ -5621,22 +5965,23 @@ else ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len"; then + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8 ; do + for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && - test $i != 17 # 1/2 MB should be enough + test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring @@ -5654,7 +5999,7 @@ else fi -if test -n $lt_cv_sys_max_cmd_len ; then +if test -n "$lt_cv_sys_max_cmd_len"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else @@ -5672,30 +6017,6 @@ max_cmd_len=$lt_cv_sys_max_cmd_len : ${MV="mv -f"} : ${RM="rm -f"} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 -$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } -# Try some XSI features -xsi_shell=no -( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,b/c, \ - && eval 'test $(( 1 + 1 )) -eq 2 \ - && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ - && xsi_shell=yes -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 -$as_echo "$xsi_shell" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 -$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } -lt_shell_append=no -( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ - >/dev/null 2>&1 \ - && lt_shell_append=yes -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 -$as_echo "$lt_shell_append" >&6; } - - if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else @@ -5818,13 +6139,13 @@ esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) - if test "$GCC" != yes; then + if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) - if test "$GCC" = yes; then - reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi @@ -5938,9 +6259,6 @@ test -z "$OBJDUMP" && OBJDUMP=objdump - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : @@ -5952,13 +6270,13 @@ lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. +# 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given extended regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) @@ -5985,8 +6303,7 @@ mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. - # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. - if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else @@ -6022,10 +6339,6 @@ freebsd* | dragonfly*) fi ;; -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - haiku*) lt_cv_deplibs_check_method=pass_all ;; @@ -6064,7 +6377,7 @@ irix5* | irix6* | nonstopux*) ;; # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; @@ -6086,8 +6399,8 @@ newos6*) lt_cv_deplibs_check_method=pass_all ;; -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' @@ -6140,6 +6453,9 @@ sysv4 | sysv4.3*) tpf*) lt_cv_deplibs_check_method=pass_all ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; esac fi @@ -6285,9 +6601,6 @@ test -z "$DLLTOOL" && DLLTOOL=dlltool - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : @@ -6297,8 +6610,8 @@ else case $host_os in cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh - # decide which to use based on capabilities of $DLLTOOL + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib @@ -6310,7 +6623,7 @@ cygwin* | mingw* | pw32* | cegcc*) ;; *) # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd="$ECHO" + lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac @@ -6465,7 +6778,7 @@ if ac_fn_c_try_compile "$LINENO"; then : ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - if test "$ac_status" -eq 0; then + if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 @@ -6473,7 +6786,7 @@ if ac_fn_c_try_compile "$LINENO"; then : ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - if test "$ac_status" -ne 0; then + if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi @@ -6486,7 +6799,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } -if test "x$lt_cv_ar_at_file" = xno; then +if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file @@ -6703,7 +7016,7 @@ old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in - openbsd*) + bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) @@ -6793,7 +7106,7 @@ cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; @@ -6826,14 +7139,44 @@ case `$NM -V 2>&1` in symcode='[ABCDGIRSTW]' ;; esac +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -6851,21 +7194,24 @@ for ac_symprfx in "" "_"; do # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function - # and D for any global variable. + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ -" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ -" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ -" s[1]~/^[@?]/{print s[1], s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" @@ -6913,11 +7259,11 @@ _LT_EOF if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST -#elif defined(__osf__) +#elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else @@ -6943,7 +7289,7 @@ lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; @@ -6963,13 +7309,13 @@ _LT_EOF mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS - LIBS="conftstm.$ac_objext" + LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext}; then + test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS @@ -6990,7 +7336,7 @@ _LT_EOF rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then + if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= @@ -7032,6 +7378,16 @@ fi + + + + + + + + + + @@ -7055,9 +7411,9 @@ fi lt_sysroot= -case ${with_sysroot} in #( +case $with_sysroot in #( yes) - if test "$GCC" = yes; then + if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( @@ -7067,8 +7423,8 @@ case ${with_sysroot} in #( no|'') ;; #( *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 -$as_echo "${with_sysroot}" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac @@ -7080,18 +7436,99 @@ $as_echo "${lt_sysroot:-no}" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes +test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -7100,24 +7537,25 @@ ia64-*-hpux*) test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) - HPUX_IA64_MODE="32" + HPUX_IA64_MODE=32 ;; *ELF-64*) - HPUX_IA64_MODE="64" + HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - if test "$lt_cv_prog_gnu_ld" = yes; then + if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" @@ -7146,9 +7584,50 @@ ia64-*-hpux*) rm -rf conftest* ;; -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -7162,9 +7641,19 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) - LD="${LD-ld} -m elf_i386" + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac ;; - ppc64-*linux*|powerpc64-*linux*) + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -7183,7 +7672,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - ppc*-*linux*|powerpc*-*linux*) + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -7201,7 +7693,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" + SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } @@ -7241,13 +7733,14 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } - if test x"$lt_cv_cc_needs_belf" != x"yes"; then + if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" + CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -7259,7 +7752,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } case $lt_cv_prog_gnu_ld in yes*) case $host in - i?86-*-solaris*) + i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) @@ -7268,7 +7761,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD="${LD-ld}_sol2" + LD=${LD-ld}_sol2 fi ;; *) @@ -7284,7 +7777,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } ;; esac -need_locks="$enable_libtool_lock" +need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. @@ -7395,7 +7888,7 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } -if test "x$lt_cv_path_mainfest_tool" != xyes; then +if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi @@ -7898,7 +8391,7 @@ if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no - if test -z "${LT_MULTI_MODULE}"; then + if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the @@ -7916,7 +8409,7 @@ else cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. - elif test -f libconftest.dylib && test $_lt_result -eq 0; then + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 @@ -7955,7 +8448,7 @@ else fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 @@ -7984,7 +8477,7 @@ _LT_EOF _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 - elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 @@ -7997,32 +8490,32 @@ fi $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[012][,.]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then + if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi - if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= @@ -8030,6 +8523,41 @@ $as_echo "$lt_cv_ld_force_load" >&6; } ;; esac +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -8324,14 +8852,14 @@ if test "${enable_static+set}" = set; then : *) enable_static=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac else @@ -8344,14 +8872,312 @@ fi +enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. +set dummy ${ac_tool_prefix}as; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AS="${ac_tool_prefix}as" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AS=$ac_cv_prog_AS +if test -n "$AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 +$as_echo "$AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AS"; then + ac_ct_AS=$AS + # Extract the first word of "as", so it can be a program name with args. +set dummy as; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AS"; then + ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AS="as" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AS=$ac_cv_prog_ac_ct_AS +if test -n "$ac_ct_AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 +$as_echo "$ac_ct_AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AS" = x; then + AS="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AS=$ac_ct_AS + fi +else + AS="$ac_cv_prog_AS" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + + ;; +esac + +test -z "$AS" && AS=as + + + + + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + enable_dlopen=no - enable_win32_dll=no - # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : @@ -8362,14 +9188,14 @@ if test "${enable_shared+set}" = set; then : *) enable_shared=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac else @@ -8394,14 +9220,14 @@ if test "${with_pic+set}" = set; then : *) pic_mode=default # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac else @@ -8409,8 +9235,6 @@ else fi -test -z "$pic_mode" && pic_mode=default - @@ -8426,14 +9250,14 @@ if test "${enable_fast_install+set}" = set; then : *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac else @@ -8447,11 +9271,63 @@ fi + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + # This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ltmain" +LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' @@ -8500,7 +9376,7 @@ test -z "$LN_S" && LN_S="ln -s" -if test -n "${ZSH_VERSION+set}" ; then +if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi @@ -8539,7 +9415,7 @@ aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then + if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -8550,14 +9426,14 @@ esac ofile=libtool can_build_shared=yes -# All known linkers require a `.a' archive for static linking (except MSVC, +# All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a -with_gnu_ld="$lt_cv_prog_gnu_ld" +with_gnu_ld=$lt_cv_prog_gnu_ld -old_CC="$CC" -old_CFLAGS="$CFLAGS" +old_CC=$CC +old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc @@ -8566,15 +9442,8 @@ test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +func_cc_basename $compiler +cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it @@ -8589,22 +9458,22 @@ if ${lt_cv_path_MAGIC_CMD+:} false; then : else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/${ac_tool_prefix}file; then - lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -8627,13 +9496,13 @@ _LT_EOF break fi done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } @@ -8655,22 +9524,22 @@ if ${lt_cv_path_MAGIC_CMD+:} false; then : else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/file; then - lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -8693,13 +9562,13 @@ _LT_EOF break fi done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } @@ -8720,7 +9589,7 @@ esac # Use C for the default configuration in the libtool script -lt_save_CC="$CC" +lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -8782,7 +9651,7 @@ if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; @@ -8798,7 +9667,7 @@ else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -8828,7 +9697,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } -if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : @@ -8846,17 +9715,18 @@ lt_prog_compiler_pic= lt_prog_compiler_static= - if test "$GCC" = yes; then + if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi + lt_prog_compiler_pic='-fPIC' ;; amigaos*) @@ -8867,8 +9737,8 @@ lt_prog_compiler_static= ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -8884,6 +9754,11 @@ lt_prog_compiler_static= # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac ;; darwin* | rhapsody*) @@ -8954,7 +9829,7 @@ lt_prog_compiler_static= case $host_os in aix*) lt_prog_compiler_wl='-Wl,' - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else @@ -8962,10 +9837,29 @@ lt_prog_compiler_static= fi ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac ;; hpux9* | hpux10* | hpux11*) @@ -8981,7 +9875,7 @@ lt_prog_compiler_static= ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static='${wl}-a ${wl}archive' + lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) @@ -8990,9 +9884,9 @@ lt_prog_compiler_static= lt_prog_compiler_static='-non_shared' ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in - # old Intel for x86_64 which still supported -KPIC. + # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' @@ -9017,6 +9911,12 @@ lt_prog_compiler_static= lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) @@ -9114,7 +10014,7 @@ lt_prog_compiler_static= ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi @@ -9143,7 +10043,7 @@ lt_prog_compiler_static= fi case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: + # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; @@ -9175,7 +10075,7 @@ else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -9205,7 +10105,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } -if test x"$lt_cv_prog_compiler_pic_works" = xyes; then +if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; @@ -9237,7 +10137,7 @@ if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -9256,13 +10156,13 @@ else fi fi $RM -r conftest* - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } -if test x"$lt_cv_prog_compiler_static_works" = xyes; then +if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= @@ -9382,8 +10282,8 @@ $as_echo "$lt_cv_prog_compiler_c_o" >&6; } -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } @@ -9395,9 +10295,9 @@ $as_echo_n "checking if we can lock with hard links... " >&6; } ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } - if test "$hard_links" = no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else @@ -9440,9 +10340,9 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if @@ -9457,7 +10357,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. - if test "$GCC" != yes; then + if test yes != "$GCC"; then with_gnu_ld=no fi ;; @@ -9465,7 +10365,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; - openbsd*) + openbsd* | bitrig*) with_gnu_ld=no ;; esac @@ -9475,7 +10375,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility @@ -9497,24 +10397,24 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie esac fi - if test "$lt_use_gnu_ld_interface" = yes; then + if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' + wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no - case `$LD -v 2>&1` in + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... @@ -9527,7 +10427,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then + if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 @@ -9546,7 +10446,7 @@ _LT_EOF case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) @@ -9562,7 +10462,7 @@ _LT_EOF allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi @@ -9572,7 +10472,7 @@ _LT_EOF # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' - export_dynamic_flag_spec='${wl}--export-all-symbols' + export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes @@ -9580,61 +10480,89 @@ _LT_EOF exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no - if test "$host_os" = linux-dietlibc; then + if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test "$tmp_diet" = no + && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -9645,42 +10573,47 @@ _LT_EOF lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac - archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -9694,8 +10627,8 @@ _LT_EOF archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; @@ -9713,8 +10646,8 @@ _LT_EOF _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -9726,7 +10659,7 @@ _LT_EOF ld_shlibs=no cat <<_LT_EOF 1>&2 -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify @@ -9741,9 +10674,9 @@ _LT_EOF # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -9760,15 +10693,15 @@ _LT_EOF *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac - if test "$ld_shlibs" = no; then + if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= @@ -9784,7 +10717,7 @@ _LT_EOF # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported @@ -9792,34 +10725,57 @@ _LT_EOF ;; aix[4-9]*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag="" + no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global - # defined symbols, whereas GNU nm marks them as "W". + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi ;; esac @@ -9838,13 +10794,21 @@ _LT_EOF hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes - file_list_spec='${wl}-f,' + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac - if test "$GCC" = yes; then + if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` + collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -9863,35 +10827,42 @@ _LT_EOF ;; esac shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' else # not using gcc - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' else - shared_flag='${wl}-bM:SRE' + shared_flag='$wl-bM:SRE' fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' fi fi - export_dynamic_flag_spec='${wl}-bexpall' + export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes - if test "$aix_use_runtimelinking" = yes; then + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. - if test "${lt_cv_aix_libpath+set}" = set; then + if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : @@ -9926,7 +10897,7 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_="/usr/lib:/lib" + lt_cv_aix_libpath_=/usr/lib:/lib fi fi @@ -9934,17 +10905,17 @@ fi aix_libpath=$lt_cv_aix_libpath_ fi - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. - if test "${lt_cv_aix_libpath+set}" = set; then + if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : @@ -9979,7 +10950,7 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_="/usr/lib:/lib" + lt_cv_aix_libpath_=/usr/lib:/lib fi fi @@ -9987,21 +10958,33 @@ fi aix_libpath=$lt_cv_aix_libpath_ fi - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - no_undefined_flag=' ${wl}-bernotok' - allow_undefined_flag=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. - whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; @@ -10010,7 +10993,7 @@ fi case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) @@ -10040,16 +11023,17 @@ fi # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes @@ -10058,18 +11042,18 @@ fi # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) # Assume MSVC wrapper @@ -10078,7 +11062,7 @@ fi # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. @@ -10097,24 +11081,24 @@ fi hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported - if test "$lt_cv_ld_force_load" = "yes"; then - whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes - allow_undefined_flag="$_lt_dar_allow_undefined" + allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; + ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac - if test "$_lt_dar_can_shared" = "yes"; then + if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all - archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no @@ -10156,33 +11140,33 @@ fi ;; hpux9*) - if test "$GCC" = yes; then - archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else - archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes - export_dynamic_flag_spec='${wl}-E' + export_dynamic_flag_spec='$wl-E' ;; hpux10*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then - archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes - export_dynamic_flag_spec='${wl}-E' + export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes @@ -10190,25 +11174,25 @@ fi ;; hpux11*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then + if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) - archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) @@ -10220,7 +11204,7 @@ if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -10239,14 +11223,14 @@ else fi fi $RM -r conftest* - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } -if test x"$lt_cv_prog_compiler__b" = xyes; then - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi @@ -10254,8 +11238,8 @@ fi ;; esac fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in @@ -10266,7 +11250,7 @@ fi *) hardcode_direct=yes hardcode_direct_absolute=yes - export_dynamic_flag_spec='${wl}-E' + export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. @@ -10277,8 +11261,8 @@ fi ;; irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. @@ -10288,8 +11272,8 @@ $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " > if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } @@ -10301,24 +11285,34 @@ else fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } - if test "$lt_cv_irix_exported_symbol" = yes; then - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out @@ -10333,7 +11327,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; @@ -10341,27 +11335,19 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } *nto* | *qnx*) ;; - openbsd*) + openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-R$libdir' - ;; - *) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - esac + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no @@ -10372,33 +11358,53 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported - archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes ;; osf3*) - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' @@ -10409,24 +11415,24 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } solaris*) no_undefined_flag=' -z defs' - if test "$GCC" = yes; then - wlarc='${wl}' - archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) - wlarc='${wl}' - archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi @@ -10436,11 +11442,11 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', + # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi @@ -10450,10 +11456,10 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } ;; sunos4*) - if test "x$host_vendor" = xsequent; then + if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. - archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi @@ -10502,43 +11508,43 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag='${wl}-z,text' + no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not + # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - no_undefined_flag='${wl}-z,text' - allow_undefined_flag='${wl}-z,nodefs' + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes - export_dynamic_flag_spec='${wl}-Bexport' + export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; @@ -10553,10 +11559,10 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } ;; esac - if test x$host_vendor = xsni; then + if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - export_dynamic_flag_spec='${wl}-Blargedynsym' + export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi @@ -10564,7 +11570,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } -test "$ld_shlibs" = no && can_build_shared=no +test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld @@ -10590,7 +11596,7 @@ x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes - if test "$enable_shared" = yes && test "$GCC" = yes; then + if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. @@ -10805,14 +11811,14 @@ esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in - mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; - *) lt_sed_strip_eq="s,=/,/,g" ;; + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in @@ -10828,28 +11834,35 @@ if test "$GCC" = yes; then ;; esac # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. + # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; + lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } @@ -10863,7 +11876,7 @@ BEGIN {RS=" "; FS="/|\n";} { # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's,/\([A-Za-z]:\),\1,g'` ;; + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else @@ -10872,7 +11885,7 @@ fi library_names_spec= libname_spec='lib$name' soname_spec= -shrext_cmds=".so" +shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= @@ -10889,14 +11902,16 @@ hardcode_into_libs=no # flags to be left without arguments need_version=unknown + + case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' + soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) @@ -10904,41 +11919,91 @@ aix[4-9]*) need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac shlibpath_var=LIBPATH fi ;; @@ -10948,18 +12013,18 @@ amigaos*) powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) - library_names_spec='${libname}${shared_ext}' + library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; @@ -10967,8 +12032,8 @@ beos*) bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" @@ -10980,7 +12045,7 @@ bsdi[45]*) cygwin* | mingw* | pw32* | cegcc*) version_type=windows - shrext_cmds=".dll" + shrext_cmds=.dll need_version=no need_lib_prefix=no @@ -10989,8 +12054,8 @@ cygwin* | mingw* | pw32* | cegcc*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ @@ -11006,17 +12071,17 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' @@ -11025,8 +12090,8 @@ cygwin* | mingw* | pw32* | cegcc*) *,cl*) # Native MSVC libname_spec='$name' - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - library_names_spec='${libname}.dll.lib' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' case $build_os in mingw*) @@ -11053,7 +12118,7 @@ cygwin* | mingw* | pw32* | cegcc*) sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) - sys_lib_search_path_spec="$LIB" + sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` @@ -11066,8 +12131,8 @@ cygwin* | mingw* | pw32* | cegcc*) esac # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' @@ -11080,7 +12145,7 @@ cygwin* | mingw* | pw32* | cegcc*) *) # Assume MSVC wrapper - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac @@ -11093,8 +12158,8 @@ darwin* | rhapsody*) version_type=darwin need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' @@ -11107,8 +12172,8 @@ dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -11126,12 +12191,13 @@ freebsd* | dragonfly*) version_type=freebsd-$objformat case $version_type in freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac @@ -11156,26 +12222,15 @@ freebsd* | dragonfly*) esac ;; -gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=yes + shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -11193,14 +12248,15 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' @@ -11208,8 +12264,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; @@ -11218,8 +12274,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... @@ -11232,8 +12288,8 @@ interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -11244,7 +12300,7 @@ irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) - if test "$lt_cv_prog_gnu_ld" = yes; then + if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix @@ -11252,8 +12308,8 @@ irix5* | irix6* | nonstopux*) esac need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= @@ -11272,8 +12328,8 @@ irix5* | irix6* | nonstopux*) esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; @@ -11282,13 +12338,33 @@ linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -11332,7 +12408,12 @@ fi # before this can be enabled. hardcode_into_libs=yes - # Append ld.so.conf contents to the search path + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" @@ -11352,12 +12433,12 @@ netbsd*) need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH @@ -11367,7 +12448,7 @@ netbsd*) newsos6) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; @@ -11376,58 +12457,68 @@ newsos6) version_type=qnx need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; -openbsd*) +openbsd* | bitrig*) version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" + sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi + shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' - shrext_cmds=".dll" + version_type=windows + shrext_cmds=.dll + need_version=no need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) @@ -11438,8 +12529,8 @@ solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes @@ -11449,11 +12540,11 @@ solaris*) sunos4*) version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes @@ -11461,8 +12552,8 @@ sunos4*) sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) @@ -11483,24 +12574,24 @@ sysv4 | sysv4.3*) ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf + version_type=sco need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' @@ -11518,7 +12609,7 @@ tpf*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes @@ -11526,8 +12617,8 @@ tpf*) uts4*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -11537,20 +12628,35 @@ uts4*) esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no +test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then +if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + @@ -11647,15 +12753,15 @@ $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || - test "X$hardcode_automatic" = "Xyes" ; then + test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. - if test "$hardcode_direct" != no && + if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && - test "$hardcode_minus_L" != no; then + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else @@ -11670,12 +12776,12 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } -if test "$hardcode_action" = relink || - test "$inherit_rpath" = yes; then +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi @@ -11685,7 +12791,7 @@ fi - if test "x$enable_dlopen" != xyes; then + if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown @@ -11695,23 +12801,23 @@ else case $host_os in beos*) - lt_cv_dlopen="load_add_on" + lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) - lt_cv_dlopen="dlopen" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) - # if libdl is installed we need to link against it + # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : @@ -11749,10 +12855,10 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else - lt_cv_dlopen="dyld" + lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes @@ -11760,10 +12866,18 @@ fi ;; + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : - lt_cv_dlopen="shl_load" + lt_cv_dlopen=shl_load else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } @@ -11802,11 +12916,11 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" + lt_cv_dlopen=dlopen else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } @@ -11845,7 +12959,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } @@ -11884,7 +12998,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } @@ -11923,7 +13037,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi @@ -11944,21 +13058,21 @@ fi ;; esac - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else + if test no = "$lt_cv_dlopen"; then enable_dlopen=no + else + enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - save_LIBS="$LIBS" + save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 @@ -11966,7 +13080,7 @@ $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else - if test "$cross_compiling" = yes; then : + if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 @@ -12013,9 +13127,9 @@ else # endif #endif -/* When -fvisbility=hidden is used, assume the code has been annotated +/* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ -#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif @@ -12045,7 +13159,7 @@ _LT_EOF (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -12065,14 +13179,14 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } - if test "x$lt_cv_dlopen_self" = xyes; then + if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else - if test "$cross_compiling" = yes; then : + if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 @@ -12119,9 +13233,9 @@ else # endif #endif -/* When -fvisbility=hidden is used, assume the code has been annotated +/* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ -#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif @@ -12151,7 +13265,7 @@ _LT_EOF (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -12172,9 +13286,9 @@ fi $as_echo "$lt_cv_dlopen_self_static" >&6; } fi - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS ;; esac @@ -12218,7 +13332,7 @@ else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) - if test -n "$STRIP" ; then + if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 @@ -12246,7 +13360,7 @@ fi - # Report which library types will actually be built + # Report what library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 @@ -12254,13 +13368,13 @@ $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } - test "$can_build_shared" = "no" && enable_shared=no + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' @@ -12268,8 +13382,12 @@ $as_echo_n "checking whether to build shared libraries... " >&6; } ;; aix[4-9]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac @@ -12279,7 +13397,7 @@ $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes + test yes = "$enable_shared" || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } @@ -12293,7 +13411,7 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -CC="$lt_save_CC" +CC=$lt_save_CC @@ -12317,3592 +13435,26 @@ CC="$lt_save_CC" # Only expand once: -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -if test -z "$CXX"; then - if test -n "$CCC"; then - CXX=$CCC - else - if test -n "$ac_tool_prefix"; then - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CXX=$ac_cv_prog_CXX -if test -n "$CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 -$as_echo "$CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CXX" && break - done -fi -if test -z "$CXX"; then - ac_ct_CXX=$CXX - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CXX"; then - ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CXX="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CXX=$ac_cv_prog_ac_ct_CXX -if test -n "$ac_ct_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 -$as_echo "$ac_ct_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CXX" && break -done - - if test "x$ac_ct_CXX" = x; then - CXX="g++" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_ct_CXX - fi -fi - - fi -fi -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 -$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } -if ${ac_cv_cxx_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_cxx_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 -$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GXX=yes -else - GXX= -fi -ac_test_CXXFLAGS=${CXXFLAGS+set} -ac_save_CXXFLAGS=$CXXFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 -$as_echo_n "checking whether $CXX accepts -g... " >&6; } -if ${ac_cv_prog_cxx_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_cxx_werror_flag=$ac_cxx_werror_flag - ac_cxx_werror_flag=yes - ac_cv_prog_cxx_g=no - CXXFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_prog_cxx_g=yes -else - CXXFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -else - ac_cxx_werror_flag=$ac_save_cxx_werror_flag - CXXFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_prog_cxx_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cxx_werror_flag=$ac_save_cxx_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 -$as_echo "$ac_cv_prog_cxx_g" >&6; } -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS=$ac_save_CXXFLAGS -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -depcc="$CXX" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CXX_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CXX_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CXX_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CXX_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } -CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then - am__fastdepCXX_TRUE= - am__fastdepCXX_FALSE='#' -else - am__fastdepCXX_TRUE='#' - am__fastdepCXX_FALSE= -fi - - - - - -func_stripname_cnf () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; - esac -} # func_stripname_cnf - - if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 -$as_echo_n "checking how to run the C++ preprocessor... " >&6; } -if test -z "$CXXCPP"; then - if ${ac_cv_prog_CXXCPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CXXCPP needs to be expanded - for CXXCPP in "$CXX -E" "/lib/cpp" - do - ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CXXCPP=$CXXCPP - -fi - CXXCPP=$ac_cv_prog_CXXCPP -else - ac_cv_prog_CXXCPP=$CXXCPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 -$as_echo "$CXXCPP" >&6; } -ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -else - _lt_caught_CXX_error=yes -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -archive_cmds_need_lc_CXX=no -allow_undefined_flag_CXX= -always_export_symbols_CXX=no -archive_expsym_cmds_CXX= -compiler_needs_object_CXX=no -export_dynamic_flag_spec_CXX= -hardcode_direct_CXX=no -hardcode_direct_absolute_CXX=no -hardcode_libdir_flag_spec_CXX= -hardcode_libdir_separator_CXX= -hardcode_minus_L_CXX=no -hardcode_shlibpath_var_CXX=unsupported -hardcode_automatic_CXX=no -inherit_rpath_CXX=no -module_cmds_CXX= -module_expsym_cmds_CXX= -link_all_deplibs_CXX=unknown -old_archive_cmds_CXX=$old_archive_cmds -reload_flag_CXX=$reload_flag -reload_cmds_CXX=$reload_cmds -no_undefined_flag_CXX= -whole_archive_flag_spec_CXX= -enable_shared_with_static_runtimes_CXX=no - -# Source file extension for C++ test sources. -ac_ext=cpp - -# Object file extension for compiled C++ test sources. -objext=o -objext_CXX=$objext - -# No sense in running all these tests if we already determined that -# the CXX compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_caught_CXX_error" != yes; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="int some_variable = 0;" - - # Code to be used in simple link tests - lt_simple_link_test_code='int main(int, char *[]) { return(0); }' - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - - - - - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - - # save warnings/boilerplate of simple test code - ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$RM conftest* - - ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$RM -r conftest* - - - # Allow CC to be a program name with arguments. - lt_save_CC=$CC - lt_save_CFLAGS=$CFLAGS - lt_save_LD=$LD - lt_save_GCC=$GCC - GCC=$GXX - lt_save_with_gnu_ld=$with_gnu_ld - lt_save_path_LD=$lt_cv_path_LD - if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx - else - $as_unset lt_cv_prog_gnu_ld - fi - if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX - else - $as_unset lt_cv_path_LD - fi - test -z "${LDCXX+set}" || LD=$LDCXX - CC=${CXX-"c++"} - CFLAGS=$CXXFLAGS - compiler=$CC - compiler_CXX=$CC - for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` - - - if test -n "$compiler"; then - # We don't want -fno-exception when compiling C++ code, so set the - # no_builtin_flag separately - if test "$GXX" = yes; then - lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' - else - lt_prog_compiler_no_builtin_flag_CXX= - fi - - if test "$GXX" = yes; then - # Set up default GNU C++ configuration - - - -# Check whether --with-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes -else - with_gnu_ld=no -fi - -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 -$as_echo_n "checking for ld used by $CC... " >&6; } - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` - while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do - ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 -$as_echo_n "checking for GNU ld... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 -$as_echo_n "checking for non-GNU ld... " >&6; } -fi -if ${lt_cv_path_LD+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -$as_echo "$LD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 -$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } -if ${lt_cv_prog_gnu_ld+:} false; then : - $as_echo_n "(cached) " >&6 -else - # I'd rather use --version here, but apparently some GNU lds only accept -v. -case `$LD -v 2>&1 &5 -$as_echo "$lt_cv_prog_gnu_ld" >&6; } -with_gnu_ld=$lt_cv_prog_gnu_ld - - - - - - - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='${wl}' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | - $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_CXX= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - - else - GXX=no - with_gnu_ld=no - wlarc= - fi - - # PORTME: fill in a description of your system's C++ link characteristics - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } - ld_shlibs_CXX=yes - case $host_os in - aix3*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aix[4-9]*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds_CXX='' - hardcode_direct_CXX=yes - hardcode_direct_absolute_CXX=yes - hardcode_libdir_separator_CXX=':' - link_all_deplibs_CXX=yes - file_list_spec_CXX='${wl}-f,' - - if test "$GXX" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - hardcode_direct_CXX=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L_CXX=yes - hardcode_libdir_flag_spec_CXX='-L$libdir' - hardcode_libdir_separator_CXX= - fi - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - export_dynamic_flag_spec_CXX='${wl}-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to - # export. - always_export_symbols_CXX=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag_CXX='-berok' - # Determine the default libpath from the value encoded in an empty - # executable. - if test "${lt_cv_aix_libpath+set}" = set; then - aix_libpath=$lt_cv_aix_libpath -else - if ${lt_cv_aix_libpath__CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - - lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }' - lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX="/usr/lib:/lib" - fi - -fi - - aix_libpath=$lt_cv_aix_libpath__CXX -fi - - hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" - - archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag_CXX="-z nodefs" - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - if test "${lt_cv_aix_libpath+set}" = set; then - aix_libpath=$lt_cv_aix_libpath -else - if ${lt_cv_aix_libpath__CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - - lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }' - lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX="/usr/lib:/lib" - fi - -fi - - aix_libpath=$lt_cv_aix_libpath__CXX -fi - - hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag_CXX=' ${wl}-bernotok' - allow_undefined_flag_CXX=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then - # We only use this code for GNU lds that support --whole-archive. - whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - else - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_CXX='$convenience' - fi - archive_cmds_need_lc_CXX=yes - # This is similar to how AIX traditionally builds its shared - # libraries. - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag_CXX=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs_CXX=no - fi - ;; - - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - cygwin* | mingw* | pw32* | cegcc*) - case $GXX,$cc_basename in - ,cl* | no,cl*) - # Native MSVC - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec_CXX=' ' - allow_undefined_flag_CXX=unsupported - always_export_symbols_CXX=yes - file_list_spec_CXX='@' - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' - # The linker will not automatically build a static lib if we build a DLL. - # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' - enable_shared_with_static_runtimes_CXX=yes - # Don't use ranlib - old_postinstall_cmds_CXX='chmod 644 $oldlib' - postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - func_to_tool_file "$lt_outputfile"~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' - ;; - *) - # g++ - # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_CXX='-L$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-all-symbols' - allow_undefined_flag_CXX=unsupported - always_export_symbols_CXX=no - enable_shared_with_static_runtimes_CXX=yes - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs_CXX=no - fi - ;; - esac - ;; - darwin* | rhapsody*) - - - archive_cmds_need_lc_CXX=no - hardcode_direct_CXX=no - hardcode_automatic_CXX=yes - hardcode_shlibpath_var_CXX=unsupported - if test "$lt_cv_ld_force_load" = "yes"; then - whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' - - else - whole_archive_flag_spec_CXX='' - fi - link_all_deplibs_CXX=yes - allow_undefined_flag_CXX="$_lt_dar_allow_undefined" - case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; - *) _lt_dar_can_shared=$GCC ;; - esac - if test "$_lt_dar_can_shared" = "yes"; then - output_verbose_link_cmd=func_echo_all - archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" - if test "$lt_cv_apple_cc_single_mod" != "yes"; then - archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" - archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" - fi - - else - ld_shlibs_CXX=no - fi - - ;; - - dgux*) - case $cc_basename in - ec++*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - ghcx*) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - freebsd2.*) - # C++ shared libraries reported to be fairly broken before - # switch to ELF - ld_shlibs_CXX=no - ;; - - freebsd-elf*) - archive_cmds_need_lc_CXX=no - ;; - - freebsd* | dragonfly*) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - ld_shlibs_CXX=yes - ;; - - gnu*) - ;; - - haiku*) - archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - link_all_deplibs_CXX=yes - ;; - - hpux9*) - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_CXX=: - export_dynamic_flag_spec_CXX='${wl}-E' - hardcode_direct_CXX=yes - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aCC*) - archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test "$GXX" = yes; then - archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - - hpux10*|hpux11*) - if test $with_gnu_ld = no; then - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - case $host_cpu in - hppa*64*|ia64*) - ;; - *) - export_dynamic_flag_spec_CXX='${wl}-E' - ;; - esac - fi - case $host_cpu in - hppa*64*|ia64*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - ;; - *) - hardcode_direct_CXX=yes - hardcode_direct_absolute_CXX=yes - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aCC*) - case $host_cpu in - hppa*64*) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then - case $host_cpu in - hppa*64*) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - - interix[3-9]*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - irix5* | irix6*) - case $cc_basename in - CC*) - # SGI C++ - archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' - fi - fi - link_all_deplibs_CXX=yes - ;; - esac - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - inherit_rpath_CXX=yes - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc* | ecpc* ) - # Intel C++ - with_gnu_ld=yes - # version 8.0 and above of icpc choke on multiply defined symbols - # if we add $predep_objects and $postdep_objects, however 7.1 and - # earlier do not add the objects themselves. - case `$CC -V 2>&1` in - *"Version 7."*) - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 8.0 or newer - tmp_idyn= - case $host_cpu in - ia64*) tmp_idyn=' -i_dynamic';; - esac - archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - archive_cmds_need_lc_CXX=no - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - case `$CC -V` in - *pgCC\ [1-5].* | *pgcpp\ [1-5].*) - prelink_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' - old_archive_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ - $RANLIB $oldlib' - archive_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - archive_expsym_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - ;; - *) # Version 6 and above use weak symbols - archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - ;; - esac - - hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - ;; - cxx*) - # Compaq C++ - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_CXX='-rpath $libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' - ;; - xl* | mpixl* | bgxl*) - # IBM XL 8.0 on PPC, with GNU ld - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then - archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' - hardcode_libdir_flag_spec_CXX='-R$libdir' - whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' - compiler_needs_object_CXX=yes - - # Not sure whether something based on - # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 - # would be better. - output_verbose_link_cmd='func_echo_all' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' - ;; - esac - ;; - esac - ;; - - lynxos*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - - m88k*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - - mvs*) - case $cc_basename in - cxx*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - hardcode_libdir_flag_spec_CXX='-R$libdir' - hardcode_direct_CXX=yes - hardcode_shlibpath_var_CXX=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - - *nto* | *qnx*) - ld_shlibs_CXX=yes - ;; - - openbsd2*) - # C++ shared libraries are fairly broken - ld_shlibs_CXX=no - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - hardcode_direct_CXX=yes - hardcode_shlibpath_var_CXX=no - hardcode_direct_absolute_CXX=yes - archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - export_dynamic_flag_spec_CXX='${wl}-E' - whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - fi - output_verbose_link_cmd=func_echo_all - else - ld_shlibs_CXX=no - fi - ;; - - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - hardcode_libdir_separator_CXX=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - case $host in - osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; - *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; - esac - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - cxx*) - case $host in - osf3*) - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - ;; - *) - allow_undefined_flag_CXX=' -expect_unresolved \*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ - $RM $lib.exp' - hardcode_libdir_flag_spec_CXX='-rpath $libdir' - ;; - esac - - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - case $host in - osf3*) - archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - ;; - *) - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - ;; - esac - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - - psos*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - lcc*) - # Lucid - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - solaris*) - case $cc_basename in - CC* | sunCC*) - # Sun C++ 4.2, 5.x and Centerline C++ - archive_cmds_need_lc_CXX=yes - no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - hardcode_libdir_flag_spec_CXX='-R$libdir' - hardcode_shlibpath_var_CXX=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. - # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' - ;; - esac - link_all_deplibs_CXX=yes - - output_verbose_link_cmd='func_echo_all' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' - ;; - gcx*) - # Green Hills C++ Compiler - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - no_undefined_flag_CXX=' ${wl}-z ${wl}defs' - if $CC --version | $GREP -v '^2\.7' > /dev/null; then - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - else - # g++ 2.7 appears to require `-G' NOT `-shared' on this - # platform. - archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - fi - - hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - ;; - esac - fi - ;; - esac - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag_CXX='${wl}-z,text' - archive_cmds_need_lc_CXX=no - hardcode_shlibpath_var_CXX=no - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - no_undefined_flag_CXX='${wl}-z,text' - allow_undefined_flag_CXX='${wl}-z,nodefs' - archive_cmds_need_lc_CXX=no - hardcode_shlibpath_var_CXX=no - hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir' - hardcode_libdir_separator_CXX=':' - link_all_deplibs_CXX=yes - export_dynamic_flag_spec_CXX='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ - '"$old_archive_cmds_CXX" - reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ - '"$reload_cmds_CXX" - ;; - *) - archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - vxworks*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 -$as_echo "$ld_shlibs_CXX" >&6; } - test "$ld_shlibs_CXX" = no && can_build_shared=no - - GCC_CXX="$GXX" - LD_CXX="$LD" - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - # Dependencies to place before and after the object being linked: -predep_objects_CXX= -postdep_objects_CXX= -predeps_CXX= -postdeps_CXX= -compiler_lib_search_path_CXX= - -cat > conftest.$ac_ext <<_LT_EOF -class Foo -{ -public: - Foo (void) { a = 0; } -private: - int a; -}; -_LT_EOF - - -_lt_libdeps_save_CFLAGS=$CFLAGS -case "$CC $CFLAGS " in #( -*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; -*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; -*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; -esac - -if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - # Parse the compiler output and extract the necessary - # objects, libraries and library flags. - - # Sentinel used to keep track of whether or not we are before - # the conftest object file. - pre_test_object_deps_done=no - - for p in `eval "$output_verbose_link_cmd"`; do - case ${prev}${p} in - - -L* | -R* | -l*) - # Some compilers place space between "-{L,R}" and the path. - # Remove the space. - if test $p = "-L" || - test $p = "-R"; then - prev=$p - continue - fi - - # Expand the sysroot to ease extracting the directories later. - if test -z "$prev"; then - case $p in - -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; - -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; - -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; - esac - fi - case $p in - =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; - esac - if test "$pre_test_object_deps_done" = no; then - case ${prev} in - -L | -R) - # Internal compiler library paths should come after those - # provided the user. The postdeps already come after the - # user supplied libs so there is no need to process them. - if test -z "$compiler_lib_search_path_CXX"; then - compiler_lib_search_path_CXX="${prev}${p}" - else - compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" - fi - ;; - # The "-l" case would never come before the object being - # linked, so don't bother handling this case. - esac - else - if test -z "$postdeps_CXX"; then - postdeps_CXX="${prev}${p}" - else - postdeps_CXX="${postdeps_CXX} ${prev}${p}" - fi - fi - prev= - ;; - - *.lto.$objext) ;; # Ignore GCC LTO objects - *.$objext) - # This assumes that the test object file only shows up - # once in the compiler output. - if test "$p" = "conftest.$objext"; then - pre_test_object_deps_done=yes - continue - fi - - if test "$pre_test_object_deps_done" = no; then - if test -z "$predep_objects_CXX"; then - predep_objects_CXX="$p" - else - predep_objects_CXX="$predep_objects_CXX $p" - fi - else - if test -z "$postdep_objects_CXX"; then - postdep_objects_CXX="$p" - else - postdep_objects_CXX="$postdep_objects_CXX $p" - fi - fi - ;; - - *) ;; # Ignore the rest. - - esac - done - - # Clean up. - rm -f a.out a.exe -else - echo "libtool.m4: error: problem compiling CXX test program" -fi - -$RM -f confest.$objext -CFLAGS=$_lt_libdeps_save_CFLAGS - -# PORTME: override above test on systems where it is broken -case $host_os in -interix[3-9]*) - # Interix 3.5 installs completely hosed .la files for C++, so rather than - # hack all around it, let's just trust "g++" to DTRT. - predep_objects_CXX= - postdep_objects_CXX= - postdeps_CXX= - ;; - -linux*) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - if test "$solaris_use_stlport4" != yes; then - postdeps_CXX='-library=Cstd -library=Crun' - fi - ;; - esac - ;; - -solaris*) - case $cc_basename in - CC* | sunCC*) - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - # Adding this requires a known-good setup of shared libraries for - # Sun compiler versions before 5.6, else PIC objects from an old - # archive will be linked into the output, leading to subtle bugs. - if test "$solaris_use_stlport4" != yes; then - postdeps_CXX='-library=Cstd -library=Crun' - fi - ;; - esac - ;; -esac - - -case " $postdeps_CXX " in -*" -lc "*) archive_cmds_need_lc_CXX=no ;; -esac - compiler_lib_search_dirs_CXX= -if test -n "${compiler_lib_search_path_CXX}"; then - compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - lt_prog_compiler_wl_CXX= -lt_prog_compiler_pic_CXX= -lt_prog_compiler_static_CXX= - - - # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - lt_prog_compiler_pic_CXX='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - lt_prog_compiler_pic_CXX='-DDLL_EXPORT' - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic_CXX='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - lt_prog_compiler_pic_CXX= - ;; - haiku*) - # PIC is the default for Haiku. - # The "-static" flag exists, but is broken. - lt_prog_compiler_static_CXX= - ;; - interix[3-9]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic_CXX=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - ;; - *) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - esac - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - lt_prog_compiler_pic_CXX='-fPIC -shared' - ;; - *) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - esac - else - case $host_os in - aix[4-9]*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - else - lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68*) - # Green Hills C++ Compiler - # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_CXX='-DDLL_EXPORT' - ;; - dgux*) - case $cc_basename in - ec++*) - lt_prog_compiler_pic_CXX='-KPIC' - ;; - ghcx*) - # Green Hills C++ Compiler - lt_prog_compiler_pic_CXX='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | dragonfly*) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' - if test "$host_cpu" != ia64; then - lt_prog_compiler_pic_CXX='+Z' - fi - ;; - aCC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_CXX='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - interix*) - # This is c89, which is MS Visual C++ (no shared libs) - # Anyone wants to do a port? - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) - case $cc_basename in - KCC*) - # KAI C++ Compiler - lt_prog_compiler_wl_CXX='--backend -Wl,' - lt_prog_compiler_pic_CXX='-fPIC' - ;; - ecpc* ) - # old Intel C++ for x86_64 which still supported -KPIC. - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-static' - ;; - icpc* ) - # Intel C++, used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-fPIC' - lt_prog_compiler_static_CXX='-static' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-fpic' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - cxx*) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - lt_prog_compiler_pic_CXX= - lt_prog_compiler_static_CXX='-non_shared' - ;; - xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) - # IBM XL 8.0, 9.0 on PPC and BlueGene - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-qpic' - lt_prog_compiler_static_CXX='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - lt_prog_compiler_wl_CXX='-Qoption ld ' - ;; - esac - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx*) - lt_prog_compiler_pic_CXX='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd*) - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - lt_prog_compiler_pic_CXX='-fPIC -shared' - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - lt_prog_compiler_wl_CXX='--backend -Wl,' - ;; - RCC*) - # Rational C++ 2.4.1 - lt_prog_compiler_pic_CXX='-pic' - ;; - cxx*) - # Digital/Compaq C++ - lt_prog_compiler_wl_CXX='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - lt_prog_compiler_pic_CXX= - lt_prog_compiler_static_CXX='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - solaris*) - case $cc_basename in - CC* | sunCC*) - # Sun C++ 4.2, 5.x and Centerline C++ - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - lt_prog_compiler_wl_CXX='-Qoption ld ' - ;; - gcx*) - # Green Hills C++ Compiler - lt_prog_compiler_pic_CXX='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - lt_prog_compiler_pic_CXX='-pic' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - lcc*) - # Lucid - lt_prog_compiler_pic_CXX='-pic' - ;; - *) - ;; - esac - ;; - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - lt_prog_compiler_pic_CXX='-KPIC' - ;; - *) - ;; - esac - ;; - vxworks*) - ;; - *) - lt_prog_compiler_can_build_shared_CXX=no - ;; - esac - fi - -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic_CXX= - ;; - *) - lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" - ;; -esac - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 -$as_echo_n "checking for $compiler option to produce PIC... " >&6; } -if ${lt_cv_prog_compiler_pic_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } -lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 -$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } -if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_pic_works_CXX=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_pic_works_CXX=yes - fi - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } - -if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then - case $lt_prog_compiler_pic_CXX in - "" | " "*) ;; - *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; - esac -else - lt_prog_compiler_pic_CXX= - lt_prog_compiler_can_build_shared_CXX=no -fi - -fi - - - - - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } -if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_static_works_CXX=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_static_works_CXX=yes - fi - else - lt_cv_prog_compiler_static_works_CXX=yes - fi - fi - $RM -r conftest* - LDFLAGS="$save_LDFLAGS" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } - -if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then - : -else - lt_prog_compiler_static_CXX= -fi - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_c_o_CXX=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o_CXX=yes - fi - fi - chmod u+w . 2>&5 - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_c_o_CXX=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o_CXX=yes - fi - fi - chmod u+w . 2>&5 - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 -$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } - - - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 -$as_echo_n "checking if we can lock with hard links... " >&6; } - hard_links=yes - $RM conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 -$as_echo "$hard_links" >&6; } - if test "$hard_links" = no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } - - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' - case $host_os in - aix[4-9]*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global defined - # symbols, whereas GNU nm marks them as "W". - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - export_symbols_cmds_CXX="$ltdll_cmds" - ;; - cygwin* | mingw* | cegcc*) - case $cc_basename in - cl*) - exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' - ;; - *) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' - exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' - ;; - esac - ;; - *) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 -$as_echo "$ld_shlibs_CXX" >&6; } -test "$ld_shlibs_CXX" = no && can_build_shared=no - -with_gnu_ld_CXX=$with_gnu_ld - - - - - - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc_CXX" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc_CXX=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds_CXX in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 -$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } -if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_CXX - pic_flag=$lt_prog_compiler_pic_CXX - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_CXX - allow_undefined_flag_CXX= - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 - (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - then - lt_cv_archive_cmds_need_lc_CXX=no - else - lt_cv_archive_cmds_need_lc_CXX=yes - fi - allow_undefined_flag_CXX=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 -$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } - archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX - ;; - esac - fi - ;; -esac - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 -$as_echo_n "checking dynamic linker characteristics... " >&6; } - -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix[4-9]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - case $host_cpu in - powerpc) - # Since July 2007 AmigaOS4 officially supports .so libraries. - # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - ;; - m68k) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - esac - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32* | cegcc*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$cc_basename in - yes,*) - # gcc - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - - ;; - mingw* | cegcc*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - dynamic_linker='Win32 ld.exe' - ;; - - *,cl*) - # Native MSVC - libname_spec='$name' - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - library_names_spec='${libname}.dll.lib' - - case $build_os in - mingw*) - sys_lib_search_path_spec= - lt_save_ifs=$IFS - IFS=';' - for lt_path in $LIB - do - IFS=$lt_save_ifs - # Let DOS variable expansion print the short 8.3 style file name. - lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` - sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" - done - IFS=$lt_save_ifs - # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` - ;; - cygwin*) - # Convert to unix form, then to dos form, then back to unix form - # but this time dos style (no spaces!) so that the unix form looks - # like /cygdrive/c/PROGRA~1:/cygdr... - sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` - sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` - sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - ;; - *) - sys_lib_search_path_spec="$LIB" - if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # FIXME: find the short name or the path components, as spaces are - # common. (e.g. "Program Files" -> "PROGRA~1") - ;; - esac - - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - dynamic_linker='Win32 link.exe' - ;; - - *) - # Assume MSVC wrapper - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - dynamic_linker='Win32 ld.exe' - ;; - esac - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[23].*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2.*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -haiku*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - dynamic_linker="$host_os runtime_loader" - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=yes - sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555, ... - postinstall_cmds='chmod 555 $lib' - # or fails outright, so override atomically: - install_override_mode=555 - ;; - -interix[3-9]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux # correct to gnu/linux during the next big refactor - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - - # Some binutils ld are patched to set DT_RUNPATH - if ${lt_cv_shlibpath_overrides_runpath+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_shlibpath_overrides_runpath=no - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ - LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : - lt_cv_shlibpath_overrides_runpath=yes -fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir - -fi - - shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -*nto* | *qnx*) - version_type=qnx - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='ldqnx.so' - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -tpf*) - # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -uts4*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 -$as_echo "$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" -fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 -$as_echo_n "checking how to hardcode library paths into programs... " >&6; } -hardcode_action_CXX= -if test -n "$hardcode_libdir_flag_spec_CXX" || - test -n "$runpath_var_CXX" || - test "X$hardcode_automatic_CXX" = "Xyes" ; then - - # We can hardcode non-existent directories. - if test "$hardcode_direct_CXX" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no && - test "$hardcode_minus_L_CXX" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action_CXX=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action_CXX=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action_CXX=unsupported -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 -$as_echo "$hardcode_action_CXX" >&6; } - -if test "$hardcode_action_CXX" = relink || - test "$inherit_rpath_CXX" = yes; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - - - - - - - - fi # test -n "$compiler" - - CC=$lt_save_CC - CFLAGS=$lt_save_CFLAGS - LDCXX=$LD - LD=$lt_save_LD - GCC=$lt_save_GCC - with_gnu_ld=$lt_save_with_gnu_ld - lt_cv_path_LDCXX=$lt_cv_path_LD - lt_cv_path_LD=$lt_save_path_LD - lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld - lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test "$_lt_caught_CXX_error" != yes - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - +#shared library versioning +WOLFSSL_LIBRARY_VERSION=25:0:1 +# | | | +# +------+ | +---+ +# | | | +# current:revision:age +# | | | +# | | +- increment if interfaces have been added +# | | set to zero if interfaces have been removed +# | | or changed +# | +- increment if source code has changed +# | set to zero if current is incremented +# +- increment if interfaces have been added, removed or changed + + +# Capture user C_EXTRA_FLAGS from configure line. +# Use of C_EXTRA_FLAGS is deprecated because CFLAGS was fixed but someone +# might still be using it. +CFLAGS="$CFLAGS $C_EXTRA_FLAGS $C_FLAGS" @@ -15992,282 +13544,15 @@ _ACEOF if test -n "$CFLAG_VISIBILITY" ; then : - AM_CPPFLAGS="$AM_CPPFLAGS $CFLAG_VISIBILITY" - CPPFLAGS="$CPPFLAGS $CFLAG_VISIBILITY" + AM_CFLAGS="$AM_CPPFLAGS $CFLAG_VISIBILITY" fi -# Check whether --enable-silent-rules was given. -if test "${enable_silent_rules+set}" = set; then : - enableval=$enable_silent_rules; -fi - -case $enable_silent_rules in # ((( - yes) AM_DEFAULT_VERBOSITY=0;; - no) AM_DEFAULT_VERBOSITY=1;; - *) AM_DEFAULT_VERBOSITY=0;; -esac -am_make=${MAKE-make} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 -$as_echo_n "checking whether $am_make supports nested variables... " >&6; } -if ${am_cv_make_support_nested_variables+:} false; then : - $as_echo_n "(cached) " >&6 -else - if $as_echo 'TRUE=$(BAR$(V)) -BAR0=false -BAR1=true -V=1 -am__doit: - @$(TRUE) -.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then - am_cv_make_support_nested_variables=yes -else - am_cv_make_support_nested_variables=no -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 -$as_echo "$am_cv_make_support_nested_variables" >&6; } -if test $am_cv_make_support_nested_variables = yes; then - AM_V='$(V)' - AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' -else - AM_V=$AM_DEFAULT_VERBOSITY - AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY -fi -AM_BACKSLASH='\' - - -for ac_func in gethostbyname -do : - ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" -if test "x$ac_cv_func_gethostbyname" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_GETHOSTBYNAME 1 -_ACEOF - -fi -done - -for ac_func in getaddrinfo -do : - ac_fn_c_check_func "$LINENO" "getaddrinfo" "ac_cv_func_getaddrinfo" -if test "x$ac_cv_func_getaddrinfo" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_GETADDRINFO 1 -_ACEOF - -fi -done - -for ac_func in gettimeofday -do : - ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" -if test "x$ac_cv_func_gettimeofday" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_GETTIMEOFDAY 1 -_ACEOF - -fi -done - -for ac_func in inet_ntoa -do : - ac_fn_c_check_func "$LINENO" "inet_ntoa" "ac_cv_func_inet_ntoa" -if test "x$ac_cv_func_inet_ntoa" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_INET_NTOA 1 -_ACEOF - -fi -done - -for ac_func in memset -do : - ac_fn_c_check_func "$LINENO" "memset" "ac_cv_func_memset" -if test "x$ac_cv_func_memset" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_MEMSET 1 -_ACEOF - -fi -done - -for ac_func in socket -do : - ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" -if test "x$ac_cv_func_socket" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SOCKET 1 -_ACEOF - -fi -done - -for ac_header in arpa/inet.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "arpa/inet.h" "ac_cv_header_arpa_inet_h" "$ac_includes_default" -if test "x$ac_cv_header_arpa_inet_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_ARPA_INET_H 1 -_ACEOF - -fi - -done - -for ac_header in fcntl.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default" -if test "x$ac_cv_header_fcntl_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_FCNTL_H 1 -_ACEOF - -fi - -done - -for ac_header in limits.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default" -if test "x$ac_cv_header_limits_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIMITS_H 1 -_ACEOF - -fi - -done - -for ac_header in netdb.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "netdb.h" "ac_cv_header_netdb_h" "$ac_includes_default" -if test "x$ac_cv_header_netdb_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_NETDB_H 1 -_ACEOF - -fi - -done - -for ac_header in netinet/in.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "$ac_includes_default" -if test "x$ac_cv_header_netinet_in_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_NETINET_IN_H 1 -_ACEOF - -fi - -done - -for ac_header in stddef.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "stddef.h" "ac_cv_header_stddef_h" "$ac_includes_default" -if test "x$ac_cv_header_stddef_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_STDDEF_H 1 -_ACEOF - -fi - -done - -for ac_header in sys/ioctl.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_ioctl_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SYS_IOCTL_H 1 -_ACEOF - -fi - -done - -for ac_header in sys/socket.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_socket_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SYS_SOCKET_H 1 -_ACEOF - -fi - -done - -for ac_header in sys/time.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_time_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SYS_TIME_H 1 -_ACEOF - -fi - -done - -for ac_header in errno.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "errno.h" "ac_cv_header_errno_h" "$ac_includes_default" -if test "x$ac_cv_header_errno_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_ERRNO_H 1 -_ACEOF - -fi - -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lnetwork" >&5 -$as_echo_n "checking for socket in -lnetwork... " >&6; } -if ${ac_cv_lib_network_socket+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lnetwork $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char socket (); -int -main () -{ -return socket (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_network_socket=yes -else - ac_cv_lib_network_socket=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_socket" >&5 -$as_echo "$ac_cv_lib_network_socket" >&6; } -if test "x$ac_cv_lib_network_socket" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBNETWORK 1 -_ACEOF - - LIBS="-lnetwork $LIBS" - -fi +# Moved these size of and type checks before the library checks. +# The library checks add the library to subsequent test compiles +# and in some rare cases, the networking check causes these sizeof +# checks to fail. # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. @@ -16334,6 +13619,39 @@ cat >>confdefs.h <<_ACEOF _ACEOF +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5 +$as_echo_n "checking size of time_t... " >&6; } +if ${ac_cv_sizeof_time_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (time_t))" "ac_cv_sizeof_time_t" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_time_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (time_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_time_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5 +$as_echo "$ac_cv_sizeof_time_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_TIME_T $ac_cv_sizeof_time_t +_ACEOF + + ac_fn_c_check_type "$LINENO" "__uint128_t" "ac_cv_type___uint128_t" "$ac_includes_default" if test "x$ac_cv_type___uint128_t" = xyes; then : @@ -16342,6 +13660,76 @@ cat >>confdefs.h <<_ACEOF _ACEOF +fi + +for ac_func in gethostbyname getaddrinfo gettimeofday gmtime_r inet_ntoa memset socket +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_header in arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h stddef.h sys/ioctl.h sys/socket.h sys/time.h errno.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lnetwork" >&5 +$as_echo_n "checking for socket in -lnetwork... " >&6; } +if ${ac_cv_lib_network_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnetwork $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_network_socket=yes +else + ac_cv_lib_network_socket=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_socket" >&5 +$as_echo "$ac_cv_lib_network_socket" >&6; } +if test "x$ac_cv_lib_network_socket" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNETWORK 1 +_ACEOF + + LIBS="-lnetwork $LIBS" + fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 @@ -16568,1231 +13956,6 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac -# mktime check takes forever on some systems, if time supported it would be -# highly unusual for mktime to be missing -#AC_FUNC_MKTIME - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5; } - -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -struct stat; -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_c89=$ac_arg -fi -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : - -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 -$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } -if ${am_cv_prog_cc_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF - # Make sure it works both with $CC and with simple cc. - # Following AC_PROG_CC_C_O, we do the test twice because some - # compilers refuse to overwrite an existing .o file with -o, - # though they will create one. - am_cv_prog_cc_c_o=yes - for am_i in 1 2; do - if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 - ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } \ - && test -f conftest2.$ac_objext; then - : OK - else - am_cv_prog_cc_c_o=no - break - fi - done - rm -f core conftest* - unset am_i -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 -$as_echo "$am_cv_prog_cc_c_o" >&6; } -if test "$am_cv_prog_cc_c_o" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -depcc="$CC" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CC_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CC_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CC_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CC_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } -CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then - am__fastdepCC_TRUE= - am__fastdepCC_FALSE='#' -else - am__fastdepCC_TRUE='#' - am__fastdepCC_FALSE= -fi - - -if test "x$CC" != xcc; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 -$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 -$as_echo_n "checking whether cc understands -c and -o together... " >&6; } -fi -set dummy $CC; ac_cc=`$as_echo "$2" | - sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` -if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -# Make sure it works both with $CC and with simple cc. -# We do the test twice because some compilers refuse to overwrite an -# existing .o file with -o, though they will create one. -ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' -rm -f conftest2.* -if { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && - test -f conftest2.$ac_objext && { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; -then - eval ac_cv_prog_cc_${ac_cc}_c_o=yes - if test "x$CC" != xcc; then - # Test first that cc exists at all. - if { ac_try='cc -c conftest.$ac_ext >&5' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' - rm -f conftest2.* - if { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && - test -f conftest2.$ac_objext && { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; - then - # cc works too. - : - else - # cc exists but doesn't like -o. - eval ac_cv_prog_cc_${ac_cc}_c_o=no - fi - fi - fi -else - eval ac_cv_prog_cc_${ac_cc}_c_o=no -fi -rm -f core conftest* - -fi -if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h - -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -if test -z "$CXX"; then - if test -n "$CCC"; then - CXX=$CCC - else - if test -n "$ac_tool_prefix"; then - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CXX=$ac_cv_prog_CXX -if test -n "$CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 -$as_echo "$CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CXX" && break - done -fi -if test -z "$CXX"; then - ac_ct_CXX=$CXX - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CXX"; then - ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CXX="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CXX=$ac_cv_prog_ac_ct_CXX -if test -n "$ac_ct_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 -$as_echo "$ac_ct_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CXX" && break -done - - if test "x$ac_ct_CXX" = x; then - CXX="g++" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_ct_CXX - fi -fi - - fi -fi -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 -$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } -if ${ac_cv_cxx_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_cxx_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 -$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GXX=yes -else - GXX= -fi -ac_test_CXXFLAGS=${CXXFLAGS+set} -ac_save_CXXFLAGS=$CXXFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 -$as_echo_n "checking whether $CXX accepts -g... " >&6; } -if ${ac_cv_prog_cxx_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_cxx_werror_flag=$ac_cxx_werror_flag - ac_cxx_werror_flag=yes - ac_cv_prog_cxx_g=no - CXXFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_prog_cxx_g=yes -else - CXXFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -else - ac_cxx_werror_flag=$ac_save_cxx_werror_flag - CXXFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_prog_cxx_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cxx_werror_flag=$ac_save_cxx_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 -$as_echo "$ac_cv_prog_cxx_g" >&6; } -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS=$ac_save_CXXFLAGS -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -depcc="$CXX" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CXX_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CXX_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CXX_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CXX_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } -CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then - am__fastdepCXX_TRUE= - am__fastdepCXX_FALSE='#' -else - am__fastdepCXX_TRUE='#' - am__fastdepCXX_FALSE= -fi - ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" @@ -17953,7 +14116,6 @@ else fi - LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) @@ -17997,7 +14159,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mw__mwvalidcheckl" >&5 $as_echo "$ac_cv_lib_mw__mwvalidcheckl" >&6; } if test "x$ac_cv_lib_mw__mwvalidcheckl" = xyes; then : - LIBM="-lmw" + LIBM=-lmw fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 @@ -18079,7 +14241,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5 $as_echo "$ac_cv_lib_m_cos" >&6; } if test "x$ac_cv_lib_m_cos" = xyes; then : - LIBM="-lm" + LIBM=-lm fi ;; @@ -18087,12 +14249,13 @@ esac -OPTIMIZE_CFLAGS="-Os -fomit-frame-pointer" -OPTIMIZE_FAST_CFLAGS="-O2 -fomit-frame-pointer" +OPTIMIZE_CFLAGS="-Os" +OPTIMIZE_FAST_CFLAGS="-O2" OPTIMIZE_HUGE_CFLAGS="-funroll-loops -DTFM_SMALL_SET -DTFM_HUGE_SET" DEBUG_CFLAGS="-g -DDEBUG -DDEBUG_WOLFSSL" +LIB_ADD= +LIB_STATIC_ADD= -thread_ls_on=no # Thread local storage { $as_echo "$as_me:${as_lineno-$LINENO}: checking for thread local storage (TLS) class" >&5 @@ -18144,16 +14307,15 @@ cat >>confdefs.h <<_ACEOF #define TLS $ac_cv_tls _ACEOF - - AM_CFLAGS="$AM_CFLAGS -DHAVE_THREAD_LS" - thread_ls_on=yes - + thread_ls_on=yes else - : + thread_ls_on=no fi - +if test "x$thread_ls_on" = "xyes"; then : + AM_CFLAGS="$AM_CFLAGS -DHAVE_THREAD_LS" +fi # DEBUG # Check whether --enable-debug was given. @@ -18194,6 +14356,167 @@ else fi +# Distro build feature subset (Debian, Ubuntu, etc.) +# Check whether --enable-distro was given. +if test "${enable_distro+set}" = set; then : + enableval=$enable_distro; ENABLED_DISTRO=$enableval +else + ENABLED_DISTRO=no + +fi + +if test "$ENABLED_DISTRO" = "yes" +then + enable_shared=yes + enable_static=yes + enable_all=yes +fi + + +# ALL FEATURES +# Check whether --enable-all was given. +if test "${enable_all+set}" = set; then : + enableval=$enable_all; ENABLED_ALL=$enableval +else + ENABLED_ALL=no + +fi + +if test "$ENABLED_ALL" = "yes" +then + enable_dtls=yes + enable_tls13=yes + enable_openssh=yes + enable_opensslextra=yes + enable_opensslall=yes + enable_savesession=yes + enable_savecert=yes + enable_atomicuser=yes + enable_pkcallbacks=yes + enable_aesgcm=yes + enable_aesccm=yes + enable_aesctr=yes + enable_aesofb=yes + enable_aescfb=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 + enable_certreq=yes + enable_certext=yes + enable_sep=yes + enable_hkdf=yes + enable_dsa=yes + enable_ecccustcurves=yes + enable_compkey=yes + enable_curve25519=yes + enable_curve448=yes + enable_ed25519=yes + enable_fpecc=yes + enable_eccencrypt=yes + enable_psk=yes + enable_idea=yes + enable_cmac=yes + enable_xts=yes + enable_webserver=yes + enable_hc128=yes + enable_rabbit=yes + enable_ocsp=yes + enable_ocspstapling=yes + enable_ocspstapling2=yes + enable_crl=yes + enable_crl_monitor=yes + enable_sni=yes + enable_maxfragment=yes + enable_alpn=yes + enable_truncatedhmac=yes + enable_trusted_ca=yes + enable_supportedcurves=yes + 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_openvpn=yes + enable_asio=yes + enable_libwebsockets=yes + enable_qt=yes + enable_pwdbased=yes + enable_aeskeywrap=yes + enable_x963kdf=yes + enable_scrypt=yes + enable_indef=yes + enable_enckeys=yes + enable_hashflags=yes + enable_dhdefaultparams=yes + + # Enable AES Decrypt, AES ECB, Alt Names, DER Load, Keep Certs, CRL IO with Timeout + AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_DECRYPT -DHAVE_AES_ECB -DWOLFSSL_ALT_NAMES -DWOLFSSL_DER_LOAD -DKEEP_OUR_CERT -DKEEP_PEER_CERT -DHAVE_CRL_IO -DHAVE_IO_TIMEOUT" + + # Enable DH const table speedups (eliminates `-lm` math lib dependency) + AM_CFLAGS="$AM_CFLAGS -DHAVE_FFDHE_2048 -DHAVE_FFDHE_3072 -DFP_MAX_BITS=8192" + + # Enable multiple attribute additions such as DC + AM_CFLAGS="-DWOLFSSL_MULTI_ATTRIB $AM_CFLAGS" +fi + + +# Support for forcing 32-bit mode +# To force 32-bit instructions use: +# ./configure CFLAGS="-m32" LDFLAGS="-m32" && make +# The checks for sizeof long and long/long are run at the top of configure and require "-m32" to be set directly in the ./configure statement. +# Check whether --enable-32bit was given. +if test "${enable_32bit+set}" = set; then : + enableval=$enable_32bit; ENABLED_32BIT=$enableval +else + ENABLED_32BIT=no + +fi + + +# 16-bit compiler support +# Check whether --enable-16bit was given. +if test "${enable_16bit+set}" = set; then : + enableval=$enable_16bit; ENABLED_16BIT=$enableval +else + ENABLED_16BIT=no + +fi + +if test "$ENABLED_16BIT" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWC_16BIT_CPU" +fi + + + +# Support for disabling all ASM +# Check whether --enable-asm was given. +if test "${enable_asm+set}" = set; then : + enableval=$enable_asm; ENABLED_ASM=$enableval +else + ENABLED_ASM=yes + +fi + + +if test "$ENABLED_ASM" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DTFM_NO_ASM -DWOLFSSL_NO_ASM" +fi + + # SINGLE THREADED # Check whether --enable-singlethreaded was given. if test "${enable_singlethreaded+set}" = set; then : @@ -18203,19 +14526,12 @@ else fi - - if test x"$CC" = xclang; then - wolfssl_darwin_clang=yes - elif test x"$CC" = x || test x"$CC" = xgcc; then - if /usr/bin/gcc -v 2>&1 | grep 'clang' >/dev/null 2>&1; then - wolfssl_darwin_clang=yes - fi - fi - if test "x$ENABLED_SINGLETHREADED" = "xno" ; then : + + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -18225,19 +14541,23 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). +# requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + if test "x$PTHREAD_CC" != "x"; then : + CC="$PTHREAD_CC" +fi CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 -$as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5 +$as_echo_n "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18263,12 +14583,13 @@ rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 $as_echo "$ax_pthread_ok" >&6; } - if test x"$ax_pthread_ok" = xno; then + if test "x$ax_pthread_ok" = "xno"; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different @@ -18281,7 +14602,7 @@ fi # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. -ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: @@ -18290,56 +14611,257 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# ... -mt is also the pthreads flag for HP/aCC +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) -case ${host_os} in +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5 +$as_echo "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;} +fi +rm -f conftest* + + ;; + solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthreads/-mt/ - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). - ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" - ;; - - darwin*) - - if test x"$wolfssl_darwin_clang" = x"yes"; then : - ax_pthread_flags="$ax_pthread_flags" -else - ax_pthread_flags="-pthread $ax_pthread_flags" -fi + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" ;; esac -if test x"$ax_pthread_ok" = xno; then -for flag in $ax_pthread_flags; do +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) - case $flag in +if test "x$GCC" = "xyes"; then : + ax_pthread_flags="-pthread -pthreads $ax_pthread_flags" +fi + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +if test "x$ax_pthread_check_macro" = "x--"; then : + ax_pthread_check_cond=0 +else + ax_pthread_check_cond="!defined($ax_pthread_check_macro)" +fi + +# Are we compiling with Clang? + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5 +$as_echo_n "checking whether $CC is Clang... " >&6; } +if ${ax_cv_PTHREAD_CLANG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1; then : + ax_cv_PTHREAD_CLANG=yes +fi +rm -f conftest* + + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG" >&6; } +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5 +$as_echo_n "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; } +if ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + if test "x$ax_pthread_try" = "xunknown"; then : + break +fi + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_link="$ax_pthread_2step_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + if test "x$ax_pthread_try" = "x"; then : + ax_pthread_try=no +fi + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; } + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in none) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 $as_echo_n "checking whether pthreads work without any flags... " >&6; } ;; + -mt,pthread) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with -mt -lpthread" >&5 +$as_echo_n "checking whether pthreads work with -mt -lpthread... " >&6; } + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + -*) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 -$as_echo_n "checking whether pthreads work with $flag... " >&6; } - PTHREAD_CFLAGS="$flag" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5 +$as_echo_n "checking whether pthreads work with $ax_pthread_try_flag... " >&6; } + PTHREAD_CFLAGS="$ax_pthread_try_flag" ;; pthread-config) @@ -18381,22 +14903,24 @@ $as_echo "no" >&6; } fi - if test x"$ax_pthread_config" = xno; then continue; fi + if test "x$ax_pthread_config" = "xno"; then : + continue +fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 -$as_echo_n "checking for the pthreads library -l$flag... " >&6; } - PTHREAD_LIBS="-l$flag" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5 +$as_echo_n "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; } + PTHREAD_LIBS="-l$ax_pthread_try_flag" ;; esac - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we @@ -18407,6 +14931,7 @@ $as_echo_n "checking for the pthreads library -l$flag... " >&6; } # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -18431,14 +14956,14 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 $as_echo "$ax_pthread_ok" >&6; } - if test "x$ax_pthread_ok" = xyes; then - break; - fi + if test "x$ax_pthread_ok" = "xyes"; then : + break +fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" @@ -18446,74 +14971,82 @@ done fi # Various other checks: -if test "x$ax_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 $as_echo_n "checking for joinable pthread attribute... " >&6; } - attr_name=unknown - for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ax_cv_PTHREAD_JOINABLE_ATTR+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -int attr = $attr; return attr /* ; */ +int attr = $ax_pthread_attr; return attr /* ; */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - attr_name=$attr; break + ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - done - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5 -$as_echo "$attr_name" >&6; } - if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5 +$as_echo "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; } + if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"; then : cat >>confdefs.h <<_ACEOF -#define PTHREAD_CREATE_JOINABLE $attr_name +#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR _ACEOF - fi + ax_pthread_joinable_attr_defined=yes - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 -$as_echo_n "checking if more special flags are required for pthreads... " >&6; } - flag=no - case ${host_os} in - aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; - osf* | hpux*) flag="-D_REENTRANT";; - solaris*) - if test "$GCC" = "yes"; then - flag="-D_REENTRANT" - else - flag="-mt -D_REENTRANT" - fi - ;; - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5 -$as_echo "${flag}" >&6; } - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5 +$as_echo_n "checking whether more special flags are required for pthreads... " >&6; } +if ${ax_cv_PTHREAD_SPECIAL_FLAGS+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5 +$as_echo "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; } + if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"; then : + PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes +fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 $as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; } if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then : $as_echo_n "(cached) " >&6 else - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - - #include +#include int main () { @@ -18533,23 +15066,26 @@ rm -f core conftest.err conftest.$ac_objext \ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 $as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } - if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"; then : + if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"; then : $as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h + ax_pthread_prio_inherit_defined=yes + fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" # More AIX lossage: compile with *_r variant - if test "x$GCC" != xyes; then + if test "x$GCC" != "xyes"; then case $host_os in aix*) case "x/$CC" in #( x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) : #handle absolute path differently from PATH based program lookup - case "x$CC" in #( + case "x$CC" in #( x/*) : if as_fn_executable_p ${CC}_r; then : PTHREAD_CC="${CC}_r" @@ -18614,11 +15150,19 @@ test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$ax_pthread_ok" = xyes; then +if test "x$ax_pthread_ok" = "xyes"; then $as_echo "#define HAVE_PTHREAD 1" >>confdefs.h + # If AX_PTHREAD is adding -Qunused-arguments, need to prepend with -Xcompiler libtool will use it. Newer + # versions of clang don't need the -Q flag when using pthreads. + case $PTHREAD_CFLAGS in #( + -Qunused-arguments*) : + PTHREAD_CFLAGS="-Xcompiler $PTHREAD_CFLAGS" ;; #( + *) : + ;; +esac AM_CFLAGS="-D_POSIX_THREADS $AM_CFLAGS $PTHREAD_CFLAGS" LIBS="$LIBS $PTHREAD_LIBS" @@ -18658,6 +15202,419 @@ then AM_CFLAGS="-DWOLFSSL_DTLS $AM_CFLAGS" fi +# DTLS change MTU +# Check whether --enable-dtls-mtu was given. +if test "${enable_dtls_mtu+set}" = set; then : + enableval=$enable_dtls_mtu; ENABLED_DTLS_MTU=$enableval +else + ENABLED_DTLS_MTU=no + +fi + +if test "$ENABLED_DTLS_MTU" = "yes" +then + AM_CFLAGS="-DWOLFSSL_DTLS_MTU $AM_CFLAGS" +fi + + +# TLS v1.3 Draft 18 +# Check whether --enable-tls13-draft18 was given. +if test "${enable_tls13_draft18+set}" = set; then : + enableval=$enable_tls13_draft18; ENABLED_TLS13_DRAFT18=$enableval +else + ENABLED_TLS13_DRAFT18=no + +fi + +if test "$ENABLED_TLS13_DRAFT18" = "yes" +then + AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT -DWOLFSSL_TLS13_DRAFT_18 $AM_CFLAGS" +fi + + +# TLS v1.3 Draft 22 +# Check whether --enable-tls13-draft22 was given. +if test "${enable_tls13_draft22+set}" = set; then : + enableval=$enable_tls13_draft22; ENABLED_TLS13_DRAFT22=$enableval +else + ENABLED_TLS13_DRAFT22=no + +fi + +if test "$ENABLED_TLS13_DRAFT22" = "yes" +then + AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT -DWOLFSSL_TLS13_DRAFT_22 $AM_CFLAGS" +fi + + +# TLS v1.3 Draft 23 +# Check whether --enable-tls13-draft23 was given. +if test "${enable_tls13_draft23+set}" = set; then : + enableval=$enable_tls13_draft23; ENABLED_TLS13_DRAFT23=$enableval +else + ENABLED_TLS13_DRAFT23=no + +fi + +if test "$ENABLED_TLS13_DRAFT23" = "yes" +then + AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT -DWOLFSSL_TLS13_DRAFT_23 $AM_CFLAGS" +fi + + +# TLS v1.3 Draft 26 +# Check whether --enable-tls13-draft26 was given. +if test "${enable_tls13_draft26+set}" = set; then : + enableval=$enable_tls13_draft26; ENABLED_TLS13_DRAFT26=$enableval +else + ENABLED_TLS13_DRAFT26=no + +fi + +if test "$ENABLED_TLS13_DRAFT26" = "yes" +then + AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT -DWOLFSSL_TLS13_DRAFT_26 $AM_CFLAGS" +fi + + +# TLS v1.3 Draft 28 +# Check whether --enable-tls13-draft28 was given. +if test "${enable_tls13_draft28+set}" = set; then : + enableval=$enable_tls13_draft28; ENABLED_TLS13_DRAFT28=$enableval +else + ENABLED_TLS13_DRAFT28=no + +fi + +if test "$ENABLED_TLS13_DRAFT28" = "yes" +then + AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT $AM_CFLAGS" +fi + + +# TLS v1.3 +# Check whether --enable-tls13 was given. +if test "${enable_tls13+set}" = set; then : + enableval=$enable_tls13; ENABLED_TLS13=$enableval +else + ENABLED_TLS13=no + +fi + + +if test "$ENABLED_TLS13_DRAFT18" = "yes" || test "$ENABLED_TLS13_DRAFT22" = "yes" || test "$ENABLED_TLS13_DRAFT23" = "yes" || test "$ENABLED_TLS13_DRAFT26" = "yes" || test "$ENABLED_TLS13_DRAFT28" = "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 + + +# Post-handshake Authentication +# Check whether --enable-postauth was given. +if test "${enable_postauth+set}" = set; then : + enableval=$enable_postauth; ENABLED_TLS13_POST_AUTH=$enableval +else + ENABLED_TLS13_POST_AUTH=no + +fi + +if test "$ENABLED_TLS13_POST_AUTH" = "yes" +then + if test "x$ENABLED_TLS13" = "xno" + then + as_fn_error $? "cannot enable postauth without enabling tls13." "$LINENO" 5 + fi + AM_CFLAGS="-DWOLFSSL_POST_HANDSHAKE_AUTH $AM_CFLAGS" +fi + + +# Hello Retry Request Cookie +# Check whether --enable-hrrcookie was given. +if test "${enable_hrrcookie+set}" = set; then : + enableval=$enable_hrrcookie; ENABLED_SEND_HRR_COOKIE=$enableval +else + ENABLED_SEND_HRR_COOKIE=no + +fi + +if test "$ENABLED_SEND_HRR_COOKIE" = "yes" +then + if test "x$ENABLED_TLS13" = "xno" + then + as_fn_error $? "cannot enable hrrcookie without enabling tls13." "$LINENO" 5 + fi + AM_CFLAGS="-DWOLFSSL_SEND_HRR_COOKIE $AM_CFLAGS" +fi + + +# RNG +# Check whether --enable-rng was given. +if test "${enable_rng+set}" = set; then : + enableval=$enable_rng; ENABLED_RNG=$enableval +else + ENABLED_RNG=yes + +fi + + +if test "$ENABLED_RNG" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DWC_NO_RNG" +fi + + +# DTLS-SCTP +# Check whether --enable-sctp was given. +if test "${enable_sctp+set}" = set; then : + enableval=$enable_sctp; ENABLED_SCTP=$enableval +else + ENABLED_SCTP=no +fi + + +if test "x$ENABLED_SCTP" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SCTP" >&5 +$as_echo_n "checking for SCTP... " >&6; } + if test "$cross_compiling" = yes; then : + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run test program while cross compiling +See \`config.log' for more details" "$LINENO" 5; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main () +{ +int s = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); if (s == -1) return 1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "SCTP not available, remove enable-sctp from configure" "$LINENO" 5 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi + + +# DTLS-MULTICAST +# Check whether --enable-mcast was given. +if test "${enable_mcast+set}" = set; then : + enableval=$enable_mcast; ENABLED_MCAST=$enableval +else + ENABLED_MCAST=no +fi + + + +# List of open source project defines using our openssl compatibility layer: +# openssh (--enable-openssh) WOLFSSL_OPENSSH +# openvpn (--enable-openvpn) +# nginix (--enable-nginx) WOLFSSL_NGINX +# haproxy (--enable-haproxy) WOLFSSL_HAPROXY +# wpa_supplicant (--enable-wpas) WOLFSSL_WPAS +# ssl fortress (--enable-fortress) FORTRESS +# ssl bump (--enable-bump) +# signal (--enable-signal) +# lighty (--enable-lighty) HAVE_LIGHTY +# stunnel (--enable-stunnel) HAVE_STUNNEL +# asio (--enable-asio) WOLFSSL_ASIO +# libwebsockets (--enable-libwebsockets) WOLFSSL_LIBWEBSOCKETS +# qt (--enable-qt) WOLFSSL_QT +# qt test (--enable-qt-test) WOLFSSL_QT_TEST +# HAVE_POCO_LIB +# WOLFSSL_MYSQL_COMPATIBLE +# web server (--enable-webserver) HAVE_WEBSERVER + + +# OpenSSH compatibility Build +# Check whether --enable-openssh was given. +if test "${enable_openssh+set}" = set; then : + enableval=$enable_openssh; ENABLED_OPENSSH=$enableval +else + ENABLED_OPENSSH=no +fi + + +# OpenVPN compatibility Build +# Check whether --enable-openvpn was given. +if test "${enable_openvpn+set}" = set; then : + enableval=$enable_openvpn; ENABLED_OPENVPN=$enableval +else + ENABLED_OPENVPN=no +fi + + +# nginx compatibility build +# Check whether --enable-nginx was given. +if test "${enable_nginx+set}" = set; then : + enableval=$enable_nginx; ENABLED_NGINX=$enableval +else + ENABLED_NGINX=no + +fi + + +# haproxy compatibility build +# Check whether --enable-haproxy was given. +if test "${enable_haproxy+set}" = set; then : + enableval=$enable_haproxy; ENABLED_HAPROXY=$enableval +else + ENABLED_HAPROXY=no + +fi + + +# wpa_supplicant support +# Check whether --enable-wpas was given. +if test "${enable_wpas+set}" = set; then : + enableval=$enable_wpas; ENABLED_WPAS=$enableval +else + ENABLED_WPAS=no + +fi + + +# wpa_supplicant support +# Check whether --enable-wpas-dpp was given. +if test "${enable_wpas_dpp+set}" = set; then : + enableval=$enable_wpas_dpp; ENABLED_WPAS_DPP=$enableval +else + ENABLED_WPAS_DPP=no + +fi + + +if test "$ENABLED_WPAS_DPP" = "yes" +then + ENABLED_WPAS="yes" +fi + +# Fortress build +# Check whether --enable-fortress was given. +if test "${enable_fortress+set}" = set; then : + enableval=$enable_fortress; ENABLED_FORTRESS=$enableval +else + ENABLED_FORTRESS=no + +fi + + +# libwebsockets Support +# Check whether --enable-libwebsockets was given. +if test "${enable_libwebsockets+set}" = set; then : + enableval=$enable_libwebsockets; ENABLED_LIBWEBSOCKETS=$enableval +else + ENABLED_LIBWEBSOCKETS=no + +fi + +if test "$ENABLED_LIBWEBSOCKETS" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LIBWEBSOCKETS -DOPENSSL_NO_EC" +fi + + +if test "$ENABLED_OPENSSH" = "yes" +then + ENABLED_FORTRESS="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_OPENSSH -DHAVE_EX_DATA -DWOLFSSL_BASE16" +fi + +#Qt Support +# Check whether --enable-qt was given. +if test "${enable_qt+set}" = set; then : + enableval=$enable_qt; ENABLED_QT=$enableval +else + ENABLED_QT=no + +fi + + +# ssl bump build +# Check whether --enable-bump was given. +if test "${enable_bump+set}" = set; then : + enableval=$enable_bump; ENABLED_BUMP=$enableval +else + ENABLED_BUMP=no + +fi + + +# SNIFFER +# Check whether --enable-sniffer was given. +if test "${enable_sniffer+set}" = set; then : + enableval=$enable_sniffer; ENABLED_SNIFFER=$enableval +else + ENABLED_SNIFFER=no + +fi + + +# signal compatibility build +# Check whether --enable-signal was given. +if test "${enable_signal+set}" = set; then : + enableval=$enable_signal; ENABLED_SIGNAL=$enableval +else + ENABLED_SIGNAL=no + +fi + + +# OpenSSL Coexist +# Check whether --enable-opensslcoexist was given. +if test "${enable_opensslcoexist+set}" = set; then : + enableval=$enable_opensslcoexist; ENABLED_OPENSSLCOEXIST=$enableval +else + ENABLED_OPENSSLCOEXIST=no + +fi + +if test "x$ENABLED_OPENSSLCOEXIST" = "xyes" +then + # make sure old names are disabled + enable_oldnames=no + + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_COEXIST" +fi + + +# OPENSSL Compatibility ALL +# Check whether --enable-opensslall was given. +if test "${enable_opensslall+set}" = set; then : + enableval=$enable_opensslall; ENABLED_OPENSSLALL=$enableval +else + ENABLED_OPENSSLALL=no + +fi + +if test "$ENABLED_LIBWEBSOCKETS" = "yes" || test "$ENABLED_OPENVPN" = "yes" || test "$ENABLED_WPAS_DPP" = "yes" +then + ENABLED_OPENSSLALL="yes" +fi + +if test "$ENABLED_OPENSSLALL" = "yes" +then +AM_CFLAGS="-DOPENSSL_ALL -DWOLFSSL_EITHER_SIDE -DWC_RSA_NO_PADDING -DWC_RSA_PSS $AM_CFLAGS" +fi # OPENSSL Extra Compatibility # Check whether --enable-opensslextra was given. @@ -18668,16 +15625,29 @@ else fi -if test "$ENABLED_OPENSSLEXTRA" = "yes" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" || test "$ENABLED_SIGNAL" = "yes" || test "$ENABLED_WPAS" = "yes" || test "$ENABLED_FORTRESS" = "yes" || test "$ENABLED_BUMP" = "yes" || test "$ENABLED_SNIFFER" = "yes" || test "$ENABLED_OPENSSLALL" = "yes" || test "$ENABLED_LIBWEBSOCKETS" = "yes" then - AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" + ENABLED_OPENSSLEXTRA="yes" +fi + +if test "$ENABLED_OPENSSLEXTRA" = "yes" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" +then + AM_CFLAGS="-DOPENSSL_EXTRA -DWOLFSSL_ALWAYS_VERIFY_CB $AM_CFLAGS" + AM_CFLAGS="-DWOLFSSL_VERIFY_CB_ALL_CERTS -DWOLFSSL_EXTRA_ALERTS $AM_CFLAGS" fi if test "$ENABLED_OPENSSLEXTRA" = "yes" && test "$ENABLED_SMALL" = "yes" then - as_fn_error $? "cannot enable small and opensslextra, only one or the other." "$LINENO" 5 + as_fn_error $? "cannot enable small and opensslextra, only one or the other." "$LINENO" 5 fi +if test "$ENABLED_OPENSSLEXTRA" = "x509small" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling only a subset of X509 opensslextra" >&5 +$as_echo "$as_me: Enabling only a subset of X509 opensslextra" >&6;} + AM_CFLAGS="-DOPENSSL_EXTRA_X509_SMALL $AM_CFLAGS" + AM_CFLAGS="-DWOLFSSL_EKU_OID -DWOLFSSL_MULTI_ATTRIB $AM_CFLAGS" +fi # High Strength Build # Check whether --enable-maxstrength was given. @@ -18689,6 +15659,27 @@ fi +# Harden, enable Timing Resistance and Blinding by default +# Check whether --enable-harden was given. +if test "${enable_harden+set}" = set; then : + enableval=$enable_harden; ENABLED_HARDEN=$enableval +else + ENABLED_HARDEN=yes +fi + + +if test "$ENABLED_HARDEN" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DTFM_TIMING_RESISTANT -DECC_TIMING_RESISTANT" + if test "$ENABLED_RNG" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DWC_RSA_BLINDING" + fi +else + AM_CFLAGS="$AM_CFLAGS -DWC_NO_HARDEN" +fi + + # IPv6 Test Apps # Check whether --enable-ipv6 was given. if test "${enable_ipv6+set}" = set; then : @@ -18701,48 +15692,32 @@ fi if test "$ENABLED_IPV6" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DTEST_IPV6" -fi - - if test "x$ENABLED_IPV6" = "xyes"; then - BUILD_IPV6_TRUE= - BUILD_IPV6_FALSE='#' -else - BUILD_IPV6_TRUE='#' - BUILD_IPV6_FALSE= + AM_CFLAGS="$AM_CFLAGS -DTEST_IPV6 -DWOLFSSL_IPV6" fi - -# Fortress build -# Check whether --enable-fortress was given. -if test "${enable_fortress+set}" = set; then : - enableval=$enable_fortress; ENABLED_FORTRESS=$enableval -else - ENABLED_FORTRESS=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" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT -DWOLFSSL_DER_LOAD" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KEY_GEN -DWOLFSSL_DES_ECB" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WPAS" 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" -fi - - -# ssl bump build -# Check whether --enable-bump was given. -if test "${enable_bump+set}" = set; then : - enableval=$enable_bump; ENABLED_BUMP=$enableval -else - ENABLED_BUMP=no - + AM_CFLAGS="$AM_CFLAGS -DFORTRESS -DWOLFSSL_ALWAYS_VERIFY_CB -DWOLFSSL_AES_COUNTER -DWOLFSSL_AES_DIRECT -DWOLFSSL_DER_LOAD -DWOLFSSL_KEY_GEN" fi if test "$ENABLED_BUMP" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DLARGE_STATIC_BUFFERS -DWOLFSSL_CERT_GEN -DWOLFSSL_KEY_GEN -DHUGE_SESSION_CACHE -DOPENSSL_EXTRA -DFP_MAX_BITS=8192 -DWOLFSSL_DER_LOAD -DWOLFSSL_ALT_NAMES -DWOLFSSL_TEST_CERT" + AM_CFLAGS="$AM_CFLAGS -DLARGE_STATIC_BUFFERS -DWOLFSSL_CERT_GEN -DWOLFSSL_KEY_GEN -DHUGE_SESSION_CACHE -DFP_MAX_BITS=8192 -DWOLFSSL_DER_LOAD -DWOLFSSL_ALT_NAMES -DWOLFSSL_TEST_CERT" fi ENABLED_SLOWMATH="yes" @@ -18759,34 +15734,63 @@ fi if test "$ENABLED_LEANPSK" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LEANPSK -DHAVE_NULL_CIPHER -DSINGLE_THREADED -DNO_AES -DNO_FILESYSTEM -DNO_RABBIT -DNO_RSA -DNO_DSA -DNO_DH -DNO_CERTS -DNO_PWDBASED -DNO_DES3 -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 - if test "x$ENABLED_LEANPSK" = "xyes"; then - BUILD_LEANPSK_TRUE= - BUILD_LEANPSK_FALSE='#' + +# lean TLS build (TLS 1.2 client only (no client auth), ECC256, AES128 and SHA256 w/o Shamir) +# Check whether --enable-leantls was given. +if test "${enable_leantls+set}" = set; then : + enableval=$enable_leantls; ENABLED_LEANTLS=$enableval else - BUILD_LEANPSK_TRUE='#' - BUILD_LEANPSK_FALSE= -fi - - - -# big cache -# Check whether --enable-bigcache was given. -if test "${enable_bigcache+set}" = set; then : - enableval=$enable_bigcache; ENABLED_BIGCACHE=$enableval -else - ENABLED_BIGCACHE=no + ENABLED_LEANTLS=no fi -if test "$ENABLED_BIGCACHE" = "yes" +if test "$ENABLED_LEANTLS" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DBIG_SESSION_CACHE" + 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 -DNO_WOLFSSL_CM_VERIFY" + enable_lowresource=yes +fi + + +# low resource options to reduce flash and memory use +# Check whether --enable-lowresource was given. +if test "${enable_lowresource+set}" = set; then : + enableval=$enable_lowresource; ENABLED_LOWRESOURCE=$enableval +else + ENABLED_LOWRESOURCE=no + +fi + + +if test "$ENABLED_LOWRESOURCE" = "yes" +then + # low memory / flash flags + AM_CFLAGS="$AM_CFLAGS -DNO_SESSION_CACHE -DRSA_LOW_MEM -DALT_ECC_SIZE -DGCM_SMALL -DCURVE25519_SMALL -DED25519_SMALL -DWOLFSSL_SMALL_CERT_VERIFY" + + # low flash flags + AM_CFLAGS="$AM_CFLAGS -DUSE_SLOW_SHA -DUSE_SLOW_SHA256 -DUSE_SLOW_SHA512" +fi + + +# TITAN cache +# Check whether --enable-titancache was given. +if test "${enable_titancache+set}" = set; then : + enableval=$enable_titancache; ENABLED_TITANCACHE=$enableval +else + ENABLED_TITANCACHE=no + +fi + + +if test "$ENABLED_TITANCACHE" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DTITAN_SESSION_CACHE" fi @@ -18806,6 +15810,22 @@ then fi +# big cache +# Check whether --enable-bigcache was given. +if test "${enable_bigcache+set}" = set; then : + enableval=$enable_bigcache; ENABLED_BIGCACHE=$enableval +else + ENABLED_BIGCACHE=no + +fi + + +if test "$ENABLED_BIGCACHE" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DBIG_SESSION_CACHE" +fi + + # SMALL cache # Check whether --enable-smallcache was given. if test "${enable_smallcache+set}" = set; then : @@ -18854,6 +15874,22 @@ then fi +# Write duplicate WOLFSSL object +# Check whether --enable-writedup was given. +if test "${enable_writedup+set}" = set; then : + enableval=$enable_writedup; ENABLED_WRITEDUP=$enableval +else + ENABLED_WRITEDUP=no + +fi + + +if test "$ENABLED_WRITEDUP" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_WRITE_DUP" +fi + + # Atomic User Record Layer # Check whether --enable-atomicuser was given. if test "${enable_atomicuser+set}" = set; then : @@ -18886,17 +15922,90 @@ then fi -# SNIFFER -# Check whether --enable-sniffer was given. -if test "${enable_sniffer+set}" = set; then : - enableval=$enable_sniffer; ENABLED_SNIFFER=$enableval +# Microchip/Atmel CryptoAuthLib +ENABLED_CRYPTOAUTHLIB="no" +trylibatcadir="" + +# Check whether --with-cryptoauthlib was given. +if test "${with_cryptoauthlib+set}" = set; then : + withval=$with_cryptoauthlib; + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cryptoauthlib" >&5 +$as_echo_n "checking for cryptoauthlib... " >&6; } + CPPFLAGS="$CPPFLAGS -DWOLFSSL_ATECC508A" + LIBS="$LIBS -lcryptoauth" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + atcab_init(0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + libatca_linked=yes else - ENABLED_SNIFFER=no + libatca_linked=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + if test "x$libatca_linked" = "xno" ; then + if test "x$withval" != "xno" ; then + trylibatcadir=$withval + fi + if test "x$withval" = "xyes" ; then + trylibatcadir="/usr" + fi + + LDFLAGS="$LDFLAGS -L$trylibatcadir/lib" + CPPFLAGS="$CPPFLAGS -I$trylibatcadir/lib" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + atcab_init(0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + libatca_linked=yes +else + libatca_linked=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + if test "x$libatca_linked" = "xno" ; then + as_fn_error $? "cryptoauthlib isn't found. + If it's already installed, specify its path using --with-cryptoauthlib=/dir/" "$LINENO" 5 + fi + + AM_LDFLAGS="$AM_LDFLAGS -L$trylibatcadir/lib" + AM_CFLAGS="$AM_CFLAGS -I$trylibatcadir/lib" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + + ENABLED_CRYPTOAUTHLIB="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ATECC508A" + fi -# sniffer does't work in maxstrength mode + +# sniffer doesn't work in maxstrength mode if test "$ENABLED_SNIFFER" = "yes" && test "$ENABLED_MAXSTRENGTH" = "yes" then as_fn_error $? "cannot enable maxstrength in sniffer mode." "$LINENO" 5 @@ -18905,7 +16014,7 @@ fi ENABLED_SNIFFTEST=no if test "x$ENABLED_SNIFFER" = "xyes" ; then : - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SNIFFER -DOPENSSL_EXTRA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SNIFFER" for ac_header in pcap/pcap.h do : ac_fn_c_check_header_mongrel "$LINENO" "pcap/pcap.h" "ac_cv_header_pcap_pcap_h" "$ac_includes_default" @@ -18925,22 +16034,23 @@ done fi - if test "x$ENABLED_SNIFFER" = "xyes" ; then - BUILD_SNIFFER_TRUE= - BUILD_SNIFFER_FALSE='#' + +# AES-CBC +# Check whether --enable-aescbc was given. +if test "${enable_aescbc+set}" = set; then : + enableval=$enable_aescbc; ENABLED_AESCBC=$enableval else - BUILD_SNIFFER_TRUE='#' - BUILD_SNIFFER_FALSE= + ENABLED_AESCBC=yes + fi - if test "x$ENABLED_SNIFFTEST" = "xyes" ; then - BUILD_SNIFFTEST_TRUE= - BUILD_SNIFFTEST_FALSE='#' -else - BUILD_SNIFFTEST_TRUE='#' - BUILD_SNIFFTEST_FALSE= + +if test "$ENABLED_AESCBC" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DNO_AES_CBC" fi +# leanpsk and leantls don't need gcm # AES-GCM # Check whether --enable-aesgcm was given. @@ -18952,44 +16062,36 @@ else fi -# lean psk does't need gcm -if test "$ENABLED_LEANPSK" = "yes" +# leanpsk and leantls don't need gcm +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 - if test "x$ENABLED_AESGCM" = "xyes"; then - BUILD_AESGCM_TRUE= - BUILD_AESGCM_FALSE='#' -else - BUILD_AESGCM_TRUE='#' - BUILD_AESGCM_FALSE= -fi - - # AES-CCM # Check whether --enable-aesccm was given. @@ -19006,17 +16108,129 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_AESCCM" fi - if test "x$ENABLED_AESCCM" = "xyes"; then - BUILD_AESCCM_TRUE= - BUILD_AESCCM_FALSE='#' + +# AES-CTR +# Check whether --enable-aesctr was given. +if test "${enable_aesctr+set}" = set; then : + enableval=$enable_aesctr; ENABLED_AESCTR=$enableval else - BUILD_AESCCM_TRUE='#' - BUILD_AESCCM_FALSE= + ENABLED_AESCTR=no + +fi + +if test "$ENABLED_OPENVPN" = "yes" +then + ENABLED_AESCTR=yes +fi + +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-OFB +# Check whether --enable-aesofb was given. +if test "${enable_aesofb+set}" = set; then : + enableval=$enable_aesofb; ENABLED_AESOFB=$enableval +else + ENABLED_AESOFB=no -# AES-NI +fi + + +if test "$ENABLED_AESOFB" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_OFB -DWOLFSSL_AES_DIRECT" +fi + + +# AES-CFB +# Check whether --enable-aescfb was given. +if test "${enable_aescfb+set}" = set; then : + enableval=$enable_aescfb; ENABLED_AESCFB=$enableval +else + ENABLED_AESCFB=no + +fi + + +if test "$ENABLED_AESCFB" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_CFB" +fi + + +# AES-ARM +# Check whether --enable-armasm was given. +if test "${enable_armasm+set}" = set; then : + enableval=$enable_armasm; ENABLED_ARMASM=$enableval +else + ENABLED_ARMASM=no + +fi + +if test "$ENABLED_ARMASM" = "yes" && test "$ENABLED_ASM" = "yes" +then + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_ARMASM" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ARMASM -DWOLFSSL_NO_HASH_RAW" + #Check if mcpu and mfpu values already set if not use default + case $CPPFLAGS in + *mcpu* | *mfpu*) + break;; #Do not override user set values + *) + case $host_cpu in + *aarch64*) + # +crypto needed for hardware acceleration + AM_CPPFLAGS="$AM_CPPFLAGS -mcpu=generic+crypto" + + # Check for and set -mstrict-align compiler flag + # Used to set assumption that Aarch64 systems will not handle + # unaligned memory references. The flag -mstrict-align is needed + # on some compiler versions to avoid an invalid addressing mode + # error with "m" constraint variables in the inline assembly AES + # code. Even though unaligned load/store access is permitted on + # normal memory with Cortex-A series boards with the exception + # being exclusive and ordered access. + case $CPPFLAGS in + *mstrict-align*) + break;; # already set by user + *) + AM_CPPFLAGS="$AM_CPPFLAGS -mstrict-align" + { $as_echo "$as_me:${as_lineno-$LINENO}: 64bit ARMv8, setting -mstrict-align" >&5 +$as_echo "$as_me: 64bit ARMv8, setting -mstrict-align" >&6;};; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: 64bit ARMv8 found, setting mcpu to generic+crypto" >&5 +$as_echo "$as_me: 64bit ARMv8 found, setting mcpu to generic+crypto" >&6;};; + *) + AM_CPPFLAGS="$AM_CPPFLAGS -mfpu=crypto-neon-fp-armv8" + { $as_echo "$as_me:${as_lineno-$LINENO}: 32bit ARMv8 found, setting mfpu to crypto-neon-fp-armv8" >&5 +$as_echo "$as_me: 32bit ARMv8 found, setting mfpu to crypto-neon-fp-armv8" >&6;};; + esac + esac +fi + + +# Xilinx hardened crypto +# Check whether --enable-xilinx was given. +if test "${enable_xilinx+set}" = set; then : + enableval=$enable_xilinx; ENABLED_XILINX=$enableval +else + ENABLED_XILINX=no + +fi + +if test "$ENABLED_XILINX" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_XILINX -DWOLFSSL_XILINX_CRYPT" +fi + + +# INTEL AES-NI # Check whether --enable-aesni was given. if test "${enable_aesni+set}" = set; then : enableval=$enable_aesni; ENABLED_AESNI=$enableval @@ -19036,35 +16250,160 @@ else fi -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" + 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 - AM_CFLAGS="$AM_CFLAGS -maes -msse4" + # 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 + if test "x$ENABLED_AESGCM" != "xno"; then : + AM_CCASFLAGS="$AM_CCASFLAGS -DHAVE_AESGCM" +fi + fi + + if test "$ENABLED_INTELASM" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DHAVE_INTEL_RDSEED -DUSE_INTEL_SPEEDUP" + ENABLED_AESNI=yes fi fi -if test "$ENABLED_INTELASM" = "yes" -then - AM_CFLAGS="$AM_CFLAGS -DHAVE_INTEL_RDGEN -DUSE_INTEL_SPEEDUP" - ENABLED_AESNI=yes -fi - - if test "x$ENABLED_AESNI" = "xyes"; then - BUILD_AESNI_TRUE= - BUILD_AESNI_FALSE='#' +# INTEL RDRAND +# Check whether --enable-intelrand was given. +if test "${enable_intelrand+set}" = set; then : + enableval=$enable_intelrand; ENABLED_INTELRDRAND=$enableval else - BUILD_AESNI_TRUE='#' - BUILD_AESNI_FALSE= + ENABLED_INTELRDRAND=no + fi +if test "$ENABLED_INTELRDRAND" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_INTEL_RDRAND" +fi + + +# Linux af_alg +# Check whether --enable-afalg was given. +if test "${enable_afalg+set}" = set; then : + enableval=$enable_afalg; ENABLED_AFALG=$enableval +else + ENABLED_AFALG=no + +fi + + +if test "$ENABLED_AFALG" = "yes" +then + if test "$ENABLED_AESCCM" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_HASH" +fi + +if test "$ENABLED_AFALG" = "xilinx" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX -DWOLFSSL_AFALG_XILINX_AES" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX_SHA3 -DWOLFSSL_AFALG_XILINX_RSA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NOSHA3_224 -DWOLFSSL_NOSHA3_256 -DWOLFSSL_NOSHA3_512 -DWOLFSSL_NO_SHAKE256" + ENABLED_AFALG="yes" + ENABLED_XILINX="yes" +fi + +if test "$ENABLED_AFALG" = "xilinx-aes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX -DWOLFSSL_AFALG_XILINX_AES" + ENABLED_AFALG="yes" + ENABLED_XILINX="yes" +fi + +if test "$ENABLED_AFALG" = "xilinx-sha3" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX_SHA3" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NOSHA3_224 -DWOLFSSL_NOSHA3_256 -DWOLFSSL_NOSHA3_512 -DWOLFSSL_NO_SHAKE256" + ENABLED_AFALG="yes" + ENABLED_XILINX="yes" +fi + +if test "$ENABLED_AFALG" = "xilinx-rsa" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX_RSA" + ENABLED_AFALG="yes" + ENABLED_XILINX="yes" +fi + + +# Support for Linux dev/crypto calls +# Check whether --enable-devcrypto was given. +if test "${enable_devcrypto+set}" = set; then : + enableval=$enable_devcrypto; ENABLED_DEVCRYPTO=$enableval +else + ENABLED_DEVCRYPTO=no + +fi + + +if test "$ENABLED_DEVCRYPTO" = "yes" || test "$ENABLED_DEVCRYPTO" = "all" +then + #enable all devcrypto supported algorithms + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_CBC" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_AES" + if test "$ENABLED_AESCCM" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_HASH" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_HASH_RAW" + ENABLED_DEVCRYPTO=yes +fi +if test "$ENABLED_DEVCRYPTO" = "aes" +then + #enable only AES-CBC algorithm support + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_AES" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_CBC" + if test "$ENABLED_AESCCM" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT" + fi + ENABLED_DEVCRYPTO=yes +fi +if test "$ENABLED_DEVCRYPTO" = "cbc" +then + #enable only AES-CBC algorithm support + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_CBC" + ENABLED_DEVCRYPTO=yes +fi +if test "$ENABLED_DEVCRYPTO" = "hash" +then + #enable only hash algorithm support + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_HASH" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_HASH_RAW" + ENABLED_DEVCRYPTO=yes +fi + # Camellia # Check whether --enable-camellia was given. @@ -19081,15 +16420,6 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_CAMELLIA" fi - if test "x$ENABLED_CAMELLIA" = "xyes"; then - BUILD_CAMELLIA_TRUE= - BUILD_CAMELLIA_FALSE='#' -else - BUILD_CAMELLIA_TRUE='#' - BUILD_CAMELLIA_FALSE= -fi - - # MD2 # Check whether --enable-md2 was given. @@ -19111,15 +16441,6 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MD2" fi - if test "x$ENABLED_MD2" = "xyes"; then - BUILD_MD2_TRUE= - BUILD_MD2_FALSE='#' -else - BUILD_MD2_TRUE='#' - BUILD_MD2_FALSE= -fi - - # NULL CIPHER # Check whether --enable-nullcipher was given. @@ -19131,6 +16452,11 @@ else fi +if test "$ENABLED_OPENSSH" = "yes" +then + ENABLED_NULL_CIPHER="yes" +fi + if test "$ENABLED_NULL_CIPHER" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_NULL_CIPHER" @@ -19146,20 +16472,16 @@ else fi +if test "$ENABLED_OPENSSH" = "yes" +then + ENABLED_RIPEMD="yes" +fi + if test "$ENABLED_RIPEMD" = "yes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_RIPEMD" fi - if test "x$ENABLED_RIPEMD" = "xyes"; then - BUILD_RIPEMD_TRUE= - BUILD_RIPEMD_FALSE='#' -else - BUILD_RIPEMD_TRUE='#' - BUILD_RIPEMD_FALSE= -fi - - # BLAKE2 # Check whether --enable-blake2 was given. @@ -19173,62 +16495,81 @@ fi if test "$ENABLED_BLAKE2" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DHAVE_BLAKE2" + AM_CFLAGS="$AM_CFLAGS -DHAVE_BLAKE2 -DHAVE_BLAKE2B" fi - if test "x$ENABLED_BLAKE2" = "xyes"; then - BUILD_BLAKE2_TRUE= - BUILD_BLAKE2_FALSE='#' + +# Check whether --enable-blake2s was given. +if test "${enable_blake2s+set}" = set; then : + enableval=$enable_blake2s; ENABLED_BLAKE2S=$enableval else - BUILD_BLAKE2_TRUE='#' - BUILD_BLAKE2_FALSE= + ENABLED_BLAKE2S=Sno + fi - -# set sha512 default -SHA512_DEFAULT=no -if test "$host_cpu" = "x86_64" +if test "$ENABLED_BLAKE2S" = "yes" then -SHA512_DEFAULT=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_BLAKE2S" + ENABLED_BLAKE2="yes" fi + # SHA512 # Check whether --enable-sha512 was given. if test "${enable_sha512+set}" = set; then : enableval=$enable_sha512; ENABLED_SHA512=$enableval else - ENABLED_SHA512=$SHA512_DEFAULT + ENABLED_SHA512=yes fi -# lean psk does't need sha512 -if test "$ENABLED_LEANPSK" = "yes" +# options that don't require sha512 +if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" || test "$ENABLED_32BIT" = "yes" || test "$ENABLED_16BIT" = "yes" then - ENABLED_SHA512=no + ENABLED_SHA512="no" +fi + +# options that require sha512 +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_WPAS" = "yes" || test "$ENABLED_FORTRESS" = "yes" +then + ENABLED_SHA512="yes" + ENABLED_SHA384="yes" fi if test "$ENABLED_SHA512" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512 -DWOLFSSL_SHA384" -fi - -if test "$ENABLED_FORTRESS" = "yes" -then - ENABLED_SHA512="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512" fi - if test "x$ENABLED_SHA512" = "xyes"; then - BUILD_SHA512_TRUE= - BUILD_SHA512_FALSE='#' +# SHA384 +# Check whether --enable-sha384 was given. +if test "${enable_sha384+set}" = set; then : + enableval=$enable_sha384; ENABLED_SHA384=$enableval else - BUILD_SHA512_TRUE='#' - BUILD_SHA512_FALSE= + ENABLED_SHA384=yes + fi +# options that don't require sha384 +if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" || test "$ENABLED_32BIT" = "yes" || test "$ENABLED_16BIT" = "yes" +then + ENABLED_SHA384="no" +fi + +# options that require sha384 +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_WPAS" = "yes" || test "$ENABLED_FORTRESS" = "yes" +then + ENABLED_SHA384="yes" +fi +if test "$ENABLED_SHA384" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA384" +fi + # SESSION CERTS # Check whether --enable-sessioncerts was given. @@ -19240,6 +16581,15 @@ else fi +if test "x$ENABLED_NGINX" = "xyes" || test "x$ENABLED_OPENVPN" = "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" @@ -19271,6 +16621,10 @@ else fi +if test "$ENABLED_OPENVPN" = "yes" +then + ENABLED_CERTGEN=yes +fi if test "$ENABLED_CERTGEN" = "yes" then @@ -19298,6 +16652,42 @@ then fi +# CERT REQUEST EXTENSION +# Check whether --enable-certext was given. +if test "${enable_certext+set}" = set; then : + enableval=$enable_certext; ENABLED_CERTEXT=$enableval +else + ENABLED_CERTEXT=no + +fi + +if test "$ENABLED_OPENVPN" = "yes" +then + ENABLED_CERTEXT=yes +fi + +if test "$ENABLED_CERTEXT" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" +fi + + +# DECODED CERT CACHE +# Check whether --enable-certgencache was given. +if test "${enable_certgencache+set}" = set; then : + enableval=$enable_certgencache; ENABLED_certgencache=$enableval +else + ENABLED_certgencache=no + +fi + + +if test "$ENABLED_certgencache" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN_CACHE" +fi + + # SEP # Check whether --enable-sep was given. if test "${enable_sep+set}" = set; then : @@ -19322,11 +16712,28 @@ else fi +if test "$ENABLED_TLS13" = "yes" +then + ENABLED_HKDF="yes" +fi if test "$ENABLED_HKDF" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_HKDF" fi +# X9.63 KDF +# Check whether --enable-x963kdf was given. +if test "${enable_x963kdf+set}" = set; then : + enableval=$enable_x963kdf; ENABLED_X963KDF=$enableval +else + ENABLED_X963KDF=no + +fi + +if test "$ENABLED_X963KDF" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_X963_KDF" +fi # DSA # Check whether --enable-dsa was given. @@ -19338,68 +16745,113 @@ else fi -if test "$ENABLED_DSA" = "no" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" || test "$ENABLED_WPAS" = "yes" || test "$ENABLED_QT" = "yes" +then + ENABLED_DSA="yes" +fi + +if test "$ENABLED_DSA" = "no" && test "$ENABLED_OPENSSH" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_DSA" fi - if test "x$ENABLED_DSA" = "xyes"; then - BUILD_DSA_TRUE= - BUILD_DSA_FALSE='#' +# ECC Shamir +# Check whether --enable-eccshamir was given. +if test "${enable_eccshamir+set}" = set; then : + enableval=$enable_eccshamir; ENABLED_ECC_SHAMIR=$enableval else - BUILD_DSA_TRUE='#' - BUILD_DSA_FALSE= + ENABLED_ECC_SHAMIR=yes + fi -# set ecc default -ECC_DEFAULT=no - -if test "$host_cpu" = "x86_64" -then -ECC_DEFAULT=yes -fi - # ECC # Check whether --enable-ecc was given. if test "${enable_ecc+set}" = set; then : enableval=$enable_ecc; ENABLED_ECC=$enableval else - ENABLED_ECC=$ECC_DEFAULT + ENABLED_ECC=yes fi -# lean psk does't need ecc +# lean psk doesn't need ecc if test "$ENABLED_LEANPSK" = "yes" then ENABLED_ECC=no fi +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" || test "$ENABLED_SIGNAL" = "yes" +then + ENABLED_ECC="yes" +fi + if test "$ENABLED_ECC" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256 -DECC_SHAMIR" + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" + if test "$ENABLED_ECC_SHAMIR" = "yes" && test "$ENABLED_LOWRESOURCE" = "no" + then + AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR" + fi fi - if test "x$ENABLED_ECC" = "xyes"; then - BUILD_ECC_TRUE= - BUILD_ECC_FALSE='#' + +# ECC Custom Curves +# Check whether --enable-ecccustcurves was given. +if test "${enable_ecccustcurves+set}" = set; then : + enableval=$enable_ecccustcurves; ENABLED_ECCCUSTCURVES=$enableval else - BUILD_ECC_TRUE='#' - BUILD_ECC_FALSE= + ENABLED_ECCCUSTCURVES=no + fi - -if test "$ENABLED_ECC" = "yes" && test "$ENABLED_SMALL" = "yes" +if test "$ENABLED_ECCCUSTCURVES" != "no" then - as_fn_error $? "cannot enable ecc and small, ecc requires TLS which small turns off." "$LINENO" 5 + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CUSTOM_CURVES" + + # For distro, all or ecccustcurves=all builds, enable all curve types + if test "$ENABLED_DISTRO" = "yes" || test "$ENABLED_ALL" = "yes" || test "$ENABLED_ECCCUSTCURVES" = "all" + then + # Enable ECC SECPR2, SECPR3, BRAINPOOL and KOBLITZ curves + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ" + + # Enable ECC Cofactor support + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_CDH" + + # If fastmath enabled and on x86 use speedups + if test "x$ENABLED_FASTMATH" = "xyes" && test "$host_cpu" = "x86_64" + then + AM_CFLAGS="$AM_CFLAGS -DTFM_ECC192 -DTFM_ECC224 -DTFM_ECC256 -DTFM_ECC384 -DTFM_ECC521" + fi + fi +fi + + +# Compressed Key +# Check whether --enable-compkey was given. +if test "${enable_compkey+set}" = set; then : + enableval=$enable_compkey; ENABLED_COMPKEY=$enableval +else + ENABLED_COMPKEY=no + +fi + + +if test "$ENABLED_WPAS" = "yes" +then + ENABLED_COMPKEY=yes +fi +if test "$ENABLED_COMPKEY" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_COMP_KEY" fi # for using memory optimization setting on both curve25519 and ed25519 -ENABLED_CURVED25519_SMALL=no +ENABLED_CURVE25519_SMALL=no +ENABLED_ED25519_SMALL=no # CURVE25519 # Check whether --enable-curve25519 was given. @@ -19412,30 +16864,31 @@ fi -if test "$ENABLED_CURVE25519" = "small" +if test "$ENABLED_OPENSSH" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DCURVED25519_SMALL" - ENABLED_CURVED25519_SMALL=yes - ENABLED_CURVE25519=yes + ENABLED_CURVE25519="yes" fi -if test "$ENABLED_CURVE25519" = "yes" +if test "$ENABLED_CURVE25519" != "no" then + 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" || test "$ENABLED_32BIT" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DNO_CURVED25519_128BIT" + ENABLED_CURVE25519=yes + fi + AM_CFLAGS="$AM_CFLAGS -DHAVE_CURVE25519" ENABLED_FEMATH=yes fi - if test "x$ENABLED_CURVE25519" = "xyes"; then - BUILD_CURVE25519_TRUE= - BUILD_CURVE25519_FALSE='#' -else - BUILD_CURVE25519_TRUE='#' - BUILD_CURVE25519_FALSE= -fi - - - # ED25519 # Check whether --enable-ed25519 was given. if test "${enable_ed25519+set}" = set; then : @@ -19447,15 +16900,21 @@ fi -if test "$ENABLED_ED25519" = "small" +if test "$ENABLED_OPENSSH" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DCURVED25519_SMALL" - ENABLED_CURVED25519_SMALL=yes - ENABLED_ED25519=yes + ENABLED_ED25519="yes" fi -if test "$ENABLED_ED25519" = "yes" +if test "$ENABLED_ED25519" != "no" && test "$ENABLED_32BIT" = "no" then + if test "$ENABLED_ED25519" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DED25519_SMALL" + ENABLED_ED25519_SMALL=yes + ENABLED_CURVE25519_SMALL=yes + ENABLED_ED25519=yes + fi + if test "$ENABLED_SHA512" = "no" then as_fn_error $? "cannot enable ed25519 without enabling sha512." "$LINENO" 5 @@ -19465,39 +16924,75 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_ED25519" fi - if test "x$ENABLED_ED25519" = "xyes"; then - BUILD_ED25519_TRUE= - BUILD_ED25519_FALSE='#' + +# for using memory optimization setting on both curve448 and ed448 +ENABLED_CURVE448_SMALL=no +ENABLED_ED448_SMALL=no + +# CURVE448 +# Check whether --enable-curve448 was given. +if test "${enable_curve448+set}" = set; then : + enableval=$enable_curve448; ENABLED_CURVE448=$enableval else - BUILD_ED25519_TRUE='#' - BUILD_ED25519_FALSE= + ENABLED_CURVE448=no + fi - if test "x$ENABLED_CURVED25519_SMALL" = "xyes"; then - BUILD_CURVED25519_SMALL_TRUE= - BUILD_CURVED25519_SMALL_FALSE='#' -else - BUILD_CURVED25519_SMALL_TRUE='#' - BUILD_CURVED25519_SMALL_FALSE= + +if test "$ENABLED_CURVE448" != "no" +then + if test "$ENABLED_CURVE448" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DCURVE448_SMALL" + ENABLED_CURVE448_SMALL=yes + ENABLED_CURVE448=yes + fi + + if test "$ENABLED_CURVE448" = "no128bit" || test "$ENABLED_32BIT" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DNO_CURVED448_128BIT" + ENABLED_CURVE448=yes + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_CURVE448" + ENABLED_FE448=yes fi - if test "x$ENABLED_FEMATH" = "xyes"; then - BUILD_FEMATH_TRUE= - BUILD_FEMATH_FALSE='#' +# ED448 +# Check whether --enable-ed448 was given. +if test "${enable_ed448+set}" = set; then : + enableval=$enable_ed448; ENABLED_ED448=$enableval else - BUILD_FEMATH_TRUE='#' - BUILD_FEMATH_FALSE= + ENABLED_ED448=no + fi - if test "x$ENABLED_GEMATH" = "xyes"; then - BUILD_GEMATH_TRUE= - BUILD_GEMATH_FALSE='#' -else - BUILD_GEMATH_TRUE='#' - BUILD_GEMATH_FALSE= + +if test "$ENABLED_ED448" != "no" && test "$ENABLED_32BIT" = "no" +then + if test "$ENABLED_ED448" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DED448_SMALL" + ENABLED_ED448_SMALL=yes + ENABLED_CURVE448_SMALL=yes + ENABLED_ED448=yes + fi + + if test "$ENABLED_SHA512" = "no" + then + as_fn_error $? "cannot enable ed448 without enabling sha512." "$LINENO" 5 + fi + ENABLED_FE448=yes + ENABLED_GE448=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_ED448" + + # EdDSA448 requires SHAKE256 which requires SHA-3 + ENABLED_SHAKE3=yes + ENABLED_SHAKE256=yes fi + # FP ECC, Fixed Point cache ECC # Check whether --enable-fpecc was given. if test "${enable_fpecc+set}" = set; then : @@ -19552,17 +17047,24 @@ else fi -if test "$ENABLED_PSK" = "no" && test "$ENABLED_LEANPSK" = "no" -then - AM_CFLAGS="$AM_CFLAGS -DNO_PSK" +# Single PSK identity +# Check whether --enable-psk-one-id was given. +if test "${enable_psk_one_id+set}" = set; then : + enableval=$enable_psk_one_id; ENABLED_PSK_ONE_ID=$enableval +else + ENABLED_PSK_ONE_ID=no + fi -if test "$ENABLED_PSK" = "no" && test "$ENABLED_LEANPSK" = "yes" +if test "$ENABLED_PSK_ONE_ID" = "yes" then - ENABLED_PSK=yes + if test "$ENABLED_PSK" = "no" + then + ENABLED_PSK="yes" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_PSK_ONE_ID" fi - # ERROR STRINGS # Check whether --enable-errorstrings was given. if test "${enable_errorstrings+set}" = set; then : @@ -19577,8 +17079,8 @@ if test "$ENABLED_ERROR_STRINGS" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_ERROR_STRINGS" else - # turn off error strings if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off error strings if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_ERROR_STRINGS" ENABLED_ERROR_STRINGS=no @@ -19586,6 +17088,22 @@ else fi +# ERROR QUEUE +# Check whether --enable-errorqueue was given. +if test "${enable_errorqueue+set}" = set; then : + enableval=$enable_errorqueue; ENABLED_ERROR_QUEUE=$enableval +else + ENABLED_ERROR_QUEUE=yes + +fi + + +if test "$ENABLED_ERROR_QUEUE" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DNO_ERROR_QUEUE" +fi + + # OLD TLS # Check whether --enable-oldtls was given. if test "${enable_oldtls+set}" = set; then : @@ -19600,8 +17118,8 @@ if test "$ENABLED_OLD_TLS" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_OLD_TLS" else - # turn off old if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off old if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_OLD_TLS" ENABLED_OLD_TLS=no @@ -19609,6 +17127,59 @@ else fi +# TLSv1.2 +# Check whether --enable-tlsv12 was given. +if test "${enable_tlsv12+set}" = set; then : + enableval=$enable_tlsv12; ENABLED_TLSV12=$enableval +else + ENABLED_TLSV12=yes + +fi + + +if test "$ENABLED_TLSV12" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_TLS12 -DNO_OLD_TLS" +fi + + +# TLSv1.0 +# Check whether --enable-tlsv10 was given. +if test "${enable_tlsv10+set}" = set; then : + enableval=$enable_tlsv10; ENABLED_TLSV10=$enableval +else + ENABLED_TLSV10=no + +fi + + +if test "$ENABLED_TLSV10" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALLOW_TLSV10" +fi + + +# SSLv3 +# Check whether --enable-sslv3 was given. +if test "${enable_sslv3+set}" = set; then : + enableval=$enable_sslv3; ENABLED_SSLV3=$enableval +else + ENABLED_SSLV3=no + +fi + + +if test "x$ENABLED_HAPROXY" = "xyes" +then + ENABLED_SSLV3="yes" +fi + +if test "$ENABLED_SSLV3" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALLOW_SSLV3" +fi + + # STACK SIZE info for examples # Check whether --enable-stacksize was given. if test "${enable_stacksize+set}" = set; then : @@ -19679,7 +17250,7 @@ fi fi - AM_CFLAGS="$AM_CFLAGS -DHAVE_STACK_SIZE -DWOLFSSL_LOW_MEMORY" + AM_CFLAGS="$AM_CFLAGS -DHAVE_STACK_SIZE" fi @@ -19697,23 +17268,128 @@ if test "$ENABLED_MEMORY" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_WOLFSSL_MEMORY" else - # turn off memory cb if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off memory cb if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then # but don't turn on NO_WOLFSSL_MEMORY because using own ENABLED_MEMORY=no fi fi - if test "x$ENABLED_MEMORY" = "xyes"; then - BUILD_MEMORY_TRUE= - BUILD_MEMORY_FALSE='#' + +# MEMORY SIZE info +# Check whether --enable-trackmemory was given. +if test "${enable_trackmemory+set}" = set; then : + enableval=$enable_trackmemory; ENABLED_TRACKMEMORY=$enableval else - BUILD_MEMORY_TRUE='#' - BUILD_MEMORY_FALSE= + ENABLED_TRACKMEMORY=no + fi +if test "$ENABLED_TRACKMEMORY" = "yes" +then + if test "$ENABLED_MEMORY" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TRACK_MEMORY" + else + as_fn_error $? "trackmemory requires using wolfSSL memory (--enable-memory)." "$LINENO" 5 + fi +fi + +# MEMORY usage logging +# Check whether --enable-memorylog was given. +if test "${enable_memorylog+set}" = set; then : + enableval=$enable_memorylog; ENABLED_MEMORYLOG=$enableval +else + ENABLED_MEMORYLOG=no + +fi + + +if test "$ENABLED_MEMORYLOG" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MEMORY_LOG" +fi + + +# STACK usage logging +# Check whether --enable-stacklog was given. +if test "${enable_stacklog+set}" = set; then : + enableval=$enable_stacklog; ENABLED_STACKLOG=$enableval +else + ENABLED_STACKLOG=no + +fi + + +if test "$ENABLED_STACKLOG" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STACK_LOG -finstrument-functions" +fi + +if test "$ENABLED_QT" = "yes" +then + # Requires opensslextra and opensslall + if test "x$ENABLED_OPENSSLALL" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" + then + ENABLED_OPENSSLALL="yes" + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_EXTRA -DOPENSSL_ALL -DHAVE_EX_DATA" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_QT -DWOLFSSL_ALLOW_TLSV10 -DSESSION_CERTS -DOPENSSL_NO_SSL2" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALLOW_SSLV3 -DWOLFSSL_KEY_GEN -DHAVE_EX_DATA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CUSTOM_CURVES -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ" + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi + + # Requires PSK make sure on + if test "x$ENABLED_PSK" = "xno" + then + ENABLED_PSK="yes" + fi + + # Requires RC4 make sure on + if test "x$ENABLED_ARC4" = "xno" + then + ENABLED_ARC4="yes" + fi + + if test "x$ENABLED_CERTEXT" = "xno" + then + ENABLED_CERTEXT="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" + fi + + if test "x$ENABLED_CERTGEN" = "xno" + then + ENABLED_CERTGEN="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN" + fi + + # requires oldnames disabled + enable_oldnames=no +fi + +# Check whether --enable-qt-test was given. +if test "${enable_qt_test+set}" = set; then : + enableval=$enable_qt_test; ENABLED_QT_TEST=$enableval +else + ENABLED_QT_TEST=no + +fi + + +if test "$ENABLED_QT_TEST" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_NO_SSL3 -DWOLFSSL_STATIC_RSA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_PSK" +fi # RSA # Check whether --enable-rsa was given. @@ -19729,23 +17405,90 @@ if test "$ENABLED_RSA" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_RSA" else - # turn off RSA if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off RSA if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_RSA" ENABLED_RSA=no fi fi - if test "x$ENABLED_RSA" = "xyes"; then - BUILD_RSA_TRUE= - BUILD_RSA_FALSE='#' +# Check whether --enable-oaep was given. +if test "${enable_oaep+set}" = set; then : + enableval=$enable_oaep; ENABLED_OAEP=$enableval else - BUILD_RSA_TRUE='#' - BUILD_RSA_FALSE= + ENABLED_OAEP=yes + fi +if test "$ENABLED_OAEP" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DWC_NO_RSA_OAEP" +fi + +# Check whether --enable-rsapub was given. +if test "${enable_rsapub+set}" = set; then : + enableval=$enable_rsapub; ENABLED_RSAPUB=$enableval +else + ENABLED_RSAPUB=no + +fi + + +if test "$ENABLED_RSAPUB" = "yes" +then + if test "$ENABLED_RSA" = "no" + then + ENABLED_RSA="yes" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_RSA_PUBLIC_ONLY" +fi + +# Check whether --enable-rsavfy was given. +if test "${enable_rsavfy+set}" = set; then : + enableval=$enable_rsavfy; ENABLED_RSAVFY=$enableval +else + ENABLED_RSAVFY=no + +fi + + +if test "$ENABLED_RSAVFY" = "yes" +then + if test "$ENABLED_RSA" = "no" + then + ENABLED_RSA="yes" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_RSA_PUBLIC_ONLY -DWOLFSSL_RSA_VERIFY_ONLY" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_RSA_VERIFY_INLINE -DNO_SIG_WRAPPER" +fi + + +# RSA-PSS +# Check whether --enable-rsapss was given. +if test "${enable_rsapss+set}" = set; then : + enableval=$enable_rsapss; ENABLED_RSAPSS=$enableval +else + ENABLED_RSAPSS=no + +fi + + +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 # Check whether --enable-dh was given. @@ -19757,27 +17500,23 @@ else fi +if test "$ENABLED_OPENSSH" = "yes" +then + ENABLED_DH="yes" +fi + if test "$ENABLED_DH" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_DH" else - # turn off DH if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off DH if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_DH" ENABLED_DH=no fi fi - if test "x$ENABLED_DH" = "xyes"; then - BUILD_DH_TRUE= - BUILD_DH_FALSE='#' -else - BUILD_DH_TRUE='#' - BUILD_DH_FALSE= -fi - - # Anonymous # Check whether --enable-anon was given. @@ -19789,7 +17528,10 @@ else fi - +if test "x$ENABLED_WPAS" = "xyes" +then + ENABLED_ANON=yes +fi if test "x$ENABLED_ANON" = "xyes" then if test "x$ENABLED_DH" != "xyes" @@ -19815,9 +17557,9 @@ fi if test "$ENABLED_ASN" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_ASN -DNO_CERTS" - if test "$ENABLED_DH" = "no" + if test "$ENABLED_DH" = "no" && test "$ENABLED_ECC" = "no" then - # DH needs bigint + # DH and ECC need bigint AM_CFLAGS="$AM_CFLAGS -DNO_BIG_INT" fi else @@ -19826,10 +17568,16 @@ else then AM_CFLAGS="$AM_CFLAGS -DNO_ASN -DNO_CERTS -DNO_BIG_INT" ENABLED_ASN=no + else + if test "$ENABLED_ASN" = "nocrypt" + then + AM_CFLAGS="$AM_CFLAGS -DNO_ASN_CRYPT" + enable_pwdbased=no + fi fi fi -if test "$ENABLED_RSA" = "yes" && test "$ENABLED_ASN" = "no" +if test "$ENABLED_RSA" = "yes" && test "$ENABLED_RSAVFY" = "no" && test "$ENABLED_ASN" = "no" then as_fn_error $? "please disable rsa if disabling asn." "$LINENO" 5 fi @@ -19839,32 +17587,13 @@ then as_fn_error $? "please disable dsa if disabling asn." "$LINENO" 5 fi -if test "$ENABLED_ECC" = "yes" && test "$ENABLED_ASN" = "no" -then - as_fn_error $? "please disable ecc if disabling asn." "$LINENO" 5 -fi - -if test "$ENABLED_PSK" = "no" && test "$ENABLED_ASN" = "no" -then - as_fn_error $? "please enable psk if disabling asn." "$LINENO" 5 -fi - -# DH needs bigint -if test "$ENABLED_ASN" = "no" && test "$ENABLED_DH" = "no" +# DH and ECC need bigint +if test "$ENABLED_ASN" = "no" && test "$ENABLED_DH" = "no" && test "$ENABLED_ECC" = "no" && test "$ENABLED_RSA" = "no" then ENABLED_FASTMATH=no ENABLED_SLOWMATH=no fi - if test "x$ENABLED_ASN" = "xyes"; then - BUILD_ASN_TRUE= - BUILD_ASN_FALSE='#' -else - BUILD_ASN_TRUE='#' - BUILD_ASN_FALSE= -fi - - # AES # Check whether --enable-aes was given. @@ -19879,6 +17608,14 @@ fi if test "$ENABLED_AES" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_AES" + if test "$ENABLED_FORTRESS" = "yes" + then + as_fn_error $? "fortress requires aes" "$LINENO" 5 + fi + if test "$ENABLED_ECC_ENCRYPT" = "yes" + then + as_fn_error $? "cannot enable eccencrypt and hkdf without aes." "$LINENO" 5 + fi if test "$ENABLED_AESGCM" = "yes" then as_fn_error $? "AESGCM requires AES." "$LINENO" 5 @@ -19887,6 +17624,10 @@ then then as_fn_error $? "AESCCM requires AES." "$LINENO" 5 fi + if test "$ENABLED_AESCTR" = "yes" + then + as_fn_error $? "AESCTR requires AES." "$LINENO" 5 + fi else # turn off AES if leanpsk on if test "$ENABLED_LEANPSK" = "yes" @@ -19896,15 +17637,6 @@ else fi fi - if test "x$ENABLED_AES" = "xyes"; then - BUILD_AES_TRUE= - BUILD_AES_FALSE='#' -else - BUILD_AES_TRUE='#' - BUILD_AES_FALSE= -fi - - # CODING # Check whether --enable-coding was given. @@ -19928,14 +17660,40 @@ else fi fi - if test "x$ENABLED_CODING" = "xyes"; then - BUILD_CODING_TRUE= - BUILD_CODING_FALSE='#' + +# Base64 Encode +BASE64ENCODE_DEFAULT=no +if test "$host_cpu" = "x86_64" +then +BASE64ENCODE_DEFAULT=yes +fi +# Check whether --enable-base64encode was given. +if test "${enable_base64encode+set}" = set; then : + enableval=$enable_base64encode; ENABLED_BASE64ENCODE=$enableval else - BUILD_CODING_TRUE='#' - BUILD_CODING_FALSE= + ENABLED_BASE64ENCODE=$BASE64ENCODE_DEFAULT + fi +if test "$ENABLED_BASE64ENCODE" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_BASE64_ENCODE" +fi + + +# Base16 +# Check whether --enable-base16 was given. +if test "${enable_base16+set}" = set; then : + enableval=$enable_base16; ENABLED_BASE16=$enableval +else + ENABLED_BASE16=no + +fi + +if test "$ENABLED_BASE16" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_BASE16" +fi # DES3 @@ -19943,32 +17701,30 @@ fi if test "${enable_des3+set}" = set; then : enableval=$enable_des3; ENABLED_DES3=$enableval else - ENABLED_DES3=yes + ENABLED_DES3=no fi -if test "$ENABLED_DES3" = "no" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_QT" = "yes" || test "$ENABLED_OPENVPN" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DNO_DES3" -else - # turn off DES3 if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" - then - AM_CFLAGS="$AM_CFLAGS -DNO_DES3" - ENABLED_DES3=no - fi + ENABLED_DES3="yes" fi - if test "x$ENABLED_DES3" = "xyes"; then - BUILD_DES3_TRUE= - BUILD_DES3_FALSE='#' +# IDEA +# Check whether --enable-idea was given. +if test "${enable_idea+set}" = set; then : + enableval=$enable_idea; ENABLED_IDEA=$enableval else - BUILD_DES3_TRUE='#' - BUILD_DES3_FALSE= + ENABLED_IDEA=no + fi +if test "x$ENABLED_IDEA" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_IDEA" +fi # ARC4 # Check whether --enable-arc4 was given. @@ -19980,28 +17736,23 @@ else fi +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_WPAS" = "yes" +then + ENABLED_ARC4="yes" +fi + if test "$ENABLED_ARC4" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_RC4" else - # turn off ARC4 if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off ARC4 if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_RC4" ENABLED_ARC4=no fi fi - if test "x$ENABLED_ARC4" = "xyes"; then - BUILD_RC4_TRUE= - BUILD_RC4_FALSE='#' -else - BUILD_RC4_TRUE='#' - BUILD_RC4_FALSE= -fi - - - # MD5 # Check whether --enable-md5 was given. if test "${enable_md5+set}" = set; then : @@ -20016,23 +17767,14 @@ if test "$ENABLED_MD5" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_MD5 -DNO_OLD_TLS" else - # turn off MD5 if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off MD5 if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_MD5 -DNO_OLD_TLS" ENABLED_MD5=no fi fi - if test "x$ENABLED_MD5" = "xyes"; then - BUILD_MD5_TRUE= - BUILD_MD5_FALSE='#' -else - BUILD_MD5_TRUE='#' - BUILD_MD5_FALSE= -fi - - # SHA # Check whether --enable-sha was given. @@ -20048,48 +17790,49 @@ if test "$ENABLED_SHA" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_SHA -DNO_OLD_TLS" else - # turn off SHA if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off SHA if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_SHA -DNO_OLD_TLS" ENABLED_SHA=no fi fi - if test "x$ENABLED_SHA" = "xyes"; then - BUILD_SHA_TRUE= - BUILD_SHA_FALSE='#' + +# CMAC +# Check whether --enable-cmac was given. +if test "${enable_cmac+set}" = set; then : + enableval=$enable_cmac; ENABLED_CMAC=$enableval else - BUILD_SHA_TRUE='#' - BUILD_SHA_FALSE= -fi - - - -# MD4 -# Check whether --enable-md4 was given. -if test "${enable_md4+set}" = set; then : - enableval=$enable_md4; ENABLED_MD4=$enableval -else - ENABLED_MD4=no + ENABLED_CMAC=no fi -if test "$ENABLED_MD4" = "no" +if test "$ENABLED_WPAS" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DNO_MD4" + ENABLED_CMAC=yes fi - if test "x$ENABLED_MD4" = "xyes"; then - BUILD_MD4_TRUE= - BUILD_MD4_FALSE='#' +if test "x$ENABLED_CMAC" = "xyes"; then : + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CMAC -DWOLFSSL_AES_DIRECT" +fi + + +# AES-XTS +# Check whether --enable-xts was given. +if test "${enable_xts+set}" = set; then : + enableval=$enable_xts; ENABLED_XTS=$enableval else - BUILD_MD4_TRUE='#' - BUILD_MD4_FALSE= + ENABLED_XTS=no + fi +if test "x$ENABLED_XTS" = "xyes"; then : + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_XTS -DWOLFSSL_AES_DIRECT" +fi + # Web Server Build # Check whether --enable-webserver was given. @@ -20106,6 +17849,20 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_WEBSERVER" fi +# Web Client Build (HTTP Client) +# Check whether --enable-webclient was given. +if test "${enable_webclient+set}" = set; then : + enableval=$enable_webclient; ENABLED_WEBCLIENT=$enableval +else + ENABLED_WEBCLIENT=no + +fi + + +if test "$ENABLED_WEBCLIENT" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_HTTP_CLIENT" +fi # HC128 @@ -20125,15 +17882,6 @@ else AM_CFLAGS="$AM_CFLAGS -DHAVE_HC128" fi - if test "x$ENABLED_HC128" = "xyes"; then - BUILD_HC128_TRUE= - BUILD_HC128_FALSE='#' -else - BUILD_HC128_TRUE='#' - BUILD_HC128_FALSE= -fi - - # RABBIT # Check whether --enable-rabbit was given. @@ -20152,74 +17900,195 @@ else AM_CFLAGS="$AM_CFLAGS -DHAVE_RABBIT" fi - if test "x$ENABLED_RABBIT" = "xyes"; then - BUILD_RABBIT_TRUE= - BUILD_RABBIT_FALSE='#' -else - BUILD_RABBIT_TRUE='#' - BUILD_RABBIT_FALSE= -fi - - # FIPS # Check whether --enable-fips was given. if test "${enable_fips+set}" = set; then : - enableval=$enable_fips; ENABLED_FIPS=$enableval + enableval=$enable_fips; ENABLED_FIPS=$enableval else - ENABLED_FIPS=no + ENABLED_FIPS="no" +fi + + +case $ENABLED_FIPS in #( + "v2") : + FIPS_VERSION="v2" + ENABLED_FIPS=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS -DHAVE_FIPS_VERSION=2 -DWOLFSSL_KEY_GEN -DWOLFSSL_SHA224 -DWOLFSSL_AES_DIRECT -DHAVE_AES_ECB -DHAVE_ECC_CDH -DWC_RSA_NO_PADDING -DWOLFSSL_VALIDATE_FFC_IMPORT -DHAVE_FFDHE_Q" + ENABLED_KEYGEN="yes" + ENABLED_SHA224="yes" + # Shake256 is a SHA-3 algorithm not in our FIPS algorithm list + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_SHAKE256" + if test "x$ENABLED_AESCCM" != "xyes"; then : + ENABLED_AESCCM="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_AESCCM" +fi + if test "x$ENABLED_RSAPSS" != "xyes"; then : + ENABLED_RSAPSS="yes" + AM_CFLAGS="$AM_CFLAGS -DWC_RSA_PSS" +fi + if test "x$ENABLED_ECC" != "xyes"; then : + ENABLED_ECC="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256 -DWOLFSSL_VALIDATE_ECC_IMPORT" + if test "x$ENABLED_ECC_SHAMIR" = "xyes"; then : + AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR" +fi +else + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_VALIDATE_ECC_IMPORT" +fi + if test "x$ENABLED_AESCTR" != "xyes"; then : + ENABLED_AESCTR="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_COUNTER" +fi + if test "x$ENABLED_CMAC" != "xyes"; then : + ENABLED_CMAC="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CMAC" +fi + if test "x$ENABLED_HKDF" != "xyes"; then : + ENABLED_HKDF="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_HKDF" +fi + if test "x$ENABLED_INTELASM" = "xyes"; then : + AM_CFLAGS="$AM_CFLAGS -DFORCE_FAILURE_RDSEED" +fi + ;; #( + "rand") : + + ENABLED_FIPS="yes" + FIPS_VERSION="rand" + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_FIPS_RAND -DHAVE_FIPS -DHAVE_FIPS_VERSION=2" + ;; #( + "no") : + FIPS_VERSION="none" ;; #( + *) : + + ENABLED_FIPS="yes" + FIPS_VERSION="v1" + AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS" + ;; +esac + +if test "x$ENABLED_FIPS" = "xyes" && test "x$thread_ls_on" = "xno"; then : + as_fn_error $? "FIPS requires Thread Local Storage" "$LINENO" 5 +fi + +if test "x$ENABLED_FIPS" = "xyes" && test "x$FIPS_VERSION" != "xrand"; then : + + # Force enable the prerequisites. + if test "x$ENABLED_SHA512" = "xno"; then : + ENABLED_SHA512="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512 -DWOLFSSL_SHA384" +fi + if test "x$ENABLED_AESGCM" = "xno"; then : + ENABLED_AESGCM="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM" +fi + if test "x$ENABLED_DES3" = "xno"; then : + ENABLED_DES3="yes" +fi + +else + + if test "x$ENABLED_FORTRESS" = "xyes"; then : + ENABLED_DES3="yes" +fi fi -if test "x$ENABLED_FIPS" = "xyes" +# SELFTEST +# Check whether --enable-selftest was given. +if test "${enable_selftest+set}" = set; then : + enableval=$enable_selftest; ENABLED_SELFTEST=$enableval +else + ENABLED_SELFTEST=no + +fi + + +if test "x$ENABLED_SELFTEST" = "xyes" then - # requires thread local storage - if test "$thread_ls_on" = "no" + AM_CFLAGS="$AM_CFLAGS -DHAVE_SELFTEST" +fi + + +# set sha224 default +SHA224_DEFAULT=no +if test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64" +then + if test "x$ENABLED_AFALG" = "xno" && test "x$ENABLED_DEVCRYPTO" = "xno" && ( test "x$ENABLED_FIPS" = "xno" || test "x$FIPS_VERSION" = "xv2" ) then - as_fn_error $? "FIPS requires Thread Local Storage" "$LINENO" 5 + SHA224_DEFAULT=yes fi - # requires SHA512 - if test "x$ENABLED_SHA512" = "xno" +fi + +# SHA224 +# Check whether --enable-sha224 was given. +if test "${enable_sha224+set}" = set; then : + enableval=$enable_sha224; ENABLED_SHA224=$enableval +else + ENABLED_SHA224=$SHA224_DEFAULT + +fi + + +if test "$ENABLED_SHA224" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA224" +fi + + +# set sha3 default +SHA3_DEFAULT=no +if test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64" +then + if test "x$ENABLED_FIPS" = "xno" || test "x$FIPS_VERSION" = "xv2" then - ENABLED_SHA512="yes" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512 -DWOLFSSL_SHA384" - if test "x$ENABLED_SHA512" = "xyes"; then - BUILD_SHA512_TRUE= - BUILD_SHA512_FALSE='#' -else - BUILD_SHA512_TRUE='#' - BUILD_SHA512_FALSE= + SHA3_DEFAULT=yes + fi fi - fi - # requires AESGCM - if test "x$ENABLED_AESGCM" != "xyes" +# SHA3 +# Check whether --enable-sha3 was given. +if test "${enable_sha3+set}" = set; then : + enableval=$enable_sha3; ENABLED_SHA3=$enableval +else + ENABLED_SHA3=$SHA3_DEFAULT + +fi + + +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 + +# SHAKE256 +# Check whether --enable-shake256 was given. +if test "${enable_shake256+set}" = set; then : + enableval=$enable_shake256; ENABLED_SHAKE256=$enableval +else + ENABLED_SHAKE256=$ENABLED_SHA3 + +fi + + +if test "$ENABLED_SHAKE256" = "yes" || test "$ENABLED_SHAKE256" = "small" +then + if test "$ENABLED_32BIT" = "no" then - ENABLED_AESGCM="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM" - if test "x$ENABLED_SHA512" = "xyes"; then - BUILD_SHA512_TRUE= - BUILD_SHA512_FALSE='#' -else - BUILD_SHA512_TRUE='#' - BUILD_SHA512_FALSE= -fi - + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHAKE256" + if test "$ENABLED_SHA3" = "no" + then + as_fn_error $? "Must have SHA-3 enabled: --enable-sha3" "$LINENO" 5 + fi fi - AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS" fi - if test "x$ENABLED_FIPS" = "xyes"; then - BUILD_FIPS_TRUE= - BUILD_FIPS_FALSE='#' -else - BUILD_FIPS_TRUE='#' - BUILD_FIPS_FALSE= -fi - - - # set POLY1305 default POLY1305_DEFAULT=yes @@ -20238,8 +18107,8 @@ else fi -# lean psk does't need poly1305 -if test "$ENABLED_LEANPSK" = "yes" +# leanpsk and leantls don't need poly1305 +if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then ENABLED_POLY1305=no fi @@ -20249,15 +18118,6 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_POLY1305 -DHAVE_ONE_TIME_AUTH" fi - if test "x$ENABLED_POLY1305" = "xyes"; then - BUILD_POLY1305_TRUE= - BUILD_POLY1305_FALSE='#' -else - BUILD_POLY1305_TRUE='#' - BUILD_POLY1305_FALSE= -fi - - # set CHACHA default CHACHA_DEFAULT=yes @@ -20277,26 +18137,22 @@ else fi -# lean psk does't need chacha -if test "$ENABLED_LEANPSK" = "yes" +# leanpsk and leantls don't need chacha +if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" 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" fi - if test "x$ENABLED_CHACHA" = "xyes"; then - BUILD_CHACHA_TRUE= - BUILD_CHACHA_FALSE='#' -else - BUILD_CHACHA_TRUE='#' - BUILD_CHACHA_FALSE= -fi - - # Hash DRBG # Check whether --enable-hashdrbg was given. @@ -20312,11 +18168,13 @@ 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 @@ -20359,15 +18217,6 @@ then AM_CFLAGS="$AM_CFLAGS -DNO_INLINE" fi - if test "x$ENABLED_INLINE" = "xyes"; then - BUILD_INLINE_TRUE= - BUILD_INLINE_FALSE='#' -else - BUILD_INLINE_TRUE='#' - BUILD_INLINE_FALSE= -fi - - # OCSP # Check whether --enable-ocsp was given. @@ -20378,20 +18227,16 @@ else fi +if test "x$ENABLED_OPENSSLALL" = "xyes" || test "x$ENABLED_NGINX" = "xyes" +then + ENABLED_OCSP=yes +fi + if test "$ENABLED_OCSP" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" fi - if test "x$ENABLED_OCSP" = "xyes"; then - BUILD_OCSP_TRUE= - BUILD_OCSP_FALSE='#' -else - BUILD_OCSP_TRUE='#' - BUILD_OCSP_FALSE= -fi - - if test "$ENABLED_OCSP" = "yes" then @@ -20445,6 +18290,62 @@ $as_echo "$as_me: WARNING: openssl command line tool not available for testing o fi +# Certificate Status Request : a.k.a. OCSP Stapling +# Check whether --enable-ocspstapling was given. +if test "${enable_ocspstapling+set}" = set; then : + enableval=$enable_ocspstapling; ENABLED_CERTIFICATE_STATUS_REQUEST=$enableval +else + ENABLED_CERTIFICATE_STATUS_REQUEST=no + +fi + + +if test "x$ENABLED_NGINX" = "xyes" || test "x$ENABLED_WPAS" = "xyes" || test "x$ENABLED_HAPROXY" = "xyes" +then + 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" + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi +fi + + +# Certificate Status Request v2 : a.k.a. OCSP stapling v2 +# Check whether --enable-ocspstapling2 was given. +if test "${enable_ocspstapling2+set}" = set; then : + enableval=$enable_ocspstapling2; ENABLED_CERTIFICATE_STATUS_REQUEST_V2=$enableval +else + ENABLED_CERTIFICATE_STATUS_REQUEST_V2=no + +fi + + +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" + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi +fi + + # CRL # Check whether --enable-crl was given. if test "${enable_crl+set}" = set; then : @@ -20454,20 +18355,17 @@ else fi + +if test "x$ENABLED_NGINX" = "xyes" || test "x$ENABLED_HAPROXY" = "xyes" || test "x$ENABLED_OPENVPN" = "xyes" +then + ENABLED_CRL=yes +fi + if test "$ENABLED_CRL" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL" fi - if test "x$ENABLED_CRL" = "xyes"; then - BUILD_CRL_TRUE= - BUILD_CRL_FALSE='#' -else - BUILD_CRL_TRUE='#' - BUILD_CRL_FALSE= -fi - - # CRL Monitor # Check whether --enable-crl-monitor was given. @@ -20484,19 +18382,141 @@ then *linux* | *darwin* | *freebsd*) AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL_MONITOR" ;; *) - as_fn_error $? "crl monitor only allowed on linux, OS X, or freebsd" "$LINENO" 5 ;; + if test "x$ENABLED_DISTRO" = "xyes" ; then + ENABLED_CRL_MONITOR="no" + else + as_fn_error $? "crl monitor only allowed on linux, OS X, or freebsd" "$LINENO" 5 + fi + break;; esac fi - if test "x$ENABLED_CRL_MONITOR" = "xyes"; then - BUILD_CRL_MONITOR_TRUE= - BUILD_CRL_MONITOR_FALSE='#' + +# USER CRYPTO +ENABLED_USER_CRYPTO="no" +ENABLED_USER_RSA="no" + +$as_echo "#define BUILD_USER_RSA /**/" >>confdefs.h + +trycryptodir="" + +# Check whether --with-user-crypto was given. +if test "${with_user_crypto+set}" = set; then : + withval=$with_user_crypto; + CPPFLAGS="$CPPFLAGS -DHAVE_USER_CRYPTO" + LIBS="$LIBS -lusercrypto" + + if test "x$withval" != "xno" ; then + trycryptodir=$withval + fi + if test "x$withval" = "xyes" ; then + trycryptodir="/usr/local" + fi + + LDFLAGS="$LDFLAGS -L$trycryptodir/lib" + CPPFLAGS="$CPPFLAGS -I$trycryptodir/include" + + #Look for RSA Init function in usercrypto lib + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wc_InitRsaKey in -lusercrypto" >&5 +$as_echo_n "checking for wc_InitRsaKey in -lusercrypto... " >&6; } +if ${ac_cv_lib_usercrypto_wc_InitRsaKey+:} false; then : + $as_echo_n "(cached) " >&6 else - BUILD_CRL_MONITOR_TRUE='#' - BUILD_CRL_MONITOR_FALSE= + ac_check_lib_save_LIBS=$LIBS +LIBS="-lusercrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char wc_InitRsaKey (); +int +main () +{ +return wc_InitRsaKey (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_usercrypto_wc_InitRsaKey=yes +else + ac_cv_lib_usercrypto_wc_InitRsaKey=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usercrypto_wc_InitRsaKey" >&5 +$as_echo "$ac_cv_lib_usercrypto_wc_InitRsaKey" >&6; } +if test "x$ac_cv_lib_usercrypto_wc_InitRsaKey" = xyes; then : + user_rsa_linked=yes +else + user_rsa_linked=no fi + if test "x$user_rsa_linked" = "xyes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: User user_rsa.h being used" >&5 +$as_echo "$as_me: User user_rsa.h being used" >&6;} + AM_CFLAGS="$AM_CFLAGS -DHAVE_USER_RSA" + ENABLED_USER_RSA=yes + ENABLED_USER_CRYPTO=yes + fi + + + #Display check and find result of link attempts + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for USER_CRYPTO" >&5 +$as_echo_n "checking for USER_CRYPTO... " >&6; } + if test "x$ENABLED_USER_CRYPTO" = "xno" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "USER_CRYPTO not found. Either move to /usr/include and /usr/lib or + Specify its path using --with-user-crypto=/dir/" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + # Check if .la is available if not then rely on exported path + as_ac_File=`$as_echo "ac_cv_file_$trycryptodir/lib/libusercrypto.la" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $trycryptodir/lib/libusercrypto.la" >&5 +$as_echo_n "checking for $trycryptodir/lib/libusercrypto.la... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "$trycryptodir/lib/libusercrypto.la"; then + eval "$as_ac_File=yes" +else + eval "$as_ac_File=no" +fi +fi +eval ac_res=\$$as_ac_File + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : + LIB_ADD="$trycryptodir/lib/libusercrypto.la $LIB_ADD" +else + LIB_ADD="-lusercrypto $LIB_ADD" +fi + + AM_LDFLAGS="$AM_LDFLAGS -L$trycryptodir/lib" + AM_CFLAGS="$AM_CFLAGS -DHAVE_USER_CRYPTO" + fi + + +fi + + +if test "$ENABLED_USER_CRYPTO" = "yes" && test "$ENABLED_FIPS" = "yes" +then + as_fn_error $? "cannot enable user crypto and fips, user crypto posibility of using code in fips boundary." "$LINENO" 5 +fi + # NTRU ENABLED_NTRU="no" @@ -20507,12 +18527,12 @@ if test "${with_ntru+set}" = set; then : withval=$with_ntru; { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NTRU" >&5 $as_echo_n "checking for NTRU... " >&6; } - CPPFLAGS="$CPPFLAGS -DHAVE_NTRU" - LIBS="$LIBS -lNTRUEncrypt" + CPPFLAGS="$CPPFLAGS -DHAVE_NTRU -DHAVE_TLS_EXTENSIONS" + LIBS="$LIBS -lntruencrypt" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include +#include int main () { @@ -20529,20 +18549,20 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - if test "x$ntru_linked" == "xno" ; then + if test "x$ntru_linked" = "xno" ; then if test "x$withval" != "xno" ; then tryntrudir=$withval fi - if test "x$withval" == "xyes" ; then + if test "x$withval" = "xyes" ; then tryntrudir="/usr" fi - LDFLAGS="$AM_LDFLAGS -L$tryntrudir/lib" + LDFLAGS="$AM_LDFLAGS $LDFLAGS -L$tryntrudir/lib" CPPFLAGS="$CPPFLAGS -I$tryntrudir/include" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include +#include int main () { @@ -20559,7 +18579,7 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - if test "x$ntru_linked" == "xno" ; then + if test "x$ntru_linked" = "xno" ; then as_fn_error $? "NTRU isn't found. If it's already installed, specify its path using --with-ntru=/dir/" "$LINENO" 5 fi @@ -20571,27 +18591,116 @@ $as_echo "yes" >&6; } $as_echo "yes" >&6; } fi - AM_CFLAGS="$AM_CFLAGS -DHAVE_NTRU" + AM_CFLAGS="$AM_CFLAGS -DHAVE_NTRU -DHAVE_TLS_EXTENSIONS" ENABLED_NTRU="yes" fi - if test "x$ENABLED_NTRU" = "xyes"; then - BUILD_NTRU_TRUE= - BUILD_NTRU_FALSE='#' + +# QSH +# Check whether --enable-qsh was given. +if test "${enable_qsh+set}" = set; then : + enableval=$enable_qsh; ENABLED_QSH=$enableval else - BUILD_NTRU_TRUE='#' - BUILD_NTRU_FALSE= + ENABLED_QSH=no + fi -if test "$ENABLED_NTRU" = "yes" && test "$ENABLED_SMALL" = "yes" +if test "x$ENABLED_QSH" = "xyes" then - as_fn_error $? "cannot enable ntru and small, ntru requires TLS which small turns off." "$LINENO" 5 + if test "x$ENABLED_NTRU" = "xno" + then + as_fn_error $? "cannot enable qsh without NTRU" "$LINENO" 5 + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_QSH" fi + +# Whitewood netRandom client library +ENABLED_WNR="no" +trywnrdir="" + +# Check whether --with-wnr was given. +if test "${with_wnr+set}" = set; then : + withval=$with_wnr; + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Whitewood netRandom" >&5 +$as_echo_n "checking for Whitewood netRandom... " >&6; } + CPPFLAGS="$CPPFLAGS -DHAVE_WNR" + LIBS="$LIBS -lwnr" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + wnr_setup(0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + wnr_linked=yes +else + wnr_linked=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + if test "x$wnr_linked" = "xno" ; then + if test "x$withval" != "xno" ; then + trywnrdir=$withval + fi + if test "x$withval" = "xyes" ; then + trywnrdir="/usr/local" + fi + + LDFLAGS="$AM_LDFLAGS $LDFLAGS -L$trywnrdir/lib" + CPPFLAGS="$CPPFLAGS -I$trywnrdir/include" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + wnr_setup(0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + wnr_linked=yes +else + wnr_linked=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + if test "x$wnr_linked" = "xno" ; then + as_fn_error $? "Whitewood netRandom isn't found. + If it's already installed, specify its path using --with-wnr=/dir/" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + AM_LDFLAGS="$AM_LDFLAGS -L$trywnrdir/lib" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_WNR" + ENABLED_WNR="yes" + + +fi + + + # SNI # Check whether --enable-sni was given. if test "${enable_sni+set}" = set; then : @@ -20601,6 +18710,10 @@ else fi +if test "x$ENABLED_QT" = "xyes" +then + ENABLED_SNI="yes" +fi if test "x$ENABLED_SNI" = "xyes" then @@ -20617,11 +18730,40 @@ else fi +# ALPN +# Check whether --enable-alpn was given. +if test "${enable_alpn+set}" = set; then : + enableval=$enable_alpn; ENABLED_ALPN=$enableval +else + ENABLED_ALPN=no + +fi + + +if test "x$ENABLED_ALPN" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_ALPN" +fi + +# Maximum Fragment Length if test "x$ENABLED_MAX_FRAGMENT" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_MAX_FRAGMENT" fi +# Trusted CA Indication Extension +# Check whether --enable-trustedca was given. +if test "${enable_trustedca+set}" = set; then : + enableval=$enable_trustedca; ENABLED_TRUSTED_CA=$enableval +else + ENABLED_TRUSTED_CA=no +fi + + +if test "x$ENABLED_TRUSTED_CA" = "xyes"; then : + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_TRUSTED_CA" +fi + # Truncated HMAC # Check whether --enable-truncatedhmac was given. if test "${enable_truncatedhmac+set}" = set; then : @@ -20668,22 +18810,72 @@ then then as_fn_error $? "cannot enable renegotiation-indication and secure-renegotiation." "$LINENO" 5 fi - AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SECURE_RENEGOTIATION" + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SECURE_RENEGOTIATION -DHAVE_SERVER_RENEGOTIATION_INFO" +fi + +# Fallback SCSV +# Check whether --enable-fallback-scsv was given. +if test "${enable_fallback_scsv+set}" = set; then : + enableval=$enable_fallback_scsv; ENABLED_FALLBACK_SCSV=$enableval +else + ENABLED_FALLBACK_SCSV=no + +fi + + +if test "x$ENABLED_FALLBACK_SCSV" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_FALLBACK_SCSV" fi # Supported Elliptic Curves Extensions # Check whether --enable-supportedcurves was given. if test "${enable_supportedcurves+set}" = set; then : - enableval=$enable_supportedcurves; ENABLED_SUPPORTED_CURVES=$enableval + enableval=$enable_supportedcurves; ENABLED_SUPPORTED_CURVES=$enableval else - ENABLED_SUPPORTED_CURVES=no - + ENABLED_SUPPORTED_CURVES=yes fi if test "x$ENABLED_SUPPORTED_CURVES" = "xyes" then - AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SUPPORTED_CURVES" + if test "x$ENABLED_ECC" = "xno" && test "x$ENABLED_CURVE25519" = "xno"; then : + ENABLED_SUPPORTED_CURVES=no +else + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SUPPORTED_CURVES" +fi +fi + +# Diffie-Hellman +if test "$ENABLED_DH" = "yes" +then + if test "$ENABLED_TLS13" = "yes" || test "$ENABLED_SUPPORTED_CURVES" = "yes" + then + AM_CFLAGS="-DHAVE_FFDHE_2048 $AM_CFLAGS" + fi +fi + +# FFDHE parameters only +# Check whether --enable-ffdhe-only was given. +if test "${enable_ffdhe_only+set}" = set; then : + enableval=$enable_ffdhe_only; ENABLED_FFDHE_ONLY=$enableval +else + ENABLED_FFDHE_ONLY=no + +fi + + +if test "x$ENABLED_FFDHE_ONLY" = "xyes" +then + if test "$ENABLED_DH" = "no" + then + as_fn_error $? "FFDHE only support requires DH support" "$LINENO" 5 + fi + if test "$ENABLED_SUPPORTED_CURVES" = "no" + then + as_fn_error $? "FFDHE only support requires Supported Curves extension" "$LINENO" 5 + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_REQUIRE_FFDHE" fi # Session Ticket Extension @@ -20696,11 +18888,31 @@ else fi +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" fi +# Extended Master Secret Extension +# Check whether --enable-extended-master was given. +if test "${enable_extended_master+set}" = set; then : + enableval=$enable_extended_master; ENABLED_EXTENDED_MASTER=$enableval +else + ENABLED_EXTENDED_MASTER=yes + +fi + + +if test "x$ENABLED_EXTENDED_MASTER" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_EXTENDED_MASTER" +fi + # TLS Extensions # Check whether --enable-tlsx was given. if test "${enable_tlsx+set}" = set; then : @@ -20711,14 +18923,61 @@ else fi +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 - ENABLED_MAX_FRAGMENT=yes - ENABLED_TRUNCATED_HMAC=yes - ENABLED_SUPPORTED_CURVES=yes - AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC -DHAVE_SUPPORTED_CURVES" + ENABLED_SNI=yes + ENABLED_MAX_FRAGMENT=yes + ENABLED_TRUNCATED_HMAC=yes + ENABLED_ALPN=yes + ENABLED_TRUSTED_CA=yes + ENABLED_ENCRYPT_THEN_MAC=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC -DHAVE_ALPN -DHAVE_TRUSTED_CA" + # Check the ECC supported curves prereq + if test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_CURVE25519" = "xyes"; then : + ENABLED_SUPPORTED_CURVES=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_SUPPORTED_CURVES" fi +fi + +# Early Data handshake in TLS v1.3 and above +# Check whether --enable-earlydata was given. +if test "${enable_earlydata+set}" = set; then : + enableval=$enable_earlydata; ENABLED_TLS13_EARLY_DATA=$enableval +else + ENABLED_TLS13_EARLY_DATA=no + +fi + + +if test "$ENABLED_TLS13_EARLY_DATA" = "group" +then + ENABLED_TLS13_EARLY_DATA="yes" + # Group EarlyData with ClientHello + AM_CFLAGS="-DWOLFSSL_EARLY_DATA_GROUP $AM_CFLAGS" +fi +if test "$ENABLED_TLS13_EARLY_DATA" = "yes" +then + if test "x$ENABLED_TLS13" = "xno" + then + as_fn_error $? "cannot enable earlydata without enabling tls13." "$LINENO" 5 + fi + if test "x$ENABLED_SESSION_TICKET" = "xno" && test "x$ENABLED_PSK" = "xno" + then + as_fn_error $? "cannot enable earlydata without enabling session tickets and/or PSK." "$LINENO" 5 + fi + AM_CFLAGS="-DWOLFSSL_EARLY_DATA $AM_CFLAGS" +fi + +if test "$ENABLED_TLSV12" = "no" && test "$ENABLED_TLS13" = "yes" && test "x$ENABLED_SESSION_TICKET" = "xno" +then + AM_CFLAGS="$AM_CFLAGS -DNO_SESSION_CACHE" +fi + # PKCS7 # Check whether --enable-pkcs7 was given. @@ -20729,19 +18988,15 @@ else fi -if test "$ENABLED_PKCS7" = "yes" -then - AM_CFLAGS="$AM_CFLAGS -DHAVE_PKCS7" -fi - if test "x$ENABLED_PKCS7" = "xyes"; then - BUILD_PKCS7_TRUE= - BUILD_PKCS7_FALSE='#' +# wolfSSH Options +# Check whether --enable-ssh was given. +if test "${enable_ssh+set}" = set; then : + enableval=$enable_ssh; ENABLED_WOLFSSH=$enableval else - BUILD_PKCS7_TRUE='#' - BUILD_PKCS7_FALSE= -fi + ENABLED_WOLFSSH=no +fi # Simple Certificate Enrollment Protocol (SCEP) @@ -20753,41 +19008,56 @@ else fi -if test "$ENABLED_WOLFSCEP" = "yes" -then - # Enable prereqs if not already enabled - if test "x$ENABLED_KEYGEN" = "xno" - then - ENABLED_KEYGEN="yes" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KEY_GEN" - fi - if test "x$ENABLED_CERTGEN" = "xno" - then - ENABLED_CERTGEN="yes" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN" - fi - if test "x$ENABLED_CERTREQ" = "xno" - then - ENABLED_CERTREQ="yes" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_REQ" - fi - if test "x$ENABLED_PKCS7" = "xno" - then - ENABLED_PKCS7="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_PKCS7" - if test "x$ENABLED_PKCS7" = "xyes"; then - BUILD_PKCS7_TRUE= - BUILD_PKCS7_FALSE='#' + + +# Secure Remote Password +# Check whether --enable-srp was given. +if test "${enable_srp+set}" = set; then : + enableval=$enable_srp; ENABLED_SRP=$enableval else - BUILD_PKCS7_TRUE='#' - BUILD_PKCS7_FALSE= + ENABLED_SRP=no + fi - fi - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_WOLFSCEP" + +if test "x$ENABLED_SRP" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_HAVE_SRP" fi +# Indefinite length encoded BER message support +# Check whether --enable-indef was given. +if test "${enable_indef+set}" = set; then : + enableval=$enable_indef; ENABLED_BER_INDEF=$enableval +else + ENABLED_BER_INDEF=no + +fi + + +if test "x$ENABLED_BER_INDEF" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DASN_BER_TO_DER" +fi + + + +# Small Stack - Cache on object +# Check whether --enable-smallstackcache was given. +if test "${enable_smallstackcache+set}" = set; then : + enableval=$enable_smallstackcache; ENABLED_SMALL_STACK_CACHE=$enableval +else + ENABLED_SMALL_STACK_CACHE=no + +fi + + +if test "x$ENABLED_SMALL_STACK_CACHE" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SMALL_STACK_CACHE" +fi + # Small Stack # Check whether --enable-smallstack was given. if test "${enable_smallstack+set}" = set; then : @@ -20798,6 +19068,10 @@ else fi +if test "x$ENABLED_SMALL_STACK_CACHE" = "xyes" +then + ENABLED_SMALL_STACK=yes +fi if test "x$ENABLED_SMALL_STACK" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SMALL_STACK" @@ -20864,15 +19138,6 @@ fi AM_CFLAGS="$AM_CFLAGS -DHAVE_VALGRIND" fi - if test "x$ENABLED_VALGRIND" = "xyes"; then - USE_VALGRIND_TRUE= - USE_VALGRIND_FALSE='#' -else - USE_VALGRIND_TRUE='#' - USE_VALGRIND_FALSE= -fi - - # Test certs, use internal cert functions for extra testing # Check whether --enable-testcert was given. @@ -20931,17 +19196,14 @@ then if test "x$ENABLED_ECC" = "xno" then ENABLED_ECC="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256 -DECC_SHAMIR" - if test "x$ENABLED_ECC" = "xyes"; then - BUILD_ECC_TRUE= - BUILD_ECC_FALSE='#' -else - BUILD_ECC_TRUE='#' - BUILD_ECC_FALSE= -fi + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" + if test "$ENABLED_ECC_SHAMIR" = "yes" + 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" @@ -20950,6 +19212,470 @@ fi fi +# wolfSSL JNI +# Check whether --enable-jni was given. +if test "${enable_jni+set}" = set; then : + enableval=$enable_jni; ENABLED_JNI=$enableval +else + ENABLED_JNI=no + +fi + +if test "$ENABLED_JNI" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_JNI" + + # Enable prereqs if not already enabled + if test "x$ENABLED_DTLS" = "xno" + then + ENABLED_DTLS="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DTLS" + fi + if test "x$ENABLED_OPENSSLEXTRA" = "xno" + then + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_EXTRA" + fi + if test "x$ENABLED_CRL" = "xno" + then + ENABLED_CRL="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL" + fi + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi + if test "x$ENABLED_CRL_MONITOR" = "xno" && test "x$ENABLED_DISTRO" = "xno" + then + ENABLED_CRL_MONITOR="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL_MONITOR" + fi + if test "x$ENABLED_SAVESESSION" = "xno" + then + ENABLED_SAVESESSION="yes" + AM_CFLAGS="$AM_CFLAGS -DPERSIST_SESSION_CACHE" + fi + if test "x$ENABLED_SAVECERT" = "xno" + then + ENABLED_SAVECERT="yes" + AM_CFLAGS="$AM_CFLAGS -DPERSIST_CERT_CACHE" + fi + if test "x$ENABLED_ATOMICUSER" = "xno" + then + ENABLED_ATOMICUSER="yes" + AM_CFLAGS="$AM_CFLAGS -DATOMIC_USER" + fi + if test "x$ENABLED_ECC" = "xno" + then + ENABLED_ECC="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" + + if test "$ENABLED_ECC_SHAMIR" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR" + fi + fi + if test "x$ENABLED_PKCALLBACKS" = "xno" + then + ENABLED_PKCALLBACKS="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_PK_CALLBACKS" + fi + if test "x$ENABLED_DH" = "xno" + then + ENABLED_DH="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_DH" + fi + if test "x$ENABLED_PSK" = "xno" + then + ENABLED_PSK="yes" + fi + if test "x$ENABLED_CERTEXT" = "xno" + then + ENABLED_CERTEXT="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" + fi + if test "x$ENABLED_CERTGEN" = "xno" + then + ENABLED_CERTGEN="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN" + fi +fi + +# lighty Support +# Check whether --enable-lighty was given. +if test "${enable_lighty+set}" = set; then : + enableval=$enable_lighty; ENABLED_LIGHTY=$enableval +else + ENABLED_LIGHTY=no + +fi + +if test "$ENABLED_LIGHTY" = "yes" +then + # 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 + AM_CFLAGS="$AM_CFLAGS -DHAVE_LIGHTY -DHAVE_WOLFSSL_SSL_H=1" +fi + +if test "$ENABLED_NGINX" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NGINX -DWOLFSSL_SIGNER_DER_CERT" +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_OPENVPN" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DES_ECB -DHAVE_EX_DATA -DWOLFSSL_KEY_GEN" +fi + + +if test "$ENABLED_NGINX" = "yes"|| test "x$ENABLED_HAPROXY" = "xyes" || test "x$ENABLED_LIGHTY" = "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 + +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_WPAS" = "yes" || test "$ENABLED_QT" = "yes" +then + ENABLED_ARC4="yes" +fi + +if test "$ENABLED_ARC4" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DNO_RC4" +else + # turn off ARC4 if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DNO_RC4" + ENABLED_ARC4=no + fi +fi + +# Asio Support +# Check whether --enable-asio was given. +if test "${enable_asio+set}" = set; then : + enableval=$enable_asio; ENABLED_ASIO=$enableval +else + ENABLED_ASIO=no + +fi + +if test "$ENABLED_ASIO" = "yes" +then + # Requires opensslextra and opensslall + if test "x$ENABLED_OPENSSLALL" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" + then + ENABLED_OPENSSLALL="yes" + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="-DOPENSSL_EXTRA -DOPENSSL_ALL $AM_CFLAGS" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ASIO -DASIO_USE_WOLFSSL -DWOLFSSL_KEY_GEN" + AM_CFLAGS="$AM_CFLAGS -DBOOST_ASIO_USE_WOLFSSL -DHAVE_EX_DATA" + AM_CFLAGS="$AM_CFLAGS -DSSL_TXT_TLSV1_2 -DSSL_TXT_TLSV1_1" + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3" + if test "$ENABLED_TLSV10" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DSSL_TXT_TLSV1" + fi + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi +fi + +# Apache HTTPD +# Check whether --enable-apachehttpd was given. +if test "${enable_apachehttpd+set}" = set; then : + enableval=$enable_apachehttpd; ENABLED_APACHE_HTTPD=$enableval +else + ENABLED_APACHE_HTTPD=no + +fi + +if test "$ENABLED_APACHE_HTTPD" = "yes" +then + # Requires opensslextra and opensslall + if test "x$ENABLED_OPENSSLALL" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" + then + ENABLED_OPENSSLALL="yes" + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="-DOPENSSL_EXTRA -DOPENSSL_ALL $AM_CFLAGS" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_APACHE_HTTPD" + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 -DOPENSSL_NO_COMP" + AM_CFLAGS="$AM_CFLAGS -DHAVE_EX_DATA -DWOLFSSL_SIGNER_DER_CERT" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT -DWOLFSSL_CERT_GEN" + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi + + # Requires sessioncerts make sure on + if test "x$ENABLED_SESSIONCERTS" = "xno" + then + ENABLED_SESSIONCERTS="yes" + AM_CFLAGS="$AM_CFLAGS -DSESSION_CERTS" + fi + + # Requires ALPN + if test "x$ENABLED_ALPN" = "xno" + then + ENABLED_ALPN="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_ALPN" + fi + + # Requires CRL + if test "x$ENABLED_CRL" = "xno" + then + ENABLED_CRL="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL" + fi + + # Requires Certificate Generation, Request and Extensions + if test "x$ENABLED_CERTGEN" = "xno" + then + ENABLED_CERTGEN="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN" + fi + if test "x$ENABLED_CERTREQ" = "xno" + then + ENABLED_CERTREQ="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_REQ" + fi + if test "x$ENABLED_CERTEXT" = "xno" + then + ENABLED_CERTEXT="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" + fi + + # Requires Secure Renegotiation + if test "x$ENABLED_SECURE_RENEGOTIATION" = "xno" + then + AM_CFLAGS="$AM_CFLAGS -DHAVE_SECURE_RENEGOTIATION -DHAVE_SERVER_RENEGOTIATION_INFO" + fi +fi + +# Encrypt-Then-Mac +# Check whether --enable-enc-then-mac was given. +if test "${enable_enc_then_mac+set}" = set; then : + enableval=$enable_enc_then_mac; ENABLED_ENCRYPT_THEN_MAC=$enableval +else + ENABLED_ENCRYPT_THEN_MAC=yes + +fi + + +if test "x$ENABLED_APACHE_HTTPD" = "xyes" +then + ENABLED_ENCRYPT_THEN_MAC=no +fi + +if test "x$ENABLED_TLSX" = "xyes" +then + ENABLED_ENCRYPT_THEN_MAC=yes +fi + +if test "x$ENABLED_SNIFFER" == "xyes"; then : + ENABLED_ENCRYPT_THEN_MAC="no" +fi + +if test "x$ENABLED_ENCRYPT_THEN_MAC" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_ENCRYPT_THEN_MAC" +fi + + +# stunnel Support +# Check whether --enable-stunnel was given. +if test "${enable_stunnel+set}" = set; then : + enableval=$enable_stunnel; ENABLED_STUNNEL=$enableval +else + ENABLED_STUNNEL=no + +fi + +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" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" + then + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" + fi + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi + + # Requires coding make sure on + if test "x$ENABLED_CODING" = "xno" + then + ENABLED_CODING="yes" + fi + + # Requires sessioncerts make sure on + if test "x$ENABLED_SESSIONCERTS" = "xno" + then + ENABLED_SESSIONCERTS="yes" + AM_CFLAGS="$AM_CFLAGS -DSESSION_CERTS" + fi + + # Requires crls, make sure on + if test "x$ENABLED_CRL" = "xno" + then + ENABLED_CRL="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL" + fi + + # Requires DES3, make sure on + if test "x$ENABLED_DES3" = "xno" + then + ENABLED_DES3="yes" + fi + + # Requires tlsx, make sure on + 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" + + # Check the ECC supported curves prereq + if test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_CURVE25519" = "xyes"; then : + ENABLED_SUPPORTED_CURVES=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_SUPPORTED_CURVES" +fi + fi + + # Requires ecc make sure on + if test "x$ENABLED_ECC" = "xno" + then + ENABLED_OPENSSLEXTRA="yes" + ENABLED_ECC="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" + + if test "$ENABLED_ECC_SHAMIR" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR" + fi + fi + + # Requires wolfSSL_OBJ_txt2nid + if test "x$ENABLED_CERTEXT" = "xno" + then + ENABLED_CERTEXT="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" + fi + + # Requires certgen + if test "x$ENABLED_CERTGEN" = "xno" + then + ENABLED_CERTGEN="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN" + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_STUNNEL -DWOLFSSL_ALWAYS_VERIFY_CB" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI -DHAVE_EX_DATA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DES_ECB" +fi + +if test "$ENABLED_PSK" = "no" && test "$ENABLED_LEANPSK" = "no" \ + && test "x$ENABLED_STUNNEL" = "xno" +then + AM_CFLAGS="$AM_CFLAGS -DNO_PSK" +fi + +if test "$ENABLED_PSK" = "no" && \ + (test "$ENABLED_LEANPSK" = "yes" || test "x$ENABLED_STUNNEL" = "xyes") +then + ENABLED_PSK=yes +fi + +# MD4 +# Check whether --enable-md4 was given. +if test "${enable_md4+set}" = set; then : + enableval=$enable_md4; ENABLED_MD4=$enableval +else + ENABLED_MD4=no + +fi + + + +if test "$ENABLED_MD4" = "no" +then + #turn on MD4 if using stunnel + if test "x$ENABLED_STUNNEL" = "xyes" + then + ENABLED_MD4="yes" + else + AM_CFLAGS="$AM_CFLAGS -DNO_MD4" + fi +fi + + +# Encrypted keys +# Check whether --enable-enckeys was given. +if test "${enable_enckeys+set}" = set; then : + enableval=$enable_enckeys; ENABLED_ENCKEYS=$enableval +else + ENABLED_ENCKEYS=no + +fi + + +if test "$ENABLED_OPENSSLEXTRA" = "yes" || test "$ENABLED_WEBSERVER" = "yes" +then + ENABLED_ENCKEYS=yes +fi + +if test "$ENABLED_ENCKEYS" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ENCRYPTED_KEYS" +fi + + # PWDBASED has to come after certservice since we want it on w/o explicit on # PWDBASED # Check whether --enable-pwdbased was given. @@ -20963,31 +19689,88 @@ fi if test "$ENABLED_PWDBASED" = "no" then - if test "$ENABLED_OPENSSLEXTRA" = "yes" || test "$ENABLED_WEBSERVER" = "yes" + if test "$ENABLED_OPENSSLEXTRA" = "yes" || test "$ENABLED_OPENSSLALL" = "yes" || test "$ENABLED_WEBSERVER" = "yes" || test "$ENABLED_ENCKEYS" = "yes" then - # opensslextra and webserver needs pwdbased + # opensslextra, opensslall, webserver, and enckeys needs pwdbased ENABLED_PWDBASED=yes else AM_CFLAGS="$AM_CFLAGS -DNO_PWDBASED" fi fi - if test "x$ENABLED_PWDBASED" = "xyes"; then - BUILD_PWDBASED_TRUE= - BUILD_PWDBASED_FALSE='#' + +# Check whether --enable-scrypt was given. +if test "${enable_scrypt+set}" = set; then : + enableval=$enable_scrypt; ENABLED_SCRYPT=$enableval else - BUILD_PWDBASED_TRUE='#' - BUILD_PWDBASED_FALSE= + ENABLED_SCRYPT=no + fi +if test "$ENABLED_SCRYPT" = "yes" +then + if test "$ENABLED_PWDBASED" = "no" + then + as_fn_error $? "cannot enable scrypt without enabling pwdbased." "$LINENO" 5 + fi + AM_CFLAGS="$AM_CFLAGS -DHAVE_SCRYPT" +fi + + +# wolfCrypt Only Build +# Check whether --enable-cryptonly was given. +if test "${enable_cryptonly+set}" = set; then : + enableval=$enable_cryptonly; ENABLED_CRYPTONLY=$enableval +else + ENABLED_CRYPTONLY=no +fi + + +if test "x$FIPS_VERSION" = "xrand"; then : + ENABLED_CRYPTONLY="yes" +fi + +if test "$ENABLED_CRYPTONLY" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_ONLY" +fi + +if test "x$ENABLED_CRYPTONLY" = "xno" +then + if test "x$ENABLED_PSK" = "xno" && test "x$ENABLED_ASN" = "xno" + then + as_fn_error $? "please enable psk if disabling asn." "$LINENO" 5 + fi + + if test "x$ENABLED_ECC" = "xyes" && test "x$ENABLED_ASN" = "xno" + then + as_fn_error $? "please disable ecc if disabling asn." "$LINENO" 5 + fi + + if test "$ENABLED_AFALG" = "yes" + then + # for TLS connections the intermediate hash needs to store buffer + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_HASH_KEEP" + fi + + if test "$ENABLED_DEVCRYPTO" = "yes" + then + # for TLS connections the intermediate hash needs to store buffer + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_HASH_KEEP" + fi +fi # set fastmath default FASTMATH_DEFAULT=no -if test "$host_cpu" = "x86_64" +if test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64" then -FASTMATH_DEFAULT=yes + FASTMATH_DEFAULT=yes +fi +if test "$ENABLED_SP_MATH" = "yes" +then + FASTMATH_DEFAULT=no fi # fastmath @@ -21002,10 +19785,10 @@ fi if test "x$ENABLED_FASTMATH" = "xyes" then - # turn off fastmth if leanpsk on or asn off (w/o dh) + # turn off fastmth if leanpsk on or asn off (w/o DH and ECC) if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_ASN" = "no" then - if test "$ENABLED_DH" = "no" + if test "$ENABLED_DH" = "no" && test "$ENABLED_ECC" = "no" && test "$ENABLED_RSA" = "no" then ENABLED_FASTMATH=no else @@ -21046,23 +19829,6 @@ then ENABLED_SLOWMATH="no" fi - if test "x$ENABLED_FASTMATH" = "xyes"; then - BUILD_FASTMATH_TRUE= - BUILD_FASTMATH_FALSE='#' -else - BUILD_FASTMATH_TRUE='#' - BUILD_FASTMATH_FALSE= -fi - - if test "x$ENABLED_SLOWMATH" = "xyes"; then - BUILD_SLOWMATH_TRUE= - BUILD_SLOWMATH_FALSE='#' -else - BUILD_SLOWMATH_TRUE='#' - BUILD_SLOWMATH_FALSE= -fi - - # Enable Examples, used to disable examples # Check whether --enable-examples was given. @@ -21080,12 +19846,18 @@ fi if test "x$ENABLED_INLINE" = "xno"; then : ENABLED_EXAMPLES="no" fi - if test "x$ENABLED_EXAMPLES" = "xyes"; then - BUILD_EXAMPLES_TRUE= - BUILD_EXAMPLES_FALSE='#' +if test "x$ENABLED_CRYPTONLY" = "xyes"; then : + ENABLED_EXAMPLES="no" +fi + + +# Enable wolfCrypt test and benchmark +# Check whether --enable-crypttests was given. +if test "${enable_crypttests+set}" = set; then : + enableval=$enable_crypttests; ENABLED_CRYPT_TESTS=$enableval else - BUILD_EXAMPLES_TRUE='#' - BUILD_EXAMPLES_FALSE= + ENABLED_CRYPT_TESTS=yes + fi @@ -21121,15 +19893,15 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - if test "x$libz_linked" == "xno" ; then + if test "x$libz_linked" = "xno" ; then if test "x$withval" != "xno" ; then trylibzdir=$withval fi - if test "x$withval" == "xyes" ; then + if test "x$withval" = "xyes" ; then trylibzdir="/usr" fi - AM_LDFLAGS="$AM_LDFLAGS -L$trylibzdir/lib" + LDFLAGS="$LDFLAGS -L$trylibzdir/lib" CPPFLAGS="$CPPFLAGS -I$trylibzdir/include" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -21151,7 +19923,7 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - if test "x$libz_linked" == "xno" ; then + if test "x$libz_linked" = "xno" ; then as_fn_error $? "libz isn't found. If it's already installed, specify its path using --with-libz=/dir/" "$LINENO" 5 fi @@ -21166,15 +19938,40 @@ $as_echo "yes" >&6; } fi - if test "x$ENABLED_LIBZ" = "xyes"; then - BUILD_LIBZ_TRUE= - BUILD_LIBZ_FALSE='#' + + +# PKCS#11 +# Check whether --enable-pkcs11 was given. +if test "${enable_pkcs11+set}" = set; then : + enableval=$enable_pkcs11; ENABLED_PKCS11=$enableval else - BUILD_LIBZ_TRUE='#' - BUILD_LIBZ_FALSE= + ENABLED_PKCS11=no + fi +if test "x$ENABLED_PKCS11" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_PKCS11 -DHAVE_WOLF_BIGINT" + LIBS="$LIBS -ldl" +fi + + +# PKCS#12 +# Check whether --enable-pkcs12 was given. +if test "${enable_pkcs12+set}" = set; then : + enableval=$enable_pkcs12; ENABLED_PKCS12=$enableval +else + ENABLED_PKCS12=yes + +fi + + +if test "x$ENABLED_PKCS12" = "xno" +then + AM_CFLAGS="$AM_CFLAGS -DNO_PKCS12" +fi + # cavium trycaviumdir="" @@ -21185,18 +19982,19 @@ if test "${with_cavium+set}" = set; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cavium" >&5 $as_echo_n "checking for cavium... " >&6; } CPPFLAGS="$CPPFLAGS -DHAVE_CAVIUM" + LIB_ADD="-lrt $LIB_ADD" - if test "x$withval" == "xyes" ; then - as_fn_error $? "need a PATH for --with-cavium" "$LINENO" 5 - fi - if test "x$withval" != "xno" ; then - trycaviumdir=$withval - fi + if test "x$withval" = "xyes" ; then + as_fn_error $? "need a PATH for --with-cavium" "$LINENO" 5 + fi + if test "x$withval" != "xno" ; then + trycaviumdir=$withval + fi - LDFLAGS="$AM_LDFLAGS $trycaviumdir/api/cavium_common.o" - CPPFLAGS="$CPPFLAGS -I$trycaviumdir/include" + LDFLAGS="$AM_LDFLAGS $trycaviumdir/api/cavium_common.o" + CPPFLAGS="$CPPFLAGS -I$trycaviumdir/include" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include "cavium_common.h" int @@ -21215,20 +20013,995 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - if test "x$cavium_linked" == "xno" ; then - as_fn_error $? "cavium isn't found. - If it's already installed, specify its path using --with-cavium=/dir/" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + if test "x$cavium_linked" = "xno" ; then + as_fn_error $? "cavium isn't found. + If it's already installed, specify its path using --with-cavium=/dir/" "$LINENO" 5 + else + AM_CFLAGS="$AM_CFLAGS -DHAVE_CAVIUM" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - enable_shared=no - enable_static=yes + enable_shared=no + enable_static=yes + ENABLED_CAVIUM=yes + +else + ENABLED_CAVIUM=no + +fi + + +# cavium V +trycaviumdir="" + +# Check whether --with-cavium-v was given. +if test "${with_cavium_v+set}" = set; then : + withval=$with_cavium_v; + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cavium" >&5 +$as_echo_n "checking for cavium... " >&6; } + AM_CFLAGS="$AM_CFLAGS -DHAVE_CAVIUM -DHAVE_CAVIUM_V" + LIB_ADD="-lrt -lcrypto $LIB_ADD" + + if test "x$withval" = "xyes" ; then + as_fn_error $? "need a PATH for --with-cavium" "$LINENO" 5 + fi + if test "x$withval" != "xno" ; then + trycaviumdir=$withval + fi + + as_ac_File=`$as_echo "ac_cv_file_$trycaviumdir/lib/libnitrox.a" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $trycaviumdir/lib/libnitrox.a" >&5 +$as_echo_n "checking for $trycaviumdir/lib/libnitrox.a... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "$trycaviumdir/lib/libnitrox.a"; then + eval "$as_ac_File=yes" +else + eval "$as_ac_File=no" +fi +fi +eval ac_res=\$$as_ac_File + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$trycaviumdir/lib/libnitrox.a" | $as_tr_cpp` 1 +_ACEOF +AM_CPPFLAGS="-I$trycaviumdir/include $AM_CPPFLAGS" +else + ENABLED_CAVIUM_V=no +fi + + LIB_STATIC_ADD="$trycaviumdir/lib/libnitrox.a $LIB_STATIC_ADD" + + if test "$ENABLED_CAVIUM_V" = "no"; then + as_fn_error $? "Could not find Nitrox library" "$LINENO" 5 + fi + + enable_shared=no + enable_static=yes + enable_opensslextra=yes + + ENABLED_CAVIUM=yes + ENABLED_CAVIUM_V=yes + +else + + ENABLED_CAVIUM_=no + ENABLED_CAVIUM_V=no fi +# Cavium Octeon +OCTEON_ROOT="" +: ${OCTEON_OBJ="obj-octeon2"} +: ${OCTEON_HOST="standalone"} + + +# Check whether --with-octeon-sync was given. +if test "${with_octeon_sync+set}" = set; then : + withval=$with_octeon_sync; + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for octeon" >&5 +$as_echo_n "checking for octeon... " >&6; } + + if test "x$withval" = "xyes" ; then + as_fn_error $? "need a PATH for --with-octeon" "$LINENO" 5 + fi + if test "x$withval" != "xno" ; then + OCTEON_ROOT=$withval + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_CAVIUM_OCTEON_SYNC" + AM_CFLAGS="$AM_CFLAGS -DOCTEON_MODEL=$OCTEON_MODEL" + AM_CFLAGS="$AM_CFLAGS -I$OCTEON_ROOT/executive" + case $OCTEON_HOST in #( + 'linux') : + AM_CFLAGS="$AM_CFLAGS -DCVMX_BUILD_FOR_LINUX_HOST" ;; #( + *) : + ;; +esac + + #-I$OCTEON_ROOT/target/include + AM_LDFLAGS="$AM_LDFLAGS -lrt -Xlinker -T -Xlinker $OCTEON_ROOT/executive/cvmx-shared-linux.ld" + AM_LDFLAGS="$AM_LDFLAGS -L$OCTEON_ROOT/executive/$OCTEON_OBJ -lcvmx -lfdt" + + enable_shared=no + enable_static=yes + + ENABLED_OCTEON_SYNC=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + ENABLED_OCTEON_SYNC=no + +fi + + + +# Intel QuickAssist +QAT_DIR="" +BUILD_INTEL_QAT_VERSION=2 + + +# Check whether --with-intelqa was given. +if test "${with_intelqa+set}" = set; then : + withval=$with_intelqa; ENABLED_INTEL_QA=yes; QAT_DIR=$withval +else + ENABLED_INTEL_QA=no +fi + + + +# Check whether --with-intelqa-sync was given. +if test "${with_intelqa_sync+set}" = set; then : + withval=$with_intelqa_sync; ENABLED_INTEL_QA_SYNC=yes; QAT_DIR=$withval +else + ENABLED_INTEL_QA_SYNC=no +fi + + +if test "x$ENABLED_INTEL_QA" = "xyes" && test "x$ENABLED_INTEL_QA_SYNC" = "xyes"; then : + as_fn_error $? "Both Intel QA Async and Sync are selected, only select one." "$LINENO" 5 +fi + +if test "x$ENABLED_INTEL_QA" = "xyes" || test "x$ENABLED_INTEL_QA_SYNC" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for intelqa" >&5 +$as_echo_n "checking for intelqa... " >&6; } + if test "x$ENABLED_INTEL_QA" = "xyes"; then : + AM_CPPFLAGS="$AM_CPPFLAGS -DHAVE_INTEL_QA -DDO_CRYPTO -DUSER_SPACE"; intelqa_opt="" +else + AM_CPPFLAGS="$AM_CPPFLAGS -DHAVE_INTEL_QA_SYNC -DQAT_USE_POLLING_THREAD -DO_CRYPTO -DUSER_SPACE"; intelqa_opt="-sync" +fi + OLD_LIBS="$LIBS" + OLD_CPPFLAGS="$CPPFLAGS" + + if test "x$QAT_DIR" = "xyes"; then : + as_fn_error $? "need a PATH for --with-intelqa$intelqa_opt" "$LINENO" 5 +fi + + AM_CPPFLAGS="$AM_CPPFLAGS -I$QAT_DIR/quickassist/include -I$QAT_DIR/quickassist/include/lac -I$QAT_DIR/quickassist/utilities/osal/include \ + -I$QAT_DIR/quickassist/utilities/osal/src/linux/user_space/include -I$QAT_DIR/quickassist/lookaside/access_layer/include \ + -I$QAT_DIR/quickassist/lookaside/access_layer/src/common/include -I$srcdir/wolfssl -I$srcdir/wolfssl/wolfcrypt/port/intel \ + -I$QAT_DIR/quickassist/utilities/libusdm_drv" + CPPFLAGS="$AM_CPPFLAGS" + + LDFLAGS="$LDFLAGS -L$QAT_DIR/build" + LIBS="$LIBS -lqat_s -lusdm_drv_s" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include "cpa_cy_common.h" +int +main () +{ +Cpa16U count = 0; cpaCyGetNumInstances(&count); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + intelqa_linked=yes +else + intelqa_linked=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + if test "x$intelqa_linked" = "xno"; then : + # Try old QAT driver libraries + LIBS="$OLD_LIBS -licp_qa_al_s" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include "cpa_cy_common.h" +int +main () +{ +Cpa16U count = 0; cpaCyGetNumInstances(&count); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + intelqa_linked=yes +else + intelqa_linked=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "x$intelqa_linked" = "xno"; then : + as_fn_error $? "Intel QuickAssist not found. If it's already installed, specify its path using --with-intelqa$intelqa_opt=/dir/" "$LINENO" 5 +else + BUILD_INTEL_QAT_VERSION=1 +fi + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + if test "x$BUILD_INTEL_QAT_VERSION" == "x1"; then : + LIB_ADD="-ladf_proxy -losal -lrt $LIB_ADD" +else + LIB_ADD="-losal -lrt $LIB_ADD" +fi + CPPFLAGS="$OLD_CPPFLAGS" + +fi + + +# Single Precision maths implementation +# Check whether --enable-sp was given. +if test "${enable_sp+set}" = set; then : + enableval=$enable_sp; ENABLED_SP=$enableval +else + ENABLED_SP=no +fi + + +ENABLED_SP_RSA=no +ENABLED_SP_DH=no +ENABLED_SP_FF_2048=no +ENABLED_SP_FF_3072=no +ENABLED_SP_FF_4096=no +ENABLED_SP_ECC=no +ENABLED_SP_EC_256=no +ENABLED_SP_EC_384=no +ENABLED_SP_NO_MALLOC=no +for v in `echo $ENABLED_SP | tr "," " "` +do + case $v in + small) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_2048=yes + ENABLED_SP_FF_3072=yes + ENABLED_SP_ECC=yes + ENABLED_SP_SMALL=yes + ENABLED_SP_EC_256=yes + if test "$host_cpu" = "x86_64"; then + ENABLED_SP_FF_4096=yes + ENABLED_SP_EC_384=yes + fi + ;; + yes) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_2048=yes + ENABLED_SP_FF_3072=yes + ENABLED_SP_ECC=yes + ENABLED_SP_EC_256=yes + if test "$host_cpu" = "x86_64"; then + ENABLED_SP_FF_4096=yes + ENABLED_SP_EC_384=yes + fi + ;; + no) + ;; + + smallec256 | smallp256 | small256) + ENABLED_SP_ECC=yes + ENABLED_SP_SMALL=yes + ENABLED_SP_EC_256=yes + ;; + ec256 | p256 | 256) + ENABLED_SP_ECC=yes + ENABLED_SP_EC_256=yes + ;; + smallec384 | smallp384 | small384) + ENABLED_SP_ECC=yes + ENABLED_SP_SMALL=yes + ENABLED_SP_EC_384=yes + ;; + ec384 | p384 | 384) + ENABLED_SP_ECC=yes + ENABLED_SP_EC_384=yes + ;; + + small2048) + ENABLED_SP_SMALL=yes + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_2048=yes + ;; + 2048) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_2048=yes + ;; + + smallrsa2048) + ENABLED_SP_SMALL=yes + ENABLED_SP_RSA=yes + ENABLED_SP_FF_2048=yes + ;; + rsa2048) + ENABLED_SP_RSA=yes + ENABLED_SP_FF_2048=yes + ;; + + small3072) + ENABLED_SP_SMALL=yes + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_3072=yes + ;; + 3072) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_3072=yes + ;; + + smallrsa3072) + ENABLED_SP_SMALL=yes + ENABLED_SP_RSA=yes + ENABLED_SP_FF_3072=yes + ;; + rsa3072) + ENABLED_SP_RSA=yes + ENABLED_SP_FF_3072=yes + ;; + + small4096) + ENABLED_SP_SMALL=yes + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_4096=yes + ;; + + 4096 | +4096) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_4096=yes + ;; + + smallrsa4096) + ENABLED_SP_SMALL=yes + ENABLED_SP_RSA=yes + ENABLED_SP_FF_4096=yes + ;; + + rsa4096) + ENABLED_SP_RSA=yes + ENABLED_SP_FF_4096=yes + ;; + + nomalloc) + ENABLED_SP_NO_MALLOC=yes + ;; + + *) + as_fn_error $? "Invalid choice of Single Precision length in bits 256, 2048, 3072: $ENABLED_SP." "$LINENO" 5 + 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" + AM_CCASFLAGS="$AM_CCASFLAGS -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" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_HAVE_SP_DH" +fi +if test "$ENABLED_SP_RSA" = "yes" || test "$ENABLED_SP_DH" = "yes"; then + if test "$ENABLED_SP_FF_2048" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_2048" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NO_2048" + fi + if test "$ENABLED_SP_FF_3072" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_3072" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NO_3072" + fi + if test "$ENABLED_SP_FF_4096" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_4096" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_4096" + fi +fi +if test "$ENABLED_ECC" = "yes" && test "$ENABLED_SP_ECC" = "yes"; then + ENABLED_SP=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_SP_ECC" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_HAVE_SP_ECC" + if test "$ENABLED_SP_EC_256" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_256" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NO_256" + fi + if test "$ENABLED_SP_EC_384" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC384 -DWOLFSSL_SP_384" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_384" + fi +fi +if test "$ENABLED_SP_SMALL" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_SMALL" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_SMALL" +fi +if test "$ENABLED_SP_NO_MALLOC" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_MALLOC" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NO_MALLOC" +fi + + +# Check whether --enable-sp-asm was given. +if test "${enable_sp_asm+set}" = set; then : + enableval=$enable_sp_asm; ENABLED_SP_ASM=$enableval +else + ENABLED_SP_ASM=no +fi + +if test "$ENABLED_SP_ASM" = "yes"; then + if test "$ENABLED_SP" = "no"; then + as_fn_error $? "Must have SP enabled: --enable-sp" "$LINENO" 5 + fi + if test "$ENABLED_ASM" = "no"; then + as_fn_error $? "Assembly code turned off" "$LINENO" 5 + fi + + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_ASM" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_ASM" + case $host_cpu in + *aarch64*) + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_ARM64_ASM" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_ARM64_ASM" + ENABLED_SP_ARM64_ASM=yes + ;; + *arm*) + if test $host_alias = "thumb"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_ARM_THUMB_ASM -mthumb -march=armv6" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_ARM_THUMB_ASM" + ENABLED_SP_ARM_THUMB_ASM=yes + else + if test $host_alias = "cortex"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_ARM_CORTEX_M_ASM -mcpu=cortex-r5" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_ARM_CORTEX_M_ASM" + ENABLED_SP_ARM_CORTEX_ASM=yes + else + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_ARM32_ASM" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_ARM32_ASM" + ENABLED_SP_ARM32_ASM=yes + fi + fi + ;; + *x86_64*) + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_X86_64_ASM" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_X86_64_ASM" + ENABLED_SP_X86_64_ASM=yes + ;; + *) + as_fn_error $? "ASM not available for CPU. Supported CPUs: x86_64, aarch64, arm" "$LINENO" 5 + ;; + esac +fi + +# Check whether --enable-sp-math was given. +if test "${enable_sp_math+set}" = set; then : + enableval=$enable_sp_math; ENABLED_SP_MATH=$enableval +else + ENABLED_SP_MATH=no +fi + +if test "$ENABLED_SP_MATH" = "yes"; then + if test "$ENABLED_SP" = "no"; then + as_fn_error $? "Must have SP enabled: --enable-sp" "$LINENO" 5 + fi + if test "$ENABLED_ECCCUSTCURVES" = "yes"; then + as_fn_error $? "Cannot use single precision math and custom curves" "$LINENO" 5 + fi + if test "$ENABLED_OPENSSLEXTRA" = "yes"; then + as_fn_error $? "Cannot use single precision math and OpenSSL extra" "$LINENO" 5 + fi + if test "$ENABLED_DSA" = "yes"; then + as_fn_error $? "Cannot use single precision math and DSA" "$LINENO" 5 + fi + if test "$ENABLED_SRP" = "yes"; then + as_fn_error $? "Cannot use single precision math and SRP" "$LINENO" 5 + fi + if test "$ENABLED_SP_RSA" = "no" && test "$ENABLED_RSA" = "yes"; then + as_fn_error $? "Cannot use RSA single precision only math and RSA" "$LINENO" 5 + fi + if test "$ENABLED_SP_DH" = "no" && test "$ENABLED_DH" = "yes"; then + as_fn_error $? "Cannot use DH single precision only math and DH" "$LINENO" 5 + fi + + ENABLED_FASTMATH="no" + ENABLED_SLOWMATH="no" +fi +if test "$ENABLED_SP_MATH" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_MATH" +fi + + +# Fast RSA using Intel IPP +ippdir="${srcdir}/IPP" +ipplib="lib" # if autoconf guesses 32bit system changes lib directory +fastRSA_found=no +abs_path=`pwd` + +# set up variables used +IPPLIBS= +IPPHEADERS= +IPPLINK= + +# Check whether --enable-fast-rsa was given. +if test "${enable_fast_rsa+set}" = set; then : + enableval=$enable_fast_rsa; ENABLED_FAST_RSA=$enableval +else + ENABLED_FAST_RSA=no +fi + + +if test "$ENABLED_USER_RSA" = "no" && test "$ENABLED_FIPS" = "no"; then + + if test "$ac_cv_sizeof_long" = "4" && test "$ac_cv_sizeof_long_long" = "8"; then + ipplib="lib_32" # 32 bit OS detected + fi + +# Use static IPP Libraries +if test "$enable_shared" = "no" && test "$ENABLED_FAST_RSA" = "yes"; then + case $host_os in + *darwin*) + ipplib="$ipplib/mac_static" + as_fn_error $? "Issue with static linking to libippcp.a on Mac. + Dynamic IPP libraries supported on Mac" "$LINENO" 5 + break;; + + *linux*) + ipplib="$ipplib/linux_static" + break;; + *) + ENABLED_FAST_RSA=no + esac + + as_ac_File=`$as_echo "ac_cv_file_$srcdir/IPP/$ipplib/libippcore.a" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $srcdir/IPP/$ipplib/libippcore.a" >&5 +$as_echo_n "checking for $srcdir/IPP/$ipplib/libippcore.a... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "$srcdir/IPP/$ipplib/libippcore.a"; then + eval "$as_ac_File=yes" +else + eval "$as_ac_File=no" +fi +fi +eval ac_res=\$$as_ac_File + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$srcdir/IPP/$ipplib/libippcore.a" | $as_tr_cpp` 1 +_ACEOF + +else + ENABLED_FAST_RSA=no +fi +as_ac_File=`$as_echo "ac_cv_file_$srcdir/IPP/$ipplib/libippcp.a" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $srcdir/IPP/$ipplib/libippcp.a" >&5 +$as_echo_n "checking for $srcdir/IPP/$ipplib/libippcp.a... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "$srcdir/IPP/$ipplib/libippcp.a"; then + eval "$as_ac_File=yes" +else + eval "$as_ac_File=no" +fi +fi +eval ac_res=\$$as_ac_File + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$srcdir/IPP/$ipplib/libippcp.a" | $as_tr_cpp` 1 +_ACEOF + +else + ENABLED_FAST_RSA=no +fi + + as_ac_File=`$as_echo "ac_cv_file_$srcdir/IPP/include/ipp.h" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $srcdir/IPP/include/ipp.h" >&5 +$as_echo_n "checking for $srcdir/IPP/include/ipp.h... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "$srcdir/IPP/include/ipp.h"; then + eval "$as_ac_File=yes" +else + eval "$as_ac_File=no" +fi +fi +eval ac_res=\$$as_ac_File + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$srcdir/IPP/include/ipp.h" | $as_tr_cpp` 1 +_ACEOF +AM_CPPFLAGS="-I$srcdir/IPP/include $AM_CPPFLAGS" +else + ENABLED_FAST_RSA=no +fi +as_ac_File=`$as_echo "ac_cv_file_$srcdir/IPP/include/ippcp.h" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $srcdir/IPP/include/ippcp.h" >&5 +$as_echo_n "checking for $srcdir/IPP/include/ippcp.h... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "$srcdir/IPP/include/ippcp.h"; then + eval "$as_ac_File=yes" +else + eval "$as_ac_File=no" +fi +fi +eval ac_res=\$$as_ac_File + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$srcdir/IPP/include/ippcp.h" | $as_tr_cpp` 1 +_ACEOF +AM_CPPFLAGS="-I$srcdir/IPP/include $AM_CPPFLAGS" +else + ENABLED_FAST_RSA=no +fi + + LIB_STATIC_ADD="$srcdir/IPP/$ipplib/libippcp.a $srcdir/IPP/$ipplib/libippcore.a $LIB_STATIC_ADD" + if test "$ENABLED_FAST_RSA" = "no"; then + as_fn_error $? "Could not find fast rsa libraries" "$LINENO" 5 + fi +else + +# Check for and use bundled IPP libraries +if test "$ENABLED_FAST_RSA" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Using local IPP crypto library" >&5 +$as_echo "$as_me: Using local IPP crypto library" >&6;} + + as_ac_File=`$as_echo "ac_cv_file_$abs_path/IPP/include/ippcp.h" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $abs_path/IPP/include/ippcp.h" >&5 +$as_echo_n "checking for $abs_path/IPP/include/ippcp.h... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "$abs_path/IPP/include/ippcp.h"; then + eval "$as_ac_File=yes" +else + eval "$as_ac_File=no" +fi +fi +eval ac_res=\$$as_ac_File + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$abs_path/IPP/include/ippcp.h" | $as_tr_cpp` 1 +_ACEOF + + # build and default locations on linux and mac + STORE_LDFLAGS=${LDFLAGS} + STORE_CPPFLAGS=${CPPFLAGS} + + # using LDFLAGS instead of AM_ temporarily to test link to library + LDFLAGS="-L$ippdir/$ipplib -lippcp -lippcore" + CPPFLAGS="-I$ippdir/include" + for ac_header in ippcp.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "ippcp.h" "ac_cv_header_ippcp_h" "$ac_includes_default" +if test "x$ac_cv_header_ippcp_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_IPPCP_H 1 +_ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ippsRSAEncrypt_PKCSv15 in -lippcp" >&5 +$as_echo_n "checking for ippsRSAEncrypt_PKCSv15 in -lippcp... " >&6; } +if ${ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lippcp $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ippsRSAEncrypt_PKCSv15 (); +int +main () +{ +return ippsRSAEncrypt_PKCSv15 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15=yes +else + ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15" >&5 +$as_echo "$ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15" >&6; } +if test "x$ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15" = xyes; then : + fastRSA_found=yes +else + fastRSA_found=no +fi + +else + fastRSA_found=no +fi + +done + + name="$ippdir/$ipplib/libippcp" + case $host_os in + *darwin*) + # check file existence and conditionally set variables + as_ac_File=`$as_echo "ac_cv_file_$abs_path/IPP/$ipplib/libippcp.dylib" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $abs_path/IPP/$ipplib/libippcp.dylib" >&5 +$as_echo_n "checking for $abs_path/IPP/$ipplib/libippcp.dylib... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "$abs_path/IPP/$ipplib/libippcp.dylib"; then + eval "$as_ac_File=yes" +else + eval "$as_ac_File=no" +fi +fi +eval ac_res=\$$as_ac_File + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$abs_path/IPP/$ipplib/libippcp.dylib" | $as_tr_cpp` 1 +_ACEOF + + IPPLIBS="${name}.dylib ${name}-9.0.dylib ${name}e9-9.0.dylib ${name}g9-9.0.dylib ${name}h9-9.0.dylib ${name}k0-9.0.dylib ${name}l9-9.0.dylib ${name}n8-9.0.dylib ${name}p8-9.0.dylib ${name}s8-9.0.dylib ${name}y8-9.0.dylib IPP/lib/libippcore.dylib IPP/lib/libippcore-9.0.dylib" + IPPLINK="mkdir -p src/.libs && ln -f ${name}.dylib src/.libs/libippcp.dylib && ln -f ${srcdir}/${name}-9.0.dylib src/.libs/libippcp-9.0.dylib && ln -f ${srcdir}/${name}e9-9.0.dylib src/.libs/libippcpe9-9.0.dylib && ln -f ${srcdir}/${name}g9-9.0.dylib src/.libs/libippcpg9-9.0.dylib && ln -f ${srcdir}/${name}h9-9.0.dylib src/.libs/libippcph9-9.0.dylib && ln -f ${srcdir}/${name}k0-9.0.dylib src/.libs/libippcpk0-9.0.dylib && ln -f ${srcdir}/${name}l9-9.0.dylib src/.libs/libippcpl9-9.0.dylib && ln -f ${srcdir}/${name}n8-9.0.dylib src/.libs/libippcpn8-9.0.dylib && ln -f ${srcdir}/${name}p8-9.0.dylib src/.libs/libippcpp8-9.0.dylib && ln -f ${srcdir}/${name}s8-9.0.dylib src/.libs/libippcps8-9.0.dylib && ln -f ${srcdir}/${name}y8-9.0.dylib src/.libs/libippcpy8-9.0.dylib && ln -f ${srcdir}/IPP/lib/libippcore.dylib src/.libs/libippcore.dylib && ln -f ${srcdir}/IPP/lib/libippcore-9.0.dylib src/.libs/libippcore-9.0.dylib" + +else + fastRSA_found=no +fi + + break;; + + *linux*) + # check file existence and conditionally set variables + as_ac_File=`$as_echo "ac_cv_file_$abs_path/IPP/$ipplib/libippcp.so.9.0" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $abs_path/IPP/$ipplib/libippcp.so.9.0" >&5 +$as_echo_n "checking for $abs_path/IPP/$ipplib/libippcp.so.9.0... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "$abs_path/IPP/$ipplib/libippcp.so.9.0"; then + eval "$as_ac_File=yes" +else + eval "$as_ac_File=no" +fi +fi +eval ac_res=\$$as_ac_File + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$abs_path/IPP/$ipplib/libippcp.so.9.0" | $as_tr_cpp` 1 +_ACEOF + + if test "$ac_cv_sizeof_long" = "4" && test "$ac_cv_sizeof_long_long" = "8"; then + IPPLIBS="${name}.so.9.0 ${name}g9.so.9.0 ${name}h9.so.9.0 ${name}p8.so.9.0 ${name}px.so.9.0 ${name}s8.so.9.0 ${name}.so ${name}w7.so.9.0 IPP/$ipplib/libippcore.so IPP/$ipplib/libippcore.so.9.0" + IPPLINK="mkdir -p src/.libs && ln -f ${name}.so.9.0 src/.libs/libippcp.so.9.0 && ln -f ${name}g9.so.9.0 src/.libs/libippcpg9.so.9.0 && ln -f ${name}h9.so.9.0 src/.libs/libippcph9.so.9.0 && ln -f ${name}p8.so.9.0 src/.libs/libippcpp8.so.9.0 && ln -f ${name}px.so.9.0 src/.libs/libippcppx.so.9.0 && ln -f ${name}s8.so.9.0 src/.libs/libippcps8.so.9.0 && ln -f ${name}.so src/.libs/libippcp.so && ln -f ${name}w7.so.9.0 src/.libs/libippcpw7.so.9.0 && ln -f IPP/$ipplib/libippcore.so src/.libs/libippcore.so && ln -f IPP/$ipplib/libippcore.so.9.0 src/.libs/libippcore.so.9.0" + else + IPPLIBS="${name}.so.9.0 ${name}e9.so.9.0 ${name}k0.so.9.0 ${name}l9.so.9.0 ${name}m7.so.9.0 ${name}mx.so.9.0 ${name}.so ${name}n8.so.9.0 ${name}y8.so.9.0 IPP/lib/libippcore.so IPP/lib/libippcore.so.9.0" + IPPLINK="mkdir -p src/.libs && ln -f ${name}.so.9.0 src/.libs/libippcp.so.9.0 && ln -f ${name}e9.so.9.0 src/.libs/libippcpe9.so.9.0 && ln -f ${name}k0.so.9.0 src/.libs/libippcpk0.so.9.0 && ln -f ${name}l9.so.9.0 src/.libs/libippcpl9.so.9.0 && ln -f ${name}m7.so.9.0 src/.libs/libippcpm7.so.9.0 && ln -f ${name}mx.so.9.0 src/.libs/libippcpmx.so.9.0 && ln -f ${name}.so src/.libs/libippcp.so && ln -f ${name}n8.so.9.0 src/.libs/libippcpn8.so.9.0 && ln -f ${name}y8.so.9.0 src/.libs/libippcpy8.so.9.0 && ln -f IPP/lib/libippcore.so src/.libs/libippcore.so && ln -f IPP/lib/libippcore.so.9.0 src/.libs/libippcore.so.9.0" + fi + +else + fastRSA_found=no +fi + + break;; + *) + fastRSA_found=no + esac + + if test "$fastRSA_found" = "yes"; then + # was succesfull so add tested LDFLAGS to AM_ flags + AM_LDFLAGS="${AM_LDFLAGS} ${LDFLAGS}" + AM_CPPFLAGS="${AM_CPPFLAGS} ${CPPFLAGS}" + IPPHEADERS="${srcdir}/IPP/include/*.h" + fi + + # restore LDFLAGS to user set + LDFLAGS=${STORE_LDFLAGS} + CPPFLAGS=${STORE_CPPFLAGS} + +else + fastRSA_found=no +fi + +fi + +# Don't cache the result so it can be checked +{ ac_cv_header_ippcp_h=; unset ac_cv_header_ippcp_h;} +{ ac_cv_header_ipp_h=; unset ac_cv_header_ipp_h;} +{ ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15=; unset ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15;}; + +# Check link and see if user has pre-existing IPP Libraries if not using local +if test "$ENABLED_FAST_RSA" = "yes" && test "$fastRSA_found" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Checking if IPP crypto library installed" >&5 +$as_echo "$as_me: Checking if IPP crypto library installed" >&6;} + ac_fn_c_check_header_mongrel "$LINENO" "ippcp.h" "ac_cv_header_ippcp_h" "$ac_includes_default" +if test "x$ac_cv_header_ippcp_h" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ippsRSAEncrypt_PKCSv15 in -lippcp" >&5 +$as_echo_n "checking for ippsRSAEncrypt_PKCSv15 in -lippcp... " >&6; } +if ${ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lippcp $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ippsRSAEncrypt_PKCSv15 (); +int +main () +{ +return ippsRSAEncrypt_PKCSv15 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15=yes +else + ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15" >&5 +$as_echo "$ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15" >&6; } +if test "x$ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15" = xyes; then : + + fastRSA_found=yes + AM_LDFLAGS="${AM_LDFLAGS} -lippcore -lippcp" + +else + fastRSA_found=no +fi + + +else + fastRSA_found=no +fi + + + + # Error out on not finding libraries + if test "$fastRSA_found" = "no"; then + as_fn_error $? "Could not find fast rsa libraries" "$LINENO" 5 + fi +fi +fi # end of if for shared library +else # if user rsa is set than do not use fast rsa option + if test "$ENABLED_FAST_RSA" = "yes"; then + as_fn_error $? "Could not use fast rsa libraries with user crypto or fips" "$LINENO" 5 + fi +fi # end of if for user rsa crypto or fips + +# End result of checking for IPP Libraries +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fast RSA" >&5 +$as_echo_n "checking for fast RSA... " >&6; } +if test "$ENABLED_FAST_RSA" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DHAVE_FAST_RSA -DHAVE_USER_RSA" + # add in user crypto header that uses Intel IPP + AM_CPPFLAGS="$AM_CPPFLAGS -I$srcdir/wolfcrypt/user-crypto/include" + if test "$enable_shared" = "yes"; then + LIBS="$LIBS -lippcore -lippcp" + LIB_ADD="-lippcp -lippcore $LIB_ADD" + else + LIB_ADD="$srcdir/IPP/$ipplib/libippcp.a $srcdir/IPP/$ipplib/libippcore.a $LIB_ADD" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + + +# static memory use +# Check whether --enable-staticmemory was given. +if test "${enable_staticmemory+set}" = set; then : + enableval=$enable_staticmemory; ENABLED_STATICMEMORY=$enableval +else + ENABLED_STATICMEMORY=no + +fi + + +if test "x$ENABLED_STATICMEMORY" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY" + if test "x$ENABLED_FASTMATH" = "xno" + then + as_fn_error $? "please use --enable-fastmath if enabling staticmemory." "$LINENO" 5 + fi + if test "$ENABLED_LOWRESOURCE" = "yes" && test "$ENABLED_RSA" = "no" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY_SMALL" + fi +fi + + # microchip api # Check whether --enable-mcapi was given. if test "${enable_mcapi+set}" = set; then : @@ -21241,7 +21014,12 @@ fi 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" @@ -21259,110 +21037,1047 @@ then as_fn_error $? "please use --with-libz if enabling mcapi." "$LINENO" 5 fi - if test "x$ENABLED_MCAPI" = "xyes"; then - BUILD_MCAPI_TRUE= - BUILD_MCAPI_FALSE='#' + +# Asynchronous Crypto +# Check whether --enable-asynccrypt was given. +if test "${enable_asynccrypt+set}" = set; then : + enableval=$enable_asynccrypt; ENABLED_ASYNCCRYPT=$enableval else - BUILD_MCAPI_TRUE='#' - BUILD_MCAPI_FALSE= + ENABLED_ASYNCCRYPT=no + fi - -# wolfSSL JNI -# Check whether --enable-jni was given. -if test "${enable_jni+set}" = set; then : - enableval=$enable_jni; ENABLED_JNI=$enableval -else - ENABLED_JNI=no - -fi - -if test "$ENABLED_JNI" = "yes" +if test "$ENABLED_ASYNCCRYPT" = "yes" then - # Enable prereqs if not already enabled - if test "x$ENABLED_DTLS" = "xno" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ASYNC_CRYPT -DHAVE_WOLF_EVENT -DHAVE_WOLF_BIGINT -DWOLFSSL_NO_HASH_RAW" + + # if no async hardware then use simulator for testing + if test "x$ENABLED_CAVIUM" = "xno" && test "x$ENABLED_INTEL_QA" = "xno" then - ENABLED_DTLS="yes" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DTLS" + # Async threading is Linux specific + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ASYNC_CRYPT_TEST" fi - if test "x$ENABLED_OPENSSLEXTRA" = "xno" - then - ENABLED_OPENSSLEXTRA="yes" - AM_CFLAGS="$AM_CFLAGS -DOPENSSL_EXTRA" +fi + + +# 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 + as_fn_error $? "Please enable asynchronous support using --enable-asynccrypt" "$LINENO" 5 fi - if test "x$ENABLED_CRL" = "xno" - then - ENABLED_CRL="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL" - if test "x$ENABLED_CRL" = "xyes"; then - BUILD_CRL_TRUE= - BUILD_CRL_FALSE='#' +fi + + +# Asynchronous threading +# Check whether --enable-asyncthreads was given. +if test "${enable_asyncthreads+set}" = set; then : + enableval=$enable_asyncthreads; ENABLED_ASYNCTHREADS=$enableval else - BUILD_CRL_TRUE='#' - BUILD_CRL_FALSE= + ENABLED_ASYNCTHREADS=yes + fi - fi - if test "x$ENABLED_OCSP" = "xno" - then - ENABLED_OCSP="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" - if test "x$ENABLED_OCSP" = "xyes"; then - BUILD_OCSP_TRUE= - BUILD_OCSP_FALSE='#' + +if test "$ENABLED_ASYNCCRYPT" = "yes" && test "$ENABLED_ASYNCTHREADS" = "yes" +then + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + if test "x$PTHREAD_CC" != "x"; then : + CC="$PTHREAD_CC" +fi + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5 +$as_echo_n "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_join (); +int +main () +{ +return pthread_join (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5 +$as_echo "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;} +fi +rm -f conftest* + + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; +esac + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +if test "x$GCC" = "xyes"; then : + ax_pthread_flags="-pthread -pthreads $ax_pthread_flags" +fi + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +if test "x$ax_pthread_check_macro" = "x--"; then : + ax_pthread_check_cond=0 else - BUILD_OCSP_TRUE='#' - BUILD_OCSP_FALSE= + ax_pthread_check_cond="!defined($ax_pthread_check_macro)" fi - fi - if test "x$ENABLED_CRL_MONITOR" = "xno" +# Are we compiling with Clang? + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5 +$as_echo_n "checking whether $CC is Clang... " >&6; } +if ${ax_cv_PTHREAD_CLANG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1; then : + ax_cv_PTHREAD_CLANG=yes +fi +rm -f conftest* + + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG" >&6; } +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5 +$as_echo_n "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; } +if ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + if test "x$ax_pthread_try" = "xunknown"; then : + break +fi + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_link="$ax_pthread_2step_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + if test "x$ax_pthread_try" = "x"; then : + ax_pthread_try=no +fi + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; } + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 +$as_echo_n "checking whether pthreads work without any flags... " >&6; } + ;; + + -mt,pthread) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with -mt -lpthread" >&5 +$as_echo_n "checking whether pthreads work with -mt -lpthread... " >&6; } + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5 +$as_echo_n "checking whether pthreads work with $ax_pthread_try_flag... " >&6; } + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + # Extract the first word of "pthread-config", so it can be a program name with args. +set dummy pthread-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ax_pthread_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ax_pthread_config"; then + ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ax_pthread_config="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" +fi +fi +ax_pthread_config=$ac_cv_prog_ax_pthread_config +if test -n "$ax_pthread_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 +$as_echo "$ax_pthread_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$ax_pthread_config" = "xno"; then : + continue +fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5 +$as_echo_n "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; } + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; } +int +main () +{ +pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xyes"; then : + break +fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 +$as_echo_n "checking for joinable pthread attribute... " >&6; } +if ${ax_cv_PTHREAD_JOINABLE_ATTR+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int attr = $ax_pthread_attr; return attr /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5 +$as_echo "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; } + if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"; then : + +cat >>confdefs.h <<_ACEOF +#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR +_ACEOF + + ax_pthread_joinable_attr_defined=yes + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5 +$as_echo_n "checking whether more special flags are required for pthreads... " >&6; } +if ${ax_cv_PTHREAD_SPECIAL_FLAGS+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5 +$as_echo "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; } + if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"; then : + PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 +$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; } +if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int i = PTHREAD_PRIO_INHERIT; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_PRIO_INHERIT=yes +else + ax_cv_PTHREAD_PRIO_INHERIT=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 +$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } + if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"; then : + +$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h + + ax_pthread_prio_inherit_defined=yes + +fi + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + case "x/$CC" in #( + x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) : + #handle absolute path differently from PATH based program lookup + case "x$CC" in #( + x/*) : + if as_fn_executable_p ${CC}_r; then : + PTHREAD_CC="${CC}_r" +fi ;; #( + *) : + for ac_prog in ${CC}_r +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PTHREAD_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PTHREAD_CC"; then + ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PTHREAD_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PTHREAD_CC=$ac_cv_prog_PTHREAD_CC +if test -n "$PTHREAD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 +$as_echo "$PTHREAD_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PTHREAD_CC" && break +done +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + ;; +esac ;; #( + *) : + ;; +esac + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + + + + + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + ENABLED_ASYNCTHREADS=yes + : +else + ax_pthread_ok=no + ENABLED_ASYNCTHREADS=no +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +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 + + +# cryptodev is old name, replaced with cryptocb +# Check whether --enable-cryptodev was given. +if test "${enable_cryptodev+set}" = set; then : + enableval=$enable_cryptodev; ENABLED_CRYPTOCB=$enableval +else + ENABLED_CRYPTOCB=no +fi + + +# Support for crypto callbacks +# Check whether --enable-cryptocb was given. +if test "${enable_cryptocb+set}" = set; then : + enableval=$enable_cryptocb; ENABLED_CRYPTOCB=$enableval +else + ENABLED_CRYPTOCB=no + +fi + + +if test "x$ENABLED_PKCS11" = "xyes" +then + ENABLED_CRYPTOCB=yes +fi +if test "$ENABLED_CRYPTOCB" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLF_CRYPTO_CB" +fi + + +# Session Export +# Check whether --enable-sessionexport was given. +if test "${enable_sessionexport+set}" = set; then : + enableval=$enable_sessionexport; ENABLED_SESSIONEXPORT=$enableval +else + ENABLED_SESSIONEXPORT=no + +fi + + +if test "$ENABLED_SESSIONEXPORT" = "yes" || + test "$ENABLED_SESSIONEXPORT" = "nopeer" +then + if test "$ENABLED_DTLS" = "no" then - ENABLED_CRL_MONITOR="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL_MONITOR" + as_fn_error $? "Only DTLS supported with session export" "$LINENO" 5 fi - if test "x$ENABLED_SAVESESSION" = "xno" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SESSION_EXPORT" + + if test "$ENABLED_SESSIONEXPORT" = "nopeer" then - ENABLED_SAVESESSION="yes" - AM_CFLAGS="$AM_CFLAGS -DPERSIST_SESSION_CACHE" - fi - if test "x$ENABLED_SAVECERT" = "xno" - then - ENABLED_SAVECERT="yes" - AM_CFLAGS="$AM_CFLAGS -DPERSIST_CERT_CACHE" - fi - if test "x$ENABLED_ATOMICUSER" = "xno" - then - ENABLED_ATOMICUSER="yes" - AM_CFLAGS="$AM_CFLAGS -DATOMIC_USER" - fi - if test "x$ENABLED_ECC" = "xno" - then - ENABLED_ECC="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC" - fi - if test "x$ENABLED_PKCALLBACKS" = "xno" - then - ENABLED_PKCALLBACKS="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_PK_CALLBACKS" - fi - if test "x$ENABLED_DH" = "xno" - then - ENABLED_DH="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_DH" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SESSION_EXPORT_NOPEER" fi fi -# Check for build-type conflicts +# AES key wrap +# Check whether --enable-aeskeywrap was given. +if test "${enable_aeskeywrap+set}" = set; then : + enableval=$enable_aeskeywrap; ENABLED_AESKEYWRAP=$enableval +else + ENABLED_AESKEYWRAP=no + +fi + + +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 +# Check whether --enable-oldnames was given. +if test "${enable_oldnames+set}" = set; then : + enableval=$enable_oldnames; ENABLED_OLDNAMES=$enableval +else + ENABLED_OLDNAMES=yes + +fi + + +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" + AM_CFLAGS="$AM_CFLAGS -DNO_OLD_SHA_NAMES" +fi + + +# Memory Tests +# Check whether --enable-memtest was given. +if test "${enable_memtest+set}" = set; then : + enableval=$enable_memtest; ENABLED_MEMTEST=$enableval +else + ENABLED_MEMTEST=no + +fi + + +if test "x$ENABLED_MEMTEST" != "xno" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TRACK_MEMORY -DWOLFSSL_DEBUG_MEMORY -DWOLFSSL_FORCE_MALLOC_FAIL_TEST" +fi + + +# Enable hash flags support +# Hash flags are useful for runtime options such as SHA3 KECCAK256 selection +# Check whether --enable-hashflags was given. +if test "${enable_hashflags+set}" = set; then : + enableval=$enable_hashflags; ENABLED_HASHFLAGS=$enableval +else + ENABLED_HASHFLAGS=no + +fi + + +if test "x$ENABLED_HASHFLAGS" != "xno" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HASH_FLAGS" +fi + +# Support for enabling setting default DH parameters in +# Check whether --enable-defaultdhparams was given. +if test "${enable_defaultdhparams+set}" = set; then : + enableval=$enable_defaultdhparams; ENABLED_DHDEFAULTPARAMS=$enableval +else + ENABLED_DHDEFAULTPARAMS=no + +fi + +if test "$ENABLED_DHDEFAULTPARAMS" = "yes" || test "$ENABLED_QT" = "no" +then + ENABLED_DHDEFAULTPARAMS=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_DH_DEFAULT_PARAMS" +fi + +# User Settings +# Check whether --enable-usersettings was given. +if test "${enable_usersettings+set}" = set; then : + enableval=$enable_usersettings; ENABLED_USERSETTINGS=$enableval +else + ENABLED_USERSETTINGS=no + +fi + + + +# Default optimization CFLAGS enable +# Check whether --enable-optflags was given. +if test "${enable_optflags+set}" = set; then : + enableval=$enable_optflags; ENABLED_OPTFLAGS=$enableval +else + ENABLED_OPTFLAGS=yes + +fi + + + +# check if should run the trusted peer certs test +# (for now checking both C_FLAGS and C_EXTRA_FLAGS) +case "$CFLAGS $CPPFLAGS" in #( + *'WOLFSSL_TRUST_PEER_CERT'*) : + ENABLED_TRUSTED_PEER_CERT=yes ;; #( + *) : + ;; +esac + + +# 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 + + +# When building for wolfRand, strip out all options to disable everything. +if test "x$ENABLED_FIPS" = "xyes" && test "x$FIPS_VERSION" = "xrand"; then : + NEW_AM_CFLAGS="-DNO_AES -DNO_DH -DNO_ASN -DNO_RSA -DNO_SHA -DNO_MD5 -DNO_BIG_INT" +for v in $AM_CFLAGS +do + case $v in +-DHAVE_FFDHE_2048 | -DTFM_TIMING_RESISTANT | -DECC_TIMING_RESISTANT | \ +-DWC_RSA_BLINDING | -DHAVE_AESGCM | -DWOLFSSL_SHA512 | -DWOLFSSL_SHA384 | \ +-DHAVE_ECC | -DTFM_ECC256 | -DECC_SHAMIR | -DHAVE_TLS_EXTENSIONS | \ +-DHAVE_SUPPORTED_CURVES | -DHAVE_EXTENDED_MASTER | -DUSE_FAST_MATH) + $as_echo "ignoring $v" + ;; + *) + NEW_AM_CFLAGS="$NEW_AM_CFLAGS $v" + ;; + esac +done +AM_CFLAGS=$NEW_AM_CFLAGS +fi + + +################################################################################ +# Check for build-type conflicts # +################################################################################ + if test "x$ENABLED_MAXSTRENGTH" = "xyes" && \ test "x$ENABLED_LEANPSK" = "xyes"; then : as_fn_error $? "Cannot use Max Strength and Lean PSK at the same time." "$LINENO" 5 fi +if test "x$ENABLED_OCSP" = "xyes" && \ + test "x$ENABLED_ASN" = "xno"; then : + as_fn_error $? "please enable asn if enabling ocsp." "$LINENO" 5 +fi + +if test "x$ENABLED_OCSP" = "xyes" && \ + test "x$ENABLED_RSA" = "xno" && \ + test "x$ENABLED_ECC" = "xno"; then : + as_fn_error $? "please enable rsa or ecc if enabling ocsp." "$LINENO" 5 +fi + +# Sync Intel QA and Sync Cavium Octeon require the crypto callback +if test "x$ENABLED_INTEL_QA_SYNC" = "xyes" || test "x$ENABLED_OCTEON_SYNC" = "xyes"; then : + if test "x$ENABLED_CRYPTOCB" = "xno"; then : + as_fn_error $? "please enable the crypto callback support using --enable-cryptocb" "$LINENO" 5 +fi +fi + +# checks for pkcs7 needed enables +if test "x$ENABLED_PKCS7" = "xyes" && \ + test "x$ENABLED_RSA" = "xno" && \ + test "x$ENABLED_ECC" = "xno"; then : + as_fn_error $? "please enable ecc or rsa if enabling pkcs7." "$LINENO" 5 +fi + +if test "x$ENABLED_PKCS7" = "xyes" && \ + test "x$ENABLED_SHA" = "xno"; then : + as_fn_error $? "please enable sha if enabling pkcs7." "$LINENO" 5 +fi + +if test "x$ENABLED_PKCS7" = "xyes" && \ + test "x$ENABLED_AES" = "xno" && \ + test "x$ENABLED_DES3" = "xno"; then : + as_fn_error $? "please enable either AES or 3DES if enabling pkcs7." "$LINENO" 5 +fi + +if test "x$ENABLED_WOLFSCEP" = "xyes" && \ + test "x$ENABLED_AES" = "xno" && \ + test "x$ENABLED_DES3" = "xno"; then : + as_fn_error $? "please enable either AES or 3DES if enabling scep." "$LINENO" 5 +fi + +if test "x$ENABLED_LEANTLS" = "xyes" && \ + test "x$ENABLED_ECC" = "xno"; then : + as_fn_error $? "please enable ecc if enabling leantls." "$LINENO" 5 +fi + +if test "x$ENABLED_SNIFFER" = "xyes" && \ + test "x$ENABLED_RSA" = "xno"; then : + as_fn_error $? "please enable rsa if enabling sniffer." "$LINENO" 5 +fi + +# Lean TLS forces off prereqs of SCEP. +if test "x$ENABLED_SCEP" = "xyes" && \ + test "x$ENABLED_LEANTLS" = "xyes"; then : + as_fn_error $? "Cannot use SCEP and Lean TLS at the same time." "$LINENO" 5 +fi + +# CMAC currently requires AES. +if test "x$ENABLED_CMAC" = "xyes" && \ + test "x$ENABLED_AES" = "xno"; then : + as_fn_error $? "cannot use CMAC without AES." "$LINENO" 5 +fi + +################################################################################ +# Update CFLAGS based on options # +################################################################################ + +if test "x$ENABLED_MCAPI" = "xyes"; then : + if test "x$ENABLED_DES3" = "xno"; then : + ENABLED_DES3="yes" +fi +fi + +if test "$ENABLED_WOLFSCEP" = "yes" +then + # Enable prereqs if not already enabled + if test "x$ENABLED_KEYGEN" = "xno" + then + ENABLED_KEYGEN="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KEY_GEN" + fi + if test "x$ENABLED_CERTGEN" = "xno" + then + ENABLED_CERTGEN="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN" + fi + if test "x$ENABLED_CERTREQ" = "xno" + then + ENABLED_CERTREQ="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_REQ" + fi + if test "x$ENABLED_CERTEXT" = "xno" + then + ENABLED_CERTEXT="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" + fi + if test "x$ENABLED_PKCS7" = "xno" + then + ENABLED_PKCS7="yes" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_WOLFSCEP" +fi +#if test "$ENABLED_SP_MATH" = "yes" && test "$ENABLED_KEYGEN" = "yes"; then +# AC_MSG_ERROR([Cannot use single precision math and key generation]) +#fi + +if test "x$ENABLED_PKCS7" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_PKCS7" + # Enable prereqs if not already enabled + if test "x$ENABLED_AESKEYWRAP" = "xno" + then + ENABLED_AESKEYWRAP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_KEYWRAP -DWOLFSSL_AES_DIRECT" + fi + if test "x$ENABLED_X963KDF" = "xno" && test "$ENABLED_ECC" = "yes" + then + ENABLED_X963KDF="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_X963_KDF" + fi +fi + +if test "x$ENABLED_DES3" = "xno" +then + AM_CFLAGS="$AM_CFLAGS -DNO_DES3" +else + # turn off DES3 if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DNO_DES3" + ENABLED_DES3=no + fi +fi + -# Update CFLAGS based on options if test "x$ENABLED_MAXSTRENGTH" = "xyes"; then : AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MAX_STRENGTH" fi @@ -21373,13 +22088,92 @@ if test "x$ENABLED_MAXSTRENGTH" = "xyes" && \ ENABLED_OLD_TLS=no fi +if test "x$ENABLED_MAXSTRENGTH" = "xyes" && \ + test "x$ENABLED_SSLV3" = "xyes"; then : + as_fn_error $? "Cannot use Max Strength and SSLv3 at the same time." "$LINENO" 5 +fi + +if test "x$ENABLED_SCTP" = "xyes"; then : + AM_CFLAGS="-DWOLFSSL_SCTP $AM_CFLAGS" +fi + +if test "x$ENABLED_MCAST" = "xyes"; then : + AM_CFLAGS="-DWOLFSSL_MULTICAST $AM_CFLAGS" +fi + +# WOLFSSL_AFALG does not support SHA224 yet +if (test "x$ENABLED_AFALG" = "xyes") && (test "x$ENABLED_SHA224" = "xyes"); then : + as_fn_error $? "--enable-sha224 with --enable-afalg not yet supported" "$LINENO" 5 +fi + +# WOLFSSL_DEVCRYPTO does not support SHA224 yet +if (test "x$ENABLED_DEVCRYPTO" = "xyes") && (test "x$ENABLED_SHA224" = "xyes"); then : + as_fn_error $? "--enable-sha224 with --enable-devcrypto not yet supported" "$LINENO" 5 +fi + +# SCTP and Multicast require DTLS +if (test "x$ENABLED_DTLS" = "xno") && \ + (test "x$ENABLED_SCTP" = "xyes" || test "x$ENABLED_MCAST" = "xyes"); then : + AM_CFLAGS="-DWOLFSSL_DTLS $AM_CFLAGS" + ENABLED_DTLS=yes +fi + +# Multicast requires the null cipher +if test "x$ENABLED_NULL_CIPHER" = "xno" && \ + test "x$ENABLED_MCAST" = "xyes"; then : + AM_CFLAGS="-DHAVE_NULL_CIPHER $AM_CFLAGS" + ENABLED_NULL_CIPHER=yes +fi + +# 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. +if test "x$ENABLED_WOLFSSH" = "xyes"; then : + if test "x$ENABLED_WPAS" = "xno"; then : + AM_CFLAGS="-DWOLFSSL_PUBLIC_MP $AM_CFLAGS" +fi + if test "x$ENABLED_AESGCM" = "xno"; then : + as_fn_error $? "cannot enable wolfSSH with AES-GCM disabled" "$LINENO" 5 +fi + if test "x$ENABLED_ECC" = "xno"; then : + as_fn_error $? "cannot enable wolfSSH with ECC disabled" "$LINENO" 5 +fi + if test "x$ENABLED_SHA" = "xno"; then : + as_fn_error $? "cannot enable wolfSSH with SHA-1 disabled" "$LINENO" 5 +fi + if test "x$ENABLED_SHA512" = "xno"; then : + as_fn_error $? "cannot enable wolfSSH with SHA-512/384 disabled" "$LINENO" 5 +fi + +fi + +if test "x$ENABLED_OPENSSLCOEXIST" = "xyes"; then + if test "x$ENABLED_OPENSSLALL" = "xyes"; then + as_fn_error $? "Cannot use --enable-opensslcoexist with --enable-opensslall" "$LINENO" 5 + fi + if test "x$ENABLED_OPENSSLEXTRA" = "xyes"; then + as_fn_error $? "Cannot use --enable-opensslcoexist with --enable-opensslextra" "$LINENO" 5 + fi +fi +################################################################################ + +# USER SETTINGS +if test "x$ENABLED_USERSETTINGS" = "xyes" +then + # Replace all options and just use WOLFSSL_USER_SETTINGS + AM_CFLAGS="-DWOLFSSL_USER_SETTINGS" +fi # OPTIMIZE FLAGS -if test "$GCC" = "yes" +# For distro disable custom build options that interfere with symbol generation +if test "$GCC" = "yes" && test "$ENABLED_DISTRO" = "no" then AM_CFLAGS="$AM_CFLAGS -Wall -Wno-unused" if test "$ax_enable_debug" = "no" then + if test "x$ENABLED_OPTFLAGS" = "xyes"; then : + if test "$ENABLED_FASTMATH" = "yes" then AM_CFLAGS="$AM_CFLAGS $OPTIMIZE_FAST_CFLAGS" @@ -21390,6 +22184,8 @@ then else AM_CFLAGS="$AM_CFLAGS $OPTIMIZE_CFLAGS" fi + +fi fi fi @@ -21399,6 +22195,12 @@ then AM_CFLAGS="$AM_CFLAGS -wd10006" fi +# Expose HAVE___UINT128_T to options flags" +if test "$ac_cv_type___uint128_t" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE___UINT128_T=1" +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 @@ -21571,7 +22373,7 @@ fi if test -d ".hg"; then : ac_cv_vcs_system="mercurial" fi - if test -d ".git"; then : + if test -e ".git"; then : ac_cv_vcs_system="git" fi @@ -21622,6 +22424,8 @@ fi + + AX_HARDEN_LIB= ax_append_compile_link_flags_extra= if test "x$ac_cv_vcs_checkout" = "xyes"; then : @@ -21656,7 +22460,7 @@ rm -f core conftest.err conftest.$ac_objext \ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Werror" >&5 $as_echo "$ax_cv_check_ldflags___Werror" >&6; } -if test x"$ax_cv_check_ldflags___Werror" = xyes; then : +if test "x$ax_cv_check_ldflags___Werror" = xyes; then : AX_HARDEN_LIB="-Werror $AX_HARDEN_LIB" @@ -21697,7 +22501,7 @@ rm -f core conftest.err conftest.$ac_objext \ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Werror" >&5 $as_echo "$ax_cv_check_ldflags___Werror" >&6; } -if test x"$ax_cv_check_ldflags___Werror" = xyes; then : +if test "x$ax_cv_check_ldflags___Werror" = xyes; then : ax_append_compile_link_flags_extra='-Werror' @@ -21740,7 +22544,7 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : AX_HARDEN_LIB="-z relro -z now $AX_HARDEN_LIB" @@ -21781,7 +22585,7 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : AX_HARDEN_LIB="-pie $AX_HARDEN_LIB" @@ -21792,62 +22596,7 @@ fi LIB="$LIB $AX_HARDEN_LIB" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts " >&5 -$as_echo_n "checking whether C compiler accepts ... " >&6; } -if ${ax_cv_check_cflags__+:} false; then : - $as_echo_n "(cached) " >&6 -else - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS " - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags__=yes -else - ax_cv_check_cflags__=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__" >&5 -$as_echo "$ax_cv_check_cflags__" >&6; } -if test x"$ax_cv_check_cflags__" = xyes; then : - : -else - : -fi - -if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains "; } >&5 - (: CFLAGS already contains ) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \""; } >&5 - (: CFLAGS="$CFLAGS ") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - CFLAGS="$CFLAGS " - ;; - esac -else - CFLAGS="" -fi @@ -21859,13 +22608,14 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu - CFLAGS= ac_cv_warnings_as_errors=no ax_append_compile_cflags_extra= if test "$ac_cv_vcs_checkout" = "yes"; then : + + for flag in -Werror; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags__$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -21898,27 +22648,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -21933,6 +22693,8 @@ else + + for flag in -Werror; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags__$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -21965,27 +22727,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${ax_append_compile_cflags_extra+:} false; then : - case " $ax_append_compile_cflags_extra " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : ax_append_compile_cflags_extra already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${ax_append_compile_cflags_extra+:} false; then : + + case " $ax_append_compile_cflags_extra " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : ax_append_compile_cflags_extra already contains \$flag"; } >&5 (: ax_append_compile_cflags_extra already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : ax_append_compile_cflags_extra=\"\$ax_append_compile_cflags_extra \$flag\""; } >&5 - (: ax_append_compile_cflags_extra="$ax_append_compile_cflags_extra $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append ax_append_compile_cflags_extra " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : ax_append_compile_cflags_extra=\"\$ax_append_compile_cflags_extra\""; } >&5 + (: ax_append_compile_cflags_extra="$ax_append_compile_cflags_extra") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - ax_append_compile_cflags_extra="$ax_append_compile_cflags_extra $flag" - ;; - esac + ;; +esac + else - ax_append_compile_cflags_extra="$flag" + + ax_append_compile_cflags_extra=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : ax_append_compile_cflags_extra=\"\$ax_append_compile_cflags_extra\""; } >&5 + (: ax_append_compile_cflags_extra="$ax_append_compile_cflags_extra") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22001,6 +22773,8 @@ fi + + for flag in -g; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags__$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22033,27 +22807,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22064,6 +22848,8 @@ done + + for flag in -ggdb; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22096,27 +22882,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22127,6 +22923,8 @@ done + + for flag in -O0; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22159,27 +22957,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22193,6 +23001,8 @@ fi + + for flag in -Wno-pragmas; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22225,27 +23035,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22257,6 +23077,8 @@ done + + for flag in -Wall; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22289,27 +23111,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22320,6 +23152,8 @@ done + + for flag in -Wno-strict-aliasing; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22352,27 +23186,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22383,6 +23227,8 @@ done + + for flag in -Wextra; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22415,27 +23261,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22446,6 +23302,8 @@ done + + for flag in -Wunknown-pragmas; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22478,27 +23336,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22509,6 +23377,8 @@ done + + for flag in -Wthis-test-should-fail; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22541,27 +23411,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22576,6 +23456,8 @@ else + + for flag in --param=ssp-buffer-size=1; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22608,27 +23490,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22641,6 +23533,8 @@ done fi + + for flag in -Waddress; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22673,27 +23567,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22704,6 +23608,8 @@ done + + for flag in -Warray-bounds; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22736,27 +23642,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22767,6 +23683,8 @@ done + + for flag in -Wbad-function-cast; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22799,27 +23717,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22830,6 +23758,8 @@ done + + for flag in -Wchar-subscripts; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22862,27 +23792,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22893,6 +23833,8 @@ done + + for flag in -Wcomment; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22925,27 +23867,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -22956,6 +23908,8 @@ done + + for flag in -Wfloat-equal; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -22988,27 +23942,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23019,6 +23983,8 @@ done + + for flag in -Wformat-security; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23051,27 +24017,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23082,6 +24058,8 @@ done + + for flag in -Wformat=2; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23114,27 +24092,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23145,6 +24133,8 @@ done + + for flag in -Wmaybe-uninitialized; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23177,27 +24167,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23208,6 +24208,8 @@ done + + for flag in -Wmissing-field-initializers; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23240,27 +24242,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23271,6 +24283,8 @@ done + + for flag in -Wmissing-noreturn; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23303,27 +24317,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23334,6 +24358,8 @@ done + + for flag in -Wmissing-prototypes; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23366,27 +24392,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23397,6 +24433,8 @@ done + + for flag in -Wnested-externs; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23429,27 +24467,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23460,6 +24508,8 @@ done + + for flag in -Wnormalized=id; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23492,27 +24542,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23523,6 +24583,8 @@ done + + for flag in -Woverride-init; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23555,27 +24617,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23586,6 +24658,8 @@ done + + for flag in -Wpointer-arith; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23618,27 +24692,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23649,6 +24733,8 @@ done + + for flag in -Wpointer-sign; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23681,27 +24767,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23712,6 +24808,8 @@ done + + for flag in -Wredundant-decls; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23744,27 +24842,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23775,6 +24883,8 @@ done + + for flag in -Wshadow; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23807,27 +24917,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23838,6 +24958,8 @@ done + + for flag in -Wshorten-64-to-32; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23870,27 +24992,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23901,6 +25033,8 @@ done + + for flag in -Wsign-compare; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23933,27 +25067,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -23964,6 +25108,8 @@ done + + for flag in -Wstrict-overflow=1; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -23996,27 +25142,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -24027,6 +25183,8 @@ done + + for flag in -Wstrict-prototypes; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -24059,27 +25217,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -24090,6 +25258,8 @@ done + + for flag in -Wswitch-enum; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -24122,27 +25292,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -24153,6 +25333,8 @@ done + + for flag in -Wundef; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -24185,27 +25367,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -24216,6 +25408,8 @@ done + + for flag in -Wunused; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -24248,27 +25442,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -24279,6 +25483,8 @@ done + + for flag in -Wunused-result; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -24311,27 +25517,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -24342,6 +25558,8 @@ done + + for flag in -Wunused-variable; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -24374,27 +25592,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -24405,6 +25633,8 @@ done + + for flag in -Wwrite-strings; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -24437,27 +25667,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac + ;; +esac + else - CFLAGS="$flag" + + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + fi else @@ -24468,6 +25708,8 @@ done + + for flag in -fwrapv; do as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 @@ -24500,90 +25742,37 @@ fi eval ac_res=\$$as_CACHEVAR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 +if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then : + +if ${CFLAGS+:} false; then : + + case " $CFLAGS " in #( + *" $flag "*) : + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 (: CFLAGS already contains $flag) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 + test $ac_status = 0; } ;; #( + *) : + + as_fn_append CFLAGS " $flag" + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac -else - CFLAGS="$flag" -fi + ;; +esac else - : -fi -done - - - -for flag in -fPIE; do - as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ax_append_compile_cflags_extra_$flag" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 -$as_echo_n "checking whether C compiler accepts $flag... " >&6; } -if eval \${$as_CACHEVAR+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS $ax_append_compile_cflags_extra $flag" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$as_CACHEVAR=yes" -else - eval "$as_CACHEVAR=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -eval ac_res=\$$as_CACHEVAR - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then : - if ${CFLAGS+:} false; then : - case " $CFLAGS " in - *" $flag "*) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$flag"; } >&5 - (: CFLAGS already contains $flag) 2>&5 + CFLAGS=$flag + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5 + (: CFLAGS="$CFLAGS") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - ;; - *) - { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$flag\""; } >&5 - (: CFLAGS="$CFLAGS $flag") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - CFLAGS="$CFLAGS $flag" - ;; - esac -else - CFLAGS="$flag" + fi else @@ -24600,15 +25789,939 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu -# link to ws2_32 if on mingw +# if mingw then link to ws2_32 for sockets case $host_os in - *mingw32) - LDFLAGS="$LDFLAGS -lws2_32" ;; + mingw*) + LDFLAGS="$LDFLAGS -lws2_32" + if test "$enable_shared" = "yes" + then + +$as_echo "#define WOLFSSL_DLL 1" >>confdefs.h + + if test "$enable_static" = "yes" + then + MINGW_LIB_WARNING="yes" + fi + fi ;; esac -# add user C_EXTRA_FLAGS back -CFLAGS="$CFLAGS $USER_C_EXTRA_FLAGS" -OPTION_FLAGS="$USER_C_EXTRA_FLAGS $AM_CFLAGS" + +# The following AM_CONDITIONAL statements set flags for use in the Makefiles. +# Some of these affect build targets and objects, some trigger different +# test scripts for make check. + if test "x$ENABLED_DISTRO" = "xyes"; then + BUILD_DISTRO_TRUE= + BUILD_DISTRO_FALSE='#' +else + BUILD_DISTRO_TRUE='#' + BUILD_DISTRO_FALSE= +fi + + if test "x$ENABLED_ALL" = "xyes"; then + BUILD_ALL_TRUE= + BUILD_ALL_FALSE='#' +else + BUILD_ALL_TRUE='#' + BUILD_ALL_FALSE= +fi + + if test "x$ENABLED_TLS13" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_TLS13_TRUE= + BUILD_TLS13_FALSE='#' +else + BUILD_TLS13_TRUE='#' + BUILD_TLS13_FALSE= +fi + + if test "x$ENABLED_RNG" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_RNG_TRUE= + BUILD_RNG_FALSE='#' +else + BUILD_RNG_TRUE='#' + BUILD_RNG_FALSE= +fi + + if test "x$ENABLED_SCTP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SCTP_TRUE= + BUILD_SCTP_FALSE='#' +else + BUILD_SCTP_TRUE='#' + BUILD_SCTP_FALSE= +fi + + if test "x$ENABLED_MCAST" = "xyes"; then + BUILD_MCAST_TRUE= + BUILD_MCAST_FALSE='#' +else + BUILD_MCAST_TRUE='#' + BUILD_MCAST_FALSE= +fi + + if test "x$ENABLED_IPV6" = "xyes"; then + BUILD_IPV6_TRUE= + BUILD_IPV6_FALSE='#' +else + BUILD_IPV6_TRUE='#' + BUILD_IPV6_FALSE= +fi + + if test "x$ENABLED_LEANPSK" = "xyes"; then + BUILD_LEANPSK_TRUE= + BUILD_LEANPSK_FALSE='#' +else + BUILD_LEANPSK_TRUE='#' + BUILD_LEANPSK_FALSE= +fi + + if test "x$ENABLED_LEANTLS" = "xyes"; then + BUILD_LEANTLS_TRUE= + BUILD_LEANTLS_FALSE='#' +else + BUILD_LEANTLS_TRUE='#' + BUILD_LEANTLS_FALSE= +fi + + if test "x$ENABLED_LOWRESOURCE" = "xyes"; then + BUILD_LOWMEM_TRUE= + BUILD_LOWMEM_FALSE='#' +else + BUILD_LOWMEM_TRUE='#' + BUILD_LOWMEM_FALSE= +fi + + if test "x$ENABLED_PKCALLBACKS" = "xyes"; then + BUILD_PKCALLBACKS_TRUE= + BUILD_PKCALLBACKS_FALSE='#' +else + BUILD_PKCALLBACKS_TRUE='#' + BUILD_PKCALLBACKS_FALSE= +fi + + if test "x$ENABLED_CRYPTOAUTHLIB" = "xyes"; then + BUILD_CRYPTOAUTHLIB_TRUE= + BUILD_CRYPTOAUTHLIB_FALSE='#' +else + BUILD_CRYPTOAUTHLIB_TRUE='#' + BUILD_CRYPTOAUTHLIB_FALSE= +fi + + if test "x$ENABLED_SNIFFER" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SNIFFER_TRUE= + BUILD_SNIFFER_FALSE='#' +else + BUILD_SNIFFER_TRUE='#' + BUILD_SNIFFER_FALSE= +fi + + if test "x$ENABLED_SNIFFTEST" = "xyes"; then + BUILD_SNIFFTEST_TRUE= + BUILD_SNIFFTEST_FALSE='#' +else + BUILD_SNIFFTEST_TRUE='#' + BUILD_SNIFFTEST_FALSE= +fi + + if test "x$ENABLED_AESGCM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_AESGCM_TRUE= + BUILD_AESGCM_FALSE='#' +else + BUILD_AESGCM_TRUE='#' + BUILD_AESGCM_FALSE= +fi + + if test "x$ENABLED_AESCCM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_AESCCM_TRUE= + BUILD_AESCCM_FALSE='#' +else + BUILD_AESCCM_TRUE='#' + BUILD_AESCCM_FALSE= +fi + + if test "x$ENABLED_ARMASM" = "xyes"; then + BUILD_ARMASM_TRUE= + BUILD_ARMASM_FALSE='#' +else + BUILD_ARMASM_TRUE='#' + BUILD_ARMASM_FALSE= +fi + + if test "x$ENABLED_XILINX" = "xyes"; then + BUILD_XILINX_TRUE= + BUILD_XILINX_FALSE='#' +else + BUILD_XILINX_TRUE='#' + BUILD_XILINX_FALSE= +fi + + if test "x$ENABLED_AESNI" = "xyes"; then + BUILD_AESNI_TRUE= + BUILD_AESNI_FALSE='#' +else + BUILD_AESNI_TRUE='#' + BUILD_AESNI_FALSE= +fi + + if test "x$ENABLED_INTELASM" = "xyes"; then + BUILD_INTELASM_TRUE= + BUILD_INTELASM_FALSE='#' +else + BUILD_INTELASM_TRUE='#' + BUILD_INTELASM_FALSE= +fi + + if test "x$ENABLED_AFALG" = "xyes"; then + BUILD_AFALG_TRUE= + BUILD_AFALG_FALSE='#' +else + BUILD_AFALG_TRUE='#' + BUILD_AFALG_FALSE= +fi + + if test "x$ENABLED_DEVCRYPTO" = "xyes"; then + BUILD_DEVCRYPTO_TRUE= + BUILD_DEVCRYPTO_FALSE='#' +else + BUILD_DEVCRYPTO_TRUE='#' + BUILD_DEVCRYPTO_FALSE= +fi + + if test "x$ENABLED_CAMELLIA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_CAMELLIA_TRUE= + BUILD_CAMELLIA_FALSE='#' +else + BUILD_CAMELLIA_TRUE='#' + BUILD_CAMELLIA_FALSE= +fi + + if test "x$ENABLED_MD2" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_MD2_TRUE= + BUILD_MD2_FALSE='#' +else + BUILD_MD2_TRUE='#' + BUILD_MD2_FALSE= +fi + + if test "x$ENABLED_RIPEMD" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_RIPEMD_TRUE= + BUILD_RIPEMD_FALSE='#' +else + BUILD_RIPEMD_TRUE='#' + BUILD_RIPEMD_FALSE= +fi + + if test "x$ENABLED_BLAKE2" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_BLAKE2_TRUE= + BUILD_BLAKE2_FALSE='#' +else + BUILD_BLAKE2_TRUE='#' + BUILD_BLAKE2_FALSE= +fi + + if test "x$ENABLED_BLAKE2S" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_BLAKE2S_TRUE= + BUILD_BLAKE2S_FALSE='#' +else + BUILD_BLAKE2S_TRUE='#' + BUILD_BLAKE2S_FALSE= +fi + + if test "x$ENABLED_SHA512" = "xyes" || test "x$ENABLED_SHA384" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SHA512_TRUE= + BUILD_SHA512_FALSE='#' +else + BUILD_SHA512_TRUE='#' + BUILD_SHA512_FALSE= +fi + + if test "x$ENABLED_DSA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_DSA_TRUE= + BUILD_DSA_FALSE='#' +else + BUILD_DSA_TRUE='#' + BUILD_DSA_FALSE= +fi + + if test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_ECC_TRUE= + BUILD_ECC_FALSE='#' +else + BUILD_ECC_TRUE='#' + BUILD_ECC_FALSE= +fi + + if test "x$ENABLED_ED25519" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_ED25519_TRUE= + BUILD_ED25519_FALSE='#' +else + BUILD_ED25519_TRUE='#' + BUILD_ED25519_FALSE= +fi + + if test "x$ENABLED_ED25519_SMALL" = "xyes"; then + BUILD_ED25519_SMALL_TRUE= + BUILD_ED25519_SMALL_FALSE='#' +else + BUILD_ED25519_SMALL_TRUE='#' + BUILD_ED25519_SMALL_FALSE= +fi + + if test "x$ENABLED_FEMATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_FEMATH_TRUE= + BUILD_FEMATH_FALSE='#' +else + BUILD_FEMATH_TRUE='#' + BUILD_FEMATH_FALSE= +fi + + if test "x$ENABLED_GEMATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_GEMATH_TRUE= + BUILD_GEMATH_FALSE='#' +else + BUILD_GEMATH_TRUE='#' + BUILD_GEMATH_FALSE= +fi + + if test "x$ENABLED_CURVE25519" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_CURVE25519_TRUE= + BUILD_CURVE25519_FALSE='#' +else + BUILD_CURVE25519_TRUE='#' + BUILD_CURVE25519_FALSE= +fi + + if test "x$ENABLED_CURVE25519_SMALL" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_CURVE25519_SMALL_TRUE= + BUILD_CURVE25519_SMALL_FALSE='#' +else + BUILD_CURVE25519_SMALL_TRUE='#' + BUILD_CURVE25519_SMALL_FALSE= +fi + + if test "x$ENABLED_ED448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_ED448_TRUE= + BUILD_ED448_FALSE='#' +else + BUILD_ED448_TRUE='#' + BUILD_ED448_FALSE= +fi + + if test "x$ENABLED_ED448_SMALL" = "xyes"; then + BUILD_ED448_SMALL_TRUE= + BUILD_ED448_SMALL_FALSE='#' +else + BUILD_ED448_SMALL_TRUE='#' + BUILD_ED448_SMALL_FALSE= +fi + + if test "x$ENABLED_FE448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_FE448_TRUE= + BUILD_FE448_FALSE='#' +else + BUILD_FE448_TRUE='#' + BUILD_FE448_FALSE= +fi + + if test "x$ENABLED_GE448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_GE448_TRUE= + BUILD_GE448_FALSE='#' +else + BUILD_GE448_TRUE='#' + BUILD_GE448_FALSE= +fi + + if test "x$ENABLED_CURVE448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_CURVE448_TRUE= + BUILD_CURVE448_FALSE='#' +else + BUILD_CURVE448_TRUE='#' + BUILD_CURVE448_FALSE= +fi + + if test "x$ENABLED_CURVE448_SMALL" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_CURVE448_SMALL_TRUE= + BUILD_CURVE448_SMALL_FALSE='#' +else + BUILD_CURVE448_SMALL_TRUE='#' + BUILD_CURVE448_SMALL_FALSE= +fi + + if test "x$ENABLED_MEMORY" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_MEMORY_TRUE= + BUILD_MEMORY_FALSE='#' +else + BUILD_MEMORY_TRUE='#' + BUILD_MEMORY_FALSE= +fi + + if test "x$ENABLED_RSA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_RSA_TRUE= + BUILD_RSA_FALSE='#' +else + BUILD_RSA_TRUE='#' + BUILD_RSA_FALSE= +fi + + if test "x$ENABLED_DH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_DH_TRUE= + BUILD_DH_FALSE='#' +else + BUILD_DH_TRUE='#' + BUILD_DH_FALSE= +fi + + if test "x$ENABLED_ASN" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_ASN_TRUE= + BUILD_ASN_FALSE='#' +else + BUILD_ASN_TRUE='#' + BUILD_ASN_FALSE= +fi + + if test "x$ENABLED_AES" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_AES_TRUE= + BUILD_AES_FALSE='#' +else + BUILD_AES_TRUE='#' + BUILD_AES_FALSE= +fi + + if test "x$ENABLED_CODING" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_CODING_TRUE= + BUILD_CODING_FALSE='#' +else + BUILD_CODING_TRUE='#' + BUILD_CODING_FALSE= +fi + + if test "x$ENABLED_IDEA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_IDEA_TRUE= + BUILD_IDEA_FALSE='#' +else + BUILD_IDEA_TRUE='#' + BUILD_IDEA_FALSE= +fi + + if test "x$ENABLED_ARC4" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_RC4_TRUE= + BUILD_RC4_FALSE='#' +else + BUILD_RC4_TRUE='#' + BUILD_RC4_FALSE= +fi + + if test "x$ENABLED_MD5" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_MD5_TRUE= + BUILD_MD5_FALSE='#' +else + BUILD_MD5_TRUE='#' + BUILD_MD5_FALSE= +fi + + if test "x$ENABLED_SHA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SHA_TRUE= + BUILD_SHA_FALSE='#' +else + BUILD_SHA_TRUE='#' + BUILD_SHA_FALSE= +fi + + if test "x$ENABLED_HC128" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_HC128_TRUE= + BUILD_HC128_FALSE='#' +else + BUILD_HC128_TRUE='#' + BUILD_HC128_FALSE= +fi + + if test "x$ENABLED_RABBIT" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_RABBIT_TRUE= + BUILD_RABBIT_FALSE='#' +else + BUILD_RABBIT_TRUE='#' + BUILD_RABBIT_FALSE= +fi + + if test "x$ENABLED_FIPS" = "xyes"; then + BUILD_FIPS_TRUE= + BUILD_FIPS_FALSE='#' +else + BUILD_FIPS_TRUE='#' + BUILD_FIPS_FALSE= +fi + + if test "x$FIPS_VERSION" = "xv1"; then + BUILD_FIPS_V1_TRUE= + BUILD_FIPS_V1_FALSE='#' +else + BUILD_FIPS_V1_TRUE='#' + BUILD_FIPS_V1_FALSE= +fi + + if test "x$FIPS_VERSION" = "xv2"; then + BUILD_FIPS_V2_TRUE= + BUILD_FIPS_V2_FALSE='#' +else + BUILD_FIPS_V2_TRUE='#' + BUILD_FIPS_V2_FALSE= +fi + + if test "x$FIPS_VERSION" = "xrand"; then + BUILD_FIPS_RAND_TRUE= + BUILD_FIPS_RAND_FALSE='#' +else + BUILD_FIPS_RAND_TRUE='#' + BUILD_FIPS_RAND_FALSE= +fi + + if test "x$ENABLED_CMAC" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_CMAC_TRUE= + BUILD_CMAC_FALSE='#' +else + BUILD_CMAC_TRUE='#' + BUILD_CMAC_FALSE= +fi + + if test "x$ENABLED_SELFTEST" = "xyes"; then + BUILD_SELFTEST_TRUE= + BUILD_SELFTEST_FALSE='#' +else + BUILD_SELFTEST_TRUE='#' + BUILD_SELFTEST_FALSE= +fi + + if test "x$ENABLED_SHA224" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SHA224_TRUE= + BUILD_SHA224_FALSE='#' +else + BUILD_SHA224_TRUE='#' + BUILD_SHA224_FALSE= +fi + + if test "x$ENABLED_SHA3" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SHA3_TRUE= + BUILD_SHA3_FALSE='#' +else + BUILD_SHA3_TRUE='#' + BUILD_SHA3_FALSE= +fi + + if test "x$ENABLED_POLY1305" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_POLY1305_TRUE= + BUILD_POLY1305_FALSE='#' +else + BUILD_POLY1305_TRUE='#' + BUILD_POLY1305_FALSE= +fi + + if test "x$ENABLED_CHACHA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_CHACHA_TRUE= + BUILD_CHACHA_FALSE='#' +else + BUILD_CHACHA_TRUE='#' + BUILD_CHACHA_FALSE= +fi + + if test "x$ENABLED_INLINE" = "xyes"; then + BUILD_INLINE_TRUE= + BUILD_INLINE_FALSE='#' +else + BUILD_INLINE_TRUE='#' + BUILD_INLINE_FALSE= +fi + + if test "x$ENABLED_OCSP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_OCSP_TRUE= + BUILD_OCSP_FALSE='#' +else + BUILD_OCSP_TRUE='#' + BUILD_OCSP_FALSE= +fi + + if test "x$ENABLED_CERTIFICATE_STATUS_REQUEST" = "xyes"; then + BUILD_OCSP_STAPLING_TRUE= + BUILD_OCSP_STAPLING_FALSE='#' +else + BUILD_OCSP_STAPLING_TRUE='#' + BUILD_OCSP_STAPLING_FALSE= +fi + + if test "x$ENABLED_CERTIFICATE_STATUS_REQUEST_V2" = "xyes"; then + BUILD_OCSP_STAPLING_V2_TRUE= + BUILD_OCSP_STAPLING_V2_FALSE='#' +else + BUILD_OCSP_STAPLING_V2_TRUE='#' + BUILD_OCSP_STAPLING_V2_FALSE= +fi + + if test "x$ENABLED_CRL" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_CRL_TRUE= + BUILD_CRL_FALSE='#' +else + BUILD_CRL_TRUE='#' + BUILD_CRL_FALSE= +fi + + if test "x$ENABLED_CRL_MONITOR" = "xyes"; then + BUILD_CRL_MONITOR_TRUE= + BUILD_CRL_MONITOR_FALSE='#' +else + BUILD_CRL_MONITOR_TRUE='#' + BUILD_CRL_MONITOR_FALSE= +fi + + if test "x$ENABLED_USER_RSA" = "xyes" ; then + BUILD_USER_RSA_TRUE= + BUILD_USER_RSA_FALSE='#' +else + BUILD_USER_RSA_TRUE='#' + BUILD_USER_RSA_FALSE= +fi + + if test "x$ENABLED_USER_CRYPTO" = "xyes"; then + BUILD_USER_CRYPTO_TRUE= + BUILD_USER_CRYPTO_FALSE='#' +else + BUILD_USER_CRYPTO_TRUE='#' + BUILD_USER_CRYPTO_FALSE= +fi + + if test "x$ENABLED_NTRU" = "xyes"; then + BUILD_NTRU_TRUE= + BUILD_NTRU_FALSE='#' +else + BUILD_NTRU_TRUE='#' + BUILD_NTRU_FALSE= +fi + + if test "x$ENABLED_WNR" = "xyes"; then + BUILD_WNR_TRUE= + BUILD_WNR_FALSE='#' +else + BUILD_WNR_TRUE='#' + BUILD_WNR_FALSE= +fi + + if test "x$ENABLED_SRP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SRP_TRUE= + BUILD_SRP_FALSE='#' +else + BUILD_SRP_TRUE='#' + BUILD_SRP_FALSE= +fi + + if test "x$ENABLED_VALGRIND" = "xyes"; then + USE_VALGRIND_TRUE= + USE_VALGRIND_FALSE='#' +else + USE_VALGRIND_TRUE='#' + USE_VALGRIND_FALSE= +fi + + if test "x$ENABLED_MD4" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_MD4_TRUE= + BUILD_MD4_FALSE='#' +else + BUILD_MD4_TRUE='#' + BUILD_MD4_FALSE= +fi + + if test "x$ENABLED_PWDBASED" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_PWDBASED_TRUE= + BUILD_PWDBASED_FALSE='#' +else + BUILD_PWDBASED_TRUE='#' + BUILD_PWDBASED_FALSE= +fi + + if test "x$ENABLED_SCRYPT" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SCRYPT_TRUE= + BUILD_SCRYPT_FALSE='#' +else + BUILD_SCRYPT_TRUE='#' + BUILD_SCRYPT_FALSE= +fi + + if test "x$ENABLED_CRYPTONLY" = "xyes" && test "x$ENABLED_OPENSSLEXTRA" = "xno"; then + BUILD_CRYPTONLY_TRUE= + BUILD_CRYPTONLY_FALSE='#' +else + BUILD_CRYPTONLY_TRUE='#' + BUILD_CRYPTONLY_FALSE= +fi + + if test "x$ENABLED_FASTMATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_FASTMATH_TRUE= + BUILD_FASTMATH_FALSE='#' +else + BUILD_FASTMATH_TRUE='#' + BUILD_FASTMATH_FALSE= +fi + + if test "x$ENABLED_SLOWMATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SLOWMATH_TRUE= + BUILD_SLOWMATH_FALSE='#' +else + BUILD_SLOWMATH_TRUE='#' + BUILD_SLOWMATH_FALSE= +fi + + if test "x$ENABLED_EXAMPLES" = "xyes" && test "x$ENABLED_LEANTLS" = "xno"; then + BUILD_EXAMPLE_SERVERS_TRUE= + BUILD_EXAMPLE_SERVERS_FALSE='#' +else + BUILD_EXAMPLE_SERVERS_TRUE='#' + BUILD_EXAMPLE_SERVERS_FALSE= +fi + + if test "x$ENABLED_EXAMPLES" = "xyes"; then + BUILD_EXAMPLE_CLIENTS_TRUE= + BUILD_EXAMPLE_CLIENTS_FALSE='#' +else + BUILD_EXAMPLE_CLIENTS_TRUE='#' + BUILD_EXAMPLE_CLIENTS_FALSE= +fi + + if test "x$ENABLED_EXAMPLES" = "xyes" && test "x$ENABLED_LEANTLS" = "xno"; then + BUILD_TESTS_TRUE= + BUILD_TESTS_FALSE='#' +else + BUILD_TESTS_TRUE='#' + BUILD_TESTS_FALSE= +fi + + if test "x$ENABLED_SINGLETHREADED" = "xno" && test "x$ENABLED_EXAMPLES" = "xyes" && test "x$ENABLED_LEANTLS" = "xno"; then + BUILD_THREADED_EXAMPLES_TRUE= + BUILD_THREADED_EXAMPLES_FALSE='#' +else + BUILD_THREADED_EXAMPLES_TRUE='#' + BUILD_THREADED_EXAMPLES_FALSE= +fi + + if test "x$ENABLED_CRYPT_TESTS" = "xyes"; then + BUILD_WOLFCRYPT_TESTS_TRUE= + BUILD_WOLFCRYPT_TESTS_FALSE='#' +else + BUILD_WOLFCRYPT_TESTS_TRUE='#' + BUILD_WOLFCRYPT_TESTS_FALSE= +fi + + if test "x$ENABLED_LIBZ" = "xyes"; then + BUILD_LIBZ_TRUE= + BUILD_LIBZ_FALSE='#' +else + BUILD_LIBZ_TRUE='#' + BUILD_LIBZ_FALSE= +fi + + if test "x$ENABLED_PKCS11" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_PKCS11_TRUE= + BUILD_PKCS11_FALSE='#' +else + BUILD_PKCS11_TRUE='#' + BUILD_PKCS11_FALSE= +fi + + if test "x$ENABLED_PKCS12" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_PKCS12_TRUE= + BUILD_PKCS12_FALSE='#' +else + BUILD_PKCS12_TRUE='#' + BUILD_PKCS12_FALSE= +fi + + if test "x$ENABLED_CAVIUM" = "xyes"; then + BUILD_CAVIUM_TRUE= + BUILD_CAVIUM_FALSE='#' +else + BUILD_CAVIUM_TRUE='#' + BUILD_CAVIUM_FALSE= +fi + + if test "x$ENABLED_CAVIUM_V" = "xyes"; then + BUILD_CAVIUM_V_TRUE= + BUILD_CAVIUM_V_FALSE='#' +else + BUILD_CAVIUM_V_TRUE='#' + BUILD_CAVIUM_V_FALSE= +fi + + if test "x$ENABLED_OCTEON_SYNC" = "xyes"; then + BUILD_OCTEON_SYNC_TRUE= + BUILD_OCTEON_SYNC_FALSE='#' +else + BUILD_OCTEON_SYNC_TRUE='#' + BUILD_OCTEON_SYNC_FALSE= +fi + + if test "x$ENABLED_INTEL_QA" = "xyes"; then + BUILD_INTEL_QA_TRUE= + BUILD_INTEL_QA_FALSE='#' +else + BUILD_INTEL_QA_TRUE='#' + BUILD_INTEL_QA_FALSE= +fi + + if test "x$ENABLED_INTEL_QA_SYNC" = "xyes"; then + BUILD_INTEL_QA_SYNC_TRUE= + BUILD_INTEL_QA_SYNC_FALSE='#' +else + BUILD_INTEL_QA_SYNC_TRUE='#' + BUILD_INTEL_QA_SYNC_FALSE= +fi + + if test "x$ENABLED_SP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SP_TRUE= + BUILD_SP_FALSE='#' +else + BUILD_SP_TRUE='#' + BUILD_SP_FALSE= +fi + + if (test "x$ENABLED_SP" = "xyes" && test "x$ENABLED_SP_ASM" = "xno") || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SP_C_TRUE= + BUILD_SP_C_FALSE='#' +else + BUILD_SP_C_TRUE='#' + BUILD_SP_C_FALSE= +fi + + if test "x$ENABLED_SP_ARM64_ASM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SP_ARM64_TRUE= + BUILD_SP_ARM64_FALSE='#' +else + BUILD_SP_ARM64_TRUE='#' + BUILD_SP_ARM64_FALSE= +fi + + if test "x$ENABLED_SP_ARM32_ASM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SP_ARM32_TRUE= + BUILD_SP_ARM32_FALSE='#' +else + BUILD_SP_ARM32_TRUE='#' + BUILD_SP_ARM32_FALSE= +fi + + if test "x$ENABLED_SP_ARM_THUMB_ASM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SP_ARM_THUMB_TRUE= + BUILD_SP_ARM_THUMB_FALSE='#' +else + BUILD_SP_ARM_THUMB_TRUE='#' + BUILD_SP_ARM_THUMB_FALSE= +fi + + if test "x$ENABLED_SP_ARM_CORTEX_ASM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SP_ARM_CORTEX_TRUE= + BUILD_SP_ARM_CORTEX_FALSE='#' +else + BUILD_SP_ARM_CORTEX_TRUE='#' + BUILD_SP_ARM_CORTEX_FALSE= +fi + + if test "x$ENABLED_SP_X86_64_ASM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SP_X86_64_TRUE= + BUILD_SP_X86_64_FALSE='#' +else + BUILD_SP_X86_64_TRUE='#' + BUILD_SP_X86_64_FALSE= +fi + + if test "x$ENABLED_SP_MATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_SP_INT_TRUE= + BUILD_SP_INT_FALSE='#' +else + BUILD_SP_INT_TRUE='#' + BUILD_SP_INT_FALSE= +fi + + if test "x$ENABLED_FAST_RSA" = "xyes"; then + BUILD_FAST_RSA_TRUE= + BUILD_FAST_RSA_FALSE='#' +else + BUILD_FAST_RSA_TRUE='#' + BUILD_FAST_RSA_FALSE= +fi + + if test "x$ENABLED_MCAPI" = "xyes"; then + BUILD_MCAPI_TRUE= + BUILD_MCAPI_FALSE='#' +else + BUILD_MCAPI_TRUE='#' + BUILD_MCAPI_FALSE= +fi + + if test "x$ENABLED_ASYNCCRYPT" = "xyes"; then + BUILD_ASYNCCRYPT_TRUE= + BUILD_ASYNCCRYPT_FALSE='#' +else + BUILD_ASYNCCRYPT_TRUE='#' + BUILD_ASYNCCRYPT_FALSE= +fi + + if test "x$ENABLED_ASYNCCRYPT" = "xyes"; then + BUILD_WOLFEVENT_TRUE= + BUILD_WOLFEVENT_FALSE='#' +else + BUILD_WOLFEVENT_TRUE='#' + BUILD_WOLFEVENT_FALSE= +fi + + if test "x$ENABLED_CRYPTOCB" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_CRYPTOCB_TRUE= + BUILD_CRYPTOCB_FALSE='#' +else + BUILD_CRYPTOCB_TRUE='#' + BUILD_CRYPTOCB_FALSE= +fi + + if test "x$ENABLED_PSK" = "xyes"; then + BUILD_PSK_TRUE= + BUILD_PSK_FALSE='#' +else + BUILD_PSK_TRUE='#' + BUILD_PSK_FALSE= +fi + + if test "x$ENABLED_TRUSTED_PEER_CERT" = "xyes"; then + BUILD_TRUST_PEER_CERT_TRUE= + BUILD_TRUST_PEER_CERT_FALSE='#' +else + BUILD_TRUST_PEER_CERT_TRUE='#' + BUILD_TRUST_PEER_CERT_FALSE= +fi + + if test "x$ENABLED_PKI" = "xyes"; then + BUILD_PKI_TRUE= + BUILD_PKI_FALSE='#' +else + BUILD_PKI_TRUE='#' + BUILD_PKI_FALSE= +fi + + if test "x$ENABLED_DES3" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_DES3_TRUE= + BUILD_DES3_FALSE='#' +else + BUILD_DES3_TRUE='#' + BUILD_DES3_FALSE= +fi + + if test "x$ENABLED_PKCS7" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"; then + BUILD_PKCS7_TRUE= + BUILD_PKCS7_FALSE='#' +else + BUILD_PKCS7_TRUE='#' + BUILD_PKCS7_FALSE= +fi + + if test "x$ENABLED_HASHFLAGS" = "xyes"; then + BUILD_HASHFLAGS_TRUE= + BUILD_HASHFLAGS_FALSE='#' +else + BUILD_HASHFLAGS_TRUE='#' + BUILD_HASHFLAGS_FALSE= +fi + + @@ -24620,24 +26733,13 @@ OPTION_FLAGS="$USER_C_EXTRA_FLAGS $AM_CFLAGS" + + + # FINAL ac_config_files="$ac_config_files stamp-h" -ac_config_files="$ac_config_files Makefile" - -ac_config_files="$ac_config_files wolfssl/version.h" - -ac_config_files="$ac_config_files wolfssl/options.h" - -#have options.h and version.h for autoconf fips tag and build -#if test "x$ENABLED_FIPS" = "xyes" -#then -# AC_CONFIG_FILES([cyassl/version.h]) -# AC_CONFIG_FILES([cyassl/options.h]) -#fi -ac_config_files="$ac_config_files support/wolfssl.pc" - -ac_config_files="$ac_config_files rpm/spec" +ac_config_files="$ac_config_files Makefile wolfssl/version.h wolfssl/options.h cyassl/options.h support/wolfssl.pc rpm/spec" # create a generic PACKAGE-config file @@ -24657,7 +26759,7 @@ echo 'package="'$P'"' >>$F echo 'version="'$V'"' >>$F echo 'libs="'$L'"' >>$F echo ' ' >>$F -# in the order of occurence a standard automake Makefile +# in the order of occurrence a standard automake Makefile echo 'prefix="'$prefix'"' >>$F echo 'exec_prefix="'$exec_prefix'"' >>$F echo 'bindir="'$bindir'"' >>$F @@ -24772,57 +26874,98 @@ echo 'fi' >>$F GENERIC_CONFIG="$F" - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking the number of available CPUs" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking the number of available CPUs" >&5 $as_echo_n "checking the number of available CPUs... " >&6; } CPU_COUNT="0" - case $host_os in #( + # Try generic methods - *darwin*) : - - if test -x /usr/sbin/sysctl; then : - - sysctl_a=`/usr/sbin/sysctl -a 2>/dev/null| grep -c hw.cpu` - if test sysctl_a; then : - - CPU_COUNT=`/usr/sbin/sysctl -n hw.ncpu` + # 'getconf' is POSIX utility, but '_NPROCESSORS_ONLN' and + # 'NPROCESSORS_ONLN' are platform-specific + command -v getconf >/dev/null 2>&1 && \ + CPU_COUNT=`getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null` || CPU_COUNT="0" + if test "$CPU_COUNT" -gt "0" 2>/dev/null || ! command -v nproc >/dev/null 2>&1; then : + : # empty +else + # 'nproc' is part of GNU Coreutils and is widely available + CPU_COUNT=`OMP_NUM_THREADS='' nproc 2>/dev/null` || CPU_COUNT=`nproc 2>/dev/null` || CPU_COUNT="0" fi - -fi ;; #( - - *linux*) : - - if test "x$CPU_COUNT" = "x0" -a -e /proc/cpuinfo; then : - - if test "x$CPU_COUNT" = "x0" -a -e /proc/cpuinfo; then : - - CPU_COUNT=`$EGREP -c '^processor' /proc/cpuinfo` - -fi - -fi - ;; #( + if test "$CPU_COUNT" -gt "0" 2>/dev/null; then : + : # empty +else + # Try platform-specific preferred methods + case $host_os in #( + *linux*) : + CPU_COUNT=`lscpu -p 2>/dev/null | $EGREP -e '^[0-9]+,' -c` || CPU_COUNT="0" ;; #( + *darwin*) : + CPU_COUNT=`sysctl -n hw.logicalcpu 2>/dev/null` || CPU_COUNT="0" ;; #( + freebsd*) : + command -v sysctl >/dev/null 2>&1 && CPU_COUNT=`sysctl -n kern.smp.cpus 2>/dev/null` || CPU_COUNT="0" ;; #( + netbsd*) : + command -v sysctl >/dev/null 2>&1 && CPU_COUNT=`sysctl -n hw.ncpuonline 2>/dev/null` || CPU_COUNT="0" ;; #( + solaris*) : + command -v psrinfo >/dev/null 2>&1 && CPU_COUNT=`psrinfo 2>/dev/null | $EGREP -e '^[0-9].*on-line' -c 2>/dev/null` || CPU_COUNT="0" ;; #( + mingw*) : + CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^[0-9]+/' -c` || CPU_COUNT="0" ;; #( + msys*) : + CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^[0-9]+/' -c` || CPU_COUNT="0" ;; #( + cygwin*) : + CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^[0-9]+/' -c` || CPU_COUNT="0" ;; #( *) : ;; esac - - if test "x$CPU_COUNT" = "x0"; then : - - CPU_COUNT="1" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unable to detect (assuming 1) " >&5 -$as_echo "unable to detect (assuming 1) " >&6; } - +fi + if test "$CPU_COUNT" -gt "0" 2>/dev/null || ! command -v sysctl >/dev/null 2>&1; then : + : # empty else - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPU_COUNT " >&5 -$as_echo "$CPU_COUNT " >&6; } + # Try less preferred generic method + # 'hw.ncpu' exist on many platforms, but not on GNU/Linux + CPU_COUNT=`sysctl -n hw.ncpu 2>/dev/null` || CPU_COUNT="0" fi + if test "$CPU_COUNT" -gt "0" 2>/dev/null; then : + : # empty +else + # Try platform-specific fallback methods + # They can be less accurate and slower then preferred methods + case $host_os in #( + *linux*) : + CPU_COUNT=`$EGREP -e '^processor' -c /proc/cpuinfo 2>/dev/null` || CPU_COUNT="0" ;; #( + *darwin*) : + CPU_COUNT=`system_profiler SPHardwareDataType 2>/dev/null | $EGREP -i -e 'number of cores:'|cut -d : -f 2 -s|tr -d ' '` || CPU_COUNT="0" ;; #( + freebsd*) : + CPU_COUNT=`dmesg 2>/dev/null| $EGREP -e '^cpu[0-9]+: '|sort -u|$EGREP -e '^' -c` || CPU_COUNT="0" ;; #( + netbsd*) : + CPU_COUNT=`command -v cpuctl >/dev/null 2>&1 && cpuctl list 2>/dev/null| $EGREP -e '^[0-9]+ .* online ' -c` || \ + CPU_COUNT=`dmesg 2>/dev/null| $EGREP -e '^cpu[0-9]+ at'|sort -u|$EGREP -e '^' -c` || CPU_COUNT="0" ;; #( + solaris*) : + command -v kstat >/dev/null 2>&1 && CPU_COUNT=`kstat -m cpu_info -s state -p 2>/dev/null | $EGREP -c -e 'on-line'` || \ + CPU_COUNT=`kstat -m cpu_info 2>/dev/null | $EGREP -c -e 'module: cpu_info'` || CPU_COUNT="0" ;; #( + mingw*) : + if CPU_COUNT=`reg query 'HKLM\\Hardware\\Description\\System\\CentralProcessor' 2>/dev/null | $EGREP -e '\\\\[0-9]+$' -c`; then : + : # empty +else + test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS" +fi ;; #( + msys*) : + test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS" ;; #( + cygwin*) : + test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS" ;; #( + *) : + ;; +esac +fi + if test "x$CPU_COUNT" != "x0" && test "$CPU_COUNT" -gt 0 2>/dev/null; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPU_COUNT" >&5 +$as_echo "$CPU_COUNT" >&6; } +else + CPU_COUNT="1" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unable to detect (assuming 1)" >&5 +$as_echo "unable to detect (assuming 1)" >&6; } + +fi AX_DOLLAR="\$" AX_SRB="\\135" @@ -24837,7 +26980,7 @@ AMINCLUDE="aminclude.am" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $AMINCLUDE" >&5 $as_echo "$as_me: creating $AMINCLUDE" >&6;} -AMINCLUDE_TIME=`date` +AMINCLUDE_TIME=`LC_ALL=C date` printf " @@ -24861,7 +27004,8 @@ else fi if test "x$enable_jobserver" = "xyes"; then - let enable_jobserver=$CPU_COUNT+1 + enable_jobserver=$CPU_COUNT + : $((enable_jobserver+=1)) fi if test "x$enable_jobserver" != "xno"; then @@ -24871,7 +27015,7 @@ $as_echo "$as_me: added jobserver support to make for $enable_jobserver jobs" >& -printf "AM_MAKEFLAGS += -j$enable_jobserver \n" >> "$AMINCLUDE" +printf "%s" "AM_MAKEFLAGS += -j$enable_jobserver " >> "$AMINCLUDE" fi @@ -24994,14 +27138,6 @@ $as_echo_n "checking that generated files are newer than configure... " >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } - if test -n "$EXEEXT"; then - am__EXEEXT_TRUE= - am__EXEEXT_FALSE='#' -else - am__EXEEXT_TRUE='#' - am__EXEEXT_FALSE= -fi - if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -25010,19 +27146,15 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= fi -if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi + if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCCAS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -25031,6 +27163,34 @@ if test -z "${DEBUG_TRUE}" && test -z "${DEBUG_FALSE}"; then as_fn_error $? "conditional \"DEBUG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${IS_VCS_CHECKOUT_TRUE}" && test -z "${IS_VCS_CHECKOUT_FALSE}"; then + as_fn_error $? "conditional \"IS_VCS_CHECKOUT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_DISTRO_TRUE}" && test -z "${BUILD_DISTRO_FALSE}"; then + as_fn_error $? "conditional \"BUILD_DISTRO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_ALL_TRUE}" && test -z "${BUILD_ALL_FALSE}"; then + as_fn_error $? "conditional \"BUILD_ALL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_TLS13_TRUE}" && test -z "${BUILD_TLS13_FALSE}"; then + as_fn_error $? "conditional \"BUILD_TLS13\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_RNG_TRUE}" && test -z "${BUILD_RNG_FALSE}"; then + as_fn_error $? "conditional \"BUILD_RNG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_SCTP_TRUE}" && test -z "${BUILD_SCTP_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SCTP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_MCAST_TRUE}" && test -z "${BUILD_MCAST_FALSE}"; then + as_fn_error $? "conditional \"BUILD_MCAST\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_IPV6_TRUE}" && test -z "${BUILD_IPV6_FALSE}"; then as_fn_error $? "conditional \"BUILD_IPV6\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -25039,6 +27199,22 @@ if test -z "${BUILD_LEANPSK_TRUE}" && test -z "${BUILD_LEANPSK_FALSE}"; then as_fn_error $? "conditional \"BUILD_LEANPSK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${BUILD_LEANTLS_TRUE}" && test -z "${BUILD_LEANTLS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_LEANTLS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_LOWMEM_TRUE}" && test -z "${BUILD_LOWMEM_FALSE}"; then + as_fn_error $? "conditional \"BUILD_LOWMEM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_PKCALLBACKS_TRUE}" && test -z "${BUILD_PKCALLBACKS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_PKCALLBACKS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CRYPTOAUTHLIB_TRUE}" && test -z "${BUILD_CRYPTOAUTHLIB_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CRYPTOAUTHLIB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_SNIFFER_TRUE}" && test -z "${BUILD_SNIFFER_FALSE}"; then as_fn_error $? "conditional \"BUILD_SNIFFER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -25055,10 +27231,30 @@ if test -z "${BUILD_AESCCM_TRUE}" && test -z "${BUILD_AESCCM_FALSE}"; then as_fn_error $? "conditional \"BUILD_AESCCM\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${BUILD_ARMASM_TRUE}" && test -z "${BUILD_ARMASM_FALSE}"; then + as_fn_error $? "conditional \"BUILD_ARMASM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_XILINX_TRUE}" && test -z "${BUILD_XILINX_FALSE}"; then + as_fn_error $? "conditional \"BUILD_XILINX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_AESNI_TRUE}" && test -z "${BUILD_AESNI_FALSE}"; then as_fn_error $? "conditional \"BUILD_AESNI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${BUILD_INTELASM_TRUE}" && test -z "${BUILD_INTELASM_FALSE}"; then + as_fn_error $? "conditional \"BUILD_INTELASM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_AFALG_TRUE}" && test -z "${BUILD_AFALG_FALSE}"; then + as_fn_error $? "conditional \"BUILD_AFALG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_DEVCRYPTO_TRUE}" && test -z "${BUILD_DEVCRYPTO_FALSE}"; then + as_fn_error $? "conditional \"BUILD_DEVCRYPTO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_CAMELLIA_TRUE}" && test -z "${BUILD_CAMELLIA_FALSE}"; then as_fn_error $? "conditional \"BUILD_CAMELLIA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -25075,6 +27271,10 @@ if test -z "${BUILD_BLAKE2_TRUE}" && test -z "${BUILD_BLAKE2_FALSE}"; then as_fn_error $? "conditional \"BUILD_BLAKE2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${BUILD_BLAKE2S_TRUE}" && test -z "${BUILD_BLAKE2S_FALSE}"; then + as_fn_error $? "conditional \"BUILD_BLAKE2S\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_SHA512_TRUE}" && test -z "${BUILD_SHA512_FALSE}"; then as_fn_error $? "conditional \"BUILD_SHA512\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -25087,16 +27287,12 @@ if test -z "${BUILD_ECC_TRUE}" && test -z "${BUILD_ECC_FALSE}"; then as_fn_error $? "conditional \"BUILD_ECC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${BUILD_CURVE25519_TRUE}" && test -z "${BUILD_CURVE25519_FALSE}"; then - as_fn_error $? "conditional \"BUILD_CURVE25519\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${BUILD_ED25519_TRUE}" && test -z "${BUILD_ED25519_FALSE}"; then as_fn_error $? "conditional \"BUILD_ED25519\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${BUILD_CURVED25519_SMALL_TRUE}" && test -z "${BUILD_CURVED25519_SMALL_FALSE}"; then - as_fn_error $? "conditional \"BUILD_CURVED25519_SMALL\" was never defined. +if test -z "${BUILD_ED25519_SMALL_TRUE}" && test -z "${BUILD_ED25519_SMALL_FALSE}"; then + as_fn_error $? "conditional \"BUILD_ED25519_SMALL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_FEMATH_TRUE}" && test -z "${BUILD_FEMATH_FALSE}"; then @@ -25107,6 +27303,38 @@ if test -z "${BUILD_GEMATH_TRUE}" && test -z "${BUILD_GEMATH_FALSE}"; then as_fn_error $? "conditional \"BUILD_GEMATH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${BUILD_CURVE25519_TRUE}" && test -z "${BUILD_CURVE25519_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CURVE25519\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CURVE25519_SMALL_TRUE}" && test -z "${BUILD_CURVE25519_SMALL_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CURVE25519_SMALL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_ED448_TRUE}" && test -z "${BUILD_ED448_FALSE}"; then + as_fn_error $? "conditional \"BUILD_ED448\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_ED448_SMALL_TRUE}" && test -z "${BUILD_ED448_SMALL_FALSE}"; then + as_fn_error $? "conditional \"BUILD_ED448_SMALL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_FE448_TRUE}" && test -z "${BUILD_FE448_FALSE}"; then + as_fn_error $? "conditional \"BUILD_FE448\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_GE448_TRUE}" && test -z "${BUILD_GE448_FALSE}"; then + as_fn_error $? "conditional \"BUILD_GE448\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CURVE448_TRUE}" && test -z "${BUILD_CURVE448_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CURVE448\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CURVE448_SMALL_TRUE}" && test -z "${BUILD_CURVE448_SMALL_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CURVE448_SMALL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_MEMORY_TRUE}" && test -z "${BUILD_MEMORY_FALSE}"; then as_fn_error $? "conditional \"BUILD_MEMORY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -25131,8 +27359,8 @@ if test -z "${BUILD_CODING_TRUE}" && test -z "${BUILD_CODING_FALSE}"; then as_fn_error $? "conditional \"BUILD_CODING\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${BUILD_DES3_TRUE}" && test -z "${BUILD_DES3_FALSE}"; then - as_fn_error $? "conditional \"BUILD_DES3\" was never defined. +if test -z "${BUILD_IDEA_TRUE}" && test -z "${BUILD_IDEA_FALSE}"; then + as_fn_error $? "conditional \"BUILD_IDEA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_RC4_TRUE}" && test -z "${BUILD_RC4_FALSE}"; then @@ -25147,10 +27375,6 @@ if test -z "${BUILD_SHA_TRUE}" && test -z "${BUILD_SHA_FALSE}"; then as_fn_error $? "conditional \"BUILD_SHA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${BUILD_MD4_TRUE}" && test -z "${BUILD_MD4_FALSE}"; then - as_fn_error $? "conditional \"BUILD_MD4\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${BUILD_HC128_TRUE}" && test -z "${BUILD_HC128_FALSE}"; then as_fn_error $? "conditional \"BUILD_HC128\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -25159,18 +27383,38 @@ if test -z "${BUILD_RABBIT_TRUE}" && test -z "${BUILD_RABBIT_FALSE}"; then as_fn_error $? "conditional \"BUILD_RABBIT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${BUILD_SHA512_TRUE}" && test -z "${BUILD_SHA512_FALSE}"; then - as_fn_error $? "conditional \"BUILD_SHA512\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${BUILD_SHA512_TRUE}" && test -z "${BUILD_SHA512_FALSE}"; then - as_fn_error $? "conditional \"BUILD_SHA512\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${BUILD_FIPS_TRUE}" && test -z "${BUILD_FIPS_FALSE}"; then as_fn_error $? "conditional \"BUILD_FIPS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${BUILD_FIPS_V1_TRUE}" && test -z "${BUILD_FIPS_V1_FALSE}"; then + as_fn_error $? "conditional \"BUILD_FIPS_V1\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_FIPS_V2_TRUE}" && test -z "${BUILD_FIPS_V2_FALSE}"; then + as_fn_error $? "conditional \"BUILD_FIPS_V2\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_FIPS_RAND_TRUE}" && test -z "${BUILD_FIPS_RAND_FALSE}"; then + as_fn_error $? "conditional \"BUILD_FIPS_RAND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CMAC_TRUE}" && test -z "${BUILD_CMAC_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CMAC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_SELFTEST_TRUE}" && test -z "${BUILD_SELFTEST_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SELFTEST\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_SHA224_TRUE}" && test -z "${BUILD_SHA224_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SHA224\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_SHA3_TRUE}" && test -z "${BUILD_SHA3_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SHA3\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_POLY1305_TRUE}" && test -z "${BUILD_POLY1305_FALSE}"; then as_fn_error $? "conditional \"BUILD_POLY1305\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -25187,6 +27431,14 @@ if test -z "${BUILD_OCSP_TRUE}" && test -z "${BUILD_OCSP_FALSE}"; then as_fn_error $? "conditional \"BUILD_OCSP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${BUILD_OCSP_STAPLING_TRUE}" && test -z "${BUILD_OCSP_STAPLING_FALSE}"; then + as_fn_error $? "conditional \"BUILD_OCSP_STAPLING\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_OCSP_STAPLING_V2_TRUE}" && test -z "${BUILD_OCSP_STAPLING_V2_FALSE}"; then + as_fn_error $? "conditional \"BUILD_OCSP_STAPLING_V2\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_CRL_TRUE}" && test -z "${BUILD_CRL_FALSE}"; then as_fn_error $? "conditional \"BUILD_CRL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -25195,30 +27447,46 @@ if test -z "${BUILD_CRL_MONITOR_TRUE}" && test -z "${BUILD_CRL_MONITOR_FALSE}"; as_fn_error $? "conditional \"BUILD_CRL_MONITOR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${BUILD_USER_RSA_TRUE}" && test -z "${BUILD_USER_RSA_FALSE}"; then + as_fn_error $? "conditional \"BUILD_USER_RSA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_USER_CRYPTO_TRUE}" && test -z "${BUILD_USER_CRYPTO_FALSE}"; then + as_fn_error $? "conditional \"BUILD_USER_CRYPTO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_NTRU_TRUE}" && test -z "${BUILD_NTRU_FALSE}"; then as_fn_error $? "conditional \"BUILD_NTRU\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${BUILD_PKCS7_TRUE}" && test -z "${BUILD_PKCS7_FALSE}"; then - as_fn_error $? "conditional \"BUILD_PKCS7\" was never defined. +if test -z "${BUILD_WNR_TRUE}" && test -z "${BUILD_WNR_FALSE}"; then + as_fn_error $? "conditional \"BUILD_WNR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${BUILD_PKCS7_TRUE}" && test -z "${BUILD_PKCS7_FALSE}"; then - as_fn_error $? "conditional \"BUILD_PKCS7\" was never defined. +if test -z "${BUILD_SRP_TRUE}" && test -z "${BUILD_SRP_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SRP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_VALGRIND_TRUE}" && test -z "${USE_VALGRIND_FALSE}"; then as_fn_error $? "conditional \"USE_VALGRIND\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${BUILD_ECC_TRUE}" && test -z "${BUILD_ECC_FALSE}"; then - as_fn_error $? "conditional \"BUILD_ECC\" was never defined. +if test -z "${BUILD_MD4_TRUE}" && test -z "${BUILD_MD4_FALSE}"; then + as_fn_error $? "conditional \"BUILD_MD4\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_PWDBASED_TRUE}" && test -z "${BUILD_PWDBASED_FALSE}"; then as_fn_error $? "conditional \"BUILD_PWDBASED\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${BUILD_SCRYPT_TRUE}" && test -z "${BUILD_SCRYPT_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SCRYPT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CRYPTONLY_TRUE}" && test -z "${BUILD_CRYPTONLY_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CRYPTONLY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_FASTMATH_TRUE}" && test -z "${BUILD_FASTMATH_FALSE}"; then as_fn_error $? "conditional \"BUILD_FASTMATH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -25227,28 +27495,132 @@ if test -z "${BUILD_SLOWMATH_TRUE}" && test -z "${BUILD_SLOWMATH_FALSE}"; then as_fn_error $? "conditional \"BUILD_SLOWMATH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${BUILD_EXAMPLES_TRUE}" && test -z "${BUILD_EXAMPLES_FALSE}"; then - as_fn_error $? "conditional \"BUILD_EXAMPLES\" was never defined. +if test -z "${BUILD_EXAMPLE_SERVERS_TRUE}" && test -z "${BUILD_EXAMPLE_SERVERS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_EXAMPLE_SERVERS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_EXAMPLE_CLIENTS_TRUE}" && test -z "${BUILD_EXAMPLE_CLIENTS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_EXAMPLE_CLIENTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_TESTS_TRUE}" && test -z "${BUILD_TESTS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_THREADED_EXAMPLES_TRUE}" && test -z "${BUILD_THREADED_EXAMPLES_FALSE}"; then + as_fn_error $? "conditional \"BUILD_THREADED_EXAMPLES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_WOLFCRYPT_TESTS_TRUE}" && test -z "${BUILD_WOLFCRYPT_TESTS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_WOLFCRYPT_TESTS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_LIBZ_TRUE}" && test -z "${BUILD_LIBZ_FALSE}"; then as_fn_error $? "conditional \"BUILD_LIBZ\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${BUILD_PKCS11_TRUE}" && test -z "${BUILD_PKCS11_FALSE}"; then + as_fn_error $? "conditional \"BUILD_PKCS11\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_PKCS12_TRUE}" && test -z "${BUILD_PKCS12_FALSE}"; then + as_fn_error $? "conditional \"BUILD_PKCS12\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CAVIUM_TRUE}" && test -z "${BUILD_CAVIUM_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CAVIUM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CAVIUM_V_TRUE}" && test -z "${BUILD_CAVIUM_V_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CAVIUM_V\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_OCTEON_SYNC_TRUE}" && test -z "${BUILD_OCTEON_SYNC_FALSE}"; then + as_fn_error $? "conditional \"BUILD_OCTEON_SYNC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_INTEL_QA_TRUE}" && test -z "${BUILD_INTEL_QA_FALSE}"; then + as_fn_error $? "conditional \"BUILD_INTEL_QA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_INTEL_QA_SYNC_TRUE}" && test -z "${BUILD_INTEL_QA_SYNC_FALSE}"; then + as_fn_error $? "conditional \"BUILD_INTEL_QA_SYNC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_SP_TRUE}" && test -z "${BUILD_SP_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_SP_C_TRUE}" && test -z "${BUILD_SP_C_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SP_C\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_SP_ARM64_TRUE}" && test -z "${BUILD_SP_ARM64_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SP_ARM64\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_SP_ARM32_TRUE}" && test -z "${BUILD_SP_ARM32_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SP_ARM32\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_SP_ARM_THUMB_TRUE}" && test -z "${BUILD_SP_ARM_THUMB_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SP_ARM_THUMB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_SP_ARM_CORTEX_TRUE}" && test -z "${BUILD_SP_ARM_CORTEX_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SP_ARM_CORTEX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_SP_X86_64_TRUE}" && test -z "${BUILD_SP_X86_64_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SP_X86_64\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_SP_INT_TRUE}" && test -z "${BUILD_SP_INT_FALSE}"; then + as_fn_error $? "conditional \"BUILD_SP_INT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_FAST_RSA_TRUE}" && test -z "${BUILD_FAST_RSA_FALSE}"; then + as_fn_error $? "conditional \"BUILD_FAST_RSA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_MCAPI_TRUE}" && test -z "${BUILD_MCAPI_FALSE}"; then as_fn_error $? "conditional \"BUILD_MCAPI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${BUILD_CRL_TRUE}" && test -z "${BUILD_CRL_FALSE}"; then - as_fn_error $? "conditional \"BUILD_CRL\" was never defined. +if test -z "${BUILD_ASYNCCRYPT_TRUE}" && test -z "${BUILD_ASYNCCRYPT_FALSE}"; then + as_fn_error $? "conditional \"BUILD_ASYNCCRYPT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${BUILD_OCSP_TRUE}" && test -z "${BUILD_OCSP_FALSE}"; then - as_fn_error $? "conditional \"BUILD_OCSP\" was never defined. +if test -z "${BUILD_WOLFEVENT_TRUE}" && test -z "${BUILD_WOLFEVENT_FALSE}"; then + as_fn_error $? "conditional \"BUILD_WOLFEVENT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${IS_VCS_CHECKOUT_TRUE}" && test -z "${IS_VCS_CHECKOUT_FALSE}"; then - as_fn_error $? "conditional \"IS_VCS_CHECKOUT\" was never defined. +if test -z "${BUILD_CRYPTOCB_TRUE}" && test -z "${BUILD_CRYPTOCB_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CRYPTOCB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_PSK_TRUE}" && test -z "${BUILD_PSK_FALSE}"; then + as_fn_error $? "conditional \"BUILD_PSK\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_TRUST_PEER_CERT_TRUE}" && test -z "${BUILD_TRUST_PEER_CERT_FALSE}"; then + as_fn_error $? "conditional \"BUILD_TRUST_PEER_CERT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_PKI_TRUE}" && test -z "${BUILD_PKI_FALSE}"; then + as_fn_error $? "conditional \"BUILD_PKI\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_DES3_TRUE}" && test -z "${BUILD_DES3_FALSE}"; then + as_fn_error $? "conditional \"BUILD_DES3\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_PKCS7_TRUE}" && test -z "${BUILD_PKCS7_FALSE}"; then + as_fn_error $? "conditional \"BUILD_PKCS7\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_HASHFLAGS_TRUE}" && test -z "${BUILD_HASHFLAGS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_HASHFLAGS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi @@ -25648,7 +28020,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by wolfssl $as_me 3.6.0, which was +This file was extended by wolfssl $as_me 4.4.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -25709,13 +28081,13 @@ Configuration commands: $config_commands Report bugs to . -wolfssl home page: ." +wolfssl home page: ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -wolfssl config.status 3.6.0 +wolfssl config.status 4.4.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -25834,7 +28206,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" +AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" # The HP-UX ksh and POSIX shell print the target directory to stdout @@ -25847,9 +28219,13 @@ delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' @@ -25877,12 +28253,10 @@ lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_q lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' -OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' -DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' @@ -25899,10 +28273,13 @@ compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' @@ -25967,67 +28344,14 @@ finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' -sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' -compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' -predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' -postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' -predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' -postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' -compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' -LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' -reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' -reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' -old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' -compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' -GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' -lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' -archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' -enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' -export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' -whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' -compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' -old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' -old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' -archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' -archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' -module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' -module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' -with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' -allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' -no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' -inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' -link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' -always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' -export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' -exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' -include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' -prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' -postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' -file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' -hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' -compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' -predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' -postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' -predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' -postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' -compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' @@ -26042,7 +28366,10 @@ _LTECHO_EOF' } # Quote evaled strings. -for var in SHELL \ +for var in AS \ +DLLTOOL \ +OBJDUMP \ +SHELL \ ECHO \ PATH_SEPARATOR \ SED \ @@ -26055,12 +28382,10 @@ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ -OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ -DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ @@ -26072,9 +28397,12 @@ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ nm_file_list_spec \ +lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ @@ -26106,41 +28434,10 @@ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ -striplib \ -compiler_lib_search_dirs \ -predep_objects \ -postdep_objects \ -predeps \ -postdeps \ -compiler_lib_search_path \ -LD_CXX \ -reload_flag_CXX \ -compiler_CXX \ -lt_prog_compiler_no_builtin_flag_CXX \ -lt_prog_compiler_pic_CXX \ -lt_prog_compiler_wl_CXX \ -lt_prog_compiler_static_CXX \ -lt_cv_prog_compiler_c_o_CXX \ -export_dynamic_flag_spec_CXX \ -whole_archive_flag_spec_CXX \ -compiler_needs_object_CXX \ -with_gnu_ld_CXX \ -allow_undefined_flag_CXX \ -no_undefined_flag_CXX \ -hardcode_libdir_flag_spec_CXX \ -hardcode_libdir_separator_CXX \ -exclude_expsyms_CXX \ -include_expsyms_CXX \ -file_list_spec_CXX \ -compiler_lib_search_dirs_CXX \ -predep_objects_CXX \ -postdep_objects_CXX \ -predeps_CXX \ -postdeps_CXX \ -compiler_lib_search_path_CXX; do +striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -26167,21 +28464,11 @@ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ -sys_lib_dlsearch_path_spec \ -reload_cmds_CXX \ -old_archive_cmds_CXX \ -old_archive_from_new_cmds_CXX \ -old_archive_from_expsyms_cmds_CXX \ -archive_cmds_CXX \ -archive_expsym_cmds_CXX \ -module_cmds_CXX \ -module_expsym_cmds_CXX \ -export_symbols_cmds_CXX \ -prelink_cmds_CXX \ -postlink_cmds_CXX; do +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -26190,27 +28477,22 @@ postlink_cmds_CXX; do done ac_aux_dir='$ac_aux_dir' -xsi_shell='$xsi_shell' -lt_shell_append='$lt_shell_append' -# See if we are running on zsh, and set the options which allow our +# See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}" ; then +if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' - TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' - - _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 @@ -26219,13 +28501,14 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 for ac_config_target in $ac_config_targets do case $ac_config_target in - "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.in" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.in" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "stamp-h") CONFIG_FILES="$CONFIG_FILES stamp-h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "wolfssl/version.h") CONFIG_FILES="$CONFIG_FILES wolfssl/version.h" ;; "wolfssl/options.h") CONFIG_FILES="$CONFIG_FILES wolfssl/options.h" ;; + "cyassl/options.h") CONFIG_FILES="$CONFIG_FILES cyassl/options.h" ;; "support/wolfssl.pc") CONFIG_FILES="$CONFIG_FILES support/wolfssl.pc" ;; "rpm/spec") CONFIG_FILES="$CONFIG_FILES rpm/spec" ;; @@ -26827,29 +29110,35 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + case $CONFIG_FILES in #( + *\'*) : + eval set x "$CONFIG_FILES" ;; #( + *) : + set x $CONFIG_FILES ;; #( + *) : + ;; +esac shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$mf" | + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`$as_dirname -- "$am_mf" || +$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$am_mf" : 'X\(//\)[^/]' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -26867,106 +29156,101 @@ $as_echo X"$mf" | q } s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + am_filepart=`$as_basename -- "$am_mf" || +$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$am_mf" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } - /^X\(\/\/\)[^/].*/{ + /^X\/\(\/\/\)$/{ s//\1/ q } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ + /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` - as_dir=$dirpart/$fdir; as_fn_mkdir_p - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + { echo "$as_me:$LINENO: cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles" >&5 + (cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } || am_rc=$? done + if test $am_rc -ne 0; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE=\"gmake\" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking). +See \`config.log' for more details" "$LINENO" 5; } + fi + { am_dirpart=; unset am_dirpart;} + { am_filepart=; unset am_filepart;} + { am_mf=; unset am_mf;} + { am_rc=; unset am_rc;} + rm -f conftest-deps.mk } ;; "libtool":C) - # See if we are running on zsh, and set the options which allow our + # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then + if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi - cfgfile="${ofile}T" + cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL - -# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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 of the License, or +# (at your option) any later version. # -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. # -# This file is part of GNU Libtool. -# -# GNU Libtool 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. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, or -# obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# along with this program. If not, see . # The names of the tagged configurations supported by this script. -available_tags="CXX " +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG @@ -26977,6 +29261,15 @@ macro_revision=$macro_revision # Whether or not to build static libraries. build_old_libs=$enable_static +# Assembler program. +AS=$lt_AS + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Object dumper program. +OBJDUMP=$lt_OBJDUMP + # Whether or not to build shared libraries. build_libtool_libs=$enable_shared @@ -26986,6 +29279,9 @@ pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + # Shell to use when invoking shell scripts. SHELL=$lt_SHELL @@ -27050,9 +29346,6 @@ to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd -# An object symbol dumper. -OBJDUMP=$lt_OBJDUMP - # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method @@ -27065,9 +29358,6 @@ file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob -# DLL creation program. -DLLTOOL=$lt_DLLTOOL - # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd @@ -27103,18 +29393,27 @@ global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec -# The root where to search for dependent libraries,and in which our libraries should be installed. +# The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + # The name of the directory that contains temporary libtool files. objdir=$objdir @@ -27205,8 +29504,11 @@ hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec -# Run-time system search path for libraries. -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen @@ -27299,13 +29601,13 @@ hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute @@ -27353,22 +29655,67 @@ file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action -# The directories searched by this compiler when creating a shared library. -compiler_lib_search_dirs=$lt_compiler_lib_search_dirs - -# Dependencies to place before and after the objects being linked to -# create a shared library. -predep_objects=$lt_predep_objects -postdep_objects=$lt_postdep_objects -predeps=$lt_predeps -postdeps=$lt_postdeps - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path - # ### END LIBTOOL CONFIG +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + _LT_EOF case $host_os in @@ -27377,7 +29724,7 @@ _LT_EOF # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then +if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -27386,7 +29733,7 @@ _LT_EOF esac -ltmain="$ac_aux_dir/ltmain.sh" +ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if @@ -27396,322 +29743,10 @@ ltmain="$ac_aux_dir/ltmain.sh" sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) - if test x"$xsi_shell" = xyes; then - sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ -func_dirname ()\ -{\ -\ case ${1} in\ -\ */*) func_dirname_result="${1%/*}${2}" ;;\ -\ * ) func_dirname_result="${3}" ;;\ -\ esac\ -} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_basename ()$/,/^} # func_basename /c\ -func_basename ()\ -{\ -\ func_basename_result="${1##*/}"\ -} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ -func_dirname_and_basename ()\ -{\ -\ case ${1} in\ -\ */*) func_dirname_result="${1%/*}${2}" ;;\ -\ * ) func_dirname_result="${3}" ;;\ -\ esac\ -\ func_basename_result="${1##*/}"\ -} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ -func_stripname ()\ -{\ -\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ -\ # positional parameters, so assign one to ordinary parameter first.\ -\ func_stripname_result=${3}\ -\ func_stripname_result=${func_stripname_result#"${1}"}\ -\ func_stripname_result=${func_stripname_result%"${2}"}\ -} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ -func_split_long_opt ()\ -{\ -\ func_split_long_opt_name=${1%%=*}\ -\ func_split_long_opt_arg=${1#*=}\ -} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ -func_split_short_opt ()\ -{\ -\ func_split_short_opt_arg=${1#??}\ -\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ -} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ -func_lo2o ()\ -{\ -\ case ${1} in\ -\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ -\ *) func_lo2o_result=${1} ;;\ -\ esac\ -} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_xform ()$/,/^} # func_xform /c\ -func_xform ()\ -{\ - func_xform_result=${1%.*}.lo\ -} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_arith ()$/,/^} # func_arith /c\ -func_arith ()\ -{\ - func_arith_result=$(( $* ))\ -} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_len ()$/,/^} # func_len /c\ -func_len ()\ -{\ - func_len_result=${#1}\ -} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - -fi - -if test x"$lt_shell_append" = xyes; then - sed -e '/^func_append ()$/,/^} # func_append /c\ -func_append ()\ -{\ - eval "${1}+=\\${2}"\ -} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ -func_append_quoted ()\ -{\ -\ func_quote_for_eval "${2}"\ -\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ -} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: - - - # Save a `func_append' function call where possible by direct use of '+=' - sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -else - # Save a `func_append' function call even when '+=' is not available - sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -fi - -if test x"$_lt_function_replace_fail" = x":"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 -$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} -fi - - mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" - - cat <<_LT_EOF >> "$ofile" - -# ### BEGIN LIBTOOL TAG CONFIG: CXX - -# The linker used to build libraries. -LD=$lt_LD_CXX - -# How to create reloadable object files. -reload_flag=$lt_reload_flag_CXX -reload_cmds=$lt_reload_cmds_CXX - -# Commands used to build an old-style archive. -old_archive_cmds=$lt_old_archive_cmds_CXX - -# A language specific compiler. -CC=$lt_compiler_CXX - -# Is the compiler the GNU compiler? -with_gcc=$GCC_CXX - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_CXX - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_CXX - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_CXX - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_CXX - -# Whether or not to disallow shared libs when runtime libs are static. -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX - -# Whether the compiler copes with passing no objects directly. -compiler_needs_object=$lt_compiler_needs_object_CXX - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX - -# Commands used to build a shared archive. -archive_cmds=$lt_archive_cmds_CXX -archive_expsym_cmds=$lt_archive_expsym_cmds_CXX - -# Commands used to build a loadable module if different from building -# a shared archive. -module_cmds=$lt_module_cmds_CXX -module_expsym_cmds=$lt_module_expsym_cmds_CXX - -# Whether we are building with GNU ld or not. -with_gnu_ld=$lt_with_gnu_ld_CXX - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_CXX - -# Flag that enforces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_CXX - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX - -# Whether we need a single "-rpath" flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX - -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes -# DIR into the resulting binary. -hardcode_direct=$hardcode_direct_CXX - -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes -# DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \${shlibpath_var} if the -# library is relocated. -hardcode_direct_absolute=$hardcode_direct_absolute_CXX - -# Set to "yes" if using the -LDIR flag during linking hardcodes DIR -# into the resulting binary. -hardcode_minus_L=$hardcode_minus_L_CXX - -# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR -# into the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX - -# Set to "yes" if building a shared library automatically hardcodes DIR -# into the library and all subsequent libraries and executables linked -# against it. -hardcode_automatic=$hardcode_automatic_CXX - -# Set to yes if linker adds runtime paths of dependent libraries -# to runtime path list. -inherit_rpath=$inherit_rpath_CXX - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_CXX - -# Set to "yes" if exported symbols are required. -always_export_symbols=$always_export_symbols_CXX - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_CXX - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_CXX - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_CXX - -# Commands necessary for linking programs (against libraries) with templates. -prelink_cmds=$lt_prelink_cmds_CXX - -# Commands necessary for finishing linking programs. -postlink_cmds=$lt_postlink_cmds_CXX - -# Specify filename containing input files. -file_list_spec=$lt_file_list_spec_CXX - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_CXX - -# The directories searched by this compiler when creating a shared library. -compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX - -# Dependencies to place before and after the objects being linked to -# create a shared library. -predep_objects=$lt_predep_objects_CXX -postdep_objects=$lt_postdep_objects_CXX -predeps=$lt_predeps_CXX -postdeps=$lt_postdeps_CXX - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_CXX - -# ### END LIBTOOL TAG CONFIG: CXX -_LT_EOF - ;; "stamp-h":F) echo timestamp > stamp-h ;; @@ -27758,55 +29793,48 @@ fi echo "---" echo "Running make clean..." make clean >/dev/null 2>&1 -# Touch files that may not be in repository -echo "Touching File..." -touch ctaocrypt/src/fips.c -touch ctaocrypt/src/fips_test.c -echo # generate user options header echo "---" echo "Generating user options header..." OPTION_FILE="wolfssl/options.h" -#if -#OPTION_FILE+="cyassl/options.h" -#fi rm -f $OPTION_FILE echo "/* wolfssl options.h" > $OPTION_FILE echo " * generated from configure options" >> $OPTION_FILE echo " *" >> $OPTION_FILE -echo " * Copyright (C) 2006-2015 wolfSSL Inc." >> $OPTION_FILE +echo " * Copyright (C) 2006-2020 wolfSSL Inc." >> $OPTION_FILE echo " *" >> $OPTION_FILE echo " * This file is part of wolfSSL. (formerly known as CyaSSL)" >> $OPTION_FILE echo " *" >> $OPTION_FILE echo " */" >> $OPTION_FILE echo "" >> $OPTION_FILE -echo "#pragma once" >> $OPTION_FILE +echo "#ifndef WOLFSSL_OPTIONS_H" >> $OPTION_FILE +echo "#define WOLFSSL_OPTIONS_H" >> $OPTION_FILE +echo "" >> $OPTION_FILE echo "" >> $OPTION_FILE echo "#ifdef __cplusplus" >> $OPTION_FILE echo "extern \"C\" {" >> $OPTION_FILE echo "#endif" >> $OPTION_FILE echo "" >> $OPTION_FILE -for option in $OPTION_FLAGS; do - defonly=`echo $option | sed 's/-D//'` +for option in $CPPFLAGS $AM_CPPFLAGS $CFLAGS $AM_CFLAGS; do + defonly=`echo $option | sed 's/^-D//'` if test "$defonly" != "$option" then noequalsign=`echo $defonly | sed 's/=/ /'` if test "$noequalsign" = "NDEBUG" || test "$noequalsign" = "DEBUG" then - echo "not outputing (N)DEBUG to $OPTION_FILE" + echo "not outputting (N)DEBUG to $OPTION_FILE" continue fi - # allow user to igonore system options - ignoresys=no - if [[ $noequalsign == _* ]] ; + # allow user to ignore system options + ignoresys=$(echo "$noequalsign" | grep '^_.*') + if test -n "$ignoresys" then - ignoresys=yes echo "#ifndef WOLFSSL_OPTIONS_IGNORE_SYS" >> $OPTION_FILE fi @@ -27814,7 +29842,7 @@ for option in $OPTION_FLAGS; do echo "#undef $noarg" >> $OPTION_FILE echo "#define $noequalsign" >> $OPTION_FILE - if test "$ignoresys" = "yes" + if test -n "$ignoresys" then echo "#endif" >> $OPTION_FILE fi @@ -27830,9 +29858,12 @@ echo "#ifdef __cplusplus" >> $OPTION_FILE echo "}" >> $OPTION_FILE echo "#endif" >> $OPTION_FILE echo "" >> $OPTION_FILE +echo "" >> $OPTION_FILE +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 @@ -27843,96 +29874,215 @@ do echo "$line" >> cyassl/options.h done < $OPTION_FILE +# switch ifdef protection in cyassl/option.h to CYASSL_OPTONS_H, remove bak +sed -i.bak 's/WOLFSSL_OPTIONS_H/CYASSL_OPTIONS_H/g' cyassl/options.h + +# workaround for mingw sed that may get "Permission denied" trying to preserver permissions +case $host_os in + mingw*) + chmod u+w cyassl/options.h ;; +esac + +rm cyassl/options.h.bak + + # output config summary echo "---" echo "Configuration summary for $PACKAGE_NAME version $VERSION" echo "" -echo " * Installation prefix: $prefix" -echo " * System type: $host_vendor-$host_os" -echo " * Host CPU: $host_cpu" -echo " * C Compiler: $CC" -echo " * C Flags: $CFLAGS" -echo " * C++ Compiler: $CXX" -echo " * C++ Flags: $CXXFLAGS" -echo " * CPP Flags: $CPPFLAGS" -echo " * LIB Flags: $LIB" -echo " * Debug enabled: $ax_enable_debug" -echo " * Warnings as failure: $ac_cv_warnings_as_errors" -echo " * make -j: $enable_jobserver" -echo " * VCS checkout: $ac_cv_vcs_checkout" +echo " * Installation prefix: $prefix" +echo " * System type: $host_vendor-$host_os" +echo " * Host CPU: $host_cpu" +echo " * C Compiler: $CC" +echo " * C Flags: $CFLAGS" +echo " * C++ Compiler: $CXX" +echo " * C++ Flags: $CXXFLAGS" +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" echo echo " Features " -echo " * Single threaded: $ENABLED_SINGLETHREADED" -echo " * Filesystem: $ENABLED_FILESYSTEM" -echo " * OpenSSL Extra API: $ENABLED_OPENSSLEXTRA" -echo " * Max Strength Build: $ENABLED_MAXSTRENGTH" -echo " * fastmath: $ENABLED_FASTMATH" -echo " * sniffer: $ENABLED_SNIFFER" -echo " * snifftest: $ENABLED_SNIFFTEST" -echo " * ARC4: $ENABLED_ARC4" -echo " * AES: $ENABLED_AES" -echo " * AES-NI: $ENABLED_AESNI" -echo " * AES-GCM: $ENABLED_AESGCM" -echo " * AES-CCM: $ENABLED_AESCCM" -echo " * DES3: $ENABLED_DES3" -echo " * Camellia: $ENABLED_CAMELLIA" -echo " * NULL Cipher: $ENABLED_NULL_CIPHER" -echo " * MD5: $ENABLED_MD5" -echo " * RIPEMD: $ENABLED_RIPEMD" -echo " * SHA: $ENABLED_SHA" -echo " * SHA-512: $ENABLED_SHA512" -echo " * BLAKE2: $ENABLED_BLAKE2" -echo " * keygen: $ENABLED_KEYGEN" -echo " * certgen: $ENABLED_CERTGEN" -echo " * certreq: $ENABLED_CERTREQ" -echo " * HC-128: $ENABLED_HC128" -echo " * RABBIT: $ENABLED_RABBIT" -echo " * CHACHA: $ENABLED_CHACHA" -echo " * Hash DRBG: $ENABLED_HASHDRBG" -echo " * PWDBASED: $ENABLED_PWDBASED" -echo " * HKDF: $ENABLED_HKDF" -echo " * MD4: $ENABLED_MD4" -echo " * PSK: $ENABLED_PSK" -echo " * Poly1305: $ENABLED_POLY1305" -echo " * LEANPSK: $ENABLED_LEANPSK" -echo " * RSA: $ENABLED_RSA" -echo " * DSA: $ENABLED_DSA" -echo " * DH: $ENABLED_DH" -echo " * ECC: $ENABLED_ECC" -echo " * CURVE25519: $ENABLED_CURVE25519" -echo " * ED25519: $ENABLED_ED25519" -echo " * FPECC: $ENABLED_FPECC" -echo " * ECC_ENCRYPT: $ENABLED_ECC_ENCRYPT" -echo " * ASN: $ENABLED_ASN" -echo " * Anonymous cipher: $ENABLED_ANON" -echo " * CODING: $ENABLED_CODING" -echo " * MEMORY: $ENABLED_MEMORY" -echo " * I/O POOL: $ENABLED_IOPOOL" -echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" -echo " * DTLS: $ENABLED_DTLS" -echo " * Old TLS Versions: $ENABLED_OLD_TLS" -echo " * OCSP: $ENABLED_OCSP" -echo " * CRL: $ENABLED_CRL" -echo " * CRL-MONITOR: $ENABLED_CRL_MONITOR" -echo " * Persistent session cache: $ENABLED_SAVESESSION" -echo " * Persistent cert cache: $ENABLED_SAVECERT" -echo " * Atomic User Record Layer: $ENABLED_ATOMICUSER" -echo " * Public Key Callbacks: $ENABLED_PKCALLBACKS" -echo " * NTRU: $ENABLED_NTRU" -echo " * SNI: $ENABLED_SNI" -echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT" -echo " * Truncated HMAC: $ENABLED_TRUNCATED_HMAC" -echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION" -echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION" -echo " * Supported Elliptic Curves: $ENABLED_SUPPORTED_CURVES" -echo " * Session Ticket: $ENABLED_SESSION_TICKET" -echo " * All TLS Extensions: $ENABLED_TLSX" -echo " * PKCS#7 $ENABLED_PKCS7" -echo " * wolfSCEP $ENABLED_WOLFSCEP" -echo " * Small Stack: $ENABLED_SMALL_STACK" -echo " * valgrind unit tests: $ENABLED_VALGRIND" -echo " * LIBZ: $ENABLED_LIBZ" -echo " * Examples: $ENABLED_EXAMPLES" +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" +echo " * AES: $ENABLED_AES" +echo " * AES-NI: $ENABLED_AESNI" +echo " * AES-CBC: $ENABLED_AESCBC" +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" +echo " * NULL Cipher: $ENABLED_NULL_CIPHER" +echo " * MD5: $ENABLED_MD5" +echo " * RIPEMD: $ENABLED_RIPEMD" +echo " * SHA: $ENABLED_SHA" +echo " * SHA-224: $ENABLED_SHA224" +echo " * SHA-384: $ENABLED_SHA384" +echo " * SHA-512: $ENABLED_SHA512" +echo " * SHA3: $ENABLED_SHA3" +echo " * SHAKE256: $ENABLED_SHAKE256" +echo " * BLAKE2: $ENABLED_BLAKE2" +echo " * CMAC: $ENABLED_CMAC" +echo " * keygen: $ENABLED_KEYGEN" +echo " * certgen: $ENABLED_CERTGEN" +echo " * certreq: $ENABLED_CERTREQ" +echo " * certext: $ENABLED_CERTEXT" +echo " * certgencache: $ENABLED_certgencache" +echo " * HC-128: $ENABLED_HC128" +echo " * RABBIT: $ENABLED_RABBIT" +echo " * CHACHA: $ENABLED_CHACHA" +echo " * Hash DRBG: $ENABLED_HASHDRBG" +echo " * PWDBASED: $ENABLED_PWDBASED" +echo " * scrypt: $ENABLED_SCRYPT" +echo " * wolfCrypt Only: $ENABLED_CRYPTONLY" +echo " * HKDF: $ENABLED_HKDF" +echo " * X9.63 KDF: $ENABLED_X963KDF" +echo " * MD4: $ENABLED_MD4" +echo " * PSK: $ENABLED_PSK" +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 " * DH Default Parameters: $ENABLED_DHDEFAULTPARAMS" +echo " * ECC: $ENABLED_ECC" +echo " * ECC Custom Curves $ENABLED_ECCCUSTCURVES" +echo " * CURVE25519: $ENABLED_CURVE25519" +echo " * ED25519: $ENABLED_ED25519" +echo " * CURVE448: $ENABLED_CURVE448" +echo " * ED448: $ENABLED_ED448" +echo " * FPECC: $ENABLED_FPECC" +echo " * ECC_ENCRYPT: $ENABLED_ECC_ENCRYPT" +echo " * ASN: $ENABLED_ASN" +echo " * Anonymous cipher: $ENABLED_ANON" +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 " * Apache httpd: $ENABLED_APACHE_HTTPD" +echo " * NGINX: $ENABLED_NGINX" +echo " * ASIO: $ENABLED_ASIO" +echo " * LIBWEBSOCKETS: $ENABLED_LIBWEBSOCKETS" +echo " * Qt $ENABLED_QT" +echo " * Qt Unit Testing $ENABLED_QT_TEST" +echo " * SIGNAL: $ENABLED_SIGNAL" +echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" +echo " * DTLS: $ENABLED_DTLS" +echo " * SCTP: $ENABLED_SCTP" +echo " * Indefinite Length: $ENABLED_BER_INDEF" +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 " * TLS v1.3 Draft 22: $ENABLED_TLS13_DRAFT22" +echo " * TLS v1.3 Draft 23: $ENABLED_TLS13_DRAFT23" +echo " * TLS v1.3 Draft 26: $ENABLED_TLS13_DRAFT26" +echo " * TLS v1.3 Draft 28: $ENABLED_TLS13_DRAFT28" +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" +echo " * CRL: $ENABLED_CRL" +echo " * CRL-MONITOR: $ENABLED_CRL_MONITOR" +echo " * Persistent session cache: $ENABLED_SAVESESSION" +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" +echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT" +echo " * Trusted CA Indication: $ENABLED_TRUSTED_CA" +echo " * Truncated HMAC: $ENABLED_TRUNCATED_HMAC" +echo " * Supported Elliptic Curves: $ENABLED_SUPPORTED_CURVES" +echo " * FFDHE only in client: $ENABLED_FFDHE_ONLY" +echo " * Session Ticket: $ENABLED_SESSION_TICKET" +echo " * Extended Master Secret: $ENABLED_EXTENDED_MASTER" +echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION" +echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION" +echo " * Fallback SCSV: $ENABLED_FALLBACK_SCSV" +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" +echo " * valgrind unit tests: $ENABLED_VALGRIND" +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 " * PKCS#11: $ENABLED_PKCS11" +echo " * PKCS#12: $ENABLED_PKCS12" +echo " * Cavium Nitox: $ENABLED_CAVIUM" +echo " * Cavium Octeon (Sync): $ENABLED_OCTEON_SYNC" +echo " * Intel Quick Assist: $ENABLED_INTEL_QA" +echo " * ARM ASM: $ENABLED_ARMASM" +echo " * AES Key Wrap: $ENABLED_AESKEYWRAP" +echo " * Write duplicate: $ENABLED_WRITEDUP" +echo " * Xilinx Hardware Acc.: $ENABLED_XILINX" +echo " * Inline Code: $ENABLED_INLINE" +echo " * Linux AF_ALG: $ENABLED_AFALG" +echo " * Linux devcrypto: $ENABLED_DEVCRYPTO" +echo " * Crypto callbacks: $ENABLED_CRYPTOCB" echo "" echo "---" +################################################################################ +# Show warnings at bottom so they are noticed +################################################################################ + +if test "$ENABLED_ASYNCCRYPT" = "yes" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Make sure real async files are loaded. Contact wolfSSL for details on using the asynccrypt option." >&5 +$as_echo "$as_me: WARNING: Make sure real async files are loaded. Contact wolfSSL for details on using the asynccrypt option." >&2;} +fi + +# MinGW static vs shared library +# Reference URL from libtool for MinGW is located at +# http://www.gnu.org/software/libtool/manual/libtool.html#Cygwin-to-MinGW-Cross +# this allows for not even having dllimport/dllexport on functions +# with recent libtools, only requiring it with global variables. +# +# The following warning is displayed here because if not using "contemporary GNU +# tools" there is the possibility of export/import issues. +# wolfSSL uses __declspec(dllexport) and "contemporary GNU tools" handle the +# case where both static and shared libraries are built. +# +# More can be found about the MinGW linker at +# https://sourceware.org/binutils/docs/ld/WIN32.html +if test "$MINGW_LIB_WARNING" = "yes" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Building with shared and static library at the same time on this system may cause export/import problems when using non contemporary GNU tools." >&5 +$as_echo "$as_me: WARNING: Building with shared and static library at the same time on this system may cause export/import problems when using non contemporary GNU tools." >&2;} +fi + diff --git a/FreeRTOS-Plus/Source/WolfSSL/configure.ac b/FreeRTOS-Plus/Source/WolfSSL/configure.ac index 4b6d3314d..ff6b79f86 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/configure.ac +++ b/FreeRTOS-Plus/Source/WolfSSL/configure.ac @@ -1,114 +1,93 @@ # configure.ac # -# Copyright (C) 2006-2015 wolfSSL Inc. +# Copyright (C) 2006-2020 wolfSSL Inc. # # This file is part of wolfSSL. (formerly known as CyaSSL) # # - -AC_INIT([wolfssl],[3.6.0],[https://github.com/wolfssl/wolfssl/issues],[wolfssl],[http://www.wolfssl.com]) - +AC_COPYRIGHT([Copyright (C) 2006-2020 wolfSSL Inc.]) +AC_PREREQ([2.63]) +AC_INIT([wolfssl],[4.4.0],[https://github.com/wolfssl/wolfssl/issues],[wolfssl],[https://www.wolfssl.com]) AC_CONFIG_AUX_DIR([build-aux]) +# The following sets CFLAGS to empty if unset on command line. We do not +# want the default "-g -O2" that AC_PROG_CC sets automatically. +: ${CFLAGS=""} + +# Test ar for the "U" option. Should be checked before the libtool macros. +xxx_ar_flags=$(ar --help 2>&1) +AS_CASE([$xxx_ar_flags],[*'use actual timestamps and uids/gids'*],[: ${AR_FLAGS="Ucru"}]) + +AC_PROG_CC +AM_PROG_CC_C_O AC_CANONICAL_HOST -AC_CANONICAL_BUILD - -AM_INIT_AUTOMAKE([1.11 -Wall -Werror -Wno-portability foreign tar-ustar subdir-objects no-define color-tests]) -AC_PREREQ([2.63]) - -AC_ARG_PROGRAM -AC_DEFUN([PROTECT_AC_USE_SYSTEM_EXTENSIONS], - [AX_SAVE_FLAGS - AC_LANG_PUSH([C]) - AC_USE_SYSTEM_EXTENSIONS - AC_LANG_POP([C]) - AX_RESTORE_FLAGS - ]) -#PROTECT_AC_USE_SYSTEM_EXTENSIONS - AC_CONFIG_MACRO_DIR([m4]) -AC_CONFIG_HEADERS([config.h:config.in])dnl Keep filename to 8.3 for MS-DOS. +AM_INIT_AUTOMAKE([1.11 -Wall -Werror -Wno-portability foreign tar-ustar subdir-objects no-define color-tests]) +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) -#shared library versioning -WOLFSSL_LIBRARY_VERSION=0:2:0 -# | | | -# +------+ | +---+ -# | | | -# current:revision:age -# | | | -# | | +- increment if interfaces have been added -# | | set to zero if interfaces have been removed -# | | or changed -# | +- increment if source code has changed -# | set to zero if current is incremented -# +- increment if interfaces have been added, removed or changed -AC_SUBST([WOLFSSL_LIBRARY_VERSION]) +AC_ARG_PROGRAM -# capture user C_EXTRA_FLAGS from ./configure line, CFLAGS may hold -g -O2 even -# if user doesn't override, no way to tell -USER_C_EXTRA_FLAGS="$C_EXTRA_FLAGS" +AC_CONFIG_HEADERS([config.h:config.in]) LT_PREREQ([2.2]) -LT_INIT([disable-static],[win32-dll]) -LT_LANG([C++]) -LT_LANG([C]) +LT_INIT([disable-static win32-dll]) + +#shared library versioning +WOLFSSL_LIBRARY_VERSION=25:0:1 +# | | | +# +------+ | +---+ +# | | | +# current:revision:age +# | | | +# | | +- increment if interfaces have been added +# | | set to zero if interfaces have been removed +# | | or changed +# | +- increment if source code has changed +# | set to zero if current is incremented +# +- increment if interfaces have been added, removed or changed +AC_SUBST([WOLFSSL_LIBRARY_VERSION]) + +# Capture user C_EXTRA_FLAGS from configure line. +# Use of C_EXTRA_FLAGS is deprecated because CFLAGS was fixed but someone +# might still be using it. +CFLAGS="$CFLAGS $C_EXTRA_FLAGS $C_FLAGS" gl_VISIBILITY AS_IF([ test -n "$CFLAG_VISIBILITY" ], [ - AM_CPPFLAGS="$AM_CPPFLAGS $CFLAG_VISIBILITY" - CPPFLAGS="$CPPFLAGS $CFLAG_VISIBILITY" + AM_CFLAGS="$AM_CPPFLAGS $CFLAG_VISIBILITY" ]) -m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) -AC_CHECK_FUNCS([gethostbyname]) -AC_CHECK_FUNCS([getaddrinfo]) -AC_CHECK_FUNCS([gettimeofday]) -AC_CHECK_FUNCS([inet_ntoa]) -AC_CHECK_FUNCS([memset]) -AC_CHECK_FUNCS([socket]) -AC_CHECK_HEADERS([arpa/inet.h]) -AC_CHECK_HEADERS([fcntl.h]) -AC_CHECK_HEADERS([limits.h]) -AC_CHECK_HEADERS([netdb.h]) -AC_CHECK_HEADERS([netinet/in.h]) -AC_CHECK_HEADERS([stddef.h]) -AC_CHECK_HEADERS([sys/ioctl.h]) -AC_CHECK_HEADERS([sys/socket.h]) -AC_CHECK_HEADERS([sys/time.h]) -AC_CHECK_HEADERS([errno.h]) -AC_CHECK_LIB(network,socket) -AC_CHECK_SIZEOF(long long, 8) -AC_CHECK_SIZEOF(long, 4) -AC_CHECK_TYPES(__uint128_t) +# Moved these size of and type checks before the library checks. +# The library checks add the library to subsequent test compiles +# and in some rare cases, the networking check causes these sizeof +# checks to fail. +AC_CHECK_SIZEOF([long long]) +AC_CHECK_SIZEOF([long]) +AC_CHECK_SIZEOF([time_t]) +AC_CHECK_TYPES([__uint128_t]) +AC_CHECK_FUNCS([gethostbyname getaddrinfo gettimeofday gmtime_r inet_ntoa memset socket]) +AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h stddef.h sys/ioctl.h sys/socket.h sys/time.h errno.h]) +AC_CHECK_LIB([network],[socket]) AC_C_BIGENDIAN -# mktime check takes forever on some systems, if time supported it would be -# highly unusual for mktime to be missing -#AC_FUNC_MKTIME -AC_PROG_CC -AC_PROG_CC_C_O -AC_PROG_CXX AC_PROG_INSTALL AC_TYPE_SIZE_T AC_TYPE_UINT8_T AM_PROG_AS -AM_PROG_CC_C_O LT_LIB_M -OPTIMIZE_CFLAGS="-Os -fomit-frame-pointer" -OPTIMIZE_FAST_CFLAGS="-O2 -fomit-frame-pointer" +OPTIMIZE_CFLAGS="-Os" +OPTIMIZE_FAST_CFLAGS="-O2" OPTIMIZE_HUGE_CFLAGS="-funroll-loops -DTFM_SMALL_SET -DTFM_HUGE_SET" DEBUG_CFLAGS="-g -DDEBUG -DDEBUG_WOLFSSL" +LIB_ADD= +LIB_STATIC_ADD= -thread_ls_on=no # Thread local storage -AX_TLS([ - [AM_CFLAGS="$AM_CFLAGS -DHAVE_THREAD_LS"] - [thread_ls_on=yes] - ] , [:]) - +AX_TLS([thread_ls_on=yes],[thread_ls_on=no]) +AS_IF([test "x$thread_ls_on" = "xyes"],[AM_CFLAGS="$AM_CFLAGS -DHAVE_THREAD_LS"]) # DEBUG AX_DEBUG @@ -117,28 +96,177 @@ AS_IF([test "$ax_enable_debug" = "yes"], [AM_CFLAGS="$AM_CFLAGS -DNDEBUG"]) +# Distro build feature subset (Debian, Ubuntu, etc.) +AC_ARG_ENABLE([distro], + [AS_HELP_STRING([--enable-distro],[Enable wolfSSL distro build (default: disabled)])], + [ ENABLED_DISTRO=$enableval ], + [ ENABLED_DISTRO=no ] + ) +if test "$ENABLED_DISTRO" = "yes" +then + enable_shared=yes + enable_static=yes + enable_all=yes +fi + + +# 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_opensslall=yes + enable_savesession=yes + enable_savecert=yes + enable_atomicuser=yes + enable_pkcallbacks=yes + enable_aesgcm=yes + enable_aesccm=yes + enable_aesctr=yes + enable_aesofb=yes + enable_aescfb=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 + enable_certreq=yes + enable_certext=yes + enable_sep=yes + enable_hkdf=yes + enable_dsa=yes + enable_ecccustcurves=yes + enable_compkey=yes + enable_curve25519=yes + enable_curve448=yes + enable_ed25519=yes + enable_fpecc=yes + enable_eccencrypt=yes + enable_psk=yes + enable_idea=yes + enable_cmac=yes + enable_xts=yes + enable_webserver=yes + enable_hc128=yes + enable_rabbit=yes + enable_ocsp=yes + enable_ocspstapling=yes + enable_ocspstapling2=yes + enable_crl=yes + enable_crl_monitor=yes + enable_sni=yes + enable_maxfragment=yes + enable_alpn=yes + enable_truncatedhmac=yes + enable_trusted_ca=yes + enable_supportedcurves=yes + 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_openvpn=yes + enable_asio=yes + enable_libwebsockets=yes + enable_qt=yes + enable_pwdbased=yes + enable_aeskeywrap=yes + enable_x963kdf=yes + enable_scrypt=yes + enable_indef=yes + enable_enckeys=yes + enable_hashflags=yes + enable_dhdefaultparams=yes + + # Enable AES Decrypt, AES ECB, Alt Names, DER Load, Keep Certs, CRL IO with Timeout + AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_DECRYPT -DHAVE_AES_ECB -DWOLFSSL_ALT_NAMES -DWOLFSSL_DER_LOAD -DKEEP_OUR_CERT -DKEEP_PEER_CERT -DHAVE_CRL_IO -DHAVE_IO_TIMEOUT" + + # Enable DH const table speedups (eliminates `-lm` math lib dependency) + AM_CFLAGS="$AM_CFLAGS -DHAVE_FFDHE_2048 -DHAVE_FFDHE_3072 -DFP_MAX_BITS=8192" + + # Enable multiple attribute additions such as DC + AM_CFLAGS="-DWOLFSSL_MULTI_ATTRIB $AM_CFLAGS" +fi + + +# Support for forcing 32-bit mode +# To force 32-bit instructions use: +# ./configure CFLAGS="-m32" LDFLAGS="-m32" && make +# The checks for sizeof long and long/long are run at the top of configure and require "-m32" to be set directly in the ./configure statement. +AC_ARG_ENABLE([32bit], + [AS_HELP_STRING([--enable-32bit],[Enables 32-bit support (default: disabled)])], + [ ENABLED_32BIT=$enableval ], + [ ENABLED_32BIT=no ] + ) + +# 16-bit compiler support +AC_ARG_ENABLE([16bit], + [AS_HELP_STRING([--enable-16bit],[Enables 16-bit support (default: disabled)])], + [ ENABLED_16BIT=$enableval ], + [ ENABLED_16BIT=no ] + ) +if test "$ENABLED_16BIT" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWC_16BIT_CPU" +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 + + # 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 ]) AS_IF([ test "x$ENABLED_SINGLETHREADED" = "xno" ],[ AX_PTHREAD([ AC_DEFINE([HAVE_PTHREAD], [1], [Define if you have POSIX threads libraries and header files.]) + # If AX_PTHREAD is adding -Qunused-arguments, need to prepend with -Xcompiler libtool will use it. Newer + # versions of clang don't need the -Q flag when using pthreads. + AS_CASE([$PTHREAD_CFLAGS],[-Qunused-arguments*],[PTHREAD_CFLAGS="-Xcompiler $PTHREAD_CFLAGS"]) AM_CFLAGS="-D_POSIX_THREADS $AM_CFLAGS $PTHREAD_CFLAGS" LIBS="$LIBS $PTHREAD_LIBS" ],[ ENABLED_SINGLETHREADED=yes ]) - ]) + ]) AS_IF([ test "x$ENABLED_SINGLETHREADED" = "xyes" ],[ AM_CFLAGS="-DSINGLE_THREADED $AM_CFLAGS" ]) # 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 ] ) @@ -147,106 +275,474 @@ then AM_CFLAGS="-DWOLFSSL_DTLS $AM_CFLAGS" fi +# DTLS change MTU +AC_ARG_ENABLE([dtls-mtu], + [AS_HELP_STRING([--enable-dtls-mtu],[Enable setting the MTU size for wolfSSL DTLS (default: disabled)])], + [ ENABLED_DTLS_MTU=$enableval ], + [ ENABLED_DTLS_MTU=no ] + ) +if test "$ENABLED_DTLS_MTU" = "yes" +then + AM_CFLAGS="-DWOLFSSL_DTLS_MTU $AM_CFLAGS" +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 -DWOLFSSL_TLS13_DRAFT_18 $AM_CFLAGS" +fi + + +# TLS v1.3 Draft 22 +AC_ARG_ENABLE([tls13-draft22], + [AS_HELP_STRING([--enable-tls13-draft22],[Enable wolfSSL TLS v1.3 Draft 22 (default: disabled)])], + [ ENABLED_TLS13_DRAFT22=$enableval ], + [ ENABLED_TLS13_DRAFT22=no ] + ) +if test "$ENABLED_TLS13_DRAFT22" = "yes" +then + AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT -DWOLFSSL_TLS13_DRAFT_22 $AM_CFLAGS" +fi + + +# TLS v1.3 Draft 23 +AC_ARG_ENABLE([tls13-draft23], + [AS_HELP_STRING([--enable-tls13-draft23],[Enable wolfSSL TLS v1.3 Draft 23 (default: disabled)])], + [ ENABLED_TLS13_DRAFT23=$enableval ], + [ ENABLED_TLS13_DRAFT23=no ] + ) +if test "$ENABLED_TLS13_DRAFT23" = "yes" +then + AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT -DWOLFSSL_TLS13_DRAFT_23 $AM_CFLAGS" +fi + + +# TLS v1.3 Draft 26 +AC_ARG_ENABLE([tls13-draft26], + [AS_HELP_STRING([--enable-tls13-draft26],[Enable wolfSSL TLS v1.3 Draft 26 (default: disabled)])], + [ ENABLED_TLS13_DRAFT26=$enableval ], + [ ENABLED_TLS13_DRAFT26=no ] + ) +if test "$ENABLED_TLS13_DRAFT26" = "yes" +then + AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT -DWOLFSSL_TLS13_DRAFT_26 $AM_CFLAGS" +fi + + +# TLS v1.3 Draft 28 +AC_ARG_ENABLE([tls13-draft28], + [AS_HELP_STRING([--enable-tls13-draft28],[Enable wolfSSL TLS v1.3 Draft 28 (default: disabled)])], + [ ENABLED_TLS13_DRAFT28=$enableval ], + [ ENABLED_TLS13_DRAFT28=no ] + ) +if test "$ENABLED_TLS13_DRAFT28" = "yes" +then + AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT $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" || test "$ENABLED_TLS13_DRAFT22" = "yes" || test "$ENABLED_TLS13_DRAFT23" = "yes" || test "$ENABLED_TLS13_DRAFT26" = "yes" || test "$ENABLED_TLS13_DRAFT28" = "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 + + +# 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 + + +# Hello Retry Request Cookie +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 + + +# 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 + + +# DTLS-SCTP +AC_ARG_ENABLE([sctp], + [AS_HELP_STRING([--enable-sctp],[Enable wolfSSL DTLS-SCTP support (default: disabled)])], + [ENABLED_SCTP=$enableval], + [ENABLED_SCTP=no]) + +AS_IF([test "x$ENABLED_SCTP" = "xyes"], + [AC_MSG_CHECKING([for SCTP]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( +[[ +#include +#include +]], +[[int s = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); if (s == -1) return 1;]])], +[AC_MSG_RESULT(yes)], +[AC_MSG_RESULT(no) + AC_MSG_ERROR([SCTP not available, remove enable-sctp from configure])]) +]) + + +# DTLS-MULTICAST +AC_ARG_ENABLE([mcast], + [AS_HELP_STRING([--enable-mcast],[Enable wolfSSL DTLS multicast support (default: disabled)])], + [ENABLED_MCAST=$enableval], + [ENABLED_MCAST=no]) + + +# List of open source project defines using our openssl compatibility layer: +# openssh (--enable-openssh) WOLFSSL_OPENSSH +# openvpn (--enable-openvpn) +# nginix (--enable-nginx) WOLFSSL_NGINX +# haproxy (--enable-haproxy) WOLFSSL_HAPROXY +# wpa_supplicant (--enable-wpas) WOLFSSL_WPAS +# ssl fortress (--enable-fortress) FORTRESS +# ssl bump (--enable-bump) +# signal (--enable-signal) +# lighty (--enable-lighty) HAVE_LIGHTY +# stunnel (--enable-stunnel) HAVE_STUNNEL +# asio (--enable-asio) WOLFSSL_ASIO +# libwebsockets (--enable-libwebsockets) WOLFSSL_LIBWEBSOCKETS +# qt (--enable-qt) WOLFSSL_QT +# qt test (--enable-qt-test) WOLFSSL_QT_TEST +# HAVE_POCO_LIB +# WOLFSSL_MYSQL_COMPATIBLE +# web server (--enable-webserver) HAVE_WEBSERVER + + +# OpenSSH compatibility Build +AC_ARG_ENABLE([openssh], + [AS_HELP_STRING([--enable-openssh],[Enable OpenSSH compatibility build (default: disabled)])], + [ENABLED_OPENSSH=$enableval], + [ENABLED_OPENSSH=no]) + +# OpenVPN compatibility Build +AC_ARG_ENABLE([openvpn], + [AS_HELP_STRING([--enable-openvpn],[Enable OpenVPN compatibility build (default: disabled)])], + [ENABLED_OPENVPN=$enableval], + [ENABLED_OPENVPN=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 ] + ) + +# wpa_supplicant support +AC_ARG_ENABLE([wpas], + [AS_HELP_STRING([--enable-wpas],[Enable wpa_supplicant support (default: disabled)])], + [ ENABLED_WPAS=$enableval ], + [ ENABLED_WPAS=no ] + ) + +# wpa_supplicant support +AC_ARG_ENABLE([wpas-dpp], + [AS_HELP_STRING([--enable-wpas-dpp],[Enable wpa_supplicant support with dpp (default: disabled)])], + [ ENABLED_WPAS_DPP=$enableval ], + [ ENABLED_WPAS_DPP=no ] + ) + +if test "$ENABLED_WPAS_DPP" = "yes" +then + ENABLED_WPAS="yes" +fi + +# Fortress build +AC_ARG_ENABLE([fortress], + [AS_HELP_STRING([--enable-fortress],[Enable SSL fortress build (default: disabled)])], + [ ENABLED_FORTRESS=$enableval ], + [ ENABLED_FORTRESS=no ] + ) + +# libwebsockets Support +AC_ARG_ENABLE([libwebsockets], + [AS_HELP_STRING([--enable-libwebsockets],[Enable libwebsockets (default: disabled)])], + [ ENABLED_LIBWEBSOCKETS=$enableval ], + [ ENABLED_LIBWEBSOCKETS=no ] + ) +if test "$ENABLED_LIBWEBSOCKETS" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LIBWEBSOCKETS -DOPENSSL_NO_EC" +fi + + +if test "$ENABLED_OPENSSH" = "yes" +then + ENABLED_FORTRESS="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_OPENSSH -DHAVE_EX_DATA -DWOLFSSL_BASE16" +fi + +#Qt Support +AC_ARG_ENABLE([qt], + [AS_HELP_STRING([--enable-qt],[Enable qt (default: disabled)])], + [ ENABLED_QT=$enableval ], + [ ENABLED_QT=no ] + ) + +# ssl bump build +AC_ARG_ENABLE([bump], + [AS_HELP_STRING([--enable-bump],[Enable SSL Bump build (default: disabled)])], + [ ENABLED_BUMP=$enableval ], + [ ENABLED_BUMP=no ] + ) + +# SNIFFER +AC_ARG_ENABLE([sniffer], + [AS_HELP_STRING([--enable-sniffer],[Enable wolfSSL sniffer support (default: disabled)])], + [ ENABLED_SNIFFER=$enableval ], + [ ENABLED_SNIFFER=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 Compatibility ALL +AC_ARG_ENABLE([opensslall], +[AS_HELP_STRING([--enable-opensslall],[Enable all OpenSSL API, size++ (default: disabled)])], +[ ENABLED_OPENSSLALL=$enableval ], +[ ENABLED_OPENSSLALL=no ] +) +if test "$ENABLED_LIBWEBSOCKETS" = "yes" || test "$ENABLED_OPENVPN" = "yes" || test "$ENABLED_WPAS_DPP" = "yes" +then + ENABLED_OPENSSLALL="yes" +fi + +if test "$ENABLED_OPENSSLALL" = "yes" +then +AM_CFLAGS="-DOPENSSL_ALL -DWOLFSSL_EITHER_SIDE -DWC_RSA_NO_PADDING -DWC_RSA_PSS $AM_CFLAGS" +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_OPENSSLEXTRA" = "yes" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" || test "$ENABLED_SIGNAL" = "yes" || test "$ENABLED_WPAS" = "yes" || test "$ENABLED_FORTRESS" = "yes" || test "$ENABLED_BUMP" = "yes" || test "$ENABLED_SNIFFER" = "yes" || test "$ENABLED_OPENSSLALL" = "yes" || test "$ENABLED_LIBWEBSOCKETS" = "yes" then - AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" + ENABLED_OPENSSLEXTRA="yes" +fi + +if test "$ENABLED_OPENSSLEXTRA" = "yes" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" +then + AM_CFLAGS="-DOPENSSL_EXTRA -DWOLFSSL_ALWAYS_VERIFY_CB $AM_CFLAGS" + AM_CFLAGS="-DWOLFSSL_VERIFY_CB_ALL_CERTS -DWOLFSSL_EXTRA_ALERTS $AM_CFLAGS" fi if test "$ENABLED_OPENSSLEXTRA" = "yes" && test "$ENABLED_SMALL" = "yes" then - AC_MSG_ERROR([cannot enable small and opensslextra, only one or the other.]) + AC_MSG_ERROR([cannot enable small and opensslextra, only one or the other.]) fi +if test "$ENABLED_OPENSSLEXTRA" = "x509small" +then + AC_MSG_NOTICE([Enabling only a subset of X509 opensslextra]) + AM_CFLAGS="-DOPENSSL_EXTRA_X509_SMALL $AM_CFLAGS" + AM_CFLAGS="-DWOLFSSL_EKU_OID -DWOLFSSL_MULTI_ATTRIB $AM_CFLAGS" +fi # High Strength Build AC_ARG_ENABLE([maxstrength], - [AS_HELP_STRING([--enable-maxstrength],[Enable Max Strengh build, allows TLSv1.2-AEAD-PFS ciphers only (default: disabled)])], + [AS_HELP_STRING([--enable-maxstrength],[Enable Max Strength build, allows TLSv1.2-AEAD-PFS ciphers only (default: disabled)])], [ENABLED_MAXSTRENGTH=$enableval], [ENABLED_MAXSTRENGTH=no]) +# Harden, enable Timing Resistance and Blinding by default +AC_ARG_ENABLE([harden], + [AS_HELP_STRING([--enable-harden],[Enable Hardened build, Enables Timing Resistance and Blinding (default: enabled)])], + [ENABLED_HARDEN=$enableval], + [ENABLED_HARDEN=yes]) + +if test "$ENABLED_HARDEN" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DTFM_TIMING_RESISTANT -DECC_TIMING_RESISTANT" + if test "$ENABLED_RNG" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DWC_RSA_BLINDING" + fi +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"]) +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" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT -DWOLFSSL_DER_LOAD" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KEY_GEN -DWOLFSSL_DES_ECB" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WPAS" +fi -# Fortress build -AC_ARG_ENABLE([fortress], - [ --enable-fortress Enable SSL fortress build (default: disabled)], - [ ENABLED_FORTRESS=$enableval ], - [ ENABLED_FORTRESS=no ] - ) 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 -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)], - [ ENABLED_BUMP=$enableval ], - [ ENABLED_BUMP=no ] - ) - if test "$ENABLED_BUMP" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DLARGE_STATIC_BUFFERS -DWOLFSSL_CERT_GEN -DWOLFSSL_KEY_GEN -DHUGE_SESSION_CACHE -DOPENSSL_EXTRA -DFP_MAX_BITS=8192 -DWOLFSSL_DER_LOAD -DWOLFSSL_ALT_NAMES -DWOLFSSL_TEST_CERT" + AM_CFLAGS="$AM_CFLAGS -DLARGE_STATIC_BUFFERS -DWOLFSSL_CERT_GEN -DWOLFSSL_KEY_GEN -DHUGE_SESSION_CACHE -DFP_MAX_BITS=8192 -DWOLFSSL_DER_LOAD -DWOLFSSL_ALT_NAMES -DWOLFSSL_TEST_CERT" fi ENABLED_SLOWMATH="yes" -# lean psk build +# 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 -DHAVE_NULL_CIPHER -DSINGLE_THREADED -DNO_AES -DNO_FILESYSTEM -DNO_RABBIT -DNO_RSA -DNO_DSA -DNO_DH -DNO_CERTS -DNO_PWDBASED -DNO_DES3 -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"]) - -# big cache -AC_ARG_ENABLE([bigcache], - [ --enable-bigcache Enable big session cache (default: disabled)], - [ ENABLED_BIGCACHE=$enableval ], - [ ENABLED_BIGCACHE=no ] +# lean TLS build (TLS 1.2 client only (no client auth), ECC256, AES128 and SHA256 w/o Shamir) +AC_ARG_ENABLE([leantls], + [AS_HELP_STRING([--enable-leantls],[Enable Lean TLS build (default: disabled)])], + [ ENABLED_LEANTLS=$enableval ], + [ ENABLED_LEANTLS=no ] ) -if test "$ENABLED_BIGCACHE" = "yes" +if test "$ENABLED_LEANTLS" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DBIG_SESSION_CACHE" + 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 -DNO_WOLFSSL_CM_VERIFY" + enable_lowresource=yes +fi + + +# 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 -DALT_ECC_SIZE -DGCM_SMALL -DCURVE25519_SMALL -DED25519_SMALL -DWOLFSSL_SMALL_CERT_VERIFY" + + # low flash flags + AM_CFLAGS="$AM_CFLAGS -DUSE_SLOW_SHA -DUSE_SLOW_SHA256 -DUSE_SLOW_SHA512" +fi + + +# TITAN cache +AC_ARG_ENABLE([titancache], + [AS_HELP_STRING([--enable-titancache],[Enable titan session cache (default: disabled)])], + [ ENABLED_TITANCACHE=$enableval ], + [ ENABLED_TITANCACHE=no ] + ) + +if test "$ENABLED_TITANCACHE" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DTITAN_SESSION_CACHE" 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 ] ) @@ -257,9 +753,22 @@ then fi +# big cache +AC_ARG_ENABLE([bigcache], + [AS_HELP_STRING([--enable-bigcache],[Enable big session cache (default: disabled)])], + [ ENABLED_BIGCACHE=$enableval ], + [ ENABLED_BIGCACHE=no ] + ) + +if test "$ENABLED_BIGCACHE" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DBIG_SESSION_CACHE" +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 ] ) @@ -270,9 +779,9 @@ then fi -# Persistent session cache +# 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 ] ) @@ -283,9 +792,9 @@ then fi -# Persistent cert cache +# 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 ] ) @@ -296,9 +805,22 @@ then fi -# Atomic User Record Layer +# 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 ] ) @@ -309,9 +831,9 @@ then fi -# Public Key Callbacks +# 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 ] ) @@ -322,14 +844,50 @@ then fi -# SNIFFER -AC_ARG_ENABLE([sniffer], - [AS_HELP_STRING([--enable-sniffer],[Enable wolfSSL sniffer support (default: disabled)])], - [ ENABLED_SNIFFER=$enableval ], - [ ENABLED_SNIFFER=no ] - ) +# Microchip/Atmel CryptoAuthLib +ENABLED_CRYPTOAUTHLIB="no" +trylibatcadir="" +AC_ARG_WITH([cryptoauthlib], + [AS_HELP_STRING([--with-cryptoauthlib=PATH],[PATH to CryptoAuthLib install (default /usr/)])], + [ + AC_MSG_CHECKING([for cryptoauthlib]) + CPPFLAGS="$CPPFLAGS -DWOLFSSL_ATECC508A" + LIBS="$LIBS -lcryptoauth" -# sniffer does't work in maxstrength mode + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ atcab_init(0); ]])],[ libatca_linked=yes ],[ libatca_linked=no ]) + + if test "x$libatca_linked" = "xno" ; then + if test "x$withval" != "xno" ; then + trylibatcadir=$withval + fi + if test "x$withval" = "xyes" ; then + trylibatcadir="/usr" + fi + + LDFLAGS="$LDFLAGS -L$trylibatcadir/lib" + CPPFLAGS="$CPPFLAGS -I$trylibatcadir/lib" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ atcab_init(0); ]])],[ libatca_linked=yes ],[ libatca_linked=no ]) + + if test "x$libatca_linked" = "xno" ; then + AC_MSG_ERROR([cryptoauthlib isn't found. + If it's already installed, specify its path using --with-cryptoauthlib=/dir/]) + fi + + AM_LDFLAGS="$AM_LDFLAGS -L$trylibatcadir/lib" + AM_CFLAGS="$AM_CFLAGS -I$trylibatcadir/lib" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([yes]) + fi + + ENABLED_CRYPTOAUTHLIB="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ATECC508A" + ] +) + + +# sniffer doesn't work in maxstrength mode if test "$ENABLED_SNIFFER" = "yes" && test "$ENABLED_MAXSTRENGTH" = "yes" then AC_MSG_ERROR([cannot enable maxstrength in sniffer mode.]) @@ -338,15 +896,27 @@ fi ENABLED_SNIFFTEST=no AS_IF([ test "x$ENABLED_SNIFFER" = "xyes" ], [ - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SNIFFER -DOPENSSL_EXTRA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SNIFFER" AC_CHECK_HEADERS([pcap/pcap.h], [ ENABLED_SNIFFTEST=yes ], [ AC_MSG_WARN([cannot enable sniffer test without having libpcap available.]) ] ) ]) -AM_CONDITIONAL([BUILD_SNIFFER], [ test "x$ENABLED_SNIFFER" = "xyes" ]) -AM_CONDITIONAL([BUILD_SNIFFTEST], [ test "x$ENABLED_SNIFFTEST" = "xyes" ]) + +# AES-CBC +AC_ARG_ENABLE([aescbc], + [AS_HELP_STRING([--enable-aescbc],[Enable wolfSSL AES-CBC support (default: enabled)])], + [ ENABLED_AESCBC=$enableval ], + [ ENABLED_AESCBC=yes ] + ) + +if test "$ENABLED_AESCBC" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DNO_AES_CBC" +fi + +# leanpsk and leantls don't need gcm # AES-GCM AC_ARG_ENABLE([aesgcm], @@ -355,41 +925,40 @@ AC_ARG_ENABLE([aesgcm], [ ENABLED_AESGCM=yes ] ) -# lean psk does't need gcm -if test "$ENABLED_LEANPSK" = "yes" +# leanpsk and leantls don't need gcm +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 -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 ] ) @@ -399,10 +968,111 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_AESCCM" 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_OPENVPN" = "yes" +then + ENABLED_AESCTR=yes +fi + +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-NI +# AES-OFB +AC_ARG_ENABLE([aesofb], + [AS_HELP_STRING([--enable-aesofb],[Enable wolfSSL AES-OFB support (default: disabled)])], + [ ENABLED_AESOFB=$enableval ], + [ ENABLED_AESOFB=no ] + ) + +if test "$ENABLED_AESOFB" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_OFB -DWOLFSSL_AES_DIRECT" +fi + + +# AES-CFB +AC_ARG_ENABLE([aescfb], + [AS_HELP_STRING([--enable-aescfb],[Enable wolfSSL AES-CFB support (default: disabled)])], + [ ENABLED_AESCFB=$enableval ], + [ ENABLED_AESCFB=no ] + ) + +if test "$ENABLED_AESCFB" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_CFB" +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" && test "$ENABLED_ASM" = "yes" +then + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_ARMASM" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ARMASM -DWOLFSSL_NO_HASH_RAW" + #Check if mcpu and mfpu values already set if not use default + case $CPPFLAGS in + *mcpu* | *mfpu*) + break;; #Do not override user set values + *) + case $host_cpu in + *aarch64*) + # +crypto needed for hardware acceleration + AM_CPPFLAGS="$AM_CPPFLAGS -mcpu=generic+crypto" + + # Check for and set -mstrict-align compiler flag + # Used to set assumption that Aarch64 systems will not handle + # unaligned memory references. The flag -mstrict-align is needed + # on some compiler versions to avoid an invalid addressing mode + # error with "m" constraint variables in the inline assembly AES + # code. Even though unaligned load/store access is permitted on + # normal memory with Cortex-A series boards with the exception + # being exclusive and ordered access. + case $CPPFLAGS in + *mstrict-align*) + break;; # already set by user + *) + AM_CPPFLAGS="$AM_CPPFLAGS -mstrict-align" + AC_MSG_NOTICE([64bit ARMv8, setting -mstrict-align]);; + esac + AC_MSG_NOTICE([64bit ARMv8 found, setting mcpu to generic+crypto]);; + *) + AM_CPPFLAGS="$AM_CPPFLAGS -mfpu=crypto-neon-fp-armv8" + AC_MSG_NOTICE([32bit ARMv8 found, setting mfpu to crypto-neon-fp-armv8]);; + esac + esac +fi + + +# 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 + + +# INTEL AES-NI AC_ARG_ENABLE([aesni], [AS_HELP_STRING([--enable-aesni],[Enable wolfSSL AES-NI support (default: disabled)])], [ ENABLED_AESNI=$enableval ], @@ -416,32 +1086,153 @@ 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" + 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 - AM_CFLAGS="$AM_CFLAGS -maes -msse4" + # 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 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"]) + +# Linux af_alg +AC_ARG_ENABLE([afalg], + [AS_HELP_STRING([--enable-afalg],[Enable Linux af_alg use for crypto (default: disabled)])], + [ ENABLED_AFALG=$enableval ], + [ ENABLED_AFALG=no ] + ) + +if test "$ENABLED_AFALG" = "yes" +then + if test "$ENABLED_AESCCM" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_HASH" +fi + +if test "$ENABLED_AFALG" = "xilinx" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX -DWOLFSSL_AFALG_XILINX_AES" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX_SHA3 -DWOLFSSL_AFALG_XILINX_RSA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NOSHA3_224 -DWOLFSSL_NOSHA3_256 -DWOLFSSL_NOSHA3_512 -DWOLFSSL_NO_SHAKE256" + ENABLED_AFALG="yes" + ENABLED_XILINX="yes" +fi + +if test "$ENABLED_AFALG" = "xilinx-aes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX -DWOLFSSL_AFALG_XILINX_AES" + ENABLED_AFALG="yes" + ENABLED_XILINX="yes" +fi + +if test "$ENABLED_AFALG" = "xilinx-sha3" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX_SHA3" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NOSHA3_224 -DWOLFSSL_NOSHA3_256 -DWOLFSSL_NOSHA3_512 -DWOLFSSL_NO_SHAKE256" + ENABLED_AFALG="yes" + ENABLED_XILINX="yes" +fi + +if test "$ENABLED_AFALG" = "xilinx-rsa" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_XILINX_RSA" + ENABLED_AFALG="yes" + ENABLED_XILINX="yes" +fi + + +# Support for Linux dev/crypto calls +AC_ARG_ENABLE([devcrypto], + [AS_HELP_STRING([--enable-devcrypto],[Enable Linux dev crypto calls: all | aes (all aes support) | hash (all hash algos) | cbc (aes-cbc only) (default: disabled)])], + [ ENABLED_DEVCRYPTO=$enableval ], + [ ENABLED_DEVCRYPTO=no ] + ) + +if test "$ENABLED_DEVCRYPTO" = "yes" || test "$ENABLED_DEVCRYPTO" = "all" +then + #enable all devcrypto supported algorithms + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_CBC" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_AES" + if test "$ENABLED_AESCCM" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_HASH" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_HASH_RAW" + ENABLED_DEVCRYPTO=yes +fi +if test "$ENABLED_DEVCRYPTO" = "aes" +then + #enable only AES-CBC algorithm support + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_AES" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_CBC" + if test "$ENABLED_AESCCM" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT" + fi + ENABLED_DEVCRYPTO=yes +fi +if test "$ENABLED_DEVCRYPTO" = "cbc" +then + #enable only AES-CBC algorithm support + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_CBC" + ENABLED_DEVCRYPTO=yes +fi +if test "$ENABLED_DEVCRYPTO" = "hash" +then + #enable only hash algorithm support + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_HASH" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_HASH_RAW" + ENABLED_DEVCRYPTO=yes +fi # 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 ] ) @@ -451,12 +1242,10 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_CAMELLIA" fi -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 ] ) @@ -471,16 +1260,19 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MD2" fi -AM_CONDITIONAL([BUILD_MD2], [test "x$ENABLED_MD2" = "xyes"]) - -# NULL CIPHER +# 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 ] ) +if test "$ENABLED_OPENSSH" = "yes" +then + ENABLED_NULL_CIPHER="yes" +fi + if test "$ENABLED_NULL_CIPHER" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_NULL_CIPHER" @@ -488,75 +1280,114 @@ 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 ] ) +if test "$ENABLED_OPENSSH" = "yes" +then + ENABLED_RIPEMD="yes" +fi + if test "$ENABLED_RIPEMD" = "yes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_RIPEMD" fi -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 BLAKE2b support (default: disabled)])], [ ENABLED_BLAKE2=$enableval ], [ ENABLED_BLAKE2=no ] ) if test "$ENABLED_BLAKE2" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DHAVE_BLAKE2" + AM_CFLAGS="$AM_CFLAGS -DHAVE_BLAKE2 -DHAVE_BLAKE2B" fi -AM_CONDITIONAL([BUILD_BLAKE2], [test "x$ENABLED_BLAKE2" = "xyes"]) +AC_ARG_ENABLE([blake2s], + [AS_HELP_STRING([--enable-blake2s],[Enable wolfSSL BLAKE2s support (default: disabled)])], + [ ENABLED_BLAKE2S=$enableval ], + [ ENABLED_BLAKE2S=Sno ] + ) -# set sha512 default -SHA512_DEFAULT=no -if test "$host_cpu" = "x86_64" +if test "$ENABLED_BLAKE2S" = "yes" then -SHA512_DEFAULT=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_BLAKE2S" + ENABLED_BLAKE2="yes" fi + # SHA512 AC_ARG_ENABLE([sha512], - [AS_HELP_STRING([--enable-sha512],[Enable wolfSSL SHA-512 support (default: enabled on x86_64)])], + [AS_HELP_STRING([--enable-sha512],[Enable wolfSSL SHA-512 support (default: enabled)])], [ ENABLED_SHA512=$enableval ], - [ ENABLED_SHA512=$SHA512_DEFAULT ] + [ ENABLED_SHA512=yes ] ) -# lean psk does't need sha512 -if test "$ENABLED_LEANPSK" = "yes" +# options that don't require sha512 +if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" || test "$ENABLED_32BIT" = "yes" || test "$ENABLED_16BIT" = "yes" then - ENABLED_SHA512=no + ENABLED_SHA512="no" +fi + +# options that require sha512 +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_WPAS" = "yes" || test "$ENABLED_FORTRESS" = "yes" +then + ENABLED_SHA512="yes" + ENABLED_SHA384="yes" fi if test "$ENABLED_SHA512" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512 -DWOLFSSL_SHA384" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512" fi -if test "$ENABLED_FORTRESS" = "yes" + +# SHA384 +AC_ARG_ENABLE([sha384], + [AS_HELP_STRING([--enable-sha384],[Enable wolfSSL SHA-384 support (default: enabled)])], + [ ENABLED_SHA384=$enableval ], + [ ENABLED_SHA384=yes ] + ) + +# options that don't require sha384 +if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" || test "$ENABLED_32BIT" = "yes" || test "$ENABLED_16BIT" = "yes" then - ENABLED_SHA512="yes" + ENABLED_SHA384="no" fi - -AM_CONDITIONAL([BUILD_SHA512], [test "x$ENABLED_SHA512" = "xyes"]) +# options that require sha384 +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_WPAS" = "yes" || test "$ENABLED_FORTRESS" = "yes" +then + ENABLED_SHA384="yes" +fi +if test "$ENABLED_SHA384" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA384" +fi # 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" || test "x$ENABLED_OPENVPN" = "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" @@ -565,7 +1396,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 ] ) @@ -578,10 +1409,14 @@ 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 ] ) +if test "$ENABLED_OPENVPN" = "yes" +then + ENABLED_CERTGEN=yes +fi if test "$ENABLED_CERTGEN" = "yes" then @@ -591,7 +1426,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 ] ) @@ -606,9 +1441,39 @@ then fi +# CERT REQUEST EXTENSION +AC_ARG_ENABLE([certext], + [AS_HELP_STRING([--enable-certext],[Enable cert request extensions (default: disabled)])], + [ ENABLED_CERTEXT=$enableval ], + [ ENABLED_CERTEXT=no ] + ) +if test "$ENABLED_OPENVPN" = "yes" +then + ENABLED_CERTEXT=yes +fi + +if test "$ENABLED_CERTEXT" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" +fi + + +# DECODED CERT CACHE +AC_ARG_ENABLE([certgencache], + [AS_HELP_STRING([--enable-certgencache],[Enable decoded cert caching (default: disabled)])], + [ ENABLED_certgencache=$enableval ], + [ ENABLED_certgencache=no ] + ) + +if test "$ENABLED_certgencache" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN_CACHE" +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 ] ) @@ -618,70 +1483,134 @@ then fi -# HKDF +# 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" fi +# X9.63 KDF +AC_ARG_ENABLE([x963kdf], + [AS_HELP_STRING([--enable-x963kdf],[Enable X9.63 KDF support (default: disabled)])], + [ ENABLED_X963KDF=$enableval ], + [ ENABLED_X963KDF=no ] + ) +if test "$ENABLED_X963KDF" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_X963_KDF" +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_DSA" = "no" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" || test "$ENABLED_WPAS" = "yes" || test "$ENABLED_QT" = "yes" +then + ENABLED_DSA="yes" +fi + +if test "$ENABLED_DSA" = "no" && test "$ENABLED_OPENSSH" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_DSA" fi -AM_CONDITIONAL([BUILD_DSA], [test "x$ENABLED_DSA" = "xyes"]) +# ECC Shamir +AC_ARG_ENABLE([eccshamir], + [AS_HELP_STRING([--enable-eccshamir],[Enable ECC Shamir (default: enabled)])], + [ ENABLED_ECC_SHAMIR=$enableval ], + [ ENABLED_ECC_SHAMIR=yes ] + ) -# set ecc default -ECC_DEFAULT=no - -if test "$host_cpu" = "x86_64" -then -ECC_DEFAULT=yes -fi - # ECC AC_ARG_ENABLE([ecc], - [AS_HELP_STRING([--enable-ecc],[Enable ECC (default: enabled on x86_64)])], + [AS_HELP_STRING([--enable-ecc],[Enable ECC (default: enabled)])], [ ENABLED_ECC=$enableval ], - [ ENABLED_ECC=$ECC_DEFAULT ] + [ ENABLED_ECC=yes ] ) -# lean psk does't need ecc +# lean psk doesn't need ecc if test "$ENABLED_LEANPSK" = "yes" then ENABLED_ECC=no fi -if test "$ENABLED_ECC" = "yes" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" || test "$ENABLED_SIGNAL" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256 -DECC_SHAMIR" + ENABLED_ECC="yes" fi -AM_CONDITIONAL([BUILD_ECC], [test "x$ENABLED_ECC" = "xyes"]) - - -if test "$ENABLED_ECC" = "yes" && test "$ENABLED_SMALL" = "yes" +if test "$ENABLED_ECC" = "yes" then - AC_MSG_ERROR([cannot enable ecc and small, ecc requires TLS which small turns off.]) + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" + if test "$ENABLED_ECC_SHAMIR" = "yes" && test "$ENABLED_LOWRESOURCE" = "no" + then + AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR" + fi +fi + + +# ECC Custom Curves +AC_ARG_ENABLE([ecccustcurves], + [AS_HELP_STRING([--enable-ecccustcurves],[Enable ECC custom curves (default: disabled)])], + [ ENABLED_ECCCUSTCURVES=$enableval ], + [ ENABLED_ECCCUSTCURVES=no ] + ) + +if test "$ENABLED_ECCCUSTCURVES" != "no" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CUSTOM_CURVES" + + # For distro, all or ecccustcurves=all builds, enable all curve types + if test "$ENABLED_DISTRO" = "yes" || test "$ENABLED_ALL" = "yes" || test "$ENABLED_ECCCUSTCURVES" = "all" + then + # Enable ECC SECPR2, SECPR3, BRAINPOOL and KOBLITZ curves + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ" + + # Enable ECC Cofactor support + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_CDH" + + # If fastmath enabled and on x86 use speedups + if test "x$ENABLED_FASTMATH" = "xyes" && test "$host_cpu" = "x86_64" + then + AM_CFLAGS="$AM_CFLAGS -DTFM_ECC192 -DTFM_ECC224 -DTFM_ECC256 -DTFM_ECC384 -DTFM_ECC521" + fi + fi +fi + + +# Compressed Key +AC_ARG_ENABLE([compkey], + [AS_HELP_STRING([--enable-compkey],[Enable compressed keys support (default: disabled)])], + [ ENABLED_COMPKEY=$enableval ], + [ 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" 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], @@ -691,23 +1620,31 @@ AC_ARG_ENABLE([curve25519], ) -if test "$ENABLED_CURVE25519" = "small" +if test "$ENABLED_OPENSSH" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DCURVED25519_SMALL" - ENABLED_CURVED25519_SMALL=yes - ENABLED_CURVE25519=yes + ENABLED_CURVE25519="yes" fi -if test "$ENABLED_CURVE25519" = "yes" +if test "$ENABLED_CURVE25519" != "no" then + 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" || test "$ENABLED_32BIT" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DNO_CURVED25519_128BIT" + ENABLED_CURVE25519=yes + fi + AM_CFLAGS="$AM_CFLAGS -DHAVE_CURVE25519" ENABLED_FEMATH=yes fi -AM_CONDITIONAL([BUILD_CURVE25519], [test "x$ENABLED_CURVE25519" = "xyes"]) - - # ED25519 AC_ARG_ENABLE([ed25519], [AS_HELP_STRING([--enable-ed25519],[Enable ED25519 (default: disabled)])], @@ -716,15 +1653,21 @@ AC_ARG_ENABLE([ed25519], ) -if test "$ENABLED_ED25519" = "small" +if test "$ENABLED_OPENSSH" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DCURVED25519_SMALL" - ENABLED_CURVED25519_SMALL=yes - ENABLED_ED25519=yes + ENABLED_ED25519="yes" fi -if test "$ENABLED_ED25519" = "yes" +if test "$ENABLED_ED25519" != "no" && test "$ENABLED_32BIT" = "no" then + if test "$ENABLED_ED25519" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DED25519_SMALL" + ENABLED_ED25519_SMALL=yes + ENABLED_CURVE25519_SMALL=yes + ENABLED_ED25519=yes + fi + if test "$ENABLED_SHA512" = "no" then AC_MSG_ERROR([cannot enable ed25519 without enabling sha512.]) @@ -734,14 +1677,72 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_ED25519" fi -AM_CONDITIONAL([BUILD_ED25519], [test "x$ENABLED_ED25519" = "xyes"]) -AM_CONDITIONAL([BUILD_CURVED25519_SMALL], [test "x$ENABLED_CURVED25519_SMALL" = "xyes"]) -AM_CONDITIONAL([BUILD_FEMATH], [test "x$ENABLED_FEMATH" = "xyes"]) -AM_CONDITIONAL([BUILD_GEMATH], [test "x$ENABLED_GEMATH" = "xyes"]) + +# for using memory optimization setting on both curve448 and ed448 +ENABLED_CURVE448_SMALL=no +ENABLED_ED448_SMALL=no + +# CURVE448 +AC_ARG_ENABLE([curve448], + [AS_HELP_STRING([--enable-curve448],[Enable Curve448 (default: disabled)])], + [ ENABLED_CURVE448=$enableval ], + [ ENABLED_CURVE448=no ] + ) + +if test "$ENABLED_CURVE448" != "no" +then + if test "$ENABLED_CURVE448" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DCURVE448_SMALL" + ENABLED_CURVE448_SMALL=yes + ENABLED_CURVE448=yes + fi + + if test "$ENABLED_CURVE448" = "no128bit" || test "$ENABLED_32BIT" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DNO_CURVED448_128BIT" + ENABLED_CURVE448=yes + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_CURVE448" + ENABLED_FE448=yes +fi + +# ED448 +AC_ARG_ENABLE([ed448], + [AS_HELP_STRING([--enable-ed448],[Enable ED448 (default: disabled)])], + [ ENABLED_ED448=$enableval ], + [ ENABLED_ED448=no ] + ) + +if test "$ENABLED_ED448" != "no" && test "$ENABLED_32BIT" = "no" +then + if test "$ENABLED_ED448" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DED448_SMALL" + ENABLED_ED448_SMALL=yes + ENABLED_CURVE448_SMALL=yes + ENABLED_ED448=yes + fi + + if test "$ENABLED_SHA512" = "no" + then + AC_MSG_ERROR([cannot enable ed448 without enabling sha512.]) + fi + ENABLED_FE448=yes + ENABLED_GE448=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_ED448" + + # EdDSA448 requires SHAKE256 which requires SHA-3 + ENABLED_SHAKE3=yes + ENABLED_SHAKE256=yes +fi + + # 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 ] ) @@ -750,7 +1751,7 @@ if test "$ENABLED_FPECC" = "yes" then if test "$ENABLED_ECC" = "no" then - AC_MSG_ERROR([cannot enable fpecc without enabling ecc.]) + AC_MSG_ERROR([cannot enable fpecc without enabling ecc.]) fi AM_CFLAGS="$AM_CFLAGS -DFP_ECC" fi @@ -758,7 +1759,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 ] ) @@ -767,37 +1768,41 @@ if test "$ENABLED_ECC_ENCRYPT" = "yes" then if test "$ENABLED_ECC" = "no" then - AC_MSG_ERROR([cannot enable eccencrypt without enabling ecc.]) + AC_MSG_ERROR([cannot enable eccencrypt without enabling ecc.]) fi if test "$ENABLED_HKDF" = "no" then - AC_MSG_ERROR([cannot enable eccencrypt without enabling hkdf.]) + AC_MSG_ERROR([cannot enable eccencrypt without enabling hkdf.]) fi AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_ENCRYPT" fi -# PSK +# 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 ] ) -if test "$ENABLED_PSK" = "no" && test "$ENABLED_LEANPSK" = "no" +# Single PSK identity +AC_ARG_ENABLE([psk-one-id], + [AS_HELP_STRING([--enable-psk-one-id],[Enable PSK (default: disabled)])], + [ ENABLED_PSK_ONE_ID=$enableval ], + [ ENABLED_PSK_ONE_ID=no ] + ) +if test "$ENABLED_PSK_ONE_ID" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DNO_PSK" + if test "$ENABLED_PSK" = "no" + then + ENABLED_PSK="yes" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_PSK_ONE_ID" fi -if test "$ENABLED_PSK" = "no" && test "$ENABLED_LEANPSK" = "yes" -then - ENABLED_PSK=yes -fi - - # 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 ] ) @@ -806,8 +1811,8 @@ if test "$ENABLED_ERROR_STRINGS" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_ERROR_STRINGS" else - # turn off error strings if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off error strings if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_ERROR_STRINGS" ENABLED_ERROR_STRINGS=no @@ -815,9 +1820,22 @@ else fi -# OLD TLS +# ERROR QUEUE +AC_ARG_ENABLE([errorqueue], + [AS_HELP_STRING([--disable-errorqueue],[Disables adding nodes to error queue when compiled with OPENSSL_EXTRA (default: enabled)])], + [ ENABLED_ERROR_QUEUE=$enableval ], + [ ENABLED_ERROR_QUEUE=yes ] + ) + +if test "$ENABLED_ERROR_QUEUE" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DNO_ERROR_QUEUE" +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 ] ) @@ -826,8 +1844,8 @@ if test "$ENABLED_OLD_TLS" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_OLD_TLS" else - # turn off old if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off old if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_OLD_TLS" ENABLED_OLD_TLS=no @@ -835,9 +1853,53 @@ else fi -# STACK SIZE info for examples +# TLSv1.2 +AC_ARG_ENABLE([tlsv12], + [AS_HELP_STRING([--enable-tlsv12],[Enable TLS versions 1.2 (default: enabled)])], + [ ENABLED_TLSV12=$enableval ], + [ ENABLED_TLSV12=yes ] + ) + +if test "$ENABLED_TLSV12" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_TLS12 -DNO_OLD_TLS" +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)])], + [ ENABLED_SSLV3=$enableval ], + [ ENABLED_SSLV3=no] + ) + +if test "x$ENABLED_HAPROXY" = "xyes" +then + ENABLED_SSLV3="yes" +fi + +if test "$ENABLED_SSLV3" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALLOW_SSLV3" +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 ] ) @@ -846,13 +1908,13 @@ if test "$ENABLED_STACKSIZE" = "yes" then AC_CHECK_FUNC([posix_memalign], [], [AC_MSG_ERROR(stacksize needs posix_memalign)]) AC_CHECK_FUNC([pthread_attr_setstack], [], AC_CHECK_LIB([pthread],[pthread_attr_setstack])) - AM_CFLAGS="$AM_CFLAGS -DHAVE_STACK_SIZE -DWOLFSSL_LOW_MEMORY" + AM_CFLAGS="$AM_CFLAGS -DHAVE_STACK_SIZE" fi -# MEMORY +# 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 ] ) @@ -861,20 +1923,120 @@ if test "$ENABLED_MEMORY" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_WOLFSSL_MEMORY" else - # turn off memory cb if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off memory cb if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then # but don't turn on NO_WOLFSSL_MEMORY because using own ENABLED_MEMORY=no fi 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 + +# MEMORY usage logging +AC_ARG_ENABLE([memorylog], + [AS_HELP_STRING([--enable-memorylog],[Enable dynamic memory logging (default: disabled)])], + [ ENABLED_MEMORYLOG=$enableval ], + [ ENABLED_MEMORYLOG=no ] + ) + +if test "$ENABLED_MEMORYLOG" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MEMORY_LOG" +fi -# RSA +# STACK usage logging +AC_ARG_ENABLE([stacklog], + [AS_HELP_STRING([--enable-stacklog],[Enable stack logging (default: disabled)])], + [ ENABLED_STACKLOG=$enableval ], + [ ENABLED_STACKLOG=no ] + ) + +if test "$ENABLED_STACKLOG" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STACK_LOG -finstrument-functions" +fi + +if test "$ENABLED_QT" = "yes" +then + # Requires opensslextra and opensslall + if test "x$ENABLED_OPENSSLALL" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" + then + ENABLED_OPENSSLALL="yes" + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_EXTRA -DOPENSSL_ALL -DHAVE_EX_DATA" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_QT -DWOLFSSL_ALLOW_TLSV10 -DSESSION_CERTS -DOPENSSL_NO_SSL2" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALLOW_SSLV3 -DWOLFSSL_KEY_GEN -DHAVE_EX_DATA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CUSTOM_CURVES -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ" + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi + + # Requires PSK make sure on + if test "x$ENABLED_PSK" = "xno" + then + ENABLED_PSK="yes" + fi + + # Requires RC4 make sure on + if test "x$ENABLED_ARC4" = "xno" + then + ENABLED_ARC4="yes" + fi + + if test "x$ENABLED_CERTEXT" = "xno" + then + ENABLED_CERTEXT="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" + fi + + if test "x$ENABLED_CERTGEN" = "xno" + then + ENABLED_CERTGEN="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN" + fi + + # requires oldnames disabled + enable_oldnames=no +fi + +AC_ARG_ENABLE([qt-test], + [AS_HELP_STRING([--enable-qt-test],[Enable qt tests (default: disabled)])], + [ ENABLED_QT_TEST=$enableval ], + [ ENABLED_QT_TEST=no ] + ) + +if test "$ENABLED_QT_TEST" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_NO_SSL3 -DWOLFSSL_STATIC_RSA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_PSK" +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 ] ) @@ -883,15 +2045,77 @@ if test "$ENABLED_RSA" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_RSA" else - # turn off RSA if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off RSA if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_RSA" ENABLED_RSA=no fi fi -AM_CONDITIONAL([BUILD_RSA], [test "x$ENABLED_RSA" = "xyes"]) +AC_ARG_ENABLE([oaep], + [AS_HELP_STRING([--enable-oaep],[Enable RSA OAEP (default: enabled)])], + [ ENABLED_OAEP=$enableval ], + [ ENABLED_OAEP=yes ] + ) + +if test "$ENABLED_OAEP" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DWC_NO_RSA_OAEP" +fi + +AC_ARG_ENABLE([rsapub], + [AS_HELP_STRING([--enable-rsapub],[Enable RSA Public Only (default: disabled)])], + [ ENABLED_RSAPUB=$enableval ], + [ ENABLED_RSAPUB=no ] + ) + +if test "$ENABLED_RSAPUB" = "yes" +then + if test "$ENABLED_RSA" = "no" + then + ENABLED_RSA="yes" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_RSA_PUBLIC_ONLY" +fi + +AC_ARG_ENABLE([rsavfy], + [AS_HELP_STRING([--enable-rsavfy],[Enable RSA Verify Inline Only (default: disabled)])], + [ ENABLED_RSAVFY=$enableval ], + [ ENABLED_RSAVFY=no ] + ) + +if test "$ENABLED_RSAVFY" = "yes" +then + if test "$ENABLED_RSA" = "no" + then + ENABLED_RSA="yes" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_RSA_PUBLIC_ONLY -DWOLFSSL_RSA_VERIFY_ONLY" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_RSA_VERIFY_INLINE -DNO_SIG_WRAPPER" +fi + + +# 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 @@ -901,20 +2125,23 @@ AC_ARG_ENABLE([dh], [ ENABLED_DH=yes ] ) +if test "$ENABLED_OPENSSH" = "yes" +then + ENABLED_DH="yes" +fi + if test "$ENABLED_DH" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_DH" else - # turn off DH if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off DH if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_DH" ENABLED_DH=no fi fi -AM_CONDITIONAL([BUILD_DH], [test "x$ENABLED_DH" = "xyes"]) - # Anonymous AC_ARG_ENABLE([anon], @@ -923,7 +2150,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" @@ -938,7 +2168,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 ] ) @@ -946,9 +2176,9 @@ AC_ARG_ENABLE([asn], if test "$ENABLED_ASN" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_ASN -DNO_CERTS" - if test "$ENABLED_DH" = "no" + if test "$ENABLED_DH" = "no" && test "$ENABLED_ECC" = "no" then - # DH needs bigint + # DH and ECC need bigint AM_CFLAGS="$AM_CFLAGS -DNO_BIG_INT" fi else @@ -957,10 +2187,16 @@ else then AM_CFLAGS="$AM_CFLAGS -DNO_ASN -DNO_CERTS -DNO_BIG_INT" ENABLED_ASN=no + else + if test "$ENABLED_ASN" = "nocrypt" + then + AM_CFLAGS="$AM_CFLAGS -DNO_ASN_CRYPT" + enable_pwdbased=no + fi fi fi -if test "$ENABLED_RSA" = "yes" && test "$ENABLED_ASN" = "no" +if test "$ENABLED_RSA" = "yes" && test "$ENABLED_RSAVFY" = "no" && test "$ENABLED_ASN" = "no" then AC_MSG_ERROR([please disable rsa if disabling asn.]) fi @@ -970,29 +2206,17 @@ then AC_MSG_ERROR([please disable dsa if disabling asn.]) fi -if test "$ENABLED_ECC" = "yes" && test "$ENABLED_ASN" = "no" -then - AC_MSG_ERROR([please disable ecc if disabling asn.]) -fi - -if test "$ENABLED_PSK" = "no" && test "$ENABLED_ASN" = "no" -then - AC_MSG_ERROR([please enable psk if disabling asn.]) -fi - -# DH needs bigint -if test "$ENABLED_ASN" = "no" && test "$ENABLED_DH" = "no" +# DH and ECC need bigint +if test "$ENABLED_ASN" = "no" && test "$ENABLED_DH" = "no" && test "$ENABLED_ECC" = "no" && test "$ENABLED_RSA" = "no" then ENABLED_FASTMATH=no ENABLED_SLOWMATH=no fi -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 ] ) @@ -1000,6 +2224,14 @@ AC_ARG_ENABLE([aes], if test "$ENABLED_AES" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_AES" + if test "$ENABLED_FORTRESS" = "yes" + then + AC_MSG_ERROR([fortress requires aes]) + fi + if test "$ENABLED_ECC_ENCRYPT" = "yes" + then + AC_MSG_ERROR([cannot enable eccencrypt and hkdf without aes.]) + fi if test "$ENABLED_AESGCM" = "yes" then AC_MSG_ERROR([AESGCM requires AES.]) @@ -1008,6 +2240,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" @@ -1017,12 +2253,10 @@ else fi fi -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 ] ) @@ -1039,56 +2273,87 @@ else fi fi -AM_CONDITIONAL([BUILD_CODING], [test "x$ENABLED_CODING" = "xyes"]) + +# Base64 Encode +BASE64ENCODE_DEFAULT=no +if test "$host_cpu" = "x86_64" +then +BASE64ENCODE_DEFAULT=yes +fi +AC_ARG_ENABLE([base64encode], + [AS_HELP_STRING([--enable-base64encode],[Enable Base64 encoding (default: enabled on x86_64)])], + [ ENABLED_BASE64ENCODE=$enableval ], + [ ENABLED_BASE64ENCODE=$BASE64ENCODE_DEFAULT ] + ) +if test "$ENABLED_BASE64ENCODE" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_BASE64_ENCODE" +fi + + +# Base16 +AC_ARG_ENABLE([base16], + [AS_HELP_STRING([--enable-base16],[Enable Base16 encoding/decoding (default: disabled)])], + [ ENABLED_BASE16=$enableval ], + [ ENABLED_BASE16=no ] + ) +if test "$ENABLED_BASE16" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_BASE16" +fi # DES3 AC_ARG_ENABLE([des3], - [ --enable-des3 Enable DES3 (default: enabled)], + [AS_HELP_STRING([--enable-des3],[Enable DES3 (default: disabled)])], [ ENABLED_DES3=$enableval ], - [ ENABLED_DES3=yes ] + [ ENABLED_DES3=no ] ) -if test "$ENABLED_DES3" = "no" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_QT" = "yes" || test "$ENABLED_OPENVPN" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DNO_DES3" -else - # turn off DES3 if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" - then - AM_CFLAGS="$AM_CFLAGS -DNO_DES3" - ENABLED_DES3=no - fi + ENABLED_DES3="yes" fi -AM_CONDITIONAL([BUILD_DES3], [test "x$ENABLED_DES3" = "xyes"]) +# IDEA +AC_ARG_ENABLE([idea], + [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" +fi -# ARC4 +# 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" || test "$ENABLED_WPAS" = "yes" +then + ENABLED_ARC4="yes" +fi + if test "$ENABLED_ARC4" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_RC4" else - # turn off ARC4 if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off ARC4 if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_RC4" ENABLED_ARC4=no fi fi -AM_CONDITIONAL([BUILD_RC4], [test "x$ENABLED_ARC4" = "xyes"]) - - -# MD5 +# 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 ] ) @@ -1097,20 +2362,18 @@ if test "$ENABLED_MD5" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_MD5 -DNO_OLD_TLS" else - # turn off MD5 if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off MD5 if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_MD5 -DNO_OLD_TLS" ENABLED_MD5=no fi fi -AM_CONDITIONAL([BUILD_MD5], [test "x$ENABLED_MD5" = "xyes"]) - -# SHA +# 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 ] ) @@ -1119,35 +2382,45 @@ if test "$ENABLED_SHA" = "no" then AM_CFLAGS="$AM_CFLAGS -DNO_SHA -DNO_OLD_TLS" else - # turn off SHA if leanpsk on - if test "$ENABLED_LEANPSK" = "yes" + # turn off SHA if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DNO_SHA -DNO_OLD_TLS" ENABLED_SHA=no fi fi -AM_CONDITIONAL([BUILD_SHA], [test "x$ENABLED_SHA" = "xyes"]) - -# MD4 -AC_ARG_ENABLE([md4], - [ --enable-md4 Enable MD4 (default: disabled)], - [ ENABLED_MD4=$enableval ], - [ ENABLED_MD4=no ] +# CMAC +AC_ARG_ENABLE([cmac], + [AS_HELP_STRING([--enable-cmac],[Enable CMAC (default: disabled)])], + [ ENABLED_CMAC=$enableval ], + [ ENABLED_CMAC=no ] ) -if test "$ENABLED_MD4" = "no" +if test "$ENABLED_WPAS" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DNO_MD4" + ENABLED_CMAC=yes fi -AM_CONDITIONAL([BUILD_MD4], [test "x$ENABLED_MD4" = "xyes"]) +AS_IF([test "x$ENABLED_CMAC" = "xyes"], + [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CMAC -DWOLFSSL_AES_DIRECT"]) -# Web Server Build +# 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 ] ) @@ -1157,11 +2430,22 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_WEBSERVER" fi +# Web Client Build (HTTP Client) +AC_ARG_ENABLE([webclient], + [AS_HELP_STRING([--enable-webclient],[Enable Web Client (HTTP) (default: disabled)])], + [ ENABLED_WEBCLIENT=$enableval ], + [ ENABLED_WEBCLIENT=no ] + ) + +if test "$ENABLED_WEBCLIENT" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_HTTP_CLIENT" +fi -# HC128 +# 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 ] ) @@ -1173,12 +2457,10 @@ else AM_CFLAGS="$AM_CFLAGS -DHAVE_HC128" fi -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 ] ) @@ -1190,42 +2472,156 @@ else AM_CFLAGS="$AM_CFLAGS -DHAVE_RABBIT" fi -AM_CONDITIONAL([BUILD_RABBIT], [test "x$ENABLED_RABBIT" = "xyes"]) - # FIPS AC_ARG_ENABLE([fips], [AS_HELP_STRING([--enable-fips],[Enable FIPS 140-2, Will NOT work w/o FIPS license (default: disabled)])], - [ ENABLED_FIPS=$enableval ], - [ ENABLED_FIPS=no ] + [ENABLED_FIPS=$enableval], + [ENABLED_FIPS="no"]) + +AS_CASE([$ENABLED_FIPS], + ["v2"],[FIPS_VERSION="v2" + ENABLED_FIPS=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS -DHAVE_FIPS_VERSION=2 -DWOLFSSL_KEY_GEN -DWOLFSSL_SHA224 -DWOLFSSL_AES_DIRECT -DHAVE_AES_ECB -DHAVE_ECC_CDH -DWC_RSA_NO_PADDING -DWOLFSSL_VALIDATE_FFC_IMPORT -DHAVE_FFDHE_Q" + ENABLED_KEYGEN="yes" + ENABLED_SHA224="yes" + # Shake256 is a SHA-3 algorithm not in our FIPS algorithm list + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_SHAKE256" + AS_IF([test "x$ENABLED_AESCCM" != "xyes"], + [ENABLED_AESCCM="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_AESCCM"]) + AS_IF([test "x$ENABLED_RSAPSS" != "xyes"], + [ENABLED_RSAPSS="yes" + AM_CFLAGS="$AM_CFLAGS -DWC_RSA_PSS"]) + AS_IF([test "x$ENABLED_ECC" != "xyes"], + [ENABLED_ECC="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256 -DWOLFSSL_VALIDATE_ECC_IMPORT" + AS_IF([test "x$ENABLED_ECC_SHAMIR" = "xyes"], + [AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR"])], + [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_VALIDATE_ECC_IMPORT"]) + AS_IF([test "x$ENABLED_AESCTR" != "xyes"], + [ENABLED_AESCTR="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_COUNTER"]) + AS_IF([test "x$ENABLED_CMAC" != "xyes"], + [ENABLED_CMAC="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CMAC"]) + AS_IF([test "x$ENABLED_HKDF" != "xyes"], + [ENABLED_HKDF="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_HKDF"]) + AS_IF([test "x$ENABLED_INTELASM" = "xyes"], + [AM_CFLAGS="$AM_CFLAGS -DFORCE_FAILURE_RDSEED"]) + ], + ["rand"],[ + ENABLED_FIPS="yes" + FIPS_VERSION="rand" + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_FIPS_RAND -DHAVE_FIPS -DHAVE_FIPS_VERSION=2" + ], + ["no"],[FIPS_VERSION="none"], + [ + ENABLED_FIPS="yes" + FIPS_VERSION="v1" + AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS" + ]) + +AS_IF([test "x$ENABLED_FIPS" = "xyes" && test "x$thread_ls_on" = "xno"], + [AC_MSG_ERROR([FIPS requires Thread Local Storage])]) + +AS_IF([test "x$ENABLED_FIPS" = "xyes" && test "x$FIPS_VERSION" != "xrand"], +[ + # Force enable the prerequisites. + AS_IF([test "x$ENABLED_SHA512" = "xno"], + [ENABLED_SHA512="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512 -DWOLFSSL_SHA384"]) + AS_IF([test "x$ENABLED_AESGCM" = "xno"], + [ENABLED_AESGCM="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM"]) + AS_IF([test "x$ENABLED_DES3" = "xno"],[ENABLED_DES3="yes"]) +], +[ + AS_IF([test "x$ENABLED_FORTRESS" = "xyes"],[ENABLED_DES3="yes"]) +]) + + +# SELFTEST +AC_ARG_ENABLE([selftest], + [AS_HELP_STRING([--enable-selftest],[Enable selftest, Will NOT work w/o CAVP selftest license (default: disabled)])], + [ ENABLED_SELFTEST=$enableval ], + [ ENABLED_SELFTEST=no ] ) -if test "x$ENABLED_FIPS" = "xyes" +if test "x$ENABLED_SELFTEST" = "xyes" then - # requires thread local storage - if test "$thread_ls_on" = "no" - then - AC_MSG_ERROR([FIPS requires Thread Local Storage]) - fi - # requires SHA512 - if test "x$ENABLED_SHA512" = "xno" - then - ENABLED_SHA512="yes" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512 -DWOLFSSL_SHA384" - AM_CONDITIONAL([BUILD_SHA512], [test "x$ENABLED_SHA512" = "xyes"]) - fi - # requires AESGCM - if test "x$ENABLED_AESGCM" != "xyes" - then - ENABLED_AESGCM="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM" - AM_CONDITIONAL([BUILD_SHA512], [test "x$ENABLED_SHA512" = "xyes"]) - fi - AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS" + AM_CFLAGS="$AM_CFLAGS -DHAVE_SELFTEST" fi -AM_CONDITIONAL([BUILD_FIPS], [test "x$ENABLED_FIPS" = "xyes"]) +# set sha224 default +SHA224_DEFAULT=no +if test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64" +then + if test "x$ENABLED_AFALG" = "xno" && test "x$ENABLED_DEVCRYPTO" = "xno" && ( test "x$ENABLED_FIPS" = "xno" || test "x$FIPS_VERSION" = "xv2" ) + then + SHA224_DEFAULT=yes + fi +fi + +# SHA224 +AC_ARG_ENABLE([sha224], + [AS_HELP_STRING([--enable-sha224],[Enable wolfSSL SHA-224 support (default: enabled on x86_64/aarch64)])], + [ ENABLED_SHA224=$enableval ], + [ ENABLED_SHA224=$SHA224_DEFAULT ] + ) + +if test "$ENABLED_SHA224" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA224" +fi + + +# set sha3 default +SHA3_DEFAULT=no +if test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64" +then + if test "x$ENABLED_FIPS" = "xno" || test "x$FIPS_VERSION" = "xv2" + 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/aarch64)])], + [ 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 + +# SHAKE256 +AC_ARG_ENABLE([shake256], + [AS_HELP_STRING([--enable-shake256],[Enable wolfSSL SHAKE256 support (default: enabled on x86_64/aarch64)])], + [ ENABLED_SHAKE256=$enableval ], + [ ENABLED_SHAKE256=$ENABLED_SHA3 ] + ) + +if test "$ENABLED_SHAKE256" = "yes" || test "$ENABLED_SHAKE256" = "small" +then + if test "$ENABLED_32BIT" = "no" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHAKE256" + if test "$ENABLED_SHA3" = "no" + then + AC_MSG_ERROR([Must have SHA-3 enabled: --enable-sha3]) + fi + fi +fi # set POLY1305 default POLY1305_DEFAULT=yes @@ -1242,8 +2638,8 @@ AC_ARG_ENABLE([poly1305], [ ENABLED_POLY1305=$POLY1305_DEFAULT] ) -# lean psk does't need poly1305 -if test "$ENABLED_LEANPSK" = "yes" +# leanpsk and leantls don't need poly1305 +if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" then ENABLED_POLY1305=no fi @@ -1253,8 +2649,6 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_POLY1305 -DHAVE_ONE_TIME_AUTH" fi -AM_CONDITIONAL([BUILD_POLY1305], [test "x$ENABLED_POLY1305" = "xyes"]) - # set CHACHA default CHACHA_DEFAULT=yes @@ -1266,28 +2660,31 @@ 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] ) -# lean psk does't need chacha -if test "$ENABLED_LEANPSK" = "yes" +# leanpsk and leantls don't need chacha +if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" 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" fi -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 ] ) @@ -1296,18 +2693,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 +# 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 ] ) @@ -1325,9 +2724,9 @@ else fi -# inline Build +# 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 ] ) @@ -1337,23 +2736,24 @@ then AM_CFLAGS="$AM_CFLAGS -DNO_INLINE" fi -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_OPENSSLALL" = "xyes" || test "x$ENABLED_NGINX" = "xyes" +then + ENABLED_OCSP=yes +fi + if test "$ENABLED_OCSP" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" fi -AM_CONDITIONAL([BUILD_OCSP], [test "x$ENABLED_OCSP" = "xyes"]) - if test "$ENABLED_OCSP" = "yes" then @@ -1369,24 +2769,78 @@ then fi -# CRL +# Certificate Status Request : a.k.a. OCSP Stapling +AC_ARG_ENABLE([ocspstapling], + [AS_HELP_STRING([--enable-ocspstapling],[Enable OCSP Stapling (default: disabled)])], + [ ENABLED_CERTIFICATE_STATUS_REQUEST=$enableval ], + [ ENABLED_CERTIFICATE_STATUS_REQUEST=no ] + ) + +if test "x$ENABLED_NGINX" = "xyes" || test "x$ENABLED_WPAS" = "xyes" || test "x$ENABLED_HAPROXY" = "xyes" +then + 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" + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi +fi + + +# Certificate Status Request v2 : a.k.a. OCSP stapling v2 +AC_ARG_ENABLE([ocspstapling2], + [AS_HELP_STRING([--enable-ocspstapling2],[Enable OCSP Stapling v2 (default: disabled)])], + [ ENABLED_CERTIFICATE_STATUS_REQUEST_V2=$enableval ], + [ 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" + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi +fi + + +# 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" || test "x$ENABLED_OPENVPN" = "xyes" +then + ENABLED_CRL=yes +fi + if test "$ENABLED_CRL" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL" fi -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 ], ) @@ -1397,39 +2851,96 @@ then *linux* | *darwin* | *freebsd*) AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL_MONITOR" ;; *) - AC_MSG_ERROR([crl monitor only allowed on linux, OS X, or freebsd]) ;; + if test "x$ENABLED_DISTRO" = "xyes" ; then + ENABLED_CRL_MONITOR="no" + else + AC_MSG_ERROR( [crl monitor only allowed on linux, OS X, or freebsd]) + fi + break;; esac fi -AM_CONDITIONAL([BUILD_CRL_MONITOR], [test "x$ENABLED_CRL_MONITOR" = "xyes"]) + +# USER CRYPTO +ENABLED_USER_CRYPTO="no" +ENABLED_USER_RSA="no" +AC_DEFINE([BUILD_USER_RSA], [], [User RSA is being defined]) +trycryptodir="" +AC_ARG_WITH([user-crypto], + [AS_HELP_STRING([--with-user-crypto=PATH],[Path to USER_CRYPTO install (default /usr/local)])], + [ + CPPFLAGS="$CPPFLAGS -DHAVE_USER_CRYPTO" + LIBS="$LIBS -lusercrypto" + + if test "x$withval" != "xno" ; then + trycryptodir=$withval + fi + if test "x$withval" = "xyes" ; then + trycryptodir="/usr/local" + fi + + LDFLAGS="$LDFLAGS -L$trycryptodir/lib" + CPPFLAGS="$CPPFLAGS -I$trycryptodir/include" + + #Look for RSA Init function in usercrypto lib + AC_CHECK_LIB([usercrypto], [wc_InitRsaKey], [user_rsa_linked=yes], [user_rsa_linked=no]) + + if test "x$user_rsa_linked" = "xyes" ; then + AC_MSG_NOTICE([User user_rsa.h being used]) + AM_CFLAGS="$AM_CFLAGS -DHAVE_USER_RSA" + ENABLED_USER_RSA=yes + ENABLED_USER_CRYPTO=yes + fi + + + #Display check and find result of link attempts + AC_MSG_CHECKING([for USER_CRYPTO]) + if test "x$ENABLED_USER_CRYPTO" = "xno" ; then + AC_MSG_RESULT([no]) + AC_MSG_ERROR([USER_CRYPTO not found. Either move to /usr/include and /usr/lib or + Specify its path using --with-user-crypto=/dir/]) + else + AC_MSG_RESULT([yes]) + # Check if .la is available if not then rely on exported path + AC_CHECK_FILE($trycryptodir/lib/libusercrypto.la, [LIB_ADD="$trycryptodir/lib/libusercrypto.la $LIB_ADD"], [LIB_ADD="-lusercrypto $LIB_ADD"]) + AM_LDFLAGS="$AM_LDFLAGS -L$trycryptodir/lib" + AM_CFLAGS="$AM_CFLAGS -DHAVE_USER_CRYPTO" + fi + ] +) + +if test "$ENABLED_USER_CRYPTO" = "yes" && test "$ENABLED_FIPS" = "yes" +then + AC_MSG_ERROR([cannot enable user crypto and fips, user crypto posibility of using code in fips boundary.]) +fi # NTRU ENABLED_NTRU="no" tryntrudir="" AC_ARG_WITH([ntru], - [ --with-ntru=PATH Path to NTRU install (default /usr/) ], + [AS_HELP_STRING([--with-ntru=PATH],[Path to NTRU install (default /usr/)])], [ AC_MSG_CHECKING([for NTRU]) - CPPFLAGS="$CPPFLAGS -DHAVE_NTRU" - LIBS="$LIBS -lNTRUEncrypt" + 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 ]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ ntru_crypto_drbg_instantiate(0, 0, 0, 0, 0); ]])], [ ntru_linked=yes ],[ ntru_linked=no ]) - if test "x$ntru_linked" == "xno" ; then + if test "x$ntru_linked" = "xno" ; then if test "x$withval" != "xno" ; then tryntrudir=$withval fi - if test "x$withval" == "xyes" ; then + if test "x$withval" = "xyes" ; then tryntrudir="/usr" fi - LDFLAGS="$AM_LDFLAGS -L$tryntrudir/lib" + LDFLAGS="$AM_LDFLAGS $LDFLAGS -L$tryntrudir/lib" CPPFLAGS="$CPPFLAGS -I$tryntrudir/include" - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ ntru_crypto_drbg_instantiate(0, 0, 0, 0, 0); ]])], [ ntru_linked=yes ],[ ntru_linked=no ]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ ntru_crypto_drbg_instantiate(0, 0, 0, 0, 0); ]])], [ ntru_linked=yes ],[ ntru_linked=no ]) - if test "x$ntru_linked" == "xno" ; then + if test "x$ntru_linked" = "xno" ; then AC_MSG_ERROR([NTRU isn't found. If it's already installed, specify its path using --with-ntru=/dir/]) fi @@ -1439,24 +2950,81 @@ AC_ARG_WITH([ntru], AC_MSG_RESULT([yes]) fi - AM_CFLAGS="$AM_CFLAGS -DHAVE_NTRU" + AM_CFLAGS="$AM_CFLAGS -DHAVE_NTRU -DHAVE_TLS_EXTENSIONS" ENABLED_NTRU="yes" ] ) -AM_CONDITIONAL([BUILD_NTRU], [test "x$ENABLED_NTRU" = "xyes"]) -if test "$ENABLED_NTRU" = "yes" && test "$ENABLED_SMALL" = "yes" +# 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 - AC_MSG_ERROR([cannot enable ntru and small, ntru requires TLS which small turns off.]) + 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="" +AC_ARG_WITH([wnr], + [AS_HELP_STRING([--with-wnr=PATH],[Path to Whitewood netRandom install (default /usr/local)])], + [ + AC_MSG_CHECKING([for Whitewood netRandom]) + CPPFLAGS="$CPPFLAGS -DHAVE_WNR" + LIBS="$LIBS -lwnr" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ wnr_setup(0, 0); ]])], [ wnr_linked=yes ],[ wnr_linked=no ]) + + if test "x$wnr_linked" = "xno" ; then + if test "x$withval" != "xno" ; then + trywnrdir=$withval + fi + if test "x$withval" = "xyes" ; then + trywnrdir="/usr/local" + fi + + LDFLAGS="$AM_LDFLAGS $LDFLAGS -L$trywnrdir/lib" + CPPFLAGS="$CPPFLAGS -I$trywnrdir/include" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ wnr_setup(0, 0); ]])], [ wnr_linked=yes ],[ wnr_linked=no ]) + + if test "x$wnr_linked" = "xno" ; then + AC_MSG_ERROR([Whitewood netRandom isn't found. + If it's already installed, specify its path using --with-wnr=/dir/]) + fi + AC_MSG_RESULT([yes]) + AM_LDFLAGS="$AM_LDFLAGS -L$trywnrdir/lib" + else + AC_MSG_RESULT([yes]) + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_WNR" + ENABLED_WNR="yes" + ] +) + + # 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 ] ) +if test "x$ENABLED_QT" = "xyes" +then + ENABLED_SNI="yes" +fi if test "x$ENABLED_SNI" = "xyes" then @@ -1465,19 +3033,40 @@ 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], + [AS_HELP_STRING([--enable-alpn],[Enable ALPN (default: disabled)])], + [ ENABLED_ALPN=$enableval ], + [ ENABLED_ALPN=no ] + ) + +if test "x$ENABLED_ALPN" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_ALPN" +fi + +# Maximum Fragment Length if test "x$ENABLED_MAX_FRAGMENT" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_MAX_FRAGMENT" fi +# Trusted CA Indication Extension +AC_ARG_ENABLE([trustedca], + [AS_HELP_STRING([--enable-trustedca],[Enable Trusted CA Indication (default: disabled)])], + [ ENABLED_TRUSTED_CA=$enableval ],[ ENABLED_TRUSTED_CA=no ]) + +AS_IF([test "x$ENABLED_TRUSTED_CA" = "xyes"], + [AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_TRUSTED_CA"]) + # 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 ] ) @@ -1512,19 +3101,61 @@ then then AC_MSG_ERROR([cannot enable renegotiation-indication and secure-renegotiation.]) fi - AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SECURE_RENEGOTIATION" + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SECURE_RENEGOTIATION -DHAVE_SERVER_RENEGOTIATION_INFO" +fi + +# Fallback SCSV +AC_ARG_ENABLE([fallback-scsv], + [AS_HELP_STRING([--enable-fallback-scsv],[Enable Fallback SCSV (default: disabled)])], + [ ENABLED_FALLBACK_SCSV=$enableval ], + [ ENABLED_FALLBACK_SCSV=no ] + ) + +if test "x$ENABLED_FALLBACK_SCSV" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_FALLBACK_SCSV" fi # Supported Elliptic Curves Extensions AC_ARG_ENABLE([supportedcurves], - [AS_HELP_STRING([--enable-supportedcurves],[Enable Supported Elliptic Curves (default: disabled)])], - [ ENABLED_SUPPORTED_CURVES=$enableval ], - [ ENABLED_SUPPORTED_CURVES=no ] - ) + [AS_HELP_STRING([--enable-supportedcurves],[Enable Supported Elliptic Curves (default: enabled)])], + [ENABLED_SUPPORTED_CURVES=$enableval], + [ENABLED_SUPPORTED_CURVES=yes]) if test "x$ENABLED_SUPPORTED_CURVES" = "xyes" then - AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SUPPORTED_CURVES" + AS_IF([test "x$ENABLED_ECC" = "xno" && test "x$ENABLED_CURVE25519" = "xno"], + [ENABLED_SUPPORTED_CURVES=no], + [AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SUPPORTED_CURVES"]) +fi + +# Diffie-Hellman +if test "$ENABLED_DH" = "yes" +then + if test "$ENABLED_TLS13" = "yes" || test "$ENABLED_SUPPORTED_CURVES" = "yes" + then + AM_CFLAGS="-DHAVE_FFDHE_2048 $AM_CFLAGS" + fi +fi + +# FFDHE parameters only +AC_ARG_ENABLE([ffdhe-only], + [AS_HELP_STRING([--enable-ffdhe-only],[Enable using only FFDHE in client (default: disabled)])], + [ ENABLED_FFDHE_ONLY=$enableval ], + [ ENABLED_FFDHE_ONLY=no ] + ) + +if test "x$ENABLED_FFDHE_ONLY" = "xyes" +then + if test "$ENABLED_DH" = "no" + then + AC_MSG_ERROR([FFDHE only support requires DH support]) + fi + if test "$ENABLED_SUPPORTED_CURVES" = "no" + then + AC_MSG_ERROR([FFDHE only support requires Supported Curves extension]) + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_REQUIRE_FFDHE" fi # Session Ticket Extension @@ -1534,83 +3165,160 @@ 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" fi +# Extended Master Secret Extension +AC_ARG_ENABLE([extended-master], + [AS_HELP_STRING([--enable-extended-master],[Enable Extended Master Secret (default: enabled)])], + [ ENABLED_EXTENDED_MASTER=$enableval ], + [ ENABLED_EXTENDED_MASTER=yes ] + ) + +if test "x$ENABLED_EXTENDED_MASTER" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_EXTENDED_MASTER" +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 - ENABLED_MAX_FRAGMENT=yes - ENABLED_TRUNCATED_HMAC=yes - ENABLED_SUPPORTED_CURVES=yes - AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC -DHAVE_SUPPORTED_CURVES" + ENABLED_SNI=yes + ENABLED_MAX_FRAGMENT=yes + ENABLED_TRUNCATED_HMAC=yes + ENABLED_ALPN=yes + ENABLED_TRUSTED_CA=yes + ENABLED_ENCRYPT_THEN_MAC=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC -DHAVE_ALPN -DHAVE_TRUSTED_CA" + # Check the ECC supported curves prereq + AS_IF([test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_CURVE25519" = "xyes"], + [ENABLED_SUPPORTED_CURVES=yes + 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" = "group" +then + ENABLED_TLS13_EARLY_DATA="yes" + # Group EarlyData with ClientHello + AM_CFLAGS="-DWOLFSSL_EARLY_DATA_GROUP $AM_CFLAGS" +fi +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 + +if test "$ENABLED_TLSV12" = "no" && test "$ENABLED_TLS13" = "yes" && test "x$ENABLED_SESSION_TICKET" = "xno" +then + AM_CFLAGS="$AM_CFLAGS -DNO_SESSION_CACHE" +fi + + # PKCS7 AC_ARG_ENABLE([pkcs7], - [ --enable-pkcs7 Enable PKCS7 (default: disabled)], + [AS_HELP_STRING([--enable-pkcs7],[Enable PKCS7 (default: disabled)])], [ ENABLED_PKCS7=$enableval ], [ ENABLED_PKCS7=no ], ) -if test "$ENABLED_PKCS7" = "yes" -then - AM_CFLAGS="$AM_CFLAGS -DHAVE_PKCS7" -fi - -AM_CONDITIONAL([BUILD_PKCS7], [test "x$ENABLED_PKCS7" = "xyes"]) +# 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 ] ) -if test "$ENABLED_WOLFSCEP" = "yes" + + +# Secure Remote Password +AC_ARG_ENABLE([srp], + [AS_HELP_STRING([--enable-srp],[Enable Secure Remote Password (default: disabled)])], + [ ENABLED_SRP=$enableval ], + [ ENABLED_SRP=no ] + ) + +if test "x$ENABLED_SRP" = "xyes" then - # Enable prereqs if not already enabled - if test "x$ENABLED_KEYGEN" = "xno" - then - ENABLED_KEYGEN="yes" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KEY_GEN" - fi - if test "x$ENABLED_CERTGEN" = "xno" - then - ENABLED_CERTGEN="yes" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN" - fi - if test "x$ENABLED_CERTREQ" = "xno" - then - ENABLED_CERTREQ="yes" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_REQ" - fi - if test "x$ENABLED_PKCS7" = "xno" - then - ENABLED_PKCS7="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_PKCS7" - AM_CONDITIONAL([BUILD_PKCS7], [test "x$ENABLED_PKCS7" = "xyes"]) - fi - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_WOLFSCEP" + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_HAVE_SRP" fi +# Indefinite length encoded BER message support +AC_ARG_ENABLE([indef], + [AS_HELP_STRING([--enable-indef],[Enable parsing of indefinite length encoded msgs (default: disabled)])], + [ ENABLED_BER_INDEF=$enableval ], + [ ENABLED_BER_INDEF=no ] + ) + +if test "x$ENABLED_BER_INDEF" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DASN_BER_TO_DER" +fi + + + +# Small Stack - Cache on object +AC_ARG_ENABLE([smallstackcache], + [AS_HELP_STRING([--enable-smallstackcache],[Enable Small Stack Usage Caching (default: disabled)])], + [ ENABLED_SMALL_STACK_CACHE=$enableval ], + [ ENABLED_SMALL_STACK_CACHE=no ] + ) + +if test "x$ENABLED_SMALL_STACK_CACHE" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SMALL_STACK_CACHE" +fi + # 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 ] ) +if test "x$ENABLED_SMALL_STACK_CACHE" = "xyes" +then + ENABLED_SMALL_STACK=yes +fi if test "x$ENABLED_SMALL_STACK" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SMALL_STACK" @@ -1619,7 +3327,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 ] ) @@ -1637,12 +3345,10 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_VALGRIND" fi -AM_CONDITIONAL([USE_VALGRIND], [test "x$ENABLED_VALGRIND" = "xyes"]) - -# Test certs, use internal cert functions for extra testing +# 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 ] ) @@ -1656,7 +3362,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 ] ) @@ -1671,9 +3377,9 @@ then fi -# Certificate Service Support +# 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 ] ) @@ -1688,10 +3394,14 @@ then if test "x$ENABLED_ECC" = "xno" then ENABLED_ECC="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256 -DECC_SHAMIR" - AM_CONDITIONAL([BUILD_ECC], [test "x$ENABLED_ECC" = "xyes"]) + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" + + if test "$ENABLED_ECC_SHAMIR" = "yes" + 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" @@ -1700,210 +3410,16 @@ then fi -# 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)], - [ ENABLED_PWDBASED=$enableval ], - [ ENABLED_PWDBASED=no ] - ) - -if test "$ENABLED_PWDBASED" = "no" -then - if test "$ENABLED_OPENSSLEXTRA" = "yes" || test "$ENABLED_WEBSERVER" = "yes" - then - # opensslextra and webserver needs pwdbased - ENABLED_PWDBASED=yes - else - AM_CFLAGS="$AM_CFLAGS -DNO_PWDBASED" - fi -fi - -AM_CONDITIONAL([BUILD_PWDBASED], [test "x$ENABLED_PWDBASED" = "xyes"]) - - -# set fastmath default -FASTMATH_DEFAULT=no - -if test "$host_cpu" = "x86_64" -then -FASTMATH_DEFAULT=yes -fi - -# fastmath -AC_ARG_ENABLE([fastmath], - [ --enable-fastmath Enable fast math ops (default: enabled on x86_64)], - [ ENABLED_FASTMATH=$enableval ], - [ ENABLED_FASTMATH=$FASTMATH_DEFAULT] - ) - -if test "x$ENABLED_FASTMATH" = "xyes" -then - # turn off fastmth if leanpsk on or asn off (w/o dh) - if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_ASN" = "no" - then - if test "$ENABLED_DH" = "no" - then - ENABLED_FASTMATH=no - else - AM_CFLAGS="$AM_CFLAGS -DUSE_FAST_MATH" - ENABLED_SLOWMATH="no" - fi - else - AM_CFLAGS="$AM_CFLAGS -DUSE_FAST_MATH" - ENABLED_SLOWMATH="no" - fi - if test "$host_cpu" = "x86_64" - then - # Have settings.h set FP_MAX_BITS higher if user didn't set directly - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_X86_64_BUILD" - fi -fi - - -# fast HUGE math -AC_ARG_ENABLE([fasthugemath], - [ --enable-fasthugemath Enable fast math + huge code (default: disabled)], - [ ENABLED_FASTHUGEMATH=$enableval ], - [ ENABLED_FASTHUGEMATH=no ] - ) - -if test "$ENABLED_BUMP" = "yes" -then - ENABLED_FASTHUGEMATH="yes" -fi - -if test "$ENABLED_FASTHUGEMATH" = "yes" -then - ENABLED_FASTMATH="yes" - AM_CFLAGS="$AM_CFLAGS -DUSE_FAST_MATH" - ENABLED_SLOWMATH="no" -fi - -AM_CONDITIONAL([BUILD_FASTMATH], [test "x$ENABLED_FASTMATH" = "xyes"]) -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)], - [ ENABLED_EXAMPLES=$enableval ], - [ ENABLED_EXAMPLES=yes ] - ) - -AS_IF([test "x$ENABLED_FILESYSTEM" = "xno"], [ENABLED_EXAMPLES="no"]) -AS_IF([test "x$ENABLED_INLINE" = "xno"], [ENABLED_EXAMPLES="no"]) -AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$ENABLED_EXAMPLES" = "xyes"]) - - -# LIBZ -ENABLED_LIBZ="no" -trylibzdir="" -AC_ARG_WITH([libz], - [ --with-libz=PATH PATH to libz install (default /usr/) ], - [ - AC_MSG_CHECKING([for libz]) - CPPFLAGS="$CPPFLAGS -DHAVE_LIBZ" - LIBS="$LIBS -lz" - - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ deflateInit(0, 8); ]])],[ libz_linked=yes ],[ libz_linked=no ]) - - if test "x$libz_linked" == "xno" ; then - if test "x$withval" != "xno" ; then - trylibzdir=$withval - fi - if test "x$withval" == "xyes" ; then - trylibzdir="/usr" - fi - - AM_LDFLAGS="$AM_LDFLAGS -L$trylibzdir/lib" - CPPFLAGS="$CPPFLAGS -I$trylibzdir/include" - - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ deflateInit(0, 8); ]])],[ libz_linked=yes ],[ libz_linked=no ]) - - if test "x$libz_linked" == "xno" ; then - AC_MSG_ERROR([libz isn't found. - If it's already installed, specify its path using --with-libz=/dir/]) - fi - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([yes]) - fi - ENABLED_LIBZ="yes" - ] -) -AM_CONDITIONAL([BUILD_LIBZ], [test "x$ENABLED_LIBZ" = "xyes"]) - - -# cavium -trycaviumdir="" -AC_ARG_WITH([cavium], - [ --with-cavium=PATH PATH to cavium/software dir ], - [ - AC_MSG_CHECKING([for cavium]) - CPPFLAGS="$CPPFLAGS -DHAVE_CAVIUM" - - if test "x$withval" == "xyes" ; then - AC_MSG_ERROR([need a PATH for --with-cavium]) - fi - if test "x$withval" != "xno" ; then - trycaviumdir=$withval - fi - - LDFLAGS="$AM_LDFLAGS $trycaviumdir/api/cavium_common.o" - CPPFLAGS="$CPPFLAGS -I$trycaviumdir/include" - - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "cavium_common.h"]], [[ CspShutdown(CAVIUM_DEV_ID); ]])],[ cavium_linked=yes ],[ cavium_linked=no ]) - - 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/]) - fi - AC_MSG_RESULT([yes]) - enable_shared=no - enable_static=yes - ] -) - - -# microchip api -AC_ARG_ENABLE([mcapi], - [ --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" -fi - -if test "$ENABLED_MCAPI" = "yes" && test "$ENABLED_SHA512" = "no" -then - AC_MSG_ERROR([please enable sha512 if enabling mcapi.]) -fi - -if test "$ENABLED_MCAPI" = "yes" && test "$ENABLED_ECC" = "no" -then - AC_MSG_ERROR([please enable ecc if enabling mcapi.]) -fi - -if test "$ENABLED_MCAPI" = "yes" && test "$ENABLED_LIBZ" = "no" -then - AC_MSG_ERROR([please use --with-libz if enabling mcapi.]) -fi - -AM_CONDITIONAL([BUILD_MCAPI], [test "x$ENABLED_MCAPI" = "xyes"]) - - # 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 ] ) if test "$ENABLED_JNI" = "yes" then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_JNI" + # Enable prereqs if not already enabled if test "x$ENABLED_DTLS" = "xno" then @@ -1919,15 +3435,13 @@ then then ENABLED_CRL="yes" AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL" - AM_CONDITIONAL([BUILD_CRL], [test "x$ENABLED_CRL" = "xyes"]) fi if test "x$ENABLED_OCSP" = "xno" then ENABLED_OCSP="yes" AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" - AM_CONDITIONAL([BUILD_OCSP], [test "x$ENABLED_OCSP" = "xyes"]) fi - if test "x$ENABLED_CRL_MONITOR" = "xno" + if test "x$ENABLED_CRL_MONITOR" = "xno" && test "x$ENABLED_DISTRO" = "xno" then ENABLED_CRL_MONITOR="yes" AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL_MONITOR" @@ -1950,7 +3464,12 @@ then if test "x$ENABLED_ECC" = "xno" then ENABLED_ECC="yes" - AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC" + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" + + if test "$ENABLED_ECC_SHAMIR" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR" + fi fi if test "x$ENABLED_PKCALLBACKS" = "xno" then @@ -1962,16 +3481,1584 @@ then ENABLED_DH="yes" AM_CFLAGS="$AM_CFLAGS -DHAVE_DH" fi + if test "x$ENABLED_PSK" = "xno" + then + ENABLED_PSK="yes" + fi + if test "x$ENABLED_CERTEXT" = "xno" + then + ENABLED_CERTEXT="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" + fi + if test "x$ENABLED_CERTGEN" = "xno" + then + ENABLED_CERTGEN="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN" + fi +fi + +# lighty Support +AC_ARG_ENABLE([lighty], + [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" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" + then + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" + fi + AM_CFLAGS="$AM_CFLAGS -DHAVE_LIGHTY -DHAVE_WOLFSSL_SSL_H=1" +fi + +if test "$ENABLED_NGINX" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NGINX -DWOLFSSL_SIGNER_DER_CERT" +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_OPENVPN" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DES_ECB -DHAVE_EX_DATA -DWOLFSSL_KEY_GEN" fi -# Check for build-type conflicts +if test "$ENABLED_NGINX" = "yes"|| test "x$ENABLED_HAPROXY" = "xyes" || test "x$ENABLED_LIGHTY" = "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 + +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_WPAS" = "yes" || test "$ENABLED_QT" = "yes" +then + ENABLED_ARC4="yes" +fi + +if test "$ENABLED_ARC4" = "no" +then + AM_CFLAGS="$AM_CFLAGS -DNO_RC4" +else + # turn off ARC4 if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DNO_RC4" + ENABLED_ARC4=no + fi +fi + +# Asio Support +AC_ARG_ENABLE([asio], + [AS_HELP_STRING([--enable-asio],[Enable asio (default: disabled)])], + [ ENABLED_ASIO=$enableval ], + [ ENABLED_ASIO=no ] + ) +if test "$ENABLED_ASIO" = "yes" +then + # Requires opensslextra and opensslall + if test "x$ENABLED_OPENSSLALL" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" + then + ENABLED_OPENSSLALL="yes" + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="-DOPENSSL_EXTRA -DOPENSSL_ALL $AM_CFLAGS" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ASIO -DASIO_USE_WOLFSSL -DWOLFSSL_KEY_GEN" + AM_CFLAGS="$AM_CFLAGS -DBOOST_ASIO_USE_WOLFSSL -DHAVE_EX_DATA" + AM_CFLAGS="$AM_CFLAGS -DSSL_TXT_TLSV1_2 -DSSL_TXT_TLSV1_1" + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3" + if test "$ENABLED_TLSV10" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DSSL_TXT_TLSV1" + fi + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi +fi + +# Apache HTTPD +AC_ARG_ENABLE([apachehttpd], + [AS_HELP_STRING([--enable-apachehttpd],[Enable Apache httpd (default: disabled)])], + [ ENABLED_APACHE_HTTPD=$enableval ], + [ ENABLED_APACHE_HTTPD=no ] + ) +if test "$ENABLED_APACHE_HTTPD" = "yes" +then + # Requires opensslextra and opensslall + if test "x$ENABLED_OPENSSLALL" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" + then + ENABLED_OPENSSLALL="yes" + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="-DOPENSSL_EXTRA -DOPENSSL_ALL $AM_CFLAGS" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_APACHE_HTTPD" + AM_CFLAGS="$AM_CFLAGS -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 -DOPENSSL_NO_COMP" + AM_CFLAGS="$AM_CFLAGS -DHAVE_EX_DATA -DWOLFSSL_SIGNER_DER_CERT" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT -DWOLFSSL_CERT_GEN" + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi + + # Requires sessioncerts make sure on + if test "x$ENABLED_SESSIONCERTS" = "xno" + then + ENABLED_SESSIONCERTS="yes" + AM_CFLAGS="$AM_CFLAGS -DSESSION_CERTS" + fi + + # Requires ALPN + if test "x$ENABLED_ALPN" = "xno" + then + ENABLED_ALPN="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_ALPN" + fi + + # Requires CRL + if test "x$ENABLED_CRL" = "xno" + then + ENABLED_CRL="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL" + fi + + # Requires Certificate Generation, Request and Extensions + if test "x$ENABLED_CERTGEN" = "xno" + then + ENABLED_CERTGEN="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN" + fi + if test "x$ENABLED_CERTREQ" = "xno" + then + ENABLED_CERTREQ="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_REQ" + fi + if test "x$ENABLED_CERTEXT" = "xno" + then + ENABLED_CERTEXT="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" + fi + + # Requires Secure Renegotiation + if test "x$ENABLED_SECURE_RENEGOTIATION" = "xno" + then + AM_CFLAGS="$AM_CFLAGS -DHAVE_SECURE_RENEGOTIATION -DHAVE_SERVER_RENEGOTIATION_INFO" + fi +fi + +# Encrypt-Then-Mac +AC_ARG_ENABLE([enc-then-mac], + [AS_HELP_STRING([--enable-enc-then-mac],[Enable Encryptr-Then-Mac extension (default: enabled)])], + [ ENABLED_ENCRYPT_THEN_MAC=$enableval ], + [ ENABLED_ENCRYPT_THEN_MAC=yes ] + ) + +if test "x$ENABLED_APACHE_HTTPD" = "xyes" +then + ENABLED_ENCRYPT_THEN_MAC=no +fi + +if test "x$ENABLED_TLSX" = "xyes" +then + ENABLED_ENCRYPT_THEN_MAC=yes +fi + +AS_IF([test "x$ENABLED_SNIFFER" == "xyes"],[ENABLED_ENCRYPT_THEN_MAC="no"]) + +if test "x$ENABLED_ENCRYPT_THEN_MAC" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_ENCRYPT_THEN_MAC" +fi + + +# stunnel Support +AC_ARG_ENABLE([stunnel], + [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" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" + then + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" + fi + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + fi + + # Requires coding make sure on + if test "x$ENABLED_CODING" = "xno" + then + ENABLED_CODING="yes" + fi + + # Requires sessioncerts make sure on + if test "x$ENABLED_SESSIONCERTS" = "xno" + then + ENABLED_SESSIONCERTS="yes" + AM_CFLAGS="$AM_CFLAGS -DSESSION_CERTS" + fi + + # Requires crls, make sure on + if test "x$ENABLED_CRL" = "xno" + then + ENABLED_CRL="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL" + fi + + # Requires DES3, make sure on + if test "x$ENABLED_DES3" = "xno" + then + ENABLED_DES3="yes" + fi + + # Requires tlsx, make sure on + 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" + + # Check the ECC supported curves prereq + AS_IF([test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_CURVE25519" = "xyes"], + [ENABLED_SUPPORTED_CURVES=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_SUPPORTED_CURVES"]) + fi + + # Requires ecc make sure on + if test "x$ENABLED_ECC" = "xno" + then + ENABLED_OPENSSLEXTRA="yes" + ENABLED_ECC="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" + + if test "$ENABLED_ECC_SHAMIR" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR" + fi + fi + + # Requires wolfSSL_OBJ_txt2nid + if test "x$ENABLED_CERTEXT" = "xno" + then + ENABLED_CERTEXT="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" + fi + + # Requires certgen + if test "x$ENABLED_CERTGEN" = "xno" + then + ENABLED_CERTGEN="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN" + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_STUNNEL -DWOLFSSL_ALWAYS_VERIFY_CB" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI -DHAVE_EX_DATA" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DES_ECB" +fi + +if test "$ENABLED_PSK" = "no" && test "$ENABLED_LEANPSK" = "no" \ + && test "x$ENABLED_STUNNEL" = "xno" +then + AM_CFLAGS="$AM_CFLAGS -DNO_PSK" +fi + +if test "$ENABLED_PSK" = "no" && \ + (test "$ENABLED_LEANPSK" = "yes" || test "x$ENABLED_STUNNEL" = "xyes") +then + ENABLED_PSK=yes +fi + +# MD4 +AC_ARG_ENABLE([md4], + [AS_HELP_STRING([--enable-md4],[Enable MD4 (default: disabled)])], + [ ENABLED_MD4=$enableval ], + [ ENABLED_MD4=no ] + ) + + +if test "$ENABLED_MD4" = "no" +then + #turn on MD4 if using stunnel + if test "x$ENABLED_STUNNEL" = "xyes" + then + ENABLED_MD4="yes" + else + AM_CFLAGS="$AM_CFLAGS -DNO_MD4" + fi +fi + + +# Encrypted keys +AC_ARG_ENABLE([enckeys], + [AS_HELP_STRING([--enable-enckeys],[Enable PEM encrypted private key support (default: disabled)])], + [ ENABLED_ENCKEYS=$enableval ], + [ ENABLED_ENCKEYS=no ] + ) + +if test "$ENABLED_OPENSSLEXTRA" = "yes" || test "$ENABLED_WEBSERVER" = "yes" +then + ENABLED_ENCKEYS=yes +fi + +if test "$ENABLED_ENCKEYS" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ENCRYPTED_KEYS" +fi + + +# PWDBASED has to come after certservice since we want it on w/o explicit on +# PWDBASED +AC_ARG_ENABLE([pwdbased], + [AS_HELP_STRING([--enable-pwdbased],[Enable PWDBASED (default: disabled)])], + [ ENABLED_PWDBASED=$enableval ], + [ ENABLED_PWDBASED=no ] + ) + +if test "$ENABLED_PWDBASED" = "no" +then + if test "$ENABLED_OPENSSLEXTRA" = "yes" || test "$ENABLED_OPENSSLALL" = "yes" || test "$ENABLED_WEBSERVER" = "yes" || test "$ENABLED_ENCKEYS" = "yes" + then + # opensslextra, opensslall, webserver, and enckeys needs pwdbased + ENABLED_PWDBASED=yes + else + AM_CFLAGS="$AM_CFLAGS -DNO_PWDBASED" + fi +fi + + +AC_ARG_ENABLE([scrypt], + [AS_HELP_STRING([--enable-scrypt],[Enable SCRYPT (default: disabled)])], + [ ENABLED_SCRYPT=$enableval ], + [ ENABLED_SCRYPT=no ] + ) + +if test "$ENABLED_SCRYPT" = "yes" +then + if test "$ENABLED_PWDBASED" = "no" + then + AC_MSG_ERROR([cannot enable scrypt without enabling pwdbased.]) + fi + AM_CFLAGS="$AM_CFLAGS -DHAVE_SCRYPT" +fi + + +# wolfCrypt Only Build +AC_ARG_ENABLE([cryptonly], + [AS_HELP_STRING([--enable-cryptonly],[Enable wolfCrypt Only build (default: disabled)])], + [ENABLED_CRYPTONLY=$enableval], + [ENABLED_CRYPTONLY=no]) + +AS_IF([test "x$FIPS_VERSION" = "xrand"],[ENABLED_CRYPTONLY="yes"]) + +if test "$ENABLED_CRYPTONLY" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_ONLY" +fi + +if test "x$ENABLED_CRYPTONLY" = "xno" +then + if test "x$ENABLED_PSK" = "xno" && test "x$ENABLED_ASN" = "xno" + then + AC_MSG_ERROR([please enable psk if disabling asn.]) + fi + + if test "x$ENABLED_ECC" = "xyes" && test "x$ENABLED_ASN" = "xno" + then + AC_MSG_ERROR([please disable ecc if disabling asn.]) + fi + + if test "$ENABLED_AFALG" = "yes" + then + # for TLS connections the intermediate hash needs to store buffer + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AFALG_HASH_KEEP" + fi + + if test "$ENABLED_DEVCRYPTO" = "yes" + then + # for TLS connections the intermediate hash needs to store buffer + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEVCRYPTO_HASH_KEEP" + fi +fi + +# set fastmath default +FASTMATH_DEFAULT=no + +if test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64" +then + FASTMATH_DEFAULT=yes +fi +if test "$ENABLED_SP_MATH" = "yes" +then + FASTMATH_DEFAULT=no +fi + +# fastmath +AC_ARG_ENABLE([fastmath], + [AS_HELP_STRING([--enable-fastmath],[Enable fast math ops (default: enabled on x86_64/aarch64)])], + [ ENABLED_FASTMATH=$enableval ], + [ ENABLED_FASTMATH=$FASTMATH_DEFAULT] + ) + +if test "x$ENABLED_FASTMATH" = "xyes" +then + # turn off fastmth if leanpsk on or asn off (w/o DH and ECC) + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_ASN" = "no" + then + if test "$ENABLED_DH" = "no" && test "$ENABLED_ECC" = "no" && test "$ENABLED_RSA" = "no" + then + ENABLED_FASTMATH=no + else + AM_CFLAGS="$AM_CFLAGS -DUSE_FAST_MATH" + ENABLED_SLOWMATH="no" + fi + else + AM_CFLAGS="$AM_CFLAGS -DUSE_FAST_MATH" + ENABLED_SLOWMATH="no" + fi + if test "$host_cpu" = "x86_64" + then + # Have settings.h set FP_MAX_BITS higher if user didn't set directly + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_X86_64_BUILD" + fi +fi + + +# fast HUGE math +AC_ARG_ENABLE([fasthugemath], + [AS_HELP_STRING([--enable-fasthugemath],[Enable fast math + huge code (default: disabled)])], + [ ENABLED_FASTHUGEMATH=$enableval ], + [ ENABLED_FASTHUGEMATH=no ] + ) + +if test "$ENABLED_BUMP" = "yes" +then + ENABLED_FASTHUGEMATH="yes" +fi + +if test "$ENABLED_FASTHUGEMATH" = "yes" +then + ENABLED_FASTMATH="yes" + AM_CFLAGS="$AM_CFLAGS -DUSE_FAST_MATH" + ENABLED_SLOWMATH="no" +fi + + +# Enable Examples, used to disable examples +AC_ARG_ENABLE([examples], + [AS_HELP_STRING([--enable-examples],[Enable Examples (default: enabled)])], + [ ENABLED_EXAMPLES=$enableval ], + [ ENABLED_EXAMPLES=yes ] + ) + +AS_IF([test "x$ENABLED_FILESYSTEM" = "xno"], [ENABLED_EXAMPLES="no"]) +AS_IF([test "x$ENABLED_INLINE" = "xno"], [ENABLED_EXAMPLES="no"]) +AS_IF([test "x$ENABLED_CRYPTONLY" = "xyes"], [ENABLED_EXAMPLES="no"]) + + +# Enable wolfCrypt test and benchmark +AC_ARG_ENABLE([crypttests], + [AS_HELP_STRING([--enable-crypttests],[Enable Crypt Bench/Test (default: enabled)])], + [ ENABLED_CRYPT_TESTS=$enableval ], + [ ENABLED_CRYPT_TESTS=yes ] + ) + + +# LIBZ +ENABLED_LIBZ="no" +trylibzdir="" +AC_ARG_WITH([libz], + [ --with-libz=PATH PATH to libz install (default /usr/) ], + [ + AC_MSG_CHECKING([for libz]) + CPPFLAGS="$CPPFLAGS -DHAVE_LIBZ" + LIBS="$LIBS -lz" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ deflateInit(0, 8); ]])],[ libz_linked=yes ],[ libz_linked=no ]) + + if test "x$libz_linked" = "xno" ; then + if test "x$withval" != "xno" ; then + trylibzdir=$withval + fi + if test "x$withval" = "xyes" ; then + trylibzdir="/usr" + fi + + LDFLAGS="$LDFLAGS -L$trylibzdir/lib" + CPPFLAGS="$CPPFLAGS -I$trylibzdir/include" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ deflateInit(0, 8); ]])],[ libz_linked=yes ],[ libz_linked=no ]) + + if test "x$libz_linked" = "xno" ; then + AC_MSG_ERROR([libz isn't found. + If it's already installed, specify its path using --with-libz=/dir/]) + fi + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([yes]) + fi + ENABLED_LIBZ="yes" + ] +) + + +# PKCS#11 +AC_ARG_ENABLE([pkcs11], + [AS_HELP_STRING([--enable-pkcs11],[Enable pkcs11 access (default: disabled)])], + [ ENABLED_PKCS11=$enableval ], + [ ENABLED_PKCS11=no ] + ) + +if test "x$ENABLED_PKCS11" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_PKCS11 -DHAVE_WOLF_BIGINT" + LIBS="$LIBS -ldl" +fi + + +# PKCS#12 +AC_ARG_ENABLE([pkcs12], + [AS_HELP_STRING([--enable-pkcs12],[Enable pkcs12 (default: enabled)])], + [ ENABLED_PKCS12=$enableval ], + [ ENABLED_PKCS12=yes ] + ) + +if test "x$ENABLED_PKCS12" = "xno" +then + AM_CFLAGS="$AM_CFLAGS -DNO_PKCS12" +fi + + +# cavium +trycaviumdir="" +AC_ARG_WITH([cavium], + [ --with-cavium=PATH PATH to cavium/software dir ], + [ + 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]) + fi + if test "x$withval" != "xno" ; then + trycaviumdir=$withval + fi + + LDFLAGS="$AM_LDFLAGS $trycaviumdir/api/cavium_common.o" + CPPFLAGS="$CPPFLAGS -I$trycaviumdir/include" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "cavium_common.h"]], [[ CspShutdown(CAVIUM_DEV_ID); ]])],[ cavium_linked=yes ],[ cavium_linked=no ]) + + 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 + enable_static=yes + ENABLED_CAVIUM=yes + ], + [ ENABLED_CAVIUM=no ] +) + +# cavium V +trycaviumdir="" +AC_ARG_WITH([cavium-v], + [ --with-cavium-v=PATH PATH to Cavium V/software dir ], + [ + AC_MSG_CHECKING([for cavium]) + AM_CFLAGS="$AM_CFLAGS -DHAVE_CAVIUM -DHAVE_CAVIUM_V" + LIB_ADD="-lrt -lcrypto $LIB_ADD" + + if test "x$withval" = "xyes" ; then + AC_MSG_ERROR([need a PATH for --with-cavium]) + fi + if test "x$withval" != "xno" ; then + trycaviumdir=$withval + fi + + AC_CHECK_FILES([$trycaviumdir/lib/libnitrox.a], [AM_CPPFLAGS="-I$trycaviumdir/include $AM_CPPFLAGS"], [ENABLED_CAVIUM_V=no]) + LIB_STATIC_ADD="$trycaviumdir/lib/libnitrox.a $LIB_STATIC_ADD" + + if test "$ENABLED_CAVIUM_V" = "no"; then + AC_MSG_ERROR([Could not find Nitrox library]) + fi + + enable_shared=no + enable_static=yes + enable_opensslextra=yes + + ENABLED_CAVIUM=yes + ENABLED_CAVIUM_V=yes + ], + [ + ENABLED_CAVIUM_=no + ENABLED_CAVIUM_V=no + ] +) + + +# Cavium Octeon +OCTEON_ROOT="" +: ${OCTEON_OBJ="obj-octeon2"} +: ${OCTEON_HOST="standalone"} + +AC_ARG_WITH([octeon-sync], + [AS_HELP_STRING([--with-octeon-sync=PATH],[PATH to Cavium Octeon SDK dir (sync)])], + [ + AC_MSG_CHECKING([for octeon]) + + if test "x$withval" = "xyes" ; then + AC_MSG_ERROR([need a PATH for --with-octeon]) + fi + if test "x$withval" != "xno" ; then + OCTEON_ROOT=$withval + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_CAVIUM_OCTEON_SYNC" + AM_CFLAGS="$AM_CFLAGS -DOCTEON_MODEL=$OCTEON_MODEL" + AM_CFLAGS="$AM_CFLAGS -I$OCTEON_ROOT/executive" + AS_CASE([$OCTEON_HOST],['linux'],[AM_CFLAGS="$AM_CFLAGS -DCVMX_BUILD_FOR_LINUX_HOST"]) + + #-I$OCTEON_ROOT/target/include + AM_LDFLAGS="$AM_LDFLAGS -lrt -Xlinker -T -Xlinker $OCTEON_ROOT/executive/cvmx-shared-linux.ld" + AM_LDFLAGS="$AM_LDFLAGS -L$OCTEON_ROOT/executive/$OCTEON_OBJ -lcvmx -lfdt" + + enable_shared=no + enable_static=yes + + ENABLED_OCTEON_SYNC=yes + AC_MSG_RESULT([yes]) + ], + [ENABLED_OCTEON_SYNC=no] +) + + +# Intel QuickAssist +QAT_DIR="" +BUILD_INTEL_QAT_VERSION=2 + +AC_ARG_WITH([intelqa], + [AS_HELP_STRING([--with-intelqa=PATH],[PATH to Intel QuickAssist (QAT) driver dir])], + [ENABLED_INTEL_QA=yes; QAT_DIR=$withval], + [ENABLED_INTEL_QA=no]) + +AC_ARG_WITH([intelqa-sync], + [AS_HELP_STRING([--with-intelqa-sync=PATH],[PATH to Intel QuickAssist (QAT) driver dir (sync)])], + [ENABLED_INTEL_QA_SYNC=yes; QAT_DIR=$withval], + [ENABLED_INTEL_QA_SYNC=no]) + +AS_IF([test "x$ENABLED_INTEL_QA" = "xyes" && test "x$ENABLED_INTEL_QA_SYNC" = "xyes"], + [AC_MSG_ERROR([Both Intel QA Async and Sync are selected, only select one.])]) + +AS_IF([test "x$ENABLED_INTEL_QA" = "xyes" || test "x$ENABLED_INTEL_QA_SYNC" = "xyes"], + [AC_MSG_CHECKING([for intelqa]) + AS_IF([test "x$ENABLED_INTEL_QA" = "xyes"], + [AM_CPPFLAGS="$AM_CPPFLAGS -DHAVE_INTEL_QA -DDO_CRYPTO -DUSER_SPACE"; intelqa_opt=""], + [AM_CPPFLAGS="$AM_CPPFLAGS -DHAVE_INTEL_QA_SYNC -DQAT_USE_POLLING_THREAD -DO_CRYPTO -DUSER_SPACE"; intelqa_opt="-sync"]) + OLD_LIBS="$LIBS" + OLD_CPPFLAGS="$CPPFLAGS" + + AS_IF([test "x$QAT_DIR" = "xyes"],[AC_MSG_ERROR([need a PATH for --with-intelqa$intelqa_opt])]) + + AM_CPPFLAGS="$AM_CPPFLAGS -I$QAT_DIR/quickassist/include -I$QAT_DIR/quickassist/include/lac -I$QAT_DIR/quickassist/utilities/osal/include \ + -I$QAT_DIR/quickassist/utilities/osal/src/linux/user_space/include -I$QAT_DIR/quickassist/lookaside/access_layer/include \ + -I$QAT_DIR/quickassist/lookaside/access_layer/src/common/include -I$srcdir/wolfssl -I$srcdir/wolfssl/wolfcrypt/port/intel \ + -I$QAT_DIR/quickassist/utilities/libusdm_drv" + CPPFLAGS="$AM_CPPFLAGS" + + LDFLAGS="$LDFLAGS -L$QAT_DIR/build" + LIBS="$LIBS -lqat_s -lusdm_drv_s" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "cpa_cy_common.h"]],[[Cpa16U count = 0; cpaCyGetNumInstances(&count);]])],[intelqa_linked=yes],[intelqa_linked=no]) + + AS_IF([test "x$intelqa_linked" = "xno"], + [# Try old QAT driver libraries + LIBS="$OLD_LIBS -licp_qa_al_s" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "cpa_cy_common.h"]],[[Cpa16U count = 0; cpaCyGetNumInstances(&count);]])],[intelqa_linked=yes],[intelqa_linked=no]) + AS_IF([test "x$intelqa_linked" = "xno"], + [AC_MSG_ERROR([Intel QuickAssist not found. If it's already installed, specify its path using --with-intelqa$intelqa_opt=/dir/])], + [BUILD_INTEL_QAT_VERSION=1]) + ]) + + AC_MSG_RESULT([yes]) + + AS_IF([test "x$BUILD_INTEL_QAT_VERSION" == "x1"], + [LIB_ADD="-ladf_proxy -losal -lrt $LIB_ADD"], + [LIB_ADD="-losal -lrt $LIB_ADD"]) + CPPFLAGS="$OLD_CPPFLAGS" +]) + + +# 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 ], + ) + +ENABLED_SP_RSA=no +ENABLED_SP_DH=no +ENABLED_SP_FF_2048=no +ENABLED_SP_FF_3072=no +ENABLED_SP_FF_4096=no +ENABLED_SP_ECC=no +ENABLED_SP_EC_256=no +ENABLED_SP_EC_384=no +ENABLED_SP_NO_MALLOC=no +for v in `echo $ENABLED_SP | tr "," " "` +do + case $v in + small) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_2048=yes + ENABLED_SP_FF_3072=yes + ENABLED_SP_ECC=yes + ENABLED_SP_SMALL=yes + ENABLED_SP_EC_256=yes + if test "$host_cpu" = "x86_64"; then + ENABLED_SP_FF_4096=yes + ENABLED_SP_EC_384=yes + fi + ;; + yes) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_2048=yes + ENABLED_SP_FF_3072=yes + ENABLED_SP_ECC=yes + ENABLED_SP_EC_256=yes + if test "$host_cpu" = "x86_64"; then + ENABLED_SP_FF_4096=yes + ENABLED_SP_EC_384=yes + fi + ;; + no) + ;; + + smallec256 | smallp256 | small256) + ENABLED_SP_ECC=yes + ENABLED_SP_SMALL=yes + ENABLED_SP_EC_256=yes + ;; + ec256 | p256 | 256) + ENABLED_SP_ECC=yes + ENABLED_SP_EC_256=yes + ;; + smallec384 | smallp384 | small384) + ENABLED_SP_ECC=yes + ENABLED_SP_SMALL=yes + ENABLED_SP_EC_384=yes + ;; + ec384 | p384 | 384) + ENABLED_SP_ECC=yes + ENABLED_SP_EC_384=yes + ;; + + small2048) + ENABLED_SP_SMALL=yes + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_2048=yes + ;; + 2048) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_2048=yes + ;; + + smallrsa2048) + ENABLED_SP_SMALL=yes + ENABLED_SP_RSA=yes + ENABLED_SP_FF_2048=yes + ;; + rsa2048) + ENABLED_SP_RSA=yes + ENABLED_SP_FF_2048=yes + ;; + + small3072) + ENABLED_SP_SMALL=yes + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_3072=yes + ;; + 3072) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_3072=yes + ;; + + smallrsa3072) + ENABLED_SP_SMALL=yes + ENABLED_SP_RSA=yes + ENABLED_SP_FF_3072=yes + ;; + rsa3072) + ENABLED_SP_RSA=yes + ENABLED_SP_FF_3072=yes + ;; + + small4096) + ENABLED_SP_SMALL=yes + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_4096=yes + ;; + + 4096 | +4096) + ENABLED_SP_RSA=yes + ENABLED_SP_DH=yes + ENABLED_SP_FF_4096=yes + ;; + + smallrsa4096) + ENABLED_SP_SMALL=yes + ENABLED_SP_RSA=yes + ENABLED_SP_FF_4096=yes + ;; + + rsa4096) + ENABLED_SP_RSA=yes + ENABLED_SP_FF_4096=yes + ;; + + nomalloc) + ENABLED_SP_NO_MALLOC=yes + ;; + + *) + 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" + AM_CCASFLAGS="$AM_CCASFLAGS -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" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_HAVE_SP_DH" +fi +if test "$ENABLED_SP_RSA" = "yes" || test "$ENABLED_SP_DH" = "yes"; then + if test "$ENABLED_SP_FF_2048" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_2048" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NO_2048" + fi + if test "$ENABLED_SP_FF_3072" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_3072" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NO_3072" + fi + if test "$ENABLED_SP_FF_4096" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_4096" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_4096" + fi +fi +if test "$ENABLED_ECC" = "yes" && test "$ENABLED_SP_ECC" = "yes"; then + ENABLED_SP=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_SP_ECC" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_HAVE_SP_ECC" + if test "$ENABLED_SP_EC_256" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_256" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NO_256" + fi + if test "$ENABLED_SP_EC_384" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC384 -DWOLFSSL_SP_384" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_384" + fi +fi +if test "$ENABLED_SP_SMALL" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_SMALL" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_SMALL" +fi +if test "$ENABLED_SP_NO_MALLOC" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_MALLOC" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NO_MALLOC" +fi + + +AC_ARG_ENABLE([sp-asm], + [AS_HELP_STRING([--enable-sp-asm],[Enable Single Precision assembly implementation (default: disabled)])], + [ ENABLED_SP_ASM=$enableval ], + [ ENABLED_SP_ASM=no ], + ) +if test "$ENABLED_SP_ASM" = "yes"; then + if test "$ENABLED_SP" = "no"; then + AC_MSG_ERROR([Must have SP enabled: --enable-sp]) + fi + if test "$ENABLED_ASM" = "no"; then + AC_MSG_ERROR([Assembly code turned off]) + fi + + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_ASM" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_ASM" + case $host_cpu in + *aarch64*) + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_ARM64_ASM" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_ARM64_ASM" + ENABLED_SP_ARM64_ASM=yes + ;; + *arm*) + if test $host_alias = "thumb"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_ARM_THUMB_ASM -mthumb -march=armv6" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_ARM_THUMB_ASM" + ENABLED_SP_ARM_THUMB_ASM=yes + else + if test $host_alias = "cortex"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_ARM_CORTEX_M_ASM -mcpu=cortex-r5" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_ARM_CORTEX_M_ASM" + ENABLED_SP_ARM_CORTEX_ASM=yes + else + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_ARM32_ASM" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_ARM32_ASM" + ENABLED_SP_ARM32_ASM=yes + fi + fi + ;; + *x86_64*) + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_X86_64_ASM" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_X86_64_ASM" + ENABLED_SP_X86_64_ASM=yes + ;; + *) + AC_MSG_ERROR([ASM not available for CPU. Supported CPUs: x86_64, aarch64, arm]) + ;; + esac +fi + +AC_ARG_ENABLE([sp-math], + [AS_HELP_STRING([--enable-sp-math],[Enable Single Precision math implementation only (default: disabled)])], + [ ENABLED_SP_MATH=$enableval ], + [ ENABLED_SP_MATH=no ], + ) +if test "$ENABLED_SP_MATH" = "yes"; then + if test "$ENABLED_SP" = "no"; then + AC_MSG_ERROR([Must have SP enabled: --enable-sp]) + fi + if test "$ENABLED_ECCCUSTCURVES" = "yes"; then + AC_MSG_ERROR([Cannot use single precision math and custom curves]) + fi + if test "$ENABLED_OPENSSLEXTRA" = "yes"; then + AC_MSG_ERROR([Cannot use single precision math and OpenSSL extra]) + fi + if test "$ENABLED_DSA" = "yes"; then + AC_MSG_ERROR([Cannot use single precision math and DSA]) + fi + if test "$ENABLED_SRP" = "yes"; then + AC_MSG_ERROR([Cannot use single precision math and SRP]) + fi + if test "$ENABLED_SP_RSA" = "no" && test "$ENABLED_RSA" = "yes"; then + AC_MSG_ERROR([Cannot use RSA single precision only math and RSA]) + fi + if test "$ENABLED_SP_DH" = "no" && test "$ENABLED_DH" = "yes"; then + AC_MSG_ERROR([Cannot use DH single precision only math and DH]) + fi + + ENABLED_FASTMATH="no" + ENABLED_SLOWMATH="no" +fi +if test "$ENABLED_SP_MATH" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_MATH" +fi + + +# Fast RSA using Intel IPP +ippdir="${srcdir}/IPP" +ipplib="lib" # if autoconf guesses 32bit system changes lib directory +fastRSA_found=no +abs_path=`pwd` + +# set up variables used +IPPLIBS= +IPPHEADERS= +IPPLINK= + +AC_ARG_ENABLE([fast-rsa], + [AS_HELP_STRING([--enable-fast-rsa],[Enable RSA using Intel IPP (default: disabled)])], + [ ENABLED_FAST_RSA=$enableval ], + [ ENABLED_FAST_RSA=no ], + ) + +if test "$ENABLED_USER_RSA" = "no" && test "$ENABLED_FIPS" = "no"; then + + if test "$ac_cv_sizeof_long" = "4" && test "$ac_cv_sizeof_long_long" = "8"; then + ipplib="lib_32" # 32 bit OS detected + fi + +# Use static IPP Libraries +if test "$enable_shared" = "no" && test "$ENABLED_FAST_RSA" = "yes"; then + case $host_os in + *darwin*) + ipplib="$ipplib/mac_static" + AC_MSG_ERROR([Issue with static linking to libippcp.a on Mac. + Dynamic IPP libraries supported on Mac]) + break;; + + *linux*) + ipplib="$ipplib/linux_static" + break;; + *) + ENABLED_FAST_RSA=no + esac + + AC_CHECK_FILES([$srcdir/IPP/$ipplib/libippcore.a $srcdir/IPP/$ipplib/libippcp.a], [], [ENABLED_FAST_RSA=no]) + AC_CHECK_FILES([$srcdir/IPP/include/ipp.h $srcdir/IPP/include/ippcp.h], [AM_CPPFLAGS="-I$srcdir/IPP/include $AM_CPPFLAGS"], [ENABLED_FAST_RSA=no]) + LIB_STATIC_ADD="$srcdir/IPP/$ipplib/libippcp.a $srcdir/IPP/$ipplib/libippcore.a $LIB_STATIC_ADD" + if test "$ENABLED_FAST_RSA" = "no"; then + AC_MSG_ERROR([Could not find fast rsa libraries]) + fi +else + +# Check for and use bundled IPP libraries +if test "$ENABLED_FAST_RSA" = "yes"; then + AC_MSG_NOTICE([Using local IPP crypto library]) + + AC_CHECK_FILES([$abs_path/IPP/include/ippcp.h], + [ + # build and default locations on linux and mac + STORE_LDFLAGS=${LDFLAGS} + STORE_CPPFLAGS=${CPPFLAGS} + + # using LDFLAGS instead of AM_ temporarily to test link to library + LDFLAGS="-L$ippdir/$ipplib -lippcp -lippcore" + CPPFLAGS="-I$ippdir/include" + AC_CHECK_HEADERS([ippcp.h], [AC_CHECK_LIB([ippcp], [ippsRSAEncrypt_PKCSv15], [fastRSA_found=yes], [fastRSA_found=no])], [fastRSA_found=no]) + name="$ippdir/$ipplib/libippcp" + case $host_os in + *darwin*) + # check file existence and conditionally set variables + AC_CHECK_FILES([$abs_path/IPP/$ipplib/libippcp.dylib], [ + IPPLIBS="${name}.dylib ${name}-9.0.dylib ${name}e9-9.0.dylib ${name}g9-9.0.dylib ${name}h9-9.0.dylib ${name}k0-9.0.dylib ${name}l9-9.0.dylib ${name}n8-9.0.dylib ${name}p8-9.0.dylib ${name}s8-9.0.dylib ${name}y8-9.0.dylib IPP/lib/libippcore.dylib IPP/lib/libippcore-9.0.dylib" + IPPLINK="mkdir -p src/.libs && ln -f ${name}.dylib src/.libs/libippcp.dylib && ln -f ${srcdir}/${name}-9.0.dylib src/.libs/libippcp-9.0.dylib && ln -f ${srcdir}/${name}e9-9.0.dylib src/.libs/libippcpe9-9.0.dylib && ln -f ${srcdir}/${name}g9-9.0.dylib src/.libs/libippcpg9-9.0.dylib && ln -f ${srcdir}/${name}h9-9.0.dylib src/.libs/libippcph9-9.0.dylib && ln -f ${srcdir}/${name}k0-9.0.dylib src/.libs/libippcpk0-9.0.dylib && ln -f ${srcdir}/${name}l9-9.0.dylib src/.libs/libippcpl9-9.0.dylib && ln -f ${srcdir}/${name}n8-9.0.dylib src/.libs/libippcpn8-9.0.dylib && ln -f ${srcdir}/${name}p8-9.0.dylib src/.libs/libippcpp8-9.0.dylib && ln -f ${srcdir}/${name}s8-9.0.dylib src/.libs/libippcps8-9.0.dylib && ln -f ${srcdir}/${name}y8-9.0.dylib src/.libs/libippcpy8-9.0.dylib && ln -f ${srcdir}/IPP/lib/libippcore.dylib src/.libs/libippcore.dylib && ln -f ${srcdir}/IPP/lib/libippcore-9.0.dylib src/.libs/libippcore-9.0.dylib" + ], [fastRSA_found=no]) + break;; + + *linux*) + # check file existence and conditionally set variables + AC_CHECK_FILES([$abs_path/IPP/$ipplib/libippcp.so.9.0], [ + if test "$ac_cv_sizeof_long" = "4" && test "$ac_cv_sizeof_long_long" = "8"; then + IPPLIBS="${name}.so.9.0 ${name}g9.so.9.0 ${name}h9.so.9.0 ${name}p8.so.9.0 ${name}px.so.9.0 ${name}s8.so.9.0 ${name}.so ${name}w7.so.9.0 IPP/$ipplib/libippcore.so IPP/$ipplib/libippcore.so.9.0" + IPPLINK="mkdir -p src/.libs && ln -f ${name}.so.9.0 src/.libs/libippcp.so.9.0 && ln -f ${name}g9.so.9.0 src/.libs/libippcpg9.so.9.0 && ln -f ${name}h9.so.9.0 src/.libs/libippcph9.so.9.0 && ln -f ${name}p8.so.9.0 src/.libs/libippcpp8.so.9.0 && ln -f ${name}px.so.9.0 src/.libs/libippcppx.so.9.0 && ln -f ${name}s8.so.9.0 src/.libs/libippcps8.so.9.0 && ln -f ${name}.so src/.libs/libippcp.so && ln -f ${name}w7.so.9.0 src/.libs/libippcpw7.so.9.0 && ln -f IPP/$ipplib/libippcore.so src/.libs/libippcore.so && ln -f IPP/$ipplib/libippcore.so.9.0 src/.libs/libippcore.so.9.0" + else + IPPLIBS="${name}.so.9.0 ${name}e9.so.9.0 ${name}k0.so.9.0 ${name}l9.so.9.0 ${name}m7.so.9.0 ${name}mx.so.9.0 ${name}.so ${name}n8.so.9.0 ${name}y8.so.9.0 IPP/lib/libippcore.so IPP/lib/libippcore.so.9.0" + IPPLINK="mkdir -p src/.libs && ln -f ${name}.so.9.0 src/.libs/libippcp.so.9.0 && ln -f ${name}e9.so.9.0 src/.libs/libippcpe9.so.9.0 && ln -f ${name}k0.so.9.0 src/.libs/libippcpk0.so.9.0 && ln -f ${name}l9.so.9.0 src/.libs/libippcpl9.so.9.0 && ln -f ${name}m7.so.9.0 src/.libs/libippcpm7.so.9.0 && ln -f ${name}mx.so.9.0 src/.libs/libippcpmx.so.9.0 && ln -f ${name}.so src/.libs/libippcp.so && ln -f ${name}n8.so.9.0 src/.libs/libippcpn8.so.9.0 && ln -f ${name}y8.so.9.0 src/.libs/libippcpy8.so.9.0 && ln -f IPP/lib/libippcore.so src/.libs/libippcore.so && ln -f IPP/lib/libippcore.so.9.0 src/.libs/libippcore.so.9.0" + fi + ], [fastRSA_found=no]) + break;; + *) + fastRSA_found=no + esac + + if test "$fastRSA_found" = "yes"; then + # was succesfull so add tested LDFLAGS to AM_ flags + AM_LDFLAGS="${AM_LDFLAGS} ${LDFLAGS}" + AM_CPPFLAGS="${AM_CPPFLAGS} ${CPPFLAGS}" + IPPHEADERS="${srcdir}/IPP/include/*.h" + fi + + # restore LDFLAGS to user set + LDFLAGS=${STORE_LDFLAGS} + CPPFLAGS=${STORE_CPPFLAGS} + ], [fastRSA_found=no]) +fi + +# Don't cache the result so it can be checked +AS_UNSET([ac_cv_header_ippcp_h]) +AS_UNSET([ac_cv_header_ipp_h]) +AS_UNSET([ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15]); + +# Check link and see if user has pre-existing IPP Libraries if not using local +if test "$ENABLED_FAST_RSA" = "yes" && test "$fastRSA_found" = "no"; then + AC_MSG_NOTICE([Checking if IPP crypto library installed]) + AC_CHECK_HEADER([ippcp.h], [AC_CHECK_LIB([ippcp], [ippsRSAEncrypt_PKCSv15], + [ + fastRSA_found=yes + AM_LDFLAGS="${AM_LDFLAGS} -lippcore -lippcp" + ], [ fastRSA_found=no]) + ], [fastRSA_found=no]) + + # Error out on not finding libraries + if test "$fastRSA_found" = "no"; then + AC_MSG_ERROR([Could not find fast rsa libraries]) + fi +fi +fi # end of if for shared library +else # if user rsa is set than do not use fast rsa option + if test "$ENABLED_FAST_RSA" = "yes"; then + AC_MSG_ERROR([Could not use fast rsa libraries with user crypto or fips]) + fi +fi # end of if for user rsa crypto or fips + +# End result of checking for IPP Libraries +AC_MSG_CHECKING([for fast RSA]) +if test "$ENABLED_FAST_RSA" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DHAVE_FAST_RSA -DHAVE_USER_RSA" + # add in user crypto header that uses Intel IPP + AM_CPPFLAGS="$AM_CPPFLAGS -I$srcdir/wolfcrypt/user-crypto/include" + if test "$enable_shared" = "yes"; then + LIBS="$LIBS -lippcore -lippcp" + LIB_ADD="-lippcp -lippcore $LIB_ADD" + else + LIB_ADD="$srcdir/IPP/$ipplib/libippcp.a $srcdir/IPP/$ipplib/libippcore.a $LIB_ADD" + fi + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +AC_SUBST([IPPLIBS]) +AC_SUBST([IPPHEADERS]) +AC_SUBST([IPPLINK]) + + +# static memory use +AC_ARG_ENABLE([staticmemory], + [AS_HELP_STRING([--enable-staticmemory],[Enable static memory use (default: disabled)])], + [ ENABLED_STATICMEMORY=$enableval ], + [ ENABLED_STATICMEMORY=no ] + ) + +if test "x$ENABLED_STATICMEMORY" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY" + if test "x$ENABLED_FASTMATH" = "xno" + then + AC_MSG_ERROR([please use --enable-fastmath if enabling staticmemory.]) + fi + if test "$ENABLED_LOWRESOURCE" = "yes" && test "$ENABLED_RSA" = "no" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY_SMALL" + fi +fi + + +# microchip api +AC_ARG_ENABLE([mcapi], + [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" + 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" +then + AC_MSG_ERROR([please enable sha512 if enabling mcapi.]) +fi + +if test "$ENABLED_MCAPI" = "yes" && test "$ENABLED_ECC" = "no" +then + AC_MSG_ERROR([please enable ecc if enabling mcapi.]) +fi + +if test "$ENABLED_MCAPI" = "yes" && test "$ENABLED_LIBZ" = "no" +then + AC_MSG_ERROR([please use --with-libz if enabling mcapi.]) +fi + + +# Asynchronous Crypto +AC_ARG_ENABLE([asynccrypt], + [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 -DHAVE_WOLF_BIGINT -DWOLFSSL_NO_HASH_RAW" + + # 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 + + +# 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 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 + + +# cryptodev is old name, replaced with cryptocb +AC_ARG_ENABLE([cryptodev], + [AS_HELP_STRING([--enable-cryptodev],[DEPRECATED, use cryptocb instead])], + [ ENABLED_CRYPTOCB=$enableval ],[ ENABLED_CRYPTOCB=no ]) + +# Support for crypto callbacks +AC_ARG_ENABLE([cryptocb], + [AS_HELP_STRING([--enable-cryptocb],[Enable crypto callbacks (default: disabled)])], + [ ENABLED_CRYPTOCB=$enableval ], + [ ENABLED_CRYPTOCB=no ] + ) + +if test "x$ENABLED_PKCS11" = "xyes" +then + ENABLED_CRYPTOCB=yes +fi +if test "$ENABLED_CRYPTOCB" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLF_CRYPTO_CB" +fi + + +# Session Export +AC_ARG_ENABLE([sessionexport], + [AS_HELP_STRING([--enable-sessionexport],[Enable export and import of sessions (default: disabled)])], + [ ENABLED_SESSIONEXPORT=$enableval ], + [ ENABLED_SESSIONEXPORT=no ] + ) + +if test "$ENABLED_SESSIONEXPORT" = "yes" || + test "$ENABLED_SESSIONEXPORT" = "nopeer" +then + if test "$ENABLED_DTLS" = "no" + then + AC_MSG_ERROR([Only DTLS supported with session export]) + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SESSION_EXPORT" + + if test "$ENABLED_SESSIONEXPORT" = "nopeer" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SESSION_EXPORT_NOPEER" + fi +fi + + +# AES key wrap +AC_ARG_ENABLE([aeskeywrap], + [AS_HELP_STRING([--enable-aeskeywrap],[Enable AES key wrap support (default: disabled)])], + [ ENABLED_AESKEYWRAP=$enableval ], + [ 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" + AM_CFLAGS="$AM_CFLAGS -DNO_OLD_SHA_NAMES" +fi + + +# Memory Tests +AC_ARG_ENABLE([memtest], + [AS_HELP_STRING([--enable-memtest],[Memory testing option, for internal use (default: disabled)])], + [ ENABLED_MEMTEST=$enableval ], + [ ENABLED_MEMTEST=no ] + ) + +if test "x$ENABLED_MEMTEST" != "xno" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TRACK_MEMORY -DWOLFSSL_DEBUG_MEMORY -DWOLFSSL_FORCE_MALLOC_FAIL_TEST" +fi + + +# Enable hash flags support +# Hash flags are useful for runtime options such as SHA3 KECCAK256 selection +AC_ARG_ENABLE([hashflags], + [AS_HELP_STRING([--enable-hashflags],[Enable support for hash flags (default: disabled)])], + [ ENABLED_HASHFLAGS=$enableval ], + [ ENABLED_HASHFLAGS=no ] + ) + +if test "x$ENABLED_HASHFLAGS" != "xno" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HASH_FLAGS" +fi + +# Support for enabling setting default DH parameters in +AC_ARG_ENABLE([defaultdhparams], + [AS_HELP_STRING([--enable-dhdefaultparams],[Enables option for default dh parameters (default: disabled)])], + [ ENABLED_DHDEFAULTPARAMS=$enableval ], + [ ENABLED_DHDEFAULTPARAMS=no ] + ) +if test "$ENABLED_DHDEFAULTPARAMS" = "yes" || test "$ENABLED_QT" = "no" +then + ENABLED_DHDEFAULTPARAMS=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_DH_DEFAULT_PARAMS" +fi + +# User Settings +AC_ARG_ENABLE([usersettings], + [AS_HELP_STRING([--enable-usersettings],[Use your own user_settings.h and do not add Makefile CFLAGS (default: disabled)])], + [ ENABLED_USERSETTINGS=$enableval ], + [ ENABLED_USERSETTINGS=no ] + ) + + +# Default optimization CFLAGS enable +AC_ARG_ENABLE([optflags], + [AS_HELP_STRING([--enable-optflags],[Enable default optimization CFLAGS for the compiler (default: enabled)])], + [ ENABLED_OPTFLAGS=$enableval ], + [ ENABLED_OPTFLAGS=yes ] + ) + + +# check if should run the trusted peer certs test +# (for now checking both C_FLAGS and C_EXTRA_FLAGS) +AS_CASE(["$CFLAGS $CPPFLAGS"],[*'WOLFSSL_TRUST_PEER_CERT'*],[ENABLED_TRUSTED_PEER_CERT=yes]) + + +# 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 + + +# When building for wolfRand, strip out all options to disable everything. +AS_IF([test "x$ENABLED_FIPS" = "xyes" && test "x$FIPS_VERSION" = "xrand"], +[NEW_AM_CFLAGS="-DNO_AES -DNO_DH -DNO_ASN -DNO_RSA -DNO_SHA -DNO_MD5 -DNO_BIG_INT" +for v in $AM_CFLAGS +do + case $v in +-DHAVE_FFDHE_2048 | -DTFM_TIMING_RESISTANT | -DECC_TIMING_RESISTANT | \ +-DWC_RSA_BLINDING | -DHAVE_AESGCM | -DWOLFSSL_SHA512 | -DWOLFSSL_SHA384 | \ +-DHAVE_ECC | -DTFM_ECC256 | -DECC_SHAMIR | -DHAVE_TLS_EXTENSIONS | \ +-DHAVE_SUPPORTED_CURVES | -DHAVE_EXTENDED_MASTER | -DUSE_FAST_MATH) + AS_ECHO(["ignoring $v"]) + ;; + *) + NEW_AM_CFLAGS="$NEW_AM_CFLAGS $v" + ;; + esac +done +AM_CFLAGS=$NEW_AM_CFLAGS]) + + +################################################################################ +# Check for build-type conflicts # +################################################################################ + AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes" && \ test "x$ENABLED_LEANPSK" = "xyes"], [AC_MSG_ERROR([Cannot use Max Strength and Lean PSK at the same time.])]) +AS_IF([test "x$ENABLED_OCSP" = "xyes" && \ + test "x$ENABLED_ASN" = "xno"], + [AC_MSG_ERROR([please enable asn if enabling ocsp.])]) + +AS_IF([test "x$ENABLED_OCSP" = "xyes" && \ + test "x$ENABLED_RSA" = "xno" && \ + test "x$ENABLED_ECC" = "xno"], + [AC_MSG_ERROR([please enable rsa or ecc if enabling ocsp.])]) + +# Sync Intel QA and Sync Cavium Octeon require the crypto callback +AS_IF([test "x$ENABLED_INTEL_QA_SYNC" = "xyes" || test "x$ENABLED_OCTEON_SYNC" = "xyes"], + [AS_IF([test "x$ENABLED_CRYPTOCB" = "xno"], + [AC_MSG_ERROR([please enable the crypto callback support using --enable-cryptocb])])]) + +# checks for pkcs7 needed enables +AS_IF([test "x$ENABLED_PKCS7" = "xyes" && \ + test "x$ENABLED_RSA" = "xno" && \ + test "x$ENABLED_ECC" = "xno"], + [AC_MSG_ERROR([please enable ecc or rsa if enabling pkcs7.])]) + +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.])]) + +AS_IF([test "x$ENABLED_SNIFFER" = "xyes" && \ + test "x$ENABLED_RSA" = "xno"], + [AC_MSG_ERROR([please enable rsa if enabling sniffer.])]) + +# Lean TLS forces off prereqs of SCEP. +AS_IF([test "x$ENABLED_SCEP" = "xyes" && \ + test "x$ENABLED_LEANTLS" = "xyes"], + [AC_MSG_ERROR([Cannot use SCEP and Lean TLS at the same time.])]) + +# CMAC currently requires AES. +AS_IF([test "x$ENABLED_CMAC" = "xyes" && \ + test "x$ENABLED_AES" = "xno"], + [AC_MSG_ERROR([cannot use CMAC without AES.])]) + +################################################################################ +# Update CFLAGS based on options # +################################################################################ + +AS_IF([test "x$ENABLED_MCAPI" = "xyes"], + [AS_IF([test "x$ENABLED_DES3" = "xno"],[ENABLED_DES3="yes"])]) + +if test "$ENABLED_WOLFSCEP" = "yes" +then + # Enable prereqs if not already enabled + if test "x$ENABLED_KEYGEN" = "xno" + then + ENABLED_KEYGEN="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KEY_GEN" + fi + if test "x$ENABLED_CERTGEN" = "xno" + then + ENABLED_CERTGEN="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN" + fi + if test "x$ENABLED_CERTREQ" = "xno" + then + ENABLED_CERTREQ="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_REQ" + fi + if test "x$ENABLED_CERTEXT" = "xno" + then + ENABLED_CERTEXT="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" + fi + if test "x$ENABLED_PKCS7" = "xno" + then + ENABLED_PKCS7="yes" + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_WOLFSCEP" +fi +#if test "$ENABLED_SP_MATH" = "yes" && test "$ENABLED_KEYGEN" = "yes"; then +# AC_MSG_ERROR([Cannot use single precision math and key generation]) +#fi + +if test "x$ENABLED_PKCS7" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_PKCS7" + # Enable prereqs if not already enabled + if test "x$ENABLED_AESKEYWRAP" = "xno" + then + ENABLED_AESKEYWRAP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_KEYWRAP -DWOLFSSL_AES_DIRECT" + fi + if test "x$ENABLED_X963KDF" = "xno" && test "$ENABLED_ECC" = "yes" + then + ENABLED_X963KDF="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_X963_KDF" + fi +fi + +if test "x$ENABLED_DES3" = "xno" +then + AM_CFLAGS="$AM_CFLAGS -DNO_DES3" +else + # turn off DES3 if leanpsk or leantls on + if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DNO_DES3" + ENABLED_DES3=no + fi +fi + -# Update CFLAGS based on options AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MAX_STRENGTH"]) @@ -1980,13 +5067,73 @@ AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes" && \ [AM_CFLAGS="$AM_CFLAGS -DNO_OLD_TLS" ENABLED_OLD_TLS=no]) +AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes" && \ + test "x$ENABLED_SSLV3" = "xyes"], + [AC_MSG_ERROR([Cannot use Max Strength and SSLv3 at the same time.])]) + +AS_IF([test "x$ENABLED_SCTP" = "xyes"], + [AM_CFLAGS="-DWOLFSSL_SCTP $AM_CFLAGS"]) + +AS_IF([test "x$ENABLED_MCAST" = "xyes"], + [AM_CFLAGS="-DWOLFSSL_MULTICAST $AM_CFLAGS"]) + +# WOLFSSL_AFALG does not support SHA224 yet +AS_IF([(test "x$ENABLED_AFALG" = "xyes") && (test "x$ENABLED_SHA224" = "xyes")], + [AC_MSG_ERROR([--enable-sha224 with --enable-afalg not yet supported])]) + +# WOLFSSL_DEVCRYPTO does not support SHA224 yet +AS_IF([(test "x$ENABLED_DEVCRYPTO" = "xyes") && (test "x$ENABLED_SHA224" = "xyes")], + [AC_MSG_ERROR([--enable-sha224 with --enable-devcrypto not yet supported])]) + +# 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])]) + ]) + +if test "x$ENABLED_OPENSSLCOEXIST" = "xyes"; then + if test "x$ENABLED_OPENSSLALL" = "xyes"; then + AC_MSG_ERROR([Cannot use --enable-opensslcoexist with --enable-opensslall]) + fi + if test "x$ENABLED_OPENSSLEXTRA" = "xyes"; then + AC_MSG_ERROR([Cannot use --enable-opensslcoexist with --enable-opensslextra]) + fi +fi +################################################################################ + +# USER SETTINGS +if test "x$ENABLED_USERSETTINGS" = "xyes" +then + # Replace all options and just use WOLFSSL_USER_SETTINGS + AM_CFLAGS="-DWOLFSSL_USER_SETTINGS" +fi # OPTIMIZE FLAGS -if test "$GCC" = "yes" +# For distro disable custom build options that interfere with symbol generation +if test "$GCC" = "yes" && test "$ENABLED_DISTRO" = "no" then AM_CFLAGS="$AM_CFLAGS -Wall -Wno-unused" if test "$ax_enable_debug" = "no" then + AS_IF([test "x$ENABLED_OPTFLAGS" = "xyes"], [ if test "$ENABLED_FASTMATH" = "yes" then AM_CFLAGS="$AM_CFLAGS $OPTIMIZE_FAST_CFLAGS" @@ -1997,6 +5144,7 @@ then else AM_CFLAGS="$AM_CFLAGS $OPTIMIZE_CFLAGS" fi + ]) fi fi @@ -2006,38 +5154,161 @@ then AM_CFLAGS="$AM_CFLAGS -wd10006" fi +# Expose HAVE___UINT128_T to options flags" +if test "$ac_cv_type___uint128_t" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE___UINT128_T=1" +fi + LIB_SOCKET_NSL AX_HARDEN_CC_COMPILER_FLAGS -# link to ws2_32 if on mingw +# if mingw then link to ws2_32 for sockets case $host_os in - *mingw32) - LDFLAGS="$LDFLAGS -lws2_32" ;; + mingw*) + LDFLAGS="$LDFLAGS -lws2_32" + if test "$enable_shared" = "yes" + then + AC_DEFINE([WOLFSSL_DLL], [1], [Use __declspec(dllexport) when building library]) + if test "$enable_static" = "yes" + then + MINGW_LIB_WARNING="yes" + fi + fi ;; esac -# add user C_EXTRA_FLAGS back -CFLAGS="$CFLAGS $USER_C_EXTRA_FLAGS" -OPTION_FLAGS="$USER_C_EXTRA_FLAGS $AM_CFLAGS" + +# The following AM_CONDITIONAL statements set flags for use in the Makefiles. +# Some of these affect build targets and objects, some trigger different +# test scripts for make check. +AM_CONDITIONAL([BUILD_DISTRO],[test "x$ENABLED_DISTRO" = "xyes"]) +AM_CONDITIONAL([BUILD_ALL],[test "x$ENABLED_ALL" = "xyes"]) +AM_CONDITIONAL([BUILD_TLS13],[test "x$ENABLED_TLS13" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_RNG],[test "x$ENABLED_RNG" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SCTP],[test "x$ENABLED_SCTP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_MCAST],[test "x$ENABLED_MCAST" = "xyes"]) +AM_CONDITIONAL([BUILD_IPV6],[test "x$ENABLED_IPV6" = "xyes"]) +AM_CONDITIONAL([BUILD_LEANPSK],[test "x$ENABLED_LEANPSK" = "xyes"]) +AM_CONDITIONAL([BUILD_LEANTLS],[test "x$ENABLED_LEANTLS" = "xyes"]) +AM_CONDITIONAL([BUILD_LOWMEM],[test "x$ENABLED_LOWRESOURCE" = "xyes"]) +AM_CONDITIONAL([BUILD_PKCALLBACKS], [ test "x$ENABLED_PKCALLBACKS" = "xyes"]) +AM_CONDITIONAL([BUILD_CRYPTOAUTHLIB],[test "x$ENABLED_CRYPTOAUTHLIB" = "xyes"]) +AM_CONDITIONAL([BUILD_SNIFFER], [ test "x$ENABLED_SNIFFER" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SNIFFTEST],[ test "x$ENABLED_SNIFFTEST" = "xyes"]) +AM_CONDITIONAL([BUILD_AESGCM],[test "x$ENABLED_AESGCM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_AESCCM],[test "x$ENABLED_AESCCM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_ARMASM],[test "x$ENABLED_ARMASM" = "xyes"]) +AM_CONDITIONAL([BUILD_XILINX],[test "x$ENABLED_XILINX" = "xyes"]) +AM_CONDITIONAL([BUILD_AESNI],[test "x$ENABLED_AESNI" = "xyes"]) +AM_CONDITIONAL([BUILD_INTELASM],[test "x$ENABLED_INTELASM" = "xyes"]) +AM_CONDITIONAL([BUILD_AFALG],[test "x$ENABLED_AFALG" = "xyes"]) +AM_CONDITIONAL([BUILD_DEVCRYPTO],[test "x$ENABLED_DEVCRYPTO" = "xyes"]) +AM_CONDITIONAL([BUILD_CAMELLIA],[test "x$ENABLED_CAMELLIA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_MD2],[test "x$ENABLED_MD2" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_RIPEMD],[test "x$ENABLED_RIPEMD" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_BLAKE2],[test "x$ENABLED_BLAKE2" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_BLAKE2S],[test "x$ENABLED_BLAKE2S" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SHA512],[test "x$ENABLED_SHA512" = "xyes" || test "x$ENABLED_SHA384" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_DSA],[test "x$ENABLED_DSA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_ECC],[test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_ED25519],[test "x$ENABLED_ED25519" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_ED25519_SMALL],[test "x$ENABLED_ED25519_SMALL" = "xyes"]) +AM_CONDITIONAL([BUILD_FEMATH], [test "x$ENABLED_FEMATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_GEMATH], [test "x$ENABLED_GEMATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CURVE25519],[test "x$ENABLED_CURVE25519" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CURVE25519_SMALL],[test "x$ENABLED_CURVE25519_SMALL" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_ED448],[test "x$ENABLED_ED448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_ED448_SMALL],[test "x$ENABLED_ED448_SMALL" = "xyes"]) +AM_CONDITIONAL([BUILD_FE448], [test "x$ENABLED_FE448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_GE448], [test "x$ENABLED_GE448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CURVE448],[test "x$ENABLED_CURVE448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CURVE448_SMALL],[test "x$ENABLED_CURVE448_SMALL" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_MEMORY],[test "x$ENABLED_MEMORY" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_RSA],[test "x$ENABLED_RSA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_DH],[test "x$ENABLED_DH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_ASN],[test "x$ENABLED_ASN" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_AES],[test "x$ENABLED_AES" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CODING],[test "x$ENABLED_CODING" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_IDEA],[test "x$ENABLED_IDEA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_RC4],[test "x$ENABLED_ARC4" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_MD5],[test "x$ENABLED_MD5" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SHA],[test "x$ENABLED_SHA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_HC128],[test "x$ENABLED_HC128" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_RABBIT],[test "x$ENABLED_RABBIT" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_FIPS],[test "x$ENABLED_FIPS" = "xyes"]) +AM_CONDITIONAL([BUILD_FIPS_V1],[test "x$FIPS_VERSION" = "xv1"]) +AM_CONDITIONAL([BUILD_FIPS_V2],[test "x$FIPS_VERSION" = "xv2"]) +AM_CONDITIONAL([BUILD_FIPS_RAND],[test "x$FIPS_VERSION" = "xrand"]) +AM_CONDITIONAL([BUILD_CMAC],[test "x$ENABLED_CMAC" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SELFTEST],[test "x$ENABLED_SELFTEST" = "xyes"]) +AM_CONDITIONAL([BUILD_SHA224],[test "x$ENABLED_SHA224" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SHA3],[test "x$ENABLED_SHA3" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_POLY1305],[test "x$ENABLED_POLY1305" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CHACHA],[test "x$ENABLED_CHACHA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_INLINE],[test "x$ENABLED_INLINE" = "xyes"]) +AM_CONDITIONAL([BUILD_OCSP],[test "x$ENABLED_OCSP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_OCSP_STAPLING],[test "x$ENABLED_CERTIFICATE_STATUS_REQUEST" = "xyes"]) +AM_CONDITIONAL([BUILD_OCSP_STAPLING_V2],[test "x$ENABLED_CERTIFICATE_STATUS_REQUEST_V2" = "xyes"]) +AM_CONDITIONAL([BUILD_CRL],[test "x$ENABLED_CRL" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CRL_MONITOR],[test "x$ENABLED_CRL_MONITOR" = "xyes"]) +AM_CONDITIONAL([BUILD_USER_RSA],[test "x$ENABLED_USER_RSA" = "xyes"] ) +AM_CONDITIONAL([BUILD_USER_CRYPTO],[test "x$ENABLED_USER_CRYPTO" = "xyes"]) +AM_CONDITIONAL([BUILD_NTRU],[test "x$ENABLED_NTRU" = "xyes"]) +AM_CONDITIONAL([BUILD_WNR],[test "x$ENABLED_WNR" = "xyes"]) +AM_CONDITIONAL([BUILD_SRP],[test "x$ENABLED_SRP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([USE_VALGRIND],[test "x$ENABLED_VALGRIND" = "xyes"]) +AM_CONDITIONAL([BUILD_MD4],[test "x$ENABLED_MD4" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_PWDBASED],[test "x$ENABLED_PWDBASED" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SCRYPT],[test "x$ENABLED_SCRYPT" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CRYPTONLY],[test "x$ENABLED_CRYPTONLY" = "xyes" && test "x$ENABLED_OPENSSLEXTRA" = "xno"]) +AM_CONDITIONAL([BUILD_FASTMATH],[test "x$ENABLED_FASTMATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SLOWMATH],[test "x$ENABLED_SLOWMATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_EXAMPLE_SERVERS],[test "x$ENABLED_EXAMPLES" = "xyes" && test "x$ENABLED_LEANTLS" = "xno"]) +AM_CONDITIONAL([BUILD_EXAMPLE_CLIENTS],[test "x$ENABLED_EXAMPLES" = "xyes"]) +AM_CONDITIONAL([BUILD_TESTS],[test "x$ENABLED_EXAMPLES" = "xyes" && test "x$ENABLED_LEANTLS" = "xno"]) +AM_CONDITIONAL([BUILD_THREADED_EXAMPLES],[test "x$ENABLED_SINGLETHREADED" = "xno" && test "x$ENABLED_EXAMPLES" = "xyes" && test "x$ENABLED_LEANTLS" = "xno"]) +AM_CONDITIONAL([BUILD_WOLFCRYPT_TESTS],[test "x$ENABLED_CRYPT_TESTS" = "xyes"]) +AM_CONDITIONAL([BUILD_LIBZ],[test "x$ENABLED_LIBZ" = "xyes"]) +AM_CONDITIONAL([BUILD_PKCS11],[test "x$ENABLED_PKCS11" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_PKCS12],[test "x$ENABLED_PKCS12" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CAVIUM],[test "x$ENABLED_CAVIUM" = "xyes"]) +AM_CONDITIONAL([BUILD_CAVIUM_V],[test "x$ENABLED_CAVIUM_V" = "xyes"]) +AM_CONDITIONAL([BUILD_OCTEON_SYNC],[test "x$ENABLED_OCTEON_SYNC" = "xyes"]) +AM_CONDITIONAL([BUILD_INTEL_QA],[test "x$ENABLED_INTEL_QA" = "xyes"]) +AM_CONDITIONAL([BUILD_INTEL_QA_SYNC],[test "x$ENABLED_INTEL_QA_SYNC" = "xyes"]) +AM_CONDITIONAL([BUILD_SP],[test "x$ENABLED_SP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SP_C],[(test "x$ENABLED_SP" = "xyes" && test "x$ENABLED_SP_ASM" = "xno") || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SP_ARM64],[test "x$ENABLED_SP_ARM64_ASM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SP_ARM32],[test "x$ENABLED_SP_ARM32_ASM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SP_ARM_THUMB],[test "x$ENABLED_SP_ARM_THUMB_ASM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SP_ARM_CORTEX],[test "x$ENABLED_SP_ARM_CORTEX_ASM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SP_X86_64],[test "x$ENABLED_SP_X86_64_ASM" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_SP_INT],[test "x$ENABLED_SP_MATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_FAST_RSA],[test "x$ENABLED_FAST_RSA" = "xyes"]) +AM_CONDITIONAL([BUILD_MCAPI],[test "x$ENABLED_MCAPI" = "xyes"]) +AM_CONDITIONAL([BUILD_ASYNCCRYPT],[test "x$ENABLED_ASYNCCRYPT" = "xyes"]) +AM_CONDITIONAL([BUILD_WOLFEVENT],[test "x$ENABLED_ASYNCCRYPT" = "xyes"]) +AM_CONDITIONAL([BUILD_CRYPTOCB],[test "x$ENABLED_CRYPTOCB" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_PSK],[test "x$ENABLED_PSK" = "xyes"]) +AM_CONDITIONAL([BUILD_TRUST_PEER_CERT],[test "x$ENABLED_TRUSTED_PEER_CERT" = "xyes"]) +AM_CONDITIONAL([BUILD_PKI],[test "x$ENABLED_PKI" = "xyes"]) +AM_CONDITIONAL([BUILD_DES3],[test "x$ENABLED_DES3" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_PKCS7],[test "x$ENABLED_PKCS7" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_HASHFLAGS],[test "x$ENABLED_HASHFLAGS" = "xyes"]) + CREATE_HEX_VERSION AC_SUBST([AM_CPPFLAGS]) AC_SUBST([AM_CFLAGS]) AC_SUBST([AM_LDFLAGS]) +AC_SUBST([AM_CCASFLAGS]) +AC_SUBST([LIB_ADD]) +AC_SUBST([LIB_STATIC_ADD]) # FINAL AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h]) -AC_CONFIG_FILES([Makefile]) -AC_CONFIG_FILES([wolfssl/version.h]) -AC_CONFIG_FILES([wolfssl/options.h]) -#have options.h and version.h for autoconf fips tag and build -#if test "x$ENABLED_FIPS" = "xyes" -#then -# AC_CONFIG_FILES([cyassl/version.h]) -# AC_CONFIG_FILES([cyassl/options.h]) -#fi -AC_CONFIG_FILES([support/wolfssl.pc]) -AC_CONFIG_FILES([rpm/spec]) +AC_CONFIG_FILES([Makefile wolfssl/version.h wolfssl/options.h cyassl/options.h support/wolfssl.pc rpm/spec]) AX_CREATE_GENERIC_CONFIG AX_AM_JOBSERVER([yes]) @@ -2049,55 +5320,48 @@ AC_OUTPUT echo "---" echo "Running make clean..." make clean >/dev/null 2>&1 -# Touch files that may not be in repository -echo "Touching File..." -touch ctaocrypt/src/fips.c -touch ctaocrypt/src/fips_test.c -echo -# generate user options header +# generate user options header echo "---" echo "Generating user options header..." OPTION_FILE="wolfssl/options.h" -#if -#OPTION_FILE+="cyassl/options.h" -#fi rm -f $OPTION_FILE -echo "/* wolfssl options.h" > $OPTION_FILE +echo "/* wolfssl options.h" > $OPTION_FILE echo " * generated from configure options" >> $OPTION_FILE echo " *" >> $OPTION_FILE -echo " * Copyright (C) 2006-2015 wolfSSL Inc." >> $OPTION_FILE +echo " * Copyright (C) 2006-2020 wolfSSL Inc." >> $OPTION_FILE echo " *" >> $OPTION_FILE echo " * This file is part of wolfSSL. (formerly known as CyaSSL)" >> $OPTION_FILE echo " *" >> $OPTION_FILE echo " */" >> $OPTION_FILE -echo "" >> $OPTION_FILE -echo "#pragma once" >> $OPTION_FILE -echo "" >> $OPTION_FILE -echo "#ifdef __cplusplus" >> $OPTION_FILE -echo "extern \"C\" {" >> $OPTION_FILE -echo "#endif" >> $OPTION_FILE -echo "" >> $OPTION_FILE +echo "" >> $OPTION_FILE +echo "#ifndef WOLFSSL_OPTIONS_H" >> $OPTION_FILE +echo "#define WOLFSSL_OPTIONS_H" >> $OPTION_FILE +echo "" >> $OPTION_FILE +echo "" >> $OPTION_FILE +echo "#ifdef __cplusplus" >> $OPTION_FILE +echo "extern \"C\" {" >> $OPTION_FILE +echo "#endif" >> $OPTION_FILE +echo "" >> $OPTION_FILE -for option in $OPTION_FLAGS; do - defonly=`echo $option | sed 's/-D//'` +for option in $CPPFLAGS $AM_CPPFLAGS $CFLAGS $AM_CFLAGS; do + defonly=`echo $option | sed 's/^-D//'` if test "$defonly" != "$option" then noequalsign=`echo $defonly | sed 's/=/ /'` if test "$noequalsign" = "NDEBUG" || test "$noequalsign" = "DEBUG" then - echo "not outputing (N)DEBUG to $OPTION_FILE" + echo "not outputting (N)DEBUG to $OPTION_FILE" continue fi - # allow user to igonore system options - ignoresys=no - if [[[ $noequalsign == _* ]]] ; + # allow user to ignore system options + ignoresys=$(echo "$noequalsign" | grep '^_.*') + if test -n "$ignoresys" then - ignoresys=yes echo "#ifndef WOLFSSL_OPTIONS_IGNORE_SYS" >> $OPTION_FILE fi @@ -2105,7 +5369,7 @@ for option in $OPTION_FLAGS; do echo "#undef $noarg" >> $OPTION_FILE echo "#define $noequalsign" >> $OPTION_FILE - if test "$ignoresys" = "yes" + if test -n "$ignoresys" then echo "#endif" >> $OPTION_FILE fi @@ -2116,14 +5380,17 @@ for option in $OPTION_FLAGS; do fi done -echo "" >> $OPTION_FILE -echo "#ifdef __cplusplus" >> $OPTION_FILE -echo "}" >> $OPTION_FILE -echo "#endif" >> $OPTION_FILE -echo "" >> $OPTION_FILE +echo "" >> $OPTION_FILE +echo "#ifdef __cplusplus" >> $OPTION_FILE +echo "}" >> $OPTION_FILE +echo "#endif" >> $OPTION_FILE +echo "" >> $OPTION_FILE +echo "" >> $OPTION_FILE +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 @@ -2134,96 +5401,213 @@ do echo "$line" >> cyassl/options.h done < $OPTION_FILE +# switch ifdef protection in cyassl/option.h to CYASSL_OPTONS_H, remove bak +sed -i.bak 's/WOLFSSL_OPTIONS_H/CYASSL_OPTIONS_H/g' cyassl/options.h + +# workaround for mingw sed that may get "Permission denied" trying to preserver permissions +case $host_os in + mingw*) + chmod u+w cyassl/options.h ;; +esac + +rm cyassl/options.h.bak + + # output config summary echo "---" echo "Configuration summary for $PACKAGE_NAME version $VERSION" echo "" -echo " * Installation prefix: $prefix" -echo " * System type: $host_vendor-$host_os" -echo " * Host CPU: $host_cpu" -echo " * C Compiler: $CC" -echo " * C Flags: $CFLAGS" -echo " * C++ Compiler: $CXX" -echo " * C++ Flags: $CXXFLAGS" -echo " * CPP Flags: $CPPFLAGS" -echo " * LIB Flags: $LIB" -echo " * Debug enabled: $ax_enable_debug" -echo " * Warnings as failure: $ac_cv_warnings_as_errors" -echo " * make -j: $enable_jobserver" -echo " * VCS checkout: $ac_cv_vcs_checkout" -echo +echo " * Installation prefix: $prefix" +echo " * System type: $host_vendor-$host_os" +echo " * Host CPU: $host_cpu" +echo " * C Compiler: $CC" +echo " * C Flags: $CFLAGS" +echo " * C++ Compiler: $CXX" +echo " * C++ Flags: $CXXFLAGS" +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" +echo echo " Features " -echo " * Single threaded: $ENABLED_SINGLETHREADED" -echo " * Filesystem: $ENABLED_FILESYSTEM" -echo " * OpenSSL Extra API: $ENABLED_OPENSSLEXTRA" -echo " * Max Strength Build: $ENABLED_MAXSTRENGTH" -echo " * fastmath: $ENABLED_FASTMATH" -echo " * sniffer: $ENABLED_SNIFFER" -echo " * snifftest: $ENABLED_SNIFFTEST" -echo " * ARC4: $ENABLED_ARC4" -echo " * AES: $ENABLED_AES" -echo " * AES-NI: $ENABLED_AESNI" -echo " * AES-GCM: $ENABLED_AESGCM" -echo " * AES-CCM: $ENABLED_AESCCM" -echo " * DES3: $ENABLED_DES3" -echo " * Camellia: $ENABLED_CAMELLIA" -echo " * NULL Cipher: $ENABLED_NULL_CIPHER" -echo " * MD5: $ENABLED_MD5" -echo " * RIPEMD: $ENABLED_RIPEMD" -echo " * SHA: $ENABLED_SHA" -echo " * SHA-512: $ENABLED_SHA512" -echo " * BLAKE2: $ENABLED_BLAKE2" -echo " * keygen: $ENABLED_KEYGEN" -echo " * certgen: $ENABLED_CERTGEN" -echo " * certreq: $ENABLED_CERTREQ" -echo " * HC-128: $ENABLED_HC128" -echo " * RABBIT: $ENABLED_RABBIT" -echo " * CHACHA: $ENABLED_CHACHA" -echo " * Hash DRBG: $ENABLED_HASHDRBG" -echo " * PWDBASED: $ENABLED_PWDBASED" -echo " * HKDF: $ENABLED_HKDF" -echo " * MD4: $ENABLED_MD4" -echo " * PSK: $ENABLED_PSK" -echo " * Poly1305: $ENABLED_POLY1305" -echo " * LEANPSK: $ENABLED_LEANPSK" -echo " * RSA: $ENABLED_RSA" -echo " * DSA: $ENABLED_DSA" -echo " * DH: $ENABLED_DH" -echo " * ECC: $ENABLED_ECC" -echo " * CURVE25519: $ENABLED_CURVE25519" -echo " * ED25519: $ENABLED_ED25519" -echo " * FPECC: $ENABLED_FPECC" -echo " * ECC_ENCRYPT: $ENABLED_ECC_ENCRYPT" -echo " * ASN: $ENABLED_ASN" -echo " * Anonymous cipher: $ENABLED_ANON" -echo " * CODING: $ENABLED_CODING" -echo " * MEMORY: $ENABLED_MEMORY" -echo " * I/O POOL: $ENABLED_IOPOOL" -echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" -echo " * DTLS: $ENABLED_DTLS" -echo " * Old TLS Versions: $ENABLED_OLD_TLS" -echo " * OCSP: $ENABLED_OCSP" -echo " * CRL: $ENABLED_CRL" -echo " * CRL-MONITOR: $ENABLED_CRL_MONITOR" -echo " * Persistent session cache: $ENABLED_SAVESESSION" -echo " * Persistent cert cache: $ENABLED_SAVECERT" -echo " * Atomic User Record Layer: $ENABLED_ATOMICUSER" -echo " * Public Key Callbacks: $ENABLED_PKCALLBACKS" -echo " * NTRU: $ENABLED_NTRU" -echo " * SNI: $ENABLED_SNI" -echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT" -echo " * Truncated HMAC: $ENABLED_TRUNCATED_HMAC" -echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION" -echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION" -echo " * Supported Elliptic Curves: $ENABLED_SUPPORTED_CURVES" -echo " * Session Ticket: $ENABLED_SESSION_TICKET" -echo " * All TLS Extensions: $ENABLED_TLSX" -echo " * PKCS#7 $ENABLED_PKCS7" -echo " * wolfSCEP $ENABLED_WOLFSCEP" -echo " * Small Stack: $ENABLED_SMALL_STACK" -echo " * valgrind unit tests: $ENABLED_VALGRIND" -echo " * LIBZ: $ENABLED_LIBZ" -echo " * Examples: $ENABLED_EXAMPLES" +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" +echo " * AES: $ENABLED_AES" +echo " * AES-NI: $ENABLED_AESNI" +echo " * AES-CBC: $ENABLED_AESCBC" +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" +echo " * NULL Cipher: $ENABLED_NULL_CIPHER" +echo " * MD5: $ENABLED_MD5" +echo " * RIPEMD: $ENABLED_RIPEMD" +echo " * SHA: $ENABLED_SHA" +echo " * SHA-224: $ENABLED_SHA224" +echo " * SHA-384: $ENABLED_SHA384" +echo " * SHA-512: $ENABLED_SHA512" +echo " * SHA3: $ENABLED_SHA3" +echo " * SHAKE256: $ENABLED_SHAKE256" +echo " * BLAKE2: $ENABLED_BLAKE2" +echo " * CMAC: $ENABLED_CMAC" +echo " * keygen: $ENABLED_KEYGEN" +echo " * certgen: $ENABLED_CERTGEN" +echo " * certreq: $ENABLED_CERTREQ" +echo " * certext: $ENABLED_CERTEXT" +echo " * certgencache: $ENABLED_certgencache" +echo " * HC-128: $ENABLED_HC128" +echo " * RABBIT: $ENABLED_RABBIT" +echo " * CHACHA: $ENABLED_CHACHA" +echo " * Hash DRBG: $ENABLED_HASHDRBG" +echo " * PWDBASED: $ENABLED_PWDBASED" +echo " * scrypt: $ENABLED_SCRYPT" +echo " * wolfCrypt Only: $ENABLED_CRYPTONLY" +echo " * HKDF: $ENABLED_HKDF" +echo " * X9.63 KDF: $ENABLED_X963KDF" +echo " * MD4: $ENABLED_MD4" +echo " * PSK: $ENABLED_PSK" +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 " * DH Default Parameters: $ENABLED_DHDEFAULTPARAMS" +echo " * ECC: $ENABLED_ECC" +echo " * ECC Custom Curves $ENABLED_ECCCUSTCURVES" +echo " * CURVE25519: $ENABLED_CURVE25519" +echo " * ED25519: $ENABLED_ED25519" +echo " * CURVE448: $ENABLED_CURVE448" +echo " * ED448: $ENABLED_ED448" +echo " * FPECC: $ENABLED_FPECC" +echo " * ECC_ENCRYPT: $ENABLED_ECC_ENCRYPT" +echo " * ASN: $ENABLED_ASN" +echo " * Anonymous cipher: $ENABLED_ANON" +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 " * Apache httpd: $ENABLED_APACHE_HTTPD" +echo " * NGINX: $ENABLED_NGINX" +echo " * ASIO: $ENABLED_ASIO" +echo " * LIBWEBSOCKETS: $ENABLED_LIBWEBSOCKETS" +echo " * Qt $ENABLED_QT" +echo " * Qt Unit Testing $ENABLED_QT_TEST" +echo " * SIGNAL: $ENABLED_SIGNAL" +echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" +echo " * DTLS: $ENABLED_DTLS" +echo " * SCTP: $ENABLED_SCTP" +echo " * Indefinite Length: $ENABLED_BER_INDEF" +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 " * TLS v1.3 Draft 22: $ENABLED_TLS13_DRAFT22" +echo " * TLS v1.3 Draft 23: $ENABLED_TLS13_DRAFT23" +echo " * TLS v1.3 Draft 26: $ENABLED_TLS13_DRAFT26" +echo " * TLS v1.3 Draft 28: $ENABLED_TLS13_DRAFT28" +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" +echo " * CRL: $ENABLED_CRL" +echo " * CRL-MONITOR: $ENABLED_CRL_MONITOR" +echo " * Persistent session cache: $ENABLED_SAVESESSION" +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" +echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT" +echo " * Trusted CA Indication: $ENABLED_TRUSTED_CA" +echo " * Truncated HMAC: $ENABLED_TRUNCATED_HMAC" +echo " * Supported Elliptic Curves: $ENABLED_SUPPORTED_CURVES" +echo " * FFDHE only in client: $ENABLED_FFDHE_ONLY" +echo " * Session Ticket: $ENABLED_SESSION_TICKET" +echo " * Extended Master Secret: $ENABLED_EXTENDED_MASTER" +echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION" +echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION" +echo " * Fallback SCSV: $ENABLED_FALLBACK_SCSV" +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" +echo " * valgrind unit tests: $ENABLED_VALGRIND" +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 " * PKCS#11: $ENABLED_PKCS11" +echo " * PKCS#12: $ENABLED_PKCS12" +echo " * Cavium Nitox: $ENABLED_CAVIUM" +echo " * Cavium Octeon (Sync): $ENABLED_OCTEON_SYNC" +echo " * Intel Quick Assist: $ENABLED_INTEL_QA" +echo " * ARM ASM: $ENABLED_ARMASM" +echo " * AES Key Wrap: $ENABLED_AESKEYWRAP" +echo " * Write duplicate: $ENABLED_WRITEDUP" +echo " * Xilinx Hardware Acc.: $ENABLED_XILINX" +echo " * Inline Code: $ENABLED_INLINE" +echo " * Linux AF_ALG: $ENABLED_AFALG" +echo " * Linux devcrypto: $ENABLED_DEVCRYPTO" +echo " * Crypto callbacks: $ENABLED_CRYPTOCB" echo "" echo "---" +################################################################################ +# Show warnings at bottom so they are noticed +################################################################################ + +if test "$ENABLED_ASYNCCRYPT" = "yes" +then + AC_MSG_WARN([Make sure real async files are loaded. Contact wolfSSL for details on using the asynccrypt option.]) +fi + +# MinGW static vs shared library +# Reference URL from libtool for MinGW is located at +# http://www.gnu.org/software/libtool/manual/libtool.html#Cygwin-to-MinGW-Cross +# this allows for not even having dllimport/dllexport on functions +# with recent libtools, only requiring it with global variables. +# +# The following warning is displayed here because if not using "contemporary GNU +# tools" there is the possibility of export/import issues. +# wolfSSL uses __declspec(dllexport) and "contemporary GNU tools" handle the +# case where both static and shared libraries are built. +# +# More can be found about the MinGW linker at +# https://sourceware.org/binutils/docs/ld/WIN32.html +if test "$MINGW_LIB_WARNING" = "yes" +then + AC_MSG_WARN([Building with shared and static library at the same time on this system may cause export/import problems when using non contemporary GNU tools.]) +fi + diff --git a/FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/misc.c b/FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/misc.c index dc4198be8..bd127625d 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/misc.c +++ b/FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/misc.c @@ -1,8 +1,8 @@ /* misc.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,12 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef NO_INLINE #include #else /* for inline includes */ + #define WOLFSSL_MISC_INCLUDED #include #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/wolfcrypt_first.c b/FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/wolfcrypt_first.c index c694aa045..74e759a7a 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/wolfcrypt_first.c +++ b/FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/wolfcrypt_first.c @@ -1,8 +1,8 @@ /* wolfcrypt_first.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* This file needs to be linked first in order to work correctly */ #ifdef HAVE_CONFIG_H @@ -30,6 +31,12 @@ #ifdef HAVE_FIPS +#ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$a") + #pragma const_seg(".fipsB$a") +#endif + + /* read only start address */ const unsigned int wolfCrypt_FIPS_ro_start[] = { 0x1a2b3c4d, 0x00000001 }; diff --git a/FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/wolfcrypt_last.c b/FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/wolfcrypt_last.c index cdcd741a1..60cb33a4e 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/wolfcrypt_last.c +++ b/FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/wolfcrypt_last.c @@ -1,8 +1,8 @@ /* wolfcrypt_last.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* This file needs to be linked last in order to work correctly */ #ifdef HAVE_CONFIG_H @@ -30,6 +31,12 @@ #ifdef HAVE_FIPS +#ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$l") + #pragma const_seg(".fipsB$l") +#endif + + /* last function of text/code segment */ int wolfCrypt_FIPS_last(void); int wolfCrypt_FIPS_last(void) diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/callbacks.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/callbacks.h index f74f7a65e..69dd3476b 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/callbacks.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/callbacks.h @@ -1,8 +1,8 @@ /* callbacks.h * - * Copyright (C) 2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/crl.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/crl.h index 87e402f38..7f285a33e 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/crl.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/crl.h @@ -1,8 +1,8 @@ /* crl.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/aes.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/aes.h index 2bb213589..dae7812e8 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/aes.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/aes.h @@ -1,8 +1,8 @@ /* aes.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_AES #ifndef CTAO_CRYPT_AES_H @@ -55,11 +56,6 @@ #define AesCcmDecrypt wc_AesCcmDecrypt #endif /* HAVE_AESCCM */ -#ifdef HAVE_CAVIUM - #define AesInitCavium wc_AesInitCavium - #define AesFreeCavium wc_AesFreeCavium -#endif - #endif /* CTAO_CRYPT_AES_H */ #endif /* NO_AES */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/arc4.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/arc4.h index 965b079a0..627d79735 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/arc4.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/arc4.h @@ -1,8 +1,8 @@ /* arc4.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,20 +16,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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_ARC4_H #define CTAO_CRYPT_ARC4_H /* for arc4 reverse compatibility */ #ifndef NO_RC4 #include - #define CYASSL_ARC4_CAVIUM_MAGIC WOLFSSL_ARC4_CAVIUM_MAGIC #define Arc4Process wc_Arc4Process #define Arc4SetKey wc_Arc4SetKey - #define Arc4InitCavium wc_Arc4InitCavium - #define Arc4FreeCavium wc_Arc4FreeCavium + #define Arc4AsyncInit wc_Arc4AsyncInit + #define Arc4AsyncFree wc_Arc4AsyncFree #endif #endif /* CTAO_CRYPT_ARC4_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/asn.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/asn.h index c27c144dd..673cce748 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/asn.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/asn.h @@ -1,8 +1,8 @@ /* asn.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_ASN #ifndef CTAO_CRYPT_ASN_H @@ -37,10 +38,8 @@ #include -#ifndef WOLFSSL_PEMCERT_TODER_DEFINED #ifndef NO_FILESYSTEM - #define CyaSSL_PemCertToDer wolfSSL_PemCertToDer -#endif + #define CyaSSL_PemCertToDer wc_PemCertToDer #endif #endif /* CTAO_CRYPT_ASN_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/asn_public.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/asn_public.h index 040734eab..5e75943f0 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/asn_public.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/asn_public.h @@ -1,8 +1,8 @@ /* asn_public.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_ASN_PUBLIC_H #define CTAO_CRYPT_ASN_PUBLIC_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/blake2-impl.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/blake2-impl.h index fc5ec3a49..e815f0769 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/blake2-impl.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/blake2-impl.h @@ -12,9 +12,9 @@ */ /* blake2-impl.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -28,15 +28,16 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAOCRYPT_BLAKE2_IMPL_H #define CTAOCRYPT_BLAKE2_IMPL_H #include -#include +#include #endif /* CTAOCRYPT_BLAKE2_IMPL_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/blake2-int.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/blake2-int.h index 07ea8e745..77244a232 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/blake2-int.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/blake2-int.h @@ -12,9 +12,9 @@ */ /* blake2-int.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -28,16 +28,17 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAOCRYPT_BLAKE2_INT_H #define CTAOCRYPT_BLAKE2_INT_H #include -#include +#include #endif /* CTAOCRYPT_BLAKE2_INT_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/blake2.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/blake2.h index b7749173c..c1378d9cd 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/blake2.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/blake2.h @@ -1,8 +1,8 @@ /* blake2.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_BLAKE2 #ifndef CTAOCRYPT_BLAKE2_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/camellia.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/camellia.h index bbe7dcf1b..8c0ce8d4c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/camellia.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/camellia.h @@ -1,8 +1,8 @@ /* camellia.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_CAMELLIA_H #define CTAO_CRYPT_CAMELLIA_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/chacha.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/chacha.h index 7651d28af..bfe099851 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/chacha.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/chacha.h @@ -1,8 +1,8 @@ /* chacha.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_CHACHA_H #define CTAO_CRYPT_CHACHA_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/coding.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/coding.h index 47f5d2533..9902a5aba 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/coding.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/coding.h @@ -1,8 +1,8 @@ /* coding.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_CODING_H #define CTAO_CRYPT_CODING_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/compress.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/compress.h index 632af2ec3..6bb26c6b0 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/compress.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/compress.h @@ -1,8 +1,8 @@ /* compress.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_LIBZ #ifndef CTAO_CRYPT_COMPRESS_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/des3.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/des3.h index c6fbaa8b7..8e355196d 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/des3.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/des3.h @@ -1,8 +1,8 @@ /* des3.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_DES3 #ifndef CTAO_CRYPT_DES3_H @@ -38,9 +39,9 @@ #define Des3_CbcEncrypt wc_Des3_CbcEncrypt #define Des3_CbcDecrypt wc_Des3_CbcDecrypt #define Des3_CbcDecryptWithKey wc_Des3_CbcDecryptWithKey -#ifdef HAVE_CAVIUM - #define Des3_InitCavium wc_Des3_InitCavium - #define Des3_FreeCavium wc_Des3_FreeCavium +#ifdef WOLFSSL_ASYNC_CRYPT + #define Des3AsyncInit wc_Des3AsyncInit + #define Des3AsyncFree wc_Des3AsyncFree #endif #endif /* NO_DES3 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/dh.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/dh.h index 4bd7757b5..80d4e51d3 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/dh.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/dh.h @@ -1,8 +1,8 @@ /* dh.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_DH #ifndef CTAO_CRYPT_DH_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/dsa.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/dsa.h index bdc8cd5ac..d99429081 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/dsa.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/dsa.h @@ -1,8 +1,8 @@ /* dsa.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_DSA #ifndef CTAO_CRYPT_DSA_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/ecc.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/ecc.h index 3ae13f76d..b4b2f96c4 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/ecc.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/ecc.h @@ -1,8 +1,8 @@ /* ecc.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_ECC #ifndef CTAO_CRYPT_ECC_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/error-crypt.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/error-crypt.h index f20145543..55a973947 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/error-crypt.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/error-crypt.h @@ -1,8 +1,8 @@ /* error-crypt.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_ERROR_H #define CTAO_CRYPT_ERROR_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/fips_test.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/fips_test.h index 12e1ce0a0..cdfad6cae 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/fips_test.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/fips_test.h @@ -1,8 +1,8 @@ /* fips_test.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_FIPS_TEST_H #define CTAO_CRYPT_FIPS_TEST_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/hc128.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/hc128.h index b2c9bc9d3..af1186bde 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/hc128.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/hc128.h @@ -1,8 +1,8 @@ /* hc128.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_HC128 #ifndef CTAO_CRYPT_HC128_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/hmac.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/hmac.h index 4625f10ea..4c0dd153a 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/hmac.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/hmac.h @@ -1,8 +1,8 @@ /* hmac.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_HMAC #ifndef CTAO_CRYPT_HMAC_H @@ -29,9 +30,9 @@ #define HmacSetKey wc_HmacSetKey #define HmacUpdate wc_HmacUpdate #define HmacFinal wc_HmacFinal -#ifdef HAVE_CAVIUM - #define HmacInitCavium wc_HmacInitCavium - #define HmacFreeCavium wc_HmacFreeCavium +#ifdef WOLFSSL_ASYNC_CRYPT + #define HmacAsyncInit wc_HmacAsyncInit + #define HmacAsyncFree wc_HmacAsyncFree #endif #define CyaSSL_GetHmacMaxSize wolfSSL_GetHmacMaxSize #ifdef HAVE_HKDF diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/integer.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/integer.h index 97b22822b..2aed0cd0f 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/integer.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/integer.h @@ -1,8 +1,8 @@ /* integer.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* * Based on public domain LibTomMath 0.38 by Tom St Denis, tomstdenis@iahu.ca, * http://math.libtomcrypt.com diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/logging.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/logging.h index faa85d449..12fa22c61 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/logging.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/logging.h @@ -1,8 +1,8 @@ /* logging.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* submitted by eof */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/md2.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/md2.h index cb7633752..e3e7816e6 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/md2.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/md2.h @@ -1,8 +1,8 @@ /* md2.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* check for old macro */ #if !defined(CYASSL_MD2) && defined(WOLFSSL_MD2) #define CYASSL_MD2 diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/md4.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/md4.h index 458465621..f550a71ad 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/md4.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/md4.h @@ -1,8 +1,8 @@ /* md4.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_MD4 #ifndef CTAO_CRYPT_MD4_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/md5.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/md5.h index 3f5d01756..4f5dc4727 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/md5.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/md5.h @@ -1,8 +1,8 @@ /* md5.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_MD5 #ifndef CTAO_CRYPT_MD5_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/memory.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/memory.h index 285005350..a7f2a8b3a 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/memory.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/memory.h @@ -1,8 +1,8 @@ /* memory.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* submitted by eof */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/misc.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/misc.h index a640044e5..02c544101 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/misc.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/misc.h @@ -1,8 +1,8 @@ /* misc.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_MISC_H #define CTAO_CRYPT_MISC_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/mpi_class.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/mpi_class.h index 0ce92a64c..01141a98b 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/mpi_class.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/mpi_class.h @@ -1,8 +1,8 @@ /* mpi_class.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,8 +16,9 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/mpi_superclass.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/mpi_superclass.h index 68cd0a6e3..ca7531c21 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/mpi_superclass.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/mpi_superclass.h @@ -1,8 +1,8 @@ /* mpi_superclass.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* super class file for PK algos */ #include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/pkcs7.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/pkcs7.h index dfb7c2fd3..4b0488f25 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/pkcs7.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/pkcs7.h @@ -1,8 +1,8 @@ /* pkcs7.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -10,16 +10,17 @@ * (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 + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_PKCS7 #ifndef CTAO_CRYPT_PKCS7_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/poly1305.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/poly1305.h index bceb772a5..72021ab27 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/poly1305.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/poly1305.h @@ -1,8 +1,8 @@ /* poly1305.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_POLY1305 #ifndef CTAO_CRYPT_POLY1305_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h index a5dca8904..e56e236c9 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/port/pic32/pic32mz-crypt.h @@ -1,8 +1,8 @@ /* pic32mz-crypt.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef PIC32MZ_CRYPT_H #define PIC32MZ_CRYPT_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/pwdbased.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/pwdbased.h index 7d6dced51..9f1d1de36 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/pwdbased.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/pwdbased.h @@ -1,8 +1,8 @@ /* pwdbased.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_PWDBASED #ifndef CTAO_CRYPT_PWDBASED_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/rabbit.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/rabbit.h index a6e92ec2e..109e97331 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/rabbit.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/rabbit.h @@ -1,8 +1,8 @@ /* rabbit.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_RABBIT #ifndef CTAO_CRYPT_RABBIT_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/random.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/random.h index 6d3a96fea..9581ff92c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/random.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/random.h @@ -1,8 +1,8 @@ /* random.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_RANDOM_H #define CTAO_CRYPT_RANDOM_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/ripemd.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/ripemd.h index 4458fcc44..25bcf990e 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/ripemd.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/ripemd.h @@ -1,8 +1,8 @@ /* ripemd.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,11 +16,12 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_RIPEMD_H #define CTAO_CRYPT_RIPEME_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/rsa.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/rsa.h index 72f8dc5d0..18949e393 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/rsa.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/rsa.h @@ -1,8 +1,8 @@ /* rsa.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_RSA #ifndef CTAO_CRYPT_RSA_H @@ -44,11 +45,12 @@ #ifdef WOLFSSL_KEY_GEN #define MakeRsaKey wc_MakeRsaKey #define RsaKeyToDer wc_RsaKeyToDer + #define CheckProbablePrime wc_CheckProbablePrime #endif -#ifdef HAVE_CAVIUM - #define RsaInitCavium wc_RsaInitCavium - #define RsaFreeCavium wc_RsaFreeCavium +#ifdef WOLFSSL_ASYNC_CRYPT + #define RsaAsyncInit wc_RsaAsyncInit + #define RsaAsyncFree wc_RsaAsyncFree #endif #endif /* CTAO_CRYPT_RSA_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/settings.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/settings.h index 2d1ab55d7..4cea7e201 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/settings.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/settings.h @@ -1,8 +1,8 @@ /* settings.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Place OS specific preprocessor flags, defines, includes here, will be included into every file because types.h includes it */ @@ -26,9 +27,6 @@ #ifndef CTAO_CRYPT_SETTINGS_H #define CTAO_CRYPT_SETTINGS_H -/* for reverse compatibility after name change */ -#include - #ifdef __cplusplus extern "C" { #endif @@ -56,7 +54,7 @@ /* Uncomment next line if using PIC32MZ Crypto Engine */ /* #define CYASSL_MICROCHIP_PIC32MZ */ - + /* Uncomment next line if using FreeRTOS */ /* #define FREERTOS */ @@ -81,15 +79,12 @@ /* Uncomment next line if using STM32F2 */ /* #define CYASSL_STM32F2 */ -/* Uncomment next line if using Comverge settings */ -/* #define COMVERGE */ - /* Uncomment next line if using QL SEP settings */ /* #define CYASSL_QL */ /* Uncomment next line if building for EROAD */ /* #define CYASSL_EROAD */ - + /* Uncomment next line if building for IAR EWARM */ /* #define CYASSL_IAR_ARM */ @@ -113,25 +108,10 @@ #include #endif +/* for reverse compatibility after name change */ +#include -#ifdef COMVERGE - #define THREADX - #define HAVE_NETX - #define CYASSL_USER_IO - #define NO_WRITEV - #define NO_DEV_RANDOM - #define NO_FILESYSTEM - #define NO_SHA512 - #define NO_DH - #define NO_DSA - #define NO_HC128 - #define NO_RSA - #define NO_SESSION_CACHE - #define HAVE_ECC -#endif - - -#ifdef THREADX +#ifdef THREADX #define SIZEOF_LONG_LONG 8 #endif @@ -145,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 @@ -157,7 +137,7 @@ #define CYASSL_USER_IO #define BENCH_EMBEDDED #endif - + #ifdef MICROCHIP_PIC32 /* #define CYASSL_MICROCHIP_PIC32MZ */ #define SIZEOF_LONG_LONG 8 @@ -170,16 +150,20 @@ #define TFM_TIMING_RESISTANT #endif -#ifdef CYASSL_MICROCHIP_PIC32MZ - #define CYASSL_PIC32MZ_CE - #define CYASSL_PIC32MZ_CRYPT - #define HAVE_AES_ENGINE - #define CYASSL_PIC32MZ_RNG - /* #define CYASSL_PIC32MZ_HASH */ +#if defined(CYASSL_MICROCHIP_PIC32MZ) || defined(WOLFSSL_MICROCHIP_PIC32MZ) + #ifndef NO_PIC32MZ_CRYPT + #define WOLFSSL_PIC32MZ_CRYPT + #endif + #ifndef NO_PIC32MZ_RNG + #define WOLFSSL_PIC32MZ_RNG + #endif + #ifndef NO_PIC32MZ_HASH + #define WOLFSSL_PIC32MZ_HASH + #endif + #define CYASSL_AES_COUNTER #define HAVE_AESGCM #define NO_BIG_INT - #endif #ifdef MICROCHIP_TCPIP_V5 @@ -200,7 +184,7 @@ #ifdef MBED #define CYASSL_USER_IO #define NO_FILESYSTEM - #define NO_CERT + #define NO_CERTS #define USE_CERT_BUFFERS_1024 #define NO_WRITEV #define NO_DEV_RANDOM @@ -266,7 +250,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 @@ -274,7 +258,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 @@ -406,7 +390,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 @@ -482,7 +466,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))) @@ -497,7 +481,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), \ @@ -597,13 +581,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 @@ -717,17 +701,11 @@ #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 -#ifdef HAVE_CRL - /* not widely supported yet */ - #undef NO_SKID - #define NO_SKID -#endif - #ifdef __INTEL_COMPILER #pragma warning(disable:2259) /* explicit casts to smaller sizes, disable */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/settings_comp.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/settings_comp.h index 89278a2db..c886d8e62 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/settings_comp.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/settings_comp.h @@ -1,8 +1,8 @@ /* settings_comp.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_SETTINGS_C_H #define CTAO_CRYPT_SETTINGS_C_H @@ -50,9 +51,22 @@ #if defined(NO_WOLFSSL_MEMORY) && !defined(NO_CYASSL_MEMORY) #define NO_CYASSL_MEMORY #endif -#ifdef WOLFSSL_KEY_GEN +#if defined(WOLFSSL_KEY_GEN) && !defined(CYASSL_KEY_GEN) #define CYASSL_KEY_GEN #endif +/* AES */ +#if defined(WOLFSSL_AES_DIRECT) && !defined(CYASSL_AES_DIRECT) + #define CYASSL_AES_DIRECT +#endif +#if defined(WOLFSSL_AES_COUNTER) && !defined(CYASSL_AES_COUNTER) + #define CYASSL_AES_COUNTER +#endif + +/* DES */ +#if defined(WOLFSSL_DES_ECB) && !defined(CYASSL_DES_ECB) + #define CYASSL_DES_ECB +#endif + #endif /* CTAO_CRYPT_SETTINGS_C_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/sha.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/sha.h index 56927e2de..92c8e33ad 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/sha.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/sha.h @@ -1,8 +1,8 @@ /* sha.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef NO_SHA #ifndef CTAO_CRYPT_SHA_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/sha256.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/sha256.h index b8b1f2465..000e834bb 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/sha256.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/sha256.h @@ -1,8 +1,8 @@ /* sha256.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,11 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* code submitted by raphael.huck@efixo.com */ + #ifndef NO_SHA256 @@ -34,6 +34,13 @@ #define Sha256Final wc_Sha256Final #define Sha256Hash wc_Sha256Hash +#ifdef WOLFSSL_SHA224 + #define InitSha224 wc_InitSha224 + #define Sha224Update wc_Sha224Update + #define Sha224Final wc_Sha224Final + #define Sha224Hash wc_Sha224Hash +#endif + #endif /* CTAO_CRYPT_SHA256_H */ #endif /* NO_SHA256 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/sha512.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/sha512.h index 3eab76005..39c634235 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/sha512.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/sha512.h @@ -1,8 +1,8 @@ /* sha512.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_SHA512_H #define CTAO_CRYPT_SHA512_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/tfm.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/tfm.h index 0b16b5189..5eba3d339 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/tfm.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/tfm.h @@ -1,8 +1,8 @@ /* tfm.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* * Based on public domain TomsFastMath 0.10 by Tom St Denis, tomstdenis@iahu.ca, * http://math.libtomcrypt.com diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/types.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/types.h index 95bfb45e0..b6d97b51f 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/types.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/types.h @@ -1,8 +1,8 @@ /* types.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_TYPES_H #define CTAO_CRYPT_TYPES_H @@ -33,7 +34,6 @@ #define CYASSL_MAX_16BIT WOLFSSL_MAX_16BIT #define CYASSL_MAX_ERROR_SZ WOLFSSL_MAX_ERROR_SZ #define cyassl_word wolfssl_word -#define CYASSL_MAX_ERROR_SZ WOLFSSL_MAX_ERROR_SZ #endif /* CTAO_CRYPT_TYPES_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/visibility.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/visibility.h index 6bb4953a3..f22c08481 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/visibility.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/visibility.h @@ -1,8 +1,8 @@ /* visibility.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Visibility control macros */ #ifndef CTAO_CRYPT_VISIBILITY_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/wc_port.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/wc_port.h index f35a451ca..50fb90ad9 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/wc_port.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ctaocrypt/wc_port.h @@ -1,8 +1,8 @@ /* port.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef CTAO_CRYPT_PORT_H #define CTAO_CRYPT_PORT_H diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/error-ssl.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/error-ssl.h index 8eab84354..e5189fac4 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/error-ssl.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/error-ssl.h @@ -1,8 +1,8 @@ /* error-ssl.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/include.am b/FreeRTOS-Plus/Source/WolfSSL/cyassl/include.am index db1f089ee..b4c7e0436 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/include.am @@ -16,10 +16,16 @@ nobase_include_HEADERS+= \ cyassl/certs_test.h \ cyassl/test.h \ cyassl/version.h \ - cyassl/options.h \ cyassl/ocsp.h \ cyassl/crl.h noinst_HEADERS+= \ cyassl/internal.h +# For distro build don't install options.h. +# It depends on the architecture and conflicts with Multi-Arch. +if BUILD_DISTRO +noinst_HEADERS+= cyassl/options.h +else +nobase_include_HEADERS+= cyassl/options.h +endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/internal.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/internal.h index c0ba722e8..80d451e98 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/internal.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/internal.h @@ -1,8 +1,8 @@ /* internal.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ocsp.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ocsp.h index 1ad9efe04..e06a1b53c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ocsp.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ocsp.h @@ -1,8 +1,8 @@ /* ocsp.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/des.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/des.h index 0c8d55c11..de4676402 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/des.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/des.h @@ -1,8 +1,8 @@ /* des.h * - * Copyright (C) 2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,11 +16,12 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* des.h defines mini des openssl compatibility layer + +/* des.h defines mini des openssl compatibility layer * */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/dsa.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/dsa.h index 2bb476bbd..39ddf8ce7 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/dsa.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/dsa.h @@ -1,3 +1,12 @@ /* dsa.h for openSSL */ +#ifndef CYASSL_OPENSSL_DSA +#define CYASSL_OPENSSL_DSA + +#define CyaSSL_DSA_LoadDer wolfSSL_DSA_LoadDer +#define CyaSSL_DSA_do_sign wolfSSL_DSA_do_sign + +#include #include +#endif + diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ec25519.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ec25519.h new file mode 100644 index 000000000..6ee894506 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ec25519.h @@ -0,0 +1,3 @@ +/* ec25519.h */ + +#include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ec448.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ec448.h new file mode 100644 index 000000000..c3fe4c3ab --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ec448.h @@ -0,0 +1,3 @@ +/* ec448.h */ + +#include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ecdh.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ecdh.h new file mode 100644 index 000000000..b774bf0da --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ecdh.h @@ -0,0 +1,3 @@ +/* ecdh.h for openssl */ + +#include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ed25519.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ed25519.h new file mode 100644 index 000000000..240cbcaaf --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ed25519.h @@ -0,0 +1,3 @@ +/* ed25519.h */ + +#include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ed448.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ed448.h new file mode 100644 index 000000000..ebb9c6194 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ed448.h @@ -0,0 +1,3 @@ +/* ed448.h */ + +#include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/evp.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/evp.h index fe9f42410..b7ad1f50c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/evp.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/evp.h @@ -1,8 +1,8 @@ /* evp.h * - * Copyright (C) 2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,12 +16,26 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* evp.h defines mini evp openssl compatibility layer + +/* evp.h defines mini evp openssl compatibility layer * */ +#ifndef CYASSL_OPENSSL_EVP +#define CYASSL_OPENSSL_EVP + +#define CyaSSL_StoreExternalIV wolfSSL_StoreExternalIV +#define CyaSSL_SetInternalIV wolfSSL_SetInternalIV +#define CYASSL_EVP_MD WOLFSSL_EVP_MD +#define CyaSSL_EVP_X_STATE wolfSSL_EVP_X_STATE +#define CyaSSL_EVP_X_STATE_LEN wolfSSL_EVP_X_STATE_LEN +#define CyaSSL_3des_iv wolfSSL_3des_iv +#define CyaSSL_aes_ctr_iv wolfSSL_aes_ctr_iv + #include +#endif + diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/hmac.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/hmac.h index f35fd7542..6dd377994 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/hmac.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/hmac.h @@ -1,8 +1,8 @@ /* hmac.h * - * Copyright (C) 2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,11 +16,12 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* hmac.h defines mini hamc openssl compatibility layer + +/* hmac.h defines mini hamc openssl compatibility layer * */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/include.am b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/include.am index e531f767a..a1b25c6b6 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/include.am @@ -11,7 +11,12 @@ nobase_include_HEADERS+= \ cyassl/openssl/dh.h \ cyassl/openssl/dsa.h \ cyassl/openssl/ecdsa.h \ + cyassl/openssl/ecdh.h \ cyassl/openssl/ec.h \ + cyassl/openssl/ec25519.h \ + cyassl/openssl/ed25519.h \ + cyassl/openssl/ec448.h \ + cyassl/openssl/ed448.h \ cyassl/openssl/engine.h \ cyassl/openssl/err.h \ cyassl/openssl/evp.h \ @@ -29,6 +34,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/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/rsa.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/rsa.h index 06f10a573..f4f24b825 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/rsa.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/rsa.h @@ -1,3 +1,12 @@ /* rsa.h for openSSL */ +#ifndef CYASSL_OPENSSL_RSA +#define CYASSL_OPENSSL_RSA + +#define CyaSSL_RSA_GenAdd wolfSSL_RSA_GenAdd +#define CyaSSL_RSA_LoadDer wolfSSL_RSA_LoadDer + +#include #include +#endif + diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ssl.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ssl.h index 094b9943b..3896292c1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ssl.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ssl.h @@ -1,8 +1,8 @@ /* ssl.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -15,13 +15,20 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * a with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* ssl.h defines openssl compatibility layer + +/* ssl.h defines openssl compatibility layer * */ +#ifndef CYASSL_OPENSSL_H_ +#define CYASSL_OPENSSL_H_ +#include #include + +#endif + diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ssl23.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ssl23.h new file mode 100644 index 000000000..a91524b9b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/openssl/ssl23.h @@ -0,0 +1,3 @@ +/* ssl23.h for openssl */ + +#include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/options.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/options.h index ff58ee4a7..ff991bdb5 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/options.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/options.h @@ -1,93 +1,40 @@ -/* cyassl options.h - * generated from wolfssl/options.h +/* options.h.in + * + * Copyright (C) 2006-2020 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 options.h -* generated from configure options -* -* Copyright (C) 2006-2015 wolfSSL Inc. -* -* This file is part of wolfSSL. (formerly known as CyaSSL) -* -*/ -#pragma once + +/* default blank options for autoconf */ + +#ifndef CYASSL_OPTIONS_H +#define CYASSL_OPTIONS_H + #ifdef __cplusplus extern "C" { #endif -#ifndef WOLFSSL_OPTIONS_IGNORE_SYS -#undef _POSIX_THREADS -#define _POSIX_THREADS -#endif - -#undef HAVE_THREAD_LS -#define HAVE_THREAD_LS - -#ifndef WOLFSSL_OPTIONS_IGNORE_SYS -#undef _THREAD_SAFE -#define _THREAD_SAFE -#endif - -#undef HAVE_AESGCM -#define HAVE_AESGCM - -#undef WOLFSSL_SHA512 -#define WOLFSSL_SHA512 - -#undef WOLFSSL_SHA384 -#define WOLFSSL_SHA384 - -#undef NO_DSA -#define NO_DSA - -#undef HAVE_ECC -#define HAVE_ECC - -#undef TFM_ECC256 -#define TFM_ECC256 - -#undef ECC_SHAMIR -#define ECC_SHAMIR - -#undef NO_PSK -#define NO_PSK - -#undef NO_RC4 -#define NO_RC4 - -#undef NO_MD4 -#define NO_MD4 - -#undef NO_HC128 -#define NO_HC128 - -#undef NO_RABBIT -#define NO_RABBIT - -#undef HAVE_POLY1305 -#define HAVE_POLY1305 - -#undef HAVE_ONE_TIME_AUTH -#define HAVE_ONE_TIME_AUTH - -#undef HAVE_CHACHA -#define HAVE_CHACHA - -#undef HAVE_HASHDRBG -#define HAVE_HASHDRBG - -#undef NO_PWDBASED -#define NO_PWDBASED - -#undef USE_FAST_MATH -#define USE_FAST_MATH - -#undef WOLFSSL_X86_64_BUILD -#define WOLFSSL_X86_64_BUILD - #ifdef __cplusplus } #endif + +#endif /* CYASSL_OPTIONS_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/options.h.in b/FreeRTOS-Plus/Source/WolfSSL/cyassl/options.h.in new file mode 100644 index 000000000..ff991bdb5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/options.h.in @@ -0,0 +1,40 @@ +/* options.h.in + * + * Copyright (C) 2006-2020 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 + */ + + +/* default blank options for autoconf */ + +#ifndef CYASSL_OPTIONS_H +#define CYASSL_OPTIONS_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif /* CYASSL_OPTIONS_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/sniffer.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/sniffer.h index 2ae674409..629785591 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/sniffer.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/sniffer.h @@ -1,8 +1,8 @@ /* sniffer.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/sniffer_error.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/sniffer_error.h index 8b3e00346..8d7e8e159 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/sniffer_error.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/sniffer_error.h @@ -1,8 +1,8 @@ /* sniffer_error.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ssl.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ssl.h index eadf29681..5d36b366e 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/ssl.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/ssl.h @@ -1,8 +1,8 @@ /* ssl.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -15,12 +15,13 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * a with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* - * ssl.h makes wolfssl backwards compatibile with cyassl + * ssl.h makes wolfssl backwards compatible with cyassl */ #ifndef WOLFSSL_CYASSL_H_ @@ -165,6 +166,8 @@ #define CyaSSL_X509_get_der wolfSSL_X509_get_der #define CyaSSL_X509_notBefore wolfSSL_X509_notBefore #define CyaSSL_X509_notAfter wolfSSL_X509_notAfter +#define CyaSSL_X509_get_notBefore wolfSSL_X509_get_notBefore +#define CyaSSL_X509_get_notAfter wolfSSL_X509_get_notAfter #define CyaSSL_X509_version wolfSSL_X509_version #define CyaSSL_cmp_peer_cert_to_file wolfSSL_cmp_peer_cert_to_file @@ -225,7 +228,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 @@ -444,7 +447,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 @@ -485,21 +487,20 @@ #define CyaDTLSv1_2_client_method wolfDTLSv1_2_client_method #define CyaDTLSv1_2_server_method wolfDTLSv1_2_server_method #define CyaSSL_set_group_messages wolfSSL_set_group_messages -#define CyaSSL_set_using_nonblock wolfSSL_set_using_nonblock #define CyaSSL_CTX_set_cipher_list wolfSSL_CTX_set_cipher_list #define CyaSSL_CTX_set_group_messages wolfSSL_CTX_set_group_messages #define CyaSSL_CTX_set_session_cache_mode wolfSSL_CTX_set_session_cache_mode /* Callbacks */ -/* - * Empty commment denotes not listed in CyaSSL Manual - * (soon to be wolfSSL Manual) +/* + * Empty comment denotes not listed in CyaSSL Manual + * (soon to be wolfSSL Manual) */ #define CyaSSL_accept_ex wolfSSL_accept_ex -#define CyaSSL_SetIORecv wolfSSL_SetIORecv -#define CyaSSL_SetIOSend wolfSSL_SetIOSend +#define CyaSSL_SetIORecv wolfSSL_CTX_SetIORecv +#define CyaSSL_SetIOSend wolfSSL_CTX_SetIOSend #define CyaSSL_connect_ex wolfSSL_connect_ex #define CyaSSL_CTX_SetCACb wolfSSL_CTX_SetCACb #define CyaSSL_SetIOReadCtx wolfSSL_SetIOReadCtx @@ -566,9 +567,9 @@ /* OCSP and CRL */ -/* - * Empty commment denotes not listed in CyaSSL Manual - * (soon to be wolfSSL Manual) +/* + * Empty comment denotes not listed in CyaSSL Manual + * (soon to be wolfSSL Manual) */ #define CYASSL_CRL_MONITOR WOLFSSL_CRL_MONITOR /**/ @@ -623,6 +624,7 @@ #define CyaSSL_dtls_get_peer wolfSSL_dtls_get_peer #define CyaSSL_dtls_got_timeout wolfSSL_dtls_got_timeout #define CyaSSL_dtls_get_current_timeout wolfSSL_dtls_get_current_timeout +#define CyaSSL_set_using_nonblock wolfSSL_dtls_set_using_nonblock /* Certificate Manager */ #define CyaSSL_CertManagerNew wolfSSL_CertManagerNew @@ -657,7 +659,6 @@ /* OpenSSL Compatibility Layer */ -#define CyaSSL_PemCertToDer wolfSSL_PemCertToDer #define CyaSSL_get_sessionID wolfSSL_get_sessionID #define CyaSSL_get_peer_count wolfSSL_get_peer_count #define CyaSSL_get_chain_cert wolfSSL_get_chain_cert diff --git a/FreeRTOS-Plus/Source/WolfSSL/cyassl/version.h b/FreeRTOS-Plus/Source/WolfSSL/cyassl/version.h index 79bcc1793..0f59b121b 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/cyassl/version.h +++ b/FreeRTOS-Plus/Source/WolfSSL/cyassl/version.h @@ -1,8 +1,8 @@ /* cyassl/version.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #include #define LIBCYASSL_VERSION_STRING LIBWOLFSSL_VERSION_STRING diff --git a/FreeRTOS-Plus/Source/WolfSSL/doc/README.txt b/FreeRTOS-Plus/Source/WolfSSL/doc/README.txt index e96989407..efaed1b45 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/doc/README.txt +++ b/FreeRTOS-Plus/Source/WolfSSL/doc/README.txt @@ -1,3 +1,8 @@ The wolfSSL manual is available at: http://www.wolfssl.com/documentation/wolfSSL-Manual.pdf +The wolfSSL API guide is available at: +https://www.wolfssl.com/doxygen/wolfssl_API.html + +The wolfCrypt API guide is available at: +https://www.wolfssl.com/doxygen/wolfcrypt_API.html diff --git a/FreeRTOS-Plus/Source/WolfSSL/doc/include.am b/FreeRTOS-Plus/Source/WolfSSL/doc/include.am index 5bef623aa..3be217ce0 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/doc/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/doc/include.am @@ -3,3 +3,19 @@ # All paths should be given relative to the root dist_doc_DATA+= doc/README.txt + +dox-pdf: + echo "Generating PDF" + cd doc && ./generate_documentation.sh -install -pdf || (echo "HTML generation failed $$?"; exit 1) + +dox-html: + echo "Generating HTML" + cd doc && ./generate_documentation.sh -install -html || (echo "HTML generation failed $$?"; exit 1) + +dox: dox-html dox-pdf + +clean-local: + -rm -rf doc/build/ + -rm -rf doc/html/ + -rm -f doc/refman.pdf + -rm -f doc/doxygen_warnings diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/benchmark/include.am b/FreeRTOS-Plus/Source/WolfSSL/examples/benchmark/include.am new file mode 100644 index 000000000..9440df4aa --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/benchmark/include.am @@ -0,0 +1,15 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + + +if BUILD_THREADED_EXAMPLES +noinst_PROGRAMS += examples/benchmark/tls_bench +noinst_HEADERS += examples/benchmark/tls_bench.h +examples_benchmark_tls_bench_SOURCES = examples/benchmark/tls_bench.c +examples_benchmark_tls_bench_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +examples_benchmark_tls_bench_DEPENDENCIES = src/libwolfssl.la +endif + +dist_example_DATA+= examples/benchmark/tls_bench.c +DISTCLEANFILES+= examples/benchmark/.libs/tls_bench diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/benchmark/tls_bench.c b/FreeRTOS-Plus/Source/WolfSSL/examples/benchmark/tls_bench.c new file mode 100644 index 000000000..e22ea9c43 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/benchmark/tls_bench.c @@ -0,0 +1,1948 @@ +/* tls_bench.c + * + * Copyright (C) 2006-2020 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 + */ + + +/* +Example gcc build statement +gcc -lwolfssl -lpthread -o tls_bench tls_bench.c +./tls_bench + +Or + +#include +bench_tls(args); +*/ + + +#ifdef HAVE_CONFIG_H + #include +#endif +#ifndef WOLFSSL_USER_SETTINGS + #include +#endif +#include +#include +#include /* WC_MAX_DIGEST_SIZE */ +#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 + +/* For testing no pthread support */ +#if 0 + #undef HAVE_PTHREAD +#endif + +/* PTHREAD requires server and client enabled */ +#if defined(HAVE_PTHREAD) && (defined(NO_WOLFSSL_CLIENT) || defined(NO_WOLFSSL_SERVER)) + #undef HAVE_PTHREAD +#endif + +#ifdef HAVE_PTHREAD + #include +#endif + +#if 0 +#define BENCH_USE_NONBLOCK +#endif + +/* Defaults for configuration parameters */ +#define BENCH_DEFAULT_HOST "localhost" +#define BENCH_DEFAULT_PORT 11112 +#define NUM_THREAD_PAIRS 1 /* Thread pairs of server/client */ +#ifndef BENCH_RUNTIME_SEC + #ifdef BENCH_EMBEDDED + #define BENCH_RUNTIME_SEC 15 + #else + #define BENCH_RUNTIME_SEC 1 + #endif +#endif +/* TLS packet size */ +#ifndef TEST_PACKET_SIZE + #ifdef BENCH_EMBEDDED + #define TEST_PACKET_SIZE (2 * 1024) + #else + #define TEST_PACKET_SIZE (16 * 1024) + #endif +#endif +/* Total bytes to benchmark per connection */ +#ifndef TEST_MAX_SIZE + #ifdef BENCH_EMBEDDED + #define TEST_MAX_SIZE (16 * 1024) + #else + #define TEST_MAX_SIZE (128 * 1024) + #endif +#endif + +#ifdef WOLFSSL_DTLS + #ifdef BENCH_EMBEDDED + /* WOLFSSL_MAX_MTU in internal.h */ + #define TEST_DTLS_PACKET_SIZE (1500) + #else + /* MAX_UDP_SIZE in interna.h */ + #define TEST_DTLS_PACKET_SIZE (8092) + #endif +#endif + +/* In memory transfer buffer maximum size */ +/* Must be large enough to handle max TLS packet size plus max TLS header MAX_MSG_EXTRA */ +#define MEM_BUFFER_SZ (TEST_PACKET_SIZE + 38 + WC_MAX_DIGEST_SIZE) +#define SHOW_VERBOSE 0 /* Default output is tab delimited format */ + +#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ + !defined(WOLFCRYPT_ONLY) + +/* shutdown message - nice signal to server, we are done */ +static const char* kShutdown = "shutdown"; + +#ifndef NO_WOLFSSL_CLIENT +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"; +#endif + +#if !defined(NO_DH) + +#define MIN_DHKEY_BITS 1024 + +#if !defined(NO_WOLFSSL_SERVER) +/* dh2048 p */ +static const unsigned char dhp[] = +{ + 0xb0, 0xa1, 0x08, 0x06, 0x9c, 0x08, 0x13, 0xba, 0x59, 0x06, 0x3c, 0xbc, 0x30, + 0xd5, 0xf5, 0x00, 0xc1, 0x4f, 0x44, 0xa7, 0xd6, 0xef, 0x4a, 0xc6, 0x25, 0x27, + 0x1c, 0xe8, 0xd2, 0x96, 0x53, 0x0a, 0x5c, 0x91, 0xdd, 0xa2, 0xc2, 0x94, 0x84, + 0xbf, 0x7d, 0xb2, 0x44, 0x9f, 0x9b, 0xd2, 0xc1, 0x8a, 0xc5, 0xbe, 0x72, 0x5c, + 0xa7, 0xe7, 0x91, 0xe6, 0xd4, 0x9f, 0x73, 0x07, 0x85, 0x5b, 0x66, 0x48, 0xc7, + 0x70, 0xfa, 0xb4, 0xee, 0x02, 0xc9, 0x3d, 0x9a, 0x4a, 0xda, 0x3d, 0xc1, 0x46, + 0x3e, 0x19, 0x69, 0xd1, 0x17, 0x46, 0x07, 0xa3, 0x4d, 0x9f, 0x2b, 0x96, 0x17, + 0x39, 0x6d, 0x30, 0x8d, 0x2a, 0xf3, 0x94, 0xd3, 0x75, 0xcf, 0xa0, 0x75, 0xe6, + 0xf2, 0x92, 0x1f, 0x1a, 0x70, 0x05, 0xaa, 0x04, 0x83, 0x57, 0x30, 0xfb, 0xda, + 0x76, 0x93, 0x38, 0x50, 0xe8, 0x27, 0xfd, 0x63, 0xee, 0x3c, 0xe5, 0xb7, 0xc8, + 0x09, 0xae, 0x6f, 0x50, 0x35, 0x8e, 0x84, 0xce, 0x4a, 0x00, 0xe9, 0x12, 0x7e, + 0x5a, 0x31, 0xd7, 0x33, 0xfc, 0x21, 0x13, 0x76, 0xcc, 0x16, 0x30, 0xdb, 0x0c, + 0xfc, 0xc5, 0x62, 0xa7, 0x35, 0xb8, 0xef, 0xb7, 0xb0, 0xac, 0xc0, 0x36, 0xf6, + 0xd9, 0xc9, 0x46, 0x48, 0xf9, 0x40, 0x90, 0x00, 0x2b, 0x1b, 0xaa, 0x6c, 0xe3, + 0x1a, 0xc3, 0x0b, 0x03, 0x9e, 0x1b, 0xc2, 0x46, 0xe4, 0x48, 0x4e, 0x22, 0x73, + 0x6f, 0xc3, 0x5f, 0xd4, 0x9a, 0xd6, 0x30, 0x07, 0x48, 0xd6, 0x8c, 0x90, 0xab, + 0xd4, 0xf6, 0xf1, 0xe3, 0x48, 0xd3, 0x58, 0x4b, 0xa6, 0xb9, 0xcd, 0x29, 0xbf, + 0x68, 0x1f, 0x08, 0x4b, 0x63, 0x86, 0x2f, 0x5c, 0x6b, 0xd6, 0xb6, 0x06, 0x65, + 0xf7, 0xa6, 0xdc, 0x00, 0x67, 0x6b, 0xbb, 0xc3, 0xa9, 0x41, 0x83, 0xfb, 0xc7, + 0xfa, 0xc8, 0xe2, 0x1e, 0x7e, 0xaf, 0x00, 0x3f, 0x93 +}; + +/* dh2048 g */ +static const unsigned char dhg[] = +{ + 0x02, +}; +#endif /* !NO_WOLFSSL_SERVER */ +#endif /* !NO_DH */ + +#ifdef HAVE_PTHREAD +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; +#endif + +typedef struct { + double connTime; + double rxTime; + double txTime; + int connCount; + int rxTotal; + int txTotal; +} stats_t; + +typedef struct { + int shutdown; + int sockFd; + int ret; +} side_t; + +typedef struct { + const char* cipher; + const char* host; + word32 port; + int packetSize; /* The data payload size in the packet */ + int maxSize; + int runTimeSec; + int showPeerInfo; + int showVerbose; +#ifndef NO_WOLFSSL_SERVER + int listenFd; +#endif +#ifdef WOLFSSL_DTLS + int doDTLS; + struct sockaddr_in serverAddr; + struct sockaddr_in clientAddr; +#ifdef HAVE_PTHREAD + int serverReady; + int clientOrserverOnly; + pthread_mutex_t dtls_mutex; + pthread_cond_t dtls_cond; +#endif +#endif + side_t client; + side_t server; + +#ifdef HAVE_PTHREAD + int useLocalMem; + + /* client messages to server in memory */ + memBuf_t to_server; + + /* server messages to client in memory */ + memBuf_t to_client; +#endif + + /* server */ + stats_t server_stats; + + /* client */ + stats_t client_stats; +} info_t; + +/* Global vars for argument parsing */ +int myoptind = 0; +char* myoptarg = NULL; + +#ifdef WOLFSSL_DTLS +int DoneHandShake = 0; +#endif + +static double gettime_secs(int reset) +{ + struct timeval tv; + gettimeofday(&tv, 0); + (void)reset; + + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; +} + + +#ifdef HAVE_PTHREAD +/* server send callback */ +static int ServerMemSend(info_t* info, char* buf, int sz) +{ + pthread_mutex_lock(&info->to_client.mutex); + +#ifndef BENCH_USE_NONBLOCK + /* check for overflow */ + if (info->to_client.write_idx + sz > MEM_BUFFER_SZ) { + pthread_mutex_unlock(&info->to_client.mutex); + printf("ServerMemSend overflow\n"); + return -1; + } +#else + if (info->to_client.write_idx + sz > MEM_BUFFER_SZ) + sz = MEM_BUFFER_SZ - info->to_client.write_idx; +#endif + + XMEMCPY(&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); + +#ifdef BENCH_USE_NONBLOCK + if (sz == 0) + return WOLFSSL_CBIO_ERR_WANT_WRITE; +#endif + return sz; +} + +/* server recv callback */ +static int ServerMemRecv(info_t* info, char* buf, int sz) +{ + pthread_mutex_lock(&info->to_server.mutex); + +#ifndef BENCH_USE_NONBLOCK + 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); +#else + if (info->to_server.write_idx - info->to_server.read_idx < sz) + sz = info->to_server.write_idx - info->to_server.read_idx; +#endif + + XMEMCPY(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; + +#ifdef BENCH_USE_NONBLOCK + if (sz == 0) + return WOLFSSL_CBIO_ERR_WANT_READ; +#endif + return sz; +} + +/* client send callback */ +static int ClientMemSend(info_t* info, char* buf, int sz) +{ + pthread_mutex_lock(&info->to_server.mutex); + +#ifndef BENCH_USE_NONBLOCK + /* check for overflow */ + if (info->to_client.write_idx + sz > MEM_BUFFER_SZ) { + printf("ClientMemSend overflow %d %d %d\n", info->to_client.write_idx, sz, MEM_BUFFER_SZ); + pthread_mutex_unlock(&info->to_server.mutex); + return -1; + } +#else + if (info->to_server.write_idx + sz > MEM_BUFFER_SZ) + sz = MEM_BUFFER_SZ - info->to_server.write_idx; +#endif + + XMEMCPY(&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); + +#ifdef BENCH_USE_NONBLOCK + if (sz == 0) + return WOLFSSL_CBIO_ERR_WANT_WRITE; +#endif + return sz; +} + +/* client recv callback */ +static int ClientMemRecv(info_t* info, char* buf, int sz) +{ + pthread_mutex_lock(&info->to_client.mutex); + +#ifndef BENCH_USE_NONBLOCK + while (info->to_client.write_idx - info->to_client.read_idx < sz) + pthread_cond_wait(&info->to_client.cond, &info->to_client.mutex); +#else + if (info->to_client.write_idx - info->to_client.read_idx < sz) + sz = info->to_client.write_idx - info->to_client.read_idx; +#endif + + XMEMCPY(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); + +#ifdef BENCH_USE_NONBLOCK + if (sz == 0) + return WOLFSSL_CBIO_ERR_WANT_READ; +#endif + return sz; +} +#endif /* HAVE_PTHREAD */ + +static int SocketRecv(int sockFd, char* buf, int sz) +{ + int recvd = (int)recv(sockFd, buf, sz, 0); + if (recvd == -1) { + switch (errno) { + #if EAGAIN != SOCKET_EWOULDBLOCK + case EAGAIN: /* EAGAIN == EWOULDBLOCK on some systems, but not others */ + #endif + case SOCKET_EWOULDBLOCK: + return WOLFSSL_CBIO_ERR_WANT_READ; + case SOCKET_ECONNRESET: + return WOLFSSL_CBIO_ERR_CONN_RST; + case SOCKET_EINTR: + return WOLFSSL_CBIO_ERR_ISR; + case SOCKET_ECONNREFUSED: /* DTLS case */ + return WOLFSSL_CBIO_ERR_WANT_READ; + case SOCKET_ECONNABORTED: + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + default: + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + else if (recvd == 0) { + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + return recvd; +} + +static int SocketSend(int sockFd, char* buf, int sz) +{ + int sent = (int)send(sockFd, buf, sz, 0); + if (sent == -1) { + switch (errno) { + #if EAGAIN != SOCKET_EWOULDBLOCK + case EAGAIN: /* EAGAIN == EWOULDBLOCK on some systems, but not others */ + #endif + case SOCKET_EWOULDBLOCK: + return WOLFSSL_CBIO_ERR_WANT_READ; + case SOCKET_ECONNRESET: + return WOLFSSL_CBIO_ERR_CONN_RST; + case SOCKET_EINTR: + return WOLFSSL_CBIO_ERR_ISR; + case SOCKET_EPIPE: + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + default: + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + else if (sent == 0) { + return 0; + } + return sent; +} +#ifdef WOLFSSL_DTLS +static int ReceiveFrom(WOLFSSL *ssl, int sd, char *buf, int sz) +{ + int recvd; + int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); + struct sockaddr peer; + socklen_t peerSz; + + if (DoneHandShake) dtls_timeout = 0; + + if (!wolfSSL_get_using_nonblock(ssl)) { + struct timeval timeout; + XMEMSET(&timeout, 0, sizeof(timeout)); + timeout.tv_sec = dtls_timeout; + + if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, + sizeof(timeout)) != 0) { + printf("setsockopt rcvtimeo failed\n"); + } + } + + recvd = (int)recvfrom(sd, buf, sz, 0, (SOCKADDR*)&peer, &peerSz); + + if (recvd < 0) { + + if (errno == SOCKET_EWOULDBLOCK || errno == SOCKET_EAGAIN) { + if (wolfSSL_dtls_get_using_nonblock(ssl)) { + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + } + else if (errno == SOCKET_ECONNRESET) { + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (errno == SOCKET_EINTR) { + return WOLFSSL_CBIO_ERR_ISR; + } + else if (errno == SOCKET_ECONNREFUSED) { + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + else { + if (recvd == 0) { + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + } + + return recvd; +} + +static int SendTo(int sd, char *buf, int sz, const struct sockaddr *peer, + socklen_t peerSz) +{ + int sent; + + sent = (int)sendto(sd, buf, sz, 0, peer, peerSz); + + if (sent < 0) { + if (errno == SOCKET_EWOULDBLOCK || errno == SOCKET_EAGAIN) { + return WOLFSSL_CBIO_ERR_WANT_WRITE; + } + else if (errno == SOCKET_ECONNRESET) { + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (errno == SOCKET_EINTR) { + return WOLFSSL_CBIO_ERR_ISR; + } + else if (errno == SOCKET_EPIPE) { + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + else { + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return sent; +} + +static int myDoneHsCb(WOLFSSL* ssl, void* user_ctx) +{ + (void) ssl; + (void) user_ctx; + + DoneHandShake = 1; + return 1; +} +#endif + +#ifndef NO_WOLFSSL_SERVER +static int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + info_t* info = (info_t*)ctx; + (void)ssl; +#ifdef HAVE_PTHREAD + if (info->useLocalMem) + return ServerMemSend(info, buf, sz); +#endif +#ifdef WOLFSSL_DTLS + if (info->doDTLS) { + return SendTo(info->server.sockFd, buf, sz, + (const struct sockaddr*)&info->clientAddr, sizeof(info->clientAddr)); + } else +#endif + return SocketSend(info->server.sockFd, buf, sz); +} +static int ServerRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + info_t* info = (info_t*)ctx; + (void)ssl; +#ifdef HAVE_PTHREAD + if (info->useLocalMem) + return ServerMemRecv(info, buf, sz); +#endif +#ifdef WOLFSSL_DTLS + if (info->doDTLS) { + return ReceiveFrom(ssl, info->server.sockFd, buf, sz); + } else +#endif + return SocketRecv(info->server.sockFd, buf, sz); +} +#endif /* !NO_WOLFSSL_SERVER */ + +#ifndef NO_WOLFSSL_CLIENT +static int ClientSend(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + info_t* info = (info_t*)ctx; + (void)ssl; +#ifdef HAVE_PTHREAD + if (info->useLocalMem) + return ClientMemSend(info, buf, sz); +#endif +#ifdef WOLFSSL_DTLS + if (info->doDTLS) { + return SendTo(info->client.sockFd, buf, sz, + (const struct sockaddr*)&info->serverAddr, sizeof(info->serverAddr)); + } else +#endif + return SocketSend(info->client.sockFd, buf, sz); +} +static int ClientRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + info_t* info = (info_t*)ctx; + (void)ssl; +#ifdef HAVE_PTHREAD + if (info->useLocalMem) + return ClientMemRecv(info, buf, sz); +#endif +#ifdef WOLFSSL_DTLS + if (info->doDTLS) { + return ReceiveFrom(ssl, info->client.sockFd, buf, sz); + } else +#endif + return SocketRecv(info->client.sockFd, buf, sz); +} +#endif /* !NO_WOLFSSL_CLIENT */ + +static void CloseAndCleanupSocket(int* sockFd) +{ + if (*sockFd != -1) { + close(*sockFd); + *sockFd = -1; + } +#ifdef WOLFSSL_DTLS + DoneHandShake = 0; +#endif +} + +#ifdef BENCH_USE_NONBLOCK +static int SetSocketNonBlocking(int sockFd) +{ + int flags = fcntl(sockFd, F_GETFL, 0); + if (flags < 0) { + printf("fcntl get failed\n"); + return -1; + } + flags = fcntl(sockFd, F_SETFL, flags | O_NONBLOCK); + if (flags < 0) { + printf("fcntl set failed\n"); + return -1; + } + return 0; +} +#endif + +#ifndef NO_WOLFSSL_CLIENT +static int SetupSocketAndConnect(info_t* info, const char* host, + word32 port) +{ + struct sockaddr_in servAddr; + struct hostent* entry; + + /* Setup server address */ + XMEMSET(&servAddr, 0, sizeof(servAddr)); + servAddr.sin_family = AF_INET; + servAddr.sin_port = htons(port); + + /* Resolve host */ + entry = gethostbyname(host); + if (entry) { + XMEMCPY(&servAddr.sin_addr.s_addr, entry->h_addr_list[0], + entry->h_length); + } + else { + servAddr.sin_addr.s_addr = inet_addr(host); + } + +#ifdef WOLFSSL_DTLS + if (info->doDTLS) { + /* Create the SOCK_DGRAM socket type is implemented on the User + * Datagram Protocol/Internet Protocol(UDP/IP protocol).*/ + if ((info->client.sockFd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + printf("ERROR: failed to create the SOCK_DGRAM socket\n"); + return -1; + } + XMEMCPY(&info->serverAddr, &servAddr, sizeof(servAddr)); + } else { +#endif + /* Create a socket that uses an Internet IPv4 address, + * Sets the socket to be stream based (TCP), + * 0 means choose the default protocol. */ + if ((info->client.sockFd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + printf("ERROR: failed to create the socket\n"); + return -1; + } + + /* Connect to the server */ + if (connect(info->client.sockFd, (struct sockaddr*)&servAddr, + sizeof(servAddr)) == -1) { + printf("ERROR: failed to connect\n"); + return -1; + } +#ifdef WOLFSSL_DTLS + } +#endif + +#ifdef BENCH_USE_NONBLOCK + if (SetSocketNonBlocking(info->client.sockFd) != 0) { + return -1; + } +#endif + + if (info->showVerbose) { + printf("Connected to %s on port %d\n", host, port); + } + + return 0; +} + +static int bench_tls_client(info_t* info) +{ + byte *writeBuf = NULL, *readBuf = NULL; + double start, total = 0; + int ret, readBufSz; + WOLFSSL_CTX* cli_ctx = NULL; + WOLFSSL* cli_ssl = NULL; + int haveShownPeerInfo = 0; + int tls13 = XSTRNCMP(info->cipher, "TLS13", 5) == 0; + int total_sz; + + total = gettime_secs(0); + + /* set up client */ +#ifdef WOLFSSL_DTLS + if(info->doDTLS) { + if (tls13) return WOLFSSL_SUCCESS; + cli_ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method()); + } else +#endif +#ifdef WOLFSSL_TLS13 + if (tls13) + cli_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); +#endif + if (!tls13) +#ifdef WOLFSSL_DTLS + if(!info->doDTLS) +#endif +#if !defined(WOLFSSL_TLS13) + cli_ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); +#elif !defined(WOLFSSL_NO_TLS12) + cli_ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); +#endif + + if (cli_ctx == NULL) { + printf("error creating ctx\n"); + ret = MEMORY_E; goto exit; + } + +#ifndef NO_CERTS +#ifdef HAVE_ECC + if (XSTRSTR(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 +#endif + { + ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, ca_cert_der_2048, + sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1); + } + if (ret != WOLFSSL_SUCCESS) { + printf("error loading CA\n"); + goto exit; + } +#endif + + wolfSSL_CTX_SetIOSend(cli_ctx, ClientSend); + wolfSSL_CTX_SetIORecv(cli_ctx, ClientRecv); + + /* set cipher suite */ + ret = wolfSSL_CTX_set_cipher_list(cli_ctx, info->cipher); + if (ret != WOLFSSL_SUCCESS) { + printf("error setting cipher suite\n"); + goto exit; + } + +#ifndef NO_DH + ret = wolfSSL_CTX_SetMinDhKey_Sz(cli_ctx, MIN_DHKEY_BITS); + if (ret != WOLFSSL_SUCCESS) { + printf("Error setting minimum DH key size\n"); + goto exit; + } +#endif + + /* Allocate and initialize a packet sized buffer */ + writeBuf = (unsigned char*)XMALLOC(info->packetSize, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (writeBuf == NULL) { + printf("failed to allocate write memory\n"); + ret = MEMORY_E; goto exit; + } + + /* Allocate read buffer */ + readBufSz = info->packetSize; + readBuf = (unsigned char*)XMALLOC(readBufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (readBuf == NULL) { + printf("failed to allocate read memory\n"); + ret = MEMORY_E; goto exit; + } + + /* BENCHMARK CONNECTIONS LOOP */ + while (!info->client.shutdown) { + int writeSz = info->packetSize; + #ifdef BENCH_USE_NONBLOCK + int err; + #endif + + #ifdef HAVE_PTHREAD + if (!info->useLocalMem) + #endif + { + /* Setup socket and connection */ + ret = SetupSocketAndConnect(info, info->host, info->port); + if (ret != 0) goto exit; + } + + cli_ssl = wolfSSL_new(cli_ctx); + if (cli_ssl == NULL) { + printf("error creating client object\n"); + goto exit; + } + +#ifdef WOLFSSL_DTLS + if (info->doDTLS) { + ret = wolfSSL_dtls_set_peer(cli_ssl, &info->serverAddr, + sizeof(info->serverAddr)); + if (ret != WOLFSSL_SUCCESS) { + printf("error setting dtls peer\n"); + goto exit; + } + ret = wolfSSL_SetHsDoneCb(cli_ssl, myDoneHsCb, NULL); + if (ret != WOLFSSL_SUCCESS) { + printf("error handshake done callback\n"); + goto exit; + } + } +#endif + wolfSSL_SetIOReadCtx(cli_ssl, info); + wolfSSL_SetIOWriteCtx(cli_ssl, info); + +#if defined(HAVE_PTHREAD) && defined(WOLFSSL_DTLS) + /* synchronize with server */ + if (info->doDTLS && !info->clientOrserverOnly) { + pthread_mutex_lock(&info->dtls_mutex); + if (info->serverReady != 1) { + pthread_cond_wait(&info->dtls_cond, &info->dtls_mutex); + } + /* for next loop */ + info->serverReady = 0; + pthread_mutex_unlock(&info->dtls_mutex); + } +#endif + /* perform connect */ + start = gettime_secs(1); + #ifndef BENCH_USE_NONBLOCK + ret = wolfSSL_connect(cli_ssl); + #else + do + { + ret = wolfSSL_connect(cli_ssl); + err = wolfSSL_get_error(cli_ssl, ret); + } + while (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE); + #endif + start = gettime_secs(0) - start; + if (ret != WOLFSSL_SUCCESS) { + printf("error connecting client\n"); + ret = wolfSSL_get_error(cli_ssl, ret); + goto exit; + } + info->client_stats.connTime += start; + info->client_stats.connCount++; + + if ((info->showPeerInfo) && (!haveShownPeerInfo)) { + haveShownPeerInfo = 1; + showPeer(cli_ssl); + } + + /* check for run time completion and issue shutdown */ + if (gettime_secs(0) - total >= info->runTimeSec) { + info->client.shutdown = 1; + + writeSz = (int)XSTRLEN(kShutdown) + 1; + XMEMCPY(writeBuf, kShutdown, writeSz); /* include null term */ + if (info->showVerbose) { + printf("Sending shutdown\n"); + } + + ret = wolfSSL_write(cli_ssl, writeBuf, writeSz); + if (ret < 0) { + printf("error on client write\n"); + ret = wolfSSL_get_error(cli_ssl, ret); + goto exit; + } + } + else { + XMEMSET(writeBuf, 0, info->packetSize); + XSTRNCPY((char*)writeBuf, kTestStr, info->packetSize); + } + + /* write / read echo loop */ + ret = 0; + total_sz = 0; + while (ret == 0 && total_sz < info->maxSize && !info->client.shutdown) { + /* write test message to server */ + start = gettime_secs(1); + #ifndef BENCH_USE_NONBLOCK + ret = wolfSSL_write(cli_ssl, writeBuf, writeSz); + #else + do { + ret = wolfSSL_write(cli_ssl, writeBuf, writeSz); + err = wolfSSL_get_error(cli_ssl, ret); + } + while (err == WOLFSSL_ERROR_WANT_WRITE); + #endif + info->client_stats.txTime += gettime_secs(0) - start; + if (ret < 0) { + printf("error on client write\n"); + ret = wolfSSL_get_error(cli_ssl, ret); + goto exit; + } + info->client_stats.txTotal += ret; + total_sz += ret; + + /* read echo of message from server */ + XMEMSET(readBuf, 0, readBufSz); + start = gettime_secs(1); + #ifndef BENCH_USE_NONBLOCK + ret = wolfSSL_read(cli_ssl, readBuf, readBufSz); + #else + do { + ret = wolfSSL_read(cli_ssl, readBuf, readBufSz); + err = wolfSSL_get_error(cli_ssl, ret); + } + while (err == WOLFSSL_ERROR_WANT_READ); + #endif + info->client_stats.rxTime += gettime_secs(0) - start; + if (ret < 0) { + printf("error on client read\n"); + ret = wolfSSL_get_error(cli_ssl, ret); + goto exit; + } + info->client_stats.rxTotal += ret; + ret = 0; /* reset return code */ + + /* validate echo */ + if (XMEMCMP((char*)writeBuf, (char*)readBuf, writeSz) != 0) { + printf("echo check failed!\n"); + ret = wolfSSL_get_error(cli_ssl, ret); + goto exit; + } + } + + CloseAndCleanupSocket(&info->client.sockFd); + + wolfSSL_free(cli_ssl); + cli_ssl = NULL; + } + +exit: + + if (ret != 0 && ret != WOLFSSL_SUCCESS) { + printf("Client Error: %d (%s)\n", ret, + wolfSSL_ERR_reason_error_string(ret)); + } + + /* clean up */ + CloseAndCleanupSocket(&info->client.sockFd); + if (cli_ssl != NULL) + wolfSSL_free(cli_ssl); + if (cli_ctx != NULL) + wolfSSL_CTX_free(cli_ctx); + XFREE(readBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(writeBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + info->client.ret = ret; + + return ret; +} + +#ifdef HAVE_PTHREAD +static void* client_thread(void* args) +{ + int ret; + info_t* info = (info_t*)args; + + ret = bench_tls_client(info); + + pthread_cond_signal(&info->to_server.cond); + info->to_client.done = 1; + info->client.ret = ret; + + return NULL; +} +#endif /* HAVE_PTHREAD */ +#endif /* !NO_WOLFSSL_CLIENT */ + + +#ifndef NO_WOLFSSL_SERVER +static int SetupSocketAndListen(int* listenFd, word32 port, int doDTLS) +{ + struct sockaddr_in servAddr; +#if defined(_MSC_VER) || defined(__MINGW32__) + char optval = 1; +#else + int optval = 1; +#endif +#ifndef WOLFSSL_DTLS + (void) doDTLS; +#endif + /* Setup server address */ + XMEMSET(&servAddr, 0, sizeof(servAddr)); + servAddr.sin_family = AF_INET; + servAddr.sin_port = htons(port); + servAddr.sin_addr.s_addr = INADDR_ANY; + +#ifdef WOLFSSL_DTLS + if (doDTLS) { + /* Create a socket that is implemented on the User Datagram Protocol/ + * Interet Protocol(UDP/IP protocol). */ + if((*listenFd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + printf("ERROR: failed to create the socket\n"); + return -1; + } + } else +#endif + /* Create a socket that uses an Internet IPv4 address, + * Sets the socket to be stream based (TCP), + * 0 means choose the default protocol. */ + if ((*listenFd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + printf("ERROR: failed to create the socket\n"); + return -1; + } + + /* allow reuse */ + if (setsockopt(*listenFd, SOL_SOCKET, SO_REUSEADDR, + &optval, sizeof(optval)) == -1) { + printf("setsockopt SO_REUSEADDR failed\n"); + return -1; + } + + /* Connect to the server */ + if (bind(*listenFd, (struct sockaddr*)&servAddr, + sizeof(servAddr)) == -1) { + printf("ERROR: failed to bind\n"); + return -1; + } +#ifdef WOLFSSL_DTLS + if (!doDTLS) +#endif + if (listen(*listenFd, 5) != 0) { + printf("ERROR: failed to listen\n"); + return -1; + } + +#ifdef BENCH_USE_NONBLOCK + if (SetSocketNonBlocking(*listenFd) != 0) { + return -1; + } +#endif + + return 0; +} + +static int SocketWaitClient(info_t* info) +{ + int connd; + struct sockaddr_in clientAddr; + socklen_t size = sizeof(clientAddr); +#ifdef WOLFSSL_DTLS + char msg[64]; + + if (info->doDTLS) { +#ifdef HAVE_PTHREAD + if (!info->clientOrserverOnly) { + pthread_mutex_lock(&info->dtls_mutex); + info->serverReady = 1; + pthread_cond_signal(&info->dtls_cond); + pthread_mutex_unlock(&info->dtls_mutex); + } +#endif + connd = (int)recvfrom(info->listenFd, (char *)msg, sizeof(msg), + MSG_PEEK, (struct sockaddr*)&clientAddr, &size); + if (connd < -1) { + printf("ERROR: failed to accept the connection\n"); + return -1; + } + XMEMCPY(&info->clientAddr, &clientAddr, sizeof(clientAddr)); + info->server.sockFd = info->listenFd; + } else { +#endif + if ((connd = accept(info->listenFd, (struct sockaddr*)&clientAddr, &size)) == -1) { + if (errno == SOCKET_EWOULDBLOCK) + return -2; + printf("ERROR: failed to accept the connection\n"); + return -1; + } + info->server.sockFd = connd; +#ifdef WOLFSSL_DTLS + } +#endif + + if (info->showVerbose) { + printf("Got client %d\n", connd); + } + + return 0; +} +static void CloseAndCleanupListenSocket(int* listenFd) +{ + if (*listenFd != -1) { + close(*listenFd); + *listenFd = -1; + } +} + +static int bench_tls_server(info_t* info) +{ + byte *readBuf = NULL; + double start; + int ret, len = 0, readBufSz; + WOLFSSL_CTX* srv_ctx = NULL; + WOLFSSL* srv_ssl = NULL; + int tls13 = XSTRNCMP(info->cipher, "TLS13", 5) == 0; + int total_sz; + + /* set up server */ +#ifdef WOLFSSL_DTLS + if(info->doDTLS) { + if(tls13) return WOLFSSL_SUCCESS; + srv_ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method()); + } else { +#endif +#ifdef WOLFSSL_TLS13 + if (tls13) + srv_ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); +#endif + if (!tls13) + srv_ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()); +#ifdef WOLFSSL_DTLS + } +#endif + if (srv_ctx == NULL) { + printf("error creating server ctx\n"); + ret = MEMORY_E; goto exit; + } + +#ifndef NO_CERTS +#ifdef HAVE_ECC + if (XSTRSTR(info->cipher, "ECDSA")) { + ret = wolfSSL_CTX_use_PrivateKey_buffer(srv_ctx, ecc_key_der_256, + sizeof_ecc_key_der_256, WOLFSSL_FILETYPE_ASN1); + } + else +#endif + { + ret = wolfSSL_CTX_use_PrivateKey_buffer(srv_ctx, server_key_der_2048, + sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1); + } + if (ret != WOLFSSL_SUCCESS) { + printf("error loading server key\n"); + goto exit; + } + +#ifdef HAVE_ECC + if (XSTRSTR(info->cipher, "ECDSA")) { + ret = wolfSSL_CTX_use_certificate_buffer(srv_ctx, serv_ecc_der_256, + sizeof_serv_ecc_der_256, WOLFSSL_FILETYPE_ASN1); + } + else +#endif + { + ret = wolfSSL_CTX_use_certificate_buffer(srv_ctx, server_cert_der_2048, + sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1); + } + if (ret != WOLFSSL_SUCCESS) { + printf("error loading server cert\n"); + goto exit; + } +#endif /* !NO_CERTS */ + + wolfSSL_CTX_SetIOSend(srv_ctx, ServerSend); + wolfSSL_CTX_SetIORecv(srv_ctx, ServerRecv); + + /* set cipher suite */ + ret = wolfSSL_CTX_set_cipher_list(srv_ctx, info->cipher); + if (ret != WOLFSSL_SUCCESS) { + printf("error setting cipher suite\n"); + goto exit; + } + +#ifndef NO_DH + ret = wolfSSL_CTX_SetMinDhKey_Sz(srv_ctx, MIN_DHKEY_BITS); + if (ret != WOLFSSL_SUCCESS) { + printf("Error setting minimum DH key size\n"); + goto exit; + } +#endif + + /* Allocate read buffer */ + readBufSz = info->packetSize; + readBuf = (unsigned char*)XMALLOC(readBufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (readBuf == NULL) { + printf("failed to allocate read memory\n"); + ret = MEMORY_E; goto exit; + } + + /* BENCHMARK CONNECTIONS LOOP */ + while (!info->server.shutdown) { + #ifdef BENCH_USE_NONBLOCK + int err; + #endif + + #ifdef HAVE_PTHREAD + if (!info->useLocalMem) + #endif + { + /* Accept client connections */ + ret = SocketWaitClient(info); + #ifdef BENCH_USE_NONBLOCK + if (ret == -2) { + sleep(0); + continue; + } + #endif + if (ret != 0) { + goto exit; + } + } + + srv_ssl = wolfSSL_new(srv_ctx); + if (srv_ssl == NULL) { + printf("error creating server object\n"); + ret = MEMORY_E; goto exit; + } +#ifdef WOLFSSL_DTLS + if (info->doDTLS) { + ret = wolfSSL_dtls_set_peer(srv_ssl, &info->clientAddr, + sizeof(info->clientAddr)); + if (ret != WOLFSSL_SUCCESS) { + printf("error setting dtls peer\n"); + goto exit; + } + } +#endif + + wolfSSL_SetIOReadCtx(srv_ssl, info); + wolfSSL_SetIOWriteCtx(srv_ssl, info); + #ifndef NO_DH + wolfSSL_SetTmpDH(srv_ssl, dhp, sizeof(dhp), dhg, sizeof(dhg)); + #endif + + /* accept TLS connection */ + start = gettime_secs(1); + #ifndef BENCH_USE_NONBLOCK + ret = wolfSSL_accept(srv_ssl); + #else + do { + ret = wolfSSL_accept(srv_ssl); + err = wolfSSL_get_error(srv_ssl, ret); + } + while (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE); + #endif + start = gettime_secs(0) - start; + if (ret != WOLFSSL_SUCCESS) { + printf("error on server accept\n"); + ret = wolfSSL_get_error(srv_ssl, ret); + goto exit; + } + + info->server_stats.connTime += start; + info->server_stats.connCount++; + + /* echo loop */ + ret = 0; + total_sz = 0; + while (ret == 0 && total_sz < info->maxSize) { + double rxTime; + + /* read message from client */ + XMEMSET(readBuf, 0, readBufSz); + start = gettime_secs(1); + #ifndef BENCH_USE_NONBLOCK + ret = wolfSSL_read(srv_ssl, readBuf, readBufSz); + #else + do { + ret = wolfSSL_read(srv_ssl, readBuf, readBufSz); + err = wolfSSL_get_error(srv_ssl, ret); + } + while (err == WOLFSSL_ERROR_WANT_READ); + #endif + rxTime = gettime_secs(0) - start; + + /* shutdown signals, no more connections for this cipher */ + if (XSTRSTR((const char*)readBuf, kShutdown) != NULL) { + info->server.shutdown = 1; + if (info->showVerbose) { + printf("Server shutdown done\n"); + } + ret = 0; /* success */ + break; + } + + info->server_stats.rxTime += rxTime; + if (ret < 0) { + printf("error on server read\n"); + ret = wolfSSL_get_error(srv_ssl, ret); + goto exit; + } + info->server_stats.rxTotal += ret; + len = ret; + total_sz += ret; + + /* write message back to client */ + start = gettime_secs(1); + #ifndef BENCH_USE_NONBLOCK + ret = wolfSSL_write(srv_ssl, readBuf, len); + #else + do { + ret = wolfSSL_write(srv_ssl, readBuf, len); + err = wolfSSL_get_error(srv_ssl, ret); + } + while (err == WOLFSSL_ERROR_WANT_WRITE); + #endif + info->server_stats.txTime += gettime_secs(0) - start; + if (ret < 0) { + printf("error on server write\n"); + ret = wolfSSL_get_error(srv_ssl, ret); + goto exit; + } + info->server_stats.txTotal += ret; + ret = 0; /* reset return code */ + } + + CloseAndCleanupSocket(&info->server.sockFd); + + wolfSSL_free(srv_ssl); + srv_ssl = NULL; +#ifdef WOLFSSL_DTLS + if (info->doDTLS) { + SetupSocketAndListen(&info->listenFd, info->port, info->doDTLS); + } +#endif + + } + +exit: + + if (ret != 0 && ret != WOLFSSL_SUCCESS) { + printf("Server Error: %d (%s)\n", ret, + wolfSSL_ERR_reason_error_string(ret)); + } + + /* clean up */ + CloseAndCleanupSocket(&info->server.sockFd); + if (srv_ssl != NULL) + wolfSSL_free(srv_ssl); + if (srv_ctx != NULL) + wolfSSL_CTX_free(srv_ctx); + XFREE(readBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + info->server.ret = ret; + + return ret; +} + +#ifdef HAVE_PTHREAD +static void* server_thread(void* args) +{ + int ret = 0; + info_t* info = (info_t*)args; + + if (!info->useLocalMem) { + /* Setup TLS server listener */ +#ifdef WOLFSSL_DTLS + ret = SetupSocketAndListen(&info->listenFd, info->port, info->doDTLS); +#else + ret = SetupSocketAndListen(&info->listenFd, info->port, 0); +#endif + } + if (ret == 0) { + ret = bench_tls_server(info); + + if (!info->useLocalMem) { + CloseAndCleanupListenSocket(&info->listenFd); + } + } + + pthread_cond_signal(&info->to_client.cond); + info->to_server.done = 1; + info->server.ret = ret; + + return NULL; +} +#endif /* HAVE_PTHREAD */ +#endif /* !NO_WOLFSSL_SERVER */ + + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif +static void print_stats(stats_t* wcStat, 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 = "%-6s %-33s %11d %9d %9.3f %9.3f %9.3f %9.3f %17.3f %15.3f\n"; + } + + printf(formatStr, + desc, + cipher, + wcStat->txTotal + wcStat->rxTotal, + wcStat->connCount, + wcStat->rxTime * 1000, + wcStat->txTime * 1000, + wcStat->rxTotal / wcStat->rxTime / 1024 / 1024, + wcStat->txTotal / wcStat->txTime / 1024 / 1024, + wcStat->connTime * 1000, + wcStat->connTime * 1000 / wcStat->connCount); +} + +static void Usage(void) +{ + printf("tls_bench " LIBWOLFSSL_VERSION_STRING + " NOTE: All files relative to wolfSSL home dir\n"); + printf("-? Help, print this usage\n"); + printf("-c Run as client only, no threading and uses sockets\n"); + printf("-s Run as server only, no threading and uses sockets\n"); + printf("-h Host (default %s)\n", BENCH_DEFAULT_HOST); + printf("-P Port (default %d)\n", BENCH_DEFAULT_PORT); + printf("-e List Every cipher suite available\n"); + printf("-i Show peer info\n"); + printf("-l Cipher suite list (: delimited)\n"); + printf("-t Time (seconds) to run each test (default %d)\n", BENCH_RUNTIME_SEC); + printf("-p The packet size in bytes [1-16kB] (default %d)\n", TEST_PACKET_SIZE); +#ifdef WOLFSSL_DTLS + printf(" In the case of DTLS, [1-8kB] (default %d)\n", TEST_DTLS_PACKET_SIZE); +#endif + printf("-S The total size in bytes (default %d)\n", TEST_MAX_SIZE); + printf("-v Show verbose output\n"); +#ifdef DEBUG_WOLFSSL + printf("-d Enable debug messages\n"); +#endif +#ifdef HAVE_PTHREAD + printf("-T Number of threaded server/client pairs (default %d)\n", NUM_THREAD_PAIRS); + printf("-m Use local memory, not socket\n"); +#endif +#ifdef WOLFSSL_DTLS + printf("-u Use DTLS\n"); +#endif +} + +static void ShowCiphers(void) +{ + char ciphers[WOLFSSL_CIPHER_LIST_MAX_SIZE]; + + int ret = wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers)); + + if (ret == WOLFSSL_SUCCESS) + printf("%s\n", ciphers); +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +int bench_tls(void* args) +{ + int ret = 0; + info_t *theadInfo = NULL, *info; + stats_t cli_comb, srv_comb; + int i; + char *cipher, *next_cipher, *ciphers = NULL; + int argc = 0; + char** argv = NULL; + int ch; + + /* Vars configured by command line arguments */ + int argRuntimeSec = BENCH_RUNTIME_SEC; + char *argCipherList = NULL; + int argTestPacketSize = TEST_PACKET_SIZE; + int argTestMaxSize = TEST_MAX_SIZE; + int argThreadPairs = NUM_THREAD_PAIRS; + int argShowVerbose = SHOW_VERBOSE; + int argClientOnly = 0; + int argServerOnly = 0; + const char* argHost = BENCH_DEFAULT_HOST; + int argPort = BENCH_DEFAULT_PORT; + int argShowPeerInfo = 0; +#ifdef HAVE_PTHREAD + int doShutdown; +#endif +#if !defined(NO_WOLFSSL_SERVER) || defined(HAVE_PTHREAD) + int argLocalMem = 0; + int listenFd = -1; +#endif +#ifdef WOLFSSL_DTLS + int doDTLS = 0; + int option_p = 0; +#endif + if (args != NULL) { + argc = ((func_args*)args)->argc; + argv = ((func_args*)args)->argv; + ((func_args*)args)->return_code = -1; /* error state */ + } + + /* Initialize wolfSSL */ + wolfSSL_Init(); + + /* Parse command line arguments */ + while ((ch = mygetopt(argc, argv, "?" "udeil:p:t:vT:sch:P:mS:")) != -1) { + switch (ch) { + case '?' : + Usage(); + goto exit; + + case 's': + argServerOnly = 1; + break; + + case 'c': + argClientOnly = 1; + break; + + case 'h': + argHost = myoptarg; + break; + + case 'P': + argPort = atoi(myoptarg); + break; + + case 'd' : + #ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); + #endif + break; + + case 'e' : + ShowCiphers(); + goto exit; + + case 'i' : + argShowPeerInfo = 1; + break; + + case 'l' : + argCipherList = myoptarg; + break; + + case 'p' : + argTestPacketSize = atoi(myoptarg); + if (argTestPacketSize > (16 * 1024)) { + printf("Invalid packet size %d\n", argTestPacketSize); + Usage(); + ret = MY_EX_USAGE; goto exit; + } + #ifdef WOLFSSL_DTLS + option_p = 1; + #endif + break; + + case 'S' : + argTestMaxSize = atoi(myoptarg); + break; + + case 't' : + argRuntimeSec = atoi(myoptarg); + break; + + case 'v' : + argShowVerbose = 1; + break; + + case 'T' : + #ifdef HAVE_PTHREAD + argThreadPairs = atoi(myoptarg); + #endif + break; + + case 'm': + #ifdef HAVE_PTHREAD + argLocalMem = 1; + #endif + break; + case 'u': + #ifdef WOLFSSL_DTLS + doDTLS = 1; + #ifdef BENCH_USE_NONBLOCK + printf("tls_bench hasn't yet supported DTLS " + "non-blocking mode.\n"); + Usage(); + ret = MY_EX_USAGE; goto exit; + #endif + #endif + break; + default: + Usage(); + ret = MY_EX_USAGE; goto exit; + } + } + + /* reset for test cases */ + myoptind = 0; + + if (argCipherList != NULL) { + /* Use the list from CL argument */ + cipher = argCipherList; + } + else { + /* Run for each cipher */ + ciphers = (char*)XMALLOC(WOLFSSL_CIPHER_LIST_MAX_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ciphers == NULL) { + goto exit; + } + wolfSSL_get_ciphers(ciphers, WOLFSSL_CIPHER_LIST_MAX_SIZE); + cipher = ciphers; + } + + /* for server or client side only, only 1 thread is allowed */ + if (argServerOnly || argClientOnly) { + argThreadPairs = 1; + } +#ifndef HAVE_PTHREAD + else { + printf("Threading is not enabled, so please use -s or -c to indicate side\n"); + Usage(); + ret = MY_EX_USAGE; goto exit; + } +#endif + + /* Allocate test info array */ + theadInfo = (info_t*)XMALLOC(sizeof(info_t) * argThreadPairs, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (theadInfo == NULL) { + ret = MEMORY_E; goto exit; + } + XMEMSET(theadInfo, 0, sizeof(info_t) * argThreadPairs); + +#ifndef NO_WOLFSSL_SERVER + /* Use same listen socket to avoid timing issues between client and server */ + if (argServerOnly && !argLocalMem) { + /* Setup TLS server listener */ +#ifdef WOLFSSL_DTLS + ret = SetupSocketAndListen(&listenFd, argPort, doDTLS); +#else + ret = SetupSocketAndListen(&listenFd, argPort, 0); +#endif + if (ret != 0) goto exit; + } +#endif + +#ifdef WOLFSSL_DTLS + if (doDTLS) { + if (argLocalMem) { + printf("tls_bench hasn't yet supported DTLS with local memory.\n"); + ret = MY_EX_USAGE; goto exit; + } + if (option_p && argTestPacketSize > TEST_DTLS_PACKET_SIZE){ + printf("Invalid packet size %d\n", argTestPacketSize); + Usage(); + ret = MY_EX_USAGE; goto exit; + } else { + /* argTestPacketSize would be default for tcp packet */ + if (argTestPacketSize >= TEST_PACKET_SIZE) + argTestPacketSize = TEST_DTLS_PACKET_SIZE; + } + } +#endif + printf("Running TLS Benchmarks...\n"); + + /* parse by : */ + while ((cipher != NULL) && (cipher[0] != '\0')) { + next_cipher = strchr(cipher, ':'); + if (next_cipher != NULL) { + cipher[next_cipher - cipher] = '\0'; + } + + if (argShowVerbose) { + printf("Cipher: %s\n", cipher); + } + + for (i=0; ihost = argHost; + info->port = argPort + i; /* threads must have separate ports */ + info->cipher = cipher; + info->packetSize = argTestPacketSize; + + info->runTimeSec = argRuntimeSec; + info->maxSize = argTestMaxSize; + info->showPeerInfo = argShowPeerInfo; + info->showVerbose = argShowVerbose; + #ifndef NO_WOLFSSL_SERVER + info->listenFd = listenFd; + #endif + info->client.sockFd = -1; + info->server.sockFd = -1; + + #ifdef WOLFSSL_DTLS + info->doDTLS = doDTLS; + #ifdef HAVE_PTHREAD + info->serverReady = 0; + if (argServerOnly || argClientOnly) { + info->clientOrserverOnly = 1; + } + #endif + #endif + if (argClientOnly) { + #ifndef NO_WOLFSSL_CLIENT + ret = bench_tls_client(info); + #endif + } + else if (argServerOnly) { + #ifndef NO_WOLFSSL_SERVER + ret = bench_tls_server(info); + #endif + } + else { + #ifdef HAVE_PTHREAD + info->useLocalMem = argLocalMem; + pthread_mutex_init(&info->to_server.mutex, NULL); + pthread_mutex_init(&info->to_client.mutex, NULL); + #ifdef WOLFSSL_DTLS + pthread_mutex_init(&info->dtls_mutex, NULL); + pthread_cond_init(&info->dtls_cond, NULL); + #endif + 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); + #endif + } + } + + #ifdef HAVE_PTHREAD + /* For threading, wait for completion */ + if (!argClientOnly && !argServerOnly) { + /* Wait until threads are marked done */ + do { + doShutdown = 1; + + for (i = 0; i < argThreadPairs; ++i) { + info = &theadInfo[i]; + if (!info->to_client.done || !info->to_server.done) { + doShutdown = 0; + sleep(1); /* Allow other threads to run */ + } + + } + } while (!doShutdown); + if (argShowVerbose) { + printf("Shutdown complete\n"); + } + } + #endif /* HAVE_PTHREAD */ + + if (argShowVerbose) { + /* print results */ + for (i = 0; i < argThreadPairs; ++i) { + info = &theadInfo[i]; + + printf("\nThread %d\n", i); + #ifndef NO_WOLFSSL_SERVER + if (!argClientOnly) + print_stats(&info->server_stats, "Server", info->cipher, 1); + #endif + #ifndef NO_WOLFSSL_CLIENT + if (!argServerOnly) + print_stats(&info->client_stats, "Client", info->cipher, 1); + #endif + } + } + + /* print combined results for more than one thread */ + XMEMSET(&cli_comb, 0, sizeof(cli_comb)); + XMEMSET(&srv_comb, 0, sizeof(srv_comb)); + + for (i = 0; i < argThreadPairs; ++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; + } + + if (argShowVerbose) { + printf("Totals for %d Threads\n", argThreadPairs); + } + else { + printf("%-6s %-33s %11s %9s %9s %9s %9s %9s %17s %15s\n", + "Side", "Cipher", "Total Bytes", "Num Conns", "Rx ms", "Tx ms", + "Rx MB/s", "Tx MB/s", "Connect Total ms", "Connect Avg ms"); + #ifndef NO_WOLFSSL_SERVER + if (!argClientOnly) + print_stats(&srv_comb, "Server", theadInfo[0].cipher, 0); + #endif + #ifndef NO_WOLFSSL_CLIENT + if (!argServerOnly) + print_stats(&cli_comb, "Client", theadInfo[0].cipher, 0); + #endif + } + + /* target next cipher */ + cipher = (next_cipher != NULL) ? (next_cipher + 1) : NULL; + } /* while */ + +exit: + +#ifndef NO_WOLFSSL_SERVER + if (argServerOnly && !argLocalMem) { + /* Close server listener */ + CloseAndCleanupListenSocket(&listenFd); + } +#endif + + /* Cleanup the wolfSSL environment */ + wolfSSL_Cleanup(); + + /* Free theadInfo array */ + XFREE(theadInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* Free cipher list */ + XFREE(ciphers, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* Return reporting a success */ + if (args) + ((func_args*)args)->return_code = ret; + + return ret; +} +#endif /* (!NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER) && !WOLFCRYPT_ONLY */ + +#ifndef NO_MAIN_DRIVER + +int main(int argc, char** argv) +{ + func_args args; + + args.argc = argc; + args.argv = argv; + args.return_code = 0; + +#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && !defined(WOLFCRYPT_ONLY) + bench_tls(&args); +#endif + + return args.return_code; +} + +#endif /* !NO_MAIN_DRIVER */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/benchmark/tls_bench.h b/FreeRTOS-Plus/Source/WolfSSL/examples/benchmark/tls_bench.h new file mode 100644 index 000000000..483a3ae4f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/benchmark/tls_bench.h @@ -0,0 +1,30 @@ +/* tls_bench.h + * + * Copyright (C) 2006-2020 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_TLS_BENCH_H +#define WOLFSSL_TLS_BENCH_H + + +int bench_tls(void* args); + + +#endif /* WOLFSSL_TLS_BENCH_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/client/client.c b/FreeRTOS-Plus/Source/WolfSSL/examples/client/client.c index 5838c67b9..6c8cf5013 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/client/client.c +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/client/client.c @@ -1,8 +1,8 @@ /* client.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,202 +16,1399 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif -#include - -#if defined(WOLFSSL_MDK_ARM) - #include - #include - - #if defined(WOLFSSL_MDK5) - #include "cmsis_os.h" - #include "rl_fs.h" - #include "rl_net.h" - #else - #include "rtl.h" - #endif - - #include "wolfssl_MDK_ARM.h" -#endif - #include -#if !defined(WOLFSSL_TRACK_MEMORY) && !defined(NO_MAIN_DRIVER) - /* in case memory tracker wants stats */ - #define WOLFSSL_TRACK_MEMORY -#endif - #include +#if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + #include + #include + #include "rl_fs.h" + #include "rl_net.h" +#endif + #include -#include "examples/client/client.h" +#include +#include +#ifndef NO_WOLFSSL_CLIENT +#ifdef USE_FAST_MATH + /* included to inspect the size of FP_MAX_BITS */ + /* need integer.h header to make sure right math version used */ + #include +#endif +#ifdef HAVE_ECC + #include +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + static int devId = INVALID_DEVID; +#endif + +#define DEFAULT_TIMEOUT_SEC 2 +#ifndef MAX_NON_BLOCK_SEC +#define MAX_NON_BLOCK_SEC 10 +#endif + +#define OCSP_STAPLING 1 +#define OCSP_STAPLINGV2 2 +#define OCSP_STAPLINGV2_MULTI 3 +#define OCSP_STAPLING_OPT_MAX OCSP_STAPLINGV2_MULTI + +/* 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. */ + +static int lng_index = 0; #ifdef WOLFSSL_CALLBACKS - int handShakeCB(HandShakeInfo*); - int timeoutCB(TimeoutInfo*); - Timeval timeout; + WOLFSSL_TIMEVAL timeoutConnect; + 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 select_ret; + int ret; + int error; + SOCKET_T sockfd; + int select_ret = 0; + int elapsedSec = 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, timeoutConnect); +#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 + #ifdef WOLFSSL_ASYNC_CRYPT + || error == WC_PENDING_E + #endif + #ifdef WOLFSSL_NONBLOCK_OCSP + || error == OCSP_WANT_READ + #endif + )) { int currTimeout = 1; - if (error == SSL_ERROR_WANT_READ) + if (error == WOLFSSL_ERROR_WANT_READ) printf("... client would read block\n"); - else + else if (error == WOLFSSL_ERROR_WANT_WRITE) printf("... client would write block\n"); -#ifdef WOLFSSL_DTLS - currTimeout = wolfSSL_dtls_get_current_timeout(ssl); +#ifdef WOLFSSL_ASYNC_CRYPT + if (error == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + else #endif - select_ret = tcp_select(sockfd, currTimeout); - - if ((select_ret == TEST_RECV_READY) || - (select_ret == TEST_ERROR_READY)) { - #ifndef WOLFSSL_CALLBACKS - ret = wolfSSL_connect(ssl); - #else - ret = wolfSSL_connect_ex(ssl,handShakeCB,timeoutCB,timeout); + { + if (error != WOLFSSL_ERROR_WANT_WRITE) { + #ifdef WOLFSSL_DTLS + currTimeout = wolfSSL_dtls_get_current_timeout(ssl); #endif + select_ret = tcp_select(sockfd, currTimeout); + } + } + + if ((select_ret == TEST_RECV_READY) || (select_ret == TEST_SEND_READY) + || (select_ret == TEST_ERROR_READY) + #ifdef WOLFSSL_ASYNC_CRYPT + || error == WC_PENDING_E + #endif + ) { + #ifndef WOLFSSL_CALLBACKS + ret = wolfSSL_connect(ssl); + #else + ret = wolfSSL_connect_ex(ssl, handShakeCB, timeoutCB, + timeoutConnect); + #endif error = wolfSSL_get_error(ssl, 0); + elapsedSec = 0; /* reset elapsed */ + if (error == WOLFSSL_ERROR_WANT_WRITE) { + /* Do a send select here. */ + select_ret = tcp_select_tx(sockfd, 1); + if (select_ret == TEST_TIMEOUT) { + error = WOLFSSL_FATAL_ERROR; + } + } } else if (select_ret == TEST_TIMEOUT && !wolfSSL_dtls(ssl)) { - error = SSL_ERROR_WANT_READ; + error = WOLFSSL_ERROR_WANT_READ; + + elapsedSec += currTimeout; + if (elapsedSec > MAX_NON_BLOCK_SEC) { + printf("Nonblocking connect timeout\n"); + error = WOLFSSL_FATAL_ERROR; + } } #ifdef WOLFSSL_DTLS else if (select_ret == TEST_TIMEOUT && wolfSSL_dtls(ssl) && - wolfSSL_dtls_got_timeout(ssl) >= 0) { - error = SSL_ERROR_WANT_READ; + wolfSSL_dtls_got_timeout(ssl) >= 0) { + 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; } -static void Usage(void) +static void ShowCiphers(void) { - printf("client " LIBWOLFSSL_VERSION_STRING - " NOTE: All files relative to wolfSSL home dir\n"); - 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); - printf("-v SSL version [0-3], SSLv3(0) - TLS1.2(3)), default %d\n", - CLIENT_DEFAULT_VERSION); - printf("-l Cipher list\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); + static char ciphers[WOLFSSL_CIPHER_LIST_MAX_SIZE]; + + int ret = wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers)); + + if (ret == WOLFSSL_SUCCESS) + printf("%s\n", ciphers); +} + +/* Shows which versions are valid */ +static void ShowVersions(void) +{ +#ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_SSLV3 + printf("0:"); + #endif + #ifdef WOLFSSL_ALLOW_TLSV10 + printf("1:"); + #endif + printf("2:"); +#endif /* NO_OLD_TLS */ +#ifndef WOLFSSL_NO_TLS12 + printf("3:"); +#endif +#ifdef WOLFSSL_TLS13 + printf("4:"); +#endif + printf("d(downgrade):"); +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + printf("e(either):"); +#endif + printf("\n"); +} + +#ifdef WOLFSSL_TLS13 +static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, + int useX448) +{ + int groups[3] = {0}; + int count = 0; + + (void)useX25519; + (void)useX448; + + WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); + if (onlyKeyShare == 0 || onlyKeyShare == 2) { + #ifdef HAVE_CURVE25519 + if (useX25519) { + groups[count++] = WOLFSSL_ECC_X25519; + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != WOLFSSL_SUCCESS) + err_sys("unable to use curve x25519"); + } + else + #endif + #ifdef HAVE_CURVE448 + if (useX448) { + groups[count++] = WOLFSSL_ECC_X448; + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448) != WOLFSSL_SUCCESS) + err_sys("unable to use curve x448"); + } + else + #endif + { + #ifdef HAVE_ECC + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + groups[count++] = WOLFSSL_ECC_SECP256R1; + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve secp256r1"); + } + #endif + #endif + } + } + if (onlyKeyShare == 0 || onlyKeyShare == 1) { + #ifdef HAVE_FFDHE_2048 + groups[count++] = WOLFSSL_FFDHE_2048; + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) != WOLFSSL_SUCCESS) + err_sys("unable to use DH 2048-bit parameters"); + #endif + } + + if (wolfSSL_set_groups(ssl, groups, count) != WOLFSSL_SUCCESS) + err_sys("unable to set groups"); + WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); +} +#endif + +#ifdef WOLFSSL_EARLY_DATA +static void EarlyData(WOLFSSL_CTX* ctx, WOLFSSL* ssl, const char* msg, + int msgSz, char* buffer) +{ + int err; + int ret; + + do { + err = 0; /* reset error */ + ret = wolfSSL_write_early_data(ssl, msg, msgSz, &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_early_data msg error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("SSL_write_early_data failed"); + } + do { + err = 0; /* reset error */ + ret = wolfSSL_write_early_data(ssl, msg, msgSz, &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_early_data msg error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + err_sys("SSL_write_early_data failed"); + } +} +#endif + +/* Measures average time to create, connect and disconnect a connection (TPS). +Benchmark = number of connections. */ +static const char* client_bench_conmsg[][5] = { + /* English */ + { + "wolfSSL_resume avg took:", "milliseconds\n", + "wolfSSL_connect avg took:", "milliseconds\n", + NULL + }, + #ifndef NO_MULTIBYTE_PRINT + /* Japanese */ + { + "wolfSSL_resume 平均時間:", "ミリ秒\n", + "wolfSSL_connect 平均時間:", "ミリ秒\n", + } + #endif +}; + +static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, + int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession, int useX25519, + int useX448, int helloRetry, int onlyKeyShare, int version, int earlyData) +{ + /* time passed in number of connects give average */ + int times = benchmark, skip = times * 0.1; + int loops = resumeSession ? 2 : 1; + int i = 0, err, ret; +#ifndef NO_SESSION_CACHE + WOLFSSL_SESSION* benchSession = NULL; +#endif +#ifdef WOLFSSL_TLS13 + byte* reply[80]; + static const char msg[] = "GET /index.html HTTP/1.0\r\n\r\n"; +#ifdef WOLFSSL_EARLY_DATA + static const char earlyMsg[] = "A drop of info"; +#endif +#endif + const char** words = client_bench_conmsg[lng_index]; + + (void)resumeSession; + (void)useX25519; + (void)useX448; + (void)helloRetry; + (void)onlyKeyShare; + (void)version; + (void)earlyData; + + while (loops--) { + #ifndef NO_SESSION_CACHE + int benchResume = resumeSession && loops == 0; + #endif + double start = current_time(1), avg; + + for (i = 0; i < times; i++) { + SOCKET_T sockfd; + WOLFSSL* ssl; + + if (i == skip) + start = current_time(1); + + ssl = wolfSSL_new(ctx); + if (ssl == NULL) + err_sys("unable to get SSL object"); + + #ifndef NO_SESSION_CACHE + if (benchResume) + wolfSSL_set_session(ssl, benchSession); + #endif + #ifdef WOLFSSL_TLS13 + else if (version >= 4) { + if (!helloRetry) + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448); + else + wolfSSL_NoKeyShares(ssl); + } + #endif + + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); + + if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { + err_sys("error in setting fd"); + } + + #if defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \ + defined(WOLFSSL_EARLY_DATA) + if (version >= 4 && benchResume && earlyData) { + char buffer[WOLFSSL_MAX_ERROR_SZ]; + EarlyData(ctx, ssl, earlyMsg, sizeof(earlyMsg)-1, buffer); + } + #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) { + err_sys("SSL_connect failed"); + } + + #ifdef WOLFSSL_TLS13 + #ifndef NO_SESSION_CACHE + if (version >= 4 && resumeSession && !benchResume) + #else + if (version >= 4 && resumeSession) + #endif + { + 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 + if (i == (times-1) && resumeSession) { + benchSession = wolfSSL_get_session(ssl); + } + #endif + wolfSSL_free(ssl); ssl = NULL; + CloseSocket(sockfd); + } + avg = current_time(0) - start; + avg /= (times - skip); + avg *= 1000; /* milliseconds */ + #ifndef NO_SESSION_CACHE + if (benchResume) + printf("%s %8.3f %s\n", words[0],avg, words[1]); + else + #endif + printf("%s %8.3f %s\n", words[2],avg, words[3]); + + WOLFSSL_TIME(times); + } + + return EXIT_SUCCESS; +} + +/* Measures throughput in kbps. Throughput = number of bytes */ +static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, + int dtlsUDP, int dtlsSCTP, int block, size_t throughput, int useX25519, + int useX448) +{ + double start, conn_time = 0, tx_time = 0, rx_time = 0; + SOCKET_T sockfd; + WOLFSSL* ssl; + 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) != WOLFSSL_SUCCESS) { + err_sys("error in setting fd"); + } + + (void)useX25519; + (void)useX448; + #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_CURVE448 + if (useX448) { + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve x448"); + } + } + #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; + + /* Record connection time */ + conn_time = current_time(0) - start; + + /* Allocate TX/RX buffers */ + tx_buffer = (char*)XMALLOC(block, NULL, DYNAMIC_TYPE_TMP_BUFFER); + rx_buffer = (char*)XMALLOC(block, 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); + #endif + if (ret == 0) { + size_t xfer_bytes; + + /* Generate random data to send */ + ret = wc_RNG_GenerateBlock(&rng, (byte*)tx_buffer, block); + wc_FreeRng(&rng); + if(ret != 0) { + err_sys("wc_RNG_GenerateBlock failed"); + } + + /* Perform TX and RX of bytes */ + xfer_bytes = 0; + while (throughput > xfer_bytes) { + int len, rx_pos, select_ret; + + /* Determine packet size */ + len = min(block, (int)(throughput - xfer_bytes)); + + /* Perform TX */ + start = current_time(1); + 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, 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) { + 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 { + rx_pos += ret; + } + } + rx_time += current_time(0) - start; + } + + /* 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"); + } + + /* Update overall position */ + xfer_bytes += len; + } + } + else { + err_sys("wc_InitRng failed"); + } + (void)rng; /* for WC_NO_RNG case */ + } + else { + err_sys("Client buffer malloc failed"); + } + 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"); + } + + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); ssl = NULL; + CloseSocket(sockfd); + +#if !defined(__MINGW32__) + printf("wolfSSL Client Benchmark %zu bytes\n" +#else + printf("wolfSSL Client Benchmark %d bytes\n" +#endif + "\tConnect %8.3f ms\n" + "\tTX %8.3f ms (%8.3f MBps)\n" + "\tRX %8.3f ms (%8.3f MBps)\n", +#if !defined(__MINGW32__) + throughput, +#else + (int)throughput, +#endif + conn_time * 1000, + tx_time * 1000, throughput / tx_time / 1024 / 1024, + rx_time * 1000, throughput / rx_time / 1024 / 1024 + ); + + return EXIT_SUCCESS; +} + +const char* starttlsCmd[6] = { + "220", + "EHLO mail.example.com\r\n", + "250", + "STARTTLS\r\n", + "220", + "QUIT\r\n", +}; + +/* Initiates the STARTTLS command sequence over TCP */ +static int StartTLS_Init(SOCKET_T* sockfd) +{ + char tmpBuf[256]; + + if (sockfd == NULL) + return BAD_FUNC_ARG; + + /* S: 220 SMTP service ready */ + 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); + } else { + err_sys("incorrect STARTTLS command received"); + } + + /* C: EHLO mail.example.com */ + if (send(*sockfd, starttlsCmd[1], (int)XSTRLEN(starttlsCmd[1]), 0) != + (int)XSTRLEN(starttlsCmd[1])) + err_sys("failed to send STARTTLS EHLO command\n"); + + /* S: 250 offers a warm hug of welcome */ + 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); + } else { + err_sys("incorrect STARTTLS command received"); + } + + /* C: STARTTLS */ + if (send(*sockfd, starttlsCmd[3], (int)XSTRLEN(starttlsCmd[3]), 0) != + (int)XSTRLEN(starttlsCmd[3])) { + err_sys("failed to send STARTTLS command\n"); + } + + /* S: 220 Go ahead */ + 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); + } else { + err_sys("incorrect STARTTLS command received, expected 220"); + } + + return WOLFSSL_SUCCESS; +} + +/* Closes down the SMTP connection */ +static int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown) +{ + int ret, err = 0; + char tmpBuf[256]; + + if (ssl == NULL) + return BAD_FUNC_ARG; + + printf("\nwolfSSL client shutting down SMTP connection\n"); + + XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); + + /* C: QUIT */ + 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 */ + 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 == WOLFSSL_SHUTDOWN_NOT_DONE) { + if (tcp_select(wolfSSL_get_fd(ssl), DEFAULT_TIMEOUT_SEC) == + TEST_RECV_READY) { + ret = wolfSSL_shutdown(ssl); /* bidirectional shutdown */ + if (ret == WOLFSSL_SUCCESS) + printf("Bidirectional shutdown complete\n"); + } + if (ret != WOLFSSL_SUCCESS) + printf("Bidirectional shutdown failed\n"); + } + + return WOLFSSL_SUCCESS; +} + +static void ClientWrite(WOLFSSL* ssl, char* msg, int msgSz, const char* str) +{ + 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 == WOLFSSL_ERROR_WANT_WRITE + #ifdef WOLFSSL_ASYNC_CRYPT + || err == WC_PENDING_E + #endif + ); + if (ret != msgSz) { + printf("SSL_write%s msg error %d, %s\n", str, err, + wolfSSL_ERR_error_string(err, buffer)); + err_sys("SSL_write failed"); + } +} + +static void ClientRead(WOLFSSL* ssl, char* reply, int replyLen, int mustRead, + const char* str) +{ + int ret, err; + char buffer[WOLFSSL_MAX_ERROR_SZ]; + double start = current_time(1), elapsed; + + 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"); + } + } + + if (mustRead && err == WOLFSSL_ERROR_WANT_READ) { + elapsed = current_time(0) - start; + if (elapsed > MAX_NON_BLOCK_SEC) { + printf("Nonblocking read timeout\n"); + ret = WOLFSSL_FATAL_ERROR; + break; + } + } + } while ((mustRead && err == WOLFSSL_ERROR_WANT_READ) + #ifdef WOLFSSL_ASYNC_CRYPT + || err == WC_PENDING_E + #endif + ); + if (ret > 0) { + reply[ret] = 0; + printf("%s%s\n", str, reply); + } +} + + +/* when adding new option, please follow the steps below: */ +/* 1. add new option message in English section */ +/* 2. increase the number of the second column */ +/* 3. add the same message into Japanese section */ +/* (will be translated later) */ +/* 4. add printf() into suitable position of Usage() */ +static const char* client_usage_msg[][59] = { + /* English */ + { + " NOTE: All files relative to wolfSSL home dir\n", /* 0 */ + "Max RSA key size in bits for build is set at : ", /* 1 */ +#ifdef NO_RSA + "RSA not supported\n", /* 2 */ +#elif defined(WOLFSSL_SP_MATH) /* case of SP math only */ +#ifndef WOLFSSL_SP_NO_3072 + "3072\n", /* 2 */ +#elif !defined(WOLFSSL_SP_NO_2048) + "2048\n", /* 2 */ +#else + "0\n", /* 2 */ +#endif +#elif defined(USE_FAST_MATH) +#else + "INFINITE\n", /* 2 */ +#endif + "-? Help, print this usage\n" + " 0: English, 1: Japanese\n", /* 3 */ + "-h Host to connect to, default", /* 4 */ + "-p Port to connect on, not 0, default", /* 5 */ + +#ifndef WOLFSSL_TLS13 + "-v SSL version [0-3], SSLv3(0) - TLS1.2(3)), default", /* 6 */ + "-V Prints valid ssl version numbers" + ", SSLv3(0) - TLS1.2(3)\n", /* 7 */ +#else + "-v SSL version [0-4], SSLv3(0) - TLS1.3(4)), default", /* 6 */ + "-V Prints valid ssl version numbers," + " SSLv3(0) - TLS1.3(4)\n", /* 7 */ +#endif + "-l Cipher suite list (: delimited)\n", /* 8 */ + "-c Certificate file, default", /* 9 */ + "-k Key file, default", /* 10 */ + "-A Certificate Authority file, default", /* 11 */ #ifndef NO_DH - printf("-Z Minimum DH key bits, default %d\n", - DEFAULT_MIN_DHKEY_BITS); + "-Z Minimum DH key bits, default", /* 12 */ #endif - printf("-b Benchmark connections 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("-g Send server HTTP GET\n"); - printf("-u Use UDP DTLS," - " add -v 2 for DTLSv1 (default), -v 3 for DTLSv1.2\n"); - printf("-m Match domain name in cert\n"); - printf("-N Use Non-blocking sockets\n"); - printf("-r Resume session\n"); - printf("-w Wait for bidirectional shutdown\n"); + "-b Benchmark connections and print stats\n", /* 13 */ +#ifdef HAVE_ALPN + "-L Application-Layer Protocol" + " Negotiation ({C,F}:)\n", /* 14 */ +#endif + "-B Benchmark throughput" + " using bytes and print stats\n", /* 15 */ + "-s Use pre Shared keys\n", /* 16 */ + "-d Disable peer checks\n", /* 17 */ + "-D Override Date Errors example\n", /* 18 */ + "-e List Every cipher suite available, \n", /* 19 */ + "-g Send server HTTP GET\n", /* 20 */ + "-u Use UDP DTLS," + " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n", /* 21 */ +#ifdef WOLFSSL_SCTP + "-G Use SCTP DTLS," + " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n", /* 22 */ +#endif + "-m Match domain name in cert\n", /* 23 */ + "-N Use Non-blocking sockets\n", /* 24 */ +#ifndef NO_SESSION_CACHE + "-r Resume session\n", /* 25 */ +#endif + "-w Wait for bidirectional shutdown\n", /* 26 */ + "-M Use STARTTLS, using protocol (smtp)\n", /* 27 */ #ifdef HAVE_SECURE_RENEGOTIATION - printf("-R Allow Secure Renegotiation\n"); - printf("-i Force client Initiated Secure Renegotiation\n"); + "-R Allow Secure Renegotiation\n", /* 28 */ + "-i Force client Initiated Secure Renegotiation\n", /* 29 */ #endif - printf("-f Fewer packets/group messages\n"); - printf("-x Disable client cert/key loading\n"); - printf("-X Driven by eXternal test case\n"); + "-f Fewer packets/group messages\n", /* 30 */ + "-x Disable client cert/key loading\n", /* 31 */ + "-X Driven by eXternal test case\n", /* 32 */ + "-j Use verify callback override\n", /* 33 */ #ifdef SHOW_SIZES - printf("-z Print structure sizes\n"); + "-z Print structure sizes\n", /* 34 */ #endif #ifdef HAVE_SNI - printf("-S Use Host Name Indication\n"); + "-S Use Host Name Indication\n", /* 35 */ #endif #ifdef HAVE_MAX_FRAGMENT - printf("-L Use Maximum Fragment Length [1-5]\n"); + "-F Use Maximum Fragment Length [1-6]\n", /* 36 */ #endif #ifdef HAVE_TRUNCATED_HMAC - printf("-T Use Truncated HMAC\n"); + "-T Use Truncated HMAC\n", /* 37 */ +#endif +#ifdef HAVE_EXTENDED_MASTER + "-n Disable Extended Master Secret\n", /* 38 */ #endif #ifdef HAVE_OCSP - printf("-o Perform OCSP lookup on peer certificate\n"); - printf("-O Perform OCSP lookup using as responder\n"); + "-o Perform OCSP lookup on peer certificate\n", /* 39 */ + "-O Perform OCSP lookup using as responder\n", /* 40 */ #endif -#ifdef ATOMIC_USER - printf("-U Atomic User Record Layer Callbacks\n"); +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + "-W Use OCSP Stapling (1 v1, 2 v2, 3 v2 multi)\n", /* 41 */ #endif -#ifdef HAVE_PK_CALLBACKS - printf("-P Public Key Callbacks\n"); +#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY) + "-U Atomic User Record Layer Callbacks\n", /* 42 */ +#endif +#ifdef HAVE_PK_CALLBACKS + "-P Public Key Callbacks\n", /* 43 */ #endif #ifdef HAVE_ANON - printf("-a Anonymous client\n"); + "-a Anonymous client\n", /* 44 */ #endif #ifdef HAVE_CRL - printf("-C Disable CRL\n"); + "-C Disable CRL\n", /* 45 */ +#endif +#ifdef WOLFSSL_TRUST_PEER_CERT + "-E Path to load trusted peer cert\n", /* 46 */ +#endif +#ifdef HAVE_WNR + "-q Whitewood config file, defaults\n", /* 47 */ +#endif + "-H Internal tests" + " [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 48 */ + " loadSSL, disallowETM]\n", /* 49 */ +#ifdef WOLFSSL_TLS13 + "-J Use HelloRetryRequest to choose group for KE\n", /* 50 */ + "-K Key Exchange for PSK not using (EC)DHE\n", /* 51 */ + "-I Update keys and IVs before sending data\n", /* 52 */ +#ifndef NO_DH + "-y Key Share with FFDHE named groups only\n", /* 53 */ +#endif +#ifdef HAVE_ECC + "-Y Key Share with ECC named groups only\n", /* 54 */ +#endif +#endif /* WOLFSSL_TLS13 */ +#ifdef HAVE_CURVE25519 + "-t Use X25519 for key exchange\n", /* 55 */ +#endif +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + "-Q Support requesting certificate post-handshake\n", /* 56 */ +#endif +#ifdef WOLFSSL_EARLY_DATA + "-0 Early data sent to server (0-RTT handshake)\n", /* 57 */ +#endif +#ifdef WOLFSSL_MULTICAST + "-3 Multicast, grpid < 256\n", /* 58 */ +#endif + "-1 Display a result by specified language.\n" + " 0: English, 1: Japanese\n", /* 59 */ +#if !defined(NO_DH) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK) + "-2 Disable DH Prime check\n", /* 60 */ +#endif +#ifdef HAVE_SECURE_RENEGOTIATION + "-4 Use resumption for renegotiation\n", /* 61 */ +#endif +#ifdef HAVE_TRUSTED_CA + "-5 Use Trusted CA Key Indication\n", /* 62 */ +#endif +#ifdef HAVE_CURVE448 + "-8 Use X448 for key exchange\n", /* 65 */ +#endif + NULL, + }, +#ifndef NO_MULTIBYTE_PRINT + /* Japanese */ + { + " 注意 : 全てのファイルは wolfSSL ホーム・ディレクトリからの相対です。" + "\n", /* 0 */ + "RSAの最大ビットは次のように設定されています: ", /* 1 */ +#ifdef NO_RSA + "RSAはサポートされていません。\n", /* 2 */ +#elif defined(WOLFSSL_SP_MATH) /* case of SP math only */ +#ifndef WOLFSSL_SP_NO_3072 + "3072\n", /* 2 */ +#elif !defined(WOLFSSL_SP_NO_2048) + "2048\n", /* 2 */ +#else + "0\n", /* 2 */ +#endif +#elif defined(USE_FAST_MATH) +#else + "無限\n", /* 2 */ +#endif + "-? ヘルプ, 使い方を表示\n" + " 0: 英語、 1: 日本語\n", /* 3 */ + "-h 接続先ホスト, 既定値", /* 4 */ + "-p 接続先ポート, 0は無効, 既定値", /* 5 */ + +#ifndef WOLFSSL_TLS13 + "-v SSL バージョン [0-3], SSLv3(0) - TLS1.2(3))," + " 既定値", /* 6 */ + "-V 有効な ssl バージョン番号を出力, SSLv3(0) -" + " TLS1.2(3)\n", /* 7 */ +#else + "-v SSL バージョン [0-4], SSLv3(0) - TLS1.3(4))," + " 既定値", /* 6 */ + "-V 有効な ssl バージョン番号を出力, SSLv3(0) -" + " TLS1.3(4)\n", /* 7 */ +#endif + "-l 暗号スイートリスト (区切り文字 :)\n", /* 8 */ + "-c 証明書ファイル, 既定値", /* 9 */ + "-k 鍵ファイル, 既定値", /* 10 */ + "-A 認証局ファイル, 既定値", /* 11 */ +#ifndef NO_DH + "-Z 最小 DH 鍵 ビット, 既定値", /* 12 */ +#endif + "-b ベンチマーク 接続及び結果出力する\n", /* 13 */ +#ifdef HAVE_ALPN + "-L アプリケーション層プロトコルネゴシエーションを行う" + " ({C,F}:)\n", /* 14 */ +#endif + "-B バイトを用いてのベンチマーク・スループット測定" + "と結果を出力する\n", /* 15 */ + "-s 事前共有鍵を使用する\n", /* 16 */ + "-d ピア確認を無効とする\n", /* 17 */ + "-D 日付エラー用コールバック例の上書きを行う\n", /* 18 */ + "-e 利用可能な全ての暗号スイートをリスト, \n", /* 19 */ + "-g サーバーへ HTTP GET を送信\n", /* 20 */ + "-u UDP DTLSを使用する。-v 2 を追加指定すると" + " DTLSv1, -v 3 を追加指定すると DTLSv1.2 (既定値)\n", /* 21 */ +#ifdef WOLFSSL_SCTP + "-G SCTP DTLSを使用する。-v 2 を追加指定すると" + " DTLSv1, -v 3 を追加指定すると DTLSv1.2 (既定値)\n", /* 22 */ +#endif + "-m 証明書内のドメイン名一致を確認する\n", /* 23 */ + "-N ノンブロッキング・ソケットを使用する\n", /* 24 */ +#ifndef NO_SESSION_CACHE + "-r セッションを継続する\n", /* 25 */ +#endif + "-w 双方向シャットダウンを待つ\n", /* 26 */ + "-M STARTTLSを使用する, プロトコル(smtp)を" + "使用する\n", /* 27 */ +#ifdef HAVE_SECURE_RENEGOTIATION + "-R セキュアな再ネゴシエーションを許可する\n", /* 28 */ + "-i クライアント主導のネゴシエーションを強制する\n", /* 29 */ +#endif + "-f より少ないパケット/グループメッセージを使用する\n",/* 30 */ + "-x クライアントの証明書/鍵のロードを無効する\n", /* 31 */ + "-X 外部テスト・ケースにより動作する\n", /* 32 */ + "-j コールバック・オーバーライドの検証を使用する\n", /* 33 */ +#ifdef SHOW_SIZES + "-z 構造体のサイズを表示する\n", /* 34 */ +#endif +#ifdef HAVE_SNI + "-S ホスト名表示を使用する\n", /* 35 */ +#endif +#ifdef HAVE_MAX_FRAGMENT + "-F 最大フラグメント長[1-6]を設定する\n", /* 36 */ +#endif +#ifdef HAVE_TRUNCATED_HMAC + "-T Truncated HMACを使用する\n", /* 37 */ +#endif +#ifdef HAVE_EXTENDED_MASTER + "-n マスターシークレット拡張を無効にする\n", /* 38 */ +#endif +#ifdef HAVE_OCSP + "-o OCSPルックアップをピア証明書で実施する\n", /* 39 */ + "-O OCSPルックアップを、を使用し" + "応答者として実施する\n", /* 40 */ +#endif +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + "-W OCSP Staplingを使用する" + " (1 v1, 2 v2, 3 v2 multi)\n", /* 41 */ +#endif +#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY) + "-U アトミック・ユーザー記録の" + "コールバックを利用する\n", /* 42 */ +#endif +#ifdef HAVE_PK_CALLBACKS + "-P 公開鍵コールバック\n", /* 43 */ +#endif +#ifdef HAVE_ANON + "-a 匿名クライアント\n", /* 44 */ +#endif +#ifdef HAVE_CRL + "-C CRLを無効\n", /* 45 */ +#endif +#ifdef WOLFSSL_TRUST_PEER_CERT + "-E 信頼出来るピアの証明書ロードの為のパス\n", /* 46 */ +#endif +#ifdef HAVE_WNR + "-q Whitewood コンフィグファイル, 既定値\n", /* 47 */ +#endif + "-H 内部テスト" + " [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 48 */ + " loadSSL, disallowETM]\n", /* 49 */ +#ifdef WOLFSSL_TLS13 + "-J HelloRetryRequestをKEのグループ選択に使用する\n", /* 50 */ + "-K 鍵交換にPSKを使用、(EC)DHEは使用しない\n", /* 51 */ + "-I データ送信前に、鍵とIVを更新する\n", /* 52 */ +#ifndef NO_DH + "-y FFDHE名前付きグループとの鍵共有のみ\n", /* 53 */ +#endif +#ifdef HAVE_ECC + "-Y ECC名前付きグループとの鍵共有のみ\n", /* 54 */ +#endif +#endif /* WOLFSSL_TLS13 */ +#ifdef HAVE_CURVE25519 + "-t X25519を鍵交換に使用する\n", /* 55 */ +#endif +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + "-Q ポストハンドシェークの証明要求をサポートする\n", /* 56 */ +#endif +#ifdef WOLFSSL_EARLY_DATA + "-0 Early data をサーバーへ送信する" + "(0-RTTハンドシェイク)\n", /* 57 */ +#endif +#ifdef WOLFSSL_MULTICAST + "-3 マルチキャスト, grpid < 256\n", /* 58 */ +#endif + "-1 指定された言語で結果を表示します。\n" + " 0: 英語、 1: 日本語\n", /* 59 */ +#if !defined(NO_DH) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK) + "-2 DHプライム番号チェックを無効にする\n", /* 60 */ +#endif +#ifdef HAVE_SECURE_RENEGOTIATION + "-4 再交渉に再開を使用\n", /* 61 */ +#endif +#ifdef HAVE_TRUSTED_CA + "-5 信頼できる認証局の鍵表示を使用する\n", /* 62 */ +#endif +#ifdef HAVE_CURVE448 + "-8 Use X448 for key exchange\n", /* 65 */ +#endif + NULL, + }, +#endif + +}; + +static void Usage(void) +{ + int msgid = 0; + const char** msg = client_usage_msg[lng_index]; + + printf("%s%s%s", "wolfSSL client ", LIBWOLFSSL_VERSION_STRING, + msg[msgid]); + + /* print out so that scripts can know what the max supported key size is */ + printf("%s", msg[++msgid]); +#ifdef NO_RSA + printf("%s", msg[++msgid]); +#elif defined(WOLFSSL_SP_MATH) /* case of SP math only */ + #ifndef WOLFSSL_SP_NO_3072 + printf("%s", msg[++msgid]); + #elif !defined(WOLFSSL_SP_NO_2048) + printf("%s", msg[++msgid]); + #else + printf("%s", msg[++msgid]); + #endif +#elif defined(USE_FAST_MATH) + printf("%d\n", FP_MAX_BITS/2); +#else + /* normal math has unlimited max size */ + printf("%s", msg[++msgid]); +#endif + + printf("%s", msg[++msgid]); /* ? */ + printf("%s %s\n", msg[++msgid], wolfSSLIP); /* -h */ + printf("%s %d\n", msg[++msgid], wolfSSLPort); /* -p */ +#ifndef WOLFSSL_TLS13 + printf("%s %d\n", msg[++msgid], CLIENT_DEFAULT_VERSION); /* -v */ + printf("%s", msg[++msgid]); /* -V */ +#else + printf("%s %d\n", msg[++msgid], CLIENT_DEFAULT_VERSION); /* -v */ + printf("%s", msg[++msgid]); /* -V */ +#endif + printf("%s", msg[++msgid]); /* -l */ + printf("%s %s\n", msg[++msgid], cliCertFile); /* -c */ + printf("%s %s\n", msg[++msgid], cliKeyFile); /* -k */ + printf("%s %s\n", msg[++msgid], caCertFile); /* -A */ +#ifndef NO_DH + printf("%s %d\n", msg[++msgid], DEFAULT_MIN_DHKEY_BITS); +#endif + printf("%s", msg[++msgid]); /* -b */ +#ifdef HAVE_ALPN + printf("%s", msg[++msgid]); /* -L */ +#endif + printf("%s", msg[++msgid]); /* -B */ + printf("%s", msg[++msgid]); /* -s */ + printf("%s", msg[++msgid]); /* -d */ + printf("%s", msg[++msgid]); /* -D */ + printf("%s", msg[++msgid]); /* -e */ + printf("%s", msg[++msgid]); /* -g */ + printf("%s", msg[++msgid]); /* -u */ +#ifdef WOLFSSL_SCTP + printf("%s", msg[++msgid]); /* -G */ +#endif + printf("%s", msg[++msgid]); /* -m */ + printf("%s", msg[++msgid]); /* -N */ +#ifndef NO_SESSION_CACHE + printf("%s", msg[++msgid]); /* -r */ +#endif + printf("%s", msg[++msgid]); /* -w */ + printf("%s", msg[++msgid]); /* -M */ +#ifdef HAVE_SECURE_RENEGOTIATION + printf("%s", msg[++msgid]); /* -R */ + printf("%s", msg[++msgid]); /* -i */ +#endif + printf("%s", msg[++msgid]); /* -f */ + printf("%s", msg[++msgid]); /* -x */ + printf("%s", msg[++msgid]); /* -X */ + printf("%s", msg[++msgid]); /* -j */ +#ifdef SHOW_SIZES + printf("%s", msg[++msgid]); /* -z */ +#endif +#ifdef HAVE_SNI + printf("%s", msg[++msgid]); /* -S */ +#endif +#ifdef HAVE_MAX_FRAGMENT + printf("%s", msg[++msgid]); /* -F */ +#endif +#ifdef HAVE_TRUNCATED_HMAC + printf("%s", msg[++msgid]); /* -T */ +#endif +#ifdef HAVE_EXTENDED_MASTER + printf("%s", msg[++msgid]); /* -n */ +#endif +#ifdef HAVE_OCSP + printf("%s", msg[++msgid]); /* -o */ + printf("%s", msg[++msgid]); /* -O */ +#endif +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + printf("%s", msg[++msgid]); /* -W */ +#endif +#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY) + printf("%s", msg[++msgid]); /* -U */ +#endif +#ifdef HAVE_PK_CALLBACKS + printf("%s", msg[++msgid]); /* -P */ +#endif +#ifdef HAVE_ANON + printf("%s", msg[++msgid]); /* -a */ +#endif +#ifdef HAVE_CRL + printf("%s", msg[++msgid]); /* -C */ +#endif +#ifdef WOLFSSL_TRUST_PEER_CERT + printf("%s", msg[++msgid]); /* -E */ +#endif +#ifdef HAVE_WNR + printf("%s %s\n", msg[++msgid], wnrConfig); /* -q */ +#endif + printf("%s", msg[++msgid]); /* -H */ + printf("%s", msg[++msgid]); /* more -H options */ +#ifdef WOLFSSL_TLS13 + printf("%s", msg[++msgid]); /* -J */ + printf("%s", msg[++msgid]); /* -K */ + printf("%s", msg[++msgid]); /* -I */ +#ifndef NO_DH + printf("%s", msg[++msgid]); /* -y */ +#endif +#ifdef HAVE_ECC + printf("%s", msg[++msgid]); /* -Y */ +#endif +#endif /* WOLFSSL_TLS13 */ +#ifdef HAVE_CURVE25519 + printf("%s", msg[++msgid]); /* -t */ +#endif +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + printf("%s", msg[++msgid]); /* -Q */ +#endif +#ifdef WOLFSSL_EARLY_DATA + printf("%s", msg[++msgid]); /* -0 */ +#endif +#ifdef WOLFSSL_MULTICAST + printf("%s", msg[++msgid]); /* -3 */ +#endif + printf("%s", msg[++msgid]); /* -1 */ +#if !defined(NO_DH) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK) + printf("%s", msg[++msgid]); /* -2 */ +#endif +#ifdef HAVE_SECURE_RENEGOTIATION + printf("%s", msg[++msgid]); /* -4 */ +#endif +#ifdef HAVE_TRUSTED_CA + printf("%s", msg[++msgid]); /* -5 */ +#endif +#ifdef HAVE_CURVE448 + printf("%s", msg[++msgid]); /* -8 */ #endif } THREAD_RETURN WOLFSSL_THREAD client_test(void* args) { - SOCKET_T sockfd = 0; + SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; - WOLFSSL_METHOD* method = 0; + wolfSSL_method_func method = NULL; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; - + WOLFSSL* sslResume = 0; WOLFSSL_SESSION* session = 0; - char resumeMsg[] = "resuming wolfssl!"; - int resumeSz = sizeof(resumeMsg); + byte* flatSession = NULL; + int flatSessionSz = 0; +#ifndef WOLFSSL_ALT_TEST_STRINGS char msg[32] = "hello wolfssl!"; /* GET may make bigger */ - char reply[80]; - int input; - int msgSz = (int)strlen(msg); + char resumeMsg[32] = "resuming wolfssl!"; +#else + char msg[32] = "hello wolfssl!\n"; + char resumeMsg[32] = "resuming wolfssl!\n"; +#endif + + char reply[128]; + int msgSz = (int)XSTRLEN(msg); + int resumeSz = (int)XSTRLEN(resumeMsg); word16 port = wolfSSLPort; char* host = (char*)wolfSSLIP; - const char* domain = "www.wolfssl.com"; - + const char* domain = "localhost"; /* can't default to www.wolfssl.com + because can't tell if we're really + going there to detect old chacha-poly + */ +#ifndef WOLFSSL_VXWORKS int ch; +#endif int version = CLIENT_INVALID_VERSION; int usePsk = 0; int useAnon = 0; int sendGET = 0; int benchmark = 0; + int block = TEST_BUFFER_SIZE; + size_t throughput = 0; int doDTLS = 0; + int dtlsUDP = 0; + int dtlsSCTP = 0; + int doMcast = 0; int matchName = 0; int doPeerCheck = 1; int nonBlocking = 0; @@ -220,54 +1417,148 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) int disableCRL = 0; int externalTest = 0; int ret; + int err = 0; int scr = 0; /* allow secure renegotiation */ int forceScr = 0; /* force client initiaed scr */ - int trackMemory = 0; + int resumeScr = 0; /* use resumption for renegotiation */ +#ifndef WOLFSSL_NO_CLIENT_AUTH int useClientCert = 1; +#else + int useClientCert = 0; +#endif int fewerPackets = 0; int atomicUser = 0; +#ifdef HAVE_PK_CALLBACKS int pkCallbacks = 0; + PkCbInfo pkCbInfo; +#endif int overrideDateErrors = 0; int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS; + 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; + const char* verifyCert; + const char* ourCert; + const char* ourKey; + + int doSTARTTLS = 0; + char* starttlsProt = NULL; + int useVerifyCb = 0; + int useSupCurve = 0; + +#ifdef WOLFSSL_TRUST_PEER_CERT + const char* trustCert = NULL; +#endif #ifdef HAVE_SNI char* sniHostName = NULL; #endif +#ifdef HAVE_TRUSTED_CA + int trustedCaKeyId = 0; +#endif #ifdef HAVE_MAX_FRAGMENT byte maxFragment = 0; #endif #ifdef HAVE_TRUNCATED_HMAC - byte truncatedHMAC = 0; + byte truncatedHMAC = 0; +#endif +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + byte statusRequest = 0; +#endif +#ifdef HAVE_EXTENDED_MASTER + byte disableExtMasterSecret = 0; +#endif + int helloRetry = 0; + int onlyKeyShare = 0; +#ifdef WOLFSSL_TLS13 + int noPskDheKe = 0; + int postHandAuth = 0; +#endif + int updateKeysIVs = 0; + int earlyData = 0; +#ifdef WOLFSSL_MULTICAST + byte mcastID = 0; +#endif +#if !defined(NO_DH) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK) + int doDhKeyCheck = 1; #endif - #ifdef HAVE_OCSP int useOcsp = 0; char* ocspUrl = NULL; #endif + int useX25519 = 0; + int useX448 = 0; + int exitWithRet = 0; + int loadCertKeyIntoSSLObj = 0; + +#ifdef HAVE_ENCRYPT_THEN_MAC + int disallowETM = 0; +#endif + +#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 + WOLFSSL_HEAP_HINT *heap = NULL; +#endif + ((func_args*)args)->return_code = -1; /* error state */ -#ifdef NO_RSA - verifyCert = (char*)eccCert; - ourCert = (char*)cliEccCert; - ourKey = (char*)cliEccKey; +#ifndef NO_RSA + verifyCert = caCertFile; + ourCert = cliCertFile; + ourKey = cliKeyFile; +#else + #ifdef HAVE_ECC + verifyCert = caEccCertFile; + ourCert = cliEccCertFile; + ourKey = cliEccKeyFile; + #elif defined(HAVE_ED25519) + verifyCert = caEdCertFile; + ourCert = cliEdCertFile; + ourKey = cliEdKeyFile; + #elif defined(HAVE_ED448) + verifyCert = caEd448CertFile; + ourCert = cliEd448CertFile; + ourKey = cliEd448KeyFile; + #else + verifyCert = NULL; + ourCert = NULL; + ourKey = NULL; + #endif #endif + (void)resumeSz; (void)session; + (void)flatSession; + (void)flatSessionSz; (void)sslResume; - (void)trackMemory; (void)atomicUser; - (void)pkCallbacks; (void)scr; (void)forceScr; + (void)resumeScr; (void)ourKey; (void)ourCert; (void)verifyCert; @@ -275,16 +1566,35 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void)overrideDateErrors; (void)disableCRL; (void)minDhKeyBits; + (void)alpnList; + (void)alpn_opt; + (void)updateKeysIVs; + (void)earlyData; + (void)useX25519; + (void)useX448; + (void)helloRetry; + (void)onlyKeyShare; + (void)useSupCurve; + (void)loadCertKeyIntoSSLObj; StackTrap(); - while ((ch = mygetopt(argc, argv, - "?gdDusmNrwRitfxXUPCh:p:v:l:A:c:k:Z:b:zS:L:ToO:a")) - != -1) { +#ifndef WOLFSSL_VXWORKS + /* 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:" + "01:23:458")) != -1) { switch (ch) { case '?' : + if(myoptarg!=NULL) { + lng_index = atoi(myoptarg); + if(lng_index<0||lng_index>1){ + lng_index = 0; + } + } Usage(); - exit(EXIT_SUCCESS); + XEXIT_T(EXIT_SUCCESS); case 'g' : sendGET = 1; @@ -294,6 +1604,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) doPeerCheck = 0; break; + case 'e' : + ShowCiphers(); + XEXIT_T(EXIT_SUCCESS); + case 'D' : overrideDateErrors = 1; break; @@ -305,18 +1619,26 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) break; case 'u' : - doDTLS = 1; + doDTLS = 1; + dtlsUDP = 1; + break; + + case 'G' : + #ifdef WOLFSSL_SCTP + doDTLS = 1; + dtlsSCTP = 1; + #endif break; case 's' : usePsk = 1; break; - case 't' : - #ifdef USE_WOLFSSL_MEMORY - trackMemory = 1; - #endif + #ifdef WOLFSSL_TRUST_PEER_CERT + case 'E' : + trustCert = myoptarg; break; + #endif case 'm' : matchName = 1; @@ -335,13 +1657,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) break; case 'U' : - #ifdef ATOMIC_USER + #if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY) atomicUser = 1; #endif break; case 'P' : - #ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_PK_CALLBACKS pkCallbacks = 1; #endif break; @@ -360,17 +1682,75 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) break; case 'v' : + if (myoptarg[0] == 'd') { + version = CLIENT_DOWNGRADE_VERSION; + break; + } + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + else if (myoptarg[0] == 'e') { + version = EITHER_DOWNGRADE_VERSION; + #ifndef NO_CERTS + loadCertKeyIntoSSLObj = 1; + #endif + break; + } + #endif version = atoi(myoptarg); - if (version < 0 || version > 3) { + if (version < 0 || version > 4) { Usage(); - exit(MY_EX_USAGE); + XEXIT_T(MY_EX_USAGE); } break; + case 'V' : + ShowVersions(); + XEXIT_T(EXIT_SUCCESS); + case 'l' : 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, "exitWithRet", 11) == 0) { + printf("Skip exit() for testing\n"); + exitWithRet = 1; + } + else if (XSTRNCMP(myoptarg, "verifyFail", 10) == 0) { + printf("Verify should fail\n"); + myVerifyFail = 1; + } + else if (XSTRNCMP(myoptarg, "useSupCurve", 11) == 0) { + printf("Attempting to test use supported curve\n"); + #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + useSupCurve = 1; + #else + printf("Supported curves not compiled in!\n"); + #endif + } + else if (XSTRNCMP(myoptarg, "loadSSL", 7) == 0) { + printf("Load cert/key into wolfSSL object\n"); + #ifndef NO_CERTS + loadCertKeyIntoSSLObj = 1; + #else + printf("Certs turned off with NO_CERTS!\n"); + #endif + } + else if (XSTRNCMP(myoptarg, "disallowETM", 7) == 0) { + printf("Disallow Enrypt-Then-MAC\n"); + #ifdef HAVE_ENCRYPT_THEN_MAC + disallowETM = 1; + #endif + } + else { + Usage(); + XEXIT_T(MY_EX_USAGE); + } + break; + case 'A' : verifyCert = myoptarg; break; @@ -388,7 +1768,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) minDhKeyBits = atoi(myoptarg); if (minDhKeyBits <= 0 || minDhKeyBits > 16000) { Usage(); - exit(MY_EX_USAGE); + XEXIT_T(MY_EX_USAGE); } #endif break; @@ -397,7 +1777,21 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) benchmark = atoi(myoptarg); if (benchmark < 0 || benchmark > 1000000) { Usage(); - exit(MY_EX_USAGE); + XEXIT_T(MY_EX_USAGE); + } + break; + + case 'B' : + throughput = atol(myoptarg); + for (; *myoptarg != '\0'; myoptarg++) { + if (*myoptarg == ',') { + block = atoi(myoptarg + 1); + break; + } + } + if (throughput == 0 || block <= 0) { + Usage(); + XEXIT_T(MY_EX_USAGE); } break; @@ -433,18 +1827,26 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) break; case 'S' : + if (XSTRNCMP(myoptarg, "check", 5) == 0) { + #ifdef HAVE_SNI + printf("SNI is: ON\n"); + #else + printf("SNI is: OFF\n"); + #endif + XEXIT_T(EXIT_SUCCESS); + } #ifdef HAVE_SNI sniHostName = myoptarg; #endif break; - case 'L' : + case 'F' : #ifdef HAVE_MAX_FRAGMENT maxFragment = atoi(myoptarg); - if (maxFragment < WOLFSSL_MFL_2_9 || - maxFragment > WOLFSSL_MFL_2_13) { + if (maxFragment < WOLFSSL_MFL_MIN || + maxFragment > WOLFSSL_MFL_MAX) { Usage(); - exit(MY_EX_USAGE); + XEXIT_T(MY_EX_USAGE); } #endif break; @@ -455,6 +1857,23 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif break; + case 'n' : + #ifdef HAVE_EXTENDED_MASTER + disableExtMasterSecret = 1; + #endif + break; + + case 'W' : + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + statusRequest = atoi(myoptarg); + if (statusRequest > OCSP_STAPLING_OPT_MAX) { + Usage(); + XEXIT_T(MY_EX_USAGE); + } + #endif + break; + case 'o' : #ifdef HAVE_OCSP useOcsp = 1; @@ -474,36 +1893,240 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif break; + case 'L' : + #ifdef HAVE_ALPN + alpnList = myoptarg; + + if (alpnList[0] == 'C' && alpnList[1] == ':') + alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH; + else if (alpnList[0] == 'F' && alpnList[1] == ':') + alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH; + else { + Usage(); + XEXIT_T(MY_EX_USAGE); + } + + alpnList += 2; + + #endif + break; + + case 'M' : + doSTARTTLS = 1; + starttlsProt = myoptarg; + + if (XSTRNCMP(starttlsProt, "smtp", 4) != 0) { + Usage(); + XEXIT_T(MY_EX_USAGE); + } + + break; + + case 'q' : + #ifdef HAVE_WNR + wnrConfigFile = myoptarg; + #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; + #ifdef HAVE_ECC + useSupCurve = 1; + #ifdef WOLFSSL_TLS13 + onlyKeyShare = 2; + #endif + #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 '1' : + lng_index = atoi(myoptarg); + if(lng_index<0||lng_index>1){ + lng_index = 0; + } + break; + + case '2' : + #if !defined(NO_DH) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK) + doDhKeyCheck = 0; + #endif + break; + + case '3' : + #ifdef WOLFSSL_MULTICAST + doMcast = 1; + mcastID = (byte)(atoi(myoptarg) & 0xFF); + #endif + break; + + case '4' : + #ifdef HAVE_SECURE_RENEGOTIATION + scr = 1; + forceScr = 1; + resumeScr = 1; + #endif + break; + + case '5' : + #ifdef HAVE_TRUSTED_CA + trustedCaKeyId = 1; + #endif /* HAVE_TRUSTED_CA */ + break; + + case '8' : + #ifdef HAVE_CURVE448 + useX448 = 1; + #ifdef HAVE_ECC + useSupCurve = 1; + #ifdef WOLFSSL_TLS13 + onlyKeyShare = 2; + #endif + #endif + #endif + break; + default: Usage(); - exit(MY_EX_USAGE); + XEXIT_T(MY_EX_USAGE); } } myoptind = 0; /* reset for test cases */ +#endif /* !WOLFSSL_VXWORKS */ if (externalTest) { /* detect build cases that wouldn't allow test against wolfssl.com */ int done = 0; - (void)done; #ifdef NO_RSA - done = 1; + done += 1; /* require RSA for external tests */ #endif + if (!XSTRNCMP(domain, "www.globalsign.com", 14)) { + /* www.globalsign.com does not respond to ipv6 ocsp requests */ + #if defined(TEST_IPV6) && defined(HAVE_OCSP) + done += 1; + #endif + + /* www.globalsign.com has limited supported cipher suites */ + #if defined(NO_AES) && defined(HAVE_OCSP) + done += 1; + #endif + + /* www.globalsign.com only supports static RSA or ECDHE with AES */ + /* We cannot expect users to have on static RSA so test for ECC only + * as some users will most likely be on 32-bit systems where ECC + * is not enabled by default */ + #if defined(HAVE_OCSP) && !defined(HAVE_ECC) + done += 1; + #endif + } + #ifndef NO_PSK - done = 1; + if (usePsk) { + done += 1; /* don't perform exernal tests if PSK is enabled */ + } #endif #ifdef NO_SHA - done = 1; /* external cert chain most likely has SHA */ + done += 1; /* external cert chain most likely has SHA */ + #endif + + #if !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) \ + || ( defined(HAVE_ECC) && !defined(HAVE_SUPPORTED_CURVES) \ + && !defined(WOLFSSL_STATIC_RSA) ) + /* google needs ECDHE+Supported Curves or static RSA */ + if (!XSTRNCMP(domain, "www.google.com", 14)) + done += 1; + #endif + + #if !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) + /* wolfssl needs ECDHE or static RSA */ + if (!XSTRNCMP(domain, "www.wolfssl.com", 15)) + done += 1; + #endif + + #if !defined(WOLFSSL_SHA384) + if (!XSTRNCMP(domain, "www.wolfssl.com", 15)) { + /* wolfssl need sha384 for cert chain verify */ + done += 1; + } + #endif + + #if !defined(HAVE_AESGCM) && defined(NO_AES) && \ + !(defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) + /* need at least one of these for external tests */ + done += 1; + #endif + + #if defined(HAVE_QSH) + /*currently google server rejects client hello with QSH extension.*/ + done += 1; + #endif + + /* For the external test, if we disable AES, GoDaddy will reject the + * connection. They only currently support AES suites, RC4 and 3DES + * suites. With AES disabled we only offer PolyChacha suites. */ + #if defined(NO_AES) && !defined(HAVE_AESGCM) + if (!XSTRNCMP(domain, "www.wolfssl.com", 15)) { + done += 1; + } #endif if (done) { - printf("external test can't be run in this mode"); + printf("external test can't be run in this mode\n"); ((func_args*)args)->return_code = 0; - exit(EXIT_SUCCESS); + XEXIT_T(EXIT_SUCCESS); } } @@ -518,51 +2141,81 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (doDTLS) { if (version == 3) version = -2; + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + else if (version == EITHER_DOWNGRADE_VERSION) + version = -3; + #endif else version = -1; } } -#ifdef USE_WOLFSSL_MEMORY - if (trackMemory) - InitMemoryTracker(); +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) + err_sys("can't load whitewood net random config file"); #endif switch (version) { #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 + #ifndef WOLFSSL_NO_TLS12 case 3: - method = wolfTLSv1_2_client_method(); + method = wolfTLSv1_2_client_method_ex; break; -#endif + #endif + + #ifdef WOLFSSL_TLS13 + case 4: + method = wolfTLSv1_3_client_method_ex; + break; + #endif + + case CLIENT_DOWNGRADE_VERSION: + method = wolfSSLv23_client_method_ex; + break; + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + case EITHER_DOWNGRADE_VERSION: + method = wolfSSLv23_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 + #ifndef WOLFSSL_NO_TLS12 case -2: - method = wolfDTLSv1_2_client_method(); + method = wolfDTLSv1_2_client_method_ex; break; + #endif + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + case -3: + method = wolfDTLSv1_2_method_ex; + break; + #endif #endif default: @@ -573,68 +2226,141 @@ 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 in case 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 (wc_LoadStaticMemory(&heap, memory, sizeof(memory), WOLFMEM_GENERAL, 1) + != 0) { + err_sys("unable to load static memory"); + } + + ctx = wolfSSL_CTX_new_ex(method(heap), heap); if (ctx == NULL) err_sys("unable to get ctx"); - if (cipherList) - if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) - err_sys("client can't set cipher list 1"); - -#ifdef WOLFSSL_LEANPSK - usePsk = 1; + 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)); + if (ctx == NULL) + err_sys("unable to get ctx"); #endif -#if defined(NO_RSA) && !defined(HAVE_ECC) - usePsk = 1; +#ifdef SINGLE_THREADED + if (wolfSSL_CTX_new_rng(ctx) != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("Single Threaded new rng at CTX failed"); + } +#endif + + if (cipherList && !useDefCipherList) { + if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("client can't set cipher list 1"); + } + } + +#ifdef WOLFSSL_LEANPSK + if (!usePsk) { + usePsk = 1; + } +#endif + +#if defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ + !defined(HAVE_ED448) + if (!usePsk) { + usePsk = 1; + } #endif if (fewerPackets) wolfSSL_CTX_set_group_messages(ctx); #ifndef NO_DH - wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits); + if (wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits) + != WOLFSSL_SUCCESS) { + err_sys("Error setting minimum DH key size"); + } #endif if (usePsk) { #ifndef NO_PSK wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb); + #ifdef WOLFSSL_TLS13 + wolfSSL_CTX_set_psk_client_tls13_callback(ctx, my_psk_client_tls13_cb); + #endif 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); ctx = NULL; err_sys("client can't set cipher list 2"); + } } #endif - useClientCert = 0; + if (useClientCert) { + useClientCert = 0; + } } if (useAnon) { #ifdef HAVE_ANON - if (cipherList == NULL) { + if (cipherList == NULL || (cipherList && useDefCipherList)) { + const char* defaultCipherList; wolfSSL_CTX_allow_anon_cipher(ctx); - if (wolfSSL_CTX_set_cipher_list(ctx,"ADH-AES128-SHA") != SSL_SUCCESS) + defaultCipherList = "ADH-AES256-GCM-SHA384:" + "ADH-AES128-SHA"; + if (wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList) + != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("client can't set cipher list 4"); + } } #endif - useClientCert = 0; + if (useClientCert) { + useClientCert = 0; + } } -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +#ifdef WOLFSSL_SCTP + if (dtlsSCTP) + wolfSSL_CTX_dtls_set_sctp(ctx); +#endif + +#ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif #if defined(WOLFSSL_SNIFFER) if (cipherList == NULL) { /* don't use EDH, can't sniff tmp keys */ - if (wolfSSL_CTX_set_cipher_list(ctx, "AES256-SHA256") != SSL_SUCCESS) { + if (wolfSSL_CTX_set_cipher_list(ctx, "AES128-SHA") != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("client can't set cipher list 3"); } } @@ -642,13 +2368,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, WOLFSSL_OCSP_NO_NONCE); + else { + wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_CHECKALL); + } + + #ifdef WOLFSSL_NONBLOCK_OCSP + wolfSSL_CTX_SetOCSP_Cb(ctx, OCSPIOCb, OCSPRespFreeCb, NULL); + #endif } #endif @@ -656,195 +2391,676 @@ 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); +#ifdef HAVE_EXT_CACHE + wolfSSL_CTX_sess_set_get_cb(ctx, mySessGetCb); + wolfSSL_CTX_sess_set_new_cb(ctx, mySessNewCb); + wolfSSL_CTX_sess_set_remove_cb(ctx, mySessRemCb); #endif -#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) - if (useClientCert){ - if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) != SSL_SUCCESS) + +#ifndef NO_CERTS + if (useClientCert && !loadCertKeyIntoSSLObj){ + #ifndef TEST_LOAD_BUFFER + if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) + != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("can't load client cert file, check file and run from" " wolfSSL home dir"); + } + #else + load_buffer(ctx, ourCert, WOLFSSL_CERT_CHAIN); + #endif + } - if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) - != SSL_SUCCESS) + #ifdef HAVE_PK_CALLBACKS + pkCbInfo.ourKey = ourKey; + #endif + if (useClientCert && !loadCertKeyIntoSSLObj + #if defined(HAVE_PK_CALLBACKS) && defined(TEST_PK_PRIVKEY) + && !pkCallbacks + #endif + ) { + #ifndef TEST_LOAD_BUFFER + if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("can't load client private key file, check file and run " "from wolfSSL home dir"); + } + #else + load_buffer(ctx, ourKey, WOLFSSL_KEY); + #endif } - if (!usePsk && !useAnon) { - if (wolfSSL_CTX_load_verify_locations(ctx, verifyCert,0) != SSL_SUCCESS) + if (!usePsk && !useAnon && !useVerifyCb && !myVerifyFail) { + #ifndef TEST_LOAD_BUFFER + unsigned int verify_flags = 0; + #ifdef TEST_BEFORE_DATE + verify_flags |= WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY; + #endif + if (wolfSSL_CTX_load_verify_locations_ex(ctx, verifyCert, 0, verify_flags) + != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("can't load ca file, Please run from wolfSSL home dir"); -#ifdef HAVE_ECC - /* load ecc verify too, echoserver uses it by default w/ ecc */ - if (wolfSSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS) - err_sys("can't load ecc ca file, Please run from wolfSSL home dir"); -#endif /* HAVE_ECC */ - } -#endif /* !NO_FILESYSTEM && !NO_CERTS */ -#if !defined(NO_CERTS) - 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); -#endif + } + #else + load_buffer(ctx, verifyCert, WOLFSSL_CA); + #endif /* !NO_FILESYSTEM */ -#ifdef HAVE_CAVIUM - wolfSSL_CTX_UseCavium(ctx, CAVIUM_DEV_ID); -#endif + #ifdef HAVE_ECC + /* load ecc verify too, echoserver uses it by default w/ ecc */ + #ifndef TEST_LOAD_BUFFER + if (wolfSSL_CTX_load_verify_locations_ex(ctx, eccCertFile, 0, verify_flags) + != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't load ecc ca file, Please run from wolfSSL home dir"); + } + #else + load_buffer(ctx, eccCertFile, WOLFSSL_CA); + #endif /* !TEST_LOAD_BUFFER */ + #endif /* HAVE_ECC */ + #if defined(WOLFSSL_TRUST_PEER_CERT) && !defined(NO_FILESYSTEM) + if (trustCert) { + if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert, + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't load trusted peer cert file"); + } + } + #endif /* WOLFSSL_TRUST_PEER_CERT && !NO_FILESYSTEM */ + } + if (useVerifyCb || myVerifyFail) + 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 /* !NO_CERTS */ + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevOpen(&devId); + 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 (sniHostName) { + if (wolfSSL_CTX_UseSNI(ctx, 0, sniHostName, + (word16) XSTRLEN(sniHostName)) != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; 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); ctx = NULL; 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); ctx = NULL; 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); ctx = NULL; err_sys("UseSessionTicket failed"); + } +#endif +#ifdef HAVE_EXTENDED_MASTER + if (disableExtMasterSecret) + if (wolfSSL_CTX_DisableExtendedMasterSecret(ctx) != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("DisableExtendedMasterSecret failed"); + } +#endif +#if defined(HAVE_SUPPORTED_CURVES) + #if defined(HAVE_CURVE25519) + if (useX25519) { + if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_X25519) + != WOLFSSL_SUCCESS) { + err_sys("unable to support X25519"); + } + } + #endif /* HAVE_CURVE25519 */ + #if defined(HAVE_CURVE448) + if (useX448) { + if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_X448) + != WOLFSSL_SUCCESS) { + err_sys("unable to support X448"); + } + } + #endif /* HAVE_CURVE448 */ + #ifdef HAVE_ECC + if (useSupCurve) { + #if !defined(NO_ECC_SECP) && \ + (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) + if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_SECP384R1) + != WOLFSSL_SUCCESS) { + err_sys("unable to support secp384r1"); + } + #endif + #if !defined(NO_ECC_SECP) && \ + (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) + if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_SECP256R1) + != WOLFSSL_SUCCESS) { + err_sys("unable to support secp256r1"); + } + #endif + } + #endif /* HAVE_ECC */ + #ifdef HAVE_FFDHE_2048 + if (useSupCurve) { + if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_FFDHE_2048) + != WOLFSSL_SUCCESS) { + err_sys("unable to support FFDHE 2048"); + } + } + #endif +#endif /* HAVE_SUPPORTED_CURVES */ + +#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 (benchmark) { - /* time passed in number of connects give average */ - int times = benchmark; - int loops = resumeSession ? 2 : 1; - int i = 0; - WOLFSSL_SESSION* benchSession = NULL; - - while (loops--) { - int benchResume = resumeSession && loops == 0; - double start = current_time(), avg; - - for (i = 0; i < times; i++) { - tcp_connect(&sockfd, host, port, doDTLS); - - ssl = wolfSSL_new(ctx); - if (benchResume) - wolfSSL_set_session(ssl, benchSession); - wolfSSL_set_fd(ssl, sockfd); - if (wolfSSL_connect(ssl) != SSL_SUCCESS) - err_sys("SSL_connect failed"); - - wolfSSL_shutdown(ssl); - if (i == (times-1) && resumeSession) { - benchSession = wolfSSL_get_session(ssl); - } - wolfSSL_free(ssl); - CloseSocket(sockfd); - } - avg = current_time() - start; - avg /= times; - avg *= 1000; /* milliseconds */ - if (benchResume) - printf("wolfSSL_resume avg took: %8.3f milliseconds\n", avg); - else - printf("wolfSSL_connect avg took: %8.3f milliseconds\n", avg); - } - - wolfSSL_CTX_free(ctx); - ((func_args*)args)->return_code = 0; - - exit(EXIT_SUCCESS); + ((func_args*)args)->return_code = + ClientBenchmarkConnections(ctx, host, port, dtlsUDP, dtlsSCTP, + benchmark, resumeSession, useX25519, + useX448, helloRetry, onlyKeyShare, + version, earlyData); + wolfSSL_CTX_free(ctx); ctx = NULL; + XEXIT_T(EXIT_SUCCESS); } - + + if (throughput) { + ((func_args*)args)->return_code = + ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP, + block, throughput, useX25519, useX448); + wolfSSL_CTX_free(ctx); ctx = NULL; + XEXIT_T(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) + if (wolfSSL_CTX_get_read_ahead(ctx) != 0) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("bad read ahead default value"); + } + if (wolfSSL_CTX_set_read_ahead(ctx, 1) != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("error setting read ahead value"); + } + #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); ctx = NULL; + err_sys("Couldn't set multicast cipher list."); + } +#endif + } + +#ifdef HAVE_PK_CALLBACKS + if (pkCallbacks) + SetupPkCallbacks(ctx); +#endif + ssl = wolfSSL_new(ctx); - if (ssl == NULL) + if (ssl == NULL) { + wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("unable to get SSL object"); - #ifdef HAVE_SESSION_TICKET - wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)"initial session"); + } + + +#ifndef NO_CERTS + if (useClientCert && loadCertKeyIntoSSLObj){ + #ifndef TEST_LOAD_BUFFER + if (wolfSSL_use_certificate_chain_file(ssl, ourCert) + != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't load client cert file, check file and run from" + " wolfSSL home dir"); + } + #else + load_ssl_buffer(ssl, ourCert, WOLFSSL_CERT_CHAIN); + #endif + } + + if (loadCertKeyIntoSSLObj + #if defined(HAVE_PK_CALLBACKS) && defined(TEST_PK_PRIVKEY) + && !pkCallbacks + #endif + ) { + #ifndef TEST_LOAD_BUFFER + if (wolfSSL_use_PrivateKey_file(ssl, ourKey, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't load client private key file, check file and run " + "from wolfSSL home dir"); + } + #else + load_ssl_buffer(ssl, ourKey, WOLFSSL_KEY); + #endif + } +#endif /* !NO_CERTS */ + +#ifdef OPENSSL_EXTRA + wolfSSL_KeepArrays(ssl); +#endif + +#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 defined(WOLFSSL_TLS13) && (!defined(NO_DH) || defined(HAVE_ECC) || \ + defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)) + 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_CURVE448 + if (useX448) { + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve x448"); + } + } + #endif + #ifdef HAVE_ECC + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve secp256r1"); + } + #endif + #endif + } + 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 + } #endif - if (doDTLS) { - SOCKADDR_IN_T addr; - build_addr(&addr, host, port, 1); - wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr)); - tcp_socket(&sockfd, 1); } else { - tcp_connect(&sockfd, host, port, 0); - } - -#ifdef HAVE_POLY1305 - /* use old poly to connect with google server */ - if (!XSTRNCMP(domain, "www.google.com", 14)) { - if (wolfSSL_use_old_poly(ssl, 1) != 0) - err_sys("unable to set to old poly"); + wolfSSL_NoKeyShares(ssl); } #endif - wolfSSL_set_fd(ssl, sockfd); + 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); ctx = NULL; + err_sys("unable to set mcast secret"); + } +#endif + } + + #ifdef HAVE_SESSION_TICKET + wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)"initial session"); + #endif + +#ifdef HAVE_TRUSTED_CA + if (trustedCaKeyId) { + if (wolfSSL_UseTrustedCA(ssl, WOLFSSL_TRUSTED_CA_PRE_AGREED, + NULL, 0) != WOLFSSL_SUCCESS) { + err_sys("UseTrustedCA failed"); + } + } +#endif +#ifdef HAVE_ALPN + if (alpnList != NULL) { + printf("ALPN accepted protocols list : %s\n", alpnList); + wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt); + } +#endif + +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ + defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (statusRequest) { + if (version == 4 && + (statusRequest == OCSP_STAPLINGV2 || \ + statusRequest == OCSP_STAPLINGV2_MULTI)) { + err_sys("Cannot use OCSP Stapling V2 with TLSv1.3"); + } + + if (wolfSSL_CTX_EnableOCSPStapling(ctx) != WOLFSSL_SUCCESS) + err_sys("can't enable OCSP Stapling Certificate Manager"); + + switch (statusRequest) { + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + case OCSP_STAPLING: + if (wolfSSL_UseOCSPStapling(ssl, WOLFSSL_CSR_OCSP, + WOLFSSL_CSR_OCSP_USE_NONCE) != WOLFSSL_SUCCESS) { + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("UseCertificateStatusRequest failed"); + } + break; + #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + case OCSP_STAPLINGV2: + if (wolfSSL_UseOCSPStaplingV2(ssl, + WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE) + != WOLFSSL_SUCCESS) { + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("UseCertificateStatusRequest failed"); + } + break; + case OCSP_STAPLINGV2_MULTI: + if (wolfSSL_UseOCSPStaplingV2(ssl, + WOLFSSL_CSR2_OCSP_MULTI, 0) + != WOLFSSL_SUCCESS) { + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("UseCertificateStatusRequest failed"); + } + break; + #endif + default: + err_sys("Invalid OCSP Stapling option"); + } + + wolfSSL_CTX_EnableOCSP(ctx, 0); + } +#endif + +#if !defined(NO_DH) && !defined(WOLFSSL_OLD_PRIME_CHECK) && \ + !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + if (!doDhKeyCheck) + wolfSSL_SetEnableDhKeyTest(ssl, 0); +#endif + +#ifdef HAVE_ENCRYPT_THEN_MAC + if (disallowETM) + wolfSSL_AllowEncryptThenMac(ssl, 0); +#endif + + + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); + if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("error in setting fd"); + } + + /* STARTTLS */ + if (doSTARTTLS) { + if (StartTLS_Init(&sockfd) != WOLFSSL_SUCCESS) { + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("error during STARTTLS protocol"); + } + } + #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); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; 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); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; 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); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("can't set crl callback"); + } } #endif #ifdef HAVE_SECURE_RENEGOTIATION if (scr) { - if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS) + if (wolfSSL_UseSecureRenegotiation(ssl) != WOLFSSL_SUCCESS) { + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("can't enable secure renegotiation"); + } } #endif -#ifdef ATOMIC_USER +#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY) if (atomicUser) SetupAtomicUser(ctx, ssl); #endif #ifdef HAVE_PK_CALLBACKS if (pkCallbacks) - SetupPkCallbacks(ctx, ssl); + SetupPkCallbackContexts(ssl, &pkCbInfo); #endif if (matchName && doPeerCheck) wolfSSL_check_domain_name(ssl, domain); #ifndef WOLFSSL_CALLBACKS if (nonBlocking) { - wolfSSL_set_using_nonblock(ssl, 1); +#ifdef WOLFSSL_DTLS + if (doDTLS) { + wolfSSL_dtls_set_using_nonblock(ssl, 1); + } +#endif tcp_set_nonblocking(&sockfd); - NonBlockingSSL_Connect(ssl); + ret = NonBlockingSSL_Connect(ssl); } - else if (wolfSSL_connect(ssl) != SSL_SUCCESS) { - /* see note at top of README */ - int err = wolfSSL_get_error(ssl, 0); - char buffer[WOLFSSL_MAX_ERROR_SZ]; - printf("err = %d, %s\n", err, - wolfSSL_ERR_error_string(err, buffer)); - err_sys("SSL_connect failed"); - /* if you're getting an error here */ + else { +#ifdef WOLFSSL_EARLY_DATA + if (usePsk && earlyData) + EarlyData(ctx, ssl, msg, msgSz, buffer); +#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); } #else - timeout.tv_sec = 2; - timeout.tv_usec = 0; - NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ + timeoutConnect.tv_sec = DEFAULT_TIMEOUT_SEC; + timeoutConnect.tv_usec = 0; + ret = NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ +#endif + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + printf("wolfSSL_connect error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + + /* cleanup */ + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + CloseSocket(sockfd); + + if (!exitWithRet) + err_sys("wolfSSL_connect failed"); + /* see note at top of README */ + /* if you're getting an error here */ + + ((func_args*)args)->return_code = err; + goto exit; + } + + showPeerEx(ssl, lng_index); + +#ifdef OPENSSL_EXTRA + printf("Session timeout set to %ld seconds\n", wolfSSL_get_timeout(ssl)); + { + byte* rnd; + byte* pt; + size_t size; + + /* get size of buffer then print */ + size = wolfSSL_get_client_random(NULL, NULL, 0); + if (size == 0) { + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("error getting client random buffer size"); + } + + rnd = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (rnd == NULL) { + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("error creating client random buffer"); + } + + size = wolfSSL_get_client_random(ssl, rnd, size); + if (size == 0) { + XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("error getting client random buffer"); + } + + printf("Client Random : "); + for (pt = rnd; pt < rnd + size; pt++) printf("%02X", *pt); + printf("\n"); + XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + } + + #if defined(OPENSSL_ALL) + /* print out session to stdout */ + { + WOLFSSL_BIO* bio = wolfSSL_BIO_new_fp(stdout, BIO_NOCLOSE); + if (bio != NULL) { + if (wolfSSL_SESSION_print(bio, wolfSSL_get_session(ssl)) != + WOLFSSL_SUCCESS) { + wolfSSL_BIO_printf(bio, "ERROR: Unable to print out session\n"); + } + } + wolfSSL_BIO_free(bio); + } + #endif +#endif + + if (doSTARTTLS && starttlsProt != NULL) { + if (XSTRNCMP(starttlsProt, "smtp", 4) == 0) { + if (SMTP_Shutdown(ssl, wc_shutdown) != WOLFSSL_SUCCESS) { + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("error closing STARTTLS connection"); + } + } + + wolfSSL_free(ssl); ssl = NULL; + CloseSocket(sockfd); + + wolfSSL_CTX_free(ctx); ctx = NULL; + + ((func_args*)args)->return_code = 0; + return 0; + } + +#ifdef HAVE_ALPN + if (alpnList != NULL) { + char *protocol_name = NULL; + word16 protocol_nameSz = 0; + + err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz); + if (err == WOLFSSL_SUCCESS) + printf("Received ALPN protocol : %s (%d)\n", + protocol_name, protocol_nameSz); + 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"); + } #endif - showPeer(ssl); #ifdef HAVE_SECURE_RENEGOTIATION if (scr && forceScr) { if (nonBlocking) { printf("not doing secure renegotiation on example with" - " nonblocking yet"); + " nonblocking yet\n"); } else { - if (wolfSSL_Rehandshake(ssl) != SSL_SUCCESS) { - int err = wolfSSL_get_error(ssl, 0); - char buffer[WOLFSSL_MAX_ERROR_SZ]; - printf("err = %d, %s\n", err, - wolfSSL_ERR_error_string(err, buffer)); - err_sys("wolfSSL_Rehandshake failed"); + if (!resumeScr) { + printf("Beginning secure rengotiation.\n"); + if (wolfSSL_Rehandshake(ssl) != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + printf("err = %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("wolfSSL_Rehandshake failed"); + } + else { + printf("RENEGOTIATION SUCCESSFUL\n"); + } + } + else { + printf("Beginning secure resumption.\n"); + if (wolfSSL_SecureResume(ssl) != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + printf("err = %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("wolfSSL_SecureResume failed"); + } + else { + printf("SECURE RESUMPTION SUCCESSFUL\n"); + } } } } @@ -852,152 +3068,352 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (sendGET) { printf("SSL connect ok, sending GET...\n"); - msgSz = 28; - strncpy(msg, "GET /index.html HTTP/1.0\r\n\r\n", msgSz); + msgSz = sizeof("GET /index.html HTTP/1.0\r\n\r\n"); + XSTRNCPY(msg, "GET /index.html HTTP/1.0\r\n\r\n", msgSz); msg[msgSz] = '\0'; - } - if (wolfSSL_write(ssl, msg, msgSz) != msgSz) - 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); - - 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; - } - } + resumeSz = msgSz; + XSTRNCPY(resumeMsg, "GET /index.html HTTP/1.0\r\n\r\n", resumeSz); + resumeMsg[resumeSz] = '\0'; } - else if (input < 0) { - int readErr = wolfSSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) - err_sys("wolfSSL_read failed"); + +/* 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 +#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ + +#ifdef WOLFSSL_TLS13 + if (updateKeysIVs) + wolfSSL_update_keys(ssl); +#endif + + ClientWrite(ssl, msg, msgSz, ""); + + ClientRead(ssl, reply, sizeof(reply)-1, 1, ""); + +#if defined(WOLFSSL_TLS13) + if (updateKeysIVs || 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); } #endif - if (doDTLS == 0) { /* don't send alert after "break" command */ - ret = wolfSSL_shutdown(ssl); - if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) - wolfSSL_shutdown(ssl); /* bidirectional shutdown */ +#if defined(OPENSSL_EXTRA) && defined(HAVE_EXT_CACHE) + if (session != NULL && resumeSession) { + flatSessionSz = wolfSSL_i2d_SSL_SESSION(session, NULL); + if (flatSessionSz != 0) { + int checkSz = wolfSSL_i2d_SSL_SESSION(session, &flatSession); + if (flatSession == NULL) + err_sys("error creating flattened session buffer"); + if (checkSz != flatSessionSz) { + XFREE(flatSession, NULL, DYNAMIC_TYPE_TMP_BUFFER); + err_sys("flat session size check failure"); + } + } } -#ifdef ATOMIC_USER +#endif + + if (dtlsUDP == 0) { /* don't send alert after "break" command */ + ret = wolfSSL_shutdown(ssl); + if (wc_shutdown && ret == WOLFSSL_SHUTDOWN_NOT_DONE) { + if (tcp_select(sockfd, DEFAULT_TIMEOUT_SEC) == TEST_RECV_READY) { + ret = wolfSSL_shutdown(ssl); /* bidirectional shutdown */ + if (ret == WOLFSSL_SUCCESS) + printf("Bidirectional shutdown complete\n"); + } + if (ret != WOLFSSL_SUCCESS) + printf("Bidirectional shutdown failed\n"); + } + } +#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY) if (atomicUser) FreeAtomicUser(ssl); #endif - wolfSSL_free(ssl); + + /* 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); ssl = NULL; CloseSocket(sockfd); #ifndef NO_SESSION_CACHE if (resumeSession) { - if (doDTLS) { - SOCKADDR_IN_T addr; - #ifdef USE_WINDOWS_API - Sleep(500); - #elif defined(WOLFSSL_TIRTOS) - Task_sleep(1); - #else - sleep(1); - #endif - build_addr(&addr, host, port, 1); - wolfSSL_dtls_set_peer(sslResume, &addr, sizeof(addr)); - tcp_socket(&sockfd, 1); + sslResume = wolfSSL_new(ctx); + if (sslResume == NULL) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("unable to get SSL object"); } - else { - tcp_connect(&sockfd, host, port, 0); + +#if !defined(NO_DH) && !defined(WOLFSSL_OLD_PRIME_CHECK) && \ + !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + if (!doDhKeyCheck) + wolfSSL_SetEnableDhKeyTest(sslResume, 0); +#endif + + if (dtlsUDP) { +#ifdef USE_WINDOWS_API + Sleep(500); +#elif defined(WOLFSSL_TIRTOS) + Task_sleep(1); +#else + sleep(1); +#endif } - wolfSSL_set_fd(sslResume, sockfd); -#ifdef HAVE_SECURE_RENEGOTIATION - if (scr) { - if (wolfSSL_UseSecureRenegotiation(sslResume) != SSL_SUCCESS) - err_sys("can't enable secure renegotiation"); + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, sslResume); + if (wolfSSL_set_fd(sslResume, sockfd) != WOLFSSL_SUCCESS) { + wolfSSL_free(sslResume); sslResume = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("error in setting fd"); + } +#ifdef HAVE_ALPN + if (alpnList != NULL) { + printf("ALPN accepted protocols list : %s\n", alpnList); + wolfSSL_UseALPN(sslResume, alpnList, (word32)XSTRLEN(alpnList), + alpn_opt); } #endif +#ifdef HAVE_SECURE_RENEGOTIATION + if (scr) { + if (wolfSSL_UseSecureRenegotiation(sslResume) != WOLFSSL_SUCCESS) { + wolfSSL_free(sslResume); sslResume = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't enable secure renegotiation"); + } + } +#endif + +#if defined(OPENSSL_EXTRA) && defined(HAVE_EXT_CACHE) + if (flatSession) { + const byte* constFlatSession = flatSession; + session = wolfSSL_d2i_SSL_SESSION(NULL, + &constFlatSession, flatSessionSz); + } +#endif + wolfSSL_set_session(sslResume, session); + +#if defined(OPENSSL_EXTRA) && defined(HAVE_EXT_CACHE) + if (flatSession) { + XFREE(flatSession, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_SESSION_free(session); + } +#endif #ifdef HAVE_SESSION_TICKET wolfSSL_set_SessionTicket_cb(sslResume, sessionTicketCB, (void*)"resumed session"); #endif - - showPeer(sslResume); + #ifndef WOLFSSL_CALLBACKS if (nonBlocking) { - wolfSSL_set_using_nonblock(sslResume, 1); - tcp_set_nonblocking(&sockfd); - NonBlockingSSL_Connect(sslResume); - } - else if (wolfSSL_connect(sslResume) != SSL_SUCCESS) - err_sys("SSL resume failed"); -#else - timeout.tv_sec = 2; - timeout.tv_usec = 0; - NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ +#ifdef WOLFSSL_DTLS + if (doDTLS) { + wolfSSL_dtls_set_using_nonblock(sslResume, 1); + } #endif + tcp_set_nonblocking(&sockfd); + ret = NonBlockingSSL_Connect(sslResume); + } + else { + #ifdef WOLFSSL_EARLY_DATA + #ifndef HAVE_SESSION_TICKET + if (!usePsk) { + } + else + #endif + if (earlyData) { + EarlyData(ctx, sslResume, msg, msgSz, buffer); + } + #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 + timeoutConnect.tv_sec = DEFAULT_TIMEOUT_SEC; + timeoutConnect.tv_usec = 0; + ret = NonBlockingSSL_Connect(sslResume); /* 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); sslResume = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("wolfSSL_connect resume failed"); + } + + showPeerEx(sslResume, lng_index); if (wolfSSL_session_reused(sslResume)) printf("reused session id\n"); else printf("didn't reuse session id!!!\n"); - if (wolfSSL_write(sslResume, resumeMsg, resumeSz) != resumeSz) - err_sys("SSL_write failed"); +#ifdef HAVE_ALPN + if (alpnList != NULL) { + char *protocol_name = NULL; + word16 protocol_nameSz = 0; + printf("Sending ALPN accepted list : %s\n", alpnList); + err = wolfSSL_ALPN_GetProtocol(sslResume, &protocol_name, + &protocol_nameSz); + if (err == WOLFSSL_SUCCESS) + printf("Received ALPN protocol : %s (%d)\n", + protocol_name, protocol_nameSz); + 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"); + } +#endif + + /* 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 + #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ + +#ifdef HAVE_SECURE_RENEGOTIATION + if (scr && forceScr) { 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 + printf("not doing secure renegotiation on example with" + " nonblocking yet\n"); + } else { + if (!resumeScr) { + printf("Beginning secure rengotiation.\n"); + if (wolfSSL_Rehandshake(sslResume) != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(sslResume, 0); + printf("err = %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(sslResume); sslResume = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("wolfSSL_Rehandshake failed"); + } + else { + printf("RENEGOTIATION SUCCESSFUL\n"); + } + } + else { + printf("Beginning secure resumption.\n"); + if (wolfSSL_SecureResume(sslResume) != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(sslResume, 0); + printf("err = %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(sslResume); sslResume = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("wolfSSL_SecureResume failed"); + } + else { + printf("SECURE RESUMPTION SUCCESSFUL\n"); + } + } } + } +#endif /* HAVE_SECURE_RENEGOTIATION */ - input = wolfSSL_read(sslResume, reply, sizeof(reply)-1); - if (input > 0) { - reply[input] = 0; - printf("Server resume response: %s\n", reply); - } + ClientWrite(sslResume, resumeMsg, resumeSz, " resume"); + ClientRead(sslResume, reply, sizeof(reply)-1, sendGET, + "Server resume: "); /* try to send session break */ - wolfSSL_write(sslResume, msg, msgSz); + ClientWrite(sslResume, msg, msgSz, " resume 2"); 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 */ - wolfSSL_free(sslResume); + /* 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); sslResume = NULL; CloseSocket(sockfd); } #endif /* NO_SESSION_CACHE */ - wolfSSL_CTX_free(ctx); + wolfSSL_CTX_free(ctx); ctx = NULL; ((func_args*)args)->return_code = 0; -#ifdef USE_WOLFSSL_MEMORY - if (trackMemory) - ShowMemoryTracker(); -#endif /* USE_WOLFSSL_MEMORY */ +exit: + +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + +#if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) \ + && defined(HAVE_STACK_SIZE) + wc_ecc_fp_free(); /* free per thread cache */ +#endif + + /* There are use cases when these assignments are not read. To avoid + * potential confusion those warnings have been handled here. + */ + (void) overrideDateErrors; + (void) useClientCert; + (void) verifyCert; + (void) ourCert; + (void) ourKey; + (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 @@ -1006,38 +3422,35 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) { func_args args; -#ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) - err_sys("Cavium OpenNitroxDevice failed"); -#endif /* HAVE_CAVIUM */ StartTCP(); args.argc = argc; args.argv = argv; + args.return_code = 0; - wolfSSL_Init(); #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_MDK_SHELL) && !defined(STACK_TRAP) wolfSSL_Debugging_ON(); #endif - if (CurrentDir("_build")) - ChangeDirBack(1); - else if (CurrentDir("client")) - ChangeDirBack(2); - else if (CurrentDir("Debug") || CurrentDir("Release")) - ChangeDirBack(3); - + wolfSSL_Init(); + ChangeToWolfRoot(); + +#ifndef NO_WOLFSSL_CLIENT #ifdef HAVE_STACK_SIZE StackSizeCheck(&args, client_test); -#else +#else client_test(&args); +#endif +#else + printf("Client not compiled in!\n"); #endif wolfSSL_Cleanup(); -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); -#endif +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context"); +#endif /* HAVE_WNR */ + return args.return_code; } @@ -1045,39 +3458,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/FreeRTOS-Plus/Source/WolfSSL/examples/client/client.h b/FreeRTOS-Plus/Source/WolfSSL/examples/client/client.h index e4b13be48..72402e99f 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/client/client.h +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/client/client.h @@ -1,8 +1,8 @@ /* client.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,16 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#pragma once + +#ifndef WOLFSSL_CLIENT_H +#define WOLFSSL_CLIENT_H + THREAD_RETURN WOLFSSL_THREAD client_test(void* args); + +#endif /* WOLFSSL_CLIENT_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/client/client.vcproj b/FreeRTOS-Plus/Source/WolfSSL/examples/client/client.vcproj index a743bcaff..4b758dcb7 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/client/client.vcproj +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/client/client.vcproj @@ -41,8 +41,8 @@ + + Disabled - ../../;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -178,8 +178,8 @@ Disabled - ../../;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -193,13 +193,14 @@ true Console MachineX86 + false Disabled - ../../;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -216,8 +217,8 @@ Disabled - ../../;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -235,8 +236,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -257,8 +258,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -279,8 +280,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -300,8 +301,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -326,6 +327,9 @@ false + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/client/include.am b/FreeRTOS-Plus/Source/WolfSSL/examples/client/include.am index d0ddcdfaa..876f6a28e 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/client/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/client/include.am @@ -1,11 +1,11 @@ # vim:ft=automake # All paths should be given relative to the root -if BUILD_EXAMPLES +if BUILD_EXAMPLE_CLIENTS noinst_PROGRAMS += examples/client/client noinst_HEADERS += examples/client/client.h examples_client_client_SOURCES = examples/client/client.c -examples_client_client_LDADD = src/libwolfssl.la +examples_client_client_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) examples_client_client_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += examples/client/client.sln diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/echoclient.c b/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/echoclient.c index 594d146cf..e27ecc2b5 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/echoclient.c +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/echoclient.c @@ -1,8 +1,8 @@ /* echoclient.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,37 +16,41 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include - /* let's use cyassl layer AND cyassl openssl layer */ #include #include +#ifdef CYASSL_DTLS + #include +#endif -#if defined(CYASSL_MDK_ARM) +#if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) #include #include - - #if defined(CYASSL_MDK5) - #include "cmsis_os.h" - #include "rl_fs.h" - #include "rl_net.h" - #else - #include "rtl.h" - #endif - - #include "cyassl_MDK_ARM.h" + #include "cmsis_os.h" + #include "rl_fs.h" + #include "rl_net.h" + #include "wolfssl_MDK_ARM.h" #endif #include -#include "examples/echoclient/echoclient.h" +#include + +#ifndef NO_WOLFSSL_CLIENT + +#ifdef WOLFSSL_ASYNC_CRYPT + static int devId = INVALID_DEVID; +#endif + void echoclient_test(void* args) { @@ -55,8 +59,10 @@ void echoclient_test(void* args) FILE* fin = stdin ; FILE* fout = stdout; +#ifndef WOLFSSL_MDK_SHELL int inCreated = 0; int outCreated = 0; +#endif char msg[1024]; char reply[1024+1]; @@ -65,28 +71,32 @@ void echoclient_test(void* args) SSL_CTX* ctx = 0; SSL* ssl = 0; + int ret = 0, err = 0; int doDTLS = 0; int doPSK = 0; int sendSz; +#ifndef WOLFSSL_MDK_SHELL int argc = 0; char** argv = 0; +#endif word16 port = yasslPort; + char buffer[CYASSL_MAX_ERROR_SZ]; ((func_args*)args)->return_code = -1; /* error state */ - -#ifndef CYASSL_MDK_SHELL + +#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) { fout = fopen(argv[2], "w"); outCreated = 1; } +#endif if (!fin) err_sys("can't open input file"); if (!fout) err_sys("can't open output file"); @@ -95,94 +105,137 @@ void echoclient_test(void* args) doDTLS = 1; #endif -#ifdef CYASSL_LEANPSK +#ifdef CYASSL_LEANPSK doPSK = 1; #endif - -#if defined(NO_RSA) && !defined(HAVE_ECC) +#if defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ + !defined(HAVE_ED448) doPSK = 1; #endif + (void)doPSK; -#if defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API) && !defined(CYASSL_MDK_SHELL) +#if defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_SHELL) port = ((func_args*)args)->signal->port; #endif #if defined(CYASSL_DTLS) method = DTLSv1_2_client_method(); -#elif !defined(NO_TLS) +#elif !defined(NO_TLS) method = CyaSSLv23_client_method(); -#else +#elif defined(WOLFSSL_ALLOW_SSLV3) method = SSLv3_client_method(); +#else + #error "no valid client method type" #endif ctx = SSL_CTX_new(method); #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"); + #elif defined(HAVE_ED25519) + if (SSL_CTX_load_verify_locations(ctx, caEdCertFile, 0) != WOLFSSL_SUCCESS) + err_sys("can't load ca file, Please run from wolfSSL home dir"); + #elif defined(HAVE_ED448) + if (SSL_CTX_load_verify_locations(ctx, caEd448CertFile, 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, CYASSL_CA); + load_buffer(ctx, caCertFile, WOLFSSL_CA); #endif #if defined(CYASSL_SNIFFER) /* don't use EDH, can't sniff tmp keys */ SSL_CTX_set_cipher_list(ctx, "AES256-SHA"); #endif - if (doPSK) { #ifndef NO_PSK + if (doPSK) { const char *defaultCipherList; CyaSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb); #ifdef HAVE_NULL_CIPHER defaultCipherList = "PSK-NULL-SHA256"; + #elif defined(HAVE_AESGCM) && !defined(NO_DH) + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; #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 } +#endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +#ifdef WOLFSSL_ENCRYPTED_KEYS SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif - #if defined(CYASSL_MDK_ARM) - CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); - #endif +#if defined(WOLFSSL_MDK_ARM) + CyaSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, 0); +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevOpen(&devId); + 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); - if (doDTLS) { - SOCKADDR_IN_T addr; - build_addr(&addr, yasslIP, port, 1); - CyaSSL_dtls_set_peer(ssl, &addr, sizeof(addr)); - tcp_socket(&sockfd, 1); - } - else { - tcp_connect(&sockfd, yasslIP, port, 0); - } - 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 */ Sleep(100); #endif - if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed"); + do { + err = 0; /* Reset error */ + ret = SSL_connect(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); + 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)strlen(msg); - if (SSL_write(ssl, msg, sendSz) != sendSz) + sendSz = (int)XSTRLEN(msg); + + 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); @@ -194,29 +247,47 @@ void echoclient_test(void* args) break; } - #ifndef CYASSL_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 } @@ -224,7 +295,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 @@ -232,14 +315,21 @@ void echoclient_test(void* args) SSL_free(ssl); SSL_CTX_free(ctx); +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + fflush(fout); +#ifndef WOLFSSL_MDK_SHELL if (inCreated) fclose(fin); if (outCreated) fclose(fout); +#endif 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 @@ -248,37 +338,36 @@ void echoclient_test(void* args) { func_args args; -#ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) - err_sys("Cavium OpenNitroxDevice failed"); -#endif /* HAVE_CAVIUM */ +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) + err_sys("Whitewood netRandom global config failed"); +#endif StartTCP(); args.argc = argc; args.argv = argv; + args.return_code = 0; CyaSSL_Init(); -#if defined(DEBUG_CYASSL) && !defined(CYASSL_MDK_SHELL) +#if defined(DEBUG_CYASSL) && !defined(WOLFSSL_MDK_SHELL) CyaSSL_Debugging_ON(); #endif #ifndef CYASSL_TIRTOS - if (CurrentDir("echoclient")) - ChangeDirBack(2); - else if (CurrentDir("Debug") || CurrentDir("Release")) - ChangeDirBack(3); + ChangeToWolfRoot(); #endif +#ifndef NO_WOLFSSL_CLIENT echoclient_test(&args); +#endif CyaSSL_Cleanup(); -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); -#endif +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context"); +#endif /* HAVE_WNR */ + return args.return_code; } - + #endif /* NO_MAIN_DRIVER */ - - diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/echoclient.h b/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/echoclient.h index d945edb4a..0aebffbc2 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/echoclient.h +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/echoclient.h @@ -1,8 +1,8 @@ /* echoclient.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,8 +16,15 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#pragma once + +#ifndef WOLFSSL_ECHOCLIENT_H +#define WOLFSSL_ECHOCLIENT_H + + void echoclient_test(void* args); + +#endif /* WOLFSSL_ECHOCLIENT_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/echoclient.vcproj b/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/echoclient.vcproj index 3a2a085a4..55d2610cb 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/echoclient.vcproj +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/echoclient.vcproj @@ -41,8 +41,8 @@ + + Disabled - ../../;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -173,14 +173,13 @@ Console MachineX86 false - Disabled - ../../;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -194,13 +193,14 @@ true Console MachineX86 + false Disabled - ../../;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -217,8 +217,8 @@ Disabled - ../../;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -236,8 +236,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -252,15 +252,14 @@ true MachineX86 false - MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -281,8 +280,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -302,8 +301,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -328,6 +327,9 @@ false + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/include.am b/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/include.am index 179cf9907..7f0bc47d1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/echoclient/include.am @@ -3,11 +3,11 @@ # All paths should be given relative to the root -if BUILD_EXAMPLES +if BUILD_EXAMPLE_CLIENTS noinst_PROGRAMS += examples/echoclient/echoclient noinst_HEADERS += examples/echoclient/echoclient.h examples_echoclient_echoclient_SOURCES = examples/echoclient/echoclient.c -examples_echoclient_echoclient_LDADD = src/libwolfssl.la +examples_echoclient_echoclient_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) examples_echoclient_echoclient_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += examples/echoclient/echoclient.sln diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/echoserver.c b/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/echoserver.c index 6b5c575e6..d268ab479 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/echoserver.c +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/echoserver.c @@ -1,8 +1,8 @@ /* echoserver.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -29,19 +30,13 @@ #include /* ecc_fp_free */ #endif -#if defined(CYASSL_MDK_ARM) +#if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) #include #include - - #if defined(CYASSL_MDK5) - #include "cmsis_os.h" - #include "rl_fs.h" - #include "rl_net.h" - #else - #include "rtl.h" - #endif - - #include "cyassl_MDK_ARM.h" + #include "cmsis_os.h" + #include "rl_fs.h" + #include "rl_net.h" + #include "wolfssl_MDK_ARM.h" #endif #include @@ -53,6 +48,12 @@ #include "examples/echoserver/echoserver.h" +#ifndef NO_WOLFSSL_SERVER + +#ifdef WOLFSSL_ASYNC_CRYPT + static int devId = INVALID_DEVID; +#endif + #define SVR_COMMAND_SIZE 256 static void SignalReady(void* args, word16 port) @@ -78,14 +79,16 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) CYASSL_METHOD* method = 0; CYASSL_CTX* ctx = 0; + int ret = 0; int doDTLS = 0; - int doPSK = 0; + int doPSK; int outCreated = 0; int shutDown = 0; int useAnyAddr = 0; - word16 port = yasslPort; + 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; @@ -105,40 +108,46 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) doDTLS = 1; #endif -#ifdef CYASSL_LEANPSK +#if (defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ + !defined(HAVE_ED448)) || defined(CYASSL_LEANPSK) doPSK = 1; +#else + doPSK = 0; #endif -#if defined(NO_RSA) && !defined(HAVE_ECC) - doPSK = 1; +#if defined(NO_MAIN_DRIVER) && !defined(CYASSL_SNIFFER) && \ + !defined(WOLFSSL_MDK_SHELL) && !defined(CYASSL_TIRTOS) && \ + !defined(USE_WINDOWS_API) + /* Let tcp_listen assign port */ + port = 0; +#else + /* Use default port */ + port = wolfSSLPort; #endif - #if defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API) && \ - !defined(CYASSL_SNIFFER) && !defined(CYASSL_MDK_SHELL) && \ - !defined(CYASSL_TIRTOS) - port = 0; - #endif - #if defined(USE_ANY_ADDR) - useAnyAddr = 1; - #endif +#if defined(USE_ANY_ADDR) + useAnyAddr = 1; +#endif #ifdef CYASSL_TIRTOS fdOpenSession(Task_self()); #endif - tcp_listen(&sockfd, &port, useAnyAddr, doDTLS); + tcp_listen(&sockfd, &port, useAnyAddr, doDTLS, 0); #if defined(CYASSL_DTLS) method = CyaDTLSv1_2_server_method(); -#elif !defined(NO_TLS) +#elif !defined(NO_TLS) method = CyaSSLv23_server_method(); -#else +#elif defined(WOLFSSL_ALLOW_SSLV3) method = CyaSSLv3_server_method(); +#else + #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) +#ifdef WOLFSSL_ENCRYPTED_KEYS CyaSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif @@ -151,47 +160,69 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) #ifndef NO_FILESYSTEM if (doPSK == 0) { - #ifdef HAVE_NTRU + #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(HAVE_ED25519) && !defined(CYASSL_SNIFFER) + /* ed25519 */ + if (CyaSSL_CTX_use_certificate_chain_file(ctx, edCertFile) + != WOLFSSL_SUCCESS) + err_sys("can't load server cert file, " + "Please run from wolfSSL home dir"); + + if (CyaSSL_CTX_use_PrivateKey_file(ctx, edKeyFile, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) + err_sys("can't load server key file, " + "Please run from wolfSSL home dir"); + #elif defined(HAVE_ED448) && !defined(CYASSL_SNIFFER) + /* ed448 */ + if (CyaSSL_CTX_use_certificate_chain_file(ctx, ed448CertFile) + != WOLFSSL_SUCCESS) + err_sys("can't load server cert file, " + "Please run from wolfSSL home dir"); + + if (CyaSSL_CTX_use_PrivateKey_file(ctx, ed448KeyFile, + 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, CYASSL_CERT); - load_buffer(ctx, svrKey, CYASSL_KEY); + load_buffer(ctx, svrCertFile, WOLFSSL_CERT); + load_buffer(ctx, svrKeyFile, WOLFSSL_KEY); } #endif @@ -208,43 +239,84 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) CyaSSL_CTX_use_psk_identity_hint(ctx, "cyassl server"); #ifdef HAVE_NULL_CIPHER defaultCipherList = "PSK-NULL-SHA256"; + #elif defined(HAVE_AESGCM) && !defined(NO_DH) + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; #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) { + printf("Async device open failed\nRunning without async\n"); + } + wolfSSL_CTX_UseAsync(ctx, devId); +#endif /* WOLFSSL_ASYNC_CRYPT */ + 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; int firstRead = 1; int gotFirstG = 0; - -#ifndef CYASSL_DTLS + int err = 0; SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); +#ifndef CYASSL_DTLS clientfd = accept(sockfd, (struct sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); #else - clientfd = udp_read_connect(sockfd); + clientfd = sockfd; + { + /* For DTLS, peek at the next datagram so we can get the client's + * address and set it into the ssl object later to generate the + * cookie. */ + int n; + byte b[1500]; + n = (int)recvfrom(clientfd, (char*)b, sizeof(b), MSG_PEEK, + (struct sockaddr*)&client, &client_len); + if (n <= 0) + err_sys("recvfrom failed"); + } #endif - if (clientfd == -1) err_sys("tcp accept failed"); + if (WOLFSSL_SOCKET_IS_INVALID(clientfd)) err_sys("tcp accept failed"); ssl = CyaSSL_new(ctx); if (ssl == NULL) err_sys("SSL_new failed"); CyaSSL_set_fd(ssl, clientfd); + #ifdef CYASSL_DTLS + 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 - if (CyaSSL_accept(ssl) != SSL_SUCCESS) { + + do { + err = 0; /* Reset error */ + ret = CyaSSL_accept(ssl); + 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 (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); @@ -254,7 +326,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 */ @@ -267,7 +373,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; @@ -283,43 +389,75 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) break; } #endif - if ( strncmp(command, "GET", 3) == 0) { - char type[] = "HTTP/1.0 200 ok\r\nContent-type:" - " text/html\r\n\r\n"; - 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;
+            if (strncmp(command, "GET", 3) == 0) {
+                const char resp[] =
+                    "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"
+                    "
\r\n"
+                    "greetings from wolfSSL\r\n
\r\n\r\n"; - strncpy(&command[echoSz], header, sizeof(header)); - echoSz += (int)sizeof(header) - 1; - strncpy(&command[echoSz], body, sizeof(body)); - echoSz += (int)sizeof(body) - 1; - strncpy(&command[echoSz], footer, sizeof(footer)); - echoSz += (int)sizeof(footer); + echoSz = (int)strlen(resp) + 1; + if (echoSz > (int)sizeof(command)) { + /* Internal error. */ + err_sys("HTTP response greater than buffer."); + } + strncpy(command, resp, sizeof(command)); - 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); #ifdef CYASSL_DTLS - tcp_listen(&sockfd, &port, useAnyAddr, doDTLS); + tcp_listen(&sockfd, &port, useAnyAddr, doDTLS, 0); SignalReady(args, port); #endif } @@ -348,11 +486,17 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) TicketCleanup(); #endif +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + #ifndef CYASSL_TIRTOS return 0; #endif } +#endif /* !NO_WOLFSSL_SERVER */ + /* so overall tests can pull in test function */ #ifndef NO_MAIN_DRIVER @@ -361,35 +505,33 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) { func_args args; -#ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) - err_sys("Cavium OpenNitroxDevice failed"); -#endif /* HAVE_CAVIUM */ +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) + err_sys("Whitewood netRandom global config failed"); +#endif StartTCP(); args.argc = argc; args.argv = argv; + args.return_code = 0; CyaSSL_Init(); #if defined(DEBUG_CYASSL) && !defined(CYASSL_MDK_SHELL) CyaSSL_Debugging_ON(); #endif - if (CurrentDir("echoserver")) - ChangeDirBack(2); - else if (CurrentDir("Debug") || CurrentDir("Release")) - ChangeDirBack(3); + ChangeToWolfRoot(); +#ifndef NO_WOLFSSL_SERVER echoserver_test(&args); +#endif CyaSSL_Cleanup(); -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); -#endif +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context"); +#endif /* HAVE_WNR */ + return args.return_code; } - #endif /* NO_MAIN_DRIVER */ - - diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/echoserver.h b/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/echoserver.h index 2f0d88d3d..622193f61 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/echoserver.h +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/echoserver.h @@ -1,8 +1,8 @@ /* echoserver.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,16 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#pragma once + +#ifndef WOLFSSL_ECHOSERVER_H +#define WOLFSSL_ECHOSERVER_H + THREAD_RETURN WOLFSSL_THREAD echoserver_test(void* args); + + +#endif /* WOLFSSL_ECHOSERVER_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/echoserver.vcproj b/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/echoserver.vcproj index 0fc396f06..2d6d58199 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/echoserver.vcproj +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/echoserver.vcproj @@ -41,8 +41,8 @@ + + Disabled - ../../;%(AdditionalIncludeDirectories) - USE_ANY_ADDR;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + USE_ANY_ADDR;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -173,14 +173,13 @@ Console MachineX86 false - Disabled - ../../;%(AdditionalIncludeDirectories) - USE_ANY_ADDR;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + USE_ANY_ADDR;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -194,13 +193,14 @@ true Console MachineX86 + false Disabled - ../../;%(AdditionalIncludeDirectories) - USE_ANY_ADDR;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + USE_ANY_ADDR;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -217,8 +217,8 @@ Disabled - ../../;%(AdditionalIncludeDirectories) - USE_ANY_ADDR;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + USE_ANY_ADDR;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -236,8 +236,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - USE_ANY_ADDR;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + USE_ANY_ADDR;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -258,8 +258,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - USE_ANY_ADDR;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + USE_ANY_ADDR;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -280,8 +280,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - USE_ANY_ADDR;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + USE_ANY_ADDR;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -301,8 +301,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - USE_ANY_ADDR;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + USE_ANY_ADDR;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -327,6 +327,9 @@ false + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/include.am b/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/include.am index a84312191..516c40441 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/echoserver/include.am @@ -3,11 +3,11 @@ # All paths should be given relative to the root -if BUILD_EXAMPLES +if BUILD_EXAMPLE_SERVERS noinst_PROGRAMS += examples/echoserver/echoserver noinst_HEADERS += examples/echoserver/echoserver.h examples_echoserver_echoserver_SOURCES = examples/echoserver/echoserver.c -examples_echoserver_echoserver_LDADD = src/libwolfssl.la +examples_echoserver_echoserver_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) examples_echoserver_echoserver_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += examples/echoserver/echoserver.sln diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/include.am b/FreeRTOS-Plus/Source/WolfSSL/examples/include.am new file mode 100644 index 000000000..03c06eb6b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/include.am @@ -0,0 +1,9 @@ +# 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 +include examples/server/include.am +include examples/sctp/include.am diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/include.am b/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/include.am new file mode 100644 index 000000000..ae970b40b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/include.am @@ -0,0 +1,38 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + + +if BUILD_SCTP +if BUILD_EXAMPLE_SERVERS +noinst_PROGRAMS += \ + examples/sctp/sctp-server \ + examples/sctp/sctp-server-dtls +examples_sctp_sctp_server_SOURCES = examples/sctp/sctp-server.c +examples_sctp_sctp_server_LDADD = $(LIB_STATIC_ADD) +examples_sctp_sctp_server_dtls_SOURCES = examples/sctp/sctp-server-dtls.c +examples_sctp_sctp_server_dtls_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +examples_sctp_sctp_server_dtls_DEPENDENCIES = src/libwolfssl.la +endif +if BUILD_EXAMPLE_CLIENTS +noinst_PROGRAMS += \ + examples/sctp/sctp-client \ + examples/sctp/sctp-client-dtls +examples_sctp_sctp_client_SOURCES = examples/sctp/sctp-client.c +examples_sctp_sctp_client_LDADD = $(LIB_STATIC_ADD) +examples_sctp_sctp_client_dtls_SOURCES = examples/sctp/sctp-client-dtls.c +examples_sctp_sctp_client_dtls_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +examples_sctp_sctp_client_dtls_DEPENDENCIES = src/libwolfssl.la +endif +endif + +dist_example_DATA += \ + examples/sctp/sctp-server.c \ + examples/sctp/sctp-server-dtls.c \ + examples/sctp/sctp-client.c \ + examples/sctp/sctp-client-dtls.c +DISTCLEANFILES += \ + examples/sctp/.libs/sctp-server \ + examples/sctp/.libs/sctp-server-dtls \ + examples/sctp/.libs/sctp-client \ + examples/sctp/.libs/sctp-client-dtls diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-client-dtls.c b/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-client-dtls.c new file mode 100644 index 000000000..c0a222463 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-client-dtls.c @@ -0,0 +1,130 @@ +/* sctp-client-dtls.c + * + * Copyright (C) 2006-2020 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 */ +#ifndef WOLFSSL_USER_SETTINGS + #include +#endif +#include +#include + +#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) +/* sctp */ +#include +#include +#include +#include + +/* std */ +#include +#include +#include +#include + +#define cacert "./certs/ca-cert.pem" + +static int err_sys(const char* msg) +{ + perror(msg); + exit(EXIT_FAILURE); +} +#endif /* WOLFSSL_SCTP && WOLFSSL_DTLS */ + +int main() +{ +#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) + int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); + + if (sd < 0) + err_sys("sctp socket error"); + + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = inet_addr("127.0.0.1"); + sa.sin_port = htons(12345); + + int ret = connect(sd, (struct sockaddr*)&sa, sizeof(sa)); + if (ret < 0) + err_sys("sctp connect error"); + + const char* response = "hello there"; + char buffer[80]; + + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method()); + if (ctx == NULL) + err_sys("ctx new dtls client failed"); + + ret = wolfSSL_CTX_dtls_set_sctp(ctx); + if (ret != WOLFSSL_SUCCESS) + err_sys("set sctp mode failed"); + + ret = wolfSSL_CTX_load_verify_locations(ctx, cacert, NULL); + if (ret != WOLFSSL_SUCCESS) + err_sys("ca cert error"); + + WOLFSSL* ssl = wolfSSL_new(ctx); + if (ssl == NULL) + err_sys("ssl new dtls client failed"); + + wolfSSL_set_fd(ssl, sd); + + ret = wolfSSL_connect(ssl); + 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_write(ssl, response, (int)strlen(response)); + int got = wolfSSL_read(ssl, buffer, sizeof(buffer)); + if (got > 0) { + buffer[got] = 0; + printf("server said: %s\n", buffer); + } + + unsigned char bigBuf[4096]; + unsigned int i; + + for (i = 0; i < (int)sizeof(bigBuf); i++) + bigBuf[i] = (unsigned char)(i & 0xFF); + wolfSSL_write(ssl, bigBuf, sizeof(bigBuf)); + memset(bigBuf, 0, sizeof(bigBuf)); + + wolfSSL_read(ssl, bigBuf, sizeof(bigBuf)); + for (i = 0; i < sizeof(bigBuf); i++) { + if (bigBuf[i] != (unsigned char)(i & 0xFF)) { + printf("big message check fail\n"); + break; + } + } + + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + + close(sd); +#endif /* WOLFSSL_SCTP && WOLFSSL_DTLS */ + + return 0; +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-client.c b/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-client.c new file mode 100644 index 000000000..cb01354d8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-client.c @@ -0,0 +1,72 @@ +/* sctp-client.c + * + * Copyright (C) 2006-2020 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_USER_SETTINGS + #include +#endif +#include + +#ifdef WOLFSSL_SCTP + +/* sctp */ +#include +#include +#include +#include + +/* std */ +#include +#include +#include +#endif /* WOLFSSL_SCTP */ + +int main() +{ +#ifdef WOLFSSL_SCTP + int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); + + if (sd < 0) + perror("sctp socket error"); + + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = inet_addr("127.0.0.1"); + sa.sin_port = htons(12345); + + int ret = connect(sd, (struct sockaddr*)&sa, sizeof(sa)); + if (ret < 0) + perror("sctp connect error"); + + const char* msg = "hello sctp"; + char buffer[80]; + + send(sd, msg, strlen(msg), 0); + int got = (int)recv(sd, buffer, sizeof(buffer), 0); + if (got > 0) { + buffer[got] = 0; + printf("server said: %s\n", buffer); + } + + close(sd); +#endif /* WOLFSSL_SCTP */ + return 0; +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-server-dtls.c b/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-server-dtls.c new file mode 100644 index 000000000..50a20f241 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-server-dtls.c @@ -0,0 +1,128 @@ +/* sctp-server-dtls.c + * + * Copyright (C) 2006-2020 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 */ +#ifndef WOLFSSL_USER_SETTINGS + #include +#endif +#include +#include + +#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) +/* sctp */ +#include +#include +#include + +/* std */ +#include +#include +#include +#include + + +#define key "./certs/server-key.pem" +#define cert "./certs/server-cert.pem" + +static int err_sys(const char* msg) +{ + perror(msg); + exit(EXIT_FAILURE); +} +#endif /* WOLFSSL_SCTP && WOLFSSL_DTLS */ + +int main() +{ +#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) + int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); + + if (sd < 0) + err_sys("sctp socket error"); + + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = htonl(INADDR_ANY); + sa.sin_port = htons(12345); + + int ret = bind(sd, (struct sockaddr*)&sa, sizeof(sa)); + if (ret < 0) + err_sys("sctp bind error"); + + listen(sd, 3); + + int client_sd = accept(sd, NULL, NULL); + if (client_sd < 0) + err_sys("sctp accept error"); + + const char* response = "well hello to you"; + char buffer[80]; + + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method()); + if (ctx == NULL) + err_sys("ctx new dtls server failed"); + + ret = wolfSSL_CTX_dtls_set_sctp(ctx); + if (ret != WOLFSSL_SUCCESS) + err_sys("set sctp mode failed"); + + 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, WOLFSSL_FILETYPE_PEM); + if (ret != WOLFSSL_SUCCESS) + err_sys("use cert error"); + + WOLFSSL* ssl = wolfSSL_new(ctx); + if (ssl == NULL) + err_sys("ssl new dtls server failed"); + + wolfSSL_set_fd(ssl, client_sd); + + ret = wolfSSL_accept(ssl); + 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))); + + int got = wolfSSL_read(ssl, buffer, sizeof(buffer)); + if (got > 0) { + buffer[got] = 0; + printf("client said: %s\n", buffer); + } + wolfSSL_write(ssl, response, (int)strlen(response)); + + unsigned char bigBuf[4096]; + + wolfSSL_read(ssl, bigBuf, sizeof(bigBuf)); + wolfSSL_write(ssl, bigBuf, sizeof(bigBuf)); + + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + + close(sd); +#endif /* WOLFSSL_SCTP && WOLFSSL_DTLS */ + return 0; +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-server.c b/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-server.c new file mode 100644 index 000000000..34b02c9ce --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/sctp/sctp-server.c @@ -0,0 +1,77 @@ +/* sctp-server.c + * + * Copyright (C) 2006-2020 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_USER_SETTINGS + #include +#endif +#include + +#ifdef WOLFSSL_SCTP +/* sctp */ +#include +#include +#include + +/* std */ +#include +#include +#include +#endif /* WOLFSSL_SCTP */ + +int main() +{ +#ifdef WOLFSSL_SCTP + int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); + + if (sd < 0) + perror("sctp socket error"); + + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = htonl(INADDR_ANY); + sa.sin_port = htons(12345); + + int ret = bind(sd, (struct sockaddr*)&sa, sizeof(sa)); + if (ret < 0) + perror("sctp bind error"); + + listen(sd, 3); + + int client_sd = accept(sd, NULL, NULL); + if (client_sd < 0) + perror("sctp accept error"); + + const char* response = "hi there"; + char buffer[80]; + + int got = (int)recv(client_sd, buffer, sizeof(buffer), 0); + if (got > 0) { + buffer[got] = 0; + printf("client said: %s\n", buffer); + } + send(client_sd, response, strlen(response), 0); + + + close(sd); +#endif /* WOLFSSL_SCTP */ + return 0; +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/server/include.am b/FreeRTOS-Plus/Source/WolfSSL/examples/server/include.am index bd7037682..8a3d75119 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/server/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/server/include.am @@ -3,11 +3,11 @@ # All paths should be given relative to the root -if BUILD_EXAMPLES +if BUILD_EXAMPLE_SERVERS noinst_PROGRAMS += examples/server/server noinst_HEADERS += examples/server/server.h examples_server_server_SOURCES = examples/server/server.c -examples_server_server_LDADD = src/libwolfssl.la +examples_server_server_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) examples_server_server_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += examples/server/server.sln diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/server/server.c b/FreeRTOS-Plus/Source/WolfSSL/examples/server/server.c index a8d597a7e..192c03a72 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/server/server.c +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/server/server.c @@ -1,8 +1,8 @@ /* server.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,207 +16,1056 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif -#include /* name change portability layer */ +#include /* name change portability layer */ -#include +#include #ifdef HAVE_ECC - #include /* ecc_fp_free */ + #include /* wc_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(CYASSL_MDK_ARM) +#if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) #include #include - - #if defined(CYASSL_MDK5) - #include "cmsis_os.h" - #include "rl_fs.h" - #include "rl_net.h" - #else - #include "rtl.h" - #endif - - #include "cyassl_MDK_ARM.h" + #include "rl_fs.h" + #include "rl_net.h" +#endif + +#include +#include +#ifdef WOLFSSL_DTLS + #include #endif -#include -#include #include "examples/server/server.h" +#ifndef NO_WOLFSSL_SERVER + +#ifdef WOLFSSL_ASYNC_CRYPT + static int devId = INVALID_DEVID; +#endif + +#define DEFAULT_TIMEOUT_SEC 2 + +/* Note on using port 0: if the server uses port 0 to bind an ephemeral port + * number and is using the ready file for scripted testing, the code in + * 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\r\n" + "Content-Type: text/html\r\n" + "Connection: close\r\n" + "Content-Length: 141\r\n" + "\r\n" + "\r\n" + "\r\n" + "Welcome to wolfSSL!\r\n" + "\r\n" + "\r\n" + "

wolfSSL has successfully performed handshake!

\r\n" + "\r\n" + "\r\n"; + +int runWithErrors = 0; /* Used with -x flag to run err_sys vs. print errors */ +int catastrophic = 0; /* Use with -x flag to still exit when an error is + * considered catastrophic EG the servers own cert failing + * to load would be catastrophic since there would be no + * cert to send to clients attempting to connect. The + * server should error out completely in that case + */ +static int lng_index = 0; + +#ifdef WOLFSSL_CALLBACKS + #if !defined(NO_OLD_TIMEVAL_NAME) + Timeval srvTo; + #else + WOLFSSL_TIMEVAL srvTo; + #endif + static int srvHandShakeCB(HandShakeInfo* info) + { + (void)info; + return 0; + } + + static int srvTimeoutCB(TimeoutInfo* info) + { + (void)info; + return 0; + } -#ifdef CYASSL_CALLBACKS - int srvHandShakeCB(HandShakeInfo*); - int srvTimeoutCB(TimeoutInfo*); - Timeval srvTo; #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 NonBlockingSSL_Accept(SSL* ssl) +static void err_sys_ex(int out, const char* msg) { -#ifndef CYASSL_CALLBACKS + 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); + } +} + + +#ifdef WOLFSSL_DTLS + +/* Translates return codes returned from + * send() and recv() if need be. + */ +static WC_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 WC_INLINE int wolfSSL_LastError(void) +{ +#ifdef USE_WINDOWS_API + return WSAGetLastError(); +#elif defined(EBSNET) + return xn_getlasterror(); +#else + return errno; +#endif +} + +/* wolfSSL Sock Addr */ +struct WOLFSSL_TEST_SOCKADDR { + unsigned int sz; /* sockaddr size */ + SOCKADDR_IN_T sa; /* pointer to the sockaddr_in or sockaddr_in6 */ +}; + +typedef struct WOLFSSL_TEST_DTLS_CTX { + struct WOLFSSL_TEST_SOCKADDR peer; + int rfd; + int wfd; + int failOnce; + word32 blockSeq; +} WOLFSSL_TEST_DTLS_CTX; + + +static WC_INLINE int PeekSeq(const char* buf, word32* seq) +{ + const char* c = buf + 3; + + if ((c[0] | c[1] | c[2] | c[3]) == 0) { + *seq = (c[4] << 24) | (c[5] << 16) | (c[6] << 8) | c[7]; + return 1; + } + + return 0; +} + + +/* The send embedded callback + * return : nb bytes sent, or error + */ +static int TestEmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + WOLFSSL_TEST_DTLS_CTX* dtlsCtx = (WOLFSSL_TEST_DTLS_CTX*)ctx; + int sd = dtlsCtx->wfd; + int sent; + int err; + + (void)ssl; + + WOLFSSL_ENTER("TestEmbedSendTo()"); + + if (dtlsCtx->failOnce) { + word32 seq = 0; + + if (PeekSeq(buf, &seq) && seq == dtlsCtx->blockSeq) { + dtlsCtx->failOnce = 0; + WOLFSSL_MSG("Forcing WANT_WRITE"); + return WOLFSSL_CBIO_ERR_WANT_WRITE; + } + } + + sent = (int)sendto(sd, buf, sz, 0, (const SOCKADDR*)&dtlsCtx->peer.sa, + dtlsCtx->peer.sz); + + sent = TranslateReturnCode(sent, sd); + + if (sent < 0) { + err = wolfSSL_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; +} + +#endif /* WOLFSSL_DTLS */ + + +static int NonBlockingSSL_Accept(SSL* ssl) +{ +#ifndef WOLFSSL_CALLBACKS int ret = SSL_accept(ssl); #else - int ret = CyaSSL_accept_ex(ssl, srvHandShakeCB, srvTimeoutCB, srvTo); + int ret = wolfSSL_accept_ex(ssl, srvHandShakeCB, srvTimeoutCB, srvTo); #endif int error = SSL_get_error(ssl, 0); - SOCKET_T sockfd = (SOCKET_T)CyaSSL_get_fd(ssl); - int select_ret; + SOCKET_T sockfd = (SOCKET_T)SSL_get_fd(ssl); + 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 + #ifdef WOLFSSL_ASYNC_CRYPT + || error == WC_PENDING_E + #endif + )) { int currTimeout = 1; - if (error == SSL_ERROR_WANT_READ) - printf("... server would read block\n"); + if (error == WOLFSSL_ERROR_WANT_READ) { + /* printf("... server would read block\n"); */ + } + else if (error == WOLFSSL_ERROR_WANT_WRITE) { + /* printf("... server would write block\n"); */ + } + + #ifdef WOLFSSL_ASYNC_CRYPT + if (error == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } else - printf("... server would write block\n"); + #endif + { + if (error != WOLFSSL_ERROR_WANT_WRITE) { + #ifdef WOLFSSL_DTLS + currTimeout = wolfSSL_dtls_get_current_timeout(ssl); + #endif + select_ret = tcp_select(sockfd, currTimeout); + } + } -#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)) { - #ifndef CYASSL_CALLBACKS + if ((select_ret == TEST_RECV_READY) || (select_ret == TEST_SEND_READY) + || (select_ret == TEST_ERROR_READY) + #ifdef WOLFSSL_ASYNC_CRYPT + || error == WC_PENDING_E + #endif + ) { + #ifndef WOLFSSL_CALLBACKS ret = SSL_accept(ssl); #else - ret = CyaSSL_accept_ex(ssl, + ret = wolfSSL_accept_ex(ssl, srvHandShakeCB, srvTimeoutCB, srvTo); #endif error = SSL_get_error(ssl, 0); + if (error == WOLFSSL_ERROR_WANT_WRITE) { + /* Do a select here. */ + select_ret = tcp_select_tx(sockfd, 1); + if (select_ret == TEST_TIMEOUT) + error = WOLFSSL_FATAL_ERROR; + } } - else if (select_ret == TEST_TIMEOUT && !CyaSSL_dtls(ssl)) { - error = SSL_ERROR_WANT_READ; + else if (select_ret == TEST_TIMEOUT && !wolfSSL_dtls(ssl)) { + error = WOLFSSL_ERROR_WANT_READ; } -#ifdef CYASSL_DTLS - else if (select_ret == TEST_TIMEOUT && CyaSSL_dtls(ssl) && - CyaSSL_dtls_got_timeout(ssl) >= 0) { - error = SSL_ERROR_WANT_READ; + #ifdef WOLFSSL_DTLS + else if (select_ret == TEST_TIMEOUT && wolfSSL_dtls(ssl) && + wolfSSL_dtls_got_timeout(ssl) >= 0) { + error = WOLFSSL_ERROR_WANT_READ; } -#endif + #endif else { - error = SSL_FATAL_ERROR; + error = WOLFSSL_FATAL_ERROR; } } - if (ret != SSL_SUCCESS) - err_sys("SSL_accept failed"); + + return ret; } +/* Echo number of bytes specified by -e arg */ +int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block, + size_t throughput) +{ + int ret = 0, err; + double start = 0, rx_time = 0, tx_time = 0; + int select_ret, len, rx_pos; + size_t xfer_bytes = 0; + char* buffer; + + buffer = (char*)malloc(block); + 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(block, (int)(throughput - xfer_bytes)); + rx_pos = 0; + + if (throughput) { + start = current_time(1); + } + + /* 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"); + break; + } + } + 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; + } + } + + free(buffer); + + if (throughput) { + #if !defined(__MINGW32__) + printf("wolfSSL Server Benchmark %zu bytes\n" + #else + printf("wolfSSL Server Benchmark %d bytes\n" + #endif + "\tRX %8.3f ms (%8.3f MBps)\n" + "\tTX %8.3f ms (%8.3f MBps)\n", + #if !defined(__MINGW32__) + throughput, + #else + (int)throughput, + #endif + 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[WOLFSSL_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 WOLFSSL_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"); + } + } + else if (SSL_get_error(ssl, 0) == 0 && + tcp_select(SSL_get_fd(ssl), 0) == TEST_RECV_READY) { + err = WOLFSSL_ERROR_WANT_READ; + } + } while (err == WC_PENDING_E || err == WOLFSSL_ERROR_WANT_READ); + 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[WOLFSSL_MAX_ERROR_SZ]; + int len; + +#ifdef OPENSSL_ALL + /* Fuzz testing expects reply split over two msgs when TLSv1.0 or below */ + if (wolfSSL_GetVersion(ssl) <= WOLFSSL_TLSV1) + len = outputLen / 2; + else +#endif + len = outputLen; + + do { + err = 0; /* reset error */ + ret = SSL_write(ssl, output, 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 + } + else if (ret != outputLen) { + output += ret; + len = (outputLen -= ret); + err = WOLFSSL_ERROR_WANT_WRITE; + } + } 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"); + } +} +/* when adding new option, please follow the steps below: */ +/* 1. add new option message in English section */ +/* 2. increase the number of the second column */ +/* 3. add the same message into Japanese section */ +/* (will be translated later) */ +/* 4. add printf() into suitable position of Usage() */ +static const char* server_usage_msg[][49] = { + /* English */ + { + " NOTE: All files relative to wolfSSL home dir\n", /* 0 */ + "-? Help, print this usage\n" + " 0: English, 1: Japanese\n", /* 1 */ + "-p Port to listen on, not 0, default", /* 2 */ +#ifndef WOLFSSL_TLS13 + "-v SSL version [0-3], SSLv3(0) - TLS1.2(3)), default", /* 3 */ +#else + "-v SSL version [0-4], SSLv3(0) - TLS1.3(4)), default", /* 3 */ +#endif + "-l Cipher suite list (: delimited)\n", /* 4 */ + "-c Certificate file, default", /* 5 */ + "-k Key file, default", /* 6 */ + "-A Certificate Authority file, default", /* 7 */ + "-R Create Ready file for external monitor" + " default none\n", /* 8 */ +#ifndef NO_DH + "-D Diffie-Hellman Params file, default", /* 9 */ + "-Z Minimum DH key bits, default", /* 10 */ +#endif +#ifdef HAVE_ALPN + "-L Application-Layer Protocol Negotiation" + " ({C,F}:)\n", /* 11 */ +#endif + "-d Disable client cert check\n", /* 12 */ + "-b Bind to any interface instead of localhost only\n",/* 13 */ + "-s Use pre Shared keys\n", /* 14 */ + "-u Use UDP DTLS," + " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n", /* 15 */ +#ifdef WOLFSSL_SCTP + "-G Use SCTP DTLS," + " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n", /* 16 */ +#endif + "-f Fewer packets/group messages\n", /* 17 */ + "-r Allow one client Resumption\n", /* 18 */ + "-N Use Non-blocking sockets\n", /* 19 */ + "-S Use Host Name Indication\n", /* 20 */ + "-w Wait for bidirectional shutdown\n", /* 21 */ +#ifdef HAVE_OCSP + "-o Perform OCSP lookup on peer certificate\n", /* 22 */ + "-O Perform OCSP lookup using as responder\n", /* 23 */ +#endif +#ifdef HAVE_PK_CALLBACKS + "-P Public Key Callbacks\n", /* 24 */ +#endif +#ifdef HAVE_ANON + "-a Anonymous server\n", /* 25 */ +#endif +#ifndef NO_PSK + "-I Do not send PSK identity hint\n", /* 26 */ +#endif + "-x Print server errors but do not close connection\n",/* 27 */ + "-i Loop indefinitely (allow repeated connections)\n", /* 28 */ + "-e Echo data mode (return raw bytes received)\n", /* 29 */ +#ifdef HAVE_NTRU + "-n Use NTRU key (needed for NTRU suites)\n", /* 30 */ +#endif + "-B Benchmark throughput" + " using bytes and print stats\n", /* 31 */ +#ifdef HAVE_CRL + "-V Disable CRL\n", /* 32 */ +#endif +#ifdef WOLFSSL_TRUST_PEER_CERT + "-E Path to load trusted peer cert\n", /* 33 */ +#endif +#ifdef HAVE_WNR + "-q Whitewood config file, default", /* 34 */ +#endif + "-g Return basic HTML web page\n", /* 35 */ + "-C The number of connections to accept, default: 1\n",/* 36 */ + "-H Internal tests" + " [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 37 */ + " loadSSL, disallowETM]\n", /* 38 */ +#ifdef WOLFSSL_TLS13 + "-U Update keys and IVs before sending\n", /* 39 */ + "-K Key Exchange for PSK not using (EC)DHE\n", /* 40 */ +#ifndef NO_DH + "-y Pre-generate Key Share using FFDHE_2048 only\n", /* 41 */ +#endif +#ifdef HAVE_ECC + "-Y Pre-generate Key Share using P-256 only \n", /* 42 */ +#endif +#ifdef HAVE_CURVE25519 + "-t Pre-generate Key share using Curve25519 only\n", /* 43 */ +#endif +#ifdef HAVE_SESSION_TICKET + "-T Do not generate session ticket\n", /* 44 */ +#endif + "-F Send alert if no mutual authentication\n", /* 45 */ +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + "-Q Request certificate from client post-handshake\n", /* 46 */ +#endif +#ifdef WOLFSSL_SEND_HRR_COOKIE + "-J Server sends Cookie Extension containing state\n", /* 47 */ +#endif +#endif /* WOLFSSL_TLS13 */ +#ifdef WOLFSSL_EARLY_DATA + "-0 Early data read from client (0-RTT handshake)\n", /* 48 */ +#endif +#ifdef WOLFSSL_MULTICAST + "-3 Multicast, grpid < 256\n", /* 49 */ +#endif + "-1 Display a result by specified language." + "\n 0: English, 1: Japanese\n", /* 50 */ +#ifdef HAVE_TRUSTED_CA + "-5 Use Trusted CA Key Indication\n", /* 53 */ +#endif +#ifdef HAVE_CURVE448 + "-8 Pre-generate Key share using Curve448 only\n", /* 55 */ +#endif + NULL, + }, +#ifndef NO_MULTIBYTE_PRINT + /* Japanese */ + { + " 注意 : 全てのファイルは" + " wolfSSL ホーム・ディレクトリからの相対です。\n", /* 0 */ + "-? ヘルプ, 使い方を表示\n" + " 0: 英語、 1: 日本語\n", /* 1 */ + "-p 接続先ポート, 0は無効, 既定値", /* 2 */ +#ifndef WOLFSSL_TLS13 + "-v SSL バージョン [0-3], SSLv3(0) - TLS1.2(3))," + " 既定値", /* 3 */ +#else + "-v SSL バージョン [0-4], SSLv3(0) - TLS1.3(4))," + " 既定値", /* 3 */ +#endif + "-l 暗号スイートリスト (区切り文字 :)\n", /* 4 */ + "-c 証明書ファイル, 既定値", /* 5 */ + "-k 鍵ファイル, 既定値", /* 6 */ + "-A 認証局ファイル, 既定値", /* 7 */ + "-R 外部モニタ用の準備完了ファイルを作成する。" + "既定値 なし\n", /* 8 */ +#ifndef NO_DH + "-D ディフィー・ヘルマンのパラメータファイル," + " 既定値", /* 9 */ + "-Z 最小 DH 鍵 ビット, 既定値", /* 10 */ +#endif +#ifdef HAVE_ALPN + "-L アプリケーション層プロトコルネゴシエーションを行う" + " ({C,F}:)\n", /* 11 */ +#endif + "-d クライアント認証を無効とする\n", /* 12 */ + "-b ローカルホスト以外のインターフェースへも" + "バインドする\n", /* 13 */ + "-s 事前共有鍵を使用する\n", /* 14 */ + "-u UDP DTLSを使用する。-v 2 を追加指定すると" + " DTLSv1, -v 3 を追加指定すると DTLSv1.2 (既定値)\n", /* 15 */ +#ifdef WOLFSSL_SCTP + "-G SCTP DTLSを使用する。-v 2 を追加指定すると" + " DTLSv1, -v 3 を追加指定すると DTLSv1.2 (既定値)\n", /* 16 */ +#endif + "-f より少ないパケット/グループメッセージを使用する\n",/* 17 */ + "-r クライアントの再開を許可する\n", /* 18 */ + "-N ノンブロッキング・ソケットを使用する\n", /* 19 */ + "-S ホスト名表示を使用する\n", /* 20 */ + "-w 双方向シャットダウンを待つ\n", /* 21 */ +#ifdef HAVE_OCSP + "-o OCSPルックアップをピア証明書で実施する\n", /* 22 */ + "-O OCSPルックアップを、" + "を使用し応答者として実施する\n", /* 23 */ +#endif +#ifdef HAVE_PK_CALLBACKS + "-P 公開鍵コールバック\n", /* 24 */ +#endif +#ifdef HAVE_ANON + "-a 匿名サーバー\n", /* 25 */ +#endif +#ifndef NO_PSK + "-I PSKアイデンティティのヒントを送信しない\n", /* 26 */ +#endif + "-x サーバーエラーを出力するが接続を切断しない\n", /* 27 */ + "-i 無期限にループする(繰り返し接続を許可)\n", /* 28 */ + "-e エコー・データモード" + "(受け取ったバイトデータを返す)\n", /* 29 */ +#ifdef HAVE_NTRU + "-n NTRU鍵を使用する(NTRUスイートに必要)\n", /* 30 */ +#endif + "-B バイトを用いてのベンチマーク・スループット" + "測定と結果を出力する\n", /* 31 */ +#ifdef HAVE_CRL + "-V CRLを無効とする\n", /* 32 */ +#endif +#ifdef WOLFSSL_TRUST_PEER_CERT + "-E 信頼出来るピアの証明書ロードの為のパス\n\n", /* 33 */ +#endif +#ifdef HAVE_WNR + "-q Whitewood コンフィグファイル, 既定値", /* 34 */ +#endif + "-g 基本的な Web ページを返す\n", /* 35 */ + "-C アクセプト可能な接続数を指定する。既定値: 1\n", /* 36 */ + "-H 内部テスト" + " [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 37 */ + " loadSSL, disallowETM]\n", /* 38 */ +#ifdef WOLFSSL_TLS13 + "-U データ送信前に、鍵とIVを更新する\n", /* 39 */ + "-K 鍵交換にPSKを使用、(EC)DHEは使用しない\n", /* 40 */ +#ifndef NO_DH + "-y FFDHE_2048のみを使用して鍵共有を事前生成する\n", /* 41 */ +#endif +#ifdef HAVE_ECC + "-Y P-256のみを使用したキー共有の事前生成\n", /* 42 */ +#endif +#ifdef HAVE_CURVE25519 + "-t Curve25519のみを使用して鍵共有を事前生成する\n", /* 43 */ +#endif +#ifdef HAVE_SESSION_TICKET + "-T セッションチケットを生成しない\n", /* 44 */ +#endif + "-F Send alert if no mutual authentication\n", /* 45 */ +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + "-Q クライアントのポストハンドシェイクから" + "証明書を要求する\n", /* 46 */ +#endif +#ifdef WOLFSSL_SEND_HRR_COOKIE + "-J サーバーの状態を含むTLS Cookie 拡張を送信する\n", /* 47 */ +#endif +#endif /* WOLFSSL_TLS13 */ +#ifdef WOLFSSL_EARLY_DATA + "-0 クライアントからの Early Data 読み取り" + "(0-RTTハンドシェイク)\n", /* 48 */ +#endif +#ifdef WOLFSSL_MULTICAST + "-3 マルチキャスト, grpid < 256\n", /* 49 */ +#endif + "-1 指定された言語で結果を表示します。" + "\n 0: 英語、 1: 日本語\n", /* 50 */ +#ifdef HAVE_TRUSTED_CA + "-5 信頼できる認証局の鍵表示を使用する\n", /* 53 */ +#endif +#ifdef HAVE_CURVE448 + "-8 Pre-generate Key share using Curve448 only\n", /* 55 */ +#endif + NULL, + }, +#endif +}; static void Usage(void) { - printf("server " LIBCYASSL_VERSION_STRING - " 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); - printf("-v SSL version [0-3], SSLv3(0) - TLS1.2(3)), default %d\n", - SERVER_DEFAULT_VERSION); - printf("-l Cipher list\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); + int msgId = 0; + const char** msg = server_usage_msg[lng_index]; + + printf("%s%s%s", "server ", LIBWOLFSSL_VERSION_STRING, + msg[msgId]); + printf("%s", msg[++msgId]); /* ? */ + printf("%s %d\n", msg[++msgId], wolfSSLPort); /* -p */ +#ifndef WOLFSSL_TLS13 + printf("%s %d\n", msg[++msgId], SERVER_DEFAULT_VERSION); /* -v */ +#else + printf("%s %d\n", msg[++msgId], SERVER_DEFAULT_VERSION); /* -v */ +#endif + printf("%s", msg[++msgId]); /* -l */ + printf("%s %s\n", msg[++msgId], svrCertFile); /* -c */ + printf("%s %s\n", msg[++msgId], svrKeyFile); /* -k */ + printf("%s %s\n", msg[++msgId], cliCertFile); /* -A */ + printf("%s", msg[++msgId]); /* -R */ #ifndef NO_DH - printf("-D Diffie-Hellman Params file, default %s\n", dhParam); - printf("-Z Minimum DH key bits, default %d\n", - DEFAULT_MIN_DHKEY_BITS); + printf("%s %s\n", msg[++msgId], dhParamFile); /* -D */ + printf("%s %d\n", msg[++msgId], DEFAULT_MIN_DHKEY_BITS);/* -Z */ #endif - 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 (default), -v 3 for DTLSv1.2\n"); - printf("-f Fewer packets/group messages\n"); - printf("-R Create server ready file, for external monitor\n"); - printf("-r Allow one client Resumption\n"); - printf("-N Use Non-blocking sockets\n"); - printf("-S Use Host Name Indication\n"); - printf("-w Wait for bidirectional shutdown\n"); +#ifdef HAVE_ALPN + printf("%s", msg[++msgId]); /* -L */ +#endif + printf("%s", msg[++msgId]); /* -d */ + printf("%s", msg[++msgId]); /* -b */ + printf("%s", msg[++msgId]); /* -s */ + printf("%s", msg[++msgId]); /* -u */ +#ifdef WOLFSSL_SCTP + printf("%s", msg[++msgId]); /* -G */ +#endif + printf("%s", msg[++msgId]); /* -f */ + printf("%s", msg[++msgId]); /* -r */ + printf("%s", msg[++msgId]); /* -N */ + printf("%s", msg[++msgId]); /* -S */ + printf("%s", msg[++msgId]); /* -w */ +#ifdef HAVE_SECURE_RENEGOTIATION + printf("-M Allow Secure Renegotiation\n"); + printf("-m Force Server Initiated Secure Renegotiation\n"); +#endif /* HAVE_SECURE_RENEGOTIATION */ #ifdef HAVE_OCSP - printf("-o Perform OCSP lookup on peer certificate\n"); - printf("-O Perform OCSP lookup using as responder\n"); + printf("%s", msg[++msgId]); /* -o */ + printf("%s", msg[++msgId]); /* -O */ #endif -#ifdef HAVE_PK_CALLBACKS - printf("-P Public Key Callbacks\n"); +#ifdef HAVE_PK_CALLBACKS + printf("%s", msg[++msgId]); /* -P */ #endif #ifdef HAVE_ANON - printf("-a Anonymous server\n"); + printf("%s", msg[++msgId]); /* -a */ +#endif +#ifndef NO_PSK + printf("%s", msg[++msgId]); /* -I */ +#endif + printf("%s", msg[++msgId]); /* -x */ + printf("%s", msg[++msgId]); /* -i */ + printf("%s", msg[++msgId]); /* -e */ +#ifdef HAVE_NTRU + printf("%s", msg[++msgId]); /* -n */ +#endif + printf("%s", msg[++msgId]); /* -B */ +#ifdef HAVE_CRL + printf("%s", msg[++msgId]); /* -V */ +#endif +#ifdef WOLFSSL_TRUST_PEER_CERT + printf("%s", msg[++msgId]); /* -E */ +#endif +#ifdef HAVE_WNR + printf("%s %s\n", msg[++msgId], wnrConfig); /* -q */ +#endif + printf("%s", msg[++msgId]); /* -g */ + printf("%s", msg[++msgId]); /* -C */ + printf("%s", msg[++msgId]); /* -H */ + printf("%s", msg[++msgId]); /* more -H options */ +#ifdef WOLFSSL_TLS13 + printf("%s", msg[++msgId]); /* -U */ + printf("%s", msg[++msgId]); /* -K */ +#ifndef NO_DH + printf("%s", msg[++msgId]); /* -y */ +#endif +#ifdef HAVE_ECC + printf("%s", msg[++msgId]); /* -Y */ +#endif +#ifdef HAVE_CURVE25519 + printf("%s", msg[++msgId]); /* -t */ +#endif +#ifdef HAVE_SESSION_TICKET + printf("%s", msg[++msgId]); /* -T */ +#endif + printf("%s", msg[++msgId]); /* -F */ +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + printf("%s", msg[++msgId]); /* -Q */ +#endif +#ifdef WOLFSSL_SEND_HRR_COOKIE + printf("%s", msg[++msgId]); /* -J */ +#endif +#endif /* WOLFSSL_TLS13 */ +#ifdef WOLFSSL_EARLY_DATA + printf("%s", msg[++msgId]); /* -0 */ +#endif +#if !defined(NO_DH) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK) + printf("-2 Disable DH Prime check\n"); +#endif +#ifdef WOLFSSL_DTLS + printf("-4 DTLS fake would-block for message seq\n"); +#endif +#ifdef WOLFSSL_MULTICAST + printf("%s", msg[++msgId]); /* -3 */ +#endif + printf("%s", msg[++msgId]); /* -1 */ +#ifdef HAVE_TRUSTED_CA + printf("%s", msg[++msgId]); /* -5 */ +#endif /* HAVE_TRUSTED_CA */ +#ifdef HAVE_CURVE448 + printf("%s", msg[++msgId]); /* -8 */ #endif } -THREAD_RETURN CYASSL_THREAD server_test(void* args) +THREAD_RETURN WOLFSSL_THREAD server_test(void* args) { - SOCKET_T sockfd = 0; - SOCKET_T clientfd = 0; + SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; + SOCKET_T clientfd = WOLFSSL_SOCKET_INVALID; - SSL_METHOD* method = 0; + wolfSSL_method_func method = NULL; SSL_CTX* ctx = 0; SSL* ssl = 0; - char msg[] = "I hear you fa shizzle!"; +#ifndef WOLFSSL_ALT_TEST_STRINGS + const char msg[] = "I hear you fa shizzle!"; +#else + const char msg[] = "I hear you fa shizzle!\n"; +#endif + int useWebServerMsg = 0; char input[80]; - int idx; +#ifndef WOLFSSL_VXWORKS int ch; +#endif int version = SERVER_DEFAULT_VERSION; +#ifndef WOLFSSL_NO_CLIENT_AUTH int doCliCertCheck = 1; +#else + int doCliCertCheck = 0; +#endif +#ifdef HAVE_CRL + int disableCRL = 0; +#endif int useAnyAddr = 0; - word16 port = yasslPort; + word16 port = wolfSSLPort; int usePsk = 0; + int usePskPlus = 0; int useAnon = 0; int doDTLS = 0; + int dtlsUDP = 0; + int dtlsSCTP = 0; + int doMcast = 0; +#ifdef WOLFSSL_DTLS + int doBlockSeq = 0; + WOLFSSL_TEST_DTLS_CTX dtlsCtx; +#endif int needDH = 0; int useNtruKey = 0; int nonBlocking = 0; - int trackMemory = 0; int fewerPackets = 0; +#ifdef HAVE_PK_CALLBACKS int pkCallbacks = 0; - int serverReadyFile = 0; + PkCbInfo pkCbInfo; +#endif int wc_shutdown = 0; - int resume = 0; /* do resume, and resume count */ - int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS; + int resume = 0; + int resumeCount = 0; + int loops = 1; + int cnt = 0; + int echoData = 0; + int block = TEST_BUFFER_SIZE; + size_t throughput = 0; + int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS; + short minRsaKeyBits = DEFAULT_MIN_RSAKEY_BITS; + short minEccKeyBits = DEFAULT_MIN_ECCKEY_BITS; + int doListen = 1; + int crlFlags = 0; int ret; + int err = 0; + char* serverReadyFile = NULL; + 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 overrideDateErrors = 0; + const char* verifyCert; + const char* ourCert; + const char* ourKey; + const char* ourDhParam = dhParamFile; + tcp_ready* readySignal = NULL; int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; +#ifdef WOLFSSL_TRUST_PEER_CERT + const char* trustCert = NULL; +#endif + +#ifndef NO_PSK + int sendPskIdentityHint = 1; +#endif + #ifdef HAVE_SNI char* sniHostName = NULL; #endif +#ifdef HAVE_TRUSTED_CA + int trustedCaKeyId = 0; +#endif /* HAVE_TRUSTED_CA */ + #ifdef HAVE_OCSP int useOcsp = 0; char* ocspUrl = NULL; #endif +#ifdef HAVE_WNR + const char* wnrConfigFile = wnrConfig; +#endif + char buffer[WOLFSSL_MAX_ERROR_SZ]; +#ifdef WOLFSSL_TLS13 + int noPskDheKe = 0; +#endif + int updateKeysIVs = 0; + int mutualAuth = 0; + int postHandAuth = 0; +#ifdef WOLFSSL_EARLY_DATA + int earlyData = 0; +#endif +#ifdef HAVE_SECURE_RENEGOTIATION + int scr = 0; + int forceScr = 0; +#endif /* HAVE_SECURE_RENEGOTIATION */ +#ifdef WOLFSSL_SEND_HRR_COOKIE + int hrrCookie = 0; +#endif + byte mcastID = 0; +#if !defined(NO_DH) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK) + int doDhKeyCheck = 1; +#endif + +#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[204000]; + #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 +#ifdef WOLFSSL_TLS13 + int onlyKeyShare = 0; + int noTicket = 0; +#endif + int useX25519 = 0; + int useX448 = 0; + int exitWithRet = 0; + int loadCertKeyIntoSSLObj = 0; + +#ifdef HAVE_ENCRYPT_THEN_MAC + int disallowETM = 0; +#endif + ((func_args*)args)->return_code = -1; /* error state */ -#ifdef NO_RSA - verifyCert = (char*)cliEccCert; - ourCert = (char*)eccCert; - ourKey = (char*)eccKey; +#ifndef NO_RSA + verifyCert = cliCertFile; + ourCert = svrCertFile; + ourKey = svrKeyFile; +#else + #ifdef HAVE_ECC + verifyCert = cliEccCertFile; + ourCert = eccCertFile; + ourKey = eccKeyFile; + #elif defined(HAVE_ED25519) + verifyCert = cliEdCertFile; + ourCert = edCertFile; + ourKey = edKeyFile; + #elif defined(HAVE_ED448) + verifyCert = cliEd448CertFile; + ourCert = ed448CertFile; + ourKey = ed448KeyFile; + #else + verifyCert = NULL; + ourCert = NULL; + ourKey = NULL; + #endif #endif - (void)trackMemory; - (void)pkCallbacks; + (void)needDH; (void)ourKey; (void)ourCert; @@ -225,22 +1074,57 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) (void)useNtruKey; (void)doCliCertCheck; (void)minDhKeyBits; + (void)minRsaKeyBits; + (void)minEccKeyBits; + (void)alpnList; + (void)alpn_opt; + (void)crlFlags; + (void)readySignal; + (void)updateKeysIVs; + (void)mutualAuth; + (void)postHandAuth; + (void)mcastID; + (void)loadCertKeyIntoSSLObj; + (void)overrideDateErrors; + (void)nonBlocking; -#ifdef CYASSL_TIRTOS +#ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif - while ((ch = mygetopt(argc, argv, "?dbstnNufrRawPp:v:l:A:c:k:Z:S:oO:D:")) - != -1) { +#ifdef WOLFSSL_VXWORKS + useAnyAddr = 1; +#else + /* Not Used: h, z, F, T, V, W, X */ + while ((ch = mygetopt(argc, argv, "?:" + "abc:defgijk:l:mnop:q:rstuv:wxy" + "A:B:C:D:E:FGH:IJKL:MNO:PQR:S:TUVYZ:" + "01:23:4:58")) != -1) { switch (ch) { case '?' : + if(myoptarg!=NULL) { + lng_index = atoi(myoptarg); + if(lng_index<0||lng_index>1){ + lng_index = 0; + } + } Usage(); - exit(EXIT_SUCCESS); + XEXIT_T(EXIT_SUCCESS); + + case 'x' : + runWithErrors = 1; + break; case 'd' : doCliCertCheck = 0; break; + case 'V' : + #ifdef HAVE_CRL + disableCRL = 1; + #endif + break; + case 'b' : useAnyAddr = 1; break; @@ -249,10 +1133,8 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) usePsk = 1; break; - case 't' : - #ifdef USE_WOLFSSL_MEMORY - trackMemory = 1; - #endif + case 'j' : + usePskPlus = 1; break; case 'n' : @@ -261,6 +1143,14 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) case 'u' : doDTLS = 1; + dtlsUDP = 1; + break; + + case 'G' : + #ifdef WOLFSSL_SCTP + doDTLS = 1; + dtlsSCTP = 1; + #endif break; case 'f' : @@ -268,7 +1158,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) break; case 'R' : - serverReadyFile = 1; + serverReadyFile = myoptarg; break; case 'r' : @@ -278,17 +1168,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) break; case 'P' : - #ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_PK_CALLBACKS pkCallbacks = 1; #endif break; case 'p' : port = (word16)atoi(myoptarg); - #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API) - if (port == 0) - err_sys("port number cannot be 0"); - #endif break; case 'w' : @@ -296,10 +1182,23 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) break; case 'v' : + if (myoptarg[0] == 'd') { + version = SERVER_DOWNGRADE_VERSION; + break; + } + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + else if (myoptarg[0] == 'e') { + version = EITHER_DOWNGRADE_VERSION; + #ifndef NO_CERTS + loadCertKeyIntoSSLObj = 1; + #endif + break; + } + #endif version = atoi(myoptarg); - if (version < 0 || version > 3) { + if (version < 0 || version > 4) { Usage(); - exit(MY_EX_USAGE); + XEXIT_T(MY_EX_USAGE); } break; @@ -307,6 +1206,48 @@ 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, "exitWithRet", 11) == 0) { + printf("Skip exit() for testing\n"); + exitWithRet = 1; + } + else if (XSTRNCMP(myoptarg, "verifyFail", 10) == 0) { + printf("Verify should fail\n"); + myVerifyFail = 1; + } + else if (XSTRNCMP(myoptarg, "loadSSL", 7) == 0) { + printf("Also load cert/key into wolfSSL object\n"); + #ifndef NO_CERTS + loadCertKeyIntoSSLObj = 2; + #endif + } + else if (XSTRNCMP(myoptarg, "loadSSLOnly", 11) == 0) { + printf("Only load cert/key into wolfSSL object\n"); + #ifndef NO_CERTS + loadCertKeyIntoSSLObj = 1; + #endif + } + else if (XSTRNCMP(myoptarg, "disallowETM", 11) == 0) { + printf("Disallow Encrypt-Then-MAC\n"); + #ifdef HAVE_ENCRYPT_THEN_MAC + disallowETM = 1; + #endif + } + else if (XSTRNCMP(myoptarg, "overrideDateErr", 15) == 0) { + #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) + overrideDateErrors = 1; + #endif + } + else { + Usage(); + XEXIT_T(MY_EX_USAGE); + } + break; + case 'A' : verifyCert = myoptarg; break; @@ -330,7 +1271,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) minDhKeyBits = atoi(myoptarg); if (minDhKeyBits <= 0 || minDhKeyBits > 16000) { Usage(); - exit(MY_EX_USAGE); + XEXIT_T(MY_EX_USAGE); } #endif break; @@ -363,14 +1304,208 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) useAnon = 1; #endif break; + case 'I': + #ifndef NO_PSK + sendPskIdentityHint = 0; + #endif + break; + + case 'L' : + #ifdef HAVE_ALPN + alpnList = myoptarg; + + if (alpnList[0] == 'C' && alpnList[1] == ':') + alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH; + else if (alpnList[0] == 'F' && alpnList[1] == ':') + alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH; + else { + Usage(); + XEXIT_T(MY_EX_USAGE); + } + + alpnList += 2; + + #endif + break; + + case 'i' : + loops = -1; + break; + + case 'C' : + loops = atoi(myoptarg); + if (loops <= 0) { + Usage(); + XEXIT_T(MY_EX_USAGE); + } + break; + + case 'e' : + echoData = 1; + break; + + case 'B': + throughput = atol(myoptarg); + for (; *myoptarg != '\0'; myoptarg++) { + if (*myoptarg == ',') { + block = atoi(myoptarg + 1); + break; + } + } + if (throughput == 0 || block <= 0) { + Usage(); + XEXIT_T(MY_EX_USAGE); + } + break; + + #ifdef WOLFSSL_TRUST_PEER_CERT + case 'E' : + trustCert = myoptarg; + break; + #endif + + case 'q' : + #ifdef HAVE_WNR + wnrConfigFile = myoptarg; + #endif + break; + + case 'g' : + useWebServerMsg = 1; + 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 't' : + #ifdef HAVE_CURVE25519 + useX25519 = 1; + #if defined(WOLFSSL_TLS13) && defined(HAVE_ECC) + onlyKeyShare = 2; + #endif + #endif + break; + + case 'K' : + #ifdef WOLFSSL_TLS13 + noPskDheKe = 1; + #endif + break; + + case 'T' : + #if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + noTicket = 1; + #endif + break; + + case 'U' : + #ifdef WOLFSSL_TLS13 + updateKeysIVs = 1; + #endif + break; + + case 'F' : + mutualAuth = 1; + 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 'M' : + #ifdef HAVE_SECURE_RENEGOTIATION + scr = 1; + #endif /* HAVE_SECURE_RENEGOTIATION */ + break; + + case 'm' : + #ifdef HAVE_SECURE_RENEGOTIATION + scr = 1; + forceScr = 1; + #endif /* HAVE_SECURE_RENEGOTIATION */ + break; + + case '0' : + #ifdef WOLFSSL_EARLY_DATA + earlyData = 1; + #endif + break; + + case '1' : + lng_index = atoi(myoptarg); + if(lng_index<0||lng_index>1){ + lng_index = 0; + } + break; + + case '2' : + #if !defined(NO_DH) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK) + doDhKeyCheck = 0; + #endif + break; + + case '3' : + #ifdef WOLFSSL_MULTICAST + doMcast = 1; + mcastID = (byte)(atoi(myoptarg) & 0xFF); + #endif + break; + + case '4' : + #ifdef WOLFSSL_DTLS + XMEMSET(&dtlsCtx, 0, sizeof(dtlsCtx)); + doBlockSeq = 1; + dtlsCtx.blockSeq = atoi(myoptarg); + #endif + break; + + case '5' : + #ifdef HAVE_TRUSTED_CA + trustedCaKeyId = 1; + #endif /* HAVE_TRUSTED_CA */ + break; + + case '8' : + #ifdef HAVE_CURVE448 + useX448 = 1; + #if defined(WOLFSSL_TLS13) && defined(HAVE_ECC) + onlyKeyShare = 2; + #endif + #endif + break; default: Usage(); - exit(MY_EX_USAGE); + XEXIT_T(MY_EX_USAGE); } } myoptind = 0; /* reset for test cases */ +#endif /* !WOLFSSL_VXWORKS */ + + /* Can only use DTLS over UDP or SCTP, can't do both. */ + if (dtlsUDP && dtlsSCTP) { + err_sys_ex(runWithErrors, "Cannot use DTLS with both UDP and SCTP."); + } /* sort out DTLS versus TLS versions */ if (version == CLIENT_INVALID_VERSION) { @@ -383,305 +1518,979 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if (doDTLS) { if (version == 3) version = -2; + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + else if (version == EITHER_DOWNGRADE_VERSION) + version = -3; + #endif else version = -1; } } -#ifdef USE_CYASSL_MEMORY - if (trackMemory) - InitMemoryTracker(); +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) + err_sys_ex(runWithErrors, "can't load whitewood net random config " + "file"); #endif switch (version) { #ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_SSLV3 case 0: - method = SSLv3_server_method(); - break; - - #ifndef NO_TLS - case 1: - method = TLSv1_server_method(); - break; - - - case 2: - method = TLSv1_1_server_method(); - break; - - #endif -#endif - -#ifndef NO_TLS - case 3: - method = TLSv1_2_server_method(); - break; -#endif - -#ifdef CYASSL_DTLS - #ifndef NO_OLD_TLS - case -1: - method = DTLSv1_server_method(); + method = wolfSSLv3_server_method_ex; break; #endif - case -2: - method = DTLSv1_2_server_method(); + #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 /* !NO_TLS */ +#endif /* !NO_OLD_TLS */ + +#ifndef NO_TLS + #ifndef WOLFSSL_NO_TLS12 + case 3: + method = wolfTLSv1_2_server_method_ex; + break; + #endif + + #ifdef WOLFSSL_TLS13 + case 4: + method = wolfTLSv1_3_server_method_ex; + break; + #endif + + case SERVER_DOWNGRADE_VERSION: + method = wolfSSLv23_server_method_ex; + break; + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + case EITHER_DOWNGRADE_VERSION: + method = wolfSSLv23_method_ex; + break; + #endif +#endif /* NO_TLS */ + +#ifdef WOLFSSL_DTLS + #ifndef NO_OLD_TLS + case -1: + method = wolfDTLSv1_server_method_ex; + break; + #endif + + #ifndef WOLFSSL_NO_TLS12 + case -2: + method = wolfDTLSv1_2_server_method_ex; + break; + #endif + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + case -3: + method = wolfDTLSv1_2_method_ex; + break; + #endif #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"); - ctx = SSL_CTX_new(method); +#ifdef WOLFSSL_STATIC_MEMORY + #ifdef DEBUG_WOLFSSL + /* print off helper buffer sizes for use with static memory + * printing to stderr in case 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_ex(catastrophic, "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) + != WOLFSSL_SUCCESS) + err_sys_ex(catastrophic, "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(catastrophic, "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(catastrophic, "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 custom cipher list"); + } -#ifdef CYASSL_LEANPSK - usePsk = 1; +#ifdef WOLFSSL_LEANPSK + if (!usePsk) { + usePsk = 1; + } #endif -#if defined(NO_RSA) && !defined(HAVE_ECC) - usePsk = 1; +#if defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ + !defined(HAVE_ED448) + if (!usePsk) { + usePsk = 1; + } #endif if (fewerPackets) - CyaSSL_CTX_set_group_messages(ctx); + wolfSSL_CTX_set_group_messages(ctx); -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +#ifdef WOLFSSL_SCTP + if (dtlsSCTP) + wolfSSL_CTX_dtls_set_sctp(ctx); +#endif + +#ifdef WOLFSSL_ENCRYPTED_KEYS SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif -#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) - if (!usePsk && !useAnon) { - if (SSL_CTX_use_certificate_file(ctx, ourCert, SSL_FILETYPE_PEM) - != SSL_SUCCESS) - err_sys("can't load server cert file, check file and run from" - " wolfSSL home dir"); +#if !defined(NO_CERTS) + if ((!usePsk || usePskPlus) && !useAnon && !(loadCertKeyIntoSSLObj == 1)) { + #ifndef TEST_LOAD_BUFFER + if (SSL_CTX_use_certificate_chain_file(ctx, ourCert) + != WOLFSSL_SUCCESS) + err_sys_ex(catastrophic, "can't load server cert file, check file " + "and run from wolfSSL home dir"); + #else + /* loads cert chain file using buffer API */ + load_buffer(ctx, ourCert, WOLFSSL_CERT_CHAIN); + #endif } #endif #ifndef NO_DH - wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits); + 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) != WOLFSSL_SUCCESS){ + err_sys_ex(runWithErrors, "Error setting minimum RSA key size"); + } +#endif +#ifdef HAVE_ECC + 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, " + if (wolfSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey) + != WOLFSSL_SUCCESS) + err_sys_ex(catastrophic, "can't load ntru key file, " "Please run from wolfSSL home dir"); } #endif - -#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) - if (!useNtruKey && !usePsk && !useAnon) { - 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 " - "from wolfSSL home dir"); +#if !defined(NO_CERTS) + #ifdef HAVE_PK_CALLBACKS + pkCbInfo.ourKey = ourKey; + #endif + if (!useNtruKey && (!usePsk || usePskPlus) && !useAnon + && !(loadCertKeyIntoSSLObj == 1) + #if defined(HAVE_PK_CALLBACKS) && defined(TEST_PK_PRIVKEY) + && !pkCallbacks + #endif /* HAVE_PK_CALLBACKS && TEST_PK_PRIVKEY */ + ) { + #ifndef TEST_LOAD_BUFFER + if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) + err_sys_ex(catastrophic, "can't load server private key file, " + "check file and run from wolfSSL home dir"); + #else + /* loads private key file using buffer API */ + load_buffer(ctx, ourKey, WOLFSSL_KEY); + #endif } #endif - if (usePsk) { + if (usePsk || usePskPlus) { #ifndef NO_PSK SSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb); - SSL_CTX_use_psk_identity_hint(ctx, "cyassl server"); - if (cipherList == NULL) { + #ifdef WOLFSSL_TLS13 + wolfSSL_CTX_set_psk_server_tls13_callback(ctx, my_psk_server_tls13_cb); + #endif + + if (sendPskIdentityHint == 1) + SSL_CTX_use_psk_identity_hint(ctx, "cyassl server"); + + 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 } +#ifndef NO_CERTS + if (mutualAuth) + wolfSSL_CTX_mutual_auth(ctx, 1); +#endif + + +#ifdef HAVE_ECC + /* Use ECDHE key size that matches long term key. + * Zero means use ctx->privateKeySz. + * Default ECDHE_SIZE is 32 bytes + */ + if (wolfSSL_CTX_SetTmpEC_DHE_Sz(ctx, 0) != WOLFSSL_SUCCESS){ + err_sys_ex(runWithErrors, "Error setting ECDHE size"); + } +#endif 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"); + wolfSSL_CTX_allow_anon_cipher(ctx); + if (cipherList == NULL || (cipherList && useDefCipherList)) { + const char* defaultCipherList; + defaultCipherList = "ADH-AES256-GCM-SHA384:" + "ADH-AES128-SHA"; + if (SSL_CTX_set_cipher_list(ctx, defaultCipherList) + != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "server can't set cipher list 4"); } #endif } #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) - /* if not using PSK, verify peer with certs */ - if (doCliCertCheck && usePsk == 0 && useAnon == 0) { - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | - 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"); - } + /* 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) { + unsigned int verify_flags = 0; + SSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER | + (usePskPlus ? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK : + WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), + overrideDateErrors == 1 ? myDateCb : NULL); + + #ifdef TEST_BEFORE_DATE + verify_flags |= WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY; + #endif + + if (wolfSSL_CTX_load_verify_locations_ex(ctx, verifyCert, 0, + verify_flags) != WOLFSSL_SUCCESS) { + err_sys_ex(catastrophic, + "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, + WOLFSSL_FILETYPE_PEM)) + != WOLFSSL_SUCCESS) { + err_sys_ex(runWithErrors, "can't load trusted peer cert file"); + } + } + #endif /* WOLFSSL_TRUST_PEER_CERT */ + } #endif -#if defined(CYASSL_SNIFFER) +#if defined(WOLFSSL_SNIFFER) /* don't use EDH, can't sniff tmp keys */ if (cipherList == NULL) { - if (SSL_CTX_set_cipher_list(ctx, "AES256-SHA256") != 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"); + if (wolfSSL_CTX_UseSNI(ctx, WOLFSSL_SNI_HOST_NAME, sniHostName, + (word16) XSTRLEN(sniHostName)) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "UseSNI failed"); #endif -while (1) { /* allow resume option */ - if (resume > 1) { /* already did listen, just do accept */ - if (doDTLS == 0) { - SOCKADDR_IN_T client; - socklen_t client_len = sizeof(client); - clientfd = accept(sockfd, (struct sockaddr*)&client, - (ACCEPT_THIRD_T)&client_len); - } else { - tcp_listen(&sockfd, &port, useAnyAddr, doDTLS); - clientfd = udp_read_connect(sockfd); +#ifdef USE_WINDOWS_API + if (port == 0) { + /* Generate random port for testing */ + port = GetRandomPort(); + } +#endif /* USE_WINDOWS_API */ + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevOpen(&devId); + 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); + if (noTicket) + wolfSSL_CTX_no_ticket_TLSv13(ctx); +#endif + + while (1) { + /* allow resume option */ + 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 { + tcp_listen(&sockfd, &port, useAnyAddr, dtlsUDP, dtlsSCTP); + clientfd = sockfd; + } + if (WOLFSSL_SOCKET_IS_INVALID(clientfd)) { + err_sys_ex(runWithErrors, "tcp accept failed"); + } } - #ifdef USE_WINDOWS_API - if (clientfd == INVALID_SOCKET) err_sys("tcp accept failed"); - #else - if (clientfd == -1) err_sys("tcp accept failed"); - #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_ex(runWithErrors, "ctx not using static memory"); + if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */ + 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"); + if (doDTLS && dtlsUDP) { +#ifdef WOLFSSL_DTLS + if (doBlockSeq) { + wolfSSL_CTX_SetIOSend(ctx, TestEmbedSendTo); + } +#endif + } + +#ifdef HAVE_PK_CALLBACKS + if (pkCallbacks) + SetupPkCallbacks(ctx); +#endif + + ssl = SSL_new(ctx); + if (ssl == NULL) + err_sys_ex(catastrophic, "unable to create an SSL object"); + #ifdef OPENSSL_EXTRA + wolfSSL_KeepArrays(ssl); + #endif + + /* Support for loading private key and cert using WOLFSSL object */ +#if !defined(NO_CERTS) + if ((!usePsk || usePskPlus) && !useAnon && loadCertKeyIntoSSLObj) { + #ifndef TEST_LOAD_BUFFER + if (SSL_use_certificate_chain_file(ssl, ourCert) + != WOLFSSL_SUCCESS) + err_sys_ex(catastrophic, "can't load server cert file, check file " + "and run from wolfSSL home dir"); + #else + /* loads cert chain file using buffer API */ + load_ssl_buffer(ssl, ourCert, WOLFSSL_CERT_CHAIN); + #endif + } + + if (!useNtruKey && (!usePsk || usePskPlus) && !useAnon && + loadCertKeyIntoSSLObj + #if defined(HAVE_PK_CALLBACKS) && defined(TEST_PK_PRIVKEY) + && !pkCallbacks + #endif /* HAVE_PK_CALLBACKS && TEST_PK_PRIVKEY */ + ) { + #ifndef TEST_LOAD_BUFFER + if (SSL_use_PrivateKey_file(ssl, ourKey, WOLFSSL_FILETYPE_PEM) + != WOLFSSL_SUCCESS) + err_sys_ex(catastrophic, "can't load server private key file, check" + "file and run from wolfSSL home dir"); + #else + /* loads private key file using buffer API */ + load_ssl_buffer(ssl, ourKey, WOLFSSL_KEY); + #endif + } +#endif /* !NO_CERTS */ + +#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) + fprintf(stderr, "After creating SSL\n"); + if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1) + err_sys_ex(runWithErrors, "ctx not using static memory"); + if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */ + 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 + } + +#ifdef HAVE_SECURE_RENEGOTIATION + if (scr) { + if (wolfSSL_UseSecureRenegotiation(ssl) != WOLFSSL_SUCCESS) { + err_sys_ex(runWithErrors, "can't enable secure renegotiation"); + } + } +#endif /* HAVE_SECURE_RENEGOTIATION */ #ifndef NO_HANDSHAKE_DONE_CB - wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL); + wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL); #endif #ifdef HAVE_CRL - CyaSSL_EnableCRL(ssl, 0); - CyaSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, CYASSL_CRL_MONITOR | - CYASSL_CRL_START_MON); - CyaSSL_SetCRL_Cb(ssl, CRL_CallBack); + if (!disableCRL) { +#ifdef HAVE_CRL_MONITOR + crlFlags = WOLFSSL_CRL_MONITOR | WOLFSSL_CRL_START_MON; +#endif + if (wolfSSL_EnableCRL(ssl, 0) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "unable to enable CRL"); + if (wolfSSL_LoadCRL(ssl, crlPemDir, WOLFSSL_FILETYPE_PEM, crlFlags) + != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "unable to load CRL"); + if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != WOLFSSL_SUCCESS) + err_sys_ex(runWithErrors, "unable to set CRL callback url"); + } #endif #ifdef HAVE_OCSP - if (useOcsp) { - if (ocspUrl != NULL) { - CyaSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl); - CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE - | CYASSL_OCSP_URL_OVERRIDE); + if (useOcsp) { + 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, WOLFSSL_OCSP_NO_NONCE); } - else - CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE); - } -#endif +#ifndef NO_RSA + /* All the OSCP Stapling test certs are RSA. */ +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + { /* scope start */ + const char* ca1 = "certs/ocsp/intermediate1-ca-cert.pem"; + const char* ca2 = "certs/ocsp/intermediate2-ca-cert.pem"; + const char* ca3 = "certs/ocsp/intermediate3-ca-cert.pem"; + int fails = 0; + + if (wolfSSL_CTX_EnableOCSPStapling(ctx) != WOLFSSL_SUCCESS) { + err_sys_ex(catastrophic, "can't enable OCSP Stapling " + "Certificate Manager"); + } + if (SSL_CTX_load_verify_locations(ctx, ca1, 0) != WOLFSSL_SUCCESS) { + fails++; + err_sys_ex(runWithErrors, "can't load ca file, Please run from " + "wolfSSL home dir"); + } + if (SSL_CTX_load_verify_locations(ctx, ca2, 0) != WOLFSSL_SUCCESS) { + fails++; + err_sys_ex(runWithErrors, "can't load ca file, Please run from " + "wolfSSL home dir"); + } + if (SSL_CTX_load_verify_locations(ctx, ca3, 0) != WOLFSSL_SUCCESS) { + fails++; + err_sys_ex(runWithErrors, "can't load ca file, Please run from " + "wolfSSL home dir"); + } + if (fails > 2) { + err_sys_ex(catastrophic, "Failed to load any intermediates for " + "OCSP stapling test"); + } + } /* scope end */ +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ +#endif /* NO_RSA */ +#endif /* HAVE_OCSP */ + #ifdef HAVE_PK_CALLBACKS - if (pkCallbacks) - SetupPkCallbacks(ctx, ssl); + if (pkCallbacks) + SetupPkCallbackContexts(ssl, &pkCbInfo); #endif - if (resume < 2) { /* do listen and accept */ - tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr, - doDTLS, serverReadyFile); - } + #ifdef WOLFSSL_TLS13 + if (version >= 4) { + WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); + if (onlyKeyShare == 2) { + if (useX25519 == 1) { + #ifdef HAVE_CURVE25519 + int groups[1] = { WOLFSSL_ECC_X25519 }; - SSL_set_fd(ssl, clientfd); - if (usePsk == 0 || useAnon == 1 || cipherList != NULL || needDH == 1) { - #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN) - CyaSSL_SetTmpDH_file(ssl, ourDhParam, SSL_FILETYPE_PEM); - #elif !defined(NO_DH) - SetDH(ssl); /* repick suites with DHE, higher priority than PSK */ + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve x25519"); + } + if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { + err_sys("unable to set groups: x25519"); + } #endif - } + } + else if (useX448 == 1) { + #ifdef HAVE_CURVE448 + int groups[1] = { WOLFSSL_ECC_X448 }; -#ifndef CYASSL_CALLBACKS - if (nonBlocking) { - CyaSSL_set_using_nonblock(ssl, 1); - tcp_set_nonblocking(&clientfd); - NonBlockingSSL_Accept(ssl); - } else if (SSL_accept(ssl) != SSL_SUCCESS) { - int err = SSL_get_error(ssl, 0); - char buffer[CYASSL_MAX_ERROR_SZ]; - printf("error = %d, %s\n", err, ERR_error_string(err, buffer)); - err_sys("SSL_accept failed"); - } -#else - NonBlockingSSL_Accept(ssl); -#endif - showPeer(ssl); + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve x448"); + } + if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { + err_sys("unable to set groups: x448"); + } + #endif + } + else { + #ifdef HAVE_ECC + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + int groups[1] = { WOLFSSL_ECC_SECP256R1 }; - idx = SSL_read(ssl, input, sizeof(input)-1); - if (idx > 0) { - input[idx] = 0; - printf("Client message: %s\n", input); + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) + != WOLFSSL_SUCCESS) { + err_sys("unable to use curve secp256r1"); + } + if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { + err_sys("unable to set groups: secp256r1"); + } + #endif + #endif + } + } + else if (onlyKeyShare == 1) { + #ifdef HAVE_FFDHE_2048 + int groups[1] = { WOLFSSL_FFDHE_2048 }; - } - else if (idx < 0) { - int readErr = SSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) - err_sys("SSL_read failed"); - } - - if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) - err_sys("SSL_write failed"); - - #if defined(CYASSL_MDK_SHELL) && defined(HAVE_MDK_RTX) - os_dly_wait(500) ; - #elif defined (CYASSL_TIRTOS) - Task_yield(); + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) + != WOLFSSL_SUCCESS) { + err_sys("unable to use DH 2048-bit parameters"); + } + if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { + err_sys("unable to set groups: DH 2048-bit"); + } + #endif + } + WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); + } #endif - if (doDTLS == 0) { - ret = SSL_shutdown(ssl); - if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) - SSL_shutdown(ssl); /* bidirectional shutdown */ - } - SSL_free(ssl); - if (resume == 1) { - CloseSocket(clientfd); - resume++; /* only do one resume for testing */ - continue; - } - break; /* out of while loop, done with normal and resume option */ -} - SSL_CTX_free(ctx); + #ifdef HAVE_ENCRYPT_THEN_MAC + if (disallowETM) + wolfSSL_AllowEncryptThenMac(ssl, 0); + #endif + + + /* do accept */ + readySignal = ((func_args*)args)->signal; + if (readySignal) { + readySignal->srfName = serverReadyFile; + } + tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr, + dtlsUDP, dtlsSCTP, serverReadyFile ? 1 : 0, doListen); + doListen = 0; /* Don't listen next time */ + + if (SSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) { + err_sys_ex(catastrophic, "error in setting fd"); + } + +#ifdef HAVE_TRUSTED_CA + if (trustedCaKeyId) { + if (wolfSSL_UseTrustedCA(ssl, WOLFSSL_TRUSTED_CA_PRE_AGREED, + NULL, 0) != WOLFSSL_SUCCESS) { + err_sys_ex(runWithErrors, "UseTrustedCA failed"); + } + } +#endif /* HAVE_TRUSTED_CA */ + +#ifdef HAVE_ALPN + if (alpnList != NULL) { + printf("ALPN accepted protocols list : %s\n", alpnList); + wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt); + } +#endif + +#ifdef WOLFSSL_DTLS + if (doDTLS && dtlsUDP) { + SOCKADDR_IN_T cliaddr; + byte b[1500]; + int n; + socklen_t len = sizeof(cliaddr); + + /* For DTLS, peek at the next datagram so we can get the client's + * address and set it into the ssl object later to generate the + * cookie. */ + n = (int)recvfrom(clientfd, (char*)b, sizeof(b), MSG_PEEK, + (struct sockaddr*)&cliaddr, &len); + if (n <= 0) + err_sys_ex(runWithErrors, "recvfrom failed"); + + if (doBlockSeq) { + XMEMCPY(&dtlsCtx.peer.sa, &cliaddr, len); + dtlsCtx.peer.sz = len; + dtlsCtx.wfd = clientfd; + dtlsCtx.failOnce = 1; + + wolfSSL_SetIOWriteCtx(ssl, &dtlsCtx); + } + else { + wolfSSL_dtls_set_peer(ssl, &cliaddr, len); + } + } +#endif + if ((usePsk == 0 || usePskPlus) || useAnon == 1 || cipherList != NULL + || needDH == 1) { + #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN) + wolfSSL_SetTmpDH_file(ssl, ourDhParam, WOLFSSL_FILETYPE_PEM); + #elif !defined(NO_DH) + SetDH(ssl); /* repick suites with DHE, higher priority than + * PSK */ + #endif +#if !defined(NO_DH) && !defined(WOLFSSL_OLD_PRIME_CHECK) && \ + !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + if (!doDhKeyCheck) + wolfSSL_SetEnableDhKeyTest(ssl, 0); +#endif + } + +#ifndef WOLFSSL_CALLBACKS + if (nonBlocking) { + #ifdef WOLFSSL_DTLS + if (doDTLS) { + wolfSSL_dtls_set_using_nonblock(ssl, 1); + } + #endif + tcp_set_nonblocking(&clientfd); + + ret = NonBlockingSSL_Accept(ssl); + } + 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); + } + #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("SSL_accept error %d, %s\n", err, + ERR_error_string(err, buffer)); + if (!exitWithRet) { + err_sys_ex(runWithErrors, "SSL_accept failed"); + } else { + /* cleanup */ + SSL_free(ssl); ssl = NULL; + SSL_CTX_free(ctx); ctx = NULL; + CloseSocket(clientfd); + CloseSocket(sockfd); + ((func_args*)args)->return_code = err; + goto exit; + } + } + + showPeerEx(ssl, lng_index); + if (SSL_state(ssl) != 0) { + err_sys_ex(runWithErrors, "SSL in error state"); + } + +#ifdef OPENSSL_EXTRA + { + byte* rnd; + byte* pt; + size_t size; + + /* get size of buffer then print */ + size = wolfSSL_get_server_random(NULL, NULL, 0); + if (size == 0) { + err_sys_ex(runWithErrors, "error getting server random buffer " + "size"); + } + + rnd = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (rnd == NULL) { + err_sys_ex(runWithErrors, "error creating server random buffer"); + } + + size = wolfSSL_get_server_random(ssl, rnd, size); + if (size == 0) { + if (rnd) { + XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + rnd = NULL; + } + err_sys_ex(runWithErrors, "error getting server random buffer"); + } + + if (rnd) { + printf("Server Random : "); + for (pt = rnd; pt < rnd + size; pt++) printf("%02X", *pt); + printf("\n"); + + XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + rnd = NULL; + } + } +#endif + +#ifdef HAVE_ALPN + if (alpnList != NULL) { + char *protocol_name = NULL, *list = NULL; + word16 protocol_nameSz = 0, listSz = 0; + + err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, + &protocol_nameSz); + if (err == WOLFSSL_SUCCESS) + printf("Sent ALPN protocol : %s (%d)\n", + protocol_name, protocol_nameSz); + 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 == WOLFSSL_SUCCESS) + printf("List of protocol names sent by Client: %s (%d)\n", + list, listSz); + else + printf("Get list of client's protocol name failed\n"); + + free(list); + } +#endif + +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) + #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (postHandAuth) { + unsigned int verify_flags = 0; + + SSL_set_verify(ssl, WOLFSSL_VERIFY_PEER | + ((usePskPlus) ? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK : + WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), 0); + + #ifdef TEST_BEFORE_DATE + verify_flags |= WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY; + #endif + + if (wolfSSL_CTX_load_verify_locations_ex(ctx, verifyCert, 0, + verify_flags) + != 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_trust_peer_cert(ssl, 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 (echoData == 0 && throughput == 0) { + ServerRead(ssl, input, sizeof(input)-1); + err = SSL_get_error(ssl, 0); + } + +#if defined(HAVE_SECURE_RENEGOTIATION) && \ + defined(HAVE_SERVER_RENEGOTIATION_INFO) + if (scr && forceScr) { + if (nonBlocking) { + printf("not doing secure renegotiation on example with" + " nonblocking yet\n"); + } else { + if (wolfSSL_Rehandshake(ssl) != WOLFSSL_SUCCESS) { + printf("not doing secure renegotiation\n"); + } + else { + printf("RENEGOTIATION SUCCESSFUL\n"); + } + } + } +#endif /* HAVE_SECURE_RENEGOTIATION */ + + if (err == 0 && echoData == 0 && throughput == 0) { + const char* write_msg; + int write_msg_sz; + +#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); + +#ifdef WOLFSSL_TLS13 + if (updateKeysIVs || postHandAuth) + ServerRead(ssl, input, sizeof(input)-1); +#endif + } + else if (err == 0 || err == WOLFSSL_ERROR_ZERO_RETURN) { + ServerEchoData(ssl, clientfd, echoData, block, throughput); + } + +#if defined(WOLFSSL_MDK_SHELL) && defined(HAVE_MDK_RTX) + os_dly_wait(500) ; +#elif defined (WOLFSSL_TIRTOS) + Task_yield(); +#endif + + if (dtlsUDP == 0) { + ret = SSL_shutdown(ssl); + if (wc_shutdown && ret == WOLFSSL_SHUTDOWN_NOT_DONE) { + ret = SSL_shutdown(ssl); /* bidirectional shutdown */ + if (ret == WOLFSSL_SUCCESS) + printf("Bidirectional shutdown complete\n"); + } + } + + /* display collected statistics */ +#ifdef WOLFSSL_STATIC_MEMORY + if (wolfSSL_is_static_memory(ssl, &ssl_stats) != 1) + 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"); + 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 + SSL_free(ssl); ssl = NULL; + + CloseSocket(clientfd); + + if (resume == 1 && resumeCount == 0) { + resumeCount++; /* only do one resume for testing */ + continue; + } + resumeCount = 0; + + cnt++; + if (loops > 0 && --loops == 0) { + break; /* out of while loop, done with normal and resume option */ + } + } /* while(1) */ + + WOLFSSL_TIME(cnt); + (void)cnt; + +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + wolfSSL_CTX_DisableOCSPStapling(ctx); +#endif - CloseSocket(clientfd); CloseSocket(sockfd); + SSL_CTX_free(ctx); ctx = NULL; + ((func_args*)args)->return_code = 0; +exit: -#if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ - && defined(HAVE_THREAD_LS) - ecc_fp_free(); /* free per thread cache */ +#if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) \ + && (defined(NO_MAIN_DRIVER) || defined(HAVE_STACK_SIZE)) + wc_ecc_fp_free(); /* free per thread cache */ #endif -#ifdef USE_WOLFSSL_MEMORY - if (trackMemory) - ShowMemoryTracker(); -#endif - -#ifdef CYASSL_TIRTOS +#ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif @@ -690,11 +2499,31 @@ while (1) { /* allow resume option */ TicketCleanup(); #endif -#ifndef CYASSL_TIRTOS +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + + /* There are use cases when these assignments are not read. To avoid + * potential confusion those warnings have been handled here. + */ + (void) ourKey; + (void) verifyCert; + (void) doCliCertCheck; + (void) useNtruKey; + (void) ourDhParam; + (void) ourCert; + (void) useX25519; + (void) useX448; +#ifdef HAVE_SECURE_RENEGOTIATION + (void) forceScr; +#endif +#ifndef WOLFSSL_TIRTOS return 0; #endif } +#endif /* !NO_WOLFSSL_SERVER */ + /* so overall tests can pull in test function */ #ifndef NO_MAIN_DRIVER @@ -702,39 +2531,41 @@ while (1) { /* allow resume option */ int main(int argc, char** argv) { func_args args; + tcp_ready ready; -#ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) - err_sys("Cavium OpenNitroxDevice failed"); -#endif /* HAVE_CAVIUM */ StartTCP(); args.argc = argc; args.argv = argv; + args.signal = &ready; + args.return_code = 0; + InitTcpReady(&ready); - CyaSSL_Init(); -#if defined(DEBUG_CYASSL) && !defined(CYASSL_MDK_SHELL) - CyaSSL_Debugging_ON(); +#if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_MDK_SHELL) + wolfSSL_Debugging_ON(); #endif - if (CurrentDir("_build")) - ChangeDirBack(1); - else if (CurrentDir("server")) - ChangeDirBack(2); - else if (CurrentDir("Debug") || CurrentDir("Release")) - ChangeDirBack(3); - + wolfSSL_Init(); + ChangeToWolfRoot(); + +#ifndef NO_WOLFSSL_SERVER #ifdef HAVE_STACK_SIZE StackSizeCheck(&args, server_test); -#else +#else server_test(&args); #endif - CyaSSL_Cleanup(); - -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); +#else + printf("Server not compiled in!\n"); #endif + + wolfSSL_Cleanup(); + FreeTcpReady(&ready); + +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys_ex(runWithErrors, "Failed to free netRandom context"); +#endif /* HAVE_WNR */ + return args.return_code; } @@ -742,36 +2573,3 @@ while (1) { /* allow resume option */ 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/FreeRTOS-Plus/Source/WolfSSL/examples/server/server.h b/FreeRTOS-Plus/Source/WolfSSL/examples/server/server.h index c42260fce..91927c7ea 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/server/server.h +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/server/server.h @@ -1,8 +1,8 @@ /* server.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#pragma once + +#ifndef WOLFSSL_SERVER_H +#define WOLFSSL_SERVER_H + THREAD_RETURN WOLFSSL_THREAD server_test(void* args); + +/* Echo bytes using buffer of blockSize until [echoData] bytes are complete. */ +/* If [bechmarkThroughput] set the statistcs will be output at the end */ +int ServerEchoData(WOLFSSL* ssl, int clientfd, int echoData, int blockSize, + size_t benchmarkThroughput); + + +#endif /* WOLFSSL_SERVER_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/examples/server/server.vcproj b/FreeRTOS-Plus/Source/WolfSSL/examples/server/server.vcproj index ebb1af4a4..05cd28833 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/examples/server/server.vcproj +++ b/FreeRTOS-Plus/Source/WolfSSL/examples/server/server.vcproj @@ -41,8 +41,8 @@ + +
Disabled - ../../;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -173,14 +173,13 @@ Console MachineX86 false - Disabled - ../../;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -194,13 +193,14 @@ true Console MachineX86 + false Disabled - ../../;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -217,8 +217,8 @@ Disabled - ../../;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -236,8 +236,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -252,15 +252,14 @@ true MachineX86 false - MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -281,8 +280,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -302,8 +301,8 @@ MaxSpeed true - ../../;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../../;../../IDE/WIN;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -328,6 +327,9 @@ false + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/fips-hash.sh b/FreeRTOS-Plus/Source/WolfSSL/fips-hash.sh new file mode 100644 index 000000000..fa2c1b908 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/fips-hash.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +if test ! -x ./wolfcrypt/test/testwolfcrypt +then + echo "fips-hash: wolfCrypt test missing" + exit 1 +fi + +if test ! -s ./wolfcrypt/src/fips_test.c +then + echo "fips-hash: fips_test.c missing" + exit 1 +fi + +NEWHASH=$(./wolfcrypt/test/testwolfcrypt | sed -n 's/hash = \(.*\)/\1/p') +if test -n "$NEWHASH" +then + sed -i.bak "s/^\".*\";/\"${NEWHASH}\";/" wolfcrypt/src/fips_test.c +fi + diff --git a/FreeRTOS-Plus/Source/WolfSSL/gencertbuf.pl b/FreeRTOS-Plus/Source/WolfSSL/gencertbuf.pl index d3d116695..6b71fffad 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/gencertbuf.pl +++ b/FreeRTOS-Plus/Source/WolfSSL/gencertbuf.pl @@ -15,35 +15,95 @@ use warnings; # output C header file to write cert/key buffers to my $outputFile = "./wolfssl/certs_test.h"; +# ecc keys and certs to be converted +# Used with HAVE_ECC && USE_CERT_BUFFERS_256 + +my @fileList_ecc = ( + [ "./certs/ecc-client-key.der", "ecc_clikey_der_256" ], + [ "./certs/ecc-client-keyPub.der", "ecc_clikeypub_der_256" ], + [ "./certs/client-ecc-cert.der", "cliecc_cert_der_256" ], + [ "./certs/ecc-key.der", "ecc_key_der_256" ], + [ "./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/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/server-ed25519-key.der", "server_ed25519_key" ], + [ "./certs/ed25519/ca-ed25519.der", "ca_ed25519_cert" ], + [ "./certs/ed25519/client-ed25519.der", "client_ed25519_cert" ], + [ "./certs/ed25519/client-ed25519-key.der", "client_ed25519_key" ] + ); + # 1024-bit certs/keys to be converted # Used with USE_CERT_BUFFERS_1024 define. my @fileList_1024 = ( [ "./certs/1024/client-key.der", "client_key_der_1024" ], + [ "./certs/1024/client-keyPub.der", "client_keypub_der_1024" ], [ "./certs/1024/client-cert.der", "client_cert_der_1024" ], [ "./certs/1024/dh1024.der", "dh_key_der_1024" ], [ "./certs/1024/dsa1024.der", "dsa_key_der_1024" ], - [ "./certs/1024/rsa1024.der", "rsa_key_der_1024" ] + [ "./certs/1024/rsa1024.der", "rsa_key_der_1024" ], + [ "./certs/1024/ca-key.der", "ca_key_der_1024"], + [ "./certs/1024/ca-cert.der", "ca_cert_der_1024" ], + [ "./certs/1024/server-key.der", "server_key_der_1024" ], + [ "./certs/1024/server-cert.der", "server_cert_der_1024" ] ); # 2048-bit certs/keys to be converted # Used with USE_CERT_BUFFERS_2048 define. - my @fileList_2048 = ( [ "./certs/client-key.der", "client_key_der_2048" ], + [ "./certs/client-keyPub.der", "client_keypub_der_2048" ], [ "./certs/client-cert.der", "client_cert_der_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/ca-cert-chain.der", "ca_cert_chain_der" ], [ "./certs/server-key.der", "server_key_der_2048" ], [ "./certs/server-cert.der", "server_cert_der_2048" ] ); +# 3072-bit certs/keys to be converted +# Used with USE_CERT_BUFFERS_3072 define. +my @fileList_3072 = ( + [ "./certs/dh3072.der", "dh_key_der_3072" ], + [ "./certs/dsa3072.der", "dsa_key_der_3072" ], + [ "./certs/rsa3072.der", "rsa_key_der_3072" ], + [ "./certs/3072/client-key.der", "client_key_der_3072" ], + [ "./certs/3072/client-keyPub.der", "client_keypub_der_3072" ], + [ "./certs/3072/client-cert.der", "client_cert_der_3072" ], + ); + +# 4096-bit certs/keys to be converted +# Used with USE_CERT_BUFFERS_4096 define. +my @fileList_4096 = ( + [ "./certs/4096/client-key.der", "client_key_der_4096" ], + [ "./certs/4096/client-keyPub.der", "client_keypub_der_4096" ], + [ "./certs/4096/client-cert.der", "client_cert_der_4096" ], + [ "./certs/dh4096.der", "dh_key_der_4096" ], + ); + # ---------------------------------------------------------------------------- +my $num_ecc = @fileList_ecc; +my $num_ed = @fileList_ed; my $num_1024 = @fileList_1024; my $num_2048 = @fileList_2048; +my $num_3072 = @fileList_3072; +my $num_4096 = @fileList_4096; # open our output file, "+>" creates and/or truncates open OUT_FILE, "+>", $outputFile or die $!; @@ -52,6 +112,7 @@ print OUT_FILE "/* certs_test.h */\n\n"; print OUT_FILE "#ifndef WOLFSSL_CERTS_TEST_H\n"; print OUT_FILE "#define WOLFSSL_CERTS_TEST_H\n\n"; + # convert and print 1024-bit cert/keys print OUT_FILE "#ifdef USE_CERT_BUFFERS_1024\n\n"; for (my $i = 0; $i < $num_1024; $i++) { @@ -66,9 +127,11 @@ for (my $i = 0; $i < $num_1024; $i++) { print OUT_FILE "};\n"; print OUT_FILE "static const int sizeof_$sname = sizeof($sname);\n\n"; } +print OUT_FILE "#endif /* USE_CERT_BUFFERS_1024 */\n\n"; + # convert and print 2048-bit certs/keys -print OUT_FILE "#elif defined(USE_CERT_BUFFERS_2048)\n\n"; +print OUT_FILE "#ifdef USE_CERT_BUFFERS_2048\n\n"; for (my $i = 0; $i < $num_2048; $i++) { my $fname = $fileList_2048[$i][0]; @@ -82,7 +145,63 @@ for (my $i = 0; $i < $num_2048; $i++) { print OUT_FILE "static const int sizeof_$sname = sizeof($sname);\n\n"; } -print OUT_FILE "#endif /* USE_CERT_BUFFERS_1024 */\n\n"; + +print OUT_FILE "#endif /* USE_CERT_BUFFERS_2048 */\n\n"; + + +# convert and print 3072-bit certs/keys +print OUT_FILE "#ifdef USE_CERT_BUFFERS_3072\n\n"; +for (my $i = 0; $i < $num_3072; $i++) { + + my $fname = $fileList_3072[$i][0]; + my $sname = $fileList_3072[$i][1]; + + print OUT_FILE "/* $fname, 3072-bit */\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 /* USE_CERT_BUFFERS_3072 */\n\n"; + + +# convert and print 4096-bit certs/keys +print OUT_FILE "#ifdef USE_CERT_BUFFERS_4096\n\n"; +for (my $i = 0; $i < $num_4096; $i++) { + + my $fname = $fileList_4096[$i][0]; + my $sname = $fileList_4096[$i][1]; + + print OUT_FILE "/* $fname, 4096-bit */\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 /* USE_CERT_BUFFERS_4096 */\n\n"; + + +# convert and print 256-bit cert/keys +print OUT_FILE "#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256)\n\n"; +for (my $i = 0; $i < $num_ecc; $i++) { + + my $fname = $fileList_ecc[$i][0]; + my $sname = $fileList_ecc[$i][1]; + + print OUT_FILE "/* $fname, ECC */\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_ECC && USE_CERT_BUFFERS_256 */\n\n"; + + print OUT_FILE "/* dh1024 p */ static const unsigned char dh_p[] = { @@ -103,7 +222,24 @@ static const unsigned char dh_p[] = static const unsigned char dh_g[] = { 0x02, -};\n\n\n"; +};\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 @@ -122,14 +258,17 @@ sub file_to_hex { for (my $i = 0, my $j = 1; $i < $fileLen; $i++, $j++) { if ($j == 1) { - print OUT_FILE "\t"; + print OUT_FILE " "; + } + if ($j != 1) { + print OUT_FILE " "; } read($fp, $byte, 1) or die "Error reading $fileName"; my $output = sprintf("0x%02X", ord($byte)); print OUT_FILE $output; if ($i != ($fileLen - 1)) { - print OUT_FILE ", "; + print OUT_FILE ","; } if ($j == 10) { @@ -140,6 +279,5 @@ sub file_to_hex { print OUT_FILE "\n"; - close($fp); + close($fp); } - diff --git a/FreeRTOS-Plus/Source/WolfSSL/input b/FreeRTOS-Plus/Source/WolfSSL/input index 06dbbf076..a8cdf06c1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/input +++ b/FreeRTOS-Plus/Source/WolfSSL/input @@ -48,7 +48,9 @@ int main(int argc, char** argv) ssl = SSL_new(ctx); - SSL_set_fd(ssl, sockfd); + if (SSL_set_fd(ssl, sockfd) != SSL_SUCCESS) + err_sys("can't set ssl fd"); + if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed"); while (fgets(send, sizeof(send), fin)) { diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_add_am_macro.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_add_am_macro.m4 index 51ce0d0c2..3962002bf 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_add_am_macro.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_add_am_macro.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_add_am_macro.html +# https://www.gnu.org/software/autoconf-archive/ax_add_am_macro.html # =========================================================================== # # SYNOPSIS @@ -21,7 +21,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 9 +#serial 10 AC_DEFUN([AX_ADD_AM_MACRO],[ AC_REQUIRE([AX_AM_MACROS]) diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_am_jobserver.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_am_jobserver.m4 index 5a398f8bb..7da8d5e71 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_am_jobserver.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_am_jobserver.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_am_jobserver.html +# https://www.gnu.org/software/autoconf-archive/ax_am_jobserver.html # =========================================================================== # # SYNOPSIS @@ -33,7 +33,9 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 7.1 +#serial 8.1 +# Local update: Make the increment of enable-jobserver so it isn't executable +# and is more posix syntax. AC_DEFUN([AX_AM_JOBSERVER], [ AC_REQUIRE([AX_COUNT_CPUS]) @@ -44,7 +46,8 @@ AC_DEFUN([AX_AM_JOBSERVER], [ yes: enable one more than CPU count ],, [enable_jobserver=m4_ifval([$1],[$1],[yes])]) if test "x$enable_jobserver" = "xyes"; then - let enable_jobserver=$CPU_COUNT+1 + enable_jobserver=$CPU_COUNT + : $((enable_jobserver+=1)) fi m4_pattern_allow(AM_MAKEFLAGS) if test "x$enable_jobserver" != "xno"; then diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_am_macros.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_am_macros.m4 index 6b4bd2239..36c3ab6a2 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_am_macros.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_am_macros.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_am_macros.html +# https://www.gnu.org/software/autoconf-archive/ax_am_macros.html # =========================================================================== # # SYNOPSIS @@ -24,7 +24,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 9 +#serial 11 AC_DEFUN([AX_AM_MACROS], [ @@ -32,7 +32,7 @@ AC_MSG_NOTICE([adding automake macro support]) AMINCLUDE="aminclude.am" AC_SUBST(AMINCLUDE) AC_MSG_NOTICE([creating $AMINCLUDE]) -AMINCLUDE_TIME=`date` +AMINCLUDE_TIME=`LC_ALL=C date` AX_PRINT_TO_FILE([$AMINCLUDE],[[ # generated automatically by configure from AX_AUTOMAKE_MACROS # on $AMINCLUDE_TIME diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_append_compile_flags.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_append_compile_flags.m4 index 1f8e70845..5b6f1af51 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_append_compile_flags.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_append_compile_flags.m4 @@ -1,10 +1,10 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html -# =========================================================================== +# ============================================================================ +# https://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html +# ============================================================================ # # SYNOPSIS # -# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS]) +# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # @@ -20,6 +20,8 @@ # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# # NOTE: This macro depends on the AX_APPEND_FLAG and # AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with # AX_APPEND_LINK_FLAGS. @@ -39,7 +41,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -54,12 +56,12 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 3 +#serial 6 AC_DEFUN([AX_APPEND_COMPILE_FLAGS], -[AC_REQUIRE([AX_CHECK_COMPILE_FLAG]) -AC_REQUIRE([AX_APPEND_FLAG]) +[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) +AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) for flag in $1; do - AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3]) + AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4]) done ])dnl AX_APPEND_COMPILE_FLAGS diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_append_flag.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_append_flag.m4 index 1d38b76fb..e8c5312af 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_append_flag.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_append_flag.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html +# https://www.gnu.org/software/autoconf-archive/ax_append_flag.html # =========================================================================== # # SYNOPSIS @@ -34,7 +34,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -49,21 +49,23 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 2 +#serial 7 AC_DEFUN([AX_APPEND_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX -AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl -AS_VAR_SET_IF(FLAGS, - [case " AS_VAR_GET(FLAGS) " in - *" $1 "*) - AC_RUN_LOG([: FLAGS already contains $1]) - ;; - *) - AC_RUN_LOG([: FLAGS="$FLAGS $1"]) - AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"]) - ;; - esac], - [AS_VAR_SET(FLAGS,["$1"])]) +[dnl +AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF +AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])]) +AS_VAR_SET_IF(FLAGS,[ + AS_CASE([" AS_VAR_GET(FLAGS) "], + [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])], + [ + AS_VAR_APPEND(FLAGS,[" $1"]) + AC_RUN_LOG([: FLAGS="$FLAGS"]) + ]) + ], + [ + AS_VAR_SET(FLAGS,[$1]) + AC_RUN_LOG([: FLAGS="$FLAGS"]) + ]) AS_VAR_POPDEF([FLAGS])dnl ])dnl AX_APPEND_FLAG diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_append_to_file.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_append_to_file.m4 index f9f54e088..fca570837 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_append_to_file.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_append_to_file.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_append_to_file.html +# https://www.gnu.org/software/autoconf-archive/ax_append_to_file.html # =========================================================================== # # SYNOPSIS @@ -19,9 +19,9 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 8 +#serial 9 AC_DEFUN([AX_APPEND_TO_FILE],[ AC_REQUIRE([AX_FILE_ESCAPES]) -printf "$2\n" >> "$1" +printf "%s" "$2" >> "$1" ]) diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_check_compile_flag.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_check_compile_flag.m4 index c3a8d695a..dcabb92a1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_check_compile_flag.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_check_compile_flag.m4 @@ -1,10 +1,10 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS # -# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # @@ -19,6 +19,8 @@ # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # @@ -38,7 +40,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -53,19 +55,19 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 2 +#serial 5 AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], +AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_check_link_flag.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_check_link_flag.m4 index e2d0d363e..819409a20 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_check_link_flag.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_check_link_flag.m4 @@ -1,10 +1,10 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html +# https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html # =========================================================================== # # SYNOPSIS # -# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # @@ -19,6 +19,8 @@ # EXTRA-FLAGS FLAG". This can for example be used to force the linker to # issue an error when a bad flag is given. # +# INPUT gives an alternative input source to AC_LINK_IFELSE. +# # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. # @@ -38,7 +40,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -53,18 +55,19 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 2 +#serial 5 AC_DEFUN([AX_CHECK_LINK_FLAG], -[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ ax_check_save_flags=$LDFLAGS LDFLAGS="$LDFLAGS $4 $1" - AC_LINK_IFELSE([AC_LANG_PROGRAM()], + AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) LDFLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], +AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_count_cpus.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_count_cpus.m4 index d4f3d290f..5db892553 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_count_cpus.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_count_cpus.m4 @@ -1,20 +1,24 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_count_cpus.html +# https://www.gnu.org/software/autoconf-archive/ax_count_cpus.html # =========================================================================== # # SYNOPSIS # -# AX_COUNT_CPUS +# AX_COUNT_CPUS([ACTION-IF-DETECTED],[ACTION-IF-NOT-DETECTED]) # # DESCRIPTION # -# Attempt to count the number of processors present on the machine. If the -# detection fails, then a value of 1 is assumed. +# Attempt to count the number of logical processor cores (including +# virtual and HT cores) currently available to use on the machine and +# place detected value in CPU_COUNT variable. # -# The value is placed in the CPU_COUNT variable. +# On successful detection, ACTION-IF-DETECTED is executed if present. If +# the detection fails, then ACTION-IF-NOT-DETECTED is triggered. The +# default ACTION-IF-NOT-DETECTED is to set CPU_COUNT to 1. # # LICENSE # +# Copyright (c) 2014,2016 Karlson2k (Evgeny Grin) # Copyright (c) 2012 Brian Aker # Copyright (c) 2008 Michael Paul Bailey # Copyright (c) 2008 Christophe Tournayre @@ -24,34 +28,74 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 10 +#serial 22 - AC_DEFUN([AX_COUNT_CPUS],[ - AC_REQUIRE([AC_CANONICAL_HOST]) - AC_REQUIRE([AC_PROG_EGREP]) + AC_DEFUN([AX_COUNT_CPUS],[dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + AC_REQUIRE([AC_PROG_EGREP])dnl AC_MSG_CHECKING([the number of available CPUs]) CPU_COUNT="0" - AS_CASE([$host_os],[ - *darwin*],[ - AS_IF([test -x /usr/sbin/sysctl],[ - sysctl_a=`/usr/sbin/sysctl -a 2>/dev/null| grep -c hw.cpu` - AS_IF([test sysctl_a],[ - CPU_COUNT=`/usr/sbin/sysctl -n hw.ncpu` - ]) - ])],[ - *linux*],[ - AS_IF([test "x$CPU_COUNT" = "x0" -a -e /proc/cpuinfo],[ - AS_IF([test "x$CPU_COUNT" = "x0" -a -e /proc/cpuinfo],[ - CPU_COUNT=`$EGREP -c '^processor' /proc/cpuinfo` - ]) - ]) - ]) + # Try generic methods - AS_IF([test "x$CPU_COUNT" = "x0"],[ - CPU_COUNT="1" - AC_MSG_RESULT( [unable to detect (assuming 1)] ) - ],[ - AC_MSG_RESULT( $CPU_COUNT ) - ]) - ]) + # 'getconf' is POSIX utility, but '_NPROCESSORS_ONLN' and + # 'NPROCESSORS_ONLN' are platform-specific + command -v getconf >/dev/null 2>&1 && \ + CPU_COUNT=`getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null` || CPU_COUNT="0" + AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null || ! command -v nproc >/dev/null 2>&1]],[[: # empty]],[dnl + # 'nproc' is part of GNU Coreutils and is widely available + CPU_COUNT=`OMP_NUM_THREADS='' nproc 2>/dev/null` || CPU_COUNT=`nproc 2>/dev/null` || CPU_COUNT="0" + ])dnl + + AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null]],[[: # empty]],[dnl + # Try platform-specific preferred methods + AS_CASE([[$host_os]],dnl + [[*linux*]],[[CPU_COUNT=`lscpu -p 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+,' -c` || CPU_COUNT="0"]],dnl + [[*darwin*]],[[CPU_COUNT=`sysctl -n hw.logicalcpu 2>/dev/null` || CPU_COUNT="0"]],dnl + [[freebsd*]],[[command -v sysctl >/dev/null 2>&1 && CPU_COUNT=`sysctl -n kern.smp.cpus 2>/dev/null` || CPU_COUNT="0"]],dnl + [[netbsd*]], [[command -v sysctl >/dev/null 2>&1 && CPU_COUNT=`sysctl -n hw.ncpuonline 2>/dev/null` || CPU_COUNT="0"]],dnl + [[solaris*]],[[command -v psrinfo >/dev/null 2>&1 && CPU_COUNT=`psrinfo 2>/dev/null | $EGREP -e '^@<:@0-9@:>@.*on-line' -c 2>/dev/null` || CPU_COUNT="0"]],dnl + [[mingw*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]],dnl + [[msys*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]],dnl + [[cygwin*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]]dnl + )dnl + ])dnl + + AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null || ! command -v sysctl >/dev/null 2>&1]],[[: # empty]],[dnl + # Try less preferred generic method + # 'hw.ncpu' exist on many platforms, but not on GNU/Linux + CPU_COUNT=`sysctl -n hw.ncpu 2>/dev/null` || CPU_COUNT="0" + ])dnl + + AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null]],[[: # empty]],[dnl + # Try platform-specific fallback methods + # They can be less accurate and slower then preferred methods + AS_CASE([[$host_os]],dnl + [[*linux*]],[[CPU_COUNT=`$EGREP -e '^processor' -c /proc/cpuinfo 2>/dev/null` || CPU_COUNT="0"]],dnl + [[*darwin*]],[[CPU_COUNT=`system_profiler SPHardwareDataType 2>/dev/null | $EGREP -i -e 'number of cores:'|cut -d : -f 2 -s|tr -d ' '` || CPU_COUNT="0"]],dnl + [[freebsd*]],[[CPU_COUNT=`dmesg 2>/dev/null| $EGREP -e '^cpu@<:@0-9@:>@+: '|sort -u|$EGREP -e '^' -c` || CPU_COUNT="0"]],dnl + [[netbsd*]], [[CPU_COUNT=`command -v cpuctl >/dev/null 2>&1 && cpuctl list 2>/dev/null| $EGREP -e '^@<:@0-9@:>@+ .* online ' -c` || \ + CPU_COUNT=`dmesg 2>/dev/null| $EGREP -e '^cpu@<:@0-9@:>@+ at'|sort -u|$EGREP -e '^' -c` || CPU_COUNT="0"]],dnl + [[solaris*]],[[command -v kstat >/dev/null 2>&1 && CPU_COUNT=`kstat -m cpu_info -s state -p 2>/dev/null | $EGREP -c -e 'on-line'` || \ + CPU_COUNT=`kstat -m cpu_info 2>/dev/null | $EGREP -c -e 'module: cpu_info'` || CPU_COUNT="0"]],dnl + [[mingw*]],[AS_IF([[CPU_COUNT=`reg query 'HKLM\\Hardware\\Description\\System\\CentralProcessor' 2>/dev/null | $EGREP -e '\\\\@<:@0-9@:>@+$' -c`]],dnl + [[: # empty]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]])],dnl + [[msys*]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]],dnl + [[cygwin*]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]]dnl + )dnl + ])dnl + + AS_IF([[test "x$CPU_COUNT" != "x0" && test "$CPU_COUNT" -gt 0 2>/dev/null]],[dnl + AC_MSG_RESULT([[$CPU_COUNT]]) + m4_ifvaln([$1],[$1],)dnl + ],[dnl + m4_ifval([$2],[dnl + AS_UNSET([[CPU_COUNT]]) + AC_MSG_RESULT([[unable to detect]]) + $2 + ], [dnl + CPU_COUNT="1" + AC_MSG_RESULT([[unable to detect (assuming 1)]]) + ])dnl + ])dnl + ])dnl diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_create_generic_config.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_create_generic_config.m4 index 535838f46..59aeee617 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_create_generic_config.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_create_generic_config.m4 @@ -9,7 +9,7 @@ # DESCRIPTION # # Creates a generic PACKAGE-config file that has all the things that you -# want, hmm, well, atleast it has --cflags, --version, --libs. Ahhm, did +# want, hmm, well, at least it has --cflags, --version, --libs. Ahhm, did # you see ax_path_generic in the autoconf-archive? ;-) # # this macros saves you all the typing for a pkg-config.in script, you @@ -78,7 +78,7 @@ echo 'package="'$P'"' >>$F echo 'version="'$V'"' >>$F echo 'libs="'$L'"' >>$F echo ' ' >>$F -# in the order of occurence a standard automake Makefile +# in the order of occurrence a standard automake Makefile echo 'prefix="'$prefix'"' >>$F echo 'exec_prefix="'$exec_prefix'"' >>$F echo 'bindir="'$bindir'"' >>$F diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_file_escapes.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_file_escapes.m4 index f4c6a06ae..a86fdc326 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_file_escapes.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_file_escapes.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_file_escapes.html +# https://www.gnu.org/software/autoconf-archive/ax_file_escapes.html # =========================================================================== # # SYNOPSIS @@ -19,7 +19,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 7 +#serial 8 AC_DEFUN([AX_FILE_ESCAPES],[ AX_DOLLAR="\$" diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_harden_compiler_flags.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_harden_compiler_flags.m4 index 018ffcbd6..908855626 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_harden_compiler_flags.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_harden_compiler_flags.m4 @@ -61,10 +61,13 @@ # AX_APPEND_COMPILE_FLAGS([-fstack-check],,[$ax_append_compile_cflags_extra]) -- problems with fastmath stack size checks # AX_APPEND_COMPILE_FLAGS([-floop-parallelize-all],,[$ax_append_compile_cflags_extra]) -- causes RSA verify problem on x64 # AX_APPEND_COMPILE_FLAGS([-Wunreachable-code],,[$ax_append_compile_cflags_extra]) -- older clang and when gcc had it are buggy +# AX_APPEND_COMPILE_FLAGS([-fPIE],,[$ax_append_compile_cflags_extra]) -- Flag for executables not libraries -#serial 4.1 +#serial 4.2 +# changes: deleted the clearing of CFLAGS AC_DEFUN([AX_HARDEN_LINKER_FLAGS], [ + AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) AC_REQUIRE([AX_VCS_CHECKOUT]) AC_REQUIRE([AX_DEBUG]) @@ -93,11 +96,11 @@ ]) AC_DEFUN([AX_HARDEN_CC_COMPILER_FLAGS], [ + AX_REQUIRE_DEFINED([AX_APPEND_COMPILE_FLAGS]) AC_REQUIRE([AX_HARDEN_LINKER_FLAGS]) AC_LANG_PUSH([C]) - CFLAGS= ac_cv_warnings_as_errors=no ax_append_compile_cflags_extra= AS_IF([test "$ac_cv_vcs_checkout" = "yes"],[ @@ -155,11 +158,11 @@ AX_APPEND_COMPILE_FLAGS([-Wunused-variable],,[$ax_append_compile_cflags_extra]) AX_APPEND_COMPILE_FLAGS([-Wwrite-strings],,[$ax_append_compile_cflags_extra]) AX_APPEND_COMPILE_FLAGS([-fwrapv],,[$ax_append_compile_cflags_extra]) - AX_APPEND_COMPILE_FLAGS([-fPIE],,[$ax_append_compile_cflags_extra]) AC_LANG_POP ]) AC_DEFUN([AX_HARDEN_CXX_COMPILER_FLAGS], [ + AC_REQUIRE_DEFINED([AX_APPEND_COMPILE_FLAGS]) AC_REQUIRE([AX_HARDEN_CC_COMPILER_FLAGS]) AC_LANG_PUSH([C++]) @@ -227,6 +230,7 @@ ]) AC_DEFUN([AX_CC_OTHER_FLAGS], [ + AX_REQUIRE_DEFINED([AX_APPEND_COMPILE_FLAGS]) AC_REQUIRE([AX_HARDEN_CC_COMPILER_FLAGS]) AC_LANG_PUSH([C]) diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_print_to_file.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_print_to_file.m4 index 5b9d1c391..8aa71120d 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_print_to_file.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_print_to_file.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_print_to_file.html +# https://www.gnu.org/software/autoconf-archive/ax_print_to_file.html # =========================================================================== # # SYNOPSIS @@ -19,7 +19,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 7 +#serial 8 AC_DEFUN([AX_PRINT_TO_FILE],[ AC_REQUIRE([AX_FILE_ESCAPES]) diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_pthread.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_pthread.m4 index bdb34b0ae..ada7071f2 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_pthread.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_pthread.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_pthread.html +# https://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS @@ -19,10 +19,10 @@ # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, -# but also link it with them as well. e.g. you should link with +# but also to link with them as well. For example, you might link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # -# If you are only building threads programs, you may wish to use these +# If you are only building threaded programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" @@ -30,8 +30,8 @@ # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant -# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name -# (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with @@ -67,7 +67,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -82,35 +82,40 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 20 +#serial 24 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_SED]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). +# requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) - AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes) - AC_MSG_RESULT($ax_pthread_ok) - if test x"$ax_pthread_ok" = xno; then + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = "xno"; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different @@ -123,7 +128,7 @@ fi # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. -ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: @@ -132,71 +137,225 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# ... -mt is also the pthreads flag for HP/aCC +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) -case ${host_os} in +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; + solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthreads/-mt/ - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). - ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" - ;; - - darwin*) - AC_REQUIRE([WOLFSSL_DARWIN_USING_CLANG]) - AS_IF([test x"$wolfssl_darwin_clang" = x"yes"], - [ax_pthread_flags="$ax_pthread_flags"], - [ax_pthread_flags="-pthread $ax_pthread_flags"]) + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" ;; esac -if test x"$ax_pthread_ok" = xno; then -for flag in $ax_pthread_flags; do +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) - case $flag in +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) + +# Are we compiling with Clang? + +AC_CACHE_CHECK([whether $CC is Clang], + [ax_cv_PTHREAD_CLANG], + [ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) + fi + ]) +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; + -mt,pthread) + AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + -*) - AC_MSG_CHECKING([whether pthreads work with $flag]) - PTHREAD_CFLAGS="$flag" + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" ;; pthread-config) - AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no) - if test x"$ax_pthread_config" = xno; then continue; fi + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) - AC_MSG_CHECKING([for the pthreads library -l$flag]) - PTHREAD_LIBS="-l$flag" + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" ;; esac - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we @@ -207,7 +366,11 @@ for flag in $ax_pthread_flags; do # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include +dnl# if $ax_pthread_check_cond +dnl# error "$ax_pthread_check_macro must be defined" +dnl# endif static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; @@ -216,16 +379,14 @@ for flag in $ax_pthread_flags; do pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], - [ax_pthread_ok=yes], - []) + [ax_pthread_ok=yes], + []) - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" - AC_MSG_RESULT($ax_pthread_ok) - if test "x$ax_pthread_ok" = xyes; then - break; - fi + AC_MSG_RESULT([$ax_pthread_ok]) + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) PTHREAD_LIBS="" PTHREAD_CFLAGS="" @@ -233,70 +394,74 @@ done fi # Various other checks: -if test "x$ax_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - AC_MSG_CHECKING([for joinable pthread attribute]) - attr_name=unknown - for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [int attr = $attr; return attr /* ; */])], - [attr_name=$attr; break], - []) - done - AC_MSG_RESULT($attr_name) - if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then - AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, - [Define to necessary symbol if this constant - uses a non-standard name on your system.]) - fi + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) - AC_MSG_CHECKING([if more special flags are required for pthreads]) - flag=no - case ${host_os} in - aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; - osf* | hpux*) flag="-D_REENTRANT";; - solaris*) - if test "$GCC" = "yes"; then - flag="-D_REENTRANT" - else - flag="-mt -D_REENTRANT" - fi - ;; - esac - AC_MSG_RESULT(${flag}) - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], - ax_cv_PTHREAD_PRIO_INHERIT, [ - AC_LINK_IFELSE([ - AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])], - [ax_cv_PTHREAD_PRIO_INHERIT=yes], - [ax_cv_PTHREAD_PRIO_INHERIT=no]) + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) - AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], - AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.])) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" # More AIX lossage: compile with *_r variant - if test "x$GCC" != xyes; then + if test "x$GCC" != "xyes"; then case $host_os in aix*) AS_CASE(["x/$CC"], - [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], - [#handle absolute path differently from PATH based program lookup - AS_CASE(["x$CC"], - [x/*], - [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], - [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) ;; esac fi @@ -304,13 +469,13 @@ fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" -AC_SUBST(PTHREAD_LIBS) -AC_SUBST(PTHREAD_CFLAGS) -AC_SUBST(PTHREAD_CC) +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$ax_pthread_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) +if test "x$ax_pthread_ok" = "xyes"; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) : else ax_pthread_ok=no diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_require_defined.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_require_defined.m4 new file mode 100644 index 000000000..17c3eab7d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_require_defined.m4 @@ -0,0 +1,37 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_require_defined.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_REQUIRE_DEFINED(MACRO) +# +# DESCRIPTION +# +# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have +# been defined and thus are available for use. This avoids random issues +# where a macro isn't expanded. Instead the configure script emits a +# non-fatal: +# +# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found +# +# It's like AC_REQUIRE except it doesn't expand the required macro. +# +# Here's an example: +# +# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) +# +# LICENSE +# +# Copyright (c) 2014 Mike Frysinger +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 2 + +AC_DEFUN([AX_REQUIRE_DEFINED], [dnl + m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) +])dnl AX_REQUIRE_DEFINED diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_vcs_checkout.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_vcs_checkout.m4 index 8047b65ec..4636b58ed 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ax_vcs_checkout.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ax_vcs_checkout.m4 @@ -45,7 +45,10 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#serial 6 +#serial 6.1 +# +# Added tweak for git. The base repo's .git is a directory. Any worktree's +# .git is a file. Use -e to check for either dir or file. AC_DEFUN([AX_VCS_SYSTEM], [AC_PREREQ([2.63])dnl @@ -54,7 +57,7 @@ AC_DEFUN([AX_VCS_SYSTEM], AS_IF([test -d ".bzr"],[ac_cv_vcs_system="bazaar"]) AS_IF([test -d ".svn"],[ac_cv_vcs_system="svn"]) AS_IF([test -d ".hg"],[ac_cv_vcs_system="mercurial"]) - AS_IF([test -d ".git"],[ac_cv_vcs_system="git"]) + AS_IF([test -e ".git"],[ac_cv_vcs_system="git"]) ]) AC_DEFINE_UNQUOTED([VCS_SYSTEM],["$ac_cv_vcs_system"],[VCS system]) ]) diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/libtool.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/libtool.m4 index 4adcf73bd..a3bc337b7 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/libtool.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/libtool.m4 @@ -1,8 +1,6 @@ # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives @@ -10,36 +8,30 @@ # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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 of the License, or +# (at your option) any later version. # -# This file is part of GNU Libtool. +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. # -# GNU Libtool 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. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, or -# obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# along with this program. If not, see . ]) -# serial 57 LT_INIT +# serial 58 LT_INIT # LT_PREREQ(VERSION) @@ -67,7 +59,7 @@ esac # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], -[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl @@ -91,7 +83,7 @@ dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ltmain" +LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' @@ -111,26 +103,43 @@ dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + # _LT_CC_BASENAME(CC) # ------------------- -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], -[for cc_temp in $1""; do - case $cc_temp in - compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; - distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set -# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} @@ -177,15 +186,16 @@ m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ -# See if we are running on zsh, and set the options which allow our +# See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}" ; then +if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) -if test -n "${ZSH_VERSION+set}" ; then +if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi @@ -198,7 +208,7 @@ aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then + if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -209,14 +219,14 @@ esac ofile=libtool can_build_shared=yes -# All known linkers require a `.a' archive for static linking (except MSVC, +# All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a -with_gnu_ld="$lt_cv_prog_gnu_ld" +with_gnu_ld=$lt_cv_prog_gnu_ld -old_CC="$CC" -old_CFLAGS="$CFLAGS" +old_CC=$CC +old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc @@ -269,14 +279,14 @@ no_glob_subst='s/\*/\\\*/g' # _LT_PROG_LTMAIN # --------------- -# Note that this code is called both from `configure', and `config.status' +# Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, -# `config.status' has no value for ac_aux_dir unless we are using Automake, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) -ltmain="$ac_aux_dir/ltmain.sh" +ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN @@ -286,7 +296,7 @@ ltmain="$ac_aux_dir/ltmain.sh" # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS -# in macros and then make a single call at the end using the `libtool' +# in macros and then make a single call at the end using the 'libtool' # label. @@ -421,8 +431,8 @@ m4_define([_lt_decl_all_varnames], # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ -# Quote a variable value, and forward it to `config.status' so that its -# declaration there will have the same value as in `configure'. VARNAME +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) @@ -446,7 +456,7 @@ m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl -available_tags="_LT_TAGS"dnl +available_tags='_LT_TAGS'dnl ]) @@ -474,7 +484,7 @@ m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables -# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], @@ -500,8 +510,8 @@ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations -# into `config.status', and then the shell code to quote escape them in -# for loops in `config.status'. Finally, any additional code accumulated +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], @@ -547,7 +557,7 @@ for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -560,7 +570,7 @@ for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -576,7 +586,7 @@ _LT_OUTPUT_LIBTOOL_INIT # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the -# `#!' sequence but before initialization text begins. After this +# '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). @@ -598,7 +608,7 @@ AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF -test $lt_write_fail = 0 && chmod +x $1[]dnl +test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT @@ -621,7 +631,7 @@ exec AS_MESSAGE_LOG_FD>>config.log } >&AS_MESSAGE_LOG_FD lt_cl_help="\ -\`$as_me' creates a local libtool stub from the current configuration, +'$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. @@ -643,7 +653,7 @@ Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." -while test $[#] != 0 +while test 0 != $[#] do case $[1] in --version | --v* | -V ) @@ -656,10 +666,10 @@ do lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] -Try \`$[0] --help' for more information.]) ;; +Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] -Try \`$[0] --help' for more information.]) ;; +Try '$[0] --help' for more information.]) ;; esac shift done @@ -685,7 +695,7 @@ chmod +x "$CONFIG_LT" # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: -test "$silent" = yes && +test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false @@ -705,32 +715,47 @@ m4_defun([_LT_CONFIG], _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ - # See if we are running on zsh, and set the options which allow our + # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then + if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi - cfgfile="${ofile}T" + cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL - -# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. -# + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + _LT_COPYING _LT_LIBTOOL_TAGS +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + _LT_EOF case $host_os in @@ -739,7 +764,7 @@ _LT_EOF # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then +if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -756,8 +781,6 @@ _LT_EOF sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) - _LT_PROG_REPLACE_SHELLFNS - mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" @@ -775,7 +798,6 @@ _LT_EOF [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' - TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS @@ -974,7 +996,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no - if test -z "${LT_MULTI_MODULE}"; then + if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the @@ -992,7 +1014,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. - elif test -f libconftest.dylib && test $_lt_result -eq 0; then + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD @@ -1010,7 +1032,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], @@ -1032,7 +1054,7 @@ _LT_EOF _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD - elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD @@ -1042,32 +1064,32 @@ _LT_EOF ]) case $host_os in rhapsody* | darwin1.[[012]]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then + if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi - if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= @@ -1087,29 +1109,29 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES], _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - if test "$lt_cv_ld_force_load" = "yes"; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; + ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac - if test "$_lt_dar_can_shared" = "yes"; then + if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all - _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], -[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then - _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else @@ -1129,7 +1151,7 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES], # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl -if test "${lt_cv_aix_libpath+set}" = set; then +if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], @@ -1147,7 +1169,7 @@ else _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) @@ -1167,8 +1189,8 @@ m4_define([_LT_SHELL_INIT], # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start -# of the generated configure script which will find a shell with a builtin -# printf (which we can use as an echo command). +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO @@ -1196,10 +1218,10 @@ fi # Invoke $ECHO with all args, space-separated. func_echo_all () { - $ECHO "$*" + $ECHO "$*" } -case "$ECHO" in +case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; @@ -1225,16 +1247,17 @@ _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], -[ --with-sysroot[=DIR] Search for dependent libraries within DIR - (or the compiler's sysroot if not specified).], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= -case ${with_sysroot} in #( +case $with_sysroot in #( yes) - if test "$GCC" = yes; then + if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( @@ -1244,14 +1267,14 @@ case ${with_sysroot} in #( no|'') ;; #( *) - AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl -[dependent libraries, and in which our libraries should be installed.])]) +[dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- @@ -1259,31 +1282,33 @@ m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes +test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) - HPUX_IA64_MODE="32" + HPUX_IA64_MODE=32 ;; *ELF-64*) - HPUX_IA64_MODE="64" + HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then - if test "$lt_cv_prog_gnu_ld" = yes; then + if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" @@ -1312,9 +1337,46 @@ ia64-*-hpux*) rm -rf conftest* ;; -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in @@ -1324,9 +1386,19 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) - LD="${LD-ld} -m elf_i386" + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac ;; - ppc64-*linux*|powerpc64-*linux*) + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -1345,7 +1417,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - ppc*-*linux*|powerpc*-*linux*) + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -1363,19 +1438,20 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" + SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) - if test x"$lt_cv_cc_needs_belf" != x"yes"; then + if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" + CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in @@ -1383,7 +1459,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) case $lt_cv_prog_gnu_ld in yes*) case $host in - i?86-*-solaris*) + i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) @@ -1392,7 +1468,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD="${LD-ld}_sol2" + LD=${LD-ld}_sol2 fi ;; *) @@ -1408,7 +1484,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) ;; esac -need_locks="$enable_libtool_lock" +need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK @@ -1427,11 +1503,11 @@ AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) - if test "$ac_status" -eq 0; then + if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) - if test "$ac_status" -ne 0; then + if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi @@ -1439,7 +1515,7 @@ AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], ]) ]) -if test "x$lt_cv_ar_at_file" = xno; then +if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file @@ -1470,7 +1546,7 @@ old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in - openbsd*) + bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) @@ -1506,7 +1582,7 @@ AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$3" + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -1533,7 +1609,7 @@ AC_CACHE_CHECK([$1], [$2], $RM conftest* ]) -if test x"[$]$2" = xyes; then +if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) @@ -1555,7 +1631,7 @@ AC_DEFUN([_LT_LINKER_OPTION], m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -1574,10 +1650,10 @@ AC_CACHE_CHECK([$1], [$2], fi fi $RM -r conftest* - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS ]) -if test x"[$]$2" = xyes; then +if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) @@ -1598,7 +1674,7 @@ AC_DEFUN([LT_CMD_MAX_LEN], AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 - teststring="ABCD" + teststring=ABCD case $build_os in msdosdjgpp*) @@ -1638,7 +1714,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl lt_cv_sys_max_cmd_len=8192; ;; - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` @@ -1688,22 +1764,23 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len"; then + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8 ; do + for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && - test $i != 17 # 1/2 MB should be enough + test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring @@ -1719,7 +1796,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl ;; esac ]) -if test -n $lt_cv_sys_max_cmd_len ; then +if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) @@ -1747,7 +1824,7 @@ m4_defun([_LT_HEADER_DLFCN], # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl -if test "$cross_compiling" = yes; then : +if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 @@ -1794,9 +1871,9 @@ else # endif #endif -/* When -fvisbility=hidden is used, assume the code has been annotated +/* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ -#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif @@ -1822,7 +1899,7 @@ int main () return status; }] _LT_EOF - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in @@ -1843,7 +1920,7 @@ rm -fr conftest* # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl -if test "x$enable_dlopen" != xyes; then +if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown @@ -1853,44 +1930,52 @@ else case $host_os in beos*) - lt_cv_dlopen="load_add_on" + lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) - lt_cv_dlopen="dlopen" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) - # if libdl is installed we need to link against it + # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ - lt_cv_dlopen="dyld" + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + *) AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen="shl_load"], + [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen="dlopen"], + [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) @@ -1899,21 +1984,21 @@ else ;; esac - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else + if test no = "$lt_cv_dlopen"; then enable_dlopen=no + else + enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - save_LIBS="$LIBS" + save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], @@ -1923,7 +2008,7 @@ else lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) - if test "x$lt_cv_dlopen_self" = xyes; then + if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl @@ -1933,9 +2018,9 @@ else ]) fi - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS ;; esac @@ -2027,8 +2112,8 @@ m4_defun([_LT_COMPILER_FILE_LOCKS], m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) -hard_links="nottested" -if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes @@ -2038,8 +2123,8 @@ if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) - if test "$hard_links" = no; then - AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else @@ -2066,8 +2151,8 @@ objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl -AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", - [Define to the sub-directory in which libtool stores uninstalled libraries.]) +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR @@ -2079,15 +2164,15 @@ m4_defun([_LT_LINKER_HARDCODE_LIBPATH], _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || - test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. - if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && - test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else @@ -2101,12 +2186,12 @@ else fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) -if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || - test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi @@ -2130,7 +2215,7 @@ else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) - if test -n "$STRIP" ; then + if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) @@ -2148,6 +2233,47 @@ _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics @@ -2158,17 +2284,18 @@ m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in - mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; - *) lt_sed_strip_eq="s,=/,/,g" ;; + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in @@ -2184,28 +2311,35 @@ if test "$GCC" = yes; then ;; esac # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. + # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; + lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } @@ -2219,7 +2353,7 @@ BEGIN {RS=" "; FS="/|\n";} { # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else @@ -2228,7 +2362,7 @@ fi]) library_names_spec= libname_spec='lib$name' soname_spec= -shrext_cmds=".so" +shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= @@ -2245,14 +2379,17 @@ hardcode_into_libs=no # flags to be left without arguments need_version=unknown +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' + soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) @@ -2260,41 +2397,91 @@ aix[[4-9]]*) need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac shlibpath_var=LIBPATH fi ;; @@ -2304,18 +2491,18 @@ amigaos*) powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) - library_names_spec='${libname}${shared_ext}' + library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; @@ -2323,8 +2510,8 @@ beos*) bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" @@ -2336,7 +2523,7 @@ bsdi[[45]]*) cygwin* | mingw* | pw32* | cegcc*) version_type=windows - shrext_cmds=".dll" + shrext_cmds=.dll need_version=no need_lib_prefix=no @@ -2345,8 +2532,8 @@ cygwin* | mingw* | pw32* | cegcc*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ @@ -2362,17 +2549,17 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' @@ -2381,8 +2568,8 @@ m4_if([$1], [],[ *,cl*) # Native MSVC libname_spec='$name' - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - library_names_spec='${libname}.dll.lib' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' case $build_os in mingw*) @@ -2409,7 +2596,7 @@ m4_if([$1], [],[ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) - sys_lib_search_path_spec="$LIB" + sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` @@ -2422,8 +2609,8 @@ m4_if([$1], [],[ esac # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' @@ -2436,7 +2623,7 @@ m4_if([$1], [],[ *) # Assume MSVC wrapper - library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac @@ -2449,8 +2636,8 @@ darwin* | rhapsody*) version_type=darwin need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' @@ -2463,8 +2650,8 @@ dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -2482,12 +2669,13 @@ freebsd* | dragonfly*) version_type=freebsd-$objformat case $version_type in freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac @@ -2512,26 +2700,15 @@ freebsd* | dragonfly*) esac ;; -gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=yes + shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -2549,14 +2726,15 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' @@ -2564,8 +2742,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; @@ -2574,8 +2752,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... @@ -2588,8 +2766,8 @@ interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -2600,7 +2778,7 @@ irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) - if test "$lt_cv_prog_gnu_ld" = yes; then + if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix @@ -2608,8 +2786,8 @@ irix5* | irix6* | nonstopux*) esac need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= @@ -2628,8 +2806,8 @@ irix5* | irix6* | nonstopux*) esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; @@ -2638,13 +2816,33 @@ linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -2669,7 +2867,12 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu) # before this can be enabled. hardcode_into_libs=yes - # Append ld.so.conf contents to the search path + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" @@ -2689,12 +2892,12 @@ netbsd*) need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH @@ -2704,7 +2907,7 @@ netbsd*) newsos6) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; @@ -2713,58 +2916,68 @@ newsos6) version_type=qnx need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; -openbsd*) +openbsd* | bitrig*) version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" + sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[[89]] | openbsd2.[[89]].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi + shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' - shrext_cmds=".dll" + version_type=windows + shrext_cmds=.dll + need_version=no need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) @@ -2775,8 +2988,8 @@ solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes @@ -2786,11 +2999,11 @@ solaris*) sunos4*) version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes @@ -2798,8 +3011,8 @@ sunos4*) sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) @@ -2820,24 +3033,24 @@ sysv4 | sysv4.3*) ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf + version_type=sco need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' @@ -2855,7 +3068,7 @@ tpf*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes @@ -2863,8 +3076,8 @@ tpf*) uts4*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -2873,20 +3086,30 @@ uts4*) ;; esac AC_MSG_RESULT([$dynamic_linker]) -test "$dynamic_linker" = no && can_build_shared=no +test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then +if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) @@ -2919,39 +3142,41 @@ _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) -_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], - [Run-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- -# find a file program which can recognize shared library +# find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$1; then - lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -2974,11 +3199,11 @@ _LT_EOF break fi done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else @@ -2996,7 +3221,7 @@ dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- -# find a file program which can recognize a shared library +# find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then @@ -3023,16 +3248,16 @@ m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], - [test "$withval" = no || with_gnu_ld=yes], + [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld -if test "$GCC" = yes; then +if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw + # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; @@ -3046,7 +3271,7 @@ if test "$GCC" = yes; then while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done - test -z "$LD" && LD="$ac_prog" + test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. @@ -3057,37 +3282,37 @@ if test "$GCC" = yes; then with_gnu_ld=unknown ;; esac -elif test "$with_gnu_ld" = yes; then +elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" + lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies @@ -3173,13 +3435,13 @@ lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. +# 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given extended regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) @@ -3206,8 +3468,7 @@ mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. - # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. - if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else @@ -3243,10 +3504,6 @@ freebsd* | dragonfly*) fi ;; -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - haiku*) lt_cv_deplibs_check_method=pass_all ;; @@ -3285,7 +3542,7 @@ irix5* | irix6* | nonstopux*) ;; # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; @@ -3307,8 +3564,8 @@ newos6*) lt_cv_deplibs_check_method=pass_all ;; -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' @@ -3361,6 +3618,9 @@ sysv4 | sysv4.3*) tpf*) lt_cv_deplibs_check_method=pass_all ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; esac ]) @@ -3401,33 +3661,38 @@ AC_DEFUN([LT_PATH_NM], AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. - lt_cv_path_NM="$NM" + lt_cv_path_NM=$NM else - lt_nm_to_check="${ac_tool_prefix}nm" + lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" - break + break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" - break + break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but @@ -3438,21 +3703,21 @@ else esac fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) -if test "$lt_cv_path_NM" != "no"; then - NM="$lt_cv_path_NM" +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) - case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) - DUMPBIN="$DUMPBIN -symbols" + DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: @@ -3460,8 +3725,8 @@ else esac fi AC_SUBST([DUMPBIN]) - if test "$DUMPBIN" != ":"; then - NM="$DUMPBIN" + if test : != "$DUMPBIN"; then + NM=$DUMPBIN fi fi test -z "$NM" && NM=nm @@ -3507,8 +3772,8 @@ lt_cv_sharedlib_from_linklib_cmd, case $host_os in cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh - # decide which to use based on capabilities of $DLLTOOL + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib @@ -3520,7 +3785,7 @@ cygwin* | mingw* | pw32* | cegcc*) ;; *) # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd="$ECHO" + lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) @@ -3547,13 +3812,28 @@ AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) -if test "x$lt_cv_path_mainfest_tool" != xyes; then +if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + # LT_LIB_M # -------- # check for math library @@ -3565,11 +3845,11 @@ case $host in # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) - AC_CHECK_LIB(m, cos, LIBM="-lm") + AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) @@ -3588,7 +3868,7 @@ m4_defun([_LT_COMPILER_NO_RTTI], _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; @@ -3640,7 +3920,7 @@ cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; @@ -3673,14 +3953,44 @@ case `$NM -V 2>&1` in symcode='[[ABCDGIRSTW]]' ;; esac +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -3698,21 +4008,24 @@ for ac_symprfx in "" "_"; do # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function - # and D for any global variable. + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ -" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ -" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ -" s[1]~/^[@?]/{print s[1], s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" @@ -3752,11 +4065,11 @@ _LT_EOF if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST -#elif defined(__osf__) +#elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else @@ -3782,7 +4095,7 @@ lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; @@ -3802,9 +4115,9 @@ _LT_EOF mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS - LIBS="conftstm.$ac_objext" + LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS @@ -3825,7 +4138,7 @@ _LT_EOF rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then + if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= @@ -3852,12 +4165,16 @@ _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS @@ -3873,17 +4190,18 @@ _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then + if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) @@ -3894,8 +4212,8 @@ m4_if([$1], [CXX], [ ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -3911,6 +4229,11 @@ m4_if([$1], [CXX], [ # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac ;; darwin* | rhapsody*) # PIC is the default on this platform @@ -3960,7 +4283,7 @@ m4_if([$1], [CXX], [ case $host_os in aix[[4-9]]*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else @@ -4001,14 +4324,14 @@ m4_if([$1], [CXX], [ case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default @@ -4037,7 +4360,7 @@ m4_if([$1], [CXX], [ ;; esac ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler @@ -4045,7 +4368,7 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) - # old Intel C++ for x86_64 which still supported -KPIC. + # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' @@ -4190,17 +4513,18 @@ m4_if([$1], [CXX], [ fi ], [ - if test "$GCC" = yes; then + if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) @@ -4211,8 +4535,8 @@ m4_if([$1], [CXX], [ ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -4229,6 +4553,11 @@ m4_if([$1], [CXX], [ # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac ;; darwin* | rhapsody*) @@ -4299,7 +4628,7 @@ m4_if([$1], [CXX], [ case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else @@ -4307,11 +4636,30 @@ m4_if([$1], [CXX], [ fi ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac ;; hpux9* | hpux10* | hpux11*) @@ -4327,7 +4675,7 @@ m4_if([$1], [CXX], [ ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) @@ -4336,9 +4684,9 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in - # old Intel for x86_64 which still supported -KPIC. + # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' @@ -4363,6 +4711,12 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) @@ -4460,7 +4814,7 @@ m4_if([$1], [CXX], [ ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi @@ -4489,7 +4843,7 @@ m4_if([$1], [CXX], [ fi ]) case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: + # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; @@ -4555,17 +4909,21 @@ m4_if([$1], [CXX], [ case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global defined - # symbols, whereas GNU nm marks them as "W". + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) - _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in @@ -4611,9 +4969,9 @@ m4_if([$1], [CXX], [ # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if @@ -4629,7 +4987,7 @@ dnl Note also adjust exclude_expsyms for C++ above. # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. - if test "$GCC" != yes; then + if test yes != "$GCC"; then with_gnu_ld=no fi ;; @@ -4637,7 +4995,7 @@ dnl Note also adjust exclude_expsyms for C++ above. # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; - openbsd*) + openbsd* | bitrig*) with_gnu_ld=no ;; esac @@ -4647,7 +5005,7 @@ dnl Note also adjust exclude_expsyms for C++ above. # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility @@ -4669,24 +5027,24 @@ dnl Note also adjust exclude_expsyms for C++ above. esac fi - if test "$lt_use_gnu_ld_interface" = yes; then + if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' + wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no - case `$LD -v 2>&1` in + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... @@ -4699,7 +5057,7 @@ dnl Note also adjust exclude_expsyms for C++ above. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then + if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 @@ -4718,7 +5076,7 @@ _LT_EOF case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) @@ -4734,7 +5092,7 @@ _LT_EOF _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -4744,7 +5102,7 @@ _LT_EOF # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes @@ -4752,61 +5110,89 @@ _LT_EOF _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no - if test "$host_os" = linux-dietlibc; then + if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test "$tmp_diet" = no + && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -4817,42 +5203,47 @@ _LT_EOF lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac - _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -4866,8 +5257,8 @@ _LT_EOF _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; @@ -4885,8 +5276,8 @@ _LT_EOF _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -4898,7 +5289,7 @@ _LT_EOF _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify @@ -4913,9 +5304,9 @@ _LT_EOF # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -4932,15 +5323,15 @@ _LT_EOF *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac - if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= @@ -4956,7 +5347,7 @@ _LT_EOF # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported @@ -4964,34 +5355,57 @@ _LT_EOF ;; aix[[4-9]]*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag="" + no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - # Also, AIX nm treats weak defined symbols like other global - # defined symbols, whereas GNU nm marks them as "W". + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi ;; esac @@ -5010,13 +5424,21 @@ _LT_EOF _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac - if test "$GCC" = yes; then + if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` + collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -5035,61 +5457,80 @@ _LT_EOF ;; esac shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' else # not using gcc - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' else - shared_flag='${wl}-bM:SRE' + shared_flag='$wl-bM:SRE' fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' fi fi - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else - if test "$host_cpu" = ia64; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; @@ -5098,7 +5539,7 @@ _LT_EOF case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) @@ -5128,16 +5569,17 @@ _LT_EOF # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes @@ -5146,18 +5588,18 @@ _LT_EOF # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) # Assume MSVC wrapper @@ -5166,7 +5608,7 @@ _LT_EOF # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. @@ -5216,33 +5658,33 @@ _LT_EOF ;; hpux9*) - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes @@ -5250,25 +5692,25 @@ _LT_EOF ;; hpux11*) - if test "$GCC" = yes && test "$with_gnu_ld" = no; then + if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ @@ -5276,14 +5718,14 @@ _LT_EOF # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in @@ -5294,7 +5736,7 @@ _LT_EOF *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. @@ -5305,16 +5747,16 @@ _LT_EOF ;; irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], - [save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], @@ -5327,21 +5769,31 @@ _LT_EOF end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) - LDFLAGS="$save_LDFLAGS"]) - if test "$lt_cv_irix_exported_symbol" = yes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out @@ -5356,7 +5808,7 @@ _LT_EOF newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; @@ -5364,27 +5816,19 @@ _LT_EOF *nto* | *qnx*) ;; - openbsd*) + openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else - case $host_os in - openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - ;; - esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no @@ -5395,33 +5839,53 @@ _LT_EOF _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) - if test "$GCC" = yes; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' @@ -5432,24 +5896,24 @@ _LT_EOF solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' - if test "$GCC" = yes; then - wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' - _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) - wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi @@ -5459,11 +5923,11 @@ _LT_EOF solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', + # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi @@ -5473,10 +5937,10 @@ _LT_EOF ;; sunos4*) - if test "x$host_vendor" = xsequent; then + if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi @@ -5525,43 +5989,43 @@ _LT_EOF ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not + # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; @@ -5576,17 +6040,17 @@ _LT_EOF ;; esac - if test x$host_vendor = xsni; then + if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) -test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld @@ -5603,7 +6067,7 @@ x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - if test "$enable_shared" = yes && test "$GCC" = yes; then + if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. @@ -5683,12 +6147,12 @@ _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], - [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], - [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is - "absolute", i.e impossible to change by setting ${shlibpath_var} if the + "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR @@ -5729,10 +6193,10 @@ dnl [Compiler flag to generate thread safe objects]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to `libtool'. +# the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl -lt_save_CC="$CC" +lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. @@ -5772,18 +6236,18 @@ if test -n "$compiler"; then LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB - # Report which library types will actually be built + # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' @@ -5791,8 +6255,12 @@ if test -n "$compiler"; then ;; aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac @@ -5800,13 +6268,13 @@ if test -n "$compiler"; then AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes + test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP -CC="$lt_save_CC" +CC=$lt_save_CC ])# _LT_LANG_C_CONFIG @@ -5814,14 +6282,14 @@ CC="$lt_save_CC" # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to `libtool'. +# the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl -if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes @@ -5863,7 +6331,7 @@ _LT_TAGVAR(objext, $1)=$objext # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_caught_CXX_error" != yes; then +if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" @@ -5905,35 +6373,35 @@ if test "$_lt_caught_CXX_error" != yes; then if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately - if test "$GXX" = yes; then + if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi - if test "$GXX" = yes; then + if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) - wlarc='${wl}' + wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi @@ -5969,18 +6437,30 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag="" + no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in @@ -5990,6 +6470,13 @@ if test "$_lt_caught_CXX_error" != yes; then ;; esac done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi ;; esac @@ -6008,13 +6495,21 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac - if test "$GXX" = yes; then + if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` + collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -6032,64 +6527,84 @@ if test "$_lt_caught_CXX_error" != yes; then fi esac shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' else # not using gcc - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' else - shared_flag='${wl}-bM:SRE' + shared_flag='$wl-bM:SRE' fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' fi fi - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else - if test "$host_cpu" = ia64; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared - # libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; @@ -6099,7 +6614,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -6127,57 +6642,58 @@ if test "$_lt_caught_CXX_error" != yes; then # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" + shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; - else - $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile="$lt_outputfile.exe" - lt_tool_outputfile="$lt_tool_outputfile.exe" - ;; - esac~ - func_to_tool_file "$lt_outputfile"~ - if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -6188,6 +6704,34 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_DARWIN_LINKER_FEATURES($1) ;; + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + dgux*) case $cc_basename in ec++*) @@ -6222,18 +6766,15 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(ld_shlibs, $1)=yes ;; - gnu*) - ;; - haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default @@ -6245,7 +6786,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. @@ -6254,11 +6795,11 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test "$GXX" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no @@ -6268,15 +6809,15 @@ if test "$_lt_caught_CXX_error" != yes; then ;; hpux10*|hpux11*) - if test $with_gnu_ld = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi @@ -6302,13 +6843,13 @@ if test "$_lt_caught_CXX_error" != yes; then aCC*) case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists @@ -6319,20 +6860,20 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi @@ -6347,22 +6888,22 @@ if test "$_lt_caught_CXX_error" != yes; then interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is @@ -6371,22 +6912,22 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler @@ -6394,8 +6935,8 @@ if test "$_lt_caught_CXX_error" != yes; then # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. @@ -6404,10 +6945,10 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. @@ -6421,59 +6962,59 @@ if test "$_lt_caught_CXX_error" != yes; then # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac - _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ - $RANLIB $oldlib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' @@ -6487,18 +7028,18 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) @@ -6506,10 +7047,10 @@ if test "$_lt_caught_CXX_error" != yes; then *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on @@ -6567,22 +7108,17 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(ld_shlibs, $1)=yes ;; - openbsd2*) - # C++ shared libraries are fairly broken - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - openbsd*) + openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else @@ -6598,9 +7134,9 @@ if test "$_lt_caught_CXX_error" != yes; then # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using @@ -6618,17 +7154,17 @@ if test "$_lt_caught_CXX_error" != yes; then cxx*) case $host in osf3*) - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ - $RM $lib.exp' + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac @@ -6643,21 +7179,21 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists @@ -6703,9 +7239,9 @@ if test "$_lt_caught_CXX_error" != yes; then # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no @@ -6713,7 +7249,7 @@ if test "$_lt_caught_CXX_error" != yes; then solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. + # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; @@ -6730,30 +7266,30 @@ if test "$_lt_caught_CXX_error" != yes; then ;; gcx*) # Green Hills C++ Compiler - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else - # g++ 2.7 appears to require `-G' NOT `-shared' on this + # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. - _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when @@ -6761,11 +7297,11 @@ if test "$_lt_caught_CXX_error" != yes; then output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi @@ -6774,52 +7310,52 @@ if test "$_lt_caught_CXX_error" != yes; then ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not + # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ - '"$_LT_TAGVAR(old_archive_cmds, $1)" + '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ - '"$_LT_TAGVAR(reload_cmds, $1)" + '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; @@ -6850,10 +7386,10 @@ if test "$_lt_caught_CXX_error" != yes; then esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) - test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no - _LT_TAGVAR(GCC, $1)="$GXX" - _LT_TAGVAR(LD, $1)="$LD" + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -6880,7 +7416,7 @@ if test "$_lt_caught_CXX_error" != yes; then lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test "$_lt_caught_CXX_error" != yes +fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG @@ -6902,13 +7438,14 @@ AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF + # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose @@ -6992,13 +7529,13 @@ if AC_TRY_EVAL(ac_compile); then pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do - case ${prev}${p} in + case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. - if test $p = "-L" || - test $p = "-R"; then + if test x-L = "$p" || + test x-R = "$p"; then prev=$p continue fi @@ -7014,16 +7551,16 @@ if AC_TRY_EVAL(ac_compile); then case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac - if test "$pre_test_object_deps_done" = no; then - case ${prev} in + if test no = "$pre_test_object_deps_done"; then + case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then - _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else - _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being @@ -7031,9 +7568,9 @@ if AC_TRY_EVAL(ac_compile); then esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then - _LT_TAGVAR(postdeps, $1)="${prev}${p}" + _LT_TAGVAR(postdeps, $1)=$prev$p else - _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= @@ -7048,15 +7585,15 @@ if AC_TRY_EVAL(ac_compile); then continue fi - if test "$pre_test_object_deps_done" = no; then + if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then - _LT_TAGVAR(predep_objects, $1)="$p" + _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then - _LT_TAGVAR(postdep_objects, $1)="$p" + _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi @@ -7087,51 +7624,6 @@ interix[[3-9]]*) _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; - -linux*) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - if test "$solaris_use_stlport4" != yes; then - _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; - -solaris*) - case $cc_basename in - CC* | sunCC*) - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - # Adding this requires a known-good setup of shared libraries for - # Sun compiler versions before 5.6, else PIC objects from an old - # archive will be linked into the output, leading to subtle bugs. - if test "$solaris_use_stlport4" != yes; then - _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; esac ]) @@ -7140,7 +7632,7 @@ case " $_LT_TAGVAR(postdeps, $1) " in esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then - _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) @@ -7160,10 +7652,10 @@ _LT_TAGDECL([], [compiler_lib_search_path], [1], # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) -if test -z "$F77" || test "X$F77" = "Xno"; then +if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi @@ -7200,7 +7692,7 @@ _LT_TAGVAR(objext, $1)=$objext # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_disable_F77" != yes; then +if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t @@ -7222,7 +7714,7 @@ if test "$_lt_disable_F77" != yes; then _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. - lt_save_CC="$CC" + lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} @@ -7236,21 +7728,25 @@ if test "$_lt_disable_F77" != yes; then AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac @@ -7258,11 +7754,11 @@ if test "$_lt_disable_F77" != yes; then AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes + test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) - _LT_TAGVAR(GCC, $1)="$G77" - _LT_TAGVAR(LD, $1)="$LD" + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -7279,9 +7775,9 @@ if test "$_lt_disable_F77" != yes; then fi # test -n "$compiler" GCC=$lt_save_GCC - CC="$lt_save_CC" - CFLAGS="$lt_save_CFLAGS" -fi # test "$_lt_disable_F77" != yes + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG @@ -7291,11 +7787,11 @@ AC_LANG_POP # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) -if test -z "$FC" || test "X$FC" = "Xno"; then +if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi @@ -7332,7 +7828,7 @@ _LT_TAGVAR(objext, $1)=$objext # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_disable_FC" != yes; then +if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t @@ -7354,7 +7850,7 @@ if test "$_lt_disable_FC" != yes; then _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. - lt_save_CC="$CC" + lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} @@ -7370,21 +7866,25 @@ if test "$_lt_disable_FC" != yes; then AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac @@ -7392,11 +7892,11 @@ if test "$_lt_disable_FC" != yes; then AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes + test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) - _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" - _LT_TAGVAR(LD, $1)="$LD" + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -7416,7 +7916,7 @@ if test "$_lt_disable_FC" != yes; then GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS -fi # test "$_lt_disable_FC" != yes +fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG @@ -7426,7 +7926,7 @@ AC_LANG_POP # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE @@ -7460,7 +7960,7 @@ CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)="$LD" +_LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. @@ -7497,7 +7997,7 @@ CFLAGS=$lt_save_CFLAGS # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE @@ -7531,7 +8031,7 @@ CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)="$LD" +_LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. @@ -7568,7 +8068,7 @@ CFLAGS=$lt_save_CFLAGS # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. +# to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE @@ -7584,7 +8084,7 @@ _LT_TAGVAR(objext, $1)=$objext lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests -lt_simple_link_test_code="$lt_simple_compile_test_code" +lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER @@ -7594,7 +8094,7 @@ _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. -lt_save_CC="$CC" +lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= @@ -7623,7 +8123,7 @@ AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) - test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) @@ -7734,7 +8234,7 @@ lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && continue + test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in @@ -7751,9 +8251,9 @@ for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough - test $lt_ac_count -gt 10 && break + test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` - if test $lt_ac_count -gt $lt_ac_max; then + if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi @@ -7777,27 +8277,7 @@ dnl AC_DEFUN([LT_AC_PROG_SED], []) # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], -[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) -# Try some XSI features -xsi_shell=no -( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,b/c, \ - && eval 'test $(( 1 + 1 )) -eq 2 \ - && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ - && xsi_shell=yes -AC_MSG_RESULT([$xsi_shell]) -_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) - -AC_MSG_CHECKING([whether the shell understands "+="]) -lt_shell_append=no -( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ - >/dev/null 2>&1 \ - && lt_shell_append=yes -AC_MSG_RESULT([$lt_shell_append]) -_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) - -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false @@ -7821,102 +8301,9 @@ _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES -# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) -# ------------------------------------------------------ -# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and -# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. -m4_defun([_LT_PROG_FUNCTION_REPLACE], -[dnl { -sed -e '/^$1 ()$/,/^} # $1 /c\ -$1 ()\ -{\ -m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) -} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") -test 0 -eq $? || _lt_function_replace_fail=: -]) - - -# _LT_PROG_REPLACE_SHELLFNS -# ------------------------- -# Replace existing portable implementations of several shell functions with -# equivalent extended shell implementations where those features are available.. -m4_defun([_LT_PROG_REPLACE_SHELLFNS], -[if test x"$xsi_shell" = xyes; then - _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac]) - - _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl - func_basename_result="${1##*/}"]) - - _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac - func_basename_result="${1##*/}"]) - - _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary parameter first. - func_stripname_result=${3} - func_stripname_result=${func_stripname_result#"${1}"} - func_stripname_result=${func_stripname_result%"${2}"}]) - - _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl - func_split_long_opt_name=${1%%=*} - func_split_long_opt_arg=${1#*=}]) - - _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl - func_split_short_opt_arg=${1#??} - func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) - - _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl - case ${1} in - *.lo) func_lo2o_result=${1%.lo}.${objext} ;; - *) func_lo2o_result=${1} ;; - esac]) - - _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) - - _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) - - _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) -fi - -if test x"$lt_shell_append" = xyes; then - _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) - - _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl - func_quote_for_eval "${2}" -dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ - eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) - - # Save a `func_append' function call where possible by direct use of '+=' - sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -else - # Save a `func_append' function call even when '+=' is not available - sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ - && mv -f "$cfgfile.tmp" "$cfgfile" \ - || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") - test 0 -eq $? || _lt_function_replace_fail=: -fi - -if test x"$_lt_function_replace_fail" = x":"; then - AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) -fi -]) - # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- -# Determine which file name conversion functions should be used by +# Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ltoptions.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ltoptions.m4 index 5d9acd8e2..94b082976 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ltoptions.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ltoptions.m4 @@ -1,14 +1,14 @@ # Helper functions for option handling. -*- Autoconf -*- # -# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. -# serial 7 ltoptions.m4 +# serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) @@ -29,7 +29,7 @@ m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), - [m4_warning([Unknown $1 option `$2'])])[]dnl + [m4_warning([Unknown $1 option '$2'])])[]dnl ]) @@ -75,13 +75,15 @@ m4_if([$1],[LT_INIT],[ dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither - dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], - [_LT_ENABLE_FAST_INSTALL]) + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS @@ -112,7 +114,7 @@ AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `dlopen' option into LT_INIT's first parameter.]) +put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: @@ -148,7 +150,7 @@ AU_DEFUN([AC_LIBTOOL_WIN32_DLL], _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `win32-dll' option into LT_INIT's first parameter.]) +put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: @@ -157,9 +159,9 @@ dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- -# implement the --enable-shared flag, and supports the `shared' and -# `disable-shared' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], @@ -172,14 +174,14 @@ AC_ARG_ENABLE([shared], *) enable_shared=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) @@ -211,9 +213,9 @@ dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- -# implement the --enable-static flag, and support the `static' and -# `disable-static' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], @@ -226,14 +228,14 @@ AC_ARG_ENABLE([static], *) enable_static=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) @@ -265,9 +267,9 @@ dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- -# implement the --enable-fast-install flag, and support the `fast-install' -# and `disable-fast-install' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], @@ -280,14 +282,14 @@ AC_ARG_ENABLE([fast-install], *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) @@ -304,14 +306,14 @@ AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put -the `fast-install' option into LT_INIT's first parameter.]) +the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put -the `disable-fast-install' option into LT_INIT's first parameter.]) +the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: @@ -319,11 +321,64 @@ dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + # _LT_WITH_PIC([MODE]) # -------------------- -# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. -# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], @@ -334,19 +389,17 @@ m4_define([_LT_WITH_PIC], *) pic_mode=default # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac], - [pic_mode=default]) - -test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC @@ -359,7 +412,7 @@ AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `pic-only' option into LT_INIT's first parameter.]) +put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ltsugar.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ltsugar.m4 index 9000a057d..48bc9344a 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ltsugar.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ltsugar.m4 @@ -1,6 +1,7 @@ # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # -# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives @@ -33,7 +34,7 @@ m4_define([_lt_join], # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support -# Autoconf-2.59 which quotes differently. +# Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], @@ -44,7 +45,7 @@ m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ -# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/ltversion.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/ltversion.m4 index 07a8602d4..fa04b52a3 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/ltversion.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/ltversion.m4 @@ -1,6 +1,6 @@ # ltversion.m4 -- version numbers -*- Autoconf -*- # -# Copyright (C) 2004 Free Software Foundation, Inc. +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives @@ -9,15 +9,15 @@ # @configure_input@ -# serial 3337 ltversion.m4 +# serial 4179 ltversion.m4 # This file is part of GNU Libtool -m4_define([LT_PACKAGE_VERSION], [2.4.2]) -m4_define([LT_PACKAGE_REVISION], [1.3337]) +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.4.2' -macro_revision='1.3337' +[macro_version='2.4.6' +macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/lt~obsolete.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/lt~obsolete.m4 index c573da90c..c6b26f88f 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/lt~obsolete.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/lt~obsolete.m4 @@ -1,6 +1,7 @@ # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # -# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives @@ -11,7 +12,7 @@ # These exist entirely to fool aclocal when bootstrapping libtool. # -# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # @@ -25,7 +26,7 @@ # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/visibility.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/visibility.m4 index 75c34b6e1..7e9976475 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/visibility.m4 +++ b/FreeRTOS-Plus/Source/WolfSSL/m4/visibility.m4 @@ -1,5 +1,5 @@ -# visibility.m4 serial 4 (gettext-0.18.2) -dnl Copyright (C) 2005, 2008, 2010-2011 Free Software Foundation, Inc. +# visibility.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 2005, 2008, 2010-2018 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -12,7 +12,7 @@ dnl __attribute__((__visibility__("hidden"))) and dnl __attribute__((__visibility__("default"))). dnl Does *not* test for __visibility__("protected") - which has tricky dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on -dnl MacOS X. +dnl Mac OS X. dnl Does *not* test for __visibility__("internal") - which has processor dnl dependent semantics. dnl Does *not* test for #pragma GCC visibility push(hidden) - which is diff --git a/FreeRTOS-Plus/Source/WolfSSL/m4/wolfssl_darwin_clang.m4 b/FreeRTOS-Plus/Source/WolfSSL/m4/wolfssl_darwin_clang.m4 deleted file mode 100644 index fee9b6ae0..000000000 --- a/FreeRTOS-Plus/Source/WolfSSL/m4/wolfssl_darwin_clang.m4 +++ /dev/null @@ -1,37 +0,0 @@ -# =========================================================================== -# -# SYNOPSIS -# -# WOLFSSL_DARWIN_USING_CLANG -# -# DESCRIPTION -# -# With the advent of Apple Xcode v5.0, the old tool sets are missing from -# the distribution. The provided "gcc" executable wrapper accepts the -# "-pthread" flag, and passes it to the underlying "clang" which chokes -# on it. This script checks the version of the gcc executable to see if -# it reports it is really "clang". -# -# The value is placed in the wolfssl_darwin_clang variable. -# -# LICENSE -# -# Copyright (c) 2013 John Safranek -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 1 - -AC_DEFUN([WOLFSSL_DARWIN_USING_CLANG], - [ - if test x"$CC" = xclang; then - wolfssl_darwin_clang=yes - elif test x"$CC" = x || test x"$CC" = xgcc; then - if /usr/bin/gcc -v 2>&1 | grep 'clang' >/dev/null 2>&1; then - wolfssl_darwin_clang=yes - fi - fi - ]) diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/PIC32MZ-serial.h b/FreeRTOS-Plus/Source/WolfSSL/mcapi/PIC32MZ-serial.h new file mode 100644 index 000000000..b0df814c8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/PIC32MZ-serial.h @@ -0,0 +1,75 @@ +void _mon_putc(char c); + +#define BAUD_GEN(sysclk, baud) ((sysclk / (16 * baud)) - 1) + +#ifdef MICROCHIP_PIC32 +#if defined (__32MZ2048ECH144__) || defined(__32MZ2048ECM144__) || defined(__32MZ2048EFM144__) + /* Code generated from Harmony example then exported using Window -> PIC32 Memory View -> Configuration Bits into system_config.h */ + #define SYS_CLK_FREQ 200000000ul + #define SYS_CLK_BUS_PERIPHERAL_2 100000000ul + + // DEVCFG3 + #pragma config FMIIEN = ON // Ethernet RMII/MII Enable (MII Enabled) + #pragma config FETHIO = ON // Ethernet I/O Pin Select (Default Ethernet I/O) + #pragma config PGL1WAY = ON // Permission Group Lock One Way Configuration (Allow only one reconfiguration) + #pragma config PMDL1WAY = ON // Peripheral Module Disable Configuration (Allow only one reconfiguration) + #pragma config IOL1WAY = ON // Peripheral Pin Select Configuration (Allow only one reconfiguration) + #pragma config FUSBIDIO = ON // USB USBID Selection (Controlled by the USB Module) + + // DEVCFG2 + #pragma config FPLLIDIV = DIV_1 // System PLL Input Divider (1x Divider) + #pragma config FPLLRNG = RANGE_5_10_MHZ // System PLL Input Range (5-10 MHz Input) + #pragma config FPLLICLK = PLL_FRC // System PLL Input Clock Selection (FRC is input to the System PLL) + #pragma config FPLLMULT = MUL_50 // System PLL Multiplier (PLL Multiply by 50) + #pragma config FPLLODIV = DIV_2 // System PLL Output Clock Divider (2x Divider) + #pragma config UPLLFSEL = FREQ_24MHZ // USB PLL Input Frequency Selection (USB PLL input is 24 MHz) + + // DEVCFG1 + #pragma config FNOSC = SPLL // Oscillator Selection Bits (System PLL) + #pragma config DMTINTV = WIN_127_128 // DMT Count Window Interval (Window/Interval value is 127/128 counter value) + #pragma config FSOSCEN = OFF // Secondary Oscillator Enable (Disable SOSC) + #pragma config IESO = OFF // Internal/External Switch Over (Disabled) + #pragma config POSCMOD = OFF // Primary Oscillator Configuration (Primary osc disabled) + #pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin (Disabled) + #pragma config FCKSM = CSECME // Clock Switching and Monitor Selection (Clock Switch Enabled, FSCM Enabled) + #pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576) + #pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming) + #pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode) + #pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled) + #pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%) + #pragma config DMTCNT = DMT31 // Deadman Timer Count Selection (2^31 (2147483648)) + #pragma config FDMTEN = OFF // Deadman Timer Enable (Deadman Timer is disabled) + + // DEVCFG0 + #pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2) + + // DEVCP0 + #pragma config CP = OFF // Code Protect (Protection Disabled) + + #include +#endif +#endif + +static void init_serial(unsigned int sysClk) { +#ifdef MICROCHIP_PIC32 +#if defined (__32MZ2048ECH144__) || defined(__32MZ2048ECM144__) || defined(__32MZ2048EFM144__) + /* This is for pin B14 which is connected to the USB to UART connector J11 located under Ethernet connector */ + + /* Setup UART2 */ +#ifdef SYS_CLK_BUS_PERIPHERAL_2 + U2BRG = BAUD_GEN(SYS_CLK_BUS_PERIPHERAL_2, 115200); +#else + if (sysClk > 100000000) + sysClk /= 2; + U2BRG = BAUD_GEN(sysClk, 115200); +#endif + ANSELBCLR = 0x4000; + ANSELGCLR = 0x0040; + RPB14R = 0x02; + U2RXR = 0x01; + U2MODE = 0x8000; + U2STA = 0x400; +#endif +#endif + (void)sysClk; +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/README b/FreeRTOS-Plus/Source/WolfSSL/mcapi/README new file mode 100644 index 000000000..2cfb368b4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/README @@ -0,0 +1,79 @@ +WolfSSL MPLAB X Project Files + +This directory contains project files for the Microchip MPLAB X IDE. These +projects have been set up to use the Microchip PIC32 Ethernet Starter Kit +and the Microchip XC32 compiler, and have been created specifically to test +the Microchip-specific WolfCrypt API with compression support. For MPLAB X +projects that don't use compression and are generic to the WolfCrypt API, +please see the /mplabx directory. + +In order to generate the necessary auto-generated MPLAB X files, make sure +to import the cyassl.X and zlib.X projects into your MPLAB X workspace before +trying to build either the WolfCrypt test or benchmark applications. This will +correctly set up the respective project's Makefiles. + +Included Project Files +----------------------- + +1. wolfSSL library (wolfssl.X) + + This project builds a static wolfSSL library. Prior to building this + project, uncomment the MICROCHIP_PIC32 define located in: + + /wolfssl/wolfcrypt/settings.h + + After this project has been built, the compiled library will be located + at: + + /mplabx/wolfssl.X/dist/default/production/wolfssl.X.a + + Note that this project includes the zlib header location in the project's + include paths. This is because this project has been set up to be compiled + with zlib support to enable compression and decompression features. + +2. wolfCrypt Test App (wolfcrypt_test.X) + + This project tests the wolfCrypt cryptography modules. It is generally + a good idea to run this first on an embedded system after compiling + wolfSSL in order to verify all underlying crypto is working correctly. + +3. wolfCrypt Benchmark App (wolfcrypt_benchmark.X) + + This project builds the wolfCrypt benchmark application. If the wolfSSL + project (wolfssl.X) has been compiled with libz support and is being + used to build this project, the zlib.X project will need to added to + the "Libraries" folder under the wolfcrypt_benchmark.X project before + it will compile successfully. + +4. wolfCrypt MCAPI Test App (wolfcrypt_mcapi.X) + + This project tests the Microchip crypto API layer. The Microchip crypto + layer is located under the /mcapi directory. + +5. zlib library (zlib.X) + + This project builds the zlib library for use in the wolfcrypt_test.X + and wolfcrypt_mcapi.X projects. This project expects the zlib sources + to be located under the wolfSSL root directory. Currently it is set up + to work with zlib 1.2.8, and looks for sources under: + + /zlib-1.2.8 + +PIC32MX/PIC32MZ +--------------- + +The projects are set for PIC32MX by default. For PIC32MZ, change project +properties->Devices and add "WOLFSSL_MICROCHIP_PIC32M" to +XC32-gcc->Preprocessing and messages-> Preprocessor macros. + +MIPS16 and MIPS32 Support +------------------------- + +These projects support both MIPS16 and MIPS32 instruction sets. Switching +between these two instruction sets can be done in each project's properties +settings by checking the "Generate 16-bit code" checkbox. + +Support +------- +Please send questions or comments to support@wolfssl.com + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/crypto.c b/FreeRTOS-Plus/Source/WolfSSL/mcapi/crypto.c new file mode 100644 index 000000000..9437f1ede --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/crypto.c @@ -0,0 +1,782 @@ +/* crypto.c + * + * Copyright (C) 2006-2020 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 + */ + + +/* Implements Microchip CRYPTO API layer */ +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif +#ifdef MICROCHIP_MPLAB_HARMONY + #include "system_config.h" + #include "crypto/crypto.h" +#else + #include "crypto.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef NO_MD5 +/* Initialize MD5 */ +int CRYPT_MD5_Initialize(CRYPT_MD5_CTX* md5) +{ + typedef char md5_test[sizeof(CRYPT_MD5_CTX) >= sizeof(Md5) ? 1 : -1]; + (void)sizeof(md5_test); + + if (md5 == NULL) + return BAD_FUNC_ARG; + + return wc_InitMd5((Md5*)md5); +} + +int CRYPT_MD5_DataSizeSet(CRYPT_MD5_CTX* md5, unsigned int sz) +{ + if (md5 == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_PIC32MZ_HASH + wc_Md5SizeSet((Md5*)md5, sz); +#else + (void)sz; +#endif + + return 0; +} + +/* Add data to MD5 */ +int CRYPT_MD5_DataAdd(CRYPT_MD5_CTX* md5, const unsigned char* input, + unsigned int sz) +{ + if (md5 == NULL || input == NULL) + return BAD_FUNC_ARG; + + return wc_Md5Update((Md5*)md5, input, sz); +} + + +/* Get MD5 Final into digest */ +int CRYPT_MD5_Finalize(CRYPT_MD5_CTX* md5, unsigned char* digest) +{ + if (md5 == NULL || digest == NULL) + return BAD_FUNC_ARG; + + return wc_Md5Final((Md5*)md5, digest); +} +#endif + +#ifndef NO_SHA + +/* Initialize SHA */ +int CRYPT_SHA_Initialize(CRYPT_SHA_CTX* sha) +{ + typedef char sha_test[sizeof(CRYPT_SHA_CTX) >= sizeof(Sha) ? 1 : -1]; + (void)sizeof(sha_test); + + if (sha == NULL) + return BAD_FUNC_ARG; + + return wc_InitSha((wc_Sha*)sha); +} + +int CRYPT_SHA_DataSizeSet(CRYPT_SHA_CTX* sha, unsigned int sz) +{ + if (sha == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_PIC32MZ_HASH + wc_ShaSizeSet((wc_Sha*)sha, sz); +#else + (void)sz; +#endif + + return 0; +} + +/* Add data to SHA */ +int CRYPT_SHA_DataAdd(CRYPT_SHA_CTX* sha, const unsigned char* input, + unsigned int sz) +{ + if (sha == NULL || input == NULL) + return BAD_FUNC_ARG; + + return wc_ShaUpdate((wc_Sha*)sha, input, sz); +} + + +/* Get SHA Final into digest */ +int CRYPT_SHA_Finalize(CRYPT_SHA_CTX* sha, unsigned char* digest) +{ + if (sha == NULL || digest == NULL) + return BAD_FUNC_ARG; + + return wc_ShaFinal((wc_Sha*)sha, digest); +} +#endif + +#ifndef NO_SHA256 + +/* Initialize SHA-256 */ +int CRYPT_SHA256_Initialize(CRYPT_SHA256_CTX* sha256) +{ + typedef char sha_test[sizeof(CRYPT_SHA256_CTX) >= sizeof(wc_Sha256) ? 1 : -1]; + (void)sizeof(sha_test); + + if (sha256 == NULL) + return BAD_FUNC_ARG; + + return wc_InitSha256((wc_Sha256*)sha256); +} + +int CRYPT_SHA256_DataSizeSet(CRYPT_SHA256_CTX* sha256, unsigned int sz) +{ + if (sha256 == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_PIC32MZ_HASH + wc_Sha256SizeSet((wc_Sha256*)sha256, sz); +#else + (void)sz; +#endif + + return 0; +} + +/* Add data to SHA-256 */ +int CRYPT_SHA256_DataAdd(CRYPT_SHA256_CTX* sha256, const unsigned char* input, + unsigned int sz) +{ + if (sha256 == NULL || input == NULL) + return BAD_FUNC_ARG; + + return wc_Sha256Update((wc_Sha256*)sha256, input, sz); +} + + +/* Get SHA-256 Final into digest */ +int CRYPT_SHA256_Finalize(CRYPT_SHA256_CTX* sha256, unsigned char* digest) +{ + if (sha256 == NULL || digest == NULL) + return BAD_FUNC_ARG; + + return wc_Sha256Final((wc_Sha256*)sha256, digest); +} +#endif + +#ifdef WOLFSSL_SHA512 +#ifdef WOLFSSL_SHA384 +/* Initialize SHA-384 */ +int CRYPT_SHA384_Initialize(CRYPT_SHA384_CTX* sha384) +{ + typedef char sha_test[sizeof(CRYPT_SHA384_CTX) >= sizeof(wc_Sha384) ? 1 : -1]; + (void)sizeof(sha_test); + + if (sha384 == NULL) + return BAD_FUNC_ARG; + + return wc_InitSha384((wc_Sha384*)sha384); +} + + +/* Add data to SHA-384 */ +int CRYPT_SHA384_DataAdd(CRYPT_SHA384_CTX* sha384, const unsigned char* input, + unsigned int sz) +{ + if (sha384 == NULL || input == NULL) + return BAD_FUNC_ARG; + + return wc_Sha384Update((wc_Sha384*)sha384, input, sz); +} + + +/* Get SHA-384 Final into digest */ +int CRYPT_SHA384_Finalize(CRYPT_SHA384_CTX* sha384, unsigned char* digest) +{ + if (sha384 == NULL || digest == NULL) + return BAD_FUNC_ARG; + + return wc_Sha384Final((wc_Sha384*)sha384, digest); +} +#endif + + +/* Initialize SHA-512 */ +int CRYPT_SHA512_Initialize(CRYPT_SHA512_CTX* sha512) +{ + typedef char sha_test[sizeof(CRYPT_SHA512_CTX) >= sizeof(wc_Sha512) ? 1 : -1]; + (void)sizeof(sha_test); + + if (sha512 == NULL) + return BAD_FUNC_ARG; + + return wc_InitSha512((wc_Sha512*)sha512); +} + + +/* Add data to SHA-512 */ +int CRYPT_SHA512_DataAdd(CRYPT_SHA512_CTX* sha512, const unsigned char* input, + unsigned int sz) +{ + if (sha512 == NULL || input == NULL) + return BAD_FUNC_ARG; + + return wc_Sha512Update((wc_Sha512*)sha512, input, sz); +} + + +/* Get SHA-512 Final into digest */ +int CRYPT_SHA512_Finalize(CRYPT_SHA512_CTX* sha512, unsigned char* digest) +{ + if (sha512 == NULL || digest == NULL) + return BAD_FUNC_ARG; + + return wc_Sha512Final((wc_Sha512*)sha512, digest); +} +#endif + +#ifndef NO_HMAC +/* Set HMAC key with type */ +int CRYPT_HMAC_SetKey(CRYPT_HMAC_CTX* hmac, int type, const unsigned char* key, + unsigned int sz) +{ + /* compile-time check to verify CRYPT_HMAC_CTX is large enough to hold Hmac */ + typedef char hmac_test[sizeof(CRYPT_HMAC_CTX) >= sizeof(Hmac) ? 1 : -1]; + (void)sizeof(hmac_test); + + if (hmac == NULL || key == NULL) + return BAD_FUNC_ARG; + + if (type != CRYPT_HMAC_SHA && type != CRYPT_HMAC_SHA256 && + type != CRYPT_HMAC_SHA384 && type != CRYPT_HMAC_SHA512) { + return BAD_FUNC_ARG; /* bad hmac type */ + } + + return wc_HmacSetKey((Hmac*)hmac, type, key, sz); +} + + +int CRYPT_HMAC_DataAdd(CRYPT_HMAC_CTX* hmac, const unsigned char* input, + unsigned int sz) +{ + if (hmac == NULL || input == NULL) + return BAD_FUNC_ARG; + + return wc_HmacUpdate((Hmac*)hmac, input, sz); +} + + +/* Get HMAC Final into digest */ +int CRYPT_HMAC_Finalize(CRYPT_HMAC_CTX* hmac, unsigned char* digest) +{ + if (hmac == NULL || digest == NULL) + return BAD_FUNC_ARG; + + return wc_HmacFinal((Hmac*)hmac, digest); +} + +#endif + +#ifdef HAVE_LIBZ + +/* Huffman Compression, set flag to do static, otherwise dynamic */ +/* return compressed size, otherwise < 0 for error */ +int CRYPT_HUFFMAN_Compress(unsigned char* out, unsigned int outSz, + const unsigned char* in, unsigned int inSz, + unsigned int flags) +{ + if (out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_Compress(out, outSz, in, inSz, flags); +} + + +/* Huffman DeCompression, self determines type */ +/* return decompressed size, otherwise < 0 for error */ +int CRYPT_HUFFMAN_DeCompress(unsigned char* out, unsigned int outSz, + const unsigned char* in, unsigned int inSz) +{ + if (out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_DeCompress(out, outSz, in, inSz); +} + +#endif + +#ifndef NO_RNG + +/* RNG Initialize, < 0 on error */ +int CRYPT_RNG_Initialize(CRYPT_RNG_CTX* rng) +{ + typedef char rng_test[sizeof(CRYPT_RNG_CTX) >= sizeof(WC_RNG) ? 1 : -1]; + (void)sizeof(rng_test); + + if (rng == NULL) + return BAD_FUNC_ARG; + + return wc_InitRng((WC_RNG*)rng); +} + + +/* RNG Get single bytes, < 0 on error */ +int CRYPT_RNG_Get(CRYPT_RNG_CTX* rng, unsigned char* b) +{ + if (rng == NULL || b == NULL) + return BAD_FUNC_ARG; + + return wc_RNG_GenerateByte((WC_RNG*)rng, (byte*)b); +} + + +/* RNG Block Generation of sz bytes, < 0 on error */ +int CRYPT_RNG_BlockGenerate(CRYPT_RNG_CTX* rng, unsigned char* b, + unsigned int sz) +{ + if (rng == NULL || b == NULL) + return BAD_FUNC_ARG; + + return wc_RNG_GenerateBlock((WC_RNG*)rng, b, sz); +} + +#endif + +#ifndef NO_DES3 +/* Triple DES Key Set, may have iv, will have direction */ +int CRYPT_TDES_KeySet(CRYPT_TDES_CTX* tdes, const unsigned char* key, + const unsigned char* iv, int dir) +{ + typedef char tdes_test[sizeof(CRYPT_TDES_CTX) >= sizeof(Des3) ? 1 : -1]; + (void)sizeof(tdes_test); + + if (tdes == NULL || key == NULL) + return BAD_FUNC_ARG; + + return wc_Des3_SetKey((Des3*)tdes, key, iv, dir); +} + + +/* Triple DES Iv Set, sometimes added later */ +int CRYPT_TDES_IvSet(CRYPT_TDES_CTX* tdes, const unsigned char* iv) +{ + if (tdes == NULL || iv == NULL) + return BAD_FUNC_ARG; + + return wc_Des3_SetIV((Des3*)tdes, iv); +} + + +/* Triple DES CBC Encrypt */ +int CRYPT_TDES_CBC_Encrypt(CRYPT_TDES_CTX* tdes, unsigned char* out, + const unsigned char* in, unsigned int inSz) +{ + if (tdes == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_Des3_CbcEncrypt((Des3*)tdes, out, in, inSz); +} + + +/* Triple DES CBC Decrypt */ +int CRYPT_TDES_CBC_Decrypt(CRYPT_TDES_CTX* tdes, unsigned char* out, + const unsigned char* in, unsigned int inSz) +{ + if (tdes == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_Des3_CbcDecrypt((Des3*)tdes, out, in, inSz); +} + +#endif + +#ifndef NO_AES + +/* AES Key Set, may have iv, will have direction */ +int CRYPT_AES_KeySet(CRYPT_AES_CTX* aes, const unsigned char* key, + unsigned int keyLen, const unsigned char* iv, int dir) +{ + typedef char aes_test[sizeof(CRYPT_AES_CTX) >= sizeof(Aes) ? 1 : -1]; + (void)sizeof(aes_test); + + if (aes == NULL || key == NULL) + return BAD_FUNC_ARG; + + return wc_AesSetKey((Aes*)aes, key, keyLen, iv, dir); +} + + +/* AES Iv Set, sometimes added later */ +int CRYPT_AES_IvSet(CRYPT_AES_CTX* aes, const unsigned char* iv) +{ + if (aes == NULL || iv == NULL) + return BAD_FUNC_ARG; + + return wc_AesSetIV((Aes*)aes, iv); +} + + +/* AES CBC Encrypt */ +int CRYPT_AES_CBC_Encrypt(CRYPT_AES_CTX* aes, unsigned char* out, + const unsigned char* in, unsigned int inSz) +{ + if (aes == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_AesCbcEncrypt((Aes*)aes, out, in, inSz); +} + + +/* AES CBC Decrypt */ +int CRYPT_AES_CBC_Decrypt(CRYPT_AES_CTX* aes, unsigned char* out, + const unsigned char* in, unsigned int inSz) +{ + if (aes == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_AesCbcDecrypt((Aes*)aes, out, in, inSz); +} +#endif + +#ifdef WOLFSSL_AES_COUNTER +/* AES CTR Encrypt (used for decrypt too, with ENCRYPT key setup) */ +int CRYPT_AES_CTR_Encrypt(CRYPT_AES_CTX* aes, unsigned char* out, + const unsigned char* in, unsigned int inSz) +{ + if (aes == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_AesCtrEncrypt((Aes*)aes, out, in, inSz); +} +#endif + +#ifdef WOLFSSL_AES_DIRECT + +/* AES Direct mode encrypt, one block at a time */ +int CRYPT_AES_DIRECT_Encrypt(CRYPT_AES_CTX* aes, unsigned char* out, + const unsigned char* in) +{ + if (aes == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + wc_AesEncryptDirect((Aes*)aes, out, in); + + return 0; +} + + +/* AES Direct mode decrypt, one block at a time */ +int CRYPT_AES_DIRECT_Decrypt(CRYPT_AES_CTX* aes, unsigned char* out, + const unsigned char* in) +{ + if (aes == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + wc_AesDecryptDirect((Aes*)aes, out, in); + + return 0; +} +#endif + +#ifndef NO_RSA + +/* RSA Initialize */ +int CRYPT_RSA_Initialize(CRYPT_RSA_CTX* rsa) +{ + if (rsa == NULL) + return BAD_FUNC_ARG; + + rsa->holder = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (rsa->holder == NULL) + return -1; + + return wc_InitRsaKey((RsaKey*)rsa->holder, NULL); +} + + +/* RSA Free resources */ +int CRYPT_RSA_Free(CRYPT_RSA_CTX* rsa) +{ + if (rsa == NULL) + return BAD_FUNC_ARG; + + wc_FreeRsaKey((RsaKey*)rsa->holder); + XFREE(rsa->holder, NULL, DYNAMIC_TYPE_RSA); + rsa->holder = NULL; + + return 0; +} + + +/* RSA Public key decode ASN.1 */ +int CRYPT_RSA_PublicKeyDecode(CRYPT_RSA_CTX* rsa, const unsigned char* in, + unsigned int inSz) +{ + unsigned int idx = 0; + (void)idx; + + if (rsa == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_RsaPublicKeyDecode(in, &idx, (RsaKey*)rsa->holder, inSz); +} + + +/* RSA Private key decode ASN.1 */ +int CRYPT_RSA_PrivateKeyDecode(CRYPT_RSA_CTX* rsa, const unsigned char* in, + unsigned int inSz) +{ + unsigned int idx = 0; + (void)idx; + + if (rsa == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_RsaPrivateKeyDecode(in, &idx, (RsaKey*)rsa->holder, inSz); +} + + +/* RSA Public Encrypt */ +int CRYPT_RSA_PublicEncrypt(CRYPT_RSA_CTX* rsa, unsigned char* out, + unsigned int outSz, const unsigned char* in, + unsigned int inSz, CRYPT_RNG_CTX* rng) +{ + if (rsa == NULL || in == NULL || out == NULL || rng == NULL) + return BAD_FUNC_ARG; + + return wc_RsaPublicEncrypt(in, inSz, out, outSz, (RsaKey*)rsa->holder, + (WC_RNG*)rng); +} + + +/* RSA Private Decrypt */ +int CRYPT_RSA_PrivateDecrypt(CRYPT_RSA_CTX* rsa, unsigned char* out, + unsigned int outSz, const unsigned char* in, + unsigned int inSz) +{ + if (rsa == NULL || in == NULL || out == NULL) + return BAD_FUNC_ARG; + + return wc_RsaPrivateDecrypt(in, inSz, out, outSz, (RsaKey*)rsa->holder); +} + + +/* RSA Get Encrypt size helper */ +int CRYPT_RSA_EncryptSizeGet(CRYPT_RSA_CTX* rsa) +{ + if (rsa == NULL) + return BAD_FUNC_ARG; + + return wc_RsaEncryptSize((RsaKey*)rsa->holder); +} + + +int CRYPT_RSA_SetRng(CRYPT_RSA_CTX* rsa, CRYPT_RNG_CTX* rng) +{ + if (rsa == NULL) + return BAD_FUNC_ARG; + +#ifdef WC_RSA_BLINDING + return wc_RsaSetRNG((RsaKey*)rsa->holder, (WC_RNG*)rng); +#else + (void)rng; + + return 0; +#endif +} +#endif + +#ifdef HAVE_ECC + +/* ECC init */ +int CRYPT_ECC_Initialize(CRYPT_ECC_CTX* ecc) +{ + if (ecc == NULL) + return BAD_FUNC_ARG; + + ecc->holder = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC); + if (ecc->holder == NULL) + return -1; + + wc_ecc_init((ecc_key*)ecc->holder); + + return 0; +} + + +/* ECC free resources */ +int CRYPT_ECC_Free(CRYPT_ECC_CTX* ecc) +{ + if (ecc == NULL) + return BAD_FUNC_ARG; + + wc_ecc_free((ecc_key*)ecc->holder); + XFREE(ecc->holder, NULL, DYNAMIC_TYPE_ECC); + ecc->holder = NULL; + + return 0; +} + + +/* ECC Public x963 Export */ +int CRYPT_ECC_PublicExport(CRYPT_ECC_CTX* ecc, unsigned char* out, + unsigned int outSz, unsigned int* usedSz) +{ + int ret; + unsigned int inOut = outSz; + + if (ecc == NULL || out == NULL) + return BAD_FUNC_ARG; + + ret = wc_ecc_export_x963((ecc_key*)ecc->holder, out, &inOut); + *usedSz = inOut; + + return ret; +} + + +/* ECC Public x963 Import */ +int CRYPT_ECC_PublicImport(CRYPT_ECC_CTX* ecc, const unsigned char* in, + unsigned int inSz) +{ + if (ecc == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_ecc_import_x963(in, inSz, (ecc_key*)ecc->holder); +} + + +/* ECC Private x963 Import */ +int CRYPT_ECC_PrivateImport(CRYPT_ECC_CTX* ecc, const unsigned char* priv, + unsigned int privSz, const unsigned char* pub, unsigned int pubSz) +{ + if (ecc == NULL || priv == NULL || pub == NULL) + return BAD_FUNC_ARG; + + return wc_ecc_import_private_key(priv, privSz, pub, pubSz, + (ecc_key*)ecc->holder); +} + + +/* ECC DHE Make key */ +int CRYPT_ECC_DHE_KeyMake(CRYPT_ECC_CTX* ecc, CRYPT_RNG_CTX* rng, int keySz) +{ + if (ecc == NULL || rng == NULL) + return BAD_FUNC_ARG; + + return wc_ecc_make_key((WC_RNG*)rng, keySz, (ecc_key*)ecc->holder); +} + + +/* ECC DHE Make shared secret with our private and peer public */ +int CRYPT_ECC_DHE_SharedSecretMake(CRYPT_ECC_CTX* priv, CRYPT_ECC_CTX* pub, + unsigned char* out, unsigned int outSz, unsigned int* usedSz) +{ + int ret; + unsigned int inOut = outSz; + + if (priv == NULL || pub == NULL || out == NULL || usedSz == NULL) + return BAD_FUNC_ARG; + + ret = wc_ecc_shared_secret((ecc_key*)priv->holder, (ecc_key*)pub->holder, + out, &inOut); + *usedSz = inOut; + + return ret; +} + + +/* ECC DSA Hash Sign */ +int CRYPT_ECC_DSA_HashSign(CRYPT_ECC_CTX* ecc, CRYPT_RNG_CTX* rng, + unsigned char* sig, unsigned int sigSz, + unsigned int* usedSz, const unsigned char* in, + unsigned int inSz) +{ + int ret; + unsigned int inOut = sigSz; + + if (ecc == NULL || rng == NULL || sig == NULL || usedSz == NULL || + in == NULL) + return BAD_FUNC_ARG; + + ret = wc_ecc_sign_hash(in, inSz, sig, &inOut, (WC_RNG*)rng, + (ecc_key*)ecc->holder); + *usedSz = inOut; + + return ret; +} + + +/* ECC DSA Hash Verify */ +int CRYPT_ECC_DSA_HashVerify(CRYPT_ECC_CTX* ecc, const unsigned char* sig, + unsigned int sigSz, unsigned char* hash, + unsigned int hashSz, int* status) +{ + if (ecc == NULL || sig == NULL || hash == NULL || status == NULL) + return BAD_FUNC_ARG; + + return wc_ecc_verify_hash(sig, sigSz, hash, hashSz, status, + (ecc_key*)ecc->holder); +} + + +/* ECC get key size helper */ +int CRYPT_ECC_KeySizeGet(CRYPT_ECC_CTX* ecc) +{ + if (ecc == NULL) + return BAD_FUNC_ARG; + + return wc_ecc_size((ecc_key*)ecc->holder); +} + + +/* ECC get signature size helper */ +int CRYPT_ECC_SignatureSizeGet(CRYPT_ECC_CTX* ecc) +{ + if (ecc == NULL) + return BAD_FUNC_ARG; + + return wc_ecc_sig_size((ecc_key*)ecc->holder); +} + +#endif + +/* Save error string from err to str which needs to be >= 80 chars */ +int CRYPT_ERROR_StringGet(int err, char* str) +{ + if (str == NULL) + return BAD_FUNC_ARG; + + wc_ErrorString(err, str); + + return 0; +} + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/crypto.h b/FreeRTOS-Plus/Source/WolfSSL/mcapi/crypto.h new file mode 100644 index 000000000..ddb450b63 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/crypto.h @@ -0,0 +1,273 @@ +/* crypto.h + * + * Copyright (C) 2006-2020 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 + */ + + + +/* Defines Microchip CRYPTO API layer */ + + +#ifndef MC_CRYPTO_API_H +#define MC_CRYPTO_API_H + + +#ifdef __cplusplus + extern "C" { +#endif + +/* MD5 */ +typedef struct CRYPT_MD5_CTX { + int holder[28]; /* big enough to hold internal, but check on init */ +} CRYPT_MD5_CTX; + +int CRYPT_MD5_Initialize(CRYPT_MD5_CTX*); +int CRYPT_MD5_DataAdd(CRYPT_MD5_CTX*, const unsigned char*, unsigned int); +int CRYPT_MD5_Finalize(CRYPT_MD5_CTX*, unsigned char*); +int CRYPT_MD5_DataSizeSet(CRYPT_MD5_CTX* md5, unsigned int sz); + +enum { + CRYPT_MD5_DIGEST_SIZE = 16 +}; + + +/* SHA */ +typedef struct CRYPT_SHA_CTX { + int holder[29]; /* big enough to hold internal, but check on init */ +} CRYPT_SHA_CTX; + +int CRYPT_SHA_Initialize(CRYPT_SHA_CTX*); +int CRYPT_SHA_DataAdd(CRYPT_SHA_CTX*, const unsigned char*, unsigned int); +int CRYPT_SHA_Finalize(CRYPT_SHA_CTX*, unsigned char*); +int CRYPT_SHA_DataSizeSet(CRYPT_SHA_CTX* sha, unsigned int sz); + +enum { + CRYPT_SHA_DIGEST_SIZE = 20 +}; + + +/* SHA-256 */ +typedef struct CRYPT_SHA256_CTX { + int holder[32]; /* big enough to hold internal, but check on init */ +} CRYPT_SHA256_CTX; + +int CRYPT_SHA256_Initialize(CRYPT_SHA256_CTX*); +int CRYPT_SHA256_DataAdd(CRYPT_SHA256_CTX*, const unsigned char*, unsigned int); +int CRYPT_SHA256_Finalize(CRYPT_SHA256_CTX*, unsigned char*); +int CRYPT_SHA256_DataSizeSet(CRYPT_SHA256_CTX* sha256, unsigned int sz); + +enum { + CRYPT_SHA256_DIGEST_SIZE = 32 +}; + + +/* SHA-384 */ +typedef struct CRYPT_SHA384_CTX { + long long holder[36]; /* big enough to hold internal, but check on init */ +} CRYPT_SHA384_CTX; + +int CRYPT_SHA384_Initialize(CRYPT_SHA384_CTX*); +int CRYPT_SHA384_DataAdd(CRYPT_SHA384_CTX*, const unsigned char*, unsigned int); +int CRYPT_SHA384_Finalize(CRYPT_SHA384_CTX*, unsigned char*); + +enum { + CRYPT_SHA384_DIGEST_SIZE = 48 +}; + + +/* SHA-512 */ +typedef struct CRYPT_SHA512_CTX { + long long holder[36]; /* big enough to hold internal, but check on init */ +} CRYPT_SHA512_CTX; + +int CRYPT_SHA512_Initialize(CRYPT_SHA512_CTX*); +int CRYPT_SHA512_DataAdd(CRYPT_SHA512_CTX*, const unsigned char*, unsigned int); +int CRYPT_SHA512_Finalize(CRYPT_SHA512_CTX*, unsigned char*); + +enum { + CRYPT_SHA512_DIGEST_SIZE = 64 +}; + + +/* HMAC */ +typedef struct CRYPT_HMAC_CTX { + long long holder[98]; /* big enough to hold internal, but check on init */ +} CRYPT_HMAC_CTX; + +int CRYPT_HMAC_SetKey(CRYPT_HMAC_CTX*, int, const unsigned char*, unsigned int); +int CRYPT_HMAC_DataAdd(CRYPT_HMAC_CTX*, const unsigned char*, unsigned int); +int CRYPT_HMAC_Finalize(CRYPT_HMAC_CTX*, unsigned char*); + +/* HMAC types */ +enum { + CRYPT_HMAC_SHA = 4, + CRYPT_HMAC_SHA256 = 6, + CRYPT_HMAC_SHA384 = 7, + CRYPT_HMAC_SHA512 = 8 +}; + + +/* Huffman */ +int CRYPT_HUFFMAN_Compress(unsigned char*, unsigned int, const unsigned char*, + unsigned int, unsigned int); +int CRYPT_HUFFMAN_DeCompress(unsigned char*, unsigned int, const unsigned char*, + unsigned int); + +/* flag to use static huffman */ +enum { + CRYPT_HUFFMAN_COMPRESS_STATIC = 1 +}; + + +/* RNG */ +typedef struct CRYPT_RNG_CTX { + int holder[66]; /* big enough to hold internal, but check on init */ +} CRYPT_RNG_CTX; + +int CRYPT_RNG_Initialize(CRYPT_RNG_CTX*); +int CRYPT_RNG_Get(CRYPT_RNG_CTX*, unsigned char*); +int CRYPT_RNG_BlockGenerate(CRYPT_RNG_CTX*, unsigned char*, unsigned int); + + +/* TDES */ +typedef struct CRYPT_TDES_CTX { + int holder[104]; /* big enough to hold internal, but check on init */ +} CRYPT_TDES_CTX; + +int CRYPT_TDES_KeySet(CRYPT_TDES_CTX*, const unsigned char*, + const unsigned char*, int); +int CRYPT_TDES_IvSet(CRYPT_TDES_CTX*, const unsigned char*); +int CRYPT_TDES_CBC_Encrypt(CRYPT_TDES_CTX*, unsigned char*, + const unsigned char*, unsigned int); +int CRYPT_TDES_CBC_Decrypt(CRYPT_TDES_CTX*, unsigned char*, + const unsigned char*, unsigned int); + +/* key direction flags for setup */ +enum { + CRYPT_TDES_ENCRYPTION = 0, + CRYPT_TDES_DECRYPTION = 1 +}; + + +/* AES */ +typedef struct CRYPT_AES_CTX { + int holder[90]; /* big enough to hold internal, but check on init */ +} CRYPT_AES_CTX; + +/* key */ +int CRYPT_AES_KeySet(CRYPT_AES_CTX*, const unsigned char*, unsigned int, + const unsigned char*, int); +int CRYPT_AES_IvSet(CRYPT_AES_CTX*, const unsigned char*); + +/* cbc */ +int CRYPT_AES_CBC_Encrypt(CRYPT_AES_CTX*, unsigned char*, + const unsigned char*, unsigned int); +int CRYPT_AES_CBC_Decrypt(CRYPT_AES_CTX*, unsigned char*, + const unsigned char*, unsigned int); + +/* ctr (counter), use Encrypt both ways with ENCRYPT key setup */ +int CRYPT_AES_CTR_Encrypt(CRYPT_AES_CTX*, unsigned char*, + const unsigned char*, unsigned int); + +/* direct, one block at a time */ +int CRYPT_AES_DIRECT_Encrypt(CRYPT_AES_CTX*, unsigned char*, + const unsigned char*); +int CRYPT_AES_DIRECT_Decrypt(CRYPT_AES_CTX*, unsigned char*, + const unsigned char*); + +/* key direction flags for setup, ctr always uses ENCRYPT flag */ +enum { + CRYPT_AES_ENCRYPTION = 0, + CRYPT_AES_DECRYPTION = 1, + CRYPT_AES_BLOCK_SIZE = 16 +}; + + + +/* RSA */ +typedef struct CRYPT_RSA_CTX { + void* holder; +} CRYPT_RSA_CTX; + +/* init/free */ +int CRYPT_RSA_Initialize(CRYPT_RSA_CTX*); +int CRYPT_RSA_Free(CRYPT_RSA_CTX*); + +/* key decode */ +int CRYPT_RSA_PublicKeyDecode(CRYPT_RSA_CTX*, const unsigned char*, + unsigned int); +int CRYPT_RSA_PrivateKeyDecode(CRYPT_RSA_CTX*, const unsigned char*, + unsigned int); + +/* encrypt/decrypt */ +int CRYPT_RSA_PublicEncrypt(CRYPT_RSA_CTX*, unsigned char*, + unsigned int, const unsigned char*, unsigned int, + CRYPT_RNG_CTX*); +int CRYPT_RSA_PrivateDecrypt(CRYPT_RSA_CTX*, unsigned char*, + unsigned int, const unsigned char*, unsigned int); + +/* helpers */ +int CRYPT_RSA_EncryptSizeGet(CRYPT_RSA_CTX*); +int CRYPT_RSA_SetRng(CRYPT_RSA_CTX*, CRYPT_RNG_CTX*); + + + +/* ECC */ +typedef struct CRYPT_ECC_CTX { + void* holder; +} CRYPT_ECC_CTX; + +/* init/free */ +int CRYPT_ECC_Initialize(CRYPT_ECC_CTX*); +int CRYPT_ECC_Free(CRYPT_ECC_CTX*); + +/* key coders */ +int CRYPT_ECC_PublicExport(CRYPT_ECC_CTX*, unsigned char*, unsigned int, + unsigned int*); +int CRYPT_ECC_PublicImport(CRYPT_ECC_CTX*, const unsigned char*, unsigned int); +int CRYPT_ECC_PrivateImport(CRYPT_ECC_CTX*, const unsigned char*, unsigned int, + const unsigned char*, unsigned int); + +/* dhe */ +int CRYPT_ECC_DHE_KeyMake(CRYPT_ECC_CTX*, CRYPT_RNG_CTX*, int); +int CRYPT_ECC_DHE_SharedSecretMake(CRYPT_ECC_CTX*, CRYPT_ECC_CTX*, + unsigned char*, unsigned int, unsigned int*); + +/* dsa */ +int CRYPT_ECC_DSA_HashSign(CRYPT_ECC_CTX*, CRYPT_RNG_CTX*, unsigned char*, + unsigned int, unsigned int*, const unsigned char*, unsigned int); +int CRYPT_ECC_DSA_HashVerify(CRYPT_ECC_CTX*, const unsigned char*, + unsigned int, unsigned char*, unsigned int, int*); + +/* helpers */ +int CRYPT_ECC_KeySizeGet(CRYPT_ECC_CTX*); +int CRYPT_ECC_SignatureSizeGet(CRYPT_ECC_CTX*); + + +/* Error string helper, string needs to be >= 80 chars */ +int CRYPT_ERROR_StringGet(int, char*); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* MC_CRYPTO_API_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/include.am b/FreeRTOS-Plus/Source/WolfSSL/mcapi/include.am new file mode 100644 index 000000000..9448a5232 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/include.am @@ -0,0 +1,19 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +if BUILD_MCAPI +check_PROGRAMS += mcapi/test +noinst_PROGRAMS += mcapi/test +mcapi_test_SOURCES = mcapi/crypto.c \ + mcapi/mcapi_test.c +mcapi_test_LDADD = src/libwolfssl.la +mcapi_test_DEPENDENCIES = src/libwolfssl.la +endif + +noinst_HEADERS += mcapi/crypto.h + +EXTRA_DIST += \ + mcapi/README \ + mcapi/PIC32MZ-serial.h \ + mcapi/user_settings.h diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/mcapi_test.c b/FreeRTOS-Plus/Source/WolfSSL/mcapi/mcapi_test.c new file mode 100644 index 000000000..cf0c31075 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/mcapi_test.c @@ -0,0 +1,1510 @@ +/* mcapi_test.c + * + * Copyright (C) 2006-2020 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 + */ + + + +/* Tests Microchip CRYPTO API layer */ + + + +/* mc api header */ +#include "crypto.h" + +#include + +/* sanity test against our default implementation, wolfssl headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define USE_CERT_BUFFERS_1024 +#include + +#if defined(WOLFSSL_MICROCHIP_PIC32MZ) + #define MICROCHIP_PIC32 + #include + #pragma config ICESEL = ICS_PGx2 + /* ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2) */ + #include + #include + #include "PIC32MZ-serial.h" + #define SYSTEMConfigPerformance(n) /* void out SYSTEMConfigPerformance(); */ +#elif defined(MICROCHIP_PIC32) + #define PIC32_STARTER_KIT + #include + #include + #include + #define _SUPPRESS_PLIB_WARNING + #define _DISABLE_OPENADC10_CONFIGPORT_WARNING + #include + #include + #define init_serial() /* void out init_serial() */ +#else + #include /* order matters above ? */ +#endif +#define OUR_DATA_SIZE 1024 +static byte ourData[OUR_DATA_SIZE]; +static byte* key = NULL; +static byte* iv = NULL; +static CRYPT_RNG_CTX mcRng; +static WC_RNG defRng; + +static int check_md5(void); +static int check_sha(void); +static int check_sha256(void); +static int check_sha384(void); +static int check_sha512(void); +static int check_hmac(void); +static int check_compress(void); +static int check_rng(void); +static int check_des3(void); +static int check_aescbc(void); +static int check_aesctr(void); +static int check_aesdirect(void); +static int check_rsa(void); +static int check_ecc(void); + + +int main(int argc, char** argv) +{ + int ret; + int i; + + (void)argc; + (void)argv; + +#if defined(MICROCHIP_PIC32) + init_serial() ; /* initialize PIC32MZ serial I/O */ + SYSTEMConfigPerformance(80000000); + DBINIT(); +#endif + + /* align key, iv pointers */ + key = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_KEY); + if (key == NULL) { + printf("mcapi key alloc failed\n"); + return -1; + } + + iv = (byte*)XMALLOC(16, NULL, DYNAMIC_TYPE_KEY); + if (iv == NULL) { + printf("mcapi iv alloc failed\n"); + return -1; + } + + for (i = 0; i < OUR_DATA_SIZE; i++) + ourData[i] = (byte)i; + + ret = check_md5(); + if (ret != 0) { + printf("mcapi check_md5 failed\n"); + return -1; + } + + ret = check_sha(); + if (ret != 0) { + printf("mcapi check_sha failed\n"); + return -1; + } + + ret = check_sha256(); + if (ret != 0) { + printf("mcapi check_sha256 failed\n"); + return -1; + } + + ret = check_sha384(); + if (ret != 0) { + printf("mcapi check_sha384 failed\n"); + return -1; + } + + ret = check_sha512(); + if (ret != 0) { + printf("mcapi check_sha512 failed\n"); + return -1; + } + + ret = check_hmac(); + if (ret != 0) { + printf("mcapi check_hmac failed\n"); + return -1; + } + + ret = check_compress(); + if (ret != 0) { + printf("mcapi check_compress failed\n"); + return -1; + } + + ret = check_rng(); + if (ret != 0) { + printf("mcapi check_rng failed\n"); + return -1; + } + + ret = check_des3(); + if (ret != 0) { + printf("mcapi check_des3 failed\n"); + return -1; + } + + ret = check_aescbc(); + if (ret != 0) { + printf("mcapi check_aes cbc failed\n"); + return -1; + } + + ret = check_aesctr(); + if (ret != 0) { + printf("mcapi check_aes ctr failed\n"); + return -1; + } + + ret = check_aesdirect(); + if (ret != 0) { + printf("mcapi check_aes direct failed\n"); + return -1; + } + + ret = check_rsa(); + if (ret != 0) { + printf("mcapi check_rsa failed\n"); + return -1; + } + + ret = check_ecc(); + if (ret != 0) { + printf("mcapi check_ecc failed\n"); + return -1; + } + + XFREE(iv, NULL, DYNAMIC_TYPE_KEY); + XFREE(key, NULL, DYNAMIC_TYPE_KEY); + + return 0; +} + + +/* check mcapi md5 against internal */ +static int check_md5(void) +{ + CRYPT_MD5_CTX mcMd5; + Md5 defMd5; + int ret; + byte mcDigest[CRYPT_MD5_DIGEST_SIZE]; + byte defDigest[MD5_DIGEST_SIZE]; + + CRYPT_MD5_Initialize(&mcMd5); + ret = wc_InitMd5(&defMd5); + + if (ret == 0) { + CRYPT_MD5_DataAdd(&mcMd5, ourData, OUR_DATA_SIZE); + ret = wc_Md5Update(&defMd5, ourData, OUR_DATA_SIZE); + } + + if (ret == 0) { + CRYPT_MD5_Finalize(&mcMd5, mcDigest); + ret = wc_Md5Final(&defMd5, defDigest); + } + + if (ret != 0) { + printf("md5 failed\n"); + return -1; + } + + if (ret == 0 && memcmp(mcDigest, defDigest, CRYPT_MD5_DIGEST_SIZE) != 0) { + printf("md5 final memcmp failed\n"); + return -1; + } + printf("md5 mcapi test passed\n"); + + return ret; +} + + +/* check mcapi sha against internal */ +static int check_sha(void) +{ + CRYPT_SHA_CTX mcSha; + Sha defSha; + int ret = 0; + byte mcDigest[CRYPT_SHA_DIGEST_SIZE]; + byte defDigest[SHA_DIGEST_SIZE]; + + CRYPT_SHA_Initialize(&mcSha); + ret = wc_InitSha(&defSha); + if (ret != 0) { + printf("sha init default failed\n"); + return -1; + } + + CRYPT_SHA_DataAdd(&mcSha, ourData, OUR_DATA_SIZE); + wc_ShaUpdate(&defSha, ourData, OUR_DATA_SIZE); + + CRYPT_SHA_Finalize(&mcSha, mcDigest); + wc_ShaFinal(&defSha, defDigest); + + if (memcmp(mcDigest, defDigest, CRYPT_SHA_DIGEST_SIZE) != 0) { + printf("sha final memcmp failed\n"); + return -1; + } + printf("sha mcapi test passed\n"); + + return 0; +} + + +/* check mcapi sha256 against internal */ +static int check_sha256(void) +{ + CRYPT_SHA256_CTX mcSha256; + wc_Sha256 defSha256; + int ret; + byte mcDigest[CRYPT_SHA256_DIGEST_SIZE]; + byte defDigest[WC_SHA256_DIGEST_SIZE]; + + CRYPT_SHA256_Initialize(&mcSha256); + ret = wc_InitSha256(&defSha256); + if (ret != 0) { + printf("sha256 init default failed\n"); + return -1; + } + + CRYPT_SHA256_DataAdd(&mcSha256, ourData, OUR_DATA_SIZE); + ret = wc_Sha256Update(&defSha256, ourData, OUR_DATA_SIZE); + if (ret != 0) { + printf("sha256 update default failed\n"); + return -1; + } + + CRYPT_SHA256_Finalize(&mcSha256, mcDigest); + ret = wc_Sha256Final(&defSha256, defDigest); + if (ret != 0) { + printf("sha256 final default failed\n"); + return -1; + } + + if (memcmp(mcDigest, defDigest, CRYPT_SHA256_DIGEST_SIZE) != 0) { + printf("sha256 final memcmp fialed\n"); + return -1; + } + printf("sha256 mcapi test passed\n"); + + return 0; +} + + +/* check mcapi sha384 against internal */ +static int check_sha384(void) +{ + CRYPT_SHA384_CTX mcSha384; + wc_Sha384 defSha384; + int ret; + byte mcDigest[CRYPT_SHA384_DIGEST_SIZE]; + byte defDigest[WC_SHA384_DIGEST_SIZE]; + + CRYPT_SHA384_Initialize(&mcSha384); + ret = wc_InitSha384(&defSha384); + if (ret != 0) { + printf("sha384 init default failed\n"); + return -1; + } + + CRYPT_SHA384_DataAdd(&mcSha384, ourData, OUR_DATA_SIZE); + ret = wc_Sha384Update(&defSha384, ourData, OUR_DATA_SIZE); + if (ret != 0) { + printf("sha384 update default failed\n"); + return -1; + } + + CRYPT_SHA384_Finalize(&mcSha384, mcDigest); + ret = wc_Sha384Final(&defSha384, defDigest); + if (ret != 0) { + printf("sha384 final default failed\n"); + return -1; + } + + if (memcmp(mcDigest, defDigest, CRYPT_SHA384_DIGEST_SIZE) != 0) { + printf("sha384 final memcmp fialed\n"); + return -1; + } + printf("sha384 mcapi test passed\n"); + + return 0; +} + + +/* check mcapi sha512 against internal */ +static int check_sha512(void) +{ + CRYPT_SHA512_CTX mcSha512; + wc_Sha512 defSha512; + int ret; + byte mcDigest[CRYPT_SHA512_DIGEST_SIZE]; + byte defDigest[WC_SHA512_DIGEST_SIZE]; + + CRYPT_SHA512_Initialize(&mcSha512); + ret = wc_InitSha512(&defSha512); + if (ret != 0) { + printf("sha512 init default failed\n"); + return -1; + } + + CRYPT_SHA512_DataAdd(&mcSha512, ourData, OUR_DATA_SIZE); + ret = wc_Sha512Update(&defSha512, ourData, OUR_DATA_SIZE); + if (ret != 0) { + printf("sha512 update default failed\n"); + return -1; + } + + CRYPT_SHA512_Finalize(&mcSha512, mcDigest); + ret = wc_Sha512Final(&defSha512, defDigest); + if (ret != 0) { + printf("sha512 final default failed\n"); + return -1; + } + + if (memcmp(mcDigest, defDigest, CRYPT_SHA512_DIGEST_SIZE) != 0) { + printf("sha512 final memcmp fialed\n"); + return -1; + } + printf("sha512 mcapi test passed\n"); + + return 0; +} + + +/* check mcapi hmac against internal */ +static int check_hmac(void) +{ + CRYPT_HMAC_CTX mcHmac; + Hmac defHmac; + int ret; + byte mcDigest[CRYPT_SHA512_DIGEST_SIZE]; + byte defDigest[WC_SHA512_DIGEST_SIZE]; + + memcpy((char*)key, "Jefe", 4); + + /* SHA1 */ + CRYPT_HMAC_SetKey(&mcHmac, CRYPT_HMAC_SHA, key, 4); + ret = wc_HmacSetKey(&defHmac, WC_SHA, key, 4); + if (ret != 0) { + printf("hmac sha setkey default failed\n"); + return -1; + } + + CRYPT_HMAC_DataAdd(&mcHmac, ourData, OUR_DATA_SIZE); + ret = wc_HmacUpdate(&defHmac, ourData, OUR_DATA_SIZE); + if (ret != 0) { + printf("hmac sha update default failed\n"); + return -1; + } + + CRYPT_HMAC_Finalize(&mcHmac, mcDigest); + ret = wc_HmacFinal(&defHmac, defDigest); + if (ret != 0) { + printf("hmac sha final default failed\n"); + return -1; + } + + if (memcmp(mcDigest, defDigest, CRYPT_SHA_DIGEST_SIZE) != 0) { + printf("hmac sha final memcmp fialed\n"); + return -1; + } + printf("hmac sha mcapi test passed\n"); + + /* SHA-256 */ + CRYPT_HMAC_SetKey(&mcHmac, CRYPT_HMAC_SHA256, key, 4); + ret = wc_HmacSetKey(&defHmac, WC_SHA256, key, 4); + if (ret != 0) { + printf("hmac sha256 setkey default failed\n"); + return -1; + } + + CRYPT_HMAC_DataAdd(&mcHmac, ourData, OUR_DATA_SIZE); + ret = wc_HmacUpdate(&defHmac, ourData, OUR_DATA_SIZE); + if (ret != 0) { + printf("hmac sha256 update default failed\n"); + return -1; + } + + CRYPT_HMAC_Finalize(&mcHmac, mcDigest); + ret = wc_HmacFinal(&defHmac, defDigest); + if (ret != 0) { + printf("hmac sha256 final default failed\n"); + return -1; + } + + if (memcmp(mcDigest, defDigest, CRYPT_SHA256_DIGEST_SIZE) != 0) { + printf("hmac sha256 final memcmp fialed\n"); + return -1; + } + printf("hmac sha256 mcapi test passed\n"); + + /* SHA-384 */ + CRYPT_HMAC_SetKey(&mcHmac, CRYPT_HMAC_SHA384, key, 4); + ret = wc_HmacSetKey(&defHmac, WC_SHA384, key, 4); + if (ret != 0) { + printf("hmac sha384 setkey default failed\n"); + return -1; + } + + CRYPT_HMAC_DataAdd(&mcHmac, ourData, OUR_DATA_SIZE); + ret = wc_HmacUpdate(&defHmac, ourData, OUR_DATA_SIZE); + if (ret != 0) { + printf("hmac sha384 update default failed\n"); + return -1; + } + + CRYPT_HMAC_Finalize(&mcHmac, mcDigest); + ret = wc_HmacFinal(&defHmac, defDigest); + if (ret != 0) { + printf("hmac sha384 final default failed\n"); + return -1; + } + + if (memcmp(mcDigest, defDigest, CRYPT_SHA384_DIGEST_SIZE) != 0) { + printf("hmac sha384 final memcmp fialed\n"); + return -1; + } + printf("hmac sha384 mcapi test passed\n"); + + /* SHA-512 */ + CRYPT_HMAC_SetKey(&mcHmac, CRYPT_HMAC_SHA512, key, 4); + ret = wc_HmacSetKey(&defHmac, WC_SHA512, key, 4); + if (ret != 0) { + printf("hmac sha512 setkey default failed\n"); + return -1; + } + + CRYPT_HMAC_DataAdd(&mcHmac, ourData, OUR_DATA_SIZE); + ret = wc_HmacUpdate(&defHmac, ourData, OUR_DATA_SIZE); + if (ret != 0) { + printf("hmac sha512 update default failed\n"); + return -1; + } + + CRYPT_HMAC_Finalize(&mcHmac, mcDigest); + ret = wc_HmacFinal(&defHmac, defDigest); + if (ret != 0) { + printf("hmac sha512 final default failed\n"); + return -1; + } + + if (memcmp(mcDigest, defDigest, CRYPT_SHA512_DIGEST_SIZE) != 0) { + printf("hmac sha512 final memcmp fialed\n"); + return -1; + } + printf("hmac sha512 mcapi test passed\n"); + + return 0; +} + + +/* check mcapi compress against internal */ +static int check_compress(void) +{ + const unsigned char text[] = + "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" + "four loko whatever street art yr farm-to-table.\n"; + + unsigned int inSz = sizeof(text); + unsigned int outSz; + unsigned char cBuffer[1024]; + unsigned char dBuffer[1024]; + + int ret1, ret2; + + /* dynamic */ + ret1 = CRYPT_HUFFMAN_Compress(cBuffer, sizeof(cBuffer), text, inSz, 0); + ret2 = wc_Compress(dBuffer, sizeof(dBuffer), text, inSz, 0); + + if (ret1 != ret2 || ret1 < 0) { + printf("compress dynamic ret failed\n"); + return -1; + } + + if (memcmp(cBuffer, dBuffer, ret1) != 0) { + printf("compress dynamic cmp failed\n"); + return -1; + } + + outSz = ret1; + + ret1 = CRYPT_HUFFMAN_DeCompress(dBuffer, sizeof(dBuffer), cBuffer, outSz); + + if (memcmp(dBuffer, text, inSz) != 0) { + printf("mcapi decompress dynamic cmp failed\n"); + return -1; + } + + memset(dBuffer, 0, sizeof(dBuffer)); + + ret1 = wc_DeCompress(dBuffer, sizeof(dBuffer), cBuffer, outSz); + + if (memcmp(dBuffer, text, inSz) != 0) { + printf("decompress dynamic cmp failed\n"); + return -1; + } + + memset(cBuffer, 0, sizeof(cBuffer)); + memset(dBuffer, 0, sizeof(dBuffer)); + + /* static */ + ret1 = CRYPT_HUFFMAN_Compress(cBuffer, sizeof(cBuffer), text, inSz, 1); + ret2 = wc_Compress(dBuffer, sizeof(dBuffer), text, inSz, 1); + + if (ret1 != ret2 || ret1 < 0) { + printf("compress static ret failed\n"); + return -1; + } + + if (memcmp(cBuffer, dBuffer, ret1) != 0) { + printf("compress static cmp failed\n"); + return -1; + } + + outSz = ret1; + + ret1 = CRYPT_HUFFMAN_DeCompress(dBuffer, sizeof(dBuffer), cBuffer, outSz); + + if (memcmp(dBuffer, text, inSz) != 0) { + printf("mcapi decompress static cmp failed\n"); + return -1; + } + + memset(dBuffer, 0, sizeof(dBuffer)); + + ret1 = wc_DeCompress(dBuffer, sizeof(dBuffer), cBuffer, outSz); + + if (memcmp(dBuffer, text, inSz) != 0) { + printf("decompress static cmp failed\n"); + return -1; + } + + printf("huffman mcapi test passed\n"); + + return 0; +} + + +#define RANDOM_BYTE_SZ 32 + +/* check mcapi rng */ +static int check_rng(void) +{ + int ret; + int i; + byte in[RANDOM_BYTE_SZ]; + byte out[RANDOM_BYTE_SZ]; + + for (i = 0; i < RANDOM_BYTE_SZ; i++) + in[i] = (byte)i; + + for (i = 0; i < RANDOM_BYTE_SZ; i++) + out[i] = (byte)i; + + ret = wc_InitRng(&defRng); + if (ret != 0) { + printf("default rng init failed\n"); + return -1; + } + + ret = CRYPT_RNG_Initialize(&mcRng); + if (ret != 0) { + printf("mcapi rng init failed\n"); + return -1; + } + + ret = CRYPT_RNG_Get(&mcRng, &out[0]); + if (ret != 0) { + printf("mcapi rng get failed\n"); + return -1; + } + + ret = CRYPT_RNG_BlockGenerate(&mcRng, out, RANDOM_BYTE_SZ); + if (ret != 0) { + printf("mcapi rng block gen failed\n"); + return -1; + } + + if (memcmp(in, out, RANDOM_BYTE_SZ) == 0) { + printf("mcapi rng block gen output failed\n"); + return -1; + } + + printf("rng mcapi test passed\n"); + + return 0; +} + + +#define TDES_TEST_SIZE 32 + +/* check mcapi des3 */ +static int check_des3(void) +{ + CRYPT_TDES_CTX mcDes3; + Des3 defDes3; + int ret; + byte out1[TDES_TEST_SIZE]; + byte out2[TDES_TEST_SIZE]; + + memcpy((char*)key, "1234567890abcdefghijklmn", 24); + memcpy((char*)iv, "12345678", 8); + + /* cbc encrypt */ + ret = CRYPT_TDES_KeySet(&mcDes3, key, iv, CRYPT_TDES_ENCRYPTION); + if (ret != 0) { + printf("mcapi tdes key set failed\n"); + return -1; + } + ret = wc_Des3_SetKey(&defDes3, key, iv, DES_ENCRYPTION); + if (ret != 0) { + printf("default des3 key set failed\n"); + return -1; + } + + ret = CRYPT_TDES_CBC_Encrypt(&mcDes3, out1, ourData, TDES_TEST_SIZE); + if (ret != 0) { + printf("mcapi tdes cbc encrypt failed\n"); + return -1; + } + ret = wc_Des3_CbcEncrypt(&defDes3, out2, ourData, TDES_TEST_SIZE); + if (ret != 0) { + printf("mcapi default tdes cbc encrypt failed\n"); + return -1; + } + + if (memcmp(out1, out2, TDES_TEST_SIZE) != 0) { + printf("mcapi tdes cbc encrypt cmp failed\n"); + return -1; + } + + /* cbc decrypt */ + ret = CRYPT_TDES_KeySet(&mcDes3, key, iv, CRYPT_TDES_DECRYPTION); + if (ret != 0) { + printf("mcapi tdes key set failed\n"); + return -1; + } + ret = wc_Des3_SetKey(&defDes3, key, iv, DES_DECRYPTION); + if (ret != 0) { + printf("default des3 key set failed\n"); + return -1; + } + + ret = CRYPT_TDES_CBC_Decrypt(&mcDes3, out2, out1, TDES_TEST_SIZE); + if (ret != 0) { + printf("mcapi tdes cbc decrypt failed\n"); + return -1; + } + ret = wc_Des3_CbcDecrypt(&defDes3, out1, out1, TDES_TEST_SIZE); + if (ret != 0) { + printf("mcapi default tdes cbc decrypt failed\n"); + return -1; + } + + if (memcmp(out1, out2, TDES_TEST_SIZE) != 0) { + printf("mcapi tdes cbc decrypt cmp failed\n"); + return -1; + } + + if (memcmp(out1, ourData, TDES_TEST_SIZE) != 0) { + printf("mcapi tdes cbc decrypt orig cmp failed\n"); + return -1; + } + + printf("tdes mcapi test passed\n"); + + return 0; +} + + +#define AES_TEST_SIZE 32 + +/* check mcapi aes cbc */ +static int check_aescbc(void) +{ + CRYPT_AES_CTX mcAes; + Aes defAes; + int ret; + byte out1[AES_TEST_SIZE]; + byte out2[AES_TEST_SIZE]; + + memcpy((char*)key, "1234567890abcdefghijklmnopqrstuv", 32); + memcpy((char*)iv, "1234567890abcdef", 16); + + /* 128 cbc encrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 16, iv, CRYPT_AES_ENCRYPTION); + if (ret != 0) { + printf("mcapi aes-128 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 16, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("default aes-128 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_CBC_Encrypt(&mcAes, out1, ourData, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-128 cbc encrypt failed\n"); + return -1; + } + wc_AesCbcEncrypt(&defAes, out2, ourData, AES_TEST_SIZE); + + if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { + printf("mcapi aes-128 cbc encrypt cmp failed\n"); + return -1; + } + + /* 128 cbc decrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 16, iv, CRYPT_AES_DECRYPTION); + if (ret != 0) { + printf("mcapi aes-128 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 16, iv, DES_DECRYPTION); + if (ret != 0) { + printf("default aes-128 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_CBC_Decrypt(&mcAes, out2, out1, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-128 cbc decrypt failed\n"); + return -1; + } + wc_AesCbcDecrypt(&defAes, out1, out1, AES_TEST_SIZE); + + if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { + printf("mcapi aes-128 cbc decrypt cmp failed\n"); + return -1; + } + + if (memcmp(out1, ourData, AES_TEST_SIZE) != 0) { + printf("mcapi aes-128 cbc decrypt orig cmp failed\n"); + return -1; + } + + /* 192 cbc encrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 24, iv, CRYPT_AES_ENCRYPTION); + if (ret != 0) { + printf("mcapi aes-192 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 24, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("default aes-192 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_CBC_Encrypt(&mcAes, out1, ourData, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-192 cbc encrypt failed\n"); + return -1; + } + wc_AesCbcEncrypt(&defAes, out2, ourData, AES_TEST_SIZE); + + if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { + printf("mcapi aes-192 cbc encrypt cmp failed\n"); + return -1; + } + + /* 192 cbc decrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 24, iv, CRYPT_AES_DECRYPTION); + if (ret != 0) { + printf("mcapi aes-192 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 24, iv, AES_DECRYPTION); + if (ret != 0) { + printf("default aes-192 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_CBC_Decrypt(&mcAes, out2, out1, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-192 cbc decrypt failed\n"); + return -1; + } + wc_AesCbcDecrypt(&defAes, out1, out1, AES_TEST_SIZE); + + if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { + printf("mcapi aes-192 cbc decrypt cmp failed\n"); + return -1; + } + + if (memcmp(out1, ourData, AES_TEST_SIZE) != 0) { + printf("mcapi aes-192 cbc decrypt orig cmp failed\n"); + return -1; + } + + /* 256 cbc encrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 32, iv, CRYPT_AES_ENCRYPTION); + if (ret != 0) { + printf("mcapi aes-256 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 32, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("default aes-256 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_CBC_Encrypt(&mcAes, out1, ourData, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-256 cbc encrypt failed\n"); + return -1; + } + wc_AesCbcEncrypt(&defAes, out2, ourData, AES_TEST_SIZE); + + if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { + printf("mcapi aes-256 cbc encrypt cmp failed\n"); + return -1; + } + + /* 256 cbc decrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 32, iv, CRYPT_AES_DECRYPTION); + if (ret != 0) { + printf("mcapi aes-256 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 32, iv, AES_DECRYPTION); + if (ret != 0) { + printf("default aes-256 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_CBC_Decrypt(&mcAes, out2, out1, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-256 cbc decrypt failed\n"); + return -1; + } + wc_AesCbcDecrypt(&defAes, out1, out1, AES_TEST_SIZE); + + if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { + printf("mcapi aes-256 cbc decrypt cmp failed\n"); + return -1; + } + + if (memcmp(out1, ourData, AES_TEST_SIZE) != 0) { + printf("mcapi aes-256 cbc decrypt orig cmp failed\n"); + return -1; + } + + printf("aes-cbc mcapi test passed\n"); + + return 0; +} + + +/* check mcapi aes ctr */ +static int check_aesctr(void) +{ + CRYPT_AES_CTX mcAes; + Aes defAes; + int ret; + byte out1[AES_TEST_SIZE]; + byte out2[AES_TEST_SIZE]; + + memcpy((char*)key, "1234567890abcdefghijklmnopqrstuv", 32); + memcpy((char*)iv, "1234567890abcdef", 16); + + /* 128 ctr encrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 16, iv, CRYPT_AES_ENCRYPTION); + if (ret != 0) { + printf("mcapi aes-128 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 16, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("default aes-128 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_CTR_Encrypt(&mcAes, out1, ourData, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-128 ctr encrypt failed\n"); + return -1; + } + ret = wc_AesCtrEncrypt(&defAes, out2, ourData, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-128 ctr encrypt set failed\n"); + return -1; + } + if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { + printf("mcapi aes-128 ctr encrypt cmp failed\n"); + return -1; + } + + /* 128 ctr decrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 16, iv, CRYPT_AES_ENCRYPTION); + if (ret != 0) { + printf("mcapi aes-128 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 16, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("default aes-128 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_CTR_Encrypt(&mcAes, out2, out1, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-128 ctr decrypt failed\n"); + return -1; + } + + if (memcmp(out2, ourData, AES_TEST_SIZE) != 0) { + printf("mcapi aes-128 ctr decrypt orig cmp failed\n"); + return -1; + } + + /* 192 ctr encrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 24, iv, CRYPT_AES_ENCRYPTION); + if (ret != 0) { + printf("mcapi aes-192 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 24, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("default aes-192 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_CTR_Encrypt(&mcAes, out1, ourData, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-192 ctr encrypt failed\n"); + return -1; + } + ret = wc_AesCtrEncrypt(&defAes, out2, ourData, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-192 ctr encrypt set failed\n"); + return -1; + } + if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { + printf("mcapi aes-192 ctr encrypt cmp failed\n"); + return -1; + } + + /* 192 ctr decrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 24, iv, CRYPT_AES_ENCRYPTION); + if (ret != 0) { + printf("mcapi aes-192 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 24, iv, AES_DECRYPTION); + if (ret != 0) { + printf("default aes-192 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_CTR_Encrypt(&mcAes, out2, out1, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-192 ctr decrypt failed\n"); + return -1; + } + + if (memcmp(out2, ourData, AES_TEST_SIZE) != 0) { + printf("mcapi aes-192 ctr decrypt orig cmp failed\n"); + return -1; + } + + /* 256 ctr encrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 32, iv, CRYPT_AES_ENCRYPTION); + if (ret != 0) { + printf("mcapi aes-256 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 32, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("default aes-256 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_CTR_Encrypt(&mcAes, out1, ourData, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-256 ctr encrypt failed\n"); + return -1; + } + ret = wc_AesCtrEncrypt(&defAes, out2, ourData, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-256 ctr encrypt set failed\n"); + return -1; + } + if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { + printf("mcapi aes-256 ctr encrypt cmp failed\n"); + return -1; + } + + /* 256 ctr decrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 32, iv, CRYPT_AES_ENCRYPTION); + if (ret != 0) { + printf("mcapi aes-256 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 32, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("default aes-256 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_CTR_Encrypt(&mcAes, out2, out1, AES_TEST_SIZE); + if (ret != 0) { + printf("mcapi aes-256 ctr decrypt failed\n"); + return -1; + } + + if (memcmp(out2, ourData, AES_TEST_SIZE) != 0) { + printf("mcapi aes-256 ctr decrypt orig cmp failed\n"); + return -1; + } + + printf("aes-ctr mcapi test passed\n"); + + return 0; +} + + +/* check mcapi aes direct */ +static int check_aesdirect(void) +{ + CRYPT_AES_CTX mcAes; + Aes defAes; + int ret; + byte out1[CRYPT_AES_BLOCK_SIZE]; + byte out2[16]; /* one block at a time */ + + memcpy((char*)key, "1234567890abcdefghijklmnopqrstuv", 32); + memcpy((char*)iv, "1234567890abcdef", 16); + + /* 128 direct encrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 16, iv, CRYPT_AES_ENCRYPTION); + if (ret != 0) { + printf("mcapi aes-128 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 16, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("default aes-128 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_DIRECT_Encrypt(&mcAes, out1, ourData); + if (ret != 0) { + printf("mcapi aes-128 direct encrypt failed\n"); + return -1; + } + wc_AesEncryptDirect(&defAes, out2, ourData); + + if (memcmp(out1, out2, CRYPT_AES_BLOCK_SIZE) != 0) { + printf("mcapi aes-128 direct encrypt cmp failed\n"); + return -1; + } + + /* 128 direct decrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 16, iv, CRYPT_AES_DECRYPTION); + if (ret != 0) { + printf("mcapi aes-128 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 16, iv, DES_DECRYPTION); + if (ret != 0) { + printf("default aes-128 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_DIRECT_Decrypt(&mcAes, out2, out1); + if (ret != 0) { + printf("mcapi aes-128 direct decrypt failed\n"); + return -1; + } + wc_AesDecryptDirect(&defAes, out1, out1); + + if (memcmp(out1, out2, CRYPT_AES_BLOCK_SIZE) != 0) { + printf("mcapi aes-128 direct decrypt cmp failed\n"); + return -1; + } + + if (memcmp(out1, ourData, CRYPT_AES_BLOCK_SIZE) != 0) { + printf("mcapi aes-128 direct decrypt orig cmp failed\n"); + return -1; + } + + /* 192 direct encrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 24, iv, CRYPT_AES_ENCRYPTION); + if (ret != 0) { + printf("mcapi aes-192 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 24, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("default aes-192 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_DIRECT_Encrypt(&mcAes, out1, ourData); + if (ret != 0) { + printf("mcapi aes-192 direct encrypt failed\n"); + return -1; + } + wc_AesEncryptDirect(&defAes, out2, ourData); + + if (memcmp(out1, out2, CRYPT_AES_BLOCK_SIZE) != 0) { + printf("mcapi aes-192 direct encrypt cmp failed\n"); + return -1; + } + + /* 192 direct decrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 24, iv, CRYPT_AES_DECRYPTION); + if (ret != 0) { + printf("mcapi aes-192 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 24, iv, AES_DECRYPTION); + if (ret != 0) { + printf("default aes-192 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_DIRECT_Decrypt(&mcAes, out2, out1); + if (ret != 0) { + printf("mcapi aes-192 direct decrypt failed\n"); + return -1; + } + wc_AesDecryptDirect(&defAes, out1, out1); + + if (memcmp(out1, out2, CRYPT_AES_BLOCK_SIZE) != 0) { + printf("mcapi aes-192 direct decrypt cmp failed\n"); + return -1; + } + + if (memcmp(out1, ourData, CRYPT_AES_BLOCK_SIZE) != 0) { + printf("mcapi aes-192 direct decrypt orig cmp failed\n"); + return -1; + } + + /* 256 direct encrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 32, iv, CRYPT_AES_ENCRYPTION); + if (ret != 0) { + printf("mcapi aes-256 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 32, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("default aes-256 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_DIRECT_Encrypt(&mcAes, out1, ourData); + if (ret != 0) { + printf("mcapi aes-256 direct encrypt failed\n"); + return -1; + } + wc_AesEncryptDirect(&defAes, out2, ourData); + + if (memcmp(out1, out2, CRYPT_AES_BLOCK_SIZE) != 0) { + printf("mcapi aes-256 direct encrypt cmp failed\n"); + return -1; + } + + /* 256 direct decrypt */ + ret = CRYPT_AES_KeySet(&mcAes, key, 32, iv, CRYPT_AES_DECRYPTION); + if (ret != 0) { + printf("mcapi aes-256 key set failed\n"); + return -1; + } + ret = wc_AesSetKey(&defAes, key, 32, iv, AES_DECRYPTION); + if (ret != 0) { + printf("default aes-256 key set failed\n"); + return -1; + } + + ret = CRYPT_AES_DIRECT_Decrypt(&mcAes, out2, out1); + if (ret != 0) { + printf("mcapi aes-256 direct decrypt failed\n"); + return -1; + } + wc_AesDecryptDirect(&defAes, out1, out1); + + if (memcmp(out1, out2, CRYPT_AES_BLOCK_SIZE) != 0) { + printf("mcapi aes-256 direct decrypt cmp failed\n"); + return -1; + } + + if (memcmp(out1, ourData, CRYPT_AES_BLOCK_SIZE) != 0) { + printf("mcapi aes-256 direct decrypt orig cmp failed\n"); + return -1; + } + + printf("aes-direct mcapi test passed\n"); + + return 0; +} + + +#define RSA_TEST_SIZE 64 + +/* check mcapi rsa */ +static int check_rsa(void) +{ + CRYPT_RSA_CTX mcRsa; + RsaKey defRsa; + int ret; + int ret2; + unsigned int keySz = (unsigned int)sizeof(client_key_der_1024); + unsigned int idx = 0; + byte out1[256]; + byte out2[256]; + + ret = wc_InitRsaKey(&defRsa, NULL); + if (ret == 0) + ret = CRYPT_RSA_Initialize(&mcRsa); + if (ret != 0) { + printf("mcapi rsa init failed\n"); + return -1; + } + + ret = CRYPT_RSA_PrivateKeyDecode(&mcRsa, client_key_der_1024, keySz); + if (ret != 0) { + printf("mcapi rsa private key decode failed\n"); + return -1; + } + + ret = wc_RsaPrivateKeyDecode(client_key_der_1024, &idx, &defRsa, keySz); + if (ret != 0) { + printf("default rsa private key decode failed\n"); + return -1; + } + + ret = CRYPT_RSA_SetRng(&mcRsa, &mcRng); + if (ret != 0) { + printf("mcapi rsa set rng failed\n"); + return -1; + } + + ret = CRYPT_RSA_PublicEncrypt(&mcRsa, out1, sizeof(out1), ourData, + RSA_TEST_SIZE, &mcRng); + if (ret < 0) { + printf("mcapi rsa public encrypt failed\n"); + return -1; + } + + ret2 = wc_RsaPublicEncrypt(ourData, RSA_TEST_SIZE, out2, sizeof(out2), + &defRsa, &defRng); + if (ret2 < 0) { + printf("default rsa public encrypt failed\n"); + return -1; + } + + if (ret != ret2) { + printf("default rsa public encrypt sz != mcapi sz\n"); + return -1; + } + + if (ret != CRYPT_RSA_EncryptSizeGet(&mcRsa)) { + printf("mcapi encrypt sz get != mcapi sz\n"); + return -1; + } + + ret = CRYPT_RSA_PrivateDecrypt(&mcRsa, out2, sizeof(out2), out1, ret); + if (ret < 0) { + printf("mcapi rsa private derypt failed\n"); + return -1; + } + + if (ret != RSA_TEST_SIZE) { + printf("mcapi rsa private derypt plain size wrong\n"); + return -1; + } + + if (memcmp(out2, ourData, ret) != 0) { + printf("mcapi rsa private derypt plain text bad\n"); + return -1; + } + + wc_FreeRsaKey(&defRsa); + ret = CRYPT_RSA_Free(&mcRsa); + if (ret != 0) { + printf("mcapi rsa free failed\n"); + return -1; + } + + printf("rsa mcapi test passed\n"); + + return 0; +} + + +/* check mcapi ecc */ +static int check_ecc(void) +{ + CRYPT_ECC_CTX userA; + CRYPT_ECC_CTX userB; + int ret; + byte sharedA[100]; + byte sharedB[100]; + byte sig[100]; + unsigned int aSz = (unsigned int)sizeof(sharedA); + unsigned int bSz = (unsigned int)sizeof(sharedB); + unsigned int sigSz = (unsigned int)sizeof(sig); + unsigned int usedA = 0; + unsigned int usedB = 0; + int verifyStatus = 0; + + /* init */ + ret = CRYPT_ECC_Initialize(&userA); + if (ret != 0) { + printf("mcapi ecc init failed\n"); + return -1; + } + + ret = CRYPT_ECC_Initialize(&userB); + if (ret != 0) { + printf("mcapi ecc init b failed\n"); + return -1; + } + + /* dhe + helpers */ + ret = CRYPT_ECC_DHE_KeyMake(&userA, &mcRng, 32); + if (ret != 0) { + printf("mcapi ecc make key failed\n"); + return -1; + } + + ret = CRYPT_ECC_DHE_KeyMake(&userB, &mcRng, 32); + if (ret != 0) { + printf("mcapi ecc make key b failed\n"); + return -1; + } + + ret = CRYPT_ECC_KeySizeGet(&userA); + if (ret <= 0) { + printf("mcapi ecc key size get failed\n"); + return -1; + } + + ret = CRYPT_ECC_SignatureSizeGet(&userA); + if (ret <= 0) { + printf("mcapi ecc signature size get failed\n"); + return -1; + } + + ret = CRYPT_ECC_DHE_SharedSecretMake(&userA, &userB, sharedA, aSz, &usedA); + if (ret != 0) { + printf("mcapi ecc make shared secret failed\n"); + return -1; + } + + ret = CRYPT_ECC_DHE_SharedSecretMake(&userB, &userA, sharedB, bSz, &usedB); + if (ret != 0) { + printf("mcapi ecc make shared secret failed\n"); + return -1; + } + + if (usedA != usedB || usedA == 0) { + printf("mcapi ecc make shared secret output size match failed\n"); + return -1; + } + + if (memcmp(sharedA, sharedB, usedA) != 0) { + printf("mcapi ecc make shared secret output match cmp failed\n"); + return -1; + } + + /* dsa */ + ret = CRYPT_ECC_DSA_HashSign(&userA, &mcRng, sig, sigSz, &usedA, ourData, + CRYPT_SHA_DIGEST_SIZE); + if (ret != 0) { + printf("mcapi ecc sign hash failed\n"); + return -1; + } + + sigSz = usedA; + if (sigSz == 0) { + printf("mcapi ecc sign hash bad sig size\n"); + return -1; + } + + ret = CRYPT_ECC_DSA_HashVerify(&userA, sig, sigSz, ourData, + CRYPT_SHA_DIGEST_SIZE, &verifyStatus); + if (ret != 0) { + printf("mcapi ecc verify hash failed\n"); + return -1; + } + if (verifyStatus != 1) { + printf("mcapi ecc verify hash status failed\n"); + return -1; + } + + /* import / export */ + usedA = 0; + ret = CRYPT_ECC_PublicExport(&userA, sharedA, aSz, &usedA); + if (ret != 0) { + printf("mcapi ecc public export failed\n"); + return -1; + } + + ret = CRYPT_ECC_PublicImport(&userB, sharedA, usedA); + if (ret != 0) { + printf("mcapi ecc public import failed\n"); + return -1; + } + + ret = CRYPT_ECC_Free(&userA); + if (ret != 0) { + printf("mcapi ecc free failed\n"); + return -1; + } + + ret = CRYPT_ECC_Free(&userB); + if (ret != 0) { + printf("mcapi ecc free b failed\n"); + return -1; + } + + printf("ecc mcapi test passed\n"); + + return 0; +} + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/user_settings.h b/FreeRTOS-Plus/Source/WolfSSL/mcapi/user_settings.h new file mode 100644 index 000000000..b89a6f785 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/user_settings.h @@ -0,0 +1,386 @@ +/* Example custom user settings for wolfSSL */ + +#ifndef WOLFSSL_USER_SETTINGS_H +#define WOLFSSL_USER_SETTINGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include /* for size_t */ + + +/* ------------------------------------------------------------------------- */ +/* Platform */ +/* ------------------------------------------------------------------------- */ +#undef WOLFSSL_GENERAL_ALIGNMENT +#define WOLFSSL_GENERAL_ALIGNMENT 4 + +#undef SINGLE_THREADED +#define SINGLE_THREADED + +#undef WOLFSSL_SMALL_STACK +#define WOLFSSL_SMALL_STACK + +#undef MICROCHIP_PIC32 +#define MICROCHIP_PIC32 + +#undef WOLFSSL_MICROCHIP_PIC32MZ +#define WOLFSSL_MICROCHIP_PIC32MZ + + +/* ------------------------------------------------------------------------- */ +/* Math Configuration */ +/* ------------------------------------------------------------------------- */ +#undef USE_FAST_MATH +#define USE_FAST_MATH + +#ifdef USE_FAST_MATH + #undef TFM_TIMING_RESISTANT + #define TFM_TIMING_RESISTANT + + /* Optimizations */ + //#define TFM_MIPS +#endif + + +/* ------------------------------------------------------------------------- */ +/* Crypto */ +/* ------------------------------------------------------------------------- */ +/* ECC */ +#if 1 + #undef HAVE_ECC + #define HAVE_ECC + + /* Manually define enabled curves */ + #undef ECC_USER_CURVES + #define ECC_USER_CURVES + + //#define HAVE_ECC192 + //#define HAVE_ECC224 + #undef NO_ECC256 + //#define HAVE_ECC384 + //#define HAVE_ECC521 + + /* Fixed point cache (speeds repeated operations against same private key) */ + #undef FP_ECC + //#define FP_ECC + #ifdef FP_ECC + /* Bits / Entries */ + #undef FP_ENTRIES + #define FP_ENTRIES 2 + #undef FP_LUT + #define FP_LUT 4 + #endif + + /* Optional ECC calculation method */ + /* Note: doubles heap usage, but slightly faster */ + #undef ECC_SHAMIR + #define ECC_SHAMIR + + /* Reduces heap usage, but slower */ + #undef ECC_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + + #ifdef USE_FAST_MATH + /* use reduced size math buffers for ecc points */ + #undef ALT_ECC_SIZE + #define ALT_ECC_SIZE + + /* Enable TFM optimizations for ECC */ + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #define TFM_ECC192 + #endif + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #define TFM_ECC224 + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #define TFM_ECC256 + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #define TFM_ECC384 + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #define TFM_ECC521 + #endif + #endif +#endif + +/* RSA */ +#undef NO_RSA +#if 1 + #ifdef USE_FAST_MATH + /* Maximum math bits (Max RSA key bits * 2) */ + #undef FP_MAX_BITS + #define FP_MAX_BITS 4096 + #endif + + /* half as much memory but twice as slow */ + #undef RSA_LOW_MEM + //#define RSA_LOW_MEM + + /* timing resistance */ + #undef WC_RSA_BLINDING + #define WC_RSA_BLINDING +#else + #define NO_RSA +#endif + +/* AES */ +#undef NO_AES +#if 1 + #undef HAVE_AES_DECRYPT + #define HAVE_AES_DECRYPT + + #undef HAVE_AESGCM + #define HAVE_AESGCM + + /* GCM Method: GCM_SMALL, GCM_WORD32 or GCM_TABLE */ + #undef GCM_SMALL + #define GCM_SMALL + + #undef HAVE_AESCCM + #define HAVE_AESCCM + + #undef WOLFSSL_AES_COUNTER + #define WOLFSSL_AES_COUNTER + + #undef WOLFSSL_AES_DIRECT + #define WOLFSSL_AES_DIRECT +#else + #define NO_AES +#endif + +/* DES3 */ +#undef NO_DES3 +#if 1 + #undef WOLFSSL_DES_ECB + #define WOLFSSL_DES_ECB +#else + #define NO_DES3 +#endif + + +/* ChaCha20 / Poly1305 */ +#undef HAVE_CHACHA +#undef HAVE_POLY1305 +#if 0 + #define HAVE_CHACHA + #define HAVE_POLY1305 + + /* Needed for Poly1305 */ + #undef HAVE_ONE_TIME_AUTH + #define HAVE_ONE_TIME_AUTH +#endif + +/* Ed25519 / Curve25519 */ +#undef HAVE_CURVE25519 +#undef HAVE_ED25519 +#if 0 + #define HAVE_CURVE25519 + #define HAVE_ED25519 + + /* Optionally use small math (less flash usage, but much slower) */ + #if 0 + #define CURVED25519_SMALL + #endif +#endif + + +/* ------------------------------------------------------------------------- */ +/* Hashing */ +/* ------------------------------------------------------------------------- */ +/* Sha */ +#undef NO_SHA +#if 1 + /* 1k smaller, but 25% slower */ + //#define USE_SLOW_SHA +#else + #define NO_SHA +#endif + +/* Sha256 */ +#undef NO_SHA256 +#if 1 +#else + #define NO_SHA256 +#endif + +/* Sha512 */ +#undef WOLFSSL_SHA512 +#if 1 + #define WOLFSSL_SHA512 + + /* Sha384 */ + #undef WOLFSSL_SHA384 + #if 1 + #define WOLFSSL_SHA384 + #endif + + /* over twice as small, but 50% slower */ + //#define USE_SLOW_SHA2 +#endif + +/* MD5 */ +#undef NO_MD5 +#if 1 +#else + #define NO_MD5 +#endif + + +/* ------------------------------------------------------------------------- */ +/* Benchmark / Test */ +/* ------------------------------------------------------------------------- */ +/* Use reduced benchmark / test sizes */ +#undef BENCH_EMBEDDED +#define BENCH_EMBEDDED + +#undef USE_CERT_BUFFERS_2048 +#define USE_CERT_BUFFERS_2048 + +#undef USE_CERT_BUFFERS_1024 +//#define USE_CERT_BUFFERS_1024 + +#undef USE_CERT_BUFFERS_256 +#define USE_CERT_BUFFERS_256 + + +/* ------------------------------------------------------------------------- */ +/* Time */ +/* ------------------------------------------------------------------------- */ +#if 0 + /* Override Current Time */ + /* Allows custom "custom_time()" function to be used for benchmark */ + #define WOLFSSL_USER_CURRTIME + #define USER_TICKS + extern unsigned long custom_time(unsigned long* timer); + #define XTIME custom_time +#else + #warning Time/RTC disabled + #undef NO_ASN_TIME + #define NO_ASN_TIME +#endif + +/* ------------------------------------------------------------------------- */ +/* Debugging */ +/* ------------------------------------------------------------------------- */ +#undef DEBUG_WOLFSSL +#define DEBUG_WOLFSSL + +#ifdef DEBUG_WOLFSSL + /* Use this to measure / print heap usage */ + #if 0 + #undef USE_WOLFSSL_MEMORY + #define USE_WOLFSSL_MEMORY + #undef WOLFSSL_TRACK_MEMORY + #define WOLFSSL_TRACK_MEMORY + #endif +#else + #undef NO_WOLFSSL_MEMORY + #define NO_WOLFSSL_MEMORY + + #undef NO_ERROR_STRINGS + //#define NO_ERROR_STRINGS +#endif + + +/* ------------------------------------------------------------------------- */ +/* Enable Features */ +/* ------------------------------------------------------------------------- */ +#undef KEEP_PEER_CERT +//#define KEEP_PEER_CERT + +#undef HAVE_COMP_KEY +//#define HAVE_COMP_KEY + +#undef HAVE_TLS_EXTENSIONS +//#define HAVE_TLS_EXTENSIONS + +#undef HAVE_SUPPORTED_CURVES +//#define HAVE_SUPPORTED_CURVES + +#undef WOLFSSL_BASE64_ENCODE +//#define WOLFSSL_BASE64_ENCODE + +/* TLS Session Cache */ +#if 0 + #define SMALL_SESSION_CACHE +#else + #define NO_SESSION_CACHE +#endif + + +/* ------------------------------------------------------------------------- */ +/* Disable Features */ +/* ------------------------------------------------------------------------- */ +#undef NO_WOLFSSL_SERVER +//#define NO_WOLFSSL_SERVER + +#undef NO_WOLFSSL_CLIENT +//#define NO_WOLFSSL_CLIENT + +#undef NO_CRYPT_TEST +//#define NO_CRYPT_TEST + +#undef NO_CRYPT_BENCHMARK +//#define NO_CRYPT_BENCHMARK + +/* In-lining of misc.c functions */ +/* If defined, must include wolfcrypt/src/misc.c in build */ +/* Slower, but about 1k smaller */ +#undef NO_INLINE +//#define NO_INLINE + +#undef NO_FILESYSTEM +#define NO_FILESYSTEM + +#undef NO_WRITEV +#define NO_WRITEV + +#undef NO_MAIN_DRIVER +#define NO_MAIN_DRIVER + +#undef NO_DEV_RANDOM +#define NO_DEV_RANDOM + +#undef NO_DSA +#define NO_DSA + +#undef NO_DH +#define NO_DH + +#undef NO_RC4 +#define NO_RC4 + +#undef NO_OLD_TLS +#define NO_OLD_TLS + +#undef NO_HC128 +#define NO_HC128 + +#undef NO_RABBIT +#define NO_RABBIT + +#undef NO_PSK +#define NO_PSK + +#undef NO_MD4 +#define NO_MD4 + +#undef NO_PWDBASED +#define NO_PWDBASED + +#undef NO_CODING +//#define NO_CODING + + +/* Suppress array-bounds */ +#pragma GCC diagnostic ignored "-Warray-bounds" + + +#ifdef __cplusplus +} +#endif + +#endif /* WOLFSSL_USER_SETTINGS_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/Makefile b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/Makefile new file mode 100644 index 000000000..55369918f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/Makefile @@ -0,0 +1,108 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help message +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/nbproject/configurations.xml b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/nbproject/configurations.xml new file mode 100644 index 000000000..09fb14503 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/nbproject/configurations.xml @@ -0,0 +1,196 @@ + + + + + ../user_settings.h + + + + + ../mcapi_test.c + ../crypto.c + + + Makefile + + + + .. + + Makefile + + + + localhost + PIC32MX795F512L + + + SKDEPIC32PlatformTool + XC32 + 1.34 + 4 + + + + + + + + + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/nbproject/include.am b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/nbproject/include.am new file mode 100644 index 000000000..11b2ae9cb --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/nbproject/include.am @@ -0,0 +1,11 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mcapi/wolfcrypt_mcapi.X/Makefile + +EXTRA_DIST += \ + mcapi/wolfcrypt_mcapi.X/nbproject/configurations.xml \ + mcapi/wolfcrypt_mcapi.X/nbproject/project.xml + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/nbproject/project.xml b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/nbproject/project.xml new file mode 100644 index 000000000..c133c7c87 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_mcapi.X/nbproject/project.xml @@ -0,0 +1,20 @@ + + + com.microchip.mplab.nbide.embedded.makeproject + + + wolfcrypt_mcapi + 2ca6ab9b-e225-4ad3-b48e-9ea7b47a4ca4 + 0 + c + + + ISO-8859-1 + + + ../wolfssl.X + ../zlib.X + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/Makefile b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/Makefile new file mode 100644 index 000000000..55369918f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/Makefile @@ -0,0 +1,108 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help message +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/nbproject/configurations.xml b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/nbproject/configurations.xml new file mode 100644 index 000000000..5112f0ab3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/nbproject/configurations.xml @@ -0,0 +1,212 @@ + + + + + ../user_settings.h + + + + + ../../mplabx/test_main.c + ../../wolfcrypt/test/test.c + + + Makefile + + + + ../../mplabx + ../../wolfcrypt/test + + Makefile + + + + localhost + PIC32MX795F512L + + + SKDEPIC32PlatformTool + XC32 + 1.34 + 4 + + + + + + + + + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/nbproject/include.am b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/nbproject/include.am new file mode 100644 index 000000000..83cdc61d7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/nbproject/include.am @@ -0,0 +1,11 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mcapi/wolfcrypt_test.X/Makefile + +EXTRA_DIST += \ + mcapi/wolfcrypt_test.X/nbproject/configurations.xml \ + mcapi/wolfcrypt_test.X/nbproject/project.xml + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/nbproject/project.xml b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/nbproject/project.xml new file mode 100644 index 000000000..0fd889d6b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfcrypt_test.X/nbproject/project.xml @@ -0,0 +1,20 @@ + + + com.microchip.mplab.nbide.embedded.makeproject + + + wolfcrypt_test + b34c4937-7042-4352-88b1-7717bcdf8aeb + 0 + c + + + ISO-8859-1 + + + ../wolfssl.X + ../zlib.X + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/Makefile b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/Makefile new file mode 100644 index 000000000..55369918f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/Makefile @@ -0,0 +1,108 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help message +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/nbproject/configurations.xml b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/nbproject/configurations.xml new file mode 100644 index 000000000..d805bac76 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/nbproject/configurations.xml @@ -0,0 +1,243 @@ + + + + + ../user_settings.h + + + + + + ../../wolfcrypt/src/aes.c + ../../wolfcrypt/src/arc4.c + ../../wolfcrypt/src/asm.c + ../../wolfcrypt/src/asn.c + ../../wolfcrypt/src/blake2b.c + ../../wolfcrypt/src/camellia.c + ../../wolfcrypt/src/chacha.c + ../../wolfcrypt/src/coding.c + ../../wolfcrypt/src/compress.c + ../../wolfcrypt/src/des3.c + ../../wolfcrypt/src/dh.c + ../../wolfcrypt/src/dsa.c + ../../wolfcrypt/src/ecc.c + ../../wolfcrypt/src/ecc_fp.c + ../../wolfcrypt/src/error.c + ../../wolfcrypt/src/hc128.c + ../../wolfcrypt/src/hmac.c + ../../wolfcrypt/src/integer.c + ../../wolfcrypt/src/logging.c + ../../wolfcrypt/src/md2.c + ../../wolfcrypt/src/md4.c + ../../wolfcrypt/src/md5.c + ../../wolfcrypt/src/memory.c + ../../wolfcrypt/src/misc.c + ../../wolfcrypt/src/pkcs7.c + ../../wolfcrypt/src/poly1305.c + ../../wolfcrypt/src/pwdbased.c + ../../wolfcrypt/src/rabbit.c + ../../wolfcrypt/src/random.c + ../../wolfcrypt/src/ripemd.c + ../../wolfcrypt/src/rsa.c + ../../wolfcrypt/src/sha.c + ../../wolfcrypt/src/sha256.c + ../../wolfcrypt/src/sha512.c + ../../wolfcrypt/src/tfm.c + ../../wolfcrypt/src/wc_port.c + ../../wolfcrypt/src/port/pic32/pic32mz-hash.c + ../../wolfcrypt/src/port/pic32/pic32mz-crypt.c + ../../wolfcrypt/src/hash.c + ../../wolfcrypt/src/chacha20_poly1305.c + ../../wolfcrypt/src/curve25519.c + ../../wolfcrypt/src/ed25519.c + ../../wolfcrypt/src/fe_low_mem.c + ../../wolfcrypt/src/fe_operations.c + ../../wolfcrypt/src/ge_low_mem.c + ../../wolfcrypt/src/ge_operations.c + ../../wolfcrypt/src/wc_encrypt.c + ../../wolfcrypt/src/pkcs12.c + ../../wolfcrypt/src/signature.c + ../../wolfcrypt/src/wolfevent.c + ../../wolfcrypt/src/wolfmath.c + + + ../../src/crl.c + ../../src/internal.c + ../../src/wolfio.c + ../../src/keys.c + ../../src/ocsp.c + ../../src/sniffer.c + ../../src/ssl.c + ../../src/tls.c + ../../src/tls13.c + + + + Makefile + + + + .. + ../../ctaocrypt/src + ../../src + ../../wolfcrypt + + Makefile + + + + localhost + PIC32MX795F512L + + + SKDEPIC32PlatformTool + XC32 + 1.34 + 4 + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/nbproject/include.am b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/nbproject/include.am new file mode 100644 index 000000000..9ace61b5e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/nbproject/include.am @@ -0,0 +1,11 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mcapi/wolfssl.X/Makefile + +EXTRA_DIST += \ + mcapi/wolfssl.X/nbproject/configurations.xml \ + mcapi/wolfssl.X/nbproject/project.xml + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/nbproject/project.xml b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/nbproject/project.xml new file mode 100644 index 000000000..efab333a4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/wolfssl.X/nbproject/project.xml @@ -0,0 +1,17 @@ + + + com.microchip.mplab.nbide.embedded.makeproject + + + wolfssl + 93bbfc3a-a0fa-4d48-bbc8-6cd47a2bd05b + 0 + c + + + ISO-8859-1 + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/Makefile b/FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/Makefile new file mode 100644 index 000000000..55369918f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/Makefile @@ -0,0 +1,108 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help message +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/nbproject/configurations.xml b/FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/nbproject/configurations.xml new file mode 100644 index 000000000..cf780f4e7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/nbproject/configurations.xml @@ -0,0 +1,210 @@ + + + + + + + + + ../../zlib-1.2.8/adler32.c + ../../zlib-1.2.8/compress.c + ../../zlib-1.2.8/crc32.c + ../../zlib-1.2.8/deflate.c + ../../zlib-1.2.8/gzclose.c + ../../zlib-1.2.8/gzlib.c + ../../zlib-1.2.8/gzread.c + ../../zlib-1.2.8/gzwrite.c + ../../zlib-1.2.8/infback.c + ../../zlib-1.2.8/inffast.c + ../../zlib-1.2.8/inflate.c + ../../zlib-1.2.8/inftrees.c + ../../zlib-1.2.8/trees.c + ../../zlib-1.2.8/uncompr.c + ../../zlib-1.2.8/zutil.c + + + Makefile + + + Makefile + + + + localhost + PIC32MX795F512L + + + PKOBSKDEPlatformTool + XC32 + 1.34 + 4 + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/nbproject/include.am b/FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/nbproject/include.am new file mode 100644 index 000000000..8cb88ca86 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/nbproject/include.am @@ -0,0 +1,10 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mcapi/zlib.X/Makefile + +EXTRA_DIST += \ + mcapi/zlib.X/nbproject/configurations.xml \ + mcapi/zlib.X/nbproject/project.xml diff --git a/FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/nbproject/project.xml b/FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/nbproject/project.xml new file mode 100644 index 000000000..d3b077973 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mcapi/zlib.X/nbproject/project.xml @@ -0,0 +1,17 @@ + + + com.microchip.mplab.nbide.embedded.makeproject + + + zlib + 8eef651d-e634-46ae-9183-39443c98e390 + 0 + c + + + ISO-8859-1 + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/PIC32MZ-serial.h b/FreeRTOS-Plus/Source/WolfSSL/mplabx/PIC32MZ-serial.h new file mode 100644 index 000000000..a64bdb766 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/PIC32MZ-serial.h @@ -0,0 +1,96 @@ +void _mon_putc(char c); + +#define BAUD_GEN(sysclk, baud) ((sysclk / (16 * baud)) - 1) + +#ifdef MICROCHIP_PIC32 +#if defined (__32MZ2048ECH144__) || defined(__32MZ2048ECM144__) || defined(__32MZ2048EFM144__) + /* Code generated from Harmony example then exported using Window -> PIC32 Memory View -> Configuration Bits into system_config.h */ + #define SYS_CLK_FREQ 200000000ul + #define SYS_CLK_BUS_PERIPHERAL_2 100000000ul + + /* PIC32MZ2048EFM144 Configuration Bit Settings */ + + /*** DEVCFG0 ***/ + #pragma config DEBUG = OFF + #pragma config JTAGEN = OFF + #pragma config ICESEL = ICS_PGx2 + #pragma config TRCEN = OFF + #pragma config BOOTISA = MIPS32 + #pragma config FECCCON = OFF_UNLOCKED + #pragma config FSLEEP = OFF + #pragma config DBGPER = PG_ALL + #pragma config SMCLR = MCLR_NORM + #pragma config SOSCGAIN = GAIN_2X + #pragma config SOSCBOOST = ON + #pragma config POSCGAIN = GAIN_2X + #pragma config POSCBOOST = ON + #pragma config EJTAGBEN = NORMAL + #pragma config CP = OFF + + /*** DEVCFG1 ***/ + #pragma config FNOSC = SPLL + #pragma config DMTINTV = WIN_127_128 + #pragma config FSOSCEN = OFF + #pragma config IESO = OFF + #pragma config POSCMOD = EC + #pragma config OSCIOFNC = OFF + #pragma config FCKSM = CSECME + #pragma config WDTPS = PS1048576 + #pragma config WDTSPGM = STOP + #pragma config FWDTEN = OFF + #pragma config WINDIS = NORMAL + #pragma config FWDTWINSZ = WINSZ_25 + #pragma config DMTCNT = DMT31 + #pragma config FDMTEN = OFF + + /*** DEVCFG2 ***/ + #pragma config FPLLIDIV = DIV_3 + #pragma config FPLLRNG = RANGE_5_10_MHZ + #pragma config FPLLICLK = PLL_POSC + #pragma config FPLLMULT = MUL_50 + #pragma config FPLLODIV = DIV_2 + #pragma config UPLLFSEL = FREQ_24MHZ + + /*** DEVCFG3 ***/ + #pragma config USERID = 0xffff + #pragma config FMIIEN = ON + #pragma config FETHIO = ON + #pragma config PGL1WAY = ON + #pragma config PMDL1WAY = ON + #pragma config IOL1WAY = ON + #pragma config FUSBIDIO = ON + + /*** BF1SEQ0 ***/ + #pragma config TSEQ = 0x0000 + #pragma config CSEQ = 0xffff + + /* #pragma config statements should precede project file includes. */ + /* Use project enums instead of #define for ON and OFF. */ + + #include +#endif +#endif + +static void init_serial(unsigned int sysClk) { +#ifdef MICROCHIP_PIC32 +#if defined (__32MZ2048ECH144__) || defined(__32MZ2048ECM144__) || defined(__32MZ2048EFM144__) + /* This is for pin B14 which is connected to the USB to UART connector J11 located under Ethernet connector */ + + /* Setup UART2 */ +#ifdef SYS_CLK_BUS_PERIPHERAL_2 + U2BRG = BAUD_GEN(SYS_CLK_BUS_PERIPHERAL_2, 115200); +#else + if (sysClk > 100000000) + sysClk /= 2; + U2BRG = BAUD_GEN(sysClk, 115200); +#endif + ANSELBCLR = 0x4000; + ANSELGCLR = 0x0040; + RPB14R = 0x02; + U2RXR = 0x01; + U2MODE = 0x8000; + U2STA = 0x400; +#endif +#endif + (void)sysClk; +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/README b/FreeRTOS-Plus/Source/WolfSSL/mplabx/README new file mode 100644 index 000000000..66c0731a0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/README @@ -0,0 +1,66 @@ +wolfSSL MPLAB X Project Files + +This directory contains project files for the Microchip MPLAB X IDE. These +projects have been set up to use the Microchip PIC32 Ethernet Starter Kit +and the Microchip XC32 compiler. + +In order to generate the necessary auto-generated MPLAB X files, make sure +to import the wolfssl.X project into your MPLAB X workspace before trying to +build either the wolfCrypt test or benchmark applications. This will +correctly set up the respective project's Makefiles. + +Included Project Files +----------------------- + +1. wolfSSL library (wolfssl.X) + + This project builds a static wolfSSL library. The settings for this project + are in `user_settings.h`: + + /wolfssl/wolfcrypt/settings.h + + After this project has been built, the compiled library will be located + at: + + /mplabx/wolfssl.X/dist/default/production/wolfssl.X.a + +2. wolfCrypt Test App (wolfcrypt_test.X) + + This project tests the wolfCrypt cryptography modules. It is generally + a good idea to run this first on an embedded system after compiling + wolfSSL in order to verify all underlying crypto is working correctly. + +3. wolfCrypt Benchmark App (wolfcrypt_benchmark.X) + + This project builds the wolfCrypt benchmark application. + For the benchmark timer, adjust CLOCK value under + "#elif defined MICROCHIP_PIC32" in wolfcrypt/benchmark/benchmark.c + +PIC32MX/PIC32MZ +--------------- + +The projects are set for PIC32MZ by default. For PIC32MX, comment out the +`WOLFSSL_MICROCHIP_PIC32MZ` line in `user_settings.h`. + +You also need to adjust the microcontroller device in the project properties. + + +MIPS16 and MIPS32 Support +------------------------- + +These projects support both MIPS16 and MIPS32 instruction sets. Switching +between these two instruction sets can be done in each project's properties +settings by checking the "Generate 16-bit code" checkbox. + + +Legacy Peripheral Libraries +___________________________ + +If you get a linker error locating `ReadCoreTimer` and `WriteCoreTimer` you +can enable wrappers in benchmark_main.c and test_main.c. + + +Support +------- +Please send questions or comments to support@wolfssl.com + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/benchmark_main.c b/FreeRTOS-Plus/Source/WolfSSL/mplabx/benchmark_main.c new file mode 100644 index 000000000..461e53bea --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/benchmark_main.c @@ -0,0 +1,79 @@ +/* benchmark_main.c + * + * Copyright (C) 2006-2020 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_MICROCHIP_PIC32MZ) + #define MICROCHIP_PIC32 + #include + #include + #include "PIC32MZ-serial.h" + #include + #define SYSTEMConfigPerformance(a) /* void out SYSTEMConfigPerformance(); */ + #define SYS_CLK 200000000 +#else + #define PIC32_STARTER_KIT + #define _SUPPRESS_PLIB_WARNING + #define _DISABLE_OPENADC10_CONFIGPORT_WARNING + #include + #include + #define init_serial() /* void out init_serial() ; */ + #define SYS_CLK 80000000 +#endif + +#if 1 +/* enable this if ReadCoreTimer and WriteCoreTimer are missing */ +unsigned int ReadCoreTimer(void) +{ + unsigned int timer; + timer = __builtin_mfc0(9, 0); + return timer; +} +void WriteCoreTimer(unsigned int t) +{ + /* do nothing here */ + (void)t; +} +#endif + +/* + * Main driver for wolfCrypt benchmarks. + */ +int main(int argc, char** argv) +{ + SYSTEMConfigPerformance(SYS_CLK); + DBINIT(); + + init_serial(SYS_CLK) ; /* initialize PIC32MZ serial I/O */ + + printf("wolfCrypt Benchmark:\n"); + + benchmark_test(NULL); + + printf("End of wolfCrypt Benchmark:\n"); + return 0; +} + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/include.am b/FreeRTOS-Plus/Source/WolfSSL/mplabx/include.am new file mode 100644 index 000000000..0536e9006 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/include.am @@ -0,0 +1,10 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mplabx/README \ + mplabx/benchmark_main.c \ + mplabx/test_main.c \ + mplabx/PIC32MZ-serial.h \ + mplabx/user_settings.h diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/test_main.c b/FreeRTOS-Plus/Source/WolfSSL/mplabx/test_main.c new file mode 100644 index 000000000..8d1881cc4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/test_main.c @@ -0,0 +1,99 @@ +/* main.c + * + * Copyright (C) 2006-2020 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_MICROCHIP_PIC32MZ) + #define MICROCHIP_PIC32 + #include + #include + #include "PIC32MZ-serial.h" + #include + #define SYSTEMConfigPerformance(a) /* void out SYSTEMConfigPerformance(); */ + #define SYS_CLK 200000000 +#else + #define PIC32_STARTER_KIT + #include + #include + #include + #define _SUPPRESS_PLIB_WARNING + #define _DISABLE_OPENADC10_CONFIGPORT_WARNING + #include + #include + #define init_serial(x) /* void out init_serial() */ + #define SYS_CLK 80000000 +#endif + +/* func_args from test.h, so don't have to pull in other junk */ +typedef struct func_args { + int argc; + char** argv; + int return_code; +} func_args; + + +#if 1 +/* enable this if ReadCoreTimer and WriteCoreTimer are missing */ +unsigned int ReadCoreTimer(void) +{ + unsigned int timer; + timer = __builtin_mfc0(9, 0); + return timer; +} +void WriteCoreTimer(unsigned int t) +{ + /* do nothing here */ + (void)t; +} +#endif + +/* + * Main driver for WolfCrypt tests. + */ +int main(int argc, char** argv) +{ + func_args args; + + SYSTEMConfigPerformance(SYS_CLK); + DBINIT(); + + init_serial(SYS_CLK) ; /* initialize PIC32MZ serial I/O */ + + printf("WolfCrypt Test:\n"); + + args.argc = argc; + args.argv = argv; + + wolfcrypt_test(&args); + + if (args.return_code == 0) { + printf("All tests passed!\n"); + } + + return 0; +} + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/user_settings.h b/FreeRTOS-Plus/Source/WolfSSL/mplabx/user_settings.h new file mode 100644 index 000000000..b89a6f785 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/user_settings.h @@ -0,0 +1,386 @@ +/* Example custom user settings for wolfSSL */ + +#ifndef WOLFSSL_USER_SETTINGS_H +#define WOLFSSL_USER_SETTINGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include /* for size_t */ + + +/* ------------------------------------------------------------------------- */ +/* Platform */ +/* ------------------------------------------------------------------------- */ +#undef WOLFSSL_GENERAL_ALIGNMENT +#define WOLFSSL_GENERAL_ALIGNMENT 4 + +#undef SINGLE_THREADED +#define SINGLE_THREADED + +#undef WOLFSSL_SMALL_STACK +#define WOLFSSL_SMALL_STACK + +#undef MICROCHIP_PIC32 +#define MICROCHIP_PIC32 + +#undef WOLFSSL_MICROCHIP_PIC32MZ +#define WOLFSSL_MICROCHIP_PIC32MZ + + +/* ------------------------------------------------------------------------- */ +/* Math Configuration */ +/* ------------------------------------------------------------------------- */ +#undef USE_FAST_MATH +#define USE_FAST_MATH + +#ifdef USE_FAST_MATH + #undef TFM_TIMING_RESISTANT + #define TFM_TIMING_RESISTANT + + /* Optimizations */ + //#define TFM_MIPS +#endif + + +/* ------------------------------------------------------------------------- */ +/* Crypto */ +/* ------------------------------------------------------------------------- */ +/* ECC */ +#if 1 + #undef HAVE_ECC + #define HAVE_ECC + + /* Manually define enabled curves */ + #undef ECC_USER_CURVES + #define ECC_USER_CURVES + + //#define HAVE_ECC192 + //#define HAVE_ECC224 + #undef NO_ECC256 + //#define HAVE_ECC384 + //#define HAVE_ECC521 + + /* Fixed point cache (speeds repeated operations against same private key) */ + #undef FP_ECC + //#define FP_ECC + #ifdef FP_ECC + /* Bits / Entries */ + #undef FP_ENTRIES + #define FP_ENTRIES 2 + #undef FP_LUT + #define FP_LUT 4 + #endif + + /* Optional ECC calculation method */ + /* Note: doubles heap usage, but slightly faster */ + #undef ECC_SHAMIR + #define ECC_SHAMIR + + /* Reduces heap usage, but slower */ + #undef ECC_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + + #ifdef USE_FAST_MATH + /* use reduced size math buffers for ecc points */ + #undef ALT_ECC_SIZE + #define ALT_ECC_SIZE + + /* Enable TFM optimizations for ECC */ + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #define TFM_ECC192 + #endif + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #define TFM_ECC224 + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #define TFM_ECC256 + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #define TFM_ECC384 + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #define TFM_ECC521 + #endif + #endif +#endif + +/* RSA */ +#undef NO_RSA +#if 1 + #ifdef USE_FAST_MATH + /* Maximum math bits (Max RSA key bits * 2) */ + #undef FP_MAX_BITS + #define FP_MAX_BITS 4096 + #endif + + /* half as much memory but twice as slow */ + #undef RSA_LOW_MEM + //#define RSA_LOW_MEM + + /* timing resistance */ + #undef WC_RSA_BLINDING + #define WC_RSA_BLINDING +#else + #define NO_RSA +#endif + +/* AES */ +#undef NO_AES +#if 1 + #undef HAVE_AES_DECRYPT + #define HAVE_AES_DECRYPT + + #undef HAVE_AESGCM + #define HAVE_AESGCM + + /* GCM Method: GCM_SMALL, GCM_WORD32 or GCM_TABLE */ + #undef GCM_SMALL + #define GCM_SMALL + + #undef HAVE_AESCCM + #define HAVE_AESCCM + + #undef WOLFSSL_AES_COUNTER + #define WOLFSSL_AES_COUNTER + + #undef WOLFSSL_AES_DIRECT + #define WOLFSSL_AES_DIRECT +#else + #define NO_AES +#endif + +/* DES3 */ +#undef NO_DES3 +#if 1 + #undef WOLFSSL_DES_ECB + #define WOLFSSL_DES_ECB +#else + #define NO_DES3 +#endif + + +/* ChaCha20 / Poly1305 */ +#undef HAVE_CHACHA +#undef HAVE_POLY1305 +#if 0 + #define HAVE_CHACHA + #define HAVE_POLY1305 + + /* Needed for Poly1305 */ + #undef HAVE_ONE_TIME_AUTH + #define HAVE_ONE_TIME_AUTH +#endif + +/* Ed25519 / Curve25519 */ +#undef HAVE_CURVE25519 +#undef HAVE_ED25519 +#if 0 + #define HAVE_CURVE25519 + #define HAVE_ED25519 + + /* Optionally use small math (less flash usage, but much slower) */ + #if 0 + #define CURVED25519_SMALL + #endif +#endif + + +/* ------------------------------------------------------------------------- */ +/* Hashing */ +/* ------------------------------------------------------------------------- */ +/* Sha */ +#undef NO_SHA +#if 1 + /* 1k smaller, but 25% slower */ + //#define USE_SLOW_SHA +#else + #define NO_SHA +#endif + +/* Sha256 */ +#undef NO_SHA256 +#if 1 +#else + #define NO_SHA256 +#endif + +/* Sha512 */ +#undef WOLFSSL_SHA512 +#if 1 + #define WOLFSSL_SHA512 + + /* Sha384 */ + #undef WOLFSSL_SHA384 + #if 1 + #define WOLFSSL_SHA384 + #endif + + /* over twice as small, but 50% slower */ + //#define USE_SLOW_SHA2 +#endif + +/* MD5 */ +#undef NO_MD5 +#if 1 +#else + #define NO_MD5 +#endif + + +/* ------------------------------------------------------------------------- */ +/* Benchmark / Test */ +/* ------------------------------------------------------------------------- */ +/* Use reduced benchmark / test sizes */ +#undef BENCH_EMBEDDED +#define BENCH_EMBEDDED + +#undef USE_CERT_BUFFERS_2048 +#define USE_CERT_BUFFERS_2048 + +#undef USE_CERT_BUFFERS_1024 +//#define USE_CERT_BUFFERS_1024 + +#undef USE_CERT_BUFFERS_256 +#define USE_CERT_BUFFERS_256 + + +/* ------------------------------------------------------------------------- */ +/* Time */ +/* ------------------------------------------------------------------------- */ +#if 0 + /* Override Current Time */ + /* Allows custom "custom_time()" function to be used for benchmark */ + #define WOLFSSL_USER_CURRTIME + #define USER_TICKS + extern unsigned long custom_time(unsigned long* timer); + #define XTIME custom_time +#else + #warning Time/RTC disabled + #undef NO_ASN_TIME + #define NO_ASN_TIME +#endif + +/* ------------------------------------------------------------------------- */ +/* Debugging */ +/* ------------------------------------------------------------------------- */ +#undef DEBUG_WOLFSSL +#define DEBUG_WOLFSSL + +#ifdef DEBUG_WOLFSSL + /* Use this to measure / print heap usage */ + #if 0 + #undef USE_WOLFSSL_MEMORY + #define USE_WOLFSSL_MEMORY + #undef WOLFSSL_TRACK_MEMORY + #define WOLFSSL_TRACK_MEMORY + #endif +#else + #undef NO_WOLFSSL_MEMORY + #define NO_WOLFSSL_MEMORY + + #undef NO_ERROR_STRINGS + //#define NO_ERROR_STRINGS +#endif + + +/* ------------------------------------------------------------------------- */ +/* Enable Features */ +/* ------------------------------------------------------------------------- */ +#undef KEEP_PEER_CERT +//#define KEEP_PEER_CERT + +#undef HAVE_COMP_KEY +//#define HAVE_COMP_KEY + +#undef HAVE_TLS_EXTENSIONS +//#define HAVE_TLS_EXTENSIONS + +#undef HAVE_SUPPORTED_CURVES +//#define HAVE_SUPPORTED_CURVES + +#undef WOLFSSL_BASE64_ENCODE +//#define WOLFSSL_BASE64_ENCODE + +/* TLS Session Cache */ +#if 0 + #define SMALL_SESSION_CACHE +#else + #define NO_SESSION_CACHE +#endif + + +/* ------------------------------------------------------------------------- */ +/* Disable Features */ +/* ------------------------------------------------------------------------- */ +#undef NO_WOLFSSL_SERVER +//#define NO_WOLFSSL_SERVER + +#undef NO_WOLFSSL_CLIENT +//#define NO_WOLFSSL_CLIENT + +#undef NO_CRYPT_TEST +//#define NO_CRYPT_TEST + +#undef NO_CRYPT_BENCHMARK +//#define NO_CRYPT_BENCHMARK + +/* In-lining of misc.c functions */ +/* If defined, must include wolfcrypt/src/misc.c in build */ +/* Slower, but about 1k smaller */ +#undef NO_INLINE +//#define NO_INLINE + +#undef NO_FILESYSTEM +#define NO_FILESYSTEM + +#undef NO_WRITEV +#define NO_WRITEV + +#undef NO_MAIN_DRIVER +#define NO_MAIN_DRIVER + +#undef NO_DEV_RANDOM +#define NO_DEV_RANDOM + +#undef NO_DSA +#define NO_DSA + +#undef NO_DH +#define NO_DH + +#undef NO_RC4 +#define NO_RC4 + +#undef NO_OLD_TLS +#define NO_OLD_TLS + +#undef NO_HC128 +#define NO_HC128 + +#undef NO_RABBIT +#define NO_RABBIT + +#undef NO_PSK +#define NO_PSK + +#undef NO_MD4 +#define NO_MD4 + +#undef NO_PWDBASED +#define NO_PWDBASED + +#undef NO_CODING +//#define NO_CODING + + +/* Suppress array-bounds */ +#pragma GCC diagnostic ignored "-Warray-bounds" + + +#ifdef __cplusplus +} +#endif + +#endif /* WOLFSSL_USER_SETTINGS_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/Makefile b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/Makefile new file mode 100644 index 000000000..7b941ab95 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/Makefile @@ -0,0 +1,108 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help message +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/nbproject/configurations.xml b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/nbproject/configurations.xml new file mode 100644 index 000000000..a6bdcd00a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/nbproject/configurations.xml @@ -0,0 +1,218 @@ + + + + + ../user_settings.h + + + + + ../../wolfcrypt/benchmark/benchmark.c + ../benchmark_main.c + + + Makefile + + + + .. + ../../wolfcrypt/benchmark + + Makefile + + + + localhost + PIC32MZ2048EFM144 + + + PKOBSKDEPlatformTool + XC32 + + 4 + + + + + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/nbproject/include.am b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/nbproject/include.am new file mode 100644 index 000000000..8fccbc726 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/nbproject/include.am @@ -0,0 +1,11 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mplabx/wolfcrypt_benchmark.X/Makefile + +EXTRA_DIST += \ + mplabx/wolfcrypt_benchmark.X/nbproject/configurations.xml \ + mplabx/wolfcrypt_benchmark.X/nbproject/project.xml + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/nbproject/project.xml b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/nbproject/project.xml new file mode 100644 index 000000000..91468cb01 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_benchmark.X/nbproject/project.xml @@ -0,0 +1,19 @@ + + + com.microchip.mplab.nbide.embedded.makeproject + + + wolfcrypt_benchmark + 22e4138b-5f20-4957-ac0a-c181b94d3342 + 0 + c + + h + ISO-8859-1 + + + ../wolfssl.X + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/Makefile b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/Makefile new file mode 100644 index 000000000..7b941ab95 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/Makefile @@ -0,0 +1,108 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help message +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/nbproject/configurations.xml b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/nbproject/configurations.xml new file mode 100644 index 000000000..1ee4b6bda --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/nbproject/configurations.xml @@ -0,0 +1,218 @@ + + + + + ../user_settings.h + + + + + ../test_main.c + ../../wolfcrypt/test/test.c + + + Makefile + + + + .. + ../../wolfcrypt/test + + Makefile + + + + localhost + PIC32MZ2048EFM144 + + + PKOBSKDEPlatformTool + XC32 + + 4 + + + + + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/nbproject/include.am b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/nbproject/include.am new file mode 100644 index 000000000..840e87973 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/nbproject/include.am @@ -0,0 +1,11 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mplabx/wolfcrypt_test.X/Makefile + +EXTRA_DIST += \ + mplabx/wolfcrypt_test.X/nbproject/configurations.xml \ + mplabx/wolfcrypt_test.X/nbproject/project.xml + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/nbproject/project.xml b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/nbproject/project.xml new file mode 100644 index 000000000..c2ffc29aa --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfcrypt_test.X/nbproject/project.xml @@ -0,0 +1,19 @@ + + + com.microchip.mplab.nbide.embedded.makeproject + + + wolfcrypt_test + b34c4937-7042-4352-88b1-7717bcdf8aeb + 0 + c + + h + ISO-8859-1 + + + ../wolfssl.X + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/Makefile b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/Makefile new file mode 100644 index 000000000..7b941ab95 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/Makefile @@ -0,0 +1,108 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help message +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/nbproject/configurations.xml b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/nbproject/configurations.xml new file mode 100644 index 000000000..a07c30598 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/nbproject/configurations.xml @@ -0,0 +1,265 @@ + + + + + ../user_settings.h + + + + + + ../../wolfcrypt/src/aes.c + ../../wolfcrypt/src/arc4.c + ../../wolfcrypt/src/asm.c + ../../wolfcrypt/src/asn.c + ../../wolfcrypt/src/blake2b.c + ../../wolfcrypt/src/camellia.c + ../../wolfcrypt/src/chacha.c + ../../wolfcrypt/src/coding.c + ../../wolfcrypt/src/compress.c + ../../wolfcrypt/src/des3.c + ../../wolfcrypt/src/dh.c + ../../wolfcrypt/src/dsa.c + ../../wolfcrypt/src/ecc.c + ../../wolfcrypt/src/ecc_fp.c + ../../wolfcrypt/src/error.c + ../../wolfcrypt/src/hc128.c + ../../wolfcrypt/src/hmac.c + ../../wolfcrypt/src/integer.c + ../../wolfcrypt/src/logging.c + ../../wolfcrypt/src/md2.c + ../../wolfcrypt/src/md4.c + ../../wolfcrypt/src/md5.c + ../../wolfcrypt/src/memory.c + ../../wolfcrypt/src/misc.c + ../../wolfcrypt/src/pkcs7.c + ../../wolfcrypt/src/poly1305.c + ../../wolfcrypt/src/pwdbased.c + ../../wolfcrypt/src/rabbit.c + ../../wolfcrypt/src/random.c + ../../wolfcrypt/src/ripemd.c + ../../wolfcrypt/src/rsa.c + ../../wolfcrypt/src/sha.c + ../../wolfcrypt/src/sha256.c + ../../wolfcrypt/src/sha512.c + ../../wolfcrypt/src/tfm.c + ../../wolfcrypt/src/wc_port.c + ../../wolfcrypt/src/port/pic32/pic32mz-crypt.c + ../../wolfcrypt/src/hash.c + ../../wolfcrypt/src/chacha20_poly1305.c + ../../wolfcrypt/src/curve25519.c + ../../wolfcrypt/src/ed25519.c + ../../wolfcrypt/src/fe_low_mem.c + ../../wolfcrypt/src/fe_operations.c + ../../wolfcrypt/src/ge_low_mem.c + ../../wolfcrypt/src/ge_operations.c + ../../wolfcrypt/src/wc_encrypt.c + ../../wolfcrypt/src/pkcs12.c + ../../wolfcrypt/src/signature.c + ../../wolfcrypt/src/wolfevent.c + ../../wolfcrypt/src/wolfmath.c + + + ../../src/crl.c + ../../src/internal.c + ../../src/wolfio.c + ../../src/keys.c + ../../src/ocsp.c + ../../src/sniffer.c + ../../src/ssl.c + ../../src/tls.c + ../../src/tls13.c + + + + Makefile + + + + .. + ../../cyassl/ctaocrypt + ../../ctaocrypt/src + ../../src + ../../wolfcrypt/src + + Makefile + + + + localhost + PIC32MZ2048EFM144 + + + PKOBSKDEPlatformTool + XC32 + 1.33 + 4 + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/nbproject/include.am b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/nbproject/include.am new file mode 100644 index 000000000..510c26ae0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/nbproject/include.am @@ -0,0 +1,10 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mplabx/wolfssl.X/Makefile + +EXTRA_DIST += \ + mplabx/wolfssl.X/nbproject/configurations.xml \ + mplabx/wolfssl.X/nbproject/project.xml diff --git a/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/nbproject/project.xml b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/nbproject/project.xml new file mode 100644 index 000000000..92994f1f0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mplabx/wolfssl.X/nbproject/project.xml @@ -0,0 +1,17 @@ + + + com.microchip.mplab.nbide.embedded.makeproject + + + wolfssl + 93bbfc3a-a0fa-4d48-bbc8-6cd47a2bd05b + 0 + c + + h + ISO-8859-1 + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/README b/FreeRTOS-Plus/Source/WolfSSL/mqx/README new file mode 100644 index 000000000..55c13c671 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/README @@ -0,0 +1,43 @@ +wolfSSL Freescale CodeWarrior Project Files + +This directory contains project files for Freescale CodeWarrior 10.6 with +the Freescale GCC compiler. These project have been created to use MQX, RTCS, +and MFS on the Freescale Kinetis K70 Tower System (TWRK70F120M). + +Included Project Files +----------------------- + +1. wolfSSL library (/wolfssl) + + Prior to building this project, uncomment the FREESCALE_MQX define + located in: + + /wolfssl/wolfcrypt/settings.h + +2. wolfCrypt Test App (/wolfcrypt_test) + +3. wolfCrypt Benchmark App (/wolfcrypt_benchmark) + +3. Example wolfSSL Client (/wolfssl_client) + +4. Utility library (/util_lib) + + This library is used by the wolfSSL example client project and wolfCrypt + test app project for opening/closing the SD card, etc. + +Importing into CodeWarrior Workspace +------------------------------------ + +These projects can be imported into a CodeWarrior workspace using the standard +"Import Project" feature. To import a project from CodeWarrior, follow +these steps: + +1. File -> Import +2. General -> Existing Projects into Workspace +3. Select Root Directory (browse to this "/mqx" directory) +4. Select desired projects -> Finish + +Keep in mind that the projects above reference wolfSSL source files and header +files with relative paths to the projects' current location in the +/mqx directory. + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/.cproject b/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/.cproject new file mode 100644 index 000000000..5c4fc14ec --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/.cproject @@ -0,0 +1,541 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/.project b/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/.project new file mode 100644 index 000000000..5f5f5ffaa --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/.project @@ -0,0 +1,31 @@ + + + util_lib + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + MQX_ROOT_DIR + file:/C:/Freescale/Freescale_MQX_4_1 + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/Sources/include.am b/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/Sources/include.am new file mode 100644 index 000000000..4b54a5a60 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/Sources/include.am @@ -0,0 +1,12 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mqx/util_lib/.cproject \ + mqx/util_lib/.project + +EXTRA_DIST += \ + mqx/util_lib/Sources/util.c \ + mqx/util_lib/Sources/util.h + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/Sources/util.c b/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/Sources/util.c new file mode 100644 index 000000000..c7ce08bca --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/Sources/util.c @@ -0,0 +1,180 @@ +/* util.c */ + +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" + +#if !BSPCFG_ENABLE_IO_SUBSYSTEM + #error This application requires BSPCFG_ENABLE_IO_SUBSYSTEM defined \ + non-zero in user_config.h. Please recompile BSP with this option. +#endif + +#ifndef BSP_DEFAULT_IO_CHANNEL_DEFINED + #error This application requires BSP_DEFAULT_IO_CHANNEL to be not \ + NULL. Please set corresponding BSPCFG_ENABLE_TTYx to non-zero \ + in user_config.h and recompile BSP with this option. +#endif + +#if defined BSP_SDCARD_ESDHC_CHANNEL + #if ! BSPCFG_ENABLE_ESDHC + #error This application requires BSPCFG_ENABLE_ESDHC defined \ + non-zero in user_config.h. Please recompile libraries with \ + this option. + #endif +#elif defined BSP_SDCARD_SDHC_CHANNEL + #if ! BSPCFG_ENABLE_SDHC + #error This application requires BSPCFG_ENABLE_SDHC defined \ + non-zero in user_config.h. Please recompile libraries with \ + this option. + #endif +#endif + +#if defined (BSP_SDCARD_SPI_CHANNEL) + #define SDCARD_COM_CHANNEL BSP_SDCARD_SPI_CHANNEL +#elif defined (BSP_SDCARD_ESDHC_CHANNEL) + #define SDCARD_COM_CHANNEL BSP_SDCARD_ESDHC_CHANNEL +#elif defined (BSP_SDCARD_SDHC_CHANNEL) + #define SDCARD_COM_CHANNEL BSP_SDCARD_SDHC_CHANNEL +#else + #error "SDCARD low level communication device not defined!" +#endif + +int sdcard_open(MQX_FILE_PTR *com_handle, MQX_FILE_PTR *sdcard_handle, + MQX_FILE_PTR *partman_handle, MQX_FILE_PTR *filesystem_handle, + char *partman_name, char *filesystem_name) +{ + _mqx_int error_code; + _mqx_uint param; + + /* Open low level communication device */ + *com_handle = fopen(SDCARD_COM_CHANNEL, NULL); + + if (NULL == *com_handle) { + printf("Error installing communication handle.\n"); + return -60; + } + + /* Install SD card device */ + error_code = _io_sdcard_install("sdcard:", (void *)&_bsp_sdcard0_init, + *com_handle); + if (error_code != MQX_OK) { + printf("Error installing SD card device (0x%x)\n", error_code); + return -61; + } + + _time_delay(200); + + /* Open the device which MFS will be installed on */ + *sdcard_handle = fopen("sdcard:", 0); + if (*sdcard_handle == NULL) { + printf("Unable to open SD card device.\n"); + return -62; + } + + /* Install partition manager over SD card driver */ + error_code = _io_part_mgr_install(*sdcard_handle, partman_name, 0); + if (error_code != MFS_NO_ERROR) { + printf("Error installing partition manager: %s\n", MFS_Error_text( + (uint32_t) error_code)); + return -63; + } + + /* Open partition manager */ + *partman_handle = fopen(partman_name, NULL); + if (*partman_handle == NULL) { + error_code = ferror(*partman_handle); + printf("Error opening partition manager: %s\n", MFS_Error_text( + (uint32_t) error_code)); + return -64; + } + + /* Validate partition 1 */ + param = 1; + error_code = _io_ioctl(*partman_handle, IO_IOCTL_VAL_PART, ¶m); + if (error_code == MQX_OK) { + /* Install MFS over partition 1 */ + error_code = _io_mfs_install(*partman_handle, filesystem_name, param); + if (error_code != MFS_NO_ERROR) { + printf("Error initializing MFS over partition: %s\n", + MFS_Error_text((uint32_t) error_code)); + return -65; + } + + } else { + /* Install MFS over SD card driver */ + error_code = _io_mfs_install(*sdcard_handle, filesystem_name, + (_file_size) 0); + if (error_code != MFS_NO_ERROR) { + printf("Error initializing MFS: %s\n", MFS_Error_text( + (uint32_t) error_code)); + return -66; + } + } /* end Validate partition 1 */ + + /* Open file system */ + *filesystem_handle = fopen(filesystem_name, NULL); + error_code = ferror(*filesystem_handle); + if ((error_code != MFS_NO_ERROR) && (error_code != MFS_NOT_A_DOS_DISK)) { + printf("Error opening filesystem: %s\n", MFS_Error_text( + (uint32_t) error_code)); + return -67; + } + if (error_code == MFS_NOT_A_DOS_DISK) { + printf("NOT A DOS DISK! You must format to continue.\n"); + return -68; + } + + return 0; +} + +int sdcard_close(MQX_FILE_PTR *sdcard_handle, MQX_FILE_PTR *partman_handle, + MQX_FILE_PTR *filesystem_handle, + char *partman_name, char *filesystem_name) +{ + _mqx_int error_code; + + /* Close the filesystem */ + if (MQX_OK != fclose(*filesystem_handle)) { + printf("Error closing filesystem.\n"); + return -69; + } + *filesystem_handle = NULL; + + /* Uninstall MFS */ + error_code = _io_dev_uninstall(filesystem_name); + if (error_code != MFS_NO_ERROR) { + printf("Error uninstalling filesystem.\n"); + return -70; + } + + /* Close partition manager */ + if (MQX_OK != fclose(*partman_handle)) { + printf("Unable to close partition manager.\n"); + return -71; + } + *partman_handle = NULL; + + /* Uninstall partition manager */ + error_code = _io_dev_uninstall(partman_name); + if (error_code != MFS_NO_ERROR) { + printf("Error uninstalling partition manager.\n"); + return -72; + } + + /* Close the SD card device */ + if (MQX_OK != fclose(*sdcard_handle)) { + printf("Unable to close SD card device.\n"); + return -73; + } + *sdcard_handle = NULL; + + return 0; +} + +/* EOF */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/Sources/util.h b/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/Sources/util.h new file mode 100644 index 000000000..67bdca2fe --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/util_lib/Sources/util.h @@ -0,0 +1,14 @@ +/* util.h */ + +#ifndef UTIL_H_ +#define UTIL_H_ + +int sdcard_open(MQX_FILE_PTR *com_handle, MQX_FILE_PTR *sdcard_handle, + MQX_FILE_PTR *partman_handle, MQX_FILE_PTR *filesystem_handle, + char *partman_name, char *filesystem_name); + +int sdcard_close(MQX_FILE_PTR *sdcard_handle, MQX_FILE_PTR *partman_handle, + MQX_FILE_PTR *filesystem_handle, + char *partman_name, char *filesystem_name); + +#endif /* UTIL_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/.cproject b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/.cproject new file mode 100644 index 000000000..d110e10ea --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/.cproject @@ -0,0 +1,698 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/.project b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/.project new file mode 100644 index 000000000..082bb8973 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/.project @@ -0,0 +1,42 @@ + + + wolfcrypt_benchmark + + + +wolfssl + +util_lib + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + Sources/wolfcrypt_benchmark + 2 + PARENT-2-PROJECT_LOC/wolfcrypt/benchmark + + + + + MQX_ROOT_DIR + file:/C:/Freescale/Freescale_MQX_4_1 + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Debugger/K70FN1M0.mem b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Debugger/K70FN1M0.mem new file mode 100644 index 000000000..4a7c6198d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Debugger/K70FN1M0.mem @@ -0,0 +1,43 @@ +// Memory Configuration File +// +// Description: +// A memory configuration file contains commands that define the legally accessible +// areas of memory for your specific board. Useful for example when the debugger +// tries to display the content of a "char *" variable, that has not yet been initialized. +// In this case the debugger may try to read from a bogus address, which could cause a +// bus error. +// +// Board: +// Kinetis K70FN1M0 +// +// Reference: +// - + + +// All reserved ranges read back 0xBABA... +reservedchar 0xBA + +usederivative "MK70F15" + +// Memory Map: +// ---------------------------------------------------------------------- + +range 0x00000000 0x000FFFFF 4 ReadWrite // 1024KB Code Flash +reserved 0x00100000 0x13FFFFFF +range 0x14000000 0x14003FFF 4 ReadWrite // 16KB Programming acceleration RAM +reserved 0x14004000 0x1FFEFFFF +range 0x1FFF0000 0x1FFFFFFF 4 ReadWrite // 64KB On chip SRAM (TCML) +range 0x20000000 0x2000FFFF 4 ReadWrite // 64KB On chip SRAM (TCMU) +reserved 0x20010000 0x21FFFFFF +range 0x22000000 0x221FFFFF 4 ReadWrite // Aliased to TCMU SRAM bitband +reserved 0x22200000 0x3FFFFFFF +reserved 0x60000000 0x6FFFFFFF // Flexbus for external memory +range 0x70000000 0x7FFFFFFF 4 ReadWrite // DRAM Controller - Write-back +range 0x80000000 0x8FFFFFFF 4 ReadWrite // DRAM Controller - Write-through +reserved 0x90000000 0xDFFFFFFF // Flexbus for external memory +reserved 0xE0100000 0xFFFFFFFF + +// Comment the following line for NFC-projects +reserved 0x400A8000 0x400ABEFF +// Uncomment the following line for NFC-projects +//range 0x400A8000 0x400ABEFF 4 ReadWrite diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Debugger/init_kinetis.tcl b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Debugger/init_kinetis.tcl new file mode 100644 index 000000000..467b8ff9f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Debugger/init_kinetis.tcl @@ -0,0 +1,71 @@ +# this method initializes debug modules which are not affected by software reset +# register names should be referenced including the register group name to improve performance + +proc init_debug_modules {} { + # initialize LR to avoid invalid stack after reset + reg "User\\/System Mode Registers/LR" = 0xFFFFFFFF + + # clear DWT function registers + reg "Core Debug Registers/DEMCR" = 0x1000001 + reg "Data Watchpoint and Trace Unit Registers/DWT_FUNCTION0" = 0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_FUNCTION1" = 0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_FUNCTION2" = 0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_FUNCTION3" = 0x0 + # clear FPB comparators + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP0" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP1" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP2" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP3" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP4" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP5" = 0x0 +} + +proc init_trace_modules {} { + # clear DWT registers + reg "Data Watchpoint and Trace Unit Registers/DWT_CTRL" =0x40000000 + reg "Data Watchpoint and Trace Unit Registers/DWT_CYCCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_CPICNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_EXCCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_SLEEPCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_LSUCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_FOLDCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_COMP0" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_COMP1" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_COMP2" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_COMP3" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_MASK0" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_MASK1" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_MASK2" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_MASK3" =0x0 + # clear ITM registers + reg "Instrumentation Trace Macrocell Registers/ITM_LAR" =0xc5acce55 + reg "Instrumentation Trace Macrocell Registers/ITM_TER" =0x0 + reg "Instrumentation Trace Macrocell Registers/ITM_TPR" =0x0 + reg "Instrumentation Trace Macrocell Registers/ITM_TCR" =0x0 + reg "Instrumentation Trace Macrocell Registers/ITM_LAR" =0x1 + # reset Funnel registers + reg "Embedded Trace Funnel Registers/ETF_FCR" =0x300 + # clear MCM registers + reg "Core Platform Miscellaneous Control Module (MCM) Registers/MCM_ETBCC" =0x0 + reg "Core Platform Miscellaneous Control Module (MCM) Registers/MCM_ETBRL" =0x0 + # set SCB_VTOR register for RAM + reg "System Control Registers/SCB_VTOR" =0x20000000 +} + +proc envsetup {} { + # Environment Setup + radix x + config hexprefix 0x + config MemIdentifier p + config MemWidth 32 + config MemAccess 32 + config MemSwap off +} + +#------------------------------------------------------------------------------- +# Main +#------------------------------------------------------------------------------- + + envsetup + init_debug_modules + init_trace_modules diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Debugger/mass_erase_kinetis.tcl b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Debugger/mass_erase_kinetis.tcl new file mode 100644 index 000000000..2d8b84054 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Debugger/mass_erase_kinetis.tcl @@ -0,0 +1,31 @@ +# This script performs the mass erase operation for Kinetis targets + +# Command mass erase with system reset and core reset +set mdmapControl [cmdwin::reg MDMAP_C -np] +set mdmapControl [expr $mdmapControl | 0x19] +cmdwin::reg MDMAP_C = $mdmapControl + +# Release system reset while still holding core reset +set mdmapControl [expr $mdmapControl & 0xFFFFFFF7] +cmdwin::reg MDMAP_C = $mdmapControl + +# Wait for the mass erase operation to complete +set done 0 +for {set i 0} {$i < 10} {incr i} { + refresh + set mdmapControl [cmdwin::reg MDMAP_C -np] + if {($mdmapControl & 1) == 0} { + set done 1 + break; + } + wait 50 +} + +# Release the core reset +set mdmapControl [expr $mdmapControl & 0xFFFFFFEF] +cmdwin::reg MDMAP_C = $mdmapControl +if {$done} { + puts "OK: Mass erase succeeded" +} else { + puts "Error: Timeout" +} \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/ReferencedRSESystems.xml b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/ReferencedRSESystems.xml new file mode 100644 index 000000000..6d9f8f799 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/ReferencedRSESystems.xml @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Sources/include.am b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Sources/include.am new file mode 100644 index 000000000..fb4221836 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Sources/include.am @@ -0,0 +1,22 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mqx/wolfcrypt_benchmark/.cproject \ + mqx/wolfcrypt_benchmark/.project \ + mqx/wolfcrypt_benchmark/Debugger/K70FN1M0.mem \ + mqx/wolfcrypt_benchmark/Debugger/init_kinetis.tcl \ + mqx/wolfcrypt_benchmark/Debugger/mass_erase_kinetis.tcl \ + mqx/wolfcrypt_benchmark/ReferencedRSESystems.xml \ + mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch \ + mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch \ + mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink \ + mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch \ + mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch \ + mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch + +EXTRA_DIST += \ + mqx/wolfcrypt_benchmark/Sources/main.c \ + mqx/wolfcrypt_benchmark/Sources/main.h + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Sources/main.c b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Sources/main.c new file mode 100644 index 000000000..683463039 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Sources/main.c @@ -0,0 +1,94 @@ +/* main.c */ + +#include "main.h" + +/* SD card open/close utility functions */ +#include "util.h" + +#if !BSPCFG_ENABLE_IO_SUBSYSTEM +#error This application requires BSPCFG_ENABLE_IO_SUBSYSTEM defined \ + non-zero in user_config.h. Please recompile BSP with this option. +#endif + +#ifndef BSP_DEFAULT_IO_CHANNEL_DEFINED +#error This application requires BSP_DEFAULT_IO_CHANNEL to be not NULL. \ + Please set corresponding BSPCFG_ENABLE_TTYx to non-zero in \ + user_config.h and recompile BSP with this option. +#endif + +TASK_TEMPLATE_STRUCT MQX_template_list[] = +{ + /* Task number, Entry point, Stack, Pri, String, Auto? */ + {MAIN_TASK, Main_task, 30000, 9, "main", MQX_AUTO_START_TASK}, + {0, 0, 0, 0, 0, 0, } +}; + +#if defined BSP_SDCARD_ESDHC_CHANNEL + #if ! BSPCFG_ENABLE_ESDHC + #error This application requires BSPCFG_ENABLE_ESDHC defined \ + non-zero in user_config.h. Please recompile libraries with \ + this option. + #endif + +#elif defined BSP_SDCARD_SDHC_CHANNEL + #if ! BSPCFG_ENABLE_SDHC + #error This application requires BSPCFG_ENABLE_SDHC defined \ + non-zero in user_config.h. Please recompile libraries with \ + this option. + #endif +#endif + +#if defined (BSP_SDCARD_SPI_CHANNEL) + #define SDCARD_COM_CHANNEL BSP_SDCARD_SPI_CHANNEL +#elif defined (BSP_SDCARD_ESDHC_CHANNEL) + #define SDCARD_COM_CHANNEL BSP_SDCARD_ESDHC_CHANNEL +#elif defined (BSP_SDCARD_SDHC_CHANNEL) + #define SDCARD_COM_CHANNEL BSP_SDCARD_SDHC_CHANNEL +#else + #error "SDCARD low level communication device not defined!" +#endif + +/* func_args from test.h */ +typedef struct func_args { + int argc; + char** argv; + int return_code; +} func_args; + +/*TASK*----------------------------------------------------------------- + * Function Name : Main_task + * Comments : + * This task opens the SD card device and runs the + * wolfCrypt benchmark functions located in benchmark.c. + *END------------------------------------------------------------------*/ + +void Main_task(uint32_t initial_data) +{ + int ret = 0; + func_args args; + char filesystem_name[] = "a:"; + char partman_name[] = "pm:"; + MQX_FILE_PTR com_handle, sdcard_handle, filesystem_handle, partman_handle; + + ret = sdcard_open(&com_handle, &sdcard_handle, &partman_handle, + &filesystem_handle, partman_name, filesystem_name); + if (ret != 0) { + printf("error: sdcard_open(), ret = %d\n", ret); + _mqx_exit(1); + } + printf("SD card installed to %s\n", filesystem_name); + + benchmark_test(&args); + + ret = sdcard_close(&sdcard_handle, &partman_handle, + &filesystem_handle, partman_name, filesystem_name); + if (ret != 0) { + printf("error: sdcard_close(), ret = %d\n", ret); + _mqx_exit(1); + } + printf("SD card uninstalled.\n"); + + _mqx_exit(0); + +} + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Sources/main.h b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Sources/main.h new file mode 100644 index 000000000..23ba07231 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/Sources/main.h @@ -0,0 +1,20 @@ +/* main.h */ + +#ifndef __main_h_ +#define __main_h_ + +#include +#include +#include +#include +#include +#include +#include + +#define MAIN_TASK 1 + +extern void Main_task (uint32_t); +int benchmark_test(void* args); + +#endif /* __main_h_ */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch new file mode 100644 index 000000000..03b293770 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch new file mode 100644 index 000000000..beda4b284 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink new file mode 100644 index 000000000..de1b137f3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink @@ -0,0 +1,34 @@ +[BREAKPOINTS] +ShowInfoWin = 1 +EnableFlashBP = 2 +BPDuringExecution = 0 +[CFI] +CFISize = 0x00 +CFIAddr = 0x00 +[CPU] +OverrideMemMap = 0 +AllowSimulation = 1 +ScriptFile="" +[FLASH] +CacheExcludeSize = 0x00 +CacheExcludeAddr = 0x00 +MinNumBytesFlashDL = 0 +SkipProgOnCRCMatch = 1 +VerifyDownload = 1 +AllowCaching = 1 +EnableFlashDL = 2 +Override = 0 +Device="UNSPECIFIED" +[GENERAL] +WorkRAMSize = 0x00 +WorkRAMAddr = 0x00 +RAMUsageLimit = 0x00 +[SWO] +SWOLogFile="" +[MEM] +RdOverrideOrMask = 0x00 +RdOverrideAndMask = 0xFFFFFFFF +RdOverrideAddr = 0xFFFFFFFF +WrOverrideOrMask = 0x00 +WrOverrideAndMask = 0xFFFFFFFF +WrOverrideAddr = 0xFFFFFFFF diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch new file mode 100644 index 000000000..4b4a78bd1 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch new file mode 100644 index 000000000..4b4a78bd1 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch new file mode 100644 index 000000000..f09268cc4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_benchmark/wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/.cproject b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/.cproject new file mode 100644 index 000000000..6287ebbe5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/.cproject @@ -0,0 +1,681 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/.project b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/.project new file mode 100644 index 000000000..fab6252bd --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/.project @@ -0,0 +1,42 @@ + + + wolfcrypt_test + + + +wolfssl + +util_lib + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + Sources/test + 2 + PARENT-2-PROJECT_LOC/wolfcrypt/test + + + + + MQX_ROOT_DIR + file:/C:/Freescale/Freescale_MQX_4_1 + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Debugger/K70FN1M0.mem b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Debugger/K70FN1M0.mem new file mode 100644 index 000000000..4a7c6198d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Debugger/K70FN1M0.mem @@ -0,0 +1,43 @@ +// Memory Configuration File +// +// Description: +// A memory configuration file contains commands that define the legally accessible +// areas of memory for your specific board. Useful for example when the debugger +// tries to display the content of a "char *" variable, that has not yet been initialized. +// In this case the debugger may try to read from a bogus address, which could cause a +// bus error. +// +// Board: +// Kinetis K70FN1M0 +// +// Reference: +// - + + +// All reserved ranges read back 0xBABA... +reservedchar 0xBA + +usederivative "MK70F15" + +// Memory Map: +// ---------------------------------------------------------------------- + +range 0x00000000 0x000FFFFF 4 ReadWrite // 1024KB Code Flash +reserved 0x00100000 0x13FFFFFF +range 0x14000000 0x14003FFF 4 ReadWrite // 16KB Programming acceleration RAM +reserved 0x14004000 0x1FFEFFFF +range 0x1FFF0000 0x1FFFFFFF 4 ReadWrite // 64KB On chip SRAM (TCML) +range 0x20000000 0x2000FFFF 4 ReadWrite // 64KB On chip SRAM (TCMU) +reserved 0x20010000 0x21FFFFFF +range 0x22000000 0x221FFFFF 4 ReadWrite // Aliased to TCMU SRAM bitband +reserved 0x22200000 0x3FFFFFFF +reserved 0x60000000 0x6FFFFFFF // Flexbus for external memory +range 0x70000000 0x7FFFFFFF 4 ReadWrite // DRAM Controller - Write-back +range 0x80000000 0x8FFFFFFF 4 ReadWrite // DRAM Controller - Write-through +reserved 0x90000000 0xDFFFFFFF // Flexbus for external memory +reserved 0xE0100000 0xFFFFFFFF + +// Comment the following line for NFC-projects +reserved 0x400A8000 0x400ABEFF +// Uncomment the following line for NFC-projects +//range 0x400A8000 0x400ABEFF 4 ReadWrite diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Debugger/init_kinetis.tcl b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Debugger/init_kinetis.tcl new file mode 100644 index 000000000..467b8ff9f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Debugger/init_kinetis.tcl @@ -0,0 +1,71 @@ +# this method initializes debug modules which are not affected by software reset +# register names should be referenced including the register group name to improve performance + +proc init_debug_modules {} { + # initialize LR to avoid invalid stack after reset + reg "User\\/System Mode Registers/LR" = 0xFFFFFFFF + + # clear DWT function registers + reg "Core Debug Registers/DEMCR" = 0x1000001 + reg "Data Watchpoint and Trace Unit Registers/DWT_FUNCTION0" = 0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_FUNCTION1" = 0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_FUNCTION2" = 0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_FUNCTION3" = 0x0 + # clear FPB comparators + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP0" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP1" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP2" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP3" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP4" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP5" = 0x0 +} + +proc init_trace_modules {} { + # clear DWT registers + reg "Data Watchpoint and Trace Unit Registers/DWT_CTRL" =0x40000000 + reg "Data Watchpoint and Trace Unit Registers/DWT_CYCCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_CPICNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_EXCCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_SLEEPCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_LSUCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_FOLDCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_COMP0" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_COMP1" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_COMP2" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_COMP3" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_MASK0" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_MASK1" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_MASK2" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_MASK3" =0x0 + # clear ITM registers + reg "Instrumentation Trace Macrocell Registers/ITM_LAR" =0xc5acce55 + reg "Instrumentation Trace Macrocell Registers/ITM_TER" =0x0 + reg "Instrumentation Trace Macrocell Registers/ITM_TPR" =0x0 + reg "Instrumentation Trace Macrocell Registers/ITM_TCR" =0x0 + reg "Instrumentation Trace Macrocell Registers/ITM_LAR" =0x1 + # reset Funnel registers + reg "Embedded Trace Funnel Registers/ETF_FCR" =0x300 + # clear MCM registers + reg "Core Platform Miscellaneous Control Module (MCM) Registers/MCM_ETBCC" =0x0 + reg "Core Platform Miscellaneous Control Module (MCM) Registers/MCM_ETBRL" =0x0 + # set SCB_VTOR register for RAM + reg "System Control Registers/SCB_VTOR" =0x20000000 +} + +proc envsetup {} { + # Environment Setup + radix x + config hexprefix 0x + config MemIdentifier p + config MemWidth 32 + config MemAccess 32 + config MemSwap off +} + +#------------------------------------------------------------------------------- +# Main +#------------------------------------------------------------------------------- + + envsetup + init_debug_modules + init_trace_modules diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Debugger/mass_erase_kinetis.tcl b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Debugger/mass_erase_kinetis.tcl new file mode 100644 index 000000000..2d8b84054 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Debugger/mass_erase_kinetis.tcl @@ -0,0 +1,31 @@ +# This script performs the mass erase operation for Kinetis targets + +# Command mass erase with system reset and core reset +set mdmapControl [cmdwin::reg MDMAP_C -np] +set mdmapControl [expr $mdmapControl | 0x19] +cmdwin::reg MDMAP_C = $mdmapControl + +# Release system reset while still holding core reset +set mdmapControl [expr $mdmapControl & 0xFFFFFFF7] +cmdwin::reg MDMAP_C = $mdmapControl + +# Wait for the mass erase operation to complete +set done 0 +for {set i 0} {$i < 10} {incr i} { + refresh + set mdmapControl [cmdwin::reg MDMAP_C -np] + if {($mdmapControl & 1) == 0} { + set done 1 + break; + } + wait 50 +} + +# Release the core reset +set mdmapControl [expr $mdmapControl & 0xFFFFFFEF] +cmdwin::reg MDMAP_C = $mdmapControl +if {$done} { + puts "OK: Mass erase succeeded" +} else { + puts "Error: Timeout" +} \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/ReferencedRSESystems.xml b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/ReferencedRSESystems.xml new file mode 100644 index 000000000..ea3c502e9 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/ReferencedRSESystems.xml @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Sources/include.am b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Sources/include.am new file mode 100644 index 000000000..1fe7ffa28 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Sources/include.am @@ -0,0 +1,22 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mqx/wolfcrypt_test/.cproject \ + mqx/wolfcrypt_test/.project \ + mqx/wolfcrypt_test/Debugger/K70FN1M0.mem \ + mqx/wolfcrypt_test/Debugger/init_kinetis.tcl \ + mqx/wolfcrypt_test/Debugger/mass_erase_kinetis.tcl \ + mqx/wolfcrypt_test/ReferencedRSESystems.xml \ + mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch \ + mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch \ + mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink \ + mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch \ + mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch \ + mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch + +EXTRA_DIST += \ + mqx/wolfcrypt_test/Sources/main.c \ + mqx/wolfcrypt_test/Sources/main.h + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Sources/main.c b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Sources/main.c new file mode 100644 index 000000000..040a2bf3c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Sources/main.c @@ -0,0 +1,94 @@ +/* main.c */ + +#include "main.h" + +/* SD card open/close utility functions */ +#include "util.h" + +#if !BSPCFG_ENABLE_IO_SUBSYSTEM +#error This application requires BSPCFG_ENABLE_IO_SUBSYSTEM defined \ + non-zero in user_config.h. Please recompile BSP with this option. +#endif + +#ifndef BSP_DEFAULT_IO_CHANNEL_DEFINED +#error This application requires BSP_DEFAULT_IO_CHANNEL to be not NULL. \ + Please set corresponding BSPCFG_ENABLE_TTYx to non-zero in \ + user_config.h and recompile BSP with this option. +#endif + +TASK_TEMPLATE_STRUCT MQX_template_list[] = +{ + /* Task number, Entry point, Stack, Pri, String, Auto? */ + {MAIN_TASK, Main_task, 20000, 9, "main", MQX_AUTO_START_TASK}, + {0, 0, 0, 0, 0, 0, } +}; + +#if defined BSP_SDCARD_ESDHC_CHANNEL + #if ! BSPCFG_ENABLE_ESDHC + #error This application requires BSPCFG_ENABLE_ESDHC defined \ + non-zero in user_config.h. Please recompile libraries with \ + this option. + #endif + +#elif defined BSP_SDCARD_SDHC_CHANNEL + #if ! BSPCFG_ENABLE_SDHC + #error This application requires BSPCFG_ENABLE_SDHC defined \ + non-zero in user_config.h. Please recompile libraries with \ + this option. + #endif +#endif + +#if defined (BSP_SDCARD_SPI_CHANNEL) + #define SDCARD_COM_CHANNEL BSP_SDCARD_SPI_CHANNEL +#elif defined (BSP_SDCARD_ESDHC_CHANNEL) + #define SDCARD_COM_CHANNEL BSP_SDCARD_ESDHC_CHANNEL +#elif defined (BSP_SDCARD_SDHC_CHANNEL) + #define SDCARD_COM_CHANNEL BSP_SDCARD_SDHC_CHANNEL +#else + #error "SDCARD low level communication device not defined!" +#endif + +/* func_args from test.h */ +typedef struct func_args { + int argc; + char** argv; + int return_code; +} func_args; + +/*TASK*----------------------------------------------------------------- + * Function Name : Main_task + * Comments : + * This task opens the SD card device and runs the + * wolfCrypt test functions located in test.c. + *END------------------------------------------------------------------*/ + +void Main_task(uint32_t initial_data) +{ + int ret = 0; + func_args args; + char filesystem_name[] = "a:"; + char partman_name[] = "pm:"; + MQX_FILE_PTR com_handle, sdcard_handle, filesystem_handle, partman_handle; + + ret = sdcard_open(&com_handle, &sdcard_handle, &partman_handle, + &filesystem_handle, partman_name, filesystem_name); + if (ret != 0) { + printf("error: sdcard_open(), ret = %d\n", ret); + _mqx_exit(1); + } + printf("SD card installed to %s\n", filesystem_name); + + wolfcrypt_test(&args); + + ret = sdcard_close(&sdcard_handle, &partman_handle, + &filesystem_handle, partman_name, filesystem_name); + if (ret != 0) { + printf("error: sdcard_close(), ret = %d\n", ret); + _mqx_exit(1); + } + printf("SD card uninstalled.\n"); + + _mqx_exit(0); + +} + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Sources/main.h b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Sources/main.h new file mode 100644 index 000000000..189c7ce15 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/Sources/main.h @@ -0,0 +1,20 @@ +/* main.h */ + +#ifndef __main_h_ +#define __main_h_ + +#include +#include +#include +#include +#include +#include +#include + +#define MAIN_TASK 1 + +extern void Main_task (uint32_t); +void wolfcrypt_test(void* args); + +#endif /* __main_h_ */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch new file mode 100644 index 000000000..bc7fd451b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch new file mode 100644 index 000000000..9217d72fa --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink new file mode 100644 index 000000000..f40a58f1c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink @@ -0,0 +1,34 @@ +[BREAKPOINTS] +ShowInfoWin = 1 +EnableFlashBP = 2 +BPDuringExecution = 0 +[CFI] +CFISize = 0x00 +CFIAddr = 0x00 +[CPU] +OverrideMemMap = 0 +AllowSimulation = 1 +ScriptFile="" +[FLASH] +CacheExcludeSize = 0x00 +CacheExcludeAddr = 0x00 +MinNumBytesFlashDL = 0 +SkipProgOnCRCMatch = 1 +VerifyDownload = 1 +AllowCaching = 1 +EnableFlashDL = 2 +Override = 0 +Device="UNSPECIFIED" +[GENERAL] +WorkRAMSize = 0x00 +WorkRAMAddr = 0x00 +RAMUsageLimit = 0x00 +[SWO] +SWOLogFile="" +[MEM] +RdOverrideOrMask = 0x00 +RdOverrideAndMask = 0xFFFFFFFF +RdOverrideAddr = 0xFFFFFFFF +WrOverrideOrMask = 0x00 +WrOverrideAndMask = 0xFFFFFFFF +WrOverrideAddr = 0xFFFFFFFF diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch new file mode 100644 index 000000000..2cc81ce38 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch new file mode 100644 index 000000000..2cc81ce38 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch new file mode 100644 index 000000000..d089c2435 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfcrypt_test/wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl/.cproject b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl/.cproject new file mode 100644 index 000000000..7a2b634f8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl/.cproject @@ -0,0 +1,1145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl/.project b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl/.project new file mode 100644 index 000000000..8a201057b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl/.project @@ -0,0 +1,48 @@ + + + wolfssl + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + twrk70f120m_Int_Flash_DDRData_Debug + 2 + PARENT-5-PROJECT_LOC/Documents/GitHub/wolfssl/mqx/wolfssl/twrk70f120m_Int_Flash_DDRData_Debug/build-wolfssl-twrk70f120m_Int_Flash_DDRData_Debug + + + Sources/wolfcrypt_src + 2 + PARENT-2-PROJECT_LOC/wolfcrypt/src + + + Sources/wolfssl_src + 2 + PARENT-2-PROJECT_LOC/src + + + + + MQX_ROOT_DIR + file:/C:/Freescale/Freescale_MQX_4_1 + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl/include.am b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl/include.am new file mode 100644 index 000000000..99cbf0895 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl/include.am @@ -0,0 +1,11 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mqx/README + +EXTRA_DIST += \ + mqx/wolfssl/.cproject \ + mqx/wolfssl/.project + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/.cproject b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/.cproject new file mode 100644 index 000000000..559a66666 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/.cproject @@ -0,0 +1,681 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/.project b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/.project new file mode 100644 index 000000000..f82a98c06 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/.project @@ -0,0 +1,35 @@ + + + wolfssl_client + + + +wolfssl + +util_lib + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + MQX_ROOT_DIR + file:/C:/Freescale/Freescale_MQX_4_1 + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Debugger/K70FN1M0.mem b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Debugger/K70FN1M0.mem new file mode 100644 index 000000000..4a7c6198d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Debugger/K70FN1M0.mem @@ -0,0 +1,43 @@ +// Memory Configuration File +// +// Description: +// A memory configuration file contains commands that define the legally accessible +// areas of memory for your specific board. Useful for example when the debugger +// tries to display the content of a "char *" variable, that has not yet been initialized. +// In this case the debugger may try to read from a bogus address, which could cause a +// bus error. +// +// Board: +// Kinetis K70FN1M0 +// +// Reference: +// - + + +// All reserved ranges read back 0xBABA... +reservedchar 0xBA + +usederivative "MK70F15" + +// Memory Map: +// ---------------------------------------------------------------------- + +range 0x00000000 0x000FFFFF 4 ReadWrite // 1024KB Code Flash +reserved 0x00100000 0x13FFFFFF +range 0x14000000 0x14003FFF 4 ReadWrite // 16KB Programming acceleration RAM +reserved 0x14004000 0x1FFEFFFF +range 0x1FFF0000 0x1FFFFFFF 4 ReadWrite // 64KB On chip SRAM (TCML) +range 0x20000000 0x2000FFFF 4 ReadWrite // 64KB On chip SRAM (TCMU) +reserved 0x20010000 0x21FFFFFF +range 0x22000000 0x221FFFFF 4 ReadWrite // Aliased to TCMU SRAM bitband +reserved 0x22200000 0x3FFFFFFF +reserved 0x60000000 0x6FFFFFFF // Flexbus for external memory +range 0x70000000 0x7FFFFFFF 4 ReadWrite // DRAM Controller - Write-back +range 0x80000000 0x8FFFFFFF 4 ReadWrite // DRAM Controller - Write-through +reserved 0x90000000 0xDFFFFFFF // Flexbus for external memory +reserved 0xE0100000 0xFFFFFFFF + +// Comment the following line for NFC-projects +reserved 0x400A8000 0x400ABEFF +// Uncomment the following line for NFC-projects +//range 0x400A8000 0x400ABEFF 4 ReadWrite diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Debugger/init_kinetis.tcl b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Debugger/init_kinetis.tcl new file mode 100644 index 000000000..467b8ff9f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Debugger/init_kinetis.tcl @@ -0,0 +1,71 @@ +# this method initializes debug modules which are not affected by software reset +# register names should be referenced including the register group name to improve performance + +proc init_debug_modules {} { + # initialize LR to avoid invalid stack after reset + reg "User\\/System Mode Registers/LR" = 0xFFFFFFFF + + # clear DWT function registers + reg "Core Debug Registers/DEMCR" = 0x1000001 + reg "Data Watchpoint and Trace Unit Registers/DWT_FUNCTION0" = 0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_FUNCTION1" = 0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_FUNCTION2" = 0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_FUNCTION3" = 0x0 + # clear FPB comparators + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP0" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP1" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP2" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP3" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP4" = 0x0 + reg "Flash Patch and Breakpoint Unit Registers/FP_COMP5" = 0x0 +} + +proc init_trace_modules {} { + # clear DWT registers + reg "Data Watchpoint and Trace Unit Registers/DWT_CTRL" =0x40000000 + reg "Data Watchpoint and Trace Unit Registers/DWT_CYCCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_CPICNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_EXCCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_SLEEPCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_LSUCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_FOLDCNT" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_COMP0" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_COMP1" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_COMP2" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_COMP3" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_MASK0" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_MASK1" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_MASK2" =0x0 + reg "Data Watchpoint and Trace Unit Registers/DWT_MASK3" =0x0 + # clear ITM registers + reg "Instrumentation Trace Macrocell Registers/ITM_LAR" =0xc5acce55 + reg "Instrumentation Trace Macrocell Registers/ITM_TER" =0x0 + reg "Instrumentation Trace Macrocell Registers/ITM_TPR" =0x0 + reg "Instrumentation Trace Macrocell Registers/ITM_TCR" =0x0 + reg "Instrumentation Trace Macrocell Registers/ITM_LAR" =0x1 + # reset Funnel registers + reg "Embedded Trace Funnel Registers/ETF_FCR" =0x300 + # clear MCM registers + reg "Core Platform Miscellaneous Control Module (MCM) Registers/MCM_ETBCC" =0x0 + reg "Core Platform Miscellaneous Control Module (MCM) Registers/MCM_ETBRL" =0x0 + # set SCB_VTOR register for RAM + reg "System Control Registers/SCB_VTOR" =0x20000000 +} + +proc envsetup {} { + # Environment Setup + radix x + config hexprefix 0x + config MemIdentifier p + config MemWidth 32 + config MemAccess 32 + config MemSwap off +} + +#------------------------------------------------------------------------------- +# Main +#------------------------------------------------------------------------------- + + envsetup + init_debug_modules + init_trace_modules diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Debugger/mass_erase_kinetis.tcl b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Debugger/mass_erase_kinetis.tcl new file mode 100644 index 000000000..2d8b84054 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Debugger/mass_erase_kinetis.tcl @@ -0,0 +1,31 @@ +# This script performs the mass erase operation for Kinetis targets + +# Command mass erase with system reset and core reset +set mdmapControl [cmdwin::reg MDMAP_C -np] +set mdmapControl [expr $mdmapControl | 0x19] +cmdwin::reg MDMAP_C = $mdmapControl + +# Release system reset while still holding core reset +set mdmapControl [expr $mdmapControl & 0xFFFFFFF7] +cmdwin::reg MDMAP_C = $mdmapControl + +# Wait for the mass erase operation to complete +set done 0 +for {set i 0} {$i < 10} {incr i} { + refresh + set mdmapControl [cmdwin::reg MDMAP_C -np] + if {($mdmapControl & 1) == 0} { + set done 1 + break; + } + wait 50 +} + +# Release the core reset +set mdmapControl [expr $mdmapControl & 0xFFFFFFEF] +cmdwin::reg MDMAP_C = $mdmapControl +if {$done} { + puts "OK: Mass erase succeeded" +} else { + puts "Error: Timeout" +} \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/ReferencedRSESystems.xml b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/ReferencedRSESystems.xml new file mode 100644 index 000000000..4feeab4e3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/ReferencedRSESystems.xml @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Sources/include.am b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Sources/include.am new file mode 100644 index 000000000..335af80c6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Sources/include.am @@ -0,0 +1,22 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +EXTRA_DIST += \ + mqx/wolfssl_client/.cproject \ + mqx/wolfssl_client/.project \ + mqx/wolfssl_client/Debugger/K70FN1M0.mem \ + mqx/wolfssl_client/Debugger/init_kinetis.tcl \ + mqx/wolfssl_client/Debugger/mass_erase_kinetis.tcl \ + mqx/wolfssl_client/ReferencedRSESystems.xml \ + mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch \ + mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch \ + mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink \ + mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch \ + mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch \ + mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch + +EXTRA_DIST += \ + mqx/wolfssl_client/Sources/main.c \ + mqx/wolfssl_client/Sources/main.h + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Sources/main.c b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Sources/main.c new file mode 100644 index 000000000..4b42b79ad --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Sources/main.c @@ -0,0 +1,293 @@ +/* + * main.c + */ + +#include "main.h" +#include "util.h" + +#if !BSPCFG_ENABLE_IO_SUBSYSTEM +#error This application requires BSPCFG_ENABLE_IO_SUBSYSTEM defined \ + non-zero in user_config.h. Please recompile BSP with this option. +#endif + +#ifndef BSP_DEFAULT_IO_CHANNEL_DEFINED +#error This application requires BSP_DEFAULT_IO_CHANNEL to be not NULL. \ + Please set corresponding BSPCFG_ENABLE_TTYx to non-zero in \ + user_config.h and recompile BSP with this option. +#endif + +#if defined BSP_SDCARD_ESDHC_CHANNEL +#if ! BSPCFG_ENABLE_ESDHC +#error This application requires BSPCFG_ENABLE_ESDHC defined non-zero in \ + user_config.h. Please recompile libraries with this option. +#endif + +#elif defined BSP_SDCARD_SDHC_CHANNEL + +#if ! BSPCFG_ENABLE_SDHC +#error This application requires BSPCFG_ENABLE_SDHC defined non-zero in \ + user_config.h. Please recompile libraries with this option. +#endif + +#endif + +#if defined (BSP_SDCARD_SPI_CHANNEL) + #define SDCARD_COM_CHANNEL BSP_SDCARD_SPI_CHANNEL +#elif defined (BSP_SDCARD_ESDHC_CHANNEL) + #define SDCARD_COM_CHANNEL BSP_SDCARD_ESDHC_CHANNEL +#elif defined (BSP_SDCARD_SDHC_CHANNEL) + #define SDCARD_COM_CHANNEL BSP_SDCARD_SDHC_CHANNEL +#else + #error "SDCARD low level communication device not defined!" +#endif + +TASK_TEMPLATE_STRUCT MQX_template_list[] = +{ + /* Task number, Entry point, Stack, Pri, String, Auto? */ + {MAIN_TASK, Main_task, 20000, 9, "main", MQX_AUTO_START_TASK}, + {0, 0, 0, 0, 0, 0, } +}; + +/*TASK*----------------------------------------------------- + * + * Task Name : Main_task + * Comments : + * This task sets up the SD card and Ethernet devices, + * then starts the example wolfSSL client. The example + * wolfSSL client connects to a server over TLS and sends + * a simple HTTP GET message, then prints out the reply + * from the server. + * + * To change the IP address and port of the server, + * change the wolfsslIP and wolfsslPort variables in + * client_test(). Note that wolfsslIP needs to be given + * in hexadecimal. + * + *END*-----------------------------------------------------*/ + +void Main_task(uint32_t initial_data) +{ + int ret = 0; + char filesystem_name[] = "a:"; + char partman_name[] = "pm:"; + MQX_FILE_PTR com_handle, sdcard_handle, filesystem_handle, partman_handle; + + printf("Starting client example... \n"); + + ret = sdcard_open(&com_handle, &sdcard_handle, &partman_handle, + &filesystem_handle, partman_name, filesystem_name); + + if (ret != 0) { + printf("error: sdcard_open(), ret = %d\n", ret); + _mqx_exit(1); + } + printf("SD card installed to %s\n", filesystem_name); + + setup_ethernet(); + setup_clock(); + client_test(); + + ret = sdcard_close(&sdcard_handle, &partman_handle, &filesystem_handle, + partman_name, filesystem_name); + + if (ret != 0) { + printf("error: sdcard_close(), ret = %d\n", ret); + _mqx_exit(1); + } + printf("SD card uninstalled.\n"); + + _mqx_exit(0); +} + +void setup_ethernet(void) +{ + int error; + _enet_handle ehandle; /* for Ethernet driver */ + _rtcs_if_handle ihandle; + _enet_address address; + + error = RTCS_create(); + if (error) { + err_sys("failed to create RTCS"); + } + + ENET_get_mac_address(BSP_DEFAULT_ENET_DEVICE, ENET_IPADDR, address); + + /* Set up the Ethernet driver */ + error = ENET_initialize(BSP_DEFAULT_ENET_DEVICE, address, 0, &ehandle); + if (error) + err_sys("failed to initialize Ethernet driver"); + + error = RTCS_if_add(ehandle, RTCS_IF_ENET, &ihandle); + if (error) + err_sys("failed to add interface for Ethernet"); + + error = RTCS_if_bind(ihandle, ENET_IPADDR, ENET_IPMASK); + if (error) + err_sys("failed to bind interface for Ethernet"); + +#ifdef GATE_IPADDR + RTCS_gate_add(GATE_IPADDR, INADDR_ANY, INADDR_ANY); +#endif + + printf("Ethernet device %d bound to %X\n", BSP_DEFAULT_ENET_DEVICE, + ENET_IPADDR); +} + +void setup_clock(void) +{ + uint32_t ret = 0, i = 0; + uint32_t sntp_connected = 0; + uint32_t sntp_max_tries = 3; + TIME_STRUCT time_s; + DATE_STRUCT date_s; + + /* NTP server: nist1-lnk.binary.net */ + _ip_address ipaddr = IPADDR(216,229,0,179); + + for (i = 0; i < sntp_max_tries; i++) { + + printf("Getting time from NTP server [ attempt %u of %u ]...\n", + i+1, sntp_max_tries); + + /* update time from NTP server */ + ret = SNTP_oneshot(ipaddr, 5000); + + if (ret == RTCS_OK) { + sntp_connected = 1; + printf("SNTP successfully updated device time\n"); + break; + } else if (ret == RTCSERR_TIMEOUT) { + printf("SNTP attempt timed out.\n"); + } + + _time_delay(1000); + } + + if (sntp_connected == 0) { + err_sys("SNTP failed to update device time"); + } + + /* print device time, for debug purposes */ + _time_get(&time_s); + _time_to_date(&time_s, &date_s); + printf("Current time: %02d/%02d/%02d %02d:%02d:%02d\n", + date_s.YEAR, date_s.MONTH, date_s.DAY, date_s.HOUR, date_s.MINUTE, + date_s.SECOND); + + return; +} + +int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store) +{ + (void)preverify; + char buffer[80]; + + printf("In verification callback, error = %d, %s\n", + store->error, wolfSSL_ERR_error_string(store->error, buffer)); + + return 0; +} + +void client_test(void) +{ + char msg[64]; + char reply[1024]; + int sockfd, input; + int ret = 0, msgSz = 0; + struct sockaddr_in servaddr; + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + + long wolfsslIP = IPADDR(192,168,1,125); + long wolfsslPort = 11111; + + /* for debug, compile wolfSSL with DEBUG_WOLFSSL defined */ + wolfSSL_Debugging_ON(); + + wolfSSL_Init(); + + ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + if (ctx == 0) + err_sys("setting up ctx"); + + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify); + + ret = wolfSSL_CTX_use_certificate_file(ctx, clientCert, SSL_FILETYPE_PEM); + if (ret != SSL_SUCCESS) + err_sys("can't load client cert file, check file"); + + ret = wolfSSL_CTX_use_PrivateKey_file(ctx, clientKey, SSL_FILETYPE_PEM); + if (ret != SSL_SUCCESS) + err_sys("can't load client key file, check file"); + + ret = wolfSSL_CTX_load_verify_locations(ctx, caCert, 0); + if (ret != SSL_SUCCESS) + err_sys("can't load CA cert file, check file"); + + /* create socket descriptor */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == RTCS_SOCKET_ERROR) { + err_sys("socket creation failed"); + } else { + printf("socket created successfully\n"); + } + + /* + * Unlike most TCP/IP stacks, RTCS requires that sin_port and + * sin_addr needs to be in Host Byte Order, not Network Byte Order. + * This means we shouldn't use htons() when setting these values. + */ + memset((char*)&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = wolfsslPort; + servaddr.sin_addr.s_addr = wolfsslIP; + + ret = connect(sockfd, &servaddr, sizeof(servaddr)); + if (ret != RTCS_OK) { + err_sys("connect() failed"); + } else { + printf("Connected to %lx, port %d.\n", servaddr.sin_addr.s_addr, + servaddr.sin_port); + } + + if ( (ssl = wolfSSL_new(ctx)) == NULL) + err_sys("wolfSSL_new failed"); + + ret = wolfSSL_set_fd(ssl, sockfd); + if (ret != SSL_SUCCESS) + err_sys("wolfSSL_set_fd failed"); + + ret = wolfSSL_connect(ssl); + if (ret != SSL_SUCCESS) + err_sys("wolfSSL_connect failed"); + + printf("wolfSSL_connect() ok, sending GET...\n"); + msgSz = 28; + strncpy(msg, "GET /index.html HTTP/1.0\r\n\r\n", msgSz); + if (wolfSSL_write(ssl, msg, msgSz) != msgSz) + err_sys("wolfSSL_write() failed"); + + input = wolfSSL_read(ssl, reply, sizeof(reply)-1); + if (input > 0) { + reply[input] = 0; + printf("Server response: %s\n", reply); + + while (1) { + input = wolfSSL_read(ssl, reply, sizeof(reply)-1); + if (input > 0) { + reply[input] = 0; + printf("%s\n", reply); + } else { + break; + } + } + } + + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + wolfSSL_Cleanup(); +} + +/* EOF */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Sources/main.h b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Sources/main.h new file mode 100644 index 000000000..1740ddcb4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/Sources/main.h @@ -0,0 +1,60 @@ +/* main.h */ + +#ifndef __main_h_ +#define __main_h_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MAIN_TASK 1 + +extern void Main_task(uint32_t); +extern void setup_ethernet(void); +extern void setup_clock(void); +extern void client_test(void); + +/* cert file locations */ +static const char* caCert = "a:\\certs\\ca-cert.pem"; +static const char* clientCert = "a:\\certs\\client-cert.pem"; +static const char* clientKey = "a:\\certs\\client-key.pem"; + +static inline void err_sys(const char* msg) +{ + printf("wolfssl error: %s\n", msg); + if (msg) + _mqx_exit(1); +} + +/* PPP device must be set manually and + * must be different from the default IO channel (BSP_DEFAULT_IO_CHANNEL) + */ +#define PPP_DEVICE "ittyb:" + +/* + * Define PPP_DEVICE_DUN only when using PPP to communicate + * to Win9x Dial-Up Networking over a null-modem + * This is ignored if PPP_DEVICE is not #define'd + */ +#define PPP_DEVICE_DUN 1 + +#ifndef ENET_IPADDR + #define ENET_IPADDR IPADDR(192,168,1,155) +#endif + +#ifndef ENET_IPMASK + #define ENET_IPMASK IPADDR(255,255,255,0) +#endif + +#define GATE_IPADDR IPADDR(192,168,1,1) + +#endif /* __main_h_ */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch new file mode 100644 index 000000000..183c73dc4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch new file mode 100644 index 000000000..32434797a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink new file mode 100644 index 000000000..f40a58f1c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink @@ -0,0 +1,34 @@ +[BREAKPOINTS] +ShowInfoWin = 1 +EnableFlashBP = 2 +BPDuringExecution = 0 +[CFI] +CFISize = 0x00 +CFIAddr = 0x00 +[CPU] +OverrideMemMap = 0 +AllowSimulation = 1 +ScriptFile="" +[FLASH] +CacheExcludeSize = 0x00 +CacheExcludeAddr = 0x00 +MinNumBytesFlashDL = 0 +SkipProgOnCRCMatch = 1 +VerifyDownload = 1 +AllowCaching = 1 +EnableFlashDL = 2 +Override = 0 +Device="UNSPECIFIED" +[GENERAL] +WorkRAMSize = 0x00 +WorkRAMAddr = 0x00 +RAMUsageLimit = 0x00 +[SWO] +SWOLogFile="" +[MEM] +RdOverrideOrMask = 0x00 +RdOverrideAndMask = 0xFFFFFFFF +RdOverrideAddr = 0xFFFFFFFF +WrOverrideOrMask = 0x00 +WrOverrideAndMask = 0xFFFFFFFF +WrOverrideAddr = 0xFFFFFFFF diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch new file mode 100644 index 000000000..66a3e7c01 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch new file mode 100644 index 000000000..66a3e7c01 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch new file mode 100644 index 000000000..9f67cb934 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/mqx/wolfssl_client/wolfssl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/resource.h b/FreeRTOS-Plus/Source/WolfSSL/resource.h new file mode 100644 index 000000000..b8c8297e7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by wolfssl.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/rpm/spec.in b/FreeRTOS-Plus/Source/WolfSSL/rpm/spec.in index 1e291ddbf..188d91066 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/rpm/spec.in +++ b/FreeRTOS-Plus/Source/WolfSSL/rpm/spec.in @@ -59,21 +59,26 @@ mkdir -p $RPM_BUILD_ROOT/ %files %defattr(-,root,root,-) -%doc AUTHORS ChangeLog COPYING NEWS README +%doc AUTHORS ChangeLog.md COPYING README README.md %{_docdir}/wolfssl/taoCert.txt %{_docdir}/wolfssl/example/echoserver.c %{_docdir}/wolfssl/example/server.c %{_docdir}/wolfssl/example/echoclient.c %{_docdir}/wolfssl/example/client.c +%{_docdir}/wolfssl/example/sctp-client.c +%{_docdir}/wolfssl/example/sctp-server.c +%{_docdir}/wolfssl/example/sctp-client-dtls.c +%{_docdir}/wolfssl/example/sctp-server-dtls.c +%{_docdir}/wolfssl/example/tls_bench.c %{_docdir}/wolfssl/README.txt %{_libdir}/libwolfssl.la %{_libdir}/libwolfssl.so -%{_libdir}/libwolfssl.so.0 -%{_libdir}/libwolfssl.so.0.0.2 +%{_libdir}/libwolfssl.so.24 +%{_libdir}/libwolfssl.so.24.1.0 %files devel %defattr(-,root,root,-) -%doc AUTHORS ChangeLog COPYING NEWS README +%doc AUTHORS ChangeLog.md COPYING README README.md %{_bindir}/wolfssl-config %{_includedir}/cyassl/callbacks.h %{_includedir}/cyassl/certs_test.h @@ -108,7 +113,6 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/cyassl/ctaocrypt/mpi_superclass.h %{_includedir}/cyassl/ctaocrypt/pkcs7.h %{_includedir}/cyassl/ctaocrypt/poly1305.h -%{_includedir}/cyassl/ctaocrypt/wc_port.h %{_includedir}/cyassl/ctaocrypt/pwdbased.h %{_includedir}/cyassl/ctaocrypt/rabbit.h %{_includedir}/cyassl/ctaocrypt/random.h @@ -122,6 +126,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/cyassl/ctaocrypt/tfm.h %{_includedir}/cyassl/ctaocrypt/types.h %{_includedir}/cyassl/ctaocrypt/visibility.h +%{_includedir}/cyassl/ctaocrypt/wc_port.h %{_includedir}/cyassl/error-ssl.h %{_includedir}/cyassl/ocsp.h %{_includedir}/cyassl/openssl/asn1.h @@ -133,7 +138,12 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/cyassl/openssl/dh.h %{_includedir}/cyassl/openssl/dsa.h %{_includedir}/cyassl/openssl/ec.h +%{_includedir}/cyassl/openssl/ec25519.h +%{_includedir}/cyassl/openssl/ec448.h +%{_includedir}/cyassl/openssl/ecdh.h %{_includedir}/cyassl/openssl/ecdsa.h +%{_includedir}/cyassl/openssl/ed25519.h +%{_includedir}/cyassl/openssl/ed448.h %{_includedir}/cyassl/openssl/engine.h %{_includedir}/cyassl/openssl/err.h %{_includedir}/cyassl/openssl/evp.h @@ -152,6 +162,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 @@ -165,6 +176,61 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/callbacks.h %{_includedir}/wolfssl/certs_test.h %{_includedir}/wolfssl/crl.h +%{_includedir}/wolfssl/error-ssl.h +%{_includedir}/wolfssl/ocsp.h +%{_includedir}/wolfssl/openssl/aes.h +%{_includedir}/wolfssl/openssl/asn1.h +%{_includedir}/wolfssl/openssl/bio.h +%{_includedir}/wolfssl/openssl/bn.h +%{_includedir}/wolfssl/openssl/buffer.h +%{_includedir}/wolfssl/openssl/conf.h +%{_includedir}/wolfssl/openssl/crypto.h +%{_includedir}/wolfssl/openssl/des.h +%{_includedir}/wolfssl/openssl/dh.h +%{_includedir}/wolfssl/openssl/dsa.h +%{_includedir}/wolfssl/openssl/ec.h +%{_includedir}/wolfssl/openssl/ec25519.h +%{_includedir}/wolfssl/openssl/ec448.h +%{_includedir}/wolfssl/openssl/ecdh.h +%{_includedir}/wolfssl/openssl/ecdsa.h +%{_includedir}/wolfssl/openssl/ed25519.h +%{_includedir}/wolfssl/openssl/ed448.h +%{_includedir}/wolfssl/openssl/engine.h +%{_includedir}/wolfssl/openssl/err.h +%{_includedir}/wolfssl/openssl/evp.h +%{_includedir}/wolfssl/openssl/hmac.h +%{_includedir}/wolfssl/openssl/lhash.h +%{_includedir}/wolfssl/openssl/md4.h +%{_includedir}/wolfssl/openssl/md5.h +%{_includedir}/wolfssl/openssl/obj_mac.h +%{_includedir}/wolfssl/openssl/objects.h +%{_includedir}/wolfssl/openssl/ocsp.h +%{_includedir}/wolfssl/openssl/opensslconf.h +%{_includedir}/wolfssl/openssl/opensslv.h +%{_includedir}/wolfssl/openssl/ossl_typ.h +%{_includedir}/wolfssl/openssl/pem.h +%{_includedir}/wolfssl/openssl/pkcs12.h +%{_includedir}/wolfssl/openssl/pkcs7.h +%{_includedir}/wolfssl/openssl/rand.h +%{_includedir}/wolfssl/openssl/rc4.h +%{_includedir}/wolfssl/openssl/ripemd.h +%{_includedir}/wolfssl/openssl/rsa.h +%{_includedir}/wolfssl/openssl/sha.h +%{_includedir}/wolfssl/openssl/sha3.h +%{_includedir}/wolfssl/openssl/ssl.h +%{_includedir}/wolfssl/openssl/ssl23.h +%{_includedir}/wolfssl/openssl/stack.h +%{_includedir}/wolfssl/openssl/tls1.h +%{_includedir}/wolfssl/openssl/ui.h +%{_includedir}/wolfssl/openssl/x509.h +%{_includedir}/wolfssl/openssl/x509_vfy.h +%{_includedir}/wolfssl/openssl/x509v3.h +%{_includedir}/wolfssl/options.h +%{_includedir}/wolfssl/sniffer.h +%{_includedir}/wolfssl/sniffer_error.h +%{_includedir}/wolfssl/ssl.h +%{_includedir}/wolfssl/test.h +%{_includedir}/wolfssl/version.h %{_includedir}/wolfssl/wolfcrypt/aes.h %{_includedir}/wolfssl/wolfcrypt/arc4.h %{_includedir}/wolfssl/wolfcrypt/asn.h @@ -175,32 +241,41 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/wolfcrypt/camellia.h %{_includedir}/wolfssl/wolfcrypt/chacha.h %{_includedir}/wolfssl/wolfcrypt/chacha20_poly1305.h +%{_includedir}/wolfssl/wolfcrypt/cmac.h %{_includedir}/wolfssl/wolfcrypt/coding.h %{_includedir}/wolfssl/wolfcrypt/compress.h +%{_includedir}/wolfssl/wolfcrypt/cpuid.h +%{_includedir}/wolfssl/wolfcrypt/cryptocb.h %{_includedir}/wolfssl/wolfcrypt/curve25519.h +%{_includedir}/wolfssl/wolfcrypt/curve448.h %{_includedir}/wolfssl/wolfcrypt/des3.h %{_includedir}/wolfssl/wolfcrypt/dh.h %{_includedir}/wolfssl/wolfcrypt/dsa.h %{_includedir}/wolfssl/wolfcrypt/ecc.h %{_includedir}/wolfssl/wolfcrypt/ed25519.h +%{_includedir}/wolfssl/wolfcrypt/ed448.h %{_includedir}/wolfssl/wolfcrypt/error-crypt.h +%{_includedir}/wolfssl/wolfcrypt/fe_448.h %{_includedir}/wolfssl/wolfcrypt/fe_operations.h %{_includedir}/wolfssl/wolfcrypt/fips_test.h +%{_includedir}/wolfssl/wolfcrypt/ge_448.h %{_includedir}/wolfssl/wolfcrypt/ge_operations.h %{_includedir}/wolfssl/wolfcrypt/hash.h %{_includedir}/wolfssl/wolfcrypt/hc128.h %{_includedir}/wolfssl/wolfcrypt/hmac.h +%{_includedir}/wolfssl/wolfcrypt/idea.h %{_includedir}/wolfssl/wolfcrypt/integer.h %{_includedir}/wolfssl/wolfcrypt/logging.h %{_includedir}/wolfssl/wolfcrypt/md2.h %{_includedir}/wolfssl/wolfcrypt/md4.h %{_includedir}/wolfssl/wolfcrypt/md5.h +%{_includedir}/wolfssl/wolfcrypt/mem_track.h %{_includedir}/wolfssl/wolfcrypt/memory.h %{_includedir}/wolfssl/wolfcrypt/misc.h %{_includedir}/wolfssl/wolfcrypt/mpi_class.h %{_includedir}/wolfssl/wolfcrypt/mpi_superclass.h +%{_includedir}/wolfssl/wolfcrypt/pkcs12.h %{_includedir}/wolfssl/wolfcrypt/pkcs7.h -%{_includedir}/wolfssl/wolfcrypt/wc_port.h %{_includedir}/wolfssl/wolfcrypt/poly1305.h %{_includedir}/wolfssl/wolfcrypt/pwdbased.h %{_includedir}/wolfssl/wolfcrypt/rabbit.h @@ -210,56 +285,61 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/wolfcrypt/settings.h %{_includedir}/wolfssl/wolfcrypt/sha.h %{_includedir}/wolfssl/wolfcrypt/sha256.h +%{_includedir}/wolfssl/wolfcrypt/sha3.h %{_includedir}/wolfssl/wolfcrypt/sha512.h +%{_includedir}/wolfssl/wolfcrypt/signature.h +%{_includedir}/wolfssl/wolfcrypt/srp.h %{_includedir}/wolfssl/wolfcrypt/tfm.h %{_includedir}/wolfssl/wolfcrypt/types.h %{_includedir}/wolfssl/wolfcrypt/visibility.h -%{_includedir}/wolfssl/error-ssl.h -%{_includedir}/wolfssl/ocsp.h -%{_includedir}/wolfssl/openssl/asn1.h -%{_includedir}/wolfssl/openssl/bio.h -%{_includedir}/wolfssl/openssl/bn.h -%{_includedir}/wolfssl/openssl/conf.h -%{_includedir}/wolfssl/openssl/crypto.h -%{_includedir}/wolfssl/openssl/des.h -%{_includedir}/wolfssl/openssl/dh.h -%{_includedir}/wolfssl/openssl/dsa.h -%{_includedir}/wolfssl/openssl/ec.h -%{_includedir}/wolfssl/openssl/ecdsa.h -%{_includedir}/wolfssl/openssl/engine.h -%{_includedir}/wolfssl/openssl/err.h -%{_includedir}/wolfssl/openssl/evp.h -%{_includedir}/wolfssl/openssl/hmac.h -%{_includedir}/wolfssl/openssl/lhash.h -%{_includedir}/wolfssl/openssl/md4.h -%{_includedir}/wolfssl/openssl/md5.h -%{_includedir}/wolfssl/openssl/ocsp.h -%{_includedir}/wolfssl/openssl/opensslconf.h -%{_includedir}/wolfssl/openssl/opensslv.h -%{_includedir}/wolfssl/openssl/ossl_typ.h -%{_includedir}/wolfssl/openssl/pem.h -%{_includedir}/wolfssl/openssl/pkcs12.h -%{_includedir}/wolfssl/openssl/rand.h -%{_includedir}/wolfssl/openssl/ripemd.h -%{_includedir}/wolfssl/openssl/rsa.h -%{_includedir}/wolfssl/openssl/sha.h -%{_includedir}/wolfssl/openssl/ssl.h -%{_includedir}/wolfssl/openssl/stack.h -%{_includedir}/wolfssl/openssl/ui.h -%{_includedir}/wolfssl/openssl/x509.h -%{_includedir}/wolfssl/openssl/x509v3.h -%{_includedir}/wolfssl/options.h -%{_includedir}/wolfssl/sniffer.h -%{_includedir}/wolfssl/sniffer_error.h -%{_includedir}/wolfssl/ssl.h -%{_includedir}/wolfssl/test.h -%{_includedir}/wolfssl/version.h +%{_includedir}/wolfssl/wolfcrypt/wc_encrypt.h +%{_includedir}/wolfssl/wolfcrypt/wc_port.h +%{_includedir}/wolfssl/wolfcrypt/wolfevent.h +%{_includedir}/wolfssl/wolfcrypt/wolfmath.h +%{_includedir}/wolfssl/wolfio.h %{_libdir}/pkgconfig/wolfssl.pc %changelog +* Thu Apr 16 2020 John Safranek +- Add some missing headers. +- Sort the file list. +* Thu Dec 19 2019 Jacob Barthelmeh +- Add wolfssl/openssl/tls1.h, wolfssl/openssl/x509_vfy.h +* Fri Mar 15 2019 John Safranek +- Updates for the v4 release. +* Thu Dec 20 2018 Jacob Barthelmeh +- Remove wolfssl/wolfcrypt/fips.h, add wolfssl/openssl/pkcs7.h +* Wed Jun 20 2018 Jacob Barthelmeh +- Remove NEWS, update ChangeLog to ChangeLog.md, remove wolfssl/wolfcrypt/fips.h, add wolfssl/wolfcrypt/cryptocb.h +* Thu May 31 2018 John Safranek +- Update the version number on the library SO file. +* Fri Mar 02 2018 Jacob Barthelmeh +- Added headder files fips.h, buffer.h, objects.h, rc4.h and example tls_bench.c +* 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 +- Added header for wolfssl/openssl/aes.h +* Fri Oct 28 2016 Jacob Barthelmeh +- Added header for pkcs12 +* Fri Sep 23 2016 John Safranek +- Add the dtls-sctp example sources +* Tue Jun 14 2016 Jacob Barthelmeh +- Change location for mem_track.h header +- Added header for cmac.h +* Thu Mar 17 2016 Jacob Barthelmeh +- Added header for mem_track.h +* Wed Dec 30 2015 Jacob Barthelmeh +- Added headers for curve25519 and ed25519 openssl compatibility +- Added headers for Idea, srp, signature, and wc_encrypt * Tue Mar 31 2015 John Safranek - Added recent new wolfcrypt headers for curve25519 * Fri Jan 09 2015 John Safranek - Update for cyassl->wolfssl name change -* Fri Oct 20 2012 Brian Aker +* Sat Oct 20 2012 Brian Aker - Initial package diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/benchmark.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/benchmark.test new file mode 100644 index 000000000..435f2fd6e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/benchmark.test @@ -0,0 +1,115 @@ +#!/bin/sh + +#benchmark.test + +if [ "$#" -lt 2 ]; then + echo "Usage: $0 [mode] [num] [clientargs] [serverargs]" >&2 + echo " [mode]: 1=Connection Rate (TPS), 2=Throughput Bytes" >&2 + echo " [num]: Mode 1=Connection Count, Mode 2=Bytes to TX/RX" >&2 + echo " [clientargs]: Passed to client (see \"./example/client/client -?\" for help)" >&2 + echo " Example: Use different cipher suite: \"-l DHE-RSA-AES256-SHA\"" >&2 + echo " [serverargs]: Passed to server (see \"./example/server/server -?\" for help)" >&2 + echo " Example: Disable client certificate check: \"-d\"" >&2 + echo "Note: If additional client or server args contains spaces wrap with double quotes" >&2 + exit 1 +fi + +# Use unique benchmark port so it won't conflict with any other tests +bench_port=11113 +no_pid=-1 +server_pid=$no_pid +counter=0 +client_result=-1 + +remove_ready_file() { + if test -e /tmp/wolfssl_server_ready; then + echo "removing existing server_ready file" + rm /tmp/wolfssl_server_ready + 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 + +# Start server in loop continuous mode (-L) with echo data (-e) enabled and non-blocking (-N) +echo "\nStarting example server for benchmark test" +remove_ready_file +# benchmark connections +if [ $1 -eq 1 ] +then + # start server in loop mode with port + ./examples/server/server -i -p $bench_port $4 & + server_pid=$! +fi + +# benchmark throughput +if [ $1 -eq 2 ] +then + # start server in loop mode, non-blocking, benchmark throughput with port + ./examples/server/server -i -N -B $2 -p $bench_port $4 & + server_pid=$! +fi + + +echo "Waiting for server_ready file..." +while [ ! -s /tmp/wolfssl_server_ready -a "$counter" -lt 20 ]; do + sleep 0.1 + counter=$((counter+ 1)) +done + +# benchmark connections +if [ $1 -eq 1 ] +then + echo "Starting example client to benchmark connection average time" + # start client to benchmark average time for each connection using port + ./examples/client/client -b $2 -p $bench_port $3 + client_result=$? +fi + +# benchmark throughput +if [ $1 -eq 2 ] +then + echo "Starting example client to benchmark throughput" + # start client in non-blocking mode, benchmark throughput using port + ./examples/client/client -N -B $2 -p $bench_port $3 + client_result=$? +fi + +if [ $client_result != 0 ] +then + echo "Client failed!" + do_cleanup + exit 1 +fi + +# End server +kill -6 $server_pid +server_result=$? +remove_ready_file + +if [ $server_result != 0 ] +then + echo "Server failed!" + exit 1 +fi + +echo "\nSuccess!\n" + +exit 0 diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/cleanup_testfiles.sh b/FreeRTOS-Plus/Source/WolfSSL/scripts/cleanup_testfiles.sh new file mode 100644 index 000000000..c7f3885fc --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/cleanup_testfiles.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# Script to cleanup test files +# This is helpful if running ./tests/unit.test as sudo, +# which creates these files with sudoer permissions and +# will cause issues on subsequent tests without sudo + +rm -f ./tests/bio_write_test.txt +rm -f ./test-write-dhparams.pem +rm -f ./certeccrsa.pem +rm -f ./certeccrsa.der +rm -f ./ecc-key.der +rm -f ./ecc-key.pem +rm -f ./ecc-public-key.der diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/crl-revoked.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/crl-revoked.test new file mode 100644 index 000000000..5588aa5b4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/crl-revoked.test @@ -0,0 +1,118 @@ +#!/bin/sh + +#crl.test + +revocation_code="-361" +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 +crl_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_crl_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_test() { + echo -e "\nStarting example server for crl test...\n" + + remove_ready_file + + # starts the server on crl_port, -R generates ready file to be used as a + # mutex lock, -c loads the revoked certificate. We capture the processid + # into the variable server_pid + ./examples/server/server -R $ready_file -p $crl_port \ + -c certs/server-revoked-cert.pem -k certs/server-revoked-key.pem & + 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 + crl_port=`cat $ready_file` + + # starts client on crl_port and captures the output from client + capture_out=$(./examples/client/client -p $crl_port 2>&1) + client_result=$? + + wait $server_pid + server_result=$? + + case "$capture_out" in + *$revocation_code*) + # only exit with zero on detection of the expected error code + echo "" + echo "Successful Revocation!!!!" + echo "" + exit_code=0 + echo "exiting with $exit_code" + exit $exit_code + ;; + *) + echo "" + echo "Certificate was not revoked saw this instead: $capture_out" + echo "" + echo "configure with --enable-crl and run this script again" + echo "" + esac +} + + +######### begin program ######### + +# run the test +run_test + +# If we get to this exit, exit_code will be a 1 signaling failure +echo "exiting with $exit_code certificate was not revoked" +exit $exit_code +########## end program ########## + diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/dertoc.pl b/FreeRTOS-Plus/Source/WolfSSL/scripts/dertoc.pl new file mode 100644 index 000000000..c02d7d3f3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/dertoc.pl @@ -0,0 +1,71 @@ +#!/usr/bin/perl + +# dertoc.pl +# version 1.0 +# Updated 07/31/2018 +# +# Copyright (C) 2006-2018 wolfSSL Inc. +# + +use strict; +use warnings; + +my $num_args = $#ARGV + 1; +if ($num_args != 3 ) { + print "usage: ./scripts/dertoc.pl ./certs/server-cert.der server_cert_der_2048 dertoc.c\n"; + exit; +} + +my $inFile = $ARGV[0]; +my $outName = $ARGV[1]; +my $outputFile = $ARGV[2]; + +# open our output file, "+>" creates and/or truncates +open OUT_FILE, "+>", $outputFile or die $!; + +print OUT_FILE "/* $outputFile */\n\n"; + +print OUT_FILE "static const unsigned char $outName\[] =\n"; +print OUT_FILE "{\n"; +file_to_hex($inFile); +print OUT_FILE "};\n"; +print OUT_FILE "static const int sizeof_$outName = sizeof($outName);\n\n"; + +# close file +close OUT_FILE or die $!; + + + +# print file as hex, comma-separated, as needed by C buffer +sub file_to_hex { + my $fileName = $_[0]; + + open my $fp, "<", $fileName or die $!; + binmode($fp); + + my $fileLen = -s $fileName; + my $byte; + + for (my $i = 0, my $j = 1; $i < $fileLen; $i++, $j++) + { + if ($j == 1) { + print OUT_FILE "\t"; + } + read($fp, $byte, 1) or die "Error reading $fileName"; + my $output = sprintf("0x%02X", ord($byte)); + print OUT_FILE $output; + + if ($i != ($fileLen - 1)) { + print OUT_FILE ", "; + } + + if ($j == 10) { + $j = 0; + print OUT_FILE "\n"; + } + } + + print OUT_FILE "\n"; + + close($fp); +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/external.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/external.test new file mode 100644 index 000000000..9557a0b43 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/external.test @@ -0,0 +1,34 @@ +#!/bin/sh + +# external.test + +server=www.wolfssl.com +ca=./certs/wolfssl-website-ca.pem + +[ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 + +# www.wolfssl.com isn't using RFC 8446 yet but the draft instead. +./examples/client/client -v 3 2>&1 | grep -- 'Bad SSL version' +if [ $? -ne 0 ]; then + + # cloudflare seems to change CAs quickly, disabled by default + if test -n "$WOLFSSL_EXTERNAL_TEST"; then + echo "WOLFSSL_EXTERNAL_TEST set, running test..." + else + echo "WOLFSSL_EXTERNAL_TEST NOT set, won't run" + exit 0 + fi + + # is our desired server there? + ./scripts/ping.test $server 2 + RESULT=$? + [ $RESULT -ne 0 ] && exit 0 + + # client test against the server + ./examples/client/client -X -C -h $server -p 443 -g -A $ca + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "\n\nClient connection failed" && exit 1 + +fi + +exit 0 diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/google.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/google.test new file mode 100644 index 000000000..7b58a8a29 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/google.test @@ -0,0 +1,26 @@ +#!/bin/sh + +# google.test + +server=www.google.com + +[ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 + +# TODO: [TLS13] Remove this when google supports final version of TLS 1.3 +./examples/client/client -v 3 2>&1 | grep -- 'Bad SSL version' +if [ $? -eq 0 ]; then + echo -e "\n\nClient doesn't support TLS v1.2" + exit 0 +fi + +# is our desired server there? +./scripts/ping.test $server 2 +RESULT=$? +[ $RESULT -ne 0 ] && exit 0 + +# client test against the server +./examples/client/client -X -C -h $server -p 443 -g -d +RESULT=$? +[ $RESULT -ne 0 ] && echo -e "\n\nClient connection failed" && exit 1 + +exit 0 diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/include.am b/FreeRTOS-Plus/Source/WolfSSL/scripts/include.am new file mode 100644 index 000000000..195dae78a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/include.am @@ -0,0 +1,98 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + + + +if BUILD_SNIFFTEST +dist_noinst_SCRIPTS+= scripts/sniffer-testsuite.test +endif + +if BUILD_EXAMPLE_SERVERS + +dist_noinst_SCRIPTS+= scripts/resume.test + +EXTRA_DIST+= scripts/benchmark.test +EXTRA_DIST+= scripts/memtest.sh + +# The CRL and OCSP tests use RSA certificates. +if BUILD_RSA + +if BUILD_CRL +# make revoked test rely on completion of resume test +dist_noinst_SCRIPTS+= scripts/crl-revoked.test +scripts/crl-revoked.log: scripts/resume.log +endif + +if BUILD_OCSP_STAPLING +dist_noinst_SCRIPTS+= scripts/ocsp-stapling.test +scripts/ocsp-stapling.log: tests/unit.log +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: tests/unit.log +scripts/ocsp-stapling-with-ca-as-responder.log: scripts/ocsp.log +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: tests/unit.log +scripts/ocsp-stapling2.log: scripts/ocsp.log +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: tests/unit.log +scripts/ocsp-stapling2.log: scripts/ocsp.log +endif + +endif + +endif + +if BUILD_PSK +dist_noinst_SCRIPTS+= scripts/psk.test +endif + +if BUILD_TRUST_PEER_CERT +dist_noinst_SCRIPTS+= scripts/trusted_peer.test +endif + +if BUILD_PKCALLBACKS +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 +if !BUILD_IPV6 +dist_noinst_SCRIPTS+= scripts/external.test +dist_noinst_SCRIPTS+= scripts/google.test +dist_noinst_SCRIPTS+= scripts/openssl.test + +if BUILD_OCSP +dist_noinst_SCRIPTS+= scripts/ocsp.test +endif + +endif +endif + +EXTRA_DIST += scripts/testsuite.pcap \ + scripts/sniffer-ipv6.pcap \ + scripts/ping.test + +# leave openssl.test as extra until non bash works +EXTRA_DIST += scripts/openssl.test + +EXTRA_DIST += scripts/dertoc.pl + +# for use with wolfssl-x.x.x-commercial-fips-stm32l4-v2 +EXTRA_DIST += scripts/stm32l4-v4_0_1_build.sh + +EXTRA_DIST += scripts/cleanup_testfiles.sh diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/memtest.sh b/FreeRTOS-Plus/Source/WolfSSL/scripts/memtest.sh new file mode 100644 index 000000000..41fa8edcc --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/memtest.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Run this script from the wolfSSL root as `./scripts/memtest.sh`. + +./autogen.sh +./configure --enable-debug --disable-shared --enable-memtest \ + --enable-opensslextra --enable-des3 --enable-dh --enable-ecc --enable-aesgcm --enable-aesccm --enable-hc128 \ + --enable-sniffer --enable-psk --enable-rabbit --enable-camellia --enable-sha512 --enable-crl --enable-ocsp --enable-savesession \ + --enable-savecert --enable-atomicuser --enable-pkcallbacks --enable-scep; + + #DTLS has issue with trapping client/server failure disconnect since its stateless. Need to find way to communicate failure through file system. + #--enable-dtls +make + +for i in {1..1000} +do + echo "Trying $i...\n" + + ./tests/unit.test > ./scripts/memtest.txt 2>&1 + + RESULT=$? + [ $RESULT -eq 139 ] && echo "Mem Seg Fault" && exit 1 +done +echo "Loop SUCCESS" diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp-stapling-with-ca-as-responder.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp-stapling-with-ca-as-responder.test new file mode 100644 index 000000000..4773ec104 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp-stapling-with-ca-as-responder.test @@ -0,0 +1,231 @@ +#!/bin/bash +# ocsp-stapling.test + + +./examples/client/client -v 3 2>&1 | grep -- 'Bad SSL version' +if [ $? -eq 0 ]; then + echo "TLS 1.2 or lower required" + echo "Skipped" + exit 0 +fi + + +WORKSPACE=`pwd` +CERT_DIR="./certs/ocsp" +resume_port=0 +ready_file=`pwd`/wolf_ocsp_s1_readyF$$ +ready_file2=`pwd`/wolf_ocsp_s1_readyF2$$ +printf '%s\n' "ready file: $ready_file" + +test_cnf="ocsp_s_w_ca_a_r.cnf" + +copy_originals() { + cd $CERT_DIR + cp intermediate1-ca-cert.pem bak-intermediate1-ca-cert.pem + cp intermediate2-ca-cert.pem bak-intermediate2-ca-cert.pem + cp intermediate3-ca-cert.pem bak-intermediate3-ca-cert.pem + cp ocsp-responder-cert.pem bak-ocsp-responder-cert.pem + cp root-ca-cert.pem bak-root-ca-cert.pem + cp server1-cert.pem bak-server1-cert.pem + cp server2-cert.pem bak-server2-cert.pem + cp server3-cert.pem bak-server3-cert.pem + cp server4-cert.pem bak-server4-cert.pem + cp server5-cert.pem bak-server5-cert.pem + cd $WORKSPACE +} + +restore_originals() { + cd $CERT_DIR + mv bak-intermediate1-ca-cert.pem intermediate1-ca-cert.pem + mv bak-intermediate2-ca-cert.pem intermediate2-ca-cert.pem + mv bak-intermediate3-ca-cert.pem intermediate3-ca-cert.pem + mv bak-ocsp-responder-cert.pem ocsp-responder-cert.pem + mv bak-root-ca-cert.pem root-ca-cert.pem + mv bak-server1-cert.pem server1-cert.pem + mv bak-server2-cert.pem server2-cert.pem + mv bak-server3-cert.pem server3-cert.pem + mv bak-server4-cert.pem server4-cert.pem + mv bak-server5-cert.pem server5-cert.pem +} + +wait_for_readyFile(){ + + counter=0 + + while [ ! -s $1 -a "$counter" -lt 20 ]; do + echo -e "waiting for ready file..." + sleep 0.1 + counter=$((counter+ 1)) + done + + if test -e $1; then + echo -e "found ready file, starting client..." + else + echo -e "NO ready file ending test..." + exit 1 + fi + +} + +remove_single_rF(){ + if test -e $1; then + printf '%s\n' "removing ready file: $1" + rm $1 + fi +} + +#create a configure file for cert generation with the port 0 solution +create_new_cnf() { + copy_originals + + printf '%s\n' "Random Port Selected: $RPORTSELECTED" + + printf '%s\n' "#" > $test_cnf + printf '%s\n' "# openssl configuration file for OCSP certificates" >> $test_cnf + printf '%s\n' "#" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# Extensions to add to a certificate request (intermediate1-ca)" >> $test_cnf + printf '%s\n' "[ v3_req1 ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:false" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "keyUsage = nonRepudiation, digitalSignature, keyEncipherment" >> $test_cnf + printf '%s\n' "authorityInfoAccess = OCSP;URI:http://127.0.0.1:$1" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# Extensions to add to a certificate request (intermediate2-ca)" >> $test_cnf + printf '%s\n' "[ v3_req2 ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:false" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "keyUsage = nonRepudiation, digitalSignature, keyEncipherment" >> $test_cnf + printf '%s\n' "authorityInfoAccess = OCSP;URI:http://127.0.0.1:22222" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# Extensions to add to a certificate request (intermediate3-ca)" >> $test_cnf + printf '%s\n' "[ v3_req3 ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:false" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "keyUsage = nonRepudiation, digitalSignature, keyEncipherment" >> $test_cnf + printf '%s\n' "authorityInfoAccess = OCSP;URI:http://127.0.0.1:22223" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# Extensions for a typical CA" >> $test_cnf + printf '%s\n' "[ v3_ca ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:true" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "keyUsage = keyCertSign, cRLSign" >> $test_cnf + printf '%s\n' "authorityInfoAccess = OCSP;URI:http://127.0.0.1:22220" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# OCSP extensions." >> $test_cnf + printf '%s\n' "[ v3_ocsp ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:false" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "extendedKeyUsage = OCSPSigning" >> $test_cnf + + mv $test_cnf $CERT_DIR/$test_cnf + cd $CERT_DIR + CURR_LOC=`pwd` + printf '%s\n' "echo now in $CURR_LOC" + ./renewcerts-for-test.sh $test_cnf + cd $WORKSPACE +} + +remove_ready_file() { + if test -e $ready_file; then + printf '%s\n' "removing ready file" + rm $ready_file + fi + if test -e $ready_file2; then + printf '%s\n' "removing ready file: $ready_file2" + rm $ready_file2 + fi +} + + +cleanup() +{ + for i in $(jobs -pr) + do + kill -s HUP "$i" + done + remove_ready_file + rm $CERT_DIR/$test_cnf + restore_originals +} +trap cleanup EXIT INT TERM HUP + +server=login.live.com +ca=certs/external/baltimore-cybertrust-root.pem + +[ ! -x ./examples/client/client ] && printf '\n\n%s\n' "Client doesn't exist" && exit 1 + +# create a port 0 port to use with openssl ocsp responder +./examples/server/server -R $ready_file -p $resume_port & +wait_for_readyFile $ready_file +if [ ! -f $ready_file ]; then + printf '%s\n' "Failed to create ready file: \"$ready_file\"" + exit 1 +else + RPORTSELECTED=`cat $ready_file` + printf '%s\n' "Random port selected: $RPORTSELECTED" + # Use client connection to shutdown the server cleanly + ./examples/client/client -p $RPORTSELECTED + create_new_cnf $RPORTSELECTED +fi +sleep 1 + +# is our desired server there? - login.live.com doesn't answers PING +#./scripts/ping.test $server 2 + +# client test against the server +# external test case was never running, disable for now but retain case in event +# we wish to re-activate in the future. +#./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 +# OLD: ./certs/ocsp/ocspd-intermediate1-ca-issued-certs-with-ca-as-responder.sh & +# NEW: openssl isn't being cleaned up, invoke directly in script for cleanup +# purposes! +openssl ocsp -port $RPORTSELECTED -nmin 1 \ + -index certs/ocsp/index-intermediate1-ca-issued-certs.txt \ + -rsigner certs/ocsp/intermediate1-ca-cert.pem \ + -rkey certs/ocsp/intermediate1-ca-key.pem \ + -CA certs/ocsp/intermediate1-ca-cert.pem \ + $@ \ + & + +sleep 1 +# "jobs" is not portable for posix. Must use bash interpreter! +[ $(jobs -r | wc -l) -ne 1 ] && printf '\n\n%s\n' "Setup ocsp responder failed, skipping" && exit 0 + +printf '%s\n\n' "------------- TEST CASE 1 SHOULD PASS ------------------------" +# client test against our own server - GOOD CERT +./examples/server/server -c certs/ocsp/server1-cert.pem \ + -k certs/ocsp/server1-key.pem -R $ready_file2 \ + -p $resume_port & +wait_for_readyFile $ready_file2 +CLI_PORT=`cat $ready_file2` +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 \ + -p $CLI_PORT +RESULT=$? +[ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection failed" && exit 1 +printf '%s\n\n' "Test PASSED!" + +printf '%s\n\n' "------------- TEST CASE 2 SHOULD REVOKE ----------------------" +# client test against our own server - REVOKED CERT +remove_single_rF $ready_file2 +./examples/server/server -c certs/ocsp/server2-cert.pem \ + -k certs/ocsp/server2-key.pem -R $ready_file2 \ + -p $resume_port & +wait_for_readyFile $ready_file2 +CLI_PORT=`cat $ready_file2` +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 \ + -p $CLI_PORT +RESULT=$? +[ $RESULT -ne 1 ] && printf '\n\n%s\n' "Client connection succeeded $RESULT" && exit 1 +printf '%s\n\n' "Test successfully REVOKED!" + +exit 0 diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp-stapling.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp-stapling.test new file mode 100644 index 000000000..778c7151e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp-stapling.test @@ -0,0 +1,314 @@ +#!/bin/bash + +# ocsp-stapling.test + + +./examples/client/client -v 3 2>&1 | grep -- 'Bad SSL version' +if [ $? -eq 0 ]; then + echo "TLS 1.2 or lower required" + echo "Skipped" + exit 0 +fi + + +# create a unique ready file ending in PID for the script instance ($$) to take +# advantage of port zero solution +WORKSPACE=`pwd` +CERT_DIR="./certs/ocsp" +resume_port=0 +ready_file=`pwd`/wolf_ocsp_s1_readyF$$ +ready_file2=`pwd`/wolf_ocsp_s1_readyF2$$ +printf '%s\n' "ready file: $ready_file" + +test_cnf="ocsp_s1.cnf" + +copy_originals() { + cd $CERT_DIR + cp intermediate1-ca-cert.pem bak-intermediate1-ca-cert.pem + cp intermediate2-ca-cert.pem bak-intermediate2-ca-cert.pem + cp intermediate3-ca-cert.pem bak-intermediate3-ca-cert.pem + cp ocsp-responder-cert.pem bak-ocsp-responder-cert.pem + cp root-ca-cert.pem bak-root-ca-cert.pem + cp server1-cert.pem bak-server1-cert.pem + cp server2-cert.pem bak-server2-cert.pem + cp server3-cert.pem bak-server3-cert.pem + cp server4-cert.pem bak-server4-cert.pem + cp server5-cert.pem bak-server5-cert.pem + cd $WORKSPACE +} + +restore_originals() { + cd $CERT_DIR + mv bak-intermediate1-ca-cert.pem intermediate1-ca-cert.pem + mv bak-intermediate2-ca-cert.pem intermediate2-ca-cert.pem + mv bak-intermediate3-ca-cert.pem intermediate3-ca-cert.pem + mv bak-ocsp-responder-cert.pem ocsp-responder-cert.pem + mv bak-root-ca-cert.pem root-ca-cert.pem + mv bak-server1-cert.pem server1-cert.pem + mv bak-server2-cert.pem server2-cert.pem + mv bak-server3-cert.pem server3-cert.pem + mv bak-server4-cert.pem server4-cert.pem + mv bak-server5-cert.pem server5-cert.pem +} + +wait_for_readyFile(){ + + counter=0 + + while [ ! -s $1 -a "$counter" -lt 20 ]; do + echo -e "waiting for ready file..." + sleep 0.1 + counter=$((counter+ 1)) + done + + if test -e $1; then + echo -e "found ready file, starting client..." + else + echo -e "NO ready file ending test..." + exit 1 + fi + +} + +remove_single_rF(){ + if test -e $1; then + printf '%s\n' "removing ready file: $1" + rm $1 + fi +} + +#create a configure file for cert generation with the port 0 solution +create_new_cnf() { + copy_originals + + printf '%s\n' "Random Port Selected: $RPORTSELECTED" + + printf '%s\n' "#" > $test_cnf + printf '%s\n' "# openssl configuration file for OCSP certificates" >> $test_cnf + printf '%s\n' "#" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# Extensions to add to a certificate request (intermediate1-ca)" >> $test_cnf + printf '%s\n' "[ v3_req1 ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:false" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "keyUsage = nonRepudiation, digitalSignature, keyEncipherment" >> $test_cnf + printf '%s\n' "authorityInfoAccess = OCSP;URI:http://127.0.0.1:$1" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# Extensions to add to a certificate request (intermediate2-ca)" >> $test_cnf + printf '%s\n' "[ v3_req2 ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:false" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "keyUsage = nonRepudiation, digitalSignature, keyEncipherment" >> $test_cnf + printf '%s\n' "authorityInfoAccess = OCSP;URI:http://127.0.0.1:22222" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# Extensions to add to a certificate request (intermediate3-ca)" >> $test_cnf + printf '%s\n' "[ v3_req3 ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:false" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "keyUsage = nonRepudiation, digitalSignature, keyEncipherment" >> $test_cnf + printf '%s\n' "authorityInfoAccess = OCSP;URI:http://127.0.0.1:22223" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# Extensions for a typical CA" >> $test_cnf + printf '%s\n' "[ v3_ca ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:true" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "keyUsage = keyCertSign, cRLSign" >> $test_cnf + printf '%s\n' "authorityInfoAccess = OCSP;URI:http://127.0.0.1:22220" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# OCSP extensions." >> $test_cnf + printf '%s\n' "[ v3_ocsp ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:false" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "extendedKeyUsage = OCSPSigning" >> $test_cnf + + mv $test_cnf $CERT_DIR/$test_cnf + cd $CERT_DIR + CURR_LOC=`pwd` + printf '%s\n' "echo now in $CURR_LOC" + ./renewcerts-for-test.sh $test_cnf + cd $WORKSPACE +} + +remove_ready_file() { + if test -e $ready_file; then + printf '%s\n' "removing ready file" + rm $ready_file + fi + if test -e $ready_file2; then + printf '%s\n' "removing ready file: $ready_file2" + rm $ready_file2 + fi +} + +cleanup() +{ + for i in $(jobs -pr) + do + kill -s HUP "$i" + done + remove_ready_file + rm $CERT_DIR/$test_cnf + restore_originals +} +trap cleanup EXIT INT TERM HUP + +server=login.live.com +ca=certs/external/baltimore-cybertrust-root.pem + +[ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 +./examples/client/client '-?' 2>&1 | grep -- 'Client not compiled in!' +if [ $? -eq 0 ]; then + exit 0 +fi + +# check if supported key size is large enough to handle 4096 bit RSA +size=`./examples/client/client '-?' | grep "Max RSA key"` +size=`echo ${size//[^0-9]/}` +if [ ! -z "$size" ]; then + printf 'check on max key size of %d ...' $size + if [ $size -lt 4096 ]; then + printf '%s\n' "4096 bit RSA keys not supported" + exit 0 + fi + printf 'OK\n' +fi + +# test interop fail case +ready_file=`pwd`/wolf_ocsp_readyF$$ +printf '%s\n' "ready file: $ready_file" +./examples/server/server -o -R $ready_file & +wolf_pid=$! +wait_for_readyFile $ready_file +if [ ! -f $ready_file ]; then + printf '%s\n' "Failed to create ready file: \"$ready_file\"" + exit 1 +else + # should fail if ocspstapling is also enabled + RPORTSELECTED=`cat $ready_file` + echo "hi" | openssl s_client -status -connect 127.0.0.1:${RPORTSELECTED} -cert ./certs/client-cert.pem -key ./certs/client-key.pem -CAfile ./certs/ocsp/root-ca-cert.pem + if [ $? -eq 0 ]; then + printf '%s\n' "Succeeded when should have failed" + remove_single_rF $ready_file + exit 1 + fi + remove_single_rF $ready_file + wait $wolf_pid + if [ $? -ne 1 ]; then + printf '%s\n' "wolfSSL server unexpected fail value" + exit 1 + fi +fi + + +# create a port 0 port to use with openssl ocsp responder +./examples/server/server -R $ready_file -p $resume_port & +wait_for_readyFile $ready_file +if [ ! -f $ready_file ]; then + printf '%s\n' "Failed to create ready file: \"$ready_file\"" + exit 1 +else + RPORTSELECTED=`cat $ready_file` + printf '%s\n' "Random port selected: $RPORTSELECTED" + # Use client connection to shutdown the server cleanly + ./examples/client/client -p $RPORTSELECTED + create_new_cnf $RPORTSELECTED +fi +sleep 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 -C -h $server -p 443 -A $ca -g -W 1 +RESULT=$? +[ $RESULT -ne 0 ] && echo -e "\n\nClient connection failed" && exit 1 + + +# Test with example server + +./examples/server/server '-?' 2>&1 | grep -- 'Server not compiled in!' +if [ $? -eq 0 ]; then + exit 0 +fi + +# setup ocsp responder +# OLD: ./certs/ocsp/ocspd-intermediate1-ca-issued-certs.sh & +# NEW: openssl isn't being cleaned up, invoke directly in script for cleanup +# purposes! +openssl ocsp -port $RPORTSELECTED -nmin 1 \ + -index certs/ocsp/index-intermediate1-ca-issued-certs.txt \ + -rsigner certs/ocsp/ocsp-responder-cert.pem \ + -rkey certs/ocsp/ocsp-responder-key.pem \ + -CA certs/ocsp/intermediate1-ca-cert.pem \ + "$@" & + +sleep 1 +# "jobs" is not portable for posix. Must use bash interpreter! +[ $(jobs -r | wc -l) -ne 1 ] && \ + printf '\n\n%s\n' "Setup ocsp responder failed, skipping" && exit 0 + +printf '%s\n\n' "------------- TEST CASE 1 SHOULD PASS ------------------------" +# client test against our own server - GOOD CERT +./examples/server/server -c certs/ocsp/server1-cert.pem -R $ready_file2 \ + -k certs/ocsp/server1-key.pem -p $resume_port & +wait_for_readyFile $ready_file2 +CLI_PORT=`cat $ready_file2` +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -p $CLI_PORT +RESULT=$? +[ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 2 failed" && exit 1 +printf '%s\n\n' "Test PASSED!" + +printf '%s\n\n' "------------- TEST CASE 2 SHOULD REVOKE ----------------------" +# client test against our own server - REVOKED CERT +remove_single_rF $ready_file2 +./examples/server/server -c certs/ocsp/server2-cert.pem -R $ready_file2 \ + -k certs/ocsp/server2-key.pem -p $resume_port & +wait_for_readyFile $ready_file2 +sleep 1 +CLI_PORT=`cat $ready_file2` +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -p $CLI_PORT +RESULT=$? +[ $RESULT -ne 1 ] && printf '\n\n%s\n' "Client connection succeeded $RESULT" \ + && exit 1 +printf '%s\n\n' "Test successfully REVOKED!" + + +./examples/client/client -v 4 2>&1 | grep -- 'Bad SSL version' +if [ $? -ne 0 ]; then + printf '%s\n\n' "------------- TEST CASE 3 SHOULD PASS --------------------" + # client test against our own server - GOOD CERT + remove_single_rF $ready_file2 + ./examples/server/server -c certs/ocsp/server1-cert.pem -R $ready_file2 \ + -k certs/ocsp/server1-key.pem -v 4 \ + -p $resume_port & + wait_for_readyFile $ready_file2 + CLI_PORT=`cat $ready_file2` + ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 -F 1 \ + -p $CLI_PORT + RESULT=$? + [ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 3 failed" && exit 1 + printf '%s\n\n' "Test PASSED!" + + printf '%s\n\n' "------------- TEST CASE 4 SHOULD REVOKE ------------------" + # client test against our own server - REVOKED CERT + remove_single_rF $ready_file2 + ./examples/server/server -c certs/ocsp/server2-cert.pem -R $ready_file2 \ + -k certs/ocsp/server2-key.pem -v 4 \ + -p $resume_port & + wait_for_readyFile $ready_file2 + CLI_PORT=`cat $ready_file2` + ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 -F 1 \ + -p $CLI_PORT + RESULT=$? + [ $RESULT -ne 1 ] && \ + printf '\n\n%s\n' "Client connection succeeded $RESULT" \ + && exit 1 + printf '%s\n\n' "Test successfully REVOKED!" +fi + +exit 0 diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp-stapling2.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp-stapling2.test new file mode 100644 index 000000000..f162365ab --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp-stapling2.test @@ -0,0 +1,395 @@ +#!/bin/bash +# ocsp-stapling.test + + +./examples/client/client -v 3 2>&1 | grep -- 'Bad SSL version' +if [ $? -eq 0 ]; then + echo "TLS 1.2 or lower required" + echo "Skipped" + exit 0 +fi + + +WORKSPACE=`pwd` +CERT_DIR="certs/ocsp" + +resume_port=0 +ready_file1=`pwd`/wolf_ocsp_s2_readyF1$$ +ready_file2=`pwd`/wolf_ocsp_s2_readyF2$$ +ready_file3=`pwd`/wolf_ocsp_s2_readyF3$$ +ready_file4=`pwd`/wolf_ocsp_s2_readyF4$$ +ready_file5=`pwd`/wolf_ocsp_s2_readyF5$$ +printf '%s\n' "ready file 1: $ready_file1" +printf '%s\n' "ready file 2: $ready_file2" +printf '%s\n' "ready file 3: $ready_file3" +printf '%s\n' "ready file 4: $ready_file4" +printf '%s\n' "ready file 5: $ready_file5" + +test_cnf="ocsp_s2.cnf" + +copy_originals() { + cd $CERT_DIR + cp intermediate1-ca-cert.pem bak-intermediate1-ca-cert.pem + cp intermediate2-ca-cert.pem bak-intermediate2-ca-cert.pem + cp intermediate3-ca-cert.pem bak-intermediate3-ca-cert.pem + cp ocsp-responder-cert.pem bak-ocsp-responder-cert.pem + cp root-ca-cert.pem bak-root-ca-cert.pem + cp server1-cert.pem bak-server1-cert.pem + cp server2-cert.pem bak-server2-cert.pem + cp server3-cert.pem bak-server3-cert.pem + cp server4-cert.pem bak-server4-cert.pem + cp server5-cert.pem bak-server5-cert.pem + cd $WORKSPACE +} + +restore_originals() { + cd $CERT_DIR + mv bak-intermediate1-ca-cert.pem intermediate1-ca-cert.pem + mv bak-intermediate2-ca-cert.pem intermediate2-ca-cert.pem + mv bak-intermediate3-ca-cert.pem intermediate3-ca-cert.pem + mv bak-ocsp-responder-cert.pem ocsp-responder-cert.pem + mv bak-root-ca-cert.pem root-ca-cert.pem + mv bak-server1-cert.pem server1-cert.pem + mv bak-server2-cert.pem server2-cert.pem + mv bak-server3-cert.pem server3-cert.pem + mv bak-server4-cert.pem server4-cert.pem + mv bak-server5-cert.pem server5-cert.pem +} + +wait_for_readyFile(){ + + counter=0 + + while [ ! -s $1 -a "$counter" -lt 20 ]; do + echo -e "waiting for ready file..." + sleep 0.1 + counter=$((counter+ 1)) + done + + if test -e $1; then + echo -e "found ready file, starting client..." + else + echo -e "NO ready file ending test..." + exit 1 + fi + +} + +remove_single_rF(){ + if test -e $1; then + printf '%s\n' "removing ready file: $1" + rm $1 + fi +} + +#create a configure file for cert generation with the port 0 solution +create_new_cnf() { + copy_originals + + printf '%s\n' "Random Port Selected: $RPORTSELECTED" + + printf '%s\n' "#" > $test_cnf + printf '%s\n' "# openssl configuration file for OCSP certificates" >> $test_cnf + printf '%s\n' "#" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# Extensions to add to a certificate request (intermediate1-ca)" >> $test_cnf + printf '%s\n' "[ v3_req1 ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:false" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "keyUsage = nonRepudiation, digitalSignature, keyEncipherment" >> $test_cnf + printf '%s\n' "authorityInfoAccess = OCSP;URI:http://127.0.0.1:$1" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# Extensions to add to a certificate request (intermediate2-ca)" >> $test_cnf + printf '%s\n' "[ v3_req2 ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:false" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "keyUsage = nonRepudiation, digitalSignature, keyEncipherment" >> $test_cnf + printf '%s\n' "authorityInfoAccess = OCSP;URI:http://127.0.0.1:$2" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# Extensions to add to a certificate request (intermediate3-ca)" >> $test_cnf + printf '%s\n' "[ v3_req3 ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:false" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "keyUsage = nonRepudiation, digitalSignature, keyEncipherment" >> $test_cnf + printf '%s\n' "authorityInfoAccess = OCSP;URI:http://127.0.0.1:$3" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# Extensions for a typical CA" >> $test_cnf + printf '%s\n' "[ v3_ca ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:true" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "keyUsage = keyCertSign, cRLSign" >> $test_cnf + printf '%s\n' "authorityInfoAccess = OCSP;URI:http://127.0.0.1:$4" >> $test_cnf + printf '%s\n' "" >> $test_cnf + printf '%s\n' "# OCSP extensions." >> $test_cnf + printf '%s\n' "[ v3_ocsp ]" >> $test_cnf + printf '%s\n' "basicConstraints = CA:false" >> $test_cnf + printf '%s\n' "subjectKeyIdentifier = hash" >> $test_cnf + printf '%s\n' "authorityKeyIdentifier = keyid:always,issuer:always" >> $test_cnf + printf '%s\n' "extendedKeyUsage = OCSPSigning" >> $test_cnf + + mv $test_cnf $CERT_DIR/$test_cnf + cd $CERT_DIR + CURR_LOC=`pwd` + printf '%s\n' "echo now in $CURR_LOC" + ./renewcerts-for-test.sh $test_cnf + cd $WORKSPACE +} + +remove_ready_file(){ + if test -e $ready_file1; then + printf '%s\n' "removing ready file: $ready_file1" + rm $ready_file1 + fi + if test -e $ready_file2; then + printf '%s\n' "removing ready file: $ready_file2" + rm $ready_file2 + fi + if test -e $ready_file3; then + printf '%s\n' "removing ready file: $ready_file3" + rm $ready_file3 + fi + if test -e $ready_file4; then + printf '%s\n' "removing ready file: $ready_file4" + rm $ready_file4 + fi + if test -e $ready_file5; then + printf '%s\n' "removing ready file: $ready_file5" + rm $ready_file5 + fi +} + +cleanup() +{ + for i in $(jobs -pr) + do + kill -s HUP "$i" + done + remove_ready_file + rm $CERT_DIR/$test_cnf + restore_originals +} +trap cleanup EXIT INT TERM HUP + +[ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 + +# check if supported key size is large enough to handle 4096 bit RSA +size=`./examples/client/client '-?' | grep "Max RSA key"` +size=`echo ${size//[^0-9]/}` +if [ ! -z "$size" ]; then + printf 'check on max key size of %d ...' $size + if [ $size -lt 4096 ]; then + printf '%s\n' "4096 bit RSA keys not supported" + exit 0 + fi + printf 'OK\n' +fi + +#get four unique ports +# 1: +./examples/server/server -R $ready_file1 -p $resume_port & +wait_for_readyFile $ready_file1 +if [ ! -f $ready_file1 ]; then + printf '%s\n' "Failed to create ready file1: \"$ready_file1\"" + exit 1 +fi +# 2: +./examples/server/server -R $ready_file2 -p $resume_port & +wait_for_readyFile $ready_file2 +if [ ! -f $ready_file2 ]; then + printf '%s\n' "Failed to create ready file2: \"$ready_file2\"" + exit 1 +fi +# 3: +./examples/server/server -R $ready_file3 -p $resume_port & +wait_for_readyFile $ready_file3 +if [ ! -f $ready_file3 ]; then + printf '%s\n' "Failed to create ready file3: \"$ready_file3\"" + exit 1 +fi +# 4: +./examples/server/server -R $ready_file4 -p $resume_port & +wait_for_readyFile $ready_file4 +if [ ! -f $ready_file4 ]; then + printf '%s\n' "Failed to create ready file4: \"$ready_file4\"" + exit 1 +else + RPORTSELECTED1=`cat $ready_file1` + RPORTSELECTED2=`cat $ready_file2` + RPORTSELECTED3=`cat $ready_file3` + RPORTSELECTED4=`cat $ready_file4` + printf '%s\n' "------------- PORTS ---------------" + printf '%s' "Random ports selected: $RPORTSELECTED1 $RPORTSELECTED2" + printf '%s\n' " $RPORTSELECTED3 $RPORTSELECTED4" + printf '%s\n' "-----------------------------------" + # Use client connections to cleanly shutdown the servers + ./examples/client/client -p $RPORTSELECTED1 + ./examples/client/client -p $RPORTSELECTED2 + ./examples/client/client -p $RPORTSELECTED3 + ./examples/client/client -p $RPORTSELECTED4 + create_new_cnf $RPORTSELECTED1 $RPORTSELECTED2 $RPORTSELECTED3 \ + $RPORTSELECTED4 +fi +sleep 1 + +# setup ocsp responders +# OLD: ./certs/ocsp/ocspd-root-ca-and-intermediate-cas.sh & +# NEW: openssl isn't being cleaned up, invoke directly in script for cleanup +# purposes! +openssl ocsp -port $RPORTSELECTED1 -nmin 1 \ + -index certs/ocsp/index-ca-and-intermediate-cas.txt \ + -rsigner certs/ocsp/ocsp-responder-cert.pem \ + -rkey certs/ocsp/ocsp-responder-key.pem \ + -CA certs/ocsp/root-ca-cert.pem \ + $@ \ + & + +# OLD: ./certs/ocsp/ocspd-intermediate2-ca-issued-certs.sh & +# NEW: openssl isn't being cleaned up, invoke directly in script for cleanup +# purposes! +openssl ocsp -port $RPORTSELECTED2 -nmin 1 \ + -index certs/ocsp/index-intermediate2-ca-issued-certs.txt \ + -rsigner certs/ocsp/ocsp-responder-cert.pem \ + -rkey certs/ocsp/ocsp-responder-key.pem \ + -CA certs/ocsp/intermediate2-ca-cert.pem \ + $@ \ + & + +# OLD: ./certs/ocsp/ocspd-intermediate3-ca-issued-certs.sh & +# NEW: openssl isn't being cleaned up, invoke directly in script for cleanup +# purposes! +openssl ocsp -port $RPORTSELECTED3 -nmin 1 \ + -index certs/ocsp/index-intermediate3-ca-issued-certs.txt \ + -rsigner certs/ocsp/ocsp-responder-cert.pem \ + -rkey certs/ocsp/ocsp-responder-key.pem \ + -CA certs/ocsp/intermediate3-ca-cert.pem \ + $@ \ + & + +sleep 1 +# "jobs" is not portable for posix. Must use bash interpreter! +[ $(jobs -r | wc -l) -ne 3 ] && printf '\n\n%s\n' "Setup ocsp responder failed, skipping" && exit 0 + +printf '\n\n%s\n\n' "All OCSP responders started successfully!" +printf '%s\n\n' "------------- TEST CASE 1 SHOULD PASS ------------------------" +# client test against our own server - GOOD CERTS +./examples/server/server -c certs/ocsp/server3-cert.pem \ + -k certs/ocsp/server3-key.pem -R $ready_file5 \ + -p $resume_port & +wait_for_readyFile $ready_file5 +CLI_PORT=`cat $ready_file5` +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 2 -v 3 \ + -p $CLI_PORT +RESULT=$? +[ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 1 failed" && exit 1 +printf '%s\n\n' "Test PASSED!" + +printf '%s\n\n' "TEST CASE 2 DISABLED PENDING REVIEW" +#printf '%s\n\n' "------------- TEST CASE 2 SHOULD PASS ------------------------" +#remove_single_rF $ready_file5 +#./examples/server/server -c certs/ocsp/server3-cert.pem \ +# -k certs/ocsp/server3-key.pem -R $ready_file5 \ +# -p $resume_port & +#wait_for_readyFile $ready_file5 +#CLI_PORT=`cat $ready_file5` +#./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 3 -v 3 \ +# -p $CLI_PORT +#RESULT=$? +#[ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 2 failed" && exit 1 +#printf '%s\n\n' "Test PASSED!" + +printf '%s\n\n' "------------- TEST CASE 3 SHOULD REVOKE ----------------------" +# client test against our own server - REVOKED SERVER CERT +remove_single_rF $ready_file5 +./examples/server/server -c certs/ocsp/server4-cert.pem \ + -k certs/ocsp/server4-key.pem -R $ready_file5 \ + -p $resume_port & +wait_for_readyFile $ready_file5 +CLI_PORT=`cat $ready_file5` +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 2 -v 3 \ + -p $CLI_PORT +RESULT=$? +[ $RESULT -ne 1 ] && printf '\n\n%s\n' "Client connection succeeded $RESULT" && exit 1 +printf '%s\n\n' "Test successfully REVOKED!" + +printf '%s\n\n' "------------- TEST CASE 4 SHOULD REVOKE ----------------------" +remove_single_rF $ready_file5 +./examples/server/server -c certs/ocsp/server4-cert.pem \ + -k certs/ocsp/server4-key.pem -R $ready_file5 \ + -p $resume_port & +sleep 1 +CLI_PORT=`cat $ready_file5` +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 3 -v 3 \ + -p $CLI_PORT +RESULT=$? +[ $RESULT -ne 1 ] && printf '\n\n%s\n' "Client connection succeeded $RESULT" && exit 1 +printf '%s\n\n' "Test successfully REVOKED!" + +printf '%s\n\n' "------------- TEST CASE 5 SHOULD PASS ------------------------" +# client test against our own server - REVOKED INTERMEDIATE CERT +remove_single_rF $ready_file5 +./examples/server/server -c certs/ocsp/server5-cert.pem \ + -k certs/ocsp/server5-key.pem -R $ready_file5 \ + -p $resume_port & +wait_for_readyFile $ready_file5 +CLI_PORT=`cat $ready_file5` +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 2 -v 3 \ + -p $CLI_PORT +RESULT=$? +[ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection 3 failed $RESULT" && exit 1 +printf '%s\n\n' "Test PASSED!" + +printf '%s\n\n' "------------- TEST CASE 6 SHOULD REVOKE ----------------------" +remove_single_rF $ready_file5 +./examples/server/server -c certs/ocsp/server5-cert.pem \ + -k certs/ocsp/server5-key.pem -R $ready_file5 \ + -p $resume_port & +wait_for_readyFile $ready_file5 +CLI_PORT=`cat $ready_file5` +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 3 -v 3 \ + -p $CLI_PORT +RESULT=$? +[ $RESULT -ne 1 ] && printf '\n\n%s\n' "Client connection succeeded $RESULT" && exit 1 +printf '%s\n\n' "Test successfully REVOKED!" +printf '%s\n\n' "------------- TEST CASE 7 LOAD CERT IN SSL -------------------" +remove_single_rF $ready_file5 +./examples/server/server -c certs/ocsp/server1-cert.pem \ + -k certs/ocsp/server1-key.pem -R $ready_file5 \ + -p $resume_port -H loadSSL & +wolf_pid=$! +wait_for_readyFile $ready_file5 +CLI_PORT=`cat $ready_file5` +echo "test connection" | openssl s_client -status -connect 127.0.0.1:$CLI_PORT -cert ./certs/client-cert.pem -key ./certs/client-key.pem -CAfile ./certs/ocsp/root-ca-cert.pem +RESULT=$? +[ $RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection failed $RESULT" && exit 1 +wait $wolf_pid +if [ $? -ne 0 ]; then + printf '%s\n' "Unexpected server result" + exit 1 +fi +printf '%s\n\n' "Test successful" +printf '%s\n\n' "------------- TEST CASE 8 SHOULD REVOKE ----------------------" +remove_single_rF $ready_file5 +./examples/server/server -c certs/ocsp/server4-cert.pem \ + -k certs/ocsp/server4-key.pem -R $ready_file5 \ + -p $resume_port -H loadSSL & +wolf_pid=$! +sleep 1 +CLI_PORT=`cat $ready_file5` +./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 3 -v 3 \ + -p $CLI_PORT +RESULT=$? +[ $RESULT -ne 1 ] && printf '\n\n%s\n' "Client connection succeeded $RESULT" && exit 1 +wait $wolf_pid +if [ $? -ne 1 ]; then + printf '%s\n' "Unexpected server result" + exit 1 +fi +printf '%s\n\n' "Test successfully REVOKED!" + +printf '%s\n\n' "------------------- TESTS COMPLETE ---------------------------" + +exit 0 diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp.test new file mode 100644 index 000000000..543705617 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/ocsp.test @@ -0,0 +1,92 @@ +#!/bin/sh + +# ocsp.test + +server=www.globalsign.com +ca=certs/external/ca-globalsign-root.pem + +[ ! -x ./examples/client/client ] && printf '\n\n%s\n' "Client doesn't exist" \ + && exit 1 + +./examples/client/client -v 3 2>&1 | grep -- 'Bad SSL version' +if [ $? -eq 0 ]; then + echo "TLS 1.2 or lower required" + echo "Skipped" + exit 0 +fi + +GL_UNREACHABLE=0 +# Global Sign now requires server name indication extension to work, check +# enabled prior to testing +OUTPUT=$(eval "./examples/client/client -S check") +if [ "$OUTPUT" = "SNI is: ON" ]; then + printf '\n\n%s\n\n' "SNI is on, proceed with globalsign test" + + # is our desired server there? + ./scripts/ping.test $server 2 + RESULT=$? + if [ $RESULT -ne 0 ]; then + GL_UNREACHABLE=1 + fi + + if [ $RESULT -eq 0 ]; then + # client test against the server + ./examples/client/client -X -C -h $server -p 443 -A $ca -g -o -N -v d -S $server + GL_RESULT=$? + [ $GL_RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection failed" + else + GL_RESULT=1 + fi +else + printf '\n\n%s\n\n' "SNI disabled, skipping globalsign test" + GL_RESULT=0 +fi + +server=www.google.com +ca=certs/external/ca-google-root.pem + +# is our desired server there? +./scripts/ping.test $server 2 +RESULT=$? +if [ $RESULT -eq 0 ]; then + # client test against the server + ./examples/client/client -X -C -h $server -p 443 -A $ca -g -o -N + GR_RESULT=$? + [ $GR_RESULT -ne 0 ] && printf '\n\n%s\n' "Client connection failed" +else + GR_RESULT=1 +fi + +if test -n "$WOLFSSL_OCSP_TEST"; then + # check that both passed + if [ $GL_RESULT -eq 0 ] && [ $GR_RESULT -eq 0 ]; then + printf '\n\n%s\n' "Both OCSP connection to globalsign and google passed" + printf '%s\n' "Test Passed!" + exit 0 + elif [ $GL_UNREACHABLE -eq 1 ] && [ $GR_RESULT -eq 0 ]; then + printf '%s\n' "Global Sign is currently unreachable. Logging it but if" + printf '%s\n' "this continues to occur should be investigated" + exit 0 + else + # Unlike other environment variables the intent of WOLFSSL_OCSP_TEST + # is to indicate a requirement for both tests to pass. If variable is + # set and either tests fail then whole case fails. Do not set the + # variable if either case passing is to be considered a success. + printf '\n\n%s\n' "One of the OCSP connections to either globalsign or" + printf '%s\n' "google failed, however since WOLFSSL_OCSP_TEST is set" + printf '%s\n' "the test is considered to have failed" + printf '%s\n' "Test Failed!" + exit 1 + fi +else + # if environment variable is not set then just need one to pass + if [ $GL_RESULT -ne 0 ] && [ $GR_RESULT -ne 0 ]; then + printf '\n\n%s\n' "Both OCSP connection to globalsign and google failed" + printf '%s\n' "Test Failed!" + exit 1 + else + printf '\n\n%s\n' "WOLFSSL_OCSP_TEST NOT set, and 1 of the tests passed" + printf '%s\n' "Test Passed!" + exit 0 + fi +fi diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/openssl.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/openssl.test new file mode 100644 index 000000000..341beff6a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/openssl.test @@ -0,0 +1,327 @@ +#!/bin/sh + +#openssl.test + +# need a unique port since may run the same time as testsuite +generate_port() { + port=`LC_CTYPE=C tr -cd 0-9 /dev/null 2>&1 || { echo >&2 "Requires openssl command, but it's not installed. Ending."; exit 0; } + + +echo -e "\nTesting for _build directory as part of distcheck, different paths" +currentDir=`pwd` +if [ $currentDir = *"_build" ] +then + echo -e "_build directory detected, moving a directory back" + cd .. +fi + + +# get wolfssl ciphers +wolf_ciphers=`./examples/client/client -e` + +found_free_port=0 +while [ "$counter" -lt 20 ]; do + echo -e "\nTrying to start openssl server on port $openssl_port...\n" + + $OPENSSL s_server -accept $openssl_port -cert ./certs/server-cert.pem -key ./certs/server-key.pem -quiet -CAfile ./certs/client-ca.pem -www -dhparam ./certs/dh2048.pem -dcert ./certs/server-ecc.pem -dkey ./certs/ecc-key.pem -verify 10 -verify_return_error -psk 1a2b3c4d -cipher "ALL:eNULL" & + server_pid=$! + # wait to see if s_server successfully starts before continuing + sleep 0.1 + + if ps -p $server_pid > /dev/null + then + echo "s_server started successfully on port $openssl_port" + found_free_port=1 + break + else + #port already started, try a different port + counter=$((counter+ 1)) + generate_port + openssl_port=$port + fi +done + +if [ $found_free_port = 0 ] +then + echo -e "Couldn't find free port for server" + do_cleanup + exit 1 +fi + +# if ECDH-RSA is enabled then start up server for ECDH-RSA suites +case $wolf_ciphers in +*ECDH-RSA*) + generate_port + ecdh_port=$port + found_free_port=0 + counter=0 + while [ "$counter" -lt 20 ]; do + echo -e "\nTrying to start ECDH-RSA openssl server on port $ecdh_port...\n" + + $OPENSSL s_server -accept $ecdh_port -cert ./certs/server-ecc-rsa.pem -key ./certs/ecc-key.pem -quiet -CAfile ./certs/client-ca.pem -www -dhparam ./certs/dh2048.pem -verify 10 -verify_return_error -cipher "ALL:eNULL" & + ecdh_server_pid=$! + # wait to see if s_server successfully starts before continuing + sleep 0.1 + + if ps -p $ecdh_server_pid > /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 +while [ "$counter" -lt 20 ]; do + echo -e "waiting for openssl s_server ready..." + nc -z localhost $openssl_port + nc_result=$? + if [ $nc_result = 0 ] + then + echo -e "openssl s_server ready!" + server_ready=1 + break + fi + sleep 0.1 + counter=$((counter+ 1)) +done + + +if [ $server_ready = 0 ] +then + echo -e "Couldn't verify openssl server is running, timeout error" + do_cleanup + exit 1 +fi + +OIFS=$IFS # store old separator to reset +IFS=$'\:' # set delimiter +set -f # no globbing + +wolf_versions=`./examples/client/client -V` +wolf_versions="$wolf_versions:4" #:4 will test without -v flag + +wolf_temp_suites_total=0 +wolf_temp_suites_tested=0 + +for version in $wolf_versions; +do + echo -e "version = $version" + # get openssl ciphers depending on version + # -s flag for only supported ciphers + 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" + testing_summary="$testing_summary SSLv3\tNo\tN/A\tN/A\t (No OpenSSL Support for cipherstring)\n" + continue + fi + ;; + "1") + openssl_ciphers=`$OPENSSL ciphers -s "TLSv1"` + tlsv1_sup=$? + if [ $tlsv1_sup != 0 ] + then + echo -e "Not testing TLSv1. No OpenSSL support for 'TLSv1' modifier" + testing_summary="$testing_summary TLSv1\tNo\tN/A\tN/A\t (No OpenSSL Support for cipherstring)\n" + continue + fi + ;; + "2") + openssl_ciphers=`$OPENSSL ciphers -s "TLSv1.1"` + tlsv1_1_sup=$? + if [ $tlsv1_1_sup != 0 ] + then + echo -e "Not testing TLSv1.1. No OpenSSL support for 'TLSv1.1' modifier" + testing_summary="${testing_summary}TLSv1.1\tNo\tN/A\tN/A\t (No OpenSSL Support for cipherstring)\n" + continue + fi + ;; + "3") + openssl_ciphers=`$OPENSSL ciphers -s "TLSv1.2"` + tlsv1_2_sup=$? + if [ $tlsv1_2_sup != 0 ] + then + echo -e "Not testing TLSv1.2. No OpenSSL support for 'TLSv1.2' modifier" + testing_summary="$testing_summary TLSv1.2\tNo\tN/A\tN/A\t (No OpenSSL Support for cipherstring)\n" + continue + fi + ;; + "4") #test all suites + openssl_ciphers=`$OPENSSL ciphers -s "ALL"` + all_sup=$? + if [ $all_sup != 0 ] + then + echo -e "Not testing ALL. No OpenSSL support for ALL modifier" + testing_summary="$testing_summary ALL\tNo\tN/A\tN/A\t (No OpenSSL Support for cipherstring)\n" + continue + fi + ;; + esac + + for wolfSuite in $wolf_ciphers; do + echo -e "trying wolfSSL cipher suite $wolfSuite" + wolf_temp_suites_total=$((wolf_temp_suites_total + 1)) + matchSuite=0; + + case ":$openssl_ciphers:" in *":$wolfSuite:"*) # add extra : for edge cases + echo -e "Matched to OpenSSL suite support" + matchSuite=1;; + esac + + if [ $matchSuite = 0 ] + then + echo -e "Couldn't match suite, continuing..." + continue + fi + + # check for psk suite and turn on client psk if so + 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 $port -g -r -l $wolfSuite -v $version $psk $adh $caCert + else + # do all versions + ./examples/client/client -p $port -g -r -l $wolfSuite $psk $adh $caCert + fi + + client_result=$? + + if [ $client_result != 0 ] + then + echo -e "client failed! Suite = $wolfSuite version = $version" + do_cleanup + exit 1 + fi + wolf_temp_suites_tested=$((wolf_temp_suites_tested+1)) + + done + wolf_suites_tested=$((wolf_temp_suites_tested+wolf_suites_tested)) + wolf_suites_total=$((wolf_temp_suites_total+wolf_suites_total)) + echo -e "wolfSSL suites tested with version:$version $wolf_temp_suites_tested" + version_name + testing_summary="$testing_summary$versionName\tYes\t$wolf_temp_suites_total\t$wolf_temp_suites_tested\n" + wolf_temp_suites_total=0 + wolf_temp_suites_tested=0 +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" +echo -e "\nSuccess!\n\n\n\n" +echo -e "$testing_summary" +exit 0 diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/ping.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/ping.test new file mode 100644 index 000000000..f1049d48e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/ping.test @@ -0,0 +1,29 @@ +#!/bin/sh + +# ping.test + +# defaults +server=www.wolfssl.com +tries=2 + +# populate args +if [ "$#" -gt 1 ]; then + tries=$2 +fi +if [ "$#" -gt 0 ]; then + server=$1 +fi + +# determine os +OS="`uname`" +case $OS in + MINGW* | MSYS*) PINGSW=-n ;; + *) PINGSW=-c ;; +esac + +# is our desired server there? +ping $PINGSW $tries $server +RESULT=$? +[ $RESULT -ne 0 ] && echo -e "\n\nCouldn't find $server, skipping" && exit 1 + +exit 0 diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/pkcallbacks.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/pkcallbacks.test new file mode 100644 index 000000000..24c9228f5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/pkcallbacks.test @@ -0,0 +1,123 @@ +#!/bin/sh + +#pkcallbacks.test + +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 +pk_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_pk_ready$$ + +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 +} + +# 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_test() { + echo -e "\nStarting example server for pkcallbacks test...\n" + + remove_ready_file + + # starts the server on pk_port, -R generates ready file to be used as a + # mutex lock, -P does pkcallbacks. We capture the processid + # into the variable server_pid + ./examples/server/server -P -R $ready_file -p $pk_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 + pk_port=`cat $ready_file` + + # starts client on pk_port with pkcallbacks, captures the output from client + capture_out=$(./examples/client/client -P -p $pk_port 2>&1) + client_result=$? + + if [ $client_result != 0 ] + then + echo -e "client failed!" + do_cleanup + exit 1 + fi + + wait $server_pid + server_result=$? + + if [ $server_result != 0 ] + then + echo -e "server failed!" + exit 1 + fi + +} + + +######### begin program ######### + +# run the test +run_test + +# If we get to this, success +echo "Success!" +exit 0 +########## end program ########## + diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/psk.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/psk.test new file mode 100644 index 000000000..d11ac59b5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/psk.test @@ -0,0 +1,148 @@ +#!/bin/sh + +# psk.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 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..." + + # 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 +./examples/client/client '-?' 2>&1 | grep -- 'Client not compiled in!' +if [ $? -eq 0 ]; then + exit 0 +fi +./examples/server/server '-?' 2>&1 | grep -- 'Server not compiled in!' +if [ $? -eq 0 ]; then + exit 0 +fi + +# Usual psk server / psk client. This use case is tested in +# tests/unit.test and is used here for just checking if PSK is enabled +port=0 +./examples/server/server -s -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -s -p $port +RESULT=$? +remove_ready_file +# if fail here then is a settings issue so return 0 +if [ $RESULT -ne 0 ]; then + echo -e "\n\nPSK not enabled" + do_cleanup + exit 0 +fi +echo "" + +# client test against the server +############################### + +./examples/client/client -v 3 2>&1 | grep -- 'Bad SSL version' +if [ $? -ne 0 ]; then + # Usual server / client. This use case is tested in + # tests/unit.test and is used here for just checking if cipher suite + # is available (one case for example is with disable-asn) + port=0 + ./examples/server/server -R $ready_file -p $port -l DHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-DES-CBC3-SHA & + server_pid=$! + create_port + ./examples/client/client -p $port + RESULT=$? + remove_ready_file + # if fail here then is a settings issue so return 0 + if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with chosen non PSK suites" + do_cleanup + exit 0 + fi + echo "" + + # psk server with non psk client + port=0 + ./examples/server/server -j -R $ready_file -p $port & + server_pid=$! + create_port + ./examples/client/client -p $port + RESULT=$? + remove_ready_file + if [ $RESULT -ne 0 ]; then + echo -e "\n\nClient connection failed" + do_cleanup + exit 1 + fi + echo "" + + # check fail if no auth, psk server with non psk client + echo "Checking fail when not sending peer cert" + port=0 + ./examples/server/server -j -R $ready_file -p $port & + server_pid=$! + create_port + ./examples/client/client -x -p $port + RESULT=$? + remove_ready_file + if [ $RESULT -eq 0 ]; then + echo -e "\n\nClient connected when supposed to fail" + do_cleanup + exit 1 + fi +fi + +echo -e "\nALL Tests Passed" + +exit 0 + diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/resume.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/resume.test new file mode 100644 index 000000000..35d05e1f2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/resume.test @@ -0,0 +1,144 @@ +#!/bin/sh + +#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 +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_resume_ready$$ + +echo "ready file $ready_file" + +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 +} + +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=$! + + 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..." + do_cleanup + exit 1 + fi + + # get created port 0 ephemeral port + resume_port=`cat $ready_file` + + capture_out=$(./examples/client/client $1 -r -p $resume_port 2>&1) + client_result=$? + + if [ $client_result != 0 ] + then + echo -e "client failed!\ncapture_out=$capture_out\nclient_result=$client_result" + do_cleanup + exit 1 + fi + + wait $server_pid + server_result=$? + remove_ready_file + + if [ $server_result != 0 ] + then + echo -e "client failed!" + exit 1 + fi + + case "$capture_out" in + *$resume_string*) + echo "resumed session" ;; + *) + echo "did NOT resume session as expected" + exit 1 + ;; + esac +} + +trap do_trap INT TERM + +./examples/client/client '-?' 2>&1 | grep -- 'Client not compiled in!' +if [ $? -ne 0 ]; then + ./examples/server/server '-?' 2>&1 | grep -- 'Server not compiled in!' + if [ $? -ne 0 ]; then + RUN_TEST="Y" + fi +fi + +./examples/client/client '-?' 2>&1 | grep -- 'Resume session' +if [ $? -ne 0 ]; then + RUN_TEST="Y" +fi + +if [ "$RUN_TEST" = "Y" ]; then + do_test + + # 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 + *$ems_string*) + echo -e "\nRepeating resume test without extended master secret..." + do_test -n ;; + *) + ;; + esac +fi + +echo -e "\nSuccess!\n" + +exit 0 diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/sniffer-ipv6.pcap b/FreeRTOS-Plus/Source/WolfSSL/scripts/sniffer-ipv6.pcap new file mode 100644 index 0000000000000000000000000000000000000000..6d8ac43430d0b276ab03394048ddfcf47c0c8c79 GIT binary patch literal 9484 zcmd^FdpuOz+uw6>opCAmP$NQQ>=~CxMdDPB`;c2HArwYqq)?26D3?x3DJ4#bP?Qq7 zkXtySB6TVvx=0c##k&^r!|9@*_mA^_-u3ycnYH$wy}!@%eJ*P~dk;4c4|fHEAVy0S z=U~A1@L0nl>c|>Trn9@e`9ji4I>TAs!e}AMZLyNZVl{L%X{D(pNryxwQ_)qc{Ydh@ zZcJAaji#?krY=Mf9HN96IXIF`Xe4VA1tn8d$?A(pn|$2dok$doRhnufc|8Y)ubU^B zkr$Iua0!A(sED4AhnJ&+7fIgAjp6L=>cH5#kfcIJ$tooI?IYhxsFI61MFriYN!^4x zJF3GAL4)!`+1J6zNaIAXKniy{ig1B5?BE#jzmN&u3f>c5zXMJ{lRn6XJTs1?T7xm{ zb3xz8`!)nw#I6H|6B`t1V#CxD6#824t97LQAH3eUb_^7!?9y9oZRBL+;{LC z9y^LR6<5+^3NELw*K}|dU22KXgs&+BY+BCjZ{tGjiMZ}i5YV8$G62^QjA0+wmo#mC zX#g7y;un2}$OAi#=?U>52GnsPmcmplsN*!S#&krXjz7Yx19-4Oy(|G%78t`mu2=9c z>Lm*FikPgIFb;>T2iCX2;R27<9bNoN^pn+X>|BEcl}80J+k{VX-B^C}t}b^~f!h(_ z0Eja9DH-7bF3Qc0VZ-1tI1Cnp5D@Tza3lN(FCvDBA|i+oB7pFNVE6bTLR2VD0%QcWZ(Fo8xdN-|VaLDx(q$ zmP*FFSA5i&lP?tA_~PXk1JQxgt z4MAClCvQax^zEh4+l@mER+xahMUMq zbMR%-=}cFO06GgEA`rP((mlO>+?j5kE)-Ez7#_qC`FwqS$-Z>=&EDSbWJkIOWgaRy zE(RAynBUEFGhJuG574i$EGMN=GVm@Q;nO*0g-4l z!>_6lh#WK@FE2WSITMkCG4m&qi(x}>!5BUS4aRU|gE1K7dK_nq)rxo9Jo4-HSIA+U z%k;C}70RHO<7$%!WI8#tDbBk&Q=E2XgLb1B&jOPcM@O?rf|K^Sm6!jNSf`qsg`9G{)gMT(aoyp4 zX1{1U)+4(_3`4%m|E#Q9C(kYUHx;)q&(fvTKIdKNuPk-(%VslTkwtEc#|DW) zY41B+xP5~4{8yYx6zY-=8x*$Oonu#i>iP}G9ejF=QR?9!s&rhEZ-GGl5%1RZ3o5tp zlxS{D$;)xm)#ZB8#9639%C(-KdiGUm%X5c4x9Sf+c~EC^t`UpFAedyI2)(wI z(j zQ6FOir3_eQT{SgLvm>q-1l#$Xvv?K|v?Y`5PBJbw3Qk=mu zvFF6?;iYX#R$I;-e$sHm^;vz{p5KqOmQi_&OL12?BJ3`Q6x`C(matB>YeZr)2SH#rgdlu(_EGJ%j|Z0H&YTtwT;r#(PoDeXwF>W-tm_rg3kg; z>MTf72S=0C1oHk5CM#5PQnCWmf2os##Ps8Yb&Xi1BzR$Nh^}3Y#yo>}Mn3#Km()%^ zsoI5$Z^(R%+x$kMrzvNbCx-=rKVHfx==N+gJWjXddA44^Qo0H-Xh_Q!BY35@Gns-?jmTBPYOe26NcI?i~@$>F&2Hy1womkrn^kZwvAups>J9 zDnB4J#D_XhtbKWa9G2i1?BjAQoUR;|?BjA!{wW8Z7u*yyh&PpMu^Dq+$^Ij*C)S`6 zGsoil5tbp_h?*mIjibd;7lJwLBYcAT1OMgceEz5YsN@56R3RIBRrk-RU*Mod)fKq;mzC%x-es-+qU3ry(&cKBPlfs-gL?6S$b!FkK6bzEVa@eV zz^yuV&AB?zS;p;5r{F%jHr0V!If8%mx%e;f+tGqqyEgWWfbN0%r8>tAyYGZPS!^aw zOw#J>Nj6YxYpFf_M11!(<0EzaooSpXE1N`EDR_(Nl1B}u9|*k}u5(m_d-FnOBDw7?$4I z`F>kNsE(*Wj^jm!FgBvfgwa-+~d;PtG&&vxyDNd*m~OK>oT18i1s6RHN4CjHHg zu3@6PEqJ`-V#{S4_c~ukSq)=V!)=sR5hVDn-z2e8Qdmjow0;OOw{TGK z4Wj9#2YKiZ^DNjkCtCUs8dGgH{VkdFvMb2ZE&Mq#X$|@`_@OJ`?vTvkVSn9EyOl4P zpRC_$uQppwz3|ClYrVsk6$Xc}8w^f7YFIMhkr}zu^K)^uwDp#VJ`HZ&{&;3Mjf~B1 z;Vq_DGgSg!=iN?S;}NWD^2&Q*2^CQk`Vj6H?LiXHa^7&OF5*tBlSgvekW)*#-Sax> z`&fqUYg|;Ai`ap-w4*{dmc_0sYs-OhZfLdpthGg3sY}+B?(5L=j@))0-iC-xIQss*`f9dL}}INXa~qK4A`> zx<-_OTne92!alw>P2*Y4=<}6IzT9k;gCK9$PFRm&F71VD!^k=a9=^c_pXIPw#!;=n z9QLny8>2YgysdKZneb@d#;8on+r1!fW7zo-_ymwF%h@YqoB2+lLTKy9bGgA*_v;QZ zA0B}x4d5zef*!|vdZ$E@zP$zKF<@~)IL;tRfVo-WpK8DoPcycOS6FELe zp2w3EU#8FzC~n{%uNT$MnTT9$*MGJ1%*Xd3(Fe(way6L?*e{uxIe+;WxAN*Kxt$Ns zIo*q%C5VLHmgOyuZ&_5pc-7RF?i2JID^qF1p`gJ#*CQ@@8090^p5_~61Usx;chJ>A z>FjGUn`OfUr$O^i%LAp(Y{MvQEznB9yfoE$h))$-)lrji{t%%nuWg;0o;u|SPD8Fp zK~l@8LY7(0r6a|{*50sVohn~m^f1YO7jO0g9xrRsC1eNScB+lZfcKf%SoH+3an<*1 z95BJgKAYpHHee3>xQ&&jYh%?D<2F_sxA6e&wsvoyJ9lwZbZzU6RjT?>ll7U45dHb-n9ud-E&7coo}O32J)VLZoAC z_Or!Zju6C}8}6^nw|X7ae7>OFy8gV!lFMaw&5xvI@>cXOm|v`nxginbe)7cflZkAJ zLJ5}Cs!v_d_hzewJ;cW77#pqIHczbX!G#mOpW=m|=Bn|j2zh$Z=m%n#^IP%tH%c*! zm-=>JQgi=QSx_J{Cz(60lUSE~TuP*ByV;>i*SmXDXZ>lt!(q;gox+DnsD#3&d(q2` zb?if=_t_E>(`Z(odTR}N*q%$Zel*Doi+O?DpZ2EMK%90>>v4kVtoIU=DAMsHTW)L8ou_QbwjNW?7?qM@wI^;`5Fo^ zC;1x0oQAKBVG8ADk6}*swSf^|vlnEmt$AE^UZ$Gx#>~Rjur0z#E_AN$x(!>Z3T+OA zt6y}eyGiA<@~?RIdr_KJgjsHJk#+1MS~uS^ZAL5fvYoVW|U&t7^|P73y#S-I0S&kCgh} zt8_YiA#PLnf>_hwYs_~?u|xsZxA=O|f2m>l`_e|+)Ph4#a)K!3=AHMiENY$O(I1-r zVZTpViBWu7d6$XF8AJOFr{T;V%leQH`D^^!jU-PepmUUcA8W4Wxq~kf7dDklF2&Rl zCh(O4#<0O$#tC#_fidhOHitS`{@mtcI%JRV1$9_I+2%sP=4esIZx)&1qRX3C7%>)S z2D}CRwIpp04F5vSbrTJ8yv3od}d|s!hd#jFaN+*KFE0 zBIB&@+jL@Xr%c8ArPx+C05Oma{O8K|{AVJT+RU-qri-OHbFB6sVNLX@bpUIUPeBf+ z;Zvi}az;382YKYmH+@R)&!o38%&yGtm{^4+zE;Jirs8OnJFfz}?ah5RqqmwipAL;h zx0@|Bxr5U_$%=`b;8PpH7&hql3?QQp7{flE>jZ!9_hT{!0z0>x3IZ7=!2e#rJ)qCR zZ`k1deg4b)kHu9xypJg!e2m>6lzEf>A96gqn2G@>SJHjJzmpi=BrgViyPK1<6KT^< nlGErPh_DFfh%Ec=nNe|L APP_ROOT/$TARGET_FILE.c" + cp "$WOLF_ROOT/wolfcrypt/src/$TARGET_FILE".c "$APP_ROOT/" + done + + # uncomment to copy over the test app for testing purposes + #cp "$WOLF_ROOT/wolfcrypt/test/test.c" ./ + else + printf '%s\n' "Please update the MY_WOLF_RELEASE_VARIABLE to the name" + printf '%s\n' "of the release you received most recently. Currently" + printf '%s\n' "it is set to \"$MY_WOLF_RELEASE_NAME\"" + fi +} + +update_user_settings(){ + if [ -f user_settings.h ]; then + printf '%s\n' "Removing old user_settings.h" + rm user_settings.h + fi + + printf '%s\n' "Generating new user_settings.h..." + touch user_settings.h + + printf '%s\n' "#ifndef STM32L4_V_4_0_1_USER_SETTINGS_H" > user_settings.h + { + printf '%s\n' "#define STM32L4_V_4_0_1_USER_SETTINGS_H"; + printf '%s\n' ""; + printf '%s\n' "/* FIPS SETTINGS - BEGIN */"; + printf '%s\n' "#define HAVE_FIPS"; + printf '%s\n' "#define HAVE_FIPS_VERSION 2"; + printf '%s\n' "#define NO_THREAD_LS"; + printf '%s\n' "#define NO_STRICT_ECDSA_LEN"; + printf '%s\n' "#define HAVE_ECC"; + printf '%s\n' "#define HAVE_HKDF"; + printf '%s\n' "#define HAVE_AESCCM"; + printf '%s\n' "#define HAVE_AES_ECB"; + printf '%s\n' "#define HAVE_ECC_CDH"; + printf '%s\n' "#define HAVE_FFDHE_Q"; + printf '%s\n' "#define HAVE_FFDHE_2048"; # NEW + printf '%s\n' "#define HAVE_HASHDRBG"; + printf '%s\n' "#define WOLFSSL_SHA3"; + printf '%s\n' "#define WOLFSSL_CMAC"; + printf '%s\n' "#define WOLFSSL_SHA224"; + printf '%s\n' "#define WOLFSSL_SHA384"; + printf '%s\n' "#define WOLFSSL_SHA512"; + printf '%s\n' "#define WOLFSSL_KEY_GEN"; + printf '%s\n' "#define WOLFSSL_PUBLIC_MP"; + printf '%s\n' "#define WOLFSSL_AES_DIRECT"; + printf '%s\n' "#define WOLFSSL_AES_COUNTER"; + printf '%s\n' "#define WOLFSSL_BASE64_ENCODE"; + printf '%s\n' "#define WOLFSSL_VALIDATE_FFC_IMPORT"; + printf '%s\n' "#define WOLFSSL_VALIDATE_ECC_IMPORT"; + printf '%s\n' "#define WC_RSA_PSS"; + printf '%s\n' "#define WC_RSA_NO_PADDING"; +# NEW printf '%s\n' "#define WC_RSA_BLINDING"; + printf '%s\n' "#define FP_MAX_BITS 8192"; + printf '%s\n' ""; + printf '%s\n' "/* For operational testing use only in validation effort */"; +# printf '%s\n' "/* #define HAVE_FORCE_FIPS_FAILURE */"; + printf '%s\n' "#define HAVE_FORCE_FIPS_FAILURE"; + printf '%s\n' "/* FIPS SETTINGS - END */"; + printf '%s\n' ""; + printf '%s\n' "/* Debugging */"; + printf '%s\n' "/* #define WOLFSSL_DEBUG_MEMORY */"; + printf '%s\n' "/* #define WOLFSSL_TRACK_MEMORY */"; + printf '%s\n' "/* #define WOLFSSL_DEBUG_MEMORY_PRINT */"; + printf '%s\n' "/* Debugging */"; + printf '%s\n' ""; + printf '%s\n' "/* Environment settings */"; + printf '%s\n' "#define NO_FILESYSTEM"; + printf '%s\n' "#define USE_FAST_MATH"; + printf '%s\n' "#define NO_MAIN_DRIVER"; + printf '%s\n' "#define WOLFCRYPT_ONLY"; + printf '%s\n' "#define WC_RSA_BLINDING"; + printf '%s\n' "#define SINGLE_THREADED"; + printf '%s\n' "#define TFM_TIMING_RESISTANT"; + printf '%s\n' "#define ECC_TIMING_RESISTANT"; + printf '%s\n' "#define USE_CERT_BUFFERS_256"; + printf '%s\n' "#define USE_CERT_BUFFERS_2048"; + printf '%s\n' "#define WOLFSSL_STM32L4"; + printf '%s\n' "#define WOLFSSL_STM32_CUBEMX"; + printf '%s\n' "#define WOLFSSL_CUBEMX_USE_LL"; + printf '%s\n' "#define STM32_RNG"; + printf '%s\n' "#define NO_STM32_CRYPTO"; + printf '%s\n' "#define NO_STM32_HASH"; + printf '%s\n' "#define NO_OLD_RNGNAME"; + printf '%s\n' "/* Environment settings */"; + printf '%s\n' ""; + printf '%s\n' "/* Tuning options */"; + printf '%s\n' "#define ALT_ECC_SIZE"; + printf '%s\n' "#define NO_RC4"; + printf '%s\n' "#define NO_MD4"; + printf '%s\n' "#define NO_PSK"; + printf '%s\n' "#define NO_HC128"; + printf '%s\n' "#define NO_RABBIT"; + printf '%s\n' "#define GCM_SMALL"; + printf '%s\n' "#define TFM_ECC256"; + printf '%s\n' "#define ECC_SHAMIR"; + printf '%s\n' "#define HAVE_AESGCM"; + printf '%s\n' "#define NO_PWDBASED"; + printf '%s\n' "/* Tuning options */"; + printf '%s\n' ""; + printf '%s\n' "/* Non-FIPS related settings */"; + printf '%s\n' "#define HAVE_TLS_EXTENSIONS"; + printf '%s\n' "#define HAVE_EXTENDED_MASTER"; + printf '%s\n' "#define HAVE_SUPPORTED_CURVES"; + printf '%s\n' "/* Non-FIPS related settings */"; + printf '%s\n' ""; + printf '%s\n' "/* Agent harness settings */"; + printf '%s\n' "#define USE_NORMAL_PRINTF"; + printf '%s\n' "#define STM32L4R9I_DISCO"; + printf '%s\n' "#define USE_NORMAL_SCAN"; + printf '%s\n' "#define HAVE_FIPS"; + printf '%s\n' "#define HAVE_FIPS_VERSION 2"; + printf '%s\n' "#define VERIFY_GENERATED_PSS_SIGS"; + printf '%s\n' "/* Agent harness settings */"; + printf '%s\n' ""; + printf '%s\n' "#endif /* STM32L4_V_4_0_1_USER_SETTINGS_H */"; + printf '%s\n' ""; + } >> user_settings.h + + printf '%s\n' "new user_settings.h has been created" +} + +assumptions + +if [ -f wolfssl/ssl.h ]; then + if [ -f "$FIRMWARE_ROOT"/project.mk ]; then + printf '%s\n' "Found ../../../project.mk, wolfSSL properly placed in" + printf '%s\n' "application root directory" + else + printf '%s\n' "Failed to locate ../../../project.mk, wolfSSL in wrong" + printf '%s\n' "location or assumptions need updated." + fi +else + printf '%s\n' "Run this script from the wolfSSL root directory" + exit 1 +fi + +flatten_wolfcrypt_sources +# optional test application, remove if not testing +if [ -f "$APP_ROOT/test.c" ]; then + printf '%s\n' "Removing: $APP_ROOT/test.c" + rm "$APP_ROOT/test.c" +fi +printf '%s\n' "WOLF_ROOT/wolfcrypt/test/test.c --> APP_ROOT/test.c" +cp "$WOLF_ROOT/wolfcrypt/test/test.c" "$APP_ROOT/" +# optional test application section end + +# used during fips validation only, these will not be in final distribution +#./scripts/flatten-agent-sources.sh +#./scripts/flatten-op-test.sh +# used during fips validation only, these will not be in final distribution + +update_user_settings + +cd "$FIRMWARE_ROOT" +make clean +make -j 1 +cd "$APP_ROOT" +make install-target diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/testsuite.pcap b/FreeRTOS-Plus/Source/WolfSSL/scripts/testsuite.pcap new file mode 100644 index 0000000000000000000000000000000000000000..a39ad39163e491b079e34a54e95df88ef78e817d GIT binary patch literal 52480 zcmeFac{o`906?x}HCt?{)3#`kr$-uf1NM_u6ai`?L3bpWc?cIot3E@&5ha z#{a(-6L@@&77?B*_y@?b4IFBCc#0u%ig=2|czA($c=*V%Ixk@3aZfG-`S;7Wt*!l* z0DqQHp%0&cfCwL-l$^rxFemcQ2mt_LszaFer_oFSo7MRdJ-2Uwn_0dc&P2HXFtq`5 zKR5?+V8Za8W|6V|7spkb2=6=? z3vyt`xrC19{f>qJSse5JVHYJZTN^yFc<}HRetB7NAZWvdtmblRuy|4BD@G- zf*e?z&>i_(a4>-5^|y@%_?Hh65NO`n6GdZkPvVZz+XE5i4b_o9@RJrSv<*&G6T6bW zcp=1g>jrc7;Ux8-bR+9Zd~4NIOSMA_veCN^sWOe)m}eRs!joU0Nd910U%*^Nj*Vdv zeq4ME8QGW?yicFxu=ihuk85tdz4q7ov~qN1YGVj`jvC&6Dz zi%5t_VgFJjIR1Zr*jP1kN)qHu`ufNIQKO(F(Ld+v>f-MCzcSlnc*Tg*DW-Z(j~8SFkqkYwHC8SB-8sn`^&`EzO&(`A zHd%Vps7i~7B?pOdCgph5()XlzjGA$G*i*I0Slp;Aw^LRo`_e~RFV0qB%u!H0`DoCo1m130?;26Bsa46YeBrsGt+;xSD!#wBtv&oHK#)6ISZj z10um4$Uo;K3~mw$eh|dK8*4-7*}}uD@KxNh;zl2{$j8sGa)Q%u1gHETI(Hcy9G}?k|2zc z@p^Xei-k$ZLy4}hZQ2Tzrka;47sv^>XB#$+h)d@jk2w4#xS1x-<)z-SV`9e~vSbP4 zyv$19%L~kP3>~mA>-!n*enGzb;?d|K9+lsXohBnv74l+yc{7x3ukYx{ytXNdx>$cz zVv>>bGi}^N1136w_kicQSYyH!eos~ZpPDj5$9L6wkC@rJzPykd6#R)%_ezVZ?o{2S zBK?s!MbUf<>`cnKWR=^UvR`wPg|+chmK7L((u+dY^^0KPI||lfMa?th3`DF zORX<_zvcc~`0%Kyz?K1Oy1rp-Y|haDjk{&I!Z)t>BYN(NV9V%*Z5aqh2@DT8utSvJ z?Eo917vbg*MgJZmAvFLX&Iyo#l@p?Y*c}xN>^!o=m%#>>4B_P1{};!L5O8k8I2jO5 zg6w~CsQ!y1r%Qyl2sSX}z;0r*DH>aFFrv4&ecCJ(7jowU?i2{`gH5awkMIs2;cc*q z6@yLe>c%EUhF4`-7H4+GC>!T;`v0^V{JkqMh-^o;Eec8s9d{QS_tQ>J|NAyGaT$p} zH?#G>{6BTr|Dz49h2Vw2ZUPSi|`?7-93~!a*MNh8j>GIx{`8AZ$ zNGcLs#zvvS(CTSZDHh@q6W)ADF-W7iwKvs@nKT{Dc&Zm)Se`ZaDR=+$zk z(s7c@lgmpp&uD*38CLQ3^4sG)@0?a{)va+Kd-TF*!R=+ZB8I-)@}9ev$fJ~t;rk4Q z-|YAv*m!&Kr^(0FoZ6T04NbgH&H9aP1Sa4(l`HR+$2@Ps&Nkw1Xs|!?zp$bG|38Jn zhPHXl{SP;^FxvQ5vqA3YIU~P)3`|7JZkCGWV@*v$^!&cnueppPCJ9!l%7z!Z+v|0u zXtjMhwXOZj(w_Qt*(SD06)QVOdz;)1d-7tWQ1nIc+vTRbObL}4av%SLp{IW`n7$aO zr+%Yb?dGf$5G8mr{i)Yc`$gilZDlNHeeS!6hanW|nH72M#o}9i+by>MH{)Nd&RxJ!0iT1AV`DMJ zS8!HGb2c^!#k3JUFDmef;P#q0YBA*kizz-aEgtv?g(tLRv|FLa#QX{aPfYB5%?_>{ zdmZy9ji-gUOGU%yA?9~P4snCEgDrjYnhIbRw7 z+gmL@*^_x$E$frrvEjWkJ5&0Cla!x?+Z?X;7!t$rEnU z2bNX7ZWl>X@R{D%NE{(VTy-oZkww^=apr4wfynqd+OXxa@;wwT%R7Qs-|0Sin^?W5 zLuu|F_jqYK+Pz8hSB&7ud#+bjCbIWVe#q^W@l3A0_(o=NDLOagN9j8|8FJSy9#x%P z^+aRu*k)g@rT)-ZblN#pDLpN~Bspr$eV9QmpEWB*dJi{O2~yG~NHnQh=#u^$jnWMe zO~D`gl*CK| zugt7{Rys(0wCX_0tIR8Vj`7FswfO84oY&H+fA2-$j(t9=U-hkX_kFL8t9Y%zThuZk zpz^-;UT-zyExEU52%4PX1%1r_5Z1i3=}zZ*DIVpuF~ymMUJi zUsKwiMAzbzI;X(2fP19D-8mtSDMV$&_!hcZ3g`HcEM9X!@UaKm(jF;qgK8HqR#vy zY9t~aWK`V{PX3YqM!9;^&L3@uG*NUy3yz0hHJfj3 zx^IIaly@ULn%AUN7BKXHd`;>6Idk;@MV+>S7l)V=k6o$}V>aUplw#Cwo6>wHXk5o> zEtjH8W@JPr;-qcx{^uo5{M6EE8bq=mBKhb)mn;=ZAbAZ|EXk99M|d13!heenI2gb| zN67PUgld3>Te9vS=#pV+^d9%HG<3;$)=QS$B*-f}VY!Pju&X;zdF69D=W}zLpI^Q* zM$iS`~`!V|A2I?s!DWAnA*Jd+gbp?<5eNiIwYlTYU0+K^PI`XohLC zCac@^8%W6vz~FG_*Yha!;5PD9p#*u-gOdGu>%BR@OduT5{QuT{FuxQzPADCG+&Q0-Ng-4aW#4kA#hmQSy|%mif3%no zkIE1dCUKu4rXdM9LE9D7=c?IRSyHB9cPy25+5VY8|6xw8Q%G^HL!?fVprx?M*@EPB zfm9kysvdA~XFz?{790%V;LHF-N=GunNu-8+>Xgu#@4wwVlFuvK+z{&i@JubnXqBQN&fGGZdqJl(!mWuH*6*S+Qol5=;ZS$@CpFrg}#IbXb=Yv}d=Nh`yIP+x ze0<`xRMIDzl_{RD9}ebt#INj47gTLO^i^~r$!$@km;)Ki8%V{u@52V;y={FkbnuG5 zhj1RQqB+=Uqzk5X14yn2mfRSGvrX;4INsX;Cm+W74B@=F@Shxl|KfawaBSVsoQ)Z| zb$w0)@K#MF=_sv=a8EGy$n$VY{9{R z++i1m`GWHqL%N$6{P)BzJ{8(;HMl+5UcsHzd&O1acXrj&1Qv~eSXIv>F>`LOwFkd7 zAFpd=)>!2%uI?AzcTr%8r5Cvve`^~h`>XCx{yET^o@BZC%)4v~B9c@GZyQ>QVHpSN7<;Z#eu!k1aKZ$5t{v7l{1&oqxi#S2H5=hz-qH9Jb;7y zz-l;m3l92$)us*hftABYi^3qm{cn7ai+|rSPFJQ7x>Bia$3M91r?HEO%~~^CWWT4; z%YMT_&enY)$vQgc?weJ;d+eO2BE>R&K-2GlHlE~q4^si6ck}^zSlA-ZfY2WSy+50) zn|i8%gZtpC%*bxHzVQA2_o>o93m@L*Q>7D-6}dnN4g7aSW=6K* zKc6aXuE^#PPSnBwW~jW~XY|QNaLT zYxBi|i+1yZi%}f@hxfT84c@a{@H1pmOME*hV~|+Eaoe>vL-sqNUMI(|6BgE#uI@wQ zQCDouW7J;w7%b1Xgp$&5xyT+DqM>hJBe=Wk+JoYYfzM9dDp@QeO27KJp}b7V`^@4^ zqHb!zha-FnUw-Q_xRjRTz5YcwmeG4-r?KJfq3WHd^n1oFgEV$G*-uyRpnKZBbVXBH z|GlhSuhDtup;a{$H8tVi>2qecfZs+G+D8kH{|7*!{1R3`ujw}(NOi{@-hU|+n=QT_YjVcib7Z&Uou zOun48->v-RjoD*qMX3>|Oc%Gi(UtjJN*P|Rj;GhpG#Xoq|6Va2lH>Kebs=}6PQ%@*}qHeg>!R^;$Q&h-=5fBB(i@? zJqc*IC1S-X5teqb*cyxqq5WH;b=rD~l08d!8%;Zc#q6~kOB;!tUqrLLqN*1NaAGz$ zw~@MjQ}~See((MKbC{!NLl=(iDGd--lwnMKR%340`f{jJ^BXdY=D=WZXQTgTbcwKe zse!yMf)f4N149P07vcPXa31;nC#M5&Zv9c}O%9Ls-^HQm+Jb`t9CUH^uJ^zkK3xb5 z&mtEzxlXe861S>~zHc+rUddBe9|SUHODM(;Ul;1Q$`tQhM=#0I{5$O2SnfSjbYKKV~K%@@VY{9_*4oqr+B2)8q@{De6 z(6!SRjih!@{cTevjSLrUl7G-NQraBdJ3gPY!*DA3nwDEuXWZ%Kk0%Csa`^5~cgtMz z#oOazi%3~Rq?jhrgTW?#d2E%18b}qxq^<)F7~}eZU4QH_INf;^2Lm`}o88Lw#F3;# zp3TKCdfI&Ny8X(sKz5*+oRg?jmVcmK_4iWR3mRK%IT_w@n*!yhqpfb=J|hz4 z5DAA^w8Ta-EYu*Ghd`nYCh-y?;TE$62Lm`Ti8`OT7l#>4=j9Lje!Dx^Ynk@BCWBRC z;@$n~vBUNHuM^nDnjbdnTMds}UT-cDobE&b%r|6R-DBP(M3W z$;Mp%@>fPraevxr<8h-KW$HrxD$Iz~PB0kUYv$-QdN9~zREn+r2!Yfin3OO?YI0!< z4hC>wQb$Q1J<8_QzL$Kyx?xiAh&(3qYaNYlyMnw_V}b9ZK#^~1&YynoW;M9j$Y~s- z@8l^vvu4p`bV*=sIBhhy?IZ_5GgB&6cc>zUjj)T0aDGdq#__v-8|^xU=!cqU;qb} zRDC+VMsT^yvpDld@2)3ie2_|@p5N2;vRCKJODpgk#}c5R=!y2^mC!!S?Tk!0iosT3{;}Ft*ByJU+;U zNk{_@ZW6mqx8Ps^2PPpn`)t}~wA(f4**(Lsqe*=%ECZEsb*)14X{@uV56>r9vsF8_ zckWZWkH4GUejzLckQoVkv-PCX@)0ba`z6u(va{CRVWFs?!KFVWZoGe0aw@~TK{4>P z==LjhL|4RKpJq*@I>>!C$ehvfnQQ zIaWj$;+Q0wVxM~k&0Hb~@d z+%M%bB3R4sA^AxtPR2pNEk$GQ@SJqqe11LYn(!M%L8j{ID`Bn3^iqXL-4sI)273)P zfn-8})P0zg9z@D8YYPqra9~od^gO%0)E-)8I62*sUp-G#m$v(~?!?TYpG~G7`Zn|Y z7ObB4OjjmaQ)B2(j_f-TM7SWo8couquRvRKBaSs<0+F(WNIjB34+fi5$k-|yF_21! zNd*E9?ln`5^N|C^!2k|yx&{AwAYP+R)1M*TEp-`B${>z%rCB9p;r5-0n7{>f@e1py zmy$$%QTnfa6RW1*O9mqn5fBL?UbMtUGHk>k8RQkFYM4X`M1lk7Mi#}v01ixoLABb0 z(KWwn()y+RH%@=O&wD4h%wA>wnvG~r8D#%b88OxT^zyluPe-ZT(Ubyw9sj9;tY_VY zy}#}tgCPTh!Tk^?6O0}Vw!%L_Qb9l}1t!G}k&46l!XJu*0UVgrVV3QrN+BE}0ypuy z)0XkYsmes!FqezdM5$-W_7#6On8J$-x%arl(k1fEV_DJ(JNlfZ_#1S?yHlTAh{heX zi$q3yFforGS5d%GQ_MY}uSms56A@1p6xEwgi})|kWX?j2D?>J&uk z=2i4yHY)6|1d?h6Qi(7r2fzViTtEKl<^*lU!2r&`3&ZC06M5C)o~L0L{B`I;r5aHw zxn}52@AKC~>eTQ42!0?Z?4mKYZLgxNYQyCxBl2C3JNVbX)alei_Lx|3PPnZ2u+`@Hyo<`=qGLhm*Es1>h$64G(&aY>~7 zro*zVanY!c@|5=dV^0VWX-IJm1@2F^4^aWH@bn_gxf zL9wzjUWaGgmCo*+DQ2Fp9cJ{)d~y2iOCL7Pt`8S3blSMH78ZZEmH!rb>G6`tc#*5! z7umUNit`5jGLixZ5UFH{RMj!G6teel$nQ$t$w!#pDzeF-O%l{T6~(_|A3&yzBJLvF*wRY##s{N_TSm{l^ncS&Dvz}#}B zhqraYZq3L=M_lGbVc)?+cKrpd0pg|dKT|*8b4MQCGsiN`L&-W}BVLnCdz@0er?TLa z^ZhslQUD5&kGKXm59w<8%j_fSGc)7g8$Ve5y6}z^cv=j-v<$i5s1W2YP1BlqTqQ? zfFzLk^Y!4(WF{dJcbK-|Ag>3*B)CRyMHLhriBoXeHCUbMoKE=l23g1c^1kZ&rf$h% zk1X;whLLQ#QQqWJ?`Da*xo;y9a}bFgx#*K)D<}z)r~wi&uq4(12X}Rox88z-0UX#h z;}P_({z|sHNA?@GpC%tZl!aPUt~4+z)AO1}F7~#4jtyYe7fyW5BySrQNAK=>+I?FK zclGXTcgbwOzOz0LI4B)_| z_TSI%;l+!%6?1LXmfFE+JJE-?54|v!?^~5j0=VCX^CqMah-r&{mOOCbC37Fol-szt ztK$7%YEx#%mv1IT9!x-_Fc7KWJoI3&N%?}Legml}SW?^&srm6OI2gczN!2&4>c4$c z^=+J(C$#3>qf_Fe!c%3eohEUu6WS?tIRV@U{l;WU=tif#THC_wZI7R1FFq4*+uMHY zLmTt2In{VXN)RG7=!_l=HmTnrDdc(2pAGoUq@*BHx4v(|K{w$4UEN5#hE2<#9I0%b zd2|0)&i%r($BgY%;`&zwF6Oo*KNu<1ClE9`A?z!7c;db`hqTpvp9X_;iC4!jJ*GRa z_jMDzMWo~*Qo1-F#;{3&=RX|C^Pfwwq%;5rcXhMH{a(uYn*aeD91P&V7KR?)C{xZQ zo)g4A*A@4-7FQ%3COc2KH~Ga5EgDXet9`9x4{5mhN*w4DB$|9w$C-l=2_1+;JTw^& z@VqBr0Z810Nti$+CRt(0U^y7Tfl1st*1s<|&^T$g@DU}Mmou0;XO0dDjJ8_Vw%ivn zj9M35ZQVYLKEC|Ge@rH8pg(r~qrqv2gheI#|{a$vhTo6}22ca|ZxcIgvFlZPKKP$`1bsQg{L4ZjQfuqVq~ibrFfxHwb=O#j_dW%dnZCtzxQRy{qJ*SG~CVIRV)-xgFD!b4XI>A(H*l zXvvLhh{L%qP-Ymii zv#jdNPND3ymZ$U@wS0o4q_fLJ$@NUN?N@wfS#CKU;X6k8spIj5rIORnVvD7ksX5&n z_C`FG+$TC#=!Zx~KqNnjpd~jF2n5ezLL}J~w%}j@2PPRbHngMeoae{w zSB~7>=JqWdGu)zq? zlyNFXS6_BvwaUir_UZ&QmF)hv4Gdp$CUe06f)a zlZ@WAXBVyfm>ePA%jrGAqHRYbhOb;WA{X&)B&kCueoDNnHKtpigu0cL{9F3mEAh)d z&fkOwr5~ujJJat+C_zCv#Fk}$=xxieklJAiPwRd65y@K+$re)d;IK(%j;(TX0LfsO zWDP{JpLq)o25?}KJ}*N;s8)YxsUM&SHUAJ0bAVm+a=fqH&4eqZuNU6FypdCK*=SF~ zt;cJl0i{13GR%6Yd$@|k(_Ak89B|;wzITx=rM3N?Z3l7pohDm;_Q*R+2-Fd-7_1-P^S0aYQA3J5kM7|tz zwpULbZW<=td4$<)mRMW6`J$Zx3#-c)m9~7D5Y-TT)tgRdrIbeo@Gz4zsacNHsttK0qX{a-mO-P0Fj- zI*1QQ{Q3RL&7`Iw5~&PZaFFj;!X%O`XJ&NR9uogN9k~#3fXwAxHQn)Zi8~$MCEr@o zYJX{1tYu>F)bq0`T{69qvA-SSfX?*Xq5T74@O6#IM;YOPo#Q?z#JQCnSmm=fYRk+B?g<#hKox3l~o| z96ou)PD*JhSSVa*yzvLYS*~32y!8e@DHsfHv+@eG>%(~qB;y36aNEl39awsZluSJ| znGMe0ZDs!T4y)G2NyQJcwPATZZ#*(1paO6Gk1F<()aOFTK#3?wZc>r9#hv z7z@LT+mp}#WS~ss&&4G5Tw$W@&m~JkrrREf)C2)~FxUz^fuxY1m+^xo#RHL|#c5We zI2gczB^5XRz}%#t`AM(ob2dwc&rYd}b=k+*5AGK{n0#r%FZ=RnkGhMU{)g>WJa-tH zIqBY%lpGNHrZIB(gX!H$mrtD$h?F2iDryuhg}sJmK~i^t6tt}@1(9lmexl~w;QUux zIY5g&uHc4zjxxK6ls%UfSC?C)V8|42{)M}{xLu9?g6qiD3Pe}C#U!NC9yYzZ&a z_{B|b{89S8K-Ql7QjE?AnogO<4<3@t>a+3=d?nN)a{m>RrPs}qM=25`#4B!^NTt&l zd9PS?Y;#eIF?w(OI7Xqs)Xt!Ngm-2Cz*oFo0!VVY5Xn)TC43_}E~#ScU=kn+Z8Mud zBn6@S6qbXunPHNwIxN=YA;cldp+xR->Fv)g+B8`D9vBOBCI47fl6XA3>j6Vl-QqQ$ zQ#pn29Amh4J72xS7q;@cpJ00j{j)W__isn1T`NTH)%nCFe-{XeR6-;zA(D;;umplh zK$1~F@;od_XTSlM(E5S>6ksQ)y9EaWIItx?<*v9*PXDbdYQItrHu&(6rtGKZ{BV50 zXwhJ4A^plPvaw?ysizI1x2LJ>OnxO}YKKUigGfYKpihoXDhecZ07yXF(18#MKb#Mz zC=SwwhDpo?RNTiLvwM3dWhgAy`F8bW1G!DU+f|!>djAPxlAj@O+ssfD43gi8cB$fjWbSt2KO0`Llq2Eba{u^hXCxw#29ZdF_8PbvK@x620@`NI zgGj_c-*donkTx?+VmXV7KGrmE;c_TLfw&jLt>q#-%S)vF?kRGsvJ=Q9 zxb&eYU!Yb>>MUPoP=~a90 zs9+o;)5Al`cdmD>AX1GGscW6+!C>e1B1onRNX5aV+8|PQpkEK=+TdUS2PQ@R&_L(T z;pN4^xO2Yabb3Q-N?bab`?8dele{6D{fLcIaAE} zXD(RPdQ0q#q*r&0kyVWTF&(J;wLh-AOe z790%Vz$CxyKKe-4m8I2(&s`=rMDLMw^Up#1>GK2`#6kB1Rvs2Ih4NXN!u zbv$y+GPdJI+s$8}W+F<=D)VXB?j>Yi>MbsRN#{h)()vMtec_mcNKWrT4{jrY5DJiF z9FTN|Nv;77?lrfBw*?0SII!tiV9{J)u)xRG`0o4J-1^q>BHNF-ugzr~4=fL5<~4WT zW6$=}j&@1p`53cY6fuzBZ@YTahX(I=>-8}MU+bG|>#wd6IsJW?o?D0>3^utqkem*X zx(t(|0UTVZ2#+l|7{Gx^W$Y%gAj~x07P4c~NbGHvb-9V@1?OM=yQVCdiCB+JvFwQz zZ0N|qkJowJ%^FM?6;yc7HgB(w?yI1X^YmF9N$VfqcR{4e6w!mhCZz+C>IG7cFey&J z0b@knF}UpCf`b7Zv%jx7k$h!F(q$TsCj&%TnihADSF(l8Tn|)RyrF7HxUG4{bM))@ ze)EHYaV`!8-*al4+15Xv^Ft&|g3u?&CesU&2?G+)HnappqUg&Ood0S=yZv6=&nZx_ zzun29X^AVKiktsA*UVjRc^+O`)0V>WjxVc)^!vQ%+JqxjclVjBy+9TQIfw)oe6EL$ zt@4lo342%)>VShgy}Aa`64*pHI2gczO)v75TG6?l+Vc%h-UO9((^e5jGDPxF~z+1G`M#5MQ25?|f>9pM5^?@To&DqOY*+(B1W^ogqOm5QEbM%U?h*o2! z?3u0A%ZUy(QLUS2d1@H`(LPHed`*6kcigzosC&o62qJX~A|?F}Js50-pMa#afRrsv z$_a2{aQ3N$16yz~fCHlaYo8iZ>3C#zwa__P@Xq;~6A=zOm)A5@o|Dw2%}6pYOtQ>Z zOMiQ!GS+bZV25PpEsc}Geg!g`%}2HKUq!DdJ#|>MGmk!Sx5Zd(sbSlwPNaFJ7rV;q_XQ_jHe-DAElr)L?{tot zPaXR4qbHMp6p;*rNNNe72e*-AC@V-Z4@jPcNnQmU+-q*|@fI8m;J~IQ8-2j}ws%w) zlN3X$e~^_uSx8%I>Q%j_nsl%DX(|){5c@25(@AkB0@F)bmXAt51%2tWyK*9TDJdh9 z$xv=rrVb*N3X#e?g&qvH;&~uBD*?S)5k~ zu*rM|$sj+<8T5w)a`N?FMmt2}m=0P3#lZj$T0&r5g5s($)iB@Zbob+9(ca6VMFVo| z{E9OgL%EU7OR*;mA4Q%muV%cgR5OGz*6|%Vw%#r3f=HZz-d%^Ljji%B1Bo**iFXi* z`XRIgHi-=m25?{!s{F#~+;am$?@}I+S+La4XG}~ohu8ZUuGE(vh$u^FdeV90<@ZMa_aaG*KqLx`(I?-iATKjWq6T#XI^TrELKsF$a+_euX|cwt`(C z2|XZT0h7RUCc?`A*93BG1BV(OUfRmDEjSp!0UH-~A6lQ5$aJz8XnZ_MJ)hS5>oWKJ zcYc1Yn2u*BT+~xjEgluke&=3o)OY??=XT}f(R1lcks>BlwQ=QDhmLV3ak~C8C%Ah% zz*_bhpW7gnW1cq^qo(ZiF-yk;8?~n?FWwB7_vsAZjm<`+iNRoTd*wOX(SyY%r&nx! zQ5;DB*;d}XhPFebo9(vXAZ=xs^qUoev_R$F9`PSC*(Z1CD&D$O>+)ob#VDbhFw{!& zUXK>LXz+#Lwi|k^SM6eh@1J~g*iK2-_8D2vWQCYX-{_^&owtnc?=|E#Ce`Mac)E{k zx5JJhqKMS)cfUNiHSd4VL8Ny>qR!n)vk&X-%vhP5W0F-z?cQy>j9$ym)BR0g>JZkzT`j ze2PuF8YGV(McHJcpB;PY?QEZH3#~sBg}-bpaj|=TBllP6V5(&dI>sX zHaHl-fh|mD?4}&(pLI^oD=r%Q%8VYHkr-m}6=NQ^8l+skC9QkxM1tua*`E^R-u!z% zPSSrYMkMqg60(WtlW$a_AIklXwP_ z&;=64uq0do2h67R1G~CL%B*g|!2pi`->a*RPLu6h$yMh^M`<#wQdR4`H6CF`?>_Z@ zXI=PB|Cgb0@{JVtV)X}mhx;h1S>%{JN~`d5;u6_9KfSRoxbxA1-ymdPQIJPK=lFHs zdi&XHvK>fLUJyy?e)Qn5N$D0_has;h{Mj7cOez>6DbKzI2WgJNB&F0IP#hUNv#fd3 zg}mDE!%Wfnl<#Z?dECd(NV&5~3YgNBL`}_ICl$KiEVM`RWl+M+Z(}P@)C+sQI9UcfuNZq8&vrbsrm;r-;J9Z^q0x4&K-15bkAw;3^V$9|9$N=<(K)?gvsN~=g%xKg;2i^+JQ*^fJpY?ysm>y z>K#Z5c}2kmCQ0n_x1_2*S`x*<01iy@-C#Z8vRFrSSCSi1**i8f58iOfN*lkKQ2u(^ z2Z;~AdP@}OQQK2n;q@*y8$P)%UBfR&mGaKLQ*(*l)Yn%>eR`JmBl9`ET?bFRSklq+ zUVoW{3JebSHtgId^x&{b-WproD*_~SVUqk1Nw=e0a4>)alhl|$WK9!Y@*$~iuk-s) z?r9N|%9##F@lVls`kS`;&=gu++7pqHrXE+8HPZ4nkt?0$x~a>L725Fq;kTRk+E1|@ zjO{3WPTt;*PZ~C}80c+|Bq;%r{0Qy%?iDGv4#x+Qe>O)qS4RbiWG2pw$QwywIY@I9 zCb_%DwpO%J)5P|AWaw4%`}5ax?^+!+(RXZ#=XX>rl3+T={I=JIe8T z*Z1;{l4Z_uv5`ucO+;JJX7BjU*z}HajJ2)^;ruEJ-84 z!Cf6Q{I=j=0LSd_eNN=Fp4)D^yjgwxF4MPdh4O0@7bed5t9lzOiSJxX5Ven_5&bc- zL(kGU(uuy1@x|;}MB)@gV!{`Fa%_deKvKvn3=S{}2Z+R5&n-9@z=27aTn?W7ddQ90 zqPs-(=)3em4+A=t`lQbDte-k0_r{rA4BXbSN4c%bS8!_SxoHu{J4C`AA~E*_ee#WK zDqIRAQ41tAVG>sWrxe_AAP4r2qlgmc#u>%I08Yl=Nw|KZHZLfRE^P>Z6=FDuS$a5Q zPI)*i>+!+m`c{pBw|io{+0U>^9a+@5z4JCkgV}%jYn(<)T}jHMyRDe;FBgw&1uH!+BIRqyYe9;T4k<#) zG`a}bBx^yEC7=j4up$&eih#Ej2Lm{;BK+t&d{6#}$^)M9)X-Spp^NpwQzZxEIPt!H zOC)m8<8Zf!=yQA0Wxvm8TfqMOT3IHu+J`UP*6 zsqfB#*(e^__&e8b=WeS>_B=>Yw~lpsqBOoh%6n~sPPg=hRK9+q*fyfXj@!#z1sprb z)i_^b+)PIV)%wr#Xm_8=xQ0l+he$^Gz!Hc6-~ZxAzW;RyCOHK-xT|X#&h6hul2{G~ zaLoQrQskFKeE&-gmIMZH!0cH+u&b+21I|qWHi-=m25>-hxZN_vy?l%ZXZ%I*&Jsw(`l_D! zm?eC}nS=hp0RFQKH{PT%Ut*f?%$57h@js+Hk{cZ8D@rs~bG^A!>qHvi&ROm2^%6)j ztPrW^IL%mWMZx#KB9QNYorX#6g-G!u2_slcS<0SEV*SzXwIg8>}aHDgm@Ei3Z)wfoXd0U!D9?Ku%_UAZTo ztr0oLUmYbA5P2x;xLx1Lq2_0o@|QYHqsRK|uc{CUCY((en+*8AS40_*I0ci?hDf;3 zq9srq4B)^d40qZ+s9EtGG2kF~2&TZqja-SI5&N`Cvxg#ORQ#7411-z5e{n4gO=P# z@)G#{KLO?=F9A*|ND(>yxwp)r+=7DvoQ%JdbUhs3))py1Zgnt?ha{Jr()u_< z#%%&q&y%GQGpfpmo)UMQVYnc9pYzM0Tv0%I%%dvQ>P7V)CK7a1a*s#tEOVb<0> zsq6K&|J3-8AZfBF+PA;&m&P~L>#J)qiM~5{Ew${*m6MN8_E`jo)WwQOtiNCu2Pwi? zoR?Iv34!1FyW|6kZ~|6@bVv~%r=p91;$Q#=Rs^qKnmarvM^cxPn8quemyP*3ANTa0 zTC!$gTr^3v{}fo!QgYVLH$Zp3%AJu{h419+!P2W@fyom24+7I{b3eEVx_rU7FFr5! z=dB{*RLS2*l_V-K>c|+ndY-)X7=4_~yaaqH`Qv%T% zMu9&uUEsHD2+rF&#LFGN8RjwNsI}8$;yjbd)Ah}~8Y1yC3w?5I0>40#w}FHaOri-Q zu?GFzD6ql701iw-^2xFKOSvj%y5GGi4;}qLL)>*eqOrj{>jZ^cb)({1MmwuQQg8Nc zBdv)u#a_de>o1hGLnQ1Z&=S}rZjY@BiUA23n8Yi<0kaGB{EigoYmq1p25@5jPQoIU z-sw^l$@PNa8~O5Lj^1oF-m}Bs0xF(l#Ld5U(oIrXk-g&Au5Y0}l~uz@Zuk{%#oLrY zpr>_r#=NndClQ@S{X1)~!#6|9cpoO(48`*Xl>F}RY+}*6mh$wAsgRiEBV_u$he(V3 zL`!cZCn#2I9Z3(Qp)J61i1Y}~>$oTm(gK7@i!A>bdfo8px3jL<#X}FAx!(qae^fW}eZU`;Ckx(Q(NIC^bOTm&}1svRKj=yFL z4hC>w)0IKsaNW?SwH=Oiy_~j%Bm<6L=iZnt#937mNwlj`Tf0w@s5Yf|G{3%SWn9nj zw5^5V^{$Fw6e9b8S~J`3kyOX|@QUJK00$;nRm9jIA|qz9pQ=_yjqB@z zZOB8?)&0k)x--+1cQUglUH(v)9xU*DFwuOm>#TUYnTOEDyeyk3?unEsNrjhlJep~A zmbrTIC-#eQaV(F%=td-^Ad=vhMDY}f@$dpcp^*cdWX9O)K6W4}29s0)9Ng(h#j*tl z130khI8U$kNr~pmm6FERig{)wT^=b{@|2p>V?|Zv;VR!43YF+M@ZGI`8_k_zee6!} zNQ_8mKqSa;+UOe<-p3A->H!ka=BqwLV)i9k0>$~S=Bu01kDo6vH*;n2}2+u0!zXc za58ZAu{826I2gbI7a{Ja1dGBi9>(`l_=dk;JCMMt@W}L&YxNolPv$qF<2NHc#(Z{` z-2Oe8_j+(wkuSj;ObekdU)-(K)H^EPdQYRwqZDOYp7bfwEzZ{H@lu{WKKvc512j|xVRGh&PD6OU8C;my1qm`N?tS8x$bNU%Fv9eqS~J09!F>c^h_xU ztMGR2%=+k%f4Kb(`=AHwO?#2AeOf<_H9VgYA8Xz5dpAR)xWR!;u?!^XAc%Aq^zQ$% zG)NlxF|B6t2LUAyF^RJ{J^0puHT9wZA z>Xcp zCMOka8_)aZt}9CYeMY#qW+9vVgTH|1&>Clh9g^fth@=S4f`LsSdTdpQ7D)2{A&Cr5 z5aCn+4({q%$c-)*ih}{1e^<|S&ibo}XFl|||LSy7da;(qCKhw`{O5;#R!nWua!tF7 zI5S_=F}u#Ts)cCUG%ww+mG(FwY>%A04kED)`Z-L979`aKB>rr!Zc4O3B<|td6l^4g z<)E9Z|4L8}9E~@f`H(hgO;#>^b&Zy#DrL%~%hHCG%uvvE#LHkJv%EV%?!LHdu$H9x ztC?+xLN^;$*md`dxG@ED;Bnlg2SebmPPbeN9!CC6Zaa4 zbV#_}lJB9udwJ-0;QgDjp8^ze1F_7klCH)I1*=xs+x2$-4Nz>!%uIkcK65O{QhsYX}9|y zV4e?*d(6+?p<(AVXwzsW@mL5c0-^igt1B_i(vMBP7$koU6hRSI1X{qsEkX!%l@{9I zU;qbJggheB`i|GVClw=Rc@$J7ZHb2Vb>5QUYnPYanX~*zul$VB@twsM+&imzcIEX+ zeBd(LuTRJClTT|^<~lu|`q(eHN)x}k(Y5?y@7aJ0HSWh|96nj>X-v&4ipn~`)Jlgr z$YNpr@C^6T`HHnSY!f}}J(yjPB3#3H2?v|twXs!U+J~FxJ z>5t-I0LSU?nV`sR&`(#Qcua5c_S3Z?j1Hc!{S0-BRy_;;f#F7~r)2Si)VJFy>e|;x zTlGrCwmHThxu$N5X%sT^q6&;*|L|lCNmdXdSDn_%v<1}s3!v>+2BS#Ub0}!dxI4=ZXD?AL6LcUDF3X?hlk*eE@g8>|vl=G4Z zZ|^s^BrTsqGlEk?lyjP;B=(A;`xu3r(@R>sOtT-3cK`|rfCI+3e*Dwd{E2fzj^bbd$L#NGO62mH z)uyW@uYUz;vn^;A1WX@DB5s>0j*Jey>Z7v|eS4sUR?+{SFi&489y!r>>H75tF6ST; zjuU7J>@`#bk~s+^WMLA45Q)jfEjSp!fl26Ht;tQ*P2H{?_UU^YDNXdaW%&0&qsaP( zH(JUAMxo@+=O-m(6to8GwC6vtWSIFO(<=-jA%W92z*g`iNMaC3Fu^1e04D<^fgIQ* z(jMY`1r5c)08Y%`Nmvw@#7sYz7qjrd*YNad_;|3sV|1#2g~|h;%wcT5cFx@j;Lr^81c|w)i%$sT&aK8E8j9c!Ptq_+ZkPnY>MgKkIuv zoiA1GTX}gojANK?+mgtHgVs&%ClB)CZ|@-QbUDL%QU6*HW$~kYpH}`r3ave~Bh-xq zxrc6*GR)Y?3!FRsoRJLAl7BJkJ)iQ@6(WY;Rhsr+-1UgaE`LR&OCZwhIGZ^(A@IA6 zBFOJQVqi(v01j|Kb<>Vgp^Jy&U;xMe@1%8HeRt-}c?7QHJh~9KR-I6J_SPNUvF~%U z#q)iWF_J|CWyO)9=bE&6R-OIMu;2Jjq+QE?g@!i%@V?zOt^IwcV{=If`e+WFEO0nj zcr|}W{2(IP2$B5miXPm?H7NpqA2NmkNdDO}+)VZrAoF zpVKQ@<&CE8Uidk++oDe0<9g=zvCiLyZ!U!^X&KV_RO-@%b;qfHFktmRwY@A-CBdk3 zwH#`6iUlN)LW*%Y^N*0Iz!3x=$}BmDv*S>lHt+(rU13?ND5%N9FfNe%)I?&_HW z-RH0z4B)^Po=d6ZAE@UXw$Bo|pH&PyD3sio@IX78=(u)#Y`V=O&v;6`hBIRyzN&xk z9@u^6o60bf)JKSf3eE!+Y*MKpDdhJd|7;0vCN%?*_=)qHGKzz432r7OvXUJ?o_x;g zceG1_`04xy11Yz~Z_3TRknQGcRK6Jz#Ga`(@#gLHp?JlDJ%_GKuXrI6OAv{X=g=g; z?>~wlU!GuqB|+fvcM^LJZ^6L;4lIdCwOU%kVf`F)Z5BU&cJlB9Q?qkFp6+)$6xCSz zYmGkS;)Q2My;SgcTY>FL#5a4>)aE+X8| zYl_;h=ndZ9TCSxnDc&dM89}bA_>-A!G>)4_a?r%)aEO01^R?g4*UTDM^37f8r`S$U ziyr&gxD;!&S{Ns@laDV3k=h55vYJE>W}~8_;J*hJ(*mS~U{X>Lsk?W#;9vj;CgnWj zT2+xlH#sb=nvxrAa*g!xSXZ_0|I^%=hEvsref%8fATtR^G>DM#m`Y|c6(wnqGDn$Z zNV6gHm@=gj;gP9Sl*}TcG?**O2_Z>DnZ0Wtr{`&(R<7&4-Y@Tm{Q<{+-M{<4_FC)Q zd+ogs2gTc|yOSyhtGt_xi_6zJ>g+jJ^|3jPr1w)gPOkZ6l&$ltm9(zv^Hm6xDg;Ul zy5fkc0Z!=wD0Uds4hR(e0vd|q_>v9*=)j=9W96(Kt<9LrnuzTDpk~K;vu#`Yh9?7N zeNVprbmd*=+<4gGGFvI{lb{EAt)j;74h6_Jaot^9)4$R%%uP}~maPxZ}QEg*{1muJ|c zJwty*c3qtiX^{D`{XG|}gE_{hgQJS%_w^I;E7MAeN^I!G}U235U1v(}9N{l=^ytz1bpA1*gL4~HN=lPHH-k5c^S>C=bU{mgpZ z*H3@+-FEepM`w42<>6x^H5p?8iL~Jk`4jrz`EBP*QjzUr7R^zv32t<#BzsWubro}lpb|# z4Li?vIni|y?q_s1S-6DPx+}FqQlSzk_X@<+QgNd=~UeQ|PYQZS0 z{-d1(QZ2i56AU-`r<|WXzxVR0$pRAF>4L|7w=cyt=_?{mH9?@{_dzpU51cXpP%B_i z?|@DeIA@T9vV00lr%DdRsU;l(&;iy`uNZb4n5m2&)V zOTcX9trEZS@o@9eBlXRnlzDqUi>olm6lA2x&XnyiiD6q?$7enK)=F*D6X{_wX8T^A z#CfwH2N6gT1d?YP8gl8Jk~PS&k3nux7J@+zLm&mAyYVPG1fTJ#mi zSYXF9?Q!V$UZWi7EG<0o(sFW>pXcECz^kyho_i%T2bju*{jPlROJ(@@&lZ2u@MrBW zFPdT|w3*v{)E~^S?Oi`n_|hGL9EU(wDWM^k9EjluPNo7#IvC_41oBMGGCBmH1B0AP z7q$*-&=BfRIVt18Q!Vqlkof6Bcu%ZnnPtA85R3VpwM+*zo4c}0*0z1c_Se!r4Drkg z{BWc9l1=7jT=MHo@sC<~)4{6SgQa`Scb%4tK_Kb8{#>Q=1)_taIGGBZM4s;`0E1)) zI@I0u2y`tdyQD(^IxxsUVW}syABx!)or5mCd|okDHp;B^R%36^93S2H%0mrB1_yek5x@8%q8D^=sfb=sYq!g?_ATU2LefeKtA_F zLsFas&wrFfp8tr0K?(sK7pi$oylWX90?;x4^PD7#{3zX7t}8qJ{;Q~@MXg(qW2lkF zl+A~;Qnlf=3PxPAJO))Sr|<`PrB1{OD*D=o@HHK zeC+)9e|k5Qw0U+$S&e zDxO^K<|19RO5~TOl|rBn+&~9Iab^fOgKSygfkD+mpq$v2(IEgG7}O_&*AE27d&c9t z+8tx@-k}-o(xM7SgX%a3_4-({>i6AXqM!D3pxbE`E~bAvUs~}8H~WsY%X+&pM z^00hDoN9tVRdu6-p*WS(J1Z{*oSKF~y#YGZ=ZpvaGCBmH1M6-vH7$Y>p`}S$^V{CU zu+k=-XI_gP@0&EAj#1ha*dUedYD>axcW;fqAGF3kQh=9y;`cxxLZB5^c`4w`2jC1B z3}OfZ(Hw?`SaO)6LjXE3h_@94@fro3g}+UT~t$0!JFNB!Lmm&NO`Mv)w=`q0{5mib`B#DIPX7~ zHPz53lF8fV*vBH*hoA*}W}rjeor(t0$)Gr~r1Q6eeenwsNzc`hw+VHU?p%foIn#0BJ)LW`hqbkEQBFj(J_`H&4>;2p7-NG)EvfArK5yh4v*UV!`zvd2s!Q_ygvI z0MI!{wKkh*Mnj-<2tWsRqTiBsx=E~6kLe37416`bkK0!6I&;vvh_UZKv#os_-HA73 z^z$2}IbR#+2#m$r=VUw^Rr#5Esx@o&$*A%~c+wgKN)!SWWq=Nbl2LFyDE1(523o+E zg+P^kTSn(^1$+Y?lJDdv(=uji-MT2==cPNpkzqz%^uylMAlRWEWlvYxL{ zucvbGd6-5xTdfmz@qqIt`S%<9K+!mxAbEC>cHooazQnO~9Pe0Xo#(Etz*2 z9RkpSoikq|6O$Ne1d`&6k~>WI@Z4$&9v_nIGd!Kl^?b-IuFUF7#Lb;ZpW(Uwbm!T4azJru^VI; zab(sJa$~P-p$m`aYo8Pr8C&#Mu%3B&!tZYDKx;MvVGekb*o6qDwC=QF}4ydOIog zS=a=LQ}l8BAulZt{!2W8gYNtsT)EEz1yVIf)rqP(?0ft;#$A*n#6W*S zfG~acZmh@CxQlaEi%)QgKO)XYM=utHrXWtlLm#CdNd-pRT5Ys==jZ>VM0#2L-PK?4J3Ly~FyOz-*039j_F0gr?Xnl6-Rlm`- z0F|M634=!$1S@BYc10w2GLCNNH)Yr@%esM=zAxds<3>AYL*0_84did**+)N!u&tAc-7tFxnL^h$_W9ce^ z$$2YzIBm=Fyn1v6>ckh5w;UwD_v9G_qW&qm@g*lNNdhPC0w+db5KR!B0{8%Nmz)d^ zcrso?bd+)EcqmC-R;LZ3QwrVJK<2vlH?B^Ijullo;J5tzRp%Wzls2B8tN8?7@tDSkB9raTgS z1XDn>xVRt>K8siH#Nu$YlxmwK@;5vXK!zqqh~^m8>Ja2=@`_V)G0=@FSP9nz4>ruYS68I+T|M#Ba%RQ6?N+p}}8I8-z;q7{ah z2Xuz;81k`%hwtCdiPl+4Q_Biq`ZGU(NAva%JbWG#27e2K&&1$w5(Drl!~k4yDvkzA zLxaT2j)oD36@feyD1Psd5K&qRiu$cp^1f|-7&o2!?#tM#wn z&@Wl0+Ac} zC61ZR$Hzy?$IaQ^)6-eX*3Cs`9dXUSVK891*&ST%-86pt0C6o3i;O&Ri;RrS7FnW< zyczg$3sIi9nerpi|Kk5XYzi79GdOUMD(4ZkNBON+q; zVA(Ll04yU-02Yg>ieEuGpgDfr?u_?*o5yGJ$Wpz7mt~_7 z$=235g6W8Q{AG?b zA+EKhJpX(j?9TTrJ0mSnG;eRrT)y`{$;FbtOwjW+11@Y;Gy9_>HDa&Q5_Xi4T2~*c zPpzu9J;|oMg(#cgCo34A=2ODioap({d}D(nOU+iRjKTs3EiHzj&J|^H>+hRx$jTY6 zC4I8K@T586!<$z|`5iPkEC!qIKS%VR2JYkbtzpG;<5%71kZrh>6!@`W>Xou9POEVp zYqSc{zXAEXAl|>4=wIQtN+kLyhgXg88ubx5+xr=vYl!`WZE60=8UBg?PrGjb114Eh zuPJSnO(c;SLE*&H5^-4U;_n>XZ}^~MW!^a#>~U80RiHuS2jOiCRnHHRHs4p36-^&yUf+Iq_ty5K*%5(dm*j_e z1qaz_BFN>&nc}JV#XT-d;&&}=J`e83m$w`vAqkGHQn|}VEc#UIgw2i-%hGv_P zI&mWC*GgW4@DR`e{!DGCvf6flm{R>BvDD*Hv+UJ~#}_#2v_N zM;`bVWd0cVFnCrVfCxT-jL6T6&?D)8BXS2a4c~!{$R!XRnk|3TdHgq>lRmVVZD3wR zjwL{>`Wfo2d`rt0Fhg`a1|$2OMY%r!v2^ShFr{L=t@X4+j}i1=exHroGm`u^RN7G? z=iQg6TNr2hpt8I8uKG~SsRS3DG@4`W_RlW!-!v_+uy+({mhfuHB?V?~d#TLMjg!`S z+Ia3;NTx}KmETn^(Va{d!=Fm8ePh_vFjgNR(8!!}%OmZ4-`r>JL8THVbEQR0Yr%f~ zZ&}#n@Pn%dFp5r5AKbZ*hpkAi$+;ca)bYZ5pLOlz{J>Q+dCeQ??=MGW?hR8TE8hm<9;aCz?-3?&t$Q}Q(jxG=M6>1UH>TTow+ z745*9CYZ%>Kt~O98|0w$Jtd($n8g+CzpPo1LR+&6tdOwel}<7wDy|x|+HX;HfvBFt zqRIq1=RicrL5b=VH`T2-OC7kP>))tA0qxg1_t&~j!?00e=Xd~bm*PzP$;}P*FZ(Bn zC+Dx-tM5&=R+&&!RDDsXWjyb3vORcmID51%`u-VGn%4VlPl=1qPEL+BbCNH>=0czr zSN;vE5_z~qBMge)_s>+neXxuU0qFdfYH0-Ozf=nXHR=v9L0ujppHr0rAVp6>RJVVN z3Q?0r#tJc@L!Ii3a%fafb8P?}64igHChH(eWDQB4Di7U{@9146UIc#J=~W%}ohu}W zM!aC;WkhPEh}wa*hB~q%cXNV;yMyB&36FAb3gr-!GkkI0X^@t;+FiU72}T|Q<)(xV zX32L1s*?pk<-wq~104_}`JnV42b-*AbO=Dl{NMgVh9Z|;l26Dsmb#Fr55 z6J&^UK4yKxnbV2eoy7GD6I9h!bE;bBw&}0)98x9iq7ye2vsbQJcV|V48M|Ia$hl(j zlgW-iAU;FC{#8bhGspq&PL2?ru6!tj7H~Aej|1-LaiAjsx+QW@x}|896k3PkXax8O bW;ggYw7|bKr=N!W?{(@M7naU<)c^huZEo82 literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/tls13.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/tls13.test new file mode 100644 index 000000000..df67a3963 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/tls13.test @@ -0,0 +1,203 @@ +#!/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_tls13_ready$$ +client_file=`pwd`/wolfssl_tls13_client$$ + +echo "ready file $ready_file" + +create_port() { + while [ ! -s $ready_file ]; do + if [ "$counter" -gt 50 ]; then + break + fi + echo -e "waiting for ready file..." + sleep 0.1 + counter=$((counter+ 1)) + done + + if [ -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 [ -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 + if [ -e $client_file ]; then + echo -e "removing existing client file" + rm $client_file + fi +} + +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 +./examples/client/client '-?' 2>&1 | grep -- 'Client not compiled in!' +if [ $? -eq 0 ]; then + exit 0 +fi +./examples/server/server '-?' 2>&1 | grep -- 'Server not compiled in!' +if [ $? -eq 0 ]; then + exit 0 +fi + +# 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 | tee $client_file +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 not enabled" + do_cleanup + exit 1 +fi +echo "" + +# 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 -eq 0 ]; then + echo -e "\n\nIssue with mismatched TLS v1.3 cipher suites" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 mutual auth required but client doesn't send certificates. +echo -e "\n\nTLS v1.3 mutual auth fail" +port=0 +./examples/server/server -v 4 -F -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -x -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -eq 0 ]; then + echo -e "\n\nIssue with requiring mutual authentication" + do_cleanup + exit 1 +fi +echo "" + + +./examples/client/client -v 3 2>&1 | grep -- 'Bad SSL version' +if [ $? -ne 0 ]; then + # 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 "" + + echo "Find usable TLS 1.2 cipher suite" + for CS in ECDHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES128-GCM-SHA256 + do + echo $CS + ./examples/client/client -e | grep $CS >/dev/null + if [ "$?" = "0" ]; then + TLS12_CS=$CS + break + fi + done + if [ "$TLS12_CS" != "" ]; then + # TLS 1.3 downgrade server and client - no common TLS 1.3 ciphers + echo -e "\n\nTLS v1.3 downgrade server and client - no common TLS 1.3 ciphers" + port=0 + SERVER_CS="TLS13-AES256-GCM-SHA384:$TLS12_CS" + CLIENT_CS="TLS13-AES128-GCM-SHA256:$TLS12_CS" + ./examples/server/server -v d -l $SERVER_CS -R $ready_file -p $port & + server_pid=$! + create_port + ./examples/client/client -v d -l $CLIENT_CS -p $port + RESULT=$? + remove_ready_file + if [ $RESULT -eq 0 ]; then + echo -e "\n\nTLS v1.3 downgrading to TLS v1.2 due to ciphers" + do_cleanup + exit 1 + fi + echo "" + else + echo "No usable TLS 1.2 cipher suite found" + fi +fi + +do_cleanup + +echo -e "\nALL Tests Passed" + +exit 0 + diff --git a/FreeRTOS-Plus/Source/WolfSSL/scripts/trusted_peer.test b/FreeRTOS-Plus/Source/WolfSSL/scripts/trusted_peer.test new file mode 100644 index 000000000..67ee7803e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/scripts/trusted_peer.test @@ -0,0 +1,286 @@ +#!/bin/sh + +# trusted_peer.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_tp_ready$$ + +# variables for certs so can use RSA or ECC +client_cert=`pwd`/certs/client-cert.pem +client_ca=`pwd`/certs/ca-cert.pem +client_key=`pwd`/certs/client-key.pem +ca_key=`pwd`/certs/ca-key.pem +server_cert=`pwd`/certs/server-cert.pem +server_key=`pwd`/certs/server-key.pem +combined_cert=`pwd`/certs/client_combined.pem +wrong_ca=`pwd`/certs/wolfssl-website-ca.pem +wrong_cert=`pwd`/certs/server-revoked-cert.pem + +echo "ready file $ready_file" + +create_port() { + 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..." + + # 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 + +# Look for if RSA and/or ECC is enabled and adjust certs/keys +ciphers=`./examples/client/client -e` +if [[ $ciphers != *"RSA"* ]]; then + if [[ $ciphers == *"ECDSA"* ]]; then + client_cert=`pwd`/certs/client-ecc-cert.pem + client_ca=`pwd`/certs/server-ecc.pem + client_key=`pwd`/certs/ecc-client-key.pem + ca_key=`pwd`/certs/ecc-key.pem + server_cert=`pwd`/certs/server-ecc.pem + server_key=`pwd`/certs/ecc-key.pem + wrong_ca=`pwd`/certs/server-ecc-comp.pem + wrong_cert=`pwd`/certs/server-ecc-comp.pem + else + echo "configure options not set up for test. No RSA or ECC" + exit 0 + fi +fi + +# CRL list not set up for tests +crl_test=`./examples/client/client -h` +if [[ $crl_test == *"-C "* ]]; then + echo "test not set up to run with CRL" + exit 0 +fi + +# Test for trusted peer certs build +echo "" +echo "Checking built with trusted peer certs " +echo "-----------------------------------------------------" +port=0 +remove_ready_file +./examples/server/server -E $client_cert -c $server_cert -k $server_key -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -A $client_ca -p $port +RESULT=$? +remove_ready_file +# if fail here then is a settings issue so return 0 +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTrusted peer certs not enabled \"WOLFSSL_TRUST_PEER_CERT\"" + do_cleanup + exit 0 +fi +echo "" + +# Test that using no CA's and only trusted peer certs works +echo "Server and Client relying on trusted peer cert loaded" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -A $wrong_ca -E $client_cert -c $server_cert -k $server_key -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -A $wrong_ca -E $server_cert -c $client_cert -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\nServer and Client trusted peer cert failed!" + do_cleanup + exit 1 +fi +echo "" + +# Test that using server trusted peer certs works +echo "Server relying on trusted peer cert loaded" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -A $wrong_ca -E $client_cert -c $server_cert -k $server_key -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -A $client_ca -c $client_cert -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\nServer trusted peer cert test failed!" + do_cleanup + exit 1 +fi +echo "" + +# Test that using client trusted peer certs works +echo "Client relying on trusted peer cert loaded" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -c $server_cert -k $server_key -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -A $wrong_ca -E $server_cert -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\nClient trusted peer cert test failed!" + do_cleanup + exit 1 +fi +echo "" + +# Test that client fall through to CA works +echo "Client fall through to loaded CAs" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -c $server_cert -k $server_key -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -A $client_ca -E $wrong_cert -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\nClient trusted peer cert fall through to CA test failed!" + do_cleanup + exit 1 +fi +echo "" + +# Test that client can fail +# check if using ECC client example is hard coded to load correct ECC ca so skip +if [[ $wrong_ca != *"ecc"* ]]; then +echo "Client wrong CA and wrong trusted peer cert loaded" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -c $server_cert -k $server_key -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -A $wrong_ca -E $wrong_cert -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -eq 0 ]; then + echo -e "\nClient trusted peer cert test failed!" + do_cleanup + exit 1 +fi +echo "" +fi + +# Test that server can fail +echo "Server wrong CA and wrong trusted peer cert loaded" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -A $wrong_ca -E $wrong_cert -c $server_cert -k $server_key -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -A $client_ca -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -eq 0 ]; then + echo -e "\nServer trusted peer cert test failed!" + do_cleanup + exit 1 +fi +echo "" + +# Test that server fall through to CA works +echo "Server fall through to loaded CAs" +echo "-----------------------------------------------------" +port=0 +./examples/server/server -E $wrong_cert -c $server_cert -k $server_key -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -A $client_ca -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\nServer trusted peer cert fall through to CA test failed!" + do_cleanup + exit 1 +fi +echo "" + +# test loading multiple certs +echo "Server loading multiple trusted peer certs" +echo "Test two success cases and one fail case" +echo "-----------------------------------------------------" +port=0 +cat $client_cert $client_ca > $combined_cert +./examples/server/server -i -A $wrong_ca -E $combined_cert -c $server_cert -k $server_key -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -A $client_ca -c $client_cert -k $client_key -p $port +RESULT=$? +if [ $RESULT -ne 0 ]; then + echo -e "\nServer load multiple trusted peer certs failed!" + do_cleanup + exit 1 +fi +./examples/client/client -A $client_ca -c $client_ca -k $ca_key -p $port +RESULT=$? +if [ $RESULT -ne 0 ]; then + echo -e "\nServer load multiple trusted peer certs failed!" + do_cleanup + exit 1 +fi +./examples/client/client -A $client_ca -c $wrong_cert -k $client_key -p $port +RESULT=$? +if [ $RESULT -eq 0 ]; then + echo -e "\nServer load multiple trusted peer certs failed!" + do_cleanup + exit 1 +fi + +do_cleanup # kill PID of server running in infinite loop +rm $combined_cert +remove_ready_file +echo "" + +echo "-----------------------------------------------------" +echo "ALL TESTS PASSED" +echo "-----------------------------------------------------" + +exit 0 + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/bio.c b/FreeRTOS-Plus/Source/WolfSSL/src/bio.c new file mode 100644 index 000000000..4afeaa929 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/src/bio.c @@ -0,0 +1,1705 @@ +/* bio.c + * + * Copyright (C) 2006-2020 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 + */ + +#include + +#if !defined(WOLFSSL_BIO_INCLUDED) + #ifndef WOLFSSL_IGNORE_FILE_WARN +// #warning bio.c does not need to be compiled separately from ssl.c + #endif +#else + + +/* Helper function to decode a base64 input + * + * returns size of resulting buffer on success + */ +static int wolfSSL_BIO_BASE64_read(WOLFSSL_BIO* bio, void* buf, int len) +{ + word32 frmtSz = len; + + WOLFSSL_ENTER("wolfSSL_BIO_BASE64_read"); + + if (Base64_Decode((const byte*)buf, (word32)len, (byte*)buf, &frmtSz) !=0) { + WOLFSSL_MSG("Err doing base64 decode"); + return SSL_FATAL_ERROR; + } + + (void)bio; + return (int)frmtSz; +} + + +/* Helper function to read from WOLFSSL_BIO_BIO type + * + * returns amount in bytes read on success + */ +static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) +{ + int sz; + char* pt; + + sz = wolfSSL_BIO_nread(bio, &pt, len); + + if (sz > 0) { + XMEMCPY(buf, pt, sz); + } + + 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; + WOLFSSL_ENTER("wolfSSL_BIO_MEMORY_read"); + + sz = wolfSSL_BIO_pending(bio); + if (sz > 0) { + const unsigned char* 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, (void*)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, (void*)(pt + sz), memSz - sz); + + /* reset internal bio->mem */ + XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->ptr = tmp; + bio->num = memSz-sz; + if (bio->mem_buf != NULL) { + bio->mem_buf->data = (char*)bio->ptr; + bio->mem_buf->length = bio->num; + } + } + bio->wrSz -= sz; + } + else { + WOLFSSL_MSG("Issue with getting bio mem pointer"); + return 0; + } + } + else { + return WOLFSSL_BIO_ERROR; + } + + return sz; +} + +#ifndef WOLFCRYPT_ONLY +/* Helper function to read from WOLFSSL_BIO_SSL type + * + * returns the number of bytes read on success + */ +static int wolfSSL_BIO_SSL_read(WOLFSSL_BIO* bio, void* buf, + int len, WOLFSSL_BIO* front) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BIO_SSL_read"); + + /* already got eof, again is error */ + if ((front == NULL) || front->eof) + return WOLFSSL_FATAL_ERROR; + + bio->flags &= ~(WOLFSSL_BIO_FLAG_RETRY); /* default no retry */ + ret = wolfSSL_read((WOLFSSL*)bio->ptr, buf, len); + if (ret == 0) + front->eof = 1; + else if (ret < 0) { + int err = wolfSSL_get_error((WOLFSSL*)bio->ptr, 0); + if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) { + front->eof = 1; + } + else { + bio->flags |= WOLFSSL_BIO_FLAG_RETRY; /* should retry */ + } + } + + return ret; +} + +static int wolfSSL_BIO_MD_read(WOLFSSL_BIO* bio, void* buf, int sz) +{ + int ret = sz; + + if (wolfSSL_EVP_MD_CTX_type((WOLFSSL_EVP_MD_CTX*)bio->ptr) == NID_hmac) { + if (wolfSSL_EVP_DigestSignUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, + sz) != WOLFSSL_SUCCESS) + { + ret = WOLFSSL_FATAL_ERROR; + } + } + else { + if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, ret) + != WOLFSSL_SUCCESS) { + ret = WOLFSSL_FATAL_ERROR; + } + } + return ret; +} +#endif /* WOLFCRYPT_ONLY */ + + +/* Used to read data from a WOLFSSL_BIO structure + * + * bio structure to read data from + * buf buffer to hold the result + * len length of buf buffer + * + * returns the number of bytes read on success + */ +int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) +{ + int ret = 0; + WOLFSSL_BIO* front = bio; + int sz = 0; + + WOLFSSL_ENTER("wolfSSL_BIO_read"); + + /* info cb, abort if user returns <= 0*/ + if (front != NULL && front->infoCb != NULL) { + ret = (int)front->infoCb(front, WOLFSSL_BIO_CB_READ, (const char*)buf, + len, 0, 1); + if (ret <= 0) { + return ret; + } + } + + /* start at end of list and work backwards */ + while ((bio != NULL) && (bio->next != NULL)) { + bio = bio->next; + } + + while (bio != NULL && ret >= 0) { + /* check for custom read */ + if (bio->method && bio->method->readCb) { + ret = bio->method->readCb(bio, (char*)buf, len); + } + + /* formatting data */ + if (bio->type == WOLFSSL_BIO_BASE64 && ret > 0 && sz > 0) { + ret = wolfSSL_BIO_BASE64_read(bio, buf, sz); + } + + /* write BIOs */ + if (bio && bio->type == WOLFSSL_BIO_BIO) { + ret = wolfSSL_BIO_BIO_read(bio, buf, len); + } + + if (bio && bio->type == WOLFSSL_BIO_MEMORY) { + ret = wolfSSL_BIO_MEMORY_read(bio, buf, len); + } + + #ifndef NO_FILESYSTEM + if (bio && bio->type == WOLFSSL_BIO_FILE) { + ret = (int)XFREAD(buf, 1, len, (XFILE)bio->ptr); + } + #endif + + #ifndef WOLFCRYPT_ONLY + if (bio && bio->type == WOLFSSL_BIO_SSL) { + ret = wolfSSL_BIO_SSL_read(bio, buf, len, front); + } + + /* data passing through BIO MD wrapper */ + if (bio && bio->type == WOLFSSL_BIO_MD && ret > 0) { + ret = wolfSSL_BIO_MD_read(bio, buf, ret); + } + #endif + + /* case where front of list is done */ + if (bio == front) { + break; /* at front of list so be done */ + } + + if (ret > 0) { + sz = ret; /* adjust size for formatting */ + } + + /* previous WOLFSSL_BIO in list working towards head of list */ + bio = bio->prev; + } + + /* info cb, user can override return value */ + if (front != NULL && front->infoCb != NULL) { + ret = (int)front->infoCb(front, + WOLFSSL_BIO_CB_READ | WOLFSSL_BIO_CB_RETURN, + (const char*)buf, len, 0, ret); + } + + return ret; +} + + +/* Converts data into base64 output + * + * returns the resulting buffer size on success. + */ +static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, + word32 inLen, byte* out, word32* outLen) +{ + byte* tmp = NULL; + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_BIO_BASE64_write"); + + if (bio == NULL || data == NULL || out == NULL || outLen == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_BASE64_ENCODE) + tmp = (byte*)XMALLOC(*outLen, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return WOLFSSL_FATAL_ERROR; + } + + if ((bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) == + WOLFSSL_BIO_FLAG_BASE64_NO_NL) { + if (Base64_Encode_NoNl((const byte*)data, inLen, + tmp, outLen) < 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + else { + if (Base64_Encode((const byte*)data, inLen, + tmp, outLen) < 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + if (ret != WOLFSSL_FATAL_ERROR) { + ret = (int) inLen; + XMEMCPY(out, tmp, *outLen); + + } + XFREE(tmp, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); +#else + (void)bio; + (void)data; + (void)inLen; + (void)out; + (void)outLen; + (void)tmp; + WOLFSSL_MSG("BASE64 encoding not compiled in"); +#endif + return ret; +} + + +#ifndef WOLFCRYPT_ONLY +/* Helper function for writing to a WOLFSSL_BIO_SSL type + * + * returns the amount written in bytes on success + */ +static int wolfSSL_BIO_SSL_write(WOLFSSL_BIO* bio, const void* data, + int len, WOLFSSL_BIO* front) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BIO_SSL_write"); + + if (bio->ptr == NULL) { + return BAD_FUNC_ARG; + } + + bio->flags &= ~(WOLFSSL_BIO_FLAG_RETRY); /* default no retry */ + ret = wolfSSL_write((WOLFSSL*)bio->ptr, data, len); + if (ret == 0) + front->eof = 1; + else if (ret < 0) { + int err = wolfSSL_get_error((WOLFSSL*)bio->ptr, 0); + if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) { + front->eof = 1; + } + else { + bio->flags |= WOLFSSL_BIO_FLAG_RETRY; /* should retry */ + } + } + return ret; +} +#endif /* WOLFCRYPT_ONLY */ + + +/* Writes to a WOLFSSL_BIO_BIO type. + * + * returns the amount written on success + */ +static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data, + int len) +{ + int sz; + char* buf; + + WOLFSSL_ENTER("wolfSSL_BIO_BIO_write"); + + /* adding in sanity checks for static analysis tools */ + if (bio == NULL || data == NULL) { + return BAD_FUNC_ARG; + } + + sz = wolfSSL_BIO_nwrite(bio, &buf, len); + + /* test space for write */ + if (sz <= 0) { + WOLFSSL_MSG("No room left to write"); + return sz; + } + + XMEMCPY(buf, data, sz); + + return sz; +} + + +/* for complete compatibility a bio memory write allocs its own memory + * until the application runs out .... + * + * bio structure to hold incoming data + * data buffer holding the data to be written + * len length of data buffer + * + * returns the amount of data written on success and WOLFSSL_FAILURE or + * WOLFSSL_BIO_ERROR for failure cases. + */ +static int wolfSSL_BIO_MEMORY_write(WOLFSSL_BIO* bio, const void* data, + int len) +{ + int sz; + const unsigned char* buf; + + WOLFSSL_ENTER("wolfSSL_BIO_MEMORY_write"); + + if (bio == NULL || data == NULL) { + return BAD_FUNC_ARG; + } + + sz = wolfSSL_BIO_pending(bio); + if (sz < 0) { + WOLFSSL_MSG("Error getting memory data"); + return sz; + } + + if (bio->ptr == NULL) { + bio->ptr = (byte*)XMALLOC(len, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (bio->ptr == NULL) { + WOLFSSL_MSG("Error on malloc"); + return WOLFSSL_FAILURE; + } + bio->num = len; + if (bio->mem_buf != NULL) { + bio->mem_buf->data = (char*)bio->ptr; + bio->mem_buf->length = bio->num; + } + } + + /* check if will fit in current buffer size */ + if (wolfSSL_BIO_get_mem_data(bio, (void*)&buf) < 0) { + return WOLFSSL_BIO_ERROR; + } + if (bio->num < sz + len) { + bio->ptr = (byte*)XREALLOC(bio->ptr, sz + len, bio->heap, + DYNAMIC_TYPE_OPENSSL); + if (bio->ptr == NULL) { + WOLFSSL_MSG("Error on realloc"); + return WOLFSSL_FAILURE; + } + bio->num = sz + len; + if (bio->mem_buf != NULL) { + bio->mem_buf->data = (char*)bio->ptr; + bio->mem_buf->length = bio->num; + } + } + + XMEMCPY((byte*)bio->ptr + sz, data, len); + bio->wrSz += len; + + return len; +} + + +#ifndef WOLFCRYPT_ONLY +/* Helper function for writing to a WOLFSSL_BIO_MD type + * + * returns the amount written in bytes on success (0) + */ +static int wolfSSL_BIO_MD_write(WOLFSSL_BIO* bio, const void* data, int len) +{ + int ret = 0; + + if (bio == NULL || data == NULL) { + return BAD_FUNC_ARG; + } + + if (wolfSSL_EVP_MD_CTX_type((WOLFSSL_EVP_MD_CTX*)bio->ptr) == NID_hmac) { + if (wolfSSL_EVP_DigestSignUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, + len) != WOLFSSL_SUCCESS) { + ret = WOLFSSL_BIO_ERROR; + } + } + else { + if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, len) + != WOLFSSL_SUCCESS) { + ret = WOLFSSL_BIO_ERROR; + } + } + return ret; +} +#endif /* WOLFCRYPT_ONLY */ + + +/* Writes data to a WOLFSSL_BIO structure + * + * bio structure to write to + * data holds the data to be written + * len length of data buffer + * + * returns the amount written in bytes on success + */ +int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) +{ + int ret = 0; + int retB64 = 0; + WOLFSSL_BIO* front = bio; + void* frmt = NULL; + word32 frmtSz = 0; + + WOLFSSL_ENTER("wolfSSL_BIO_write"); + + /* info cb, abort if user returns <= 0*/ + if (front != NULL && front->infoCb != NULL) { + ret = (int)front->infoCb(front, WOLFSSL_BIO_CB_WRITE, + (const char*)data, len, 0, 1); + if (ret <= 0) { + return ret; + } + } + + while (bio != NULL && ret >= 0) { + /* check for custom write */ + if (bio->method && bio->method->writeCb) { + ret = bio->method->writeCb(bio, (const char*)data, len); + } + + /* check for formatting */ + if (bio->type == WOLFSSL_BIO_BASE64) { +#if defined(WOLFSSL_BASE64_ENCODE) + word32 sz = 0; + + if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { + if (Base64_Encode_NoNl((const byte*)data, len, NULL, + &sz) != LENGTH_ONLY_E) { + WOLFSSL_MSG("Error with base 64 get length"); + ret = SSL_FATAL_ERROR; + } + } + else { + if (Base64_Encode((const byte*)data, len, NULL, &sz) != + LENGTH_ONLY_E) { + WOLFSSL_MSG("Error with base 64 get length"); + ret = SSL_FATAL_ERROR; + } + } + + if (frmt == NULL && sz > 0 && ret != SSL_FATAL_ERROR) { + frmt = (void*)XMALLOC(sz, front->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (frmt == NULL) { + WOLFSSL_MSG("Memory error"); + ret = SSL_FATAL_ERROR; + } + frmtSz = sz; + } + else if (sz > frmtSz) { + frmt = (void*)XREALLOC(frmt, sz, front->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (frmt == NULL) { + WOLFSSL_MSG("Memory error"); + ret = SSL_FATAL_ERROR; + } + /* since frmt already existed then data should point to knew + formatted buffer */ + data = frmt; + len = frmtSz; + frmtSz = sz; + } +#endif /* defined(WOLFSSL_BASE64_ENCODE) */ + + if (ret >= 0) { + /* change so that data is formatted buffer */ + retB64 = wolfSSL_BIO_BASE64_write(bio, data, (word32)len, + (byte*)frmt, &frmtSz); + data = frmt; + len = frmtSz; + } + } + + /* write bios */ + if (bio && bio->type == WOLFSSL_BIO_BIO) { + ret = wolfSSL_BIO_BIO_write(bio, data, len); + } + + if (bio && bio->type == WOLFSSL_BIO_MEMORY) { + ret = wolfSSL_BIO_MEMORY_write(bio, data, len); + } + + #ifndef NO_FILESYSTEM + if (bio && bio->type == WOLFSSL_BIO_FILE) { + ret = (int)XFWRITE(data, 1, len, (XFILE)bio->ptr); + } + #endif + + #ifndef WOLFCRYPT_ONLY + if (bio && bio->type == WOLFSSL_BIO_SSL) { + /* already got eof, again is error */ + if (front->eof) { + ret = SSL_FATAL_ERROR; + } + else { + ret = wolfSSL_BIO_SSL_write(bio, data, len, front); + } + } + + if (bio && bio->type == WOLFSSL_BIO_MD) { + if (bio->next != NULL) { /* data passing through MD BIO */ + ret = wolfSSL_BIO_MD_write(bio, data, len); + } + } + #endif /* WOLFCRYPT_ONLY */ + + /* advance to the next bio in list */ + bio = bio->next; + } + + if (frmt != NULL) { + XFREE(frmt, front->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + /* info cb, user can override return value */ + if (front != NULL && front->infoCb != NULL) { + ret = (int)front->infoCb(front, + WOLFSSL_BIO_CB_WRITE | WOLFSSL_BIO_CB_RETURN, + (const char*)data, 0, 0, ret); + } + + if (retB64 != 0) + return retB64; + else + return ret; +} + + +/* Wrapper for other BIO type functions, expected to grow as OpenSSL compatibility + * layer grows. + * + * return info. specific to the cmd that is passed in. + */ +#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) +long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bio, int cmd, long larg, void *parg) +{ + long ret; + + (void)larg; /* not currently used */ + + WOLFSSL_ENTER("wolfSSL_BIO_ctrl"); + + if (bio && bio->method && bio->method->ctrlCb) { + return bio->method->ctrlCb(bio, cmd, larg, parg); + } + + switch(cmd) { + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: + ret = (long)wolfSSL_BIO_ctrl_pending(bio); + break; + case BIO_CTRL_INFO: + ret = (long)wolfSSL_BIO_get_mem_data(bio, parg); + break; + case BIO_CTRL_FLUSH: + ret = (long)wolfSSL_BIO_flush(bio); + break; + case BIO_CTRL_RESET: + ret = (long)wolfSSL_BIO_reset(bio); + break; + default: + WOLFSSL_MSG("CMD not yet implemented"); + ret = WOLFSSL_FAILURE; + break; + } + return ret; +} +#endif + + +/* helper function for wolfSSL_BIO_gets + * size till a newline is hit + * returns the number of bytes including the new line character + */ +static int wolfSSL_getLineLength(char* in, int inSz) +{ + int i; + + for (i = 0; i < inSz; i++) { + if (in[i] == '\n') { + return i + 1; /* includes new line character */ + } + } + + return inSz; /* rest of buffer is all one line */ +} + + +/* Gets the next line from bio. Goes until a new line character or end of + * buffer is reached. + * + * bio the structure to read a new line from + * buf buffer to hold the result + * sz the size of "buf" buffer + * + * returns the size of the result placed in buf on success and a 0 or negative + * value in an error case. + */ +int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz) +{ + int ret = WOLFSSL_BIO_UNSET; + + WOLFSSL_ENTER("wolfSSL_BIO_gets"); + + if (bio == NULL || buf == NULL) { + return WOLFSSL_FAILURE; + } + + /* not enough space for character plus terminator */ + if (sz <= 1) { + return 0; + } + + /* info cb, abort if user returns <= 0*/ + if (bio->infoCb != NULL) { + ret = (int)bio->infoCb(bio, WOLFSSL_BIO_CB_GETS, buf, sz, 0, 1); + if (ret <= 0) { + return ret; + } + } + + /* check if is custom method */ + if (bio->method && bio->method->getsCb) { + return bio->method->getsCb(bio, buf, sz); + } + + switch (bio->type) { +#ifndef NO_FILESYSTEM + case WOLFSSL_BIO_FILE: + if (((XFILE)bio->ptr) == XBADFILE) { + return WOLFSSL_BIO_ERROR; + } + + #if defined(MICRIUM) || defined(LSR_FS) || defined(EBSNET) + WOLFSSL_MSG("XFGETS not ported for this system yet"); + ret = XFGETS(buf, sz, (XFILE)bio->ptr); + #else + if (XFGETS(buf, sz, (XFILE)bio->ptr) != NULL) { + ret = (int)XSTRLEN(buf); + } + else { + ret = WOLFSSL_BIO_ERROR; + } + #endif + break; +#endif /* NO_FILESYSTEM */ + case WOLFSSL_BIO_MEMORY: + { + const byte* c; + int cSz; + cSz = wolfSSL_BIO_pending(bio); + if (cSz == 0) { + ret = 0; /* Nothing to read */ + buf[0] = '\0'; + break; + } + + if (wolfSSL_BIO_get_mem_data(bio, (void*)&c) <= 0) { + ret = WOLFSSL_BIO_ERROR; + break; + } + + cSz = wolfSSL_getLineLength((char*)c, cSz); + /* check case where line was bigger then buffer and buffer + * needs end terminator */ + if (cSz >= sz) { + cSz = sz - 1; + buf[cSz] = '\0'; + } + else { + /* not minus 1 here because placing terminator after + msg and have checked that sz is large enough */ + buf[cSz] = '\0'; + } + + ret = wolfSSL_BIO_MEMORY_read(bio, (void*)buf, cSz); + /* ret is read after the switch statement */ + break; + } + case WOLFSSL_BIO_BIO: + { + char* c; + int cSz; + cSz = wolfSSL_BIO_nread0(bio, &c); + if (cSz == 0) { + ret = 0; /* Nothing to read */ + buf[0] = '\0'; + break; + } + + cSz = wolfSSL_getLineLength(c, cSz); + /* check case where line was bigger then buffer and buffer + * needs end terminator */ + if (cSz >= sz) { + cSz = sz - 1; + buf[cSz] = '\0'; + } + else { + /* not minus 1 here because placing terminator after + msg and have checked that sz is large enough */ + buf[cSz] = '\0'; + } + + ret = wolfSSL_BIO_nread(bio, &c, cSz); + if (ret > 0 && ret < sz) { + XMEMCPY(buf, c, ret); + } + break; + } + +#ifndef WOLFCRYPT_ONLY + /* call final on hash */ + case WOLFSSL_BIO_MD: + if (wolfSSL_EVP_MD_CTX_size((WOLFSSL_EVP_MD_CTX*)bio->ptr) > sz) { + WOLFSSL_MSG("Output buffer was too small for digest"); + ret = WOLFSSL_FAILURE; + } + else { + unsigned int szOut = 0; + ret = wolfSSL_EVP_DigestFinal((WOLFSSL_EVP_MD_CTX*)bio->ptr, + (unsigned char*)buf, &szOut); + if (ret == WOLFSSL_SUCCESS) { + ret = szOut; + } + } + break; +#endif /* WOLFCRYPT_ONLY */ + + default: + WOLFSSL_MSG("BIO type not supported yet with wolfSSL_BIO_gets"); + } + + /* info cb, user can override return value */ + if (bio->infoCb != NULL) { + ret = (int)bio->infoCb(bio, WOLFSSL_BIO_CB_GETS | WOLFSSL_BIO_CB_RETURN, + buf, sz, 0, ret); + } + + return ret; +} + + +/* Writes a null terminated string to bio. + * + * bio the structure to write to + * buf buffer to holding input string + * + * returns the size of the result placed in bio on success and a 0 or negative + * value in an error case. -2 is returned if the implementation is not + * supported for the BIO type. + */ +int wolfSSL_BIO_puts(WOLFSSL_BIO* bio, const char* buf) +{ + int sz; + + if (bio == NULL || buf == NULL) { + return WOLFSSL_FATAL_ERROR; + } + + /* check if is custom method */ + if (bio->method && bio->method->putsCb) { + return bio->method->putsCb(bio, buf); + } + + sz = (int)XSTRLEN(buf); + if (sz <= 0) { + return WOLFSSL_FATAL_ERROR; + } + + return wolfSSL_BIO_write(bio, buf, sz); +} + + +/* searches through bio list for a BIO of type "type" + * returns NULL on failure to find a given type */ +WOLFSSL_BIO* wolfSSL_BIO_find_type(WOLFSSL_BIO* bio, int type) +{ + WOLFSSL_BIO* local = NULL; + WOLFSSL_BIO* current; + + WOLFSSL_ENTER("wolfSSL_BIO_find_type"); + + if (bio == NULL) { + return local; + } + + current = bio; + while (current != NULL) { + if (current->type == type) { + WOLFSSL_MSG("Found matching WOLFSSL_BIO type"); + local = current; + break; + } + current = current->next; + } + + return local; +} + + +/* returns a pointer to the next WOLFSSL_BIO in the chain on success. + * If a failure case then NULL is returned */ +WOLFSSL_BIO* wolfSSL_BIO_next(WOLFSSL_BIO* bio) +{ + WOLFSSL_ENTER("wolfSSL_BIO_next"); + + if (bio == NULL) { + WOLFSSL_MSG("Bad argument passed in"); + return NULL; + } + + return bio->next; +} + +/* BIO_wpending returns the number of bytes pending to be written. */ +size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio) +{ + WOLFSSL_ENTER("BIO_wpending"); + + if (bio == NULL) + return 0; + + if (bio->type == WOLFSSL_BIO_MEMORY) { + return bio->wrSz; + } + + /* type BIO_BIO then check paired buffer */ + if (bio->type == WOLFSSL_BIO_BIO && bio->pair != NULL) { + WOLFSSL_BIO* pair = bio->pair; + return pair->wrIdx; + } + + return 0; +} + +/* Return the number of pending bytes in read and write buffers */ +size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio) +{ + WOLFSSL_ENTER("wolfSSL_BIO_ctrl_pending"); + if (bio == NULL) { + return 0; + } + + if (bio->type == WOLFSSL_BIO_MD) { + /* MD is a wrapper only get next bio */ + while (bio->next != NULL) { + bio = bio->next; + if (bio->type != WOLFSSL_BIO_MD) { + break; + } + } + } + +#ifndef WOLFCRYPT_ONLY + if (bio->type == WOLFSSL_BIO_SSL && bio->ptr != NULL) { + return (long)wolfSSL_pending((WOLFSSL*)bio->ptr); + } +#endif + + if (bio->type == WOLFSSL_BIO_MEMORY) { + return bio->wrSz; + } + + /* type BIO_BIO then check paired buffer */ + if (bio->type == WOLFSSL_BIO_BIO && bio->pair != NULL) { + WOLFSSL_BIO* pair = bio->pair; + if (pair->wrIdx > 0 && pair->wrIdx <= pair->rdIdx) { + /* in wrap around state where beginning of buffer is being + * overwritten */ + return pair->wrSz - pair->rdIdx + pair->wrIdx; + } + else { + /* simple case where has not wrapped around */ + return pair->wrIdx - pair->rdIdx; + } + } + return 0; +} + + +long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **ptr) +{ + WOLFSSL_BIO* front = bio; + long ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_BIO_get_mem_ptr"); + + if (bio == NULL || ptr == NULL) { + return WOLFSSL_FAILURE; + } + + /* start at end and work backwards to find a memory BIO in the BIO chain */ + while ((bio != NULL) && (bio->next != NULL)) { + bio = bio->next; + } + + while (bio != NULL) { + + if (bio->type == WOLFSSL_BIO_MEMORY) { + *ptr = bio->mem_buf; + ret = WOLFSSL_SUCCESS; + } + + if (bio == front) { + break; + } + bio = bio->prev; + } + + return ret; +} + +WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg) +{ + (void) bp; + (void) cmd; + (void) larg; + (void) iarg; + WOLFSSL_STUB("BIO_int_ctrl"); + return 0; +} + + +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 != WOLFSSL_BIO_BIO || size < 0) { + 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 WOLFSSL_FAILURE; + } + + bio->wrSz = (int)size; + if (bio->wrSz < 0) { + WOLFSSL_MSG("Unexpected negative size value"); + return WOLFSSL_FAILURE; + } + + if (bio->ptr != NULL) { + XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL); + } + + bio->ptr = (byte*)XMALLOC(bio->wrSz, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (bio->ptr == NULL) { + WOLFSSL_MSG("Memory allocation error"); + return WOLFSSL_FAILURE; + } + bio->num = bio->wrSz; + bio->wrIdx = 0; + bio->rdIdx = 0; + if (bio->mem_buf != NULL) { + bio->mem_buf->data = (char*)bio->ptr; + bio->mem_buf->length = bio->num; + } + + return WOLFSSL_SUCCESS; +} + + +/* Joins two BIO_BIO types. The write of b1 goes to the read of b2 and vice + * versa. Creating something similar to a two way pipe. + * Reading and writing between the two BIOs is not thread safe, they are + * expected to be used by the same thread. */ +int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2) +{ + WOLFSSL_ENTER("wolfSSL_BIO_make_bio_pair"); + + if (b1 == NULL || b2 == NULL) { + WOLFSSL_LEAVE("wolfSSL_BIO_make_bio_pair", BAD_FUNC_ARG); + return WOLFSSL_FAILURE; + } + + /* both are expected to be of type BIO and not already paired */ + if (b1->type != WOLFSSL_BIO_BIO || b2->type != WOLFSSL_BIO_BIO || + b1->pair != NULL || b2->pair != NULL) { + WOLFSSL_MSG("Expected type BIO and not already paired"); + return WOLFSSL_FAILURE; + } + + /* set default write size if not already set */ + if (b1->ptr == NULL && wolfSSL_BIO_set_write_buf_size(b1, + WOLFSSL_BIO_SIZE) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + if (b2->ptr == NULL && wolfSSL_BIO_set_write_buf_size(b2, + WOLFSSL_BIO_SIZE) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + b1->pair = b2; + b2->pair = b1; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b) +{ + WOLFSSL_ENTER("wolfSSL_BIO_ctrl_reset_read_request"); + + if (b == NULL || b->type == WOLFSSL_BIO_MEMORY) { + return SSL_FAILURE; + } + + b->readRq = 0; + + return WOLFSSL_SUCCESS; +} + + +/* Does not advance read index pointer */ +int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf) +{ + WOLFSSL_ENTER("wolfSSL_BIO_nread0"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return 0; + } + + /* if paired read from pair */ + if (bio->pair != NULL) { + WOLFSSL_BIO* pair = bio->pair; + + /* case where have wrapped around write buffer */ + *buf = (char*)pair->ptr + pair->rdIdx; + if (pair->wrIdx > 0 && pair->rdIdx >= pair->wrIdx) { + return pair->wrSz - pair->rdIdx; + } + else { + return pair->wrIdx - pair->rdIdx; + } + } + + return 0; +} + + +/* similar to wolfSSL_BIO_nread0 but advances the read index */ +int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num) +{ + int sz = WOLFSSL_BIO_UNSET; + + WOLFSSL_ENTER("wolfSSL_BIO_nread"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return WOLFSSL_FAILURE; + } + + if (bio->type == WOLFSSL_BIO_MEMORY) { + return SSL_FAILURE; + } + + if (bio->pair != NULL) { + /* special case if asking to read 0 bytes */ + if (num == 0) { + *buf = (char*)bio->pair->ptr + bio->pair->rdIdx; + return 0; + } + + /* get amount able to read and set buffer pointer */ + sz = wolfSSL_BIO_nread0(bio, buf); + if (sz == 0) { + return WOLFSSL_BIO_ERROR; + } + + if (num < sz) { + sz = num; + } + bio->pair->rdIdx += sz; + + /* check if have read to the end of the buffer and need to reset */ + if (bio->pair->rdIdx == bio->pair->wrSz) { + bio->pair->rdIdx = 0; + if (bio->pair->wrIdx == bio->pair->wrSz) { + bio->pair->wrIdx = 0; + } + } + + /* check if read up to write index, if so then reset index */ + if (bio->pair->rdIdx == bio->pair->wrIdx) { + bio->pair->rdIdx = 0; + bio->pair->wrIdx = 0; + } + } + + return sz; +} + + +int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num) +{ + int sz = WOLFSSL_BIO_UNSET; + + WOLFSSL_ENTER("wolfSSL_BIO_nwrite"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return 0; + } + + if (bio->type != WOLFSSL_BIO_BIO) { + return SSL_FAILURE; + } + + if (bio->pair != NULL) { + if (num == 0) { + *buf = (char*)bio->ptr + bio->wrIdx; + return 0; + } + + if (bio->wrIdx < bio->rdIdx) { + /* if wrapped around only write up to read index. In this case + * rdIdx is always greater then wrIdx so sz will not be negative. */ + sz = bio->rdIdx - bio->wrIdx; + } + else if (bio->rdIdx > 0 && bio->wrIdx == bio->rdIdx) { + return WOLFSSL_BIO_ERROR; /* no more room to write */ + } + else { + /* write index is past read index so write to end of buffer */ + sz = bio->wrSz - bio->wrIdx; + + if (sz <= 0) { + /* either an error has occurred with write index or it is at the + * end of the write buffer. */ + if (bio->rdIdx == 0) { + /* no more room, nothing has been read */ + return WOLFSSL_BIO_ERROR; + } + + bio->wrIdx = 0; + + /* check case where read index is not at 0 */ + if (bio->rdIdx > 0) { + sz = bio->rdIdx; /* can write up to the read index */ + } + else { + sz = bio->wrSz; /* no restriction other then buffer size */ + } + } + } + + if (num < sz) { + sz = num; + } + *buf = (char*)bio->ptr + bio->wrIdx; + bio->wrIdx += sz; + + /* if at the end of the buffer and space for wrap around then set + * write index back to 0 */ + if (bio->wrIdx == bio->wrSz && bio->rdIdx > 0) { + bio->wrIdx = 0; + } + } + + return sz; +} + + +/* Reset BIO to initial state */ +int wolfSSL_BIO_reset(WOLFSSL_BIO *bio) +{ + WOLFSSL_ENTER("wolfSSL_BIO_reset"); + + if (bio == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + /* -1 is consistent failure even for FILE type */ + return WOLFSSL_BIO_ERROR; + } + + switch (bio->type) { + #ifndef NO_FILESYSTEM + case WOLFSSL_BIO_FILE: + XREWIND((XFILE)bio->ptr); + return 0; + #endif + + case WOLFSSL_BIO_BIO: + bio->rdIdx = 0; + bio->wrIdx = 0; + return 0; + + case WOLFSSL_BIO_MEMORY: + bio->rdIdx = 0; + bio->wrIdx = 0; + bio->wrSz = 0; + XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->ptr = NULL; + bio->num = 0; + if (bio->mem_buf != NULL) { + bio->mem_buf->data = (char*)bio->ptr; + bio->mem_buf->length = bio->num; + } + return 0; + +#ifndef WOLFCRYPT_ONLY + case WOLFSSL_BIO_MD: + if (bio->ptr != NULL) { + const WOLFSSL_EVP_MD* md = + wolfSSL_EVP_MD_CTX_md((WOLFSSL_EVP_MD_CTX*)bio->ptr); + wolfSSL_EVP_MD_CTX_init((WOLFSSL_EVP_MD_CTX*)bio->ptr); + wolfSSL_EVP_DigestInit((WOLFSSL_EVP_MD_CTX*)bio->ptr, md); + } + return 0; +#endif /* WOLFCRYPT_ONLY */ + + default: + WOLFSSL_MSG("Unknown BIO type needs added to reset function"); + } + + return WOLFSSL_BIO_ERROR; +} + +#ifndef NO_FILESYSTEM +long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_fp"); + + if (bio == NULL || fp == XBADFILE) { + WOLFSSL_LEAVE("wolfSSL_BIO_set_fp", BAD_FUNC_ARG); + return WOLFSSL_FAILURE; + } + + if (bio->type != WOLFSSL_BIO_FILE) { + return WOLFSSL_FAILURE; + } + + bio->shutdown = (byte)c; + bio->ptr = (XFILE)fp; + + return WOLFSSL_SUCCESS; +} + + +long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp) +{ + WOLFSSL_ENTER("wolfSSL_BIO_get_fp"); + + if (bio == NULL || fp == XBADFILE) { + return WOLFSSL_FAILURE; + } + + if (bio->type != WOLFSSL_BIO_FILE) { + return SSL_FAILURE; + } + + *fp = (XFILE)bio->ptr; + + return WOLFSSL_SUCCESS; +} + +/* overwrites file */ +int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name) +{ + WOLFSSL_ENTER("wolfSSL_BIO_write_filename"); + + if (bio == NULL || name == NULL) { + return WOLFSSL_FAILURE; + } + + if (bio->type == WOLFSSL_BIO_FILE) { + if (((XFILE)bio->ptr) != XBADFILE && bio->shutdown == BIO_CLOSE) { + XFCLOSE((XFILE)bio->ptr); + } + + bio->ptr = XFOPEN(name, "w"); + if (((XFILE)bio->ptr) == XBADFILE) { + return WOLFSSL_FAILURE; + } + bio->shutdown = BIO_CLOSE; + + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; +} + + +int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs) +{ + WOLFSSL_ENTER("wolfSSL_BIO_seek"); + + if (bio == NULL) { + return -1; + } + + /* offset ofs from beginning of file */ + if (bio->type == WOLFSSL_BIO_FILE && + XFSEEK((XFILE)bio->ptr, ofs, SEEK_SET) < 0) { + return -1; + } + + return 0; +} +#endif /* NO_FILESYSTEM */ + + +long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_mem_eof_return"); + + if (bio != NULL) { + bio->eof = v; + } + + return 0; +} + +int wolfSSL_BIO_get_len(WOLFSSL_BIO *bio) +{ + int len; +#ifndef NO_FILESYSTEM + long memSz = 0, curr = 0; + XFILE file; +#endif + + WOLFSSL_ENTER("wolfSSL_BIO_get_len"); + + if ((len = wolfSSL_BIO_pending(bio)) > 0) { + } +#ifndef NO_FILESYSTEM + else if (bio->type == WOLFSSL_BIO_FILE) { + if (wolfSSL_BIO_get_fp(bio, &file) != WOLFSSL_SUCCESS) + len = BAD_FUNC_ARG; + if (len == 0) { + curr = XFTELL(file); + if (curr < 0) { + len = WOLFSSL_BAD_FILE; + } + if (XFSEEK(file, 0, XSEEK_END) != 0) + len = WOLFSSL_BAD_FILE; + } + if (len == 0) { + memSz = XFTELL(file); + if (memSz > MAX_WOLFSSL_FILE_SIZE || memSz < 0) + len = WOLFSSL_BAD_FILE; + } + if (len == 0) { + memSz -= curr; + len = (int)memSz; + if (XFSEEK(file, curr, SEEK_SET) != 0) + len = WOLFSSL_BAD_FILE; + } + } +#endif + return len; +} + + +void wolfSSL_BIO_set_callback(WOLFSSL_BIO *bio, wolf_bio_info_cb callback_func) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_callback"); + + if (bio != NULL) { + bio->infoCb = callback_func; + } +} + + +wolf_bio_info_cb wolfSSL_BIO_get_callback(WOLFSSL_BIO *bio) +{ + WOLFSSL_ENTER("wolfSSL_BIO_get_callback"); + + if (bio != NULL) { + return bio->infoCb; + } + + return NULL; +} + + +void wolfSSL_BIO_set_callback_arg(WOLFSSL_BIO *bio, char *arg) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_callback_arg"); + + if (bio != NULL) { + bio->infoArg = arg; + } +} + + +char* wolfSSL_BIO_get_callback_arg(const WOLFSSL_BIO *bio) +{ + WOLFSSL_ENTER("wolfSSL_BIO_get_callback_arg"); + + if (bio != NULL) { + return bio->infoArg; + } + + return NULL; +} + + +/* store a user pointer in the WOLFSSL_BIO structure */ +void wolfSSL_BIO_set_data(WOLFSSL_BIO* bio, void *ptr) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_data"); + + if (bio != NULL) { + bio->usrCtx = ptr; + } +} + + +void* wolfSSL_BIO_get_data(WOLFSSL_BIO* bio) +{ + WOLFSSL_ENTER("wolfSSL_BIO_get_data"); + + if (bio != NULL) + return bio->usrCtx; + + WOLFSSL_MSG("WOLFSSL_BIO was null"); + return NULL; +} + +/* If flag is 0 then blocking is set, if 1 then non blocking. + * Always returns 1 + */ +long wolfSSL_BIO_set_nbio(WOLFSSL_BIO* bio, long on) +{ + #ifndef WOLFSSL_DTLS + (void)on; + #endif + WOLFSSL_ENTER("wolfSSL_BIO_set_nbio"); + + switch (bio->type) { + case WOLFSSL_BIO_SOCKET: + #ifdef XFCNTL + { + int flag = XFCNTL(bio->num, F_GETFL, 0); + if (on) + XFCNTL(bio->num, F_SETFL, flag | O_NONBLOCK); + else + XFCNTL(bio->num, F_SETFL, flag & ~O_NONBLOCK); + } + #endif + break; + case WOLFSSL_BIO_SSL: + #ifdef WOLFSSL_DTLS + wolfSSL_dtls_set_using_nonblock((WOLFSSL*)bio->ptr, (int)on); + #endif + break; + + default: + WOLFSSL_MSG("Unsupported bio type for non blocking"); + break; + } + + return 1; +} + + + +/* creates a new custom WOLFSSL_BIO_METHOD */ +WOLFSSL_BIO_METHOD *wolfSSL_BIO_meth_new(int type, const char *name) +{ + WOLFSSL_BIO_METHOD* meth; + + WOLFSSL_ENTER("wolfSSL_BIO_meth_new"); + + meth = (WOLFSSL_BIO_METHOD*)XMALLOC(sizeof(WOLFSSL_BIO_METHOD), NULL, + DYNAMIC_TYPE_OPENSSL); + if (meth == NULL) { + WOLFSSL_MSG("Error allocating memory for WOLFSSL_BIO_METHOD"); + return NULL; + } + XMEMSET(meth, 0, sizeof(WOLFSSL_BIO_METHOD)); + meth->type = (byte)type; + XSTRNCPY(meth->name, name, MAX_BIO_METHOD_NAME - 1); + + return meth; +} + + +void wolfSSL_BIO_meth_free(WOLFSSL_BIO_METHOD *biom) +{ + WOLFSSL_ENTER("wolfSSL_BIO_meth_free"); + if (biom) { + XFREE(biom, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + + +int wolfSSL_BIO_meth_set_write(WOLFSSL_BIO_METHOD *biom, + wolfSSL_BIO_meth_write_cb biom_write) +{ + WOLFSSL_ENTER("wolfSSL_BIO_meth_set_write"); + if (biom) { + biom->writeCb = biom_write; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} + + +int wolfSSL_BIO_meth_set_read(WOLFSSL_BIO_METHOD *biom, + wolfSSL_BIO_meth_read_cb biom_read) +{ + WOLFSSL_ENTER("wolfSSL_BIO_meth_set_read"); + if (biom) { + biom->readCb = biom_read; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} + + +int wolfSSL_BIO_meth_set_puts(WOLFSSL_BIO_METHOD *biom, + wolfSSL_BIO_meth_puts_cb biom_puts) +{ + WOLFSSL_ENTER("wolfSSL_BIO_meth_set_puts"); + if (biom) { + biom->putsCb = biom_puts; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} + + +int wolfSSL_BIO_meth_set_gets(WOLFSSL_BIO_METHOD *biom, + wolfSSL_BIO_meth_gets_cb biom_gets) +{ + WOLFSSL_ENTER("wolfSSL_BIO_meth_set_gets"); + if (biom) { + biom->getsCb = biom_gets; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} + + +int wolfSSL_BIO_meth_set_ctrl(WOLFSSL_BIO_METHOD *biom, + wolfSSL_BIO_meth_ctrl_get_cb biom_ctrl) +{ + WOLFSSL_ENTER("wolfSSL_BIO_meth_set_ctrl"); + if (biom) { + biom->ctrlCb = biom_ctrl; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} + + +int wolfSSL_BIO_meth_set_create(WOLFSSL_BIO_METHOD *biom, + wolfSSL_BIO_meth_create_cb biom_create) +{ + WOLFSSL_ENTER("wolfSSL_BIO_meth_set_create"); + if (biom) { + biom->createCb = biom_create; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} + + +int wolfSSL_BIO_meth_set_destroy(WOLFSSL_BIO_METHOD *biom, + wolfSSL_BIO_meth_destroy_cb biom_destroy) +{ + WOLFSSL_STUB("wolfSSL_BIO_meth_set_destroy"); + if (biom) { + biom->freeCb = biom_destroy; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} + + +/* this compatibility function can be used for multiple BIO types */ +int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p) +{ + WOLFSSL_ENTER("wolfSSL_BIO_get_mem_data"); + + if (bio == NULL) + return WOLFSSL_FATAL_ERROR; + + if (p) { + *(byte**)p = (byte*)bio->ptr; + } + + return bio->num; +} + +int wolfSSL_BIO_pending(WOLFSSL_BIO* bio) +{ + return (int)wolfSSL_BIO_ctrl_pending(bio); +} + + +int wolfSSL_BIO_flush(WOLFSSL_BIO* bio) +{ + /* for wolfSSL no flushing needed */ + WOLFSSL_ENTER("BIO_flush"); + (void)bio; + return 1; +} +#endif /* WOLFSSL_BIO_INCLUDED */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/crl.c b/FreeRTOS-Plus/Source/WolfSSL/src/crl.c index 0f47ee1a4..a48cf9d83 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/src/crl.c +++ b/FreeRTOS-Plus/Source/WolfSSL/src/crl.c @@ -1,8 +1,8 @@ /* crl.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Name change compatibility layer no longer needs included here */ #ifdef HAVE_CONFIG_H @@ -27,48 +28,62 @@ #include +#ifndef WOLFCRYPT_ONLY #ifdef HAVE_CRL #include #include -#include -#include #include #ifdef HAVE_CRL_MONITOR - static int StopMonitor(int mfd); -#endif + #if (defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__)) + static int StopMonitor(int mfd); + #else + #error "CRL monitor only currently supported on linux or mach" + #endif +#endif /* HAVE_CRL_MONITOR */ -/* Initialze CRL members */ +/* Initialize CRL members */ int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm) { WOLFSSL_ENTER("InitCRL"); - + if(cm != NULL) + crl->heap = cm->heap; + else + crl->heap = NULL; crl->cm = cm; crl->crlList = NULL; crl->monitors[0].path = NULL; crl->monitors[1].path = NULL; #ifdef HAVE_CRL_MONITOR - crl->tid = 0; - crl->mfd = -1; /* mfd for bsd is kqueue fd, eventfd for linux */ + crl->tid = 0; + crl->mfd = -1; /* mfd for bsd is kqueue fd, eventfd for linux */ + crl->setup = 0; /* thread setup done predicate */ + if (pthread_cond_init(&crl->cond, 0) != 0) { + WOLFSSL_MSG("Pthread condition init failed"); + return BAD_COND_E; + } #endif - if (InitMutex(&crl->crlLock) != 0) - return BAD_MUTEX_E; + if (wc_InitMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("Init Mutex failed"); + return BAD_MUTEX_E; + } return 0; } -/* Initialze CRL Entry */ -static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) +/* Initialize CRL Entry */ +static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff, + int verified, void* heap) { WOLFSSL_ENTER("InitCRL_Entry"); XMEMCPY(crle->issuerHash, dcrl->issuerHash, CRL_DIGEST_SIZE); /* XMEMCPY(crle->crlHash, dcrl->crlHash, CRL_DIGEST_SIZE); - * copy the hash here if needed for optimized comparisons */ + * copy the hash here if needed for optimized comparisons */ XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE); XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE); crle->lastDateFormat = dcrl->lastDateFormat; @@ -77,23 +92,60 @@ 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); + #ifndef NO_SKID + crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet; + if (crle->extAuthKeyIdSet) + XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE); + #endif + } + else { + crle->toBeSigned = NULL; + crle->signature = NULL; + } + + (void)verified; + (void)heap; return 0; } /* Free all CRL Entry resources */ -static void FreeCRL_Entry(CRL_Entry* crle) +static void FreeCRL_Entry(CRL_Entry* crle, void* heap) { - RevokedCert* tmp = crle->certs; + RevokedCert* tmp = crle->certs; + RevokedCert* next; WOLFSSL_ENTER("FreeCRL_Entry"); - while(tmp) { - RevokedCert* next = tmp->next; - XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED); + 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; } @@ -104,19 +156,18 @@ void FreeCRL(WOLFSSL_CRL* crl, int dynamic) CRL_Entry* tmp = crl->crlList; WOLFSSL_ENTER("FreeCRL"); - if (crl->monitors[0].path) - XFREE(crl->monitors[0].path, NULL, DYNAMIC_TYPE_CRL_MONITOR); + XFREE(crl->monitors[0].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR); if (crl->monitors[1].path) - XFREE(crl->monitors[1].path, NULL, DYNAMIC_TYPE_CRL_MONITOR); + XFREE(crl->monitors[1].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR); while(tmp) { CRL_Entry* next = tmp->next; - FreeCRL_Entry(tmp); - XFREE(tmp, NULL, DYNAMIC_TYPE_CRL_ENTRY); + FreeCRL_Entry(tmp, crl->heap); + XFREE(tmp, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); tmp = next; - } + } #ifdef HAVE_CRL_MONITOR if (crl->tid != 0) { @@ -124,28 +175,25 @@ void FreeCRL(WOLFSSL_CRL* crl, int dynamic) if (StopMonitor(crl->mfd) == 0) pthread_join(crl->tid, NULL); else { - WOLFSSL_MSG("stop monitor failed, cancel instead"); - pthread_cancel(crl->tid); + WOLFSSL_MSG("stop monitor failed"); } } + pthread_cond_destroy(&crl->cond); #endif - FreeMutex(&crl->crlLock); + wc_FreeMutex(&crl->crlLock); if (dynamic) /* free self */ - XFREE(crl, NULL, DYNAMIC_TYPE_CRL); + XFREE(crl, crl->heap, DYNAMIC_TYPE_CRL); } -/* 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 (LockMutex(&crl->crlLock) != 0) { - WOLFSSL_MSG("LockMutex failed"); + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); return BAD_MUTEX_E; } @@ -154,14 +202,113 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) while (crle) { if (XMEMCMP(crle->issuerHash, cert->issuerHash, CRL_DIGEST_SIZE) == 0) { WOLFSSL_MSG("Found CRL Entry on list"); + + if (crle->verified == 0) { + Signer* ca = NULL; + #ifndef NO_SKID + byte extAuthKeyId[KEYID_SIZE]; + #endif + byte issuerHash[CRL_DIGEST_SIZE]; + byte* tbs; + 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); + #ifndef NO_SKID + XMEMCPY(extAuthKeyId, crle->extAuthKeyId, + sizeof(extAuthKeyId)); + #endif + XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash)); + + wc_UnLockMutex(&crl->crlLock); + + #ifndef NO_SKID + 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) { + XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + 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"); - if (!ValidateDate(crle->nextDate, crle->nextDateFormat, AFTER)) { - WOLFSSL_MSG("CRL next date is no longer valid"); - ret = ASN_AFTER_DATE_E; + #ifdef WOLFSSL_NO_CRL_NEXT_DATE + if (crle->nextDateFormat != ASN_OTHER_TYPE) + #endif + { + #ifndef NO_ASN_TIME + if (!XVALIDATE_DATE(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; @@ -171,126 +318,161 @@ 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; } - rc = rc->next; + rc = rc->next; } } - UnLockMutex(&crl->crlLock); + 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]; WOLFSSL_MSG("Issuing missing CRL callback"); url[0] = '\0'; - if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) { - XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz); - url[cert->extCrlInfoSz] = '\0'; - } - else { - WOLFSSL_MSG("CRL url too long"); + if (cert->extCrlInfo) { + if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) { + XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz); + url[cert->extCrlInfoSz] = '\0'; + } + else { + WOLFSSL_MSG("CRL url too long"); + } } + crl->cm->cbMissingCRL(url); } } - - return ret; + 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; WOLFSSL_ENTER("AddCRL"); - crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), NULL, DYNAMIC_TYPE_CRL_ENTRY); + crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap, DYNAMIC_TYPE_CRL_ENTRY); if (crle == NULL) { WOLFSSL_MSG("alloc CRL Entry failed"); 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, NULL, DYNAMIC_TYPE_CRL_ENTRY); + XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); return -1; } - if (LockMutex(&crl->crlLock) != 0) { - WOLFSSL_MSG("LockMutex failed"); - FreeCRL_Entry(crle); - XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY); + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); + FreeCRL_Entry(crle, crl->heap); + XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); return BAD_MUTEX_E; } crle->next = crl->crlList; crl->crlList = crle; - UnLockMutex(&crl->crlLock); + wc_UnLockMutex(&crl->crlLock); return 0; } -/* 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 verify) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; const byte* myBuffer = buff; /* if DER ok, otherwise switch */ - buffer der; + DerBuffer* der = NULL; #ifdef WOLFSSL_SMALL_STACK DecodedCRL* dcrl; #else DecodedCRL dcrl[1]; #endif - der.buffer = NULL; - WOLFSSL_ENTER("BufferLoadCRL"); if (crl == NULL || buff == NULL || sz == 0) return BAD_FUNC_ARG; - if (type == SSL_FILETYPE_PEM) { - int eccKey = 0; /* not used */ - EncryptedInfo info; - info.ctx = NULL; - - ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, &eccKey); + if (type == WOLFSSL_FILETYPE_PEM) { + #ifdef WOLFSSL_PEM_TO_DER + ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, NULL, NULL); if (ret == 0) { - myBuffer = der.buffer; - sz = der.length; + myBuffer = der->buffer; + sz = der->length; } else { WOLFSSL_MSG("Pem to Der failed"); + FreeDer(&der); return -1; } + #else + ret = NOT_COMPILED_IN; + #endif } #ifdef WOLFSSL_SMALL_STACK dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (dcrl == NULL) { - if (der.buffer) - XFREE(der.buffer, NULL, DYNAMIC_TYPE_CRL); - + FreeDer(&der); return MEMORY_E; } #endif - InitDecodedCRL(dcrl); + InitDecodedCRL(dcrl, crl->heap); ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm); - if (ret != 0) { + if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && verify == NO_VERIFY)) { 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"); } @@ -302,32 +484,82 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - if (der.buffer) - XFREE(der.buffer, NULL, DYNAMIC_TYPE_CRL); + FreeDer(&der); - return ret ? ret : SSL_SUCCESS; /* convert 0 to SSL_SUCCESS */ + return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */ } +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) +int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl) +{ + CRL_Entry *crle; + WOLFSSL_CRL *crl; + + WOLFSSL_ENTER("wolfSSL_X509_STORE_add_crl"); + if (store == NULL || newcrl == NULL) + return BAD_FUNC_ARG; + + crl = store->crl; + crle = newcrl->crlList; + + if (wc_LockMutex(&crl->crlLock) != 0) + { + WOLFSSL_MSG("wc_LockMutex failed"); + return BAD_MUTEX_E; + } + crle->next = crl->crlList; + crl->crlList = crle; + newcrl->crlList = NULL; + wc_UnLockMutex(&crl->crlLock); + + WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_crl", WOLFSSL_SUCCESS); + + return WOLFSSL_SUCCESS; +} +#endif #ifdef HAVE_CRL_MONITOR +/* Signal Monitor thread is setup, save status to setup flag, 0 on success */ +static int SignalSetup(WOLFSSL_CRL* crl, int status) +{ + int ret; + + /* signal to calling thread we're setup */ + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex crlLock failed"); + return BAD_MUTEX_E; + } + + crl->setup = status; + ret = pthread_cond_signal(&crl->cond); + + wc_UnLockMutex(&crl->crlLock); + + if (ret != 0) + return BAD_COND_E; + + return 0; +} + + /* read in new CRL entries and save new list */ static int SwapLists(WOLFSSL_CRL* crl) { int ret; CRL_Entry* newList; #ifdef WOLFSSL_SMALL_STACK - WOLFSSL_CRL* tmp; + WOLFSSL_CRL* tmp; #else WOLFSSL_CRL tmp[1]; #endif - + #ifdef WOLFSSL_SMALL_STACK tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) return MEMORY_E; -#endif +#endif if (InitCRL(tmp, crl->cm) < 0) { WOLFSSL_MSG("Init tmp CRL failed"); @@ -338,8 +570,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 @@ -350,8 +582,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 @@ -361,8 +593,8 @@ static int SwapLists(WOLFSSL_CRL* crl) } } - if (LockMutex(&crl->crlLock) != 0) { - WOLFSSL_MSG("LockMutex failed"); + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); FreeCRL(tmp, 0); #ifdef WOLFSSL_SMALL_STACK XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -376,7 +608,7 @@ static int SwapLists(WOLFSSL_CRL* crl) tmp->crlList = crl->crlList; crl->crlList = newList; - UnLockMutex(&crl->crlLock); + wc_UnLockMutex(&crl->crlLock); FreeCRL(tmp, 0); @@ -439,6 +671,7 @@ static void* DoMonitor(void* arg) crl->mfd = kqueue(); if (crl->mfd == -1) { WOLFSSL_MSG("kqueue failed"); + SignalSetup(crl, MONITOR_SETUP_E); return NULL; } @@ -446,6 +679,7 @@ static void* DoMonitor(void* arg) EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL); if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) { WOLFSSL_MSG("kevent monitor customer event failed"); + SignalSetup(crl, MONITOR_SETUP_E); close(crl->mfd); return NULL; } @@ -457,6 +691,7 @@ static void* DoMonitor(void* arg) fPEM = open(crl->monitors[0].path, XEVENT_MODE); if (fPEM == -1) { WOLFSSL_MSG("PEM event dir open failed"); + SignalSetup(crl, MONITOR_SETUP_E); close(crl->mfd); return NULL; } @@ -466,7 +701,10 @@ static void* DoMonitor(void* arg) fDER = open(crl->monitors[1].path, XEVENT_MODE); if (fDER == -1) { WOLFSSL_MSG("DER event dir open failed"); + if (fPEM != -1) + close(fPEM); close(crl->mfd); + SignalSetup(crl, MONITOR_SETUP_E); return NULL; } } @@ -479,10 +717,20 @@ static void* DoMonitor(void* arg) EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0); + /* signal to calling thread we're setup */ + if (SignalSetup(crl, 1) != 0) { + if (fPEM != -1) + close(fPEM); + if (fDER != -1) + close(fDER); + close(crl->mfd); + return NULL; + } + for (;;) { struct kevent event; int numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL); - + WOLFSSL_MSG("Got kevent"); if (numEvents == -1) { @@ -520,7 +768,7 @@ static void* DoMonitor(void* arg) #ifndef max - static INLINE int max(int a, int b) + static WC_INLINE int max(int a, int b) { return a > b ? a : b; } @@ -559,6 +807,7 @@ static void* DoMonitor(void* arg) crl->mfd = eventfd(0, 0); /* our custom shutdown event */ if (crl->mfd < 0) { WOLFSSL_MSG("eventfd failed"); + SignalSetup(crl, MONITOR_SETUP_E); return NULL; } @@ -566,6 +815,7 @@ static void* DoMonitor(void* arg) if (notifyFd < 0) { WOLFSSL_MSG("inotify failed"); close(crl->mfd); + SignalSetup(crl, MONITOR_SETUP_E); return NULL; } @@ -576,6 +826,7 @@ static void* DoMonitor(void* arg) WOLFSSL_MSG("PEM notify add watch failed"); close(crl->mfd); close(notifyFd); + SignalSetup(crl, MONITOR_SETUP_E); return NULL; } } @@ -587,6 +838,7 @@ static void* DoMonitor(void* arg) WOLFSSL_MSG("DER notify add watch failed"); close(crl->mfd); close(notifyFd); + SignalSetup(crl, MONITOR_SETUP_E); return NULL; } } @@ -597,6 +849,19 @@ static void* DoMonitor(void* arg) return NULL; #endif + /* signal to calling thread we're setup */ + if (SignalSetup(crl, 1) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + if (wd > 0) + inotify_rm_watch(notifyFd, wd); + close(crl->mfd); + close(notifyFd); + return NULL; + } + for (;;) { fd_set readfds; int result; @@ -607,7 +872,7 @@ static void* DoMonitor(void* arg) FD_SET(crl->mfd, &readfds); result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL); - + WOLFSSL_MSG("Got notify event"); if (result < 0) { @@ -620,11 +885,11 @@ static void* DoMonitor(void* arg) break; } - length = read(notifyFd, buff, 8192); + length = (int) read(notifyFd, buff, 8192); if (length < 0) { WOLFSSL_MSG("notify read problem, continue"); continue; - } + } if (SwapLists(crl) < 0) { WOLFSSL_MSG("SwapLists problem, continue"); @@ -643,42 +908,60 @@ static void* DoMonitor(void* arg) return NULL; } - -#else - -#error "CRL monitor only currently supported on linux or mach" - #endif /* MACH or linux */ /* Start Monitoring the CRL path(s) in a thread */ static int StartMonitorCRL(WOLFSSL_CRL* crl) { - pthread_attr_t attr; + int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("StartMonitorCRL"); - if (crl == NULL) + if (crl == NULL) return BAD_FUNC_ARG; if (crl->tid != 0) { WOLFSSL_MSG("Monitor thread already running"); - return MONITOR_RUNNING_E; + return ret; /* that's ok, someone already started */ } - pthread_attr_init(&attr); - - if (pthread_create(&crl->tid, &attr, DoMonitor, crl) != 0) { + if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) { WOLFSSL_MSG("Thread creation error"); return THREAD_CREATE_E; } - return SSL_SUCCESS; + /* wait for setup to complete */ + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex crlLock error"); + return BAD_MUTEX_E; + } + + while (crl->setup == 0) { + if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) { + ret = BAD_COND_E; + break; + } + } + + if (crl->setup < 0) + ret = crl->setup; /* store setup error */ + + wc_UnLockMutex(&crl->crlLock); + + if (ret < 0) { + WOLFSSL_MSG("DoMonitor setup failure"); + crl->tid = 0; /* thread already done */ + } + + return ret; } #else /* HAVE_CRL_MONITOR */ +#ifndef NO_FILESYSTEM + static int StartMonitorCRL(WOLFSSL_CRL* crl) { (void)crl; @@ -689,102 +972,122 @@ static int StartMonitorCRL(WOLFSSL_CRL* crl) return NOT_COMPILED_IN; } +#endif /* NO_FILESYSTEM */ + #endif /* HAVE_CRL_MONITOR */ +#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 (strstr(entry->d_name, ".pem") == NULL) { - WOLFSSL_MSG("not .pem file, skipping"); - continue; - } - } - else { - if (strstr(entry->d_name, ".der") == NULL && - strstr(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, + VERIFY) != 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) { + word32 pathLen; + char* pathBuf; + WOLFSSL_MSG("monitor path requested"); - if (type == SSL_FILETYPE_PEM) { - crl->monitors[0].path = strdup(path); - crl->monitors[0].type = SSL_FILETYPE_PEM; - if (crl->monitors[0].path == NULL) - ret = MEMORY_E; - } else { - crl->monitors[1].path = strdup(path); - crl->monitors[1].type = SSL_FILETYPE_ASN1; - if (crl->monitors[1].path == NULL) - ret = MEMORY_E; + pathLen = (word32)XSTRLEN(path); + pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR); + if (pathBuf) { + XSTRNCPY(pathBuf, path, pathLen+1); + + 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 = WOLFSSL_FILETYPE_PEM; + } else { + /* free old path before setting a new one */ + if (crl->monitors[1].path) { + XFREE(crl->monitors[1].path, crl->heap, + DYNAMIC_TYPE_CRL_MONITOR); + } + crl->monitors[1].path = pathBuf; + crl->monitors[1].type = WOLFSSL_FILETYPE_ASN1; + } + + if (monitor & WOLFSSL_CRL_START_MON) { + WOLFSSL_MSG("start monitoring requested"); + + ret = StartMonitorCRL(crl); + } + } + else { + ret = MEMORY_E; } - - if (monitor & WOLFSSL_CRL_START_MON) { - WOLFSSL_MSG("start monitoring requested"); - - ret = StartMonitorCRL(crl); - } } - - closedir(dir); return ret; } +#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/FreeRTOS-Plus/Source/WolfSSL/src/include.am b/FreeRTOS-Plus/Source/WolfSSL/src/include.am index 80ed4de80..a7f20deac 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/src/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/src/include.am @@ -4,14 +4,29 @@ lib_LTLIBRARIES+= src/libwolfssl.la src_libwolfssl_la_SOURCES = - src_libwolfssl_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${WOLFSSL_LIBRARY_VERSION} -src_libwolfssl_la_LIBADD = $(LIBM) +src_libwolfssl_la_LIBADD = $(LIBM) $(LIB_ADD) $(LIB_STATIC_ADD) src_libwolfssl_la_CFLAGS = -DBUILDING_WOLFSSL $(AM_CFLAGS) src_libwolfssl_la_CPPFLAGS = -DBUILDING_WOLFSSL $(AM_CPPFLAGS) -# fips first file +# install the packaged IPP libraries +if BUILD_FAST_RSA + +# Link needed IPP libraries +noinst_SCRIPTS+=IPP_links +IPP_links: + @$(IPPLINK) + +ippdir = $(libdir) +ipp_DATA = $(IPPLIBS) + +include_HEADERS+=$(IPPHEADERS) +endif # BUILD_FAST_RSA + if BUILD_FIPS + +if BUILD_FIPS_V1 +# fips first file src_libwolfssl_la_SOURCES += ctaocrypt/src/wolfcrypt_first.c src_libwolfssl_la_SOURCES += \ @@ -46,55 +61,274 @@ src_libwolfssl_la_SOURCES += ctaocrypt/src/fips_test.c src_libwolfssl_la_SOURCES += ctaocrypt/src/wolfcrypt_last.c endif +if BUILD_FIPS_V2 +# FIPSv2 first file +src_libwolfssl_la_SOURCES += \ + wolfcrypt/src/wolfcrypt_first.c + src_libwolfssl_la_SOURCES += \ wolfcrypt/src/hmac.c \ wolfcrypt/src/random.c \ - wolfcrypt/src/sha256.c \ - wolfcrypt/src/hash.c + wolfcrypt/src/sha256.c if BUILD_RSA src_libwolfssl_la_SOURCES += wolfcrypt/src/rsa.c endif +if BUILD_ECC +src_libwolfssl_la_SOURCES += wolfcrypt/src/ecc.c +endif + if BUILD_AES src_libwolfssl_la_SOURCES += wolfcrypt/src/aes.c endif +if BUILD_AESNI +src_libwolfssl_la_SOURCES += wolfcrypt/src/aes_asm.S +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/aes_gcm_asm.S +endif +endif + if BUILD_DES3 src_libwolfssl_la_SOURCES += wolfcrypt/src/des3.c endif if BUILD_SHA src_libwolfssl_la_SOURCES += wolfcrypt/src/sha.c +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha256_asm.S +endif endif if BUILD_SHA512 src_libwolfssl_la_SOURCES += wolfcrypt/src/sha512.c +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha512_asm.S +endif endif -src_libwolfssl_la_SOURCES += \ - wolfcrypt/src/logging.c \ - wolfcrypt/src/wc_port.c \ - wolfcrypt/src/error.c - -if BUILD_MEMORY -src_libwolfssl_la_SOURCES += wolfcrypt/src/memory.c +if BUILD_SHA3 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha3.c endif if BUILD_DH src_libwolfssl_la_SOURCES += wolfcrypt/src/dh.c endif +if BUILD_CMAC +src_libwolfssl_la_SOURCES += wolfcrypt/src/cmac.c +endif + +src_libwolfssl_la_SOURCES += wolfcrypt/src/fips.c \ + wolfcrypt/src/fips_test.c + +# fips last file +src_libwolfssl_la_SOURCES += wolfcrypt/src/wolfcrypt_last.c +endif + +if BUILD_FIPS_RAND +src_libwolfssl_la_SOURCES += \ + wolfcrypt/src/wolfcrypt_first.c \ + wolfcrypt/src/hmac.c \ + wolfcrypt/src/random.c \ + wolfcrypt/src/sha256.c \ + wolfcrypt/src/sha256_asm.S \ + wolfcrypt/src/fips.c \ + wolfcrypt/src/fips_test.c \ + wolfcrypt/src/wolfcrypt_last.c +endif BUILD_FIPS_RAND + +endif BUILD_FIPS + +# For wolfRand, exclude everything else. +if !BUILD_FIPS_RAND + +# For FIPSV2, exclude the wolfCrypt files included above. +# For wolfRand, exclude just a couple files. +# For old FIPS, keep the wolfCrypt versions of the +# CtaoCrypt files included above. +if !BUILD_FIPS_V2 +src_libwolfssl_la_SOURCES += wolfcrypt/src/hmac.c +endif + +# CAVP self test +if BUILD_SELFTEST +src_libwolfssl_la_SOURCES += wolfcrypt/src/selftest.c +endif + +endif !BUILD_FIPS_RAND + +src_libwolfssl_la_SOURCES += \ + wolfcrypt/src/hash.c \ + wolfcrypt/src/cpuid.c + +if !BUILD_FIPS_RAND + +if !BUILD_FIPS_V2 +if BUILD_RNG +src_libwolfssl_la_SOURCES += wolfcrypt/src/random.c +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha256.c +else +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha256.c +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha256_asm.S +endif +endif +endif + +if BUILD_AFALG +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/af_alg/afalg_hash.c +endif + +if BUILD_WOLFEVENT +src_libwolfssl_la_SOURCES += wolfcrypt/src/wolfevent.c +endif + +if BUILD_ASYNCCRYPT +src_libwolfssl_la_SOURCES += wolfcrypt/src/async.c +endif + +if !BUILD_USER_RSA +if BUILD_RSA +if BUILD_FAST_RSA +src_libwolfssl_la_SOURCES += wolfcrypt/user-crypto/src/rsa.c +else +if !BUILD_FIPS_V2 +src_libwolfssl_la_SOURCES += wolfcrypt/src/rsa.c +endif +endif +endif +endif + +if BUILD_SP +if BUILD_SP_C +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_c32.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_c64.c +endif +if BUILD_SP_X86_64 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_x86_64.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_x86_64_asm.S +endif +if BUILD_SP_ARM32 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_arm32.c +endif +if BUILD_SP_ARM_THUMB +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_armthumb.c +endif +if BUILD_SP_ARM64 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_arm64.c +endif +if BUILD_SP_INT +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_int.c +endif +if BUILD_SP_ARM_CORTEX +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_cortexm.c +endif +endif + +if !BUILD_FIPS_V2 +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 +endif +if BUILD_AFALG +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/af_alg/afalg_aes.c +endif +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_CMAC +src_libwolfssl_la_SOURCES += wolfcrypt/src/cmac.c +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_DES3 +src_libwolfssl_la_SOURCES += wolfcrypt/src/des3.c +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_SHA +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha.c +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_SHA512 +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha512.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha512-asm.S +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha512-asm.S +else +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha512.c +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha512_asm.S +endif +endif +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_SHA3 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha3.c +endif +endif + + +endif !BUILD_FIPS_RAND + +src_libwolfssl_la_SOURCES += \ + wolfcrypt/src/logging.c \ + wolfcrypt/src/wc_port.c \ + wolfcrypt/src/error.c + +if !BUILD_FIPS_RAND +src_libwolfssl_la_SOURCES += \ + wolfcrypt/src/wc_encrypt.c \ + wolfcrypt/src/signature.c \ + wolfcrypt/src/wolfmath.c +endif !BUILD_FIPS_RAND + +if BUILD_MEMORY +src_libwolfssl_la_SOURCES += wolfcrypt/src/memory.c +endif + +if !BUILD_FIPS_RAND +if !BUILD_FIPS_V2 +if BUILD_DH +src_libwolfssl_la_SOURCES += wolfcrypt/src/dh.c +endif +endif + if BUILD_ASN src_libwolfssl_la_SOURCES += wolfcrypt/src/asn.c endif +endif !BUILD_FIPS_RAND + if BUILD_CODING src_libwolfssl_la_SOURCES += wolfcrypt/src/coding.c endif +if !BUILD_FIPS_RAND + if BUILD_POLY1305 +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-poly1305.c +endif src_libwolfssl_la_SOURCES += wolfcrypt/src/poly1305.c +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/poly1305_asm.S +endif endif if BUILD_RC4 @@ -111,14 +345,18 @@ endif if BUILD_PWDBASED src_libwolfssl_la_SOURCES += wolfcrypt/src/pwdbased.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/pkcs12.c endif if BUILD_DSA src_libwolfssl_la_SOURCES += wolfcrypt/src/dsa.c endif +if !BUILD_FIPS_V2 if BUILD_AESNI -src_libwolfssl_la_SOURCES += wolfcrypt/src/aes_asm.s +src_libwolfssl_la_SOURCES += wolfcrypt/src/aes_asm.S +src_libwolfssl_la_SOURCES += wolfcrypt/src/aes_gcm_asm.S +endif endif if BUILD_CAMELLIA @@ -136,6 +374,9 @@ endif if BUILD_BLAKE2 src_libwolfssl_la_SOURCES += wolfcrypt/src/blake2b.c endif +if BUILD_BLAKE2S +src_libwolfssl_la_SOURCES += wolfcrypt/src/blake2s.c +endif if BUILD_HC128 src_libwolfssl_la_SOURCES += wolfcrypt/src/hc128.c @@ -146,7 +387,14 @@ src_libwolfssl_la_SOURCES += wolfcrypt/src/rabbit.c endif if BUILD_CHACHA +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-chacha.c +else src_libwolfssl_la_SOURCES += wolfcrypt/src/chacha.c +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/chacha_asm.S +endif +endif if BUILD_POLY1305 src_libwolfssl_la_SOURCES += wolfcrypt/src/chacha20_poly1305.c endif @@ -164,9 +412,11 @@ if BUILD_SLOWMATH src_libwolfssl_la_SOURCES += wolfcrypt/src/integer.c endif +if !BUILD_FIPS_V2 if BUILD_ECC src_libwolfssl_la_SOURCES += wolfcrypt/src/ecc.c endif +endif if BUILD_CURVE25519 src_libwolfssl_la_SOURCES += wolfcrypt/src/curve25519.c @@ -177,18 +427,57 @@ 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 +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_x25519_asm.S +else +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-curve25519.S +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519.S +else src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_operations.c endif endif +endif +endif if BUILD_GEMATH -if BUILD_CURVED25519_SMALL +if BUILD_ED25519_SMALL src_libwolfssl_la_SOURCES += wolfcrypt/src/ge_low_mem.c else src_libwolfssl_la_SOURCES += wolfcrypt/src/ge_operations.c +if !BUILD_FEMATH +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_x25519_asm.S +else +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519.S +else +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_operations.c +endif +endif +endif +endif +endif + +if BUILD_CURVE448 +src_libwolfssl_la_SOURCES += wolfcrypt/src/curve448.c +endif + +if BUILD_ED448 +src_libwolfssl_la_SOURCES += wolfcrypt/src/ed448.c +endif + +if BUILD_FE448 +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_448.c +endif + +if BUILD_GE448 +src_libwolfssl_la_SOURCES += wolfcrypt/src/ge_448.c +if !BUILD_FE448 +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_448.c endif endif @@ -200,14 +489,31 @@ if BUILD_PKCS7 src_libwolfssl_la_SOURCES += wolfcrypt/src/pkcs7.c endif +if BUILD_SRP +src_libwolfssl_la_SOURCES += wolfcrypt/src/srp.c +endif + +if BUILD_IDEA +src_libwolfssl_la_SOURCES += wolfcrypt/src/idea.c +endif + +if BUILD_AFALG +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/af_alg/wc_afalg.c +endif + +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 @@ -220,3 +526,6 @@ if BUILD_SNIFFER src_libwolfssl_la_SOURCES += src/sniffer.c endif +endif !BUILD_CRYPTONLY + +endif !BUILD_FIPS_RAND diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/internal.c b/FreeRTOS-Plus/Source/WolfSSL/src/internal.c index 75d85b130..fbdbb13a0 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/src/internal.c +++ b/FreeRTOS-Plus/Source/WolfSSL/src/internal.c @@ -1,8 +1,8 @@ /* internal.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,16 +16,37 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include +/* + * WOLFSSL_SMALL_CERT_VERIFY: + * Verify the certificate signature without using DecodedCert. Doubles up + * on some code but allows smaller peak heap memory usage. + * Cannot be used with WOLFSSL_NONBLOCK_OCSP. + * WOLFSSL_ALT_CERT_CHAINS: + * Allows CA's to be presented by peer, but not part of a valid chain. + * Default wolfSSL behavior is to require validation of all presented peer + * certificates. This also allows loading intermediate CA's as trusted + * and ignoring no signer failures for CA's up the chain to root. + */ + + +#ifdef EXTERNAL_OPTS_OPENVPN +#error EXTERNAL_OPTS_OPENVPN should not be defined\ + when building wolfSSL +#endif + +#ifndef WOLFCRYPT_ONLY + #include #include #include @@ -33,21 +54,24 @@ #ifdef NO_INLINE #include #else + #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" #endif #ifdef HAVE_NTRU - #include "ntru_crypto.h" + #include "libntruencrypt/ntru_crypto.h" #endif -#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || defined(CHACHA_AEAD_TEST) - #ifdef FREESCALE_MQX - #include - #else +#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || \ + defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG) + #ifndef NO_STDIO_FILESYSTEM #include #endif #endif @@ -56,12 +80,8 @@ #include #endif -#ifndef TRUE - #define TRUE 1 -#endif -#ifndef FALSE - #define FALSE 0 -#endif + +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } #ifdef _MSC_VER /* disable for while(0) cases at the .c level for now */ @@ -77,13 +97,11 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #error Cannot use both secure-renegotiation and renegotiation-indication #endif -static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, - const byte* input, int inSz, int type); +#ifndef WOLFSSL_NO_TLS12 #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 @@ -98,54 +116,66 @@ static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, #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) + #if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_ED448)) && !defined(WOLFSSL_NO_CLIENT_AUTH) static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32); #endif + #ifdef WOLFSSL_DTLS + static int SendHelloVerifyRequest(WOLFSSL*, const byte*, byte); + #endif /* WOLFSSL_DTLS */ #endif +#endif /* !WOLFSSL_NO_TLS12 */ #ifdef WOLFSSL_DTLS - static INLINE int DtlsCheckWindow(DtlsState* state); - static INLINE int DtlsUpdateWindow(DtlsState* state); + static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl); + static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl); #endif -typedef enum { +enum processReply { doProcessInit = 0, #ifndef NO_WOLFSSL_SERVER runProcessOldClientHello, #endif getRecordLayerHeader, getData, + verifyEncryptedMessage, + decryptMessage, + verifyMessage, runProcessingOneMessage -} processReply; +}; -#ifndef NO_OLD_TLS + +#ifndef WOLFSSL_NO_TLS12 +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) + +/* Server random bytes for TLS v1.3 described downgrade protection mechanism. */ +static const byte tls13Downgrade[7] = { + 0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44 +}; +#define TLS13_DOWNGRADE_SZ sizeof(tls13Downgrade) + +#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */ + +#if !defined(NO_OLD_TLS) && !defined(WOLFSSL_AEAD_ONLY) static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, - int content, int verify); + int padSz, int content, int verify); #endif -#ifndef NO_CERTS -static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes); +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifdef HAVE_QSH + int QSH_Init(WOLFSSL* ssl); #endif -static void PickHashSigAlgo(WOLFSSL* ssl, - const byte* hashSigAlgo, word32 hashSigAlgoSz); - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - +#ifdef WOLFSSL_RENESAS_TSIP_TLS + int tsip_useable(const WOLFSSL *ssl); + int tsip_generatePremasterSecret(); + int tsip_generateEncryptPreMasterSecret(WOLFSSL *ssl, byte *out, word32 *outSz); +#endif int IsTLS(const WOLFSSL* ssl) { if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR) @@ -159,108 +189,172 @@ int IsAtLeastTLSv1_2(const WOLFSSL* ssl) { if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR) return 1; +#ifdef WOLFSSL_DTLS if (ssl->version.major == DTLS_MAJOR && ssl->version.minor <= DTLSv1_2_MINOR) return 1; +#endif return 0; } - -#ifdef HAVE_NTRU - -static byte GetEntropy(ENTROPY_CMD cmd, byte* out) +int IsAtLeastTLSv1_3(const ProtocolVersion pv) { - /* TODO: add locking? */ - static RNG rng; + return (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR); +} - if (cmd == INIT) - return (wc_InitRng(&rng) == 0) ? 1 : 0; +static WC_INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend) +{ + (void)isSend; - if (out == NULL) + #ifdef WOLFSSL_DTLS + /* For DTLS, epoch 0 is always not encrypted. */ + if (ssl->options.dtls && !isSend && ssl->keys.curEpoch == 0) return 0; + #endif /* WOLFSSL_DTLS */ - if (cmd == GET_BYTE_OF_ENTROPY) - return (wc_RNG_GenerateBlock(&rng, out, 1) == 0) ? 1 : 0; +#ifdef WOLFSSL_TLS13 + if (isSend) + return ssl->encrypt.setup; + else + return ssl->decrypt.setup; +#else + return ssl->keys.encryptionOn; +#endif +} - if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY) { - *out = 1; - return 1; + +#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) +/* If SCTP is not enabled returns the state of the dtls option. + * If SCTP is enabled returns dtls && !sctp. */ +static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl) +{ + int result = ssl->options.dtls; + + if (result) { +#ifdef WOLFSSL_SCTP + result = !ssl->options.dtlsSctp; +#endif } + return result; +} +#endif /* DTLS || !WOLFSSL_NO_TLS12 */ + + +#ifdef HAVE_QSH +/* free all structs that where used with QSH */ +static int QSH_FreeAll(WOLFSSL* ssl) +{ + QSHKey* key = ssl->QSH_Key; + QSHKey* preKey = NULL; + QSHSecret* secret = ssl->QSH_secret; + QSHScheme* list = NULL; + QSHScheme* preList = NULL; + + /* free elements in struct */ + while (key) { + preKey = key; + if (key->pri.buffer) { + ForceZero(key->pri.buffer, key->pri.length); + XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + } + if (key->pub.buffer) + XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + key = (QSHKey*)key->next; + + /* free struct */ + XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH); + } + + + /* free all of peers QSH keys */ + key = ssl->peerQSHKey; + while (key) { + preKey = key; + if (key->pri.buffer) { + ForceZero(key->pri.buffer, key->pri.length); + XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + } + if (key->pub.buffer) + XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + key = (QSHKey*)key->next; + + /* free struct */ + XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH); + } + key = NULL; + + /* free secret information */ + if (secret) { + /* free up the QSHScheme list in QSHSecret */ + if (secret->list) + list = secret->list; + while (list) { + preList = list; + if (list->PK) + XFREE(list->PK, ssl->heap, DYNAMIC_TYPE_SECRET); + list = (QSHScheme*)list->next; + XFREE(preList, ssl->heap, DYNAMIC_TYPE_QSH); + } + + /* free secret buffers */ + if (secret->SerSi) { + 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_SECRET); + } + 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_SECRET); + } + XFREE(secret->CliSi, ssl->heap, DYNAMIC_TYPE_SECRET); + } + } + XFREE(secret, ssl->heap, DYNAMIC_TYPE_QSH); + secret = NULL; + return 0; } - -#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; -} - - -#ifdef WOLFSSL_DTLS - -static INLINE void c32to48(word32 in, byte out[6]) -{ - out[0] = 0; - out[1] = 0; - out[2] = (in >> 24) & 0xff; - out[3] = (in >> 16) & 0xff; - out[4] = (in >> 8) & 0xff; - out[5] = in & 0xff; -} - -#endif /* WOLFSSL_DTLS */ - - -/* 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) -/* 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) +#ifdef HAVE_NTRU +static WOLFSSL_GLOBAL WC_RNG* rng; +static WOLFSSL_GLOBAL wolfSSL_Mutex* rngMutex; + +static word32 GetEntropy(unsigned char* out, word32 num_bytes) { - *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2]; + int ret = 0; + + if (rng == NULL) { + if ((rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), 0, + 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_MUTEX)) == NULL) + return DRBG_OUT_OF_MEMORY; + wc_InitMutex(rngMutex); + } + + ret |= wc_LockMutex(rngMutex); + ret |= wc_RNG_GenerateBlock(rng, out, num_bytes); + ret |= wc_UnLockMutex(rngMutex); + + if (ret != 0) + return DRBG_ENTROPY_FAIL; + + return DRBG_OK; } - - -/* 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) - -/* 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 */ - +#endif /* HAVE_NTRU */ #ifdef HAVE_LIBZ @@ -328,7 +422,7 @@ static INLINE void ato32(const byte* c, word32* u32) } - /* decompress in to out, returnn out size or error */ + /* decompress in to out, return out size or error */ static int myDeCompress(WOLFSSL* ssl, byte* in,int inSz, byte* out,int outSz) { int err; @@ -348,6 +442,1140 @@ static INLINE void ato32(const byte* c, word32* u32) #endif /* HAVE_LIBZ */ +#ifdef WOLFSSL_SESSION_EXPORT +#ifdef WOLFSSL_DTLS +/* serializes the cipher specs struct for exporting */ +static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + word32 idx = 0; + CipherSpecs* specs; + + WOLFSSL_ENTER("ExportCipherSpecState"); + + if (exp == NULL || ssl == NULL) { + return BAD_FUNC_ARG; + } + + specs= &(ssl->specs); + + if (DTLS_EXPORT_SPC_SZ > len) { + return BUFFER_E; + } + + XMEMSET(exp, 0, DTLS_EXPORT_SPC_SZ); + + c16toa(specs->key_size, exp + idx); idx += OPAQUE16_LEN; + c16toa(specs->iv_size, exp + idx); idx += OPAQUE16_LEN; + c16toa(specs->block_size, exp + idx); idx += OPAQUE16_LEN; + c16toa(specs->aead_mac_size, exp + idx); idx += OPAQUE16_LEN; + exp[idx++] = specs->bulk_cipher_algorithm; + exp[idx++] = specs->cipher_type; + exp[idx++] = specs->mac_algorithm; + exp[idx++] = specs->kea; + exp[idx++] = specs->sig_algo; + exp[idx++] = specs->hash_size; + exp[idx++] = specs->pad_size; + exp[idx++] = specs->static_ecdh; + + if (idx != DTLS_EXPORT_SPC_SZ) { + WOLFSSL_MSG("DTLS_EXPORT_SPC_SZ needs updated and export version"); + return DTLS_EXPORT_VER_E; + } + + WOLFSSL_LEAVE("ExportCipherSpecState", idx); + (void)ver; + return idx; +} + + +/* serializes the key struct for exporting */ +static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver, + byte small) +{ + word32 idx = 0; + byte sz; + Keys* keys; + + WOLFSSL_ENTER("ExportKeyState"); + + if (exp == NULL || ssl == NULL) { + return BAD_FUNC_ARG; + } + + keys = &(ssl->keys); + + if (DTLS_EXPORT_MIN_KEY_SZ > len) { + WOLFSSL_MSG("Buffer not large enough for minimum key struct size"); + return BUFFER_E; + } + + XMEMSET(exp, 0, DTLS_EXPORT_MIN_KEY_SZ); + + c32toa(keys->peer_sequence_number_hi, exp + idx); idx += OPAQUE32_LEN; + c32toa(keys->peer_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; + c32toa(keys->sequence_number_hi, exp + idx); idx += OPAQUE32_LEN; + c32toa(keys->sequence_number_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->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); + idx += OPAQUE16_LEN; + + c16toa(keys->dtls_sequence_number_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->dtls_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->dtls_prev_sequence_number_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->dtls_prev_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->dtls_epoch, exp + idx); idx += OPAQUE16_LEN; + c16toa(keys->dtls_handshake_number, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->encryptSz, exp + idx); idx += OPAQUE32_LEN; + c32toa(keys->padSz, exp + idx); idx += OPAQUE32_LEN; + exp[idx++] = keys->encryptionOn; + exp[idx++] = keys->decryptedCur; + + /* from here on the buffer needs checked because is variable length that + * can be larger than DTLS_EXPORT_MIN_KEY_SZ */ + { + word32 i; + if ((OPAQUE16_LEN * 2) + idx + + (2 * (WOLFSSL_DTLS_WINDOW_WORDS * OPAQUE32_LEN)) > len) { + WOLFSSL_MSG("Buffer not large enough for WOLFSSL_DTLS_WINDOW_WORDS"); + return BUFFER_E; + } + + c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN; + for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) { + 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->peerSeq[0].prevWindow[i], exp + idx); + idx += OPAQUE32_LEN; + } + } + + if (idx >= len) { + WOLFSSL_MSG("Buffer not large enough for truncated hmac flag"); + return BUFFER_E; + } + +#ifdef HAVE_TRUNCATED_HMAC + sz = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ: ssl->specs.hash_size; + exp[idx++] = ssl->truncated_hmac; +#else + sz = ssl->specs.hash_size; + exp[idx++] = 0; /* no truncated hmac */ +#endif + + sz = (small)? 0: sz; + if (idx + (sz * 2) + OPAQUE8_LEN > len) { + WOLFSSL_MSG("Buffer not large enough for MAC secret"); + return BUFFER_E; + } + + exp[idx++] = sz; + if (sz > 0) { + #ifndef WOLFSSL_AEAD_ONLY + XMEMCPY(exp + idx, keys->client_write_MAC_secret, sz); idx += sz; + XMEMCPY(exp + idx, keys->server_write_MAC_secret, sz); idx += sz; + #else + XMEMSET(exp + idx, 0, sz); idx += sz; + XMEMSET(exp + idx, 0, sz); idx += sz; + #endif + } + + sz = (small)? 0: ssl->specs.key_size; + if (idx + (sz * 2) + OPAQUE8_LEN > len) { + WOLFSSL_MSG("Buffer not large enough for write key"); + return BUFFER_E; + } + + exp[idx++] = sz; + if (sz > 0) { + XMEMCPY(exp + idx, keys->client_write_key, sz); idx += sz; + XMEMCPY(exp + idx, keys->server_write_key, sz); idx += sz; + } + + sz = (small)? 0: ssl->specs.iv_size; + if (idx + (sz * 2) + OPAQUE8_LEN + AEAD_MAX_EXP_SZ > len) { + WOLFSSL_MSG("Buffer not large enough for IVs"); + return BUFFER_E; + } + + exp[idx++] = sz; + if (sz > 0) { + XMEMCPY(exp + idx, keys->client_write_IV, sz); idx += sz; + XMEMCPY(exp + idx, keys->server_write_IV, sz); idx += sz; + } + XMEMCPY(exp + idx, keys->aead_exp_IV, AEAD_MAX_EXP_SZ); + idx += AEAD_MAX_EXP_SZ; + + sz = (small)? 0: AEAD_MAX_IMP_SZ; + if (idx + (sz * 2) + OPAQUE8_LEN > len) { + WOLFSSL_MSG("Buffer not large enough for imp IVs"); + return BUFFER_E; + } + exp[idx++] = sz; + if (sz > 0) { + XMEMCPY(exp + idx, keys->aead_enc_imp_IV, sz); idx += sz; + XMEMCPY(exp + idx, keys->aead_dec_imp_IV, sz); idx += sz; + } + + /* DTLS_EXPORT_KEY_SZ is max value. idx size can vary */ + if (idx > DTLS_EXPORT_KEY_SZ) { + WOLFSSL_MSG("DTLS_EXPORT_KEY_SZ needs updated and export version"); + return DTLS_EXPORT_VER_E; + } + + WOLFSSL_LEAVE("ExportKeyState", idx); + (void)ver; + return idx; +} + +static int ImportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + word32 idx = 0; + CipherSpecs* specs; + + WOLFSSL_ENTER("ImportCipherSpecState"); + + if (exp == NULL || ssl == NULL) { + return BAD_FUNC_ARG; + } + + specs= &(ssl->specs); + + if (DTLS_EXPORT_SPC_SZ > len) { + WOLFSSL_MSG("Buffer not large enough for max spec struct size"); + return BUFFER_E; + } + + ato16(exp + idx, &specs->key_size); idx += OPAQUE16_LEN; + ato16(exp + idx, &specs->iv_size); idx += OPAQUE16_LEN; + ato16(exp + idx, &specs->block_size); idx += OPAQUE16_LEN; + ato16(exp + idx, &specs->aead_mac_size); idx += OPAQUE16_LEN; + specs->bulk_cipher_algorithm = exp[idx++]; + specs->cipher_type = exp[idx++]; + specs->mac_algorithm = exp[idx++]; + specs->kea = exp[idx++]; + specs->sig_algo = exp[idx++]; + specs->hash_size = exp[idx++]; + specs->pad_size = exp[idx++]; + specs->static_ecdh = exp[idx++]; + + WOLFSSL_LEAVE("ImportCipherSpecState", idx); + (void)ver; + return idx; +} + + +static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + word32 idx = 0; + byte sz; + Keys* keys; + + WOLFSSL_ENTER("ImportKeyState"); + + if (exp == NULL || ssl == NULL) { + return BAD_FUNC_ARG; + } + + keys = &(ssl->keys); + + /* check minimum length -- includes byte used for size indicators */ + if (len < DTLS_EXPORT_MIN_KEY_SZ) { + WOLFSSL_MSG("Buffer not large enough for minimum expected size"); + return BUFFER_E; + } + ato32(exp + idx, &keys->peer_sequence_number_hi); idx += OPAQUE32_LEN; + ato32(exp + idx, &keys->peer_sequence_number_lo); idx += OPAQUE32_LEN; + ato32(exp + idx, &keys->sequence_number_hi); idx += OPAQUE32_LEN; + ato32(exp + idx, &keys->sequence_number_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->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); + idx += OPAQUE16_LEN; + + ato16(exp + idx, &keys->dtls_sequence_number_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->dtls_sequence_number_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->dtls_prev_sequence_number_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->dtls_prev_sequence_number_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->dtls_epoch); idx += OPAQUE16_LEN; + ato16(exp + idx, &keys->dtls_handshake_number); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->encryptSz); idx += OPAQUE32_LEN; + ato32(exp + idx, &keys->padSz); idx += OPAQUE32_LEN; + keys->encryptionOn = exp[idx++]; + keys->decryptedCur = exp[idx++]; + + { + word16 i, wordCount, wordAdj = 0; + + /* do window */ + ato16(exp + idx, &wordCount); + idx += OPAQUE16_LEN; + + if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) { + wordCount = WOLFSSL_DTLS_WINDOW_WORDS; + wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32); + } + + XMEMSET(keys->peerSeq[0].window, 0xFF, DTLS_SEQ_SZ); + for (i = 0; i < wordCount; i++) { + ato32(exp + idx, &keys->peerSeq[0].window[i]); + idx += OPAQUE32_LEN; + } + idx += wordAdj; + + /* do prevWindow */ + ato16(exp + idx, &wordCount); + idx += OPAQUE16_LEN; + + if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) { + wordCount = WOLFSSL_DTLS_WINDOW_WORDS; + wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32); + } + + XMEMSET(keys->peerSeq[0].prevWindow, 0xFF, DTLS_SEQ_SZ); + for (i = 0; i < wordCount; i++) { + ato32(exp + idx, &keys->peerSeq[0].prevWindow[i]); + idx += OPAQUE32_LEN; + } + idx += wordAdj; + + } + +#ifdef HAVE_TRUNCATED_HMAC + ssl->truncated_hmac = exp[idx++]; +#else + idx++; /* no truncated hmac */ +#endif + sz = exp[idx++]; +#ifndef WOLFSSL_AEAD_ONLY + if (sz > sizeof(keys->client_write_MAC_secret) || (sz * 2) + idx > len) { + WOLFSSL_MSG("Buffer not large enough for MAC import"); + return BUFFER_E; + } + if (sz > 0) { + XMEMCPY(keys->client_write_MAC_secret, exp + idx, sz); idx += sz; + XMEMCPY(keys->server_write_MAC_secret, exp + idx, sz); idx += sz; + } +#else + if (sz + idx > len) { + return BUFFER_E; + } + idx += sz; idx += sz; +#endif + + sz = exp[idx++]; + if (sz > sizeof(keys->client_write_key) || (sz * 2) + idx > len) { + WOLFSSL_MSG("Buffer not large enough for key import"); + return BUFFER_E; + } + if (sz > 0) { + XMEMCPY(keys->client_write_key, exp + idx, sz); idx += sz; + XMEMCPY(keys->server_write_key, exp + idx, sz); idx += sz; + } + + sz = exp[idx++]; + if (sz > sizeof(keys->client_write_IV) || (sz * 2) + idx > len) { + WOLFSSL_MSG("Buffer not large enough for write IV import"); + return BUFFER_E; + } + if (sz > 0) { + XMEMCPY(keys->client_write_IV, exp + idx, sz); idx += sz; + XMEMCPY(keys->server_write_IV, exp + idx, sz); idx += sz; + } + XMEMCPY(keys->aead_exp_IV, exp + idx, AEAD_MAX_EXP_SZ); + idx += AEAD_MAX_EXP_SZ; + + sz = exp[idx++]; + if (sz > sizeof(keys->aead_enc_imp_IV) || (sz * 2) + idx > len) { + WOLFSSL_MSG("Buffer not large enough for imp IV import"); + return BUFFER_E; + } + if (sz > 0) { + XMEMCPY(keys->aead_enc_imp_IV, exp + idx, sz); idx += sz; + XMEMCPY(keys->aead_dec_imp_IV, exp + idx, sz); idx += sz; + } + + WOLFSSL_LEAVE("ImportKeyState", idx); + (void)ver; + return idx; +} + + +/* copy over necessary information from Options struct to buffer + * On success returns size of buffer used on failure returns a negative value */ +static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + int idx = 0; + word16 zero = 0; + Options* options = &ssl->options; + + WOLFSSL_ENTER("dtls_export_new"); + + if (exp == NULL || options == NULL || len < DTLS_EXPORT_OPT_SZ) { + return BAD_FUNC_ARG; + } + + XMEMSET(exp, 0, DTLS_EXPORT_OPT_SZ); + + /* these options are kept and sent to indicate verify status and strength + * of handshake */ + exp[idx++] = options->sendVerify; + exp[idx++] = options->verifyPeer; + exp[idx++] = options->verifyNone; + exp[idx++] = options->downgrade; +#ifndef NO_DH + c16toa(options->minDhKeySz, exp + idx); idx += OPAQUE16_LEN; + c16toa(options->maxDhKeySz, exp + idx); idx += OPAQUE16_LEN; + c16toa(options->dhKeySz, exp + idx); idx += OPAQUE16_LEN; +#else + c16toa(zero, exp + idx); idx += OPAQUE16_LEN; + c16toa(zero, exp + idx); idx += OPAQUE16_LEN; + c16toa(zero, exp + idx); idx += OPAQUE16_LEN; +#endif +#ifndef NO_RSA + c16toa((word16)(options->minRsaKeySz), exp + idx); idx += OPAQUE16_LEN; +#else + c16toa(zero, exp + idx); idx += OPAQUE16_LEN; +#endif +#ifdef HAVE_ECC + c16toa((word16)(options->minEccKeySz), exp + idx); idx += OPAQUE16_LEN; +#else + c16toa(zero, exp + idx); idx += OPAQUE16_LEN; +#endif + + /* these options are kept to indicate state and behavior */ +#ifndef NO_PSK + exp[idx++] = options->havePSK; +#else + exp[idx++] = 0; +#endif + exp[idx++] = options->sessionCacheOff; + exp[idx++] = options->sessionCacheFlushOff; + exp[idx++] = options->side; + exp[idx++] = options->resuming; + exp[idx++] = options->haveSessionId; + exp[idx++] = options->tls; + exp[idx++] = options->tls1_1; + exp[idx++] = options->dtls; + exp[idx++] = options->connReset; + exp[idx++] = options->isClosed; + exp[idx++] = options->closeNotify; + exp[idx++] = options->sentNotify; + exp[idx++] = options->usingCompression; + exp[idx++] = options->haveRSA; + exp[idx++] = options->haveECC; + exp[idx++] = options->haveDH; + exp[idx++] = options->haveNTRU; + exp[idx++] = options->haveQSH; + exp[idx++] = options->haveECDSAsig; + exp[idx++] = options->haveStaticECC; + exp[idx++] = options->havePeerVerify; + exp[idx++] = options->usingPSK_cipher; + exp[idx++] = options->usingAnon_cipher; + exp[idx++] = options->sendAlertState; + exp[idx++] = options->partialWrite; + exp[idx++] = options->quietShutdown; + exp[idx++] = options->groupMessages; +#ifdef HAVE_POLY1305 + exp[idx++] = options->oldPoly; +#else + exp[idx++] = 0; +#endif +#ifdef HAVE_ANON + exp[idx++] = options->haveAnon; +#else + exp[idx++] = 0; +#endif +#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; + exp[idx++] = options->cipherSuite; + exp[idx++] = options->serverState; + exp[idx++] = options->clientState; + exp[idx++] = options->handShakeState; + exp[idx++] = options->handShakeDone; + exp[idx++] = options->minDowngrade; + exp[idx++] = options->connectState; + exp[idx++] = options->acceptState; + exp[idx++] = options->asyncState; + + /* version of connection */ + exp[idx++] = ssl->version.major; + exp[idx++] = ssl->version.minor; + + (void)zero; + + /* check if changes were made and notify of need to update export version */ + 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); + + return idx; +} + + +/* copy items from Export struct to Options struct + * On success returns size of buffer used on failure returns a negative value */ +static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + int idx = 0; + Options* options = &ssl->options; + + 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; + } + + + /* these options are kept and sent to indicate verify status and strength + * of handshake */ + options->sendVerify = exp[idx++]; + options->verifyPeer = exp[idx++]; + options->verifyNone = exp[idx++]; + options->downgrade = exp[idx++]; +#ifndef NO_DH + ato16(exp + idx, &(options->minDhKeySz)); idx += OPAQUE16_LEN; + ato16(exp + idx, &(options->maxDhKeySz)); idx += OPAQUE16_LEN; + ato16(exp + idx, &(options->dhKeySz)); idx += OPAQUE16_LEN; +#else + idx += OPAQUE16_LEN; + idx += OPAQUE16_LEN; + idx += OPAQUE16_LEN; +#endif +#ifndef NO_RSA + ato16(exp + idx, (word16*)&(options->minRsaKeySz)); idx += OPAQUE16_LEN; +#else + idx += OPAQUE16_LEN; +#endif +#ifdef HAVE_ECC + ato16(exp + idx, (word16*)&(options->minEccKeySz)); idx += OPAQUE16_LEN; +#else + idx += OPAQUE16_LEN; +#endif + + /* these options are kept to indicate state and behavior */ +#ifndef NO_PSK + options->havePSK = exp[idx++]; +#else + idx++; +#endif + options->sessionCacheOff = exp[idx++]; + options->sessionCacheFlushOff = exp[idx++]; + options->side = exp[idx++]; + options->resuming = exp[idx++]; + options->haveSessionId = exp[idx++]; + options->tls = exp[idx++]; + options->tls1_1 = exp[idx++]; + options->dtls = exp[idx++]; + options->connReset = exp[idx++]; + options->isClosed = exp[idx++]; + options->closeNotify = exp[idx++]; + options->sentNotify = exp[idx++]; + options->usingCompression = exp[idx++]; + options->haveRSA = exp[idx++]; + options->haveECC = exp[idx++]; + options->haveDH = exp[idx++]; + options->haveNTRU = exp[idx++]; + options->haveQSH = exp[idx++]; + options->haveECDSAsig = exp[idx++]; + options->haveStaticECC = exp[idx++]; + options->havePeerVerify = exp[idx++]; + options->usingPSK_cipher = exp[idx++]; + options->usingAnon_cipher = exp[idx++]; + options->sendAlertState = exp[idx++]; + options->partialWrite = exp[idx++]; + options->quietShutdown = exp[idx++]; + options->groupMessages = exp[idx++]; +#ifdef HAVE_POLY1305 + options->oldPoly = exp[idx++]; /* set when to use old rfc way of poly*/ +#else + idx++; +#endif +#ifdef HAVE_ANON + options->haveAnon = exp[idx++]; /* User wants to allow Anon suites */ +#else + idx++; +#endif +#ifdef HAVE_SESSION_TICKET + 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++]; + options->cipherSuite = exp[idx++]; + options->serverState = exp[idx++]; + options->clientState = exp[idx++]; + options->handShakeState = exp[idx++]; + options->handShakeDone = exp[idx++]; + options->minDowngrade = exp[idx++]; + options->connectState = exp[idx++]; + options->acceptState = exp[idx++]; + options->asyncState = exp[idx++]; + + /* version of connection */ + if (ssl->version.major != exp[idx++] || ssl->version.minor != exp[idx++]) { + WOLFSSL_MSG("Version mismatch ie DTLS v1 vs v1.2"); + return VERSION_ERROR; + } + + return idx; +} + +#ifndef WOLFSSL_SESSION_EXPORT_NOPEER +static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + int idx = 0; + int ipSz = DTLS_EXPORT_IP; /* start as max size */ + int fam = 0; + word16 port = 0; + char ip[DTLS_EXPORT_IP]; + + if (ver != DTLS_EXPORT_VERSION) { + WOLFSSL_MSG("Export version not supported"); + return BAD_FUNC_ARG; + } + + if (ssl == NULL || exp == NULL || len < sizeof(ip) + 3 * DTLS_EXPORT_LEN) { + return BAD_FUNC_ARG; + } + + if (ssl->ctx->CBGetPeer == NULL) { + WOLFSSL_MSG("No get peer call back set"); + return BAD_FUNC_ARG; + } + if (ssl->ctx->CBGetPeer(ssl, ip, &ipSz, &port, &fam) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Get peer callback error"); + return SOCKET_ERROR_E; + } + + /* check that ipSz/fam is not negative or too large since user can set cb */ + if (ipSz < 0 || ipSz > DTLS_EXPORT_IP || fam < 0) { + WOLFSSL_MSG("Bad ipSz or fam returned from get peer callback"); + return SOCKET_ERROR_E; + } + + c16toa((word16)fam, exp + idx); idx += DTLS_EXPORT_LEN; + c16toa((word16)ipSz, exp + idx); idx += DTLS_EXPORT_LEN; + XMEMCPY(exp + idx, ip, ipSz); idx += ipSz; + c16toa(port, exp + idx); idx += DTLS_EXPORT_LEN; + + return idx; +} +#endif /* !WOLFSSL_SESSION_EXPORT_NOPEER */ + + +static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver) +{ + word16 idx = 0; + word16 ipSz; + word16 fam; + word16 port; + char ip[DTLS_EXPORT_IP]; + + if (ver != DTLS_EXPORT_VERSION && ver != DTLS_EXPORT_VERSION_3) { + WOLFSSL_MSG("Export version not supported"); + return BAD_FUNC_ARG; + } + + if (len == 0) { + WOLFSSL_MSG("No peer info sent"); + return 0; + } + + if (ssl == NULL || buf == NULL || len < 3 * DTLS_EXPORT_LEN) { + return BAD_FUNC_ARG; + } + + /* import sin family */ + ato16(buf + idx, &fam); idx += DTLS_EXPORT_LEN; + + /* 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) { + return BUFFER_E; + } + XMEMSET(ip, 0, sizeof(ip)); + XMEMCPY(ip, buf + idx, ipSz); idx += ipSz; + 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 */ + if (ssl->ctx->CBSetPeer == NULL) { + WOLFSSL_MSG("No set peer function"); + return BAD_FUNC_ARG; + } + if (ssl->ctx->CBSetPeer(ssl, ip, ipSz, port, fam) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error setting peer info"); + return SOCKET_ERROR_E; + } + + return idx; +} + + +/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session state only + * buf is used to hold the serialized WOLFSSL struct and sz is the size of buf + * passed in. + * On success returns the size of serialized session state.*/ +int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, byte* buf, word32 sz) +{ + int ret; + word32 idx = 0; + word32 totalLen = 0; + + WOLFSSL_ENTER("wolfSSL_dtls_export_state_internal"); + + if (buf == NULL || ssl == NULL) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", BAD_FUNC_ARG); + return BAD_FUNC_ARG; + } + + totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */ + /* each of the following have a 2 byte length before data */ + totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_MIN_KEY_SZ; + if (totalLen > sz) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", BUFFER_E); + return BUFFER_E; + } + + buf[idx++] = (byte)DTLS_EXPORT_STATE_PRO; + buf[idx++] = ((byte)DTLS_EXPORT_STATE_PRO & 0xF0) | + ((byte)DTLS_EXPORT_VERSION & 0X0F); + idx += DTLS_EXPORT_LEN; /* leave room for total length */ + + /* export keys struct and dtls state -- variable length stored in ret */ + idx += DTLS_EXPORT_LEN; /* leave room for length */ + if ((ret = ExportKeyState(ssl, buf + idx, sz - idx, + DTLS_EXPORT_VERSION, 1)) < 0) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", ret); + return ret; + } + c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret; + + /* place total length of exported buffer minus 2 bytes protocol/version */ + c16toa((word16)(idx - DTLS_EXPORT_LEN), buf + DTLS_EXPORT_LEN); + +#ifdef WOLFSSL_SESSION_EXPORT_DEBUG + /* if compiled with debug options then print the version, protocol, size */ + { + char debug[256]; + XSNPRINTF(debug, sizeof(debug), "Exporting DTLS session state\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); + } +#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ + + WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", idx); + return idx; +} + + +/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session + * buf is used to hold the serialized WOLFSSL struct and sz is the size of buf + * passed in. + * On success returns the size of serialized session.*/ +int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, word32 sz) +{ + int ret; + word32 idx = 0; + word32 totalLen = 0; + + WOLFSSL_ENTER("wolfSSL_dtls_export_internal"); + + if (buf == NULL || ssl == NULL) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BAD_FUNC_ARG); + return BAD_FUNC_ARG; + } + + totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */ + /* each of the following have a 2 byte length before data */ + totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_OPT_SZ; + totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_KEY_SZ; + totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ; + totalLen += DTLS_EXPORT_LEN + ssl->buffers.dtlsCtx.peer.sz; + + if (totalLen > sz) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BUFFER_E); + return BUFFER_E; + } + + buf[idx++] = (byte)DTLS_EXPORT_PRO; + buf[idx++] = ((byte)DTLS_EXPORT_PRO & 0xF0) | + ((byte)DTLS_EXPORT_VERSION & 0X0F); + + idx += DTLS_EXPORT_LEN; /* leave spot for length */ + + c16toa((word16)DTLS_EXPORT_OPT_SZ, buf + idx); idx += DTLS_EXPORT_LEN; + if ((ret = dtls_export_new(ssl, buf + idx, sz - idx, + DTLS_EXPORT_VERSION)) < 0) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret); + return ret; + } + idx += ret; + + /* export keys struct and dtls state -- variable length stored in ret */ + idx += DTLS_EXPORT_LEN; /* leave room for length */ + if ((ret = ExportKeyState(ssl, buf + idx, sz - idx, + DTLS_EXPORT_VERSION, 0)) < 0) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret); + return ret; + } + c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret; + + /* export of cipher specs struct */ + c16toa((word16)DTLS_EXPORT_SPC_SZ, buf + idx); idx += DTLS_EXPORT_LEN; + if ((ret = ExportCipherSpecState(ssl, buf + idx, sz - idx, + DTLS_EXPORT_VERSION)) < 0) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret); + return ret; + } + idx += ret; + + /* export of dtls peer information */ + idx += DTLS_EXPORT_LEN; +#ifdef WOLFSSL_SESSION_EXPORT_NOPEER + ret = 0; /* not saving peer port/ip information */ +#else + if ((ret = ExportPeerInfo(ssl, buf + idx, sz - idx, + DTLS_EXPORT_VERSION)) < 0) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret); + return ret; + } +#endif + c16toa(ret, buf + idx - DTLS_EXPORT_LEN); + idx += ret; + + /* place total length of exported buffer minus 2 bytes protocol/version */ + c16toa((word16)(idx - DTLS_EXPORT_LEN), buf + DTLS_EXPORT_LEN); + + /* if compiled with debug options then print the version, protocol, size */ +#ifdef WOLFSSL_SESSION_EXPORT_DEBUG + { + char debug[256]; + 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); + } +#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ + + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", idx); + return idx; +} + + +/* On success return amount of buffer consumed */ +int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, byte* buf, word32 sz) +{ + word32 idx = 0; + word16 length = 0; + int version; + int ret; + + WOLFSSL_ENTER("wolfSSL_dtls_import_state_internal"); + /* check at least enough room for protocol and length */ + if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) { + WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", BAD_FUNC_ARG); + return BAD_FUNC_ARG; + } + + if (buf[idx++] != (byte)DTLS_EXPORT_STATE_PRO || + (buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) { + WOLFSSL_MSG("Incorrect protocol"); + return BAD_FUNC_ARG; + } + version = buf[idx++] & 0x0F; + + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */ + WOLFSSL_MSG("Buffer size sanity check failed"); + return BUFFER_E; + } + +#ifdef WOLFSSL_SESSION_EXPORT_DEBUG + /* if compiled with debug options then print the version, protocol, size */ + { + char debug[256]; + XSNPRINTF(debug, sizeof(debug), "Importing DTLS session state\n" + "\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n" + , (int)version, buf[0], (buf[1] >> 4), length); + WOLFSSL_MSG(debug); + } +#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ + + /* perform sanity checks and extract Options information used */ + switch (version) { + case DTLS_EXPORT_VERSION: + break; + + default: + WOLFSSL_MSG("Bad export state version"); + return BAD_FUNC_ARG; + + } + + /* perform sanity checks and extract Keys struct */ + if (DTLS_EXPORT_LEN + idx > sz) { + WOLFSSL_MSG("Import Key struct error"); + return BUFFER_E; + } + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) { + WOLFSSL_MSG("Import Key struct error"); + return BUFFER_E; + } + if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) { + WOLFSSL_MSG("Import Key struct error"); + WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", ret); + return ret; + } + idx += ret; + + WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", ret); + return ret; +} + + +/* On success return amount of buffer consumed */ +int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz) +{ + word32 idx = 0; + word16 length = 0; + int version; + int ret; + int optSz; + + WOLFSSL_ENTER("wolfSSL_dtls_import_internal"); + /* check at least enough room for protocol and length */ + if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) { + return BAD_FUNC_ARG; + } + + /* sanity check on protocol ID and size of buffer */ + if (buf[idx++] != (byte)DTLS_EXPORT_PRO || + (buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) { + /* don't increment on second idx to next get version */ + + /* check if importing state only */ + return wolfSSL_dtls_import_state_internal(ssl, buf, sz); + } + version = buf[idx++] & 0x0F; + + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */ + return BUFFER_E; + } + + /* if compiled with debug options then print the version, protocol, size */ +#ifdef WOLFSSL_SESSION_EXPORT_DEBUG + { + char debug[256]; + 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); + } +#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ + + /* perform sanity checks and extract Options information used */ + 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 != optSz) { + WOLFSSL_MSG("Import Options struct error"); + return BUFFER_E; + } + if ((ret = dtls_export_load(ssl, buf + idx, length, version)) < 0) { + WOLFSSL_MSG("Import Options struct error"); + return ret; + } + idx += length; + + /* perform sanity checks and extract Keys struct */ + if (DTLS_EXPORT_LEN + idx > sz) { + WOLFSSL_MSG("Import Key struct error"); + return BUFFER_E; + } + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) { + WOLFSSL_MSG("Import Key struct error"); + return BUFFER_E; + } + if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) { + WOLFSSL_MSG("Import Key struct error"); + return ret; + } + idx += ret; + + /* perform sanity checks and extract CipherSpecs struct */ + if (DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ + idx > sz) { + WOLFSSL_MSG("Import CipherSpecs struct error"); + return BUFFER_E; + } + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if ( length != DTLS_EXPORT_SPC_SZ) { + WOLFSSL_MSG("Import CipherSpecs struct error"); + return BUFFER_E; + } + if ((ret = ImportCipherSpecState(ssl, buf + idx, length, version)) < 0) { + WOLFSSL_MSG("Import CipherSpecs struct error"); + return ret; + } + idx += ret; + + /* perform sanity checks and extract DTLS peer info */ + if (DTLS_EXPORT_LEN + idx > sz) { + WOLFSSL_MSG("Import DTLS peer info error"); + return BUFFER_E; + } + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if (idx + length > sz) { + WOLFSSL_MSG("Import DTLS peer info error"); + return BUFFER_E; + } + if ((ret = ImportPeerInfo(ssl, buf + idx, length, version)) < 0) { + WOLFSSL_MSG("Import Peer Addr error"); + return ret; + } + idx += ret; + + SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE); + + /* set hmac function to use when verifying */ + if (ssl->options.tls == 1 || ssl->options.tls1_1 == 1 || + ssl->options.dtls == 1) { + ssl->hmac = TLS_hmac; + } + + /* make sure is a valid suite used */ + if (wolfSSL_get_cipher(ssl) == NULL) { + WOLFSSL_MSG("Can not match cipher suite imported"); + return MATCH_SUITE_ERROR; + } + + /* do not allow stream ciphers with DTLS, except for NULL cipher */ + if (ssl->specs.cipher_type == stream && + ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null) { + WOLFSSL_MSG("Can not import stream ciphers for DTLS"); + return SANITY_CIPHER_E; + } + + return idx; +} +#endif /* WOLFSSL_DTLS */ +#endif /* WOLFSSL_SESSION_EXPORT */ + + void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv) { method->version = pv; @@ -355,121 +1583,373 @@ void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv) method->downgrade = 0; } - -/* Initialze SSL context, return 0 on success */ -int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method) +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) +int InitSSL_Side(WOLFSSL* ssl, word16 side) { + if (ssl == NULL) + return BAD_FUNC_ARG; + + /* set side */ + ssl->options.side = side; + + /* reset options that are side specific */ +#ifdef HAVE_NTRU + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.haveNTRU = 1; /* always on client side */ + /* server can turn on by loading key */ + } +#endif +#ifdef HAVE_ECC + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.haveECDSAsig = 1; /* always on client side */ + ssl->options.haveECC = 1; /* server turns on with ECC key cert */ + ssl->options.haveStaticECC = 1; /* server can turn on by loading key */ + } +#elif defined(HAVE_ED25519) || defined(HAVE_ED448) + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.haveECDSAsig = 1; /* always on client side */ + ssl->options.haveECC = 1; /* server turns on with ECC key cert */ + } +#endif + +#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if ((ssl->ctx->method->version.major == SSLv3_MAJOR) && + (ssl->ctx->method->version.minor >= TLSv1_MINOR)) { + ssl->options.haveEMS = 1; + } + #ifdef WOLFSSL_DTLS + if (ssl->ctx->method->version.major == DTLS_MAJOR) + ssl->options.haveEMS = 1; + #endif /* WOLFSSL_DTLS */ + } +#endif /* HAVE_EXTENDED_MASTER && !NO_WOLFSSL_CLIENT */ + +#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) + if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) { + int ret; + ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0); + if (ret != 0) { + WOLFSSL_MSG("DTLS Cookie Secret error"); + return ret; + } + } +#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ + + return InitSSL_Suites(ssl); +} +#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ + +/* Initialize SSL context, return 0 on success */ +int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) +{ + int ret = 0; + XMEMSET(ctx, 0, sizeof(WOLFSSL_CTX)); ctx->method = method; ctx->refCount = 1; /* so either CTX_free or SSL_free can release */ ctx->heap = ctx; /* defaults to self */ ctx->timeout = WOLFSSL_SESSION_TIMEOUT; - ctx->minDowngrade = TLSv1_MINOR; /* current default */ + ctx->minDowngrade = WOLFSSL_MIN_DOWNGRADE; /* current default: TLSv1_MINOR */ - if (InitMutex(&ctx->countMutex) < 0) { + if (wc_InitMutex(&ctx->countMutex) < 0) { WOLFSSL_MSG("Mutex error on CTX init"); + ctx->err = CTX_INIT_MUTEX_E; return BAD_MUTEX_E; } #ifndef NO_DH - ctx->minDhKeySz = MIN_DHKEY_SZ; + ctx->minDhKeySz = MIN_DHKEY_SZ; + ctx->maxDhKeySz = MAX_DHKEY_SZ; +#endif +#ifndef NO_RSA + ctx->minRsaKeySz = MIN_RSAKEY_SZ; #endif - #ifdef HAVE_ECC + ctx->minEccKeySz = MIN_ECCKEY_SZ; ctx->eccTempKeySz = ECDHE_SIZE; #endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ctx->verifyDepth = MAX_CHAIN_DEPTH; +#endif +#ifdef OPENSSL_EXTRA + ctx->cbioFlag = WOLFSSL_CBIO_NONE; +#endif #ifndef WOLFSSL_USER_IO - ctx->CBIORecv = EmbedReceive; - ctx->CBIOSend = EmbedSend; - #ifdef WOLFSSL_DTLS + #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 + #elif defined WOLFSSL_UIP + ctx->CBIORecv = uIPReceive; + ctx->CBIOSend = uIPSend; + #ifdef WOLFSSL_DTLS if (method->version.major == DTLS_MAJOR) { - ctx->CBIORecv = EmbedReceiveFrom; - ctx->CBIOSend = EmbedSendTo; - ctx->CBIOCookie = EmbedGenerateCookie; + ctx->CBIOSendTo = uIPSendTo; + ctx->CBIORecvFrom = uIPRecvFrom; } - #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 ctx->CBIORecv = NetX_Receive; ctx->CBIOSend = NetX_Send; +#elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + ctx->CBIORecv = Mynewt_Receive; + ctx->CBIOSend = Mynewt_Send; +#elif defined(WOLFSSL_GNRC) + ctx->CBIORecv = GNRC_ReceiveFrom; + ctx->CBIOSend = GNRC_SendTo; #endif #ifdef HAVE_NTRU if (method->side == WOLFSSL_CLIENT_END) - ctx->haveNTRU = 1; /* always on cliet side */ + ctx->haveNTRU = 1; /* always on client side */ /* server can turn on by loading key */ #endif #ifdef HAVE_ECC if (method->side == WOLFSSL_CLIENT_END) { - ctx->haveECDSAsig = 1; /* always on cliet side */ + ctx->haveECDSAsig = 1; /* always on client side */ + ctx->haveECC = 1; /* server turns on with ECC key cert */ ctx->haveStaticECC = 1; /* server can turn on by loading key */ } +#elif defined(HAVE_ED25519) || defined(HAVE_ED448) + if (method->side == WOLFSSL_CLIENT_END) { + ctx->haveECDSAsig = 1; /* always on client side */ + ctx->haveECC = 1; /* server turns on with ECC key cert */ + } #endif -#ifdef HAVE_CAVIUM - ctx->devId = NO_CAVIUM_DEVICE; + ctx->devId = INVALID_DEVID; + +#if defined(WOLFSSL_DTLS) + #ifdef WOLFSSL_SCTP + ctx->dtlsMtuSz = MAX_RECORD_SIZE; + #elif defined(WOLFSSL_DTLS_MTU) + ctx->dtlsMtuSz = MAX_MTU; + #endif #endif #ifndef NO_CERTS - ctx->cm = wolfSSL_CertManagerNew(); + ctx->cm = wolfSSL_CertManagerNew_ex(heap); if (ctx->cm == NULL) { WOLFSSL_MSG("Bad Cert Manager New"); return BAD_CERT_MANAGER_ERROR; } + #ifdef OPENSSL_EXTRA + /* setup WOLFSSL_X509_STORE */ + ctx->x509_store.cm = ctx->cm; + #endif #endif +#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) + if (method->side == WOLFSSL_CLIENT_END) { + if ((method->version.major == SSLv3_MAJOR) && + (method->version.minor >= TLSv1_MINOR)) { + + ctx->haveEMS = 1; + } +#ifdef WOLFSSL_DTLS + if (method->version.major == DTLS_MAJOR) + ctx->haveEMS = 1; +#endif /* WOLFSSL_DTLS */ + } +#endif /* HAVE_EXTENDED_MASTER && !NO_WOLFSSL_CLIENT */ + #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT; #endif - return 0; +#ifdef HAVE_WOLF_EVENT + 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 */ + ctx->verifyDepth = MAX_CHAIN_DEPTH; + + return ret; } /* In case contexts are held in array and don't want to free actual ctx */ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) { +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && \ + defined(HAVE_TLS_EXTENSIONS) && !defined(NO_WOLFSSL_SERVER) + int i; +#endif + +#ifdef HAVE_WOLF_EVENT + wolfEventQueue_Free(&ctx->event_queue); +#endif /* HAVE_WOLF_EVENT */ + +#ifdef WOLFSSL_STATIC_MEMORY + if (ctx->onHeap == 1) { + XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD); + } + else { + XFREE(ctx->method, NULL, DYNAMIC_TYPE_METHOD); + } +#else XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD); - if (ctx->suites) +#endif + ctx->method = NULL; + if (ctx->suites) { XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES); + ctx->suites = NULL; + } #ifndef NO_DH - XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH); - XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); -#endif + XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ctx->serverDH_G.buffer = NULL; + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ctx->serverDH_P.buffer = NULL; +#endif /* !NO_DH */ + +#ifdef SINGLE_THREADED + if (ctx->rng) { + wc_FreeRng(ctx->rng); + XFREE(ctx->rng, ctx->heap, DYNAMIC_TYPE_RNG); + ctx->rng = NULL; + } +#endif /* SINGLE_THREADED */ + #ifndef NO_CERTS - XFREE(ctx->privateKey.buffer, ctx->heap, DYNAMIC_TYPE_KEY); - XFREE(ctx->certificate.buffer, ctx->heap, DYNAMIC_TYPE_CERT); - XFREE(ctx->certChain.buffer, ctx->heap, DYNAMIC_TYPE_CERT); + FreeDer(&ctx->privateKey); + FreeDer(&ctx->certificate); + #ifdef KEEP_OUR_CERT + if (ctx->ourCert && ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + ctx->ourCert = NULL; + } + #endif /* KEEP_OUR_CERT */ + FreeDer(&ctx->certChain); wolfSSL_CertManagerFree(ctx->cm); -#endif + ctx->cm = NULL; + #ifdef OPENSSL_EXTRA + /* ctx->cm was free'd so cm of x509 store should now be NULL */ + if (ctx->x509_store_pt != NULL) { + ctx->x509_store_pt->cm = NULL; + } + wolfSSL_X509_STORE_free(ctx->x509_store_pt); + 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, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->ca_names = next; + } + #endif + #if defined(OPENSSL_ALL) || 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 - TLSX_FreeAll(ctx->extensions); + TLSX_FreeAll(ctx->extensions, ctx->heap); + +#ifndef NO_WOLFSSL_SERVER +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ctx->certOcspRequest) { + FreeOcspRequest(ctx->certOcspRequest); + XFREE(ctx->certOcspRequest, ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST); + } #endif + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + for (i = 0; i < MAX_CHAIN_DEPTH; i++) { + if (ctx->chainOcspRequest[i]) { + FreeOcspRequest(ctx->chainOcspRequest[i]); + XFREE(ctx->chainOcspRequest[i], ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST); + ctx->chainOcspRequest[i] = NULL; + } + } +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ +#endif /* !NO_WOLFSSL_SERVER */ + +#endif /* HAVE_TLS_EXTENSIONS */ +#ifdef OPENSSL_EXTRA + if(ctx->alpn_cli_protos) { + XFREE((void *)ctx->alpn_cli_protos, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->alpn_cli_protos = NULL; + } +#endif +#ifdef WOLFSSL_STATIC_MEMORY + if (ctx->heap != NULL) { +#ifdef WOLFSSL_HEAP_TEST + /* avoid dereferencing a test value */ + if (ctx->heap != (void*)WOLFSSL_HEAP_TEST) +#endif + { + WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)(ctx->heap); + wc_FreeMutex(&((WOLFSSL_HEAP*)(hint->memory))->memory_mutex); + } + } +#endif /* WOLFSSL_STATIC_MEMORY */ } void FreeSSL_Ctx(WOLFSSL_CTX* ctx) { - int doFree = 0; + int refCount; - if (LockMutex(&ctx->countMutex) != 0) { - WOLFSSL_MSG("Couldn't lock count mutex"); + /* decrement CTX reference count */ + if ((refCount = SSL_CTX_RefCount(ctx, -1)) < 0) { + /* check error state, if mutex error code then mutex init failed but + * CTX was still malloc'd */ + if (ctx->err == CTX_INIT_MUTEX_E) { + SSL_CtxResourceFree(ctx); + XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX); + } return; } - ctx->refCount--; - if (ctx->refCount == 0) - doFree = 1; - UnLockMutex(&ctx->countMutex); - if (doFree) { + if (refCount == 0) { + void* heap = ctx->heap; WOLFSSL_MSG("CTX ref count down to 0, doing full free"); SSL_CtxResourceFree(ctx); - FreeMutex(&ctx->countMutex); - XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX); + wc_FreeMutex(&ctx->countMutex); +#ifdef WOLFSSL_STATIC_MEMORY + if (ctx->onHeap == 0) { + heap = NULL; + } +#endif + XFREE(ctx, heap, DYNAMIC_TYPE_CTX); + (void)heap; /* not used in some builds */ } else { (void)ctx; @@ -509,7 +1989,7 @@ void InitCiphers(WOLFSSL* ssl) ssl->encrypt.chacha = NULL; ssl->decrypt.chacha = NULL; #endif -#ifdef HAVE_POLY1305 +#if defined(HAVE_POLY1305) && defined(HAVE_ONE_TIME_AUTH) ssl->auth.poly1305 = NULL; #endif ssl->encrypt.setup = 0; @@ -517,6 +1997,10 @@ void InitCiphers(WOLFSSL* ssl) #ifdef HAVE_ONE_TIME_AUTH ssl->auth.setup = 0; #endif +#ifdef HAVE_IDEA + ssl->encrypt.idea = NULL; + ssl->decrypt.idea = NULL; +#endif } @@ -525,35 +2009,34 @@ void FreeCiphers(WOLFSSL* ssl) { (void)ssl; #ifdef BUILD_ARC4 - #ifdef HAVE_CAVIUM - if (ssl->devId != NO_CAVIUM_DEVICE) { - wc_Arc4FreeCavium(ssl->encrypt.arc4); - wc_Arc4FreeCavium(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 HAVE_CAVIUM - if (ssl->devId != NO_CAVIUM_DEVICE) { - wc_Des3_FreeCavium(ssl->encrypt.des3); - wc_Des3_FreeCavium(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 HAVE_CAVIUM - if (ssl->devId != NO_CAVIUM_DEVICE) { - wc_AesFreeCavium(ssl->encrypt.aes); - wc_AesFreeCavium(ssl->decrypt.aes); - } +#if defined(BUILD_AES) || defined(BUILD_AESGCM) /* See: InitKeys() in keys.c + * on addition of BUILD_AESGCM + * check (enc->aes, dec->aes) */ + wc_AesFree(ssl->encrypt.aes); + wc_AesFree(ssl->decrypt.aes); + #if (defined(BUILD_AESGCM) || defined(HAVE_AESCCM)) && \ + !defined(WOLFSSL_NO_TLS12) + XFREE(ssl->decrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + XFREE(ssl->encrypt.additional, 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); #endif +#ifdef CIPHER_NONCE + XFREE(ssl->decrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + XFREE(ssl->encrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER); +#endif #ifdef HAVE_CAMELLIA XFREE(ssl->encrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER); @@ -570,95 +2053,212 @@ void FreeCiphers(WOLFSSL* ssl) XFREE(ssl->encrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif -#ifdef HAVE_POLY1305 +#if defined(HAVE_POLY1305) && defined(HAVE_ONE_TIME_AUTH) XFREE(ssl->auth.poly1305, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif +#ifdef HAVE_IDEA + XFREE(ssl->encrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(ssl->decrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER) + wc_HmacFree(ssl->encrypt.hmac); + wc_HmacFree(ssl->decrypt.hmac); + XFREE(ssl->encrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(ssl->decrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif } void InitCipherSpecs(CipherSpecs* cs) { + XMEMSET(cs, 0, sizeof(CipherSpecs)); + cs->bulk_cipher_algorithm = INVALID_BYTE; cs->cipher_type = INVALID_BYTE; cs->mac_algorithm = INVALID_BYTE; cs->kea = INVALID_BYTE; cs->sig_algo = INVALID_BYTE; - - cs->hash_size = 0; - cs->static_ecdh = 0; - cs->key_size = 0; - cs->iv_size = 0; - cs->block_size = 0; } -static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, - int haveRSAsig, int haveAnon) +#if defined(USE_ECDSA_KEYSZ_HASH_ALGO) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_ECC)) +static int GetMacDigestSize(byte macAlgo) { - int idx = 0; - - if (haveECDSAsig) { - #ifdef WOLFSSL_SHA512 - suites->hashSigAlgo[idx++] = sha512_mac; - suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; - #endif - #ifdef WOLFSSL_SHA384 - suites->hashSigAlgo[idx++] = sha384_mac; - suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; - #endif - #ifndef NO_SHA256 - suites->hashSigAlgo[idx++] = sha256_mac; - suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; - #endif - #ifndef NO_SHA - suites->hashSigAlgo[idx++] = sha_mac; - suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; - #endif + switch (macAlgo) { + #ifndef NO_SHA + case sha_mac: + return WC_SHA_DIGEST_SIZE; + #endif + #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 + default: + break; } + return NOT_COMPILED_IN; +} +#endif /* USE_ECDSA_KEYSZ_HASH_ALGO */ + +static WC_INLINE void AddSuiteHashSigAlgo(Suites* suites, byte macAlgo, byte sigAlgo, + int keySz, word16* inOutIdx) +{ + int addSigAlgo = 1; + +#ifdef USE_ECDSA_KEYSZ_HASH_ALGO + if (sigAlgo == ecc_dsa_sa_algo) { + int digestSz = GetMacDigestSize(macAlgo); + /* do not add sig/algos with digest size larger than key size */ + if (digestSz <= 0 || (keySz > 0 && digestSz > keySz)) { + addSigAlgo = 0; + } + } +#else + (void)keySz; +#endif /* USE_ECDSA_KEYSZ_HASH_ALGO */ + + if (addSigAlgo) { +#ifdef WC_RSA_PSS + if (sigAlgo == rsa_pss_sa_algo) { + /* RSA PSS is sig then mac */ + suites->hashSigAlgo[*inOutIdx] = sigAlgo; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = macAlgo; + *inOutIdx += 1; + #ifdef WOLFSSL_TLS13 + /* Add the certificate algorithm as well */ + suites->hashSigAlgo[*inOutIdx] = sigAlgo; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = PSS_RSAE_TO_PSS_PSS(macAlgo); + *inOutIdx += 1; + #endif + } + else +#endif + { + suites->hashSigAlgo[*inOutIdx] = macAlgo; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = sigAlgo; + *inOutIdx += 1; + } + } +} + +void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, + int haveAnon, int tls1_2, int keySz) +{ + word16 idx = 0; + + (void)tls1_2; + (void)keySz; + +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + if (haveECDSAsig) { +#ifdef HAVE_ECC + #ifdef WOLFSSL_SHA512 + AddSuiteHashSigAlgo(suites, sha512_mac, ecc_dsa_sa_algo, keySz, &idx); + #endif + #ifdef WOLFSSL_SHA384 + AddSuiteHashSigAlgo(suites, sha384_mac, ecc_dsa_sa_algo, keySz, &idx); + #endif + #ifndef NO_SHA256 + AddSuiteHashSigAlgo(suites, sha256_mac, ecc_dsa_sa_algo, keySz, &idx); + #endif + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) + AddSuiteHashSigAlgo(suites, sha_mac, ecc_dsa_sa_algo, keySz, &idx); + #endif +#endif + #ifdef HAVE_ED25519 + AddSuiteHashSigAlgo(suites, ED25519_SA_MAJOR, ED25519_SA_MINOR, keySz, + &idx); + #endif + #ifdef HAVE_ED448 + AddSuiteHashSigAlgo(suites, ED448_SA_MAJOR, ED448_SA_MINOR, keySz, + &idx); + #endif + } +#endif /* HAVE_ECC || HAVE_ED25519 || defined(HAVE_ED448 */ if (haveRSAsig) { + #ifdef WC_RSA_PSS + if (tls1_2) { #ifdef WOLFSSL_SHA512 - suites->hashSigAlgo[idx++] = sha512_mac; - suites->hashSigAlgo[idx++] = rsa_sa_algo; + AddSuiteHashSigAlgo(suites, sha512_mac, rsa_pss_sa_algo, keySz, + &idx); #endif #ifdef WOLFSSL_SHA384 - suites->hashSigAlgo[idx++] = sha384_mac; - suites->hashSigAlgo[idx++] = rsa_sa_algo; + AddSuiteHashSigAlgo(suites, sha384_mac, rsa_pss_sa_algo, keySz, + &idx); #endif #ifndef NO_SHA256 - suites->hashSigAlgo[idx++] = sha256_mac; - suites->hashSigAlgo[idx++] = rsa_sa_algo; - #endif - #ifndef NO_SHA - suites->hashSigAlgo[idx++] = sha_mac; - suites->hashSigAlgo[idx++] = rsa_sa_algo; + AddSuiteHashSigAlgo(suites, sha256_mac, rsa_pss_sa_algo, keySz, + &idx); #endif + } + #endif + #ifdef WOLFSSL_SHA512 + AddSuiteHashSigAlgo(suites, sha512_mac, rsa_sa_algo, keySz, &idx); + #endif + #ifdef WOLFSSL_SHA384 + AddSuiteHashSigAlgo(suites, sha384_mac, rsa_sa_algo, keySz, &idx); + #endif + #ifndef NO_SHA256 + AddSuiteHashSigAlgo(suites, sha256_mac, rsa_sa_algo, keySz, &idx); + #endif + #ifdef WOLFSSL_SHA224 + AddSuiteHashSigAlgo(suites, sha224_mac, rsa_sa_algo, keySz, &idx); + #endif + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) + AddSuiteHashSigAlgo(suites, sha_mac, rsa_sa_algo, keySz, &idx); + #endif } +#ifdef HAVE_ANON if (haveAnon) { - #ifdef HAVE_ANON - suites->hashSigAlgo[idx++] = sha_mac; - suites->hashSigAlgo[idx++] = anonymous_sa_algo; - #endif + AddSuiteHashSigAlgo(suites, sha_mac, anonymous_sa_algo, keySz, &idx); } +#endif - suites->hashSigAlgoSz = (word16)idx; + (void)haveAnon; + (void)haveECDSAsig; + suites->hashSigAlgoSz = 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 haveStaticECC, int side) + word16 haveECDSAsig, word16 haveECC, + word16 haveStaticECC, int side) { 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; (void)tls; /* shut up compiler */ (void)tls1_2; + (void)dtls; (void)haveDH; (void)havePSK; (void)haveNTRU; (void)haveStaticECC; + (void)haveECC; + (void)side; + (void)haveRSA; /* some builds won't read */ + (void)haveRSAsig; /* non ecc builds won't read */ if (suites == NULL) { WOLFSSL_MSG("InitSuites pointer error"); @@ -668,67 +2268,133 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, if (suites->setSuites) return; /* trust user settings, don't override */ +#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 + +#ifdef HAVE_NULL_CIPHER + #ifdef BUILD_TLS_SHA256_SHA256 + if (tls1_3) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_SHA256_SHA256; + } + #endif + + #ifdef BUILD_TLS_SHA384_SHA384 + if (tls1_3) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_SHA384_SHA384; + } + #endif +#endif +#endif /* WOLFSSL_TLS13 */ + +#ifndef WOLFSSL_NO_TLS12 + +#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_RSA) if (side == WOLFSSL_SERVER_END && haveStaticECC) { haveRSA = 0; /* can't do RSA with ECDSA key */ - (void)haveRSA; /* some builds won't read */ } if (side == WOLFSSL_SERVER_END && haveECDSAsig) { haveRSAsig = 0; /* can't have RSA sig if signed by ECDSA */ - (void)haveRSAsig; /* non ecc builds won't read */ } +#endif /* !NO_WOLFSSL_SERVER */ #ifdef WOLFSSL_DTLS if (pv.major == DTLS_MAJOR) { + dtls = 1; tls = 1; + /* May be dead assignments dependent upon configuration */ + (void) dtls; + (void) tls; tls1_2 = pv.minor <= DTLSv1_2_MINOR; } #endif #ifdef HAVE_RENEGOTIATION_INDICATION if (side == WOLFSSL_CLIENT_END) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV; } #endif -#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA - if (tls && haveNTRU && haveRSA) { - suites->suites[idx++] = 0; - suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA; +#ifdef BUILD_TLS_QSH + if (tls) { + suites->suites[idx++] = QSH_BYTE; + suites->suites[idx++] = TLS_QSH; } #endif +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + if (tls && haveNTRU && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA; + } +#endif + #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA if (tls && haveNTRU && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_128_CBC_SHA; } #endif #ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA - if (tls && haveNTRU && haveRSA) { - suites->suites[idx++] = 0; + if (!dtls && tls && haveNTRU && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA; } #endif #ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA if (tls && haveNTRU && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA; } #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - if (tls1_2 && haveECDSAsig) { + if (tls1_2 && haveECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384; } #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - if (tls1_2 && haveECDSAsig) { + if (tls1_2 && haveECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; } @@ -750,41 +2416,41 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 if (tls1_2 && haveDH && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_GCM_SHA384; } #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 if (tls1_2 && haveDH && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256; } #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 if (tls1_2 && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_AES_256_GCM_SHA384; } #endif #ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 if (tls1_2 && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_AES_128_GCM_SHA256; } #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - if (tls1_2 && haveECDSAsig && haveStaticECC) { + if (tls1_2 && haveECC && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384; } #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - if (tls1_2 && haveECDSAsig && haveStaticECC) { + if (tls1_2 && haveECC && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256; } @@ -806,62 +2472,86 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 if (tls1_2 && haveDH && havePSK) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_GCM_SHA384; } #endif +#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA + if (tls1_2 && haveDH) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveDH) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DH_anon_WITH_AES_256_GCM_SHA384; + } +#endif + #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 if (tls1_2 && haveDH && havePSK) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_GCM_SHA256; } #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384 if (tls1_2 && havePSK) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_PSK_WITH_AES_256_GCM_SHA384; } #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 if (tls1_2 && havePSK) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_PSK_WITH_AES_128_GCM_SHA256; } #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 - if (tls1_2 && haveECDSAsig) { + if (tls1_2 && haveECC) { suites->suites[idx++] = CHACHA_BYTE; suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256; } #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - if (tls && haveRSA) { + if (tls1_2 && haveRSA) { suites->suites[idx++] = CHACHA_BYTE; suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256; } #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - if (tls && haveRSA) { + if (tls1_2 && haveRSA) { suites->suites[idx++] = CHACHA_BYTE; suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256; } #endif +/* Place as higher priority for MYSQL */ +#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA; + } +#endif +#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; } #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - if (tls1_2 && haveECDSAsig) { + if (tls1_2 && haveECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256; } @@ -875,21 +2565,21 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 - if (tls1_2 && haveECDSAsig && haveStaticECC) { + if (tls1_2 && haveECC && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256; } #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; } #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - if (tls1_2 && haveECDSAsig) { + if (tls1_2 && haveECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384; } @@ -903,63 +2593,63 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 - if (tls1_2 && haveECDSAsig && haveStaticECC) { + if (tls1_2 && haveECC && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384; } #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - if (tls && haveECDSAsig) { + if (tls && haveECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA; } #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - if (tls && haveECDSAsig && haveStaticECC) { + if (tls && haveECC && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA; } #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - if (tls && haveECDSAsig) { + if (tls && haveECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA; } #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - if (tls && haveECDSAsig && haveStaticECC) { + if (tls && haveECC && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA; } #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - if (tls && haveECDSAsig) { + if (!dtls && tls && haveECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_RC4_128_SHA; } #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA - if (tls && haveECDSAsig && haveStaticECC) { + if (!dtls && tls && haveECC && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_RC4_128_SHA; } #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - if (tls && haveECDSAsig) { + if (tls && haveECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA; } #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - if (tls && haveECDSAsig && haveStaticECC) { + if (tls && haveECC && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA; } @@ -994,14 +2684,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA - if (tls && haveRSA) { + if (!dtls && tls && haveRSA) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_RSA_WITH_RC4_128_SHA; } #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA - if (tls && haveRSAsig && haveStaticECC) { + if (!dtls && tls && haveRSAsig && haveStaticECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDH_RSA_WITH_RC4_128_SHA; } @@ -1021,15 +2711,22 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, } #endif +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM + if (tls1_2 && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM; + } +#endif + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 - if (tls1_2 && haveECDSAsig) { + if (tls1_2 && haveECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; } #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 - if (tls1_2 && haveECDSAsig) { + if (tls1_2 && haveECC) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8; } @@ -1050,113 +2747,204 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - if (tls1_2 && haveDH && haveRSA) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveDH && haveRSA) +#else + if (tls && haveDH && haveRSA) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; 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) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveDH && haveRSA) +#else + if (tls && haveDH && haveRSA) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256; } #endif +/* Place as higher priority for MYSQL testing */ +#if !defined(WOLFSSL_MYSQL_COMPATIBLE) #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA if (tls && haveDH && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA; } #endif +#endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA if (tls && haveDH && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA; } #endif +#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA; + } +#endif + #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 - if (tls1_2 && haveRSA) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveRSA) +#else + if (tls && haveRSA) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256; } #endif #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 - if (tls1_2 && haveRSA) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveRSA) +#else + if (tls && haveRSA) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256; } #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA if (tls && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA; } #endif #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA if (tls && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA; } #endif +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + if (tls1_2 && haveECC) { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = + TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA + if (tls && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_NULL_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_MD5 + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_NULL_MD5; + } +#endif + #ifdef BUILD_TLS_RSA_WITH_NULL_SHA if (tls && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA; } #endif #ifdef BUILD_TLS_RSA_WITH_NULL_SHA256 - if (tls && haveRSA) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveRSA) +#else + if (tls && haveRSA) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA256; } #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA if (tls && havePSK) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA; } #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - if (tls && haveDH && havePSK) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveDH && havePSK) +#else + if (tls && haveDH && havePSK) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CBC_SHA384; } #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 - if (tls && havePSK) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && havePSK) +#else + if (tls && havePSK) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA384; } #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - if (tls && haveDH && havePSK) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveDH && havePSK) +#else + if (tls && haveDH && havePSK) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CBC_SHA256; } #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 - if (tls && havePSK) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && havePSK) +#else + if (tls1 && havePSK) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA256; } #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA if (tls && havePSK) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA; } #endif @@ -1175,6 +2963,54 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, } #endif +#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && havePSK) +#else + if (tls && havePSK) +#endif + { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_CHACHA20_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && havePSK) +#else + if (tls && havePSK) +#endif + { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && havePSK) +#else + if (tls && havePSK) +#endif + { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && havePSK) +#else + if (tls && havePSK) +#endif + { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256; + } +#endif + #ifdef BUILD_TLS_PSK_WITH_AES_128_CCM if (tls && havePSK) { suites->suites[idx++] = ECC_BYTE; @@ -1204,168 +3040,299 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384 - if (tls && haveDH && havePSK) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveDH && havePSK) +#else + if (tls && haveDH && havePSK) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA384; } #endif #ifdef BUILD_TLS_PSK_WITH_NULL_SHA384 - if (tls && havePSK) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && havePSK) +#else + if (tls && havePSK) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA384; } #endif +#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256 +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && havePSK) +#else + if (tls && havePSK) +#endif + { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_PSK_WITH_NULL_SHA256; + } +#endif + #ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256 - if (tls && haveDH && havePSK) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveDH && havePSK) +#else + if (tls && haveDH && havePSK) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA256; } #endif #ifdef BUILD_TLS_PSK_WITH_NULL_SHA256 - if (tls && havePSK) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && havePSK) +#else + if (tls && havePSK) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA256; } #endif #ifdef BUILD_TLS_PSK_WITH_NULL_SHA if (tls && havePSK) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA; } #endif #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA - if (haveRSA ) { - suites->suites[idx++] = 0; + if (!dtls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA; } #endif #ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5 - if (haveRSA ) { - suites->suites[idx++] = 0; + if (!dtls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5; } #endif #ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA if (haveRSA ) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA; } #endif #ifdef BUILD_TLS_RSA_WITH_HC_128_MD5 - if (tls && haveRSA) { - suites->suites[idx++] = 0; + if (!dtls && tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_HC_128_MD5; } #endif #ifdef BUILD_TLS_RSA_WITH_HC_128_SHA - if (tls && haveRSA) { - suites->suites[idx++] = 0; + if (!dtls && tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_HC_128_SHA; } #endif -#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256 - if (tls && haveRSA) { - suites->suites[idx++] = 0; - suites->suites[idx++] = TLS_RSA_WITH_HC_128_B2B256; - } -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256 - if (tls && haveRSA) { - suites->suites[idx++] = 0; - suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_B2B256; - } -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256 - if (tls && haveRSA) { - suites->suites[idx++] = 0; - suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_B2B256; - } -#endif - #ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA - if (tls && haveRSA) { - suites->suites[idx++] = 0; + if (!dtls && tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_RABBIT_SHA; } #endif #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA if (tls && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA; } #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA if (tls && haveDH && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA; } #endif #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA if (tls && haveRSA) { - suites->suites[idx++] = 0; + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA; } #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++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA; } #endif #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 - if (tls && haveRSA) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveRSA) +#else + if (tls && haveRSA) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256; } #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - if (tls && haveDH && haveRSA) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveDH && haveRSA) +#else + if (tls && haveDH && haveRSA) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256; } #endif #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 - if (tls && haveRSA) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveRSA) +#else + if (tls && haveRSA) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256; } #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - if (tls && haveDH && haveRSA) { - suites->suites[idx++] = 0; +#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + if (tls1_2 && haveDH && haveRSA) +#else + if (tls && haveDH && haveRSA) +#endif + { + suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256; } #endif +#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA + if (haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = SSL_RSA_WITH_IDEA_CBC_SHA; + } +#endif + +#endif /* !WOLFSSL_NO_TLS12 */ + suites->suiteSz = idx; - InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, 0); + InitSuitesHashSigAlgo(suites, haveECDSAsig | haveECC, haveRSAsig | haveRSA, + 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 WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType) +{ + switch (input[0]) { + case NEW_SA_MAJOR: + #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; + } + else + #endif + #ifdef HAVE_ED448 + /* ED448: 0x0808 */ + if (input[1] == ED448_SA_MINOR) { + *hsType = ed448_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + else + #endif + #ifdef WC_RSA_PSS + /* PSS PSS signatures: 0x080[9-b] */ + if (input[1] >= pss_sha256 && input[1] <= pss_sha512) { + *hsType = rsa_pss_pss_algo; + *hashAlgo = PSS_PSS_HASH_TO_MAC(input[1]); + } + else + #endif + { + *hsType = input[0]; + *hashAlgo = input[1]; + } + break; + default: + *hashAlgo = input[0]; + *hsType = input[1]; + break; + } +} +#endif /* !NO_WOLFSSL_SERVER || !NO_CERTS */ + +#ifndef WOLFSSL_NO_TLS12 +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) +#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) || (!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 + #ifdef WOLFSSL_SHA224 + case sha224_mac: + return WC_HASH_TYPE_SHA224; + #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) */ +#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */ +#endif /* !WOLFSSL_NO_TLS12 */ #ifndef NO_CERTS - void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag) { (void)dynamicFlag; @@ -1373,65 +3340,65 @@ void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag) if (name != NULL) { name->name = name->staticName; name->dynamicName = 0; -#ifdef OPENSSL_EXTRA + name->sz = 0; +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) XMEMSET(&name->fullName, 0, sizeof(DecodedName)); + XMEMSET(&name->cnEntry, 0, sizeof(WOLFSSL_X509_NAME_ENTRY)); + XMEMSET(&name->extra, 0, sizeof(name->extra)); + name->cnEntry.value = &(name->cnEntry.data); /* point to internal data*/ + name->cnEntry.nid = ASN_COMMON_NAME; + name->x509 = NULL; #endif /* OPENSSL_EXTRA */ } } -void FreeX509Name(WOLFSSL_X509_NAME* name) +void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap) { if (name != NULL) { - if (name->dynamicName) - XFREE(name->name, NULL, DYNAMIC_TYPE_SUBJECT_CN); -#ifdef OPENSSL_EXTRA - if (name->fullName.fullName != NULL) - XFREE(name->fullName.fullName, NULL, DYNAMIC_TYPE_X509); -#endif /* OPENSSL_EXTRA */ + if (name->dynamicName) { + XFREE(name->name, heap, DYNAMIC_TYPE_SUBJECT_CN); + name->name = NULL; + } +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + { + int i; + if (name->fullName.fullName != NULL) { + XFREE(name->fullName.fullName, heap, DYNAMIC_TYPE_X509); + name->fullName.fullName = NULL; + } + for (i = 0; i < MAX_NAME_ENTRIES; i++) { + /* free ASN1 string data */ + if (name->extra[i].set && name->extra[i].data.data != NULL) { + XFREE(name->extra[i].data.data, heap, DYNAMIC_TYPE_OPENSSL); + } + } + wolfSSL_ASN1_OBJECT_free(&name->cnEntry.object); + } +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ } + (void)heap; } /* Initialize wolfSSL X509 type */ -void InitX509(WOLFSSL_X509* x509, int dynamicFlag) +void InitX509(WOLFSSL_X509* x509, int dynamicFlag, void* heap) { + if (x509 == NULL) { + WOLFSSL_MSG("Null parameter passed in!"); + return; + } + + XMEMSET(x509, 0, sizeof(WOLFSSL_X509)); + + x509->heap = heap; InitX509Name(&x509->issuer, 0); InitX509Name(&x509->subject, 0); - x509->version = 0; - x509->pubKey.buffer = NULL; - x509->sig.buffer = NULL; - x509->derCert.buffer = NULL; - x509->altNames = NULL; - x509->altNamesNext = NULL; x509->dynamicMemory = (byte)dynamicFlag; - x509->isCa = 0; -#ifdef HAVE_ECC - x509->pkCurveOID = 0; -#endif /* HAVE_ECC */ -#ifdef OPENSSL_EXTRA - x509->pathLength = 0; - x509->basicConstSet = 0; - x509->basicConstCrit = 0; - x509->basicConstPlSet = 0; - x509->subjAltNameSet = 0; - x509->subjAltNameCrit = 0; - x509->authKeyIdSet = 0; - x509->authKeyIdCrit = 0; - x509->authKeyId = NULL; - x509->authKeyIdSz = 0; - x509->subjKeyIdSet = 0; - x509->subjKeyIdCrit = 0; - x509->subjKeyId = NULL; - x509->subjKeyIdSz = 0; - x509->keyUsageSet = 0; - x509->keyUsageCrit = 0; - x509->keyUsage = 0; - #ifdef WOLFSSL_SEP - x509->certPolicySet = 0; - x509->certPolicyCrit = 0; - #endif /* WOLFSSL_SEP */ -#endif /* OPENSSL_EXTRA */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + x509->refCount = 1; + (void)wc_InitMutex(&x509->refMutex); + #endif } @@ -1441,44 +3408,2209 @@ void FreeX509(WOLFSSL_X509* x509) if (x509 == NULL) return; - FreeX509Name(&x509->issuer); - FreeX509Name(&x509->subject); - if (x509->pubKey.buffer) - XFREE(x509->pubKey.buffer, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - XFREE(x509->derCert.buffer, NULL, DYNAMIC_TYPE_SUBJECT_CN); - XFREE(x509->sig.buffer, NULL, DYNAMIC_TYPE_SIGNATURE); - #ifdef OPENSSL_EXTRA - XFREE(x509->authKeyId, NULL, 0); - XFREE(x509->subjKeyId, NULL, 0); - #endif /* OPENSSL_EXTRA */ - if (x509->altNames) - FreeAltNames(x509->altNames, NULL); - if (x509->dynamicMemory) - XFREE(x509, NULL, DYNAMIC_TYPE_X509); + FreeX509Name(&x509->issuer, x509->heap); + FreeX509Name(&x509->subject, x509->heap); + if (x509->pubKey.buffer) { + XFREE(x509->pubKey.buffer, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY); + x509->pubKey.buffer = NULL; + } + FreeDer(&x509->derCert); + XFREE(x509->sig.buffer, x509->heap, DYNAMIC_TYPE_SIGNATURE); + x509->sig.buffer = NULL; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + XFREE(x509->authKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->authKeyId = NULL; + XFREE(x509->subjKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->subjKeyId = NULL; + if (x509->authInfo != NULL) { + XFREE(x509->authInfo, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->authInfo = NULL; + } + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + if (x509->authInfoCaIssuer != NULL) { + XFREE(x509->authInfoCaIssuer, x509->heap, DYNAMIC_TYPE_X509_EXT); + } + if (x509->ext_sk != NULL) { + wolfSSL_sk_X509_EXTENSION_free(x509->ext_sk); + } + #endif /* OPENSSL_ALL || WOLFSSL_QT */ + #ifdef OPENSSL_EXTRA + /* Free serialNumber that was set by wolfSSL_X509_get_serialNumber */ + if (x509->serialNumber != NULL) { + wolfSSL_ASN1_INTEGER_free(x509->serialNumber); + } + #endif + if (x509->extKeyUsageSrc != NULL) { + XFREE(x509->extKeyUsageSrc, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->extKeyUsageSrc= NULL; + } + #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + #if defined(OPENSSL_ALL) + if (x509->algor.algorithm) { + wolfSSL_ASN1_OBJECT_free(x509->algor.algorithm); + x509->algor.algorithm = NULL; + } + if (x509->key.algor) { + wolfSSL_X509_ALGOR_free(x509->key.algor); + x509->key.algor = NULL; + } + if (x509->key.pkey) { + wolfSSL_EVP_PKEY_free(x509->key.pkey); + x509->key.pkey = NULL; + } + #endif /* OPENSSL_ALL */ + if (x509->altNames) { + FreeAltNames(x509->altNames, x509->heap); + x509->altNames = NULL; + } + + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + wc_FreeMutex(&x509->refMutex); + #endif } -#endif /* NO_CERTS */ - -/* init everything to 0, NULL, default values before calling anything that may - fail so that desctructor has a "good" state to cleanup */ -int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) +#if !defined(WOLFSSL_NO_TLS12) +/* Encode the signature algorithm into buffer. + * + * hashalgo The hash algorithm. + * hsType The signature type. + * output The buffer to encode into. + */ +static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) { - int ret; - byte haveRSA = 0; + 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 +#ifdef HAVE_ED448 + case ed448_sa_algo: + output[0] = ED448_SA_MAJOR; + output[1] = ED448_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 + } + (void)hashAlgo; + (void)output; +} +#endif + +#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_NO_CLIENT_AUTH) +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 /* !WOLFSSL_NO_TLS12 && !WOLFSSL_NO_CLIENT_AUTH */ +#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */ +#endif /* !NO_CERTS */ + +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) +static word32 MacSize(WOLFSSL* ssl) +{ +#ifdef HAVE_TRUNCATED_HMAC + word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ + : ssl->specs.hash_size; +#else + word32 digestSz = ssl->specs.hash_size; +#endif + + return digestSz; +} +#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */ + +#ifndef NO_RSA +#ifndef WOLFSSL_NO_TLS12 +#if !defined(NO_WOLFSSL_SERVER) || (!defined(NO_WOLFSSL_CLIENT) && \ + !defined(WOLFSSL_NO_CLIENT_AUTH)) +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 + #ifdef WOLFSSL_SHA224 + case sha224_mac: + return SHA224h; + #endif + #ifndef NO_SHA + case sha_mac: + return SHAh; + #endif + } + + return 0; +} +#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ +#endif /* !WOLFSSL_NO_TLS12 */ + +#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 + +#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH) +int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key, + DerBuffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + (void)sigAlgo; + (void)hashAlgo; + + WOLFSSL_ENTER("RsaSign"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + if (key) { + 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) { + void* ctx = wolfSSL_GetRsaPssSignCtx(ssl); + 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) { + void* ctx = wolfSSL_GetRsaSignCtx(ssl); + ret = ssl->ctx->RsaSignCb(ssl, in, inSz, out, outSz, keyBuf, keySz, + ctx); + } + else +#endif /*HAVE_PK_CALLBACKS */ + ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, key, ssl->rng); + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (key && ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* For positive response return in outSz */ + if (ret > 0) { + *outSz = ret; + ret = 0; + } + + WOLFSSL_LEAVE("RsaSign", ret); + + return ret; +} +#endif + +int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo, + int hashAlgo, RsaKey* key, buffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + (void)sigAlgo; + (void)hashAlgo; + + WOLFSSL_ENTER("RsaVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize 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) { + void* ctx = wolfSSL_GetRsaPssVerifyCtx(ssl); + 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) { + void* ctx = wolfSSL_GetRsaVerifyCtx(ssl); + ret = ssl->ctx->RsaVerifyCb(ssl, in, inSz, out, keyBuf, keySz, ctx); + } + else +#endif /*HAVE_PK_CALLBACKS */ + { + ret = wc_RsaSSL_VerifyInline(in, inSz, out, 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("RsaVerify", ret); + + return ret; +} + +/* Verify RSA signature, 0 on success */ +/* This function is used to check the sign result */ +int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, + const byte* plain, word32 plainSz, int sigAlgo, int hashAlgo, RsaKey* key, + DerBuffer* keyBufInfo) +{ + byte* out = NULL; /* inline result */ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + (void)sigAlgo; + (void)hashAlgo; + + WOLFSSL_ENTER("VerifyRsaSign"); + + if (verifySig == NULL || plain == NULL) { + return BAD_FUNC_ARG; + } + + if (sigSz > ENCRYPT_LEN) { + WOLFSSL_MSG("Signature buffer too big"); + return BUFFER_E; + } + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + if (key) { + 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->RsaPssSignCheckCb) { + /* The key buffer includes private/public portion, + but only public is used */ + /* If HSM hardware is checking the signature result you can + optionally skip the sign check and return 0 */ + /* The ctx here is the RsaSignCtx set using wolfSSL_SetRsaSignCtx */ + void* ctx = wolfSSL_GetRsaPssSignCtx(ssl); + ret = ssl->ctx->RsaPssSignCheckCb(ssl, verifySig, sigSz, &out, + TypeHash(hashAlgo), mgf, + keyBuf, keySz, ctx); + if (ret > 0) { + ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret, + hashType); + if (ret != 0) + ret = VERIFY_CERT_ERROR; + } + } + else + #endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_RsaPSS_VerifyInline(verifySig, sigSz, &out, hashType, mgf, + key); + if (ret > 0) { + #ifdef HAVE_SELFTEST + ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret, + hashType); + #else + ret = wc_RsaPSS_CheckPadding_ex(plain, plainSz, out, ret, + hashType, -1, + mp_count_bits(&key->n)); + #endif + if (ret != 0) + ret = VERIFY_CERT_ERROR; + } + } + + } + else +#endif /* WC_RSA_PSS */ + { + #ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaSignCheckCb) { + /* The key buffer includes private/public portion, + but only public is used */ + /* If HSM hardware is checking the signature result you can + optionally skip the sign check and return 0 */ + /* The ctx here is the RsaSignCtx set using wolfSSL_SetRsaSignCtx */ + void* ctx = wolfSSL_GetRsaSignCtx(ssl); + ret = ssl->ctx->RsaSignCheckCb(ssl, verifySig, sigSz, &out, + keyBuf, keySz, ctx); + } + else + #endif /* HAVE_PK_CALLBACKS */ + { + 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 */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (key && ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("VerifyRsaSign", ret); + + return ret; +} + +#ifndef WOLFSSL_NO_TLS12 + +#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH) +int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, + RsaKey* key, DerBuffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("RsaDec"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize 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) { + void* ctx = wolfSSL_GetRsaDecCtx(ssl); + ret = ssl->ctx->RsaDecCb(ssl, in, inSz, out, keyBuf, keySz, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(key, ssl->rng); + if (ret != 0) + return ret; + #endif + ret = wc_RsaPrivateDecryptInline(in, inSz, out, key); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* For positive response return in outSz */ + if (ret > 0) { + *outSz = ret; + ret = 0; + } + + WOLFSSL_LEAVE("RsaDec", ret); + + return ret; +} +#endif /* !NO_WOLFSSL_SERVER) || !WOLFSSL_NO_CLIENT_AUTH */ + +int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, + RsaKey* key, buffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("RsaEnc"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize 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) { + void* ctx = wolfSSL_GetRsaEncCtx(ssl); + ret = ssl->ctx->RsaEncCb(ssl, in, inSz, out, outSz, keyBuf, keySz, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, key, ssl->rng); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* For positive response return in outSz */ + if (ret > 0) { + *outSz = ret; + ret = 0; + } + + WOLFSSL_LEAVE("RsaEnc", ret); + + return ret; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +#endif /* NO_RSA */ + +#ifdef HAVE_ECC + +int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, ecc_key* key, DerBuffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("EccSign"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + if (key) { + 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) { + void* ctx = wolfSSL_GetEccSignCtx(ssl); + ret = ssl->ctx->EccSignCb(ssl, in, inSz, out, outSz, keyBuf, + keySz, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ecc_sign_hash(in, inSz, out, outSz, ssl->rng, key); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (key && ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("EccSign", ret); + + return ret; +} + +int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, + word32 outSz, ecc_key* key, buffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("EccVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize 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) { + void* ctx = wolfSSL_GetEccVerifyCtx(ssl); + ret = ssl->ctx->EccVerifyCb(ssl, in, inSz, out, outSz, keyBuf, keySz, + &ssl->eccVerifyRes, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ecc_verify_hash(in, inSz, out, outSz, &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("EccVerify", ret); + + return ret; +} + +#ifdef HAVE_PK_CALLBACKS + /* Gets ECC key for shared secret callback testing + * Client side: returns peer key + * Server side: returns private key + */ + static int EccGetKey(WOLFSSL* ssl, ecc_key** otherKey) + { + int ret = NO_PEER_KEY; + ecc_key* tmpKey = NULL; + + if (ssl == NULL || otherKey == NULL) { + return BAD_FUNC_ARG; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->specs.static_ecdh) { + if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent || + !ssl->peerEccDsaKey->dp) { + return NO_PEER_KEY; + } + tmpKey = (struct ecc_key*)ssl->peerEccDsaKey; + } + else { + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || + !ssl->peerEccKey->dp) { + return NO_PEER_KEY; + } + tmpKey = (struct ecc_key*)ssl->peerEccKey; + } + } + else if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->specs.static_ecdh) { + if (ssl->hsKey == NULL) { + return NO_PRIVATE_KEY; + } + tmpKey = (struct ecc_key*)ssl->hsKey; + } + else { + if (!ssl->eccTempKeyPresent) { + return NO_PRIVATE_KEY; + } + tmpKey = (struct ecc_key*)ssl->eccTempKey; + } + } + + if (tmpKey) { + *otherKey = tmpKey; + ret = 0; + } + + return ret; + } +#endif /* HAVE_PK_CALLBACKS */ + +int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, + byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen, + int side) +{ + 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; + (void)pubKeySz; + (void)side; + + WOLFSSL_ENTER("EccSharedSecret"); + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->EccSharedSecretCb) { + ret = EccGetKey(ssl, &otherKey); + if (ret != 0) + return ret; + #ifdef WOLFSSL_ASYNC_CRYPT + asyncDev = &otherKey->asyncDev; + #endif + } +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize 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) { + void* ctx = wolfSSL_GetEccSharedSecretCtx(ssl); + ret = ssl->ctx->EccSharedSecretCb(ssl, otherKey, pubKeyDer, + pubKeySz, out, outlen, side, ctx); + } + else +#endif + { + ret = wc_ecc_shared_secret(priv_key, pub_key, out, outlen); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("EccSharedSecret", ret); + + return ret; +} + +int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) +{ + int ret = 0; + int keySz = 0; + int ecc_curve = ECC_CURVE_DEF; + + WOLFSSL_ENTER("EccMakeKey"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret != 0) + return ret; +#endif + + /* get key size */ + if (peer == NULL) { + keySz = ssl->eccTempKeySz; + } + else { + keySz = peer->dp->size; + } + + /* get curve type */ + if (ssl->ecdhCurveOID > 0) { + ecc_curve = wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL); + } + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->EccKeyGenCb) { + void* ctx = wolfSSL_GetEccKeyGenCtx(ssl); + ret = ssl->ctx->EccKeyGenCb(ssl, key, keySz, ecc_curve, ctx); + } + else +#endif + { + ret = wc_ecc_make_key_ex(ssl->rng, keySz, key, ecc_curve); + } + + /* make sure the curve is set for TLS */ + if (ret == 0 && key->dp) { + ssl->ecdhCurveOID = key->dp->oidSum; + #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE) + ssl->namedGroup = 0; + #endif + } + + /* 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("EccMakeKey", ret); + + return ret; +} +#endif /* HAVE_ECC */ + +#ifdef HAVE_ED25519 +/* Check whether the key contains a public key. + * If not then pull it out of the leaf certificate. + * + * ssl SSL/TLS object. + * returns MEMORY_E when unable to allocate memory, a parsing error, otherwise + * 0 on success. + */ +int Ed25519CheckPubKey(WOLFSSL* ssl) +{ + ed25519_key* key = (ed25519_key*)ssl->hsKey; + int ret = 0; + + /* Public key required for signing. */ + if (!key->pubKeySet) { + DerBuffer* leaf = ssl->buffers.certificate; + DecodedCert* cert = (DecodedCert*)XMALLOC(sizeof(*cert), + ssl->heap, DYNAMIC_TYPE_DCERT); + if (cert == NULL) + ret = MEMORY_E; + + if (ret == 0) { + InitDecodedCert(cert, leaf->buffer, leaf->length, ssl->heap); + ret = DecodeToKey(cert, 0); + } + if (ret == 0) { + ret = wc_ed25519_import_public(cert->publicKey, cert->pubKeySize, + key); + } + if (cert != NULL) { + FreeDecodedCert(cert); + XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); + } + } + + return ret; +} + +/* Sign the data using EdDSA and key using Ed25519. + * + * 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 Ed25519 key data. + * keySz The length of the private key data in bytes. + * ctx The callback context. + * returns 0 on success, otherwise the value is an error. + */ +int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, ed25519_key* key, DerBuffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("Ed25519Sign"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize 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) { + void* ctx = wolfSSL_GetEd25519SignCtx(ssl); + 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 Ed25519. + * + * 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 Ed25519 key data. + * keySz The length of the private key data in bytes. + * ctx The callback context. + * returns 0 on success, otherwise the value is an error. + */ +int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, + word32 msgSz, ed25519_key* key, buffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("Ed25519Verify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize 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) { + void* ctx = wolfSSL_GetEd25519VerifyCtx(ssl); + 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 */ + +#ifndef WOLFSSL_NO_TLS12 + +#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) +{ + int ret; + + (void)ssl; + (void)pubKeyDer; + (void)pubKeySz; + (void)side; + + WOLFSSL_ENTER("X25519SharedSecret"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize 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) { + void* ctx = wolfSSL_GetX25519SharedSecretCtx(ssl); + 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 + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->X25519KeyGenCb) { + void* ctx = wolfSSL_GetX25519KeyGenCtx(ssl); + ret = ssl->ctx->X25519KeyGenCb(ssl, key, CURVE25519_KEYSIZE, ctx); + } + else +#endif + { + ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key); + } + + if (ret == 0) { + ssl->ecdhCurveOID = ECC_X25519_OID; + #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE) + ssl->namedGroup = 0; + #endif + } + + /* 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 */ + +#ifdef HAVE_ED448 +/* Check whether the key contains a public key. + * If not then pull it out of the leaf certificate. + * + * ssl SSL/TLS object. + * returns MEMORY_E when unable to allocate memory, a parsing error, otherwise + * 0 on success. + */ +int Ed448CheckPubKey(WOLFSSL* ssl) +{ + ed448_key* key = (ed448_key*)ssl->hsKey; + int ret = 0; + + /* Public key required for signing. */ + if (!key->pubKeySet) { + DerBuffer* leaf = ssl->buffers.certificate; + DecodedCert* cert = (DecodedCert*)XMALLOC(sizeof(*cert), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + ret = MEMORY_E; + + if (ret == 0) { + InitDecodedCert(cert, leaf->buffer, leaf->length, ssl->heap); + ret = DecodeToKey(cert, 0); + } + if (ret == 0) { + ret = wc_ed448_import_public(cert->publicKey, cert->pubKeySize, + key); + } + if (cert != NULL) { + FreeDecodedCert(cert); + XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); + } + } + + return ret; +} + +/* Sign the data using EdDSA and key using Ed448. + * + * 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 Ed448 key data. + * keySz The length of the private key data in bytes. + * ctx The callback context. + * returns 0 on success, otherwise the value is an error. + */ +int Ed448Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, ed448_key* key, DerBuffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("Ed448Sign"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize 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->Ed448SignCb) { + void* ctx = wolfSSL_GetEd448SignCtx(ssl); + ret = ssl->ctx->Ed448SignCb(ssl, in, inSz, out, outSz, keyBuf, keySz, + ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ed448_sign_msg(in, inSz, out, outSz, key, NULL, 0); + } + + /* 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("Ed448Sign", ret); + + return ret; +} + +/* Verify the data using EdDSA and key using Ed448. + * + * 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 Ed448 key data. + * keySz The length of the private key data in bytes. + * ctx The callback context. + * returns 0 on success, otherwise the value is an error. + */ +int Ed448Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, + word32 msgSz, ed448_key* key, buffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("Ed448Verify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize 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->Ed448VerifyCb) { + void* ctx = wolfSSL_GetEd448VerifyCtx(ssl); + ret = ssl->ctx->Ed448VerifyCb(ssl, in, inSz, msg, msgSz, keyBuf, keySz, + &ssl->eccVerifyRes, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ed448_verify_msg(in, inSz, msg, msgSz, &ssl->eccVerifyRes, key, + NULL, 0); + } + + /* 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("Ed448Verify", ret); + + return ret; +} +#endif /* HAVE_ED448 */ + +#ifdef HAVE_CURVE448 +#ifdef HAVE_PK_CALLBACKS + /* Gets X448 key for shared secret callback testing + * Client side: returns peer key + * Server side: returns private key + */ + static int X448GetKey(WOLFSSL* ssl, curve448_key** otherKey) + { + int ret = NO_PEER_KEY; + struct curve448_key* tmpKey = NULL; + + if (ssl == NULL || otherKey == NULL) { + return BAD_FUNC_ARG; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (!ssl->peerX448Key || !ssl->peerX448KeyPresent) { + return NO_PEER_KEY; + } + tmpKey = (struct curve448_key*)ssl->peerX448Key; + } + else if (ssl->options.side == WOLFSSL_SERVER_END) { + if (!ssl->eccTempKeyPresent) { + return NO_PRIVATE_KEY; + } + tmpKey = (struct curve448_key*)ssl->eccTempKey; + } + + if (tmpKey) { + *otherKey = (curve448_key *)tmpKey; + ret = 0; + } + + return ret; + } +#endif /* HAVE_PK_CALLBACKS */ + +static int X448SharedSecret(WOLFSSL* ssl, curve448_key* priv_key, + curve448_key* pub_key, byte* pubKeyDer, + word32* pubKeySz, byte* out, word32* outlen, + int side) +{ + int ret; + + (void)ssl; + (void)pubKeyDer; + (void)pubKeySz; + (void)side; + + WOLFSSL_ENTER("X448SharedSecret"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize 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->X448SharedSecretCb) { + curve448_key* otherKey = NULL; + + ret = X448GetKey(ssl, &otherKey); + if (ret == 0) { + void* ctx = wolfSSL_GetX448SharedSecretCtx(ssl); + ret = ssl->ctx->X448SharedSecretCb(ssl, otherKey, pubKeyDer, + pubKeySz, out, outlen, side, ctx); + } + } + else +#endif + { + ret = wc_curve448_shared_secret_ex(priv_key, pub_key, out, outlen, + EC448_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("X448SharedSecret", ret); + + return ret; +} + +static int X448MakeKey(WOLFSSL* ssl, curve448_key* key, curve448_key* peer) +{ + int ret = 0; + + (void)peer; + + WOLFSSL_ENTER("X448MakeKey"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->X448KeyGenCb) { + void* ctx = wolfSSL_GetX448KeyGenCtx(ssl); + ret = ssl->ctx->X448KeyGenCb(ssl, key, CURVE448_KEY_SIZE, ctx); + } + else +#endif + { + ret = wc_curve448_make_key(ssl->rng, CURVE448_KEY_SIZE, key); + } + + if (ret == 0) { + ssl->ecdhCurveOID = ECC_X448_OID; + #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE) + ssl->namedGroup = 0; + #endif + } + + /* 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("X448MakeKey", ret); + + return ret; +} +#endif /* HAVE_CURVE448 */ + +#if !defined(NO_CERTS) || !defined(NO_PSK) +#if !defined(NO_DH) + +int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, + byte* priv, word32* privSz, + byte* pub, word32* pubSz) +{ + int ret; + + WOLFSSL_ENTER("DhGenKeyPair"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize 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); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("DhGenKeyPair", ret); + + return ret; +} + +int DhAgree(WOLFSSL* ssl, DhKey* dhKey, + const byte* priv, word32 privSz, + const byte* otherPub, word32 otherPubSz, + byte* agree, word32* agreeSz) +{ + int ret; + + (void)ssl; + + WOLFSSL_ENTER("DhAgree"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->DhAgreeCb) { + void* ctx = wolfSSL_GetDhAgreeCtx(ssl); + + WOLFSSL_MSG("Calling DhAgree Callback Function"); + ret = ssl->ctx->DhAgreeCb(ssl, dhKey, priv, privSz, + otherPub, otherPubSz, agree, agreeSz, ctx); + } + else +#endif + { +#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + ret = wc_DhCheckPubValue(ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, otherPub, otherPubSz); + if (ret != 0) { + #ifdef OPENSSL_EXTRA + SendAlert(ssl, alert_fatal, illegal_parameter); + #endif + } + else +#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); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("DhAgree", ret); + + return ret; +} +#endif /* !NO_DH */ +#endif /* !NO_CERTS || !NO_PSK */ + +#endif /* !WOLFSSL_NO_TLS12 */ + + +#ifdef HAVE_PK_CALLBACKS +int wolfSSL_IsPrivatePkSet(WOLFSSL* ssl) +{ + int pkcbset = 0; + (void)ssl; + +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + !defined(NO_RSA) + if (0 + #ifdef HAVE_ECC + || (ssl->ctx->EccSignCb != NULL && + ssl->buffers.keyType == ecc_dsa_sa_algo) + #endif + #ifdef HAVE_ED25519 + || (ssl->ctx->Ed25519SignCb != NULL && + ssl->buffers.keyType == ed25519_sa_algo) + #endif + #ifdef HAVE_ED448 + || (ssl->ctx->Ed448SignCb != NULL && + ssl->buffers.keyType == ed448_sa_algo) + #endif + #ifndef NO_RSA + || (ssl->ctx->RsaSignCb != NULL && ssl->buffers.keyType == rsa_sa_algo) + || (ssl->ctx->RsaDecCb != NULL && ssl->buffers.keyType == rsa_kea) + #ifdef WC_RSA_PSS + || (ssl->ctx->RsaPssSignCb != NULL && + ssl->buffers.keyType == rsa_pss_sa_algo) + #endif + #endif + ) { + pkcbset = 1; + } +#endif + return pkcbset; +} + +int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx) +{ + int pkcbset = 0; + (void)ctx; +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + !defined(NO_RSA) + if (0 + #ifdef HAVE_ECC + || ctx->EccSignCb != NULL + #endif + #ifdef HAVE_ED25519 + || ctx->Ed25519SignCb != NULL + #endif + #ifdef HAVE_ED448 + || ctx->Ed448SignCb != NULL + #endif + #ifndef NO_RSA + || ctx->RsaSignCb != NULL + || ctx->RsaDecCb != NULL + #ifdef WC_RSA_PSS + || ctx->RsaPssSignCb != NULL + #endif + #endif + ) { + pkcbset = 1; + } +#endif + return pkcbset; +} +#endif /* HAVE_PK_CALLBACKS */ + + +int InitSSL_Suites(WOLFSSL* ssl) +{ + int keySz = 0; byte havePSK = 0; byte haveAnon = 0; + byte haveRSA = 0; + byte haveMcast = 0; - (void) haveAnon; + (void)haveAnon; /* Squash unused var warnings */ + (void)haveMcast; - XMEMSET(ssl, 0, sizeof(WOLFSSL)); - - ssl->ctx = ctx; /* only for passing to calls, options could change */ - ssl->version = ctx->method->version; + if (!ssl) + return BAD_FUNC_ARG; #ifndef NO_RSA haveRSA = 1; #endif +#ifndef NO_PSK + havePSK = (byte)ssl->options.havePSK; +#endif /* NO_PSK */ +#ifdef HAVE_ANON + haveAnon = (byte)ssl->options.haveAnon; +#endif /* HAVE_ANON*/ +#ifdef WOLFSSL_MULTICAST + haveMcast = (byte)ssl->options.haveMcast; +#endif /* WOLFSSL_MULTICAST */ + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->options.side == WOLFSSL_SERVER_END) + ssl->options.maxEarlyDataSz = ssl->ctx->maxEarlyDataSz; +#endif +#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ + ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ + (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) + ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END || + ssl->buffers.keyType == ed25519_sa_algo || + ssl->buffers.keyType == ed448_sa_algo; +#endif + +#ifndef NO_CERTS + keySz = ssl->buffers.keySz; +#endif + + /* 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, Anon, or + * Multicast. This should be true even if just switching ssl ctx */ + if (ssl->options.side == WOLFSSL_SERVER_END && + !havePSK && !haveAnon && !haveMcast) { + + /* server certificate must be loaded */ + if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer) { + WOLFSSL_MSG("Server missing certificate"); + return NO_PRIVATE_KEY; + } + + /* allow no private key if using PK callbacks and CB is set */ + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + WOLFSSL_MSG("Using PK for server private key"); + } + else + #endif + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + WOLFSSL_MSG("Server missing private key"); + return NO_PRIVATE_KEY; + } + } +#endif + + return WOLFSSL_SUCCESS; +} + +/* returns new reference count. Arg incr positive=up or negative=down */ +int SSL_CTX_RefCount(WOLFSSL_CTX* ctx, int incr) +{ + int refCount; + + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + if (wc_LockMutex(&ctx->countMutex) != 0) { + WOLFSSL_MSG("Couldn't lock CTX count mutex"); + return BAD_MUTEX_E; + } + + ctx->refCount += incr; + /* make sure refCount is never negative */ + if (ctx->refCount < 0) { + ctx->refCount = 0; + } + refCount = ctx->refCount; + + wc_UnLockMutex(&ctx->countMutex); + + return refCount; +} + +/* 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 + 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) +{ + int ret; + byte newSSL; + + if (!ssl || !ctx) + return BAD_FUNC_ARG; + +#ifndef SINGLE_THREADED + if (ssl->suites == NULL && !writeDup) + return BAD_FUNC_ARG; +#endif + + newSSL = ssl->ctx == NULL; /* Assign after null check */ + +#ifndef NO_PSK + if (ctx->server_hint[0] && ssl->arrays == NULL && !writeDup) { + return BAD_FUNC_ARG; /* needed for copy below */ + } +#endif + + /* decrement previous CTX reference count if exists. + * This should only happen if switching ctxs!*/ + if (!newSSL) { + WOLFSSL_MSG("freeing old ctx to decrement reference count. Switching ctx."); + wolfSSL_CTX_free(ssl->ctx); + } + + /* increment CTX reference count */ + if ((ret = SSL_CTX_RefCount(ctx, 1)) < 0) { + return ret; + } + ret = WOLFSSL_SUCCESS; /* set default ret */ + + ssl->ctx = ctx; /* only for passing to calls, options could change */ + ssl->version = ctx->method->version; + +#ifdef HAVE_ECC + ssl->eccTempKeySz = ctx->eccTempKeySz; + ssl->ecdhCurveOID = ctx->ecdhCurveOID; +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + ssl->pkCurveOID = ctx->pkCurveOID; +#endif + +#ifdef OPENSSL_EXTRA + ssl->options.mask = ctx->mask; + ssl->CBIS = ctx->CBIS; +#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; + + ssl->options.haveDH = ctx->haveDH; + ssl->options.haveNTRU = ctx->haveNTRU; + ssl->options.haveECDSAsig = ctx->haveECDSAsig; + ssl->options.haveECC = ctx->haveECC; + ssl->options.haveStaticECC = ctx->haveStaticECC; + +#ifndef NO_PSK + ssl->options.havePSK = ctx->havePSK; + ssl->options.client_psk_cb = ctx->client_psk_cb; + ssl->options.server_psk_cb = ctx->server_psk_cb; +#ifdef WOLFSSL_TLS13 + ssl->options.client_psk_tls13_cb = ctx->client_psk_tls13_cb; + ssl->options.server_psk_tls13_cb = ctx->server_psk_tls13_cb; +#endif +#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; +#endif +#ifndef NO_DH + ssl->options.minDhKeySz = ctx->minDhKeySz; + ssl->options.maxDhKeySz = ctx->maxDhKeySz; +#endif +#ifndef NO_RSA + ssl->options.minRsaKeySz = ctx->minRsaKeySz; +#endif +#ifdef HAVE_ECC + ssl->options.minEccKeySz = ctx->minEccKeySz; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + 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; + ssl->options.failNoCert = ctx->failNoCert; + ssl->options.failNoCertxPSK = ctx->failNoCertxPSK; + ssl->options.sendVerify = ctx->sendVerify; + + ssl->options.partialWrite = ctx->partialWrite; + ssl->options.quietShutdown = ctx->quietShutdown; + ssl->options.groupMessages = ctx->groupMessages; + +#ifndef NO_DH + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + ssl->options.dhKeyTested = ctx->dhKeyTested; + #endif + 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; +#ifdef WOLFSSL_TLS13 + ssl->buffers.certChainCnt = ctx->certChainCnt; +#endif + ssl->buffers.key = ctx->privateKey; + ssl->buffers.keyType = ctx->privateKeyType; + ssl->buffers.keyId = ctx->privateKeyId; + ssl->buffers.keySz = ctx->privateKeySz; + ssl->buffers.keyDevId = ctx->privateKeyDevId; +#endif +#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ + ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ + (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) + ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END || + ssl->buffers.keyType == ed25519_sa_algo || + ssl->buffers.keyType == ed448_sa_algo; +#endif + + +#ifdef WOLFSSL_ASYNC_CRYPT + ssl->devId = ctx->devId; +#endif + + if (writeDup == 0) { +#ifndef NO_PSK + 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) { +#ifndef SINGLE_THREADED + *ssl->suites = *ctx->suites; +#else + ssl->suites = ctx->suites; +#endif + } + else { + XMEMSET(ssl->suites, 0, sizeof(Suites)); + } + + if (ssl->options.side != WOLFSSL_NEITHER_END) { + /* Defer initializing suites until accept or connect */ + ret = InitSSL_Suites(ssl); + } + } /* writeDup check */ + +#ifdef WOLFSSL_SESSION_EXPORT + #ifdef WOLFSSL_DTLS + ssl->dtls_export = ctx->dtls_export; /* export function for session */ + #endif +#endif + + ssl->CBIORecv = ctx->CBIORecv; + ssl->CBIOSend = ctx->CBIOSend; +#ifdef OPENSSL_EXTRA + ssl->readAhead = ctx->readAhead; +#endif + ssl->verifyDepth = ctx->verifyDepth; + + return ret; +} + +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; + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Md5SetFlags(&ssl->hsHashes->hashMd5, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#ifndef NO_SHA + ret = wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_ShaSetFlags(&ssl->hsHashes->hashSha, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#endif /* !NO_OLD_TLS */ +#ifndef NO_SHA256 + ret = wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Sha256SetFlags(&ssl->hsHashes->hashSha256, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Sha384SetFlags(&ssl->hsHashes->hashSha384, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Sha512SetFlags(&ssl->hsHashes->hashSha512, WC_HASH_FLAG_WILLCOPY); + #endif +#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 + #if (defined(HAVE_ED25519) || defined(HAVE_ED448)) && \ + !defined(WOLFSSL_NO_CLIENT_AUTH) + if (ssl->hsHashes->messages != NULL) { + XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes->messages = NULL; + } + #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 writeDup) +{ + int ret; + + XMEMSET(ssl, 0, sizeof(WOLFSSL)); + +#if defined(WOLFSSL_STATIC_MEMORY) + if (ctx->heap != NULL) { + WOLFSSL_HEAP_HINT* ssl_hint; + WOLFSSL_HEAP_HINT* ctx_hint; + + /* avoid dereferencing a test value */ + #ifdef WOLFSSL_HEAP_TEST + if (ctx->heap == (void*)WOLFSSL_HEAP_TEST) { + ssl->heap = ctx->heap; + } + else { + #endif + ssl->heap = (WOLFSSL_HEAP_HINT*)XMALLOC(sizeof(WOLFSSL_HEAP_HINT), + ctx->heap, DYNAMIC_TYPE_SSL); + if (ssl->heap == NULL) { + return MEMORY_E; + } + XMEMSET(ssl->heap, 0, sizeof(WOLFSSL_HEAP_HINT)); + ssl_hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap)); + ctx_hint = ((WOLFSSL_HEAP_HINT*)(ctx->heap)); + + /* lock and check IO count / handshake count */ + if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL); + ssl->heap = NULL; /* free and set to NULL for IO counter */ + return BAD_MUTEX_E; + } + if (ctx_hint->memory->maxHa > 0 && + ctx_hint->memory->maxHa <= ctx_hint->memory->curHa) { + WOLFSSL_MSG("At max number of handshakes for static memory"); + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL); + ssl->heap = NULL; /* free and set to NULL for IO counter */ + return MEMORY_E; + } + + if (ctx_hint->memory->maxIO > 0 && + ctx_hint->memory->maxIO <= ctx_hint->memory->curIO) { + WOLFSSL_MSG("At max number of IO allowed for static memory"); + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL); + ssl->heap = NULL; /* free and set to NULL for IO counter */ + return MEMORY_E; + } + ctx_hint->memory->curIO++; + ctx_hint->memory->curHa++; + ssl_hint->memory = ctx_hint->memory; + ssl_hint->haFlag = 1; + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + + /* check if tracking stats */ + if (ctx_hint->memory->flag & WOLFMEM_TRACK_STATS) { + ssl_hint->stats = (WOLFSSL_MEM_CONN_STATS*)XMALLOC( + sizeof(WOLFSSL_MEM_CONN_STATS), ctx->heap, DYNAMIC_TYPE_SSL); + if (ssl_hint->stats == NULL) { + return MEMORY_E; + } + XMEMSET(ssl_hint->stats, 0, sizeof(WOLFSSL_MEM_CONN_STATS)); + } + + /* check if using fixed IO buffers */ + if (ctx_hint->memory->flag & WOLFMEM_IO_POOL_FIXED) { + if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + return BAD_MUTEX_E; + } + if (SetFixedIO(ctx_hint->memory, &(ssl_hint->inBuf)) != 1) { + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + return MEMORY_E; + } + if (SetFixedIO(ctx_hint->memory, &(ssl_hint->outBuf)) != 1) { + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + return MEMORY_E; + } + if (ssl_hint->outBuf == NULL || ssl_hint->inBuf == NULL) { + WOLFSSL_MSG("Not enough memory to create fixed IO buffers"); + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + return MEMORY_E; + } + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + } + #ifdef WOLFSSL_HEAP_TEST + } + #endif + } + else { + ssl->heap = ctx->heap; + } +#else + ssl->heap = ctx->heap; /* carry over user heap without static memory */ +#endif /* WOLFSSL_STATIC_MEMORY */ ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer; ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN; @@ -1487,17 +5619,12 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN; #ifdef KEEP_PEER_CERT - InitX509(&ssl->peerCert, 0); + InitX509(&ssl->peerCert, 0, ssl->heap); #endif -#ifdef HAVE_ECC - ssl->eccTempKeySz = ctx->eccTempKeySz; - ssl->pkCurveOID = ctx->pkCurveOID; -#endif - - ssl->timeout = ctx->timeout; 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 */ @@ -1505,100 +5632,102 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef HAVE_NETX ssl->IOCB_ReadCtx = &ssl->nxCtx; /* default NetX IO ctx, same for read */ ssl->IOCB_WriteCtx = &ssl->nxCtx; /* and write */ +#elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + ssl->mnCtx = mynewt_ctx_new(); + if(!ssl->mnCtx) { + return MEMORY_E; + } + ssl->IOCB_ReadCtx = ssl->mnCtx; /* default Mynewt IO ctx, same for read */ + ssl->IOCB_WriteCtx = ssl->mnCtx; /* and write */ +#elif defined (WOLFSSL_GNRC) + ssl->IOCB_ReadCtx = ssl->gnrcCtx; + ssl->IOCB_WriteCtx = ssl->gnrcCtx; #endif -#ifdef WOLFSSL_DTLS - ssl->dtls_expected_rx = MAX_MTU; -#endif - - 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.haveNTRU = ctx->haveNTRU; - ssl->options.haveECDSAsig = ctx->haveECDSAsig; - ssl->options.haveStaticECC = ctx->haveStaticECC; - -#ifndef NO_PSK - havePSK = ctx->havePSK; - ssl->options.havePSK = ctx->havePSK; - ssl->options.client_psk_cb = ctx->client_psk_cb; - ssl->options.server_psk_cb = ctx->server_psk_cb; -#endif /* NO_PSK */ - -#ifdef HAVE_ANON - haveAnon = ctx->haveAnon; - ssl->options.haveAnon = ctx->haveAnon; -#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; #ifndef NO_DH - ssl->options.minDhKeySz = ctx->minDhKeySz; + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + ssl->options.dhDoKeyTest = 1; + #endif #endif #ifdef WOLFSSL_DTLS + #ifdef WOLFSSL_SCTP + ssl->options.dtlsSctp = ctx->dtlsSctp; + #endif + #if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU) + ssl->dtlsMtuSz = ctx->dtlsMtuSz; + ssl->dtls_expected_rx = ssl->dtlsMtuSz; + #else + ssl->dtls_expected_rx = MAX_MTU; + #endif ssl->dtls_timeout_init = DTLS_TIMEOUT_INIT; ssl->dtls_timeout_max = DTLS_TIMEOUT_MAX; ssl->dtls_timeout = ssl->dtls_timeout_init; + ssl->buffers.dtlsCtx.rfd = -1; + ssl->buffers.dtlsCtx.wfd = -1; #endif - ssl->options.sessionCacheOff = ctx->sessionCacheOff; - ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff; - - ssl->options.verifyPeer = ctx->verifyPeer; - ssl->options.verifyNone = ctx->verifyNone; - ssl->options.failNoCert = ctx->failNoCert; - ssl->options.sendVerify = ctx->sendVerify; - +#ifndef WOLFSSL_AEAD_ONLY #ifndef NO_OLD_TLS ssl->hmac = SSL_hmac; /* default to SSLv3 */ - #else + #elif !defined(WOLFSSL_NO_TLS12) ssl->hmac = TLS_hmac; #endif - - ssl->heap = ctx->heap; /* defaults to self */ - - ssl->options.dtls = ssl->version.major == DTLS_MAJOR; - ssl->options.partialWrite = ctx->partialWrite; - ssl->options.quietShutdown = ctx->quietShutdown; - 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; - } -#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; #endif -#ifdef WOLFSSL_DTLS - ssl->buffers.dtlsCtx.fd = -1; -#endif ssl->cipher.ssl = ssl; -#ifdef HAVE_CAVIUM - ssl->devId = ctx->devId; +#ifdef HAVE_EXTENDED_MASTER + ssl->options.haveEMS = ctx->haveEMS; +#endif + ssl->options.useClientOrder = ctx->useClientOrder; + ssl->options.mutualAuth = ctx->mutualAuth; + +#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 + + if (ctx->numGroups > 0) { + XMEMCPY(ssl->group, ctx->group, sizeof(*ctx->group) * ctx->numGroups); + ssl->numGroups = ctx->numGroups; + } #endif #ifdef HAVE_TLS_EXTENSIONS #ifdef HAVE_MAX_FRAGMENT ssl->max_fragment = MAX_RECORD_SIZE; #endif +#ifdef HAVE_ALPN + ssl->alpn_client_list = NULL; + #if defined(OPENSSL_ALL) || 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; +#endif +#endif /* HAVE_TLS_EXTENSIONS */ + +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + ssl->options.disallowEncThenMac = ctx->disallowEncThenMac; #endif /* default alert state (none) */ @@ -1607,121 +5736,178 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->alert_history.last_tx.code = -1; ssl->alert_history.last_tx.level = -1; +#ifdef OPENSSL_EXTRA + /* copy over application session context ID */ + ssl->sessionCtxSz = ctx->sessionCtxSz; + XMEMCPY(ssl->sessionCtx, ctx->sessionCtx, ctx->sessionCtxSz); + ssl->cbioFlag = ctx->cbioFlag; + +#endif + InitCiphers(ssl); InitCipherSpecs(&ssl->specs); /* all done with init, now can return errors, call other stuff */ - /* 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 - - /* increment CTX reference count */ - if (LockMutex(&ctx->countMutex) != 0) { - WOLFSSL_MSG("Couldn't lock CTX count mutex"); - return BAD_MUTEX_E; - } - ctx->refCount++; - UnLockMutex(&ctx->countMutex); - - /* 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"); + if (ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays Memory error"); + return MEMORY_E; + } + XMEMSET(ssl->arrays, 0, sizeof(Arrays)); +#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_SNIFFER) + ssl->arrays->preMasterSz = ENCRYPT_LEN; + 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); +#endif + +#ifdef OPENSSL_EXTRA + if ((ssl->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( + sizeof(WOLFSSL_X509_VERIFY_PARAM), + ssl->heap, DYNAMIC_TYPE_OPENSSL)) == NULL) { + WOLFSSL_MSG("ssl->param memory error"); return MEMORY_E; } - XMEMSET(ssl->arrays, 0, sizeof(Arrays)); + XMEMSET(ssl->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); +#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'; - } -#endif /* NO_PSK */ - - /* RNG */ - ssl->rng = (RNG*)XMALLOC(sizeof(RNG), ssl->heap, DYNAMIC_TYPE_RNG); - if (ssl->rng == NULL) { - WOLFSSL_MSG("RNG Memory error"); - return MEMORY_E; - } - - if ( (ret = wc_InitRng(ssl->rng)) != 0) { - WOLFSSL_MSG("RNG Init error"); - return ret; - } - - /* 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 (ctx->suites) - *ssl->suites = *ctx->suites; - else - XMEMSET(ssl->suites, 0, sizeof(Suites)); - - -#ifndef NO_CERTS - /* make sure server has cert and key unless using PSK or Anon */ - if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon) - if (!ssl->buffers.certificate.buffer || !ssl->buffers.key.buffer) { - WOLFSSL_MSG("Server missing certificate and/or private key"); - return NO_PRIVATE_KEY; +#ifdef SINGLE_THREADED + if (ctx->suites == NULL) +#endif + { + /* suites */ + ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, + DYNAMIC_TYPE_SUITES); + if (ssl->suites == NULL) { + WOLFSSL_MSG("Suites Memory error"); + return MEMORY_E; + } + #ifdef OPENSSL_ALL + ssl->suites->stack = NULL; + #endif +#ifdef SINGLE_THREADED + ssl->options.ownSuites = 1; +#endif + } +#ifdef SINGLE_THREADED + else { + ssl->options.ownSuites = 0; } #endif + } + + /* Initialize SSL with the appropriate fields from it's ctx */ + /* 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; + +#ifdef SINGLE_THREADED + ssl->rng = ctx->rng; /* CTX may have one, if so use it */ +#endif + + if (ssl->rng == NULL) { + /* RNG */ + ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap,DYNAMIC_TYPE_RNG); + if (ssl->rng == NULL) { + WOLFSSL_MSG("RNG Memory error"); + return MEMORY_E; + } + XMEMSET(ssl->rng, 0, sizeof(WC_RNG)); + ssl->options.weOwnRng = 1; + + /* FIPS RNG API does not accept a heap hint */ +#ifndef HAVE_FIPS + if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap, ssl->devId)) != 0) { + WOLFSSL_MSG("RNG Init error"); + return ret; + } +#else + if ( (ret = wc_InitRng(ssl->rng)) != 0) { + WOLFSSL_MSG("RNG Init error"); + return ret; + } +#endif + } + +#ifdef HAVE_WRITE_DUP + if (writeDup) { + /* all done */ + return 0; + } +#endif + + /* 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); + if (ret != 0) { + WOLFSSL_MSG("DTLS Cookie Secret error"); + return ret; + } + } +#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ + #ifdef HAVE_SECRET_CALLBACK ssl->sessionSecretCb = NULL; ssl->sessionSecretCtx = NULL; +#ifdef WOLFSSL_TLS13 + ssl->tls13SecretCb = NULL; + ssl->tls13SecretCtx = NULL; +#endif #endif - /* 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.haveStaticECC, - ssl->options.side); - else - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, TRUE, - ssl->options.haveNTRU, ssl->options.haveECDSAsig, - ssl->options.haveStaticECC, ssl->options.side); +#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 + if (ssl->options.side == WOLFSSL_CLIENT_END) { + int useSecureReneg = ssl->ctx->useSecureReneg; + /* use secure renegotiation by default (not recommend) */ + #ifdef WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT + useSecureReneg = 1; + #endif + if (useSecureReneg) { + ret = wolfSSL_UseSecureRenegotiation(ssl); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + } +#endif /* HAVE_SECURE_RENEGOTIATION */ return 0; } @@ -1730,15 +5916,300 @@ 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 */ } XFREE(ssl->arrays, ssl->heap, DYNAMIC_TYPE_ARRAYS); ssl->arrays = NULL; } +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_ED25519 */ + #ifdef HAVE_CURVE25519 + case DYNAMIC_TYPE_CURVE25519: + wc_curve25519_free((curve25519_key*)*pKey); + break; + #endif /* HAVE_CURVE25519 */ + #ifdef HAVE_ED448 + case DYNAMIC_TYPE_ED448: + wc_ed448_free((ed448_key*)*pKey); + break; + #endif /* HAVE_ED448 */ + #ifdef HAVE_CURVE448 + case DYNAMIC_TYPE_CURVE448: + wc_curve448_free((curve448_key*)*pKey); + break; + #endif /* HAVE_CURVE448 */ + #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 */ + #ifdef HAVE_ED448 + case DYNAMIC_TYPE_ED448: + sz = sizeof(ed448_key); + break; + #endif /* HAVE_ED448 */ + #ifdef HAVE_CURVE448 + case DYNAMIC_TYPE_CURVE448: + sz = sizeof(curve448_key); + break; + #endif /* HAVE_CURVE448 */ + #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 memory 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 */ + #ifdef HAVE_ED448 + case DYNAMIC_TYPE_ED448: + wc_ed448_init((ed448_key*)*pKey); + ret = 0; + break; + #endif /* HAVE_CURVE448 */ + #ifdef HAVE_CURVE448 + case DYNAMIC_TYPE_CURVE448: + wc_curve448_init((curve448_key*)*pKey); + ret = 0; + break; + #endif /* HAVE_CURVE448 */ + #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) || defined(HHAVE_ED448) || defined(HAVE_CURVE448) +static int ReuseKey(WOLFSSL* ssl, int type, void* pKey) +{ + int ret = 0; + + (void)ssl; + + 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 */ + #ifdef HAVE_ED448 + case DYNAMIC_TYPE_ED448: + wc_ed448_free((ed448_key*)pKey); + ret = wc_ed448_init((ed448_key*)pKey); + break; + #endif /* HAVE_CURVE448 */ + #ifdef HAVE_CURVE448 + case DYNAMIC_TYPE_CURVE448: + wc_curve448_free((curve448_key*)pKey); + ret = wc_curve448_init((curve448_key*)pKey); + break; + #endif /* HAVE_CURVE448 */ + #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_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_DIGEST); + ssl->buffers.digest.buffer = NULL; + ssl->buffers.digest.length = 0; + } + + /* 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 +} + + +/* Free up all memory used by Suites structure from WOLFSSL */ +void FreeSuites(WOLFSSL* ssl) +{ +#ifdef SINGLE_THREADED + if (ssl->options.ownSuites) +#endif + { + #ifdef OPENSSL_ALL + wolfSSL_sk_SSL_CIPHER_free(ssl->suites->stack); + #endif + XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); + } + ssl->suites = NULL; +} + /* In case holding SSL object in array and don't want to free actual ssl */ void SSL_ResourceFree(WOLFSSL* ssl) @@ -1751,78 +6222,146 @@ void SSL_ResourceFree(WOLFSSL* ssl) FreeCiphers(ssl); FreeArrays(ssl, 0); - wc_FreeRng(ssl->rng); - XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); - XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); - XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); + FreeKeyExchange(ssl); + if (ssl->options.weOwnRng) { + wc_FreeRng(ssl->rng); + XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); + } + FreeSuites(ssl); + FreeHandshakeHashes(ssl); XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); -#ifndef NO_DH - XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH); - XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH); - /* 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); + /* clear keys struct after session */ + ForceZero(&ssl->keys, sizeof(Keys)); + +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + ForceZero(&ssl->clientSecret, sizeof(ssl->clientSecret)); + ForceZero(&ssl->serverSecret, sizeof(ssl->serverSecret)); } #endif + +#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_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) { + 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 - if (ssl->buffers.weOwnCert) - XFREE(ssl->buffers.certificate.buffer, ssl->heap, DYNAMIC_TYPE_CERT); - if (ssl->buffers.weOwnCertChain) - XFREE(ssl->buffers.certChain.buffer, ssl->heap, DYNAMIC_TYPE_CERT); - if (ssl->buffers.weOwnKey) - XFREE(ssl->buffers.key.buffer, ssl->heap, DYNAMIC_TYPE_KEY); + ssl->keepCert = 0; /* make sure certificate is free'd */ + 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 +#ifdef WOLFSSL_RENESAS_TSIP_TLS + XFREE(ssl->peerTsipEncRsaKeyIndex, ssl->heap, DYNAMIC_TYPE_RSA); #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 - if (ssl->dtls_pool != NULL) { - DtlsPoolReset(ssl); - XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_NONE); - } - if (ssl->dtls_msg_list != NULL) { - DtlsMsgListDelete(ssl->dtls_msg_list, ssl->heap); - ssl->dtls_msg_list = NULL; + DtlsMsgPoolReset(ssl); + if (ssl->dtls_rx_msg_list != NULL) { + DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap); + ssl->dtls_rx_msg_list = NULL; + ssl->dtls_rx_msg_list_sz = 0; } XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR); ssl->buffers.dtlsCtx.peer.sa = NULL; +#ifndef NO_WOLFSSL_SERVER + XFREE(ssl->buffers.dtlsCookieSecret.buffer, ssl->heap, + DYNAMIC_TYPE_COOKIE_PWD); #endif -#if defined(KEEP_PEER_CERT) || defined(GOAHEAD_WS) - FreeX509(&ssl->peerCert); -#endif -#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS) - wolfSSL_BIO_free(ssl->biord); - if (ssl->biord != ssl->biowr) /* in case same as write */ +#endif /* WOLFSSL_DTLS */ +#ifdef OPENSSL_EXTRA + if (ssl->biord != ssl->biowr) /* only free write if different */ wolfSSL_BIO_free(ssl->biowr); + wolfSSL_BIO_free(ssl->biord); /* always free read bio */ + ssl->biowr = NULL; + ssl->biord = NULL; #endif #ifdef HAVE_LIBZ 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); - } - 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); + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; +#endif +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) ||defined(HAVE_CURVE448) + { + int dtype = 0; + #ifdef HAVE_ECC + dtype = DYNAMIC_TYPE_ECC; + #endif + #ifdef HAVE_CURVE25519 + if (ssl->peerX25519KeyPresent + #ifdef HAVE_ECC + || ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519 + #endif /* HAVE_ECC */ + ) + { + dtype = DYNAMIC_TYPE_CURVE25519; + } + #endif /* HAVE_CURVE25519 */ + #ifdef HAVE_CURVE448 + if (ssl->peerX448KeyPresent + #ifdef HAVE_ECC + || ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE448 + #endif /* HAVE_ECC */ + ) + { + dtype = DYNAMIC_TYPE_CURVE448; + } + #endif /* HAVE_CURVE448 */ + FreeKey(ssl, dtype, (void**)&ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; } +#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ +#ifdef HAVE_CURVE25519 + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; +#endif +#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_CURVE448 + FreeKey(ssl, DYNAMIC_TYPE_CURVE448, (void**)&ssl->peerX448Key); + ssl->peerX448KeyPresent = 0; +#endif +#ifdef HAVE_ED448 + FreeKey(ssl, DYNAMIC_TYPE_ED448, (void**)&ssl->peerEd448Key); + ssl->peerEd448KeyPresent = 0; + #ifdef HAVE_PK_CALLBACKS + if (ssl->buffers.peerEd448Key.buffer != NULL) { + XFREE(ssl->buffers.peerEd448Key.buffer, ssl->heap, + DYNAMIC_TYPE_ED448); + ssl->buffers.peerEd448Key.buffer = NULL; + } + #endif #endif #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC @@ -1833,38 +6372,105 @@ void SSL_ResourceFree(WOLFSSL* ssl) #endif /* NO_RSA */ #endif /* HAVE_PK_CALLBACKS */ #ifdef HAVE_TLS_EXTENSIONS - TLSX_FreeAll(ssl->extensions); + TLSX_FreeAll(ssl->extensions, ssl->heap); + +#ifdef HAVE_ALPN + if (ssl->alpn_client_list != NULL) { + XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN); + ssl->alpn_client_list = NULL; + } +#endif +#endif /* HAVE_TLS_EXTENSIONS */ +#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + if (ssl->mnCtx) { + mynewt_ctx_clear(ssl->mnCtx); + ssl->mnCtx = NULL; + } #endif #ifdef HAVE_NETX if (ssl->nxCtx.nxPacket) nx_packet_release(ssl->nxCtx.nxPacket); #endif -} +#ifdef KEEP_PEER_CERT + FreeX509(&ssl->peerCert); +#endif -#ifdef WOLFSSL_TI_HASH -static void HashFinal(WOLFSSL * ssl) { - byte dummyHash[32] ; -#ifndef NO_MD5 - wc_Md5Final(&(ssl->hsHashes->hashMd5), dummyHash) ; +#ifdef HAVE_SESSION_TICKET + if (ssl->session.isDynamic) { + XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ssl->session.ticket = ssl->session.staticTicket; + ssl->session.isDynamic = 0; + ssl->session.ticketLen = 0; + } #endif -#ifndef NO_SHA - wc_ShaFinal(&(ssl->hsHashes->hashSha), dummyHash) ; +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(ssl->extSession); #endif -#ifndef NO_SHA256 - wc_Sha256Final(&(ssl->hsHashes->hashSha256), dummyHash) ; +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite) { + FreeWriteDup(ssl); + } +#endif +#ifdef OPENSSL_EXTRA + if (ssl->param) { + XFREE(ssl->param, ssl->heap, DYNAMIC_TYPE_OPENSSL); + } +#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 */ + if (ssl->heap != NULL) { + #ifdef WOLFSSL_HEAP_TEST + /* avoid dereferencing a test value */ + if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) { + #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) { + WOLFSSL_MSG("Bad memory_mutex lock"); + } + ctx_heap->curIO--; + if (FreeFixedIO(ctx_heap, &(ssl_hint->outBuf)) != 1) { + WOLFSSL_MSG("Error freeing fixed output buffer"); + } + if (FreeFixedIO(ctx_heap, &(ssl_hint->inBuf)) != 1) { + WOLFSSL_MSG("Error freeing fixed output buffer"); + } + if (ssl_hint->haFlag) { /* check if handshake count has been decreased*/ + ctx_heap->curHa--; + } + wc_UnLockMutex(&(ctx_heap->memory_mutex)); + + /* check if tracking stats */ + if (ctx_heap->flag & WOLFMEM_TRACK_STATS) { + XFREE(ssl_hint->stats, heap, DYNAMIC_TYPE_SSL); + } + XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL); + #ifdef WOLFSSL_HEAP_TEST + } + #endif + } +#endif /* WOLFSSL_STATIC_MEMORY */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + wolfSSL_sk_CIPHER_free(ssl->supportedCiphers); + wolfSSL_sk_X509_free(ssl->peerCertChain); #endif } -#else - - #define HashFinal(ssl) - -#endif /* Free any handshake resources no longer needed */ void FreeHandshakeResources(WOLFSSL* ssl) { - HashFinal(ssl) ; #ifdef HAVE_SECURE_RENEGOTIATION if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) { WOLFSSL_MSG("Secure Renegotiation needs to retain handshake resources"); @@ -1876,100 +6482,147 @@ void FreeHandshakeResources(WOLFSSL* ssl) if (ssl->buffers.inputBuffer.dynamicFlag) ShrinkInputBuffer(ssl, NO_FORCED_FREE); - /* suites */ - XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); - ssl->suites = NULL; - - /* hsHashes */ - XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); - ssl->hsHashes = NULL; +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (!ssl->options.tls1_3) +#endif + { + #ifndef OPENSSL_ALL + /* free suites unless using compatibility layer */ + FreeSuites(ssl); + #endif + /* hsHashes */ + FreeHandshakeHashes(ssl); + } /* RNG */ - if (ssl->specs.cipher_type == stream || ssl->options.tls1_1 == 0) { - wc_FreeRng(ssl->rng); - XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); - ssl->rng = NULL; + if (ssl->options.tls1_1 == 0 +#ifndef WOLFSSL_AEAD_ONLY + || ssl->specs.cipher_type == stream +#endif +#if defined(WOLFSSL_TLS13) + #if !defined(WOLFSSL_POST_HANDSHAKE_AUTH) + || ssl->options.tls1_3 + #elif !defined(HAVE_SESSION_TICKET) + || (ssl->options.tls1_3 && ssl->options.side == WOLFSSL_SERVER_END) + #endif +#endif + ) { + if (ssl->options.weOwnRng) { + wc_FreeRng(ssl->rng); + XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); + ssl->rng = NULL; + ssl->options.weOwnRng = 0; + } } #ifdef WOLFSSL_DTLS /* DTLS_POOL */ - if (ssl->options.dtls && ssl->dtls_pool != NULL) { - DtlsPoolReset(ssl); - XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_DTLS_POOL); - ssl->dtls_pool = NULL; + if (ssl->options.dtls) { + DtlsMsgPoolReset(ssl); + DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap); + ssl->dtls_rx_msg_list = NULL; + ssl->dtls_rx_msg_list_sz = 0; } #endif - /* arrays */ - if (ssl->options.saveArrays == 0) - FreeArrays(ssl, 1); +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) && \ + defined(HAVE_SESSION_TICKET) + if (!ssl->options.tls1_3) +#endif + /* arrays */ + if (ssl->options.saveArrays == 0) + FreeArrays(ssl, 1); +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (!ssl->options.tls1_3 || ssl->options.side == WOLFSSL_CLIENT_END) +#endif + { #ifndef NO_RSA - /* peerRsaKey */ - if (ssl->peerRsaKey) { - wc_FreeRsaKey(ssl->peerRsaKey); - XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA); - ssl->peerRsaKey = NULL; - } + /* peerRsaKey */ + FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; #endif +#ifdef HAVE_ECC + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; +#endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; +#endif /* HAVE_ED25519 */ +#ifdef HAVE_ED448 + FreeKey(ssl, DYNAMIC_TYPE_ED448, (void**)&ssl->peerEd448Key); + ssl->peerEd448KeyPresent = 0; +#endif /* HAVE_ED448 */ + } #ifdef HAVE_ECC - if (ssl->peerEccKey) - { - if (ssl->peerEccKeyPresent) { - wc_ecc_free(ssl->peerEccKey); - ssl->peerEccKeyPresent = 0; - } - XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); - ssl->peerEccKey = NULL; - } - 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; - } + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; #endif +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) + { + int dtype; + #ifdef HAVE_ECC + dtype = DYNAMIC_TYPE_ECC; + #endif + #ifdef HAVE_CURVE25519 + #ifdef HAVE_ECC + if (ssl->peerX25519KeyPresent || + ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519) + #endif /* HAVE_ECC */ + { + dtype = DYNAMIC_TYPE_CURVE25519; + } + #endif /* HAVE_CURVE25519 */ + #ifdef HAVE_CURVE448 + #ifdef HAVE_ECC + if (ssl->peerX448KeyPresent || + ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE448) + #endif /* HAVE_ECC */ + { + dtype = DYNAMIC_TYPE_CURVE448; + } + #endif /* HAVE_CURVE448 */ + FreeKey(ssl, dtype, (void**)&ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; + } +#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ +#ifdef HAVE_CURVE25519 + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; +#endif +#ifdef HAVE_CURVE448 + FreeKey(ssl, DYNAMIC_TYPE_CURVE448, (void**)&ssl->peerX448Key); + ssl->peerX448KeyPresent = 0; +#endif + #ifndef NO_DH - XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_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_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); + if (ssl->buffers.weOwnDH) { + 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 +#endif /* !NO_DH */ + #ifndef NO_CERTS - if (ssl->buffers.weOwnCert) { - XFREE(ssl->buffers.certificate.buffer, ssl->heap, DYNAMIC_TYPE_CERT); - ssl->buffers.certificate.buffer = NULL; - } - if (ssl->buffers.weOwnCertChain) { - XFREE(ssl->buffers.certChain.buffer, ssl->heap, DYNAMIC_TYPE_CERT); - ssl->buffers.certChain.buffer = NULL; - } - if (ssl->buffers.weOwnKey) { - XFREE(ssl->buffers.key.buffer, ssl->heap, DYNAMIC_TYPE_KEY); - ssl->buffers.key.buffer = NULL; - } + wolfSSL_UnloadCertsKeys(ssl); #endif #ifdef HAVE_PK_CALLBACKS +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (!ssl->options.tls1_3 || ssl->options.side == WOLFSSL_CLIENT_END) +#endif + { #ifdef HAVE_ECC XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC); ssl->buffers.peerEccDsaKey.buffer = NULL; @@ -1978,134 +6631,196 @@ 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 + #ifdef HAVE_ED448 + XFREE(ssl->buffers.peerEd448Key.buffer, ssl->heap, DYNAMIC_TYPE_ED448); + ssl->buffers.peerEd448Key.buffer = NULL; + #endif + } #endif /* HAVE_PK_CALLBACKS */ + +#ifdef HAVE_QSH + QSH_FreeAll(ssl); +#endif + +#ifdef HAVE_SESSION_TICKET + if (ssl->session.isDynamic) { + XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ssl->session.ticket = ssl->session.staticTicket; + ssl->session.isDynamic = 0; + ssl->session.ticketLen = 0; + } +#endif + +#if defined(HAVE_TLS_EXTENSIONS) && !defined(HAVE_SNI) && \ + !defined(HAVE_ALPN) && !defined(WOLFSSL_POST_HANDSHAKE_AUTH) + /* Some extensions need to be kept for post-handshake querying. */ + TLSX_FreeAll(ssl->extensions, ssl->heap); + ssl->extensions = NULL; +#endif + +#ifdef WOLFSSL_STATIC_MEMORY + /* when done with handshake decrement current handshake count */ + if (ssl->heap != NULL) { + #ifdef WOLFSSL_HEAP_TEST + /* avoid dereferencing a test value */ + if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) { + #endif + WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap; + WOLFSSL_HEAP* ctx_heap; + + ctx_heap = ssl_hint->memory; + if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + } + ctx_heap->curHa--; + ssl_hint->haFlag = 0; /* set to zero since handshake has been dec */ + wc_UnLockMutex(&(ctx_heap->memory_mutex)); + #ifdef WOLFSSL_HEAP_TEST + } + #endif + } +#endif /* WOLFSSL_STATIC_MEMORY */ } -void FreeSSL(WOLFSSL* ssl) +/* heap argument is the heap hint used when creating SSL */ +void FreeSSL(WOLFSSL* ssl, void* heap) { - FreeSSL_Ctx(ssl->ctx); /* will decrement and free underyling CTX if 0 */ + if (ssl->ctx) { + FreeSSL_Ctx(ssl->ctx); /* will decrement and free underlying CTX if 0 */ + } SSL_ResourceFree(ssl); - XFREE(ssl, ssl->heap, DYNAMIC_TYPE_SSL); + XFREE(ssl, heap, DYNAMIC_TYPE_SSL); + (void)heap; } +#if !defined(NO_OLD_TLS) || defined(WOLFSSL_DTLS) || \ + ((defined(HAVE_CHACHA) || defined(HAVE_AESCCM) || defined(HAVE_AESGCM)) \ + && defined(HAVE_AEAD)) + +#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) +static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2]) +{ + if (verify) { + seq[0] = ssl->keys.peer_sequence_number_hi; + seq[1] = ssl->keys.peer_sequence_number_lo++; + if (seq[1] > ssl->keys.peer_sequence_number_lo) { + /* handle rollover */ + ssl->keys.peer_sequence_number_hi++; + } + } + else { + seq[0] = ssl->keys.sequence_number_hi; + seq[1] = ssl->keys.sequence_number_lo++; + if (seq[1] > ssl->keys.sequence_number_lo) { + /* handle rollover */ + ssl->keys.sequence_number_hi++; + } + } +} +#endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 */ + #ifdef WOLFSSL_DTLS - -int DtlsPoolInit(WOLFSSL* ssl) +static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2]) { - if (ssl->dtls_pool == NULL) { - DtlsPool *pool = (DtlsPool*)XMALLOC(sizeof(DtlsPool), - ssl->heap, DYNAMIC_TYPE_DTLS_POOL); - if (pool == NULL) { - WOLFSSL_MSG("DTLS Buffer Pool Memory error"); - return MEMORY_E; - } - else { - int i; - - for (i = 0; i < DTLS_POOL_SZ; i++) { - pool->buf[i].length = 0; - pool->buf[i].buffer = NULL; - } - pool->used = 0; - ssl->dtls_pool = pool; + if (order == PREV_ORDER) { + /* Previous epoch case */ + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + seq[0] = (((word32)ssl->keys.dtls_epoch - 1) << 16) | + (ssl->options.mcastID << 8) | + (ssl->keys.dtls_prev_sequence_number_hi & 0xFF); + #endif } + else + seq[0] = (((word32)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) { + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + seq[0] = ((word32)ssl->keys.curEpoch << 16) | + (ssl->keys.curPeerId << 8) | + (ssl->keys.curSeq_hi & 0xFF); + #endif + } + else + seq[0] = ((word32)ssl->keys.curEpoch << 16) | + (ssl->keys.curSeq_hi & 0xFFFF); + seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */ + } + else { + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + seq[0] = ((word32)ssl->keys.dtls_epoch << 16) | + (ssl->options.mcastID << 8) | + (ssl->keys.dtls_sequence_number_hi & 0xFF); + #endif + } + else + seq[0] = ((word32)ssl->keys.dtls_epoch << 16) | + (ssl->keys.dtls_sequence_number_hi & 0xFFFF); + seq[1] = ssl->keys.dtls_sequence_number_lo; } - return 0; } - -int DtlsPoolSave(WOLFSSL* ssl, const byte *src, int sz) +static WC_INLINE void DtlsSEQIncrement(WOLFSSL* ssl, int order) { - DtlsPool *pool = ssl->dtls_pool; - if (pool != NULL && pool->used < DTLS_POOL_SZ) { - buffer *pBuf = &pool->buf[pool->used]; - pBuf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_DTLS_POOL); - if (pBuf->buffer == NULL) { - WOLFSSL_MSG("DTLS Buffer Memory error"); - return MEMORY_ERROR; - } - XMEMCPY(pBuf->buffer, src, sz); - pBuf->length = (word32)sz; - pool->used++; - } - return 0; -} + word32 seq; - -void DtlsPoolReset(WOLFSSL* ssl) -{ - DtlsPool *pool = ssl->dtls_pool; - if (pool != NULL) { - buffer *pBuf; - int i, used; - - used = pool->used; - for (i = 0, pBuf = &pool->buf[0]; i < used; i++, pBuf++) { - XFREE(pBuf->buffer, ssl->heap, DYNAMIC_TYPE_DTLS_POOL); - pBuf->buffer = NULL; - pBuf->length = 0; - } - pool->used = 0; - } - ssl->dtls_timeout = ssl->dtls_timeout_init; -} - - -int DtlsPoolTimeout(WOLFSSL* ssl) -{ - int result = -1; - if (ssl->dtls_timeout < ssl->dtls_timeout_max) { - ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER; - result = 0; - } - return result; -} - - -int DtlsPoolSend(WOLFSSL* ssl) -{ - int ret; - DtlsPool *pool = ssl->dtls_pool; - - if (pool != NULL && pool->used > 0) { - int i; - for (i = 0; i < pool->used; i++) { - int sendResult; - buffer* buf = &pool->buf[i]; - - DtlsRecordLayerHeader* dtls = (DtlsRecordLayerHeader*)buf->buffer; - - word16 message_epoch; - ato16(dtls->epoch, &message_epoch); - if (message_epoch == ssl->keys.dtls_epoch) { - /* Increment record sequence number on retransmitted handshake - * messages */ - c32to48(ssl->keys.dtls_sequence_number, dtls->sequence_number); - ssl->keys.dtls_sequence_number++; - } - else { - /* The Finished message is sent with the next epoch, keep its - * sequence number */ - } - - if ((ret = CheckAvailableSize(ssl, buf->length)) != 0) - return ret; - - XMEMCPY(ssl->buffers.outputBuffer.buffer, buf->buffer, buf->length); - ssl->buffers.outputBuffer.idx = 0; - ssl->buffers.outputBuffer.length = buf->length; - - sendResult = SendBuffered(ssl); - if (sendResult < 0) { - return sendResult; - } + if (order == PREV_ORDER) { + seq = ssl->keys.dtls_prev_sequence_number_lo++; + if (seq > ssl->keys.dtls_prev_sequence_number_lo) { + /* handle rollover */ + ssl->keys.dtls_prev_sequence_number_hi++; + } + } + else if (order == PEER_ORDER) { + seq = ssl->keys.peer_sequence_number_lo++; + if (seq > ssl->keys.peer_sequence_number_lo) { + /* handle rollover */ + ssl->keys.peer_sequence_number_hi++; + } + } + else { + seq = ssl->keys.dtls_sequence_number_lo++; + if (seq > ssl->keys.dtls_sequence_number_lo) { + /* handle rollover */ + ssl->keys.dtls_sequence_number_hi++; } } - return 0; } +#endif /* WOLFSSL_DTLS */ +#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) +static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out) +{ + word32 seq[2] = {0, 0}; + + if (!ssl->options.dtls) { + GetSEQIncrement(ssl, verifyOrder, seq); + } + else { +#ifdef WOLFSSL_DTLS + DtlsGetSEQ(ssl, verifyOrder, seq); +#endif + } + + c32toa(seq[0], out); + c32toa(seq[1], out + OPAQUE32_LEN); +} +#endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 */ +#endif /* !NO_OLD_TLS || WOLFSSL_DTLS || + * ((HAVE_CHACHA || HAVE_AESCCM || HAVE_AESGCM) && HAVE_AEAD) */ + +#ifdef WOLFSSL_DTLS /* functions for managing DTLS datagram reordering */ @@ -2116,18 +6831,18 @@ int DtlsPoolSend(WOLFSSL* ssl) * extra space for the headers. */ DtlsMsg* DtlsMsgNew(word32 sz, void* heap) { - DtlsMsg* msg = NULL; + DtlsMsg* msg; + (void)heap; msg = (DtlsMsg*)XMALLOC(sizeof(DtlsMsg), heap, DYNAMIC_TYPE_DTLS_MSG); if (msg != NULL) { + XMEMSET(msg, 0, sizeof(DtlsMsg)); msg->buf = (byte*)XMALLOC(sz + DTLS_HANDSHAKE_HEADER_SZ, - heap, DYNAMIC_TYPE_NONE); + heap, DYNAMIC_TYPE_DTLS_BUFFER); if (msg->buf != NULL) { - msg->next = NULL; - msg->seq = 0; msg->sz = sz; - msg->fragSz = 0; + msg->type = no_shake; msg->msg = msg->buf + DTLS_HANDSHAKE_HEADER_SZ; } else { @@ -2144,8 +6859,14 @@ void DtlsMsgDelete(DtlsMsg* item, void* heap) (void)heap; if (item != NULL) { + DtlsFrag* cur = item->fragList; + while (cur != NULL) { + DtlsFrag* next = cur->next; + XFREE(cur, heap, DYNAMIC_TYPE_DTLS_FRAG); + cur = next; + } if (item->buf != NULL) - XFREE(item->buf, heap, DYNAMIC_TYPE_NONE); + XFREE(item->buf, heap, DYNAMIC_TYPE_DTLS_BUFFER); XFREE(item, heap, DYNAMIC_TYPE_DTLS_MSG); } } @@ -2162,32 +6883,128 @@ void DtlsMsgListDelete(DtlsMsg* head, void* heap) } -void DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type, - word32 fragOffset, word32 fragSz) +/* Create a DTLS Fragment from *begin - end, adjust new *begin and bytesLeft */ +static DtlsFrag* CreateFragment(word32* begin, word32 end, const byte* data, + byte* buf, word32* bytesLeft, void* heap) +{ + DtlsFrag* newFrag; + word32 added = end - *begin + 1; + + (void)heap; + newFrag = (DtlsFrag*)XMALLOC(sizeof(DtlsFrag), heap, + DYNAMIC_TYPE_DTLS_FRAG); + if (newFrag != NULL) { + newFrag->next = NULL; + newFrag->begin = *begin; + newFrag->end = end; + + XMEMCPY(buf + *begin, data, added); + *bytesLeft -= added; + *begin = newFrag->end + 1; + } + + return newFrag; +} + + +int DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type, + word32 fragOffset, word32 fragSz, void* heap) { if (msg != NULL && data != NULL && msg->fragSz <= msg->sz && - fragOffset <= msg->sz && (fragOffset + fragSz) <= msg->sz) { + (fragOffset + fragSz) <= msg->sz) { + DtlsFrag* cur = msg->fragList; + DtlsFrag* prev = cur; + DtlsFrag* newFrag; + word32 bytesLeft = fragSz; /* could be overlapping fragment */ + word32 startOffset = fragOffset; + word32 added; msg->seq = seq; msg->type = type; - msg->fragSz += fragSz; - /* If fragOffset is zero, this is either a full message that is out - * of order, or the first fragment of a fragmented message. Copy the - * handshake message header with the message data. Zero length messages - * like Server Hello Done should be saved as well. */ - if (fragOffset == 0) + + if (fragOffset == 0) { XMEMCPY(msg->buf, data - DTLS_HANDSHAKE_HEADER_SZ, - fragSz + DTLS_HANDSHAKE_HEADER_SZ); - else { - /* If fragOffet is non-zero, this is an additional fragment that - * needs to be copied to its location in the message buffer. Also - * copy the total size of the message over the fragment size. The - * hash routines look at a defragmented message if it had actually - * come across as a single handshake message. */ - XMEMCPY(msg->msg + fragOffset, data, fragSz); + DTLS_HANDSHAKE_HEADER_SZ); + c32to24(msg->sz, msg->msg - DTLS_HANDSHAKE_FRAG_SZ); + } + + /* if no message data, just return */ + if (fragSz == 0) + return 0; + + /* if list is empty add full fragment to front */ + if (cur == NULL) { + newFrag = CreateFragment(&fragOffset, fragOffset + fragSz - 1, data, + msg->msg, &bytesLeft, heap); + if (newFrag == NULL) + return MEMORY_E; + + msg->fragSz = fragSz; + msg->fragList = newFrag; + + return 0; + } + + /* add to front if before current front, up to next->begin */ + if (fragOffset < cur->begin) { + word32 end = fragOffset + fragSz - 1; + + if (end >= cur->begin) + end = cur->begin - 1; + + added = end - fragOffset + 1; + newFrag = CreateFragment(&fragOffset, end, data, msg->msg, + &bytesLeft, heap); + if (newFrag == NULL) + return MEMORY_E; + + msg->fragSz += added; + + newFrag->next = cur; + msg->fragList = newFrag; + } + + /* while we have bytes left, try to find a gap to fill */ + while (bytesLeft > 0) { + /* get previous packet in list */ + while (cur && (fragOffset >= cur->begin)) { + prev = cur; + cur = cur->next; + } + + /* don't add duplicate data */ + if (prev->end >= fragOffset) { + if ( (fragOffset + bytesLeft - 1) <= prev->end) + return 0; + fragOffset = prev->end + 1; + bytesLeft = startOffset + fragSz - fragOffset; + } + + if (cur == NULL) + /* we're at the end */ + added = bytesLeft; + else + /* we're in between two frames */ + added = min(bytesLeft, cur->begin - fragOffset); + + /* data already there */ + if (added == 0) + continue; + + newFrag = CreateFragment(&fragOffset, fragOffset + added - 1, + data + fragOffset - startOffset, + msg->msg, &bytesLeft, heap); + if (newFrag == NULL) + return MEMORY_E; + + msg->fragSz += added; + + newFrag->next = prev->next; + prev->next = newFrag; } - c32to24(msg->sz, msg->msg - DTLS_HANDSHAKE_FRAG_SZ); } + + return 0; } @@ -2200,44 +7017,60 @@ DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 seq) } -DtlsMsg* DtlsMsgStore(DtlsMsg* head, word32 seq, const byte* data, +void DtlsMsgStore(WOLFSSL* ssl, word32 seq, const byte* data, word32 dataSz, byte type, word32 fragOffset, word32 fragSz, void* heap) { - /* See if seq exists in the list. If it isn't in the list, make * a new item of size dataSz, copy fragSz bytes from data to msg->msg * starting at offset fragOffset, and add fragSz to msg->fragSz. If * the seq is in the list and it isn't full, copy fragSz bytes from * data to msg->msg starting at offset fragOffset, and add fragSz to - * msg->fragSz. The new item should be inserted into the list in its + * msg->fragSz. Insertions take into account data already in the list + * in case there are overlaps in the handshake message due to retransmit + * messages. The new item should be inserted into the list in its * proper position. * * 1. Find seq in list, or where seq should go in list. If seq not in * list, create new item and insert into list. Either case, keep * pointer to item. - * 2. If msg->fragSz + fragSz < sz, copy data to msg->msg at offset - * fragOffset. Add fragSz to msg->fragSz. + * 2. Copy the data from the message to the stored message where it + * belongs without overlaps. */ + DtlsMsg* head = ssl->dtls_rx_msg_list; + if (head != NULL) { DtlsMsg* cur = DtlsMsgFind(head, seq); if (cur == NULL) { cur = DtlsMsgNew(dataSz, heap); if (cur != NULL) { - DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz); - head = DtlsMsgInsert(head, cur); + if (DtlsMsgSet(cur, seq, data, type, + fragOffset, fragSz, heap) < 0) { + DtlsMsgDelete(cur, heap); + } + else { + ssl->dtls_rx_msg_list_sz++; + head = DtlsMsgInsert(head, cur); + } } } else { - DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz); + /* If this fails, the data is just dropped. */ + DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz, heap); } } else { head = DtlsMsgNew(dataSz, heap); - DtlsMsgSet(head, seq, data, type, fragOffset, fragSz); + if (DtlsMsgSet(head, seq, data, type, fragOffset, fragSz, heap) < 0) { + DtlsMsgDelete(head, heap); + head = NULL; + } + else { + ssl->dtls_rx_msg_list_sz++; + } } - return head; + ssl->dtls_rx_msg_list = head; } @@ -2271,9 +7104,202 @@ DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item) return head; } + +/* DtlsMsgPoolSave() adds the message to the end of the stored transmit list. */ +int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz) +{ + DtlsMsg* item; + int ret = 0; + + WOLFSSL_ENTER("DtlsMsgPoolSave()"); + + if (ssl->dtls_tx_msg_list_sz > DTLS_POOL_SZ) { + WOLFSSL_ERROR(DTLS_POOL_SZ_E); + return DTLS_POOL_SZ_E; + } + + item = DtlsMsgNew(dataSz, ssl->heap); + + if (item != NULL) { + DtlsMsg* cur = ssl->dtls_tx_msg_list; + + XMEMCPY(item->buf, data, dataSz); + item->sz = dataSz; + item->seq = ssl->keys.dtls_epoch; + + if (cur == NULL) + ssl->dtls_tx_msg_list = item; + else { + while (cur->next) + cur = cur->next; + cur->next = item; + } + ssl->dtls_tx_msg_list_sz++; + } + else + ret = MEMORY_E; + + WOLFSSL_LEAVE("DtlsMsgPoolSave()", ret); + return ret; +} + + +/* DtlsMsgPoolTimeout() updates the timeout time. */ +int DtlsMsgPoolTimeout(WOLFSSL* ssl) +{ + int result = -1; + if (ssl->dtls_timeout < ssl->dtls_timeout_max) { + ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER; + result = 0; + } + WOLFSSL_LEAVE("DtlsMsgPoolTimeout()", result); + return result; +} + + +/* DtlsMsgPoolReset() deletes the stored transmit list and resets the timeout + * value. */ +void DtlsMsgPoolReset(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("DtlsMsgPoolReset()"); + if (ssl->dtls_tx_msg_list) { + DtlsMsgListDelete(ssl->dtls_tx_msg_list, ssl->heap); + ssl->dtls_tx_msg_list = NULL; + ssl->dtls_tx_msg = NULL; + ssl->dtls_tx_msg_list_sz = 0; + ssl->dtls_timeout = ssl->dtls_timeout_init; + } +} + + +int VerifyForDtlsMsgPoolSend(WOLFSSL* ssl, byte type, word32 fragOffset) +{ + /** + * only the first message from previous flight should be valid + * to be used for triggering retransmission of whole DtlsMsgPool. + * change cipher suite type is not verified here + */ + return ((fragOffset == 0) && + (((ssl->options.side == WOLFSSL_SERVER_END) && + ((type == client_hello) || + ((ssl->options.verifyPeer) && (type == certificate)) || + ((!ssl->options.verifyPeer) && (type == client_key_exchange)))) || + ((ssl->options.side == WOLFSSL_CLIENT_END) && + (type == server_hello)))); +} + + +/* DtlsMsgPoolSend() will send the stored transmit list. The stored list is + * updated with new sequence numbers, and will be re-encrypted if needed. */ +int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) +{ + int ret = 0; + DtlsMsg* pool; + + WOLFSSL_ENTER("DtlsMsgPoolSend()"); + + pool = ssl->dtls_tx_msg == NULL ? ssl->dtls_tx_msg_list : ssl->dtls_tx_msg; + + if (pool != NULL) { + if ((ssl->options.side == WOLFSSL_SERVER_END && + !(ssl->options.acceptState == SERVER_HELLO_DONE || + ssl->options.acceptState == ACCEPT_FINISHED_DONE || + ssl->options.acceptState == ACCEPT_THIRD_REPLY_DONE)) || + (ssl->options.side == WOLFSSL_CLIENT_END && + !(ssl->options.connectState == CLIENT_HELLO_SENT || + ssl->options.connectState == HELLO_AGAIN_REPLY || + ssl->options.connectState == FINISHED_DONE || + ssl->options.connectState == SECOND_REPLY_DONE))) { + + WOLFSSL_ERROR(DTLS_RETX_OVER_TX); + ssl->error = DTLS_RETX_OVER_TX; + return WOLFSSL_FATAL_ERROR; + } + + while (pool != NULL) { + if (pool->seq == 0) { + DtlsRecordLayerHeader* dtls; + int epochOrder; + + dtls = (DtlsRecordLayerHeader*)pool->buf; + /* If the stored record's epoch is 0, and the currently set + * epoch is 0, use the "current order" sequence number. + * If the stored record's epoch is 0 and the currently set + * epoch is not 0, the stored record is considered a "previous + * order" sequence number. */ + epochOrder = (ssl->keys.dtls_epoch == 0) ? + CUR_ORDER : PREV_ORDER; + + WriteSEQ(ssl, epochOrder, dtls->sequence_number); + DtlsSEQIncrement(ssl, epochOrder); + if ((ret = CheckAvailableSize(ssl, pool->sz)) != 0) { + WOLFSSL_ERROR(ret); + return ret; + } + + XMEMCPY(ssl->buffers.outputBuffer.buffer, + pool->buf, pool->sz); + ssl->buffers.outputBuffer.idx = 0; + ssl->buffers.outputBuffer.length = pool->sz; + } + else if (pool->seq == ssl->keys.dtls_epoch) { + byte* input; + byte* output; + int inputSz, sendSz; + + input = pool->buf; + inputSz = pool->sz; + sendSz = inputSz + MAX_MSG_EXTRA; + + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + WOLFSSL_ERROR(ret); + return ret; + } + + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 0, 0, 0); + if (sendSz < 0) { + WOLFSSL_ERROR(BUILD_MSG_ERROR); + return BUILD_MSG_ERROR; + } + + ssl->buffers.outputBuffer.length += sendSz; + } + + ret = SendBuffered(ssl); + if (ret < 0) { + WOLFSSL_ERROR(ret); + return ret; + } + + /** + * on server side, retransmission is being triggered only by sending + * first message of given flight, in order to trigger client + * to retransmit its whole flight. Sending the whole previous flight + * could lead to retransmission of previous client flight for each + * server message from previous flight. Therefore one message should + * be enough to do the trick. + */ + if (sendOnlyFirstPacket && + ssl->options.side == WOLFSSL_SERVER_END) { + + pool = NULL; + } + else + pool = pool->next; + ssl->dtls_tx_msg = pool; + } + } + + WOLFSSL_LEAVE("DtlsMsgPoolSend()", ret); + return ret; +} + #endif /* WOLFSSL_DTLS */ -#ifndef NO_OLD_TLS +#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) ProtocolVersion MakeSSLv3(void) { @@ -2284,7 +7310,7 @@ ProtocolVersion MakeSSLv3(void) return pv; } -#endif /* NO_OLD_TLS */ +#endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */ #ifdef WOLFSSL_DTLS @@ -2298,6 +7324,8 @@ ProtocolVersion MakeDTLSv1(void) return pv; } +#ifndef WOLFSSL_NO_TLS12 + ProtocolVersion MakeDTLSv1_2(void) { ProtocolVersion pv; @@ -2307,12 +7335,38 @@ ProtocolVersion MakeDTLSv1_2(void) return pv; } +#endif /* !WOLFSSL_NO_TLS12 */ + #endif /* WOLFSSL_DTLS */ +#ifndef NO_ASN_TIME +#if defined(USER_TICKS) +#if 0 + word32 LowResTimer(void) + { + /* + write your own clock tick function if don't want time(0) + needs second accuracy but doesn't have to correlated to EPOCH + */ + } +#endif +#elif defined(TIME_OVERRIDES) -#ifdef USE_WINDOWS_API + /* use same asn time overrides unless user wants tick override above */ + + #ifndef HAVE_TIME_T_TYPE + typedef long time_t; + #endif + extern time_t XTIME(time_t * timer); + + word32 LowResTimer(void) + { + return (word32) XTIME(0); + } + +#elif defined(USE_WINDOWS_API) word32 LowResTimer(void) { @@ -2339,17 +7393,26 @@ ProtocolVersion MakeDTLSv1_2(void) return (word32)rtp_get_system_sec(); } +#elif defined(WOLFSSL_DEOS) + + word32 LowResTimer(void) + { + const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds(); + uint32_t *systemTickPtr = systemTickPointer(); + + return (word32) *systemTickPtr/systemTickTimeInHz; + } #elif defined(MICRIUM) word32 LowResTimer(void) { - NET_SECURE_OS_TICK clk; + 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); } @@ -2357,7 +7420,7 @@ ProtocolVersion MakeDTLSv1_2(void) word32 LowResTimer(void) { - return (word32) TickGet(); + return (word32) (TickGet() / TICKS_PER_SECOND); } @@ -2369,19 +7432,20 @@ ProtocolVersion MakeDTLSv1_2(void) word32 LowResTimer(void) { - return (word32) SYS_TMR_TickCountGet(); + return (word32) (SYS_TMR_TickCountGet() / + SYS_TMR_TickCounterFrequencyGet()); } #else word32 LowResTimer(void) { - return (word32) SYS_TICK_Get(); + return (word32) (SYS_TICK_Get() / SYS_TICK_TicksPerSecondGet()); } #endif -#elif defined(FREESCALE_MQX) +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) word32 LowResTimer(void) { @@ -2391,6 +7455,31 @@ ProtocolVersion MakeDTLSv1_2(void) return (word32) mqxTime.SECONDS; } +#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) + + #include "include/task.h" + + unsigned int LowResTimer(void) + { + return (unsigned int)(((float)xTaskGetTickCount())/configTICK_RATE_HZ); + } + +#elif defined(FREERTOS) + + #include "task.h" + + unsigned int LowResTimer(void) + { + return (unsigned int)(((float)xTaskGetTickCount())/configTICK_RATE_HZ); + } + +#elif defined(FREESCALE_KSDK_BM) + + #include "lwip/sys.h" /* lwIP */ + word32 LowResTimer(void) + { + return sys_now()/1000; + } #elif defined(WOLFSSL_TIRTOS) @@ -2398,49 +7487,172 @@ ProtocolVersion MakeDTLSv1_2(void) { return (word32) Seconds_get(); } +#elif defined(WOLFSSL_XILINX) + #include "xrtcpsu.h" -#elif defined(USER_TICKS) -#if 0 word32 LowResTimer(void) { - /* - write your own clock tick function if don't want time(0) - needs second accuracy but doesn't have to correlated to EPOCH - */ + 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) + + word32 LowResTimer(void) + { + return (word32)(uTaskerSystemTick / TICK_RESOLUTION); + } + +#elif defined(WOLFSSL_NUCLEUS_1_2) + + #define NU_TICKS_PER_SECOND 100 + + word32 LowResTimer(void) + { + /* returns number of 10ms ticks, so 100 ticks/sec */ + return NU_Retrieve_Clock() / NU_TICKS_PER_SECOND; + } +#elif defined(WOLFSSL_APACHE_MYNEWT) + + #include "os/os_time.h" + word32 LowResTimer(void) + { + word32 now; + struct os_timeval tv; + os_gettimeofday(&tv, NULL); + now = (word32)tv.tv_sec; + return now; + } + +#elif defined(WOLFSSL_ZEPHYR) + + word32 LowResTimer(void) + { + return k_uptime_get() / 1000; + } + +#else + /* Posix style time */ + #if !defined(USER_TIME) && !defined(USE_WOLF_TM) + #include + #endif + + word32 LowResTimer(void) + { + return (word32)XTIME(0); } #endif +#endif /* !NO_ASN_TIME */ +#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ + ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ + (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) +/* Store the message for use with CertificateVerify using EdDSA. + * + * ssl SSL/TLS object. + * data Message to store. + * sz Size of message to store. + * returns MEMORY_E if not able to reallocate, otherwise 0. + */ +static int EdDSA_Update(WOLFSSL* ssl, const byte* data, int sz) +{ + int ret = 0; + byte* msgs; -#elif defined(TIME_OVERRIDES) + if (ssl->options.cacheMessages) { + msgs = (byte*)XREALLOC(ssl->hsHashes->messages, + ssl->hsHashes->length + sz, + ssl->heap, DYNAMIC_TYPE_HASHES); + if (msgs == NULL) + ret = MEMORY_E; + if (ret == 0) { + ssl->hsHashes->messages = msgs; + XMEMCPY(msgs + ssl->hsHashes->length, data, sz); + ssl->hsHashes->prevLen = ssl->hsHashes->length; + ssl->hsHashes->length += sz; + } + } - /* use same asn time overrides unless user wants tick override above */ + return ret; +} +#endif /* (HAVE_ED25519 || HAVE_ED448) && !WOLFSSL_NO_CLIENT_AUTH */ - #ifndef HAVE_TIME_T_TYPE - typedef long time_t; +#ifndef NO_CERTS +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); +#endif +#ifndef NO_OLD_TLS + #ifndef NO_SHA + wc_ShaUpdate(&ssl->hsHashes->hashSha, output, sz); #endif - extern time_t XTIME(time_t * timer); + #ifndef NO_MD5 + wc_Md5Update(&ssl->hsHashes->hashMd5, output, sz); + #endif +#endif /* NO_OLD_TLS */ - word32 LowResTimer(void) - { - return (word32) XTIME(0); + if (IsAtLeastTLSv1_2(ssl)) { + #ifndef NO_SHA256 + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, output, sz); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_SHA384 + ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, output, sz); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_SHA512 + ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, output, sz); + if (ret != 0) + return ret; + #endif + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ + ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ + (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) + ret = EdDSA_Update(ssl, output, sz); + if (ret != 0) + return ret; + #endif } -#else /* !USE_WINDOWS_API && !HAVE_RTP_SYS && !MICRIUM && !USER_TICKS */ - - #include - - word32 LowResTimer(void) - { - return (word32)time(0); - } - - -#endif /* USE_WINDOWS_API */ + return ret; +} +#endif /* NO_CERTS */ /* 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) { - const byte* adj = output + RECORD_HEADER_SZ + ivSz; + int ret = 0; + const byte* adj; + + if (ssl->hsHashes == NULL) + return BAD_FUNC_ARG; + + adj = output + RECORD_HEADER_SZ + ivSz; sz -= RECORD_HEADER_SZ; #ifdef HAVE_FUZZER @@ -2454,44 +7666,54 @@ static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) } #endif #ifndef NO_OLD_TLS -#ifndef NO_SHA - wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz); -#endif -#ifndef NO_MD5 - wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz); -#endif + #ifndef NO_SHA + wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz); + #endif + #ifndef NO_MD5 + wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz); + #endif #endif if (IsAtLeastTLSv1_2(ssl)) { - int ret; - -#ifndef NO_SHA256 + #ifndef NO_SHA256 ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz); if (ret != 0) return ret; -#endif -#ifdef WOLFSSL_SHA384 + #endif + #ifdef WOLFSSL_SHA384 ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz); if (ret != 0) return ret; -#endif -#ifdef WOLFSSL_SHA512 + #endif + #ifdef WOLFSSL_SHA512 ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz); if (ret != 0) return ret; -#endif + #endif + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ + ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ + (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) + ret = EdDSA_Update(ssl, adj, sz); + if (ret != 0) + return ret; + #endif } - return 0; + return ret; } /* 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) { - const byte* adj = input - HANDSHAKE_HEADER_SZ; + int ret = 0; + const byte* adj; + + adj = input - HANDSHAKE_HEADER_SZ; sz += HANDSHAKE_HEADER_SZ; + (void)adj; + #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { adj -= DTLS_HANDSHAKE_EXTRA; @@ -2499,36 +7721,45 @@ 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); -#endif -#ifndef NO_MD5 - wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz); -#endif + #ifndef NO_SHA + wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz); + #endif + #ifndef NO_MD5 + wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz); + #endif #endif if (IsAtLeastTLSv1_2(ssl)) { - int ret; - -#ifndef NO_SHA256 + #ifndef NO_SHA256 ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz); if (ret != 0) return ret; -#endif -#ifdef WOLFSSL_SHA384 + #endif + #ifdef WOLFSSL_SHA384 ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz); if (ret != 0) return ret; -#endif -#ifdef WOLFSSL_SHA512 + #endif + #ifdef WOLFSSL_SHA512 ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz); if (ret != 0) return ret; -#endif + #endif + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ + ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ + (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) + ret = EdDSA_Update(ssl, adj, sz); + if (ret != 0) + return ret; + #endif } - return 0; + return ret; } @@ -2539,35 +7770,65 @@ static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl /* record layer header */ rl = (RecordLayerHeader*)output; + if (rl == NULL) { + return; + } 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)) { +#ifdef WOLFSSL_TLS13_DRAFT_18 + rl->pvMinor = TLSv1_MINOR; +#else + rl->pvMinor = TLSv1_2_MINOR; +#endif + } + else +#endif + rl->pvMinor = ssl->version.minor; - if (!ssl->options.dtls) +#ifdef WOLFSSL_ALTERNATIVE_DOWNGRADE + if (ssl->options.side == WOLFSSL_CLIENT_END + && ssl->options.connectState == CONNECT_BEGIN + && !ssl->options.resuming) { + rl->pvMinor = ssl->options.downgrade ? ssl->options.minDowngrade + : ssl->version.minor; + } +#endif + + if (!ssl->options.dtls) { c16toa((word16)length, rl->length); + } else { #ifdef WOLFSSL_DTLS DtlsRecordLayerHeader* dtls; /* dtls record layer header extensions */ dtls = (DtlsRecordLayerHeader*)output; - c16toa(ssl->keys.dtls_epoch, dtls->epoch); - c32to48(ssl->keys.dtls_sequence_number++, dtls->sequence_number); + WriteSEQ(ssl, 0, dtls->sequence_number); c16toa((word16)length, dtls->length); #endif } } +#if !defined(WOLFSSL_NO_TLS12) || (defined(HAVE_SESSION_TICKET) && \ + !defined(NO_WOLFSSL_SERVER)) /* add handshake header for message */ -static void AddHandShakeHeader(byte* output, word32 length, byte type, - WOLFSSL* ssl) +static void AddHandShakeHeader(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; + if (hs == NULL) + return; + hs->type = type; c32to24(length, hs->length); /* type and length same for each */ #ifdef WOLFSSL_DTLS @@ -2577,44 +7838,79 @@ static void AddHandShakeHeader(byte* output, word32 length, byte type, /* dtls handshake header extensions */ dtls = (DtlsHandShakeHeader*)output; c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq); - c32to24(0, dtls->fragment_offset); - c32to24(length, dtls->fragment_length); + c32to24(fragOffset, dtls->fragment_offset); + c32to24(fragLength, dtls->fragment_length); } #endif } - /* add both headers for handshake message */ static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl) { - if (!ssl->options.dtls) { - AddRecordHeader(output, length + HANDSHAKE_HEADER_SZ, handshake, ssl); - AddHandShakeHeader(output + RECORD_HEADER_SZ, length, type, ssl); - } + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + #ifdef WOLFSSL_DTLS - else { - AddRecordHeader(output, length+DTLS_HANDSHAKE_HEADER_SZ, handshake,ssl); - AddHandShakeHeader(output + DTLS_RECORD_HEADER_SZ, length, type, ssl); + if (ssl->options.dtls) { + lengthAdj += DTLS_HANDSHAKE_EXTRA; + outputAdj += DTLS_RECORD_EXTRA; } #endif + + AddRecordHeader(output, length + lengthAdj, handshake, ssl); + AddHandShakeHeader(output + outputAdj, length, 0, length, type, ssl); } +#endif /* !WOLFSSL_NO_TLS12 || (HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER) */ + + +#ifndef WOLFSSL_NO_TLS12 +#if !defined(NO_CERTS) && (!defined(NO_WOLFSSL_SERVER) || \ + !defined(WOLFSSL_NO_CLIENT_AUTH)) +static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset, + word32 length, byte type, WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + (void)fragSz; + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + lengthAdj += DTLS_HANDSHAKE_EXTRA; + outputAdj += DTLS_RECORD_EXTRA; + } +#endif + + AddRecordHeader(output, fragSz + lengthAdj, handshake, ssl); + AddHandShakeHeader(output + outputAdj, length, fragOffset, fragSz, type, ssl); +} +#endif /* NO_CERTS */ +#endif /* !WOLFSSL_NO_TLS12 */ /* return bytes received, -1 on error */ -static int Receive(WOLFSSL* ssl, byte* buf, word32 sz) +static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz) { int recvd; - if (ssl->ctx->CBIORecv == NULL) { + if (ssl->CBIORecv == NULL) { WOLFSSL_MSG("Your IO Recv callback is null, please set"); return -1; } retry: - recvd = ssl->ctx->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx); - if (recvd < 0) + recvd = ssl->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx); + if (recvd < 0) { switch (recvd) { case WOLFSSL_CBIO_ERR_GENERAL: /* general/unknown error */ + #if defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD) + if (ssl->biord) { + /* If retry and read flags are set, return WANT_READ */ + if ((ssl->biord->flags & WOLFSSL_BIO_FLAG_READ) && + (ssl->biord->flags & WOLFSSL_BIO_FLAG_RETRY)) { + return WANT_READ; + } + } + #endif return -1; case WOLFSSL_CBIO_ERR_WANT_READ: /* want read, would block */ @@ -2639,6 +7935,9 @@ retry: timeout.it_value.tv_usec == 0) { XSTRNCPY(ssl->timeoutInfo.timeoutName, "recv() timeout", MAX_TIMEOUT_NAME_SZ); + ssl->timeoutInfo.timeoutName[ + MAX_TIMEOUT_NAME_SZ] = '\0'; + WOLFSSL_MSG("Got our timeout"); return WANT_READ; } @@ -2651,16 +7950,23 @@ retry: return -1; case WOLFSSL_CBIO_ERR_TIMEOUT: -#ifdef WOLFSSL_DTLS - if (DtlsPoolTimeout(ssl) == 0 && DtlsPoolSend(ssl) == 0) + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && + !ssl->options.handShakeDone && + DtlsMsgPoolTimeout(ssl) == 0 && + DtlsMsgPoolSend(ssl, 0) == 0) { + + /* retry read for DTLS during handshake only */ goto retry; - else -#endif - return -1; + } + #endif + return -1; default: + WOLFSSL_MSG("Unexpected recv return code"); return recvd; } + } return recvd; } @@ -2690,7 +7996,7 @@ void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree) WOLFSSL_MSG("Shrinking input buffer\n"); - if (!forcedFree && usedLength) + if (!forcedFree && usedLength > 0) XMEMCPY(ssl->buffers.inputBuffer.staticBuffer, ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx, usedLength); @@ -2707,13 +8013,21 @@ void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree) int SendBuffered(WOLFSSL* ssl) { - if (ssl->ctx->CBIOSend == NULL) { + if (ssl->CBIOSend == NULL) { WOLFSSL_MSG("Your IO Send callback is null, please set"); 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, + int sent = ssl->CBIOSend(ssl, (char*)ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.idx, (int)ssl->buffers.outputBuffer.length, @@ -2738,6 +8052,9 @@ int SendBuffered(WOLFSSL* ssl) timeout.it_value.tv_usec == 0) { XSTRNCPY(ssl->timeoutInfo.timeoutName, "send() timeout", MAX_TIMEOUT_NAME_SZ); + ssl->timeoutInfo.timeoutName[ + MAX_TIMEOUT_NAME_SZ] = '\0'; + WOLFSSL_MSG("Got our timeout"); return WANT_WRITE; } @@ -2775,12 +8092,18 @@ int SendBuffered(WOLFSSL* ssl) /* Grow the output buffer */ -static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) +static WC_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 */ @@ -2789,14 +8112,29 @@ 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 + +#ifdef WOLFSSL_STATIC_MEMORY + /* can be from IO memory pool which does not need copy if same buffer */ + if (ssl->buffers.outputBuffer.length && + tmp == ssl->buffers.outputBuffer.buffer) { + ssl->buffers.outputBuffer.bufferSize = + size + ssl->buffers.outputBuffer.length; + return 0; + } +#endif if (ssl->buffers.outputBuffer.length) XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer, @@ -2807,10 +8145,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; @@ -2822,8 +8164,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 @@ -2833,13 +8181,34 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) while (align < hdrSz) align *= 2; } - tmp = (byte*) XMALLOC(size + usedLength + align, ssl->heap, - DYNAMIC_TYPE_IN_BUFFER); +#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); 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 + +#ifdef WOLFSSL_STATIC_MEMORY + /* can be from IO memory pool which does not need copy if same buffer */ + if (usedLength && tmp == ssl->buffers.inputBuffer.buffer) { + ssl->buffers.inputBuffer.bufferSize = size + usedLength; + ssl->buffers.inputBuffer.idx = 0; + ssl->buffers.inputBuffer.length = usedLength; + return 0; + } +#endif if (usedLength) XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer + @@ -2850,10 +8219,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; @@ -2866,7 +8238,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; @@ -2898,46 +8269,78 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } else { #ifdef WOLFSSL_DTLS +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, input + *inOutIdx, DTLS_RECORD_HEADER_SZ, + FUZZ_HEAD, ssl->fuzzerCtx); +#endif /* type and version in same sport */ XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ); *inOutIdx += ENUM_LEN + VERSION_SZ; - ato16(input + *inOutIdx, &ssl->keys.dtls_state.curEpoch); - *inOutIdx += 4; /* advance past epoch, skip first 2 seq bytes for now */ - ato32(input + *inOutIdx, &ssl->keys.dtls_state.curSeq); - *inOutIdx += 4; /* advance past rest of seq */ + ato16(input + *inOutIdx, &ssl->keys.curEpoch); + *inOutIdx += OPAQUE16_LEN; + 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 */ ato16(input + *inOutIdx, size); *inOutIdx += LENGTH_SZ; -#ifdef HAVE_FUZZER - if (ssl->fuzzerCb) - ssl->fuzzerCb(ssl, input + *inOutIdx - LENGTH_SZ - 8 - ENUM_LEN - - VERSION_SZ, ENUM_LEN + VERSION_SZ + 8 + LENGTH_SZ, - FUZZ_HEAD, ssl->fuzzerCtx); -#endif #endif } +#ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && !DtlsCheckWindow(ssl)) { + WOLFSSL_LEAVE("GetRecordHeader()", SEQUENCE_ERROR); + return SEQUENCE_ERROR; + } +#endif + /* 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 && +#ifdef WOLFSSL_TLS13_DRAFT_18 + (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_MINOR) +#else + (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_2_MINOR) +#endif + )) +#endif + { if (ssl->options.side == WOLFSSL_SERVER_END && - ssl->options.acceptState == ACCEPT_BEGIN) + ssl->options.acceptState < ACCEPT_FIRST_REPLY_DONE) + WOLFSSL_MSG("Client attempting to connect with different version"); else if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.downgrade && ssl->options.connectState < FIRST_REPLY_DONE) WOLFSSL_MSG("Server attempting to accept with different version"); + else if (ssl->options.dtls && rh->type == handshake) + /* Check the DTLS handshake message RH version later. */ + WOLFSSL_MSG("DTLS handshake, skip RH version number check"); else { WOLFSSL_MSG("SSL version error"); + /* send alert per RFC5246 Appendix E. Backward Compatibility */ + if (ssl->options.side == WOLFSSL_CLIENT_END) { +#ifdef WOLFSSL_MYSQL_COMPATIBLE + SendAlert(ssl, alert_fatal, wc_protocol_version); +#else + SendAlert(ssl, alert_fatal, protocol_version); +#endif + } return VERSION_ERROR; /* only use requested version */ } } -#ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if (DtlsCheckWindow(&ssl->keys.dtls_state) != 1) - return SEQUENCE_ERROR; - } -#endif - /* record layer length check */ #ifdef HAVE_MAX_FRAGMENT if (*size > (ssl->max_fragment + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) { @@ -2968,7 +8371,7 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return 0; } - +#ifndef WOLFSSL_NO_TLS12 static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, byte *type, word32 *size, word32 totalSz) { @@ -2984,7 +8387,7 @@ static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return 0; } - +#endif #ifdef WOLFSSL_DTLS static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input, @@ -2995,12 +8398,14 @@ static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input, word32 idx = *inOutIdx; *inOutIdx += HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA; - if (*inOutIdx > totalSz) + if (*inOutIdx > totalSz) { + WOLFSSL_ERROR(BUFFER_E); return BUFFER_E; + } *type = input[idx++]; c24to32(input + idx, size); - idx += BYTE3_LEN; + idx += OPAQUE24_LEN; ato16(input + idx, &ssl->keys.dtls_peer_handshake_number); idx += DTLS_HANDSHAKE_SEQ_SZ; @@ -3009,12 +8414,24 @@ static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input, idx += DTLS_HANDSHAKE_FRAG_SZ; c24to32(input + idx, fragSz); + if (ssl->curRL.pvMajor != ssl->version.major || + ssl->curRL.pvMinor != ssl->version.minor) { + + if (*type != client_hello && *type != hello_verify_request) { + WOLFSSL_ERROR(VERSION_ERROR); + return VERSION_ERROR; + } + else { + WOLFSSL_MSG("DTLS Handshake ignoring hello or verify version"); + } + } return 0; } #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, @@ -3032,116 +8449,116 @@ 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 +#ifndef WOLFSSL_NO_TLS12 + /* Finished doesn't support SHA512, not SHA512 cipher suites yet */ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - #ifdef WOLFSSL_SHA384 - Sha384* sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif -#else - #ifdef WOLFSSL_SHA384 - Sha384 sha384[1]; - #endif -#endif -#ifdef WOLFSSL_SMALL_STACK - if (ssl == NULL - #ifdef WOLFSSL_SHA384 - || sha384 == NULL - #endif - ) { - #ifdef WOLFSSL_SHA384 - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return MEMORY_E; - } -#endif - - /* store current states, building requires get_digest which resets state */ -#ifdef WOLFSSL_SHA384 - sha384[0] = ssl->hsHashes->hashSha384; -#endif + if (ssl == NULL) + return BAD_FUNC_ARG; #ifndef NO_TLS if (ssl->options.tls) { @@ -3150,37 +8567,29 @@ 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 - /* restore */ - if (IsAtLeastTLSv1_2(ssl)) { - #ifdef WOLFSSL_SHA384 - ssl->hsHashes->hashSha384 = sha384[0]; - #endif - } - -#ifdef WOLFSSL_SMALL_STACK -#ifdef WOLFSSL_SHA384 - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif -#endif - return ret; } +#endif /* WOLFSSL_NO_TLS12 */ +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) /* cipher requirements */ enum { REQUIRES_RSA, REQUIRES_DHE, - REQUIRES_ECC_DSA, + REQUIRES_ECC, REQUIRES_ECC_STATIC, REQUIRES_PSK, REQUIRES_NTRU, - REQUIRES_RSA_SIG + REQUIRES_RSA_SIG, + REQUIRES_AEAD }; @@ -3191,17 +8600,21 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) static int CipherRequires(byte first, byte second, int requirement) { + (void)requirement; + +#ifndef WOLFSSL_NO_TLS12 + +#ifdef HAVE_CHACHA if (first == CHACHA_BYTE) { switch (second) { - case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : if (requirement == REQUIRES_RSA) return 1; break; case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : - if (requirement == REQUIRES_ECC_DSA) + if (requirement == REQUIRES_ECC) return 1; break; @@ -3211,15 +8624,55 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) if (requirement == REQUIRES_DHE) return 1; break; + + case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; + + + case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + break; + + case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + break; + + case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; } + + if (requirement == REQUIRES_AEAD) + return 1; + } +#endif /* HAVE_CHACHA */ /* ECC extensions */ if (first == ECC_BYTE) { switch (second) { - -#ifndef NO_RSA +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) + #ifndef NO_RSA case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA : if (requirement == REQUIRES_RSA) return 1; @@ -3232,7 +8685,7 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 1; break; -#ifndef NO_DES3 + #ifndef NO_DES3 case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA : if (requirement == REQUIRES_RSA) return 1; @@ -3244,9 +8697,9 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) if (requirement == REQUIRES_RSA_SIG) return 1; break; -#endif + #endif /* !NO_DES3 */ -#ifndef NO_RC4 + #ifndef NO_RC4 case TLS_ECDHE_RSA_WITH_RC4_128_SHA : if (requirement == REQUIRES_RSA) return 1; @@ -3258,12 +8711,12 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) if (requirement == REQUIRES_RSA_SIG) return 1; break; -#endif -#endif /* NO_RSA */ + #endif /* !NO_RC4 */ + #endif /* NO_RSA */ -#ifndef NO_DES3 + #ifndef NO_DES3 case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA : - if (requirement == REQUIRES_ECC_DSA) + if (requirement == REQUIRES_ECC) return 1; break; @@ -3271,10 +8724,10 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) if (requirement == REQUIRES_ECC_STATIC) return 1; break; -#endif -#ifndef NO_RC4 + #endif /* !NO_DES3 */ + #ifndef NO_RC4 case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : - if (requirement == REQUIRES_ECC_DSA) + if (requirement == REQUIRES_ECC) return 1; break; @@ -3282,8 +8735,8 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) if (requirement == REQUIRES_ECC_STATIC) return 1; break; -#endif -#ifndef NO_RSA + #endif /* !NO_RC4 */ + #ifndef NO_RSA case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA : if (requirement == REQUIRES_RSA) return 1; @@ -3295,10 +8748,10 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) if (requirement == REQUIRES_RSA_SIG) return 1; break; -#endif + #endif /* !NO_RSA */ case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA : - if (requirement == REQUIRES_ECC_DSA) + if (requirement == REQUIRES_ECC) return 1; break; @@ -3308,7 +8761,7 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) break; case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA : - if (requirement == REQUIRES_ECC_DSA) + if (requirement == REQUIRES_ECC) return 1; break; @@ -3318,34 +8771,48 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) break; case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 : - if (requirement == REQUIRES_ECC_DSA) + if (requirement == REQUIRES_ECC) + return 1; + if (requirement == REQUIRES_AEAD) return 1; break; case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 : - if (requirement == REQUIRES_ECC_DSA) + if (requirement == REQUIRES_ECC) + return 1; + if (requirement == REQUIRES_AEAD) return 1; break; case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 : if (requirement == REQUIRES_ECC_STATIC) return 1; + if (requirement == REQUIRES_AEAD) + return 1; break; case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 : if (requirement == REQUIRES_ECC_STATIC) return 1; + if (requirement == REQUIRES_AEAD) + return 1; break; +#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ #ifndef NO_RSA + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : if (requirement == REQUIRES_RSA) return 1; + if (requirement == REQUIRES_AEAD) + return 1; break; case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 : if (requirement == REQUIRES_RSA) return 1; + if (requirement == REQUIRES_AEAD) + return 1; break; case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 : @@ -3353,6 +8820,8 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 1; if (requirement == REQUIRES_RSA_SIG) return 1; + if (requirement == REQUIRES_AEAD) + return 1; break; case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 : @@ -3360,22 +8829,27 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 1; if (requirement == REQUIRES_RSA_SIG) return 1; + if (requirement == REQUIRES_AEAD) + return 1; break; - + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + #ifdef HAVE_AESCCM case TLS_RSA_WITH_AES_128_CCM_8 : case TLS_RSA_WITH_AES_256_CCM_8 : if (requirement == REQUIRES_RSA) return 1; if (requirement == REQUIRES_RSA_SIG) return 1; + if (requirement == REQUIRES_AEAD) + return 1; break; + #endif /* HAVE_AESCCM */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : 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 : @@ -3385,34 +8859,43 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) if (requirement == REQUIRES_ECC_STATIC) return 1; break; -#endif + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ +#endif /* !NO_RSA */ +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM : case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 : case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 : - if (requirement == REQUIRES_ECC_DSA) + if (requirement == REQUIRES_ECC) + return 1; + if (requirement == REQUIRES_AEAD) return 1; break; case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 : case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : - if (requirement == REQUIRES_ECC_DSA) + if (requirement == REQUIRES_ECC) return 1; break; case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 : case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 : - if (requirement == REQUIRES_ECC_DSA) + if (requirement == REQUIRES_ECC) return 1; if (requirement == REQUIRES_ECC_STATIC) return 1; break; +#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ +#ifndef NO_PSK case TLS_PSK_WITH_AES_128_CCM: case TLS_PSK_WITH_AES_256_CCM: case TLS_PSK_WITH_AES_128_CCM_8: case TLS_PSK_WITH_AES_256_CCM_8: if (requirement == REQUIRES_PSK) return 1; + if (requirement == REQUIRES_AEAD) + return 1; break; case TLS_DHE_PSK_WITH_AES_128_CCM: @@ -3421,41 +8904,92 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 1; if (requirement == REQUIRES_DHE) return 1; + if (requirement == REQUIRES_AEAD) + return 1; break; +#endif /* !NO_PSK */ +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) + case TLS_ECDHE_ECDSA_WITH_NULL_SHA : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_ECDHE_PSK_WITH_NULL_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + break; + + case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + break; +#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + +#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER) + case TLS_SHA256_SHA256: + break; + case TLS_SHA384_SHA384: + break; +#endif default: WOLFSSL_MSG("Unsupported cipher suite, CipherRequires ECC"); return 0; } /* switch */ } /* if */ - if (first != ECC_BYTE) { /* normal suites */ + +#endif /* !WOLFSSL_NO_TLS12 */ + + /* 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; + } + } + +#ifndef WOLFSSL_NO_TLS12 + + if (first != ECC_BYTE && first != CHACHA_BYTE && + first != TLS13_BYTE) { /* normal suites */ switch (second) { #ifndef NO_RSA + #ifndef NO_RC4 case SSL_RSA_WITH_RC4_128_SHA : if (requirement == REQUIRES_RSA) return 1; break; - case TLS_NTRU_RSA_WITH_RC4_128_SHA : - if (requirement == REQUIRES_NTRU) - return 1; - break; - case SSL_RSA_WITH_RC4_128_MD5 : if (requirement == REQUIRES_RSA) return 1; break; + #endif /* NO_RC4 */ case SSL_RSA_WITH_3DES_EDE_CBC_SHA : if (requirement == REQUIRES_RSA) return 1; break; - case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA : + #ifdef HAVE_NTRU + case TLS_NTRU_RSA_WITH_RC4_128_SHA : if (requirement == REQUIRES_NTRU) return 1; break; + #endif /* HAVE_NTRU */ case TLS_RSA_WITH_AES_128_CBC_SHA : if (requirement == REQUIRES_RSA) @@ -3467,35 +9001,67 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 1; break; - case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA : + #ifdef HAVE_NTRU + case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA : if (requirement == REQUIRES_NTRU) return 1; break; + #endif /* HAVE_NTRU */ case TLS_RSA_WITH_AES_256_CBC_SHA : if (requirement == REQUIRES_RSA) return 1; break; + #ifdef HAVE_NTRU + case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; + #endif /* HAVE_NTRU */ + case TLS_RSA_WITH_AES_256_CBC_SHA256 : if (requirement == REQUIRES_RSA) return 1; break; + case TLS_RSA_WITH_NULL_MD5 : case TLS_RSA_WITH_NULL_SHA : case TLS_RSA_WITH_NULL_SHA256 : if (requirement == REQUIRES_RSA) return 1; break; + #ifdef HAVE_NTRU case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA : if (requirement == REQUIRES_NTRU) return 1; break; -#endif + #endif /* HAVE_NTRU */ + #ifdef HAVE_IDEA + case SSL_RSA_WITH_IDEA_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + #endif /* HAVE_IDEA */ +#endif /* !NO_RSA */ + +#ifndef NO_PSK case TLS_PSK_WITH_AES_128_GCM_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + if (requirement == REQUIRES_AEAD) + return 1; + break; + case TLS_PSK_WITH_AES_256_GCM_SHA384 : + if (requirement == REQUIRES_PSK) + return 1; + if (requirement == REQUIRES_AEAD) + return 1; + break; + case TLS_PSK_WITH_AES_128_CBC_SHA256 : case TLS_PSK_WITH_AES_256_CBC_SHA384 : case TLS_PSK_WITH_AES_128_CBC_SHA : @@ -3509,6 +9075,14 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 : case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 : + if (requirement == REQUIRES_DHE) + return 1; + if (requirement == REQUIRES_PSK) + return 1; + if (requirement == REQUIRES_AEAD) + return 1; + break; + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 : case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 : case TLS_DHE_PSK_WITH_NULL_SHA384 : @@ -3518,6 +9092,7 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) if (requirement == REQUIRES_PSK) return 1; break; +#endif /* NO_PSK */ #ifndef NO_RSA case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 : @@ -3548,6 +9123,7 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 1; break; +#ifndef NO_HC128 case TLS_RSA_WITH_HC_128_MD5 : if (requirement == REQUIRES_RSA) return 1; @@ -3557,27 +9133,21 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) if (requirement == REQUIRES_RSA) return 1; break; +#endif /* NO_HC128 */ - case TLS_RSA_WITH_HC_128_B2B256: - if (requirement == REQUIRES_RSA) - return 1; - break; - - case TLS_RSA_WITH_AES_128_CBC_B2B256: - case TLS_RSA_WITH_AES_256_CBC_B2B256: - if (requirement == REQUIRES_RSA) - return 1; - break; - +#ifndef NO_RABBIT case TLS_RSA_WITH_RABBIT_SHA : if (requirement == REQUIRES_RSA) return 1; break; +#endif /* !NO_RABBIT */ case TLS_RSA_WITH_AES_128_GCM_SHA256 : case TLS_RSA_WITH_AES_256_GCM_SHA384 : if (requirement == REQUIRES_RSA) return 1; + if (requirement == REQUIRES_AEAD) + return 1; break; case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 : @@ -3586,8 +9156,11 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 1; if (requirement == REQUIRES_DHE) return 1; + if (requirement == REQUIRES_AEAD) + return 1; break; +#ifdef HAVE_CAMELLIA case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA : case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA : case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 : @@ -3607,12 +9180,32 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) if (requirement == REQUIRES_DHE) return 1; break; +#endif /* HAVE_CAMELLIA */ + + case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_RSA_SIG) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; #endif #ifdef HAVE_ANON case TLS_DH_anon_WITH_AES_128_CBC_SHA : if (requirement == REQUIRES_DHE) return 1; break; + case TLS_DH_anon_WITH_AES_256_GCM_SHA384: + if (requirement == REQUIRES_DHE) + return 1; + if (requirement == REQUIRES_AEAD) + return 1; + break; +#endif +#ifdef WOLFSSL_MULTICAST + case WDM_WITH_NULL_SHA256 : + break; #endif default: @@ -3621,20 +9214,25 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) } /* switch */ } /* if ECC / Normal suites else */ +#endif /* !WOLFSSL_NO_TLS12 */ + return 0; } +#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ + #ifndef NO_CERTS /* Match names with wildcards, each wildcard can represent a single name - component or fragment but not mulitple names, i.e., + component or fragment but not multiple names, i.e., *.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) { + int ret = 0; char p, s; if (pattern == NULL || str == NULL || len <= 0) @@ -3643,13 +9241,13 @@ static int MatchDomainName(const char* pattern, int len, const char* str) while (len > 0) { p = (char)XTOLOWER((unsigned char)*pattern++); - if (p == 0) + if (p == '\0') break; if (p == '*') { while (--len > 0 && - (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') - ; + (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') { + } if (len == 0) p = '\0'; @@ -3667,19 +9265,23 @@ static int MatchDomainName(const char* pattern, int len, const char* str) return 0; } - if (*str != '\0') - str++; - if (len > 0) + if (len > 0) { + str++; len--; + } } - return *str == '\0'; + if (*str == '\0' && len == 0) { + ret = 1; /* success */ + } + + return ret; } /* 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; @@ -3690,9 +9292,9 @@ static int CheckAltNames(DecodedCert* dCert, char* domain) altName = dCert->altNames; while (altName) { - WOLFSSL_MSG(" individual AltName check"); + WOLFSSL_MSG("\tindividual AltName check"); - if (MatchDomainName(altName->name,(int)XSTRLEN(altName->name), domain)){ + if (MatchDomainName(altName->name, altName->len, domain)){ match = 1; break; } @@ -3703,15 +9305,113 @@ static int CheckAltNames(DecodedCert* dCert, char* domain) return match; } +#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; -#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) + 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, altName->len, domain)) { + match = 1; + *checkCN = 0; + break; + } + /* No matches and wild pattern match failed. */ + else if (altName->name && altName->len >=1 && + 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; +} + +int CheckIPAddr(DecodedCert* dCert, char* ipasc) +{ + WOLFSSL_MSG("Checking IPAddr"); + + return CheckHostName(dCert, ipasc, (size_t)XSTRLEN(ipasc)); +} +#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) || \ + defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) /* Copy parts X509 needs from Decoded cert, 0 on success */ +/* The same DecodedCert cannot be copied to WOLFSSL_X509 twice otherwise the + * altNames pointers could be free'd by second x509 still active by first */ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) { int ret = 0; - if (x509 == NULL || dCert == NULL) + if (x509 == NULL || dCert == NULL || + dCert->subjectCNLen < 0) return BAD_FUNC_ARG; x509->version = dCert->version + 1; @@ -3719,36 +9419,47 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) XSTRNCPY(x509->issuer.name, dCert->issuer, ASN_NAME_MAX); x509->issuer.name[ASN_NAME_MAX - 1] = '\0'; x509->issuer.sz = (int)XSTRLEN(x509->issuer.name) + 1; -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) if (dCert->issuerName.fullName != NULL) { XMEMCPY(&x509->issuer.fullName, &dCert->issuerName, sizeof(DecodedName)); x509->issuer.fullName.fullName = (char*)XMALLOC( - dCert->issuerName.fullNameLen, NULL, DYNAMIC_TYPE_X509); + dCert->issuerName.fullNameLen, x509->heap, + DYNAMIC_TYPE_X509); if (x509->issuer.fullName.fullName != NULL) XMEMCPY(x509->issuer.fullName.fullName, dCert->issuerName.fullName, dCert->issuerName.fullNameLen); } -#endif /* OPENSSL_EXTRA */ + x509->issuer.x509 = x509; +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ XSTRNCPY(x509->subject.name, dCert->subject, ASN_NAME_MAX); x509->subject.name[ASN_NAME_MAX - 1] = '\0'; x509->subject.sz = (int)XSTRLEN(x509->subject.name) + 1; -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) if (dCert->subjectName.fullName != NULL) { XMEMCPY(&x509->subject.fullName, &dCert->subjectName, sizeof(DecodedName)); x509->subject.fullName.fullName = (char*)XMALLOC( - dCert->subjectName.fullNameLen, NULL, DYNAMIC_TYPE_X509); + dCert->subjectName.fullNameLen, x509->heap, DYNAMIC_TYPE_X509); if (x509->subject.fullName.fullName != NULL) XMEMCPY(x509->subject.fullName.fullName, dCert->subjectName.fullName, dCert->subjectName.fullNameLen); } -#endif /* OPENSSL_EXTRA */ + x509->subject.x509 = x509; +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + x509->subject.rawLen = min(dCert->subjectRawLen, sizeof(x509->subject.raw)); + XMEMCPY(x509->subject.raw, dCert->subjectRaw, x509->subject.rawLen); +#ifdef WOLFSSL_CERT_EXT + x509->issuer.rawLen = min(dCert->issuerRawLen, sizeof(x509->issuer.raw)); + XMEMCPY(x509->issuer.raw, dCert->issuerRaw, x509->issuer.rawLen); +#endif +#endif XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE); x509->serialSz = dCert->serialSz; - if (dCert->subjectCNLen < ASN_NAME_MAX) { + if (dCert->subjectCN && dCert->subjectCNLen < ASN_NAME_MAX) { XMEMCPY(x509->subjectCN, dCert->subjectCN, dCert->subjectCNLen); x509->subjectCN[dCert->subjectCNLen] = '\0'; } @@ -3765,14 +9476,14 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) else x509->deviceTypeSz = 0; minSz = min(dCert->hwTypeSz, EXTERNAL_SERIAL_SIZE); - if (minSz != 0) { + if (minSz > 0) { x509->hwTypeSz = minSz; XMEMCPY(x509->hwType, dCert->hwType, minSz); } else x509->hwTypeSz = 0; minSz = min(dCert->hwSerialNumSz, EXTERNAL_SERIAL_SIZE); - if (minSz != 0) { + if (minSz > 0) { x509->hwSerialNumSz = minSz; XMEMCPY(x509->hwSerialNum, dCert->hwSerialNum, minSz); } @@ -3781,25 +9492,28 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) } #endif /* WOLFSSL_SEP */ { - int minSz = min(dCert->beforeDateLen, MAX_DATE_SZ); - if (minSz != 0) { - x509->notBeforeSz = minSz; - XMEMCPY(x509->notBefore, dCert->beforeDate, minSz); + int minSz; + if (dCert->beforeDateLen > 0) { + minSz = min(dCert->beforeDate[1], MAX_DATE_SZ); + x509->notBefore.type = dCert->beforeDate[0]; + x509->notBefore.length = minSz; + XMEMCPY(x509->notBefore.data, &dCert->beforeDate[2], minSz); } else - x509->notBeforeSz = 0; - minSz = min(dCert->afterDateLen, MAX_DATE_SZ); - if (minSz != 0) { - x509->notAfterSz = minSz; - XMEMCPY(x509->notAfter, dCert->afterDate, minSz); + x509->notBefore.length = 0; + if (dCert->afterDateLen > 0) { + minSz = min(dCert->afterDate[1], MAX_DATE_SZ); + x509->notAfter.type = dCert->afterDate[0]; + x509->notAfter.length = minSz; + XMEMCPY(x509->notAfter.data, &dCert->afterDate[2], minSz); } else - x509->notAfterSz = 0; + x509->notAfter.length = 0; } if (dCert->publicKey != NULL && dCert->pubKeySize != 0) { x509->pubKey.buffer = (byte*)XMALLOC( - dCert->pubKeySize, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + dCert->pubKeySize, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (x509->pubKey.buffer != NULL) { x509->pubKeyOID = dCert->keyOID; x509->pubKey.length = dCert->pubKeySize; @@ -3807,11 +9521,34 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) } else ret = MEMORY_E; +#if defined(OPENSSL_ALL) + if (ret == 0) { + x509->key.pubKeyOID = dCert->keyOID; + + if (!x509->key.algor) { + x509->key.algor = wolfSSL_X509_ALGOR_new(); + } else { + wolfSSL_ASN1_OBJECT_free(x509->key.algor->algorithm); + } + if (!(x509->key.algor->algorithm = + wolfSSL_OBJ_nid2obj(dCert->keyOID))) { + ret = PUBLIC_KEY_E; + } + + wolfSSL_EVP_PKEY_free(x509->key.pkey); + if (!(x509->key.pkey = wolfSSL_d2i_PUBKEY(NULL, + &dCert->publicKey, + dCert->pubKeySize))) { + ret = PUBLIC_KEY_E; + } + } +#endif } - 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, NULL, DYNAMIC_TYPE_SIGNATURE); + dCert->sigLength, x509->heap, DYNAMIC_TYPE_SIGNATURE); if (x509->sig.buffer == NULL) { ret = MEMORY_E; } @@ -3820,37 +9557,110 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) x509->sig.length = dCert->sigLength; x509->sigOID = dCert->signatureOID; } +#if defined(OPENSSL_ALL) + wolfSSL_ASN1_OBJECT_free(x509->algor.algorithm); + if (!(x509->algor.algorithm = + wolfSSL_OBJ_nid2obj(dCert->signatureOID))) { + ret = PUBLIC_KEY_E; + } +#endif } /* store cert for potential retrieval */ - x509->derCert.buffer = (byte*)XMALLOC(dCert->maxIdx, NULL, - DYNAMIC_TYPE_CERT); - if (x509->derCert.buffer == NULL) { - ret = MEMORY_E; + if (AllocDer(&x509->derCert, dCert->maxIdx, CERT_TYPE, x509->heap) == 0) { + XMEMCPY(x509->derCert->buffer, dCert->source, dCert->maxIdx); } else { - XMEMCPY(x509->derCert.buffer, dCert->source, dCert->maxIdx); - x509->derCert.length = dCert->maxIdx; + ret = MEMORY_E; } x509->altNames = dCert->altNames; dCert->weOwnAltNames = 0; x509->altNamesNext = x509->altNames; /* index hint */ +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + !defined(IGNORE_NAME_CONSTRAINTS) + /* add copies of alternate emails from dCert to X509 */ + if (dCert->altEmailNames != NULL) { + DNS_entry* cur = dCert->altEmailNames; + + while (cur != NULL) { + if (cur->type == ASN_RFC822_TYPE) { + DNS_entry* dnsEntry; + int strLen = cur->len; + + dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), x509->heap, + DYNAMIC_TYPE_ALTNAME); + if (dnsEntry == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + dnsEntry->type = ASN_RFC822_TYPE; + dnsEntry->name = (char*)XMALLOC(strLen + 1, x509->heap, + DYNAMIC_TYPE_ALTNAME); + if (dnsEntry->name == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + XFREE(dnsEntry, x509->heap, DYNAMIC_TYPE_ALTNAME); + return MEMORY_E; + } + dnsEntry->len = strLen; + XMEMCPY(dnsEntry->name, cur->name, strLen); + dnsEntry->name[strLen] = '\0'; + + dnsEntry->next = x509->altNames; + x509->altNames = dnsEntry; + } + cur = cur->next; + } + } +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + x509->isCa = dCert->isCA; -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) x509->pathLength = dCert->pathLength; x509->keyUsage = dCert->extKeyUsage; + x509->CRLdistSet = dCert->extCRLdistSet; + x509->CRLdistCrit = dCert->extCRLdistCrit; + x509->CRLInfo = dCert->extCrlInfo; + x509->CRLInfoSz = dCert->extCrlInfoSz; + x509->authInfoSet = dCert->extAuthInfoSet; + x509->authInfoCrit = dCert->extAuthInfoCrit; + if (dCert->extAuthInfo != NULL && dCert->extAuthInfoSz > 0) { + x509->authInfo = (byte*)XMALLOC(dCert->extAuthInfoSz, x509->heap, + DYNAMIC_TYPE_X509_EXT); + if (x509->authInfo != NULL) { + XMEMCPY(x509->authInfo, dCert->extAuthInfo, dCert->extAuthInfoSz); + x509->authInfoSz = dCert->extAuthInfoSz; + } + else { + ret = MEMORY_E; + } + } + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + if (dCert->extAuthInfoCaIssuer != NULL && dCert->extAuthInfoCaIssuerSz > 0) { + x509->authInfoCaIssuer = (byte*)XMALLOC(dCert->extAuthInfoCaIssuerSz, x509->heap, + DYNAMIC_TYPE_X509_EXT); + if (x509->authInfoCaIssuer != NULL) { + XMEMCPY(x509->authInfoCaIssuer, dCert->extAuthInfoCaIssuer, dCert->extAuthInfoCaIssuerSz); + x509->authInfoCaIssuerSz = dCert->extAuthInfoCaIssuerSz; + } + else { + ret = MEMORY_E; + } + } + #endif x509->basicConstSet = dCert->extBasicConstSet; x509->basicConstCrit = dCert->extBasicConstCrit; - x509->basicConstPlSet = dCert->extBasicConstPlSet; + x509->basicConstPlSet = dCert->pathLengthSet; x509->subjAltNameSet = dCert->extSubjAltNameSet; x509->subjAltNameCrit = dCert->extSubjAltNameCrit; x509->authKeyIdSet = dCert->extAuthKeyIdSet; x509->authKeyIdCrit = dCert->extAuthKeyIdCrit; if (dCert->extAuthKeyIdSrc != NULL && dCert->extAuthKeyIdSz != 0) { - x509->authKeyId = (byte*)XMALLOC(dCert->extAuthKeyIdSz, NULL, 0); + x509->authKeyId = (byte*)XMALLOC(dCert->extAuthKeyIdSz, x509->heap, + DYNAMIC_TYPE_X509_EXT); if (x509->authKeyId != NULL) { XMEMCPY(x509->authKeyId, dCert->extAuthKeyIdSrc, dCert->extAuthKeyIdSz); @@ -3862,7 +9672,8 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) x509->subjKeyIdSet = dCert->extSubjKeyIdSet; x509->subjKeyIdCrit = dCert->extSubjKeyIdCrit; if (dCert->extSubjKeyIdSrc != NULL && dCert->extSubjKeyIdSz != 0) { - x509->subjKeyId = (byte*)XMALLOC(dCert->extSubjKeyIdSz, NULL, 0); + x509->subjKeyId = (byte*)XMALLOC(dCert->extSubjKeyIdSz, x509->heap, + DYNAMIC_TYPE_X509_EXT); if (x509->subjKeyId != NULL) { XMEMCPY(x509->subjKeyId, dCert->extSubjKeyIdSrc, dCert->extSubjKeyIdSz); @@ -3873,595 +9684,2142 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) } x509->keyUsageSet = dCert->extKeyUsageSet; x509->keyUsageCrit = dCert->extKeyUsageCrit; - #ifdef WOLFSSL_SEP + if (dCert->extExtKeyUsageSrc != NULL && dCert->extExtKeyUsageSz > 0) { + x509->extKeyUsageSrc = (byte*)XMALLOC(dCert->extExtKeyUsageSz, + x509->heap, DYNAMIC_TYPE_X509_EXT); + if (x509->extKeyUsageSrc != NULL) { + XMEMCPY(x509->extKeyUsageSrc, dCert->extExtKeyUsageSrc, + dCert->extExtKeyUsageSz); + x509->extKeyUsageSz = dCert->extExtKeyUsageSz; + x509->extKeyUsageCrit = dCert->extExtKeyUsageCrit; + x509->extKeyUsageCount = dCert->extExtKeyUsageCount; + } + else { + ret = MEMORY_E; + } + } + #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT) x509->certPolicySet = dCert->extCertPolicySet; x509->certPolicyCrit = dCert->extCertPolicyCrit; - #endif /* WOLFSSL_SEP */ -#endif /* OPENSSL_EXTRA */ -#ifdef HAVE_ECC + #endif /* WOLFSSL_SEP || WOLFSSL_QT */ + #ifdef WOLFSSL_CERT_EXT + { + int i; + for (i = 0; i < dCert->extCertPoliciesNb && i < MAX_CERTPOL_NB; i++) + XMEMCPY(x509->certPolicies[i], dCert->extCertPolicies[i], + MAX_CERTPOL_SZ); + x509->certPoliciesNb = dCert->extCertPoliciesNb; + } + #endif /* WOLFSSL_CERT_EXT */ +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) x509->pkCurveOID = dCert->pkCurveOID; -#endif /* HAVE_ECC */ +#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ return ret; } #endif /* KEEP_PEER_CERT || SESSION_CERTS */ - -static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, - word32 size) +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ + (defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(WOLFSSL_NO_TLS12)) +static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 status_length) { - word32 listSz; - word32 begin = *inOutIdx; - int ret = 0; - int anyError = 0; - int totalCerts = 0; /* number of certs in certs buffer */ - int count; - buffer certs[MAX_CHAIN_DEPTH]; + int ret = 0; + OcspRequest* request; -#ifdef WOLFSSL_SMALL_STACK - char* domain = NULL; - DecodedCert* dCert = NULL; - WOLFSSL_X509_STORE_CTX* store = NULL; -#else - char domain[ASN_NAME_MAX]; - DecodedCert dCert[1]; - WOLFSSL_X509_STORE_CTX store[1]; -#endif - - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo); - if (ssl->toInfoOn) AddLateName("Certificate", &ssl->timeoutInfo); + #ifdef WOLFSSL_SMALL_STACK + CertStatus* status; + OcspResponse* response; + #else + CertStatus status[1]; + OcspResponse response[1]; #endif - if ((*inOutIdx - begin) + OPAQUE24_LEN > size) - return BUFFER_ERROR; - - c24to32(input + *inOutIdx, &listSz); - *inOutIdx += OPAQUE24_LEN; - -#ifdef HAVE_MAX_FRAGMENT - if (listSz > ssl->max_fragment) { - SendAlert(ssl, alert_fatal, record_overflow); - return BUFFER_E; - } -#else - if (listSz > MAX_RECORD_SIZE) - return BUFFER_E; -#endif - - 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) - 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(" Put 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 - - /* 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; + do { + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) { + request = (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions); + ssl->status_request = 0; + break; + } #endif - 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)) { - buffer add; - add.length = myCert.length; - add.buffer = (byte*)XMALLOC(myCert.length, ssl->heap, - DYNAMIC_TYPE_CA); - WOLFSSL_MSG("Adding CA from chain"); - - if (add.buffer == NULL) - return MEMORY_E; - XMEMCPY(add.buffer, myCert.buffer, myCert.length); - - ret = AddCA(ssl->ctx->cm, add, WOLFSSL_CHAIN_CA, - ssl->ctx->verifyPeer); - 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; - (void)doCrlLookup; -#ifdef HAVE_OCSP - if (ssl->ctx->cm->ocspEnabled && ssl->ctx->cm->ocspCheckAll) { - WOLFSSL_MSG("Doing Non Leaf OCSP check"); - ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert); - doCrlLookup = (ret == OCSP_CERT_UNKNOWN); - if (ret != 0) { - doCrlLookup = 0; - WOLFSSL_MSG("\tOCSP Lookup not ok"); - } + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + request = (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions, + WOLFSSL_CSR2_OCSP, 0); + ssl->status_request_v2 = 0; + break; } -#endif /* HAVE_OCSP */ + #endif -#ifdef HAVE_CRL - if (doCrlLookup && ssl->ctx->cm->crlEnabled - && ssl->ctx->cm->crlCheckAll) { - WOLFSSL_MSG("Doing Non Leaf CRL check"); - ret = CheckCertCRL(ssl->ctx->cm->crl, dCert); + return BUFFER_ERROR; + } while(0); - if (ret != 0) { - WOLFSSL_MSG("\tCRL check not ok"); - } - } -#endif /* HAVE_CRL */ + if (request == NULL) + return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */ + + #ifdef WOLFSSL_SMALL_STACK + 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_OCSP_STATUS); + if (response) + XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + + return MEMORY_ERROR; } -#endif /* HAVE_OCSP || HAVE_CRL */ + #endif - if (ret != 0 && anyError == 0) - anyError = ret; /* save error from last time */ + InitOcspResponse(response, status, input +*inOutIdx, status_length); - FreeDecodedCert(dCert); - count--; + 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, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); + XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + #endif + + return ret; +} +#endif + + + +#ifdef HAVE_PK_CALLBACKS + +#ifdef HAVE_ECC + static int SigPkCbEccVerify(const unsigned char* sig, unsigned int sigSz, + const unsigned char* hash, unsigned int hashSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx) + { + int ret = NOT_COMPILED_IN; + WOLFSSL* ssl = (WOLFSSL*)ctx; + + if (ssl && ssl->ctx->EccVerifyCb) { + ret = ssl->ctx->EccVerifyCb(ssl, sig, sigSz, hash, hashSz, + keyDer, keySz, result, ssl->EccVerifyCtx); + } + return ret; + } +#endif +#ifndef NO_RSA + static int SigPkCbRsaVerify(unsigned char* sig, unsigned int sigSz, + unsigned char** out, const unsigned char* keyDer, unsigned int keySz, + void* ctx) + { + int ret = NOT_COMPILED_IN; + WOLFSSL* ssl = (WOLFSSL*)ctx; + + if (ssl && ssl->ctx->RsaVerifyCb) { + ret = ssl->ctx->RsaVerifyCb(ssl, sig, sigSz, out, keyDer, keySz, + ssl->RsaVerifyCtx); + } + return ret; + } +#endif + +int InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx) +{ + if (ssl == NULL || sigCtx == NULL) + return BAD_FUNC_ARG; + + /* only setup the verify callback if a PK is set */ +#ifdef HAVE_ECC + if (ssl->ctx->EccVerifyCb) { + sigCtx->pkCbEcc = SigPkCbEccVerify; + sigCtx->pkCtxEcc = ssl; + } +#endif +#ifndef NO_RSA + /* only setup the verify callback if a PK is set */ + if (ssl->ctx->RsaVerifyCb) { + sigCtx->pkCbRsa = SigPkCbRsaVerify; + sigCtx->pkCtxRsa = ssl; + } +#endif + + return 0; +} + +#endif /* HAVE_PK_CALLBACKS */ + + +#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH) +static void DoCertFatalAlert(WOLFSSL* ssl, int ret) +{ + int alertWhy; + if (ssl == NULL || ret == 0) { + return; } - /* 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"); - - InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap); - ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone, - ssl->ctx->cm); - if (ret == 0) { - WOLFSSL_MSG("Verified Peer's cert"); - 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 (ssl->keys.encryptionOn) { - /* 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); - } - } + /* Determine alert reason */ + alertWhy = bad_certificate; + if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) { + alertWhy = certificate_expired; + } +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) + else if (ret == CRL_CERT_REVOKED) { + alertWhy = certificate_revoked; + } #endif - -#if defined(HAVE_OCSP) || defined(HAVE_CRL) - if (fatal == 0) { - int doCrlLookup = 1; - (void)doCrlLookup; -#ifdef HAVE_OCSP - if (ssl->ctx->cm->ocspEnabled) { - ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert); - doCrlLookup = (ret == OCSP_CERT_UNKNOWN); - if (ret != 0) { - WOLFSSL_MSG("\tOCSP Lookup not ok"); - fatal = 0; - } - } -#endif /* HAVE_OCSP */ - -#ifdef HAVE_CRL - if (doCrlLookup && 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 */ - } -#endif /* HAVE_OCSP || HAVE_CRL */ - -#ifdef KEEP_PEER_CERT - { - /* set X509 format for peer cert even if fatal */ - int copyRet = CopyDecodedToX509(&ssl->peerCert, dCert); - if (copyRet == MEMORY_E) - fatal = 1; - } -#endif - -#ifndef IGNORE_KEY_EXTENSIONS - if (dCert->extKeyUsageSet) { - if ((ssl->specs.kea == rsa_kea) && - (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; - } - } - - 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; - } - } - else { - if ((dCert->extExtKeyUsage & - (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) { - WOLFSSL_MSG("ExtKeyUse Client Auth not set"); - ret = EXTKEYUSE_AUTH_E; - } - } - } -#endif /* IGNORE_KEY_EXTENSIONS */ - - if (fatal) { - FreeDecodedCert(dCert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - ssl->error = ret; - return ret; - } - ssl->options.havePeerCert = 1; - -#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 if (ret == NO_PEER_CERT) { +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + alertWhy = certificate_required; } else - domain[0] = '\0'; - - if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) { - if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen, - (char*)ssl->buffers.domainName.buffer) == 0) { - WOLFSSL_MSG("DomainName match on common name failed"); - if (CheckAltNames(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 */ - } - } - } - - /* decode peer key */ - switch (dCert->keyOID) { - #ifndef NO_RSA - case RSAk: - { - word32 idx = 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(ssl->peerRsaKey, - ssl->ctx->heap); - } - } else if (ssl->peerRsaKeyPresent) { - /* don't leak on reuse */ - wc_FreeRsaKey(ssl->peerRsaKey); - ssl->peerRsaKeyPresent = 0; - keyRet = wc_InitRsaKey(ssl->peerRsaKey, ssl->heap); - } - - 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 */ - } - } - 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: - { - if (ssl->peerEccDsaKey == NULL) { - /* alloc/init on demand */ - ssl->peerEccDsaKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->ctx->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccDsaKey == NULL) { - WOLFSSL_MSG("PeerEccDsaKey Memory error"); - return MEMORY_E; - } - wc_ecc_init(ssl->peerEccDsaKey); - } else if (ssl->peerEccDsaKeyPresent) { - /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccDsaKey); - ssl->peerEccDsaKeyPresent = 0; - wc_ecc_init(ssl->peerEccDsaKey); - } - if (wc_ecc_import_x963(dCert->publicKey, dCert->pubKeySize, - ssl->peerEccDsaKey) != 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 */ - } - } - break; - #endif /* HAVE_ECC */ - default: - break; - } - - FreeDecodedCert(dCert); - } - -#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 + { + alertWhy = handshake_failure; + } + } - if (anyError != 0 && ret == 0) - ret = anyError; + /* send fatal alert and mark connection closed */ + SendAlert(ssl, alert_fatal, alertWhy); /* try to send */ + ssl->options.isClosed = 1; +} +/* WOLFSSL_ALWAYS_VERIFY_CB: Use verify callback for success or failure cases */ +/* WOLFSSL_VERIFY_CB_ALL_CERTS: Issue callback for all intermediate certificates */ + +/* Callback is issued for certificate presented in TLS Certificate (11) packet. + * The intermediates are done first then peer leaf cert last. Use the + * store->error_depth member to determine index (0=peer, >1 intermediates) + */ + +int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, + ProcPeerCertArgs* args) +{ + int verify_ok = 0, use_cb = 0; + void *heap = (ssl != NULL) ? ssl->heap : cm->heap; + + /* Determine if verify was okay */ + if (ret == 0) { + verify_ok = 1; + } + + /* Determine if verify callback should be used */ 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; -#ifdef KEEP_PEER_CERT - store->current_cert = &ssl->peerCert; -#else - store->current_cert = NULL; -#endif -#ifdef 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; - } - #endif - } - if (ret != 0) { - SendAlert(ssl, alert_fatal, why); /* try to send */ - ssl->options.isClosed = 1; - } + if ((ssl != NULL) && (!ssl->options.verifyNone)) { + use_cb = 1; /* always report errors */ } - ssl->error = ret; } #ifdef WOLFSSL_ALWAYS_VERIFY_CB - else { - if (ssl->verifyCallback) { - int ok; - - store->error = ret; - store->error_depth = totalCerts; - store->discardSessionCerts = 0; - store->domain = domain; - store->userCtx = ssl->verifyCbCtx; -#ifdef KEEP_PEER_CERT - store->current_cert = &ssl->peerCert; + /* always use verify callback on peer leaf cert */ + if (args->certIdx == 0) { + use_cb = 1; + } #endif - store->ex_data = ssl; +#ifdef WOLFSSL_VERIFY_CB_ALL_CERTS + /* perform verify callback on other intermediate certs (not just peer) */ + if (args->certIdx > 0) { + use_cb = 1; + } +#endif +#if defined(OPENSSL_EXTRA) + /* perform domain name check on the peer certificate */ + if (args->dCertInit && args->dCert && (ssl != NULL) && + ssl->param && ssl->param->hostName[0]) { + /* If altNames names is present, then subject common name is ignored */ + if (args->dCert->altNames != NULL) { + if (CheckAltNames(args->dCert, ssl->param->hostName) == 0 ) { + if (ret == 0) { + ret = DOMAIN_NAME_MISMATCH; + } + } + } + else { + if (args->dCert->subjectCN) { + if (MatchDomainName(args->dCert->subjectCN, + args->dCert->subjectCNLen, + ssl->param->hostName) == 0) { + if (ret == 0) { + ret = DOMAIN_NAME_MISMATCH; + } + } + } + } + } - 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; + /* perform IP address check on the peer certificate */ + if ((args->dCertInit != 0) && (args->dCert != NULL) && (ssl != NULL) && + (ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) { + if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) { + if (ret == 0) { + ret = IPADDR_MISMATCH; } - #ifdef SESSION_CERTS - if (store->discardSessionCerts) { - WOLFSSL_MSG("Verify callback requested discard sess certs"); - ssl->session.chain.count = 0; - } - #endif } } #endif + /* if verify callback has been set */ + if ((use_cb && (ssl != NULL) && ((ssl->verifyCallback != NULL) + #ifdef OPENSSL_ALL + || (ssl->ctx->verifyCertCb != NULL) + #endif + )) + #ifndef NO_WOLFSSL_CM_VERIFY + || (cm->verifyCallback != NULL) + #endif + ) { + int verifyFail = 0; + #ifdef WOLFSSL_SMALL_STACK + WOLFSSL_X509_STORE_CTX* store; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_X509* x509; + #endif + char* domain = NULL; + #else + WOLFSSL_X509_STORE_CTX store[1]; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_X509 x509[1]; + #endif + char domain[ASN_NAME_MAX]; + #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; + #ifdef WOLFSSL_SMALL_STACK + store = (WOLFSSL_X509_STORE_CTX*)XMALLOC( + sizeof(WOLFSSL_X509_STORE_CTX), heap, DYNAMIC_TYPE_X509_STORE); + if (store == NULL) { + return MEMORY_E; + } + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, + DYNAMIC_TYPE_X509); + if (x509 == NULL) { + XFREE(store, heap, DYNAMIC_TYPE_X509); + return MEMORY_E; + } + #endif + domain = (char*)XMALLOC(ASN_NAME_MAX, heap, DYNAMIC_TYPE_STRING); + if (domain == NULL) { + XFREE(store, heap, DYNAMIC_TYPE_X509); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + XFREE(x509, heap, DYNAMIC_TYPE_X509); + #endif + return MEMORY_E; + } + #endif /* WOLFSSL_SMALL_STACK */ + + XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX)); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + XMEMSET(x509, 0, sizeof(WOLFSSL_X509)); + #endif + domain[0] = '\0'; + + /* build subject CN as string to return in store */ + if (args->dCertInit && args->dCert && args->dCert->subjectCN) { + int subjectCNLen = args->dCert->subjectCNLen; + if (subjectCNLen > ASN_NAME_MAX-1) + subjectCNLen = ASN_NAME_MAX-1; + if (subjectCNLen > 0) { + XMEMCPY(domain, args->dCert->subjectCN, subjectCNLen); + domain[subjectCNLen] = '\0'; + } + } + + store->error = ret; + store->error_depth = args->certIdx; + store->discardSessionCerts = 0; + store->domain = domain; + store->userCtx = (ssl != NULL) ? ssl->verifyCbCtx : cm; + store->certs = args->certs; + store->totalCerts = args->totalCerts; + #if defined(HAVE_EX_DATA) || defined(FORTRESS) + if (wolfSSL_CRYPTO_set_ex_data(&store->ex_data, 0, ssl) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Failed to store ssl context in WOLFSSL_X509_STORE_CTX"); + } + #endif + + if (ssl != NULL) { + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if (ssl->ctx->x509_store_pt != NULL) { + store->store = ssl->ctx->x509_store_pt; + } + else { + store->store = &ssl->ctx->x509_store; + } + #if defined(OPENSSL_EXTRA) + store->depth = args->count; + store->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( + sizeof(WOLFSSL_X509_VERIFY_PARAM), + heap, DYNAMIC_TYPE_OPENSSL); + if (store->param == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(domain, heap, DYNAMIC_TYPE_STRING); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + XFREE(x509, heap, DYNAMIC_TYPE_X509); + #endif + XFREE(store, heap, DYNAMIC_TYPE_X509_STORE); + #endif + return MEMORY_E; + } + XMEMSET(store->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + /* Overwrite with non-default param values in SSL */ + if (ssl->param) { + if (ssl->param->check_time) + store->param->check_time = ssl->param->check_time; + + if (ssl->param->flags) + store->param->flags = ssl->param->flags; + + if (ssl->param->hostName[0]) + XMEMCPY(store->param->hostName, ssl->param->hostName, + WOLFSSL_HOST_NAME_MAX); + + } + #endif /* defined(OPENSSL_EXTRA) */ + #endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)*/ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + #ifdef KEEP_PEER_CERT + if (args->certIdx == 0) { + store->current_cert = &ssl->peerCert; /* use existing X509 */ + } + else + #endif + { + InitX509(x509, 0, heap); + if (CopyDecodedToX509(x509, args->dCert) == 0) { + store->current_cert = x509; + } + else { + FreeX509(x509); + } + } + #endif + #ifdef SESSION_CERTS + store->sesChain = &ssl->session.chain; + #endif + } + #ifndef NO_WOLFSSL_CM_VERIFY + /* non-zero return code indicates failure override */ + if ((cm != NULL) && (cm->verifyCallback != NULL)) { + store->userCtx = cm; + if (cm->verifyCallback(verify_ok, store)) { + if (ret != 0) { + WOLFSSL_MSG("Verify CM callback overriding error!"); + ret = 0; + } + } + else { + verifyFail = 1; + } + } + #endif + + if (ssl != NULL) { + #ifdef OPENSSL_ALL + /* non-zero return code indicates failure override */ + if (ssl->ctx->verifyCertCb) { + if (ssl->ctx->verifyCertCb(store, ssl->ctx->verifyCertCbArg)) { + if (ret != 0) { + WOLFSSL_MSG("Verify Cert callback overriding error!"); + ret = 0; + } + } + else { + verifyFail = 1; + } + } + #endif + + /* non-zero return code indicates failure override */ + if (ssl->verifyCallback) { + if (ssl->verifyCallback(verify_ok, store)) { + if (ret != 0) { + WOLFSSL_MSG("Verify callback overriding error!"); + ret = 0; + } + } + else { + verifyFail = 1; + } + } + } + + if (verifyFail) { + /* induce error if one not present */ + if (ret == 0) { + ret = VERIFY_CERT_ERROR; + } + + /* mark as verify error */ + args->verifyErr = 1; + } + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + if (args->certIdx > 0) + FreeX509(x509); + #endif + #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + wolfSSL_sk_X509_free(store->chain); + store->chain = NULL; + #endif + #ifdef SESSION_CERTS + if ((ssl != NULL) && (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 */ +#ifdef OPENSSL_EXTRA + if ((ssl != NULL) && (store->param)) { + XFREE(store->param, heap, DYNAMIC_TYPE_OPENSSL); + } +#endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(domain, heap, DYNAMIC_TYPE_STRING); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + XFREE(x509, heap, DYNAMIC_TYPE_X509); + #endif + XFREE(store, heap, DYNAMIC_TYPE_X509_STORE); + #endif } - if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) - ssl->options.serverState = SERVER_CERT_COMPLETE; + (void)heap; - if (ssl->keys.encryptionOn) { - *inOutIdx += ssl->keys.padSz; + return ret; +} + +static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs) +{ + ProcPeerCertArgs* args = (ProcPeerCertArgs*)pArgs; + + (void)ssl; + + 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; + } +} + +static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args, + int certType, int verify, byte** pSubjectHash, int* pAlreadySigner) +{ + int ret = 0; + buffer* cert; + byte* subjectHash = NULL; + int alreadySigner = 0; +#ifdef WOLFSSL_SMALL_CERT_VERIFY + int sigRet = 0; +#endif + + if (ssl == NULL || args == NULL) + return BAD_FUNC_ARG; + + /* check to make sure certificate index is valid */ + if (args->certIdx > args->count) + return BUFFER_E; + + /* check if returning from non-blocking OCSP */ + /* skip this section because cert is already initialized and parsed */ +#ifdef WOLFSSL_NONBLOCK_OCSP + if (args->lastErr == OCSP_WANT_READ) { + args->lastErr = 0; /* clear error */ + return 0; + } +#endif + +#ifdef WOLFSSL_TRUST_PEER_CERT + /* we have trusted peer */ + if (args->haveTrustPeer) { + return 0; + } +#endif + + /* get certificate buffer */ + cert = &args->certs[args->certIdx]; + +#ifdef WOLFSSL_SMALL_CERT_VERIFY + if (verify == VERIFY) { + /* for small cert verify, release decoded cert during signature check to + reduce peak memory usage */ + if (args->dCert != NULL) { + if (args->dCertInit) { + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } + XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT); + args->dCert = NULL; + } + + /* perform cert parsing and signature check */ + sigRet = CheckCertSignature(cert->buffer, cert->length, + ssl->heap, ssl->ctx->cm); + /* fail on errors here after the ParseCertRelative call, so dCert is populated */ + + /* verify name only in ParseCertRelative below, signature check done */ + verify = VERIFY_NAME; + } +#endif /* WOLFSSL_SMALL_CERT_VERIFY */ + + /* make sure the decoded cert structure is allocated and initialized */ + if (!args->dCertInit + #ifdef WOLFSSL_SMALL_CERT_VERIFY + || args->dCert == NULL + #endif + ) { + #ifdef WOLFSSL_SMALL_CERT_VERIFY + if (args->dCert == NULL) { + args->dCert = (DecodedCert*)XMALLOC( + sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (args->dCert == NULL) { + return MEMORY_E; + } + } + #endif + + InitDecodedCert(args->dCert, cert->buffer, cert->length, ssl->heap); + + args->dCertInit = 1; + args->dCert->sigCtx.devId = ssl->devId; + #ifdef WOLFSSL_ASYNC_CRYPT + args->dCert->sigCtx.asyncCtx = ssl; + #endif + + #ifdef HAVE_PK_CALLBACKS + /* setup the PK callback context */ + ret = InitSigPkCb(ssl, &args->dCert->sigCtx); + if (ret != 0) + return ret; + #endif } -#ifdef WOLFSSL_SMALL_STACK - XFREE(store, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER); + /* Parse Certificate */ + ret = ParseCertRelative(args->dCert, certType, verify, ssl->ctx->cm); + /* perform below checks for date failure cases */ + if (ret == 0 || ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) { + /* get subject and determine if already loaded */ + #ifndef NO_SKID + if (args->dCert->extAuthKeyIdSet) + subjectHash = args->dCert->extSubjKeyId; + else + #endif + subjectHash = args->dCert->subjectHash; + alreadySigner = AlreadySigner(ssl->ctx->cm, subjectHash); + } + +#ifdef WOLFSSL_SMALL_CERT_VERIFY + /* get signature check failures from above */ + if (ret == 0) + ret = sigRet; +#endif + + if (pSubjectHash) + *pSubjectHash = subjectHash; + if (pAlreadySigner) + *pAlreadySigner = alreadySigner; + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + args->dCert->sigCtx.asyncDev); + } #endif return ret; } +/* Check key sizes for certs. Is redundant check since + ProcessBuffer also performs this check. */ +static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args) +{ + int ret = 0; + + if (ssl->options.verifyNone) { + return ret; + } + + 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 */ + #ifdef HAVE_ED448 + case ED448k: + if (ssl->options.minEccKeySz < 0 || + ED448_KEY_SIZE < (word16)ssl->options.minEccKeySz) { + WOLFSSL_MSG( + "ECC key size in cert chain error"); + ret = ECC_KEY_SIZE_E; + } + break; + #endif /* HAVE_ED448 */ + default: + WOLFSSL_MSG("Key size not checked"); + /* key not being checked for size if not in + switch */ + break; + } + + return ret; +} + +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; +#elif defined(WOLFSSL_SMALL_STACK) + ProcPeerCertArgs* args = NULL; +#else + ProcPeerCertArgs args[1]; +#endif + byte* subjectHash = NULL; + int alreadySigner = 0; + + 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 */ +#elif defined(WOLFSSL_SMALL_STACK) + args = (ProcPeerCertArgs*)XMALLOC( + sizeof(ProcPeerCertArgs), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } +#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 + } + + switch (ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + word32 listSz; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "Certificate"); + if (ssl->toInfoOn) + AddLateName("Certificate", &ssl->timeoutInfo); + #endif + + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + byte ctxSz; + + /* Certificate Request Context */ + if ((args->idx - args->begin) + OPAQUE8_LEN > totalSz) + ERROR_OUT(BUFFER_ERROR, exit_ppc); + ctxSz = *(input + args->idx); + args->idx++; + if ((args->idx - args->begin) + ctxSz > totalSz) + ERROR_OUT(BUFFER_ERROR, exit_ppc); + #ifndef NO_WOLFSSL_CLIENT + /* Must be empty when received from server. */ + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ctxSz != 0) { + ERROR_OUT(INVALID_CERT_CTX_E, exit_ppc); + } + } + #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) { + ERROR_OUT(INVALID_CERT_CTX_E, exit_ppc); + } + 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 + ERROR_OUT(INVALID_CERT_CTX_E, exit_ppc); + } + } + #endif + args->idx += ctxSz; + + #ifdef OPENSSL_EXTRA + /* allocate buffer for cert extensions */ + args->exts = (buffer*)XMALLOC(sizeof(buffer) * + (ssl->verifyDepth + 1), ssl->heap, DYNAMIC_TYPE_CERT_EXT); + if (args->exts == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + #else + /* 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); + } + #endif + } + #endif + + /* allocate buffer for certs */ + #ifdef OPENSSL_EXTRA + args->certs = (buffer*)XMALLOC(sizeof(buffer) * + (ssl->verifyDepth + 1), ssl->heap, DYNAMIC_TYPE_DER); + if (args->certs == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + XMEMSET(args->certs, 0, sizeof(buffer) * (ssl->verifyDepth + 1)); + #else + args->certs = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH, + ssl->heap, DYNAMIC_TYPE_DER); + if (args->certs == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + XMEMSET(args->certs, 0, sizeof(buffer) * MAX_CHAIN_DEPTH); + #endif /* OPENSSL_EXTRA */ + + /* 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_CERTIFICATE_SZ) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + if ((args->idx - args->begin) + listSz != totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + + 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 defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + if (args->totalCerts > ssl->verifyDepth) { + ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG; + ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc); + } + #else + if (args->totalCerts >= ssl->verifyDepth || + args->totalCerts >= MAX_CHAIN_DEPTH) { + ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc); + } + #endif + + 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) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + ato16(input + args->idx, &extSz); + args->idx += OPAQUE16_LEN; + if ((args->idx - args->begin) + extSz > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + /* 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; + ret = TLSX_Parse(ssl, args->exts[args->totalCerts].buffer, + args->exts[args->totalCerts].length, certificate, NULL); + if (ret < 0) { + ERROR_OUT(ret, exit_ppc); + } + } + #endif + + args->totalCerts++; + WOLFSSL_MSG("\tPut another cert into chain"); + } /* while (listSz) */ + + args->count = args->totalCerts; + args->certIdx = 0; /* select peer cert (first one) */ + + if (args->count == 0 && ssl->options.mutualAuth && + ssl->options.side == WOLFSSL_SERVER_END) { + ret = NO_PEER_CERT; + DoCertFatalAlert(ssl, ret); + } + + args->dCertInit = 0; + #ifndef WOLFSSL_SMALL_CERT_VERIFY + args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (args->dCert == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + XMEMSET(args->dCert, 0, sizeof(DecodedCert)); + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + if (args->count > 0) { + + /* check for trusted peer and get untrustedDepth */ + #if defined(WOLFSSL_TRUST_PEER_CERT) || defined(OPENSSL_EXTRA) + if (args->certIdx == 0) { + #ifdef WOLFSSL_TRUST_PEER_CERT + TrustedPeerCert* tp; + int matchType = WC_MATCH_NAME; + #endif + + ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, NO_VERIFY, + &subjectHash, &alreadySigner); + if (ret != 0) + goto exit_ppc; + + #ifdef OPENSSL_EXTRA + /* Determine untrusted depth */ + if (!alreadySigner && (!args->dCert || + !args->dCertInit || !args->dCert->selfSigned)) { + args->untrustedDepth = 1; + } + #endif + + #ifdef WOLFSSL_TRUST_PEER_CERT + #ifndef NO_SKID + if (args->dCert->extAuthKeyIdSet) + matchType = WC_MATCH_SKID; + #endif + tp = GetTrustedPeer(ssl->ctx->cm, subjectHash, matchType); + WOLFSSL_MSG("Checking for trusted peer cert"); + + if (tp && MatchTrustedPeer(tp, args->dCert)) { + WOLFSSL_MSG("Found matching trusted peer cert"); + args->haveTrustPeer = 1; + } + else if (tp == NULL) { + /* no trusted peer cert */ + WOLFSSL_MSG("No matching trusted peer cert. Checking CAs"); + } + else { + WOLFSSL_MSG("Trusted peer cert did not match!"); + } + if (!args->haveTrustPeer) + #endif + { + /* free cert if not trusted peer */ + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } + } + #endif /* WOLFSSL_TRUST_PEER_CERT || OPENSSL_EXTRA */ + + /* check certificate up to peer's first */ + /* do not verify chain if trusted peer cert found */ + while (args->count > 1 + #ifdef WOLFSSL_TRUST_PEER_CERT + && !args->haveTrustPeer + #endif /* WOLFSSL_TRUST_PEER_CERT */ + ) { + int skipAddCA = 0; + + /* select last certificate */ + args->certIdx = args->count - 1; + + ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, + !ssl->options.verifyNone ? VERIFY : NO_VERIFY, + &subjectHash, &alreadySigner); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_ppc; + #endif + if (ret == 0) { + ret = ProcessPeerCertCheckKey(ssl, args); + } + + 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) { + #ifdef OPENSSL_EXTRA + if (args->certIdx > args->untrustedDepth) { + args->untrustedDepth = (char)args->certIdx + 1; + } + #endif + + if (alreadySigner) { + WOLFSSL_MSG("Verified CA from chain and already had it"); + } + } + else { + WOLFSSL_MSG("Failed to verify CA from chain"); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->peerVerifyRet = X509_V_ERR_INVALID_CA; + #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 */ + + /* Do verify callback */ + ret = DoVerifyCallback(ssl->ctx->cm, ssl, ret, args); + + #ifdef WOLFSSL_ALT_CERT_CHAINS + /* For alternate cert chain, its okay for a CA cert to fail + with ASN_NO_SIGNER_E here. The "alternate" certificate + chain mode only requires that the peer certificate + validate to a trusted CA */ + if (ret != 0 && args->dCert->isCA) { + if (ret == ASN_NO_SIGNER_E) { + if (!ssl->options.usingAltCertChain) { + WOLFSSL_MSG("Trying alternate cert chain"); + ssl->options.usingAltCertChain = 1; + } + + ret = 0; /* clear error and continue */ + } + + /* do not add to certificate manager */ + skipAddCA = 1; + } + #endif /* WOLFSSL_ALT_CERT_CHAINS */ + + /* If valid CA then add to Certificate Manager */ + if (ret == 0 && args->dCert->isCA && + !ssl->options.verifyNone && !skipAddCA) { + buffer* cert = &args->certs[args->certIdx]; + + /* Is valid CA */ + #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS) + /* if using alternate chain, store the cert used */ + if (ssl->options.usingAltCertChain) { + AddSessionCertToChain(&ssl->session.altChain, + cert->buffer, cert->length); + } + #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */ + if (!alreadySigner) { + DerBuffer* add = NULL; + ret = AllocDer(&add, cert->length, CA_TYPE, ssl->heap); + if (ret < 0) + goto exit_ppc; + + XMEMCPY(add->buffer, cert->buffer, cert->length); + + /* CA already verified above in ParseCertRelative */ + WOLFSSL_MSG("Adding CA from chain"); + ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, + NO_VERIFY); + if (ret == WOLFSSL_SUCCESS) { + ret = 0; + } + } + } + + /* Handle error codes */ + if (ret != 0) { + if (!ssl->options.verifyNone) { + DoCertFatalAlert(ssl, ret); + } + ssl->error = ret; /* Report SSL error */ + + if (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 && !args->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"); + + /* select peer cert (first one) */ + args->certIdx = 0; + + ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, + !ssl->options.verifyNone ? VERIFY : NO_VERIFY, + &subjectHash, &alreadySigner); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_ppc; + #endif + if (ret == 0) { + WOLFSSL_MSG("Verified Peer's cert"); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->peerVerifyRet = X509_V_OK; + #endif + #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS) + /* if using alternate chain, store the cert used */ + if (ssl->options.usingAltCertChain) { + buffer* cert = &args->certs[args->certIdx]; + AddSessionCertToChain(&ssl->session.altChain, + cert->buffer, cert->length); + } + #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */ + + /* check if fatal error */ + if (args->verifyErr) { + args->fatal = 1; + if (ret == 0) { + ret = args->lastErr; + } + } + else { + args->fatal = 0; + } + } + else if (ret == ASN_PARSE_E || ret == BUFFER_E) { + WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR"); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + SendAlert(ssl, alert_fatal, bad_certificate); + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + args->fatal = 1; + } + else { + WOLFSSL_MSG("Failed to verify Peer's cert"); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->peerVerifyRet = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; + #endif + if (ssl->verifyCallback) { + WOLFSSL_MSG( + "\tCallback override available, will continue"); + /* check if fatal error */ + args->fatal = (args->verifyErr) ? 1 : 0; + } + else { + WOLFSSL_MSG("\tNo callback override available, fatal"); + args->fatal = 1; + #ifdef OPENSSL_EXTRA + SendAlert(ssl, alert_fatal, bad_certificate); + #endif + } + } + + #ifdef HAVE_SECURE_RENEGOTIATION + if (args->fatal == 0 && !IsAtLeastTLSv1_3(ssl->version) + && ssl->secure_renegotiation + && ssl->secure_renegotiation->enabled) { + + if (IsEncryptionOn(ssl, 0)) { + /* compare against previous time */ + if (ssl->secure_renegotiation->subject_hash_set) { + if (XMEMCMP(args->dCert->subjectHash, + ssl->secure_renegotiation->subject_hash, + KEYID_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, KEYID_SIZE); + ssl->secure_renegotiation->subject_hash_set = 1; + } + } + #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; + #if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + if (ssl->options.tls1_3) { + TLSX* ext = TLSX_Find(ssl->extensions, + TLSX_STATUS_REQUEST); + if (ext != NULL) { + word32 idx = 0; + CertificateStatusRequest* csr = + (CertificateStatusRequest*)ext->data; + ret = ProcessCSR(ssl, csr->response.buffer, + &idx, csr->response.length); + if (ret < 0) + goto exit_ppc; + } + } + #endif + } + #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; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + 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; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + 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) { + int copyRet = 0; + + #ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && + ssl->secure_renegotiation->enabled) { + /* free old peer cert */ + FreeX509(&ssl->peerCert); + } + #endif + + /* set X509 format for peer cert */ + copyRet = CopyDecodedToX509(&ssl->peerCert, args->dCert); + if (copyRet == MEMORY_E) { + args->fatal = 1; + } + } + #endif /* KEEP_PEER_CERT */ + + #ifndef IGNORE_KEY_EXTENSIONS + #if defined(OPENSSL_EXTRA) + /* when compatibility layer is turned on and no verify is + * set then ignore the certificate key extension */ + if (args->dCert->extKeyUsageSet && + args->dCert->extKeyUsageCrit == 0 && + ssl->options.verifyNone) { + WOLFSSL_MSG("Not verifying certificate key usage"); + } + else + #endif + 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 defined(OPENSSL_EXTRA) + /* when compatibility layer is turned on and no verify is + * set then ignore the certificate key extension */ + if (args->dCert->extExtKeyUsageSet && + args->dCert->extExtKeyUsageCrit == 0 && + ssl->options.verifyNone) { + WOLFSSL_MSG("Not verifying certificate ext key usage"); + } + else + #endif + 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; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + SendAlert(ssl, alert_fatal, bad_certificate); + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + goto exit_ppc; + } + + ssl->options.havePeerCert = 1; + + if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) { + #ifndef WOLFSSL_ALLOW_NO_CN_IN_SAN + /* Per RFC 5280 section 4.2.1.6, "Whenever such identities + * are to be bound into a certificate, the subject + * alternative name extension MUST be used." */ + if (args->dCert->altNames) { + if (CheckAltNames(args->dCert, + (char*)ssl->buffers.domainName.buffer) == 0 ) { + WOLFSSL_MSG("DomainName match on alt names failed"); + /* try to get peer key still */ + ret = DOMAIN_NAME_MISMATCH; + } + } + else { + if (MatchDomainName( + args->dCert->subjectCN, + args->dCert->subjectCNLen, + (char*)ssl->buffers.domainName.buffer) == 0) { + WOLFSSL_MSG("DomainName match on common name failed"); + ret = DOMAIN_NAME_MISMATCH; + } + } + #else /* WOLFSSL_ALL_NO_CN_IN_SAN */ + /* Old behavior. */ + if (MatchDomainName(args->dCert->subjectCN, + args->dCert->subjectCNLen, + (char*)ssl->buffers.domainName.buffer) == 0) { + 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"); + /* try to get peer key still */ + ret = DOMAIN_NAME_MISMATCH; + } + } + #endif /* WOLFSSL_ALL_NO_CN_IN_SAN */ + } + + /* decode peer key */ + switch (args->dCert->keyOID) { + #ifndef NO_RSA + case RSAk: + { + word32 keyIdx = 0; + int keyRet = 0; + + if (ssl->peerRsaKey == NULL) { + keyRet = AllocKey(ssl, DYNAMIC_TYPE_RSA, + (void**)&ssl->peerRsaKey); + } else if (ssl->peerRsaKeyPresent) { + keyRet = ReuseKey(ssl, DYNAMIC_TYPE_RSA, + ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; + } + + if (keyRet != 0 || wc_RsaPublicKeyDecode( + args->dCert->publicKey, &keyIdx, ssl->peerRsaKey, + args->dCert->pubKeySize) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerRsaKeyPresent = 1; + #ifdef WOLFSSL_RENESAS_TSIP_TLS + /* copy encrypted tsip key index into ssl object */ + if (args->dCert->tsip_encRsaKeyIdx) { + if (!ssl->peerTsipEncRsaKeyIndex) { + ssl->peerTsipEncRsaKeyIndex = (byte*)XMALLOC( + TSIP_TLS_ENCPUBKEY_SZ_BY_CERTVRFY, + ssl->heap, DYNAMIC_TYPE_RSA); + if (!ssl->peerTsipEncRsaKeyIndex) { + args->lastErr = MEMORY_E; + goto exit_ppc; + } + } + + XMEMCPY(ssl->peerTsipEncRsaKeyIndex, + args->dCert->tsip_encRsaKeyIdx, + TSIP_TLS_ENCPUBKEY_SZ_BY_CERTVRFY); + } + #endif + #ifdef HAVE_PK_CALLBACKS + #ifndef NO_RSA + #ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->buffers.peerRsaKey.buffer) { + XFREE(ssl->buffers.peerRsaKey.buffer, + ssl->heap, DYNAMIC_TYPE_RSA); + ssl->buffers.peerRsaKey.buffer = NULL; + } + #endif + + + 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) + < 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 (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 keyRet = 0; + word32 idx = 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; + } + + if (keyRet != 0 || + wc_EccPublicKeyDecode(args->dCert->publicKey, &idx, + ssl->peerEccDsaKey, + args->dCert->pubKeySize) != 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 && + !ssl->options.verifyNone && + wc_ecc_size(ssl->peerEccDsaKey) + < ssl->options.minEccKeySz) { + 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_ED25519 */ + #ifdef HAVE_ED448 + case ED448k: + { + int keyRet = 0; + if (ssl->peerEd448Key == NULL) { + /* alloc/init on demand */ + keyRet = AllocKey(ssl, DYNAMIC_TYPE_ED448, + (void**)&ssl->peerEd448Key); + } else if (ssl->peerEd448KeyPresent) { + keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ED448, + ssl->peerEd448Key); + ssl->peerEd448KeyPresent = 0; + } + + if (keyRet != 0 || + wc_ed448_import_public(args->dCert->publicKey, + args->dCert->pubKeySize, + ssl->peerEd448Key) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerEd448KeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEd448Key.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_ED448); + if (ssl->buffers.peerEd448Key.buffer == NULL) { + ERROR_OUT(MEMORY_ERROR, exit_ppc); + } + else { + XMEMCPY(ssl->buffers.peerEd448Key.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerEd448Key.length = + args->dCert->pubKeySize; + } + #endif /*HAVE_PK_CALLBACKS */ + } + + /* check size of peer ECC key */ + if (ret == 0 && ssl->peerEd448KeyPresent && + !ssl->options.verifyNone && + ED448_KEY_SIZE < ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Peer ECC key is too small"); + } + break; + } + #endif /* HAVE_ED448 */ + default: + break; + } + + /* args->dCert free'd in function cleanup after callback */ + } /* 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: + { + /* load last error */ + if (args->lastErr != 0 && ret == 0) { + ret = args->lastErr; + } + + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + if (args->untrustedDepth > ssl->options.verifyDepth) { + ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG; + ret = MAX_CHAIN_ERROR; + } + #endif + + /* Do verify callback */ + ret = DoVerifyCallback(ssl->ctx->cm, ssl, ret, args); + + 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) { + if (!ssl->options.verifyNone) { + DoCertFatalAlert(ssl, ret); + } + ssl->error = ret; /* Report SSL error */ + } + + if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.serverState = SERVER_CERT_COMPLETE; + } + + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + args->idx += MacSize(ssl); + #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; + } + default: + ret = INPUT_CASE_ERROR; + break; + } /* switch(ssl->options.asyncState) */ + +exit_ppc: + + 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 received 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) +#elif defined(WOLFSSL_NONBLOCK_OCSP) + XFREE(args, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + ssl->nonblockarg = NULL; +#elif defined(WOLFSSL_SMALL_STACK) + XFREE(args, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + FreeKeyExchange(ssl); + + return ret; +} +#endif + +#ifndef WOLFSSL_NO_TLS12 +#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH) + +/* handle processing of certificate (11) */ +static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) +{ + int ret; + + WOLFSSL_START(WC_FUNC_CERTIFICATE_DO); + WOLFSSL_ENTER("DoCertificate"); + +#ifdef SESSION_CERTS + /* Reset the session cert chain count in case the session resume failed. */ + ssl->session.chain.count = 0; + #ifdef WOLFSSL_ALT_CERT_CHAINS + ssl->session.altChain.count = 0; + #endif +#endif /* SESSION_CERTS */ + + ret = ProcessPeerCerts(ssl, input, inOutIdx, size); +#ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_ERROR || ret == ASN_PARSE_E) + SendAlert(ssl, alert_fatal, decode_error); +#endif + +#ifdef OPENSSL_EXTRA + ssl->options.serverState = SERVER_CERT_COMPLETE; +#endif + + WOLFSSL_LEAVE("DoCertificate", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_DO); + + return ret; +} + +/* handle processing of certificate_status (22) */ +static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) +{ + int ret = 0; + byte status_type; + word32 status_length; + + WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_DO); + WOLFSSL_ENTER("DoCertificateStatus"); + + if (size < ENUM_LEN + OPAQUE24_LEN) + return BUFFER_ERROR; + + status_type = input[(*inOutIdx)++]; + + c24to32(input + *inOutIdx, &status_length); + *inOutIdx += OPAQUE24_LEN; + + if (size != ENUM_LEN + OPAQUE24_LEN + status_length) + return BUFFER_ERROR; + + switch (status_type) { + + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + + /* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */ + case WOLFSSL_CSR2_OCSP: + ret = ProcessCSR(ssl, input, inOutIdx, status_length); + break; + + #endif + + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + + case WOLFSSL_CSR2_OCSP_MULTI: { + OcspRequest* request; + word32 list_length = status_length; + byte idx = 0; + + #ifdef WOLFSSL_SMALL_STACK + CertStatus* status; + OcspResponse* response; + #else + CertStatus status[1]; + OcspResponse response[1]; + #endif + + do { + if (ssl->status_request_v2) { + ssl->status_request_v2 = 0; + break; + } + + return BUFFER_ERROR; + } while(0); + + #ifdef WOLFSSL_SMALL_STACK + 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, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); + if (response) + XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + + return MEMORY_ERROR; + } + #endif + + while (list_length && ret == 0) { + if (OPAQUE24_LEN > list_length) { + ret = BUFFER_ERROR; + break; + } + + c24to32(input + *inOutIdx, &status_length); + *inOutIdx += OPAQUE24_LEN; + list_length -= OPAQUE24_LEN; + + if (status_length > list_length) { + ret = BUFFER_ERROR; + break; + } + + if (status_length) { + InitOcspResponse(response, status, input +*inOutIdx, + status_length); + + 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, idx++); + + if (request == NULL) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (CompareOcspReqResp(request, response) == 0) + break; + else if (idx == 1) /* server cert must be OK */ + ret = BAD_CERTIFICATE_STATUS_ERROR; + } + + *inOutIdx += status_length; + list_length -= status_length; + } + } + + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + ssl->status_request_v2 = 0; + #endif + + #ifdef WOLFSSL_SMALL_STACK + XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS); + XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + #endif + + } + break; + + #endif + + default: + ret = BUFFER_ERROR; + } + + if (ret != 0) + SendAlert(ssl, alert_fatal, bad_certificate_status_response); + + if (IsEncryptionOn(ssl, 0)) { + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + word32 digestSz = MacSize(ssl); + if (*inOutIdx + ssl->keys.padSz + digestSz > size) + return BUFFER_E; + *inOutIdx += ssl->keys.padSz + digestSz; + } + else + #endif + { + if (*inOutIdx + ssl->keys.padSz > size) + return BUFFER_E; + *inOutIdx += ssl->keys.padSz; + } + } + + WOLFSSL_LEAVE("DoCertificateStatus", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_DO); + + return ret; +} + +#endif + +#endif /* !WOLFSSL_NO_TLS12 */ + #endif /* !NO_CERTS */ +#ifndef WOLFSSL_NO_TLS12 static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, word32 totalSz) { (void)input; + WOLFSSL_START(WC_FUNC_HELLO_REQUEST_DO); + WOLFSSL_ENTER("DoHelloRequest"); + if (size) /* must be 0 */ return BUFFER_ERROR; - if (ssl->keys.encryptionOn) { - /* access beyond input + size should be checked against totalSz */ - if (*inOutIdx + ssl->keys.padSz > totalSz) - return BUFFER_E; + if (IsEncryptionOn(ssl, 0)) { + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + word32 digestSz = MacSize(ssl); + if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz) + return BUFFER_E; + *inOutIdx += ssl->keys.padSz + digestSz; + } + else + #endif + { + /* access beyond input + size should be checked against totalSz */ + if (*inOutIdx + ssl->keys.padSz > totalSz) + return BUFFER_E; - *inOutIdx += ssl->keys.padSz; + *inOutIdx += ssl->keys.padSz; + } } if (ssl->options.side == WOLFSSL_SERVER_END) { @@ -4471,6 +11829,8 @@ static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_SECURE_RENEGOTIATION else if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) { ssl->secure_renegotiation->startScr = 1; + WOLFSSL_LEAVE("DoHelloRequest", 0); + WOLFSSL_END(WC_FUNC_HELLO_REQUEST_DO); return 0; } #endif @@ -4485,21 +11845,36 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, { word32 finishedSz = (ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ); + WOLFSSL_START(WC_FUNC_FINISHED_DO); + WOLFSSL_ENTER("DoFinished"); + if (finishedSz != size) return BUFFER_ERROR; /* check against totalSz */ - if (*inOutIdx + size + ssl->keys.padSz > totalSz) - return BUFFER_E; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + if (*inOutIdx + size + ssl->keys.padSz + MacSize(ssl) > totalSz) + return BUFFER_E; + } + else + #endif + { + if (*inOutIdx + size + ssl->keys.padSz > totalSz) + return BUFFER_E; + } #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo); + if (ssl->hsInfoOn) AddPacketName(ssl, "Finished"); if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo); #endif if (sniff == NO_SNIFF) { if (XMEMCMP(input + *inOutIdx, &ssl->hsHashes->verifyHashes,size) != 0){ WOLFSSL_MSG("Verify finished error on hashes"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, decrypt_error); + #endif return VERIFY_FINISHED_ERROR; } } @@ -4513,42 +11888,57 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, else XMEMCPY(ssl->secure_renegotiation->client_verify_data, input + *inOutIdx, TLS_FINISHED_SZ); + ssl->secure_renegotiation->verifySet = 1; } #endif /* force input exhaustion at ProcessReply consuming padSz */ *inOutIdx += size + ssl->keys.padSz; +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + *inOutIdx += MacSize(ssl); +#endif if (ssl->options.side == WOLFSSL_CLIENT_END) { ssl->options.serverState = SERVER_FINISHED_COMPLETE; +#ifdef OPENSSL_EXTRA + ssl->cbmode = SSL_CB_MODE_WRITE; + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; +#endif if (!ssl->options.resuming) { - ssl->options.handShakeState = HANDSHAKE_DONE; - ssl->options.handShakeDone = 1; - -#ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - /* Other side has received our Finished, go to next epoch */ - ssl->keys.dtls_epoch++; - ssl->keys.dtls_sequence_number = 1; +#ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS); } #endif + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; } } else { ssl->options.clientState = CLIENT_FINISHED_COMPLETE; +#ifdef OPENSSL_EXTRA + ssl->cbmode = SSL_CB_MODE_READ; + ssl->options.serverState = SERVER_FINISHED_COMPLETE; +#endif if (ssl->options.resuming) { - ssl->options.handShakeState = HANDSHAKE_DONE; - ssl->options.handShakeDone = 1; - -#ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - /* Other side has received our Finished, go to next epoch */ - ssl->keys.dtls_epoch++; - ssl->keys.dtls_sequence_number = 1; +#ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS); } #endif + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; } } +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + DtlsMsgPoolReset(ssl); + } +#endif + + WOLFSSL_LEAVE("DoFinished", 0); + WOLFSSL_END(WC_FUNC_FINISHED_DO); return 0; } @@ -4575,6 +11965,9 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) case client_hello: if (ssl->msgsReceived.got_client_hello) { WOLFSSL_MSG("Duplicate ClientHello received"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); + #endif return DUPLICATE_MSG_E; } ssl->msgsReceived.got_client_hello = 1; @@ -4640,6 +12033,26 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) #endif break; +#ifndef NO_WOLFSSL_CLIENT + case certificate_status: + if (ssl->msgsReceived.got_certificate_status) { + WOLFSSL_MSG("Duplicate CertificateSatatus received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_status = 1; + + if (ssl->msgsReceived.got_certificate == 0) { + WOLFSSL_MSG("No Certificate before CertificateStatus"); + return OUT_OF_ORDER_E; + } + if (ssl->msgsReceived.got_server_key_exchange != 0) { + WOLFSSL_MSG("CertificateStatus after ServerKeyExchange"); + return OUT_OF_ORDER_E; + } + + break; +#endif + #ifndef NO_WOLFSSL_CLIENT case server_key_exchange: if (ssl->msgsReceived.got_server_key_exchange) { @@ -4648,10 +12061,30 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) } ssl->msgsReceived.got_server_key_exchange = 1; - if ( ssl->msgsReceived.got_server_hello == 0) { - WOLFSSL_MSG("No ServerHello before Cert"); + if (ssl->msgsReceived.got_server_hello == 0) { + WOLFSSL_MSG("No ServerHello before ServerKeyExchange"); return OUT_OF_ORDER_E; } + if (ssl->msgsReceived.got_certificate_status == 0) { +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) { + int ret; + + WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange"); + if ((ret = TLSX_CSR_ForceRequest(ssl)) != 0) + return ret; + } +#endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + int ret; + + WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange"); + if ((ret = TLSX_CSR2_ForceRequest(ssl)) != 0) + return ret; + } +#endif + } break; #endif @@ -4678,6 +12111,7 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) if (ssl->msgsReceived.got_certificate == 0) { if (ssl->specs.kea == psk_kea || ssl->specs.kea == dhe_psk_kea || + ssl->specs.kea == ecdhe_psk_kea || ssl->options.usingAnon_cipher) { WOLFSSL_MSG("No Cert required"); } else { @@ -4686,9 +12120,18 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) } } if (ssl->msgsReceived.got_server_key_exchange == 0) { + int pskNoServerHint = 0; /* not required in this case */ + + #ifndef NO_PSK + if (ssl->specs.kea == psk_kea && + ssl->arrays != NULL && + ssl->arrays->server_hint[0] == 0) + pskNoServerHint = 1; + #endif if (ssl->specs.static_ecdh == 1 || ssl->specs.kea == rsa_kea || - ssl->specs.kea == ntru_kea) { + ssl->specs.kea == ntru_kea || + pskNoServerHint) { WOLFSSL_MSG("No KeyExchange required"); } else { WOLFSSL_MSG("No ServerKeyExchange before ServerDone"); @@ -4717,6 +12160,9 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) case client_key_exchange: if (ssl->msgsReceived.got_client_key_exchange) { WOLFSSL_MSG("Duplicate ClientKeyExchange received"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); + #endif return DUPLICATE_MSG_E; } ssl->msgsReceived.got_client_key_exchange = 1; @@ -4737,25 +12183,50 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) if (ssl->msgsReceived.got_change_cipher == 0) { WOLFSSL_MSG("Finished received before ChangeCipher"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); + #endif return NO_CHANGE_CIPHER_E; } - break; case change_cipher_hs: if (ssl->msgsReceived.got_change_cipher) { WOLFSSL_MSG("Duplicate ChangeCipher received"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); + #endif return DUPLICATE_MSG_E; } - ssl->msgsReceived.got_change_cipher = 1; + /* DTLS is going to ignore the CCS message if the client key + * exchange message wasn't received yet. */ + if (!ssl->options.dtls) + ssl->msgsReceived.got_change_cipher = 1; #ifndef NO_WOLFSSL_CLIENT if (ssl->options.side == WOLFSSL_CLIENT_END) { - if (!ssl->options.resuming && - ssl->msgsReceived.got_server_hello_done == 0) { - WOLFSSL_MSG("No ServerHelloDone before ChangeCipher"); - return OUT_OF_ORDER_E; + if (!ssl->options.resuming) { + if (ssl->msgsReceived.got_server_hello_done == 0) { + WOLFSSL_MSG("No ServerHelloDone before ChangeCipher"); + return OUT_OF_ORDER_E; + } } + else { + if (ssl->msgsReceived.got_server_hello == 0) { + WOLFSSL_MSG("No ServerHello before ChangeCipher on Resume"); + return OUT_OF_ORDER_E; + } + } + #ifdef HAVE_SESSION_TICKET + if (ssl->expect_session_ticket) { + WOLFSSL_MSG("Expected session ticket missing"); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + return OUT_OF_ORDER_E; + #endif + return SESSION_TICKET_EXPECT_E; + } + #endif } #endif #ifndef NO_WOLFSSL_SERVER @@ -4763,11 +12234,29 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) if (!ssl->options.resuming && ssl->msgsReceived.got_client_key_exchange == 0) { WOLFSSL_MSG("No ClientKeyExchange before ChangeCipher"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); + #endif return OUT_OF_ORDER_E; } + #ifndef NO_CERTS + if (ssl->options.verifyPeer && + ssl->options.havePeerCert) { + + if (!ssl->options.havePeerVerify) { + WOLFSSL_MSG("client didn't send cert verify"); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + return OUT_OF_ORDER_E; + #endif + return NO_PEER_VERIFY; + } + } + #endif } #endif - + if (ssl->options.dtls) + ssl->msgsReceived.got_change_cipher = 1; break; default: @@ -4783,13 +12272,51 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, byte type, word32 size, word32 totalSz) { int ret = 0; - (void)totalSz; + word32 expectedIdx; 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) + if (*inOutIdx + size > totalSz) { + WOLFSSL_MSG("Incomplete Data"); return INCOMPLETE_DATA; + } + + expectedIdx = *inOutIdx + size + + (ssl->keys.encryptionOn ? ssl->keys.padSz : 0); +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead && ssl->keys.encryptionOn) + expectedIdx += MacSize(ssl); +#endif + +#if !defined(WOLFSSL_NO_SERVER) && \ + defined(HAVE_SECURE_RENEGOTIATION) && \ + defined(HAVE_SERVER_RENEGOTIATION_INFO) + if (ssl->options.handShakeDone && type == client_hello && + ssl->secure_renegotiation && + ssl->secure_renegotiation->enabled) + { + WOLFSSL_MSG("Reset handshake state"); + XMEMSET(&ssl->msgsReceived, 0, sizeof(MsgsReceived)); + ssl->options.serverState = NULL_STATE; + ssl->options.clientState = NULL_STATE; + ssl->options.connectState = CONNECT_BEGIN; + ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; + ssl->options.handShakeState = NULL_STATE; + ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; + + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + } +#endif /* sanity check msg received */ if ( (ret = SanityCheckMsgReceived(ssl, type)) != 0) { @@ -4797,13 +12324,15 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, return ret; } -#ifdef WOLFSSL_CALLBACKS +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) /* 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); + AddPacketInfo(ssl, 0, handshake, input + *inOutIdx - add, + size + add, READ_PROTO, ssl->heap); + #ifdef WOLFSSL_CALLBACKS AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); + #endif } #endif @@ -4837,11 +12366,32 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* above checks handshake state */ /* hello_request not hashed */ - if (type != hello_request) { + /* Also, skip hashing the client_hello message here for DTLS. It will be + * hashed later if the DTLS cookie is correct. */ + if (type != hello_request && + !(IsDtlsNotSctpMode(ssl) && type == client_hello) + #ifdef WOLFSSL_ASYNC_CRYPT + && ssl->error != WC_PENDING_E + #endif + #ifdef WOLFSSL_NONBLOCK_OCSP + && ssl->error != OCSP_WANT_READ + #endif + ) { ret = HashInput(ssl, input + *inOutIdx, size); - if (ret != 0) return ret; + if (ret != 0) { + WOLFSSL_MSG("Incomplete handshake hashes"); + return ret; + } } +#ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL){ + ssl->cbmode = SSL_CB_MODE_READ; + ssl->cbtype = type; + ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS); + } +#endif + switch (type) { case hello_request: @@ -4858,6 +12408,25 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, case server_hello: WOLFSSL_MSG("processing server hello"); ret = DoServerHello(ssl, input, inOutIdx, size); + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ + ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ + (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) + if (ssl->options.resuming || !IsAtLeastTLSv1_2(ssl) || + IsAtLeastTLSv1_3(ssl->version)) { + + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) + if (ret != WC_PENDING_E && ret != OCSP_WANT_READ) + #endif + { + ssl->options.cacheMessages = 0; + if (ssl->hsHashes->messages != NULL) { + XFREE(ssl->hsHashes->messages, ssl->heap, + DYNAMIC_TYPE_HASHES); + ssl->hsHashes->messages = NULL; + } + } + } + #endif break; #ifndef NO_CERTS @@ -4880,24 +12449,34 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif /* HAVE_SESSION_TICKET */ #endif -#ifndef NO_CERTS +#if !defined(NO_CERTS) && (!defined(NO_WOLFSSL_CLIENT) || \ + !defined(WOLFSSL_NO_CLIENT_AUTH)) case certificate: WOLFSSL_MSG("processing certificate"); - ret = DoCertificate(ssl, input, inOutIdx, size); + ret = DoCertificate(ssl, input, inOutIdx, size); + break; + + case certificate_status: + WOLFSSL_MSG("processing certificate status"); + ret = DoCertificateStatus(ssl, input, inOutIdx, size); break; #endif 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(ssl, "ServerHelloDone"); + if (ssl->toInfoOn) + AddLateName("ServerHelloDone", &ssl->timeoutInfo); + #endif ssl->options.serverState = SERVER_HELLODONE_COMPLETE; - if (ssl->keys.encryptionOn) { + if (IsEncryptionOn(ssl, 0)) { *inOutIdx += ssl->keys.padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + *inOutIdx += MacSize(ssl); + #endif } if (ssl->options.resuming) { WOLFSSL_MSG("Not resuming as thought"); @@ -4914,6 +12493,42 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, case client_hello: WOLFSSL_MSG("processing client hello"); ret = DoClientHello(ssl, input, inOutIdx, size); + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ + ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ + (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) + if (ssl->options.resuming || !ssl->options.verifyPeer || \ + !IsAtLeastTLSv1_2(ssl) || IsAtLeastTLSv1_3(ssl->version)) { + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) + if (ret != WC_PENDING_E && ret != OCSP_WANT_READ) + #endif + { + ssl->options.cacheMessages = 0; + if (ssl->hsHashes->messages != NULL) { + XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes->messages = NULL; + } + } + } + #endif + if (IsEncryptionOn(ssl, 0)) { + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + word32 digestSz = MacSize(ssl); + if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz) + return BUFFER_E; + *inOutIdx += ssl->keys.padSz + digestSz; + } + else + #endif + { + /* access beyond input + size should be checked against totalSz + */ + if (*inOutIdx + ssl->keys.padSz > totalSz) + return BUFFER_E; + + *inOutIdx += ssl->keys.padSz; + } + } break; case client_key_exchange: @@ -4921,12 +12536,13 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = DoClientKeyExchange(ssl, input, inOutIdx, size); break; -#if !defined(NO_RSA) || defined(HAVE_ECC) +#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_ED448)) && !defined(WOLFSSL_NO_CLIENT_AUTH) case certificate_verify: WOLFSSL_MSG("processing certificate verify"); ret = DoCertificateVerify(ssl, input, inOutIdx, size); break; -#endif /* !NO_RSA || HAVE_ECC */ +#endif /* (!NO_RSA || ECC || ED25519 || ED448) && !WOLFSSL_NO_CLIENT_AUTH */ #endif /* !NO_WOLFSSL_SERVER */ @@ -4935,6 +12551,38 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = UNKNOWN_HANDSHAKE_TYPE; break; } + if (ret == 0 && expectedIdx != *inOutIdx) { + WOLFSSL_MSG("Extra data in handshake message"); + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, decode_error); + ret = DECODE_E; + } + + if (ret == 0 && ssl->buffers.inputBuffer.dynamicFlag + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) + /* do not shrink input for async or non-block */ + && ssl->error != WC_PENDING_E && ssl->error != OCSP_WANT_READ + #endif + ) { + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + } + +#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 || ret == OCSP_WANT_READ) && *inOutIdx > 0) { + *inOutIdx -= HANDSHAKE_HEADER_SZ; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + *inOutIdx -= DTLS_HANDSHAKE_EXTRA; + } + #endif + } + + /* make sure async error is cleared */ + if (ret == 0 && (ssl->error == WC_PENDING_E || ssl->error == OCSP_WANT_READ)) { + ssl->error = 0; + } +#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */ WOLFSSL_LEAVE("DoHandShakeMsgType()", ret); return ret; @@ -4944,79 +12592,335 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz) { - byte type; - word32 size; int ret = 0; + word32 inputLength; WOLFSSL_ENTER("DoHandShakeMsg()"); - if (GetHandShakeHeader(ssl, input, inOutIdx, &type, &size, totalSz) != 0) - return PARSE_ERROR; + if (ssl->arrays == NULL) { + byte type; + word32 size; - ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); + if (GetHandShakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0) + return PARSE_ERROR; + + ssl->options.handShakeState = type; + + return DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); + } + + inputLength = ssl->buffers.inputBuffer.length - *inOutIdx; + + /* 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 - HANDSHAKE_HEADER_SZ; + return 0; + } + + ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); + } + else { + word32 pendSz = + ssl->arrays->pendingMsgSz - ssl->arrays->pendingMsgOffset; + + /* Catch the case where there may be the remainder of a fragmented + * handshake message and the next handshake message in the same + * record. */ + if (inputLength > pendSz) + inputLength = pendSz; + + XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset, + input + *inOutIdx, inputLength); + ssl->arrays->pendingMsgOffset += inputLength; + *inOutIdx += inputLength; + + if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz) + { + word32 idx = HANDSHAKE_HEADER_SZ; + ret = DoHandShakeMsgType(ssl, + ssl->arrays->pendingMsg, + &idx, ssl->arrays->pendingMsgType, + ssl->arrays->pendingMsgSz - idx, + ssl->arrays->pendingMsgSz); + #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; + } + } + } WOLFSSL_LEAVE("DoHandShakeMsg()", ret); return ret; } +#endif /* !WOLFSSL_NO_TLS12 */ #ifdef WOLFSSL_DTLS -static INLINE int DtlsCheckWindow(DtlsState* state) +static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl) { - word32 cur; - word32 next; - DtlsSeq window; + word32* window; + word16 cur_hi, next_hi; + word32 cur_lo, next_lo, diff; + int curLT; + WOLFSSL_DTLS_PEERSEQ* peerSeq = NULL; - if (state->curEpoch == state->nextEpoch) { - next = state->nextSeq; - window = state->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 (state->curEpoch < state->nextEpoch) { - next = state->prevSeq; - window = state->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; } - cur = state->curSeq; + cur_hi = ssl->keys.curSeq_hi; + cur_lo = ssl->keys.curSeq_lo; - if ((next > DTLS_SEQ_BITS) && (cur < next - DTLS_SEQ_BITS)) { + /* If the difference between next and cur is > 2^32, way outside window. */ + if ((cur_hi > next_hi + 1) || (next_hi > cur_hi + 1)) { + WOLFSSL_MSG("Current record from way too far in the future."); return 0; } - else if ((cur < next) && (window & ((DtlsSeq)1 << (next - cur - 1)))) { + + if (cur_hi == next_hi) { + curLT = cur_lo < next_lo; + diff = curLT ? next_lo - cur_lo : cur_lo - next_lo; + } + else { + curLT = cur_hi < next_hi; + diff = curLT ? cur_lo - next_lo : next_lo - cur_lo; + } + + /* Check to see that the next value is greater than the number of messages + * trackable in the window, and that the difference between the next + * expected sequence number and the received sequence number is inside the + * window. */ + if ((next_hi || next_lo > DTLS_SEQ_BITS) && + curLT && (diff > DTLS_SEQ_BITS)) { + + 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)) { + WOLFSSL_MSG("Current record sequence number already received."); + return 0; + } + } return 1; } -static INLINE int DtlsUpdateWindow(DtlsState* state) +#ifdef WOLFSSL_MULTICAST +static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first, + word32 second, word32 max) { - word32 cur; - word32* next; - DtlsSeq* window; + word32 newCur = 0; - if (state->curEpoch == state->nextEpoch) { - next = &state->nextSeq; - window = &state->window; + if (cur < first) + newCur = first; + else if (cur < second) + newCur = second; + else if (cur < max) + newCur = max; + + return newCur; +} +#endif /* WOLFSSL_MULTICAST */ + + +static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl) +{ + word32* window; + word32* next_lo; + word16* next_hi; + int curLT; + word32 cur_lo, diff; + word16 cur_hi; + 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 = &state->prevSeq; - window = &state->prevWindow; + next_hi = &peerSeq->prevSeq_hi; + next_lo = &peerSeq->prevSeq_lo; + window = peerSeq->prevWindow; } - cur = state->curSeq; - - if (cur < *next) { - *window |= ((DtlsSeq)1 << (*next - cur - 1)); + if (cur_hi == *next_hi) { + curLT = cur_lo < *next_lo; + diff = curLT ? *next_lo - cur_lo : cur_lo - *next_lo; } else { - *window <<= (1 + cur - *next); - *window |= 1; - *next = cur + 1; + curLT = cur_hi < *next_hi; + diff = curLT ? cur_lo - *next_lo : *next_lo - cur_lo; + } + + if (curLT) { + word32 idx = diff / DTLS_WORD_BITS; + word32 newDiff = diff % DTLS_WORD_BITS; + + if (idx < WOLFSSL_DTLS_WINDOW_WORDS) + window[idx] |= (1 << newDiff); + } + else { + if (diff >= DTLS_SEQ_BITS) + XMEMSET(window, 0, DTLS_SEQ_SZ); + else { + word32 idx, newDiff, temp, i; + word32 oldWindow[WOLFSSL_DTLS_WINDOW_WORDS]; + + temp = 0; + diff++; + idx = diff / DTLS_WORD_BITS; + newDiff = diff % DTLS_WORD_BITS; + + XMEMCPY(oldWindow, window, sizeof(oldWindow)); + + for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) { + if (i < idx) + window[i] = 0; + else { + temp |= (oldWindow[i-idx] << newDiff); + window[i] = temp; + temp = oldWindow[i-idx] >> (DTLS_WORD_BITS - newDiff - 1); + } + } + } + window[0] |= 1; + *next_lo = cur_lo + 1; + if (*next_lo < cur_lo) + (*next_hi)++; } return 1; @@ -5025,12 +12929,14 @@ static INLINE int DtlsUpdateWindow(DtlsState* state) static int DtlsMsgDrain(WOLFSSL* ssl) { - DtlsMsg* item = ssl->dtls_msg_list; + DtlsMsg* item = ssl->dtls_rx_msg_list; int ret = 0; + WOLFSSL_ENTER("DtlsMsgDrain()"); + /* While there is an item in the store list, and it is the expected * message, and it is complete, and there hasn't been an error in the - * last messge... */ + * last message... */ while (item != NULL && ssl->keys.dtls_expected_peer_handshake_number == item->seq && item->fragSz == item->sz && @@ -5039,11 +12945,19 @@ static int DtlsMsgDrain(WOLFSSL* ssl) ssl->keys.dtls_expected_peer_handshake_number++; ret = DoHandShakeMsgType(ssl, item->msg, &idx, item->type, item->sz, item->sz); - ssl->dtls_msg_list = item->next; + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ssl->keys.dtls_expected_peer_handshake_number--; + break; + } + #endif + ssl->dtls_rx_msg_list = item->next; DtlsMsgDelete(item, ssl->heap); - item = ssl->dtls_msg_list; + item = ssl->dtls_rx_msg_list; + ssl->dtls_rx_msg_list_sz--; } + WOLFSSL_LEAVE("DtlsMsgDrain()", ret); return ret; } @@ -5057,12 +12971,38 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, int ret = 0; WOLFSSL_ENTER("DoDtlsHandShakeMsg()"); - if (GetDtlsHandShakeHeader(ssl, input, inOutIdx, &type, - &size, &fragOffset, &fragSz, totalSz) != 0) - return PARSE_ERROR; - if (*inOutIdx + fragSz > totalSz) + /* 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) { + WOLFSSL_ERROR(PARSE_ERROR); + 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; + } + + /* check that we have complete fragment */ + if (*inOutIdx + fragSz > totalSz) { + WOLFSSL_ERROR(INCOMPLETE_DATA); return INCOMPLETE_DATA; + } /* Check the handshake sequence number first. If out of order, * add the current message to the list. If the message is in order, @@ -5076,38 +13016,84 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ssl->keys.dtls_peer_handshake_number > ssl->keys.dtls_expected_peer_handshake_number) { /* Current message is out of order. It will get stored in the list. - * Storing also takes care of defragmentation. */ - ssl->dtls_msg_list = DtlsMsgStore(ssl->dtls_msg_list, - ssl->keys.dtls_peer_handshake_number, input + *inOutIdx, - size, type, fragOffset, fragSz, ssl->heap); - *inOutIdx += fragSz; - ret = 0; + * Storing also takes care of defragmentation. If the messages is a + * client hello, we need to process this out of order; the server + * is not supposed to keep state, but the second client hello will + * have a different handshake sequence number than is expected, and + * the server shouldn't be expecting any particular handshake sequence + * number. (If the cookie changes multiple times in quick succession, + * the client could be sending multiple new client hello messages + * with newer and newer cookies.) */ + if (type != client_hello) { + if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) { + DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number, + input + *inOutIdx, size, type, + fragOffset, fragSz, ssl->heap); + } + *inOutIdx += fragSz; + ret = 0; + } + else { + ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); + if (ret == 0) { + ssl->keys.dtls_expected_peer_handshake_number = + ssl->keys.dtls_peer_handshake_number + 1; + } + } } else if (ssl->keys.dtls_peer_handshake_number < ssl->keys.dtls_expected_peer_handshake_number) { /* Already saw this message and processed it. It can be ignored. */ *inOutIdx += fragSz; - ret = 0; + if(type == finished ) { + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + word32 digestSz = MacSize(ssl); + if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz) + return BUFFER_E; + *inOutIdx += ssl->keys.padSz + digestSz; + } + else + #endif + { + if (*inOutIdx + ssl->keys.padSz > totalSz) { + WOLFSSL_ERROR(BUFFER_E); + return BUFFER_E; + } + *inOutIdx += ssl->keys.padSz; + } + } + if (IsDtlsNotSctpMode(ssl) && + VerifyForDtlsMsgPoolSend(ssl, type, fragOffset)) { + + ret = DtlsMsgPoolSend(ssl, 0); + } } else if (fragSz < size) { - /* Since this branch is in order, but fragmented, dtls_msg_list will be - * pointing to the message with this fragment in it. Check it to see + /* Since this branch is in order, but fragmented, dtls_rx_msg_list will + * be pointing to the message with this fragment in it. Check it to see * if it is completed. */ - ssl->dtls_msg_list = DtlsMsgStore(ssl->dtls_msg_list, - ssl->keys.dtls_peer_handshake_number, input + *inOutIdx, - size, type, fragOffset, fragSz, ssl->heap); + if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) { + DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number, + input + *inOutIdx, size, type, + fragOffset, fragSz, ssl->heap); + } *inOutIdx += fragSz; ret = 0; - if (ssl->dtls_msg_list != NULL && - ssl->dtls_msg_list->fragSz >= ssl->dtls_msg_list->sz) + if (ssl->dtls_rx_msg_list != NULL && + ssl->dtls_rx_msg_list->fragSz >= ssl->dtls_rx_msg_list->sz) ret = DtlsMsgDrain(ssl); } else { /* This branch is in order next, and a complete message. */ - ssl->keys.dtls_expected_peer_handshake_number++; ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); - if (ret == 0 && ssl->dtls_msg_list != NULL) - ret = DtlsMsgDrain(ssl); + if (ret == 0) { + if (type != client_hello || !IsDtlsNotSctpMode(ssl)) + ssl->keys.dtls_expected_peer_handshake_number++; + if (ssl->dtls_rx_msg_list != NULL) { + ret = DtlsMsgDrain(ssl); + } + } } WOLFSSL_LEAVE("DoDtlsHandShakeMsg()", ret); @@ -5115,97 +13101,25 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, } #endif - -#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \ - || defined(HAVE_AESGCM) -static INLINE word32 GetSEQIncrement(WOLFSSL* ssl, int verify) -{ -#ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if (verify) - return ssl->keys.dtls_state.curSeq; /* explicit from peer */ - else - return ssl->keys.dtls_sequence_number - 1; /* already incremented */ - } -#endif - if (verify) - return ssl->keys.peer_sequence_number++; - else - return ssl->keys.sequence_number++; -} -#endif - +#ifndef WOLFSSL_NO_TLS12 #ifdef HAVE_AEAD -static INLINE void AeadIncrementExpIV(WOLFSSL* ssl) + +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + (((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) || \ + (defined(HAVE_POLY1305) && defined(HAVE_CHACHA))) +static WC_INLINE void AeadIncrementExpIV(WOLFSSL* ssl) { int i; - for (i = AEAD_EXP_IV_SZ-1; i >= 0; i--) { + for (i = AEAD_MAX_EXP_SZ-1; i >= 0; i--) { if (++ssl->keys.aead_exp_IV[i]) return; } } +#endif #if defined(HAVE_POLY1305) && defined(HAVE_CHACHA) -/*more recent rfc's concatonate input for poly1305 differently*/ -static int Poly1305Tag(WOLFSSL* ssl, byte* additional, const byte* out, - byte* cipher, word16 sz, byte* tag) -{ - int ret = 0; - int paddingSz = 0; - int msglen = (sz - ssl->specs.aead_mac_size); - word32 keySz = 32; - int blockSz = 16; - byte padding[16]; - - if (msglen < 0) - return INPUT_CASE_ERROR; - - XMEMSET(padding, 0, sizeof(padding)); - - if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, cipher, keySz)) != 0) - return ret; - - /* additional input to poly1305 */ - if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional, blockSz)) != 0) - return ret; - - /* cipher input */ - if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, msglen)) != 0) - return ret; - - /* handle padding for cipher input to make it 16 bytes long */ - if (msglen % 16 != 0) { - paddingSz = (16 - (sz - ssl->specs.aead_mac_size) % 16); - if (paddingSz < 0) - return INPUT_CASE_ERROR; - - if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, paddingSz)) - != 0) - return ret; - } - - /* add size of AD and size of cipher to poly input */ - XMEMSET(padding, 0, sizeof(padding)); - padding[0] = blockSz; - - /* 32 bit size of cipher to 64 bit endian */ - padding[8] = msglen & 0xff; - padding[9] = (msglen >> 8) & 0xff; - padding[10] = (msglen >>16) & 0xff; - padding[11] = (msglen >>24) & 0xff; - if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, sizeof(padding))) - != 0) - return ret; - - /* generate tag */ - if ((ret = wc_Poly1305Final(ssl->auth.poly1305, tag)) != 0) - return ret; - - return ret; -} - - /* Used for the older version of creating AEAD tags with Poly1305 */ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out, byte* cipher, word16 sz, byte* tag) @@ -5213,7 +13127,7 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out, int ret = 0; int msglen = (sz - ssl->specs.aead_mac_size); word32 keySz = 32; - byte padding[8]; /* used to temporarly store lengths */ + byte padding[8]; /* used to temporarily store lengths */ #ifdef CHACHA_AEAD_TEST printf("Using old version of poly1305 input.\n"); @@ -5225,9 +13139,6 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out, if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, cipher, keySz)) != 0) return ret; - /* add TLS compressed length and additional input to poly1305 */ - additional[AEAD_AUTH_DATA_SZ - 2] = (msglen >> 8) & 0xff; - additional[AEAD_AUTH_DATA_SZ - 1] = msglen & 0xff; if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional, AEAD_AUTH_DATA_SZ)) != 0) return ret; @@ -5248,8 +13159,8 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out, /* 32 bit size of cipher to 64 bit endian */ padding[0] = msglen & 0xff; padding[1] = (msglen >> 8) & 0xff; - padding[2] = (msglen >> 16) & 0xff; - padding[3] = (msglen >> 24) & 0xff; + padding[2] = ((word32)msglen >> 16) & 0xff; + padding[3] = ((word32)msglen >> 24) & 0xff; if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, sizeof(padding))) != 0) return ret; @@ -5262,46 +13173,65 @@ 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 implementation follows an older draft for creating the nonce and MAC. + * The flag oldPoly gets set automatically 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 comparison 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) { const byte* additionalSrc = input - RECORD_HEADER_SZ; - int ret = 0; + int ret = 0; + word32 msgLen = (sz - ssl->specs.aead_mac_size); byte tag[POLY1305_AUTH_SZ]; - byte additional[CHACHA20_BLOCK_SIZE]; - byte nonce[AEAD_NONCE_SZ]; - byte cipher[CHACHA20_256_KEY_SIZE]; /* generated key for poly1305 */ + byte add[AEAD_AUTH_DATA_SZ]; + byte nonce[CHACHA20_NONCE_SZ]; + byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for poly1305 */ #ifdef CHACHA_AEAD_TEST int i; #endif - XMEMSET(tag, 0, sizeof(tag)); - XMEMSET(nonce, 0, AEAD_NONCE_SZ); - XMEMSET(cipher, 0, sizeof(cipher)); - XMEMSET(additional, 0, CHACHA20_BLOCK_SIZE); - - /* get nonce */ - c32toa(ssl->keys.sequence_number, nonce + AEAD_IMP_IV_SZ - + AEAD_SEQ_OFFSET); + XMEMSET(tag, 0, sizeof(tag)); + XMEMSET(nonce, 0, sizeof(nonce)); + XMEMSET(poly, 0, sizeof(poly)); + XMEMSET(add, 0, sizeof(add)); /* opaque SEQ number stored for AD */ - c32toa(GetSEQIncrement(ssl, 0), additional + AEAD_SEQ_OFFSET); + 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 if (ssl->options.dtls) { - c16toa(ssl->keys.dtls_epoch, additional); additionalSrc -= DTLS_HANDSHAKE_EXTRA; } #endif - XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3); + /* add TLS message size to additional data */ + add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff; + add[AEAD_AUTH_DATA_SZ - 1] = msgLen & 0xff; + + XMEMCPY(add + AEAD_TYPE_OFFSET, additionalSrc, 3); #ifdef CHACHA_AEAD_TEST printf("Encrypt Additional : "); - for (i = 0; i < CHACHA20_BLOCK_SIZE; i++) { - printf("%02x", additional[i]); + for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) { + printf("%02x", add[i]); } printf("\n\n"); printf("input before encryption :\n"); @@ -5313,36 +13243,73 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, printf("\n"); #endif - /* set the nonce for chacha and get poly1305 key */ - if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0)) != 0) - return ret; + if (ssl->options.oldPoly == 0) { + /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte + * record sequence number XORed with client_write_IV/server_write_IV */ + XMEMCPY(nonce, ssl->keys.aead_enc_imp_IV, CHACHA20_IMP_IV_SZ); + nonce[4] ^= add[0]; + nonce[5] ^= add[1]; + nonce[6] ^= add[2]; + nonce[7] ^= add[3]; + nonce[8] ^= add[4]; + nonce[9] ^= add[5]; + nonce[10] ^= add[6]; + nonce[11] ^= add[7]; + } - if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, cipher, - cipher, sizeof(cipher))) != 0) + /* set the nonce for chacha and get poly1305 key */ + if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0)) != 0) { + ForceZero(nonce, CHACHA20_NONCE_SZ); return ret; + } + + /* create Poly1305 key using chacha20 keystream */ + if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, poly, + poly, sizeof(poly))) != 0) { + ForceZero(nonce, CHACHA20_NONCE_SZ); + return ret; + } + + /* set the counter after getting poly1305 key */ + if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 1)) != 0) { + ForceZero(nonce, CHACHA20_NONCE_SZ); + return ret; + } + ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */ /* encrypt the plain text */ - if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, out, input, - sz - ssl->specs.aead_mac_size)) != 0) + if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, out, + input, msgLen)) != 0) { + ForceZero(poly, sizeof(poly)); return ret; + } - /* get the tag : future use of hmac could go here*/ - if (ssl->options.oldPoly == 1) { - if ((ret = Poly1305TagOld(ssl, additional, (const byte* )out, - cipher, sz, tag)) != 0) + /* get the poly1305 tag using either old padding scheme or more recent */ + if (ssl->options.oldPoly != 0) { + if ((ret = Poly1305TagOld(ssl, add, (const byte* )out, + poly, sz, tag)) != 0) { + ForceZero(poly, sizeof(poly)); return ret; + } } else { - if ((ret = Poly1305Tag(ssl, additional, (const byte* )out, - cipher, sz, tag)) != 0) + if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, + sizeof(poly))) != 0) { + ForceZero(poly, sizeof(poly)); return ret; + } + if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add, + sizeof(add), out, msgLen, tag, sizeof(tag))) != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } } + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ /* append tag to ciphertext */ - XMEMCPY(out + sz - ssl->specs.aead_mac_size, tag, sizeof(tag)); + XMEMCPY(out + msgLen, tag, sizeof(tag)); AeadIncrementExpIV(ssl); - ForceZero(nonce, AEAD_NONCE_SZ); #ifdef CHACHA_AEAD_TEST printf("mac tag :\n"); @@ -5364,19 +13331,29 @@ 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 implementation follows an older draft for creating the nonce and MAC. + * The flag oldPoly gets set automatically 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 comparison 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) { - byte additional[CHACHA20_BLOCK_SIZE]; - byte nonce[AEAD_NONCE_SZ]; + byte add[AEAD_AUTH_DATA_SZ]; + byte nonce[CHACHA20_NONCE_SZ]; byte tag[POLY1305_AUTH_SZ]; - byte cipher[CHACHA20_256_KEY_SIZE]; /* generated key for mac */ - int ret = 0; - - XMEMSET(tag, 0, sizeof(tag)); - XMEMSET(cipher, 0, sizeof(cipher)); - XMEMSET(nonce, 0, AEAD_NONCE_SZ); - XMEMSET(additional, 0, CHACHA20_BLOCK_SIZE); + byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */ + int ret = 0; + int msgLen = (sz - ssl->specs.aead_mac_size); #ifdef CHACHA_AEAD_TEST int i; @@ -5389,64 +13366,103 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, printf("\n"); #endif - /* get nonce */ - c32toa(ssl->keys.peer_sequence_number, nonce + AEAD_IMP_IV_SZ - + AEAD_SEQ_OFFSET); + XMEMSET(tag, 0, sizeof(tag)); + XMEMSET(poly, 0, sizeof(poly)); + XMEMSET(nonce, 0, sizeof(nonce)); + XMEMSET(add, 0, sizeof(add)); - /* sequence number field is 64-bits, we only use 32-bits */ - c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_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 */ - additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; - additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; - additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; - /* Store the type, version. */ - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - c16toa(ssl->keys.dtls_state.curEpoch, additional); - #endif + add[AEAD_TYPE_OFFSET] = ssl->curRL.type; + add[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; + add[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; + + /* add TLS message size to additional data */ + add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff; + add[AEAD_AUTH_DATA_SZ - 1] = msgLen & 0xff; #ifdef CHACHA_AEAD_TEST printf("Decrypt Additional : "); - for (i = 0; i < CHACHA20_BLOCK_SIZE; i++) { - printf("%02x", additional[i]); + for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) { + printf("%02x", add[i]); } printf("\n\n"); #endif + if (ssl->options.oldPoly == 0) { + /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte + * record sequence number XORed with client_write_IV/server_write_IV */ + XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, CHACHA20_IMP_IV_SZ); + nonce[4] ^= add[0]; + nonce[5] ^= add[1]; + nonce[6] ^= add[2]; + nonce[7] ^= add[3]; + nonce[8] ^= add[4]; + nonce[9] ^= add[5]; + nonce[10] ^= add[6]; + nonce[11] ^= add[7]; + } + /* set nonce and get poly1305 key */ - if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0)) != 0) + if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0)) != 0) { + ForceZero(nonce, CHACHA20_NONCE_SZ); return ret; + } - if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, cipher, - cipher, sizeof(cipher))) != 0) + /* use chacha20 keystream to get poly1305 key for tag */ + if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, poly, + poly, sizeof(poly))) != 0) { + ForceZero(nonce, CHACHA20_NONCE_SZ); return ret; + } - /* get the tag : future use of hmac could go here*/ - if (ssl->options.oldPoly == 1) { - if ((ret = Poly1305TagOld(ssl, additional, input, cipher, - sz, tag)) != 0) + /* set counter after getting poly1305 key */ + if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 1)) != 0) { + ForceZero(nonce, CHACHA20_NONCE_SZ); + return ret; + } + ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */ + + /* get the tag using Poly1305 */ + if (ssl->options.oldPoly != 0) { + if ((ret = Poly1305TagOld(ssl, add, input, poly, sz, tag)) != 0) { + ForceZero(poly, sizeof(poly)); return ret; + } } else { - if ((ret = Poly1305Tag(ssl, additional, input, cipher, - sz, tag)) != 0) + if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, + sizeof(poly))) != 0) { + ForceZero(poly, sizeof(poly)); return ret; + } + if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add, + sizeof(add), (byte*)input, msgLen, tag, sizeof(tag))) != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } } + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ - /* check mac sent along with packet */ - if (ConstantCompare(input + sz - ssl->specs.aead_mac_size, tag, - ssl->specs.aead_mac_size) != 0) { - WOLFSSL_MSG("Mac did not match"); - SendAlert(ssl, alert_fatal, bad_record_mac); - ForceZero(nonce, AEAD_NONCE_SZ); + /* check tag sent along with packet */ + if (ConstantCompare(input + msgLen, tag, ssl->specs.aead_mac_size) != 0) { + WOLFSSL_MSG("MAC did not match"); + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, bad_record_mac); return VERIFY_MAC_ERROR; } - /* if mac was good decrypt message */ - if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain, input, - sz - ssl->specs.aead_mac_size)) != 0) + /* if the tag was good decrypt message */ + if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain, + input, msgLen)) != 0) return ret; #ifdef CHACHA_AEAD_TEST @@ -5465,175 +13481,313 @@ 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) +#if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + +#if !defined(NO_GCM_ENCRYPT_EXTRA) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) +/* The following type is used to share code between AES-GCM and AES-CCM. */ + typedef int (*AesAuthEncryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + #define AES_AUTH_ENCRYPT_FUNC AesAuthEncryptFunc + #define AES_GCM_ENCRYPT wc_AesGcmEncrypt_ex + #define AES_CCM_ENCRYPT wc_AesCcmEncrypt_ex +#else + #define AES_AUTH_ENCRYPT_FUNC wc_AesAuthEncryptFunc + #define AES_GCM_ENCRYPT wc_AesGcmEncrypt + #define AES_CCM_ENCRYPT wc_AesCcmEncrypt +#endif + +#endif + + +static WC_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; + switch (ssl->specs.bulk_cipher_algorithm) { + #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 + /* initialize event */ + asyncDev = &ssl->encrypt.des3->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) + break; + #endif + + 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 + + #if defined(BUILD_AES) && defined(HAVE_AES_CBC) + case wolfssl_aes: + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + asyncDev = &ssl->encrypt.aes->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) + break; + #endif + #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + if (tsip_useable(ssl)) { + ret = wc_tsip_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz); + } else + #endif + 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 */ + { + AES_AUTH_ENCRYPT_FUNC aes_auth_fn; + const byte* additionalSrc; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + asyncDev = &ssl->encrypt.aes->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) + break; + #endif + + #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM) + aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + ? AES_GCM_ENCRYPT : AES_CCM_ENCRYPT; + #elif defined(BUILD_AESGCM) + aes_auth_fn = AES_GCM_ENCRYPT; + #else + aes_auth_fn = AES_CCM_ENCRYPT; + #endif + additionalSrc = input - 5; + + XMEMSET(ssl->encrypt.additional, 0, AEAD_AUTH_DATA_SZ); + + /* sequence number field is 64-bits */ + WriteSEQ(ssl, CUR_ORDER, ssl->encrypt.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(ssl->encrypt.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, + ssl->encrypt.additional + AEAD_LEN_OFFSET); +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) + 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); +#endif + 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 +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + XMEMCPY(out, + ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, AESGCM_EXP_IV_SZ); +#endif + } + break; + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + + #ifdef HAVE_CAMELLIA + case wolfssl_camellia: + ret = wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz); + break; + #endif + + #ifdef HAVE_HC128 + case wolfssl_hc128: + ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz); + break; + #endif + + #ifdef BUILD_RABBIT + case wolfssl_rabbit: + ret = wc_RabbitProcess(ssl->encrypt.rabbit, 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_NULL_CIPHER + case wolfssl_cipher_null: + if (input != out) { + XMEMMOVE(out, input, sz); + } + break; + #endif + + #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 HAVE_FUZZER - if (ssl->fuzzerCb) - ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx); +#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 - switch (ssl->specs.bulk_cipher_algorithm) { - #ifdef BUILD_ARC4 - case wolfssl_rc4: - wc_Arc4Process(ssl->encrypt.arc4, out, input, sz); - break; - #endif + return ret; +} - #ifdef BUILD_DES3 - case wolfssl_triple_des: - ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz); - break; - #endif +static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz, + int asyncOkay) +{ + int ret = 0; - #ifdef BUILD_AES - case wolfssl_aes: - ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz); - break; - #endif - - #ifdef BUILD_AESGCM - case wolfssl_aes_gcm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AEAD_NONCE_SZ]; - const byte* additionalSrc = input - 5; - - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); - - /* sequence number field is 64-bits, we only use 32-bits */ - c32toa(GetSEQIncrement(ssl, 0), - additional + AEAD_SEQ_OFFSET); - - /* Store the type, version. Unfortunately, they are in - * the input buffer ahead of the plaintext. */ - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - c16toa(ssl->keys.dtls_epoch, additional); - 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 - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, - ssl->keys.aead_enc_imp_IV, AEAD_IMP_IV_SZ); - XMEMCPY(nonce + AEAD_IMP_IV_SZ, - ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ); - ret = wc_AesGcmEncrypt(ssl->encrypt.aes, - out + AEAD_EXP_IV_SZ, input + AEAD_EXP_IV_SZ, - sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AEAD_NONCE_SZ, - out + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ); - if (ret == 0) - AeadIncrementExpIV(ssl); - ForceZero(nonce, AEAD_NONCE_SZ); - } - break; - #endif - - #ifdef HAVE_AESCCM - case wolfssl_aes_ccm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AEAD_NONCE_SZ]; - const byte* additionalSrc = input - 5; - - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); - - /* sequence number field is 64-bits, we only use 32-bits */ - c32toa(GetSEQIncrement(ssl, 0), - additional + AEAD_SEQ_OFFSET); - - /* Store the type, version. Unfortunately, they are in - * the input buffer ahead of the plaintext. */ - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - c16toa(ssl->keys.dtls_epoch, additional); - 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 - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, - ssl->keys.aead_enc_imp_IV, AEAD_IMP_IV_SZ); - XMEMCPY(nonce + AEAD_IMP_IV_SZ, - ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ); - wc_AesCcmEncrypt(ssl->encrypt.aes, - out + AEAD_EXP_IV_SZ, input + AEAD_EXP_IV_SZ, - sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AEAD_NONCE_SZ, - out + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ); - AeadIncrementExpIV(ssl); - ForceZero(nonce, AEAD_NONCE_SZ); - } - break; - #endif - - #ifdef HAVE_CAMELLIA - case wolfssl_camellia: - wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz); - break; - #endif - - #ifdef HAVE_HC128 - case wolfssl_hc128: - ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz); - break; - #endif - - #ifdef BUILD_RABBIT - case wolfssl_rabbit: - ret = wc_RabbitProcess(ssl->encrypt.rabbit, 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_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 WOLFSSL_ASYNC_CRYPT + if (ssl->error == WC_PENDING_E) { + ssl->error = 0; /* clear async */ } +#endif + + 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 */ +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) + AeadIncrementExpIV(ssl); +#endif + if (ssl->encrypt.nonce) + ForceZero(ssl->encrypt.nonce, AESGCM_NONCE_SZ); + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + break; + } + } + + /* Reset state */ + ssl->encrypt.state = CIPHER_STATE_BEGIN; return ret; } - -static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, +static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) { int ret = 0; @@ -5642,162 +13796,300 @@ 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 + /* initialize 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 + + #if defined(BUILD_AES) && defined(HAVE_AES_CBC) + case wolfssl_aes: + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + if (tsip_useable(ssl)) { + ret = wc_tsip_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz); + } else + #endif + 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 + /* initialize 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); - break; + #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 - #ifdef BUILD_AESGCM - case wolfssl_aes_gcm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AEAD_NONCE_SZ]; + XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ); - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); + /* sequence number field is 64-bits */ + WriteSEQ(ssl, PEER_ORDER, ssl->decrypt.additional); - /* sequence number field is 64-bits, we only use 32-bits */ - c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET); + 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; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - c16toa(ssl->keys.dtls_state.curEpoch, additional); - #endif - - additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; - additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; - additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; - - c16toa(sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AEAD_IMP_IV_SZ); - XMEMCPY(nonce + AEAD_IMP_IV_SZ, input, AEAD_EXP_IV_SZ); - if (wc_AesGcmDecrypt(ssl->decrypt.aes, - plain + AEAD_EXP_IV_SZ, - input + AEAD_EXP_IV_SZ, - sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AEAD_NONCE_SZ, - input + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ) < 0) { - 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, AEAD_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 - case wolfssl_aes_ccm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AEAD_NONCE_SZ]; - - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); - - /* sequence number field is 64-bits, we only use 32-bits */ - c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET); - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - c16toa(ssl->keys.dtls_state.curEpoch, additional); - #endif - - additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; - additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; - additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; - - c16toa(sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AEAD_IMP_IV_SZ); - XMEMCPY(nonce + AEAD_IMP_IV_SZ, input, AEAD_EXP_IV_SZ); - if (wc_AesCcmDecrypt(ssl->decrypt.aes, - plain + AEAD_EXP_IV_SZ, - input + AEAD_EXP_IV_SZ, - sz - AEAD_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AEAD_NONCE_SZ, - input + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ) < 0) { - SendAlert(ssl, alert_fatal, bad_record_mac); - ret = VERIFY_MAC_ERROR; - } - ForceZero(nonce, AEAD_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 - - default: - WOLFSSL_MSG("wolfSSL Decrypt programming error"); - ret = DECRYPT_ERROR; + default: + WOLFSSL_MSG("wolfSSL Decrypt programming error"); + ret = DECRYPT_ERROR; } return ret; } +static WC_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; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +/* 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 WC_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) { #ifdef HAVE_TRUNCATED_HMAC - word32 minLength = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ + word32 minLength = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ : ssl->specs.hash_size; #else word32 minLength = ssl->specs.hash_size; /* covers stream */ #endif +#ifndef WOLFSSL_AEAD_ONLY if (ssl->specs.cipher_type == block) { +#ifdef HAVE_ENCRYPT_THEN_MAC + if (ssl->options.startedETMRead) { + if ((encryptSz - MacSize(ssl)) % ssl->specs.block_size) { + WOLFSSL_MSG("Block ciphertext not block size"); + return SANITY_CIPHER_E; + } + } + else +#endif if (encryptSz % ssl->specs.block_size) { WOLFSSL_MSG("Block ciphertext not block size"); return SANITY_CIPHER_E; @@ -5811,10 +14103,12 @@ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) if (ssl->options.tls1_1) minLength += ssl->specs.block_size; /* explicit IV */ } - else if (ssl->specs.cipher_type == aead) { + else +#endif + if (ssl->specs.cipher_type == aead) { minLength = ssl->specs.aead_mac_size; /* authTag size */ - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - minLength += AEAD_EXP_IV_SZ; /* explicit IV */ + if (CipherHasExpIV(ssl)) + minLength += AESGCM_EXP_IV_SZ; /* explicit IV */ } if (encryptSz < minLength) { @@ -5826,167 +14120,7 @@ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) } -#ifndef NO_OLD_TLS - -static INLINE void Md5Rounds(int rounds, const byte* data, int sz) -{ - Md5 md5; - int i; - - wc_InitMd5(&md5); - - for (i = 0; i < rounds; i++) - wc_Md5Update(&md5, data, sz); -} - - - -/* do a dummy sha round */ -static INLINE void ShaRounds(int rounds, const byte* data, int sz) -{ - 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); -} -#endif - - -#ifndef NO_SHA256 - -static INLINE void Sha256Rounds(int rounds, const byte* data, int sz) -{ - Sha256 sha256; - int i; - - wc_InitSha256(&sha256); /* no error check on purpose, dummy round */ - - for (i = 0; i < rounds; i++) { - wc_Sha256Update(&sha256, data, sz); - /* no error check on purpose, dummy round */ - } - -} - -#endif - - -#ifdef WOLFSSL_SHA384 - -static INLINE void Sha384Rounds(int rounds, const byte* data, int sz) -{ - Sha384 sha384; - int i; - - wc_InitSha384(&sha384); /* no error check on purpose, dummy round */ - - for (i = 0; i < rounds; i++) { - wc_Sha384Update(&sha384, data, sz); - /* no error check on purpose, dummy round */ - } -} - -#endif - - -#ifdef WOLFSSL_SHA512 - -static INLINE void Sha512Rounds(int rounds, const byte* data, int sz) -{ - Sha512 sha512; - int i; - - wc_InitSha512(&sha512); /* no error check on purpose, dummy round */ - - for (i = 0; i < rounds; i++) { - wc_Sha512Update(&sha512, data, sz); - /* no error check on purpose, dummy round */ - } -} - -#endif - - -#ifdef WOLFSSL_RIPEMD - -static INLINE void RmdRounds(int rounds, const byte* data, int sz) -{ - RipeMd ripemd; - int i; - - wc_InitRipeMd(&ripemd); - - for (i = 0; i < rounds; i++) - wc_RipeMdUpdate(&ripemd, data, sz); -} - -#endif - - -/* Do dummy rounds */ -static INLINE void DoRounds(int type, int rounds, const byte* data, int sz) -{ - switch (type) { - - case no_mac : - break; - -#ifndef NO_OLD_TLS -#ifndef NO_MD5 - case md5_mac : - Md5Rounds(rounds, data, sz); - break; -#endif - -#ifndef NO_SHA - case sha_mac : - ShaRounds(rounds, data, sz); - break; -#endif -#endif - -#ifndef NO_SHA256 - case sha256_mac : - Sha256Rounds(rounds, data, sz); - break; -#endif - -#ifdef WOLFSSL_SHA384 - case sha384_mac : - Sha384Rounds(rounds, data, sz); - break; -#endif - -#ifdef WOLFSSL_SHA512 - case sha512_mac : - Sha512Rounds(rounds, data, sz); - break; -#endif - -#ifdef WOLFSSL_RIPEMD - case rmd_mac : - RmdRounds(rounds, data, sz); - break; -#endif - - default: - WOLFSSL_MSG("Bad round type"); - break; - } -} - - -/* do number of compression rounds on dummy data */ -static INLINE void CompressRounds(WOLFSSL* ssl, int rounds, const byte* dummy) -{ - if (rounds) - DoRounds(ssl->specs.mac_algorithm, rounds, dummy, COMPRESS_LOWER); -} - - +#ifndef WOLFSSL_AEAD_ONLY /* check all length bytes for the pad value, return 0 on success */ static int PadCheck(const byte* a, byte pad, int length) { @@ -6001,76 +14135,130 @@ static int PadCheck(const byte* a, byte pad, int length) } -/* get compression extra rounds */ -static INLINE int GetRounds(int pLen, int padLen, int t) +/* Mask the padding bytes with the expected values. + * Constant time implementation - does maximum pad size possible. + * + * data Message data. + * sz Size of the message including MAC and padding and padding length. + * macSz Size of the MAC. + * returns 0 on success, otherwise failure. + */ +static byte MaskPadding(const byte* data, int sz, int macSz) { - int roundL1 = 1; /* round up flags */ - int roundL2 = 1; + int i; + int checkSz = sz - 1; + byte paddingSz = data[sz - 1]; + byte mask; + byte good = ctMaskGT(paddingSz, sz - 1 - macSz); - int L1 = COMPRESS_CONSTANT + pLen - t; - int L2 = COMPRESS_CONSTANT + pLen - padLen - 1 - t; + if (checkSz > TLS_MAX_PAD_SZ) + checkSz = TLS_MAX_PAD_SZ; - L1 -= COMPRESS_UPPER; - L2 -= COMPRESS_UPPER; + for (i = 0; i < checkSz; i++) { + mask = ctMaskLTE(i, paddingSz); + good |= mask & (data[sz - 1 - i] ^ paddingSz); + } - if ( (L1 % COMPRESS_LOWER) == 0) - roundL1 = 0; - if ( (L2 % COMPRESS_LOWER) == 0) - roundL2 = 0; - - L1 /= COMPRESS_LOWER; - L2 /= COMPRESS_LOWER; - - L1 += roundL1; - L2 += roundL2; - - return L1 - L2; + return good; } +/* Mask the MAC in the message with the MAC calculated. + * Constant time implementation - starts looking for MAC where maximum padding + * size has it. + * + * data Message data. + * sz Size of the message including MAC and padding and padding length. + * macSz Size of the MAC data. + * expMac Expected MAC value. + * returns 0 on success, otherwise failure. + */ +static byte MaskMac(const byte* data, int sz, int macSz, byte* expMac) +{ + int i, j; + unsigned char mac[WC_MAX_DIGEST_SIZE]; + int scanStart = sz - 1 - TLS_MAX_PAD_SZ - macSz; + int macEnd = sz - 1 - data[sz - 1]; + int macStart = macEnd - macSz; + int r = 0; + unsigned char started, notEnded; + unsigned char good = 0; + + scanStart &= ctMaskIntGTE(scanStart, 0); + macStart &= ctMaskIntGTE(macStart, 0); + + /* Div on Intel has different speeds depending on value. + * Use a bitwise AND or mod a specific value (converted to mul). */ + if ((macSz & (macSz - 1)) == 0) + r = (macSz - (scanStart - macStart)) & (macSz - 1); +#ifndef NO_SHA + else if (macSz == WC_SHA_DIGEST_SIZE) + r = (macSz - (scanStart - macStart)) % WC_SHA_DIGEST_SIZE; +#endif +#ifdef WOLFSSL_SHA384 + else if (macSz == WC_SHA384_DIGEST_SIZE) + r = (macSz - (scanStart - macStart)) % WC_SHA384_DIGEST_SIZE; +#endif + + XMEMSET(mac, 0, macSz); + for (i = scanStart; i < sz; i += macSz) { + for (j = 0; j < macSz && j + i < sz; j++) { + started = ctMaskGTE(i + j, macStart); + notEnded = ctMaskLT(i + j, macEnd); + mac[j] |= started & notEnded & data[i + j]; + } + } + + if ((macSz & (macSz - 1)) == 0) { + for (i = 0; i < macSz; i++) + good |= expMac[i] ^ mac[(i + r) & (macSz - 1)]; + } +#ifndef NO_SHA + else if (macSz == WC_SHA_DIGEST_SIZE) { + for (i = 0; i < macSz; i++) + good |= expMac[i] ^ mac[(i + r) % WC_SHA_DIGEST_SIZE]; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (macSz == WC_SHA384_DIGEST_SIZE) { + for (i = 0; i < macSz; i++) + good |= expMac[i] ^ mac[(i + r) % WC_SHA384_DIGEST_SIZE]; + } +#endif + + return good; +} /* timing resistant pad/verify check, return 0 on success */ -static int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t, - int pLen, int content) +int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz, + int pLen, int content) { - byte verify[MAX_DIGEST_SIZE]; - byte dmy[sizeof(WOLFSSL) >= MAX_PAD_SIZE ? 1 : MAX_PAD_SIZE] = {0}; - byte* dummy = sizeof(dmy) < MAX_PAD_SIZE ? (byte*) ssl : dmy; + byte verify[WC_MAX_DIGEST_SIZE]; + byte good; int ret = 0; - (void)dmy; + good = MaskPadding(input, pLen, macSz); + /* 4th argument has potential to underflow, ssl->hmac function should + * either increment the size by (macSz + padLen + 1) before use or check on + * the size to make sure is valid. */ + ret = ssl->hmac(ssl, verify, input, pLen - macSz - padLen - 1, padLen, + content, 1); + good |= MaskMac(input, pLen, ssl->specs.hash_size, verify); - if ( (t + padLen + 1) > pLen) { - WOLFSSL_MSG("Plain Len not long enough for pad/mac"); - PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE); - ssl->hmac(ssl, verify, input, pLen - t, content, 1); /* still compare */ - ConstantCompare(verify, input + pLen - t, t); - - return VERIFY_MAC_ERROR; - } - - if (PadCheck(input + pLen - (padLen + 1), (byte)padLen, padLen + 1) != 0) { - WOLFSSL_MSG("PadCheck failed"); - PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1); - ssl->hmac(ssl, verify, input, pLen - t, content, 1); /* still compare */ - ConstantCompare(verify, input + pLen - t, t); - - return VERIFY_MAC_ERROR; - } - - PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1); - ret = ssl->hmac(ssl, verify, input, pLen - padLen - 1 - t, content, 1); - - CompressRounds(ssl, GetRounds(pLen, padLen, t), dummy); - - if (ConstantCompare(verify, input + (pLen - padLen - 1 - t), t) != 0) { - WOLFSSL_MSG("Verify MAC compare failed"); - return VERIFY_MAC_ERROR; - } + /* Non-zero on failure. */ + good = (byte)~(word32)good; + good &= good >> 4; + good &= good >> 2; + good &= good >> 1; + /* Make ret negative on masking failure. */ + ret -= 1 - good; + /* Treat any failure as verify MAC error. */ if (ret != 0) - return VERIFY_MAC_ERROR; - return 0; + ret = VERIFY_MAC_ERROR; + + return ret; } +#endif int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) @@ -6084,26 +14272,58 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA]; #endif +#ifdef WOLFSSL_EARLY_DATA + if (ssl->options.tls1_3 && ssl->options.handShakeDone == 0) { + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->earlyData != no_early_data && + ssl->options.clientState < CLIENT_FINISHED_COMPLETE) { + ssl->earlyDataSz += ssl->curSize; + if (ssl->earlyDataSz <= ssl->options.maxEarlyDataSz) { + WOLFSSL_MSG("Ignoring EarlyData!"); + *inOutIdx = ssl->buffers.inputBuffer.length; + return 0; + } + WOLFSSL_MSG("Too much EarlyData!"); + } + } +#endif if (ssl->options.handShakeDone == 0) { WOLFSSL_MSG("Received App data before a handshake completed"); SendAlert(ssl, alert_fatal, unexpected_message); return OUT_OF_ORDER_E; } +#ifndef WOLFSSL_AEAD_ONLY if (ssl->specs.cipher_type == block) { if (ssl->options.tls1_1) ivExtra = ssl->specs.block_size; } - else if (ssl->specs.cipher_type == aead) { - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - ivExtra = AEAD_EXP_IV_SZ; + else +#endif + if (ssl->specs.cipher_type == aead) { + if (CipherHasExpIV(ssl)) + ivExtra = AESGCM_EXP_IV_SZ; } dataSz = msgSz - ivExtra - ssl->keys.padSz; +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + dataSz -= MacSize(ssl); +#endif if (dataSz < 0) { WOLFSSL_MSG("App data buffer error, malicious input?"); + SendAlert(ssl, alert_fatal, unexpected_message); return BUFFER_ERROR; } +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData > early_data_ext) { + 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) { @@ -6122,6 +14342,10 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) } idx += ssl->keys.padSz; +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + idx += MacSize(ssl); +#endif #ifdef HAVE_LIBZ /* decompress could be bigger, overwrite after verify */ @@ -6140,19 +14364,33 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type, { byte level; byte code; + word32 dataSz = totalSz - *inOutIdx; - #ifdef WOLFSSL_CALLBACKS + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) - AddPacketName("Alert", &ssl->handShakeInfo); + AddPacketName(ssl, "Alert"); if (ssl->toInfoOn) - /* add record header back on to info + 2 byte level, data */ - AddPacketInfo("Alert", &ssl->timeoutInfo, input + *inOutIdx - - RECORD_HEADER_SZ, 2 + RECORD_HEADER_SZ, ssl->heap); + /* add record header back on to info + alert bytes level/code */ + AddPacketInfo(ssl, "Alert", alert, input + *inOutIdx - + RECORD_HEADER_SZ, RECORD_HEADER_SZ + ALERT_SIZE, + READ_PROTO, ssl->heap); #endif + if (IsEncryptionOn(ssl, 0)) { + dataSz -= ssl->keys.padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + dataSz -= MacSize(ssl); + #endif + } + /* make sure can read the message */ - if (*inOutIdx + ALERT_SIZE > totalSz) + if (dataSz != ALERT_SIZE) { +#ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); +#endif return BUFFER_E; + } level = input[(*inOutIdx)++]; code = input[(*inOutIdx)++]; @@ -6163,16 +14401,35 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type, ssl->options.isClosed = 1; /* Don't send close_notify */ } + if (++ssl->options.alertCount >= WOLFSSL_ALERT_COUNT_MAX) { + WOLFSSL_MSG("Alert count exceeded"); +#ifdef WOLFSSL_EXTRA_ALERTS + if (level != alert_warning || code != close_notify) + SendAlert(ssl, alert_fatal, unexpected_message); +#endif + return ALERT_COUNT_E; + } + WOLFSSL_MSG("Got alert"); if (*type == close_notify) { - WOLFSSL_MSG(" close notify"); + WOLFSSL_MSG("\tclose notify"); ssl->options.closeNotify = 1; } +#ifdef WOLFSSL_TLS13 + if (*type == decode_error) { + WOLFSSL_MSG("\tdecode error"); + } + if (*type == illegal_parameter) { + WOLFSSL_MSG("\tillegal parameter"); + } +#endif WOLFSSL_ERROR(*type); - if (ssl->keys.encryptionOn) { - if (*inOutIdx + ssl->keys.padSz > totalSz) - return BUFFER_E; + if (IsEncryptionOn(ssl, 0)) { *inOutIdx += ssl->keys.padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + *inOutIdx += MacSize(ssl); + #endif } return level; @@ -6200,14 +14457,16 @@ static int GetInputData(WOLFSSL *ssl, word32 size) } #endif + /* check that no lengths or size values are negative */ + if (usedLength < 0 || maxLength < 0 || inSz <= 0) { + return BUFFER_ERROR; + } + if (inSz > maxLength) { if (GrowInputBuffer(ssl, size + dtlsExtra, usedLength) < 0) return MEMORY_E; } - if (inSz <= 0) - return BUFFER_ERROR; - /* Put buffer data at start if not there */ if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0) XMEMMOVE(ssl->buffers.inputBuffer.buffer, @@ -6220,16 +14479,16 @@ static int GetInputData(WOLFSSL *ssl, word32 size) /* read data from network */ do { - in = Receive(ssl, + in = wolfSSLReceive(ssl, ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.length, inSz); - if (in == -1) - return SOCKET_ERROR_E; - if (in == WANT_READ) return WANT_READ; + if (in < 0) + return SOCKET_ERROR_E; + if (in > inSz) return RECV_OVERFLOW_E; @@ -6238,24 +14497,62 @@ 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; } +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) +static WC_INLINE int VerifyMacEnc(WOLFSSL* ssl, const byte* input, word32 msgSz, + int content) +{ + int ret; +#ifdef HAVE_TRUNCATED_HMAC + word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ + : ssl->specs.hash_size; +#else + word32 digestSz = ssl->specs.hash_size; +#endif + byte verify[WC_MAX_DIGEST_SIZE]; -static INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, + WOLFSSL_MSG("Verify MAC of Encrypted Data"); + + if (msgSz < digestSz) { + return VERIFY_MAC_ERROR; + } + + ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1); + ret |= ConstantCompare(verify, input + msgSz - digestSz, digestSz); + if (ret != 0) { + return VERIFY_MAC_ERROR; + } + + return 0; +} +#endif + +static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, int content, word32* padSz) { +#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) int ivExtra = 0; int ret; word32 pad = 0; word32 padByte = 0; #ifdef HAVE_TRUNCATED_HMAC - word32 digestSz = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ + word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ : ssl->specs.hash_size; #else word32 digestSz = ssl->specs.hash_size; #endif - byte verify[MAX_DIGEST_SIZE]; + byte verify[WC_MAX_DIGEST_SIZE]; + if (ssl->specs.cipher_type == block) { if (ssl->options.tls1_1) @@ -6283,8 +14580,8 @@ static INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, badPadLen = 1; } PadCheck(dummy, (byte)pad, MAX_PAD_SIZE); /* timing only */ - ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1, - content, 1); + ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1, pad, + content, 1); if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1, digestSz) != 0) return VERIFY_MAC_ERROR; @@ -6293,20 +14590,27 @@ static INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, } } else if (ssl->specs.cipher_type == stream) { - ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, content, 1); + ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1); if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0){ return VERIFY_MAC_ERROR; } if (ret != 0) return VERIFY_MAC_ERROR; } +#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ if (ssl->specs.cipher_type == aead) { *padSz = ssl->specs.aead_mac_size; } +#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) else { *padSz = digestSz + pad + padByte; } +#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ + + (void)input; + (void)msgSz; + (void)content; return 0; } @@ -6319,7 +14623,7 @@ int ProcessReply(WOLFSSL* ssl) int ret = 0, type, readSz; int atomicUser = 0; word32 startIdx = 0; -#ifdef WOLFSSL_DTLS +#if defined(WOLFSSL_DTLS) int used; #endif @@ -6328,7 +14632,14 @@ int ProcessReply(WOLFSSL* ssl) atomicUser = 1; #endif - if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE){ + if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE + #ifdef WOLFSSL_ASYNC_CRYPT + && ssl->error != WC_PENDING_E + #endif + #ifdef WOLFSSL_NONBLOCK_OCSP + && ssl->error != OCSP_WANT_READ + #endif + ) { WOLFSSL_MSG("ProcessReply retry in error state, not allowed"); return ssl->error; } @@ -6342,10 +14653,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) { @@ -6356,9 +14667,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 } @@ -6375,15 +14687,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; } @@ -6399,6 +14711,7 @@ int ProcessReply(WOLFSSL* ssl) ssl->options.processReply = getRecordLayerHeader; continue; } + FALL_THROUGH; /* in the WOLFSSL_SERVER case, run the old client hello */ case runProcessOldClientHello: @@ -6433,6 +14746,7 @@ int ProcessReply(WOLFSSL* ssl) } #endif /* OLD_HELLO_ALLOWED */ + FALL_THROUGH; /* get the record layer header */ case getRecordLayerHeader: @@ -6442,25 +14756,52 @@ int ProcessReply(WOLFSSL* ssl) &ssl->curRL, &ssl->curSize); #ifdef WOLFSSL_DTLS if (ssl->options.dtls && ret == SEQUENCE_ERROR) { + WOLFSSL_MSG("Silently dropping out of order DTLS message"); 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); + if (ret != 0) + return ret; + } + continue; } #endif if (ret != 0) return ret; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && IsEncryptionOn(ssl, 0) && + ssl->curRL.type != application_data && + ssl->curRL.type != change_cipher_spec) { + SendAlert(ssl, alert_fatal, unexpected_message); + return PARSE_ERROR; + } +#endif + ssl->options.processReply = getData; + FALL_THROUGH; /* retrieve record layer data */ case getData: /* get sz bytes or return error */ if (!ssl->options.dtls) { - if ((ret = GetInputData(ssl, ssl->curSize)) < 0) + if ((ret = GetInputData(ssl, ssl->curSize)) < 0) { +#ifdef WOLFSSL_EXTRA_ALERTS + if (ret != WANT_READ) + SendAlert(ssl, alert_fatal, bad_record_mac); +#endif return ret; - } else { + } + } + else { #ifdef WOLFSSL_DTLS /* read ahead may already have */ used = ssl->buffers.inputBuffer.length - @@ -6471,89 +14812,332 @@ int ProcessReply(WOLFSSL* ssl) #endif } - ssl->options.processReply = runProcessingOneMessage; + if (IsEncryptionOn(ssl, 0)) { + int tooLong = 0; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + tooLong = ssl->curSize > MAX_TLS13_ENC_SZ; + tooLong |= ssl->curSize - ssl->specs.aead_mac_size > + MAX_TLS13_PLAIN_SZ; + } +#endif +#ifdef WOLFSSL_EXTRA_ALERTS + if (!IsAtLeastTLSv1_3(ssl->version)) + tooLong = ssl->curSize > MAX_TLS_CIPHER_SZ; +#endif + if (tooLong) { + WOLFSSL_MSG("Encrypted data too long"); +#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS) + SendAlert(ssl, alert_fatal, record_overflow); +#endif + return BUFFER_ERROR; + } + } + ssl->keys.padSz = 0; + + ssl->options.processReply = verifyEncryptedMessage; startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */ + FALL_THROUGH; - /* the record layer is here */ - case runProcessingOneMessage: - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls && - ssl->keys.dtls_state.curEpoch < ssl->keys.dtls_state.nextEpoch) - ssl->keys.decryptedCur = 1; - #endif - - if (ssl->keys.encryptionOn && ssl->keys.decryptedCur == 0) - { - ret = SanityCheckCipherText(ssl, ssl->curSize); - if (ret < 0) + /* verify digest of encrypted message */ + case verifyEncryptedMessage: +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 && + !atomicUser && ssl->options.startedETMRead) { + ret = VerifyMacEnc(ssl, ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, + ssl->curSize, ssl->curRL.type); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) return ret; + #endif + if (ret < 0) { + WOLFSSL_MSG("VerifyMacEnc 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 */ + #ifdef WOLFSSL_EXTRA_ALERTS + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, bad_record_mac); + #endif + return DECRYPT_ERROR; + } + ssl->keys.encryptSz = ssl->curSize; + } +#endif + ssl->options.processReply = decryptMessage; + FALL_THROUGH; + + /* decrypt message */ + case decryptMessage: + +#if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_TLS13_DRAFT_18) + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) +#else + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 && + (!IsAtLeastTLSv1_3(ssl->version) || + ssl->curRL.type != change_cipher_spec)) +#endif + { + bufferStatic* in = &ssl->buffers.inputBuffer; + + ret = SanityCheckCipherText(ssl, ssl->curSize); + if (ret < 0) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, bad_record_mac); + #endif + return ret; + } 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, - 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 += AEAD_EXP_IV_SZ; - #endif /* ATOMIC_USER */ + #ifdef ATOMIC_USER + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + ret = ssl->ctx->VerifyDecryptCb(ssl, + in->buffer + in->idx, in->buffer + in->idx, + ssl->curSize - MacSize(ssl), + ssl->curRL.type, 1, &ssl->keys.padSz, + ssl->DecryptVerifyCtx); + } + else + #endif + { + ret = ssl->ctx->DecryptVerifyCb(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize, ssl->curRL.type, 1, + &ssl->keys.padSz, ssl->DecryptVerifyCtx); + } + #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_ERROR(ret); - return DECRYPT_ERROR; + if (!ssl->options.tls1_3) { + #ifndef WOLFSSL_NO_TLS12 + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + word32 digestSz = MacSize(ssl); + ret = Decrypt(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize - digestSz); + ssl->keys.padSz = + in->buffer[in->idx + ssl->curSize - digestSz - 1]; + ssl->keys.padSz += 1; + ssl->keys.decryptedCur = 1; } + else + #endif + { + ret = Decrypt(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize); + } + #else + ret = DECRYPT_ERROR; + #endif + } + else + { + #ifdef WOLFSSL_TLS13 + #if defined(WOLFSSL_TLS13_DRAFT_18) || \ + defined(WOLFSSL_TLS13_DRAFT_22) || \ + defined(WOLFSSL_TLS13_DRAFT_23) + ret = DecryptTls13(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize, NULL, 0); + #else + ret = DecryptTls13(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize, + (byte*)&ssl->curRL, RECORD_HEADER_SZ); + #endif + #else + ret = DECRYPT_ERROR; + #endif /* WOLFSSL_TLS13 */ + } + } + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + + if (ret >= 0) { + #ifndef WOLFSSL_NO_TLS12 + /* handle success */ + #ifndef WOLFSSL_AEAD_ONLY if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) ssl->buffers.inputBuffer.idx += ssl->specs.block_size; + #endif /* go past TLSv1.1 IV */ - if (ssl->specs.cipher_type == aead && - ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - ssl->buffers.inputBuffer.idx += AEAD_EXP_IV_SZ; + if (CipherHasExpIV(ssl)) + ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ; + #endif + } + else { + WOLFSSL_MSG("Decrypt failed"); + WOLFSSL_ERROR(ret); + #ifdef WOLFSSL_EARLY_DATA + if (ssl->options.tls1_3) { + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->earlyData != no_early_data && + ssl->options.clientState < + CLIENT_FINISHED_COMPLETE) { + ssl->earlyDataSz += ssl->curSize; + if (ssl->earlyDataSz <= + ssl->options.maxEarlyDataSz) { + WOLFSSL_MSG("Ignoring EarlyData!"); + 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; + } + WOLFSSL_MSG("Too much EarlyData!"); + } + SendAlert(ssl, alert_fatal, bad_record_mac); + } + #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 !defined(WOLFSSL_TLS13) || defined(WOLFSSL_TLS13_DRAFT_18) + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) +#else + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 && + (!IsAtLeastTLSv1_3(ssl->version) || + ssl->curRL.type != change_cipher_spec)) +#endif + { + if (!atomicUser +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + && !ssl->options.startedETMRead +#endif + ) { 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 */ + #ifdef WOLFSSL_EXTRA_ALERTS + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, bad_record_mac); + #endif + return DECRYPT_ERROR; + } } - if (ret < 0) { - 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 = (word16)(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 } - if (ssl->options.dtls) { - #ifdef WOLFSSL_DTLS - DtlsUpdateWindow(&ssl->keys.dtls_state); - #endif /* WOLFSSL_DTLS */ + ssl->options.processReply = runProcessingOneMessage; + FALL_THROUGH; + + /* the record layer is here */ + case runProcessingOneMessage: + + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (IsEncryptionOn(ssl, 0) && ssl->options.startedETMRead) { + if (ssl->buffers.inputBuffer.length - ssl->keys.padSz - + ssl->buffers.inputBuffer.idx - + MacSize(ssl) > MAX_PLAINTEXT_SZ) { + WOLFSSL_MSG("Plaintext too long - Encrypt-Then-MAC"); + #if defined(WOLFSSL_EXTRA_ALERTS) + SendAlert(ssl, alert_fatal, record_overflow); + #endif + return BUFFER_ERROR; + } } + else + #endif + if (ssl->buffers.inputBuffer.length - ssl->keys.padSz - + ssl->buffers.inputBuffer.idx > MAX_PLAINTEXT_SZ) { + WOLFSSL_MSG("Plaintext too long"); +#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS) + SendAlert(ssl, alert_fatal, record_overflow); +#endif + return BUFFER_ERROR; + } + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + DtlsUpdateWindow(ssl); + } + #endif /* WOLFSSL_DTLS */ WOLFSSL_MSG("received record layer msg"); switch (ssl->curRL.type) { case handshake : /* debugging in DoHandShakeMsg */ - if (!ssl->options.dtls) { - ret = DoHandShakeMsg(ssl, - ssl->buffers.inputBuffer.buffer, - &ssl->buffers.inputBuffer.idx, - ssl->buffers.inputBuffer.length); - } - else { + if (ssl->options.dtls) { #ifdef WOLFSSL_DTLS ret = DoDtlsHandShakeMsg(ssl, ssl->buffers.inputBuffer.buffer, @@ -6561,69 +15145,167 @@ int ProcessReply(WOLFSSL* ssl) ssl->buffers.inputBuffer.length); #endif } - if (ret != 0) + else if (!IsAtLeastTLSv1_3(ssl->version)) { +#ifndef WOLFSSL_NO_TLS12 + ret = DoHandShakeMsg(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.length); +#else + ret = BUFFER_ERROR; +#endif + } + else { +#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 > early_data_ext && + ssl->options.handShakeState == HANDSHAKE_DONE) { + ssl->earlyData = no_early_data; + ssl->options.processReply = doProcessInit; + return ZERO_RETURN; + } + #endif +#else + ret = BUFFER_ERROR; +#endif + } + if (ret != 0) { + WOLFSSL_ERROR(ret); return ret; + } break; case change_cipher_spec: WOLFSSL_MSG("got CHANGE CIPHER SPEC"); - #ifdef WOLFSSL_CALLBACKS + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) - AddPacketName("ChangeCipher", &ssl->handShakeInfo); + AddPacketName(ssl, "ChangeCipher"); /* add record header back on info */ if (ssl->toInfoOn) { - AddPacketInfo("ChangeCipher", &ssl->timeoutInfo, + AddPacketInfo(ssl, "ChangeCipher", + change_cipher_spec, ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ, - 1 + RECORD_HEADER_SZ, ssl->heap); + 1 + RECORD_HEADER_SZ, READ_PROTO, ssl->heap); + #ifdef WOLFSSL_CALLBACKS AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); + #endif } #endif - ret = SanityCheckMsgReceived(ssl, change_cipher_hs); - if (ret != 0) - return ret; - -#ifdef HAVE_SESSION_TICKET - if (ssl->options.side == WOLFSSL_CLIENT_END && - ssl->expect_session_ticket) { - WOLFSSL_MSG("Expected session ticket missing"); - return SESSION_TICKET_EXPECT_E; +#ifdef WOLFSSL_TLS13 + #ifdef WOLFSSL_TLS13_DRAFT_18 + if (IsAtLeastTLSv1_3(ssl->version)) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return UNKNOWN_RECORD_TYPE; } + #else + if (IsAtLeastTLSv1_3(ssl->version)) { + word32 i = ssl->buffers.inputBuffer.idx; + if (ssl->options.handShakeState == HANDSHAKE_DONE) { + SendAlert(ssl, alert_fatal, unexpected_message); + return UNKNOWN_RECORD_TYPE; + } + if (ssl->curSize != 1 || + ssl->buffers.inputBuffer.buffer[i] != 1) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return UNKNOWN_RECORD_TYPE; + } + ssl->buffers.inputBuffer.idx++; + break; + } + #endif #endif - if (ssl->keys.encryptionOn && ssl->options.handShakeDone) { +#ifndef WOLFSSL_NO_TLS12 + ret = SanityCheckMsgReceived(ssl, change_cipher_hs); + if (ret != 0) { + if (!ssl->options.dtls) { + return ret; + } + else { + #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. */ + if (ret != DUPLICATE_MSG_E && ret != OUT_OF_ORDER_E) + return ret; + + if (IsDtlsNotSctpMode(ssl)) { + ret = DtlsMsgPoolSend(ssl, 1); + if (ret != 0) + return ret; + } + + if (ssl->curSize != 1) { + WOLFSSL_MSG("Malicious or corrupted" + " duplicate ChangeCipher msg"); + return LENGTH_ERROR; + } + ssl->buffers.inputBuffer.idx++; + break; + #endif /* WOLFSSL_DTLS */ + } + } + + if (IsEncryptionOn(ssl, 0) && ssl->options.handShakeDone) { ssl->buffers.inputBuffer.idx += ssl->keys.padSz; ssl->curSize -= (word16) ssl->buffers.inputBuffer.idx; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + word32 digestSz = MacSize(ssl); + ssl->buffers.inputBuffer.idx += digestSz; + ssl->curSize -= digestSz; + } + #endif } if (ssl->curSize != 1) { WOLFSSL_MSG("Malicious or corrupted ChangeCipher msg"); return LENGTH_ERROR; } - #ifndef NO_CERTS - if (ssl->options.side == WOLFSSL_SERVER_END && - ssl->options.verifyPeer && - ssl->options.havePeerCert) - if (!ssl->options.havePeerVerify) { - WOLFSSL_MSG("client didn't send cert verify"); - return NO_PEER_VERIFY; - } - #endif - ssl->buffers.inputBuffer.idx++; 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; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + ssl->options.startedETMRead = ssl->options.encThenMac; + #endif + #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - DtlsPoolReset(ssl); - ssl->keys.dtls_state.nextEpoch++; - ssl->keys.dtls_state.nextSeq = 0; + 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 + 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); + XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ); } #endif @@ -6637,13 +15319,26 @@ int ProcessReply(WOLFSSL* ssl) server : client); if (ret != 0) return ret; +#endif /* !WOLFSSL_NO_TLS12 */ break; case application_data: WOLFSSL_MSG("got app DATA"); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls && ssl->options.dtlsHsRetain) { + FreeHandshakeResources(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)) + &ssl->buffers.inputBuffer.idx)) != 0) { WOLFSSL_ERROR(ret); return ret; @@ -6676,24 +15371,41 @@ int ProcessReply(WOLFSSL* ssl) ssl->options.processReply = doProcessInit; /* input exhausted? */ - if (ssl->buffers.inputBuffer.idx == ssl->buffers.inputBuffer.length) + if (ssl->buffers.inputBuffer.idx >= ssl->buffers.inputBuffer.length) return 0; /* 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 (ssl->keys.encryptionOn) { + if (IsEncryptionOn(ssl, 0)) { WOLFSSL_MSG("Bundled encrypted messages, remove middle pad"); - ssl->buffers.inputBuffer.idx -= ssl->keys.padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) { + word32 digestSz = MacSize(ssl); + if (ssl->buffers.inputBuffer.idx >= + ssl->keys.padSz + digestSz) { + ssl->buffers.inputBuffer.idx -= + ssl->keys.padSz + digestSz; + } + else { + WOLFSSL_MSG("\tmiddle padding error"); + return FATAL_ERROR; + } + } + else + #endif + { + 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; @@ -6720,6 +15432,21 @@ int SendChangeCipher(WOLFSSL* ssl) int idx = RECORD_HEADER_SZ; int ret; + #ifdef OPENSSL_EXTRA + ssl->cbmode = SSL_CB_MODE_WRITE; + if (ssl->options.side == WOLFSSL_SERVER_END){ + ssl->options.serverState = SERVER_CHANGECIPHERSPEC_COMPLETE; + if (ssl->CBIS != NULL) + ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS); + } + else{ + ssl->options.clientState = + CLIENT_CHANGECIPHERSPEC_COMPLETE; + if (ssl->CBIS != NULL) + ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS); + } + #endif + #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { sendSz += DTLS_RECORD_EXTRA; @@ -6728,15 +15455,15 @@ int SendChangeCipher(WOLFSSL* ssl) #endif /* are we in scr */ - if (ssl->keys.encryptionOn && ssl->options.handShakeDone) { + if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { sendSz += MAX_MSG_EXTRA; } - /* check for avalaible size */ + /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; - /* get ouput buffer */ + /* get output buffer */ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; @@ -6744,34 +15471,36 @@ int SendChangeCipher(WOLFSSL* ssl) output[idx] = 1; /* turn it on */ - if (ssl->keys.encryptionOn && ssl->options.handShakeDone) { + if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { byte input[ENUM_LEN]; int inputSz = ENUM_LEN; input[0] = 1; /* turn it on */ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - change_cipher_spec); - if (sendSz < 0) + change_cipher_spec, 0, 0, 0); + if (sendSz < 0) { return sendSz; + } } #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + if (IsDtlsNotSctpMode(ssl)) { + DtlsSEQIncrement(ssl, CUR_ORDER); + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) return ret; } #endif - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("ChangeCipher", &ssl->handShakeInfo); + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) AddPacketName(ssl, "ChangeCipher"); if (ssl->toInfoOn) - AddPacketInfo("ChangeCipher", &ssl->timeoutInfo, output, sendSz, - ssl->heap); + AddPacketInfo(ssl, "ChangeCipher", change_cipher_spec, output, + sendSz, WRITE_PROTO, ssl->heap); #endif ssl->buffers.outputBuffer.length += sendSz; if (ssl->options.groupMessages) return 0; - #ifdef WOLFSSL_DTLS + #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_DEBUG_DTLS) else if (ssl->options.dtls) { /* If using DTLS, force the ChangeCipherSpec message to be in the * same datagram as the finished message. */ @@ -6783,23 +15512,25 @@ int SendChangeCipher(WOLFSSL* ssl) } -#ifndef NO_OLD_TLS +#if !defined(NO_OLD_TLS) && !defined(WOLFSSL_AEAD_ONLY) static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, - int content, int verify) + int padLen, int content, int verify) { - byte result[MAX_DIGEST_SIZE]; + byte result[WC_MAX_DIGEST_SIZE]; word32 digestSz = ssl->specs.hash_size; /* actual sizes */ word32 padSz = ssl->specs.pad_size; int ret = 0; - Md5 md5; - Sha sha; + wc_Md5 md5; + wc_Sha sha; /* data */ byte seq[SEQ_SZ]; byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */ const byte* macSecret = wolfSSL_GetMacSecret(ssl, verify); + (void)padLen; + #ifdef HAVE_FUZZER if (ssl->fuzzerCb) ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx); @@ -6808,314 +15539,643 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, XMEMSET(seq, 0, SEQ_SZ); conLen[0] = (byte)content; c16toa((word16)sz, &conLen[ENUM_LEN]); - c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]); + 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; } +#endif /* !NO_OLD_TLS && !WOLFSSL_AEAD_ONLY */ + #ifndef NO_CERTS -static void BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest) -{ - byte md5_result[MD5_DIGEST_SIZE]; +#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 - 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); #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, 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); /* 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 */ - 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); + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX); #endif + + return ret; } +#endif /* !NO_MD5 && !NO_OLD_TLS */ - -static void BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest) +#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) +static int BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest) { - 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); #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, 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, 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, digest); + 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX); #endif + return ret; } -#endif /* NO_CERTS */ -#endif /* NO_OLD_TLS */ +#endif /* !NO_SHA && (!NO_OLD_TLS || WOLFSSL_ALLOW_TLS_SHA1) */ - -#ifndef NO_CERTS - -static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) +int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) { - /* store current states, building requires get_digest which resets state */ - #ifdef WOLFSSL_SHA384 - Sha384 sha384 = ssl->hsHashes->hashSha384; - #endif - #ifdef WOLFSSL_SHA512 - Sha512 sha512 = ssl->hsHashes->hashSha512; - #endif + 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)) { - int ret; - #ifndef NO_SHA256 - ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256,hashes->sha256); + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, + hashes->sha256); if (ret != 0) return ret; #endif #ifdef WOLFSSL_SHA384 - ret = wc_Sha384Final(&ssl->hsHashes->hashSha384,hashes->sha384); + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, + hashes->sha384); if (ret != 0) return ret; #endif #ifdef WOLFSSL_SHA512 - ret = wc_Sha512Final(&ssl->hsHashes->hashSha512,hashes->sha512); + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, + hashes->sha512); if (ret != 0) return ret; #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 } - /* restore */ -#endif - if (IsAtLeastTLSv1_2(ssl)) { - #ifdef WOLFSSL_SHA384 - ssl->hsHashes->hashSha384 = sha384; - #endif - #ifdef WOLFSSL_SHA512 - ssl->hsHashes->hashSha512 = sha512; - #endif - } - - return 0; + return ret; } -#endif /* WOLFSSL_LEANPSK */ +#endif /* !NO_CERTS */ + +#ifndef WOLFSSL_NO_TLS12 +/* 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; +} BuildMsgArgs; + +static void FreeBuildMsgArgs(WOLFSSL* ssl, void* pArgs) +{ + BuildMsgArgs* args = (BuildMsgArgs*)pArgs; + + (void)ssl; + (void)args; + + if (args->iv) { + XFREE(args->iv, ssl->heap, DYNAMIC_TYPE_SALT); + args->iv = NULL; + } +} +#endif /* Build SSL Message, encrypted */ -static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, - const byte* input, int inSz, int type) +int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay) { -#ifdef HAVE_TRUNCATED_HMAC - word32 digestSz = min(ssl->specs.hash_size, - ssl->truncated_hmac ? TRUNCATED_HMAC_SZ : ssl->specs.hash_size); +#ifndef WOLFSSL_NO_TLS12 + 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 +#endif + + WOLFSSL_ENTER("BuildMessage"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_NO_TLS12 + return BuildTls13Message(ssl, output, outSz, input, inSz, type, + hashOutput, sizeOnly, asyncOkay); #else - word32 digestSz = ssl->specs.hash_size; -#endif - word32 sz = RECORD_HEADER_SZ + inSz + digestSz; - 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; - -#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; + } + + /* Reset state */ + if (ret == WC_NOT_PENDING_E) { + ret = 0; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + XMEMSET(args, 0, sizeof(BuildMsgArgs)); + + 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 + } + + switch (ssl->options.buildMsgState) { + case BUILD_MSG_BEGIN: + { + /* catch mistaken sizeOnly parameter */ + if (!sizeOnly && (output == NULL || input == NULL) ) { + ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg); + } + if (sizeOnly && (output || input) ) { + WOLFSSL_MSG("BuildMessage w/sizeOnly doesn't need input/output"); + ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg); + } + + ssl->options.buildMsgState = BUILD_MSG_SIZE; + } + 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 WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sz += DTLS_RECORD_EXTRA; + args->idx += DTLS_RECORD_EXTRA; + args->headerSz += DTLS_RECORD_EXTRA; + } + #endif + + #ifndef WOLFSSL_AEAD_ONLY + 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 > MAX_IV_SZ) + ERROR_OUT(BUFFER_E, exit_buildmsg); + } + args->sz += 1; /* pad byte */ + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMWrite) { + args->pad = (args->sz - args->headerSz - + args->digestSz) % blockSz; + } + else + #endif + args->pad = (args->sz - args->headerSz) % blockSz; + #ifdef OPENSSL_EXTRA + if(args->pad != 0) + #endif + args->pad = blockSz - args->pad; + args->sz += args->pad; + } + #endif /* WOLFSSL_AEAD_ONLY */ + + #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) { + args->iv = (byte*)XMALLOC(args->ivSz, ssl->heap, DYNAMIC_TYPE_SALT); + if (args->iv == NULL) + ERROR_OUT(MEMORY_E, exit_buildmsg); + + ret = wc_RNG_GenerateBlock(ssl->rng, args->iv, args->ivSz); + if (ret != 0) + goto exit_buildmsg; + + } +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \ + defined(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 - if (ssl->specs.cipher_type == block) { - word32 blockSz = ssl->specs.block_size; - if (ssl->options.tls1_1) { - ivSz = blockSz; - sz += ivSz; + args->size = (word16)(args->sz - args->headerSz); /* include mac and digest */ + AddRecordHeader(output, args->size, (byte)type, ssl); - if (ivSz > (word32)sizeof(iv)) - return BUFFER_E; + /* write to output */ + if (args->ivSz > 0) { + XMEMCPY(output + args->idx, args->iv, + min(args->ivSz, MAX_IV_SZ)); + args->idx += args->ivSz; + } + XMEMCPY(output + args->idx, input, inSz); + args->idx += inSz; - ret = wc_RNG_GenerateBlock(ssl->rng, iv, ivSz); + ssl->options.buildMsgState = BUILD_MSG_HASH; + } + FALL_THROUGH; + case BUILD_MSG_HASH: + { + if (type == handshake && hashOutput) { + ret = HashOutput(ssl, output, args->headerSz + inSz, args->ivSz); + if (ret != 0) + goto exit_buildmsg; + } + #ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type == block) { + word32 tmpIdx; + word32 i; + + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMWrite) + tmpIdx = args->idx; + else + #endif + tmpIdx = args->idx + args->digestSz; + + for (i = 0; i <= args->pad; i++) + output[tmpIdx++] = (byte)args->pad; /* pad byte gets pad value */ + } + #endif + + ssl->options.buildMsgState = BUILD_MSG_VERIFY_MAC; + } + FALL_THROUGH; + case BUILD_MSG_VERIFY_MAC: + { + /* User Record Layer Callback handling */ + #ifdef ATOMIC_USER + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMWrite) { + if (ssl->ctx->EncryptMacCb) { + ret = ssl->ctx->EncryptMacCb(ssl, output + args->idx + + args->pad + 1, type, 0, + output + args->headerSz, + output + args->headerSz, + args->size - args->digestSz, + ssl->MacEncryptCtx); + goto exit_buildmsg; + } + } + else + #endif + { + 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 + + #ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type != aead + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + && !ssl->options.startedETMWrite + #endif + ) { + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac && + ssl->specs.hash_size > args->digestSz) { + #ifdef WOLFSSL_SMALL_STACK + byte* hmac; + #else + byte hmac[WC_MAX_DIGEST_SIZE]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap, + DYNAMIC_TYPE_DIGEST); + if (hmac == NULL) + ERROR_OUT(MEMORY_E, exit_buildmsg); + #endif + + ret = ssl->hmac(ssl, hmac, + output + args->headerSz + args->ivSz, inSz, + -1, type, 0); + XMEMCPY(output + args->idx, hmac, args->digestSz); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST); + #endif + } + else + #endif + { + ret = ssl->hmac(ssl, output + args->idx, output + + args->headerSz + args->ivSz, inSz, -1, type, 0); + } + } + #endif /* WOLFSSL_AEAD_ONLY */ if (ret != 0) - return ret; + goto exit_buildmsg; + ssl->options.buildMsgState = BUILD_MSG_ENCRYPT; } - sz += 1; /* pad byte */ - pad = (sz - headerSz) % blockSz; - pad = blockSz - pad; - sz += pad; - } - -#ifdef HAVE_AEAD - if (ssl->specs.cipher_type == aead) { - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - ivSz = AEAD_EXP_IV_SZ; - - sz += (ivSz + ssl->specs.aead_mac_size - digestSz); - XMEMCPY(iv, ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ); - } -#endif - 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); - - /* 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) { - ret = HashOutput(ssl, output, headerSz + inSz, ivSz); - if (ret != 0) - return ret; - } - - if (ssl->specs.cipher_type == block) { - word32 tmpIdx = idx + digestSz; - - 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) { - #ifdef WOLFSSL_SMALL_STACK - byte* hmac = NULL; - #else - byte hmac[MAX_DIGEST_SIZE]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - hmac = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (hmac == NULL) - return MEMORY_E; - #endif - - ret = ssl->hmac(ssl, hmac, output + headerSz + ivSz, inSz, - type, 0); - XMEMCPY(output + idx, hmac, digestSz); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - } else -#endif - ret = ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, - type, 0); + FALL_THROUGH; + case BUILD_MSG_ENCRYPT: + { + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMWrite) { + ret = Encrypt(ssl, output + args->headerSz, + output + args->headerSz, + args->size - args->digestSz, asyncOkay); + } + else + #endif + { + ret = Encrypt(ssl, output + args->headerSz, + output + args->headerSz, args->size, asyncOkay); + } + if (ret != 0) + goto exit_buildmsg; + ssl->options.buildMsgState = BUILD_MSG_ENCRYPTED_VERIFY_MAC; } - if (ret != 0) - return ret; + FALL_THROUGH; + case BUILD_MSG_ENCRYPTED_VERIFY_MAC: + { + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMWrite) { + WOLFSSL_MSG("Calculate MAC of Encrypted Data"); - if ( (ret = Encrypt(ssl, output + headerSz, output+headerSz,size)) != 0) - return ret; + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac && + ssl->specs.hash_size > args->digestSz) { + #ifdef WOLFSSL_SMALL_STACK + byte* hmac = NULL; + #else + byte hmac[WC_MAX_DIGEST_SIZE]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap, + DYNAMIC_TYPE_DIGEST); + if (hmac == NULL) + ERROR_OUT(MEMORY_E, exit_buildmsg); + #endif + + ret = ssl->hmac(ssl, hmac, output + args->headerSz, + args->ivSz + inSz + args->pad + 1, -1, type, + 0); + XMEMCPY(output + args->idx + args->pad + 1, hmac, + args->digestSz); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST); + #endif + } + else + #endif + { + ret = ssl->hmac(ssl, output + args->idx + args->pad + 1, + output + args->headerSz, + args->ivSz + inSz + args->pad + 1, -1, type, + 0); + } + } + #endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */ + } } - 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; + + #ifdef WOLFSSL_DTLS + if (ret == 0 && ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + + /* return sz on success */ + if (ret == 0) + ret = args->sz; + + /* Final cleanup */ + FreeBuildMsgArgs(ssl, args); +#ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = NULL; +#endif + + return ret; +#endif /* !WOLFSSL_NO_TLS12 */ } +#ifndef WOLFSSL_NO_TLS12 int SendFinished(WOLFSSL* ssl) { @@ -7129,15 +16189,17 @@ int SendFinished(WOLFSSL* ssl) int headerSz = HANDSHAKE_HEADER_SZ; int outputSz; - #ifdef WOLFSSL_DTLS - word32 sequence_number = ssl->keys.dtls_sequence_number; - word16 epoch = ssl->keys.dtls_epoch; - #endif + WOLFSSL_START(WC_FUNC_FINISHED_SEND); + WOLFSSL_ENTER("SendFinished"); /* setup encrypt keys */ if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) return ret; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + ssl->options.startedETMWrite = ssl->options.encThenMac; + #endif + /* check for available size */ outputSz = sizeof(input) + MAX_MSG_EXTRA; if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) @@ -7145,19 +16207,22 @@ int SendFinished(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - /* Send Finished message with the next epoch, but don't commit that - * change until the other end confirms its reception. */ headerSz += DTLS_HANDSHAKE_EXTRA; ssl->keys.dtls_epoch++; - ssl->keys.dtls_sequence_number = 0; /* reset after epoch change */ + ssl->keys.dtls_prev_sequence_number_hi = + ssl->keys.dtls_sequence_number_hi; + ssl->keys.dtls_prev_sequence_number_lo = + ssl->keys.dtls_sequence_number_lo; + ssl->keys.dtls_sequence_number_hi = 0; + ssl->keys.dtls_sequence_number_lo = 0; } #endif - /* get ouput buffer */ + /* get output buffer */ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; - AddHandShakeHeader(input, finishedSz, finished, ssl); + AddHandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl); /* make finished hashes */ hashes = (Hashes*)&input[headerSz]; @@ -7176,211 +16241,525 @@ int SendFinished(WOLFSSL* ssl) } #endif + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, input, headerSz + finishedSz)) != 0) + return ret; + } + #endif + sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz, - handshake); + handshake, 1, 0, 0); if (sendSz < 0) return BUILD_MSG_ERROR; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - ssl->keys.dtls_epoch = epoch; - ssl->keys.dtls_sequence_number = sequence_number; - } - #endif - if (!ssl->options.resuming) { #ifndef NO_SESSION_CACHE AddSession(ssl); /* just try */ #endif if (ssl->options.side == WOLFSSL_SERVER_END) { + #ifdef OPENSSL_EXTRA + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + ssl->cbmode = SSL_CB_MODE_WRITE; + if (ssl->CBIS != NULL) + ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, SSL_SUCCESS); + #endif ssl->options.handShakeState = HANDSHAKE_DONE; ssl->options.handShakeDone = 1; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - /* Other side will soon receive our Finished, go to next - * epoch. */ - ssl->keys.dtls_epoch++; - ssl->keys.dtls_sequence_number = 1; - } - #endif } } else { if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef OPENSSL_EXTRA + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + ssl->cbmode = SSL_CB_MODE_WRITE; + if (ssl->CBIS != NULL) + ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, SSL_SUCCESS); + #endif ssl->options.handShakeState = HANDSHAKE_DONE; ssl->options.handShakeDone = 1; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - /* Other side will soon receive our Finished, go to next - * epoch. */ - ssl->keys.dtls_epoch++; - ssl->keys.dtls_sequence_number = 1; - } - #endif } } - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) - return ret; - } - #endif - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo); + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) AddPacketName(ssl, "Finished"); if (ssl->toInfoOn) - AddPacketInfo("Finished", &ssl->timeoutInfo, output, sendSz, - ssl->heap); + AddPacketInfo(ssl, "Finished", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); #endif ssl->buffers.outputBuffer.length += sendSz; - return SendBuffered(ssl); + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendFinished", ret); + WOLFSSL_END(WC_FUNC_FINISHED_SEND); + + return ret; +} +#endif /* WOLFSSL_NO_TLS12 */ + +#ifndef NO_WOLFSSL_SERVER +#if (!defined(WOLFSSL_NO_TLS12) && \ + (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ + defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)) +/* Parses and decodes the certificate then initializes "request". In the case + * of !ssl->buffers.weOwnCert, ssl->ctx->certOcspRequest gets set to "request". + * + * Returns 0 on success + */ +static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request, + DecodedCert* cert, byte* certData, word32 length) +{ + int ret; + + if (request != NULL) + XMEMSET(request, 0, sizeof(OcspRequest)); + + InitDecodedCert(cert, certData, length, ssl->heap); + /* TODO: Setup async support here */ + ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm); + if (ret != 0) { + WOLFSSL_MSG("ParseCert failed"); + } + if (ret == 0) + 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); + } + } + } + + FreeDecodedCert(cert); + + return ret; } + +/* Creates OCSP response and places it in variable "response". Memory + * management for "buffer* response" is up to the caller. + * + * Also creates an OcspRequest in the case that ocspRequest is null or that + * ssl->buffers.weOwnCert is set. In those cases managing ocspRequest free'ing + * is up to the caller. NOTE: in OcspCreateRequest ssl->ctx->certOcspRequest can + * be set to point to "ocspRequest" and it then should not be free'd since + * wolfSSL_CTX_free will take care of it. + * + * Returns 0 on success + */ +int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest, + buffer* response) +{ + int ret = 0; + OcspRequest* request = NULL; + byte createdRequest = 0; + + if (ssl == NULL || ocspRequest == NULL || response == NULL) + return BAD_FUNC_ARG; + + XMEMSET(response, 0, sizeof(*response)); + request = *ocspRequest; + + /* unable to fetch status. skip. */ + if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0) + return 0; + + if (request == NULL || ssl->buffers.weOwnCert) { + DerBuffer* der = ssl->buffers.certificate; + #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), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + #endif + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + if (request == NULL) + ret = MEMORY_E; + + createdRequest = 1; + if (ret == 0) { + ret = CreateOcspRequest(ssl, request, cert, der->buffer, + der->length); + } + + if (ret != 0) { + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + } + + #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) { + ret = 0; + } + } + + /* free request up if error case found otherwise return it */ + if (ret != 0 && createdRequest) { + FreeOcspRequest(request); + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + } + + if (ret == 0) + *ocspRequest = request; + + return ret; +} +#endif +#endif /* !NO_WOLFSSL_SERVER */ + +#ifndef WOLFSSL_NO_TLS12 + #ifndef NO_CERTS +#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH) +/* handle generation of certificate (11) */ int SendCertificate(WOLFSSL* ssl) { - int sendSz, length, ret = 0; - word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - word32 certSz, listSz; - byte* output = 0; + int ret = 0; + word32 certSz, certChainSz, headerSz, listSz, payloadSz; + word32 length, maxFragment; + + WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND); + WOLFSSL_ENTER("SendCertificate"); if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) return 0; /* not needed */ if (ssl->options.sendVerify == SEND_BLANK_CERT) { - certSz = 0; - length = CERT_HEADER_SZ; - listSz = 0; + #ifdef OPENSSL_EXTRA + if (ssl->version.major == SSLv3_MAJOR + && ssl->version.minor == SSLv3_MINOR){ + SendAlert(ssl, alert_warning, no_certificate); + return 0; + } else { + #endif + certSz = 0; + certChainSz = 0; + headerSz = CERT_HEADER_SZ; + length = CERT_HEADER_SZ; + listSz = 0; + #ifdef OPENSSL_EXTRA + } + #endif } else { - certSz = ssl->buffers.certificate.length; + if (!ssl->buffers.certificate) { + WOLFSSL_MSG("Send Cert missing certificate buffer"); + return BUFFER_ERROR; + } + certSz = ssl->buffers.certificate->length; + headerSz = 2 * CERT_HEADER_SZ; /* list + cert size */ - length = certSz + 2 * CERT_HEADER_SZ; + length = certSz + headerSz; listSz = certSz + CERT_HEADER_SZ; /* may need to send rest of chain, already has leading size(s) */ - if (ssl->buffers.certChain.buffer) { - length += ssl->buffers.certChain.length; - listSz += ssl->buffers.certChain.length; + if (certSz && ssl->buffers.certChain) { + certChainSz = ssl->buffers.certChain->length; + length += certChainSz; + listSz += certChainSz; } + else + certChainSz = 0; } - sendSz = length + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + payloadSz = length; + + if (ssl->fragOffset != 0) + length -= (ssl->fragOffset + headerSz); + + maxFragment = MAX_RECORD_SIZE; + + if (ssl->options.dtls) { #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - } - #endif - - if (ssl->keys.encryptionOn) - sendSz += MAX_MSG_EXTRA; - - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) - return ret; - - /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; - - AddHeaders(output, length, certificate, ssl); - - /* list total */ - c32to24(listSz, output + i); - i += CERT_HEADER_SZ; - - /* member */ - if (certSz) { - c32to24(certSz, output + i); - i += CERT_HEADER_SZ; - XMEMCPY(output + i, ssl->buffers.certificate.buffer, certSz); - i += certSz; - - /* send rest of chain? */ - if (ssl->buffers.certChain.buffer) { - XMEMCPY(output + i, ssl->buffers.certChain.buffer, - ssl->buffers.certChain.length); - i += ssl->buffers.certChain.length; - } + /* The 100 bytes is used to account for the UDP and IP headers. + It can also include the record padding and MAC if the + SendCertificate is called for a secure renegotiation. */ + maxFragment = MAX_MTU - DTLS_RECORD_HEADER_SZ + - DTLS_HANDSHAKE_HEADER_SZ - 100; + #endif /* WOLFSSL_DTLS */ } - if (ssl->keys.encryptionOn) { - byte* input; - int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + maxFragment = wolfSSL_GetMaxRecordSize(ssl, maxFragment); - input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (input == NULL) - return MEMORY_E; + while (length > 0 && ret == 0) { + byte* output = NULL; + word32 fragSz = 0; + word32 i = RECORD_HEADER_SZ; + int sendSz = RECORD_HEADER_SZ; - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); - sendSz = BuildMessage(ssl, output, sendSz, input,inputSz,handshake); - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (!ssl->options.dtls) { + if (ssl->fragOffset == 0) { + if (headerSz + certSz + certChainSz <= + maxFragment - HANDSHAKE_HEADER_SZ) { - if (sendSz < 0) - return sendSz; - } else { - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) + fragSz = headerSz + certSz + certChainSz; + } + else { + fragSz = maxFragment - HANDSHAKE_HEADER_SZ; + } + sendSz += fragSz + HANDSHAKE_HEADER_SZ; + i += HANDSHAKE_HEADER_SZ; + } + else { + fragSz = min(length, maxFragment); + sendSz += fragSz; + } + + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + } + else { + #ifdef WOLFSSL_DTLS + fragSz = min(length, maxFragment); + sendSz += fragSz + DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA + + HANDSHAKE_HEADER_SZ; + i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA + + HANDSHAKE_HEADER_SZ; + #endif + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; - } + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + if (ssl->fragOffset == 0) { + if (!ssl->options.dtls) { + AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl); + if (!IsEncryptionOn(ssl, 1)) + HashOutputRaw(ssl, output + RECORD_HEADER_SZ, + HANDSHAKE_HEADER_SZ); + } + else { + #ifdef WOLFSSL_DTLS + AddHeaders(output, payloadSz, certificate, ssl); + if (!IsEncryptionOn(ssl, 1)) + HashOutputRaw(ssl, + output + RECORD_HEADER_SZ + DTLS_RECORD_EXTRA, + HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA); + /* Adding the headers increments these, decrement them for + * actual message header. */ + ssl->keys.dtls_handshake_number--; + AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl); + ssl->keys.dtls_handshake_number--; + #endif /* WOLFSSL_DTLS */ + } + + /* list total */ + c32to24(listSz, output + i); + if (!IsEncryptionOn(ssl, 1)) + HashOutputRaw(ssl, output + i, CERT_HEADER_SZ); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + if (certSz) { + c32to24(certSz, output + i); + if (!IsEncryptionOn(ssl, 1)) + HashOutputRaw(ssl, output + i, CERT_HEADER_SZ); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + + if (!IsEncryptionOn(ssl, 1)) { + HashOutputRaw(ssl, ssl->buffers.certificate->buffer, certSz); + if (certChainSz) + HashOutputRaw(ssl, ssl->buffers.certChain->buffer, + certChainSz); + } + } + } + else { + if (!ssl->options.dtls) { + AddRecordHeader(output, fragSz, handshake, ssl); + } + else { + #ifdef WOLFSSL_DTLS + AddFragHeaders(output, fragSz, ssl->fragOffset + headerSz, + payloadSz, certificate, ssl); + ssl->keys.dtls_handshake_number--; + #endif /* WOLFSSL_DTLS */ + } + } + + /* member */ + if (certSz && ssl->fragOffset < certSz) { + word32 copySz = min(certSz - ssl->fragOffset, fragSz); + XMEMCPY(output + i, + ssl->buffers.certificate->buffer + ssl->fragOffset, copySz); + i += copySz; + ssl->fragOffset += copySz; + length -= copySz; + fragSz -= copySz; + } + if (certChainSz && fragSz) { + word32 copySz = min(certChainSz + certSz - ssl->fragOffset, fragSz); + XMEMCPY(output + i, + ssl->buffers.certChain->buffer + ssl->fragOffset - certSz, + copySz); + i += copySz; + ssl->fragOffset += copySz; + length -= copySz; + } + + if (IsEncryptionOn(ssl, 1)) { + byte* input = NULL; + int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + + if (inputSz < 0) { + WOLFSSL_MSG("Send Cert bad inputSz"); + return BUFFER_E; + } + + if (inputSz > 0) { /* clang thinks could be zero, let's help */ + 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, 0); + + if (inputSz > 0) + 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) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) return ret; } #endif - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo); + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "Certificate"); if (ssl->toInfoOn) - AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, - ssl->heap); + AddPacketInfo(ssl, "Certificate", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); #endif - if (ssl->options.side == WOLFSSL_SERVER_END) - ssl->options.serverState = SERVER_CERT_COMPLETE; + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + } - ssl->buffers.outputBuffer.length += sendSz; - if (ssl->options.groupMessages) - return 0; - else - return SendBuffered(ssl); + if (ret != WANT_WRITE) { + /* Clean up the fragment offset. */ + ssl->fragOffset = 0; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + ssl->keys.dtls_handshake_number++; + #endif + if (ssl->options.side == WOLFSSL_SERVER_END){ + ssl->options.serverState = SERVER_CERT_COMPLETE; + } + } + + WOLFSSL_LEAVE("SendCertificate", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_SEND); + + return ret; } +#endif /* !NO_WOLFSSL_SERVER || !WOLFSSL_NO_CLIENT_AUTH */ - +/* handle generation of certificate_request (13) */ int SendCertificateRequest(WOLFSSL* ssl) { byte *output; int ret; int sendSz; word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + word32 dnLen = 0; +#if defined(OPENSSL_ALL) || defined(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 */ + WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND); + WOLFSSL_ENTER("SendCertificateRequest"); + if (IsAtLeastTLSv1_2(ssl)) reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz; +#if defined(OPENSSL_ALL) || defined(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 */ sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz; + if (!ssl->options.dtls) { + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + } + else { #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - } + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; #endif + } /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; - /* get ouput buffer */ + /* get output buffer */ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; @@ -7389,7 +16768,8 @@ int SendCertificateRequest(WOLFSSL* ssl) /* write to output */ output[i++] = (byte)typeTotal; /* # of types */ #ifdef HAVE_ECC - if (ssl->options.cipherSuite0 == ECC_BYTE && + if ((ssl->options.cipherSuite0 == ECC_BYTE || + ssl->options.cipherSuite0 == CHACHA_BYTE) && ssl->specs.sig_algo == ecc_dsa_sa_algo) { output[i++] = ecdsa_sign; } else @@ -7401,43 +16781,381 @@ 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; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + names = ssl->ctx->ca_names; + while (names != NULL) { + byte seq[MAX_SEQ_SZ]; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + 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; + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + + 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, 0); + 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); + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) return ret; } - #endif - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) - return ret; - - #ifdef WOLFSSL_CALLBACKS + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) - AddPacketName("CertificateRequest", &ssl->handShakeInfo); + AddPacketName(ssl, "CertificateRequest"); if (ssl->toInfoOn) - AddPacketInfo("CertificateRequest", &ssl->timeoutInfo, output, - sendSz, ssl->heap); + AddPacketInfo(ssl, "CertificateRequest", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); #endif ssl->buffers.outputBuffer.length += sendSz; if (ssl->options.groupMessages) - return 0; + ret = 0; else - return SendBuffered(ssl); + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendCertificateRequest", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND); + + return ret; } + +#ifndef NO_WOLFSSL_SERVER +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) +static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, + byte count) +{ + byte* output = NULL; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + word32 length = ENUM_LEN; + int sendSz = 0; + int ret = 0; + int i = 0; + + WOLFSSL_ENTER("BuildCertificateStatus"); + + switch (type) { + case WOLFSSL_CSR2_OCSP_MULTI: + length += OPAQUE24_LEN; + FALL_THROUGH; /* followed by */ + + case WOLFSSL_CSR2_OCSP: + for (i = 0; i < count; i++) + length += OPAQUE24_LEN + status[i].length; + break; + + default: + return 0; + } + + sendSz = idx + length; + + if (ssl->keys.encryptionOn) + sendSz += MAX_MSG_EXTRA; + + if ((ret = CheckAvailableSize(ssl, sendSz)) == 0) { + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(output, length, certificate_status, ssl); + + output[idx++] = type; + + if (type == WOLFSSL_CSR2_OCSP_MULTI) { + c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx); + idx += OPAQUE24_LEN; + } + + for (i = 0; i < count; i++) { + c32to24(status[i].length, output + idx); + idx += OPAQUE24_LEN; + + XMEMCPY(output + idx, status[i].buffer, status[i].length); + idx += status[i].length; + } + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = idx - RECORD_HEADER_SZ; + + 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, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + ret = sendSz; + } + else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, output, sendSz, 0); + } + + #ifdef WOLFSSL_DTLS + if (ret == 0 && IsDtlsNotSctpMode(ssl)) + ret = DtlsMsgPoolSave(ssl, output, sendSz); + #endif + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ret == 0 && ssl->hsInfoOn) + AddPacketName(ssl, "CertificateStatus"); + if (ret == 0 && ssl->toInfoOn) + AddPacketInfo(ssl, "CertificateStatus", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + #endif + + if (ret == 0) { + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + } + } + + WOLFSSL_LEAVE("BuildCertificateStatus", ret); + return ret; +} +#endif +#endif /* NO_WOLFSSL_SERVER */ + +/* handle generation of certificate_status (22) */ +int SendCertificateStatus(WOLFSSL* ssl) +{ + int ret = 0; + byte status_type = 0; + + WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_SEND); + WOLFSSL_ENTER("SendCertificateStatus"); + + (void) ssl; + +#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 + + switch (status_type) { + + #ifndef NO_WOLFSSL_SERVER + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + /* case WOLFSSL_CSR_OCSP: */ + case WOLFSSL_CSR2_OCSP: + { + OcspRequest* request = ssl->ctx->certOcspRequest; + buffer response; + + ret = CreateOcspResponse(ssl, &request, &response); + + /* if a request was successfully created and not stored in + * ssl->ctx then free it */ + if (ret == 0 && request != ssl->ctx->certOcspRequest) { + FreeOcspRequest(request); + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + } + + if (ret == 0 && response.buffer) { + ret = BuildCertificateStatus(ssl, status_type, &response, 1); + + XFREE(response.buffer, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + response.buffer = NULL; + } + break; + } + + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + + #if defined HAVE_CERTIFICATE_STATUS_REQUEST_V2 + case WOLFSSL_CSR2_OCSP_MULTI: + { + OcspRequest* request = ssl->ctx->certOcspRequest; + buffer responses[1 + MAX_CHAIN_DEPTH]; + int i = 0; + + XMEMSET(responses, 0, sizeof(responses)); + + ret = CreateOcspResponse(ssl, &request, &responses[0]); + + /* if a request was successfully created and not stored in + * ssl->ctx then free it */ + if (ret == 0 && request != ssl->ctx->certOcspRequest) { + FreeOcspRequest(request); + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + } + + if (ret == 0 && (!ssl->ctx->chainOcspRequest[0] + || ssl->buffers.weOwnCertChain)) { + buffer der; + word32 idx = 0; + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert; + #else + DecodedCert cert[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + #endif + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + if (request == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); + #endif + return MEMORY_E; + } + + while (idx + OPAQUE24_LEN < ssl->buffers.certChain->length) { + c24to32(ssl->buffers.certChain->buffer + idx, &der.length); + idx += OPAQUE24_LEN; + + der.buffer = ssl->buffers.certChain->buffer + idx; + idx += der.length; + + if (idx > ssl->buffers.certChain->length) + break; + + ret = CreateOcspRequest(ssl, request, cert, der.buffer, + der.length); + if (ret == 0) { + 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) { + ret = 0; + } + + + i++; + FreeOcspRequest(request); + } + } + + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + #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) { + ret = 0; + } + } + } + + if (responses[0].buffer) { + if (ret == 0) { + ret = BuildCertificateStatus(ssl, status_type, 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_OCSP_REQUEST); + } + } + } + + break; + } + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + #endif /* NO_WOLFSSL_SERVER */ + + default: + break; + } + + WOLFSSL_LEAVE("SendCertificateStatus", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_SEND); + + return ret; +} + #endif /* !NO_CERTS */ +#endif /* WOLFSSL_NO_TLS12 */ + + +/* If secure renegotiation is disabled, this will always return false. + * Otherwise it checks to see if we are currently renegotiating. */ +static WC_INLINE int IsSCR(WOLFSSL* ssl) +{ +#ifndef HAVE_SECURE_RENEGOTIATION + (void)ssl; +#else /* HAVE_SECURE_RENEGOTIATION */ + if (ssl->secure_renegotiation && + ssl->secure_renegotiation->enabled && + ssl->options.handShakeState != HANDSHAKE_DONE) + return 1; +#endif /* HAVE_SECURE_RENEGOTIATION */ + return 0; +} + int SendData(WOLFSSL* ssl, const void* data, int sz) { @@ -7445,24 +17163,66 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) sendSz, ret, dtlsExtra = 0; + int groupMsgs = 0; - if (ssl->error == WANT_WRITE) + if (ssl->error == WANT_WRITE + #ifdef WOLFSSL_ASYNC_CRYPT + || ssl->error == WC_PENDING_E + #endif + ) { ssl->error = 0; + } - if (ssl->options.handShakeState != HANDSHAKE_DONE) { + /* don't allow write after decrypt or mac error */ + if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR) { + /* For DTLS allow these possible errors and allow the session + to continue despite them */ + if (ssl->options.dtls) { + ssl->error = 0; + } + else { + WOLFSSL_MSG("Not allowing write after decrypt or mac error"); + return WOLFSSL_FATAL_ERROR; + } + } + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + if (ssl->options.handShakeState == HANDSHAKE_DONE) { + WOLFSSL_MSG("handshake complete, trying to send early data"); + return BUILD_MSG_ERROR; + } + #ifdef WOLFSSL_EARLY_DATA_GROUP + groupMsgs = 1; + #endif + } + else +#endif + if (ssl->options.handShakeState != HANDSHAKE_DONE && !IsSCR(ssl)) { 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_WRITE; + } + #endif return err; + } } /* last time system socket output buffer was full, try again to send */ - if (ssl->buffers.outputBuffer.length > 0) { + if (!groupMsgs && ssl->buffers.outputBuffer.length > 0) { WOLFSSL_MSG("output buffer was full, trying to send again"); if ( (ssl->error = SendBuffered(ssl)) < 0) { WOLFSSL_ERROR(ssl->error); - if (ssl->error == SOCKET_ERROR_E && ssl->options.connReset) - return 0; /* peer reset */ + if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset || + ssl->options.isClosed)) { + ssl->error = SOCKET_PEER_CLOSED_E; + WOLFSSL_ERROR(ssl->error); + return 0; /* peer reset or closed */ + } return ssl->error; } else { @@ -7484,14 +17244,10 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) #endif for (;;) { -#ifdef HAVE_MAX_FRAGMENT - int len = min(sz - sent, min(ssl->max_fragment, OUTPUT_RECORD_SIZE)); -#else - int len = min(sz - sent, OUTPUT_RECORD_SIZE); -#endif + int len; byte* out; byte* sendBuffer = (byte*)data + sent; /* may switch on comp */ - int buffSz = len; /* may switch on comp */ + int buffSz; /* may switch on comp */ int outputSz; #ifdef HAVE_LIBZ byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA]; @@ -7499,19 +17255,21 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) if (sent == sz) break; + len = wolfSSL_GetMaxRecordSize(ssl, sz - sent); + #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - len = min(len, MAX_UDP_SIZE); - buffSz = len; + if (IsDtlsNotSctpMode(ssl)) { + len = min(len, MAX_UDP_SIZE); } #endif + buffSz = len; /* check for available size */ outputSz = len + COMP_EXTRA + dtlsExtra + MAX_MSG_EXTRA; if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) return ssl->error = ret; - /* get ouput buffer */ + /* get output buffer */ out = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; @@ -7524,29 +17282,48 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) sendBuffer = comp; } #endif - sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz, - application_data); - 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; - if ( (ret = SendBuffered(ssl)) < 0) { - WOLFSSL_ERROR(ret); + if ( (ssl->error = SendBuffered(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); /* store for next call if WANT_WRITE or user embedSend() that doesn't present like WANT_WRITE */ ssl->buffers.plainSz = len; ssl->buffers.prevSent = sent; - if (ret == SOCKET_ERROR_E && ssl->options.connReset) - return 0; /* peer reset */ - return ssl->error = ret; + if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset || + ssl->options.isClosed)) { + ssl->error = SOCKET_PEER_CLOSED_E; + WOLFSSL_ERROR(ssl->error); + return 0; /* peer reset or closed */ + } + return ssl->error; } sent += len; /* only one message per attempt */ if (ssl->options.partialWrite == 1) { - WOLFSSL_MSG("Paritial Write on, only sending one record"); + WOLFSSL_MSG("Partial Write on, only sending one record"); break; } } @@ -7561,29 +17338,56 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) WOLFSSL_ENTER("ReceiveData()"); - if (ssl->error == WANT_READ) + /* reset error state */ + if (ssl->error == WANT_READ + #ifdef WOLFSSL_ASYNC_CRYPT + || ssl->error == WC_PENDING_E + #endif + ) { 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 */ if (ssl->error != 0 && ssl->error != WANT_WRITE) { WOLFSSL_MSG("User calling wolfSSL_read in error state, not allowed"); return ssl->error; } +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + } + 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; + } } #ifdef HAVE_SECURE_RENEGOTIATION startScr: if (ssl->secure_renegotiation && ssl->secure_renegotiation->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; + ssl->secure_renegotiation->startScr = 0; /* only start once */ } #endif @@ -7643,7 +17447,29 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) int outputSz; int dtlsExtra = 0; - /* if sendalert is called again for nonbloking */ + WOLFSSL_ENTER("SendAlert"); + +#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); if (ret == 0) @@ -7651,6 +17477,11 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) return ret; } + #ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_ALERT, type); + } + #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) dtlsExtra = DTLS_RECORD_EXTRA; @@ -7661,7 +17492,11 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) return ret; - /* get ouput buffer */ + /* Check output buffer */ + if (ssl->buffers.outputBuffer.buffer == NULL) + return BUFFER_E; + + /* get output buffer */ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; @@ -7675,8 +17510,11 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) /* only send encrypted alert if handshake actually complete, otherwise other side may not be able to handle it */ - if (ssl->keys.encryptionOn && ssl->options.handShakeDone) - sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, alert); + if (IsEncryptionOn(ssl, 1) && (IsAtLeastTLSv1_3(ssl->version) || + ssl->options.handShakeDone)) { + sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, alert, + 0, 0, 0); + } else { AddRecordHeader(output, ALERT_SIZE, alert, ssl); @@ -7696,17 +17534,22 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) if (sendSz < 0) return BUILD_MSG_ERROR; - #ifdef WOLFSSL_CALLBACKS + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) - AddPacketName("Alert", &ssl->handShakeInfo); + AddPacketName(ssl, "Alert"); if (ssl->toInfoOn) - AddPacketInfo("Alert", &ssl->timeoutInfo, output, sendSz,ssl->heap); + AddPacketInfo(ssl, "Alert", alert, output, sendSz, WRITE_PROTO, + ssl->heap); #endif ssl->buffers.outputBuffer.length += sendSz; ssl->options.sendAlertState = 1; - return SendBuffered(ssl); + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendAlert", ret); + + return ret; } const char* wolfSSL_ERR_reason_error_string(unsigned long e) @@ -7727,6 +17570,11 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) switch (error) { +#ifdef WOLFSSL_WPAS + case 0 : + return "ok"; +#endif + case UNSUPPORTED_SUITE : return "unsupported cipher suite"; @@ -7773,7 +17621,7 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) return "error during decryption"; case FATAL_ERROR : - return "revcd alert fatal error"; + return "received alert fatal error"; case ENCRYPT_ERROR : return "error during encryption"; @@ -7796,6 +17644,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case MATCH_SUITE_ERROR : return "can't match cipher suite"; + case COMPRESSION_ERROR : + return "compression mismatch error"; + case BUILD_MSG_ERROR : return "build message failure"; @@ -7805,21 +17656,21 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case DOMAIN_NAME_MISMATCH : return "peer subject name mismatch"; + case IPADDR_MISMATCH : + return "peer ip address 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 : @@ -7852,15 +17703,6 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case NTRU_DECRYPT_ERROR: return "NTRU decrypt error"; - case ZLIB_INIT_ERROR: - return "zlib init error"; - - case ZLIB_COMPRESS_ERROR: - return "zlib compress error"; - - case ZLIB_DECOMPRESS_ERROR: - return "zlib decompress error"; - case GETTIME_ERROR: return "gettimeofday() error"; @@ -7880,7 +17722,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: @@ -7904,8 +17746,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"; @@ -7919,8 +17761,8 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case CRL_MISSING: return "CRL missing, not loaded"; - case MONITOR_RUNNING_E: - return "CRL monitor already running"; + case MONITOR_SETUP_E: + return "CRL monitor setup error"; case THREAD_CREATE_E: return "Thread creation problem"; @@ -7946,9 +17788,6 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case SUITES_ERROR: return "Suites Pointer Error"; - case SSL_NO_PEM_HEADER: - return "No PEM Header Error"; - case OUT_OF_ORDER_E: return "Out of order message, fatal"; @@ -7976,6 +17815,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case UNKNOWN_SNI_HOST_NAME_E: return "Unrecognized host name Error"; + case UNKNOWN_MAX_FRAG_LEN_E: + return "Unrecognized max frag len Error"; + case KEYUSE_SIGNATURE_E: return "Key Use digitalSignature not set Error"; @@ -7997,9 +17839,6 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case SESSION_TICKET_EXPECT_E: return "Session Ticket Error"; - case SCR_DIFFERENT_CERT_E: - return "Peer sent different cert during SCR"; - case SESSION_SECRET_CB_E: return "Session Secret Callback Error"; @@ -8030,6 +17869,123 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case DH_KEY_SIZE_E: return "DH key too small Error"; + case SNI_ABSENT_ERROR: + return "No Server Name Indication extension Error"; + + case RSA_SIGN_FAULT: + return "RSA Signature Fault Error"; + + case HANDSHAKE_SIZE_ERROR: + return "Handshake message too large Error"; + + case UNKNOWN_ALPN_PROTOCOL_NAME_E: + return "Unrecognized protocol name Error"; + + case BAD_CERTIFICATE_STATUS_ERROR: + return "Bad Certificate Status Message Error"; + + 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"; + + case ECC_KEY_SIZE_E: + return "ECC key too small"; + + case DTLS_EXPORT_VER_E: + return "Version needs updated after code change or version mismatch"; + + case INPUT_SIZE_E: + return "Input size too large Error"; + + case CTX_INIT_MUTEX_E: + return "Initialize ctx mutex error"; + + case EXT_MASTER_SECRET_NEEDED_E: + return "Extended Master Secret must be enabled to resume EMS session"; + + case DTLS_POOL_SZ_E: + return "Maximum DTLS pool size exceeded"; + + 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 wasn't 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 PRF_MISSING: + return "Pseudo-random function is not enabled"; + + 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"; + + case DTLS_RETX_OVER_TX: + return "DTLS interrupting flight transmit with retransmit"; + + case DH_PARAMS_NOT_FFDHE_E: + return "Server DH parameters were not from the FFDHE set as required"; + + case TCA_INVALID_ID_TYPE: + return "TLS Extension Trusted CA ID type invalid"; + + case TCA_ABSENT_ERROR: + return "TLS Extension Trusted CA ID response absent"; + + case TSIP_MAC_DIGSZ_E: + return "TSIP MAC size invalid, must be sized for SHA-1 or SHA-256"; + + case CLIENT_CERT_CB_ERROR: + return "Error importing client cert or key from callback"; + + case SSL_SHUTDOWN_ALREADY_DONE_E: + return "Shutdown has already occurred"; + + case TLS13_SECRET_CB_E: + return "TLS1.3 Secret Callback Error"; + default : return "unknown error number"; } @@ -8040,820 +17996,789 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) void SetErrorString(int error, char* str) { XSTRNCPY(str, wolfSSL_ERR_reason_error_string(error), WOLFSSL_MAX_ERROR_SZ); + str[WOLFSSL_MAX_ERROR_SZ-1] = 0; } +#ifndef NO_ERROR_STRINGS + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + #define SUITE_INFO(x,y,z,w,v,u) {(x),(y),(z),(w),(v),(u)} + #else + #define SUITE_INFO(x,y,z,w,v,u) {(x),(y),(z),(w)} + #endif +#else + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + #define SUITE_INFO(x,y,z,w,v,u) {(x),(z),(w),(v),(u)} + #else + #define SUITE_INFO(x,y,z,w,v,u) {(x),(z),(w)} + #endif +#endif -/* be sure to add to cipher_name_idx too !!!! */ -static const char* const cipher_names[] = +static const CipherSuiteInfo cipher_names[] = { + +#ifdef BUILD_TLS_AES_128_GCM_SHA256 + SUITE_INFO("TLS13-AES128-GCM-SHA256","TLS_AES_128_GCM_SHA256",TLS13_BYTE,TLS_AES_128_GCM_SHA256, TLSv1_3_MINOR, SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_AES_256_GCM_SHA384 + SUITE_INFO("TLS13-AES256-GCM-SHA384","TLS_AES_256_GCM_SHA384",TLS13_BYTE,TLS_AES_256_GCM_SHA384, TLSv1_3_MINOR, SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + SUITE_INFO("TLS13-CHACHA20-POLY1305-SHA256","TLS_CHACHA20_POLY1305_SHA256",TLS13_BYTE,TLS_CHACHA20_POLY1305_SHA256, TLSv1_3_MINOR, SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_AES_128_CCM_SHA256 + SUITE_INFO("TLS13-AES128-CCM-SHA256","TLS_AES_128_CCM_SHA256",TLS13_BYTE,TLS_AES_128_CCM_SHA256, TLSv1_3_MINOR, SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + SUITE_INFO("TLS13-AES128-CCM-8-SHA256","TLS_AES_128_CCM_8_SHA256",TLS13_BYTE,TLS_AES_128_CCM_8_SHA256,TLSv1_3_MINOR, SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_SHA256_SHA256 + SUITE_INFO("TLS13-SHA256-SHA256","TLS_SHA256_SHA256",ECC_BYTE,TLS_SHA256_SHA256,TLSv1_3_MINOR, SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_SHA384_SHA384 + SUITE_INFO("TLS13-SHA384-SHA384","TLS_SHA384_SHA384",ECC_BYTE,TLS_SHA384_SHA384,TLSv1_3_MINOR, SSLv3_MAJOR), +#endif + +#ifndef WOLFSSL_NO_TLS12 + #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA - "RC4-SHA", + SUITE_INFO("RC4-SHA","SSL_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_SHA,SSLv3_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5 - "RC4-MD5", + SUITE_INFO("RC4-MD5","SSL_RSA_WITH_RC4_128_MD5",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_MD5,SSLv3_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA - "DES-CBC3-SHA", + SUITE_INFO("DES-CBC3-SHA","SSL_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_3DES_EDE_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA - "AES128-SHA", + SUITE_INFO("AES128-SHA","TLS_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA - "AES256-SHA", + SUITE_INFO("AES256-SHA","TLS_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_MD5 + SUITE_INFO("NULL-MD5","TLS_RSA_WITH_NULL_MD5",CIPHER_BYTE,TLS_RSA_WITH_NULL_MD5,SSLv3_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_NULL_SHA - "NULL-SHA", + SUITE_INFO("NULL-SHA","TLS_RSA_WITH_NULL_SHA",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA,SSLv3_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_NULL_SHA256 - "NULL-SHA256", + SUITE_INFO("NULL-SHA256","TLS_RSA_WITH_NULL_SHA256",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA - "DHE-RSA-AES128-SHA", + SUITE_INFO("DHE-RSA-AES128-SHA","TLS_DHE_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA - "DHE-RSA-AES256-SHA", + SUITE_INFO("DHE-RSA-AES256-SHA","TLS_DHE_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 - "DHE-PSK-AES256-GCM-SHA384", + SUITE_INFO("DHE-PSK-AES256-GCM-SHA384","TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,TLSv1_2_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 - "DHE-PSK-AES128-GCM-SHA256", + SUITE_INFO("DHE-PSK-AES128-GCM-SHA256","TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384 - "PSK-AES256-GCM-SHA384", + SUITE_INFO("PSK-AES256-GCM-SHA384","TLS_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_GCM_SHA384,TLSv1_2_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 - "PSK-AES128-GCM-SHA256", + SUITE_INFO("PSK-AES128-GCM-SHA256","TLS_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_GCM_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - "DHE-PSK-AES256-CBC-SHA384", + SUITE_INFO("DHE-PSK-AES256-CBC-SHA384","TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - "DHE-PSK-AES128-CBC-SHA256", + SUITE_INFO("DHE-PSK-AES128-CBC-SHA256","TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 - "PSK-AES256-CBC-SHA384", + SUITE_INFO("PSK-AES256-CBC-SHA384","TLS_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA384,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 - "PSK-AES128-CBC-SHA256", + SUITE_INFO("PSK-AES128-CBC-SHA256","TLS_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA - "PSK-AES128-CBC-SHA", + SUITE_INFO("PSK-AES128-CBC-SHA","TLS_PSK_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA - "PSK-AES256-CBC-SHA", + SUITE_INFO("PSK-AES256-CBC-SHA","TLS_PSK_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM - "DHE-PSK-AES128-CCM", + SUITE_INFO("DHE-PSK-AES128-CCM","TLS_DHE_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_128_CCM,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM - "DHE-PSK-AES256-CCM", + SUITE_INFO("DHE-PSK-AES256-CCM","TLS_DHE_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_256_CCM,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_CCM - "PSK-AES128-CCM", + SUITE_INFO("PSK-AES128-CCM","TLS_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_CCM - "PSK-AES256-CCM", + SUITE_INFO("PSK-AES256-CCM","TLS_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8 - "PSK-AES128-CCM-8", + SUITE_INFO("PSK-AES128-CCM-8","TLS_PSK_WITH_AES_128_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM_8,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8 - "PSK-AES256-CCM-8", + SUITE_INFO("PSK-AES256-CCM-8","TLS_PSK_WITH_AES_256_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM_8,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384 - "DHE-PSK-NULL-SHA384", + SUITE_INFO("DHE-PSK-NULL-SHA384","TLS_DHE_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA384,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256 - "DHE-PSK-NULL-SHA256", + SUITE_INFO("DHE-PSK-NULL-SHA256","TLS_DHE_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA256,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_NULL_SHA384 - "PSK-NULL-SHA384", + SUITE_INFO("PSK-NULL-SHA384","TLS_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA384,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_NULL_SHA256 - "PSK-NULL-SHA256", + SUITE_INFO("PSK-NULL-SHA256","TLS_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA256,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_PSK_WITH_NULL_SHA - "PSK-NULL-SHA", + SUITE_INFO("PSK-NULL-SHA","TLS_PSK_WITH_NULL_SHA",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_HC_128_MD5 - "HC128-MD5", + SUITE_INFO("HC128-MD5","TLS_RSA_WITH_HC_128_MD5",CIPHER_BYTE,TLS_RSA_WITH_HC_128_MD5,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_HC_128_SHA - "HC128-SHA", -#endif - -#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256 - "HC128-B2B256", -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256 - "AES128-B2B256", -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256 - "AES256-B2B256", + SUITE_INFO("HC128-SHA","TLS_RSA_WITH_HC_128_SHA",CIPHER_BYTE,TLS_RSA_WITH_HC_128_SHA,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA - "RABBIT-SHA", + SUITE_INFO("RABBIT-SHA","TLS_RSA_WITH_RABBIT_SHA",CIPHER_BYTE,TLS_RSA_WITH_RABBIT_SHA,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA - "NTRU-RC4-SHA", + SUITE_INFO("NTRU-RC4-SHA","TLS_NTRU_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA - "NTRU-DES-CBC3-SHA", + SUITE_INFO("NTRU-DES-CBC3-SHA","TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA - "NTRU-AES128-SHA", + SUITE_INFO("NTRU-AES128-SHA","TLS_NTRU_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_128_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA - "NTRU-AES256-SHA", + SUITE_INFO("NTRU-AES256-SHA","TLS_NTRU_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8 - "AES128-CCM-8", + SUITE_INFO("AES128-CCM-8","TLS_RSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_128_CCM_8, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8 - "AES256-CCM-8", + SUITE_INFO("AES256-CCM-8","TLS_RSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_256_CCM_8, TLSv1_2_MINOR, SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM + SUITE_INFO("ECDHE-ECDSA-AES128-CCM","TLS_ECDHE_ECDSA_WITH_AES_128_CCM",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 - "ECDHE-ECDSA-AES128-CCM-8", + SUITE_INFO("ECDHE-ECDSA-AES128-CCM-8","TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 - "ECDHE-ECDSA-AES256-CCM-8", + SUITE_INFO("ECDHE-ECDSA-AES256-CCM-8","TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - "ECDHE-RSA-AES128-SHA", + SUITE_INFO("ECDHE-RSA-AES128-SHA","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - "ECDHE-RSA-AES256-SHA", + SUITE_INFO("ECDHE-RSA-AES256-SHA","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - "ECDHE-ECDSA-AES128-SHA", + SUITE_INFO("ECDHE-ECDSA-AES128-SHA","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - "ECDHE-ECDSA-AES256-SHA", + SUITE_INFO("ECDHE-ECDSA-AES256-SHA","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA - "ECDHE-RSA-RC4-SHA", + SUITE_INFO("ECDHE-RSA-RC4-SHA","TLS_ECDHE_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - "ECDHE-RSA-DES-CBC3-SHA", + SUITE_INFO("ECDHE-RSA-DES-CBC3-SHA","TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - "ECDHE-ECDSA-RC4-SHA", + SUITE_INFO("ECDHE-ECDSA-RC4-SHA","TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - "ECDHE-ECDSA-DES-CBC3-SHA", + SUITE_INFO("ECDHE-ECDSA-DES-CBC3-SHA","TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 - "AES128-SHA256", + SUITE_INFO("AES128-SHA256","TLS_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA256, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 - "AES256-SHA256", + SUITE_INFO("AES256-SHA256","TLS_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - "DHE-RSA-AES128-SHA256", + SUITE_INFO("DHE-RSA-AES128-SHA256","TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - "DHE-RSA-AES256-SHA256", + SUITE_INFO("DHE-RSA-AES256-SHA256","TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - "ECDH-RSA-AES128-SHA", + SUITE_INFO("ECDH-RSA-AES128-SHA","TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - "ECDH-RSA-AES256-SHA", + SUITE_INFO("ECDH-RSA-AES256-SHA","TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - "ECDH-ECDSA-AES128-SHA", + SUITE_INFO("ECDH-ECDSA-AES128-SHA","TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - "ECDH-ECDSA-AES256-SHA", + SUITE_INFO("ECDH-ECDSA-AES256-SHA","TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA - "ECDH-RSA-RC4-SHA", + SUITE_INFO("ECDH-RSA-RC4-SHA","TLS_ECDH_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - "ECDH-RSA-DES-CBC3-SHA", + SUITE_INFO("ECDH-RSA-DES-CBC3-SHA","TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA - "ECDH-ECDSA-RC4-SHA", + SUITE_INFO("ECDH-ECDSA-RC4-SHA","TLS_ECDH_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - "ECDH-ECDSA-DES-CBC3-SHA", + SUITE_INFO("ECDH-ECDSA-DES-CBC3-SHA","TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 - "AES128-GCM-SHA256", + SUITE_INFO("AES128-GCM-SHA256","TLS_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 - "AES256-GCM-SHA384", + SUITE_INFO("AES256-GCM-SHA384","TLS_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_RSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - "DHE-RSA-AES128-GCM-SHA256", + SUITE_INFO("DHE-RSA-AES128-GCM-SHA256","TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - "DHE-RSA-AES256-GCM-SHA384", + SUITE_INFO("DHE-RSA-AES256-GCM-SHA384","TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - "ECDHE-RSA-AES128-GCM-SHA256", + SUITE_INFO("ECDHE-RSA-AES128-GCM-SHA256","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - "ECDHE-RSA-AES256-GCM-SHA384", + SUITE_INFO("ECDHE-RSA-AES256-GCM-SHA384","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - "ECDHE-ECDSA-AES128-GCM-SHA256", + SUITE_INFO("ECDHE-ECDSA-AES128-GCM-SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - "ECDHE-ECDSA-AES256-GCM-SHA384", + SUITE_INFO("ECDHE-ECDSA-AES256-GCM-SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - "ECDH-RSA-AES128-GCM-SHA256", + SUITE_INFO("ECDH-RSA-AES128-GCM-SHA256","TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - "ECDH-RSA-AES256-GCM-SHA384", + SUITE_INFO("ECDH-RSA-AES256-GCM-SHA384","TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - "ECDH-ECDSA-AES128-GCM-SHA256", + SUITE_INFO("ECDH-ECDSA-AES128-GCM-SHA256","TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - "ECDH-ECDSA-AES256-GCM-SHA384", + SUITE_INFO("ECDH-ECDSA-AES256-GCM-SHA384","TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - "CAMELLIA128-SHA", + SUITE_INFO("CAMELLIA128-SHA","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - "DHE-RSA-CAMELLIA128-SHA", + SUITE_INFO("DHE-RSA-CAMELLIA128-SHA","TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - "CAMELLIA256-SHA", + SUITE_INFO("CAMELLIA256-SHA","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - "DHE-RSA-CAMELLIA256-SHA", + SUITE_INFO("DHE-RSA-CAMELLIA256-SHA","TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 - "CAMELLIA128-SHA256", + SUITE_INFO("CAMELLIA128-SHA256","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - "DHE-RSA-CAMELLIA128-SHA256", + SUITE_INFO("DHE-RSA-CAMELLIA128-SHA256","TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 - "CAMELLIA256-SHA256", + SUITE_INFO("CAMELLIA256-SHA256","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - "DHE-RSA-CAMELLIA256-SHA256", + SUITE_INFO("DHE-RSA-CAMELLIA256-SHA256","TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - "ECDHE-RSA-AES128-SHA256", + SUITE_INFO("ECDHE-RSA-AES128-SHA256","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - "ECDHE-ECDSA-AES128-SHA256", + SUITE_INFO("ECDHE-ECDSA-AES128-SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 - "ECDH-RSA-AES128-SHA256", + SUITE_INFO("ECDH-RSA-AES128-SHA256","TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 - "ECDH-ECDSA-AES128-SHA256", + SUITE_INFO("ECDH-ECDSA-AES128-SHA256","TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - "ECDHE-RSA-AES256-SHA384", + SUITE_INFO("ECDHE-RSA-AES256-SHA384","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - "ECDHE-ECDSA-AES256-SHA384", + SUITE_INFO("ECDHE-ECDSA-AES256-SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 - "ECDH-RSA-AES256-SHA384", + SUITE_INFO("ECDH-RSA-AES256-SHA384","TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 - "ECDH-ECDSA-AES256-SHA384", + SUITE_INFO("ECDH-ECDSA-AES256-SHA384","TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - "ECDHE-RSA-CHACHA20-POLY1305", + SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305","TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 - "ECDHE-ECDSA-CHACHA20-POLY1305", + SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305","TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - "DHE-RSA-CHACHA20-POLY1305", + SUITE_INFO("DHE-RSA-CHACHA20-POLY1305","TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305-OLD","TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305-OLD","TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + SUITE_INFO("DHE-RSA-CHACHA20-POLY1305-OLD","TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256, TLSv1_2_MINOR, SSLv3_MAJOR), #endif #ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA - "ADH-AES128-SHA", + SUITE_INFO("ADH-AES128-SHA","TLS_DH_anon_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DH_anon_WITH_AES_128_CBC_SHA, TLSv1_2_MINOR, SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384 + SUITE_INFO("ADH-AES256-GCM-SHA384","TLS_DH_anon_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DH_anon_WITH_AES_256_GCM_SHA384, TLSv1_2_MINOR, SSLv3_MAJOR), +#endif + +#ifdef BUILD_TLS_QSH + SUITE_INFO("QSH","TLS_QSH",QSH_BYTE,TLS_QSH, TLSv1_MINOR, SSLv3_MAJOR), #endif #ifdef HAVE_RENEGOTIATION_INDICATION - "RENEGOTIATION-INFO", + SUITE_INFO("RENEGOTIATION-INFO","TLS_EMPTY_RENEGOTIATION_INFO_SCSV",CIPHER_BYTE,TLS_EMPTY_RENEGOTIATION_INFO_SCSV,SSLv3_MINOR,SSLv3_MAJOR), #endif -}; - -/* cipher suite number that matches above name table */ -static int cipher_name_idx[] = -{ - -#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA - SSL_RSA_WITH_RC4_128_SHA, -#endif - -#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5 - SSL_RSA_WITH_RC4_128_MD5, -#endif - -#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA - SSL_RSA_WITH_3DES_EDE_CBC_SHA, -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA - TLS_RSA_WITH_AES_128_CBC_SHA, -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA - TLS_RSA_WITH_AES_256_CBC_SHA, -#endif - -#ifdef BUILD_TLS_RSA_WITH_NULL_SHA - TLS_RSA_WITH_NULL_SHA, +#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA + SUITE_INFO("IDEA-CBC-SHA","SSL_RSA_WITH_IDEA_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_IDEA_CBC_SHA,SSLv3_MINOR,SSLv3_MAJOR), #endif -#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256 - TLS_RSA_WITH_NULL_SHA256, +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA + SUITE_INFO("ECDHE-ECDSA-NULL-SHA","TLS_ECDHE_ECDSA_WITH_NULL_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif -#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA - TLS_DHE_RSA_WITH_AES_128_CBC_SHA, +#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256 + SUITE_INFO("ECDHE-PSK-NULL-SHA256","TLS_ECDHE_PSK_WITH_NULL_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_NULL_SHA256,TLSv1_MINOR,SSLv3_MAJOR), #endif -#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA - TLS_DHE_RSA_WITH_AES_256_CBC_SHA, +#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + SUITE_INFO("ECDHE-PSK-AES128-CBC-SHA256","TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,TLSv1_MINOR,SSLv3_MAJOR), #endif -#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 - TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, +#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 + SUITE_INFO("PSK-CHACHA20-POLY1305","TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR), #endif -#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 - TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, +#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + SUITE_INFO("ECDHE-PSK-CHACHA20-POLY1305","TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR), #endif -#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384 - TLS_PSK_WITH_AES_256_GCM_SHA384, +#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + SUITE_INFO("DHE-PSK-CHACHA20-POLY1305","TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,TLSv1_2_MINOR,SSLv3_MAJOR), #endif -#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 - TLS_PSK_WITH_AES_128_GCM_SHA256, +#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + SUITE_INFO("EDH-RSA-DES-CBC3-SHA","TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, TLSv1_MINOR, SSLv3_MAJOR), #endif -#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, +#ifdef BUILD_WDM_WITH_NULL_SHA256 + SUITE_INFO("WDM-NULL-SHA256","WDM_WITH_NULL_SHA256",CIPHER_BYTE,WDM_WITH_NULL_SHA256, TLSv1_3_MINOR, SSLv3_MAJOR) #endif -#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 - TLS_PSK_WITH_AES_256_CBC_SHA384, -#endif - -#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 - TLS_PSK_WITH_AES_128_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA - TLS_PSK_WITH_AES_128_CBC_SHA, -#endif - -#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA - TLS_PSK_WITH_AES_256_CBC_SHA, -#endif - -#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM - TLS_DHE_PSK_WITH_AES_128_CCM, -#endif - -#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM - TLS_DHE_PSK_WITH_AES_256_CCM, -#endif - -#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM - TLS_PSK_WITH_AES_128_CCM, -#endif - -#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM - TLS_PSK_WITH_AES_256_CCM, -#endif - -#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8 - TLS_PSK_WITH_AES_128_CCM_8, -#endif - -#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8 - TLS_PSK_WITH_AES_256_CCM_8, -#endif - -#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384 - TLS_DHE_PSK_WITH_NULL_SHA384, -#endif - -#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256 - TLS_DHE_PSK_WITH_NULL_SHA256, -#endif - -#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384 - TLS_PSK_WITH_NULL_SHA384, -#endif - -#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256 - TLS_PSK_WITH_NULL_SHA256, -#endif - -#ifdef BUILD_TLS_PSK_WITH_NULL_SHA - TLS_PSK_WITH_NULL_SHA, -#endif - -#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5 - TLS_RSA_WITH_HC_128_MD5, -#endif - -#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA - TLS_RSA_WITH_HC_128_SHA, -#endif - -#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256 - TLS_RSA_WITH_HC_128_B2B256, -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256 - TLS_RSA_WITH_AES_128_CBC_B2B256, -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256 - TLS_RSA_WITH_AES_256_CBC_B2B256, -#endif - -#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA - TLS_RSA_WITH_RABBIT_SHA, -#endif - -#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA - TLS_NTRU_RSA_WITH_RC4_128_SHA, -#endif - -#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA - TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA, -#endif - -#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA - TLS_NTRU_RSA_WITH_AES_128_CBC_SHA, -#endif - -#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA - TLS_NTRU_RSA_WITH_AES_256_CBC_SHA, -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8 - TLS_RSA_WITH_AES_128_CCM_8, -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8 - TLS_RSA_WITH_AES_256_CCM_8, -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 - TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 - TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, -#endif - -#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, -#endif - -#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, -#endif - -#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA - TLS_ECDHE_RSA_WITH_RC4_128_SHA, -#endif - -#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 - TLS_RSA_WITH_AES_128_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 - TLS_RSA_WITH_AES_256_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA - TLS_ECDH_RSA_WITH_RC4_128_SHA, -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA - TLS_ECDH_ECDSA_WITH_RC4_128_SHA, -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 - TLS_RSA_WITH_AES_128_GCM_SHA256, -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 - TLS_RSA_WITH_AES_256_GCM_SHA384, -#endif - -#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, -#endif - -#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, -#endif - -#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, -#endif - -#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, -#endif - -#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, -#endif - -#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, -#endif - -#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, -#endif - -#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, -#endif - -#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 - TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 - TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 - TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 - TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, -#endif - -#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 - TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 - TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, -#endif - -#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, -#endif - -#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, -#endif - -#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA - TLS_DH_anon_WITH_AES_128_CBC_SHA, -#endif - -#ifdef HAVE_RENEGOTIATION_INDICATION - TLS_EMPTY_RENEGOTIATION_INFO_SCSV, -#endif +#endif /* WOLFSSL_NO_TLS12 */ }; /* returns the cipher_names array */ -const char* const* GetCipherNames(void) +const CipherSuiteInfo* GetCipherNames(void) { return cipher_names; } -/* returns the size of the cipher_names array */ +/* returns the number of elements in the cipher_names array */ int GetCipherNamesSize(void) { - return (int)(sizeof(cipher_names) / sizeof(char*)); + return (int)(sizeof(cipher_names) / sizeof(CipherSuiteInfo)); } +const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite) +{ + int i; + const char* nameInternal = "None"; + + for (i = 0; i < GetCipherNamesSize(); i++) { + if ((cipher_names[i].cipherSuite0 == cipherSuite0) && + (cipher_names[i].cipherSuite == cipherSuite)) { + nameInternal = cipher_names[i].name; + break; + } + } + return nameInternal; +} + +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +const char* GetCipherKeaStr(char n[][MAX_SEGMENT_SZ]) { + const char* keaStr = NULL; + const char *n0,*n1,*n2,*n3,*n4; + n0 = n[0]; + n1 = n[1]; + n2 = n[2]; + n3 = n[3]; + n4 = n[4]; + + if (XSTRNCMP(n0,"ECDHE",5) == 0 && XSTRNCMP(n1,"PSK",3) == 0) + keaStr = "ECDHEPSK"; + else if (XSTRNCMP(n0,"ECDH",4) == 0) + keaStr = "ECDH"; + else if (XSTRNCMP(n0,"DHE",3) == 0 && XSTRNCMP(n1,"PSK",3) == 0) + keaStr = "DHEPSK"; + else if (XSTRNCMP(n0,"DHE",3) == 0) + keaStr = "DH"; + else if (XSTRNCMP(n0,"RSA",3) == 0 && XSTRNCMP(n1,"PSK",3) == 0) + keaStr = "RSAPSK"; + else if (XSTRNCMP(n0,"SRP",3) == 0) + keaStr = "SRP"; + else if (XSTRNCMP(n0,"PSK",3) == 0) + keaStr = "PSK"; + else if (XSTRNCMP(n0,"EDH",3) == 0) + keaStr = "EDH"; + else if ((XSTRNCMP(n1,"SHA",3) == 0) || (XSTRNCMP(n2,"SHA",3) == 0) || + (XSTRNCMP(n3,"SHA",3) == 0) || (XSTRNCMP(n4,"SHA",3) == 0) || + (XSTRNCMP(n2,"RSA",3) == 0) || (XSTRNCMP(n0,"AES128",6) == 0) || + (XSTRNCMP(n0,"AES256",6) == 0) || (XSTRNCMP(n1,"MD5",3) == 0)) + keaStr = "RSA"; + else + keaStr = "unknown"; + + return keaStr; +} + +const char* GetCipherAuthStr(char n[][MAX_SEGMENT_SZ]) { + + const char* authStr = NULL; + const char *n0,*n1,*n2; + n0 = n[0]; + n1 = n[1]; + n2 = n[2]; + + if ((XSTRNCMP(n0,"AES128",6) == 0) || (XSTRNCMP(n0,"AES256",6) == 0) || + ((XSTRNCMP(n0,"TLS13",5) == 0) && ((XSTRNCMP(n1,"AES128",6) == 0) || + (XSTRNCMP(n1,"AES256",6) == 0) || (XSTRNCMP(n1,"CHACHA20",8) == 0))) || + (XSTRNCMP(n0,"RSA",3) == 0) || (XSTRNCMP(n1,"RSA",3) == 0) || + (XSTRNCMP(n1,"SHA",3) == 0) || (XSTRNCMP(n2,"SHA",3) == 0) || + (XSTRNCMP(n1,"MD5",3) == 0)) + authStr = "RSA"; + else if (XSTRNCMP(n0,"PSK",3) == 0 || XSTRNCMP(n1,"PSK",3) == 0) + authStr = "PSK"; + else if (XSTRNCMP(n0,"SRP",3) == 0 && XSTRNCMP(n1,"AES",3) == 0) + authStr = "SRP"; + else if (XSTRNCMP(n1,"ECDSA",5) == 0) + authStr = "ECDSA"; + else + authStr = "unknown"; + + return authStr; +} + +const char* GetCipherEncStr(char n[][MAX_SEGMENT_SZ]) { + const char* encStr = NULL; + const char *n0,*n1,*n2,*n3; + n0 = n[0]; + n1 = n[1]; + n2 = n[2]; + n3 = n[3]; + + if ((XSTRNCMP(n0,"AES256",6) == 0 && XSTRNCMP(n1,"GCM",3) == 0) || + (XSTRNCMP(n1,"AES256",6) == 0 && XSTRNCMP(n2,"GCM",3) == 0) || + (XSTRNCMP(n2,"AES256",6) == 0 && XSTRNCMP(n3,"GCM",3) == 0)) + encStr = "AESGCM(256)"; + + else if ((XSTRNCMP(n0,"AES128",6) == 0 && XSTRNCMP(n1,"GCM",3) == 0) || + (XSTRNCMP(n1,"AES128",6) == 0 && XSTRNCMP(n2,"GCM",3) == 0) || + (XSTRNCMP(n2,"AES128",6) == 0 && XSTRNCMP(n3,"GCM",3) == 0)) + encStr = "AESGCM(128)"; + + else if ((XSTRNCMP(n0,"AES128",6) == 0 && XSTRNCMP(n1,"CCM",3) == 0) || + (XSTRNCMP(n1,"AES128",6) == 0 && XSTRNCMP(n2,"CCM",3) == 0) || + (XSTRNCMP(n2,"AES128",6) == 0 && XSTRNCMP(n3,"CCM",3) == 0)) + encStr = "AESCCM(128)"; + + else if ((XSTRNCMP(n0,"AES128",6) == 0) || + (XSTRNCMP(n1,"AES128",6) == 0) || + (XSTRNCMP(n2,"AES128",6) == 0) || + (XSTRNCMP(n1,"AES",3) == 0 && XSTRNCMP(n2,"128",3) == 0) || + (XSTRNCMP(n2,"AES",3) == 0 && XSTRNCMP(n3,"128",3) == 0)) + encStr = "AES(128)"; + + else if ((XSTRNCMP(n0,"AES256",6) == 0) || + (XSTRNCMP(n1,"AES256",6) == 0) || + (XSTRNCMP(n2,"AES256",6) == 0) || + (XSTRNCMP(n1,"AES",3) == 0 && XSTRNCMP(n2,"256",3) == 0) || + (XSTRNCMP(n2,"AES",3) == 0 && XSTRNCMP(n3,"256",3) == 0)) + encStr = "AES(256)"; + + else if ((XSTRNCMP(n0,"CAMELLIA256",11) == 0) || + (XSTRNCMP(n2,"CAMELLIA256",11) == 0)) + encStr = "CAMELLIA(256)"; + else if ((XSTRNCMP(n0,"CAMELLIA128",11) == 0) || + (XSTRNCMP(n2,"CAMELLIA128",11) == 0)) + encStr = "CAMELLIA(128)"; + else if ((XSTRNCMP(n0,"RC4",3) == 0) || (XSTRNCMP(n2,"RC4",3) == 0)) + encStr = "RC4"; + else if (((XSTRNCMP(n0,"DES",3) == 0) || (XSTRNCMP(n2,"DES",3) == 0)) && + ((XSTRNCMP(n1,"CBC3",4) == 0) || (XSTRNCMP(n3,"CBC3",4) == 0))) + encStr = "3DES"; + else if ((XSTRNCMP(n1,"CHACHA20",8) == 0 && XSTRNCMP(n2,"POLY1305",8) == 0) || + (XSTRNCMP(n2,"CHACHA20",8) == 0 && XSTRNCMP(n3,"POLY1305",8) == 0)) + encStr = "CHACHA20/POLY1305(256)"; + else if ((XSTRNCMP(n0,"NULL",4) == 0) || (XSTRNCMP(n1,"NULL",4) == 0) || + (XSTRNCMP(n2,"NULL",4) == 0) || + ((XSTRNCMP(n0,"TLS13",5) == 0) && (XSTRNCMP(n3,"",0) == 0))) + encStr = "None"; + else if ((XSTRNCMP(n0,"IDEA",4) == 0)) + encStr = "IDEA"; + else if ((XSTRNCMP(n0,"RABBIT",4) == 0)) + encStr = "RABBIT"; + else if ((XSTRNCMP(n0,"HC128",5) == 0)) + encStr = "HC128"; + else + encStr = "unknown"; + + return encStr; +} + +/* Returns the MAC string of a cipher or "unknown" on failure */ +const char* GetCipherMacStr(char n[][MAX_SEGMENT_SZ]) { + + const char* macStr = NULL; + const char *n1,*n2,*n3,*n4; + n1 = n[1]; + n2 = n[2]; + n3 = n[3]; + n4 = n[4]; + + if ((XSTRNCMP(n4,"SHA256",6) == 0) || (XSTRNCMP(n3,"SHA256",6) == 0) || + (XSTRNCMP(n2,"SHA256",6) == 0) || (XSTRNCMP(n1,"SHA256",6) == 0)) + macStr = "SHA256"; + else if ((XSTRNCMP(n4,"SHA384",6) == 0) || + (XSTRNCMP(n3,"SHA384",6) == 0) || + (XSTRNCMP(n2,"SHA384",6) == 0) || + (XSTRNCMP(n1,"SHA384",6) == 0)) + macStr = "SHA384"; + else if ((XSTRNCMP(n4,"SHA",3) == 0) || (XSTRNCMP(n3,"SHA",3) == 0) || + (XSTRNCMP(n2,"SHA",3) == 0) || (XSTRNCMP(n1,"SHA",3) == 0) || + (XSTRNCMP(n1,"MD5",3) == 0)) + macStr = "SHA1"; + else if ((XSTRNCMP(n3,"GCM",3) == 0) || + (XSTRNCMP(n1,"CCM",3) == 0) || + (XSTRNCMP(n2,"CCM",3) == 0) || (XSTRNCMP(n3,"CCM",3) == 0) || + (XSTRNCMP(n1,"CHACHA20",8) == 0 && XSTRNCMP(n2,"POLY1305",8) == 0) || + (XSTRNCMP(n2,"CHACHA20",8) == 0 && XSTRNCMP(n3,"POLY1305",8) == 0)) + macStr = "AEAD"; + else + macStr = "unknown"; + + return macStr; +} + +/* Returns the number of bits based on the cipher enc string, or 0 on failure */ +int SetCipherBits(const char* enc) { + int ret = WOLFSSL_FAILURE; + + if ((XSTRNCMP(enc,"AESGCM(256)",11) == 0) || + (XSTRNCMP(enc,"AES(256)",8) == 0) || + (XSTRNCMP(enc,"CAMELLIA(256)",13) == 0) || + (XSTRNCMP(enc,"CHACHA20/POLY1305(256)",22) == 0)) + ret = 256; + else if + ((XSTRNCMP(enc,"3DES",4) == 0)) + ret = 168; + else if + ((XSTRNCMP(enc,"AESGCM(128)",11) == 0) || + (XSTRNCMP(enc,"AES(128)",8) == 0) || + (XSTRNCMP(enc,"CAMELLIA(128)",13) == 0) || + (XSTRNCMP(enc,"IDEA",4) == 0) || + (XSTRNCMP(enc,"RC4",3) == 0)) + ret = 128; + else if + ((XSTRNCMP(enc,"DES",3) == 0)) + ret = 56; + + return ret; +} +#endif /* WOLFSSL_QT || OPENSSL_ALL */ + +const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite) +{ +#ifndef NO_ERROR_STRINGS + int i; + const char* nameIana = "NONE"; + + for (i = 0; i < GetCipherNamesSize(); i++) { + if ((cipher_names[i].cipherSuite0 == cipherSuite0) && + (cipher_names[i].cipherSuite == cipherSuite)) { + nameIana = cipher_names[i].name_iana; + break; + } + } + return nameIana; +#else + (void)cipherSuite0; + (void)cipherSuite; + return NULL; +#endif +} + +const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return NULL; + } + + return GetCipherNameInternal(ssl->options.cipherSuite0, ssl->options.cipherSuite); +} + +const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return NULL; + } + + return GetCipherNameIana(ssl->options.cipherSuite0, ssl->options.cipherSuite); +} + +int GetCipherSuiteFromName(const char* name, byte* cipherSuite0, + byte* cipherSuite) +{ + int ret = BAD_FUNC_ARG; + int i; + unsigned long len = (unsigned long)XSTRLEN(name); + + for (i = 0; i < GetCipherNamesSize(); i++) { + if (XSTRNCMP(name, cipher_names[i].name, len) == 0) { + *cipherSuite0 = cipher_names[i].cipherSuite0; + *cipherSuite = cipher_names[i].cipherSuite; + ret = 0; + break; + } + } + + return ret; +} + /** 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; @@ -8868,8 +18793,9 @@ int SetCipherList(Suites* suites, const char* list) return 0; } - if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0) - return 1; /* wolfSSL defualt */ + if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0 || + XSTRNCMP(next, "DEFAULT", 7) == 0) + return 1; /* wolfSSL default */ do { char* current = next; @@ -8885,22 +18811,67 @@ int SetCipherList(Suites* suites, const char* list) name[(length == sizeof(name)) ? length - 1 : length] = 0; for (i = 0; i < suiteSz; i++) { - if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) { - suites->suites[idx++] = (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE - : (XSTRSTR(name, "EC")) ? ECC_BYTE - : (XSTRSTR(name, "CCM")) ? ECC_BYTE - : 0x00; /* normal */ + if (XSTRNCMP(name, cipher_names[i].name, sizeof(name)) == 0 + #ifndef NO_ERROR_STRINGS + || XSTRNCMP(name, cipher_names[i].name_iana, sizeof(name)) == 0 + #endif + ) { + #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; + } - suites->suites[idx++] = (byte)cipher_name_idx[i]; + } + #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++] = cipher_names[i].cipherSuite0; + suites->suites[idx++] = cipher_names[i].cipherSuite; /* The suites are either ECDSA, RSA, PSK, or Anon. The RSA * suites don't necessarily have RSA in the name. */ + #ifdef WOLFSSL_TLS13 + if (cipher_names[i].cipherSuite0 == TLS13_BYTE || + (cipher_names[i].cipherSuite0 == ECC_BYTE && + (cipher_names[i].cipherSuite == TLS_SHA256_SHA256 || + cipher_names[i].cipherSuite == TLS_SHA384_SHA384))) { + #ifndef NO_RSA + haveRSAsig = 1; + #endif + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_ED448) + haveECDSAsig = 1; + #endif + } + else + #endif + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_ED448) if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA")) haveECDSAsig = 1; - else if (XSTRSTR(name, "ADH")) + else + #endif + #ifdef HAVE_ANON + if (XSTRSTR(name, "ADH")) haveAnon = 1; - else if ((haveRSAsig == 0) && (XSTRSTR(name, "PSK") == NULL)) + else + #endif + if (haveRSAsig == 0 + #ifndef NO_PSK + && (XSTRSTR(name, "PSK") == NULL) + #endif + ) { haveRSAsig = 1; + } ret = 1; /* found at least one */ break; @@ -8910,59 +18881,205 @@ 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; } -static void PickHashSigAlgo(WOLFSSL* ssl, - const byte* hashSigAlgo, word32 hashSigAlgoSz) +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) +int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) { word32 i; + int ret = MATCH_SUITE_ERROR; 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 + } +#ifndef WOLFSSL_NO_TLS12 + 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; + } +#endif + + if (hashSigAlgoSz == 0) + return 0; /* 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_ED25519 + if (ssl->pkCurveOID == ECC_ED25519_OID) { + if (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; + ret = 0; break; } + } + #endif + #ifdef HAVE_ED448 + if (ssl->pkCurveOID == ECC_ED448_OID) { + if (sigAlgo != ed448_sa_algo) + continue; + + if (sigAlgo == ed448_sa_algo && + ssl->suites->sigAlgo == ecc_dsa_sa_algo) { + ssl->suites->sigAlgo = sigAlgo; + ssl->suites->hashAlgo = sha512_mac; + ret = 0; + break; + } + } + #endif + #if defined(WOLFSSL_TLS13) && defined(HAVE_ECC) + if (IsAtLeastTLSv1_3(ssl->version) && sigAlgo == ssl->suites->sigAlgo && + sigAlgo == ecc_dsa_sa_algo) { + + int digestSz = GetMacDigestSize(hashAlgo); + if (digestSz <= 0) + continue; + + /* TLS 1.3 signature algorithms for ECDSA match hash length with + * key size. + */ + if (digestSz != ssl->buffers.keySz) + continue; + + ssl->suites->hashAlgo = hashAlgo; + ssl->suites->sigAlgo = sigAlgo; + ret = 0; + break; /* done selected sig/hash algorithms */ + } + else + #endif + /* For ECDSA the `USE_ECDSA_KEYSZ_HASH_ALGO` build option will choose a hash + * algorithm that matches the ephemeral ECDHE key size or the next highest + * available. This workaround resolves issue with some peer's that do not + * properly support scenarios such as a P-256 key hashed with SHA512. + */ + #if defined(HAVE_ECC) && defined(USE_ECDSA_KEYSZ_HASH_ALGO) + if (sigAlgo == ssl->suites->sigAlgo && sigAlgo == ecc_dsa_sa_algo) { + int digestSz = GetMacDigestSize(hashAlgo); + if (digestSz <= 0) + continue; + + /* For ecc_dsa_sa_algo, pick hash algo that is curve size unless + algorithm in not compiled in, then choose next highest */ + if (digestSz == ssl->eccTempKeySz) { + ssl->suites->hashAlgo = hashAlgo; + ssl->suites->sigAlgo = sigAlgo; + #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE) + ssl->namedGroup = 0; + #endif + ret = 0; + break; /* done selected sig/hash algorithms */ + } + /* not strong enough, so keep checking hashSigAlso list */ + if (digestSz < ssl->eccTempKeySz) + continue; + + /* mark as highest and check remainder of hashSigAlgo list */ + ssl->suites->hashAlgo = hashAlgo; + ssl->suites->sigAlgo = sigAlgo; + ret = 0; + } + else + #endif + #ifdef WC_RSA_PSS + if (IsAtLeastTLSv1_3(ssl->version) && + ssl->suites->sigAlgo == rsa_sa_algo && + sigAlgo != rsa_pss_sa_algo) { + continue; + } + else if (sigAlgo == ssl->suites->sigAlgo || + (sigAlgo == rsa_pss_sa_algo && + (ssl->suites->sigAlgo == rsa_sa_algo))) + #else + if (sigAlgo == ssl->suites->sigAlgo) + #endif + { + /* pick highest available between both server and client */ + switch (hashAlgo) { + case sha_mac: + #ifdef WOLFSSL_SHA224 + case sha224_mac: + #endif #ifndef NO_SHA256 - else if (hashSigAlgo[i] == sha256_mac) { - ssl->suites->hashAlgo = sha256_mac; - break; - } + case sha256_mac: #endif #ifdef WOLFSSL_SHA384 - else if (hashSigAlgo[i] == sha384_mac) { - ssl->suites->hashAlgo = sha384_mac; - break; - } + case sha384_mac: #endif #ifdef WOLFSSL_SHA512 - else if (hashSigAlgo[i] == sha512_mac) { - ssl->suites->hashAlgo = sha512_mac; - break; - } + case sha512_mac: #endif + /* not strong enough, so keep checking hashSigAlso list */ + if (hashAlgo < ssl->suites->hashAlgo) { + ret = 0; + continue; + } + /* mark as highest and check remainder of hashSigAlgo list */ + ssl->suites->hashAlgo = hashAlgo; + ssl->suites->sigAlgo = sigAlgo; + break; + default: + continue; + } + ret = 0; + break; + } +#if defined(WOLFSSL_TLS13) + else if (ssl->specs.sig_algo == 0 && IsAtLeastTLSv1_3(ssl->version)) { + } +#endif + else if (ssl->specs.sig_algo == 0) + { + ssl->suites->hashAlgo = ssl->specs.mac_algorithm; + ret = 0; } } + + return ret; } +#endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */ +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) -#ifdef WOLFSSL_CALLBACKS - - /* Initialisze HandShakeInfo */ - void InitHandShakeInfo(HandShakeInfo* info) + /* Initialize HandShakeInfo */ + void InitHandShakeInfo(HandShakeInfo* info, WOLFSSL* ssl) { int i; + info->ssl = ssl; info->cipherName[0] = 0; for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++) info->packetNames[i][0] = 0; @@ -8971,36 +19088,46 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } /* Set Final HandShakeInfo parameters */ - void FinishHandShakeInfo(HandShakeInfo* info, const WOLFSSL* ssl) + void FinishHandShakeInfo(HandShakeInfo* info) { int i; - int sz = sizeof(cipher_name_idx)/sizeof(int); + int sz = GetCipherNamesSize(); for (i = 0; i < sz; i++) - if (ssl->options.cipherSuite == (byte)cipher_name_idx[i]) { - if (ssl->options.cipherSuite0 == ECC_BYTE) + if (info->ssl->options.cipherSuite == + (byte)cipher_names[i].cipherSuite) { + if (info->ssl->options.cipherSuite0 == ECC_BYTE) continue; /* ECC suites at end */ - XSTRNCPY(info->cipherName, cipher_names[i], MAX_CIPHERNAME_SZ); + XSTRNCPY(info->cipherName, cipher_names[i].name, MAX_CIPHERNAME_SZ); + info->cipherName[MAX_CIPHERNAME_SZ] = '\0'; break; } /* error max and min are negative numbers */ - if (ssl->error <= MIN_PARAM_ERR && ssl->error >= MAX_PARAM_ERR) - info->negotiationError = ssl->error; + if (info->ssl->error <= MIN_PARAM_ERR && info->ssl->error >= MAX_PARAM_ERR) + info->negotiationError = info->ssl->error; } /* Add name to info packet names, increase packet name count */ - void AddPacketName(const char* name, HandShakeInfo* info) + void AddPacketName(WOLFSSL* ssl, const char* name) { + #ifdef WOLFSSL_CALLBACKS + HandShakeInfo* info = &ssl->handShakeInfo; if (info->numberPackets < MAX_PACKETS_HANDSHAKE) { - XSTRNCPY(info->packetNames[info->numberPackets++], name, - MAX_PACKETNAME_SZ); + char* packetName = info->packetNames[info->numberPackets]; + XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ); + packetName[MAX_PACKETNAME_SZ] = '\0'; + info->numberPackets++; } + #endif + (void)ssl; + (void)name; } - /* Initialisze TimeoutInfo */ + #ifdef WOLFSSL_CALLBACKS + /* Initialize TimeoutInfo */ void InitTimeoutInfo(TimeoutInfo* info) { int i; @@ -9034,55 +19161,19 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } - - /* Add PacketInfo to TimeoutInfo */ - void AddPacketInfo(const char* name, TimeoutInfo* info, const byte* data, - int sz, void* heap) - { - if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) { - Timeval currTime; - - /* may add name after */ - if (name) - XSTRNCPY(info->packets[info->numberPackets].packetName, name, - MAX_PACKETNAME_SZ); - - /* add data, put in buffer if bigger than static buffer */ - info->packets[info->numberPackets].valueSz = sz; - if (sz < MAX_VALUE_SZ) - XMEMCPY(info->packets[info->numberPackets].value, data, sz); - else { - info->packets[info->numberPackets].bufferValue = - 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; - else - XMEMCPY(info->packets[info->numberPackets].bufferValue, - data, sz); - } - gettimeofday(&currTime, 0); - info->packets[info->numberPackets].timestamp.tv_sec = - currTime.tv_sec; - info->packets[info->numberPackets].timestamp.tv_usec = - currTime.tv_usec; - info->numberPackets++; - } - } - - - /* Add packet name to previsouly added packet info */ + /* Add packet name to previously added packet info */ void AddLateName(const char* name, TimeoutInfo* info) { /* make sure we have a valid previous one */ if (info->numberPackets > 0 && info->numberPackets < MAX_PACKETS_HANDSHAKE) { - XSTRNCPY(info->packets[info->numberPackets - 1].packetName, name, - MAX_PACKETNAME_SZ); + char* packetName = info->packets[info->numberPackets-1].packetName; + XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ); + packetName[MAX_PACKETNAME_SZ] = '\0'; } } - /* Add record header to previsouly added packet info */ + /* Add record header to previously added packet info */ void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info) { /* make sure we have a valid previous one */ @@ -9097,13 +19188,343 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } } + #endif /* WOLFSSL_CALLBACKS */ + + + /* Add PacketInfo to TimeoutInfo + * + * ssl WOLFSSL structure sending or receiving packet + * name name of packet being sent + * type type of packet being sent + * data data bing sent with packet + * sz size of data buffer + * written 1 if this packet is being written to wire, 0 if being read + * heap custom heap to use for mallocs/frees + */ + void AddPacketInfo(WOLFSSL* ssl, const char* name, int type, + const byte* data, int sz, int written, void* heap) + { + #ifdef WOLFSSL_CALLBACKS + TimeoutInfo* info = &ssl->timeoutInfo; + + if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) { + WOLFSSL_TIMEVAL currTime; + + /* may add name after */ + if (name) { + char* packetName = info->packets[info->numberPackets].packetName; + XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ); + packetName[MAX_PACKETNAME_SZ] = '\0'; + } + + /* add data, put in buffer if bigger than static buffer */ + info->packets[info->numberPackets].valueSz = sz; + if (sz < MAX_VALUE_SZ) + XMEMCPY(info->packets[info->numberPackets].value, data, sz); + else { + info->packets[info->numberPackets].bufferValue = + (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; + else + XMEMCPY(info->packets[info->numberPackets].bufferValue, + data, sz); + } + gettimeofday(&currTime, 0); + info->packets[info->numberPackets].timestamp.tv_sec = + currTime.tv_sec; + info->packets[info->numberPackets].timestamp.tv_usec = + currTime.tv_usec; + info->numberPackets++; + } + #endif /* WOLFSSL_CALLBACKS */ + #ifdef OPENSSL_EXTRA + if (ssl->protoMsgCb != NULL && sz > RECORD_HEADER_SZ) { + /* version from hex to dec 16 is 16^1, 256 from 16^2 and + 4096 from 16^3 */ + int version = (ssl->version.minor & 0X0F) + + (ssl->version.minor & 0xF0) * 16 + + (ssl->version.major & 0X0F) * 256 + + (ssl->version.major & 0xF0) * 4096; + + ssl->protoMsgCb(written, version, type, + (const void *)(data + RECORD_HEADER_SZ), + (size_t)(sz - RECORD_HEADER_SZ), + ssl, ssl->protoMsgCtx); + } + #endif /* OPENSSL_EXTRA */ + (void)written; + (void)name; + (void)heap; + (void)type; + (void)ssl; + } + #endif /* WOLFSSL_CALLBACKS */ +#if !defined(NO_CERTS) +/* Decode the private key - RSA/ECC/Ed25519/Ed448 - 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; + int keySz; + word32 idx; + +#ifdef HAVE_PK_CALLBACKS + /* allow no private key if using PK callbacks and CB is set */ + if (wolfSSL_IsPrivatePkSet(ssl)) { + *length = GetPrivateKeySigSize(ssl); + return 0; + } + else +#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); + } + +#ifdef HAVE_PKCS11 + if (ssl->buffers.keyDevId != INVALID_DEVID && ssl->buffers.keyId) { + if (ssl->buffers.keyType == rsa_sa_algo) + ssl->hsType = DYNAMIC_TYPE_RSA; + else if (ssl->buffers.keyType == ecc_dsa_sa_algo) + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + + if (ssl->buffers.keyType == rsa_sa_algo) { + #ifndef NO_RSA + ret = wc_InitRsaKey_Id((RsaKey*)ssl->hsKey, + ssl->buffers.key->buffer, ssl->buffers.key->length, + ssl->heap, ssl->buffers.keyDevId); + if (ret == 0) { + if (ssl->buffers.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)ssl->buffers.keySz; + } + #else + ret = NOT_COMPILED_IN; + #endif + } + else if (ssl->buffers.keyType == ecc_dsa_sa_algo) { + #ifdef HAVE_ECC + ret = wc_ecc_init_id((ecc_key*)ssl->hsKey, ssl->buffers.key->buffer, + ssl->buffers.key->length, ssl->heap, + ssl->buffers.keyDevId); + if (ret == 0) { + if (ssl->buffers.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_calc(ssl->buffers.keySz); + } + #else + ret = NOT_COMPILED_IN; + #endif + } + goto exit_dpk; + } +#endif + +#ifndef NO_RSA + if (ssl->buffers.keyType == rsa_sa_algo || ssl->buffers.keyType == 0) { + 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 */ + + if (ssl->buffers.keyType == ecc_dsa_sa_algo || ssl->buffers.keyType == 0) { + 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 + + if (ssl->buffers.keyType == ed25519_sa_algo || ssl->buffers.keyType == 0) { + 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. */ + 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 /* HAVE_ED25519 */ +#ifdef HAVE_ED448 + #if !defined(NO_RSA) || defined(HAVE_ECC) + FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey); + #endif + + if (ssl->buffers.keyType == ed448_sa_algo || ssl->buffers.keyType == 0) { + ssl->hsType = DYNAMIC_TYPE_ED448; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + + #ifdef HAVE_ED25519 + WOLFSSL_MSG("Trying ED448 private key, ED25519 didn't work"); + #elif defined(HAVE_ECC) + WOLFSSL_MSG("Trying ED448 private key, ECC didn't work"); + #elif !defined(NO_RSA) + WOLFSSL_MSG("Trying ED448 private key, RSA didn't work"); + #else + WOLFSSL_MSG("Trying ED447 private key"); + #endif + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an ED448 private key. */ + ret = wc_Ed448PrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (ed448_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using ED448 private key"); + + /* Check it meets the minimum ECC key size requirements. */ + if (ED448_KEY_SIZE < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ED448 key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = ED448_SIG_SIZE; + + goto exit_dpk; + } + } +#endif /* HAVE_ED448 */ + + (void)idx; + (void)keySz; + (void)length; +exit_dpk: + return ret; +} + +#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */ /* client only parts */ #ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + + /* handle generation of client_hello (1) */ int SendClientHello(WOLFSSL* ssl) { byte *output; @@ -9113,6 +19534,15 @@ static void PickHashSigAlgo(WOLFSSL* ssl, ? ssl->session.sessionIDSz : 0; int ret; + word16 extSz = 0; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + return SendTls13ClientHello(ssl); +#endif + + WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND); + WOLFSSL_ENTER("SendClientHello"); if (ssl->suites == NULL) { WOLFSSL_MSG("Bad suites pointer in SendClientHello"); @@ -9123,28 +19553,47 @@ static void PickHashSigAlgo(WOLFSSL* ssl, if (ssl->options.resuming && ssl->session.ticketLen > 0) { SessionTicket* ticket; - ticket = TLSX_SessionTicket_Create(0, - ssl->session.ticket, ssl->session.ticketLen); + ticket = TLSX_SessionTicket_Create(0, ssl->session.ticket, + ssl->session.ticketLen, ssl->heap); if (ticket == NULL) return MEMORY_E; - ret = TLSX_UseSessionTicket(&ssl->extensions, ticket); - if (ret != SSL_SUCCESS) return ret; + ret = TLSX_UseSessionTicket(&ssl->extensions, ticket, ssl->heap); + if (ret != WOLFSSL_SUCCESS) { + TLSX_SessionTicket_Free(ticket, ssl->heap); + return ret; + } idSz = 0; } #endif - length = VERSION_SZ + RAN_LEN + idSz + ENUM_LEN + ssl->suites->suiteSz + SUITE_LEN + COMP_LEN + ENUM_LEN; #ifdef HAVE_TLS_EXTENSIONS - length += TLSX_GetRequestSize(ssl); + /* auto populate extensions supported unless user defined */ + if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0) + return ret; + #ifdef HAVE_QSH + if (QSH_Init(ssl) != 0) + return MEMORY_E; + #endif + extSz = 0; + ret = TLSX_GetRequestSize(ssl, client_hello, &extSz); + if (ret != 0) + return ret; + length += extSz; #else - if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) { - length += ssl->suites->hashSigAlgoSz + HELLO_EXT_SZ; - } + if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) + extSz += HELLO_EXT_SZ + HELLO_EXT_SIGALGO_SZ + + ssl->suites->hashSigAlgoSz; +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS) + extSz += HELLO_EXT_SZ; +#endif + if (extSz != 0) + length += extSz + HELLO_EXT_SZ_SZ; #endif sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; @@ -9157,41 +19606,41 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } #endif - if (ssl->keys.encryptionOn) + if (IsEncryptionOn(ssl, 1)) sendSz += MAX_MSG_EXTRA; /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; - /* get ouput buffer */ + /* get output buffer */ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; AddHeaders(output, length, client_hello, ssl); - /* client hello, first version */ + /* client hello, first version */ output[idx++] = ssl->version.major; 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, @@ -9199,7 +19648,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; @@ -9211,13 +19660,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; @@ -9225,71 +19674,102 @@ static void PickHashSigAlgo(WOLFSSL* ssl, output[idx++] = NO_COMPRESSION; #ifdef HAVE_TLS_EXTENSIONS - idx += TLSX_WriteRequest(ssl, output + idx); + extSz = 0; + ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &extSz); + if (ret != 0) + return ret; + idx += extSz; (void)idx; /* suppress analyzer warning, keep idx current */ #else - if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) - { - int i; - /* add in the extensions length */ - c16toa(HELLO_EXT_LEN + ssl->suites->hashSigAlgoSz, output + idx); - idx += 2; + if (extSz != 0) { + c16toa(extSz, output + idx); + idx += HELLO_EXT_SZ_SZ; - c16toa(HELLO_EXT_SIG_ALGO, output + idx); - idx += 2; - c16toa(HELLO_EXT_SIGALGO_SZ+ssl->suites->hashSigAlgoSz, output+idx); - idx += 2; - c16toa(ssl->suites->hashSigAlgoSz, output + idx); - idx += 2; - for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, idx++) { - output[idx] = ssl->suites->hashSigAlgo[i]; + if (IsAtLeastTLSv1_2(ssl)) { + if (ssl->suites->hashSigAlgoSz) { + word16 i; + /* extension type */ + c16toa(HELLO_EXT_SIG_ALGO, output + idx); + idx += HELLO_EXT_TYPE_SZ; + /* extension data length */ + c16toa(HELLO_EXT_SIGALGO_SZ + ssl->suites->hashSigAlgoSz, + output + idx); + idx += HELLO_EXT_SZ_SZ; + /* sig algos length */ + c16toa(ssl->suites->hashSigAlgoSz, output + idx); + idx += HELLO_EXT_SIGALGO_SZ; + for (i=0; i < ssl->suites->hashSigAlgoSz; i++, idx++) { + output[idx] = ssl->suites->hashSigAlgo[i]; + } + } } +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS) { + c16toa(HELLO_EXT_EXTMS, output + idx); + idx += HELLO_EXT_TYPE_SZ; + c16toa(0, output + idx); + idx += HELLO_EXT_SZ_SZ; + } +#endif } #endif - if (ssl->keys.encryptionOn) { + if (IsEncryptionOn(ssl, 1)) { 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); - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (sendSz < 0) return sendSz; } else { + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif ret = HashOutput(ssl, output, sendSz, 0); if (ret != 0) return ret; } - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) - return ret; - } - #endif - ssl->options.clientState = CLIENT_HELLO_COMPLETE; +#ifdef OPENSSL_EXTRA + ssl->cbmode = SSL_CB_MODE_WRITE; + if (ssl->CBIS != NULL) + ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS); +#endif -#ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo); +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello"); if (ssl->toInfoOn) - AddPacketInfo("ClientHello", &ssl->timeoutInfo, output, sendSz, - ssl->heap); + AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); #endif ssl->buffers.outputBuffer.length += sendSz; - return SendBuffered(ssl); + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendClientHello", ret); + WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND); + + return ret; } + /* handle processing of DTLS hello_verify_request (3) */ static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size) { @@ -9298,23 +19778,26 @@ static void PickHashSigAlgo(WOLFSSL* ssl, word32 begin = *inOutIdx; #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("HelloVerifyRequest", - &ssl->handShakeInfo); + if (ssl->hsInfoOn) AddPacketName(ssl, "HelloVerifyRequest"); if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo); #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - DtlsPoolReset(ssl); + DtlsMsgPoolReset(ssl); } #endif - if ((*inOutIdx - begin) + OPAQUE16_LEN + OPAQUE8_LEN > size) + if (OPAQUE16_LEN + OPAQUE8_LEN > size) return BUFFER_ERROR; XMEMCPY(&pv, input + *inOutIdx, OPAQUE16_LEN); *inOutIdx += OPAQUE16_LEN; + if (pv.major != DTLS_MAJOR || + (pv.minor != DTLS_MINOR && pv.minor != DTLSv1_2_MINOR)) + return VERSION_ERROR; + cookieSz = input[(*inOutIdx)++]; if (cookieSz) { @@ -9335,7 +19818,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } - static INLINE int DSH_CheckSessionId(WOLFSSL* ssl) + static WC_INLINE int DSH_CheckSessionId(WOLFSSL* ssl) { int ret = 0; @@ -9347,7 +19830,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #ifdef HAVE_SESSION_TICKET /* server may send blank ticket which may not be expected to indicate - * exisiting one ok but will also be sending a new one */ + * existing one ok but will also be sending a new one */ ret = ret || (ssl->session.ticketLen > 0); #endif @@ -9358,42 +19841,42 @@ 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_TLS13_DRAFT + if (pv.major == TLS_DRAFT_MAJOR) { + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_3_MINOR; + } + #endif -#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; + #ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_HANDSHAKE_START, SSL_SUCCESS); + } + #endif 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(" no downgrade allowed, fatal error"); + WOLFSSL_MSG("\tno downgrade allowed, fatal error"); return VERSION_ERROR; } if (pv.minor < ssl->options.minDowngrade) { - WOLFSSL_MSG(" version below minimum allowed, fatal error"); + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); return VERSION_ERROR; } @@ -9406,25 +19889,108 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } #endif + /* Checks made - OK to downgrade. */ if (pv.minor == SSLv3_MINOR) { /* turn off tls */ - WOLFSSL_MSG(" downgrading to SSLv3"); + WOLFSSL_MSG("\tdowngrading to SSLv3"); ssl->options.tls = 0; ssl->options.tls1_1 = 0; ssl->version.minor = SSLv3_MINOR; } else if (pv.minor == TLSv1_MINOR) { /* turn off tls 1.1+ */ - WOLFSSL_MSG(" downgrading to TLSv1"); + WOLFSSL_MSG("\tdowngrading to TLSv1"); ssl->options.tls1_1 = 0; ssl->version.minor = TLSv1_MINOR; } else if (pv.minor == TLSv1_1_MINOR) { - WOLFSSL_MSG(" downgrading to TLSv1.1"); + 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; + } + + /* handle processing of server_hello (2) */ + 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; + + WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO); + WOLFSSL_ENTER("DoServerHello"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello"); + 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)) { + byte type = server_hello; + return DoTls13ServerHello(ssl, input, inOutIdx, helloSz, &type); + } +#endif + /* random */ XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); i += RAN_LEN; @@ -9470,6 +20036,29 @@ static void PickHashSigAlgo(WOLFSSL* ssl, ssl->options.cipherSuite = cs1; compression = input[i++]; +#ifndef WOLFSSL_NO_STRICT_CIPHER_SUITE + { + word32 idx, found = 0; + /* confirm server_hello cipher suite is one sent in client_hello */ + for (idx = 0; idx < ssl->suites->suiteSz; idx += 2) { + if (ssl->suites->suites[idx] == cs0 && + ssl->suites->suites[idx+1] == cs1) { + found = 1; + break; + } + } + if (!found) { + WOLFSSL_MSG("ServerHello did not use cipher suite from ClientHello"); + return MATCH_SUITE_ERROR; + } + } +#endif /* !WOLFSSL_NO_STRICT_CIPHER_SUITE */ + + if (compression != NO_COMPRESSION && !ssl->options.usingCompression) { + WOLFSSL_MSG("Server forcing compression w/o support"); + return COMPRESSION_ERROR; + } + if (compression != ZLIB_COMPRESSION && ssl->options.usingCompression) { WOLFSSL_MSG("Server refused compression, turning off"); ssl->options.usingCompression = 0; /* turn off if server refused */ @@ -9477,11 +20066,9 @@ static void PickHashSigAlgo(WOLFSSL* ssl, *inOutIdx = i; - /* tls extensions */ - if ( (i - begin) < helloSz) { #ifdef HAVE_TLS_EXTENSIONS + if ( (i - begin) < helloSz) { if (TLSX_SupportExtensions(ssl)) { - int ret = 0; word16 totalExtSz; if ((i - begin) + OPAQUE16_LEN > helloSz) @@ -9493,27 +20080,94 @@ static void PickHashSigAlgo(WOLFSSL* ssl, if ((i - begin) + totalExtSz > helloSz) return BUFFER_ERROR; - if ((ret = TLSX_Parse(ssl, (byte *) input + i, - totalExtSz, 0, NULL))) + if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, + server_hello, NULL))) return ret; i += totalExtSz; *inOutIdx = i; } else -#endif *inOutIdx = begin + helloSz; /* skip extensions */ } + else + ssl->options.haveEMS = 0; /* If no extensions, no EMS */ +#else + { + int allowExt = 0; + byte pendingEMS = 0; + + if ( (i - begin) < helloSz) { + if (ssl->version.major == SSLv3_MAJOR && + ssl->version.minor >= TLSv1_MINOR) { + + allowExt = 1; + } +#ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) + allowExt = 1; +#endif + + if (allowExt) { + word16 totalExtSz; + + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + + while (totalExtSz) { + word16 extId, extSz; + + if (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz) + return BUFFER_ERROR; + + ato16(&input[i], &extId); + i += OPAQUE16_LEN; + ato16(&input[i], &extSz); + i += OPAQUE16_LEN; + + if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz) + return BUFFER_ERROR; + + if (extId == HELLO_EXT_EXTMS) + pendingEMS = 1; + else + i += extSz; + + totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz; + } + + *inOutIdx = i; + } + else + *inOutIdx = begin + helloSz; /* skip extensions */ + } + + if (!pendingEMS && ssl->options.haveEMS) + ssl->options.haveEMS = 0; + } +#endif ssl->options.serverState = SERVER_HELLO_COMPLETE; - if (ssl->keys.encryptionOn) { + if (IsEncryptionOn(ssl, 0)) { *inOutIdx += ssl->keys.padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMWrite && + ssl->specs.cipher_type == block) { + *inOutIdx += MacSize(ssl); + } + #endif } #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) @@ -9521,23 +20175,89 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } #endif /* HAVE_SECRET_CALLBACK */ - if (ssl->options.resuming) { + ret = CompleteServerHello(ssl); + + WOLFSSL_LEAVE("DoServerHello", ret); + WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO); + + return ret; + } + +#ifdef WOLFSSL_TLS13 + /* returns 1 if able to do TLS 1.3 otherwise 0 */ + static int TLSv1_3_Capable(WOLFSSL* ssl) + { + #ifndef WOLFSSL_TLS13 + return 0; + #else + int ret = 0; + + if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) { + ret = 1; + } + + #ifdef OPENSSL_EXTRA + if ((wolfSSL_get_options(ssl) & SSL_OP_NO_TLSv1_3)) { + /* option set at run time to disable TLS 1.3 */ + ret = 0; + } + #endif + return ret; + #endif + } +#endif /* WOLFSSL_TLS13 */ + + int CompleteServerHello(WOLFSSL* ssl) + { + int ret; + + if (!ssl->options.resuming) { + byte* down = ssl->arrays->serverRandom + RAN_LEN - + TLS13_DOWNGRADE_SZ - 1; + byte vers = ssl->arrays->serverRandom[RAN_LEN - 1]; + #ifdef WOLFSSL_TLS13 + if (TLSv1_3_Capable(ssl)) { + /* TLS v1.3 capable client not allowed to downgrade when + * connecting to TLS v1.3 capable server unless cipher suite + * demands it. + */ + if (XMEMCMP(down, tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && + (vers == 0 || vers == 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(down, tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && + vers == 0) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return VERSION_ERROR; + } + } + } + else { 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; @@ -9552,15 +20272,17 @@ static void PickHashSigAlgo(WOLFSSL* ssl, ssl->options.resuming = 0; /* server denied resumption try */ } } - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - DtlsPoolReset(ssl); - } - #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + DtlsMsgPoolReset(ssl); + } + #endif return SetCipherSpecs(ssl); } +#endif /* WOLFSSL_NO_TLS12 */ + /* Make sure client setup is valid for this suite, true on success */ int VerifyClientSuite(WOLFSSL* ssl) @@ -9586,23 +20308,32 @@ static void PickHashSigAlgo(WOLFSSL* ssl, return 1; /* success */ } +#ifndef WOLFSSL_NO_TLS12 #ifndef NO_CERTS - /* just read in and ignore for now TODO: */ + /* handle processing of certificate_request (13) */ static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size) { word16 len; word32 begin = *inOutIdx; + #ifdef OPENSSL_EXTRA + int ret; + WOLFSSL_X509* x509 = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; + #endif + + WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_DO); + WOLFSSL_ENTER("DoCertificateRequest"); #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) - AddPacketName("CertificateRequest", &ssl->handShakeInfo); + AddPacketName(ssl, "CertificateRequest"); if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo); #endif - if ((*inOutIdx - begin) + OPAQUE8_LEN > size) + if (OPAQUE8_LEN > size) return BUFFER_ERROR; len = input[(*inOutIdx)++]; @@ -9624,8 +20355,25 @@ static void PickHashSigAlgo(WOLFSSL* ssl, if ((*inOutIdx - begin) + len > size) return BUFFER_ERROR; - PickHashSigAlgo(ssl, input + *inOutIdx, len); + if (PickHashSigAlgo(ssl, input + *inOutIdx, len) != 0 && + ssl->buffers.certificate && + ssl->buffers.certificate->buffer) { + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + WOLFSSL_MSG("Using PK for client private key"); + return INVALID_PARAMETER; + } + #endif + if (ssl->buffers.key && ssl->buffers.key->buffer) { + return INVALID_PARAMETER; + } + } *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 */ @@ -9654,50 +20402,133 @@ static void PickHashSigAlgo(WOLFSSL* ssl, len -= OPAQUE16_LEN + dnSz; } + #ifdef OPENSSL_EXTRA + /* call client cert callback if no cert has been loaded */ + if ((ssl->ctx->CBClientCert != NULL) && + (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer)) { + + ret = ssl->ctx->CBClientCert(ssl, &x509, &pkey); + if (ret == 1) { + if ((wolfSSL_use_certificate(ssl, x509) != WOLFSSL_SUCCESS) || + (wolfSSL_use_PrivateKey(ssl, pkey) != WOLFSSL_SUCCESS)) { + return CLIENT_CERT_CB_ERROR; + } + wolfSSL_X509_free(x509); + wolfSSL_EVP_PKEY_free(pkey); + + } else if (ret < 0) { + return WOLFSSL_ERROR_WANT_X509_LOOKUP; + } + } + #endif + /* don't send client cert or cert verify if user hasn't provided cert and private key */ - if (ssl->buffers.certificate.buffer && ssl->buffers.key.buffer) - ssl->options.sendVerify = SEND_CERT; + if (ssl->buffers.certificate && ssl->buffers.certificate->buffer) { + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + WOLFSSL_MSG("Using PK for client private key"); + ssl->options.sendVerify = SEND_CERT; + } + #endif + if (ssl->buffers.key && ssl->buffers.key->buffer) { + ssl->options.sendVerify = SEND_CERT; + } + } + #ifdef OPENSSL_EXTRA + else + #else else if (IsTLS(ssl)) + #endif + { ssl->options.sendVerify = SEND_BLANK_CERT; + } - if (ssl->keys.encryptionOn) + if (IsEncryptionOn(ssl, 0)) { *inOutIdx += ssl->keys.padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + *inOutIdx += MacSize(ssl); + #endif + } + + WOLFSSL_LEAVE("DoCertificateRequest", 0); + WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO); return 0; } #endif /* !NO_CERTS */ -#ifdef HAVE_ECC +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) - static int CheckCurveId(int oid) + static int CheckCurveId(int tlsCurveId) { - int ret = 0; + int ret = ECC_CURVE_ERROR; - switch (oid) { -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) - case WOLFSSL_ECC_SECP160R1: -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) - case WOLFSSL_ECC_SECP192R1: -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) - case WOLFSSL_ECC_SECP224R1: -#endif -#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) - case WOLFSSL_ECC_SECP256R1: -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) - case WOLFSSL_ECC_SECP384R1: -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) - case WOLFSSL_ECC_SECP521R1: -#endif - break; - - default: - ret = -1; + switch (tlsCurveId) { + #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP160R1: return ECC_SECP160R1_OID; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + case WOLFSSL_ECC_SECP160R2: return ECC_SECP160R2_OID; + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP160K1: return ECC_SECP160K1_OID; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP192R1: return ECC_SECP192R1_OID; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP192K1: return ECC_SECP192K1_OID; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP224R1: return ECC_SECP224R1_OID; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP224K1: return ECC_SECP224K1_OID; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: return ECC_X25519_OID; + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: return ECC_SECP256R1_OID; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP256K1: return ECC_SECP256K1_OID; + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + case WOLFSSL_ECC_BRAINPOOLP256R1: return ECC_BRAINPOOLP256R1_OID; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #ifdef HAVE_CURVE448 + case WOLFSSL_ECC_X448: return ECC_X448_OID; + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: return ECC_SECP384R1_OID; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_BRAINPOOL + case WOLFSSL_ECC_BRAINPOOLP384R1: return ECC_BRAINPOOLP384R1_OID; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_BRAINPOOL + case WOLFSSL_ECC_BRAINPOOLP512R1: return ECC_BRAINPOOLP512R1_OID; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: return ECC_SECP521R1_OID; + #endif /* !NO_ECC_SECP */ + #endif } return ret; @@ -9705,984 +20536,2586 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #endif /* HAVE_ECC */ - static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, - word32* inOutIdx, word32 size) - { - word16 length = 0; - word32 begin = *inOutIdx; - int ret = 0; - #define ERROR_OUT(err, eLabel) do { ret = err; goto eLabel; } while(0) +/* Persistable DoServerKeyExchange arguments */ +typedef struct DskeArgs { + byte* output; /* not allocated */ +#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_ED448) + byte* verifySig; +#endif + word32 idx; + word32 begin; +#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_ED448) + word16 verifySigSz; +#endif + word16 sigSz; + byte sigAlgo; + byte hashAlgo; +#if !defined(NO_RSA) && defined(WC_RSA_PSS) + int bits; +#endif +} DskeArgs; - (void)length; /* shut up compiler warnings */ - (void)begin; - (void)ssl; - (void)input; - (void)size; - (void)ret; +static void FreeDskeArgs(WOLFSSL* ssl, void* pArgs) +{ + DskeArgs* args = (DskeArgs*)pArgs; - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddLateName("ServerKeyExchange", &ssl->timeoutInfo); - #endif + (void)ssl; + (void)args; - #ifndef NO_PSK - if (ssl->specs.kea == psk_kea) { - - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) - return BUFFER_ERROR; - - XMEMCPY(ssl->arrays->server_hint, input + *inOutIdx, - min(length, MAX_PSK_ID_LEN)); - - ssl->arrays->server_hint[min(length, MAX_PSK_ID_LEN - 1)] = 0; - *inOutIdx += length; - - return 0; - } - #endif - #ifndef NO_DH - if (ssl->specs.kea == diffie_hellman_kea) - { - /* p */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) - return BUFFER_ERROR; - - if (length < ssl->options.minDhKeySz) { - WOLFSSL_MSG("Server using a DH key that is too small"); - SendAlert(ssl, alert_fatal, handshake_failure); - return DH_KEY_SIZE_E; - } - - ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_DH); - - if (ssl->buffers.serverDH_P.buffer) - ssl->buffers.serverDH_P.length = length; - else - return MEMORY_ERROR; - - XMEMCPY(ssl->buffers.serverDH_P.buffer, input + *inOutIdx, length); - *inOutIdx += length; - - ssl->options.dhKeySz = length; - - /* g */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) - return BUFFER_ERROR; - - ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_DH); - - if (ssl->buffers.serverDH_G.buffer) - ssl->buffers.serverDH_G.length = length; - else - return MEMORY_ERROR; - - XMEMCPY(ssl->buffers.serverDH_G.buffer, input + *inOutIdx, length); - *inOutIdx += length; - - /* pub */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) - return BUFFER_ERROR; - - ssl->buffers.serverDH_Pub.buffer = (byte*) XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_DH); - - if (ssl->buffers.serverDH_Pub.buffer) - ssl->buffers.serverDH_Pub.length = length; - else - return MEMORY_ERROR; - - XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + *inOutIdx, length); - *inOutIdx += length; - } /* dh_kea */ - #endif /* NO_DH */ - - #ifdef HAVE_ECC - if (ssl->specs.kea == ecc_diffie_hellman_kea) - { - byte b; - - if ((*inOutIdx - begin) + ENUM_LEN + OPAQUE16_LEN + OPAQUE8_LEN > size) - return BUFFER_ERROR; - - b = input[(*inOutIdx)++]; - - if (b != named_curve) - return ECC_CURVETYPE_ERROR; - - *inOutIdx += 1; /* curve type, eat leading 0 */ - b = input[(*inOutIdx)++]; - - if (CheckCurveId(b) != 0) { - return ECC_CURVE_ERROR; - } - - length = input[(*inOutIdx)++]; - - if ((*inOutIdx - begin) + length > size) - return BUFFER_ERROR; - - if (ssl->peerEccKey == NULL) { - /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->ctx->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - return MEMORY_E; - } - wc_ecc_init(ssl->peerEccKey); - } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccKey); - ssl->peerEccKeyPresent = 0; - wc_ecc_init(ssl->peerEccKey); - } - - if (wc_ecc_import_x963(input + *inOutIdx, length, ssl->peerEccKey) != 0) - return ECC_PEERKEY_ERROR; - - *inOutIdx += length; - ssl->peerEccKeyPresent = 1; - } - #endif /* HAVE_ECC */ - - #if !defined(NO_DH) && !defined(NO_PSK) - if (ssl->specs.kea == dhe_psk_kea) { - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) - return BUFFER_ERROR; - - XMEMCPY(ssl->arrays->server_hint, input + *inOutIdx, - min(length, MAX_PSK_ID_LEN)); - - ssl->arrays->server_hint[min(length, MAX_PSK_ID_LEN - 1)] = 0; - *inOutIdx += length; - - /* p */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) - return BUFFER_ERROR; - - if (length < ssl->options.minDhKeySz) { - WOLFSSL_MSG("Server using a DH key that is too small"); - SendAlert(ssl, alert_fatal, handshake_failure); - return DH_KEY_SIZE_E; - } - - ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_DH); - - if (ssl->buffers.serverDH_P.buffer) - ssl->buffers.serverDH_P.length = length; - else - return MEMORY_ERROR; - - XMEMCPY(ssl->buffers.serverDH_P.buffer, input + *inOutIdx, length); - *inOutIdx += length; - - ssl->options.dhKeySz = length; - - /* g */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) - return BUFFER_ERROR; - - ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_DH); - - if (ssl->buffers.serverDH_G.buffer) - ssl->buffers.serverDH_G.length = length; - else - return MEMORY_ERROR; - - XMEMCPY(ssl->buffers.serverDH_G.buffer, input + *inOutIdx, length); - *inOutIdx += length; - - /* pub */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) - return BUFFER_ERROR; - - ssl->buffers.serverDH_Pub.buffer = (byte*) XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_DH); - - if (ssl->buffers.serverDH_Pub.buffer) - ssl->buffers.serverDH_Pub.length = length; - else - return MEMORY_ERROR; - - XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + *inOutIdx, length); - *inOutIdx += length; +#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_ED448) + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->verifySig = NULL; } - #endif /* !NO_DH || !NO_PSK */ +#endif +} - #if !defined(NO_DH) || defined(HAVE_ECC) - if (!ssl->options.usingAnon_cipher && - (ssl->specs.kea == ecc_diffie_hellman_kea || - ssl->specs.kea == diffie_hellman_kea)) - { -#ifndef NO_OLD_TLS -#ifdef WOLFSSL_SMALL_STACK - Md5* md5 = NULL; - Sha* sha = NULL; -#else - Md5 md5[1]; - Sha sha[1]; -#endif -#endif -#ifndef NO_SHA256 -#ifdef WOLFSSL_SMALL_STACK - Sha256* sha256 = NULL; - byte* hash256 = NULL; -#else - Sha256 sha256[1]; - byte hash256[SHA256_DIGEST_SIZE]; -#endif -#endif -#ifdef WOLFSSL_SHA384 -#ifdef WOLFSSL_SMALL_STACK - Sha384* sha384 = NULL; - byte* hash384 = NULL; -#else - Sha384 sha384[1]; - byte hash384[SHA384_DIGEST_SIZE]; -#endif -#endif -#ifdef WOLFSSL_SHA512 -#ifdef WOLFSSL_SMALL_STACK - Sha512* sha512 = NULL; - byte* hash512 = NULL; -#else - Sha512 sha512[1]; - byte hash512[SHA512_DIGEST_SIZE]; -#endif -#endif -#ifdef WOLFSSL_SMALL_STACK - byte* hash = NULL; - byte* messageVerify = NULL; -#else - byte hash[FINISHED_SZ]; - byte messageVerify[MAX_DH_SZ]; -#endif - byte hashAlgo = sha_mac; - byte sigAlgo = ssl->specs.sig_algo; - word16 verifySz = (word16) (*inOutIdx - begin); - -#ifndef NO_OLD_TLS - byte doMd5 = 0; - byte doSha = 0; -#endif -#ifndef NO_SHA256 - byte doSha256 = 0; -#endif -#ifdef WOLFSSL_SHA384 - byte doSha384 = 0; -#endif -#ifdef WOLFSSL_SHA512 - byte doSha512 = 0; +#ifndef NO_DH +static int GetDhPublicKey(WOLFSSL* ssl, const byte* input, word32 size, + DskeArgs* args) +{ + int ret = 0; + word16 length; +#ifdef HAVE_FFDHE + const DhParams* params = NULL; + int group = 0; #endif - (void)hash; - (void)sigAlgo; - (void)hashAlgo; + ssl->buffers.weOwnDH = 1; - /* save message for hash verify */ - if (verifySz > MAX_DH_SZ) - ERROR_OUT(BUFFER_ERROR, done); + ssl->buffers.serverDH_P.buffer = NULL; + ssl->buffers.serverDH_G.buffer = NULL; + ssl->buffers.serverDH_Pub.buffer = NULL; - #ifdef WOLFSSL_SMALL_STACK - messageVerify = (byte*)XMALLOC(MAX_DH_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (messageVerify == NULL) - ERROR_OUT(MEMORY_E, done); + /* p */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_gdpk); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_gdpk); + } + + if (length < ssl->options.minDhKeySz) { + WOLFSSL_MSG("Server using a DH key that is too small"); + SendAlert(ssl, alert_fatal, handshake_failure); + ERROR_OUT(DH_KEY_SIZE_E, exit_gdpk); + } + if (length > ssl->options.maxDhKeySz) { + WOLFSSL_MSG("Server using a DH key that is too big"); + SendAlert(ssl, alert_fatal, handshake_failure); + ERROR_OUT(DH_KEY_SIZE_E, exit_gdpk); + } + + ssl->buffers.serverDH_P.buffer = + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ssl->buffers.serverDH_P.buffer) { + ssl->buffers.serverDH_P.length = length; + } + else { + ERROR_OUT(MEMORY_ERROR, exit_gdpk); + } + + XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx, + length); + args->idx += length; + + ssl->options.dhKeySz = length; + + /* g */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_gdpk); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_gdpk); + } + + ssl->buffers.serverDH_G.buffer = + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ssl->buffers.serverDH_G.buffer) { + ssl->buffers.serverDH_G.length = length; + } + else { + ERROR_OUT(MEMORY_ERROR, exit_gdpk); + } + + XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx, + length); + args->idx += length; + + /* pub */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_gdpk); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_gdpk); + } + + ssl->buffers.serverDH_Pub.buffer = + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ssl->buffers.serverDH_Pub.buffer) { + ssl->buffers.serverDH_Pub.length = length; + } + else { + ERROR_OUT(MEMORY_ERROR, exit_gdpk); + } + + XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx, + length); + args->idx += length; + +#ifdef HAVE_FFDHE + switch (ssl->options.dhKeySz) { + #ifdef HAVE_FFDHE_2048 + case 2048/8: + params = wc_Dh_ffdhe2048_Get(); + group = WOLFSSL_FFDHE_2048; + break; #endif + #ifdef HAVE_FFDHE_3072 + case 3072/8: + params = wc_Dh_ffdhe3072_Get(); + group = WOLFSSL_FFDHE_3072; + break; + #endif + #ifdef HAVE_FFDHE_4096 + case 4096/8: + params = wc_Dh_ffdhe4096_Get(); + group = WOLFSSL_FFDHE_4096; + break; + #endif + #ifdef HAVE_FFDHE_6144 + case 6144/8: + params = wc_Dh_ffdhe6144_Get(); + group = WOLFSSL_FFDHE_6144; + break; + #endif + #ifdef HAVE_FFDHE_8192 + case 8192/8: + params = wc_Dh_ffdhe8192_Get(); + group = WOLFSSL_FFDHE_8192; + break; + #endif + default: + break; + } - XMEMCPY(messageVerify, input + begin, verifySz); + if (params == NULL || params->g_len != ssl->buffers.serverDH_G.length || + (XMEMCMP(ssl->buffers.serverDH_G.buffer, params->g, + params->g_len) != 0) || + (XMEMCMP(ssl->buffers.serverDH_P.buffer, params->p, + params->p_len) != 0)) { + WOLFSSL_MSG("Server not using FFDHE parameters"); + #ifdef WOLFSSL_REQUIRE_FFDHE + SendAlert(ssl, alert_fatal, handshake_failure); + ERROR_OUT(DH_PARAMS_NOT_FFDHE_E, exit_gdpk); + #endif + } + else { + ssl->namedGroup = group; + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + ssl->options.dhDoKeyTest = 0; + #endif + } +#endif /* HAVE_FFDHE */ - if (IsAtLeastTLSv1_2(ssl)) { - byte setHash = 0; - if ((*inOutIdx - begin) + ENUM_LEN + ENUM_LEN > size) - ERROR_OUT(BUFFER_ERROR, done); +exit_gdpk: + return ret; +} +#endif - hashAlgo = input[(*inOutIdx)++]; - sigAlgo = input[(*inOutIdx)++]; +/* handle processing of server_key_exchange (12) */ +static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ + 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 - switch (hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - doSha512 = 1; - setHash = 1; - #endif + (void)input; + (void)size; + + WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_DO); + WOLFSSL_ENTER("DoServerKeyExchange"); + +#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_dske; + } + else +#endif + { + /* Reset state */ + ret = 0; + 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.asyncState) + { + case TLS_ASYNC_BEGIN: + { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "ServerKeyExchange"); + if (ssl->toInfoOn) + AddLateName("ServerKeyExchange", &ssl->timeoutInfo); + #endif + + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + int srvHintLen; + word16 length; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + 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); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + args->idx += length; break; - - case sha384_mac: - #ifdef WOLFSSL_SHA384 - doSha384 = 1; - setHash = 1; - #endif + } + #endif /* !NO_PSK */ + #ifndef NO_DH + case diffie_hellman_kea: + { + ret = GetDhPublicKey(ssl, input, size, args); + if (ret != 0) + goto exit_dske; break; + } + #endif /* !NO_DH */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + case ecc_diffie_hellman_kea: + { + byte b; + #ifdef HAVE_ECC + int curveId; + #endif + int curveOid; + word16 length; - case sha256_mac: - #ifndef NO_SHA256 - doSha256 = 1; - setHash = 1; + if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN + + OPAQUE8_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + b = input[args->idx++]; + if (b != named_curve) { + ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske); + } + + 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; + #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE) + ssl->namedGroup = 0; + #endif + + length = input[args->idx++]; + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, 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->peerX25519KeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519, + ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + if (ret != 0) { + goto exit_dske; + } + } + + if ((ret = wc_curve25519_check_public( + input + args->idx, length, + EC25519_LITTLE_ENDIAN)) != 0) { + #ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_E) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret == ECC_OUT_OF_RANGE_E) + SendAlert(ssl, alert_fatal, bad_record_mac); + else { + SendAlert(ssl, alert_fatal, illegal_parameter); + } + #endif + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + 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 + #ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) { + if (ssl->peerX448Key == NULL) { + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448, + (void**)&ssl->peerX448Key); + if (ret != 0) { + goto exit_dske; + } + } else if (ssl->peerX448KeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448, + ssl->peerX448Key); + ssl->peerX448KeyPresent = 0; + if (ret != 0) { + goto exit_dske; + } + } + + if ((ret = wc_curve448_check_public( + input + args->idx, length, + EC448_LITTLE_ENDIAN)) != 0) { + #ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_E) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret == ECC_OUT_OF_RANGE_E) + SendAlert(ssl, alert_fatal, bad_record_mac); + else { + SendAlert(ssl, alert_fatal, illegal_parameter); + } + #endif + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + if (wc_curve448_import_public_ex(input + args->idx, + length, ssl->peerX448Key, + EC448_LITTLE_ENDIAN) != 0) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + args->idx += length; + ssl->peerX448KeyPresent = 1; + break; + } + #endif + #ifdef HAVE_ECC + if (ssl->peerEccKey == NULL) { + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + if (ret != 0) { + goto exit_dske; + } + } else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + if (ret != 0) { + goto exit_dske; + } + } + + curveId = wc_ecc_get_oid(curveOid, NULL, NULL); + if (wc_ecc_import_x963_ex(input + args->idx, length, + ssl->peerEccKey, curveId) != 0) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, illegal_parameter); #endif - break; + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } - case sha_mac: - #ifndef NO_OLD_TLS - doSha = 1; - setHash = 1; - #endif + args->idx += length; + ssl->peerEccKeyPresent = 1; + #endif break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + int srvHintLen; + word16 length; + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + 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); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + args->idx += length; + + ret = GetDhPublicKey(ssl, input, size, args); + if (ret != 0) + goto exit_dske; + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + byte b; + int curveOid, curveId; + int srvHintLen; + word16 length; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + 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); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + + args->idx += length; + + 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[args->idx++]; + if (b != named_curve) { + ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske); + } + + 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[args->idx++]; + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, 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; + } + } + + if ((ret = wc_curve25519_check_public( + input + args->idx, length, + EC25519_LITTLE_ENDIAN)) != 0) { + #ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_E) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret == ECC_OUT_OF_RANGE_E) + SendAlert(ssl, alert_fatal, bad_record_mac); + else { + SendAlert(ssl, alert_fatal, illegal_parameter); + } + #endif + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + 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 + #ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) { + if (ssl->peerX448Key == NULL) { + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448, + (void**)&ssl->peerX448Key); + if (ret != 0) { + goto exit_dske; + } + } else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448, + ssl->peerX448Key); + ssl->peerX448KeyPresent = 0; + if (ret != 0) { + goto exit_dske; + } + } + + if ((ret = wc_curve448_check_public( + input + args->idx, length, + EC448_LITTLE_ENDIAN)) != 0) { + #ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_E) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret == ECC_OUT_OF_RANGE_E) + SendAlert(ssl, alert_fatal, bad_record_mac); + else { + SendAlert(ssl, alert_fatal, illegal_parameter); + } + #endif + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + if (wc_curve448_import_public_ex(input + args->idx, + length, ssl->peerX448Key, + EC448_LITTLE_ENDIAN) != 0) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + args->idx += length; + ssl->peerX448KeyPresent = 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) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + if (ret != 0) { + goto exit_dske; + } + } + + curveId = wc_ecc_get_oid(curveOid, NULL, NULL); + if (wc_ecc_import_x963_ex(input + args->idx, length, + ssl->peerEccKey, curveId) != 0) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + args->idx += length; + ssl->peerEccKeyPresent = 1; + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */ default: - ERROR_OUT(ALGO_ID_E, done); + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; } - if (setHash == 0) { - ERROR_OUT(ALGO_ID_E, done); - } + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - } else { - /* only using sha and md5 for rsa */ - #ifndef NO_OLD_TLS - doSha = 1; - if (sigAlgo == rsa_sa_algo) { - doMd5 = 1; - } - #else - ERROR_OUT(ALGO_ID_E, done); - #endif - } - - /* signature */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - ERROR_OUT(BUFFER_ERROR, done); - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) - ERROR_OUT(BUFFER_ERROR, done); - - /* inOutIdx updated at the end of the function */ - - /* verify signature */ - #ifdef WOLFSSL_SMALL_STACK - hash = (byte*)XMALLOC(FINISHED_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (hash == NULL) - ERROR_OUT(MEMORY_E, done); - #endif - -#ifndef NO_OLD_TLS - /* md5 */ - #ifdef WOLFSSL_SMALL_STACK - if (doMd5) { - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (md5 == NULL) - ERROR_OUT(MEMORY_E, done); - } - #endif - if (doMd5) { - wc_InitMd5(md5); - wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN); - wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN); - wc_Md5Update(md5, messageVerify, verifySz); - wc_Md5Final(md5, hash); - } - /* sha */ - #ifdef WOLFSSL_SMALL_STACK - if (doSha) { - sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha == NULL) - ERROR_OUT(MEMORY_E, done); - } - #endif - if (doSha) { - ret = wc_InitSha(sha); - if (ret != 0) goto done; - wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN); - wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN); - wc_ShaUpdate(sha, messageVerify, verifySz); - wc_ShaFinal(sha, hash + MD5_DIGEST_SIZE); - } -#endif - -#ifndef NO_SHA256 - #ifdef WOLFSSL_SMALL_STACK - if (doSha256) { - sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha256 == NULL || hash256 == NULL) - ERROR_OUT(MEMORY_E, done); - } - #endif - if (doSha256) { - if (!(ret = wc_InitSha256(sha256)) - && !(ret = wc_Sha256Update(sha256, ssl->arrays->clientRandom, - RAN_LEN)) - && !(ret = wc_Sha256Update(sha256, ssl->arrays->serverRandom, - RAN_LEN)) - && !(ret = wc_Sha256Update(sha256, messageVerify, verifySz))) - ret = wc_Sha256Final(sha256, hash256); - if (ret != 0) goto done; - } -#endif - -#ifdef WOLFSSL_SHA384 - #ifdef WOLFSSL_SMALL_STACK - if (doSha384) { - sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha384 == NULL || hash384 == NULL) - ERROR_OUT(MEMORY_E, done); - } - #endif - if (doSha384) { - if (!(ret = wc_InitSha384(sha384)) - && !(ret = wc_Sha384Update(sha384, ssl->arrays->clientRandom, - RAN_LEN)) - && !(ret = wc_Sha384Update(sha384, ssl->arrays->serverRandom, - RAN_LEN)) - && !(ret = wc_Sha384Update(sha384, messageVerify, verifySz))) - ret = wc_Sha384Final(sha384, hash384); - if (ret != 0) goto done; - } -#endif - -#ifdef WOLFSSL_SHA512 - #ifdef WOLFSSL_SMALL_STACK - if (doSha512) { - sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha512 == NULL || hash512 == NULL) - ERROR_OUT(MEMORY_E, done); - } - #endif - if (doSha512) { - if (!(ret = wc_InitSha512(sha512)) - && !(ret = wc_Sha512Update(sha512, ssl->arrays->clientRandom, - RAN_LEN)) - && !(ret = wc_Sha512Update(sha512, ssl->arrays->serverRandom, - RAN_LEN)) - && !(ret = wc_Sha512Update(sha512, messageVerify, verifySz))) - ret = wc_Sha512Final(sha512, hash512); - if (ret != 0) goto done; - } -#endif - -#ifndef NO_RSA - /* rsa */ - if (sigAlgo == rsa_sa_algo) + case TLS_ASYNC_BUILD: { - byte* out = NULL; - byte doUserRsa = 0; - word32 verifiedSz = 0; - - #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->RsaVerifyCb) - doUserRsa = 1; - #endif /*HAVE_PK_CALLBACKS */ - - if (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent) - ERROR_OUT(NO_PEER_KEY, done); - - if (doUserRsa) { - #ifdef HAVE_PK_CALLBACKS - verifiedSz = ssl->ctx->RsaVerifyCb(ssl, - (byte *)input + *inOutIdx, - length, &out, - ssl->buffers.peerRsaKey.buffer, - ssl->buffers.peerRsaKey.length, - ssl->RsaVerifyCtx); - #endif /*HAVE_PK_CALLBACKS */ - } - else - verifiedSz = wc_RsaSSL_VerifyInline((byte *)input + *inOutIdx, - length, &out, ssl->peerRsaKey); - - if (IsAtLeastTLSv1_2(ssl)) { - word32 encSigSz; -#ifndef NO_OLD_TLS - byte* digest = &hash[MD5_DIGEST_SIZE]; - int typeH = SHAh; - int digestSz = SHA_DIGEST_SIZE; -#else - byte* digest = hash256; - int typeH = SHA256h; - int digestSz = SHA256_DIGEST_SIZE; -#endif -#ifdef WOLFSSL_SMALL_STACK - byte* encodedSig = NULL; -#else - byte encodedSig[MAX_ENCODED_SIG_SZ]; -#endif - - if (hashAlgo == sha_mac) { - #ifndef NO_SHA - digest = &hash[MD5_DIGEST_SIZE]; - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = hash256; - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = hash384; - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = hash512; - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - #endif + switch(ssl->specs.kea) + { + case psk_kea: + case dhe_psk_kea: + case ecdhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; } - #ifdef WOLFSSL_SMALL_STACK - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig == NULL) - ERROR_OUT(MEMORY_E, done); - #endif + case diffie_hellman_kea: + case ecc_diffie_hellman_kea: + { + #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) \ + && !defined(HAVE_ED448) + ERROR_OUT(NOT_COMPILED_IN, exit_dske); + #else + enum wc_HashType hashType; + word16 verifySz; - if (digest == NULL) - ERROR_OUT(ALGO_ID_E, done); - encSigSz = wc_EncodeSignature(encodedSig, digest, digestSz, - typeH); - if (encSigSz != verifiedSz || !out || XMEMCMP(out, encodedSig, - min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) - ret = VERIFY_SIGN_ERROR; + if (ssl->options.usingAnon_cipher) { + break; + } - #ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - if (ret != 0) - goto done; - } - else if (verifiedSz != FINISHED_SZ || !out || XMEMCMP(out, - hash, FINISHED_SZ) != 0) - ERROR_OUT(VERIFY_SIGN_ERROR, done); - } else -#endif -#ifdef HAVE_ECC - /* ecdsa */ - if (sigAlgo == ecc_dsa_sa_algo) { - int verify = 0; -#ifndef NO_OLD_TLS - byte* digest = &hash[MD5_DIGEST_SIZE]; - word32 digestSz = SHA_DIGEST_SIZE; -#else - byte* digest = hash256; - word32 digestSz = SHA256_DIGEST_SIZE; -#endif - byte doUserEcc = 0; + verifySz = (word16)(args->idx - args->begin); + if (verifySz > MAX_DH_SZ) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } - #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->EccVerifyCb) - doUserEcc = 1; - #endif + if (IsAtLeastTLSv1_2(ssl)) { + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > + size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } - if (!ssl->peerEccDsaKeyPresent) - ERROR_OUT(NO_PEER_KEY, done); + 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); + } + } else { + /* only using sha and md5 for rsa */ + #ifndef NO_OLD_TLS + hashType = WC_HASH_TYPE_SHA; + if (args->sigAlgo == rsa_sa_algo) { + hashType = WC_HASH_TYPE_MD5_SHA; + } + #else + ERROR_OUT(ALGO_ID_E, exit_dske); + #endif + } - if (IsAtLeastTLSv1_2(ssl)) { - if (hashAlgo == sha_mac) { - #ifndef NO_SHA - digest = &hash[MD5_DIGEST_SIZE]; - digestSz = SHA_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = hash256; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = hash384; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = hash512; - digestSz = SHA512_DIGEST_SIZE; - #endif - } - } - if (doUserEcc) { - #ifdef HAVE_PK_CALLBACKS - ret = ssl->ctx->EccVerifyCb(ssl, input + *inOutIdx, length, - digest, digestSz, - ssl->buffers.peerEccDsaKey.buffer, - ssl->buffers.peerEccDsaKey.length, - &verify, ssl->EccVerifyCtx); - #endif - } - else { - ret = wc_ecc_verify_hash(input + *inOutIdx, length, - digest, digestSz, &verify, ssl->peerEccDsaKey); - } - if (ret != 0 || verify == 0) - ERROR_OUT(VERIFY_SIGN_ERROR, done); - } - else -#endif /* HAVE_ECC */ - ERROR_OUT(ALGO_ID_E, done); + /* signature */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } - /* signature length */ - *inOutIdx += length; + ato16(input + args->idx, &args->verifySigSz); + args->idx += OPAQUE16_LEN; - ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + if ((args->idx - args->begin) + args->verifySigSz > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } - done: -#ifdef WOLFSSL_SMALL_STACK - #ifndef NO_OLD_TLS - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - #ifndef NO_SHA256 - XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - #ifdef WOLFSSL_SHA384 - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - #ifdef WOLFSSL_SHA512 - XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - if (ret != 0) - return ret; - } + /* buffer for signature */ + ssl->buffers.sig.buffer = (byte*)XMALLOC(SEED_LEN + verifySz, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dske); + } + ssl->buffers.sig.length = SEED_LEN + verifySz; - if (ssl->keys.encryptionOn) { - *inOutIdx += ssl->keys.padSz; - } + /* 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 + args->begin, verifySz); /* message */ - return 0; -#else /* !NO_DH or HAVE_ECC */ - return NOT_COMPILED_IN; /* not supported by build */ -#endif /* !NO_DH or HAVE_ECC */ + if (args->sigAlgo != ed25519_sa_algo) { + int digest_sz = wc_HashGetDigestSize(hashType); + if (digest_sz <= 0) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + ssl->buffers.digest.length = (unsigned int)digest_sz; - #undef ERROR_OUT - } + /* buffer for hash */ + 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; + } + } - int SendClientKeyExchange(WOLFSSL* ssl) - { -#ifdef WOLFSSL_SMALL_STACK - byte* encSecret = NULL; -#else - byte encSecret[MAX_ENCRYPT_SZ]; -#endif - word32 encSz = 0; - word32 idx = 0; - int ret = 0; - byte doUserRsa = 0; - - (void)doUserRsa; - -#ifdef HAVE_PK_CALLBACKS - #ifndef NO_RSA - if (ssl->ctx->RsaEncCb) - doUserRsa = 1; - #endif /* NO_RSA */ -#endif /*HAVE_PK_CALLBACKS */ - - #ifdef WOLFSSL_SMALL_STACK - encSecret = (byte*)XMALLOC(MAX_ENCRYPT_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encSecret == NULL) - return MEMORY_E; - #endif - - switch (ssl->specs.kea) { - #ifndef NO_RSA - case rsa_kea: - ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->preMasterSecret, - SECRET_LEN); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } - - ssl->arrays->preMasterSecret[0] = ssl->chVersion.major; - ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor; - ssl->arrays->preMasterSz = SECRET_LEN; - - if (ssl->peerRsaKey == NULL || ssl->peerRsaKeyPresent == 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } - - if (doUserRsa) { - #ifdef HAVE_PK_CALLBACKS + switch (args->sigAlgo) + { #ifndef NO_RSA - encSz = MAX_ENCRYPT_SZ; - ret = ssl->ctx->RsaEncCb(ssl, - ssl->arrays->preMasterSecret, - SECRET_LEN, - encSecret, &encSz, - ssl->buffers.peerRsaKey.buffer, - ssl->buffers.peerRsaKey.length, - ssl->RsaEncCtx); - #endif /* NO_RSA */ - #endif /*HAVE_PK_CALLBACKS */ + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif + case rsa_sa_algo: + { + if (ssl->peerRsaKey == NULL || + !ssl->peerRsaKeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_dske); + } + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + { + if (!ssl->peerEccDsaKeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_dske); + } + break; + } + #endif /* HAVE_ECC */ + #if defined(HAVE_ED25519) + case ed25519_sa_algo: + { + if (!ssl->peerEd25519KeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_dske); + } + break; + } + #endif /* HAVE_ED25519 */ + #if defined(HAVE_ED448) + case ed448_sa_algo: + { + if (!ssl->peerEd448KeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_dske); + } + break; + } + #endif /* HAVE_ED448 */ + + default: + ret = ALGO_ID_E; + } /* switch (args->sigAlgo) */ + + #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 && !HAVE_ED448 */ + break; + } + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + switch(ssl->specs.kea) + { + case psk_kea: + case dhe_psk_kea: + case ecdhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + + case diffie_hellman_kea: + case ecc_diffie_hellman_kea: + { + #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) \ + && !defined(HAVE_ED448) + ERROR_OUT(NOT_COMPILED_IN, exit_dske); + #else + if (ssl->options.usingAnon_cipher) { + break; + } + + 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(args->verifySig, input + args->idx, + args->verifySigSz); + } + + switch (args->sigAlgo) + { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif + case rsa_sa_algo: + { + ret = RsaVerify(ssl, + args->verifySig, args->verifySigSz, + &args->output, + args->sigAlgo, args->hashAlgo, + ssl->peerRsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerRsaKey + #else + NULL + #endif + ); + + if (ret >= 0) { + args->sigSz = (word16)ret; + #ifdef WC_RSA_PSS + args->bits = mp_count_bits(&ssl->peerRsaKey->n); + #endif + ret = 0; + } + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + /* peerRsaKey */ + FreeKey(ssl, DYNAMIC_TYPE_RSA, + (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; + } + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + { + ret = EccVerify(ssl, + args->verifySig, args->verifySigSz, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + ssl->peerEccDsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEccDsaKey + #else + NULL + #endif + ); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + /* peerEccDsaKey */ + FreeKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + } + break; + } + #endif /* HAVE_ECC */ + #if defined(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.peerEd25519Key + #else + NULL + #endif + ); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + /* peerEccDsaKey */ + FreeKey(ssl, DYNAMIC_TYPE_ED25519, + (void**)&ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; + } + break; + } + #endif /* HAVE_ED25519 */ + #if defined(HAVE_ED448) + case ed448_sa_algo: + { + ret = Ed448Verify(ssl, + args->verifySig, args->verifySigSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->peerEd448Key, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEd448Key + #else + NULL + #endif + ); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + /* peerEccDsaKey */ + FreeKey(ssl, DYNAMIC_TYPE_ED448, + (void**)&ssl->peerEd448Key); + ssl->peerEd448KeyPresent = 0; + } + break; + } + #endif /* HAVE_ED448 */ + + default: + ret = ALGO_ID_E; + } /* switch (sigAlgo) */ + #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 && !HAVE_ED448 */ + break; + } + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + switch(ssl->specs.kea) + { + case psk_kea: + case dhe_psk_kea: + case ecdhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + + case diffie_hellman_kea: + case ecc_diffie_hellman_kea: + { + #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) \ + && !defined(HAVE_ED448) + ERROR_OUT(NOT_COMPILED_IN, exit_dske); + #else + if (ssl->options.usingAnon_cipher) { + break; + } + + /* increment index after verify is done */ + args->idx += args->verifySigSz; + + switch(args->sigAlgo) + { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #ifdef HAVE_SELFTEST + ret = wc_RsaPSS_CheckPadding( + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + args->output, args->sigSz, + HashAlgoToType(args->hashAlgo)); + #else + ret = wc_RsaPSS_CheckPadding_ex( + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + args->output, args->sigSz, + HashAlgoToType(args->hashAlgo), + -1, args->bits); + #endif + if (ret != 0) + return ret; + break; + #endif + case rsa_sa_algo: + { + if (IsAtLeastTLSv1_2(ssl)) { + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig; + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif + word32 encSigSz; + + #ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_dske); + } + #endif + + encSigSz = wc_EncodeSignature(encodedSig, + ssl->buffers.digest.buffer, + 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_SIGNATURE); + #endif + if (ret != 0) { + goto exit_dske; + } + } + 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; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + /* Nothing to do in this algo */ + break; + #endif /* HAVE_ECC */ + #if defined(HAVE_ED25519) + case ed25519_sa_algo: + /* Nothing to do in this algo */ + break; + #endif /* HAVE_ED25519 */ + #if defined(HAVE_ED448) + case ed448_sa_algo: + /* Nothing to do in this algo */ + break; + #endif /* HAVE_ED448 */ + default: + ret = ALGO_ID_E; + } /* switch (sigAlgo) */ + #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 && !HAVE_ED448 */ + break; + } + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + args->idx += MacSize(ssl); + #endif + } + + /* QSH extensions */ + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + word16 name; + int qshSz; + + /* extension name */ + 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 + args->idx, + size, 0)) < 0) { + ERROR_OUT(qshSz, exit_dske); + } + args->idx += qshSz; } else { - ret = wc_RsaPublicEncrypt(ssl->arrays->preMasterSecret, - SECRET_LEN, encSecret, MAX_ENCRYPT_SZ, - ssl->peerRsaKey, ssl->rng); - if (ret > 0) { - encSz = ret; - ret = 0; /* set success to 0 */ - } + /* unknown extension sent server ignored handshake */ + ERROR_OUT(BUFFER_ERROR, exit_dske); } - break; + } #endif - #ifndef NO_DH - case diffie_hellman_kea: - { - buffer serverP = ssl->buffers.serverDH_P; - buffer serverG = ssl->buffers.serverDH_G; - buffer serverPub = ssl->buffers.serverDH_Pub; - #ifdef WOLFSSL_SMALL_STACK - byte* priv = NULL; - #else - byte priv[ENCRYPT_LEN]; - #endif - word32 privSz = 0; - DhKey key; - if (serverP.buffer == 0 || serverG.buffer == 0 || - serverPub.buffer == 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; - #ifdef WOLFSSL_SMALL_STACK - priv = (byte*)XMALLOC(ENCRYPT_LEN, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (priv == NULL) { - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } - #endif + case TLS_ASYNC_END: + { + /* return index */ + *inOutIdx = args->idx; - wc_InitDhKey(&key); - ret = wc_DhSetKey(&key, serverP.buffer, serverP.length, - serverG.buffer, serverG.length); - if (ret == 0) - /* for DH, encSecret is Yc, agree is pre-master */ - ret = wc_DhGenerateKeyPair(&key, ssl->rng, priv, &privSz, - encSecret, &encSz); - if (ret == 0) - ret = wc_DhAgree(&key, ssl->arrays->preMasterSecret, - &ssl->arrays->preMasterSz, priv, privSz, - serverPub.buffer, serverPub.length); - #ifdef WOLFSSL_SMALL_STACK - XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - wc_FreeDhKey(&key); - } + ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_dske: + + WOLFSSL_LEAVE("DoServerKeyExchange", ret); + WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_DO); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not received so it can process again */ + ssl->msgsReceived.got_server_key_exchange = 0; + + return ret; + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Final cleanup */ + FreeDskeArgs(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} + + +#ifdef HAVE_QSH + +#ifdef HAVE_NTRU +/* Encrypt a byte array using ntru + key a struct containing the public key to use + bufIn array to be encrypted + inSz size of bufIn array + bufOut cipher text out + outSz will be set to the new size of cipher text + */ +static int NtruSecretEncrypt(QSHKey* key, byte* bufIn, word32 inSz, + byte* bufOut, word16* outSz) +{ + int ret; + DRBG_HANDLE drbg; + + /* sanity checks on input arguments */ + if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL) + return BAD_FUNC_ARG; + + if (key->pub.buffer == NULL) + return BAD_FUNC_ARG; + + switch (key->name) { + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + break; + default: + WOLFSSL_MSG("Unknown QSH encryption key!"); + return -1; + } + + /* set up ntru drbg */ + ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); + if (ret != DRBG_OK) + return NTRU_DRBG_ERROR; + + /* encrypt the byte array */ + ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length, key->pub.buffer, + inSz, bufIn, outSz, bufOut); + ntru_crypto_drbg_uninstantiate(drbg); + if (ret != NTRU_OK) + return NTRU_ENCRYPT_ERROR; + + return ret; +} + +/* Decrypt a byte array using ntru + key a struct containing the private key to use + bufIn array to be decrypted + inSz size of bufIn array + bufOut plain text out + outSz will be set to the new size of plain text + */ + +static int NtruSecretDecrypt(QSHKey* key, byte* bufIn, word32 inSz, + byte* bufOut, word16* outSz) +{ + int ret; + DRBG_HANDLE drbg; + + /* sanity checks on input arguments */ + if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL) + return BAD_FUNC_ARG; + + if (key->pri.buffer == NULL) + return BAD_FUNC_ARG; + + switch (key->name) { + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + break; + default: + WOLFSSL_MSG("Unknown QSH decryption key!"); + return -1; + } + + + /* set up drbg */ + ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); + if (ret != DRBG_OK) + return NTRU_DRBG_ERROR; + + /* decrypt cipher text */ + ret = ntru_crypto_ntru_decrypt(key->pri.length, key->pri.buffer, + inSz, bufIn, outSz, bufOut); + ntru_crypto_drbg_uninstantiate(drbg); + if (ret != NTRU_OK) + return NTRU_ENCRYPT_ERROR; + + return ret; +} +#endif /* HAVE_NTRU */ + +int QSH_Init(WOLFSSL* ssl) +{ + /* check so not initializing twice when running DTLS */ + if (ssl->QSH_secret != NULL) + return 0; + + /* malloc memory for holding generated secret information */ + if ((ssl->QSH_secret = (QSHSecret*)XMALLOC(sizeof(QSHSecret), ssl->heap, + DYNAMIC_TYPE_QSH)) == NULL) + return MEMORY_E; + + ssl->QSH_secret->CliSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap, + DYNAMIC_TYPE_SECRET); + if (ssl->QSH_secret->CliSi == NULL) + return MEMORY_E; + + ssl->QSH_secret->SerSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap, + DYNAMIC_TYPE_SECRET); + if (ssl->QSH_secret->SerSi == NULL) + return MEMORY_E; + + /* initialize variables */ + ssl->QSH_secret->list = NULL; + ssl->QSH_secret->CliSi->length = 0; + ssl->QSH_secret->CliSi->buffer = NULL; + ssl->QSH_secret->SerSi->length = 0; + ssl->QSH_secret->SerSi->buffer = NULL; + + return 0; +} + + +static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn, + byte* out, word32* szOut) +{ + int ret = 0; + word16 size = *szOut; + + (void)in; + (void)szIn; + (void)out; + (void)szOut; + + WOLFSSL_MSG("Encrypting QSH key material"); + + switch (key->name) { + #ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + ret = NtruSecretEncrypt(key, in, szIn, out, &size); + break; + #endif + default: + WOLFSSL_MSG("Unknown QSH encryption key!"); + return -1; + } + + *szOut = size; + + return ret; +} + + +/* Decrypt using Quantum Safe Handshake algorithms */ +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) { + #ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + ret = NtruSecretDecrypt(key, in, szIn, out, &size); + break; + #endif + default: + WOLFSSL_MSG("Unknown QSH decryption key!"); + return -1; + } + + *szOut = size; + + return ret; +} + + +/* Get the max cipher text for corresponding encryption scheme + (encrypting 48 or max plain text whichever is smaller) + */ +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]; +#endif + + if (key == NULL || key->pub.length == 0) + return 0; + + switch(key->name) { +#ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + isNtru = 1; break; - #endif /* NO_DH */ - #ifndef NO_PSK - case psk_kea: + case WOLFSSL_NTRU_EESS593: + isNtru = 1; + break; + case WOLFSSL_NTRU_EESS743: + isNtru = 1; + break; +#endif + default: + WOLFSSL_MSG("Unknown QSH encryption scheme size!"); + return 0; + } + +#ifdef HAVE_NTRU + if (isNtru) { + ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); + if (ret != DRBG_OK) + return NTRU_DRBG_ERROR; + ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length, + key->pub.buffer, inSz, bufIn, &outSz, NULL); + if (ret != NTRU_OK) { + return NTRU_ENCRYPT_ERROR; + } + ntru_crypto_drbg_uninstantiate(drbg); + ret = outSz; + } +#endif + + return ret; +} + +/* Generate the secret byte material for pms + returns length on success and -1 on fail + */ +static int QSH_GenerateSerCliSecret(WOLFSSL* ssl, byte isServer) +{ + int sz = 0; + int plainSz = 48; /* lesser of 48 and max plain text able to encrypt */ + int offset = 0; + word32 tmpSz = 0; + buffer* buf; + QSHKey* current; + QSHScheme* schmPre = NULL; + QSHScheme* schm = NULL; + + if (ssl == NULL) + return -1; + + WOLFSSL_MSG("Generating QSH secret key material"); + + current = ssl->peerQSHKey; + /* get size of buffer needed */ + while (current) { + if (current->pub.length != 0) { + sz += plainSz; + } + current = (QSHKey*)current->next; + } + + /* allocate memory for buffer */ + if (isServer) { + buf = ssl->QSH_secret->SerSi; + } + else { + buf = ssl->QSH_secret->CliSi; + } + buf->length = sz; + buf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_SECRET); + if (buf->buffer == NULL) { + WOLFSSL_ERROR(MEMORY_E); + } + + /* create secret information */ + sz = 0; + current = ssl->peerQSHKey; + while (current) { + schm = (QSHScheme*)XMALLOC(sizeof(QSHScheme), ssl->heap, + DYNAMIC_TYPE_QSH); + if (schm == NULL) + return MEMORY_E; + + /* initialize variables */ + schm->name = 0; + schm->PK = NULL; + schm->PKLen = 0; + schm->next = NULL; + if (ssl->QSH_secret->list == NULL) { + ssl->QSH_secret->list = schm; + } + else { + if (schmPre) + schmPre->next = schm; + } + + tmpSz = QSH_MaxSecret(current); + + if ((schm->PK = (byte*)XMALLOC(tmpSz, ssl->heap, + DYNAMIC_TYPE_SECRET)) == NULL) + return -1; + + /* store info for writing extension */ + schm->name = current->name; + + /* no key to use for encryption */ + if (tmpSz == 0) { + current = (QSHKey*)current->next; + continue; + } + + if (wc_RNG_GenerateBlock(ssl->rng, buf->buffer + offset, plainSz) + != 0) { + return -1; + } + if (QSH_Encrypt(current, buf->buffer + offset, plainSz, schm->PK, + &tmpSz) != 0) { + return -1; + } + schm->PKLen = tmpSz; + + sz += tmpSz; + offset += plainSz; + schmPre = schm; + current = (QSHKey*)current->next; + } + + return sz; +} + + +static word32 QSH_KeyGetSize(WOLFSSL* ssl) +{ + word32 sz = 0; + QSHKey* current; + + if (ssl == NULL) + return -1; + + current = ssl->peerQSHKey; + sz += OPAQUE16_LEN; /* type of extension ie 0x00 0x18 */ + sz += OPAQUE24_LEN; + /* get size of buffer needed */ + while (current) { + sz += OPAQUE16_LEN; /* scheme id */ + sz += OPAQUE16_LEN; /* encrypted key len*/ + sz += QSH_MaxSecret(current); + current = (QSHKey*)current->next; + } + + return sz; +} + + +/* handle QSH key Exchange + return 0 on success + */ +static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) +{ + int ret = 0; + + WOLFSSL_ENTER("QSH KeyExchange"); + + ret = QSH_GenerateSerCliSecret(ssl, isServer); + if (ret < 0) + return MEMORY_E; + + return 0; +} + +#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; + } +} + +/* handle generation client_key_exchange (16) */ +int SendClientKeyExchange(WOLFSSL* ssl) +{ + int ret = 0; +#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_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); + WOLFSSL_ENTER("SendClientKeyExchange"); + +#ifdef OPENSSL_EXTRA + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + ssl->cbmode = SSL_CB_MODE_WRITE; + if (ssl->CBIS != NULL) + ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS); +#endif + +#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_scke; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(SckeArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeSckeArgs; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + if (ssl->peerRsaKey == NULL || + ssl->peerRsaKeyPresent == 0) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + break; + #endif + #ifndef NO_DH + case diffie_hellman_kea: + if (ssl->buffers.serverDH_P.buffer == NULL || + ssl->buffers.serverDH_G.buffer == NULL || + ssl->buffers.serverDH_Pub.buffer == NULL) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + break; + #endif /* NO_DH */ + #ifndef NO_PSK + case psk_kea: + /* sanity check that PSK client callback has been set */ + if (ssl->options.client_psk_cb == NULL) { + WOLFSSL_MSG("No client PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_scke); + } + break; + #endif /* NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + if (ssl->buffers.serverDH_P.buffer == NULL || + ssl->buffers.serverDH_G.buffer == NULL || + ssl->buffers.serverDH_Pub.buffer == NULL) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + /* sanity check that PSK client callback has been set */ + if (ssl->options.client_psk_cb == NULL) { + WOLFSSL_MSG("No client PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_scke); + } + break; + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + /* sanity check that PSK client callback has been set */ + if (ssl->options.client_psk_cb == NULL) { + WOLFSSL_MSG("No client PSK callback set"); + 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 + #ifdef HAVE_CURVE448 + if (ssl->peerX448KeyPresent) { + /* Check client ECC public key */ + if (!ssl->peerX448Key) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X448SharedSecretCb != NULL) { + break; + } + #endif + + /* create private key */ + ssl->hsType = DYNAMIC_TYPE_CURVE448; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_scke; + } + + ret = X448MakeKey(ssl, (curve448_key*)ssl->hsKey, + ssl->peerX448Key); + break; + } + #endif + /* Check client ECC public key */ + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || + !ssl->peerEccKey->dp) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + /* create ephemeral private key */ + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_scke; + } + + ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, ssl->peerEccKey); + + break; + #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + if (ssl->peerNtruKeyPresent == 0) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + break; + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + case ecc_diffie_hellman_kea: + { + #ifdef HAVE_ECC + ecc_key* peerKey; + #endif + + #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 + #ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) { + if (ssl->ctx->X448SharedSecretCb != NULL) + break; + } + else + #endif + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #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_CURVE448 + if (ssl->peerX448KeyPresent) { + if (!ssl->peerX448Key) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + /* create private key */ + ssl->hsType = DYNAMIC_TYPE_CURVE448; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_scke; + } + + ret = X448MakeKey(ssl, (curve448_key*)ssl->hsKey, + ssl->peerX448Key); + break; + } + #endif + #ifdef HAVE_ECC + if (ssl->specs.static_ecdh) { + /* Note: EccDsa is really fixed Ecc key here */ + if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + peerKey = ssl->peerEccDsaKey; + } + else { + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + peerKey = ssl->peerEccKey; + } + if (peerKey == NULL) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + /* create ephemeral private key */ + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_scke; + } + + ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, peerKey); + #endif + + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + 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); + } + if (ssl->arrays->preMasterSecret == NULL) { + ssl->arrays->preMasterSz = ENCRYPT_LEN; + ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_SECRET); + if (ssl->arrays->preMasterSecret == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); + } + XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN); + } + + switch(ssl->specs.kea) + { + #ifndef NO_RSA + case rsa_kea: + { + /* build PreMasterSecret with RNG data */ + #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + if (tsip_useable(ssl)) { + ret = tsip_generatePremasterSecret( + &ssl->arrays->preMasterSecret[VERSION_SZ], + ENCRYPT_LEN - VERSION_SZ); + } else { + #endif + ret = wc_RNG_GenerateBlock(ssl->rng, + &ssl->arrays->preMasterSecret[VERSION_SZ], + SECRET_LEN - VERSION_SZ); + #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + } + #endif + if (ret != 0) { + goto exit_scke; + } + + ssl->arrays->preMasterSecret[0] = ssl->chVersion.major; + ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor; + + ssl->arrays->preMasterSz = SECRET_LEN; + + break; + } + #endif /* !NO_RSA */ + #ifndef NO_DH + case diffie_hellman_kea: + { + ssl->buffers.sig.length = ENCRYPT_LEN; + 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; + } + + #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ + !defined(WOLFSSL_OLD_PRIME_CHECK) + if (ssl->options.dhDoKeyTest && + !ssl->options.dhKeyTested) + { + ret = wc_DhSetCheckKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length, + NULL, 0, 0, ssl->rng); + if (ret != 0) { + goto exit_scke; + } + ssl->options.dhKeyTested = 1; + } + else + #endif + { + 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, (word32*)&ssl->buffers.sig.length, + args->encSecret, &args->encSz); + + /* set the max agree result size */ + ssl->arrays->preMasterSz = ENCRYPT_LEN; + break; + } + #endif /* !NO_DH */ + #ifndef NO_PSK + case psk_kea: { byte* pms = ssl->arrays->preMasterSecret; - 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) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return PSK_KEY_ERROR; + ERROR_OUT(PSK_KEY_ERROR, exit_scke); } - encSz = (word32)XSTRLEN(ssl->arrays->client_identity); - if (encSz > MAX_PSK_ID_LEN) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return CLIENT_ID_ERROR; + 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; } - break; - #endif /* NO_PSK */ - #if !defined(NO_DH) && !defined(NO_PSK) - case dhe_psk_kea: + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: { - byte* pms = ssl->arrays->preMasterSecret; - byte* es = encSecret; - buffer serverP = ssl->buffers.serverDH_P; - buffer serverG = ssl->buffers.serverDH_G; - buffer serverPub = ssl->buffers.serverDH_Pub; - #ifdef WOLFSSL_SMALL_STACK - byte* priv = NULL; - #else - byte priv[ENCRYPT_LEN]; - #endif - word32 privSz = 0; - word32 pubSz = 0; - word32 esSz = 0; - DhKey key; - - if (serverP.buffer == 0 || serverG.buffer == 0 || - serverPub.buffer == 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } + word32 esSz = 0; + args->output = args->encSecret; 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) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return PSK_KEY_ERROR; + 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) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return CLIENT_ID_ERROR; + ERROR_OUT(CLIENT_ID_ERROR, exit_scke); } - #ifdef WOLFSSL_SMALL_STACK - priv = (byte*)XMALLOC(ENCRYPT_LEN, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (priv == NULL) { - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; + ssl->buffers.sig.length = ENCRYPT_LEN; + 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); } - #endif - c16toa((word16)esSz, es); - es += OPAQUE16_LEN; - XMEMCPY(es, ssl->arrays->client_identity, esSz); - es += esSz; - encSz = esSz + OPAQUE16_LEN; - wc_InitDhKey(&key); - ret = wc_DhSetKey(&key, serverP.buffer, serverP.length, - serverG.buffer, serverG.length); - if (ret == 0) - /* for DH, encSecret is Yc, agree is pre-master */ - ret = wc_DhGenerateKeyPair(&key, ssl->rng, priv, &privSz, - es + OPAQUE16_LEN, &pubSz); - if (ret == 0) - ret = wc_DhAgree(&key, pms + OPAQUE16_LEN, - &ssl->arrays->preMasterSz, priv, privSz, - serverPub.buffer, serverPub.length); - wc_FreeDhKey(&key); - #ifdef WOLFSSL_SMALL_STACK - XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + 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; + + args->length = 0; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; + goto exit_scke; } - c16toa((word16)pubSz, es); - encSz += pubSz + OPAQUE16_LEN; + #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ + !defined(WOLFSSL_OLD_PRIME_CHECK) + if (ssl->options.dhDoKeyTest && + !ssl->options.dhKeyTested) + { + ret = wc_DhSetCheckKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length, + NULL, 0, 0, ssl->rng); + if (ret != 0) { + goto exit_scke; + } + ssl->options.dhKeyTested = 1; + } + else + #endif + { + 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, (word32*)&ssl->buffers.sig.length, + args->output + OPAQUE16_LEN, &args->length); + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + word32 esSz = 0; + args->output = args->encSecret; + + /* Send PSK client identity */ + 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) { + 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, 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 */ + args->length = MAX_ENCRYPT_SZ; + + /* Create shared ECC key leaving room at the beginning + 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_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X448SharedSecretCb != NULL) { + break; + } + #endif + + ret = wc_curve448_export_public_ex( + (curve448_key*)ssl->hsKey, + args->output + OPAQUE8_LEN, &args->length, + EC448_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) { + break; + } + #endif + + /* 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 || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + ret = wc_RNG_GenerateBlock(ssl->rng, + ssl->arrays->preMasterSecret, SECRET_LEN); + if (ret != 0) { + goto exit_scke; + } + + ssl->arrays->preMasterSz = SECRET_LEN; + args->encSz = MAX_ENCRYPT_SZ; + break; + } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + 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_CURVE448 + if (ssl->hsType == DYNAMIC_TYPE_CURVE448) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X448SharedSecretCb != NULL) { + break; + } + #endif + + ret = wc_curve448_export_public_ex( + (curve448_key*)ssl->hsKey, + args->encSecret + OPAQUE8_LEN, &args->encSz, + EC448_LITTLE_ENDIAN); + if (ret != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); + } + + break; + } + #endif + #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + /* Place ECC key in buffer, leaving room for size */ + 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 || HAVE_CURVE25519 || HAVE_CURVE448 */ + + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + switch(ssl->specs.kea) + { + #ifndef NO_RSA + case rsa_kea: + { + #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + if (tsip_useable(ssl) && + wc_RsaEncryptSize(ssl->peerRsaKey) == 256) { + ret = tsip_generateEncryptPreMasterSecret(ssl, + args->encSecret, + &args->encSz); + + } else + #endif + ret = RsaEnc(ssl, + ssl->arrays->preMasterSecret, SECRET_LEN, + args->encSecret, &args->encSz, + ssl->peerRsaKey, + #if defined(HAVE_PK_CALLBACKS) + &ssl->buffers.peerRsaKey + #else + NULL + #endif + ); + + break; + } + #endif /* !NO_RSA */ + #ifndef NO_DH + case diffie_hellman_kea: + { + 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, + &ssl->arrays->preMasterSz); + break; + } + #endif /* !NO_DH */ + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + 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, + &ssl->arrays->preMasterSz); + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + #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 + ); + if (!ssl->specs.static_ecdh + #ifdef WOLFSSL_ASYNC_CRYPT + && ret != WC_PENDING_E + #endif + ) { + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + } + break; + } + #endif + #ifdef HAVE_CURVE448 + if (ssl->peerX448KeyPresent) { + ret = X448SharedSecret(ssl, + (curve448_key*)ssl->hsKey, ssl->peerX448Key, + args->output + OPAQUE8_LEN, &args->length, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &ssl->arrays->preMasterSz, + WOLFSSL_CLIENT_END + ); + if (!ssl->specs.static_ecdh + #ifdef WOLFSSL_ASYNC_CRYPT + && ret != WC_PENDING_E + #endif + ) { + FreeKey(ssl, DYNAMIC_TYPE_CURVE448, + (void**)&ssl->peerX448Key); + ssl->peerX448KeyPresent = 0; + } + break; + } + #endif + ret = EccSharedSecret(ssl, + (ecc_key*)ssl->hsKey, ssl->peerEccKey, + args->output + OPAQUE8_LEN, &args->length, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &ssl->arrays->preMasterSz, + WOLFSSL_CLIENT_END + ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + FreeKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + } + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !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); + if (rc != DRBG_OK) { + ERROR_OUT(NTRU_DRBG_ERROR, exit_scke); + } + rc = ntru_crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen, + ssl->peerNtruKey, + ssl->arrays->preMasterSz, + ssl->arrays->preMasterSecret, + &tmpEncSz, + args->encSecret); + args->encSz = tmpEncSz; + ntru_crypto_drbg_uninstantiate(drbg); + if (rc != NTRU_OK) { + ERROR_OUT(NTRU_ENCRYPT_ERROR, exit_scke); + } + ret = 0; + break; + } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + case ecc_diffie_hellman_kea: + { + #ifdef HAVE_ECC + ecc_key* peerKey; + #endif + + #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 + ); + if (!ssl->specs.static_ecdh + #ifdef WOLFSSL_ASYNC_CRYPT + && ret != WC_PENDING_E + #endif + ) { + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + } + break; + } + #endif + #ifdef HAVE_CURVE448 + if (ssl->peerX448KeyPresent) { + ret = X448SharedSecret(ssl, + (curve448_key*)ssl->hsKey, ssl->peerX448Key, + args->encSecret + OPAQUE8_LEN, &args->encSz, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + WOLFSSL_CLIENT_END + ); + if (!ssl->specs.static_ecdh + #ifdef WOLFSSL_ASYNC_CRYPT + && ret != WC_PENDING_E + #endif + ) { + FreeKey(ssl, DYNAMIC_TYPE_CURVE448, + (void**)&ssl->peerX448Key); + ssl->peerX448KeyPresent = 0; + } + break; + } + #endif + #ifdef HAVE_ECC + peerKey = (ssl->specs.static_ecdh) ? + ssl->peerEccDsaKey : ssl->peerEccKey; + + ret = EccSharedSecret(ssl, + (ecc_key*)ssl->hsKey, peerKey, + args->encSecret + OPAQUE8_LEN, &args->encSz, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + WOLFSSL_CLIENT_END + ); + if (!ssl->specs.static_ecdh + #ifdef WOLFSSL_ASYNC_CRYPT + && ret != WC_PENDING_E + #endif + && !ssl->options.keepResources) { + FreeKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + } + #endif + + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + switch(ssl->specs.kea) + { + #ifndef NO_RSA + case rsa_kea: + { + break; + } + #endif /* !NO_RSA */ + #ifndef NO_DH + case diffie_hellman_kea: + { + break; + } + #endif /* !NO_DH */ + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + + /* validate args */ + if (args->output == NULL || args->length == 0) { + ERROR_OUT(BAD_FUNC_ARG, exit_scke); + } + + 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; @@ -10693,628 +23126,865 @@ static void PickHashSigAlgo(WOLFSSL* ssl, pms += OPAQUE16_LEN; XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); ssl->arrays->preMasterSz += - ssl->arrays->psk_keySz + OPAQUE16_LEN; + ssl->arrays->psk_keySz + OPAQUE16_LEN; ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); ssl->arrays->psk_keySz = 0; /* No further need */ + break; } - break; - #endif /* !NO_DH && !NO_PSK */ - #ifdef HAVE_NTRU - case ntru_kea: + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: { - word32 rc; - word16 cipherLen = MAX_ENCRYPT_SZ; - DRBG_HANDLE drbg; - static uint8_t const wolfsslStr[] = { - 'C', 'y', 'a', 'S', 'S', 'L', ' ', 'N', 'T', 'R', 'U' - }; + byte* pms = ssl->arrays->preMasterSecret; - ret = wc_RNG_GenerateBlock(ssl->rng, - ssl->arrays->preMasterSecret, SECRET_LEN); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; + /* validate args */ + if (args->output == NULL || args->length > ENCRYPT_LEN) { + ERROR_OUT(BAD_FUNC_ARG, exit_scke); } - ssl->arrays->preMasterSz = SECRET_LEN; + /* place size of public key in output buffer */ + *args->output = (byte)args->length; + args->encSz += args->length + OPAQUE8_LEN; - if (ssl->peerNtruKeyPresent == 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } + /* Create pre master secret is the concatenation of + eccSize + eccSharedKey + pskSize + pskKey */ + c16toa((word16)ssl->arrays->preMasterSz, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN; + pms += ssl->arrays->preMasterSz; - rc = ntru_crypto_drbg_instantiate(MAX_NTRU_BITS, wolfsslStr, - sizeof(wolfsslStr), GetEntropy, - &drbg); - if (rc != DRBG_OK) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NTRU_DRBG_ERROR; - } + 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; - rc = ntru_crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen, - ssl->peerNtruKey, - ssl->arrays->preMasterSz, - ssl->arrays->preMasterSecret, - &cipherLen, encSecret); - ntru_crypto_drbg_uninstantiate(drbg); - if (rc != NTRU_OK) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NTRU_ENCRYPT_ERROR; - } - - encSz = cipherLen; - ret = 0; + ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->psk_keySz = 0; /* No further need */ + break; } - break; - #endif /* HAVE_NTRU */ - #ifdef HAVE_ECC - case ecc_diffie_hellman_kea: + #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: { - ecc_key myKey; - ecc_key* peerKey = NULL; - word32 size = MAX_ENCRYPT_SZ; - - if (ssl->specs.static_ecdh) { - /* TODO: EccDsa is really fixed Ecc change naming */ - if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent || - !ssl->peerEccDsaKey->dp) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } - peerKey = ssl->peerEccDsaKey; - } - else { - if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || - !ssl->peerEccKey->dp) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } - peerKey = ssl->peerEccKey; - } - - if (peerKey == NULL) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } - - wc_ecc_init(&myKey); - ret = wc_ecc_make_key(ssl->rng, peerKey->dp->size, &myKey); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ECC_MAKEKEY_ERROR; - } - - /* precede export with 1 byte length */ - ret = wc_ecc_export_x963(&myKey, encSecret + 1, &size); - encSecret[0] = (byte)size; - encSz = size + 1; - - if (ret != 0) - ret = ECC_EXPORT_ERROR; - else { - size = sizeof(ssl->arrays->preMasterSecret); - ret = wc_ecc_shared_secret(&myKey, peerKey, - ssl->arrays->preMasterSecret, &size); - if (ret != 0) - ret = ECC_SHARED_ERROR; - } - - ssl->arrays->preMasterSz = size; - wc_ecc_free(&myKey); + break; } - break; - #endif /* HAVE_ECC */ - default: - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ALGO_ID_E; /* unsupported kea */ - } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + case ecc_diffie_hellman_kea: + { + /* place size of public key in buffer */ + *args->encSecret = (byte)args->encSz; + args->encSz += OPAQUE8_LEN; + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ - if (ret == 0) { - byte *output; - int sendSz; - word32 tlsSz = 0; + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ - if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea) + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + word32 tlsSz = 0; + word32 idx = 0; + + #ifdef HAVE_QSH + word32 qshSz = 0; + if (ssl->peerQSHKeyPresent) { + qshSz = QSH_KeyGetSize(ssl); + } + #endif + + if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea) { tlsSz = 2; + } if (ssl->specs.kea == ecc_diffie_hellman_kea || - ssl->specs.kea == dhe_psk_kea) /* always off */ + ssl->specs.kea == dhe_psk_kea || + ssl->specs.kea == ecdhe_psk_kea) { /* always off */ tlsSz = 0; + } - sendSz = encSz + tlsSz + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; - idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->encSz + tlsSz + idx; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; - idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; - } - #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; + args->sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; + } + #endif - if (ssl->keys.encryptionOn) - sendSz += MAX_MSG_EXTRA; + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + #ifdef HAVE_QSH + args->encSz += qshSz; + args->sendSz += qshSz; + #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_scke; } - /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + /* get output buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; - AddHeaders(output, encSz + tlsSz, client_key_exchange, ssl); + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + byte idxSave = idx; + idx = args->sendSz - qshSz; + if (QSH_KeyExchangeWrite(ssl, 0) != 0) { + ERROR_OUT(MEMORY_E, exit_scke); + } + + /* extension type */ + 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, + args->output + idx) > qshSz - OPAQUE16_LEN) { + ERROR_OUT(MEMORY_E, exit_scke); + } + + idx = idxSave; + } + #endif + + AddHeaders(args->output, args->encSz + tlsSz, client_key_exchange, ssl); + + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + 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 (ssl->keys.encryptionOn) { - byte* input; - int inputSz = idx-RECORD_HEADER_SZ; /* buildmsg adds rechdr */ - - input = (byte*)XMALLOC(inputSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (input == NULL) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return MEMORY_E; + if (IsEncryptionOn(ssl, 1)) { + 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); - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (sendSz < 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return sendSz; - } - } else { - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + args->inputSz); } - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } - } - #endif + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ClientKeyExchange", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo, - output, sendSz, ssl->heap); - #endif - - ssl->buffers.outputBuffer.length += sendSz; - - if (ssl->options.groupMessages) - ret = 0; - else - ret = SendBuffered(ssl); - } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - if (ret == 0 || ret == WANT_WRITE) { - int tmpRet = MakeMasterSecret(ssl); - if (tmpRet != 0) - ret = tmpRet; /* save WANT_WRITE unless more serious */ - ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; - } - /* No further need for PMS */ - ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); - ssl->arrays->preMasterSz = 0; - - return ret; - } - -#ifndef NO_CERTS - int SendCertificateVerify(WOLFSSL* ssl) - { - byte *output; - int sendSz = MAX_CERT_VERIFY_SZ, length, ret; - word32 idx = 0; - word32 sigOutSz = 0; -#ifndef NO_RSA - RsaKey key; - int initRsaKey = 0; -#endif - int usingEcc = 0; -#ifdef HAVE_ECC - ecc_key eccKey; -#endif - - (void)idx; - - if (ssl->options.sendVerify == SEND_BLANK_CERT) - return 0; /* sent blank cert, can't verify */ - - if (ssl->keys.encryptionOn) - sendSz += MAX_MSG_EXTRA; - - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) - return ret; - - /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; - - ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); - if (ret != 0) - return ret; - -#ifdef HAVE_ECC - wc_ecc_init(&eccKey); -#endif -#ifndef NO_RSA - ret = wc_InitRsaKey(&key, ssl->heap); - if (ret == 0) initRsaKey = 1; - if (ret == 0) - ret = wc_RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key, - ssl->buffers.key.length); - if (ret == 0) - sigOutSz = wc_RsaEncryptSize(&key); - else -#endif + case TLS_ASYNC_END: { - #ifdef HAVE_ECC - WOLFSSL_MSG("Trying ECC client cert, RSA didn't work"); + 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 */ - idx = 0; - ret = wc_EccPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &eccKey, - ssl->buffers.key.length); - if (ret == 0) { - WOLFSSL_MSG("Using ECC client cert"); - usingEcc = 1; - sigOutSz = MAX_ENCODED_SIG_SZ; + if (ret >= 0) { + args->sendSz = ret; + ret = 0; + } } else { - WOLFSSL_MSG("Bad client cert type"); - } - #endif - } - if (ret == 0) { - byte* verify = (byte*)&output[RECORD_HEADER_SZ + - HANDSHAKE_HEADER_SZ]; -#ifndef NO_OLD_TLS - byte* signBuffer = ssl->hsHashes->certHashes.md5; -#else - byte* signBuffer = NULL; -#endif - word32 signSz = FINISHED_SZ; - word32 extraSz = 0; /* tls 1.2 hash/sig */ -#ifdef WOLFSSL_SMALL_STACK - byte* encodedSig = NULL; -#else - byte encodedSig[MAX_ENCODED_SIG_SZ]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig == NULL) { - #ifndef NO_RSA - if (initRsaKey) - wc_FreeRsaKey(&key); - #endif - #ifdef HAVE_ECC - wc_ecc_free(&eccKey); - #endif - return MEMORY_E; - } -#endif - - (void)encodedSig; - (void)signSz; - (void)signBuffer; - #ifdef WOLFSSL_DTLS if (ssl->options.dtls) - verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + DtlsSEQIncrement(ssl, CUR_ORDER); #endif - length = sigOutSz; - if (IsAtLeastTLSv1_2(ssl)) { - verify[0] = ssl->suites->hashAlgo; - verify[1] = usingEcc ? ecc_dsa_sa_algo : rsa_sa_algo; - extraSz = HASH_SIG_SIZE; + ret = HashOutput(ssl, args->output, args->sendSz, 0); } - if (usingEcc) { -#ifdef HAVE_ECC - word32 localSz = MAX_ENCODED_SIG_SZ; - word32 digestSz; - byte* digest; - byte doUserEcc = 0; -#ifndef NO_OLD_TLS - /* old tls default */ - digestSz = SHA_DIGEST_SIZE; - digest = ssl->hsHashes->certHashes.sha; -#else - /* new tls default */ - digestSz = SHA256_DIGEST_SIZE; - digest = ssl->hsHashes->certHashes.sha256; -#endif - - #ifdef HAVE_PK_CALLBACKS - #ifdef HAVE_ECC - if (ssl->ctx->EccSignCb) - doUserEcc = 1; - #endif /* HAVE_ECC */ - #endif /*HAVE_PK_CALLBACKS */ - - if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->suites->hashAlgo == sha_mac) { - #ifndef NO_SHA - digest = ssl->hsHashes->certHashes.sha; - digestSz = SHA_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = ssl->hsHashes->certHashes.sha256; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = ssl->hsHashes->certHashes.sha384; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = ssl->hsHashes->certHashes.sha512; - digestSz = SHA512_DIGEST_SIZE; - #endif - } - } - - if (doUserEcc) { - #ifdef HAVE_PK_CALLBACKS - #ifdef HAVE_ECC - ret = ssl->ctx->EccSignCb(ssl, digest, digestSz, - encodedSig, &localSz, - ssl->buffers.key.buffer, - ssl->buffers.key.length, - ssl->EccSignCtx); - #endif /* HAVE_ECC */ - #endif /*HAVE_PK_CALLBACKS */ - } - else { - ret = wc_ecc_sign_hash(digest, digestSz, encodedSig, - &localSz, ssl->rng, &eccKey); - } - if (ret == 0) { - length = localSz; - c16toa((word16)length, verify + extraSz); /* prepend hdr */ - XMEMCPY(verify + extraSz + VERIFY_HEADER,encodedSig,length); - } -#endif + if (ret != 0) { + goto exit_scke; } -#ifndef NO_RSA - else { - byte doUserRsa = 0; - #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->RsaSignCb) - doUserRsa = 1; - #endif /*HAVE_PK_CALLBACKS */ - - if (IsAtLeastTLSv1_2(ssl)) { - /* - * MSVC Compiler complains because it can not - * guarantee any of the conditionals will succeed in - * assigning a value before wc_EncodeSignature executes. - */ - byte* digest = NULL; - int digestSz = 0; - int typeH = 0; - int didSet = 0; - - if (ssl->suites->hashAlgo == sha_mac) { - #ifndef NO_SHA - digest = ssl->hsHashes->certHashes.sha; - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; - didSet = 1; - #endif - } - else if (ssl->suites->hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = ssl->hsHashes->certHashes.sha256; - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - didSet = 1; - #endif - } - else if (ssl->suites->hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = ssl->hsHashes->certHashes.sha384; - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - didSet = 1; - #endif - } - else if (ssl->suites->hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = ssl->hsHashes->certHashes.sha512; - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - didSet = 1; - #endif - } - - if (didSet == 0) { - /* defaults */ - #ifndef NO_OLD_TLS - digest = ssl->hsHashes->certHashes.sha; - digestSz = SHA_DIGEST_SIZE; - typeH = SHAh; - #else - digest = ssl->hsHashes->certHashes.sha256; - digestSz = SHA256_DIGEST_SIZE; - typeH = SHA256h; - #endif - } - - signSz = wc_EncodeSignature(encodedSig, digest,digestSz,typeH); - signBuffer = encodedSig; + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) { + goto exit_scke; } - - c16toa((word16)length, verify + extraSz); /* prepend hdr */ - if (doUserRsa) { - #ifdef HAVE_PK_CALLBACKS - #ifndef NO_RSA - word32 ioLen = ENCRYPT_LEN; - ret = ssl->ctx->RsaSignCb(ssl, signBuffer, signSz, - verify + extraSz + VERIFY_HEADER, - &ioLen, - ssl->buffers.key.buffer, - ssl->buffers.key.length, - ssl->RsaSignCtx); - #endif /* NO_RSA */ - #endif /*HAVE_PK_CALLBACKS */ - } - else { - ret = wc_RsaSSL_Sign(signBuffer, signSz, verify + extraSz + - VERIFY_HEADER, ENCRYPT_LEN, &key, ssl->rng); - } - - if (ret > 0) - ret = 0; /* RSA reset */ } -#endif -#ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + #endif - if (ret == 0) { - AddHeaders(output, length + extraSz + VERIFY_HEADER, - certificate_verify, ssl); + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "ClientKeyExchange"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "ClientKeyExchange", handshake, + args->output, args->sendSz, WRITE_PROTO, ssl->heap); + #endif - sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length + - extraSz + VERIFY_HEADER; + ssl->buffers.outputBuffer.length += args->sendSz; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - } - #endif - - if (ssl->keys.encryptionOn) { - byte* input; - int inputSz = sendSz - RECORD_HEADER_SZ; - /* build msg adds rec hdr */ - input = (byte*)XMALLOC(inputSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (input == NULL) - ret = MEMORY_E; - else { - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); - sendSz = BuildMessage(ssl, output, - MAX_CERT_VERIFY_SZ +MAX_MSG_EXTRA, - input, inputSz, handshake); - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - - if (sendSz < 0) - ret = sendSz; - } - } else { - ret = HashOutput(ssl, output, sendSz, 0); - } - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) - return ret; - } - #endif + if (!ssl->options.groupMessages) { + ret = SendBuffered(ssl); } + if (ret == 0 || ret == WANT_WRITE) { + int tmpRet = MakeMasterSecret(ssl); + if (tmpRet != 0) { + ret = tmpRet; /* save WANT_WRITE unless more serious */ + } + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + } + break; } -#ifndef NO_RSA - if (initRsaKey) - wc_FreeRsaKey(&key); -#endif -#ifdef HAVE_ECC - wc_ecc_free(&eccKey); + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_scke: + + WOLFSSL_LEAVE("SendClientKeyExchange", ret); + WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) + return ret; #endif - if (ret == 0) { - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("CertificateVerify", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("CertificateVerify", &ssl->timeoutInfo, - output, sendSz, ssl->heap); - #endif - ssl->buffers.outputBuffer.length += sendSz; - if (ssl->options.groupMessages) - return 0; - else - return SendBuffered(ssl); - } - else - return ret; + /* No further need for PMS */ + if (ssl->arrays->preMasterSecret != NULL) { + ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); } + ssl->arrays->preMasterSz = 0; + + /* Final cleanup */ + FreeSckeArgs(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifndef NO_CERTS + +#ifdef HAVE_PK_CALLBACKS + int GetPrivateKeySigSize(WOLFSSL* ssl) + { + int sigSz = 0; + + if (ssl == NULL) + return 0; + + switch (ssl->buffers.keyType) { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif + case rsa_sa_algo: + sigSz = ssl->buffers.keySz; + ssl->hsType = DYNAMIC_TYPE_RSA; + break; + #endif + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + sigSz = wc_ecc_sig_size_calc(ssl->buffers.keySz); + ssl->hsType = DYNAMIC_TYPE_ECC; + break; + #endif + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + sigSz = ED25519_SIG_SIZE; /* fixed known value */ + ssl->hsType = DYNAMIC_TYPE_ED25519; + break; + #endif + #ifdef HAVE_ED448 + case ed448_sa_algo: + sigSz = ED448_SIG_SIZE; /* fixed known value */ + ssl->hsType = DYNAMIC_TYPE_ED448; + break; + #endif + default: + break; + } + return sigSz; + } +#endif /* HAVE_PK_CALLBACKS */ + +#ifndef WOLFSSL_NO_TLS12 + +#ifndef WOLFSSL_NO_CLIENT_AUTH +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; + } +} + +/* handle generation of certificate_verify (15) */ +int SendCertificateVerify(WOLFSSL* ssl) +{ + 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_START(WC_FUNC_CERTIFICATE_VERIFY_SEND); + WOLFSSL_ENTER("SendCertificateVerify"); + +#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(ScvArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeScvArgs; + #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 + MAX_MSG_EXTRA; + if (IsEncryptionOn(ssl, 1)) { + 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: + { + ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); + if (ret != 0) { + goto exit_scv; + } + + if (ssl->buffers.key == NULL) { + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) + args->length = GetPrivateKeySigSize(ssl); + else + #endif + ERROR_OUT(NO_PRIVATE_KEY, exit_scv); + } + else { + /* Decode private key. */ + ret = DecodePrivateKey(ssl, &args->length); + if (ret != 0) { + goto exit_scv; + } + } + + if (args->length == 0) { + ERROR_OUT(NO_PRIVATE_KEY, exit_scv); + } + + /* 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]; + 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_SIGNATURE); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + 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 */ + SetDigest(ssl, sha_mac); + #endif + #else + #ifndef NO_SHA256 + /* new tls default */ + SetDigest(ssl, sha256_mac); + #endif + #endif /* !NO_OLD_TLS */ + + 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; + else if (ssl->hsType == DYNAMIC_TYPE_ED448) + args->sigAlgo = ed448_sa_algo; + + 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 and SHA hash as value to sign */ + XMEMCPY(ssl->buffers.sig.buffer, + (byte*)ssl->hsHashes->certHashes.md5, FINISHED_SZ); + } + #endif + + #ifndef NO_RSA + if (args->sigAlgo == rsa_sa_algo) { + ssl->buffers.sig.length = FINISHED_SZ; + 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, + TypeHash(ssl->suites->hashAlgo)); + } + + /* prepend hdr */ + c16toa(args->length, args->verify + args->extraSz); + } + #ifdef WC_RSA_PSS + 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 + #endif /* !NO_RSA */ + #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH) + if (args->sigAlgo == ed25519_sa_algo) { + ret = Ed25519CheckPubKey(ssl); + if (ret != 0) + goto exit_scv; + } + #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */ + #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH) + if (args->sigAlgo == ed448_sa_algo) { + ret = Ed448CheckPubKey(ssl); + if (ret != 0) + goto exit_scv; + } + #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */ + + /* 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) { + ecc_key* key = (ecc_key*)ssl->hsKey; + + ret = EccSign(ssl, + ssl->buffers.digest.buffer, ssl->buffers.digest.length, + ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length, + key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + } + #endif /* HAVE_ECC */ + #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH) + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + ed25519_key* key = (ed25519_key*)ssl->hsKey; + + ret = Ed25519Sign(ssl, + ssl->hsHashes->messages, ssl->hsHashes->length, + ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length, + key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + } + #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */ + #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH) + if (ssl->hsType == DYNAMIC_TYPE_ED448) { + ed448_key* key = (ed448_key*)ssl->hsKey; + + ret = Ed448Sign(ssl, + ssl->hsHashes->messages, ssl->hsHashes->length, + ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length, + key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + } + #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */ + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + RsaKey* key = (RsaKey*)ssl->hsKey; + + /* restore verify pointer */ + args->verify = &args->output[args->idx]; + + ret = RsaSign(ssl, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, + args->verify + args->extraSz + VERIFY_HEADER, &args->sigSz, + args->sigAlgo, ssl->suites->hashAlgo, key, + ssl->buffers.key + ); + } + #endif /* !NO_RSA */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + /* restore verify pointer */ + args->verify = &args->output[args->idx]; + + switch (ssl->hsType) { + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + #endif + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + #endif + #ifdef HAVE_ED448 + case DYNAMIC_TYPE_ED448: + #endif + 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); + break; + #endif + #ifndef NO_RSA + case 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(args->verifySig, args->verify + args->extraSz + + VERIFY_HEADER, args->sigSz); + } + + /* check for signature faults */ + ret = VerifyRsaSign(ssl, + args->verifySig, args->sigSz, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, + args->sigAlgo, ssl->suites->hashAlgo, key, + ssl->buffers.key + ); + break; + } + #endif /* !NO_RSA */ + default: + break; + } + + /* 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: + { + if (args->output == NULL) { + ERROR_OUT(BUFFER_ERROR, exit_scv); + } + AddHeaders(args->output, (word32)args->length + args->extraSz + + VERIFY_HEADER, certificate_verify, ssl); + + args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + + (word32)args->length + args->extraSz + VERIFY_HEADER; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif + + if (IsEncryptionOn(ssl, 1)) { + args->inputSz = args->sendSz - RECORD_HEADER_SZ; + /* build msg adds rec hdr */ + args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, + DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + 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, + 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, args->output, args->sendSz, 0); + } + + if (ret != 0) { + goto exit_scv; + } + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz); + } + #endif + + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "CertificateVerify"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "CertificateVerify", handshake, + args->output, args->sendSz, WRITE_PROTO, 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("SendCertificateVerify", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + return ret; + } +#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; +} +#endif /* WOLFSSL_NO_CLIENT_AUTH */ + +#endif /* WOLFSSL_NO_TLS12 */ + #endif /* NO_CERTS */ + #ifdef HAVE_SESSION_TICKET -int DoSessionTicket(WOLFSSL* ssl, - const byte* input, word32* inOutIdx, word32 size) +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 + * supersede the existing session cache info. */ + ssl->options.haveSessionId = 1; +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + XMEMCPY(ssl->session.sessionID, + ssl->session.ticket + length - ID_LEN, ID_LEN); + } + else +#endif + XMEMCPY(ssl->arrays->sessionID, + ssl->session.ticket + length - ID_LEN, ID_LEN); + } + + return 0; +} + +#ifndef WOLFSSL_NO_TLS12 + +/* handle processing of session_ticket (4) */ +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"); return SESSION_TICKET_EXPECT_E; } - if ((*inOutIdx - begin) + OPAQUE32_LEN > size) + if (OPAQUE32_LEN > size) return BUFFER_ERROR; ato32(input + *inOutIdx, &lifetime); @@ -11326,60 +23996,138 @@ int DoSessionTicket(WOLFSSL* ssl, ato16(input + *inOutIdx, &length); *inOutIdx += OPAQUE16_LEN; - if (length > sizeof(ssl->session.ticket)) - return SESSION_TICKET_LEN_E; - if ((*inOutIdx - begin) + length > size) return BUFFER_ERROR; - /* 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 (ssl->keys.encryptionOn) { + if (IsEncryptionOn(ssl, 0)) { *inOutIdx += ssl->keys.padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + *inOutIdx += MacSize(ssl); + #endif } ssl->expect_session_ticket = 0; return 0; } + +#endif /* !WOLFSSL_NO_TLS12 */ + #endif /* HAVE_SESSION_TICKET */ #endif /* NO_WOLFSSL_CLIENT */ +#ifdef HAVE_ECC + /* returns the WOLFSSL_* version of the curve from the OID sum */ + word16 GetCurveByOID(int oidSum) { + switch(oidSum) { + #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case ECC_SECP160R1_OID: + return WOLFSSL_ECC_SECP160R1; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + case ECC_SECP160R2_OID: + return WOLFSSL_ECC_SECP160R2; + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_KOBLITZ + case ECC_SECP160K1_OID: + return WOLFSSL_ECC_SECP160K1; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case ECC_SECP192R1_OID: + return WOLFSSL_ECC_SECP192R1; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case ECC_SECP192K1_OID: + return WOLFSSL_ECC_SECP192K1; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case ECC_SECP224R1_OID: + return WOLFSSL_ECC_SECP224R1; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case ECC_SECP224K1_OID: + return WOLFSSL_ECC_SECP224K1; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case ECC_SECP256R1_OID: + return WOLFSSL_ECC_SECP256R1; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case ECC_SECP256K1_OID: + return WOLFSSL_ECC_SECP256K1; + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + case ECC_BRAINPOOLP256R1_OID: + return WOLFSSL_ECC_BRAINPOOLP256R1; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case ECC_SECP384R1_OID: + return WOLFSSL_ECC_SECP384R1; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_BRAINPOOL + case ECC_BRAINPOOLP384R1_OID: + return WOLFSSL_ECC_BRAINPOOLP384R1; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_BRAINPOOL + case ECC_BRAINPOOLP512R1_OID: + return WOLFSSL_ECC_BRAINPOOLP512R1; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case ECC_SECP521R1_OID: + return WOLFSSL_ECC_SECP521R1; + #endif /* !NO_ECC_SECP */ + #endif + default: + WOLFSSL_MSG("Curve OID not compiled in or implemented"); + return 0; + } + } +#endif /* HAVE_ECC */ + #ifndef NO_WOLFSSL_SERVER +#ifndef WOLFSSL_NO_TLS12 + + /* handle generation of server_hello (2) */ int SendServerHello(WOLFSSL* ssl) { - byte *output; - word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - int sendSz; - int ret; - byte sessIdSz = ID_LEN; + int ret; + byte *output; + word16 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + byte sessIdSz = ID_LEN; + byte echoId = 0; /* ticket echo id flag */ + byte cacheOff = 0; /* session cache off flag */ + + WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND); + WOLFSSL_ENTER("SendServerHello"); length = VERSION_SZ + RAN_LEN + ID_LEN + ENUM_LEN @@ -11387,49 +24135,115 @@ int DoSessionTicket(WOLFSSL* ssl, + ENUM_LEN; #ifdef HAVE_TLS_EXTENSIONS - length += TLSX_GetResponseSize(ssl); - + ret = TLSX_GetResponseSize(ssl, server_hello, &length); + if (ret != 0) + return ret; #ifdef HAVE_SESSION_TICKET - if (ssl->options.useTicket && ssl->arrays->sessionIDSz == 0) { - /* no session id */ - length -= ID_LEN; - sessIdSz = 0; + if (ssl->options.useTicket) { + /* echo session id sz can be 0,32 or bogus len in between */ + sessIdSz = ssl->arrays->sessionIDSz; + if (sessIdSz > ID_LEN) { + WOLFSSL_MSG("Bad bogus session id len"); + return BUFFER_ERROR; + } + if (!IsAtLeastTLSv1_3(ssl->version)) + length -= (ID_LEN - sessIdSz); /* adjust ID_LEN assumption */ + echoId = 1; } #endif /* HAVE_SESSION_TICKET */ +#else + if (ssl->options.haveEMS) { + length += HELLO_EXT_SZ_SZ + HELLO_EXT_SZ; + } #endif - /* check for avalaible size */ - if ((ret = CheckAvailableSize(ssl, MAX_HELLO_SZ)) != 0) + /* is the session cache off at build or runtime */ +#ifdef NO_SESSION_CACHE + cacheOff = 1; +#else + if (ssl->options.sessionCacheOff == 1) { + cacheOff = 1; + } +#endif + + /* 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 + if (ssl->options.dtls) { + /* Server Hello should use the same sequence number as the + * Client Hello. */ + ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; + ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; + idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif /* WOLFSSL_DTLS */ + + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; - /* get ouput buffer */ + /* get output buffer */ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; AddHeaders(output, length, server_hello, ssl); - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - } - #endif /* now write to output */ - /* first version */ - output[idx++] = ssl->version.major; - output[idx++] = ssl->version.minor; + /* first version */ + output[idx++] = (byte)ssl->version.major; + output[idx++] = (byte)ssl->version.minor; - /* then random */ + /* then random and session id */ if (!ssl->options.resuming) { - ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom, - RAN_LEN); + /* generate random part and session id */ + ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, + RAN_LEN + sizeof(sessIdSz) + sessIdSz); if (ret != 0) return ret; - } - XMEMCPY(output + idx, ssl->arrays->serverRandom, RAN_LEN); - idx += RAN_LEN; +#ifdef WOLFSSL_TLS13 + if (TLSv1_3_Capable(ssl)) { + /* TLS v1.3 capable server downgraded. */ + XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ); + output[idx + RAN_LEN - 1] = (byte)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 */ + XMEMCPY(output + idx, ssl->arrays->serverRandom, RAN_LEN); + idx += RAN_LEN; + output[idx++] = sessIdSz; + XMEMCPY(output + idx, ssl->arrays->sessionID, sessIdSz); + } + idx += sessIdSz; #ifdef SHOW_SECRETS { @@ -11440,1427 +24254,1715 @@ int DoSessionTicket(WOLFSSL* ssl, printf("\n"); } #endif - /* then session id */ - output[idx++] = sessIdSz; - if (sessIdSz) { - if (!ssl->options.resuming) { - ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->sessionID, - sessIdSz); - if (ret != 0) return ret; - } - - XMEMCPY(output + idx, ssl->arrays->sessionID, sessIdSz); - idx += sessIdSz; - } - - /* then cipher suite */ + /* then cipher suite */ output[idx++] = ssl->options.cipherSuite0; output[idx++] = ssl->options.cipherSuite; - /* then compression */ + /* then compression */ if (ssl->options.usingCompression) output[idx++] = ZLIB_COMPRESSION; else output[idx++] = NO_COMPRESSION; - /* last, extensions */ + /* last, extensions */ #ifdef HAVE_TLS_EXTENSIONS - TLSX_WriteResponse(ssl, output + idx); + { + word16 offset = 0; + ret = TLSX_WriteResponse(ssl, output + idx, server_hello, &offset); + if (ret != 0) + return ret; + idx += offset; + } +#else +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS) { + c16toa(HELLO_EXT_SZ, output + idx); + idx += HELLO_EXT_SZ_SZ; + + c16toa(HELLO_EXT_EXTMS, output + idx); + idx += HELLO_EXT_TYPE_SZ; + c16toa(0, output + idx); + /*idx += HELLO_EXT_SZ_SZ;*/ + /* idx is not used after this point. uncomment the line above + * if adding any more extensions in the future. */ + } +#endif #endif - ssl->buffers.outputBuffer.length += sendSz; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) - return ret; - } - #endif + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */ - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) - return ret; + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ServerHello", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("ServerHello", &ssl->timeoutInfo, output, sendSz, - ssl->heap); - #endif + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + 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 + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + } + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "ServerHello"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "ServerHello", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + #endif ssl->options.serverState = SERVER_HELLO_COMPLETE; + ssl->buffers.outputBuffer.length += sendSz; + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif if (ssl->options.groupMessages) - return 0; + ret = 0; else - return SendBuffered(ssl); + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendServerHello", ret); + WOLFSSL_END(WC_FUNC_SERVER_HELLO_SEND); + + return ret; } -#ifdef HAVE_ECC +#if defined(HAVE_ECC) - static byte SetCurveId(int size) + static byte SetCurveId(ecc_key* key) { - switch(size) { -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) - case 20: - return WOLFSSL_ECC_SECP160R1; -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) - case 24: - return WOLFSSL_ECC_SECP192R1; -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) - case 28: - return WOLFSSL_ECC_SECP224R1; -#endif -#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) - case 32: - return WOLFSSL_ECC_SECP256R1; -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) - case 48: - return WOLFSSL_ECC_SECP384R1; -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) - case 66: - return WOLFSSL_ECC_SECP521R1; -#endif - default: - return 0; + if (key == NULL || key->dp == NULL) { + WOLFSSL_MSG("SetCurveId: Invalid key!"); + return 0; } + + return (byte)GetCurveByOID(key->dp->oidSum); } #endif /* HAVE_ECC */ + typedef struct SskeArgs { + byte* output; /* not allocated */ + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + (!defined(NO_DH) && !defined(NO_RSA)) + byte* sigDataBuf; + #endif + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) + byte* exportBuf; + #endif + #ifndef NO_RSA + byte* verifySig; + #endif + byte* input; + word32 idx; + word32 tmpSigSz; + word32 length; + word32 sigSz; + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + (!defined(NO_DH) && !defined(NO_RSA)) + word32 sigDataSz; + #endif + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) + word32 exportSz; + #endif + #ifdef HAVE_QSH + word32 qshSz; + #endif + int sendSz; + int inputSz; + } SskeArgs; - int SendServerKeyExchange(WOLFSSL* ssl) + static void FreeSskeArgs(WOLFSSL* ssl, void* pArgs) { - int ret = 0; + SskeArgs* args = (SskeArgs*)pArgs; + (void)ssl; - #define ERROR_OUT(err, eLabel) do { ret = err; goto eLabel; } while(0) - #ifndef NO_PSK - if (ssl->specs.kea == psk_kea) - { - byte *output; - word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - int sendSz; - if (ssl->arrays->server_hint[0] == 0) return 0; /* don't send */ - - /* include size part */ - length = (word32)XSTRLEN(ssl->arrays->server_hint); - if (length > MAX_PSK_ID_LEN) - return SERVER_HINT_ERROR; - - length += HINT_LEN_SZ; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - } - #endif - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) - return ret; - - /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; - - AddHeaders(output, length, server_key_exchange, ssl); - - /* key data */ - c16toa((word16)(length - HINT_LEN_SZ), output + idx); - idx += HINT_LEN_SZ; - XMEMCPY(output + idx, ssl->arrays->server_hint,length -HINT_LEN_SZ); - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) - return ret; - #endif - - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) - return ret; - - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, output, - sendSz, ssl->heap); - #endif - - ssl->buffers.outputBuffer.length += sendSz; - if (ssl->options.groupMessages) - ret = 0; - else - ret = SendBuffered(ssl); - ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) + if (args->exportBuf) { + XFREE(args->exportBuf, ssl->heap, DYNAMIC_TYPE_DER); + args->exportBuf = NULL; } - #endif /*NO_PSK */ - - #if !defined(NO_DH) && !defined(NO_PSK) - if (ssl->specs.kea == dhe_psk_kea) { - byte *output; - word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - word32 hintLen; - int sendSz; - DhKey dhKey; - - if (ssl->buffers.serverDH_P.buffer == NULL || - ssl->buffers.serverDH_G.buffer == NULL) - return NO_DH_PARAMS; - - if (ssl->buffers.serverDH_Pub.buffer == NULL) { - ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC( - ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap, - DYNAMIC_TYPE_DH); - if (ssl->buffers.serverDH_Pub.buffer == NULL) - return MEMORY_E; - } - - if (ssl->buffers.serverDH_Priv.buffer == NULL) { - ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC( - ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap, - DYNAMIC_TYPE_DH); - if (ssl->buffers.serverDH_Priv.buffer == NULL) - return MEMORY_E; - } - - wc_InitDhKey(&dhKey); - ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length); - if (ret == 0) - ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, - ssl->buffers.serverDH_Priv.buffer, - &ssl->buffers.serverDH_Priv.length, - ssl->buffers.serverDH_Pub.buffer, - &ssl->buffers.serverDH_Pub.length); - wc_FreeDhKey(&dhKey); - if (ret != 0) - return ret; - - length = LENGTH_SZ * 3 + /* p, g, pub */ - ssl->buffers.serverDH_P.length + - ssl->buffers.serverDH_G.length + - ssl->buffers.serverDH_Pub.length; - - /* include size part */ - hintLen = (word32)XSTRLEN(ssl->arrays->server_hint); - if (hintLen > MAX_PSK_ID_LEN) - return SERVER_HINT_ERROR; - length += hintLen + HINT_LEN_SZ; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - } - #endif - - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) - return ret; - - /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; - - AddHeaders(output, 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; - - /* 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; - - /* 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; - - /* 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); - idx += ssl->buffers.serverDH_Pub.length; - (void)idx; /* suppress analyzer warning, and keep idx current */ - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) - return ret; - #endif - - ret = HashOutput(ssl, output, sendSz, 0); - - if (ret != 0) - return ret; - - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, output, - sendSz, ssl->heap); - #endif - - ssl->buffers.outputBuffer.length += sendSz; - if (ssl->options.groupMessages) - ret = 0; - else - ret = SendBuffered(ssl); - ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + #endif + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + (!defined(NO_DH) && !defined(NO_RSA)) + if (args->sigDataBuf) { + XFREE(args->sigDataBuf, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->sigDataBuf = NULL; } - #endif /* !NO_DH && !NO_PSK */ - - #ifdef HAVE_ECC - if (ssl->specs.kea == ecc_diffie_hellman_kea) - { - byte *output; - word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - int sendSz; - word32 sigSz; - word32 preSigSz, preSigIdx; - #ifndef NO_RSA - RsaKey rsaKey; - #endif - ecc_key dsaKey; - #ifdef WOLFSSL_SMALL_STACK - byte* exportBuf = NULL; - #else - byte exportBuf[MAX_EXPORT_ECC_SZ]; - #endif - word32 expSz = MAX_EXPORT_ECC_SZ; - - #ifndef NO_OLD_TLS - byte doMd5 = 0; - byte doSha = 0; - #endif - #ifndef NO_SHA256 - byte doSha256 = 0; - #endif - #ifdef WOLFSSL_SHA384 - byte doSha384 = 0; - #endif - #ifdef WOLFSSL_SHA512 - byte doSha512 = 0; - #endif - - if (ssl->specs.static_ecdh) { - WOLFSSL_MSG("Using Static ECDH, not sending ServerKeyExchagne"); - return 0; - } - - /* curve type, named curve, length(1) */ - length = ENUM_LEN + CURVE_LEN + ENUM_LEN; - /* pub key size */ - WOLFSSL_MSG("Using ephemeral ECDH"); - - /* 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->ctx->heap, DYNAMIC_TYPE_ECC); - if (ssl->eccTempKey == NULL) { - WOLFSSL_MSG("EccTempKey Memory error"); - return MEMORY_E; - } - wc_ecc_init(ssl->eccTempKey); - } - if (ssl->eccTempKeyPresent == 0) { - if (wc_ecc_make_key(ssl->rng, ssl->eccTempKeySz, - ssl->eccTempKey) != 0) { - return ECC_MAKEKEY_ERROR; - } - ssl->eccTempKeyPresent = 1; - } - - #ifdef WOLFSSL_SMALL_STACK - exportBuf = (byte*)XMALLOC(MAX_EXPORT_ECC_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (exportBuf == NULL) - return MEMORY_E; - #endif - - if (wc_ecc_export_x963(ssl->eccTempKey, exportBuf, &expSz) != 0) - ERROR_OUT(ECC_EXPORT_ERROR, done_a); - length += expSz; - - preSigSz = length; - preSigIdx = idx; - - #ifndef NO_RSA - ret = wc_InitRsaKey(&rsaKey, ssl->heap); - if (ret != 0) - goto done_a; - #endif - - wc_ecc_init(&dsaKey); - - /* sig length */ - length += LENGTH_SZ; - - if (!ssl->buffers.key.buffer) { - #ifndef NO_RSA - wc_FreeRsaKey(&rsaKey); - #endif - wc_ecc_free(&dsaKey); - ERROR_OUT(NO_PRIVATE_KEY, done_a); - } - - #ifndef NO_RSA - if (ssl->specs.sig_algo == rsa_sa_algo) { - /* rsa sig size */ - word32 i = 0; - ret = wc_RsaPrivateKeyDecode(ssl->buffers.key.buffer, &i, - &rsaKey, ssl->buffers.key.length); - if (ret != 0) - goto done_a; - sigSz = wc_RsaEncryptSize(&rsaKey); - } else - #endif - - if (ssl->specs.sig_algo == ecc_dsa_sa_algo) { - /* ecdsa sig size */ - word32 i = 0; - ret = wc_EccPrivateKeyDecode(ssl->buffers.key.buffer, &i, - &dsaKey, ssl->buffers.key.length); - if (ret != 0) - goto done_a; - sigSz = wc_ecc_sig_size(&dsaKey); /* worst case estimate */ - } - else { - #ifndef NO_RSA - wc_FreeRsaKey(&rsaKey); - #endif - wc_ecc_free(&dsaKey); - ERROR_OUT(ALGO_ID_E, done_a); /* unsupported type */ - } - length += sigSz; - - if (IsAtLeastTLSv1_2(ssl)) - length += HASH_SIG_SIZE; - - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - preSigIdx = idx; - } - #endif - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { - #ifndef NO_RSA - wc_FreeRsaKey(&rsaKey); - #endif - wc_ecc_free(&dsaKey); - goto done_a; - } - - /* get ouput buffer */ - 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(wc_ecc_size(ssl->eccTempKey)); - output[idx++] = (byte)expSz; - XMEMCPY(output + idx, exportBuf, expSz); - idx += expSz; - if (IsAtLeastTLSv1_2(ssl)) { - byte setHash = 0; - - output[idx++] = ssl->suites->hashAlgo; - output[idx++] = ssl->suites->sigAlgo; - - switch (ssl->suites->hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - doSha512 = 1; - setHash = 1; - #endif - break; - - case sha384_mac: - #ifdef WOLFSSL_SHA384 - doSha384 = 1; - setHash = 1; - #endif - break; - - case sha256_mac: - #ifndef NO_SHA256 - doSha256 = 1; - setHash = 1; - #endif - break; - - case sha_mac: - #ifndef NO_OLD_TLS - doSha = 1; - setHash = 1; - #endif - break; - - default: - WOLFSSL_MSG("Bad hash sig algo"); - break; - } - - if (setHash == 0) { - #ifndef NO_RSA - wc_FreeRsaKey(&rsaKey); - #endif - wc_ecc_free(&dsaKey); - ERROR_OUT(ALGO_ID_E, done_a); - } - } else { - /* only using sha and md5 for rsa */ - #ifndef NO_OLD_TLS - doSha = 1; - if (ssl->suites->sigAlgo == rsa_sa_algo) { - doMd5 = 1; - } - #else - #ifndef NO_RSA - wc_FreeRsaKey(&rsaKey); - #endif - wc_ecc_free(&dsaKey); - ERROR_OUT(ALGO_ID_E, done_a); - #endif - } - - /* Signtaure length will be written later, when we're sure what it - is */ - - #ifdef HAVE_FUZZER - if (ssl->fuzzerCb) - ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, FUZZ_SIGNATURE, - ssl->fuzzerCtx); - #endif - - /* do signature */ - { - #ifndef NO_OLD_TLS - #ifdef WOLFSSL_SMALL_STACK - Md5* md5 = NULL; - Sha* sha = NULL; - #else - Md5 md5[1]; - Sha sha[1]; - #endif - #endif - #ifdef WOLFSSL_SMALL_STACK - byte* hash = NULL; - #else - byte hash[FINISHED_SZ]; - #endif - #ifndef NO_SHA256 - #ifdef WOLFSSL_SMALL_STACK - Sha256* sha256 = NULL; - byte* hash256 = NULL; - #else - Sha256 sha256[1]; - byte hash256[SHA256_DIGEST_SIZE]; - #endif - #endif - #ifdef WOLFSSL_SHA384 - #ifdef WOLFSSL_SMALL_STACK - Sha384* sha384 = NULL; - byte* hash384 = NULL; - #else - Sha384 sha384[1]; - byte hash384[SHA384_DIGEST_SIZE]; - #endif - #endif - #ifdef WOLFSSL_SHA512 - #ifdef WOLFSSL_SMALL_STACK - Sha512* sha512 = NULL; - byte* hash512 = NULL; - #else - Sha512 sha512[1]; - byte hash512[SHA512_DIGEST_SIZE]; - #endif - #endif - - #ifdef WOLFSSL_SMALL_STACK - hash = (byte*)XMALLOC(FINISHED_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (hash == NULL) - ERROR_OUT(MEMORY_E, done_a); - #endif - - #ifndef NO_OLD_TLS - /* md5 */ - #ifdef WOLFSSL_SMALL_STACK - if (doMd5) { - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (md5 == NULL) - ERROR_OUT(MEMORY_E, done_a2); - } - #endif - if (doMd5) { - wc_InitMd5(md5); - wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN); - wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN); - wc_Md5Update(md5, output + preSigIdx, preSigSz); - wc_Md5Final(md5, hash); - } - /* sha */ - #ifdef WOLFSSL_SMALL_STACK - if (doSha) { - sha = (Sha*)XMALLOC(sizeof(Sha), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha == NULL) - ERROR_OUT(MEMORY_E, done_a2); - } - #endif - if (doSha) { - ret = wc_InitSha(sha); - if (ret != 0) goto done_a2; - wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN); - wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN); - wc_ShaUpdate(sha, output + preSigIdx, preSigSz); - wc_ShaFinal(sha, &hash[MD5_DIGEST_SIZE]); - } - #endif - - #ifndef NO_SHA256 - #ifdef WOLFSSL_SMALL_STACK - if (doSha256) { - sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha256 == NULL || hash256 == NULL) - ERROR_OUT(MEMORY_E, done_a2); - } - #endif - - if (doSha256) { - if (!(ret = wc_InitSha256(sha256)) - && !(ret = wc_Sha256Update(sha256, - ssl->arrays->clientRandom, RAN_LEN)) - && !(ret = wc_Sha256Update(sha256, - ssl->arrays->serverRandom, RAN_LEN)) - && !(ret = wc_Sha256Update(sha256, - output + preSigIdx, preSigSz))) - ret = wc_Sha256Final(sha256, hash256); - - if (ret != 0) goto done_a2; - } - #endif - - #ifdef WOLFSSL_SHA384 - #ifdef WOLFSSL_SMALL_STACK - if (doSha384) { - sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha384 == NULL || hash384 == NULL) - ERROR_OUT(MEMORY_E, done_a2); - } - #endif - - if (doSha384) { - if (!(ret = wc_InitSha384(sha384)) - && !(ret = wc_Sha384Update(sha384, - ssl->arrays->clientRandom, RAN_LEN)) - && !(ret = wc_Sha384Update(sha384, - ssl->arrays->serverRandom, RAN_LEN)) - && !(ret = wc_Sha384Update(sha384, - output + preSigIdx, preSigSz))) - ret = wc_Sha384Final(sha384, hash384); - - if (ret != 0) goto done_a2; - } - #endif - - #ifdef WOLFSSL_SHA512 - #ifdef WOLFSSL_SMALL_STACK - if (doSha512) { - sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha512 == NULL || hash512 == NULL) - ERROR_OUT(MEMORY_E, done_a2); - } - #endif - - if (doSha512) { - if (!(ret = wc_InitSha512(sha512)) - && !(ret = wc_Sha512Update(sha512, - ssl->arrays->clientRandom, RAN_LEN)) - && !(ret = wc_Sha512Update(sha512, - ssl->arrays->serverRandom, RAN_LEN)) - && !(ret = wc_Sha512Update(sha512, - output + preSigIdx, preSigSz))) - ret = wc_Sha512Final(sha512, hash512); - - if (ret != 0) goto done_a2; - } - #endif - - #ifndef NO_RSA - if (ssl->suites->sigAlgo == rsa_sa_algo) { - byte* signBuffer = hash; - word32 signSz = FINISHED_SZ; - byte doUserRsa = 0; - #ifdef WOLFSSL_SMALL_STACK - byte* encodedSig = NULL; - #else - byte encodedSig[MAX_ENCODED_SIG_SZ]; - #endif - - #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->RsaSignCb) - doUserRsa = 1; - #endif - - #ifdef WOLFSSL_SMALL_STACK - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig == NULL) - ERROR_OUT(MEMORY_E, done_a2); - #endif - - if (IsAtLeastTLSv1_2(ssl)) { - byte* digest = &hash[MD5_DIGEST_SIZE]; - int typeH = SHAh; - int digestSz = SHA_DIGEST_SIZE; - - if (ssl->suites->hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = hash256; - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = hash384; - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = hash512; - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - #endif - } - - if (digest == NULL) { - #ifndef NO_RSA - wc_FreeRsaKey(&rsaKey); - #endif - wc_ecc_free(&dsaKey); - ERROR_OUT(ALGO_ID_E, done_a2); - } - signSz = wc_EncodeSignature(encodedSig, digest, - digestSz, typeH); - signBuffer = encodedSig; - } - /* write sig size here */ - c16toa((word16)sigSz, output + idx); - idx += LENGTH_SZ; - - if (doUserRsa) { - #ifdef HAVE_PK_CALLBACKS - word32 ioLen = sigSz; - ret = ssl->ctx->RsaSignCb(ssl, signBuffer, signSz, - output + idx, &ioLen, - ssl->buffers.key.buffer, - ssl->buffers.key.length, - ssl->RsaSignCtx); - #endif /*HAVE_PK_CALLBACKS */ - } - else - ret = wc_RsaSSL_Sign(signBuffer, signSz, output + idx, - sigSz, &rsaKey, ssl->rng); - - wc_FreeRsaKey(&rsaKey); - wc_ecc_free(&dsaKey); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - if (ret < 0) - goto done_a2; - } else - #endif - - if (ssl->suites->sigAlgo == ecc_dsa_sa_algo) { - #ifndef NO_OLD_TLS - byte* digest = &hash[MD5_DIGEST_SIZE]; - word32 digestSz = SHA_DIGEST_SIZE; - #else - byte* digest = hash256; - word32 digestSz = SHA256_DIGEST_SIZE; - #endif - word32 sz = sigSz; - byte doUserEcc = 0; - - #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC) - if (ssl->ctx->EccSignCb) - doUserEcc = 1; - #endif - - if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->suites->hashAlgo == sha_mac) { - #ifndef NO_SHA - digest = &hash[MD5_DIGEST_SIZE]; - digestSz = SHA_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = hash256; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = hash384; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = hash512; - digestSz = SHA512_DIGEST_SIZE; - #endif - } - } - - if (doUserEcc) { - #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC) - ret = ssl->ctx->EccSignCb(ssl, digest, digestSz, - output + LENGTH_SZ + idx, &sz, - ssl->buffers.key.buffer, - ssl->buffers.key.length, - ssl->EccSignCtx); - #endif - } - else { - ret = wc_ecc_sign_hash(digest, digestSz, - output + LENGTH_SZ + idx, &sz, ssl->rng, &dsaKey); - } - #ifndef NO_RSA - wc_FreeRsaKey(&rsaKey); - #endif - wc_ecc_free(&dsaKey); - - if (ret < 0) - goto done_a2; - - /* Now that we know the real sig size, write it. */ - c16toa((word16)sz, output + idx); - - /* And adjust length and sendSz from estimates */ - length += sz - sigSz; - sendSz += sz - sigSz; - } - - done_a2: - #ifdef WOLFSSL_SMALL_STACK - #ifndef NO_OLD_TLS - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #ifndef NO_SHA256 - XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - #ifdef WOLFSSL_SHA384 - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - #ifdef WOLFSSL_SHA512 - XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - #endif - - if (ret < 0) - goto done_a; - } - - AddHeaders(output, length, server_key_exchange, ssl); - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) - goto done_a; - #endif - - if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0) - goto done_a; - - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, - output, sendSz, ssl->heap); - #endif - - ssl->buffers.outputBuffer.length += sendSz; - if (ssl->options.groupMessages) - ret = 0; - else - ret = SendBuffered(ssl); - ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; - - done_a: - #ifdef WOLFSSL_SMALL_STACK - XFREE(exportBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - return ret; + #endif + #ifndef NO_RSA + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->verifySig = NULL; } - #endif /* HAVE_ECC */ - - #if !defined(NO_DH) && !defined(NO_RSA) - if (ssl->specs.kea == diffie_hellman_kea) { - byte *output; - word32 length = 0, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - int sendSz; - word32 sigSz = 0, i = 0; - word32 preSigSz = 0, preSigIdx = 0; - RsaKey rsaKey; - DhKey dhKey; - - if (ssl->buffers.serverDH_P.buffer == NULL || - ssl->buffers.serverDH_G.buffer == NULL) - return NO_DH_PARAMS; - - if (ssl->buffers.serverDH_Pub.buffer == NULL) { - ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC( - ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap, - DYNAMIC_TYPE_DH); - if (ssl->buffers.serverDH_Pub.buffer == NULL) - return MEMORY_E; - } - - if (ssl->buffers.serverDH_Priv.buffer == NULL) { - ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC( - ssl->buffers.serverDH_P.length + 2, ssl->ctx->heap, - DYNAMIC_TYPE_DH); - if (ssl->buffers.serverDH_Priv.buffer == NULL) - return MEMORY_E; - } - - wc_InitDhKey(&dhKey); - ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length); - if (ret == 0) - ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, - ssl->buffers.serverDH_Priv.buffer, - &ssl->buffers.serverDH_Priv.length, - ssl->buffers.serverDH_Pub.buffer, - &ssl->buffers.serverDH_Pub.length); - wc_FreeDhKey(&dhKey); - - if (ret != 0) return ret; - - length = LENGTH_SZ * 3; /* p, g, pub */ - length += ssl->buffers.serverDH_P.length + - ssl->buffers.serverDH_G.length + - ssl->buffers.serverDH_Pub.length; - - preSigIdx = idx; - preSigSz = length; - - if (!ssl->options.usingAnon_cipher) { - ret = wc_InitRsaKey(&rsaKey, ssl->heap); - if (ret != 0) return ret; - - /* sig length */ - length += LENGTH_SZ; - - if (!ssl->buffers.key.buffer) - return NO_PRIVATE_KEY; - - ret = wc_RsaPrivateKeyDecode(ssl->buffers.key.buffer, &i, &rsaKey, - ssl->buffers.key.length); - if (ret == 0) { - sigSz = wc_RsaEncryptSize(&rsaKey); - length += sigSz; - } - else { - wc_FreeRsaKey(&rsaKey); - return ret; - } - - if (IsAtLeastTLSv1_2(ssl)) - length += HASH_SIG_SIZE; - } - - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - preSigIdx = idx; - } - #endif - - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { - if (!ssl->options.usingAnon_cipher) - wc_FreeRsaKey(&rsaKey); - return ret; - } - - /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; - - AddHeaders(output, 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, - ssl->buffers.serverDH_P.length); - 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; - - /* 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); - idx += ssl->buffers.serverDH_Pub.length; - - #ifdef HAVE_FUZZER - if (ssl->fuzzerCb) - ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, FUZZ_SIGNATURE, - ssl->fuzzerCtx); - #endif - - /* Add signature */ - if (!ssl->options.usingAnon_cipher) { - #ifndef NO_OLD_TLS - #ifdef WOLFSSL_SMALL_STACK - Md5* md5 = NULL; - Sha* sha = NULL; - #else - Md5 md5[1]; - Sha sha[1]; - #endif - #endif - #ifdef WOLFSSL_SMALL_STACK - byte* hash = NULL; - #else - byte hash[FINISHED_SZ]; - #endif - #ifndef NO_SHA256 - #ifdef WOLFSSL_SMALL_STACK - Sha256* sha256 = NULL; - byte* hash256 = NULL; - #else - Sha256 sha256[1]; - byte hash256[SHA256_DIGEST_SIZE]; - #endif - #endif - #ifdef WOLFSSL_SHA384 - #ifdef WOLFSSL_SMALL_STACK - Sha384* sha384 = NULL; - byte* hash384 = NULL; - #else - Sha384 sha384[1]; - byte hash384[SHA384_DIGEST_SIZE]; - #endif - #endif - #ifdef WOLFSSL_SHA512 - #ifdef WOLFSSL_SMALL_STACK - Sha512* sha512 = NULL; - byte* hash512 = NULL; - #else - Sha512 sha512[1]; - byte hash512[SHA512_DIGEST_SIZE]; - #endif - #endif - - #ifndef NO_OLD_TLS - byte doMd5 = 0; - byte doSha = 0; - #endif - #ifndef NO_SHA256 - byte doSha256 = 0; - #endif - #ifdef WOLFSSL_SHA384 - byte doSha384 = 0; - #endif - #ifdef WOLFSSL_SHA512 - byte doSha512 = 0; - #endif - - /* Add hash/signature algo ID */ - if (IsAtLeastTLSv1_2(ssl)) { - byte setHash = 0; - - output[idx++] = ssl->suites->hashAlgo; - output[idx++] = ssl->suites->sigAlgo; - - switch (ssl->suites->hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - doSha512 = 1; - setHash = 1; - #endif - break; - - case sha384_mac: - #ifdef WOLFSSL_SHA384 - doSha384 = 1; - setHash = 1; - #endif - break; - - case sha256_mac: - #ifndef NO_SHA256 - doSha256 = 1; - setHash = 1; - #endif - break; - - case sha_mac: - #ifndef NO_OLD_TLS - doSha = 1; - setHash = 1; - #endif - break; - - default: - WOLFSSL_MSG("Bad hash sig algo"); - break; - } - - if (setHash == 0) { - wc_FreeRsaKey(&rsaKey); - return ALGO_ID_E; - } - } else { - /* only using sha and md5 for rsa */ - #ifndef NO_OLD_TLS - doSha = 1; - if (ssl->suites->sigAlgo == rsa_sa_algo) { - doMd5 = 1; - } - #else - wc_FreeRsaKey(&rsaKey); - return ALGO_ID_E; - #endif - } - - /* signature size */ - c16toa((word16)sigSz, output + idx); - idx += LENGTH_SZ; - - /* do signature */ - #ifdef WOLFSSL_SMALL_STACK - hash = (byte*)XMALLOC(FINISHED_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (hash == NULL) - return MEMORY_E; /* No heap commitment before this point, - from now on, the resources are freed - at done_b. */ - #endif - - #ifndef NO_OLD_TLS - /* md5 */ - #ifdef WOLFSSL_SMALL_STACK - if (doMd5) { - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (md5 == NULL) - ERROR_OUT(MEMORY_E, done_b); - } - #endif - if (doMd5) { - wc_InitMd5(md5); - wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN); - wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN); - wc_Md5Update(md5, output + preSigIdx, preSigSz); - wc_Md5Final(md5, hash); - } - - /* sha */ - #ifdef WOLFSSL_SMALL_STACK - if (doSha) { - sha = (Sha*)XMALLOC(sizeof(Sha), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha == NULL) - ERROR_OUT(MEMORY_E, done_b); - } - #endif - - if (doSha) { - if ((ret = wc_InitSha(sha)) != 0) - goto done_b; - wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN); - wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN); - wc_ShaUpdate(sha, output + preSigIdx, preSigSz); - wc_ShaFinal(sha, &hash[MD5_DIGEST_SIZE]); - } - #endif - - #ifndef NO_SHA256 - #ifdef WOLFSSL_SMALL_STACK - if (doSha256) { - sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha256 == NULL || hash256 == NULL) - ERROR_OUT(MEMORY_E, done_b); - } - #endif - - if (doSha256) { - if (!(ret = wc_InitSha256(sha256)) - && !(ret = wc_Sha256Update(sha256, - ssl->arrays->clientRandom, RAN_LEN)) - && !(ret = wc_Sha256Update(sha256, - ssl->arrays->serverRandom, RAN_LEN)) - && !(ret = wc_Sha256Update(sha256, - output + preSigIdx, preSigSz))) - ret = wc_Sha256Final(sha256, hash256); - - if (ret != 0) goto done_b; - } - #endif - - #ifdef WOLFSSL_SHA384 - #ifdef WOLFSSL_SMALL_STACK - if (doSha384) { - sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha384 == NULL || hash384 == NULL) - ERROR_OUT(MEMORY_E, done_b); - } - #endif - - if (doSha384) { - if (!(ret = wc_InitSha384(sha384)) - && !(ret = wc_Sha384Update(sha384, - ssl->arrays->clientRandom, RAN_LEN)) - && !(ret = wc_Sha384Update(sha384, - ssl->arrays->serverRandom, RAN_LEN)) - && !(ret = wc_Sha384Update(sha384, - output + preSigIdx, preSigSz))) - ret = wc_Sha384Final(sha384, hash384); - - if (ret != 0) goto done_b; - } - #endif - - #ifdef WOLFSSL_SHA512 - #ifdef WOLFSSL_SMALL_STACK - if (doSha512) { - sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha512 == NULL || hash512 == NULL) - ERROR_OUT(MEMORY_E, done_b); - } - #endif - - if (doSha512) { - if (!(ret = wc_InitSha512(sha512)) - && !(ret = wc_Sha512Update(sha512, - ssl->arrays->clientRandom, RAN_LEN)) - && !(ret = wc_Sha512Update(sha512, - ssl->arrays->serverRandom, RAN_LEN)) - && !(ret = wc_Sha512Update(sha512, - output + preSigIdx, preSigSz))) - ret = wc_Sha512Final(sha512, hash512); - - if (ret != 0) goto done_b; - } - #endif - - #ifndef NO_RSA - if (ssl->suites->sigAlgo == rsa_sa_algo) { - byte* signBuffer = hash; - word32 signSz = FINISHED_SZ; - #ifdef WOLFSSL_SMALL_STACK - byte* encodedSig = NULL; - #else - byte encodedSig[MAX_ENCODED_SIG_SZ]; - #endif - byte doUserRsa = 0; - - #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->RsaSignCb) - doUserRsa = 1; - #endif - - #ifdef WOLFSSL_SMALL_STACK - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig == NULL) - ERROR_OUT(MEMORY_E, done_b); - #endif - - if (IsAtLeastTLSv1_2(ssl)) { - byte* digest = &hash[MD5_DIGEST_SIZE]; - int typeH = SHAh; - int digestSz = SHA_DIGEST_SIZE; - - if (ssl->suites->hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = hash256; - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = hash384; - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = hash512; - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - #endif - } - - if (digest == NULL) { - ret = ALGO_ID_E; - } else { - signSz = wc_EncodeSignature(encodedSig, digest, - digestSz, typeH); - signBuffer = encodedSig; - } - } - if (doUserRsa && ret == 0) { - #ifdef HAVE_PK_CALLBACKS - word32 ioLen = sigSz; - ret = ssl->ctx->RsaSignCb(ssl, signBuffer, signSz, - output + idx, &ioLen, - ssl->buffers.key.buffer, - ssl->buffers.key.length, - ssl->RsaSignCtx); - #endif - } else if (ret == 0) { - ret = wc_RsaSSL_Sign(signBuffer, signSz, output + idx, - sigSz, &rsaKey, ssl->rng); - } - - wc_FreeRsaKey(&rsaKey); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - } - #endif - - done_b: - #ifdef WOLFSSL_SMALL_STACK - #ifndef NO_OLD_TLS - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #ifndef NO_SHA256 - XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - #ifdef WOLFSSL_SHA384 - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - #ifdef WOLFSSL_SHA512 - XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - #endif - - if (ret < 0) return ret; - } - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) - return ret; - #endif - - if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0) - return ret; - - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, - output, sendSz, ssl->heap); - #endif - - ssl->buffers.outputBuffer.length += sendSz; - if (ssl->options.groupMessages) - ret = 0; - else - ret = SendBuffered(ssl); - ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; - } - #endif /* NO_DH */ - - return ret; - #undef ERROR_OUT + #endif + (void)args; } + /* handle generation of server_key_exchange (12) */ + int SendServerKeyExchange(WOLFSSL* ssl) + { + int ret; + #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 + + WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_SEND); + WOLFSSL_ENTER("SendServerKeyExchange"); + + #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_sske; + } + else + #endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(SskeArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeSskeArgs; + #endif + } + + switch(ssl->options.asyncState) + { + 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) + { + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + WOLFSSL_MSG("Using ephemeral ECDH PSK"); + break; + } + #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */ + #if defined(HAVE_ECC) + case ecc_diffie_hellman_kea: + { + if (ssl->specs.static_ecdh) { + WOLFSSL_MSG("Using Static ECDH, not sending " + "ServerKeyExchange"); + ERROR_OUT(0, exit_sske); + } + + WOLFSSL_MSG("Using ephemeral ECDH"); + break; + } + #endif /* HAVE_ECC */ + } + + /* Preparing keys */ + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && (!defined(NO_PSK) || !defined(NO_RSA)) + #if !defined(NO_PSK) + case dhe_psk_kea: + #endif + #if !defined(NO_RSA) + case diffie_hellman_kea: + #endif + { + /* Allocate DH key buffers and generate key */ + if (ssl->buffers.serverDH_P.buffer == NULL || + ssl->buffers.serverDH_G.buffer == NULL) { + ERROR_OUT(NO_DH_PARAMS, exit_sske); + } + + 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 + OPAQUE16_LEN, + ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ssl->buffers.serverDH_Pub.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + } + + 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 + OPAQUE16_LEN, + ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (ssl->buffers.serverDH_Priv.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + } + + 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; + } + + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \ + !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + if (ssl->options.dhDoKeyTest && + !ssl->options.dhKeyTested) + { + ret = wc_DhSetCheckKey( + ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length, + NULL, 0, 0, ssl->rng); + if (ret != 0) { + goto exit_sske; + } + ssl->options.dhKeyTested = 1; + } + else + #endif + { + 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_sske; + } + } + + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_Priv.buffer, + (word32*)&ssl->buffers.serverDH_Priv.length, + ssl->buffers.serverDH_Pub.buffer, + (word32*)&ssl->buffers.serverDH_Pub.length); + break; + } + #endif /* !NO_DH && (!NO_PSK || !NO_RSA) */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + /* Fall through to create temp ECC key */ + #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + 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_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) { + /* need ephemeral key now, create it if missing */ + if (ssl->eccTempKey == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448, + (void**)&ssl->eccTempKey); + if (ret != 0) { + goto exit_sske; + } + } + + if (ssl->eccTempKeyPresent == 0) { + ret = X448MakeKey(ssl, + (curve448_key*)ssl->eccTempKey, NULL); + if (ret == 0 || ret == WC_PENDING_E) { + ssl->eccTempKeyPresent = + DYNAMIC_TYPE_CURVE448; + } + } + break; + } + #endif + #ifdef HAVE_ECC + /* need ephemeral key now, create it if missing */ + if (ssl->eccTempKey == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->eccTempKey); + if (ret != 0) { + goto exit_sske; + } + } + + if (ssl->eccTempKeyPresent == 0) { + ret = EccMakeKey(ssl, ssl->eccTempKey, NULL); + if (ret == 0 || ret == WC_PENDING_E) { + ssl->eccTempKeyPresent = DYNAMIC_TYPE_ECC; + } + } + #endif + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + default: + /* Skip ServerKeyExchange */ + goto exit_sske; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_sske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + #if (!defined(NO_DH) && !defined(NO_RSA)) || (defined(HAVE_ECC) || \ + defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)) + word32 preSigSz, preSigIdx; + #endif + + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + 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 */ + args->length = (word32)XSTRLEN(ssl->arrays->server_hint); + if (args->length > MAX_PSK_ID_LEN) { + ERROR_OUT(SERVER_HINT_ERROR, exit_sske); + } + + args->length += HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + args->length += args->qshSz; + args->sendSz += args->qshSz; + #endif + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif + + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_sske; + } + + /* get output buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(args->output, args->length, + server_key_exchange, ssl); + + /* key data */ + #ifdef HAVE_QSH + c16toa((word16)(args->length - args->qshSz - + HINT_LEN_SZ), args->output + args->idx); + #else + c16toa((word16)(args->length - HINT_LEN_SZ), + args->output + args->idx); + #endif + + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, + args->length - HINT_LEN_SZ); + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + word32 hintLen; + + 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; + + /* include size part */ + hintLen = (word32)XSTRLEN(ssl->arrays->server_hint); + if (hintLen > MAX_PSK_ID_LEN) { + ERROR_OUT(SERVER_HINT_ERROR, exit_sske); + } + args->length += hintLen + HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + args->length += args->qshSz; + args->sendSz += args->qshSz; + #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif + + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_sske; + } + + /* get output buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(args->output, args->length, + server_key_exchange, ssl); + + /* key data */ + 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, + 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, + 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, + 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 */ + /* args->idx += ssl->buffers.serverDH_Pub.length; */ + break; + } + #endif /* !defined(NO_DH) && !defined(NO_PSK) */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + word32 hintLen; + + /* curve type, named curve, length(1) */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN; + + 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); + } + #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); + } + } + else + #endif + #ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) { + if (wc_curve448_export_public_ex( + (curve448_key*)ssl->eccTempKey, + args->exportBuf, &args->exportSz, + EC448_LITTLE_ENDIAN) != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + } + } + 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); + } + args->length += hintLen + HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + args->length += args->qshSz; + args->sendSz += args->qshSz; + #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif + + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_sske; + } + + /* get output buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* key data */ + 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 */ + 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 + #ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) + args->output[args->idx++] = WOLFSSL_ECC_X448; + else + #endif + { + #ifdef HAVE_ECC + args->output[args->idx++] = + SetCurveId(ssl->eccTempKey); + #endif + } + args->output[args->idx++] = (byte)args->exportSz; + XMEMCPY(args->output + args->idx, args->exportBuf, + args->exportSz); + break; + } + #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + case ecc_diffie_hellman_kea: + { + enum wc_HashType hashType; + + /* curve type, named curve, length(1) */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN; + + /* Export temp ECC key and add to length */ + 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); + } + #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); + } + } + else + #endif + #ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) { + if (wc_curve448_export_public_ex( + (curve448_key*)ssl->eccTempKey, + args->exportBuf, &args->exportSz, + EC448_LITTLE_ENDIAN) != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + } + } + else + #endif + { + #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) + if (wc_ecc_export_x963(ssl->eccTempKey, + args->exportBuf, &args->exportSz) != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + } + #endif + } + args->length += args->exportSz; + + preSigSz = args->length; + preSigIdx = args->idx; + + if (ssl->buffers.key == NULL) { + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + args->tmpSigSz = GetPrivateKeySigSize(ssl); + if (args->tmpSigSz == 0) { + ERROR_OUT(NO_PRIVATE_KEY, exit_sske); + } + } + else + #endif + ERROR_OUT(NO_PRIVATE_KEY, exit_sske); + } + else { + switch(ssl->suites->sigAlgo) { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif + case rsa_sa_algo: + { + word16 keySz; + + ssl->buffers.keyType = rsa_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_sske; + } + + args->tmpSigSz = (word32)keySz; + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + { + word16 keySz; + + ssl->buffers.keyType = ecc_dsa_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_sske; + } + /* worst case estimate */ + args->tmpSigSz = keySz; + break; + } + #endif + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + word16 keySz; + + ssl->buffers.keyType = ed25519_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_sske; + } + + /* worst case estimate */ + args->tmpSigSz = ED25519_SIG_SIZE; + break; + } + #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED448 + case ed448_sa_algo: + { + word16 keySz; + + ssl->buffers.keyType = ed448_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_sske; + } + + /* worst case estimate */ + args->tmpSigSz = ED448_SIG_SIZE; + break; + } + #endif /* HAVE_ED448 */ + default: + ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */ + } /* switch(ssl->specs.sig_algo) */ + } + + /* sig length */ + args->length += LENGTH_SZ; + args->length += args->tmpSigSz; + + if (IsAtLeastTLSv1_2(ssl)) { + args->length += HASH_SIG_SIZE; + } + + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + args->length += args->qshSz; + args->sendSz += args->qshSz; + #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + preSigIdx = args->idx; + } + #endif + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_sske; + } + + /* get output buffer */ + 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 */ + 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 + #ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) + args->output[args->idx++] = WOLFSSL_ECC_X448; + else + #endif + { + #ifdef HAVE_ECC + args->output[args->idx++] = + SetCurveId(ssl->eccTempKey); + #endif + } + 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)) { + 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); + } + + } else { + /* only using sha and md5 for rsa */ + #ifndef NO_OLD_TLS + hashType = WC_HASH_TYPE_SHA; + if (ssl->suites->sigAlgo == rsa_sa_algo) { + hashType = WC_HASH_TYPE_MD5_SHA; + } + #else + ERROR_OUT(ALGO_ID_E, exit_sske); + #endif + } + + /* Signature length will be written later, when we're sure what it is */ + + #ifdef HAVE_FUZZER + if (ssl->fuzzerCb) { + ssl->fuzzerCb(ssl, args->output + preSigIdx, + preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx); + } + #endif + + /* Assemble buffer to hash for signature */ + 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(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); + + if (ssl->suites->sigAlgo != ed25519_sa_algo && + ssl->suites->sigAlgo != ed448_sa_algo) { + ssl->buffers.sig.length = + wc_HashGetDigestSize(hashType); + if ((int)ssl->buffers.sig.length < 0) { + ERROR_OUT(HASH_TYPE_E, exit_sske); + } + 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; + } + } + + args->sigSz = args->tmpSigSz; + + /* Sign hash to create signature */ + switch (ssl->suites->sigAlgo) + { + #ifndef NO_RSA + case rsa_sa_algo: + { + /* For TLS 1.2 re-encode signature */ + if (IsAtLeastTLSv1_2(ssl)) { + byte* encodedSig = (byte*)XMALLOC( + MAX_ENCODED_SIG_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + + 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_SIGNATURE); + ssl->buffers.sig.buffer = encodedSig; + } + + /* write sig size here */ + 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 */ + case ecc_dsa_sa_algo: + { + break; + } + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + ret = Ed25519CheckPubKey(ssl); + if (ret != 0) + goto exit_sske; + break; + #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED448 + case ed448_sa_algo: + ret = Ed448CheckPubKey(ssl); + if (ret != 0) + goto exit_sske; + break; + #endif /* HAVE_ED448 */ + } /* switch(ssl->specs.sig_algo) */ + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + #if !defined(NO_DH) && !defined(NO_RSA) + case diffie_hellman_kea: + { + enum wc_HashType hashType; + + 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 = args->idx; + preSigSz = args->length; + + if (!ssl->options.usingAnon_cipher) { + word16 keySz; + + /* sig length */ + args->length += LENGTH_SZ; + + if (ssl->buffers.key == NULL) { + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) + keySz = (word32)GetPrivateKeySigSize(ssl); + else + #endif + ERROR_OUT(NO_PRIVATE_KEY, exit_sske); + } + else + { + if (ssl->buffers.keyType == 0) + ssl->buffers.keyType = rsa_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_sske; + } + } + + if (keySz == 0) { /* test if keySz has error */ + ERROR_OUT(keySz, exit_sske); + } + + args->tmpSigSz = (word32)keySz; + args->length += args->tmpSigSz; + + if (IsAtLeastTLSv1_2(ssl)) { + args->length += HASH_SIG_SIZE; + } + } + + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + args->length += args->qshSz; + args->sendSz += args->qshSz; + #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + preSigIdx = args->idx; + } + #endif + + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_sske; + } + + /* get output buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(args->output, args->length, + server_key_exchange, ssl); + + /* add p, g, pub */ + 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, + 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, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_Pub.buffer, + ssl->buffers.serverDH_Pub.length); + args->idx += ssl->buffers.serverDH_Pub.length; + + #ifdef HAVE_FUZZER + if (ssl->fuzzerCb) { + ssl->fuzzerCb(ssl, args->output + preSigIdx, + preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx); + } + #endif + + if (ssl->options.usingAnon_cipher) { + break; + } + + /* Determine hash type */ + if (IsAtLeastTLSv1_2(ssl)) { + 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); + } + } else { + /* only using sha and md5 for rsa */ + #ifndef NO_OLD_TLS + hashType = WC_HASH_TYPE_SHA; + if (ssl->suites->sigAlgo == rsa_sa_algo) { + hashType = WC_HASH_TYPE_MD5_SHA; + } + #else + ERROR_OUT(ALGO_ID_E, exit_sske); + #endif + } + + /* signature size */ + c16toa((word16)args->tmpSigSz, args->output + args->idx); + args->idx += LENGTH_SZ; + + /* Assemble buffer to hash for signature */ + 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(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); + + if (ssl->suites->sigAlgo != ed25519_sa_algo && + ssl->suites->sigAlgo != ed448_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; + } + } + + args->sigSz = args->tmpSigSz; + + /* Sign hash to create signature */ + switch (ssl->suites->sigAlgo) + { + #ifndef NO_RSA + case rsa_sa_algo: + { + /* For TLS 1.2 re-encode signature */ + if (IsAtLeastTLSv1_2(ssl)) { + byte* encodedSig = (byte*)XMALLOC( + MAX_ENCODED_SIG_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + + 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_SIGNATURE); + ssl->buffers.sig.buffer = encodedSig; + } + break; + } + #endif /* NO_RSA */ + } /* switch (ssl->suites->sigAlgo) */ + break; + } + #endif /* !defined(NO_DH) && !defined(NO_RSA) */ + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_sske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + break; + } + #endif /* !defined(NO_DH) && !defined(NO_PSK) */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + break; + } + #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */ + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_ED448) + case ecc_diffie_hellman_kea: + { + /* Sign hash to create signature */ + 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, + args->output + args->idx, + &args->sigSz, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, + key, + ssl->buffers.key + ); + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + { + ecc_key* key = (ecc_key*)ssl->hsKey; + + ret = EccSign(ssl, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + args->output + LENGTH_SZ + args->idx, + &args->sigSz, + key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + break; + } + #endif /* HAVE_ECC */ + #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, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + break; + } + #endif + #ifdef HAVE_ED448 + case ed448_sa_algo: + { + ed448_key* key = (ed448_key*)ssl->hsKey; + + ret = Ed448Sign(ssl, + args->sigDataBuf, args->sigDataSz, + args->output + LENGTH_SZ + args->idx, + &args->sigSz, + key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + break; + } + #endif + } /* switch(ssl->specs.sig_algo) */ + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + #if !defined(NO_DH) && !defined(NO_RSA) + case diffie_hellman_kea: + { + /* Sign hash to create signature */ + 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; + } + + ret = RsaSign(ssl, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + args->output + args->idx, + &args->sigSz, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, + key, + ssl->buffers.key + ); + break; + } + #endif /* NO_RSA */ + } /* switch (ssl->suites->sigAlgo) */ + + break; + } + #endif /* !defined(NO_DH) && !defined(NO_RSA) */ + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_sske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + #endif /* !defined(NO_DH) && !defined(NO_PSK) */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + case ecc_diffie_hellman_kea: + { + 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 (args->verifySig == NULL) { + if (args->sigSz == 0) { + ERROR_OUT(BAD_COND_E, exit_sske); + } + args->verifySig = (byte*)XMALLOC( + args->sigSz, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (!args->verifySig) { + ERROR_OUT(MEMORY_E, exit_sske); + } + XMEMCPY(args->verifySig, + args->output + args->idx, args->sigSz); + } + + /* check for signature faults */ + ret = VerifyRsaSign(ssl, + args->verifySig, args->sigSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, + key, ssl->buffers.key + ); + break; + } + #endif + case ecc_dsa_sa_algo: + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + #endif + #ifdef HAVE_ED448 + case ed448_sa_algo: + #endif + { + /* 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; + } + default: + ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */ + } /* switch(ssl->specs.sig_algo) */ + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + #if !defined(NO_DH) && !defined(NO_RSA) + case diffie_hellman_kea: + { + 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 (args->verifySig == NULL) { + if (args->sigSz == 0) { + ERROR_OUT(BAD_COND_E, exit_sske); + } + args->verifySig = (byte*)XMALLOC( + args->sigSz, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (!args->verifySig) { + ERROR_OUT(MEMORY_E, exit_sske); + } + XMEMCPY(args->verifySig, + args->output + args->idx, args->sigSz); + } + + /* check for signature faults */ + ret = VerifyRsaSign(ssl, + args->verifySig, args->sigSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, + key, ssl->buffers.key + ); + break; + } + #endif + } /* switch (ssl->suites->sigAlgo) */ + break; + } + #endif /* !defined(NO_DH) && !defined(NO_RSA) */ + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_sske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + 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, + args->output + args->idx); + args->idx += OPAQUE16_LEN; + + /* write to output and check amount written */ + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, + args->output + args->idx) > + args->qshSz - OPAQUE16_LEN) { + ERROR_OUT(MEMORY_E, exit_sske); + } + } + } + #endif + + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + if (ssl->specs.kea == ecdhe_psk_kea || + ssl->specs.kea == ecc_diffie_hellman_kea) { + /* Check output to make sure it was set */ + if (args->output) { + AddHeaders(args->output, args->length, + server_key_exchange, ssl); + } + else { + ERROR_OUT(BUFFER_ERROR, exit_sske); + } + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + + if (IsEncryptionOn(ssl, 1)) { + args->inputSz = args->length + HANDSHAKE_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_sske); + } + + if (args->output == NULL) { + ERROR_OUT(BUFFER_ERROR, exit_sske); + } + + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + args->inputSz); + 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 (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, + args->output, args->sendSz)) != 0) { + goto exit_sske; + } + } + + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + + ret = HashOutput(ssl, args->output, args->sendSz, 0); + if (ret != 0) { + goto exit_sske; + } + } + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) { + AddPacketName(ssl, "ServerKeyExchange"); + } + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "ServerKeyExchange", handshake, + args->output, args->sendSz, WRITE_PROTO, ssl->heap); + } + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + ssl->buffers.outputBuffer.length += args->sendSz; + if (!ssl->options.groupMessages) { + ret = SendBuffered(ssl); + } + + ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + + exit_sske: + + WOLFSSL_LEAVE("SendServerKeyExchange", ret); + WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_SEND); + + #ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) + return ret; + #endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Final cleanup */ + FreeSskeArgs(ssl, args); + FreeKeyExchange(ssl); + + return ret; + } + +#if defined(HAVE_SERVER_RENEGOTIATION_INFO) || defined(HAVE_FALLBACK_SCSV) || \ + defined(OPENSSL_ALL) + + /* search suites for specific one, idx on success, negative on error */ +#ifndef WOLFSSL_TLS13 + static +#endif + int FindSuite(Suites* suites, byte first, byte second) + { + int i; + + if (suites == NULL || suites->suiteSz == 0) { + WOLFSSL_MSG("Suites pointer error or suiteSz 0"); + return SUITES_ERROR; + } + + for (i = 0; i < suites->suiteSz-1; i += SUITE_LEN) { + if (suites->suites[i] == first && + suites->suites[i+1] == second ) + return i; + } + + return MATCH_SUITE_ERROR; + } + +#endif + +#endif /* !WOLFSSL_NO_TLS12 */ /* Make sure server cert/key are valid for this suite, true on success */ static int VerifyServerSuite(WOLFSSL* ssl, word16 idx) @@ -12903,10 +26005,10 @@ int DoSessionTicket(WOLFSSL* ssl, } } - if (CipherRequires(first, second, REQUIRES_ECC_DSA)) { - WOLFSSL_MSG("Requires ECCDSA"); - if (ssl->options.haveECDSAsig == 0) { - WOLFSSL_MSG("Don't have ECCDSA"); + if (CipherRequires(first, second, REQUIRES_ECC)) { + WOLFSSL_MSG("Requires ECC"); + if (ssl->options.haveECC == 0) { + WOLFSSL_MSG("Don't have ECC"); return 0; } } @@ -12944,56 +26046,128 @@ int DoSessionTicket(WOLFSSL* ssl, } } -#ifdef HAVE_SUPPORTED_CURVES - if (!TLSX_ValidateEllipticCurves(ssl, first, second)) { - WOLFSSL_MSG("Don't have matching curves"); +#if !defined(WOLFSSL_OLDTLS_AEAD_CIPHERSUITES) + if (CipherRequires(first, second, REQUIRES_AEAD)) { + WOLFSSL_MSG("Requires AEAD"); + if (ssl->version.major == SSLv3_MAJOR && + ssl->version.minor < TLSv1_2_MINOR) { + WOLFSSL_MSG("Version of SSL does not support AEAD ciphers"); return 0; + } + + } +#endif + +#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES) + if (!TLSX_ValidateSupportedCurves(ssl, first, second)) { + WOLFSSL_MSG("Don't have matching curves"); + return 0; } #endif /* ECCDHE is always supported if ECC on */ +#ifdef HAVE_QSH + /* need to negotiate a classic suite in addition to TLS_QSH */ + if (first == QSH_BYTE && second == TLS_QSH) { + if (TLSX_SupportExtensions(ssl)) { + ssl->options.haveQSH = 1; /* matched TLS_QSH */ + } + else { + WOLFSSL_MSG("Version of SSL connection does not support " + "TLS_QSH"); + } + return 0; + } +#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_COMPLETE; + else if (ret != 0) + return 0; + } + else if (first == TLS13_BYTE || (first == ECC_BYTE && + (second == TLS_SHA256_SHA256 || second == TLS_SHA384_SHA384))) { + /* Can't negotiate TLS 1.3 cipher suites with lower protocol + * version. */ + return 0; + } +#endif + return 1; } - - static int MatchSuite(WOLFSSL* ssl, Suites* peerSuites) +#ifndef NO_WOLFSSL_SERVER + 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) { + result = 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"); /* & 0x1 equivalent % 2 */ if (peerSuites->suiteSz == 0 || peerSuites->suiteSz & 0x1) - return MATCH_SUITE_ERROR; + return BUFFER_ERROR; 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; } - +#endif #ifdef OLD_HELLO_ALLOWED @@ -13007,12 +26181,13 @@ int DoSessionTicket(WOLFSSL* ssl, word16 i, j; ProtocolVersion pv; Suites clSuites; + int ret = -1; (void)inSz; WOLFSSL_MSG("Got old format client hello"); #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) - AddPacketName("ClientHello", &ssl->handShakeInfo); + AddPacketName(ssl, "ClientHello"); if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo); #endif @@ -13046,62 +26221,71 @@ int DoSessionTicket(WOLFSSL* ssl, if (ssl->version.minor > pv.minor) { byte haveRSA = 0; byte havePSK = 0; + int keySz = 0; + if (!ssl->options.downgrade) { WOLFSSL_MSG("Client trying to connect with lesser version"); return VERSION_ERROR; } if (pv.minor < ssl->options.minDowngrade) { - WOLFSSL_MSG(" version below minimum allowed, fatal error"); + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); return VERSION_ERROR; } if (pv.minor == SSLv3_MINOR) { /* turn off tls */ - WOLFSSL_MSG(" downgrading to SSLv3"); + WOLFSSL_MSG("\tdowngrading to SSLv3"); ssl->options.tls = 0; ssl->options.tls1_1 = 0; ssl->version.minor = SSLv3_MINOR; } else if (pv.minor == TLSv1_MINOR) { - WOLFSSL_MSG(" downgrading to TLSv1"); + WOLFSSL_MSG("\tdowngrading to TLSv1"); /* turn off tls 1.1+ */ ssl->options.tls1_1 = 0; ssl->version.minor = TLSv1_MINOR; } else if (pv.minor == TLSv1_1_MINOR) { - WOLFSSL_MSG(" downgrading to TLSv1.1"); + 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 +#ifndef NO_CERTS + keySz = ssl->buffers.keySz; +#endif - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveNTRU, - ssl->options.haveECDSAsig, ssl->options.haveStaticECC, - ssl->options.side); + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); } /* suite size */ ato16(&input[idx], &clSuites.suiteSz); - idx += 2; + idx += OPAQUE16_LEN; - if (clSuites.suiteSz > MAX_SUITE_SZ) + if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) return BUFFER_ERROR; clSuites.hashSigAlgoSz = 0; /* 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; @@ -13110,10 +26294,10 @@ int DoSessionTicket(WOLFSSL* ssl, 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; @@ -13136,14 +26320,14 @@ int DoSessionTicket(WOLFSSL* ssl, ssl->options.usingCompression = 0; /* turn off */ ssl->options.clientState = CLIENT_HELLO_COMPLETE; + ssl->cbmode = SSL_CB_MODE_WRITE; *inOutIdx = idx; ssl->options.haveSessionId = 1; /* DoClientHello uses same resume code */ if (ssl->options.resuming) { /* let's try */ - int ret = -1; WOLFSSL_SESSION* session = GetSession(ssl, - ssl->arrays->masterSecret); + ssl->arrays->masterSecret, 1); #ifdef HAVE_SESSION_TICKET if (ssl->options.useTicket == 1) { session = &ssl->session; @@ -13154,13 +26338,13 @@ int DoSessionTicket(WOLFSSL* ssl, 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; } - #ifdef SESSION_CERTS - ssl->session = *session; /* restore session certs. */ - #endif ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom, RAN_LEN); @@ -13183,79 +26367,299 @@ int DoSessionTicket(WOLFSSL* ssl, } } - return MatchSuite(ssl, &clSuites); + ret = MatchSuite(ssl, &clSuites); + if (ret != 0)return ret; + return SanityCheckMsgReceived(ssl, client_hello); } #endif /* OLD_HELLO_ALLOWED */ +#ifndef WOLFSSL_NO_TLS12 - static int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + int HandleTlsResumption(WOLFSSL* ssl, int bogusID, Suites* clSuites) + { + int ret = 0; + WOLFSSL_SESSION* session; + + (void)bogusID; + + session = GetSession(ssl, ssl->arrays->masterSecret, 1); + #ifdef HAVE_SESSION_TICKET + if (ssl->options.useTicket == 1) { + session = &ssl->session; + } else if (bogusID == 1 && ssl->options.rejectTicket == 0) { + WOLFSSL_MSG("Bogus session ID without session ticket"); + return BUFFER_ERROR; + } + #endif + + if (!session) { + WOLFSSL_MSG("Session lookup for resume failed"); + ssl->options.resuming = 0; + } + else if (session->haveEMS != ssl->options.haveEMS) { + /* RFC 7627, 5.3, server-side */ + /* if old sess didn't have EMS, but new does, full handshake */ + if (!session->haveEMS && ssl->options.haveEMS) { + WOLFSSL_MSG("Attempting to resume a session that didn't " + "use EMS with a new session with EMS. Do full " + "handshake."); + ssl->options.resuming = 0; + } + /* if old sess used EMS, but new doesn't, MUST abort */ + else if (session->haveEMS && !ssl->options.haveEMS) { + WOLFSSL_MSG("Trying to resume a session with EMS without " + "using EMS"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, handshake_failure); + #endif + return EXT_MASTER_SECRET_NEEDED_E; + } + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif + } + else { + #ifndef NO_RESUME_SUITE_CHECK + int j; + + /* Check client suites include the one in session */ + for (j = 0; j < clSuites->suiteSz; j += 2) { + if (clSuites->suites[j] == session->cipherSuite0 && + clSuites->suites[j+1] == session->cipherSuite) { + break; + } + } + if (j == clSuites->suiteSz) { + WOLFSSL_MSG("Prev session's cipher suite not in ClientHello"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, illegal_parameter); + #endif + return UNSUPPORTED_SUITE; + } + #endif + + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif + if (MatchSuite(ssl, clSuites) < 0) { + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + return UNSUPPORTED_SUITE; + } + + ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom, + RAN_LEN); + if (ret != 0) + return ret; + + #ifdef NO_OLD_TLS + ret = DeriveTlsKeys(ssl); + #else + #ifndef NO_TLS + if (ssl->options.tls) + ret = DeriveTlsKeys(ssl); + #endif + if (!ssl->options.tls) + ret = DeriveKeys(ssl); + #endif + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + } + + return ret; + } + + + /* handle processing of client_hello (1) */ + int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz) { byte b; + byte bogusID = 0; /* flag for a bogus session id */ ProtocolVersion pv; Suites clSuites; word32 i = *inOutIdx; word32 begin = i; + int ret = 0; +#ifdef WOLFSSL_DTLS + Hmac cookieHmac; + byte peerCookie[MAX_COOKIE_LEN]; + byte peerCookieSz = 0; + byte cookieType; + byte cookieSz = 0; + + XMEMSET(&cookieHmac, 0, sizeof(Hmac)); +#endif /* WOLFSSL_DTLS */ + + WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO); + WOLFSSL_ENTER("DoClientHello"); #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo); + if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello"); 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) + if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) return BUFFER_ERROR; /* protocol version */ XMEMCPY(&pv, input + i, OPAQUE16_LEN); ssl->chVersion = pv; /* store */ +#ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + #if defined(NO_SHA) && defined(NO_SHA256) + #error "DTLS needs either SHA or SHA-256" + #endif /* NO_SHA && NO_SHA256 */ + + #if !defined(NO_SHA) && defined(NO_SHA256) + cookieType = WC_SHA; + cookieSz = WC_SHA_DIGEST_SIZE; + #endif /* NO_SHA */ + #ifndef NO_SHA256 + cookieType = WC_SHA256; + cookieSz = WC_SHA256_DIGEST_SIZE; + #endif /* NO_SHA256 */ + ret = wc_HmacSetKey(&cookieHmac, cookieType, + ssl->buffers.dtlsCookieSecret.buffer, + ssl->buffers.dtlsCookieSecret.length); + if (ret != 0) return ret; + ret = wc_HmacUpdate(&cookieHmac, + (const byte*)ssl->buffers.dtlsCtx.peer.sa, + ssl->buffers.dtlsCtx.peer.sz); + if (ret != 0) return ret; + ret = wc_HmacUpdate(&cookieHmac, input + i, OPAQUE16_LEN); + if (ret != 0) return ret; + } +#endif /* WOLFSSL_DTLS */ i += OPAQUE16_LEN; - if (ssl->version.minor > pv.minor) { - byte haveRSA = 0; - byte havePSK = 0; + /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */ + if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR) + pv.minor = TLSv1_2_MINOR; + + if ((!ssl->options.dtls && ssl->version.minor > pv.minor) || + (ssl->options.dtls && ssl->version.minor != DTLS_MINOR + && ssl->version.minor != DTLSv1_2_MINOR && pv.minor != DTLS_MINOR + && pv.minor != DTLSv1_2_MINOR)) { + + word16 haveRSA = 0; + word16 havePSK = 0; + int keySz = 0; if (!ssl->options.downgrade) { WOLFSSL_MSG("Client trying to connect with lesser version"); return VERSION_ERROR; } if (pv.minor < ssl->options.minDowngrade) { - WOLFSSL_MSG(" version below minimum allowed, fatal error"); + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); return VERSION_ERROR; } if (pv.minor == SSLv3_MINOR) { /* turn off tls */ - WOLFSSL_MSG(" downgrading to SSLv3"); + WOLFSSL_MSG("\tdowngrading to SSLv3"); ssl->options.tls = 0; ssl->options.tls1_1 = 0; ssl->version.minor = SSLv3_MINOR; } else if (pv.minor == TLSv1_MINOR) { /* turn off tls 1.1+ */ - WOLFSSL_MSG(" downgrading to TLSv1"); + WOLFSSL_MSG("\tdowngrading to TLSv1"); ssl->options.tls1_1 = 0; ssl->version.minor = TLSv1_MINOR; } else if (pv.minor == TLSv1_1_MINOR) { - WOLFSSL_MSG(" downgrading to TLSv1.1"); + 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.haveStaticECC, - ssl->options.side); + 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 + if (IsDtlsNotSctpMode(ssl)) { + ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN); + if (ret != 0) return ret; + } +#endif /* WOLFSSL_DTLS */ i += RAN_LEN; #ifdef SHOW_SECRETS @@ -13271,13 +26675,26 @@ int DoSessionTicket(WOLFSSL* ssl, /* session id */ b = input[i++]; - if (b == ID_LEN) { - if ((i - begin) + ID_LEN > helloSz) +#ifdef HAVE_SESSION_TICKET + if (b > 0 && b < ID_LEN) { + bogusID = 1; + WOLFSSL_MSG("Client sent bogus session id, let's allow for echo"); + } +#endif + + if (b == ID_LEN || bogusID) { + if ((i - begin) + b > helloSz) return BUFFER_ERROR; - XMEMCPY(ssl->arrays->sessionID, input + i, ID_LEN); - ssl->arrays->sessionIDSz = ID_LEN; - i += ID_LEN; + XMEMCPY(ssl->arrays->sessionID, input + i, b); +#ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1); + if (ret != 0) return ret; + } +#endif /* WOLFSSL_DTLS */ + ssl->arrays->sessionIDSz = b; + i += b; ssl->options.resuming = 1; /* client wants to resume */ WOLFSSL_MSG("Client wants to resume session"); } @@ -13293,30 +26710,18 @@ int DoSessionTicket(WOLFSSL* ssl, if ((i - begin) + OPAQUE8_LEN > helloSz) return BUFFER_ERROR; - b = input[i++]; + peerCookieSz = input[i++]; - if (b) { - byte cookie[MAX_COOKIE_LEN]; - - if (b > MAX_COOKIE_LEN) + if (peerCookieSz) { + if (peerCookieSz > MAX_COOKIE_LEN) return BUFFER_ERROR; - if ((i - begin) + b > helloSz) + if ((i - begin) + peerCookieSz > helloSz) return BUFFER_ERROR; - if (ssl->ctx->CBIOCookie == NULL) { - WOLFSSL_MSG("Your Cookie callback is null, please set"); - return COOKIE_ERROR; - } + XMEMCPY(peerCookie, input + i, peerCookieSz); - if ((ssl->ctx->CBIOCookie(ssl, cookie, COOKIE_SZ, - ssl->IOCB_CookieCtx) != COOKIE_SZ) - || (b != COOKIE_SZ) - || (XMEMCMP(cookie, input + i, b) != 0)) { - return COOKIE_ERROR; - } - - i += b; + i += peerCookieSz; } } #endif @@ -13332,10 +26737,49 @@ int DoSessionTicket(WOLFSSL* ssl, if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz) return BUFFER_ERROR; - if (clSuites.suiteSz > MAX_SUITE_SZ) + if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) return BUFFER_ERROR; XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz); + +#ifdef HAVE_SERVER_RENEGOTIATION_INFO + /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */ + if (FindSuite(&clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >= 0) { + TLSX* extension; + + /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */ + ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO); + if (extension) { + ssl->secure_renegotiation = + (SecureRenegotiation*)extension->data; + ssl->secure_renegotiation->enabled = 1; + } + } +#endif /* HAVE_SERVER_RENEGOTIATION_INFO */ +#if defined(HAVE_FALLBACK_SCSV) || defined(OPENSSL_ALL) + /* check for TLS_FALLBACK_SCSV suite */ + if (FindSuite(&clSuites, TLS_FALLBACK_SCSV, 0) >= 0) { + WOLFSSL_MSG("Found Fallback SCSV"); + if (ssl->ctx->method->version.minor > pv.minor) { + WOLFSSL_MSG("Client trying to connect with lesser version"); + SendAlert(ssl, alert_fatal, inappropriate_fallback); + return VERSION_ERROR; + } + } +#endif + +#ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + ret = wc_HmacUpdate(&cookieHmac, + input + i - OPAQUE16_LEN, + clSuites.suiteSz + OPAQUE16_LEN); + if (ret != 0) return ret; + } +#endif /* WOLFSSL_DTLS */ i += clSuites.suiteSz; clSuites.hashSigAlgoSz = 0; @@ -13345,37 +26789,106 @@ int DoSessionTicket(WOLFSSL* ssl, if ((i - begin) + b > helloSz) return BUFFER_ERROR; - if (ssl->options.usingCompression) { - int match = 0; + if (b == 0) { + WOLFSSL_MSG("No compression types in list"); +#ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, decode_error); +#endif + return COMPRESSION_ERROR; + } + +#ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + byte newCookie[MAX_COOKIE_LEN]; + + ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1); + if (ret != 0) return ret; + ret = wc_HmacFinal(&cookieHmac, newCookie); + if (ret != 0) return ret; + + /* If a cookie callback is set, call it to overwrite the cookie. + * This should be deprecated. The code now calculates the cookie + * using an HMAC as expected. */ + if (ssl->ctx->CBIOCookie != NULL && + ssl->ctx->CBIOCookie(ssl, newCookie, cookieSz, + ssl->IOCB_CookieCtx) != cookieSz) { + return COOKIE_ERROR; + } + + /* Check the cookie, see if we progress the state machine. */ + if (peerCookieSz != cookieSz || + XMEMCMP(peerCookie, newCookie, cookieSz) != 0) { + + /* Send newCookie to client in a HelloVerifyRequest message + * and let the state machine alone. */ + ssl->msgsReceived.got_client_hello = 0; + ssl->keys.dtls_handshake_number = 0; + ssl->keys.dtls_expected_peer_handshake_number = 0; + *inOutIdx += helloSz; + return SendHelloVerifyRequest(ssl, newCookie, cookieSz); + } + + /* This was skipped in the DTLS case so we could handle the hello + * verify request. */ + ret = HashInput(ssl, input + *inOutIdx, helloSz); + if (ret != 0) return ret; + } +#endif /* WOLFSSL_DTLS */ + + { + /* compression match types */ + int matchNo = 0; + int matchZlib = 0; while (b--) { byte comp = input[i++]; - if (comp == ZLIB_COMPRESSION) - match = 1; + if (comp == NO_COMPRESSION) { + matchNo = 1; + } + if (comp == ZLIB_COMPRESSION) { + matchZlib = 1; + } } - if (!match) { - WOLFSSL_MSG("Not matching compression, turning off"); + if (ssl->options.usingCompression == 0 && matchNo) { + WOLFSSL_MSG("Matched No Compression"); + } else if (ssl->options.usingCompression && matchZlib) { + WOLFSSL_MSG("Matched zlib Compression"); + } else if (ssl->options.usingCompression && matchNo) { + WOLFSSL_MSG("Could only match no compression, turning off"); ssl->options.usingCompression = 0; /* turn off */ + } else { + WOLFSSL_MSG("Could not match compression"); +#ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, illegal_parameter); +#endif + return COMPRESSION_ERROR; } } - else - i += b; /* ignore, since we're not on */ *inOutIdx = i; /* tls extensions */ if ((i - begin) < helloSz) { #ifdef HAVE_TLS_EXTENSIONS - if (TLSX_SupportExtensions(ssl)) { - int ret = 0; + #ifdef HAVE_QSH + QSH_Init(ssl); + #endif + if (TLSX_SupportExtensions(ssl)) #else - if (IsAtLeastTLSv1_2(ssl)) { + if (IsAtLeastTLSv1_2(ssl)) #endif + { /* Process the hello extension. Skip unsupported. */ word16 totalExtSz; +#ifdef HAVE_TLS_EXTENSIONS + /* auto populate extensions supported unless user defined */ + if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0) + return ret; +#endif + if ((i - begin) + OPAQUE16_LEN > helloSz) return BUFFER_ERROR; @@ -13386,9 +26899,23 @@ int DoSessionTicket(WOLFSSL* ssl, return BUFFER_ERROR; #ifdef HAVE_TLS_EXTENSIONS - if ((ret = TLSX_Parse(ssl, (byte *) input + i, - totalExtSz, 1, &clSuites))) + /* tls extensions */ + if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, + client_hello, &clSuites))) return ret; + #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(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + if((ret=SNI_Callback(ssl))) + return ret; + ssl->options.side = WOLFSSL_SERVER_END; + #endif i += totalExtSz; #else @@ -13407,19 +26934,30 @@ int DoSessionTicket(WOLFSSL* ssl, 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) + ssl->options.haveEMS = 1; +#endif else i += extSz; @@ -13436,291 +26974,547 @@ int DoSessionTicket(WOLFSSL* ssl, ssl->options.haveSessionId = 1; /* ProcessOld uses same resume code */ - if (ssl->options.resuming && (!ssl->options.dtls || - ssl->options.acceptState == HELLO_VERIFY_SENT)) { /* let's try */ - int ret = -1; - WOLFSSL_SESSION* session = GetSession(ssl, - ssl->arrays->masterSecret); - #ifdef HAVE_SESSION_TICKET - if (ssl->options.useTicket == 1) { - session = &ssl->session; - } + if (ssl->options.resuming) { + ret = HandleTlsResumption(ssl, bogusID, &clSuites); + if (ret != 0) + return ret; + + #ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && + ssl->secure_renegotiation->enabled && + IsEncryptionOn(ssl, 0)) + ssl->secure_renegotiation->startScr = 1; #endif - if (!session) { - WOLFSSL_MSG("Session lookup for resume failed"); - ssl->options.resuming = 0; - } - else { - if (MatchSuite(ssl, &clSuites) < 0) { - WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); - return UNSUPPORTED_SUITE; - } - #ifdef SESSION_CERTS - ssl->session = *session; /* restore session certs. */ - #endif - - ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom, - RAN_LEN); - if (ret != 0) - return ret; - - #ifdef NO_OLD_TLS - ret = DeriveTlsKeys(ssl); - #else - #ifndef NO_TLS - if (ssl->options.tls) - ret = DeriveTlsKeys(ssl); - #endif - if (!ssl->options.tls) - ret = DeriveKeys(ssl); - #endif - ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + if (ssl->options.clientState == CLIENT_KEYEXCHANGE_COMPLETE) { + WOLFSSL_LEAVE("DoClientHello", ret); + WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); return ret; } } - return MatchSuite(ssl, &clSuites); - } -#if !defined(NO_RSA) || defined(HAVE_ECC) - static int DoCertificateVerify(WOLFSSL* ssl, byte* input, word32* inOutIdx, - word32 size) - { - word16 sz = 0; - int ret = VERIFY_CERT_ERROR; /* start in error state */ - byte hashAlgo = sha_mac; - byte sigAlgo = anonymous_sa_algo; - word32 begin = *inOutIdx; - - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("CertificateVerify", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddLateName("CertificateVerify", &ssl->timeoutInfo); - #endif - - - if (IsAtLeastTLSv1_2(ssl)) { - if ((*inOutIdx - begin) + ENUM_LEN + ENUM_LEN > size) - return BUFFER_ERROR; - - hashAlgo = input[(*inOutIdx)++]; - sigAlgo = input[(*inOutIdx)++]; +#if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_DH_DEFAULT_PARAMS) + #if defined(HAVE_FFDHE) && defined(HAVE_SUPPORTED_CURVES) + if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS) != NULL) { + /* Set FFDHE parameters or clear DHE parameters if FFDH parameters + * present and no matches in the server's list. */ + ret = TLSX_SupportedFFDHE_Set(ssl); + if (ret != 0) + return ret; } - - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &sz); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + sz > size || sz > ENCRYPT_LEN) - return BUFFER_ERROR; - - /* RSA */ -#ifndef NO_RSA - if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { - byte* out = NULL; - int outLen = 0; - byte doUserRsa = 0; - - #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->RsaVerifyCb) - doUserRsa = 1; - #endif /*HAVE_PK_CALLBACKS */ - - WOLFSSL_MSG("Doing RSA peer cert verify"); - - if (doUserRsa) { - #ifdef HAVE_PK_CALLBACKS - outLen = ssl->ctx->RsaVerifyCb(ssl, input + *inOutIdx, sz, - &out, - ssl->buffers.peerRsaKey.buffer, - ssl->buffers.peerRsaKey.length, - ssl->RsaVerifyCtx); - #endif /*HAVE_PK_CALLBACKS */ - } - else { - outLen = wc_RsaSSL_VerifyInline(input + *inOutIdx, sz, &out, - ssl->peerRsaKey); - } - - if (IsAtLeastTLSv1_2(ssl)) { -#ifdef WOLFSSL_SMALL_STACK - byte* encodedSig = NULL; -#else - byte encodedSig[MAX_ENCODED_SIG_SZ]; -#endif - word32 sigSz; - byte* digest = ssl->hsHashes->certHashes.sha; - int typeH = SHAh; - int digestSz = SHA_DIGEST_SIZE; - -#ifdef WOLFSSL_SMALL_STACK - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig == NULL) - return MEMORY_E; + #endif #endif - if (sigAlgo != rsa_sa_algo) { - WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); - } - - if (hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = ssl->hsHashes->certHashes.sha256; - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = ssl->hsHashes->certHashes.sha384; - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = ssl->hsHashes->certHashes.sha512; - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - #endif - } - - sigSz = wc_EncodeSignature(encodedSig, digest, digestSz, typeH); - - if (outLen == (int)sigSz && out && XMEMCMP(out, encodedSig, - min(sigSz, MAX_ENCODED_SIG_SZ)) == 0) - ret = 0; /* verified */ - -#ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + ret = MatchSuite(ssl, &clSuites); +#ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_ERROR) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret < 0) + SendAlert(ssl, alert_fatal, handshake_failure); #endif - } - else { - if (outLen == FINISHED_SZ && out && XMEMCMP(out, - &ssl->hsHashes->certHashes, - FINISHED_SZ) == 0) { - ret = 0; /* verified */ - } - } + +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled && + IsEncryptionOn(ssl, 0)) { + ssl->secure_renegotiation->startScr = 1; } #endif -#ifdef HAVE_ECC - if (ssl->peerEccDsaKeyPresent) { - int verify = 0; - int err = -1; - byte* digest = ssl->hsHashes->certHashes.sha; - word32 digestSz = SHA_DIGEST_SIZE; - byte doUserEcc = 0; - - #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->EccVerifyCb) - doUserEcc = 1; - #endif - - WOLFSSL_MSG("Doing ECC peer cert verify"); - - if (IsAtLeastTLSv1_2(ssl)) { - if (sigAlgo != ecc_dsa_sa_algo) { - WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); - } - - if (hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = ssl->hsHashes->certHashes.sha256; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = ssl->hsHashes->certHashes.sha384; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = ssl->hsHashes->certHashes.sha512; - digestSz = SHA512_DIGEST_SIZE; - #endif - } - } - - if (doUserEcc) { - #ifdef HAVE_PK_CALLBACKS - ret = ssl->ctx->EccVerifyCb(ssl, input + *inOutIdx, sz, digest, - digestSz, - ssl->buffers.peerEccDsaKey.buffer, - ssl->buffers.peerEccDsaKey.length, - &verify, ssl->EccVerifyCtx); - #endif - } - else { - err = wc_ecc_verify_hash(input + *inOutIdx, sz, digest, - digestSz, &verify, ssl->peerEccDsaKey); - } - - if (err == 0 && verify == 1) - ret = 0; /* verified */ - } -#endif - *inOutIdx += sz; - - if (ret == 0) - ssl->options.havePeerVerify = 1; + WOLFSSL_LEAVE("DoClientHello", ret); + WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); return ret; } -#endif /* !NO_RSA || HAVE_ECC */ + +#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_ED448)) && !defined(WOLFSSL_NO_CLIENT_AUTH) + + 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; + } + + /* handle processing of certificate_verify (15) */ + static int DoCertificateVerify(WOLFSSL* ssl, byte* input, + word32* inOutIdx, word32 size) + { + 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_START(WC_FUNC_CERTIFICATE_VERIFY_DO); + WOLFSSL_ENTER("DoCertificateVerify"); + + #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(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.asyncState) + { + case TLS_ASYNC_BEGIN: + { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "CertificateVerify"); + 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: + { + if (IsAtLeastTLSv1_2(ssl)) { + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + + 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 + #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH) + else if (ssl->peerEd25519KeyPresent) + args->sigAlgo = ed25519_sa_algo; + #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */ + #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH) + else if (ssl->peerEd448KeyPresent) + args->sigAlgo = ed448_sa_algo; + #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */ + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + + ato16(input + args->idx, &args->sz); + args->idx += OPAQUE16_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) { + + 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 (args->sigAlgo != ecc_dsa_sa_algo) { + WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); + } + + SetDigest(ssl, args->hashAlgo); + } + } + #endif /* HAVE_ECC */ + #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH) + 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 && !NO_ED25519_CLIENT_AUTH */ + #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH) + if (ssl->peerEd448KeyPresent) { + WOLFSSL_MSG("Doing ED448 peer cert verify"); + if (IsAtLeastTLSv1_2(ssl) && + args->sigAlgo != ed448_sa_algo) { + WOLFSSL_MSG( + "Oops, peer sent ED448 key but not in verify"); + } + } + #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + 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 + args->idx, + args->sz, + &args->output, + args->sigAlgo, args->hashAlgo, + ssl->peerRsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerRsaKey + #else + NULL + #endif + ); + if (ret >= 0) { + if (args->sigAlgo == rsa_sa_algo) + args->sendSz = ret; + else { + args->sigSz = ret; + args->sendSz = ssl->buffers.digest.length; + } + 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, + ssl->buffers.digest.buffer, ssl->buffers.digest.length, + ssl->peerEccDsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEccDsaKey + #else + NULL + #endif + ); + } + #endif /* HAVE_ECC */ + #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH) + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing Ed25519 peer cert verify"); + + ret = Ed25519Verify(ssl, + input + args->idx, args->sz, + ssl->hsHashes->messages, ssl->hsHashes->prevLen, + ssl->peerEd25519Key, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEd25519Key + #else + NULL + #endif + ); + } + #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */ + #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH) + if (ssl->peerEd448KeyPresent) { + WOLFSSL_MSG("Doing Ed448 peer cert verify"); + + ret = Ed448Verify(ssl, + input + args->idx, args->sz, + ssl->hsHashes->messages, ssl->hsHashes->prevLen, + ssl->peerEd448Key, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEd448Key + #else + NULL + #endif + ); + } + #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */ + + #ifdef WOLFSSL_ASYNC_CRYPT + /* handle async pending */ + if (ret == WC_PENDING_E) + goto exit_dcv; + #endif + + /* Check for error */ + if (ret != 0) { + ret = SIG_VERIFY_E; + 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) { + if (IsAtLeastTLSv1_2(ssl)) { + #ifdef WC_RSA_PSS + if (args->sigAlgo == rsa_pss_sa_algo) { + SetDigest(ssl, args->hashAlgo); + + #ifdef HAVE_SELFTEST + ret = wc_RsaPSS_CheckPadding( + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + args->output, args->sigSz, + HashAlgoToType(args->hashAlgo)); + #else + ret = wc_RsaPSS_CheckPadding_ex( + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + args->output, args->sigSz, + HashAlgoToType(args->hashAlgo), -1, + mp_count_bits(&ssl->peerRsaKey->n)); + #endif + if (ret != 0) { + ret = SIG_VERIFY_E; + goto exit_dcv; + } + } + else + #endif + { + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig; + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif + + #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 + } + } + else { + if (args->sendSz != FINISHED_SZ || !args->output || + XMEMCMP(args->output, + &ssl->hsHashes->certHashes, FINISHED_SZ) != 0) { + ret = VERIFY_CERT_ERROR; + } + } + } + #endif /* !NO_RSA */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + args->idx += MacSize(ssl); + #endif + } + + ssl->options.havePeerVerify = 1; + + /* Set final index */ + args->idx += args->sz; + *inOutIdx = args->idx; + + /* 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("DoCertificateVerify", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_DO); + + #ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not received so it can process again */ + ssl->msgsReceived.got_certificate_verify = 0; + + return ret; + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + #ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_ERROR) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret == SIG_VERIFY_E) + SendAlert(ssl, alert_fatal, decrypt_error); + else if (ret != 0) + SendAlert(ssl, alert_fatal, bad_certificate); + #endif + /* Digest is not allocated, so do this to prevent free */ + ssl->buffers.digest.buffer = NULL; + ssl->buffers.digest.length = 0; + + /* Final cleanup */ + FreeDcvArgs(ssl, args); + FreeKeyExchange(ssl); + + return ret; + } + +#endif /* (!NO_RSA || ECC || ED25519 || ED448) && !WOLFSSL_NO_CLIENT_AUTH */ + + /* handle generation of server_hello_done (14) */ 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; + + WOLFSSL_START(WC_FUNC_SERVER_HELLO_DONE_SEND); + WOLFSSL_ENTER("SendServerHelloDone"); + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + #endif + + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; - #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; - /* get ouput buffer */ + /* get output buffer */ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; AddHeaders(output, 0, server_hello_done, ssl); - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) - return 0; - } - #endif + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */ - ret = HashOutput(ssl, output, sendSz, 0); + 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, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } else { + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, output, sendSz, 0); if (ret != 0) return ret; + } -#ifdef WOLFSSL_CALLBACKS + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) - AddPacketName("ServerHelloDone", &ssl->handShakeInfo); + AddPacketName(ssl, "ServerHelloDone"); if (ssl->toInfoOn) - AddPacketInfo("ServerHelloDone", &ssl->timeoutInfo, output, sendSz, - ssl->heap); -#endif + AddPacketInfo(ssl, "ServerHelloDone", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + #endif ssl->options.serverState = SERVER_HELLODONE_COMPLETE; ssl->buffers.outputBuffer.length += sendSz; - return SendBuffered(ssl); + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendServerHelloDone", ret); + WOLFSSL_END(WC_FUNC_SERVER_HELLO_DONE_SEND); + + return ret; } +#endif /* !WOLFSSL_NO_TLS12 */ #ifdef HAVE_SESSION_TICKET @@ -13734,6 +27528,17 @@ int DoSessionTicket(WOLFSSL* ssl, byte suite[SUITE_LEN]; /* cipher suite when created */ byte msecret[SECRET_LEN]; /* master secret */ word32 timestamp; /* born on */ + word16 haveEMS; /* have extended master secret */ +#ifdef WOLFSSL_TLS13 + word32 ageAdd; /* Obfuscation of age */ + word16 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 */ @@ -13747,7 +27552,7 @@ int DoSessionTicket(WOLFSSL* ssl, } 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; @@ -13755,6 +27560,8 @@ int DoSessionTicket(WOLFSSL* ssl, int ret; byte zeros[WOLFSSL_TICKET_MAC_SZ]; /* biggest cmp size */ + XMEMSET(&it, 0, sizeof(it)); + /* build internal */ it.pv.major = ssl->version.major; it.pv.minor = ssl->version.minor; @@ -13762,17 +27569,47 @@ int DoSessionTicket(WOLFSSL* ssl, 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); + #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)); /* encrypt */ encLen = WOLFSSL_TICKET_ENC_SZ; /* max size user can use */ - ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac, 1, + if (ssl->ctx->ticketEncCb == NULL) { + ret = WOLFSSL_TICKET_RET_FATAL; + } + else { + ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac, 1, et->enc_ticket, sizeof(InternalTicket), &encLen, ssl->ctx->ticketEncCtx); + } if (ret == WOLFSSL_TICKET_RET_OK) { if (encLen < (int)sizeof(InternalTicket) || encLen > WOLFSSL_TICKET_ENC_SZ) { @@ -13830,6 +27667,9 @@ int DoSessionTicket(WOLFSSL* ssl, int outLen; word16 inLen; + WOLFSSL_START(WC_FUNC_TICKET_DO); + WOLFSSL_ENTER("DoClientTicket"); + if (len > SESSION_TICKET_LEN || len < (word32)(sizeof(InternalTicket) + WOLFSSL_TICKET_FIXED_SZ)) { return BAD_TICKET_MSG_SZ; @@ -13844,19 +27684,75 @@ int DoSessionTicket(WOLFSSL* ssl, return BAD_TICKET_MSG_SZ; } outLen = inLen; /* may be reduced by user padding */ - ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, + + if (ssl->ctx->ticketEncCb == NULL) { + ret = WOLFSSL_TICKET_RET_FATAL; + } + else { + ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->enc_ticket + inLen, 0, et->enc_ticket, inLen, &outLen, ssl->ctx->ticketEncCtx); + } if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) return ret; - if (outLen > inLen || outLen < (int)sizeof(InternalTicket)) { + if (outLen > (int)inLen || outLen < (int)sizeof(InternalTicket)) { WOLFSSL_MSG("Bad user ticket decrypt len"); return BAD_TICKET_KEY_CB_SZ; } /* get master secret */ - if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) - XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); + if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) { + if (ssl->version.minor < it->pv.minor) { + WOLFSSL_MSG("Ticket has greater version"); + return VERSION_ERROR; + } + else if (ssl->version.minor > it->pv.minor) { + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Ticket has lesser version"); + return VERSION_ERROR; + } + + WOLFSSL_MSG("Downgrading protocol due to ticket"); + + if (it->pv.minor < ssl->options.minDowngrade) + return VERSION_ERROR; + ssl->version.minor = it->pv.minor; + } + + + 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; + #ifndef NO_RESUME_SUITE_CHECK + ssl->session.cipherSuite0 = it->suite[0]; + ssl->session.cipherSuite = it->suite[1]; + #endif + } + 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 + } + } + + WOLFSSL_LEAVE("DoClientTicket", ret); + WOLFSSL_END(WC_FUNC_TICKET_DO); return ret; } @@ -13871,12 +27767,8 @@ int DoSessionTicket(WOLFSSL* ssl, word32 length = SESSION_HINT_SZ + LENGTH_SZ; word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - length += DTLS_RECORD_EXTRA; - idx += DTLS_RECORD_EXTRA; - } - #endif + WOLFSSL_START(WC_FUNC_TICKET_SEND); + WOLFSSL_ENTER("SendTicket"); if (ssl->options.createTicket) { ret = CreateTicket(ssl); @@ -13886,11 +27778,21 @@ int DoSessionTicket(WOLFSSL* ssl, length += ssl->session.ticketLen; sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + if (!ssl->options.dtls) { + if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) + sendSz += MAX_MSG_EXTRA; + } + else { + #ifdef WOLFSSL_DTLS + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + #endif + } /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; - /* get ouput buffer */ + /* get output buffer */ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; @@ -13906,23 +27808,114 @@ int DoSessionTicket(WOLFSSL* ssl, /* ticket */ XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen); - /* idx += ssl->session.ticketLen; */ + idx += ssl->session.ticketLen; + + if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { + byte* input; + int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + + 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, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } + else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + + DtlsSEQIncrement(ssl, CUR_ORDER); + } + #endif + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + } - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) return ret; ssl->buffers.outputBuffer.length += sendSz; - return SendBuffered(ssl); + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTicket", ret); + WOLFSSL_END(WC_FUNC_TICKET_SEND); + + return ret; } #endif /* HAVE_SESSION_TICKET */ +#ifndef WOLFSSL_NO_TLS12 -#ifdef WOLFSSL_DTLS - int SendHelloVerifyRequest(WOLFSSL* ssl) +#if defined(HAVE_SECURE_RENEGOTIATION) && \ + defined(HAVE_SERVER_RENEGOTIATION_INFO) && \ + !defined(WOLFSSL_NO_SERVER) + + /* handle generation of server's hello_request (0) */ + int SendHelloRequest(WOLFSSL* ssl) + { + byte* output; + int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int ret; + + WOLFSSL_START(WC_FUNC_HELLO_REQUEST_SEND); + WOLFSSL_ENTER("SendHelloRequest"); + + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(output, 0, hello_request, ssl); + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */ + + 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, 0, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendHelloRequest", ret); + WOLFSSL_END(WC_FUNC_HELLO_REQUEST_SEND); + + return ret; + } + +#endif /* HAVE_SECURE_RENEGOTIATION && HAVE_SERVER_RENEGOTIATION_INFO */ + +#ifdef WOLFSSL_DTLS + /* handle generation of DTLS hello_verify_request (3) */ + static int SendHelloVerifyRequest(WOLFSSL* ssl, + const byte* cookie, byte cookieSz) { byte* output; - byte cookieSz = COOKIE_SZ; int length = VERSION_SZ + ENUM_LEN + cookieSz; int idx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ; int sendSz = length + idx; @@ -13932,457 +27925,1488 @@ int DoSessionTicket(WOLFSSL* ssl, if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; - /* get ouput buffer */ + /* get output buffer */ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; + /* Hello Verify Request should use the same sequence number as the + * Client Hello. */ + ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; + ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; AddHeaders(output, length, hello_verify_request, ssl); - output[idx++] = ssl->chVersion.major; - output[idx++] = ssl->chVersion.minor; +#ifdef OPENSSL_EXTRA + output[idx++] = DTLS_MAJOR; + output[idx++] = DTLS_MINOR; +#else + output[idx++] = ssl->version.major; + output[idx++] = ssl->version.minor; +#endif output[idx++] = cookieSz; - if (ssl->ctx->CBIOCookie == NULL) { - WOLFSSL_MSG("Your Cookie callback is null, please set"); + if (cookie == NULL || cookieSz == 0) return COOKIE_ERROR; - } - if ((ret = ssl->ctx->CBIOCookie(ssl, output + idx, cookieSz, - ssl->IOCB_CookieCtx)) < 0) - return ret; - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) - return ret; + XMEMCPY(output + idx, cookie, cookieSz); -#ifdef WOLFSSL_CALLBACKS +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) - AddPacketName("HelloVerifyRequest", &ssl->handShakeInfo); + AddPacketName(ssl, "HelloVerifyRequest"); if (ssl->toInfoOn) - AddPacketInfo("HelloVerifyRequest", &ssl->timeoutInfo, output, - sendSz, ssl->heap); + AddPacketInfo(ssl, "HelloVerifyRequest", handshake, output, + sendSz, WRITE_PROTO, ssl->heap); #endif - ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE; ssl->buffers.outputBuffer.length += sendSz; return SendBuffered(ssl); } -#endif +#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; + } + + /* handle processing client_key_exchange (16) */ static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size) { - int ret = 0; - word32 length = 0; - byte* out = NULL; - word32 begin = *inOutIdx; + 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 - (void)length; /* shut up compiler warnings */ - (void)out; - (void)input; (void)size; - (void)begin; + (void)input; - if (ssl->options.side != WOLFSSL_SERVER_END) { - WOLFSSL_MSG("Client received client keyexchange, attack?"); - WOLFSSL_ERROR(ssl->error = SIDE_ERROR); - return SSL_FATAL_ERROR; + WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); + WOLFSSL_ENTER("DoClientKeyExchange"); + + #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_dcke; + } + else + #endif /* WOLFSSL_ASYNC_CRYPT */ + { + /* Reset state */ + ret = 0; + 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 } - if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { - WOLFSSL_MSG("Client sending keyexchange at wrong time"); - SendAlert(ssl, alert_fatal, unexpected_message); - return OUT_OF_ORDER_E; - } - - #ifndef NO_CERTS - if (ssl->options.verifyPeer && ssl->options.failNoCert) - if (!ssl->options.havePeerCert) { - WOLFSSL_MSG("client didn't present peer cert"); - return NO_PEER_CERT; - } - #endif - - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ClientKeyExchange", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddLateName("ClientKeyExchange", &ssl->timeoutInfo); - #endif - - switch (ssl->specs.kea) { - #ifndef NO_RSA - case rsa_kea: + /* Do Client Key Exchange State Machine */ + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: { - word32 idx = 0; - RsaKey key; - byte doUserRsa = 0; + /* Sanity checks */ + if (ssl->options.side != WOLFSSL_SERVER_END) { + WOLFSSL_MSG("Client received client keyexchange, attack?"); + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + ERROR_OUT(WOLFSSL_FATAL_ERROR, exit_dcke); + } - #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->RsaDecCb) - doUserRsa = 1; - #endif + if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("Client sending keyexchange at wrong time"); + SendAlert(ssl, alert_fatal, unexpected_message); + ERROR_OUT(OUT_OF_ORDER_E, exit_dcke); + } - ret = wc_InitRsaKey(&key, ssl->heap); - if (ret != 0) return ret; + #ifndef NO_CERTS + if (ssl->options.verifyPeer && ssl->options.failNoCert) { + if (!ssl->options.havePeerCert) { + WOLFSSL_MSG("client didn't present peer cert"); + ERROR_OUT(NO_PEER_CERT, exit_dcke); + } + } - if (ssl->buffers.key.buffer) - ret = wc_RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, - &key, ssl->buffers.key.length); - else - return NO_PRIVATE_KEY; + if (ssl->options.verifyPeer && ssl->options.failNoCertxPSK) { + if (!ssl->options.havePeerCert && + !ssl->options.usingPSK_cipher) { + WOLFSSL_MSG("client didn't present peer cert"); + return NO_PEER_CERT; + } + } + #endif /* !NO_CERTS */ - if (ret == 0) { - length = wc_RsaEncryptSize(&key); - ssl->arrays->preMasterSz = SECRET_LEN; + #if defined(WOLFSSL_CALLBACKS) + if (ssl->hsInfoOn) { + AddPacketName(ssl, "ClientKeyExchange"); + } + if (ssl->toInfoOn) { + AddLateName("ClientKeyExchange", &ssl->timeoutInfo); + } + #endif - if (ssl->options.tls) { - word16 check; + if (ssl->arrays->preMasterSecret == NULL) { + ssl->arrays->preMasterSz = ENCRYPT_LEN; + ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_SECRET); + if (ssl->arrays->preMasterSecret == NULL) { + ERROR_OUT(MEMORY_E, exit_dcke); + } + XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN); + } - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &check); - *inOutIdx += OPAQUE16_LEN; - - if ((word32) check != length) { - WOLFSSL_MSG("RSA explicit size doesn't match"); - wc_FreeRsaKey(&key); - return RSA_PRIVATE_ERROR; + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + { + break; + } /* rsa_kea */ + #endif /* !NO_RSA */ + #ifndef NO_PSK + case psk_kea: + { + /* sanity check that PSK server callback has been set */ + if (ssl->options.server_psk_cb == NULL) { + WOLFSSL_MSG("No server PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); } + break; } - - if ((*inOutIdx - begin) + length > size) { - WOLFSSL_MSG("RSA message too big"); - wc_FreeRsaKey(&key); - return BUFFER_ERROR; + #endif /* !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { + ERROR_OUT(NO_PRIVATE_KEY, exit_dcke); + } + break; } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + case ecc_diffie_hellman_kea: + { + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + #ifndef NO_DH + case diffie_hellman_kea: + { + break; + } + #endif /* !NO_DH */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + /* sanity check that PSK server callback has been set */ + if (ssl->options.server_psk_cb == NULL) { + WOLFSSL_MSG("No server PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); + } + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + /* sanity check that PSK server callback has been set */ + if (ssl->options.server_psk_cb == NULL) { + WOLFSSL_MSG("No server PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); + } + break; + } + #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */ + default: + WOLFSSL_MSG("Bad kea type"); + ret = BAD_KEA_TYPE_E; + } /* switch (ssl->specs.kea) */ - if (doUserRsa) { - #ifdef HAVE_PK_CALLBACKS - ret = ssl->ctx->RsaDecCb(ssl, - input + *inOutIdx, length, &out, - ssl->buffers.key.buffer, - ssl->buffers.key.length, - ssl->RsaDecCtx); + /* Check for error */ + if (ret != 0) { + goto exit_dcke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + { + word16 keySz; + + ssl->buffers.keyType = rsa_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_dcke; + } + args->length = (word32)keySz; + ssl->arrays->preMasterSz = SECRET_LEN; + + if (ssl->options.tls) { + word16 check; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &check); + args->idx += OPAQUE16_LEN; + + if ((word32)check != args->length) { + WOLFSSL_MSG("RSA explicit size doesn't match"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, bad_record_mac); #endif + ERROR_OUT(RSA_PRIVATE_ERROR, exit_dcke); + } + } + + if ((args->idx - args->begin) + args->length > size) { + WOLFSSL_MSG("RSA message too big"); + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + /* 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 */ + #ifndef NO_PSK + case psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + word16 ci_sz; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + 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 ((args->idx - args->begin) + ci_sz > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + XMEMCPY(ssl->arrays->client_identity, + input + args->idx, ci_sz); + args->idx += ci_sz; + + 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); + + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); + } + + /* make psk pre master secret */ + /* length of key + length 0s + length of key + key */ + c16toa((word16) ssl->arrays->psk_keySz, pms); + pms += OPAQUE16_LEN; + + XMEMSET(pms, 0, ssl->arrays->psk_keySz); + pms += ssl->arrays->psk_keySz; + + 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 * 2) + (OPAQUE16_LEN * 2); + break; + } + #endif /* !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + word16 cipherLen; + word16 plainLen = ENCRYPT_LEN; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &cipherLen); + args->idx += OPAQUE16_LEN; + + if (cipherLen > MAX_NTRU_ENCRYPT_SZ) { + ERROR_OUT(NTRU_KEY_ERROR, exit_dcke); + } + + 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 + args->idx, &plainLen, + ssl->arrays->preMasterSecret)) { + ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke); + } + + if (plainLen != SECRET_LEN) { + ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke); + } + + args->idx += cipherLen; + ssl->arrays->preMasterSz = plainLen; + break; + } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + case ecc_diffie_hellman_kea: + { + #ifdef HAVE_ECC + ecc_key* private_key = ssl->eccTempKey; + + /* handle static private key */ + if (ssl->specs.static_ecdh && + ssl->ecdhCurveOID != ECC_X25519_OID && + ssl->ecdhCurveOID != ECC_X448_OID) { + word16 keySz; + + ssl->buffers.keyType = ecc_dsa_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_dcke; + } + private_key = (ecc_key*)ssl->hsKey; + } + #endif + + /* import peer ECC key */ + if ((args->idx - args->begin) + OPAQUE8_LEN > size) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, decode_error); + #endif + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + args->length = input[args->idx++]; + + if ((args->idx - args->begin) + args->length > size) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, decode_error); + #endif + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + #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 ((ret = wc_curve25519_check_public( + input + args->idx, args->length, + EC25519_LITTLE_ENDIAN)) != 0) { + #ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_E) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret == ECC_OUT_OF_RANGE_E) + SendAlert(ssl, alert_fatal, bad_record_mac); + else { + SendAlert(ssl, alert_fatal, + illegal_parameter); + } + #endif + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + if (wc_curve25519_import_public_ex( + input + args->idx, args->length, + ssl->peerX25519Key, + EC25519_LITTLE_ENDIAN)) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, illegal_parameter); + #endif + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + ssl->arrays->preMasterSz = CURVE25519_KEYSIZE; + + ssl->peerX25519KeyPresent = 1; + + break; + } + #endif + #ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X448SharedSecretCb != NULL) { + break; + } + #endif + if (ssl->peerX448Key == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448, + (void**)&ssl->peerX448Key); + if (ret != 0) { + goto exit_dcke; + } + } else if (ssl->peerX448KeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448, + ssl->peerX448Key); + ssl->peerX448KeyPresent = 0; + if (ret != 0) { + goto exit_dcke; + } + } + + if ((ret = wc_curve448_check_public( + input + args->idx, args->length, + EC448_LITTLE_ENDIAN)) != 0) { + #ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_E) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret == ECC_OUT_OF_RANGE_E) + SendAlert(ssl, alert_fatal, bad_record_mac); + else { + SendAlert(ssl, alert_fatal, + illegal_parameter); + } + #endif + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + if (wc_curve448_import_public_ex( + input + args->idx, args->length, + ssl->peerX448Key, + EC448_LITTLE_ENDIAN)) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, illegal_parameter); + #endif + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + ssl->arrays->preMasterSz = CURVE448_KEY_SIZE; + + ssl->peerX448KeyPresent = 1; + + break; + } + #endif + #ifdef HAVE_ECC + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + if (!ssl->specs.static_ecdh && + ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG("Ecc ephemeral key not made correctly"); + ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); + } + + if (ssl->peerEccKey == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + if (ret != 0) { + goto exit_dcke; + } + } else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, + ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + if (ret != 0) { + goto exit_dcke; + } + } + + if (wc_ecc_import_x963_ex(input + args->idx, + args->length, ssl->peerEccKey, + private_key->dp->id)) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, illegal_parameter); + #endif + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + ssl->arrays->preMasterSz = private_key->dp->size; + + ssl->peerEccKeyPresent = 1; + #endif /* HAVE_ECC */ + + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + #ifndef NO_DH + case diffie_hellman_kea: + { + word16 clientPubSz; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &clientPubSz); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + clientPubSz > size) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, decode_error); + #endif + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + 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 */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + word16 clientSz; + + /* Read in the PSK hint */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; + if (clientSz > MAX_PSK_ID_LEN) { + ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); + } + + if ((args->idx - args->begin) + clientSz > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + 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 ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + clientSz > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + 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(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + word16 clientSz; + + /* Read in the PSK hint */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; + if (clientSz > MAX_PSK_ID_LEN) { + ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); + } + if ((args->idx - args->begin) + clientSz > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + XMEMCPY(ssl->arrays->client_identity, + input + args->idx, clientSz); + args->idx += clientSz; + ssl->arrays->client_identity[clientSz] = '\0'; /* null term */ + + /* import peer ECC key */ + if ((args->idx - args->begin) + OPAQUE8_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + args->length = input[args->idx++]; + + 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 ((ret = wc_curve25519_check_public( + input + args->idx, args->length, + EC25519_LITTLE_ENDIAN)) != 0) { + #ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_E) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret == ECC_OUT_OF_RANGE_E) + SendAlert(ssl, alert_fatal, bad_record_mac); + else { + SendAlert(ssl, alert_fatal, + illegal_parameter); + } + #endif + ERROR_OUT(ECC_PEERKEY_ERROR, 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_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X448SharedSecretCb != NULL) { + break; + } + #endif + + if (ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG( + "X448 ephemeral key not made correctly"); + ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); + } + + if (ssl->peerX448Key == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448, + (void**)&ssl->peerX448Key); + if (ret != 0) { + goto exit_dcke; + } + } else if (ssl->peerX448KeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448, + ssl->peerX448Key); + ssl->peerX448KeyPresent = 0; + if (ret != 0) { + goto exit_dcke; + } + } + + if ((ret = wc_curve448_check_public( + input + args->idx, args->length, + EC448_LITTLE_ENDIAN)) != 0) { + #ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_E) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret == ECC_OUT_OF_RANGE_E) + SendAlert(ssl, alert_fatal, bad_record_mac); + else { + SendAlert(ssl, alert_fatal, + illegal_parameter); + } + #endif + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + if (wc_curve448_import_public_ex( + input + args->idx, args->length, + ssl->peerX448Key, + EC448_LITTLE_ENDIAN)) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + ssl->peerX448KeyPresent = 1; + + break; + } + #endif + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + if (ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG("Ecc ephemeral key not made correctly"); + ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); + } + + if (ssl->peerEccKey == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + if (ret != 0) { + goto exit_dcke; + } + } + else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, + ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + if (ret != 0) { + goto exit_dcke; + } + } + 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 || CURVE25519 || CURVE448) && !NO_PSK */ + default: + ret = BAD_KEA_TYPE_E; + } /* switch (ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dcke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + { + RsaKey* key = (RsaKey*)ssl->hsKey; + + ret = RsaDec(ssl, + input + args->idx, + args->length, + &args->output, + &args->sigSz, + key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + + /* Errors that can occur here that should be + * indistinguishable: + * RSA_BUFFER_E, RSA_PAD_E and RSA_PRIVATE_ERROR + */ + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_dcke; + #endif + if (ret == BAD_FUNC_ARG) + goto exit_dcke; + + args->lastErr = ret - (SECRET_LEN - args->sigSz); + ret = 0; + break; + } /* rsa_kea */ + #endif /* !NO_RSA */ + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + break; + } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + case ecc_diffie_hellman_kea: + { + void* private_key = ssl->eccTempKey; + (void)private_key; + + #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 + ); + break; + } + #endif + #ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) { + ret = X448SharedSecret(ssl, + (curve448_key*)private_key, + ssl->peerX448Key, + input + args->idx, &args->length, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + WOLFSSL_SERVER_END + ); + break; + } + #endif + #ifdef HAVE_ECC + if (ssl->specs.static_ecdh) { + private_key = ssl->hsKey; + } + + /* Generate shared secret */ + ret = EccSharedSecret(ssl, + (ecc_key*)private_key, ssl->peerEccKey, + input + args->idx, &args->length, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + WOLFSSL_SERVER_END + ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + FreeKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + } + #endif + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + #ifndef NO_DH + case diffie_hellman_kea: + { + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_Priv.buffer, + ssl->buffers.serverDH_Priv.length, + input + args->idx, + (word16)args->sigSz, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz); + break; + } + #endif /* !NO_DH */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_Priv.buffer, + 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(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + #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 WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + } + break; + } + #endif + #ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID) { + ret = X448SharedSecret(ssl, + (curve448_key*)ssl->eccTempKey, + ssl->peerX448Key, + input + args->idx, &args->length, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &args->sigSz, + WOLFSSL_SERVER_END + ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + FreeKey(ssl, DYNAMIC_TYPE_CURVE448, + (void**)&ssl->peerX448Key); + ssl->peerX448KeyPresent = 0; + } + break; + } + #endif + /* Generate shared secret */ + ret = EccSharedSecret(ssl, + ssl->eccTempKey, ssl->peerEccKey, + input + args->idx, &args->length, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &args->sigSz, + WOLFSSL_SERVER_END + ); + if (!ssl->specs.static_ecdh + #ifdef WOLFSSL_ASYNC_CRYPT + && ret != WC_PENDING_E + #endif + ) { + FreeKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + } + break; + } + #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */ + default: + ret = BAD_KEA_TYPE_E; + } /* switch (ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dcke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + { + byte mask; + int i; + + /* Add the signature length to idx */ + args->idx += args->length; + + #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"); + } + } + #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 */ + /* On error 'ret' will be negative - top bit set */ + mask = ((unsigned int)ret >> + ((sizeof(ret) * 8) - 1)) - 1; + + /* build PreMasterSecret */ + ssl->arrays->preMasterSecret[0] = ssl->chVersion.major; + ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor; + + if (args->output != NULL) { + /* Use random secret on error */ + for (i = VERSION_SZ; i < SECRET_LEN; i++) { + ssl->arrays->preMasterSecret[i] = + ctMaskSel(mask, args->output[i], + ssl->arrays->preMasterSecret[i]); + } + } + /* 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 */ + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + break; + } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + case ecc_diffie_hellman_kea: + { + /* skip past the imported peer key */ + args->idx += args->length; + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + #ifndef NO_DH + case diffie_hellman_kea: + { + args->idx += (word16)args->sigSz; + break; + } + #endif /* !NO_DH */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + word16 clientSz = (word16)args->sigSz; + + args->idx += clientSz; + c16toa((word16)ssl->arrays->preMasterSz, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN; + pms += ssl->arrays->preMasterSz; + + /* Use the PSK hint to look up the PSK and add it to the + * preMasterSecret here. */ + ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, + ssl->arrays->client_identity, ssl->arrays->psk_key, + MAX_PSK_KEY_LEN); + + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); + } + + 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; + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + word16 clientSz = (word16)args->sigSz; + + /* skip past the imported peer key */ + args->idx += args->length; + + /* Add preMasterSecret */ + 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 + * preMasterSecret here. */ + ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, + ssl->arrays->client_identity, ssl->arrays->psk_key, + MAX_PSK_KEY_LEN); + + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); + } + + 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; + break; + } + #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */ + default: + ret = BAD_KEA_TYPE_E; + } /* switch (ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dcke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead) + args->idx += MacSize(ssl); + #endif + } + + #ifdef HAVE_QSH + word16 name; + + if (ssl->options.haveQSH) { + /* extension name */ + 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 + args->idx, + size - args->idx + args->begin, 1)) < 0) { + ERROR_OUT(qshSz, exit_dcke); + } + args->idx += qshSz; } else { - ret = wc_RsaPrivateDecryptInline(input + *inOutIdx, length, - &out, &key); - } - - *inOutIdx += length; - - if (ret == SECRET_LEN) { - XMEMCPY(ssl->arrays->preMasterSecret, out, SECRET_LEN); - if (ssl->arrays->preMasterSecret[0] != - ssl->chVersion.major - || ssl->arrays->preMasterSecret[1] != - ssl->chVersion.minor) - ret = PMS_VERSION_ERROR; - else - ret = MakeMasterSecret(ssl); - } - else { - ret = RSA_PRIVATE_ERROR; + /* unknown extension sent client ignored handshake */ + ERROR_OUT(BUFFER_ERROR, exit_dcke); } } - - wc_FreeRsaKey(&key); - } - break; - #endif - #ifndef NO_PSK - case psk_kea: - { - byte* pms = ssl->arrays->preMasterSecret; - word16 ci_sz; - - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &ci_sz); - *inOutIdx += OPAQUE16_LEN; - - if (ci_sz > MAX_PSK_ID_LEN) - return CLIENT_ID_ERROR; - - if ((*inOutIdx - begin) + ci_sz > size) - return BUFFER_ERROR; - - XMEMCPY(ssl->arrays->client_identity, input + *inOutIdx, ci_sz); - *inOutIdx += ci_sz; - - ssl->arrays->client_identity[min(ci_sz, MAX_PSK_ID_LEN-1)] = 0; - ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, - ssl->arrays->client_identity, 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; - - /* make psk pre master secret */ - /* length of key + length 0s + length of key + key */ - c16toa((word16) ssl->arrays->psk_keySz, pms); - pms += OPAQUE16_LEN; - - XMEMSET(pms, 0, ssl->arrays->psk_keySz); - pms += ssl->arrays->psk_keySz; - - 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 * 2 + 4; - + #endif /* HAVE_QSH */ ret = MakeMasterSecret(ssl); - /* No further need for PSK */ - ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); - ssl->arrays->psk_keySz = 0; - } - break; - #endif /* NO_PSK */ - #ifdef HAVE_NTRU - case ntru_kea: - { - word16 cipherLen; - word16 plainLen = sizeof(ssl->arrays->preMasterSecret); - - if (!ssl->buffers.key.buffer) - return NO_PRIVATE_KEY; - - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &cipherLen); - *inOutIdx += OPAQUE16_LEN; - - if (cipherLen > MAX_NTRU_ENCRYPT_SZ) - return NTRU_KEY_ERROR; - - if ((*inOutIdx - begin) + cipherLen > size) - return BUFFER_ERROR; - - if (NTRU_OK != ntru_crypto_ntru_decrypt( - (word16) ssl->buffers.key.length, - ssl->buffers.key.buffer, cipherLen, - input + *inOutIdx, &plainLen, - ssl->arrays->preMasterSecret)) - return NTRU_DECRYPT_ERROR; - - if (plainLen != SECRET_LEN) - return NTRU_DECRYPT_ERROR; - - *inOutIdx += cipherLen; - - ssl->arrays->preMasterSz = plainLen; - ret = MakeMasterSecret(ssl); - } - break; - #endif /* HAVE_NTRU */ - #ifdef HAVE_ECC - case ecc_diffie_hellman_kea: - { - if ((*inOutIdx - begin) + OPAQUE8_LEN > size) - return BUFFER_ERROR; - - length = input[(*inOutIdx)++]; - - if ((*inOutIdx - begin) + length > size) - return BUFFER_ERROR; - - if (ssl->peerEccKey == NULL) { - /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->ctx->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - return MEMORY_E; - } - wc_ecc_init(ssl->peerEccKey); - } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccKey); - ssl->peerEccKeyPresent = 0; - wc_ecc_init(ssl->peerEccKey); + /* Check for error */ + if (ret != 0) { + goto exit_dcke; } - if (wc_ecc_import_x963(input + *inOutIdx, length, ssl->peerEccKey)) - return ECC_PEERKEY_ERROR; + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* TLS_ASYNC_FINALIZE */ + FALL_THROUGH; - *inOutIdx += length; - ssl->peerEccKeyPresent = 1; - - length = sizeof(ssl->arrays->preMasterSecret); - - if (ssl->specs.static_ecdh) { - ecc_key staticKey; - word32 i = 0; - - wc_ecc_init(&staticKey); - ret = wc_EccPrivateKeyDecode(ssl->buffers.key.buffer, &i, - &staticKey, ssl->buffers.key.length); - - if (ret == 0) - ret = wc_ecc_shared_secret(&staticKey, ssl->peerEccKey, - ssl->arrays->preMasterSecret, &length); - - wc_ecc_free(&staticKey); - } - else { - if (ssl->eccTempKeyPresent == 0) { - WOLFSSL_MSG("Ecc ephemeral key not made correctly"); - ret = ECC_MAKEKEY_ERROR; - } else { - ret = wc_ecc_shared_secret(ssl->eccTempKey,ssl->peerEccKey, - ssl->arrays->preMasterSecret, &length); - } - } - - if (ret != 0) - return ECC_SHARED_ERROR; - - ssl->arrays->preMasterSz = length; - ret = MakeMasterSecret(ssl); - } - break; - #endif /* HAVE_ECC */ - #ifndef NO_DH - case diffie_hellman_kea: + case TLS_ASYNC_END: { - word16 clientPubSz; - DhKey dhKey; + /* Set final index */ + *inOutIdx = args->idx; - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &clientPubSz); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + clientPubSz > size) - return BUFFER_ERROR; - - wc_InitDhKey(&dhKey); - ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length); - if (ret == 0) - ret = wc_DhAgree(&dhKey, ssl->arrays->preMasterSecret, - &ssl->arrays->preMasterSz, - ssl->buffers.serverDH_Priv.buffer, - ssl->buffers.serverDH_Priv.length, - input + *inOutIdx, clientPubSz); - wc_FreeDhKey(&dhKey); - - *inOutIdx += clientPubSz; - - if (ret == 0) - ret = MakeMasterSecret(ssl); - } - break; - #endif /* NO_DH */ - #if !defined(NO_DH) && !defined(NO_PSK) - case dhe_psk_kea: - { - byte* pms = ssl->arrays->preMasterSecret; - word16 clientSz; - DhKey dhKey; - - /* Read in the PSK hint */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &clientSz); - *inOutIdx += OPAQUE16_LEN; - if (clientSz > MAX_PSK_ID_LEN) - return CLIENT_ID_ERROR; - - if ((*inOutIdx - begin) + clientSz > size) - return BUFFER_ERROR; - - XMEMCPY(ssl->arrays->client_identity, - input + *inOutIdx, clientSz); - *inOutIdx += clientSz; - ssl->arrays->client_identity[min(clientSz, MAX_PSK_ID_LEN-1)] = - 0; - - /* Read in the DHE business */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &clientSz); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + clientSz > size) - return BUFFER_ERROR; - - wc_InitDhKey(&dhKey); - ret = wc_DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length); - if (ret == 0) - ret = wc_DhAgree(&dhKey, pms + OPAQUE16_LEN, - &ssl->arrays->preMasterSz, - ssl->buffers.serverDH_Priv.buffer, - ssl->buffers.serverDH_Priv.length, - input + *inOutIdx, clientSz); - wc_FreeDhKey(&dhKey); - - *inOutIdx += clientSz; - c16toa((word16)ssl->arrays->preMasterSz, pms); - ssl->arrays->preMasterSz += OPAQUE16_LEN; - pms += ssl->arrays->preMasterSz; - - /* Use the PSK hint to look up the PSK and add it to the - * preMasterSecret here. */ - ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, - ssl->arrays->client_identity, 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; - - 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; - if (ret == 0) - ret = MakeMasterSecret(ssl); - - /* No further need for PSK */ - ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); - ssl->arrays->psk_keySz = 0; - } - break; - #endif /* !NO_DH && !NO_PSK */ + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + #ifndef NO_CERTS + if (ssl->options.verifyPeer) { + ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); + } + #endif + break; + } /* TLS_ASYNC_END */ default: - { - WOLFSSL_MSG("Bad kea type"); - ret = BAD_KEA_TYPE_E; - } - break; - } + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ - /* No further need for PMS */ - ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + exit_dcke: + + WOLFSSL_LEAVE("DoClientKeyExchange", ret); + WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); + + #ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not received so it can process again */ + ssl->msgsReceived.got_client_key_exchange = 0; + + return ret; + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Cleanup PMS */ + if (ssl->arrays->preMasterSecret != NULL) { + ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + } ssl->arrays->preMasterSz = 0; - if (ret == 0) { - ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; - #ifndef NO_CERTS - if (ssl->options.verifyPeer) - ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); - #endif - } + /* Final cleanup */ + FreeDckeArgs(ssl, args); + FreeKeyExchange(ssl); return ret; } +#endif /* !WOLFSSL_NO_TLS12 */ + +#if defined(OPENSSL_ALL) || 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 */ + if(ssl && ssl->ctx && ssl->ctx->sniRecvCb) { + WOLFSSL_MSG("Calling custom sni callback"); + if(ssl->ctx->sniRecvCb(ssl, NULL, ssl->ctx->sniRecvCbArg) + == alert_fatal) { + WOLFSSL_MSG("Error in custom sni callback. Fatal alert"); + SendAlert(ssl, alert_fatal, unrecognized_name); + return FATAL_ERROR; + } + } + return 0; + } +#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + #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 */ + + +/* return the max record size */ +int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment) +{ + (void) ssl; /* Avoid compiler warnings */ + + if (maxFragment > MAX_RECORD_SIZE) { + maxFragment = MAX_RECORD_SIZE; + } + +#ifdef HAVE_MAX_FRAGMENT + if ((ssl->max_fragment != 0) && ((word16)maxFragment > ssl->max_fragment)) { + maxFragment = ssl->max_fragment; + } +#endif /* HAVE_MAX_FRAGMENT */ +#ifdef WOLFSSL_DTLS + if ((ssl->options.dtls) && (maxFragment > MAX_UDP_SIZE)) { + maxFragment = MAX_UDP_SIZE; + } +#endif + + return maxFragment; +} + + +#undef ERROR_OUT + +#endif /* WOLFCRYPT_ONLY */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/io.c b/FreeRTOS-Plus/Source/WolfSSL/src/io.c deleted file mode 100644 index 195056665..000000000 --- a/FreeRTOS-Plus/Source/WolfSSL/src/io.c +++ /dev/null @@ -1,1141 +0,0 @@ -/* io.c - * - * Copyright (C) 2006-2015 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 _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(WOLFSSL_MDK_ARM) - #if defined(WOLFSSL_MDK5) - #include "cmsis_os.h" - #include "rl_fs.h" - #include "rl_net.h" - #else - #include - #endif - #undef RNG - #include "WOLFSSL_MDK_ARM.h" - #undef RNG - #define RNG wolfSSL_RNG - /* for avoiding name conflict in "stm32f2xx.h" */ - static int errno; - #elif defined(WOLFSSL_TIRTOS) - #include - #elif defined(WOLFSSL_IAR_ARM) - /* nothing */ - #else - #include - #include - #ifndef EBSNET - #include - #endif - #include - #if !(defined(DEVKITPRO) || defined(HAVE_RTP_SYS) || defined(EBSNET)) \ - && !(defined(WOLFSSL_PICOTCP)) - #include - #include - #include - #include - #ifdef __PPU - #include - #else - #include - #endif - #endif - #ifdef HAVE_RTP_SYS - #include - #endif - #ifdef EBSNET - #include "rtipapi.h" /* errno */ - #include "socket.h" - #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) - /* RTCS doesn't have an EWOULDBLOCK error */ - #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 -#elif defined(WOLFSSL_MDK_ARM) - #if defined(WOLFSSL_MDK5) - #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 -#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 -#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; - -#ifdef FREESCALE_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 */ - } -#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(" Would block"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else { - WOLFSSL_MSG(" Socket timeout"); - return WOLFSSL_CBIO_ERR_TIMEOUT; - } - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG(" Connection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG(" Socket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_ECONNREFUSED) { - WOLFSSL_MSG(" Connection refused"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else if (err == SOCKET_ECONNABORTED) { - WOLFSSL_MSG(" Connection aborted"); - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - } - else { - WOLFSSL_MSG(" General 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); - - if (sent < 0) { - err = LastError(); - WOLFSSL_MSG("Embed Send error"); - - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - WOLFSSL_MSG(" Would Block"); - return WOLFSSL_CBIO_ERR_WANT_WRITE; - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG(" Connection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG(" Socket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_EPIPE) { - WOLFSSL_MSG(" Socket EPIPE"); - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - } - else { - WOLFSSL_MSG(" General 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->fd; - int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); - struct sockaddr_storage peer; - XSOCKLENT peerSz = sizeof(peer); - - WOLFSSL_ENTER("EmbedReceiveFrom()"); - - if (!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"); - } - } - - 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(" Would block"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else { - WOLFSSL_MSG(" Socket timeout"); - return WOLFSSL_CBIO_ERR_TIMEOUT; - } - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG(" Connection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG(" Socket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_ECONNREFUSED) { - WOLFSSL_MSG(" Connection refused"); - return WOLFSSL_CBIO_ERR_WANT_READ; - } - else { - WOLFSSL_MSG(" General error"); - return WOLFSSL_CBIO_ERR_GENERAL; - } - } - else { - if (dtlsCtx->peer.sz > 0 - && peerSz != (XSOCKLENT)dtlsCtx->peer.sz - && memcmp(&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->fd; - 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); - if (sent < 0) { - err = LastError(); - WOLFSSL_MSG("Embed Send To error"); - - if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - WOLFSSL_MSG(" Would Block"); - return WOLFSSL_CBIO_ERR_WANT_WRITE; - } - else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG(" Connection reset"); - return WOLFSSL_CBIO_ERR_CONN_RST; - } - else if (err == SOCKET_EINTR) { - WOLFSSL_MSG(" Socket interrupted"); - return WOLFSSL_CBIO_ERR_ISR; - } - else if (err == SOCKET_EPIPE) { - WOLFSSL_MSG(" Socket EPIPE"); - return WOLFSSL_CBIO_ERR_CONN_CLOSE; - } - else { - WOLFSSL_MSG(" General 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; -} - -#endif /* WOLFSSL_DTLS */ - -#ifdef HAVE_OCSP - - -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(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) -{ - 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, NULL, DYNAMIC_TYPE_IN_BUFFER); - 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 */ - do { - 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; - } - } while (len != recvBufSz); - - *respBuf = recvBuf; - return recvBufSz; -} - - -#define SCRATCH_BUFFER_SIZE 512 - -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 - - (void)ctx; - - 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, NULL, - DYNAMIC_TYPE_IN_BUFFER); - - 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); - } - - close(sfd); - XFREE(httpBuf, NULL, DYNAMIC_TYPE_IN_BUFFER); - } - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - - -void EmbedOcspRespFree(void* ctx, byte *resp) -{ - (void)ctx; - - if (resp) - XFREE(resp, NULL, DYNAMIC_TYPE_IN_BUFFER); -} - - -#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; -} - -#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 */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/keys.c b/FreeRTOS-Plus/Source/WolfSSL/src/keys.c index b06debb28..55b2d9bed 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/src/keys.c +++ b/FreeRTOS-Plus/Source/WolfSSL/src/keys.c @@ -1,8 +1,8 @@ /* keys.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Name change compatibility layer no longer needs to be included here */ #ifdef HAVE_CONFIG_H @@ -27,24 +28,27 @@ #include +#ifndef WOLFCRYPT_ONLY + #include #include #if defined(SHOW_SECRETS) || defined(CHACHA_AEAD_TEST) - #ifdef FREESCALE_MQX - #include - #else + #ifndef NO_STDIO_FILESYSTEM #include #endif #endif - +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + int tsip_useable(const WOLFSSL *ssl); +#endif int SetCipherSpecs(WOLFSSL* ssl) { #ifndef NO_WOLFSSL_CLIENT if (ssl->options.side == WOLFSSL_CLIENT_END) { /* server side verified before SetCipherSpecs call */ if (VerifyClientSuite(ssl) != 1) { - WOLFSSL_MSG("SetCipherSpecs() client has an unusuable suite"); + WOLFSSL_MSG("SetCipherSpecs() client has an unusable suite"); return UNSUPPORTED_SUITE; } } @@ -52,8 +56,64 @@ int SetCipherSpecs(WOLFSSL* ssl) /* Chacha extensions, 0xcc */ if (ssl->options.cipherSuite0 == CHACHA_BYTE) { - + switch (ssl->options.cipherSuite) { +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + 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 = 1; /* use old poly1305 padding */ + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + 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 = 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 = 1; /* use old poly1305 padding */ + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + 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 = 1; /* use old poly1305 padding */ + + break; +#endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; @@ -61,13 +121,14 @@ 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; 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 @@ -79,13 +140,14 @@ 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; 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 @@ -97,7 +159,26 @@ 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; + 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_PSK_WITH_CHACHA20_POLY1305_SHA256 + case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + 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; @@ -105,6 +186,48 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.iv_size = CHACHA20_IV_SIZE; ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + ssl->options.oldPoly = 0; /* use recent padding RFC */ + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecdhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + 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 */ + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = dhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + 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 */ + ssl->options.usingPSK_cipher = 1; break; #endif default: @@ -113,12 +236,12 @@ int SetCipherSpecs(WOLFSSL* ssl) } } - /* ECC extensions, or AES-CCM */ + /* ECC extensions, AES-CCM or TLS 1.3 Integrity-only */ if (ssl->options.cipherSuite0 == ECC_BYTE) { - + switch (ssl->options.cipherSuite) { -#ifdef HAVE_ECC +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : @@ -127,61 +250,14 @@ 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; ssl->specs.iv_size = AES_IV_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - break; -#endif -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - break; -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - break; -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - break; + break; #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 @@ -191,61 +267,14 @@ 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; ssl->specs.iv_size = AES_IV_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - break; -#endif -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - break; -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - break; -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - break; + break; #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA @@ -255,7 +284,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; @@ -265,23 +294,6 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - - break; -#endif - #ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA : ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; @@ -289,7 +301,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; @@ -299,23 +311,6 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif -#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = DES3_KEY_SIZE; - ssl->specs.block_size = DES_BLOCK_SIZE; - ssl->specs.iv_size = DES_IV_SIZE; - - break; -#endif - #ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA case TLS_ECDHE_RSA_WITH_RC4_128_SHA : ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; @@ -323,7 +318,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; @@ -333,91 +328,6 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif -#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA - case TLS_ECDH_RSA_WITH_RC4_128_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; - ssl->specs.cipher_type = stream; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = RC4_KEY_SIZE; - ssl->specs.iv_size = 0; - ssl->specs.block_size = 0; - - break; -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = DES3_KEY_SIZE; - ssl->specs.block_size = DES_BLOCK_SIZE; - ssl->specs.iv_size = DES_IV_SIZE; - - break; -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = DES3_KEY_SIZE; - ssl->specs.block_size = DES_BLOCK_SIZE; - ssl->specs.iv_size = DES_IV_SIZE; - - break; -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; - ssl->specs.cipher_type = stream; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = RC4_KEY_SIZE; - ssl->specs.iv_size = 0; - ssl->specs.block_size = 0; - - break; -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA - case TLS_ECDH_ECDSA_WITH_RC4_128_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; - ssl->specs.cipher_type = stream; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = RC4_KEY_SIZE; - ssl->specs.iv_size = 0; - ssl->specs.block_size = 0; - - break; -#endif - #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA : ssl->specs.bulk_cipher_algorithm = wolfssl_aes; @@ -425,7 +335,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; @@ -435,91 +345,6 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - - break; -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - 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.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 = AES_IV_SIZE; - - break; -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - - break; -#endif - -#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - 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.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 = AES_IV_SIZE; - - break; -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - 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.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - - break; -#endif - #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; @@ -527,12 +352,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; break; @@ -545,17 +370,160 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; break; #endif +#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256 + case TLS_ECDHE_PSK_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 = ecdhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecdhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + 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 = AES_IV_SIZE; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ + +#if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) \ + || (defined(HAVE_CURVE448) && defined(HAVE_ED448)) + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + 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 = 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.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + 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 = 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.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; + ssl->specs.cipher_type = block; + 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 = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; + ssl->specs.cipher_type = stream; + 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 = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + 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 = WC_SHA_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 = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + 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 = WC_SHA_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 = AES_IV_SIZE; + + break; +#endif + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 : ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; @@ -563,12 +531,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; break; @@ -581,85 +549,31 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; break; #endif -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - case TLS_ECDH_RSA_WITH_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 = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; - - break; -#endif - -#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - case TLS_ECDH_RSA_WITH_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 = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; - - break; -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; ssl->specs.cipher_type = aead; 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.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; - - break; -#endif - -#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - case TLS_ECDH_ECDSA_WITH_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 = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; break; #endif @@ -671,12 +585,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; break; @@ -689,16 +603,314 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; break; #endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA + case TLS_ECDHE_ECDSA_WITH_NULL_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + 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 = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + break; +#endif + +#endif /* HAVE_ECC || (CURVE25519 && ED25519) || (CURVE448 && ED448) */ + +#if defined(HAVE_ECC) + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + 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; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + 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 = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + 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; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + 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 = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + 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; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + 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; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + case TLS_ECDH_RSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + 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; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; + ssl->specs.cipher_type = block; + 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 = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; + ssl->specs.cipher_type = stream; + 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 = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + 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; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + 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 = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + 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 = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + case TLS_ECDH_RSA_WITH_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 = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + 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; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + case TLS_ECDH_RSA_WITH_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 = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + 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; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + case TLS_ECDH_ECDSA_WITH_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 = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + 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; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + case TLS_ECDH_ECDSA_WITH_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 = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + 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; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + #endif /* HAVE_ECC */ #ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8 @@ -708,12 +920,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; break; @@ -726,12 +938,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; break; @@ -744,12 +956,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; ssl->options.usingPSK_cipher = 1; @@ -763,12 +975,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; ssl->options.usingPSK_cipher = 1; @@ -782,12 +994,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; ssl->options.usingPSK_cipher = 1; @@ -801,12 +1013,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; ssl->options.usingPSK_cipher = 1; @@ -820,12 +1032,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; ssl->options.usingPSK_cipher = 1; @@ -839,25 +1051,164 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; ssl->options.usingPSK_cipher = 1; break; #endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER) + #ifdef BUILD_TLS_SHA256_SHA256 + case TLS_SHA256_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + 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 = WC_SHA256_DIGEST_SIZE / 2; + ssl->specs.block_size = 0; + ssl->specs.iv_size = HMAC_NONCE_SZ; + ssl->specs.aead_mac_size = WC_SHA256_DIGEST_SIZE; + + break; + #endif + + #ifdef BUILD_TLS_SHA384_SHA384 + case TLS_SHA384_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + 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 = WC_SHA384_DIGEST_SIZE / 2; + ssl->specs.block_size = 0; + ssl->specs.iv_size = HMAC_NONCE_SZ; + ssl->specs.aead_mac_size = WC_SHA384_DIGEST_SIZE; + + break; + #endif +#endif + default: WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC"); 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 @@ -867,7 +1218,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; @@ -884,7 +1235,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; @@ -901,7 +1252,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; @@ -918,7 +1269,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; @@ -935,7 +1286,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; @@ -952,7 +1303,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; @@ -969,7 +1320,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; @@ -979,6 +1330,23 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif +#ifdef BUILD_TLS_RSA_WITH_NULL_MD5 + case TLS_RSA_WITH_NULL_MD5 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = md5_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_MD5_DIGEST_SIZE; + ssl->specs.pad_size = PAD_MD5; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + break; +#endif + #ifdef BUILD_TLS_RSA_WITH_NULL_SHA case TLS_RSA_WITH_NULL_SHA : ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; @@ -986,7 +1354,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; @@ -1003,7 +1371,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; @@ -1020,7 +1388,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; @@ -1037,7 +1405,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; @@ -1054,7 +1422,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; @@ -1071,7 +1439,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; @@ -1088,12 +1456,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; ssl->options.usingPSK_cipher = 1; @@ -1107,18 +1475,37 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; ssl->options.usingPSK_cipher = 1; break; #endif +#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384 + case TLS_DH_anon_WITH_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 = diffie_hellman_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + 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_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + ssl->options.usingAnon_cipher = 1; + break; +#endif + #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 : ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; @@ -1126,12 +1513,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; ssl->options.usingPSK_cipher = 1; @@ -1145,12 +1532,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; ssl->options.usingPSK_cipher = 1; @@ -1164,7 +1551,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; @@ -1182,7 +1569,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; @@ -1200,7 +1587,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; @@ -1218,7 +1605,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; @@ -1236,7 +1623,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; @@ -1254,7 +1641,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; @@ -1272,7 +1659,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; @@ -1290,7 +1677,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; @@ -1308,7 +1695,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; @@ -1326,7 +1713,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; @@ -1344,7 +1731,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; @@ -1362,7 +1749,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; @@ -1372,6 +1759,23 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif +#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + 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; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 : ssl->specs.bulk_cipher_algorithm = wolfssl_aes; @@ -1379,7 +1783,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; @@ -1396,7 +1800,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; @@ -1413,7 +1817,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; @@ -1430,7 +1834,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; @@ -1439,7 +1843,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; @@ -1447,64 +1851,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 -#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256 - case TLS_RSA_WITH_HC_128_B2B256: - ssl->specs.bulk_cipher_algorithm = wolfssl_hc128; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = blake2b_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = BLAKE2B_256; - 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 - -#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256 - case TLS_RSA_WITH_AES_128_CBC_B2B256: - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = blake2b_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = BLAKE2B_256; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - - break; -#endif - -#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256 - case TLS_RSA_WITH_AES_256_CBC_B2B256: - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = blake2b_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = BLAKE2B_256; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - break; #endif @@ -1515,7 +1868,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; @@ -1532,12 +1885,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; break; @@ -1550,12 +1903,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; break; @@ -1568,12 +1921,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; break; @@ -1586,12 +1939,12 @@ 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; ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AEAD_IMP_IV_SZ; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; break; @@ -1604,7 +1957,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; @@ -1613,7 +1966,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; @@ -1621,7 +1974,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; @@ -1638,7 +1991,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; @@ -1655,7 +2008,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; @@ -1672,7 +2025,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; @@ -1689,7 +2042,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; @@ -1706,7 +2059,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; @@ -1723,7 +2076,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; @@ -1740,7 +2093,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; @@ -1751,6 +2104,36 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif +#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA + case SSL_RSA_WITH_IDEA_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_idea; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + 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 + default: WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs"); return UNSUPPORTED_SUITE; @@ -1761,13 +2144,23 @@ int SetCipherSpecs(WOLFSSL* ssl) if (ssl->version.major == 3 && ssl->version.minor >= 1) { #ifndef NO_TLS ssl->options.tls = 1; + #if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) ssl->hmac = TLS_hmac; - if (ssl->version.minor >= 2) + #endif + if (ssl->version.minor >= 2) { ssl->options.tls1_1 = 1; + if (ssl->version.minor >= 4) + ssl->options.tls1_3 = 1; + } #endif } -#ifdef WOLFSSL_DTLS +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (IsAtLeastTLSv1_3(ssl->version) || ssl->specs.cipher_type != block) + ssl->options.encThenMac = 0; +#endif + +#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.dtls) ssl->hmac = TLS_hmac; #endif @@ -1779,7 +2172,7 @@ int SetCipherSpecs(WOLFSSL* ssl) enum KeyStuff { MASTER_ROUNDS = 3, PREFIX = 3, /* up to three letters for master prefix */ - KEY_PREFIX = 7 /* up to 7 prefix letters for key rounds */ + KEY_PREFIX = 9 /* up to 9 prefix letters for key rounds */ }; @@ -1810,9 +2203,15 @@ static int SetPrefix(byte* sha_input, int idx) case 6: XMEMCPY(sha_input, "GGGGGGG", 7); break; + case 7: + XMEMCPY(sha_input, "HHHHHHHH", 8); + break; + case 8: + XMEMCPY(sha_input, "IIIIIIIII", 9); + break; default: WOLFSSL_MSG("Set Prefix error, bad input"); - return 0; + return 0; } return 1; } @@ -1820,35 +2219,38 @@ static int SetPrefix(byte* sha_input, int idx) static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, - int side, void* heap, int devId) + int side, void* heap, int devId, WC_RNG* rng, int tls13) { + (void)rng; + (void)tls13; + #ifdef BUILD_ARC4 - word32 sz = specs->key_size; if (specs->bulk_cipher_algorithm == wolfssl_rc4) { - if (enc && enc->arc4 == NULL) + word32 sz = specs->key_size; + if (enc && enc->arc4 == NULL) { enc->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->arc4 == NULL) - return MEMORY_E; - if (dec && dec->arc4 == NULL) + if (enc->arc4 == NULL) + return MEMORY_E; + } + if (dec && dec->arc4 == NULL) { dec->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->arc4 == NULL) - return MEMORY_E; -#ifdef HAVE_CAVIUM - if (devId != NO_CAVIUM_DEVICE) { - if (enc) { - if (Arc4InitCavium(enc->arc4, devId) != 0) { - WOLFSSL_MSG("Arc4InitCavium failed in SetKeys"); - return CAVIUM_INIT_E; - } - } - if (dec) { - if (Arc4InitCavium(dec->arc4, devId) != 0) { - WOLFSSL_MSG("Arc4InitCavium failed in SetKeys"); - return CAVIUM_INIT_E; - } + if (dec->arc4 == NULL) + return MEMORY_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); @@ -1866,10 +2268,18 @@ 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 */ + #error AEAD_MAX_IMP_SZ is too small for ChaCha20 + #endif + #if (MAX_WRITE_IV_SZ < 12) /* CHACHA20_IMP_IV_SZ */ + #error MAX_WRITE_IV_SZ is too small for ChaCha20 + #endif + if (specs->bulk_cipher_algorithm == wolfssl_chacha) { int chachaRet; if (enc && enc->chacha == NULL) @@ -1887,14 +2297,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, chachaRet = wc_Chacha_SetKey(enc->chacha, keys->client_write_key, specs->key_size); XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, - AEAD_IMP_IV_SZ); + CHACHA20_IMP_IV_SZ); if (chachaRet != 0) return chachaRet; } if (dec) { chachaRet = wc_Chacha_SetKey(dec->chacha, keys->server_write_key, specs->key_size); XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, - AEAD_IMP_IV_SZ); + CHACHA20_IMP_IV_SZ); if (chachaRet != 0) return chachaRet; } } @@ -1903,14 +2313,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, chachaRet = wc_Chacha_SetKey(enc->chacha, keys->server_write_key, specs->key_size); XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, - AEAD_IMP_IV_SZ); + CHACHA20_IMP_IV_SZ); if (chachaRet != 0) return chachaRet; } if (dec) { chachaRet = wc_Chacha_SetKey(dec->chacha, keys->client_write_key, specs->key_size); XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, - AEAD_IMP_IV_SZ); + CHACHA20_IMP_IV_SZ); if (chachaRet != 0) return chachaRet; } } @@ -1920,9 +2330,15 @@ 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 */ + #if (MAX_WRITE_IV_SZ < 16) /* HC_128_IV_SIZE */ + #error MAX_WRITE_IV_SZ too small for HC128 + #endif + if (specs->bulk_cipher_algorithm == wolfssl_hc128) { int hcRet; if (enc && enc->hc128 == NULL) @@ -1964,9 +2380,14 @@ 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 */ + #error MAX_WRITE_IV_SZ too small for RABBIT + #endif + if (specs->bulk_cipher_algorithm == wolfssl_rabbit) { int rabRet; if (enc && enc->rabbit == NULL) @@ -2008,36 +2429,45 @@ 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 */ + #error MAX_WRITE_IV_SZ too small for 3DES + #endif + 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 HAVE_CAVIUM - if (devId != NO_CAVIUM_DEVICE) { - if (enc) { - if (Des3_InitCavium(enc->des3, devId) != 0) { - WOLFSSL_MSG("Des3_InitCavium failed in SetKeys"); - return CAVIUM_INIT_E; - } - } - if (dec) { - if (Des3_InitCavium(dec->des3, devId) != 0) { - WOLFSSL_MSG("Des3_InitCavium failed in SetKeys"); - return CAVIUM_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, @@ -2067,36 +2497,44 @@ 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 */ + #if (MAX_WRITE_IV_SZ < 16) /* AES_IV_SIZE */ + #error MAX_WRITE_IV_SZ too small for AES + #endif + 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 HAVE_CAVIUM - if (devId != NO_CAVIUM_DEVICE) { - if (enc) { - if (wc_AesInitCavium(enc->aes, devId) != 0) { - WOLFSSL_MSG("AesInitCavium failed in SetKeys"); - return CAVIUM_INIT_E; - } - } - if (dec) { - if (wc_AesInitCavium(dec->aes, devId) != 0) { - WOLFSSL_MSG("AesInitCavium failed in SetKeys"); - return CAVIUM_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, @@ -2130,20 +2568,50 @@ 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 */ + #if (AEAD_MAX_IMP_SZ < 4) /* AESGCM_IMP_IV_SZ */ + #error AEAD_MAX_IMP_SZ too small for AESGCM + #endif + #if (AEAD_MAX_EXP_SZ < 8) /* AESGCM_EXP_IV_SZ */ + #error AEAD_MAX_EXP_SZ too small for AESGCM + #endif + #if (MAX_WRITE_IV_SZ < 4) /* AESGCM_IMP_IV_SZ */ + #error MAX_WRITE_IV_SZ too small for AESGCM + #endif + 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) { @@ -2151,14 +2619,23 @@ 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, - AEAD_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + if (!tls13) { + gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ, + keys->client_write_IV, AESGCM_IMP_IV_SZ, rng); + if (gcmRet != 0) return gcmRet; + } +#endif } 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, - AEAD_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } else { @@ -2167,14 +2644,23 @@ 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, - AEAD_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + if (!tls13) { + gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ, + keys->server_write_IV, AESGCM_IMP_IV_SZ, rng); + if (gcmRet != 0) return gcmRet; + } +#endif } 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, - AEAD_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } if (enc) @@ -2182,41 +2668,107 @@ 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) */ + #if (AEAD_MAX_IMP_SZ < 4) /* AESGCM_IMP_IV_SZ */ + #error AEAD_MAX_IMP_SZ too small for AESCCM + #endif + #if (AEAD_MAX_EXP_SZ < 8) /* AESGCM_EXP_IV_SZ */ + #error AEAD_MAX_EXP_SZ too small for AESCCM + #endif + #if (MAX_WRITE_IV_SZ < 4) /* AESGCM_IMP_IV_SZ */ + #error MAX_WRITE_IV_SZ too small for AESCCM + #endif + if (specs->bulk_cipher_algorithm == wolfssl_aes_ccm) { - 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; + int CcmRet; + + 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) { - wc_AesCcmSetKey(enc->aes, keys->client_write_key, specs->key_size); + CcmRet = wc_AesCcmSetKey(enc->aes, keys->client_write_key, + specs->key_size); + if (CcmRet != 0) { + return CcmRet; + } XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, - AEAD_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); +#if !defined(NO_PUBLIC_CCM_SET_NONCE) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + if (!tls13) { + CcmRet = wc_AesCcmSetNonce(enc->aes, keys->client_write_IV, + AEAD_MAX_IMP_SZ); + if (CcmRet != 0) return CcmRet; + } +#endif } if (dec) { - wc_AesCcmSetKey(dec->aes, keys->server_write_key, specs->key_size); + CcmRet = wc_AesCcmSetKey(dec->aes, keys->server_write_key, + specs->key_size); + if (CcmRet != 0) { + return CcmRet; + } XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, - AEAD_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } else { if (enc) { - wc_AesCcmSetKey(enc->aes, keys->server_write_key, specs->key_size); + CcmRet = wc_AesCcmSetKey(enc->aes, keys->server_write_key, + specs->key_size); + if (CcmRet != 0) { + return CcmRet; + } XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, - AEAD_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); +#if !defined(NO_PUBLIC_CCM_SET_NONCE) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + if (!tls13) { + CcmRet = wc_AesCcmSetNonce(enc->aes, keys->server_write_IV, + AEAD_MAX_IMP_SZ); + if (CcmRet != 0) return CcmRet; + } +#endif } if (dec) { - wc_AesCcmSetKey(dec->aes, keys->client_write_key, specs->key_size); + CcmRet = wc_AesCcmSetKey(dec->aes, keys->client_write_key, + specs->key_size); + if (CcmRet != 0) { + return CcmRet; + } XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, - AEAD_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } if (enc) @@ -2224,9 +2776,14 @@ 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 */ + #if (MAX_WRITE_IV_SZ < 16) /* CAMELLIA_IV_SIZE */ + #error MAX_WRITE_IV_SZ too small for CAMELLIA + #endif + if (specs->bulk_cipher_algorithm == wolfssl_camellia) { int camRet; @@ -2271,10 +2828,133 @@ 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 */ + #if (MAX_WRITE_IV_SZ < 8) /* IDEA_IV_SIZE */ + #error MAX_WRITE_IV_SZ too small for IDEA + #endif + + if (specs->bulk_cipher_algorithm == wolfssl_idea) { + int ideaRet; + + if (enc && enc->idea == NULL) + enc->idea = (Idea*)XMALLOC(sizeof(Idea), heap, DYNAMIC_TYPE_CIPHER); + if (enc && enc->idea == NULL) + return MEMORY_E; + + if (dec && dec->idea == NULL) + dec->idea = (Idea*)XMALLOC(sizeof(Idea), heap, DYNAMIC_TYPE_CIPHER); + if (dec && dec->idea == NULL) + return MEMORY_E; + + if (side == WOLFSSL_CLIENT_END) { + if (enc) { + ideaRet = wc_IdeaSetKey(enc->idea, keys->client_write_key, + specs->key_size, keys->client_write_IV, + IDEA_ENCRYPTION); + if (ideaRet != 0) return ideaRet; + } + if (dec) { + ideaRet = wc_IdeaSetKey(dec->idea, keys->server_write_key, + specs->key_size, keys->server_write_IV, + IDEA_DECRYPTION); + if (ideaRet != 0) return ideaRet; + } + } + else { + if (enc) { + ideaRet = wc_IdeaSetKey(enc->idea, keys->server_write_key, + specs->key_size, keys->server_write_IV, + IDEA_ENCRYPTION); + if (ideaRet != 0) return ideaRet; + } + if (dec) { + ideaRet = wc_IdeaSetKey(dec->idea, keys->client_write_key, + specs->key_size, keys->client_write_IV, + IDEA_DECRYPTION); + if (ideaRet != 0) return ideaRet; + } + } + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif /* HAVE_IDEA */ #ifdef HAVE_NULL_CIPHER if (specs->bulk_cipher_algorithm == wolfssl_cipher_null) { + #ifdef WOLFSSL_TLS13 + if (tls13) { + int hmacRet; + int hashType = WC_HASH_TYPE_NONE; + + switch (specs->mac_algorithm) { + case sha256_mac: + hashType = WC_SHA256; + break; + case sha384_mac: + hashType = WC_SHA384; + break; + default: + break; + } + + if (enc && enc->hmac == NULL) { + enc->hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, + DYNAMIC_TYPE_CIPHER); + if (enc->hmac == NULL) + return MEMORY_E; + } + + if (dec && dec->hmac == NULL) { + dec->hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, + DYNAMIC_TYPE_CIPHER); + if (dec->hmac == NULL) + return MEMORY_E; + } + + if (enc) { + if (wc_HmacInit(enc->hmac, heap, devId) != 0) { + WOLFSSL_MSG("HmacInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (dec) { + if (wc_HmacInit(dec->hmac, heap, devId) != 0) { + WOLFSSL_MSG("HmacInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + + if (side == WOLFSSL_CLIENT_END) { + if (enc) { + hmacRet = wc_HmacSetKey(enc->hmac, hashType, + keys->client_write_key, specs->key_size); + if (hmacRet != 0) return hmacRet; + } + if (dec) { + hmacRet = wc_HmacSetKey(dec->hmac, hashType, + keys->server_write_key, specs->key_size); + if (hmacRet != 0) return hmacRet; + } + } + else { + if (enc) { + hmacRet = wc_HmacSetKey(enc->hmac, hashType, + keys->server_write_key, specs->key_size); + if (hmacRet != 0) return hmacRet; + } + if (dec) { + hmacRet = wc_HmacSetKey(dec->hmac, hashType, + keys->client_write_key, specs->key_size); + if (hmacRet != 0) return hmacRet; + } + } + } + #endif if (enc) enc->setup = 1; if (dec) @@ -2282,10 +2962,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, } #endif - if (enc) - keys->sequence_number = 0; - if (dec) - keys->peer_sequence_number = 0; + if (enc) { + keys->sequence_number_hi = 0; + keys->sequence_number_lo = 0; + } + if (dec) { + keys->peer_sequence_number_hi = 0; + keys->peer_sequence_number_lo = 0; + } (void)side; (void)heap; (void)enc; @@ -2313,6 +2997,7 @@ static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys, if (authentication) authentication->setup = 1; #endif + (void)authentication; (void)heap; (void)keys; (void)specs; @@ -2322,6 +3007,40 @@ static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys, } #endif /* HAVE_ONE_TIME_AUTH */ +#ifdef HAVE_SECURE_RENEGOTIATION +/* function name is for cache_status++ + * This function was added because of error incrementing enum type when + * compiling with a C++ compiler. + */ +static void CacheStatusPP(SecureRenegotiation* cache) +{ + switch (cache->cache_status) { + case SCR_CACHE_NULL: + cache->cache_status = SCR_CACHE_NEEDED; + break; + + case SCR_CACHE_NEEDED: + cache->cache_status = SCR_CACHE_COPY; + break; + + case SCR_CACHE_COPY: + cache->cache_status = SCR_CACHE_PARTIAL; + break; + + case SCR_CACHE_PARTIAL: + cache->cache_status = SCR_CACHE_COMPLETE; + break; + + case SCR_CACHE_COMPLETE: + WOLFSSL_MSG("SCR Cache state Complete"); + break; + + default: + WOLFSSL_MSG("Unknown cache state!!"); + } +} +#endif /* HAVE_SECURE_RENEGOTIATION */ + /* Set wc_encrypt/wc_decrypt or both sides of key setup * note: use wc_encrypt to avoid shadowing global encrypt @@ -2329,17 +3048,13 @@ static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys, */ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) { - int devId = NO_CAVIUM_DEVICE, ret, copy = 0; + int ret, copy = 0; Ciphers* wc_encrypt = NULL; Ciphers* wc_decrypt = NULL; Keys* keys = &ssl->keys; (void)copy; -#ifdef HAVE_CAVIUM - devId = ssl->devId; -#endif - #ifdef HAVE_SECURE_RENEGOTIATION if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status) { keys = &ssl->secure_renegotiation->tmp_keys; @@ -2349,14 +3064,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, ssl->specs.key_size); + } + else { + WOLFSSL_BUFFER(ssl->keys.server_write_key, ssl->specs.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, ssl->specs.key_size); + } + else { + WOLFSSL_BUFFER(ssl->keys.client_write_key, ssl->specs.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, ssl->specs.key_size); + } + else { + WOLFSSL_BUFFER(ssl->keys.server_write_key, ssl->specs.key_size); + } + WOLFSSL_MSG("Provisioning DECRYPT key"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_BUFFER(ssl->keys.server_write_key, ssl->specs.key_size); + } + else { + WOLFSSL_BUFFER(ssl->keys.client_write_key, ssl->specs.key_size); + } +#endif wc_encrypt = &ssl->encrypt; wc_decrypt = &ssl->decrypt; break; @@ -2367,14 +3116,21 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) #ifdef HAVE_ONE_TIME_AUTH if (!ssl->auth.setup && ssl->specs.bulk_cipher_algorithm == wolfssl_chacha){ - ret = SetAuthKeys(&ssl->auth, keys, &ssl->specs, ssl->heap, devId); + ret = SetAuthKeys(&ssl->auth, keys, &ssl->specs, ssl->heap, ssl->devId); if (ret != 0) return ret; } #endif +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + /* check if keys for TSIP has been created */ + if (tsip_useable(ssl) == 1) + ret = 0; + else +#endif ret = SetKeys(wc_encrypt, wc_decrypt, keys, &ssl->specs, ssl->options.side, - ssl->heap, devId); + ssl->heap, ssl->devId, ssl->rng, ssl->options.tls1_3); #ifdef HAVE_SECURE_RENEGOTIATION if (copy) { @@ -2386,55 +3142,61 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) clientCopy = 1; if (clientCopy) { + #ifndef WOLFSSL_AEAD_ONLY XMEMCPY(ssl->keys.client_write_MAC_secret, - keys->client_write_MAC_secret, MAX_DIGEST_SIZE); + keys->client_write_MAC_secret, WC_MAX_DIGEST_SIZE); + #endif XMEMCPY(ssl->keys.client_write_key, keys->client_write_key, AES_256_KEY_SIZE); XMEMCPY(ssl->keys.client_write_IV, - keys->client_write_IV, AES_IV_SIZE); + keys->client_write_IV, MAX_WRITE_IV_SZ); } else { + #ifndef WOLFSSL_AEAD_ONLY XMEMCPY(ssl->keys.server_write_MAC_secret, - keys->server_write_MAC_secret, MAX_DIGEST_SIZE); + keys->server_write_MAC_secret, WC_MAX_DIGEST_SIZE); + #endif XMEMCPY(ssl->keys.server_write_key, keys->server_write_key, AES_256_KEY_SIZE); XMEMCPY(ssl->keys.server_write_IV, - keys->server_write_IV, AES_IV_SIZE); + keys->server_write_IV, MAX_WRITE_IV_SZ); } if (wc_encrypt) { - ssl->keys.sequence_number = keys->sequence_number; + ssl->keys.sequence_number_hi = keys->sequence_number_hi; + ssl->keys.sequence_number_lo = keys->sequence_number_lo; #ifdef HAVE_AEAD if (ssl->specs.cipher_type == aead) { /* Initialize the AES-GCM/CCM explicit IV to a zero. */ XMEMCPY(ssl->keys.aead_exp_IV, keys->aead_exp_IV, - AEAD_EXP_IV_SZ); + AEAD_MAX_EXP_SZ); /* Initialize encrypt implicit IV by encrypt side */ if (ssl->options.side == WOLFSSL_CLIENT_END) { XMEMCPY(ssl->keys.aead_enc_imp_IV, - keys->client_write_IV, AEAD_IMP_IV_SZ); + keys->client_write_IV, AEAD_MAX_IMP_SZ); } else { XMEMCPY(ssl->keys.aead_enc_imp_IV, - keys->server_write_IV, AEAD_IMP_IV_SZ); + keys->server_write_IV, AEAD_MAX_IMP_SZ); } } #endif } if (wc_decrypt) { - ssl->keys.peer_sequence_number = keys->peer_sequence_number; + ssl->keys.peer_sequence_number_hi = keys->peer_sequence_number_hi; + ssl->keys.peer_sequence_number_lo = keys->peer_sequence_number_lo; #ifdef HAVE_AEAD if (ssl->specs.cipher_type == aead) { /* Initialize decrypt implicit IV by decrypt side */ if (ssl->options.side == WOLFSSL_SERVER_END) { XMEMCPY(ssl->keys.aead_dec_imp_IV, - keys->client_write_IV, AEAD_IMP_IV_SZ); + keys->client_write_IV, AEAD_MAX_IMP_SZ); } else { XMEMCPY(ssl->keys.aead_dec_imp_IV, - keys->server_write_IV, AEAD_IMP_IV_SZ); + keys->server_write_IV, AEAD_MAX_IMP_SZ); } } #endif } - ssl->secure_renegotiation->cache_status++; + CacheStatusPP(ssl->secure_renegotiation); } #endif /* HAVE_SECURE_RENEGOTIATION */ @@ -2443,7 +3205,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; @@ -2452,32 +3214,78 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData) if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status == SCR_CACHE_NEEDED) { keys = &ssl->secure_renegotiation->tmp_keys; - ssl->secure_renegotiation->cache_status++; + CacheStatusPP(ssl->secure_renegotiation); } #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; + #ifndef WOLFSSL_AEAD_ONLY + XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); + XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); + #endif + 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) { + #ifndef WOLFSSL_AEAD_ONLY + XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); + #endif + i += sz; + } + if (side & PROVISION_SERVER) { + #ifndef WOLFSSL_AEAD_ONLY + XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); + #endif + 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) { /* Initialize the AES-GCM/CCM explicit IV to a zero. */ - XMEMSET(keys->aead_exp_IV, 0, AEAD_EXP_IV_SZ); + XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ); } #endif @@ -2487,40 +3295,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); @@ -2529,15 +3337,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); @@ -2555,18 +3363,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 @@ -2596,6 +3411,10 @@ static int CleanPreMaster(WOLFSSL* ssl) for (i = 0; i < sz; i++) ssl->arrays->preMasterSecret[i] = 0; + XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET); + ssl->arrays->preMasterSecret = NULL; + ssl->arrays->preMasterSz = 0; + return 0; } @@ -2611,14 +3430,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 @@ -2630,17 +3449,17 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) printf("\n"); } #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); @@ -2648,15 +3467,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); @@ -2677,14 +3496,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 @@ -2708,7 +3535,7 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - + if (ret == 0) ret = CleanPreMaster(ssl); else @@ -2722,14 +3549,59 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) /* Master wrapper, doesn't use SSL stack space in TLS mode */ int MakeMasterSecret(WOLFSSL* ssl) { -#ifdef NO_OLD_TLS - return MakeTlsMasterSecret(ssl); -#elif !defined(NO_TLS) - if (ssl->options.tls) return MakeTlsMasterSecret(ssl); + /* append secret to premaster : premaster | SerSi | CliSi */ +#ifdef HAVE_QSH + word32 offset = 0; + + if (ssl->peerQSHKeyPresent) { + offset += ssl->arrays->preMasterSz; + ssl->arrays->preMasterSz += ssl->QSH_secret->CliSi->length + + ssl->QSH_secret->SerSi->length; + /* test and set flag if QSH has been used */ + if (ssl->QSH_secret->CliSi->length > 0 || + ssl->QSH_secret->SerSi->length > 0) + ssl->isQSH = 1; + + /* append secrets to the premaster */ + if (ssl->QSH_secret->SerSi != NULL) { + XMEMCPY(ssl->arrays->preMasterSecret + offset, + ssl->QSH_secret->SerSi->buffer, ssl->QSH_secret->SerSi->length); + } + offset += ssl->QSH_secret->SerSi->length; + if (ssl->QSH_secret->CliSi != NULL) { + XMEMCPY(ssl->arrays->preMasterSecret + offset, + ssl->QSH_secret->CliSi->buffer, ssl->QSH_secret->CliSi->length); + } + + /* show secret SerSi and CliSi */ + #ifdef SHOW_SECRETS + { + word32 j; + printf("QSH generated secret material\n"); + printf("SerSi : "); + for (j = 0; j < ssl->QSH_secret->SerSi->length; j++) { + printf("%02x", ssl->QSH_secret->SerSi->buffer[j]); + } + printf("\n"); + printf("CliSi : "); + for (j = 0; j < ssl->QSH_secret->CliSi->length; j++) { + printf("%02x", ssl->QSH_secret->CliSi->buffer[j]); + } + printf("\n"); + } + #endif + } #endif #ifndef NO_OLD_TLS + if (ssl->options.tls) return MakeTlsMasterSecret(ssl); return MakeSslMasterSecret(ssl); +#elif !defined(WOLFSSL_NO_TLS12) + return MakeTlsMasterSecret(ssl); +#else + (void)ssl; + return 0; #endif } +#endif /* WOLFCRYPT_ONLY */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/ocsp.c b/FreeRTOS-Plus/Source/WolfSSL/src/ocsp.c index 1794d6317..b5a27197e 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/src/ocsp.c +++ b/FreeRTOS-Plus/Source/WolfSSL/src/ocsp.c @@ -1,8 +1,8 @@ /* ocsp.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Name change compatibility layer no longer needs to be included here */ #ifdef HAVE_CONFIG_H @@ -27,73 +28,91 @@ #include +#ifndef WOLFCRYPT_ONLY #ifdef HAVE_OCSP #include #include #include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm) { WOLFSSL_ENTER("InitOCSP"); - XMEMSET(ocsp, 0, sizeof(*ocsp)); - ocsp->cm = cm; - if (InitMutex(&ocsp->ocspLock) != 0) + + ForceZero(ocsp, sizeof(WOLFSSL_OCSP)); + + if (wc_InitMutex(&ocsp->ocspLock) != 0) return BAD_MUTEX_E; - return 0; -} - - -static int InitOCSP_Entry(OCSP_Entry* ocspe, DecodedCert* cert) -{ - WOLFSSL_ENTER("InitOCSP_Entry"); - - XMEMSET(ocspe, 0, sizeof(*ocspe)); - XMEMCPY(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE); - XMEMCPY(ocspe->issuerKeyHash, cert->issuerKeyHash, SHA_DIGEST_SIZE); + ocsp->cm = cm; return 0; } -static void FreeOCSP_Entry(OCSP_Entry* ocspe) +static int InitOcspEntry(OcspEntry* entry, OcspRequest* request) { - CertStatus* tmp = ocspe->status; + WOLFSSL_ENTER("InitOcspEntry"); - WOLFSSL_ENTER("FreeOCSP_Entry"); + ForceZero(entry, sizeof(OcspEntry)); - while (tmp) { - CertStatus* next = tmp->next; - XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_STATUS); - tmp = next; + XMEMCPY(entry->issuerHash, request->issuerHash, OCSP_DIGEST_SIZE); + XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE); + + return 0; +} + + +static void FreeOcspEntry(OcspEntry* entry, void* heap) +{ + CertStatus *status, *next; + + WOLFSSL_ENTER("FreeOcspEntry"); + + for (status = entry->status; status; status = next) { + next = status->next; + + if (status->rawOcspResponse) + XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS); + + XFREE(status, heap, DYNAMIC_TYPE_OCSP_STATUS); } + + (void)heap; } void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic) { - OCSP_Entry* tmp = ocsp->ocspList; + OcspEntry *entry, *next; WOLFSSL_ENTER("FreeOCSP"); - while (tmp) { - OCSP_Entry* next = tmp->next; - FreeOCSP_Entry(tmp); - XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_ENTRY); - tmp = next; + for (entry = ocsp->ocspList; entry; entry = next) { + next = entry->next; + FreeOcspEntry(entry, ocsp->cm->heap); + XFREE(entry, ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY); } - FreeMutex(&ocsp->ocspLock); + wc_FreeMutex(&ocsp->ocspLock); + if (dynamic) - XFREE(ocsp, NULL, DYNAMIC_TYPE_OCSP); + XFREE(ocsp, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); + } -static int xstat2err(int stat) +static int xstat2err(int st) { - switch (stat) { + switch (st) { case CERT_GOOD: return 0; case CERT_REVOKED: @@ -103,86 +122,323 @@ static int xstat2err(int stat) } } - -int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert) +int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer, WOLFSSL* ssl) { - byte* ocspReqBuf = NULL; - int ocspReqSz = 2048; - byte* ocspRespBuf = NULL; - int result = -1; - OCSP_Entry* ocspe; - CertStatus* certStatus = NULL; - const char *url; - int urlSz; + int ret = OCSP_LOOKUP_FAIL; + #ifdef WOLFSSL_SMALL_STACK - CertStatus* newStatus; OcspRequest* ocspRequest; - OcspResponse* ocspResponse; #else - CertStatus newStatus[1]; OcspRequest ocspRequest[1]; - OcspResponse ocspResponse[1]; #endif WOLFSSL_ENTER("CheckCertOCSP"); - if (LockMutex(&ocsp->ocspLock) != 0) { + +#ifdef WOLFSSL_SMALL_STACK + ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (ocspRequest == NULL) { + WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); + return MEMORY_E; + } +#endif + + if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce, + ocsp->cm->heap) == 0) { + ocspRequest->ssl = ssl; + ret = CheckOcspRequest(ocsp, ocspRequest, responseBuffer); + + FreeOcspRequest(ocspRequest); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + 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) +{ + WOLFSSL_ENTER("GetOcspEntry"); + + *entry = NULL; + + if (wc_LockMutex(&ocsp->ocspLock) != 0) { WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); return BAD_MUTEX_E; } - ocspe = ocsp->ocspList; - while (ocspe) { - if (XMEMCMP(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0 - && XMEMCMP(ocspe->issuerKeyHash, cert->issuerKeyHash, - SHA_DIGEST_SIZE) == 0) + for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next) + if (XMEMCMP((*entry)->issuerHash, request->issuerHash, + OCSP_DIGEST_SIZE) == 0 + && XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash, + OCSP_DIGEST_SIZE) == 0) break; - else - ocspe = ocspe->next; + + if (*entry == NULL) { + *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry), + ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY); + if (*entry) { + InitOcspEntry(*entry, request); + (*entry)->next = ocsp->ocspList; + ocsp->ocspList = *entry; + } } - if (ocspe == NULL) { - ocspe = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry), - NULL, DYNAMIC_TYPE_OCSP_ENTRY); - if (ocspe != NULL) { - InitOCSP_Entry(ocspe, cert); - ocspe->next = ocsp->ocspList; - ocsp->ocspList = ocspe; + wc_UnLockMutex(&ocsp->ocspLock); + + return *entry ? 0 : MEMORY_ERROR; +} + + +/* Mallocs responseBuffer->buffer and is up to caller to free on success + * + * Returns OCSP status + */ +static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, + OcspEntry* entry, CertStatus** status, buffer* responseBuffer) +{ + int ret = OCSP_INVALID_STATUS; + + WOLFSSL_ENTER("GetOcspStatus"); + + *status = NULL; + + if (wc_LockMutex(&ocsp->ocspLock) != 0) { + WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); + return BAD_MUTEX_E; + } + + for (*status = entry->status; *status; *status = (*status)->next) + if ((*status)->serialSz == request->serialSz + && !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz)) + break; + + if (responseBuffer && *status && !(*status)->rawOcspResponse) { + /* force fetching again */ + ret = OCSP_INVALID_STATUS; + } + else if (*status) { +#ifndef NO_ASN_TIME + if (XVALIDATE_DATE((*status)->thisDate, + (*status)->thisDateFormat, BEFORE) + && ((*status)->nextDate[0] != 0) + && XVALIDATE_DATE((*status)->nextDate, + (*status)->nextDateFormat, AFTER)) +#endif + { + ret = xstat2err((*status)->status); + + if (responseBuffer) { + responseBuffer->buffer = (byte*)XMALLOC( + (*status)->rawOcspResponseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (responseBuffer->buffer) { + responseBuffer->length = (*status)->rawOcspResponseSz; + XMEMCPY(responseBuffer->buffer, + (*status)->rawOcspResponse, + (*status)->rawOcspResponseSz); + } + } } - else { - UnLockMutex(&ocsp->ocspLock); - WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); - return MEMORY_ERROR; + } + + wc_UnLockMutex(&ocsp->ocspLock); + + 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. + */ +WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz, + WOLFSSL_BUFFER_INFO *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) { + ocsp->error = ret; + WOLFSSL_LEAVE("OcspResponseDecode failed", ocsp->error); + 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 */ + newStatus->next = status->next; + XMEMCPY(status, newStatus, sizeof(CertStatus)); + } else { - certStatus = ocspe->status; - while (certStatus) { - if (certStatus->serialSz == cert->serialSz && - XMEMCMP(certStatus->serial, cert->serial, cert->serialSz) == 0) - break; - else - certStatus = certStatus->next; + /* 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 (certStatus != NULL) { - if (!ValidateDate(certStatus->thisDate, - certStatus->thisDateFormat, BEFORE) || - (certStatus->nextDate[0] == 0) || - !ValidateDate(certStatus->nextDate, - certStatus->nextDateFormat, AFTER)) { - WOLFSSL_MSG("\tinvalid status date, looking up cert"); - } - else { - result = xstat2err(certStatus->status); - UnLockMutex(&ocsp->ocspLock); - WOLFSSL_LEAVE("CheckCertOCSP", result); - return result; + 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); } } - UnLockMutex(&ocsp->ocspLock); + 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) +{ + OcspEntry* entry = NULL; + CertStatus* status = NULL; + byte* request = NULL; + int requestSz = 2048; + int responseSz = 0; + byte* response = NULL; + const char* url = NULL; + int urlSz = 0; + int ret = -1; + WOLFSSL* ssl; + void* ioCtx; + + WOLFSSL_ENTER("CheckOcspRequest"); + + if (ocsp == NULL || ocspRequest == NULL) + return BAD_FUNC_ARG; + + if (responseBuffer) { + responseBuffer->buffer = NULL; + responseBuffer->length = 0; + } + + ret = GetOcspEntry(ocsp, ocspRequest, &entry); + if (ret != 0) + return ret; + + ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer); + 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(OPENSSL_ALL) || 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 = CheckOcspResponse(ocsp, response, ret, responseBuffer, status, + entry, NULL); + if (response != NULL) + XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); + return ret; + } + WOLFSSL_LEAVE("CheckOcspRequest", ocsp->error); + return OCSP_LOOKUP_FAIL; + } +#endif if (ocsp->cm->ocspUseOverrideURL) { url = ocsp->cm->ocspOverrideURL; @@ -191,104 +447,645 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert) else return OCSP_NEED_URL; } - else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) { - url = (const char *)cert->extAuthInfo; - urlSz = cert->extAuthInfoSz; + else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) { + url = (const char *)ocspRequest->url; + urlSz = ocspRequest->urlSz; } else { /* cert doesn't have extAuthInfo, assuming CERT_GOOD */ return 0; } - ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER); - if (ocspReqBuf == NULL) { + request = (byte*)XMALLOC(requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); + if (request == NULL) { WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); + if (responseBuffer) { + XFREE(responseBuffer->buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + responseBuffer->buffer = NULL; + } return MEMORY_ERROR; } -#ifdef WOLFSSL_SMALL_STACK - newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (newStatus == NULL || ocspRequest == NULL || ocspResponse == NULL) { - if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ocspRequest) XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); - return MEMORY_E; + requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); + if (requestSz > 0 && ocsp->cm->ocspIOCb) { + responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz, + request, requestSz, &response); } -#endif - - InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce, - ocspReqBuf, ocspReqSz); - ocspReqSz = EncodeOcspRequest(ocspRequest); - - if (ocsp->cm->ocspIOCb) - result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, - ocspReqBuf, ocspReqSz, &ocspRespBuf); - - if (result >= 0 && ocspRespBuf) { - XMEMSET(newStatus, 0, sizeof(CertStatus)); - - InitOcspResponse(ocspResponse, newStatus, ocspRespBuf, result); - OcspResponseDecode(ocspResponse); - - if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) - result = OCSP_LOOKUP_FAIL; - else { - if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) { - result = xstat2err(ocspResponse->status->status); - - if (LockMutex(&ocsp->ocspLock) != 0) - result = BAD_MUTEX_E; - else { - if (certStatus != NULL) - /* Replace existing certificate entry with updated */ - XMEMCPY(certStatus, newStatus, sizeof(CertStatus)); - else { - /* Save new certificate entry */ - certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), - NULL, DYNAMIC_TYPE_OCSP_STATUS); - if (certStatus != NULL) { - XMEMCPY(certStatus, newStatus, sizeof(CertStatus)); - certStatus->next = ocspe->status; - ocspe->status = certStatus; - ocspe->totalStatus++; - } - } - - UnLockMutex(&ocsp->ocspLock); - } - } - else - result = OCSP_LOOKUP_FAIL; - } + if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) { + ret = OCSP_WANT_READ; } - else - result = OCSP_LOOKUP_FAIL; - XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER); + XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); -#ifdef WOLFSSL_SMALL_STACK - XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + if (responseSz >= 0 && response) { + ret = CheckOcspResponse(ocsp, response, responseSz, responseBuffer, status, + entry, ocspRequest); + } - if (ocspRespBuf != NULL && ocsp->cm->ocspRespFreeCb) - ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, ocspRespBuf); + if (response != NULL && ocsp->cm->ocspRespFreeCb) + ocsp->cm->ocspRespFreeCb(ioCtx, response); - WOLFSSL_LEAVE("CheckCertOCSP", result); - return result; + /* Keep responseBuffer in the case of getting to response check. Caller + * should free responseBuffer after checking OCSP return value in "ret" */ + WOLFSSL_LEAVE("CheckOcspRequest", ret); + return ret; } +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_APACHE_HTTPD) + +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 = &bs->status->thisDateParsed; + if (nextupd != NULL) + *nextupd = &bs->status->nextDateParsed; + + /* 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; + +#ifdef OPENSSL_EXTRA + if (bs->verifyError != OCSP_VERIFY_ERROR_NONE) + return WOLFSSL_FAILURE; +#endif + + 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 == WOLFSSL_BIO_MEMORY) { + len = wolfSSL_BIO_get_mem_data(bio, &data); + if (len <= 0 || data == NULL) { + return NULL; + } + } +#ifndef NO_FILESYSTEM + else if (bio->type == WOLFSSL_BIO_FILE) { + long fcur; + long flen; + + if (bio->ptr == NULL) + return NULL; + + fcur = XFTELL((XFILE)bio->ptr); + if (fcur < 0) + return NULL; + if(XFSEEK((XFILE)bio->ptr, 0, SEEK_END) != 0) + return NULL; + flen = XFTELL((XFILE)bio->ptr); + if (flen < 0) + return NULL; + if (XFSEEK((XFILE)bio->ptr, fcur, SEEK_SET) != 0) + return NULL; + + /* check calculated length */ + fcur = flen - fcur; + if (fcur > MAX_WOLFSSL_FILE_SIZE || fcur <= 0) + return NULL; + + data = (byte*)XMALLOC(fcur, 0, DYNAMIC_TYPE_TMP_BUFFER); + if (data == NULL) + return NULL; + dataAlloced = 1; + + len = wolfSSL_BIO_read(bio, (char *)data, (int)flen); + } +#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) +{ + int 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; +} + +WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_CERTID_dup(WOLFSSL_OCSP_CERTID* id) +{ + WOLFSSL_OCSP_CERTID* certId; + + if (id == NULL) { + return NULL; + } + + certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), + id->heap, DYNAMIC_TYPE_OPENSSL); + if (certId) { + XMEMCPY(certId, id, sizeof(WOLFSSL_OCSP_CERTID)); + } + return certId; +} +#endif + +#if defined(OPENSSL_ALL) || defined(APACHE_HTTPD) +int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out, + WOLFSSL_OCSP_REQUEST *req) +{ + int size = -1; + unsigned char* data = NULL; + + WOLFSSL_ENTER("wolfSSL_i2d_OCSP_REQUEST_bio"); + if (out == NULL || req == NULL) + return WOLFSSL_FAILURE; + + size = wolfSSL_i2d_OCSP_REQUEST(req, NULL); + if (size > 0) { + data = (unsigned char*) XMALLOC(size, out->heap, + DYNAMIC_TYPE_TMP_BUFFER); + } + + if (data != NULL) { + size = wolfSSL_i2d_OCSP_REQUEST(req, &data); + } + + if (size <= 0) { + XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + if (wolfSSL_BIO_write(out, data, size) == (int)size) { + XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_SUCCESS; + } + + XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; +} +#endif /* OPENSSL_ALL || APACHE_HTTPD */ + +#ifdef OPENSSL_EXTRA +#ifndef NO_WOLFSSL_STUB +int wolfSSL_OCSP_REQUEST_add_ext(OcspRequest* req, WOLFSSL_X509_EXTENSION* ext, + int idx) +{ + WOLFSSL_STUB("wolfSSL_OCSP_REQUEST_add_ext"); + (void)req; + (void)ext; + (void)idx; + return WOLFSSL_FATAL_ERROR; +} +#endif + +#ifndef NO_WOLFSSL_STUB +OcspResponse* wolfSSL_OCSP_response_create(int status, + WOLFSSL_OCSP_BASICRESP* bs) +{ + WOLFSSL_STUB("wolfSSL_OCSP_response_create"); + (void)status; + (void)bs; + return NULL; +} +#endif + +#ifndef NO_WOLFSSL_STUB +const char* wolfSSL_OCSP_crl_reason_str(long s) +{ + WOLFSSL_STUB("wolfSSL_OCSP_crl_reason_str"); + (void)s; + return NULL; +} +#endif + +/* Returns elements of an OCSP_CERTID struct. Currently only supports + * returning the serial number, and returns an error if user requests + * any of name, pmd, and/or keyHash. + * Return 1 on success, 0 on failure */ +int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name, + WOLFSSL_ASN1_OBJECT **pmd, WOLFSSL_ASN1_STRING **keyHash, + WOLFSSL_ASN1_INTEGER **serial, WOLFSSL_OCSP_CERTID *cid) +{ + int i = 0; + WOLFSSL_ASN1_INTEGER* ser; + + WOLFSSL_ENTER("wolfSSL_OCSP_id_get0_info"); + + if (cid == NULL) + return 0; + + /* build up ASN1_INTEGER for serial */ + if (serial != NULL) { + ser = wolfSSL_ASN1_INTEGER_new(); + if (ser == NULL) + return 0; + + if (cid->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) { + /* allocate data buffer, +2 for type and length */ + ser->data = (unsigned char*)XMALLOC(cid->serialSz + 2, NULL, + DYNAMIC_TYPE_OPENSSL); + if (ser->data == NULL) { + wolfSSL_ASN1_INTEGER_free(ser); + return 0; + } + ser->dataMax = cid->serialSz + 2; + ser->isDynamic = 1; + } else { + /* Use array instead of dynamic memory */ + ser->data = ser->intData; + ser->dataMax = WOLFSSL_ASN1_INTEGER_MAX; + } + + #ifdef WOLFSSL_QT + /* Serial number starts at 0 index of ser->data */ + XMEMCPY(&ser->data[i], cid->serial, cid->serialSz); + ser->length = cid->serialSz; + #else + ser->data[i++] = ASN_INTEGER; + i += SetLength(cid->serialSz, ser->data + i); + XMEMCPY(&ser->data[i], cid->serial, cid->serialSz); + #endif + + cid->serialInt = ser; + *serial = cid->serialInt; + } + + /* Not needed for Apache, return error if user is requesting */ + if (name != NULL || pmd != NULL || keyHash != NULL) { + if (name != NULL) + *name = NULL; + + if (pmd != NULL) + *pmd = NULL; + + if (keyHash != NULL) + *keyHash = NULL; + return 0; + } + + return 1; +} + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_OCSP_request_add1_nonce(OcspRequest* req, unsigned char* val, + int sz) +{ + WOLFSSL_STUB("wolfSSL_OCSP_request_add1_nonce"); + (void)req; + (void)val; + (void)sz; + return WOLFSSL_FATAL_ERROR; +} +#endif + +/* Returns result of OCSP nonce comparison. Return values: + * 1 - nonces are both present and equal + * 2 - both nonces are absent + * 3 - nonce only present in response + * -1 - nonce only present in request + * 0 - both nonces present and equal + */ +int wolfSSL_OCSP_check_nonce(OcspRequest* req, WOLFSSL_OCSP_BASICRESP* bs) +{ + byte* reqNonce = NULL; + byte* rspNonce = NULL; + int reqNonceSz = 0; + int rspNonceSz = 0; + + WOLFSSL_ENTER("wolfSSL_OCSP_check_nonce"); + + if (req != NULL) { + reqNonce = req->nonce; + reqNonceSz = req->nonceSz; + } + + if (bs != NULL) { + rspNonce = bs->nonce; + rspNonceSz = bs->nonceSz; + } + + /* nonce absent in both req and rsp */ + if (reqNonce == NULL && rspNonce == NULL) + return 2; + + /* nonce present in rsp only */ + if (reqNonce == NULL && rspNonce != NULL) + return 3; + + /* nonce present in req only */ + if (reqNonce != NULL && rspNonce == NULL) + return -1; + + /* nonces are present and equal, return 1. Extra NULL check for fixing + scan-build warning. */ + if (reqNonceSz == rspNonceSz && reqNonce && rspNonce) { + if (XMEMCMP(reqNonce, rspNonce, reqNonceSz) == 0) + return 1; + } + + /* nonces are present but not equal */ + return 0; +} +#endif /* OPENSSL_EXTRA */ #else /* HAVE_OCSP */ @@ -300,4 +1097,4 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert) #endif /* HAVE_OCSP */ - +#endif /* WOLFCRYPT_ONLY */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/sniffer.c b/FreeRTOS-Plus/Source/WolfSSL/src/sniffer.c index b961f7bd7..908714818 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/src/sniffer.c +++ b/FreeRTOS-Plus/Source/WolfSSL/src/sniffer.c @@ -1,8 +1,8 @@ /* sniffer.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,15 +16,17 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include +#ifndef WOLFCRYPT_ONLY #ifdef WOLFSSL_SNIFFER #include @@ -32,6 +34,8 @@ #ifndef _WIN32 #include +#else + #include #endif #ifdef _WIN32 @@ -48,19 +52,20 @@ #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif +#ifdef WOLF_CRYPTO_CB + #include + #ifdef HAVE_INTEL_QA_SYNC + #include + #endif + #ifdef HAVE_CAVIUM_OCTEON_SYNC + #include + #endif +#endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - -static INLINE word32 min(word32 a, word32 b) -{ - return a > b ? b : a; -} - -#endif /* WOLFSSL_HAVE_MIN */ #ifndef WOLFSSL_SNIFFER_TIMEOUT #define WOLFSSL_SNIFFER_TIMEOUT 900 @@ -75,10 +80,13 @@ enum { ETHER_IF_ADDR_LEN = 6, /* ethernet interface address length */ LOCAL_IF_ADDR_LEN = 4, /* localhost interface address length, !windows */ TCP_PROTO = 6, /* TCP_PROTOCOL */ - IP_HDR_SZ = 20, /* IP header legnth, min */ - TCP_HDR_SZ = 20, /* TCP header legnth, min */ + IP_HDR_SZ = 20, /* IPv4 header length, min */ + IP6_HDR_SZ = 40, /* IPv6 header length, min */ + TCP_HDR_SZ = 20, /* TCP header length, min */ IPV4 = 4, /* IP version 4 */ + IPV6 = 6, /* IP version 6 */ TCP_PROTOCOL = 6, /* TCP Protocol id */ + NO_NEXT_HEADER = 59, /* IPv6 no headers follow */ TRACE_MSG_SZ = 80, /* Trace Message buffer size */ HASH_SIZE = 499, /* Session Hash Table Rows */ PSEUDO_HDR_SZ = 12, /* TCP Pseudo Header size in bytes */ @@ -87,6 +95,7 @@ enum { EXT_TYPE_SZ = 2, /* Extension length */ MAX_INPUT_SZ = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA + MTU_EXTRA, /* Max input sz of reassembly */ + EXT_MASTER_SECRET = 0x17, /* Extended Master Secret Extension ID */ TICKET_EXT_ID = 0x23 /* Session Ticket Extension ID */ }; @@ -128,8 +137,8 @@ BOOL APIENTRY DllMain( HMODULE hModule, #endif /* _WIN32 */ -static int TraceOn = 0; /* Trace is off by default */ -static FILE* TraceFile = 0; +static WOLFSSL_GLOBAL int TraceOn = 0; /* Trace is off by default */ +static WOLFSSL_GLOBAL FILE* TraceFile = 0; /* windows uses .rc table for this */ @@ -199,21 +208,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", @@ -239,14 +248,42 @@ static const char* const msgTable[] = "Decrypt Keys Not Set Up", "Late Key Load Error", "Got Certificate Status msg", - "RSA Key Missing Error" + "RSA Key Missing Error", + "Secure Renegotiation Not Supported", + + /* 76 */ + "Get Session Stats Failure", + "Reassembly Buffer Size Exceeded", + "Dropping Lost Fragment", + "Dropping Partial Record", + "Clear ACK Fault", + + /* 81 */ + "Bad Decrypt Size", + "Extended Master Secret Hash Error", + "Handshake Message Split Across TLS Records", + "ECC Private Decode Error", + "ECC Public Decode Error", + + /* 86 */ + "Watch callback not set", + "Watch hash failed", + "Watch callback failed", + "Bad Certificate Message", + "Store data callback not set", + + /* 91 */ + "No data destination Error", + "Store data callback failed", + "Loading chain input" }; /* *nix version uses table above */ static void GetError(int idx, char* str) { - XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN); + XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN-1); + str[MAX_ERROR_LEN-1] = '\0'; } @@ -287,15 +324,24 @@ typedef struct NamedKey { #endif +typedef struct IpAddrInfo { + int version; + union { + word32 ip4; + byte ip6[16]; + }; +} IpAddrInfo; + + /* Sniffer Server holds info for each server/port monitored */ typedef struct SnifferServer { SSL_CTX* ctx; /* SSL context */ char address[MAX_SERVER_ADDRESS]; /* passed in server address */ - word32 server; /* netowrk order address */ + IpAddrInfo server; /* network order address */ int port; /* server port */ #ifdef HAVE_SNI NamedKey* namedKeys; /* mapping of names and keys */ - wolfSSL_Mutex namedKeysMutex; /* mutex for namedKey list */ + wolfSSL_Mutex namedKeysMutex; /* mutex for namedKey list */ #endif struct SnifferServer* next; /* for list */ } SnifferServer; @@ -311,10 +357,17 @@ typedef struct Flags { byte clientHello; /* processed client hello yet, for SSLv2 */ byte finCount; /* get both FINs before removing */ byte fatalError; /* fatal error state */ + byte cliAckFault; /* client acked unseen data from server */ + byte srvAckFault; /* server acked unseen data from client */ + byte cliSkipPartial; /* client skips partial data to catch up */ + byte srvSkipPartial; /* server skips partial data to catch up */ +#ifdef HAVE_EXTENDED_MASTER + byte expectEms; /* expect extended master secret */ +#endif } Flags; -/* Out of Order FIN caputre */ +/* Out of Order FIN capture */ typedef struct FinCaputre { word32 cliFinSeq; /* client relative sequence FIN 0 is no */ word32 srvFinSeq; /* server relative sequence FIN, 0 is no */ @@ -323,13 +376,31 @@ typedef struct FinCaputre { } FinCaputre; +typedef struct HsHashes { +#ifndef NO_OLD_TLS +#ifndef NO_SHA + wc_Sha hashSha; +#endif +#ifndef NO_MD5 + wc_Md5 hashMd5; +#endif +#endif +#ifndef NO_SHA256 + wc_Sha256 hashSha256; +#endif +#ifdef WOLFSSL_SHA384 + wc_Sha384 hashSha384; +#endif +} HsHashes; + + /* Sniffer Session holds info for each client/server SSL/TLS session */ typedef struct SnifferSession { SnifferServer* context; /* server context */ SSL* sslServer; /* SSL server side decode */ SSL* sslClient; /* SSL client side decode */ - word32 server; /* server address in network byte order */ - word32 client; /* client address in network byte order */ + IpAddrInfo server; /* server address in network byte order */ + IpAddrInfo client; /* client address in network byte order */ word16 srvPort; /* server port */ word16 cliPort; /* client port */ word32 cliSeqStart; /* client start sequence */ @@ -339,30 +410,112 @@ typedef struct SnifferSession { FinCaputre finCaputre; /* retain out of order FIN s */ Flags flags; /* session flags */ time_t lastUsed; /* last used ticks */ + word32 keySz; /* size of the private key */ PacketBuffer* cliReassemblyList; /* client out of order packets */ PacketBuffer* srvReassemblyList; /* server out of order packets */ + word32 cliReassemblyMemory; /* client packet memory used */ + word32 srvReassemblyMemory; /* server packet memory used */ struct SnifferSession* next; /* for hash table list */ byte* ticketID; /* mac ID of session ticket */ +#ifdef HAVE_SNI + const char* sni; /* server name indication */ +#endif +#ifdef HAVE_EXTENDED_MASTER + HsHashes* hash; +#endif } SnifferSession; /* Sniffer Server List and mutex */ -static SnifferServer* ServerList = 0; -static wolfSSL_Mutex ServerListMutex; +static WOLFSSL_GLOBAL SnifferServer* ServerList = 0; +static WOLFSSL_GLOBAL wolfSSL_Mutex ServerListMutex; /* Session Hash Table, mutex, and count */ -static SnifferSession* SessionTable[HASH_SIZE]; -static wolfSSL_Mutex SessionMutex; -static int SessionCount = 0; +static WOLFSSL_GLOBAL SnifferSession* SessionTable[HASH_SIZE]; +static WOLFSSL_GLOBAL wolfSSL_Mutex SessionMutex; +static WOLFSSL_GLOBAL int SessionCount = 0; + +/* Recovery of missed data switches and stats */ +static WOLFSSL_GLOBAL wolfSSL_Mutex RecoveryMutex; /* for stats */ +static WOLFSSL_GLOBAL int RecoveryEnabled = 0; /* global switch */ +static WOLFSSL_GLOBAL int MaxRecoveryMemory = -1; + /* per session max recovery memory */ +static WOLFSSL_GLOBAL word32 MissedDataSessions = 0; + /* # of sessions with missed data */ + +/* Connection Info Callback */ +static WOLFSSL_GLOBAL SSLConnCb ConnectionCb; +static WOLFSSL_GLOBAL void* ConnectionCbCtx = NULL; + +#ifdef WOLFSSL_SNIFFER_STATS +/* Sessions Statistics */ +static WOLFSSL_GLOBAL SSLStats SnifferStats; +static WOLFSSL_GLOBAL wolfSSL_Mutex StatsMutex; +#endif + +#ifdef WOLFSSL_SNIFFER_WATCH +/* Watch Key Callback */ +static WOLFSSL_GLOBAL SSLWatchCb WatchCb; +static WOLFSSL_GLOBAL void* WatchCbCtx = NULL; +#endif + +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB +/* Store Data Callback */ +static WOLFSSL_GLOBAL SSLStoreDataCb StoreDataCb; +#endif + + +static void UpdateMissedDataSessions(void) +{ + wc_LockMutex(&RecoveryMutex); + MissedDataSessions += 1; + wc_UnLockMutex(&RecoveryMutex); +} + + +#ifdef WOLFSSL_SNIFFER_STATS +#define LOCK_STAT() do { wc_LockMutex(&StatsMutex); } while (0) +#define UNLOCK_STAT() do { wc_UnLockMutex(&StatsMutex); } while (0) +#define NOLOCK_ADD_TO_STAT(x,y) do { TraceStat(#x, y); x += y; } while (0) +#define NOLOCK_INC_STAT(x) NOLOCK_ADD_TO_STAT(x,1) +#define ADD_TO_STAT(x,y) do { LOCK_STAT(); \ + NOLOCK_ADD_TO_STAT(x,y); UNLOCK_STAT(); } while (0) +#define INC_STAT(x) do { LOCK_STAT(); \ + NOLOCK_INC_STAT(x); UNLOCK_STAT(); } while (0) +#endif + + +#ifdef WOLF_CRYPTO_CB + static WOLFSSL_GLOBAL int CryptoDeviceId = INVALID_DEVID; +#endif /* Initialize overall Sniffer */ void ssl_InitSniffer(void) { wolfSSL_Init(); - InitMutex(&ServerListMutex); - InitMutex(&SessionMutex); + wc_InitMutex(&ServerListMutex); + wc_InitMutex(&SessionMutex); + wc_InitMutex(&RecoveryMutex); +#ifdef WOLFSSL_SNIFFER_STATS + XMEMSET(&SnifferStats, 0, sizeof(SSLStats)); + wc_InitMutex(&StatsMutex); +#endif +#ifdef WOLF_CRYPTO_CB + #ifdef HAVE_INTEL_QA_SYNC + CryptoDeviceId = wc_CryptoCb_InitIntelQa(); + if (INVALID_DEVID == CryptoDeviceId) { + printf("Couldn't init the Intel QA\n"); + } + #endif + #ifdef HAVE_CAVIUM_OCTEON_SYNC + CryptoDeviceId = wc_CryptoCb_InitOcteon(); + if (INVALID_DEVID == CryptoDeviceId) { + printf("Couldn't init the Intel QA\n"); + } + #endif +#endif } @@ -374,9 +527,9 @@ static void FreeNamedKey(NamedKey* in) if (in) { if (in->key) { ForceZero(in->key, in->keySz); - free(in->key); + XFREE(in->key, NULL, DYNAMIC_TYPE_X509); } - free(in); + XFREE(in, NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY); } } @@ -400,14 +553,14 @@ static void FreeSnifferServer(SnifferServer* srv) { if (srv) { #ifdef HAVE_SNI - LockMutex(&srv->namedKeysMutex); + wc_LockMutex(&srv->namedKeysMutex); FreeNamedKeyList(srv->namedKeys); - UnLockMutex(&srv->namedKeysMutex); - FreeMutex(&srv->namedKeysMutex); + wc_UnLockMutex(&srv->namedKeysMutex); + wc_FreeMutex(&srv->namedKeysMutex); #endif SSL_CTX_free(srv->ctx); } - free(srv); + XFREE(srv, NULL, DYNAMIC_TYPE_SNIFFER_SERVER); } @@ -415,8 +568,8 @@ static void FreeSnifferServer(SnifferServer* srv) static void FreePacketBuffer(PacketBuffer* del) { if (del) { - free(del->data); - free(del); + XFREE(del->data, NULL, DYNAMIC_TYPE_SNIFFER_PB_BUFFER); + XFREE(del, NULL, DYNAMIC_TYPE_SNIFFER_PB); } } @@ -427,7 +580,7 @@ static void FreePacketList(PacketBuffer* in) if (in) { PacketBuffer* del; PacketBuffer* packet = in; - + while (packet) { del = packet; packet = packet->next; @@ -443,13 +596,16 @@ static void FreeSnifferSession(SnifferSession* session) if (session) { SSL_free(session->sslClient); SSL_free(session->sslServer); - + FreePacketList(session->cliReassemblyList); FreePacketList(session->srvReassemblyList); - free(session->ticketID); + XFREE(session->ticketID, NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID); +#ifdef HAVE_EXTENDED_MASTER + XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES); +#endif } - free(session); + XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); } @@ -462,9 +618,9 @@ void ssl_FreeSniffer(void) SnifferSession* removeSession; int i; - LockMutex(&ServerListMutex); - LockMutex(&SessionMutex); - + wc_LockMutex(&ServerListMutex); + wc_LockMutex(&SessionMutex); + srv = ServerList; while (srv) { removeServer = srv; @@ -481,11 +637,21 @@ void ssl_FreeSniffer(void) } } - UnLockMutex(&SessionMutex); - UnLockMutex(&ServerListMutex); + wc_UnLockMutex(&SessionMutex); + wc_UnLockMutex(&ServerListMutex); - FreeMutex(&SessionMutex); - FreeMutex(&ServerListMutex); + wc_FreeMutex(&RecoveryMutex); + wc_FreeMutex(&SessionMutex); + wc_FreeMutex(&ServerListMutex); + +#ifdef WOLF_CRYPTO_CB +#ifdef HAVE_INTEL_QA_SYNC + wc_CryptoCb_CleanupIntelQa(&CryptoDeviceId); +#endif +#ifdef HAVE_CAVIUM_OCTEON_SYNC + wc_CryptoCb_CleanupOcteon(&CryptoDeviceId); +#endif +#endif if (TraceFile) { TraceOn = 0; @@ -497,65 +663,118 @@ void ssl_FreeSniffer(void) } +#ifdef HAVE_EXTENDED_MASTER + +static int HashInit(HsHashes* hash) +{ + int ret = 0; + + XMEMSET(hash, 0, sizeof(HsHashes)); + +#ifndef NO_OLD_TLS +#ifndef NO_SHA + if (ret == 0) + ret = wc_InitSha(&hash->hashSha); +#endif +#ifndef NO_MD5 + if (ret == 0) { + ret = wc_InitMd5(&hash->hashMd5); + } +#endif +#endif +#ifndef NO_SHA256 + if (ret == 0) + ret = wc_InitSha256(&hash->hashSha256); +#endif +#ifdef WOLFSSL_SHA384 + if (ret == 0) + ret = wc_InitSha384(&hash->hashSha384); +#endif + + return ret; +} + + +static int HashUpdate(HsHashes* hash, const byte* input, int sz) +{ + int ret = 0; + + input -= HANDSHAKE_HEADER_SZ; + sz += HANDSHAKE_HEADER_SZ; + +#ifndef NO_OLD_TLS +#ifndef NO_SHA + if (ret == 0) + ret = wc_ShaUpdate(&hash->hashSha, input, sz); +#endif +#ifndef NO_MD5 + if (ret == 0) { + ret = wc_Md5Update(&hash->hashMd5, input, sz); + } +#endif +#endif +#ifndef NO_SHA256 + if (ret == 0) + ret = wc_Sha256Update(&hash->hashSha256, input, sz); +#endif +#ifdef WOLFSSL_SHA384 + if (ret == 0) + ret = wc_Sha384Update(&hash->hashSha384, input, sz); +#endif + + return ret; +} + + +static int HashCopy(HS_Hashes* d, HsHashes* s) +{ +#ifndef NO_OLD_TLS +#ifndef NO_SHA + XMEMCPY(&d->hashSha, &s->hashSha, sizeof(wc_Sha)); +#endif +#ifndef NO_MD5 + XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(wc_Md5)); +#endif +#endif + +#ifndef NO_SHA256 + XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(wc_Sha256)); +#endif +#ifdef WOLFSSL_SHA384 + XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(wc_Sha384)); +#endif + + return 0; +} + +#endif + + /* Initialize a SnifferServer */ static void InitSnifferServer(SnifferServer* sniffer) { - sniffer->ctx = 0; - XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS); - sniffer->server = 0; - sniffer->port = 0; -#ifdef HAVE_SNI - sniffer->namedKeys = 0; - InitMutex(&sniffer->namedKeysMutex); -#endif - sniffer->next = 0; + XMEMSET(sniffer, 0, sizeof(SnifferServer)); } /* Initialize session flags */ static void InitFlags(Flags* flags) { - flags->side = 0; - flags->serverCipherOn = 0; - flags->clientCipherOn = 0; - flags->resuming = 0; - flags->cached = 0; - flags->clientHello = 0; - flags->finCount = 0; - flags->fatalError = 0; + XMEMSET(flags, 0, sizeof(Flags)); } /* Initialize FIN Capture */ static void InitFinCapture(FinCaputre* cap) { - cap->cliFinSeq = 0; - cap->srvFinSeq = 0; - cap->cliCounted = 0; - cap->srvCounted = 0; + XMEMSET(cap, 0, sizeof(FinCaputre)); } /* Initialize a Sniffer Session */ static void InitSession(SnifferSession* session) { - session->context = 0; - session->sslServer = 0; - session->sslClient = 0; - session->server = 0; - session->client = 0; - session->srvPort = 0; - session->cliPort = 0; - session->cliSeqStart = 0; - session->srvSeqStart = 0; - session->cliExpected = 0; - session->srvExpected = 0; - session->lastUsed = 0; - session->cliReassemblyList = 0; - session->srvReassemblyList = 0; - session->next = 0; - session->ticketID = 0; - + XMEMSET(session, 0, sizeof(SnifferSession)); InitFlags(&session->flags); InitFinCapture(&session->finCaputre); } @@ -565,8 +784,8 @@ static void InitSession(SnifferSession* session) typedef struct IpInfo { int length; /* length of this header */ int total; /* total length of fragment */ - word32 src; /* network order source address */ - word32 dst; /* network order destination address */ + IpAddrInfo src; /* network order source address */ + IpAddrInfo dst; /* network order destination address */ } IpInfo; @@ -590,7 +809,7 @@ typedef struct TcpPseudoHdr { word32 dst; /* destination address */ byte rsv; /* reserved, always 0 */ byte protocol; /* IP protocol */ - word16 legnth; /* tcp header length + data length (doesn't include */ + word16 length; /* tcp header length + data length (doesn't include */ /* pseudo header length) network order */ } TcpPseudoHdr; @@ -606,13 +825,13 @@ 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; -/* IP Header */ +/* IPv4 Header */ typedef struct IpHdr { byte ver_hl; /* version/header length */ byte tos; /* type of service */ @@ -627,6 +846,27 @@ typedef struct IpHdr { } IpHdr; +/* IPv6 Header */ +typedef struct Ip6Hdr { + byte ver_hl; /* version/traffic class high */ + byte tc_fl; /* traffic class low/flow label high */ + word16 fl; /* flow label low */ + word16 length; /* payload length */ + byte next_header; /* next header (6 for TCP, any other skip) */ + byte hl; /* hop limit */ + byte src[16]; /* source address */ + byte dst[16]; /* destination address */ +} Ip6Hdr; + + +/* IPv6 extension header */ +typedef struct Ip6ExtHdr { + byte next_header; /* next header (6 for TCP, any other skip) */ + byte length; /* length in 8-octet units - 1 */ + byte reserved[6]; +} Ip6ExtHdr; + + #define IP_HL(ip) ( (((ip)->ver_hl) & 0x0f) * 4) #define IP_V(ip) ( ((ip)->ver_hl) >> 4) @@ -634,8 +874,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; /* acknowledgment number */ byte offset; /* data offset, reserved */ byte flags; /* option flags */ word16 window; /* window */ @@ -653,8 +893,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 trace file if tracing */ +static void Trace(int idx) { if (TraceOn) { char myBuffer[MAX_ERROR_LEN]; @@ -716,13 +956,9 @@ static void TracePacket(void) /* Convert network byte order address into human readable */ -static char* IpToS(word32 addr, char* str) +static const char* IpToS(int version, void* src, char* dst) { - byte* p = (byte*)&addr; - - SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - - return str; + return inet_ntop(version, src, dst, TRACE_MSG_SZ); } @@ -732,8 +968,22 @@ static void TraceIP(IpHdr* iphdr) if (TraceOn) { char src[TRACE_MSG_SZ]; char dst[TRACE_MSG_SZ]; - fprintf(TraceFile, "\tdst:%s src:%s\n", IpToS(iphdr->dst, dst), - IpToS(iphdr->src, src)); + fprintf(TraceFile, "\tdst:%s src:%s\n", + IpToS(AF_INET, &iphdr->dst, dst), + IpToS(AF_INET, &iphdr->src, src)); + } +} + + +/* Show destination and source address from Ip6Hdr for packet Trace */ +static void TraceIP6(Ip6Hdr* iphdr) +{ + if (TraceOn) { + char src[TRACE_MSG_SZ]; + char dst[TRACE_MSG_SZ]; + fprintf(TraceFile, "\tdst: %s src: %s\n", + IpToS(AF_INET6, iphdr->dst, dst), + IpToS(AF_INET6, iphdr->src, src)); } } @@ -828,7 +1078,7 @@ static void TraceAddedData(int newBytes, int existingBytes) { if (TraceOn) { fprintf(TraceFile, - "\t%d bytes added to %d exisiting bytes in User Buffer\n", + "\t%d bytes added to %d existing bytes in User Buffer\n", newBytes, existingBytes); } } @@ -861,6 +1111,44 @@ static void TraceRemovedSession(void) } +/* Show SSLInfo if provided and is valid. */ +static void TraceSessionInfo(SSLInfo* sslInfo) +{ + if (TraceOn) { + if (sslInfo != NULL && sslInfo->isValid) { + fprintf(TraceFile, + "\tver:(%u %u) suiteId:(%02x %02x) suiteName:(%s) " + #ifdef HAVE_SNI + "sni:(%s) " + #endif + "keySize:(%u)\n", + sslInfo->protocolVersionMajor, + sslInfo->protocolVersionMinor, + sslInfo->serverCipherSuite0, + sslInfo->serverCipherSuite, + sslInfo->serverCipherSuiteName, + #ifdef HAVE_SNI + sslInfo->serverNameIndication, + #endif + sslInfo->keySize); + } + } +} + + +#ifdef WOLFSSL_SNIFFER_STATS + +/* Show value added to a named statistic. */ +static void TraceStat(const char* name, int add) +{ + if (TraceOn) { + fprintf(TraceFile, "\tAdding %d to %s\n", add, name); + } +} + +#endif + + /* Set user error string */ static void SetError(int idx, char* error, SnifferSession* session, int fatal) { @@ -871,6 +1159,21 @@ static void SetError(int idx, char* error, SnifferSession* session, int fatal) } +/* Compare IpAddrInfo structs */ +static WC_INLINE int MatchAddr(IpAddrInfo l, IpAddrInfo r) +{ + if (l.version == r.version) { + if (l.version == IPV4) + return (l.ip4 == r.ip4); + else if (l.version == IPV6) + return (0 == XMEMCMP(l.ip6, r.ip6, sizeof(l.ip6))); + } + return 0; +} + + +#ifndef WOLFSSL_SNIFFER_WATCH + /* See if this IPV4 network order address has been registered */ /* return 1 is true, 0 is false */ static int IsServerRegistered(word32 addr) @@ -878,18 +1181,44 @@ static int IsServerRegistered(word32 addr) int ret = 0; /* false */ SnifferServer* sniffer; - LockMutex(&ServerListMutex); - + wc_LockMutex(&ServerListMutex); + sniffer = ServerList; while (sniffer) { - if (sniffer->server == addr) { + if (sniffer->server.ip4 == addr) { ret = 1; break; } sniffer = sniffer->next; } - - UnLockMutex(&ServerListMutex); + + wc_UnLockMutex(&ServerListMutex); + + return ret; +} + + +/* See if this port has been registered to watch */ +/* See if this IPV4 network order address has been registered */ +/* return 1 is true, 0 is false */ +static int IsServerRegistered6(byte* addr) +{ + int ret = 0; /* false */ + SnifferServer* sniffer; + + wc_LockMutex(&ServerListMutex); + + sniffer = ServerList; + while (sniffer) { + if (sniffer->server.version == IPV6 && + 0 == XMEMCMP(sniffer->server.ip6, addr, sizeof(sniffer->server.ip6))) { + ret = 1; + break; + } + sniffer = sniffer->next; + } + + wc_UnLockMutex(&ServerListMutex); return ret; } @@ -901,42 +1230,53 @@ static int IsPortRegistered(word32 port) { int ret = 0; /* false */ SnifferServer* sniffer; - - LockMutex(&ServerListMutex); - + + wc_LockMutex(&ServerListMutex); + sniffer = ServerList; while (sniffer) { if (sniffer->port == (int)port) { - ret = 1; + ret = 1; break; } sniffer = sniffer->next; } - - UnLockMutex(&ServerListMutex); + + wc_UnLockMutex(&ServerListMutex); return ret; } +#endif + /* Get SnifferServer from IP and Port */ static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) { SnifferServer* sniffer; - - LockMutex(&ServerListMutex); - + + wc_LockMutex(&ServerListMutex); + sniffer = ServerList; + +#ifndef WOLFSSL_SNIFFER_WATCH while (sniffer) { - if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src) + if (sniffer->port == tcpInfo->srcPort && + MatchAddr(sniffer->server, ipInfo->src)) break; - if (sniffer->port == tcpInfo->dstPort && sniffer->server == ipInfo->dst) + if (sniffer->port == tcpInfo->dstPort && + MatchAddr(sniffer->server, ipInfo->dst)) break; + sniffer = sniffer->next; } - - UnLockMutex(&ServerListMutex); - +#else + (void)ipInfo; + (void)tcpInfo; +#endif + + wc_UnLockMutex(&ServerListMutex); + return sniffer; } @@ -944,66 +1284,84 @@ static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) /* Hash the Session Info, return hash row */ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo) { - word32 hash = ipInfo->src * ipInfo->dst; + word32 hash = 1; + + if (ipInfo->src.version == IPV4) { + hash *= ipInfo->src.ip4 * ipInfo->dst.ip4; + } + else if (ipInfo->src.version == IPV6) { + word32* x; + word32 y; + x = (word32*)ipInfo->src.ip6; + y = x[0] ^ x[1] ^ x[2] ^ x[3]; + hash *= y; + x = (word32*)ipInfo->dst.ip6; + y = x[0] ^ x[1] ^ x[2] ^ x[3]; + hash *= y; + } hash *= tcpInfo->srcPort * tcpInfo->dstPort; - + return hash % HASH_SIZE; } -/* Get Exisiting SnifferSession from IP and Port */ +/* Get Existing SnifferSession from IP and Port */ 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); - - LockMutex(&SessionMutex); - + + wc_LockMutex(&SessionMutex); + session = SessionTable[row]; while (session) { - if (session->server == ipInfo->src && session->client == ipInfo->dst && + if (MatchAddr(session->server, ipInfo->src) && + MatchAddr(session->client, ipInfo->dst) && session->srvPort == tcpInfo->srcPort && session->cliPort == tcpInfo->dstPort) break; - if (session->client == ipInfo->src && session->server == ipInfo->dst && + + if (MatchAddr(session->client, ipInfo->src) && + MatchAddr(session->server, ipInfo->dst) && 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 */ - UnLockMutex(&SessionMutex); - + /* leave alone */ + wc_UnLockMutex(&SessionMutex); + /* determine side */ if (session) { - if (ipInfo->dst == session->context->server && - tcpInfo->dstPort == session->context->port) + if (MatchAddr(ipInfo->dst, session->server) && + tcpInfo->dstPort == session->srvPort) { + session->flags.side = WOLFSSL_SERVER_END; - else + } + else { session->flags.side = WOLFSSL_CLIENT_END; - } - + } + } + return session; } -#ifdef HAVE_SNI +#if defined(HAVE_SNI) || defined(WOLFSSL_SNIFFER_WATCH) static int LoadKeyFile(byte** keyBuf, word32* keyBufSz, const char* keyFile, int typeKey, const char* password) { byte* loadBuf; - byte* saveBuf; long fileSz = 0; - int saveBufSz; XFILE file; int ret; @@ -1013,35 +1371,61 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz, file = XFOPEN(keyFile, "rb"); if (file == XBADFILE) return -1; - XFSEEK(file, 0, XSEEK_END); + if(XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return -1; + } fileSz = XFTELL(file); + if (fileSz > MAX_WOLFSSL_FILE_SIZE || fileSz < 0) { + XFCLOSE(file); + return -1; + } XREWIND(file); - loadBuf = (byte*)malloc(fileSz); + loadBuf = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_FILE); if (loadBuf == NULL) { XFCLOSE(file); return -1; } - ret = (int)XFREAD(loadBuf, fileSz, 1, file); + ret = (int)XFREAD(loadBuf, 1, fileSz, file); XFCLOSE(file); - if (typeKey == SSL_FILETYPE_PEM) { - saveBuf = (byte*)malloc(fileSz); + if (ret != fileSz) { + XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE); + return -1; + } - saveBufSz = wolfSSL_KeyPemToDer(loadBuf, (int)fileSz, + if (typeKey == WOLFSSL_FILETYPE_PEM) { + byte* saveBuf = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_X509); + int saveBufSz = 0; + + ret = -1; + if (saveBuf != NULL) { + saveBufSz = wc_KeyPemToDer(loadBuf, (int)fileSz, saveBuf, (int)fileSz, password); - free(loadBuf); + if (saveBufSz < 0) { + saveBufSz = 0; + XFREE(saveBuf, NULL, DYNAMIC_TYPE_X509); + saveBuf = NULL; + } + else + ret = 0; + } - *keyBuf = saveBuf; - *keyBufSz = (word32)saveBufSz; + ForceZero(loadBuf, (word32)fileSz); + XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE); + + if (saveBuf) { + *keyBuf = saveBuf; + *keyBufSz = (word32)saveBufSz; + } } else { *keyBuf = loadBuf; *keyBufSz = (word32)fileSz; } - if (ret < 0) { return -1; } @@ -1052,15 +1436,46 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz, #endif +#ifdef WOLFSSL_SNIFFER_WATCH + +static int CreateWatchSnifferServer(char* error) +{ + SnifferServer* sniffer; + + sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer), NULL, + DYNAMIC_TYPE_SNIFFER_SERVER); + if (sniffer == NULL) { + SetError(MEMORY_STR, error, NULL, 0); + return -1; + } + InitSnifferServer(sniffer); + sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method()); + if (!sniffer->ctx) { + SetError(MEMORY_STR, error, NULL, 0); + FreeSnifferServer(sniffer); + return -1; + } +#ifdef WOLF_CRYPTO_CB + if (CryptoDeviceId != INVALID_DEVID) + wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId); +#endif + ServerList = sniffer; + + return 0; +} + +#endif + + static int SetNamedPrivateKey(const char* name, const char* address, int port, const char* keyFile, int typeKey, const char* password, char* error) { 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; + IpAddrInfo serverIp; #ifdef HAVE_SNI NamedKey* namedKey = NULL; @@ -1069,7 +1484,8 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, (void)name; #ifdef HAVE_SNI if (name != NULL) { - namedKey = (NamedKey*)malloc(sizeof(NamedKey)); + namedKey = (NamedKey*)XMALLOC(sizeof(NamedKey), + NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY); if (namedKey == NULL) { SetError(MEMORY_STR, error, NULL, 0); return -1; @@ -1077,11 +1493,10 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, XMEMSET(namedKey, 0, sizeof(NamedKey)); namedKey->nameSz = (word32)XSTRLEN(name); - XSTRNCPY(namedKey->name, name, sizeof(namedKey->name)); - if (namedKey->nameSz >= sizeof(namedKey->name)) { - namedKey->nameSz = sizeof(namedKey->name) - 1; - namedKey->name[namedKey->nameSz] = '\0'; - } + if (namedKey->nameSz > sizeof(namedKey->name)-1) + namedKey->nameSz = sizeof(namedKey->name)-1; + XSTRNCPY(namedKey->name, name, namedKey->nameSz); + namedKey->name[MAX_SERVER_NAME-1] = '\0'; ret = LoadKeyFile(&namedKey->key, &namedKey->keySz, keyFile, type, password); @@ -1093,16 +1508,23 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, } #endif - serverIp = inet_addr(address); + serverIp.version = IPV4; + serverIp.ip4 = inet_addr(address); + if (serverIp.ip4 == INADDR_NONE) { + if (inet_pton(AF_INET6, address, serverIp.ip6) == 1) { + serverIp.version = IPV6; + } + } sniffer = ServerList; while (sniffer != NULL && - (sniffer->server != serverIp || sniffer->port != port)) { + (!MatchAddr(sniffer->server, serverIp) || sniffer->port != port)) { sniffer = sniffer->next; } if (sniffer == NULL) { isNew = 1; - sniffer = (SnifferServer*)malloc(sizeof(SnifferServer)); + sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer), + NULL, DYNAMIC_TYPE_SNIFFER_SERVER); if (sniffer == NULL) { SetError(MEMORY_STR, error, NULL, 0); #ifdef HAVE_SNI @@ -1117,7 +1539,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, sniffer->server = serverIp; sniffer->port = port; - sniffer->ctx = SSL_CTX_new(SSLv3_client_method()); + sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method()); if (!sniffer->ctx) { SetError(MEMORY_STR, error, NULL, 0); #ifdef HAVE_SNI @@ -1130,24 +1552,29 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, if (name == NULL) { if (password) { + #ifdef WOLFSSL_ENCRYPTED_KEYS SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword); SSL_CTX_set_default_passwd_cb_userdata( sniffer->ctx, (void*)password); + #endif } 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); return -1; } + #ifdef WOLF_CRYPTO_CB + wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId); + #endif } #ifdef HAVE_SNI else { - LockMutex(&sniffer->namedKeysMutex); + wc_LockMutex(&sniffer->namedKeysMutex); namedKey->next = sniffer->namedKeys; sniffer->namedKeys = namedKey; - UnLockMutex(&sniffer->namedKeysMutex); + wc_UnLockMutex(&sniffer->namedKeysMutex); } #endif @@ -1174,10 +1601,10 @@ int ssl_SetNamedPrivateKey(const char* name, TraceHeader(); TraceSetNamedServer(name, address, port, keyFile); - LockMutex(&ServerListMutex); + wc_LockMutex(&ServerListMutex); ret = SetNamedPrivateKey(name, address, port, keyFile, typeKey, password, error); - UnLockMutex(&ServerListMutex); + wc_UnLockMutex(&ServerListMutex); if (ret == 0) Trace(NEW_SERVER_STR); @@ -1198,10 +1625,10 @@ int ssl_SetPrivateKey(const char* address, int port, const char* keyFile, TraceHeader(); TraceSetServer(address, port, keyFile); - LockMutex(&ServerListMutex); + wc_LockMutex(&ServerListMutex); ret = SetNamedPrivateKey(NULL, address, port, keyFile, typeKey, password, error); - UnLockMutex(&ServerListMutex); + wc_UnLockMutex(&ServerListMutex); if (ret == 0) Trace(NEW_SERVER_STR); @@ -1210,34 +1637,92 @@ int ssl_SetPrivateKey(const char* address, int port, const char* keyFile, } +/* Check IP Header for IPV6, TCP, and a registered server address */ +/* returns 0 on success, -1 on error */ +static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error) +{ + int version = IP_V(iphdr); + int exthdrsz = IP6_HDR_SZ; + + TraceIP6(iphdr); + Trace(IP_CHECK_STR); + + if (version != IPV6) { + SetError(BAD_IPVER_STR, error, NULL, 0); + return -1; + } + + /* Here, we need to move onto next header if not TCP. */ + if (iphdr->next_header != TCP_PROTOCOL) { + Ip6ExtHdr* exthdr = (Ip6ExtHdr*)((byte*)iphdr + IP6_HDR_SZ); + do { + int hdrsz = (exthdr->length + 1) * 8; + if (hdrsz > length - exthdrsz) { + SetError(PACKET_HDR_SHORT_STR, error, NULL, 0); + return -1; + } + exthdrsz += hdrsz; + exthdr = (Ip6ExtHdr*)((byte*)exthdr + hdrsz); + } + while (exthdr->next_header != TCP_PROTOCOL && + exthdr->next_header != NO_NEXT_HEADER); + } + +#ifndef WOLFSSL_SNIFFER_WATCH + if (!IsServerRegistered6(iphdr->src) && !IsServerRegistered6(iphdr->dst)) { + SetError(SERVER_NOT_REG_STR, error, NULL, 0); + return -1; + } +#endif + + info->length = exthdrsz; + info->total = ntohs(iphdr->length) + info->length; + /* IPv6 doesn't include its own header size in the length like v4. */ + info->src.version = IPV6; + XMEMCPY(info->src.ip6, iphdr->src, sizeof(info->src.ip6)); + info->dst.version = IPV6; + XMEMCPY(info->dst.ip6, iphdr->dst, sizeof(info->dst.ip6)); + + return 0; +} + + /* Check IP Header for IPV4, TCP, and a registered server address */ +/* If header IPv6, pass to CheckIp6Hdr(). */ /* returns 0 on success, -1 on error */ static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error) { int version = IP_V(iphdr); + if (version == IPV6) + return CheckIp6Hdr((Ip6Hdr*)iphdr, info, length, error); + TraceIP(iphdr); 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; } +#ifndef WOLFSSL_SNIFFER_WATCH if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) { SetError(SERVER_NOT_REG_STR, error, NULL, 0); return -1; } +#endif info->length = IP_HL(iphdr); info->total = ntohs(iphdr->length); - info->src = iphdr->src; - info->dst = iphdr->dst; + info->src.version = IPV4; + info->src.ip4 = iphdr->src; + info->dst.version = IPV4; + info->dst.ip4 = iphdr->dst; if (info->total == 0) info->total = length; /* reassembled may be off */ @@ -1261,12 +1746,16 @@ 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); +#ifndef WOLFSSL_SNIFFER_WATCH if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) { SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0); return -1; } +#else + (void)error; +#endif return 0; } @@ -1285,76 +1774,241 @@ static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size) } -/* Process Client Key Exchange, RSA only */ +/* Copies the session's information to the provided sslInfo. Skip copy if + * SSLInfo is not provided. */ +static void CopySessionInfo(SnifferSession* session, SSLInfo* sslInfo) +{ + if (NULL != sslInfo) { + XMEMSET(sslInfo, 0, sizeof(SSLInfo)); + + /* Pass back Session Info after we have processed the Server Hello. */ + if (0 != session->sslServer->options.cipherSuite) { + const char* pCipher; + + sslInfo->isValid = 1; + sslInfo->protocolVersionMajor = session->sslServer->version.major; + sslInfo->protocolVersionMinor = session->sslServer->version.minor; + sslInfo->serverCipherSuite0 = + session->sslServer->options.cipherSuite0; + sslInfo->serverCipherSuite = + session->sslServer->options.cipherSuite; + + pCipher = wolfSSL_get_cipher(session->sslServer); + if (NULL != pCipher) { + XSTRNCPY((char*)sslInfo->serverCipherSuiteName, pCipher, + sizeof(sslInfo->serverCipherSuiteName)); + sslInfo->serverCipherSuiteName + [sizeof(sslInfo->serverCipherSuiteName) - 1] = '\0'; + } + sslInfo->keySize = session->keySz; + #ifdef HAVE_SNI + if (NULL != session->sni) { + XSTRNCPY((char*)sslInfo->serverNameIndication, + session->sni, sizeof(sslInfo->serverNameIndication)); + sslInfo->serverNameIndication + [sizeof(sslInfo->serverNameIndication) - 1] = '\0'; + } + #endif + TraceSessionInfo(sslInfo); + } + } +} + + +/* Call the session connection start callback. */ +static void CallConnectionCb(SnifferSession* session) +{ + if (ConnectionCb != NULL) { + SSLInfo info; + CopySessionInfo(session, &info); + ConnectionCb((const void*)session, &info, ConnectionCbCtx); + } +} + + +/* Process Client Key Exchange, RSA or static ECDH */ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, SnifferSession* session, char* error) { word32 idx = 0; - RsaKey key; - int ret; + int tryEcc = 0; + int ret; - if (session->sslServer->buffers.key.buffer == NULL || - session->sslServer->buffers.key.length == 0) { + if (session->sslServer->buffers.key == NULL || + session->sslServer->buffers.key->buffer == NULL || + session->sslServer->buffers.key->length == 0) { SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE); return -1; } - ret = wc_InitRsaKey(&key, 0); - if (ret == 0) - ret = wc_RsaPrivateKeyDecode(session->sslServer->buffers.key.buffer, - &idx, &key, session->sslServer->buffers.key.length); - if (ret == 0) { - int length = wc_RsaEncryptSize(&key); - if (IsTLS(session->sslServer)) - input += 2; /* tls pre length */ + { + RsaKey key; + int length; - if (length > *sslBytes) { - SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE); - wc_FreeRsaKey(&key); - return -1; + ret = wc_InitRsaKey(&key, 0); + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode( + session->sslServer->buffers.key->buffer, + &idx, &key, session->sslServer->buffers.key->length); + if (ret != 0) { + tryEcc = 1; + #ifndef HAVE_ECC + SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE); + #else + /* If we can do ECC, this isn't fatal. Not loading an ECC + * key will be fatal, though. */ + SetError(RSA_DECODE_STR, error, session, 0); + #endif + } } - ret = wc_RsaPrivateDecrypt(input, length, - session->sslServer->arrays->preMasterSecret,SECRET_LEN, &key); - if (ret != SECRET_LEN) { - SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE); - wc_FreeRsaKey(&key); - return -1; + if (ret == 0) { + length = wc_RsaEncryptSize(&key); + if (IsTLS(session->sslServer)) { + input += 2; /* tls pre length */ + } + + if (length > *sslBytes) { + SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE); + ret = -1; + } } - ret = 0; /* not in error state */ - session->sslServer->arrays->preMasterSz = SECRET_LEN; - /* store for client side as well */ - XMEMCPY(session->sslClient->arrays->preMasterSecret, - session->sslServer->arrays->preMasterSecret, SECRET_LEN); - session->sslClient->arrays->preMasterSz = SECRET_LEN; - - #ifdef SHOW_SECRETS - { - int i; - printf("pre master secret: "); - for (i = 0; i < SECRET_LEN; i++) - printf("%02x", session->sslServer->arrays->preMasterSecret[i]); - printf("\n"); + #ifdef WC_RSA_BLINDING + if (ret == 0) { + ret = wc_RsaSetRNG(&key, session->sslServer->rng); + if (ret != 0) { + SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE); + } } #endif - } - else { - SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE); + + if (ret == 0) { + session->keySz = length * WOLFSSL_BIT_SIZE; + /* length is the key size in bytes */ + session->sslServer->arrays->preMasterSz = SECRET_LEN; + + 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, + session->sslServer->arrays->preMasterSz, &key); + } + } while (ret == WC_PENDING_E); + + if (ret != SECRET_LEN) { + SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE); + } + } + wc_FreeRsaKey(&key); - return -1; } + if (tryEcc) { +#ifdef HAVE_ECC + ecc_key key; + ecc_key pubKey; + int length, keyInit = 0, pubKeyInit = 0; + + idx = 0; + ret = wc_ecc_init(&key); + if (ret == 0) { + keyInit = 1; + ret = wc_ecc_init(&pubKey); + } + if (ret == 0) { + pubKeyInit = 1; + ret = wc_EccPrivateKeyDecode( + session->sslServer->buffers.key->buffer, + &idx, &key, session->sslServer->buffers.key->length); + if (ret != 0) { + SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE); + } + } + + if (ret == 0) { + length = wc_ecc_size(&key) * 2 + 1; + /* The length should be 2 times the key size (x and y), plus 1 + * for the type byte. */ + if (IsTLS(session->sslServer)) { + input += 1; /* Don't include the TLS length for the key. */ + } + + if (length + 1 > *sslBytes) { + SetError(PARTIAL_INPUT_STR, + error, session, FATAL_ERROR_STATE); + ret = -1; + } + } + + if (ret == 0) { + ret = wc_ecc_import_x963_ex(input, length, &pubKey, ECC_CURVE_DEF); + if (ret != 0) { + SetError(ECC_PUB_DECODE_STR, error, session, FATAL_ERROR_STATE); + } + } + + if (ret == 0) { + session->keySz = ((length - 1) / 2) * WOLFSSL_BIT_SIZE; + /* Length is in bytes. Subtract 1 for the ECC key type. Divide + * by two as the key is in (x,y) coordinates, where x and y are + * the same size, the key size. Convert from bytes to bits. */ + session->sslServer->arrays->preMasterSz = ENCRYPT_LEN; + + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &key.asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_ecc_shared_secret(&key, &pubKey, + session->sslServer->arrays->preMasterSecret, + &session->sslServer->arrays->preMasterSz); + } + } while (ret == WC_PENDING_E); + } + +#ifdef WOLFSSL_SNIFFER_STATS + if (ret != 0) + INC_STAT(SnifferStats.sslKeyFails); +#endif + + if (keyInit) + wc_ecc_free(&key); + if (pubKeyInit) + wc_ecc_free(&pubKey); +#endif + } + + /* store for client side as well */ + XMEMCPY(session->sslClient->arrays->preMasterSecret, + session->sslServer->arrays->preMasterSecret, + session->sslServer->arrays->preMasterSz); + session->sslClient->arrays->preMasterSz = + session->sslServer->arrays->preMasterSz; + + #ifdef SHOW_SECRETS + { + word32 i; + printf("pre master secret: "); + for (i = 0; i < session->sslServer->arrays->preMasterSz; i++) + printf("%02x", session->sslServer->arrays->preMasterSecret[i]); + printf("\n"); + } + #endif + if (SetCipherSpecs(session->sslServer) != 0) { SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); - wc_FreeRsaKey(&key); return -1; } if (SetCipherSpecs(session->sslClient) != 0) { SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); - wc_FreeRsaKey(&key); return -1; } @@ -1386,7 +2040,8 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, } #endif - wc_FreeRsaKey(&key); + CallConnectionCb(session); + return ret; } @@ -1425,13 +2080,17 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes, /* Process Server Hello */ -static int ProcessServerHello(const byte* input, int* sslBytes, +static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, SnifferSession* session, char* error) { ProtocolVersion pv; - byte b; + byte b, b0; int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN; int doResume = 0; + int initialBytes = *sslBytes; + + (void)msgSz; + (void)initialBytes; /* make sure we didn't miss ClientHello */ if (session->flags.clientHello == 0) { @@ -1473,14 +2132,33 @@ static int ProcessServerHello(const byte* input, int* sslBytes, *sslBytes -= b; /* cipher suite */ - b = *input++; /* first byte, ECC or not */ - session->sslServer->options.cipherSuite0 = b; - session->sslClient->options.cipherSuite0 = b; + b0 = *input++; /* first byte, ECC or not */ + session->sslServer->options.cipherSuite0 = b0; + session->sslClient->options.cipherSuite0 = b0; b = *input++; session->sslServer->options.cipherSuite = b; session->sslClient->options.cipherSuite = b; *sslBytes -= SUITE_LEN; +#ifdef WOLFSSL_SNIFFER_STATS + { + const CipherSuiteInfo* suites = GetCipherNames(); + int suitesSz = GetCipherNamesSize(); + int match = 0; + + while (suitesSz) { + if (b0 == suites->cipherSuite0 && b == suites->cipherSuite) { + match = 1; + break; + } + suites++; + suitesSz--; + } + if (!match) + INC_STAT(SnifferStats.sslCiphersUnsupported); + } +#endif /* WOLFSSL_SNIFFER_STATS */ + /* compression */ b = *input++; *sslBytes -= ENUM_LEN; @@ -1490,10 +2168,67 @@ static int ProcessServerHello(const byte* input, int* sslBytes, return -1; } - if (session->sslServer->options.haveSessionId && - XMEMCMP(session->sslServer->arrays->sessionID, +#ifdef HAVE_EXTENDED_MASTER + /* extensions */ + if ((initialBytes - *sslBytes) < msgSz) { + word16 len; + + /* skip extensions until extended master secret */ + /* make sure can read len */ + if (SUITE_LEN > *sslBytes) { + SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + len = (word16)((input[0] << 8) | input[1]); + input += SUITE_LEN; + *sslBytes -= SUITE_LEN; + /* make sure can read through all extensions */ + if (len > *sslBytes) { + SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + while (len >= EXT_TYPE_SZ + LENGTH_SZ) { + byte extType[EXT_TYPE_SZ]; + word16 extLen; + + extType[0] = input[0]; + extType[1] = input[1]; + input += EXT_TYPE_SZ; + *sslBytes -= EXT_TYPE_SZ; + + extLen = (word16)((input[0] << 8) | input[1]); + input += LENGTH_SZ; + *sslBytes -= LENGTH_SZ; + + /* make sure can read through individual extension */ + if (extLen > *sslBytes) { + SetError(SERVER_HELLO_INPUT_STR, error, session, + FATAL_ERROR_STATE); + return -1; + } + + if (extType[0] == 0x00 && extType[1] == EXT_MASTER_SECRET) { + session->flags.expectEms = 1; + } + + input += extLen; + *sslBytes -= extLen; + len -= extLen + EXT_TYPE_SZ + LENGTH_SZ; + } + } + + if (!session->flags.expectEms) { + XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES); + session->hash = NULL; + } +#endif + + if (session->sslServer->options.haveSessionId) { + if (XMEMCMP(session->sslServer->arrays->sessionID, session->sslClient->arrays->sessionID, ID_LEN) == 0) - doResume = 1; + doResume = 1; + } else if (session->sslClient->options.haveSessionId == 0 && session->sslServer->options.haveSessionId == 0 && session->ticketID) @@ -1509,8 +2244,11 @@ static int ProcessServerHello(const byte* input, int* sslBytes, if (doResume ) { int ret = 0; SSL_SESSION* resume = GetSession(session->sslServer, - session->sslServer->arrays->masterSecret); + session->sslServer->arrays->masterSecret, 0); if (resume == NULL) { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslResumeMisses); +#endif SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE); return -1; } @@ -1520,6 +2258,10 @@ static int ProcessServerHello(const byte* input, int* sslBytes, session->flags.resuming = 1; Trace(SERVER_DID_RESUMPTION_STR); +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslResumedConns); + INC_STAT(SnifferStats.sslResumptionValid); +#endif if (SetCipherSpecs(session->sslServer) != 0) { SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); return -1; @@ -1546,6 +2288,11 @@ static int ProcessServerHello(const byte* input, int* sslBytes, return -1; } } + else { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslStandardConns); +#endif + } #ifdef SHOW_SECRETS { int i; @@ -1580,31 +2327,32 @@ 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)) + if (nameSz > sizeof(name) - 1) nameSz = sizeof(name) - 1; name[nameSz] = 0; - LockMutex(&session->context->namedKeysMutex); + wc_LockMutex(&session->context->namedKeysMutex); namedKey = session->context->namedKeys; while (namedKey != NULL) { if (nameSz == namedKey->nameSz && XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) { if (wolfSSL_use_PrivateKey_buffer(session->sslServer, namedKey->key, namedKey->keySz, - SSL_FILETYPE_ASN1) != SSL_SUCCESS) { - UnLockMutex(&session->context->namedKeysMutex); + WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + wc_UnLockMutex(&session->context->namedKeysMutex); SetError(CLIENT_HELLO_LATE_KEY_STR, error, session, FATAL_ERROR_STATE); return -1; } + session->sni = namedKey->name; break; } else namedKey = namedKey->next; } - UnLockMutex(&session->context->namedKeysMutex); + wc_UnLockMutex(&session->context->namedKeysMutex); } } #endif @@ -1679,12 +2427,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) { @@ -1700,7 +2448,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes, return -1; } - while (len > EXT_TYPE_SZ + LENGTH_SZ) { + while (len >= EXT_TYPE_SZ + LENGTH_SZ) { byte extType[EXT_TYPE_SZ]; word16 extLen; @@ -1730,7 +2478,8 @@ static int ProcessClientHello(const byte* input, int* sslBytes, if (extLen) { if (session->ticketID == 0) { - session->ticketID = (byte*)malloc(ID_LEN); + session->ticketID = (byte*)XMALLOC(ID_LEN, + NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID); if (session->ticketID == 0) { SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); @@ -1750,6 +2499,83 @@ static int ProcessClientHello(const byte* input, int* sslBytes, } +#ifdef WOLFSSL_SNIFFER_WATCH + +/* Process Certificate */ +static int ProcessCertificate(const byte* input, int* sslBytes, + SnifferSession* session, char* error) +{ + Sha256 sha; + const byte* certChain; + word32 certChainSz; + word32 certSz; + int ret; + byte digest[SHA256_DIGEST_SIZE]; + + /* If the receiver is the server, this is the client certificate message, + * and it should be ignored at this point. */ + if (session->flags.side == WOLFSSL_SERVER_END) + return 0; + + if (WatchCb == NULL) { + SetError(WATCH_CB_MISSING_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + if (*sslBytes < CERT_HEADER_SZ) { + SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + ato24(input, &certChainSz); + *sslBytes -= CERT_HEADER_SZ; + input += CERT_HEADER_SZ; + + if (*sslBytes < (int)certChainSz) { + SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + certChain = input; + + ato24(input, &certSz); + input += OPAQUE24_LEN; + if (*sslBytes < (int)certSz) { + SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + *sslBytes -= certChainSz; + + ret = wc_InitSha256(&sha); + if (ret == 0) + ret = wc_Sha256Update(&sha, input, certSz); + if (ret == 0) + ret = wc_Sha256Final(&sha, digest); + if (ret != 0) { + SetError(WATCH_HASH_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + ret = WatchCb((void*)session, digest, sizeof(digest), + certChain, certChainSz, WatchCbCtx, error); + if (ret != 0) { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslKeysUnmatched); +#endif + SetError(WATCH_FAIL_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + else { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslKeyMatches); +#endif + } + + return 0; +} + +#endif + + /* Process Finished */ static int ProcessFinished(const byte* input, int size, int* sslBytes, SnifferSession* session, char* error) @@ -1757,7 +2583,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 @@ -1771,12 +2597,16 @@ 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); - if (sess == NULL) + WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0); + if (sess == NULL) { AddSession(session->sslServer); /* don't re add */ +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslResumptionInserts); +#endif + } session->flags.cached = 1; } } @@ -1807,16 +2637,35 @@ 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; if (*sslBytes < size) { - SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE); + Trace(SPLIT_HANDSHAKE_MSG_STR); + *sslBytes = 0; + return ret; + } + + /* A session's arrays are released when the handshake is completed. */ + if (session->sslServer->arrays == NULL && + session->sslClient->arrays == NULL) { + + 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) { + SetError(EXTENDED_MASTER_HASH_STR, error, + session, FATAL_ERROR_STATE); + return -1; + } + } +#endif + switch (type) { case hello_verify_request: Trace(GOT_HELLO_VERIFY_STR); @@ -1830,12 +2679,15 @@ static int DoHandShake(const byte* input, int* sslBytes, break; case server_hello: Trace(GOT_SERVER_HELLO_STR); - ret = ProcessServerHello(input, sslBytes, session, error); + ret = ProcessServerHello(size, input, sslBytes, session, error); break; case certificate_request: Trace(GOT_CERT_REQ_STR); break; case server_key_exchange: +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslEphemeralMisses); +#endif Trace(GOT_SERVER_KEY_EX_STR); /* can't know temp key passively */ SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); @@ -1843,6 +2695,14 @@ static int DoHandShake(const byte* input, int* sslBytes, break; case certificate: Trace(GOT_CERT_STR); + if (session->flags.side == WOLFSSL_SERVER_END) { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslClientAuthConns); +#endif + } +#ifdef WOLFSSL_SNIFFER_WATCH + ret = ProcessCertificate(input, sslBytes, session, error); +#endif break; case server_hello_done: Trace(GOT_SERVER_HELLO_DONE_STR); @@ -1857,7 +2717,32 @@ static int DoHandShake(const byte* input, int* sslBytes, break; case client_key_exchange: Trace(GOT_CLIENT_KEY_EX_STR); - ret = ProcessClientKeyExchange(input, sslBytes, session, error); +#ifdef HAVE_EXTENDED_MASTER + if (session->flags.expectEms && session->hash != NULL) { + if (HashCopy(session->sslServer->hsHashes, + session->hash) == 0 && + HashCopy(session->sslClient->hsHashes, + session->hash) == 0) { + + session->sslServer->options.haveEMS = 1; + session->sslClient->options.haveEMS = 1; + } + else { + SetError(EXTENDED_MASTER_HASH_STR, error, + session, FATAL_ERROR_STATE); + ret = -1; + } + XMEMSET(session->hash, 0, sizeof(HsHashes)); + XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES); + session->hash = NULL; + } + else { + session->sslServer->options.haveEMS = 0; + session->sslClient->options.haveEMS = 0; + } +#endif + if (ret == 0) + ret = ProcessClientKeyExchange(input, sslBytes, session, error); break; case certificate_verify: Trace(GOT_CERT_VER_STR); @@ -1881,43 +2766,89 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) { int ret = 0; + (void)output; + (void)input; + (void)sz; + switch (ssl->specs.bulk_cipher_algorithm) { #ifdef BUILD_ARC4 case wolfssl_rc4: 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; #endif + #ifdef HAVE_IDEA + case wolfssl_idea: + wc_IdeaCbcDecrypt(ssl->decrypt.idea, output, input, sz); + break; + #endif + + #ifdef HAVE_AESGCM + 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); + + if (wc_AesGcmEncrypt(ssl->decrypt.aes, + output, + input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + nonce, AESGCM_NONCE_SZ, + authTag, sizeof(authTag), + NULL, 0) < 0) { + Trace(BAD_DECRYPT); + ret = -1; + } + ForceZero(nonce, AESGCM_NONCE_SZ); + } + else { + Trace(BAD_DECRYPT_SIZE); + ret = -1; + } + break; + #endif + + #ifdef HAVE_NULL_CIPHER + case wolfssl_cipher_null: + XMEMCPY(output, input, sz); + break; + #endif + default: Trace(BAD_DECRYPT_TYPE); ret = -1; @@ -1946,11 +2877,16 @@ static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz, *advance = ssl->specs.block_size; } - ssl->keys.padSz = ssl->specs.hash_size; + if (ssl->specs.cipher_type == aead) { + *advance = ssl->specs.aead_mac_size; + ssl->keys.padSz = ssl->specs.aead_mac_size; + } + else + ssl->keys.padSz = ssl->specs.hash_size; if (ssl->specs.cipher_type == block) ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1; - + return output; } @@ -1963,20 +2899,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) - LockMutex(&SessionMutex); - + wc_LockMutex(&SessionMutex); + current = SessionTable[row]; - + while (current) { if (current == session) { if (previous) @@ -1990,9 +2926,9 @@ static void RemoveSession(SnifferSession* session, IpInfo* ipInfo, previous = current; current = current->next; } - + if (!haveLock) - UnLockMutex(&SessionMutex); + wc_UnLockMutex(&SessionMutex); } @@ -2001,11 +2937,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); @@ -2022,15 +2958,33 @@ 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)); + session = (SnifferSession*)XMALLOC(sizeof(SnifferSession), + NULL, DYNAMIC_TYPE_SNIFFER_SESSION); if (session == NULL) { SetError(MEMORY_STR, error, NULL, 0); return 0; } InitSession(session); +#ifdef HAVE_EXTENDED_MASTER + { + HsHashes* newHash = (HsHashes*)XMALLOC(sizeof(HsHashes), + NULL, DYNAMIC_TYPE_HASHES); + if (newHash == NULL) { + SetError(MEMORY_STR, error, NULL, 0); + XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); + return 0; + } + if (HashInit(newHash) != 0) { + SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0); + XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); + return 0; + } + session->hash = newHash; + } +#endif session->server = ipInfo->dst; session->client = ipInfo->src; session->srvPort = (word16)tcpInfo->dstPort; @@ -2038,18 +2992,22 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, session->cliSeqStart = tcpInfo->sequence; session->cliExpected = 1; /* relative */ session->lastUsed= time(NULL); - + session->keySz = 0; +#ifdef HAVE_SNI + session->sni = NULL; +#endif + session->context = GetSnifferServer(ipInfo, tcpInfo); if (session->context == NULL) { SetError(SERVER_NOT_REG_STR, error, NULL, 0); - free(session); + XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); return 0; } - + session->sslServer = SSL_new(session->context->ctx); if (session->sslServer == NULL) { SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); - free(session); + XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); return 0; } session->sslClient = SSL_new(session->context->ctx); @@ -2058,36 +3016,34 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, session->sslServer = 0; SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); - free(session); + XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); return 0; } /* put server back into server mode */ session->sslServer->options.side = WOLFSSL_SERVER_END; - + row = SessionHash(ipInfo, tcpInfo); - + /* add it to the session table */ - LockMutex(&SessionMutex); - + wc_LockMutex(&SessionMutex); + session->next = SessionTable[row]; SessionTable[row] = session; - + SessionCount++; - + if ( (SessionCount % HASH_SIZE) == 0) { TraceFindingStale(); RemoveStaleSessions(); } - - 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; - + + wc_UnLockMutex(&SessionMutex); + + /* CreateSession is called in response to a SYN packet, we know this + * is headed to the server. Also we know the server is one we care + * about as we've passed the GetSnifferServer() successfully. */ + session->flags.side = WOLFSSL_SERVER_END; + return session; } @@ -2116,16 +3072,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; } @@ -2148,38 +3104,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.legnth = htons(tcpInfo->length + dataLen); - + 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 */ @@ -2205,23 +3161,25 @@ 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); - + /* We only care about the data in the TCP/IP record. There may be extra + * data after the IP record for the FCS for Ethernet. */ + *sslBytes = (int)(packet + ipInfo->total - *sslFrame); + return 0; } @@ -2234,13 +3192,16 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes, /* create a new SnifferSession on client SYN */ if (tcpInfo->syn && !tcpInfo->ack) { TraceClientSyn(tcpInfo->sequence); +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslEncryptedConns); +#endif *session = CreateSession(ipInfo, tcpInfo, error); if (*session == NULL) { *session = GetSnifferSession(ipInfo, tcpInfo); - /* already had exisiting, so OK */ + /* already had existing, so OK */ if (*session) return 1; - + SetError(MEMORY_STR, error, NULL, 0); return -1; } @@ -2256,10 +3217,17 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes, /* don't worry about duplicate ACKs either */ if (sslBytes == 0 && tcpInfo->ack) return 1; - + +#ifdef WOLFSSL_SNIFFER_STATS + LOCK_STAT(); + NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets); + NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes); + UNLOCK_STAT(); +#endif + SetError(BAD_SESSION_STR, error, NULL, 0); return -1; - } + } } return 0; } @@ -2270,27 +3238,28 @@ 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)); + + pb = (PacketBuffer*)XMALLOC(sizeof(PacketBuffer), + NULL, DYNAMIC_TYPE_SNIFFER_PB); if (pb == NULL) return NULL; - + pb->next = 0; pb->begin = *begin; pb->end = end; - pb->data = (byte*)malloc(added); - + pb->data = (byte*)XMALLOC(added, NULL, DYNAMIC_TYPE_SNIFFER_PB_BUFFER); + if (pb->data == NULL) { - free(pb); + XFREE(pb, NULL, DYNAMIC_TYPE_SNIFFER_PB); return NULL; } XMEMCPY(pb->data, data, added); - + *bytesLeft -= added; *begin = pb->end + 1; - + return pb; } @@ -2305,29 +3274,42 @@ 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; word32 added; int bytesLeft = sslBytes; /* could be overlapping fragment */ /* if list is empty add full frame to front */ if (!curr) { + if (MaxRecoveryMemory != -1 && + (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) { + SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE); + return -1; + } add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft); if (add == NULL) { SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); return -1; } *front = add; + *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); + return -1; + } add = CreateBuffer(&seq, end, sslFrame, &bytesLeft); if (add == NULL) { SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); @@ -2335,8 +3317,9 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, } add->next = curr; *front = add; + *reassemblyMemory += sslBytes; } - + /* while we have bytes left, try to find a gap to fill */ while (bytesLeft > 0) { /* get previous packet in list */ @@ -2344,7 +3327,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) @@ -2352,18 +3335,23 @@ 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); + return -1; + } add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq], &bytesLeft); if (add == NULL) { @@ -2372,6 +3360,7 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, } add->next = prev->next; prev->next = add; + *reassemblyMemory += added; } return 1; } @@ -2398,42 +3387,48 @@ 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) ? &session->cliExpected : &session->srvExpected; PacketBuffer* reassemblyList = (session->flags.side == WOLFSSL_SERVER_END) ? session->cliReassemblyList : session->srvReassemblyList; - + 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; - + + /* The following conditional block is duplicated below. It is the + * same action but for a different setup case. If changing this + * 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, @@ -2447,36 +3442,189 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, } else if (real > *expected) { Trace(OUT_OF_ORDER_STR); - if (*sslBytes > 0) - return AddToReassembly(session->flags.side, real, *sslFrame, - *sslBytes, session, error); + if (*sslBytes > 0) { + int addResult = AddToReassembly(session->flags.side, real, + *sslFrame, *sslBytes, session, error); + if (skipPartial) { + *sslBytes = 0; + return 0; + } + else + return addResult; + } else if (tcpInfo->fin) return AddFinCapture(session, real); } + else if (*sslBytes > 0) { + if (skipPartial) { + AddToReassembly(session->flags.side, real, + *sslFrame, *sslBytes, session, error); + *expected += *sslBytes; + *sslBytes = 0; + if (tcpInfo->fin) + *expected += 1; + return 0; + } + /* The following conditional block is duplicated above. It is the + * same action but for a different setup case. If changing this + * block be sure to also update the block above. */ + else 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, + *sslFrame + reassemblyList->end - *expected + 1, + newEnd - reassemblyList->end, session, error); + } + } + } /* got expected sequence */ *expected += *sslBytes; if (tcpInfo->fin) *expected += 1; - + return 0; } +static int FindNextRecordInAssembly(SnifferSession* session, + const byte** sslFrame, int* sslBytes, + const byte** end, char* error) +{ + PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->cliReassemblyList : + &session->srvReassemblyList; + PacketBuffer* curr = *front; + PacketBuffer* prev = NULL; + byte* skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->flags.srvSkipPartial : + &session->flags.cliSkipPartial; + word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->cliReassemblyMemory : + &session->srvReassemblyMemory; + SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? + session->sslServer : + session->sslClient; + ProtocolVersion pv = ssl->version; + word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->cliExpected : + &session->srvExpected; + + while (curr != NULL) { + *expected = curr->end + 1; + + if (curr->data[0] == application_data && + curr->data[1] == pv.major && + curr->data[2] == pv.minor) { + + if (ssl->buffers.inputBuffer.length > 0) + Trace(DROPPING_PARTIAL_RECORD); + + *sslBytes = curr->end - curr->begin + 1; + if ( (word32)*sslBytes > ssl->buffers.inputBuffer.bufferSize) { + if (GrowInputBuffer(ssl, *sslBytes, 0) < 0) { + SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + } + + XMEMCPY(ssl->buffers.inputBuffer.buffer, curr->data, *sslBytes); + + *front = curr->next; + *reassemblyMemory -= *sslBytes; + FreePacketBuffer(curr); + + ssl->buffers.inputBuffer.length = *sslBytes; + *sslFrame = ssl->buffers.inputBuffer.buffer; + *end = *sslFrame + *sslBytes; + *skipPartial = 0; + + return 0; + } + else if (ssl->specs.cipher_type == block) { + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes) { +#ifdef BUILD_AES + wc_AesSetIV(ssl->decrypt.aes, + curr->data + curr->end - curr->begin + - ssl->specs.block_size + 1); +#endif + } + else if (ssl->specs.bulk_cipher_algorithm == wolfssl_triple_des) { +#ifdef BUILD_DES3 + wc_Des3_SetIV(ssl->decrypt.des3, + curr->data + curr->end - curr->begin + - ssl->specs.block_size + 1); +#endif + } + } + + Trace(DROPPING_LOST_FRAG_STR); +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslDecodeFails); +#endif + prev = curr; + curr = curr->next; + *reassemblyMemory -= (prev->end - prev->begin + 1); + FreePacketBuffer(prev); + } + + *front = curr; + + return 0; +} + + +static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session) +{ + word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->srvExpected : &session->cliExpected; + PacketBuffer* list = (session->flags.side == WOLFSSL_SERVER_END) ? + session->srvReassemblyList : + session->cliReassemblyList; + byte* skipPartial = (session->flags.side != WOLFSSL_SERVER_END) ? + &session->flags.srvSkipPartial : + &session->flags.cliSkipPartial; + + *skipPartial = 1; + if (list != NULL) + *expected = list->begin; + else { + word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? + session->srvSeqStart : session->cliSeqStart; + word32 real = tcpInfo->ackNumber - seqStart; + + *expected = real; + } + + return 1; +} + + /* Check latest ack number for missing packets return 0 ok, <0 on error */ 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) @@ -2493,7 +3641,10 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte** sslFrame, char* error) { int actualLen; - + byte* ackFault = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->flags.cliAckFault : + &session->flags.srvAckFault; + /* init SEQ from server to client */ if (tcpInfo->syn && tcpInfo->ack) { session->srvSeqStart = tcpInfo->sequence; @@ -2501,20 +3652,36 @@ 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) { - SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE); - return -1; + if (!RecoveryEnabled) { + UpdateMissedDataSessions(); + SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + else { + SetError(ACK_MISSED_STR, error, session, 0); + if (*ackFault == 0) { + *ackFault = 1; + UpdateMissedDataSessions(); + } + return FixSequence(tcpInfo, session); + } } - - return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error); + + if (*ackFault) { + Trace(CLEAR_ACK_FAULT); + *ackFault = 0; + } + + return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error); } @@ -2522,11 +3689,15 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, /* returns 0 on success (continue), -1 on error, 1 on success (end) */ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte** sslFrame, SnifferSession** session, - int* sslBytes, const byte** end, char* error) + int* sslBytes, const byte** end, + void* vChain, word32 chainSz, char* error) { word32 length; SSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ? (*session)->sslServer : (*session)->sslClient; + byte skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ? + (*session)->flags.srvSkipPartial : + (*session)->flags.cliSkipPartial; /* remove SnifferSession on 2nd FIN or RST */ if (tcpInfo->fin || tcpInfo->rst) { /* flag FIN and RST */ @@ -2534,39 +3705,90 @@ 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) { + return -1; + } + } + if (*sslBytes == 0) { Trace(NO_DATA_STR); return 1; } - + /* if current partial data, add to end of partial */ - if ( (length = ssl->buffers.inputBuffer.length) ) { + /* 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); return -1; } } - XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], *sslFrame, *sslBytes); + if (vChain == NULL) { + XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], + *sslFrame, *sslBytes); + *sslBytes += length; + ssl->buffers.inputBuffer.length = *sslBytes; + *sslFrame = ssl->buffers.inputBuffer.buffer; + *end = *sslFrame + *sslBytes; + } + } + + if (vChain != NULL) { +#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT + struct iovec* chain = (struct iovec*)vChain; + word32 i, offset, headerSz, qty, remainder; + + Trace(CHAIN_INPUT_STR); + headerSz = (word32)*sslFrame - (word32)chain[0].iov_base; + remainder = *sslBytes; + + if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { + if (GrowInputBuffer(ssl, *sslBytes, length) < 0) { + SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); + return -1; + } + } + + qty = min(*sslBytes, (word32)chain[0].iov_len - headerSz); + XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], + (byte*)chain[0].iov_base + headerSz, qty); + offset = length; + for (i = 1; i < chainSz; i++) { + offset += qty; + remainder -= qty; + + if (chain[i].iov_len > remainder) + qty = remainder; + else + qty = (word32)chain[i].iov_len; + XMEMCPY(ssl->buffers.inputBuffer.buffer + offset, + chain[i].iov_base, qty); + } + *sslBytes += length; ssl->buffers.inputBuffer.length = *sslBytes; *sslFrame = ssl->buffers.inputBuffer.buffer; *end = *sslFrame + *sslBytes; +#endif + (void)chainSz; } if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) { @@ -2585,6 +3807,10 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, } else { #ifdef STARTTLS_ALLOWED + if (ssl->buffers.inputBuffer.dynamicFlag) { + ssl->buffers.inputBuffer.length = 0; + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + } return 1; #endif } @@ -2609,60 +3835,67 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, word32* length = (session->flags.side == WOLFSSL_SERVER_END) ? &session->sslServer->buffers.inputBuffer.length : &session->sslClient->buffers.inputBuffer.length; - byte* myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ? - session->sslServer->buffers.inputBuffer.buffer : - session->sslClient->buffers.inputBuffer.buffer; - word32 bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ? - session->sslServer->buffers.inputBuffer.bufferSize : - session->sslClient->buffers.inputBuffer.bufferSize; + byte** myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->sslServer->buffers.inputBuffer.buffer : + &session->sslClient->buffers.inputBuffer.buffer; + word32* bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->sslServer->buffers.inputBuffer.bufferSize : + &session->sslClient->buffers.inputBuffer.bufferSize; SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? 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 room = *bufferSize - *length; word32 packetLen = (*front)->end - (*front)->begin + 1; - if (packetLen > room && bufferSize < MAX_INPUT_SZ) { + if (packetLen > room && *bufferSize < MAX_INPUT_SZ) { if (GrowInputBuffer(ssl, packetLen, *length) < 0) { SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); return 0; } + room = *bufferSize - *length; /* bufferSize is now bigger */ } - + if (packetLen <= room) { PacketBuffer* del = *front; - - XMEMCPY(&myBuffer[*length], (*front)->data, packetLen); + 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 break; } if (moreInput) { - *sslFrame = myBuffer; + *sslFrame = *myBuffer; *sslBytes = *length; - *end = myBuffer + *length; + *end = *myBuffer + *length; } return moreInput; } - + /* Process Message(s) from sslFrame */ /* return Number of bytes on success, 0 for no data yet, and -1 on error */ static int ProcessMessage(const byte* sslFrame, SnifferSession* session, - int sslBytes, byte* data, const byte* end,char* error) + int sslBytes, byte** data, const byte* end, + void* ctx, char* error) { const byte* sslBegin = sslFrame; const byte* recordEnd; /* end of record indicator */ - const byte* inRecordEnd; /* indictor from input stream not decrypt */ + const byte* inRecordEnd; /* indicator from input stream not decrypt */ RecordLayerHeader rh; int rhSize = 0; int ret; @@ -2690,11 +3923,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; } @@ -2710,7 +3943,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) @@ -2731,6 +3964,18 @@ doMessage: recordEnd = sslFrame - ivAdvance + rhSize; /* sslFrame moved so should recordEnd */ decrypted = 1; + +#ifdef WOLFSSL_SNIFFER_STATS + if (errCode != 0) { + INC_STAT(SnifferStats.sslKeyFails); + } + else { + LOCK_STAT(); + NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets); + NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes); + UNLOCK_STAT(); + } +#endif if (errCode != 0) { SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE); return -1; @@ -2738,7 +3983,7 @@ doMessage: } doPart: - + switch ((enum ContentType)rh.type) { case handshake: { @@ -2778,14 +4023,61 @@ doPart: Trace(GOT_APP_DATA_STR); { word32 inOutIdx = 0; - + ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx); if (ret == 0) { ret = ssl->buffers.clearOutputBuffer.length; TraceGotData(ret); if (ret) { /* may be blank message */ - XMEMCPY(&data[decoded], - ssl->buffers.clearOutputBuffer.buffer, ret); + if (data != NULL) { + byte* tmpData; /* don't leak on realloc free */ + /* add an extra byte at end of allocation in case + * user wants to null terminate plaintext */ + tmpData = (byte*)XREALLOC(*data, decoded + ret + 1, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpData == NULL) { + ForceZero(*data, decoded); + XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + *data = NULL; + SetError(MEMORY_STR, error, session, + FATAL_ERROR_STATE); + return -1; + } + *data = tmpData; + XMEMCPY(*data + decoded, + ssl->buffers.clearOutputBuffer.buffer, ret); + } + else { +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB + if (StoreDataCb) { + const byte* buf; + word32 offset = 0; + word32 bufSz; + int stored; + + buf = ssl->buffers.clearOutputBuffer.buffer; + bufSz = ssl->buffers.clearOutputBuffer.length; + do { + stored = StoreDataCb(buf, bufSz, offset, + ctx); + if (stored <= 0) { + return -1; + } + offset += stored; + } while (offset < bufSz); + } + else { + SetError(STORE_DATA_CB_MISSING_STR, error, + session, FATAL_ERROR_STATE); + return -1; + } +#else + (void)ctx; + SetError(NO_DATA_DEST_STR, error, session, + FATAL_ERROR_STATE); + return -1; +#endif + } TraceAddedData(ret, decoded); decoded += ret; ssl->buffers.clearOutputBuffer.length = 0; @@ -2804,6 +4096,9 @@ doPart: break; case alert: Trace(GOT_ALERT_STR); +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslAlerts); +#endif sslFrame += rhSize; sslBytes -= rhSize; break; @@ -2829,26 +4124,28 @@ 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, +/* Return 0=normal, else = session removed */ +static int CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, SnifferSession* session) { - if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= + int ret = 0; + if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= session->cliExpected) { if (session->finCaputre.cliCounted == 0) { session->flags.finCount += 1; @@ -2856,8 +4153,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; @@ -2865,13 +4162,16 @@ 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); + ret = 1; + } + return ret; } -/* 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) @@ -2887,62 +4187,425 @@ static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo, /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */ /* returns Number of bytes on success, 0 for no data yet, and -1 on error */ -int ssl_DecodePacket(const byte* packet, int length, byte* data, char* error) +static int ssl_DecodePacketInternal(const byte* packet, int length, + void* vChain, word32 chainSz, + byte** data, SSLInfo* sslInfo, + void* ctx, char* error) { TcpInfo tcpInfo; IpInfo ipInfo; const byte* sslFrame; - const byte* end = packet + length; + const byte* end; int sslBytes; /* ssl bytes unconsumed */ int ret; SnifferSession* session = 0; +#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT + if (packet == NULL && vChain != NULL) { + struct iovec* chain = (struct iovec*)vChain; + word32 i; + + length = 0; + for (i = 0; i < chainSz; i++) + length += chain[i].iov_len; + packet = (const byte*)chain[0].iov_base; + } +#endif + if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes, error) != 0) return -1; - + + end = sslFrame + sslBytes; + 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 */ - + else if (ret == 1) { +#ifdef WOLFSSL_SNIFFER_STATS + if (sslBytes > 0) { + LOCK_STAT(); + NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets); + NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes); + UNLOCK_STAT(); + } + else + INC_STAT(SnifferStats.sslDecryptedPackets); +#endif + 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 */ - + else if (ret == 1) { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslDecryptedPackets); +#endif + return 0; /* done for now */ + } + ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes, - &end, error); + &end, vChain, chainSz, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; else if (ret == -1) return -1; - else if (ret == 1) return 0; /* done for now */ + else if (ret == 1) { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslDecryptedPackets); +#endif + return 0; /* done for now */ + } - ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error); +#ifdef WOLFSSL_SNIFFER_STATS + if (sslBytes > 0) { + LOCK_STAT(); + NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets); + NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes); + UNLOCK_STAT(); + } + else + INC_STAT(SnifferStats.sslDecryptedPackets); +#endif + + ret = ProcessMessage(sslFrame, session, sslBytes, data, end, ctx, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; - CheckFinCapture(&ipInfo, &tcpInfo, session); + if (CheckFinCapture(&ipInfo, &tcpInfo, session) == 0) { + CopySessionInfo(session, sslInfo); + } + return ret; } +/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */ +/* returns Number of bytes on success, 0 for no data yet, and -1 on error */ +/* Also returns Session Info if available */ +int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length, + unsigned char** data, SSLInfo* sslInfo, char* error) +{ + return ssl_DecodePacketInternal(packet, length, NULL, 0, data, sslInfo, + NULL, error); +} + + +/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */ +/* returns Number of bytes on success, 0 for no data yet, and -1 on error */ +int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) +{ + return ssl_DecodePacketInternal(packet, length, NULL, 0, data, NULL, NULL, + error); +} + + +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB + +int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet, + int length, void* ctx, SSLInfo* sslInfo, char* error) +{ + return ssl_DecodePacketInternal(packet, length, NULL, 0, NULL, sslInfo, + ctx, error); +} + +#endif + + +#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT + +int ssl_DecodePacketWithChain(void* vChain, word32 chainSz, byte** data, + char* error) +{ + return ssl_DecodePacketInternal(NULL, 0, vChain, chainSz, data, NULL, NULL, + error); +} + +#endif + + +#if defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \ + defined(WOLFSSL_SNIFFER_STORE_DATA_CB) + +int ssl_DecodePacketWithChainSessionInfoStoreData(void* vChain, word32 chainSz, + void* ctx, SSLInfo* sslInfo, char* error) +{ + return ssl_DecodePacketInternal(NULL, 0, vChain, chainSz, NULL, sslInfo, + ctx, error); +} + +#endif + + +/* Deallocator for the decoded data buffer. */ +/* returns 0 on success, -1 on error */ +int ssl_FreeDecodeBuffer(byte** data, char* error) +{ + return ssl_FreeZeroDecodeBuffer(data, 0, error); +} + + +/* Deallocator for the decoded data buffer, zeros out buffer. */ +/* returns 0 on success, -1 on error */ +int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error) +{ + (void)error; + + if (sz < 0) { + return -1; + } + + if (data != NULL) { + ForceZero(*data, (word32)sz); + XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + *data = NULL; + } + + return 0; +} + + /* Enables (if traceFile)/ Disables debug tracing */ /* returns 0 on success, -1 on error */ int ssl_Trace(const char* traceFile, char* error) { if (traceFile) { - TraceFile = fopen(traceFile, "a"); - if (!TraceFile) { - SetError(BAD_TRACE_FILE_STR, error, NULL, 0); - return -1; + /* Don't try to reopen the file */ + if (TraceFile == NULL) { + TraceFile = fopen(traceFile, "a"); + if (!TraceFile) { + SetError(BAD_TRACE_FILE_STR, error, NULL, 0); + return -1; + } + TraceOn = 1; } - TraceOn = 1; } - else + else TraceOn = 0; return 0; } +/* Enables/Disables Recovery of missed data if later packets allow + * maxMemory is number of bytes to use for reassembly buffering per session, + * -1 means unlimited + * returns 0 on success, -1 on error */ +int ssl_EnableRecovery(int onOff, int maxMemory, char* error) +{ + (void)error; + RecoveryEnabled = onOff; + if (onOff) + MaxRecoveryMemory = maxMemory; + + return 0; +} + + + +#ifdef WOLFSSL_SESSION_STATS + +int ssl_GetSessionStats(unsigned int* active, unsigned int* total, + unsigned int* peak, unsigned int* maxSessions, + unsigned int* missedData, unsigned int* reassemblyMem, + char* error) +{ + int ret; + + if (missedData) { + wc_LockMutex(&RecoveryMutex); + *missedData = MissedDataSessions; + wc_UnLockMutex(&RecoveryMutex); + } + + if (reassemblyMem) { + SnifferSession* session; + int i; + + *reassemblyMem = 0; + wc_LockMutex(&SessionMutex); + for (i = 0; i < HASH_SIZE; i++) { + session = SessionTable[i]; + while (session) { + *reassemblyMem += session->cliReassemblyMemory; + *reassemblyMem += session->srvReassemblyMemory; + session = session->next; + } + } + wc_UnLockMutex(&SessionMutex); + } + + ret = wolfSSL_get_session_stats(active, total, peak, maxSessions); + + if (ret == WOLFSSL_SUCCESS) + return 0; + else { + SetError(BAD_SESSION_STATS, error, NULL, 0); + return -1; + } +} + +#endif + + + +int ssl_SetConnectionCb(SSLConnCb cb) +{ + ConnectionCb = cb; + return 0; +} + + + +int ssl_SetConnectionCtx(void* ctx) +{ + ConnectionCbCtx = ctx; + return 0; +} + + +#ifdef WOLFSSL_SNIFFER_STATS + +/* Resets the statistics tracking global structure. + * returns 0 on success, -1 on error */ +int ssl_ResetStatistics(void) +{ + wc_LockMutex(&StatsMutex); + XMEMSET(&SnifferStats, 0, sizeof(SSLStats)); + wc_UnLockMutex(&StatsMutex); + return 0; +} + + +/* Copies the SSL statistics into the provided stats record. + * returns 0 on success, -1 on error */ +int ssl_ReadStatistics(SSLStats* stats) +{ + if (stats == NULL) + return -1; + + LOCK_STAT(); + XMEMCPY(stats, &SnifferStats, sizeof(SSLStats)); + UNLOCK_STAT(); + return 0; +} + +/* Copies the SSL statistics into the provided stats record then + * resets the statistics tracking global structure. + * returns 0 on success, -1 on error */ +int ssl_ReadResetStatistics(SSLStats* stats) +{ + if (stats == NULL) + return -1; + + LOCK_STAT(); + XMEMCPY(stats, &SnifferStats, sizeof(SSLStats)); + XMEMSET(&SnifferStats, 0, sizeof(SSLStats)); + UNLOCK_STAT(); + return 0; +} + +#endif /* WOLFSSL_SNIFFER_STATS */ + + +#ifdef WOLFSSL_SNIFFER_WATCH + +int ssl_SetWatchKeyCallback_ex(SSLWatchCb cb, int devId, char* error) +{ + (void)devId; + WatchCb = cb; + return CreateWatchSnifferServer(error); +} + + +int ssl_SetWatchKeyCallback(SSLWatchCb cb, char* error) +{ + WatchCb = cb; + return CreateWatchSnifferServer(error); +} + + +int ssl_SetWatchKeyCtx(void* ctx, char* error) +{ + (void)error; + WatchCbCtx = ctx; + return 0; +} + + +int ssl_SetWatchKey_buffer(void* vSniffer, const byte* key, word32 keySz, + int keyType, char* error) +{ + SnifferSession* sniffer; + int ret; + + if (vSniffer == NULL) { + return -1; + } + if (key == NULL || keySz == 0) { + return -1; + } + + sniffer = (SnifferSession*)vSniffer; + /* Remap the keyType from what the user can use to + * what wolfSSL_use_PrivateKey_buffer expects. */ + keyType = (keyType == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM : + WOLFSSL_FILETYPE_ASN1; + + ret = wolfSSL_use_PrivateKey_buffer(sniffer->sslServer, + key, keySz, keyType); + if (ret != WOLFSSL_SUCCESS) { + SetError(KEY_FILE_STR, error, sniffer, FATAL_ERROR_STATE); + return -1; + } + + return 0; +} + + +int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType, + const char* password, char* error) +{ + byte* keyBuf = NULL; + word32 keyBufSz = 0; + int ret; + + if (vSniffer == NULL) { + return -1; + } + if (keyFile == NULL) { + return -1; + } + + /* Remap the keyType from what the user can use to + * what LoadKeyFile expects. */ + keyType = (keyType == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM : + WOLFSSL_FILETYPE_ASN1; + + ret = LoadKeyFile(&keyBuf, &keyBufSz, keyFile, keyType, password); + if (ret < 0) { + SetError(KEY_FILE_STR, error, NULL, 0); + XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509); + return -1; + } + + ret = ssl_SetWatchKey_buffer(vSniffer, keyBuf, keyBufSz, FILETYPE_DER, + error); + XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509); + + return ret; +} + +#endif /* WOLFSSL_SNIFFER_WATCH */ + + +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB + +int ssl_SetStoreDataCallback(SSLStoreDataCb cb) +{ + StoreDataCb = cb; + return 0; +} + +#endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */ #endif /* WOLFSSL_SNIFFER */ +#endif /* WOLFCRYPT_ONLY */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/ssl.c b/FreeRTOS-Plus/Source/WolfSSL/src/ssl.c index 139e343f9..58569f3e9 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/src/ssl.c +++ b/FreeRTOS-Plus/Source/WolfSSL/src/ssl.c @@ -1,8 +1,8 @@ /* ssl.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,14 +16,23 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include +#if defined(OPENSSL_EXTRA) && !defined(_WIN32) + /* turn on GNU extensions for XVASPRINTF with wolfSSL_BIO_printf */ + #undef _GNU_SOURCE + #define _GNU_SOURCE +#endif + +#if !defined(WOLFCRYPT_ONLY) || defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) #ifdef HAVE_ERRNO_H #include @@ -32,20 +41,62 @@ #include #include #include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + +#if !defined(WOLFSSL_ALLOW_NO_SUITES) && !defined(WOLFCRYPT_ONLY) + #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) \ + && !defined(WOLFSSL_STATIC_DH) && !defined(WOLFSSL_STATIC_PSK) \ + && !defined(HAVE_ED25519) && !defined(HAVE_ED448) + #error "No cipher suites defined because DH disabled, ECC disabled, and no static suites defined. Please see top of README" + #endif + #ifdef WOLFSSL_CERT_GEN + /* need access to Cert struct for creating certificate */ + #include + #endif +#endif + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(HAVE_WEBSERVER) || defined(WOLFSSL_KEY_GEN) #include + /* openssl headers end, wolfssl internal headers next */ +#endif + +#include + +#ifndef NO_RSA + #include #endif #ifdef OPENSSL_EXTRA /* openssl headers begin */ + #include #include #include #include #include + #include #include #include #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include /* openssl headers end, wolfssl internal headers next */ #include #include @@ -53,118 +104,432 @@ #include #include #include - #ifdef WOLFSSL_SHA512 + #include + #include + #include + #include + #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) + #include + #endif /* WITH_STUNNEL */ + #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) #include #endif -#endif - -#ifndef NO_FILESYSTEM - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) \ - && !defined(EBSNET) - #include - #include + #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \ + && !defined(WC_NO_RNG) + #include #endif - #ifdef EBSNET - #include "vfapi.h" - #include "vfile.h" + #if defined(HAVE_FIPS) || defined(HAVE_SELFTEST) + #include #endif -#endif /* NO_FILESYSTEM */ - -#ifndef TRUE - #define TRUE 1 + #if defined(OPENSSL_ALL) && defined(HAVE_PKCS7) + #include + #endif /* OPENSSL_ALL && HAVE_PKCS7 */ #endif -#ifndef FALSE - #define FALSE 0 +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi); + int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi); + int oid2nid(word32 oid, int grp); #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN +#if defined(WOLFSSL_QT) + #include +#endif - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } +#ifdef NO_ASN + #include +#endif +#endif /* !WOLFCRYPT_ONLY || OPENSSL_EXTRA */ -#endif /* WOLFSSSL_HAVE_MIN */ +#define WOLFSSL_EVP_INCLUDED +#include "wolfcrypt/src/evp.c" -#ifndef WOLFSSL_HAVE_MAX -#define WOLFSSL_HAVE_MAX +#ifdef OPENSSL_EXTRA +/* Global pointer to constant BN on */ +static WOLFSSL_BIGNUM* bn_one = NULL; +#endif +#ifndef WOLFCRYPT_ONLY + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) +const WOLF_EC_NIST_NAME kNistCurves[] = { + {XSTR_SIZEOF("P-192"), "P-192", NID_X9_62_prime192v1}, + {XSTR_SIZEOF("P-256"), "P-256", NID_X9_62_prime256v1}, + {XSTR_SIZEOF("P-112"), "P-112", NID_secp112r1}, + {XSTR_SIZEOF("P-112-2"), "P-112-2", NID_secp112r2}, + {XSTR_SIZEOF("P-128"), "P-128", NID_secp128r1}, + {XSTR_SIZEOF("P-128-2"), "P-128-2", NID_secp128r2}, + {XSTR_SIZEOF("P-160"), "P-160", NID_secp160r1}, + {XSTR_SIZEOF("P-160-2"), "P-160-2", NID_secp160r2}, + {XSTR_SIZEOF("P-224"), "P-224", NID_secp224r1}, + {XSTR_SIZEOF("P-384"), "P-384", NID_secp384r1}, + {XSTR_SIZEOF("P-521"), "P-521", NID_secp521r1}, + {XSTR_SIZEOF("K-160"), "K-160", NID_secp160k1}, + {XSTR_SIZEOF("K-192"), "K-192", NID_secp192k1}, + {XSTR_SIZEOF("K-224"), "K-224", NID_secp224k1}, + {XSTR_SIZEOF("K-256"), "K-256", NID_secp256k1}, + {XSTR_SIZEOF("B-160"), "B-160", NID_brainpoolP160r1}, + {XSTR_SIZEOF("B-192"), "B-192", NID_brainpoolP192r1}, + {XSTR_SIZEOF("B-224"), "B-224", NID_brainpoolP224r1}, + {XSTR_SIZEOF("B-256"), "B-256", NID_brainpoolP256r1}, + {XSTR_SIZEOF("B-320"), "B-320", NID_brainpoolP320r1}, + {XSTR_SIZEOF("B-384"), "B-384", NID_brainpoolP384r1}, + {XSTR_SIZEOF("B-512"), "B-512", NID_brainpoolP512r1}, + {0, NULL, 0}, +}; +#endif + +#if defined(WOLFSSL_RENESAS_TSIP_TLS) + /* for root ca verification */ +int tsip_tls_RootCertVerify(const byte *cert, word32 cert_len, + word32 key_n_start, word32 key_n_len, + word32 key_e_start, word32 key_e_len, + word32 cm_row); +byte tsip_rootCAverified( ); +#endif + +#ifdef WOLFSSL_SESSION_EXPORT #ifdef WOLFSSL_DTLS - static INLINE word32 max(word32 a, word32 b) - { - return a > b ? a : b; - } -#endif /* WOLFSSL_DTLS */ - -#endif /* WOLFSSL_HAVE_MAX */ - - -#ifndef WOLFSSL_LEANPSK -char* mystrnstr(const char* s1, const char* s2, unsigned int n) +int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, unsigned int sz) { - unsigned int s2_len = (unsigned int)XSTRLEN(s2); + WOLFSSL_ENTER("wolfSSL_session_import"); - if (s2_len == 0) - return (char*)s1; - - while (n >= s2_len && s1[0]) { - if (s1[0] == s2[0]) - if (XMEMCMP(s1, s2, s2_len) == 0) - return (char*)s1; - s1++; - n--; + if (ssl == NULL || buf == NULL) { + return BAD_FUNC_ARG; } - return NULL; + /* sanity checks on buffer and protocol are done in internal function */ + return wolfSSL_dtls_import_internal(ssl, buf, sz); } -#endif +/* Sets the function to call for serializing the session. This function is + * called right after the handshake is completed. */ +int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func) +{ + + WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_export"); + + /* purposefully allow func to be NULL */ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + ctx->dtls_export = func; + + return WOLFSSL_SUCCESS; +} + + +/* Sets the function in WOLFSSL struct to call for serializing the session. This + * function is called right after the handshake is completed. */ +int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func) +{ + + WOLFSSL_ENTER("wolfSSL_dtls_set_export"); + + /* purposefully allow func to be NULL */ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ssl->dtls_export = func; + + return WOLFSSL_SUCCESS; +} + + +/* This function allows for directly serializing a session rather than using + * callbacks. It has less overhead by removing a temporary buffer and gives + * control over when the session gets serialized. When using callbacks the + * session is always serialized immediately after the handshake is finished. + * + * buf is the argument to contain the serialized session + * sz is the size of the buffer passed in + * ssl is the WOLFSSL struct to serialize + * returns the size of serialized session on success, 0 on no action, and + * negative value on error */ +int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz) +{ + WOLFSSL_ENTER("wolfSSL_dtls_export"); + + if (ssl == NULL || sz == NULL) { + return BAD_FUNC_ARG; + } + + if (buf == NULL) { + *sz = MAX_EXPORT_BUFFER; + return 0; + } + + /* if not DTLS do nothing */ + if (!ssl->options.dtls) { + WOLFSSL_MSG("Currently only DTLS export is supported"); + return 0; + } + + /* copy over keys, options, and dtls state struct */ + return wolfSSL_dtls_export_internal(ssl, buf, *sz); +} + + +/* This function is similar to wolfSSL_dtls_export but only exports the portion + * of the WOLFSSL structure related to the state of the connection, i.e. peer + * sequence number, epoch, AEAD state etc. + * + * buf is the argument to contain the serialized state, if null then set "sz" to + * buffer size required + * sz is the size of the buffer passed in + * ssl is the WOLFSSL struct to serialize + * returns the size of serialized session on success, 0 on no action, and + * negative value on error */ +int wolfSSL_dtls_export_state_only(WOLFSSL* ssl, unsigned char* buf, + unsigned int* sz) +{ + WOLFSSL_ENTER("wolfSSL_dtls_export_state_only"); + + if (ssl == NULL || sz == NULL) { + return BAD_FUNC_ARG; + } + + if (buf == NULL) { + *sz = MAX_EXPORT_STATE_BUFFER; + return 0; + } + + /* if not DTLS do nothing */ + if (!ssl->options.dtls) { + WOLFSSL_MSG("Currently only DTLS export state is supported"); + return 0; + } + + /* copy over keys, options, and dtls state struct */ + return wolfSSL_dtls_export_state_internal(ssl, buf, *sz); +} + + +/* returns 0 on success */ +int wolfSSL_send_session(WOLFSSL* ssl) +{ + int ret; + byte* buf; + word16 bufSz = MAX_EXPORT_BUFFER; + + WOLFSSL_ENTER("wolfSSL_send_session"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + buf = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + return MEMORY_E; + } + + /* if not DTLS do nothing */ + if (!ssl->options.dtls) { + XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Currently only DTLS export is supported"); + return 0; + } + + /* copy over keys, options, and dtls state struct */ + ret = wolfSSL_dtls_export_internal(ssl, buf, bufSz); + if (ret < 0) { + XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + /* if no error ret has size of buffer */ + ret = ssl->dtls_export(ssl, buf, ret, NULL); + if (ret != WOLFSSL_SUCCESS) { + XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + return 0; +} +#endif /* WOLFSSL_DTLS */ +#endif /* WOLFSSL_SESSION_EXPORT */ + /* prevent multiple mutex initializations */ -static volatile int initRefCount = 0; -static wolfSSL_Mutex count_mutex; /* init ref count mutex */ +static volatile WOLFSSL_GLOBAL int initRefCount = 0; +static WOLFSSL_GLOBAL wolfSSL_Mutex count_mutex; /* init ref count mutex */ - -WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method) +/* 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 + success is freed when ctx is freed. + */ +WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap) { WOLFSSL_CTX* ctx = NULL; - WOLFSSL_ENTER("WOLFSSL_CTX_new"); + WOLFSSL_ENTER("wolfSSL_CTX_new_ex"); - if (initRefCount == 0) - wolfSSL_Init(); /* user no longer forced to call Init themselves */ + if (initRefCount == 0) { + /* user no longer forced to call Init themselves */ + int ret = wolfSSL_Init(); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_Init failed"); + WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0); + if (method != NULL) { + XFREE(method, heap, DYNAMIC_TYPE_METHOD); + } + return NULL; + } + } if (method == NULL) return ctx; - ctx = (WOLFSSL_CTX*) XMALLOC(sizeof(WOLFSSL_CTX), 0, DYNAMIC_TYPE_CTX); + ctx = (WOLFSSL_CTX*) XMALLOC(sizeof(WOLFSSL_CTX), heap, DYNAMIC_TYPE_CTX); if (ctx) { - if (InitSSL_Ctx(ctx, method) < 0) { + int ret; + + ret = InitSSL_Ctx(ctx, method, heap); + #ifdef WOLFSSL_STATIC_MEMORY + if (heap != NULL) { + ctx->onHeap = 1; /* free the memory back to heap when done */ + } + #endif + if (ret < 0) { WOLFSSL_MSG("Init CTX failed"); 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, NULL, DYNAMIC_TYPE_METHOD); + XFREE(method, heap, DYNAMIC_TYPE_METHOD); } + WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0); return ctx; } +WOLFSSL_ABI +WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method) +{ +#ifdef WOLFSSL_HEAP_TEST + /* if testing the heap hint then set top level CTX to have test value */ + return wolfSSL_CTX_new_ex(method, (void*)WOLFSSL_HEAP_TEST); +#else + return wolfSSL_CTX_new_ex(method, NULL); +#endif +} + +#ifdef OPENSSL_EXTRA +/* increases CTX reference count to track proper time to "free" */ +int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx) +{ + int refCount = SSL_CTX_RefCount(ctx, 1); + return ((refCount > 1) ? 1 : 0); +} +#endif + +WOLFSSL_ABI 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); + ctx->srp_password = NULL; + } + wc_SrpTerm(ctx->srp); + XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP); + ctx->srp = NULL; + } +#endif FreeSSL_Ctx(ctx); + } + WOLFSSL_LEAVE("SSL_CTX_free", 0); } +#ifdef HAVE_ENCRYPT_THEN_MAC +/** + * Sets whether Encrypt-Then-MAC extension can be negotiated against context. + * The default value: enabled. + * + * ctx SSL/TLS context. + * set Whether to allow or not: 1 is allow and 0 is disallow. + * returns WOLFSSL_SUCCESS + */ +int wolfSSL_CTX_AllowEncryptThenMac(WOLFSSL_CTX *ctx, int set) +{ + ctx->disallowEncThenMac = !set; + return WOLFSSL_SUCCESS; +} + +/** + * Sets whether Encrypt-Then-MAC extension can be negotiated against context. + * The default value comes from context. + * + * ctx SSL/TLS context. + * set Whether to allow or not: 1 is allow and 0 is disallow. + * returns WOLFSSL_SUCCESS + */ +int wolfSSL_AllowEncryptThenMac(WOLFSSL *ssl, int set) +{ + ssl->options.disallowEncThenMac = !set; + return WOLFSSL_SUCCESS; +} +#endif + +#ifdef SINGLE_THREADED +/* no locking in single threaded mode, allow a CTX level rng to be shared with + * WOLFSSL objects, WOLFSSL_SUCCESS on ok */ +int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx) +{ + WC_RNG* rng; + int ret; + + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ctx->heap, DYNAMIC_TYPE_RNG); + if (rng == NULL) { + return MEMORY_E; + } + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(rng, ctx->heap, ctx->devId); +#else + ret = wc_InitRng(rng); +#endif + if (ret != 0) { + XFREE(rng, ctx->heap, DYNAMIC_TYPE_RNG); + return ret; + } + + ctx->rng = rng; + return WOLFSSL_SUCCESS; +} +#endif + + +WOLFSSL_ABI WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx) { WOLFSSL* ssl = NULL; @@ -176,10 +541,10 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx) if (ctx == NULL) return ssl; - ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap,DYNAMIC_TYPE_SSL); + ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap, DYNAMIC_TYPE_SSL); if (ssl) - if ( (ret = InitSSL(ssl, ctx)) < 0) { - FreeSSL(ssl); + if ( (ret = InitSSL(ssl, ctx, 0)) < 0) { + FreeSSL(ssl, ctx->heap); ssl = 0; } @@ -188,180 +553,859 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx) } +WOLFSSL_ABI void wolfSSL_free(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_free"); if (ssl) - FreeSSL(ssl); + FreeSSL(ssl, ssl->ctx->heap); 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 existing 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 existing object into read only. Allows concurrent access from two + * different threads. + * + * ssl existing 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) { + (void)ssl; + (void)value; + +#ifndef WOLFSSL_NO_TLS12 WOLFSSL_ENTER("SSL_use_old_poly"); - ssl->options.oldPoly = value; + WOLFSSL_MSG("Warning SSL connection auto detects old/new and this function" + "is depreciated"); + ssl->options.oldPoly = (word16)value; WOLFSSL_LEAVE("SSL_use_old_poly", 0); +#endif return 0; } #endif + +WOLFSSL_ABI int wolfSSL_set_fd(WOLFSSL* ssl, int fd) { - WOLFSSL_ENTER("SSL_set_fd"); - ssl->rfd = fd; /* not used directly to allow IO callbacks */ - ssl->wfd = fd; + int ret; + WOLFSSL_ENTER("SSL_set_fd"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_set_read_fd(ssl, fd); + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_set_write_fd(ssl, fd); + } + + return ret; +} + + +int wolfSSL_set_read_fd(WOLFSSL* ssl, int fd) +{ + WOLFSSL_ENTER("SSL_set_read_fd"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ssl->rfd = fd; /* not used directly to allow IO callbacks */ ssl->IOCB_ReadCtx = &ssl->rfd; - ssl->IOCB_WriteCtx = &ssl->wfd; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx; - ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx; - ssl->buffers.dtlsCtx.fd = fd; + ssl->buffers.dtlsCtx.rfd = fd; } #endif - WOLFSSL_LEAVE("SSL_set_fd", SSL_SUCCESS); - return SSL_SUCCESS; + WOLFSSL_LEAVE("SSL_set_read_fd", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_set_write_fd(WOLFSSL* ssl, int fd) +{ + WOLFSSL_ENTER("SSL_set_write_fd"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ssl->wfd = fd; /* not used directly to allow IO callbacks */ + ssl->IOCB_WriteCtx = &ssl->wfd; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx; + ssl->buffers.dtlsCtx.wfd = fd; + } + #endif + + WOLFSSL_LEAVE("SSL_set_write_fd", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; } /** - * Get the name of cipher at priotity level passed in. + * Get the name of cipher at priority level passed in. */ char* wolfSSL_get_cipher_list(int priority) { - const char* const* ciphers = GetCipherNames(); + const CipherSuiteInfo* ciphers = GetCipherNames(); if (priority >= GetCipherNamesSize() || priority < 0) { return 0; } - return (char*)ciphers[priority]; + return (char*)ciphers[priority].name; +} + + +/** + * 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(); - int totalInc = 0; - int step = 0; - char delim = ':'; - int size = GetCipherNamesSize(); - int i; + const CipherSuiteInfo* ciphers = GetCipherNames(); + int ciphersSz = GetCipherNamesSize(); + int i; + int cipherNameSz; if (buf == NULL || len <= 0) return BAD_FUNC_ARG; - /* Add each member to the buffer delimitted by a : */ - for (i = 0; i < size; i++) { - step = (int)(XSTRLEN(ciphers[i]) + 1); /* delimiter */ - totalInc += step; + /* Add each member to the buffer delimited by a : */ + for (i = 0; i < ciphersSz; i++) { + cipherNameSz = (int)XSTRLEN(ciphers[i].name); + if (cipherNameSz + 1 < len) { + XSTRNCPY(buf, ciphers[i].name, len); + buf += cipherNameSz; - /* Check to make sure buf is large enough and will not overflow */ - if (totalInc < len) { - XSTRNCPY(buf, ciphers[i], XSTRLEN(ciphers[i])); - buf += XSTRLEN(ciphers[i]); + if (i < ciphersSz - 1) + *buf++ = ':'; + *buf = 0; - if (i < size - 1) - *buf++ = delim; + len -= cipherNameSz + 1; } else return BUFFER_E; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } +#ifndef NO_ERROR_STRINGS +/* places a list of all supported cipher suites in TLS_* format into "buf" + * return WOLFSSL_SUCCESS on success */ +int wolfSSL_get_ciphers_iana(char* buf, int len) +{ + const CipherSuiteInfo* ciphers = GetCipherNames(); + int ciphersSz = GetCipherNamesSize(); + int i; + int cipherNameSz; + + if (buf == NULL || len <= 0) + return BAD_FUNC_ARG; + + /* Add each member to the buffer delimited by a : */ + for (i = 0; i < ciphersSz; i++) { + cipherNameSz = (int)XSTRLEN(ciphers[i].name_iana); + if (cipherNameSz + 1 < len) { + XSTRNCPY(buf, ciphers[i].name_iana, len); + buf += cipherNameSz; + + if (i < ciphersSz - 1) + *buf++ = ':'; + *buf = 0; + + len -= cipherNameSz + 1; + } + else + return BUFFER_E; + } + return WOLFSSL_SUCCESS; +} +#endif /* NO_ERROR_STRINGS */ + + +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_iana(ssl); + len = min(len, (int)(XSTRLEN(cipher) + 1)); + XMEMCPY(buf, cipher, len); + return buf; +} + int wolfSSL_get_fd(const WOLFSSL* ssl) { + int fd = -1; WOLFSSL_ENTER("SSL_get_fd"); - WOLFSSL_LEAVE("SSL_get_fd", ssl->rfd); - return ssl->rfd; -} - - -int wolfSSL_get_using_nonblock(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_using_nonblock"); - WOLFSSL_LEAVE("wolfSSL_get_using_nonblock", ssl->options.usingNonblock); - return ssl->options.usingNonblock; + if (ssl) { + fd = ssl->rfd; + } + WOLFSSL_LEAVE("SSL_get_fd", fd); + return fd; } int wolfSSL_dtls(WOLFSSL* ssl) { - return ssl->options.dtls; + int dtlsOpt = 0; + if (ssl) + dtlsOpt = ssl->options.dtls; + return dtlsOpt; } +#if !defined(NO_CERTS) +/* Set whether mutual authentication is required for connections. + * Server side only. + * + * ctx The SSL/TLS CTX object. + * req 1 to indicate required and 0 when not. + * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and + * 0 on success. + */ +int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + if (ctx->method->side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + + ctx->mutualAuth = (byte)req; + + return 0; +} + +/* Set whether mutual authentication is required for the connection. + * Server side only. + * + * ssl The SSL/TLS object. + * req 1 to indicate required and 0 when not. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3, + * SIDE_ERROR when not a client and 0 on success. + */ +int wolfSSL_mutual_auth(WOLFSSL* ssl, int req) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + + ssl->options.mutualAuth = (word16)req; + + return 0; +} +#endif /* NO_CERTS */ #ifndef WOLFSSL_LEANPSK -void wolfSSL_set_using_nonblock(WOLFSSL* ssl, int nonblock) -{ - WOLFSSL_ENTER("wolfSSL_set_using_nonblock"); - ssl->options.usingNonblock = (nonblock != 0); -} - - int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz) { #ifdef WOLFSSL_DTLS - void* sa = (void*)XMALLOC(peerSz, ssl->heap, DYNAMIC_TYPE_SOCKADDR); + void* sa; + + if (ssl == NULL) + return WOLFSSL_FAILURE; + + sa = (void*)XMALLOC(peerSz, ssl->heap, DYNAMIC_TYPE_SOCKADDR); if (sa != NULL) { - if (ssl->buffers.dtlsCtx.peer.sa != NULL) + if (ssl->buffers.dtlsCtx.peer.sa != NULL) { XFREE(ssl->buffers.dtlsCtx.peer.sa,ssl->heap,DYNAMIC_TYPE_SOCKADDR); + ssl->buffers.dtlsCtx.peer.sa = NULL; + } 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 } int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz) { #ifdef WOLFSSL_DTLS + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + if (peer != NULL && peerSz != NULL - && *peerSz >= ssl->buffers.dtlsCtx.peer.sz) { + && *peerSz >= ssl->buffers.dtlsCtx.peer.sz + && 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 } + + +#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) + +int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_sctp()"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->dtlsSctp = 1; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_dtls_set_sctp(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_dtls_set_sctp()"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.dtlsSctp = 1; + return WOLFSSL_SUCCESS; +} + +#endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */ + +#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \ + defined(WOLFSSL_DTLS) + +int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX* ctx, word16 newMtu) +{ + if (ctx == NULL || newMtu > MAX_RECORD_SIZE) + return BAD_FUNC_ARG; + + ctx->dtlsMtuSz = newMtu; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (newMtu > MAX_RECORD_SIZE) { + ssl->error = BAD_FUNC_ARG; + return WOLFSSL_FAILURE; + } + + ssl->dtlsMtuSz = newMtu; + return WOLFSSL_SUCCESS; +} + +#endif /* WOLFSSL_DTLS && (WOLFSSL_SCTP || WOLFSSL_DTLS_MTU) */ + + +#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 = (byte)id; +#ifndef WOLFSSL_USER_IO + ctx->CBIORecv = EmbedReceiveFromMcast; +#endif /* WOLFSSL_USER_IO */ + + 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 WC_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 underlyig 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 + + (void)ssl; WOLFSSL_LEAVE("wolfSSL_negotiate", err); @@ -369,96 +1413,344 @@ int wolfSSL_negotiate(WOLFSSL* ssl) } +WOLFSSL_ABI +WC_RNG* wolfSSL_GetRNG(WOLFSSL* ssl) +{ + if (ssl) { + return ssl->rng; + } + + return NULL; +} + + #ifndef WOLFSSL_LEANPSK /* object size based on build */ int wolfSSL_GetObjectSize(void) { #ifdef SHOW_SIZES - printf("sizeof suites = %lu\n", sizeof(Suites)); - printf("sizeof ciphers(2) = %lu\n", sizeof(Ciphers)); + printf("sizeof suites = %lu\n", (unsigned long)sizeof(Suites)); + printf("sizeof ciphers(2) = %lu\n", (unsigned long)sizeof(Ciphers)); #ifndef NO_RC4 - printf(" sizeof arc4 = %lu\n", sizeof(Arc4)); + printf("\tsizeof arc4 = %lu\n", (unsigned long)sizeof(Arc4)); #endif - printf(" sizeof aes = %lu\n", sizeof(Aes)); + printf("\tsizeof aes = %lu\n", (unsigned long)sizeof(Aes)); #ifndef NO_DES3 - printf(" sizeof des3 = %lu\n", sizeof(Des3)); + printf("\tsizeof des3 = %lu\n", (unsigned long)sizeof(Des3)); #endif #ifndef NO_RABBIT - printf(" sizeof rabbit = %lu\n", sizeof(Rabbit)); + printf("\tsizeof rabbit = %lu\n", (unsigned long)sizeof(Rabbit)); #endif #ifdef HAVE_CHACHA - printf(" sizeof chacha = %lu\n", sizeof(Chacha)); + printf("\tsizeof chacha = %lu\n", (unsigned long)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)); + printf("sizeof cipher specs = %lu\n", (unsigned long)sizeof(CipherSpecs)); + printf("sizeof keys = %lu\n", (unsigned long)sizeof(Keys)); + printf("sizeof Hashes(2) = %lu\n", (unsigned long)sizeof(Hashes)); #ifndef NO_MD5 - printf(" sizeof MD5 = %lu\n", sizeof(Md5)); + printf("\tsizeof MD5 = %lu\n", (unsigned long)sizeof(wc_Md5)); #endif #ifndef NO_SHA - printf(" sizeof SHA = %lu\n", sizeof(Sha)); + printf("\tsizeof SHA = %lu\n", (unsigned long)sizeof(wc_Sha)); +#endif +#ifdef WOLFSSL_SHA224 + printf("\tsizeof SHA224 = %lu\n", (unsigned long)sizeof(wc_Sha224)); #endif #ifndef NO_SHA256 - printf(" sizeof SHA256 = %lu\n", sizeof(Sha256)); + printf("\tsizeof SHA256 = %lu\n", (unsigned long)sizeof(wc_Sha256)); #endif #ifdef WOLFSSL_SHA384 - printf(" sizeof SHA384 = %lu\n", sizeof(Sha384)); + printf("\tsizeof SHA384 = %lu\n", (unsigned long)sizeof(wc_Sha384)); #endif #ifdef WOLFSSL_SHA384 - printf(" sizeof SHA512 = %lu\n", sizeof(Sha512)); + printf("\tsizeof SHA512 = %lu\n", (unsigned long)sizeof(wc_Sha512)); #endif - printf("sizeof Buffers = %lu\n", sizeof(Buffers)); - printf("sizeof Options = %lu\n", sizeof(Options)); - printf("sizeof Arrays = %lu\n", sizeof(Arrays)); + printf("sizeof Buffers = %lu\n", (unsigned long)sizeof(Buffers)); + printf("sizeof Options = %lu\n", (unsigned long)sizeof(Options)); + printf("sizeof Arrays = %lu\n", (unsigned long)sizeof(Arrays)); #ifndef NO_RSA - printf("sizeof RsaKey = %lu\n", sizeof(RsaKey)); + printf("sizeof RsaKey = %lu\n", (unsigned long)sizeof(RsaKey)); #endif #ifdef HAVE_ECC - printf("sizeof ecc_key = %lu\n", sizeof(ecc_key)); + printf("sizeof ecc_key = %lu\n", (unsigned long)sizeof(ecc_key)); #endif - printf("sizeof WOLFSSL_CIPHER = %lu\n", sizeof(WOLFSSL_CIPHER)); - printf("sizeof WOLFSSL_SESSION = %lu\n", sizeof(WOLFSSL_SESSION)); - printf("sizeof WOLFSSL = %lu\n", sizeof(WOLFSSL)); - printf("sizeof WOLFSSL_CTX = %lu\n", sizeof(WOLFSSL_CTX)); + printf("sizeof WOLFSSL_CIPHER = %lu\n", (unsigned long)sizeof(WOLFSSL_CIPHER)); + printf("sizeof WOLFSSL_SESSION = %lu\n", (unsigned long)sizeof(WOLFSSL_SESSION)); + printf("sizeof WOLFSSL = %lu\n", (unsigned long)sizeof(WOLFSSL)); + printf("sizeof WOLFSSL_CTX = %lu\n", (unsigned long)sizeof(WOLFSSL_CTX)); #endif return sizeof(WOLFSSL); } + +int wolfSSL_CTX_GetObjectSize(void) +{ + return sizeof(WOLFSSL_CTX); +} + +int wolfSSL_METHOD_GetObjectSize(void) +{ + return sizeof(WOLFSSL_METHOD); +} #endif +#ifdef WOLFSSL_STATIC_MEMORY + +int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method, + unsigned char* buf, unsigned int sz, + int flag, int max) +{ + WOLFSSL_HEAP* heap; + WOLFSSL_HEAP_HINT* hint; + word32 idx = 0; + + if (ctx == NULL || buf == NULL) { + return BAD_FUNC_ARG; + } + + if (*ctx == NULL && method == NULL) { + return BAD_FUNC_ARG; + } + + if (*ctx == NULL || (*ctx)->heap == NULL) { + if (sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT) > sz - idx) { + return BUFFER_E; /* not enough memory for structures */ + } + heap = (WOLFSSL_HEAP*)buf; + idx += sizeof(WOLFSSL_HEAP); + if (wolfSSL_init_memory_heap(heap) != 0) { + return WOLFSSL_FAILURE; + } + hint = (WOLFSSL_HEAP_HINT*)(buf + idx); + idx += sizeof(WOLFSSL_HEAP_HINT); + XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT)); + hint->memory = heap; + + if (*ctx && (*ctx)->heap == NULL) { + (*ctx)->heap = (void*)hint; + } + } + else { +#ifdef WOLFSSL_HEAP_TEST + /* do not load in memory if test has been set */ + if ((*ctx)->heap == (void*)WOLFSSL_HEAP_TEST) { + return WOLFSSL_SUCCESS; + } +#endif + hint = (WOLFSSL_HEAP_HINT*)((*ctx)->heap); + heap = hint->memory; + } + + if (wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap) != 1) { + WOLFSSL_MSG("Error partitioning memory"); + return WOLFSSL_FAILURE; + } + + /* create ctx if needed */ + if (*ctx == NULL) { + *ctx = wolfSSL_CTX_new_ex(method(hint), hint); + if (*ctx == NULL) { + WOLFSSL_MSG("Error creating ctx"); + return WOLFSSL_FAILURE; + } + } + + /* determine what max applies too */ + if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { + heap->maxIO = max; + } + else { /* general memory used in handshakes */ + heap->maxHa = max; + } + + heap->flag |= flag; + + (void)max; + (void)method; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats) +{ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + WOLFSSL_ENTER("wolfSSL_is_static_memory"); + + /* fill out statistics if wanted and WOLFMEM_TRACK_STATS flag */ + if (mem_stats != NULL && ssl->heap != NULL) { + WOLFSSL_HEAP_HINT* hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap)); + WOLFSSL_HEAP* heap = hint->memory; + if (heap->flag & WOLFMEM_TRACK_STATS && hint->stats != NULL) { + XMEMCPY(mem_stats, hint->stats, sizeof(WOLFSSL_MEM_CONN_STATS)); + } + } + + return (ssl->heap) ? 1 : 0; +} + + +int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + WOLFSSL_ENTER("wolfSSL_CTX_is_static_memory"); + + /* fill out statistics if wanted */ + if (mem_stats != NULL && ctx->heap != NULL) { + WOLFSSL_HEAP* heap = ((WOLFSSL_HEAP_HINT*)(ctx->heap))->memory; + if (wolfSSL_GetMemStats(heap, mem_stats) != 1) { + return MEMORY_E; + } + } + + return (ctx->heap) ? 1 : 0; +} + +#endif /* WOLFSSL_STATIC_MEMORY */ + + +/* return max record layer size plaintext input size */ +int wolfSSL_GetMaxOutputSize(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_GetMaxOutputSize"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (ssl->options.handShakeState != HANDSHAKE_DONE) { + WOLFSSL_MSG("Handshake not complete yet"); + return BAD_FUNC_ARG; + } + + return wolfSSL_GetMaxRecordSize(ssl, OUTPUT_RECORD_SIZE); +} + + +/* return record layer size of plaintext input size */ +int wolfSSL_GetOutputSize(WOLFSSL* ssl, int inSz) +{ + int maxSize; + + WOLFSSL_ENTER("wolfSSL_GetOutputSize"); + + if (inSz < 0) + return BAD_FUNC_ARG; + + maxSize = wolfSSL_GetMaxOutputSize(ssl); + if (maxSize < 0) + return maxSize; /* error */ + if (inSz > maxSize) + return INPUT_SIZE_E; + + return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0); +} + + +#ifdef HAVE_ECC +int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX* ctx, short keySz) +{ + if (ctx == NULL || keySz < 0 || keySz % 8 != 0) { + WOLFSSL_MSG("Key size must be divisible by 8 or ctx was null"); + return BAD_FUNC_ARG; + } + + ctx->minEccKeySz = keySz / 8; +#ifndef NO_CERTS + ctx->cm->minEccKeySz = keySz / 8; +#endif + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_SetMinEccKey_Sz(WOLFSSL* ssl, short keySz) +{ + if (ssl == NULL || keySz < 0 || keySz % 8 != 0) { + WOLFSSL_MSG("Key size must be divisible by 8 or ssl was null"); + return BAD_FUNC_ARG; + } + + ssl->options.minEccKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} + +#endif /* !NO_RSA */ + +#ifndef NO_RSA +int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX* ctx, short keySz) +{ + if (ctx == NULL || keySz < 0 || keySz % 8 != 0) { + WOLFSSL_MSG("Key size must be divisible by 8 or ctx was null"); + return BAD_FUNC_ARG; + } + + ctx->minRsaKeySz = keySz / 8; + ctx->cm->minRsaKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_SetMinRsaKey_Sz(WOLFSSL* ssl, short keySz) +{ + if (ssl == NULL || keySz < 0 || keySz % 8 != 0) { + WOLFSSL_MSG("Key size must be divisible by 8 or ssl was null"); + return BAD_FUNC_ARG; + } + + ssl->options.minRsaKeySz = keySz / 8; + 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) { - byte havePSK = 0; - byte haveRSA = 1; - WOLFSSL_ENTER("wolfSSL_SetTmpDH"); - if (ssl == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG; - if (pSz < ssl->options.minDhKeySz) + if (ssl == NULL || p == NULL || g == NULL) + return BAD_FUNC_ARG; + + if ((word16)pSz < ssl->options.minDhKeySz) + return DH_KEY_SIZE_E; + if ((word16)pSz > ssl->options.maxDhKeySz) return DH_KEY_SIZE_E; - if (ssl->options.side != WOLFSSL_SERVER_END) + /* this function is for server only */ + if (ssl->options.side == WOLFSSL_CLIENT_END) return SIDE_ERROR; - if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) - XFREE(ssl->buffers.serverDH_P.buffer, ssl->ctx->heap, DYNAMIC_TYPE_DH); - if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) - XFREE(ssl->buffers.serverDH_G.buffer, ssl->ctx->heap, DYNAMIC_TYPE_DH); + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + ssl->options.dhKeyTested = 0; + ssl->options.dhDoKeyTest = 1; + #endif + + 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; + } ssl->buffers.weOwnDH = 1; /* SSL owns now */ - ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->ctx->heap, - DYNAMIC_TYPE_DH); + ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_P.buffer == NULL) - return MEMORY_E; + return MEMORY_E; - ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->ctx->heap, - DYNAMIC_TYPE_DH); + ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_G.buffer == NULL) { - XFREE(ssl->buffers.serverDH_P.buffer, ssl->ctx->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; } @@ -469,40 +1761,108 @@ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz, XMEMCPY(ssl->buffers.serverDH_G.buffer, g, gSz); ssl->options.haveDH = 1; + + if (ssl->options.side != WOLFSSL_NEITHER_END) { + word16 havePSK; + word16 haveRSA; + int keySz = 0; + #ifndef NO_PSK havePSK = ssl->options.havePSK; + #else + havePSK = 0; #endif #ifdef NO_RSA haveRSA = 0; + #else + haveRSA = 1; #endif - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, ssl->options.haveDH, - ssl->options.haveNTRU, ssl->options.haveECDSAsig, - 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 */ + +#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) +/* Enables or disables the session's DH key prime test. */ +int wolfSSL_SetEnableDhKeyTest(WOLFSSL* ssl, int enable) +{ + WOLFSSL_ENTER("wolfSSL_SetEnableDhKeyTest"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (!enable) + ssl->options.dhDoKeyTest = 0; + else + ssl->options.dhDoKeyTest = 1; + + WOLFSSL_LEAVE("wolfSSL_SetEnableDhKeyTest", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; +} +#endif + + +/* 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) { WOLFSSL_ENTER("wolfSSL_CTX_SetTmpDH"); if (ctx == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG; - if (pSz < ctx->minDhKeySz) + if ((word16)pSz < ctx->minDhKeySz) + return DH_KEY_SIZE_E; + if ((word16)pSz > ctx->maxDhKeySz) 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); + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + { + DhKey checkKey; + WC_RNG rng; + int error, freeKey = 0; - ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap,DYNAMIC_TYPE_DH); + error = wc_InitRng(&rng); + if (!error) + error = wc_InitDhKey(&checkKey); + if (!error) { + freeKey = 1; + error = wc_DhSetCheckKey(&checkKey, + p, pSz, g, gSz, NULL, 0, 0, &rng); + } + if (freeKey) + wc_FreeDhKey(&checkKey); + wc_FreeRng(&rng); + if (error) + return error; + + ctx->dhKeyTested = 1; + } + #endif + + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ctx->serverDH_P.buffer = NULL; + XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ctx->serverDH_G.buffer = NULL; + + 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); + ctx->serverDH_P.buffer = NULL; return MEMORY_E; } @@ -515,12 +1875,62 @@ 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; +} + + +int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz) +{ + if (ctx == NULL || keySz > 16000 || keySz % 8 != 0) + return BAD_FUNC_ARG; + + ctx->minDhKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz) +{ + if (ssl == NULL || keySz > 16000 || keySz % 8 != 0) + return BAD_FUNC_ARG; + + ssl->options.minDhKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz) +{ + if (ctx == NULL || keySz > 16000 || keySz % 8 != 0) + return BAD_FUNC_ARG; + + ctx->maxDhKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_SetMaxDhKey_Sz(WOLFSSL* ssl, word16 keySz) +{ + if (ssl == NULL || keySz > 16000 || keySz % 8 != 0) + return BAD_FUNC_ARG; + + ssl->options.maxDhKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_GetDhKey_Sz(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + return (ssl->options.dhKeySz * 8); } #endif /* !NO_DH */ +WOLFSSL_ABI int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz) { int ret; @@ -530,21 +1940,64 @@ 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 != no_early_data && (ret = wolfSSL_negotiate(ssl)) < 0) { + ssl->error = ret; + return WOLFSSL_FATAL_ERROR; + } + ssl->earlyData = no_early_data; +#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 + #ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_WRITE, SSL_SUCCESS); + ssl->cbmode = SSL_CB_WRITE; + } + #endif ret = SendData(ssl, data, 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; @@ -554,25 +2007,55 @@ 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 + #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) + if (ssl->options.dtls) { ssl->dtls_expected_rx = max(sz + 100, MAX_MTU); +#ifdef WOLFSSL_SCTP + if (ssl->options.dtlsSctp) +#endif +#if defined(WOLLSSL_SCTP) || defined(WOLFSSL_DTLS_MTU) + ssl->dtls_expected_rx = max(ssl->dtls_expected_rx, ssl->dtlsMtuSz); +#endif + } #endif -#ifdef HAVE_MAX_FRAGMENT - ret = ReceiveData(ssl, (byte*)data, - min(sz, min(ssl->max_fragment, OUTPUT_RECORD_SIZE)), peek); -#else - ret = ReceiveData(ssl, (byte*)data, min(sz, OUTPUT_RECORD_SIZE), peek); + sz = wolfSSL_GetMaxRecordSize(ssl, sz); + + ret = ReceiveData(ssl, (byte*)data, sz, peek); + +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite) { + if (ssl->error != 0 && ssl->error != WANT_READ + #ifdef WOLFSSL_ASYNC_CRYPT + && ssl->error != WC_PENDING_E + #endif + ) { + 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; } @@ -586,58 +2069,106 @@ int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz) } +WOLFSSL_ABI int wolfSSL_read(WOLFSSL* ssl, void* data, int sz) { WOLFSSL_ENTER("wolfSSL_read()"); + #ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_READ, SSL_SUCCESS); + ssl->cbmode = SSL_CB_READ; + } + #endif return wolfSSL_read_internal(ssl, data, sz, FALSE); } -#ifdef HAVE_CAVIUM +#ifdef WOLFSSL_MULTICAST -/* let's use cavium, SSL_SUCCESS on ok */ -int wolfSSL_UseCavium(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 */ +WOLFSSL_ABI +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 cavium, SSL_SUCCESS on ok */ -int wolfSSL_CTX_UseCavium(WOLFSSL_CTX* ctx, int devId) +WOLFSSL_ABI +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 */ +WOLFSSL_ABI +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 /* HAVE_CAVIUM */ - #ifdef HAVE_SNI +WOLFSSL_ABI int wolfSSL_UseSNI(WOLFSSL* ssl, byte type, const void* data, word16 size) { if (ssl == NULL) return BAD_FUNC_ARG; - return TLSX_UseSNI(&ssl->extensions, type, data, size); + return TLSX_UseSNI(&ssl->extensions, type, data, size, ssl->heap); } -int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, byte type, const void* data, word16 size) + +WOLFSSL_ABI +int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, byte type, const void* data, + word16 size) { if (ctx == NULL) return BAD_FUNC_ARG; - return TLSX_UseSNI(&ctx->extensions, type, data, size); + return TLSX_UseSNI(&ctx->extensions, type, data, size, ctx->heap); } #ifndef NO_WOLFSSL_SERVER @@ -648,17 +2179,20 @@ void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, byte type, byte options) TLSX_SNI_SetOptions(ssl->extensions, type, options); } + void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, byte type, byte options) { if (ctx && ctx->extensions) TLSX_SNI_SetOptions(ctx->extensions, type, options); } + byte wolfSSL_SNI_Status(WOLFSSL* ssl, byte type) { return TLSX_SNI_Status(ssl ? ssl->extensions : NULL, type); } + word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data) { if (data) @@ -670,8 +2204,9 @@ word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data) return 0; } -int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, byte type, - byte* sni, word32* inOutSz) + +int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, + byte type, byte* sni, word32* inOutSz) { if (clientHello && helloSz > 0 && sni && inOutSz && *inOutSz > 0) return TLSX_SNI_GetFromBuffer(clientHello, helloSz, type, sni, inOutSz); @@ -684,49 +2219,155 @@ int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, byte type #endif /* HAVE_SNI */ +#ifdef HAVE_TRUSTED_CA + +WOLFSSL_API int wolfSSL_UseTrustedCA(WOLFSSL* ssl, byte type, + const byte* certId, word32 certIdSz) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (type == WOLFSSL_TRUSTED_CA_PRE_AGREED) { + if (certId != NULL || certIdSz != 0) + return BAD_FUNC_ARG; + } + else if (type == WOLFSSL_TRUSTED_CA_X509_NAME) { + if (certId == NULL || certIdSz == 0) + return BAD_FUNC_ARG; + } + #ifndef NO_SHA + else if (type == WOLFSSL_TRUSTED_CA_KEY_SHA1 || + type == WOLFSSL_TRUSTED_CA_CERT_SHA1) { + if (certId == NULL || certIdSz != WC_SHA_DIGEST_SIZE) + return BAD_FUNC_ARG; + } + #endif + else + return BAD_FUNC_ARG; + + return TLSX_UseTrustedCA(&ssl->extensions, + type, certId, certIdSz, ssl->heap); +} + +#endif /* HAVE_TRUSTED_CA */ + + #ifdef HAVE_MAX_FRAGMENT #ifndef NO_WOLFSSL_CLIENT + int wolfSSL_UseMaxFragment(WOLFSSL* ssl, byte mfl) { if (ssl == NULL) return BAD_FUNC_ARG; - return TLSX_UseMaxFragment(&ssl->extensions, mfl); +#ifdef WOLFSSL_ALLOW_MAX_FRAGMENT_ADJUST + /* The following is a non-standard way to reconfigure the max packet size + post-handshake for wolfSSL_write/woflSSL_read */ + if (ssl->options.handShakeState == HANDSHAKE_DONE) { + switch (mfl) { + case WOLFSSL_MFL_2_8 : ssl->max_fragment = 256; break; + case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break; + case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break; + case WOLFSSL_MFL_2_11: ssl->max_fragment = 2048; break; + case WOLFSSL_MFL_2_12: ssl->max_fragment = 4096; break; + case WOLFSSL_MFL_2_13: ssl->max_fragment = 8192; break; + default: ssl->max_fragment = MAX_RECORD_SIZE; break; + } + return WOLFSSL_SUCCESS; + } +#endif /* WOLFSSL_MAX_FRAGMENT_ADJUST */ + + /* This call sets the max fragment TLS extension, which gets sent to server. + The server_hello response is what sets the `ssl->max_fragment` in + TLSX_MFL_Parse */ + return TLSX_UseMaxFragment(&ssl->extensions, mfl, ssl->heap); } + int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, byte mfl) { if (ctx == NULL) return BAD_FUNC_ARG; - return TLSX_UseMaxFragment(&ctx->extensions, mfl); + return TLSX_UseMaxFragment(&ctx->extensions, mfl, ctx->heap); } + #endif /* NO_WOLFSSL_CLIENT */ #endif /* HAVE_MAX_FRAGMENT */ #ifdef HAVE_TRUNCATED_HMAC #ifndef NO_WOLFSSL_CLIENT + int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl) { if (ssl == NULL) return BAD_FUNC_ARG; - return TLSX_UseTruncatedHMAC(&ssl->extensions); + return TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap); } + int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx) { if (ctx == NULL) return BAD_FUNC_ARG; - return TLSX_UseTruncatedHMAC(&ctx->extensions); + return TLSX_UseTruncatedHMAC(&ctx->extensions, ctx->heap); } + #endif /* NO_WOLFSSL_CLIENT */ #endif /* HAVE_TRUNCATED_HMAC */ +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + +int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options) +{ + if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, + options, NULL, ssl->heap, ssl->devId); +} + + +int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type, + byte options) +{ + if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type, + options, NULL, ctx->heap, ctx->devId); +} + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + +int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options) +{ + if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type, + options, ssl->heap, ssl->devId); +} + + +int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, byte status_type, + byte options) +{ + if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type, + options, ctx->heap, ctx->devId); +} + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + /* Elliptic Curves */ -#ifdef HAVE_SUPPORTED_CURVES -#ifndef NO_WOLFSSL_CLIENT +#if defined(HAVE_SUPPORTED_CURVES) && !defined(NO_WOLFSSL_CLIENT) int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name) { @@ -734,44 +2375,238 @@ int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name) return BAD_FUNC_ARG; switch (name) { + case WOLFSSL_ECC_SECP160K1: case WOLFSSL_ECC_SECP160R1: + case WOLFSSL_ECC_SECP160R2: + case WOLFSSL_ECC_SECP192K1: case WOLFSSL_ECC_SECP192R1: + case WOLFSSL_ECC_SECP224K1: case WOLFSSL_ECC_SECP224R1: + case WOLFSSL_ECC_SECP256K1: case WOLFSSL_ECC_SECP256R1: case WOLFSSL_ECC_SECP384R1: case WOLFSSL_ECC_SECP521R1: + case WOLFSSL_ECC_BRAINPOOLP256R1: + case WOLFSSL_ECC_BRAINPOOLP384R1: + case WOLFSSL_ECC_BRAINPOOLP512R1: + case WOLFSSL_ECC_X25519: + case WOLFSSL_ECC_X448: + + case WOLFSSL_FFDHE_2048: + case WOLFSSL_FFDHE_3072: + case WOLFSSL_FFDHE_4096: + case WOLFSSL_FFDHE_6144: + case WOLFSSL_FFDHE_8192: break; default: return BAD_FUNC_ARG; } - return TLSX_UseSupportedCurve(&ssl->extensions, name); + ssl->options.userCurves = 1; + + return TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap); } + int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name) { if (ctx == NULL) return BAD_FUNC_ARG; switch (name) { + case WOLFSSL_ECC_SECP160K1: case WOLFSSL_ECC_SECP160R1: + case WOLFSSL_ECC_SECP160R2: + case WOLFSSL_ECC_SECP192K1: case WOLFSSL_ECC_SECP192R1: + case WOLFSSL_ECC_SECP224K1: case WOLFSSL_ECC_SECP224R1: + case WOLFSSL_ECC_SECP256K1: case WOLFSSL_ECC_SECP256R1: case WOLFSSL_ECC_SECP384R1: case WOLFSSL_ECC_SECP521R1: + case WOLFSSL_ECC_BRAINPOOLP256R1: + case WOLFSSL_ECC_BRAINPOOLP384R1: + case WOLFSSL_ECC_BRAINPOOLP512R1: + case WOLFSSL_ECC_X25519: + case WOLFSSL_ECC_X448: + case WOLFSSL_FFDHE_2048: + case WOLFSSL_FFDHE_3072: + case WOLFSSL_FFDHE_4096: + case WOLFSSL_FFDHE_6144: + case WOLFSSL_FFDHE_8192: break; default: return BAD_FUNC_ARG; } - return TLSX_UseSupportedCurve(&ctx->extensions, name); + ctx->userCurves = 1; + + return TLSX_UseSupportedCurve(&ctx->extensions, name, ctx->heap); } +#endif /* HAVE_SUPPORTED_CURVES && !NO_WOLFSSL_CLIENT */ + +/* QSH quantum safe handshake */ +#ifdef HAVE_QSH +/* returns 1 if QSH has been used 0 otherwise */ +int wolfSSL_isQSH(WOLFSSL* ssl) +{ + /* if no ssl struct than QSH was not used */ + if (ssl == NULL) + return 0; + + return ssl->isQSH; +} + + +int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, word16 name) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + switch (name) { + #ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + break; + #endif + default: + return BAD_FUNC_ARG; + } + + ssl->user_set_QSHSchemes = 1; + + return TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0, ssl->heap); +} + +#ifndef NO_WOLFSSL_CLIENT + /* user control over sending client public key in hello + when flag = 1 will send keys if flag is 0 or function is not called + then will not send keys in the hello extension + return 0 on success + */ + int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag) + { + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->sendQSHKeys = flag; + + return 0; + } #endif /* NO_WOLFSSL_CLIENT */ -#endif /* HAVE_SUPPORTED_CURVES */ +#endif /* HAVE_QSH */ + +/* Application-Layer Protocol Negotiation */ +#ifdef HAVE_ALPN + +WOLFSSL_ABI +int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, + word32 protocol_name_listSz, byte options) +{ + char *list, *ptr, *token[WOLFSSL_MAX_ALPN_NUMBER]={NULL}; + word16 len; + int idx = 0; + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_UseALPN"); + + if (ssl == NULL || protocol_name_list == NULL) + return BAD_FUNC_ARG; + + if (protocol_name_listSz > (WOLFSSL_MAX_ALPN_NUMBER * + WOLFSSL_MAX_ALPN_PROTO_NAME_LEN + + WOLFSSL_MAX_ALPN_NUMBER)) { + WOLFSSL_MSG("Invalid arguments, protocol name list too long"); + return BAD_FUNC_ARG; + } + + if (!(options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) && + !(options & WOLFSSL_ALPN_FAILED_ON_MISMATCH)) { + WOLFSSL_MSG("Invalid arguments, options not supported"); + return BAD_FUNC_ARG; + } + + + list = (char *)XMALLOC(protocol_name_listSz+1, ssl->heap, + DYNAMIC_TYPE_ALPN); + if (list == NULL) { + WOLFSSL_MSG("Memory failure"); + return MEMORY_ERROR; + } + + XSTRNCPY(list, protocol_name_list, protocol_name_listSz); + list[protocol_name_listSz] = '\0'; + + /* read all protocol name from the list */ + token[idx] = XSTRTOK(list, ",", &ptr); + while (idx < WOLFSSL_MAX_ALPN_NUMBER && token[idx] != NULL) + token[++idx] = XSTRTOK(NULL, ",", &ptr); + + /* add protocol name list in the TLS extension in reverse order */ + while ((idx--) > 0) { + len = (word16)XSTRLEN(token[idx]); + + ret = TLSX_UseALPN(&ssl->extensions, token[idx], len, options, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("TLSX_UseALPN failure"); + break; + } + } + + XFREE(list, ssl->heap, DYNAMIC_TYPE_ALPN); + + return ret; +} + +int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name, word16 *size) +{ + return TLSX_ALPN_GetRequest(ssl ? ssl->extensions : NULL, + (void **)protocol_name, size); +} + +int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, word16 *listSz) +{ + if (list == NULL || listSz == NULL) + return BAD_FUNC_ARG; + + if (ssl->alpn_client_list == NULL) + return BUFFER_ERROR; + + *listSz = (word16)XSTRLEN(ssl->alpn_client_list); + if (*listSz == 0) + return BUFFER_ERROR; + + *list = (char *)XMALLOC((*listSz)+1, ssl->heap, DYNAMIC_TYPE_TLSX); + if (*list == NULL) + return MEMORY_ERROR; + + XSTRNCPY(*list, ssl->alpn_client_list, (*listSz)+1); + (*list)[*listSz] = 0; + + return WOLFSSL_SUCCESS; +} + + +/* used to free memory allocated by wolfSSL_ALPN_GetPeerProtocol */ +int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list) +{ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + XFREE(*list, ssl->heap, DYNAMIC_TYPE_TLSX); + *list = NULL; + + return WOLFSSL_SUCCESS; +} + +#endif /* HAVE_ALPN */ /* Secure Renegotiation */ #ifdef HAVE_SECURE_RENEGOTIATION @@ -782,11 +2617,11 @@ int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl) int ret = BAD_FUNC_ARG; if (ssl) - ret = TLSX_UseSecureRenegotiation(&ssl->extensions); + ret = TLSX_UseSecureRenegotiation(&ssl->extensions, ssl->heap); + + if (ret == WOLFSSL_SUCCESS) { + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO); - if (ret == SSL_SUCCESS) { - TLSX* extension = TLSX_Find(ssl->extensions, SECURE_RENEGOTIATION); - if (extension) ssl->secure_renegotiation = (SecureRenegotiation*)extension->data; } @@ -794,9 +2629,18 @@ int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl) return ret; } +int wolfSSL_CTX_UseSecureRenegotiation(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->useSecureReneg = 1; + return WOLFSSL_SUCCESS; +} + /* do a secure renegotiation handshake, user forced, we discourage */ -int wolfSSL_Rehandshake(WOLFSSL* ssl) +static int _Rehandshake(WOLFSSL* ssl) { int ret; @@ -813,67 +2657,120 @@ int wolfSSL_Rehandshake(WOLFSSL* ssl) return SECURE_RENEGOTIATION_E; } - if (ssl->options.handShakeState != HANDSHAKE_DONE) { - WOLFSSL_MSG("Can't renegotiate until previous handshake complete"); - return SECURE_RENEGOTIATION_E; - } + /* If the client started the renegotiation, the server will already + * have processed the client's hello. */ + if (ssl->options.side != WOLFSSL_SERVER_END || + ssl->options.acceptState != ACCEPT_FIRST_REPLY_DONE) { + + if (ssl->options.handShakeState != HANDSHAKE_DONE) { + WOLFSSL_MSG("Can't renegotiate until previous handshake complete"); + return SECURE_RENEGOTIATION_E; + } #ifndef NO_FORCE_SCR_SAME_SUITE - /* force same suite */ - if (ssl->suites) { - ssl->suites->suiteSz = SUITE_LEN; - ssl->suites->suites[0] = ssl->options.cipherSuite0; - ssl->suites->suites[1] = ssl->options.cipherSuite; + /* force same suite */ + if (ssl->suites) { + ssl->suites->suiteSz = SUITE_LEN; + ssl->suites->suites[0] = ssl->options.cipherSuite0; + ssl->suites->suites[1] = ssl->options.cipherSuite; + } +#endif + + /* reset handshake states */ + ssl->options.sendVerify = 0; + ssl->options.serverState = NULL_STATE; + ssl->options.clientState = NULL_STATE; + ssl->options.connectState = CONNECT_BEGIN; + ssl->options.acceptState = ACCEPT_BEGIN_RENEG; + ssl->options.handShakeState = NULL_STATE; + ssl->options.processReply = 0; /* TODO, move states in internal.h */ + + XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); + + ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; + +#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SERVER_RENEGOTIATION_INFO) + if (ssl->options.side == WOLFSSL_SERVER_END) { + ret = SendHelloRequest(ssl); + if (ret != 0) { + ssl->error = ret; + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* NO_WOLFSSL_SERVER && HAVE_SERVER_RENEGOTIATION_INFO */ + + ret = InitHandshakeHashes(ssl); + if (ret != 0) { + ssl->error = ret; + return WOLFSSL_FATAL_ERROR; + } } -#endif - - /* reset handshake 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 = 0; /* TODO, move states in internal.h */ - - XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); - - 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); - 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); + ssl->secure_rene_count++; return ret; } + +/* do a secure renegotiation handshake, user forced, we discourage */ +int wolfSSL_Rehandshake(WOLFSSL* ssl) +{ + int ret = WOLFSSL_SUCCESS; + WOLFSSL_ENTER("wolfSSL_Rehandshake"); + + if (ssl->options.side == WOLFSSL_SERVER_END) { + /* Reset option to send certificate verify. */ + ssl->options.sendVerify = 0; + } + else { + /* Reset resuming flag to do full secure handshake. */ + ssl->options.resuming = 0; + #ifdef HAVE_SESSION_TICKET + /* Clearing the ticket. */ + ret = wolfSSL_UseSessionTicket(ssl); + #endif + } + + if (ret == WOLFSSL_SUCCESS) + ret = _Rehandshake(ssl); + + return ret; +} + + +#ifndef NO_WOLFSSL_CLIENT + +/* do a secure resumption handshake, user forced, we discourage */ +int wolfSSL_SecureResume(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_SecureResume"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (ssl->options.side == WOLFSSL_SERVER_END) { + ssl->error = SIDE_ERROR; + return SSL_FATAL_ERROR; + } + + return _Rehandshake(ssl); +} + +#endif /* NO_WOLFSSL_CLIENT */ + +long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_SSL_get_secure_renegotiation_support"); + + if (!ssl || !ssl->secure_renegotiation) + return WOLFSSL_FAILURE; + return ssl->secure_renegotiation->enabled; +} + #endif /* HAVE_SECURE_RENEGOTIATION */ /* 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) @@ -881,10 +2778,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) @@ -892,10 +2789,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) @@ -903,7 +2800,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) */ @@ -915,7 +2812,7 @@ int wolfSSL_UseSessionTicket(WOLFSSL* ssl) if (ssl == NULL) return BAD_FUNC_ARG; - return TLSX_UseSessionTicket(&ssl->extensions, NULL); + return TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap); } int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx) @@ -923,10 +2820,11 @@ int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx) if (ctx == NULL) return BAD_FUNC_ARG; - return TLSX_UseSessionTicket(&ctx->extensions, NULL); + return TLSX_UseSessionTicket(&ctx->extensions, NULL, ctx->heap); } -WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl, byte* buf, word32* bufSz) +WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl, + byte* buf, word32* bufSz) { if (ssl == NULL || buf == NULL || bufSz == NULL || *bufSz == 0) return BAD_FUNC_ARG; @@ -938,19 +2836,43 @@ WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl, byte* buf, word32* bufSz 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; - if (bufSz > 0) + if (bufSz > 0) { + /* Ticket will fit into static ticket */ + if(bufSz <= SESSION_TICKET_LEN) { + if (ssl->session.isDynamic) { + XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ssl->session.isDynamic = 0; + ssl->session.ticket = ssl->session.staticTicket; + } + } else { /* Ticket requires dynamic ticket storage */ + if (ssl->session.ticketLen < bufSz) { /* is dyn buffer big enough */ + if(ssl->session.isDynamic) + XFREE(ssl->session.ticket, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + if(!ssl->session.ticket) { + ssl->session.ticket = ssl->session.staticTicket; + ssl->session.isDynamic = 0; + return MEMORY_ERROR; + } + ssl->session.isDynamic = 1; + } + } XMEMCPY(ssl->session.ticket, buf, bufSz); + } ssl->session.ticketLen = (word16)bufSz; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -963,10 +2885,39 @@ 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 + +#ifdef HAVE_EXTENDED_MASTER +#ifndef NO_WOLFSSL_CLIENT + +int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->haveEMS = 0; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.haveEMS = 0; + + return WOLFSSL_SUCCESS; +} + +#endif +#endif + + #ifndef WOLFSSL_LEANPSK int wolfSSL_send(WOLFSSL* ssl, const void* data, int sz, int flags) @@ -1014,63 +2965,97 @@ int wolfSSL_recv(WOLFSSL* ssl, void* data, int sz, int flags) #endif -/* SSL_SUCCESS on ok */ +/* WOLFSSL_SUCCESS on ok */ +WOLFSSL_ABI int wolfSSL_shutdown(WOLFSSL* ssl) { - int ret = SSL_FATAL_ERROR; - byte tmp; + int ret = WOLFSSL_FATAL_ERROR; 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; - } +#ifdef WOLFSSL_SHUTDOWNONCE + if (ssl->options.isClosed || ssl->options.connReset) { + /* Shutdown has already occurred. + * Caller is free to ignore this error. */ + return SSL_SHUTDOWN_ALREADY_DONE_E; + } +#endif - /* call wolfSSL_shutdown again for bidirectional shudown */ - 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 = ProcessReply(ssl); + if (ret == ZERO_RETURN) { + /* simulate OpenSSL behavior */ + ssl->error = WOLFSSL_ERROR_SYSCALL; + ret = WOLFSSL_SUCCESS; + } else if (ssl->error == WOLFSSL_ERROR_NONE) { + ret = WOLFSSL_SHUTDOWN_NOT_DONE; + } else { + WOLFSSL_ERROR(ssl->error); + ret = WOLFSSL_FATAL_ERROR; + } } } +#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; } +/* get current error state value */ +int wolfSSL_state(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + return ssl->error; +} + + +WOLFSSL_ABI 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; @@ -1078,24 +3063,38 @@ 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 */ +/* retrieve 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; } +#ifdef OPENSSL_EXTRA +/* returns SSL_WRITING, SSL_READING or SSL_NOTHING */ +int wolfSSL_want(WOLFSSL* ssl) +{ + int rw_state = SSL_NOTHING; + if (ssl) { + if (ssl->error == WANT_READ) + rw_state = SSL_READING; + else if (ssl->error == WANT_WRITE) + rw_state = SSL_WRITING; + } + return rw_state; +} +#endif /* return TRUE if current error is want read */ int wolfSSL_want_read(WOLFSSL* ssl) @@ -1121,7 +3120,7 @@ int wolfSSL_want_write(WOLFSSL* ssl) char* wolfSSL_ERR_error_string(unsigned long errNumber, char* data) { - static const char* msg = "Please supply a buffer for error string"; + static wcchar msg = "Please supply a buffer for error string"; WOLFSSL_ENTER("ERR_error_string"); if (data) { @@ -1168,9 +3167,70 @@ 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) { +#ifndef WOLFSSL_AEAD_ONLY if (ssl == NULL) return NULL; @@ -1179,6 +3239,12 @@ const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify) return ssl->keys.client_write_MAC_secret; else return ssl->keys.server_write_MAC_secret; +#else + (void)ssl; + (void)verify; + + return NULL; +#endif } @@ -1229,6 +3295,86 @@ void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl) return NULL; } +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) +/** + * Set the callback, against the context, that encrypts then MACs. + * + * ctx SSL/TLS context. + * cb Callback function to use with Encrypt-Then-MAC. + */ +void wolfSSL_CTX_SetEncryptMacCb(WOLFSSL_CTX* ctx, CallbackEncryptMac cb) +{ + if (ctx) + ctx->EncryptMacCb = cb; +} + +/** + * Set the context to use with callback that encrypts then MACs. + * + * ssl SSL/TLS object. + * ctx Callback function's context. + */ +void wolfSSL_SetEncryptMacCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->EncryptMacCtx = ctx; +} + +/** + * Get the context being used with callback that encrypts then MACs. + * + * ssl SSL/TLS object. + * returns callback function's context or NULL if SSL/TLS object is NULL. + */ +void* wolfSSL_GetEncryptMacCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EncryptMacCtx; + + return NULL; +} + + +/** + * Set the callback, against the context, that MAC verifies then decrypts. + * + * ctx SSL/TLS context. + * cb Callback function to use with Encrypt-Then-MAC. + */ +void wolfSSL_CTX_SetVerifyDecryptCb(WOLFSSL_CTX* ctx, CallbackVerifyDecrypt cb) +{ + if (ctx) + ctx->VerifyDecryptCb = cb; +} + +/** + * Set the context to use with callback that MAC verifies then decrypts. + * + * ssl SSL/TLS object. + * ctx Callback function's context. + */ +void wolfSSL_SetVerifyDecryptCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->VerifyDecryptCtx = ctx; +} + +/** + * Get the context being used with callback that MAC verifies then decrypts. + * + * ssl SSL/TLS object. + * returns callback function's context or NULL if SSL/TLS object is NULL. + */ +void* wolfSSL_GetVerifyDecryptCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->VerifyDecryptCtx; + + return NULL; +} +#endif /* HAVE_ENCRYPT_THEN_MAC !WOLFSSL_AEAD_ONLY */ + + const byte* wolfSSL_GetClientWriteKey(WOLFSSL* ssl) { @@ -1265,7 +3411,6 @@ const byte* wolfSSL_GetServerWriteIV(WOLFSSL* ssl) return NULL; } - int wolfSSL_GetKeySize(WOLFSSL* ssl) { if (ssl) @@ -1298,10 +3443,12 @@ int wolfSSL_GetCipherType(WOLFSSL* ssl) if (ssl == NULL) return BAD_FUNC_ARG; +#ifndef WOLFSSL_AEAD_ONLY if (ssl->specs.cipher_type == block) return WOLFSSL_BLOCK_TYPE; if (ssl->specs.cipher_type == stream) return WOLFSSL_STREAM_TYPE; +#endif if (ssl->specs.cipher_type == aead) return WOLFSSL_AEAD_TYPE; @@ -1361,28 +3508,59 @@ int wolfSSL_GetHmacSize(WOLFSSL* ssl) #ifndef NO_CERTS -WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void) +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) +{ + WOLFSSL_CERT_MANAGER* cm; WOLFSSL_ENTER("wolfSSL_CertManagerNew"); - cm = (WOLFSSL_CERT_MANAGER*) XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), 0, - DYNAMIC_TYPE_CERT_MANAGER); + cm = (WOLFSSL_CERT_MANAGER*) XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap, + DYNAMIC_TYPE_CERT_MANAGER); if (cm) { XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER)); - if (InitMutex(&cm->caLock) != 0) { + if (wc_InitMutex(&cm->caLock) != 0) { WOLFSSL_MSG("Bad mutex init"); wolfSSL_CertManagerFree(cm); return NULL; } + + #ifdef WOLFSSL_TRUST_PEER_CERT + if (wc_InitMutex(&cm->tpLock) != 0) { + WOLFSSL_MSG("Bad mutex init"); + wolfSSL_CertManagerFree(cm); + return NULL; + } + #endif + + /* set default minimum key size allowed */ + #ifndef NO_RSA + cm->minRsaKeySz = MIN_RSAKEY_SZ; + #endif + #ifdef HAVE_ECC + cm->minEccKeySz = MIN_ECCKEY_SZ; + #endif + cm->heap = heap; } return cm; } +WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void) +{ + return wolfSSL_CertManagerNew_ex(NULL); +} + + void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm) { WOLFSSL_ENTER("wolfSSL_CertManagerFree"); @@ -1395,14 +3573,222 @@ 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(NO_WOLFSSL_SERVER) && \ + (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ + defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) + if (cm->ocsp_stapling) + FreeOCSP(cm->ocsp_stapling, 1); #endif - FreeSignerTable(cm->caTable, CA_TABLE_SIZE, NULL); - FreeMutex(&cm->caLock); - XFREE(cm, NULL, DYNAMIC_TYPE_CERT_MANAGER); + #endif + FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap); + wc_FreeMutex(&cm->caLock); + + #ifdef WOLFSSL_TRUST_PEER_CERT + FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap); + wc_FreeMutex(&cm->tpLock); + #endif + + XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER); } } +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) +#if defined(WOLFSSL_SIGNER_DER_CERT) +/****************************************************************************** +* wolfSSL_CertManagerGetCerts - retrieve stack of X509 certificates in a +* certificate manager (CM). +* +* RETURNS: +* returns stack of X509 certs on success, otherwise returns a NULL. +*/ +WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_STACK* sk = NULL; + Signer* signers = NULL; + word32 row = 0; + DecodedCert* dCert = NULL; + WOLFSSL_X509* x509 = NULL; + int found = 0; + + if (cm == NULL) + return NULL; + + sk = wolfSSL_sk_X509_new(); + + if (sk == NULL) { + return NULL; + } + + if (wc_LockMutex(&cm->caLock) != 0) { + goto error_init; + } + + for (row = 0; row < CA_TABLE_SIZE; row++) { + signers = cm->caTable[row]; + while (signers && signers->derCert && signers->derCert->buffer) { + + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap, + DYNAMIC_TYPE_DCERT); + if (dCert == NULL) { + goto error; + } + + XMEMSET(dCert, 0, sizeof(DecodedCert)); + + InitDecodedCert(dCert, signers->derCert->buffer, + signers->derCert->length, cm->heap); + + /* Parse Certificate */ + if (ParseCert(dCert, CERT_TYPE, NO_VERIFY, cm)) { + goto error; + } + + x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), cm->heap, + DYNAMIC_TYPE_X509); + + if (x509 == NULL) { + goto error; + } + + InitX509(x509, 1, NULL); + + if (CopyDecodedToX509(x509, dCert) == 0) { + + if (wolfSSL_sk_X509_push(sk, x509) != SSL_SUCCESS) { + WOLFSSL_MSG("Unable to load x509 into stack"); + FreeX509(x509); + XFREE(x509, cm->heap, DYNAMIC_TYPE_X509); + goto error; + } + } + else { + goto error; + } + + found = 1; + + signers = signers->next; + + FreeDecodedCert(dCert); + XFREE(dCert, cm->heap, DYNAMIC_TYPE_DCERT); + dCert = NULL; + } + } + wc_UnLockMutex(&cm->caLock); + + if (!found) { + goto error_init; + } + + return sk; + +error: + wc_UnLockMutex(&cm->caLock); + +error_init: + + if (dCert) { + FreeDecodedCert(dCert); + XFREE(dCert, cm->heap, DYNAMIC_TYPE_DCERT); + } + + if (sk) + wolfSSL_sk_X509_free(sk); + + return NULL; +} +#endif /* WOLFSSL_SIGNER_DER_CERT */ + +/****************************************************************************** +* wolfSSL_X509_STORE_GetCerts - retrieve stack of X509 in a certificate store ctx +* +* This API can be used in SSL verify callback function to view cert chain +* See examples/client/client.c and myVerify() function in test.h +* +* RETURNS: +* returns stack of X509 certs on success, otherwise returns a NULL. +*/ +WOLFSSL_STACK* wolfSSL_X509_STORE_GetCerts(WOLFSSL_X509_STORE_CTX* s) +{ + int certIdx = 0; + WOLFSSL_BUFFER_INFO* cert = NULL; + DecodedCert* dCert = NULL; + WOLFSSL_X509* x509 = NULL; + WOLFSSL_STACK* sk = NULL; + int found = 0; + + if (s == NULL) { + return NULL; + } + + sk = wolfSSL_sk_X509_new(); + + if (sk == NULL) { + return NULL; + } + + for (certIdx = s->totalCerts - 1; certIdx >= 0; certIdx--) { + /* get certificate buffer */ + cert = &s->certs[certIdx]; + + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); + + if (dCert == NULL) { + goto error; + } + XMEMSET(dCert, 0, sizeof(DecodedCert)); + + InitDecodedCert(dCert, cert->buffer, cert->length, NULL); + + /* Parse Certificate */ + if (ParseCert(dCert, CERT_TYPE, NO_VERIFY, NULL)){ + goto error; + } + x509 = wolfSSL_X509_new(); + + if (x509 == NULL) { + goto error; + } + InitX509(x509, 1, NULL); + + if (CopyDecodedToX509(x509, dCert) == 0) { + + if (wolfSSL_sk_X509_push(sk, x509) != SSL_SUCCESS) { + WOLFSSL_MSG("Unable to load x509 into stack"); + wolfSSL_X509_free(x509); + goto error; + } + } + else { + goto error; + } + found = 1; + + FreeDecodedCert(dCert); + XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT); + dCert = NULL; + } + + if (!found) { + wolfSSL_sk_X509_free(sk); + sk = NULL; + } + return sk; + +error: + if (dCert) { + FreeDecodedCert(dCert); + XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT); + } + + if (sk) + wolfSSL_sk_X509_free(sk); + + return NULL; +} +#endif /* OPENSSL_EXTRA && !NO_FILESYSTEM */ /* Unload the CA signer list */ int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm) @@ -1412,184 +3798,43 @@ int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm) if (cm == NULL) return BAD_FUNC_ARG; - if (LockMutex(&cm->caLock) != 0) + if (wc_LockMutex(&cm->caLock) != 0) return BAD_MUTEX_E; - FreeSignerTable(cm->caTable, CA_TABLE_SIZE, NULL); + FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap); - UnLockMutex(&cm->caLock); + wc_UnLockMutex(&cm->caLock); - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -/* Return bytes written to buff or < 0 for error */ -int wolfSSL_CertPemToDer(const unsigned char* pem, int pemSz, - unsigned char* buff, int buffSz, - int type) +#ifdef WOLFSSL_TRUST_PEER_CERT +int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm) { - int eccKey = 0; - int ret; - buffer der; -#ifdef WOLFSSL_SMALL_STACK - EncryptedInfo* info = NULL; -#else - EncryptedInfo info[1]; -#endif + WOLFSSL_ENTER("wolfSSL_CertManagerUnload_trust_peers"); - WOLFSSL_ENTER("wolfSSL_CertPemToDer"); - - if (pem == NULL || buff == NULL || buffSz <= 0) { - WOLFSSL_MSG("Bad pem der args"); + if (cm == NULL) return BAD_FUNC_ARG; - } - if (type != CERT_TYPE && type != CA_TYPE && type != CERTREQ_TYPE) { - WOLFSSL_MSG("Bad cert type"); - return BAD_FUNC_ARG; - } + if (wc_LockMutex(&cm->tpLock) != 0) + return BAD_MUTEX_E; -#ifdef WOLFSSL_SMALL_STACK - info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (info == NULL) - return MEMORY_E; -#endif + FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap); - info->set = 0; - info->ctx = NULL; - info->consumed = 0; - der.buffer = NULL; + wc_UnLockMutex(&cm->tpLock); - ret = PemToDer(pem, pemSz, type, &der, NULL, info, &eccKey); -#ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - 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; - } - } - - XFREE(der.buffer, NULL, DYNAMIC_TYPE_KEY); - - return ret; + return WOLFSSL_SUCCESS; } +#endif /* WOLFSSL_TRUST_PEER_CERT */ - -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - -/* our KeyPemToDer password callback, password in userData */ -static INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata) -{ - (void)rw; - - if (userdata == NULL) - return 0; - - XSTRNCPY(passwd, (char*)userdata, sz); - return min((word32)sz, (word32)XSTRLEN((char*)userdata)); -} - -#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ - - -/* Return bytes written to buff or < 0 for error */ -int wolfSSL_KeyPemToDer(const unsigned char* pem, int pemSz, unsigned char* buff, - int buffSz, const char* pass) -{ - int eccKey = 0; - int ret; - buffer der; -#ifdef WOLFSSL_SMALL_STACK - EncryptedInfo* info = NULL; -#else - EncryptedInfo info[1]; -#endif - - (void)pass; - - WOLFSSL_ENTER("wolfSSL_KeyPemToDer"); - - if (pem == NULL || buff == NULL || buffSz <= 0) { - WOLFSSL_MSG("Bad pem der args"); - return BAD_FUNC_ARG; - } - -#ifdef WOLFSSL_SMALL_STACK - info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (info == NULL) - return MEMORY_E; -#endif - - info->set = 0; - info->ctx = NULL; - info->consumed = 0; - der.buffer = NULL; - -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - if (pass) { - info->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); - if (info->ctx == NULL) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return MEMORY_E; - } - - wolfSSL_CTX_set_default_passwd_cb(info->ctx, OurPasswordCb); - wolfSSL_CTX_set_default_passwd_cb_userdata(info->ctx, (void*)pass); - } -#endif - - ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, info, &eccKey); - - if (info->ctx) - wolfSSL_CTX_free(info->ctx); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - 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; - } - } - - XFREE(der.buffer, NULL, DYNAMIC_TYPE_KEY); - - return ret; -} - - -#endif /* !NO_CERTS */ - - +#endif /* NO_CERTS */ #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) -void wolfSSL_ERR_print_errors_fp(FILE* fp, int err) +void wolfSSL_ERR_print_errors_fp(XFILE fp, int err) { char data[WOLFSSL_MAX_ERROR_SZ + 1]; @@ -1598,9 +3843,21 @@ void wolfSSL_ERR_print_errors_fp(FILE* fp, int err) fprintf(fp, "%s", data); } +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +void wolfSSL_ERR_dump_errors_fp(XFILE fp) +{ + wc_ERR_print_errors_fp(fp); +} + +void wolfSSL_ERR_print_errors_cb (int (*cb)(const char *str, size_t len, + void *u), void *u) +{ + wc_ERR_print_errors_cb(cb, u); +} +#endif #endif - +WOLFSSL_ABI int wolfSSL_pending(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_pending"); @@ -1609,7 +3866,7 @@ int wolfSSL_pending(WOLFSSL* ssl) #ifndef WOLFSSL_LEANPSK -/* trun on handshake group messages for context */ +/* turn on handshake group messages for context */ int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX* ctx) { if (ctx == NULL) @@ -1617,7 +3874,7 @@ int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX* ctx) ctx->groupMessages = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif @@ -1629,7 +3886,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); @@ -1641,7 +3898,7 @@ int wolfSSL_connect_cert(WOLFSSL* ssl) #ifndef WOLFSSL_LEANPSK -/* trun on handshake group messages for ssl object */ +/* turn on handshake group messages for ssl object */ int wolfSSL_set_group_messages(WOLFSSL* ssl) { if (ssl == NULL) @@ -1649,15 +3906,19 @@ int wolfSSL_set_group_messages(WOLFSSL* ssl) ssl->options.groupMessages = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } -/* make minVersion the internal equivilant SSL version */ +/* make minVersion the internal equivalent SSL version */ static int SetMinVersionHelper(byte* minVersion, int version) { +#ifdef NO_TLS + (void)minVersion; +#endif + switch (version) { -#ifndef NO_OLD_TLS +#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) case WOLFSSL_SSLV3: *minVersion = SSLv3_MINOR; break; @@ -1665,29 +3926,39 @@ static int SetMinVersionHelper(byte* minVersion, int version) #ifndef NO_TLS #ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 case WOLFSSL_TLSV1: *minVersion = TLSv1_MINOR; break; + #endif case WOLFSSL_TLSV1_1: *minVersion = TLSv1_1_MINOR; break; #endif + #ifndef WOLFSSL_NO_TLS12 case WOLFSSL_TLSV1_2: *minVersion = TLSv1_2_MINOR; break; + #endif #endif + #ifdef WOLFSSL_TLS13 + case WOLFSSL_TLSV1_3: + *minVersion = TLSv1_3_MINOR; + break; + #endif default: WOLFSSL_MSG("Bad function argument"); 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 */ +WOLFSSL_ABI int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version) { WOLFSSL_ENTER("wolfSSL_CTX_SetMinVersion"); @@ -1701,7 +3972,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"); @@ -1715,10 +3986,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) { - byte haveRSA = 1; - byte havePSK = 0; + word16 haveRSA = 1; + word16 havePSK = 0; + int keySz = 0; WOLFSSL_ENTER("wolfSSL_SetVersion"); @@ -1728,7 +4026,7 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version) } switch (version) { -#ifndef NO_OLD_TLS +#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) case WOLFSSL_SSLV3: ssl->version = MakeSSLv3(); break; @@ -1736,17 +4034,27 @@ 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(); break; #endif + #ifndef WOLFSSL_NO_TLS12 case WOLFSSL_TLSV1_2: ssl->version = MakeTLSv1_2(); break; + #endif +#endif +#ifdef WOLFSSL_TLS13 + case WOLFSSL_TLSV1_3: + ssl->version = MakeTLSv1_3(); + break; + #endif default: @@ -1760,12 +4068,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.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 */ @@ -1773,10 +4085,10 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version) #if !defined(NO_CERTS) || !defined(NO_SESSION_CACHE) /* Make a work from the front of random hash */ -static INLINE word32 MakeWordFromHash(const byte* hashID) +static WC_INLINE word32 MakeWordFromHash(const byte* hashID) { - return (hashID[0] << 24) | (hashID[1] << 16) | (hashID[2] << 8) | - hashID[3]; + return ((word32)hashID[0] << 24) | ((word32)hashID[1] << 16) | + (hashID[2] << 8) | hashID[3]; } #endif /* !NO_CERTS || !NO_SESSION_CACHE */ @@ -1785,7 +4097,7 @@ static INLINE word32 MakeWordFromHash(const byte* hashID) #ifndef NO_CERTS /* hash is the SHA digest of name, just use first 32 bits as hash */ -static INLINE word32 HashSigner(const byte* hash) +static WC_INLINE word32 HashSigner(const byte* hash) { return MakeWordFromHash(hash) % CA_TABLE_SIZE; } @@ -1796,30 +4108,145 @@ int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash) { Signer* signers; int ret = 0; - word32 row = HashSigner(hash); + word32 row; - if (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 + + if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { + ret = 1; /* success */ + break; + } + signers = signers->next; + } + wc_UnLockMutex(&cm->caLock); + + return ret; +} + + +#ifdef WOLFSSL_TRUST_PEER_CERT +/* hash is the SHA digest of name, just use first 32 bits as hash */ +static WC_INLINE word32 TrustedPeerHashSigner(const byte* hash) +{ + return MakeWordFromHash(hash) % TP_TABLE_SIZE; +} + +/* does trusted peer already exist on signer list */ +int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash) +{ + TrustedPeerCert* tp; + int ret = 0; + word32 row = TrustedPeerHashSigner(hash); + + if (wc_LockMutex(&cm->tpLock) != 0) + return ret; + tp = cm->tpTable[row]; + while (tp) { + byte* subjectHash; #ifndef NO_SKID - subjectHash = signers->subjectKeyIdHash; + subjectHash = tp->subjectKeyIdHash; #else - subjectHash = signers->subjectNameHash; + subjectHash = tp->subjectNameHash; #endif if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { ret = 1; break; } - signers = signers->next; + tp = tp->next; } - UnLockMutex(&cm->caLock); + wc_UnLockMutex(&cm->tpLock); return ret; } +/* return Trusted Peer if found, otherwise NULL + type is what to match on + */ +TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, int type) +{ + WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp; + TrustedPeerCert* ret = NULL; + TrustedPeerCert* tp = NULL; + word32 row; + + if (cm == NULL || hash == NULL) + return NULL; + + row = TrustedPeerHashSigner(hash); + + if (wc_LockMutex(&cm->tpLock) != 0) + return ret; + + tp = cm->tpTable[row]; + while (tp) { + byte* subjectHash; + switch (type) { + #ifndef NO_SKID + case WC_MATCH_SKID: + subjectHash = tp->subjectKeyIdHash; + break; + #endif + case WC_MATCH_NAME: + subjectHash = tp->subjectNameHash; + break; + default: + WOLFSSL_MSG("Unknown search type"); + wc_UnLockMutex(&cm->tpLock); + return NULL; + } + if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { + ret = tp; + break; + } + tp = tp->next; + } + wc_UnLockMutex(&cm->tpLock); + + return ret; +} + + +int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert) +{ + if (tp == NULL || cert == NULL) + return BAD_FUNC_ARG; + + /* subject key id or subject hash has been compared when searching + tpTable for the cert from function GetTrustedPeer */ + + /* compare signatures */ + if (tp->sigLen == cert->sigLength) { + if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) { + return WOLFSSL_FAILURE; + } + } + else { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + /* return CA if found, otherwise NULL */ Signer* GetCA(void* vp, byte* hash) { @@ -1831,7 +4258,7 @@ Signer* GetCA(void* vp, byte* hash) if (cm == NULL) return NULL; - if (LockMutex(&cm->caLock) != 0) + if (wc_LockMutex(&cm->caLock) != 0) return ret; signers = cm->caTable[row]; @@ -1848,7 +4275,7 @@ Signer* GetCA(void* vp, byte* hash) } signers = signers->next; } - UnLockMutex(&cm->caLock); + wc_UnLockMutex(&cm->caLock); return ret; } @@ -1866,102 +4293,112 @@ Signer* GetCAByName(void* vp, byte* hash) if (cm == NULL) return NULL; - if (LockMutex(&cm->caLock) != 0) + if (wc_LockMutex(&cm->caLock) != 0) return ret; for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) { signers = cm->caTable[row]; while (signers && ret == NULL) { - if (XMEMCMP(hash, - signers->subjectNameHash, SIGNER_DIGEST_SIZE) == 0) { + if (XMEMCMP(hash, signers->subjectNameHash, + SIGNER_DIGEST_SIZE) == 0) { ret = signers; } signers = signers->next; } } - UnLockMutex(&cm->caLock); + wc_UnLockMutex(&cm->caLock); return ret; } #endif -/* owns der, internal now uses too */ -/* type flag ids from user or from chain received during verify - don't allow chain ones to be added w/o isCA extension */ -int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify) +#ifdef WOLFSSL_TRUST_PEER_CERT +/* add a trusted peer cert to linked list */ +int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) { - int ret; - Signer* signer = 0; - word32 row; - byte* subjectHash; -#ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; -#else - DecodedCert cert[1]; -#endif + int ret, row; + TrustedPeerCert* peerCert; + DecodedCert* cert; + DerBuffer* der = *pDer; + byte* subjectHash = NULL; - WOLFSSL_MSG("Adding a CA"); + WOLFSSL_MSG("Adding a Trusted Peer Cert"); -#ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap, + 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"); + InitDecodedCert(cert, der->buffer, der->length, cm->heap); + if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) { + FreeDecodedCert(cert); + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + return ret; + } + 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_DCERT); + return MEMORY_E; + } + XMEMSET(peerCert, 0, sizeof(TrustedPeerCert)); #ifndef NO_SKID - subjectHash = cert->extSubjKeyId; + if (cert->extAuthKeyIdSet) { + subjectHash = cert->extSubjKeyId; + } + else { + subjectHash = cert->subjectHash; + } #else subjectHash = cert->subjectHash; #endif - if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) { - WOLFSSL_MSG(" Can't add as CA if not actually one"); - ret = NOT_CA_ERROR; - } -#ifndef ALLOW_INVALID_CERTSIGN - else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA && - (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"); - ret = NOT_CA_ERROR; - } -#endif - else if (ret == 0 && AlreadySigner(cm, subjectHash)) { - WOLFSSL_MSG(" Already have this CA, not adding again"); + #ifndef IGNORE_NAME_CONSTRAINTS + if (peerCert->permittedNames) + FreeNameSubtrees(peerCert->permittedNames, cm->heap); + if (peerCert->excludedNames) + FreeNameSubtrees(peerCert->excludedNames, cm->heap); + #endif + + if (AlreadyTrustedPeer(cm, subjectHash)) { + WOLFSSL_MSG("\tAlready have this CA, not adding again"); + FreeTrustedPeer(peerCert, cm->heap); (void)ret; } - else if (ret == 0) { - /* take over signer parts */ - signer = MakeSigner(cm->heap); - if (!signer) - ret = MEMORY_ERROR; - else { - signer->keyOID = cert->keyOID; - signer->publicKey = cert->publicKey; - signer->pubKeySize = cert->pubKeySize; - signer->nameLen = cert->subjectCNLen; - signer->name = cert->subjectCN; + else { + /* add trusted peer signature */ + peerCert->sigLen = cert->sigLength; + peerCert->sig = XMALLOC(cert->sigLength, cm->heap, + DYNAMIC_TYPE_SIGNATURE); + if (peerCert->sig == NULL) { + FreeDecodedCert(cert); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + FreeTrustedPeer(peerCert, cm->heap); + return MEMORY_E; + } + XMEMCPY(peerCert->sig, cert->signature, cert->sigLength); + + /* add trusted peer name */ + peerCert->nameLen = cert->subjectCNLen; + peerCert->name = cert->subjectCN; #ifndef IGNORE_NAME_CONSTRAINTS - signer->permittedNames = cert->permittedNames; - signer->excludedNames = cert->excludedNames; + peerCert->permittedNames = cert->permittedNames; + peerCert->excludedNames = cert->excludedNames; #endif + + /* add SKID when available and hash of name */ #ifndef NO_SKID - XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId, - SIGNER_DIGEST_SIZE); + XMEMCPY(peerCert->subjectKeyIdHash, cert->extSubjKeyId, + SIGNER_DIGEST_SIZE); #endif - XMEMCPY(signer->subjectNameHash, cert->subjectHash, - SIGNER_DIGEST_SIZE); - signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage - : 0xFFFF; - signer->next = NULL; /* If Key Usage not set, all uses valid. */ - cert->publicKey = 0; /* in case lock fails don't free here. */ + XMEMCPY(peerCert->subjectNameHash, cert->subjectHash, + SIGNER_DIGEST_SIZE); + peerCert->next = NULL; /* If Key Usage not set, all uses valid. */ cert->subjectCN = 0; #ifndef IGNORE_NAME_CONSTRAINTS cert->permittedNames = NULL; @@ -1969,38 +4406,249 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify) #endif #ifndef NO_SKID - row = HashSigner(signer->subjectKeyIdHash); - #else - row = HashSigner(signer->subjectNameHash); - #endif - - if (LockMutex(&cm->caLock) == 0) { - signer->next = cm->caTable[row]; - cm->caTable[row] = signer; /* takes ownership */ - UnLockMutex(&cm->caLock); - if (cm->caCacheCallback) - cm->caCacheCallback(der.buffer, (int)der.length, type); + if (cert->extAuthKeyIdSet) { + row = TrustedPeerHashSigner(peerCert->subjectKeyIdHash); } else { - WOLFSSL_MSG(" CA Mutex Lock failed"); - ret = BAD_MUTEX_E; - FreeSigner(signer, cm->heap); + row = TrustedPeerHashSigner(peerCert->subjectNameHash); } + #else + row = TrustedPeerHashSigner(peerCert->subjectNameHash); + #endif + + if (wc_LockMutex(&cm->tpLock) == 0) { + peerCert->next = cm->tpTable[row]; + cm->tpTable[row] = peerCert; /* takes ownership */ + wc_UnLockMutex(&cm->tpLock); + } + else { + WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed"); + FreeDecodedCert(cert); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + FreeTrustedPeer(peerCert, cm->heap); + return BAD_MUTEX_E; + } + } + + WOLFSSL_MSG("\tFreeing parsed trusted peer cert"); + FreeDecodedCert(cert); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + WOLFSSL_MSG("\tFreeing der trusted peer cert"); + FreeDer(&der); + WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert"); + WOLFSSL_LEAVE("AddTrustedPeer", ret); + + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + +/* owns der, internal now uses too */ +/* type flag ids from user or from chain received during verify + don't allow chain ones to be added w/o isCA extension */ +int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) +{ + int ret; + Signer* signer = NULL; + word32 row; + byte* subjectHash; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; +#else + DecodedCert cert[1]; +#endif + DerBuffer* der = *pDer; + + WOLFSSL_MSG("Adding a CA"); + + if (cm == NULL) { + FreeDer(pDer); + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) { + FreeDer(pDer); + return MEMORY_E; + } +#endif + + InitDecodedCert(cert, der->buffer, der->length, cm->heap); + ret = ParseCert(cert, CA_TYPE, verify, cm); + WOLFSSL_MSG("\tParsed new CA"); + +#ifndef NO_SKID + subjectHash = cert->extSubjKeyId; +#else + subjectHash = cert->subjectHash; +#endif + + /* check CA key size */ + if (verify) { + switch (cert->keyOID) { + #ifndef NO_RSA + case RSAk: + if (cm->minRsaKeySz < 0 || + cert->pubKeySize < (word16)cm->minRsaKeySz) { + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("\tCA RSA key size error"); + } + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + if (cm->minEccKeySz < 0 || + cert->pubKeySize < (word16)cm->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + 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 */ + #ifdef HAVE_ED448 + case ED448k: + if (cm->minEccKeySz < 0 || + ED448_KEY_SIZE < (word16)cm->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ECC key size error"); + } + break; + #endif /* HAVE_ED448 */ + + default: + WOLFSSL_MSG("\tNo key size check done on CA"); + break; /* no size check if key type is not in switch */ } } - WOLFSSL_MSG(" Freeing Parsed CA"); + if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) { + WOLFSSL_MSG("\tCan't add as CA if not actually one"); + ret = NOT_CA_ERROR; + } +#ifndef ALLOW_INVALID_CERTSIGN + else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA && + !cert->selfSigned && (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("\tDoesn't have key usage certificate signing"); + ret = NOT_CA_ERROR; + } +#endif + else if (ret == 0 && AlreadySigner(cm, subjectHash)) { + WOLFSSL_MSG("\tAlready have this CA, not adding again"); + (void)ret; + } + else if (ret == 0) { + /* take over signer parts */ + signer = MakeSigner(cm->heap); + if (!signer) + ret = MEMORY_ERROR; + } + if (ret == 0 && signer != NULL) { + #ifdef WOLFSSL_SIGNER_DER_CERT + ret = AllocDer(&signer->derCert, der->length, der->type, NULL); + } + if (ret == 0 && signer != NULL) { + XMEMCPY(signer->derCert->buffer, der->buffer, der->length); + #endif + signer->keyOID = cert->keyOID; + 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->maxPathLen = cert->maxPathLen; + signer->pathLengthSet = cert->pathLengthSet; + signer->selfSigned = cert->selfSigned; + #ifndef IGNORE_NAME_CONSTRAINTS + signer->permittedNames = cert->permittedNames; + signer->excludedNames = cert->excludedNames; + #endif + #ifndef NO_SKID + XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId, + SIGNER_DIGEST_SIZE); + #endif + XMEMCPY(signer->subjectNameHash, cert->subjectHash, + SIGNER_DIGEST_SIZE); + #ifdef HAVE_OCSP + XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash, + KEYID_SIZE); + #endif + signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage + : 0xFFFF; + signer->next = NULL; /* If Key Usage not set, all uses valid. */ + cert->publicKey = 0; /* in case lock fails don't free here. */ + cert->subjectCN = 0; + #ifndef IGNORE_NAME_CONSTRAINTS + cert->permittedNames = NULL; + cert->excludedNames = NULL; + #endif + + #ifndef NO_SKID + row = HashSigner(signer->subjectKeyIdHash); + #else + row = HashSigner(signer->subjectNameHash); + #endif + + if (wc_LockMutex(&cm->caLock) == 0) { + signer->next = cm->caTable[row]; + cm->caTable[row] = signer; /* takes ownership */ + wc_UnLockMutex(&cm->caLock); + if (cm->caCacheCallback) + cm->caCacheCallback(der->buffer, (int)der->length, type); + } + else { + WOLFSSL_MSG("\tCA Mutex Lock failed"); + ret = BAD_MUTEX_E; + FreeSigner(signer, cm->heap); + } + } +#if defined(WOLFSSL_RENESAS_TSIP_TLS) + /* Verify CA by TSIP so that generated tsip key is going to be able to */ + /* be used for peer's cert verification */ + /* TSIP is only able to handle USER CA, and only one CA. */ + /* Therefore, it doesn't need to call TSIP again if there is already */ + /* verified CA. */ + if ( ret == 0 && signer != NULL ) { + signer->cm_idx = row; + if (type == WOLFSSL_USER_CA && tsip_rootCAverified() == 0 ) { + if ((ret = tsip_tls_RootCertVerify(cert->source, cert->maxIdx, + cert->sigCtx.pubkey_n_start, cert->sigCtx.pubkey_n_len - 1, + cert->sigCtx.pubkey_e_start, cert->sigCtx.pubkey_e_len - 1, + row/* cm index */)) + != 0) + WOLFSSL_MSG("tsip_tls_RootCertVerify() failed"); + else + WOLFSSL_MSG("tsip_tls_RootCertVerify() succeed"); + } + } +#endif + 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"); - XFREE(der.buffer, cm->heap, DYNAMIC_TYPE_CA); - WOLFSSL_MSG(" OK Freeing der CA"); + WOLFSSL_MSG("\tFreeing der CA"); + FreeDer(pDer); + 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 */ @@ -2011,22 +4659,29 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify) /* basic config gives a cache with 33 sessions, adequate for clients and embedded servers - MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that - aren't under heavy load, basically allows 200 new sessions per minute - - BIG_SESSION_CACHE yields 20,027 sessions + TITAN_SESSION_CACHE allows just over 2 million sessions, for servers + with titanic amounts of memory with long session ID timeouts and high + levels of traffic. HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load, allows over 13,000 new sessions per minute or over 200 new sessions per second + BIG_SESSION_CACHE yields 20,027 sessions + + MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that + aren't under heavy load, basically allows 200 new sessions per minute + SMALL_SESSION_CACHE only stores 6 sessions, good for embedded clients or systems where the default of nearly 3kB is too much RAM, this define uses less than 500 bytes RAM default SESSION_CACHE stores 33 sessions (no XXX_SESSION_CACHE defined) */ - #ifdef HUGE_SESSION_CACHE + #if defined(TITAN_SESSION_CACHE) + #define SESSIONS_PER_ROW 31 + #define SESSION_ROWS 64937 + #elif defined(HUGE_SESSION_CACHE) #define SESSIONS_PER_ROW 11 #define SESSION_ROWS 5981 #elif defined(BIG_SESSION_CACHE) @@ -2049,13 +4704,13 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify) WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW]; } SessionRow; - static SessionRow SessionCache[SESSION_ROWS]; + static WOLFSSL_GLOBAL SessionRow SessionCache[SESSION_ROWS]; #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) - static word32 PeakSessions; + static WOLFSSL_GLOBAL word32 PeakSessions; #endif - static wolfSSL_Mutex session_mutex; /* SessionCache mutex */ + static WOLFSSL_GLOBAL wolfSSL_Mutex session_mutex; /* SessionCache mutex */ #ifndef NO_CLIENT_CACHE @@ -2070,707 +4725,1049 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify) ClientSession Clients[SESSIONS_PER_ROW]; } ClientRow; - static ClientRow ClientCache[SESSION_ROWS]; /* Client Cache */ + static WOLFSSL_GLOBAL ClientRow ClientCache[SESSION_ROWS]; + /* Client Cache */ /* uses session mutex */ #endif /* NO_CLIENT_CACHE */ #endif /* NO_SESSION_CACHE */ - +WOLFSSL_ABI int wolfSSL_Init(void) { - int ret = SSL_SUCCESS; - WOLFSSL_ENTER("wolfSSL_Init"); if (initRefCount == 0) { -#ifndef NO_SESSION_CACHE - if (InitMutex(&session_mutex) != 0) - ret = BAD_MUTEX_E; + /* Initialize crypto for use with TLS connection */ + if (wolfCrypt_Init() != 0) { + WOLFSSL_MSG("Bad wolfCrypt Init"); + return WC_INIT_E; + } + +#ifdef OPENSSL_EXTRA + if (wolfSSL_RAND_seed(NULL, 0) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_RAND_Seed failed"); + return WC_INIT_E; + } #endif - if (InitMutex(&count_mutex) != 0) - ret = BAD_MUTEX_E; - } - if (ret == SSL_SUCCESS) { - if (LockMutex(&count_mutex) != 0) { - WOLFSSL_MSG("Bad Lock Mutex count"); + +#ifndef NO_SESSION_CACHE + if (wc_InitMutex(&session_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex session"); return BAD_MUTEX_E; } - initRefCount++; - UnLockMutex(&count_mutex); +#endif + if (wc_InitMutex(&count_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex count"); + return BAD_MUTEX_E; + } + } + + if (wc_LockMutex(&count_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex count"); + return BAD_MUTEX_E; + } + + initRefCount++; + wc_UnLockMutex(&count_mutex); + + return WOLFSSL_SUCCESS; +} + + + +#ifndef NO_CERTS + +/* process user cert chain to pass during the handshake */ +static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, + long sz, int format, int type, WOLFSSL* ssl, + long* used, EncryptedInfo* info, int verify) +{ + int ret = 0; + void* heap = wolfSSL_CTX_GetHeap(ctx, ssl); +#ifdef WOLFSSL_TLS13 + int cnt = 0; +#endif + + if ((type == CA_TYPE) && (ctx == NULL)) { + WOLFSSL_MSG("Need context for CA load"); + return BAD_FUNC_ARG; + } + + /* we may have a user cert chain, try to consume */ + if ((type == CERT_TYPE || type == CA_TYPE) && (info->consumed < sz)) { + #ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force heap usage */ + #else + byte staticBuffer[FILE_BUFFER_SIZE]; /* tmp chain buffer */ + #endif + byte* chainBuffer = staticBuffer; + int dynamicBuffer = 0; + word32 bufferSz; + long consumed = info->consumed; + word32 idx = 0; + int gotOne = 0; + + /* Calculate max possible size, including max headers */ + bufferSz = (word32)(sz - consumed) + (CERT_HEADER_SZ * MAX_CHAIN_DEPTH); + if (bufferSz > sizeof(staticBuffer)) { + WOLFSSL_MSG("Growing Tmp Chain Buffer"); + /* will shrink to actual size */ + chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE); + if (chainBuffer == NULL) { + return MEMORY_E; + } + dynamicBuffer = 1; + } + + WOLFSSL_MSG("Processing Cert Chain"); + while (consumed < sz) { + DerBuffer* part = NULL; + word32 remain = (word32)(sz - consumed); + info->consumed = 0; + + if (format == WOLFSSL_FILETYPE_PEM) { + #ifdef WOLFSSL_PEM_TO_DER + ret = PemToDer(buff + consumed, remain, type, &part, + heap, info, NULL); + #else + ret = NOT_COMPILED_IN; + #endif + } + else { + int length = remain; + if (format == WOLFSSL_FILETYPE_ASN1) { + /* get length of der (read sequence) */ + word32 inOutIdx = 0; + if (GetSequence(buff + consumed, &inOutIdx, &length, + remain) < 0) { + ret = ASN_NO_PEM_HEADER; + } + length += inOutIdx; /* include leading sequence */ + } + info->consumed = length; + if (ret == 0) { + ret = AllocDer(&part, length, type, heap); + if (ret == 0) { + XMEMCPY(part->buffer, buff + consumed, length); + } + } + } + if (ret == 0) { + gotOne = 1; +#ifdef WOLFSSL_TLS13 + cnt++; +#endif + if ((idx + part->length + CERT_HEADER_SZ) > bufferSz) { + WOLFSSL_MSG(" Cert Chain bigger than buffer"); + ret = BUFFER_E; + } + else { + c32to24(part->length, &chainBuffer[idx]); + idx += CERT_HEADER_SZ; + XMEMCPY(&chainBuffer[idx], part->buffer, part->length); + idx += part->length; + consumed += info->consumed; + if (used) + *used += info->consumed; + } + + /* add CA's to certificate manager */ + if (type == CA_TYPE) { + /* verify CA unless user set to no verify */ + ret = AddCA(ctx->cm, &part, WOLFSSL_USER_CA, verify); + gotOne = 0; /* don't exit loop for CA type */ + } + } + + FreeDer(&part); + + if (ret == ASN_NO_PEM_HEADER && gotOne) { + WOLFSSL_MSG("We got one good cert, so stuff at end ok"); + break; + } + + if (ret < 0) { + WOLFSSL_MSG(" Error in Cert in Chain"); + if (dynamicBuffer) + XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE); + return ret; + } + WOLFSSL_MSG(" Consumed another Cert in Chain"); + } + WOLFSSL_MSG("Finished Processing Cert Chain"); + + /* only retain actual size used */ + ret = 0; + if (idx > 0) { + if (ssl) { + if (ssl->buffers.weOwnCertChain) { + FreeDer(&ssl->buffers.certChain); + } + ret = AllocDer(&ssl->buffers.certChain, idx, type, heap); + if (ret == 0) { + 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 + } + } + + if (dynamicBuffer) + XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE); } return ret; } - -#ifndef NO_CERTS - -static const char* BEGIN_CERT = "-----BEGIN CERTIFICATE-----"; -static const char* END_CERT = "-----END CERTIFICATE-----"; -static const char* BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----"; -static const char* END_CERT_REQ = "-----END CERTIFICATE REQUEST-----"; -static const char* BEGIN_DH_PARAM = "-----BEGIN DH PARAMETERS-----"; -static const char* END_DH_PARAM = "-----END DH PARAMETERS-----"; -static const char* BEGIN_X509_CRL = "-----BEGIN X509 CRL-----"; -static const char* END_X509_CRL = "-----END X509 CRL-----"; -static const char* BEGIN_RSA_PRIV = "-----BEGIN RSA PRIVATE KEY-----"; -static const char* END_RSA_PRIV = "-----END RSA PRIVATE KEY-----"; -static const char* BEGIN_PRIV_KEY = "-----BEGIN PRIVATE KEY-----"; -static const char* END_PRIV_KEY = "-----END PRIVATE KEY-----"; -static const char* BEGIN_ENC_PRIV_KEY = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; -static const char* END_ENC_PRIV_KEY = "-----END ENCRYPTED PRIVATE KEY-----"; -static const char* BEGIN_EC_PRIV = "-----BEGIN EC PRIVATE KEY-----"; -static const char* END_EC_PRIV = "-----END EC PRIVATE KEY-----"; -static const char* BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----"; -static const char* END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; - -/* Remove PEM header/footer, convert to ASN1, store any encrypted data - info->consumed tracks of PEM bytes consumed in case multiple parts */ -int PemToDer(const unsigned char* buff, long longSz, int type, - buffer* der, void* heap, EncryptedInfo* info, int* eccKey) +static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der, + int* keySz, word32* idx, int* resetSuites, int* keyFormat, void* heap, int devId) { - const char* header = NULL; - const char* footer = NULL; - char* headerEnd; - char* footerEnd; - char* consumedEnd; - char* bufferEnd = (char*)(buff + longSz); - long neededSz; - int ret = 0; - int dynamicType = 0; - int sz = (int)longSz; + int ret = 0; - switch (type) { - case CA_TYPE: /* same as below */ - 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 CERTREQ_TYPE: header= BEGIN_CERT_REQ; footer= END_CERT_REQ; break; - default: header= BEGIN_RSA_PRIV; footer= END_RSA_PRIV; break; - } - - switch (type) { - case CA_TYPE: dynamicType = DYNAMIC_TYPE_CA; break; - case CERT_TYPE: dynamicType = DYNAMIC_TYPE_CERT; break; - case CRL_TYPE: dynamicType = DYNAMIC_TYPE_CRL; break; - default: dynamicType = DYNAMIC_TYPE_KEY; break; - } + (void)heap; + (void)devId; - /* find header */ - for (;;) { - headerEnd = XSTRNSTR((char*)buff, header, sz); - - if (headerEnd || type != PRIVATEKEY_TYPE) { - break; - } else if (header == BEGIN_RSA_PRIV) { - header = BEGIN_PRIV_KEY; footer = END_PRIV_KEY; - } else if (header == BEGIN_PRIV_KEY) { - header = BEGIN_ENC_PRIV_KEY; footer = END_ENC_PRIV_KEY; - } else if (header == BEGIN_ENC_PRIV_KEY) { - header = BEGIN_EC_PRIV; footer = END_EC_PRIV; - } else if (header == BEGIN_EC_PRIV) { - header = BEGIN_DSA_PRIV; footer = END_DSA_PRIV; - } else - break; - } + if (ctx == NULL && ssl == NULL) + ret = BAD_FUNC_ARG; + if (!der || !keySz || !idx || !resetSuites || !keyFormat) + ret = BAD_FUNC_ARG; - if (!headerEnd) { - WOLFSSL_MSG("Couldn't find PEM header"); - return SSL_NO_PEM_HEADER; - } - - headerEnd += XSTRLEN(header); - - /* eat end of line */ - if (headerEnd[0] == '\n') - headerEnd++; - else if (headerEnd[1] == '\n') - headerEnd += 2; - else - return SSL_BAD_FILE; - - if (type == PRIVATEKEY_TYPE) { - if (eccKey) - *eccKey = header == BEGIN_EC_PRIV; - } - -#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); - - if (!start) - start = XSTRNSTR(line, "AES", PEM_LINE_LEN); - - if (!start) return SSL_BAD_FILE; - if (!info) return SSL_BAD_FILE; - - finish = XSTRNSTR(start, ",", PEM_LINE_LEN); - - if (start && finish && (start < finish)) { - newline = XSTRNSTR(finish, "\r", PEM_LINE_LEN); - - XMEMCPY(info->name, start, finish - start); - info->name[finish - start] = 0; - XMEMCPY(info->iv, finish + 1, sizeof(info->iv)); - - if (!newline) newline = XSTRNSTR(finish, "\n", PEM_LINE_LEN); - if (newline && (newline > finish)) { - info->ivSz = (word32)(newline - (finish + 1)); - info->set = 1; - } - else - return SSL_BAD_FILE; - } - else - return SSL_BAD_FILE; - - /* eat blank line */ - while (*newline == '\r' || *newline == '\n') - newline++; - headerEnd = newline; - } - } -#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ - - /* find footer */ - footerEnd = XSTRNSTR((char*)buff, footer, sz); - if (!footerEnd) - return SSL_BAD_FILE; - - consumedEnd = footerEnd + XSTRLEN(footer); - - if (consumedEnd < bufferEnd) { /* handle no end of line on last line */ - /* eat end of line */ - if (consumedEnd[0] == '\n') - consumedEnd++; - else if (consumedEnd[1] == '\n') - consumedEnd += 2; - else - return SSL_BAD_FILE; - } - - if (info) - info->consumed = (long)(consumedEnd - (char*)buff); - - /* set up der buffer */ - neededSz = (long)(footerEnd - headerEnd); - if (neededSz > sz || neededSz < 0) - return SSL_BAD_FILE; - - der->buffer = (byte*)XMALLOC(neededSz, heap, dynamicType); - if (!der->buffer) - return MEMORY_ERROR; - - der->length = (word32)neededSz; - - if (Base64_Decode((byte*)headerEnd, (word32)neededSz, der->buffer, - &der->length) < 0) - return SSL_BAD_FILE; - - if (header == BEGIN_PRIV_KEY) { - /* pkcs8 key, convert and adjust length */ - if ((ret = ToTraditional(der->buffer, der->length)) < 0) - return ret; - - der->length = ret; - return 0; - } - -#if (defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)) && !defined(NO_PWDBASED) - if (header == BEGIN_ENC_PRIV_KEY) { - int passwordSz; +#ifndef NO_RSA + if (ret == 0 && (*keyFormat == 0 || *keyFormat == RSAk)) { + /* make sure RSA key can be used */ #ifdef WOLFSSL_SMALL_STACK - char* password = NULL; + RsaKey* key; #else - char password[80]; + RsaKey key[1]; #endif - if (!info || !info->ctx || !info->ctx->passwd_cb) - return SSL_BAD_FILE; /* no callback error */ - #ifdef WOLFSSL_SMALL_STACK - password = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (password == NULL) + key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA); + if (key == NULL) return MEMORY_E; #endif - passwordSz = info->ctx->passwd_cb(password, sizeof(password), 0, - info->ctx->userdata); - /* convert and adjust length */ - ret = ToTraditionalEnc(der->buffer, der->length, password, passwordSz); + + ret = wc_InitRsaKey_ex(key, heap, devId); + if (ret == 0) { + *idx = 0; + if (wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length) + != 0) { + #if !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ + !defined(HAVE_ED448) + WOLFSSL_MSG("RSA decode failed and ECC/ED25519/ED448 not " + "enabled to try"); + ret = WOLFSSL_BAD_FILE; + #endif + } + else { + /* check that the size of the RSA key is enough */ + int minRsaSz = ssl ? ssl->options.minRsaKeySz : + ctx->minRsaKeySz; + *keySz = wc_RsaEncryptSize((RsaKey*)key); + if (*keySz < minRsaSz) { + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("Private Key size too small"); + } + + if (ssl) { + ssl->buffers.keyType = rsa_sa_algo; + ssl->buffers.keySz = *keySz; + } + else { + ctx->privateKeyType = rsa_sa_algo; + ctx->privateKeySz = *keySz; + } + + *keyFormat = RSAk; + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.haveStaticECC = 0; + *resetSuites = 1; + } + } + + wc_FreeRsaKey(key); + } #ifdef WOLFSSL_SMALL_STACK - XFREE(password, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, heap, DYNAMIC_TYPE_RSA); #endif - - if (ret < 0) - return ret; - - der->length = ret; - return 0; } #endif +#ifdef HAVE_ECC + if (ret == 0 && (*keyFormat == 0 || *keyFormat == ECDSAk)) { + /* make sure ECC key can be used */ + #ifdef WOLFSSL_SMALL_STACK + ecc_key* key; + #else + ecc_key key[1]; + #endif - return 0; + #ifdef WOLFSSL_SMALL_STACK + key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC); + if (key == NULL) + return MEMORY_E; + #endif + + if (wc_ecc_init_ex(key, heap, devId) == 0) { + *idx = 0; + if (wc_EccPrivateKeyDecode(der->buffer, idx, key, + der->length) == 0) { + /* check for minimum ECC key size and then free */ + int minKeySz = ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz; + *keySz = wc_ecc_size(key); + if (*keySz < minKeySz) { + WOLFSSL_MSG("ECC private key too small"); + ret = ECC_KEY_SIZE_E; + } + + *keyFormat = ECDSAk; + if (ssl) { + ssl->options.haveStaticECC = 1; + ssl->buffers.keyType = ecc_dsa_sa_algo; + ssl->buffers.keySz = *keySz; + } + else { + ctx->haveStaticECC = 1; + ctx->privateKeyType = ecc_dsa_sa_algo; + ctx->privateKeySz = *keySz; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + *resetSuites = 1; + } + } + + wc_ecc_free(key); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(key, heap, DYNAMIC_TYPE_ECC); + #endif + } +#endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + if (ret == 0 && (*keyFormat == 0 || *keyFormat == ED25519k)) { + /* make sure Ed25519 key can be used */ + #ifdef WOLFSSL_SMALL_STACK + ed25519_key* key; + #else + ed25519_key key[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap, + DYNAMIC_TYPE_ED25519); + if (key == NULL) + return MEMORY_E; + #endif + + ret = wc_ed25519_init(key); + if (ret == 0) { + *idx = 0; + if (wc_Ed25519PrivateKeyDecode(der->buffer, idx, key, + der->length) == 0) { + /* check for minimum key size and then free */ + int minKeySz = ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz; + *keySz = ED25519_KEY_SIZE; + if (*keySz < minKeySz) { + WOLFSSL_MSG("ED25519 private key too small"); + ret = ECC_KEY_SIZE_E; + } + if (ret == 0) { + if (ssl) { + ssl->buffers.keyType = ed25519_sa_algo; + ssl->buffers.keySz = *keySz; + } + else if (ctx) { + ctx->privateKeyType = ed25519_sa_algo; + ctx->privateKeySz = *keySz; + } + + *keyFormat = ED25519k; + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + *resetSuites = 1; + } + } + } + + wc_ed25519_free(key); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(key, heap, DYNAMIC_TYPE_ED25519); + #endif + } +#endif /* HAVE_ED25519 */ +#ifdef HAVE_ED448 + if (ret == 0 && (*keyFormat == 0 || *keyFormat == ED448k)) { + /* make sure Ed448 key can be used */ + #ifdef WOLFSSL_SMALL_STACK + ed448_key* key = NULL; + #else + ed448_key key[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448); + if (key == NULL) + return MEMORY_E; + #endif + + ret = wc_ed448_init(key); + if (ret == 0) { + *idx = 0; + if (wc_Ed448PrivateKeyDecode(der->buffer, idx, key, + der->length) != 0) { + ret = WOLFSSL_BAD_FILE; + } + + if (ret == 0) { + /* check for minimum key size and then free */ + int minKeySz = ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz; + *keySz = ED448_KEY_SIZE; + if (*keySz < minKeySz) { + WOLFSSL_MSG("ED448 private key too small"); + ret = ECC_KEY_SIZE_E; + } + } + if (ret == 0) { + if (ssl) { + ssl->buffers.keyType = ed448_sa_algo; + ssl->buffers.keySz = *keySz; + } + else if (ctx) { + ctx->privateKeyType = ed448_sa_algo; + ctx->privateKeySz = *keySz; + } + + *keyFormat = ED448k; + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + *resetSuites = 1; + } + } + + wc_ed448_free(key); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(key, heap, DYNAMIC_TYPE_ED448); + #endif + } +#endif /* HAVE_ED448 */ + return ret; } - -/* process the buffer buff, legnth sz, into ctx of format and type +/* process the buffer buff, length sz, into ctx of format and type used tracks bytes consumed, userChain specifies a user cert chain to pass during the handshake */ -static int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, +int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, long sz, int format, int type, WOLFSSL* ssl, - long* used, int userChain) + long* used, int userChain, int verify) { - buffer der; /* holds DER or RAW (for NTRU) */ - int ret; - int dynamicType = 0; - int eccKey = 0; - int rsaKey = 0; - void* heap = ctx ? ctx->heap : NULL; + DerBuffer* der = NULL; /* holds DER or RAW (for NTRU) */ + int ret = 0; + int done = 0; + int keyFormat = 0; + int resetSuites = 0; + void* heap = wolfSSL_CTX_GetHeap(ctx, ssl); + int devId = wolfSSL_CTX_GetDevId(ctx, ssl); + word32 idx = 0; + int keySz = 0; +#if (defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)) || \ + defined(HAVE_PKCS8) + word32 algId = 0; +#endif #ifdef WOLFSSL_SMALL_STACK EncryptedInfo* info = NULL; #else EncryptedInfo info[1]; #endif - (void)dynamicType; - (void)rsaKey; + (void)devId; + (void)idx; + (void)keySz; if (used) *used = sz; /* used bytes default to sz, PEM chain may shorten*/ - if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM - && format != SSL_FILETYPE_RAW) - return SSL_BAD_FILETYPE; + /* check args */ + 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; - if (type == CA_TYPE) - dynamicType = DYNAMIC_TYPE_CA; - else if (type == CERT_TYPE) - dynamicType = DYNAMIC_TYPE_CERT; - else - dynamicType = DYNAMIC_TYPE_KEY; - #ifdef WOLFSSL_SMALL_STACK - info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap, + DYNAMIC_TYPE_ENCRYPTEDINFO); if (info == NULL) return MEMORY_E; #endif - info->set = 0; - info->ctx = ctx; - info->consumed = 0; - der.buffer = 0; - - if (format == SSL_FILETYPE_PEM) { - ret = PemToDer(buff, sz, type, &der, heap, info, &eccKey); - if (ret < 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - XFREE(der.buffer, heap, dynamicType); - return ret; - } - - if (used) - *used = info->consumed; - - /* we may have a user cert chain, try to consume */ - if (userChain && type == CERT_TYPE && info->consumed < sz) { - #ifdef WOLFSSL_SMALL_STACK - byte staticBuffer[1]; /* force heap usage */ - #else - byte staticBuffer[FILE_BUFFER_SIZE]; /* tmp chain buffer */ - #endif - byte* chainBuffer = staticBuffer; - byte* shrinked = NULL; /* shrinked to size chainBuffer - * or staticBuffer */ - int dynamicBuffer = 0; - word32 bufferSz = sizeof(staticBuffer); - long consumed = info->consumed; - word32 idx = 0; - int gotOne = 0; - - if ( (sz - consumed) > (int)bufferSz) { - WOLFSSL_MSG("Growing Tmp Chain Buffer"); - bufferSz = (word32)(sz - consumed); - /* will shrink to actual size */ - chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE); - if (chainBuffer == NULL) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - XFREE(der.buffer, heap, dynamicType); - return MEMORY_E; - } - dynamicBuffer = 1; - } - - WOLFSSL_MSG("Processing Cert Chain"); - while (consumed < sz) { - buffer part; - info->consumed = 0; - part.buffer = 0; - - ret = PemToDer(buff + consumed, sz - consumed, type, &part, - heap, info, &eccKey); - if (ret == 0) { - gotOne = 1; - if ( (idx + part.length) > bufferSz) { - WOLFSSL_MSG(" Cert Chain bigger than buffer"); - ret = BUFFER_E; - } - else { - c32to24(part.length, &chainBuffer[idx]); - idx += CERT_HEADER_SZ; - XMEMCPY(&chainBuffer[idx], part.buffer,part.length); - idx += part.length; - consumed += info->consumed; - if (used) - *used += info->consumed; - } - } - - XFREE(part.buffer, heap, dynamicType); - - if (ret == SSL_NO_PEM_HEADER && gotOne) { - WOLFSSL_MSG("We got one good PEM so stuff at end ok"); - break; - } - - if (ret < 0) { - WOLFSSL_MSG(" Error in Cert in Chain"); - if (dynamicBuffer) - XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE); - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - XFREE(der.buffer, heap, dynamicType); - return ret; - } - WOLFSSL_MSG(" Consumed another Cert in Chain"); - } - WOLFSSL_MSG("Finished Processing Cert Chain"); - - /* only retain actual size used */ - shrinked = (byte*)XMALLOC(idx, heap, dynamicType); - if (shrinked) { - if (ssl) { - if (ssl->buffers.certChain.buffer && - ssl->buffers.weOwnCertChain) { - XFREE(ssl->buffers.certChain.buffer, heap, - dynamicType); - } - ssl->buffers.certChain.buffer = shrinked; - ssl->buffers.certChain.length = idx; - XMEMCPY(ssl->buffers.certChain.buffer, chainBuffer,idx); - ssl->buffers.weOwnCertChain = 1; - } else if (ctx) { - if (ctx->certChain.buffer) - XFREE(ctx->certChain.buffer, heap, dynamicType); - ctx->certChain.buffer = shrinked; - ctx->certChain.length = idx; - XMEMCPY(ctx->certChain.buffer, chainBuffer, idx); - } - } - - if (dynamicBuffer) - XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE); - - if (shrinked == NULL) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - XFREE(der.buffer, heap, dynamicType); - return MEMORY_E; - } - } + XMEMSET(info, 0, sizeof(EncryptedInfo)); +#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED) + if (ctx) { + info->passwd_cb = ctx->passwd_cb; + info->passwd_userdata = ctx->passwd_userdata; } - else { /* ASN1 (DER) or RAW (NTRU) */ - der.buffer = (byte*) XMALLOC(sz, heap, dynamicType); - if (!der.buffer) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return MEMORY_ERROR; - } - - XMEMCPY(der.buffer, buff, sz); - der.length = (word32)sz; - } - -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - if (info->set) { - /* decrypt */ - int passwordSz; -#ifdef WOLFSSL_SMALL_STACK - char* password = NULL; - byte* key = NULL; - byte* iv = NULL; -#else - char password[80]; - byte key[AES_256_KEY_SIZE]; - #ifndef NO_MD5 - byte iv[AES_IV_SIZE]; - #endif #endif - #ifdef WOLFSSL_SMALL_STACK - password = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); - key = (byte*)XMALLOC(AES_256_KEY_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - iv = (byte*)XMALLOC(AES_IV_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (password == NULL || key == NULL || iv == NULL) { - XFREE(password, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(iv, NULL, DYNAMIC_TYPE_TMP_BUFFER); - ret = MEMORY_E; - } - else + if (format == WOLFSSL_FILETYPE_PEM) { + #ifdef WOLFSSL_PEM_TO_DER + ret = PemToDer(buff, sz, type, &der, heap, info, &keyFormat); + #else + ret = NOT_COMPILED_IN; #endif - if (!ctx || !ctx->passwd_cb) { - ret = NO_PASSWORD; - } - else { - passwordSz = ctx->passwd_cb(password, sizeof(password), 0, - ctx->userdata); - - /* use file's salt for key derivation, hex decode first */ - if (Base16_Decode(info->iv, info->ivSz, info->iv, &info->ivSz) - != 0) { - ret = ASN_INPUT_E; + } + else { + /* ASN1 (DER) or RAW (NTRU) */ + int length = (int)sz; + if (format == WOLFSSL_FILETYPE_ASN1) { + /* get length of der (read sequence or octet string) */ + word32 inOutIdx = 0; + if (GetSequence(buff, &inOutIdx, &length, (word32)sz) >= 0) { + length += inOutIdx; /* include leading sequence */ } -#ifndef NO_MD5 - else if ((ret = EVP_BytesToKey(info->name, "MD5", info->iv, - (byte*)password, passwordSz, 1, key, iv)) <= 0) { - /* empty */ + /* get length using octect string (allowed for private key types) */ + else if (type == PRIVATEKEY_TYPE && + GetOctetString(buff, &inOutIdx, &length, (word32)sz) >= 0) { + length += inOutIdx; /* include leading oct string */ } -#endif -#ifndef NO_DES3 - else if (XSTRNCMP(info->name, "DES-CBC", 7) == 0) { - ret = wc_Des_CbcDecryptWithKey(der.buffer, der.buffer, der.length, - key, info->iv); - } - else if (XSTRNCMP(info->name, "DES-EDE3-CBC", 13) == 0) { - ret = wc_Des3_CbcDecryptWithKey(der.buffer, der.buffer, der.length, - key, info->iv); - } -#endif -#ifndef NO_AES - else if (XSTRNCMP(info->name, "AES-128-CBC", 13) == 0) { - ret = wc_AesCbcDecryptWithKey(der.buffer, der.buffer, der.length, - key, AES_128_KEY_SIZE, info->iv); - } - else if (XSTRNCMP(info->name, "AES-192-CBC", 13) == 0) { - ret = wc_AesCbcDecryptWithKey(der.buffer, der.buffer, der.length, - key, AES_192_KEY_SIZE, info->iv); - } - else if (XSTRNCMP(info->name, "AES-256-CBC", 13) == 0) { - ret = wc_AesCbcDecryptWithKey(der.buffer, der.buffer, der.length, - key, AES_256_KEY_SIZE, info->iv); - } -#endif else { - ret = SSL_BAD_FILE; + ret = ASN_PARSE_E; } } - #ifdef WOLFSSL_SMALL_STACK - XFREE(password, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(iv, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + info->consumed = length; - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ret == 0) { + ret = AllocDer(&der, (word32)length, type, heap); + if (ret == 0) { + XMEMCPY(der->buffer, buff, length); + } + + #ifdef HAVE_PKCS8 + /* if private key try and remove PKCS8 header */ + if (type == PRIVATEKEY_TYPE) { + if ((ret = ToTraditional_ex(der->buffer, der->length, &algId)) > 0) { + /* Found PKCS8 header */ + /* ToTraditional_ex moves buff and returns adjusted length */ + der->length = ret; + } + ret = 0; /* failures should be ignored */ + } #endif - XFREE(der.buffer, heap, dynamicType); - return ret; } } -#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ -#ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + if (used) { + *used = info->consumed; + } - if (type == CA_TYPE) { + /* process user chain */ + if (ret >= 0) { + /* Chain should have server cert first, then intermediates, then root. + * First certificate in chain is processed below after ProcessUserChain + * and is loaded into ssl->buffers.certificate. + * Remainder are processed using ProcessUserChain and are loaded into + * ssl->buffers.certChain. */ + if (userChain) { + ret = ProcessUserChain(ctx, buff, sz, format, type, ssl, used, info, + verify); + } + } + + /* info is only used for private key with DER or PEM, so free now */ + if (ret < 0 || type != PRIVATEKEY_TYPE || format == WOLFSSL_FILETYPE_RAW) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); + #endif + } + + /* check for error */ + if (ret < 0) { + FreeDer(&der); + done = 1; + } + + if (done == 1) { + /* No operation, just skip the next section */ + } + /* Handle DER owner */ + else if (type == CA_TYPE) { if (ctx == NULL) { WOLFSSL_MSG("Need context for CA load"); - XFREE(der.buffer, heap, dynamicType); + FreeDer(&der); return BAD_FUNC_ARG; } - return AddCA(ctx->cm, der, WOLFSSL_USER_CA, ctx->verifyPeer); - /* takes der over */ + /* verify CA unless user set to no verify */ + ret = AddCA(ctx->cm, &der, WOLFSSL_USER_CA, verify); + done = 1; } +#ifdef WOLFSSL_TRUST_PEER_CERT + else if (type == TRUSTED_PEER_TYPE) { + if (ctx == NULL) { + WOLFSSL_MSG("Need context for trusted peer cert load"); + FreeDer(&der); + return BAD_FUNC_ARG; + } + /* add trusted peer cert */ + ret = AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone); + done = 1; + } +#endif /* WOLFSSL_TRUST_PEER_CERT */ else if (type == CERT_TYPE) { if (ssl) { - if (ssl->buffers.weOwnCert && ssl->buffers.certificate.buffer) - XFREE(ssl->buffers.certificate.buffer, heap, dynamicType); + /* Make sure previous is free'd */ + if (ssl->buffers.weOwnCert) { + FreeDer(&ssl->buffers.certificate); + #ifdef KEEP_OUR_CERT + FreeX509(ssl->ourCert); + if (ssl->ourCert) { + XFREE(ssl->ourCert, ssl->heap, DYNAMIC_TYPE_X509); + ssl->ourCert = NULL; + } + #endif + } ssl->buffers.certificate = der; + #ifdef KEEP_OUR_CERT + ssl->keepCert = 1; /* hold cert for ssl lifetime */ + #endif ssl->buffers.weOwnCert = 1; } else if (ctx) { - if (ctx->certificate.buffer) - XFREE(ctx->certificate.buffer, heap, dynamicType); - ctx->certificate = der; /* takes der over */ + FreeDer(&ctx->certificate); /* Make sure previous is free'd */ + #ifdef KEEP_OUR_CERT + if (ctx->ourCert) { + if (ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + } + ctx->ourCert = NULL; + } + #endif + ctx->certificate = der; } } else if (type == PRIVATEKEY_TYPE) { if (ssl) { - if (ssl->buffers.weOwnKey && ssl->buffers.key.buffer) - XFREE(ssl->buffers.key.buffer, heap, dynamicType); + /* Make sure previous is free'd */ + if (ssl->buffers.weOwnKey) { + FreeDer(&ssl->buffers.key); + } ssl->buffers.key = der; ssl->buffers.weOwnKey = 1; } else if (ctx) { - if (ctx->privateKey.buffer) - XFREE(ctx->privateKey.buffer, heap, dynamicType); - ctx->privateKey = der; /* takes der over */ + FreeDer(&ctx->privateKey); + ctx->privateKey = der; } } else { - XFREE(der.buffer, heap, dynamicType); - return SSL_BAD_CERTTYPE; + FreeDer(&der); + return WOLFSSL_BAD_CERTTYPE; } - if (type == PRIVATEKEY_TYPE && format != SSL_FILETYPE_RAW) { - #ifndef NO_RSA - if (!eccKey) { - /* make sure RSA key can be used */ - word32 idx = 0; - #ifdef WOLFSSL_SMALL_STACK - RsaKey* key = NULL; - #else - RsaKey key[1]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (key == NULL) - return MEMORY_E; - #endif - - ret = wc_InitRsaKey(key, 0); - 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 */ - #endif - if (!eccKey) - ret = SSL_BAD_FILE; - } else { - rsaKey = 1; - (void)rsaKey; /* for no ecc builds */ - } - } - - wc_FreeRsaKey(key); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - if (ret != 0) - return ret; - } + if (done == 1) { + /* No operation, just skip the next section */ + } + else if (type == PRIVATEKEY_TYPE && format != WOLFSSL_FILETYPE_RAW) { + #if defined(WOLFSSL_ENCRYPTED_KEYS) || defined(HAVE_PKCS8) + keyFormat = algId; #endif - #ifdef HAVE_ECC - if (!rsaKey) { - /* 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) { - wc_ecc_free(&key); - return SSL_BAD_FILE; + ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx, &resetSuites, + &keyFormat, heap, devId); + + #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED) + /* for WOLFSSL_FILETYPE_PEM, PemToDer manages the decryption */ + /* If private key type PKCS8 header wasn't already removed (algoId == 0) */ + if ((ret != 0 || keyFormat == 0) + && format != WOLFSSL_FILETYPE_PEM && info->passwd_cb && algId == 0) + { + int passwordSz = NAME_SZ; + #ifndef WOLFSSL_SMALL_STACK + char password[NAME_SZ]; + #else + char* password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING); + if (password == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); + #endif + FreeDer(&der); + return MEMORY_E; } - wc_ecc_free(&key); - eccKey = 1; - if (ctx) - ctx->haveStaticECC = 1; - if (ssl) - ssl->options.haveStaticECC = 1; + #endif + /* get password */ + ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ, + info->passwd_userdata); + if (ret >= 0) { + passwordSz = ret; + + /* PKCS8 decrypt */ + ret = ToTraditionalEnc(der->buffer, der->length, + password, passwordSz, &algId); + if (ret >= 0) { + der->length = ret; + } + /* ignore failures and try parsing as unencrypted */ + + ForceZero(password, passwordSz); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(password, heap, DYNAMIC_TYPE_STRING); + #endif + ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx, + &resetSuites, &keyFormat, heap, devId); } - #endif /* HAVE_ECC */ + #endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */ + + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); + #endif + + if (ret != 0) + return ret; + if (keyFormat == 0) + return WOLFSSL_BAD_FILE; + + (void)devId; } else if (type == CERT_TYPE) { #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; + DecodedCert* cert; #else DecodedCert cert[1]; #endif + #ifdef HAVE_PK_CALLBACKS + int keyType = 0; + #endif #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap, + DYNAMIC_TYPE_DCERT); if (cert == NULL) return MEMORY_E; #endif WOLFSSL_MSG("Checking cert signature type"); - InitDecodedCert(cert, der.buffer, der.length, heap); + InitDecodedCert(cert, der->buffer, der->length, heap); if (DecodeToKey(cert, 0) < 0) { WOLFSSL_MSG("Decode to key failed"); + FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, 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; + case CTC_ED448: + WOLFSSL_MSG("ED448 cert signature"); + if (ssl) + ssl->options.haveECDSAsig = 1; + else if (ctx) + ctx->haveECDSAsig = 1; break; default: WOLFSSL_MSG("Not ECDSA cert signature"); break; } - #ifdef HAVE_ECC - if (ctx) - ctx->pkCurveOID = cert->pkCurveOID; - if (ssl) + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + 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 + #ifdef HAVE_ED448 + else if (cert->keyOID == ED448k) { + 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 + #ifdef HAVE_ED448 + else if (cert->keyOID == ED448k) { + ctx->haveECC = 1; + } + #endif + #else + ctx->haveECC = ctx->haveECDSAsig; + #endif + } + #endif + + /* check key size of cert unless specified not to */ + switch (cert->keyOID) { + #ifndef NO_RSA + case RSAk: + #ifdef HAVE_PK_CALLBACKS + keyType = rsa_sa_algo; + #endif + #ifdef HAVE_PKCS11 + if (ctx) { + ctx->privateKeyType = rsa_sa_algo; + } + else { + ssl->buffers.keyType = rsa_sa_algo; + } + #endif + /* Determine RSA key size by parsing public key */ + idx = 0; + ret = wc_RsaPublicKeyDecode_ex(cert->publicKey, &idx, + cert->pubKeySize, NULL, (word32*)&keySz, NULL, NULL); + if (ret < 0) + break; + + if (ssl && !ssl->options.verifyNone) { + if (ssl->options.minRsaKeySz < 0 || + keySz < (int)ssl->options.minRsaKeySz) { + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("Certificate RSA key size too small"); + } + } + else if (ctx && !ctx->verifyNone) { + if (ctx->minRsaKeySz < 0 || + keySz < (int)ctx->minRsaKeySz) { + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("Certificate RSA key size too small"); + } + } + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + #ifdef HAVE_PK_CALLBACKS + keyType = ecc_dsa_sa_algo; + #endif + #ifdef HAVE_PKCS11 + if (ctx) { + ctx->privateKeyType = ecc_dsa_sa_algo; + } + else { + ssl->buffers.keyType = ecc_dsa_sa_algo; + } + #endif + /* Determine ECC key size based on curve */ + keySz = wc_ecc_get_curve_size_from_id( + wc_ecc_get_oid(cert->pkCurveOID, NULL, NULL)); + + if (ssl && !ssl->options.verifyNone) { + if (ssl->options.minEccKeySz < 0 || + keySz < (int)ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate ECC key size error"); + } + } + else if (ctx && !ctx->verifyNone) { + if (ctx->minEccKeySz < 0 || + keySz < (int)ctx->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate ECC key size error"); + } + } + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + #ifdef HAVE_PK_CALLBACKS + keyType = ed25519_sa_algo; + #endif + #ifdef HAVE_PKCS11 + if (ctx) { + ctx->privateKeyType = ed25519_sa_algo; + } + else { + ssl->buffers.keyType = ed25519_sa_algo; + } + #endif + /* ED25519 is fixed key size */ + keySz = ED25519_KEY_SIZE; + if (ssl && !ssl->options.verifyNone) { + if (ssl->options.minEccKeySz < 0 || + keySz < (int)ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate Ed key size error"); + } + } + else if (ctx && !ctx->verifyNone) { + if (ctx->minEccKeySz < 0 || + keySz < (int)ctx->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate ECC key size error"); + } + } + break; + #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED448 + case ED448k: + #ifdef HAVE_PK_CALLBACKS + keyType = ed448_sa_algo; + #endif + #ifdef HAVE_PKCS11 + if (ctx) { + ctx->privateKeyType = ed448_sa_algo; + } + else { + ssl->buffers.keyType = ed448_sa_algo; + } + #endif + /* ED448 is fixed key size */ + keySz = ED448_KEY_SIZE; + if (ssl && !ssl->options.verifyNone) { + if (ssl->options.minEccKeySz < 0 || + keySz < (int)ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate Ed key size error"); + } + } + else if (ctx && !ctx->verifyNone) { + if (ctx->minEccKeySz < 0 || + keySz < (int)ctx->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate ECC key size error"); + } + } + break; + #endif /* HAVE_ED448 */ + + default: + WOLFSSL_MSG("No key size check done on certificate"); + break; /* do no check if not a case for the key */ + } + + #ifdef HAVE_PK_CALLBACKS + if (ssl && ssl->buffers.keyType == 0) { + ssl->buffers.keyType = keyType; + ssl->buffers.keySz = keySz; + } + else if (ctx && ctx->privateKeyType == 0) { + ctx->privateKeyType = keyType; + ctx->privateKeySz = keySz; + } #endif FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cert, heap, DYNAMIC_TYPE_DCERT); #endif + + if (ret != 0) { + done = 1; + } } - return SSL_SUCCESS; + if (done == 1) { + #ifndef NO_WOLFSSL_CM_VERIFY + if ((type == CA_TYPE) || (type == CERT_TYPE)) { + /* Call to over-ride status */ + if ((ctx != NULL) && (ctx->cm != NULL) && + (ctx->cm->verifyCallback != NULL)) { + ret = CM_VerifyBuffer_ex(ctx->cm, buff, + sz, format, (ret == WOLFSSL_SUCCESS ? 0 : ret)); + } + } + #endif /* NO_WOLFSSL_CM_VERIFY */ + + return ret; + } + + + 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 + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + + /* let's reset suites */ + 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 WOLFSSL_SUCCESS; } /* CA PEM file for verification, may have multiple/chain certs to process */ static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, - long sz, int format, int type, WOLFSSL* ssl) + long sz, int format, int type, WOLFSSL* ssl, int verify) { long used = 0; int ret = 0; @@ -2781,34 +5778,248 @@ static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, long consumed = 0; ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl, - &consumed, 0); + &consumed, 0, verify); - if (ret == SSL_NO_PEM_HEADER && gotOne) { - WOLFSSL_MSG("We got one good PEM file so stuff at end ok"); - ret = SSL_SUCCESS; - break; + if (ret < 0) { +#if defined(WOLFSSL_WPAS) && defined(HAVE_CRL) + 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(" Processed a CRL"); + wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer, + der->length, WOLFSSL_FILETYPE_ASN1); + FreeDer(&der); + used += info.consumed; + continue; + } +#endif + + if (consumed > 0) { /* Made progress in file */ + WOLFSSL_ERROR(ret); + WOLFSSL_MSG("CA Parse failed, with progress in file."); + WOLFSSL_MSG("Search for other certs in file"); + } + else { + WOLFSSL_MSG("CA Parse failed, no progress in file."); + WOLFSSL_MSG("Do not continue search for other certs in file"); + break; + } + } + else { + WOLFSSL_MSG(" Processed a CA"); + gotOne = 1; } - - if (ret < 0) - break; - - WOLFSSL_MSG(" Processed a CA"); - gotOne = 1; used += consumed; } + if (gotOne) { + WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK"); + return WOLFSSL_SUCCESS; + } + return ret; +} + + +static WC_INLINE WOLFSSL_METHOD* cm_pick_method(void) +{ + #ifndef NO_WOLFSSL_CLIENT + #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3) + return wolfSSLv3_client_method(); + #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10) + return wolfTLSv1_client_method(); + #elif !defined(NO_OLD_TLS) + return wolfTLSv1_1_client_method(); + #elif !defined(WOLFSSL_NO_TLS12) + return wolfTLSv1_2_client_method(); + #elif defined(WOLFSSL_TLS13) + return wolfTLSv1_3_client_method(); + #else + return NULL; + #endif + #elif !defined(NO_WOLFSSL_SERVER) + #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3) + return wolfSSLv3_server_method(); + #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10) + return wolfTLSv1_server_method(); + #elif !defined(NO_OLD_TLS) + return wolfTLSv1_1_server_method(); + #elif !defined(WOLFSSL_NO_TLS12) + return wolfTLSv1_2_server_method(); + #elif defined(WOLFSSL_TLS13) + return wolfTLSv1_3_server_method(); + #else + return NULL; + #endif + #else + return NULL; + #endif +} + + +/* like load verify locations, 1 for success, < 0 for error */ +int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm, + const unsigned char* in, long sz, int format) +{ + int ret = WOLFSSL_FATAL_ERROR; + WOLFSSL_CTX* tmp; + + WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer"); + + if (cm == NULL) { + WOLFSSL_MSG("No CertManager error"); + return ret; + } + tmp = wolfSSL_CTX_new(cm_pick_method()); + + if (tmp == NULL) { + WOLFSSL_MSG("CTX new failed"); + return ret; + } + + /* for tmp use */ + wolfSSL_CertManagerFree(tmp->cm); + tmp->cm = cm; + + ret = wolfSSL_CTX_load_verify_buffer(tmp, in, sz, format); + + /* don't loose our good one */ + tmp->cm = NULL; + wolfSSL_CTX_free(tmp); + + return ret; +} + +#ifdef HAVE_CRL + +int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm, + const unsigned char* buff, long sz, int type) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLBuffer"); + if (cm == NULL) + return BAD_FUNC_ARG; + + if (cm->crl == NULL) { + if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Enable CRL failed"); + return WOLFSSL_FATAL_ERROR; + } + } + + return BufferLoadCRL(cm->crl, buff, sz, type, VERIFY); +} + +int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerFreeCRL"); + if (cm == NULL) + return BAD_FUNC_ARG; + if (cm->crl != NULL){ + FreeCRL(cm->crl, 1); + cm->crl = NULL; + } + return WOLFSSL_SUCCESS; +} + +int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, + long sz, int type) +{ + WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type); +} + + +int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff, + long sz, int type) +{ + WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer"); + + if (ssl == NULL || ssl->ctx == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_CertManagerLoadCRLBuffer(ssl->ctx->cm, buff, sz, type); +} + + +#endif /* HAVE_CRL */ + +/* turn on CRL if off and compiled in, set options */ +int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options) +{ + int ret = WOLFSSL_SUCCESS; + + (void)options; + + WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL"); + if (cm == NULL) + return BAD_FUNC_ARG; + + #ifdef HAVE_CRL + if (cm->crl == NULL) { + cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap, + DYNAMIC_TYPE_CRL); + if (cm->crl == NULL) + return MEMORY_E; + + if (InitCRL(cm->crl, cm) != 0) { + WOLFSSL_MSG("Init CRL failed"); + FreeCRL(cm->crl, 1); + cm->crl = NULL; + return WOLFSSL_FAILURE; + } + + #ifdef HAVE_CRL_IO + cm->crl->crlIOCb = EmbedCrlLookup; + #endif + } + + cm->crlEnabled = 1; + if (options & WOLFSSL_CRL_CHECKALL) + cm->crlCheckAll = 1; + #else + ret = NOT_COMPILED_IN; + #endif + return ret; } -/* Verify the ceritficate, SSL_SUCCESS for ok, < 0 for error */ -int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff, - long sz, int format) +int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL"); + if (cm == NULL) + return BAD_FUNC_ARG; + + cm->crlEnabled = 0; + + return WOLFSSL_SUCCESS; +} + +#ifndef NO_WOLFSSL_CM_VERIFY +void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm, VerifyCallback vc) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerSetVerify"); + if (cm == NULL) + return; + + cm->verifyCallback = vc; +} +#endif /* NO_WOLFSSL_CM_VERIFY */ + +/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */ +int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const byte* buff, + long sz, int format, int err_val) { int ret = 0; - buffer der; + DerBuffer* der = NULL; #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; + DecodedCert* cert; #else DecodedCert cert[1]; #endif @@ -2816,71 +6027,101 @@ int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff, WOLFSSL_ENTER("wolfSSL_CertManagerVerifyBuffer"); #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap, + DYNAMIC_TYPE_DCERT); if (cert == NULL) return MEMORY_E; #endif - der.buffer = NULL; - der.length = 0; - - if (format == SSL_FILETYPE_PEM) { - int eccKey = 0; /* not used */ - #ifdef WOLFSSL_SMALL_STACK - EncryptedInfo* info = NULL; - #else - EncryptedInfo info[1]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (info == NULL) { - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; + if (format == WOLFSSL_FILETYPE_PEM) { +#ifdef WOLFSSL_PEM_TO_DER + ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL); + if (ret != 0) { + FreeDer(&der); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + #endif + return ret; } - #endif - - info->set = 0; - info->ctx = NULL; - info->consumed = 0; - - ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, info, &eccKey); - - if (ret == 0) - InitDecodedCert(cert, der.buffer, der.length, cm->heap); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + InitDecodedCert(cert, der->buffer, der->length, cm->heap); +#else + ret = NOT_COMPILED_IN; +#endif } - else + else { InitDecodedCert(cert, (byte*)buff, (word32)sz, cm->heap); + } if (ret == 0) ret = ParseCertRelative(cert, CERT_TYPE, 1, cm); +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + /* ret needs to be self-singer error for Qt compat */ + if (ret == ASN_NO_SIGNER_E && cert->selfSigned) + ret = ASN_SELF_SIGNED_E; +#endif + #ifdef HAVE_CRL if (ret == 0 && cm->crlEnabled) ret = CheckCertCRL(cm->crl, cert); #endif - FreeDecodedCert(cert); +#ifndef NO_WOLFSSL_CM_VERIFY + /* if verify callback has been set */ + if (cm->verifyCallback) { + buffer certBuf; + #ifdef WOLFSSL_SMALL_STACK + ProcPeerCertArgs* args; + args = (ProcPeerCertArgs*)XMALLOC( + sizeof(ProcPeerCertArgs), cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args == NULL) { + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + return MEMORY_E; + } + #else + ProcPeerCertArgs args[1]; + #endif - XFREE(der.buffer, cm->heap, DYNAMIC_TYPE_CERT); -#ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + certBuf.buffer = (byte*)buff; + certBuf.length = (unsigned int)sz; + XMEMSET(args, 0, sizeof(ProcPeerCertArgs)); + + args->totalCerts = 1; + args->certs = &certBuf; + args->dCert = cert; + args->dCertInit = 1; + + if (err_val != 0) { + ret = err_val; + } + ret = DoVerifyCallback(cm, NULL, ret, args); + #ifdef WOLFSSL_SMALL_STACK + XFREE(args, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } +#else + (void)err_val; #endif - return ret == 0 ? SSL_SUCCESS : ret; + FreeDecodedCert(cert); + FreeDer(&der); +#ifdef WOLFSSL_SMALL_STACK + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); +#endif + + return ret == 0 ? WOLFSSL_SUCCESS : ret; } - +/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */ +int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff, + long sz, int format) +{ + return CM_VerifyBuffer_ex(cm, buff, sz, format, 0); +} /* 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; @@ -2891,7 +6132,7 @@ int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options) #ifdef HAVE_OCSP if (cm->ocsp == NULL) { cm->ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm->heap, - DYNAMIC_TYPE_OCSP); + DYNAMIC_TYPE_OCSP); if (cm->ocsp == NULL) return MEMORY_E; @@ -2899,7 +6140,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; @@ -2914,6 +6155,7 @@ int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options) #ifndef WOLFSSL_USER_IO cm->ocspIOCb = EmbedOcspLookup; cm->ocspRespFreeCb = EmbedOcspRespFree; + cm->ocspIOCtx = cm->heap; #endif /* WOLFSSL_USER_IO */ #else ret = NOT_COMPILED_IN; @@ -2931,14 +6173,70 @@ 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 = 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) + #ifndef NO_WOLFSSL_SERVER + 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 WOLFSSL_FAILURE; + } + } + + #ifndef WOLFSSL_USER_IO + cm->ocspIOCb = EmbedOcspLookup; + cm->ocspRespFreeCb = EmbedOcspRespFree; + cm->ocspIOCtx = cm->heap; + #endif /* WOLFSSL_USER_IO */ + #endif /* NO_WOLFSSL_SERVER */ + cm->ocspStaplingEnabled = 1; +#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; @@ -2954,44 +6252,60 @@ 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 InitDecodedCert(cert, der, sz, NULL); - if ((ret = ParseCertRelative(cert, CERT_TYPE, NO_VERIFY, cm)) != 0) { + if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm)) != 0) { WOLFSSL_MSG("ParseCert failed"); } - else if ((ret = CheckCertOCSP(cm->ocsp, cert)) != 0) { + else if ((ret = CheckCertOCSP(cm->ocsp, cert, NULL)) != 0) { WOLFSSL_MSG("CheckCertOCSP failed"); } 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; } +WOLFSSL_API int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *cm, + byte *response, int responseSz, buffer *responseBuffer, + CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP_Staple"); + if (cm == NULL || response == NULL) + return BAD_FUNC_ARG; + if (cm->ocspEnabled == 0) + return WOLFSSL_SUCCESS; + + ret = CheckOcspResponse(cm->ocsp, response, responseSz, responseBuffer, status, + entry, ocspRequest); + + return ret == 0 ? WOLFSSL_SUCCESS : ret; +} int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm, - const char* url) + const char* url) { WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSPOverrideURL"); if (cm == NULL) return BAD_FUNC_ARG; - XFREE(cm->ocspOverrideURL, cm->heap, 0); + XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL); if (url != NULL) { int urlSz = (int)XSTRLEN(url) + 1; - cm->ocspOverrideURL = (char*)XMALLOC(urlSz, cm->heap, 0); + cm->ocspOverrideURL = (char*)XMALLOC(urlSz, cm->heap, DYNAMIC_TYPE_URL); if (cm->ocspOverrideURL != NULL) { XMEMCPY(cm->ocspOverrideURL, url, urlSz); } @@ -3001,7 +6315,7 @@ int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm, else cm->ocspOverrideURL = NULL; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -3016,7 +6330,7 @@ int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm, cm->ocspRespFreeCb = respFreeCb; cm->ocspIOCtx = ioCbCtx; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -3029,7 +6343,6 @@ int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options) return BAD_FUNC_ARG; } - int wolfSSL_DisableOCSP(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_DisableOCSP"); @@ -3040,6 +6353,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"); @@ -3054,9 +6385,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; } @@ -3092,33 +6425,52 @@ int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX* ctx, const char* url) } -int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, - CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx) +int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, CbOCSPIO ioCb, + CbOCSPRespFree respFreeCb, void* ioCbCtx) { WOLFSSL_ENTER("wolfSSL_CTX_SetOCSP_Cb"); if (ctx) - return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb, respFreeCb, ioCbCtx); + return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb, + respFreeCb, ioCbCtx); else return BAD_FUNC_ARG; } +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) +int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPStapling"); + if (ctx) + return wolfSSL_CertManagerEnableOCSPStapling(ctx->cm); + else + return BAD_FUNC_ARG; +} + +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 */ +/* macro to get verify settings for AddCA */ +#define GET_VERIFY_SETTING_CTX(ctx) \ + (ctx && ctx->verifyNone ? NO_VERIFY : VERIFY) +#define GET_VERIFY_SETTING_SSL(ssl) \ + (ssl && ssl->options.verifyNone ? NO_VERIFY : VERIFY) #ifndef NO_FILESYSTEM - #if defined(WOLFSSL_MDK_ARM) - extern FILE * wolfSSL_fopen(const char *name, const char *mode) ; - #define XFOPEN wolfSSL_fopen - #else - #define XFOPEN fopen - #endif - /* process a file with name fname into ctx of format and type userChain specifies a user certificate chain to pass during handshake */ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, - WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl) + WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl, int verify) { #ifdef WOLFSSL_SMALL_STACK byte staticBuffer[1]; /* force heap usage */ @@ -3130,45 +6482,79 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, int ret; long sz = 0; XFILE file; - void* heapHint = ctx ? ctx->heap : NULL; + void* heapHint = wolfSSL_CTX_GetHeap(ctx, ssl); + const char* header = NULL; + const char* footer = NULL; (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; - XFSEEK(file, 0, XSEEK_END); + if (file == XBADFILE) return WOLFSSL_BAD_FILE; + if (XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } sz = XFTELL(file); XREWIND(file); + if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { + WOLFSSL_MSG("ProcessFile file size error"); + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + if (sz > (long)sizeof(staticBuffer)) { WOLFSSL_MSG("Getting dynamic buffer"); 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) { - XFCLOSE(file); - return SSL_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 && format == SSL_FILETYPE_PEM) - ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl); + /* Try to detect type by parsing cert header and footer */ + if (type == DETECT_CERT_TYPE) { + if (wc_PemGetHeaderFooter(CA_TYPE, &header, &footer) == 0 && + (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) { + type = CA_TYPE; + } +#ifdef HAVE_CRL + else if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 && + (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) { + type = CRL_TYPE; + } +#endif + else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 && + (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) { + type = CERT_TYPE; + } + else { + WOLFSSL_MSG("Failed to detect certificate type"); + if (dynamic) + XFREE(myBuffer, heapHint, DYNAMIC_TYPE_FILE); + XFCLOSE(file); + return WOLFSSL_BAD_CERTTYPE; + } + } + if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE) + && format == WOLFSSL_FILETYPE_PEM) { + ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl, + verify); + } #ifdef HAVE_CRL else if (type == CRL_TYPE) - ret = BufferLoadCRL(crl, myBuffer, sz, format); + ret = BufferLoadCRL(crl, myBuffer, sz, format, verify); #endif else ret = ProcessBuffer(ctx, myBuffer, sz, format, type, ssl, NULL, - userChain); + userChain, verify); } XFCLOSE(file); @@ -3178,121 +6564,139 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, return ret; } - /* loads file then loads each file in path, no c_rehash */ -int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, - const char* path) +int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file, + const char* path, word32 flags) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; +#ifndef NO_WOLFSSL_DIR + int fileRet; + int successCount = 0; + int failCount = 0; +#endif + int verify; - WOLFSSL_ENTER("wolfSSL_CTX_load_verify_locations"); - (void)path; + WOLFSSL_MSG("wolfSSL_CTX_load_verify_locations_ex"); - if (ctx == NULL || (file == NULL && path == NULL) ) - return SSL_FAILURE; + if (ctx == NULL || (file == NULL && path == NULL)) { + return WOLFSSL_FAILURE; + } - if (file) - ret = ProcessFile(ctx, file, SSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL); + verify = GET_VERIFY_SETTING_CTX(ctx); + if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) + verify = VERIFY_SKIP_DATE; + + if (file) { + ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0, + NULL, verify); +#ifndef NO_WOLFSSL_DIR + if (ret == WOLFSSL_SUCCESS) + successCount++; +#endif + } + + if (ret == WOLFSSL_SUCCESS && path) { +#ifndef NO_WOLFSSL_DIR + char* name = NULL; + #ifdef WOLFSSL_SMALL_STACK + ReadDirCtx* readCtx; + 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; - } - - 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); + fileRet = wc_ReadDirFirst(readCtx, path, &name); + while (fileRet == 0 && name) { + WOLFSSL_MSG(name); /* log file name */ + ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, CA_TYPE, + NULL, 0, NULL, verify); + if (ret != WOLFSSL_SUCCESS) { + /* handle flags for ignoring errors, skipping expired certs or + by PEM certificate header error */ + if ( (flags & WOLFSSL_LOAD_FLAG_IGNORE_ERR) || + ((flags & WOLFSSL_LOAD_FLAG_PEM_CA_ONLY) && + (ret == ASN_NO_PEM_HEADER))) { + /* Do not fail here if a certificate fails to load, + continue to next file */ + ret = WOLFSSL_SUCCESS; + } + else { + WOLFSSL_ERROR(ret); + WOLFSSL_MSG("Load CA file failed, continuing"); + failCount++; + } } - } while (ret == SSL_SUCCESS && FindNextFileA(hFind, &FindFileData)); + else { + successCount++; + } + fileRet = wc_ReadDirNext(readCtx, path, &name); + } + wc_ReadDirClose(readCtx); - #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 (fileRet != WC_READDIR_NOFILE) { + ret = fileRet; + } + /* report failure if no files were loaded or there were failures */ + else if (successCount == 0 || failCount > 0) { + /* use existing error code if exists */ + if (ret == WOLFSSL_SUCCESS) + ret = WOLFSSL_FAILURE; + } + else { + ret = WOLFSSL_SUCCESS; } #ifdef WOLFSSL_SMALL_STACK - name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (name == NULL) - 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; + (void)flags; +#endif } return ret; } +WOLFSSL_ABI +int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, + const char* path) +{ + return wolfSSL_CTX_load_verify_locations_ex(ctx, file, path, + WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS); +} -/* Verify the ceritficate, SSL_SUCCESS for ok, < 0 for error */ + +#ifdef WOLFSSL_TRUST_PEER_CERT +/* Used to specify a peer cert to match when connecting + ctx : the ctx structure to load in peer cert + file: the string name of cert file + type: type of format such as PEM/DER + */ +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 WOLFSSL_FAILURE; + } + + return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL, + GET_VERIFY_SETTING_CTX(ctx)); +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + +/* 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 @@ -3305,15 +6709,18 @@ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, WOLFSSL_ENTER("wolfSSL_CertManagerVerify"); - if (file == XBADFILE) return SSL_BAD_FILE; - XFSEEK(file, 0, XSEEK_END); + if (file == XBADFILE) return WOLFSSL_BAD_FILE; + if(XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } sz = XFTELL(file); XREWIND(file); - if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { - WOLFSSL_MSG("CertManagerVerify file bad size"); + if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { + WOLFSSL_MSG("CertManagerVerify file size error"); XFCLOSE(file); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } if (sz > (long)sizeof(staticBuffer)) { @@ -3321,13 +6728,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); @@ -3339,31 +6746,11 @@ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, } -static INLINE WOLFSSL_METHOD* cm_pick_method(void) -{ - #ifndef NO_WOLFSSL_CLIENT - #ifdef NO_OLD_TLS - return wolfTLSv1_2_client_method(); - #else - return wolfSSLv3_client_method(); - #endif - #elif !defined(NO_WOLFSSL_SERVER) - #ifdef NO_OLD_TLS - return wolfTLSv1_2_server_method(); - #else - return wolfSSLv3_server_method(); - #endif - #else - return NULL; - #endif -} - - /* like load verify locations, 1 for success, < 0 for error */ 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"); @@ -3385,76 +6772,79 @@ int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file, ret = wolfSSL_CTX_load_verify_locations(tmp, file, path); - /* don't loose our good one */ + /* don't lose our good one */ tmp->cm = NULL; wolfSSL_CTX_free(tmp); return ret; } - - -/* turn on CRL if off and compiled in, set options */ -int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options) +#ifndef NO_CHECK_PRIVATE_KEY +/* Check private against public in certificate for match + * + * ctx WOLFSSL_CTX structure to check private key in + * + * Returns SSL_SUCCESS on good private key and SSL_FAILURE if miss matched. */ +int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx) { - int ret = SSL_SUCCESS; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* der = NULL; +#else + DecodedCert der[1]; +#endif + word32 size; + byte* buff; + int ret; - (void)options; + WOLFSSL_ENTER("wolfSSL_CTX_check_private_key"); - WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL"); - if (cm == NULL) - return BAD_FUNC_ARG; + if (ctx == NULL) { + return WOLFSSL_FAILURE; + } - #ifdef HAVE_CRL - if (cm->crl == NULL) { - cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap, - DYNAMIC_TYPE_CRL); - if (cm->crl == NULL) - return MEMORY_E; +#ifndef NO_CERTS +#ifdef WOLFSSL_SMALL_STACK + der = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); + if (der == NULL) + return MEMORY_E; +#endif - if (InitCRL(cm->crl, cm) != 0) { - WOLFSSL_MSG("Init CRL failed"); - FreeCRL(cm->crl, 1); - cm->crl = NULL; - return SSL_FAILURE; - } - } - cm->crlEnabled = 1; - if (options & WOLFSSL_CRL_CHECKALL) - cm->crlCheckAll = 1; - #else - ret = NOT_COMPILED_IN; + size = ctx->certificate->length; + buff = ctx->certificate->buffer; + InitDecodedCert(der, buff, size, ctx->heap); + if (ParseCertRelative(der, CERT_TYPE, NO_VERIFY, NULL) != 0) { + FreeDecodedCert(der); + #ifdef WOLFSSL_SMALL_STACK + XFREE(der, NULL, DYNAMIC_TYPE_DCERT); #endif + return WOLFSSL_FAILURE; + } - return ret; -} - - -int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm) -{ - WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL"); - if (cm == NULL) - return BAD_FUNC_ARG; - - cm->crlEnabled = 0; - - return SSL_SUCCESS; -} - - -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; + size = ctx->privateKey->length; + buff = ctx->privateKey->buffer; + ret = wc_CheckPrivateKey(buff, size, der); + FreeDecodedCert(der); +#ifdef WOLFSSL_SMALL_STACK + XFREE(der, NULL, DYNAMIC_TYPE_DCERT); +#endif + + if (ret == 1) { + return WOLFSSL_SUCCESS; + } + else { + return WOLFSSL_FAILURE; + } +#else + WOLFSSL_MSG("NO_CERTS is defined, can not check private key"); + return WOLFSSL_FAILURE; +#endif } +#endif /* !NO_CHECK_PRIVATE_KEY */ #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; @@ -3470,18 +6860,17 @@ 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 InitDecodedCert(cert, der, sz, NULL); - if ((ret = ParseCertRelative(cert, CERT_TYPE, NO_VERIFY, cm)) != 0) { + if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm)) != 0) { WOLFSSL_MSG("ParseCert failed"); } else if ((ret = CheckCertCRL(cm->crl, cert)) != 0) { @@ -3490,10 +6879,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; } @@ -3505,9 +6894,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) @@ -3517,16 +6917,15 @@ 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; } } return LoadCRL(cm->crl, path, type, monitor); } - int wolfSSL_EnableCRL(WOLFSSL* ssl, int options) { WOLFSSL_ENTER("wolfSSL_EnableCRL"); @@ -3546,7 +6945,6 @@ int wolfSSL_DisableCRL(WOLFSSL* ssl) return BAD_FUNC_ARG; } - int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor) { WOLFSSL_ENTER("wolfSSL_LoadCRL"); @@ -3566,6 +6964,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) { @@ -3587,7 +6995,8 @@ int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx) } -int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path, int type, int monitor) +int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path, + int type, int monitor) { WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL"); if (ctx) @@ -3606,6 +7015,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 */ @@ -3614,125 +7034,69 @@ int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb) /* Add format parameter to allow DER load of CA files */ int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, - int format) + int format) { 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, + GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #endif /* WOLFSSL_DER_LOAD */ -#ifdef WOLFSSL_CERT_GEN - -/* load pem cert from file into der buffer, return der size or error */ -int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) -{ -#ifdef WOLFSSL_SMALL_STACK - EncryptedInfo* info = NULL; - byte staticBuffer[1]; /* force XMALLOC */ -#else - EncryptedInfo info[1]; - byte staticBuffer[FILE_BUFFER_SIZE]; -#endif - byte* fileBuf = staticBuffer; - int dynamic = 0; - int ret = 0; - int ecc = 0; - long sz = 0; - XFILE file = XFOPEN(fileName, "rb"); - buffer converted; - - WOLFSSL_ENTER("wolfSSL_PemCertToDer"); - - if (file == XBADFILE) - ret = SSL_BAD_FILE; - else { - XFSEEK(file, 0, XSEEK_END); - sz = XFTELL(file); - XREWIND(file); - - if (sz < 0) { - ret = SSL_BAD_FILE; - } - else if (sz > (long)sizeof(staticBuffer)) { - fileBuf = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_FILE); - if (fileBuf == NULL) - ret = MEMORY_E; - else - dynamic = 1; - } - - converted.buffer = 0; - - if (ret == 0) { - if ( (ret = (int)XFREAD(fileBuf, sz, 1, file)) < 0) - ret = SSL_BAD_FILE; - else { - #ifdef WOLFSSL_SMALL_STACK - info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (info == NULL) - ret = MEMORY_E; - else - #endif - { - ret = PemToDer(fileBuf, sz, CA_TYPE, &converted, 0, info, - &ecc); - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - } - } - - if (ret == 0) { - if (converted.length < (word32)derSz) { - XMEMCPY(derBuf, converted.buffer, converted.length); - ret = converted.length; - } - else - ret = BUFFER_E; - } - - XFREE(converted.buffer, 0, DYNAMIC_TYPE_CA); - } - - XFCLOSE(file); - if (dynamic) - XFREE(fileBuf, 0, DYNAMIC_TYPE_FILE); - } - - return ret; -} - -#endif /* WOLFSSL_CERT_GEN */ - +WOLFSSL_ABI int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file, - int format) + int format) { WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file"); - if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL) == SSL_SUCCESS) - return SSL_SUCCESS; - return SSL_FAILURE; + if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL, + GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; } -int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file,int format) +WOLFSSL_ABI +int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file, + int format) { WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file"); - if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL) - == SSL_SUCCESS) - return SSL_SUCCESS; - return SSL_FAILURE; + if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL, + GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; +} + + +/* Sets the max chain depth when verifying a certificate chain. Default depth + * is set to MAX_CHAIN_DEPTH. + * + * ctx WOLFSSL_CTX structure to set depth in + * depth max depth + */ +void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) { + WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth"); + + if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) { + WOLFSSL_MSG("Bad depth argument, too large or less than 0"); + return; + } + + ctx->verifyDepth = (byte)depth; } @@ -3742,112 +7106,60 @@ 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 } /* get cert chaining depth using ctx struct */ long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx) { - if(ctx == NULL) { + if (ctx == NULL) { return BAD_FUNC_ARG; } +#ifndef OPENSSL_EXTRA return MAX_CHAIN_DEPTH; +#else + return ctx->verifyDepth; +#endif } +WOLFSSL_ABI int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file) { - /* procces 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; + /* process up to MAX_CHAIN_DEPTH plus subject cert */ + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file"); - return SSL_FAILURE; + if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, NULL, 1, NULL, + GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; +} + + +int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx, + const char* file, int format) +{ + /* process up to MAX_CHAIN_DEPTH plus subject cert */ + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format"); + + if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL, + GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; } #ifndef NO_DH -/* server wrapper for ctx or ssl Diffie-Hellman parameters */ -static int wolfSSL_SetTmpDH_buffer_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - const unsigned char* buf, long sz, int format) -{ - buffer der; - int ret = 0; - int weOwnDer = 0; - word32 pSz = MAX_DH_SIZE; - word32 gSz = MAX_DH_SIZE; -#ifdef WOLFSSL_SMALL_STACK - byte* p = NULL; - byte* g = NULL; -#else - byte p[MAX_DH_SIZE]; - byte g[MAX_DH_SIZE]; -#endif - - der.buffer = (byte*)buf; - 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); - - if (p == NULL || g == NULL) { - XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM) - ret = SSL_BAD_FILETYPE; - else { - if (format == SSL_FILETYPE_PEM) { - der.buffer = NULL; - ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap, NULL,NULL); - weOwnDer = 1; - } - - if (ret == 0) { - if (wc_DhParamsLoad(der.buffer, der.length, p, &pSz, g, &gSz) < 0) - ret = SSL_BAD_FILETYPE; - else if (ssl) - ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz); - else - ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz); - } - } - - if (weOwnDer) - XFREE(der.buffer, ctx->heap, DYNAMIC_TYPE_KEY); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - - -/* server Diffie-Hellman parameters, SSL_SUCCESS on ok */ -int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz, - int format) -{ - return wolfSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format); -} - - -/* server ctx Diffie-Hellman parameters, SSL_SUCCESS on ok */ -int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf, - long sz, int format) -{ - return wolfSSL_SetTmpDH_buffer_wrapper(ctx, NULL, buf, sz, format); -} - - /* server Diffie-Hellman parameters */ static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, const char* fname, int format) @@ -3861,29 +7173,38 @@ static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, int dynamic = 0; int ret; long sz = 0; - XFILE file = XFOPEN(fname, "rb"); + XFILE file; - if (file == XBADFILE) return SSL_BAD_FILE; - XFSEEK(file, 0, XSEEK_END); + if (ctx == NULL || fname == NULL) + return BAD_FUNC_ARG; + + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) return WOLFSSL_BAD_FILE; + if(XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } sz = XFTELL(file); XREWIND(file); + if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { + WOLFSSL_MSG("SetTmpDH file size error"); + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + if (sz > (long)sizeof(staticBuffer)) { WOLFSSL_MSG("Getting dynamic buffer"); 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) { - XFCLOSE(file); - return SSL_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); @@ -3901,6 +7222,9 @@ static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, /* server Diffie-Hellman parameters */ int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* fname, int format) { + if (ssl == NULL) + return BAD_FUNC_ARG; + return wolfSSL_SetTmpDH_file_wrapper(ssl->ctx, ssl, fname, format); } @@ -3911,88 +7235,2545 @@ int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format) return wolfSSL_SetTmpDH_file_wrapper(ctx, NULL, fname, format); } - -int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz) -{ - if (ctx == NULL || keySz > 16000 || keySz % 8 != 0) - return BAD_FUNC_ARG; - - ctx->minDhKeySz = keySz / 8; - return SSL_SUCCESS; -} - - -int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz) -{ - if (ssl == NULL || keySz > 16000 || keySz % 8 != 0) - return BAD_FUNC_ARG; - - ssl->options.minDhKeySz = keySz / 8; - return SSL_SUCCESS; -} - - -int wolfSSL_GetDhKey_Sz(WOLFSSL* ssl) -{ - if (ssl == NULL) - return BAD_FUNC_ARG; - - return (ssl->options.dhKeySz * 8); -} - - #endif /* NO_DH */ +#endif /* NO_FILESYSTEM */ #ifdef OPENSSL_EXTRA /* put SSL type in extra for now, not very common */ +/* Converts a DER format key read from "bio" to a PKCS8 structure. + * + * bio input bio to read DER from + * pkey If not NULL then this pointer will be overwritten with a new PKCS8 + * structure. + * + * returns a WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success and NULL in fail + * case. + */ +WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio, + WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey) +{ + WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; +#ifdef WOLFSSL_PEM_TO_DER + unsigned char* mem = NULL; + int memSz; + int keySz; + word32 algId; + + WOLFSSL_MSG("wolfSSL_d2i_PKCS8_PKEY_bio()"); + + if (bio == NULL) { + return NULL; + } + + if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) { + return NULL; + } + + if ((keySz = wc_KeyPemToDer(mem, memSz, mem, memSz, NULL)) < 0) { + WOLFSSL_MSG("Not PEM format"); + keySz = memSz; + if ((keySz = ToTraditional_ex((byte*)mem, (word32)keySz, &algId)) < 0) { + return NULL; + } + } + + pkcs8 = wolfSSL_EVP_PKEY_new(); + if (pkcs8 == NULL) { + return NULL; + } + + pkcs8->pkey.ptr = (char*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (pkcs8->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkcs8); + return NULL; + } + XMEMCPY(pkcs8->pkey.ptr, mem, keySz); + pkcs8->pkey_sz = keySz; + + if (pkey != NULL) { + *pkey = pkcs8; + } +#else + (void)bio; + (void)pkey; +#endif /* WOLFSSL_PEM_TO_DER */ + + return pkcs8; +} + + +/* expecting DER format public key + * + * bio input bio to read DER from + * out If not NULL then this pointer will be overwritten with a new + * WOLFSSL_EVP_PKEY pointer + * + * returns a WOLFSSL_EVP_PKEY pointer on success and NULL in fail case. + */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** out) +{ + unsigned char* mem; + long memSz; + WOLFSSL_EVP_PKEY* pkey = NULL; + + WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio()"); + + if (bio == NULL) { + return NULL; + } + (void)out; + + memSz = wolfSSL_BIO_pending(bio); + if (memSz <= 0) { + return NULL; + } + + mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { + return NULL; + } + + if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { + pkey = wolfSSL_d2i_PUBKEY(NULL, (const unsigned char**)&mem, memSz); + if (out != NULL && pkey != NULL) { + *out = pkey; + } + } + + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return pkey; +} + + + +/* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure. + * + * out pointer to new WOLFSSL_EVP_PKEY structure. Can be NULL + * in DER buffer to convert + * inSz size of in buffer + * + * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL + * on fail + */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out, + const unsigned char** in, long inSz) +{ + WOLFSSL_EVP_PKEY* pkey = NULL; + const unsigned char* mem; + long memSz = inSz; + + WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY"); + + if (in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + mem = *in; + + #if !defined(NO_RSA) + { + RsaKey rsa; + word32 keyIdx = 0; + + /* test if RSA key */ + if (wc_InitRsaKey(&rsa, NULL) == 0 && + wc_RsaPublicKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) { + wc_FreeRsaKey(&rsa); + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey != NULL) { + pkey->pkey_sz = keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_RSA; + if (out != NULL) { + *out = pkey; + } + + pkey->ownRsa = 1; + pkey->rsa = wolfSSL_RSA_new(); + if (pkey->rsa == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + if (wolfSSL_RSA_LoadDer_ex(pkey->rsa, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, WOLFSSL_RSA_LOAD_PUBLIC) != 1) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + return pkey; + } + } + wc_FreeRsaKey(&rsa); + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + { + word32 keyIdx = 0; + ecc_key ecc; + + if (wc_ecc_init(&ecc) == 0 && + wc_EccPublicKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) { + wc_ecc_free(&ecc); + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey != NULL) { + pkey->pkey_sz = keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_EC; + if (out != NULL) { + *out = pkey; + } + + pkey->ownEcc = 1; + pkey->ecc = wolfSSL_EC_KEY_new(); + if (pkey->ecc == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + if (wolfSSL_EC_KEY_LoadDer_ex(pkey->ecc, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + return pkey; + } + } + wc_ecc_free(&ecc); + } + #endif /* HAVE_ECC */ + + #if !defined(NO_DSA) + { + DsaKey dsa; + word32 keyIdx = 0; + + /* test if DSA key */ + if (wc_InitDsaKey(&dsa) == 0 && + wc_DsaPublicKeyDecode(mem, &keyIdx, &dsa, (word32)memSz) == 0) { + wc_FreeDsaKey(&dsa); + pkey = wolfSSL_EVP_PKEY_new(); + + if (pkey != NULL) { + pkey->pkey_sz = keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_DSA; + if (out != NULL) { + *out = pkey; + } + + pkey->ownDsa = 1; + pkey->dsa = wolfSSL_DSA_new(); + if (pkey->dsa == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + + if (wolfSSL_DSA_LoadDer_ex(pkey->dsa, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, WOLFSSL_DSA_LOAD_PUBLIC) != 1) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + return pkey; + } + } + wc_FreeDsaKey(&dsa); + } + #endif /* NO_DSA */ + + #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) + { + DhKey dh; + word32 keyIdx = 0; + + /* test if DH key */ + if (wc_InitDhKey(&dh) == 0 && + wc_DhKeyDecode(mem, &keyIdx, &dh, (word32)memSz) == 0) { + wc_FreeDhKey(&dh); + pkey = wolfSSL_EVP_PKEY_new(); + + if (pkey != NULL) { + pkey->pkey_sz = (int)memSz; + pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, memSz); + pkey->type = EVP_PKEY_DH; + if (out != NULL) { + *out = pkey; + } + + pkey->ownDh = 1; + pkey->dh = wolfSSL_DH_new(); + if (pkey->dh == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + if (wolfSSL_DH_LoadDer(pkey->dh, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz) != WOLFSSL_SUCCESS) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + return pkey; + } + } + wc_FreeDhKey(&dh); + } + #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ + + return pkey; +} + + +/* Reads in a DER format key. If PKCS8 headers are found they are stripped off. + * + * type type of key + * out newly created WOLFSSL_EVP_PKEY structure + * in pointer to input key DER + * inSz size of in buffer + * + * On success a non null pointer is returned and the pointer in is advanced the + * same number of bytes read. + */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, + const unsigned char **in, long inSz) +{ + WOLFSSL_EVP_PKEY* local; + word32 idx = 0; + int ret; + word32 algId; + + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey"); + + if (in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + + /* Check if input buffer has PKCS8 header. In the case that it does not + * have a PKCS8 header then do not error out. */ + if ((ret = ToTraditionalInline_ex((const byte*)(*in), &idx, (word32)inSz, + &algId)) > 0) { + WOLFSSL_MSG("Found and removed PKCS8 header"); + } + else { + if (ret != ASN_PARSE_E) { + WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header"); + return NULL; + } + } + + if (out != NULL && *out != NULL) { + wolfSSL_EVP_PKEY_free(*out); + *out = NULL; + } + local = wolfSSL_EVP_PKEY_new(); + if (local == NULL) { + return NULL; + } + + /* sanity check on idx before use */ + if ((int)idx > inSz) { + WOLFSSL_MSG("Issue with index pointer"); + wolfSSL_EVP_PKEY_free(local); + local = NULL; + return NULL; + } + + local->type = type; + local->pkey_sz = (int)inSz - idx; + local->pkey.ptr = (char*)XMALLOC(inSz - idx, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (local->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(local); + local = NULL; + return NULL; + } + else { + XMEMCPY(local->pkey.ptr, *in + idx, inSz - idx); + } + + switch (type) { +#ifndef NO_RSA + case EVP_PKEY_RSA: + local->ownRsa = 1; + local->rsa = wolfSSL_RSA_new(); + if (local->rsa == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + if (wolfSSL_RSA_LoadDer_ex(local->rsa, + (const unsigned char*)local->pkey.ptr, local->pkey_sz, + WOLFSSL_RSA_LOAD_PRIVATE) != SSL_SUCCESS) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + break; +#endif /* NO_RSA */ +#ifdef HAVE_ECC + case EVP_PKEY_EC: + local->ownEcc = 1; + local->ecc = wolfSSL_EC_KEY_new(); + if (local->ecc == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + if (wolfSSL_EC_KEY_LoadDer(local->ecc, + (const unsigned char*)local->pkey.ptr, local->pkey_sz) + != SSL_SUCCESS) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + break; +#endif /* HAVE_ECC */ +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +#ifndef NO_DSA + case EVP_PKEY_DSA: + local->ownDsa = 1; + local->dsa = wolfSSL_DSA_new(); + if (local->dsa == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + if (wolfSSL_DSA_LoadDer(local->dsa, + (const unsigned char*)local->pkey.ptr, local->pkey_sz) + != SSL_SUCCESS) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + break; +#endif /* NO_DSA */ +#ifndef NO_DH + case EVP_PKEY_DH: + local->ownDh = 1; + local->dh = wolfSSL_DH_new(); + if (local->dh == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + if (wolfSSL_DH_LoadDer(local->dh, + (const unsigned char*)local->pkey.ptr, local->pkey_sz) + != SSL_SUCCESS) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + break; +#endif /* HAVE_DH */ +#endif /* WOLFSSL_QT || OPENSSL_ALL */ + default: + WOLFSSL_MSG("Unsupported key type"); + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + + /* advance pointer with success */ + if (local != NULL) { + if ((idx + local->pkey_sz) <= (word32)inSz) { + *in = *in + idx + local->pkey_sz; + } + + if (out != NULL) { + *out = local; + } + } + + return local; +} + +#ifndef NO_CERTS + +int wolfSSL_check_private_key(const WOLFSSL* ssl) +{ + DecodedCert der; + word32 size; + byte* buff; + int ret; + + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + + size = ssl->buffers.certificate->length; + buff = ssl->buffers.certificate->buffer; + InitDecodedCert(&der, buff, size, ssl->heap); +#ifdef HAVE_PK_CALLBACKS + ret = InitSigPkCb((WOLFSSL*)ssl, &der.sigCtx); + if (ret != 0) { + FreeDecodedCert(&der); + return ret; + } +#endif + + if (ParseCertRelative(&der, CERT_TYPE, NO_VERIFY, NULL) != 0) { + FreeDecodedCert(&der); + return WOLFSSL_FAILURE; + } + + size = ssl->buffers.key->length; + buff = ssl->buffers.key->buffer; + ret = wc_CheckPrivateKey(buff, size, &der); + FreeDecodedCert(&der); + return ret; +} + +#if defined(OPENSSL_ALL) +/* Returns the number of X509V3 extensions in X509 object, or 0 on failure */ +int wolfSSL_X509_get_ext_count(const WOLFSSL_X509* passedCert) +{ + int extCount = 0; + int length = 0; + int outSz = 0; + const byte* rawCert; + int sz = 0; + word32 idx = 0; + DecodedCert cert; + const byte* input; + + WOLFSSL_ENTER("wolfSSL_X509_get_ext_count()"); + if (passedCert == NULL) { + WOLFSSL_MSG("\tNot passed a certificate"); + return WOLFSSL_FAILURE; + } + + rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)passedCert, &outSz); + if (rawCert == NULL) { + WOLFSSL_MSG("\tpassedCert has no internal DerBuffer set."); + return WOLFSSL_FAILURE; + } + InitDecodedCert(&cert, rawCert, (word32)outSz, 0); + + if (ParseCert(&cert, CA_TYPE, NO_VERIFY, NULL) < 0) { + WOLFSSL_MSG("\tCertificate parsing failed"); + return WOLFSSL_FAILURE; + } + + input = cert.extensions; + sz = cert.extensionsSz; + + if (input == NULL || sz == 0) { + WOLFSSL_MSG("\tsz or input NULL error"); + FreeDecodedCert(&cert); + return WOLFSSL_FAILURE; + } + + if (input[idx++] != ASN_EXTENSIONS) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); + FreeDecodedCert(&cert); + return WOLFSSL_FAILURE; + } + + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: invalid length"); + FreeDecodedCert(&cert); + return WOLFSSL_FAILURE; + } + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)"); + FreeDecodedCert(&cert); + return WOLFSSL_FAILURE; + } + + while (idx < (word32)sz) { + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE"); + FreeDecodedCert(&cert); + return WOLFSSL_FAILURE; + } + idx += length; + extCount++; + } + FreeDecodedCert(&cert); + return extCount; +} + +/* Creates and returns pointer to a new X509_EXTENSION object in memory */ +WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_new(void) +{ + WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_new"); + + WOLFSSL_X509_EXTENSION* newExt; + newExt = (WOLFSSL_X509_EXTENSION*)XMALLOC(sizeof(WOLFSSL_X509_EXTENSION), + NULL, DYNAMIC_TYPE_X509_EXT); + if (newExt == NULL) + return NULL; + XMEMSET(newExt, 0, sizeof(WOLFSSL_X509_EXTENSION)); + + return newExt; +} + +void wolfSSL_X509_EXTENSION_free(WOLFSSL_X509_EXTENSION* x) +{ + WOLFSSL_ASN1_STRING asn1; + WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_free"); + if (x == NULL) + return; + + if (x->obj != NULL) + wolfSSL_ASN1_OBJECT_free(x->obj); + + asn1 = x->value; + if (asn1.length > 0 && asn1.data != NULL && asn1.isDynamic) + XFREE(asn1.data, NULL, DYNAMIC_TYPE_OPENSSL); + + wolfSSL_sk_free(x->ext_sk); + + XFREE(x, NULL, DYNAMIC_TYPE_X509_EXT); +} + +/* Creates and returns a new WOLFSSL_X509_EXTENSION stack. */ +WOLFSSL_STACK* wolfSSL_sk_new_x509_ext(void) +{ + WOLFSSL_STACK* sk; + WOLFSSL_ENTER("wolfSSL_sk_new_x509_ext"); + + sk = wolfSSL_sk_new_null(); + if (sk) { + sk->type = STACK_TYPE_X509_EXT; + } + return sk; +} + +/* return 1 on success 0 on fail */ +int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk,WOLFSSL_X509_EXTENSION* ext) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_X509_EXTENSION_push"); + + if (sk == NULL || ext == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.ext == NULL) { + sk->data.ext = ext; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_X509); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.ext = sk->data.ext; + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->data.ext = ext; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + +/* Free the structure for X509_EXTENSION stack + * + * sk stack to free nodes in + */ +void wolfSSL_sk_X509_EXTENSION_free(WOLFSSL_STACK* sk) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_X509_EXTENSION_free"); + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while ((node != NULL) && (sk->num > 1)) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + wolfSSL_X509_EXTENSION_free(tmp->data.ext); + XFREE(tmp, NULL, DYNAMIC_TYPE_X509); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + wolfSSL_X509_EXTENSION_free(sk->data.ext); + } + XFREE(sk, NULL, DYNAMIC_TYPE_X509); +} + +int wolfSSL_ASN1_BIT_STRING_set_bit(WOLFSSL_ASN1_BIT_STRING* str, int pos, + int val) +{ + int bytes_cnt, bit; + byte* temp; + + if (!str || (val != 0 && val != 1) || pos < 0) { + return WOLFSSL_FAILURE; + } + + bytes_cnt = pos/8; + bit = 1<<(7-(pos%8)); + + if (bytes_cnt+1 > str->length) { + if (!(temp = (byte*)XREALLOC(str->data, bytes_cnt+1, NULL, + DYNAMIC_TYPE_OPENSSL))) { + return WOLFSSL_FAILURE; + } + XMEMSET(temp+str->length, 0, bytes_cnt+1 - str->length); + str->data = temp; + str->length = bytes_cnt+1; + } + + str->data[bytes_cnt] &= ~bit; + str->data[bytes_cnt] |= val ? bit : 0; + + return WOLFSSL_SUCCESS; +} + +/* Gets the X509_EXTENSION* ext based on it's location in WOLFSSL_X509* x509. + * + * x509 : The X509 structure to look for the extension. + * loc : Location of the extension. If the extension is found at the given + * location, a new X509_EXTENSION structure is populated with extension-specific + * data based on the extension type. + + * Returns NULL on error or pointer to X509_EXTENSION structure containing the + * extension. The returned X509_EXTENSION should not be free'd by caller. + * The returned X509_EXTENSION is pushed onto a stack inside the x509 argument. + * This is later free'd when x509 is free'd. + * + * NOTE: for unknown extension NIDs, a X509_EXTENSION is populated with the + * extension oid as the ASN1_OBJECT (QT compatibility) + */ +WOLFSSL_X509_EXTENSION* wolfSSL_X509_get_ext(const WOLFSSL_X509* x509, int loc) +{ + WOLFSSL_X509_EXTENSION* ext = NULL; + WOLFSSL_ENTER("wolfSSL_X509_get_ext"); + if (x509 == NULL) + return NULL; + + ext = wolfSSL_X509_set_ext((WOLFSSL_X509*) x509, loc); + return ext; +} + +/* Pushes a new X509_EXTENSION* ext onto the stack inside WOLFSSL_X509* x509. + * This is currently a helper function for wolfSSL_X509_get_ext + * Caller does not free the returned WOLFSSL_X509_EXTENSION* + */ +WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) +{ + int extCount = 0, length = 0, outSz = 0, sz = 0, ret = 0; + int objSz = 0, isSet = 0; + const byte* rawCert; + const byte* input; + byte* oidBuf; + word32 oid, idx = 0, tmpIdx = 0; + WOLFSSL_X509_EXTENSION* ext = NULL; + WOLFSSL_ASN1_INTEGER* a; + WOLFSSL_STACK* sk; + DecodedCert cert; + + WOLFSSL_ENTER("wolfSSL_X509_set_ext"); + + if(x509 == NULL){ + WOLFSSL_MSG("\tNot passed a certificate"); + return NULL; + } + + if(loc <0 || (loc > wolfSSL_X509_get_ext_count(x509))){ + WOLFSSL_MSG("\tBad location argument"); + return NULL; + } + + ext = wolfSSL_X509_EXTENSION_new(); + if (ext == NULL) { + WOLFSSL_MSG("\tX509_EXTENSION_new() failed"); + return NULL; + } + + rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)x509, &outSz); + if (rawCert == NULL) { + WOLFSSL_MSG("\tX509_get_der() failed"); + wolfSSL_X509_EXTENSION_free(ext); + return NULL; + } + + InitDecodedCert( &cert, rawCert, (word32)outSz, 0); + + if (ParseCert(&cert, CA_TYPE, NO_VERIFY, NULL) < 0) { + WOLFSSL_MSG("\tCertificate parsing failed"); + wolfSSL_X509_EXTENSION_free(ext); + return NULL; + } + + input = cert.extensions; + sz = cert.extensionsSz; + + if (input == NULL || sz == 0) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + + if (input[idx++] != ASN_EXTENSIONS) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: invalid length"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + + while (idx < (word32)sz) { + oid = 0; + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + + tmpIdx = idx; + ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: OBJECT ID"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + idx = tmpIdx; + + /* Continue while loop until extCount == loc or idx > sz */ + if (extCount != loc) { + idx += length; + extCount++; + continue; + } + /* extCount == loc. Now get the extension. */ + /* Check if extension has been set */ + isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, oid); + ext->obj = wolfSSL_OBJ_nid2obj(oid); + if (ext->obj == NULL) { + WOLFSSL_MSG("\tfail: Invalid OBJECT"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + ext->obj->nid = oid; + + switch (oid) { + case BASIC_CA_OID: + if (!isSet) + break; + /* Set pathlength */ + a = wolfSSL_ASN1_INTEGER_new(); + if (a == NULL) { + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + a->length = x509->pathLength; + + /* Save ASN1_INTEGER in x509 extension */ + ext->obj->pathlen = a; + + ext->obj->ca = x509->isCa; + ext->crit = x509->basicConstCrit; + break; + + case AUTH_INFO_OID: + if (!isSet) + break; + + /* Create a stack to hold both the caIssuer and ocsp objects + in X509_EXTENSION structure */ + sk = (WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*)XMALLOC( + sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)), + NULL, DYNAMIC_TYPE_ASN1); + if (sk == NULL) { + WOLFSSL_MSG("Failed to malloc stack"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT))); + sk->type = STACK_TYPE_OBJ; + + /* Add CaIssuers object to stack */ + if (x509->authInfoCaIssuer != NULL && + x509->authInfoCaIssuerSz > 0) + { + WOLFSSL_ASN1_OBJECT* obj; + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Error creating ASN1 object"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + obj->obj = (byte*)x509->authInfoCaIssuer; + obj->objSz = x509->authInfoCaIssuerSz; + obj->grp = oidCertAuthInfoType; + obj->nid = AIA_CA_ISSUER_OID; + + ret = wolfSSL_sk_ASN1_OBJECT_push(sk, obj); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + } + + /* Add OCSP object to stack */ + if (x509->authInfo != NULL && + x509->authInfoSz > 0) + { + WOLFSSL_ASN1_OBJECT* obj; + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Error creating ASN1 object"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + obj->obj = x509->authInfo; + obj->objSz = x509->authInfoSz; + obj->grp = oidCertAuthInfoType; + obj->nid = AIA_OCSP_OID; + + ret = wolfSSL_sk_ASN1_OBJECT_push(sk, obj); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + } + ext->ext_sk = sk; + ext->crit = x509->authInfoCrit; + break; + + case AUTH_KEY_OID: + if (!isSet) + break; + + ret = wolfSSL_ASN1_STRING_set(&ext->value, x509->authKeyId, + x509->authKeyIdSz); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + ext->crit = x509->authKeyIdCrit; + break; + + case SUBJ_KEY_OID: + if (!isSet) + break; + + ret = wolfSSL_ASN1_STRING_set(&ext->value, x509->subjKeyId, + x509->subjKeyIdSz); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + ext->crit = x509->subjKeyIdCrit; + break; + + case CERT_POLICY_OID: + if (!isSet) + break; + ext->crit = x509->certPolicyCrit; + break; + + case KEY_USAGE_OID: + if (!isSet) + break; + + ret = wolfSSL_ASN1_STRING_set(&ext->value, + (byte*)&(x509->keyUsage), sizeof(word16)); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + ext->crit = x509->keyUsageCrit; + break; + + case EXT_KEY_USAGE_OID: + if (!isSet) + break; + ext->crit = x509->keyUsageCrit; + break; + + case CRL_DIST_OID: + if (!isSet) + break; + ext->crit = x509->CRLdistCrit; + break; + + case ALT_NAMES_OID: + { + WOLFSSL_GENERAL_NAME* gn = NULL; + DNS_entry* dns = NULL; + if (!isSet) + break; + + sk = (WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)*)XMALLOC( + sizeof(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)), NULL, + DYNAMIC_TYPE_ASN1); + if (sk == NULL) { + return NULL; + } + XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME))); + sk->type = STACK_TYPE_GEN_NAME; + + if (x509->subjAltNameSet && x509->altNames != NULL) { + /* alt names are DNS_entry structs */ + dns = x509->altNames; + /* Currently only support GEN_DNS type */ + while (dns != NULL) { + gn = wolfSSL_GENERAL_NAME_new(); + if (gn == NULL) { + WOLFSSL_MSG("Error creating GENERAL_NAME"); + wolfSSL_sk_free(sk); + return NULL; + } + + gn->type = dns->type; + gn->d.ia5->length = dns->len; + if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name, + gn->d.ia5->length) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set failed"); + wolfSSL_GENERAL_NAME_free(gn); + wolfSSL_sk_free(sk); + return NULL; + } + + dns = dns->next; + /* last dns in list add at end of function */ + if (dns != NULL) { + if (wolfSSL_sk_GENERAL_NAME_push(sk, gn) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error pushing onto stack"); + wolfSSL_GENERAL_NAME_free(gn); + wolfSSL_sk_free(sk); + sk = NULL; + } + } + } + if (wolfSSL_sk_GENERAL_NAME_push(sk,gn) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error pushing onto stack"); + wolfSSL_GENERAL_NAME_free(gn); + wolfSSL_sk_free(sk); + sk = NULL; + } + } + ext->ext_sk = sk; + ext->crit = x509->subjAltNameCrit; + break; + } + + default: + WOLFSSL_MSG("Unknown extension type found, parsing OID"); + /* If the extension type is not recognized/supported, + set the ASN1_OBJECT in the extension with the + parsed oid for access in later function calls */ + + /* Get OID from input */ + if (GetASNObjectId(input, &idx, &length, sz) != 0) { + WOLFSSL_MSG("Failed to Get ASN Object Id"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + oidBuf = (byte*)XMALLOC(length+1+MAX_LENGTH_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (oidBuf == NULL) { + WOLFSSL_MSG("Failed to malloc tmp buffer"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + oidBuf[0] = ASN_OBJECT_ID; + objSz++; + objSz += SetLength(length, oidBuf + 1); + objSz += length; + + /* Set object size and reallocate space in object buffer */ + ext->obj->objSz = objSz; + if(((ext->obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) || + (ext->obj->obj == NULL)) { + ext->obj->obj =(byte*)XREALLOC((byte*)ext->obj->obj, + ext->obj->objSz, + NULL,DYNAMIC_TYPE_ASN1); + if (ext->obj->obj == NULL) { + wolfSSL_ASN1_OBJECT_free(ext->obj); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + ext->obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA; + } else { + ext->obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + /* Get OID from input and copy to ASN1_OBJECT buffer */ + XMEMCPY(oidBuf+2, input+idx, length); + XMEMCPY((byte*)ext->obj->obj, oidBuf, ext->obj->objSz); + XFREE(oidBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + oidBuf = NULL; + ext->obj->grp = oidCertExtType; + ext->crit = 0; + + /* Get extension data and copy as ASN1_STRING */ + tmpIdx = idx + length; + if ((tmpIdx >= (word32)sz) || (input[tmpIdx++] != ASN_OCTET_STRING)) { + WOLFSSL_MSG("Error decoding unknown extension data"); + wolfSSL_ASN1_OBJECT_free(ext->obj); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + + if (GetLength(input, &tmpIdx, &length, sz) <= 0) { + WOLFSSL_MSG("Error: Invalid Input Length."); + wolfSSL_ASN1_OBJECT_free(ext->obj); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + ext->value.data = (char*)XMALLOC(length, NULL, DYNAMIC_TYPE_ASN1); + ext->value.isDynamic = 1; + if (ext->value.data == NULL) { + WOLFSSL_MSG("Failed to malloc ASN1_STRING data"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + XMEMCPY(ext->value.data,input+tmpIdx,length); + ext->value.length = length; + } /* switch(oid) */ + + break; /* Got the Extension. Now exit while loop. */ + + } /* while(idx < sz) */ + + /* Store the new extension in a stack inside x509 + * The extensions on the stack are free'd internally when FreeX509 is called + */ + if (x509->ext_sk == NULL) + x509->ext_sk = wolfSSL_sk_new_x509_ext(); + if (x509->ext_sk != NULL) + wolfSSL_sk_X509_EXTENSION_push(x509->ext_sk, ext); + + FreeDecodedCert(&cert); + return ext; +} + +/* Return 0 on success and 1 on failure. Copies ext data to bio, using indent + * to pad the output. flag is ignored. */ +int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, WOLFSSL_X509_EXTENSION *ext, + unsigned long flag, int indent) +{ + ASN1_OBJECT* obj; + ASN1_STRING* str; + int nid; + const int sz = CTC_NAME_SIZE*2; + int rc = WOLFSSL_FAILURE; + char tmp[CTC_NAME_SIZE*2]; + WOLFSSL_ENTER("wolfSSL_X509V3_EXT_print"); + + if ((out == NULL) || (ext == NULL)) { + WOLFSSL_MSG("NULL parameter error"); + return rc; + } + + obj = wolfSSL_X509_EXTENSION_get_object(ext); + if (obj == NULL) { + WOLFSSL_MSG("Error getting ASN1_OBJECT from X509_EXTENSION"); + return rc; + } + + str = wolfSSL_X509_EXTENSION_get_data(ext); + if (obj == NULL) { + WOLFSSL_MSG("Error getting ASN1_STRING from X509_EXTENSION"); + return rc; + } + + /* Print extension based on the type */ + nid = wolfSSL_OBJ_obj2nid(obj); + switch (nid) { + case BASIC_CA_OID: + { + char isCa[] = "TRUE"; + char notCa[] = "FALSE"; + XSNPRINTF(tmp, sz, "%*sCA:%s", indent, "", + obj->ca ? isCa : notCa); + break; + } + case ALT_NAMES_OID: + { + WOLFSSL_STACK* sk; + char* val; + int len; + tmp[0] = '\0'; /* Make sure tmp is null-terminated */ + + sk = ext->ext_sk; + while (sk != NULL) { + if (sk->type == STACK_TYPE_GEN_NAME && sk->data.gn) { + /* str is GENERAL_NAME for subject alternative name ext */ + str = sk->data.gn->d.ia5; + len = str->length + 2; /* + 2 for NULL char and "," */ + if (len > sz) { + WOLFSSL_MSG("len greater than buffer size"); + return rc; + } + + val = (char*)XMALLOC(len + indent, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (val == NULL) { + WOLFSSL_MSG("Memory error"); + return rc; + } + if (sk->next) + XSNPRINTF(val, len, "%*s%s, ", indent, "", str->strData); + else + XSNPRINTF(val, len, "%*s%s", indent, "", str->strData); + + XSTRNCAT(tmp, val, len); + XFREE(val, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + sk = sk->next; + } + break; + } + case AUTH_KEY_OID: + case SUBJ_KEY_OID: + { + char* asn1str; + asn1str = wolfSSL_i2s_ASN1_STRING(NULL, str); + XSNPRINTF(tmp, sz, "%*s%s", indent, "", asn1str); + XFREE(asn1str, NULL, DYNAMIC_TYPE_TMP_BUFFER); + break; + } + case AUTH_INFO_OID: + case CERT_POLICY_OID: + case CRL_DIST_OID: + case KEY_USAGE_OID: + WOLFSSL_MSG("X509V3_EXT_print not yet implemented for ext type"); + break; + + default: + XSNPRINTF(tmp, sz, "%*s%s", indent, "", str->strData); + } + + if (wolfSSL_BIO_write(out, tmp, (int)XSTRLEN(tmp)) == (int)XSTRLEN(tmp)) { + rc = WOLFSSL_SUCCESS; + } + (void) flag; + + return rc; +} + +/* Returns crit flag in X509_EXTENSION object */ +int wolfSSL_X509_EXTENSION_get_critical(const WOLFSSL_X509_EXTENSION* ex) +{ + WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_critical"); + if (ex == NULL) + return BAD_FUNC_ARG; + return ex->crit; +} + +/* Creates v3_ext_method for a given X509v3 extension + * + * ex : The X509_EXTENSION used to create v3_ext_method. If the extension is + * not NULL, get the NID of the extension object and populate the + * extension type-specific X509V3_EXT_* function(s) in v3_ext_method. + * + * Returns NULL on error or pointer to the v3_ext_method populated with extension + * type-specific X509V3_EXT_* function(s). + * + * NOTE: NID_subject_key_identifier is currently the only extension implementing + * the X509V3_EXT_* functions, as it is the only type called directly by QT. The + * other extension types return a pointer to a v3_ext_method struct that contains + * only the NID. + */ +const WOLFSSL_v3_ext_method* wolfSSL_X509V3_EXT_get(WOLFSSL_X509_EXTENSION* ex) +{ + int nid; + WOLFSSL_v3_ext_method method; + + WOLFSSL_ENTER("wolfSSL_X509V3_EXT_get"); + if ((ex == NULL) || (ex->obj == NULL)) { + WOLFSSL_MSG("Passed an invalid X509_EXTENSION*"); + return NULL; + } + /* Initialize all methods to NULL */ + method.d2i = NULL; + method.i2v = NULL; + method.i2s = NULL; + method.i2r = NULL; + + nid = ex->obj->nid; + if (nid <= 0) { + WOLFSSL_MSG("Failed to get nid from passed extension object"); + return NULL; + } + + switch (nid) { + case NID_basic_constraints: + break; + case NID_subject_key_identifier: + method.i2s = (X509V3_EXT_I2S)wolfSSL_i2s_ASN1_STRING; + break; + case NID_key_usage: + WOLFSSL_MSG("i2v function not yet implemented for Key Usage"); + break; + case NID_authority_key_identifier: + WOLFSSL_MSG("i2v function not yet implemented for Auth Key Id"); + break; + case NID_info_access: + WOLFSSL_MSG("i2v function not yet implemented for Info Access"); + break; + case NID_ext_key_usage: + WOLFSSL_MSG("i2v function not yet implemented for Ext Key Usage"); + break; + case NID_certificate_policies: + WOLFSSL_MSG("r2i function not yet implemented for Cert Policies"); + break; + case NID_crl_distribution_points: + WOLFSSL_MSG("r2i function not yet implemented for CRL Dist Points"); + break; + default: + /* If extension type is unknown, return NULL -- QT makes call to + X509_EXTENSION_get_data() if there is no v3_ext_method */ + WOLFSSL_MSG("X509V3_EXT_get(): Unknown extension type found"); + return NULL; + } + + method.ext_nid = nid; + ex->ext_method = method; + + return (const WOLFSSL_v3_ext_method*)&ex->ext_method; +} + +/* Parses and returns an x509v3 extension internal structure. + * + * ext : The X509_EXTENSION for parsing internal structure. If extension is + * not NULL, get the NID of the extension object and create a new + * extension-specific internal structure based on the extension type. + * + * Returns NULL on error or if NID is not found, otherwise returns a pointer to + * the extension type-specific X509_EXTENSION internal structure. + * Return is expected to be free'd by caller. + */ +void* wolfSSL_X509V3_EXT_d2i(WOLFSSL_X509_EXTENSION* ext) +{ + const WOLFSSL_v3_ext_method* method; + int ret; + WOLFSSL_ASN1_OBJECT* object; + WOLFSSL_BASIC_CONSTRAINTS* bc; + WOLFSSL_AUTHORITY_KEYID* akey; + WOLFSSL_ASN1_STRING* asn1String, *newString; + WOLFSSL_AUTHORITY_INFO_ACCESS* aia; + WOLFSSL_STACK* sk; + + WOLFSSL_ENTER("wolfSSL_X509V3_EXT_d2i"); + + if(ext == NULL) { + WOLFSSL_MSG("Bad function Argument"); + return NULL; + } + + /* extract extension info */ + method = wolfSSL_X509V3_EXT_get(ext); + if (method == NULL) { + WOLFSSL_MSG("wolfSSL_X509V3_EXT_get error"); + return NULL; + } + object = wolfSSL_X509_EXTENSION_get_object(ext); + if (object == NULL) { + WOLFSSL_MSG("X509_EXTENSION_get_object failed"); + return NULL; + } + + /* Return pointer to proper internal structure based on NID */ + switch (object->type) { + /* basicConstraints */ + case (NID_basic_constraints): + WOLFSSL_MSG("basicConstraints"); + /* Allocate new BASIC_CONSTRAINTS structure */ + bc = (WOLFSSL_BASIC_CONSTRAINTS*) + XMALLOC(sizeof(WOLFSSL_BASIC_CONSTRAINTS), NULL, + DYNAMIC_TYPE_X509_EXT); + if (bc == NULL) { + WOLFSSL_MSG("Failed to malloc basic constraints"); + return NULL; + } + /* Copy pathlen and CA into BASIC_CONSTRAINTS from object */ + bc->ca = object->ca; + if (object->pathlen->length > 0) { + bc->pathlen = wolfSSL_ASN1_INTEGER_dup(object->pathlen); + if (bc->pathlen == NULL) { + WOLFSSL_MSG("Failed to duplicate ASN1_INTEGER"); + XFREE(bc, NULL, DYNAMIC_TYPE_X509_EXT); + return NULL; + } + } + else + bc->pathlen = NULL; + return bc; + + /* subjectKeyIdentifier */ + case (NID_subject_key_identifier): + WOLFSSL_MSG("subjectKeyIdentifier"); + asn1String = wolfSSL_X509_EXTENSION_get_data(ext); + if (asn1String == NULL) { + WOLFSSL_MSG("X509_EXTENSION_get_data() failed"); + return NULL; + } + newString = wolfSSL_ASN1_STRING_new(); + if (newString == NULL) { + WOLFSSL_MSG("Failed to malloc ASN1_STRING"); + return NULL; + } + ret = wolfSSL_ASN1_STRING_set(newString, asn1String->data, + asn1String->length); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_ASN1_STRING_free(newString); + return NULL; + }; + newString->type = asn1String->type; + return newString; + + /* authorityKeyIdentifier */ + case (NID_authority_key_identifier): + WOLFSSL_MSG("AuthorityKeyIdentifier"); + + akey = (WOLFSSL_AUTHORITY_KEYID*) + XMALLOC(sizeof(WOLFSSL_AUTHORITY_KEYID), NULL, + DYNAMIC_TYPE_X509_EXT); + if (akey == NULL) { + WOLFSSL_MSG("Failed to malloc authority key id"); + return NULL; + } + + akey->keyid = wolfSSL_ASN1_STRING_new(); + if (akey->keyid == NULL) { + WOLFSSL_MSG("ASN1_STRING_new() failed"); + wolfSSL_AUTHORITY_KEYID_free(akey); + return NULL; + } + + asn1String = wolfSSL_X509_EXTENSION_get_data(ext); + if (asn1String == NULL) { + WOLFSSL_MSG("X509_EXTENSION_get_data() failed"); + wolfSSL_AUTHORITY_KEYID_free(akey); + return NULL; + } + + ret = wolfSSL_ASN1_STRING_set(akey->keyid, asn1String->data, + asn1String->length); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_AUTHORITY_KEYID_free(akey); + return NULL; + }; + akey->keyid->type = asn1String->type; + + /* For now, set issuer and serial to NULL. This may need to be + updated for future use */ + akey->issuer = NULL; + akey->serial = NULL; + return akey; + + /* keyUsage */ + case (NID_key_usage): + WOLFSSL_MSG("keyUsage"); + /* This may need to be updated for future use. The i2v method for + keyUsage is not currently set. For now, return the ASN1_STRING + representation of KeyUsage bit string */ + asn1String = wolfSSL_X509_EXTENSION_get_data(ext); + if (asn1String == NULL) { + WOLFSSL_MSG("X509_EXTENSION_get_data() failed"); + return NULL; + } + newString = wolfSSL_ASN1_STRING_new(); + if (newString == NULL) { + WOLFSSL_MSG("Failed to malloc ASN1_STRING"); + return NULL; + } + ret = wolfSSL_ASN1_STRING_set(newString, asn1String->data, + asn1String->length); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_ASN1_STRING_free(newString); + return NULL; + }; + newString->type = asn1String->type; + return newString; + + /* extKeyUsage */ + case (NID_ext_key_usage): + WOLFSSL_MSG("extKeyUsage not supported yet"); + return NULL; + + /* certificatePolicies */ + case (NID_certificate_policies): + WOLFSSL_MSG("certificatePolicies not supported yet"); + return NULL; + + /* cRLDistributionPoints */ + case (NID_crl_distribution_points): + WOLFSSL_MSG("cRLDistributionPoints not supported yet"); + return NULL; + + /* authorityInfoAccess */ + case (NID_info_access): + WOLFSSL_MSG("AuthorityInfoAccess"); + + sk = ext->ext_sk; + if (sk == NULL) { + WOLFSSL_MSG("ACCESS_DESCRIPTION stack NULL"); + return NULL; + } + + /* AUTHORITY_INFO_ACCESS is a stack of ACCESS_DESCRIPTION entries */ + aia = wolfSSL_sk_new_null(); + if (aia == NULL) { + WOLFSSL_MSG("Failed to malloc AUTHORITY_INFO_ACCESS"); + return NULL; + } + aia->type = STACK_TYPE_ACCESS_DESCRIPTION; + + while (sk) { + WOLFSSL_ACCESS_DESCRIPTION* ad; + WOLFSSL_ASN1_OBJECT* aiaEntry; + + if (sk->type != STACK_TYPE_OBJ) { + sk = sk->next; + continue; + } + + aiaEntry = sk->data.obj; + + /* ACCESS_DESCRIPTION has two members, method and location. + Method: ASN1_OBJECT as either AIA_OCSP_OID or AIA_CA_ISSUER_OID + Location: GENERAL_NAME structure containing the URI. */ + + ad = (WOLFSSL_ACCESS_DESCRIPTION*) + XMALLOC(sizeof(WOLFSSL_ACCESS_DESCRIPTION), NULL, + DYNAMIC_TYPE_X509_EXT); + if (ad == NULL) { + WOLFSSL_MSG("Failed to malloc ACCESS_DESCRIPTION"); + XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT); + return NULL; + } + XMEMSET(ad, 0, sizeof(WOLFSSL_ACCESS_DESCRIPTION)); + + /* Create new ASN1_OBJECT from oid */ + ad->method = wolfSSL_OBJ_nid2obj(aiaEntry->nid); + if (ad->method == NULL) { + WOLFSSL_MSG("OBJ_nid2obj() failed"); + XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT); + XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT); + return NULL; + } + + /* Allocate memory for GENERAL NAME */ + ad->location = (WOLFSSL_GENERAL_NAME*) + XMALLOC(sizeof(WOLFSSL_GENERAL_NAME), NULL, + DYNAMIC_TYPE_OPENSSL); + if (ad->location == NULL) { + WOLFSSL_MSG("Failed to malloc GENERAL_NAME"); + wolfSSL_ASN1_OBJECT_free(ad->method); + XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT); + XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT); + return NULL; + } + XMEMSET(ad->location, 0, sizeof(WOLFSSL_GENERAL_NAME)); + ad->location->type = GEN_URI; + ad->location->d.uniformResourceIdentifier = + wolfSSL_ASN1_STRING_new(); + /* Set the URI in GENERAL_NAME */ + ret = wolfSSL_ASN1_STRING_set( + ad->location->d.uniformResourceIdentifier, + aiaEntry->obj, aiaEntry->objSz); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_ASN1_OBJECT_free(ad->method); + XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT); + XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT); + return NULL; + } + /* Push to AUTHORITY_INFO_ACCESS stack */ + ret = wolfSSL_sk_ACCESS_DESCRIPTION_push(aia, ad); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 AD onto stack"); + wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(aia, NULL); + wolfSSL_ASN1_OBJECT_free(ad->method); + XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT); + XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT); + return NULL; + } + + sk = sk->next; + } + return aia; + + default: + WOLFSSL_MSG("Extension NID not in table, returning NULL"); + break; + } + return NULL; +} + +/* Looks for the extension matching the passed in nid + * + * x509 : certificate to get parse through for extension. + * nid : Extension OID to be found. + * lastPos : Start search from extension after lastPos. + * Set to -1 to search from index 0. + * return >= 0 If successful the extension index is returned. + * return -1 If extension is not found or error is encountered. + */ +int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509* x509, int nid, int lastPos) +{ + int extCount = 0, length = 0, outSz = 0, sz = 0, ret = 0; + int isSet = 0, found = 0, loc; + const byte* rawCert; + const byte* input; + word32 oid, idx = 0, tmpIdx = 0; + DecodedCert cert; + + WOLFSSL_ENTER("wolfSSL_X509_get_ext_by_NID"); + + if(x509 == NULL){ + WOLFSSL_MSG("\tNot passed a certificate"); + return WOLFSSL_FATAL_ERROR; + } + + if(lastPos < -1 || (lastPos > (wolfSSL_X509_get_ext_count(x509) - 1))){ + WOLFSSL_MSG("\tBad location argument"); + return WOLFSSL_FATAL_ERROR; + } + + loc = lastPos + 1; + + rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)x509, &outSz); + if (rawCert == NULL) { + WOLFSSL_MSG("\tX509_get_der() failed"); + return WOLFSSL_FATAL_ERROR; + } + + InitDecodedCert( &cert, rawCert, (word32)outSz, 0); + + if (ParseCert(&cert, CA_TYPE, NO_VERIFY, NULL) < 0) { + WOLFSSL_MSG("\tCertificate parsing failed"); + return WOLFSSL_FATAL_ERROR; + } + + input = cert.extensions; + sz = cert.extensionsSz; + + if (input == NULL || sz == 0) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); + FreeDecodedCert(&cert); + return WOLFSSL_FATAL_ERROR; + } + + if (input[idx++] != ASN_EXTENSIONS) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); + FreeDecodedCert(&cert); + return WOLFSSL_FATAL_ERROR; + } + + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: invalid length"); + FreeDecodedCert(&cert); + return WOLFSSL_FATAL_ERROR; + } + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)"); + FreeDecodedCert(&cert); + return WOLFSSL_FATAL_ERROR; + } + + while (idx < (word32)sz) { + oid = 0; + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE"); + FreeDecodedCert(&cert); + return WOLFSSL_FATAL_ERROR; + } + + tmpIdx = idx; + ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: OBJECT ID"); + FreeDecodedCert(&cert); + return WOLFSSL_FATAL_ERROR; + } + idx = tmpIdx; + + if (extCount >= loc) { + /* extCount >= loc. Now check if extension has been set */ + isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, oid); + + if (isSet && ((word32)nid == oid)) { + found = 1; + break; + } + } + + idx += length; + extCount++; + } /* while(idx < sz) */ + + FreeDecodedCert(&cert); + + return found ? extCount : WOLFSSL_FATAL_ERROR; +} + + +#endif /* OPENSSL_ALL */ + +WOLFSSL_ASN1_BIT_STRING* wolfSSL_ASN1_BIT_STRING_new(void) +{ + WOLFSSL_ASN1_BIT_STRING* str; + + str = (WOLFSSL_ASN1_BIT_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_BIT_STRING), + NULL, DYNAMIC_TYPE_OPENSSL); + if (str) { + XMEMSET(str, 0, sizeof(WOLFSSL_ASN1_BIT_STRING)); + } + return str; +} + +void wolfSSL_ASN1_BIT_STRING_free(WOLFSSL_ASN1_BIT_STRING* str) +{ + if (str) { + if (str->data) { + XFREE(str->data, NULL, DYNAMIC_TYPE_OPENSSL); + str->data = NULL; + } + XFREE(str, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +int wolfSSL_ASN1_BIT_STRING_get_bit(const WOLFSSL_ASN1_BIT_STRING* str, int i) +{ + if (!str || !str->data || str->length <= (i/8) || i < 0) { + return WOLFSSL_FAILURE; + } + + return (str->data[i/8] & (1<<(7-(i%8)))) ? 1 : 0; +} + +/* Looks for the extension matching the passed in nid + * + * c : if not null then is set to status value -2 if multiple occurrences + * of the extension are found, -1 if not found, 0 if found and not + * critical, and 1 if found and critical. + * nid : Extension OID to be found. + * idx : if NULL return first extension found match, otherwise start search at + * idx location and set idx to the location of extension returned. + * returns NULL or a pointer to an WOLFSSL_ASN1_BIT_STRING (for KEY_USAGE_OID) + * or WOLFSSL_STACK (for other) + * holding extension structure + * + * NOTE code for decoding extensions is in asn.c DecodeCertExtensions -- + * use already decoded extension in this function to avoid decoding twice. + * Currently we do not make use of idx since getting pre decoded extensions. + */ +void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, + int* idx) +{ + void* ret = NULL; + WOLFSSL_STACK* sk = NULL; + WOLFSSL_ASN1_OBJECT* obj = NULL; + WOLFSSL_GENERAL_NAME* gn = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_get_ext_d2i"); + + if (x509 == NULL) { + return NULL; + } + + if (c != NULL) { + *c = -1; /* default to not found */ + } + + switch (nid) { + case BASIC_CA_OID: + if (x509->basicConstSet) { + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + return NULL; + } + if (c != NULL) { + *c = x509->basicConstCrit; + } + obj->type = BASIC_CA_OID; + obj->grp = oidCertExtType; + obj->nid = nid; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || \ + defined(WOLFSSL_APACHE_HTTPD) + obj->ca = x509->isCa; + #endif + } + else { + WOLFSSL_MSG("No Basic Constraint set"); + } + return obj; + + case ALT_NAMES_OID: + { + DNS_entry* dns = NULL; + /* Malloc GENERAL_NAME stack */ + sk = (WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)*)XMALLOC( + sizeof(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)), NULL, + DYNAMIC_TYPE_ASN1); + if (sk == NULL) { + return NULL; + } + XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME))); + sk->type = STACK_TYPE_GEN_NAME; + + if (x509->subjAltNameSet && x509->altNames != NULL) { + /* alt names are DNS_entry structs */ + if (c != NULL) { + if (x509->altNames->next != NULL) { + *c = -2; /* more then one found */ + } + else { + *c = x509->subjAltNameCrit; + } + } + + dns = x509->altNames; + /* Currently only support GEN_DNS type */ + while (dns != NULL) { + gn = wolfSSL_GENERAL_NAME_new(); + if (gn == NULL) { + WOLFSSL_MSG("Error creating GENERAL_NAME"); + wolfSSL_sk_free(sk); + return NULL; + } + + gn->type = dns->type; + gn->d.ia5->length = dns->len; + if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name, + gn->d.ia5->length) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set failed"); + wolfSSL_GENERAL_NAME_free(gn); + wolfSSL_sk_free(sk); + return NULL; + } + + dns = dns->next; + /* last dns in list add at end of function */ + if (dns != NULL) { + if (wolfSSL_sk_GENERAL_NAME_push(sk, gn) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_GENERAL_NAME_free(gn); + wolfSSL_sk_free(sk); + sk = NULL; + } + } + } + } + else { + WOLFSSL_MSG("No Alt Names set"); + } + + break; + } + + case CRL_DIST_OID: + if (x509->CRLdistSet && x509->CRLInfo != NULL) { + if (c != NULL) { + *c = x509->CRLdistCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + return NULL; + } + obj->type = CRL_DIST_OID; + obj->grp = oidCertExtType; + obj->obj = x509->CRLInfo; + obj->objSz = x509->CRLInfoSz; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA ; + } + else { + WOLFSSL_MSG("No CRL dist set"); + } + break; + + case AUTH_INFO_OID: + if (x509->authInfoSet && x509->authInfo != NULL) { + if (c != NULL) { + *c = x509->authInfoCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + return NULL; + } + obj->type = AUTH_INFO_OID; + obj->grp = oidCertExtType; + obj->obj = x509->authInfo; + obj->objSz = x509->authInfoSz; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + else { + WOLFSSL_MSG("No Auth Info set"); + } + break; + + case AUTH_KEY_OID: + if (x509->authKeyIdSet) { + if (c != NULL) { + *c = x509->authKeyIdCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + return NULL; + } + obj->type = AUTH_KEY_OID; + obj->grp = oidCertExtType; + obj->obj = x509->authKeyId; + obj->objSz = x509->authKeyIdSz; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + else { + WOLFSSL_MSG("No Auth Key set"); + } + break; + + case SUBJ_KEY_OID: + if (x509->subjKeyIdSet) { + if (c != NULL) { + *c = x509->subjKeyIdCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + return NULL; + } + obj->type = SUBJ_KEY_OID; + obj->grp = oidCertExtType; + obj->obj = x509->subjKeyId; + obj->objSz = x509->subjKeyIdSz; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + else { + WOLFSSL_MSG("No Subject Key set"); + } + break; + + case CERT_POLICY_OID: + { + #ifdef WOLFSSL_CERT_EXT + int i; + + if (x509->certPoliciesNb > 0) { + if (c != NULL) { + if (x509->certPoliciesNb > 1) { + *c = -2; + } + else { + *c = 0; + } + } + + sk = wolfSSL_sk_new_asn1_obj(); + if (sk == NULL) { + return NULL; + } + + for (i = 0; i < x509->certPoliciesNb - 1; i++) { + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + obj->type = CERT_POLICY_OID; + obj->grp = oidCertExtType; + obj->obj = (byte*)(x509->certPolicies[i]); + obj->objSz = MAX_CERTPOL_SZ; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + 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); + sk = NULL; + } + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + obj->type = CERT_POLICY_OID; + obj->grp = oidCertExtType; + obj->obj = (byte*)(x509->certPolicies[i]); + obj->objSz = MAX_CERTPOL_SZ; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + else { + WOLFSSL_MSG("No Cert Policy set"); + } + #elif defined(WOLFSSL_SEP) + if (x509->certPolicySet) { + if (c != NULL) { + *c = x509->certPolicyCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + return NULL; + } + obj->type = CERT_POLICY_OID; + obj->grp = oidCertExtType; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + } + else { + WOLFSSL_MSG("No Cert Policy set"); + } + #else + WOLFSSL_MSG("wolfSSL not built with WOLFSSL_SEP or WOLFSSL_CERT_EXT"); + #endif + break; + } + case KEY_USAGE_OID: + { + WOLFSSL_ASN1_BIT_STRING* bit_str = NULL; + if (x509->keyUsageSet) { + if (c != NULL) { + *c = x509->keyUsageCrit; + } + + bit_str = wolfSSL_ASN1_BIT_STRING_new(); + if (bit_str == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_BIT_STRING struct"); + return NULL; + } + + bit_str->type = KEY_USAGE_OID; + bit_str->flags = 0; + bit_str->length = sizeof(word16); + bit_str->data = (byte*)XMALLOC(bit_str->length, NULL, DYNAMIC_TYPE_OPENSSL); + if (bit_str->data == NULL) { + wolfSSL_ASN1_BIT_STRING_free(bit_str); + return NULL; + } + XMEMCPY(bit_str->data, &x509->keyUsage, bit_str->length); + } + else { + WOLFSSL_MSG("No Key Usage set"); + } + /* don't add stack of and return bit string directly */ + return bit_str; + } + case INHIBIT_ANY_OID: + WOLFSSL_MSG("INHIBIT ANY extension not supported"); + break; + + case EXT_KEY_USAGE_OID: + if (x509->extKeyUsageSrc != NULL) { + if (c != NULL) { + if (x509->extKeyUsageCount > 1) { + *c = -2; + } + else { + *c = x509->extKeyUsageCrit; + } + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + return NULL; + } + obj->type = EXT_KEY_USAGE_OID; + obj->grp = oidCertExtType; + obj->obj = x509->extKeyUsageSrc; + obj->objSz = x509->extKeyUsageSz; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + else { + WOLFSSL_MSG("No Extended Key Usage set"); + } + break; + + case NAME_CONS_OID: + WOLFSSL_MSG("Name Constraint OID extension not supported"); + break; + + case PRIV_KEY_USAGE_PERIOD_OID: + WOLFSSL_MSG("Private Key Usage Period extension not supported"); + break; + + case SUBJECT_INFO_ACCESS: + WOLFSSL_MSG("Subject Info Access extension not supported"); + break; + + case POLICY_MAP_OID: + WOLFSSL_MSG("Policy Map extension not supported"); + break; + + case POLICY_CONST_OID: + WOLFSSL_MSG("Policy Constraint extension not supported"); + break; + + case ISSUE_ALT_NAMES_OID: + WOLFSSL_MSG("Issue Alt Names extension not supported"); + break; + + case TLS_FEATURE_OID: + WOLFSSL_MSG("TLS Feature extension not supported"); + break; + + default: + WOLFSSL_MSG("Unsupported/Unknown extension OID"); + } + + /* make sure stack of is allocated */ + if ((obj || gn) && sk == NULL) { + sk = wolfSSL_sk_new_asn1_obj(); + if (sk == NULL) { + goto err; + } + } + if (obj && wolfSSL_sk_ASN1_OBJECT_push(sk, obj) == WOLFSSL_SUCCESS) { + /* obj pushed successfully on stack */ + } + else if (gn && wolfSSL_sk_GENERAL_NAME_push(sk, gn) == WOLFSSL_SUCCESS) { + /* gn pushed successfully on stack */ + } + else { + /* Nothing to push or push failed */ + WOLFSSL_MSG("Error pushing ASN1_OBJECT or GENERAL_NAME object onto stack " + "or nothing to push."); + goto err; + } + ret = sk; + + (void)idx; + + return ret; + +err: + if (obj) { + wolfSSL_ASN1_OBJECT_free(obj); + } + if (gn) { + wolfSSL_GENERAL_NAME_free(gn); + } + if (sk) { + wolfSSL_sk_ASN1_OBJECT_free(sk); + } + return NULL; +} + + +int wolfSSL_X509_add_altname(WOLFSSL_X509* x509, const char* name, int type) +{ + DNS_entry* newAltName = NULL; + char* nameCopy = NULL; + word32 nameSz; + + if (x509 == NULL) + return WOLFSSL_FAILURE; + + if (name == NULL) + return WOLFSSL_SUCCESS; + + nameSz = (word32)XSTRLEN(name); + if (nameSz == 0) + return WOLFSSL_SUCCESS; + + newAltName = (DNS_entry*)XMALLOC(sizeof(DNS_entry), + x509->heap, DYNAMIC_TYPE_ALTNAME); + if (newAltName == NULL) + return WOLFSSL_FAILURE; + + nameCopy = (char*)XMALLOC(nameSz + 1, x509->heap, DYNAMIC_TYPE_ALTNAME); + if (nameCopy == NULL) { + XFREE(newAltName, x509->heap, DYNAMIC_TYPE_ALTNAME); + return WOLFSSL_FAILURE; + } + + XMEMCPY(nameCopy, name, nameSz + 1); + + newAltName->next = x509->altNames; + newAltName->type = type; + newAltName->len = nameSz; + newAltName->name = nameCopy; + x509->altNames = newAltName; + + return WOLFSSL_SUCCESS; +} + + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_X509_add_ext(WOLFSSL_X509 *x509, WOLFSSL_X509_EXTENSION *ext, int loc) +{ + WOLFSSL_STUB("wolfSSL_X509_add_ext"); + (void)x509; + (void)ext; + (void)loc; + return WOLFSSL_FAILURE; +} + +/* currently LHASH is not implemented (and not needed for Apache port) */ +WOLFSSL_X509_EXTENSION* wolfSSL_X509V3_EXT_conf_nid( + WOLF_LHASH_OF(CONF_VALUE)* conf, WOLFSSL_X509V3_CTX* ctx, int nid, + char* value) +{ + WOLFSSL_STUB("wolfSSL_X509V3_EXT_conf_nid"); + + if (conf != NULL) { + WOLFSSL_MSG("Handling LHASH not implemented yet"); + return NULL; + } + + (void)conf; + (void)ctx; + (void)nid; + (void)value; + return NULL; +} + +void wolfSSL_X509V3_set_ctx_nodb(WOLFSSL_X509V3_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_X509V3_set_ctx_nodb"); + (void)ctx; +} +#endif /* !NO_WOLFSSL_STUB */ + +/* Returns pointer to ASN1_OBJECT from an X509_EXTENSION object */ +WOLFSSL_ASN1_OBJECT* wolfSSL_X509_EXTENSION_get_object \ + (WOLFSSL_X509_EXTENSION* ext) +{ + WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_object"); + if(ext == NULL) + return NULL; + return ext->obj; +} + +/* Returns pointer to ASN1_STRING in X509_EXTENSION object */ +WOLFSSL_ASN1_STRING* wolfSSL_X509_EXTENSION_get_data(WOLFSSL_X509_EXTENSION* ext) +{ + WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_data"); + if (ext == NULL) + return NULL; + return &ext->value; +} + +#if !defined(NO_PWDBASED) +int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest, + unsigned char* buf, unsigned int* len) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_X509_digest"); + + if (x509 == NULL || digest == NULL) { + WOLFSSL_MSG("Null argument found"); + return WOLFSSL_FAILURE; + } + + if (x509->derCert == NULL) { + WOLFSSL_MSG("No DER certificate stored in X509"); + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_EVP_Digest(x509->derCert->buffer, x509->derCert->length, buf, + len, digest, NULL); + WOLFSSL_LEAVE("wolfSSL_X509_digest", ret); + return ret; +} +#endif + +int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey) +{ + WOLFSSL_ENTER("wolfSSL_use_PrivateKey"); + if (ssl == NULL || pkey == NULL ) { + return WOLFSSL_FAILURE; + } + + return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1); +} + + +int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, const unsigned char* der, + long derSz) +{ + WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1"); + if (ssl == NULL || der == NULL ) { + return WOLFSSL_FAILURE; + } + + (void)pri; /* type of private key */ + return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1); +} +/****************************************************************************** +* wolfSSL_CTX_use_PrivateKey_ASN1 - loads a private key buffer into the SSL ctx +* +* RETURNS: +* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE +*/ + +int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx, + unsigned char* der, long derSz) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_ASN1"); + if (ctx == NULL || der == NULL ) { + return WOLFSSL_FAILURE; + } + + (void)pri; /* type of private key */ + return wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1); +} + + +#ifndef NO_RSA +int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz) +{ + WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1"); + if (ssl == NULL || der == NULL ) { + return WOLFSSL_FAILURE; + } + + return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1); +} +#endif + +int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509) +{ + long idx; + + WOLFSSL_ENTER("wolfSSL_use_certificate"); + if (x509 != NULL && ssl != NULL && x509->derCert != NULL) { + if (ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length, + WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0, + GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + } + + (void)idx; + return WOLFSSL_FAILURE; +} + +#endif /* NO_CERTS */ + +#endif /* OPENSSL_EXTRA */ + +#ifndef NO_CERTS +int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, const unsigned char* der, + int derSz) +{ + long idx; + + WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1"); + if (der != NULL && ssl != NULL) { + if (ProcessBuffer(NULL, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, + ssl, &idx, 0, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + } + + (void)idx; + return WOLFSSL_FAILURE; +} + +#ifndef NO_FILESYSTEM + +WOLFSSL_ABI 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; - return SSL_FAILURE; + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, + ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; } +WOLFSSL_ABI 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; - return SSL_FAILURE; + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE, + ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; } +WOLFSSL_ABI int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file) { - /* procces 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; + /* process up to MAX_CHAIN_DEPTH plus subject cert */ + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file"); - return SSL_FAILURE; + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + if (ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, + ssl, 1, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; } +int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file, + int format) +{ + /* process up to MAX_CHAIN_DEPTH plus subject cert */ + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format"); + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1, + NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} + +#endif /* !NO_FILESYSTEM */ +#endif /* !NO_CERTS */ #ifdef HAVE_ECC /* Set Temp CTX EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */ int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz) { - if (ctx == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE) + if (ctx == NULL) + return BAD_FUNC_ARG; + + if (sz == 0) { + /* applies only to ECDSA */ + if (ctx->privateKeyType != ecc_dsa_sa_algo) + return WOLFSSL_SUCCESS; + + if (ctx->privateKeySz == 0) { + WOLFSSL_MSG("Must set private key/cert first"); + return BAD_FUNC_ARG; + } + + sz = (word16)ctx->privateKeySz; + } + + /* check size */ + if (sz < ECC_MINSIZE || sz > ECC_MAXSIZE) return BAD_FUNC_ARG; ctx->eccTempKeySz = sz; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -4004,14 +9785,15 @@ int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz) ssl->eccTempKeySz = sz; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* HAVE_ECC */ +#ifdef OPENSSL_EXTRA - +#ifndef NO_FILESYSTEM int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file, int format) { @@ -4027,24 +9809,68 @@ int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format) return wolfSSL_use_PrivateKey_file(ssl, file, format); } +#endif /* NO_FILESYSTEM */ + + +/* Copies the master secret over to out buffer. If outSz is 0 returns the size + * of master secret. + * + * ses : a session from completed TLS/SSL handshake + * out : buffer to hold copy of master secret + * outSz : size of out buffer + * returns : number of bytes copied into out buffer on success + * less then or equal to 0 is considered a failure case + */ +int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses, + unsigned char* out, int outSz) +{ + int size; + + if (outSz == 0) { + return SECRET_LEN; + } + + if (ses == NULL || out == NULL || outSz < 0) { + return 0; + } + + if (outSz > SECRET_LEN) { + size = SECRET_LEN; + } + else { + size = outSz; + } + + XMEMCPY(out, ses->masterSecret, size); + return size; +} + + +int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses) +{ + (void)ses; + return SECRET_LEN; +} #endif /* OPENSSL_EXTRA */ +#ifndef NO_FILESYSTEM #ifdef HAVE_NTRU 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; - if (ProcessFile(ctx, file, SSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0, NULL) - == SSL_SUCCESS) { + if (ctx == NULL) + return WOLFSSL_FAILURE; + + if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0, + NULL, GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { ctx->haveNTRU = 1; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - return SSL_FAILURE; + return WOLFSSL_FAILURE; } #endif /* HAVE_NTRU */ @@ -4056,42 +9882,86 @@ int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX* ctx, const char* file) void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc) { WOLFSSL_ENTER("wolfSSL_CTX_set_verify"); - if (mode & SSL_VERIFY_PEER) { + if (ctx == NULL) + return; + + if (mode & WOLFSSL_VERIFY_PEER) { ctx->verifyPeer = 1; - ctx->verifyNone = 0; /* in case perviously set */ + 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 & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) { + ctx->failNoCert = 0; /* fail on all is set to fail on PSK */ + ctx->failNoCertxPSK = 1; + } ctx->verifyCallback = vc; } +#ifdef OPENSSL_ALL +void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx, + CertVerifyCallback cb, void* arg) +{ + WOLFSSL_ENTER("SSL_CTX_set_cert_verify_callback"); + if (ctx == NULL) + return; + + ctx->verifyCertCb = cb; + ctx->verifyCertCbArg = arg; +} +#endif + void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc) { WOLFSSL_ENTER("wolfSSL_set_verify"); - if (mode & SSL_VERIFY_PEER) { + if (ssl == NULL) + return; + + if (mode & WOLFSSL_VERIFY_PEER) { ssl->options.verifyPeer = 1; - ssl->options.verifyNone = 0; /* in case perviously set */ + 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 & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) { + ssl->options.failNoCert = 0; /* fail on all is set to fail on PSK */ + ssl->options.failNoCertxPSK = 1; + } + ssl->verifyCallback = vc; } +void wolfSSL_set_verify_result(WOLFSSL *ssl, long v) +{ + WOLFSSL_ENTER("wolfSSL_set_verify_result"); + + if (ssl == NULL) + return; + +#ifdef OPENSSL_ALL + ssl->verifyCallbackResult = v; +#else + (void)v; + WOLFSSL_STUB("wolfSSL_set_verify_result"); +#endif +} /* store user ctx for verify callback */ void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx) @@ -4140,7 +10010,8 @@ int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname) #endif /* NO_FILESYSTEM */ /* Persist cert cache to memory */ -int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem, int sz, int* used) +int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem, + int sz, int* used) { WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache"); @@ -4174,29 +10045,31 @@ 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 */ #ifndef NO_SESSION_CACHE +WOLFSSL_ABI WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_get_session"); if (ssl) - return GetSession(ssl, 0); + return GetSession(ssl, 0, 1); return NULL; } +WOLFSSL_ABI int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session) { WOLFSSL_ENTER("SSL_set_session"); if (session) return SetSession(ssl, session); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } @@ -4204,7 +10077,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; @@ -4217,7 +10090,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; } @@ -4230,15 +10106,19 @@ 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 */ #if defined(PERSIST_SESSION_CACHE) -/* for persistance, if changes to layout need to increment and modify +/* for persistence, if changes to layout need to increment and modify save_session_cache() and restore_session_cache and memory versions too */ #define WOLFSSL_CACHE_VERSION 2 @@ -4297,7 +10177,7 @@ int wolfSSL_memsave_session_cache(void* mem, int sz) cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION); XMEMCPY(mem, &cache_header, sizeof(cache_header)); - if (LockMutex(&session_mutex) != 0) { + if (wc_LockMutex(&session_mutex) != 0) { WOLFSSL_MSG("Session cache mutex lock failed"); return BAD_MUTEX_E; } @@ -4311,15 +10191,15 @@ int wolfSSL_memsave_session_cache(void* mem, int sz) XMEMCPY(clRow++, ClientCache + i, sizeof(ClientRow)); #endif - UnLockMutex(&session_mutex); + 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; } -/* Restore the persistant session cache from memory */ +/* Restore the persistent session cache from memory */ int wolfSSL_memrestore_session_cache(const void* mem, int sz) { int i; @@ -4346,7 +10226,7 @@ int wolfSSL_memrestore_session_cache(const void* mem, int sz) return CACHE_MATCH_ERROR; } - if (LockMutex(&session_mutex) != 0) { + if (wc_LockMutex(&session_mutex) != 0) { WOLFSSL_MSG("Session cache mutex lock failed"); return BAD_MUTEX_E; } @@ -4360,11 +10240,11 @@ int wolfSSL_memrestore_session_cache(const void* mem, int sz) XMEMCPY(ClientCache + i, clRow++, sizeof(ClientRow)); #endif - UnLockMutex(&session_mutex); + 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) @@ -4375,7 +10255,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; @@ -4384,7 +10264,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; @@ -4399,7 +10279,7 @@ int wolfSSL_save_session_cache(const char *fname) return FWRITE_ERROR; } - if (LockMutex(&session_mutex) != 0) { + if (wc_LockMutex(&session_mutex) != 0) { WOLFSSL_MSG("Session cache mutex lock failed"); XFCLOSE(file); return BAD_MUTEX_E; @@ -4427,7 +10307,7 @@ int wolfSSL_save_session_cache(const char *fname) } #endif /* NO_CLIENT_CACHE */ - UnLockMutex(&session_mutex); + wc_UnLockMutex(&session_mutex); XFCLOSE(file); WOLFSSL_LEAVE("wolfSSL_save_session_cache", rc); @@ -4436,12 +10316,12 @@ int wolfSSL_save_session_cache(const char *fname) } -/* Restore the persistant session cache from file */ +/* Restore the persistent session cache from file */ /* doesn't use memstore because of additional memory use */ 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; @@ -4451,7 +10331,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); @@ -4470,7 +10350,7 @@ int wolfSSL_restore_session_cache(const char *fname) return CACHE_MATCH_ERROR; } - if (LockMutex(&session_mutex) != 0) { + if (wc_LockMutex(&session_mutex) != 0) { WOLFSSL_MSG("Session cache mutex lock failed"); XFCLOSE(file); return BAD_MUTEX_E; @@ -4501,7 +10381,7 @@ int wolfSSL_restore_session_cache(const char *fname) #endif /* NO_CLIENT_CACHE */ - UnLockMutex(&session_mutex); + wc_UnLockMutex(&session_mutex); XFCLOSE(file); WOLFSSL_LEAVE("wolfSSL_restore_session_cache", rc); @@ -4521,10 +10401,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; } @@ -4534,7 +10414,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; @@ -4542,7 +10422,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 @@ -4551,16 +10431,22 @@ int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx) #ifndef NO_SESSION_CACHE /* on by default if built in but allow user to turn off */ +WOLFSSL_ABI 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 */ @@ -4579,7 +10465,7 @@ typedef struct { int signerSz; /* sizeof Signer object */ } CertCacheHeader; -/* current cert persistance layout is: +/* current cert persistence layout is: 1) CertCacheHeader 2) caTable @@ -4590,7 +10476,7 @@ typedef struct { /* Return memory needed to persist this signer, have lock */ -static INLINE int GetSignerMemory(Signer* signer) +static WC_INLINE int GetSignerMemory(Signer* signer) { int sz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) + sizeof(signer->nameLen) + sizeof(signer->subjectNameHash); @@ -4608,7 +10494,7 @@ static INLINE int GetSignerMemory(Signer* signer) /* Return memory needed to persist this row, have lock */ -static INLINE int GetCertCacheRowMemory(Signer* row) +static WC_INLINE int GetCertCacheRowMemory(Signer* row) { int sz = 0; @@ -4622,7 +10508,7 @@ static INLINE int GetCertCacheRowMemory(Signer* row) /* get the size of persist cert cache, have lock */ -static INLINE int GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm) +static WC_INLINE int GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm) { int sz; int i; @@ -4637,7 +10523,7 @@ static INLINE int GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm) /* Store cert cache header columns with number of items per list, have lock */ -static INLINE void SetCertHeaderColumns(WOLFSSL_CERT_MANAGER* cm, int* columns) +static WC_INLINE void SetCertHeaderColumns(WOLFSSL_CERT_MANAGER* cm, int* columns) { int i; Signer* row; @@ -4657,7 +10543,7 @@ static INLINE void SetCertHeaderColumns(WOLFSSL_CERT_MANAGER* cm, int* columns) /* Restore whole cert row from memory, have lock, return bytes consumed, < 0 on error, have lock */ -static INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, +static WC_INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, int row, int listSz, const byte* end) { int idx = 0; @@ -4669,6 +10555,7 @@ static INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, while (listSz) { Signer* signer; + byte* publicKey; byte* start = current + idx; /* for end checks on this signer */ int minSz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) + sizeof(signer->nameLen) + sizeof(signer->subjectNameHash); @@ -4698,14 +10585,15 @@ static INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, FreeSigner(signer, cm->heap); return BUFFER_E; } - signer->publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap, - DYNAMIC_TYPE_KEY); - if (signer->publicKey == NULL) { + publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap, + DYNAMIC_TYPE_KEY); + if (publicKey == NULL) { FreeSigner(signer, cm->heap); return MEMORY_E; } - XMEMCPY(signer->publicKey, current + idx, signer->pubKeySize); + XMEMCPY(publicKey, current + idx, signer->pubKeySize); + signer->publicKey = publicKey; idx += signer->pubKeySize; /* nameLen */ @@ -4749,7 +10637,7 @@ static INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, /* Store whole cert row into memory, have lock, return bytes added */ -static INLINE int StoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, int row) +static WC_INLINE int StoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, int row) { int added = 0; Signer* list = cm->caTable[row]; @@ -4786,10 +10674,11 @@ static INLINE int StoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, int row) /* Persist cert cache to memory, have lock */ -static INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz) +static WC_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"); @@ -4825,7 +10714,7 @@ static INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) { XFILE file; - int rc = SSL_SUCCESS; + int rc = WOLFSSL_SUCCESS; int memSz; byte* mem; @@ -4834,11 +10723,11 @@ 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 (LockMutex(&cm->caLock) != 0) { - WOLFSSL_MSG("LockMutex on caLock failed"); + if (wc_LockMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("wc_LockMutex on caLock failed"); XFCLOSE(file); return BAD_MUTEX_E; } @@ -4850,7 +10739,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"); @@ -4860,7 +10749,7 @@ int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); } - UnLockMutex(&cm->caLock); + wc_UnLockMutex(&cm->caLock); XFCLOSE(file); return rc; @@ -4871,7 +10760,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; @@ -4881,17 +10770,20 @@ 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); + if(XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } memSz = (int)XFTELL(file); XREWIND(file); - if (memSz <= 0) { - WOLFSSL_MSG("Bad file size"); + if (memSz > MAX_WOLFSSL_FILE_SIZE || memSz <= 0) { + WOLFSSL_MSG("CM_RestoreCertCache file size error"); XFCLOSE(file); - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; } mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -4907,7 +10799,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"); } } @@ -4924,20 +10816,20 @@ 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"); - if (LockMutex(&cm->caLock) != 0) { - WOLFSSL_MSG("LockMutex on caLock failed"); + if (wc_LockMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("wc_LockMutex on caLock failed"); return BAD_MUTEX_E; } ret = DoMemSaveCertCache(cm, mem, sz); - if (ret == SSL_SUCCESS) + if (ret == WOLFSSL_SUCCESS) *used = GetCertCacheMemSize(cm); - UnLockMutex(&cm->caLock); + wc_UnLockMutex(&cm->caLock); return ret; } @@ -4946,7 +10838,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); @@ -4967,8 +10859,8 @@ int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz) return CACHE_MATCH_ERROR; } - if (LockMutex(&cm->caLock) != 0) { - WOLFSSL_MSG("LockMutex on caLock failed"); + if (wc_LockMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("wc_LockMutex on caLock failed"); return BAD_MUTEX_E; } @@ -4984,7 +10876,7 @@ int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz) current += added; } - UnLockMutex(&cm->caLock); + wc_UnLockMutex(&cm->caLock); return ret; } @@ -4997,14 +10889,14 @@ int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm) WOLFSSL_ENTER("CM_GetCertCacheMemSize"); - if (LockMutex(&cm->caLock) != 0) { - WOLFSSL_MSG("LockMutex on caLock failed"); + if (wc_LockMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("wc_LockMutex on caLock failed"); return BAD_MUTEX_E; } sz = GetCertCacheMemSize(cm); - UnLockMutex(&cm->caLock); + wc_UnLockMutex(&cm->caLock); return sz; } @@ -5012,45 +10904,251 @@ int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm) #endif /* PERSIST_CERT_CACHE */ #endif /* NO_CERTS */ +#ifdef OPENSSL_EXTRA + + +/* removes all cipher suites from the list that contain "toRemove" + * returns the new list size on success + */ +static int wolfSSL_remove_ciphers(char* list, int sz, const char* toRemove) +{ + int idx = 0; + char* next = (char*)list; + int totalSz = sz; + + if (list == NULL) { + return 0; + } + + do { + char* current = next; + char name[MAX_SUITE_NAME + 1]; + word32 length; + + next = XSTRSTR(next, ":"); + length = min(sizeof(name), !next ? (word32)XSTRLEN(current) /* last */ + : (word32)(next - current)); + + XSTRNCPY(name, current, length); + name[(length == sizeof(name)) ? length - 1 : length] = 0; + + if (XSTRSTR(name, toRemove)) { + XMEMMOVE(list + idx, list + idx + length, totalSz - (idx + length)); + totalSz -= length; + list[totalSz] = '\0'; + next = current; + } + else { + idx += length; + } + } while (next++); /* ++ needed to skip ':' */ + + return totalSz; +} + +/* parse some bulk lists like !eNULL / !aNULL + * + * returns WOLFSSL_SUCCESS on success and sets the cipher suite list + */ +static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, Suites* suites, + const char* list) +{ + int ret = 0; + const int suiteSz = GetCipherNamesSize(); + char* next = (char*)list; + const CipherSuiteInfo* names = GetCipherNames(); + char* localList = NULL; + int sz = 0; + + if (suites == NULL || list == NULL) { + WOLFSSL_MSG("NULL argument"); + return WOLFSSL_FAILURE; + } + + /* does list contain eNULL or aNULL? */ + if (XSTRSTR(list, "aNULL") || XSTRSTR(list, "eNULL")) { + do { + char* current = next; + char name[MAX_SUITE_NAME + 1]; + int i; + word32 length; + + next = XSTRSTR(next, ":"); + length = min(sizeof(name), !next ? (word32)XSTRLEN(current) /*last*/ + : (word32)(next - current)); + + XSTRNCPY(name, current, length); + name[(length == sizeof(name)) ? length - 1 : length] = 0; + + /* check for "not" case */ + if (name[0] == '!' && suiteSz > 0) { + /* populate list with all suites if not already created */ + if (localList == NULL) { + for (i = 0; i < suiteSz; i++) { + sz += (int)XSTRLEN(names[i].name) + 2; + } + localList = (char*)XMALLOC(sz, ctx->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (localList == NULL) { + return WOLFSSL_FAILURE; + } + wolfSSL_get_ciphers(localList, sz); + sz = (int)XSTRLEN(localList); + } + + if (XSTRSTR(name, "eNULL")) { + wolfSSL_remove_ciphers(localList, sz, "-NULL"); + } + } + } + while (next++); /* ++ needed to skip ':' */ + + ret = SetCipherList(ctx, suites, localList); + XFREE(localList, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + return (ret)? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; + } + else { + return (SetCipherList(ctx, suites, list)) ? WOLFSSL_SUCCESS : + WOLFSSL_FAILURE; + } +} + +#endif + int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list) { WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list"); + if (ctx == NULL) + return WOLFSSL_FAILURE; + /* alloc/init on demand only */ if (ctx->suites == NULL) { ctx->suites = (Suites*)XMALLOC(sizeof(Suites), ctx->heap, 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; +#ifdef OPENSSL_EXTRA + return wolfSSL_parse_cipher_list(ctx, ctx->suites, list); +#else + return (SetCipherList(ctx, ctx->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +#endif } 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; +#ifdef SINGLE_THREADED + if (ssl->ctx->suites == ssl->suites) { + ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, + DYNAMIC_TYPE_SUITES); + if (ssl->suites == NULL) { + WOLFSSL_MSG("Suites Memory error"); + return MEMORY_E; + } + ssl->options.ownSuites = 1; + } +#endif + +#ifdef OPENSSL_EXTRA + return wolfSSL_parse_cipher_list(ssl->ctx, ssl->suites, list); +#else + return (SetCipherList(ssl->ctx, ssl->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +#endif +} + + +int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl) +{ + int useNb = 0; + + if (ssl == NULL) + return WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock"); + if (ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + useNb = ssl->options.dtlsUseNonblock; +#endif + } + else { + WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is " + "DEPRECATED for non-DTLS use."); + } + return useNb; } #ifndef WOLFSSL_LEANPSK + +void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock) +{ + (void)nonblock; + + WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock"); + + if (ssl == NULL) + return; + + if (ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + ssl->options.dtlsUseNonblock = (nonblock != 0); +#endif + } + else { + WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is " + "DEPRECATED for non-DTLS use."); + } +} + + #ifdef WOLFSSL_DTLS int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl) { - (void)ssl; + int timeout = 0; + if (ssl) + timeout = ssl->dtls_timeout; - return ssl->dtls_timeout; + WOLFSSL_LEAVE("wolfSSL_dtls_get_current_timeout()", timeout); + return timeout; } +int wolfSSL_DTLSv1_get_timeout(WOLFSSL* ssl, WOLFSSL_TIMEVAL* timeleft) +{ + if (ssl && timeleft) { + XMEMSET(timeleft, 0, sizeof(WOLFSSL_TIMEVAL)); + timeleft->tv_sec = ssl->dtls_timeout; + } + return 0; +} -/* user may need to alter init dtls recv timeout, SSL_SUCCESS on ok */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_DTLSv1_handle_timeout(WOLFSSL* ssl) +{ + WOLFSSL_STUB("SSL_DTLSv1_handle_timeout"); + (void)ssl; + return 0; +} +#endif + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_DTLSv1_set_initial_timeout_duration(WOLFSSL* ssl, word32 duration_ms) +{ + WOLFSSL_STUB("SSL_DTLSv1_set_initial_timeout_duration"); + (void)ssl; + (void)duration_ms; +} +#endif + +/* 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) @@ -5064,11 +11162,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) @@ -5081,74 +11179,248 @@ 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; + WOLFSSL_ENTER("wolfSSL_dtls_got_timeout()"); - DtlsMsgListDelete(ssl->dtls_msg_list, ssl->heap); - ssl->dtls_msg_list = NULL; - if (DtlsPoolTimeout(ssl) < 0 || DtlsPoolSend(ssl) < 0) { - result = SSL_FATAL_ERROR; + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; + + if (!ssl->options.handShakeDone && + (DtlsMsgPoolTimeout(ssl) < 0 || DtlsMsgPoolSend(ssl, 0) < 0)) { + + result = WOLFSSL_FATAL_ERROR; } + + WOLFSSL_LEAVE("wolfSSL_dtls_got_timeout()", result); return result; } + +/* retransmit all the saves messages, WOLFSSL_SUCCESS on ok */ +int wolfSSL_dtls_retransmit(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_dtls_retransmit()"); + + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; + + if (!ssl->options.handShakeDone) { + int result = DtlsMsgPoolSend(ssl, 0); + if (result < 0) { + ssl->error = result; + WOLFSSL_ERROR(result); + return WOLFSSL_FATAL_ERROR; + } + } + + return 0; +} + #endif /* DTLS */ #endif /* LEANPSK */ +#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) + +/* Not an SSL function, return 0 for success, error code otherwise */ +/* Prereq: ssl's RNG needs to be initialized. */ +int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, + const byte* secret, word32 secretSz) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret"); + + if (ssl == NULL) { + WOLFSSL_MSG("need a SSL object"); + return BAD_FUNC_ARG; + } + + if (secret != NULL && secretSz == 0) { + WOLFSSL_MSG("can't have a new secret without a size"); + return BAD_FUNC_ARG; + } + + /* If secretSz is 0, use the default size. */ + if (secretSz == 0) + secretSz = COOKIE_SECRET_SZ; + + if (secretSz != ssl->buffers.dtlsCookieSecret.length) { + byte* newSecret; + + if (ssl->buffers.dtlsCookieSecret.buffer != NULL) { + ForceZero(ssl->buffers.dtlsCookieSecret.buffer, + ssl->buffers.dtlsCookieSecret.length); + XFREE(ssl->buffers.dtlsCookieSecret.buffer, + ssl->heap, DYNAMIC_TYPE_NONE); + } + + newSecret = (byte*)XMALLOC(secretSz, ssl->heap,DYNAMIC_TYPE_COOKIE_PWD); + if (newSecret == NULL) { + ssl->buffers.dtlsCookieSecret.buffer = NULL; + ssl->buffers.dtlsCookieSecret.length = 0; + WOLFSSL_MSG("couldn't allocate new cookie secret"); + return MEMORY_ERROR; + } + ssl->buffers.dtlsCookieSecret.buffer = newSecret; + ssl->buffers.dtlsCookieSecret.length = secretSz; + } + + /* If the supplied secret is NULL, randomly generate a new secret. */ + 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 ret; +} + +#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ + + +/* EITHER SIDE METHODS */ +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + WOLFSSL_METHOD* wolfSSLv23_method(void) + { + return wolfSSLv23_method_ex(NULL); + } + WOLFSSL_METHOD* wolfSSLv23_method_ex(void* heap) + { + WOLFSSL_METHOD* m = NULL; + WOLFSSL_ENTER("SSLv23_method"); + #if !defined(NO_WOLFSSL_CLIENT) + m = wolfSSLv23_client_method_ex(heap); + #elif !defined(NO_WOLFSSL_SERVER) + m = wolfSSLv23_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + + return m; + } + + #ifdef WOLFSSL_ALLOW_SSLV3 + WOLFSSL_METHOD* wolfSSLv3_method(void) + { + return wolfSSLv3_method_ex(NULL); + } + WOLFSSL_METHOD* wolfSSLv3_method_ex(void* heap) + { + WOLFSSL_METHOD* m = NULL; + WOLFSSL_ENTER("SSLv3_method"); + #if !defined(NO_WOLFSSL_CLIENT) + m = wolfSSLv3_client_method_ex(heap); + #elif !defined(NO_WOLFSSL_SERVER) + m = wolfSSLv3_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + + return m; + } + #endif +#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ + /* client only parts */ #ifndef NO_WOLFSSL_CLIENT - #ifndef NO_OLD_TLS + #ifdef OPENSSL_EXTRA + WOLFSSL_METHOD* wolfSSLv2_client_method(void) + { + WOLFSSL_STUB("wolfSSLv2_client_method"); + return NULL; + } + #endif + + #ifdef WOLFSSL_ALLOW_SSLV3 WOLFSSL_METHOD* wolfSSLv3_client_method(void) + { + return wolfSSLv3_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfSSLv3_client_method_ex(void* heap) { WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, - DYNAMIC_TYPE_METHOD); - WOLFSSL_ENTER("SSLv3_client_method"); + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("SSLv3_client_method_ex"); if (method) InitSSL_Method(method, MakeSSLv3()); return method; } - #endif + #endif /* WOLFSSL_ALLOW_SSLV3 */ - #ifdef WOLFSSL_DTLS + WOLFSSL_METHOD* wolfSSLv23_client_method(void) + { + return wolfSSLv23_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfSSLv23_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("SSLv23_client_method_ex"); + if (method) { + #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) + #if defined(WOLFSSL_TLS13) + InitSSL_Method(method, MakeTLSv1_3()); + #elif !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeTLSv1_1()); + #endif + #else #ifndef NO_OLD_TLS - WOLFSSL_METHOD* wolfDTLSv1_client_method(void) - { - WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, - DYNAMIC_TYPE_METHOD); - WOLFSSL_ENTER("DTLSv1_client_method"); - if (method) - InitSSL_Method(method, MakeDTLSv1()); - return method; - } - #endif /* NO_OLD_TLS */ - - WOLFSSL_METHOD* wolfDTLSv1_2_client_method(void) - { - WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, - DYNAMIC_TYPE_METHOD); - WOLFSSL_ENTER("DTLSv1_2_client_method"); - if (method) - InitSSL_Method(method, MakeDTLSv1_2()); - return method; - } + InitSSL_Method(method, MakeTLSv1_1()); + #endif #endif + #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13) + method->downgrade = 1; + #endif + } + return method; + } + + + #if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_SSLV3) + /* If SCTP is not enabled returns the state of the dtls option. + * If SCTP is enabled returns dtls && !sctp. */ + static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl) + { + int result = ssl->options.dtls; + + if (result) { + #ifdef WOLFSSL_SCTP + result = !ssl->options.dtlsSctp; + #endif + } + + return result; + } + #endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */ /* please see note at top of README if you get an error from connect */ + WOLFSSL_ABI int wolfSSL_connect(WOLFSSL* ssl) { + #if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)) int neededState; + #endif WOLFSSL_ENTER("SSL_connect()"); @@ -5156,33 +11428,72 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) errno = 0; #endif + if (ssl == NULL) + return BAD_FUNC_ARG; + + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + if (ssl->options.side == WOLFSSL_NEITHER_END) { + ssl->error = InitSSL_Side(ssl, WOLFSSL_CLIENT_END); + if (ssl->error != WOLFSSL_SUCCESS) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->error = 0; /* expected to be zero here */ + } + + #ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_ST_CONNECT, SSL_SUCCESS); + ssl->cbmode = SSL_CB_WRITE; + } + #endif + #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ + + #if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13) + return wolfSSL_connect_TLSv13(ssl); + #else + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif + if (ssl->options.side != WOLFSSL_CLIENT_END) { WOLFSSL_ERROR(ssl->error = SIDE_ERROR); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } #ifdef WOLFSSL_DTLS - if (ssl->version.major == DTLS_MAJOR) { - ssl->options.dtls = 1; - ssl->options.tls = 1; - ssl->options.tls1_1 = 1; - - if (DtlsPoolInit(ssl) != 0) { - ssl->error = MEMORY_ERROR; - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } - } + if (ssl->version.major == DTLS_MAJOR) { + ssl->options.dtls = 1; + ssl->options.tls = 1; + ssl->options.tls1_1 = 1; + } #endif - if (ssl->buffers.outputBuffer.length > 0) { + if (ssl->buffers.outputBuffer.length > 0 + #ifdef WOLFSSL_ASYNC_CRYPT + /* do not send buffered or advance state if last error was an + async pending operation */ + && ssl->error != WC_PENDING_E + #endif + ) { if ( (ssl->error = SendBuffered(ssl)) == 0) { - ssl->options.connectState++; - WOLFSSL_MSG("connect state: Advanced from buffered send"); + /* 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 SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } @@ -5192,10 +11503,11 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) /* 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 : @@ -5204,19 +11516,23 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) /* In DTLS, when resuming, we can go straight to FINISHED, * or do a cookie exchange and then skip to FINISHED, assume * we need the cookie exchange first. */ - if (ssl->options.dtls) + if (IsDtlsNotSctpMode(ssl)) neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; #endif /* get response */ while (ssl->options.serverState < neededState) { + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif 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) if (!ssl->options.resuming) { - if (!ssl->options.dtls) + if (!IsDtlsNotSctpMode(ssl)) neededState = SERVER_HELLODONE_COMPLETE; else neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; @@ -5225,84 +11541,73 @@ int wolfSSL_dtls_got_timeout(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 (ssl->options.dtls) { + if (ssl->options.serverState == + SERVER_HELLOVERIFYREQUEST_COMPLETE) { + 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 - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE; /* get response */ while (ssl->options.serverState < neededState) { if ( (ssl->error = ProcessReply(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; } /* if resumption failed, reset needed state */ - else if (neededState == SERVER_FINISHED_COMPLETE) + if (neededState == SERVER_FINISHED_COMPLETE) { if (!ssl->options.resuming) neededState = SERVER_HELLODONE_COMPLETE; + } } } #endif ssl->options.connectState = FIRST_REPLY_DONE; WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); + FALL_THROUGH; case FIRST_REPLY_DONE : - #ifndef NO_CERTS + #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif 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"); } @@ -5310,60 +11615,70 @@ int wolfSSL_dtls_got_timeout(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 !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) 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 + #endif /* !NO_CERTS && !WOLFSSL_NO_CLIENT_AUTH */ 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 @@ -5372,18 +11687,30 @@ int wolfSSL_dtls_got_timeout(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 */ - FreeHandshakeResources(ssl); - WOLFSSL_LEAVE("SSL_connect()", SSL_SUCCESS); - return SSL_SUCCESS; + + if (!ssl->options.dtls) { + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } + } +#ifdef WOLFSSL_DTLS + else { + ssl->options.dtlsHsRetain = 1; + } +#endif /* WOLFSSL_DTLS */ + + 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 */ } + #endif /* !WOLFSSL_NO_TLS12 */ } #endif /* NO_WOLFSSL_CLIENT */ @@ -5392,58 +11719,101 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) /* server only parts */ #ifndef NO_WOLFSSL_SERVER - #ifndef NO_OLD_TLS + #ifdef OPENSSL_EXTRA + WOLFSSL_METHOD* wolfSSLv2_server_method(void) + { + WOLFSSL_STUB("wolfSSLv2_server_method"); + return 0; + } + #endif + + #ifdef WOLFSSL_ALLOW_SSLV3 WOLFSSL_METHOD* wolfSSLv3_server_method(void) + { + return wolfSSLv3_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfSSLv3_server_method_ex(void* heap) { WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, - DYNAMIC_TYPE_METHOD); - WOLFSSL_ENTER("SSLv3_server_method"); + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("SSLv3_server_method_ex"); if (method) { InitSSL_Method(method, MakeSSLv3()); method->side = WOLFSSL_SERVER_END; } return method; } - #endif + #endif /* WOLFSSL_ALLOW_SSLV3 */ + WOLFSSL_METHOD* wolfSSLv23_server_method(void) + { + return wolfSSLv23_server_method_ex(NULL); + } - #ifdef WOLFSSL_DTLS - + WOLFSSL_METHOD* wolfSSLv23_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("SSLv23_server_method_ex"); + if (method) { + #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) + #ifdef WOLFSSL_TLS13 + InitSSL_Method(method, MakeTLSv1_3()); + #elif !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeTLSv1_1()); + #endif + #else #ifndef NO_OLD_TLS - WOLFSSL_METHOD* wolfDTLSv1_server_method(void) - { - WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), - 0, DYNAMIC_TYPE_METHOD); - WOLFSSL_ENTER("DTLSv1_server_method"); - if (method) { - InitSSL_Method(method, MakeDTLSv1()); - method->side = WOLFSSL_SERVER_END; - } - return method; - } - #endif /* NO_OLD_TLS */ - - WOLFSSL_METHOD* wolfDTLSv1_2_server_method(void) - { - WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), - 0, DYNAMIC_TYPE_METHOD); - WOLFSSL_ENTER("DTLSv1_2_server_method"); - if (method) { - InitSSL_Method(method, MakeDTLSv1_2()); - method->side = WOLFSSL_SERVER_END; - } - return method; - } + InitSSL_Method(method, MakeTLSv1_1()); + #else + #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2 + #endif #endif + #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13) + method->downgrade = 1; + #endif + method->side = WOLFSSL_SERVER_END; + } + return method; + } int wolfSSL_accept(WOLFSSL* ssl) { - byte havePSK = 0; - byte haveAnon = 0; +#if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)) + word16 havePSK = 0; + word16 haveAnon = 0; + word16 haveMcast = 0; +#endif + + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; + + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + if (ssl->options.side == WOLFSSL_NEITHER_END) { + WOLFSSL_MSG("Setting WOLFSSL_SSL to be server side"); + ssl->error = InitSSL_Side(ssl, WOLFSSL_SERVER_END); + if (ssl->error != WOLFSSL_SUCCESS) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->error = 0; /* expected to be zero here */ + } + #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ + +#if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13) + return wolfSSL_accept_TLSv13(ssl); +#else + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_accept_TLSv13(ssl); + #endif WOLFSSL_ENTER("SSL_accept()"); #ifdef HAVE_ERRNO_H @@ -5460,219 +11830,236 @@ int wolfSSL_dtls_got_timeout(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 && - (ssl->buffers.certificate.buffer == NULL || - ssl->buffers.key.buffer == NULL)) { - WOLFSSL_MSG("accept error: don't have server cert and key"); - ssl->error = NO_PRIVATE_KEY; - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + #ifndef NO_CERTS + /* in case used set_accept_state after init */ + /* allow no private key if using PK callbacks and CB is set */ + if (!havePSK && !haveAnon && !haveMcast) { + if (!ssl->buffers.certificate || + !ssl->buffers.certificate->buffer) { + + WOLFSSL_MSG("accept error: server cert required"); + WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + return WOLFSSL_FATAL_ERROR; } - #endif - #ifdef WOLFSSL_DTLS - if (ssl->version.major == DTLS_MAJOR) { - ssl->options.dtls = 1; - ssl->options.tls = 1; - ssl->options.tls1_1 = 1; - - if (DtlsPoolInit(ssl) != 0) { - ssl->error = MEMORY_ERROR; - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + WOLFSSL_MSG("Using PK for server private key"); } + else #endif + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + WOLFSSL_MSG("accept error: server key required"); + WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + return WOLFSSL_FATAL_ERROR; + } + } + #endif - if (ssl->buffers.outputBuffer.length > 0) { + #ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) { + ssl->options.dtls = 1; + ssl->options.tls = 1; + ssl->options.tls1_1 = 1; + } + #endif + + if (ssl->buffers.outputBuffer.length > 0 + #ifdef WOLFSSL_ASYNC_CRYPT + /* do not send buffered or advance state if last error was an + async pending operation */ + && ssl->error != WC_PENDING_E + #endif + ) { if ( (ssl->error = SendBuffered(ssl)) == 0) { - ssl->options.acceptState++; - WOLFSSL_MSG("accept state: Advanced from buffered send"); + /* 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 SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } switch (ssl->options.acceptState) { case ACCEPT_BEGIN : +#ifdef HAVE_SECURE_RENEGOTIATION + case ACCEPT_BEGIN_RENEG: +#endif /* get response */ 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 : - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - if ( (ssl->error = SendHelloVerifyRequest(ssl)) != 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } - #endif - ssl->options.acceptState = HELLO_VERIFY_SENT; - WOLFSSL_MSG("accept state HELLO_VERIFY_SENT"); - - case HELLO_VERIFY_SENT: - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - ssl->options.clientState = NULL_STATE; /* get again */ - /* reset messages received */ - XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); - /* 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) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } #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 - } - - while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) - if ( (ssl->error = ProcessReply(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_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 : 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 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 @@ -5681,18 +12068,40 @@ int wolfSSL_dtls_got_timeout(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 */ - FreeHandshakeResources(ssl); - WOLFSSL_LEAVE("SSL_accept()", SSL_SUCCESS); - return SSL_SUCCESS; + + if (!ssl->options.dtls) { + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } + } +#ifdef WOLFSSL_DTLS + else { + ssl->options.dtlsHsRetain = 1; + } +#endif /* WOLFSSL_DTLS */ + +#ifdef WOLFSSL_SESSION_EXPORT + if (ssl->dtls_export) { + if ((ssl->error = wolfSSL_send_session(ssl)) != 0) { + WOLFSSL_MSG("Export DTLS session error"); + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif + + WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; default : WOLFSSL_MSG("Unknown accept state ERROR"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } +#endif /* !WOLFSSL_NO_TLS12 */ } #endif /* NO_WOLFSSL_SERVER */ @@ -5711,15 +12120,15 @@ 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 */ - +WOLFSSL_ABI int wolfSSL_Cleanup(void) { - int ret = SSL_SUCCESS; + int ret = WOLFSSL_SUCCESS; int release = 0; WOLFSSL_ENTER("wolfSSL_Cleanup"); @@ -5727,7 +12136,7 @@ int wolfSSL_Cleanup(void) if (initRefCount == 0) return ret; /* possibly no init yet, but not failure either way */ - if (LockMutex(&count_mutex) != 0) { + if (wc_LockMutex(&count_mutex) != 0) { WOLFSSL_MSG("Bad Lock Mutex count"); return BAD_MUTEX_E; } @@ -5736,22 +12145,34 @@ int wolfSSL_Cleanup(void) if (initRefCount < 0) initRefCount = 0; - UnLockMutex(&count_mutex); + wc_UnLockMutex(&count_mutex); if (!release) return ret; +#ifdef OPENSSL_EXTRA + if (bn_one) { + wolfSSL_BN_free(bn_one); + bn_one = NULL; + } +#endif + #ifndef NO_SESSION_CACHE - if (FreeMutex(&session_mutex) != 0) + if (wc_FreeMutex(&session_mutex) != 0) ret = BAD_MUTEX_E; #endif - if (FreeMutex(&count_mutex) != 0) + if (wc_FreeMutex(&count_mutex) != 0) ret = BAD_MUTEX_E; -#if defined(HAVE_ECC) && defined(FP_ECC) - wc_ecc_fp_free(); +#ifdef OPENSSL_EXTRA + wolfSSL_RAND_Cleanup(); #endif + if (wolfCrypt_Cleanup() != 0) { + WOLFSSL_MSG("Error with wolfCrypt_Cleanup call"); + ret = WC_CLEANUP_E; + } + return ret; } @@ -5759,10 +12180,10 @@ int wolfSSL_Cleanup(void) #ifndef NO_SESSION_CACHE -/* some session IDs aren't random afterall, let's make them random */ -static INLINE word32 HashSession(const byte* sessionID, word32 len, int* error) +/* some session IDs aren't random after all, let's make them random */ +static WC_INLINE word32 HashSession(const byte* sessionID, word32 len, int* error) { - byte digest[MAX_DIGEST_SIZE]; + byte digest[WC_MAX_DIGEST_SIZE]; #ifndef NO_MD5 *error = wc_Md5Hash(sessionID, len, digest); @@ -5778,35 +12199,42 @@ static INLINE word32 HashSession(const byte* sessionID, word32 len, int* error) } +WOLFSSL_ABI void wolfSSL_flush_sessions(WOLFSSL_CTX* ctx, long tm) { - /* static table now, no flusing needed */ + /* static table now, no flushing needed */ (void)ctx; (void)tm; } /* set ssl session timeout in seconds */ +WOLFSSL_ABI 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; } /* set ctx session timeout in seconds */ +WOLFSSL_ABI 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; } @@ -5823,17 +12251,33 @@ 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"); return NULL; } - if (LockMutex(&session_mutex) != 0) { + if (wc_LockMutex(&session_mutex) != 0) { WOLFSSL_MSG("Lock session mutex failed"); return NULL; } @@ -5870,15 +12314,49 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len) } } - UnLockMutex(&session_mutex); + wc_UnLockMutex(&session_mutex); return ret; } #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 WC_INLINE void RestoreSession(WOLFSSL* ssl, WOLFSSL_SESSION* session, + byte* masterSecret, byte restoreSessionCerts) +{ + (void)ssl; + (void)restoreSessionCerts; -WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret) + 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; + #ifdef NO_RESUME_SUITE_CHECK + ssl->session.cipherSuite0 = session->cipherSuite0; + ssl->session.cipherSuite = session->cipherSuite; + #endif + } +#endif /* SESSION_CERTS */ +#if !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + ssl->session.cipherSuite0 = session->cipherSuite0; + ssl->session.cipherSuite = session->cipherSuite; +#endif +} + +WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, + byte restoreSessionCerts) { WOLFSSL_SESSION* ret = 0; const byte* id = NULL; @@ -5887,6 +12365,8 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret) int count; int error = 0; + (void) restoreSessionCerts; + if (ssl->options.sessionCacheOff) return NULL; @@ -5898,18 +12378,33 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret) return NULL; #endif - if (ssl->arrays) + if (!ssl->options.tls1_3 && ssl->arrays != NULL) id = ssl->arrays->sessionID; 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"); return NULL; } - if (LockMutex(&session_mutex) != 0) + if (wc_LockMutex(&session_mutex) != 0) return 0; /* start from most recently used */ @@ -5932,8 +12427,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); + RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); } else { WOLFSSL_MSG("Session timed out"); } @@ -5943,30 +12437,174 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret) } } - UnLockMutex(&session_mutex); + wc_UnLockMutex(&session_mutex); return ret; } +static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) +{ + WOLFSSL_SESSION* copyInto = &ssl->session; + void* tmpBuff = NULL; + int ticketLen = 0; + int doDynamicCopy = 0; + int ret = WOLFSSL_SUCCESS; + + (void)ticketLen; + (void)doDynamicCopy; + (void)tmpBuff; + + if (!ssl || !copyFrom) + return BAD_FUNC_ARG; + +#ifdef HAVE_SESSION_TICKET + /* Free old dynamic ticket if we had one to avoid leak */ + if (copyInto->isDynamic) { + XFREE(copyInto->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + copyInto->ticket = copyInto->staticTicket; + copyInto->isDynamic = 0; + } +#endif + + if (wc_LockMutex(&session_mutex) != 0) + return BAD_MUTEX_E; + +#ifdef HAVE_SESSION_TICKET + /* Size of ticket to alloc if needed; Use later for alloc outside lock */ + doDynamicCopy = copyFrom->isDynamic; + ticketLen = copyFrom->ticketLen; +#endif + + *copyInto = *copyFrom; + + /* Default ticket to non dynamic. This will avoid crash if we fail below */ +#ifdef HAVE_SESSION_TICKET + copyInto->ticket = copyInto->staticTicket; + copyInto->isDynamic = 0; +#endif + +#ifndef NO_RESUME_SUITE_CHECK + copyInto->cipherSuite0 = copyFrom->cipherSuite0; + copyInto->cipherSuite = copyFrom->cipherSuite; +#endif + + if (wc_UnLockMutex(&session_mutex) != 0) { + return BAD_MUTEX_E; + } + +#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; + } + +#ifdef NO_RESUME_SUITE_CHECK + copyInto->cipherSuite0 = copyFrom->cipherSuite0; + copyInto->cipherSuite = copyFrom->cipherSuite; +#endif + 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) { + tmpBuff = (byte*)XMALLOC(ticketLen, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + if (!tmpBuff) + return MEMORY_ERROR; + + if (wc_LockMutex(&session_mutex) != 0) { + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + return BAD_MUTEX_E; + } + + if ((word16)ticketLen != copyFrom->ticketLen) { + /* Another thread modified the ssl-> session ticket during alloc. + * Treat as error, since ticket different than when copy requested */ + ret = VAR_STATE_CHANGE_E; + } + + if (ret == WOLFSSL_SUCCESS) { + copyInto->ticket = (byte*)tmpBuff; + copyInto->isDynamic = 1; + XMEMCPY(copyInto->ticket, copyFrom->ticket, ticketLen); + } + } else { + /* Need to ensure ticket pointer gets updated to own buffer + * and is not pointing to buff of session copied from */ + copyInto->ticket = copyInto->staticTicket; + } + + if (doDynamicCopy) { + if (wc_UnLockMutex(&session_mutex) != 0) { + if (ret == WOLFSSL_SUCCESS) + ret = BAD_MUTEX_E; + } + } + + if (ret != WOLFSSL_SUCCESS) { + /* cleanup */ + if (tmpBuff) + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + copyInto->ticket = copyInto->staticTicket; + copyInto->isDynamic = 0; + } +#endif /* HAVE_SESSION_TICKET */ + return ret; +} + + int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) { if (ssl->options.sessionCacheOff) - return SSL_FAILURE; + return WOLFSSL_FAILURE; + +#ifdef OPENSSL_EXTRA + /* check for application context id */ + if (ssl->sessionCtxSz > 0) { + if (XMEMCMP(ssl->sessionCtx, session->sessionCtx, ssl->sessionCtxSz)) { + /* context id did not match! */ + WOLFSSL_MSG("Session context did not match"); + return SSL_FAILURE; + } + } +#endif /* OPENSSL_EXTRA */ if (LowResTimer() < (session->bornOn + session->timeout)) { - ssl->session = *session; - ssl->options.resuming = 1; + int ret = GetDeepCopySession(ssl, session); + if (ret == WOLFSSL_SUCCESS) { + ssl->options.resuming = 1; -#ifdef SESSION_CERTS - ssl->version = session->version; - ssl->options.cipherSuite0 = session->cipherSuite0; - ssl->options.cipherSuite = session->cipherSuite; +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + ssl->version = session->version; #endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + ssl->options.cipherSuite0 = session->cipherSuite0; + ssl->options.cipherSuite = session->cipherSuite; +#endif + } - return SSL_SUCCESS; + return ret; } - return SSL_FAILURE; /* session timed out */ + return WOLFSSL_FAILURE; /* session timed out */ } @@ -5977,8 +12615,16 @@ 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; + int i; + int overwrite = 0; if (ssl->options.sessionCacheOff) return 0; @@ -5991,94 +12637,278 @@ 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 */ + if(ticLen > SESSION_TICKET_LEN) { + tmpBuff = (byte*)XMALLOC(ticLen, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + if(!tmpBuff) + return MEMORY_E; } - - if (LockMutex(&session_mutex) != 0) - return BAD_MUTEX_E; - - idx = SessionCache[row].nextIdx++; -#ifdef SESSION_INDEX - ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; #endif - XMEMCPY(SessionCache[row].Sessions[idx].masterSecret, - ssl->arrays->masterSecret, SECRET_LEN); - XMEMCPY(SessionCache[row].Sessions[idx].sessionID, ssl->arrays->sessionID, - ID_LEN); - SessionCache[row].Sessions[idx].sessionIDSz = ssl->arrays->sessionIDSz; +#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); +#endif + 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. + */ +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + if (ssl->options.tls1_3) { + row = HashSession(ssl->session.sessionID, ID_LEN, &error) % + SESSION_ROWS; + } + else +#endif + { + 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; + } - SessionCache[row].Sessions[idx].timeout = ssl->timeout; - SessionCache[row].Sessions[idx].bornOn = LowResTimer(); + if (wc_LockMutex(&session_mutex) != 0) { +#ifdef HAVE_SESSION_TICKET + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif + return BAD_MUTEX_E; + } + + for (i=0; ioptions.tls1_3) { + if (XMEMCMP(ssl->session.sessionID, SessionCache[row].Sessions[i].sessionID, ID_LEN) == 0) { + WOLFSSL_MSG("Session already exists. Overwriting."); + overwrite = 1; + idx = i; + break; + } + } + else { + if (XMEMCMP(ssl->arrays->sessionID, SessionCache[row].Sessions[i].sessionID, ID_LEN) == 0) { + WOLFSSL_MSG("Session already exists. Overwriting."); + overwrite = 1; + idx = i; + break; + } + } + } + + if (!overwrite) { + idx = SessionCache[row].nextIdx++; + } +#ifdef SESSION_INDEX + ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; +#endif + session = &SessionCache[row].Sessions[idx]; + } + + 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; +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + if (ssl->options.tls1_3) { + XMEMCPY(session->sessionID, ssl->session.sessionID, ID_LEN); + session->sessionIDSz = ID_LEN; + } + else +#endif + { + XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN); + session->sessionIDSz = ssl->arrays->sessionIDSz; + } + +#ifdef OPENSSL_EXTRA + /* If using compatibility layer then check for and copy over session context + * id. */ + if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) { + XMEMCPY(session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz); + } +#endif + + session->timeout = ssl->timeout; + session->bornOn = LowResTimer(); #ifdef HAVE_SESSION_TICKET - SessionCache[row].Sessions[idx].ticketLen = ssl->session.ticketLen; - XMEMCPY(SessionCache[row].Sessions[idx].ticket, - ssl->session.ticket, ssl->session.ticketLen); + /* Check if another thread modified ticket since alloc */ + if ((word16)ticLen != ssl->session.ticketLen) { + error = VAR_STATE_CHANGE_E; + } + + if (error == 0) { + /* Cleanup cache row's old Dynamic buff if exists */ + 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) { + session->ticket = tmpBuff; + session->isDynamic = 1; + } else { + session->ticket = session->staticTicket; + session->isDynamic = 0; + } + + session->ticketLen = (word16)ticLen; + XMEMCPY(session->ticket, ssl->session.ticket, ticLen); + } else { /* cleanup, reset state */ + session->ticket = session->staticTicket; + session->isDynamic = 0; + session->ticketLen = 0; + if (tmpBuff) { + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + tmpBuff = NULL; + } + } #endif #ifdef SESSION_CERTS - 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; -#endif /* SESSION_CERTS */ - - SessionCache[row].totalCount++; - if (SessionCache[row].nextIdx == SESSIONS_PER_ROW) - SessionCache[row].nextIdx = 0; - -#ifndef NO_CLIENT_CACHE - if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->session.idLen) { - word32 clientRow, clientIdx; - - 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); - - 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 = (word16)row; - ClientCache[clientRow].Clients[clientIdx].serverIdx = (word16)idx; - - ClientCache[clientRow].totalCount++; - if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) - ClientCache[clientRow].nextIdx = 0; + if (error == 0) { + if (!overwrite || ssl->session.chain.count > 0) { + /* + * If we are overwriting and no certs present in ssl->session.chain + * then keep the old chain. + */ + session->chain.count = ssl->session.chain.count; + XMEMCPY(session->chain.certs, ssl->session.chain.certs, + sizeof(x509_buffer) * session->chain.count); } } - else - SessionCache[row].Sessions[idx].idLen = 0; +#endif /* SESSION_CERTS */ +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + if (error == 0) { + session->version = ssl->version; + } +#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & HAVE_SESSION_TICKET) */ +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + if (error == 0) { + session->cipherSuite0 = ssl->options.cipherSuite0; + session->cipherSuite = ssl->options.cipherSuite; + } +#endif +#if defined(WOLFSSL_TLS13) + if (error == 0) { + session->namedGroup = ssl->session.namedGroup; + } +#endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + if (error == 0) { + 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) { + if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->session.idLen) { + word32 clientRow, clientIdx; + + WOLFSSL_MSG("Adding client cache entry"); + + session->idLen = ssl->session.idLen; + XMEMCPY(session->serverID, ssl->session.serverID, + ssl->session.idLen); + +#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 = + (word16)row; + ClientCache[clientRow].Clients[clientIdx].serverIdx = + (word16)idx; + + ClientCache[clientRow].totalCount++; + if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) + ClientCache[clientRow].nextIdx = 0; + } + } + } + else + 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 (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; } @@ -6096,14 +12926,14 @@ 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"); row = idx >> SESSIDX_ROW_SHIFT; col = idx & SESSIDX_IDX_MASK; - if (LockMutex(&session_mutex) != 0) { + if (wc_LockMutex(&session_mutex) != 0) { return BAD_MUTEX_E; } @@ -6111,10 +12941,10 @@ 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 (UnLockMutex(&session_mutex) != 0) + if (wc_UnLockMutex(&session_mutex) != 0) result = BAD_MUTEX_E; WOLFSSL_LEAVE("wolfSSL_GetSessionAtIndex", result); @@ -6123,7 +12953,7 @@ int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session) #endif /* SESSION_INDEX */ -#if defined(SESSION_INDEX) && defined(SESSION_CERTS) +#if defined(SESSION_CERTS) WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) { @@ -6137,15 +12967,41 @@ WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) return chain; } + +#ifdef OPENSSL_EXTRA +/* gets the peer certificate associated with the session passed in + * returns null on failure, the caller should not free the returned pointer */ +WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); + if (session) { + int count; + + count = wolfSSL_get_chain_count(&session->chain); + if (count < 1 || count >= MAX_CHAIN_DEPTH) { + WOLFSSL_MSG("bad count found"); + return NULL; + } + + if (session->peer == NULL) { + session->peer = wolfSSL_get_chain_X509(&session->chain, 0); + } + return session->peer; + } + WOLFSSL_MSG("No session passed in"); + + return NULL; +} +#endif /* OPENSSL_EXTRA */ #endif /* SESSION_INDEX && SESSION_CERTS */ #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; @@ -6174,7 +13030,7 @@ static int get_locked_session_stats(word32* active, word32* total, word32* peak) break; } - /* if not expried then good */ + /* if not expired then good */ if (ticks < (SessionCache[i].Sessions[idx].bornOn + SessionCache[i].Sessions[idx].timeout) ) { now++; @@ -6199,11 +13055,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"); @@ -6218,13 +13074,13 @@ int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, if (active == NULL && total == NULL && peak == NULL) return BAD_FUNC_ARG; - if (LockMutex(&session_mutex) != 0) { + if (wc_LockMutex(&session_mutex) != 0) { return BAD_MUTEX_E; } result = get_locked_session_stats(active, total, peak); - if (UnLockMutex(&session_mutex) != 0) + if (wc_UnLockMutex(&session_mutex) != 0) result = BAD_MUTEX_E; WOLFSSL_LEAVE("wolfSSL_get_session_stats", result); @@ -6237,7 +13093,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; @@ -6251,7 +13107,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); @@ -6292,10 +13148,12 @@ int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, #else /* NO_SESSION_CACHE */ /* No session cache version */ -WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret) +WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, + byte restoreSessionCerts) { (void)ssl; (void)masterSecret; + (void)restoreSessionCerts; return NULL; } @@ -6305,30 +13163,38 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret) /* call before SSL_connect, if verifying will add name check to date check and signature check */ +WOLFSSL_ABI 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); - ssl->buffers.domainName.length = (word32)XSTRLEN(dn) + 1; - ssl->buffers.domainName.buffer = (byte*) XMALLOC( - ssl->buffers.domainName.length, ssl->heap, DYNAMIC_TYPE_DOMAIN); + ssl->buffers.domainName.length = (word32)XSTRLEN(dn); + ssl->buffers.domainName.buffer = (byte*)XMALLOC( + ssl->buffers.domainName.length + 1, ssl->heap, DYNAMIC_TYPE_DOMAIN); if (ssl->buffers.domainName.buffer) { - XSTRNCPY((char*)ssl->buffers.domainName.buffer, dn, - ssl->buffers.domainName.length); - return SSL_SUCCESS; + unsigned char* domainName = ssl->buffers.domainName.buffer; + XMEMCPY(domainName, dn, ssl->buffers.domainName.length); + domainName[ssl->buffers.domainName.length] = '\0'; + 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) { @@ -6336,7 +13202,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 @@ -6396,7 +13262,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) typedef struct itimerval Itimerval; - /* don't keep calling simple functions while setting up timer and singals + /* don't keep calling simple functions while setting up timer and signals if no inlining these are the next best */ #define AddTimes(a, b, c) \ @@ -6435,13 +13301,13 @@ int wolfSSL_set_compression(WOLFSSL* ssl) static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb, - TimeoutCallBack toCb, Timeval timeout) + TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FATAL_ERROR; int oldTimerOn = 0; /* was timer already on */ - Timeval startTime; - Timeval endTime; - Timeval totalTime; + WOLFSSL_TIMEVAL startTime; + WOLFSSL_TIMEVAL endTime; + WOLFSSL_TIMEVAL totalTime; Itimerval myTimeout; Itimerval oldTimeout; /* if old timer adjust from total time to reset */ struct sigaction act, oact; @@ -6450,7 +13316,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (hsCb) { ssl->hsInfoOn = 1; - InitHandShakeInfo(&ssl->handShakeInfo); + InitHandShakeInfo(&ssl->handShakeInfo, ssl); } if (toCb) { ssl->toInfoOn = 1; @@ -6538,7 +13404,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ssl->toInfoOn = 0; } if (hsCb) { - FinishHandShakeInfo(&ssl->handShakeInfo, ssl); + FinishHandShakeInfo(&ssl->handShakeInfo); (hsCb)(&ssl->handShakeInfo); ssl->hsInfoOn = 0; } @@ -6549,7 +13415,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifndef NO_WOLFSSL_CLIENT int wolfSSL_connect_ex(WOLFSSL* ssl, HandShakeCallBack hsCb, - TimeoutCallBack toCb, Timeval timeout) + TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout) { WOLFSSL_ENTER("wolfSSL_connect_ex"); return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout); @@ -6561,7 +13427,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifndef NO_WOLFSSL_SERVER int wolfSSL_accept_ex(WOLFSSL* ssl, HandShakeCallBack hsCb, - TimeoutCallBack toCb,Timeval timeout) + TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout) { WOLFSSL_ENTER("wolfSSL_accept_ex"); return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout); @@ -6575,56 +13441,77 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifndef NO_PSK void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx, - psk_client_callback cb) + wc_psk_client_callback cb) { WOLFSSL_ENTER("SSL_CTX_set_psk_client_callback"); + + if (ctx == NULL) + return; + ctx->havePSK = 1; ctx->client_psk_cb = cb; } - void wolfSSL_set_psk_client_callback(WOLFSSL* ssl, psk_client_callback cb) + 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"); + + if (ssl == NULL) + return; + ssl->options.havePSK = 1; ssl->options.client_psk_cb = cb; #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.haveStaticECC, - ssl->options.side); + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); } void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX* ctx, - psk_server_callback cb) + wc_psk_server_callback cb) { WOLFSSL_ENTER("SSL_CTX_set_psk_server_callback"); + if (ctx == NULL) + return; ctx->havePSK = 1; ctx->server_psk_cb = cb; } - void wolfSSL_set_psk_server_callback(WOLFSSL* ssl, psk_server_callback cb) + 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"); + if (ssl == NULL) + return; + ssl->options.havePSK = 1; ssl->options.server_psk_cb = cb; #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.haveStaticECC, - ssl->options.side); + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); } @@ -6654,12 +13541,16 @@ int wolfSSL_set_compression(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_CTX_use_psk_identity_hint"); if (hint == 0) - ctx->server_hint[0] = 0; + ctx->server_hint[0] = '\0'; else { + /* Qt does not call CTX_set_*_psk_callbacks where havePSK is set */ + #ifdef WOLFSSL_QT + ctx->havePSK=1; + #endif XSTRNCPY(ctx->server_hint, hint, MAX_PSK_ID_LEN); - ctx->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; + ctx->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -6668,15 +13559,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)-1); + ssl->arrays->server_hint[sizeof(ssl->arrays->server_hint)-1] = '\0'; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } #endif /* NO_PSK */ @@ -6689,11 +13581,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 */ @@ -6702,23 +13594,73 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifndef NO_CERTS /* used to be defined on NO_FILESYSTEM only, but are generally useful */ - /* wolfSSL extension allows DER files to be loaded from buffers as well */ - int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx, const unsigned char* in, - long sz, int format) + int wolfSSL_CTX_load_verify_buffer_ex(WOLFSSL_CTX* ctx, + const unsigned char* in, + long sz, int format, int userChain, + word32 flags) { - WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer"); - if (format == SSL_FILETYPE_PEM) - return ProcessChainBuffer(ctx, in, sz, format, CA_TYPE, NULL); + int verify; + + WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer_ex"); + + verify = GET_VERIFY_SETTING_CTX(ctx); + if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) + verify = VERIFY_SKIP_DATE; + + if (format == WOLFSSL_FILETYPE_PEM) + return ProcessChainBuffer(ctx, in, sz, format, CA_TYPE, NULL, + verify); else - return ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL,NULL,0); + return ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL, NULL, + userChain, verify); } + /* wolfSSL extension allows DER files to be loaded from buffers as well */ + int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx, + const unsigned char* in, + long sz, int format) + { + return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 0, + WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS); + } + + int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX* ctx, + const unsigned char* in, + long sz, int format) + { + return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 1, + WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS); + } + + +#ifdef WOLFSSL_TRUST_PEER_CERT + int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx, + const unsigned char* in, + long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer"); + + /* sanity check on arguments */ + if (sz < 0 || in == NULL || ctx == NULL) { + return BAD_FUNC_ARG; + } + + if (format == WOLFSSL_FILETYPE_PEM) + return ProcessChainBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, + NULL, GET_VERIFY_SETTING_CTX(ctx)); + else + return ProcessBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, NULL, + NULL, 0, GET_VERIFY_SETTING_CTX(ctx)); + } +#endif /* WOLFSSL_TRUST_PEER_CERT */ + int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx, const unsigned char* in, long sz, int format) { WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_buffer"); - return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0); + return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0, + GET_VERIFY_SETTING_CTX(ctx)); } @@ -6726,23 +13668,162 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const unsigned char* in, long sz, int format) { WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_buffer"); - return ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL,NULL,0); + return ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL, NULL, + 0, GET_VERIFY_SETTING_CTX(ctx)); } +#ifdef HAVE_PKCS11 + int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id, + long sz, int devId, long keySz) + { + int ret = WOLFSSL_FAILURE; + + FreeDer(&ctx->privateKey); + if (AllocDer(&ctx->privateKey, (word32)sz, PRIVATEKEY_TYPE, + ctx->heap) == 0) { + XMEMCPY(ctx->privateKey->buffer, id, sz); + ctx->privateKeyId = 1; + ctx->privateKeySz = (word32)keySz; + if (devId != INVALID_DEVID) + ctx->privateKeyDevId = devId; + else + ctx->privateKeyDevId = ctx->devId; + + ret = WOLFSSL_SUCCESS; + } + + return ret; + } +#endif + + int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx, + const unsigned char* in, long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer_format"); + return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 1, + GET_VERIFY_SETTING_CTX(ctx)); + } int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx, const unsigned char* in, long sz) { - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer"); - return ProcessBuffer(ctx, in, sz, SSL_FILETYPE_PEM, CERT_TYPE, NULL, - NULL, 1); + return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz, + WOLFSSL_FILETYPE_PEM); } + +#ifndef NO_DH + + /* server wrapper for ctx or ssl Diffie-Hellman parameters */ + static int wolfSSL_SetTmpDH_buffer_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + const unsigned char* buf, + long sz, int format) + { + DerBuffer* der = NULL; + int ret = 0; + word32 pSz = MAX_DH_SIZE; + word32 gSz = MAX_DH_SIZE; + #ifdef WOLFSSL_SMALL_STACK + byte* p = NULL; + byte* g = NULL; + #else + byte p[MAX_DH_SIZE]; + byte g[MAX_DH_SIZE]; + #endif + + if (ctx == NULL || buf == NULL) + return BAD_FUNC_ARG; + + ret = AllocDer(&der, 0, DH_PARAM_TYPE, ctx->heap); + if (ret != 0) { + return ret; + } + der->buffer = (byte*)buf; + der->length = (word32)sz; + + #ifdef WOLFSSL_SMALL_STACK + 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_PUBLIC_KEY); + XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + return MEMORY_E; + } + #endif + + if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM) + ret = WOLFSSL_BAD_FILETYPE; + else { + if (format == WOLFSSL_FILETYPE_PEM) { +#ifdef WOLFSSL_PEM_TO_DER + 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 /* WOLFSSL_WPAS */ +#else + ret = NOT_COMPILED_IN; +#endif /* WOLFSSL_PEM_TO_DER */ + } + + if (ret == 0) { + if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0) + ret = WOLFSSL_BAD_FILETYPE; + else if (ssl) + ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz); + else + ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz); + } + } + + FreeDer(&der); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + #endif + + return ret; + } + + + /* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ + int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz, + int format) + { + if (ssl == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format); + } + + + /* 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) + { + return wolfSSL_SetTmpDH_buffer_wrapper(ctx, NULL, buf, sz, format); + } + +#endif /* NO_DH */ + + int wolfSSL_use_certificate_buffer(WOLFSSL* ssl, const unsigned char* in, long sz, int format) { WOLFSSL_ENTER("wolfSSL_use_certificate_buffer"); - return ProcessBuffer(ssl->ctx, in, sz, format,CERT_TYPE,ssl,NULL,0); + if (ssl == NULL) + return BAD_FUNC_ARG; + + return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 0, + GET_VERIFY_SETTING_SSL(ssl)); } @@ -6750,22 +13831,60 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const unsigned char* in, long sz, int format) { WOLFSSL_ENTER("wolfSSL_use_PrivateKey_buffer"); + if (ssl == NULL) + return BAD_FUNC_ARG; + return ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE, - ssl, NULL, 0); + ssl, NULL, 0, GET_VERIFY_SETTING_SSL(ssl)); } +#ifdef HAVE_PKCS11 + int wolfSSL_use_PrivateKey_id(WOLFSSL* ssl, const unsigned char* id, + long sz, int devId, long keySz) + { + int ret = WOLFSSL_FAILURE; + + if (ssl->buffers.weOwnKey) + FreeDer(&ssl->buffers.key); + if (AllocDer(&ssl->buffers.key, (word32)sz, PRIVATEKEY_TYPE, + ssl->heap) == 0) { + XMEMCPY(ssl->buffers.key->buffer, id, sz); + ssl->buffers.weOwnKey = 1; + ssl->buffers.keyId = 1; + ssl->buffers.keySz = (word32)keySz; + if (devId != INVALID_DEVID) + ssl->buffers.keyDevId = devId; + else + ssl->buffers.keyDevId = ssl->devId; + + ret = WOLFSSL_SUCCESS; + } + + return ret; + } +#endif + + int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL* ssl, + const unsigned char* in, long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format"); + if (ssl == NULL) + return BAD_FUNC_ARG; + + return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, + ssl, NULL, 1, GET_VERIFY_SETTING_SSL(ssl)); + } int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl, const unsigned char* in, long sz) { - WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer"); - return ProcessBuffer(ssl->ctx, in, sz, SSL_FILETYPE_PEM, CERT_TYPE, - ssl, NULL, 1); + return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz, + 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) { @@ -6773,31 +13892,32 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return BAD_FUNC_ARG; } - if (ssl->buffers.weOwnCert) { + if (ssl->buffers.weOwnCert && !ssl->keepCert) { WOLFSSL_MSG("Unloading cert"); - XFREE(ssl->buffers.certificate.buffer, ssl->heap,DYNAMIC_TYPE_CERT); + FreeDer(&ssl->buffers.certificate); + #ifdef KEEP_OUR_CERT + FreeX509(ssl->ourCert); + if (ssl->ourCert) { + XFREE(ssl->ourCert, ssl->heap, DYNAMIC_TYPE_X509); + ssl->ourCert = NULL; + } + #endif ssl->buffers.weOwnCert = 0; - ssl->buffers.certificate.length = 0; - ssl->buffers.certificate.buffer = NULL; } if (ssl->buffers.weOwnCertChain) { WOLFSSL_MSG("Unloading cert chain"); - XFREE(ssl->buffers.certChain.buffer, ssl->heap,DYNAMIC_TYPE_CERT); + FreeDer(&ssl->buffers.certChain); ssl->buffers.weOwnCertChain = 0; - ssl->buffers.certChain.length = 0; - ssl->buffers.certChain.buffer = NULL; } if (ssl->buffers.weOwnKey) { WOLFSSL_MSG("Unloading key"); - XFREE(ssl->buffers.key.buffer, ssl->heap, DYNAMIC_TYPE_KEY); + FreeDer(&ssl->buffers.key); ssl->buffers.weOwnKey = 0; - ssl->buffers.key.length = 0; - ssl->buffers.key.buffer = NULL; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -6811,30 +13931,74 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return wolfSSL_CertManagerUnloadCAs(ctx->cm); } + +#ifdef WOLFSSL_TRUST_PEER_CERT + int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_CertManagerUnload_trust_peers(ctx->cm); + } +#endif /* WOLFSSL_TRUST_PEER_CERT */ /* old NO_FILESYSTEM end */ #endif /* !NO_CERTS */ -#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS) - +#ifdef OPENSSL_EXTRA int wolfSSL_add_all_algorithms(void) { WOLFSSL_ENTER("wolfSSL_add_all_algorithms"); - wolfSSL_Init(); - return SSL_SUCCESS; + if (wolfSSL_Init() == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + else + return WOLFSSL_FATAL_ERROR; } + int wolfSSL_OpenSSL_add_all_algorithms_noconf(void) + { + WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_noconf"); + if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) + return WOLFSSL_FATAL_ERROR; + + return WOLFSSL_SUCCESS; + } + + int wolfSSL_OpenSSL_add_all_algorithms_conf(void) + { + WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_conf"); + /* This function is currently the same as + wolfSSL_OpenSSL_add_all_algorithms_noconf since we do not employ + the use of a wolfssl.cnf type configuration file and is only used for + OpenSSL compatability. */ + + if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) { + return WOLFSSL_FATAL_ERROR; + } + return WOLFSSL_SUCCESS; + } + + /* returns previous set cache size which stays constant */ long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX* ctx, long sz) { /* cache size fixed at compile time in wolfSSL */ (void)ctx; (void)sz; - return 0; + WOLFSSL_MSG("session cache is set at compile time"); + #ifndef NO_SESSION_CACHE + return (long)(SESSIONS_PER_ROW * SESSION_ROWS); + #else + return 0; + #endif } +#endif +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX* ctx, int mode) { WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown"); @@ -6849,60 +14013,457 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (mode) ssl->options.quietShutdown = 1; } +#endif - +#ifdef OPENSSL_EXTRA void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr) { - WOLFSSL_ENTER("SSL_set_bio"); - wolfSSL_set_rfd(ssl, rd->fd); - wolfSSL_set_wfd(ssl, wr->fd); + WOLFSSL_ENTER("wolfSSL_set_bio"); + + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument, ssl was NULL"); + return; + } + + /* if WOLFSSL_BIO is socket type then set WOLFSSL socket to use */ + if (rd != NULL && rd->type == WOLFSSL_BIO_SOCKET) { + wolfSSL_set_rfd(ssl, rd->num); + } + if (wr != NULL && wr->type == WOLFSSL_BIO_SOCKET) { + wolfSSL_set_wfd(ssl, wr->num); + } + + /* free any existing WOLFSSL_BIOs in use */ + if (ssl->biord != NULL) { + if (ssl->biord != ssl->biowr) { + if (ssl->biowr != NULL) { + wolfSSL_BIO_free(ssl->biowr); + ssl->biowr = NULL; + } + } + wolfSSL_BIO_free(ssl->biord); + ssl->biord = NULL; + } + ssl->biord = rd; ssl->biowr = wr; + + /* set SSL to use BIO callbacks instead */ + if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0) && + (rd != NULL && rd->type != WOLFSSL_BIO_SOCKET)) { + ssl->CBIORecv = BioReceive; + } + if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0) && + (wr != NULL && wr->type != WOLFSSL_BIO_SOCKET)) { + ssl->CBIOSend = BioSend; + } + + /* User programs should always retry reading from these BIOs */ + if (rd) { + /* User writes to rd */ + BIO_set_retry_write(rd); + } + if (wr) { + /* User reads from wr */ + BIO_set_retry_read(wr); + } } +#endif - +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_WEBSERVER) void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, - STACK_OF(WOLFSSL_X509_NAME)* names) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) { + WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list"); + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) + if (ctx != NULL) + ctx->ca_names = names; + #else (void)ctx; (void)names; + #endif } - STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) + /* returns the CA's set on server side or the CA's sent from server when + * on client side */ +#if defined(SESSION_CERTS) && defined(OPENSSL_ALL) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list( + const WOLFSSL* ssl) { - (void)fname; - return 0; + WOLFSSL_ENTER("wolfSSL_get_client_CA_list"); + + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list"); + return NULL; + } + + /* return list of CAs sent from the server */ + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLF_STACK_OF(WOLFSSL_X509)* sk; + + sk = wolfSSL_get_peer_cert_chain(ssl); + if (sk != NULL) { + WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret; + WOLFSSL_X509* x509; + + ret = wolfSSL_sk_X509_NAME_new(NULL); + do { + x509 = wolfSSL_sk_X509_pop(sk); + if (x509 != NULL) { + if (wolfSSL_X509_get_isCA(x509)) { + if (wolfSSL_sk_X509_NAME_push(ret, + wolfSSL_X509_get_subject_name(x509)) != 0) { + WOLFSSL_MSG("Error pushing X509 name to stack"); + /* continue on to try other certificates and + * do not fail out here */ + } + } + wolfSSL_X509_free(x509); + } + } while (x509 != NULL); + wolfSSL_sk_X509_free(sk); + return ret; + } + return NULL; + } + else { + /* currently only can be set in the CTX */ + return ssl->ctx->ca_names; + } } +#endif /* SESSION_CERTS */ + #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ + defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) + /* registers client cert callback, called during handshake if server + requests client auth but user has not loaded client cert/key */ + void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb cb) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_client_cert_cb"); + + if (ctx != NULL) { + ctx->CBClientCert = cb; + } + } + #endif /* OPENSSL_ALL || OPENSSL_EXTRA || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || HAVE_WEBSERVER */ + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *s) + { + WOLFSSL_ENTER("wolfSSL_CTX_get_client_CA_list"); + + if (s == NULL) + return NULL; + + return s->ca_names; + } +#endif + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + #if !defined(NO_RSA) && !defined(NO_CERTS) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) + { + /* The webserver build is using this to load a CA into the server + * for client authentication as an option. Have this return NULL in + * that case. If OPENSSL_EXTRA is enabled, go ahead and include + * the function. */ + #ifdef OPENSSL_EXTRA + WOLFSSL_STACK *list = NULL; + WOLFSSL_STACK *node; + WOLFSSL_BIO* bio; + WOLFSSL_X509 *cert = NULL; + WOLFSSL_X509_NAME *subjectName = NULL; + unsigned long err; + + 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_sk_new_node(NULL); + if (node == NULL) + break; + node->type = STACK_TYPE_X509_NAME; + + /* Need a persistent copy of the subject name. */ + node->data.name = wolfSSL_X509_NAME_dup(subjectName); + /* + * Original cert will be freed so make sure not to try to access + * it in the future. + */ + node->data.name->x509 = NULL; + + /* 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; + } + + err = wolfSSL_ERR_peek_last_error(); + + if (ERR_GET_LIB(err) == ERR_LIB_PEM && + ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { + /* + * wolfSSL_PEM_read_bio_X509 pushes an ASN_NO_PEM_HEADER error + * to the error queue on file end. This should not be left + * for the caller to find so we clear the last error. + */ + wc_RemoveErrorNode(-1); + } + + wolfSSL_X509_free(cert); + wolfSSL_BIO_free(bio); + return list; + #else + (void)fname; + return NULL; + #endif + } + #endif +#endif + +#ifdef OPENSSL_EXTRA + #if !defined(NO_RSA) && !defined(NO_CERTS) + 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 + + #ifndef NO_WOLFSSL_STUB int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx) { /* TODO:, not needed in goahead */ (void)ctx; + WOLFSSL_STUB("SSL_CTX_set_default_verify_paths"); return SSL_NOT_IMPLEMENTED; } + #endif + #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; @@ -6912,31 +14473,48 @@ int wolfSSL_set_compression(WOLFSSL* ssl) *srLen = RAN_LEN; *crLen = RAN_LEN; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } +#endif /* OPENSSL_EXTRA */ +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) void wolfSSL_set_accept_state(WOLFSSL* ssl) { - byte haveRSA = 1; - byte havePSK = 0; + WOLFSSL_ENTER("wolfSSL_set_accept_state"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef HAVE_ECC + ecc_key key; + word32 idx = 0; - WOLFSSL_ENTER("SSL_set_accept_state"); - ssl->options.side = WOLFSSL_SERVER_END; - /* reset suites in case user switched */ + if (ssl->options.haveStaticECC && ssl->buffers.key != NULL) { + if (wc_ecc_init(&key) >= 0) { + 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 - #ifdef NO_RSA - haveRSA = 0; - #endif - #ifndef NO_PSK - havePSK = ssl->options.havePSK; - #endif - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, - ssl->options.haveDH, ssl->options.haveNTRU, - ssl->options.haveECDSAsig, ssl->options.haveStaticECC, - ssl->options.side); + #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 + } + + if (InitSSL_Side(ssl, WOLFSSL_SERVER_END) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error initializing server side"); + } } -#endif + +#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */ /* return true if connection established */ int wolfSSL_is_init_finished(WOLFSSL* ssl) @@ -6950,7 +14528,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return 0; } -#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS) +#ifdef OPENSSL_EXTRA + void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX* ctx, WOLFSSL_RSA*(*f)(WOLFSSL*, int, int)) { @@ -6962,19 +14541,55 @@ int wolfSSL_set_compression(WOLFSSL* ssl) void wolfSSL_set_shutdown(WOLFSSL* ssl, int opt) { - (void)ssl; - (void)opt; + WOLFSSL_ENTER("wolfSSL_set_shutdown"); + if(ssl==NULL) { + WOLFSSL_MSG("Shutdown not set. ssl is null"); + return; + } + + ssl->options.sentNotify = (opt&WOLFSSL_SENT_SHUTDOWN) > 0; + ssl->options.closeNotify = (opt&WOLFSSL_RECEIVED_SHUTDOWN) > 0; } + long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_get_options"); + WOLFSSL_MSG("wolfSSL options are set through API calls and macros"); + if(ctx == NULL) + return BAD_FUNC_ARG; + return ctx->mask; + } + +#endif + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + + static long wolf_set_options(long old_op, long op); long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt) { - /* goahead calls with 0, do nothing */ WOLFSSL_ENTER("SSL_CTX_set_options"); - (void)ctx; - return opt; + + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->mask = wolf_set_options(ctx->mask, opt); + + return ctx->mask; } +#endif + +#ifdef OPENSSL_EXTRA + + long wolfSSL_CTX_clear_options(WOLFSSL_CTX* ctx, long opt) + { + WOLFSSL_ENTER("SSL_CTX_clear_options"); + if(ctx == NULL) + return BAD_FUNC_ARG; + ctx->mask &= ~opt; + return ctx->mask; + } int wolfSSL_set_rfd(WOLFSSL* ssl, int rfd) { @@ -6983,7 +14598,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ssl->IOCB_ReadCtx = &ssl->rfd; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } @@ -6994,34 +14609,57 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ssl->IOCB_WriteCtx = &ssl->wfd; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } +#ifndef NO_CERTS - WOLFSSL_RSA* wolfSSL_RSA_generate_key(int len, unsigned long bits, - void(*f)(int, int, void*), void* data) + WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx) { - /* no tmp key needed, actual generation not supported */ - WOLFSSL_ENTER("RSA_generate_key"); - (void)len; - (void)bits; - (void)f; - (void)data; - return NULL; + if (ctx == NULL) { + return NULL; + } + + return &ctx->x509_store; } + void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str) + { + if (ctx == NULL || str == NULL) { + return; + } + + /* free cert manager if have one */ + if (ctx->cm != NULL) { + wolfSSL_CertManagerFree(ctx->cm); + } + ctx->cm = str->cm; + + /* free existing store if it exists */ + if (ctx->x509_store_pt != NULL) { + /* cert manager was free'd a little earlier in this function */ + ctx->x509_store_pt->cm = NULL; + } + wolfSSL_X509_STORE_free(ctx->x509_store_pt); + ctx->x509_store.cache = str->cache; + ctx->x509_store_pt = str; /* take ownership of store and free it + with CTX free */ + } WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert( - WOLFSSL_X509_STORE_CTX* ctx) + WOLFSSL_X509_STORE_CTX* ctx) { - (void)ctx; - return 0; + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_current_cert"); + if (ctx) + return ctx->current_cert; + return NULL; } int wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX* ctx) { + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error"); if (ctx != NULL) return ctx->error; return 0; @@ -7030,37 +14668,120 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX* ctx) { - (void)ctx; - return 0; + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error_depth"); + if(ctx) + return ctx->error_depth; + return WOLFSSL_FATAL_ERROR; } + void wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx, + WOLFSSL_X509_STORE_CTX_verify_cb verify_cb) + { + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_verify_cb"); + if(ctx == NULL) + return; + ctx->verify_cb = verify_cb; + } + +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + void wolfSSL_X509_STORE_set_verify_cb(WOLFSSL_X509_STORE *st, + WOLFSSL_X509_STORE_CTX_verify_cb verify_cb) + { + WOLFSSL_ENTER("WOLFSSL_X509_STORE_set_verify_cb"); + if (st != NULL) { + st->verify_cb = verify_cb; + } + } +#endif + + +#endif /* !NO_CERTS */ + + WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_md(void) + { + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("wolfSSL_BIO_f_md"); + meth.type = WOLFSSL_BIO_MD; + + return &meth; + } + + /* return the context and initialize the BIO state */ + int wolfSSL_BIO_get_md_ctx(WOLFSSL_BIO *bio, WOLFSSL_EVP_MD_CTX **mdcp) + { + int ret = WOLFSSL_FAILURE; + + if ((bio != NULL) && (mdcp != NULL)) { + *mdcp = (WOLFSSL_EVP_MD_CTX*)bio->ptr; + ret = WOLFSSL_SUCCESS; + } + + return ret; + } WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void) { static WOLFSSL_BIO_METHOD meth; WOLFSSL_ENTER("BIO_f_buffer"); - meth.type = BIO_BUFFER; + meth.type = WOLFSSL_BIO_BUFFER; return &meth; } - + #ifndef NO_WOLFSSL_STUB long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO* bio, long size) { /* wolfSSL has internal buffer, compatibility only */ WOLFSSL_ENTER("BIO_set_write_buffer_size"); + WOLFSSL_STUB("BIO_set_write_buffer_size"); (void)bio; return size; } + #endif + + WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_bio(void) + { + static WOLFSSL_BIO_METHOD bio_meth; + + WOLFSSL_ENTER("wolfSSL_BIO_s_bio"); + bio_meth.type = WOLFSSL_BIO_BIO; + + return &bio_meth; + } + + +#ifndef NO_FILESYSTEM + WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void) + { + static WOLFSSL_BIO_METHOD file_meth; + + WOLFSSL_ENTER("wolfSSL_BIO_s_file"); + file_meth.type = WOLFSSL_BIO_FILE; + + return &file_meth; + } +#endif WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void) { static WOLFSSL_BIO_METHOD meth; - WOLFSSL_ENTER("BIO_f_ssl"); - meth.type = BIO_SSL; + WOLFSSL_ENTER("wolfSSL_BIO_f_ssl"); + meth.type = WOLFSSL_BIO_SSL; + + return &meth; + } + + + WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void) + { + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("wolfSSL_BIO_s_socket"); + meth.type = WOLFSSL_BIO_SOCKET; return &meth; } @@ -7068,20 +14789,13 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_BIO* wolfSSL_BIO_new_socket(int sfd, int closeF) { - WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0, - DYNAMIC_TYPE_OPENSSL); + WOLFSSL_BIO* bio = wolfSSL_BIO_new(wolfSSL_BIO_s_socket()); WOLFSSL_ENTER("BIO_new_socket"); if (bio) { - bio->type = BIO_SOCKET; - bio->close = (byte)closeF; - bio->eof = 0; - bio->ssl = 0; - bio->fd = sfd; - bio->prev = 0; - bio->next = 0; - bio->mem = NULL; - bio->memLen = 0; + bio->type = WOLFSSL_BIO_SOCKET; + bio->shutdown = (byte)closeF; + bio->num = sfd; } return bio; } @@ -7090,7 +14804,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int wolfSSL_BIO_eof(WOLFSSL_BIO* b) { WOLFSSL_ENTER("BIO_eof"); - if (b->eof) + if ((b != NULL) && (b->eof)) return 1; return 0; @@ -7099,94 +14813,200 @@ int wolfSSL_set_compression(WOLFSSL* ssl) long wolfSSL_BIO_set_ssl(WOLFSSL_BIO* b, WOLFSSL* ssl, int closeF) { - WOLFSSL_ENTER("BIO_set_ssl"); - b->ssl = ssl; - b->close = (byte)closeF; + WOLFSSL_ENTER("wolfSSL_BIO_set_ssl"); + + if (b != NULL) { + b->ptr = ssl; + b->shutdown = (byte)closeF; /* add to ssl for bio free if SSL_free called before/instead of free_all? */ + } return 0; } +#ifndef NO_FILESYSTEM + long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int closeF) + { + WOLFSSL_ENTER("wolfSSL_BIO_set_fd"); + + if (b != NULL) { + b->num = fd; + b->shutdown = (byte)closeF; + } + + return WOLFSSL_SUCCESS; + } +#endif + + /* Sets the close flag */ + int wolfSSL_BIO_set_close(WOLFSSL_BIO *b, long flag) + { + WOLFSSL_ENTER("wolfSSL_BIO_set_close"); + if (b != NULL) { + b->shutdown = (byte)flag; + } + + return WOLFSSL_SUCCESS; + } + WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD* method) { - WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0, - DYNAMIC_TYPE_OPENSSL); - WOLFSSL_ENTER("BIO_new"); - if (bio) { - bio->type = method->type; - bio->close = 0; - bio->eof = 0; - bio->ssl = NULL; - bio->mem = NULL; - bio->memLen = 0; - bio->fd = 0; - bio->prev = NULL; - bio->next = NULL; - } - return bio; - } + WOLFSSL_BIO* bio; - - int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, const byte** p) - { - if (bio == NULL || p == NULL) - return SSL_FATAL_ERROR; - - *p = bio->mem; - - return bio->memLen; - } - - - WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len) - { - WOLFSSL_BIO* bio = NULL; - if (buf == NULL) - return bio; - - bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); - if (bio == NULL) - return bio; - - bio->memLen = len; - bio->mem = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL); - if (bio->mem == NULL) { - XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL); + WOLFSSL_ENTER("wolfSSL_BIO_new"); + if (method == NULL) { + WOLFSSL_MSG("Bad method pointer passed in"); return NULL; } - XMEMCPY(bio->mem, buf, len); + bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0, + DYNAMIC_TYPE_OPENSSL); + if (bio) { + XMEMSET(bio, 0, sizeof(WOLFSSL_BIO)); + bio->type = (byte)method->type; + bio->method = method; + bio->shutdown = BIO_CLOSE; /* default to close things */ + bio->init = 1; + if (method->type != WOLFSSL_BIO_FILE && + method->type != WOLFSSL_BIO_SOCKET && + method->type != WOLFSSL_BIO_MD) { + bio->mem_buf =(WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM), + 0, DYNAMIC_TYPE_OPENSSL); + if (bio->mem_buf == NULL) { + WOLFSSL_MSG("Memory error"); + wolfSSL_BIO_free(bio); + return NULL; + } + bio->mem_buf->data = (char*)bio->ptr; + } + + if (method->type == WOLFSSL_BIO_MD) { + bio->ptr = wolfSSL_EVP_MD_CTX_new(); + if (bio->ptr == NULL) { + WOLFSSL_MSG("Memory error"); + wolfSSL_BIO_free(bio); + return NULL; + } + } + + /* check if is custom method */ + if (method->createCb) { + method->createCb(bio); + } + } + return bio; + } + + WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(const void* buf, int len) + { + WOLFSSL_BIO* bio = NULL; + + if (buf == NULL || len < 0) { + return bio; + } + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); + if (bio == NULL) { + return bio; + } + + bio->num = bio->wrSz = len; + bio->ptr = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL); + if (bio->ptr == NULL) { + wolfSSL_BIO_free(bio); + return NULL; + } + if (bio->mem_buf != NULL) { + bio->mem_buf->data = (char*)bio->ptr; + bio->mem_buf->length = bio->num; + } + + XMEMCPY(bio->ptr, buf, len); return bio; } - -#ifdef USE_WINDOWS_API - #define CloseSocket(s) closesocket(s) -#elif defined(WOLFSSL_MDK_ARM) - #define CloseSocket(s) closesocket(s) - extern int closesocket(int) ; -#else - #define CloseSocket(s) close(s) -#endif - + /* + * Note : If the flag BIO_NOCLOSE is set then freeing memory buffers is up + * to the application. + * Returns 1 on success, 0 on failure + */ int wolfSSL_BIO_free(WOLFSSL_BIO* bio) { + int ret; + /* unchain?, doesn't matter in goahead since from free all */ - WOLFSSL_ENTER("BIO_free"); + WOLFSSL_ENTER("wolfSSL_BIO_free"); if (bio) { - if (bio->close) { - if (bio->ssl) - wolfSSL_free(bio->ssl); - if (bio->fd) - CloseSocket(bio->fd); + + if (bio->infoCb) { + /* info callback is called before free */ + ret = (int)bio->infoCb(bio, WOLFSSL_BIO_CB_FREE, NULL, 0, 0, 1); + if (ret <= 0) { + return ret; + } } - if (bio->mem) - XFREE(bio->mem, 0, DYNAMIC_TYPE_OPENSSL); + + /* call custom set free callback */ + if (bio->method && bio->method->freeCb) { + bio->method->freeCb(bio); + } + + /* remove from pair by setting the paired bios pair to NULL */ + if (bio->pair != NULL) { + bio->pair->pair = NULL; + } + + if (bio->shutdown) { + if (bio->type == WOLFSSL_BIO_SSL && bio->ptr) + wolfSSL_free((WOLFSSL*)bio->ptr); + #ifdef CloseSocket + if (bio->type == WOLFSSL_BIO_SOCKET && bio->num) + CloseSocket(bio->num); + #endif + } + + #ifndef NO_FILESYSTEM + if (bio->type == WOLFSSL_BIO_FILE && bio->shutdown == BIO_CLOSE) { + if (bio->ptr) { + XFCLOSE((XFILE)bio->ptr); + } + } + #endif + + if (bio->shutdown != BIO_NOCLOSE) { + if (bio->type == WOLFSSL_BIO_MEMORY && bio->ptr != NULL) { + if (bio->mem_buf != NULL) { + if (bio->mem_buf->data != (char*)bio->ptr) { + XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->ptr = NULL; + } + } + else { + XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->ptr = NULL; + } + } + if (bio->mem_buf != NULL) { + wolfSSL_BUF_MEM_free(bio->mem_buf); + bio->mem_buf = NULL; + } + } + + if (bio->type == WOLFSSL_BIO_MD) { + wolfSSL_EVP_MD_CTX_free((WOLFSSL_EVP_MD_CTX*)bio->ptr); + } + XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL); } - return 0; + return 1; + } + + /* like BIO_free, but no return value */ + void wolfSSL_BIO_vfree(WOLFSSL_BIO* bio) + { + wolfSSL_BIO_free(bio); } @@ -7202,63 +15022,6 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) - { - int ret; - WOLFSSL* ssl = 0; - WOLFSSL_BIO* front = bio; - - WOLFSSL_ENTER("BIO_read"); - /* already got eof, again is error */ - if (front->eof) - return SSL_FATAL_ERROR; - - while(bio && ((ssl = bio->ssl) == 0) ) - bio = bio->next; - - if (ssl == 0) return BAD_FUNC_ARG; - - ret = wolfSSL_read(ssl, buf, len); - if (ret == 0) - 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) ) - front->eof = 1; - } - return ret; - } - - - int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) - { - int ret; - WOLFSSL* ssl = 0; - WOLFSSL_BIO* front = bio; - - WOLFSSL_ENTER("BIO_write"); - /* already got eof, again is error */ - if (front->eof) - return SSL_FATAL_ERROR; - - while(bio && ((ssl = bio->ssl) == 0) ) - bio = bio->next; - - if (ssl == 0) return BAD_FUNC_ARG; - - ret = wolfSSL_write(ssl, data, len); - if (ret == 0) - 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) ) - front->eof = 1; - } - - return ret; - } - - WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO* top, WOLFSSL_BIO* append) { WOLFSSL_ENTER("BIO_push"); @@ -7267,36 +15030,49 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return top; } +#endif /* OPENSSL_EXTRA */ - - int wolfSSL_BIO_flush(WOLFSSL_BIO* bio) - { - /* for wolfSSL no flushing needed */ - WOLFSSL_ENTER("BIO_flush"); - (void)bio; - return 1; - } - - -#endif /* OPENSSL_EXTRA || GOAHEAD_WS */ - - -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +#ifdef WOLFSSL_ENCRYPTED_KEYS void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx, void* userdata) { WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb_userdata"); - ctx->userdata = userdata; + if (ctx) + ctx->passwd_userdata = userdata; } - 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"); - ctx->passwd_cb = cb; + if (ctx) + ctx->passwd_cb = cb; } + pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx) + { + if (ctx == NULL || ctx->passwd_cb == NULL) { + return NULL; + } + + return ctx->passwd_cb; + } + + + void* wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx) + { + if (ctx == NULL) { + return NULL; + } + + return ctx->passwd_userdata; + } + +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) int wolfSSL_num_locks(void) { return 0; @@ -7304,136 +15080,299 @@ int wolfSSL_set_compression(WOLFSSL* ssl) void wolfSSL_set_locking_callback(void (*f)(int, int, const char*, int)) { - (void)f; + WOLFSSL_ENTER("wolfSSL_set_locking_callback"); + + if (wc_SetMutexCb(f) != 0) { + WOLFSSL_MSG("Error when setting mutex call back"); + } } + + typedef unsigned long (idCb)(void); + static idCb* inner_idCb = NULL; + + unsigned long wolfSSL_thread_id(void) + { + if (inner_idCb != NULL) { + return inner_idCb(); + } + else { + return 0; + } + } + + void wolfSSL_set_id_callback(unsigned long (*f)(void)) { - (void)f; + inner_idCb = f; } unsigned long wolfSSL_ERR_get_error(void) { - /* TODO: */ - return 0; + WOLFSSL_ENTER("wolfSSL_ERR_get_error"); + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + { + unsigned long ret = wolfSSL_ERR_peek_error_line_data(NULL, NULL, + NULL, NULL); + wc_RemoveErrorNode(-1); + return ret; + } +#elif (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)) + { + int ret = wc_PullErrorNode(NULL, NULL, NULL); + + if (ret < 0) { + if (ret == BAD_STATE_E) return 0; /* no errors in queue */ + WOLFSSL_MSG("Error with pulling error node!"); + WOLFSSL_LEAVE("wolfSSL_ERR_get_error", ret); + ret = 0 - ret; /* return absolute value of error */ + + /* panic and try to clear out nodes */ + wc_ClearErrorNodes(); + } + + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif } -#ifndef NO_MD5 - - int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER* type, - const WOLFSSL_EVP_MD* md, const byte* salt, - const byte* data, int sz, int count, byte* key, byte* iv) +#if (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)) + /* print out and clear all errors */ + void wolfSSL_ERR_print_errors(WOLFSSL_BIO* bio) { - int keyLen = 0; - int ivLen = 0; - int j; - int keyLeft; - int ivLeft; - int keyOutput = 0; - byte digest[MD5_DIGEST_SIZE]; - #ifdef WOLFSSL_SMALL_STACK - Md5* md5 = NULL; - #else - Md5 md5[1]; - #endif + const char* file = NULL; + const char* reason = NULL; + int ret; + int line = 0; + char buf[WOLFSSL_MAX_ERROR_SZ * 2]; - #ifdef WOLFSSL_SMALL_STACK - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (md5 == NULL) - return 0; - #endif + WOLFSSL_ENTER("wolfSSL_ERR_print_errors"); - WOLFSSL_ENTER("EVP_BytesToKey"); - wc_InitMd5(md5); - - /* only support MD5 for now */ - if (XSTRNCMP(md, "MD5", 3) != 0) return 0; - - /* only support CBC DES and AES for now */ - if (XSTRNCMP(type, "DES-CBC", 7) == 0) { - keyLen = DES_KEY_SIZE; - ivLen = DES_IV_SIZE; - } - else if (XSTRNCMP(type, "DES-EDE3-CBC", 12) == 0) { - keyLen = DES3_KEY_SIZE; - ivLen = DES_IV_SIZE; - } - else if (XSTRNCMP(type, "AES-128-CBC", 11) == 0) { - keyLen = AES_128_KEY_SIZE; - ivLen = AES_IV_SIZE; - } - else if (XSTRNCMP(type, "AES-192-CBC", 11) == 0) { - keyLen = AES_192_KEY_SIZE; - ivLen = AES_IV_SIZE; - } - else if (XSTRNCMP(type, "AES-256-CBC", 11) == 0) { - keyLen = AES_256_KEY_SIZE; - ivLen = AES_IV_SIZE; - } - else { - #ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return 0; + if (bio == NULL) { + WOLFSSL_MSG("BIO passed in was null"); + return; } - keyLeft = keyLen; - ivLeft = ivLen; - - while (keyOutput < (keyLen + ivLen)) { - int digestLeft = MD5_DIGEST_SIZE; - /* D_(i - 1) */ - if (keyOutput) /* first time D_0 is empty */ - wc_Md5Update(md5, digest, MD5_DIGEST_SIZE); - /* data */ - wc_Md5Update(md5, data, sz); - /* salt */ - if (salt) - wc_Md5Update(md5, salt, EVP_SALT_SIZE); - wc_Md5Final(md5, digest); - /* count */ - for (j = 1; j < count; j++) { - wc_Md5Update(md5, digest, MD5_DIGEST_SIZE); - wc_Md5Final(md5, digest); - } - - if (keyLeft) { - int store = min(keyLeft, MD5_DIGEST_SIZE); - XMEMCPY(&key[keyLen - keyLeft], digest, store); - - keyOutput += store; - keyLeft -= store; - digestLeft -= store; - } - - if (ivLeft && digestLeft) { - int store = min(ivLeft, digestLeft); - XMEMCPY(&iv[ivLen - ivLeft], &digest[MD5_DIGEST_SIZE - - digestLeft], store); - keyOutput += store; - ivLeft -= store; - } + do { + ret = wc_PeekErrorNode(0, &file, &reason, &line); + if (ret >= 0) { + const char* r = wolfSSL_ERR_reason_error_string(0 - ret); + XSNPRINTF(buf, sizeof(buf), "error:%d:wolfSSL library:%s:%s:%d\n", + ret, r, file, line); + wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)); + wc_RemoveErrorNode(0); } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - return keyOutput == (keyLen + ivLen) ? keyOutput : 0; + } while (ret >= 0); } - -#endif /* NO_MD5 */ +#endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */ #endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ - #ifdef OPENSSL_EXTRA +#if !defined(NO_WOLFSSL_SERVER) +size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out, + size_t outSz) +{ + size_t size; + + /* return max size of buffer */ + if (outSz == 0) { + return RAN_LEN; + } + + if (ssl == NULL || out == NULL) { + return 0; + } + + if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays struct not saved after handshake"); + return 0; + } + + if (outSz > RAN_LEN) { + size = RAN_LEN; + } + else { + size = outSz; + } + + XMEMCPY(out, ssl->arrays->serverRandom, size); + return size; +} + + +/* Used to get the peer ephemeral public key sent during the connection + * NOTE: currently wolfSSL_KeepHandshakeResources(WOLFSSL* ssl) must be called + * before the ephemeral key is stored. + * return WOLFSSL_SUCCESS on success */ +int wolfSSL_get_server_tmp_key(const WOLFSSL* ssl, WOLFSSL_EVP_PKEY** pkey) +{ + WOLFSSL_EVP_PKEY* ret = NULL; + + WOLFSSL_ENTER("wolfSSL_get_server_tmp_key"); + + if (ssl == NULL || pkey == NULL) { + WOLFSSL_MSG("Bad argument passed in"); + return WOLFSSL_FAILURE; + } + +#ifdef HAVE_ECC + if (ssl->peerEccKey != NULL) { + unsigned char* der; + const unsigned char* pt; + unsigned int derSz = 0; + int sz; + + if (wc_ecc_export_x963(ssl->peerEccKey, NULL, &derSz) != + LENGTH_ONLY_E) { + WOLFSSL_MSG("get ecc der size failed"); + return WOLFSSL_FAILURE; + } + + derSz += MAX_SEQ_SZ + (2 * MAX_ALGO_SZ) + MAX_SEQ_SZ + TRAILING_ZERO; + der = (unsigned char*)XMALLOC(derSz, ssl->heap, DYNAMIC_TYPE_KEY); + if (der == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + + if ((sz = wc_EccPublicKeyToDer(ssl->peerEccKey, der, derSz, 1)) <= 0) { + WOLFSSL_MSG("get ecc der failed"); + XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY); + return WOLFSSL_FAILURE; + } + pt = der; /* in case pointer gets advanced */ + ret = wolfSSL_d2i_PUBKEY(NULL, &pt, sz); + XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY); + } +#endif + + *pkey = ret; + if (ret == NULL) + return WOLFSSL_FAILURE; + else + return WOLFSSL_SUCCESS; +} + +#endif /* !NO_WOLFSSL_SERVER */ + +int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version"); + + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + switch (version) { +#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) + case SSL3_VERSION: + ctx->minDowngrade = SSLv3_MINOR; + break; +#endif +#ifndef NO_TLS + #ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 + case TLS1_VERSION: + ctx->minDowngrade = TLSv1_MINOR; + break; + #endif + case TLS1_1_VERSION: + ctx->minDowngrade = TLSv1_1_MINOR; + break; + #endif + #ifndef WOLFSSL_NO_TLS12 + case TLS1_2_VERSION: + ctx->minDowngrade = TLSv1_2_MINOR; + break; + #endif + #ifdef WOLFSSL_TLS13 + case TLS1_3_VERSION: + ctx->minDowngrade = TLSv1_3_MINOR; + break; + #endif +#endif +#ifdef WOLFSSL_DTLS + #ifndef NO_OLD_TLS + case DTLS1_VERSION: + ctx->minDowngrade = DTLS_MINOR; + break; + #endif + case DTLS1_2_VERSION: + ctx->minDowngrade = DTLSv1_2_MINOR; + break; +#endif + default: + return BAD_FUNC_ARG; + } + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int ver) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_max_proto_version"); + + /* supported only at compile-time only */ + (void)ctx; + (void)ver; + return WOLFSSL_SUCCESS; +} + + +#if !defined(NO_WOLFSSL_CLIENT) +/* Return the amount of random bytes copied over or error case. + * ssl : ssl struct after handshake + * out : buffer to hold random bytes + * outSz : either 0 (return max buffer sz) or size of out buffer + * + * NOTE: wolfSSL_KeepArrays(ssl) must be called to retain handshake information. + */ +size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, + size_t outSz) +{ + size_t size; + + /* return max size of buffer */ + if (outSz == 0) { + return RAN_LEN; + } + + if (ssl == NULL || out == NULL) { + return 0; + } + + if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays struct not saved after handshake"); + return 0; + } + + if (outSz > RAN_LEN) { + size = RAN_LEN; + } + else { + size = outSz; + } + + XMEMCPY(out, ssl->arrays->clientRandom, size); + return size; +} +#endif /* !NO_WOLFSSL_CLIENT */ + + unsigned long wolfSSLeay(void) { return SSLEAY_VERSION_NUMBER; } + unsigned long wolfSSL_OpenSSL_version_num(void) + { + return OPENSSL_VERSION_NUMBER; + } const char* wolfSSLeay_version(int type) { @@ -7444,699 +15383,646 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #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 */ +#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 */ +#endif /* !NO_SHA */ +#ifdef WOLFSSL_SHA224 - void wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256) + int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX* sha) { - typedef char sha_test[sizeof(SHA256_CTX) >= sizeof(Sha256) ? 1 : -1]; + int ret; + + typedef char sha_test[sizeof(SHA224_CTX) >= sizeof(wc_Sha224) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA224_Init"); + ret = wc_InitSha224((wc_Sha224*)sha); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX* sha, const void* input, + unsigned long sz) + { + int ret; + + WOLFSSL_ENTER("SHA224_Update"); + ret = wc_Sha224Update((wc_Sha224*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA224_Final(byte* input, WOLFSSL_SHA224_CTX* sha) + { + int ret; + + WOLFSSL_ENTER("SHA224_Final"); + ret = wc_Sha224Final((wc_Sha224*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + +#endif /* WOLFSSL_SHA224 */ + + + int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256) + { + 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 +#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 */ +#endif /* WOLFSSL_SHA384 */ - #ifdef WOLFSSL_SHA512 +#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 */ +#endif /* WOLFSSL_SHA512 */ +#ifdef WOLFSSL_SHA3 +#ifndef WOLFSSL_NOSHA3_224 - #ifndef NO_MD5 - - const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void) + int wolfSSL_SHA3_224_Init(WOLFSSL_SHA3_224_CTX* sha) { - static const char* type = "MD5"; - WOLFSSL_ENTER("EVP_md5"); - return type; - } + int ret; - #endif /* NO_MD5 */ + typedef char sha_test[sizeof(SHA3_224_CTX) >= sizeof(wc_Sha3) ? 1 : -1]; + (void)sizeof(sha_test); + WOLFSSL_ENTER("SHA3_224_Init"); + ret = wc_InitSha3_224((wc_Sha3*)sha, NULL, 0); -#ifndef NO_SHA - const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void) - { - static const char* type = "SHA"; - WOLFSSL_ENTER("EVP_sha1"); - return type; - } -#endif /* NO_SHA */ + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; - - const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void) - { - static const char* type = "SHA256"; - WOLFSSL_ENTER("EVP_sha256"); - return type; - } - - #ifdef WOLFSSL_SHA384 - - const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void) - { - static const char* type = "SHA384"; - WOLFSSL_ENTER("EVP_sha384"); - return type; - } - - #endif /* WOLFSSL_SHA384 */ - - #ifdef WOLFSSL_SHA512 - - const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void) - { - static const char* type = "SHA512"; - WOLFSSL_ENTER("EVP_sha512"); - return type; - } - - #endif /* WOLFSSL_SHA512 */ - - - void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx) - { - WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init"); - (void)ctx; - /* do nothing */ + return 0; } - const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void) + int wolfSSL_SHA3_224_Update(WOLFSSL_SHA3_224_CTX* sha, const void* input, + unsigned long sz) { - static const char* type = "AES128-CBC"; - WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cbc"); - return type; + int ret; + + WOLFSSL_ENTER("SHA3_224_Update"); + ret = wc_Sha3_224_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void) + int wolfSSL_SHA3_224_Final(byte* input, WOLFSSL_SHA3_224_CTX* sha) { - static const char* type = "AES192-CBC"; - WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cbc"); - return type; + int ret; + + WOLFSSL_ENTER("SHA3_224_Final"); + ret = wc_Sha3_224_Final((wc_Sha3*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + +#endif /* WOLFSSL_NOSHA3_224 */ + + +#ifndef WOLFSSL_NOSHA3_256 + int wolfSSL_SHA3_256_Init(WOLFSSL_SHA3_256_CTX* sha3_256) + { + int ret; + + typedef char sha_test[sizeof(SHA3_256_CTX) >= sizeof(wc_Sha3) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA3_256_Init"); + ret = wc_InitSha3_256((wc_Sha3*)sha3_256, NULL, 0); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void) + int wolfSSL_SHA3_256_Update(WOLFSSL_SHA3_256_CTX* sha, const void* input, + unsigned long sz) { - static const char* type = "AES256-CBC"; - WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cbc"); - return type; + int ret; + + WOLFSSL_ENTER("SHA3_256_Update"); + ret = wc_Sha3_256_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void) + int wolfSSL_SHA3_256_Final(byte* input, WOLFSSL_SHA3_256_CTX* sha) { - static const char* type = "AES128-CTR"; - WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ctr"); - return type; + int ret; + + WOLFSSL_ENTER("SHA3_256_Final"); + ret = wc_Sha3_256_Final((wc_Sha3*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } +#endif /* WOLFSSL_NOSHA3_256 */ + + + int wolfSSL_SHA3_384_Init(WOLFSSL_SHA3_384_CTX* sha) + { + int ret; + + typedef char sha_test[sizeof(SHA3_384_CTX) >= sizeof(wc_Sha3) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA3_384_Init"); + ret = wc_InitSha3_384((wc_Sha3*)sha, NULL, 0); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void) + int wolfSSL_SHA3_384_Update(WOLFSSL_SHA3_384_CTX* sha, const void* input, + unsigned long sz) { - static const char* type = "AES192-CTR"; - WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ctr"); - return type; + int ret; + + WOLFSSL_ENTER("SHA3_384_Update"); + ret = wc_Sha3_384_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void) + int wolfSSL_SHA3_384_Final(byte* input, WOLFSSL_SHA3_384_CTX* sha) { - static const char* type = "AES256-CTR"; - WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ctr"); - return type; - } + int ret; + WOLFSSL_ENTER("SHA3_384_Final"); + ret = wc_Sha3_384_Final((wc_Sha3*)sha, input); - const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void) - { - static const char* type = "DES-CBC"; - WOLFSSL_ENTER("wolfSSL_EVP_des_cbc"); - return type; - } + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; - - const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void) - { - static const char* type = "DES-EDE3-CBC"; - WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc"); - return type; - } - - - const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void) - { - static const char* type = "ARC4"; - WOLFSSL_ENTER("wolfSSL_EVP_rc4"); - return type; - } - - - const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void) - { - static const char* type = "NULL"; - WOLFSSL_ENTER("wolfSSL_EVP_enc_null"); - return type; - } - - - int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx) - { - WOLFSSL_ENTER("EVP_MD_CTX_cleanup"); - (void)ctx; return 0; } - void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx) +#ifndef WOLFSSL_NOSHA3_512 + + int wolfSSL_SHA3_512_Init(WOLFSSL_SHA3_512_CTX* sha) { - WOLFSSL_ENTER("EVP_CIPHER_CTX_init"); - if (ctx) { - ctx->cipherType = 0xff; /* no init */ - ctx->keyLen = 0; - ctx->enc = 1; /* start in encrypt mode */ - } + int ret; + + typedef char sha_test[sizeof(SHA3_512_CTX) >= sizeof(wc_Sha3) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA3_512_Init"); + ret = wc_InitSha3_512((wc_Sha3*)sha, NULL, 0); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - /* SSL_SUCCESS on ok */ - int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx) + int wolfSSL_SHA3_512_Update(WOLFSSL_SHA3_512_CTX* sha, const void* input, + unsigned long sz) { - WOLFSSL_ENTER("EVP_CIPHER_CTX_cleanup"); - if (ctx) { - ctx->cipherType = 0xff; /* no more init */ - ctx->keyLen = 0; - } + int ret; - return SSL_SUCCESS; + WOLFSSL_ENTER("SHA3_512_Update"); + ret = wc_Sha3_512_Update((wc_Sha3*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; } - /* SSL_SUCCESS on ok */ - int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx, - const WOLFSSL_EVP_CIPHER* type, byte* key, - byte* iv, int enc) + int wolfSSL_SHA3_512_Final(byte* input, WOLFSSL_SHA3_512_CTX* sha) { -#if defined(NO_AES) && defined(NO_DES3) - (void)iv; - (void)enc; -#else - int ret = 0; -#endif + int ret; - WOLFSSL_ENTER("wolfSSL_EVP_CipherInit"); - if (ctx == NULL) { - WOLFSSL_MSG("no ctx"); - return 0; /* failure */ - } + WOLFSSL_ENTER("SHA3_512_Final"); + ret = wc_Sha3_512_Final((wc_Sha3*)sha, input); - if (type == NULL && ctx->cipherType == 0xff) { - WOLFSSL_MSG("no type set"); - return 0; /* failure */ - } + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; -#ifndef NO_AES - if (ctx->cipherType == AES_128_CBC_TYPE || (type && - XSTRNCMP(type, "AES128-CBC", 10) == 0)) { - WOLFSSL_MSG("AES-128-CBC"); - ctx->cipherType = AES_128_CBC_TYPE; - ctx->keyLen = 16; - if (enc == 0 || enc == 1) - ctx->enc = enc ? 1 : 0; - if (key) { - ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, - ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); - if (ret != 0) - return ret; - } - if (iv && key == NULL) { - ret = wc_AesSetIV(&ctx->cipher.aes, iv); - if (ret != 0) - return ret; - } - } - else if (ctx->cipherType == AES_192_CBC_TYPE || (type && - XSTRNCMP(type, "AES192-CBC", 10) == 0)) { - WOLFSSL_MSG("AES-192-CBC"); - ctx->cipherType = AES_192_CBC_TYPE; - ctx->keyLen = 24; - if (enc == 0 || enc == 1) - ctx->enc = enc ? 1 : 0; - if (key) { - ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, - ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); - if (ret != 0) - return ret; - } - if (iv && key == NULL) { - ret = wc_AesSetIV(&ctx->cipher.aes, iv); - if (ret != 0) - return ret; - } - } - else if (ctx->cipherType == AES_256_CBC_TYPE || (type && - XSTRNCMP(type, "AES256-CBC", 10) == 0)) { - WOLFSSL_MSG("AES-256-CBC"); - ctx->cipherType = AES_256_CBC_TYPE; - ctx->keyLen = 32; - if (enc == 0 || enc == 1) - ctx->enc = enc ? 1 : 0; - if (key) { - ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, - ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); - if (ret != 0) - return ret; - } - if (iv && key == NULL) { - ret = wc_AesSetIV(&ctx->cipher.aes, iv); - if (ret != 0) - return ret; - } - } -#ifdef WOLFSSL_AES_COUNTER - else if (ctx->cipherType == AES_128_CTR_TYPE || (type && - XSTRNCMP(type, "AES128-CTR", 10) == 0)) { - WOLFSSL_MSG("AES-128-CTR"); - ctx->cipherType = AES_128_CTR_TYPE; - ctx->keyLen = 16; - if (enc == 0 || enc == 1) - ctx->enc = enc ? 1 : 0; - if (key) { - ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, - AES_ENCRYPTION); - if (ret != 0) - return ret; - } - if (iv && key == NULL) { - ret = wc_AesSetIV(&ctx->cipher.aes, iv); - if (ret != 0) - return ret; - } - } - else if (ctx->cipherType == AES_192_CTR_TYPE || (type && - XSTRNCMP(type, "AES192-CTR", 10) == 0)) { - WOLFSSL_MSG("AES-192-CTR"); - ctx->cipherType = AES_192_CTR_TYPE; - ctx->keyLen = 24; - if (enc == 0 || enc == 1) - ctx->enc = enc ? 1 : 0; - if (key) { - ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, - AES_ENCRYPTION); - if (ret != 0) - return ret; - } - if (iv && key == NULL) { - ret = wc_AesSetIV(&ctx->cipher.aes, iv); - if (ret != 0) - return ret; - } - } - else if (ctx->cipherType == AES_256_CTR_TYPE || (type && - XSTRNCMP(type, "AES256-CTR", 10) == 0)) { - WOLFSSL_MSG("AES-256-CTR"); - ctx->cipherType = AES_256_CTR_TYPE; - ctx->keyLen = 32; - if (enc == 0 || enc == 1) - ctx->enc = enc ? 1 : 0; - if (key) { - ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, - AES_ENCRYPTION); - if (ret != 0) - return ret; - } - if (iv && key == NULL) { - ret = wc_AesSetIV(&ctx->cipher.aes, iv); - if (ret != 0) - return ret; - } - } -#endif /* WOLFSSL_AES_CTR */ -#endif /* NO_AES */ - -#ifndef NO_DES3 - else if (ctx->cipherType == DES_CBC_TYPE || (type && - XSTRNCMP(type, "DES-CBC", 7) == 0)) { - WOLFSSL_MSG("DES-CBC"); - ctx->cipherType = DES_CBC_TYPE; - ctx->keyLen = 8; - if (enc == 0 || enc == 1) - ctx->enc = enc ? 1 : 0; - if (key) { - ret = wc_Des_SetKey(&ctx->cipher.des, key, iv, - ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); - if (ret != 0) - return ret; - } - - if (iv && key == NULL) - wc_Des_SetIV(&ctx->cipher.des, iv); - } - else if (ctx->cipherType == DES_EDE3_CBC_TYPE || (type && - XSTRNCMP(type, "DES-EDE3-CBC", 11) == 0)) { - WOLFSSL_MSG("DES-EDE3-CBC"); - ctx->cipherType = DES_EDE3_CBC_TYPE; - ctx->keyLen = 24; - if (enc == 0 || enc == 1) - ctx->enc = enc ? 1 : 0; - if (key) { - ret = wc_Des3_SetKey(&ctx->cipher.des3, key, iv, - ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); - if (ret != 0) - return ret; - } - - if (iv && key == NULL) { - ret = wc_Des3_SetIV(&ctx->cipher.des3, iv); - if (ret != 0) - return ret; - } - } -#endif /* NO_DES3 */ -#ifndef NO_RC4 - else if (ctx->cipherType == ARC4_TYPE || (type && - XSTRNCMP(type, "ARC4", 4) == 0)) { - WOLFSSL_MSG("ARC4"); - ctx->cipherType = ARC4_TYPE; - if (ctx->keyLen == 0) /* user may have already set */ - ctx->keyLen = 16; /* default to 128 */ - if (key) - wc_Arc4SetKey(&ctx->cipher.arc4, key, ctx->keyLen); - } -#endif /* NO_RC4 */ - else if (ctx->cipherType == NULL_CIPHER_TYPE || (type && - XSTRNCMP(type, "NULL", 4) == 0)) { - WOLFSSL_MSG("NULL cipher"); - ctx->cipherType = NULL_CIPHER_TYPE; - ctx->keyLen = 0; - } - else - return 0; /* failure */ - - - return SSL_SUCCESS; + return 0; } +#endif /* WOLFSSL_NOSHA3_512 */ +#endif /* WOLFSSL_SHA3 */ - /* SSL_SUCCESS on ok */ - int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx) - { - WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_key_length"); - if (ctx) - return ctx->keyLen; - - return 0; /* failure */ - } - - - /* SSL_SUCCESS on ok */ - int wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx, - int keylen) - { - WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_key_length"); - if (ctx) - ctx->keyLen = keylen; - else - return 0; /* failure */ - - return SSL_SUCCESS; - } - - - /* SSL_SUCCESS on ok */ - int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src, - word32 len) - { - int ret = 0; - WOLFSSL_ENTER("wolfSSL_EVP_Cipher"); - - if (ctx == NULL || dst == NULL || src == NULL) { - WOLFSSL_MSG("Bad function argument"); - return 0; /* failure */ - } - - if (ctx->cipherType == 0xff) { - WOLFSSL_MSG("no init"); - return 0; /* failure */ - } - - switch (ctx->cipherType) { - -#ifndef NO_AES - case AES_128_CBC_TYPE : - case AES_192_CBC_TYPE : - case AES_256_CBC_TYPE : - WOLFSSL_MSG("AES CBC"); - if (ctx->enc) - ret = wc_AesCbcEncrypt(&ctx->cipher.aes, dst, src, len); - else - ret = wc_AesCbcDecrypt(&ctx->cipher.aes, dst, src, len); - break; - -#ifdef WOLFSSL_AES_COUNTER - case AES_128_CTR_TYPE : - case AES_192_CTR_TYPE : - case AES_256_CTR_TYPE : - WOLFSSL_MSG("AES CTR"); - wc_AesCtrEncrypt(&ctx->cipher.aes, dst, src, len); - break; -#endif -#endif /* NO_AES */ - -#ifndef NO_DES3 - case DES_CBC_TYPE : - if (ctx->enc) - wc_Des_CbcEncrypt(&ctx->cipher.des, dst, src, len); - else - wc_Des_CbcDecrypt(&ctx->cipher.des, dst, src, len); - break; - - case DES_EDE3_CBC_TYPE : - if (ctx->enc) - ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, dst, src, len); - else - ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, dst, src, len); - break; -#endif - -#ifndef NO_RC4 - case ARC4_TYPE : - wc_Arc4Process(&ctx->cipher.arc4, dst, src, len); - break; -#endif - - case NULL_CIPHER_TYPE : - XMEMCPY(dst, src, len); - break; - - default: { - WOLFSSL_MSG("bad type"); - return 0; /* failure */ - } - } - - if (ret != 0) { - WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); - return 0; /* failuer */ - } - - WOLFSSL_MSG("wolfSSL_EVP_Cipher success"); - return SSL_SUCCESS; /* success */ - } - - - /* 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) { #ifndef NO_AES +#ifdef HAVE_AES_CBC case AES_128_CBC_TYPE : case AES_192_CBC_TYPE : case AES_256_CBC_TYPE : WOLFSSL_MSG("AES CBC"); - memcpy(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); + XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); break; - +#endif +#ifdef HAVE_AESGCM + case AES_128_GCM_TYPE : + case AES_192_GCM_TYPE : + case AES_256_GCM_TYPE : + WOLFSSL_MSG("AES GCM"); + XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); + break; +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AES_ECB + case AES_128_ECB_TYPE : + case AES_192_ECB_TYPE : + case AES_256_ECB_TYPE : + WOLFSSL_MSG("AES ECB"); + break; +#endif #ifdef WOLFSSL_AES_COUNTER case AES_128_CTR_TYPE : case AES_192_CTR_TYPE : case AES_256_CTR_TYPE : WOLFSSL_MSG("AES CTR"); - memcpy(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); + XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); break; #endif /* WOLFSSL_AES_COUNTER */ - +#ifdef WOLFSSL_AES_CFB +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + case AES_128_CFB1_TYPE: + case AES_192_CFB1_TYPE: + case AES_256_CFB1_TYPE: + WOLFSSL_MSG("AES CFB1"); + break; + case AES_128_CFB8_TYPE: + case AES_192_CFB8_TYPE: + case AES_256_CFB8_TYPE: + WOLFSSL_MSG("AES CFB8"); + break; +#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ + case AES_128_CFB128_TYPE: + case AES_192_CFB128_TYPE: + case AES_256_CFB128_TYPE: + WOLFSSL_MSG("AES CFB128"); + break; +#endif /* WOLFSSL_AES_CFB */ +#if defined(WOLFSSL_AES_OFB) + case AES_128_OFB_TYPE: + case AES_192_OFB_TYPE: + case AES_256_OFB_TYPE: + WOLFSSL_MSG("AES OFB"); + break; +#endif /* WOLFSSL_AES_OFB */ +#ifdef WOLFSSL_AES_XTS + case AES_128_XTS_TYPE: + case AES_256_XTS_TYPE: + WOLFSSL_MSG("AES XTS"); + break; +#endif /* WOLFSSL_AES_XTS */ #endif /* NO_AES */ #ifndef NO_DES3 case DES_CBC_TYPE : WOLFSSL_MSG("DES CBC"); - memcpy(ctx->iv, &ctx->cipher.des.reg, DES_BLOCK_SIZE); + XMEMCPY(ctx->iv, &ctx->cipher.des.reg, DES_BLOCK_SIZE); break; case DES_EDE3_CBC_TYPE : WOLFSSL_MSG("DES EDE3 CBC"); - memcpy(ctx->iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE); + XMEMCPY(ctx->iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE); + break; +#endif +#ifdef WOLFSSL_DES_ECB + case DES_ECB_TYPE : + WOLFSSL_MSG("DES ECB"); + break; + case DES_EDE3_ECB_TYPE : + WOLFSSL_MSG("DES3 ECB"); break; #endif +#ifdef HAVE_IDEA + case IDEA_CBC_TYPE : + WOLFSSL_MSG("IDEA CBC"); + XMEMCPY(ctx->iv, &ctx->cipher.idea.reg, IDEA_BLOCK_SIZE); + break; +#endif case ARC4_TYPE : WOLFSSL_MSG("ARC4"); break; @@ -8147,14 +16033,13 @@ int wolfSSL_set_compression(WOLFSSL* ssl) 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) { @@ -8162,25 +16047,41 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (ctx == NULL) { WOLFSSL_MSG("Bad function argument"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } switch (ctx->cipherType) { #ifndef NO_AES +#ifdef HAVE_AES_CBC case AES_128_CBC_TYPE : case AES_192_CBC_TYPE : case AES_256_CBC_TYPE : WOLFSSL_MSG("AES CBC"); - memcpy(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); + XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); break; - +#endif +#ifdef HAVE_AESGCM + case AES_128_GCM_TYPE : + case AES_192_GCM_TYPE : + case AES_256_GCM_TYPE : + WOLFSSL_MSG("AES GCM"); + XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); + break; +#endif +#ifdef HAVE_AES_ECB + case AES_128_ECB_TYPE : + case AES_192_ECB_TYPE : + case AES_256_ECB_TYPE : + WOLFSSL_MSG("AES ECB"); + break; +#endif #ifdef WOLFSSL_AES_COUNTER case AES_128_CTR_TYPE : case AES_192_CTR_TYPE : case AES_256_CTR_TYPE : WOLFSSL_MSG("AES CTR"); - memcpy(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); + XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); break; #endif @@ -8189,15 +16090,29 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifndef NO_DES3 case DES_CBC_TYPE : WOLFSSL_MSG("DES CBC"); - memcpy(&ctx->cipher.des.reg, ctx->iv, DES_BLOCK_SIZE); + XMEMCPY(&ctx->cipher.des.reg, ctx->iv, DES_BLOCK_SIZE); break; case DES_EDE3_CBC_TYPE : WOLFSSL_MSG("DES EDE3 CBC"); - memcpy(&ctx->cipher.des3.reg, ctx->iv, DES_BLOCK_SIZE); + XMEMCPY(&ctx->cipher.des3.reg, ctx->iv, DES_BLOCK_SIZE); + break; +#endif +#ifdef WOLFSSL_DES_ECB + case DES_ECB_TYPE : + WOLFSSL_MSG("DES ECB"); + break; + case DES_EDE3_ECB_TYPE : + WOLFSSL_MSG("DES3 ECB"); break; #endif +#ifdef HAVE_IDEA + case IDEA_CBC_TYPE : + WOLFSSL_MSG("IDEA CBC"); + XMEMCPY(&ctx->cipher.idea.reg, ctx->iv, IDEA_BLOCK_SIZE); + break; +#endif case ARC4_TYPE : WOLFSSL_MSG("ARC4"); break; @@ -8208,247 +16123,329 @@ int wolfSSL_set_compression(WOLFSSL* ssl) default: { WOLFSSL_MSG("bad type"); - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - - /* SSL_SUCCESS on ok */ - int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx, const WOLFSSL_EVP_MD* type) - { - WOLFSSL_ENTER("EVP_DigestInit"); - if (XSTRNCMP(type, "SHA256", 6) == 0) { - ctx->macType = SHA256; - wolfSSL_SHA256_Init((SHA256_CTX*)&ctx->hash); - } - #ifdef WOLFSSL_SHA384 - else if (XSTRNCMP(type, "SHA384", 6) == 0) { - ctx->macType = SHA384; - wolfSSL_SHA384_Init((SHA384_CTX*)&ctx->hash); - } - #endif - #ifdef WOLFSSL_SHA512 - else if (XSTRNCMP(type, "SHA512", 6) == 0) { - ctx->macType = SHA512; - wolfSSL_SHA512_Init((SHA512_CTX*)&ctx->hash); - } - #endif - #ifndef NO_MD5 - else if (XSTRNCMP(type, "MD5", 3) == 0) { - ctx->macType = MD5; - wolfSSL_MD5_Init((MD5_CTX*)&ctx->hash); - } - #endif - #ifndef NO_SHA - /* has to be last since would pick or 256, 384, or 512 too */ - else if (XSTRNCMP(type, "SHA", 3) == 0) { - ctx->macType = SHA; - wolfSSL_SHA_Init((SHA_CTX*)&ctx->hash); - } - #endif /* NO_SHA */ - else - return BAD_FUNC_ARG; - - return SSL_SUCCESS; - } - - - /* SSL_SUCCESS on ok */ - int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data, - unsigned long sz) - { - WOLFSSL_ENTER("EVP_DigestUpdate"); - - switch (ctx->macType) { -#ifndef NO_MD5 - case MD5: - wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data, - (unsigned long)sz); - break; -#endif -#ifndef NO_SHA - case SHA: - wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data, - (unsigned long)sz); - break; -#endif -#ifndef NO_SHA256 - case SHA256: - wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data, - (unsigned long)sz); - break; -#endif -#ifdef WOLFSSL_SHA384 - case SHA384: - wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data, - (unsigned long)sz); - break; -#endif -#ifdef WOLFSSL_SHA512 - case SHA512: - wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data, - (unsigned long)sz); - break; -#endif - default: - return BAD_FUNC_ARG; - } - - return SSL_SUCCESS; - } - - - /* SSL_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: - wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash); - if (s) *s = MD5_DIGEST_SIZE; - break; -#endif -#ifndef NO_SHA - case SHA: - wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash); - if (s) *s = SHA_DIGEST_SIZE; - break; -#endif -#ifndef NO_SHA256 - case SHA256: - wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash); - if (s) *s = SHA256_DIGEST_SIZE; - break; -#endif -#ifdef WOLFSSL_SHA384 - case SHA384: - wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash); - if (s) *s = SHA384_DIGEST_SIZE; - break; -#endif -#ifdef WOLFSSL_SHA512 - case SHA512: - wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash); - if (s) *s = SHA512_DIGEST_SIZE; - break; -#endif - default: - return BAD_FUNC_ARG; - } - - return SSL_SUCCESS; - } - - - /* SSL_SUCCESS on ok */ - int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, - unsigned int* s) - { - WOLFSSL_ENTER("EVP_DigestFinal_ex"); - return EVP_DigestFinal(ctx, md, s); - } - - unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key, - int key_len, const unsigned char* d, int n, - unsigned char* md, unsigned int* md_len) + int key_len, const unsigned char* d, int n, + unsigned char* md, unsigned int* md_len) { int type; + int mdlen; unsigned char* ret = NULL; #ifdef WOLFSSL_SMALL_STACK Hmac* hmac = NULL; #else Hmac hmac[1]; #endif + void* heap = NULL; - WOLFSSL_ENTER("HMAC"); - if (!md) + WOLFSSL_ENTER("wolfSSL_HMAC"); + if (!md) { + WOLFSSL_MSG("Static buffer not supported, pass in md buffer"); return NULL; /* no static buffer support */ + } - if (XSTRNCMP(evp_md, "MD5", 3) == 0) - type = MD5; - else if (XSTRNCMP(evp_md, "SHA", 3) == 0) - type = SHA; - else +#ifndef NO_MD5 + if (XSTRNCMP(evp_md, "MD5", 3) == 0) { + type = WC_MD5; + mdlen = WC_MD5_DIGEST_SIZE; + } else +#endif +#ifdef WOLFSSL_SHA224 + if (XSTRNCMP(evp_md, "SHA224", 6) == 0) { + type = WC_SHA224; + mdlen = WC_SHA224_DIGEST_SIZE; + } else +#endif +#ifndef NO_SHA256 + if (XSTRNCMP(evp_md, "SHA256", 6) == 0) { + type = WC_SHA256; + mdlen = WC_SHA256_DIGEST_SIZE; + } else +#endif +#ifdef WOLFSSL_SHA384 + if (XSTRNCMP(evp_md, "SHA384", 6) == 0) { + type = WC_SHA384; + mdlen = WC_SHA384_DIGEST_SIZE; + } else +#endif +#ifdef WOLFSSL_SHA512 + if (XSTRNCMP(evp_md, "SHA512", 6) == 0) { + type = WC_SHA512; + mdlen = WC_SHA512_DIGEST_SIZE; + } else +#endif +#ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + if (XSTRNCMP(evp_md, "SHA3_224", 8) == 0) { + type = WC_SHA3_224; + mdlen = WC_SHA3_224_DIGEST_SIZE; + } else + #endif + #ifndef WOLFSSL_NOSHA3_256 + if (XSTRNCMP(evp_md, "SHA3_256", 8) == 0) { + type = WC_SHA3_256; + mdlen = WC_SHA3_256_DIGEST_SIZE; + } else + #endif + if (XSTRNCMP(evp_md, "SHA3_384", 8) == 0) { + type = WC_SHA3_384; + mdlen = WC_SHA3_384_DIGEST_SIZE; + } else + #ifndef WOLFSSL_NOSHA3_512 + if (XSTRNCMP(evp_md, "SHA3_512", 8) == 0) { + type = WC_SHA3_512; + mdlen = WC_SHA3_512_DIGEST_SIZE; + } else + #endif +#endif +#ifndef NO_SHA + if (XSTRNCMP(evp_md, "SHA", 3) == 0) { + type = WC_SHA; + mdlen = WC_SHA_DIGEST_SIZE; + } else +#endif + { 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 = mdlen; + ret = md; + } } + } + wc_HmacFree(hmac); + } #ifdef WOLFSSL_SMALL_STACK - XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); #endif + (void)evp_md; return ret; } void wolfSSL_ERR_clear_error(void) { - /* TODO: */ + WOLFSSL_ENTER("wolfSSL_ERR_clear_error"); + +#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX) || \ + defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + wc_ClearErrorNodes(); +#endif } int wolfSSL_RAND_status(void) { - return SSL_SUCCESS; /* wolfCrypt provides enough seed internally */ + return WOLFSSL_SUCCESS; /* wolfCrypt provides enough seed internally */ } - + #ifndef NO_WOLFSSL_STUB void wolfSSL_RAND_add(const void* add, int len, double entropy) { (void)add; (void)len; (void)entropy; - + WOLFSSL_STUB("RAND_add"); /* wolfSSL seeds/adds internally, use explicit RNG if you want to take control */ } - + #endif #ifndef NO_DES3 - /* SSL_SUCCESS on ok */ + /* 0 on ok */ int wolfSSL_DES_key_sched(WOLFSSL_const_DES_cblock* key, - WOLFSSL_DES_key_schedule* schedule) + WOLFSSL_DES_key_schedule* schedule) { - WOLFSSL_ENTER("DES_key_sched"); - XMEMCPY(schedule, key, sizeof(const_DES_cblock)); - return SSL_SUCCESS; + WOLFSSL_ENTER("wolfSSL_DES_key_sched"); + + if (key == NULL || schedule == NULL) { + WOLFSSL_MSG("Null argument passed in"); + } + else { + XMEMCPY(schedule, key, sizeof(WOLFSSL_const_DES_cblock)); + } + + return 0; + } + + + /* intended to behave similar to Kerberos mit_des_cbc_cksum + * return the last 4 bytes of cipher text */ + WOLFSSL_DES_LONG wolfSSL_DES_cbc_cksum(const unsigned char* in, + WOLFSSL_DES_cblock* out, long length, WOLFSSL_DES_key_schedule* sc, + WOLFSSL_const_DES_cblock* iv) + { + WOLFSSL_DES_LONG ret; + unsigned char* tmp; + unsigned char* data = (unsigned char*)in; + long dataSz = length; + byte dynamicFlag = 0; /* when padding the buffer created needs free'd */ + + WOLFSSL_ENTER("wolfSSL_DES_cbc_cksum"); + + if (in == NULL || out == NULL || sc == NULL || iv == NULL) { + WOLFSSL_MSG("Bad argument passed in"); + return 0; + } + + /* if input length is not a multiple of DES_BLOCK_SIZE pad with 0s */ + if (dataSz % DES_BLOCK_SIZE) { + dataSz += DES_BLOCK_SIZE - (dataSz % DES_BLOCK_SIZE); + data = (unsigned char*)XMALLOC(dataSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (data == NULL) { + WOLFSSL_MSG("Issue creating temporary buffer"); + return 0; + } + dynamicFlag = 1; /* set to free buffer at end */ + XMEMCPY(data, in, length); + XMEMSET(data + length, 0, dataSz - length); /* padding */ + } + + tmp = (unsigned char*)XMALLOC(dataSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + WOLFSSL_MSG("Issue creating temporary buffer"); + if (dynamicFlag == 1) { + XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + return 0; + } + + wolfSSL_DES_cbc_encrypt(data, tmp, dataSz, sc, + (WOLFSSL_DES_cblock*)iv, 1); + XMEMCPY((unsigned char*)out, tmp + (dataSz - DES_BLOCK_SIZE), + DES_BLOCK_SIZE); + + ret = (((*((unsigned char*)out + 4) & 0xFF) << 24)| + ((*((unsigned char*)out + 5) & 0xFF) << 16)| + ((*((unsigned char*)out + 6) & 0xFF) << 8) | + (*((unsigned char*)out + 7) & 0xFF)); + + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (dynamicFlag == 1) { + XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return ret; } void wolfSSL_DES_cbc_encrypt(const unsigned char* input, - unsigned char* output, long length, - WOLFSSL_DES_key_schedule* schedule, WOLFSSL_DES_cblock* ivec, - int enc) + unsigned char* output, long length, + WOLFSSL_DES_key_schedule* schedule, + WOLFSSL_DES_cblock* ivec, int enc) { Des myDes; + byte lastblock[DES_BLOCK_SIZE]; + int lb_sz; + long blk; WOLFSSL_ENTER("DES_cbc_encrypt"); /* OpenSSL compat, no ret */ wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc); + lb_sz = length%DES_BLOCK_SIZE; + blk = length/DES_BLOCK_SIZE; - if (enc) - wc_Des_CbcEncrypt(&myDes, output, input, (word32)length); - else - wc_Des_CbcDecrypt(&myDes, output, input, (word32)length); + if (enc){ + wc_Des_CbcEncrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE); + if(lb_sz){ + XMEMSET(lastblock, 0, DES_BLOCK_SIZE); + XMEMCPY(lastblock, input+length-lb_sz, lb_sz); + wc_Des_CbcEncrypt(&myDes, output+blk*DES_BLOCK_SIZE, + lastblock, (word32)DES_BLOCK_SIZE); + } + } + else { + wc_Des_CbcDecrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE); + if(lb_sz){ + wc_Des_CbcDecrypt(&myDes, lastblock, input+length-lb_sz, (word32)DES_BLOCK_SIZE); + XMEMCPY(output+length-lb_sz, lastblock, lb_sz); + } + } + } + + + /* WOLFSSL_DES_key_schedule is a unsigned char array of size 8 */ + void wolfSSL_DES_ede3_cbc_encrypt(const unsigned char* input, + unsigned char* output, long sz, + WOLFSSL_DES_key_schedule* ks1, + WOLFSSL_DES_key_schedule* ks2, + WOLFSSL_DES_key_schedule* ks3, + WOLFSSL_DES_cblock* ivec, int enc) + { + int ret; + Des3 des; + byte key[24];/* EDE uses 24 size key */ + byte lastblock[DES_BLOCK_SIZE]; + int lb_sz; + long blk; + + WOLFSSL_ENTER("wolfSSL_DES_ede3_cbc_encrypt"); + + XMEMSET(key, 0, sizeof(key)); + XMEMCPY(key, *ks1, DES_BLOCK_SIZE); + XMEMCPY(&key[DES_BLOCK_SIZE], *ks2, DES_BLOCK_SIZE); + XMEMCPY(&key[DES_BLOCK_SIZE * 2], *ks3, DES_BLOCK_SIZE); + lb_sz = sz%DES_BLOCK_SIZE; + blk = sz/DES_BLOCK_SIZE; + + /* OpenSSL compat, no ret */ + (void)wc_Des3Init(&des, NULL, INVALID_DEVID); + + if (enc) { + wc_Des3_SetKey(&des, key, (const byte*)ivec, DES_ENCRYPTION); + ret = wc_Des3_CbcEncrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE); + #endif + (void)ret; /* ignore return codes for processing */ + if(lb_sz){ + XMEMSET(lastblock, 0, DES_BLOCK_SIZE); + XMEMCPY(lastblock, input+sz-lb_sz, lb_sz); + ret = wc_Des3_CbcEncrypt(&des, output+blk*DES_BLOCK_SIZE, + lastblock, (word32)DES_BLOCK_SIZE); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE); + #endif + (void)ret; /* ignore return codes for processing */ + } + } + else { + wc_Des3_SetKey(&des, key, (const byte*)ivec, DES_DECRYPTION); + ret = wc_Des3_CbcDecrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE); + #endif + (void)ret; /* ignore return codes for processing */ + if(lb_sz){ + ret = wc_Des3_CbcDecrypt(&des, lastblock, input+sz-lb_sz, (word32)DES_BLOCK_SIZE); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &des.asyncDev, WC_ASYNC_FLAG_NONE); + #endif + (void)ret; /* ignore return codes for processing */ + XMEMCPY(output+sz-lb_sz, lastblock, lb_sz); + } + } + wc_Des3Free(&des); } @@ -8459,55 +16456,138 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int enc) { Des myDes; + byte lastblock[DES_BLOCK_SIZE]; + int lb_sz; + long idx = length; + long blk; WOLFSSL_ENTER("DES_ncbc_encrypt"); /* OpenSSL compat, no ret */ wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc); + lb_sz = length%DES_BLOCK_SIZE; + blk = length/DES_BLOCK_SIZE; + idx -= sizeof(DES_cblock); + if (lb_sz) { + idx += DES_BLOCK_SIZE - lb_sz; + } + if (enc){ + wc_Des_CbcEncrypt(&myDes, output, input, + (word32)blk * DES_BLOCK_SIZE); + if (lb_sz){ + XMEMSET(lastblock, 0, DES_BLOCK_SIZE); + XMEMCPY(lastblock, input+length-lb_sz, lb_sz); + wc_Des_CbcEncrypt(&myDes, output + blk * DES_BLOCK_SIZE, + lastblock, (word32)DES_BLOCK_SIZE); + } + XMEMCPY(ivec, output + idx, sizeof(DES_cblock)); + } else { + WOLFSSL_DES_cblock tmp; + XMEMCPY(tmp, input + idx, sizeof(DES_cblock)); + wc_Des_CbcDecrypt(&myDes, output, input, + (word32)blk * DES_BLOCK_SIZE); + if (lb_sz){ + wc_Des_CbcDecrypt(&myDes, lastblock, input + length - lb_sz, + (word32)DES_BLOCK_SIZE); + XMEMCPY(output+length-lb_sz, lastblock, lb_sz); + } + XMEMCPY(ivec, tmp, sizeof(WOLFSSL_DES_cblock)); + } - if (enc) - wc_Des_CbcEncrypt(&myDes, output, input, (word32)length); - else - wc_Des_CbcDecrypt(&myDes, output, input, (word32)length); - - XMEMCPY(ivec, output + length - sizeof(DES_cblock), sizeof(DES_cblock)); } #endif /* NO_DES3 */ - void wolfSSL_ERR_free_strings(void) { /* handled internally */ } - - void wolfSSL_ERR_remove_state(unsigned long state) - { - /* TODO: GetErrors().Remove(); */ - (void)state; - } - - - void wolfSSL_EVP_cleanup(void) - { - /* nothing to do here */ - } - - void wolfSSL_cleanup_all_ex_data(void) { /* nothing to do here */ } - 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.sendVerify = 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 + if (wc_InitMd5_ex(&ssl->hsHashes->hashMd5, ssl->heap, + ssl->devId) != 0) { + return WOLFSSL_FAILURE; + } + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Md5SetFlags(&ssl->hsHashes->hashMd5, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#ifndef NO_SHA + if (wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap, + ssl->devId) != 0) { + return WOLFSSL_FAILURE; + } + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_ShaSetFlags(&ssl->hsHashes->hashSha, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#endif +#ifndef NO_SHA256 + if (wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap, + ssl->devId) != 0) { + return WOLFSSL_FAILURE; + } + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Sha256SetFlags(&ssl->hsHashes->hashSha256, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#ifdef WOLFSSL_SHA384 + if (wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap, + ssl->devId) != 0) { + return WOLFSSL_FAILURE; + } + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Sha384SetFlags(&ssl->hsHashes->hashSha384, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#ifdef WOLFSSL_SHA512 + if (wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap, + ssl->devId) != 0) { + return WOLFSSL_FAILURE; + } + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Sha512SetFlags(&ssl->hsHashes->hashSha512, WC_HASH_FLAG_WILLCOPY); + #endif +#endif + } +#ifdef SESSION_CERTS + ssl->session.chain.count = 0; +#endif +#ifdef KEEP_PEER_CERT + FreeX509(&ssl->peerCert); + InitX509(&ssl->peerCert, 0, ssl->heap); +#endif + + return WOLFSSL_SUCCESS; + } long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t) { @@ -8519,103 +16599,691 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ses->timeout = tmptime; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } +#endif +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) 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) - ctx->partialWrite = 1; + switch(mode) { + case SSL_MODE_ENABLE_PARTIAL_WRITE: + ctx->partialWrite = 1; + break; + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + case SSL_MODE_RELEASE_BUFFERS: + WOLFSSL_MSG("SSL_MODE_RELEASE_BUFFERS not implemented."); + break; + #endif + default: + WOLFSSL_MSG("Mode Not Implemented"); + } + + /* SSL_MODE_AUTO_RETRY + * Should not return -1 with renegotiation on read/write */ return mode; } +#endif +#ifdef OPENSSL_EXTRA + #ifndef NO_WOLFSSL_STUB long wolfSSL_SSL_get_mode(WOLFSSL* ssl) { /* TODO: */ (void)ssl; + WOLFSSL_STUB("SSL_get_mode"); return 0; } + #endif - + #ifndef NO_WOLFSSL_STUB long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx) { /* TODO: */ (void)ctx; + WOLFSSL_STUB("SSL_CTX_get_mode"); return 0; } + #endif - + #ifndef NO_WOLFSSL_STUB void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m) { /* TODO: maybe? */ (void)ctx; (void)m; + WOLFSSL_STUB("SSL_CTX_set_default_read_ahead"); + } + #endif + + + /* Storing app session context id, this value is inherited by WOLFSSL + * objects created from WOLFSSL_CTX. Any session that is imported with a + * different session context id will be rejected. + * + * ctx structure to set context in + * sid_ctx value of context to set + * sid_ctx_len length of sid_ctx buffer + * + * Returns SSL_SUCCESS in success case and SSL_FAILURE when failing + */ + int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX* ctx, + const unsigned char* sid_ctx, + unsigned int sid_ctx_len) + { + WOLFSSL_ENTER("SSL_CTX_set_session_id_context"); + + /* No application specific context needed for wolfSSL */ + if (sid_ctx_len > ID_LEN || ctx == NULL || sid_ctx == NULL) { + return SSL_FAILURE; + } + XMEMCPY(ctx->sessionCtx, sid_ctx, sid_ctx_len); + ctx->sessionCtxSz = (byte)sid_ctx_len; + + return SSL_SUCCESS; } - int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX* ctx, - const unsigned char* sid_ctx, - unsigned int sid_ctx_len) + + /* Storing app session context id. Any session that is imported with a + * different session context id will be rejected. + * + * ssl structure to set context in + * id value of context to set + * len length of sid_ctx buffer + * + * Returns SSL_SUCCESS in success case and SSL_FAILURE when failing + */ + int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id, + unsigned int len) { - /* No application specific context needed for wolfSSL */ - (void)ctx; - (void)sid_ctx; - (void)sid_ctx_len; + WOLFSSL_ENTER("wolfSSL_set_session_id_context"); + + if (len > ID_LEN || ssl == NULL || id == NULL) { + return SSL_FAILURE; + } + XMEMCPY(ssl->sessionCtx, id, len); + ssl->sessionCtxSz = (byte)len; + return SSL_SUCCESS; } long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx) { - /* TODO: maybe? */ (void)ctx; - return (~0); + #ifndef NO_SESSION_CACHE + return (long)(SESSIONS_PER_ROW * SESSION_ROWS); + #else + return 0; + #endif } - unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line, - const char** data, int *flags) + + /* returns the unsigned error value and increments the pointer into the + * error queue. + * + * file pointer to file name + * line gets set to line number of error when not NULL + */ + unsigned long wolfSSL_ERR_get_error_line(const char** file, int* line) { - /* Not implemented */ + #ifdef DEBUG_WOLFSSL + int ret = wc_PullErrorNode(file, NULL, line); + if (ret < 0) { + if (ret == BAD_STATE_E) return 0; /* no errors in queue */ + WOLFSSL_MSG("Issue getting error node"); + WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line", ret); + ret = 0 - ret; /* return absolute value of error */ + + /* panic and try to clear out nodes */ + wc_ClearErrorNodes(); + } + return (unsigned long)ret; + #else (void)file; (void)line; - (void)data; - (void)flags; + return 0; + #endif + } + + +#if (defined(DEBUG_WOLFSSL) || defined(OPENSSL_EXTRA)) && \ + (!defined(_WIN32) && !defined(NO_ERROR_QUEUE)) + static const char WOLFSSL_SYS_ACCEPT_T[] = "accept"; + static const char WOLFSSL_SYS_BIND_T[] = "bind"; + static const char WOLFSSL_SYS_CONNECT_T[] = "connect"; + static const char WOLFSSL_SYS_FOPEN_T[] = "fopen"; + static const char WOLFSSL_SYS_FREAD_T[] = "fread"; + static const char WOLFSSL_SYS_GETADDRINFO_T[] = "getaddrinfo"; + static const char WOLFSSL_SYS_GETSOCKOPT_T[] = "getsockopt"; + static const char WOLFSSL_SYS_GETSOCKNAME_T[] = "getsockname"; + static const char WOLFSSL_SYS_GETHOSTBYNAME_T[] = "gethostbyname"; + static const char WOLFSSL_SYS_GETNAMEINFO_T[] = "getnameinfo"; + static const char WOLFSSL_SYS_GETSERVBYNAME_T[] = "getservbyname"; + static const char WOLFSSL_SYS_IOCTLSOCKET_T[] = "ioctlsocket"; + static const char WOLFSSL_SYS_LISTEN_T[] = "listen"; + static const char WOLFSSL_SYS_OPENDIR_T[] = "opendir"; + static const char WOLFSSL_SYS_SETSOCKOPT_T[] = "setsockopt"; + static const char WOLFSSL_SYS_SOCKET_T[] = "socket"; + + /* switch with int mapped to function name for compatibility */ + static const char* wolfSSL_ERR_sys_func(int fun) + { + switch (fun) { + case WOLFSSL_SYS_ACCEPT: return WOLFSSL_SYS_ACCEPT_T; + case WOLFSSL_SYS_BIND: return WOLFSSL_SYS_BIND_T; + case WOLFSSL_SYS_CONNECT: return WOLFSSL_SYS_CONNECT_T; + case WOLFSSL_SYS_FOPEN: return WOLFSSL_SYS_FOPEN_T; + case WOLFSSL_SYS_FREAD: return WOLFSSL_SYS_FREAD_T; + case WOLFSSL_SYS_GETADDRINFO: return WOLFSSL_SYS_GETADDRINFO_T; + case WOLFSSL_SYS_GETSOCKOPT: return WOLFSSL_SYS_GETSOCKOPT_T; + case WOLFSSL_SYS_GETSOCKNAME: return WOLFSSL_SYS_GETSOCKNAME_T; + case WOLFSSL_SYS_GETHOSTBYNAME: return WOLFSSL_SYS_GETHOSTBYNAME_T; + case WOLFSSL_SYS_GETNAMEINFO: return WOLFSSL_SYS_GETNAMEINFO_T; + case WOLFSSL_SYS_GETSERVBYNAME: return WOLFSSL_SYS_GETSERVBYNAME_T; + case WOLFSSL_SYS_IOCTLSOCKET: return WOLFSSL_SYS_IOCTLSOCKET_T; + case WOLFSSL_SYS_LISTEN: return WOLFSSL_SYS_LISTEN_T; + case WOLFSSL_SYS_OPENDIR: return WOLFSSL_SYS_OPENDIR_T; + case WOLFSSL_SYS_SETSOCKOPT: return WOLFSSL_SYS_SETSOCKOPT_T; + case WOLFSSL_SYS_SOCKET: return WOLFSSL_SYS_SOCKET_T; + default: + return "NULL"; + } + } +#endif /* DEBUG_WOLFSSL */ + + + /* @TODO when having an error queue this needs to push to the queue */ + void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file, + int line) + { + WOLFSSL_ENTER("wolfSSL_ERR_put_error"); + + #if !defined(DEBUG_WOLFSSL) && !defined(OPENSSL_EXTRA) + (void)fun; + (void)err; + (void)file; + (void)line; + WOLFSSL_MSG("Not compiled in debug mode"); + #elif defined(OPENSSL_EXTRA) && \ + (defined(_WIN32) || defined(NO_ERROR_QUEUE)) + (void)fun; + (void)file; + (void)line; + WOLFSSL_ERROR(err); + #else + WOLFSSL_ERROR_LINE(err, wolfSSL_ERR_sys_func(fun), (unsigned int)line, + file, NULL); + #endif + (void)lib; + } + + + /* Similar to wolfSSL_ERR_get_error_line but takes in a flags argument for + * more flexibility. + * + * file output pointer to file where error happened + * line output to line number of error + * data output data. Is a string if ERR_TXT_STRING flag is used + * flags bit flag to adjust data output + * + * Returns the error value or 0 if no errors are in the queue + */ + unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line, + const char** data, int *flags) + { + int ret; + + WOLFSSL_STUB("wolfSSL_ERR_get_error_line_data"); + + if (flags != NULL) { + if ((*flags & ERR_TXT_STRING) == ERR_TXT_STRING) { + ret = wc_PullErrorNode(file, data, line); + if (ret < 0) { + if (ret == BAD_STATE_E) return 0; /* no errors in queue */ + WOLFSSL_MSG("Error with pulling error node!"); + WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret); + ret = 0 - ret; /* return absolute value of error */ + + /* panic and try to clear out nodes */ + wc_ClearErrorNodes(); + } + + return (unsigned long)ret; + } + } + + ret = wc_PullErrorNode(file, NULL, line); + if (ret < 0) { + if (ret == BAD_STATE_E) return 0; /* no errors in queue */ + WOLFSSL_MSG("Error with pulling error node!"); + WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret); + ret = 0 - ret; /* return absolute value of error */ + + /* panic and try to clear out nodes */ + wc_ClearErrorNodes(); + } + + return (unsigned long)ret; } #endif /* OPENSSL_EXTRA */ -#if defined(KEEP_PEER_CERT) +#if (defined(KEEP_PEER_CERT) && defined(SESSION_CERTS)) || \ + (defined(OPENSSL_ALL) && defined(HAVE_PKCS7)) + /* 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; + #else + DecodedCert cert[1]; + #endif + if (x509 == NULL || in == NULL || len <= 0) + return BAD_FUNC_ARG; + #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) { + /* Check if x509 was not previously initialized by wolfSSL_X509_new() */ + if (x509->dynamicMemory != TRUE) + InitX509(x509, 0, NULL); + ret = CopyDecodedToX509(x509, cert); + FreeDecodedCert(cert); + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + #endif + + return ret; + } +#endif /* (KEEP_PEER_CERT && SESSION_CERTS) || (OPENSSL_ALL && HAVE_PKCS7) */ + + +#ifdef KEEP_PEER_CERT + WOLFSSL_ABI WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_get_peer_certificate"); + if (ssl == NULL) + return NULL; + 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 */ +#if defined(SESSION_CERTS) +/* Return stack of peer certs. + * If Qt or OPENSSL_ALL is defined then return ssl->peerCertChain. + * All other cases return &ssl->session.chain + * ssl->peerCertChain is type WOLFSSL_STACK* + * ssl->session.chain is type WOLFSSL_X509_CHAIN + * Caller does not need to free return. The stack is Free'd when WOLFSSL* ssl is. + */ +WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) +{ + WOLFSSL_STACK* sk; + WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain"); -#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) + if (ssl == NULL) + return NULL; - void wolfSSL_FreeX509(WOLFSSL_X509* x509) - { - WOLFSSL_ENTER("wolfSSL_FreeX509"); - FreeX509(x509); + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + if (ssl->peerCertChain == NULL) + wolfSSL_set_peer_cert_chain((WOLFSSL*) ssl); + sk = ssl->peerCertChain; + #else + sk = (WOLF_STACK_OF(WOLFSSL_X509)* )&ssl->session.chain; + #endif + + if (sk == NULL) { + WOLFSSL_MSG("Error: Null Peer Cert Chain"); + } + return sk; +} + +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +/* Builds up and creates a stack of peer certificates for ssl->peerCertChain + based off of the ssl session chain. Returns stack of WOLFSSL_X509 certs or + NULL on failure */ +WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) +{ + WOLFSSL_STACK* sk; + WOLFSSL_X509* x509; + int i = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain"); + if ((ssl == NULL) || (ssl->session.chain.count == 0)) + return NULL; + + sk = wolfSSL_sk_X509_new(); + i = ssl->session.chain.count-1; + for (; i >= 0; i--) { + /* For servers, the peer certificate chain does not include the peer + certificate, so do not add it to the stack */ + if (ssl->options.side == WOLFSSL_SERVER_END && i == 0) + continue; + x509 = wolfSSL_X509_new(); + if (x509 == NULL) { + WOLFSSL_MSG("Error Creating X509"); + return NULL; + } + ret = DecodeToX509(x509, ssl->session.chain.certs[i].buffer, + ssl->session.chain.certs[i].length); + + if (ret != 0 || wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error decoding cert"); + wolfSSL_X509_free(x509); + wolfSSL_sk_X509_free(sk); + return NULL; + } } + if (sk == NULL) { + WOLFSSL_MSG("Null session chain"); + } + /* This is Free'd when ssl is Free'd */ + ssl->peerCertChain = sk; + return sk; +} +#endif /* OPENSSL_ALL || WOLFSSL_QT */ +#endif /* SESSION_CERTS */ +#ifndef NO_CERTS +#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \ + defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + +/* user externally called free X509, if dynamic go ahead with free, otherwise + * don't */ +static void ExternalFreeX509(WOLFSSL_X509* x509) +{ + int doFree = 0; + + WOLFSSL_ENTER("ExternalFreeX509"); + if (x509) { + if (x509->dynamicMemory) { + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + if (wc_LockMutex(&x509->refMutex) != 0) { + WOLFSSL_MSG("Couldn't lock x509 mutex"); + } + /* only free if all references to it are done */ + x509->refCount--; + if (x509->refCount == 0) + doFree = 1; + wc_UnLockMutex(&x509->refMutex); + #else + doFree = 1; + #endif /* OPENSSL_EXTRA */ + + if (doFree) { + FreeX509(x509); + XFREE(x509, x509->heap, DYNAMIC_TYPE_X509); + } + } else { + WOLFSSL_MSG("free called on non dynamic object, not freeing"); + } + } +} + +/* Frees an external WOLFSSL_X509 structure */ +WOLFSSL_ABI +void wolfSSL_X509_free(WOLFSSL_X509* x509) +{ + WOLFSSL_ENTER("wolfSSL_FreeX509"); + ExternalFreeX509(x509); +} + + +/* copy name into in buffer, at most sz bytes, if buffer is null will + malloc buffer, call responsible for freeing */ +WOLFSSL_ABI +char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME* name, char* in, int 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; + + if (!in) { + #ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MSG("Using static memory -- please pass in a buffer"); + return NULL; + #else + in = (char*)XMALLOC(name->sz, NULL, DYNAMIC_TYPE_OPENSSL); + if (!in ) return in; + copySz = name->sz; + #endif + } + + if (copySz <= 0) + return in; + + XMEMCPY(in, name->name, copySz - 1); + in[copySz - 1] = 0; + + return in; +} + +#if defined(OPENSSL_EXTRA) && defined(XSNPRINTF) +/* Copies X509 subject name into a buffer, with comma-separated name entries + * (matching OpenSSL v1.0.0 format) + * Example Output for Issuer: + * + * C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting, + * CN=www.wolfssl.com, emailAddress=info@wolfssl.com + */ +char* wolfSSL_X509_get_name_oneline(WOLFSSL_X509_NAME* name, char* in, int sz) +{ + WOLFSSL_X509_NAME_ENTRY* entry; + int nameSz, strSz, count, i, idx = 0; + int totalSz = 0; + char *str; + char tmpBuf[256]; + char buf[80]; + const char* sn; + WOLFSSL_ENTER("wolfSSL_X509_get_name_oneline"); + + if (name == NULL) { + WOLFSSL_MSG("wolfSSL_X509_get_subject_name failed"); + return NULL; + } + #ifdef WOLFSSL_STATIC_MEMORY + if (!in) { + WOLFSSL_MSG("Using static memory -- please pass in a buffer"); + return NULL; + } + #endif + + tmpBuf[0] = '\0'; /* Make sure tmpBuf is NULL terminated */ + /* Loop through X509 name entries and copy new format to buffer */ + count = wolfSSL_X509_NAME_entry_count(name); + for (i = 0; i < count; i++) { + + /* Get name entry and size */ + entry = wolfSSL_X509_NAME_get_entry(name, i); + if (entry == NULL) { + WOLFSSL_MSG("X509_NAME_get_entry failed"); + return NULL; + } + nameSz = wolfSSL_X509_NAME_get_text_by_NID(name, entry->nid, buf, + sizeof(buf)); + if (nameSz < 0) { + WOLFSSL_MSG("X509_NAME_get_text_by_NID failed"); + return NULL; + } + + /* Get short name */ + sn = wolfSSL_OBJ_nid2sn(entry->nid); + if (sn == NULL) { + WOLFSSL_MSG("OBJ_nid2sn failed"); + return NULL; + } + + /* Copy sn and name text to buffer + * Add extra strSz for '=', ',', ' ' and '\0' characters in XSNPRINTF. + */ + if (i != count - 1) { + strSz = (int)XSTRLEN(sn) + nameSz + 4; + totalSz+= strSz; + str = (char*)XMALLOC(strSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) { + WOLFSSL_MSG("Memory error"); + return NULL; + } + XSNPRINTF(str, strSz, "%s=%s, ", sn, buf); + } + else { + /* Copy last name entry + * Add extra strSz for '=' and '\0' characters in XSNPRINTF. + */ + strSz = (int)XSTRLEN(sn) + nameSz + 2; + totalSz+= strSz; + str = (char*)XMALLOC(strSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) { + WOLFSSL_MSG("Memory error"); + return NULL; + } + XSNPRINTF(str, strSz, "%s=%s", sn, buf); + } + /* Copy string to tmpBuf */ + XSTRNCAT(tmpBuf, str, strSz); + idx += strSz; + XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + /* Allocate space based on total string size if no buffer was provided */ + if (!in) { + in = (char*)XMALLOC(totalSz+1, NULL, DYNAMIC_TYPE_OPENSSL); + if (in == NULL) { + WOLFSSL_MSG("Memory error"); + return in; + } + } + else { + if (totalSz > sz) { + WOLFSSL_MSG("Memory error"); + return NULL; + } + } + + XMEMCPY(in, tmpBuf, totalSz); + in[totalSz] = '\0'; + + return in; +} +#endif + + +/* Wraps wolfSSL_X509_d2i + * + * returns a WOLFSSL_X509 structure pointer on success and NULL on fail + */ +WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509, const unsigned char** in, + int len) +{ + WOLFSSL_X509* newX509 = NULL; + + newX509 = wolfSSL_X509_d2i(x509, *in, len); + if (newX509 != NULL) { + *in += newX509->derCert->length; + } + return newX509; +} + + +WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len) +{ + WOLFSSL_X509 *newX509 = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_d2i"); + + if (in != NULL && len != 0) { + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert; + #else + DecodedCert cert[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return NULL; + #endif + + InitDecodedCert(cert, (byte*)in, len, NULL); + if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) { + newX509 = wolfSSL_X509_new(); + if (newX509 != NULL) { + if (CopyDecodedToX509(newX509, cert) != 0) { + wolfSSL_X509_free(newX509); + newX509 = NULL; + } + } + } + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + #endif + } + + if (x509 != NULL) + *x509 = newX509; + + return newX509; +} +#endif /* KEEP_PEER_CERT || SESSION_CERTS || OPENSSL_EXTRA || + OPENSSL_EXTRA_X509_SMALL */ + + + +#if defined(OPENSSL_ALL) || defined(KEEP_OUR_CERT) || defined(KEEP_PEER_CERT) || \ + defined(SESSION_CERTS) /* return the next, if any, altname from the peer cert */ + WOLFSSL_ABI char* wolfSSL_X509_get_next_altname(WOLFSSL_X509* cert) { char* ret = NULL; @@ -8635,21 +17303,6 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return ret; } - - WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert) - { - WOLFSSL_ENTER("X509_get_issuer_name"); - return &cert->issuer; - } - - - WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert) - { - WOLFSSL_ENTER("X509_get_subject_name"); - return &cert->subject; - } - - int wolfSSL_X509_get_isCA(WOLFSSL_X509* x509) { int isCA = 0; @@ -8664,8 +17317,2624 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return isCA; } + int wolfSSL_X509_get_signature(WOLFSSL_X509* x509, + unsigned char* buf, int* bufSz) + { + WOLFSSL_ENTER("wolfSSL_X509_get_signature"); + if (x509 == NULL || bufSz == NULL || (*bufSz < (int)x509->sig.length && + buf != NULL)) + return WOLFSSL_FATAL_ERROR; + + if (buf != NULL) + XMEMCPY(buf, x509->sig.buffer, x509->sig.length); + *bufSz = x509->sig.length; + + return WOLFSSL_SUCCESS; + } + + + /* Getter function that copies over the DER public key buffer to "buf" and + * sets the size in bufSz. If "buf" is NULL then just bufSz is set to needed + * buffer size. "bufSz" passed in should initially be set by the user to be + * the size of "buf". This gets checked to make sure the buffer is large + * enough to hold the public key. + * + * Note: this is the X.509 form of key with "header" info. + * return WOLFSSL_SUCCESS on success + */ + int wolfSSL_X509_get_pubkey_buffer(WOLFSSL_X509* x509, + unsigned char* buf, int* bufSz) + { + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert; + #else + DecodedCert cert[1]; + #endif + word32 idx; + const byte* der; + int length = 0; + int ret, derSz = 0; + int badDate = 0; + const byte* pubKeyX509 = NULL; + int pubKeyX509Sz = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_pubkey_buffer"); + if (x509 == NULL || bufSz == NULL) { + WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", BAD_FUNC_ARG); + return WOLFSSL_FATAL_ERROR; + } + + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), + x509->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) { + WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", MEMORY_E); + return WOLFSSL_FATAL_ERROR; + } + #endif + + der = wolfSSL_X509_get_der(x509, &derSz); + InitDecodedCert(cert, der, derSz, NULL); + ret = wc_GetPubX509(cert, 0, &badDate); + if (ret >= 0) { + idx = cert->srcIdx; + pubKeyX509 = cert->source + cert->srcIdx; + ret = GetSequence(cert->source, &cert->srcIdx, &length, + cert->maxIdx); + pubKeyX509Sz = length + (cert->srcIdx - idx); + } + + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, x509->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", ret); + return WOLFSSL_FATAL_ERROR; + } + + if (buf != NULL) { + if (pubKeyX509Sz > *bufSz) { + WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", BUFFER_E); + return WOLFSSL_FATAL_ERROR; + } + XMEMCPY(buf, pubKeyX509, pubKeyX509Sz); + } + *bufSz = pubKeyX509Sz; + + return WOLFSSL_SUCCESS; + } + + + /* Getter function for the public key OID value + * return public key OID stored in WOLFSSL_X509 structure */ + int wolfSSL_X509_get_pubkey_type(WOLFSSL_X509* x509) + { + if (x509 == NULL) + return WOLFSSL_FAILURE; + return x509->pubKeyOID; + } + + /* write X509 serial number in unsigned binary to buffer + buffer needs to be at least EXTERNAL_SERIAL_SIZE (32) for all cases + return WOLFSSL_SUCCESS on success */ + int wolfSSL_X509_get_serial_number(WOLFSSL_X509* x509, + byte* in, int* inOutSz) + { + WOLFSSL_ENTER("wolfSSL_X509_get_serial_number"); + if (x509 == NULL || in == NULL || + inOutSz == NULL || *inOutSz < x509->serialSz) + return BAD_FUNC_ARG; + + XMEMCPY(in, x509->serial, x509->serialSz); + *inOutSz = x509->serialSz; + + return WOLFSSL_SUCCESS; + } + + /* not an openssl compatibility function - getting for derCert */ + const byte* wolfSSL_X509_get_der(WOLFSSL_X509* x509, int* outSz) + { + WOLFSSL_ENTER("wolfSSL_X509_get_der"); + + if (x509 == NULL || x509->derCert == NULL || outSz == NULL) + return NULL; + + *outSz = (int)x509->derCert->length; + return x509->derCert->buffer; + } + + /* used by JSSE (not a standard compatibility function) */ + /* this is not thread safe */ + WOLFSSL_ABI + const byte* wolfSSL_X509_notBefore(WOLFSSL_X509* x509) + { + static byte notBeforeData[CTC_DATE_SIZE]; /* temp buffer for date */ + WOLFSSL_ENTER("wolfSSL_X509_notBefore"); + + if (x509 == NULL) + return NULL; + + XMEMSET(notBeforeData, 0, sizeof(notBeforeData)); + notBeforeData[0] = (byte)x509->notBefore.type; + notBeforeData[1] = (byte)x509->notBefore.length; + XMEMCPY(¬BeforeData[2], x509->notBefore.data, x509->notBefore.length); + + return notBeforeData; + } + /* used by JSSE (not a standard compatibility function) */ + /* this is not thread safe */ + WOLFSSL_ABI + const byte* wolfSSL_X509_notAfter(WOLFSSL_X509* x509) + { + static byte notAfterData[CTC_DATE_SIZE]; /* temp buffer for date */ + WOLFSSL_ENTER("wolfSSL_X509_notAfter"); + + if (x509 == NULL) + return NULL; + + XMEMSET(notAfterData, 0, sizeof(notAfterData)); + notAfterData[0] = (byte)x509->notAfter.type; + notAfterData[1] = (byte)x509->notAfter.length; + XMEMCPY(¬AfterData[2], x509->notAfter.data, x509->notAfter.length); + + return notAfterData; + } + + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) && !defined(NO_WOLFSSL_STUB) + WOLFSSL_ASN1_TIME* wolfSSL_X509_gmtime_adj(WOLFSSL_ASN1_TIME *s, long adj) + { + (void) s; + (void) adj; + WOLFSSL_STUB("wolfSSL_X509_gmtime_adj"); + return NULL; + } + #endif + + /* get the buffer to be signed (tbs) from the WOLFSSL_X509 certificate + * + * outSz : gets set to the size of the buffer + * returns a pointer to the internal buffer at the location of TBS on + * on success and NULL on failure. + */ + const unsigned char* wolfSSL_X509_get_tbs(WOLFSSL_X509* x509, int* outSz) + { + int sz = 0, len; + unsigned int idx = 0, tmpIdx; + const unsigned char* der = NULL; + const unsigned char* tbs = NULL; + + if (x509 == NULL || outSz == NULL) { + return NULL; + } + + der = wolfSSL_X509_get_der(x509, &sz); + if (der == NULL) { + return NULL; + } + + if (GetSequence(der, &idx, &len, sz) < 0) { + return NULL; + } + tbs = der + idx; + tmpIdx = idx; + if (GetSequence(der, &idx, &len, sz) < 0) { + return NULL; + } + *outSz = len + (idx - tmpIdx); + return tbs; + } + + int wolfSSL_X509_version(WOLFSSL_X509* x509) + { + WOLFSSL_ENTER("wolfSSL_X509_version"); + + if (x509 == NULL) + return 0; + + return x509->version; + } + +#ifdef WOLFSSL_SEP + +/* copy oid into in buffer, at most *inOutSz bytes, if buffer is null will + malloc buffer, call responsible for freeing. Actual size returned in + *inOutSz. Requires inOutSz be non-null */ +byte* wolfSSL_X509_get_device_type(WOLFSSL_X509* x509, byte* in, int *inOutSz) +{ + int copySz; + + WOLFSSL_ENTER("wolfSSL_X509_get_dev_type"); + if (inOutSz == NULL) return NULL; + if (!x509->deviceTypeSz) return in; + + copySz = min(*inOutSz, x509->deviceTypeSz); + + if (!in) { + #ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MSG("Using static memory -- please pass in a buffer"); + return NULL; + #else + in = (byte*)XMALLOC(x509->deviceTypeSz, 0, DYNAMIC_TYPE_OPENSSL); + if (!in) return in; + copySz = x509->deviceTypeSz; + #endif + } + + XMEMCPY(in, x509->deviceType, copySz); + *inOutSz = copySz; + + return in; +} + + +byte* wolfSSL_X509_get_hw_type(WOLFSSL_X509* x509, byte* in, int* inOutSz) +{ + int copySz; + + WOLFSSL_ENTER("wolfSSL_X509_get_hw_type"); + if (inOutSz == NULL) return NULL; + if (!x509->hwTypeSz) return in; + + copySz = min(*inOutSz, x509->hwTypeSz); + + if (!in) { + #ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MSG("Using static memory -- please pass in a buffer"); + return NULL; + #else + in = (byte*)XMALLOC(x509->hwTypeSz, 0, DYNAMIC_TYPE_OPENSSL); + if (!in) return in; + copySz = x509->hwTypeSz; + #endif + } + + XMEMCPY(in, x509->hwType, copySz); + *inOutSz = copySz; + + return in; +} + + +byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in, + int* inOutSz) +{ + int copySz; + + WOLFSSL_ENTER("wolfSSL_X509_get_hw_serial_number"); + if (inOutSz == NULL) return NULL; + if (!x509->hwTypeSz) return in; + + copySz = min(*inOutSz, x509->hwSerialNumSz); + + if (!in) { + #ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MSG("Using static memory -- please pass in a buffer"); + return NULL; + #else + in = (byte*)XMALLOC(x509->hwSerialNumSz, 0, DYNAMIC_TYPE_OPENSSL); + if (!in) return in; + copySz = x509->hwSerialNumSz; + #endif + } + + XMEMCPY(in, x509->hwSerialNum, copySz); + *inOutSz = copySz; + + return in; +} + +#endif /* WOLFSSL_SEP */ + +/* require OPENSSL_EXTRA since wolfSSL_X509_free is wrapped by OPENSSL_EXTRA */ +#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA) + +WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notBefore(const WOLFSSL_X509* x509) +{ + WOLFSSL_ENTER("wolfSSL_X509_get_notBefore"); + + if (x509 == NULL) + return NULL; + + return (WOLFSSL_ASN1_TIME*)&x509->notBefore; +} + + +WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notAfter(const WOLFSSL_X509* x509) +{ + WOLFSSL_ENTER("wolfSSL_X509_get_notAfter"); + + if (x509 == NULL) + return NULL; + + return (WOLFSSL_ASN1_TIME*)&x509->notAfter; +} + + +/* return 1 on success 0 on fail */ +int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509) +{ + WOLFSSL_STACK* node; + WOLFSSL_ENTER("wolfSSL_sk_X509_push"); + + if (sk == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.x509 == NULL) { + sk->data.x509 = x509; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_X509); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new x509 onto head of stack */ + node->data.x509 = sk->data.x509; + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->data.x509 = x509; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + + +WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) { + WOLFSSL_STACK* node; + WOLFSSL_X509* x509; + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + x509 = sk->data.x509; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.x509 = node->data.x509; + sk->next = node->next; + XFREE(node, NULL, DYNAMIC_TYPE_X509); + } + else { /* last x509 in stack */ + sk->data.x509 = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return x509; +} + +/* Getter function for WOLFSSL_X509 pointer + * + * sk is the stack to retrieve pointer from + * i is the index value in stack + * + * returns a pointer to a WOLFSSL_X509 structure on success and NULL on + * fail + */ +WOLFSSL_X509* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)* sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_value"); + + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.x509; +} + +WOLFSSL_X509* wolfSSL_sk_X509_shift(WOLF_STACK_OF(WOLFSSL_X509)* sk) +{ + return wolfSSL_sk_X509_pop(sk); +} + +#ifndef NO_WOLFSSL_STUB +void* wolfSSL_sk_X509_OBJECT_value(WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* sk, int x) +{ + (void) sk; + (void) x; + return NULL; +} +#endif + + +/* Free's all nodes in X509 stack. This is different then wolfSSL_sk_X509_free + * in that it allows for choosing the function to use when freeing an X509s. + * + * sk stack to free nodes in + * f X509 free function + */ +void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, + void (*f) (WOLFSSL_X509*)) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_X509_pop_free"); + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (node && sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + if (f) + f(tmp->data.x509); + else + wolfSSL_X509_free(tmp->data.x509); + tmp->data.x509 = NULL; + XFREE(tmp, NULL, DYNAMIC_TYPE_X509); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + if (f) + f(sk->data.x509); + else + wolfSSL_X509_free(sk->data.x509); + sk->data.x509 = NULL; + } + XFREE(sk, NULL, DYNAMIC_TYPE_X509); +} + + +/* free structure for x509 stack */ +void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509)* sk) +{ + wolfSSL_sk_X509_pop_free(sk, NULL); +} + +#endif /* NO_CERTS && OPENSSL_EXTRA */ + +#if defined(OPENSSL_ALL) || defined (WOLFSSL_QT) +/* return 1 on success 0 on fail */ +int wolfSSL_sk_ACCESS_DESCRIPTION_push(WOLF_STACK_OF(ACCESS_DESCRIPTION)* sk, + WOLFSSL_ACCESS_DESCRIPTION* access) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_ACCESS_DESCRIPTION_push"); + + if (sk == NULL || access == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.access == NULL) { + sk->data.access = access; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_ASN1); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.access = sk->data.access; + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->data.access = access; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + +/* Frees all nodes in ACCESS_DESCRIPTION stack +* +* sk stack of nodes to free +* f free function to use, not called with wolfSSL +*/ +void wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(WOLFSSL_STACK* sk, + void (*f) (WOLFSSL_ACCESS_DESCRIPTION*)) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_ACCESS_DESCRIPTION_pop_free"); + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (node && sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + if (f) + f(tmp->data.access); + else + wolfSSL_ACCESS_DESCRIPTION_free(tmp->data.access); + tmp->data.access = NULL; + XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + if (f) + f(sk->data.access); + else { + if(sk->data.access->method) { + + wolfSSL_ASN1_OBJECT_free(sk->data.access->method); + } + if(sk->data.access->location) { + wolfSSL_GENERAL_NAME_free(sk->data.access->location); + } + } + sk->data.access = NULL; + } + XFREE(sk, NULL, DYNAMIC_TYPE_ASN1); +} + +void wolfSSL_sk_ACCESS_DESCRIPTION_free(WOLFSSL_STACK* sk) +{ + wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(sk, NULL); +} + +void wolfSSL_ACCESS_DESCRIPTION_free(WOLFSSL_ACCESS_DESCRIPTION* access) +{ + WOLFSSL_ENTER("wolfSSL_ACCESS_DESCRIPTION_free"); + if (access == NULL) + return; + + if (access->method) + wolfSSL_ASN1_OBJECT_free(access->method); + if (access->location) + wolfSSL_GENERAL_NAME_free(access->location); + + /* access = NULL, don't try to access or double free it */ +} +#endif #ifdef OPENSSL_EXTRA + +/* create a generic wolfSSL stack node + * returns a new WOLFSSL_STACK structure on success */ +WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap) +{ + WOLFSSL_STACK* sk; + WOLFSSL_ENTER("wolfSSL_sk_new_node"); + + sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), heap, + DYNAMIC_TYPE_OPENSSL); + if (sk != NULL) { + XMEMSET(sk, 0, sizeof(*sk)); + sk->heap = heap; + } + + return sk; +} + +/* free's node but does not free internal data such as in->data.x509 */ +void wolfSSL_sk_free_node(WOLFSSL_STACK* in) +{ + if (in != NULL) { + XFREE(in, in->heap, DYNAMIC_TYPE_OPENSSL); + } +} + +/* pushes node "in" onto "stack" and returns pointer to the new stack on success + * also handles internal "num" for number of nodes on stack + * return WOLFSSL_SUCCESS on success + */ +int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in) +{ + if (stack == NULL || in == NULL) { + return WOLFSSL_FAILURE; + } + + if (*stack == NULL) { + in->num = 1; + *stack = in; + return WOLFSSL_SUCCESS; + } + + in->num = (*stack)->num + 1; + in->next = *stack; + *stack = in; + return WOLFSSL_SUCCESS; +} + +/* return 1 on success 0 on fail */ +int wolfSSL_sk_push(WOLFSSL_STACK* sk, const void *data) +{ + int ret = WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_sk_push"); + + switch (sk->type) { + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + case STACK_TYPE_X509: + ret = wolfSSL_sk_X509_push(sk, (WOLFSSL_X509*) data); + break; + #ifndef NO_WOLFSSL_STUB + case STACK_TYPE_CIPHER: + ret = wolfSSL_sk_CIPHER_push(sk, (WOLFSSL_CIPHER*) data); + break; + #endif + case STACK_TYPE_GEN_NAME: + ret = wolfSSL_sk_ASN1_OBJECT_push(sk, (WOLFSSL_ASN1_OBJECT*) data); + break; + case STACK_TYPE_ACCESS_DESCRIPTION: + ret = wolfSSL_sk_ACCESS_DESCRIPTION_push(sk, + (WOLFSSL_ACCESS_DESCRIPTION*) data); + break; + case STACK_TYPE_NULL: + ret = wolfSSL_sk_GENERIC_push(sk, (void*) data); + break; + case STACK_TYPE_OBJ: + ret = wolfSSL_sk_ASN1_OBJECT_push(sk, (WOLFSSL_ASN1_OBJECT*) data); + break; + #endif + default: + ret = wolfSSL_sk_ASN1_OBJECT_push(sk, (WOLFSSL_ASN1_OBJECT*) data); + break; + } + + return ret; +} + +/* Creates and returns new GENERAL_NAME structure */ +WOLFSSL_GENERAL_NAME* wolfSSL_GENERAL_NAME_new(void) +{ + WOLFSSL_GENERAL_NAME* gn; + WOLFSSL_ENTER("GENERAL_NAME_new"); + + gn = (WOLFSSL_GENERAL_NAME*)XMALLOC(sizeof(WOLFSSL_GENERAL_NAME), NULL, + DYNAMIC_TYPE_ASN1); + if (gn == NULL) { + return NULL; + } + XMEMSET(gn, 0, sizeof(WOLFSSL_GENERAL_NAME)); + + gn->d.ia5 = wolfSSL_ASN1_STRING_new(); + if (gn->d.ia5 == NULL) { + WOLFSSL_MSG("Issue creating ASN1_STRING struct"); + wolfSSL_GENERAL_NAME_free(gn); + return NULL; + } + return gn; +} + +/* return 1 on success 0 on fail */ +int wolfSSL_sk_GENERAL_NAME_push(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)* sk, + WOLFSSL_GENERAL_NAME* gn) +{ + WOLFSSL_STACK* node; + WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_push"); + + if (sk == NULL || gn == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.gn == NULL) { + sk->data.gn = gn; + sk->num += 1; + + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_ASN1); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.gn = sk->data.gn; + node->next = sk->next; + sk->next = node; + sk->data.gn = gn; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + +/* Returns the general name at index i from the stack + * + * sk stack to get general name from + * idx index to get + * + * return a pointer to the internal node of the stack + */ +WOLFSSL_GENERAL_NAME* wolfSSL_sk_GENERAL_NAME_value(WOLFSSL_STACK* sk, int idx) +{ + WOLFSSL_STACK* ret; + + if (sk == NULL) { + return NULL; + } + + ret = wolfSSL_sk_get_node(sk, idx); + if (ret != NULL) { + return ret->data.gn; + } + return NULL; +} + +/* Gets the number of nodes in the stack + * + * sk stack to get the number of nodes from + * + * returns the number of nodes, -1 if no nodes + */ +int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_num"); + + if (sk == NULL) { + return -1; + } + + return (int)sk->num; +} + +/* Frees all nodes in a GENERAL NAME stack + * + * sk stack of nodes to free + * f free function to use, not called with wolfSSL + */ +void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk, + void (*f) (WOLFSSL_GENERAL_NAME*)) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_pop_free"); + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (node && sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + if (f) + f(tmp->data.gn); + else + wolfSSL_GENERAL_NAME_free(tmp->data.gn); + XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + if (f) + f(sk->data.gn); + else + wolfSSL_GENERAL_NAME_free(sk->data.gn); + } + XFREE(sk, NULL, DYNAMIC_TYPE_ASN1); +} + +void wolfSSL_sk_GENERAL_NAME_free(WOLFSSL_STACK* sk) +{ + WOLFSSL_ENTER("sk_GENERAL_NAME_free"); + wolfSSL_sk_GENERAL_NAME_pop_free(sk, NULL); +} + + +/* returns the number of nodes in stack on success and WOLFSSL_FATAL_ERROR + * on fail */ +int wolfSSL_sk_ACCESS_DESCRIPTION_num(WOLFSSL_STACK* sk) +{ + if (sk == NULL) { + return WOLFSSL_FATAL_ERROR; + } + + return (int)sk->num; +} + +#ifndef NO_WOLFSSL_STUB +/* similar to call to sk_ACCESS_DESCRIPTION_pop_free */ +void wolfSSL_AUTHORITY_INFO_ACCESS_free( + WOLF_STACK_OF(WOLFSSL_ACCESS_DESCRIPTION)* sk) +{ + WOLFSSL_STUB("wolfSSL_AUTHORITY_INFO_ACCESS_free"); + (void)sk; +} +#endif + +/* returns the node at index "idx", NULL if not found */ +WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx) +{ + int i; + WOLFSSL_STACK* ret = NULL; + WOLFSSL_STACK* current; + + current = sk; + for (i = 0; i <= idx && current != NULL; i++) { + if (i == idx) { + ret = current; + break; + } + current = current->next; + } + return ret; +} + +/* returns NULL on fail and pointer to internal data on success */ +WOLFSSL_ACCESS_DESCRIPTION* wolfSSL_sk_ACCESS_DESCRIPTION_value( + WOLFSSL_STACK* sk, int idx) +{ + WOLFSSL_STACK* ret; + + if (sk == NULL) { + return NULL; + } + + ret = wolfSSL_sk_get_node(sk, idx); + if (ret != NULL) { + return ret->data.access; + } + return NULL; +} + +/* Frees GENERAL_NAME objects. +*/ +void wolfSSL_GENERAL_NAME_free(WOLFSSL_GENERAL_NAME* name) +{ + WOLFSSL_ENTER("wolfSSL_GENERAL_NAME_Free"); + if(name != NULL) { + if (name->d.dNSName != NULL) { + wolfSSL_ASN1_STRING_free(name->d.dNSName); + name->d.dNSName = NULL; + } + if (name->d.uniformResourceIdentifier != NULL) { + wolfSSL_ASN1_STRING_free(name->d.uniformResourceIdentifier); + name->d.uniformResourceIdentifier = NULL; + } + if (name->d.iPAddress != NULL) { + wolfSSL_ASN1_STRING_free(name->d.iPAddress); + name->d.iPAddress = NULL; + } + if (name->d.registeredID != NULL) { + wolfSSL_ASN1_OBJECT_free(name->d.registeredID); + name->d.registeredID = NULL; + } + if (name->d.ia5 != NULL) { + wolfSSL_ASN1_STRING_free(name->d.ia5); + name->d.ia5 = NULL; + } + XFREE(name, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +void wolfSSL_GENERAL_NAMES_free(WOLFSSL_GENERAL_NAMES *gens) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_GENERAL_NAMES_free"); + + if (gens == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = gens->next; + while (gens->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + wolfSSL_ASN1_OBJECT_free(tmp->data.obj); + XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1); + gens->num -= 1; + } + + /* free head of stack */ + if (gens->num == 1) { + wolfSSL_ASN1_OBJECT_free(gens->data.obj); + } + XFREE(gens, NULL, DYNAMIC_TYPE_ASN1); +} + +#if defined(OPENSSL_ALL) +WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* wolfSSL_sk_X509_EXTENSION_new_null(void) +{ + WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL); + if (sk) { + sk->type = STACK_TYPE_X509_EXT; + } + + return (WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)*)sk;; +} + +/* returns the number of nodes on the stack */ +int wolfSSL_sk_X509_EXTENSION_num(WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk) +{ + if (sk != NULL) { + return (int)sk->num; + } + return WOLFSSL_FATAL_ERROR; +} + + +/* returns null on failure and pointer to internal value on success */ +WOLFSSL_X509_EXTENSION* wolfSSL_sk_X509_EXTENSION_value( + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, int idx) +{ + WOLFSSL_STACK* ret; + + if (sk == NULL) { + return NULL; + } + + ret = wolfSSL_sk_get_node(sk, idx); + if (ret != NULL) { + return ret->data.ext; + } + return NULL; +} + +/* frees all of the nodes and the values in stack */ +void wolfSSL_sk_X509_EXTENSION_pop_free( + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, + void (*f) (WOLFSSL_X509_EXTENSION*)) +{ + WOLFSSL_STACK* current; + + if (sk == NULL) { + return; + } + + current = sk; + while (current != NULL) { + WOLFSSL_STACK* toFree = current; + current = current->next; + + if (f) + f(toFree->data.ext); + wolfSSL_sk_free_node(toFree); + } +} + +#if defined(HAVE_ECC) +/* Copies ecc_key into new WOLFSSL_EC_KEY object + * + * src : EC_KEY to duplicate. If EC_KEY is not null, create new EC_KEY and copy + * internal ecc_key from src to dup. + * + * Returns pointer to duplicate EC_KEY. + */ +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src) +{ + WOLFSSL_EC_KEY *dup; + ecc_key *key, *srcKey; + int ret; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_dup"); + + if (src == NULL || src->internal == NULL || src->group == NULL || \ + src->pub_key == NULL || src->priv_key == NULL) { + + WOLFSSL_MSG("src NULL error"); + return NULL; + } + + dup = wolfSSL_EC_KEY_new(); + if (dup == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new error"); + return NULL; + } + + key = (ecc_key*)dup->internal; + if (key == NULL) { + WOLFSSL_MSG("ecc_key NULL error"); + wolfSSL_EC_KEY_free(dup); + return NULL; + } + srcKey = (ecc_key*)src->internal; + + /* ecc_key */ + /* copy pubkey */ + ret = wc_ecc_copy_point(&srcKey->pubkey, &key->pubkey); + if (ret != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_copy_point error"); + wolfSSL_EC_KEY_free(dup); + return NULL; + } + + /* copy private key k */ + ret = mp_copy(&srcKey->k, &key->k); + if (ret != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + wolfSSL_EC_KEY_free(dup); + return NULL; + } + + /* copy domain parameters */ + if (srcKey->dp) { + ret = wc_ecc_set_curve(key, 0, srcKey->dp->id); + if (ret != 0) { + WOLFSSL_MSG("wc_ecc_set_curve error"); + return NULL; + } + } + + key->type = srcKey->type; + key->idx = srcKey->idx; + key->state = srcKey->state; + key->flags = srcKey->flags; + + /* Copy group */ + if (dup->group == NULL) { + WOLFSSL_MSG("EC_GROUP_new_by_curve_name error"); + wolfSSL_EC_KEY_free(dup); + return NULL; + } + + dup->group->curve_idx = src->group->curve_idx; + dup->group->curve_nid = src->group->curve_nid; + dup->group->curve_oid = src->group->curve_oid; + + /* Copy public key */ + if (src->pub_key->internal == NULL || dup->pub_key->internal == NULL) { + WOLFSSL_MSG("NULL pub_key error"); + wolfSSL_EC_KEY_free(dup); + return NULL; + } + + /* Copy public key internal */ + ret = wc_ecc_copy_point((ecc_point*)src->pub_key->internal, \ + (ecc_point*)dup->pub_key->internal); + if (ret != MP_OKAY) { + WOLFSSL_MSG("ecc_copy_point error"); + wolfSSL_EC_KEY_free(dup); + return NULL; + } + + /* Copy X, Y, Z */ + dup->pub_key->X = wolfSSL_BN_dup(src->pub_key->X); + if (!dup->pub_key->X && src->pub_key->X) { + WOLFSSL_MSG("Error copying EC_POINT"); + wolfSSL_EC_KEY_free(dup); + return NULL; + } + dup->pub_key->Y = wolfSSL_BN_dup(src->pub_key->Y); + if (!dup->pub_key->Y && src->pub_key->Y) { + WOLFSSL_MSG("Error copying EC_POINT"); + wolfSSL_EC_KEY_free(dup); + return NULL; + } + dup->pub_key->Z = wolfSSL_BN_dup(src->pub_key->Z); + if (!dup->pub_key->Z && src->pub_key->Z) { + WOLFSSL_MSG("Error copying EC_POINT"); + wolfSSL_EC_KEY_free(dup); + return NULL; + } + + dup->pub_key->inSet = src->pub_key->inSet; + dup->pub_key->exSet = src->pub_key->exSet; + + /* Copy private key */ + if (src->priv_key->internal == NULL || dup->priv_key->internal == NULL) { + WOLFSSL_MSG("NULL priv_key error"); + wolfSSL_EC_KEY_free(dup); + return NULL; + } + + /* Free priv_key before call to dup function */ + wolfSSL_BN_free(dup->priv_key); + dup->priv_key = wolfSSL_BN_dup(src->priv_key); + if (dup->priv_key == NULL) { + WOLFSSL_MSG("BN_dup error"); + wolfSSL_EC_KEY_free(dup); + return NULL; + } + + return dup; + +} +#endif /* HAVE_ECC */ + +#if !defined(NO_DH) +int wolfSSL_DH_check(const WOLFSSL_DH *dh, int *codes) +{ + int isPrime = MP_NO, codeTmp = 0; + WC_RNG rng; + + WOLFSSL_ENTER("wolfSSL_DH_check"); + if (dh == NULL){ + return WOLFSSL_FAILURE; + } + + if (dh->g == NULL || dh->g->internal == NULL){ + codeTmp = DH_NOT_SUITABLE_GENERATOR; + } + + if (dh->p == NULL || dh->p->internal == NULL){ + codeTmp = DH_CHECK_P_NOT_PRIME; + } + else + { + /* test if dh->p has prime */ + if (wc_InitRng(&rng) == 0){ + mp_prime_is_prime_ex((mp_int*)dh->p->internal,8,&isPrime,&rng); + } + else { + WOLFSSL_MSG("Error initializing rng\n"); + return WOLFSSL_FAILURE; + } + wc_FreeRng(&rng); + if (isPrime != MP_YES){ + codeTmp = DH_CHECK_P_NOT_PRIME; + } + } + /* User may choose to enter NULL for codes if they don't want to check it*/ + if (codes != NULL){ + *codes = codeTmp; + } + + /* if codeTmp was set,some check was flagged invalid */ + if (codeTmp){ + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* Converts DER encoded DH parameters to a WOLFSSL_DH structure. + * + * dh : structure to copy DH parameters into. + * pp : DER encoded DH parameters + * length : length to copy + * + * Returns pointer to WOLFSSL_DH structure on success, or NULL on failure + */ +WOLFSSL_DH *wolfSSL_d2i_DHparams(WOLFSSL_DH **dh, const unsigned char **pp, + long length) +{ + WOLFSSL_DH *newDH = NULL; + int ret; + word32 idx = 0; + + WOLFSSL_ENTER("wolfSSL_d2i_DHparams"); + + if (pp == NULL || length <= 0) { + WOLFSSL_MSG("bad argument"); + return NULL; + } + + if ((newDH = wolfSSL_DH_new()) == NULL) { + WOLFSSL_MSG("wolfSSL_DH_new() failed"); + return NULL; + } + + ret = wc_DhKeyDecode(*pp, &idx, (DhKey*)newDH->internal, (word32)length); + if (ret != 0) { + WOLFSSL_MSG("DhKeyDecode() failed"); + wolfSSL_DH_free(newDH); + return NULL; + } + newDH->inSet = 1; + + if (SetDhExternal(newDH) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDhExternal failed"); + wolfSSL_DH_free(newDH); + return NULL; + } + + *pp += length; + if (dh != NULL){ + *dh = newDH; + } + + return newDH; +} + +/* Converts internal WOLFSSL_DH structure to DER encoded DH. + * + * dh : structure to copy DH parameters from. + * out : DER buffer for DH parameters + * + * Returns size of DER on success and WOLFSSL_FAILURE if error + */ +int wolfSSL_i2d_DHparams(const WOLFSSL_DH *dh, unsigned char **out) +{ + word32 len; + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_i2d_DHparams"); + + if (dh == NULL) { + WOLFSSL_MSG("Bad parameters"); + return WOLFSSL_FAILURE; + } + + /* Get total length */ + len = 2 + mp_leading_bit((mp_int*)dh->p->internal) + + mp_unsigned_bin_size((mp_int*)dh->p->internal) + + 2 + mp_leading_bit((mp_int*)dh->g->internal) + + mp_unsigned_bin_size((mp_int*)dh->g->internal); + + /* Two bytes required for length if ASN.1 SEQ data greater than 127 bytes + * and less than 256 bytes. + */ + len = ((len > 127) ? 2 : 1) + len; + + if (out != NULL && *out != NULL) { + ret = StoreDHparams(*out, &len, (mp_int*)dh->p->internal, + (mp_int*)dh->g->internal); + if (ret != MP_OKAY) { + WOLFSSL_MSG("StoreDHparams error"); + len = 0; + } + else{ + *out += len; + } + } + return (int)len; +} +#endif /* !NO_DH */ + +#endif /* OPENSSL_ALL */ + +#endif /* OPENSSL_EXTRA */ + +#ifndef NO_FILESYSTEM + +#ifndef NO_STDIO_FILESYSTEM + +WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file) +{ + WOLFSSL_X509* newX509 = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_d2i_fp"); + + if (file != XBADFILE) { + byte* fileBuffer = NULL; + long sz = 0; + + if (XFSEEK(file, 0, XSEEK_END) != 0) + return NULL; + sz = XFTELL(file); + XREWIND(file); + + if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { + WOLFSSL_MSG("X509_d2i file size error"); + return NULL; + } + + fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); + if (fileBuffer != NULL) { + 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); + } + } + + if (x509 != NULL) + *x509 = newX509; + + return newX509; +} + +#endif /* NO_STDIO_FILESYSTEM */ + +WOLFSSL_ABI +WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format) +{ +#ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force heap usage */ +#else + byte staticBuffer[FILE_BUFFER_SIZE]; +#endif + byte* fileBuffer = staticBuffer; + int dynamic = 0; + int ret; + long sz = 0; + XFILE file; + + WOLFSSL_X509* x509 = NULL; + + /* Check the inputs */ + if ((fname == NULL) || + (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM)) + return NULL; + + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) + return NULL; + + if (XFSEEK(file, 0, XSEEK_END) != 0){ + XFCLOSE(file); + return NULL; + } + sz = XFTELL(file); + XREWIND(file); + + if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { + WOLFSSL_MSG("X509_load_certificate_file size error"); + XFCLOSE(file); + return NULL; + } + + if (sz > (long)sizeof(staticBuffer)) { + fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); + if (fileBuffer == NULL) { + XFCLOSE(file); + return NULL; + } + dynamic = 1; + } + + ret = (int)XFREAD(fileBuffer, 1, sz, file); + if (ret != sz) { + XFCLOSE(file); + if (dynamic) + XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); + return NULL; + } + + XFCLOSE(file); + + x509 = wolfSSL_X509_load_certificate_buffer(fileBuffer, (int)sz, format); + + if (dynamic) + XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); + + return x509; +} + +#endif /* NO_FILESYSTEM */ + + +WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer( + const unsigned char* buf, int sz, int format) +{ + int ret; + WOLFSSL_X509* x509 = NULL; + DerBuffer* der = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_load_certificate_ex"); + + if (format == WOLFSSL_FILETYPE_PEM) { + #ifdef WOLFSSL_PEM_TO_DER + if (PemToDer(buf, sz, CERT_TYPE, &der, NULL, NULL, NULL) != 0) { + FreeDer(&der); + } + #else + ret = NOT_COMPILED_IN; + #endif + } + else { + ret = AllocDer(&der, (word32)sz, CERT_TYPE, NULL); + if (ret == 0) { + XMEMCPY(der->buffer, buf, sz); + } + } + + /* At this point we want `der` to have the certificate in DER format */ + /* ready to be decoded. */ + if (der != NULL && der->buffer != NULL) { + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert; + #else + DecodedCert cert[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + if (cert != NULL) + #endif + { + InitDecodedCert(cert, der->buffer, der->length, NULL); + if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) { + x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, + DYNAMIC_TYPE_X509); + if (x509 != NULL) { + InitX509(x509, 1, NULL); + if (CopyDecodedToX509(x509, cert) != 0) { + wolfSSL_X509_free(x509); + x509 = NULL; + } + } + } + + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + #endif + } + + FreeDer(&der); + } + + return x509; +} + +#endif /* KEEP_PEER_CERT || SESSION_CERTS */ + +/* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function + KEEP_OUR_CERT is to insure ability for returning ssl certificate */ +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + defined(KEEP_OUR_CERT) +WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return NULL; + } + + if (ssl->buffers.weOwnCert) { + if (ssl->ourCert == NULL) { + if (ssl->buffers.certificate == NULL) { + WOLFSSL_MSG("Certificate buffer not set!"); + return NULL; + } + #ifndef WOLFSSL_X509_STORE_CERTS + ssl->ourCert = wolfSSL_X509_d2i(NULL, + ssl->buffers.certificate->buffer, + ssl->buffers.certificate->length); + #endif + } + return ssl->ourCert; + } + else { /* if cert not owned get parent ctx cert or return null */ + if (ssl->ctx) { + if (ssl->ctx->ourCert == NULL) { + if (ssl->ctx->certificate == NULL) { + WOLFSSL_MSG("Ctx Certificate buffer not set!"); + return NULL; + } + #ifndef WOLFSSL_X509_STORE_CERTS + ssl->ctx->ourCert = wolfSSL_X509_d2i(NULL, + ssl->ctx->certificate->buffer, + ssl->ctx->certificate->length); + #endif + ssl->ctx->ownOurCert = 1; + } + return ssl->ctx->ourCert; + } + } + + return NULL; +} +#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */ +#endif /* NO_CERTS */ + + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +#ifndef NO_ASN +void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj) +{ + if (obj == NULL) { + return; + } + if ((obj->obj != NULL) && ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0)) { + WOLFSSL_MSG("Freeing ASN1 data"); + XFREE((void*)obj->obj, obj->heap, DYNAMIC_TYPE_ASN1); + obj->obj = NULL; + } + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + if (obj->pathlen != NULL) { + wolfSSL_ASN1_INTEGER_free(obj->pathlen); + obj->pathlen = NULL; + } + #endif + if ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC) != 0) { + WOLFSSL_MSG("Freeing ASN1 OBJECT"); + XFREE(obj, NULL, DYNAMIC_TYPE_ASN1); + } +} +#endif /* NO_ASN */ +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#ifdef OPENSSL_EXTRA +#ifndef NO_ASN +WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void) +{ + WOLFSSL_ASN1_OBJECT* obj; + + obj = (WOLFSSL_ASN1_OBJECT*)XMALLOC(sizeof(WOLFSSL_ASN1_OBJECT), NULL, + DYNAMIC_TYPE_ASN1); + if (obj == NULL) { + return NULL; + } + + XMEMSET(obj, 0, sizeof(WOLFSSL_ASN1_OBJECT)); + obj->d.ia5 = &(obj->d.ia5_internal); +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + obj->d.iPAddress = &(obj->d.iPAddress_internal); +#endif + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + return obj; +} + +/* Creates and returns a new WOLFSSL_CIPHER stack. */ +WOLFSSL_STACK* wolfSSL_sk_new_asn1_obj(void) +{ + WOLFSSL_STACK* sk; + WOLFSSL_ENTER("wolfSSL_sk_new_asn1_obj"); + + sk = wolfSSL_sk_new_null(); + if (sk == NULL) + return NULL; + sk->type = STACK_TYPE_OBJ; + + return sk; +} + +/* return 1 on success 0 on fail */ +int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, + WOLFSSL_ASN1_OBJECT* obj) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_push"); + + if (sk == NULL || obj == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.obj == NULL) { + sk->data.obj = obj; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_ASN1); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.obj = sk->data.obj; + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->data.obj = obj; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + + +WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJECT_pop( + WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_ASN1_OBJECT* obj; + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + obj = sk->data.obj; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.obj = node->data.obj; + sk->next = node->next; + XFREE(node, NULL, DYNAMIC_TYPE_ASN1); + } + else { /* last obj in stack */ + sk->data.obj = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return obj; +} + + +/* Free the structure for ASN1_OBJECT stack + * + * sk stack to free nodes in + */ +void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) +{ + wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL); +} + +/* Free's all nodes in ASN1_OBJECT stack. + * This is different then wolfSSL_ASN1_OBJECT_free in that it allows for + * choosing the function to use when freeing an ASN1_OBJECT stack. + * + * sk stack to free nodes in + * f X509 free function + */ +void wolfSSL_sk_ASN1_OBJECT_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, + void (*f) (WOLFSSL_ASN1_OBJECT*)) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_pop_free"); + + if (sk == NULL) { + WOLFSSL_MSG("Parameter error"); + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (node && sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + if (f) + f(tmp->data.obj); + else + wolfSSL_ASN1_OBJECT_free(tmp->data.obj); + tmp->data.obj = NULL; + XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + if (f) + f(sk->data.obj); + else + wolfSSL_ASN1_OBJECT_free(sk->data.obj); + sk->data.obj = NULL; + } + 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(). + */ + unsigned char* buf; + unsigned char* inPtr; + int inLen; + + if (!out || !in) { + return -1; + } + + inPtr = wolfSSL_ASN1_STRING_data(in); + inLen = wolfSSL_ASN1_STRING_length(in); + if (!inPtr || inLen < 0) { + return -1; + } + buf = (unsigned char*)XMALLOC(inLen + 1, NULL, DYNAMIC_TYPE_OPENSSL); + if (!buf) { + return -1; + } + XMEMCPY(buf, inPtr, inLen + 1); + *out = buf; + return inLen; +} + +/* Returns string representation of ASN1_STRING */ +char* wolfSSL_i2s_ASN1_STRING(WOLFSSL_v3_ext_method *method, + const WOLFSSL_ASN1_STRING *s) +{ + int i; + int tmpSz = 100; + int valSz = 5; + char* tmp; + char val[5]; + unsigned char* str; + + WOLFSSL_ENTER("wolfSSL_i2s_ASN1_STRING"); + (void)method; + + if(s == NULL || s->data == NULL) { + WOLFSSL_MSG("Bad Function Argument"); + return NULL; + } + str = (unsigned char*)XMALLOC(s->length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) { + WOLFSSL_MSG("Memory Error"); + return NULL; + } + XMEMCPY(str, (unsigned char*)s->data, s->length); + + tmp = (char*)XMALLOC(tmpSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + WOLFSSL_MSG("Memory Error"); + XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + XMEMSET(tmp, 0, tmpSz); + + for (i = 0; i < tmpSz && i < (s->length - 1); i++) { + XSNPRINTF(val, valSz - 1, "%02X:", str[i]); + XSTRNCAT(tmp, val, valSz); + } + XSNPRINTF(val, valSz - 1, "%02X", str[i]); + XSTRNCAT(tmp, val, valSz); + XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return tmp; +} +#endif /* NO_ASN */ + +void wolfSSL_set_connect_state(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_set_connect_state"); + 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 (InitSSL_Side(ssl, WOLFSSL_CLIENT_END) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error initializing client side"); + } +} +#endif /* OPENSSL_EXTRA */ + + +int wolfSSL_get_shutdown(const WOLFSSL* ssl) +{ + int isShutdown = 0; + + WOLFSSL_ENTER("wolfSSL_get_shutdown"); + + if (ssl) { + /* in OpenSSL, WOLFSSL_SENT_SHUTDOWN = 1, when closeNotifySent * + * WOLFSSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */ + isShutdown = ((ssl->options.closeNotify||ssl->options.connReset) << 1) + | (ssl->options.sentNotify); + } + return isShutdown; +} + + +int wolfSSL_session_reused(WOLFSSL* ssl) +{ + int resuming = 0; + if (ssl) + resuming = ssl->options.resuming; + return resuming; +} + +#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) +WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) +{ +#ifdef HAVE_EXT_CACHE + WOLFSSL_SESSION* copy; + + WOLFSSL_ENTER("wolfSSL_SESSION_dup"); + + if (session == NULL) + return NULL; +#ifdef HAVE_SESSION_TICKET + if (session->isDynamic && !session->ticket) { + WOLFSSL_MSG("Session dynamic flag is set but ticket pointer is null"); + return NULL; + } +#endif + + copy = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL, + DYNAMIC_TYPE_OPENSSL); + if (copy != NULL) { + XMEMCPY(copy, session, sizeof(WOLFSSL_SESSION)); + copy->isAlloced = 1; +#ifdef HAVE_SESSION_TICKET + if (session->isDynamic) { + copy->ticket = (byte*)XMALLOC(session->ticketLen, NULL, + DYNAMIC_TYPE_SESSION_TICK); + XMEMCPY(copy->ticket, session->ticket, session->ticketLen); + } else { + copy->ticket = copy->staticTicket; + } +#endif +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + copy->peer = wolfSSL_X509_dup(session->peer); +#endif + } + return copy; +#else + WOLFSSL_MSG("wolfSSL_SESSION_dup was called " + "but HAVE_EXT_CACHE is not defined"); + (void)session; + return NULL; +#endif /* HAVE_EXT_CACHE */ +} + +void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) +{ + if (session == NULL) + return; + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (session->peer) { + wolfSSL_X509_free(session->peer); + } +#endif + +#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 + + +/* helper function that takes in a protocol version struct and returns string */ +static const char* wolfSSL_internal_get_version(ProtocolVersion* version) +{ + WOLFSSL_ENTER("wolfSSL_get_version"); + + if (version == NULL) { + return "Bad arg"; + } + + if (version->major == SSLv3_MAJOR) { + switch (version->minor) { + #ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_SSLV3 + case SSLv3_MINOR : + return "SSLv3"; + #endif + #ifdef WOLFSSL_ALLOW_TLSV10 + case TLSv1_MINOR : + return "TLSv1"; + #endif + case TLSv1_1_MINOR : + return "TLSv1.1"; + #endif + case TLSv1_2_MINOR : + return "TLSv1.2"; + #ifdef WOLFSSL_TLS13 + case TLSv1_3_MINOR : + #ifdef WOLFSSL_TLS13_DRAFT + #ifdef WOLFSSL_TLS13_DRAFT_18 + return "TLSv1.3 (Draft 18)"; + #elif defined(WOLFSSL_TLS13_DRAFT_22) + return "TLSv1.3 (Draft 22)"; + #elif defined(WOLFSSL_TLS13_DRAFT_23) + return "TLSv1.3 (Draft 23)"; + #elif defined(WOLFSSL_TLS13_DRAFT_26) + return "TLSv1.3 (Draft 26)"; + #else + return "TLSv1.3 (Draft 28)"; + #endif + #else + return "TLSv1.3"; + #endif + #endif + default: + return "unknown"; + } + } +#ifdef WOLFSSL_DTLS + else if (version->major == DTLS_MAJOR) { + switch (version->minor) { + case DTLS_MINOR : + return "DTLS"; + case DTLSv1_2_MINOR : + return "DTLSv1.2"; + default: + return "unknown"; + } + } +#endif /* WOLFSSL_DTLS */ + return "unknown"; +} + + +const char* wolfSSL_get_version(WOLFSSL* ssl) +{ + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument"); + return "unknown"; + } + + return wolfSSL_internal_get_version(&ssl->version); +} + + +/* current library version */ +const char* wolfSSL_lib_version(void) +{ + return LIBWOLFSSL_VERSION_STRING; +} + + +/* current library version in hex */ +word32 wolfSSL_lib_version_hex(void) +{ + return LIBWOLFSSL_VERSION_HEX; +} + + +int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_get_current_cipher_suite"); + if (ssl) + return (ssl->options.cipherSuite0 << 8) | ssl->options.cipherSuite; + return 0; +} + +WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_get_current_cipher"); + if (ssl) { + ssl->cipher.cipherSuite0 = ssl->options.cipherSuite0; + ssl->cipher.cipherSuite = ssl->options.cipherSuite; + return &ssl->cipher; + } + else + return NULL; +} + + +const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher) +{ + WOLFSSL_ENTER("wolfSSL_CIPHER_get_name"); + + if (cipher == NULL) { + return NULL; + } + + #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) && \ + !defined(WOLFSSL_QT) + return GetCipherNameIana(cipher->cipherSuite0, cipher->cipherSuite); + #else + return wolfSSL_get_cipher_name_from_suite(cipher->cipherSuite0, + cipher->cipherSuite); + #endif +} + +const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher) +{ + WOLFSSL_ENTER("SSL_CIPHER_get_version"); + + if (cipher == NULL || cipher->ssl == NULL) { + return NULL; + } + + return wolfSSL_get_version(cipher->ssl); +} + +const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session) +{ + if (session == NULL) { + return NULL; + } + +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) + return GetCipherNameIana(session->cipherSuite0, session->cipherSuite); + #else + return GetCipherNameInternal(session->cipherSuite0, session->cipherSuite); + #endif +#else + return NULL; +#endif +} + +const char* wolfSSL_get_cipher(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_cipher"); + return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl)); +} + +/* gets cipher name in the format DHE-RSA-... rather then TLS_DHE... */ +const char* wolfSSL_get_cipher_name(WOLFSSL* ssl) +{ + /* get access to cipher_name_idx in internal.c */ + return wolfSSL_get_cipher_name_internal(ssl); +} + +const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0, + const byte cipherSuite) +{ + return GetCipherNameInternal(cipherSuite0, cipherSuite); +} + +const char* wolfSSL_get_cipher_name_iana_from_suite(const byte cipherSuite0, + const byte cipherSuite) +{ + return GetCipherNameIana(cipherSuite0, cipherSuite); +} + + +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +/* Creates and returns a new WOLFSSL_CIPHER stack. */ +WOLFSSL_STACK* wolfSSL_sk_new_cipher(void) +{ + WOLFSSL_STACK* sk; + WOLFSSL_ENTER("wolfSSL_sk_new_cipher"); + + sk = wolfSSL_sk_new_null(); + if (sk == NULL) + return NULL; + sk->type = STACK_TYPE_CIPHER; + + return sk; +} + +#ifndef NO_WOLFSSL_STUB +/* Keep as stubs for now */ +/* return 1 on success 0 on fail */ +int wolfSSL_sk_CIPHER_push(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, + WOLFSSL_CIPHER* cipher) +{ + WOLFSSL_STUB("wolfSSL_sk_CIPHER_push"); + (void)sk; + (void)cipher; + return 0; +} + + +WOLFSSL_CIPHER* wolfSSL_sk_CIPHER_pop(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk) +{ + WOLFSSL_STUB("wolfSSL_sk_CIPHER_pop"); + (void)sk; + return NULL; +} +#endif /* NO_WOLFSSL_STUB */ +#endif /* WOLFSSL_QT || OPENSSL_ALL */ + +word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher) +{ + word16 cipher_id = 0; + + WOLFSSL_ENTER("SSL_CIPHER_get_id"); + + if (cipher && cipher->ssl) { + cipher_id = (cipher->ssl->options.cipherSuite0 << 8) | + cipher->ssl->options.cipherSuite; + } + + return cipher_id; +} + +const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value) +{ + const WOLFSSL_CIPHER* cipher = NULL; + byte cipherSuite0, cipherSuite; + WOLFSSL_ENTER("SSL_get_cipher_by_value"); + + /* extract cipher id information */ + cipherSuite = (value & 0xFF); + cipherSuite0 = ((value >> 8) & 0xFF); + + /* TODO: lookup by cipherSuite0 / cipherSuite */ + (void)cipherSuite0; + (void)cipherSuite; + + return cipher; +} + + +#if defined(OPENSSL_ALL) +/* Free the structure for WOLFSSL_CIPHER stack + * + * sk stack to free nodes in + */ +void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_STACK* tmp; + WOLFSSL_ENTER("wolfSSL_sk_CIPHER_free"); + + if (sk == NULL) + return; + + /* parse through stack freeing each node */ + node = sk->next; + while (node) { + tmp = node; + node = node->next; + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + } + + /* free head of stack */ + XFREE(sk, NULL, DYNAMIC_TYPE_ASN1); +} +#endif + +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \ + !defined(NO_DH) +#ifdef HAVE_FFDHE +static const char* wolfssl_ffdhe_name(word16 group) +{ + const char* str = NULL; + switch (group) { + case WOLFSSL_FFDHE_2048: + str = "FFDHE_2048"; + break; + case WOLFSSL_FFDHE_3072: + str = "FFDHE_3072"; + break; + case WOLFSSL_FFDHE_4096: + str = "FFDHE_4096"; + break; + case WOLFSSL_FFDHE_6144: + str = "FFDHE_6144"; + break; + case WOLFSSL_FFDHE_8192: + str = "FFDHE_8192"; + break; + } + return str; +} +#endif +/* 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) +{ + const char* cName = NULL; + + if (ssl == NULL) + return NULL; + +#ifdef HAVE_FFDHE + if (ssl->namedGroup != 0) { + cName = wolfssl_ffdhe_name(ssl->namedGroup); + } +#endif + +#ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID && cName == NULL) { + cName = "X25519"; + } +#endif + +#ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID && cName == NULL) { + cName = "X448"; + } +#endif + +#ifdef HAVE_ECC + if (ssl->ecdhCurveOID != 0 && cName == NULL) { + cName = wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, + NULL)); + } +#endif + + return cName; +} +#endif + + +#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(KEEP_PEER_CERT) || \ + defined(SESSION_CERTS) +/* Smaller subset of X509 compatibility functions. Avoid increasing the size of + * this subset and its memory usage */ + +#if !defined(NO_CERTS) +/* returns a pointer to a new WOLFSSL_X509 structure on success and NULL on + * fail + */ +WOLFSSL_X509* wolfSSL_X509_new(void) +{ + WOLFSSL_X509* x509; + + x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, + DYNAMIC_TYPE_X509); + if (x509 != NULL) { + InitX509(x509, 1, NULL); + } + + return x509; +} + +WOLFSSL_ABI +WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert) +{ + WOLFSSL_ENTER("wolfSSL_X509_get_subject_name"); + if (cert && cert->subject.sz != 0) + return &cert->subject; + return NULL; +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_SHA) +/****************************************************************************** +* wolfSSL_X509_subject_name_hash - compute the hash digest of the raw subject name +* +* RETURNS: +* The beginning of the hash digest. Otherwise, returns zero. +* Note: +* Returns a different hash value from OpenSSL's X509_subject_name_hash() API +* depending on the subject name. +*/ +unsigned long wolfSSL_X509_subject_name_hash(const WOLFSSL_X509* x509) +{ + word32 ret = 0; + int retHash; + WOLFSSL_X509_NAME *subjectName = NULL; + +#ifdef WOLFSSL_PIC32MZ_HASH + byte digest[PIC32_DIGEST_SIZE]; +#else + byte digest[WC_SHA_DIGEST_SIZE]; +#endif + + if (x509 == NULL){ + return WOLFSSL_FAILURE; + } + + subjectName = wolfSSL_X509_get_subject_name((WOLFSSL_X509*)x509); + + if (subjectName != NULL){ + retHash = wc_ShaHash((const byte*)subjectName->name, + (word32)subjectName->sz, digest); + + if(retHash != 0){ + WOLFSSL_MSG("Hash of X509 subjectName has failed"); + return WOLFSSL_FAILURE; + } + ret = MakeWordFromHash(digest); + } + + return (unsigned long)ret; +} +#endif + +WOLFSSL_ABI +WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert) +{ + WOLFSSL_ENTER("X509_get_issuer_name"); + if (cert && cert->issuer.sz != 0) + return &cert->issuer; + return NULL; +} + + +int wolfSSL_X509_get_signature_type(WOLFSSL_X509* x509) +{ + int type = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_signature_type"); + + if (x509 != NULL) + type = x509->sigOID; + + return type; +} + +#if defined(OPENSSL_EXTRA_X509_SMALL) + +/* 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) +{ + char *text = NULL; + int textSz = 0; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_get_text_by_NID"); + + switch (nid) { + case ASN_COMMON_NAME: + text = name->fullName.fullName + name->fullName.cnIdx; + textSz = name->fullName.cnLen; + break; + case ASN_SUR_NAME: + text = name->fullName.fullName + name->fullName.snIdx; + textSz = name->fullName.snLen; + break; + case ASN_SERIAL_NUMBER: + text = name->fullName.fullName + name->fullName.serialIdx; + textSz = name->fullName.serialLen; + break; + case ASN_COUNTRY_NAME: + text = name->fullName.fullName + name->fullName.cIdx; + textSz = name->fullName.cLen; + break; + case ASN_LOCALITY_NAME: + text = name->fullName.fullName + name->fullName.lIdx; + textSz = name->fullName.lLen; + break; + case ASN_STATE_NAME: + text = name->fullName.fullName + name->fullName.stIdx; + textSz = name->fullName.stLen; + break; + case ASN_ORG_NAME: + text = name->fullName.fullName + name->fullName.oIdx; + textSz = name->fullName.oLen; + break; + case ASN_ORGUNIT_NAME: + text = name->fullName.fullName + name->fullName.ouIdx; + textSz = name->fullName.ouLen; + break; + case ASN_DOMAIN_COMPONENT: + text = name->fullName.fullName + name->fullName.dcIdx[0]; + textSz = name->fullName.dcLen[0]; + break; + case NID_emailAddress: + text = name->fullName.fullName + name->fullName.emailIdx; + textSz = name->fullName.emailLen; + break; + #ifdef WOLFSSL_CERT_EXT + case ASN_BUS_CAT: + text = name->fullName.fullName + name->fullName.bcIdx; + textSz = name->fullName.bcLen; + break; + #endif + default: + WOLFSSL_MSG("Entry type not found"); + return WOLFSSL_FATAL_ERROR; + } + + /* 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 + 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 - 1); /* do not include null character in size */ +} + +/* Creates a new WOLFSSL_EVP_PKEY structure that has the public key from x509 + * + * returns a pointer to the created WOLFSSL_EVP_PKEY on success and NULL on fail + */ +WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509) +{ + WOLFSSL_EVP_PKEY* key = NULL; + WOLFSSL_ENTER("X509_get_pubkey"); + if (x509 != NULL) { + key = wolfSSL_EVP_PKEY_new_ex(x509->heap); + if (key != NULL) { + if (x509->pubKeyOID == RSAk) { + key->type = EVP_PKEY_RSA; + } + else if (x509->pubKeyOID == DSAk) { + key->type = EVP_PKEY_DSA; + } + else { + key->type = EVP_PKEY_EC; + } + key->save_type = 0; + key->pkey.ptr = (char*)XMALLOC( + x509->pubKey.length, x509->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (key->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(key); + return NULL; + } + XMEMCPY(key->pkey.ptr, x509->pubKey.buffer, x509->pubKey.length); + key->pkey_sz = x509->pubKey.length; + + #ifdef HAVE_ECC + key->pkey_curve = (int)x509->pkCurveOID; + #endif /* HAVE_ECC */ + + /* decode RSA key */ + #ifndef NO_RSA + if (key->type == EVP_PKEY_RSA) { + key->ownRsa = 1; + key->rsa = wolfSSL_RSA_new(); + if (key->rsa == NULL) { + wolfSSL_EVP_PKEY_free(key); + return NULL; + } + + if (wolfSSL_RSA_LoadDer_ex(key->rsa, + (const unsigned char*)key->pkey.ptr, key->pkey_sz, + WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) { + wolfSSL_EVP_PKEY_free(key); + return NULL; + } + } + #endif /* NO_RSA */ + + /* decode ECC key */ + #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) + if (key->type == EVP_PKEY_EC) { + word32 idx = 0; + + key->ownEcc = 1; + key->ecc = wolfSSL_EC_KEY_new(); + if (key->ecc == NULL || key->ecc->internal == NULL) { + wolfSSL_EVP_PKEY_free(key); + return NULL; + } + + /* not using wolfSSL_EC_KEY_LoadDer because public key in x509 + * is in the format of x963 (no sequence at start of buffer) */ + if (wc_EccPublicKeyDecode((const unsigned char*)key->pkey.ptr, + &idx, (ecc_key*)key->ecc->internal, key->pkey_sz) < 0) { + WOLFSSL_MSG("wc_EccPublicKeyDecode failed"); + wolfSSL_EVP_PKEY_free(key); + return NULL; + } + + if (SetECKeyExternal(key->ecc) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyExternal failed"); + wolfSSL_EVP_PKEY_free(key); + return NULL; + } + + key->ecc->inSet = 1; + } + #endif /* HAVE_ECC */ + + #ifndef NO_DSA + if (key->type == EVP_PKEY_DSA) { + key->ownDsa = 1; + key->dsa = wolfSSL_DSA_new(); + if (key->dsa == NULL) { + wolfSSL_EVP_PKEY_free(key); + return NULL; + } + + if (wolfSSL_DSA_LoadDer_ex(key->dsa, + (const unsigned char*)key->pkey.ptr, key->pkey_sz, \ + WOLFSSL_DSA_LOAD_PUBLIC) != SSL_SUCCESS) { + wolfSSL_DSA_free(key->dsa); + key->dsa = NULL; + wolfSSL_EVP_PKEY_free(key); + return NULL; + } + } + #endif /* NO_DSA */ + } + } + return key; +} +#endif /* OPENSSL_EXTRA_X509_SMALL */ +#endif /* !NO_CERTS */ + +/* End of smaller subset of X509 compatibility functions. Avoid increasing the + * size of this subset and its memory usage */ +#endif /* OPENSSL_EXTRA_X509_SMALL */ + +#if defined(OPENSSL_ALL) +/* Takes two WOLFSSL_X509* certificates and performs a Sha hash of each, if the + * has values are the same, then it will do an XMEMCMP to confirm they are + * identical. Returns a 0 when certificates match, returns a negative number + * when certificates are not a match. +*/ +int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b) +{ + const byte* derA; + const byte* derB; + int retHashA; + int retHashB; + int outSzA = 0; + int outSzB = 0; + + #ifdef WOLFSSL_PIC32MZ_HASH + byte digestA[PIC32_DIGEST_SIZE]; + byte digestB[PIC32_DIGEST_SIZE]; + #else + byte digestA[WC_SHA_DIGEST_SIZE]; + byte digestB[WC_SHA_DIGEST_SIZE]; + #endif + + if (a == NULL || b == NULL){ + return BAD_FUNC_ARG; + } + + derA = wolfSSL_X509_get_der((WOLFSSL_X509*)a, &outSzA); + if(derA == NULL){ + WOLFSSL_MSG("wolfSSL_X509_get_der - certificate A has failed"); + return WOLFSSL_FATAL_ERROR; + } + derB = wolfSSL_X509_get_der((WOLFSSL_X509*)b, &outSzB); + if(derB == NULL){ + WOLFSSL_MSG("wolfSSL_X509_get_der - certificate B has failed"); + return WOLFSSL_FATAL_ERROR; + } + + retHashA = wc_ShaHash(derA, (word32)outSzA, digestA); + if(retHashA != 0){ + WOLFSSL_MSG("Hash of certificate A has failed"); + return WOLFSSL_FATAL_ERROR; + } + retHashB = wc_ShaHash(derB, (word32)outSzB, digestB); + if(retHashB != 0){ + WOLFSSL_MSG("Hash of certificate B has failed"); + return WOLFSSL_FATAL_ERROR; + } + + if (outSzA == outSzB){ + #ifdef WOLFSSL_PIC32MZ_HASH + if(XMEMCMP(digestA, digestB, PIC32_DIGEST_SIZE) != 0){ + return WOLFSSL_FATAL_ERROR; + } + #else + if(XMEMCMP(digestA, digestB, WC_SHA_DIGEST_SIZE) != 0){ + return WOLFSSL_FATAL_ERROR; + } + #endif + else{ + WOLFSSL_LEAVE("wolfSSL_X509_cmp", 0); + return 0; + } + } + else{ + WOLFSSL_LEAVE("wolfSSL_X509_cmp", WOLFSSL_FATAL_ERROR); + return WOLFSSL_FATAL_ERROR; + } + } +#endif + +#if defined(OPENSSL_EXTRA) +#if !defined(NO_CERTS) int wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509* x509, int nid) { int isSet = 0; @@ -8679,9 +19948,15 @@ int wolfSSL_set_compression(WOLFSSL* ssl) case AUTH_KEY_OID: isSet = x509->authKeyIdSet; break; case SUBJ_KEY_OID: isSet = x509->subjKeyIdSet; break; case KEY_USAGE_OID: isSet = x509->keyUsageSet; break; - #ifdef WOLFSSL_SEP + case CRL_DIST_OID: isSet = x509->CRLdistSet; break; + case EXT_KEY_USAGE_OID: isSet = ((x509->extKeyUsageSrc) ? 1 : 0); + break; + case AUTH_INFO_OID: isSet = x509->authInfoSet; break; + #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT) case CERT_POLICY_OID: isSet = x509->certPolicySet; break; - #endif /* WOLFSSL_SEP */ + #endif /* WOLFSSL_SEP || WOLFSSL_QT */ + default: + WOLFSSL_MSG("NID not in table"); } } @@ -8704,9 +19979,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl) case AUTH_KEY_OID: crit = x509->authKeyIdCrit; break; case SUBJ_KEY_OID: crit = x509->subjKeyIdCrit; break; case KEY_USAGE_OID: crit = x509->keyUsageCrit; break; - #ifdef WOLFSSL_SEP + case CRL_DIST_OID: crit= x509->CRLdistCrit; break; + #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT) case CERT_POLICY_OID: crit = x509->certPolicyCrit; break; - #endif /* WOLFSSL_SEP */ + #endif /* WOLFSSL_SEP || WOLFSSL_QT */ } } @@ -8761,8 +20037,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - byte* wolfSSL_X509_get_authorityKeyID( - WOLFSSL_X509* x509, byte* dst, int* dstLen) + byte* wolfSSL_X509_get_authorityKeyID(WOLFSSL_X509* x509, + byte* dst, int* dstLen) { byte *id = NULL; int copySz = 0; @@ -8772,7 +20048,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (x509 != NULL) { if (x509->authKeyIdSet) { copySz = min(dstLen != NULL ? *dstLen : 0, - (int)x509->authKeyIdSz); + (int)x509->authKeyIdSz); id = x509->authKeyId; } @@ -8789,8 +20065,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - byte* wolfSSL_X509_get_subjectKeyID( - WOLFSSL_X509* x509, byte* dst, int* dstLen) + byte* wolfSSL_X509_get_subjectKeyID(WOLFSSL_X509* x509, + byte* dst, int* dstLen) { byte *id = NULL; int copySz = 0; @@ -8824,995 +20100,1297 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_ENTER("wolfSSL_X509_NAME_entry_count"); if (name != NULL) - count = name->fullName.entryCount; + count = name->fullName.locSz; WOLFSSL_LEAVE("wolfSSL_X509_NAME_entry_count", count); return count; } - int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name, - int nid, char* buf, int len) + + int wolfSSL_X509_NAME_get_index_by_NID(WOLFSSL_X509_NAME* name, + int nid, int pos) { - char *text = NULL; - int textSz = 0; + int value = nid, i; - WOLFSSL_ENTER("wolfSSL_X509_NAME_get_text_by_NID"); + WOLFSSL_ENTER("wolfSSL_X509_NAME_get_index_by_NID"); - switch (nid) { - case ASN_COMMON_NAME: - text = name->fullName.fullName + name->fullName.cnIdx; - textSz = name->fullName.cnLen; - break; - case ASN_SUR_NAME: - text = name->fullName.fullName + name->fullName.snIdx; - textSz = name->fullName.snLen; - break; - case ASN_SERIAL_NUMBER: - text = name->fullName.fullName + name->fullName.serialIdx; - textSz = name->fullName.serialLen; - break; - case ASN_COUNTRY_NAME: - text = name->fullName.fullName + name->fullName.cIdx; - textSz = name->fullName.cLen; - break; - case ASN_LOCALITY_NAME: - text = name->fullName.fullName + name->fullName.lIdx; - textSz = name->fullName.lLen; - break; - case ASN_STATE_NAME: - text = name->fullName.fullName + name->fullName.stIdx; - textSz = name->fullName.stLen; - break; - case ASN_ORG_NAME: - text = name->fullName.fullName + name->fullName.oIdx; - textSz = name->fullName.oLen; - break; - case ASN_ORGUNIT_NAME: - text = name->fullName.fullName + name->fullName.ouIdx; - textSz = name->fullName.ouLen; - break; - default: - break; + if (name == NULL || pos >= DN_NAMES_MAX + DOMAIN_COMPONENT_MAX) { + return BAD_FUNC_ARG; } - if (buf != NULL && text != NULL) { - textSz = min(textSz, len); - XMEMCPY(buf, text, textSz); - buf[textSz] = '\0'; + if (value == NID_emailAddress) { + value = ASN_EMAIL_NAME; } - WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz); - return textSz; + i = pos + 1; /* start search after index passed in */ + if (i < 0) { + i = 0; + } + + for (;i < name->fullName.locSz && + i < DN_NAMES_MAX + DOMAIN_COMPONENT_MAX; i++) { + if (name->fullName.loc[i] == value) { + return i; + } + } + return WOLFSSL_FATAL_ERROR; + } + + + WOLFSSL_ASN1_STRING* wolfSSL_X509_NAME_ENTRY_get_data( + WOLFSSL_X509_NAME_ENTRY* in) + { + WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_data"); + if (in == NULL) + return NULL; + + return in->value; + } + + + /* Creates a new WOLFSSL_ASN1_STRING structure. + * + * returns a pointer to the new structure created on success or NULL if fail + */ + WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void) + { + WOLFSSL_ASN1_STRING* asn1; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_new"); + + asn1 = (WOLFSSL_ASN1_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_STRING), NULL, + DYNAMIC_TYPE_OPENSSL); + if (asn1 != NULL) { + XMEMSET(asn1, 0, sizeof(WOLFSSL_ASN1_STRING)); + } + + return asn1; /* no check for null because error case is returning null*/ + } + + + /* used to free a WOLFSSL_ASN1_STRING structure */ + void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1) + { + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_free"); + + if (asn1 != NULL) { + if (asn1->length > 0 && asn1->data != NULL && asn1->isDynamic) { + XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL); + } + XFREE(asn1, NULL, DYNAMIC_TYPE_OPENSSL); + } + } + + + /* Creates a new WOLFSSL_ASN1_STRING structure given the input type. + * + * type is the type of set when WOLFSSL_ASN1_STRING is created + * + * returns a pointer to the new structure created on success or NULL if fail + */ + WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type) + { + WOLFSSL_ASN1_STRING* asn1; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type_new"); + + asn1 = wolfSSL_ASN1_STRING_new(); + if (asn1 == NULL) { + return NULL; + } + asn1->type = type; + + return asn1; + } + + +/****************************************************************************** +* wolfSSL_ASN1_STRING_type - returns the type of +* +* RETURNS: +* returns the type set for . Otherwise, returns WOLFSSL_FAILURE. +*/ + int wolfSSL_ASN1_STRING_type(const WOLFSSL_ASN1_STRING* asn1) + { + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type"); + + if (asn1 == NULL) { + return WOLFSSL_FAILURE; + } + + return asn1->type; + } + + /* if dataSz is negative then use XSTRLEN to find length of data + * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ + /* `data` can be NULL and only buffer will be allocated */ + int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data, + int dataSz) + { + int sz; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_set"); + + if (asn1 == NULL || (data == NULL && dataSz < 0)) { + return WOLFSSL_FAILURE; + } + + if (dataSz < 0) { + sz = (int)XSTRLEN((const char*)data) + 1; /* +1 for null */ + } + else { + sz = dataSz; + } + + if (sz < 0) { + return WOLFSSL_FAILURE; + } + + /* free any existing data before copying */ + if (asn1->data != NULL && asn1->isDynamic) { + XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL); + asn1->data = NULL; + } + + if (sz > CTC_NAME_SIZE) { + /* create new data buffer and copy over */ + asn1->data = (char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL); + if (asn1->data == NULL) { + return WOLFSSL_FAILURE; + } + asn1->isDynamic = 1; + } + else { + XMEMSET(asn1->strData, 0, CTC_NAME_SIZE); + asn1->data = asn1->strData; + asn1->isDynamic = 0; + } + if (data != NULL) { + XMEMCPY(asn1->data, data, sz); + asn1->data[sz] = '\0'; + } + asn1->length = sz; + + return WOLFSSL_SUCCESS; + } + + + unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING* asn) + { + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_data"); + + if (asn) { + return (unsigned char*)asn->data; + } + else { + return NULL; + } + } + + + int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING* asn) + { + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_length"); + + if (asn) { + return asn->length; + } + else { + return 0; + } + } + +#ifndef NO_WOLFSSL_STUB + WOLFSSL_ASN1_STRING* wolfSSL_d2i_DISPLAYTEXT(WOLFSSL_ASN1_STRING **asn, + const unsigned char **in, long len) + { + WOLFSSL_STUB("d2i_DISPLAYTEXT"); + (void)asn; + (void)in; + (void)len; + return NULL; } #endif - - /* copy name into in buffer, at most sz bytes, if buffer is null will - malloc buffer, call responsible for freeing */ - char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME* name, char* in, int sz) +#ifdef XSNPRINTF /* a snprintf function needs to be available */ + /* Writes the human readable form of x509 to bio. + * + * bio WOLFSSL_BIO to write to. + * x509 Certificate to write. + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ + int wolfSSL_X509_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509* x509, + unsigned long nmflags, unsigned long cflag) { - int copySz = min(sz, name->sz); + WOLFSSL_ENTER("wolfSSL_X509_print_ex"); - WOLFSSL_ENTER("wolfSSL_X509_NAME_oneline"); - if (!name->sz) return in; + #ifndef NO_WOLFSSL_STUB + /* flags currently not supported */ + (void)nmflags; + (void)cflag; + #endif - if (!in) { - in = (char*)XMALLOC(name->sz, 0, DYNAMIC_TYPE_OPENSSL); - if (!in ) return in; - copySz = name->sz; + if (bio == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; } - if (copySz == 0) - return in; + if (wolfSSL_BIO_write(bio, "Certificate:\n", + (int)XSTRLEN("Certificate:\n")) <= 0) { + return WOLFSSL_FAILURE; + } - XMEMCPY(in, name->name, copySz - 1); - in[copySz - 1] = 0; + if (wolfSSL_BIO_write(bio, " Data:\n", + (int)XSTRLEN(" Data:\n")) <= 0) { + return WOLFSSL_FAILURE; + } - return in; - } + /* print version of cert */ + { + int version; + char tmp[20]; + if ((version = wolfSSL_X509_version(x509)) < 0) { + WOLFSSL_MSG("Error getting X509 version"); + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_write(bio, " Version:", + (int)XSTRLEN(" Version:")) <= 0) { + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp), " %d (0x%x)\n", version, (byte)version-1); + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } - int wolfSSL_X509_get_signature_type(WOLFSSL_X509* x509) - { - int type = 0; + /* print serial number out */ + { + unsigned char serial[32]; + int sz = sizeof(serial); - WOLFSSL_ENTER("wolfSSL_X509_get_signature_type"); + XMEMSET(serial, 0, sz); + if (wolfSSL_X509_get_serial_number(x509, serial, &sz) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error getting x509 serial number"); + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_write(bio, " Serial Number:", + (int)XSTRLEN(" Serial Number:")) <= 0) { + return WOLFSSL_FAILURE; + } - if (x509 != NULL) - type = x509->sigOID; + /* if serial can fit into byte than print on the same line */ + if (sz <= (int)sizeof(byte)) { + char tmp[17]; + XSNPRINTF(tmp, sizeof(tmp), " %d (0x%x)\n", serial[0],serial[0]); + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + else { + int i; + char tmp[100]; + int tmpSz = 100; + char val[5]; + int valSz = 5; - return type; - } - - - int wolfSSL_X509_get_signature(WOLFSSL_X509* x509, - unsigned char* buf, int* bufSz) - { - WOLFSSL_ENTER("wolfSSL_X509_get_signature"); - if (x509 == NULL || bufSz == NULL || *bufSz < (int)x509->sig.length) - return SSL_FATAL_ERROR; - - if (buf != NULL) - XMEMCPY(buf, x509->sig.buffer, x509->sig.length); - *bufSz = x509->sig.length; - - return SSL_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 */ - int wolfSSL_X509_get_serial_number(WOLFSSL_X509* x509, byte* in, int* inOutSz) - { - WOLFSSL_ENTER("wolfSSL_X509_get_serial_number"); - if (x509 == NULL || in == NULL || - inOutSz == NULL || *inOutSz < x509->serialSz) - return BAD_FUNC_ARG; - - XMEMCPY(in, x509->serial, x509->serialSz); - *inOutSz = x509->serialSz; - - return SSL_SUCCESS; - } - - - const byte* wolfSSL_X509_get_der(WOLFSSL_X509* x509, int* outSz) - { - WOLFSSL_ENTER("wolfSSL_X509_get_der"); - - if (x509 == NULL || outSz == NULL) - return NULL; - - *outSz = (int)x509->derCert.length; - return x509->derCert.buffer; - } - - - int wolfSSL_X509_version(WOLFSSL_X509* x509) - { - WOLFSSL_ENTER("wolfSSL_X509_version"); - - if (x509 == NULL) - return 0; - - return x509->version; - } - - - const byte* wolfSSL_X509_notBefore(WOLFSSL_X509* x509) - { - WOLFSSL_ENTER("wolfSSL_X509_notBefore"); - - if (x509 == NULL) - return NULL; - - return x509->notBefore; - } - - - const byte* wolfSSL_X509_notAfter(WOLFSSL_X509* x509) - { - WOLFSSL_ENTER("wolfSSL_X509_notAfter"); - - if (x509 == NULL) - return NULL; - - return x509->notAfter; - } - - -#ifdef WOLFSSL_SEP - -/* copy oid into in buffer, at most *inOutSz bytes, if buffer is null will - malloc buffer, call responsible for freeing. Actual size returned in - *inOutSz. Requires inOutSz be non-null */ -byte* wolfSSL_X509_get_device_type(WOLFSSL_X509* x509, byte* in, int *inOutSz) -{ - int copySz; - - WOLFSSL_ENTER("wolfSSL_X509_get_dev_type"); - if (inOutSz == NULL) return NULL; - if (!x509->deviceTypeSz) return in; - - copySz = min(*inOutSz, x509->deviceTypeSz); - - if (!in) { - in = (byte*)XMALLOC(x509->deviceTypeSz, 0, DYNAMIC_TYPE_OPENSSL); - if (!in) return in; - copySz = x509->deviceTypeSz; - } - - XMEMCPY(in, x509->deviceType, copySz); - *inOutSz = copySz; - - return in; -} - - -byte* wolfSSL_X509_get_hw_type(WOLFSSL_X509* x509, byte* in, int* inOutSz) -{ - int copySz; - - WOLFSSL_ENTER("wolfSSL_X509_get_hw_type"); - if (inOutSz == NULL) return NULL; - if (!x509->hwTypeSz) return in; - - copySz = min(*inOutSz, x509->hwTypeSz); - - if (!in) { - in = (byte*)XMALLOC(x509->hwTypeSz, 0, DYNAMIC_TYPE_OPENSSL); - if (!in) return in; - copySz = x509->hwTypeSz; - } - - XMEMCPY(in, x509->hwType, copySz); - *inOutSz = copySz; - - return in; -} - - -byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in,int* inOutSz) -{ - int copySz; - - WOLFSSL_ENTER("wolfSSL_X509_get_hw_serial_number"); - if (inOutSz == NULL) return NULL; - if (!x509->hwTypeSz) return in; - - copySz = min(*inOutSz, x509->hwSerialNumSz); - - if (!in) { - in = (byte*)XMALLOC(x509->hwSerialNumSz, 0, DYNAMIC_TYPE_OPENSSL); - if (!in) return in; - copySz = x509->hwSerialNumSz; - } - - XMEMCPY(in, x509->hwSerialNum, copySz); - *inOutSz = copySz; - - return in; -} - -#endif /* WOLFSSL_SEP */ - - -WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len) -{ - WOLFSSL_X509 *newX509 = NULL; - - WOLFSSL_ENTER("wolfSSL_X509_d2i"); - - if (in != NULL && len != 0) { - #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; - #else - DecodedCert cert[1]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (cert == NULL) - return NULL; - #endif - - InitDecodedCert(cert, (byte*)in, len, NULL); - if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) { - newX509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), - NULL, DYNAMIC_TYPE_X509); - if (newX509 != NULL) { - InitX509(newX509, 1); - if (CopyDecodedToX509(newX509, cert) != 0) { - XFREE(newX509, NULL, DYNAMIC_TYPE_X509); - newX509 = NULL; + /* serial is larger than int size so print off hex values */ + if (wolfSSL_BIO_write(bio, "\n ", + (int)XSTRLEN("\n ")) <= 0) { + return WOLFSSL_FAILURE; + } + tmp[0] = '\0'; + for (i = 0; i < sz - 1 && (3 * i) < tmpSz - valSz; i++) { + XSNPRINTF(val, sizeof(val) - 1, "%02x:", serial[i]); + val[3] = '\0'; /* make sure is null terminated */ + XSTRNCAT(tmp, val, valSz); + } + XSNPRINTF(val, sizeof(val) - 1, "%02x\n", serial[i]); + val[3] = '\0'; /* make sure is null terminated */ + XSTRNCAT(tmp, val, valSz); + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; } } } - FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - } - if (x509 != NULL) - *x509 = newX509; - - return newX509; -} - - -#ifndef NO_FILESYSTEM - -#ifndef NO_STDIO_FILESYSTEM - -WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file) -{ - WOLFSSL_X509* newX509 = NULL; - - WOLFSSL_ENTER("wolfSSL_X509_d2i_fp"); - - if (file != XBADFILE) { - byte* fileBuffer = NULL; - long sz = 0; - - XFSEEK(file, 0, XSEEK_END); - sz = XFTELL(file); - XREWIND(file); - - if (sz < 0) { - WOLFSSL_MSG("Bad tell on FILE"); - return NULL; - } - - fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); - if (fileBuffer != NULL) { - int ret = (int)XFREAD(fileBuffer, sz, 1, file); - if (ret > 0) { - newX509 = wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz); - } - XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); - } - } - - if (x509 != NULL) - *x509 = newX509; - - return newX509; -} - -#endif /* NO_STDIO_FILESYSTEM */ - -WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format) -{ -#ifdef WOLFSSL_SMALL_STACK - byte staticBuffer[1]; /* force heap usage */ -#else - byte staticBuffer[FILE_BUFFER_SIZE]; -#endif - byte* fileBuffer = staticBuffer; - int dynamic = 0; - int ret; - long sz = 0; - XFILE file; - - WOLFSSL_X509* x509 = NULL; - buffer der; - - WOLFSSL_ENTER("wolfSSL_X509_load_certificate"); - - /* Check the inputs */ - if ((fname == NULL) || - (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM)) - return NULL; - - file = XFOPEN(fname, "rb"); - if (file == XBADFILE) - return NULL; - - XFSEEK(file, 0, XSEEK_END); - sz = XFTELL(file); - XREWIND(file); - - if (sz > (long)sizeof(staticBuffer)) { - fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); - if (fileBuffer == NULL) { - XFCLOSE(file); - return NULL; - } - dynamic = 1; - } - else if (sz < 0) { - XFCLOSE(file); - return NULL; - } - - ret = (int)XFREAD(fileBuffer, sz, 1, file); - if (ret < 0) { - XFCLOSE(file); - if (dynamic) - XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); - return NULL; - } - - XFCLOSE(file); - - der.buffer = NULL; - der.length = 0; - - if (format == SSL_FILETYPE_PEM) { - int ecc = 0; - #ifdef WOLFSSL_SMALL_STACK - EncryptedInfo* info = NULL; - #else - EncryptedInfo info[1]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (info == NULL) { - if (dynamic) - XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); - - return NULL; - } - #endif - - info->set = 0; - info->ctx = NULL; - info->consumed = 0; - - if (PemToDer(fileBuffer, sz, CERT_TYPE, &der, NULL, info, &ecc) != 0) + /* print signature algo */ { - /* Only time this should fail, and leave `der` with a buffer - is when the Base64 Decode fails. Release `der.buffer` in - that case. */ - if (der.buffer != NULL) { - XFREE(der.buffer, NULL, DYNAMIC_TYPE_CERT); - der.buffer = NULL; + int oid; + const char* sig; + + if ((oid = wolfSSL_X509_get_signature_type(x509)) <= 0) { + WOLFSSL_MSG("Error getting x509 signature type"); + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_write(bio, " Signature Algorithm: ", + (int)XSTRLEN(" Signature Algorithm: ")) <= 0) { + return WOLFSSL_FAILURE; + } + sig = GetSigName(oid); + if (wolfSSL_BIO_write(bio, sig, (int)XSTRLEN(sig)) <= 0) { + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) { + return WOLFSSL_FAILURE; } } - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - } - else { - der.buffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_CERT); - if (der.buffer != NULL) { - XMEMCPY(der.buffer, fileBuffer, sz); - der.length = (word32)sz; - } - } - - if (dynamic) - XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); - - /* At this point we want `der` to have the certificate in DER format */ - /* ready to be decoded. */ - if (der.buffer != NULL) { - #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; - #else - DecodedCert cert[1]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (cert != NULL) - #endif + /* print issuer */ { - InitDecodedCert(cert, der.buffer, der.length, NULL); - if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) { - x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, - DYNAMIC_TYPE_X509); - if (x509 != NULL) { - InitX509(x509, 1); - if (CopyDecodedToX509(x509, cert) != 0) { - XFREE(x509, NULL, DYNAMIC_TYPE_X509); - x509 = NULL; + char* issuer; + #ifdef WOLFSSL_SMALL_STACK + char* buff = NULL; + int issSz = 0; + #else + char buff[256]; + int issSz = 256; + #endif + + #if defined(WOLFSSL_QT) + issuer = wolfSSL_X509_get_name_oneline( + wolfSSL_X509_get_issuer_name(x509), buff, issSz); + #else + issuer = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_issuer_name(x509), buff, issSz); + #endif + + if (wolfSSL_BIO_write(bio, " Issuer: ", + (int)XSTRLEN(" Issuer: ")) <= 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + return WOLFSSL_FAILURE; + } + if (issuer != NULL) { + if (wolfSSL_BIO_write(bio, issuer, (int)XSTRLEN(issuer)) <= 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + return WOLFSSL_FAILURE; + } + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) { + return WOLFSSL_FAILURE; + } + } + + #ifndef NO_ASN_TIME + /* print validity */ + { + char tmp[80]; + + if (wolfSSL_BIO_write(bio, " Validity\n", + (int)XSTRLEN(" Validity\n")) <= 0) { + return WOLFSSL_FAILURE; + } + + if (wolfSSL_BIO_write(bio, " Not Before: ", + (int)XSTRLEN(" Not Before: ")) <= 0) { + return WOLFSSL_FAILURE; + } + if (x509->notBefore.length > 0) { + if (GetTimeString(x509->notBefore.data, ASN_UTC_TIME, + tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) { + if (GetTimeString(x509->notBefore.data, ASN_GENERALIZED_TIME, + tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error getting not before date"); + return WOLFSSL_FAILURE; } } } + else { + XSTRNCPY(tmp, "Not Set", sizeof(tmp)-1); + } + tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */ + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } - FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - } - - XFREE(der.buffer, NULL, DYNAMIC_TYPE_CERT); - } - - return x509; -} - -#endif /* NO_FILESYSTEM */ - -#endif /* KEEP_PEER_CERT || SESSION_CERTS */ - - -#ifdef OPENSSL_EXTRA -int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) -{ -#ifdef FORTRESS - if (ssl != NULL && idx < MAX_EX_DATA) - { - ssl->ex_data[idx] = data; - return SSL_SUCCESS; - } -#else - (void)ssl; - (void)idx; - (void)data; -#endif - return SSL_FAILURE; -} - - -int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id, - unsigned int len) -{ - (void)ssl; - (void)id; - (void)len; - return 0; -} - - -void wolfSSL_set_connect_state(WOLFSSL* ssl) -{ - (void)ssl; - /* client by default */ -} -#endif - -int wolfSSL_get_shutdown(const WOLFSSL* ssl) -{ - return (ssl->options.isClosed || - ssl->options.connReset || - ssl->options.sentNotify); -} - - -int wolfSSL_session_reused(WOLFSSL* ssl) -{ - return ssl->options.resuming; -} - -#ifdef OPENSSL_EXTRA -void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) -{ - (void)session; -} -#endif - -const char* wolfSSL_get_version(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("SSL_get_version"); - if (ssl->version.major == SSLv3_MAJOR) { - switch (ssl->version.minor) { - case SSLv3_MINOR : - return "SSLv3"; - case TLSv1_MINOR : - return "TLSv1"; - case TLSv1_1_MINOR : - return "TLSv1.1"; - case TLSv1_2_MINOR : - return "TLSv1.2"; - default: - return "unknown"; - } - } - else if (ssl->version.major == DTLS_MAJOR) { - switch (ssl->version.minor) { - case DTLS_MINOR : - return "DTLS"; - case DTLSv1_2_MINOR : - return "DTLSv1.2"; - default: - return "unknown"; - } - } - return "unknown"; -} - - -/* current library version */ -const char* wolfSSL_lib_version(void) -{ - return LIBWOLFSSL_VERSION_STRING; -} - - -/* current library version in hex */ -word32 wolfSSL_lib_version_hex(void) -{ - return LIBWOLFSSL_VERSION_HEX; -} - - -int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("SSL_get_current_cipher_suite"); - if (ssl) - return (ssl->options.cipherSuite0 << 8) | ssl->options.cipherSuite; - return 0; -} - -WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("SSL_get_current_cipher"); - if (ssl) - return &ssl->cipher; - else - return NULL; -} - - -const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher) -{ - (void)cipher; - - WOLFSSL_ENTER("SSL_CIPHER_get_name"); -#ifndef NO_ERROR_STRINGS - if (cipher) { -#if defined(HAVE_CHACHA) - if (cipher->ssl->options.cipherSuite0 == CHACHA_BYTE) { - /* ChaCha suites */ - switch (cipher->ssl->options.cipherSuite) { -#ifdef HAVE_CHACHA -#ifndef NO_RSA - case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : - return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"; - - case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : - return "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"; -#endif - case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : - return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"; -#endif + if (wolfSSL_BIO_write(bio, "\n Not After : ", + (int)XSTRLEN("\n Not After : ")) <= 0) { + return WOLFSSL_FAILURE; + } + if (x509->notAfter.length > 0) { + if (GetTimeString(x509->notAfter.data, ASN_UTC_TIME, + tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) { + if (GetTimeString(x509->notAfter.data, ASN_GENERALIZED_TIME, + tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error getting not after date"); + return WOLFSSL_FAILURE; + } + } + } + else { + XSTRNCPY(tmp, "Not Set", sizeof(tmp)-1); + } + tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */ + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; } } + #endif + + /* print subject */ + { + char* subject; + #ifdef WOLFSSL_SMALL_STACK + char* buff = NULL; + int subSz = 0; + #else + char buff[256]; + int subSz = 256; + #endif + + #if defined(WOLFSSL_QT) + subject = wolfSSL_X509_get_name_oneline( + wolfSSL_X509_get_subject_name(x509), buff, subSz); + #else + subject = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_subject_name(x509), buff, subSz); + #endif + + if (wolfSSL_BIO_write(bio, "\n Subject: ", + (int)XSTRLEN("\n Subject: ")) <= 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + return WOLFSSL_FAILURE; + } + if (subject != NULL) { + if (wolfSSL_BIO_write(bio, subject, (int)XSTRLEN(subject)) <= 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + return WOLFSSL_FAILURE; + } + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + } + + /* get and print public key */ + if (wolfSSL_BIO_write(bio, "\n Subject Public Key Info:\n", + (int)XSTRLEN("\n Subject Public Key Info:\n")) <= 0) { + return WOLFSSL_FAILURE; + } + { + #if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || defined(HAVE_ECC) + char tmp[100]; + #endif + + switch (x509->pubKeyOID) { + #ifndef NO_RSA + case RSAk: + if (wolfSSL_BIO_write(bio, + " Public Key Algorithm: rsaEncryption\n", + (int)XSTRLEN(" Public Key Algorithm: rsaEncryption\n")) <= 0) { + return WOLFSSL_FAILURE; + } + #ifdef HAVE_USER_RSA + if (wolfSSL_BIO_write(bio, + " Build without user RSA to print key\n", + (int)XSTRLEN(" Build without user RSA to print key\n")) + <= 0) { + return WOLFSSL_FAILURE; + } + #else + { + RsaKey rsa; + word32 idx = 0; + int sz; + byte lbit = 0; + int rawLen; + unsigned char* rawKey; + + if (wc_InitRsaKey(&rsa, NULL) != 0) { + WOLFSSL_MSG("wc_InitRsaKey failure"); + return WOLFSSL_FAILURE; + } + if (wc_RsaPublicKeyDecode(x509->pubKey.buffer, + &idx, &rsa, x509->pubKey.length) != 0) { + WOLFSSL_MSG("Error decoding RSA key"); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + if ((sz = wc_RsaEncryptSize(&rsa)) < 0) { + WOLFSSL_MSG("Error getting RSA key size"); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1, "%s%s: (%d bit)\n%s\n", + " ", "Public-Key", 8 * sz, + " Modulus:"); + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + + /* print out modulus */ + XSNPRINTF(tmp, sizeof(tmp) - 1," "); + tmp[sizeof(tmp) - 1] = '\0'; + if (mp_leading_bit(&rsa.n)) { + lbit = 1; + XSTRNCAT(tmp, "00", 3); + } + + rawLen = mp_unsigned_bin_size(&rsa.n); + rawKey = (unsigned char*)XMALLOC(rawLen, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (rawKey == NULL) { + WOLFSSL_MSG("Memory error"); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + mp_to_unsigned_bin(&rsa.n, rawKey); + for (idx = 0; idx < (word32)rawLen; idx++) { + char val[5]; + int valSz = 5; + + if ((idx == 0) && !lbit) { + XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]); + } + else if ((idx != 0) && (((idx + lbit) % 15) == 0)) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + XFREE(rawKey, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1, + ":\n "); + XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]); + } + else { + XSNPRINTF(val, valSz - 1, ":%02x", rawKey[idx]); + } + XSTRNCAT(tmp, val, valSz); + } + XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* print out remaining modulus values */ + if ((idx > 0) && (((idx - 1 + lbit) % 15) != 0)) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + + /* print out exponent values */ + rawLen = mp_unsigned_bin_size(&rsa.e); + if (rawLen < 0) { + WOLFSSL_MSG("Error getting exponent size"); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + + if ((word32)rawLen < sizeof(word32)) { + rawLen = sizeof(word32); + } + rawKey = (unsigned char*)XMALLOC(rawLen, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (rawKey == NULL) { + WOLFSSL_MSG("Memory error"); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + XMEMSET(rawKey, 0, rawLen); + mp_to_unsigned_bin(&rsa.e, rawKey); + if ((word32)rawLen <= sizeof(word32)) { + idx = *(word32*)rawKey; + #ifdef BIG_ENDIAN_ORDER + idx = ByteReverseWord32(idx); + #endif + } + XSNPRINTF(tmp, sizeof(tmp) - 1, + "\n Exponent: %d (0x%x)\n",idx, idx); + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeRsaKey(&rsa); + } + #endif /* HAVE_USER_RSA */ + break; + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + case ECDSAk: + { + word32 i; + ecc_key ecc; + + if (wolfSSL_BIO_write(bio, + " Public Key Algorithm: EC\n", + (int)XSTRLEN(" Public Key Algorithm: EC\n")) <= 0) { + return WOLFSSL_FAILURE; + } + if (wc_ecc_init_ex(&ecc, x509->heap, INVALID_DEVID) + != 0) { + return WOLFSSL_FAILURE; + } + + i = 0; + if (wc_EccPublicKeyDecode(x509->pubKey.buffer, &i, + &ecc, x509->pubKey.length) != 0) { + wc_ecc_free(&ecc); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1, "%s%s: (%d bit)\n%s\n", + " ", "Public-Key", + 8 * wc_ecc_size(&ecc), + " pub:"); + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + wc_ecc_free(&ecc); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1," "); + { + word32 derSz; + byte* der; + + derSz = wc_ecc_size(&ecc) * WOLFSSL_BIT_SIZE; + der = (byte*)XMALLOC(derSz, x509->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + wc_ecc_free(&ecc); + return WOLFSSL_FAILURE; + } + + if (wc_ecc_export_x963(&ecc, der, &derSz) != 0) { + wc_ecc_free(&ecc); + XFREE(der, x509->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + for (i = 0; i < derSz; i++) { + char val[5]; + int valSz = 5; + + if (i == 0) { + XSNPRINTF(val, valSz - 1, "%02x", der[i]); + } + else if ((i % 15) == 0) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + wc_ecc_free(&ecc); + XFREE(der, x509->heap, + DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1, + ":\n "); + XSNPRINTF(val, valSz - 1, "%02x", der[i]); + } + else { + XSNPRINTF(val, valSz - 1, ":%02x", der[i]); + } + XSTRNCAT(tmp, val, valSz); + } + + /* print out remaining modulus values */ + if ((i > 0) && (((i - 1) % 15) != 0)) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + wc_ecc_free(&ecc); + XFREE(der, x509->heap, + DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + } + + XFREE(der, x509->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + XSNPRINTF(tmp, sizeof(tmp) - 1, "\n%s%s: %s\n", + " ", "ASN1 OID", + ecc.dp->name); + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + wc_ecc_free(&ecc); + return WOLFSSL_FAILURE; + } + wc_ecc_free(&ecc); + } + break; + #endif /* HAVE_ECC */ + default: + WOLFSSL_MSG("Unknown key type"); + return WOLFSSL_FAILURE; + } + } + + /* print out extensions */ + if (wolfSSL_BIO_write(bio, " X509v3 extensions:\n", + (int)XSTRLEN(" X509v3 extensions:\n")) <= 0) { + return WOLFSSL_FAILURE; + } + + /* print subject key id */ + if (x509->subjKeyIdSet && x509->subjKeyId != NULL && + x509->subjKeyIdSz > 0) { + char tmp[100]; + word32 i; + char val[5]; + int valSz = 5; + + + if (wolfSSL_BIO_write(bio, + " X509v3 Subject Key Identifier: \n", + (int)XSTRLEN(" X509v3 Subject Key Identifier: \n")) + <= 0) { + return WOLFSSL_FAILURE; + } + + XSNPRINTF(tmp, sizeof(tmp) - 1, " "); + for (i = 0; i < sizeof(tmp) && i < (x509->subjKeyIdSz - 1); i++) { + XSNPRINTF(val, valSz - 1, "%02X:", x509->subjKeyId[i]); + XSTRNCAT(tmp, val, valSz); + } + XSNPRINTF(val, valSz - 1, "%02X\n", x509->subjKeyId[i]); + XSTRNCAT(tmp, val, valSz); + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + + /* printf out authority key id */ + if (x509->authKeyIdSet && x509->authKeyId != NULL && + x509->authKeyIdSz > 0) { + char tmp[100]; + word32 i; + char val[5]; + int valSz = 5; + int len = 0; + + if (wolfSSL_BIO_write(bio, + " X509v3 Authority Key Identifier: \n", + (int)XSTRLEN(" X509v3 Authority Key Identifier: \n")) + <= 0) { + return WOLFSSL_FAILURE; + } + + XSNPRINTF(tmp, sizeof(tmp) - 1, " keyid"); + for (i = 0; i < x509->authKeyIdSz; i++) { + /* check if buffer is almost full */ + if (XSTRLEN(tmp) >= sizeof(tmp) - valSz) { + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + tmp[0] = '\0'; + } + XSNPRINTF(val, valSz - 1, ":%02X", x509->authKeyId[i]); + XSTRNCAT(tmp, val, valSz); + } + len = (int)XSTRLEN("\n"); + XSTRNCAT(tmp, "\n", len + 1); + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + + /* print basic constraint */ + if (x509->basicConstSet) { + char tmp[100]; + + if (wolfSSL_BIO_write(bio, + "\n X509v3 Basic Constraints: \n", + (int)XSTRLEN("\n X509v3 Basic Constraints: \n")) + <= 0) { + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp), + " CA:%s\n", + (x509->isCa)? "TRUE": "FALSE"); + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + + /* print out signature */ + if (x509->sig.length > 0) { + unsigned char* sig; + int sigSz; + int i; + char tmp[100]; + int sigOid = wolfSSL_X509_get_signature_type(x509); + + if (wolfSSL_BIO_write(bio, + " Signature Algorithm: ", + (int)XSTRLEN(" Signature Algorithm: ")) <= 0) { + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1,"%s\n", GetSigName(sigOid)); + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + + sigSz = (int)x509->sig.length; + sig = (unsigned char*)XMALLOC(sigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sig == NULL) { + return WOLFSSL_FAILURE; + } + + if (wolfSSL_X509_get_signature(x509, sig, &sigSz) <= 0) { + XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1," "); + tmp[sizeof(tmp) - 1] = '\0'; + for (i = 0; i < sigSz; i++) { + char val[5]; + int valSz = 5; + + if (i == 0) { + XSNPRINTF(val, valSz - 1, "%02x", sig[i]); + } + else if (((i % 18) == 0)) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) + <= 0) { + XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1, + ":\n "); + XSNPRINTF(val, valSz - 1, "%02x", sig[i]); + } + else { + XSNPRINTF(val, valSz - 1, ":%02x", sig[i]); + } + XSTRNCAT(tmp, val, valSz); + } + XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* print out remaining sig values */ + if ((i > 0) && (((i - 1) % 18) != 0)) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) + <= 0) { + return WOLFSSL_FAILURE; + } + } + } + + /* done with print out */ + if (wolfSSL_BIO_write(bio, "\n\0", (int)XSTRLEN("\n\0")) <= 0) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; + } + int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509) + { + return wolfSSL_X509_print_ex(bio, x509, 0, 0); + } + +#endif /* XSNPRINTF */ + +#endif /* NO_CERTS */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +/* Creates cipher->description based on cipher->offset + * cipher->offset is set in wolfSSL_get_ciphers_compat when it is added + * to a stack of ciphers. + * @param [in] cipher: A cipher from a stack of ciphers. + * return WOLFSSL_SUCCESS if cipher->description is set, else WOLFSSL_FAILURE + */ +int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER* cipher) +{ + int ret = WOLFSSL_FAILURE; + int i,j,k; + int strLen; + unsigned long offset; + char* dp; + const char* name; + const char *keaStr, *authStr, *encStr, *macStr, *protocol; + char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; + unsigned char len = MAX_DESCRIPTION_SZ-1; + const CipherSuiteInfo* cipher_names; + ProtocolVersion pv; + WOLFSSL_ENTER("wolfSSL_sk_CIPHER_description"); + + if (cipher == NULL) + return WOLFSSL_FAILURE; + + dp = cipher->description; + if (dp == NULL) + return WOLFSSL_FAILURE; + + cipher_names = GetCipherNames(); + + offset = cipher->offset; + pv.major = cipher_names[offset].major; + pv.minor = cipher_names[offset].minor; + protocol = wolfSSL_internal_get_version(&pv); + + name = cipher_names[offset].name; + + if (name == NULL) + return ret; + + /* Segment cipher name into n[n0,n1,n2,n4] + * These are used later for comparisons to create: + * keaStr, authStr, encStr, macStr + * + * If cipher_name = ECDHE-ECDSA-AES256-SHA + * then n0 = "ECDHE", n1 = "ECDSA", n2 = "AES256", n3 = "SHA" + * and n = [n0,n1,n2,n3,0] + */ + strLen = (int)XSTRLEN(name); + + for (i = 0, j = 0, k = 0; i <= strLen; i++) { + if (k > MAX_SEGMENTS || j > MAX_SEGMENT_SZ) + break; + + if (name[i] != '-' && name[i] != '\0') { + n[k][j] = name[i]; /* Fill kth segment string until '-' */ + j++; + } + else { + n[k][j] = '\0'; + j = 0; + k++; + } + } + /* keaStr */ + keaStr = GetCipherKeaStr(n); + /* authStr */ + authStr = GetCipherAuthStr(n); + /* encStr */ + encStr = GetCipherEncStr(n); + if ((cipher->bits = SetCipherBits(encStr)) == WOLFSSL_FAILURE) { + WOLFSSL_MSG("Cipher Bits Not Set."); + } + /* macStr */ + macStr = GetCipherMacStr(n); + + + /* Build up the string by copying onto the end. */ + XSTRNCPY(dp, name, len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= (int)strLen; dp += strLen; + + XSTRNCPY(dp, " ", len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= (int)strLen; dp += strLen; + XSTRNCPY(dp, protocol, len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= (int)strLen; dp += strLen; + + XSTRNCPY(dp, " Kx=", len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= (int)strLen; dp += strLen; + XSTRNCPY(dp, keaStr, len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= (int)strLen; dp += strLen; + + XSTRNCPY(dp, " Au=", len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= (int)strLen; dp += strLen; + XSTRNCPY(dp, authStr, len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= (int)strLen; dp += strLen; + + XSTRNCPY(dp, " Enc=", len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= (int)strLen; dp += strLen; + XSTRNCPY(dp, encStr, len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= (int)strLen; dp += strLen; + + XSTRNCPY(dp, " Mac=", len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= (int)strLen; dp += strLen; + XSTRNCPY(dp, macStr, len); + dp[len-1] = '\0'; + + return WOLFSSL_SUCCESS; +} #endif -#if defined(HAVE_ECC) || defined(HAVE_AESCCM) - /* Awkwardly, the ECC cipher suites use the ECC_BYTE as expected, - * but the AES-CCM cipher suites also use it, even the ones that - * aren't ECC. */ - if (cipher->ssl->options.cipherSuite0 == ECC_BYTE) { - /* ECC suites */ - switch (cipher->ssl->options.cipherSuite) { -#ifdef HAVE_ECC -#ifndef NO_RSA - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : - return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; -#endif - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : - return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; -#ifndef NO_RSA - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 : - return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; -#endif - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 : - return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; -#ifndef NO_RSA - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 : - return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; -#endif - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 : - return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; -#ifndef NO_RSA - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 : - return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; -#endif - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 : - return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; -#ifndef NO_SHA -#ifndef NO_RSA - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA : - return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA : - return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; -#endif - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA : - return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA : - return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; -#ifndef NO_RC4 - #ifndef NO_RSA - case TLS_ECDHE_RSA_WITH_RC4_128_SHA : - return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; - #endif - case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : - return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; -#endif -#ifndef NO_DES3 - #ifndef NO_RSA - case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA : - return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; - #endif - case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA : - return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; +char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in, + int len) +{ + char *ret = in; + const char *keaStr, *authStr, *encStr, *macStr; + size_t strLen; + WOLFSSL_ENTER("wolfSSL_CIPHER_description"); + + if (cipher == NULL || in == NULL) + return NULL; + +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + /* if cipher is in the stack from wolfSSL_get_ciphers_compat then + * Return the description based on cipher_names[cipher->offset] + */ + if (cipher->in_stack == TRUE) { + wolfSSL_sk_CIPHER_description((WOLFSSL_CIPHER*)cipher); + XSTRNCPY(in,cipher->description,len); + return ret; + } #endif + /* Get the cipher description based on the SSL session cipher */ + switch (cipher->ssl->specs.kea) { + case no_kea: + keaStr = "None"; + break; #ifndef NO_RSA - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA : - return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA : - return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; + case rsa_kea: + keaStr = "RSA"; + break; #endif - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA : - return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA : - return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; -#ifndef NO_RC4 - #ifndef NO_RSA - case TLS_ECDH_RSA_WITH_RC4_128_SHA : - return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; - #endif - case TLS_ECDH_ECDSA_WITH_RC4_128_SHA : - return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; -#endif -#ifndef NO_DES3 - #ifndef NO_RSA - case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA : - return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; - #endif - case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA : - return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; -#endif -#endif /* NO_SHA */ - -#ifdef HAVE_AESGCM -#ifndef NO_RSA - case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : - return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 : - return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; -#endif - case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 : - return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; - case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 : - return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; -#ifndef NO_RSA - case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 : - return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 : - return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; -#endif - case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 : - return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; - case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 : - return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; -#endif -#endif /* HAVE_ECC */ - -#ifdef HAVE_AESCCM -#ifndef NO_RSA - case TLS_RSA_WITH_AES_128_CCM_8 : - return "TLS_RSA_WITH_AES_128_CCM_8"; - case TLS_RSA_WITH_AES_256_CCM_8 : - return "TLS_RSA_WITH_AES_256_CCM_8"; +#ifndef NO_DH + case diffie_hellman_kea: + keaStr = "DHE"; + break; #endif + case fortezza_kea: + keaStr = "FZ"; + break; #ifndef NO_PSK - case TLS_PSK_WITH_AES_128_CCM_8 : - return "TLS_PSK_WITH_AES_128_CCM_8"; - case TLS_PSK_WITH_AES_256_CCM_8 : - return "TLS_PSK_WITH_AES_256_CCM_8"; - case TLS_PSK_WITH_AES_128_CCM : - return "TLS_PSK_WITH_AES_128_CCM"; - case TLS_PSK_WITH_AES_256_CCM : - return "TLS_PSK_WITH_AES_256_CCM"; - case TLS_DHE_PSK_WITH_AES_128_CCM : - return "TLS_DHE_PSK_WITH_AES_128_CCM"; - case TLS_DHE_PSK_WITH_AES_256_CCM : - return "TLS_DHE_PSK_WITH_AES_256_CCM"; + 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 TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - return "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8"; - case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 : - return "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8"; -#endif + case ecc_diffie_hellman_kea: + keaStr = "ECDHE"; + break; + case ecc_static_diffie_hellman_kea: + keaStr = "ECDH"; + break; #endif + default: + keaStr = "unknown"; + break; + } - default: - return "NONE"; - } - } -#endif /* ECC */ - if (cipher->ssl->options.cipherSuite0 != ECC_BYTE && - cipher->ssl->options.cipherSuite0 != CHACHA_BYTE) { - - /* normal suites */ - switch (cipher->ssl->options.cipherSuite) { + 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 - #ifndef NO_SHA - case SSL_RSA_WITH_RC4_128_SHA : - return "SSL_RSA_WITH_RC4_128_SHA"; + 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 - #ifndef NO_MD5 - case SSL_RSA_WITH_RC4_128_MD5 : - return "SSL_RSA_WITH_RC4_128_MD5"; + #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 -#ifndef NO_SHA - #ifndef NO_DES3 - case SSL_RSA_WITH_3DES_EDE_CBC_SHA : - return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; - #endif - case TLS_RSA_WITH_AES_128_CBC_SHA : - return "TLS_RSA_WITH_AES_128_CBC_SHA"; - case TLS_RSA_WITH_AES_256_CBC_SHA : - return "TLS_RSA_WITH_AES_256_CBC_SHA"; +#ifdef HAVE_CHACHA + case wolfssl_chacha: + encStr = "CHACHA20/POLY1305(256)"; + break; #endif - case TLS_RSA_WITH_AES_128_CBC_SHA256 : - return "TLS_RSA_WITH_AES_128_CBC_SHA256"; - case TLS_RSA_WITH_AES_256_CBC_SHA256 : - return "TLS_RSA_WITH_AES_256_CBC_SHA256"; - #ifdef HAVE_BLAKE2 - case TLS_RSA_WITH_AES_128_CBC_B2B256: - return "TLS_RSA_WITH_AES_128_CBC_B2B256"; - case TLS_RSA_WITH_AES_256_CBC_B2B256: - return "TLS_RSA_WITH_AES_256_CBC_B2B256"; - #endif -#ifndef NO_SHA - case TLS_RSA_WITH_NULL_SHA : - return "TLS_RSA_WITH_NULL_SHA"; +#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 - case TLS_RSA_WITH_NULL_SHA256 : - return "TLS_RSA_WITH_NULL_SHA256"; -#endif /* NO_RSA */ -#ifndef NO_PSK #ifndef NO_SHA - case TLS_PSK_WITH_AES_128_CBC_SHA : - return "TLS_PSK_WITH_AES_128_CBC_SHA"; - case TLS_PSK_WITH_AES_256_CBC_SHA : - return "TLS_PSK_WITH_AES_256_CBC_SHA"; + case sha_mac: + macStr = "SHA1"; + break; +#endif +#ifdef HAVE_SHA224 + case sha224_mac: + macStr = "SHA224"; + break; #endif #ifndef NO_SHA256 - case TLS_PSK_WITH_AES_128_CBC_SHA256 : - return "TLS_PSK_WITH_AES_128_CBC_SHA256"; - case TLS_PSK_WITH_NULL_SHA256 : - return "TLS_PSK_WITH_NULL_SHA256"; - case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 : - return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"; - case TLS_DHE_PSK_WITH_NULL_SHA256 : - return "TLS_DHE_PSK_WITH_NULL_SHA256"; - #ifdef HAVE_AESGCM - case TLS_PSK_WITH_AES_128_GCM_SHA256 : - return "TLS_PSK_WITH_AES_128_GCM_SHA256"; - case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 : - return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"; - #endif + case sha256_mac: + macStr = "SHA256"; + break; #endif -#ifdef WOLFSSL_SHA384 - case TLS_PSK_WITH_AES_256_CBC_SHA384 : - return "TLS_PSK_WITH_AES_256_CBC_SHA384"; - case TLS_PSK_WITH_NULL_SHA384 : - return "TLS_PSK_WITH_NULL_SHA384"; - case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 : - return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"; - case TLS_DHE_PSK_WITH_NULL_SHA384 : - return "TLS_DHE_PSK_WITH_NULL_SHA384"; - #ifdef HAVE_AESGCM - case TLS_PSK_WITH_AES_256_GCM_SHA384 : - return "TLS_PSK_WITH_AES_256_GCM_SHA384"; - case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 : - return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"; - #endif +#ifdef HAVE_SHA384 + case sha384_mac: + macStr = "SHA384"; + break; #endif -#ifndef NO_SHA - case TLS_PSK_WITH_NULL_SHA : - return "TLS_PSK_WITH_NULL_SHA"; +#ifdef HAVE_SHA512 + case sha512_mac: + macStr = "SHA512"; + break; #endif -#endif /* NO_PSK */ -#ifndef NO_RSA - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 : - return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 : - return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; -#ifndef NO_SHA - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA : - return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA : - return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; -#endif -#ifndef NO_HC128 - #ifndef NO_MD5 - case TLS_RSA_WITH_HC_128_MD5 : - return "TLS_RSA_WITH_HC_128_MD5"; - #endif - #ifndef NO_SHA - case TLS_RSA_WITH_HC_128_SHA : - return "TLS_RSA_WITH_HC_128_SHA"; - #endif - #ifdef HAVE_BLAKE2 - case TLS_RSA_WITH_HC_128_B2B256: - return "TLS_RSA_WITH_HC_128_B2B256"; - #endif -#endif /* NO_HC128 */ -#ifndef NO_SHA - #ifndef NO_RABBIT - case TLS_RSA_WITH_RABBIT_SHA : - return "TLS_RSA_WITH_RABBIT_SHA"; - #endif - #ifdef HAVE_NTRU - #ifndef NO_RC4 - case TLS_NTRU_RSA_WITH_RC4_128_SHA : - return "TLS_NTRU_RSA_WITH_RC4_128_SHA"; - #endif - #ifndef NO_DES3 - case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA : - return "TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA"; - #endif - case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA : - return "TLS_NTRU_RSA_WITH_AES_128_CBC_SHA"; - case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA : - return "TLS_NTRU_RSA_WITH_AES_256_CBC_SHA"; - #endif /* HAVE_NTRU */ -#endif /* NO_SHA */ - case TLS_RSA_WITH_AES_128_GCM_SHA256 : - return "TLS_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_RSA_WITH_AES_256_GCM_SHA384 : - return "TLS_RSA_WITH_AES_256_GCM_SHA384"; - case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 : - return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 : - return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; -#ifndef NO_SHA - case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA : - return "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"; - case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA : - return "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"; -#endif - case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 : - return "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"; - case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 : - return "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"; -#ifndef NO_SHA - case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA : - return "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"; - case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA : - return "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"; -#endif - case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 : - return "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"; - case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 : - return "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"; -#endif /* NO_RSA */ -#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 - default: - return "NONE"; - } /* switch */ - } /* normal / ECC */ + default: + macStr = "unknown"; + break; } -#endif /* NO_ERROR_STRINGS */ - return "NONE"; + + /* 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; } -const char* wolfSSL_get_cipher(WOLFSSL* ssl) +#ifndef NO_SESSION_CACHE + +WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) { - WOLFSSL_ENTER("wolfSSL_get_cipher"); - return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl)); + if (ssl == NULL) { + return NULL; + } + + /* sessions are stored statically, no need for reference count */ + return wolfSSL_get_session(ssl); } -#ifdef OPENSSL_EXTRA +#endif /* NO_SESSION_CACHE */ -char* wolfSSL_CIPHER_description(WOLFSSL_CIPHER* cipher, char* in, int len) -{ - (void)cipher; - (void)in; - (void)len; - return 0; -} - - -WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) /* what's ref count */ -{ - (void)ssl; - return 0; -} - - -void wolfSSL_X509_free(WOLFSSL_X509* buf) -{ - FreeX509(buf); -} - - /* was do nothing */ /* void OPENSSL_free(void* buf) @@ -9821,7 +21399,7 @@ void OPENSSL_free(void* buf) } */ - +#ifndef NO_WOLFSSL_STUB int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, int* ssl) { @@ -9830,21 +21408,10 @@ int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, (void)port; (void)path; (void)ssl; + WOLFSSL_STUB("OCSP_parse_url"); return 0; } - - -WOLFSSL_METHOD* wolfSSLv2_client_method(void) -{ - return 0; -} - - -WOLFSSL_METHOD* wolfSSLv2_server_method(void) -{ - return 0; -} - +#endif #ifndef NO_MD4 @@ -9876,17 +21443,29 @@ void wolfSSL_MD4_Final(unsigned char* digest, WOLFSSL_MD4_CTX* md4) #endif /* NO_MD4 */ -WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* top) +/* Removes a WOLFSSL_BIO struct from the WOLFSSL_BIO linked list. + * + * bio is the WOLFSSL_BIO struct in the list and removed. + * + * The return WOLFSSL_BIO struct is the next WOLFSSL_BIO in the list or NULL if + * there is none. + */ +WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* bio) { - (void)top; - return 0; -} + if (bio == NULL) { + WOLFSSL_MSG("Bad argument passed in"); + return NULL; + } + if (bio->prev != NULL) { + bio->prev->next = bio->next; + } -int wolfSSL_BIO_pending(WOLFSSL_BIO* bio) -{ - (void)bio; - return 0; + if (bio->next != NULL) { + bio->next->prev = bio->prev; + } + + return bio->next; } @@ -9895,8 +21474,8 @@ WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void) { static WOLFSSL_BIO_METHOD meth; - WOLFSSL_ENTER("BIO_s_mem"); - meth.type = BIO_MEMORY; + WOLFSSL_ENTER("wolfSSL_BIO_s_mem"); + meth.type = WOLFSSL_BIO_MEMORY; return &meth; } @@ -9904,38 +21483,89 @@ WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void) WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void) { - return 0; + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("wolfSSL_BIO_f_base64"); + meth.type = WOLFSSL_BIO_BASE64; + + return &meth; } +/* Set the flag for the bio. + * + * bio the structure to set the flag in + * flags the flag to use + */ void wolfSSL_BIO_set_flags(WOLFSSL_BIO* bio, int flags) { - (void)bio; - (void)flags; + WOLFSSL_ENTER("wolfSSL_BIO_set_flags"); + + if (bio != NULL) { + bio->flags |= flags; + } } +void wolfSSL_BIO_clear_flags(WOLFSSL_BIO *bio, int flags) +{ + WOLFSSL_ENTER("wolfSSL_BIO_clear_flags"); + if (bio != NULL) { + bio->flags &= ~flags; + } +} +/* Set ex_data for WOLFSSL_BIO + * + * bio : BIO structure to set ex_data in + * idx : Index of ex_data to set + * data : Data to set in ex_data + * + * Returns WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE on failure + */ +int wolfSSL_BIO_set_ex_data(WOLFSSL_BIO *bio, int idx, void *data) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_ex_data"); + #ifdef HAVE_EX_DATA + if (bio != NULL && idx < MAX_EX_DATA) { + return wolfSSL_CRYPTO_set_ex_data(&bio->ex_data, idx, data); + } + #else + (void)bio; + (void)idx; + (void)data; + #endif + return WOLFSSL_FAILURE; +} +/* Get ex_data in WOLFSSL_BIO at given index + * + * bio : BIO structure to get ex_data from + * idx : Index of ex_data to get data from + * + * Returns void pointer to ex_data on success or NULL on failure + */ +void *wolfSSL_BIO_get_ex_data(WOLFSSL_BIO *bio, int idx) +{ + WOLFSSL_ENTER("wolfSSL_BIO_get_ex_data"); + #ifdef HAVE_EX_DATA + if (bio != NULL && idx < MAX_EX_DATA && idx >= 0) { + return wolfSSL_CRYPTO_get_ex_data(&bio->ex_data, idx); + } + #else + (void)bio; + (void)idx; + #endif + return NULL; +} + +#ifndef NO_WOLFSSL_STUB void wolfSSL_RAND_screen(void) { - + WOLFSSL_STUB("RAND_screen"); } +#endif -const char* wolfSSL_RAND_file_name(char* fname, unsigned long len) -{ - (void)fname; - (void)len; - return 0; -} - - -int wolfSSL_RAND_write_file(const char* fname) -{ - (void)fname; - return 0; -} - int wolfSSL_RAND_load_file(const char* fname, long len) { @@ -9948,177 +21578,1108 @@ int wolfSSL_RAND_load_file(const char* fname, long len) } -int wolfSSL_RAND_egd(const char* path) -{ - (void)path; - return 0; -} - - - +#ifndef NO_WOLFSSL_STUB WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void) { + WOLFSSL_STUB("COMP_zlib"); return 0; } +#endif - +#ifndef NO_WOLFSSL_STUB WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void) { + WOLFSSL_STUB("COMP_rle"); return 0; } +#endif - +#ifndef NO_WOLFSSL_STUB int wolfSSL_COMP_add_compression_method(int method, void* data) { (void)method; (void)data; + WOLFSSL_STUB("COMP_add_compression_method"); return 0; } +#endif - - -int wolfSSL_get_ex_new_index(long idx, void* data, void* cb1, void* cb2, - void* cb3) -{ - (void)idx; - (void)data; - (void)cb1; - (void)cb2; - (void)cb3; - return 0; -} - - +#ifndef NO_WOLFSSL_STUB void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)( const char*, int)) { + WOLFSSL_STUB("CRYPTO_set_dynlock_create_callback"); (void)f; } +#endif - +#ifndef NO_WOLFSSL_STUB void wolfSSL_set_dynlock_lock_callback( void (*f)(int, WOLFSSL_dynlock_value*, const char*, int)) { + WOLFSSL_STUB("CRYPTO_set_set_dynlock_lock_callback"); (void)f; } +#endif - +#ifndef NO_WOLFSSL_STUB void wolfSSL_set_dynlock_destroy_callback( void (*f)(WOLFSSL_dynlock_value*, const char*, int)) { + WOLFSSL_STUB("CRYPTO_set_set_dynlock_destroy_callback"); (void)f; } - +#endif const char* wolfSSL_X509_verify_cert_error_string(long err) { - (void)err; - return 0; + return wolfSSL_ERR_reason_error_string(err); } - +#ifndef NO_WOLFSSL_STUB int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir, long len) { (void)lookup; (void)dir; (void)len; + WOLFSSL_STUB("X509_LOOKUP_add_dir"); return 0; } - +#endif int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, - const char* file, long len) + const char* file, long type) { +#if !defined(NO_FILESYSTEM) && \ + (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)) + int ret = WOLFSSL_FAILURE; + XFILE fp; + long sz; + byte* pem = NULL; + byte* curr = NULL; + byte* prev = NULL; + WOLFSSL_X509* x509; + const char* header = NULL; + const char* footer = NULL; + + if (type != X509_FILETYPE_PEM) + return BAD_FUNC_ARG; + + fp = XFOPEN(file, "r"); + if (fp == XBADFILE) + return BAD_FUNC_ARG; + + if(XFSEEK(fp, 0, XSEEK_END) != 0) { + XFCLOSE(fp); + return WOLFSSL_BAD_FILE; + } + sz = XFTELL(fp); + XREWIND(fp); + + if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { + WOLFSSL_MSG("X509_LOOKUP_load_file size error"); + 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 { + /* get PEM header and footer based on type */ + if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 && + XSTRNSTR((char*)curr, header, (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, + NO_VERIFY); + if (ret != WOLFSSL_SUCCESS) + goto end; +#endif + curr = (byte*)XSTRNSTR((char*)curr, footer, (unsigned int)sz); + } + else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 && + XSTRNSTR((char*)curr, header, (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, footer, (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; + WOLFSSL_ENTER("SSL_X509_STORE_add_lookup"); + if (store == NULL) + return NULL; + + /* 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; +} + + +#ifndef NO_CERTS +/* Converts the X509 to DER format and outputs it into bio. + * + * bio is the structure to hold output DER + * x509 certificate to create DER from + * + * returns WOLFSSL_SUCCESS on success + */ +int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509) +{ + WOLFSSL_ENTER("wolfSSL_i2d_X509_bio"); + + if (bio == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + if (x509->derCert != NULL) { + word32 len = x509->derCert->length; + byte* der = x509->derCert->buffer; + + if (wolfSSL_BIO_write(bio, der, len) == (int)len) { + return SSL_SUCCESS; + } + } + + return WOLFSSL_FAILURE; +} + + +/* Converts an internal structure to a DER buffer + * + * x509 structure to get DER buffer from + * out buffer to hold result. If NULL then *out is NULL then a new buffer is + * created. + * + * returns the size of the DER result on success + */ +int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out) +{ + const unsigned char* der; + int derSz = 0; + + WOLFSSL_ENTER("wolfSSL_i2d_X509"); + + if (x509 == NULL) { + WOLFSSL_LEAVE("wolfSSL_i2d_X509", BAD_FUNC_ARG); + return BAD_FUNC_ARG; + } + + der = wolfSSL_X509_get_der(x509, &derSz); + if (der == NULL) { + WOLFSSL_LEAVE("wolfSSL_i2d_X509", MEMORY_E); + return MEMORY_E; + } + + if (out != NULL && *out == NULL) { + *out = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL); + if (*out == NULL) { + WOLFSSL_LEAVE("wolfSSL_i2d_X509", MEMORY_E); + return MEMORY_E; + } + } + + if (out != NULL) + XMEMCPY(*out, der, derSz); + + WOLFSSL_LEAVE("wolfSSL_i2d_X509", derSz); + return derSz; +} + + +/* Converts the DER from bio and creates a WOLFSSL_X509 structure from it. + * + * bio is the structure holding DER + * x509 certificate to create from DER. Can be NULL + * + * returns pointer to WOLFSSL_X509 structure on success and NULL on fail + */ +WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509) +{ + WOLFSSL_X509* localX509 = NULL; + unsigned char* mem = NULL; + int ret; + word32 size; + + WOLFSSL_ENTER("wolfSSL_d2i_X509_bio"); + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + + ret = wolfSSL_BIO_get_mem_data(bio, &mem); + if (mem == NULL || ret <= 0) { + WOLFSSL_MSG("Failed to get data from bio struct"); + return NULL; + } + size = ret; + + localX509 = wolfSSL_X509_d2i(NULL, mem, size); + if (localX509 == NULL) { + return NULL; + } + + if (x509 != NULL) { + *x509 = localX509; + } + + return localX509; +} + + +#if !defined(NO_ASN) && !defined(NO_PWDBASED) +WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) +{ + WC_PKCS12* localPkcs12 = NULL; + unsigned char* mem = NULL; + int ret; + word32 size; + + WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio"); + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + + localPkcs12 = wc_PKCS12_new(); + if (localPkcs12 == NULL) { + WOLFSSL_MSG("Memory error"); + return NULL; + } + + if (pkcs12 != NULL) { + *pkcs12 = localPkcs12; + } + + ret = wolfSSL_BIO_get_mem_data(bio, &mem); + if (mem == NULL || ret <= 0) { + WOLFSSL_MSG("Failed to get data from bio struct"); + wc_PKCS12_free(localPkcs12); + if (pkcs12 != NULL) { + *pkcs12 = NULL; + } + return NULL; + } + size = ret; + + ret = wc_d2i_PKCS12(mem, size, localPkcs12); + if (ret < 0) { + WOLFSSL_MSG("Failed to get PKCS12 sequence"); + wc_PKCS12_free(localPkcs12); + if (pkcs12 != NULL) { + *pkcs12 = NULL; + } + return NULL; + } + + return localPkcs12; +} + +/* Converts the PKCS12 to DER format and outputs it into bio. + * + * bio is the structure to hold output DER + * pkcs12 structure to create DER from + * + * return 1 for success or 0 if an error occurs + */ +int wolfSSL_i2d_PKCS12_bio(WOLFSSL_BIO *bio, WC_PKCS12 *pkcs12) +{ + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_i2d_PKCS12_bio"); + + if ((bio != NULL) && (pkcs12 != NULL)) { + word32 certSz = 0; + byte *certDer = NULL; + + certSz = wc_i2d_PKCS12(pkcs12, &certDer, NULL); + if ((certSz > 0) && (certDer != NULL)) { + if (wolfSSL_BIO_write(bio, certDer, certSz) == (int)certSz) { + ret = SSL_SUCCESS; + } + } + + if (certDer != NULL) { + XFREE(certDer, NULL, DYNAMIC_TYPE_PKCS); + } + } + + return ret; +} + +/* helper function to get raw pointer to DER buffer from WOLFSSL_EVP_PKEY */ +static int wolfSSL_EVP_PKEY_get_der(WOLFSSL_EVP_PKEY* key, unsigned char** der) +{ + if (!key) + return WOLFSSL_FAILURE; + if (der) + *der = (unsigned char*)key->pkey.ptr; + return key->pkey_sz; +} + +/* Copies unencrypted DER key buffer into "der". If "der" is null then the size + * of buffer needed is returned + * NOTE: This also advances the "der" pointer to be at the end of buffer. + * + * Returns size of key buffer on success + */ +int wolfSSL_i2d_PrivateKey(WOLFSSL_EVP_PKEY* key, unsigned char** der) +{ + if (key == NULL) { + return WOLFSSL_FATAL_ERROR; + } + + if (key->pkey_sz <= 0 || !key->pkey.ptr) { + return WOLFSSL_FATAL_ERROR; + } + + if (der != NULL) { + /* since this function signature has no size value passed in it is + * assumed that the user has allocated a large enough buffer */ + XMEMCPY(*der, key->pkey.ptr, key->pkey_sz); + *der += key->pkey_sz; + } + return key->pkey_sz; +} + +/* Creates a new WC_PKCS12 structure + * + * pass password to use + * name friendlyName to use + * pkey private key to go into PKCS12 bundle + * cert certificate to go into PKCS12 bundle + * ca extra certificates that can be added to bundle. Can be NULL + * keyNID type of encryption to use on the key (-1 means no encryption) + * certNID type of encryption to use on the certificate + * itt number of iterations with encryption + * macItt number of iterations with mac creation + * keyType flag for signature and/or encryption key + * + * returns a pointer to a new WC_PKCS12 structure on success and NULL on fail + */ +WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name, + WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert, + WOLF_STACK_OF(WOLFSSL_X509)* ca, + int keyNID, int certNID, int itt, int macItt, int keyType) +{ + WC_PKCS12* pkcs12; + WC_DerCertList* list = NULL; + word32 passSz; + byte* keyDer; + word32 keyDerSz; + byte* certDer; + int certDerSz; + + int ret; + + WOLFSSL_ENTER("wolfSSL_PKCS12_create()"); + + if (pass == NULL || pkey == NULL || cert == NULL) { + WOLFSSL_LEAVE("wolfSSL_PKCS12_create()", BAD_FUNC_ARG); + return NULL; + } + passSz = (word32)XSTRLEN(pass); + + if ((ret = wolfSSL_EVP_PKEY_get_der(pkey, &keyDer)) < 0) { + WOLFSSL_LEAVE("wolfSSL_PKCS12_create", ret); + return NULL; + } + keyDerSz = ret; + + certDer = (byte*)wolfSSL_X509_get_der(cert, &certDerSz); + if (certDer == NULL) { + return NULL; + } + + if (ca != NULL) { + WC_DerCertList* cur; + unsigned long numCerts = ca->num; + byte* curDer; + int curDerSz = 0; + WOLFSSL_STACK* sk = ca; + + while (numCerts > 0 && sk != NULL) { + cur = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), NULL, + DYNAMIC_TYPE_PKCS); + if (cur == NULL) { + wc_FreeCertList(list, NULL); + return NULL; + } + + curDer = (byte*)wolfSSL_X509_get_der(sk->data.x509, &curDerSz); + if (curDer == NULL || curDerSz < 0) { + XFREE(cur, NULL, DYNAMIC_TYPE_PKCS); + wc_FreeCertList(list, NULL); + return NULL; + } + + cur->buffer = (byte*)XMALLOC(curDerSz, NULL, DYNAMIC_TYPE_PKCS); + if (cur->buffer == NULL) { + XFREE(cur, NULL, DYNAMIC_TYPE_PKCS); + wc_FreeCertList(list, NULL); + return NULL; + } + XMEMCPY(cur->buffer, curDer, curDerSz); + cur->bufferSz = curDerSz; + cur->next = list; + list = cur; + + sk = sk->next; + numCerts--; + } + } + + pkcs12 = wc_PKCS12_create(pass, passSz, name, keyDer, keyDerSz, + certDer, certDerSz, list, keyNID, certNID, itt, macItt, + keyType, NULL); + + if (ca != NULL) { + wc_FreeCertList(list, NULL); + } + + return pkcs12; +} + + +/* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure */ +int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, + WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, WOLF_STACK_OF(WOLFSSL_X509)** ca) +{ + DecodedCert DeCert; + void* heap = NULL; + int ret; + byte* certData = NULL; + word32 certDataSz; + byte* pk = NULL; + word32 pkSz; + WC_DerCertList* certList = NULL; + + WOLFSSL_ENTER("wolfSSL_PKCS12_parse"); + + /* make sure we init return args */ + if (pkey) *pkey = NULL; + if (cert) *cert = NULL; + if (ca) *ca = NULL; + + if (pkcs12 == NULL || psw == NULL || pkey == NULL || cert == NULL) { + WOLFSSL_MSG("Bad argument value"); + return WOLFSSL_FAILURE; + } + + heap = wc_PKCS12_GetHeap(pkcs12); + + if (ca == NULL) { + ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz, + NULL); + } + else { + ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz, + &certList); + } + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret); + return WOLFSSL_FAILURE; + } + + /* Decode cert and place in X509 stack struct */ + if (certList != NULL) { + WC_DerCertList* current = certList; + + *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_PUBLIC_KEY); + } + if (certData != NULL) { + XFREE(*cert, heap, DYNAMIC_TYPE_PKCS); *cert = NULL; + } + /* Free up WC_DerCertList and move on */ + while (current != NULL) { + WC_DerCertList* next = current->next; + + XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + current = next; + } + return WOLFSSL_FAILURE; + } + XMEMSET(*ca, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509))); + + /* add list of DER certs as X509's to stack */ + while (current != NULL) { + WC_DerCertList* toFree = current; + WOLFSSL_X509* x509; + + x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, + DYNAMIC_TYPE_X509); + InitX509(x509, 1, heap); + InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap); + if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) { + WOLFSSL_MSG("Issue with parsing certificate"); + FreeDecodedCert(&DeCert); + wolfSSL_X509_free(x509); + } + else { + if ((ret = CopyDecodedToX509(x509, &DeCert)) != 0) { + WOLFSSL_MSG("Failed to copy decoded cert"); + FreeDecodedCert(&DeCert); + wolfSSL_X509_free(x509); + wolfSSL_sk_X509_free(*ca); *ca = NULL; + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (certData != NULL) { + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + } + /* Free up WC_DerCertList */ + while (current != NULL) { + WC_DerCertList* next = current->next; + + XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + current = next; + } + return WOLFSSL_FAILURE; + } + FreeDecodedCert(&DeCert); + + if (wolfSSL_sk_X509_push(*ca, x509) != 1) { + WOLFSSL_MSG("Failed to push x509 onto stack"); + wolfSSL_X509_free(x509); + wolfSSL_sk_X509_free(*ca); *ca = NULL; + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (certData != NULL) { + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + } + + /* Free up WC_DerCertList */ + while (current != NULL) { + WC_DerCertList* next = current->next; + + XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + current = next; + } + return WOLFSSL_FAILURE; + } + } + current = current->next; + XFREE(toFree->buffer, heap, DYNAMIC_TYPE_PKCS); + XFREE(toFree, heap, DYNAMIC_TYPE_PKCS); + } + } + + + /* Decode cert and place in X509 struct */ + if (certData != NULL) { + *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, + DYNAMIC_TYPE_X509); + if (*cert == NULL) { + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + return WOLFSSL_FAILURE; + } + InitX509(*cert, 1, heap); + InitDecodedCert(&DeCert, certData, certDataSz, heap); + if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) { + WOLFSSL_MSG("Issue with parsing certificate"); + } + if ((ret = CopyDecodedToX509(*cert, &DeCert)) != 0) { + WOLFSSL_MSG("Failed to copy decoded cert"); + FreeDecodedCert(&DeCert); + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + wolfSSL_X509_free(*cert); *cert = NULL; + return WOLFSSL_FAILURE; + } + FreeDecodedCert(&DeCert); + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + } + + + /* get key type */ + ret = BAD_STATE_E; + if (pk != NULL) { /* decode key if present */ + *pkey = wolfSSL_EVP_PKEY_new_ex(heap); + if (*pkey == NULL) { + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + return WOLFSSL_FAILURE; + } + #ifndef NO_RSA + { + word32 keyIdx = 0; + RsaKey key; + + if (wc_InitRsaKey(&key, heap) != 0) { + ret = BAD_STATE_E; + } + else { + if ((ret = wc_RsaPrivateKeyDecode(pk, &keyIdx, &key, pkSz)) + == 0) { + (*pkey)->type = EVP_PKEY_RSA; + (*pkey)->rsa = wolfSSL_RSA_new(); + (*pkey)->ownRsa = 1; /* we own RSA */ + if ((*pkey)->rsa == NULL) { + WOLFSSL_MSG("issue creating EVP RSA key"); + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; + XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + return WOLFSSL_FAILURE; + } + if ((ret = wolfSSL_RSA_LoadDer_ex((*pkey)->rsa, pk, pkSz, + WOLFSSL_RSA_LOAD_PRIVATE)) != SSL_SUCCESS) { + WOLFSSL_MSG("issue loading RSA key"); + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; + XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + return WOLFSSL_FAILURE; + } + + WOLFSSL_MSG("Found PKCS12 RSA key"); + ret = 0; /* set in success state for upcoming ECC check */ + } + wc_FreeRsaKey(&key); + } + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + { + word32 keyIdx = 0; + ecc_key key; + + if (ret != 0) { /* if is in fail state check if ECC key */ + if (wc_ecc_init(&key) != 0) { + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; + XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + return WOLFSSL_FAILURE; + } + + if ((ret = wc_EccPrivateKeyDecode(pk, &keyIdx, &key, pkSz)) + != 0) { + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; + XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + WOLFSSL_MSG("Bad PKCS12 key format"); + return WOLFSSL_FAILURE; + } + (*pkey)->type = EVP_PKEY_EC; + (*pkey)->pkey_curve = key.dp->oidSum; + wc_ecc_free(&key); + WOLFSSL_MSG("Found PKCS12 ECC key"); + } + } + #else + if (ret != 0) { /* if is in fail state and no ECC then fail */ + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; + XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + WOLFSSL_MSG("Bad PKCS12 key format"); + return WOLFSSL_FAILURE; + } + #endif /* HAVE_ECC */ + + (*pkey)->save_type = 0; + (*pkey)->pkey_sz = pkSz; + (*pkey)->pkey.ptr = (char*)pk; + } + + (void)ret; + (void)ca; + + return WOLFSSL_SUCCESS; +} +#endif /* !defined(NO_ASN) && !defined(NO_PWDBASED) */ + + +/* no-op function. Was initially used for adding encryption algorithms available + * for PKCS12 */ +void wolfSSL_PKCS12_PBE_add(void) +{ + WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add"); +} + + + +WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_chain"); + + if (ctx == NULL) { + return NULL; + } + +#ifdef SESSION_CERTS + /* if chain is null but sesChain is available then populate stack */ + if (ctx->chain == NULL && ctx->sesChain != NULL) { + int i; + WOLFSSL_X509_CHAIN* c = ctx->sesChain; + WOLFSSL_STACK* sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), + NULL, DYNAMIC_TYPE_X509); + + if (sk == NULL) { + return NULL; + } + + XMEMSET(sk, 0, sizeof(WOLFSSL_STACK)); + ctx->chain = sk; + + for (i = 0; i < c->count && i < MAX_CHAIN_DEPTH; i++) { + WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, i); + + if (x509 == NULL) { + WOLFSSL_MSG("Unable to get x509 from chain"); + wolfSSL_sk_X509_free(sk); + return NULL; + } + + if (wolfSSL_sk_X509_push(sk, x509) != SSL_SUCCESS) { + WOLFSSL_MSG("Unable to load x509 into stack"); + wolfSSL_sk_X509_free(sk); + wolfSSL_X509_free(x509); + return NULL; + } + } + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) + /* add CA used to verify top of chain to the list */ + if (c->count > 0) { + WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, c->count - 1); + if (x509 != NULL) { + WOLFSSL_X509* issuer = NULL; + if (wolfSSL_X509_STORE_CTX_get1_issuer(&issuer, ctx, x509) + == WOLFSSL_SUCCESS) { + /* check that the certificate being looked up is not self + * signed and that a issuer was found */ + if (issuer != NULL && wolfSSL_X509_NAME_cmp(&x509->issuer, + &x509->subject) != 0) { + if (wolfSSL_sk_X509_push(sk, issuer) != SSL_SUCCESS) { + WOLFSSL_MSG("Unable to load CA x509 into stack"); + wolfSSL_sk_X509_free(sk); + wolfSSL_X509_free(issuer); + return NULL; + } + } + else { + WOLFSSL_MSG("Certificate is self signed"); + if (issuer != NULL) + wolfSSL_X509_free(issuer); + } + } + else { + WOLFSSL_MSG("Could not find CA for certificate"); + } + } + } +#endif + + } +#endif /* SESSION_CERTS */ + + return ctx->chain; +} + +/* make shallow copy of the stack, data pointers are copied by reference */ +WOLFSSL_STACK* wolfSSL_sk_X509_dup(WOLFSSL_STACK* sk) +{ + unsigned long i; + WOLFSSL_STACK* dup = NULL; + WOLFSSL_STACK* node = NULL; + WOLFSSL_STACK *dIdx = NULL, *sIdx = sk; + + if (sk == NULL) { + return NULL; + } + + for (i = 0; i < sk->num; i++) { + + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_X509); + if (node == NULL) { + if (i != 0) { + wolfSSL_sk_free(dup); + } + WOLFSSL_MSG("Memory error"); + return NULL; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* copy sk node to new node, data by reference */ + node->data.x509 = sIdx->data.x509; + node->num = sIdx->num; + + /* insert node into list, progress idx */ + if (i == 0) { + dup = node; + } else { + dIdx->next = node; + } + + dIdx = node; + sIdx = sIdx->next; + } + + return dup; +} + + +/* like X509_STORE_CTX_get_chain(), but return a copy with data reference + counts increased */ +WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get1_chain(WOLFSSL_X509_STORE_CTX* ctx) +{ + unsigned long i; + WOLFSSL_STACK* ref; + WOLFSSL_STACK* dup; + + if (ctx == NULL) { + return NULL; + } + + /* get chain in ctx */ + ref = wolfSSL_X509_STORE_CTX_get_chain(ctx); + if (ref == NULL) { + return ref; + } + + /* create duplicate of ctx chain */ + dup = wolfSSL_sk_X509_dup(ref); + if (dup == NULL) { + return NULL; + } + + /* increase ref counts of inner data X509 */ + ref = dup; + for (i = 0; i < dup->num && ref != NULL; i++) { + if (wc_LockMutex(&ref->data.x509->refMutex) != 0) { + WOLFSSL_MSG("Failed to lock x509 mutex"); + } + ref->data.x509->refCount++; + wc_UnLockMutex(&ref->data.x509->refMutex); + ref = ref->next; + } + + return dup; } 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) { - buffer derCert; - derCert.buffer = (byte*)XMALLOC(x509->derCert.length, - NULL, DYNAMIC_TYPE_CERT); - if (derCert.buffer != NULL) { - derCert.length = x509->derCert.length; - /* AddCA() frees the buffer. */ - XMEMCPY(derCert.buffer, - x509->derCert.buffer, x509->derCert.length); - result = AddCA(store->cm, derCert, WOLFSSL_USER_CA, 1); - if (result != SSL_SUCCESS) result = SSL_FATAL_ERROR; + if (store != NULL && store->cm != NULL && x509 != NULL + && x509->derCert != NULL) { + DerBuffer* derCert = NULL; + + result = AllocDer(&derCert, x509->derCert->length, + x509->derCert->type, NULL); + if (result == 0) { + /* AddCA() frees the buffer. */ + XMEMCPY(derCert->buffer, + x509->derCert->buffer, x509->derCert->length); + result = AddCA(store->cm, &derCert, WOLFSSL_USER_CA, VERIFY); } } WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_cert", result); + + if (result != WOLFSSL_SUCCESS) { + result = WOLFSSL_FATAL_ERROR; + } + return result; } - WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) { WOLFSSL_X509_STORE* store = NULL; + WOLFSSL_ENTER("SSL_X509_STORE_new"); - store = (WOLFSSL_X509_STORE*)XMALLOC(sizeof(WOLFSSL_X509_STORE), NULL, 0); - if (store != NULL) { - store->cm = wolfSSL_CertManagerNew(); - if (store->cm == NULL) { - XFREE(store, NULL, 0); - store = NULL; - } - } + if ((store = (WOLFSSL_X509_STORE*)XMALLOC(sizeof(WOLFSSL_X509_STORE), NULL, + DYNAMIC_TYPE_X509_STORE)) == NULL) + goto err_exit; + + XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE)); + store->isDynamic = 1; + + if ((store->cm = wolfSSL_CertManagerNew()) == NULL) + goto err_exit; + +#ifdef HAVE_CRL + store->crl = NULL; + if ((store->crl = (WOLFSSL_X509_CRL *)XMALLOC(sizeof(WOLFSSL_X509_CRL), + NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL) + goto err_exit; + if (InitCRL(store->crl, NULL) < 0) + goto err_exit; +#endif + +#ifdef OPENSSL_EXTRA + if ((store->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( + sizeof(WOLFSSL_X509_VERIFY_PARAM), + NULL,DYNAMIC_TYPE_OPENSSL)) == NULL) + goto err_exit; + +#endif return store; + +err_exit: + if (store == NULL) + return NULL; + + wolfSSL_X509_STORE_free(store); + + return NULL; } 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, 0); + wolfSSL_CertManagerFree(store->cm); +#ifdef HAVE_CRL + if (store->crl != NULL) + wolfSSL_X509_CRL_free(store->crl); +#endif +#ifdef OPENSSL_EXTRA + if (store->param != NULL) + XFREE(store->param, NULL, DYNAMIC_TYPE_OPENSSL); +#endif + XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); } } +int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag) +{ + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_X509_STORE_set_flags"); + + if (store == NULL) + return WOLFSSL_FAILURE; + + if ((flag & WOLFSSL_CRL_CHECKALL) || (flag & WOLFSSL_CRL_CHECK)) { + ret = wolfSSL_CertManagerEnableCRL(store->cm, (int)flag); + } + + (void)store; + (void)flag; + + return ret; +} + + int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store) { (void)store; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } - +#ifndef NO_WOLFSSL_STUB int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx, WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj) { @@ -10126,49 +22687,105 @@ int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx, (void)idx; (void)name; (void)obj; + WOLFSSL_STUB("X509_STORE_get_by_subject"); return 0; } - +#endif WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void) { - WOLFSSL_X509_STORE_CTX* ctx = (WOLFSSL_X509_STORE_CTX*)XMALLOC( - sizeof(WOLFSSL_X509_STORE_CTX), NULL, 0); + WOLFSSL_X509_STORE_CTX* ctx; + WOLFSSL_ENTER("X509_STORE_CTX_new"); - if (ctx != NULL) + ctx = (WOLFSSL_X509_STORE_CTX*)XMALLOC(sizeof(WOLFSSL_X509_STORE_CTX), NULL, + DYNAMIC_TYPE_X509_CTX); + if (ctx != NULL) { + ctx->param = NULL; wolfSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL); + } return ctx; } 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) { + WOLFSSL_X509* x509_cert; + int ret = 0; (void)sk; + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_init"); + if (ctx != NULL) { ctx->store = store; + #ifndef WOLFSSL_X509_STORE_CERTS ctx->current_cert = x509; + #else + if(x509 != NULL){ + ctx->current_cert = wolfSSL_X509_d2i(NULL, x509->derCert->buffer,x509->derCert->length); + if(ctx->current_cert == NULL) + return WOLFSSL_FATAL_ERROR; + } else + ctx->current_cert = NULL; + #endif + + ctx->chain = sk; + /* Add intermediate certificates from stack to store */ + while (sk != NULL) { + x509_cert = sk->data.x509; + if (x509_cert != NULL && x509_cert->isCa) { + ret = wolfSSL_X509_STORE_add_cert(store, x509_cert); + if (ret < 0) { + return WOLFSSL_FATAL_ERROR; + } + } + sk = sk->next; + } + + ctx->sesChain = NULL; ctx->domain = NULL; - ctx->ex_data = NULL; +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + XMEMSET(&ctx->ex_data, 0, sizeof(ctx->ex_data)); +#endif ctx->userCtx = NULL; ctx->error = 0; ctx->error_depth = 0; ctx->discardSessionCerts = 0; +#ifdef OPENSSL_EXTRA + if (ctx->param == NULL) { + 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; } void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx) { + WOLFSSL_ENTER("X509_STORE_CTX_free"); if (ctx != NULL) { + #if !defined(OPENSSL_ALL) && !defined(WOLFSSL_QT) if (ctx->store != NULL) wolfSSL_X509_STORE_free(ctx->store); + #ifndef WOLFSSL_KEEP_STORE_CERTS if (ctx->current_cert != NULL) wolfSSL_FreeX509(ctx->current_cert); - XFREE(ctx, NULL, 0); + #endif + #endif /* !OPENSSL_ALL && !WOLFSSL_QT */ +#ifdef OPENSSL_EXTRA + if (ctx->param != NULL){ + XFREE(ctx->param,NULL,DYNAMIC_TYPE_OPENSSL); + } +#endif + XFREE(ctx, NULL, DYNAMIC_TYPE_X509_CTX); } } @@ -10176,470 +22793,4495 @@ void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx) void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx) { (void)ctx; + /* Do nothing */ } +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +/* Returns corresponding X509 error from internal ASN error */ +static int GetX509Error(int e) +{ + switch (e) { + case ASN_BEFORE_DATE_E: + return X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; + case ASN_AFTER_DATE_E: + return X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; + case ASN_NO_SIGNER_E: + return X509_V_ERR_INVALID_CA; + case ASN_SELF_SIGNED_E: + return X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; + case ASN_PATHLEN_INV_E: + case ASN_PATHLEN_SIZE_E: + return X509_V_ERR_PATH_LENGTH_EXCEEDED; + case ASN_SIG_OID_E: + case ASN_SIG_CONFIRM_E: + case ASN_SIG_HASH_E: + case ASN_SIG_KEY_E: + return X509_V_ERR_CERT_SIGNATURE_FAILURE; + default: + WOLFSSL_MSG("Error not configured or implemented yet"); + return e; + } +} +#endif +/* Verifies certificate chain using WOLFSSL_X509_STORE_CTX + * returns 0 on success or < 0 on failure. + */ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx) { + int ret = 0; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + int depth = 0; + int error; + byte *afterDate, *beforeDate; +#endif + WOLFSSL_ENTER("wolfSSL_X509_verify_cert"); + if (ctx != NULL && ctx->store != NULL && ctx->store->cm != NULL - && ctx->current_cert != NULL) { - return wolfSSL_CertManagerVerifyBuffer(ctx->store->cm, - ctx->current_cert->derCert.buffer, - ctx->current_cert->derCert.length, - SSL_FILETYPE_ASN1); + && ctx->current_cert != NULL && ctx->current_cert->derCert != NULL) { + ret = wolfSSL_CertManagerVerifyBuffer(ctx->store->cm, + ctx->current_cert->derCert->buffer, + ctx->current_cert->derCert->length, + WOLFSSL_FILETYPE_ASN1); + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + /* If there was an error, process it and add it to CTX */ + if (ret < 0) { + /* Get corresponding X509 error */ + error = GetX509Error(ret); + /* Set error depth */ + if (ctx->chain) + depth = (int)ctx->chain->num; + + wolfSSL_X509_STORE_CTX_set_error(ctx, error); + wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth); + ctx->store->verify_cb(0, ctx); + } + + error = 0; + /* wolfSSL_CertManagerVerifyBuffer only returns ASN_AFTER_DATE_E or + ASN_BEFORE_DATE_E if there are no additional errors found in the + cert. Therefore, check if the cert is expired or not yet valid + in order to return the correct expected error. */ + afterDate = ctx->current_cert->notAfter.data; + beforeDate = ctx->current_cert->notBefore.data; + + if (ValidateDate(afterDate, ctx->current_cert->notAfter.type, + AFTER) < 1) { + error = X509_V_ERR_CERT_HAS_EXPIRED; + } + else if (ValidateDate(beforeDate, ctx->current_cert->notBefore.type, + BEFORE) < 1) { + error = X509_V_ERR_CERT_NOT_YET_VALID; + } + + if (error != 0 ) { + wolfSSL_X509_STORE_CTX_set_error(ctx, error); + wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth); + if (ctx->store && ctx->store->verify_cb) + ctx->store->verify_cb(0, ctx); + } +#endif /* OPENSSL_ALL || WOLFSSL_QT */ + return ret; } - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } +/* Use the public key to verify the signature. Note: this only verifies + * the certificate signature. + * returns WOLFSSL_SUCCESS on successful signature verification */ +int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey) +{ + int ret; + const byte* der; + int derSz = 0; + int type; + + if (x509 == NULL || pkey == NULL) { + return WOLFSSL_FATAL_ERROR; + } + + der = wolfSSL_X509_get_der(x509, &derSz); + if (der == NULL) { + WOLFSSL_MSG("Error getting WOLFSSL_X509 DER"); + return WOLFSSL_FATAL_ERROR; + } + + switch (pkey->type) { + case EVP_PKEY_RSA: + type = RSAk; + break; + + case EVP_PKEY_EC: + type = ECDSAk; + break; + + case EVP_PKEY_DSA: + type = DSAk; + break; + + default: + WOLFSSL_MSG("Unknown pkey key type"); + return WOLFSSL_FATAL_ERROR; + } + + ret = CheckCertSignaturePubKey(der, derSz, x509->heap, + (unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, type); + if (ret == 0) { + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} +#endif /* NO_CERTS */ + +#if !defined(NO_FILESYSTEM) +static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type) +{ + void *newx509 = NULL; + byte *fileBuffer = NULL; + long sz = 0; + + /* init variable */ + if (x509) + *x509 = NULL; + + /* argument check */ + if (file == XBADFILE) { + return NULL; + } + + /* determine file size */ + if (XFSEEK(file, 0, XSEEK_END) != 0) { + return NULL; + } + sz = XFTELL(file); + XREWIND(file); + + if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { + WOLFSSL_MSG("d2i_X509_fp_ex file size error"); + return NULL; + } + + fileBuffer = (byte *)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); + if (fileBuffer != NULL) { + if ((long)XFREAD(fileBuffer, 1, sz, file) != sz) { + WOLFSSL_MSG("File read failed"); + goto err_exit; + } + if (type == CERT_TYPE) { + newx509 = (void *)wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz); + } + #ifdef HAVE_CRL + else if (type == CRL_TYPE) { + newx509 = (void *)wolfSSL_d2i_X509_CRL(NULL, fileBuffer, (int)sz); + } + #endif + #if !defined(NO_ASN) && !defined(NO_PWDBASED) + else if (type == PKCS12_TYPE) { + if ((newx509 = wc_PKCS12_new()) == NULL) { + goto err_exit; + } + if (wc_d2i_PKCS12(fileBuffer, (int)sz, (WC_PKCS12*)newx509) < 0) { + goto err_exit; + } + } + #endif + else { + goto err_exit; + } + if (newx509 == NULL) { + WOLFSSL_MSG("X509 failed"); + goto err_exit; + } + } + + if (x509) + *x509 = newx509; + + goto _exit; + +err_exit: +#if !defined(NO_ASN) && !defined(NO_PWDBASED) + if ((newx509 != NULL) && (type == PKCS12_TYPE)) { + wc_PKCS12_free((WC_PKCS12*)newx509); + newx509 = NULL; + } +#endif +_exit: + if (fileBuffer != NULL) + XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); + + return newx509; +} + +WOLFSSL_X509_PKCS12 *wolfSSL_d2i_PKCS12_fp(XFILE fp, WOLFSSL_X509_PKCS12 **pkcs12) +{ + WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_fp"); + return (WOLFSSL_X509_PKCS12 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)pkcs12, PKCS12_TYPE); +} + +WOLFSSL_X509 *wolfSSL_d2i_X509_fp(XFILE fp, WOLFSSL_X509 **x509) +{ + WOLFSSL_ENTER("wolfSSL_d2i_X509_fp"); + return (WOLFSSL_X509 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)x509, CERT_TYPE); +} +#endif /* !NO_FILESYSTEM */ + + +#ifdef HAVE_CRL +#ifndef NO_FILESYSTEM +WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE fp, WOLFSSL_X509_CRL **crl) +{ + WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL_fp"); + return (WOLFSSL_X509_CRL *)wolfSSL_d2i_X509_fp_ex(fp, (void **)crl, CRL_TYPE); +} +#endif /* !NO_FILESYSTEM */ + + +WOLFSSL_X509_CRL* wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL** crl, + const unsigned char* in, int len) +{ + WOLFSSL_X509_CRL *newcrl = NULL; + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL"); + + if (in == NULL) { + WOLFSSL_MSG("Bad argument value"); + } else { + newcrl = (WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (newcrl == NULL){ + WOLFSSL_MSG("New CRL allocation failed"); + } else { + ret = InitCRL(newcrl, NULL); + if (ret < 0) { + WOLFSSL_MSG("Init tmp CRL failed"); + } else { + ret = BufferLoadCRL(newcrl, in, len, WOLFSSL_FILETYPE_ASN1, + NO_VERIFY); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Buffer Load CRL failed"); + } else { + if (crl) { + *crl = newcrl; + } + } + } + } + } + + if((ret != WOLFSSL_SUCCESS) && (newcrl != NULL)) { + wolfSSL_X509_CRL_free(newcrl); + newcrl = NULL; + } + + return newcrl; +} + +void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl) +{ + WOLFSSL_ENTER("wolfSSL_X509_CRL_free"); + + FreeCRL(crl, 1); + return; +} +#endif /* HAVE_CRL */ + +#ifndef NO_WOLFSSL_STUB WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL* crl) { (void)crl; + WOLFSSL_STUB("X509_CRL_get_lastUpdate"); return 0; } - - +#endif +#ifndef NO_WOLFSSL_STUB WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL* crl) { (void)crl; + WOLFSSL_STUB("X509_CRL_get_nextUpdate"); return 0; } +#endif - -WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509) -{ - WOLFSSL_EVP_PKEY* key = NULL; - if (x509 != NULL) { - key = (WOLFSSL_EVP_PKEY*)XMALLOC( - sizeof(WOLFSSL_EVP_PKEY), NULL, DYNAMIC_TYPE_PUBLIC_KEY); - if (key != NULL) { - key->type = x509->pubKeyOID; - key->save_type = 0; - key->pkey.ptr = (char*)XMALLOC( - x509->pubKey.length, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - if (key->pkey.ptr == NULL) { - XFREE(key, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - return NULL; - } - XMEMCPY(key->pkey.ptr, - x509->pubKey.buffer, x509->pubKey.length); - key->pkey_sz = x509->pubKey.length; - #ifdef HAVE_ECC - key->pkey_curve = (int)x509->pkCurveOID; - #endif /* HAVE_ECC */ - } - } - return key; -} - - +#ifndef NO_WOLFSSL_STUB int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* key) { (void)crl; (void)key; + WOLFSSL_STUB("X509_CRL_verify"); return 0; } +#endif +#endif /* OPENSSL_EXTRA */ +#ifdef OPENSSL_EXTRA -void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX* ctx, int err) +/* Gets pointer to X509_STORE that was used to create context. + * + * Return valid pointer on success, NULL if ctx was NULL or not initialized + */ +WOLFSSL_X509_STORE* wolfSSL_X509_STORE_CTX_get0_store( + WOLFSSL_X509_STORE_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get0_store"); + + if (ctx == NULL) + return NULL; + + return ctx->store; +} + +WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_cert(WOLFSSL_X509_STORE_CTX* ctx) +{ + if (ctx == NULL) + return NULL; + + return ctx->current_cert; +} + +void wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX* ctx, + unsigned long flags, + time_t t) +{ + (void)flags; + + if (ctx == NULL || ctx->param == NULL) + return; + + ctx->param->check_time = t; + ctx->param->flags |= WOLFSSL_USE_CHECK_TIME; +} + +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +#ifndef NO_WOLFSSL_STUB +int wolfSSL_X509_STORE_CTX_set_purpose(WOLFSSL_X509_STORE_CTX *ctx, + int purpose) { (void)ctx; - (void)err; + (void)purpose; + WOLFSSL_STUB("wolfSSL_X509_STORE_CTX_set_purpose"); + return 0; +} +#endif +#endif /* WOLFSSL_QT || OPENSSL_ALL */ + +#ifndef NO_WOLFSSL_STUB +/* Returns default file name and path of config file. However + a wolfssl.cnf file is not currently supported */ +char* wolfSSL_CONF_get1_default_config_file(void) +{ + WOLFSSL_ENTER("wolfSSL_CONF_get1_default_config_file"); + WOLFSSL_STUB("CONF_get1_default_config_file"); + return NULL; +} +#endif +/****************************************************************************** +* wolfSSL_X509_VERIFY_PARAM_set1_host - sets the DNS hostname to name +* hostnames is cleared if name is NULL or empty. +* +* RETURNS: +* +*/ +int wolfSSL_X509_VERIFY_PARAM_set1_host(WOLFSSL_X509_VERIFY_PARAM* pParam, + const char* name, + unsigned int nameSz) +{ + unsigned int sz = 0; + + if (pParam == NULL) + return WOLFSSL_FAILURE; + + XMEMSET(pParam->hostName, 0, WOLFSSL_HOST_NAME_MAX); + + if (name == NULL) + return WOLFSSL_SUCCESS; + + sz = (unsigned int)XSTRLEN(name); + + /* If name is NUL-terminated, namelen can be set to zero. */ + if(nameSz == 0 || nameSz > sz) + nameSz = sz; + + if (nameSz > 0 && name[nameSz - 1] == '\0') + nameSz--; + + if (nameSz > WOLFSSL_HOST_NAME_MAX-1) + nameSz = WOLFSSL_HOST_NAME_MAX-1; + + if (nameSz > 0) + XMEMCPY(pParam->hostName, name, nameSz); + + pParam->hostName[nameSz] = '\0'; + + return WOLFSSL_SUCCESS; +} +/****************************************************************************** +* wolfSSL_get0_param - return a pointer to the SSL verification parameters +* +* RETURNS: +* returns pointer to the SSL verification parameters on success, +* otherwise returns NULL +*/ +WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return NULL; + } + return ssl->param; } - -void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj) +/* Set the host flag in the X509_VERIFY_PARAM structure */ +void wolfSSL_X509_VERIFY_PARAM_set_hostflags(WOLFSSL_X509_VERIFY_PARAM* param, + unsigned int flags) { - (void)obj; -} - - -void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key) -{ - if (key != NULL) { - if (key->pkey.ptr != NULL) - XFREE(key->pkey.ptr, NULL, 0); - XFREE(key, NULL, 0); + if (param != NULL) { + param->hostFlags = flags; } } - -int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME* asnTime) +/* Sets the expected IP address to ipasc. + * + * param is a pointer to the X509_VERIFY_PARAM structure + * ipasc is a NULL-terminated string with N.N.N.N for IPv4 and + * HH:HH ... HH:HH for IPv6. There is no validation performed on the + * parameter, and it must be an exact match with the IP in the cert. + * + * return 1 for success and 0 for failure*/ +int wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(WOLFSSL_X509_VERIFY_PARAM *param, + const char *ipasc) { - (void)asnTime; - return 0; + int ret = WOLFSSL_FAILURE; + + if (param != NULL) { + if (ipasc == NULL) { + param->ipasc[0] = '\0'; + } + else { + XSTRNCPY(param->ipasc, ipasc, WOLFSSL_MAX_IPSTR-1); + param->ipasc[WOLFSSL_MAX_IPSTR-1] = '\0'; + } + ret = WOLFSSL_SUCCESS; + } + + return ret; } +#ifndef NO_WOLFSSL_STUB +void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj) +{ + (void)obj; + WOLFSSL_STUB("X509_OBJECT_free_contents"); +} +#endif +#ifndef NO_ASN_TIME +int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME* asnTime) +{ + return wolfSSL_X509_cmp_time(asnTime, NULL); +} + +/* return -1 if asnTime is earlier than or equal to cmpTime, and 1 otherwise + * return 0 on error + */ +int wolfSSL_X509_cmp_time(const WOLFSSL_ASN1_TIME* asnTime, time_t* cmpTime) +{ + int ret = WOLFSSL_FAILURE, i = 0; + time_t tmpTime, *pTime = &tmpTime; + byte data_ptr[MAX_TIME_STRING_SZ], inv = 0; + struct tm ts, *tmpTs, *ct; +#if defined(NEED_TMP_TIME) + /* for use with gmtime_r */ + struct tm tmpTimeStorage; + + tmpTs = &tmpTimeStorage; +#else + tmpTs = NULL; +#endif + (void)tmpTs; + + if (asnTime == NULL) { + return WOLFSSL_FAILURE; + } + + if (cmpTime == NULL) { + /* Use current time */ + *pTime = XTIME(0); + } + else { + pTime = cmpTime; + } + + /* Convert ASN1_time to time_t */ + XMEMSET(&ts, 0, sizeof(struct tm)); + + /* Check type */ + if (asnTime->type == ASN_UTC_TIME) { + /* 2-digit year */ + XMEMCPY(data_ptr, &asnTime->data[i], ASN_UTC_TIME_SIZE); + ts.tm_year = (data_ptr[i] - '0') * 10; i++; + ts.tm_year += data_ptr[i] - '0'; i++; + if (ts.tm_year < 70) { + ts.tm_year += 100; + } + } + else if (asnTime->type == ASN_GENERALIZED_TIME) { + /* 4-digit year */ + XMEMCPY(data_ptr, &asnTime->data[i], ASN_GENERALIZED_TIME_SIZE); + ts.tm_year = (data_ptr[i] - '0') * 1000; i++; + ts.tm_year += (data_ptr[i] - '0') * 100; i++; + ts.tm_year += (data_ptr[i] - '0') * 10; i++; + ts.tm_year += data_ptr[i] - '0'; i++; + ts.tm_year -= 1900; + } + else { + /* Invalid type */ + inv = 1; + } + + if (inv != 1) { + ts.tm_mon = (data_ptr[i] - '0') * 10; i++; + ts.tm_mon += (data_ptr[i] - '0') - 1; i++; /* January is 0 not 1 */ + ts.tm_mday = (data_ptr[i] - '0') * 10; i++; + ts.tm_mday += (data_ptr[i] - '0'); i++; + ts.tm_hour = (data_ptr[i] - '0') * 10; i++; + ts.tm_hour += (data_ptr[i] - '0'); i++; + ts.tm_min = (data_ptr[i] - '0') * 10; i++; + ts.tm_min += (data_ptr[i] - '0'); i++; + ts.tm_sec = (data_ptr[i] - '0') * 10; i++; + ts.tm_sec += (data_ptr[i] - '0'); + + /* Convert to time struct*/ + ct = XGMTIME(pTime, tmpTs); + + if (ct == NULL) + return GETTIME_ERROR; + + /* DateGreaterThan returns 1 for >; 0 for <= */ + ret = DateGreaterThan(&ts, ct) ? 1 : -1; + } + + return ret; +} +#endif /* !NO_ASN_TIME */ + +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) && !defined(USER_TIME) && \ + !defined(TIME_OVERRIDES) +WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj_ex(WOLFSSL_ASN1_TIME *asnTime, + int offset_day, long offset_sec, time_t *in_tm) +{ + /* get current time if in_tm is null */ + time_t t = in_tm ? *in_tm : XTIME(0); + return wolfSSL_ASN1_TIME_adj(asnTime, t, offset_day, offset_sec); +} + +WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj(WOLFSSL_ASN1_TIME *asnTime, + long offset_sec, time_t *in_tm) +{ + return wolfSSL_X509_time_adj_ex(asnTime, 0, offset_sec, in_tm); +} +#endif + +#ifndef NO_WOLFSSL_STUB int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED* revoked) { (void)revoked; + WOLFSSL_STUB("sk_X509_REVOKED_num"); return 0; } +#endif - - +#ifndef NO_WOLFSSL_STUB WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL* crl) { (void)crl; + WOLFSSL_STUB("X509_CRL_get_REVOKED"); return 0; } +#endif - +#ifndef NO_WOLFSSL_STUB WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value( WOLFSSL_X509_REVOKED* revoked, int value) { (void)revoked; (void)value; + WOLFSSL_STUB("sk_X509_REVOKED_value"); return 0; } +#endif +/* Used to create a new WOLFSSL_ASN1_INTEGER structure. + * returns a pointer to new structure on success and NULL on failure + */ +WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void) +{ + WOLFSSL_ASN1_INTEGER* a; + + a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL, + DYNAMIC_TYPE_OPENSSL); + if (a == NULL) { + return NULL; + } + + XMEMSET(a, 0, sizeof(WOLFSSL_ASN1_INTEGER)); + a->data = a->intData; + a->dataMax = WOLFSSL_ASN1_INTEGER_MAX; + a->length = 0; + return a; +} + + +/* free's internal elements of WOLFSSL_ASN1_INTEGER and free's "in" itself */ +void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER* in) +{ + if (in != NULL) { + if (in->isDynamic) { + XFREE(in->data, NULL, DYNAMIC_TYPE_OPENSSL); + } + XFREE(in, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + + +/* Duplicate all WOLFSSL_ASN1_INTEGER members from src to dup + * src : WOLFSSL_ASN1_INTEGER to duplicate + * Returns pointer to duplicate WOLFSSL_ASN1_INTEGER + */ +WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_dup(const WOLFSSL_ASN1_INTEGER* src) +{ + WOLFSSL_ASN1_INTEGER* dup; + WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_dup"); + if (!src) + return NULL; + + dup = wolfSSL_ASN1_INTEGER_new(); + + if (dup == NULL) + return NULL; + + dup->negative = src->negative; + dup->dataMax = src->dataMax; + dup->isDynamic = src->isDynamic; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + dup->length = src->length; +#endif + XSTRNCPY((char*)dup->intData,(const char*)src->intData,WOLFSSL_ASN1_INTEGER_MAX); + + if (dup->isDynamic && src->data && dup->dataMax) { + dup->data = (unsigned char*) + XMALLOC(src->dataMax,NULL,DYNAMIC_TYPE_OPENSSL); + if (dup->data == NULL) { + wolfSSL_ASN1_INTEGER_free(dup); + return NULL; + } + XMEMCPY(dup->data,src->data,dup->dataMax); + } + return dup; +} + + +/* sets the value of WOLFSSL_ASN1_INTEGER a to the long value v. */ +int wolfSSL_ASN1_INTEGER_set(WOLFSSL_ASN1_INTEGER *a, long v) +{ + int ret = WOLFSSL_SUCCESS; /* return 1 for success and 0 for failure */ + int j; + unsigned int i = 0; + unsigned char tmp[sizeof(long)+1] = {0}; + + if (a != NULL) { + /* dynamically create data buffer, +2 for type and length */ + a->data = (unsigned char*)XMALLOC((sizeof(long)+1) + 2, NULL, + DYNAMIC_TYPE_OPENSSL); + if (a->data == NULL) { + wolfSSL_ASN1_INTEGER_free(a); + ret = WOLFSSL_FAILURE; + } + else { + a->dataMax = (int)(sizeof(long)+1) + 2; + a->isDynamic = 1; + } + } + else { + /* Invalid parameter */ + ret = WOLFSSL_FAILURE; + } + + + if (ret != WOLFSSL_FAILURE) { + /* Set type */ + a->data[i++] = ASN_INTEGER; + + /* Check for negative */ + if (v < 0) { + a->negative = 1; + v *= -1; + } + + /* Create char buffer */ + for (j = 0; j < (int)sizeof(long); j++) { + if (v == 0) { + break; + } + tmp[j] = (unsigned char)(v & 0xff); + v >>= 8; + } + + /* Set length */ + a->data[i++] = (unsigned char)((j == 0) ? ++j : j); + /* +2 for type and length */ + a->length = j + 2; + + /* Copy to data */ + for (; j > 0; j--) { + a->data[i++] = tmp[j-1]; + } + } + + return ret; +} 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_new(); + if (a == NULL) + return NULL; + + /* Make sure there is space for the data, ASN.1 type and length. */ + if (x509->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) { + /* dynamically create data buffer, +2 for type and length */ + a->data = (unsigned char*)XMALLOC(x509->serialSz + 2, NULL, + DYNAMIC_TYPE_OPENSSL); + if (a->data == NULL) { + wolfSSL_ASN1_INTEGER_free(a); + return NULL; + } + a->dataMax = x509->serialSz + 2; + a->isDynamic = 1; + } else { + /* Use array instead of dynamic memory */ + a->data = a->intData; + a->dataMax = WOLFSSL_ASN1_INTEGER_MAX; + } + + #ifdef WOLFSSL_QT + XMEMCPY(&a->data[i], x509->serial, x509->serialSz); + a->length = x509->serialSz; + #else + a->data[i++] = ASN_INTEGER; + i += SetLength(x509->serialSz, a->data + i); + XMEMCPY(&a->data[i], x509->serial, x509->serialSz); + a->length = x509->serialSz + 2; + #endif + + x509->serialNumber = a; + + return a; } +#endif /* OPENSSL_EXTRA */ +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) +#ifndef NO_ASN_TIME 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; } +char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len) +{ + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_string"); + + if (t == NULL || buf == NULL || len < 5) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + + if (t->length > len) { + WOLFSSL_MSG("Length of date is longer then buffer"); + return NULL; + } + + if (!GetTimeString(t->data, t->type, buf, len)) { + return NULL; + } + + return buf; +} +#endif /* !NO_ASN_TIME */ +#endif /* WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY || + OPENSSL_EXTRA*/ +#ifdef OPENSSL_EXTRA + +#ifndef NO_WOLFSSL_STUB int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER* a, const WOLFSSL_ASN1_INTEGER* b) { (void)a; (void)b; + WOLFSSL_STUB("ASN1_INTEGER_cmp"); return 0; } +#endif - +#ifndef NO_WOLFSSL_STUB long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* i) { (void)i; + WOLFSSL_STUB("ASN1_INTEGER_get"); return 0; } +#endif - - +/* get X509_STORE_CTX ex_data, max idx is MAX_EX_DATA */ void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx) { -#ifdef FORTRESS - if (ctx != NULL && idx == 0) - return ctx->ex_data; -#else + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_ex_data"); + #if defined(HAVE_EX_DATA) || defined(FORTRESS) + if (ctx != NULL) { + return wolfSSL_CRYPTO_get_ex_data(&ctx->ex_data, idx); + } + #else (void)ctx; (void)idx; -#endif - return 0; + #endif + return NULL; } +/* set X509_STORE_CTX ex_data, max idx is MAX_EX_DATA. Return WOLFSSL_SUCCESS + * on success, WOLFSSL_FAILURE on error. */ +int wolfSSL_X509_STORE_CTX_set_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx, + void *data) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_ex_data"); + #if defined(HAVE_EX_DATA) || defined(FORTRESS) + if (ctx != NULL) + { + return wolfSSL_CRYPTO_set_ex_data(&ctx->ex_data, idx, data); + } + #else + (void)ctx; + (void)idx; + (void)data; + #endif + return WOLFSSL_FAILURE; +} + +#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) +void wolfSSL_X509_STORE_CTX_set_depth(WOLFSSL_X509_STORE_CTX* ctx, int depth) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_depth"); + if (ctx) + ctx->depth = depth; +} +#endif + + +WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_current_issuer( + WOLFSSL_X509_STORE_CTX* ctx) +{ + int ret; + WOLFSSL_X509* issuer; + + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get0_current_issuer"); + + if (ctx == NULL) { + return NULL; + } + + ret = wolfSSL_X509_STORE_CTX_get1_issuer(&issuer, ctx, ctx->current_cert); + if (ret == WOLFSSL_SUCCESS) { + return issuer; + } + + return NULL; +} + + +/* Gets an index to store SSL structure at. + * + * Returns positive index on success and negative values on failure + */ int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void) { + WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx"); + + /* store SSL at index 0 */ return 0; } -void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) +/* Set an error stat in the X509 STORE CTX + * + */ +void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX* ctx, int er) { -#ifdef FORTRESS - if (ssl != NULL && idx < MAX_EX_DATA) - return ssl->ex_data[idx]; -#else - (void)ssl; - (void)idx; -#endif - return 0; + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_error"); + + if (ctx != NULL) { + ctx->error = er; + } } - -void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx, void (*f)(void)) +/* Set the error depth in the X509 STORE CTX */ +void wolfSSL_X509_STORE_CTX_set_error_depth(WOLFSSL_X509_STORE_CTX* ctx, + int depth) { - (void)ctx; - (void)f; + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_error_depth"); + + if (ctx != NULL) { + ctx->error_depth = depth; + } +} + +/* Sets a function callback that will send information about the state of all + * WOLFSSL objects that have been created by the WOLFSSL_CTX structure passed + * in. + * + * ctx WOLFSSL_CTX structure to set callback function in + * f callback function to use + */ +void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx, + void (*f)(const WOLFSSL* ssl, int type, int val)) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback"); + if (ctx == NULL) { + WOLFSSL_MSG("Bad function argument"); + } + else { + ctx->CBIS = f; + } } unsigned long wolfSSL_ERR_peek_error(void) { - return 0; + WOLFSSL_ENTER("wolfSSL_ERR_peek_error"); + + return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL); } - -int wolfSSL_ERR_GET_REASON(int err) +int wolfSSL_ERR_GET_LIB(unsigned long err) { - (void)err; - return 0; + switch (err) { + case PEM_R_NO_START_LINE: + case PEM_R_PROBLEMS_GETTING_PASSWORD: + case PEM_R_BAD_PASSWORD_READ: + case PEM_R_BAD_DECRYPT: + return ERR_LIB_PEM; + case EVP_R_BAD_DECRYPT: + case EVP_R_BN_DECODE_ERROR: + case EVP_R_DECODE_ERROR: + case EVP_R_PRIVATE_KEY_DECODE_ERROR: + return ERR_LIB_EVP; + default: + return 0; + } } - -char* wolfSSL_alert_type_string_long(int alertID) +/* This function is to find global error values that are the same through out + * all library version. With wolfSSL having only one set of error codes the + * return value is pretty straight forward. The only thing needed is all wolfSSL + * error values are typically negative. + * + * Returns the error reason + */ +int wolfSSL_ERR_GET_REASON(unsigned long err) { - (void)alertID; - return 0; + int ret = (int)err; + + WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON"); + +#if defined(OPENSSL_ALL) || 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 + + /* check if error value is in range of wolfSSL errors */ + ret = 0 - ret; /* setting as negative value */ + /* wolfCrypt range is less than MAX (-100) + wolfSSL range is MIN (-300) and lower */ + if (ret < MAX_CODE_E && ret > MIN_CODE_E) { + return ret; + } + else { + WOLFSSL_MSG("Not in range of typical error values"); + ret = (int)err; + } + + return ret; } -char* wolfSSL_alert_desc_string_long(int alertID) +/* returns a string that describes the alert + * + * alertID the alert value to look up + */ +const char* wolfSSL_alert_type_string_long(int alertID) { - (void)alertID; - return 0; + WOLFSSL_ENTER("wolfSSL_alert_type_string_long"); + + switch (alertID) { + case close_notify: + { + static const char close_notify_str[] = + "close_notify"; + return close_notify_str; + } + + case unexpected_message: + { + static const char unexpected_message_str[] = + "unexpected_message"; + return unexpected_message_str; + } + + case bad_record_mac: + { + static const char bad_record_mac_str[] = + "bad_record_mac"; + return bad_record_mac_str; + } + + case record_overflow: + { + static const char record_overflow_str[] = + "record_overflow"; + return record_overflow_str; + } + + case decompression_failure: + { + static const char decompression_failure_str[] = + "decompression_failure"; + return decompression_failure_str; + } + + case handshake_failure: + { + static const char handshake_failure_str[] = + "handshake_failure"; + return handshake_failure_str; + } + + case no_certificate: + { + static const char no_certificate_str[] = + "no_certificate"; + return no_certificate_str; + } + + case bad_certificate: + { + static const char bad_certificate_str[] = + "bad_certificate"; + return bad_certificate_str; + } + + case unsupported_certificate: + { + static const char unsupported_certificate_str[] = + "unsupported_certificate"; + return unsupported_certificate_str; + } + + case certificate_revoked: + { + static const char certificate_revoked_str[] = + "certificate_revoked"; + return certificate_revoked_str; + } + + case certificate_expired: + { + static const char certificate_expired_str[] = + "certificate_expired"; + return certificate_expired_str; + } + + case certificate_unknown: + { + static const char certificate_unknown_str[] = + "certificate_unknown"; + return certificate_unknown_str; + } + + case illegal_parameter: + { + static const char illegal_parameter_str[] = + "illegal_parameter"; + return illegal_parameter_str; + } + + case unknown_ca: + { + static const char unknown_ca_str[] = + "unknown_ca"; + return unknown_ca_str; + } + + case decode_error: + { + static const char decode_error_str[] = + "decode_error"; + return decode_error_str; + } + + case decrypt_error: + { + static const char decrypt_error_str[] = + "decrypt_error"; + return decrypt_error_str; + } + + #ifdef WOLFSSL_MYSQL_COMPATIBLE + /* catch name conflict for enum protocol with MYSQL build */ + case wc_protocol_version: + { + static const char wc_protocol_version_str[] = + "wc_protocol_version"; + return wc_protocol_version_str; + } + + #else + case protocol_version: + { + static const char protocol_version_str[] = + "protocol_version"; + return protocol_version_str; + } + + #endif + case no_renegotiation: + { + static const char no_renegotiation_str[] = + "no_renegotiation"; + return no_renegotiation_str; + } + + case unrecognized_name: + { + static const char unrecognized_name_str[] = + "unrecognized_name"; + return unrecognized_name_str; + } + + case bad_certificate_status_response: + { + static const char bad_certificate_status_response_str[] = + "bad_certificate_status_response"; + return bad_certificate_status_response_str; + } + + case no_application_protocol: + { + static const char no_application_protocol_str[] = + "no_application_protocol"; + return no_application_protocol_str; + } + + default: + WOLFSSL_MSG("Unknown Alert"); + return NULL; + } } -char* wolfSSL_state_string_long(WOLFSSL* ssl) +const char* wolfSSL_alert_desc_string_long(int alertID) { - (void)ssl; - return 0; + WOLFSSL_ENTER("wolfSSL_alert_desc_string_long"); + return wolfSSL_alert_type_string_long(alertID); } +/* Gets the current state of the WOLFSSL structure + * + * ssl WOLFSSL structure to get state of + * + * Returns a human readable string of the WOLFSSL structure state + */ +const char* wolfSSL_state_string_long(const WOLFSSL* ssl) +{ + + static const char* OUTPUT_STR[14][6][3] = { + { + {"SSLv3 Initialization","SSLv3 Initialization","SSLv3 Initialization"}, + {"TLSv1 Initialization","TLSv2 Initialization","TLSv2 Initialization"}, + {"TLSv1_1 Initialization","TLSv1_1 Initialization","TLSv1_1 Initialization"}, + {"TLSv1_2 Initialization","TLSv1_2 Initialization","TLSv1_2 Initialization"}, + {"DTLSv1 Initialization","DTLSv1 Initialization","DTLSv1 Initialization"}, + {"DTLSv1_2 Initialization","DTLSv1_2 Initialization","DTLSv1_2 Initialization"}, + }, + { + {"SSLv3 read Server Hello Verify Request", + "SSLv3 write Server Hello Verify Request", + "SSLv3 Server Hello Verify Request"}, + {"TLSv1 read Server Hello Verify Request", + "TLSv1 write Server Hello Verify Request", + "TLSv1 Server Hello Verify Request"}, + {"TLSv1_1 read Server Hello Verify Request", + "TLSv1_1 write Server Hello Verify Request", + "TLSv1_1 Server Hello Verify Request"}, + {"TLSv1_2 read Server Hello Verify Request", + "TLSv1_2 write Server Hello Verify Request", + "TLSv1_2 Server Hello Verify Request"}, + {"DTLSv1 read Server Hello Verify Request", + "DTLSv1 write Server Hello Verify Request", + "DTLSv1 Server Hello Verify Request"}, + {"DTLSv1_2 read Server Hello Verify Request", + "DTLSv1_2 write Server Hello Verify Request", + "DTLSv1_2 Server Hello Verify Request"}, + }, + { + {"SSLv3 read Server Hello", + "SSLv3 write Server Hello", + "SSLv3 Server Hello"}, + {"TLSv1 read Server Hello", + "TLSv1 write Server Hello", + "TLSv1 Server Hello"}, + {"TLSv1_1 read Server Hello", + "TLSv1_1 write Server Hello", + "TLSv1_1 Server Hello"}, + {"TLSv1_2 read Server Hello", + "TLSv1_2 write Server Hello", + "TLSv1_2 Server Hello"}, + {"DTLSv1 read Server Hello", + "DTLSv1 write Server Hello", + "DTLSv1 Server Hello"}, + {"DTLSv1_2 read Server Hello" + "DTLSv1_2 write Server Hello", + "DTLSv1_2 Server Hello", + }, + }, + { + {"SSLv3 read Server Session Ticket", + "SSLv3 write Server Session Ticket", + "SSLv3 Server Session Ticket"}, + {"TLSv1 read Server Session Ticket", + "TLSv1 write Server Session Ticket", + "TLSv1 Server Session Ticket"}, + {"TLSv1_1 read Server Session Ticket", + "TLSv1_1 write Server Session Ticket", + "TLSv1_1 Server Session Ticket"}, + {"TLSv1_2 read Server Session Ticket", + "TLSv1_2 write Server Session Ticket", + "TLSv1_2 Server Session Ticket"}, + {"DTLSv1 read Server Session Ticket", + "DTLSv1 write Server Session Ticket", + "DTLSv1 Server Session Ticket"}, + {"DTLSv1_2 read Server Session Ticket", + "DTLSv1_2 write Server Session Ticket", + "DTLSv1_2 Server Session Ticket"}, + }, + { + {"SSLv3 read Server Cert", + "SSLv3 write Server Cert", + "SSLv3 Server Cert"}, + {"TLSv1 read Server Cert", + "TLSv1 write Server Cert", + "TLSv1 Server Cert"}, + {"TLSv1_1 read Server Cert", + "TLSv1_1 write Server Cert", + "TLSv1_1 Server Cert"}, + {"TLSv1_2 read Server Cert", + "TLSv1_2 write Server Cert", + "TLSv1_2 Server Cert"}, + {"DTLSv1 read Server Cert", + "DTLSv1 write Server Cert", + "DTLSv1 Server Cert"}, + {"DTLSv1_2 read Server Cert", + "DTLSv1_2 write Server Cert", + "DTLSv1_2 Server Cert"}, + }, + { + {"SSLv3 read Server Key Exchange", + "SSLv3 write Server Key Exchange", + "SSLv3 Server Key Exchange"}, + {"TLSv1 read Server Key Exchange", + "TLSv1 write Server Key Exchange", + "TLSv1 Server Key Exchange"}, + {"TLSv1_1 read Server Key Exchange", + "TLSv1_1 write Server Key Exchange", + "TLSv1_1 Server Key Exchange"}, + {"TLSv1_2 read Server Key Exchange", + "TLSv1_2 write Server Key Exchange", + "TLSv1_2 Server Key Exchange"}, + {"DTLSv1 read Server Key Exchange", + "DTLSv1 write Server Key Exchange", + "DTLSv1 Server Key Exchange"}, + {"DTLSv1_2 read Server Key Exchange", + "DTLSv1_2 write Server Key Exchange", + "DTLSv1_2 Server Key Exchange"}, + }, + { + {"SSLv3 read Server Hello Done", + "SSLv3 write Server Hello Done", + "SSLv3 Server Hello Done"}, + {"TLSv1 read Server Hello Done", + "TLSv1 write Server Hello Done", + "TLSv1 Server Hello Done"}, + {"TLSv1_1 read Server Hello Done", + "TLSv1_1 write Server Hello Done", + "TLSv1_1 Server Hello Done"}, + {"TLSv1_2 read Server Hello Done", + "TLSv1_2 write Server Hello Done", + "TLSv1_2 Server Hello Done"}, + {"DTLSv1 read Server Hello Done", + "DTLSv1 write Server Hello Done", + "DTLSv1 Server Hello Done"}, + {"DTLSv1_2 read Server Hello Done", + "DTLSv1_2 write Server Hello Done", + "DTLSv1_2 Server Hello Done"}, + }, + { + {"SSLv3 read Server Change CipherSpec", + "SSLv3 write Server Change CipherSpec", + "SSLv3 Server Change CipherSpec"}, + {"TLSv1 read Server Change CipherSpec", + "TLSv1 write Server Change CipherSpec", + "TLSv1 Server Change CipherSpec"}, + {"TLSv1_1 read Server Change CipherSpec", + "TLSv1_1 write Server Change CipherSpec", + "TLSv1_1 Server Change CipherSpec"}, + {"TLSv1_2 read Server Change CipherSpec", + "TLSv1_2 write Server Change CipherSpec", + "TLSv1_2 Server Change CipherSpec"}, + {"DTLSv1 read Server Change CipherSpec", + "DTLSv1 write Server Change CipherSpec", + "DTLSv1 Server Change CipherSpec"}, + {"DTLSv1_2 read Server Change CipherSpec", + "DTLSv1_2 write Server Change CipherSpec", + "DTLSv1_2 Server Change CipherSpec"}, + }, + { + {"SSLv3 read Server Finished", + "SSLv3 write Server Finished", + "SSLv3 Server Finished"}, + {"TLSv1 read Server Finished", + "TLSv1 write Server Finished", + "TLSv1 Server Finished"}, + {"TLSv1_1 read Server Finished", + "TLSv1_1 write Server Finished", + "TLSv1_1 Server Finished"}, + {"TLSv1_2 read Server Finished", + "TLSv1_2 write Server Finished", + "TLSv1_2 Server Finished"}, + {"DTLSv1 read Server Finished", + "DTLSv1 write Server Finished", + "DTLSv1 Server Finished"}, + {"DTLSv1_2 read Server Finished", + "DTLSv1_2 write Server Finished", + "DTLSv1_2 Server Finished"}, + }, + { + {"SSLv3 read Client Hello", + "SSLv3 write Client Hello", + "SSLv3 Client Hello"}, + {"TLSv1 read Client Hello", + "TLSv1 write Client Hello", + "TLSv1 Client Hello"}, + {"TLSv1_1 read Client Hello", + "TLSv1_1 write Client Hello", + "TLSv1_1 Client Hello"}, + {"TLSv1_2 read Client Hello", + "TLSv1_2 write Client Hello", + "TLSv1_2 Client Hello"}, + {"DTLSv1 read Client Hello", + "DTLSv1 write Client Hello", + "DTLSv1 Client Hello"}, + {"DTLSv1_2 read Client Hello", + "DTLSv1_2 write Client Hello", + "DTLSv1_2 Client Hello"}, + }, + { + {"SSLv3 read Client Key Exchange", + "SSLv3 write Client Key Exchange", + "SSLv3 Client Key Exchange"}, + {"TLSv1 read Client Key Exchange", + "TLSv1 write Client Key Exchange", + "TLSv1 Client Key Exchange"}, + {"TLSv1_1 read Client Key Exchange", + "TLSv1_1 write Client Key Exchange", + "TLSv1_1 Client Key Exchange"}, + {"TLSv1_2 read Client Key Exchange", + "TLSv1_2 write Client Key Exchange", + "TLSv1_2 Client Key Exchange"}, + {"DTLSv1 read Client Key Exchange", + "DTLSv1 write Client Key Exchange", + "DTLSv1 Client Key Exchange"}, + {"DTLSv1_2 read Client Key Exchange", + "DTLSv1_2 write Client Key Exchange", + "DTLSv1_2 Client Key Exchange"}, + }, + { + {"SSLv3 read Client Change CipherSpec", + "SSLv3 write Client Change CipherSpec", + "SSLv3 Client Change CipherSpec"}, + {"TLSv1 read Client Change CipherSpec", + "TLSv1 write Client Change CipherSpec", + "TLSv1 Client Change CipherSpec"}, + {"TLSv1_1 read Client Change CipherSpec", + "TLSv1_1 write Client Change CipherSpec", + "TLSv1_1 Client Change CipherSpec"}, + {"TLSv1_2 read Client Change CipherSpec", + "TLSv1_2 write Client Change CipherSpec", + "TLSv1_2 Client Change CipherSpec"}, + {"DTLSv1 read Client Change CipherSpec", + "DTLSv1 write Client Change CipherSpec", + "DTLSv1 Client Change CipherSpec"}, + {"DTLSv1_2 read Client Change CipherSpec", + "DTLSv1_2 write Client Change CipherSpec", + "DTLSv1_2 Client Change CipherSpec"}, + }, + { + {"SSLv3 read Client Finished", + "SSLv3 write Client Finished", + "SSLv3 Client Finished"}, + {"TLSv1 read Client Finished", + "TLSv1 write Client Finished", + "TLSv1 Client Finished"}, + {"TLSv1_1 read Client Finished", + "TLSv1_1 write Client Finished", + "TLSv1_1 Client Finished"}, + {"TLSv1_2 read Client Finished", + "TLSv1_2 write Client Finished", + "TLSv1_2 Client Finished"}, + {"DTLSv1 read Client Finished", + "DTLSv1 write Client Finished", + "DTLSv1 Client Finished"}, + {"DTLSv1_2 read Client Finished", + "DTLSv1_2 write Client Finished", + "DTLSv1_2 Client Finished"}, + }, + { + {"SSLv3 Handshake Done", + "SSLv3 Handshake Done", + "SSLv3 Handshake Done"}, + {"TLSv1 Handshake Done", + "TLSv1 Handshake Done", + "TLSv1 Handshake Done"}, + {"TLSv1_1 Handshake Done", + "TLSv1_1 Handshake Done", + "TLSv1_1 Handshake Done"}, + {"TLSv1_2 Handshake Done", + "TLSv1_2 Handshake Done", + "TLSv1_2 Handshake Done"}, + {"DTLSv1 Handshake Done", + "DTLSv1 Handshake Done", + "DTLSv1 Handshake Done"}, + {"DTLSv1_2 Handshake Done" + "DTLSv1_2 Handshake Done" + "DTLSv1_2 Handshake Done"} + } + }; + enum ProtocolVer { + SSL_V3 = 0, + TLS_V1, + TLS_V1_1, + TLS_V1_2, + DTLS_V1, + DTLS_V1_2, + UNKNOWN = 100 + }; + + enum IOMode { + SS_READ = 0, + SS_WRITE, + SS_NEITHER + }; + + enum SslState { + ss_null_state = 0, + ss_server_helloverify, + ss_server_hello, + ss_sessionticket, + ss_server_cert, + ss_server_keyexchange, + ss_server_hellodone, + ss_server_changecipherspec, + ss_server_finished, + ss_client_hello, + ss_client_keyexchange, + ss_client_changecipherspec, + ss_client_finished, + ss_handshake_done + }; + + int protocol = 0; + int cbmode = 0; + int state = 0; + + WOLFSSL_ENTER("wolfSSL_state_string_long"); + if (ssl == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return NULL; + } + + /* Get state of callback */ + if (ssl->cbmode == SSL_CB_MODE_WRITE){ + cbmode = SS_WRITE; + } else if (ssl->cbmode == SSL_CB_MODE_READ){ + cbmode = SS_READ; + } else { + cbmode = SS_NEITHER; + } + + /* Get protocol version */ + switch (ssl->version.major){ + case SSLv3_MAJOR: + switch (ssl->version.minor){ + case TLSv1_MINOR: + protocol = TLS_V1; + break; + case TLSv1_1_MINOR: + protocol = TLS_V1_1; + break; + case TLSv1_2_MINOR: + protocol = TLS_V1_2; + break; + case SSLv3_MINOR: + protocol = SSL_V3; + break; + default: + protocol = UNKNOWN; + } + break; + case DTLS_MAJOR: + switch (ssl->version.minor){ + case DTLS_MINOR: + protocol = DTLS_V1; + break; + case DTLSv1_2_MINOR: + protocol = DTLS_V1_2; + break; + default: + protocol = UNKNOWN; + } + break; + default: + protocol = UNKNOWN; + } + + /* accept process */ + if (ssl->cbmode == SSL_CB_MODE_READ){ + state = ssl->cbtype; + switch (state) { + case hello_verify_request: + state = ss_server_helloverify; + break; + case session_ticket: + state = ss_sessionticket; + break; + case server_hello: + state = ss_server_hello; + break; + case server_hello_done: + state = ss_server_hellodone; + break; + case certificate: + state = ss_server_cert; + break; + case server_key_exchange: + state = ss_server_keyexchange; + break; + case client_hello: + state = ss_client_hello; + break; + case client_key_exchange: + state = ss_client_keyexchange; + break; + case finished: + if (ssl->options.side == WOLFSSL_SERVER_END) + state = ss_client_finished; + else if (ssl->options.side == WOLFSSL_CLIENT_END) + state = ss_server_finished; + else { + WOLFSSL_MSG("Unknown State"); + state = ss_null_state; + } + break; + default: + WOLFSSL_MSG("Unknown State"); + state = ss_null_state; + } + } else { + /* Send process */ + if (ssl->options.side == WOLFSSL_SERVER_END) + state = ssl->options.serverState; + else + state = ssl->options.clientState; + + switch(state){ + case SERVER_HELLOVERIFYREQUEST_COMPLETE: + state = ss_server_helloverify; + break; + case SERVER_HELLO_COMPLETE: + state = ss_server_hello; + break; + case SERVER_CERT_COMPLETE: + state = ss_server_cert; + break; + case SERVER_KEYEXCHANGE_COMPLETE: + state = ss_server_keyexchange; + break; + case SERVER_HELLODONE_COMPLETE: + state = ss_server_hellodone; + break; + case SERVER_CHANGECIPHERSPEC_COMPLETE: + state = ss_server_changecipherspec; + break; + case SERVER_FINISHED_COMPLETE: + state = ss_server_finished; + break; + case CLIENT_HELLO_COMPLETE: + state = ss_client_hello; + break; + case CLIENT_KEYEXCHANGE_COMPLETE: + state = ss_client_keyexchange; + break; + case CLIENT_CHANGECIPHERSPEC_COMPLETE: + state = ss_client_changecipherspec; + break; + case CLIENT_FINISHED_COMPLETE: + state = ss_client_finished; + break; + case HANDSHAKE_DONE: + state = ss_handshake_done; + break; + default: + WOLFSSL_MSG("Unknown State"); + state = ss_null_state; + } + } + + if (protocol == UNKNOWN) + return NULL; + else + return OUTPUT_STR[state][protocol][cbmode]; +} + +/* + * Sets default PEM callback password if null is passed into + * the callback parameter of a PEM_read_bio_* function. + * + * Returns callback phrase size on success or WOLFSSL_FAILURE otherwise. + */ int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key) { - (void)name; - (void)num; + int sz; (void)w; - (void)key; - return 0; + WOLFSSL_ENTER("wolfSSL_PEM_def_callback"); + + /* We assume that the user passes a default password as userdata */ + if (key) { + sz = (int)XSTRLEN((const char*)key); + sz = (sz > num) ? num : sz; + XMEMCPY(name, key, sz); + return sz; + } else { + WOLFSSL_MSG("Error, default password cannot be created."); + return WOLFSSL_FAILURE; + } +} + +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +static long wolf_set_options(long old_op, long op) +{ + /* if SSL_OP_ALL then turn all bug workarounds on */ + if ((op & SSL_OP_ALL) == SSL_OP_ALL) { + WOLFSSL_MSG("\tSSL_OP_ALL"); + } + + /* by default cookie exchange is on with DTLS */ + if ((op & SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE) { + WOLFSSL_MSG("\tSSL_OP_COOKIE_EXCHANGE : on by default"); + } + + if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) { + WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2"); + } + +#ifdef SSL_OP_NO_TLSv1_3 + if ((op & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_3"); + } +#endif + + if ((op & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2"); + } + + 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) == SSL_OP_NO_TLSv1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1"); + } + + if ((op & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { + WOLFSSL_MSG("\tSSL_OP_NO_SSLv3"); + } + + if ((op & SSL_OP_CIPHER_SERVER_PREFERENCE) == SSL_OP_CIPHER_SERVER_PREFERENCE) { + WOLFSSL_MSG("\tSSL_OP_CIPHER_SERVER_PREFERENCE"); + } + + if ((op & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) { + #ifdef HAVE_LIBZ + WOLFSSL_MSG("SSL_OP_NO_COMPRESSION"); + #else + WOLFSSL_MSG("SSL_OP_NO_COMPRESSION: compression not compiled in"); + #endif + } + + return old_op | op; +} +#endif + +#ifdef OPENSSL_EXTRA +long wolfSSL_set_options(WOLFSSL* ssl, long op) +{ + word16 haveRSA = 1; + word16 havePSK = 0; + int keySz = 0; + + WOLFSSL_ENTER("wolfSSL_set_options"); + + if (ssl == NULL) { + return 0; + } + + ssl->options.mask = wolf_set_options(ssl->options.mask, op); + +#ifdef SSL_OP_NO_TLSv1_3 + if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) { + if (ssl->version.minor == TLSv1_3_MINOR) + ssl->version.minor = TLSv1_2_MINOR; + } +#endif + + if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_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) { + if (ssl->version.minor == TLSv1_1_MINOR) + ssl->version.minor = TLSv1_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { + if (ssl->version.minor == TLSv1_MINOR) + ssl->version.minor = SSLv3_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) { + #ifdef HAVE_LIBZ + ssl->options.usingCompression = 0; + #endif + } + + /* 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; } +long wolfSSL_get_options(const WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_options"); + if(ssl == NULL) + return WOLFSSL_FAILURE; + return ssl->options.mask; +} + +long wolfSSL_clear_options(WOLFSSL* ssl, long opt) +{ + WOLFSSL_ENTER("SSL_clear_options"); + if(ssl == NULL) + return WOLFSSL_FAILURE; + ssl->options.mask &= ~opt; + return ssl->options.mask; +} + + +#if defined(HAVE_SECURE_RENEGOTIATION) \ + || defined(HAVE_SERVER_RENEGOTIATION_INFO) +/* clears the counter for number of renegotiations done + * returns the current count before it is cleared */ +long wolfSSL_clear_num_renegotiations(WOLFSSL *s) +{ + long total; + + WOLFSSL_ENTER("wolfSSL_clear_num_renegotiations"); + if (s == NULL) + return 0; + + total = s->secure_rene_count; + s->secure_rene_count = 0; + return total; +} + + +/* return the number of renegotiations since wolfSSL_new */ +long wolfSSL_total_renegotiations(WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_total_renegotiations"); + return wolfSSL_num_renegotiations(s); +} + + +/* return the number of renegotiations since wolfSSL_new */ +long wolfSSL_num_renegotiations(WOLFSSL* s) +{ + if (s == NULL) { + return 0; + } + + return s->secure_rene_count; +} +#endif /* HAVE_SECURE_RENEGOTIATION || HAVE_SERVER_RENEGOTIATION_INFO */ + +#ifndef NO_DH +long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh) +{ + int pSz, gSz; + byte *p, *g; + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_set_tmp_dh"); + + if (!ssl || !dh) + return BAD_FUNC_ARG; + + /* Get needed size for p and g */ + pSz = wolfSSL_BN_bn2bin(dh->p, NULL); + gSz = wolfSSL_BN_bn2bin(dh->g, NULL); + + if (pSz <= 0 || gSz <= 0) + return WOLFSSL_FATAL_ERROR; + + p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (!p) + return MEMORY_E; + + g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (!g) { + XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return MEMORY_E; + } + + pSz = wolfSSL_BN_bn2bin(dh->p, p); + gSz = wolfSSL_BN_bn2bin(dh->g, g); + + if (pSz >= 0 && gSz >= 0) /* Conversion successful */ + ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz); + + XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + + return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR; +} +#endif /* !NO_DH */ + + +#ifdef HAVE_PK_CALLBACKS +long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) +{ + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + + ssl->loggingCtx = arg; + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_PK_CALLBACKS */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) +const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *sess, unsigned int *sid_ctx_length) +{ + const byte *c = wolfSSL_SESSION_get_id((SSL_SESSION *)sess, sid_ctx_length); + return c; +} +#endif + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +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; +} +#endif + +#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, + 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 */ + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts"); + return WOLFSSL_FAILURE; +} +#endif + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts"); + return WOLFSSL_FAILURE; +} +#endif + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids"); + return WOLFSSL_FAILURE; +} +#endif + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids"); + return WOLFSSL_FAILURE; +} +#endif + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +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; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** 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; +} +#endif + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD) \ + || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS) +WOLFSSL_X509_ALGOR* wolfSSL_X509_ALGOR_new(void) +{ + WOLFSSL_X509_ALGOR* ret; + ret = (WOLFSSL_X509_ALGOR*)XMALLOC(sizeof(WOLFSSL_X509_ALGOR), NULL, + DYNAMIC_TYPE_OPENSSL); + if (ret) { + XMEMSET(ret, 0, sizeof(WOLFSSL_X509_ALGOR)); + } + return ret; +} + +void wolfSSL_X509_ALGOR_free(WOLFSSL_X509_ALGOR *alg) +{ + if (alg) { + wolfSSL_ASN1_OBJECT_free(alg->algorithm); + wolfSSL_ASN1_TYPE_free(alg->parameter); + XFREE(alg, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +/* Returns X509_ALGOR struct with signature algorithm */ +const WOLFSSL_X509_ALGOR* wolfSSL_X509_get0_tbs_sigalg(const WOLFSSL_X509 *x509) +{ + WOLFSSL_ENTER("X509_get0_tbs_sigalg"); + + if (x509 == NULL) { + WOLFSSL_MSG("x509 struct NULL error"); + return NULL; + } + + return &x509->algor; +} + +/* Sets paobj pointer to X509_ALGOR signature algorithm */ +void wolfSSL_X509_ALGOR_get0(const WOLFSSL_ASN1_OBJECT **paobj, int *pptype, + const void **ppval, const WOLFSSL_X509_ALGOR *algor) +{ + WOLFSSL_ENTER("X509_ALGOR_get0"); + + if (!algor) { + WOLFSSL_MSG("algor object is NULL"); + return; + } + + if (paobj) + *paobj = algor->algorithm; + if (ppval) + *ppval = algor->algorithm; + if (pptype) { + if (algor->parameter) { + *pptype = algor->parameter->type; + } + else { + /* Default to V_ASN1_OBJECT */ + *pptype = V_ASN1_OBJECT; + } + } +} + +/** + * Populate algor members. + * + * @param algor The object to be set + * @param aobj The value to be set in algor->algorithm + * @param ptype The type of algor->parameter + * @param pval The value of algor->parameter + * @return WOLFSSL_SUCCESS on success + * WOLFSSL_FAILURE on missing parameters or bad malloc + */ +int wolfSSL_X509_ALGOR_set0(WOLFSSL_X509_ALGOR *algor, WOLFSSL_ASN1_OBJECT *aobj, + int ptype, void *pval) +{ + if (!algor) { + return WOLFSSL_FAILURE; + } + if (aobj) { + algor->algorithm = aobj; + } + if (pval) { + if (!algor->parameter) { + algor->parameter = wolfSSL_ASN1_TYPE_new(); + if (!algor->parameter) { + return WOLFSSL_FAILURE; + } + } + wolfSSL_ASN1_TYPE_set(algor->parameter, ptype, pval); + } + return WOLFSSL_SUCCESS; +} + +/** + * Set `a` in a smart way. + * + * @param a Object to set + * @param type The type of object in value + * @param value Object to set + */ +void wolfSSL_ASN1_TYPE_set(WOLFSSL_ASN1_TYPE *a, int type, void *value) +{ + if (!a || !value) { + return; + } + switch (type) { + case V_ASN1_OBJECT: + a->value.object = value; + break; + case V_ASN1_UTCTIME: + a->value.utctime = value; + break; + case V_ASN1_GENERALIZEDTIME: + a->value.generalizedtime = value; + break; + default: + WOLFSSL_MSG("Unknown or unsupported ASN1_TYPE"); + return; + } + a->type = type; +} + +/** + * Allocate a new WOLFSSL_ASN1_TYPE object. + * + * @return New zero'ed WOLFSSL_ASN1_TYPE object + */ +WOLFSSL_ASN1_TYPE* wolfSSL_ASN1_TYPE_new(void) +{ + WOLFSSL_ASN1_TYPE* ret = (WOLFSSL_ASN1_TYPE*)XMALLOC(sizeof(WOLFSSL_ASN1_TYPE), + NULL, DYNAMIC_TYPE_OPENSSL); + if (!ret) + return NULL; + XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TYPE)); + return ret; +} + +/** + * Free WOLFSSL_ASN1_TYPE and all its members. + * + * @param at Object to free + */ +void wolfSSL_ASN1_TYPE_free(WOLFSSL_ASN1_TYPE* at) +{ + if (at) { + switch (at->type) { + case V_ASN1_OBJECT: + wolfSSL_ASN1_OBJECT_free(at->value.object); + break; + case V_ASN1_UTCTIME: + wolfSSL_ASN1_TIME_free(at->value.utctime); + break; + case V_ASN1_GENERALIZEDTIME: + wolfSSL_ASN1_TIME_free(at->value.generalizedtime); + break; + default: + WOLFSSL_MSG("Unknown or unsupported ASN1_TYPE"); + break; + } + XFREE(at, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +/** + * Allocate a new WOLFSSL_X509_PUBKEY object. + * + * @return New zero'ed WOLFSSL_X509_PUBKEY object + */ +WOLFSSL_X509_PUBKEY *wolfSSL_X509_PUBKEY_new(void) +{ + WOLFSSL_X509_PUBKEY *ret; + ret = (WOLFSSL_X509_PUBKEY*)XMALLOC(sizeof(WOLFSSL_X509_PUBKEY), NULL, + DYNAMIC_TYPE_OPENSSL); + if (!ret) { + return NULL; + } + XMEMSET(ret, 0, sizeof(WOLFSSL_X509_PUBKEY)); + ret->algor = wolfSSL_X509_ALGOR_new(); + if (!ret->algor) { + wolfSSL_X509_PUBKEY_free(ret); + return NULL; + } + return ret; +} + +/** + * Free WOLFSSL_X509_PUBKEY and all its members. + * + * @param at Object to free + */ +void wolfSSL_X509_PUBKEY_free(WOLFSSL_X509_PUBKEY *x) +{ + if (x) { + if (x->algor) { + wolfSSL_X509_ALGOR_free(x->algor); + } + if (x->pkey) { + wolfSSL_EVP_PKEY_free(x->pkey); + } + XFREE(x, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +/* Returns X509_PUBKEY structure containing X509_ALGOR and EVP_PKEY */ +WOLFSSL_X509_PUBKEY* wolfSSL_X509_get_X509_PUBKEY(const WOLFSSL_X509* x509) +{ + WOLFSSL_ENTER("X509_get_X509_PUBKEY"); + + if (x509 == NULL) { + WOLFSSL_MSG("x509 struct NULL error"); + return NULL; + } + + return (WOLFSSL_X509_PUBKEY*)&x509->key; +} + +/* Sets ppkalg pointer to X509_PUBKEY algorithm. Returns WOLFSSL_SUCCESS on + success or WOLFSSL_FAILURE on error. */ +int wolfSSL_X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, WOLFSSL_X509_ALGOR **pa, + WOLFSSL_X509_PUBKEY *pub) +{ + WOLFSSL_ENTER("X509_PUBKEY_get0_param"); + + if (!pub || !pub->pubKeyOID) { + WOLFSSL_MSG("X509_PUBKEY struct not populated"); + return WOLFSSL_FAILURE; + } + + if (!pub->algor) { + if (!(pub->algor = wolfSSL_X509_ALGOR_new())) { + return WOLFSSL_FAILURE; + } + pub->algor->algorithm = wolfSSL_OBJ_nid2obj(pub->pubKeyOID); + if (pub->algor->algorithm == NULL) { + WOLFSSL_MSG("Failed to create object from NID"); + return WOLFSSL_FAILURE; + } + } + + if (pa) + *pa = pub->algor; + if (ppkalg) + *ppkalg = pub->algor->algorithm; + if (pk) + wolfSSL_EVP_PKEY_get_der(pub->pkey, (unsigned char **)pk); + if (ppklen) + *ppklen = wolfSSL_EVP_PKEY_get_der(pub->pkey, NULL); + + return WOLFSSL_SUCCESS; +} + +/* Returns a pointer to the pkey when passed a key */ +WOLFSSL_EVP_PKEY* wolfSSL_X509_PUBKEY_get(WOLFSSL_X509_PUBKEY* key) +{ + WOLFSSL_ENTER("wolfSSL_X509_PUBKEY_get"); + if(key == NULL || key->pkey == NULL){ + WOLFSSL_LEAVE("wolfSSL_X509_PUBKEY_get", BAD_FUNC_ARG); + return NULL; + } + WOLFSSL_LEAVE("wolfSSL_X509_PUBKEY_get", WOLFSSL_SUCCESS); + return key->pkey; +} + +int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key) +{ + WOLFSSL_X509_PUBKEY *pk = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_PUBKEY_set"); + + if (!x || !key) { + return WOLFSSL_FAILURE; + } + + if (!(pk = wolfSSL_X509_PUBKEY_new())) { + return WOLFSSL_FAILURE; + } + + switch (key->type) { +#ifndef NO_RSA + case EVP_PKEY_RSA: + pk->algor->algorithm= wolfSSL_OBJ_nid2obj(RSAk); + break; +#endif +#ifndef NO_DSA + case EVP_PKEY_DSA: + pk->algor->algorithm = wolfSSL_OBJ_nid2obj(DSAk); + break; +#endif +#ifdef HAVE_ECC + case EVP_PKEY_EC: + pk->algor->algorithm = wolfSSL_OBJ_nid2obj(ECDSAk); + break; +#endif + default: + WOLFSSL_MSG("Unknown key type"); + goto error; + } + + if (!pk->algor->algorithm) { + WOLFSSL_MSG("Failed to create algorithm object"); + goto error; + } + + if (!wolfSSL_EVP_PKEY_up_ref(key)) { + WOLFSSL_MSG("Failed to up key reference"); + goto error; + } + pk->pkey = key; + + wolfSSL_X509_PUBKEY_free(*x); + *x = pk; + return WOLFSSL_SUCCESS; +error: + if (pk) { + wolfSSL_X509_PUBKEY_free(pk); + } + return WOLFSSL_FAILURE; +} + +#endif /* OPENSSL_ALL || WOLFSSL_APACHE_HTTPD || WOLFSSL_HAPROXY*/ + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl) +{ + (void)ssl; + WOLFSSL_STUB("SSL_get_privatekey"); + return NULL; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** 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; +} +#endif + +/* Return number of bytes written to BIO on success. 0 on failure. */ +WOLFSSL_API int wolfSSL_i2a_ASN1_OBJECT(WOLFSSL_BIO *bp, + WOLFSSL_ASN1_OBJECT *a) +{ + int length = 0; + word32 idx = 0; + const char null_str[] = "NULL"; + + WOLFSSL_ENTER("wolfSSL_i2a_ASN1_OBJECT"); + + if (bp == NULL) + return WOLFSSL_FAILURE; + + if (a == NULL) { + /* Write "NULL" */ + if (wolfSSL_BIO_write(bp, null_str, (int)XSTRLEN(null_str)) == + (int)XSTRLEN(null_str)) { + return (int)XSTRLEN(null_str); + } + else { + return WOLFSSL_FAILURE; + } + } + + + if ((a->obj == NULL) || (a->obj[idx++] != ASN_OBJECT_ID)) { + WOLFSSL_MSG("Bad ASN1 Object"); + return WOLFSSL_FAILURE; + } + + if (GetLength((const byte*)a->obj, &idx, &length, + a->objSz) < 0 || length < 0) { + return WOLFSSL_FAILURE; + } + + if (wolfSSL_BIO_write(bp, a->obj + idx, length) == (int)length) { + return length; + } + + return WOLFSSL_FAILURE; +} + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) +#ifndef NO_WOLFSSL_STUB +/*** 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; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** 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 +#endif /* WOLFSSL_HAPROXY */ + +#ifndef NO_WOLFSSL_STUB +/*** 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"); +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void) +{ + WOLFSSL_STUB("SSL_COMP_get_compression_methods"); + return NULL; +} +#endif + + +int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* p) +{ + WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_num"); + if (p == NULL) { + return WOLFSSL_FATAL_ERROR; + } + return (int)p->num; +} + +#if !defined(NO_FILESYSTEM) +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(XFILE 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 +#endif + +#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) +/* Loads certificate(s) files in pem format into X509_STORE struct from either + * a file or directory. + * Returns WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE if an error occurs. + */ +WOLFSSL_API int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str, + const char *file, const char *dir) +{ + WOLFSSL_CTX* ctx; + char *name = NULL; + int ret = WOLFSSL_SUCCESS; + int successes = 0; +#ifdef WOLFSSL_SMALL_STACK + ReadDirCtx* readCtx = NULL; +#else + ReadDirCtx readCtx[1]; +#endif + + WOLFSSL_ENTER("X509_STORE_load_locations"); + + if (str == NULL || str->cm == NULL || (file == NULL && dir == NULL)) + return WOLFSSL_FAILURE; + + /* tmp ctx for setting our cert manager */ + ctx = wolfSSL_CTX_new(cm_pick_method()); + if (ctx == NULL) + return WOLFSSL_FAILURE; + + wolfSSL_CertManagerFree(ctx->cm); + ctx->cm = str->cm; + +#ifdef HAVE_CRL + if (str->cm->crl == NULL) { + if (wolfSSL_CertManagerEnableCRL(str->cm, 0) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Enable CRL failed"); + wolfSSL_CTX_free(ctx); + return WOLFSSL_FAILURE; + } + } +#endif + + /* Load individual file */ + if (file) { + /* Try to process file with type DETECT_CERT_TYPE to parse the + correct certificate header and footer type */ + ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, DETECT_CERT_TYPE, + NULL, 0, str->cm->crl, 0); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Failed to load file"); + ret = WOLFSSL_FAILURE; + } + } + + /* Load files in dir */ + if (dir && ret == WOLFSSL_SUCCESS) { + #ifdef WOLFSSL_SMALL_STACK + readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (readCtx == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + #endif + + /* try to load each regular file in dir */ + ret = wc_ReadDirFirst(readCtx, dir, &name); + while (ret == 0 && name) { + WOLFSSL_MSG(name); + /* Try to process file with type DETECT_CERT_TYPE to parse the + correct certificate header and footer type */ + ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, DETECT_CERT_TYPE, + NULL, 0, str->cm->crl, 0); + /* Not failing on load errors */ + if (ret != WOLFSSL_SUCCESS) + WOLFSSL_MSG("Failed to load file in path, continuing"); + else + successes++; + + ret = wc_ReadDirNext(readCtx, dir, &name); + } + wc_ReadDirClose(readCtx); + + /* Success if at least one file in dir was loaded */ + if (successes > 0) + ret = WOLFSSL_SUCCESS; + else { + WOLFSSL_ERROR(ret); + ret = WOLFSSL_FAILURE; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX); + #endif + } + + ctx->cm = NULL; + wolfSSL_CTX_free(ctx); + + return ret; +} +#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ + +#ifndef NO_WOLFSSL_STUB +/*** 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; +} +#endif + +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) +{ + if (s == NULL || resp == NULL) + return 0; + + *resp = s->ocspResp; + return s->ocspRespSz; +} + +WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len) +{ + if (s == NULL) + return WOLFSSL_FAILURE; + + s->ocspResp = resp; + s->ocspRespSz = len; + + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_OCSP */ + +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +long wolfSSL_get_verify_result(const WOLFSSL *ssl) +{ + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + + return ssl->peerVerifyRet; +} +#endif + +#ifdef OPENSSL_EXTRA + +#ifndef NO_WOLFSSL_STUB +/* shows the number of accepts attempted by CTX in it's lifetime */ long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx) { + WOLFSSL_STUB("wolfSSL_CTX_sess_accept"); (void)ctx; return 0; } +#endif - +#ifndef NO_WOLFSSL_STUB +/* shows the number of connects attempted CTX in it's lifetime */ long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx) { + WOLFSSL_STUB("wolfSSL_CTX_sess_connect"); (void)ctx; return 0; } +#endif +#ifndef NO_WOLFSSL_STUB +/* shows the number of accepts completed by CTX in it's lifetime */ long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx) { + WOLFSSL_STUB("wolfSSL_CTX_sess_accept_good"); (void)ctx; return 0; } +#endif +#ifndef NO_WOLFSSL_STUB +/* shows the number of connects completed by CTX in it's lifetime */ long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx) { + WOLFSSL_STUB("wolfSSL_CTX_sess_connect_good"); (void)ctx; return 0; } +#endif +#ifndef NO_WOLFSSL_STUB +/* shows the number of renegotiation accepts attempted by CTX */ long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx) { + WOLFSSL_STUB("wolfSSL_CTX_sess_accept_renegotiate"); (void)ctx; return 0; } +#endif +#ifndef NO_WOLFSSL_STUB +/* shows the number of renegotiation accepts attempted by CTX */ long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx) { + WOLFSSL_STUB("wolfSSL_CTX_sess_connect_renegotiate"); (void)ctx; return 0; } +#endif +#ifndef NO_WOLFSSL_STUB long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx) { + WOLFSSL_STUB("wolfSSL_CTX_sess_hits"); (void)ctx; return 0; } +#endif +#ifndef NO_WOLFSSL_STUB long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx) { + WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits"); (void)ctx; return 0; } +#endif +#ifndef NO_WOLFSSL_STUB long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx) { + WOLFSSL_STUB("wolfSSL_CTX_sess_cache_full"); (void)ctx; return 0; } +#endif +#ifndef NO_WOLFSSL_STUB long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx) { + WOLFSSL_STUB("wolfSSL_CTX_sess_misses"); (void)ctx; return 0; } +#endif +#ifndef NO_WOLFSSL_STUB long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx) { + WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts"); (void)ctx; return 0; } +#endif +/* Return the total number of sessions */ long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx) { + word32 total = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_sess_number"); (void)ctx; + +#ifdef WOLFSSL_SESSION_STATS + if (wolfSSL_get_session_stats(NULL, &total, NULL, NULL) != SSL_SUCCESS) { + WOLFSSL_MSG("Error getting session stats"); + } +#else + WOLFSSL_MSG("Please use macro WOLFSSL_SESSION_STATS for session stats"); +#endif + + return (long)total; +} + + +#ifndef NO_CERTS +long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) +{ + byte* chain = NULL; + long chainSz = 0; + int derSz; + const byte* der; + 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 WOLFSSL_FAILURE; + } + + der = wolfSSL_X509_get_der(x509, &derSz); + if (der == NULL || derSz <= 0) { + WOLFSSL_MSG("Error getting X509 DER"); + return WOLFSSL_FAILURE; + } + + if (ctx->certificate == NULL) { + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format"); + + /* Process buffer makes first certificate the leaf. */ + ret = ProcessBuffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, + NULL, NULL, 1, GET_VERIFY_SETTING_CTX(ctx)); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + return WOLFSSL_FAILURE; + } + } + else { + /* 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, + GET_VERIFY_SETTING_CTX(ctx)); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + return WOLFSSL_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); + if (chain != NULL) + XFREE(chain, ctx->heap, DYNAMIC_TYPE_DER); + + return WOLFSSL_SUCCESS; +} + + +long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg) +{ + if (ctx == NULL || ctx->cm == NULL) { + return WOLFSSL_FAILURE; + } + + ctx->cm->ocspIOCtx = arg; + return WOLFSSL_SUCCESS; +} + +#endif /* NO_CERTS */ + + +/* Get the session cache mode for CTX + * + * ctx WOLFSSL_CTX struct to get cache mode from + * + * Returns a bit mask that has the session cache mode */ +WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx) +{ + long m = 0; + + WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode"); + + if (ctx == NULL) { + return m; + } + + if (ctx->sessionCacheOff != 1) { + m |= SSL_SESS_CACHE_SERVER; + } + + if (ctx->sessionCacheFlushOff == 1) { + m |= SSL_SESS_CACHE_NO_AUTO_CLEAR; + } + +#ifdef HAVE_EXT_CACHE + if (ctx->internalCacheOff == 1) { + m |= SSL_SESS_CACHE_NO_INTERNAL_STORE; + } +#endif + + return m; +} + + +int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) { + return WOLFSSL_FAILURE; + } + + return ctx->readAhead; +} + + +int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v) +{ + if (ctx == NULL) { + return WOLFSSL_FAILURE; + } + + ctx->readAhead = (byte)v; + + return WOLFSSL_SUCCESS; +} + + +long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx, + void* arg) +{ + if (ctx == NULL) { + return WOLFSSL_FAILURE; + } + + ctx->userPRFArg = arg; + return WOLFSSL_SUCCESS; +} + + +#ifndef NO_DES3 +/* 0 on success */ +int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes, + WOLFSSL_DES_key_schedule* key) +{ +#ifdef WOLFSSL_CHECK_DESKEY + return wolfSSL_DES_set_key_checked(myDes, key); +#else + wolfSSL_DES_set_key_unchecked(myDes, key); + return 0; +#endif +} + + + +/* return true in fail case (1) */ +static int DES_check(word32 mask, word32 mask2, unsigned char* key) +{ + word32 value[2]; + + /* sanity check on length made in wolfSSL_DES_set_key_checked */ + value[0] = mask; + value[1] = mask2; + return (XMEMCMP(value, key, sizeof(value)) == 0)? 1: 0; +} + + +/* check that the key is odd parity and is not a weak key + * returns -1 if parity is wrong, -2 if weak/null key and 0 on success */ +int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, + WOLFSSL_DES_key_schedule* key) +{ + if (myDes == NULL || key == NULL) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_set_key_checked"); + return -2; + } + else { + word32 sz = sizeof(WOLFSSL_DES_key_schedule); + + /* sanity check before call to DES_check */ + if (sz != (sizeof(word32) * 2)) { + WOLFSSL_MSG("Unexpected WOLFSSL_DES_key_schedule size"); + return -2; + } + + /* check odd parity */ + if (wolfSSL_DES_check_key_parity(myDes) != 1) { + WOLFSSL_MSG("Odd parity test fail"); + return -1; + } + + if (wolfSSL_DES_is_weak_key(myDes) == 1) { + WOLFSSL_MSG("Weak key found"); + return -2; + } + + /* passed tests, now copy over key */ + XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock)); + + return 0; + } +} + + +/* check is not weak. Weak key list from Nist "Recommendation for the Triple + * Data Encryption Algorithm (TDEA) Block Cipher" + * + * returns 1 if is weak 0 if not + */ +int wolfSSL_DES_is_weak_key(WOLFSSL_const_DES_cblock* key) +{ + word32 mask, mask2; + + WOLFSSL_ENTER("wolfSSL_DES_is_weak_key"); + + if (key == NULL) { + WOLFSSL_MSG("NULL key passed in"); + return 1; + } + + mask = 0x01010101; mask2 = 0x01010101; + if (DES_check(mask, mask2, *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0xFEFEFEFE; mask2 = 0xFEFEFEFE; + if (DES_check(mask, mask2, *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0xE0E0E0E0; mask2 = 0xF1F1F1F1; + if (DES_check(mask, mask2, *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0x1F1F1F1F; mask2 = 0x0E0E0E0E; + if (DES_check(mask, mask2, *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + /* semi-weak *key check (list from same Nist paper) */ + mask = 0x011F011F; mask2 = 0x010E010E; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0x01E001E0; mask2 = 0x01F101F1; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0x01FE01FE; mask2 = 0x01FE01FE; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0x1FE01FE0; mask2 = 0x0EF10EF1; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0x1FFE1FFE; mask2 = 0x0EFE0EFE; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + return 0; } -#ifndef NO_DES3 void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock* myDes, WOLFSSL_DES_key_schedule* key) { - (void)myDes; - (void)key; + if (myDes != NULL && key != NULL) { + XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock)); + } } +/* Sets the parity of the DES key for use */ void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes) { - (void)myDes; + word32 i; + word32 sz = sizeof(WOLFSSL_DES_cblock); + + WOLFSSL_ENTER("wolfSSL_DES_set_odd_parity"); + + for (i = 0; i < sz; i++) { + unsigned char c = (*myDes)[i]; + if (( + ((c >> 1) & 0x01) ^ + ((c >> 2) & 0x01) ^ + ((c >> 3) & 0x01) ^ + ((c >> 4) & 0x01) ^ + ((c >> 5) & 0x01) ^ + ((c >> 6) & 0x01) ^ + ((c >> 7) & 0x01)) == (c & 0x01)) { + WOLFSSL_MSG("Flipping parity bit"); + (*myDes)[i] = c ^ 0x01; + } + } } - -void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa, - WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int len) +int wolfSSL_DES_check_key_parity(WOLFSSL_DES_cblock *myDes) { - (void)desa; - (void)desb; - (void)key; - (void)len; + word32 i; + word32 sz = sizeof(WOLFSSL_DES_cblock); + + WOLFSSL_ENTER("wolfSSL_DES_check_key_parity"); + + for (i = 0; i < sz; i++) { + unsigned char c = (*myDes)[i]; + if (( + ((c >> 1) & 0x01) ^ + ((c >> 2) & 0x01) ^ + ((c >> 3) & 0x01) ^ + ((c >> 4) & 0x01) ^ + ((c >> 5) & 0x01) ^ + ((c >> 6) & 0x01) ^ + ((c >> 7) & 0x01)) == (c & 0x01)) { + return 0; + } + } + return 1; } +#ifdef WOLFSSL_DES_ECB +/* Encrypt 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 enc) +{ + 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 (enc){ + if (wc_Des_EcbEncrypt(&myDes, (byte*) desb, (const byte*) desa, + sizeof(WOLFSSL_DES_cblock)) != 0){ + WOLFSSL_MSG("wc_Des_EcbEncrypt return error."); + } + } else { + if (wc_Des_EcbDecrypt(&myDes, (byte*) desb, (const byte*) desa, + sizeof(WOLFSSL_DES_cblock)) != 0){ + WOLFSSL_MSG("wc_Des_EcbDecrpyt return error."); + } + } + } +} +#endif #endif /* NO_DES3 */ +#ifndef NO_RC4 +/* Set the key state for Arc4 structure. + * + * key Arc4 structure to use + * len length of data buffer + * data initial state to set Arc4 structure + */ +void wolfSSL_RC4_set_key(WOLFSSL_RC4_KEY* key, int len, + const unsigned char* data) +{ + typedef char rc4_test[sizeof(WOLFSSL_RC4_KEY) >= sizeof(Arc4) ? 1 : -1]; + (void)sizeof(rc4_test); + + WOLFSSL_ENTER("wolfSSL_RC4_set_key"); + + if (key == NULL || len < 0) { + WOLFSSL_MSG("bad argument passed in"); + return; + } + + XMEMSET(key, 0, sizeof(WOLFSSL_RC4_KEY)); + wc_Arc4SetKey((Arc4*)key, data, (word32)len); +} + + +/* Encrypt/decrypt with Arc4 structure. + * + * len length of buffer to encrypt/decrypt (in/out) + * in buffer to encrypt/decrypt + * out results of encryption/decryption + */ +void wolfSSL_RC4(WOLFSSL_RC4_KEY* key, size_t len, + const unsigned char* in, unsigned char* out) +{ + WOLFSSL_ENTER("wolfSSL_RC4"); + + if (key == NULL || in == NULL || out == NULL) { + WOLFSSL_MSG("Bad argument passed in"); + return; + } + + wc_Arc4Process((Arc4*)key, out, in, (word32)len); +} +#endif /* NO_RC4 */ + +#ifndef NO_AES + +#ifdef WOLFSSL_AES_DIRECT +/* AES encrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input. + * + * input Data to encrypt + * output Encrypted data after done + * key AES key to use for encryption + */ +void wolfSSL_AES_encrypt(const unsigned char* input, unsigned char* output, + AES_KEY *key) +{ + WOLFSSL_ENTER("wolfSSL_AES_encrypt"); + + if (input == NULL || output == NULL || key == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return; + } + + wc_AesEncryptDirect((Aes*)key, output, input); +} + + +/* AES decrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input. + * + * input Data to decrypt + * output Decrypted data after done + * key AES key to use for encryption + */ +void wolfSSL_AES_decrypt(const unsigned char* input, unsigned char* output, + AES_KEY *key) +{ + WOLFSSL_ENTER("wolfSSL_AES_decrypt"); + + if (input == NULL || output == NULL || key == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return; + } + + wc_AesDecryptDirect((Aes*)key, output, input); +} +#endif /* WOLFSSL_AES_DIRECT */ + +/* Setup of an AES key to use for encryption. + * + * key key in bytes to use for encryption + * bits size of key in bits + * aes AES structure to initialize + */ +int wolfSSL_AES_set_encrypt_key(const unsigned char *key, const int bits, + AES_KEY *aes) +{ + typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1]; + (void)sizeof(aes_test); + + WOLFSSL_ENTER("wolfSSL_AES_set_encrypt_key"); + + if (key == NULL || aes == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return -1; + } + + XMEMSET(aes, 0, sizeof(AES_KEY)); + if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_ENCRYPTION) != 0) { + WOLFSSL_MSG("Error in setting AES key"); + return -1; + } + return 0; +} + + +/* Setup of an AES key to use for decryption. + * + * key key in bytes to use for decryption + * bits size of key in bits + * aes AES structure to initialize + */ +int wolfSSL_AES_set_decrypt_key(const unsigned char *key, const int bits, + AES_KEY *aes) +{ + typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1]; + (void)sizeof(aes_test); + + WOLFSSL_ENTER("wolfSSL_AES_set_decrypt_key"); + + if (key == NULL || aes == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return -1; + } + + XMEMSET(aes, 0, sizeof(AES_KEY)); + if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_DECRYPTION) != 0) { + WOLFSSL_MSG("Error in setting AES key"); + return -1; + } + return 0; +} + + +#ifdef HAVE_AES_ECB +/* Encrypt/decrypt a 16 byte block of data using the key passed in. + * + * in buffer to encrypt/decrypt + * out buffer to hold result of encryption/decryption + * key AES structure to use with encryption/decryption + * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption + */ +void wolfSSL_AES_ecb_encrypt(const unsigned char *in, unsigned char* out, + AES_KEY *key, const int enc) +{ + Aes* aes; + + WOLFSSL_ENTER("wolfSSL_AES_ecb_encrypt"); + + if (key == NULL || in == NULL || out == NULL) { + WOLFSSL_MSG("Error, Null argument passed in"); + return; + } + + aes = (Aes*)key; + if (enc == AES_ENCRYPT) { + if (wc_AesEcbEncrypt(aes, out, in, AES_BLOCK_SIZE) != 0) { + WOLFSSL_MSG("Error with AES CBC encrypt"); + } + } + else { + #ifdef HAVE_AES_DECRYPT + if (wc_AesEcbDecrypt(aes, out, in, AES_BLOCK_SIZE) != 0) { + WOLFSSL_MSG("Error with AES CBC decrypt"); + } + #else + WOLFSSL_MSG("AES decryption not compiled in"); + #endif + } +} +#endif /* HAVE_AES_ECB */ + +#ifdef HAVE_AES_CBC +/* Encrypt data using key and iv passed in. iv gets updated to most recent iv + * state after encryption/decryption. + * + * in buffer to encrypt/decrypt + * out buffer to hold result of encryption/decryption + * len length of input buffer + * key AES structure to use with encryption/decryption + * iv iv to use with operation + * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption + */ +void wolfSSL_AES_cbc_encrypt(const unsigned char *in, unsigned char* out, + size_t len, AES_KEY *key, unsigned char* iv, const int enc) +{ + Aes* aes; + + WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt"); + + if (key == NULL || in == NULL || out == NULL || iv == NULL || len == 0) { + WOLFSSL_MSG("Error, Null argument passed in"); + return; + } + + aes = (Aes*)key; + if (wc_AesSetIV(aes, (const byte*)iv) != 0) { + WOLFSSL_MSG("Error with setting iv"); + return; + } + + if (enc == AES_ENCRYPT) { + if (wc_AesCbcEncrypt(aes, out, in, (word32)len) != 0) { + WOLFSSL_MSG("Error with AES CBC encrypt"); + } + } + else { + if (wc_AesCbcDecrypt(aes, out, in, (word32)len) != 0) { + WOLFSSL_MSG("Error with AES CBC decrypt"); + } + } + + /* to be compatible copy iv to iv buffer after completing operation */ + XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE); +} +#endif /* HAVE_AES_CBC */ + + +/* Encrypt data using CFB mode with key and iv passed in. iv gets updated to + * most recent iv state after encryption/decryption. + * + * in buffer to encrypt/decrypt + * out buffer to hold result of encryption/decryption + * len length of input buffer + * key AES structure to use with encryption/decryption + * iv iv to use with operation + * num contains the amount of block used + * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption + */ +void wolfSSL_AES_cfb128_encrypt(const unsigned char *in, unsigned char* out, + size_t len, AES_KEY *key, unsigned char* iv, int* num, + const int enc) +{ +#ifndef WOLFSSL_AES_CFB + WOLFSSL_MSG("CFB mode not enabled please use macro WOLFSSL_AES_CFB"); + (void)in; + (void)out; + (void)len; + (void)key; + (void)iv; + (void)num; + (void)enc; + + return; +#else + Aes* aes; + + WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt"); + if (key == NULL || in == NULL || out == NULL || iv == NULL) { + WOLFSSL_MSG("Error, Null argument passed in"); + return; + } + + aes = (Aes*)key; + if (wc_AesSetIV(aes, (const byte*)iv) != 0) { + WOLFSSL_MSG("Error with setting iv"); + return; + } + + if (enc == AES_ENCRYPT) { + if (wc_AesCfbEncrypt(aes, out, in, (word32)len) != 0) { + WOLFSSL_MSG("Error with AES CBC encrypt"); + } + } + else { + if (wc_AesCfbDecrypt(aes, out, in, (word32)len) != 0) { + WOLFSSL_MSG("Error with AES CBC decrypt"); + } + } + + /* to be compatible copy iv to iv buffer after completing operation */ + XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE); + + /* store number of left over bytes to num */ + *num = (aes->left)? AES_BLOCK_SIZE - aes->left : 0; +#endif /* WOLFSSL_AES_CFB */ +} +#endif /* NO_AES */ + +#ifndef NO_FILESYSTEM + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wformat-nonliteral" + #endif +#endif + +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_EXTRA) +/* returns amount printed on success, negative in fail case */ +int wolfSSL_BIO_vprintf(WOLFSSL_BIO* bio, const char* format, va_list args) +{ + int ret = -1; + + if (bio == NULL) + return WOLFSSL_FATAL_ERROR; + + switch (bio->type) { + case WOLFSSL_BIO_FILE: + if (bio->ptr == NULL) { + va_end(args); + return -1; + } + ret = vfprintf((XFILE)bio->ptr, format, args); + break; + + case WOLFSSL_BIO_MEMORY: + #if defined(OPENSSL_EXTRA) && !defined(_WIN32) + case WOLFSSL_BIO_SSL: + { + int count; + char* pt = NULL; + va_list copy; + + va_copy(copy, args); + count = vsnprintf(NULL, 0, format, args); + if (count >= 0) + { + pt = (char*)XMALLOC(count + 1, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (pt != NULL) + { + count = vsnprintf(pt, count + 1, format, copy); + if (count >= 0) + { + ret = wolfSSL_BIO_write(bio, pt, count); + } + XFREE(pt, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + } + va_end(copy); + } + break; + #endif + + default: + WOLFSSL_MSG("Unsupported WOLFSSL_BIO type for wolfSSL_BIO_printf"); + break; + } + + return ret; +} + +/* returns amount printed on success, negative in fail case */ int wolfSSL_BIO_printf(WOLFSSL_BIO* bio, const char* format, ...) { - (void)bio; - (void)format; - return 0; + int ret; + va_list args; + va_start(args, format); + + ret = wolfSSL_BIO_vprintf(bio, format, args); + + va_end(args); + + return ret; } +#endif /* !defined(NO_FILESYSTEM) && defined (OPENSSL_EXTRA) */ +#if !defined(NO_FILESYSTEM) && defined(__clang__) +#pragma clang diagnostic pop +#endif + +#undef LINE_LEN +#define LINE_LEN 16 +int wolfSSL_BIO_dump(WOLFSSL_BIO *bio, const char *buf, int length) +{ + int ret = 0; + + if (bio == NULL) + return 0; + +#ifndef NO_FILESYSTEM + if (bio->type == WOLFSSL_BIO_FILE) { + int i; + char line[80]; + + if (!buf) { + return fputs("\tNULL", (XFILE)bio->ptr); + } + + sprintf(line, "\t"); + for (i = 0; i < LINE_LEN; i++) { + if (i < length) + sprintf(line + 1 + i * 3,"%02x ", buf[i]); + else + sprintf(line + 1 + i * 3, " "); + } + sprintf(line + 1 + LINE_LEN * 3, "| "); + for (i = 0; i < LINE_LEN; i++) { + if (i < length) { + sprintf(line + 3 + LINE_LEN * 3 + i, + "%c", 31 < buf[i] && buf[i] < 127 ? buf[i] : '.'); + } + } + ret += fputs(line, (XFILE)bio->ptr); + + if (length > LINE_LEN) + ret += wolfSSL_BIO_dump(bio, buf + LINE_LEN, length - LINE_LEN); + } +#else + (void)buf; + (void)length; +#endif + + return ret; +} + +#ifndef NO_ASN_TIME int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a) { - (void)bio; - (void)a; + WOLFSSL_ENTER("ASN1_UTCTIME_print"); + if (bio == NULL || a == NULL) { + return WOLFSSL_FAILURE; + } + if (a->type != ASN_UTC_TIME) { + WOLFSSL_MSG("Error, not UTC_TIME"); + return WOLFSSL_FAILURE; + } + + return wolfSSL_ASN1_TIME_print(bio, a); +} + +/* Checks the ASN1 syntax of "a" + * returns WOLFSSL_SUCCESS (1) if correct otherwise WOLFSSL_FAILURE (0) */ +int wolfSSL_ASN1_TIME_check(const WOLFSSL_ASN1_TIME* a) +{ + char buf[MAX_TIME_STRING_SZ]; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_check"); + + /* if can parse the WOLFSSL_ASN1_TIME passed in then consider syntax good */ + if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)a, buf, + MAX_TIME_STRING_SZ) == NULL) { + return WOLFSSL_FAILURE; + } + return WOLFSSL_SUCCESS; +} +#endif /* !NO_ASN_TIME */ + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_ASN1_TIME_diff(int *pday, int *psec, + const WOLFSSL_ASN1_TIME *from, const WOLFSSL_ASN1_TIME *to) +{ + WOLFSSL_STUB("wolfSSL_ASN1_TIME_diff"); + (void)pday; + (void)psec; + (void)from; + (void)to; return 0; } - -int wolfSSL_sk_num(WOLFSSL_X509_REVOKED* rev) +WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_set(WOLFSSL_ASN1_TIME *s, time_t t) { - (void)rev; + WOLFSSL_STUB("wolfSSL_ASN1_TIME_set"); + (void)s; + (void)t; + return s; +} +#endif /* !NO_WOLFSSL_STUB */ + +/* 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 WC_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; + WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print"); + + if (bio == NULL || asnTime == NULL) + return BAD_FUNC_ARG; + + if (asnTime->type != ASN_GENERALIZED_TIME) { + WOLFSSL_MSG("Error, not GENERALIZED_TIME"); + return WOLFSSL_FAILURE; + } + p = (const char *)(asnTime->data); + /* 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; } - -void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED* rev, int i) +void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_TIME* asn1Time) { - (void)rev; - (void)i; - return 0; + WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_free"); + if (asn1Time == NULL) + return; + XMEMSET(asn1Time->data, 0, sizeof(asn1Time->data)); +} + +int wolfSSL_sk_num(WOLFSSL_STACK* sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_num"); + if (sk == NULL) + return 0; + return (int)sk->num; +} + +void* wolfSSL_sk_value(WOLFSSL_STACK* sk, int i) +{ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + int offset = i; +#endif + WOLFSSL_ENTER("wolfSSL_sk_value"); + + for (; sk != NULL && i > 0; i--) + sk = sk->next; + if (sk == NULL) + return NULL; + + switch (sk->type) { + case STACK_TYPE_X509: + return (void*)sk->data.x509; + case STACK_TYPE_CIPHER: + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + sk->data.cipher.offset = offset; + #endif + return (void*)&sk->data.cipher; + case STACK_TYPE_GEN_NAME: + return (void*)sk->data.gn; + case STACK_TYPE_ACCESS_DESCRIPTION: + return (void*)sk->data.access; + case STACK_TYPE_OBJ: + return (void*)sk->data.obj; + case STACK_TYPE_X509_EXT: + return (void*)sk->data.ext; + case STACK_TYPE_CONF_VALUE: + return (void*)sk->data.conf->value; + case STACK_TYPE_NULL: + default: + return (void*)sk->data.generic; + } +} + +/* Free the structure for ASN1_OBJECT stack */ +void wolfSSL_sk_free(WOLFSSL_STACK* sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_free"); + + if (sk == NULL) { + WOLFSSL_MSG("Error, BAD_FUNC_ARG"); + return; + } + + switch (sk->type) { + case STACK_TYPE_X509: + wolfSSL_sk_X509_free(sk); + break; + #if defined(OPENSSL_ALL) + case STACK_TYPE_CIPHER: + wolfSSL_sk_CIPHER_free(sk); + break; + #endif + case STACK_TYPE_GEN_NAME: + wolfSSL_sk_GENERAL_NAME_free(sk); + break; + #if defined(OPENSSL_ALL) || defined (WOLFSSL_QT) + case STACK_TYPE_ACCESS_DESCRIPTION: + wolfSSL_sk_ACCESS_DESCRIPTION_free(sk); + break; + #endif + case STACK_TYPE_OBJ: + wolfSSL_sk_ASN1_OBJECT_free(sk); + break; + #ifdef OPENSSL_ALL + case STACK_TYPE_X509_INFO: + wolfSSL_sk_X509_INFO_free(sk); + break; + case STACK_TYPE_X509_NAME: + wolfSSL_sk_X509_NAME_free(sk); + break; + case STACK_TYPE_CONF_VALUE: + wolfSSL_sk_CONF_VALUE_free(sk); + break; + #endif + case STACK_TYPE_NULL: + default: + wolfSSL_sk_GENERIC_free(sk); + } +} +/* Frees each node in the stack and frees the stack. + * Does not free any internal members of the stack nodes. + */ +void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk, + void (*f) (void*)) +{ + WOLFSSL_STACK* node; + WOLFSSL_STACK* tmp; + WOLFSSL_ENTER("wolfSSL_sk_GENERIC_pop_free"); + + if (sk == NULL) + return; + + /* parse through stack freeing each node */ + node = sk->next; + while (node) { + tmp = node; + node = node->next; + if (f) + f(tmp->data.generic); + tmp->data.generic = NULL; + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + } + + /* free head of stack */ + XFREE(sk, NULL, DYNAMIC_TYPE_ASN1); +} + +/* return 1 on success 0 on fail */ +int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK* sk, void* generic) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_GENERIC_push"); + + if (sk == NULL || generic == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.generic == NULL) { + sk->data.generic = generic; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK),NULL,DYNAMIC_TYPE_SSL); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new node onto head of stack */ + node->type = sk->type; + node->data.generic = sk->data.generic; + node->next = sk->next; + sk->next = node; + sk->data.generic = generic; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} +void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk) +{ + wolfSSL_sk_GENERIC_pop_free(sk, NULL); } -/* stunnel 4.28 needs */ -void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int d) +/* Free all nodes in a stack */ +void wolfSSL_sk_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, + wolfSSL_sk_freefunc func) { - (void)ctx; - (void)d; - return 0; + WOLFSSL_ENTER("wolfSSL_sk_pop_free"); + + if (sk == NULL) { + WOLFSSL_MSG("Error, BAD_FUNC_ARG"); + return; + } + + switch(sk->type) { + #if defined(OPENSSL_ALL) || defined (WOLFSSL_QT) + case STACK_TYPE_ACCESS_DESCRIPTION: + wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(sk, + wolfSSL_ACCESS_DESCRIPTION_free); + break; + #endif + case STACK_TYPE_X509: + wolfSSL_sk_X509_pop_free(sk,(void (*)(WOLFSSL_X509*))func); + break; + case STACK_TYPE_OBJ: + wolfSSL_sk_ASN1_OBJECT_pop_free(sk, + (void (*)(WOLFSSL_ASN1_OBJECT*))func); + break; + case STACK_TYPE_GEN_NAME: + wolfSSL_sk_GENERAL_NAME_pop_free(sk, + (void (*)(WOLFSSL_GENERAL_NAME*))func); + break; + #ifdef OPENSSL_ALL + case STACK_TYPE_X509_NAME: + wolfSSL_sk_X509_NAME_pop_free(sk, + (void (*)(WOLFSSL_X509_NAME*))func); + break; + case STACK_TYPE_X509_EXT: + wolfSSL_sk_X509_EXTENSION_pop_free(sk, + (void (*)(WOLFSSL_X509_EXTENSION*))func); + break; + #endif + #if defined(OPENSSL_ALL) + case STACK_TYPE_X509_INFO: + wolfSSL_sk_X509_INFO_pop_free(sk, + (void (*)(WOLFSSL_X509_INFO*))func); + break; + #endif + default: + wolfSSL_sk_GENERIC_pop_free(sk, + (void (*)(void*))func); + break; + } } - -int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int d, void* p) +#if defined(OPENSSL_ALL) +/* Free the structure for WOLFSSL_CONF_VALUE stack + * + * sk stack to free nodes in + */ +void wolfSSL_sk_CONF_VALUE_free(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk) { - (void)ctx; - (void)d; - (void)p; - return SSL_SUCCESS; + WOLFSSL_STACK* node; + WOLFSSL_STACK* tmp; + WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_free"); + + if (sk == NULL) + return; + + /* parse through stack freeing each node */ + node = sk->next; + while (node) { + tmp = node; + node = node->next; + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + } + + /* free head of stack */ + XFREE(sk, NULL, DYNAMIC_TYPE_ASN1); +} +#endif + +/* Creates and returns a new null stack. */ +WOLFSSL_STACK* wolfSSL_sk_new_null(void) +{ + WOLFSSL_STACK* sk; + WOLFSSL_ENTER("wolfSSL_sk_new_null"); + + sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (sk == NULL) { + WOLFSSL_MSG("WOLFSSL_STACK memory error"); + return NULL; + } + + XMEMSET(sk, 0, sizeof(WOLFSSL_STACK)); + sk->type = STACK_TYPE_NULL; + + return sk; } +/* frees the wolfSSL_BASIC_CONSTRAINTS object */ +void wolfSSL_BASIC_CONSTRAINTS_free(WOLFSSL_BASIC_CONSTRAINTS *bc) +{ + WOLFSSL_ENTER("wolfSSL_BASIC_CONSTRAINTS_free"); + if (bc == NULL) { + WOLFSSL_MSG("Argument is NULL"); + return; + } + if (bc->pathlen) { + wolfSSL_ASN1_INTEGER_free(bc->pathlen); + } + XFREE(bc, NULL, DYNAMIC_TYPE_OPENSSL); +} +/* frees the wolfSSL_AUTHORITY_KEYID object */ +void wolfSSL_AUTHORITY_KEYID_free(WOLFSSL_AUTHORITY_KEYID *id) +{ + WOLFSSL_ENTER("wolfSSL_AUTHORITY_KEYID_free"); + if(id == NULL) { + WOLFSSL_MSG("Argument is NULL"); + return; + } + if (id->keyid) { + wolfSSL_ASN1_STRING_free(id->keyid); + } + if (id->issuer) { + wolfSSL_ASN1_OBJECT_free(id->issuer); + } + if (id->serial) { + wolfSSL_ASN1_INTEGER_free(id->serial); + } + XFREE(id, NULL, DYNAMIC_TYPE_OPENSSL); +} + +int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk) +{ + if (sk == NULL) + return 0; + return (int)sk->num; +} + +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) +/* stunnel 4.28 needs + * + * Callback that is called if a session tries to resume but could not find + * the session to resume it. + */ void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx, WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*)) { - (void)ctx; - (void)f; -} + if (ctx == NULL) + return; +#ifdef HAVE_EXT_CACHE + ctx->get_sess_cb = f; +#else + (void)f; +#endif +} void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx, int (*f)(WOLFSSL*, WOLFSSL_SESSION*)) { - (void)ctx; - (void)f; -} + if (ctx == NULL) + return; +#ifdef HAVE_EXT_CACHE + ctx->new_sess_cb = f; +#else + (void)f; +#endif +} void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*, WOLFSSL_SESSION*)) { - (void)ctx; + if (ctx == NULL) + return; + +#ifdef HAVE_EXT_CACHE + ctx->rem_sess_cb = f; +#else (void)f; +#endif } +#endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */ +#ifdef OPENSSL_EXTRA +/* + * + * Note: It is expected that the importing and exporting function have been + * built with the same settings. For example if session tickets was + * enabled with the wolfSSL library exporting a session then it is + * expected to be turned on with the wolfSSL library importing the session. + */ 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; + + if (sess == NULL) { + return BAD_FUNC_ARG; + } + + /* 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; +#endif +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + /* Protocol version */ + size += OPAQUE16_LEN; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + /* cipher suite */ + size += OPAQUE16_LEN; +#endif +#ifndef NO_CLIENT_CACHE + /* ServerID len | ServerID */ + size += OPAQUE16_LEN + sess->idLen; +#endif +#ifdef OPENSSL_EXTRA + /* session context ID len | session context ID */ + size += OPAQUE8_LEN + sess->sessionCtxSz; +#endif +#ifdef WOLFSSL_TLS13 + /* namedGroup */ + size += OPAQUE16_LEN; +#endif +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifdef WOLFSSL_TLS13 + /* ticketSeen | ticketAdd */ + size += OPAQUE32_LEN + OPAQUE32_LEN; +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* ticketNonce */ + size += OPAQUE8_LEN + sess->ticketNonce.len; +#endif +#endif +#ifdef WOLFSSL_EARLY_DATA + size += OPAQUE32_LEN; +#endif +#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; + } +#endif +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + data[idx++] = sess->version.major; + data[idx++] = sess->version.minor; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + 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 OPENSSL_EXTRA + data[idx++] = sess->sessionCtxSz; + XMEMCPY(data + idx, sess->sessionCtx, sess->sessionCtxSz); + idx += sess->sessionCtxSz; +#endif +#ifdef WOLFSSL_TLS13 + c16toa(sess->namedGroup, data + idx); + idx += OPAQUE16_LEN; +#endif +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifdef WOLFSSL_TLS13 + c32toa(sess->ticketSeen, data + idx); + idx += OPAQUE32_LEN; + c32toa(sess->ticketAdd, data + idx); + idx += OPAQUE32_LEN; +#ifndef WOLFSSL_TLS13_DRAFT_18 + data[idx++] = sess->ticketNonce.len; + XMEMCPY(data + idx, sess->ticketNonce.data, sess->ticketNonce.len); + idx += sess->ticketNonce.len; +#endif +#endif +#ifdef WOLFSSL_EARLY_DATA + c32toa(sess->maxEarlyDataSz, data + idx); + idx += OPAQUE32_LEN; +#endif +#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. + * + * Note: It is expected that the importing and exporting function have been + * built with the same settings. For example if session tickets was + * enabled with the wolfSSL library exporting a session then it is + * expected to be turned on with the wolfSSL library importing the 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; + XMEMSET(s, 0, sizeof(WOLFSSL_SESSION)); + s->isAlloced = 1; +#ifdef HAVE_SESSION_TICKET + s->isDynamic = 0; +#endif + } + + 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; + } +#endif +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + /* Protocol Version */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->version.major = data[idx++]; + s->version.minor = data[idx++]; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + /* Cipher suite */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + 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 OPENSSL_EXTRA + /* byte for length of session context ID */ + if (i - idx < OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->sessionCtxSz = data[idx++]; + + /* app session context ID */ + if (i - idx < s->sessionCtxSz) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->sessionCtx, data + idx, s->sessionCtxSz); idx += s->sessionCtxSz; +#endif +#ifdef WOLFSSL_TLS13 + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &s->namedGroup); + idx += OPAQUE16_LEN; +#endif +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifdef WOLFSSL_TLS13 + if (i - idx < (OPAQUE32_LEN * 2)) { + ret = BUFFER_ERROR; + goto end; + } + ato32(data + idx, &s->ticketSeen); + idx += OPAQUE32_LEN; + ato32(data + idx, &s->ticketAdd); + idx += OPAQUE32_LEN; +#ifndef WOLFSSL_TLS13_DRAFT_18 + if (i - idx < OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->ticketNonce.len = data[idx++]; + + if (i - idx < s->ticketNonce.len) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->ticketNonce.data, data + idx, s->ticketNonce.len); + idx += s->ticketNonce.len; +#endif +#endif +#ifdef WOLFSSL_EARLY_DATA + if (i - idx < OPAQUE32_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato32(data + idx, &s->maxEarlyDataSz); + idx += OPAQUE32_LEN; +#endif +#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; } long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess) { + long timeout = 0; WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout"); - return sess->timeout; + if (sess) + timeout = sess->timeout; + return timeout; } long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) { + long bornOn = 0; WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); - return sess->bornOn; + if (sess) + bornOn = sess->bornOn; + return bornOn; } -int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b, - void* c) -{ - (void)idx; - (void)arg; - (void)a; - (void)b; - (void)c; - return 0; -} - #endif /* OPENSSL_EXTRA */ @@ -10655,76 +27297,65 @@ 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) { #ifdef WOLFSSL_SMALL_STACK - EncryptedInfo* info = NULL; byte staticBuffer[1]; /* force heap usage */ #else - EncryptedInfo info[1]; byte staticBuffer[FILE_BUFFER_SIZE]; #endif byte* myBuffer = staticBuffer; int dynamic = 0; - XFILE file = XBADFILE; + XFILE file; long sz = 0; - int eccKey = 0; - WOLFSSL_CTX* ctx = ssl->ctx; - WOLFSSL_X509* peer_cert = &ssl->peerCert; - buffer fileDer; + WOLFSSL_CTX* ctx = ssl->ctx; + WOLFSSL_X509* peer_cert = &ssl->peerCert; + DerBuffer* fileDer = NULL; file = XFOPEN(fname, "rb"); if (file == XBADFILE) - return SSL_BAD_FILE; + return WOLFSSL_BAD_FILE; - XFSEEK(file, 0, XSEEK_END); + if (XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } sz = XFTELL(file); XREWIND(file); + if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { + WOLFSSL_MSG("cmp_peer_cert_to_file size error"); + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + if (sz > (long)sizeof(staticBuffer)) { WOLFSSL_MSG("Getting dynamic buffer"); myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE); dynamic = 1; } - #ifdef WOLFSSL_SMALL_STACK - info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (info == NULL) - ret = MEMORY_E; - else - #endif + if ((myBuffer != NULL) && + (sz > 0) && + (XFREAD(myBuffer, 1, sz, file) == (size_t)sz) && + (PemToDer(myBuffer, (long)sz, CERT_TYPE, + &fileDer, ctx->heap, NULL, NULL) == 0) && + (fileDer->length != 0) && + (fileDer->length == peer_cert->derCert->length) && + (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer, + fileDer->length) == 0)) { - info->set = 0; - info->ctx = ctx; - info->consumed = 0; - fileDer.buffer = 0; - - if ((myBuffer != NULL) && - (sz > 0) && - (XFREAD(myBuffer, sz, 1, file) > 0) && - (PemToDer(myBuffer, sz, CERT_TYPE, - &fileDer, ctx->heap, info, &eccKey) == 0) && - (fileDer.length != 0) && - (fileDer.length == peer_cert->derCert.length) && - (XMEMCMP(peer_cert->derCert.buffer, fileDer.buffer, - fileDer.length) == 0)) - { - ret = 0; - } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + ret = 0; } - XFREE(fileDer.buffer, ctx->heap, DYNAMIC_TYPE_CERT); + FreeDer(&fileDer); + if (dynamic) XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); @@ -10734,20 +27365,379 @@ int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) return ret; } #endif +#endif /* OPENSSL_EXTRA */ +#endif /* !WOLFCRYPT_ONLY */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +const WOLFSSL_ObjectInfo wolfssl_object_info[] = { +#ifndef NO_CERTS + /* oidCertExtType */ + { NID_basic_constraints, BASIC_CA_OID, oidCertExtType, "basicConstraints", + "X509v3 Basic Constraints"}, + { NID_subject_alt_name, ALT_NAMES_OID, oidCertExtType, "subjectAltName", + "X509v3 Subject Alternative Name"}, + { CRL_DIST_OID, CRL_DIST_OID, oidCertExtType, "crlDistributionPoints", + "X509v3 CRL Distribution Points"}, + { NID_info_access, AUTH_INFO_OID, oidCertExtType, "authorityInfoAccess", + "Authority Information Access"}, + { NID_authority_key_identifier, AUTH_KEY_OID, oidCertExtType, + "authorityKeyIdentifier", "X509v3 Authority Key Identifier"}, + { NID_subject_key_identifier, SUBJ_KEY_OID, oidCertExtType, + "subjectKeyIdentifier", "X509v3 Subject Key Identifier"}, + { NID_key_usage, KEY_USAGE_OID, oidCertExtType, "keyUsage", + "X509v3 Key Usage"}, + { NID_inhibit_any_policy, INHIBIT_ANY_OID, oidCertExtType, + "inhibitAnyPolicy", "X509v3 Inhibit Any Policy"}, + { NID_ext_key_usage, KEY_USAGE_OID, oidCertExtType, + "extendedKeyUsage", "X509v3 Extended Key Usage"}, + { NID_name_constraints, NAME_CONS_OID, oidCertExtType, + "nameConstraints", "X509v3 Name Constraints"}, + { NID_certificate_policies, CERT_POLICY_OID, oidCertExtType, + "certificatePolicies", "X509v3 Certificate Policies"}, + /* oidCertAuthInfoType */ + { AIA_OCSP_OID, AIA_OCSP_OID, oidCertAuthInfoType, "authorityInfoAccess", + "Authority Information Access"}, + { AIA_CA_ISSUER_OID, AIA_CA_ISSUER_OID, oidCertAuthInfoType, + "caIssuers", "CA Issuers"}, -static RNG globalRNG; + /* oidCertPolicyType */ + { NID_any_policy, CP_ANY_OID, oidCertPolicyType, "anyPolicy", + "X509v3 Any Policy"}, + + /* oidCertAltNameType */ + { NID_hw_name_oid, HW_NAME_OID, oidCertAltNameType, "Hardware name",""}, + + /* oidCertKeyUseType */ + { NID_anyExtendedKeyUsage, EKU_ANY_OID, oidCertKeyUseType, + "anyExtendedKeyUsage", "Any Extended Key Usage"}, + { EKU_SERVER_AUTH_OID, EKU_SERVER_AUTH_OID, oidCertKeyUseType, + "serverAuth", "TLS Web Server Authentication"}, + { EKU_CLIENT_AUTH_OID, EKU_CLIENT_AUTH_OID, oidCertKeyUseType, + "clientAuth", "TLS Web Client Authentication"}, + { EKU_OCSP_SIGN_OID, EKU_OCSP_SIGN_OID, oidCertKeyUseType, + "OCSPSigning", "OCSP Signing"}, + + /* oidCertNameType */ + { NID_commonName, NID_commonName, oidCertNameType, "CN", "commonName"}, + { NID_surname, NID_surname, oidCertNameType, "SN", "surname"}, + { NID_serialNumber, NID_serialNumber, oidCertNameType, "serialNumber", + "serialNumber"}, + { NID_countryName, NID_countryName, oidCertNameType, "C", "countryName"}, + { NID_localityName, NID_localityName, oidCertNameType, "L", "localityName"}, + { NID_stateOrProvinceName, NID_stateOrProvinceName, oidCertNameType, "ST", + "stateOrProvinceName"}, + { NID_organizationName, NID_organizationName, oidCertNameType, "O", + "organizationName"}, + { NID_organizationalUnitName, NID_organizationalUnitName, oidCertNameType, + "OU", "organizationalUnitName"}, + { NID_emailAddress, NID_emailAddress, oidCertNameType, "emailAddress", + "emailAddress"}, + { NID_domainComponent, NID_domainComponent, oidCertNameType, "DC", + "domainComponent"}, + { NID_businessCategory, NID_businessCategory, oidCertNameType, "businessCategory", + "businessCategory"}, + { NID_jurisdictionCountryName, NID_jurisdictionCountryName, oidCertNameType, "jurisdictionC", + "jurisdictionCountryName"}, + { NID_jurisdictionStateOrProvinceName, NID_jurisdictionStateOrProvinceName, + oidCertNameType, "jurisdictionST", "jurisdictionStateOrProvinceName"}, +#endif +#ifdef OPENSSL_EXTRA /* OPENSSL_EXTRA_X509_SMALL only needs the above */ + /* oidHashType */ + #ifdef WOLFSSL_MD2 + { NID_md2, MD2h, oidHashType, "MD2", "md2"}, + #endif + #ifdef WOLFSSL_MD5 + { NID_md5, MD5h, oidHashType, "MD5", "md5"}, + #endif + #ifndef NO_SHA + { NID_sha1, SHAh, oidHashType, "SHA1", "sha1"}, + #endif + #ifdef WOLFSSL_SHA224 + { NID_sha224, SHA224h, oidHashType, "SHA224", "sha224"}, + #endif + #ifndef NO_SHA256 + { NID_sha256, SHA256h, oidHashType, "SHA256", "sha256"}, + #endif + #ifdef WOLFSSL_SHA384 + { NID_sha384, SHA384h, oidHashType, "SHA384", "sha384"}, + #endif + #ifdef WOLFSSL_SHA512 + { NID_sha512, SHA512h, oidHashType, "SHA512", "sha512"}, + #endif + + /* oidSigType */ + #ifndef NO_DSA + #ifndef NO_SHA + { CTC_SHAwDSA, CTC_SHAwDSA, oidSigType, "DSA-SHA1", "dsaWithSHA1"}, + #endif + #endif /* NO_DSA */ + #ifndef NO_RSA + #ifdef WOLFSSL_MD2 + { CTC_MD2wRSA, CTC_MD2wRSA, oidSigType, "RSA-MD2", + "md2WithRSAEncryption"}, + #endif + #ifndef NO_MD5 + { CTC_MD5wRSA, CTC_MD5wRSA, oidSigType, "RSA-MD5", + "md5WithRSAEncryption"}, + #endif + #ifndef NO_SHA + { CTC_SHAwRSA, CTC_SHAwRSA, oidSigType, "RSA-SHA1", + "sha1WithRSAEncryption"}, + #endif + #ifdef WOLFSSL_SHA224 + { CTC_SHA224wRSA, CTC_SHA224wRSA, oidSigType, "RSA-SHA224", + "sha224WithRSAEncryption"}, + #endif + #ifndef NO_SHA256 + { CTC_SHA256wRSA, CTC_SHA256wRSA, oidSigType, "RSA-SHA256", + "sha256WithRSAEncryption"}, + #endif + #ifdef WOLFSSL_SHA384 + { CTC_SHA384wRSA, CTC_SHA384wRSA, oidSigType, "RSA-SHA384", + "sha384WithRSAEncryption"}, + #endif + #ifdef WOLFSSL_SHA512 + { CTC_SHA512wRSA, CTC_SHA512wRSA, oidSigType, "RSA-SHA512", + "sha512WithRSAEncryption"}, + #endif + #endif /* NO_RSA */ + #ifdef HAVE_ECC + #ifndef NO_SHA + { CTC_SHAwECDSA, CTC_SHAwECDSA, oidSigType, "ecdsa-with-SHA1", "shaWithECDSA"}, + #endif + #ifdef WOLFSSL_SHA224 + { CTC_SHA224wECDSA, CTC_SHA224wECDSA, oidSigType, "ecdsa-with-SHA224","sha224WithECDSA"}, + #endif + #ifndef NO_SHA256 + { CTC_SHA256wECDSA, CTC_SHA256wECDSA, oidSigType, "ecdsa-with-SHA256","sha256WithECDSA"}, + #endif + #ifdef WOLFSSL_SHA384 + { CTC_SHA384wECDSA, CTC_SHA384wECDSA, oidSigType, "ecdsa-with-SHA384","sha384WithECDSA"}, + #endif + #ifdef WOLFSSL_SHA512 + { CTC_SHA512wECDSA, CTC_SHA512wECDSA, oidSigType, "ecdsa-with-SHA512","sha512WithECDSA"}, + #endif + #endif /* HAVE_ECC */ + + /* oidKeyType */ + #ifndef NO_DSA + { DSAk, DSAk, oidKeyType, "DSA", "dsaEncryption"}, + { NID_dsa, DSAk, oidKeyType, "DSA", "dsaEncryption"}, + #endif /* NO_DSA */ + #ifndef NO_RSA + { RSAk, RSAk, oidKeyType, "RSA", "rsaEncryption"}, + { NID_rsaEncryption, RSAk, oidKeyType, "RSA", "rsaEncryption"}, + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + { NTRUk, NTRUk, oidKeyType, "NTRU", "ntruEncryption"}, + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + { ECDSAk, ECDSAk, oidKeyType, "ECDSA", "ecdsaEncryption"}, + { NID_X9_62_id_ecPublicKey, ECDSAk, oidKeyType, "id-ecPublicKey", + "id-ecPublicKey"}, + #endif /* HAVE_ECC */ + #ifndef NO_DH + { NID_dhKeyAgreement, DHk, oidKeyType, "dhKeyAgreement", "dhKeyAgreement"}, + #endif + + /* oidCurveType */ + #ifdef HAVE_ECC + { NID_X9_62_prime192v1, ECC_SECP192R1_OID, oidCurveType, "prime192v1", "prime192v1"}, + { NID_X9_62_prime192v2, ECC_PRIME192V2_OID, oidCurveType, "prime192v2", "prime192v2"}, + { NID_X9_62_prime192v3, ECC_PRIME192V3_OID, oidCurveType, "prime192v3", "prime192v3"}, + + { NID_X9_62_prime239v1, ECC_PRIME239V1_OID, oidCurveType, "prime239v1", "prime239v1"}, + { NID_X9_62_prime239v2, ECC_PRIME239V2_OID, oidCurveType, "prime239v2", "prime239v2"}, + { NID_X9_62_prime239v3, ECC_PRIME239V3_OID, oidCurveType, "prime239v3", "prime239v3"}, + + { NID_X9_62_prime256v1, ECC_SECP256R1_OID, oidCurveType, "prime256v1", "prime256v1"}, + + { NID_secp112r1, ECC_SECP112R1_OID, oidCurveType, "secp112r1", "secp112r1"}, + { NID_secp112r2, ECC_SECP112R2_OID, oidCurveType, "secp112r2", "secp112r2"}, + + { NID_secp128r1, ECC_SECP128R1_OID, oidCurveType, "secp128r1", "secp128r1"}, + { NID_secp128r2, ECC_SECP128R2_OID, oidCurveType, "secp128r2", "secp128r2"}, + + { NID_secp160r1, ECC_SECP160R1_OID, oidCurveType, "secp160r1", "secp160r1"}, + { NID_secp160r2, ECC_SECP160R2_OID, oidCurveType, "secp160r2", "secp160r2"}, + + { NID_secp224r1, ECC_SECP224R1_OID, oidCurveType, "secp224r1", "secp224r1"}, + { NID_secp384r1, ECC_SECP384R1_OID, oidCurveType, "secp384r1", "secp384r1"}, + { NID_secp521r1, ECC_SECP521R1_OID, oidCurveType, "secp521r1", "secp521r1"}, + + { NID_secp160k1, ECC_SECP160K1_OID, oidCurveType, "secp160k1", "secp160k1"}, + { NID_secp192k1, ECC_SECP192K1_OID, oidCurveType, "secp192k1", "secp192k1"}, + { NID_secp224k1, ECC_SECP224K1_OID, oidCurveType, "secp224k1", "secp224k1"}, + { NID_secp256k1, ECC_SECP256K1_OID, oidCurveType, "secp256k1", "secp256k1"}, + + { NID_brainpoolP160r1, ECC_BRAINPOOLP160R1_OID, oidCurveType, "brainpoolP160r1", "brainpoolP160r1"}, + { NID_brainpoolP192r1, ECC_BRAINPOOLP192R1_OID, oidCurveType, "brainpoolP192r1", "brainpoolP192r1"}, + { NID_brainpoolP224r1, ECC_BRAINPOOLP224R1_OID, oidCurveType, "brainpoolP224r1", "brainpoolP224r1"}, + { NID_brainpoolP256r1, ECC_BRAINPOOLP256R1_OID, oidCurveType, "brainpoolP256r1", "brainpoolP256r1"}, + { NID_brainpoolP320r1, ECC_BRAINPOOLP320R1_OID, oidCurveType, "brainpoolP320r1", "brainpoolP320r1"}, + { NID_brainpoolP384r1, ECC_BRAINPOOLP384R1_OID, oidCurveType, "brainpoolP384r1", "brainpoolP384r1"}, + { NID_brainpoolP512r1, ECC_BRAINPOOLP512R1_OID, oidCurveType, "brainpoolP512r1", "brainpoolP512r1"}, + #endif /* HAVE_ECC */ + + /* oidBlkType */ + #ifdef WOLFSSL_AES_128 + { AES128CBCb, AES128CBCb, oidBlkType, "AES-128-CBC", "aes-128-cbc"}, + #endif + #ifdef WOLFSSL_AES_192 + { AES192CBCb, AES192CBCb, oidBlkType, "AES-192-CBC", "aes-192-cbc"}, + #endif + #ifdef WOLFSSL_AES_256 + { AES256CBCb, AES256CBCb, oidBlkType, "AES-256-CBC", "aes-256-cbc"}, + #endif + #ifndef NO_DES3 + { NID_des, DESb, oidBlkType, "DES-CBC", "des-cbc"}, + { NID_des3, DES3b, oidBlkType, "DES-EDE3-CBC", "des-ede3-cbc"}, + #endif /* !NO_DES3 */ + + /* oidOcspType */ + #ifdef HAVE_OCSP + { NID_id_pkix_OCSP_basic, OCSP_BASIC_OID, oidOcspType, "basicOCSPResponse", + "Basic OCSP Response"}, + { OCSP_NONCE_OID, OCSP_NONCE_OID, oidOcspType, "Nonce", + "OCSP Nonce"}, + #endif /* HAVE_OCSP */ + + #ifndef NO_PWDBASED + /* oidKdfType */ + { PBKDF2_OID, PBKDF2_OID, oidKdfType, "PBKDFv2", "PBKDF2"}, + + /* oidPBEType */ + { PBE_SHA1_RC4_128, PBE_SHA1_RC4_128, oidPBEType, + "PBE-SHA1-RC4-128", "pbeWithSHA1And128BitRC4"}, + { PBE_SHA1_DES, PBE_SHA1_DES, oidPBEType, "PBE-SHA1-DES", + "pbeWithSHA1AndDES-CBC"}, + { PBE_SHA1_DES3, PBE_SHA1_DES3, oidPBEType, "PBE-SHA1-3DES", + "pbeWithSHA1And3-KeyTripleDES-CBC"}, + #endif + + /* oidKeyWrapType */ + #ifdef WOLFSSL_AES_128 + { AES128_WRAP, AES128_WRAP, oidKeyWrapType, "AES-128 wrap", "aes128-wrap"}, + #endif + #ifdef WOLFSSL_AES_192 + { AES192_WRAP, AES192_WRAP, oidKeyWrapType, "AES-192 wrap", "aes192-wrap"}, + #endif + #ifdef WOLFSSL_AES_256 + { AES256_WRAP, AES256_WRAP, oidKeyWrapType, "AES-256 wrap", "aes256-wrap"}, + #endif + + #ifndef NO_PKCS7 + #ifndef NO_DH + /* oidCmsKeyAgreeType */ + #ifndef NO_SHA + { dhSinglePass_stdDH_sha1kdf_scheme, dhSinglePass_stdDH_sha1kdf_scheme, + oidCmsKeyAgreeType, "dhSinglePass-stdDH-sha1kdf-scheme", "dhSinglePass-stdDH-sha1kdf-scheme"}, + #endif + #ifdef WOLFSSL_SHA224 + { dhSinglePass_stdDH_sha224kdf_scheme, + dhSinglePass_stdDH_sha224kdf_scheme, oidCmsKeyAgreeType, + "dhSinglePass-stdDH-sha224kdf-scheme", "dhSinglePass-stdDH-sha224kdf-scheme"}, + #endif + #ifndef NO_SHA256 + { dhSinglePass_stdDH_sha256kdf_scheme, + dhSinglePass_stdDH_sha256kdf_scheme, oidCmsKeyAgreeType, + "dhSinglePass-stdDH-sha256kdf-scheme", "dhSinglePass-stdDH-sha256kdf-scheme"}, + #endif + #ifdef WOLFSSL_SHA384 + { dhSinglePass_stdDH_sha384kdf_scheme, + dhSinglePass_stdDH_sha384kdf_scheme, oidCmsKeyAgreeType, + "dhSinglePass-stdDH-sha384kdf-scheme", "dhSinglePass-stdDH-sha384kdf-scheme"}, + #endif + #ifdef WOLFSSL_SHA512 + { dhSinglePass_stdDH_sha512kdf_scheme, + dhSinglePass_stdDH_sha512kdf_scheme, oidCmsKeyAgreeType, + "dhSinglePass-stdDH-sha512kdf-scheme", "dhSinglePass-stdDH-sha512kdf-scheme"}, + #endif + #endif + #endif + #if defined(WOLFSSL_APACHE_HTTPD) + /* "1.3.6.1.5.5.7.8.7" */ + { NID_id_on_dnsSRV, NID_id_on_dnsSRV, oidCertNameType, + WOLFSSL_SN_DNS_SRV, WOLFSSL_LN_DNS_SRV }, + + /* "1.3.6.1.4.1.311.20.2.3" */ + { NID_ms_upn, WOLFSSL_MS_UPN_SUM, oidCertExtType, WOLFSSL_SN_MS_UPN, + WOLFSSL_LN_MS_UPN }, + + /* "1.3.6.1.5.5.7.1.24" */ + { NID_tlsfeature, WOLFSSL_TLS_FEATURE_SUM, oidTlsExtType, + WOLFSSL_SN_TLS_FEATURE, WOLFSSL_LN_TLS_FEATURE }, + #endif +#endif /* OPENSSL_EXTRA */ +}; + +#define WOLFSSL_OBJECT_INFO_SZ \ + (sizeof(wolfssl_object_info) / sizeof(*wolfssl_object_info)) +const size_t wolfssl_object_info_sz = WOLFSSL_OBJECT_INFO_SZ; +#endif +#if defined(OPENSSL_EXTRA) || \ + (defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA)) +static WC_RNG globalRNG; static int initGlobalRNG = 0; - -/* SSL_SUCCESS on ok */ -int wolfSSL_RAND_seed(const void* seed, int len) +#endif +#if defined(OPENSSL_EXTRA) && \ + !defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) +WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG, int *initTmpRng) { + WC_RNG* rng = NULL; - WOLFSSL_MSG("wolfSSL_RAND_seed"); + if (!rsa || !initTmpRng) { + return NULL; + } + *initTmpRng = 0; - (void)seed; - (void)len; +#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 && tmpRNG) { + if (!*tmpRNG) { +#ifdef WOLFSSL_SMALL_STACK + *tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (*tmpRNG == NULL) + return NULL; +#else + WOLFSSL_MSG("*tmpRNG is null"); + return NULL; +#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; +#ifdef WOLFSSL_SMALL_STACK + if (*tmpRNG) + XFREE(*tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + *tmpRNG = NULL; +#endif + } + } + return rng; +} +#endif +#ifndef WOLFCRYPT_ONLY + +#ifdef OPENSSL_EXTRA + +/* Not thread safe! Can be called multiple times. + * Checks if the global RNG has been created. If not then one is created. + * + * Returns SSL_SUCCESS when no error is encountered. + */ +static int wolfSSL_RAND_Init(void) +{ if (initGlobalRNG == 0) { if (wc_InitRng(&globalRNG) < 0) { WOLFSSL_MSG("wolfSSL Init Global RNG failed"); @@ -10761,515 +27751,669 @@ int wolfSSL_RAND_seed(const void* seed, int len) /* SSL_SUCCESS on ok */ -int wolfSSL_RAND_bytes(unsigned char* buf, int num) +int wolfSSL_RAND_seed(const void* seed, int len) { - int ret = 0; - int initTmpRng = 0; - RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - RNG* tmpRNG = NULL; + + WOLFSSL_MSG("wolfSSL_RAND_seed"); + + (void)seed; + (void)len; + + return wolfSSL_RAND_Init(); +} + + +/* Returns the path for reading seed data from. + * Uses the env variable $RANDFILE first if set, if not then used $HOME/.rnd + * + * Note uses stdlib by default unless XGETENV macro is overwritten + * + * fname buffer to hold path + * len length of fname buffer + * + * Returns a pointer to fname on success and NULL on failure + */ +const char* wolfSSL_RAND_file_name(char* fname, unsigned long len) +{ +#ifndef NO_FILESYSTEM + char* rt; + char ap[] = "/.rnd"; + + WOLFSSL_ENTER("wolfSSL_RAND_file_name"); + + if (fname == NULL) { + return NULL; + } + + XMEMSET(fname, 0, len); + /* if access to stdlib.h */ + if ((rt = XGETENV("RANDFILE")) != NULL) { + if (len > XSTRLEN(rt)) { + XMEMCPY(fname, rt, XSTRLEN(rt)); + } + else { + WOLFSSL_MSG("RANDFILE too large for buffer"); + rt = NULL; + } + } + + /* $RANDFILE was not set or is too large, check $HOME */ + if (rt == NULL) { + WOLFSSL_MSG("Environment variable RANDFILE not set"); + if ((rt = XGETENV("HOME")) == NULL) { + WOLFSSL_MSG("Environment variable HOME not set"); + return NULL; + } + + if (len > XSTRLEN(rt) + XSTRLEN(ap)) { + fname[0] = '\0'; + XSTRNCAT(fname, rt, len); + XSTRNCAT(fname, ap, len - XSTRLEN(rt)); + return fname; + } + else { + WOLFSSL_MSG("HOME too large for buffer"); + return NULL; + } + } + + return fname; #else - RNG tmpRNG[1]; + /* no filesystem defined */ + WOLFSSL_ENTER("wolfSSL_RAND_file_name"); + WOLFSSL_MSG("No filesystem feature enabled, not compiled in"); + (void)fname; + (void)len; + return NULL; +#endif +} + + +/* Writes 1024 bytes from the RNG to the given file name. + * + * fname name of file to write to + * + * Returns the number of bytes written + */ +int wolfSSL_RAND_write_file(const char* fname) +{ + int bytes = 0; + + WOLFSSL_ENTER("RAND_write_file"); + + if (fname == NULL) { + return SSL_FAILURE; + } + +#ifndef NO_FILESYSTEM + { + #ifndef WOLFSSL_SMALL_STACK + unsigned char buf[1024]; + #else + unsigned char* buf = (unsigned char *)XMALLOC(1024, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + WOLFSSL_MSG("malloc failed"); + return SSL_FAILURE; + } + #endif + bytes = 1024; /* default size of buf */ + + if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != SSL_SUCCESS) { + WOLFSSL_MSG("No RNG to use"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return 0; + } + + if (wc_RNG_GenerateBlock(&globalRNG, buf, bytes) != 0) { + WOLFSSL_MSG("Error generating random buffer"); + bytes = 0; + } + else { + XFILE f; + + f = XFOPEN(fname, "wb"); + if (f == XBADFILE) { + WOLFSSL_MSG("Error opening the file"); + bytes = 0; + } + else { + XFWRITE(buf, 1, bytes, f); + XFCLOSE(f); + } + } + ForceZero(buf, bytes); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } #endif - WOLFSSL_ENTER("RAND_bytes"); + return bytes; +} + +#ifndef FREERTOS_TCP + +/* These constant values are protocol values made by egd */ +#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) + #define WOLFSSL_EGD_NBLOCK 0x01 + #include +#endif + +/* This collects entropy from the path nm and seeds the global PRNG with it. + * Makes a call to wolfSSL_RAND_Init which is not thread safe. + * + * nm is the file path to the egd server + * + * Returns the number of bytes read. + */ +int wolfSSL_RAND_egd(const char* nm) +{ +#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) && !defined(HAVE_FIPS) && \ + defined(HAVE_HASHDRBG) + struct sockaddr_un rem; + int fd; + int ret = WOLFSSL_SUCCESS; + word32 bytes = 0; + word32 idx = 0; +#ifndef WOLFSSL_SMALL_STACK + unsigned char buf[256]; +#else + unsigned char* buf; + buf = (unsigned char*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + WOLFSSL_MSG("Not enough memory"); + return WOLFSSL_FATAL_ERROR; + } +#endif + + if (nm == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return WOLFSSL_FATAL_ERROR; + } + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + WOLFSSL_MSG("Error creating socket"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return WOLFSSL_FATAL_ERROR; + } + if (ret == WOLFSSL_SUCCESS) { + rem.sun_family = AF_UNIX; + XSTRNCPY(rem.sun_path, nm, sizeof(rem.sun_path) - 1); + rem.sun_path[sizeof(rem.sun_path)-1] = '\0'; + } + + /* connect to egd server */ + if (ret == WOLFSSL_SUCCESS) { + if (connect(fd, (struct sockaddr*)&rem, sizeof(struct sockaddr_un)) + == -1) { + WOLFSSL_MSG("error connecting to egd server"); + ret = WOLFSSL_FATAL_ERROR; + } + } + + while (ret == WOLFSSL_SUCCESS && bytes < 255 && idx + 2 < 256) { + if (ret == WOLFSSL_SUCCESS) { + buf[idx] = WOLFSSL_EGD_NBLOCK; + buf[idx + 1] = 255 - bytes; /* request 255 bytes from server */ + ret = (int)write(fd, buf + idx, 2); + if (ret <= 0 || ret != 2) { + if (errno == EAGAIN) { + ret = WOLFSSL_SUCCESS; + continue; + } + WOLFSSL_MSG("error requesting entropy from egd server"); + ret = WOLFSSL_FATAL_ERROR; + break; + } + } + + /* attempting to read */ + buf[idx] = 0; + ret = (int)read(fd, buf + idx, 256 - bytes); + if (ret == 0) { + WOLFSSL_MSG("error reading entropy from egd server"); + ret = WOLFSSL_FATAL_ERROR; + break; + } + if (ret > 0 && buf[idx] > 0) { + bytes += buf[idx]; /* egd stores amount sent in first byte */ + if (bytes + idx > 255 || buf[idx] > ret) { + WOLFSSL_MSG("Buffer error"); + ret = WOLFSSL_FATAL_ERROR; + break; + } + XMEMMOVE(buf + idx, buf + idx + 1, buf[idx]); + idx = bytes; + ret = WOLFSSL_SUCCESS; + if (bytes >= 255) { + break; + } + } + else { + if (errno == EAGAIN || errno == EINTR) { + WOLFSSL_MSG("EGD would read"); + ret = WOLFSSL_SUCCESS; /* try again */ + } + else if (buf[idx] == 0) { + /* if egd returned 0 then there is no more entropy to be had. + Do not try more reads. */ + ret = WOLFSSL_SUCCESS; + break; + } + else { + WOLFSSL_MSG("Error with read"); + ret = WOLFSSL_FATAL_ERROR; + } + } + } + + if (bytes > 0 && ret == WOLFSSL_SUCCESS) { + wolfSSL_RAND_Init(); /* call to check global RNG is created */ + if (wc_RNG_DRBG_Reseed(&globalRNG, (const byte*) buf, bytes) + != 0) { + WOLFSSL_MSG("Error with reseeding DRBG structure"); + ret = WOLFSSL_FATAL_ERROR; + } + #ifdef SHOW_SECRETS + { /* print out entropy found */ + word32 i; + printf("EGD Entropy = "); + for (i = 0; i < bytes; i++) { + printf("%02X", buf[i]); + } + printf("\n"); + } + #endif + } + + ForceZero(buf, bytes); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + close(fd); + + if (ret == WOLFSSL_SUCCESS) { + return bytes; + } + else { + return ret; + } +#else + WOLFSSL_MSG("Type of socket needed is not available"); + WOLFSSL_MSG("\tor using mode where DRBG API is not available"); + (void)nm; + + return WOLFSSL_FATAL_ERROR; +#endif /* USE_WOLFSSL_IO && !USE_WINDOWS_API && !HAVE_FIPS && HAVE_HASHDRBG */ +} + +#endif /* !FREERTOS_TCP */ + +void wolfSSL_RAND_Cleanup(void) +{ + WOLFSSL_ENTER("wolfSSL_RAND_Cleanup()"); + + if (initGlobalRNG != 0) { + wc_FreeRng(&globalRNG); + initGlobalRNG = 0; + } +} + + +int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num) +{ + return wolfSSL_RAND_bytes(buf, num); +} + + +/* SSL_SUCCESS on ok */ +int wolfSSL_RAND_bytes(unsigned char* buf, int num) +{ + int ret = 0; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_RAND_bytes"); #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (tmpRNG == NULL) return ret; #endif - if (wc_InitRng(tmpRNG) == 0) { + if (initGlobalRNG) + rng = &globalRNG; + else if(wc_InitRng(tmpRNG) == 0) { rng = tmpRNG; initTmpRng = 1; } - else if (initGlobalRNG) - rng = &globalRNG; - if (rng) { 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; } -WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void) + +int wolfSSL_RAND_poll(void) { - static int ctx; /* wolfcrypt doesn't now need ctx */ + byte entropy[16]; + int ret = 0; + word32 entropy_sz = 16; - WOLFSSL_MSG("wolfSSL_BN_CTX_new"); - - return (WOLFSSL_BN_CTX*)&ctx; -} - -void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx) -{ - (void)ctx; - WOLFSSL_MSG("wolfSSL_BN_CTX_init"); -} - - -void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx) -{ - (void)ctx; - WOLFSSL_MSG("wolfSSL_BN_CTX_free"); - - /* do free since static ctx that does nothing */ -} - - -static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("InitwolfSSL_BigNum"); - if (bn) { - bn->neg = 0; - bn->internal = NULL; + WOLFSSL_ENTER("wolfSSL_RAND_poll"); + if (initGlobalRNG == 0){ + WOLFSSL_MSG("Global RNG no Init"); + return WOLFSSL_FAILURE; } + ret = wc_GenerateSeed(&globalRNG.seed, entropy, entropy_sz); + if (ret != 0){ + WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + ret = WOLFSSL_FAILURE; + }else + ret = WOLFSSL_SUCCESS; + + return ret; } +#endif /* OPENSSL_EXTRA */ -WOLFSSL_BIGNUM* wolfSSL_BN_new(void) + +#ifdef OPENSSL_EXTRA + +WOLFSSL_ASN1_INTEGER* wolfSSL_BN_to_ASN1_INTEGER(const WOLFSSL_BIGNUM *bn, WOLFSSL_ASN1_INTEGER *ai) { - WOLFSSL_BIGNUM* external; - mp_int* mpi; + WOLFSSL_ASN1_INTEGER* a; + int len; + WOLFSSL_ENTER("wolfSSL_BN_to_ASN1_INTEGER"); - WOLFSSL_MSG("wolfSSL_BN_new"); + if (ai == NULL) { + a = wolfSSL_ASN1_INTEGER_new(); - mpi = (mp_int*) XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (mpi == NULL) { - WOLFSSL_MSG("wolfSSL_BN_new malloc mpi failure"); - return NULL; - } - - external = (WOLFSSL_BIGNUM*) XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL, - DYNAMIC_TYPE_BIGINT); - if (external == NULL) { - WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure"); - XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT); - return NULL; - } - - InitwolfSSL_BigNum(external); - external->internal = mpi; - if (mp_init(mpi) != MP_OKAY) { - wolfSSL_BN_free(external); - return NULL; - } - - return external; -} - - -void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_free"); - if (bn) { - if (bn->internal) { - mp_clear((mp_int*)bn->internal); - XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT); - bn->internal = NULL; - } - XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT); - } -} - - -void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_clear_free"); - - wolfSSL_BN_free(bn); -} - - -/* SSL_SUCCESS on ok */ -int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, - const WOLFSSL_BIGNUM* b) -{ - WOLFSSL_MSG("wolfSSL_BN_sub"); - - if (r == NULL || a == NULL || b == NULL) - return 0; - - if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal, - (mp_int*)r->internal) == MP_OKAY) - return SSL_SUCCESS; - - WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed"); - return 0; -} - - -/* SSL_SUCCESS on ok */ -int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, - const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c) -{ - (void)c; - WOLFSSL_MSG("wolfSSL_BN_mod"); - - if (r == NULL || a == NULL || b == NULL) - return 0; - - if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal, - (mp_int*)r->internal) == MP_OKAY) - return SSL_SUCCESS; - - WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed"); - return 0; -} - - -const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void) -{ - static WOLFSSL_BIGNUM* bn_one = NULL; - - WOLFSSL_MSG("wolfSSL_BN_value_one"); - - if (bn_one == NULL) { - bn_one = wolfSSL_BN_new(); - if (bn_one) - mp_set_int((mp_int*)bn_one->internal, 1); - } - - return bn_one; -} - - -int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_num_bytes"); - - if (bn == NULL || bn->internal == NULL) - return 0; - - return mp_unsigned_bin_size((mp_int*)bn->internal); -} - - -int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_num_bits"); - - if (bn == NULL || bn->internal == NULL) - return 0; - - return mp_count_bits((mp_int*)bn->internal); -} - - -int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_is_zero"); - - if (bn == NULL || bn->internal == NULL) - return 0; - - return mp_iszero((mp_int*)bn->internal); -} - - -int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_is_one"); - - if (bn == NULL || bn->internal == NULL) - return 0; - - if (mp_cmp_d((mp_int*)bn->internal, 1) == 0) - return 1; - - return 0; -} - - -int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_is_odd"); - - if (bn == NULL || bn->internal == NULL) - return 0; - - return mp_isodd((mp_int*)bn->internal); -} - - -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 0; - - return mp_cmp((mp_int*)a->internal, (mp_int*)b->internal); -} - - -int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r) -{ - WOLFSSL_MSG("wolfSSL_BN_bn2bin"); - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("NULL bn error"); - return SSL_FATAL_ERROR; - } - - if (r == NULL) - return mp_unsigned_bin_size((mp_int*)bn->internal); - - if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) { - WOLFSSL_MSG("mp_to_unsigned_bin error"); - return SSL_FATAL_ERROR; - } - - return mp_unsigned_bin_size((mp_int*)bn->internal); -} - - -WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len, - WOLFSSL_BIGNUM* ret) -{ - WOLFSSL_MSG("wolfSSL_BN_bin2bn"); - - if (ret && ret->internal) { - if (mp_read_unsigned_bin((mp_int*)ret->internal, str, len) != 0) { - WOLFSSL_MSG("mp_read_unsigned_bin failure"); + if (a == NULL) return NULL; - } + + a->type = V_ASN1_INTEGER; } else { - WOLFSSL_MSG("wolfSSL_BN_bin2bn wants return bignum"); + a = ai; } + if (a) { + if (wolfSSL_BN_is_negative(bn) && !wolfSSL_BN_is_zero(bn)) { + a->type |= V_ASN1_NEG_INTEGER; + a->negative = 1; + } - return ret; -} + len = wolfSSL_BN_num_bytes(bn); + if (len == 0) + len = 1; - -int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n) -{ - (void)bn; - (void)n; - WOLFSSL_MSG("wolfSSL_BN_mask_bits"); - - return SSL_FATAL_ERROR; -} - - -/* SSL_SUCCESS on ok */ -int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) -{ - int ret = 0; - int len = bits / 8; - int initTmpRng = 0; - RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - RNG* tmpRNG = NULL; - byte* buff = NULL; -#else - RNG tmpRNG[1]; - byte buff[1024]; -#endif - - (void)top; - (void)bottom; - WOLFSSL_MSG("wolfSSL_BN_rand"); - - if (bits % 8) - len++; - -#ifdef WOLFSSL_SMALL_STACK - buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); - tmpRNG = (RNG*) XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (buff == NULL || tmpRNG == NULL) { - XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } -#endif - - if (bn == NULL || bn->internal == NULL) - WOLFSSL_MSG("Bad function arguments"); - else if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; - } - else if (initGlobalRNG) - rng = &globalRNG; - - if (rng) { - if (wc_RNG_GenerateBlock(rng, buff, len) != 0) - WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + /* allocate buffer */ + if (len > (int)sizeof(a->intData)) { + /* create new data buffer and copy over */ + a->data = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); + if (a->data == NULL) { + if (a != ai) + wolfSSL_ASN1_INTEGER_free(a); + return NULL; + } + a->isDynamic = 1; + } else { - buff[0] |= 0x80 | 0x40; - buff[len-1] |= 0x01; + XMEMSET(a->intData, 0, sizeof(a->intData)); + a->data = a->intData; + } + a->length = len; - if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY) - WOLFSSL_MSG("mp read bin failed"); - else - ret = SSL_SUCCESS; + /* populate data */ + if (wolfSSL_BN_is_zero(bn)) { + a->data[0] = 0; + } + else { + len = wolfSSL_BN_bn2bin(bn, a->data); + } + a->length = len; + } + + return a; +} + +#ifdef OPENSSL_ALL +void *wolfSSL_ASN1_item_new(const WOLFSSL_ASN1_ITEM *template) +{ + void *ret = NULL; + const WOLFSSL_ASN1_TEMPLATE *member = NULL; + size_t i; + WOLFSSL_ENTER("wolfSSL_ASN1_item_new"); + if (!template) { + return NULL; + } + if (!(ret = XMALLOC(template->size, NULL, DYNAMIC_TYPE_OPENSSL))) { + return NULL; + } + XMEMSET(ret, 0, template->size); + for (member = template->members, i = 0; i < template->mcount; + member++, i++) { + switch (member->type) { + case WOLFSSL_X509_ALGOR_ASN1: + { + WOLFSSL_X509_ALGOR* algor = wolfSSL_X509_ALGOR_new(); + if (!algor) { + goto error; + } + *(WOLFSSL_X509_ALGOR**)(((byte*)ret) + member->offset) = algor; + break; + } + case WOLFSSL_ASN1_BIT_STRING_ASN1: + { + WOLFSSL_ASN1_BIT_STRING* bit_str = wolfSSL_ASN1_BIT_STRING_new(); + if (!bit_str) { + goto error; + } + *(WOLFSSL_ASN1_BIT_STRING**)(((byte*)ret) + member->offset) = bit_str; + break; + } + default: + WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_new"); + goto error; } } - - if (initTmpRng) - wc_FreeRng(tmpRNG); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; -} - - -int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n) -{ - (void)bn; - (void)n; - - WOLFSSL_MSG("wolfSSL_BN_is_bit_set"); - - return 0; -} - - -/* SSL_SUCCESS on ok */ -int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str) -{ - int ret = 0; - word32 decSz = 1024; -#ifdef WOLFSSL_SMALL_STACK - byte* decoded = NULL; -#else - byte decoded[1024]; -#endif - - WOLFSSL_MSG("wolfSSL_BN_hex2bn"); - -#ifdef WOLFSSL_SMALL_STACK - decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (decoded == NULL) - return ret; -#endif - - if (str == NULL) - WOLFSSL_MSG("Bad function argument"); - else if (Base16_Decode((byte*)str, (int)XSTRLEN(str), decoded, &decSz) < 0) - WOLFSSL_MSG("Bad Base16_Decode error"); - else if (bn == NULL) - ret = decSz; - else { - if (*bn == NULL) - *bn = wolfSSL_BN_new(); - - if (*bn == NULL) - WOLFSSL_MSG("BN new failed"); - else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) - WOLFSSL_MSG("Bad bin2bn error"); - else - ret = SSL_SUCCESS; - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - - -WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_BIGNUM* ret; - - WOLFSSL_MSG("wolfSSL_BN_dup"); - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return NULL; - } - - ret = wolfSSL_BN_new(); - if (ret == NULL) { - WOLFSSL_MSG("bn new error"); - return NULL; - } - - if (mp_copy((mp_int*)bn->internal, (mp_int*)ret->internal) != MP_OKAY) { - WOLFSSL_MSG("mp_copy error"); - wolfSSL_BN_free(ret); - return NULL; - } - - return ret; -} - - -WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn) -{ - (void)r; - (void)bn; - - WOLFSSL_MSG("wolfSSL_BN_copy"); - +error: + wolfSSL_ASN1_item_free(ret, template); return NULL; } - -int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, unsigned long w) +void wolfSSL_ASN1_item_free(void *val, const WOLFSSL_ASN1_ITEM *template) { - (void)bn; - (void)w; - - WOLFSSL_MSG("wolfSSL_BN_set_word"); - - return SSL_FATAL_ERROR; + const WOLFSSL_ASN1_TEMPLATE *member = NULL; + size_t i; + WOLFSSL_ENTER("wolfSSL_ASN1_item_free"); + if (val) { + for (member = template->members, i = 0; i < template->mcount; + member++, i++) { + switch (member->type) { + case WOLFSSL_X509_ALGOR_ASN1: + { + WOLFSSL_X509_ALGOR* algor = *(WOLFSSL_X509_ALGOR**) + (((byte*)val) + member->offset); + if (algor) { + wolfSSL_X509_ALGOR_free(algor); + } + break; + } + case WOLFSSL_ASN1_BIT_STRING_ASN1: + { + WOLFSSL_ASN1_BIT_STRING* bit_str = *(WOLFSSL_ASN1_BIT_STRING**) + (((byte*)val) + member->offset); + if (bit_str) { + wolfSSL_ASN1_BIT_STRING_free(bit_str); + } + break; + } + default: + WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_free"); + } + } + XFREE(val, NULL, DYNAMIC_TYPE_OPENSSL); + } } +#define bufLenOrNull(buf, len) (buf ? buf + len : NULL) -int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str) +static int i2dProcessMembers(const void *src, byte *buf, + const WOLFSSL_ASN1_TEMPLATE *members, size_t mcount) { - (void)bn; - (void)str; + const WOLFSSL_ASN1_TEMPLATE *member = NULL; + int len = 0, ret; + size_t i; + WOLFSSL_ENTER("processMembers"); + for (member = members, i = 0; i < mcount; member++, i++) { + switch (member->type) { + case WOLFSSL_X509_ALGOR_ASN1: + { + word32 oid = 0; + word32 idx = 0; + const WOLFSSL_X509_ALGOR* algor = *(const WOLFSSL_X509_ALGOR**) + (((byte*)src) + member->offset); + if (!algor->algorithm) { + WOLFSSL_LEAVE("processMembers", WOLFSSL_FAILURE); + return WOLFSSL_FAILURE; + } - WOLFSSL_MSG("wolfSSL_BN_dec2bn"); + if (GetObjectId(algor->algorithm->obj, &idx, &oid, + algor->algorithm->grp, algor->algorithm->objSz) < 0) { + WOLFSSL_MSG("Issue getting OID of object"); + return -1; + } - return SSL_FATAL_ERROR; + ret = SetAlgoID(oid, bufLenOrNull(buf, len), + algor->algorithm->grp, 0); + if (!ret) { + return WOLFSSL_FAILURE; + } + len += ret; + break; + } + case WOLFSSL_ASN1_BIT_STRING_ASN1: + { + const WOLFSSL_ASN1_BIT_STRING* bit_str; + bit_str = *(const WOLFSSL_ASN1_BIT_STRING**) + (((byte*)src) + member->offset); + len += SetBitString(bit_str->length, 0, bufLenOrNull(buf, len)); + if (buf && bit_str->data) { + XMEMCPY(buf + len, bit_str->data, bit_str->length); + } + len += bit_str->length; + break; + } + default: + WOLFSSL_MSG("Type not support in processMembers"); + WOLFSSL_LEAVE("processMembers", WOLFSSL_FAILURE); + return WOLFSSL_FAILURE; + } + } + WOLFSSL_LEAVE("processMembers", len); + return len; } - -char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn) +int wolfSSL_ASN1_item_i2d(const void *src, byte **dest, + const WOLFSSL_ASN1_ITEM *template) { - (void)bn; + int len = 0; + byte *buf = NULL; - WOLFSSL_MSG("wolfSSL_BN_bn2dec"); + WOLFSSL_ENTER("wolfSSL_ASN1_item_i2d"); - return NULL; + if (!src || !template) { + WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", WOLFSSL_FAILURE); + return WOLFSSL_FAILURE; + } + + if (dest && !*dest) { + len = wolfSSL_ASN1_item_i2d(src, NULL, template); + if (!len) { + goto error; + } + buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1); + if (!buf) { + goto error; + } + len = 0; + } + + switch (template->type) { + case ASN_SEQUENCE: + { + int seq_len = i2dProcessMembers(src, NULL, template->members, + template->mcount); + if (!seq_len) { + goto error; + } + len += SetSequence(seq_len, bufLenOrNull(buf, len)); + if (buf && + i2dProcessMembers(src, bufLenOrNull(buf, len), template->members, + template->mcount) != seq_len) { + WOLFSSL_MSG("Inconsistent sequence length"); + goto error; + } + len += seq_len; + break; + } + default: + WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_i2d"); + goto error; + } + + if (dest && !*dest) { + *dest = buf; + } + else if (dest && *dest && buf) { + /* *dest length is not checked because the user is responsible + * for providing a long enough buffer */ + XMEMCPY(*dest, buf, len); + } + + WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", len); + return len; +error: + if (buf) { + XFREE(buf, NULL, DYNAMIC_TYPE_ASN1); + } + WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", WOLFSSL_FAILURE); + return WOLFSSL_FAILURE; } - +#endif /* OPENSSL_ALL */ #ifndef NO_DH static void InitwolfSSL_DH(WOLFSSL_DH* dh) { if (dh) { - dh->p = NULL; - dh->g = NULL; - dh->pub_key = NULL; - dh->priv_key = NULL; - dh->internal = NULL; - dh->inSet = 0; - dh->exSet = 0; + XMEMSET(dh, 0, sizeof(WOLFSSL_DH)); } } @@ -11296,7 +28440,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; @@ -11317,24 +28466,36 @@ void wolfSSL_DH_free(WOLFSSL_DH* dh) wolfSSL_BN_free(dh->pub_key); wolfSSL_BN_free(dh->g); wolfSSL_BN_free(dh->p); + wolfSSL_BN_free(dh->q); InitwolfSSL_DH(dh); /* set back to NULLs for safety */ XFREE(dh, NULL, DYNAMIC_TYPE_DH); } } - -static int SetDhInternal(WOLFSSL_DH* dh) +int SetDhInternal(WOLFSSL_DH* dh) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FATAL_ERROR; int pSz = 1024; int gSz = 1024; +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + int privSz = 256; /* Up to 2048-bit */ + int pubSz = 256; +#endif #ifdef WOLFSSL_SMALL_STACK unsigned char* p = NULL; unsigned char* g = NULL; + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + unsigned char* priv_key = NULL; + unsigned char* pub_key = NULL; + #endif #else unsigned char p[1024]; unsigned char g[1024]; + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + unsigned char priv_key[256]; + unsigned char pub_key[256]; + #endif #endif WOLFSSL_ENTER("SetDhInternal"); @@ -11345,17 +28506,46 @@ static int SetDhInternal(WOLFSSL_DH* dh) WOLFSSL_MSG("Bad p internal size"); else if (wolfSSL_BN_bn2bin(dh->g, NULL) > gSz) WOLFSSL_MSG("Bad g internal size"); + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + else if (wolfSSL_BN_bn2bin(dh->priv_key, NULL) > privSz) + WOLFSSL_MSG("Bad private key internal size"); + else if (wolfSSL_BN_bn2bin(dh->pub_key, NULL) > privSz) + WOLFSSL_MSG("Bad public key internal size"); + #endif 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 defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + priv_key = (unsigned char*)XMALLOC(privSz,NULL,DYNAMIC_TYPE_PRIVATE_KEY); + pub_key = (unsigned char*)XMALLOC(pubSz,NULL,DYNAMIC_TYPE_PUBLIC_KEY); + #endif 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 + #endif /* WOLFSSL_SMALL_STACK */ + + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv_key); + pubSz = wolfSSL_BN_bn2bin(dh->pub_key, pub_key); + if (privSz <= 0) { + WOLFSSL_MSG("No private key size."); + } + if (pubSz <= 0) { + WOLFSSL_MSG("No public key size."); + } + if (privSz > 0 || pubSz > 0) { + ret = wc_DhSetFullKeys((DhKey*)dh->internal,priv_key,privSz, + pub_key,pubSz); + if (ret == WOLFSSL_FAILURE) { + WOLFSSL_MSG("Failed setting private or public key."); + } + } + #endif /* WOLFSSL_QT || OPENSSL_ALL */ pSz = wolfSSL_BN_bn2bin(dh->p, p); gSz = wolfSSL_BN_bn2bin(dh->g, g); @@ -11366,12 +28556,16 @@ static int SetDhInternal(WOLFSSL_DH* dh) WOLFSSL_MSG("Bad DH SetKey"); else { dh->inSet = 1; - ret = 0; + 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); + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + XFREE(priv_key, NULL, DYNAMIC_TYPE_PRIVATE_KEY); + XFREE(pub_key, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + #endif #endif } @@ -11379,54 +28573,478 @@ static int SetDhInternal(WOLFSSL_DH* dh) return ret; } +#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) +/* Set the members of DhKey into WOLFSSL_DH + * DhKey was populated from wc_DhKeyDecode + */ +int SetDhExternal(WOLFSSL_DH *dh) +{ + DhKey *key; + WOLFSSL_MSG("Entering SetDhExternal"); + if (dh == NULL || dh->internal == NULL) { + WOLFSSL_MSG("dh key NULL error"); + } + + key = (DhKey*)dh->internal; + + if (SetIndividualExternal(&dh->p, &key->p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dh param p error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&dh->g, &key->g) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dh param g error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&dh->priv_key, &key->priv) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("No DH Private Key"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&dh->pub_key, &key->pub) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("No DH Public Key"); + return WOLFSSL_FATAL_ERROR; + } + + dh->exSet = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ + +/* return code compliant with OpenSSL : + * DH prime size in bytes if success, 0 if error + */ int wolfSSL_DH_size(WOLFSSL_DH* dh) { WOLFSSL_MSG("wolfSSL_DH_size"); if (dh == NULL) - return 0; + return WOLFSSL_FATAL_ERROR; return wolfSSL_BN_num_bytes(dh->p); } +/* This sets a big number with the 768-bit prime from RFC 2409. + * + * bn if not NULL then the big number structure is used. If NULL then a new + * big number structure is created. + * + * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure. + */ +WOLFSSL_BIGNUM* wolfSSL_DH_768_prime(WOLFSSL_BIGNUM* bn) +{ + const char prm[] = { + "FFFFFFFFFFFFFFFFC90FDAA22168C234" + "C4C6628B80DC1CD129024E088A67CC74" + "020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F1437" + "4FE1356D6D51C245E485B576625E7EC6" + "F44C42E9A63A3620FFFFFFFFFFFFFFFF" + }; -/* return SSL_SUCCESS on ok, else 0 */ + WOLFSSL_ENTER("wolfSSL_DH_768_prime"); + + if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) { + WOLFSSL_MSG("Error converting DH 768 prime to big number"); + return NULL; + } + + return bn; +} + +/* This sets a big number with the 1024-bit prime from RFC 2409. + * + * bn if not NULL then the big number structure is used. If NULL then a new + * big number structure is created. + * + * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure. + */ +WOLFSSL_BIGNUM* wolfSSL_DH_1024_prime(WOLFSSL_BIGNUM* bn) +{ + const char prm[] = { + "FFFFFFFFFFFFFFFFC90FDAA22168C234" + "C4C6628B80DC1CD129024E088A67CC74" + "020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F1437" + "4FE1356D6D51C245E485B576625E7EC6" + "F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE6" + "49286651ECE65381FFFFFFFFFFFFFFFF" + }; + + WOLFSSL_ENTER("wolfSSL_DH_1024_prime"); + + if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) { + WOLFSSL_MSG("Error converting DH 1024 prime to big number"); + return NULL; + } + + return bn; +} + +/* This sets a big number with the 1536-bit prime from RFC 3526. + * + * bn if not NULL then the big number structure is used. If NULL then a new + * big number structure is created. + * + * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure. + */ +WOLFSSL_BIGNUM* wolfSSL_DH_1536_prime(WOLFSSL_BIGNUM* bn) +{ + const char prm[] = { + "FFFFFFFFFFFFFFFFC90FDAA22168C234" + "C4C6628B80DC1CD129024E088A67CC74" + "020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F1437" + "4FE1356D6D51C245E485B576625E7EC6" + "F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE6" + "49286651ECE45B3DC2007CB8A163BF05" + "98DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB" + "9ED529077096966D670C354E4ABC9804" + "F1746C08CA237327FFFFFFFFFFFFFFFF" + }; + + WOLFSSL_ENTER("wolfSSL_DH_1536_prime"); + + if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) { + WOLFSSL_MSG("Error converting DH 1536 prime to big number"); + return NULL; + } + + return bn; +} + +/* This sets a big number with the 2048-bit prime from RFC 3526. + * + * bn if not NULL then the big number structure is used. If NULL then a new + * big number structure is created. + * + * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure. + */ +WOLFSSL_BIGNUM* wolfSSL_DH_2048_prime(WOLFSSL_BIGNUM* bn) +{ + const char prm[] = { + "FFFFFFFFFFFFFFFFC90FDAA22168C234" + "C4C6628B80DC1CD129024E088A67CC74" + "020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F1437" + "4FE1356D6D51C245E485B576625E7EC6" + "F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE6" + "49286651ECE45B3DC2007CB8A163BF05" + "98DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB" + "9ED529077096966D670C354E4ABC9804" + "F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28F" + "B5C55DF06F4C52C9DE2BCBF695581718" + "3995497CEA956AE515D2261898FA0510" + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" + }; + + WOLFSSL_ENTER("wolfSSL_DH_2048_prime"); + + if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) { + WOLFSSL_MSG("Error converting DH 2048 prime to big number"); + return NULL; + } + + return bn; +} + +/* This sets a big number with the 3072-bit prime from RFC 3526. + * + * bn if not NULL then the big number structure is used. If NULL then a new + * big number structure is created. + * + * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure. + */ +WOLFSSL_BIGNUM* wolfSSL_DH_3072_prime(WOLFSSL_BIGNUM* bn) +{ + const char prm[] = { + "FFFFFFFFFFFFFFFFC90FDAA22168C234" + "C4C6628B80DC1CD129024E088A67CC74" + "020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F1437" + "4FE1356D6D51C245E485B576625E7EC6" + "F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE6" + "49286651ECE45B3DC2007CB8A163BF05" + "98DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB" + "9ED529077096966D670C354E4ABC9804" + "F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28F" + "B5C55DF06F4C52C9DE2BCBF695581718" + "3995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33" + "A85521ABDF1CBA64ECFB850458DBEF0A" + "8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619D" + "CEE3D2261AD2EE6BF12FFA06D98A0864" + "D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E2" + "08E24FA074E5AB3143DB5BFCE0FD108E" + "4B82D120A93AD2CAFFFFFFFFFFFFFFFF" + }; + + WOLFSSL_ENTER("wolfSSL_DH_3072_prime"); + + if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) { + WOLFSSL_MSG("Error converting DH 3072 prime to big number"); + return NULL; + } + + return bn; +} + +/* This sets a big number with the 4096-bit prime from RFC 3526. + * + * bn if not NULL then the big number structure is used. If NULL then a new + * big number structure is created. + * + * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure. + */ +WOLFSSL_BIGNUM* wolfSSL_DH_4096_prime(WOLFSSL_BIGNUM* bn) +{ + const char prm[] = { + "FFFFFFFFFFFFFFFFC90FDAA22168C234" + "C4C6628B80DC1CD129024E088A67CC74" + "020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F1437" + "4FE1356D6D51C245E485B576625E7EC6" + "F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE6" + "49286651ECE45B3DC2007CB8A163BF05" + "98DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB" + "9ED529077096966D670C354E4ABC9804" + "F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28F" + "B5C55DF06F4C52C9DE2BCBF695581718" + "3995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33" + "A85521ABDF1CBA64ECFB850458DBEF0A" + "8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619D" + "CEE3D2261AD2EE6BF12FFA06D98A0864" + "D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E2" + "08E24FA074E5AB3143DB5BFCE0FD108E" + "4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C" + "1A946834B6150BDA2583E9CA2AD44CE8" + "DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2" + "233BA186515BE7ED1F612970CEE2D7AF" + "B81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F" + "4DF435C934063199FFFFFFFFFFFFFFFF" + }; + + WOLFSSL_ENTER("wolfSSL_DH_4096_prime"); + + if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) { + WOLFSSL_MSG("Error converting DH 4096 prime to big number"); + return NULL; + } + + return bn; +} + +/* This sets a big number with the 6144-bit prime from RFC 3526. + * + * bn if not NULL then the big number structure is used. If NULL then a new + * big number structure is created. + * + * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure. + */ +WOLFSSL_BIGNUM* wolfSSL_DH_6144_prime(WOLFSSL_BIGNUM* bn) +{ + const char prm[] = { + "FFFFFFFFFFFFFFFFC90FDAA22168C234" + "C4C6628B80DC1CD129024E088A67CC74" + "020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F1437" + "4FE1356D6D51C245E485B576625E7EC6" + "F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE6" + "49286651ECE45B3DC2007CB8A163BF05" + "98DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB" + "9ED529077096966D670C354E4ABC9804" + "F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28F" + "B5C55DF06F4C52C9DE2BCBF695581718" + "3995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33" + "A85521ABDF1CBA64ECFB850458DBEF0A" + "8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619D" + "CEE3D2261AD2EE6BF12FFA06D98A0864" + "D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E2" + "08E24FA074E5AB3143DB5BFCE0FD108E" + "4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C" + "1A946834B6150BDA2583E9CA2AD44CE8" + "DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2" + "233BA186515BE7ED1F612970CEE2D7AF" + "B81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F" + "4DF435C93402849236C3FAB4D27C7026" + "C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AE" + "B06A53ED9027D831179727B0865A8918" + "DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF42" + "6FB8F401378CD2BF5983CA01C64B92EC" + "F032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E" + "59E7C97FBEC7E8F323A97A7E36CC88BE" + "0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0" + "A79715EEF29BE32806A1D58BB7C5DA76" + "F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468" + "043E8F663F4860EE12BF2D5B0B7474D6" + "E694F91E6DCC4024FFFFFFFFFFFFFFFF" + }; + + WOLFSSL_ENTER("wolfSSL_DH_6144_prime"); + + if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) { + WOLFSSL_MSG("Error converting DH 6144 prime to big number"); + return NULL; + } + + return bn; +} + + +/* This sets a big number with the 8192-bit prime from RFC 3526. + * + * bn if not NULL then the big number structure is used. If NULL then a new + * big number structure is created. + * + * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure. + */ +WOLFSSL_BIGNUM* wolfSSL_DH_8192_prime(WOLFSSL_BIGNUM* bn) +{ + const char prm[] = { + "FFFFFFFFFFFFFFFFC90FDAA22168C234" + "C4C6628B80DC1CD129024E088A67CC74" + "020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F1437" + "4FE1356D6D51C245E485B576625E7EC6" + "F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE6" + "49286651ECE45B3DC2007CB8A163BF05" + "98DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB" + "9ED529077096966D670C354E4ABC9804" + "F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28F" + "B5C55DF06F4C52C9DE2BCBF695581718" + "3995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33" + "A85521ABDF1CBA64ECFB850458DBEF0A" + "8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619D" + "CEE3D2261AD2EE6BF12FFA06D98A0864" + "D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E2" + "08E24FA074E5AB3143DB5BFCE0FD108E" + "4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C" + "1A946834B6150BDA2583E9CA2AD44CE8" + "DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2" + "233BA186515BE7ED1F612970CEE2D7AF" + "B81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F" + "4DF435C93402849236C3FAB4D27C7026" + "C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AE" + "B06A53ED9027D831179727B0865A8918" + "DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF42" + "6FB8F401378CD2BF5983CA01C64B92EC" + "F032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E" + "59E7C97FBEC7E8F323A97A7E36CC88BE" + "0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0" + "A79715EEF29BE32806A1D58BB7C5DA76" + "F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468" + "043E8F663F4860EE12BF2D5B0B7474D6" + "E694F91E6DBE115974A3926F12FEE5E4" + "38777CB6A932DF8CD8BEC4D073B931BA" + "3BC832B68D9DD300741FA7BF8AFC47ED" + "2576F6936BA424663AAB639C5AE4F568" + "3423B4742BF1C978238F16CBE39D652D" + "E3FDB8BEFC848AD922222E04A4037C07" + "13EB57A81A23F0C73473FC646CEA306B" + "4BCBC8862F8385DDFA9D4B7FA2C087E8" + "79683303ED5BDD3A062B3CF5B3A278A6" + "6D2A13F83F44F82DDF310EE074AB6A36" + "4597E899A0255DC164F31CC50846851D" + "F9AB48195DED7EA1B1D510BD7EE74D73" + "FAF36BC31ECFA268359046F4EB879F92" + "4009438B481C6CD7889A002ED5EE382B" + "C9190DA6FC026E479558E4475677E9AA" + "9E3050E2765694DFC81F56E880B96E71" + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF" + }; + + WOLFSSL_ENTER("wolfSSL_DH_8192_prime"); + + if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) { + WOLFSSL_MSG("Error converting DH 8192 prime to big number"); + return NULL; + } + + return bn; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) { - int ret = 0; - word32 pubSz = 768; - word32 privSz = 768; + int ret = WOLFSSL_FAILURE; + word32 pubSz = 0; + word32 privSz = 0; int initTmpRng = 0; - RNG* rng = NULL; + WC_RNG* rng = NULL; #ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG; +#else + WC_RNG tmpRNG[1]; +#endif unsigned char* pub = NULL; unsigned char* priv = NULL; - RNG* tmpRNG = NULL; -#else - unsigned char pub [768]; - unsigned char priv[768]; - RNG tmpRNG[1]; -#endif WOLFSSL_MSG("wolfSSL_DH_generate_key"); #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (RNG*)XMALLOC(sizeof(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); - - 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); + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) { + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); return ret; } #endif if (dh == NULL || dh->p == NULL || dh->g == NULL) WOLFSSL_MSG("Bad function arguments"); - else if (dh->inSet == 0 && SetDhInternal(dh) < 0) + else if (dh->inSet == 0 && SetDhInternal(dh) != WOLFSSL_SUCCESS) WOLFSSL_MSG("Bad DH set internal"); else if (wc_InitRng(tmpRNG) == 0) { rng = tmpRNG; @@ -11441,13 +29059,24 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) } if (rng) { - if (wc_DhGenerateKeyPair((DhKey*)dh->internal, rng, priv, &privSz, + pubSz = wolfSSL_BN_num_bytes(dh->p); + if (dh->length) { + privSz = dh->length/8; /* to bytes */ + } else { + privSz = pubSz; + } + pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY); + if (pub == NULL || priv == NULL) { + WOLFSSL_MSG("Unable to malloc memory"); + } + else if (wc_DhGenerateKeyPair((DhKey*)dh->internal, rng, priv, &privSz, pub, &pubSz) < 0) WOLFSSL_MSG("Bad wc_DhGenerateKeyPair"); - else { + else { if (dh->pub_key) wolfSSL_BN_free(dh->pub_key); - + dh->pub_key = wolfSSL_BN_new(); if (dh->pub_key == NULL) { WOLFSSL_MSG("Bad DH new pub"); @@ -11467,7 +29096,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; } } } @@ -11476,25 +29105,27 @@ 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); #endif + XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY); return ret; } -/* return key size on ok, 0 otherwise */ +/* return code compliant with OpenSSL : + * size of shared secret if success, -1 if error + */ int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub, WOLFSSL_DH* dh) { - int ret = 0; + int ret = WOLFSSL_FATAL_ERROR; word32 keySz = 0; - word32 pubSz = 1024; - word32 privSz = 1024; + int pubSz = 1024; + int privSz = 1024; #ifdef WOLFSSL_SMALL_STACK - unsigned char* pub = NULL; + unsigned char* pub; unsigned char* priv = NULL; #else unsigned char pub [1024]; @@ -11504,14 +29135,14 @@ 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); - return 0; + XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + return ret; } #endif @@ -11526,23 +29157,78 @@ int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub, else { privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv); pubSz = wolfSSL_BN_bn2bin(otherPub, pub); - + if (dh->inSet == 0 && SetDhInternal(dh) != SSL_SUCCESS){ + WOLFSSL_MSG("Bad DH set internal"); + } if (privSz <= 0 || pubSz <= 0) WOLFSSL_MSG("Bad BN2bin set"); - else if (wc_DhAgree((DhKey*)dh->internal, key, &keySz, priv, privSz, pub, - pubSz) < 0) + else if (wc_DhAgree((DhKey*)dh->internal, key, &keySz, + priv, privSz, pub, pubSz) < 0) WOLFSSL_MSG("wc_DhAgree failed"); else ret = (int)keySz; } #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; } + + +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +/* ownership of p,q,and g get taken over by "dh" on success and should be free'd + * with a call to wolfSSL_DH_free -- not individually. + * + * returns WOLFSSL_SUCCESS on success + */ +int wolfSSL_DH_set0_pqg(WOLFSSL_DH *dh, WOLFSSL_BIGNUM *p, + WOLFSSL_BIGNUM *q, WOLFSSL_BIGNUM *g) +{ + int ret; + WOLFSSL_ENTER("wolfSSL_DH_set0_pqg"); + + /* q can be NULL */ + if (dh == NULL || p == NULL || g == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + /* free existing internal DH structure and recreate with new p / g */ + if (dh->inSet) { + ret = wc_FreeDhKey((DhKey*)dh->internal); + if (ret != 0) { + WOLFSSL_MSG("Unable to free internal DH key"); + return WOLFSSL_FAILURE; + } + } + + wolfSSL_BN_free(dh->p); + wolfSSL_BN_free(dh->q); + wolfSSL_BN_free(dh->g); + wolfSSL_BN_free(dh->pub_key); + wolfSSL_BN_free(dh->priv_key); + + dh->p = p; + dh->q = q; + dh->g = g; + + ret = SetDhInternal(dh); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Unable to set internal DH key"); + dh->p = NULL; + dh->q = NULL; + dh->g = NULL; + dh->inSet = 0; + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +#endif /* v1.1.0 or later */ + #endif /* NO_DH */ @@ -11584,7 +29270,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; @@ -11609,290 +29300,226 @@ void wolfSSL_DSA_free(WOLFSSL_DSA* dsa) InitwolfSSL_DSA(dsa); /* set back to NULLs for safety */ XFREE(dsa, NULL, DYNAMIC_TYPE_DSA); + + /* dsa = NULL, don't try to access or double free it */ } } - -int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa) -{ - (void)dsa; - - WOLFSSL_MSG("wolfSSL_DSA_generate_key"); - - return 0; /* key gen not needed by server */ -} - - -int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits, - unsigned char* seed, int seedLen, int* counterRet, - unsigned long* hRet, void* cb) -{ - (void)dsa; - (void)bits; - (void)seed; - (void)seedLen; - (void)counterRet; - (void)hRet; - (void)cb; - - WOLFSSL_MSG("wolfSSL_DSA_generate_parameters_ex"); - - return 0; /* key gen not needed by server */ -} #endif /* NO_DSA */ +#endif /* OPENSSL_EXTRA */ -#ifndef NO_RSA -static void InitwolfSSL_Rsa(WOLFSSL_RSA* rsa) -{ - if (rsa) { - rsa->n = NULL; - rsa->e = NULL; - rsa->d = NULL; - rsa->p = NULL; - rsa->q = NULL; - rsa->dmp1 = NULL; - rsa->dmq1 = NULL; - rsa->iqmp = NULL; - rsa->internal = NULL; - rsa->inSet = 0; - rsa->exSet = 0; - } -} - - -WOLFSSL_RSA* wolfSSL_RSA_new(void) -{ - WOLFSSL_RSA* external; - RsaKey* key; - - WOLFSSL_MSG("wolfSSL_RSA_new"); - - key = (RsaKey*) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); - if (key == NULL) { - WOLFSSL_MSG("wolfSSL_RSA_new malloc RsaKey failure"); - return NULL; - } - - external = (WOLFSSL_RSA*) XMALLOC(sizeof(WOLFSSL_RSA), NULL, - DYNAMIC_TYPE_RSA); - if (external == NULL) { - WOLFSSL_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure"); - XFREE(key, NULL, DYNAMIC_TYPE_RSA); - return NULL; - } - - InitwolfSSL_Rsa(external); - if (wc_InitRsaKey(key, NULL) != 0) { - WOLFSSL_MSG("InitRsaKey WOLFSSL_RSA failure"); - XFREE(external, NULL, DYNAMIC_TYPE_RSA); - XFREE(key, NULL, DYNAMIC_TYPE_RSA); - return NULL; - } - external->internal = key; - - return external; -} - - -void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) -{ - WOLFSSL_MSG("wolfSSL_RSA_free"); - - if (rsa) { - if (rsa->internal) { - wc_FreeRsaKey((RsaKey*)rsa->internal); - XFREE(rsa->internal, NULL, DYNAMIC_TYPE_RSA); - rsa->internal = NULL; - } - wolfSSL_BN_free(rsa->iqmp); - wolfSSL_BN_free(rsa->dmq1); - wolfSSL_BN_free(rsa->dmp1); - wolfSSL_BN_free(rsa->q); - wolfSSL_BN_free(rsa->p); - wolfSSL_BN_free(rsa->d); - wolfSSL_BN_free(rsa->e); - wolfSSL_BN_free(rsa->n); - InitwolfSSL_Rsa(rsa); /* set back to NULLs for safety */ - - XFREE(rsa, NULL, DYNAMIC_TYPE_RSA); - } -} -#endif /* NO_RSA */ - - -#if !defined(NO_RSA) || !defined(NO_DSA) -static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) -{ - WOLFSSL_MSG("Entering SetIndividualExternal"); - - if (mpi == NULL) { - WOLFSSL_MSG("mpi NULL error"); - return SSL_FATAL_ERROR; - } - - if (*bn == NULL) { - *bn = wolfSSL_BN_new(); - if (*bn == NULL) { - WOLFSSL_MSG("SetIndividualExternal alloc failed"); - return SSL_FATAL_ERROR; - } - } - - if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) { - WOLFSSL_MSG("mp_copy error"); - return SSL_FATAL_ERROR; - } - - return 0; -} -#endif /* !NO_RSA && !NO_DSA */ - +#ifdef OPENSSL_EXTRA #ifndef NO_DSA -static int SetDsaExternal(WOLFSSL_DSA* dsa) +/* wolfSSL -> OpenSSL */ +int SetDsaExternal(WOLFSSL_DSA* dsa) { DsaKey* key; WOLFSSL_MSG("Entering SetDsaExternal"); 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) < 0) { + 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) < 0) { + 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) < 0) { + 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) < 0) { + 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) < 0) { + 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 0; + return WOLFSSL_SUCCESS; +} + +/* Openssl -> WolfSSL */ +int SetDsaInternal(WOLFSSL_DSA* dsa) +{ + DsaKey* key; + WOLFSSL_MSG("Entering SetDsaInternal"); + + if (dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("dsa key NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + key = (DsaKey*)dsa->internal; + + if (dsa->p != NULL && + SetIndividualInternal(dsa->p, &key->p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (dsa->q != NULL && + SetIndividualInternal(dsa->q, &key->q) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa q key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (dsa->g != NULL && + SetIndividualInternal(dsa->g, &key->g) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa g key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (dsa->pub_key != NULL) { + if (SetIndividualInternal(dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa pub_key error"); + return WOLFSSL_FATAL_ERROR; + } + + /* public key */ + key->type = DSA_PUBLIC; + } + + if (dsa->priv_key != NULL) { + if (SetIndividualInternal(dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa priv_key error"); + return WOLFSSL_FATAL_ERROR; + } + + /* private key */ + key->type = DSA_PRIVATE; + } + + dsa->inSet = 1; + + return WOLFSSL_SUCCESS; } #endif /* NO_DSA */ +#endif /* OPENSSL_EXTRA */ -#ifndef NO_RSA -static int SetRsaExternal(WOLFSSL_RSA* rsa) +#ifdef OPENSSL_EXTRA +#if !defined(NO_RSA) +/* Generates a RSA key of length len + * + * len length of RSA key i.e. 2048 + * e e to use when generating RSA key + * f callback function for generation details + * data user callback argument + * + * Note: Because of wc_MakeRsaKey an RSA key size generated can be slightly + * rounded down. For example generating a key of size 2999 with e = + * 65537 will make a key of size 374 instead of 375. + * Returns a new RSA key on success and NULL on failure + */ +WOLFSSL_RSA* wolfSSL_RSA_generate_key(int len, unsigned long e, + void(*f)(int, int, void*), void* data) { - RsaKey* key; - WOLFSSL_MSG("Entering SetRsaExternal"); + WOLFSSL_RSA* rsa = NULL; + WOLFSSL_BIGNUM* bn = NULL; - if (rsa == NULL || rsa->internal == NULL) { - WOLFSSL_MSG("rsa key NULL error"); - return SSL_FATAL_ERROR; + WOLFSSL_ENTER("wolfSSL_RSA_generate_key"); + + (void)f; + (void)data; + + if (len < 0) { + WOLFSSL_MSG("Bad argument: length was less than 0"); + return NULL; } - key = (RsaKey*)rsa->internal; - - if (SetIndividualExternal(&rsa->n, &key->n) < 0) { - WOLFSSL_MSG("rsa n key error"); - return SSL_FATAL_ERROR; + bn = wolfSSL_BN_new(); + if (bn == NULL) { + WOLFSSL_MSG("Error creating big number"); + return NULL; } - if (SetIndividualExternal(&rsa->e, &key->e) < 0) { - WOLFSSL_MSG("rsa e key error"); - return SSL_FATAL_ERROR; + if (wolfSSL_BN_set_word(bn, (WOLFSSL_BN_ULONG)e) != SSL_SUCCESS) { + WOLFSSL_MSG("Error using e value"); + wolfSSL_BN_free(bn); + return NULL; } - if (SetIndividualExternal(&rsa->d, &key->d) < 0) { - WOLFSSL_MSG("rsa d key error"); - return SSL_FATAL_ERROR; + rsa = wolfSSL_RSA_new(); + if (rsa == NULL) { + WOLFSSL_MSG("memory error"); } - - if (SetIndividualExternal(&rsa->p, &key->p) < 0) { - WOLFSSL_MSG("rsa p key error"); - return SSL_FATAL_ERROR; + else { + if (wolfSSL_RSA_generate_key_ex(rsa, len, bn, NULL) != SSL_SUCCESS){ + wolfSSL_RSA_free(rsa); + rsa = NULL; + } } + wolfSSL_BN_free(bn); - if (SetIndividualExternal(&rsa->q, &key->q) < 0) { - WOLFSSL_MSG("rsa q key error"); - return SSL_FATAL_ERROR; - } - - if (SetIndividualExternal(&rsa->dmp1, &key->dP) < 0) { - WOLFSSL_MSG("rsa dP key error"); - return SSL_FATAL_ERROR; - } - - if (SetIndividualExternal(&rsa->dmq1, &key->dQ) < 0) { - WOLFSSL_MSG("rsa dQ key error"); - return SSL_FATAL_ERROR; - } - - if (SetIndividualExternal(&rsa->iqmp, &key->u) < 0) { - WOLFSSL_MSG("rsa u key error"); - return SSL_FATAL_ERROR; - } - - rsa->exSet = 1; - - return 0; + return rsa; } -/* SSL_SUCCESS on ok */ +/* return compliant with OpenSSL + * 1 if success, 0 if error + */ int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn, - void* cb) + void* cb) { - int ret = SSL_FATAL_ERROR; + int ret = WOLFSSL_FAILURE; - WOLFSSL_MSG("wolfSSL_RSA_generate_key_ex"); - - (void)rsa; - (void)bits; (void)cb; (void)bn; + (void)bits; + + WOLFSSL_ENTER("wolfSSL_RSA_generate_key_ex"); + + if (rsa == NULL || rsa->internal == NULL) { + /* bit size checked during make key call */ + WOLFSSL_MSG("bad arguments"); + return WOLFSSL_FAILURE; + } #ifdef WOLFSSL_KEY_GEN { #ifdef WOLFSSL_SMALL_STACK - RNG* rng = NULL; + WC_RNG* rng; #else - RNG rng[1]; + WC_RNG rng[1]; #endif #ifdef WOLFSSL_SMALL_STACK - rng = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (rng == NULL) - return SSL_FATAL_ERROR; + return WOLFSSL_FAILURE; #endif if (wc_InitRng(rng) < 0) WOLFSSL_MSG("RNG init failed"); - else if (wc_MakeRsaKey((RsaKey*)rsa->internal, bits, 65537, rng) < 0) + else if (wc_MakeRsaKey((RsaKey*)rsa->internal, bits, + wolfSSL_BN_get_word(bn), rng) != MP_OKAY) WOLFSSL_MSG("wc_MakeRsaKey failed"); - else if (SetRsaExternal(rsa) < 0) + 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 @@ -11900,89 +29527,47 @@ int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn, #endif return ret; } - - -/* SSL_SUCCESS on ok */ -int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn) -{ - (void)rsa; - (void)bn; - - WOLFSSL_MSG("wolfSSL_RSA_blinding_on"); - - return SSL_SUCCESS; /* on by default */ -} - - -int wolfSSL_RSA_public_encrypt(int len, unsigned char* fr, - unsigned char* to, WOLFSSL_RSA* rsa, int padding) -{ - (void)len; - (void)fr; - (void)to; - (void)rsa; - (void)padding; - - WOLFSSL_MSG("wolfSSL_RSA_public_encrypt"); - - return SSL_FATAL_ERROR; -} - - -int wolfSSL_RSA_private_decrypt(int len, unsigned char* fr, - unsigned char* to, WOLFSSL_RSA* rsa, int padding) -{ - (void)len; - (void)fr; - (void)to; - (void)rsa; - (void)padding; - - WOLFSSL_MSG("wolfSSL_RSA_private_decrypt"); - - return SSL_FATAL_ERROR; -} - - -int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa) -{ - WOLFSSL_MSG("wolfSSL_RSA_size"); - - if (rsa == NULL) - return 0; - - return wolfSSL_BN_num_bytes(rsa->n); -} #endif /* NO_RSA */ - #ifndef NO_DSA -/* return SSL_SUCCESS on success, < 0 otherwise */ -int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, - WOLFSSL_DSA* dsa) +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa) { - int ret = SSL_FATAL_ERROR; - int initTmpRng = 0; - RNG* rng = NULL; + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_DSA_generate_key"); + + if (dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + + if (dsa->inSet == 0) { + WOLFSSL_MSG("No DSA internal set, do it"); + + if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return ret; + } + } + +#ifdef WOLFSSL_KEY_GEN + { + int initTmpRng = 0; + WC_RNG *rng = NULL; #ifdef WOLFSSL_SMALL_STACK - RNG* tmpRNG = NULL; + WC_RNG *tmpRNG; #else - RNG tmpRNG[1]; + WC_RNG tmpRNG[1]; #endif - WOLFSSL_MSG("wolfSSL_DSA_do_sign"); - - if (d == NULL || sigRet == NULL || dsa == NULL) - WOLFSSL_MSG("Bad function arguments"); - else if (dsa->inSet == 0) - WOLFSSL_MSG("No DSA internal set"); - else { - #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (tmpRNG == NULL) - return SSL_FATAL_ERROR; - #endif - + return WOLFSSL_FATAL_ERROR; +#endif if (wc_InitRng(tmpRNG) == 0) { rng = tmpRNG; initTmpRng = 1; @@ -11996,97 +29581,495 @@ int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, } if (rng) { - if (DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0) - WOLFSSL_MSG("DsaSign failed"); + if (wc_MakeDsaKey(rng, (DsaKey*)dsa->internal) != MP_OKAY) + WOLFSSL_MSG("wc_MakeDsaKey failed"); + 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); - #endif - } +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + } +#else /* WOLFSSL_KEY_GEN */ + WOLFSSL_MSG("No Key Gen built in"); +#endif return ret; } -#endif /* NO_DSA */ -#ifndef NO_RSA -/* return SSL_SUCCES on ok, 0 otherwise */ -int wolfSSL_RSA_sign(int type, const unsigned char* m, - unsigned int mLen, unsigned char* sigRet, - unsigned int* sigLen, WOLFSSL_RSA* rsa) +/* Returns a pointer to a new WOLFSSL_DSA structure on success and NULL on fail + */ +WOLFSSL_DSA* wolfSSL_DSA_generate_parameters(int bits, unsigned char* seed, + int seedLen, int* counterRet, unsigned long* hRet, + WOLFSSL_BN_CB cb, void* CBArg) { - word32 outLen; - word32 signSz; - int initTmpRng = 0; - RNG* rng = NULL; - int ret = 0; + WOLFSSL_DSA* dsa; + + WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters()"); + + (void)cb; + (void)CBArg; + dsa = wolfSSL_DSA_new(); + if (dsa == NULL) { + return NULL; + } + + if (wolfSSL_DSA_generate_parameters_ex(dsa, bits, seed, seedLen, + counterRet, hRet, NULL) != SSL_SUCCESS) { + wolfSSL_DSA_free(dsa); + return NULL; + } + + return dsa; +} + + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits, + unsigned char* seed, int seedLen, + int* counterRet, + unsigned long* hRet, void* cb) +{ + int ret = WOLFSSL_FAILURE; + + (void)bits; + (void)seed; + (void)seedLen; + (void)counterRet; + (void)hRet; + (void)cb; + + WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters_ex"); + + if (dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + +#ifdef WOLFSSL_KEY_GEN + { + int initTmpRng = 0; + WC_RNG *rng = NULL; #ifdef WOLFSSL_SMALL_STACK - RNG* tmpRNG = NULL; - byte* encodedSig = NULL; + WC_RNG *tmpRNG; #else - RNG tmpRNG[1]; - byte encodedSig[MAX_ENCODED_SIG_SZ]; + WC_RNG tmpRNG[1]; #endif - WOLFSSL_MSG("wolfSSL_RSA_sign"); - - if (m == NULL || sigRet == NULL || sigLen == NULL || rsa == NULL) - WOLFSSL_MSG("Bad function arguments"); - else if (rsa->inSet == 0) - WOLFSSL_MSG("No RSA internal set"); - else if (type != NID_md5 && type != NID_sha1) - WOLFSSL_MSG("Bad md type"); - else { - outLen = (word32)wolfSSL_BN_num_bytes(rsa->n); - - #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + 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); - if (encodedSig == NULL) { - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return 0; - } - #endif - - if (outLen == 0) - WOLFSSL_MSG("Bad RSA size"); - else if (wc_InitRng(tmpRNG) == 0) { + 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; } + + if (rng) { + if (wc_MakeDsaParameters(rng, bits, + (DsaKey*)dsa->internal) != MP_OKAY) + WOLFSSL_MSG("wc_MakeDsaParameters failed"); + else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) + WOLFSSL_MSG("SetDsaExternal failed"); + else + ret = WOLFSSL_SUCCESS; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + } +#else /* WOLFSSL_KEY_GEN */ + WOLFSSL_MSG("No Key Gen built in"); +#endif + + return ret; +} + +WOLFSSL_DSA_SIG* wolfSSL_DSA_SIG_new(void) +{ + WOLFSSL_DSA_SIG* sig; + WOLFSSL_ENTER("wolfSSL_DSA_SIG_new"); + sig = (WOLFSSL_DSA_SIG*)XMALLOC(sizeof(WOLFSSL_DSA_SIG), NULL, DYNAMIC_TYPE_OPENSSL); + if (sig) + XMEMSET(sig, 0, sizeof(WOLFSSL_DSA_SIG)); + return sig; +} + +void wolfSSL_DSA_SIG_free(WOLFSSL_DSA_SIG *sig) +{ + WOLFSSL_ENTER("wolfSSL_DSA_SIG_free"); + if (sig) { + if (sig->r) { + wolfSSL_BN_free(sig->r); + } + if (sig->s) { + wolfSSL_BN_free(sig->s); + } + XFREE(sig, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +/* return WOLFSSL_SUCCESS on success, < 0 otherwise */ +int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, + WOLFSSL_DSA* dsa) +{ + int ret = WOLFSSL_FATAL_ERROR; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_DSA_do_sign"); + + if (d == NULL || sigRet == NULL || dsa == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return ret; + } + + if (dsa->inSet == 0) + { + WOLFSSL_MSG("No DSA internal set, do it"); + + 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_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; + } + + if (rng) { + if (DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0) + WOLFSSL_MSG("DsaSign failed"); + else + ret = WOLFSSL_SUCCESS; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return ret; +} + +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) +WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest, + int outLen, WOLFSSL_DSA* dsa) +{ + WOLFSSL_DSA_SIG* sig = NULL; + byte sigBin[DSA_SIG_SIZE]; + + WOLFSSL_ENTER("wolfSSL_DSA_do_sign_ex"); + + if (!digest || !dsa || outLen != WC_SHA_DIGEST_SIZE) { + WOLFSSL_MSG("Bad function arguments"); + return NULL; + } + + if (wolfSSL_DSA_do_sign(digest, sigBin, dsa) != WOLFSSL_SUCCESS) { + return NULL; + } + + if (!(sig = wolfSSL_DSA_SIG_new())) { + goto error; + } + + if (!(sig->r = wolfSSL_BN_bin2bn(sigBin, DSA_HALF_SIZE, NULL))) { + goto error; + } + + if (!(sig->s = wolfSSL_BN_bin2bn(sigBin + DSA_HALF_SIZE, DSA_HALF_SIZE, NULL))) { + goto error; + } + + return sig; +error: + if (sig) { + wolfSSL_DSA_SIG_free(sig); + } + return NULL; +} +#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ + +int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig, + WOLFSSL_DSA* dsa, int *dsacheck) +{ + int ret = WOLFSSL_FATAL_ERROR; + + WOLFSSL_ENTER("wolfSSL_DSA_do_verify"); + + if (d == NULL || sig == NULL || dsa == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FATAL_ERROR; + } + if (dsa->inSet == 0) + { + WOLFSSL_MSG("No DSA internal set, do it"); + + if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return WOLFSSL_FATAL_ERROR; + } + } + + ret = DsaVerify(d, sig, (DsaKey*)dsa->internal, dsacheck); + if (ret != 0 || *dsacheck != 1) { + WOLFSSL_MSG("DsaVerify failed"); + return ret; + } + + return WOLFSSL_SUCCESS; +} + +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) +int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len, + WOLFSSL_DSA_SIG* sig, WOLFSSL_DSA* dsa) +{ + int dsacheck, sz; + byte sigBin[DSA_SIG_SIZE]; + byte* sigBinPtr = sigBin; + + WOLFSSL_ENTER("wolfSSL_DSA_do_verify_ex"); + + if (!digest || !sig || !dsa || digest_len != WC_SHA_DIGEST_SIZE) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + if (!sig->r || !sig->s) { + WOLFSSL_MSG("No signature found in DSA_SIG"); + return WOLFSSL_FAILURE; + } + + /* front pad with zeros */ + if (!(sz = wolfSSL_BN_num_bytes(sig->r))) { + return WOLFSSL_FAILURE; + } + while (sz++ < DSA_HALF_SIZE) { + *sigBinPtr++ = 0; + } + + if (wolfSSL_BN_bn2bin(sig->r, sigBinPtr) == WOLFSSL_FATAL_ERROR) { + return WOLFSSL_FAILURE; + } + + /* Move to s */ + sigBinPtr = sigBin + DSA_HALF_SIZE; + + /* front pad with zeros */ + if (!(sz = wolfSSL_BN_num_bytes(sig->s))) { + return WOLFSSL_FAILURE; + } + while (sz++ < DSA_HALF_SIZE) { + *sigBinPtr++ = 0; + } + + if (wolfSSL_BN_bn2bin(sig->s, sigBinPtr) == WOLFSSL_FATAL_ERROR) { + return WOLFSSL_FAILURE; + } + + if (wolfSSL_DSA_do_verify(digest, sigBin, dsa, &dsacheck) != WOLFSSL_SUCCESS || + dsacheck != 1) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ +#endif /* NO_DSA */ + + +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + +#ifdef DEBUG_SIGN +static void show(const char *title, const unsigned char *out, unsigned int outlen) +{ + const unsigned char *pt; + printf("%s[%d] = \n", title, (int)outlen); + outlen = outlen>100?100:outlen; + for (pt = out; pt < out + outlen; + printf("%c", ((*pt)&0x6f)>='A'?((*pt)&0x6f):'.'), pt++); + printf("\n"); +} +#else +#define show(a,b,c) +#endif + +/* return SSL_SUCCESS on ok, 0 otherwise */ +int wolfSSL_RSA_sign(int type, const unsigned char* m, + unsigned int mLen, unsigned char* sigRet, + unsigned int* sigLen, WOLFSSL_RSA* rsa) +{ + return wolfSSL_RSA_sign_ex(type, m, mLen, sigRet, sigLen, rsa, 1); +} + +int wolfSSL_RSA_sign_ex(int type, const unsigned char* m, + unsigned int mLen, unsigned char* sigRet, + unsigned int* sigLen, WOLFSSL_RSA* rsa, int flag) +{ + word32 outLen; + word32 signSz; + int initTmpRng = 0; + WC_RNG* rng = NULL; + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; + byte* encodedSig = NULL; +#else + WC_RNG tmpRNG[1]; + byte encodedSig[MAX_ENCODED_SIG_SZ]; +#endif + + WOLFSSL_ENTER("wolfSSL_RSA_sign"); + + if (m == NULL || sigRet == NULL || sigLen == NULL || rsa == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; + } + show("Message to Sign", m, mLen); + + switch (type) { + #ifdef WOLFSSL_MD2 + case NID_md2: type = MD2h; break; + #endif + #ifndef NO_MD5 + case NID_md5: type = MD5h; break; + #endif + #ifndef NO_SHA + case NID_sha1: type = SHAh; break; + #endif + #ifndef NO_SHA256 + case NID_sha256: type = SHA256h; break; + #endif + #ifdef WOLFSSL_SHA384 + case NID_sha384: type = SHA384h; break; + #endif + #ifdef WOLFSSL_SHA512 + case NID_sha512: type = SHA512h; break; + #endif + #ifndef WOLFSSL_NOSHA3_224 + case NID_sha3_224: type = SHA3_224h; break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case NID_sha3_256: type = SHA3_256h; break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case NID_sha3_384: type = SHA3_384h; break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case NID_sha3_512: type = SHA3_512h; break; + #endif + default: + WOLFSSL_MSG("This NID (md type) not configured or not implemented"); + 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; + } + } + + outLen = (word32)wolfSSL_BN_num_bytes(rsa->n); + +#ifdef WOLFSSL_SMALL_STACK + 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_SIGNATURE); + if (encodedSig == NULL) { + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); + return 0; + } +#endif + + if (outLen == 0) + WOLFSSL_MSG("Bad RSA size"); + else 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; } if (rng) { - type = (type == NID_md5) ? MD5h : SHAh; signSz = wc_EncodeSignature(encodedSig, m, mLen, type); if (signSz == 0) { WOLFSSL_MSG("Bad Encode Signature"); } else { - *sigLen = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen, - (RsaKey*)rsa->internal, rng); - if (*sigLen <= 0) - WOLFSSL_MSG("Bad Rsa Sign"); - else + show("Encoded Message", encodedSig, signSz); + if (flag != 0) { + ret = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen, + (RsaKey*)rsa->internal, rng); + if (ret <= 0) { + WOLFSSL_MSG("Bad Rsa Sign"); + ret = 0; + } + else { + *sigLen = (unsigned int)ret; + ret = SSL_SUCCESS; + show("Signature", sigRet, *sigLen); + } + } else { ret = SSL_SUCCESS; + XMEMCPY(sigRet, encodedSig, signSz); + *sigLen = signSz; + } } } @@ -12095,31 +30078,103 @@ 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 - WOLFSSL_MSG("wolfSSL_RSA_sign success"); + if (ret == WOLFSSL_SUCCESS) + WOLFSSL_MSG("wolfSSL_RSA_sign success"); + else { + WOLFSSL_MSG("wolfSSL_RSA_sign failed"); + } return ret; } -int wolfSSL_RSA_public_decrypt(int flen, unsigned char* from, - unsigned char* to, WOLFSSL_RSA* rsa, int padding) +/* returns WOLFSSL_SUCCESS on successful verify and WOLFSSL_FAILURE on fail */ +int wolfSSL_RSA_verify(int type, const unsigned char* m, + unsigned int mLen, const unsigned char* sig, + unsigned int sigLen, WOLFSSL_RSA* rsa) { - (void)flen; - (void)from; - (void)to; - (void)rsa; - (void)padding; + int ret; + unsigned char *sigRet ; + unsigned char *sigDec ; + unsigned int len; - WOLFSSL_MSG("wolfSSL_RSA_public_decrypt"); + WOLFSSL_ENTER("wolfSSL_RSA_verify"); + if ((m == NULL) || (sig == NULL)) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } - return SSL_FATAL_ERROR; + sigRet = (unsigned char *)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sigRet == NULL) { + WOLFSSL_MSG("Memory failure"); + return WOLFSSL_FAILURE; + } + sigDec = (unsigned char *)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sigDec == NULL) { + WOLFSSL_MSG("Memory failure"); + XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + /* get non-encrypted signature to be compared with decrypted signature */ + ret = wolfSSL_RSA_sign_ex(type, m, mLen, sigRet, &len, rsa, 0); + if (ret <= 0) { + WOLFSSL_MSG("Message Digest Error"); + XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + show("Encoded Message", sigRet, len); + /* decrypt signature */ + ret = wc_RsaSSL_Verify(sig, sigLen, (unsigned char *)sigDec, sigLen, + (RsaKey*)rsa->internal); + if (ret <= 0) { + WOLFSSL_MSG("RSA Decrypt error"); + XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + show("Decrypted Signature", sigDec, ret); + + if ((int)len == ret && XMEMCMP(sigRet, sigDec, ret) == 0) { + WOLFSSL_MSG("wolfSSL_RSA_verify success"); + XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_SUCCESS; + } + else { + WOLFSSL_MSG("wolfSSL_RSA_verify failed"); + XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } } +void wolfSSL_RSA_get0_key(const WOLFSSL_RSA *r, const WOLFSSL_BIGNUM **n, + const WOLFSSL_BIGNUM **e, const WOLFSSL_BIGNUM **d) +{ + WOLFSSL_ENTER("wolfSSL_RSA_get0_key"); -/* generate p-1 and q-1, SSL_SUCCESS on ok */ + if (r != NULL) { + if (n != NULL) + *n = r->n; + if (e != NULL) + *e = r->e; + if (d != NULL) + *d = r->d; + } else { + if (n != NULL) + *n = NULL; + if (e != NULL) + *e = NULL; + if (d != NULL) + *d = NULL; + } +} + +/* generate p-1 and q-1, WOLFSSL_SUCCESS on ok */ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa) { int err; @@ -12130,12 +30185,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); @@ -12161,186 +30216,454 @@ 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 && !HAVE_USER_RSA */ + +WOLFSSL_HMAC_CTX* wolfSSL_HMAC_CTX_new(void) +{ + return (WOLFSSL_HMAC_CTX*)XMALLOC(sizeof(WOLFSSL_HMAC_CTX), NULL, + DYNAMIC_TYPE_OPENSSL); +} + +int wolfSSL_HMAC_CTX_Init(WOLFSSL_HMAC_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init"); + + if (ctx != NULL) { + /* wc_HmacSetKey sets up ctx->hmac */ + XMEMSET(ctx, 0, sizeof(WOLFSSL_HMAC_CTX)); + } + + return WOLFSSL_SUCCESS; } -#endif /* NO_RSA */ -void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, +int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, + int keylen, const EVP_MD* type, WOLFSSL_ENGINE* e) +{ + WOLFSSL_ENTER("wolfSSL_HMAC_Init_ex"); + + /* WOLFSSL_ENGINE not used, call wolfSSL_HMAC_Init */ + (void)e; + return wolfSSL_HMAC_Init(ctx, key, keylen, type); +} + + +/* helper function for Deep copy of internal wolfSSL hmac structure + * returns WOLFSSL_SUCCESS on success */ +int wolfSSL_HmacCopy(Hmac* des, Hmac* src) +{ + void* heap; + +#ifndef HAVE_FIPS + heap = src->heap; +#else + heap = NULL; +#endif + if (wc_HmacInit(des, heap, 0) != 0) { + return WOLFSSL_FAILURE; + } + + /* requires that hash structures have no dynamic parts to them */ + switch (src->macType) { + #ifndef NO_MD5 + case WC_MD5: + wc_Md5Copy(&src->hash.md5, &des->hash.md5); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + wc_ShaCopy(&src->hash.sha, &des->hash.sha); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + wc_Sha224Copy(&src->hash.sha224, &des->hash.sha224); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + wc_Sha256Copy(&src->hash.sha256, &des->hash.sha256); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + wc_Sha384Copy(&src->hash.sha384, &des->hash.sha384); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + wc_Sha512Copy(&src->hash.sha512, &des->hash.sha512); + break; + #endif /* WOLFSSL_SHA512 */ + + default: + return WOLFSSL_FAILURE; + } + + XMEMCPY((byte*)des->ipad, (byte*)src->ipad, WC_HMAC_BLOCK_SIZE); + XMEMCPY((byte*)des->opad, (byte*)src->opad, WC_HMAC_BLOCK_SIZE); + XMEMCPY((byte*)des->innerHash, (byte*)src->innerHash, WC_MAX_DIGEST_SIZE); +#ifndef HAVE_FIPS + des->heap = heap; +#endif + des->macType = src->macType; + des->innerHashKeyed = src->innerHashKeyed; + +#ifdef WOLFSSL_ASYNC_CRYPT + XMEMCPY(&des->asyncDev, &src->asyncDev, sizeof(WC_ASYNC_DEV)); + des->keyLen = src->keyLen; + #ifdef HAVE_CAVIUM + des->data = (byte*)XMALLOC(src->dataLen, des->heap, + DYNAMIC_TYPE_HMAC); + if (des->data == NULL) { + return BUFFER_E; + } + XMEMCPY(des->data, src->data, src->dataLen); + des->dataLen = src->dataLen; + #endif /* HAVE_CAVIUM */ +#endif /* WOLFSSL_ASYNC_CRYPT */ + return WOLFSSL_SUCCESS; +} + + +/* Deep copy of information from src to des structure + * + * des destination to copy information to + * src structure to get information from + * + * Returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error + */ +int wolfSSL_HMAC_CTX_copy(WOLFSSL_HMAC_CTX* des, WOLFSSL_HMAC_CTX* src) +{ + WOLFSSL_ENTER("wolfSSL_HMAC_CTX_copy"); + + if (des == NULL || src == NULL) { + return WOLFSSL_FAILURE; + } + + des->type = src->type; + XMEMCPY((byte *)&des->save_ipad, (byte *)&src->hmac.ipad, + WC_HMAC_BLOCK_SIZE); + XMEMCPY((byte *)&des->save_opad, (byte *)&src->hmac.opad, + WC_HMAC_BLOCK_SIZE); + + return wolfSSL_HmacCopy(&des->hmac, &src->hmac); +} + + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + +static int _HMAC_Init(Hmac* hmac, int type, void* heap) +{ + int ret = 0; + + switch (type) { + #ifndef NO_MD5 + case WC_MD5: + ret = wc_InitMd5(&hmac->hash.md5); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + ret = wc_InitSha(&hmac->hash.sha); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + ret = wc_InitSha224(&hmac->hash.sha224); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_InitSha256(&hmac->hash.sha256); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = wc_InitSha384(&hmac->hash.sha384); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + ret = wc_InitSha512(&hmac->hash.sha512); + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef WOLFSSL_SHA3 + case WC_SHA3_224: + ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + case WC_SHA3_256: + ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + case WC_SHA3_384: + ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + case WC_SHA3_512: + ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + #endif + + default: + ret = BAD_FUNC_ARG; + break; + } + + (void)heap; + + return ret; +} + +#else + #define _HMAC_Init _InitHmac +#endif + + +int wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, const EVP_MD* type) { + int hmac_error = 0; + void* heap = NULL; + WOLFSSL_MSG("wolfSSL_HMAC_Init"); if (ctx == NULL) { WOLFSSL_MSG("no ctx on init"); - return; + return WOLFSSL_FAILURE; } +#ifndef HAVE_FIPS + heap = ctx->hmac.heap; +#endif + if (type) { WOLFSSL_MSG("init has type"); +#ifndef NO_MD5 if (XSTRNCMP(type, "MD5", 3) == 0) { WOLFSSL_MSG("md5 hmac"); - ctx->type = MD5; + ctx->type = WC_MD5; } - else if (XSTRNCMP(type, "SHA256", 6) == 0) { + else +#endif +#ifdef WOLFSSL_SHA224 + if (XSTRNCMP(type, "SHA224", 6) == 0) { + WOLFSSL_MSG("sha224 hmac"); + ctx->type = WC_SHA224; + } + else +#endif +#ifndef NO_SHA256 + if (XSTRNCMP(type, "SHA256", 6) == 0) { WOLFSSL_MSG("sha256 hmac"); - ctx->type = SHA256; + ctx->type = WC_SHA256; } + else +#endif +#ifdef WOLFSSL_SHA384 + if (XSTRNCMP(type, "SHA384", 6) == 0) { + WOLFSSL_MSG("sha384 hmac"); + ctx->type = WC_SHA384; + } + else +#endif +#ifdef WOLFSSL_SHA512 + if (XSTRNCMP(type, "SHA512", 6) == 0) { + WOLFSSL_MSG("sha512 hmac"); + ctx->type = WC_SHA512; + } + else +#endif +#ifndef NO_SHA /* has to be last since would pick or 256, 384, or 512 too */ - else if (XSTRNCMP(type, "SHA", 3) == 0) { + if (XSTRNCMP(type, "SHA", 3) == 0) { WOLFSSL_MSG("sha hmac"); - ctx->type = SHA; + ctx->type = WC_SHA; } - else { + else +#endif + { WOLFSSL_MSG("bad init type"); + return WOLFSSL_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 WOLFSSL_FAILURE; + } + XMEMCPY((byte *)&ctx->save_ipad, (byte *)&ctx->hmac.ipad, + WC_HMAC_BLOCK_SIZE); + XMEMCPY((byte *)&ctx->save_opad, (byte *)&ctx->hmac.opad, + WC_HMAC_BLOCK_SIZE); + } /* OpenSSL compat, no error */ - } -} - - -void wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, - int len) -{ - WOLFSSL_MSG("wolfSSL_HMAC_Update"); - - if (ctx && data) { - WOLFSSL_MSG("updating hmac"); - wc_HmacUpdate(&ctx->hmac, data, (word32)len); - /* OpenSSL compat, no error */ - } -} - - -void wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, - unsigned int* len) -{ - WOLFSSL_MSG("wolfSSL_HMAC_Final"); - - if (ctx && hash) { - WOLFSSL_MSG("final hmac"); - wc_HmacFinal(&ctx->hmac, hash); - /* OpenSSL compat, no error */ - - 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"); + } else if(ctx->type >= 0) { /* MD5 == 0 */ + WOLFSSL_MSG("recover hmac"); + wc_HmacFree(&ctx->hmac); + if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) { + ctx->hmac.macType = (byte)ctx->type; + ctx->hmac.innerHashKeyed = 0; + XMEMCPY((byte *)&ctx->hmac.ipad, (byte *)&ctx->save_ipad, + WC_HMAC_BLOCK_SIZE); + XMEMCPY((byte *)&ctx->hmac.opad, (byte *)&ctx->save_opad, + WC_HMAC_BLOCK_SIZE); + if ((hmac_error = _HMAC_Init(&ctx->hmac, ctx->hmac.macType, heap)) + !=0) { + return hmac_error; } } } + + (void)hmac_error; + + return WOLFSSL_SUCCESS; } -void wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx) +int wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, + int len) { - (void)ctx; + int hmac_error = 0; + WOLFSSL_MSG("wolfSSL_HMAC_Update"); + + if (ctx == NULL) { + WOLFSSL_MSG("no ctx"); + return WOLFSSL_FAILURE; + } + + if (data) { + WOLFSSL_MSG("updating hmac"); + hmac_error = wc_HmacUpdate(&ctx->hmac, data, (word32)len); + if (hmac_error < 0){ + WOLFSSL_MSG("hmac update error"); + return WOLFSSL_FAILURE; + } + } + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, + unsigned int* len) +{ + int hmac_error; + + WOLFSSL_MSG("wolfSSL_HMAC_Final"); + + /* "len" parameter is optional. */ + if (ctx == NULL || hash == NULL) { + WOLFSSL_MSG("invalid parameter"); + return WOLFSSL_FAILURE; + } + + WOLFSSL_MSG("final hmac"); + hmac_error = wc_HmacFinal(&ctx->hmac, hash); + if (hmac_error < 0){ + WOLFSSL_MSG("final hmac error"); + return WOLFSSL_FAILURE; + } + + if (len) { + WOLFSSL_MSG("setting output len"); + switch (ctx->type) { + #ifndef NO_MD5 + case WC_MD5: + *len = WC_MD5_DIGEST_SIZE; + break; + #endif + + #ifndef NO_SHA + case WC_SHA: + *len = WC_SHA_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + *len = WC_SHA224_DIGEST_SIZE; + break; + #endif + + #ifndef NO_SHA256 + case WC_SHA256: + *len = WC_SHA256_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + *len = WC_SHA384_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + *len = WC_SHA512_DIGEST_SIZE; + break; + #endif + + default: + WOLFSSL_MSG("bad hmac type"); + return WOLFSSL_FAILURE; + } + } + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx) +{ WOLFSSL_MSG("wolfSSL_HMAC_cleanup"); + + if (ctx) + wc_HmacFree(&ctx->hmac); + + return SSL_SUCCESS; } -const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int id) +void wolfSSL_HMAC_CTX_free(WOLFSSL_HMAC_CTX* ctx) { - WOLFSSL_MSG("wolfSSL_get_digestbynid"); + if (!ctx) { + return; + } + wolfSSL_HMAC_cleanup(ctx); + XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL); +} - switch(id) { -#ifndef NO_MD5 - case NID_md5: - return wolfSSL_EVP_md5(); -#endif -#ifndef NO_SHA - case NID_sha1: - return wolfSSL_EVP_sha1(); -#endif - default: - WOLFSSL_MSG("Bad digest id value"); +size_t wolfSSL_HMAC_size(const WOLFSSL_HMAC_CTX *ctx) +{ + if (!ctx) { + return 0; } - return NULL; + return (size_t)wc_HashGetDigestSize((enum wc_HashType)ctx->hmac.macType); } - -WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* key) -{ - (void)key; - WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_RSA"); - - return NULL; -} - - -WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key) -{ - (void)key; - WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_DSA"); - - return NULL; -} - - -void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx) -{ - WOLFSSL_MSG("wolfSSL_EVP_X_STATE"); - - if (ctx) { - switch (ctx->cipherType) { - case ARC4_TYPE: - WOLFSSL_MSG("returning arc4 state"); - return (void*)&ctx->cipher.arc4.x; - - default: - WOLFSSL_MSG("bad x state type"); - return 0; - } - } - - return NULL; -} - - -int wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx) -{ - WOLFSSL_MSG("wolfSSL_EVP_X_STATE_LEN"); - - if (ctx) { - switch (ctx->cipherType) { - case ARC4_TYPE: - WOLFSSL_MSG("returning arc4 state size"); - return sizeof(Arc4); - - default: - WOLFSSL_MSG("bad x state type"); - return 0; - } - } - - return 0; -} - - #ifndef NO_DES3 void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, @@ -12358,7 +30681,7 @@ void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, if (doset) wc_Des3_SetIV(&ctx->cipher.des3, iv); /* OpenSSL compat, no ret */ else - memcpy(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE); + XMEMCPY(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE); } #endif /* NO_DES3 */ @@ -12379,238 +30702,4841 @@ void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, } if (doset) - wc_AesSetIV(&ctx->cipher.aes, iv); /* OpenSSL compat, no ret */ + (void)wc_AesSetIV(&ctx->cipher.aes, iv); /* OpenSSL compat, no ret */ else - memcpy(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); + XMEMCPY(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); } #endif /* NO_AES */ -const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void) -{ - WOLFSSL_MSG("wolfSSL_ripemd160"); - - return NULL; -} - - -int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* type) -{ - WOLFSSL_MSG("wolfSSL_EVP_MD_size"); - - if (type == NULL) { - WOLFSSL_MSG("No md type arg"); - return BAD_FUNC_ARG; - } - - if (XSTRNCMP(type, "SHA256", 6) == 0) { - return SHA256_DIGEST_SIZE; - } -#ifndef NO_MD5 - else if (XSTRNCMP(type, "MD5", 3) == 0) { - return MD5_DIGEST_SIZE; - } -#endif -#ifdef WOLFSSL_SHA384 - else if (XSTRNCMP(type, "SHA384", 6) == 0) { - return SHA384_DIGEST_SIZE; - } -#endif -#ifdef WOLFSSL_SHA512 - else if (XSTRNCMP(type, "SHA512", 6) == 0) { - return 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; - } -#endif - - return BAD_FUNC_ARG; -} - - -int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx) -{ - WOLFSSL_MSG("wolfSSL_EVP_CIPHER_CTX_iv_length"); - - switch (ctx->cipherType) { - - case AES_128_CBC_TYPE : - case AES_192_CBC_TYPE : - case AES_256_CBC_TYPE : - WOLFSSL_MSG("AES CBC"); - return AES_BLOCK_SIZE; - -#ifdef WOLFSSL_AES_COUNTER - case AES_128_CTR_TYPE : - case AES_192_CTR_TYPE : - case AES_256_CTR_TYPE : - WOLFSSL_MSG("AES CTR"); - return AES_BLOCK_SIZE; -#endif - - case DES_CBC_TYPE : - WOLFSSL_MSG("DES CBC"); - return DES_BLOCK_SIZE; - - case DES_EDE3_CBC_TYPE : - WOLFSSL_MSG("DES EDE3 CBC"); - return DES_BLOCK_SIZE; - - case ARC4_TYPE : - WOLFSSL_MSG("ARC4"); - return 0; - - case NULL_CIPHER_TYPE : - WOLFSSL_MSG("NULL"); - return 0; - - default: { - WOLFSSL_MSG("bad type"); - } - } - return 0; -} - - +/* Free the dynamically allocated data. + * + * p Pointer to dynamically allocated memory. + */ void wolfSSL_OPENSSL_free(void* p) { WOLFSSL_MSG("wolfSSL_OPENSSL_free"); - XFREE(p, NULL, 0); + XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL); } - -int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, RSA* rsa, - const EVP_CIPHER* cipher, - unsigned char* passwd, int len, - pem_password_cb cb, void* arg) +void *wolfSSL_OPENSSL_malloc(size_t a) { - (void)bio; - (void)rsa; + return XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL); +} + +#if defined(WOLFSSL_KEY_GEN) && defined(WOLFSSL_PEM_TO_DER) + +static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, byte **cipherInfo) +{ + int ret, paddingSz; + word32 idx, cipherInfoSz; +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; +#else + EncryptedInfo info[1]; +#endif + + WOLFSSL_ENTER("EncryptDerKey"); + + if (der == NULL || derSz == NULL || cipher == NULL || + passwd == NULL || cipherInfo == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_ENCRYPTEDINFO); + if (info == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } +#endif + + XMEMSET(info, 0, sizeof(EncryptedInfo)); + + /* set the cipher name on info */ + XSTRNCPY(info->name, cipher, NAME_SZ-1); + info->name[NAME_SZ-1] = '\0'; /* null term */ + + ret = wc_EncryptedInfoGet(info, info->name); + if (ret != 0) { + WOLFSSL_MSG("unsupported cipher"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); + #endif + return WOLFSSL_FAILURE; + } + + /* Generate a random salt */ + if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("generate iv failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); +#endif + return WOLFSSL_FAILURE; + } + + /* add the padding before encryption */ + paddingSz = ((*derSz)/info->ivSz + 1) * info->ivSz - (*derSz); + if (paddingSz == 0) + paddingSz = info->ivSz; + XMEMSET(der+(*derSz), (byte)paddingSz, paddingSz); + (*derSz) += paddingSz; + + /* encrypt buffer */ + if (wc_BufferKeyEncrypt(info, der, *derSz, passwd, passwdSz, WC_MD5) != 0) { + WOLFSSL_MSG("encrypt key failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); +#endif + 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_STRING); + if (*cipherInfo == NULL) { + WOLFSSL_MSG("malloc failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); +#endif + return WOLFSSL_FAILURE; + } + XSTRNCPY((char*)*cipherInfo, info->name, cipherInfoSz); + XSTRNCAT((char*)*cipherInfo, ",", 2); + + idx = (word32)XSTRLEN((char*)*cipherInfo); + cipherInfoSz -= idx; + ret = Base16_Encode(info->iv, info->ivSz, *cipherInfo+idx, &cipherInfoSz); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); +#endif + if (ret != 0) { + WOLFSSL_MSG("Base16_Encode failed"); + XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_KEY_GEN || WOLFSSL_PEM_TO_DER */ + +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) +static int wolfSSL_RSA_To_Der(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey) +{ + int derSz = 0; + int ret; + byte* derBuf; + + WOLFSSL_ENTER("wolfSSL_RSA_To_Der"); + + if (!rsa || (publicKey != 0 && publicKey != 1)) { + WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", BAD_FUNC_ARG); + return BAD_FUNC_ARG; + } + + if (rsa->inSet == 0) { + if ((ret = SetRsaInternal(rsa)) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal() Failed"); + WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", ret); + return ret; + } + } + + if (publicKey) { + if ((derSz = wc_RsaPublicKeyDerSize((RsaKey *)rsa->internal, 1)) < 0) { + WOLFSSL_MSG("wc_RsaPublicKeyDerSize failed"); + WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", derSz); + return derSz; + } + } + else { + if ((derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, NULL, 0)) < 0) { + WOLFSSL_MSG("wc_RsaKeyToDer failed"); + WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", derSz); + return derSz; + } + } + + if (outBuf) { + if (!(derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER))) { + WOLFSSL_MSG("malloc failed"); + WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", MEMORY_ERROR); + return MEMORY_ERROR; + } + + /* Key to DER */ + if (publicKey) { + derSz = wc_RsaKeyToPublicDer((RsaKey*)rsa->internal, derBuf, derSz); + } + else { + derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, derBuf, derSz); + } + + if (derSz < 0) { + WOLFSSL_MSG("wc_RsaKeyToPublicDer failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + else { + if (*outBuf) { + XMEMCPY(*outBuf, derBuf, derSz); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + else { + *outBuf = derBuf; + } + } + } + + WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", derSz); + return derSz; +} +#endif + +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) + +/* Takes a WOLFSSL_RSA key and writes it out to a WOLFSSL_BIO + * + * bio the WOLFSSL_BIO to write to + * key the WOLFSSL_RSA key to write out + * cipher cipher used + * passwd password string if used + * len length of password string + * cb password callback to use + * arg null terminated string for passphrase + */ +int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* key, + const WOLFSSL_EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) +{ + int ret; + WOLFSSL_EVP_PKEY* pkey; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSAPrivateKey"); + + if (bio == NULL || key == NULL) { + WOLFSSL_MSG("Bad Function Arguments"); + return WOLFSSL_FAILURE; + } + + pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap); + if (pkey == NULL) { + WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed"); + return WOLFSSL_FAILURE; + } + + pkey->type = EVP_PKEY_RSA; + pkey->rsa = key; + pkey->ownRsa = 0; +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) + /* similar to how wolfSSL_PEM_write_mem_RSAPrivateKey finds DER of key */ + { + int derSz; + byte* derBuf = NULL; + + if ((derSz = wolfSSL_RSA_To_Der(key, &derBuf, 0)) < 0) { + WOLFSSL_MSG("wolfSSL_RSA_To_Der failed"); + return WOLFSSL_FAILURE; + } + + pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (pkey->pkey.ptr == NULL) { + WOLFSSL_MSG("key malloc failed"); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + pkey->pkey_sz = derSz; + XMEMCPY(pkey->pkey.ptr, derBuf, derSz); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len, + cb, arg); + + wolfSSL_EVP_PKEY_free(pkey); + + return ret; +} + +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) +/* Takes an RSA public key and writes it out to a WOLFSSL_BIO + * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE + */ +int wolfSSL_PEM_write_bio_RSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa) +{ + int ret = 0, derSz = 0; + byte *derBuf = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSA_PUBKEY"); + + if (bio == NULL || rsa == NULL) { + WOLFSSL_MSG("Bad Function Arguments"); + return WOLFSSL_FAILURE; + } + + /* Initialize pkey structure */ + pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap); + if (pkey == NULL) { + WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed"); + return WOLFSSL_FAILURE; + } + + pkey->type = EVP_PKEY_RSA; + pkey->rsa = rsa; + pkey->ownRsa = 0; + + if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1)) < 0) { + WOLFSSL_MSG("wolfSSL_RSA_To_Der failed"); + return WOLFSSL_FAILURE; + } + + pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (pkey->pkey.ptr == NULL) { + WOLFSSL_MSG("key malloc failed"); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + pkey->pkey_sz = derSz; + XMEMCPY(pkey->pkey.ptr, derBuf, derSz); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + ret = wolfSSL_PEM_write_bio_PUBKEY(bio, pkey); + wolfSSL_EVP_PKEY_free(pkey); + + return ret; +} +#endif + + +/* Reads an RSA public key from a WOLFSSL_BIO into a WOLFSSL_RSA + * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE + */ +WOLFSSL_RSA *wolfSSL_PEM_read_bio_RSA_PUBKEY(WOLFSSL_BIO* bio,WOLFSSL_RSA** rsa, + pem_password_cb* cb, void *pass) +{ + WOLFSSL_EVP_PKEY* pkey; + WOLFSSL_RSA* local; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_RSA_PUBKEY"); + + pkey = wolfSSL_PEM_read_bio_PUBKEY(bio, NULL, cb, pass); + if (pkey == NULL) { + return NULL; + } + + /* Since the WOLFSSL_RSA structure is being taken from WOLFSSL_EVP_PKEY the + * flag indicating that the WOLFSSL_RSA structure is owned should be FALSE + * to avoid having it free'd */ + pkey->ownRsa = 0; + local = pkey->rsa; + if (rsa != NULL){ + *rsa = local; + } + + wolfSSL_EVP_PKEY_free(pkey); + return local; +} + +#endif /* defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) && !defined(NO_RSA) */ + +/* Takes a public key and writes it out to a WOLFSSL_BIO + * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE + */ +int wolfSSL_PEM_write_bio_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key) +{ + byte* keyDer; + int pemSz; + int ret; + byte* tmp; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PUBKEY"); + + if (bio == NULL || key == NULL) { + return WOLFSSL_FAILURE; + } + + keyDer = (byte*)key->pkey.ptr; + + pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, PUBLICKEY_TYPE); + if (pemSz < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PUBKEY", pemSz); + return WOLFSSL_FAILURE; + } + tmp = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (tmp == NULL) { + return MEMORY_E; + } + + ret = wc_DerToPemEx(keyDer, key->pkey_sz, tmp, pemSz, + NULL, PUBLICKEY_TYPE); + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PUBKEY", ret); + XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL); + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_BIO_write(bio, tmp, pemSz); + XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (ret != pemSz) { + WOLFSSL_MSG("Unable to write full PEM to BIO"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* Takes a private key and writes it out to a WOLFSSL_BIO + * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE + */ +int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, + const WOLFSSL_EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) +{ + byte* keyDer; + int pemSz; + int type; + int ret; + byte* tmp; + (void)cipher; (void)passwd; (void)len; (void)cb; (void)arg; - WOLFSSL_MSG("wolfSSL_PEM_write_bio_RSAPrivateKey"); + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey"); - return SSL_FATAL_ERROR; + if (bio == NULL || key == NULL) { + WOLFSSL_MSG("Bad Function Arguments"); + return WOLFSSL_FAILURE; + } + + keyDer = (byte*)key->pkey.ptr; + + switch (key->type) { +#ifndef NO_RSA + case EVP_PKEY_RSA: + type = PRIVATEKEY_TYPE; + break; +#endif + +#ifndef NO_DSA + case EVP_PKEY_DSA: + type = DSA_PRIVATEKEY_TYPE; + break; +#endif + +#ifdef HAVE_ECC + case EVP_PKEY_EC: + type = ECC_PRIVATEKEY_TYPE; + break; +#endif + +#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) + case EVP_PKEY_DH: + type = DH_PRIVATEKEY_TYPE; + break; +#endif + + default: + WOLFSSL_MSG("Unknown Key type!"); + type = PRIVATEKEY_TYPE; + } + + pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, type); + if (pemSz < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz); + return WOLFSSL_FAILURE; + } + tmp = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (tmp == NULL) { + return MEMORY_E; + } + + ret = wc_DerToPemEx(keyDer, key->pkey_sz, tmp, pemSz, + NULL, type); + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret); + XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL); + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_BIO_write(bio, tmp, pemSz); + XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (ret != pemSz) { + WOLFSSL_MSG("Unable to write full PEM to BIO"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +#endif /* defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) */ + +#if (defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)) && \ + (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)) + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, + unsigned char **pem, int *plen) +{ + byte *derBuf = NULL, *tmp, *cipherInfo = NULL; + int derSz = 0; + const int type = PRIVATEKEY_TYPE; + const char* header = NULL; + const char* footer = NULL; + + WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey"); + + if (pem == NULL || plen == NULL || rsa == NULL || rsa->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + if (wc_PemGetHeaderFooter(type, &header, &footer) != 0) + return WOLFSSL_FAILURE; + + if (rsa->inSet == 0) { + WOLFSSL_MSG("No RSA internal set, do it"); + + if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return WOLFSSL_FAILURE; + } + } + + if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 0)) < 0) { + WOLFSSL_MSG("wolfSSL_RSA_To_Der failed"); + return WOLFSSL_FAILURE; + } + + /* encrypt DER buffer if required */ + if (passwd != NULL && passwdSz > 0 && cipher != NULL) { + int ret; + + ret = EncryptDerKey(derBuf, &derSz, cipher, + passwd, passwdSz, &cipherInfo); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("EncryptDerKey failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return ret; + } + + /* tmp buffer with a max size */ + *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE; + } + else { + /* tmp buffer with a max size */ + *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + (int)XSTRLEN(footer) + 1; + } + + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM); + if (tmp == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + + /* DER to PEM */ + *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type); + if (*plen <= 0) { + WOLFSSL_MSG("wc_DerToPemEx failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + if (cipherInfo != NULL) + 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_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_PEM); + return WOLFSSL_FAILURE; + } + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + + return WOLFSSL_SUCCESS; } - -int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, DSA* rsa, - const EVP_CIPHER* cipher, - unsigned char* passwd, int len, - pem_password_cb cb, void* arg) +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) { - (void)bio; - (void)rsa; - (void)cipher; - (void)passwd; - (void)len; + byte *pem; + int plen, ret; + (void)cb; - (void)arg; + (void)u; - WOLFSSL_MSG("wolfSSL_PEM_write_bio_DSAPrivateKey"); + WOLFSSL_MSG("wolfSSL_PEM_write_RSAPrivateKey"); - return SSL_FATAL_ERROR; + if (fp == XBADFILE || rsa == NULL || rsa->internal == NULL) + { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, enc, kstr, klen, &pem, &plen); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed"); + return WOLFSSL_FAILURE; + } + + ret = (int)XFWRITE(pem, plen, 1, fp); + if (ret != 1) { + WOLFSSL_MSG("RSA private key file write failed"); + return WOLFSSL_FAILURE; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + return WOLFSSL_SUCCESS; +} +#endif /* NO_FILESYSTEM */ +#endif /* WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA && WOLFSSL_PEM_TO_DER */ + + +#ifdef HAVE_ECC + +#ifdef ALT_ECC_SIZE +static int SetIndividualInternalEcc(WOLFSSL_BIGNUM* bn, mp_int* mpi) +{ + WOLFSSL_MSG("Entering SetIndividualInternal"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + if (mpi == NULL) { + WOLFSSL_MSG("mpi NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + return WOLFSSL_FATAL_ERROR; + } + + return WOLFSSL_SUCCESS; +} +#endif /* ALT_ECC_SIZE */ + +/* EC_POINT Openssl -> WolfSSL */ +static int SetECPointInternal(WOLFSSL_EC_POINT *p) +{ + ecc_point* point; + WOLFSSL_ENTER("SetECPointInternal"); + + if (p == NULL || p->internal == NULL) { + WOLFSSL_MSG("ECPoint NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + point = (ecc_point*)p->internal; + +#ifndef ALT_ECC_SIZE + if (p->X != NULL && SetIndividualInternal(p->X, point->x) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point X error"); + return WOLFSSL_FATAL_ERROR; + } + + if (p->Y != NULL && SetIndividualInternal(p->Y, point->y) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point Y error"); + return WOLFSSL_FATAL_ERROR; + } + + if (p->Z != NULL && SetIndividualInternal(p->Z, point->z) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point Z error"); + return WOLFSSL_FATAL_ERROR; + } +#else + if (p->X != NULL && SetIndividualInternalEcc(p->X, point->x) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point X error"); + return WOLFSSL_FATAL_ERROR; + } + + if (p->Y != NULL && SetIndividualInternalEcc(p->Y, point->y) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point Y error"); + return WOLFSSL_FATAL_ERROR; + } + + if (p->Z != NULL && SetIndividualInternalEcc(p->Z, point->z) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point Z error"); + return WOLFSSL_FATAL_ERROR; + } +#endif + + p->inSet = 1; + + return WOLFSSL_SUCCESS; +} + +/* EC_POINT WolfSSL -> OpenSSL */ +static int SetECPointExternal(WOLFSSL_EC_POINT *p) +{ + ecc_point* point; + + WOLFSSL_ENTER("SetECPointExternal"); + + if (p == NULL || p->internal == NULL) { + WOLFSSL_MSG("ECPoint NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + point = (ecc_point*)p->internal; + + if (SetIndividualExternal(&p->X, point->x) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point X error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&p->Y, point->y) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point Y error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&p->Z, point->z) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point Z error"); + return WOLFSSL_FATAL_ERROR; + } + + p->exSet = 1; + + return WOLFSSL_SUCCESS; } - -WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, - WOLFSSL_EVP_PKEY** key, pem_password_cb cb, void* arg) +/* EC_KEY wolfSSL -> OpenSSL */ +int SetECKeyExternal(WOLFSSL_EC_KEY* eckey) { - (void)bio; - (void)key; - (void)cb; - (void)arg; + ecc_key* key; - WOLFSSL_MSG("wolfSSL_PEM_read_bio_PrivateKey"); + WOLFSSL_ENTER("SetECKeyExternal"); + if (eckey == NULL || eckey->internal == NULL) { + WOLFSSL_MSG("ec key NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + key = (ecc_key*)eckey->internal; + + /* 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; + + if (eckey->pub_key->internal != NULL) { + /* set the internal public key */ + if (wc_ecc_copy_point(&key->pubkey, + (ecc_point*)eckey->pub_key->internal) != MP_OKAY) { + WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed"); + return WOLFSSL_FATAL_ERROR; + } + + /* set the external pubkey (point) */ + if (SetECPointExternal(eckey->pub_key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed"); + return WOLFSSL_FATAL_ERROR; + } + } + + /* set the external privkey */ + if (key->type == ECC_PRIVATEKEY) { + if (SetIndividualExternal(&eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ec priv key error"); + return WOLFSSL_FATAL_ERROR; + } + } + + eckey->exSet = 1; + + return WOLFSSL_SUCCESS; +} + +/* EC_KEY Openssl -> WolfSSL */ +int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) +{ + ecc_key* key; + + WOLFSSL_ENTER("SetECKeyInternal"); + + if (eckey == NULL || eckey->internal == NULL || eckey->group == NULL) { + WOLFSSL_MSG("ec key NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + key = (ecc_key*)eckey->internal; + + /* validate group */ + if ((eckey->group->curve_idx < 0) || + (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) { + WOLFSSL_MSG("invalid curve idx"); + return WOLFSSL_FATAL_ERROR; + } + + /* set group (idx of curve and corresponding domain parameters) */ + key->idx = eckey->group->curve_idx; + key->dp = &ecc_sets[key->idx]; + + /* set pubkey (point) */ + if (eckey->pub_key != NULL) { + if (SetECPointInternal(eckey->pub_key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ec key pub error"); + return WOLFSSL_FATAL_ERROR; + } + + /* copy over the public point to key */ + if (wc_ecc_copy_point((ecc_point*)eckey->pub_key->internal, &key->pubkey) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_copy_point error"); + return WOLFSSL_FATAL_ERROR; + } + + /* public key */ + key->type = ECC_PUBLICKEY; + } + + /* set privkey */ + if (eckey->priv_key != NULL) { + if (SetIndividualInternal(eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ec key priv error"); + return WOLFSSL_FATAL_ERROR; + } + + /* private key */ + key->type = ECC_PRIVATEKEY; + } + + eckey->inSet = 1; + + return WOLFSSL_SUCCESS; +} + +WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key) +{ + WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key"); + + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_get0_public_key Bad arguments"); + return NULL; + } + + return key->pub_key; +} + +const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key) +{ + WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group"); + + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments"); + return NULL; + } + + return key->group; +} + + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, + const WOLFSSL_BIGNUM *priv_key) +{ + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key"); + + if (key == NULL || priv_key == NULL) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + + /* free key if previously set */ + if (key->priv_key != NULL) + wolfSSL_BN_free(key->priv_key); + + key->priv_key = wolfSSL_BN_dup(priv_key); + if (key->priv_key == NULL) { + WOLFSSL_MSG("key ecc priv key NULL"); + return WOLFSSL_FAILURE; + } + + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + wolfSSL_BN_free(key->priv_key); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + + +WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key) +{ + WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key"); + + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments"); + return NULL; + } + + if (wolfSSL_BN_is_zero(key->priv_key)) { + /* return NULL if not set */ + return NULL; + } + + return key->priv_key; +} + +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid) +{ + WOLFSSL_EC_KEY *key; + int x; + int eccEnum; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name"); + + /* If NID passed in is OpenSSL type, convert it to ecc_curve_id enum */ + eccEnum = NIDToEccEnum(nid); + if (eccEnum == -1) + eccEnum = nid; + + key = wolfSSL_EC_KEY_new(); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new failure"); + return NULL; + } + + /* set the nid of the curve */ + key->group->curve_nid = eccEnum; + + /* search and set the corresponding internal curve idx */ + 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; + } + + return key; +} + +const char* wolfSSL_EC_curve_nid2nist(int nid) +{ + const WOLF_EC_NIST_NAME* nist_name; + for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) { + if (nist_name->nid == nid) { + return kNistCurves->name; + } + } return NULL; } +#ifdef WOLFSSL_TLS13 +static int populate_groups(int* groups, int max_count, char *list) +{ + char *end; + int len; + int count = 0; + const WOLF_EC_NIST_NAME* nist_name; + if (!groups || !list) { + return -1; + } + + for (end = list; ; list = ++end) { + if (count > max_count) { + WOLFSSL_MSG("Too many curves in list"); + return -1; + } + while (*end != ':' && *end != '\0') end++; + len = (int)(end - list); /* end points to char after end + * of curve name so no need for -1 */ + if ((len < kNistCurves_MIN_NAME_LEN) || + (len > kNistCurves_MAX_NAME_LEN)) { + WOLFSSL_MSG("Unrecognized curve name in list"); + return -1; + } + for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) { + if (len == nist_name->name_len && + XSTRNCMP(list, nist_name->name, nist_name->name_len) == 0) { + break; + } + } + if (!nist_name->name) { + WOLFSSL_MSG("Unrecognized curve name in list"); + return -1; + } + groups[count++] = nist_name->nid; + if (*end == '\0') break; + } + + return count; +} + +int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, char *list) +{ + int groups[WOLFSSL_MAX_GROUP_COUNT]; + int count; + + if (!ctx || !list) { + return WOLFSSL_FAILURE; + } + + if ((count = populate_groups(groups, + WOLFSSL_MAX_GROUP_COUNT, list)) == -1) { + return WOLFSSL_FAILURE; + } + + return wolfSSL_CTX_set_groups(ctx, groups, count) == WOLFSSL_SUCCESS ? + WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} + +int wolfSSL_set1_groups_list(WOLFSSL *ssl, char *list) +{ + int groups[WOLFSSL_MAX_GROUP_COUNT]; + int count; + + if (!ssl || !list) { + return WOLFSSL_FAILURE; + } + + if ((count = populate_groups(groups, + WOLFSSL_MAX_GROUP_COUNT, list)) == -1) { + return WOLFSSL_FAILURE; + } + + return wolfSSL_set_groups(ssl, groups, count) == WOLFSSL_SUCCESS ? + WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} +#endif /* WOLFSSL_TLS13 */ + +static void InitwolfSSL_ECKey(WOLFSSL_EC_KEY* key) +{ + if (key) { + key->group = NULL; + key->pub_key = NULL; + key->priv_key = NULL; + key->internal = NULL; + key->inSet = 0; + key->exSet = 0; + } +} + +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void) +{ + WOLFSSL_EC_KEY *external; + WOLFSSL_ENTER("wolfSSL_EC_KEY_new"); + + external = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), NULL, + DYNAMIC_TYPE_ECC); + if (external == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure"); + return NULL; + } + XMEMSET(external, 0, sizeof(WOLFSSL_EC_KEY)); + + InitwolfSSL_ECKey(external); + + external->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, + DYNAMIC_TYPE_ECC); + if (external->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure"); + goto error; + } + XMEMSET(external->internal, 0, sizeof(ecc_key)); + + if (wc_ecc_init((ecc_key*)external->internal) != 0) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new init ecc key failure"); + goto error; + } + + /* curve group */ + external->group = wolfSSL_EC_GROUP_new_by_curve_name(ECC_CURVE_DEF); + if (external->group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure"); + goto error; + } + + /* public key */ + external->pub_key = wolfSSL_EC_POINT_new(external->group); + if (external->pub_key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new failure"); + goto error; + } + + /* private key */ + external->priv_key = wolfSSL_BN_new(); + if (external->priv_key == NULL) { + WOLFSSL_MSG("wolfSSL_BN_new failure"); + goto error; + } + + return external; +error: + wolfSSL_EC_KEY_free(external); + return NULL; +} + +void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) +{ + WOLFSSL_ENTER("wolfSSL_EC_KEY_free"); + + if (key != NULL) { + if (key->internal != NULL) { + wc_ecc_free((ecc_key*)key->internal); + XFREE(key->internal, NULL, DYNAMIC_TYPE_ECC); + } + wolfSSL_BN_free(key->priv_key); + wolfSSL_EC_POINT_free(key->pub_key); + wolfSSL_EC_GROUP_free(key->group); + InitwolfSSL_ECKey(key); /* set back to NULLs for safety */ + + XFREE(key, NULL, DYNAMIC_TYPE_ECC); + /* key = NULL, don't try to access or double free it */ + } +} + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group) +{ + (void)key; + (void)group; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group"); + WOLFSSL_STUB("EC_KEY_set_group"); + + return -1; +} +#endif + +int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) +{ + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key"); + + if (key == NULL || key->internal == NULL || + key->group == NULL || key->group->curve_idx < 0) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments"); + return 0; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return 0; +#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; + } + + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + return 0; + } + + if (wc_ecc_make_key_ex(rng, 0, (ecc_key*)key->internal, + 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_RNG); +#endif + return 0; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed"); + return 0; + } + + return 1; +} + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag) +{ + (void)key; + (void)asn1_flag; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag"); + WOLFSSL_STUB("EC_KEY_set_asn1_flag"); +} +#endif + +static int setupPoint(const WOLFSSL_EC_POINT *p) { + if (!p) { + return WOLFSSL_FAILURE; + } + if (p->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + + if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal SetECPointInternal failed"); + return WOLFSSL_FAILURE; + } + } + return WOLFSSL_SUCCESS; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, + const WOLFSSL_EC_POINT *pub) +{ + ecc_point *pub_p, *key_p; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key"); + + if (key == NULL || key->internal == NULL || + pub == NULL || pub->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad arguments"); + return WOLFSSL_FAILURE; + } + + if (key->inSet == 0) { + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FAILURE; + } + } + + if (setupPoint(pub) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + pub_p = (ecc_point*)pub->internal; + key_p = (ecc_point*)key->pub_key->internal; + + /* create new point if required */ + if (key_p == NULL) + key_p = wc_ecc_new_point(); + + if (key_p == NULL) { + WOLFSSL_MSG("key ecc point NULL"); + return WOLFSSL_FAILURE; + } + + if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) { + WOLFSSL_MSG("ecc_copy_point failure"); + return WOLFSSL_FAILURE; + } + + if (SetECPointExternal(key->pub_key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FAILURE; + } + + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FAILURE; + } + + wolfSSL_EC_POINT_dump("pub", pub); + wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key); + + return WOLFSSL_SUCCESS; +} +/* End EC_KEY */ + +int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key) +{ + const EC_GROUP *group; + int bits, bytes; + word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */ + + if (!key) { + return WOLFSSL_FAILURE; + } + + if (!(group = wolfSSL_EC_KEY_get0_group(key))) { + return WOLFSSL_FAILURE; + } + if ((bits = wolfSSL_EC_GROUP_order_bits(group)) == 0) { + return WOLFSSL_FAILURE; + } + bytes = (bits + 7) / 8; /* bytes needed to hold bits */ + return headerSz + + 2 + /* possible leading zeroes in r and s */ + bytes + bytes + /* r and s */ + 2; +} + +int wolfSSL_ECDSA_sign(int type, const unsigned char *digest, + int digestSz, unsigned char *sig, + unsigned int *sigSz, WOLFSSL_EC_KEY *key) +{ + int ret = WOLFSSL_SUCCESS; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + int initTmpRng = 0; + + WOLFSSL_ENTER("wolfSSL_ECDSA_sign"); + + if (!key) { + return WOLFSSL_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FAILURE; +#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; + } + } + if (rng) { + if (wc_ecc_sign_hash(digest, digestSz, sig, sigSz, rng, (ecc_key*)key->internal) != MP_OKAY) { + ret = WOLFSSL_FAILURE; + } + if (initTmpRng) { + wc_FreeRng(tmpRNG); + } + } else { + ret = WOLFSSL_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + if (tmpRNG) + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + (void)type; + return ret; +} + +#ifndef HAVE_SELFTEST +/* ECC point compression types were not included in selftest ecc.h */ + +char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, + const WOLFSSL_EC_POINT* point, int form, + WOLFSSL_BN_CTX* ctx) +{ + static const char* hexDigit = "0123456789ABCDEF"; + char* hex = NULL; + int id; + int i, sz, len; + + (void)ctx; + + if (group == NULL || point == NULL) + return NULL; + + id = wc_ecc_get_curve_id(group->curve_idx); + + if ((sz = wc_ecc_get_curve_size_from_id(id)) < 0) + return NULL; + + len = sz + 1; + if (form == POINT_CONVERSION_UNCOMPRESSED) + len += sz; + + hex = (char*)XMALLOC(2 * len + 1, NULL, DYNAMIC_TYPE_ECC); + if (hex == NULL) + return NULL; + XMEMSET(hex, 0, 2 * len + 1); + + /* Put in x-ordinate after format byte. */ + i = sz - mp_unsigned_bin_size((mp_int*)point->X->internal) + 1; + if (mp_to_unsigned_bin((mp_int*)point->X->internal, (byte*)(hex + i)) < 0) { + XFREE(hex, NULL, DYNAMIC_TYPE_ECC); + return NULL; + } + + if (form == POINT_CONVERSION_COMPRESSED) { + hex[0] = mp_isodd((mp_int*)point->Y->internal) ? ECC_POINT_COMP_ODD : + ECC_POINT_COMP_EVEN; + } + else { + hex[0] = ECC_POINT_UNCOMP; + /* Put in y-ordinate after x-ordinate */ + i = 1 + 2 * sz - mp_unsigned_bin_size((mp_int*)point->Y->internal); + if (mp_to_unsigned_bin((mp_int*)point->Y->internal, + (byte*)(hex + i)) < 0) { + XFREE(hex, NULL, DYNAMIC_TYPE_ECC); + return NULL; + } + } + + for (i = len-1; i >= 0; i--) { + byte b = hex[i]; + hex[i * 2 + 1] = hexDigit[b & 0xf]; + hex[i * 2 ] = hexDigit[b >> 4]; + } + + return hex; +} + +#endif /* HAVE_SELFTEST */ + +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"); + + if (!WOLFSSL_IS_DEBUG_ON() || wolfSSL_GetLoggingCb()) { + return; + } + + if (p == NULL) { + printf("%s = NULL", msg); + return; + } + + printf("%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet); + num = wolfSSL_BN_bn2hex(p->X); + printf("\tX = %s\n", num); + XFREE(num, NULL, DYNAMIC_TYPE_ECC); + num = wolfSSL_BN_bn2hex(p->Y); + 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 */ + +/* return code compliant with OpenSSL : + * 0 if equal, 1 if not and -1 in case of error + */ +int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b, + WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp"); + + if (a == NULL || b == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments"); + return WOLFSSL_FATAL_ERROR; + } + + /* ok */ + if ((a->curve_idx == b->curve_idx) && (a->curve_nid == b->curve_nid)) + return 0; + + /* ko */ + return 1; +} + +#endif /* HAVE_ECC */ +#endif /* OPENSSL_EXTRA */ + +#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of( + const WOLFSSL_EC_GROUP *group) +{ + return group; +} + +int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth) +{ + if (meth) { + return NID_X9_62_prime_field; + } + return WOLFSSL_FAILURE; +} + +void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group) +{ + WOLFSSL_ENTER("wolfSSL_EC_GROUP_free"); + + XFREE(group, NULL, DYNAMIC_TYPE_ECC); + /* group = NULL, don't try to access or double free it */ +} +#endif + +#ifdef OPENSSL_EXTRA +#ifdef HAVE_ECC +#ifndef NO_WOLFSSL_STUB +void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag) +{ + (void)group; + (void)flag; + + WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag"); + WOLFSSL_STUB("EC_GROUP_set_asn1_flag"); +} +#endif + +WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid) +{ + WOLFSSL_EC_GROUP *g; + int x; + int eccEnum; + + WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name"); + + /* If NID passed in is OpenSSL type, convert it to ecc_curve_id enum */ + eccEnum = NIDToEccEnum(nid); + if (eccEnum == -1) + eccEnum = nid; + + + /* curve group */ + g = (WOLFSSL_EC_GROUP*) XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL, + DYNAMIC_TYPE_ECC); + if (g == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure"); + return NULL; + } + XMEMSET(g, 0, sizeof(WOLFSSL_EC_GROUP)); + + /* set the nid of the curve */ + g->curve_nid = eccEnum; + + if (eccEnum > ECC_CURVE_DEF) { + /* search and set the corresponding internal curve idx */ + 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; + } + } + + return g; +} + +/* return code compliant with OpenSSL : + * the curve nid if success, 0 if error + */ +int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group) +{ + int nid; + WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name"); + + if (group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments"); + return WOLFSSL_FAILURE; + } + + /* If curve_nid is ECC Enum type, return corresponding OpenSSL nid */ + if ((nid = EccEnumToNID(group->curve_nid)) != -1) + return nid; + + return group->curve_nid; +} + +/* return code compliant with OpenSSL : + * the degree of the curve if success, 0 if error + */ +int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group) +{ + int nid; + int tmp; + + WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree"); + + if (group == NULL || group->curve_idx < 0) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments"); + return WOLFSSL_FAILURE; + } + + /* If curve_nid passed in is an ecc_curve_id enum, convert it to the + corresponding OpenSSL NID */ + tmp = EccEnumToNID(group->curve_nid); + if (tmp != -1){ + nid = tmp; + } + else{ + nid = group->curve_nid; + } + + switch(nid) { + case NID_secp112r1: + case NID_secp112r2: + return 112; + case NID_secp128r1: + case NID_secp128r2: + return 128; + case NID_secp160k1: + case NID_secp160r1: + case NID_secp160r2: + case NID_brainpoolP160r1: + return 160; + case NID_secp192k1: + case NID_brainpoolP192r1: + case NID_X9_62_prime192v1: + return 192; + case NID_secp224k1: + case NID_secp224r1: + case NID_brainpoolP224r1: + return 224; + case NID_secp256k1: + case NID_brainpoolP256r1: + case NID_X9_62_prime256v1: + return 256; + case NID_brainpoolP320r1: + return 320; + case NID_secp384r1: + case NID_brainpoolP384r1: + return 384; + case NID_secp521r1: + return 521; + case NID_brainpoolP512r1: + return 512; + default: + return WOLFSSL_FAILURE; + } +} + +/* Converts OpenSSL NID value of ECC curves to the associated enum values in + ecc_curve_id, used by ecc_sets[].*/ +int NIDToEccEnum(int n) +{ + WOLFSSL_ENTER("NIDToEccEnum()"); + + switch(n) { + case NID_X9_62_prime192v1: + return ECC_SECP192R1; + case NID_X9_62_prime192v2: + return ECC_PRIME192V2; + case NID_X9_62_prime192v3: + return ECC_PRIME192V3; + case NID_X9_62_prime239v1: + return ECC_PRIME239V1; + case NID_X9_62_prime239v2: + return ECC_PRIME239V2; + case NID_X9_62_prime239v3: + return ECC_PRIME239V3; + case NID_X9_62_prime256v1: + return ECC_SECP256R1; + case NID_secp112r1: + return ECC_SECP112R1; + case NID_secp112r2: + return ECC_SECP112R2; + case NID_secp128r1: + return ECC_SECP128R1; + case NID_secp128r2: + return ECC_SECP128R2; + case NID_secp160r1: + return ECC_SECP160R1; + case NID_secp160r2: + return ECC_SECP160R2; + case NID_secp224r1: + return ECC_SECP224R1; + case NID_secp384r1: + return ECC_SECP384R1; + case NID_secp521r1: + return ECC_SECP521R1; + case NID_secp160k1: + return ECC_SECP160K1; + case NID_secp192k1: + return ECC_SECP192K1; + case NID_secp224k1: + return ECC_SECP224K1; + case NID_secp256k1: + return ECC_SECP256K1; + case NID_brainpoolP160r1: + return ECC_BRAINPOOLP160R1; + case NID_brainpoolP192r1: + return ECC_BRAINPOOLP192R1; + case NID_brainpoolP224r1: + return ECC_BRAINPOOLP224R1; + case NID_brainpoolP256r1: + return ECC_BRAINPOOLP256R1; + case NID_brainpoolP320r1: + return ECC_BRAINPOOLP320R1; + case NID_brainpoolP384r1: + return ECC_BRAINPOOLP384R1; + case NID_brainpoolP512r1: + return ECC_BRAINPOOLP512R1; + default: + WOLFSSL_MSG("NID not found"); + return -1; + } +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group, + WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; + + if (group == NULL || order == NULL || order->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error"); + return WOLFSSL_FAILURE; + } + + if (mp_init((mp_int*)order->internal) != MP_OKAY) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure"); + return WOLFSSL_FAILURE; + } + + if (mp_read_radix((mp_int*)order->internal, + 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 WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group) +{ + int ret; + mp_int order; + + if (group == NULL || group->curve_idx < 0) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_order_bits NULL error"); + return 0; + } + + ret = mp_init(&order); + if (ret == 0) { + ret = mp_read_radix(&order, ecc_sets[group->curve_idx].order, + MP_RADIX_HEX); + if (ret == 0) + ret = mp_count_bits(&order); + mp_clear(&order); + } + + return ret; +} + +/* End EC_GROUP */ + +/* Start EC_POINT */ + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *p, + unsigned char *out, unsigned int *len) +{ + int err; + + WOLFSSL_ENTER("wolfSSL_ECPoint_i2d"); + + if (group == NULL || p == NULL || len == NULL) { + WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error"); + return WOLFSSL_FAILURE; + } + + if (setupPoint(p) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + if (out != NULL) { + wolfSSL_EC_POINT_dump("i2d p", p); + } + + 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 WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len, + const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *p) +{ + WOLFSSL_ENTER("wolfSSL_ECPoint_d2i"); + + if (group == NULL || p == NULL || p->internal == NULL || in == NULL) { + WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error"); + return WOLFSSL_FAILURE; + } + +#ifndef HAVE_SELFTEST + if (wc_ecc_import_point_der_ex(in, len, group->curve_idx, + (ecc_point*)p->internal, 0) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_import_point_der_ex failed"); + return WOLFSSL_FAILURE; + } +#else + /* ECC_POINT_UNCOMP is not defined CAVP self test so use magic number */ + if (in[0] == 0x04) { + 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 WOLFSSL_FAILURE; + } + } + else { + WOLFSSL_MSG("Only uncompressed points supported with HAVE_SELFTEST"); + return WOLFSSL_FAILURE; + } +#endif + + /* Set new external point */ + if (SetECPointExternal(p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointExternal failed"); + return WOLFSSL_FAILURE; + } + + wolfSSL_EC_POINT_dump("d2i p", p); + + return WOLFSSL_SUCCESS; +} + +size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *p, + char form, + byte *buf, size_t len, WOLFSSL_BN_CTX *ctx) +{ + word32 min_len = (word32)len; +#ifndef HAVE_SELFTEST + int compressed = form == POINT_CONVERSION_COMPRESSED ? 1 : 0; +#endif /* !HAVE_SELFTEST */ + + WOLFSSL_ENTER("EC_POINT_point2oct"); + + if (!group || !p) { + return WOLFSSL_FAILURE; + } + + if (setupPoint(p) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + if (wolfSSL_EC_POINT_is_at_infinity(group, p)) { + /* encodes to a single 0 octet */ + if (buf != NULL) { + if (len < 1) { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + return WOLFSSL_FAILURE; + } + buf[0] = 0; + } + return 1; + } + + if (form != POINT_CONVERSION_UNCOMPRESSED +#ifndef HAVE_SELFTEST + && form != POINT_CONVERSION_COMPRESSED +#endif /* !HAVE_SELFTEST */ + ) { + WOLFSSL_MSG("Unsupported curve form"); + return WOLFSSL_FAILURE; + } + +#ifndef HAVE_SELFTEST + if (wc_ecc_export_point_der_ex(group->curve_idx, (ecc_point*)p->internal, + buf, &min_len, compressed) != (buf ? MP_OKAY : LENGTH_ONLY_E)) { + return WOLFSSL_FAILURE; + } +#else + if (wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal, + buf, &min_len) != (buf ? MP_OKAY : LENGTH_ONLY_E)) { + return WOLFSSL_FAILURE; + } +#endif /* !HAVE_SELFTEST */ + + (void)ctx; + + return (size_t)min_len; +} + +int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group, + WOLFSSL_EC_POINT *p, const unsigned char *buf, + size_t len, WOLFSSL_BN_CTX *ctx) +{ + WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point"); + + if (!group || !p) { + return WOLFSSL_FAILURE; + } + + (void)ctx; + + return wolfSSL_ECPoint_d2i((unsigned char*)buf, (unsigned int)len, group, p); +} + +int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *in, unsigned char **out) +{ + size_t len; + unsigned char *tmp = NULL; + char form; + WOLFSSL_ENTER("wolfSSL_i2o_ECPublicKey"); + + if (!in) { + WOLFSSL_MSG("wolfSSL_i2o_ECPublicKey Bad arguments"); + return WOLFSSL_FAILURE; + } + + /* Default to compressed form if not set */ + form = in->form == POINT_CONVERSION_UNCOMPRESSED ? + POINT_CONVERSION_UNCOMPRESSED: + POINT_CONVERSION_COMPRESSED; + + len = wolfSSL_EC_POINT_point2oct(in->group, in->pub_key, form, + NULL, 0, NULL); + + if (len != WOLFSSL_FAILURE && out) { + if (!*out) { + if (!(tmp = (unsigned char*)XMALLOC(len, NULL, + DYNAMIC_TYPE_OPENSSL))) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + *out = tmp; + } + + if (wolfSSL_EC_POINT_point2oct(in->group, in->pub_key, form, *out, + len, NULL) == WOLFSSL_FAILURE) { + if (tmp) { + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + *out = NULL; + } + return WOLFSSL_FAILURE; + } + + if (!tmp) { + /* Move buffer forward if it was not alloced in this function */ + *out += len; + } + } + + return (int)len; +} + +void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *eckey, char form) +{ + if (eckey && (form == POINT_CONVERSION_COMPRESSED || + form == POINT_CONVERSION_UNCOMPRESSED)) { + eckey->form = form; + } +} + + +/* wolfSSL_EC_POINT_point2bn should return "in" if not null */ +WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *p, + char form, + WOLFSSL_BIGNUM *in, WOLFSSL_BN_CTX *ctx) +{ + size_t len; + byte *buf; + WOLFSSL_BIGNUM *ret = NULL; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point"); + + if (!group || !p) { + return NULL; + } + + if ((len = wolfSSL_EC_POINT_point2oct(group, p, form, + NULL, 0, ctx)) == WOLFSSL_FAILURE) { + return NULL; + } + + if (!(buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER))) { + WOLFSSL_MSG("malloc failed"); + return NULL; + } + + if (wolfSSL_EC_POINT_point2oct(group, p, form, + buf, len, ctx) == len) { + ret = wolfSSL_BN_bin2bn(buf, (int)len, in); + } + + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group) +{ + WOLFSSL_EC_POINT *p; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_new"); + + if (group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error"); + return NULL; + } + + p = (WOLFSSL_EC_POINT *)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure"); + return NULL; + } + XMEMSET(p, 0, sizeof(WOLFSSL_EC_POINT)); + + p->internal = wc_ecc_new_point(); + if (p->internal == NULL) { + WOLFSSL_MSG("ecc_new_point failure"); + XFREE(p, NULL, DYNAMIC_TYPE_ECC); + return NULL; + } + + return p; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *point, + WOLFSSL_BIGNUM *x, + WOLFSSL_BIGNUM *y, + WOLFSSL_BN_CTX *ctx) +{ + mp_digit mp; + mp_int modulus; + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp"); + + if (group == NULL || point == NULL || point->internal == NULL || + x == NULL || y == NULL || wolfSSL_EC_POINT_is_at_infinity(group, point)) { + WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error"); + return WOLFSSL_FAILURE; + } + + if (setupPoint(point) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + if (!wolfSSL_BN_is_one(point->Z)) { + if (mp_init(&modulus) != MP_OKAY) { + WOLFSSL_MSG("mp_init failed"); + return WOLFSSL_FAILURE; + } + /* Map the Jacobian point back to affine space */ + if (mp_read_radix(&modulus, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX) != MP_OKAY) { + WOLFSSL_MSG("mp_read_radix failed"); + mp_clear(&modulus); + return WOLFSSL_FAILURE; + } + if (mp_montgomery_setup(&modulus, &mp) != MP_OKAY) { + WOLFSSL_MSG("mp_montgomery_setup failed"); + mp_clear(&modulus); + return WOLFSSL_FAILURE; + } + if (ecc_map((ecc_point*)point->internal, &modulus, mp) != MP_OKAY) { + WOLFSSL_MSG("ecc_map failed"); + mp_clear(&modulus); + return WOLFSSL_FAILURE; + } + if (SetECPointExternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointExternal failed"); + mp_clear(&modulus); + return WOLFSSL_FAILURE; + } + } + + BN_copy(x, point->X); + BN_copy(y, point->Y); + mp_clear(&modulus); + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_EC_POINT_set_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, + WOLFSSL_EC_POINT *point, + const WOLFSSL_BIGNUM *x, + const WOLFSSL_BIGNUM *y, + WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; + WOLFSSL_ENTER("wolfSSL_EC_POINT_set_affine_coordinates_GFp"); + + if (group == NULL || point == NULL || point->internal == NULL || + x == NULL || y == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp NULL error"); + return WOLFSSL_FAILURE; + } + + if (!point->X) { + point->X = wolfSSL_BN_new(); + } + if (!point->Y) { + point->Y = wolfSSL_BN_new(); + } + if (!point->Z) { + point->Z = wolfSSL_BN_new(); + } + if (!point->X || !point->Y || !point->Z) { + WOLFSSL_MSG("wolfSSL_BN_new failed"); + return WOLFSSL_FAILURE; + } + + BN_copy(point->X, x); + BN_copy(point->Y, y); + BN_copy(point->Z, wolfSSL_BN_value_one()); + + if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal failed"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +#if !defined(WOLFSSL_ATECC508A) && !defined(HAVE_SELFTEST) +/* Calculate the value: generator * n + q * m + * return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, + const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q, + const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +{ + mp_int a, prime; + int ret = WOLFSSL_FAILURE; + ecc_point* result = NULL; + ecc_point* tmp = NULL; + + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_mul"); + + if (!group || !r) { + WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error"); + return WOLFSSL_FAILURE; + } + + if (!(result = wc_ecc_new_point())) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new error"); + return WOLFSSL_FAILURE; + } + + /* read the curve prime and a */ + if (mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL) != MP_OKAY) { + WOLFSSL_MSG("mp_init_multi error"); + goto cleanup; + } + + if (q && setupPoint(q) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("setupPoint error"); + goto cleanup; + } + + if (mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX) + != MP_OKAY) { + WOLFSSL_MSG("mp_read_radix prime error"); + goto cleanup; + } + + if (mp_read_radix(&a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX) + != MP_OKAY) { + WOLFSSL_MSG("mp_read_radix a error"); + goto cleanup; + } + + if (n) { + /* load generator */ + if (wc_ecc_get_generator(result, group->curve_idx) + != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_get_generator error"); + goto cleanup; + } + } + + if (n && q && m) { + /* r = generator * n + q * m */ +#ifdef ECC_SHAMIR + if (ecc_mul2add(result, (mp_int*)n->internal, + (ecc_point*)q->internal, (mp_int*)m->internal, + result, &a, &prime, NULL) + != MP_OKAY) { + WOLFSSL_MSG("ecc_mul2add error"); + goto cleanup; + } +#else + mp_digit mp = 0; + if (mp_montgomery_setup(&prime, &mp) != MP_OKAY) { + WOLFSSL_MSG("mp_montgomery_setup nqm error"); + goto cleanup; + } + if (!(tmp = wc_ecc_new_point())) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new nqm error"); + goto cleanup; + } + /* r = generator * n */ + if (wc_ecc_mulmod((mp_int*)n->internal, result, result, &a, &prime, 1) + != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_mulmod nqm error"); + goto cleanup; + } + /* tmp = q * m */ + if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, + tmp, &a, &prime, 1) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_mulmod nqm error"); + goto cleanup; + } + /* result = result + tmp */ + if (ecc_projective_add_point(tmp, result, result, &a, &prime, mp) + != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_mulmod nqm error"); + goto cleanup; + } + if (ecc_map(result, &prime, mp) != MP_OKAY) { + WOLFSSL_MSG("ecc_map nqm error"); + goto cleanup; + } +#endif + } + else if (n) { + /* r = generator * n */ + if (wc_ecc_mulmod((mp_int*)n->internal, result, result, &a, &prime, 1) + != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_mulmod gn error"); + goto cleanup; + } + } + else if (q && m) { + /* r = q * m */ + if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, + result, &a, &prime, 1) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_mulmod qm error"); + goto cleanup; + } + } + + /* copy to destination */ + if (wc_ecc_copy_point(result, (ecc_point*)r->internal)) { + WOLFSSL_MSG("wc_ecc_copy_point error"); + goto cleanup; + } + r->inSet = 1; + if (SetECPointExternal(r) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointExternal error"); + goto cleanup; + } + + ret = WOLFSSL_SUCCESS; +cleanup: + mp_clear(&a); + mp_clear(&prime); + wc_ecc_del_point(result); + wc_ecc_del_point(tmp); + return ret; +} +#endif /* !defined(WOLFSSL_ATECC508A) && defined(ECC_SHAMIR) && + * !defined(HAVE_SELFTEST) */ + +void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p) +{ + WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free"); + + wolfSSL_EC_POINT_free(p); +} + +/* return code compliant with OpenSSL : + * 0 if equal, 1 if not and -1 in case of error + */ +int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, + WOLFSSL_BN_CTX *ctx) +{ + int ret; + + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp"); + + if (group == NULL || a == NULL || a->internal == NULL || b == NULL || + b->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments"); + return WOLFSSL_FATAL_ERROR; + } + + ret = wc_ecc_cmp_point((ecc_point*)a->internal, (ecc_point*)b->internal); + if (ret == MP_EQ) + return 0; + else if (ret == MP_LT || ret == MP_GT) + return 1; + + return WOLFSSL_FATAL_ERROR; +} + +int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src) +{ + WOLFSSL_ENTER("wolfSSL_EC_POINT_copy"); + + if (!dest || !src) { + return WOLFSSL_FAILURE; + } + + if (setupPoint(src) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + if (wc_ecc_copy_point((ecc_point*) dest->internal, + (ecc_point*) src->internal) != MP_OKAY) { + return WOLFSSL_FAILURE; + } + + dest->inSet = 1; + + if (SetECPointExternal(dest) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_ECC */ +#endif /* OPENSSL_EXTRA */ + +#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p) +{ + WOLFSSL_ENTER("wolfSSL_EC_POINT_free"); + + if (p != NULL) { + if (p->internal != NULL) { + wc_ecc_del_point((ecc_point*)p->internal); + p->internal = NULL; + } + + wolfSSL_BN_free(p->X); + wolfSSL_BN_free(p->Y); + wolfSSL_BN_free(p->Z); + p->X = NULL; + p->Y = NULL; + p->Z = NULL; + p->inSet = p->exSet = 0; + + XFREE(p, NULL, DYNAMIC_TYPE_ECC); + /* p = NULL, don't try to access or double free it */ + } +} +#endif + +#ifdef OPENSSL_EXTRA +#ifdef HAVE_ECC +/* return code compliant with OpenSSL : + * 1 if point at infinity, 0 else + */ +int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *point) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity"); + + if (group == NULL || point == NULL || point->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error"); + return WOLFSSL_FAILURE; + } + + if (setupPoint(point) != WOLFSSL_SUCCESS) { + 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 WOLFSSL_FAILURE; + } + + return ret; +} + +/* End EC_POINT */ + +size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *r, size_t nitems) +{ + size_t i, min_nitems; +#ifdef HAVE_SELFTEST + size_t ecc_sets_count; + for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++); + ecc_sets_count = i; +#endif + + if (r == NULL || nitems == 0) + return ecc_sets_count; + + min_nitems = nitems < ecc_sets_count ? nitems : ecc_sets_count; + + for (i = 0; i < min_nitems; i++) { + r[i].nid = EccEnumToNID(ecc_sets[i].id); + r[i].comment = wolfSSL_OBJ_nid2sn(r[i].nid); + } + + return ecc_sets_count; +} + +/* Start ECDSA_SIG */ +void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig) +{ + WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free"); + + if (sig) { + wolfSSL_BN_free(sig->r); + wolfSSL_BN_free(sig->s); + + XFREE(sig, NULL, DYNAMIC_TYPE_ECC); + } +} + +WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void) +{ + WOLFSSL_ECDSA_SIG *sig; + + WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new"); + + sig = (WOLFSSL_ECDSA_SIG*) XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL, + DYNAMIC_TYPE_ECC); + if (sig == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure"); + return NULL; + } + + sig->s = NULL; + sig->r = wolfSSL_BN_new(); + if (sig->r == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure"); + wolfSSL_ECDSA_SIG_free(sig); + return NULL; + } + + sig->s = wolfSSL_BN_new(); + if (sig->s == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure"); + wolfSSL_ECDSA_SIG_free(sig); + return NULL; + } + + return sig; +} + +/* return signature structure on success, NULL otherwise */ +WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen, + WOLFSSL_EC_KEY *key) +{ + WOLFSSL_ECDSA_SIG *sig = NULL; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign"); + + if (d == NULL || key == NULL || key->internal == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments"); + return NULL; + } + + /* set internal key if not done */ + if (key->inSet == 0) + { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it"); + + 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_RNG); + if (tmpRNG == NULL) + return NULL; +#endif + + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Global RNG no Init"); + else + rng = &globalRNG; + } + + if (rng) { + mp_int sig_r, sig_s; + + if (mp_init_multi(&sig_r, &sig_s, NULL, NULL, NULL, NULL) == MP_OKAY) { + if (wc_ecc_sign_hash_ex(d, dlen, rng, (ecc_key*)key->internal, + &sig_r, &sig_s) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_sign_hash_ex failed"); + } + else { + /* put signature blob in ECDSA structure */ + sig = wolfSSL_ECDSA_SIG_new(); + if (sig == NULL) + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new failed"); + 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)!=WOLFSSL_SUCCESS){ + WOLFSSL_MSG("ecdsa s key error"); + wolfSSL_ECDSA_SIG_free(sig); + sig = NULL; + } + + } + mp_free(&sig_r); + mp_free(&sig_s); + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return sig; +} + +/* return code compliant with OpenSSL : + * 1 for a valid signature, 0 for an invalid signature and -1 on error + */ +int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen, + const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key) +{ + int check_sign = 0; + + WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify"); + + if (d == NULL || sig == NULL || key == NULL || key->internal == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments"); + return WOLFSSL_FATAL_ERROR; + } + + /* set internal key if not done */ + if (key->inSet == 0) + { + WOLFSSL_MSG("No EC key internal set, do it"); + + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FATAL_ERROR; + } + } + + if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal, + (mp_int*)sig->s->internal, d, dlen, &check_sign, + (ecc_key *)key->internal) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_verify_hash failed"); + return WOLFSSL_FATAL_ERROR; + } + else if (check_sign == 0) { + WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +WOLFSSL_ECDSA_SIG *wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG **sig, + const unsigned char **pp, long len) +{ + WOLFSSL_ECDSA_SIG *s = NULL; + + if (pp == NULL) + return NULL; + + if (sig != NULL) + s = *sig; + if (s == NULL) { + s = wolfSSL_ECDSA_SIG_new(); + if (s == NULL) + return NULL; + } + + /* DecodeECC_DSA_Sig calls mp_init, so free these */ + mp_free((mp_int*)s->r->internal); + mp_free((mp_int*)s->s->internal); + + if (DecodeECC_DSA_Sig(*pp, (word32)len, (mp_int*)s->r->internal, + (mp_int*)s->s->internal) != MP_OKAY) { + if (sig == NULL || *sig == NULL) + wolfSSL_ECDSA_SIG_free(s); + return NULL; + } + + *pp += len; + if (sig != NULL) + *sig = s; + return s; +} + +int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp) +{ + word32 len; + + if (sig == NULL) + return 0; + + /* ASN.1: SEQ + INT + INT + * ASN.1 Integer must be a positive value - prepend zero if number has + * top bit set. + */ + len = 2 + mp_leading_bit((mp_int*)sig->r->internal) + + mp_unsigned_bin_size((mp_int*)sig->r->internal) + + 2 + mp_leading_bit((mp_int*)sig->s->internal) + + mp_unsigned_bin_size((mp_int*)sig->s->internal); + /* Two bytes required for length if ASN.1 SEQ data greater than 127 bytes + * and less than 256 bytes. + */ + len = 1 + ((len > 127) ? 2 : 1) + len; + if (pp != NULL && *pp != NULL) { + if (StoreECC_DSA_Sig(*pp, &len, (mp_int*)sig->r->internal, + (mp_int*)sig->s->internal) != MP_OKAY) { + len = 0; + } + else + *pp += len; + } + + return (int)len; +} +/* End ECDSA_SIG */ + +/* Start ECDH */ +/* return code compliant with OpenSSL : + * length of computed key if success, -1 if error + */ +int wolfSSL_ECDH_compute_key(void *out, size_t outlen, + const WOLFSSL_EC_POINT *pub_key, + WOLFSSL_EC_KEY *ecdh, + void *(*KDF) (const void *in, size_t inlen, + void *out, size_t *outlen)) +{ + word32 len; + (void)KDF; + + (void)KDF; + + WOLFSSL_ENTER("wolfSSL_ECDH_compute_key"); + + if (out == NULL || pub_key == NULL || pub_key->internal == NULL || + ecdh == NULL || ecdh->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FATAL_ERROR; + } + + /* set internal key if not done */ + if (ecdh->inSet == 0) + { + WOLFSSL_MSG("No EC key internal set, do it"); + + if (SetECKeyInternal(ecdh) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FATAL_ERROR; + } + } + + len = (word32)outlen; + + if (wc_ecc_shared_secret_ssh((ecc_key*)ecdh->internal, + (ecc_point*)pub_key->internal, + (byte *)out, &len) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_shared_secret failed"); + return WOLFSSL_FATAL_ERROR; + } + + return len; +} +/* End ECDH */ + +#if !defined(NO_FILESYSTEM) +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY *x) +{ + (void)fp; + (void)x; + WOLFSSL_STUB("PEM_write_EC_PUBKEY"); + WOLFSSL_MSG("wolfSSL_PEM_write_EC_PUBKEY not implemented"); + + return WOLFSSL_FAILURE; +} +#endif + +/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects + * the results to be an EC key. + * + * bio structure to read EC private key from + * ec if not null is then set to the result + * cb password callback for reading PEM + * pass password string + * + * returns a pointer to a new WOLFSSL_EC_KEY struct on success and NULL on fail + */ + +WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio, + WOLFSSL_EC_KEY** ec, + pem_password_cb* cb, void *pass) +{ + WOLFSSL_EVP_PKEY* pkey; + WOLFSSL_EC_KEY* local; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY"); + + pkey = wolfSSL_PEM_read_bio_PUBKEY(bio, NULL, cb, pass); + if (pkey == NULL) { + return NULL; + } + + /* Since the WOLFSSL_EC_KEY structure is being taken from WOLFSSL_EVP_PKEY the + * flag indicating that the WOLFSSL_EC_KEY structure is owned should be FALSE + * to avoid having it free'd */ + pkey->ownEcc = 0; + local = pkey->ecc; + if (ec != NULL) { + *ec = local; + } + + wolfSSL_EVP_PKEY_free(pkey); + return local; +} + +/* Reads a private EC key from a WOLFSSL_BIO into a WOLFSSL_EC_KEY. + * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE + */ +WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_ECPrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EC_KEY** ec, + pem_password_cb* cb, + void *pass) +{ + WOLFSSL_EVP_PKEY* pkey; + WOLFSSL_EC_KEY* local; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_ECPrivateKey"); + + pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass); + if (pkey == NULL) { + return NULL; + } + + /* Since the WOLFSSL_EC_KEY structure is being taken from WOLFSSL_EVP_PKEY the + * flag indicating that the WOLFSSL_EC_KEY structure is owned should be FALSE + * to avoid having it free'd */ + pkey->ownEcc = 0; + local = pkey->ecc; + if (ec != NULL) { + *ec = local; + } + + wolfSSL_EVP_PKEY_free(pkey); + return local; +} +#endif /* NO_FILESYSTEM */ + +#if defined(WOLFSSL_KEY_GEN) +/* Takes a public WOLFSSL_EC_KEY and writes it out to WOLFSSL_BIO + * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE + */ +int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec) +{ + int ret = 0, der_max_len = 0, derSz = 0; + byte *derBuf; + WOLFSSL_EVP_PKEY* pkey; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_EC_PUBKEY"); + + if (bio == NULL || ec == NULL) { + WOLFSSL_MSG("Bad Function Arguments"); + return WOLFSSL_FAILURE; + } + + /* Initialize pkey structure */ + pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap); + if (pkey == NULL) { + WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed"); + return WOLFSSL_FAILURE; + } + + /* Set pkey info */ + pkey->ecc = ec; + pkey->ownEcc = 0; /* pkey does not own ECC */ + pkey->type = EVP_PKEY_EC; + + /* 4 > size of pub, priv + ASN.1 additional information */ + der_max_len = 4 * wc_ecc_size((ecc_key*)ec->internal) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(der_max_len, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("Malloc failed"); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + + /* convert key to der format */ + derSz = wc_EccPublicKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len, 1); + if (derSz < 0) { + WOLFSSL_MSG("wc_EccPublicKeyToDer failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + + pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pkey->pkey.ptr == NULL) { + WOLFSSL_MSG("key malloc failed"); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + + /* add der info to the evp key */ + pkey->pkey_sz = derSz; + XMEMCPY(pkey->pkey.ptr, derBuf, derSz); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + + if((ret = wolfSSL_PEM_write_bio_PUBKEY(bio, pkey)) != WOLFSSL_SUCCESS){ + WOLFSSL_MSG("wolfSSL_PEM_write_bio_PUBKEY failed"); + } + wolfSSL_EVP_PKEY_free(pkey); + + return ret; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) +{ + int ret = 0, der_max_len = 0, derSz = 0; + byte *derBuf; + WOLFSSL_EVP_PKEY* pkey; + WOLFSSL_ENTER("WOLFSSL_PEM_write_bio_ECPrivateKey"); + + if (bio == NULL || ec == NULL) { + WOLFSSL_MSG("Bad Function Arguments"); + return WOLFSSL_FAILURE; + } + + /* Initialize pkey structure */ + pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap); + if (pkey == NULL) { + WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed"); + return WOLFSSL_FAILURE; + } + + /* Set pkey info */ + pkey->ecc = ec; + pkey->ownEcc = 0; /* pkey does not own ECC */ + pkey->type = EVP_PKEY_EC; + + /* 4 > size of pub, priv + ASN.1 additional informations + */ + der_max_len = 4 * wc_ecc_size((ecc_key*)ec->internal) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(der_max_len, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("Malloc failed"); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + + /* convert key to der format */ + derSz = wc_EccKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len); + if (derSz < 0) { + WOLFSSL_MSG("wc_EccKeyToDer failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + + pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pkey->pkey.ptr == NULL) { + WOLFSSL_MSG("key malloc failed"); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + + /* add der info to the evp key */ + pkey->pkey_sz = derSz; + XMEMCPY(pkey->pkey.ptr, derBuf, derSz); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + + ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len, + cb, arg); + wolfSSL_EVP_PKEY_free(pkey); + + return ret; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, + const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, + unsigned char **pem, int *plen) +{ +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + byte *derBuf, *tmp, *cipherInfo = NULL; + int der_max_len = 0, derSz = 0; + const int type = ECC_PRIVATEKEY_TYPE; + const char* header = NULL; + const char* footer = NULL; + + WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey"); + + if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + if (wc_PemGetHeaderFooter(type, &header, &footer) != 0) + return WOLFSSL_FAILURE; + + if (ecc->inSet == 0) { + WOLFSSL_MSG("No ECC internal set, do it"); + + if (SetECKeyInternal(ecc) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FAILURE; + } + } + + /* 4 > size of pub, priv + ASN.1 additional information */ + der_max_len = 4 * wc_ecc_size((ecc_key*)ecc->internal) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + + /* Key to DER */ + derSz = wc_EccKeyToDer((ecc_key*)ecc->internal, derBuf, der_max_len); + if (derSz < 0) { + WOLFSSL_MSG("wc_EccKeyToDer failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return WOLFSSL_FAILURE; + } + + /* encrypt DER buffer if required */ + if (passwd != NULL && passwdSz > 0 && cipher != NULL) { + int ret; + + ret = EncryptDerKey(derBuf, &derSz, cipher, + passwd, passwdSz, &cipherInfo); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("EncryptDerKey failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return ret; + } + + /* tmp buffer with a max size */ + *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE; + } + else { /* tmp buffer with a max size */ + *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + (int)XSTRLEN(footer) + 1; + } + + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM); + if (tmp == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + + /* DER to PEM */ + *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type); + if (*plen <= 0) { + WOLFSSL_MSG("wc_DerToPemEx failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + if (cipherInfo != NULL) + 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_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_PEM); + return WOLFSSL_FAILURE; + } + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + + return WOLFSSL_SUCCESS; +#else + (void)ecc; + (void)cipher; + (void)passwd; + (void)passwdSz; + (void)pem; + (void)plen; + return WOLFSSL_FAILURE; +#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ +} + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ecc, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + byte *pem; + int plen, ret; + + (void)cb; + (void)u; + + WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey"); + + if (fp == XBADFILE || ecc == NULL || ecc->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed"); + return WOLFSSL_FAILURE; + } + + ret = (int)XFWRITE(pem, plen, 1, fp); + if (ret != 1) { + WOLFSSL_MSG("ECC private key file write failed"); + return WOLFSSL_FAILURE; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + return WOLFSSL_SUCCESS; +} + +#endif /* NO_FILESYSTEM */ +#endif /* defined(WOLFSSL_KEY_GEN) */ + +#endif /* HAVE_ECC */ + + +#ifndef NO_DSA + +#if defined(WOLFSSL_KEY_GEN) + +/* Takes a DSA Privatekey and writes it out to a WOLFSSL_BIO + * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE + */ +int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) +{ + int ret = 0, der_max_len = 0, derSz = 0; + byte *derBuf; + WOLFSSL_EVP_PKEY* pkey; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_DSAPrivateKey"); + + if (bio == NULL || dsa == NULL) { + WOLFSSL_MSG("Bad Function Arguments"); + return WOLFSSL_FAILURE; + } + + pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap); + if (pkey == NULL) { + WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed"); + return WOLFSSL_FAILURE; + } + + pkey->type = EVP_PKEY_DSA; + pkey->dsa = dsa; + pkey->ownDsa = 0; + + /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */ + der_max_len = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(der_max_len, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("Malloc failed"); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + + /* convert key to der format */ + derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, der_max_len); + if (derSz < 0) { + WOLFSSL_MSG("wc_DsaKeyToDer failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + + pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pkey->pkey.ptr == NULL) { + WOLFSSL_MSG("key malloc failed"); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + + /* add der info to the evp key */ + pkey->pkey_sz = derSz; + XMEMCPY(pkey->pkey.ptr, derBuf, derSz); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + + ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len, + cb, arg); + wolfSSL_EVP_PKEY_free(pkey); + + return ret; +} + +#ifndef HAVE_SELFTEST +/* Takes a DSA public key and writes it out to a WOLFSSL_BIO + * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE + */ +int wolfSSL_PEM_write_bio_DSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa) +{ + int ret = 0, derMax = 0, derSz = 0; + byte *derBuf; + WOLFSSL_EVP_PKEY* pkey; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_DSA_PUBKEY"); + + if (bio == NULL || dsa == NULL) { + WOLFSSL_MSG("Bad function arguements"); + return WOLFSSL_FAILURE; + } + + pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap); + if (pkey == NULL) { + WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed"); + return WOLFSSL_FAILURE; + } + + pkey->type = EVP_PKEY_DSA; + pkey->dsa = dsa; + pkey->ownDsa = 0; + + /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */ + derMax = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(derMax, bio->heap, DYNAMIC_TYPE_DER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + + /* Key to DER */ + derSz = wc_DsaKeyToPublicDer((DsaKey*)dsa->internal, derBuf, derMax); + if (derSz < 0) { + WOLFSSL_MSG("wc_DsaKeyToDer failed"); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + + pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_DER); + + if (pkey->pkey.ptr == NULL) { + WOLFSSL_MSG("key malloc failed"); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + pkey->pkey_sz = derSz; + XMEMSET(pkey->pkey.ptr, 0, derSz); + + if (XMEMCPY(pkey->pkey.ptr, derBuf, derSz) == NULL) { + WOLFSSL_MSG("XMEMCPY failed"); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER); + XFREE(pkey->pkey.ptr, bio->heap, DYNAMIC_TYPE_DER); + wolfSSL_EVP_PKEY_free(pkey); + return WOLFSSL_FAILURE; + } + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER); + ret = wolfSSL_PEM_write_bio_PUBKEY(bio, pkey); + wolfSSL_EVP_PKEY_free(pkey); + return ret; +} +#endif /* HAVE_SELFTEST */ + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, + const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, + unsigned char **pem, int *plen) +{ +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + byte *derBuf, *tmp, *cipherInfo = NULL; + int der_max_len = 0, derSz = 0; + const int type = DSA_PRIVATEKEY_TYPE; + const char* header = NULL; + const char* footer = NULL; + + WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey"); + + if (pem == NULL || plen == NULL || dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + if (wc_PemGetHeaderFooter(type, &header, &footer) != 0) + return WOLFSSL_FAILURE; + + if (dsa->inSet == 0) { + WOLFSSL_MSG("No DSA internal set, do it"); + + if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return WOLFSSL_FAILURE; + } + } + + /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */ + der_max_len = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + 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_DER); + return WOLFSSL_FAILURE; + } + + /* encrypt DER buffer if required */ + if (passwd != NULL && passwdSz > 0 && cipher != NULL) { + int ret; + + ret = EncryptDerKey(derBuf, &derSz, cipher, + passwd, passwdSz, &cipherInfo); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("EncryptDerKey failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return ret; + } + + /* tmp buffer with a max size */ + *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE; + } + else { /* tmp buffer with a max size */ + *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + (int)XSTRLEN(footer) + 1; + } + + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM); + if (tmp == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + + /* DER to PEM */ + *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type); + if (*plen <= 0) { + WOLFSSL_MSG("wc_DerToPemEx failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + if (cipherInfo != NULL) + 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_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_PEM); + return WOLFSSL_FAILURE; + } + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + + return WOLFSSL_SUCCESS; +#else + (void)dsa; + (void)cipher; + (void)passwd; + (void)passwdSz; + (void)pem; + (void)plen; + return WOLFSSL_FAILURE; +#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ +} + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_DSAPrivateKey(XFILE fp, WOLFSSL_DSA *dsa, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + byte *pem; + int plen, ret; + + (void)cb; + (void)u; + + WOLFSSL_MSG("wolfSSL_PEM_write_DSAPrivateKey"); + + if (fp == XBADFILE || dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, enc, kstr, klen, &pem, &plen); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey failed"); + return WOLFSSL_FAILURE; + } + + ret = (int)XFWRITE(pem, plen, 1, fp); + if (ret != 1) { + WOLFSSL_MSG("DSA private key file write failed"); + return WOLFSSL_FAILURE; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + return WOLFSSL_SUCCESS; +} + +#endif /* NO_FILESYSTEM */ +#endif /* defined(WOLFSSL_KEY_GEN) */ + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_PEM_write_DSA_PUBKEY(XFILE fp, WOLFSSL_DSA *x) +{ + (void)fp; + (void)x; + WOLFSSL_STUB("PEM_write_DSA_PUBKEY"); + WOLFSSL_MSG("wolfSSL_PEM_write_DSA_PUBKEY not implemented"); + + return WOLFSSL_FAILURE; +} +#endif +#endif /* NO_FILESYSTEM */ + +#endif /* #ifndef NO_DSA */ + +static int pem_read_bio_key(WOLFSSL_BIO* bio, pem_password_cb* cb, void* pass, + int keyType, int* eccFlag, DerBuffer** der) +{ +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; +#else + EncryptedInfo info[1]; +#endif /* WOLFSSL_SMALL_STACK */ + pem_password_cb* localCb = NULL; + char* mem = NULL; + int memSz = 0; + int ret; + + if(cb) { + localCb = cb; + } else { + if(pass) { + localCb = wolfSSL_PEM_def_callback; + } + } + + if ((ret = wolfSSL_BIO_pending(bio)) > 0) { + memSz = ret; + mem = (char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (mem == NULL) { + WOLFSSL_MSG("Memory error"); + ret = MEMORY_E; + } + if (ret >= 0) { + if ((ret = wolfSSL_BIO_read(bio, mem, memSz)) <= 0) { + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + mem = NULL; + ret = MEMORY_E; + } + } + } + else if (bio->type == WOLFSSL_BIO_FILE) { + int sz = 100; /* read from file by 100 byte chunks */ + int idx = 0; + char* tmp = (char*)XMALLOC(sz, bio->heap, DYNAMIC_TYPE_OPENSSL); + memSz = 0; + if (tmp == NULL) { + WOLFSSL_MSG("Memory error"); + ret = MEMORY_E; + } + + while (ret >= 0 && (sz = wolfSSL_BIO_read(bio, tmp, sz)) > 0) { + char* newMem; + if (memSz + sz < 0) { + /* sanity check */ + break; + } + newMem = (char*)XREALLOC(mem, memSz + sz, bio->heap, + DYNAMIC_TYPE_OPENSSL); + if (newMem == NULL) { + WOLFSSL_MSG("Memory error"); + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + mem = NULL; + XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL); + tmp = NULL; + ret = MEMORY_E; + break; + } + mem = newMem; + XMEMCPY(mem + idx, tmp, sz); + memSz += sz; + idx += sz; + sz = 100; /* read another 100 byte chunk from file */ + } + XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL); + tmp = NULL; + if (memSz <= 0) { + WOLFSSL_MSG("No data to read from bio"); + if (mem != NULL) { + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + mem = NULL; + } + ret = BUFFER_E; + } + } + else { + WOLFSSL_MSG("No data to read from bio"); + ret = NOT_COMPILED_IN; + } + +#ifdef WOLFSSL_SMALL_STACK + if (ret >= 0) { + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (info == NULL) { + WOLFSSL_MSG("Error getting memory for EncryptedInfo structure"); + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + mem = NULL; + ret = MEMORY_E; + } + } +#endif + + if (ret >= 0) { + XMEMSET(info, 0, sizeof(EncryptedInfo)); + info->passwd_cb = localCb; + info->passwd_userdata = pass; + ret = PemToDer((const unsigned char*)mem, memSz, keyType, der, + NULL, info, eccFlag); + + if (ret < 0) { + WOLFSSL_MSG("Bad Pem To Der"); + } + else { + /* write left over data back to bio */ + if ((memSz - (int)info->consumed) > 0 && + bio->type != WOLFSSL_BIO_FILE) { + if (wolfSSL_BIO_write(bio, mem + (int)info->consumed, + memSz - (int)info->consumed) <= 0) { + WOLFSSL_MSG("Unable to advance bio read pointer"); + } + } + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + + return ret; +} + +WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** key, + pem_password_cb* cb, + void* pass) +{ + WOLFSSL_EVP_PKEY* pkey = NULL; + DerBuffer* der = NULL; + int keyFormat = 0; + int type = -1; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PrivateKey"); + + if (bio == NULL) + return pkey; + + if (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE, &keyFormat, + &der) >= 0) { + const unsigned char* ptr = der->buffer; + + if (keyFormat) { + /* keyFormat is Key_Sum enum */ + if (keyFormat == RSAk) + type = EVP_PKEY_RSA; + else if (keyFormat == ECDSAk) + type = EVP_PKEY_EC; + else if (keyFormat == DSAk) + type = EVP_PKEY_DSA; + else if (keyFormat == DHk) + type = EVP_PKEY_DH; + } + else { + /* Default to RSA if format is not set */ + type = EVP_PKEY_RSA; + } + + /* handle case where reuse is attempted */ + if (key != NULL && *key != NULL) + pkey = *key; + + wolfSSL_d2i_PrivateKey(type, &pkey, &ptr, der->length); + if (pkey == NULL) { + WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY"); + } + } + + FreeDer(&der); + + if (key != NULL && pkey != NULL) + *key = pkey; + + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PrivateKey", 0); + + return pkey; +} + +WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_bio_PUBKEY(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY **key, + pem_password_cb *cb, void *pass) +{ + WOLFSSL_EVP_PKEY* pkey = NULL; + DerBuffer* der = NULL; + int keyFormat = 0; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PUBKEY"); + + if (bio == NULL) + return pkey; + + if (pem_read_bio_key(bio, cb, pass, PUBLICKEY_TYPE, &keyFormat, &der) >= 0) { + const unsigned char* ptr = der->buffer; + + /* handle case where reuse is attempted */ + if (key != NULL && *key != NULL) + pkey = *key; + + wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length); + if (pkey == NULL) { + WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY"); + } + } + + FreeDer(&der); + + if (key != NULL && pkey != NULL) + *key = pkey; + + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PUBKEY", 0); + + return pkey; +} + + +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) +/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects + * the results to be an RSA key. + * + * bio structure to read RSA private key from + * rsa if not null is then set to the result + * cb password callback for reading PEM + * pass password string + * + * returns a pointer to a new WOLFSSL_RSA structure on success and NULL on fail + */ +WOLFSSL_RSA* wolfSSL_PEM_read_bio_RSAPrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_RSA** rsa, pem_password_cb* cb, void* pass) +{ + WOLFSSL_EVP_PKEY* pkey; + WOLFSSL_RSA* local; + + WOLFSSL_ENTER("PEM_read_bio_RSAPrivateKey"); + + pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass); + if (pkey == NULL) { + return NULL; + } + + /* Since the WOLFSSL_RSA structure is being taken from WOLFSSL_EVP_PEKY the + * flag indicating that the WOLFSSL_RSA structure is owned should be FALSE + * to avoid having it free'd */ + pkey->ownRsa = 0; + local = pkey->rsa; + if (rsa != NULL) { + *rsa = local; + } + + wolfSSL_EVP_PKEY_free(pkey); + return local; +} +#endif /* OPENSSL_EXTRA || OPENSSL_ALL || !NO_RSA */ + +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && (!defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_DSA) && defined(WOLFSSL_KEY_GEN)) +/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects + * the results to be an DSA key. + * + * bio structure to read DSA private key from + * dsa if not null is then set to the result + * cb password callback for reading PEM + * pass password string + * + * returns a pointer to a new WOLFSSL_DSA structure on success and NULL on fail + */ +WOLFSSL_DSA* wolfSSL_PEM_read_bio_DSAPrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_DSA** dsa, + pem_password_cb* cb,void *pass) +{ + WOLFSSL_EVP_PKEY* pkey = NULL; + WOLFSSL_DSA* local; + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSAPrivateKey"); + + + pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass); + if (pkey == NULL) { + WOLFSSL_MSG("Error in PEM_read_bio_PrivateKey"); + return NULL; + } + /* Since the WOLFSSL_DSA structure is being taken from WOLFSSL_EVP_PKEY the + * flag indicating that the WOLFSSL_DSA structure is owned should be FALSE + * to avoid having it free'd */ + pkey->ownDsa = 0; + local = pkey->dsa; + if (dsa != NULL) { + *dsa = local; + } + wolfSSL_EVP_PKEY_free(pkey); + return local; +} + +/* Reads an DSA public key from a WOLFSSL_BIO into a WOLFSSL_DSA. + * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE + */ +WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSA_PUBKEY(WOLFSSL_BIO* bio,WOLFSSL_DSA** dsa, + pem_password_cb* cb, void *pass) +{ + WOLFSSL_EVP_PKEY* pkey; + WOLFSSL_DSA* local; + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSA_PUBKEY"); + + pkey = wolfSSL_PEM_read_bio_PUBKEY(bio, NULL, cb, pass); + if (pkey == NULL) { + WOLFSSL_MSG("wolfSSL_PEM_read_bio_PUBKEY failed"); + return NULL; + } + + /* Since the WOLFSSL_DSA structure is being taken from WOLFSSL_EVP_PKEY the + * flag indicating that the WOLFSSL_DSA structure is owned should be FALSE + * to avoid having it free'd */ + pkey->ownDsa = 0; + local = pkey->dsa; + if (dsa != NULL) { + *dsa = local; + } + + wolfSSL_EVP_PKEY_free(pkey); + return local; +} +#endif + +#ifdef HAVE_ECC +/* returns a new WOLFSSL_EC_GROUP structure on success and NULL on fail */ +WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio, + WOLFSSL_EC_GROUP** group, pem_password_cb* cb, void* pass) +{ + WOLFSSL_EVP_PKEY* pkey; + WOLFSSL_EC_GROUP* ret = NULL; + + /* check on if bio is null is done in wolfSSL_PEM_read_bio_PrivateKey */ + pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass); + if (pkey != NULL) { + if (pkey->type != EVP_PKEY_EC) { + WOLFSSL_MSG("Unexpected key type"); + } + else { + ret = (WOLFSSL_EC_GROUP*)wolfSSL_EC_KEY_get0_group(pkey->ecc); + + /* set ecc group to null so it is not free'd when pkey is free'd */ + pkey->ecc->group = NULL; + } + } + + (void)group; + wolfSSL_EVP_PKEY_free(pkey); + return ret; +} +#endif /* HAVE_ECC */ + +#if !defined(NO_FILESYSTEM) +WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(XFILE fp, EVP_PKEY **x, + pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + + WOLFSSL_MSG("wolfSSL_PEM_read_PUBKEY not implemented"); + + return NULL; +} +#endif /* NO_FILESYSTEM */ #ifndef NO_RSA -/* Load RSA from Der, SSL_SUCCESS on success < 0 on error */ -int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* der, int derSz) + +#if defined(XSNPRINTF) && !defined(HAVE_FAST_RSA) +/* snprintf() must be available */ + +/****************************************************************************** +* wolfSSL_RSA_print - writes the human readable form of RSA to bio +* +* RETURNS: +* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE +*/ +int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int offset) { + char tmp[100] = {0}; + word32 idx = 0; + int sz = 0; + byte lbit = 0; + int rawLen = 0; + byte* rawKey = NULL; + RsaKey* iRsa = NULL; + int i = 0; + mp_int *rsaElem = NULL; + char rsaStr[][20] = { "Modulus:", + "PublicExponent:", + "PrivateExponent:", + "Prime1:", + "Prime2:", + "Exponent1:", + "Exponent2:", + "Coefficient:" + }; + + WOLFSSL_ENTER("wolfSSL_RSA_print"); + (void)offset; + + if (bio == NULL || rsa == NULL) { + return WOLFSSL_FATAL_ERROR; + } + + if ((sz = wolfSSL_RSA_size(rsa)) < 0) { + WOLFSSL_MSG("Error getting RSA key size"); + return WOLFSSL_FAILURE; + } + iRsa = (RsaKey*)rsa->internal; + + XSNPRINTF(tmp, sizeof(tmp) - 1, "\n%s: (%d bit)", + "RSA Private-Key", 8 * sz); + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + + for (i=0; in; + break; + case 1: + rsaElem = &iRsa->e; + break; + case 2: + rsaElem = &iRsa->d; + break; + case 3: + rsaElem = &iRsa->p; + break; + case 4: + rsaElem = &iRsa->q; + break; + case 5: + rsaElem = &iRsa->dP; + break; + case 6: + rsaElem = &iRsa->dQ; + break; + case 7: + rsaElem = &iRsa->u; + break; + default: + WOLFSSL_MSG("Bad index value"); + } + + if (i == 1) { + /* Print out exponent values */ + rawLen = mp_unsigned_bin_size(rsaElem); + if (rawLen < 0) { + WOLFSSL_MSG("Error getting exponent size"); + return WOLFSSL_FAILURE; + } + + if ((word32)rawLen < sizeof(word32)) { + rawLen = sizeof(word32); + } + rawKey = (byte*)XMALLOC(rawLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (rawKey == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(rawKey, 0, rawLen); + mp_to_unsigned_bin(rsaElem, rawKey); + if ((word32)rawLen <= sizeof(word32)) { + idx = *(word32*)rawKey; + #ifdef BIG_ENDIAN_ORDER + idx = ByteReverseWord32(idx); + #endif + } + XSNPRINTF(tmp, sizeof(tmp) - 1, "\nExponent: %d (0x%x)", idx, idx); + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + else { + XSNPRINTF(tmp, sizeof(tmp) - 1, "\n%s\n ", rsaStr[i]); + tmp[sizeof(tmp) - 1] = '\0'; + if (mp_leading_bit(rsaElem)) { + lbit = 1; + XSTRNCAT(tmp, "00", 3); + } + + rawLen = mp_unsigned_bin_size(rsaElem); + rawKey = (byte*)XMALLOC(rawLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (rawKey == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + mp_to_unsigned_bin(rsaElem, rawKey); + for (idx = 0; idx < (word32)rawLen; idx++) { + char val[5]; + int valSz = 5; + + if ((idx == 0) && !lbit) { + XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]); + } + else if ((idx != 0) && (((idx + lbit) % 15) == 0)) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1, + ":\n "); + XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]); + } + else { + XSNPRINTF(val, valSz - 1, ":%02x", rawKey[idx]); + } + XSTRNCAT(tmp, val, valSz); + } + XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* print out remaining values */ + if ((idx > 0) && (((idx - 1 + lbit) % 15) != 0)) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + lbit = 0; + } + + } + /* done with print out */ + if (wolfSSL_BIO_write(bio, "\n\0", (int)XSTRLEN("\n\0")) <= 0) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +#endif /* XSNPRINTF */ + +#if !defined(NO_FILESYSTEM) +#ifndef NO_WOLFSSL_STUB +WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(XFILE fp, WOLFSSL_RSA **x, + pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + WOLFSSL_STUB("PEM_read_RSAPublicKey"); + WOLFSSL_MSG("wolfSSL_PEM_read_RSAPublicKey not implemented"); + + return NULL; +} +#endif +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_PEM_write_RSAPublicKey(XFILE fp, WOLFSSL_RSA *x) +{ + (void)fp; + (void)x; + WOLFSSL_STUB("PEM_write_RSAPublicKey"); + WOLFSSL_MSG("wolfSSL_PEM_write_RSAPublicKey not implemented"); + + return WOLFSSL_FAILURE; +} +#endif + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_PEM_write_RSA_PUBKEY(XFILE fp, WOLFSSL_RSA *x) +{ + (void)fp; + (void)x; + WOLFSSL_STUB("PEM_write_RSA_PUBKEY"); + WOLFSSL_MSG("wolfSSL_PEM_write_RSA_PUBKEY not implemented"); + + return WOLFSSL_FAILURE; +} +#endif + +#endif /* NO_FILESYSTEM */ + +WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **r, const unsigned char **pp, + long len) +{ + WOLFSSL_RSA *rsa = NULL; + + WOLFSSL_ENTER("d2i_RSAPublicKey"); + + if (pp == NULL) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + if ((rsa = wolfSSL_RSA_new()) == NULL) { + WOLFSSL_MSG("RSA_new failed"); + return NULL; + } + + if (wolfSSL_RSA_LoadDer_ex(rsa, *pp, (int)len, WOLFSSL_RSA_LOAD_PUBLIC) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("RSA_LoadDer failed"); + wolfSSL_RSA_free(rsa); + rsa = NULL; + } + if (r != NULL) + *r = rsa; + + return rsa; +} + +/* Converts an RSA private key from DER format to an RSA structure. +Returns pointer to the RSA structure on success and NULL if error. */ +WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA **r, + const unsigned char **derBuf, long derSz) +{ + WOLFSSL_RSA *rsa = NULL; + + WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey"); + + /* check for bad functions arguments */ + if (derBuf == NULL) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + if ((rsa = wolfSSL_RSA_new()) == NULL) { + WOLFSSL_MSG("RSA_new failed"); + return NULL; + } + + if (wolfSSL_RSA_LoadDer_ex(rsa, *derBuf, (int)derSz, + WOLFSSL_RSA_LOAD_PRIVATE) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("RSA_LoadDer failed"); + wolfSSL_RSA_free(rsa); + rsa = NULL; + } + if (r != NULL) + *r = rsa; + + return rsa; +} + +#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \ + !defined(NO_RSA) && !defined(HAVE_USER_RSA) +/* Converts an internal RSA structure to DER format. + * If "pp" is null then buffer size only is returned. + * If "*pp" is null then a created buffer is set in *pp and the caller is + * responsible for free'ing it. + * Returns size of DER on success and WOLFSSL_FAILURE if error + */ +int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *rsa, unsigned char **pp) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_i2d_RSAPrivateKey"); + + /* check for bad functions arguments */ + if (rsa == NULL) { + WOLFSSL_MSG("Bad Function Arguments"); + return BAD_FUNC_ARG; + } + + if ((ret = wolfSSL_RSA_To_Der(rsa, pp, 0)) < 0) { + WOLFSSL_MSG("wolfSSL_RSA_To_Der failed"); + return WOLFSSL_FAILURE; + } + + return ret; /* returns size of DER if successful */ +} + + +int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *rsa, const unsigned char **pp) +{ + int ret; + + /* check for bad functions arguments */ + if (rsa == NULL) { + WOLFSSL_MSG("Bad Function Arguments"); + return BAD_FUNC_ARG; + } + + if ((ret = wolfSSL_RSA_To_Der(rsa, (byte**)pp, 1)) < 0) { + WOLFSSL_MSG("wolfSSL_RSA_To_Der failed"); + return WOLFSSL_FAILURE; + } + + return ret; +} +#endif /* !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \ + * !defined(NO_RSA) && !defined(HAVE_USER_RSA) */ + +#endif /* !NO_RSA */ +#endif /* OPENSSL_EXTRA */ + +#if !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */ +int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz) +{ + return wolfSSL_RSA_LoadDer_ex(rsa, derBuf, derSz, WOLFSSL_RSA_LOAD_PRIVATE); +} + + +int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf, + int derSz, int opt) +{ + word32 idx = 0; int ret; WOLFSSL_ENTER("wolfSSL_RSA_LoadDer"); - if (rsa == NULL || rsa->internal == NULL || der == NULL || derSz <= 0) { + if (rsa == NULL || rsa->internal == NULL || derBuf == NULL || derSz <= 0) { WOLFSSL_MSG("Bad function arguments"); - return BAD_FUNC_ARG; + return WOLFSSL_FATAL_ERROR; + } + + if (opt == WOLFSSL_RSA_LOAD_PRIVATE) { + ret = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz); + } + else { + ret = wc_RsaPublicKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz); } - ret = wc_RsaPrivateKeyDecode(der, &idx, (RsaKey*)rsa->internal, derSz); if (ret < 0) { - WOLFSSL_MSG("RsaPrivateKeyDecode failed"); - return ret; + if (opt == WOLFSSL_RSA_LOAD_PRIVATE) { + WOLFSSL_MSG("RsaPrivateKeyDecode failed"); + } + else { + WOLFSSL_MSG("RsaPublicKeyDecode failed"); + } + return SSL_FATAL_ERROR; } - if (SetRsaExternal(rsa) < 0) { + 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; } + +#if defined(WC_RSA_PSS) && (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \ + defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)) +static int hash2mgf(enum wc_HashType hType) +{ + switch (hType) { +#ifndef NO_SHA + case WC_HASH_TYPE_SHA: + return WC_MGF1SHA1; +#endif +#ifndef NO_SHA256 +#ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + return WC_MGF1SHA224; +#endif + case WC_HASH_TYPE_SHA256: + return WC_MGF1SHA256; +#endif +#ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + return WC_MGF1SHA384; +#endif +#ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + return WC_MGF1SHA512; +#endif + case WC_HASH_TYPE_NONE: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_MD5: + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_SHA3_224: + case WC_HASH_TYPE_SHA3_256: + case WC_HASH_TYPE_SHA3_384: + case WC_HASH_TYPE_SHA3_512: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + default: + WOLFSSL_MSG("Unrecognized or unsupported hash function"); + return WC_MGF1NONE; + } +} + +/* + * +-----------+ + * | M | + * +-----------+ + * | + * V + * Hash + * | + * V + * +--------+----------+----------+ + * M' = |Padding1| mHash | salt | + * +--------+----------+----------+ + * | + * +--------+----------+ V + * DB = |Padding2|maskedseed| Hash + * +--------+----------+ | + * | | + * V | +--+ + * xor <--- MGF <---| |bc| + * | | +--+ + * | | | + * V V V + * +-------------------+----------+--+ + * EM = | maskedDB |maskedseed|bc| + * +-------------------+----------+--+ + * Diagram taken from https://tools.ietf.org/html/rfc3447#section-9.1 + */ +int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *EM, + const unsigned char *mHash, + const WOLFSSL_EVP_MD *hashAlg, int saltLen) +{ + int hashLen, emLen, mgf; + int ret = WOLFSSL_FAILURE; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG _tmpRNG[1]; + WC_RNG* tmpRNG = _tmpRNG; +#endif + enum wc_HashType hashType; + + WOLFSSL_ENTER("wolfSSL_RSA_padding_add_PKCS1_PSS"); + + if (!rsa || !EM || !mHash || !hashAlg) { + return WOLFSSL_FAILURE; + } + + if (!(rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRNG, &initTmpRng))) { + WOLFSSL_MSG("WOLFSSL_RSA_GetRNG error"); + goto cleanup; + } + + if (!rsa->exSet && SetRsaExternal(rsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaExternal error"); + goto cleanup; + } + + hashType = wolfSSL_EVP_md2macType(hashAlg); + if (hashType < WC_HASH_TYPE_NONE || hashType > WC_HASH_TYPE_MAX) { + WOLFSSL_MSG("wolfSSL_EVP_md2macType error"); + goto cleanup; + } + + if ((mgf = hash2mgf(hashType)) == WC_MGF1NONE) { + WOLFSSL_MSG("hash2mgf error"); + goto cleanup; + } + + if ((hashLen = wolfSSL_EVP_MD_size(hashAlg)) < 0) { + WOLFSSL_MSG("wolfSSL_EVP_MD_size error"); + goto cleanup; + } + + if ((emLen = wolfSSL_RSA_size(rsa)) <= 0) { + WOLFSSL_MSG("wolfSSL_RSA_size error"); + goto cleanup; + } + + switch (saltLen) { + /* Negative saltLen values are treated differently */ + case RSA_PSS_SALTLEN_DIGEST: + saltLen = hashLen; + break; + case RSA_PSS_SALTLEN_MAX_SIGN: + case RSA_PSS_SALTLEN_MAX: + saltLen = emLen - hashLen - 2; + break; + default: + if (saltLen < 0) { + /* Not any currently implemented negative value */ + WOLFSSL_MSG("invalid saltLen"); + goto cleanup; + } + } + + if (wc_RsaPad_ex(mHash, wolfSSL_EVP_MD_size(hashAlg), EM, emLen, + RSA_BLOCK_TYPE_1, rng, WC_RSA_PSS_PAD, + wolfSSL_EVP_md2macType(hashAlg), mgf, NULL, 0, saltLen, + wolfSSL_BN_num_bits(rsa->n), NULL) != MP_OKAY) { + WOLFSSL_MSG("wc_RsaPad_ex error"); + goto cleanup; + } + + ret = WOLFSSL_SUCCESS; +cleanup: + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + if (tmpRNG) + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +/* + * Refer to wolfSSL_RSA_padding_add_PKCS1_PSS + * for an explanation of the parameters. + */ +int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash, + const WOLFSSL_EVP_MD *hashAlg, + const unsigned char *EM, int saltLen) +{ + int hashLen, mgf, emLen, mPrimeLen; + enum wc_HashType hashType; + byte *mPrime = NULL; + byte *buf = NULL; + + WOLFSSL_ENTER("wolfSSL_RSA_verify_PKCS1_PSS"); + + if (!rsa || !mHash || !hashAlg || !EM) { + return WOLFSSL_FAILURE; + } + + if ((hashLen = wolfSSL_EVP_MD_size(hashAlg)) < 0) { + return WOLFSSL_FAILURE; + } + + if ((emLen = wolfSSL_RSA_size(rsa)) <= 0) { + WOLFSSL_MSG("wolfSSL_RSA_size error"); + return WOLFSSL_FAILURE; + } + + switch (saltLen) { + /* Negative saltLen values are treated differently */ + case RSA_PSS_SALTLEN_DIGEST: + saltLen = hashLen; + break; + case RSA_PSS_SALTLEN_MAX_SIGN: + case RSA_PSS_SALTLEN_MAX: + saltLen = emLen - hashLen - 2; + break; + default: + if (saltLen < 0) { + /* Not any currently implemented negative value */ + WOLFSSL_MSG("invalid saltLen"); + return WOLFSSL_FAILURE; + } + } + + if (!rsa->exSet && SetRsaExternal(rsa) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + hashType = wolfSSL_EVP_md2macType(hashAlg); + if (hashType < WC_HASH_TYPE_NONE || hashType > WC_HASH_TYPE_MAX) { + WOLFSSL_MSG("wolfSSL_EVP_md2macType error"); + return WOLFSSL_FAILURE; + } + + if ((mgf = hash2mgf(hashType)) == WC_MGF1NONE) { + WOLFSSL_MSG("hash2mgf error"); + return WOLFSSL_FAILURE; + } + + if ((hashLen = wolfSSL_EVP_MD_size(hashAlg)) < 0) { + WOLFSSL_MSG("wolfSSL_EVP_MD_size error"); + return WOLFSSL_FAILURE; + } + + if (!(buf = (byte*)XMALLOC(emLen, NULL, DYNAMIC_TYPE_TMP_BUFFER))) { + WOLFSSL_MSG("malloc error"); + return WOLFSSL_FAILURE; + } + XMEMCPY(buf, EM, emLen); + + /* Remove and verify the PSS padding */ + if ((mPrimeLen = wc_RsaUnPad_ex(buf, emLen, &mPrime, + RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, hashType, + mgf, NULL, 0, saltLen, + wolfSSL_BN_num_bits(rsa->n), NULL)) < 0) { + WOLFSSL_MSG("wc_RsaPad_ex error"); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + /* Verify the hash is correct */ + if (wc_RsaPSS_CheckPadding_ex(mHash, hashLen, mPrime, mPrimeLen, hashType, + saltLen, wolfSSL_BN_num_bits(rsa->n)) + != MP_OKAY) { + WOLFSSL_MSG("wc_RsaPSS_CheckPadding_ex error"); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_SUCCESS; +} +#endif + +#if defined(OPENSSL_EXTRA) +WOLFSSL_RSA_METHOD *wolfSSL_RSA_meth_new(const char *name, int flags) +{ + int name_len; + WOLFSSL_RSA_METHOD* meth; + + if (name == NULL) { + return NULL; + } + + meth = (WOLFSSL_RSA_METHOD*)XMALLOC(sizeof(WOLFSSL_RSA_METHOD), NULL, + DYNAMIC_TYPE_OPENSSL); + name_len = (int)XSTRLEN(name); + if (!meth) { + return NULL; + } + meth->flags = flags; + meth->name = (char*)XMALLOC(name_len+1, NULL, DYNAMIC_TYPE_OPENSSL); + if (!meth->name) { + XFREE(meth, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + XMEMCPY(meth->name, name, name_len+1); + + return meth; +} + +void wolfSSL_RSA_meth_free(WOLFSSL_RSA_METHOD *meth) +{ + if (meth) { + XFREE(meth->name, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(meth, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_RSA_meth_set(WOLFSSL_RSA_METHOD *rsa, void* p) +{ + (void)rsa; + (void)p; + WOLFSSL_STUB("RSA_METHOD is not implemented."); + return 1; +} +#endif + +int wolfSSL_RSA_set_method(WOLFSSL_RSA *rsa, WOLFSSL_RSA_METHOD *meth) +{ + if (rsa) + rsa->meth = meth; + return 1; +} + +const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_method(const WOLFSSL_RSA *rsa) +{ + if (!rsa) { + return NULL; + } + return rsa->meth; +} + +const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_default_method(void) +{ + return wolfSSL_RSA_meth_new("wolfSSL RSA", 0); +} + +int wolfSSL_RSA_flags(const WOLFSSL_RSA *r) +{ + if (r && r->meth) { + return r->meth->flags; + } else { + return 0; + } +} + +void wolfSSL_RSA_set_flags(WOLFSSL_RSA *r, int flags) +{ + if (r && r->meth) { + r->meth->flags = flags; + } +} + +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) +WOLFSSL_RSA* wolfSSL_RSAPublicKey_dup(WOLFSSL_RSA *rsa) +{ + int derSz = 0; + byte *derBuf = NULL; + WOLFSSL_RSA* local; + + WOLFSSL_ENTER("wolfSSL_RSAPublicKey_dup"); + + if (!rsa) { + return NULL; + } + + local = wolfSSL_RSA_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_RSA structure"); + return NULL; + } + + if ((derSz = wolfSSL_RSA_To_Der(rsa, &derBuf, 1)) < 0) { + WOLFSSL_MSG("wolfSSL_RSA_To_Der failed"); + return NULL; + } + + if (wolfSSL_RSA_LoadDer_ex(local, + derBuf, derSz, + WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) { + wolfSSL_RSA_free(local); + local = NULL; + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_ASN1); + return local; +} +#endif + +void* wolfSSL_RSA_get_ex_data(const WOLFSSL_RSA *rsa, int idx) +{ + WOLFSSL_ENTER("wolfSSL_RSA_get_ex_data"); +#ifdef HAVE_EX_DATA + if (rsa) { + return wolfSSL_CRYPTO_get_ex_data(&rsa->ex_data, idx); + } +#else + (void)rsa; + (void)idx; +#endif + return NULL; +} + +int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data) +{ + WOLFSSL_ENTER("wolfSSL_RSA_set_ex_data"); + #ifdef HAVE_EX_DATA + if (rsa) { + return wolfSSL_CRYPTO_set_ex_data(&rsa->ex_data, idx, data); + } + #else + (void)rsa; + (void)idx; + (void)data; + #endif + return WOLFSSL_FAILURE; +} + +int wolfSSL_RSA_set0_key(WOLFSSL_RSA *r, WOLFSSL_BIGNUM *n, WOLFSSL_BIGNUM *e, + WOLFSSL_BIGNUM *d) +{ + /* If the fields n and e in r are NULL, the corresponding input + * parameters MUST be non-NULL for n and e. d may be + * left NULL (in case only the public key is used). + */ + if ((!r->n && !n) || (!r->e && !e)) + return 0; + + if (n) { + wolfSSL_BN_free(r->n); + r->n = n; + } + if (e) { + wolfSSL_BN_free(r->e); + r->e = e; + } + if (d) { + wolfSSL_BN_clear_free(r->d); + r->d = d; + } + + return 1; +} +#endif /* OPENSSL_EXTRA */ #endif /* NO_RSA */ - +#ifdef OPENSSL_EXTRA #ifndef NO_DSA -/* Load DSA from Der, SSL_SUCCESS on success < 0 on error */ -int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* der, int derSz) +/* 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; int ret; WOLFSSL_ENTER("wolfSSL_DSA_LoadDer"); - if (dsa == NULL || dsa->internal == NULL || der == NULL || derSz <= 0) { + if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) { WOLFSSL_MSG("Bad function arguments"); - return BAD_FUNC_ARG; + return WOLFSSL_FATAL_ERROR; } - ret = DsaPrivateKeyDecode(der, &idx, (DsaKey*)dsa->internal, derSz); + ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz); if (ret < 0) { WOLFSSL_MSG("DsaPrivateKeyDecode failed"); - return ret; + return WOLFSSL_FATAL_ERROR; } - if (SetDsaExternal(dsa) < 0) { + 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 */ +/* Loads DSA key from DER buffer. opt = DSA_LOAD_PRIVATE or DSA_LOAD_PUBLIC. + returns 1 on success, or 0 on failure. */ +int wolfSSL_DSA_LoadDer_ex(WOLFSSL_DSA* dsa, const unsigned char* derBuf, + int derSz, int opt) +{ + word32 idx = 0; + int ret; + WOLFSSL_ENTER("wolfSSL_DSA_LoadDer"); + if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FATAL_ERROR; + } + + if (opt == WOLFSSL_DSA_LOAD_PRIVATE) { + ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz); + } + else { + ret = DsaPublicKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz); + } + + if (ret < 0 && opt == WOLFSSL_DSA_LOAD_PRIVATE) { + WOLFSSL_MSG("DsaPrivateKeyDecode failed"); + return WOLFSSL_FATAL_ERROR; + } + else if (ret < 0 && opt == WOLFSSL_DSA_LOAD_PUBLIC) { + WOLFSSL_MSG("DsaPublicKeyDecode failed"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaExternal failed"); + return WOLFSSL_FATAL_ERROR; + } + + dsa->inSet = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* !NO_DSA */ + +#ifdef HAVE_ECC +/* 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) +{ + return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz, + WOLFSSL_EC_KEY_LOAD_PRIVATE); +} + +int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, + int derSz, int opt) +{ + word32 idx = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer"); + + if (key == NULL || key->internal == NULL || derBuf == NULL || derSz <= 0) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FATAL_ERROR; + } + + if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { + ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, + derSz); + } + else { + ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal, + derSz); + } + if (ret < 0) { + if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { + WOLFSSL_MSG("wc_EccPrivateKeyDecode failed"); + } + else { + WOLFSSL_MSG("wc_EccPublicKeyDecode failed"); + } + return WOLFSSL_FATAL_ERROR; + } + + if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyExternal failed"); + return WOLFSSL_FATAL_ERROR; + } + + key->inSet = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_ECC */ + +#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) +/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */ +int wolfSSL_DH_LoadDer(WOLFSSL_DH* dh, const unsigned char* derBuf, int derSz) +{ + word32 idx = 0; + int ret; + + if (dh == NULL || dh->internal == NULL || derBuf == NULL || derSz <= 0) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FATAL_ERROR; + } + + ret = wc_DhKeyDecode(derBuf, &idx, (DhKey*)dh->internal, (word32)derSz); + if (ret < 0) { + WOLFSSL_MSG("wc_DhKeyDecode failed"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetDhExternal(dh) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDhExternal failed"); + return WOLFSSL_FATAL_ERROR; + } + + return WOLFSSL_SUCCESS; +} +#endif /* ! NO_DH && WOLFSSL_QT || OPENSSL_ALL */ #endif /* OPENSSL_EXTRA */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + +/* increments ref count of WOLFSSL_RSA. Return 1 on success, 0 on error */ +int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa) +{ + if (rsa) { + if (wc_LockMutex(&rsa->refMutex) != 0) { + WOLFSSL_MSG("Failed to lock x509 mutex"); + } + rsa->refCount++; + wc_UnLockMutex(&rsa->refMutex); + + return 1; + } + + return 0; +} + +/* increments ref count of WOLFSSL_X509. Return 1 on success, 0 on error */ +int wolfSSL_X509_up_ref(WOLFSSL_X509* x509) +{ + if (x509) { + if (wc_LockMutex(&x509->refMutex) != 0) { + WOLFSSL_MSG("Failed to lock x509 mutex"); + } + x509->refCount++; + wc_UnLockMutex(&x509->refMutex); + + return 1; + } + + return 0; +} + +#endif /* OPENSSL_EXTRA || OPENSSL_ALL */ + + +#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) @@ -12634,7 +35560,7 @@ int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain) } -/* Get peer's ASN.1 DER ceritifcate at index (idx) length in bytes */ +/* Get peer's ASN.1 DER certificate at index (idx) length in bytes */ int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx) { WOLFSSL_ENTER("wolfSSL_get_chain_length"); @@ -12645,7 +35571,7 @@ int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx) } -/* Get peer's ASN.1 DER ceritifcate at index (idx) */ +/* Get peer's ASN.1 DER certificate at index (idx) */ byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx) { WOLFSSL_ENTER("wolfSSL_get_chain_cert"); @@ -12656,7 +35582,7 @@ byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx) } -/* Get peer's wolfSSL X509 ceritifcate at index (idx) */ +/* Get peer's wolfSSL X509 certificate at index (idx) */ WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx) { int ret; @@ -12671,15 +35597,16 @@ 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 { InitDecodedCert(cert, chain->certs[idx].buffer, chain->certs[idx].length, NULL); - if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0) + if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0) { WOLFSSL_MSG("Failed to parse cert"); + } else { x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, DYNAMIC_TYPE_X509); @@ -12687,11 +35614,11 @@ WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx) WOLFSSL_MSG("Failed alloc X509"); } else { - InitX509(x509, 1); + InitX509(x509, 1, NULL); if ((ret = CopyDecodedToX509(x509, cert)) != 0) { WOLFSSL_MSG("Failed to copy decoded"); - XFREE(x509, NULL, DYNAMIC_TYPE_X509); + wolfSSL_X509_free(x509); x509 = NULL; } } @@ -12699,39 +35626,59 @@ 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; } -/* Get peer's PEM ceritifcate at index (idx), output to buffer if inLen big - enough else return error (-1), output length is in *outLen - SSL_SUCCESS on ok */ +/* 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 WOLFSSL_SUCCESS on ok */ int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, unsigned char* buf, int inLen, int* outLen) { - const char header[] = "-----BEGIN CERTIFICATE-----\n"; - const char footer[] = "-----END CERTIFICATE-----\n"; - - int headerLen = sizeof(header) - 1; - int footerLen = sizeof(footer) - 1; +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + const char* header = NULL; + const char* footer = NULL; + int headerLen; + int footerLen; int i; int err; + word32 szNeeded = 0; WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem"); - if (!chain || !outLen || !buf) + if (!chain || !outLen || idx < 0 || idx >= wolfSSL_get_chain_count(chain)) return BAD_FUNC_ARG; + err = wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer); + if (err != 0) + return err; + + headerLen = (int)XSTRLEN(header); + footerLen = (int)XSTRLEN(footer); + + /* Null output buffer return size needed in outLen */ + if(!buf) { + if(Base64_Encode(chain->certs[idx].buffer, chain->certs[idx].length, + NULL, &szNeeded) != LENGTH_ONLY_E) + return WOLFSSL_FAILURE; + *outLen = szNeeded + headerLen + footerLen; + return LENGTH_ONLY_E; + } + /* don't even try if inLen too short */ if (inLen < headerLen + footerLen + chain->certs[idx].length) return BAD_FUNC_ARG; /* header */ - XMEMCPY(buf, header, headerLen); + if (XMEMCPY(buf, header, headerLen) == NULL) + return WOLFSSL_FATAL_ERROR; + i = headerLen; /* body */ @@ -12744,14 +35691,24 @@ int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, /* footer */ if ( (i + footerLen) > inLen) return BAD_FUNC_ARG; - XMEMCPY(buf + i, footer, footerLen); + if (XMEMCPY(buf + i, footer, footerLen) == NULL) + return WOLFSSL_FATAL_ERROR; *outLen += headerLen + footerLen; - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; +#else + (void)chain; + (void)idx; + (void)buf; + (void)inLen; + (void)outLen; + return WOLFSSL_FAILURE; +#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ } /* get session ID */ +WOLFSSL_ABI const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session) { WOLFSSL_ENTER("wolfSSL_get_sessionID"); @@ -12778,21 +35735,35 @@ void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx) #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC +void wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb) +{ + if (ctx) + ctx->EccKeyGenCb = cb; +} +void wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->EccKeyGenCtx = ctx; +} +void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EccKeyGenCtx; + return NULL; +} + +WOLFSSL_ABI void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb) { if (ctx) ctx->EccSignCb = cb; } - - void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx) { if (ssl) ssl->EccSignCtx = ctx; } - - void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl) { if (ssl) @@ -12801,21 +35772,16 @@ void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl) return NULL; } - void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb) { if (ctx) ctx->EccVerifyCb = cb; } - - void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx) { if (ssl) ssl->EccVerifyCtx = ctx; } - - void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl) { if (ssl) @@ -12824,24 +35790,197 @@ void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl) return NULL; } +void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx, CallbackEccSharedSecret cb) +{ + if (ctx) + ctx->EccSharedSecretCb = cb; +} +void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->EccSharedSecretCtx = ctx; +} +void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EccSharedSecretCtx; + + return NULL; +} #endif /* HAVE_ECC */ -#ifndef NO_RSA +#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 /* HAVE_ED25519 */ + +#ifdef HAVE_CURVE25519 +void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX* ctx, + CallbackX25519KeyGen cb) +{ + if (ctx) + ctx->X25519KeyGenCb = cb; +} +void wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->X25519KeyGenCtx = ctx; +} +void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->X25519KeyGenCtx; + + return NULL; +} + +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 /* HAVE_CURVE25519 */ + +#ifdef HAVE_ED448 +void wolfSSL_CTX_SetEd448SignCb(WOLFSSL_CTX* ctx, CallbackEd448Sign cb) +{ + if (ctx) + ctx->Ed448SignCb = cb; +} +void wolfSSL_SetEd448SignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed448SignCtx = ctx; +} +void* wolfSSL_GetEd448SignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed448SignCtx; + + return NULL; +} + +void wolfSSL_CTX_SetEd448VerifyCb(WOLFSSL_CTX* ctx, CallbackEd448Verify cb) +{ + if (ctx) + ctx->Ed448VerifyCb = cb; +} +void wolfSSL_SetEd448VerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed448VerifyCtx = ctx; +} +void* wolfSSL_GetEd448VerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed448VerifyCtx; + + return NULL; +} +#endif /* HAVE_ED448 */ + +#ifdef HAVE_CURVE448 +void wolfSSL_CTX_SetX448KeyGenCb(WOLFSSL_CTX* ctx, + CallbackX448KeyGen cb) +{ + if (ctx) + ctx->X448KeyGenCb = cb; +} +void wolfSSL_SetX448KeyGenCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->X448KeyGenCtx = ctx; +} +void* wolfSSL_GetX448KeyGenCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->X448KeyGenCtx; + + return NULL; +} + +void wolfSSL_CTX_SetX448SharedSecretCb(WOLFSSL_CTX* ctx, + CallbackX448SharedSecret cb) +{ + if (ctx) + ctx->X448SharedSecretCb = cb; +} +void wolfSSL_SetX448SharedSecretCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->X448SharedSecretCtx = ctx; +} +void* wolfSSL_GetX448SharedSecretCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->X448SharedSecretCtx; + + return NULL; +} +#endif /* HAVE_CURVE448 */ + +#ifndef NO_RSA void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb) { if (ctx) ctx->RsaSignCb = cb; } - - +void wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb) +{ + if (ctx) + ctx->RsaSignCheckCb = cb; +} void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx) { if (ssl) ssl->RsaSignCtx = ctx; } - - void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl) { if (ssl) @@ -12856,15 +35995,11 @@ void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb) if (ctx) ctx->RsaVerifyCb = cb; } - - void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx) { if (ssl) ssl->RsaVerifyCtx = ctx; } - - void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl) { if (ssl) @@ -12873,20 +36008,59 @@ 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_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb) +{ + if (ctx) + ctx->RsaPssSignCheckCb = 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 /* WC_RSA_PSS */ + void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb) { if (ctx) ctx->RsaEncCb = cb; } - - void wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx) { if (ssl) ssl->RsaEncCtx = ctx; } - - void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl) { if (ssl) @@ -12900,15 +36074,11 @@ void wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX* ctx, CallbackRsaDec cb) if (ctx) ctx->RsaDecCb = cb; } - - void wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx) { if (ssl) ssl->RsaDecCtx = ctx; } - - void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) { if (ssl) @@ -12916,13 +36086,31 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return NULL; } - - #endif /* NO_RSA */ #endif /* HAVE_PK_CALLBACKS */ #endif /* NO_CERTS */ +#if defined(HAVE_PK_CALLBACKS) && !defined(NO_DH) +void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX* ctx, CallbackDhAgree cb) +{ + if (ctx) + ctx->DhAgreeCb = cb; +} +void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->DhAgreeCtx = ctx; +} +void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->DhAgreeCtx; + + return NULL; +} +#endif /* HAVE_PK_CALLBACKS && !NO_DH */ + #ifdef WOLFSSL_HAVE_WOLFSCEP /* Used by autoconf to see if wolfSCEP is available */ @@ -12935,3 +36123,11585 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) void wolfSSL_cert_service(void) {} #endif +#ifdef OPENSSL_EXTRA + #ifndef NO_CERTS + void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name) + { + WOLFSSL_ENTER("wolfSSL_X509_NAME_free"); + FreeX509Name(name, NULL); + XFREE(name, NULL, DYNAMIC_TYPE_X509); + } + + + /* Malloc's a new WOLFSSL_X509_NAME structure + * + * returns NULL on failure, otherwise returns a new structure. + */ + WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void) + { + WOLFSSL_X509_NAME* name; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_new"); + + name = (WOLFSSL_X509_NAME*)XMALLOC(sizeof(WOLFSSL_X509_NAME), NULL, + DYNAMIC_TYPE_X509); + if (name != NULL) { + InitX509Name(name, 1); + } + return name; + } + + /* Creates a duplicate of a WOLFSSL_X509_NAME structure. + Returns a new WOLFSSL_X509_NAME structure or NULL on failure */ + WOLFSSL_X509_NAME* wolfSSL_X509_NAME_dup(WOLFSSL_X509_NAME *name) + { + WOLFSSL_X509_NAME* dup = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_dup"); + + if (name == NULL) { + WOLFSSL_MSG("NULL parameter"); + return NULL; + } + + if (!(dup = wolfSSL_X509_NAME_new())) { + return NULL; + } + + /* copy contents */ + XMEMCPY(dup, name, sizeof(WOLFSSL_X509_NAME)); + InitX509Name(dup, 1); + dup->sz = name->sz; + + /* handle dynamic portions */ + if (name->dynamicName) { + if (!(dup->name = (char*)XMALLOC(name->sz, 0, + DYNAMIC_TYPE_OPENSSL))) { + goto err; + } + } + XMEMCPY(dup->name, name->name, name->sz); + #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + !defined(NO_ASN) + if (!(dup->fullName.fullName = (char*)XMALLOC(name->fullName.fullNameLen, + 0, DYNAMIC_TYPE_OPENSSL))) { + goto err; + } + XMEMCPY(dup->fullName.fullName, name->fullName.fullName, + name->fullName.fullNameLen); + #endif + + return dup; + + err: + if (dup) { + if (dup->dynamicName && dup->name) { + XFREE(dup->name, 0, DYNAMIC_TYPE_OPENSSL); + dup->name = NULL; + } + #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + !defined(NO_ASN) + if (dup->fullName.fullName && + dup->fullName.fullName != name->fullName.fullName) { + XFREE(dup->fullName.fullName, 0, DYNAMIC_TYPE_OPENSSL); + dup->fullName.fullName = NULL; + } + #endif + wolfSSL_X509_NAME_free(dup); + } + return NULL; + } + +#if defined(WOLFSSL_CERT_GEN) + /* helper function for CopyX509NameToCertName() + * + * returns WOLFSSL_SUCCESS on success + */ + static int CopyX509NameEntry(char* out, int mx, char* in, int inLen) + { + if (inLen > mx) { + WOLFSSL_MSG("Name too long"); + XMEMCPY(out, in, mx); + } + else { + XMEMCPY(out, in, inLen); + out[inLen] = '\0'; + } + + /* make sure is null terminated */ + out[mx-1] = '\0'; + + return WOLFSSL_SUCCESS; + } + + + /* Helper function to copy cert name from a WOLFSSL_X509_NAME structure to + * a CertName structure. + * + * returns WOLFSSL_SUCCESS on success and a negative error value on failure + */ + static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName) + { + DecodedName* dn = NULL; + + if (n == NULL || cName == NULL) { + return BAD_FUNC_ARG; + } + + dn = &(n->fullName); + + /* initialize cert name */ + cName->country[0] = '\0'; + cName->countryEnc = CTC_PRINTABLE; + cName->state[0] = '\0'; + cName->stateEnc = CTC_UTF8; + cName->locality[0] = '\0'; + cName->localityEnc = CTC_UTF8; + cName->sur[0] = '\0'; + cName->surEnc = CTC_UTF8; + cName->org[0] = '\0'; + cName->orgEnc = CTC_UTF8; + cName->unit[0] = '\0'; + cName->unitEnc = CTC_UTF8; + cName->commonName[0] = '\0'; + cName->commonNameEnc = CTC_UTF8; + cName->serialDev[0] = '\0'; + cName->serialDevEnc = CTC_PRINTABLE; + #ifdef WOLFSSL_CERT_EXT + cName->busCat[0] = '\0'; + cName->busCatEnc = CTC_UTF8; + cName->joiC[0] = '\0'; + cName->joiCEnc = CTC_PRINTABLE; + cName->joiSt[0] = '\0'; + cName->joiStEnc = CTC_PRINTABLE; + #endif + cName->email[0] = '\0'; + + + /* ASN_COUNTRY_NAME */ + WOLFSSL_MSG("Copy Country Name"); + if (CopyX509NameEntry(cName->country, CTC_NAME_SIZE, dn->fullName + dn->cIdx, + dn->cLen) != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_ORGUNIT_NAME */ + WOLFSSL_MSG("Copy Org Unit Name"); + if (CopyX509NameEntry(cName->unit, CTC_NAME_SIZE, dn->fullName + dn->ouIdx, + dn->ouLen) != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_ORG_NAME */ + WOLFSSL_MSG("Copy Org Name"); + if (CopyX509NameEntry(cName->org, CTC_NAME_SIZE, dn->fullName + dn->oIdx, + dn->oLen) != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_STATE_NAME */ + WOLFSSL_MSG("Copy State Name"); + if (CopyX509NameEntry(cName->state, CTC_NAME_SIZE, dn->fullName + dn->stIdx, + dn->stLen) != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_LOCALITY_NAME */ + WOLFSSL_MSG("Copy Locality Name"); + if (CopyX509NameEntry(cName->locality, CTC_NAME_SIZE, + dn->fullName + dn->lIdx, dn->lLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_SUR_NAME */ + WOLFSSL_MSG("Copy Sur Name"); + if (CopyX509NameEntry(cName->sur, CTC_NAME_SIZE, dn->fullName + dn->snIdx, + dn->snLen) != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_COMMON_NAME */ + WOLFSSL_MSG("Copy Common Name"); + if (CopyX509NameEntry(cName->commonName, CTC_NAME_SIZE, + dn->fullName + dn->cnIdx, dn->cnLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_SERIAL_NUMBER */ + WOLFSSL_MSG("Copy Serial Number of Device"); + if (CopyX509NameEntry(cName->serialDev, CTC_NAME_SIZE, + dn->fullName + dn->serialIdx, dn->serialLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + #ifdef WOLFSSL_CERT_EXT + /* ASN_BUS_CAT */ + WOLFSSL_MSG("Copy Business Category"); + if (CopyX509NameEntry(cName->busCat, CTC_NAME_SIZE, + dn->fullName + dn->bcIdx, dn->bcLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + /* JoI Country */ + WOLFSSL_MSG("Copy Jurisdiction of Incorporation Country"); + if (CopyX509NameEntry(cName->joiC, CTC_NAME_SIZE, + dn->fullName + dn->jcIdx, dn->jcLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + /* JoI State */ + WOLFSSL_MSG("Copy Jurisdiction of Incorporation State"); + if (CopyX509NameEntry(cName->joiSt, CTC_NAME_SIZE, + dn->fullName + dn->jsIdx, dn->jsLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + #endif + + WOLFSSL_MSG("Copy Email"); + if (CopyX509NameEntry(cName->email, CTC_NAME_SIZE, + dn->fullName + dn->emailIdx, dn->emailLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + return WOLFSSL_SUCCESS; + } + +#ifdef WOLFSSL_CERT_REQ + static int ReqCertFromX509(Cert* cert, WOLFSSL_X509* req) + { + int ret; + + if (wc_InitCert(cert) != 0) + return WOLFSSL_FAILURE; + + ret = CopyX509NameToCertName(&req->subject, &cert->subject); + if (ret == WOLFSSL_SUCCESS) { + cert->version = req->version; + cert->isCA = req->isCa; +#ifdef WOLFSSL_CERT_EXT + if (req->subjKeyIdSz != 0) { + XMEMCPY(cert->skid, req->subjKeyId, req->subjKeyIdSz); + cert->skidSz = req->subjKeyIdSz; + } + if (req->keyUsageSet) + cert->keyUsage = req->keyUsage; + /* Extended Key Usage not supported. */ +#endif + } + + return ret; + } +#endif + + /* convert a WOLFSSL_X509 to a Cert structure for writing out */ + static int CertFromX509(Cert* cert, WOLFSSL_X509* x509) + { + int ret; + #ifdef WOLFSSL_CERT_EXT + int i; + #endif + + WOLFSSL_ENTER("wolfSSL_X509_to_Cert()"); + + if (x509 == NULL || cert == NULL) { + return BAD_FUNC_ARG; + } + + wc_InitCert(cert); + + cert->version = (int)wolfSSL_X509_get_version(x509); + + #ifdef WOLFSSL_ALT_NAMES + if (x509->notBefore.length > 0) { + if ((x509->notBefore.length + 2) < CTC_DATE_SIZE) { + cert->beforeDate[0] = x509->notBefore.type; + cert->beforeDate[1] = x509->notBefore.length; + XMEMCPY(&cert->beforeDate[2], x509->notBefore.data, + x509->notBefore.length); + cert->beforeDateSz = x509->notBefore.length + 2; + } + else { + WOLFSSL_MSG("Not before date too large"); + return WOLFSSL_FAILURE; + } + } + else { + cert->beforeDateSz = 0; + } + if (x509->notAfter.length > 0) { + if ((x509->notAfter.length + 2) < CTC_DATE_SIZE) { + cert->afterDate[0] = x509->notAfter.type; + cert->afterDate[1] = x509->notAfter.length; + XMEMCPY(&cert->afterDate[2], x509->notAfter.data, + x509->notAfter.length); + cert->afterDateSz = x509->notAfter.length + 2; + } + else { + WOLFSSL_MSG("Not after date too large"); + return WOLFSSL_FAILURE; + } + } + else { + cert->afterDateSz = 0; + } + + cert->altNamesSz = FlattenAltNames(cert->altNames, + sizeof(cert->altNames), x509->altNames); + + #endif /* WOLFSSL_ALT_NAMES */ + + cert->sigType = wolfSSL_X509_get_signature_type(x509); + cert->keyType = x509->pubKeyOID; + cert->isCA = wolfSSL_X509_get_isCA(x509); + + #ifdef WOLFSSL_CERT_EXT + if (x509->subjKeyIdSz < CTC_MAX_SKID_SIZE) { + XMEMCPY(cert->skid, x509->subjKeyId, x509->subjKeyIdSz); + cert->skidSz = (int)x509->subjKeyIdSz; + } + else { + WOLFSSL_MSG("Subject Key ID too large"); + return WOLFSSL_FAILURE; + } + + if (x509->authKeyIdSz < CTC_MAX_AKID_SIZE) { + XMEMCPY(cert->akid, x509->authKeyId, x509->authKeyIdSz); + cert->akidSz = (int)x509->authKeyIdSz; + } + else { + WOLFSSL_MSG("Auth Key ID too large"); + return WOLFSSL_FAILURE; + } + + for (i = 0; i < x509->certPoliciesNb; i++) { + /* copy the smaller of MAX macros, by default they are currently equal*/ + if ((int)CTC_MAX_CERTPOL_SZ <= (int)MAX_CERTPOL_SZ) { + XMEMCPY(cert->certPolicies[i], x509->certPolicies[i], + CTC_MAX_CERTPOL_SZ); + } + else { + XMEMCPY(cert->certPolicies[i], x509->certPolicies[i], + MAX_CERTPOL_SZ); + } + } + cert->certPoliciesNb = (word16)x509->certPoliciesNb; + + cert->keyUsage = x509->keyUsage; + #endif /* WOLFSSL_CERT_EXT */ + + #ifdef WOLFSSL_CERT_REQ + /* copy over challenge password for REQ certs */ + XMEMCPY(cert->challengePw, x509->challengePw, CTC_NAME_SIZE); + #endif + + if (x509->serialSz <= CTC_SERIAL_SIZE) { + XMEMCPY(cert->serial, x509->serial, x509->serialSz); + } + else { + WOLFSSL_MSG("Serial size error"); + return WOLFSSL_FAILURE; + } + + /* copy over Name structures */ + if (x509->issuerSet) + cert->selfSigned = 0; + if ((ret = CopyX509NameToCertName(&(x509->issuer), &(cert->issuer))) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error copying over issuer names"); + WOLFSSL_LEAVE("wolfSSL_X509_to_Cert()", ret); + return WOLFSSL_FAILURE; + } + if ((ret = CopyX509NameToCertName(&(x509->subject), &(cert->subject))) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error copying over subject names"); + WOLFSSL_LEAVE("wolfSSL_X509_to_Cert()", ret); + return WOLFSSL_FAILURE; + } + + cert->heap = x509->heap; + + return WOLFSSL_SUCCESS; + } + + + /* returns the sig type to use on success i.e CTC_SHAwRSA and WOLFSSL_FALURE + * on fail case */ + static int wolfSSL_sigTypeFromPKEY(WOLFSSL_EVP_MD* md, + WOLFSSL_EVP_PKEY* pkey) + { + int hashType; + int sigType = WOLFSSL_FAILURE; + + /* Convert key type and hash algorithm to a signature algorithm */ + if (wolfSSL_EVP_get_hashinfo(md, &hashType, NULL) == WOLFSSL_FAILURE) + return WOLFSSL_FAILURE; + + + if (pkey->type == EVP_PKEY_RSA) { + switch (hashType) { + case WC_HASH_TYPE_SHA: + sigType = CTC_SHAwRSA; + break; + case WC_HASH_TYPE_SHA224: + sigType = CTC_SHA224wRSA; + break; + case WC_HASH_TYPE_SHA256: + sigType = CTC_SHA256wRSA; + break; + case WC_HASH_TYPE_SHA384: + sigType = CTC_SHA384wRSA; + break; + case WC_HASH_TYPE_SHA512: + sigType = CTC_SHA512wRSA; + break; + default: + return WOLFSSL_FAILURE; + } + } + else if (pkey->type == EVP_PKEY_EC) { + switch (hashType) { + case WC_HASH_TYPE_SHA: + sigType = CTC_SHAwECDSA; + break; + case WC_HASH_TYPE_SHA224: + sigType = CTC_SHA224wECDSA; + break; + case WC_HASH_TYPE_SHA256: + sigType = CTC_SHA256wECDSA; + break; + case WC_HASH_TYPE_SHA384: + sigType = CTC_SHA384wECDSA; + break; + case WC_HASH_TYPE_SHA512: + sigType = CTC_SHA512wECDSA; + break; + default: + return WOLFSSL_FAILURE; + } + } + else + return WOLFSSL_FAILURE; + return sigType; + } + + + /* generates DER buffer from WOLFSSL_X509 + * If req == 1 then creates a request DER buffer + * + * updates derSz with certificate body size on success + * return WOLFSSL_SUCCESS on success + */ + static int wolfSSL_X509_make_der(WOLFSSL_X509* x509, int req, + unsigned char* der, int* derSz) + { + int ret; + Cert cert; + void* key = NULL; + int type = -1; + #ifndef NO_RSA + RsaKey rsa; + #endif + #ifdef HAVE_ECC + ecc_key ecc; + #endif + WC_RNG rng; + word32 idx = 0; + + if (x509 == NULL || der == NULL || derSz == NULL) + return BAD_FUNC_ARG; + + #ifndef WOLFSSL_CERT_REQ + if (req) { + WOLFSSL_MSG("WOLFSSL_CERT_REQ needed for certificate request"); + return WOLFSSL_FAILURE; + } + #endif + + #ifdef WOLFSSL_CERT_REQ + if (req) { + if (ReqCertFromX509(&cert, x509) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; + } + else + #endif + { + /* Create a Cert that has the certificate fields. */ + if (CertFromX509(&cert, x509) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; + } + + /* Create a public key object from requests public key. */ + #ifndef NO_RSA + if (x509->pubKeyOID == RSAk) { + type = RSA_TYPE; + ret = wc_InitRsaKey(&rsa, x509->heap); + if (ret != 0) + return ret; + ret = wc_RsaPublicKeyDecode(x509->pubKey.buffer, &idx, &rsa, + x509->pubKey.length); + if (ret != 0) { + wc_FreeRsaKey(&rsa); + return ret; + } + key = (void*)&rsa; + } + #endif + #ifdef HAVE_ECC + if (x509->pubKeyOID == ECDSAk) { + type = ECC_TYPE; + ret = wc_ecc_init(&ecc); + if (ret != 0) + return ret; + ret = wc_EccPublicKeyDecode(x509->pubKey.buffer, &idx, &ecc, + x509->pubKey.length); + if (ret != 0) { + wc_ecc_free(&ecc); + return ret; + } + key = (void*)&ecc; + } + #endif + if (key == NULL) + return WOLFSSL_FAILURE; + + /* Make the body of the certificate request. */ + #ifdef WOLFSSL_CERT_REQ + if (req) { + ret = wc_MakeCertReq_ex(&cert, der, *derSz, type, key); + } + else + #endif + { + ret = wc_InitRng(&rng); + if (ret != 0) + return WOLFSSL_FAILURE; + + ret = wc_MakeCert_ex(&cert, der, *derSz, type, key, &rng); + wc_FreeRng(&rng); + } + if (ret < 0) { + return ret; + } + + /* Dispose of the public key object. */ + #ifndef NO_RSA + if (x509->pubKeyOID == RSAk) + wc_FreeRsaKey(&rsa); + #endif + #ifdef HAVE_ECC + if (x509->pubKeyOID == ECDSAk) + wc_ecc_free(&ecc); + #endif + *derSz = ret; + + return WOLFSSL_SUCCESS; + } + + + /* signs a der buffer for the WOLFSSL_X509 structure using the PKEY and MD + * hash passed in + * + * WARNING: this free's and replaces the existing DER buffer in the + * WOLFSSL_X509 with the newly signed buffer. + * returns size of signed buffer on success and negative values on fail + */ + static int wolfSSL_X509_resign_cert(WOLFSSL_X509* x509, int req, + unsigned char* der, int derSz, int certBodySz, WOLFSSL_EVP_MD* md, + WOLFSSL_EVP_PKEY* pkey) + { + int ret; + void* key = NULL; + int type = -1; + int sigType; + WC_RNG rng; + + sigType = wolfSSL_sigTypeFromPKEY(md, pkey); + if (sigType == WOLFSSL_FAILURE) + return WOLFSSL_FATAL_ERROR; + + + /* Get the private key object and type from pkey. */ + #ifndef NO_RSA + if (pkey->type == EVP_PKEY_RSA) { + type = RSA_TYPE; + key = pkey->rsa->internal; + } + #endif + #ifdef HAVE_ECC + if (pkey->type == EVP_PKEY_EC) { + type = ECC_TYPE; + key = pkey->ecc->internal; + } + #endif + + /* Sign the certificate request body. */ + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + ret = wc_SignCert_ex(certBodySz, sigType, der, derSz, type, key, &rng); + wc_FreeRng(&rng); + if (ret < 0) + return ret; + + /* Put in the new certificate encoding into the x509 object. */ + FreeDer(&x509->derCert); + type = CERT_TYPE; + #ifdef WOLFSSL_REQ_CERT + if (req) { + type = CERTREQ_TYPE; + } + #endif + + if (AllocDer(&x509->derCert, ret, type, NULL) != 0) + return WOLFSSL_FATAL_ERROR; + XMEMCPY(x509->derCert->buffer, der, ret); + x509->derCert->length = ret; + + (void)req; + return ret; + } + + + /* returns the size of signature on success */ + int wolfSSL_X509_sign(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey, + const WOLFSSL_EVP_MD* md) + { + int ret; + byte der[4096]; /* @TODO dynamic set based on expected cert size */ + int derSz = sizeof(der); + + WOLFSSL_ENTER("wolfSSL_X509_sign"); + + if (x509 == NULL || pkey == NULL || md == NULL) + return WOLFSSL_FAILURE; + + x509->sigOID = wolfSSL_sigTypeFromPKEY((WOLFSSL_EVP_MD*)md, pkey); + if ((ret = wolfSSL_X509_make_der(x509, 0, der, &derSz)) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Unable to make DER for X509"); + WOLFSSL_LEAVE("wolfSSL_X509_sign", ret); + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_X509_resign_cert(x509, 0, der, sizeof(der), derSz, + (WOLFSSL_EVP_MD*)md, pkey); + if (ret <= 0) { + WOLFSSL_LEAVE("wolfSSL_X509_sign", ret); + return WOLFSSL_FAILURE; + } + + return ret; + } + + + /* Converts the x509 name structure into DER format. + * + * out pointer to either a pre setup buffer or a pointer to null for + * creating a dynamic buffer. In the case that a pre-existing buffer is + * used out will be incremented the size of the DER buffer on success. + * + * returns the size of the buffer on success, or negative value with failure + */ + int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) + { + CertName cName; + unsigned char buf[256]; /* ASN_MAX_NAME */ + int sz; + WOLFSSL_ENTER("wolfSSL_i2d_X509_NAME"); + + if (out == NULL || name == NULL) { + return BAD_FUNC_ARG; + } + XMEMSET(&cName, 0, sizeof(CertName)); + + if (CopyX509NameToCertName(name, &cName) != SSL_SUCCESS) { + WOLFSSL_MSG("Error converting x509 name to internal CertName"); + return SSL_FATAL_ERROR; + } + + sz = SetName(buf, sizeof(buf), &cName); + if (sz < 0) { + return sz; + } + + /* using buffer passed in */ + if (*out != NULL) { + XMEMCPY(*out, buf, sz); + *out += sz; + } + else { + *out = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL); + if (*out == NULL) { + return MEMORY_E; + } + XMEMCPY(*out, buf, sz); + } + + return sz; + } +#endif /* WOLFSSL_CERT_GEN */ + + + /* Compares the two X509 names. If the size of x is larger then y then a + * positive value is returned if x is smaller a negative value is returned. + * In the case that the sizes are equal a the value of strcmp between the + * two names is returned. + * + * x First name for comparison + * y Second name to compare with x + */ + int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x, + const WOLFSSL_X509_NAME* y) + { + const char* _x; + const char* _y; + WOLFSSL_ENTER("wolfSSL_X509_NAME_cmp"); + + if (x == NULL || y == NULL) { + WOLFSSL_MSG("Bad argument passed in"); + return -2; + } + + if (x == y) { + return 0; /* match */ + } + + if (x->sz != y->sz) { + return x->sz - y->sz; + } + + /* + * If the name member is not set or is immediately null terminated then + * compare the staticName member + */ + _x = (x->name && *x->name) ? x->name : x->staticName; + _y = (y->name && *y->name) ? y->name : y->staticName; + + return XSTRNCMP(_x, _y, x->sz); /* y sz is the same */ + } + + + WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, + pem_password_cb *cb, void *u) + { + WOLFSSL_X509* x509 = NULL; +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + unsigned char* pem = NULL; + int pemSz; + long i = 0, l; + const char* footer = NULL; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509"); + + if (bp == NULL) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", BAD_FUNC_ARG); + return NULL; + } + + if ((l = wolfSSL_BIO_get_len(bp)) <= 0) { + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + /* No certificate in buffer */ + WOLFSSL_ERROR(ASN_NO_PEM_HEADER); + #endif + return NULL; + } + + pem = (unsigned char*)XMALLOC(l, 0, DYNAMIC_TYPE_PEM); + if (pem == NULL) + return NULL; + + i = 0; + if (wc_PemGetHeaderFooter(CERT_TYPE, NULL, &footer) != 0) { + XFREE(pem, 0, DYNAMIC_TYPE_PEM); + return NULL; + } + + /* TODO: Inefficient + * reading in one byte at a time until see "END CERTIFICATE" + */ + while ((l = wolfSSL_BIO_read(bp, (char *)&pem[i], 1)) == 1) { + i++; + if (i > 26 && XMEMCMP((char *)&pem[i-26], footer, 25) == 0) { + if (pem[i-1] == '\r') { + /* found \r , Windows line ending is \r\n so try to read one + * more byte for \n, ignoring return value */ + (void)wolfSSL_BIO_read(bp, (char *)&pem[i++], 1); + } + break; + } + } + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + if (l == 0) + WOLFSSL_ERROR(ASN_NO_PEM_HEADER); + #endif + pemSz = (int)i; + x509 = wolfSSL_X509_load_certificate_buffer(pem, pemSz, + WOLFSSL_FILETYPE_PEM); + + if (x != NULL) { + *x = x509; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_PEM); + +#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ + (void)bp; + (void)x; + (void)cb; + (void)u; + + return x509; + } + + WOLFSSL_X509_CRL *wolfSSL_PEM_read_bio_X509_CRL(WOLFSSL_BIO *bp, + WOLFSSL_X509_CRL **x, pem_password_cb *cb, void *u) + { +#if defined(WOLFSSL_PEM_TO_DER) && defined(HAVE_CRL) + unsigned char* pem = NULL; + int pemSz; + int derSz; + DerBuffer* der = NULL; + WOLFSSL_X509_CRL* crl = NULL; + + if ((pemSz = wolfSSL_BIO_get_len(bp)) <= 0) { + goto err; + } + + pem = (unsigned char*)XMALLOC(pemSz, 0, DYNAMIC_TYPE_PEM); + if (pem == NULL) { + goto err; + } + + if (wolfSSL_BIO_read(bp, pem, pemSz) != pemSz) { + goto err; + } + + if((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0) { + goto err; + } + derSz = der->length; + if((crl = wolfSSL_d2i_X509_CRL(x, der->buffer, derSz)) == NULL) { + goto err; + } + +err: + if(pem != NULL) { + XFREE(pem, 0, DYNAMIC_TYPE_PEM); + } + if(der != NULL) { + FreeDer(&der); + } + + (void)cb; + (void)u; + + return crl; +#else + (void)bp; + (void)x; + (void)cb; + (void)u; + + return NULL; +#endif + } + +#if !defined(NO_FILESYSTEM) + static void* wolfSSL_PEM_read_X509_ex(XFILE fp, void **x, + pem_password_cb *cb, void *u, int type) + { + unsigned char* pem = NULL; + int pemSz; + long i = 0, l; + void *newx509; + int derSz; + DerBuffer* der = NULL; + + WOLFSSL_ENTER("wolfSSL_PEM_read_X509"); + + if (fp == XBADFILE) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_X509", BAD_FUNC_ARG); + return NULL; + } + /* Read cert from file */ + i = XFTELL(fp); + if (i < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_X509", BAD_FUNC_ARG); + return NULL; + } + + if (XFSEEK(fp, 0, XSEEK_END) != 0) + return NULL; + l = XFTELL(fp); + if (l < 0) + return NULL; + if (XFSEEK(fp, i, SEEK_SET) != 0) + return NULL; + pemSz = (int)(l - i); + + /* check calculated length */ + if (pemSz > MAX_WOLFSSL_FILE_SIZE || pemSz < 0) { + WOLFSSL_MSG("PEM_read_X509_ex file size error"); + return NULL; + } + + /* allocate pem buffer */ + pem = (unsigned char*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_PEM); + if (pem == NULL) + return NULL; + + if ((int)XFREAD((char *)pem, 1, pemSz, fp) != pemSz) + goto err_exit; + + switch (type) { + case CERT_TYPE: + newx509 = (void *)wolfSSL_X509_load_certificate_buffer(pem, + pemSz, WOLFSSL_FILETYPE_PEM); + break; + + #ifdef HAVE_CRL + case CRL_TYPE: + if ((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0) + goto err_exit; + derSz = der->length; + newx509 = (void*)wolfSSL_d2i_X509_CRL((WOLFSSL_X509_CRL **)x, + (const unsigned char *)der->buffer, derSz); + if (newx509 == NULL) + goto err_exit; + FreeDer(&der); + break; + #endif + + default: + goto err_exit; + } + if (x != NULL) { + *x = newx509; + } + XFREE(pem, NULL, DYNAMIC_TYPE_PEM); + return newx509; + + err_exit: + if (pem != NULL) + XFREE(pem, NULL, DYNAMIC_TYPE_PEM); + if (der != NULL) + FreeDer(&der); + + /* unused */ + (void)cb; + (void)u; + (void)derSz; + + return NULL; + } + + WOLFSSL_API WOLFSSL_X509* wolfSSL_PEM_read_X509(XFILE fp, WOLFSSL_X509 **x, + pem_password_cb *cb, void *u) + { + return (WOLFSSL_X509* )wolfSSL_PEM_read_X509_ex(fp, (void **)x, cb, u, CERT_TYPE); + } + +#if defined(HAVE_CRL) + WOLFSSL_API WOLFSSL_X509_CRL* wolfSSL_PEM_read_X509_CRL(XFILE fp, WOLFSSL_X509_CRL **crl, + pem_password_cb *cb, void *u) + { + return (WOLFSSL_X509_CRL* )wolfSSL_PEM_read_X509_ex(fp, (void **)crl, cb, u, CRL_TYPE); + } +#endif + + int wolfSSL_PEM_write_X509(XFILE fp, WOLFSSL_X509* x) + { + int ret; + WOLFSSL_BIO* bio; + + if (x == NULL) + return 0; + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio == NULL) + return 0; + + if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) { + wolfSSL_BIO_free(bio); + bio = NULL; + } + + ret = wolfSSL_PEM_write_bio_X509(bio, x); + + if (bio != NULL) + wolfSSL_BIO_free(bio); + + return ret; + } +#endif /* !NO_FILESYSTEM */ + + #define PEM_BEGIN "-----BEGIN " + #define PEM_BEGIN_SZ 11 + #define PEM_END "-----END " + #define PEM_END_SZ 9 + #define PEM_HDR_FIN "-----" + #define PEM_HDR_FIN_SZ 5 + #define PEM_HDR_FIN_EOL_NEWLINE "-----\n" + #define PEM_HDR_FIN_EOL_NULL_TERM "-----\0" + #define PEM_HDR_FIN_EOL_SZ 6 + + int wolfSSL_PEM_read_bio(WOLFSSL_BIO* bio, char **name, char **header, + unsigned char **data, long *len) + { + int ret = WOLFSSL_SUCCESS; + char pem[256]; + int pemLen; + char* p; + char* nameStr = NULL; + int nameLen = 0; + char* headerStr = NULL; + int headerLen; + int headerFound = 0; + unsigned char* der = NULL; + word32 derLen = 0; + + if (bio == NULL || name == NULL || header == NULL || data == NULL || + len == NULL) { + return WOLFSSL_FAILURE; + } + + /* Find header line. */ + pem[sizeof(pem) - 1] = '\0'; + while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) { + if (XSTRNCMP(pem, PEM_BEGIN, PEM_BEGIN_SZ) == 0) + break; + } + if (pemLen <= 0) + ret = WOLFSSL_FAILURE; + /* Have a header line. */ + if (ret == WOLFSSL_SUCCESS) { + while (pem[pemLen - 1] == '\r' || pem[pemLen - 1] == '\n') + pemLen--; + pem[pemLen] = '\0'; + if (XSTRNCMP(pem + pemLen - PEM_HDR_FIN_SZ, PEM_HDR_FIN, + PEM_HDR_FIN_SZ) != 0) { + ret = WOLFSSL_FAILURE; + } + } + + /* Get out name. */ + if (ret == WOLFSSL_SUCCESS) { + nameLen = pemLen - PEM_BEGIN_SZ - PEM_HDR_FIN_SZ; + nameStr = (char*)XMALLOC(nameLen + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (nameStr == NULL) + ret = WOLFSSL_FAILURE; + } + if (ret == WOLFSSL_SUCCESS) { + XSTRNCPY(nameStr, pem + PEM_BEGIN_SZ, nameLen); + nameStr[nameLen] = '\0'; + + /* Get header of PEM - encryption header. */ + headerLen = 0; + while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) { + while (pemLen > 0 && (pem[pemLen - 1] == '\r' || + pem[pemLen - 1] == '\n')) { + pemLen--; + } + pem[pemLen++] = '\n'; + pem[pemLen] = '\0'; + + /* Header separator is a blank line. */ + if (pem[0] == '\n') { + headerFound = 1; + break; + } + + /* Didn't find a blank line - no header. */ + if (XSTRNCMP(pem, PEM_END, PEM_END_SZ) == 0) { + der = (unsigned char*)headerStr; + derLen = headerLen; + /* Empty header - empty string. */ + headerStr = (char*)XMALLOC(1, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (headerStr == NULL) + ret = WOLFSSL_FAILURE; + else + headerStr[0] = '\0'; + break; + } + + p = (char*)XREALLOC(headerStr, headerLen + pemLen + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (p == NULL) { + ret = WOLFSSL_FAILURE; + break; + } + + headerStr = p; + XMEMCPY(headerStr + headerLen, pem, pemLen + 1); + headerLen += pemLen; + } + if (pemLen <= 0) + ret = WOLFSSL_FAILURE; + } + + /* Get body of PEM - if there was a header */ + if (ret == WOLFSSL_SUCCESS && headerFound) { + derLen = 0; + while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) { + while (pemLen > 0 && (pem[pemLen - 1] == '\r' || + pem[pemLen - 1] == '\n')) { + pemLen--; + } + pem[pemLen++] = '\n'; + pem[pemLen] = '\0'; + + if (XSTRNCMP(pem, PEM_END, PEM_END_SZ) == 0) + break; + + p = (char*)XREALLOC(der, derLen + pemLen + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (p == NULL) { + ret = WOLFSSL_FAILURE; + break; + } + + der = (unsigned char*)p; + XMEMCPY(der + derLen, pem, pemLen + 1); + derLen += pemLen; + } + if (pemLen <= 0) + ret = WOLFSSL_FAILURE; + } + + /* Check trailer. */ + if (ret == WOLFSSL_SUCCESS) { + if (XSTRNCMP(pem + PEM_END_SZ, nameStr, nameLen) != 0) + ret = WOLFSSL_FAILURE; + } + if (ret == WOLFSSL_SUCCESS) { + if (XSTRNCMP(pem + PEM_END_SZ + nameLen, + PEM_HDR_FIN_EOL_NEWLINE, + PEM_HDR_FIN_EOL_SZ) != 0 && + XSTRNCMP(pem + PEM_END_SZ + nameLen, + PEM_HDR_FIN_EOL_NULL_TERM, + PEM_HDR_FIN_EOL_SZ) != 0) { + ret = WOLFSSL_FAILURE; + } + } + + /* Base64 decode body. */ + if (ret == WOLFSSL_SUCCESS) { + if (Base64_Decode(der, derLen, der, &derLen) != 0) + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS) { + *name = nameStr; + *header = headerStr; + *data = der; + *len = derLen; + nameStr = NULL; + headerStr = NULL; + der = NULL; + } + + if (nameStr != NULL) + XFREE(nameStr, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (headerStr != NULL) + XFREE(headerStr, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der != NULL) + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; + } + + int wolfSSL_PEM_write_bio(WOLFSSL_BIO* bio, const char *name, + const char *header, const unsigned char *data, + long len) + { + int err = 0; + int outSz = 0; + int nameLen; + int headerLen; + byte* pem = NULL; + word32 pemLen; + word32 derLen = (word32)len; + + if (bio == NULL || name == NULL || header == NULL || data == NULL) + return 0; + + nameLen = (int)XSTRLEN(name); + headerLen = (int)XSTRLEN(header); + + pemLen = (derLen + 2) / 3 * 4; + pemLen += (pemLen + 63) / 64; + + pem = (byte*)XMALLOC(pemLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + err = pem == NULL; + if (!err) + err = Base64_Encode(data, derLen, pem, &pemLen) != 0; + + if (!err) { + err = wolfSSL_BIO_write(bio, PEM_BEGIN, PEM_BEGIN_SZ) != + (int)PEM_BEGIN_SZ; + } + if (!err) + err = wolfSSL_BIO_write(bio, name, nameLen) != nameLen; + if (!err) { + err = wolfSSL_BIO_write(bio, PEM_HDR_FIN_EOL_NEWLINE, + PEM_HDR_FIN_EOL_SZ) != (int)PEM_HDR_FIN_EOL_SZ; + } + if (!err && headerLen > 0) { + err = wolfSSL_BIO_write(bio, header, headerLen) != headerLen; + /* Blank line after a header and before body. */ + if (!err) + err = wolfSSL_BIO_write(bio, "\n", 1) != 1; + headerLen++; + } + if (!err) + err = wolfSSL_BIO_write(bio, pem, pemLen) != (int)pemLen; + if (!err) + err = wolfSSL_BIO_write(bio, PEM_END, PEM_END_SZ) != + (int)PEM_END_SZ; + if (!err) + err = wolfSSL_BIO_write(bio, name, nameLen) != nameLen; + if (!err) { + err = wolfSSL_BIO_write(bio, PEM_HDR_FIN_EOL_NEWLINE, + PEM_HDR_FIN_EOL_SZ) != (int)PEM_HDR_FIN_EOL_SZ; + } + + if (!err) { + outSz = PEM_BEGIN_SZ + nameLen + PEM_HDR_FIN_EOL_SZ + headerLen + + pemLen + PEM_END_SZ + nameLen + PEM_HDR_FIN_EOL_SZ; + } + + if (pem != NULL) + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return outSz; + } + +#if !defined(NO_FILESYSTEM) + int wolfSSL_PEM_read(XFILE fp, char **name, char **header, + unsigned char **data, long *len) + { + int ret; + WOLFSSL_BIO* bio; + + if (name == NULL || header == NULL || data == NULL || len == NULL) + return WOLFSSL_FAILURE; + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio == NULL) + return 0; + + if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) { + wolfSSL_BIO_free(bio); + bio = NULL; + } + + ret = wolfSSL_PEM_read_bio(bio, name, header, data, len); + + if (bio != NULL) + wolfSSL_BIO_free(bio); + + return ret; + } + + int wolfSSL_PEM_write(XFILE fp, const char *name, const char *header, + const unsigned char *data, long len) + { + int ret; + WOLFSSL_BIO* bio; + + if (name == NULL || header == NULL || data == NULL) + return 0; + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio == NULL) + return 0; + + if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) { + wolfSSL_BIO_free(bio); + bio = NULL; + } + + ret = wolfSSL_PEM_write_bio(bio, name, header, data, len); + + if (bio != NULL) + wolfSSL_BIO_free(bio); + + return ret; + } +#endif + + int wolfSSL_PEM_get_EVP_CIPHER_INFO(char* header, EncryptedInfo* cipher) + { + if (header == NULL || cipher == NULL) + return WOLFSSL_FAILURE; + + XMEMSET(cipher, 0, sizeof(*cipher)); + + if (wc_EncryptedInfoParse(cipher, &header, XSTRLEN(header)) != 0) + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; + } + + int wolfSSL_PEM_do_header(EncryptedInfo* cipher, unsigned char* data, + long* len, pem_password_cb* callback, void* ctx) + { + int ret = WOLFSSL_SUCCESS; + char password[NAME_SZ]; + int passwordSz; + + if (cipher == NULL || data == NULL || len == NULL || callback == NULL) + return WOLFSSL_FAILURE; + + passwordSz = callback(password, sizeof(password), PEM_PASS_READ, ctx); + if (passwordSz < 0) + ret = WOLFSSL_FAILURE; + + if (ret == WOLFSSL_SUCCESS) { + if (wc_BufferKeyDecrypt(cipher, data, (word32)*len, (byte*)password, + passwordSz, WC_MD5) != 0) { + ret = WOLFSSL_FAILURE; + } + } + + if (passwordSz > 0) + XMEMSET(password, 0, passwordSz); + + return ret; + } + + /* + * bp : bio to read X509 from + * x : x509 to write to + * cb : password call back for reading PEM + * u : password + * _AUX is for working with a trusted X509 certificate + */ + WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX(WOLFSSL_BIO *bp, + WOLFSSL_X509 **x, pem_password_cb *cb, void *u) { + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509"); + + /* AUX info is; trusted/rejected uses, friendly name, private key id, + * and potentially a stack of "other" info. wolfSSL does not store + * friendly name or private key id yet in WOLFSSL_X509 for human + * readability and does not support extra trusted/rejected uses for + * root CA. */ + return wolfSSL_PEM_read_bio_X509(bp, x, cb, u); + } + + +#ifdef OPENSSL_ALL + /* create and return a new WOLFSSL_X509_PKEY structure or NULL on failure */ + static WOLFSSL_X509_PKEY* wolfSSL_X509_PKEY_new(void* heap) + { + WOLFSSL_X509_PKEY* ret; + + ret = (WOLFSSL_X509_PKEY*)XMALLOC(sizeof(WOLFSSL_X509_PKEY), heap, + DYNAMIC_TYPE_KEY); + if (ret != NULL) { + XMEMSET(ret, 0, sizeof(WOLFSSL_X509_PKEY)); + ret->heap = heap; + } + return ret; + } + + + /* sets the values of X509_PKEY based on certificate passed in + * return WOLFSSL_SUCCESS on success */ + static int wolfSSL_X509_PKEY_set(WOLFSSL_X509_PKEY* xPkey, + WOLFSSL_X509* x509) + { + if (xPkey == NULL || x509 == NULL) { + return BAD_FUNC_ARG; + } + wolfSSL_EVP_PKEY_free(xPkey->dec_pkey); + xPkey->dec_pkey = wolfSSL_X509_get_pubkey(x509); + if (xPkey->dec_pkey == NULL) { + return WOLFSSL_FAILURE; + } + return WOLFSSL_SUCCESS; + } + + + /* free up all memory used by "xPkey" passed in */ + static void wolfSSL_X509_PKEY_free(WOLFSSL_X509_PKEY* xPkey) + { + if (xPkey != NULL) { + wolfSSL_EVP_PKEY_free(xPkey->dec_pkey); + } + XFREE(xPkey, xPkey->heap, DYNAMIC_TYPE_KEY); + } + + + /* Takes control of x509 on success + * helper function to break out code needed to set WOLFSSL_X509_INFO up + * free's "info" passed in if is not defaults + * + * returns WOLFSSL_SUCCESS on success + */ + static int wolfSSL_X509_INFO_set(WOLFSSL_X509_INFO* info, + WOLFSSL_X509* x509) + { + if (info == NULL || x509 == NULL) { + return BAD_FUNC_ARG; + } + + /* check is fresh "info" passed in, if not free it */ + if (info->x509 != NULL || info->x_pkey != NULL) { + WOLFSSL_X509_INFO* tmp; + + tmp = wolfSSL_X509_INFO_new(); + if (tmp == NULL) { + WOLFSSL_MSG("Unable to create new structure"); + return MEMORY_E; + } + wolfSSL_X509_INFO_free(info); + info = tmp; + } + + info->x509 = x509; + + //@TODO info->num + //@TODO info->enc_cipher + //@TODO info->enc_len + //@TODO info->enc_data + //@TODO info->crl + + info->x_pkey = wolfSSL_X509_PKEY_new(x509->heap); + return wolfSSL_X509_PKEY_set(info->x_pkey, x509); + } + + + /* + * bio WOLFSSL_BIO to read certificates from + * sk possible stack to push more X509_INFO structs to. Can be NULL + * cb callback password for encrypted PEM certificates + * u user input such as password + * + * returns stack on success and NULL or default stack passed in on fail + */ + WOLF_STACK_OF(WOLFSSL_X509_INFO)* wolfSSL_PEM_X509_INFO_read_bio( + WOLFSSL_BIO* bio, WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk, + pem_password_cb* cb, void* u) + { + WOLF_STACK_OF(WOLFSSL_X509_INFO)* localSk; + WOLFSSL_X509* x509 = NULL; + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_PEM_X509_INFO_read_bio"); + + /* attempt to used passed in stack or create a new one */ + if (sk != NULL) { + localSk = sk; + } + else { + localSk = wolfSSL_sk_X509_INFO_new_null(); + } + if (localSk == NULL) { + WOLFSSL_LEAVE("wolfSSL_PEM_X509_INFO_read_bio", MEMORY_E); + return NULL; + } + + /* parse through BIO and push new info's found onto stack */ + do { + x509 = wolfSSL_PEM_read_bio_X509(bio, NULL, cb, u); + if (x509 != NULL) { + WOLFSSL_X509_INFO* current; + + current = wolfSSL_X509_INFO_new(); + if (current == NULL) { + WOLFSSL_LEAVE("wolfSSL_PEM_X509_INFO_read_bio", MEMORY_E); + return NULL; + } + ret = wolfSSL_X509_INFO_set(current, x509); + if (ret != WOLFSSL_SUCCESS) { + wolfSSL_X509_free(x509); + } + else { + wolfSSL_sk_X509_INFO_push(localSk, current); + } + } + } while (x509 != NULL && ret == WOLFSSL_SUCCESS); + WOLFSSL_LEAVE("wolfSSL_PEM_X509_INFO_read_bio", ret); + return localSk; + } +#endif /* OPENSSL_ALL */ + + void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne) + { + WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_free"); + if (ne != NULL) { + if (ne->value != NULL && ne->value != &(ne->data)) { + wolfSSL_ASN1_STRING_free(ne->value); + } + XFREE(ne, NULL, DYNAMIC_TYPE_NAME_ENTRY); + } + } + + + WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void) + { + WOLFSSL_X509_NAME_ENTRY* ne; + + ne = (WOLFSSL_X509_NAME_ENTRY*)XMALLOC(sizeof(WOLFSSL_X509_NAME_ENTRY), + NULL, DYNAMIC_TYPE_NAME_ENTRY); + if (ne != NULL) { + XMEMSET(ne, 0, sizeof(WOLFSSL_X509_NAME_ENTRY)); + ne->value = &(ne->data); + } + + return ne; + } + + + /* Create a new WOLFSSL_X509_NAME_ENTRY structure based on the text passed + * in. Returns NULL on failure */ + WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_txt( + WOLFSSL_X509_NAME_ENTRY **neIn, const char *txt, int type, + const unsigned char *data, int dataSz) + { + int nid = -1; + WOLFSSL_X509_NAME_ENTRY* ne = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_create_by_txt()"); + + if (txt == NULL) { + return NULL; + } + + if (neIn != NULL) { + ne = *neIn; + } + + nid = wolfSSL_OBJ_txt2nid(txt); + if (nid == NID_undef) { + WOLFSSL_MSG("Unable to find text"); + ne = NULL; + } + else { + if (ne == NULL) { + ne = wolfSSL_X509_NAME_ENTRY_new(); + if (ne == NULL) { + return NULL; + } + } + ne->nid = nid; + ne->value = wolfSSL_ASN1_STRING_type_new(type); + if (ne->value != NULL) { + wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, dataSz); + ne->set = 1; + } + } + + return ne; + } + + + WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID( + WOLFSSL_X509_NAME_ENTRY** out, int nid, int type, + const unsigned char* data, int dataSz) + { + WOLFSSL_X509_NAME_ENTRY* ne; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_create_by_NID()"); + + ne = wolfSSL_X509_NAME_ENTRY_new(); + if (ne == NULL) { + return NULL; + } + + ne->nid = nid; + ne->value = wolfSSL_ASN1_STRING_type_new(type); + wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, dataSz); + ne->set = 1; + + if (out != NULL) { + *out = ne; + } + + return ne; + } + + static int RebuildFullNameAdd(DecodedName* dName, char* data) + { + int totalLen = 0; + int i; + char* fullName; + int idx; + + if (dName->cnLen != 0) + totalLen += dName->cnLen + 4; + if (dName->snLen != 0) + totalLen += dName->snLen + 4; + if (dName->cLen != 0) + totalLen += dName->cLen + 3; + if (dName->lLen != 0) + totalLen += dName->lLen + 3; + if (dName->stLen != 0) + totalLen += dName->stLen + 4; + if (dName->oLen != 0) + totalLen += dName->oLen + 3; + if (dName->ouLen != 0) + totalLen += dName->ouLen + 4; + if (dName->emailLen != 0) + totalLen += dName->emailLen + 14; + if (dName->uidLen != 0) + totalLen += dName->uidLen + 5; + if (dName->serialLen != 0) + totalLen += dName->serialLen + 14; + if (dName->dcNum != 0) { + for (i = 0; i < dName->dcNum; i++) + totalLen += dName->dcLen[i] + 4; + } + + fullName = (char*)XMALLOC(totalLen + 1, NULL, DYNAMIC_TYPE_X509); + if (fullName == NULL) + return MEMORY_E; + + idx = 0; + dName->entryCount = 0; + if (dName->cnLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_COMMON_NAME, 4); + idx += 4; + if (dName->cnIdx == -1) + XMEMCPY(fullName + idx, data, dName->cnLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->cnIdx, + dName->cnLen); + } + dName->cnIdx = idx; + idx += dName->cnLen; + } + if (dName->snLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_SUR_NAME, 4); + idx += 4; + if (dName->snIdx == -1) + XMEMCPY(fullName + idx, data, dName->snLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->snIdx, + dName->snLen); + } + dName->snIdx = idx; + idx += dName->snLen; + } + if (dName->cLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_COUNTRY_NAME, 3); + idx += 3; + if (dName->cIdx == -1) + XMEMCPY(fullName + idx, data, dName->cLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->cIdx, + dName->cLen); + } + dName->cIdx = idx; + idx += dName->cLen; + } + if (dName->lLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_LOCALITY_NAME, 3); + idx += 3; + if (dName->lIdx == -1) + XMEMCPY(fullName + idx, data, dName->lLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->lIdx, + dName->lLen); + } + dName->lIdx = idx; + idx += dName->lLen; + } + if (dName->stLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_STATE_NAME, 4); + idx += 4; + if (dName->stIdx == -1) + XMEMCPY(fullName + idx, data, dName->stLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->stIdx, + dName->stLen); + } + dName->stIdx = idx; + idx += dName->stLen; + } + if (dName->oLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_ORG_NAME, 3); + idx += 3; + if (dName->oIdx == -1) + XMEMCPY(fullName + idx, data, dName->oLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->oIdx, + dName->oLen); + } + dName->oIdx = idx; + idx += dName->oLen; + } + if (dName->ouLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_ORGUNIT_NAME, 4); + idx += 4; + if (dName->ouIdx == -1) + XMEMCPY(fullName + idx, data, dName->ouLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->ouIdx, + dName->ouLen); + } + dName->ouIdx = idx; + idx += dName->ouLen; + } + if (dName->emailLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, "/emailAddress=", 14); + idx += 14; + if (dName->emailIdx == -1) + XMEMCPY(fullName + idx, data, dName->emailLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->emailIdx, + dName->emailLen); + } + dName->emailIdx = idx; + idx += dName->emailLen; + } + if (dName->dcNum != 0) { + for (i = 0; i < dName->dcNum; i++) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_DOMAIN_COMPONENT, 4); + idx += 4; + XMEMCPY(fullName + idx, dName->fullName + dName->dcIdx[i], + dName->dcLen[i]); + dName->dcIdx[i] = idx; + idx += dName->dcLen[i]; + } + } + if (dName->uidLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, "/UID=", 5); + idx += 5; + if (dName->uidIdx == -1) + XMEMCPY(fullName + idx, data, dName->uidLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->uidIdx, + dName->uidLen); + } + dName->uidIdx = idx; + idx += dName->uidLen; + } + if (dName->serialLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_SERIAL_NUMBER, 14); + idx += 14; + if (dName->serialIdx == -1) + XMEMCPY(fullName + idx, data, dName->serialLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->serialIdx, + dName->serialLen); + } + dName->serialIdx = idx; + idx += dName->serialLen; + } + + if (dName->fullName != NULL) + XFREE(dName->fullName, NULL, DYNAMIC_TYPE_X509); + dName->fullName = fullName; + dName->fullNameLen = idx + 1; + + return 0; + } + + /* Copies entry into name. With it being copied freeing entry becomes the + * callers responsibility. + * returns 1 for success and 0 for error */ + int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name, + WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set) + { + int i; + int fullName = 1; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_add_entry()"); + + switch (entry->nid) { + case ASN_COMMON_NAME: + name->fullName.cnIdx = -1; + name->fullName.cnLen = entry->value->length; + name->fullName.cnNid = entry->nid; + break; + case ASN_SUR_NAME: + name->fullName.snIdx = -1; + name->fullName.snLen = entry->value->length; + name->fullName.snNid = entry->nid; + break; + case ASN_SERIAL_NUMBER: + name->fullName.serialIdx = -1; + name->fullName.serialLen = entry->value->length; + name->fullName.serialNid = entry->nid; + break; + case ASN_COUNTRY_NAME: + name->fullName.cIdx = -1; + name->fullName.cLen = entry->value->length; + name->fullName.cNid = entry->nid; + break; + case ASN_LOCALITY_NAME: + name->fullName.lIdx = -1; + name->fullName.lLen = entry->value->length; + name->fullName.lNid = entry->nid; + break; + case ASN_STATE_NAME: + name->fullName.stIdx = -1; + name->fullName.stLen = entry->value->length; + name->fullName.stNid = entry->nid; + break; + case ASN_ORG_NAME: + name->fullName.oIdx = -1; + name->fullName.oLen = entry->value->length; + name->fullName.oNid = entry->nid; + break; + case ASN_ORGUNIT_NAME: + name->fullName.ouIdx = -1; + name->fullName.ouLen = entry->value->length; + name->fullName.ouNid = entry->nid; + break; + case NID_emailAddress: + name->fullName.emailIdx = -1; + name->fullName.emailLen = entry->value->length; + name->fullName.emailNid = entry->nid; + break; + case ASN_USER_ID: + name->fullName.uidIdx = -1; + name->fullName.uidLen = entry->value->length; + name->fullName.uidNid = entry->nid; + break; + case ASN_DOMAIN_COMPONENT: + name->fullName.dcIdx[0] = -1; + name->fullName.dcLen[0] = entry->value->length; + break; + default: + fullName = 0; + break; + } + + if (fullName) { + int nid = entry->nid; + + if (nid == NID_emailAddress) { + nid = (int)ASN_EMAIL_NAME; + } + + if (idx >= DN_NAMES_MAX + DOMAIN_COMPONENT_MAX) { + return WOLFSSL_FAILURE; + } + + if (idx >= 0) { + name->fullName.loc[idx] = nid; + if (idx == name->fullName.locSz) { + name->fullName.locSz += 1; + } + } + + /* place at end */ + if (idx < 0 && name->fullName.locSz + 1 + < DN_NAMES_MAX + DOMAIN_COMPONENT_MAX) { + name->fullName.loc[name->fullName.locSz] = nid; + name->fullName.locSz += 1; + } + + if (RebuildFullNameAdd(&name->fullName, entry->value->data) != 0) + return WOLFSSL_FAILURE; + } + else { + for (i = 0; i < MAX_NAME_ENTRIES; i++) { + if (name->extra[i].set != 1) { /* not set so overwritten */ + WOLFSSL_X509_NAME_ENTRY* current = &(name->extra[i]); + WOLFSSL_ASN1_STRING* str; + + WOLFSSL_MSG("Found place for name entry"); + + XMEMCPY(current, entry, sizeof(WOLFSSL_X509_NAME_ENTRY)); + str = entry->value; + XMEMCPY(&(current->data), str, sizeof(WOLFSSL_ASN1_STRING)); + current->value = &(current->data); + current->data.data = (char*)XMALLOC(str->length, + name->x509->heap, DYNAMIC_TYPE_OPENSSL); + + if (current->data.data == NULL) { + return SSL_FAILURE; + } + XMEMCPY(current->data.data, str->data, str->length); + + /* make sure is null terminated */ + current->data.data[str->length - 1] = '\0'; + + current->set = 1; /* make sure now listed as set */ + break; + } + } + + if (i == MAX_NAME_ENTRIES) { + WOLFSSL_MSG("No spot found for name entry"); + return SSL_FAILURE; + } + } + + (void)idx; + (void)set; + return SSL_SUCCESS; + } + + int wolfSSL_X509_NAME_add_entry_by_txt(WOLFSSL_X509_NAME *name, + const char *field, int type, + const unsigned char *bytes, int len, + int loc, int set) + { + int ret = WOLFSSL_FAILURE; + int nid; + WOLFSSL_X509_NAME_ENTRY* entry; + + (void)type; + WOLFSSL_ENTER("wolfSSL_X509_NAME_add_entry_by_txt"); + + if (name == NULL || field == NULL) + return WOLFSSL_FAILURE; + + if ((nid = wolfSSL_OBJ_txt2nid(field)) == NID_undef) + return WOLFSSL_FAILURE; + + entry = wolfSSL_X509_NAME_ENTRY_create_by_NID(NULL, + nid, type, (unsigned char*)bytes, len); + if (entry == NULL) + return WOLFSSL_FAILURE; + + ret = wolfSSL_X509_NAME_add_entry(name, entry, loc, set); + wolfSSL_X509_NAME_ENTRY_free(entry); + + return ret; + } + + int wolfSSL_X509_NAME_add_entry_by_NID(WOLFSSL_X509_NAME *name, int nid, + int type, const unsigned char *bytes, + int len, int loc, int set) + { + int ret; + WOLFSSL_X509_NAME_ENTRY* entry; + entry = wolfSSL_X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len); + if (entry == NULL) + return WOLFSSL_FAILURE; + ret = wolfSSL_X509_NAME_add_entry(name, entry, loc, set); + wolfSSL_X509_NAME_ENTRY_free(entry); + return ret; + } + #endif /* !NO_CERTS */ + + + /* NID variables are dependent on compatibility header files currently + * + * returns a pointer to a new WOLFSSL_ASN1_OBJECT struct on success and NULL + * on fail + */ + + WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int id) + { + return wolfSSL_OBJ_nid2obj_ex(id, NULL); + } + + + WOLFSSL_LOCAL WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj_ex(int id, + WOLFSSL_ASN1_OBJECT* arg_obj) + { + word32 oidSz = 0; + const byte* oid; + word32 type = 0; + WOLFSSL_ASN1_OBJECT* obj = arg_obj; + byte objBuf[MAX_OID_SZ + MAX_LENGTH_SZ + 1]; /* +1 for object tag */ + word32 objSz = 0; + const char* sName = NULL; + int i; + + WOLFSSL_ENTER("wolfSSL_OBJ_nid2obj()"); + + for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) { + if (wolfssl_object_info[i].nid == id) { + id = wolfssl_object_info[i].id; + sName = wolfssl_object_info[i].sName; + type = wolfssl_object_info[i].type; + break; + } + } + if (i == (int)WOLFSSL_OBJECT_INFO_SZ) { + WOLFSSL_MSG("NID not in table"); + #ifdef WOLFSSL_QT + sName = NULL; + type = id; + #else + return NULL; + #endif + } + + #ifdef HAVE_ECC + if (type == 0 && wc_ecc_get_oid(id, &oid, &oidSz) > 0) { + type = oidCurveType; + } + #endif /* HAVE_ECC */ + + if (sName != NULL) { + if (XSTRLEN(sName) > WOLFSSL_MAX_SNAME - 1) { + WOLFSSL_MSG("Attempted short name is too large"); + return NULL; + } + } + + oid = OidFromId(id, type, &oidSz); + + /* set object ID to buffer */ + if (obj == NULL){ + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + return NULL; + } + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + } else { + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC; + } + obj->type = id; + obj->grp = type; + + obj->sName[0] = '\0'; + if (sName != NULL) { + XMEMCPY(obj->sName, (char*)sName, XSTRLEN((char*)sName)); + } + + objBuf[0] = ASN_OBJECT_ID; objSz++; + objSz += SetLength(oidSz, objBuf + 1); + XMEMCPY(objBuf + objSz, oid, oidSz); + objSz += oidSz; + obj->objSz = objSz; + if(((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) || + (obj->obj == NULL)) { + obj->obj = (byte*)XREALLOC((byte*)obj->obj, obj->objSz, NULL, + DYNAMIC_TYPE_ASN1); + if (obj->obj == NULL) { + wolfSSL_ASN1_OBJECT_free(obj); + return NULL; + } + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA ; + } else { + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA ; + } + XMEMCPY((byte*)obj->obj, objBuf, obj->objSz); + + (void)type; + + return obj; + } + + static const char* oid_translate_num_to_str(const char* oid) + { + const struct oid_dict { + const char* num; + const char* desc; + } oid_dict[] = { + { "2.5.29.37.0", "Any Extended Key Usage" }, + { "1.3.6.1.5.5.7.3.1", "TLS Web Server Authentication" }, + { "1.3.6.1.5.5.7.3.2", "TLS Web Client Authentication" }, + { "1.3.6.1.5.5.7.3.3", "Code Signing" }, + { "1.3.6.1.5.5.7.3.4", "E-mail Protection" }, + { "1.3.6.1.5.5.7.3.8", "Time Stamping" }, + { "1.3.6.1.5.5.7.3.9", "OCSP Signing" }, + { NULL, NULL } + }; + const struct oid_dict* idx; + + for (idx = oid_dict; idx->num != NULL; idx++) { + if (!XSTRNCMP(oid, idx->num, XSTRLEN(idx->num))) { + return idx->desc; + } + } + return NULL; + } + + /* if no_name is one than use numerical form otherwise can be short name. + * + * returns the buffer size on success + */ + int wolfSSL_OBJ_obj2txt(char *buf, int bufLen, WOLFSSL_ASN1_OBJECT *a, int no_name) + { + int bufSz; + const char* desc; + + WOLFSSL_ENTER("wolfSSL_OBJ_obj2txt()"); + + if (buf == NULL || bufLen <= 1 || a == NULL) { + WOLFSSL_MSG("Bad input argument"); + return WOLFSSL_FAILURE; + } + + if (no_name == 1) { + int length; + word32 idx = 0; + byte tag; + + if (GetASNTag(a->obj, &idx, &tag, a->objSz) != 0) { + return WOLFSSL_FAILURE; + } + + if (tag != ASN_OBJECT_ID) { + WOLFSSL_MSG("Bad ASN1 Object"); + return WOLFSSL_FAILURE; + } + + if (GetLength((const byte*)a->obj, &idx, &length, + a->objSz) < 0 || length < 0) { + return ASN_PARSE_E; + } + + if (bufLen < MAX_OID_STRING_SZ) { + bufSz = bufLen - 1; + } + else { + bufSz = MAX_OID_STRING_SZ; + } + + if ((bufSz = DecodePolicyOID(buf, (word32)bufSz, a->obj + idx, + (word32)length)) <= 0) { + WOLFSSL_MSG("Error decoding OID"); + return WOLFSSL_FAILURE; + } + + } + else { /* return short name */ + if (XSTRLEN(a->sName) + 1 < (word32)bufLen - 1) { + bufSz = (int)XSTRLEN(a->sName); + } + else { + bufSz = bufLen - 1; + } + if (bufSz) { + XMEMCPY(buf, a->sName, bufSz); + } + else if (wolfSSL_OBJ_obj2txt(buf, bufLen, a, 1)) { + if ((desc = oid_translate_num_to_str(buf))) { + bufSz = (int)XSTRLEN(desc); + XMEMCPY(buf, desc, min(bufSz, bufLen)); + } + } + else if (a->type == GEN_DNS || a->type == GEN_EMAIL || a->type == GEN_URI) { + bufSz = (int)XSTRLEN((const char*)a->obj); + XMEMCPY(buf, a->obj, min(bufSz, bufLen)); + } + } + + buf[bufSz] = '\0'; + #ifdef WOLFSSL_QT + /* For unknown extension types, QT expects the short name to be the + text representation of the oid */ + if (XSTRLEN(a->sName) == 0) { + XMEMCPY(a->sName, buf, bufSz); + } + #endif + return bufSz; + } +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + /* DN_Tags to strings */ + static const struct DN_Tag_Strings { + enum DN_Tags tag; + const char* str; + } dn_tag_strings[] = { + { ASN_COMMON_NAME, "CN" }, + { ASN_SUR_NAME, "SN" }, + { ASN_SERIAL_NUMBER, "serialNumber" }, + { ASN_COUNTRY_NAME, "C" }, + { ASN_LOCALITY_NAME, "L" }, + { ASN_STATE_NAME, "ST" }, + { ASN_ORG_NAME, "O"}, + { ASN_ORGUNIT_NAME, "OU"}, + { ASN_BUS_CAT, "businessCategory"}, + { ASN_EMAIL_NAME, "emailAddress"}, + { ASN_USER_ID, "UID"}, + { ASN_DOMAIN_COMPONENT, "DC"}, + { ASN_DN_NULL, NULL } + }; + + int wolfSSL_X509_NAME_get_index_by_OBJ(WOLFSSL_X509_NAME *name, + const WOLFSSL_ASN1_OBJECT *obj, + int idx) { + const struct DN_Tag_Strings* dn; + enum DN_Tags tag = ASN_DN_NULL; + + if (!name || idx >= name->fullName.locSz || + !obj || !obj->obj) { + return -1; + } + + if (idx < 0) { + idx = 0; + } + for (dn = dn_tag_strings; dn->str != NULL; dn++) { + /* Find the DN_Tags number for the name */ + if (XSTRNCMP((const char*) obj->sName, dn->str, obj->objSz - 1) == 0) { + tag = dn->tag; + break; + } + } + if (!tag) { + /* Unable to identify desired name */ + return -1; + } + for (idx++; idx < name->fullName.locSz; idx++) { + /* Find index of desired name */ + if ((enum DN_Tags)name->fullName.loc[idx] == tag) { + return idx; + } + } + return -1; + } +#endif + +#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \ + defined(WOLFSSL_HAPROXY) + +#ifndef NO_SHA + /* One shot SHA1 hash of message. + * + * d message to hash + * n size of d buffer + * md buffer to hold digest. Should be SHA_DIGEST_SIZE. + * + * Note: if md is null then a static buffer of SHA_DIGEST_SIZE is used. + * When the static buffer is used this function is not thread safe. + * + * Returns a pointer to the message digest on success and NULL on failure. + */ + unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, + unsigned char *md) + { + static byte dig[WC_SHA_DIGEST_SIZE]; + wc_Sha sha; + + WOLFSSL_ENTER("wolfSSL_SHA1"); + + if (wc_InitSha_ex(&sha, NULL, 0) != 0) { + WOLFSSL_MSG("SHA1 Init failed"); + return NULL; + } + + if (wc_ShaUpdate(&sha, (const byte*)d, (word32)n) != 0) { + WOLFSSL_MSG("SHA1 Update failed"); + return NULL; + } + + if (wc_ShaFinal(&sha, dig) != 0) { + WOLFSSL_MSG("SHA1 Final failed"); + return NULL; + } + + wc_ShaFree(&sha); + + if (md != NULL) { + XMEMCPY(md, dig, WC_SHA_DIGEST_SIZE); + return md; + } + else { + return (unsigned char*)dig; + } + } +#endif /* ! NO_SHA */ + +#ifndef NO_SHA256 + /* One shot SHA256 hash of message. + * + * d message to hash + * n size of d buffer + * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE. + * + * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used. + * When the static buffer is used this function is not thread safe. + * + * Returns a pointer to the message digest on success and NULL on failure. + */ + unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n, + unsigned char *md) + { + static byte dig[WC_SHA256_DIGEST_SIZE]; + wc_Sha256 sha; + + WOLFSSL_ENTER("wolfSSL_SHA256"); + + if (wc_InitSha256_ex(&sha, NULL, 0) != 0) { + WOLFSSL_MSG("SHA256 Init failed"); + return NULL; + } + + if (wc_Sha256Update(&sha, (const byte*)d, (word32)n) != 0) { + WOLFSSL_MSG("SHA256 Update failed"); + return NULL; + } + + if (wc_Sha256Final(&sha, dig) != 0) { + WOLFSSL_MSG("SHA256 Final failed"); + return NULL; + } + + wc_Sha256Free(&sha); + + if (md != NULL) { + XMEMCPY(md, dig, WC_SHA256_DIGEST_SIZE); + return md; + } + else { + return (unsigned char*)dig; + } + } +#endif /* ! NO_SHA256 */ + +#ifdef WOLFSSL_SHA384 + /* One shot SHA384 hash of message. + * + * d message to hash + * n size of d buffer + * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE. + * + * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used. + * When the static buffer is used this function is not thread safe. + * + * Returns a pointer to the message digest on success and NULL on failure. + */ + unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n, + unsigned char *md) + { + static byte dig[WC_SHA384_DIGEST_SIZE]; + wc_Sha384 sha; + + WOLFSSL_ENTER("wolfSSL_SHA384"); + + if (wc_InitSha384_ex(&sha, NULL, 0) != 0) { + WOLFSSL_MSG("SHA384 Init failed"); + return NULL; + } + + if (wc_Sha384Update(&sha, (const byte*)d, (word32)n) != 0) { + WOLFSSL_MSG("SHA384 Update failed"); + return NULL; + } + + if (wc_Sha384Final(&sha, dig) != 0) { + WOLFSSL_MSG("SHA384 Final failed"); + return NULL; + } + + wc_Sha384Free(&sha); + + if (md != NULL) { + XMEMCPY(md, dig, WC_SHA384_DIGEST_SIZE); + return md; + } + else { + return (unsigned char*)dig; + } + } +#endif /* WOLFSSL_SHA384 */ + + +#if defined(WOLFSSL_SHA512) + /* One shot SHA512 hash of message. + * + * d message to hash + * n size of d buffer + * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE. + * + * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used. + * When the static buffer is used this function is not thread safe. + * + * Returns a pointer to the message digest on success and NULL on failure. + */ + unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n, + unsigned char *md) + { + static byte dig[WC_SHA512_DIGEST_SIZE]; + wc_Sha512 sha; + + WOLFSSL_ENTER("wolfSSL_SHA512"); + + if (wc_InitSha512_ex(&sha, NULL, 0) != 0) { + WOLFSSL_MSG("SHA512 Init failed"); + return NULL; + } + + if (wc_Sha512Update(&sha, (const byte*)d, (word32)n) != 0) { + WOLFSSL_MSG("SHA512 Update failed"); + return NULL; + } + + if (wc_Sha512Final(&sha, dig) != 0) { + WOLFSSL_MSG("SHA512 Final failed"); + return NULL; + } + + wc_Sha512Free(&sha); + + if (md != NULL) { + XMEMCPY(md, dig, WC_SHA512_DIGEST_SIZE); + return md; + } + else { + return (unsigned char*)dig; + } + } +#endif /* defined(WOLFSSL_SHA512) */ +#endif /* OPENSSL_EXTRA */ + +#ifndef WOLFCRYPT_ONLY +#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \ + defined(WOLFSSL_HAPROXY) + + char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) + { + int ret; + + 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); + } + #ifndef WOLFSSL_X509_STORE_CERTS + ctx->ourCert = x; + #else + ctx->ourCert = wolfSSL_X509_d2i(NULL, x->derCert->buffer,x->derCert->length); + if(ctx->ourCert == NULL){ + return 0; + } + #endif + + 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 + #ifdef HAVE_ED448 + case ED448k: + #endif + case ECDSAk: + ctx->haveECC = 1; + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + ctx->pkCurveOID = x->pkCurveOID; + #endif + break; + } + + return WOLFSSL_SUCCESS; + } + + int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) + { + int ret; + if (ctx == NULL || x509 == NULL || x509->derCert == NULL) { + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_CTX_load_verify_buffer(ctx, x509->derCert->buffer, + x509->derCert->length, WOLFSSL_FILETYPE_ASN1); + + return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; + } + + int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) { + #ifndef NO_FILESYSTEM + XFILE fp; + + WOLFSSL_ENTER("wolfSSL_BIO_new_file"); + + if ((wolfSSL_BIO_get_fp(b, &fp) == WOLFSSL_SUCCESS) && (fp != XBADFILE)) + { + XFCLOSE(fp); + } + + fp = XFOPEN(name, "r"); + if (fp == XBADFILE) + 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 + } + + /* Return the corresponding short name for the nid . + * or NULL if short name can't be found. + */ + const char * wolfSSL_OBJ_nid2sn(int n) { + const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info; + size_t i; + WOLFSSL_ENTER("wolfSSL_OBJ_nid2sn"); + for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) { + if (obj_info->nid == n) { + return obj_info->sName; + } + } + WOLFSSL_MSG("SN not found"); + return NULL; + } + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + int wolfSSL_OBJ_sn2nid(const char *sn) { + WOLFSSL_ENTER("wolfSSL_OBJ_sn2nid"); + if (sn == NULL) + return NID_undef; + return wc_OBJ_sn2nid(sn); + } +#endif + + + /* Gets the NID value that corresponds with the ASN1 object. + * + * o ASN1 object to get NID of + * + * Return NID on success and a negative value on failure + */ + int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o) + { + word32 oid = 0; + word32 idx = 0; + + WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid"); + + if (o == NULL) { + return -1; + } + + #ifdef WOLFSSL_QT + if (o->grp == oidCertExtType) { + /* If nid is an unknown extension, return NID_undef */ + if (wolfSSL_OBJ_nid2sn(o->nid) == NULL) + return NID_undef; + } + #endif + + if (o->nid > 0) + return o->nid; + if (GetObjectId(o->obj, &idx, &oid, o->grp, o->objSz) < 0) { + WOLFSSL_MSG("Issue getting OID of object"); + return -1; + } + + return oid2nid(oid, o->grp); + } + + /* Returns the long name that corresponds with an ASN1_OBJECT nid value. + * n : NID value of ASN1_OBJECT to search */ + const char* wolfSSL_OBJ_nid2ln(int n) + { + const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info; + size_t i; + WOLFSSL_ENTER("wolfSSL_OBJ_nid2ln"); + for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) { + if (obj_info->nid == n) { + return obj_info->lName; + } + } + WOLFSSL_MSG("NID not found in table"); + return NULL; + } + + /* Return the corresponding NID for the long name + * or NID_undef if NID can't be found. + */ + int wolfSSL_OBJ_ln2nid(const char *ln) + { + const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info; + size_t i, lnlen; + WOLFSSL_ENTER("wolfSSL_OBJ_ln2nid"); + if (ln && (lnlen = XSTRLEN(ln)) > 0) { + /* Accept input like "/commonName=" */ + if (ln[0] == '/') { + ln++; + lnlen--; + } + if (lnlen) { + if (ln[lnlen-1] == '=') { + lnlen--; + } + for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) { + if (lnlen == XSTRLEN(obj_info->lName) && + XSTRNCMP(ln, obj_info->lName, lnlen) == 0) { + return obj_info->nid; + } + } + } + } + return NID_undef; + } + + /* compares two objects, return 0 if equal */ + int wolfSSL_OBJ_cmp(const WOLFSSL_ASN1_OBJECT* a, + const WOLFSSL_ASN1_OBJECT* b) + { + WOLFSSL_ENTER("wolfSSL_OBJ_cmp"); + + if (a != NULL && b != NULL && + a->obj != NULL && b->obj != NULL && + a->objSz == b->objSz) { + return XMEMCMP(a->obj, b->obj, a->objSz); + } + + return WOLFSSL_FATAL_ERROR; + } + + /* Gets the NID value that is related to the OID string passed in. Example + * string would be "2.5.29.14" for subject key ID. + * + * returns NID value on success and NID_undef on error + */ + int wolfSSL_OBJ_txt2nid(const char* s) + { + unsigned int i; + #ifdef WOLFSSL_CERT_EXT + int ret; + unsigned int sum = 0; + unsigned int outSz = MAX_OID_SZ; + unsigned char out[MAX_OID_SZ]; + #endif + + WOLFSSL_ENTER("OBJ_txt2nid"); + + if (s == NULL) { + return NID_undef; + } + + #ifdef WOLFSSL_CERT_EXT + ret = EncodePolicyOID(out, &outSz, s, NULL); + if (ret == 0) { + /* sum OID */ + for (i = 0; i < outSz; i++) { + sum += out[i]; + } + } + #endif /* WOLFSSL_CERT_EXT */ + + /* get the group that the OID's sum is in + * @TODO possible conflict with multiples */ + for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++) { + int len; + #ifdef WOLFSSL_CERT_EXT + if (ret == 0) { + if (wolfssl_object_info[i].id == (int)sum) { + return wolfssl_object_info[i].nid; + } + } + #endif + + /* try as a short name */ + len = (int)XSTRLEN(s); + if (XSTRNCMP(wolfssl_object_info[i].sName, s, len) == 0) { + return wolfssl_object_info[i].nid; + } + + /* try as a long name */ + if (XSTRNCMP(wolfssl_object_info[i].lName, s, len) == 0) { + return wolfssl_object_info[i].nid; + } + } + + return NID_undef; + } + + /* Creates new ASN1_OBJECT from short name, long name, or text + * representation of oid. If no_name is 0, then short name, long name, and + * numerical value of oid are interpreted. If no_name is 1, then only the + * numerical value of the oid is interpreted. + * + * Returns pointer to ASN1_OBJECT on success, or NULL on error. + */ +#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) + WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_txt2obj(const char* s, int no_name) + { + int len, i, ret; + int nid = NID_undef; + unsigned int outSz = MAX_OID_SZ; + unsigned char out[MAX_OID_SZ]; + unsigned int sum = 0; + + WOLFSSL_ENTER("wolfSSL_OBJ_txt2obj"); + + if (s == NULL) + return NULL; + + /* If s is numerical value, try to sum oid */ + ret = EncodePolicyOID(out, &outSz, s, NULL); + if (ret == 0) { + for (i = 0; i < (int)outSz; i++) { + sum += out[i]; + } + } + + len = (int)XSTRLEN(s); + + /* TODO: update short names in wolfssl_object_info and check OID sums + are correct */ + for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) { + /* Short name, long name, and numerical value are interpreted */ + if (no_name == 0 && ((XSTRNCMP(s, wolfssl_object_info[i].sName, len) == 0) || + (XSTRNCMP(s, wolfssl_object_info[i].lName, len) == 0) || + (wolfssl_object_info[i].id == (int)sum))) + nid = wolfssl_object_info[i].nid; + /* Only numerical value is interpreted */ + else if (no_name == 1 && wolfssl_object_info[i].id == (int)sum) + nid = wolfssl_object_info[i].nid; + } + + if (nid != NID_undef) + return wolfSSL_OBJ_nid2obj(nid); + + return NULL; + } +#endif + + /* compatibility function. Its intended use is to remove OID's from an + * internal table that have been added with OBJ_create. wolfSSL manages its + * own internal OID values and does not currently support OBJ_create. */ + void wolfSSL_OBJ_cleanup(void) + { + WOLFSSL_ENTER("wolfSSL_OBJ_cleanup()"); + } + + #ifndef NO_WOLFSSL_STUB + int wolfSSL_OBJ_create(const char *oid, const char *sn, const char *ln) + { + (void)oid; + (void)sn; + (void)ln; + WOLFSSL_STUB("wolfSSL_OBJ_create"); + return WOLFSSL_FAILURE; + } + #endif + + void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth) + { + #if !defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_STUB) + (void)ssl; + (void)depth; + WOLFSSL_STUB("wolfSSL_set_verify_depth"); + #else + WOLFSSL_ENTER("wolfSSL_set_verify_depth"); + ssl->options.verifyDepth = (byte)depth; + #endif + } + + + WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne) { + WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_object"); + if (ne == NULL) return NULL; + if (wolfSSL_OBJ_nid2obj_ex(ne->nid, &ne->object) != NULL) { + ne->object.nid = ne->nid; + return &ne->object; + } + return NULL; + } + + + /* looks up the DN given the location "loc". "loc" is the number indicating + * the order that the DN was parsed as, 0 is first DN parsed. + * + * returns the setup WOLFSSL_X509_NAME pointer on success and NULL on fail + */ + static WOLFSSL_X509_NAME* wolfSSL_nameByLoc(WOLFSSL_X509_NAME *name, int loc) + { + char* pt = NULL; + int sz = 0; + + switch (name->fullName.loc[loc]) + { + case ASN_COMMON_NAME: + sz = name->fullName.cnLen; + pt = &name->fullName.fullName[name->fullName.cnIdx]; + name->cnEntry.nid = name->fullName.cnNid; + break; + case ASN_COUNTRY_NAME: + sz = name->fullName.cLen; + pt = &name->fullName.fullName[name->fullName.cIdx]; + name->cnEntry.nid = name->fullName.cNid; + break; + case ASN_LOCALITY_NAME: + sz = name->fullName.lLen; + pt = &name->fullName.fullName[name->fullName.lIdx]; + name->cnEntry.nid = name->fullName.lNid; + break; + case ASN_STATE_NAME: + sz = name->fullName.stLen; + pt = &name->fullName.fullName[name->fullName.stIdx]; + name->cnEntry.nid = name->fullName.stNid; + break; + case ASN_ORG_NAME: + sz = name->fullName.oLen; + pt = &name->fullName.fullName[name->fullName.oIdx]; + name->cnEntry.nid = name->fullName.oNid; + break; + case ASN_ORGUNIT_NAME: + sz = name->fullName.ouLen; + pt = &name->fullName.fullName[name->fullName.ouIdx]; + name->cnEntry.nid = name->fullName.ouNid; + break; + case ASN_EMAIL_NAME: + sz = name->fullName.emailLen; + pt = &name->fullName.fullName[name->fullName.emailIdx]; + name->cnEntry.nid = name->fullName.emailNid; + break; + case ASN_SUR_NAME: + sz = name->fullName.snLen; + pt = &name->fullName.fullName[name->fullName.snIdx]; + name->cnEntry.nid = name->fullName.snNid; + break; + case ASN_USER_ID: + sz = name->fullName.uidLen; + pt = &name->fullName.fullName[name->fullName.uidIdx]; + name->cnEntry.nid = name->fullName.uidNid; + break; + case ASN_SERIAL_NUMBER: + sz = name->fullName.serialLen; + pt = &name->fullName.fullName[name->fullName.serialIdx]; + name->cnEntry.nid = name->fullName.serialNid; + break; +#ifdef WOLFSSL_CERT_EXT + case ASN_BUS_CAT: + sz = name->fullName.bcLen; + pt = &name->fullName.fullName[name->fullName.bcIdx]; + break; +#endif + + case ASN_DOMAIN_COMPONENT: + /* get index of DC i.e. first or second or ... case */ + { + int idx = 0, i; + for (i = 0; i < loc; i++) { + if (name->fullName.loc[i] == ASN_DOMAIN_COMPONENT) { + idx++; + } + } + + /* check that index is not larger than max buffer size or larger + * than the number of domain components parsed */ + if (idx >= DOMAIN_COMPONENT_MAX || idx > name->fullName.dcNum) { + WOLFSSL_MSG("Index was larger then domain buffer"); + return NULL; + } + pt = &name->fullName.fullName[name->fullName.dcIdx[idx]], + sz = name->fullName.dcLen[idx]; + name->cnEntry.nid = ASN_DOMAIN_COMPONENT; + name->cnEntry.data.type = CTC_UTF8; + } + break; + + default: + return NULL; + } + + /* -1 to leave room for trailing terminator 0 */ + if (sz == 0 || sz >= CTC_NAME_SIZE - 1) + return NULL; + if (wolfSSL_ASN1_STRING_set(name->cnEntry.value, pt, sz) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error setting local ASN1 string data"); + return NULL; + } + name->cnEntry.value->type = CTC_UTF8; + name->cnEntry.set = 1; + return name; + } + + + WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry( + WOLFSSL_X509_NAME *name, int loc) + { + WOLFSSL_ENTER("wolfSSL_X509_NAME_get_entry"); + + if (name == NULL) { + return NULL; + } + + if (loc < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + + if (loc <= DN_NAMES_MAX + name->fullName.dcNum) { + if (wolfSSL_nameByLoc(name, loc) != NULL) + return &name->cnEntry; + } + /* DC component */ + if (name->fullName.dcMode) { + if (name->fullName.fullName != NULL){ + if (loc == name->fullName.dcNum){ + name->cnEntry.data.data + = &name->fullName.fullName[name->fullName.cIdx]; + name->cnEntry.data.length = name->fullName.cLen; + name->cnEntry.nid = ASN_COUNTRY_NAME; + } else { + name->cnEntry.data.data + = &name->fullName.fullName[name->fullName.dcIdx[loc]]; + name->cnEntry.data.length = name->fullName.dcLen[loc]; + name->cnEntry.nid = ASN_DOMAIN_COMPONENT; + } + } + name->cnEntry.data.type = CTC_UTF8; + /* common name index case */ + } else if (loc == name->fullName.cnIdx && name->x509 != NULL) { + /* get CN shortcut from x509 since it has null terminator */ + name->cnEntry.data.data = name->x509->subjectCN; + name->cnEntry.data.length = name->fullName.cnLen; + name->cnEntry.data.type = CTC_UTF8; + name->cnEntry.nid = ASN_COMMON_NAME; + name->cnEntry.set = 1; + } else { + WOLFSSL_MSG("loc passed in is not in range of parsed DN's"); + return NULL; + } + return &name->cnEntry; + } + + #ifndef NO_WOLFSSL_STUB + int wolfSSL_X509_check_private_key(WOLFSSL_X509 *x509, WOLFSSL_EVP_PKEY *key) + { + (void) x509; + (void) key; + WOLFSSL_ENTER("wolfSSL_X509_check_private_key"); + WOLFSSL_STUB("X509_check_private_key"); + + return WOLFSSL_SUCCESS; + } + + 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("SSL_dup_CA_list"); + + return NULL; + } + + #endif + +#endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || + HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */ +#endif /* OPENSSL_EXTRA */ + +#ifndef WOLFCRYPT_ONLY + +#ifdef OPENSSL_EXTRA + +/* wolfSSL uses negative values for error states. This function returns an + * unsigned type so the value returned is the absolute value of the error. + */ +unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); + + (void)line; + (void)file; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(DEBUG_WOLFSSL) || \ + defined(WOLFSSL_HAPROXY) + { + int ret; + + if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + if (ret == -ASN_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + #endif + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif +} + + +#ifndef NO_CERTS +int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey"); + + if (ctx == NULL || pkey == NULL) { + return WOLFSSL_FAILURE; + } + + if (pkey->pkey.ptr != NULL) { + /* ptr for WOLFSSL_EVP_PKEY struct is expected to be DER format */ + return wolfSSL_CTX_use_PrivateKey_buffer(ctx, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, SSL_FILETYPE_ASN1); + } + + WOLFSSL_MSG("wolfSSL private key not set"); + return BAD_FUNC_ARG; +} +#endif /* !NO_CERTS */ + + +#if defined(HAVE_EX_DATA) || defined(FORTRESS) +void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); + #ifdef HAVE_EX_DATA + if(ctx != NULL) { + return wolfSSL_CRYPTO_get_ex_data(&ctx->ex_data, idx); + } + #else + (void)ctx; + (void)idx; + #endif + 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 ctx_idx++; +} + +/* Return the index that can be used for the WOLFSSL structure to store + * application data. + * + */ +int wolfSSL_get_ex_new_index(long argValue, void* arg, + WOLFSSL_CRYPTO_EX_new* cb1, WOLFSSL_CRYPTO_EX_dup* cb2, + WOLFSSL_CRYPTO_EX_free* cb3) +{ + static int ssl_idx = 0; + + WOLFSSL_ENTER("wolfSSL_get_ex_new_index"); + + (void)argValue; + (void)arg; + (void)cb1; + (void)cb2; + (void)cb3; + + return ssl_idx++; +} + + +int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data"); + #ifdef HAVE_EX_DATA + if (ctx != NULL) + { + return wolfSSL_CRYPTO_set_ex_data(&ctx->ex_data, idx, data); + } + #else + (void)ctx; + (void)idx; + (void)data; + #endif + return WOLFSSL_FAILURE; +} +#endif + + +/* Returns char* to app data stored in ex[0]. + * + * ssl WOLFSSL structure to get app data from + */ +void* wolfSSL_get_app_data(const WOLFSSL *ssl) +{ + /* checkout exdata stuff... */ + WOLFSSL_ENTER("wolfSSL_get_app_data"); + + return wolfSSL_get_ex_data(ssl, 0); +} + + +/* Set ex array 0 to have app data + * + * ssl WOLFSSL struct to set app data in + * arg data to be stored + * + * Returns SSL_SUCCESS on success and SSL_FAILURE on failure + */ +int wolfSSL_set_app_data(WOLFSSL *ssl, void* arg) { + WOLFSSL_ENTER("wolfSSL_set_app_data"); + + return wolfSSL_set_ex_data(ssl, 0, arg); +} + + +int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) +{ + WOLFSSL_ENTER("wolfSSL_set_ex_data"); +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + if (ssl != NULL) + { + return wolfSSL_CRYPTO_set_ex_data(&ssl->ex_data, idx, data); + } +#else + WOLFSSL_MSG("HAVE_EX_DATA macro is not defined"); + (void)ssl; + (void)idx; + (void)data; +#endif + return WOLFSSL_FAILURE; +} + + + +void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) +{ + WOLFSSL_ENTER("wolfSSL_get_ex_data"); +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + if (ssl != NULL) { + return wolfSSL_CRYPTO_get_ex_data(&ssl->ex_data, idx); + } +#else + WOLFSSL_MSG("HAVE_EX_DATA macro is not defined"); + (void)ssl; + (void)idx; +#endif + return 0; +} + +#ifndef NO_DSA +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; + unsigned char* buf; + word32 bufSz; + int ret; + word32 idx = 0; + DerBuffer* pDer; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSAparams"); + + ret = wolfSSL_BIO_get_mem_data(bp, &buf); + if (ret <= 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret); + return NULL; + } + + bufSz = (word32)ret; + + if (cb != NULL || u != NULL) { + /* + * cb is for a call back when encountering encrypted PEM files + * if cb == NULL and u != NULL then u = null terminated password string + */ + WOLFSSL_MSG("Not yet supporting call back or password for encrypted PEM"); + } + + if ((ret = PemToDer(buf, (long)bufSz, DSA_PARAM_TYPE, &pDer, NULL, NULL, + NULL)) < 0 ) { + WOLFSSL_MSG("Issue converting from PEM to DER"); + return NULL; + } + + if ((ret = GetSequence(pDer->buffer, &idx, &length, pDer->length)) < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret); + FreeDer(&pDer); + return NULL; + } + + dsa = wolfSSL_DSA_new(); + if (dsa == NULL) { + FreeDer(&pDer); + WOLFSSL_MSG("Error creating DSA struct"); + return NULL; + } + + key = (DsaKey*)dsa->internal; + if (key == NULL) { + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + WOLFSSL_MSG("Error finding DSA key struct"); + return NULL; + } + + if (GetInt(&key->p, pDer->buffer, &idx, pDer->length) < 0 || + GetInt(&key->q, pDer->buffer, &idx, pDer->length) < 0 || + GetInt(&key->g, pDer->buffer, &idx, pDer->length) < 0 ) { + WOLFSSL_MSG("dsa key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + 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) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa q key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa g key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (x != NULL) { + *x = dsa; + } + + FreeDer(&pDer); + return dsa; +} +#endif /* NO_DSA */ +#endif /* OPENSSL_EXTRA */ +#endif /* WOLFCRYPT_ONLY */ + +#if defined(OPENSSL_EXTRA) + +/* Begin functions for openssl/buffer.h */ +WOLFSSL_BUF_MEM* wolfSSL_BUF_MEM_new(void) +{ + WOLFSSL_BUF_MEM* buf; + buf = (WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM), NULL, + DYNAMIC_TYPE_OPENSSL); + if (buf) { + XMEMSET(buf, 0, sizeof(WOLFSSL_BUF_MEM)); + } + return buf; +} + + +/* returns length of buffer on success */ +int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len) +{ + int len_int = (int)len; + int mx; + + /* verify provided arguments */ + if (buf == NULL || len_int < 0) { + return 0; /* BAD_FUNC_ARG; */ + } + + /* check to see if fits in existing length */ + if (buf->length > len) { + buf->length = len; + return len_int; + } + + /* check to see if fits in max buffer */ + if (buf->max >= len) { + if (buf->data != NULL) { + XMEMSET(&buf->data[buf->length], 0, len - buf->length); + } + buf->length = len; + return len_int; + } + + /* expand size, to handle growth */ + mx = (len_int + 3) / 3 * 4; + + /* use realloc */ + buf->data = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buf->data == NULL) { + return 0; /* ERR_R_MALLOC_FAILURE; */ + } + + buf->max = mx; + XMEMSET(&buf->data[buf->length], 0, len - buf->length); + buf->length = len; + + return len_int; +} + +void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf) +{ + if (buf) { + if (buf->data) { + XFREE(buf->data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + buf->data = NULL; + } + buf->max = 0; + buf->length = 0; + XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); + } +} +/* End Functions for openssl/buffer.h */ + +#endif /* OPENSSL_EXTRA */ + + +#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) + +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 == XBADFILE) + 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; + return NULL; +#endif /* NO_FILESYSTEM */ +} + +#ifndef NO_FILESYSTEM +WOLFSSL_BIO* wolfSSL_BIO_new_fp(XFILE fp, int close_flag) +{ + WOLFSSL_BIO* bio; + + WOLFSSL_ENTER("wolfSSL_BIO_new_fp"); + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio == NULL) { + return bio; + } + + if (wolfSSL_BIO_set_fp(bio, fp, close_flag) != WOLFSSL_SUCCESS) { + wolfSSL_BIO_free(bio); + bio = NULL; + } + + /* file is closed when BIO is free'd or by user depending on flag */ + return bio; +} +#endif + + +#ifndef NO_DH +WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bio, WOLFSSL_DH **x, + pem_password_cb *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"); + (void)cb; + (void)u; + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + + if (bio->type == WOLFSSL_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 == WOLFSSL_BIO_FILE) { + /* Read whole file into a new buffer. */ + if (XFSEEK((XFILE)bio->ptr, 0, SEEK_END) != 0) + goto end; + sz = XFTELL((XFILE)bio->ptr); + if (XFSEEK((XFILE)bio->ptr, 0, SEEK_SET) != 0) + goto end; + if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0L) { + WOLFSSL_MSG("PEM_read_bio_DHparams file size error"); + goto end; + } + mem = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_PEM); + if (mem == NULL) + goto end; + memAlloced = 1; + + 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_new(); + if (localDh == NULL) + goto end; + } + + /* 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; + } + + if (localDh != NULL && localDh->inSet == 0) { + if (SetDhInternal(localDh) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Unable to set internal DH structure"); + 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; + (void)cb; + (void)u; + return NULL; +#endif +} + +#ifndef NO_FILESYSTEM +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) +/* Convert DH key parameters to DER format, write to output (outSz) + * If output is NULL then max expected size is set to outSz and LENGTH_ONLY_E is + * returned. + * + * Note : static function due to redefinition complications with DhKey and FIPS + * version 2 build. + * + * return bytes written on success */ +int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz) +{ + word32 sz = 0, idx = 0; + int pSz = 0, gSz = 0, ret; + byte scratch[MAX_LENGTH_SZ]; + + if (key == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + pSz = mp_unsigned_bin_size(&key->p); + if (pSz < 0) { + return pSz; + } + if (mp_leading_bit(&key->p)) { + pSz++; + } + + gSz = mp_unsigned_bin_size(&key->g); + if (gSz < 0) { + return gSz; + } + if (mp_leading_bit(&key->g)) { + gSz++; + } + + sz = ASN_TAG_SZ; /* Integer */ + sz += SetLength(pSz, scratch); + sz += ASN_TAG_SZ; /* Integer */ + sz += SetLength(gSz, scratch); + sz += gSz + pSz; + + if (out == NULL) { + byte seqScratch[MAX_SEQ_SZ]; + + *outSz = sz + SetSequence(sz, seqScratch); + return LENGTH_ONLY_E; + } + + if (*outSz < MAX_SEQ_SZ || *outSz < sz) { + return BUFFER_E; + } + + idx += SetSequence(sz, out); + if (*outSz < idx + sz) { + return BUFFER_E; + } + + out[idx++] = ASN_INTEGER; + idx += SetLength(pSz, out + idx); + if (mp_leading_bit(&key->p)) { + out[idx++] = 0x00; + pSz -= 1; /* subtract 1 from size to account for leading 0 */ + } + ret = mp_to_unsigned_bin(&key->p, out + idx); + if (ret != MP_OKAY) { + return BUFFER_E; + } + idx += pSz; + + out[idx++] = ASN_INTEGER; + idx += SetLength(gSz, out + idx); + if (mp_leading_bit(&key->g)) { + out[idx++] = 0x00; + gSz -= 1; /* subtract 1 from size to account for leading 0 */ + } + ret = mp_to_unsigned_bin(&key->g, out + idx); + if (ret != MP_OKAY) { + return BUFFER_E; + } + idx += gSz; + return idx; +} + +int wc_DhPubKeyToDer(DhKey* key, byte* out, word32* outSz) +{ + word32 sz = 0; + word32 paramSz = 0; + int ret; + int pubSz = 0; + int idx = 0; + byte scratch[MAX_ALGO_SZ]; + + /* Get size of entire key */ + + /* SEQUENCE <--| SetAlgoId + * OBJECT IDENTIFIER <--| + * SEQUENCE <-- + * INTEGER | wc_DhParamsToDer + * INTEGER <-- + */ + ret = wc_DhParamsToDer(key, NULL, ¶mSz); + if (ret != LENGTH_ONLY_E) + return ASN_PARSE_E; + sz += paramSz; + sz += SetAlgoID(DHk, scratch, oidKeyType, paramSz); + + /* BIT STRING + * INTEGER + */ + pubSz = mp_unsigned_bin_size(&key->pub); + if (pubSz < 0) + return pubSz; + + if (mp_leading_bit(&key->pub)) + pubSz++; + + sz += ASN_TAG_SZ; /* Integer */ + sz += SetLength(pubSz, scratch); + sz += pubSz; + + sz += SetBitString(pubSz, 0, scratch); + + if (out == NULL) { + /* Uppermost SEQUENCE */ + *outSz = sz + SetSequence(sz, scratch); + return LENGTH_ONLY_E; + } + /* end get size of entire key */ + + /* Check for indexing errors */ + if (*outSz < MAX_SEQ_SZ || *outSz < sz) { + return BUFFER_E; + } + + /* Build Up Entire Key */ + + idx += SetSequence(sz, out); + + idx += SetAlgoID(DHk, out+idx, oidKeyType, paramSz); + ret = wc_DhParamsToDer(key, out+idx, ¶mSz); + if (ret < 0) + return ret; + idx += ret; + + /* BIT STRING + * INTEGER + */ + idx += SetBitString(pubSz, 0, out+idx); + + out[idx++] = ASN_INTEGER; + idx += SetLength(pubSz, out + idx); + if (mp_leading_bit(&key->pub)) { + out[idx++] = 0x00; + pubSz -= 1; /* subtract 1 from size to account for leading 0 */ + } + ret = mp_to_unsigned_bin(&key->pub, out + idx); + if (ret != MP_OKAY) { + return BUFFER_E; + } + idx += pubSz; + + return idx; +} + +int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz) +{ + word32 sz = 0; + word32 paramSz = 0; + int ret; + int privSz = 0; + int idx = 0; + byte scratch[MAX_ALGO_SZ]; + + /* Get size of entire key */ + + /* INTEGER 0 */ + sz += ASN_TAG_SZ; /* Integer */ + sz += SetLength(1, scratch); + sz += 1; + + /* SEQUENCE <--| SetAlgoId + * OBJECT IDENTIFIER <--| + * SEQUENCE <-- + * INTEGER | wc_DhParamsToDer + * INTEGER <-- + */ + ret = wc_DhParamsToDer(key, NULL, ¶mSz); + if (ret != LENGTH_ONLY_E) + return ASN_PARSE_E; + sz += paramSz; + sz += SetAlgoID(DHk, scratch, oidKeyType, paramSz); + + /* OCTET STRING + * INTEGER + */ + privSz = mp_unsigned_bin_size(&key->priv); + if (privSz < 0) + return privSz; + else if (privSz > 256) /* Key is larger than 2048 */ + return ASN_VERSION_E; + + if (mp_leading_bit(&key->priv)) + privSz++; + + sz += ASN_TAG_SZ; /* Integer */ + sz += SetLength(privSz, scratch); + sz += privSz; + + sz += SetOctetString(privSz + ASN_OCTET_STRING, scratch); + + if (out == NULL) { + /* Uppermost SEQUENCE */ + *outSz = sz + SetSequence(sz, scratch); + return LENGTH_ONLY_E; + } + /* end get size of entire key */ + + /* Check for indexing errors */ + if (*outSz < MAX_SEQ_SZ || *outSz < sz) { + return BUFFER_E; + } + + /* Build Up Entire Key */ + + idx += SetSequence(sz, out); + + /* INTEGER 0 */ + out[idx++] = ASN_INTEGER; + idx += SetLength(1, out+idx); + out[idx++] = 0; + + idx += SetAlgoID(DHk, out+idx, oidKeyType, paramSz); + ret = wc_DhParamsToDer(key, out+idx, ¶mSz); + if (ret < 0) + return ret; + idx += ret; + + /* OCTET STRING + * INTEGER + */ + if (privSz == 256) { + idx += SetOctetString(privSz + ASN_OCTET_STRING, out+idx); + } else if (privSz == 128) { + idx += SetOctetString(privSz + ASN_OCTET_STRING-1, out+idx); + } else if (privSz == 64) { + idx += SetOctetString(privSz + ASN_OCTET_STRING-2, out+idx); + } else { + WOLFSSL_MSG("Unsupported key size"); + return ASN_VERSION_E; + } + + out[idx++] = ASN_INTEGER; + idx += SetLength(privSz, out + idx); + if (mp_leading_bit(&key->priv)) { + out[idx++] = 0x00; + privSz -= 1; /* subtract 1 from size to account for leading 0 */ + } + ret = mp_to_unsigned_bin(&key->priv, out + idx); + if (ret != MP_OKAY) { + return BUFFER_E; + } + idx += privSz; + + return idx; +} + +/* Writes the DH parameters in PEM format from "dh" out to the file pointer + * passed in. + * + * returns WOLFSSL_SUCCESS on success + */ +int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh) +{ + int ret; + word32 derSz = 0, pemSz = 0; + byte *der, *pem; + DhKey* key; + + WOLFSSL_ENTER("wolfSSL_PEM_write_DHparams"); + + if (dh == NULL) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", BAD_FUNC_ARG); + return WOLFSSL_FAILURE; + } + + if (dh->inSet == 0) { + if (SetDhInternal(dh) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Unable to set internal DH structure"); + return WOLFSSL_FAILURE; + } + } + key = (DhKey*)dh->internal; + ret = wc_DhParamsToDer(key, NULL, &derSz); + if (ret != LENGTH_ONLY_E) { + WOLFSSL_MSG("Failed to get size of DH params"); + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret); + return WOLFSSL_FAILURE; + } + + der = (byte*)XMALLOC(derSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", MEMORY_E); + return WOLFSSL_FAILURE; + } + ret = wc_DhParamsToDer(key, der, &derSz); + if (ret <= 0) { + WOLFSSL_MSG("Failed to export DH params"); + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret); + XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + /* convert to PEM */ + ret = wc_DerToPem(der, derSz, NULL, 0, DH_PARAM_TYPE); + if (ret < 0) { + WOLFSSL_MSG("Failed to convert DH params to PEM"); + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret); + XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + pemSz = (word32)ret; + + pem = (byte*)XMALLOC(pemSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", MEMORY_E); + XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + ret = wc_DerToPem(der, derSz, pem, pemSz, DH_PARAM_TYPE); + XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0) { + WOLFSSL_MSG("Failed to convert DH params to PEM"); + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret); + XFREE(pem, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + ret = (int)XFWRITE(pem, 1, pemSz, fp); + XFREE(pem, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret <= 0) { + WOLFSSL_MSG("Failed to write to file"); + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret); + return WOLFSSL_FAILURE; + } + + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_QT || OPENSSL_ALL */ +#endif /* !NO_FILESYSTEM */ +#endif /* !NO_DH */ + +#ifdef WOLFSSL_CERT_GEN + +#ifdef WOLFSSL_CERT_REQ +/* writes the x509 from x to the WOLFSSL_BIO bp + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail + */ +int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) +{ + byte* pem; + int pemSz = 0; + const unsigned char* der; + int derSz; + int ret; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_REQ()"); + + if (x == NULL || bp == NULL) { + return WOLFSSL_FAILURE; + } + + der = wolfSSL_X509_get_der(x, &derSz); + if (der == NULL) { + return WOLFSSL_FAILURE; + } + + /* get PEM size */ + pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERTREQ_TYPE); + if (pemSz < 0) { + return WOLFSSL_FAILURE; + } + + /* create PEM buffer and convert from DER */ + pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + return WOLFSSL_FAILURE; + } + if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERTREQ_TYPE) < 0) { + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + /* write the PEM to BIO */ + ret = wolfSSL_BIO_write(bp, pem, pemSz); + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret <= 0) return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_CERT_REQ */ + + +/* writes the x509 from x to the WOLFSSL_BIO bp + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail + */ +int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) +{ + byte* pem; + int pemSz = 0; + const unsigned char* der; + int derSz; + int ret; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX()"); + + if (bp == NULL || x == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return WOLFSSL_FAILURE; + } + + der = wolfSSL_X509_get_der(x, &derSz); + if (der == NULL) { + return WOLFSSL_FAILURE; + } + + /* get PEM size */ + pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE); + if (pemSz < 0) { + return WOLFSSL_FAILURE; + } + + /* create PEM buffer and convert from DER */ + pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + return WOLFSSL_FAILURE; + } + if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) { + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + /* write the PEM to BIO */ + ret = wolfSSL_BIO_write(bp, pem, pemSz); + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret <= 0) return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_CERT_GEN */ + +int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert) +{ + byte* pem; + int pemSz = 0; + const unsigned char* der; + int derSz; + int ret; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX()"); + + if (bio == NULL || cert == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return WOLFSSL_FAILURE; + } + + der = wolfSSL_X509_get_der(cert, &derSz); + if (der == NULL) { + return WOLFSSL_FAILURE; + } + + /* get PEM size */ + pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE); + if (pemSz < 0) { + return WOLFSSL_FAILURE; + } + + /* create PEM buffer and convert from DER */ + pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + return WOLFSSL_FAILURE; + } + if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) { + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + /* write the PEM to BIO */ + ret = wolfSSL_BIO_write(bio, pem, pemSz); + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret <= 0) return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; +} + + +#if defined(OPENSSL_EXTRA) && !defined(NO_DH) +/* Initialize 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; + byte *p, *g; + int ret=0; + + WOLFSSL_ENTER("wolfSSL_CTX_set_tmp_dh"); + + if(!ctx || !dh) + return BAD_FUNC_ARG; + + /* Get needed size for p and g */ + pSz = wolfSSL_BN_bn2bin(dh->p, NULL); + gSz = wolfSSL_BN_bn2bin(dh->g, NULL); + + if(pSz <= 0 || gSz <= 0) + return WOLFSSL_FATAL_ERROR; + + p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if(!p) + return MEMORY_E; + + g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if(!g) { + XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return MEMORY_E; + } + + pSz = wolfSSL_BN_bn2bin(dh->p, p); + gSz = wolfSSL_BN_bn2bin(dh->g, g); + + if(pSz >= 0 && gSz >= 0) /* Conversion successful */ + ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz); + + XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + + return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR; +} +#endif /* OPENSSL_EXTRA && !NO_DH */ + + +/* returns the enum value associated with handshake state + * + * ssl the WOLFSSL structure to get state of + */ +int wolfSSL_get_state(const WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_state"); + + if (ssl == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return SSL_FAILURE; + } + + return ssl->options.handShakeState; +} +#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \ + || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) + +long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt) +{ + WOLFSSL_ENTER("wolfSSL_ctrl"); + if (ssl == NULL) + return BAD_FUNC_ARG; + + switch (cmd) { + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + case SSL_CTRL_SET_TLSEXT_HOSTNAME: + WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TLSEXT_HOSTNAME."); + #ifdef HAVE_SNI + if (pt == NULL) { + WOLFSSL_MSG("Passed in NULL Host Name."); + break; + } + return wolfSSL_set_tlsext_host_name(ssl, (const char*) pt); + #else + WOLFSSL_MSG("SNI not enabled."); + break; + #endif /* HAVE_SNI */ + #endif /* WOLFSSL_NGINX || WOLFSSL_QT || OPENSSL_ALL */ + default: + WOLFSSL_MSG("Case not implemented."); + } + (void)opt; + (void)pt; + return WOLFSSL_FAILURE; +} + +long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt) +{ +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + long ctrl_opt; +#endif + long ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_CTX_ctrl"); + if (ctx == NULL) + return WOLFSSL_FAILURE; + + switch (cmd) { + case SSL_CTRL_CHAIN: +#ifdef SESSION_CERTS + { + /* + * We don't care about opt here because a copy of the certificate is + * stored anyway so increasing the reference counter is not necessary. + * Just check to make sure that it is set to one of the correct values. + */ + WOLF_STACK_OF(WOLFSSL_X509)* sk = (WOLF_STACK_OF(WOLFSSL_X509)*) pt; + WOLFSSL_X509* x509; + int i; + if (opt != 0 && opt != 1) { + ret = WOLFSSL_FAILURE; + break; + } + /* Clear certificate chain */ + FreeDer(&ctx->certChain); + if (sk) { + for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) { + x509 = wolfSSL_sk_X509_value(sk, i); + /* Prevent wolfSSL_CTX_add_extra_chain_cert from freeing cert */ + if (wolfSSL_X509_up_ref(x509) != 1) { + WOLFSSL_MSG("Error increasing reference count"); + continue; + } + if (wolfSSL_CTX_add_extra_chain_cert(ctx, x509) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error adding certificate to context"); + /* Decrease reference count on failure */ + wolfSSL_X509_free(x509); + } + } + } + /* Free previous chain */ + wolfSSL_sk_X509_free(ctx->x509Chain); + ctx->x509Chain = sk; + if (sk) { + for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) { + x509 = wolfSSL_sk_X509_value(sk, i); + /* On successful setting of new chain up all refs */ + if (wolfSSL_X509_up_ref(x509) != 1) { + WOLFSSL_MSG("Error increasing reference count"); + continue; + } + } + } + } +#else + WOLFSSL_MSG("Session certificates not compiled in"); + ret = WOLFSSL_FAILURE; +#endif + break; + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + case SSL_CTRL_OPTIONS: + WOLFSSL_MSG("Entering Case: SSL_CTRL_OPTIONS."); + ctrl_opt = wolfSSL_CTX_set_options(ctx, opt); + + #ifdef WOLFSSL_QT + /* Set whether to use client or server cipher preference */ + if ((ctrl_opt & SSL_OP_CIPHER_SERVER_PREFERENCE) + == SSL_OP_CIPHER_SERVER_PREFERENCE) { + WOLFSSL_MSG("Using Server's Cipher Preference."); + ctx->useClientOrder = FALSE; + } else { + WOLFSSL_MSG("Using Client's Cipher Preference."); + ctx->useClientOrder = TRUE; + } + #endif /* WOLFSSL_QT */ + + return ctrl_opt; +#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ + case SSL_CTRL_EXTRA_CHAIN_CERT: + WOLFSSL_MSG("Entering Case: SSL_CTRL_EXTRA_CHAIN_CERT."); + if (pt == NULL) { + WOLFSSL_MSG("Passed in x509 pointer NULL."); + ret = WOLFSSL_FAILURE; + break; + } + return wolfSSL_CTX_add_extra_chain_cert(ctx, (WOLFSSL_X509*)pt); + +#ifndef NO_DH + case SSL_CTRL_SET_TMP_DH: + WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TMP_DH."); + if (pt == NULL) { + WOLFSSL_MSG("Passed in DH pointer NULL."); + ret = WOLFSSL_FAILURE; + break; + } + return wolfSSL_CTX_set_tmp_dh(ctx, (WOLFSSL_DH*)pt); +#endif + +#ifdef HAVE_ECC + case SSL_CTRL_SET_TMP_ECDH: + WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TMP_ECDH."); + if (pt == NULL) { + WOLFSSL_MSG("Passed in ECDH pointer NULL."); + ret = WOLFSSL_FAILURE; + break; + } + return wolfSSL_SSL_CTX_set_tmp_ecdh(ctx, (WOLFSSL_EC_KEY*)pt); +#endif + case SSL_CTRL_MODE: + wolfSSL_CTX_set_mode(ctx,opt); + break; + + default: + WOLFSSL_MSG("CTX_ctrl cmd not implemented"); + ret = WOLFSSL_FAILURE; + break; + } + + (void)ctx; + (void)cmd; + (void)opt; + (void)pt; + WOLFSSL_LEAVE("wolfSSL_CTX_ctrl", (int)ret); + return ret; +} + +#ifndef WOLFSSL_NO_STUB +long wolfSSL_CTX_callback_ctrl(WOLFSSL_CTX* ctx, int cmd, void (*fp)(void)) +{ + (void) ctx; + (void) cmd; + (void) fp; + WOLFSSL_STUB("wolfSSL_CTX_callback_ctrl"); + return WOLFSSL_FAILURE; + +} +#endif /* WOLFSSL_NO_STUB */ + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_clear_extra_chain_certs(WOLFSSL_CTX* ctx) +{ + return wolfSSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS, 0l, NULL); +} +#endif + +/* Returns the verifyCallback from the ssl structure if successful. +Returns NULL otherwise. */ +VerifyCallback wolfSSL_get_verify_callback(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_verify_callback()"); + if (ssl) { + return ssl->verifyCallback; + } + return NULL; +} + +/* Creates a new bio pair. +Returns WOLFSSL_SUCCESS if no error, WOLFSSL_FAILURE otherwise.*/ +int wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO **bio1_p, size_t writebuf1, + WOLFSSL_BIO **bio2_p, size_t writebuf2) +{ + WOLFSSL_BIO *bio1 = NULL, *bio2 = NULL; + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_BIO_new_bio_pair()"); + + if (bio1_p == NULL || bio2_p == NULL) { + WOLFSSL_MSG("Bad Function Argument"); + return BAD_FUNC_ARG; + } + + /* set up the new bio structures and write buf sizes */ + if ((bio1 = wolfSSL_BIO_new(wolfSSL_BIO_s_bio())) == NULL) { + WOLFSSL_MSG("Bio allocation failed"); + ret = WOLFSSL_FAILURE; + } + if (ret) { + if ((bio2 = wolfSSL_BIO_new(wolfSSL_BIO_s_bio())) == NULL) { + WOLFSSL_MSG("Bio allocation failed"); + ret = WOLFSSL_FAILURE; + } + } + if (ret && writebuf1) { + if (!(ret = wolfSSL_BIO_set_write_buf_size(bio1, writebuf1))) { + WOLFSSL_MSG("wolfSSL_BIO_set_write_buf() failure"); + } + } + if (ret && writebuf2) { + if (!(ret = wolfSSL_BIO_set_write_buf_size(bio2, writebuf2))) { + WOLFSSL_MSG("wolfSSL_BIO_set_write_buf() failure"); + } + } + + if (ret) { + if ((ret = wolfSSL_BIO_make_bio_pair(bio1, bio2))) { + *bio1_p = bio1; + *bio2_p = bio2; + } + } + if (!ret) { + wolfSSL_BIO_free(bio1); + bio1 = NULL; + wolfSSL_BIO_free(bio2); + bio2 = NULL; + } + return ret; +} + + +#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \ + !defined(NO_RSA) && !defined(HAVE_USER_RSA) +/* Converts an rsa key from a bio buffer into an internal rsa structure. +Returns a pointer to the new WOLFSSL_RSA structure. */ +WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out) +{ + const unsigned char* bioMem = NULL; + int bioMemSz = 0; + WOLFSSL_RSA* key = NULL; + unsigned char maxKeyBuf[4096]; + unsigned char* bufPtr = NULL; + unsigned char* extraBioMem = NULL; + int extraBioMemSz = 0; + int derLength = 0; + int j = 0, i = 0; + + WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey_bio()"); + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument"); + return NULL; + } + (void)out; + + bioMemSz = wolfSSL_BIO_pending(bio); + if (bioMemSz <= 0) { + WOLFSSL_MSG("wolfSSL_BIO_pending() failure"); + return NULL; + } + + bioMem = (unsigned char*)XMALLOC(bioMemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (bioMem == NULL) { + WOLFSSL_MSG("Malloc failure"); + return NULL; + } + + bufPtr = maxKeyBuf; + if (wolfSSL_BIO_read(bio, (unsigned char*)bioMem, (int)bioMemSz) == bioMemSz) { + const byte* bioMemPt = bioMem; /* leave bioMem pointer unaltered */ + if ((key = wolfSSL_d2i_RSAPrivateKey(NULL, &bioMemPt, bioMemSz)) == NULL) { + XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + /* This function is used to get the total length of the rsa key. */ + derLength = wolfSSL_i2d_RSAPrivateKey(key, &bufPtr); + + /* Write extra data back into bio object if necessary. */ + extraBioMemSz = (bioMemSz - derLength); + if (extraBioMemSz > 0) { + extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (extraBioMem == NULL) { + WOLFSSL_MSG("Malloc failure"); + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + XFREE((unsigned char*)bioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + for (i = derLength; i < bioMemSz; i++) { + *(extraBioMem + j) = *(bioMem + i); + j++; + } + + wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz); + if (wolfSSL_BIO_pending(bio) <= 0) { + WOLFSSL_MSG("Failed to write memory to bio"); + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + XFREE((unsigned char*)bioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + } + + if (out != NULL && key != NULL) { + *out = key; + } + } + XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return key; +} +#endif + + +/* Adds the ASN1 certificate to the user ctx. +Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/ +int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX *ctx, int derSz, + const unsigned char *der) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_ASN1()"); + if (der != NULL && ctx != NULL) { + if (wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz, + WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + + } + return WOLFSSL_FAILURE; +} + + +#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \ + !defined(NO_RSA) && !defined(HAVE_USER_RSA) +/* Adds the rsa private key to the user ctx. +Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/ +int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa) +{ + int ret; + int derSize; + unsigned char maxDerBuf[4096]; + unsigned char* key = NULL; + + WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey()"); + + if (ctx == NULL || rsa == NULL) { + WOLFSSL_MSG("one or more inputs were NULL"); + return BAD_FUNC_ARG; + } + key = maxDerBuf; + /* convert RSA struct to der encoded buffer and get the size */ + if ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, &key)) <= 0) { + WOLFSSL_MSG("wolfSSL_i2d_RSAPrivateKey() failure"); + return WOLFSSL_FAILURE; + } + ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, (const unsigned char*)maxDerBuf, + derSize, SSL_FILETYPE_ASN1); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_CTX_USE_PrivateKey_buffer() failure"); + return WOLFSSL_FAILURE; + } + return ret; +} +#endif /* NO_RSA && !HAVE_FAST_RSA */ + + +/* Converts EVP_PKEY data from a bio buffer to a WOLFSSL_EVP_PKEY structure. +Returns pointer to private EVP_PKEY struct upon success, NULL if there +is a failure.*/ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** out) +{ + unsigned char* mem = NULL; + int memSz = 0; + WOLFSSL_EVP_PKEY* key = NULL; + int i = 0, j = 0; + unsigned char* extraBioMem = NULL; + int extraBioMemSz = 0; + int derLength = 0; + + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio()"); + + if (bio == NULL) { + return NULL; + } + (void)out; + + memSz = wolfSSL_BIO_pending(bio); + if (memSz <= 0) { + WOLFSSL_MSG("wolfSSL_BIO_pending() failure"); + return NULL; + } + + mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { + WOLFSSL_MSG("Malloc failure"); + return NULL; + } + + if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) { + /* Determines key type and returns the new private EVP_PKEY object */ + if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) == NULL) { + WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure"); + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + /* Write extra data back into bio object if necessary. */ + derLength = key->pkey_sz; + extraBioMemSz = (memSz - derLength); + if (extraBioMemSz > 0) { + extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (extraBioMem == NULL) { + WOLFSSL_MSG("Malloc failure"); + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + for (i = derLength; i < memSz; i++) { + *(extraBioMem + j) = *(mem + i); + j++; + } + + wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz); + if (wolfSSL_BIO_pending(bio) <= 0) { + WOLFSSL_MSG("Failed to write memory to bio"); + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + } + + if (out != NULL) { + *out = key; + } + } + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return key; +} + + +/* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure. + * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL + * on fail */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out, + unsigned char** in, long inSz) +{ + WOLFSSL_EVP_PKEY* pkey = NULL; + const unsigned char* mem; + long memSz = inSz; + + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP()"); + + if (in == NULL || *in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + mem = *in; + + #if !defined(NO_RSA) + { + RsaKey rsa; + word32 keyIdx = 0; + + /* test if RSA key */ + if (wc_InitRsaKey(&rsa, NULL) == 0 && + wc_RsaPrivateKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) { + wc_FreeRsaKey(&rsa); + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey != NULL) { + pkey->pkey_sz = keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, + DYNAMIC_TYPE_PRIVATE_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_RSA; + if (out != NULL) { + *out = pkey; + } + + pkey->ownRsa = 1; + pkey->rsa = wolfSSL_RSA_new(); + if (pkey->rsa == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + if (wolfSSL_RSA_LoadDer_ex(pkey->rsa, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, WOLFSSL_RSA_LOAD_PRIVATE) != 1) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + return pkey; + } + } + wc_FreeRsaKey(&rsa); + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + { + word32 keyIdx = 0; + ecc_key ecc; + + /* test if ecc key */ + if (wc_ecc_init(&ecc) == 0 && + wc_EccPrivateKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) { + wc_ecc_free(&ecc); + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey != NULL) { + pkey->pkey_sz = keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL, + DYNAMIC_TYPE_PRIVATE_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_EC; + if (out != NULL) { + *out = pkey; + } + return pkey; + } + } + wc_ecc_free(&ecc); + } + #endif /* HAVE_ECC */ + return pkey; +} +#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */ + + +/* stunnel compatibility functions*/ +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH))) +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) { + return wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, data); + } +#else + (void)session; + (void)idx; + (void)data; +#endif + return WOLFSSL_FAILURE; +} + + +int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, + void* cb2, CRYPTO_free_func* cb3) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_new_index"); + (void)idx; + (void)cb1; + (void)cb2; + (void)cb3; + if (XSTRNCMP((const char*)data, "redirect index", 14) == 0) { + return 0; + } + else if (XSTRNCMP((const char*)data, "addr index", 10) == 0) { + return 1; + } + 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) { + return wolfSSL_CRYPTO_get_ex_data(&session->ex_data, idx); + } +#else + (void)session; + (void)idx; +#endif + return NULL; +} + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int), + void *(*r) (void *, size_t, const char *, + int), void (*f) (void *)) +{ + (void) m; + (void) r; + (void) f; + WOLFSSL_ENTER("wolfSSL_CRYPTO_set_mem_ex_functions"); + WOLFSSL_STUB("CRYPTO_set_mem_ex_functions"); + + return WOLFSSL_FAILURE; +} +#endif + + +void wolfSSL_CRYPTO_cleanup_all_ex_data(void){ + WOLFSSL_ENTER("CRYPTO_cleanup_all_ex_data"); +} + + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator, + void (*callback) (int, int, void *), void *cb_arg) +{ + (void)prime_len; + (void)generator; + (void)callback; + (void)cb_arg; + WOLFSSL_ENTER("wolfSSL_DH_generate_parameters"); + WOLFSSL_STUB("DH_generate_parameters"); + + return NULL; +} +#endif + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH* dh, int prime_len, int generator, + void (*callback) (int, int, void *)) +{ + (void)prime_len; + (void)generator; + (void)callback; + (void)dh; + WOLFSSL_ENTER("wolfSSL_DH_generate_parameters_ex"); + WOLFSSL_STUB("DH_generate_parameters_ex"); + + return -1; +} +#endif + +void wolfSSL_ERR_load_crypto_strings(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings"); + /* Do nothing */ + return; +} + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_FIPS_mode(void) +{ + WOLFSSL_ENTER("wolfSSL_FIPS_mode"); + WOLFSSL_STUB("FIPS_mode"); + + return WOLFSSL_FAILURE; +} +#endif + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_FIPS_mode_set(int r) +{ + (void)r; + WOLFSSL_ENTER("wolfSSL_FIPS_mode_set"); + WOLFSSL_STUB("FIPS_mode_set"); + + return WOLFSSL_FAILURE; +} +#endif + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_RAND_set_rand_method(const void *meth) +{ + (void) meth; + WOLFSSL_ENTER("wolfSSL_RAND_set_rand_method"); + WOLFSSL_STUB("RAND_set_rand_method"); + + /* if implemented RAND_bytes and RAND_pseudo_bytes need updated + * those two functions will call the respective functions from meth */ + return SSL_FAILURE; +} +#endif + +int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) +{ + int ret = WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits"); + + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + (void)alg_bits; + if (c!= NULL) + ret = c->bits; + #else + if (c != NULL && c->ssl != NULL) { + ret = 8 * c->ssl->specs.key_size; + if (alg_bits != NULL) { + *alg_bits = ret; + } + } + #endif + return ret; +} + +#if defined(OPENSSL_ALL) +WOLFSSL_X509_INFO* wolfSSL_X509_INFO_new(void) +{ + WOLFSSL_X509_INFO* info; + info = (WOLFSSL_X509_INFO*)XMALLOC(sizeof(WOLFSSL_X509_INFO), NULL, + DYNAMIC_TYPE_X509); + if (info) { + XMEMSET(info, 0, sizeof(*info)); + } + return info; +} + +void wolfSSL_X509_INFO_free(WOLFSSL_X509_INFO* info) +{ + if (info == NULL) + return; + + if (info->x509) { + wolfSSL_X509_free(info->x509); + info->x509 = NULL; + } +#ifdef HAVE_CRL + if (info->crl) { + wolfSSL_X509_CRL_free(info->crl); + info->crl = NULL; + } +#endif + wolfSSL_X509_PKEY_free(info->x_pkey); + info->x_pkey = NULL; + + XFREE(info, NULL, DYNAMIC_TYPE_X509); +} +#endif + +WOLFSSL_STACK* wolfSSL_sk_X509_INFO_new_null(void) +{ + WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL); + if (sk) { + sk->type = STACK_TYPE_X509_INFO; + } + return sk; +} + + +/* returns value less than 0 on fail to match + * On a successful match the priority level found is returned + */ +int wolfSSL_sk_SSL_CIPHER_find( + WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, const WOLFSSL_CIPHER* toFind) +{ + WOLFSSL_STACK* next; + int i, sz; + + if (sk == NULL || toFind == NULL) { + return WOLFSSL_FATAL_ERROR; + } + + sz = wolfSSL_sk_SSL_CIPHER_num(sk); + next = sk; + for (i = 0; i < sz && next != NULL; i++) { + if (next->data.cipher.cipherSuite0 == toFind->cipherSuite0 && + next->data.cipher.cipherSuite == toFind->cipherSuite) { + return sz - i; /* reverse because stack pushed highest on first */ + } + next = next->next; + } + return WOLFSSL_FATAL_ERROR; +} + + +/* copies over data of "in" to "out" */ +static void wolfSSL_CIPHER_copy(WOLFSSL_CIPHER* in, WOLFSSL_CIPHER* out) +{ + if (in == NULL || out == NULL) + return; + + out->cipherSuite = in->cipherSuite; + out->cipherSuite0 = in->cipherSuite0; +} + + +/* create duplicate of stack and return the new stack + * returns null on failure */ +WOLF_STACK_OF(WOLFSSL_CIPHER)* wolfSSL_sk_SSL_CIPHER_dup( + WOLF_STACK_OF(WOLFSSL_CIPHER)* in) +{ + WOLFSSL_STACK* current; + WOLF_STACK_OF(WOLFSSL_CIPHER)* ret = NULL; + int i, sz; + + sz = wolfSSL_sk_SSL_CIPHER_num(in); + current = in; + for (i = 0; i < sz && current != NULL; i++) { + WOLFSSL_STACK* add = wolfSSL_sk_new_node(in->heap); + if (add != NULL) { + add->type = STACK_TYPE_CIPHER; + wolfSSL_CIPHER_copy(&(current->data.cipher), &(add->data.cipher)); + add->num = i+1; + add->next = ret; + ret = add; + current = current->next; + } + } + return ret; +} + +/* nothing to do yet */ +static void wolfSSL_CIPHER_free(WOLFSSL_CIPHER* in) +{ + (void)in; +} + + +/* free's all nodes in the stack and there data */ +void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk) +{ + WOLFSSL_STACK* current = sk; + + while (current != NULL) { + WOLFSSL_STACK* toFree = current; + current = current->next; + + wolfSSL_CIPHER_free(&(toFree->data.cipher)); + wolfSSL_sk_free_node(toFree); + } +} + + +int wolfSSL_sk_X509_INFO_num(const WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_num"); + + if (sk == NULL) + return -1; + return (int)sk->num; +} + +WOLFSSL_X509_INFO* wolfSSL_sk_X509_INFO_value(const WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_value"); + + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.info; +} + +WOLFSSL_X509_INFO* wolfSSL_sk_X509_INFO_pop(WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_X509_INFO* info; + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + info = sk->data.info; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.info = node->data.info; + sk->next = node->next; + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + } + else { /* last x509 in stack */ + sk->data.info = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return info; +} + +#if defined(OPENSSL_ALL) +void wolfSSL_sk_X509_INFO_pop_free(WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk, + void (*f) (WOLFSSL_X509_INFO*)) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_pop_free"); + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (node && sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + if (f) + f(tmp->data.info); + else + wolfSSL_X509_INFO_free(tmp->data.info); + tmp->data.info = NULL; + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + if (f) + f(sk->data.info); + else + wolfSSL_X509_INFO_free(sk->data.info); + sk->data.info = NULL; + } + XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); +} + +void wolfSSL_sk_X509_INFO_free(WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk) +{ + wolfSSL_sk_X509_INFO_pop_free(sk, NULL); +} + + +/* Adds the WOLFSSL_X509_INFO to the stack "sk". "sk" takes control of "in" and + * tries to free it when the stack is free'd. + * + * return 1 on success 0 on fail + */ +int wolfSSL_sk_X509_INFO_push(WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk, + WOLFSSL_X509_INFO* in) +{ + WOLFSSL_STACK* node; + + if (sk == NULL || in == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.info == NULL) { + sk->data.info = in; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_X509); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.info = sk->data.info; + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->data.info = in; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + + +WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_sk_X509_NAME_new(wolf_sk_compare_cb cb) +{ + WOLFSSL_STACK* sk; + + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_new"); + + sk = wolfSSL_sk_new_node(NULL); + if (sk != NULL) { + sk->type = STACK_TYPE_X509_NAME; + sk->comp = cb; + } + + return sk; +} + +int wolfSSL_sk_X509_NAME_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, + WOLFSSL_X509_NAME* name) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_push"); + + if (sk == NULL || name == NULL) { + return BAD_FUNC_ARG; + } + + /* no previous values in stack */ + if (sk->data.name == NULL) { + sk->data.name = name; + sk->num += 1; + return 0; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return MEMORY_E; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.name = sk->data.name; + node->next = sk->next; + sk->type = STACK_TYPE_X509_NAME; + sk->next = node; + sk->data.name = name; + sk->num += 1; + + return 0; +} + +/* return index of found, or negative to indicate not found */ +int wolfSSL_sk_X509_NAME_find(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk, + WOLFSSL_X509_NAME *name) +{ + int i; + + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_find"); + + if (sk == NULL) + return BAD_FUNC_ARG; + + for (i = 0; sk; i++, sk = sk->next) { + if (wolfSSL_X509_NAME_cmp(sk->data.name, name) == 0) { + return i; + } + } + return -1; +} + +int wolfSSL_sk_X509_OBJECT_num(const WOLF_STACK_OF(WOLFSSL_X509_OBJECT) *s) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_num"); + if (s) { + return (int)s->num; + } else { + return 0; + } +} + + +int wolfSSL_sk_X509_NAME_set_cmp_func(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, + wolf_sk_compare_cb cb) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_set_cmp_func"); + + if (sk == NULL) + return BAD_FUNC_ARG; + + sk->comp = cb; + return 0; +} +#endif /* OPENSSL_ALL */ + +int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num"); + + if (sk == NULL) + return BAD_FUNC_ARG; + + return (int)sk->num; +} + +/* Getter function for WOLFSSL_X509_NAME pointer + * + * sk is the stack to retrieve pointer from + * i is the index value in stack + * + * returns a pointer to a WOLFSSL_X509_NAME structure on success and NULL on + * fail + */ +WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk, + int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value"); + + for (; sk != NULL && i > 0; i--) { + sk = sk->next; + } + + if (i != 0 || sk == NULL) + return NULL; + + return sk->data.name; +} + +WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_X509_NAME* name; + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + name = sk->data.name; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.name = node->data.name; + sk->next = node->next; + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + } + else { /* last x509 in stack */ + sk->data.name = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return name; +} + +void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, + void (*f) (WOLFSSL_X509_NAME*)) +{ + WOLFSSL_STACK* node; + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_pop_free"); + + if (sk == NULL) + return; + + node = sk->next; + while (node && sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + if (f) + f(tmp->data.name); + else + wolfSSL_X509_NAME_free(tmp->data.name); + tmp->data.name = NULL; + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + if (f) + f(sk->data.name); + else + wolfSSL_X509_NAME_free(sk->data.name); + sk->data.name = NULL; + } + + XFREE(sk, sk->heap, DYNAMIC_TYPE_OPENSSL); +} + +/* Free only the sk structure, NOT X509_NAME members */ +void wolfSSL_sk_X509_NAME_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_free"); + + if (sk == NULL) + return; + + node = sk->next; + while (sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + sk->num -= 1; + } + + XFREE(sk, sk->heap, DYNAMIC_TYPE_OPENSSL); +} + +#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) +/* Helper function for X509_NAME_print_ex. Sets *buf to string for domain + name attribute based on NID. Returns size of buf */ +static int get_dn_attr_by_nid(int n, const char** buf) +{ + int len = 0; + const char *str; + + switch(n) + { + case NID_commonName : + str = "CN"; + len = 2; + break; + case NID_countryName: + str = "C"; + len = 1; + break; + case NID_localityName: + str = "L"; + len = 1; + break; + case NID_stateOrProvinceName: + str = "ST"; + len = 2; + break; + case NID_organizationName: + str = "O"; + len = 1; + break; + case NID_organizationalUnitName: + str = "OU"; + len = 2; + break; + case NID_emailAddress: + str = "emailAddress"; + len = 12; + break; + default: + WOLFSSL_MSG("Attribute type not found"); + str = NULL; + + } + if (buf != NULL) + *buf = str; + return len; +} +#endif + +/* + * The BIO output of wolfSSL_X509_NAME_print_ex does NOT include the null terminator + */ +int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name, + int indent, unsigned long flags) +{ +#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + int count = 0, len = 0, totalSz = 0, tmpSz = 0; + char tmp[ASN_NAME_MAX]; + char fullName[ASN_NAME_MAX]; + const char *buf = NULL; + WOLFSSL_X509_NAME_ENTRY* ne; + WOLFSSL_ASN1_STRING* str; +#endif + int i; + (void)flags; + WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex"); + + for (i = 0; i < indent; i++) { + if (wolfSSL_BIO_write(bio, " ", 1) != 1) + return WOLFSSL_FAILURE; + } + +#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + /* If XN_FLAG_DN_REV is present, print X509_NAME in reverse order */ + if (flags == (XN_FLAG_RFC2253 & ~XN_FLAG_DN_REV)) { + fullName[0] = '\0'; + count = wolfSSL_X509_NAME_entry_count(name); + for (i = 0; i < count; i++) { + ne = wolfSSL_X509_NAME_get_entry(name, count - i - 1); + if (ne == NULL) + return WOLFSSL_FAILURE; + + str = wolfSSL_X509_NAME_ENTRY_get_data(ne); + if (str == NULL) + return WOLFSSL_FAILURE; + + len = get_dn_attr_by_nid(ne->nid, &buf); + if (len == 0 || buf == NULL) + return WOLFSSL_FAILURE; + + tmpSz = str->length + len + 2; /* + 2 for '=' and comma */ + if (tmpSz > ASN_NAME_MAX) { + WOLFSSL_MSG("Size greater than ASN_NAME_MAX"); + return WOLFSSL_FAILURE; + } + + if (i < count - 1) { + /* tmpSz+1 for last null char */ + XSNPRINTF(tmp, tmpSz+1, "%s=%s,", buf, str->data); + XSTRNCAT(fullName, tmp, tmpSz); + } + else { + XSNPRINTF(tmp, tmpSz, "%s=%s", buf, str->data); + XSTRNCAT(fullName, tmp, tmpSz-1); + tmpSz--; /* Don't include null char in tmpSz */ + } + totalSz += tmpSz; + } + if (wolfSSL_BIO_write(bio, fullName, totalSz) != totalSz) + return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; + } +#else + if (flags == XN_FLAG_RFC2253) { + if (wolfSSL_BIO_write(bio, name->name + 1, name->sz - 2) + != name->sz - 2) + return WOLFSSL_FAILURE; + } +#endif /* WOLFSSL_APACHE_HTTPD || OPENSSL_ALL || WOLFSSL_NGINX */ + else if (wolfSSL_BIO_write(bio, name->name, name->sz - 1) != name->sz - 1) + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; +} + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x) +{ + (void)x; + WOLFSSL_ENTER("wolfSSL_X509_get0_pubkey_bitstr"); + WOLFSSL_STUB("X509_get0_pubkey_bitstr"); + + return NULL; +} +#endif + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +{ + (void)ctx; + (void)session; + WOLFSSL_ENTER("wolfSSL_CTX_add_session"); + WOLFSSL_STUB("SSL_CTX_add_session"); + + return WOLFSSL_SUCCESS; +} +#endif + + +int wolfSSL_version(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_version"); + if (ssl->version.major == SSLv3_MAJOR) { + switch (ssl->version.minor) { + case SSLv3_MINOR : + return SSL3_VERSION; + case TLSv1_MINOR : + return TLS1_VERSION; + case TLSv1_1_MINOR : + return TLS1_1_VERSION; + case TLSv1_2_MINOR : + return TLS1_2_VERSION; + case TLSv1_3_MINOR : + return TLS1_3_VERSION; + default: + return WOLFSSL_FAILURE; + } + } + else if (ssl->version.major == DTLS_MAJOR) { + switch (ssl->version.minor) { + case DTLS_MINOR : + return DTLS1_VERSION; + case DTLSv1_2_MINOR : + return DTLS1_2_VERSION; + default: + return WOLFSSL_FAILURE; + } + } + return WOLFSSL_FAILURE; +} + + +int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME* name) +{ + WOLFSSL_ENTER("wolfSSL_X509_NAME_get_sz"); + if(!name) + return -1; + return name->sz; +} + +#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, (word16)XSTRLEN(host_name)); + WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret); + return ret; +} + + +#ifndef NO_WOLFSSL_SERVER +const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type) +{ + void * serverName = NULL; + if (ssl == NULL) + return NULL; + TLSX_SNI_GetRequest(ssl->extensions, type, &serverName); + return (const char *)serverName; +} +#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, 0) == WOLFSSL_SUCCESS) + return ssl->ctx; + return NULL; +} + + +VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback"); + if(ctx) + return ctx->verifyCallback; + return NULL; +} + + +void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback"); + if (ctx) + 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 WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} + +int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg"); + if (ctx) { + ctx->sniRecvCbArg = arg; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} + +void wolfSSL_ERR_load_BIO_strings(void) { + WOLFSSL_ENTER("ERR_load_BIO_strings"); + /* do nothing */ +} + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_THREADID_set_callback(void(*threadid_func)(void*)) +{ + WOLFSSL_ENTER("wolfSSL_THREADID_set_callback"); + WOLFSSL_STUB("CRYPTO_THREADID_set_callback"); + (void)threadid_func; + return; +} +#endif + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_THREADID_set_numeric(void* id, unsigned long val) +{ + WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric"); + WOLFSSL_STUB("CRYPTO_THREADID_set_numeric"); + (void)id; + (void)val; + return; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +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"); + WOLFSSL_STUB("X509_STORE_get1_certs"); + (void)ctx; + (void)name; + return NULL; +} + +WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects( + WOLFSSL_X509_STORE* store) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_get0_objects"); + WOLFSSL_STUB("wolfSSL_X509_STORE_get0_objects"); + (void)store; + return NULL; +} + +WOLFSSL_X509_OBJECT* wolfSSL_sk_X509_OBJECT_delete( + WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_delete"); + WOLFSSL_STUB("wolfSSL_sk_X509_OBJECT_delete"); + (void)sk; + (void)i; + return NULL; +} + +void wolfSSL_X509_OBJECT_free(WOLFSSL_X509_OBJECT *a) +{ + WOLFSSL_ENTER("wolfSSL_X509_OBJECT_free"); + WOLFSSL_STUB("wolfSSL_X509_OBJECT_free"); + (void)a; +} + +#endif + + +#endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_LIGHTY)) */ + + +#if defined(OPENSSL_EXTRA) + +int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_num"); + + if (s == NULL) + return -1; + return (int)s->num; +} + +unsigned long wolfSSL_ERR_peek_last_error(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); + +#if defined(OPENSSL_EXTRA) || defined(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 == -ASN_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 +} + +#endif /* OPENSSL_EXTRA */ + +WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_SSL_CTX"); + return ssl->ctx; +} + +#if defined(OPENSSL_ALL) || \ + 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; +} + +#if (defined(HAVE_SESSION_TICKET) || defined(SESSION_CERTS)) && \ + !defined(NO_FILESYSTEM) + +#if defined(SESSION_CERTS) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) +/* returns a pointer to the protocol used by the session */ +static const char* wolfSSL_SESSION_get_protocol(const WOLFSSL_SESSION* in) +{ + return wolfSSL_internal_get_version((ProtocolVersion*)&in->version); +} +#endif + +/* returns true (non 0) if the session has EMS (extended master secret) */ +static int wolfSSL_SESSION_haveEMS(const WOLFSSL_SESSION* in) +{ + if (in == NULL) + return 0; + return in->haveEMS; +} + +#if defined(HAVE_SESSION_TICKET) +/* prints out the ticket to bio passed in + * return WOLFSSL_SUCCESS on success + */ +static int wolfSSL_SESSION_print_ticket(WOLFSSL_BIO* bio, + const WOLFSSL_SESSION* in, const char* tab) +{ + unsigned short i, j, z, sz; + short tag = 0; + byte* pt; + + + if (in == NULL || bio == NULL) { + return BAD_FUNC_ARG; + } + + sz = in->ticketLen; + pt = in->ticket; + + if (wolfSSL_BIO_printf(bio, "%s\n", (sz == 0)? " NONE": "") <= 0) + return WOLFSSL_FAILURE; + + for (i = 0; i < sz;) { + char asc[16]; + + if (sz - i < 16) { + if (wolfSSL_BIO_printf(bio, "%s%04X -", tab, tag + (sz - i)) <= 0) + return WOLFSSL_FAILURE; + } + else { + if (wolfSSL_BIO_printf(bio, "%s%04X -", tab, tag) <= 0) + return WOLFSSL_FAILURE; + } + for (j = 0; i < sz && j < 8; j++,i++) { + asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.'; + if (wolfSSL_BIO_printf(bio, " %02X", pt[i]) <= 0) + return WOLFSSL_FAILURE; + } + + if (i < sz) { + asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.'; + if (wolfSSL_BIO_printf(bio, "-%02X", pt[i]) <= 0) + return WOLFSSL_FAILURE; + j++; + i++; + } + + for (; i < sz && j < 16; j++,i++) { + asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.'; + if (wolfSSL_BIO_printf(bio, " %02X", pt[i]) <= 0) + return WOLFSSL_FAILURE; + } + + /* pad out spacing */ + for (z = j; z < 17; z++) { + if (wolfSSL_BIO_printf(bio, " ") <= 0) + return WOLFSSL_FAILURE; + } + + for (z = 0; z < j; z++) { + if (wolfSSL_BIO_printf(bio, "%c", asc[z]) <= 0) + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_printf(bio, "\n") <= 0) + return WOLFSSL_FAILURE; + + tag += 16; + } + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_SESSION_TICKET */ + + +/* prints out the session information in human readable form + * return WOLFSSL_SUCCESS on success + */ +int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *x) +{ + const unsigned char* pt; + unsigned char buf[SECRET_LEN]; + unsigned int sz = 0, i; + int ret; + WOLFSSL_SESSION* session = (WOLFSSL_SESSION*)x; + + if (session == NULL) { + WOLFSSL_MSG("Bad NULL argument"); + return WOLFSSL_FAILURE; + } + + if (wolfSSL_BIO_printf(bp, "%s\n", "SSL-Session:") <= 0) + return WOLFSSL_FAILURE; + +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + if (wolfSSL_BIO_printf(bp, " Protocol : %s\n", + wolfSSL_SESSION_get_protocol(session)) <= 0) + return WOLFSSL_FAILURE; +#endif + + if (wolfSSL_BIO_printf(bp, " Cipher : %s\n", + wolfSSL_SESSION_CIPHER_get_name(session)) <= 0) + return WOLFSSL_FAILURE; + + pt = wolfSSL_SESSION_get_id(session, &sz); + if (wolfSSL_BIO_printf(bp, " Session-ID: ") <= 0) + return WOLFSSL_FAILURE; + + for (i = 0; i < sz; i++) { + if (wolfSSL_BIO_printf(bp, "%02X", pt[i]) <= 0) + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_printf(bp, "\n") <= 0) + return WOLFSSL_FAILURE; + + if (wolfSSL_BIO_printf(bp, " Session-ID-ctx: \n") <= 0) + return WOLFSSL_FAILURE; + + ret = wolfSSL_SESSION_get_master_key(x, buf, sizeof(buf)); + if (wolfSSL_BIO_printf(bp, " Master-Key: ") <= 0) + return WOLFSSL_FAILURE; + + if (ret > 0) { + sz = (unsigned int)ret; + for (i = 0; i < sz; i++) { + if (wolfSSL_BIO_printf(bp, "%02X", buf[i]) <= 0) + return WOLFSSL_FAILURE; + } + } + if (wolfSSL_BIO_printf(bp, "\n") <= 0) + return WOLFSSL_FAILURE; + + /* @TODO PSK identity hint and SRP */ + + if (wolfSSL_BIO_printf(bp, " TLS session ticket:") <= 0) + return WOLFSSL_FAILURE; + +#ifdef HAVE_SESSION_TICKET + if (wolfSSL_SESSION_print_ticket(bp, x, " ") != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; +#endif + + if (wolfSSL_BIO_printf(bp, " Start Time: %ld\n", + wolfSSL_SESSION_get_time(x)) <= 0) + return WOLFSSL_FAILURE; + + if (wolfSSL_BIO_printf(bp, " Timeout : %ld (sec)\n", + wolfSSL_SESSION_get_timeout(x)) <= 0) + return WOLFSSL_FAILURE; + + /* @TODO verify return code print */ + + if (wolfSSL_BIO_printf(bp, " Extended master secret: %s\n", + (wolfSSL_SESSION_haveEMS(session) == 0)? "no" : "yes") <= 0) + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; +} +#endif /* (HAVE_SESSION_TICKET || SESSION_CERTS) && !NO_FILESYSTEM */ + +#endif /* OPENSSL_ALL || OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \ + || 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 WOLFSSL_FATAL_ERROR; + + if (ctx->verifyPeer) + mode |= WOLFSSL_VERIFY_PEER; + else if (ctx->verifyNone) + mode |= WOLFSSL_VERIFY_NONE; + + if (ctx->failNoCert) + mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT; + + if (ctx->failNoCertxPSK) + mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK; + + WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode); + return mode; +} + +#endif +#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE25519) +/* return 1 if success, 0 if error + * output keys are little endian format + */ +int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) priv; + (void) privSz; + (void) pub; + (void) pubSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = WOLFSSL_FAILURE; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_EC25519_generate_key"); + + if (priv == NULL || privSz == NULL || *privSz < CURVE25519_KEYSIZE || + pub == NULL || pubSz == NULL || *pubSz < CURVE25519_KEYSIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FAILURE; +#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; + } + + if (rng) { + curve25519_key key; + + if (wc_curve25519_init(&key) != MP_OKAY) + WOLFSSL_MSG("wc_curve25519_init failed"); + else if (wc_curve25519_make_key(rng, CURVE25519_KEYSIZE, &key)!=MP_OKAY) + WOLFSSL_MSG("wc_curve25519_make_key failed"); + /* export key pair */ + else if (wc_curve25519_export_key_raw_ex(&key, priv, privSz, pub, + pubSz, EC25519_LITTLE_ENDIAN) + != MP_OKAY) + WOLFSSL_MSG("wc_curve25519_export_key_raw_ex failed"); + else + ret = WOLFSSL_SUCCESS; + + wc_curve25519_free(&key); + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* return 1 if success, 0 if error + * input and output keys are little endian format + */ +int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz, + const unsigned char *priv, unsigned int privSz, + const unsigned char *pub, unsigned int pubSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) shared; + (void) sharedSz; + (void) priv; + (void) privSz; + (void) pub; + (void) pubSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = WOLFSSL_FAILURE; + curve25519_key privkey, pubkey; + + WOLFSSL_ENTER("wolfSSL_EC25519_shared_key"); + + if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE25519_KEYSIZE || + priv == NULL || privSz < CURVE25519_KEYSIZE || + pub == NULL || pubSz < CURVE25519_KEYSIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + + /* import private key */ + if (wc_curve25519_init(&privkey) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init privkey failed"); + return ret; + } + if (wc_curve25519_import_private_ex(priv, privSz, &privkey, + EC25519_LITTLE_ENDIAN) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_import_private_ex failed"); + wc_curve25519_free(&privkey); + return ret; + } + + /* import public key */ + if (wc_curve25519_init(&pubkey) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init pubkey failed"); + wc_curve25519_free(&privkey); + return ret; + } + if (wc_curve25519_import_public_ex(pub, pubSz, &pubkey, + EC25519_LITTLE_ENDIAN) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_import_public_ex failed"); + wc_curve25519_free(&privkey); + wc_curve25519_free(&pubkey); + return ret; + } + + if (wc_curve25519_shared_secret_ex(&privkey, &pubkey, + shared, sharedSz, + EC25519_LITTLE_ENDIAN) != MP_OKAY) + WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed"); + else + ret = WOLFSSL_SUCCESS; + + wc_curve25519_free(&privkey); + wc_curve25519_free(&pubkey); + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} +#endif /* OPENSSL_EXTRA && HAVE_CURVE25519 */ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519) +/* return 1 if success, 0 if error + * output keys are little endian format + */ +int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) priv; + (void) privSz; + (void) pub; + (void) pubSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = WOLFSSL_FAILURE; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_ED25519_generate_key"); + + if (priv == NULL || privSz == NULL || *privSz < ED25519_PRV_KEY_SIZE || + pub == NULL || pubSz == NULL || *pubSz < ED25519_PUB_KEY_SIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + +#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; + } + + if (rng) { + ed25519_key key; + + if (wc_ed25519_init(&key) != MP_OKAY) + WOLFSSL_MSG("wc_ed25519_init failed"); + else if (wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &key)!=MP_OKAY) + WOLFSSL_MSG("wc_ed25519_make_key failed"); + /* export private key */ + else if (wc_ed25519_export_key(&key, priv, privSz, pub, pubSz)!=MP_OKAY) + WOLFSSL_MSG("wc_ed25519_export_key failed"); + else + ret = WOLFSSL_SUCCESS; + + wc_ed25519_free(&key); + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* return 1 if success, 0 if error + * input and output keys are little endian format + * priv is a buffer containing private and public part of key + */ +int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz, + const unsigned char *priv, unsigned int privSz, + unsigned char *sig, unsigned int *sigSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) msg; + (void) msgSz; + (void) priv; + (void) privSz; + (void) sig; + (void) sigSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + ed25519_key key; + 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 WOLFSSL_FAILURE; + } + + /* import key */ + if (wc_ed25519_init(&key) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init failed"); + return ret; + } + if (wc_ed25519_import_private_key(priv, privSz/2, + priv+(privSz/2), ED25519_PUB_KEY_SIZE, + &key) != MP_OKAY){ + WOLFSSL_MSG("wc_ed25519_import_private failed"); + wc_ed25519_free(&key); + return ret; + } + + if (wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY) + WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed"); + else + ret = WOLFSSL_SUCCESS; + + wc_ed25519_free(&key); + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* return 1 if success, 0 if error + * input and output keys are little endian format + * pub is a buffer containing public part of key + */ +int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz, + const unsigned char *pub, unsigned int pubSz, + const unsigned char *sig, unsigned int sigSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) msg; + (void) msgSz; + (void) pub; + (void) pubSz; + (void) sig; + (void) sigSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + ed25519_key key; + 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 WOLFSSL_FAILURE; + } + + /* import key */ + if (wc_ed25519_init(&key) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init failed"); + return ret; + } + if (wc_ed25519_import_public(pub, pubSz, &key) != MP_OKAY){ + WOLFSSL_MSG("wc_ed25519_import_public failed"); + wc_ed25519_free(&key); + return ret; + } + + if ((ret = wc_ed25519_verify_msg((byte*)sig, sigSz, msg, msgSz, + &check, &key)) != MP_OKAY) { + WOLFSSL_MSG("wc_ed25519_verify_msg failed"); + } + else if (!check) + WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)"); + else + ret = WOLFSSL_SUCCESS; + + wc_ed25519_free(&key); + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +#endif /* OPENSSL_EXTRA && HAVE_ED25519 */ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE448) +/* return 1 if success, 0 if error + * output keys are little endian format + */ +int wolfSSL_EC448_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) priv; + (void) privSz; + (void) pub; + (void) pubSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = WOLFSSL_FAILURE; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_EC448_generate_key"); + + if (priv == NULL || privSz == NULL || *privSz < CURVE448_KEY_SIZE || + pub == NULL || pubSz == NULL || *pubSz < CURVE448_KEY_SIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FAILURE; +#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; + } + + if (rng) { + curve448_key key; + + if (wc_curve448_init(&key) != MP_OKAY) + WOLFSSL_MSG("wc_curve448_init failed"); + else if (wc_curve448_make_key(rng, CURVE448_KEY_SIZE, &key)!=MP_OKAY) + WOLFSSL_MSG("wc_curve448_make_key failed"); + /* export key pair */ + else if (wc_curve448_export_key_raw_ex(&key, priv, privSz, pub, pubSz, + EC448_LITTLE_ENDIAN) + != MP_OKAY) + WOLFSSL_MSG("wc_curve448_export_key_raw_ex failed"); + else + ret = WOLFSSL_SUCCESS; + + wc_curve448_free(&key); + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* return 1 if success, 0 if error + * input and output keys are little endian format + */ +int wolfSSL_EC448_shared_key(unsigned char *shared, unsigned int *sharedSz, + const unsigned char *priv, unsigned int privSz, + const unsigned char *pub, unsigned int pubSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) shared; + (void) sharedSz; + (void) priv; + (void) privSz; + (void) pub; + (void) pubSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = WOLFSSL_FAILURE; + curve448_key privkey, pubkey; + + WOLFSSL_ENTER("wolfSSL_EC448_shared_key"); + + if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE448_KEY_SIZE || + priv == NULL || privSz < CURVE448_KEY_SIZE || + pub == NULL || pubSz < CURVE448_KEY_SIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + + /* import private key */ + if (wc_curve448_init(&privkey) != MP_OKAY) { + WOLFSSL_MSG("wc_curve448_init privkey failed"); + return ret; + } + if (wc_curve448_import_private_ex(priv, privSz, &privkey, + EC448_LITTLE_ENDIAN) != MP_OKAY) { + WOLFSSL_MSG("wc_curve448_import_private_ex failed"); + wc_curve448_free(&privkey); + return ret; + } + + /* import public key */ + if (wc_curve448_init(&pubkey) != MP_OKAY) { + WOLFSSL_MSG("wc_curve448_init pubkey failed"); + wc_curve448_free(&privkey); + return ret; + } + if (wc_curve448_import_public_ex(pub, pubSz, &pubkey, + EC448_LITTLE_ENDIAN) != MP_OKAY) { + WOLFSSL_MSG("wc_curve448_import_public_ex failed"); + wc_curve448_free(&privkey); + wc_curve448_free(&pubkey); + return ret; + } + + if (wc_curve448_shared_secret_ex(&privkey, &pubkey, shared, sharedSz, + EC448_LITTLE_ENDIAN) != MP_OKAY) + WOLFSSL_MSG("wc_curve448_shared_secret_ex failed"); + else + ret = WOLFSSL_SUCCESS; + + wc_curve448_free(&privkey); + wc_curve448_free(&pubkey); + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} +#endif /* OPENSSL_EXTRA && HAVE_CURVE448 */ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ED448) +/* return 1 if success, 0 if error + * output keys are little endian format + */ +int wolfSSL_ED448_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) priv; + (void) privSz; + (void) pub; + (void) pubSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = WOLFSSL_FAILURE; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_ED448_generate_key"); + + if (priv == NULL || privSz == NULL || *privSz < ED448_PRV_KEY_SIZE || + pub == NULL || pubSz == NULL || *pubSz < ED448_PUB_KEY_SIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + +#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; + } + + if (rng) { + ed448_key key; + + if (wc_ed448_init(&key) != MP_OKAY) + WOLFSSL_MSG("wc_ed448_init failed"); + else if (wc_ed448_make_key(rng, ED448_KEY_SIZE, &key) != MP_OKAY) + WOLFSSL_MSG("wc_ed448_make_key failed"); + /* export private key */ + else if (wc_ed448_export_key(&key, priv, privSz, pub, pubSz) != MP_OKAY) + WOLFSSL_MSG("wc_ed448_export_key failed"); + else + ret = WOLFSSL_SUCCESS; + + wc_ed448_free(&key); + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* return 1 if success, 0 if error + * input and output keys are little endian format + * priv is a buffer containing private and public part of key + */ +int wolfSSL_ED448_sign(const unsigned char *msg, unsigned int msgSz, + const unsigned char *priv, unsigned int privSz, + unsigned char *sig, unsigned int *sigSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) msg; + (void) msgSz; + (void) priv; + (void) privSz; + (void) sig; + (void) sigSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + ed448_key key; + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_ED448_sign"); + + if (priv == NULL || privSz != ED448_PRV_KEY_SIZE || msg == NULL || + sig == NULL || *sigSz < ED448_SIG_SIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + + /* import key */ + if (wc_ed448_init(&key) != MP_OKAY) { + WOLFSSL_MSG("wc_curve448_init failed"); + return ret; + } + if (wc_ed448_import_private_key(priv, privSz/2, priv+(privSz/2), + ED448_PUB_KEY_SIZE, &key) != MP_OKAY){ + WOLFSSL_MSG("wc_ed448_import_private failed"); + wc_ed448_free(&key); + return ret; + } + + if (wc_ed448_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY) + WOLFSSL_MSG("wc_curve448_shared_secret_ex failed"); + else + ret = WOLFSSL_SUCCESS; + + wc_ed448_free(&key); + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* return 1 if success, 0 if error + * input and output keys are little endian format + * pub is a buffer containing public part of key + */ +int wolfSSL_ED448_verify(const unsigned char *msg, unsigned int msgSz, + const unsigned char *pub, unsigned int pubSz, + const unsigned char *sig, unsigned int sigSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) msg; + (void) msgSz; + (void) pub; + (void) pubSz; + (void) sig; + (void) sigSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + ed448_key key; + int ret = WOLFSSL_FAILURE, check = 0; + + WOLFSSL_ENTER("wolfSSL_ED448_verify"); + + if (pub == NULL || pubSz != ED448_PUB_KEY_SIZE || msg == NULL || + sig == NULL || sigSz != ED448_SIG_SIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + + /* import key */ + if (wc_ed448_init(&key) != MP_OKAY) { + WOLFSSL_MSG("wc_curve448_init failed"); + return ret; + } + if (wc_ed448_import_public(pub, pubSz, &key) != MP_OKAY){ + WOLFSSL_MSG("wc_ed448_import_public failed"); + wc_ed448_free(&key); + return ret; + } + + if ((ret = wc_ed448_verify_msg((byte*)sig, sigSz, msg, msgSz, &check, + &key)) != MP_OKAY) { + WOLFSSL_MSG("wc_ed448_verify_msg failed"); + } + else if (!check) + WOLFSSL_MSG("wc_ed448_verify_msg failed (signature invalid)"); + else + ret = WOLFSSL_SUCCESS; + + wc_ed448_free(&key); + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +#endif /* OPENSSL_EXTRA && HAVE_ED448 */ + +#ifdef WOLFSSL_JNI + +int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr) +{ + WOLFSSL_ENTER("wolfSSL_set_jobject"); + if (ssl != NULL) + { + ssl->jObjectRef = objPtr; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} + +void* wolfSSL_get_jobject(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_jobject"); + if (ssl != NULL) + return ssl->jObjectRef; + return NULL; +} + +#endif /* WOLFSSL_JNI */ + + +#ifdef WOLFSSL_ASYNC_CRYPT +int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents, + WOLF_EVENT_FLAG flags, int* eventCount) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL, + events, maxEvents, flags, eventCount); +} + +int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags) +{ + int ret, eventCount = 0; + WOLF_EVENT* events[1]; + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl, + events, sizeof(events)/sizeof(*events), flags, &eventCount); + 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(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_OPENSSH) || 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; + } + /* OpenSSL uses positive error codes */ + if (ret < 0) { + ret = -ret; + } + + if (ret == -ASN_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(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +/* returns a pointer to internal cipher suite list. Should not be free'd by + * caller. + */ +WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl) +{ + WOLF_STACK_OF(WOLFSSL_CIPHER)* ret = NULL; + Suites* suites; + + WOLFSSL_ENTER("wolfSSL_get_ciphers_compat"); + if (ssl == NULL || (ssl->suites == NULL && ssl->ctx->suites == NULL)) { + return NULL; + } + + if (ssl->suites != NULL) { + suites = ssl->suites; + } + else { + suites = ssl->ctx->suites; + } + + /* check if stack needs populated */ + if (suites->stack == NULL) { + int i; + for (i = 0; i < suites->suiteSz; i+=2) { + WOLFSSL_STACK* add = wolfSSL_sk_new_node(ssl->heap); + if (add != NULL) { + add->type = STACK_TYPE_CIPHER; + add->data.cipher.cipherSuite0 = suites->suites[i]; + add->data.cipher.cipherSuite = suites->suites[i+1]; + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + /* in_stack is checked in wolfSSL_CIPHER_description */ + add->data.cipher.in_stack = 1; + #endif + + add->next = ret; + if (ret != NULL) { + add->num = ret->num + 1; + } + else { + add->num = 1; + } + ret = add; + } + } + suites->stack = ret; + } + return suites->stack; +} + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_OPENSSL_config(char *config_name) +{ + (void)config_name; + WOLFSSL_STUB("OPENSSL_config"); +} +#endif /* !NO_WOLFSSL_STUB */ +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) +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++; +} + +#if defined(HAVE_EX_DATA) || defined(FORTRESS) +void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); +#ifdef MAX_EX_DATA + if(ex_data && idx < MAX_EX_DATA && idx >= 0) { + return ex_data->ex_data[idx]; + } +#else + (void)ex_data; + (void)idx; +#endif + return NULL; +} + +int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, void *data) +{ + WOLFSSL_ENTER("wolfSSL_CRYPTO_set_ex_data"); +#ifdef MAX_EX_DATA + if (ex_data && idx < MAX_EX_DATA && idx >= 0) { + ex_data->ex_data[idx] = data; + return WOLFSSL_SUCCESS; + } +#else + (void)ex_data; + (void)idx; + (void)data; +#endif + return WOLFSSL_FAILURE; +} +#endif /* defined(HAVE_EX_DATA) || defined(FORTRESS) */ + +void *wolfSSL_X509_get_ex_data(X509 *x509, int idx) +{ + WOLFSSL_ENTER("wolfSSL_X509_get_ex_data"); + #ifdef HAVE_EX_DATA + if (x509 != NULL) { + return wolfSSL_CRYPTO_get_ex_data(&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) + { + return wolfSSL_CRYPTO_set_ex_data(&x509->ex_data, idx, data); + } + #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; + +#if !defined(NO_FILESYSTEM) && !defined(NO_PWDBASED) + 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; +} + + +/* returns the time in seconds of the current timeout */ +long wolfSSL_get_timeout(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_timeout"); + + if (ssl == NULL) + return 0; + return ssl->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"); + /* 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. + */ + if (s == NULL) + return NULL; + + return s->biord; +} +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. + */ + if (s == NULL) + return NULL; + + return s->biowr; +} + +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) { + #ifndef NO_WOLFSSL_CLIENT + return wolfSSL_connect(s); + #else + WOLFSSL_MSG("Client not compiled in"); + return WOLFSSL_FAILURE; + #endif + } + +#ifndef NO_WOLFSSL_SERVER + return wolfSSL_accept(s); +#else + WOLFSSL_MSG("Server not compiled in"); + return WOLFSSL_FAILURE; +#endif +} + +int wolfSSL_SSL_in_init(WOLFSSL *ssl) +{ + WOLFSSL_ENTER("SSL_in_init"); + + if (ssl == NULL) + return WOLFSSL_FAILURE; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + return ssl->options.connectState < SECOND_REPLY_DONE; + } + return ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE; +} + +int wolfSSL_SSL_in_connect_init(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_connect_init"); + + if (ssl == NULL) + return WOLFSSL_FAILURE; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + return ssl->options.connectState > CONNECT_BEGIN && + ssl->options.connectState < SECOND_REPLY_DONE; + } + + return ssl->options.acceptState > ACCEPT_BEGIN && + ssl->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; + + if (flags == WOLFSSL_NO_WILDCARDS) { + WOLFSSL_MSG("X509_CHECK_FLAG_NO_WILDCARDS not yet implemented"); + return WOLFSSL_FAILURE; + } + + InitDecodedCert(&dCert, x->derCert->buffer, x->derCert->length, NULL); + ret = ParseCertRelative(&dCert, CERT_TYPE, 0, NULL); + if (ret != 0) { + FreeDecodedCert(&dCert); + 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 indefinite 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; +} + + +#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) +/* 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[WC_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'. */ + if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen)) + goto end; +#ifdef WOLFSSL_SHA512 + /* Check for SHA512, which would overrun the mac buffer */ + if (hmacCtx.hmac.macType == WC_SHA512) + goto end; +#endif + if (!wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz)) + goto end; + } + else + { + /* HMAC the encrypted data and compare it to the passed in data. */ + if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen)) + goto end; + if (!wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz)) + goto end; + 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 */ + +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || + OPENSSL_EXTRA || HAVE_LIGHTY */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +#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; +} +#endif /* OCSP */ +#endif /* OPENSSL_ALL / WOLFSSL_NGINX / WOLFSSL_HAPROXY */ + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) +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; + +#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) + /* 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; +#else + (void)cb; +#endif + + 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; + +#ifdef WOLFSSL_SIGNER_DER_CERT + /* populate issuer with Signer DER */ + *issuer = wolfSSL_X509_d2i(issuer, ca->derCert->buffer, + ca->derCert->length); + if (*issuer == NULL) + return WOLFSSL_FAILURE; +#else + /* Create an empty certificate as CA doesn't have a certificate. */ + *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0, + DYNAMIC_TYPE_OPENSSL); + if (*issuer == NULL) + return WOLFSSL_FAILURE; + + InitX509((*issuer), 1, NULL); +#endif + + /* 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; + char* url; + + if (x->authInfoSz == 0) + return NULL; + + list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK) + x->authInfoSz + 1, + NULL, DYNAMIC_TYPE_OPENSSL); + if (list == NULL) + return NULL; + + url = (char*)list; + url += sizeof(WOLFSSL_STACK); + XMEMCPY(url, x->authInfo, x->authInfoSz); + url[x->authInfoSz] = '\0'; + + list->data.string = url; + 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 /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +#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) +int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names) +{ + int idx, start = 0, len; + word16 curve; + char name[MAX_CURVE_NAME_SZ]; + + /* Disable all curves so that only the ones the user wants are enabled. */ + ctx->disabledCurves = 0xFFFFFFFFUL; + 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 (XSTRNCMP(name, "X448", len) == 0) { + curve = WOLFSSL_ECC_X448; + } + else { + #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + int ret; + const ecc_set_type *eccSet; + + ret = wc_ecc_get_curve_idx_from_name(name); + if (ret < 0) { + WOLFSSL_MSG("Could not find name in set"); + return WOLFSSL_FAILURE; + } + + eccSet = wc_ecc_get_curve_params(ret); + if (eccSet == NULL) { + WOLFSSL_MSG("NULL set returned"); + return WOLFSSL_FAILURE; + } + + curve = GetCurveByOID(eccSet->oidSum); + #else + WOLFSSL_MSG("API not present to search farther using name"); + return WOLFSSL_FAILURE; + #endif + } + + if (curve > (sizeof(word32) * WOLFSSL_BIT_SIZE)) { + /* shift left more than size of ctx->disabledCurves causes static + * analysis report */ + WOLFSSL_MSG("curve value is too large for upcoming shift"); + return WOLFSSL_FAILURE; + } + + #if defined(HAVE_SUPPORTED_CURVES) && !defined(NO_WOLFSSL_CLIENT) + /* set the supported curve so client TLS extension contains only the + * desired curves */ + if (wolfSSL_CTX_UseSupportedCurve(ctx, curve) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Unable to set supported curve"); + return WOLFSSL_FAILURE; + } + #endif + + /* Switch the bit to off and therefore is enabled. */ + ctx->disabledCurves &= ~(1U << curve); + start = idx + 1; + } + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_set1_curves_list(WOLFSSL* ssl, const char* names) +{ + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + return wolfSSL_CTX_set1_curves_list(ssl->ctx, names); +} +#endif /* OPENSSL_EXTRA && HAVE_ECC */ + +#ifdef OPENSSL_EXTRA +#ifndef NO_WOLFSSL_STUB +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 WOLFSSL_FAILURE; +} +#endif + + +/* Sets a callback for when sending and receiving protocol messages. + * + * ssl WOLFSSL structure to set callback in + * cb callback to use + * + * return SSL_SUCCESS on success and SSL_FAILURE with error case + */ +int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb) +{ + WOLFSSL_ENTER("wolfSSL_set_msg_callback"); + + if (ssl == NULL) { + return SSL_FAILURE; + } + + if (cb != NULL) { + ssl->toInfoOn = 1; + } + + ssl->protoMsgCb = cb; + return SSL_SUCCESS; +} +#ifndef NO_WOLFSSL_STUB +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 WOLFSSL_FAILURE; +} +#endif + +int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg) +{ + WOLFSSL_ENTER("wolfSSL_set_msg_callback_arg"); + if (ssl == NULL) + return WOLFSSL_FAILURE; + + ssl->protoMsgCtx = arg; + return WOLFSSL_SUCCESS; +} + +void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file, int line) +{ + void *ret; + (void)file; + (void)line; + + if (data == NULL || siz >= INT_MAX) + return NULL; + + ret = OPENSSL_malloc(siz); + if (ret == NULL) { + return NULL; + } + return XMEMCPY(ret, data, siz); +} + +int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, const unsigned char *p, + unsigned int p_len) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_alpn_protos"); + if(ctx == NULL) + return BAD_FUNC_ARG; + if((void *)ctx->alpn_cli_protos != NULL) + wolfSSL_OPENSSL_free((void *)ctx->alpn_cli_protos); + ctx->alpn_cli_protos = + (const unsigned char *)wolfSSL_OPENSSL_memdup(p, p_len, NULL, 0); + if (ctx->alpn_cli_protos == NULL) { + return SSL_FAILURE; + } + ctx->alpn_cli_protos_len = p_len; + + return SSL_SUCCESS; +} + + +#ifdef HAVE_ALPN +/* Sets the ALPN extension protos + * + * example format is + * unsigned char p[] = { + * 8, 'h', 't', 't', 'p', '/', '1', '.', '1' + * }; + * + * returns WOLFSSL_SUCCESS on success */ +int wolfSSL_set_alpn_protos(WOLFSSL* ssl, + const unsigned char* p, unsigned int p_len) +{ + WOLFSSL_BIO* bio; + char* pt; + + unsigned int sz; + unsigned int idx = 0; + int alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH; + WOLFSSL_ENTER("wolfSSL_set_alpn_protos"); + + if (ssl == NULL || p_len <= 1) { + return WOLFSSL_FAILURE; + } + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); + if (bio == NULL) { + return WOLFSSL_FAILURE; + } + + /* convert into comma separated list */ + while (idx < p_len - 1) { + unsigned int i; + + sz = p[idx++]; + if (idx + sz > p_len) { + WOLFSSL_MSG("Bad list format"); + wolfSSL_BIO_free(bio); + return WOLFSSL_FAILURE; + } + if (sz > 0) { + for (i = 0; i < sz; i++) { + wolfSSL_BIO_write(bio, &p[idx++], 1); + } + if (idx < p_len - 1) + wolfSSL_BIO_write(bio, ",", 1); + } + } + wolfSSL_BIO_write(bio, "\0", 1); + + /* clears out all current ALPN extensions set */ + TLSX_Remove(&ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL, ssl->heap); + + if ((sz = wolfSSL_BIO_get_mem_data(bio, &pt)) > 0) { + wolfSSL_UseALPN(ssl, pt, sz, alpn_opt); + } + wolfSSL_BIO_free(bio); + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_ALPN */ +#endif + +#endif /* WOLFCRYPT_ONLY */ + +#if defined(OPENSSL_EXTRA) + +#define WOLFSSL_BIO_INCLUDED +#include "src/bio.c" + +int oid2nid(word32 oid, int grp) +{ + /* get OID type */ + switch (grp) { + /* oidHashType */ + case oidHashType: + switch (oid) { + #ifdef WOLFSSL_MD2 + case MD2h: + return NID_md2; + #endif + #ifndef NO_MD5 + case MD5h: + return NID_md5; + #endif + #ifndef NO_SHA + case SHAh: + return NID_sha1; + #endif + case SHA224h: + return NID_sha224; + #ifndef NO_SHA256 + case SHA256h: + return NID_sha256; + #endif + #ifdef WOLFSSL_SHA384 + case SHA384h: + return NID_sha384; + #endif + #ifdef WOLFSSL_SHA512 + case SHA512h: + return NID_sha512; + #endif + } + break; + + /* oidSigType */ + case oidSigType: + switch (oid) { + #ifndef NO_DSA + case CTC_SHAwDSA: + return CTC_SHAwDSA; + #endif /* NO_DSA */ + #ifndef NO_RSA + case CTC_MD2wRSA: + return CTC_MD2wRSA; + case CTC_MD5wRSA: + return CTC_MD5wRSA; + case CTC_SHAwRSA: + return CTC_SHAwRSA; + case CTC_SHA224wRSA: + return CTC_SHA224wRSA; + case CTC_SHA256wRSA: + return CTC_SHA256wRSA; + case CTC_SHA384wRSA: + return CTC_SHA384wRSA; + case CTC_SHA512wRSA: + return CTC_SHA512wRSA; + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case CTC_SHAwECDSA: + return CTC_SHAwECDSA; + case CTC_SHA224wECDSA: + return CTC_SHA224wECDSA; + case CTC_SHA256wECDSA: + return CTC_SHA256wECDSA; + case CTC_SHA384wECDSA: + return CTC_SHA384wECDSA; + case CTC_SHA512wECDSA: + return CTC_SHA512wECDSA; + #endif /* HAVE_ECC */ + } + break; + + /* oidKeyType */ + case oidKeyType: + switch (oid) { + #ifndef NO_DSA + case DSAk: + return DSAk; + #endif /* NO_DSA */ + #ifndef NO_RSA + case RSAk: + return RSAk; + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + case NTRUk: + return NTRUk; + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ECDSAk: + return ECDSAk; + #endif /* HAVE_ECC */ + } + break; + + + #ifdef HAVE_ECC + case oidCurveType: + switch (oid) { + case ECC_SECP192R1_OID: + return NID_X9_62_prime192v1; + case ECC_PRIME192V2_OID: + return NID_X9_62_prime192v2; + case ECC_PRIME192V3_OID: + return NID_X9_62_prime192v3; + case ECC_PRIME239V1_OID: + return NID_X9_62_prime239v1; + case ECC_PRIME239V2_OID: + return NID_X9_62_prime239v2; + case ECC_PRIME239V3_OID: + return NID_X9_62_prime239v3; + case ECC_SECP256R1_OID: + return NID_X9_62_prime256v1; + case ECC_SECP112R1_OID: + return NID_secp112r1; + case ECC_SECP112R2_OID: + return NID_secp112r2; + case ECC_SECP128R1_OID: + return NID_secp128r1; + case ECC_SECP128R2_OID: + return NID_secp128r2; + case ECC_SECP160R1_OID: + return NID_secp160r1; + case ECC_SECP160R2_OID: + return NID_secp160r2; + case ECC_SECP224R1_OID: + return NID_secp224r1; + case ECC_SECP384R1_OID: + return NID_secp384r1; + case ECC_SECP521R1_OID: + return NID_secp521r1; + case ECC_SECP160K1_OID: + return NID_secp160k1; + case ECC_SECP192K1_OID: + return NID_secp192k1; + case ECC_SECP224K1_OID: + return NID_secp224k1; + case ECC_SECP256K1_OID: + return NID_secp256k1; + case ECC_BRAINPOOLP160R1_OID: + return NID_brainpoolP160r1; + case ECC_BRAINPOOLP192R1_OID: + return NID_brainpoolP192r1; + case ECC_BRAINPOOLP224R1_OID: + return NID_brainpoolP224r1; + case ECC_BRAINPOOLP256R1_OID: + return NID_brainpoolP256r1; + case ECC_BRAINPOOLP320R1_OID: + return NID_brainpoolP320r1; + case ECC_BRAINPOOLP384R1_OID: + return NID_brainpoolP384r1; + case ECC_BRAINPOOLP512R1_OID: + return NID_brainpoolP512r1; + } + break; + #endif /* HAVE_ECC */ + + /* oidBlkType */ + case oidBlkType: + switch (oid) { + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + return AES128CBCb; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + return AES192CBCb; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + return AES256CBCb; + #endif + #ifndef NO_DES3 + case DESb: + return NID_des; + case DES3b: + return NID_des3; + #endif + } + break; + + #ifdef HAVE_OCSP + case oidOcspType: + switch (oid) { + case OCSP_BASIC_OID: + return NID_id_pkix_OCSP_basic; + case OCSP_NONCE_OID: + return OCSP_NONCE_OID; + } + break; + #endif /* HAVE_OCSP */ + + /* oidCertExtType */ + case oidCertExtType: + switch (oid) { + case BASIC_CA_OID: + return BASIC_CA_OID; + case ALT_NAMES_OID: + return ALT_NAMES_OID; + case CRL_DIST_OID: + return CRL_DIST_OID; + case AUTH_INFO_OID: + return AUTH_INFO_OID; + case AUTH_KEY_OID: + return AUTH_KEY_OID; + case SUBJ_KEY_OID: + return SUBJ_KEY_OID; + case INHIBIT_ANY_OID: + return INHIBIT_ANY_OID; + case KEY_USAGE_OID: + return NID_key_usage; + case NAME_CONS_OID: + return NID_name_constraints; + case CERT_POLICY_OID: + return NID_certificate_policies; + } + break; + + /* oidCertAuthInfoType */ + case oidCertAuthInfoType: + switch (oid) { + case AIA_OCSP_OID: + return AIA_OCSP_OID; + case AIA_CA_ISSUER_OID: + return AIA_CA_ISSUER_OID; + } + break; + + /* oidCertPolicyType */ + case oidCertPolicyType: + switch (oid) { + case CP_ANY_OID: + return NID_any_policy; + } + break; + + /* oidCertAltNameType */ + case oidCertAltNameType: + switch (oid) { + case HW_NAME_OID: + return NID_hw_name_oid; + } + break; + + /* oidCertKeyUseType */ + case oidCertKeyUseType: + switch (oid) { + case EKU_ANY_OID: + return NID_anyExtendedKeyUsage; + case EKU_SERVER_AUTH_OID: + return EKU_SERVER_AUTH_OID; + case EKU_CLIENT_AUTH_OID: + return EKU_CLIENT_AUTH_OID; + case EKU_OCSP_SIGN_OID: + return EKU_OCSP_SIGN_OID; + } + break; + + /* oidKdfType */ + case oidKdfType: + switch (oid) { + case PBKDF2_OID: + return PBKDF2_OID; + } + break; + + /* oidPBEType */ + case oidPBEType: + switch (oid) { + case PBE_SHA1_RC4_128: + return PBE_SHA1_RC4_128; + case PBE_SHA1_DES: + return PBE_SHA1_DES; + case PBE_SHA1_DES3: + return PBE_SHA1_DES3; + } + break; + + /* oidKeyWrapType */ + case oidKeyWrapType: + switch (oid) { + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + return AES128_WRAP; + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + return AES192_WRAP; + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + return AES256_WRAP; + #endif + } + break; + + /* oidCmsKeyAgreeType */ + case oidCmsKeyAgreeType: + switch (oid) { + #ifndef NO_SHA + case dhSinglePass_stdDH_sha1kdf_scheme: + return dhSinglePass_stdDH_sha1kdf_scheme; + #endif + #ifdef WOLFSSL_SHA224 + case dhSinglePass_stdDH_sha224kdf_scheme: + return dhSinglePass_stdDH_sha224kdf_scheme; + #endif + #ifndef NO_SHA256 + case dhSinglePass_stdDH_sha256kdf_scheme: + return dhSinglePass_stdDH_sha256kdf_scheme; + #endif + #ifdef WOLFSSL_SHA384 + case dhSinglePass_stdDH_sha384kdf_scheme: + return dhSinglePass_stdDH_sha384kdf_scheme; + #endif + #ifdef WOLFSSL_SHA512 + case dhSinglePass_stdDH_sha512kdf_scheme: + return dhSinglePass_stdDH_sha512kdf_scheme; + #endif + } + break; + + default: + WOLFSSL_MSG("NID not in table"); + return -1; + } + + return -1; +} + + +/* when calling SetIndividualInternal, mpi should be cleared by caller if no + * longer used. ie mp_free(mpi). This is to free data when fastmath is + * disabled since a copy of mpi is made by this function and placed into bn. + */ +int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi) +{ + WOLFSSL_MSG("Entering SetIndividualInternal"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + if (mpi == NULL || (mp_init(mpi) != MP_OKAY)) { + WOLFSSL_MSG("mpi NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + return WOLFSSL_FATAL_ERROR; + } + + return WOLFSSL_SUCCESS; +} + + +#ifndef NO_ASN +WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, + WOLFSSL_BIGNUM *bn) +{ + mp_int mpi; + word32 idx = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_to_BN"); + + if (ai == NULL) { + return NULL; + } + + ret = GetInt(&mpi, ai->data, &idx, ai->dataMax); + if (ret != 0) { + #ifdef WOLFSSL_QT + mp_init(&mpi); /* must init mpi */ + /* Serial number in QT starts at index 0 of data */ + if (mp_read_unsigned_bin(&mpi, (byte*)ai->data, ai->length) != 0) { + mp_clear(&mpi); + return NULL; + } + #else + /* expecting ASN1 format for INTEGER */ + WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_to_BN", ret); + return NULL; + #endif + } + + /* mp_clear needs called because mpi is copied and causes memory leak with + * --disable-fastmath */ + ret = SetIndividualExternal(&bn, &mpi); + mp_clear(&mpi); + + if (ret != WOLFSSL_SUCCESS) { + return NULL; + } + return bn; +} +#endif /* !NO_ASN */ + +#if !defined(NO_DSA) && !defined(NO_DH) +WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *dsa) +{ + WOLFSSL_DH* dh; + DhKey* key; + + WOLFSSL_ENTER("wolfSSL_DSA_dup_DH"); + + if (dsa == NULL) { + return NULL; + } + + dh = wolfSSL_DH_new(); + if (dh == NULL) { + return NULL; + } + key = (DhKey*)dh->internal; + + if (dsa->p != NULL && + 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) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa g key error"); + wolfSSL_DH_free(dh); + return NULL; + } + + 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) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa g key error"); + wolfSSL_DH_free(dh); + return NULL; + } + + return dh; +} +#endif /* !NO_DSA && !NO_DH */ + + +#ifndef NO_RSA +#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) +/* Openssl -> WolfSSL */ +int SetRsaInternal(WOLFSSL_RSA* rsa) +{ + RsaKey* key; + WOLFSSL_MSG("Entering SetRsaInternal"); + + if (rsa == NULL || rsa->internal == NULL) { + WOLFSSL_MSG("rsa key NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + key = (RsaKey*)rsa->internal; + + if (SetIndividualInternal(rsa->n, &key->n) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa n key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualInternal(rsa->e, &key->e) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa e key error"); + return WOLFSSL_FATAL_ERROR; + } + + /* public key */ + key->type = RSA_PUBLIC; + + if (rsa->d != NULL) { + if (SetIndividualInternal(rsa->d, &key->d) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa d key error"); + return WOLFSSL_FATAL_ERROR; + } + + /* private key */ + key->type = RSA_PRIVATE; + } + + if (rsa->p != NULL && + SetIndividualInternal(rsa->p, &key->p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (rsa->q != NULL && + SetIndividualInternal(rsa->q, &key->q) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa q key error"); + return WOLFSSL_FATAL_ERROR; + } + +#ifndef RSA_LOW_MEM + if (rsa->dmp1 != NULL && + SetIndividualInternal(rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa dP key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (rsa->dmq1 != NULL && + SetIndividualInternal(rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa dQ key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (rsa->iqmp != NULL && + SetIndividualInternal(rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa u key error"); + return WOLFSSL_FATAL_ERROR; + } +#endif /* !RSA_LOW_MEM */ + + rsa->inSet = 1; + + return WOLFSSL_SUCCESS; +} + + +/* SSL_SUCCESS on ok */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn) +{ + (void)rsa; + (void)bn; + WOLFSSL_STUB("RSA_blinding_on"); + WOLFSSL_MSG("wolfSSL_RSA_blinding_on"); + + return WOLFSSL_SUCCESS; /* on by default */ +} +#endif + +/* return compliant with OpenSSL + * size of encrypted data if success , -1 if error + */ +int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr, + unsigned char* to, WOLFSSL_RSA* rsa, int padding) +{ + int initTmpRng = 0; + WC_RNG *rng = NULL; + int outLen; + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG _tmpRNG[1]; + WC_RNG* tmpRNG = _tmpRNG; +#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"); + + /* 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_PSS_PADDING) { + padding = WC_RSA_PSS_PAD; + hash = WC_HASH_TYPE_SHA256; + mgf = WC_MGF1SHA256; + } + else if (padding == RSA_NO_PADDING) { + padding = WC_RSA_NO_PAD; + } +#else + if (padding == RSA_PKCS1_PADDING) + ; +#endif + else { + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt unsupported padding"); + return 0; + } + + if (rsa->inSet == 0) + { + if (SetRsaInternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + + outLen = wolfSSL_RSA_size(rsa); + + rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRNG, &initTmpRng); + + if (outLen == 0) { + WOLFSSL_MSG("Bad RSA size"); + } + + if (rng) { +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + ret = wc_RsaPublicEncrypt_ex(fr, len, to, outLen, + (RsaKey*)rsa->internal, rng, padding, + hash, mgf, NULL, 0); +#else + ret = wc_RsaPublicEncrypt(fr, len, to, outLen, + (RsaKey*)rsa->internal, rng); +#endif + if (ret <= 0) { + WOLFSSL_MSG("Bad Rsa Encrypt"); + } + if (len <= 0) { + WOLFSSL_MSG("Bad Rsa Encrypt"); + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + if (tmpRNG) + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret >= 0) + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt success"); + else { + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt failed"); + ret = WOLFSSL_FATAL_ERROR; /* return -1 on error case */ + } + return ret; +} + + + + +/* return compliant with OpenSSL + * size of plain recovered data if success , -1 if error + */ +int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr, + unsigned char* to, WOLFSSL_RSA* rsa, int padding) +{ + int outLen; + int ret = 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"); + +#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_PSS_PADDING) { + padding = WC_RSA_PSS_PAD; + hash = WC_HASH_TYPE_SHA256; + mgf = WC_MGF1SHA256; + } + else if (padding == RSA_NO_PADDING) { + padding = WC_RSA_NO_PAD; + } +#else + if (padding == RSA_PKCS1_PADDING) + ; +#endif + else { + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt unsupported padding"); + return 0; + } + + if (rsa->inSet == 0) + { + if (SetRsaInternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + + outLen = wolfSSL_RSA_size(rsa); + if (outLen == 0) { + WOLFSSL_MSG("Bad RSA size"); + } + + /* size of 'to' buffer must be size of RSA key */ +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + ret = wc_RsaPrivateDecrypt_ex(fr, len, to, outLen, + (RsaKey*)rsa->internal, padding, + hash, mgf, NULL, 0); +#else + ret = wc_RsaPrivateDecrypt(fr, len, to, outLen, + (RsaKey*)rsa->internal); +#endif + + if (len <= 0) { + WOLFSSL_MSG("Bad Rsa Decrypt"); + } + + if (ret > 0) + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt success"); + else { + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt failed"); + ret = WOLFSSL_FATAL_ERROR; + } + return ret; +} + +#if !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) +int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from, + unsigned char* to, WOLFSSL_RSA* rsa, int padding) +{ + int tlen = 0; + int pad_type; + + WOLFSSL_ENTER("wolfSSL_RSA_public_decrypt"); + + if (rsa == NULL || rsa->internal == NULL || from == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + switch (padding) { + case RSA_PKCS1_PADDING: + pad_type = WC_RSA_PKCSV15_PAD; + break; + case RSA_PKCS1_OAEP_PADDING: + pad_type = WC_RSA_OAEP_PAD; + break; + case RSA_PKCS1_PSS_PADDING: + pad_type = WC_RSA_PSS_PAD; + break; + case RSA_NO_PADDING: + pad_type = WC_RSA_NO_PAD; + break; + default: + WOLFSSL_MSG("wolfSSL_RSA_public_decrypt unsupported padding"); + return WOLFSSL_FAILURE; + } + + if (rsa->inSet == 0) + { + WOLFSSL_MSG("No RSA internal set, do it"); + + if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return WOLFSSL_FAILURE; + } + } + + /* size of 'to' buffer must be size of RSA key */ + tlen = wc_RsaSSL_Verify_ex(from, flen, to, wolfSSL_RSA_size(rsa), + (RsaKey*)rsa->internal, pad_type); + if (tlen <= 0) + WOLFSSL_MSG("wolfSSL_RSA_public_decrypt failed"); + else { + WOLFSSL_MSG("wolfSSL_RSA_public_decrypt success"); + } + return tlen; +} +#endif /* !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) */ + +/* RSA private encrypt calls wc_RsaSSL_Sign. Similar function set up as RSA + * public decrypt. + * + * len Length of input buffer + * in Input buffer to sign + * out Output buffer (expected to be greater than or equal to RSA key size) + * rsa Key to use for encryption + * padding Type of RSA padding to use. + */ +int wolfSSL_RSA_private_encrypt(int len, unsigned char* in, + unsigned char* out, WOLFSSL_RSA* rsa, int padding) +{ + int sz = 0; + WC_RNG* rng = NULL; +#if !defined(WC_RSA_BLINDING) || defined(HAVE_USER_RSA) + WC_RNG rng_lcl; +#endif + RsaKey* key; + + WOLFSSL_MSG("wolfSSL_RSA_private_encrypt"); + + if (len < 0 || rsa == NULL || rsa->internal == NULL || in == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; + } + + if (padding != RSA_PKCS1_PADDING && padding != RSA_PKCS1_PSS_PADDING) { + WOLFSSL_MSG("wolfSSL_RSA_private_encrypt unsupported padding"); + return 0; + } + + if (rsa->inSet == 0) + { + WOLFSSL_MSG("Setting internal RSA structure"); + + if (SetRsaInternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + + key = (RsaKey*)rsa->internal; +#if defined(WC_RSA_BLINDING) && !defined(HAVE_USER_RSA) + rng = key->rng; +#else + rng = &rng_lcl; + #ifndef HAVE_FIPS + if (wc_InitRng_ex(rng, key->heap, INVALID_DEVID) != 0) + #else + if (wc_InitRng(rng) != 0) + #endif + { + WOLFSSL_MSG("Error with random number"); + return SSL_FATAL_ERROR; + } +#endif + + /* size of output buffer must be size of RSA key */ + sz = wc_RsaSSL_Sign(in, (word32)len, out, wolfSSL_RSA_size(rsa), key, rng); + #if !defined(WC_RSA_BLINDING) || defined(HAVE_USER_RSA) + if (wc_FreeRng(rng) != 0) { + WOLFSSL_MSG("Error freeing random number generator"); + return SSL_FATAL_ERROR; + } + #endif + if (sz <= 0) { + WOLFSSL_LEAVE("wolfSSL_RSA_private_encrypt", sz); + return 0; + } + + return sz; +} +#endif /* HAVE_USER_RSA */ +#endif + + +/* frees all nodes in the current threads error queue + * + * id thread id. ERR_remove_state is depreciated and id is ignored. The + * current threads queue will be free'd. + */ +void wolfSSL_ERR_remove_state(unsigned long id) +{ + WOLFSSL_ENTER("wolfSSL_ERR_remove_state"); + (void)id; + if (wc_ERR_remove_state() != 0) { + WOLFSSL_MSG("Error with removing the state"); + } +} + + +WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void) +{ + static int ctx; /* wolfcrypt doesn't now need ctx */ + + WOLFSSL_MSG("wolfSSL_BN_CTX_new"); + return (WOLFSSL_BN_CTX*)&ctx; + +} + +void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx) +{ + (void)ctx; + WOLFSSL_MSG("wolfSSL_BN_CTX_init"); +} + + +void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx) +{ + (void)ctx; + WOLFSSL_MSG("wolfSSL_BN_CTX_free"); + /* do free since static ctx that does nothing */ +} + +/* WOLFSSL_SUCCESS on ok */ +int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, + const WOLFSSL_BIGNUM* b) +{ + WOLFSSL_MSG("wolfSSL_BN_sub"); + + if (r == NULL || a == NULL || b == NULL) + return 0; + + if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal, + (mp_int*)r->internal) == MP_OKAY) + return WOLFSSL_SUCCESS; + + WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed"); + return 0; +} + +/* WOLFSSL_SUCCESS on ok */ +int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, + const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c) +{ + (void)c; + WOLFSSL_MSG("wolfSSL_BN_mod"); + + if (r == NULL || a == NULL || b == NULL) + return 0; + + if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal, + (mp_int*)r->internal) == MP_OKAY) + return WOLFSSL_SUCCESS; + + WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed"); + return 0; +} + + +/* r = (a^p) % m */ +int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_mod_exp"); + + (void) ctx; + if (r == NULL || a == NULL || p == NULL || m == NULL) { + WOLFSSL_MSG("Bad Argument"); + 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 WOLFSSL_SUCCESS; + } + + WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret); + (void)ret; + + return WOLFSSL_FAILURE; +} + +/* r = (a * p) % m */ +int wolfSSL_BN_mod_mul(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_mod_mul"); + + (void) ctx; + if (r == NULL || a == NULL || p == NULL || m == NULL) { + WOLFSSL_MSG("Bad Argument"); + return SSL_FAILURE; + } + + if ((ret = mp_mulmod((mp_int*)a->internal,(mp_int*)p->internal, + (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) { + return SSL_SUCCESS; + } + + WOLFSSL_LEAVE("wolfSSL_BN_mod_mul", ret); + (void)ret; + + return SSL_FAILURE; +} + +#ifdef OPENSSL_EXTRA +const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void) +{ + WOLFSSL_MSG("wolfSSL_BN_value_one"); + + if (bn_one == NULL) { + bn_one = wolfSSL_BN_new(); + 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; +} +#endif + +/* return compliant with OpenSSL + * size of BIGNUM in bytes, 0 if error */ +int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_ENTER("wolfSSL_BN_num_bytes"); + + if (bn == NULL || bn->internal == NULL) + return WOLFSSL_FAILURE; + + return mp_unsigned_bin_size((mp_int*)bn->internal); +} + +/* return compliant with OpenSSL + * size of BIGNUM in bits, 0 if error */ +int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_ENTER("wolfSSL_BN_num_bits"); + + if (bn == NULL || bn->internal == NULL) + return WOLFSSL_FAILURE; + + return mp_count_bits((mp_int*)bn->internal); +} + +int wolfSSL_BN_is_negative(const WOLFSSL_BIGNUM* bn) +{ + if (bn == NULL) + return WOLFSSL_FAILURE; + + return mp_isneg((mp_int*)bn->internal); +} + +/* return compliant with OpenSSL + * 1 if BIGNUM is zero, 0 else */ +int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_is_zero"); + + if (bn == NULL || bn->internal == NULL) + return WOLFSSL_FAILURE; + + if (mp_iszero((mp_int*)bn->internal) == MP_YES) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + +/* return compliant with OpenSSL + * 1 if BIGNUM is one, 0 else */ +int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_is_one"); + + if (bn == NULL || bn->internal == NULL) + return WOLFSSL_FAILURE; + + if (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + +/* return compliant with OpenSSL + * 1 if BIGNUM is odd, 0 else */ +int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_is_odd"); + + if (bn == NULL || bn->internal == NULL) + return WOLFSSL_FAILURE; + + if (mp_isodd((mp_int*)bn->internal) == MP_YES) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + +/* return compliant with OpenSSL + * 1 if BIGNUM is word, 0 else */ +int wolfSSL_BN_is_word(const WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w) +{ + WOLFSSL_ENTER("wolfSSL_BN_is_word"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + if (mp_isword((mp_int*)bn->internal, w) == MP_YES) { + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; +} + +/* return compliant with OpenSSL + * -1 if a < b, 0 if a == b and 1 if a > b + */ +int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b) +{ + int ret; + + WOLFSSL_MSG("wolfSSL_BN_cmp"); + + if (a == NULL || a->internal == NULL || b == NULL || b->internal == NULL) + return WOLFSSL_FATAL_ERROR; + + ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal); + + return (ret == MP_EQ ? 0 : (ret == MP_GT ? 1 : -1)); +} + +/* return compliant with OpenSSL + * length of BIGNUM in bytes, -1 if error */ +int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r) +{ + WOLFSSL_MSG("wolfSSL_BN_bn2bin"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("NULL bn error"); + return WOLFSSL_FATAL_ERROR; + } + + if (r == NULL) + return mp_unsigned_bin_size((mp_int*)bn->internal); + + if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) { + WOLFSSL_MSG("mp_to_unsigned_bin error"); + return WOLFSSL_FATAL_ERROR; + } + + return mp_unsigned_bin_size((mp_int*)bn->internal); +} + + +WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len, + WOLFSSL_BIGNUM* ret) +{ + int weOwn = 0; + + WOLFSSL_MSG("wolfSSL_BN_bin2bn"); + + /* if ret is null create a BN */ + if (ret == NULL) { + ret = wolfSSL_BN_new(); + weOwn = 1; + if (ret == NULL) + return NULL; + } + + /* check ret and ret->internal then read in value */ + if (ret && ret->internal) { + if (mp_read_unsigned_bin((mp_int*)ret->internal, str, len) != 0) { + WOLFSSL_MSG("mp_read_unsigned_bin failure"); + if (weOwn) + wolfSSL_BN_free(ret); + return NULL; + } + } else { + return NULL; + } + + return ret; +} + +/* return compliant with OpenSSL + * 1 if success, 0 if error */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n) +{ + (void)bn; + (void)n; + WOLFSSL_ENTER("wolfSSL_BN_mask_bits"); + WOLFSSL_STUB("BN_mask_bits"); + return SSL_FAILURE; +} +#endif + + +/* WOLFSSL_SUCCESS on ok */ +int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) +{ + int ret = 0; + int len = bits / 8; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; + byte* buff = NULL; +#else + WC_RNG tmpRNG[1]; + byte buff[1024]; +#endif + + (void)top; + (void)bottom; + WOLFSSL_MSG("wolfSSL_BN_rand"); + + if (bits % 8) + len++; + +#ifdef WOLFSSL_SMALL_STACK + buff = (byte*)XMALLOC(1024, 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_RNG); + return ret; + } +#endif + + if (bn == NULL || bn->internal == NULL) + WOLFSSL_MSG("Bad function arguments"); + else if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else if (initGlobalRNG) + rng = &globalRNG; + + if (rng) { + if (wc_RNG_GenerateBlock(rng, buff, len) != 0) + WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + else { + buff[0] |= 0x80 | 0x40; + buff[len-1] |= 0x01; + + if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY) + WOLFSSL_MSG("mp read bin failed"); + else + ret = WOLFSSL_SUCCESS; + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return ret; +} + + +/* WOLFSSL_SUCCESS on ok + * code is same as wolfSSL_BN_rand except for how top and bottom is handled. + * top -1 then leave most sig bit alone + * top 0 then most sig is set to 1 + * top is 1 then first two most sig bits are 1 + * + * bottom is hot then odd number */ +int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) +{ + int ret = 0; + int len = bits / 8; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; + byte* buff = NULL; +#else + WC_RNG tmpRNG[1]; + byte buff[1024]; +#endif + + WOLFSSL_MSG("wolfSSL_BN_rand"); + + if (bits % 8) + len++; + +#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); + if (buff == NULL || tmpRNG == NULL) { + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } +#endif + + if (bn == NULL || bn->internal == NULL) + WOLFSSL_MSG("Bad function arguments"); + else if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else if (initGlobalRNG) + rng = &globalRNG; + + if (rng) { + if (wc_RNG_GenerateBlock(rng, buff, len) != 0) + WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + else { + switch (top) { + case -1: + break; + + case 0: + buff[0] |= 0x80; + break; + + case 1: + buff[0] |= 0x80 | 0x40; + break; + } + + if (bottom == 1) { + buff[len-1] |= 0x01; + } + + if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY) + WOLFSSL_MSG("mp read bin failed"); + else + ret = WOLFSSL_SUCCESS; + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +/* return code compliant with OpenSSL : + * 1 if bit set, 0 else + */ +int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n) +{ + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + return mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n); +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n) +{ + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) { + WOLFSSL_MSG("mp_set_bit error"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM* bn, int n) +{ + int ret = WOLFSSL_FAILURE; +#ifndef WOLFSSL_SMALL_STACK + mp_int tmp[1]; +#else + mp_int* tmp = NULL; +#endif + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + goto cleanup; + } + if (mp_is_bit_set((mp_int*)bn->internal, n)) { +#ifdef WOLFSSL_SMALL_STACK + tmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (tmp == NULL) { + goto cleanup; + } +#endif + if (mp_init(tmp) != MP_OKAY) { + goto cleanup; + } + if (mp_set_bit(tmp, n) != MP_OKAY) { + goto cleanup; + } + if (mp_sub((mp_int*)bn->internal, tmp, (mp_int*)bn->internal) != MP_OKAY) { + goto cleanup; + } + } + + ret = WOLFSSL_SUCCESS; +cleanup: + mp_clear(tmp); +#ifdef WOLFSSL_SMALL_STACK + if (tmp) + XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return ret; +} + + +/* 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; + word32 decSz = 1024; +#ifdef WOLFSSL_SMALL_STACK + byte* decoded; +#else + byte decoded[1024]; +#endif + int weOwn = 0; + int strLen; + + WOLFSSL_MSG("wolfSSL_BN_hex2bn"); + +#ifdef WOLFSSL_SMALL_STACK + decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_DER); + if (decoded == NULL) + return ret; +#endif + + if (str == NULL || str[0] == '\0') { + WOLFSSL_MSG("Bad function argument"); + ret = WOLFSSL_FAILURE; + } else { + strLen = (int)XSTRLEN(str); + /* ignore trailing new lines */ + while (str[strLen-1] == '\n' && strLen > 0) strLen--; + + if (Base16_Decode((byte*)str, strLen, decoded, &decSz) < 0) + WOLFSSL_MSG("Bad Base16_Decode error"); + else if (bn == NULL) + ret = decSz; + else { + if (*bn == NULL) { + *bn = wolfSSL_BN_new(); + if (*bn != NULL) { + weOwn = 1; + } + } + + if (*bn == NULL) + WOLFSSL_MSG("BN new failed"); + else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) { + WOLFSSL_MSG("Bad bin2bn error"); + if (weOwn == 1) { + wolfSSL_BN_free(*bn); /* Free new BN */ + } + } + else + ret = WOLFSSL_SUCCESS; + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_DER); +#endif + + return ret; +} + + +WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_BIGNUM* ret; + + WOLFSSL_MSG("wolfSSL_BN_dup"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return NULL; + } + + ret = wolfSSL_BN_new(); + if (ret == NULL) { + WOLFSSL_MSG("bn new error"); + return NULL; + } + + if (mp_copy((mp_int*)bn->internal, (mp_int*)ret->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + wolfSSL_BN_free(ret); + return NULL; + } + + ret->neg = bn->neg; + + return ret; +} + + +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; + } + + r->neg = bn->neg; + + return r; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w) +{ + WOLFSSL_MSG("wolfSSL_BN_set_word"); + + if (bn == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + if (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) { + WOLFSSL_MSG("mp_init_set_int error"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + + +/* Returns the big number as an unsigned long if possible. + * + * bn big number structure to get value from + * + * Returns value or 0xFFFFFFFFL if bigger than unsigned long. + */ +unsigned long wolfSSL_BN_get_word(const WOLFSSL_BIGNUM* bn) +{ + mp_int* mp; + + WOLFSSL_MSG("wolfSSL_BN_get_word"); + + if (bn == NULL) { + WOLFSSL_MSG("Invalid argument"); + return 0; + } + + if (wolfSSL_BN_num_bytes(bn) > (int)sizeof(unsigned long)) { + WOLFSSL_MSG("bignum is larger than unsigned long"); + return 0xFFFFFFFFL; + } + mp = (mp_int*)bn->internal; + + return (unsigned long)(mp->dp[0]); +} + +/* return code compliant with OpenSSL : + * number length in decimal if success, 0 if error + */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str) +{ + (void)bn; + (void)str; + + WOLFSSL_MSG("wolfSSL_BN_dec2bn"); + WOLFSSL_STUB("BN_dec2bn"); + return SSL_FAILURE; +} +#endif + +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) +char *wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn) +{ + int len = 0; + char *buf; + + WOLFSSL_MSG("wolfSSL_BN_bn2dec"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return NULL; + } + + 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_OPENSSL); + if (buf == NULL) { + WOLFSSL_MSG("BN_bn2dec malloc buffer failure"); + return NULL; + } + + if (mp_todecimal((mp_int*)bn->internal, buf) != MP_OKAY) { + XFREE(buf, NULL, DYNAMIC_TYPE_ECC); + return NULL; + } + + return buf; +} +#else +char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn) +{ + (void)bn; + + WOLFSSL_MSG("wolfSSL_BN_bn2dec"); + + return NULL; +} +#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ + +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) +{ + WOLFSSL_MSG("wolfSSL_BN_lshift"); + + if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){ + WOLFSSL_MSG("bn NULL error"); + 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 WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) +{ + WOLFSSL_MSG("wolfSSL_BN_rshift"); + + if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){ + WOLFSSL_MSG("bn NULL error"); + 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 WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w) +{ + WOLFSSL_MSG("wolfSSL_BN_add_word"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + 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 WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b) +{ + WOLFSSL_MSG("wolfSSL_BN_add"); + + if (r == NULL || r->internal == NULL || a == NULL || a->internal == NULL || + b == NULL || b->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + 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 WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* r = a + b (mod m) */ +int wolfSSL_BN_mod_add(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m, + WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; + WOLFSSL_MSG("wolfSSL_BN_add"); + + if (r == NULL || r->internal == NULL || + a == NULL || a->internal == NULL || + b == NULL || b->internal == NULL || + m == NULL || m->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + if (mp_addmod((mp_int*)a->internal, (mp_int*)b->internal, + (mp_int*)m->internal, (mp_int*)r->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_add_d error"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +#ifdef WOLFSSL_KEY_GEN + +/* return code compliant with OpenSSL : + * 1 if prime, 0 if not, -1 if error + */ +int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks, + WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb) +{ + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + int initTmpRng = 0; + int res = MP_NO; + + (void)ctx; + (void)cb; + + WOLFSSL_MSG("wolfSSL_BN_is_prime_ex"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FATAL_ERROR; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FAILURE; +#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; + } + + if (rng) { + if (mp_prime_is_prime_ex((mp_int*)bn->internal, + nbchecks, &res, rng) != MP_OKAY) { + WOLFSSL_MSG("mp_prime_is_prime_ex error"); + res = MP_NO; + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + if (res != MP_YES) { + WOLFSSL_MSG("mp_prime_is_prime_ex not prime"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* return code compliant with OpenSSL : + * (bn mod w) if success, -1 if error + */ +WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn, + WOLFSSL_BN_ULONG w) +{ + WOLFSSL_BN_ULONG ret = 0; + + WOLFSSL_MSG("wolfSSL_BN_mod_word"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL 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)WOLFSSL_FATAL_ERROR; + } + + return ret; +} +#endif /* #ifdef WOLFSSL_KEY_GEN */ + +char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) +{ + int len = 0; + char *buf; + + 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, MP_RADIX_HEX, &len) != MP_OKAY) { + WOLFSSL_MSG("mp_radix_size failure"); + return NULL; + } + len += 1; /* add one for null terminator */ + + buf = (char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); + if (buf == NULL) { + WOLFSSL_MSG("BN_bn2hex malloc buffer failure"); + return NULL; + } + + if (mp_tohex((mp_int*)bn->internal, buf) != MP_OKAY) { + XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + return buf; +} + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_BN_print_fp(XFILE fp, const WOLFSSL_BIGNUM *bn) +{ + char *buf; + + WOLFSSL_ENTER("wolfSSL_BN_print_fp"); + + if (fp == XBADFILE || bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + buf = wolfSSL_BN_bn2hex(bn); + if (buf == NULL) { + WOLFSSL_MSG("wolfSSL_BN_bn2hex failure"); + return WOLFSSL_FAILURE; + } + + fprintf(fp, "%s", buf); + XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); + + return WOLFSSL_SUCCESS; +} +#endif /* !NO_FILESYSTEM */ + + +WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx) +{ + /* ctx is not used, return new Bignum */ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_CTX_get"); + + return wolfSSL_BN_new(); +} + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_CTX_start"); + WOLFSSL_STUB("BN_CTX_start"); + WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD"); +} +#endif + + +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; +} +#endif /* OPENSSL_EXTRA */ +#if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) && !defined(NO_ASN) +static int unprintable_char(char c) +{ + const unsigned char last_unprintable = 31; + const unsigned char LF = 10; + const unsigned char CR = 13; + + if (c <= last_unprintable && c != LF && c != CR) { + return 1; + } + return 0; +} + +int wolfSSL_ASN1_STRING_print(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str) +{ + int i; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_print"); + if (out == NULL || str == NULL) + return WOLFSSL_FAILURE; + + for (i=0; i < str->length; i++) { + if (unprintable_char(str->data[i])) { + str->data[i] = '.'; + } + } + + if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){ + return WOLFSSL_FAILURE; + } + + return str->length; +} +#endif /* (WOLFSSL_QT || OPENSSL_ALL) && !NO_ASN */ + +#if defined(OPENSSL_EXTRA) +int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509) +{ + WOLFSSL_ENTER("X509_check_ca"); + + if (x509 == NULL) + return WOLFSSL_FAILURE; + if (x509->isCa) + return 1; + if (x509->extKeyUsageCrit) + return 4; + + return 0; +} + + +const char *wolfSSL_ASN1_tag2str(int tag) +{ + static const char *const tag_label[31] = { + "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", "NULL", + "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", "ENUMERATED", + "", "UTF8STRING", "", "", "", + "SEQUENCE", "SET", "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", + "VIDEOTEXTSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", + "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", "UNIVERSALSTRING", + "", "BMPSTRING" + }; + + if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) + tag &= ~0x100; + if (tag < 0 || tag > 30) + return "(unknown)"; + return tag_label[tag]; +} + +static int check_esc_char(char c, char *esc) +{ + char *ptr; + + ptr = esc; + while(*ptr != 0){ + if (c == *ptr) + return 1; + ptr++; + } + return 0; +} + +int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str, + unsigned long flags) +{ + size_t str_len = 0, type_len = 0; + unsigned char *typebuf = NULL; + const char *hash="#"; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_PRINT_ex"); + if (out == NULL || str == NULL) + return WOLFSSL_FAILURE; + + /* add ASN1 type tag */ + if (flags & ASN1_STRFLGS_SHOW_TYPE){ + const char *tag = wolfSSL_ASN1_tag2str(str->type); + /* colon len + tag len + null*/ + type_len = XSTRLEN(tag) + 2; + typebuf = (unsigned char *)XMALLOC(type_len , NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (typebuf == NULL){ + WOLFSSL_MSG("memory alloc failed."); + return WOLFSSL_FAILURE; + } + XMEMSET(typebuf, 0, type_len); + XSNPRINTF((char*)typebuf, (size_t)type_len , "%s:", tag); + type_len--; + } + + /* dump hex */ + if (flags & ASN1_STRFLGS_DUMP_ALL){ + static const char hex_char[] = { '0', '1', '2', '3', '4', '5', '6', + '7','8', '9', 'A', 'B', 'C', 'D', + 'E', 'F' }; + char hex_tmp[4]; + char *str_ptr, *str_end; + + if (type_len > 0){ + if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){ + XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + str_len += type_len; + } + if (wolfSSL_BIO_write(out, hash, 1) != 1){ + goto err_exit; + } + str_len++; + if (flags & ASN1_STRFLGS_DUMP_DER){ + hex_tmp[0] = hex_char[str->type >> 4]; + hex_tmp[1] = hex_char[str->type & 0xf]; + hex_tmp[2] = hex_char[str->length >> 4]; + hex_tmp[3] = hex_char[str->length & 0xf]; + if (wolfSSL_BIO_write(out, hex_tmp, 4) != 4){ + goto err_exit; + } + str_len += 4; + XMEMSET(hex_tmp, 0, 4); + } + + str_ptr = str->data; + str_end = str->data + str->length; + while (str_ptr < str_end){ + hex_tmp[0] = hex_char[*str_ptr >> 4]; + hex_tmp[1] = hex_char[*str_ptr & 0xf]; + if (wolfSSL_BIO_write(out, hex_tmp, 2) != 2){ + goto err_exit; + } + str_ptr++; + str_len += 2; + } + if (type_len > 0) + XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return (int)str_len; + } + + if (type_len > 0){ + if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){ + XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + str_len += type_len; + } + + if (flags & ASN1_STRFLGS_ESC_2253){ + char esc_ch[] = "+;<>\\"; + char* esc_ptr; + + esc_ptr = str->data; + while (*esc_ptr != 0){ + if (check_esc_char(*esc_ptr, esc_ch)){ + if (wolfSSL_BIO_write(out,"\\", 1) != 1) + goto err_exit; + str_len++; + } + if (wolfSSL_BIO_write(out, esc_ptr, 1) != 1) + goto err_exit; + str_len++; + esc_ptr++; + } + if (type_len > 0) + XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return (int)str_len; + } + + if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){ + goto err_exit; + } + str_len += str->length; + if (type_len > 0) + XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return (int)str_len; + +err_exit: + if (type_len > 0) + XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; +} + +#if !defined(NO_ASN_TIME) && !defined(USER_TIME) && !defined(TIME_OVERRIDES) +WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_new(void) +{ + WOLFSSL_ASN1_TIME* ret = (WOLFSSL_ASN1_TIME*) + XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL, DYNAMIC_TYPE_OPENSSL); + if (!ret) + return NULL; + XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TIME)); + return ret; +} + +void wolfSSL_ASN1_TIME_free(WOLFSSL_ASN1_TIME* t) +{ + if (t) { + XFREE(t, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t, + int offset_day, long offset_sec) +{ + const time_t sec_per_day = 24*60*60; + struct tm* ts = NULL; + struct tm* tmpTime; + time_t t_adj = 0; + time_t offset_day_sec = 0; +#if defined(NEED_TMP_TIME) + struct tm tmpTimeStorage; + + tmpTime = &tmpTimeStorage; +#else + tmpTime = NULL; +#endif + (void)tmpTime; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_adj"); + + if (s == NULL){ + s = wolfSSL_ASN1_TIME_new(); + 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; + + s->type = V_ASN1_UTCTIME; + s->length = ASN_UTC_TIME_SIZE; + + 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, sizeof(utc_str), + "%02d%02d%02d%02d%02d%02dZ", + utc_year, utc_mon, utc_day, utc_hour, utc_min, utc_sec); + XMEMCPY(s->data, (byte *)utc_str, s->length); + /* GeneralizedTime */ + } else { + char gt_str[ASN_GENERALIZED_TIME_MAX]; + int gt_year,gt_mon,gt_day,gt_hour,gt_min,gt_sec; + + s->type = V_ASN1_GENERALIZEDTIME; + s->length = ASN_GENERALIZED_TIME_SIZE; + + 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, sizeof(gt_str), + "%4d%02d%02d%02d%02d%02dZ", + gt_year, gt_mon, gt_day, gt_hour, gt_min,gt_sec); + XMEMCPY(s->data, (byte *)gt_str, s->length); + } + + return s; +} +#endif /* !NO_ASN_TIME && !USER_TIME && !TIME_OVERRIDES */ + +#ifndef NO_ASN_TIME +/* not a compatibility function - length getter for opaque type */ +int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME *t) +{ + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_length"); + if (t == NULL) + return WOLFSSL_FAILURE; + return t->length; +} +/* not a compatibility function - data getter for opaque type */ +unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME *t) +{ + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_data"); + if (t == NULL) + return NULL; + return t->data; +} + +WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, + WOLFSSL_ASN1_TIME **out) +{ + int time_type = 0; + WOLFSSL_ASN1_TIME *ret = NULL; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_generalizedtime"); + if (t == NULL) { + WOLFSSL_MSG("Invalid ASN_TIME value"); + } else { + time_type = t->type; + if (time_type != ASN_UTC_TIME && time_type != ASN_GENERALIZED_TIME){ + WOLFSSL_MSG("Invalid ASN_TIME type."); + } else { + if (out == NULL || *out == NULL) { + ret = wolfSSL_ASN1_TIME_new(); + if (ret == NULL){ + WOLFSSL_MSG("memory alloc failed."); + } + } else { + ret = *out; + } + } + } + + if (ret != NULL) { + if (time_type == ASN_GENERALIZED_TIME){ + XMEMCPY(ret->data, t->data, ASN_GENERALIZED_TIME_SIZE); + } else { /* ASN_UTC_TIME */ + /* convert UTC to generalized time */ + ret->type = ASN_GENERALIZED_TIME; + ret->length = ASN_GENERALIZED_TIME_SIZE; + if (t->data[0] >= '5') { + ret->data[0] = '1'; ret->data[1] = '9'; + } else { + ret->data[0] = '2'; ret->data[1] = '0'; + } + XMEMCPY(&ret->data[2], t->data, ASN_UTC_TIME_SIZE); + } + } + + return ret; +} +#endif /* !NO_ASN_TIME */ + +#ifndef NO_ASN +int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp) +{ + unsigned char *pptr = NULL; + char pad = 0 ; + unsigned char pad_val = 0; + int ret_size = 0; + unsigned char data1 = 0; + unsigned char neg = 0; + int i = 0; + + WOLFSSL_ENTER("wolfSSL_i2c_ASN1_INTEGER"); + if (a == NULL) + return WOLFSSL_FAILURE; + + ret_size = a->intData[1]; + if (ret_size == 0) + ret_size = 1; + else{ + ret_size = (int)a->intData[1]; + neg = a->negative; + data1 = a->intData[2]; + if (ret_size == 1 && data1 == 0) + neg = 0; + /* 0x80 or greater positive number in first byte */ + if (!neg && (data1 > 127)){ + pad = 1; + pad_val = 0; + } else if (neg){ + /* negative number */ + if (data1 > 128){ + pad = 1; + pad_val = 0xff; + } else if (data1 == 128){ + for (i = 3; i < a->intData[1] + 2; i++){ + if (a->intData[i]){ + pad = 1; + pad_val = 0xff; + break; + } + } + } + } + ret_size += (int)pad; + } + if (pp == NULL) + return ret_size; + + pptr = *pp; + if (pad) + *(pptr++) = pad_val; + if (a->intData[1] == 0) + *(pptr++) = 0; + else if (!neg){ + /* positive number */ + for (i=0; i < a->intData[1]; i++){ + *pptr = a->intData[i+2]; + pptr++; + } + } else { + /* negative number */ + int str_len = 0; + + /* 0 padding from end of buffer */ + str_len = (int)a->intData[1]; + pptr += a->intData[1] - 1; + while (!a->intData[str_len + 2] && str_len > 1){ + *(pptr--) = 0; + str_len--; + } + /* 2's complement next octet */ + *(pptr--) = ((a->intData[str_len + 1]) ^ 0xff) + 1; + str_len--; + /* Complement any octets left */ + while (str_len > 0){ + *(pptr--) = a->intData[str_len + 1] ^ 0xff; + str_len--; + } + } + *pp += ret_size; + return ret_size; +} +#endif /* !NO_ASN */ + + +#ifndef NO_CERTS +int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE* store) +{ + int i = 0; + int cnt_ret = 0; + Signer **table; + + WOLFSSL_ENTER("wolfSSL_X509_CA_num"); + if (store == NULL || store->cm == NULL){ + WOLFSSL_MSG("invalid parameter"); + return WOLFSSL_FAILURE; + } + + table = store->cm->caTable; + if (table){ + if (wc_LockMutex(&store->cm->caLock) == 0){ + for (i = 0; i < CA_TABLE_SIZE; i++) { + Signer* signer = table[i]; + while (signer) { + Signer* next = signer->next; + cnt_ret++; + signer = next; + } + } + wc_UnLockMutex(&store->cm->caLock); + } + } + + return cnt_ret; +} +#endif /* !NO_CERTS */ + +long wolfSSL_X509_get_version(const WOLFSSL_X509 *x509) +{ + int version = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_version"); + + if (x509 == NULL){ + WOLFSSL_MSG("invalid parameter"); + return 0L; + } + version = x509->version; + if (version != 0) + return (long)version - 1L; + + return 0L; +} + + +int wolfSSL_X509_get_signature_nid(const WOLFSSL_X509 *x) +{ + if (x == NULL) + return 0; + + return oid2nid(x->sigOID, oidSigType); +} +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) +/* return compliant with OpenSSL + * RSA modulus size in bytes, -1 if error + */ +int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa) +{ + WOLFSSL_ENTER("wolfSSL_RSA_size"); + + if (rsa == NULL) + return WOLFSSL_FATAL_ERROR; + if (rsa->inSet == 0) + { + if (SetRsaInternal((WOLFSSL_RSA*)rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + return wc_RsaEncryptSize((RsaKey*)rsa->internal); +} +#endif + +#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) && \ + !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +/* WolfSSL -> OpenSSL */ +int SetRsaExternal(WOLFSSL_RSA* rsa) +{ + RsaKey* key; + WOLFSSL_MSG("Entering SetRsaExternal"); + + if (rsa == NULL || rsa->internal == NULL) { + WOLFSSL_MSG("rsa key NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + key = (RsaKey*)rsa->internal; + + if (SetIndividualExternal(&rsa->n, &key->n) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa n key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->e, &key->e) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa e key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (key->type == RSA_PRIVATE) { + if (SetIndividualExternal(&rsa->d, &key->d) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa d key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->p, &key->p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->q, &key->q) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa q key error"); + return WOLFSSL_FATAL_ERROR; + } + + #ifndef RSA_LOW_MEM + if (SetIndividualExternal(&rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa dP key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa dQ key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa u key error"); + return WOLFSSL_FATAL_ERROR; + } + #endif /* !RSA_LOW_MEM */ + } + rsa->exSet = 1; + + return WOLFSSL_SUCCESS; +} +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* when calling SetIndividualExternal, mpi should be cleared by caller if no + * longer used. ie mp_free(mpi). This is to free data when fastmath is + * disabled since a copy of mpi is made by this function and placed into bn. + */ +int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) +{ + byte dynamic = 0; + + WOLFSSL_MSG("Entering SetIndividualExternal"); + + if (mpi == NULL || bn == NULL) { + WOLFSSL_MSG("mpi NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + if (*bn == NULL) { + *bn = wolfSSL_BN_new(); + if (*bn == NULL) { + WOLFSSL_MSG("SetIndividualExternal alloc failed"); + return WOLFSSL_FATAL_ERROR; + } + dynamic = 1; + } + + if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + if (dynamic == 1) { + wolfSSL_BN_free(*bn); + } + return WOLFSSL_FATAL_ERROR; + } + + return WOLFSSL_SUCCESS; +} + + +static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn) +{ + if (bn) { + XMEMSET(bn, 0, sizeof(WOLFSSL_BIGNUM)); + bn->neg = 0; + bn->internal = NULL; + } +} + + +WOLFSSL_BIGNUM* wolfSSL_BN_new(void) +{ + WOLFSSL_BIGNUM* external; + mp_int* mpi; + + WOLFSSL_MSG("wolfSSL_BN_new"); + +#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT) + mpi = (mp_int*) XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (mpi == NULL) { + WOLFSSL_MSG("wolfSSL_BN_new malloc mpi failure"); + return NULL; + } +#endif + + external = (WOLFSSL_BIGNUM*) XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL, + DYNAMIC_TYPE_BIGINT); + if (external == NULL) { + WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure"); +#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT) + XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return NULL; + } + +#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) + mpi = &external->fp; +#endif + + InitwolfSSL_BigNum(external); + if (mp_init(mpi) != MP_OKAY) { + wolfSSL_BN_free(external); + return NULL; + } + external->internal = mpi; + + return external; +} + + +#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) +/* This function works without BN_free only with TFM */ +void wolfSSL_BN_init(WOLFSSL_BIGNUM* bn) +{ + if(bn == NULL)return; + WOLFSSL_MSG("wolfSSL_BN_init"); + InitwolfSSL_BigNum(bn); + if (mp_init(&bn->fp) != MP_OKAY) + return; + bn->internal = (void *)&bn->fp; +} +#endif + +void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_free"); + if (bn) { + if (bn->internal) { + mp_int* bni = (mp_int*)bn->internal; + mp_free(bni); +#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT) + XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT); +#endif + bn->internal = NULL; + } + XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT); + /* bn = NULL, don't try to access or double free it */ + } +} + +void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_clear_free"); + if (bn) { + if (bn->internal) { + mp_int* bni = (mp_int*)bn->internal; + mp_forcezero(bni); + } + wolfSSL_BN_free(bn); + } +} + +void wolfSSL_BN_clear(WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_clear"); + if (bn && bn->internal) { + mp_forcezero((mp_int*)bn->internal); + } +} +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#if !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +static void InitwolfSSL_Rsa(WOLFSSL_RSA* rsa) +{ + if (rsa) { + XMEMSET(rsa, 0, sizeof(WOLFSSL_RSA)); + } +} + + +void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) +{ + WOLFSSL_ENTER("wolfSSL_RSA_free"); + + if (rsa) { +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + int doFree = 0; + if (wc_LockMutex(&rsa->refMutex) != 0) { + WOLFSSL_MSG("Couldn't lock rsa mutex"); + } + + /* only free if all references to it are done */ + rsa->refCount--; + if (rsa->refCount == 0) { + doFree = 1; + } + wc_UnLockMutex(&rsa->refMutex); + + if (!doFree) { + return; + } + + wc_FreeMutex(&rsa->refMutex); +#endif + + if (rsa->internal) { +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \ + !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) + WC_RNG* rng; + + /* check if RNG is owned before freeing it */ + if (rsa->ownRng) { + 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; + } + wolfSSL_BN_free(rsa->iqmp); + wolfSSL_BN_free(rsa->dmq1); + wolfSSL_BN_free(rsa->dmp1); + wolfSSL_BN_free(rsa->q); + wolfSSL_BN_free(rsa->p); + wolfSSL_BN_free(rsa->d); + wolfSSL_BN_free(rsa->e); + wolfSSL_BN_free(rsa->n); + + #ifdef WC_RSA_BLINDING + if (rsa->rng && wc_FreeRng(rsa->rng) != 0) { + WOLFSSL_MSG("Issue freeing rng"); + } + XFREE(rsa->rng, NULL, DYNAMIC_TYPE_RNG); + #endif + +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) + if (rsa->meth) { + wolfSSL_RSA_meth_free(rsa->meth); + } +#endif + + InitwolfSSL_Rsa(rsa); /* set back to NULLs for safety */ + + XFREE(rsa, NULL, DYNAMIC_TYPE_RSA); + + /* rsa = NULL, don't try to access or double free it */ + } +} + +WOLFSSL_RSA* wolfSSL_RSA_new(void) +{ + WOLFSSL_RSA* external; + RsaKey* key; + + WOLFSSL_ENTER("wolfSSL_RSA_new"); + + key = (RsaKey*) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_RSA_new malloc RsaKey failure"); + return NULL; + } + + external = (WOLFSSL_RSA*) XMALLOC(sizeof(WOLFSSL_RSA), NULL, + DYNAMIC_TYPE_RSA); + if (external == NULL) { + WOLFSSL_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure"); + XFREE(key, NULL, DYNAMIC_TYPE_RSA); + return NULL; + } + + InitwolfSSL_Rsa(external); + if (wc_InitRsaKey(key, NULL) != 0) { + WOLFSSL_MSG("InitRsaKey WOLFSSL_RSA failure"); + XFREE(external, NULL, DYNAMIC_TYPE_RSA); + 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; + + 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; + } + + external->ownRng = 1; + if (rng == NULL && initGlobalRNG) { + external->ownRng = 0; + 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); + } +#else + XMEMSET(key, 0, sizeof(RsaKey)); +#endif /* WC_RSA_BLINDING */ + + external->internal = key; + external->inSet = 0; +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + external->refCount = 1; + wc_InitMutex(&external->refMutex); +#endif + return external; +} +#endif /* !NO_RSA && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */ + +#if defined(OPENSSL_ALL) && defined(HAVE_PKCS7) +PKCS7* wolfSSL_PKCS7_new(void) +{ + WOLFSSL_PKCS7* pkcs7; + int ret = 0; + + pkcs7 = (WOLFSSL_PKCS7*)XMALLOC(sizeof(*pkcs7), NULL, DYNAMIC_TYPE_PKCS7); + if (pkcs7 != NULL) { + XMEMSET(pkcs7, 0, sizeof(*pkcs7)); + ret = wc_PKCS7_Init(&pkcs7->pkcs7, NULL, INVALID_DEVID); + } + + if (ret != 0 && pkcs7 != NULL) + XFREE(pkcs7, NULL, DYNAMIC_TYPE_PKCS7); + + return (PKCS7*)pkcs7; +} +/****************************************************************************** +* wolfSSL_PKCS7_SIGNED_new - allocates PKCS7 and initialize it for a signed data +* +* RETURNS: +* returns pointer to the PKCS7 structure on success, otherwise returns NULL +*/ +PKCS7_SIGNED* wolfSSL_PKCS7_SIGNED_new(void) +{ + byte signedData[]= { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02}; + PKCS7* pkcs7 = NULL; + + if ((pkcs7 = wolfSSL_PKCS7_new()) == NULL) + return NULL; + pkcs7->contentOID = SIGNED_DATA; + if ((wc_PKCS7_SetContentType(pkcs7, signedData, sizeof(signedData))) < 0) { + if (pkcs7) { + wolfSSL_PKCS7_free(pkcs7); + return NULL; + } + } + return pkcs7; +} + +void wolfSSL_PKCS7_free(PKCS7* pkcs7) +{ + WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + + if (p7 != NULL) { + if (p7->data != NULL) + XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7); + wc_PKCS7_Free(&p7->pkcs7); + XFREE(p7, NULL, DYNAMIC_TYPE_PKCS7); + } +} +void wolfSSL_PKCS7_SIGNED_free(PKCS7_SIGNED* p7) +{ + wolfSSL_PKCS7_free(p7); + return; +} +PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len) +{ + WOLFSSL_PKCS7* pkcs7 = NULL; + word32 idx = 0; + + if (in == NULL) + return NULL; + + if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL) + return NULL; + + if (GetSequence(*in, &idx, &pkcs7->len, len) < 0) { + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + return NULL; + } + pkcs7->len += idx; + + pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7); + if (pkcs7->data == NULL) { + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + return NULL; + } + XMEMCPY(pkcs7->data, *in, pkcs7->len); + *in += pkcs7->len; + + if (p7 != NULL) + *p7 = (PKCS7*)pkcs7; + return (PKCS7*)pkcs7; +} + +PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7) +{ + WOLFSSL_PKCS7* pkcs7; + + if (bio == NULL) + return NULL; + + if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL) + return NULL; + + pkcs7->len = wolfSSL_BIO_pending(bio); + pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7); + if (pkcs7->data == NULL) { + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + return NULL; + } + + if (wolfSSL_BIO_read(bio, pkcs7->data, pkcs7->len) != pkcs7->len) { + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + return NULL; + } + + if (p7 != NULL) + *p7 = (PKCS7*)pkcs7; + return (PKCS7*)pkcs7; +} + +int wolfSSL_PKCS7_verify(PKCS7* pkcs7, WOLFSSL_STACK* certs, + WOLFSSL_X509_STORE* store, WOLFSSL_BIO* in, + WOLFSSL_BIO* out, int flags) +{ + int ret = 0; + unsigned char* mem = NULL; + int memSz = 0; + WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + + if (pkcs7 == NULL) + return WOLFSSL_FAILURE; + + if (in != NULL) { + if ((memSz = wolfSSL_BIO_get_mem_data(in, &mem)) < 0) + return WOLFSSL_FAILURE; + + p7->pkcs7.content = mem; + p7->pkcs7.contentSz = memSz; + } + + /* certs is the list of certificates to find the cert with issuer/serial. */ + (void)certs; + /* store is the certificate store to use to verify signer certificate + * associated with the signers. + */ + (void)store; + + ret = wc_PKCS7_VerifySignedData_ex(&p7->pkcs7, NULL, 0, p7->data, p7->len, + NULL, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + + if ((flags & PKCS7_NOVERIFY) != PKCS7_NOVERIFY) { + /* All signer certificates are verified. */ + return WOLFSSL_FAILURE; + } + + if (out != NULL) + wolfSSL_BIO_write(out, p7->pkcs7.content, p7->pkcs7.contentSz); + + return WOLFSSL_SUCCESS; +} + +WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* pkcs7, WOLFSSL_STACK* certs, + int flags) +{ + WOLFSSL_STACK* signers = NULL; + WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + + if (p7 == NULL) + return NULL; + /* Only PKCS#7 messages with a single cert that is the verifying certificate + * is supported. + */ + if ((flags | PKCS7_NOINTERN) == PKCS7_NOINTERN) + return NULL; + + signers = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_X509); + if (signers == NULL) + return NULL; + + signers->num = 1; + signers->data.x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, + DYNAMIC_TYPE_X509); + if (signers->data.x509 == NULL) { + XFREE(signers, NULL, DYNAMIC_TYPE_X509); + return NULL; + } + + if (DecodeToX509(signers->data.x509, p7->pkcs7.singleCert, + p7->pkcs7.singleCertSz) != 0) { + XFREE(signers->data.x509, NULL, DYNAMIC_TYPE_X509); + XFREE(signers, NULL, DYNAMIC_TYPE_X509); + return NULL; + } + + (void)certs; + + return signers; +} + +/****************************************************************************** +* wolfSSL_PEM_write_bio_PKCS7 - writes the PKCS7 data to BIO +* +* RETURNS: +* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE +*/ + +int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7) +{ +#ifdef WOLFSSL_SMALL_STACK + byte* outputHead; + byte* outputFoot; +#else + byte outputHead[2048]; + byte outputFoot[2048]; +#endif + word32 outputHeadSz = 2048; + word32 outputFootSz = 2048; + word32 outputSz = 0; + byte* output = NULL; + byte* pem = NULL; + int pemSz = -1; + enum wc_HashType hashType; + byte hashBuf[WC_MAX_DIGEST_SIZE]; + word32 hashSz = -1; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PKCS7()"); + + if (bio == NULL || p7 == NULL) + return WOLFSSL_FAILURE; + +#ifdef WOLFSSL_SMALL_STACK + outputHead = (byte*)XMALLOC(outputHeadSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (outputHead == NULL) + return MEMORY_E; + + outputFoot = (byte*)XMALLOC(outputFootSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (outputFoot == NULL) + goto error; + +#endif + + XMEMSET(hashBuf, 0, WC_MAX_DIGEST_SIZE); + XMEMSET(outputHead, 0, outputHeadSz); + XMEMSET(outputFoot, 0, outputFootSz); + + hashType = wc_OidGetHash(p7->hashOID); + hashSz = wc_HashGetDigestSize(hashType); + if (hashSz > WC_MAX_DIGEST_SIZE) + return WOLFSSL_FAILURE; + + /* only SIGNED_DATA is supported */ + switch (p7->contentOID) { + case SIGNED_DATA: + break; + default: + WOLFSSL_MSG("Unknown PKCS#7 Type"); + return WOLFSSL_FAILURE; + }; + + if ((wc_PKCS7_EncodeSignedData_ex(p7, hashBuf, hashSz, + outputHead, &outputHeadSz, outputFoot, &outputFootSz)) != 0) + return WOLFSSL_FAILURE; + + outputSz = outputHeadSz + p7->contentSz + outputFootSz; + output = (byte*)XMALLOC(outputSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + + if (!output) + return WOLFSSL_FAILURE; + + XMEMSET(output, 0, outputSz); + outputSz = 0; + XMEMCPY(&output[outputSz], outputHead, outputHeadSz); + outputSz += outputHeadSz; + XMEMCPY(&output[outputSz], p7->content, p7->contentSz); + outputSz += p7->contentSz; + XMEMCPY(&output[outputSz], outputFoot, outputFootSz); + outputSz += outputFootSz; + + /* get PEM size */ + pemSz = wc_DerToPemEx(output, outputSz, NULL, 0, NULL, CERT_TYPE); + if (pemSz < 0) + goto error; + + pemSz++; /* for '\0'*/ + + /* create PEM buffer and convert from DER to PEM*/ + if ((pem = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER)) == NULL) + goto error; + + XMEMSET(pem, 0, pemSz); + + if (wc_DerToPemEx(output, outputSz, pem, pemSz, NULL, CERT_TYPE) < 0) { + goto error; + } + if ((wolfSSL_BIO_write(bio, pem, pemSz) == pemSz)) { + XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return WOLFSSL_SUCCESS; + } + +error: +#ifdef WOLFSSL_SMALL_STACK + if (outputHead) { + XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (outputFoot) { + XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + if (output) { + XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (pem) { + XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + return WOLFSSL_FAILURE; +} +#endif /* OPENSSL_ALL && HAVE_PKCS7 */ + +#if defined(OPENSSL_EXTRA) +WOLFSSL_STACK* wolfSSL_sk_X509_new(void) +{ + WOLFSSL_STACK* s = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_X509); + if (s != NULL) { + XMEMSET(s, 0, sizeof(*s)); + s->type = STACK_TYPE_X509; + } + + return s; +} +#endif + +#ifdef OPENSSL_ALL +int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY* pkey, + const WOLFSSL_EVP_CIPHER* enc, + char* passwd, int passwdSz, + pem_password_cb* cb, void* ctx) +{ + int ret = 0; + char password[NAME_SZ]; + byte* key = NULL; + word32 keySz; + byte* pem = NULL; + int pemSz; + int type = PKCS8_PRIVATEKEY_TYPE; + int algId; + const byte* curveOid; + word32 oidSz; + int encAlgId; + + if (bio == NULL || pkey == NULL) + return -1; + + keySz = pkey->pkey_sz + 128; + key = (byte*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) + ret = MEMORY_E; + + if (ret == 0 && enc != NULL && passwd == NULL) { + passwdSz = cb(password, sizeof(password), 1, ctx); + if (passwdSz < 0) + ret = WOLFSSL_FAILURE; + passwd = password; + } + + if (ret == 0 && enc != NULL) { + WC_RNG rng; + ret = wc_InitRng(&rng); + if (ret == 0) { + #ifndef NO_DES3 + if (enc == EVP_DES_CBC) + encAlgId = DESb; + else if (enc == EVP_DES_EDE3_CBC) + encAlgId = DES3b; + else + #endif + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_256 + if (enc == EVP_AES_256_CBC) + encAlgId = AES256CBCb; + else + #endif + #endif + ret = -1; + if (ret == 0) { + ret = TraditionalEnc((byte*)pkey->pkey.ptr, pkey->pkey_sz, key, + &keySz, passwd, passwdSz, PKCS5, PBES2, + encAlgId, NULL, 0, WC_PKCS12_ITT_DEFAULT, + &rng, NULL); + if (ret > 0) { + keySz = ret; + ret = 0; + } + } + wc_FreeRng(&rng); + } + type = PKCS8_ENC_PRIVATEKEY_TYPE; + } + if (ret == 0 && enc == NULL) { + type = PKCS8_PRIVATEKEY_TYPE; + if (pkey->type == EVP_PKEY_EC) { + algId = ECDSAk; + ret = wc_ecc_get_oid(pkey->ecc->group->curve_oid, &curveOid, + &oidSz); + } + else { + algId = RSAk; + curveOid = NULL; + oidSz = 0; + } + + if (ret >= 0) { + ret = wc_CreatePKCS8Key(key, &keySz, (byte*)pkey->pkey.ptr, + pkey->pkey_sz, algId, curveOid, oidSz); + keySz = ret; + } + } + + if (password == passwd) + XMEMSET(password, 0, passwdSz); + + if (ret >= 0) { + pemSz = 2 * keySz + 2 * 64; + pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) + ret = MEMORY_E; + } + + if (ret >= 0) + ret = wc_DerToPemEx(key, keySz, pem, pemSz, NULL, type); + + if (key != NULL) + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret >= 0) { + if (wolfSSL_BIO_write(bio, pem, ret) != ret) + ret = -1; + } + + if (pem != NULL) + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return ret < 0 ? 0 : ret; + +} + +static int bio_get_data(WOLFSSL_BIO* bio, byte** data) +{ + int ret = 0; + byte* mem = NULL; +#ifndef NO_FILESYSTEM + long memSz; + XFILE file; + long curr; +#endif + + if ((ret = wolfSSL_BIO_pending(bio)) > 0) { + } +#ifndef NO_FILESYSTEM + else if (bio->type == WOLFSSL_BIO_FILE) { + if (wolfSSL_BIO_get_fp(bio, &file) != WOLFSSL_SUCCESS) + ret = BAD_FUNC_ARG; + if (ret == 0) { + curr = XFTELL(file); + if (curr < 0) { + ret = WOLFSSL_BAD_FILE; + } + if (XFSEEK(file, 0, XSEEK_END) != 0) + ret = WOLFSSL_BAD_FILE; + } + if (ret == 0) { + memSz = XFTELL(file); + if (memSz > MAX_WOLFSSL_FILE_SIZE || memSz < 0) { + ret = WOLFSSL_BAD_FILE; + } + } + if (ret == 0) { + memSz -= curr; + ret = (int)memSz; + if (XFSEEK(file, curr, SEEK_SET) != 0) + ret = WOLFSSL_BAD_FILE; + } + } +#endif + + if (ret > 0) { + mem = (byte*)XMALLOC(ret, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (mem == NULL) { + WOLFSSL_MSG("Memory error"); + ret = MEMORY_E; + } + if (ret >= 0) { + if ((ret = wolfSSL_BIO_read(bio, mem, ret)) <= 0) { + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + ret = MEMORY_E; + mem = NULL; + } + } + } + + *data = mem; + + return ret; +} + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_BIO_set_init(WOLFSSL_BIO* bio, int init) +{ + WOLFSSL_STUB("wolfSSL_BIO_set_init"); + (void)bio; + (void)init; +} + +void wolfSSL_BIO_set_shutdown(WOLFSSL_BIO* bio, int shut) +{ + WOLFSSL_STUB("wolfSSL_BIO_set_shutdown"); + (void)bio; + (void)shut; + +} +int wolfSSL_BIO_get_shutdown(WOLFSSL_BIO* bio) +{ + WOLFSSL_STUB("wolfSSL_BIO_get_shutdown"); + (void)bio; + return 0; +} +#endif /* NO_WOLFSSL_STUB */ + +void wolfSSL_BIO_clear_retry_flags(WOLFSSL_BIO* bio) +{ + WOLFSSL_ENTER("wolfSSL_BIO_clear_retry_flags"); + + if (bio) + bio->flags &= ~(WOLFSSL_BIO_FLAG_READ|WOLFSSL_BIO_FLAG_RETRY); +} + +int wolfSSL_BIO_should_retry(WOLFSSL_BIO *bio) +{ + int ret = 0; + if (bio != NULL) { + ret = (int)(bio->flags & WOLFSSL_BIO_FLAG_RETRY); + } + + return ret; +} + +/* DER data is PKCS#8 encrypted. */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** pkey, + pem_password_cb* cb, + void* ctx) +{ + int ret; + byte* der; + int len; + byte* p; + char password[NAME_SZ]; + int passwordSz; + word32 algId; + WOLFSSL_EVP_PKEY* key; + + if ((len = bio_get_data(bio, &der)) < 0) + return NULL; + + if (cb != NULL) { + passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx); + if (passwordSz < 0) { + XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + ret = ToTraditionalEnc(der, len, password, passwordSz, &algId); + if (ret < 0) { + XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + XMEMSET(password, 0, passwordSz); + } + + p = der; + key = wolfSSL_d2i_PrivateKey_EVP(pkey, &p, len); + XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); + return key; +} + +/* Detect which type of key it is before decoding. */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(WOLFSSL_EVP_PKEY** pkey, + const unsigned char** pp, + long length) +{ + int ret; + WOLFSSL_EVP_PKEY* key = NULL; + const byte* der = *pp; + word32 idx = 0; + int len = 0; + word32 end = 0; + int cnt = 0; + int type; + word32 algId; + word32 keyLen = (word32)length; + + /* Take off PKCS#8 wrapper if found. */ + if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) { + der += idx; + keyLen = len; + } + idx = 0; + len = 0; + + /* Use the number of elements in the outer sequence to determine key type. + */ + ret = GetSequence(der, &idx, &len, keyLen); + if (ret >= 0) { + end = idx + len; + while (ret >= 0 && idx < end) { + /* Skip type */ + idx++; + /* Get length and skip over - keeping count */ + len = 0; + ret = GetLength(der, &idx, &len, keyLen); + if (ret >= 0) { + if (idx + len > end) + ret = ASN_PARSE_E; + else { + idx += len; + cnt++; + } + } + } + } + + if (ret >= 0) { + /* ECC includes version, private[, curve][, public key] */ + if (cnt >= 2 && cnt <= 4) + type = EVP_PKEY_EC; + else + type = EVP_PKEY_RSA; + + key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen); + *pp = der; + } + + return key; +} +#endif + +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) +int wolfSSL_X509_set_subject_name(WOLFSSL_X509 *cert, WOLFSSL_X509_NAME *name) +{ + int i; + WOLFSSL_X509_NAME_ENTRY* ne; + + WOLFSSL_ENTER("X509_set_subject_name"); + if (cert == NULL || name == NULL) + return WOLFSSL_FAILURE; + + FreeX509Name(&cert->subject, cert->heap); + InitX509Name(&cert->subject, 0); + if (name->dynamicName) { + cert->subject.name = (char*)XMALLOC(name->sz, cert->heap, + DYNAMIC_TYPE_SUBJECT_CN); + if (cert->subject.name == NULL) + return WOLFSSL_FAILURE; + } + XMEMCPY(cert->subject.name, name->name, name->sz); + cert->subject.sz = name->sz; + + for (i = 0; i < 10; i++) { + ne = wolfSSL_X509_NAME_get_entry(name, i); + if (ne != NULL) + wolfSSL_X509_NAME_add_entry(&cert->subject, ne, i, 1); + } + cert->subject.x509 = cert; + cert->subject.name = cert->subject.fullName.fullName; + cert->subject.sz = cert->subject.fullName.fullNameLen; + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_X509_set_issuer_name(WOLFSSL_X509 *cert, WOLFSSL_X509_NAME *name) +{ + int i; + WOLFSSL_X509_NAME_ENTRY* ne; + + WOLFSSL_ENTER("X509_set_issuer_name"); + if (cert == NULL || name == NULL) + return WOLFSSL_FAILURE; + + FreeX509Name(&cert->issuer, cert->heap); + InitX509Name(&cert->issuer, 0); + if (name->dynamicName) { + cert->issuer.name = (char*)XMALLOC(name->sz, cert->heap, + DYNAMIC_TYPE_SUBJECT_CN); + if (cert->issuer.name == NULL) + return WOLFSSL_FAILURE; + } + XMEMCPY(cert->issuer.name, name->name, name->sz); + cert->issuer.sz = name->sz; + + for (i = 0; i < 10; i++) { + ne = wolfSSL_X509_NAME_get_entry(name, i); + if (ne != NULL) + wolfSSL_X509_NAME_add_entry(&cert->issuer, ne, i, 1); + } + cert->issuer.x509 = cert; + cert->issuer.name = cert->issuer.fullName.fullName; + cert->issuer.sz = cert->issuer.fullName.fullNameLen; + cert->issuerSet = 1; + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_X509_set_notAfter(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t) +{ + if (x509 == NULL || t == NULL) { + return WOLFSSL_FAILURE; + } + + XMEMCPY(&x509->notAfter, t, sizeof(WOLFSSL_ASN1_TIME)); + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_X509_set_notBefore(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t) +{ + if (x509 == NULL || t == NULL) { + return WOLFSSL_FAILURE; + } + + XMEMCPY(&x509->notBefore, t, sizeof(WOLFSSL_ASN1_TIME)); + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_X509_set_serialNumber(WOLFSSL_X509* x509, WOLFSSL_ASN1_INTEGER* s) +{ + WOLFSSL_ENTER("wolfSSL_X509_set_serialNumber"); + if (!x509 || !s || s->dataMax >= EXTERNAL_SERIAL_SIZE) + return WOLFSSL_FAILURE; + + if (s->isDynamic) + XSTRNCPY((char*)x509->serial,(char*)s->data,s->dataMax); + else + XSTRNCPY((char*)x509->serial,(char*)s->intData,s->dataMax); + + x509->serial[s->dataMax] = 0; + x509->serialSz = s->dataMax; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey) +{ + byte* p; + WOLFSSL_ENTER("wolfSSL_X509_set_pubkey"); + + if (cert == NULL || pkey == NULL) + return WOLFSSL_FAILURE; + + if (pkey->type == EVP_PKEY_RSA) + cert->pubKeyOID = RSAk; + else if (pkey->type == EVP_PKEY_EC) + cert->pubKeyOID = ECDSAk; + else + return WOLFSSL_FAILURE; + + p = (byte*)XMALLOC(pkey->pkey_sz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (p == NULL) + return WOLFSSL_FAILURE; + + if (cert->pubKey.buffer != NULL) + XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + cert->pubKey.buffer = p; + XMEMCPY(cert->pubKey.buffer, pkey->pkey.ptr, pkey->pkey_sz); + cert->pubKey.length = pkey->pkey_sz; + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_X509_set_version(WOLFSSL_X509* x509, long v) +{ + WOLFSSL_ENTER("wolfSSL_X509_set_version"); + if ((x509 == NULL) || (v < 0) || (v > INT_MAX)) { + return WOLFSSL_FAILURE; + } + x509->version = (int) v + 1; + + return WOLFSSL_SUCCESS; +} + +#endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_CERT_GEN && WOLFSSL_CERT_REQ */ + +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) + +void wolfSSL_X509V3_set_ctx(WOLFSSL_X509V3_CTX* ctx, WOLFSSL_X509* issuer, + WOLFSSL_X509* subject, WOLFSSL_X509* req, WOLFSSL_X509_CRL* crl, + int flag) +{ + int ret = WOLFSSL_SUCCESS; + WOLFSSL_ENTER("wolfSSL_X509V3_set_ctx"); + if (!ctx || !ctx->x509) + return; + + /* Set parameters in ctx as long as ret == WOLFSSL_SUCCESS */ + if (issuer) + ret = wolfSSL_X509_set_issuer_name(ctx->x509,&issuer->issuer); + + if (subject && ret == WOLFSSL_SUCCESS) + ret = wolfSSL_X509_set_subject_name(ctx->x509,&subject->subject); + + if (req && ret == WOLFSSL_SUCCESS) { + WOLFSSL_MSG("req not implemented."); + } + + if (crl && ret == WOLFSSL_SUCCESS) { + WOLFSSL_MSG("crl not implemented."); + } + + if (flag && ret == WOLFSSL_SUCCESS) { + WOLFSSL_MSG("flag not implemented."); + } + + if (!ret) { + WOLFSSL_MSG("Error setting WOLFSSL_X509V3_CTX parameters."); + } +} + +int wolfSSL_i2d_X509_REQ(WOLFSSL_X509* req, unsigned char** out) +{ + const unsigned char* der; + int derSz = 0; + WOLFSSL_ENTER("wolfSSL_i2d_X509_REQ"); + + if (req == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + der = wolfSSL_X509_get_der(req, &derSz); + if (der == NULL) { + return MEMORY_E; + } + + if (*out == NULL) { + *out = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL); + if (*out == NULL) { + return MEMORY_E; + } + } + + XMEMCPY(*out, der, derSz); + + return derSz; +} + +WOLFSSL_X509* wolfSSL_X509_REQ_new(void) +{ + return wolfSSL_X509_new(); +} + +void wolfSSL_X509_REQ_free(WOLFSSL_X509* req) +{ + wolfSSL_X509_free(req); +} + +int wolfSSL_X509_REQ_sign(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey, + const WOLFSSL_EVP_MD *md) +{ + byte der[2048]; + int derSz = sizeof(der); + + if (req == NULL || pkey == NULL || md == NULL) + return WOLFSSL_FAILURE; + + /* Create a Cert that has the certificate request fields. */ + req->sigOID = wolfSSL_sigTypeFromPKEY((WOLFSSL_EVP_MD*)md, pkey); + if (wolfSSL_X509_make_der(req, 1, der, &derSz) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + if (wolfSSL_X509_resign_cert(req, 1, der, sizeof(der), derSz, + (WOLFSSL_EVP_MD*)md, pkey) <= 0) { + return WOLFSSL_FAILURE; + } + return WOLFSSL_SUCCESS; +} + + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_X509_REQ_add_extensions(WOLFSSL_X509* req, + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* ext) +{ + (void)req; + (void)ext; + return WOLFSSL_FATAL_ERROR; +} +#endif + +int wolfSSL_X509_REQ_set_subject_name(WOLFSSL_X509 *req, + WOLFSSL_X509_NAME *name) +{ + return wolfSSL_X509_set_subject_name(req, name); +} + +int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey) +{ + return wolfSSL_X509_set_pubkey(req, pkey); +} +#endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_CERT_GEN && WOLFSSL_CERT_REQ */ + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/tls.c b/FreeRTOS-Plus/Source/WolfSSL/src/tls.c index f4c76d738..1b9858a75 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/src/tls.c +++ b/FreeRTOS-Plus/Source/WolfSSL/src/tls.c @@ -1,8 +1,8 @@ /* tls.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,16 +16,19 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include +#ifndef WOLFCRYPT_ONLY + #include #include #include @@ -33,348 +36,207 @@ #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif +#ifdef HAVE_CURVE25519 + #include +#endif +#ifdef HAVE_CURVE448 + #include +#endif +#ifdef HAVE_NTRU + #include "libntruencrypt/ntru_crypto.h" + #include +#endif + +#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 */ + +#if (!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)) +static int TLSX_KeyShare_IsSupported(int namedGroup); +#endif + +#if ((!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) || \ + (defined(WOLFSSL_TLS13) && !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) \ + && !defined(HAVE_CURVE448) && defined(HAVE_SUPPORTED_CURVES)) || \ + ((defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES))) && \ + defined(HAVE_TLS_EXTENSIONS) +static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions); +#endif #ifndef NO_TLS +/* Digest enable checks */ +#ifdef NO_OLD_TLS /* TLS 1.2 only */ + #if defined(NO_SHA256) && !defined(WOLFSSL_SHA384) && \ + !defined(WOLFSSL_SHA512) + #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2 + #endif +#else /* TLS 1.1 or older */ + #if defined(NO_MD5) && defined(NO_SHA) + #error Must have SHA1 and MD5 enabled for old TLS + #endif +#endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN +#ifdef WOLFSSL_TLS13 + #if !defined(NO_DH) && \ + !defined(HAVE_FFDHE_2048) && !defined(HAVE_FFDHE_3072) && \ + !defined(HAVE_FFDHE_4096) && !defined(HAVE_FFDHE_6144) && \ + !defined(HAVE_FFDHE_8192) + #error Please configure your TLS 1.3 DH key size using either: HAVE_FFDHE_2048, HAVE_FFDHE_3072, HAVE_FFDHE_4096, HAVE_FFDHE_6144 or HAVE_FFDHE_8192 + #endif + #if !defined(NO_RSA) && !defined(WC_RSA_PSS) + #error The build option WC_RSA_PSS is required for TLS 1.3 with RSA + #endif + #ifndef HAVE_TLS_EXTENSIONS + #ifndef _MSC_VER + #error "The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3" + #else + #pragma message("Error: The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3") + #endif + #endif +#endif - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } +/* Warn if secrets logging is enabled */ +#if defined(SHOW_SECRETS) || defined(WOLFSSL_SSLKEYLOGFILE) + #ifndef _MSC_VER + #warning The SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE options should only be used for debugging and never in a production environment + #else + #pragma message("Warning: The SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE options should only be used for debugging and never in a production environment") + #endif +#endif -#endif /* WOLFSSL_HAVE_MIN */ +/* Optional Pre-Master-Secret logging for Wireshark */ +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE) +#ifndef WOLFSSL_SSLKEYLOGFILE_OUTPUT + #define WOLFSSL_SSLKEYLOGFILE_OUTPUT "sslkeylog.log" +#endif +#endif +#ifndef WOLFSSL_NO_TLS12 #ifdef WOLFSSL_SHA384 - #define P_HASH_MAX_SIZE SHA384_DIGEST_SIZE -#else - #define P_HASH_MAX_SIZE 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 len = P_HASH_MAX_SIZE; - word32 times; - word32 lastLen; - word32 lastTime; - word32 i; - word32 idx = 0; - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - byte* previous; - byte* current; - Hmac* hmac; -#else - byte previous[P_HASH_MAX_SIZE]; /* max size */ - byte current[P_HASH_MAX_SIZE]; /* max size */ - Hmac hmac[1]; -#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); - - 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); - - return MEMORY_E; - } -#endif - - switch (hash) { - #ifndef NO_MD5 - case md5_mac: - hash = MD5; - len = MD5_DIGEST_SIZE; - break; - #endif - - #ifndef NO_SHA256 - case sha256_mac: - hash = SHA256; - len = SHA256_DIGEST_SIZE; - break; - #endif - - #ifdef WOLFSSL_SHA384 - case sha384_mac: - hash = SHA384; - len = SHA384_DIGEST_SIZE; - break; - #endif - - #ifndef NO_SHA - case sha_mac: - default: - hash = SHA; - len = SHA_DIGEST_SIZE; - break; - #endif - } - - times = resLen / len; - lastLen = resLen % len; - - if (lastLen) - times += 1; - - 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_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_HmacFinal(hmac, previous); - if (ret != 0) - break; - } - } - } - } - } - - ForceZero(previous, P_HASH_MAX_SIZE); - ForceZero(current, P_HASH_MAX_SIZE); - 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); -#endif - - return ret; -} - -#undef P_HASH_MAX_SIZE - - -#ifndef NO_OLD_TLS - -/* calculate XOR for TLSv1 PRF */ -static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha) -{ - word32 i; - - for (i = 0; i < digLen; i++) - digest[i] = md5[i] ^ sha[i]; -} - - -/* 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) -{ - int ret = 0; - word32 half = (secLen + 1) / 2; - -#ifdef WOLFSSL_SMALL_STACK - byte* md5_half; - byte* sha_half; - byte* labelSeed; - byte* md5_result; - byte* sha_result; -#else - byte md5_half[MAX_PRF_HALF]; /* half is real size */ - byte sha_half[MAX_PRF_HALF]; /* half is real size */ - byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */ - byte md5_result[MAX_PRF_DIG]; /* digLen is real size */ - byte sha_result[MAX_PRF_DIG]; /* digLen is real size */ -#endif - - if (half > MAX_PRF_HALF) - return BUFFER_E; - if (labLen + seedLen > MAX_PRF_LABSEED) - return BUFFER_E; - if (digLen > MAX_PRF_DIG) - 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); - - 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); - - return MEMORY_E; - } -#endif - - XMEMSET(md5_result, 0, digLen); - XMEMSET(sha_result, 0, digLen); - - XMEMCPY(md5_half, secret, half); - XMEMCPY(sha_half, secret + half - secLen % 2, half); - - XMEMCPY(labelSeed, label, labLen); - XMEMCPY(labelSeed + labLen, seed, seedLen); - - if ((ret = p_hash(md5_result, digLen, md5_half, half, labelSeed, - labLen + seedLen, md5_mac)) == 0) { - if ((ret = p_hash(sha_result, digLen, sha_half, half, labelSeed, - labLen + seedLen, sha_mac)) == 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); -#endif - - return ret; -} - -#endif - - -/* Wrapper to call straight thru to p_hash in TSL 1.2 cases to remove stack - 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 ret = 0; - - if (useAtLeastSha256) { -#ifdef WOLFSSL_SMALL_STACK - byte* labelSeed; -#else - byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */ -#endif - - if (labLen + seedLen > MAX_PRF_LABSEED) - return BUFFER_E; - -#ifdef WOLFSSL_SMALL_STACK - labelSeed = (byte*)XMALLOC(MAX_PRF_LABSEED, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (labelSeed == NULL) - return MEMORY_E; -#endif - - XMEMCPY(labelSeed, label, labLen); - XMEMCPY(labelSeed + labLen, seed, seedLen); - - /* If a cipher suite wants an algorithm better than sha256, it - * should use better. */ - if (hash_type < sha256_mac) - hash_type = sha256_mac; - ret = p_hash(digest, digLen, secret, secLen, labelSeed, - labLen + seedLen, hash_type); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(labelSeed, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - } -#ifndef NO_OLD_TLS - else { - ret = doPRF(digest, digLen, secret, secLen, label, labLen, seed, - seedLen); - } -#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 +#ifdef WOLFSSL_RENESAS_TSIP_TLS + int tsip_useable(const WOLFSSL *ssl); + int tsip_generateMasterSecret(const byte *pre, + const byte *cr,const byte *sr, + byte *ms/* out */); + int tsip_generateSeesionKey(WOLFSSL *ssl); + int tsip_generateVerifyData(const byte *ms, const byte *side, + const byte *handshake_hash, + byte *hashes /* out */); +#endif -int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen) { - const byte* side; - byte handshake_hash[HSHASH_SZ]; - word32 hashSz = FINISHED_SZ; + int ret = 0; + word32 hashSz = FINISHED_SZ; + if (ssl == NULL || hash == NULL || hashLen == NULL || *hashLen < HSHASH_SZ) + return BAD_FUNC_ARG; + + /* for constant timing perform these even if error */ #ifndef NO_OLD_TLS - wc_Md5GetHash(&ssl->hsHashes->hashMd5, handshake_hash); - wc_ShaGetHash(&ssl->hsHashes->hashSha, &handshake_hash[MD5_DIGEST_SIZE]); + ret |= wc_Md5GetHash(&ssl->hsHashes->hashMd5, hash); + ret |= wc_ShaGetHash(&ssl->hsHashes->hashSha, &hash[WC_MD5_DIGEST_SIZE]); #endif if (IsAtLeastTLSv1_2(ssl)) { #ifndef NO_SHA256 - if (ssl->specs.mac_algorithm <= sha256_mac) { - int ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256,handshake_hash); - - if (ret != 0) - return ret; - - hashSz = SHA256_DIGEST_SIZE; + if (ssl->specs.mac_algorithm <= sha256_mac || + ssl->specs.mac_algorithm == blake2b_mac) { + ret |= wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + hashSz = WC_SHA256_DIGEST_SIZE; } #endif #ifdef WOLFSSL_SHA384 if (ssl->specs.mac_algorithm == sha384_mac) { - int ret = wc_Sha384Final(&ssl->hsHashes->hashSha384,handshake_hash); - - if (ret != 0) - return ret; - - hashSz = SHA384_DIGEST_SIZE; + ret |= wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + hashSz = WC_SHA384_DIGEST_SIZE; } #endif } - if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) - side = tls_client; - else - side = tls_server; + *hashLen = hashSz; - 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); + if (ret != 0) + ret = BUILD_MSG_ERROR; + + return ret; } +int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +{ + int ret; + const byte* side; + word32 hashSz = HSHASH_SZ; +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + DECLARE_VAR(handshake_hash, byte, HSHASH_SZ, ssl->heap); + if (handshake_hash == NULL) + return MEMORY_E; +#else + byte handshake_hash[HSHASH_SZ]; +#endif + + ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); + if (ret == 0) { + if (XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) + side = tls_client; + else + side = tls_server; + +#ifdef WOLFSSL_HAVE_PRF +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + if (tsip_useable(ssl)) { + ret = tsip_generateVerifyData(ssl->arrays->tsip_masterSecret, + side, handshake_hash, (byte*)hashes /* out */); + } else +#endif + ret = wc_PRF_TLS((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); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)side; + (void)hashes; +#endif + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(handshake_hash, ssl->heap); +#endif + + return ret; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + #ifndef NO_OLD_TLS +#ifdef WOLFSSL_ALLOW_TLSV10 ProtocolVersion MakeTLSv1(void) { ProtocolVersion pv; @@ -383,6 +245,7 @@ ProtocolVersion MakeTLSv1(void) return pv; } +#endif /* WOLFSSL_ALLOW_TLSV10 */ ProtocolVersion MakeTLSv1_1(void) @@ -394,9 +257,11 @@ ProtocolVersion MakeTLSv1_1(void) return pv; } -#endif +#endif /* !NO_OLD_TLS */ +#ifndef WOLFSSL_NO_TLS12 + ProtocolVersion MakeTLSv1_2(void) { ProtocolVersion pv; @@ -406,60 +271,176 @@ ProtocolVersion MakeTLSv1_2(void) return pv; } +#endif /* !WOLFSSL_NO_TLS12 */ +#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 + +#ifndef WOLFSSL_NO_TLS12 + +#ifdef HAVE_EXTENDED_MASTER +static const byte ext_master_label[EXT_MASTER_LABEL_SZ + 1] = + "extended master secret"; +#endif 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]; + int ret; +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + DECLARE_VAR(seed, byte, SEED_LEN, heap); + if (seed == NULL) + return MEMORY_E; +#else + byte seed[SEED_LEN]; +#endif 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); +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS(key_dig, key_dig_len, ms, msLen, key_label, KEY_LABEL_SZ, + seed, SEED_LEN, tls1_2, hash_type, heap, devId); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)key_dig; + (void)key_dig_len; + (void)ms; + (void)msLen; + (void)tls1_2; + (void)hash_type; + (void)heap; + (void)devId; + (void)key_label; + (void)master_label; +#ifdef HAVE_EXTENDED_MASTER + (void)ext_master_label; +#endif +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(seed, heap); +#endif + + return ret; +} + +/* 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); +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + if (tsip_useable(ssl)) + ret = tsip_generateSeesionKey(ssl); + else { +#endif + 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); +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + } +#endif #ifdef WOLFSSL_SMALL_STACK - XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST); #endif return ret; } +static int _MakeTlsMasterSecret(byte* ms, word32 msLen, + const byte* pms, word32 pmsLen, + const byte* cr, const byte* sr, + int tls1_2, int hash_type, + void* heap, int devId) +{ + int ret; +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + DECLARE_VAR(seed, byte, SEED_LEN, heap); + if (seed == NULL) + return MEMORY_E; +#else + byte seed[SEED_LEN]; +#endif + + XMEMCPY(seed, cr, RAN_LEN); + XMEMCPY(seed + RAN_LEN, sr, RAN_LEN); + +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, master_label, MASTER_LABEL_SZ, + seed, SEED_LEN, tls1_2, hash_type, heap, devId); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)ms; + (void)msLen; + (void)pms; + (void)pmsLen; + (void)tls1_2; + (void)hash_type; + (void)heap; + (void)devId; +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(seed, heap); +#endif + + return ret; +} /* External facing wrapper so user can call as well, 0 on success */ int wolfSSL_MakeTlsMasterSecret(byte* ms, word32 msLen, @@ -467,34 +448,145 @@ int wolfSSL_MakeTlsMasterSecret(byte* ms, word32 msLen, const byte* cr, const byte* sr, int tls1_2, int hash_type) { - byte seed[SEED_LEN]; - - XMEMCPY(seed, cr, RAN_LEN); - 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); + 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) +{ + int ret; + +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ, + sHash, sHashLen, tls1_2, hash_type, heap, devId); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)ms; + (void)msLen; + (void)pms; + (void)pmsLen; + (void)sHash; + (void)sHashLen; + (void)tls1_2; + (void)hash_type; + (void)heap; + (void)devId; +#endif + return ret; +} + +/* 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 _MakeTlsExtendedMasterSecret(ms, msLen, pms, pmsLen, sHash, sHashLen, + tls1_2, hash_type, NULL, INVALID_DEVID); +} + +#endif /* HAVE_EXTENDED_MASTER */ + + int MakeTlsMasterSecret(WOLFSSL* ssl) { - int ret; + int ret; - ret = wolfSSL_MakeTlsMasterSecret(ssl->arrays->masterSecret, SECRET_LEN, +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS) { + word32 hashSz = HSHASH_SZ; + #ifdef WOLFSSL_SMALL_STACK + byte* handshake_hash = (byte*)XMALLOC(HSHASH_SZ, ssl->heap, + DYNAMIC_TYPE_DIGEST); + if (handshake_hash == NULL) + return MEMORY_E; + #else + byte handshake_hash[HSHASH_SZ]; + #endif + + ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); + if (ret == 0) { + ret = _MakeTlsExtendedMasterSecret( + ssl->arrays->masterSecret, SECRET_LEN, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + handshake_hash, hashSz, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, ssl->devId); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST); + #endif + } + else +#endif /* HAVE_EXTENDED_MASTER */ + { +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + if (tsip_useable(ssl)) { + ret = tsip_generateMasterSecret( + &ssl->arrays->preMasterSecret[VERSION_SZ], + ssl->arrays->clientRandom, + ssl->arrays->serverRandom, + ssl->arrays->tsip_masterSecret); + } else +#endif + 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 - int i; + /* Wireshark Pre-Master-Secret Format: + * CLIENT_RANDOM + */ + const char* CLIENT_RANDOM_LABEL = "CLIENT_RANDOM"; + int i, pmsPos = 0; + char pmsBuf[13 + 1 + 64 + 1 + 96 + 1 + 1]; - printf("master secret: "); - for (i = 0; i < SECRET_LEN; i++) - printf("%02x", ssl->arrays->masterSecret[i]); - printf("\n"); - #endif + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%s ", + CLIENT_RANDOM_LABEL); + pmsPos += XSTRLEN(CLIENT_RANDOM_LABEL) + 1; + for (i = 0; i < RAN_LEN; i++) { + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x", + ssl->arrays->clientRandom[i]); + pmsPos += 2; + } + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, " "); + pmsPos += 1; + for (i = 0; i < SECRET_LEN; i++) { + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x", + ssl->arrays->masterSecret[i]); + pmsPos += 2; + } + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "\n"); + pmsPos += 1; + + /* print master secret */ + puts(pmsBuf); + + #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE) + { + FILE* f = XFOPEN(WOLFSSL_SSLKEYLOGFILE_OUTPUT, "a"); + if (f != XBADFILE) { + XFWRITE(pmsBuf, 1, pmsPos, f); + XFCLOSE(f); + } + } + #endif + #endif /* SHOW_SECRETS */ ret = DeriveTlsKeys(ssl); } @@ -516,7 +608,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 @@ -528,83 +620,91 @@ int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* msk, unsigned int len, XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); - ret = PRF((byte*)msk, len, ssl->arrays->masterSecret, SECRET_LEN, - (const byte *)label, (word32)strlen(label), seed, SEED_LEN, - IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS((byte*)msk, len, ssl->arrays->masterSecret, SECRET_LEN, + (const byte *)label, (word32)XSTRLEN(label), seed, SEED_LEN, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, ssl->devId); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)msk; + (void)len; + (void)label; +#endif #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) +static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2]) { - 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]); -} - -#ifdef HAVE_SNI -/* 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 word32 GetSEQIncrement(WOLFSSL* ssl, int verify) -{ -#ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if (verify) - return ssl->keys.dtls_state.curSeq; /* explicit from peer */ - else - return ssl->keys.dtls_sequence_number - 1; /* already incremented */ + if (verify) { + seq[0] = ssl->keys.peer_sequence_number_hi; + seq[1] = ssl->keys.peer_sequence_number_lo++; + if (seq[1] > ssl->keys.peer_sequence_number_lo) { + /* handle rollover */ + ssl->keys.peer_sequence_number_hi++; + } + } + else { + seq[0] = ssl->keys.sequence_number_hi; + seq[1] = ssl->keys.sequence_number_lo++; + if (seq[1] > ssl->keys.sequence_number_lo) { + /* handle rollover */ + ssl->keys.sequence_number_hi++; + } } -#endif - if (verify) - return ssl->keys.peer_sequence_number++; - else - return ssl->keys.sequence_number++; } #ifdef WOLFSSL_DTLS - -static INLINE word32 GetEpoch(WOLFSSL* ssl, int verify) +static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2]) { - if (verify) - return ssl->keys.dtls_state.curEpoch; - else - return ssl->keys.dtls_epoch; + if (order == PREV_ORDER) { + /* Previous epoch case */ + seq[0] = (((word32)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] = ((word32)ssl->keys.curEpoch << 16) | + (ssl->keys.curSeq_hi & 0xFFFF); + seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */ + } + else { + seq[0] = ((word32)ssl->keys.dtls_epoch << 16) | + (ssl->keys.dtls_sequence_number_hi & 0xFFFF); + seq[1] = ssl->keys.dtls_sequence_number_lo; + } } - #endif /* WOLFSSL_DTLS */ +static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out) +{ + word32 seq[2] = {0, 0}; + + if (!ssl->options.dtls) { + GetSEQIncrement(ssl, verifyOrder, seq); + } + else { +#ifdef WOLFSSL_DTLS + DtlsGetSEQ(ssl, verifyOrder, seq); +#endif + } + + c32toa(seq[0], out); + c32toa(seq[1], out + OPAQUE32_LEN); +} + + /*** end copy ***/ @@ -618,26 +718,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 @@ -648,7 +748,7 @@ int wolfSSL_GetHmacType(WOLFSSL* ssl) #endif default: { - return SSL_FATAL_ERROR; + return WOLFSSL_FATAL_ERROR; } } } @@ -662,11 +762,7 @@ int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content, XMEMSET(inner, 0, WOLFSSL_TLS_HMAC_INNER_SZ); -#ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - c16toa((word16)GetEpoch(ssl, verify), inner); -#endif - c32toa(GetSEQIncrement(ssl, verify), &inner[sizeof(word32)]); + WriteSEQ(ssl, verify, inner); inner[SEQ_SZ] = (byte)content; inner[SEQ_SZ + ENUM_LEN] = ssl->version.major; inner[SEQ_SZ + ENUM_LEN + ENUM_LEN] = ssl->version.minor; @@ -676,52 +772,526 @@ int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content, } -/* TLS type HMAC */ -int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, - int content, int verify) +#ifndef WOLFSSL_AEAD_ONLY +#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + +/* Update the hash in the HMAC. + * + * hmac HMAC object. + * data Data to be hashed. + * sz Size of data to hash. + * returns 0 on success, otherwise failure. + */ +static int Hmac_HashUpdate(Hmac* hmac, const byte* data, word32 sz) { - Hmac hmac; + int ret = BAD_FUNC_ARG; + + switch (hmac->macType) { + #ifndef NO_SHA + case WC_SHA: + ret = wc_ShaUpdate(&hmac->hash.sha, data, sz); + break; + #endif /* !NO_SHA */ + + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_Sha256Update(&hmac->hash.sha256, data, sz); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = wc_Sha384Update(&hmac->hash.sha384, data, sz); + break; + #endif /* WOLFSSL_SHA384 */ + + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + ret = wc_Sha512Update(&hmac->hash.sha512, data, sz); + break; + #endif /* WOLFSSL_SHA512 */ + } + + return ret; +} + +/* Finalize the hash but don't put the EOC, padding or length in. + * + * hmac HMAC object. + * hash Hash result. + * returns 0 on success, otherwise failure. + */ +static int Hmac_HashFinalRaw(Hmac* hmac, unsigned char* hash) +{ + int ret = BAD_FUNC_ARG; + + switch (hmac->macType) { + #ifndef NO_SHA + case WC_SHA: + ret = wc_ShaFinalRaw(&hmac->hash.sha, hash); + break; + #endif /* !NO_SHA */ + + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_Sha256FinalRaw(&hmac->hash.sha256, hash); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = wc_Sha384FinalRaw(&hmac->hash.sha384, hash); + break; + #endif /* WOLFSSL_SHA384 */ + + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + ret = wc_Sha512FinalRaw(&hmac->hash.sha512, hash); + break; + #endif /* WOLFSSL_SHA512 */ + } + + return ret; +} + +/* Finalize the HMAC by performing outer hash. + * + * hmac HMAC object. + * mac MAC result. + * returns 0 on success, otherwise failure. + */ +static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac) +{ + int ret = BAD_FUNC_ARG; + wc_HashAlg hash; + enum wc_HashType hashType = (enum wc_HashType)hmac->macType; + int digestSz = wc_HashGetDigestSize(hashType); + int blockSz = wc_HashGetBlockSize(hashType); + + if ((digestSz >= 0) && (blockSz >= 0)) { + ret = wc_HashInit(&hash, hashType); + } + if (ret == 0) { + ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->opad, + blockSz); + if (ret == 0) + ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->innerHash, + digestSz); + if (ret == 0) + ret = wc_HashFinal(&hash, hashType, mac); + wc_HashFree(&hash, hashType); + } + + return ret; +} + +/* Calculate the HMAC of the header + message data. + * Constant time implementation using wc_Sha*FinalRaw(). + * + * hmac HMAC object. + * digest MAC result. + * in Message data. + * sz Size of the message data. + * header Constructed record header with length of handshake data. + * returns 0 on success, otherwise failure. + */ +static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in, + word32 sz, byte* header) +{ + byte lenBytes[8]; + int i, j, k; + int blockBits, blockMask; + int lastBlockLen, macLen, extraLen, eocIndex; + int blocks, safeBlocks, lenBlock, eocBlock; + int maxLen; + int blockSz, padSz; int ret; - byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; + word32 realLen; + byte extraBlock; + + switch (hmac->macType) { + #ifndef NO_SHA + case WC_SHA: + blockSz = WC_SHA_BLOCK_SIZE; + blockBits = 6; + macLen = WC_SHA_DIGEST_SIZE; + padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1; + break; + #endif /* !NO_SHA */ + + #ifndef NO_SHA256 + case WC_SHA256: + blockSz = WC_SHA256_BLOCK_SIZE; + blockBits = 6; + macLen = WC_SHA256_DIGEST_SIZE; + padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + blockSz = WC_SHA384_BLOCK_SIZE; + blockBits = 7; + macLen = WC_SHA384_DIGEST_SIZE; + padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1; + break; + #endif /* WOLFSSL_SHA384 */ + + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + blockSz = WC_SHA512_BLOCK_SIZE; + blockBits = 7; + macLen = WC_SHA512_DIGEST_SIZE; + padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1; + break; + #endif /* WOLFSSL_SHA512 */ + + default: + return BAD_FUNC_ARG; + } + blockMask = blockSz - 1; + + /* Size of data to HMAC if padding length byte is zero. */ + maxLen = WOLFSSL_TLS_HMAC_INNER_SZ + sz - 1 - macLen; + /* Complete data (including padding) has block for EOC and/or length. */ + extraBlock = ctSetLTE((maxLen + padSz) & blockMask, padSz); + /* Total number of blocks for data including padding. */ + blocks = ((maxLen + blockSz - 1) >> blockBits) + extraBlock; + /* Up to last 6 blocks can be hashed safely. */ + safeBlocks = blocks - 6; + + /* Length of message data. */ + realLen = maxLen - in[sz - 1]; + /* Number of message bytes in last block. */ + lastBlockLen = realLen & blockMask; + /* Number of padding bytes in last block. */ + extraLen = ((blockSz * 2 - padSz - lastBlockLen) & blockMask) + 1; + /* Number of blocks to create for hash. */ + lenBlock = (realLen + extraLen) >> blockBits; + /* Block containing EOC byte. */ + eocBlock = realLen >> blockBits; + /* Index of EOC byte in block. */ + eocIndex = realLen & blockMask; + + /* Add length of hmac's ipad to total length. */ + realLen += blockSz; + /* Length as bits - 8 bytes bigendian. */ + c32toa(realLen >> ((sizeof(word32) * 8) - 3), lenBytes); + c32toa(realLen << 3, lenBytes + sizeof(word32)); + + ret = Hmac_HashUpdate(hmac, (unsigned char*)hmac->ipad, blockSz); + if (ret != 0) + return ret; + + XMEMSET(hmac->innerHash, 0, macLen); + + if (safeBlocks > 0) { + ret = Hmac_HashUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ); + if (ret != 0) + return ret; + ret = Hmac_HashUpdate(hmac, in, safeBlocks * blockSz - + WOLFSSL_TLS_HMAC_INNER_SZ); + if (ret != 0) + return ret; + } + else + safeBlocks = 0; + + XMEMSET(digest, 0, macLen); + k = safeBlocks * blockSz; + for (i = safeBlocks; i < blocks; i++) { + unsigned char hashBlock[WC_MAX_BLOCK_SIZE]; + unsigned char isEocBlock = ctMaskEq(i, eocBlock); + unsigned char isOutBlock = ctMaskEq(i, lenBlock); + + for (j = 0; j < blockSz; j++, k++) { + unsigned char atEoc = ctMaskEq(j, eocIndex) & isEocBlock; + unsigned char pastEoc = ctMaskGT(j, eocIndex) & isEocBlock; + unsigned char b = 0; + + if (k < WOLFSSL_TLS_HMAC_INNER_SZ) + b = header[k]; + else if (k < maxLen) + b = in[k - WOLFSSL_TLS_HMAC_INNER_SZ]; + + b = ctMaskSel(atEoc, 0x80, b); + b &= (unsigned char)~(word32)pastEoc; + b &= ((unsigned char)~(word32)isOutBlock) | isEocBlock; + + if (j >= blockSz - 8) { + b = ctMaskSel(isOutBlock, lenBytes[j - (blockSz - 8)], b); + } + + hashBlock[j] = b; + } + + ret = Hmac_HashUpdate(hmac, hashBlock, blockSz); + if (ret != 0) + return ret; + ret = Hmac_HashFinalRaw(hmac, hashBlock); + if (ret != 0) + return ret; + for (j = 0; j < macLen; j++) + ((unsigned char*)hmac->innerHash)[j] |= hashBlock[j] & isOutBlock; + } + + ret = Hmac_OuterHash(hmac, digest); + + return ret; +} + +#endif + +#if defined(WOLFSSL_NO_HASH_RAW) || defined(HAVE_FIPS) || \ + defined(HAVE_SELFTEST) || defined(HAVE_BLAKE2) + +/* Calculate the HMAC of the header + message data. + * Constant time implementation using normal hashing operations. + * Update-Final need to be constant time. + * + * hmac HMAC object. + * digest MAC result. + * in Message data. + * sz Size of the message data. + * header Constructed record header with length of handshake data. + * returns 0 on success, otherwise failure. + */ +static int Hmac_UpdateFinal(Hmac* hmac, byte* digest, const byte* in, + word32 sz, byte* header) +{ + byte dummy[WC_MAX_BLOCK_SIZE] = {0}; + int ret; + word32 msgSz, blockSz, macSz, padSz, maxSz, realSz; + word32 currSz, offset = 0; + int msgBlocks, blocks, blockBits; + int i; + + switch (hmac->macType) { + #ifndef NO_SHA + case WC_SHA: + blockSz = WC_SHA_BLOCK_SIZE; + blockBits = 6; + macSz = WC_SHA_DIGEST_SIZE; + padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1; + break; + #endif /* !NO_SHA */ + + #ifndef NO_SHA256 + case WC_SHA256: + blockSz = WC_SHA256_BLOCK_SIZE; + blockBits = 6; + macSz = WC_SHA256_DIGEST_SIZE; + padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + blockSz = WC_SHA384_BLOCK_SIZE; + blockBits = 7; + macSz = WC_SHA384_DIGEST_SIZE; + padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1; + break; + #endif /* WOLFSSL_SHA384 */ + + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + blockSz = WC_SHA512_BLOCK_SIZE; + blockBits = 7; + macSz = WC_SHA512_DIGEST_SIZE; + padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1; + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case WC_HASH_TYPE_BLAKE2B: + blockSz = BLAKE2B_BLOCKBYTES; + blockBits = 7; + macSz = BLAKE2B_256; + padSz = 0; + break; + #endif /* HAVE_BLAK2 */ + + default: + return BAD_FUNC_ARG; + } + + msgSz = sz - (1 + in[sz - 1] + macSz); + /* Make negative result 0 */ + msgSz &= ~(0 - (msgSz >> 31)); + realSz = WOLFSSL_TLS_HMAC_INNER_SZ + msgSz; + maxSz = WOLFSSL_TLS_HMAC_INNER_SZ + (sz - 1) - macSz; + + /* Calculate #blocks processed in HMAC for max and real data. */ + blocks = maxSz >> blockBits; + blocks += ((maxSz + padSz) % blockSz) < padSz; + msgBlocks = realSz >> blockBits; + /* #Extra blocks to process. */ + blocks -= msgBlocks + (((realSz + padSz) % blockSz) < padSz); + /* Calculate whole blocks. */ + msgBlocks--; + + ret = wc_HmacUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ); + if (ret == 0) { + /* Fill the rest of the block with any available data. */ + currSz = ctMaskLT(msgSz, blockSz) & msgSz; + currSz |= ctMaskGTE(msgSz, blockSz) & blockSz; + currSz -= WOLFSSL_TLS_HMAC_INNER_SZ; + currSz &= ~(0 - (currSz >> 31)); + ret = wc_HmacUpdate(hmac, in, currSz); + offset = currSz; + } + if (ret == 0) { + /* Do the hash operations on a block basis. */ + for (i = 0; i < msgBlocks; i++, offset += blockSz) { + ret = wc_HmacUpdate(hmac, in + offset, blockSz); + if (ret != 0) + break; + } + } + if (ret == 0) + ret = wc_HmacUpdate(hmac, in + offset, msgSz - offset); + if (ret == 0) + ret = wc_HmacFinal(hmac, digest); + if (ret == 0) { + /* Do the dummy hash operations. Do at least one. */ + for (i = 0; i < blocks + 1; i++) { + ret = wc_HmacUpdate(hmac, dummy, blockSz); + if (ret != 0) + break; + } + } + + return ret; +} + +#endif + +int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz, + int content, int verify) +{ + Hmac hmac; + byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; + int ret = 0; +#ifdef HAVE_TRUNCATED_HMAC + word32 hashSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ + : ssl->specs.hash_size; +#else + word32 hashSz = ssl->specs.hash_size; +#endif if (ssl == NULL) return BAD_FUNC_ARG; #ifdef HAVE_FUZZER - if (ssl->fuzzerCb) - ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx); + /* Fuzz "in" buffer with sz to be used in HMAC algorithm */ + if (ssl->fuzzerCb) { + if (verify && padSz >= 0) { + ssl->fuzzerCb(ssl, in, sz + hashSz + padSz + 1, FUZZ_HMAC, + ssl->fuzzerCtx); + } + else { + ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx); + } + } #endif wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify); +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + if (tsip_useable(ssl)) { + if (ssl->specs.hash_size == WC_SHA_DIGEST_SIZE) + ret = tsip_Sha1Hmac(ssl, myInner, WOLFSSL_TLS_HMAC_INNER_SZ, + in, sz, digest, verify); + else if (ssl->specs.hash_size == WC_SHA256_DIGEST_SIZE) + ret = tsip_Sha256Hmac(ssl, myInner, WOLFSSL_TLS_HMAC_INNER_SZ, + in, sz, digest, verify); + else + ret = TSIP_MAC_DIGSZ_E; - 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); + } +#endif + 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) { + /* Constant time verification required. */ + if (verify && padSz >= 0) { +#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + #ifdef HAVE_BLAKE2 + if (wolfSSL_GetHmacType(ssl) == WC_HASH_TYPE_BLAKE2B) { + ret = Hmac_UpdateFinal(&hmac, digest, in, + sz + hashSz + padSz + 1, myInner); + } + else + #endif + { + ret = Hmac_UpdateFinal_CT(&hmac, digest, in, + sz + hashSz + padSz + 1, myInner); + } +#else + ret = Hmac_UpdateFinal(&hmac, digest, in, sz + hashSz + padSz + 1, + myInner); +#endif + } + else { + 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; } +#endif /* WOLFSSL_AEAD_ONLY */ + +#endif /* !WOLFSSL_NO_TLS12 */ #ifdef HAVE_TLS_EXTENSIONS +/** + * The TLSX semaphore is used to calculate the size of the extensions to be sent + * from one peer to another. + */ -/** Supports up to 64 flags. Update as needed. */ +/** Supports up to 64 flags. Increase as needed. */ #define SEMAPHORE_SIZE 8 - -static INLINE word16 TLSX_ToSemaphore(word16 type) +/** + * Converts the extension type (id) to an index in the semaphore. + * + * Official reference for TLS extension types: + * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml + * + * Motivation: + * Previously, we used the extension type itself as the index of that + * extension in the semaphore as the extension types were declared + * sequentially, but maintain a semaphore as big as the number of available + * extensions is no longer an option since the release of renegotiation_info. + * + * How to update: + * Assign extension types that extrapolate the number of available semaphores + * to the first available index going backwards in the semaphore array. + * When adding a new extension type that don't extrapolate the number of + * available semaphores, check for a possible collision with with a + * 'remapped' extension type. + */ +static WC_INLINE word16 TLSX_ToSemaphore(word16 type) { switch (type) { - case SECURE_RENEGOTIATION: + + case TLSX_RENEGOTIATION_INFO: /* 0xFF01 */ return 63; default: @@ -732,37 +1302,59 @@ static INLINE word16 TLSX_ToSemaphore(word16 type) is assigned to be used by another extension. Use this check value for the new extension and decrement the check value by one. */ - WOLFSSL_MSG("### TLSX semaphore colision or overflow detected!"); + WOLFSSL_MSG("### TLSX semaphore collision or overflow detected!"); } } return 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))) -static int TLSX_Push(TLSX** list, TLSX_Type type, void* data) +/** Creates a new extension. */ +static TLSX* TLSX_New(TLSX_Type type, void* data, void* heap) { - TLSX* extension; + TLSX* extension = (TLSX*)XMALLOC(sizeof(TLSX), heap, DYNAMIC_TYPE_TLSX); + + (void)heap; + + if (extension) { + extension->type = type; + extension->data = data; + extension->resp = 0; + extension->next = NULL; + } + + return extension; +} + +/** + * Creates a new extension and pushes it to the provided list. + * Checks for duplicate extensions, keeps the newest. + */ +static int TLSX_Push(TLSX** list, TLSX_Type type, void* data, void* heap) +{ + TLSX* extension = TLSX_New(type, data, heap); - extension = (TLSX*)XMALLOC(sizeof(TLSX), 0, DYNAMIC_TYPE_TLSX); if (extension == NULL) return MEMORY_E; - extension->type = type; - extension->data = data; - extension->resp = 0; + /* pushes the new extension on the list. */ extension->next = *list; *list = extension; - /* remove duplicated extensions, there should be only one of each type. */ + /* remove duplicate extensions, there should be only one of each type. */ do { if (extension->next && extension->next->type == type) { TLSX *next = extension->next; @@ -770,10 +1362,11 @@ static int TLSX_Push(TLSX** list, TLSX_Type type, void* data) extension->next = next->next; next->next = NULL; - TLSX_FreeAll(next); + 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)); @@ -781,90 +1374,500 @@ static int TLSX_Push(TLSX** list, TLSX_Type type, void* data) return 0; } +#ifndef NO_WOLFSSL_CLIENT -#ifndef NO_WOLFSSL_SERVER +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 + +/** Mark an extension to be sent back to the client. */ 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; } +/******************************************************************************/ +/* Application-Layer Protocol Negotiation */ +/******************************************************************************/ + +#ifdef HAVE_ALPN +/** Creates a new ALPN object, providing protocol name to use. */ +static ALPN* TLSX_ALPN_New(char *protocol_name, word16 protocol_nameSz, + void* heap) +{ + ALPN *alpn; + + WOLFSSL_ENTER("TLSX_ALPN_New"); + + if (protocol_name == NULL || + protocol_nameSz > WOLFSSL_MAX_ALPN_PROTO_NAME_LEN) { + WOLFSSL_MSG("Invalid arguments"); + return NULL; + } + + alpn = (ALPN*)XMALLOC(sizeof(ALPN), heap, DYNAMIC_TYPE_TLSX); + if (alpn == NULL) { + WOLFSSL_MSG("Memory failure"); + return NULL; + } + + alpn->next = NULL; + alpn->negotiated = 0; + alpn->options = 0; + + alpn->protocol_name = (char*)XMALLOC(protocol_nameSz + 1, + heap, DYNAMIC_TYPE_TLSX); + if (alpn->protocol_name == NULL) { + WOLFSSL_MSG("Memory failure"); + XFREE(alpn, heap, DYNAMIC_TYPE_TLSX); + return NULL; + } + + XMEMCPY(alpn->protocol_name, protocol_name, protocol_nameSz); + alpn->protocol_name[protocol_nameSz] = 0; + + (void)heap; + + return alpn; +} + +/** Releases an ALPN object. */ +static void TLSX_ALPN_Free(ALPN *alpn, void* heap) +{ + (void)heap; + + if (alpn == NULL) + return; + + XFREE(alpn->protocol_name, heap, DYNAMIC_TYPE_TLSX); + XFREE(alpn, heap, DYNAMIC_TYPE_TLSX); +} + +/** Releases all ALPN objects in the provided list. */ +static void TLSX_ALPN_FreeAll(ALPN *list, void* heap) +{ + ALPN* alpn; + + while ((alpn = list)) { + list = alpn->next; + TLSX_ALPN_Free(alpn, heap); + } +} + +/** Tells the buffered size of the ALPN objects in a list. */ +static word16 TLSX_ALPN_GetSize(ALPN *list) +{ + ALPN* alpn; + word16 length = OPAQUE16_LEN; /* list length */ + + while ((alpn = list)) { + list = alpn->next; + + length++; /* protocol name length is on one byte */ + length += (word16)XSTRLEN(alpn->protocol_name); + } + + return length; +} + +/** Writes the ALPN objects of a list in a buffer. */ +static word16 TLSX_ALPN_Write(ALPN *list, byte *output) +{ + ALPN* alpn; + word16 length = 0; + word16 offset = OPAQUE16_LEN; /* list length offset */ + + while ((alpn = list)) { + list = alpn->next; + + length = (word16)XSTRLEN(alpn->protocol_name); + + /* protocol name length */ + output[offset++] = (byte)length; + + /* protocol name value */ + XMEMCPY(output + offset, alpn->protocol_name, length); + + offset += length; + } + + /* writing list length */ + c16toa(offset - OPAQUE16_LEN, output); + + return offset; +} + +/** Finds a protocol name in the provided ALPN list */ +static ALPN* TLSX_ALPN_Find(ALPN *list, char *protocol_name, word16 size) +{ + ALPN *alpn; + + if (list == NULL || protocol_name == NULL) + return NULL; + + alpn = list; + while (alpn != NULL && ( + (word16)XSTRLEN(alpn->protocol_name) != size || + XSTRNCMP(alpn->protocol_name, protocol_name, size))) + alpn = alpn->next; + + return alpn; +} + +/** Set the ALPN matching client and server requirements */ +static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size, + void* heap) +{ + ALPN *alpn; + int ret; + + if (extensions == NULL || data == NULL) + return BAD_FUNC_ARG; + + alpn = TLSX_ALPN_New((char *)data, size, heap); + if (alpn == NULL) { + WOLFSSL_MSG("Memory failure"); + return MEMORY_E; + } + + alpn->negotiated = 1; + + ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL, (void*)alpn, + heap); + if (ret != 0) { + TLSX_ALPN_Free(alpn, heap); + return ret; + } + + return WOLFSSL_SUCCESS; +} + +/** Parses a buffer of ALPN extensions and set the first one matching + * client and server requirements */ +static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, + byte isRequest) +{ + word16 size = 0, offset = 0, idx = 0; + int r = BUFFER_ERROR; + byte match = 0; + TLSX *extension; + ALPN *alpn = NULL, *list; + + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + ato16(input, &size); + offset += OPAQUE16_LEN; + + if (size == 0) + return BUFFER_ERROR; + + extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); + if (extension == NULL) + extension = TLSX_Find(ssl->ctx->extensions, + TLSX_APPLICATION_LAYER_PROTOCOL); + +#if defined(OPENSSL_ALL) || 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 -/* SNI - Server Name Indication */ + if (extension == NULL || extension->data == NULL) { + return isRequest ? 0 + : TLSX_HandleUnsupportedExtension(ssl); + } + + /* validating alpn list length */ + if (length != OPAQUE16_LEN + size) + return BUFFER_ERROR; + + list = (ALPN*)extension->data; + + /* keep the list sent by client */ + if (isRequest) { + if (ssl->alpn_client_list != NULL) + XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN); + + ssl->alpn_client_list = (char *)XMALLOC(size, ssl->heap, + DYNAMIC_TYPE_ALPN); + if (ssl->alpn_client_list == NULL) + return MEMORY_ERROR; + } + + for (size = 0; offset < length; offset += size) { + + size = input[offset++]; + if (offset + size > length || size == 0) + return BUFFER_ERROR; + + if (isRequest) { + XMEMCPY(ssl->alpn_client_list+idx, (char*)input + offset, size); + idx += size; + ssl->alpn_client_list[idx++] = ','; + } + + if (!match) { + alpn = TLSX_ALPN_Find(list, (char*)input + offset, size); + if (alpn != NULL) { + WOLFSSL_MSG("ALPN protocol match"); + match = 1; + + /* skip reading other values if not required */ + if (!isRequest) + break; + } + } + } + + if (isRequest) + ssl->alpn_client_list[idx-1] = 0; + + if (!match) { + WOLFSSL_MSG("No ALPN protocol match"); + + /* do nothing if no protocol match between client and server and option + is set to continue (like OpenSSL) */ + if (list->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) { + WOLFSSL_MSG("Continue on mismatch"); + return 0; + } + + SendAlert(ssl, alert_fatal, no_application_protocol); + return UNKNOWN_ALPN_PROTOCOL_NAME_E; + } + + /* set the matching negotiated protocol */ + r = TLSX_SetALPN(&ssl->extensions, + alpn->protocol_name, + (word16)XSTRLEN(alpn->protocol_name), + ssl->heap); + if (r != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("TLSX_UseALPN failed"); + return BUFFER_ERROR; + } + + /* reply to ALPN extension sent from client */ + if (isRequest) { +#ifndef NO_WOLFSSL_SERVER + TLSX_SetResponse(ssl, TLSX_APPLICATION_LAYER_PROTOCOL); +#endif + } + + return 0; +} + +/** Add a protocol name to the list of accepted usable ones */ +int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size, byte options, + void* heap) +{ + ALPN *alpn; + TLSX *extension; + int ret; + + if (extensions == NULL || data == NULL) + return BAD_FUNC_ARG; + + alpn = TLSX_ALPN_New((char *)data, size, heap); + if (alpn == NULL) { + WOLFSSL_MSG("Memory failure"); + return MEMORY_E; + } + + /* Set Options of ALPN */ + alpn->options = options; + + extension = TLSX_Find(*extensions, TLSX_APPLICATION_LAYER_PROTOCOL); + if (extension == NULL) { + ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL, + (void*)alpn, heap); + if (ret != 0) { + TLSX_ALPN_Free(alpn, heap); + return ret; + } + } + else { + /* push new ALPN object to extension data. */ + alpn->next = (ALPN*)extension->data; + extension->data = (void*)alpn; + } + + return WOLFSSL_SUCCESS; +} + +/** Get the protocol name set by the server */ +int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz) +{ + TLSX *extension; + ALPN *alpn; + + if (extensions == NULL || data == NULL || dataSz == NULL) + return BAD_FUNC_ARG; + + extension = TLSX_Find(extensions, TLSX_APPLICATION_LAYER_PROTOCOL); + if (extension == NULL) { + WOLFSSL_MSG("TLS extension not found"); + return WOLFSSL_ALPN_NOT_FOUND; + } + + alpn = (ALPN *)extension->data; + if (alpn == NULL) { + WOLFSSL_MSG("ALPN extension not found"); + *data = NULL; + *dataSz = 0; + return WOLFSSL_FATAL_ERROR; + } + + if (alpn->negotiated != 1) { + + /* consider as an error */ + if (alpn->options & WOLFSSL_ALPN_FAILED_ON_MISMATCH) { + WOLFSSL_MSG("No protocol match with peer -> Failed"); + return WOLFSSL_FATAL_ERROR; + } + + /* continue without negotiated protocol */ + WOLFSSL_MSG("No protocol match with peer -> Continue"); + return WOLFSSL_ALPN_NOT_FOUND; + } + + if (alpn->next != NULL) { + WOLFSSL_MSG("Only one protocol name must be accepted"); + return WOLFSSL_FATAL_ERROR; + } + + *data = alpn->protocol_name; + *dataSz = (word16)XSTRLEN((char*)*data); + + return WOLFSSL_SUCCESS; +} + +#define ALPN_FREE_ALL TLSX_ALPN_FreeAll +#define ALPN_GET_SIZE TLSX_ALPN_GetSize +#define ALPN_WRITE TLSX_ALPN_Write +#define ALPN_PARSE TLSX_ALPN_ParseAndSet + +#else /* HAVE_ALPN */ + +#define ALPN_FREE_ALL(list, heap) +#define ALPN_GET_SIZE(list) 0 +#define ALPN_WRITE(a, b) 0 +#define ALPN_PARSE(a, b, c, d) 0 + +#endif /* HAVE_ALPN */ + +/******************************************************************************/ +/* Server Name Indication */ +/******************************************************************************/ #ifdef HAVE_SNI -static void TLSX_SNI_Free(SNI* sni) +/** Creates a new SNI object. */ +static SNI* TLSX_SNI_New(byte type, const void* data, word16 size, void* heap) +{ + SNI* sni = (SNI*)XMALLOC(sizeof(SNI), heap, DYNAMIC_TYPE_TLSX); + + (void)heap; + + if (sni) { + sni->type = type; + sni->next = NULL; + + #ifndef NO_WOLFSSL_SERVER + sni->options = 0; + sni->status = WOLFSSL_SNI_NO_MATCH; + #endif + + switch (sni->type) { + case WOLFSSL_SNI_HOST_NAME: + sni->data.host_name = (char*)XMALLOC(size + 1, heap, + DYNAMIC_TYPE_TLSX); + if (sni->data.host_name) { + XSTRNCPY(sni->data.host_name, (const char*)data, size); + sni->data.host_name[size] = '\0'; + } else { + XFREE(sni, heap, DYNAMIC_TYPE_TLSX); + sni = NULL; + } + break; + + default: /* invalid type */ + XFREE(sni, heap, DYNAMIC_TYPE_TLSX); + sni = NULL; + } + } + + return sni; +} + +/** Releases a SNI object. */ +static void TLSX_SNI_Free(SNI* sni, void* heap) { if (sni) { switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: - XFREE(sni->data.host_name, 0, DYNAMIC_TYPE_TLSX); + XFREE(sni->data.host_name, heap, DYNAMIC_TYPE_TLSX); break; } - XFREE(sni, 0, DYNAMIC_TYPE_TLSX); + XFREE(sni, heap, DYNAMIC_TYPE_TLSX); } + (void)heap; } -static void TLSX_SNI_FreeAll(SNI* list) +/** Releases all SNI objects in the provided list. */ +static void TLSX_SNI_FreeAll(SNI* list, void* heap) { SNI* sni; while ((sni = list)) { list = sni->next; - TLSX_SNI_Free(sni); + TLSX_SNI_Free(sni, heap); } } -static int TLSX_SNI_Append(SNI** list, byte type, const void* data, word16 size) -{ - SNI* sni; - - if (list == NULL) - return BAD_FUNC_ARG; - - if ((sni = XMALLOC(sizeof(SNI), 0, DYNAMIC_TYPE_TLSX)) == NULL) - return MEMORY_E; - - switch (type) { - case WOLFSSL_SNI_HOST_NAME: { - sni->data.host_name = XMALLOC(size + 1, 0, DYNAMIC_TYPE_TLSX); - - if (sni->data.host_name) { - XSTRNCPY(sni->data.host_name, (const char*)data, size); - sni->data.host_name[size] = 0; - } else { - XFREE(sni, 0, DYNAMIC_TYPE_TLSX); - return MEMORY_E; - } - } - break; - - default: /* invalid type */ - XFREE(sni, 0, DYNAMIC_TYPE_TLSX); - return BAD_FUNC_ARG; - } - - sni->type = type; - sni->next = *list; - -#ifndef NO_WOLFSSL_SERVER - sni->options = 0; - sni->status = WOLFSSL_SNI_NO_MATCH; -#endif - - *list = sni; - - return 0; -} - +/** Tells the buffered size of the SNI objects in a list. */ static word16 TLSX_SNI_GetSize(SNI* list) { SNI* sni; @@ -877,7 +1880,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; } } @@ -885,6 +1888,7 @@ static word16 TLSX_SNI_GetSize(SNI* list) return length; } +/** Writes the SNI objects of a list in a buffer. */ static word16 TLSX_SNI_Write(SNI* list, byte* output) { SNI* sni; @@ -898,7 +1902,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; @@ -915,9 +1919,10 @@ static word16 TLSX_SNI_Write(SNI* list, byte* output) return offset; } +/** 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; @@ -925,52 +1930,85 @@ static SNI* TLSX_SNI_Find(SNI *list, byte type) return sni; } -#ifndef NO_WOLFSSL_SERVER +/** Sets the status of a SNI object. */ static void TLSX_SNI_SetStatus(TLSX* extensions, byte type, byte status) { - TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); - SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); + SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type); - if (sni) { + if (sni) sni->status = status; - WOLFSSL_MSG("SNI did match!"); - } } +/** Gets the status of a SNI object. */ byte TLSX_SNI_Status(TLSX* extensions, byte type) { - TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); - SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); + SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type); if (sni) return sni->status; return 0; } -#endif +/** Parses a buffer of SNI extensions. */ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest) { #ifndef NO_WOLFSSL_SERVER word16 size = 0; word16 offset = 0; + int cacheOnly = 0; + SNI *sni = NULL; + byte type; + int matchStat; + byte matched; #endif - TLSX *extension = TLSX_Find(ssl->extensions, SERVER_NAME_INDICATION); + TLSX *extension = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME); if (!extension) - extension = TLSX_Find(ssl->ctx->extensions, SERVER_NAME_INDICATION); + extension = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME); - if (!extension || !extension->data) - return isRequest ? 0 : BUFFER_ERROR; /* not using SNI OR unexpected - SNI response from server. */ + if (!isRequest) { + #ifndef NO_WOLFSSL_CLIENT + if (!extension || !extension->data) + return TLSX_HandleUnsupportedExtension(ssl); - if (!isRequest) - return length ? BUFFER_ERROR : 0; /* SNI response must be empty! - Nothing else to do. */ + 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 + } #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; @@ -979,74 +2017,135 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, offset += OPAQUE16_LEN; /* validating sni list length */ - if (length != OPAQUE16_LEN + size) + if (length != OPAQUE16_LEN + size || size == 0) return BUFFER_ERROR; - for (size = 0; offset < length; offset += size) { - SNI *sni; - byte type = input[offset++]; + /* SNI was badly specified and only one type is now recognized and allowed. + * Only one SNI value per type (RFC6066), so, no loop. */ + type = input[offset++]; + if (type != WOLFSSL_SNI_HOST_NAME) + return BUFFER_ERROR; - if (offset + OPAQUE16_LEN > length) - return BUFFER_ERROR; + if (offset + OPAQUE16_LEN > length) + return BUFFER_ERROR; + ato16(input + offset, &size); + offset += OPAQUE16_LEN; - ato16(input + offset, &size); - offset += OPAQUE16_LEN; + if (offset + size != length || size == 0) + return BUFFER_ERROR; - if (offset + size > length) - return BUFFER_ERROR; + if (!cacheOnly && !(sni = TLSX_SNI_Find((SNI*)extension->data, type))) + return 0; /* not using this type of SNI. */ - if (!(sni = TLSX_SNI_Find((SNI*)extension->data, type))) { - continue; /* not using this SNI type */ +#ifdef WOLFSSL_TLS13 + /* Don't process the second ClientHello SNI extension if there + * was problems with the first. + */ + if (!cacheOnly && sni->status != 0) + return 0; +#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 != WOLFSSL_SUCCESS) + return r; /* throws error. */ + + if (cacheOnly) { + WOLFSSL_MSG("Forcing storage of SNI, Fake match"); + matchStat = WOLFSSL_SNI_FORCE_KEEP; + } + else if (matched) { + WOLFSSL_MSG("SNI did match!"); + matchStat = WOLFSSL_SNI_REAL_MATCH; + } + else { + WOLFSSL_MSG("fake SNI match from ANSWER_ON_MISMATCH"); + matchStat = WOLFSSL_SNI_FAKE_MATCH; } - switch(type) { - case WOLFSSL_SNI_HOST_NAME: { - byte matched = (XSTRLEN(sni->data.host_name) == size) - && (XSTRNCMP(sni->data.host_name, - (const char*)input + offset, size) == 0); + TLSX_SNI_SetStatus(ssl->extensions, type, (byte)matchStat); - if (matched || sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH) { - int r = TLSX_UseSNI(&ssl->extensions, - type, input + offset, size); - - if (r != SSL_SUCCESS) return r; /* throw error */ - - TLSX_SNI_SetStatus(ssl->extensions, type, - matched ? WOLFSSL_SNI_REAL_MATCH : WOLFSSL_SNI_FAKE_MATCH); - - } else if (!(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) { - SendAlert(ssl, alert_fatal, unrecognized_name); - - return UNKNOWN_SNI_HOST_NAME_E; - } - break; - } - } - - TLSX_SetResponse(ssl, SERVER_NAME_INDICATION); + if(!cacheOnly) + TLSX_SetResponse(ssl, TLSX_SERVER_NAME); } + else if (!(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) { + SendAlert(ssl, alert_fatal, unrecognized_name); + return UNKNOWN_SNI_HOST_NAME_E; + } +#else + (void)input; #endif return 0; } -int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size) +static int TLSX_SNI_VerifyParse(WOLFSSL* ssl, byte isRequest) { - TLSX* extension = TLSX_Find(*extensions, SERVER_NAME_INDICATION); - SNI* sni = NULL; - int ret = 0; + (void)ssl; + + if (isRequest) { + #ifndef NO_WOLFSSL_SERVER + TLSX* ctx_ext = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME); + TLSX* ssl_ext = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME); + SNI* ctx_sni = ctx_ext ? (SNI*)ctx_ext->data : NULL; + SNI* ssl_sni = ssl_ext ? (SNI*)ssl_ext->data : NULL; + SNI* sni = NULL; + + for (; ctx_sni; ctx_sni = ctx_sni->next) { + if (ctx_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) { + sni = TLSX_SNI_Find(ssl_sni, ctx_sni->type); + + if (sni) { + if (sni->status != WOLFSSL_SNI_NO_MATCH) + continue; + + /* if ssl level overrides ctx level, it is ok. */ + if ((sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) == 0) + continue; + } + + SendAlert(ssl, alert_fatal, handshake_failure); + return SNI_ABSENT_ERROR; + } + } + + for (; ssl_sni; ssl_sni = ssl_sni->next) { + if (ssl_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) { + if (ssl_sni->status != WOLFSSL_SNI_NO_MATCH) + continue; + + SendAlert(ssl, alert_fatal, handshake_failure); + return SNI_ABSENT_ERROR; + } + } + #endif /* NO_WOLFSSL_SERVER */ + } + + return 0; +} + +int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, + void* heap) +{ + TLSX* extension; + SNI* sni = NULL; if (extensions == NULL || data == NULL) return BAD_FUNC_ARG; - if ((ret = TLSX_SNI_Append(&sni, type, data, size)) != 0) - return ret; + if ((sni = TLSX_SNI_New(type, data, size, heap)) == NULL) + return MEMORY_E; + extension = TLSX_Find(*extensions, TLSX_SERVER_NAME); if (!extension) { - if ((ret = TLSX_Push(extensions, SERVER_NAME_INDICATION, (void*)sni)) - != 0) { - TLSX_SNI_Free(sni); + int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni, heap); + + if (ret != 0) { + TLSX_SNI_Free(sni, heap); return ret; } } @@ -1055,61 +2154,92 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size) sni->next = (SNI*)extension->data; extension->data = (void*)sni; - /* look for another server name of the same type to remove */ + /* 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); + TLSX_SNI_Free(next, heap); + /* 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 + +/** Tells the SNI requested by the client. */ word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data) { - TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); - SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); + SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type); if (sni && sni->status != WOLFSSL_SNI_NO_MATCH) { switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: - *data = sni->data.host_name; - return XSTRLEN(*data); + if (data) { + *data = sni->data.host_name; + return (word16)XSTRLEN((char*)*data); + } } } return 0; } +/** Sets the options for a SNI object. */ void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options) { - TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); - SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); + SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type); if (sni) sni->options = options; } +/** Retrieves a SNI request from a client hello buffer. */ 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; /* TLS record header */ - if ((enum ContentType) clientHello[offset++] != handshake) + if ((enum ContentType) clientHello[offset++] != handshake) { + + /* checking for SSLv2.0 client hello according to: */ + /* http://tools.ietf.org/html/rfc4346#appendix-E.1 */ + if ((enum HandShakeType) clientHello[++offset] == client_hello) { + offset += ENUM_LEN + VERSION_SZ; /* skip version */ + + ato16(clientHello + offset, &len16); + offset += OPAQUE16_LEN; + + if (len16 % 3) /* cipher_spec_length must be multiple of 3 */ + return BUFFER_ERROR; + + ato16(clientHello + offset, &len16); + /* Returning SNI_UNSUPPORTED do not increment offset here */ + + if (len16 != 0) /* session_id_length must be 0 */ + return BUFFER_ERROR; + + return SNI_UNSUPPORTED; + } + return BUFFER_ERROR; + } if (clientHello[offset++] != SSLv3_MAJOR) return BUFFER_ERROR; @@ -1185,7 +2315,7 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, if (helloSz < offset + extLen) return BUFFER_ERROR; - if (extType != SERVER_NAME_INDICATION) { + if (extType != TLSX_SERVER_NAME) { offset += extLen; /* skip extension */ } else { word16 listLen; @@ -1215,7 +2345,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; } } @@ -1227,20 +2357,364 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, #endif -#define SNI_FREE_ALL TLSX_SNI_FreeAll -#define SNI_GET_SIZE TLSX_SNI_GetSize -#define SNI_WRITE TLSX_SNI_Write -#define SNI_PARSE TLSX_SNI_Parse +#define SNI_FREE_ALL TLSX_SNI_FreeAll +#define SNI_GET_SIZE TLSX_SNI_GetSize +#define SNI_WRITE TLSX_SNI_Write +#define SNI_PARSE TLSX_SNI_Parse +#define SNI_VERIFY_PARSE TLSX_SNI_VerifyParse #else -#define SNI_FREE_ALL(list) -#define SNI_GET_SIZE(list) 0 -#define SNI_WRITE(a, b) 0 -#define SNI_PARSE(a, b, c, d) 0 +#define SNI_FREE_ALL(list, heap) +#define SNI_GET_SIZE(list) 0 +#define SNI_WRITE(a, b) 0 +#define SNI_PARSE(a, b, c, d) 0 +#define SNI_VERIFY_PARSE(a, b) 0 #endif /* HAVE_SNI */ +/******************************************************************************/ +/* Trusted CA Key Indication */ +/******************************************************************************/ + +#ifdef HAVE_TRUSTED_CA + +/** Creates a new TCA object. */ +static TCA* TLSX_TCA_New(byte type, const byte* id, word16 idSz, void* heap) +{ + TCA* tca = (TCA*)XMALLOC(sizeof(TCA), heap, DYNAMIC_TYPE_TLSX); + + if (tca) { + XMEMSET(tca, 0, sizeof(TCA)); + tca->type = type; + + switch (type) { + case WOLFSSL_TRUSTED_CA_PRE_AGREED: + break; + + #ifndef NO_SHA + case WOLFSSL_TRUSTED_CA_KEY_SHA1: + case WOLFSSL_TRUSTED_CA_CERT_SHA1: + if (idSz == WC_SHA_DIGEST_SIZE && + (tca->id = + (byte*)XMALLOC(idSz, heap, DYNAMIC_TYPE_TLSX))) { + XMEMCPY(tca->id, id, idSz); + tca->idSz = idSz; + } + else { + XFREE(tca, heap, DYNAMIC_TYPE_TLSX); + tca = NULL; + } + break; + #endif + + case WOLFSSL_TRUSTED_CA_X509_NAME: + if (idSz > 0 && + (tca->id = + (byte*)XMALLOC(idSz, heap, DYNAMIC_TYPE_TLSX))) { + XMEMCPY(tca->id, id, idSz); + tca->idSz = idSz; + } + else { + XFREE(tca, heap, DYNAMIC_TYPE_TLSX); + tca = NULL; + } + break; + + default: /* invalid type */ + XFREE(tca, heap, DYNAMIC_TYPE_TLSX); + tca = NULL; + } + } + + (void)heap; + + return tca; +} + +/** Releases a TCA object. */ +static void TLSX_TCA_Free(TCA* tca, void* heap) +{ + (void)heap; + + if (tca) { + if (tca->id) + XFREE(tca->id, heap, DYNAMIC_TYPE_TLSX); + XFREE(tca, heap, DYNAMIC_TYPE_TLSX); + } +} + +/** Releases all TCA objects in the provided list. */ +static void TLSX_TCA_FreeAll(TCA* list, void* heap) +{ + TCA* tca; + + while ((tca = list)) { + list = tca->next; + TLSX_TCA_Free(tca, heap); + } +} + +/** Tells the buffered size of the TCA objects in a list. */ +static word16 TLSX_TCA_GetSize(TCA* list) +{ + TCA* tca; + word16 length = OPAQUE16_LEN; /* list length */ + + while ((tca = list)) { + list = tca->next; + + length += ENUM_LEN; /* tca type */ + + switch (tca->type) { + case WOLFSSL_TRUSTED_CA_PRE_AGREED: + break; + case WOLFSSL_TRUSTED_CA_KEY_SHA1: + case WOLFSSL_TRUSTED_CA_CERT_SHA1: + length += tca->idSz; + break; + case WOLFSSL_TRUSTED_CA_X509_NAME: + length += OPAQUE16_LEN + tca->idSz; + break; + } + } + + return length; +} + +/** Writes the TCA objects of a list in a buffer. */ +static word16 TLSX_TCA_Write(TCA* list, byte* output) +{ + TCA* tca; + word16 offset = OPAQUE16_LEN; /* list length offset */ + + while ((tca = list)) { + list = tca->next; + + output[offset++] = tca->type; /* tca type */ + + switch (tca->type) { + case WOLFSSL_TRUSTED_CA_PRE_AGREED: + break; + #ifndef NO_SHA + case WOLFSSL_TRUSTED_CA_KEY_SHA1: + case WOLFSSL_TRUSTED_CA_CERT_SHA1: + if (tca->id != NULL) { + XMEMCPY(output + offset, tca->id, tca->idSz); + offset += tca->idSz; + } + else { + /* ID missing. Set to an empty string. */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + } + break; + #endif + case WOLFSSL_TRUSTED_CA_X509_NAME: + if (tca->id != NULL) { + c16toa(tca->idSz, output + offset); /* tca length */ + offset += OPAQUE16_LEN; + XMEMCPY(output + offset, tca->id, tca->idSz); + offset += tca->idSz; + } + else { + /* ID missing. Set to an empty string. */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + } + break; + default: + /* ID unknown. Set to an empty string. */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + } + } + + c16toa(offset - OPAQUE16_LEN, output); /* writing list length */ + + return offset; +} + +#ifndef NO_WOLFSSL_SERVER +static TCA* TLSX_TCA_Find(TCA *list, byte type, const byte* id, word16 idSz) +{ + TCA* tca = list; + + while (tca && tca->type != type && type != WOLFSSL_TRUSTED_CA_PRE_AGREED && + idSz != tca->idSz && !XMEMCMP(id, tca->id, idSz)) + tca = tca->next; + + return tca; +} +#endif /* NO_WOLFSSL_SERVER */ + +/** Parses a buffer of TCA extensions. */ +static int TLSX_TCA_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isRequest) +{ +#ifndef NO_WOLFSSL_SERVER + word16 size = 0; + word16 offset = 0; +#endif + + TLSX *extension = TLSX_Find(ssl->extensions, TLSX_TRUSTED_CA_KEYS); + + if (!extension) + extension = TLSX_Find(ssl->ctx->extensions, TLSX_TRUSTED_CA_KEYS); + + if (!isRequest) { + #ifndef NO_WOLFSSL_CLIENT + if (!extension || !extension->data) + return TLSX_HandleUnsupportedExtension(ssl); + + if (length > 0) + return BUFFER_ERROR; /* TCA response MUST be empty. */ + + /* Set the flag that we're good for keys */ + TLSX_SetResponse(ssl, TLSX_TRUSTED_CA_KEYS); + + return 0; + #endif + } + +#ifndef NO_WOLFSSL_SERVER + if (!extension || !extension->data) { + /* Skipping, TCA not enabled at server side. */ + return 0; + } + + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + ato16(input, &size); + offset += OPAQUE16_LEN; + + /* validating tca list length */ + if (length != OPAQUE16_LEN + size) + return BUFFER_ERROR; + + for (size = 0; offset < length; offset += size) { + TCA *tca = NULL; + byte type; + const byte* id = NULL; + word16 idSz = 0; + + if (offset + ENUM_LEN > length) + return BUFFER_ERROR; + + type = input[offset++]; + + switch (type) { + case WOLFSSL_TRUSTED_CA_PRE_AGREED: + break; + #ifndef NO_SHA + case WOLFSSL_TRUSTED_CA_KEY_SHA1: + case WOLFSSL_TRUSTED_CA_CERT_SHA1: + if (offset + WC_SHA_DIGEST_SIZE > length) + return BUFFER_ERROR; + idSz = WC_SHA_DIGEST_SIZE; + id = input + offset; + offset += idSz; + break; + #endif + case WOLFSSL_TRUSTED_CA_X509_NAME: + if (offset + OPAQUE16_LEN > length) + return BUFFER_ERROR; + ato16(input + offset, &idSz); + offset += OPAQUE16_LEN; + if ((offset > length) || (idSz > length - offset)) + return BUFFER_ERROR; + id = input + offset; + offset += idSz; + break; + default: + return TCA_INVALID_ID_TYPE; + } + + /* Find the type/ID in the TCA list. */ + tca = TLSX_TCA_Find((TCA*)extension->data, type, id, idSz); + if (tca != NULL) { + /* Found it. Set the response flag and break out of the loop. */ + TLSX_SetResponse(ssl, TLSX_TRUSTED_CA_KEYS); + break; + } + } +#else + (void)input; +#endif + + return 0; +} + +/* Checks to see if the server sent a response for the TCA. */ +static int TLSX_TCA_VerifyParse(WOLFSSL* ssl, byte isRequest) +{ + (void)ssl; + + if (!isRequest) { + #ifndef NO_WOLFSSL_CLIENT + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_TRUSTED_CA_KEYS); + + if (extension && !extension->resp) { + SendAlert(ssl, alert_fatal, handshake_failure); + return TCA_ABSENT_ERROR; + } + #endif /* NO_WOLFSSL_CLIENT */ + } + + return 0; +} + +int TLSX_UseTrustedCA(TLSX** extensions, byte type, + const byte* id, word16 idSz, void* heap) +{ + TLSX* extension; + TCA* tca = NULL; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + if ((tca = TLSX_TCA_New(type, id, idSz, heap)) == NULL) + return MEMORY_E; + + extension = TLSX_Find(*extensions, TLSX_TRUSTED_CA_KEYS); + if (!extension) { + int ret = TLSX_Push(extensions, TLSX_TRUSTED_CA_KEYS, (void*)tca, heap); + + if (ret != 0) { + TLSX_TCA_Free(tca, heap); + return ret; + } + } + else { + /* push new TCA object to extension data. */ + tca->next = (TCA*)extension->data; + extension->data = (void*)tca; + } + + return WOLFSSL_SUCCESS; +} + +#define TCA_FREE_ALL TLSX_TCA_FreeAll +#define TCA_GET_SIZE TLSX_TCA_GetSize +#define TCA_WRITE TLSX_TCA_Write +#define TCA_PARSE TLSX_TCA_Parse +#define TCA_VERIFY_PARSE TLSX_TCA_VerifyParse + +#else /* HAVE_TRUSTED_CA */ + +#define TCA_FREE_ALL(list, heap) +#define TCA_GET_SIZE(list) 0 +#define TCA_WRITE(a, b) 0 +#define TCA_PARSE(a, b, c, d) 0 +#define TCA_VERIFY_PARSE(a, b) 0 + +#endif /* HAVE_TRUSTED_CA */ + +/******************************************************************************/ +/* Max Fragment Length Negotiation */ +/******************************************************************************/ + #ifdef HAVE_MAX_FRAGMENT static word16 TLSX_MFL_Write(byte* data, byte* output) @@ -1256,7 +2730,16 @@ static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, 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_8 : ssl->max_fragment = 256; break; case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break; case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break; case WOLFSSL_MFL_2_11: ssl->max_fragment = 2048; break; @@ -1271,57 +2754,60 @@ static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, #ifndef NO_WOLFSSL_SERVER if (isRequest) { - int r = TLSX_UseMaxFragment(&ssl->extensions, *input); + 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, MAX_FRAGMENT_LENGTH); + TLSX_SetResponse(ssl, TLSX_MAX_FRAGMENT_LENGTH); } #endif return 0; } -int TLSX_UseMaxFragment(TLSX** extensions, byte mfl) +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_MIN || mfl > WOLFSSL_MFL_MAX) return BAD_FUNC_ARG; - if (mfl < WOLFSSL_MFL_2_9 || WOLFSSL_MFL_2_13 < mfl) - return BAD_FUNC_ARG; - - if ((data = XMALLOC(ENUM_LEN, 0, 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, MAX_FRAGMENT_LENGTH, data)) != 0) { - XFREE(data, 0, DYNAMIC_TYPE_TLSX); + 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; } -#define MFL_FREE_ALL(data) XFREE(data, 0, DYNAMIC_TYPE_TLSX) +#define MFL_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX) #define MFL_GET_SIZE(data) ENUM_LEN #define MFL_WRITE TLSX_MFL_Write #define MFL_PARSE TLSX_MFL_Parse #else -#define MFL_FREE_ALL(a) +#define MFL_FREE_ALL(a, b) #define MFL_GET_SIZE(a) 0 #define MFL_WRITE(a, b) 0 #define MFL_PARSE(a, b, c, d) 0 #endif /* HAVE_MAX_FRAGMENT */ +/******************************************************************************/ +/* Truncated HMAC */ +/******************************************************************************/ + #ifdef HAVE_TRUNCATED_HMAC static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length, @@ -1330,32 +2816,40 @@ static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length, if (length != 0 || input == NULL) return BUFFER_ERROR; -#ifndef NO_WOLFSSL_SERVER - if (isRequest) { - int r = TLSX_UseTruncatedHMAC(&ssl->extensions); - - if (r != SSL_SUCCESS) return r; /* throw error */ - - TLSX_SetResponse(ssl, 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; return 0; } -int TLSX_UseTruncatedHMAC(TLSX** extensions) +int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap) { int ret = 0; if (extensions == NULL) return BAD_FUNC_ARG; - if ((ret = TLSX_Push(extensions, TRUNCATED_HMAC, NULL)) != 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 @@ -1366,58 +2860,1048 @@ int TLSX_UseTruncatedHMAC(TLSX** extensions) #endif /* HAVE_TRUNCATED_HMAC */ -#ifdef HAVE_SUPPORTED_CURVES +/******************************************************************************/ +/* Certificate Status Request */ +/******************************************************************************/ -#ifndef HAVE_ECC -#error Elliptic Curves Extension requires Elliptic Curve Cryptography. \ - Use --enable-ecc in the configure script or define HAVE_ECC. -#endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST -static void TLSX_EllipticCurve_FreeAll(EllipticCurve* list) +static void TLSX_CSR_Free(CertificateStatusRequest* csr, void* heap) { - EllipticCurve* curve; - - while ((curve = list)) { - list = curve->next; - XFREE(curve, 0, DYNAMIC_TYPE_TLSX); + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + FreeOcspRequest(&csr->request.ocsp); + break; } + + XFREE(csr, heap, DYNAMIC_TYPE_TLSX); + (void)heap; } -static int TLSX_EllipticCurve_Append(EllipticCurve** list, word16 name) +static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest) { - EllipticCurve* curve; + word16 size = 0; - if (list == NULL) - return BAD_FUNC_ARG; + /* shut up compiler warnings */ + (void) csr; (void) isRequest; - if ((curve = XMALLOC(sizeof(EllipticCurve), 0, DYNAMIC_TYPE_TLSX)) == NULL) - return MEMORY_E; +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + size += ENUM_LEN + 2 * OPAQUE16_LEN; - curve->name = name; - curve->next = *list; + if (csr->request.ocsp.nonceSz) + size += OCSP_NONCE_EXT_SZ; + break; + } + } +#endif +#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + if (!isRequest && csr->ssl->options.tls1_3) + return OPAQUE8_LEN + OPAQUE24_LEN + csr->response.length; +#endif - *list = curve; + return size; +} + +static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, + byte isRequest) +{ + /* shut up compiler warnings */ + (void) csr; (void) output; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + word16 offset = 0; + word16 length = 0; + + /* type */ + output[offset++] = csr->status_type; + + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + /* responder id list */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + + /* request extensions */ + if (csr->request.ocsp.nonceSz) + length = (word16)EncodeOcspRequestExtensions( + &csr->request.ocsp, + output + offset + OPAQUE16_LEN, + OCSP_NONCE_EXT_SZ); + + c16toa(length, output + offset); + offset += OPAQUE16_LEN + length; + + break; + } + + return offset; + } +#endif +#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + if (!isRequest && csr->ssl->options.tls1_3) { + word16 offset = 0; + output[offset++] = csr->status_type; + c32to24(csr->response.length, output + offset); + offset += OPAQUE24_LEN; + XMEMCPY(output + offset, csr->response.buffer, csr->response.length); + offset += csr->response.length; + return offset; + } +#endif return 0; } -#ifndef NO_WOLFSSL_CLIENT - -static void TLSX_EllipticCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore) +static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) { - int i; + int ret; - for (i = 0; i < ssl->suites->suiteSz; i+= 2) - if (ssl->suites->suites[i] == ECC_BYTE) - return; + /* shut up compiler warnings */ + (void) ssl; (void) input; - /* No elliptic curve suite found */ - TURN_ON(semaphore, TLSX_ToSemaphore(ELLIPTIC_CURVES)); + if (!isRequest) { +#ifndef NO_WOLFSSL_CLIENT + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; + + if (!csr) { + /* look at context level */ + extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST); + csr = extension ? (CertificateStatusRequest*)extension->data : NULL; + + if (!csr) /* unexpected extension */ + return TLSX_HandleUnsupportedExtension(ssl); + + /* enable extension at ssl level */ + ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, + csr->status_type, csr->options, ssl, + ssl->heap, ssl->devId); + if (ret != WOLFSSL_SUCCESS) + return ret; + + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + /* propagate nonce */ + if (csr->request.ocsp.nonceSz) { + OcspRequest* request = + (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions); + + if (request) { + XMEMCPY(request->nonce, csr->request.ocsp.nonce, + csr->request.ocsp.nonceSz); + request->nonceSz = csr->request.ocsp.nonceSz; + } + } + break; + } + } + + ssl->status_request = 1; + + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + word32 resp_length; + word32 offset = 0; + + /* Get the new extension potentially created above. */ + extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + csr = extension ? (CertificateStatusRequest*)extension->data : NULL; + if (csr == NULL) + return MEMORY_ERROR; + + ret = 0; + if (OPAQUE8_LEN + OPAQUE24_LEN > length) + ret = BUFFER_ERROR; + if (ret == 0 && input[offset++] != WOLFSSL_CSR_OCSP) + ret = BAD_CERTIFICATE_STATUS_ERROR; + if (ret == 0) { + c24to32(input + offset, &resp_length); + offset += OPAQUE24_LEN; + if (offset + resp_length != length) + ret = BUFFER_ERROR; + } + #if !defined(NO_WOLFSSL_SERVER) + if (ret == 0) { + csr->response.buffer = input + offset; + csr->response.length = resp_length; + } + #endif + + return ret; + } + else + #endif + { + /* extension_data MUST be empty. */ + return length ? BUFFER_ERROR : 0; + } +#endif + } + else { +#ifndef NO_WOLFSSL_SERVER + byte status_type; + word16 offset = 0; + word16 size = 0; + + if (length == 0) + return 0; + if (length < ENUM_LEN) + return BUFFER_ERROR; + + status_type = input[offset++]; + + switch (status_type) { + case WOLFSSL_CSR_OCSP: { + + /* skip responder_id_list */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN + size; + + /* skip request_extensions */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN + size; + + if (offset > length) + return BUFFER_ERROR; + + /* is able to send OCSP response? */ + if (ssl->ctx->cm == NULL || !ssl->ctx->cm->ocspStaplingEnabled) + return 0; + } + break; + + /* unknown status type */ + default: + return 0; + } + + /* if using status_request and already sending it, skip this one */ + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) + return 0; + #endif + + /* accept the first good status_type and return */ + ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, + 0, ssl, ssl->heap, ssl->devId); + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ + + #if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + if (ssl->options.tls1_3) { + OcspRequest* request; + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; + if (csr == NULL) + return MEMORY_ERROR; + + request = &csr->request.ocsp; + ret = CreateOcspResponse(ssl, &request, &csr->response); + if (ret != 0) + return ret; + if (csr->response.buffer) + TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST); + } + else + #endif + TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST); + ssl->status_request = status_type; +#endif + } + + return 0; } -static word16 TLSX_EllipticCurve_GetSize(EllipticCurve* list) +int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap) { - EllipticCurve* curve; + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; + int ret = 0; + + if (csr) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: { + byte nonce[MAX_OCSP_NONCE_SZ]; + int nonceSz = csr->request.ocsp.nonceSz; + + /* preserve nonce */ + XMEMCPY(nonce, csr->request.ocsp.nonce, nonceSz); + + if ((ret = InitOcspRequest(&csr->request.ocsp, cert, 0, heap)) + != 0) + return ret; + + /* restore nonce */ + XMEMCPY(csr->request.ocsp.nonce, nonce, nonceSz); + csr->request.ocsp.nonceSz = nonceSz; + } + break; + } + } + + return ret; +} + +void* TLSX_CSR_GetRequest(TLSX* extensions) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; + + if (csr) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + return &csr->request.ocsp; + break; + } + } + + return NULL; +} + +int TLSX_CSR_ForceRequest(WOLFSSL* ssl) +{ + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; + + if (csr) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + 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; + } + } + + return 0; +} + +int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, + byte options, WOLFSSL* ssl, void* heap, + int devId) +{ + CertificateStatusRequest* csr = NULL; + int ret = 0; + + if (!extensions || status_type != WOLFSSL_CSR_OCSP) + return BAD_FUNC_ARG; + + csr = (CertificateStatusRequest*) + XMALLOC(sizeof(CertificateStatusRequest), heap, DYNAMIC_TYPE_TLSX); + if (!csr) + return MEMORY_E; + + ForceZero(csr, sizeof(CertificateStatusRequest)); + + csr->status_type = status_type; + csr->options = options; + csr->ssl = ssl; + + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + if (options & WOLFSSL_CSR_OCSP_USE_NONCE) { + WC_RNG rng; + + #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; + + wc_FreeRng(&rng); + } + } + break; + } + + if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr, heap)) != 0) { + XFREE(csr, heap, DYNAMIC_TYPE_TLSX); + return ret; + } + + return WOLFSSL_SUCCESS; +} + +#define CSR_FREE_ALL TLSX_CSR_Free +#define CSR_GET_SIZE TLSX_CSR_GetSize +#define CSR_WRITE TLSX_CSR_Write +#define CSR_PARSE TLSX_CSR_Parse + +#else + +#define CSR_FREE_ALL(data, heap) +#define CSR_GET_SIZE(a, b) 0 +#define CSR_WRITE(a, b, c) 0 +#define CSR_PARSE(a, b, c, d) 0 + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + +/******************************************************************************/ +/* Certificate Status Request v2 */ +/******************************************************************************/ + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + +static void TLSX_CSR2_FreeAll(CertificateStatusRequestItemV2* csr2, void* heap) +{ + CertificateStatusRequestItemV2* next; + + for (; csr2; csr2 = next) { + next = csr2->next; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + while(csr2->requests--) + FreeOcspRequest(&csr2->request.ocsp[csr2->requests]); + break; + } + + XFREE(csr2, heap, DYNAMIC_TYPE_TLSX); + } + (void)heap; +} + +static word16 TLSX_CSR2_GetSize(CertificateStatusRequestItemV2* csr2, + byte isRequest) +{ + word16 size = 0; + + /* shut up compiler warnings */ + (void) csr2; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + CertificateStatusRequestItemV2* next; + + for (size = OPAQUE16_LEN; csr2; csr2 = next) { + next = csr2->next; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + size += ENUM_LEN + 3 * OPAQUE16_LEN; + + if (csr2->request.ocsp[0].nonceSz) + size += OCSP_NONCE_EXT_SZ; + break; + } + } + } +#endif + + return size; +} + +static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2, + byte* output, byte isRequest) +{ + /* shut up compiler warnings */ + (void) csr2; (void) output; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + word16 offset; + word16 length; + + for (offset = OPAQUE16_LEN; csr2 != NULL; csr2 = csr2->next) { + /* status_type */ + output[offset++] = csr2->status_type; + + /* request */ + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + /* request_length */ + length = 2 * OPAQUE16_LEN; + + if (csr2->request.ocsp[0].nonceSz) + length += OCSP_NONCE_EXT_SZ; + + c16toa(length, output + offset); + offset += OPAQUE16_LEN; + + /* responder id list */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + + /* request extensions */ + length = 0; + + if (csr2->request.ocsp[0].nonceSz) + length = (word16)EncodeOcspRequestExtensions( + &csr2->request.ocsp[0], + output + offset + OPAQUE16_LEN, + OCSP_NONCE_EXT_SZ); + + c16toa(length, output + offset); + offset += OPAQUE16_LEN + length; + break; + } + } + + /* list size */ + c16toa(offset - OPAQUE16_LEN, output); + + return offset; + } +#endif + + return 0; +} + +static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + int ret; + + /* shut up compiler warnings */ + (void) ssl; (void) input; + + if (!isRequest) { +#ifndef NO_WOLFSSL_CLIENT + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; + + if (!csr2) { + /* look at context level */ + extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST_V2); + csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; + + 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, + ssl->devId); + if (ret != WOLFSSL_SUCCESS) + return ret; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + case WOLFSSL_CSR2_OCSP_MULTI: + /* propagate nonce */ + if (csr2->request.ocsp[0].nonceSz) { + OcspRequest* request = + (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions, + csr2->status_type, 0); + + if (request) { + XMEMCPY(request->nonce, + csr2->request.ocsp[0].nonce, + csr2->request.ocsp[0].nonceSz); + + request->nonceSz = + csr2->request.ocsp[0].nonceSz; + } + } + break; + } + } + } + + ssl->status_request_v2 = 1; + + return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */ +#endif + } + else { +#ifndef NO_WOLFSSL_SERVER + byte status_type; + word16 request_length; + word16 offset = 0; + word16 size = 0; + + /* list size */ + if (offset + OPAQUE16_LEN >= length) { + return BUFFER_E; + } + + ato16(input + offset, &request_length); + offset += OPAQUE16_LEN; + + if (length - OPAQUE16_LEN != request_length) + return BUFFER_ERROR; + + while (length > offset) { + if (length - offset < ENUM_LEN + OPAQUE16_LEN) + return BUFFER_ERROR; + + status_type = input[offset++]; + + ato16(input + offset, &request_length); + offset += OPAQUE16_LEN; + + if (length - offset < request_length) + return BUFFER_ERROR; + + switch (status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + /* skip responder_id_list */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + if (length - offset < size) + return BUFFER_ERROR; + + offset += OPAQUE16_LEN + size; + /* skip request_extensions */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + if (length - offset < size) + return BUFFER_ERROR; + + offset += OPAQUE16_LEN + size; + if (offset > length) + return BUFFER_ERROR; + + /* is able to send OCSP response? */ + if (ssl->ctx->cm == NULL + || !ssl->ctx->cm->ocspStaplingEnabled) + continue; + break; + + default: + /* unknown status type, skipping! */ + offset += request_length; + continue; + } + + /* if using status_request and already sending it, skip this one */ + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) + return 0; + #endif + + /* accept the first good status_type and return */ + ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, + status_type, 0, ssl->heap, ssl->devId); + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST_V2); + ssl->status_request_v2 = status_type; + + return 0; + } +#endif + } + + return 0; +} + +int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, + void* heap) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; + int ret = 0; + + for (; csr2; csr2 = csr2->next) { + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + if (!isPeer || csr2->requests != 0) + break; + + FALL_THROUGH; /* followed by */ + + case WOLFSSL_CSR2_OCSP_MULTI: { + if (csr2->requests < 1 + MAX_CHAIN_DEPTH) { + byte nonce[MAX_OCSP_NONCE_SZ]; + int nonceSz = csr2->request.ocsp[0].nonceSz; + + /* preserve nonce, replicating nonce of ocsp[0] */ + XMEMCPY(nonce, csr2->request.ocsp[0].nonce, nonceSz); + + if ((ret = InitOcspRequest( + &csr2->request.ocsp[csr2->requests], cert, + 0, heap)) != 0) + return ret; + + /* restore nonce */ + XMEMCPY(csr2->request.ocsp[csr2->requests].nonce, + nonce, nonceSz); + csr2->request.ocsp[csr2->requests].nonceSz = nonceSz; + csr2->requests++; + } + } + break; + } + } + + (void)cert; + return ret; +} + +void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte idx) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; + + for (; csr2; csr2 = csr2->next) { + if (csr2->status_type == status_type) { + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + + case WOLFSSL_CSR2_OCSP_MULTI: + /* requests are initialized in the reverse order */ + return idx < csr2->requests + ? &csr2->request.ocsp[csr2->requests - idx - 1] + : NULL; + break; + } + } + } + + return NULL; +} + +int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) +{ + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; + + /* forces only the first one */ + if (csr2) { + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + + case WOLFSSL_CSR2_OCSP_MULTI: + 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; + } + } + + return 0; +} + +int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, + byte options, void* heap, int devId) +{ + TLSX* extension = NULL; + CertificateStatusRequestItemV2* csr2 = NULL; + int ret = 0; + + if (!extensions) + return BAD_FUNC_ARG; + + if (status_type != WOLFSSL_CSR2_OCSP + && status_type != WOLFSSL_CSR2_OCSP_MULTI) + return BAD_FUNC_ARG; + + csr2 = (CertificateStatusRequestItemV2*) + XMALLOC(sizeof(CertificateStatusRequestItemV2), heap, DYNAMIC_TYPE_TLSX); + if (!csr2) + return MEMORY_E; + + ForceZero(csr2, sizeof(CertificateStatusRequestItemV2)); + + csr2->status_type = status_type; + csr2->options = options; + csr2->next = NULL; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + if (options & WOLFSSL_CSR2_OCSP_USE_NONCE) { + WC_RNG rng; + + #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; + + wc_FreeRng(&rng); + } + } + break; + } + + /* append new item */ + if ((extension = TLSX_Find(*extensions, TLSX_STATUS_REQUEST_V2))) { + CertificateStatusRequestItemV2* last = + (CertificateStatusRequestItemV2*)extension->data; + + for (; last->next; last = last->next); + + last->next = csr2; + } + else if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST_V2, csr2,heap))) { + XFREE(csr2, heap, DYNAMIC_TYPE_TLSX); + return ret; + } + + return WOLFSSL_SUCCESS; +} + +#define CSR2_FREE_ALL TLSX_CSR2_FreeAll +#define CSR2_GET_SIZE TLSX_CSR2_GetSize +#define CSR2_WRITE TLSX_CSR2_Write +#define CSR2_PARSE TLSX_CSR2_Parse + +#else + +#define CSR2_FREE_ALL(data, heap) +#define CSR2_GET_SIZE(a, b) 0 +#define CSR2_WRITE(a, b, c) 0 +#define CSR2_PARSE(a, b, c, d) 0 + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + +/******************************************************************************/ +/* Supported Elliptic Curves */ +/******************************************************************************/ + +#ifdef HAVE_SUPPORTED_CURVES + +#if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448) \ + && !defined(HAVE_FFDHE) +#error Elliptic Curves Extension requires Elliptic Curve Cryptography. \ + Use --enable-ecc in the configure script or define HAVE_ECC. \ + Alternatively use FFDHE for DH ciperhsuites. +#endif + +static int TLSX_SupportedCurve_New(SupportedCurve** curve, word16 name, + void* heap) +{ + if (curve == NULL) + return BAD_FUNC_ARG; + + (void)heap; + + *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; + + (void)heap; + + *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; + XFREE(curve, heap, DYNAMIC_TYPE_TLSX); + } + (void)heap; +} + +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) +{ + int ret = BAD_FUNC_ARG; + + while (list) { + if (list->name == name) { + ret = 0; /* curve already in use */ + break; + } + + if (list->next == NULL) { + ret = TLSX_SupportedCurve_New(&list->next, name, heap); + break; + } + + list = list->next; + } + + return ret; +} + +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; +} + +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT) + +static void TLSX_SupportedCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore) +{ + word16 i; + + for (i = 0; i < ssl->suites->suiteSz; i+= 2) { + if (ssl->suites->suites[i] == TLS13_BYTE) + return; + if (ssl->suites->suites[i] == ECC_BYTE || + ssl->suites->suites[i] == CHACHA_BYTE) { + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + return; + #endif + } + else { + #ifdef HAVE_FFDHE + return; + #endif + } + } + + /* turns semaphore on to avoid sending this extension. */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS)); +} + +static void TLSX_PointFormat_ValidateRequest(WOLFSSL* ssl, byte* semaphore) +{ + word16 i; + + for (i = 0; i < ssl->suites->suiteSz; i+= 2) { + if (ssl->suites->suites[i] == TLS13_BYTE) + return; + if (ssl->suites->suites[i] == ECC_BYTE || + ssl->suites->suites[i] == CHACHA_BYTE) { + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + return; + #endif + } + else { + #ifdef HAVE_FFDHE + return; + #endif + } + } + + /* 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 defined(HAVE_FFDHE) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + (void)semaphore; +#endif + + if (ssl->options.cipherSuite0 == TLS13_BYTE) + return; + if (ssl->options.cipherSuite0 == ECC_BYTE || + ssl->options.cipherSuite0 == CHACHA_BYTE) { +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) + return; +#endif + } + else { +#ifdef HAVE_FFDHE + return; +#endif + } + +#if !defined(HAVE_FFDHE) || (!defined(HAVE_ECC) && !defined(HAVE_CURVE25519) \ + && !defined(HAVE_CURVE448)) + /* turns semaphore on to avoid sending this extension. */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); +#endif +} + +#endif +#ifndef NO_WOLFSSL_CLIENT + +static word16 TLSX_SupportedCurve_GetSize(SupportedCurve* list) +{ + SupportedCurve* curve; word16 length = OPAQUE16_LEN; /* list length */ while ((curve = list)) { @@ -1428,40 +3912,71 @@ 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 /* NO_WOLFSSL_CLIENT */ -#ifndef NO_WOLFSSL_SERVER +#endif -static int TLSX_EllipticCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, +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; +} + +#if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) + +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)) { +#ifdef WOLFSSL_ALLOW_SERVER_SC_EXT + return 0; +#else + return BUFFER_ERROR; /* servers doesn't send this extension. */ +#endif + } if (OPAQUE16_LEN > length || length % OPAQUE16_LEN) return BUFFER_ERROR; @@ -1472,201 +3987,751 @@ static int TLSX_EllipticCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, if (length != OPAQUE16_LEN + offset) return BUFFER_ERROR; - while (offset) { + offset = OPAQUE16_LEN; + if (offset == length) + return 0; + +#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) + if (!isRequest) { + TLSX* extension; + SupportedCurve* curve; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + if (extension != NULL) { + /* Replace client list with server list of supported groups. */ + curve = (SupportedCurve*)extension->data; + extension->data = NULL; + TLSX_SupportedCurve_FreeAll(curve, ssl->heap); + + ato16(input + offset, &name); + offset += OPAQUE16_LEN; + + ret = TLSX_SupportedCurve_New(&curve, name, ssl->heap); + if (ret != 0) + return ret; /* throw error */ + extension->data = (void*)curve; + } + } +#endif + + for (; offset < length; offset += OPAQUE16_LEN) { ato16(input + offset, &name); - offset -= OPAQUE16_LEN; - r = TLSX_UseSupportedCurve(&ssl->extensions, name); - - 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) { - TLSX* extension = (first == ECC_BYTE) - ? TLSX_Find(ssl->extensions, ELLIPTIC_CURVES) - : NULL; - EllipticCurve* curve = NULL; - word32 oid = 0; - word16 octets = 0; /* acording to 'ecc_set_type ecc_sets[];' */ - int sig = 0; /* valitade signature */ - int key = 0; /* validate key */ +#endif + +#if !defined(NO_WOLFSSL_SERVER) + +#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) + +/* Checks the priority of the groups on the server and set the supported groups + * response if there is a group not advertised by the client that is preferred. + * + * ssl SSL/TLS object. + * returns 0 on success, otherwise an error. + */ +int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl) +{ + int ret; + TLSX* extension; + TLSX* priority = NULL; + TLSX* ext = NULL; + word16 name; + SupportedCurve* curve; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + /* May be doing PSK with no key exchange. */ + if (extension == NULL) + return 0; + + if ((ret = TLSX_PopulateSupportedGroups(ssl, &priority)) != WOLFSSL_SUCCESS) + return ret; + + ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS); + curve = (SupportedCurve*)ext->data; + name = curve->name; + + curve = (SupportedCurve*)extension->data; + while (curve != NULL) { + if (curve->name == name) + break; + curve = curve->next; + } + + if (curve == NULL) { + /* Couldn't find the preferred group in client list. */ + extension->resp = 1; + + /* Send server list back and free client list. */ + curve = (SupportedCurve*)extension->data; + extension->data = ext->data; + ext->data = curve; + } + + TLSX_FreeAll(priority, ssl->heap); + + return 0; +} + +#endif + +#if defined(HAVE_FFDHE) && !defined(WOLFSSL_NO_TLS12) +/* Set the highest priority common FFDHE group on the server as compared to + * client extensions. + * + * ssl SSL/TLS object. + * returns 0 on success, otherwise an error. + */ +int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl) +{ + int ret = 0; + TLSX* extension; + TLSX* priority = NULL; + TLSX* ext = NULL; + SupportedCurve* serverGroup; + SupportedCurve* clientGroup; + SupportedCurve* group; + const DhParams* params = NULL; + int found = 0; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + /* May be doing PSK with no key exchange. */ + if (extension == NULL) + return 0; + clientGroup = (SupportedCurve*)extension->data; + for (group = clientGroup; group != NULL; group = group->next) { + if (group->name >= MIN_FFHDE_GROUP && group->name <= MAX_FFHDE_GROUP) { + found = 1; + break; + } + } + if (!found) + return 0; + + if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + ssl->buffers.serverDH_P.buffer = NULL; + ssl->buffers.serverDH_G.buffer = NULL; + ssl->buffers.weOwnDH = 0; + ssl->options.haveDH = 0; + + + if ((ret = TLSX_PopulateSupportedGroups(ssl, &priority)) != WOLFSSL_SUCCESS) + return ret; + ret = 0; + + ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS); + serverGroup = (SupportedCurve*)ext->data; + + for (; serverGroup != NULL; serverGroup = serverGroup->next) { + if ((serverGroup->name & NAMED_DH_MASK) != NAMED_DH_MASK) + continue; + + for (group = clientGroup; group != NULL; group = group->next) { + if (serverGroup->name != group->name) + continue; + + switch (serverGroup->name) { + #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 + } + if (params == NULL) + return BAD_FUNC_ARG; + if (params->p_len >= ssl->options.minDhKeySz && + params->p_len <= ssl->options.maxDhKeySz) { + break; + } + } + + if (group != NULL && serverGroup->name == group->name) + break; + } + + if (serverGroup) { + ssl->buffers.serverDH_P.buffer = (unsigned char *)params->p; + ssl->buffers.serverDH_P.length = params->p_len; + ssl->buffers.serverDH_G.buffer = (unsigned char *)params->g; + ssl->buffers.serverDH_G.length = params->g_len; + ssl->namedGroup = serverGroup->name; + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \ + !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + ssl->options.dhDoKeyTest = 0; + #endif + ssl->options.haveDH = 1; + } + + TLSX_FreeAll(priority, ssl->heap); + + return ret; +} +#endif /* HAVE_FFDHE && !WOLFSSL_NO_TLS12 */ + +#endif /* !NO_WOLFSSL_SERVER */ + +#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) +/* Return the preferred group. + * + * ssl SSL/TLS object. + * checkSupported Whether to check for the first supported group. + * returns BAD_FUNC_ARG if no group found, otherwise the group. + */ +int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl, int checkSupported) +{ + TLSX* extension; + SupportedCurve* curve; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + if (extension == NULL) + return BAD_FUNC_ARG; + + curve = (SupportedCurve*)extension->data; + while (curve != NULL) { + if (!checkSupported || TLSX_KeyShare_IsSupported(curve->name)) + return curve->name; + curve = curve->next; + } + + return BAD_FUNC_ARG; +} + +#endif + +#ifndef NO_WOLFSSL_SERVER + +static int TLSX_PointFormat_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + int ret; + + /* validating formats list length */ + if (ENUM_LEN > length || length != (word16)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; +} + +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) +int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second) { + TLSX* extension = 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 (first == ECC_BYTE || first == CHACHA_BYTE) + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); if (!extension) return 1; /* no suite restriction */ - for (curve = extension->data; curve && !(sig && key); curve = curve->next) { + for (curve = (SupportedCurve*)extension->data; + curve && !(sig && key); + curve = curve->next) { + #ifdef OPENSSL_EXTRA + /* skip if name is not in supported ECC range */ + if (curve->name > WOLFSSL_ECC_X448) + continue; + /* skip if curve is disabled by user */ + if (ssl->ctx->disabledCurves & (1 << curve->name)) + continue; + #endif + + /* find supported curve */ switch (curve->name) { -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) - case WOLFSSL_ECC_SECP160R1: oid = ECC_160R1; octets = 20; break; +#ifdef HAVE_ECC + #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP160R1: + pkOid = oid = ECC_SECP160R1_OID; + octets = 20; + break; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + case WOLFSSL_ECC_SECP160R2: + pkOid = oid = ECC_SECP160R2_OID; + octets = 20; + break; + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_KOBLITZ + 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: + pkOid = oid = ECC_SECP192R1_OID; + octets = 24; + break; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + 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: + pkOid = oid = ECC_SECP224R1_OID; + octets = 28; + break; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + 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) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + pkOid = oid = ECC_SECP256R1_OID; + octets = 32; + break; + #endif /* !NO_ECC_SECP */ + #endif /* !NO_ECC256 || HAVE_ALL_CURVES */ #endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) - case WOLFSSL_ECC_SECP192R1: oid = ECC_192R1; octets = 24; break; + #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 + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP256K1: + pkOid = oid = ECC_SECP256K1_OID; + octets = 32; + break; + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + case WOLFSSL_ECC_BRAINPOOLP256R1: + pkOid = oid = ECC_BRAINPOOLP256R1_OID; + octets = 32; + break; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif #endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) - case WOLFSSL_ECC_SECP224R1: oid = ECC_224R1; octets = 28; break; -#endif -#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) - case WOLFSSL_ECC_SECP256R1: oid = ECC_256R1; octets = 32; break; -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) - case WOLFSSL_ECC_SECP384R1: oid = ECC_384R1; octets = 48; break; -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) - case WOLFSSL_ECC_SECP521R1: oid = ECC_521R1; octets = 66; break; + #ifdef HAVE_CURVE448 + case WOLFSSL_ECC_X448: + oid = ECC_X448_OID; + #ifdef HAVE_ED448 + pkOid = ECC_ED448_OID; + #else + pkOid = ECC_X448_OID; + #endif + octets = 57; + break; + #endif /* HAVE_CURVE448 */ +#ifdef HAVE_ECC + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + pkOid = oid = ECC_SECP384R1_OID; + octets = 48; + break; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_BRAINPOOL + 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: + 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: + pkOid = oid = ECC_SECP521R1_OID; + octets = 66; + break; + #endif /* !NO_ECC_SECP */ + #endif #endif default: continue; /* unsupported curve */ } - switch (second) { -#ifndef NO_DSA - /* 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; + #ifdef HAVE_ECC + /* Set default Oid */ + if (defOid == 0 && ssl->eccTempKeySz <= octets && defSz > octets) { + defOid = oid; + defSz = octets; + } - /* 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; -#endif + /* The eccTempKeySz is the preferred ephemeral key size */ + if (currOid == 0 && ssl->eccTempKeySz == octets) + currOid = oid; + if ((nextOid == 0 || nextSz > octets) && ssl->eccTempKeySz <= octets) { + nextOid = oid; + nextSz = octets; + } + #else + if (defOid == 0 && defSz > octets) { + defOid = oid; + defSz = octets; + } + + if (currOid == 0) + currOid = oid; + if (nextOid == 0 || nextSz > octets) { + nextOid = oid; + nextSz = octets; + } + #endif + + 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 == 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: + if (oid == ECC_X25519_OID && defOid == oid) { + defOid = 0; + defSz = 80; + } + if (oid == ECC_X448_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; - /* 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; +#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: + if (oid == ECC_X25519_OID && defOid == oid) { + defOid = 0; + defSz = 80; + } + if (oid == ECC_X448_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_X448_OID && defOid == oid) { + defOid = 0; + defSz = 80; + } + if (oid != ECC_X25519_OID && oid != ECC_X448_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 == 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->ecdhCurveOID == oid; + ephmSuite = 1; + break; +#endif + default: + sig = 1; + key = 1; + break; + } } } + /* Choose the default if it is at the required strength. */ +#ifdef HAVE_ECC + if (ssl->ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz) +#else + if (ssl->ecdhCurveOID == 0) +#endif + { + 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) +int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) { - TLSX* extension = TLSX_Find(*extensions, ELLIPTIC_CURVES); - EllipticCurve* curve = NULL; - int ret = 0; + TLSX* extension = NULL; + SupportedCurve* curve = NULL; + int ret; if (extensions == NULL) return BAD_FUNC_ARG; - if ((ret = TLSX_EllipticCurve_Append(&curve, name)) != 0) - return ret; + extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS); if (!extension) { - if ((ret = TLSX_Push(extensions, ELLIPTIC_CURVES, curve)) != 0) { - XFREE(curve, 0, DYNAMIC_TYPE_TLSX); + 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, 0, 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 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 +#if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) +#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) +#define EC_FREE_ALL(list, heap) #define EC_GET_SIZE(list) 0 #define EC_WRITE(a, b) 0 #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 */ -#ifdef HAVE_SECURE_RENEGOTIATION +/******************************************************************************/ +/* Renegotiation Indication */ +/******************************************************************************/ + +#if defined(HAVE_SECURE_RENEGOTIATION) \ + || defined(HAVE_SERVER_RENEGOTIATION_INFO) static byte TLSX_SecureRenegotiation_GetSize(SecureRenegotiation* data, int isRequest) { byte length = OPAQUE8_LEN; /* empty info length */ - if (data->enabled) { + /* data will be NULL for HAVE_SERVER_RENEGOTIATION_INFO only */ + if (data && data->enabled && data->verifySet) { /* client sends client_verify_data only */ length += TLS_FINISHED_SZ; @@ -1682,8 +4747,7 @@ static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data, byte* output, int isRequest) { word16 offset = OPAQUE8_LEN; /* RenegotiationInfo length */ - - if (data->enabled) { + if (data && data->enabled && data->verifySet) { /* client sends client_verify_data only */ XMEMCPY(output + offset, data->client_verify_data, TLS_FINISHED_SZ); offset += TLS_FINISHED_SZ; @@ -1695,7 +4759,7 @@ static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data, } } - output[0] = offset - 1; /* info length - self */ + output[0] = (byte)(offset - 1); /* info length - self */ return offset; } @@ -1706,18 +4770,48 @@ static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, byte* input, int ret = SECURE_RENEGOTIATION_E; if (length >= OPAQUE8_LEN) { - if (ssl->secure_renegotiation == NULL) { + if (isRequest) { #ifndef NO_WOLFSSL_SERVER - if (isRequest && *input == 0) { - ret = 0; /* don't reply, user didn't enable */ + if (ssl->secure_renegotiation == NULL) { + ret = wolfSSL_UseSecureRenegotiation(ssl); + if (ret == WOLFSSL_SUCCESS) + ret = 0; } - #endif - } - else if (isRequest) { - #ifndef NO_WOLFSSL_SERVER - if (*input == TLS_FINISHED_SZ) { - /* TODO compare client_verify_data */ - ret = 0; + if (ret != 0 && ret != SECURE_RENEGOTIATION_E) { + } + else if (!ssl->secure_renegotiation->enabled) { + if (*input == 0) { + input++; /* get past size */ + + ssl->secure_renegotiation->enabled = 1; + TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO); + ret = 0; + } + else { + /* already in error state */ + WOLFSSL_MSG("SCR client verify data present"); + } + } + else if (*input == TLS_FINISHED_SZ) { + if (length < TLS_FINISHED_SZ + 1) { + WOLFSSL_MSG("SCR malformed buffer"); + ret = BUFFER_E; + } + else { + input++; /* get past size */ + + /* validate client verify data */ + if (XMEMCMP(input, + ssl->secure_renegotiation->client_verify_data, + TLS_FINISHED_SZ) == 0) { + WOLFSSL_MSG("SCR client verify data match"); + TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO); + ret = 0; /* verified */ + } else { + /* already in error state */ + WOLFSSL_MSG("SCR client verify data Failure"); + } + } } #endif } @@ -1729,73 +4823,116 @@ static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, byte* input, ret = 0; } } - else if (*input == 2 * TLS_FINISHED_SZ) { - /* TODO compare client_verify_data and server_verify_data */ - ret = 0; + else if (*input == 2 * TLS_FINISHED_SZ && + length == 2 * TLS_FINISHED_SZ + OPAQUE8_LEN) { + input++; /* get past size */ + + /* validate client and server verify data */ + if (XMEMCMP(input, + ssl->secure_renegotiation->client_verify_data, + TLS_FINISHED_SZ) == 0 && + XMEMCMP(input + TLS_FINISHED_SZ, + ssl->secure_renegotiation->server_verify_data, + TLS_FINISHED_SZ) == 0) { + WOLFSSL_MSG("SCR client and server verify data match"); + ret = 0; /* verified */ + } else { + /* already in error state */ + WOLFSSL_MSG("SCR client and server verify data Failure"); + } } #endif } } if (ret != 0) { - /* TODO: turn on fatal error at ssl level too */ SendAlert(ssl, alert_fatal, handshake_failure); } return ret; } -int TLSX_UseSecureRenegotiation(TLSX** extensions) +int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap) { int ret = 0; - SecureRenegotiation* data = NULL; + SecureRenegotiation* data; - data = (SecureRenegotiation*)XMALLOC(sizeof(SecureRenegotiation), NULL, + data = (SecureRenegotiation*)XMALLOC(sizeof(SecureRenegotiation), heap, DYNAMIC_TYPE_TLSX); if (data == NULL) return MEMORY_E; XMEMSET(data, 0, sizeof(SecureRenegotiation)); - ret = TLSX_Push(extensions, SECURE_RENEGOTIATION, data); + ret = TLSX_Push(extensions, TLSX_RENEGOTIATION_INFO, data, heap); if (ret != 0) { - XFREE(data, 0, DYNAMIC_TYPE_TLSX); + XFREE(data, heap, DYNAMIC_TYPE_TLSX); return ret; } - return SSL_SUCCESS; + return WOLFSSL_SUCCESS; } +#ifdef HAVE_SERVER_RENEGOTIATION_INFO -#define SCR_FREE_ALL(data) XFREE(data, NULL, DYNAMIC_TYPE_TLSX) +int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap) +{ + int ret; + + /* send empty renegotiation_info extension */ + TLSX* ext = TLSX_Find(*extensions, TLSX_RENEGOTIATION_INFO); + if (ext == NULL) { + ret = TLSX_UseSecureRenegotiation(extensions, heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + + ext = TLSX_Find(*extensions, TLSX_RENEGOTIATION_INFO); + } + if (ext) + ext->resp = 1; + + return WOLFSSL_SUCCESS; +} + +#endif /* HAVE_SERVER_RENEGOTIATION_INFO */ + + +#define SCR_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX) #define SCR_GET_SIZE TLSX_SecureRenegotiation_GetSize #define SCR_WRITE TLSX_SecureRenegotiation_Write #define SCR_PARSE TLSX_SecureRenegotiation_Parse #else -#define SCR_FREE_ALL(a) +#define SCR_FREE_ALL(a, heap) #define SCR_GET_SIZE(a, b) 0 #define SCR_WRITE(a, b, c) 0 #define SCR_PARSE(a, b, c, d) 0 #endif /* HAVE_SECURE_RENEGOTIATION */ +/******************************************************************************/ +/* Session Tickets */ +/******************************************************************************/ + #ifdef HAVE_SESSION_TICKET +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT) static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl) { - TLSX* extension = TLSX_Find(ssl->extensions, SESSION_TICKET); - SessionTicket* ticket = extension ? extension->data : NULL; + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_SESSION_TICKET); + SessionTicket* ticket = extension ? + (SessionTicket*)extension->data : NULL; if (ticket) { /* TODO validate ticket timeout here! */ if (ticket->lifetime == 0xfffffff) { /* send empty ticket on timeout */ - TLSX_UseSessionTicket(&ssl->extensions, NULL); + TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap); } } } +#endif /* WLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */ static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest) @@ -1823,12 +4960,18 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, { int ret = 0; + (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 { @@ -1840,26 +4983,28 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, if (length == 0) { /* blank ticket */ - ret = TLSX_UseSessionTicket(&ssl->extensions, NULL); - if (ret == SSL_SUCCESS) { + ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap); + if (ret == WOLFSSL_SUCCESS) { ret = 0; - TLSX_SetResponse(ssl, SESSION_TICKET); /* send blank ticket */ + TLSX_SetResponse(ssl, TLSX_SESSION_TICKET); /* send blank ticket */ ssl->options.createTicket = 1; /* will send ticket msg */ ssl->options.useTicket = 1; + ssl->options.resuming = 0; /* no standard resumption */ + ssl->arrays->sessionIDSz = 0; /* no echo on blank ticket */ } } else { /* got actual ticket from client */ ret = DoClientTicket(ssl, input, length); if (ret == WOLFSSL_TICKET_RET_OK) { /* use ticket to resume */ - WOLFSSL_MSG("Using exisitng client ticket"); + WOLFSSL_MSG("Using existing client ticket"); ssl->options.useTicket = 1; ssl->options.resuming = 1; } else if (ret == WOLFSSL_TICKET_RET_CREATE) { WOLFSSL_MSG("Using existing client ticket, creating new one"); - ret = TLSX_UseSessionTicket(&ssl->extensions, NULL); - if (ret == SSL_SUCCESS) { + ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap); + if (ret == WOLFSSL_SUCCESS) { ret = 0; - TLSX_SetResponse(ssl, SESSION_TICKET); + TLSX_SetResponse(ssl, TLSX_SESSION_TICKET); /* send blank ticket */ ssl->options.createTicket = 1; /* will send ticket msg */ ssl->options.useTicket = 1; @@ -1867,6 +5012,7 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, } } else if (ret == WOLFSSL_TICKET_RET_REJECT) { WOLFSSL_MSG("Process client ticket rejected, not using"); + ssl->options.rejectTicket = 1; ret = 0; /* not fatal */ } else if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) { WOLFSSL_MSG("Process client ticket fatal error, not using"); @@ -1879,14 +5025,14 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, } WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime, - byte* data, word16 size) + byte* data, word16 size, void* heap) { SessionTicket* ticket = (SessionTicket*)XMALLOC(sizeof(SessionTicket), - NULL, DYNAMIC_TYPE_TLSX); + heap, DYNAMIC_TYPE_TLSX); if (ticket) { - ticket->data = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TLSX); + ticket->data = (byte*)XMALLOC(size, heap, DYNAMIC_TYPE_TLSX); if (ticket->data == NULL) { - XFREE(ticket, NULL, DYNAMIC_TYPE_TLSX); + XFREE(ticket, heap, DYNAMIC_TYPE_TLSX); return NULL; } @@ -1895,17 +5041,21 @@ WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime, ticket->lifetime = lifetime; } + (void)heap; + return ticket; } -WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket) +WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap) { if (ticket) { - XFREE(ticket->data, NULL, DYNAMIC_TYPE_TLSX); - XFREE(ticket, NULL, DYNAMIC_TYPE_TLSX); + XFREE(ticket->data, heap, DYNAMIC_TYPE_TLSX); + XFREE(ticket, heap, DYNAMIC_TYPE_TLSX); } + + (void)heap; } -int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket) +int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket, void* heap) { int ret = 0; @@ -1914,27 +5064,4009 @@ int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket) /* If the ticket is NULL, the client will request a new ticket from the server. Otherwise, the client will use it in the next client hello. */ - if ((ret = TLSX_Push(extensions, SESSION_TICKET, (void*)ticket)) != 0) + if ((ret = TLSX_Push(extensions, TLSX_SESSION_TICKET, (void*)ticket, 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 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_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 */ +/******************************************************************************/ +/* Quantum-Safe-Hybrid */ +/******************************************************************************/ +#ifdef HAVE_QSH +#if defined(HAVE_NTRU) +static WC_RNG* gRng; +static wolfSSL_Mutex* gRngMutex; +#endif + +static void TLSX_QSH_FreeAll(QSHScheme* list, void* heap) +{ + QSHScheme* current; + + while ((current = list)) { + list = current->next; + XFREE(current, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +static int TLSX_QSH_Append(QSHScheme** list, word16 name, byte* pub, + word16 pubLen) +{ + QSHScheme* temp; + + if (list == NULL) + return BAD_FUNC_ARG; + + if ((temp = (QSHScheme*)XMALLOC(sizeof(QSHScheme), NULL, + DYNAMIC_TYPE_TLSX)) == NULL) + return MEMORY_E; + + temp->name = name; + temp->PK = pub; + temp->PKLen = pubLen; + temp->next = *list; + + *list = temp; + + return 0; +} + + +/* request for server's public key : 02 indicates 0-2 requested */ +static byte TLSX_QSH_SerPKReq(byte* output, byte isRequest) +{ + if (isRequest) { + /* only request one public key from the server */ + output[0] = 0x01; + + return OPAQUE8_LEN; + } + else { + return 0; + } +} + +#ifndef NO_WOLFSSL_CLIENT + +/* check for TLS_QSH suite */ +static void TLSX_QSH_ValidateRequest(WOLFSSL* ssl, byte* semaphore) +{ + int i; + + for (i = 0; i < ssl->suites->suiteSz; i+= 2) + if (ssl->suites->suites[i] == QSH_BYTE) + return; + + /* No QSH suite found */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_QUANTUM_SAFE_HYBRID)); +} + + +/* return the size of the QSH hello extension + list the list of QSHScheme structs containing id and key + isRequest if 1 then is being sent to the server + */ +word16 TLSX_QSH_GetSize(QSHScheme* list, byte isRequest) +{ + QSHScheme* temp = list; + word16 length = 0; + + /* account for size of scheme list and public key list */ + if (isRequest) + length = OPAQUE16_LEN; + length += OPAQUE24_LEN; + + /* for each non null element in list add size */ + while ((temp)) { + /* add public key info Scheme | Key Length | Key */ + length += OPAQUE16_LEN; + length += OPAQUE16_LEN; + length += temp->PKLen; + + /* if client add name size for scheme list + advance to next QSHScheme struct in list */ + if (isRequest) + length += OPAQUE16_LEN; + temp = temp->next; + } + + /* add length for request server public keys */ + if (isRequest) + length += OPAQUE8_LEN; + + return length; +} + + +/* write out a list of QSHScheme IDs */ +static word16 TLSX_QSH_Write(QSHScheme* list, byte* output) +{ + QSHScheme* current = list; + word16 length = 0; + + length += OPAQUE16_LEN; + + while (current) { + c16toa(current->name, output + length); + length += OPAQUE16_LEN; + current = (QSHScheme*)current->next; + } + + c16toa(length - OPAQUE16_LEN, output); /* writing list length */ + + return length; +} + + +/* write public key list in extension */ +static word16 TLSX_QSHPK_WriteR(QSHScheme* format, byte* output) +{ + word32 offset = 0; + word16 public_len = 0; + + if (!format) + return offset; + + /* write scheme ID */ + c16toa(format->name, output + offset); + offset += OPAQUE16_LEN; + + /* write public key matching scheme */ + public_len = format->PKLen; + c16toa(public_len, output + offset); + offset += OPAQUE16_LEN; + if (format->PK) { + XMEMCPY(output+offset, format->PK, public_len); + } + + return public_len + offset; +} + +word16 TLSX_QSHPK_Write(QSHScheme* list, byte* output) +{ + QSHScheme* current = list; + word32 length = 0; + word24 toWire; + + length += OPAQUE24_LEN; + + while (current) { + length += TLSX_QSHPK_WriteR(current, output + length); + current = (QSHScheme*)current->next; + } + /* length of public keys sent */ + c32to24(length - OPAQUE24_LEN, toWire); + output[0] = toWire[0]; + output[1] = toWire[1]; + output[2] = toWire[2]; + + return length; +} + +#endif /* NO_WOLFSSL_CLIENT */ +#ifndef NO_WOLFSSL_SERVER + +static void TLSX_QSHAgreement(TLSX** extensions, void* heap) +{ + TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); + QSHScheme* format = NULL; + QSHScheme* del = NULL; + QSHScheme* prev = NULL; + + if (extension == NULL) + return; + + format = (QSHScheme*)extension->data; + while (format) { + if (format->PKLen == 0) { + /* case of head */ + if (format == extension->data) { + extension->data = format->next; + } + if (prev) + prev->next = format->next; + del = format; + format = format->next; + XFREE(del, heap, DYNAMIC_TYPE_TMP_BUFFER); + del = NULL; + } else { + prev = format; + format = format->next; + } + } + + (void)heap; +} + + +/* Parse in hello extension + input the byte stream to process + length length of total extension found + isRequest set to 1 if being sent to the server + */ +static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + byte numKeys = 0; + word16 offset = 0; + word16 schemSz = 0; + word16 offset_len = 0; + word32 offset_pk = 0; + word16 name = 0; + word16 PKLen = 0; + byte* PK = NULL; + int r; + + + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + if (isRequest) { + ato16(input, &schemSz); + + /* list of public keys available for QSH schemes */ + offset_len = schemSz + OPAQUE16_LEN; + } + + offset_pk = ((input[offset_len] << 16) & 0xFF00000) | + (((input[offset_len + 1]) << 8) & 0xFF00) | + (input[offset_len + 2] & 0xFF); + offset_len += OPAQUE24_LEN; + + /* check buffer size */ + if (offset_pk > length) + return BUFFER_ERROR; + + /* set maximum number of keys the client will accept */ + if (!isRequest) + numKeys = (ssl->maxRequest < 1)? 1 : ssl->maxRequest; + + /* hello extension read list of scheme ids */ + if (isRequest) { + + /* read in request for public keys */ + ssl->minRequest = (input[length -1] >> 4) & 0xFF; + ssl->maxRequest = input[length -1] & 0x0F; + + /* choose the min between min requested by client and 1 */ + numKeys = (ssl->minRequest > 1) ? ssl->minRequest : 1; + + if (ssl->minRequest > ssl->maxRequest) + return BAD_FUNC_ARG; + + offset += OPAQUE16_LEN; + schemSz += offset; + + /* check buffer size */ + if (schemSz > length) + return BUFFER_ERROR; + + while ((offset < schemSz) && numKeys) { + /* Scheme ID list */ + ato16(input + offset, &name); + offset += OPAQUE16_LEN; + + /* validate we have scheme id */ + if (ssl->user_set_QSHSchemes && + !TLSX_ValidateQSHScheme(&ssl->extensions, name)) { + continue; + } + + /* server create keys on demand */ + if ((r = TLSX_CreateNtruKey(ssl, name)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return r; + } + + /* peer sent an agreed upon scheme */ + r = TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0, ssl->heap); + + if (r != WOLFSSL_SUCCESS) return r; /* throw error */ + + numKeys--; + } + + /* choose the min between min requested by client and 1 */ + numKeys = (ssl->minRequest > 1) ? ssl->minRequest : 1; + } + + /* QSHPK struct */ + offset_pk += offset_len; + while ((offset_len < offset_pk) && numKeys) { + QSHKey * temp; + + if ((temp = (QSHKey*)XMALLOC(sizeof(QSHKey), ssl->heap, + DYNAMIC_TYPE_TLSX)) == NULL) + return MEMORY_E; + + /* initialize */ + temp->next = NULL; + temp->pub.buffer = NULL; + temp->pub.length = 0; + temp->pri.buffer = NULL; + temp->pri.length = 0; + + /* scheme id */ + ato16(input + offset_len, &(temp->name)); + offset_len += OPAQUE16_LEN; + + /* public key length */ + ato16(input + offset_len, &PKLen); + temp->pub.length = PKLen; + offset_len += OPAQUE16_LEN; + + + if (isRequest) { + /* validate we have scheme id */ + if (ssl->user_set_QSHSchemes && + (!TLSX_ValidateQSHScheme(&ssl->extensions, temp->name))) { + offset_len += PKLen; + XFREE(temp, ssl->heap, DYNAMIC_TYPE_TLSX); + continue; + } + } + + /* read in public key */ + if (PKLen > 0) { + temp->pub.buffer = (byte*)XMALLOC(temp->pub.length, + ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XMEMCPY(temp->pub.buffer, input + offset_len, temp->pub.length); + offset_len += PKLen; + } + else { + PK = NULL; + } + + /* use own key when adding to extensions list for sending reply */ + PKLen = 0; + PK = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, &PKLen, temp->name); + r = TLSX_UseQSHScheme(&ssl->extensions, temp->name, PK, PKLen, + ssl->heap); + + /* store peers key */ + ssl->peerQSHKeyPresent = 1; + if (TLSX_AddQSHKey(&ssl->peerQSHKey, temp) != 0) + return MEMORY_E; + + if (temp->pub.length == 0) { + XFREE(temp, ssl->heap, DYNAMIC_TYPE_TLSX); + } + + if (r != WOLFSSL_SUCCESS) {return r;} /* throw error */ + + numKeys--; + } + + /* reply to a QSH extension sent from client */ + if (isRequest) { + TLSX_SetResponse(ssl, TLSX_QUANTUM_SAFE_HYBRID); + /* only use schemes we have key generated for -- free the rest */ + TLSX_QSHAgreement(&ssl->extensions, ssl->heap); + } + + return 0; +} + + +/* Used for parsing in QSHCipher structs on Key Exchange */ +int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isServer) +{ + QSHKey* key; + word16 Max_Secret_Len = 48; + word16 offset = 0; + word16 offset_len = 0; + word32 offset_pk = 0; + word16 name = 0; + word16 secretLen = 0; + byte* secret = NULL; + word16 buffLen = 0; + byte buff[145]; /* size enough for 3 secrets */ + buffer* buf; + + /* pointer to location where secret should be stored */ + if (isServer) { + buf = ssl->QSH_secret->CliSi; + } + else { + buf = ssl->QSH_secret->SerSi; + } + + offset_pk = ((input[offset_len] << 16) & 0xFF0000) | + (((input[offset_len + 1]) << 8) & 0xFF00) | + (input[offset_len + 2] & 0xFF); + offset_len += OPAQUE24_LEN; + + /* validating extension list length -- check if trying to read over edge + of buffer */ + if (length < (offset_pk + OPAQUE24_LEN)) { + return BUFFER_ERROR; + } + + /* QSHCipherList struct */ + offset_pk += offset_len; + while (offset_len < offset_pk) { + + /* scheme id */ + ato16(input + offset_len, &name); + offset_len += OPAQUE16_LEN; + + /* public key length */ + ato16(input + offset_len, &secretLen); + offset_len += OPAQUE16_LEN; + + /* read in public key */ + if (secretLen > 0) { + secret = (byte*)(input + offset_len); + offset_len += secretLen; + } + else { + secret = NULL; + } + + /* no secret sent */ + if (secret == NULL) + continue; + + /* find corresponding key */ + key = ssl->QSH_Key; + while (key) { + if (key->name == name) + break; + else + key = (QSHKey*)key->next; + } + + /* if we do not have the key than there was a big issue negotiation */ + if (key == NULL) { + WOLFSSL_MSG("key was null for decryption!!!\n"); + return MEMORY_E; + } + + /* Decrypt sent secret */ + buffLen = Max_Secret_Len; + QSH_Decrypt(key, secret, secretLen, buff + offset, &buffLen); + offset += buffLen; + } + + /* allocate memory for buffer */ + buf->length = offset; + buf->buffer = (byte*)XMALLOC(offset, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf->buffer == NULL) + return MEMORY_E; + + /* store secrets */ + XMEMCPY(buf->buffer, buff, offset); + ForceZero(buff, offset); + + return offset_len; +} + + +/* return 1 on success */ +int TLSX_ValidateQSHScheme(TLSX** extensions, word16 theirs) { + TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); + QSHScheme* format = NULL; + + /* if no extension is sent then do not use QSH */ + if (!extension) { + WOLFSSL_MSG("No QSH Extension"); + return 0; + } + + for (format = (QSHScheme*)extension->data; format; format = format->next) { + if (format->name == theirs) { + WOLFSSL_MSG("Found Matching QSH Scheme"); + return 1; /* have QSH */ + } + } + + return 0; +} +#endif /* NO_WOLFSSL_SERVER */ + +/* test if the QSH Scheme is implemented + return 1 if yes 0 if no */ +static int TLSX_HaveQSHScheme(word16 name) +{ + switch(name) { + #ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + return 1; + #endif + case WOLFSSL_LWE_XXX: + case WOLFSSL_HFE_XXX: + return 0; /* not supported yet */ + + default: + return 0; + } +} + + +/* Add a QSHScheme struct to list of usable ones */ +int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz, + void* heap) +{ + TLSX* extension = NULL; + QSHScheme* format = NULL; + int ret = 0; + + /* sanity check */ + if (extensions == NULL || (pKey == NULL && pkeySz != 0)) + return BAD_FUNC_ARG; + + extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); + + /* if scheme is implemented than add */ + if (TLSX_HaveQSHScheme(name)) { + if ((ret = TLSX_QSH_Append(&format, name, pKey, pkeySz)) != 0) + return ret; + + extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); + if (!extension) { + if ((ret = TLSX_Push(extensions, TLSX_QUANTUM_SAFE_HYBRID, format, + heap)) != 0) { + XFREE(format, 0, DYNAMIC_TYPE_TLSX); + return ret; + } + } + else { + /* push new QSH object to extension data. */ + format->next = (QSHScheme*)extension->data; + extension->data = (void*)format; + + /* look for another format of the same name to remove (replacement) */ + do { + if (format->next && (format->next->name == name)) { + QSHScheme* next = format->next; + + format->next = next->next; + XFREE(next, 0, DYNAMIC_TYPE_TLSX); + + break; + } + } while ((format = format->next)); + } + } + return WOLFSSL_SUCCESS; +} + +#define QSH_FREE_ALL TLSX_QSH_FreeAll +#define QSH_VALIDATE_REQUEST TLSX_QSH_ValidateRequest + +#ifndef NO_WOLFSSL_CLIENT +#define QSH_GET_SIZE TLSX_QSH_GetSize +#define QSH_WRITE TLSX_QSH_Write +#else +#define QSH_GET_SIZE(list, a) 0 +#define QSH_WRITE(a, b) 0 +#endif + +#ifndef NO_WOLFSSL_SERVER +#define QSH_PARSE TLSX_QSH_Parse +#else +#define QSH_PARSE(a, b, c, d) 0 +#endif + +#define QSHPK_WRITE TLSX_QSHPK_Write +#define QSH_SERREQ TLSX_QSH_SerPKReq +#else + +#define QSH_FREE_ALL(list, heap) +#define QSH_GET_SIZE(list, a) 0 +#define QSH_WRITE(a, b) 0 +#define QSH_PARSE(a, b, c, d) 0 +#define QSHPK_WRITE(a, b) 0 +#define QSH_SERREQ(a, b) 0 +#define QSH_VALIDATE_REQUEST(a, b) + +#endif /* HAVE_QSH */ + +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) +/******************************************************************************/ +/* Encrypt-then-MAC */ +/******************************************************************************/ + +#ifndef WOLFSSL_NO_TLS12 +static int TLSX_EncryptThenMac_Use(WOLFSSL* ssl); + +/** + * Get the size of the Encrypt-Then-MAC extension. + * + * msgType Type of message to put extension into. + * pSz Size of extension data. + * return SANITY_MSG_E when the message is not allowed to have extension and + * 0 otherwise. + */ +static int TLSX_EncryptThenMac_GetSize(byte msgType, word16* pSz) +{ + (void)pSz; + + if (msgType != client_hello && msgType != server_hello) { + return SANITY_MSG_E; + } + + /* Empty extension */ + + return 0; +} + +/** + * Write the Encrypt-Then-MAC extension. + * + * data Unused + * output Extension data buffer. Unused. + * msgType Type of message to put extension into. + * pSz Size of extension data. + * return SANITY_MSG_E when the message is not allowed to have extension and + * 0 otherwise. + */ +static int TLSX_EncryptThenMac_Write(void* data, byte* output, byte msgType, + word16* pSz) +{ + (void)data; + (void)output; + (void)pSz; + + if (msgType != client_hello && msgType != server_hello) { + return SANITY_MSG_E; + } + + /* Empty extension */ + + return 0; +} + +/** + * Parse the Encrypt-Then-MAC extension. + * + * ssl SSL object + * input Extension data buffer. + * length Length of this extension's data. + * msgType Type of message to extension appeared in. + * return SANITY_MSG_E when the message is not allowed to have extension, + * BUFFER_ERROR when the extension's data is invalid, + * MEMORY_E when unable to allocate memory and + * 0 otherwise. + */ +static int TLSX_EncryptThenMac_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + int ret; + + (void)input; + + if (msgType != client_hello && msgType != server_hello) { + return SANITY_MSG_E; + } + + /* Empty extension */ + if (length != 0) + return BUFFER_ERROR; + + if (msgType == client_hello) { + /* Check the user hasn't disallowed use of Encrypt-Then-Mac. */ + if (!ssl->options.disallowEncThenMac) { + ssl->options.encThenMac = 1; + /* Set the extension reply. */ + ret = TLSX_EncryptThenMac_Use(ssl); + if (ret != 0) + return ret; + TLSX_SetResponse(ssl, TLSX_ENCRYPT_THEN_MAC); + } + return 0; + } + + /* Server Hello */ + if (ssl->options.disallowEncThenMac) + return SANITY_MSG_E; + + ssl->options.encThenMac = 1; + return 0; + +} + +/** + * Add the Encrypt-Then-MAC extension to list. + * + * ssl SSL object + * return MEMORY_E when unable to allocate memory and 0 otherwise. + */ +static int TLSX_EncryptThenMac_Use(WOLFSSL* ssl) +{ + int ret = 0; + TLSX* extension; + + /* Find the Encrypt-Then-Mac extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_ENCRYPT_THEN_MAC); + if (extension == NULL) { + /* Push new Encrypt-Then-Mac extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_ENCRYPT_THEN_MAC, NULL, + ssl->heap); + if (ret != 0) + return ret; + } + + return 0; +} + +#define ETM_GET_SIZE TLSX_EncryptThenMac_GetSize +#define ETM_WRITE TLSX_EncryptThenMac_Write +#define ETM_PARSE TLSX_EncryptThenMac_Parse + +#else + +#define ETM_GET_SIZE(a, b) 0 +#define ETM_WRITE(a, b, c, d) 0 +#define ETM_PARSE(a, b, c, d) 0 + +#endif /* !WOLFSSL_NO_TLS12 */ + +#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */ + +/******************************************************************************/ +/* Supported Versions */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +/* Return the size of the SupportedVersions extension's data. + * + * data The SSL/TLS object. + * msgType The type of the message this extension is being written into. + * returns the length of data that will be in the extension. + */ +static int TLSX_SupportedVersions_GetSize(void* data, byte msgType, word16* pSz) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + if (msgType == client_hello) { + /* TLS v1.2 and TLS v1.3 */ + int cnt = 0; + + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0) + #endif + cnt++; + + if (ssl->options.downgrade) { +#ifndef WOLFSSL_NO_TLS12 + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0) + #endif + cnt++; +#endif + +#ifndef NO_OLD_TLS + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0) + #endif + cnt++; + #ifdef WOLFSSL_ALLOW_TLSV10 + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1) == 0) + #endif + cnt++; + #endif +#endif + } + + *pSz += (word16)(OPAQUE8_LEN + cnt * OPAQUE16_LEN); + } +#ifndef WOLFSSL_TLS13_DRAFT_18 + else if (msgType == server_hello || msgType == hello_retry_request) + *pSz += OPAQUE16_LEN; +#endif + else + return SANITY_MSG_E; + + return 0; +} + +/* Writes the SupportedVersions extension into the buffer. + * + * data The SSL/TLS object. + * output The buffer to write the extension into. + * msgType The type of the message this extension is being written into. + * returns the length of data that was written. + */ +static int TLSX_SupportedVersions_Write(void* data, byte* output, + byte msgType, word16* pSz) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + byte major; + byte* cnt; + + if (msgType == client_hello) { + major = ssl->ctx->method->version.major; + + + cnt = output++; + *cnt = 0; + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0) + #endif + { + *cnt += OPAQUE16_LEN; +#ifdef WOLFSSL_TLS13_DRAFT + /* The TLS draft major number. */ + *(output++) = TLS_DRAFT_MAJOR; + /* Version of draft supported. */ + *(output++) = TLS_DRAFT_MINOR; +#else + *(output++) = major; + *(output++) = (byte)TLSv1_3_MINOR; +#endif + } + if (ssl->options.downgrade) { +#ifndef WOLFSSL_NO_TLS12 + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0) + #endif + { + *cnt += OPAQUE16_LEN; + *(output++) = major; + *(output++) = (byte)TLSv1_2_MINOR; + } +#endif + +#ifndef NO_OLD_TLS + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0) + #endif + { + *cnt += OPAQUE16_LEN; + *(output++) = major; + *(output++) = (byte)TLSv1_1_MINOR; + } + #ifdef WOLFSSL_ALLOW_TLSV10 + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1) == 0) + #endif + { + *cnt += OPAQUE16_LEN; + *(output++) = major; + *(output++) = (byte)TLSv1_MINOR; + } + #endif +#endif + } + + *pSz += (word16)(OPAQUE8_LEN + *cnt); + } +#ifndef WOLFSSL_TLS13_DRAFT_18 + else if (msgType == server_hello || msgType == hello_retry_request) { + #ifdef WOLFSSL_TLS13_DRAFT + if (ssl->version.major == SSLv3_MAJOR && + ssl->version.minor == TLSv1_3_MINOR) { + output[0] = TLS_DRAFT_MAJOR; + output[1] = TLS_DRAFT_MINOR; + } + else + #endif + { + output[0] = ssl->version.major; + output[1] = ssl->version.minor; + } + + *pSz += OPAQUE16_LEN; + } +#endif + else + return SANITY_MSG_E; + + return 0; +} + +/* Parse the SupportedVersions extension. + * + * ssl The SSL/TLS object. + * input The buffer with 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, otherwise failure. + */ +static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, byte* input, + word16 length, byte msgType) +{ + ProtocolVersion pv = ssl->ctx->method->version; + int i; + int len; + byte major, minor; + int newMinor = 0; + int set = 0; + + if (msgType == client_hello) { + /* 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 != (word16)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]; + +#ifdef WOLFSSL_TLS13_DRAFT + if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) { + major = SSLv3_MAJOR; + minor = TLSv1_3_MINOR; + } +#else + if (major == TLS_DRAFT_MAJOR) + continue; +#endif + + if (major != pv.major) + continue; + + /* No upgrade allowed. */ + if (minor > ssl->version.minor) + continue; + /* Check downgrade. */ + if (minor < ssl->version.minor) { + if (!ssl->options.downgrade) + continue; + + if (minor < ssl->options.minDowngrade) + continue; + + if (newMinor == 0 && minor > ssl->options.oldMinor) { + /* Downgrade the version. */ + ssl->version.minor = minor; + } + } + + if (minor >= TLSv1_3_MINOR) { + if (!ssl->options.tls1_3) { + ssl->options.tls1_3 = 1; + TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, ssl, + ssl->heap); +#ifndef WOLFSSL_TLS13_DRAFT_18 + TLSX_SetResponse(ssl, TLSX_SUPPORTED_VERSIONS); +#endif + } + if (minor > newMinor) { + ssl->version.minor = minor; + newMinor = minor; + } + } + else if (minor > ssl->options.oldMinor) + ssl->options.oldMinor = minor; + + set = 1; + } + if (!set) { + #ifdef WOLFSSL_MYSQL_COMPATIBLE + SendAlert(ssl, alert_fatal, wc_protocol_version); + #else + SendAlert(ssl, alert_fatal, protocol_version); + #endif + return VERSION_ERROR; + } + } +#ifndef WOLFSSL_TLS13_DRAFT_18 + else if (msgType == server_hello || msgType == hello_retry_request) { + /* Must contain one version. */ + if (length != OPAQUE16_LEN) + return BUFFER_ERROR; + + major = input[0]; + minor = input[OPAQUE8_LEN]; + + #ifdef WOLFSSL_TLS13_DRAFT + if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) { + major = SSLv3_MAJOR; + minor = TLSv1_3_MINOR; + } + #endif + + if (major != pv.major) + return VERSION_ERROR; + + /* Can't downgrade with this extension below TLS v1.3. */ + if (minor < TLSv1_3_MINOR) + return VERSION_ERROR; + + /* Version is TLS v1.2 to handle downgrading from TLS v1.3+. */ + if (ssl->options.downgrade && ssl->version.minor == TLSv1_2_MINOR) { + /* Set minor version back to TLS v1.3+ */ + ssl->version.minor = ssl->ctx->method->version.minor; + } + + /* No upgrade allowed. */ + if (ssl->version.minor < minor) + return VERSION_ERROR; + + /* Check downgrade. */ + if (ssl->version.minor > minor) { + if (!ssl->options.downgrade) + return VERSION_ERROR; + + if (minor < ssl->options.minDowngrade) + return VERSION_ERROR; + + /* Downgrade the version. */ + ssl->version.minor = minor; + } + } +#endif + else + return SANITY_MSG_E; + + return 0; +} + +/* 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, b, c) 0 +#define SV_WRITE(a, b, c, d) 0 +#define SV_PARSE(a, b, c, d) 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 int TLSX_Cookie_GetSize(Cookie* cookie, byte msgType, word16* pSz) +{ + if (msgType == client_hello || msgType == hello_retry_request) + *pSz += OPAQUE16_LEN + cookie->len; + else + return SANITY_MSG_E; + return 0; +} + +/* 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 int TLSX_Cookie_Write(Cookie* cookie, byte* output, byte msgType, + word16* pSz) +{ + if (msgType == client_hello || msgType == hello_retry_request) { + c16toa(cookie->len, output); + output += OPAQUE16_LEN; + XMEMCPY(output, &cookie->data, cookie->len); + *pSz += OPAQUE16_LEN + cookie->len; + } + else + return SANITY_MSG_E; + return 0; +} + +/* 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, c) 0 +#define CKE_WRITE(a, b, c, d) 0 +#define CKE_PARSE(a, b, c, d) 0 + +#endif +#if !defined(WOLFSSL_NO_SIGALG) +/******************************************************************************/ +/* Signature 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]; + #ifdef WOLFSSL_TLS13 + if (input[i] == rsa_pss_sa_algo && input[i + 1] >= pss_sha256 && + input[i + 1] <= pss_sha512) { + ssl->pssAlgo |= 1 << input[i + 1]; + } + #endif + } + + 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 SignatureAlgorithms 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 +#endif +/******************************************************************************/ +/* Signature Algorithms Certificate */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) +/* 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_SignatureAlgorithmsCert_GetSize(void* data) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + return OPAQUE16_LEN + ssl->certHashSigAlgoSz; +} + +/* Writes the SignatureAlgorithmsCert 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_SignatureAlgorithmsCert_Write(void* data, byte* output) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + c16toa(ssl->certHashSigAlgoSz, output); + XMEMCPY(output + OPAQUE16_LEN, ssl->certHashSigAlgo, + ssl->certHashSigAlgoSz); + + return OPAQUE16_LEN + ssl->certHashSigAlgoSz; +} + +/* Parse the SignatureAlgorithmsCert 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_SignatureAlgorithmsCert_Parse(WOLFSSL *ssl, byte* input, + word16 length, byte isRequest) +{ + 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 */ + ssl->certHashSigAlgoSz = len; + if (ssl->certHashSigAlgoSz > WOLFSSL_MAX_SIGALGO) { + WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating"); + ssl->certHashSigAlgoSz = WOLFSSL_MAX_SIGALGO; + } + XMEMCPY(ssl->certHashSigAlgo, input, ssl->certHashSigAlgoSz); + + return 0; +} + +/* Sets a new SignatureAlgorithmsCert 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_SetSignatureAlgorithmsCert(TLSX** extensions, const void* data, + void* heap) +{ + if (extensions == NULL) + return BAD_FUNC_ARG; + + return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS_CERT, (void *)data, + heap); +} + +#define SAC_GET_SIZE TLSX_SignatureAlgorithmsCert_GetSize +#define SAC_WRITE TLSX_SignatureAlgorithmsCert_Write +#define SAC_PARSE TLSX_SignatureAlgorithmsCert_Parse +#endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */ +#endif /* WOLFSSL_TLS13 */ + + +/******************************************************************************/ +/* Key Share */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +/* 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; +#ifndef NO_DH + byte* keyData; + void* key = NULL; + word32 keySz; + word32 dataSz; + const DhParams* params; +#ifdef WOLFSSL_SMALL_STACK + DhKey* dhKey = NULL; +#else + DhKey dhKey[1]; +#endif + + /* 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; + } + +#ifdef WOLFSSL_SMALL_STACK + dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH); + if (dhKey == NULL) + return MEMORY_E; +#endif + + ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); + #endif + 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->pubKey = keyData; + kse->pubKeyLen = 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); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); +#endif + + 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); + } +#else + (void)ssl; + (void)kse; + + ret = NOT_COMPILED_IN; +#endif + + return ret; +} + +/* Create a key share entry using X25519 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_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret; +#ifdef HAVE_CURVE25519 + byte* keyData = NULL; + word32 dataSize = CURVE25519_KEYSIZE; + 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; + } + + /* Make an ECC key. */ + ret = wc_curve25519_init(key); + if (ret != 0) + goto end; + ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key); + if (ret != 0) + goto end; + + /* Allocate space for the public key. */ + keyData = (byte*)XMALLOC(CURVE25519_KEYSIZE, 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->pubKey = keyData; + kse->pubKeyLen = CURVE25519_KEYSIZE; + kse->key = key; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public Curve25519 Key"); + WOLFSSL_BUFFER(keyData, dataSize); +#endif + +end: + if (ret != 0) { + /* Data owned by key share entry otherwise. */ + if (keyData != NULL) + XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + wc_curve25519_free(key); + XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + } +#else + (void)ssl; + (void)kse; + + ret = NOT_COMPILED_IN; +#endif /* HAVE_CURVE25519 */ + + return ret; +} + +/* Create a key share entry using X448 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_GenX448Key(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret; +#ifdef HAVE_CURVE448 + byte* keyData = NULL; + word32 dataSize = CURVE448_KEY_SIZE; + curve448_key* key; + + /* Allocate an ECC key to hold private key. */ + key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap, + DYNAMIC_TYPE_PRIVATE_KEY); + if (key == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + + /* Make an ECC key. */ + ret = wc_curve448_init(key); + if (ret != 0) + goto end; + ret = wc_curve448_make_key(ssl->rng, CURVE448_KEY_SIZE, key); + if (ret != 0) + goto end; + + /* Allocate space for the public key. */ + keyData = (byte*)XMALLOC(CURVE448_KEY_SIZE, 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_curve448_export_public_ex(key, keyData, &dataSize, + EC448_LITTLE_ENDIAN) != 0) { + ret = ECC_EXPORT_ERROR; + goto end; + } + + kse->pubKey = keyData; + kse->pubKeyLen = CURVE448_KEY_SIZE; + kse->key = key; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public Curve448 Key"); + WOLFSSL_BUFFER(keyData, dataSize); +#endif + +end: + if (ret != 0) { + /* Data owned by key share entry otherwise. */ + if (keyData != NULL) + XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + wc_curve448_free(key); + XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + } +#else + (void)ssl; + (void)kse; + + ret = NOT_COMPILED_IN; +#endif /* HAVE_CURVE448 */ + + return ret; +} + +/* 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; +#ifdef HAVE_ECC + byte* keyData = NULL; + word32 dataSize; + byte* keyPtr = NULL; + word32 keySize; + ecc_key* eccKey; + 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_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. */ + keyPtr = (byte*)XMALLOC(sizeof(ecc_key), ssl->heap, + DYNAMIC_TYPE_PRIVATE_KEY); + if (keyPtr == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + eccKey = (ecc_key*)keyPtr; + + /* 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->pubKey = keyData; + kse->pubKeyLen = dataSize; + kse->key = keyPtr; + +#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 (keyPtr != NULL) + XFREE(keyPtr, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (keyData != NULL) + XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } +#else + (void)ssl; + (void)kse; + + ret = NOT_COMPILED_IN; +#endif /* HAVE_ECC */ + + return ret; +} + +/* 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) +{ + /* 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); + if (kse->group == WOLFSSL_ECC_X25519) + return TLSX_KeyShare_GenX25519Key(ssl, kse); + if (kse->group == WOLFSSL_ECC_X448) + return TLSX_KeyShare_GenX448Key(ssl, kse); + return TLSX_KeyShare_GenEccKey(ssl, kse); +} + +/* 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; + if ((current->group & NAMED_DH_MASK) == 0) { + if (current->group == WOLFSSL_ECC_X25519) { +#ifdef HAVE_CURVE25519 + wc_curve25519_free((curve25519_key*)current->key); +#endif + } + else if (current->group == WOLFSSL_ECC_X448) { +#ifdef HAVE_CURVE448 + wc_curve448_free((curve448_key*)current->key); +#endif + } + else { +#ifdef HAVE_ECC + wc_ecc_free((ecc_key*)(current->key)); +#endif + } + } + if (current->key != NULL) + XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY); + XFREE(current->pubKey, heap, DYNAMIC_TYPE_PUBLIC_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) +{ + word16 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 += KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen; + } + + return 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((word16)(current->pubKeyLen), &output[i]); + i += OPAQUE16_LEN; + XMEMCPY(&output[i], current->pubKey, current->pubKeyLen); + i += (word16)current->pubKeyLen; + } + /* 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; +#ifdef WOLFSSL_SMALL_STACK + DhKey* dhKey = NULL; +#else + DhKey dhKey[1]; +#endif + + 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 + +#ifdef WOLFSSL_SMALL_STACK + dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH); + if (dhKey == NULL) + return MEMORY_E; +#endif + + ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); + #endif + 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); + #ifdef WOLFSSL_SMALL_STACK + XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); + #endif + return ret; + } + + ret = wc_DhCheckPubKey(dhKey, keyShareEntry->ke, keyShareEntry->keLen); + if (ret != 0) { + wc_FreeDhKey(dhKey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); + #endif + return PEER_KEY_ERROR; + } + + /* 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 + /* RFC 8446 Section 7.4.1: + * ... left-padded with zeros up to the size of the prime. ... + */ + if (params->p_len > ssl->arrays->preMasterSz) { + word32 diff = params->p_len - ssl->arrays->preMasterSz; + XMEMMOVE(ssl->arrays->preMasterSecret + diff, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + XMEMSET(ssl->arrays->preMasterSecret, 0, diff); + ssl->arrays->preMasterSz = params->p_len; + } + + ssl->options.dhKeySz = params->p_len; + + wc_FreeDhKey(dhKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); +#endif + if (keyShareEntry->key != NULL) { + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + keyShareEntry->key = NULL; + } + XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + keyShareEntry->pubKey = NULL; + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + keyShareEntry->ke = NULL; + + return ret; +#else + (void)ssl; + (void)keyShareEntry; + return PEER_KEY_ERROR; +#endif +} + +/* Process the X25519 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_ProcessX25519(WOLFSSL* ssl, + KeyShareEntry* keyShareEntry) +{ + int ret; + +#ifdef HAVE_CURVE25519 + curve25519_key* key = (curve25519_key*)keyShareEntry->key; + curve25519_key* peerX25519Key; + +#ifdef HAVE_ECC + if (ssl->peerEccKey != NULL) { + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKey = NULL; + } +#endif + + peerX25519Key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap, + DYNAMIC_TYPE_TLSX); + if (peerX25519Key == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_ERROR; + } + ret = wc_curve25519_init(peerX25519Key); + if (ret != 0) { + XFREE(peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX); + return ret; + } +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer Curve25519 Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + if (wc_curve25519_check_public(keyShareEntry->ke, keyShareEntry->keLen, + EC25519_LITTLE_ENDIAN) != 0) { + ret = ECC_PEERKEY_ERROR; + } + + if (ret == 0) { + if (wc_curve25519_import_public_ex(keyShareEntry->ke, + keyShareEntry->keLen, peerX25519Key, + EC25519_LITTLE_ENDIAN) != 0) { + ret = ECC_PEERKEY_ERROR; + } + } + + if (ret == 0) { + ssl->ecdhCurveOID = ECC_X25519_OID; + + ret = wc_curve25519_shared_secret_ex(key, peerX25519Key, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + EC25519_LITTLE_ENDIAN); + } + + wc_curve25519_free(peerX25519Key); + XFREE(peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX); + wc_curve25519_free((curve25519_key*)keyShareEntry->key); + if (keyShareEntry->key != NULL) { + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + keyShareEntry->key = NULL; + } +#else + (void)ssl; + (void)keyShareEntry; + + ret = PEER_KEY_ERROR; +#endif /* HAVE_CURVE25519 */ + + return ret; +} + +/* Process the X448 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_ProcessX448(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ + int ret; + +#ifdef HAVE_CURVE448 + curve448_key* key = (curve448_key*)keyShareEntry->key; + curve448_key* peerX448Key; + +#ifdef HAVE_ECC + if (ssl->peerEccKey != NULL) { + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKey = NULL; + } +#endif + + peerX448Key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap, + DYNAMIC_TYPE_TLSX); + if (peerX448Key == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_ERROR; + } + ret = wc_curve448_init(peerX448Key); + if (ret != 0) { + XFREE(peerX448Key, ssl->heap, DYNAMIC_TYPE_TLSX); + return ret; + } +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer Curve448 Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + if (wc_curve448_check_public(keyShareEntry->ke, keyShareEntry->keLen, + EC448_LITTLE_ENDIAN) != 0) { + ret = ECC_PEERKEY_ERROR; + } + + if (ret == 0) { + if (wc_curve448_import_public_ex(keyShareEntry->ke, + keyShareEntry->keLen, peerX448Key, + EC448_LITTLE_ENDIAN) != 0) { + ret = ECC_PEERKEY_ERROR; + } + } + + if (ret == 0) { + ssl->ecdhCurveOID = ECC_X448_OID; + + ret = wc_curve448_shared_secret_ex(key, peerX448Key, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + EC448_LITTLE_ENDIAN); + } + + wc_curve448_free(peerX448Key); + XFREE(peerX448Key, ssl->heap, DYNAMIC_TYPE_TLSX); + wc_curve448_free((curve448_key*)keyShareEntry->key); + if (keyShareEntry->key != NULL) { + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + keyShareEntry->key = NULL; + } +#else + (void)ssl; + (void)keyShareEntry; + + ret = PEER_KEY_ERROR; +#endif /* HAVE_CURVE448 */ + + return ret; +} + +/* 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_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; + + 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 + ); +#endif + + wc_ecc_free(ssl->peerEccKey); + XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); + ssl->peerEccKey = NULL; + wc_ecc_free((ecc_key*)(keyShareEntry->key)); + if (keyShareEntry->key != NULL) { + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + keyShareEntry->key = NULL; + } + +#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 if (keyShareEntry->group == WOLFSSL_ECC_X25519) + ret = TLSX_KeyShare_ProcessX25519(ssl, keyShareEntry); + else if (keyShareEntry->group == WOLFSSL_ECC_X448) + ret = TLSX_KeyShare_ProcessX448(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 == 0) + return INVALID_PARAMETER; + if (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 SSL/TLS object. + * name 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) { + extension = TLSX_Find(ssl->ctx->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) { + if ((extension = TLSX_Find(ssl->ctx->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 = NULL; + word16 group; + + if (msgType == client_hello) { + int offset = 0; + word16 len; + TLSX* extension; + + /* Add a KeyShare extension if it doesn't exist. */ + 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; + } + + 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 < (int)length) { + ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], length - offset, + &keyShareEntry); + if (ret < 0) + return ret; + + offset += ret; + } + + ret = 0; + } + else if (msgType == server_hello) { + int len; + + 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; + + /* ServerHello contains one key share entry. */ + len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry); + if (len != (int)length) + return BUFFER_ERROR; + + /* Not in list sent if there isn't a private key. */ + if (keyShareEntry == NULL || keyShareEntry->key == NULL) + return BAD_KEY_SHARE_DATA; + + /* Process the entry to calculate the secret. */ + ret = TLSX_KeyShare_Process(ssl, keyShareEntry); + if (ret == 0) + ssl->session.namedGroup = ssl->namedGroup = group; + } + else if (msgType == hello_retry_request) { + 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; + + /* Clear out unusable key shares. */ + ret = TLSX_KeyShare_Empty(ssl); + if (ret != 0) + return ret; + + /* 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; + KeyShareEntry** next; + + kse = (KeyShareEntry*)XMALLOC(sizeof(KeyShareEntry), heap, + DYNAMIC_TYPE_TLSX); + if (kse == NULL) + return MEMORY_E; + + XMEMSET(kse, 0, sizeof(*kse)); + kse->group = (word16)group; + + /* Add it to the back and maintain the links. */ + while (*list != NULL) { + /* Assign to temporary to work around compiler bug found by customer. */ + next = &((*list)->next); + list = next; + } + *list = kse; + *keyShareEntry = kse; + + (void)heap; + + 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) { + 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 + #ifdef HAVE_CURVE448 + case WOLFSSL_ECC_X448: + 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 + default: + return 0; + } + + return 1; +} + +/* Examines the application specified group ranking and returns the rank of the + * group. + * If no group ranking set then all groups are rank 0 (highest). + * + * ssl The SSL/TLS object. + * group The group to check ranking for. + * returns ranking from 0 to MAX_GROUP_COUNT-1 or -1 when group not in list. + */ +static int TLSX_KeyShare_GroupRank(WOLFSSL* ssl, int group) +{ + byte i; + + if (ssl->numGroups == 0) { +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP256R1; + #endif + #endif +#endif + #ifndef HAVE_FIPS + #if defined(HAVE_CURVE25519) + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_X25519; + #endif + #endif + #ifndef HAVE_FIPS + #if defined(HAVE_CURVE448) + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_X448; + #endif + #endif +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP384R1; + #endif + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP521R1; + #endif + #endif +#endif + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_2048 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_2048; + #endif + #ifdef HAVE_FFDHE_3072 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_3072; + #endif + #ifdef HAVE_FFDHE_4096 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_4096; + #endif + #ifdef HAVE_FFDHE_6144 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_6144; + #endif + #ifdef HAVE_FFDHE_8192 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_8192; + #endif + } + + for (i = 0; i < ssl->numGroups; i++) + if (ssl->group[i] == (word16)group) + return i; + + 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; + SupportedCurve* preferredCurve = NULL; + int preferredRank = WOLFSSL_MAX_GROUP_COUNT; + int rank; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + if (extension != NULL) + curve = (SupportedCurve*)extension->data; + /* Use server's preference order. */ + for (; curve != NULL; curve = curve->next) { + if (!TLSX_KeyShare_IsSupported(curve->name)) + continue; + + rank = TLSX_KeyShare_GroupRank(ssl, curve->name); + if (rank == -1) + continue; + if (rank < preferredRank) { + preferredCurve = curve; + preferredRank = rank; + } + } + curve = preferredCurve; + + 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 response. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + extension->resp = 1; +#else + + (void)ssl; + ret = NOT_COMPILED_IN; +#endif + + return ret; +} + +/* Ensure there is a key pair that can be used for key exchange. + * + * 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; + KeyShareEntry* preferredKSE = NULL; + int preferredRank = WOLFSSL_MAX_GROUP_COUNT; + int rank; + + /* 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; + + /* Use server's preference order. */ + for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) { + if (clientKSE->ke == NULL) + continue; + + /* Check consistency now - extensions in any order. */ + if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group)) + return BAD_KEY_SHARE_DATA; + + #ifdef OPENSSL_EXTRA + if ((clientKSE->group & NAMED_DH_MASK) == 0) { + /* Check if server supports group. */ + if (ssl->ctx->disabledCurves & (1 << clientKSE->group)) + continue; + } + #endif + if (!TLSX_KeyShare_IsSupported(clientKSE->group)) + continue; + + rank = TLSX_KeyShare_GroupRank(ssl, clientKSE->group); + if (rank == -1) + continue; + if (rank < preferredRank) { + preferredKSE = clientKSE; + preferredRank = rank; + } + } + clientKSE = preferredKSE; + + /* 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; + + if (clientKSE->key == NULL) { + ret = TLSX_KeyShare_GenKey(ssl, serverKSE); + if (ret != 0) + return ret; + } + else { + serverKSE->key = clientKSE->key; + serverKSE->keyLen = clientKSE->keyLen; + serverKSE->pubKey = clientKSE->pubKey; + serverKSE->pubKeyLen = clientKSE->pubKeyLen; + clientKSE->key = NULL; + clientKSE->pubKey = NULL; + } + serverKSE->ke = clientKSE->ke; + serverKSE->keLen = clientKSE->keLen; + clientKSE->ke = NULL; + clientKSE->keLen = 0; + + TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap); + extension->data = (void *)serverKSE; + + extension->resp = 1; + + return 0; +} + +/* Derive the shared secret of the key exchange. + * + * ssl The SSL/TLS object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl) +{ + int ret; + TLSX* extension; + KeyShareEntry* list = NULL; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension != NULL) + list = (KeyShareEntry*)extension->data; + + if (list == NULL) + return KEY_SHARE_ERROR; + + /* Calculate secret. */ + ret = TLSX_KeyShare_Process(ssl, list); + if (ret != 0) + return ret; + + return ret; +} + +#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 int TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType, + word16* pSz) +{ + 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; + } + *pSz += len; + return 0; + } + + if (msgType == server_hello) { + *pSz += OPAQUE16_LEN; + return 0; + } + + return SANITY_MSG_E; +} + +/* 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. + */ +int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType, + word16* pSz) +{ + 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; + } + + *pSz = len; + return 0; +} + +/* 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. + */ +int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, byte* output, + byte msgType, word16* pSz) +{ + 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); + + *pSz = idx; + return 0; +} + + +/* 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 int TLSX_PreSharedKey_Write(PreSharedKey* list, byte* output, + byte msgType, word16* pSz) +{ + if (msgType == client_hello) { + PreSharedKey* current = list; + word16 idx = 0; + word16 lenIdx; + word16 len; + int ret; + + /* 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. + */ + ret = TLSX_PreSharedKey_GetSizeBinders(list, msgType, &len); + if (ret < 0) + return ret; + *pSz += idx + len; + } + else 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); + *pSz += OPAQUE16_LEN; + } + else + return SANITY_MSG_E; + + 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; + + TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap); + + /* 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 || + identityLen > MAX_PSK_ID_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. */ + if (idx + OPAQUE16_LEN > length) + return BUFFER_E; + 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 > WC_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); + + #ifdef WOLFSSL_EARLY_DATA + ssl->options.pskIdIndex = idx + 1; + #endif + + /* 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->ctx->method->version.major || + ssl->session.version.minor != ssl->ctx->method->version.minor) { + return PSK_KEY_ERROR; + } + } + #endif + + 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; + PreSharedKey** next; + + 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) { + /* Assign to temporary to work around compiler bug found by customer. */ + next = &((*list)->next); + list = next; + } + *list = psk; + *preSharedKey = psk; + + (void)heap; + + return 0; +} + +static WC_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, c) 0 +#define PSK_WRITE(a, b, c, d) 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 int TLSX_PskKeModes_GetSize(byte modes, byte msgType, word16* pSz) +{ + 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; + *pSz += len; + return 0; + } + + 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 int TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType, + word16* pSz) +{ + 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; + + *pSz += idx; + return 0; + } + + 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; + word16 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, c) 0 +#define PKM_WRITE(a, b, c, d) 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-Handshake 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-Handshake Authentication + * extension. + */ +static int TLSX_PostHandAuth_GetSize(byte msgType, word16* pSz) +{ + if (msgType == client_hello) { + *pSz += 0; + return 0; + } + + 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 int TLSX_PostHandAuth_Write(byte* output, byte msgType, word16* pSz) +{ + (void)output; + + if (msgType == client_hello) { + *pSz += 0; + return 0; + } + + 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) +{ + (void)input; + + if (msgType == client_hello) { + /* Ensure extension is empty. */ + if (length != 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, b) 0 +#define PHA_WRITE(a, b, c) 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 int TLSX_EarlyData_GetSize(byte msgType, word16* pSz) +{ + int ret = 0; + + if (msgType == client_hello || msgType == encrypted_extensions) + *pSz += 0; + else if (msgType == session_ticket) + *pSz += OPAQUE32_LEN; + else + ret = SANITY_MSG_E; + + return ret; +} + +/* 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 int TLSX_EarlyData_Write(word32 max, byte* output, byte msgType, + word16* pSz) +{ + if (msgType == client_hello || msgType == encrypted_extensions) + return 0; + else if (msgType == session_ticket) { + c32toa(max, output); + *pSz += OPAQUE32_LEN; + return 0; + } + + 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; + + if (ssl->earlyData == expecting_early_data) + return TLSX_EarlyData_Use(ssl, 0); + ssl->earlyData = early_data_ext; + return 0; + } + if (msgType == encrypted_extensions) { + if (length != 0) + return BUFFER_E; + + /* Ensure the index of PSK identity chosen by server is 0. + * Index is plus one to handle 'not set' value of 0. + */ + if (ssl->options.pskIdIndex != 1) + return PSK_KEY_ERROR; + + return TLSX_EarlyData_Use(ssl, 1); + } + if (msgType == session_ticket) { + word32 maxSz; + + if (length != OPAQUE32_LEN) + return BUFFER_E; + ato32(input, &maxSz); + + ssl->session.maxEarlyDataSz = maxSz; + 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, b) 0 +#define EDI_WRITE(a, b, c, d) 0 +#define EDI_PARSE(a, b, c, d) 0 + +#endif + +/******************************************************************************/ +/* TLS Extensions Framework */ +/******************************************************************************/ + +/** Finds an extension in the provided list. */ TLSX* TLSX_Find(TLSX* list, TLSX_Type type) { TLSX* extension = list; @@ -1945,7 +9077,26 @@ TLSX* TLSX_Find(TLSX* list, TLSX_Type type) return extension; } -void TLSX_FreeAll(TLSX* list) +/** Remove an extension. */ +void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap) +{ + TLSX* extension = *list; + TLSX** next = list; + + while (extension && extension->type != type) { + next = &extension->next; + extension = extension->next; + } + + if (extension) { + *next = extension->next; + extension->next = NULL; + TLSX_FreeAll(extension, heap); + } +} + +/** Releases all extensions in the provided list. */ +void TLSX_FreeAll(TLSX* list, void* heap) { TLSX* extension; @@ -1953,267 +9104,1660 @@ void TLSX_FreeAll(TLSX* list) list = extension->next; switch (extension->type) { - case SERVER_NAME_INDICATION: - SNI_FREE_ALL((SNI*)extension->data); + + case TLSX_SERVER_NAME: + SNI_FREE_ALL((SNI*)extension->data, heap); break; - case MAX_FRAGMENT_LENGTH: - MFL_FREE_ALL(extension->data); + case TLSX_TRUSTED_CA_KEYS: + TCA_FREE_ALL((TCA*)extension->data, heap); break; - case TRUNCATED_HMAC: + case TLSX_MAX_FRAGMENT_LENGTH: + MFL_FREE_ALL(extension->data, heap); + break; + + case TLSX_TRUNCATED_HMAC: /* Nothing to do. */ break; - case ELLIPTIC_CURVES: - EC_FREE_ALL(extension->data); + case TLSX_SUPPORTED_GROUPS: + EC_FREE_ALL((SupportedCurve*)extension->data, heap); break; - case SECURE_RENEGOTIATION: - SCR_FREE_ALL(extension->data); + case TLSX_EC_POINT_FORMATS: + PF_FREE_ALL((PointFormat*)extension->data, heap); break; - case SESSION_TICKET: - /* Nothing to do. */ + case TLSX_STATUS_REQUEST: + CSR_FREE_ALL((CertificateStatusRequest*)extension->data, heap); break; + + case TLSX_STATUS_REQUEST_V2: + CSR2_FREE_ALL((CertificateStatusRequestItemV2*)extension->data, + heap); + break; + + case TLSX_RENEGOTIATION_INFO: + SCR_FREE_ALL(extension->data, heap); + break; + + case TLSX_SESSION_TICKET: + WOLF_STK_FREE(extension->data, heap); + break; + + case TLSX_QUANTUM_SAFE_HYBRID: + QSH_FREE_ALL((QSHScheme*)extension->data, heap); + break; + + case TLSX_APPLICATION_LAYER_PROTOCOL: + ALPN_FREE_ALL((ALPN*)extension->data, heap); + break; +#if !defined(WOLFSSL_NO_SIGALG) + case TLSX_SIGNATURE_ALGORITHMS: + break; +#endif +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + case TLSX_ENCRYPT_THEN_MAC: + break; +#endif +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + break; + + case TLSX_COOKIE: + CKE_FREE_ALL((Cookie*)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 + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + case TLSX_SIGNATURE_ALGORITHMS_CERT: + break; + #endif + + case TLSX_KEY_SHARE: + KS_FREE_ALL((KeyShareEntry*)extension->data, heap); + break; +#endif } - XFREE(extension, 0, DYNAMIC_TYPE_TLSX); + XFREE(extension, heap, DYNAMIC_TYPE_TLSX); } + + (void)heap; } +/** Checks if the tls extensions are supported based on the protocol version. */ int TLSX_SupportExtensions(WOLFSSL* ssl) { return ssl && (IsTLS(ssl) || ssl->version.major == DTLS_MAJOR); } -static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) +/** Tells the buffered size of the extensions in a list. */ +static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType, + word16* pLength) { - TLSX* extension; + int ret = 0; + TLSX* extension; word16 length = 0; + byte isRequest = (msgType == client_hello || + msgType == certificate_request); while ((extension = list)) { list = extension->next; + /* only extensions marked as response are sent back to the client. */ if (!isRequest && !extension->resp) continue; /* skip! */ + /* ssl level extensions are expected to override ctx level ones. */ if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type))) continue; /* skip! */ - /* type + data length */ + /* extension type + extension data length. */ length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN; + switch (extension->type) { - case SERVER_NAME_INDICATION: + + case TLSX_SERVER_NAME: + /* SNI only sends the name on the request. */ if (isRequest) - length += SNI_GET_SIZE(extension->data); + length += SNI_GET_SIZE((SNI*)extension->data); break; - case MAX_FRAGMENT_LENGTH: + + case TLSX_TRUSTED_CA_KEYS: + /* TCA only sends the list on the request. */ + if (isRequest) + length += TCA_GET_SIZE((TCA*)extension->data); + break; + + case TLSX_MAX_FRAGMENT_LENGTH: length += MFL_GET_SIZE(extension->data); break; - case TRUNCATED_HMAC: - /* empty extension. */ + case TLSX_TRUNCATED_HMAC: + /* always empty. */ break; - case ELLIPTIC_CURVES: - length += EC_GET_SIZE(extension->data); + case TLSX_SUPPORTED_GROUPS: + length += EC_GET_SIZE((SupportedCurve*)extension->data); break; - case SECURE_RENEGOTIATION: - length += SCR_GET_SIZE(extension->data, isRequest); + case TLSX_EC_POINT_FORMATS: + length += PF_GET_SIZE((PointFormat*)extension->data); break; - case SESSION_TICKET: - length += STK_GET_SIZE(extension->data, isRequest); + case TLSX_STATUS_REQUEST: + length += CSR_GET_SIZE( + (CertificateStatusRequest*)extension->data, isRequest); break; + + case TLSX_STATUS_REQUEST_V2: + length += CSR2_GET_SIZE( + (CertificateStatusRequestItemV2*)extension->data, + isRequest); + break; + + case TLSX_RENEGOTIATION_INFO: + length += SCR_GET_SIZE((SecureRenegotiation*)extension->data, + isRequest); + break; + + case TLSX_SESSION_TICKET: + length += WOLF_STK_GET_SIZE((SessionTicket*)extension->data, + isRequest); + break; + + case TLSX_QUANTUM_SAFE_HYBRID: + length += QSH_GET_SIZE((QSHScheme*)extension->data, isRequest); + break; + + case TLSX_APPLICATION_LAYER_PROTOCOL: + length += ALPN_GET_SIZE((ALPN*)extension->data); + break; +#if !defined(WOLFSSL_NO_SIGALG) + case TLSX_SIGNATURE_ALGORITHMS: + length += SA_GET_SIZE(extension->data); + break; +#endif +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + case TLSX_ENCRYPT_THEN_MAC: + ret = ETM_GET_SIZE(msgType, &length); + break; +#endif /* HAVE_ENCRYPT_THEN_MAC */ +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + ret = SV_GET_SIZE(extension->data, msgType, &length); + break; + + case TLSX_COOKIE: + ret = CKE_GET_SIZE((Cookie*)extension->data, msgType, &length); + break; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + case TLSX_PRE_SHARED_KEY: + ret = PSK_GET_SIZE((PreSharedKey*)extension->data, msgType, + &length); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + ret = PKM_GET_SIZE(extension->val, msgType, &length); + break; + #endif + + #ifdef WOLFSSL_EARLY_DATA + case TLSX_EARLY_DATA: + ret = EDI_GET_SIZE(msgType, &length); + break; + #endif + + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + case TLSX_POST_HANDSHAKE_AUTH: + ret = PHA_GET_SIZE(msgType, &length); + break; + #endif + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + case TLSX_SIGNATURE_ALGORITHMS_CERT: + length += SAC_GET_SIZE(extension->data); + break; + #endif + + case TLSX_KEY_SHARE: + length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType); + break; +#endif } + /* marks the extension as processed so ctx level */ + /* extensions don't overlap with ssl level ones. */ TURN_ON(semaphore, TLSX_ToSemaphore(extension->type)); } - return length; + *pLength += length; + + return ret; } -static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, - byte isRequest) +/** Writes the extensions of a list in a buffer. */ +static int TLSX_Write(TLSX* list, byte* output, byte* semaphore, + byte msgType, word16* pOffset) { - TLSX* extension; + int ret = 0; + TLSX* extension; word16 offset = 0; word16 length_offset = 0; + byte isRequest = (msgType == client_hello || + msgType == certificate_request); while ((extension = list)) { list = extension->next; + /* only extensions marked as response are written in a response. */ if (!isRequest && !extension->resp) continue; /* skip! */ + /* ssl level extensions are expected to override ctx level ones. */ if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type))) continue; /* skip! */ - /* extension type */ + /* writes extension type. */ c16toa(extension->type, output + offset); offset += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN; length_offset = offset; - /* extension data should be written internally */ + /* extension data should be written internally. */ switch (extension->type) { - case SERVER_NAME_INDICATION: - if (isRequest) - offset += SNI_WRITE(extension->data, output + offset); + case TLSX_SERVER_NAME: + if (isRequest) { + WOLFSSL_MSG("SNI extension to write"); + offset += SNI_WRITE((SNI*)extension->data, output + offset); + } break; - case MAX_FRAGMENT_LENGTH: - offset += MFL_WRITE(extension->data, output + offset); + case TLSX_TRUSTED_CA_KEYS: + WOLFSSL_MSG("Trusted CA Indication extension to write"); + if (isRequest) { + offset += TCA_WRITE((TCA*)extension->data, output + offset); + } break; - case TRUNCATED_HMAC: - /* empty extension. */ + case TLSX_MAX_FRAGMENT_LENGTH: + WOLFSSL_MSG("Max Fragment Length extension to write"); + offset += MFL_WRITE((byte*)extension->data, output + offset); break; - case ELLIPTIC_CURVES: - offset += EC_WRITE(extension->data, output + offset); + case TLSX_TRUNCATED_HMAC: + WOLFSSL_MSG("Truncated HMAC extension to write"); + /* always empty. */ break; - case SECURE_RENEGOTIATION: - offset += SCR_WRITE(extension->data, output + offset, - isRequest); + case TLSX_SUPPORTED_GROUPS: + WOLFSSL_MSG("Supported Groups extension to write"); + offset += EC_WRITE((SupportedCurve*)extension->data, + output + offset); break; - case SESSION_TICKET: - offset += STK_WRITE(extension->data, output + offset, - isRequest); + 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: + 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); + } + offset += QSHPK_WRITE((QSHScheme*)extension->data, output + offset); + offset += QSH_SERREQ(output + offset, isRequest); + break; + + case TLSX_APPLICATION_LAYER_PROTOCOL: + WOLFSSL_MSG("ALPN extension to write"); + offset += ALPN_WRITE((ALPN*)extension->data, output + offset); + break; +#if !defined(WOLFSSL_NO_SIGALG) + case TLSX_SIGNATURE_ALGORITHMS: + WOLFSSL_MSG("Signature Algorithms extension to write"); + offset += SA_WRITE(extension->data, output + offset); + break; +#endif +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + case TLSX_ENCRYPT_THEN_MAC: + WOLFSSL_MSG("Encrypt-Then-Mac extension to write"); + ret = ETM_WRITE(extension->data, output, msgType, &offset); + break; +#endif /* HAVE_ENCRYPT_THEN_MAC */ +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + WOLFSSL_MSG("Supported Versions extension to write"); + ret = SV_WRITE(extension->data, output + offset, msgType, &offset); + break; + + case TLSX_COOKIE: + WOLFSSL_MSG("Cookie extension to write"); + ret = CKE_WRITE((Cookie*)extension->data, output + offset, + msgType, &offset); + break; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + case TLSX_PRE_SHARED_KEY: + WOLFSSL_MSG("Pre-Shared Key extension to write"); + ret = PSK_WRITE((PreSharedKey*)extension->data, output + offset, + msgType, &offset); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + WOLFSSL_MSG("PSK Key Exchange Modes extension to write"); + ret = PKM_WRITE(extension->val, output + offset, msgType, + &offset); + break; + #endif + + #ifdef WOLFSSL_EARLY_DATA + case TLSX_EARLY_DATA: + WOLFSSL_MSG("Early Data extension to write"); + ret = EDI_WRITE(extension->val, output + offset, msgType, + &offset); + break; + #endif + + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + case TLSX_POST_HANDSHAKE_AUTH: + WOLFSSL_MSG("Post-Handshake Authentication extension to write"); + ret = PHA_WRITE(output + offset, msgType, &offset); + break; + #endif + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + case TLSX_SIGNATURE_ALGORITHMS_CERT: + WOLFSSL_MSG("Signature Algorithms extension to write"); + offset += SAC_WRITE(extension->data, output + offset); + break; + #endif + + case TLSX_KEY_SHARE: + WOLFSSL_MSG("Key Share extension to write"); + offset += KS_WRITE((KeyShareEntry*)extension->data, + output + offset, msgType); + break; +#endif } - /* writing extension data length */ + /* writes extension data length. */ c16toa(offset - length_offset, output + length_offset - OPAQUE16_LEN); + /* marks the extension as processed so ctx level */ + /* extensions don't overlap with ssl level ones. */ TURN_ON(semaphore, TLSX_ToSemaphore(extension->type)); } - return offset; + *pOffset += offset; + + return ret; } -#ifndef NO_WOLFSSL_CLIENT -word16 TLSX_GetRequestSize(WOLFSSL* ssl) +#if defined(HAVE_NTRU) && defined(HAVE_QSH) + +static word32 GetEntropy(unsigned char* out, word32 num_bytes) { - word16 length = 0; + int ret = 0; - if (TLSX_SupportExtensions(ssl)) { - byte semaphore[SEMAPHORE_SIZE] = {0}; - - EC_VALIDATE_REQUEST(ssl, semaphore); - STK_VALIDATE_REQUEST(ssl); - - 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 += ssl->suites->hashSigAlgoSz + HELLO_EXT_LEN; + if (gRng == NULL) { + if ((gRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, + DYNAMIC_TYPE_TLSX)) == NULL) + return DRBG_OUT_OF_MEMORY; + wc_InitRng(gRng); } - if (length) - length += OPAQUE16_LEN; /* for total length storage */ + if (gRngMutex == NULL) { + if ((gRngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), NULL, + DYNAMIC_TYPE_TLSX)) == NULL) + return DRBG_OUT_OF_MEMORY; + wc_InitMutex(gRngMutex); + } - return length; + ret |= wc_LockMutex(gRngMutex); + ret |= wc_RNG_GenerateBlock(gRng, out, num_bytes); + ret |= wc_UnLockMutex(gRngMutex); + + if (ret != 0) + return DRBG_ENTROPY_FAIL; + + return DRBG_OK; +} +#endif + + +#ifdef HAVE_QSH +static int TLSX_CreateQSHKey(WOLFSSL* ssl, int type) +{ + int ret = -1; + + (void)ssl; + + switch (type) { +#ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + ret = TLSX_CreateNtruKey(ssl, type); + break; +#endif + default: + WOLFSSL_MSG("Unknown type for creating NTRU key"); + break; + } + + return ret; } -word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) + +static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key) { - word16 offset = 0; + QSHKey* current; - if (TLSX_SupportExtensions(ssl) && output) { - byte semaphore[SEMAPHORE_SIZE] = {0}; + if (key == NULL) + return BAD_FUNC_ARG; - offset += OPAQUE16_LEN; /* extensions length */ + /* if no public key stored in key then do not add */ + if (key->pub.length == 0 || key->pub.buffer == NULL) + return 0; - EC_VALIDATE_REQUEST(ssl, semaphore); + /* first element to be added to the list */ + current = *list; + if (current == NULL) { + *list = key; + return 0; + } - if (ssl->extensions) - offset += TLSX_Write(ssl->extensions, output + offset, - semaphore, 1); + while (current->next) { + /* can only have one of the key in the list */ + if (current->name == key->name) + return -1; + current = (QSHKey*)current->next; + } - if (ssl->ctx && ssl->ctx->extensions) - offset += TLSX_Write(ssl->ctx->extensions, output + offset, - semaphore, 1); + current->next = (struct QSHKey*)key; - if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) - { - int i; - /* extension type */ - c16toa(HELLO_EXT_SIG_ALGO, output + offset); - offset += HELLO_EXT_TYPE_SZ; + return 0; +} - /* 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; +#if defined(HAVE_NTRU) +int TLSX_CreateNtruKey(WOLFSSL* ssl, int type) +{ + int ret = -1; + int ntruType; - /* sig algos */ - for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, offset++) - output[offset] = ssl->suites->hashSigAlgo[i]; + /* variable declarations for NTRU*/ + QSHKey* temp = NULL; + byte public_key[1027]; + word16 public_key_len = sizeof(public_key); + byte private_key[1120]; + word16 private_key_len = sizeof(private_key); + DRBG_HANDLE drbg; + + if (ssl == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WOLFSSL_NTRU_EESS439: + ntruType = NTRU_EES439EP1; + break; + case WOLFSSL_NTRU_EESS593: + ntruType = NTRU_EES593EP1; + break; + case WOLFSSL_NTRU_EESS743: + ntruType = NTRU_EES743EP1; + break; + default: + WOLFSSL_MSG("Unknown type for creating NTRU key"); + return -1; + } + ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); + if (ret != DRBG_OK) { + WOLFSSL_MSG("NTRU drbg instantiate failed\n"); + return ret; + } + + if ((ret = ntru_crypto_ntru_encrypt_keygen(drbg, ntruType, + &public_key_len, NULL, &private_key_len, NULL)) != NTRU_OK) + return ret; + + if ((ret = ntru_crypto_ntru_encrypt_keygen(drbg, ntruType, + &public_key_len, public_key, &private_key_len, private_key)) != NTRU_OK) + return ret; + + ret = ntru_crypto_drbg_uninstantiate(drbg); + if (ret != NTRU_OK) { + WOLFSSL_MSG("NTRU drbg uninstantiate failed\n"); + return ret; + } + + if ((temp = (QSHKey*)XMALLOC(sizeof(QSHKey), ssl->heap, + DYNAMIC_TYPE_TLSX)) == NULL) + return MEMORY_E; + temp->name = type; + temp->pub.length = public_key_len; + temp->pub.buffer = (byte*)XMALLOC(public_key_len, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + XMEMCPY(temp->pub.buffer, public_key, public_key_len); + temp->pri.length = private_key_len; + temp->pri.buffer = (byte*)XMALLOC(private_key_len, ssl->heap, + DYNAMIC_TYPE_ARRAYS); + XMEMCPY(temp->pri.buffer, private_key, private_key_len); + temp->next = NULL; + + TLSX_AddQSHKey(&ssl->QSH_Key, temp); + + (void)ssl; + (void)type; + + return ret; +} +#endif + + +/* + Used to find a public key from the list of keys + pubLen length of array + name input the name of the scheme looking for ie WOLFSSL_NTRU_ESSXXX + + returns a pointer to public key byte* or NULL if not found + */ +static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name) +{ + QSHKey* current = qsh; + + if (qsh == NULL || pubLen == NULL) + return NULL; + + *pubLen = 0; + + while(current) { + if (current->name == name) { + *pubLen = current->pub.length; + return current->pub.buffer; + } + current = (QSHKey*)current->next; + } + + return NULL; +} +#endif /* HAVE_QSH */ + +#if (!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) || \ + (defined(WOLFSSL_TLS13) && !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) \ + && !defined(HAVE_CURVE448) && defined(HAVE_SUPPORTED_CURVES)) || \ + ((defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES)) + +/* Populates the default supported groups / curves */ +static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) +{ + int ret = WOLFSSL_SUCCESS; +#ifdef WOLFSSL_TLS13 + int i; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (ssl->options.resuming && ssl->session.namedGroup != 0) { + return TLSX_UseSupportedCurve(extensions, ssl->session.namedGroup, + ssl->heap); + } +#endif + + if (ssl->numGroups != 0) { + for (i = 0; i < ssl->numGroups; i++) { + ret = TLSX_UseSupportedCurve(extensions, ssl->group[i], ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + return WOLFSSL_SUCCESS; + } +#endif /* WOLFSSL_TLS13 */ + +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + /* list in order by strength, since not all servers choose by strength */ + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP521R1, 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(extensions, + WOLFSSL_ECC_BRAINPOOLP512R1, 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(extensions, + WOLFSSL_ECC_SECP384R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif +#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ + + #ifndef HAVE_FIPS + #if defined(HAVE_CURVE448) + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_X448, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif /* HAVE_FIPS */ + +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP256R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP256K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif +#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ + + #ifndef HAVE_FIPS + #if defined(HAVE_CURVE25519) + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_X25519, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif /* HAVE_FIPS */ + +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP224R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP224K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + + #ifndef HAVE_FIPS + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP192R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP192K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP160R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_SECPR2 + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP160R2, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP160K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #endif /* HAVE_FIPS */ +#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ + + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_8192 + if (8192/8 >= ssl->options.minDhKeySz && + 8192/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_8192, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + #endif + #ifdef HAVE_FFDHE_6144 + if (6144/8 >= ssl->options.minDhKeySz && + 6144/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_6144, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + #endif + #ifdef HAVE_FFDHE_4096 + if (4096/8 >= ssl->options.minDhKeySz && + 4096/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_4096, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + #endif + #ifdef HAVE_FFDHE_3072 + if (3072/8 >= ssl->options.minDhKeySz && + 3072/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_3072, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + #endif + #ifdef HAVE_FFDHE_2048 + if (2048/8 >= ssl->options.minDhKeySz && + 2048/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_2048, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + #endif + + (void)ssl; + (void)extensions; + + return ret; +} + +#endif + +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; + QSHScheme* next; + + /* add supported QSHSchemes */ + WOLFSSL_MSG("Adding supported QSH Schemes"); +#endif + + /* server will add extension depending on what is parsed from client */ + if (!isServer) { +#ifdef HAVE_QSH + /* test if user has set a specific scheme already */ + if (!ssl->user_set_QSHSchemes) { + if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS743)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS593)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS439)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + + /* add NTRU 256 */ + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS743); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS743, + public_key, public_key_len, ssl->heap) + != WOLFSSL_SUCCESS) + ret = -1; + + /* add NTRU 196 */ + if (ssl->sendQSHKeys) { + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS593); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS593, + public_key, public_key_len, ssl->heap) + != WOLFSSL_SUCCESS) + ret = -1; + + /* add NTRU 128 */ + if (ssl->sendQSHKeys) { + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS439); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS439, + public_key, public_key_len, ssl->heap) + != WOLFSSL_SUCCESS) + ret = -1; + } + else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { + /* for each scheme make a client key */ + extension = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID); + if (extension) { + qsh = (QSHScheme*)extension->data; + + while (qsh) { + if ((ret = TLSX_CreateQSHKey(ssl, qsh->name)) != 0) + return ret; + + /* get next now because qsh could be freed */ + next = qsh->next; + + /* find the public key created and add to extension*/ + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, qsh->name); + if (TLSX_UseQSHScheme(&ssl->extensions, qsh->name, + public_key, public_key_len, + ssl->heap) != WOLFSSL_SUCCESS) + ret = -1; + qsh = next; + } + } + } +#endif + +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (!ssl->options.disallowEncThenMac) { + ret = TLSX_EncryptThenMac_Use(ssl); + if (ret != 0) + return ret; + } +#endif + +#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES) + if (!ssl->options.userCurves && !ssl->ctx->userCurves) { + if (TLSX_Find(ssl->ctx->extensions, + TLSX_SUPPORTED_GROUPS) == NULL) { + ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + } + if ((!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade) && + TLSX_Find(ssl->ctx->extensions, TLSX_EC_POINT_FORMATS) == NULL && + TLSX_Find(ssl->extensions, TLSX_EC_POINT_FORMATS) == NULL) { + ret = TLSX_UsePointFormat(&ssl->extensions, + WOLFSSL_EC_PF_UNCOMPRESSED, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } +#endif /* (HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */ + } /* is not server */ + +#if !defined(WOLFSSL_NO_SIGALG) + WOLFSSL_MSG("Adding signature algorithms extension"); + if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl, ssl->heap)) + != 0) { + return ret; + } +#else + ret = 0; +#endif + #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; + } + + #if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && \ + !defined(HAVE_CURVE448) && defined(HAVE_SUPPORTED_CURVES) + if (TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) == NULL) { + /* Put in DH groups for TLS 1.3 only. */ + ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions); + if (ret != WOLFSSL_SUCCESS) + return ret; + ret = 0; + } + #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */ + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + if (ssl->certHashSigAlgoSz > 0) { + WOLFSSL_MSG("Adding signature algorithms cert extension"); + if ((ret = TLSX_SetSignatureAlgorithmsCert(&ssl->extensions, + ssl, ssl->heap)) != 0) { + return ret; + } + } + #endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */ + + if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { + word16 namedGroup; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (ssl->options.resuming && ssl->session.namedGroup != 0) + namedGroup = ssl->session.namedGroup; + else + #endif + { + #if defined(HAVE_ECC) && (!defined(NO_ECC256) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) + namedGroup = WOLFSSL_ECC_SECP256R1; + #elif defined(HAVE_CURVE25519) + namedGroup = WOLFSSL_ECC_X25519; + #elif defined(HAVE_CURVE448) + namedGroup = WOLFSSL_ECC_X448; + #elif defined(HAVE_ECC) && (!defined(NO_ECC384) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) + namedGroup = WOLFSSL_ECC_SECP384R1; + #elif defined(HAVE_ECC) && (!defined(NO_ECC521) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) + namedGroup = WOLFSSL_ECC_SECP521R1; + #elif defined(HAVE_FFDHE_2048) + namedGroup = WOLFSSL_FFDHE_2048; + #elif defined(HAVE_FFDHE_3072) + namedGroup = WOLFSSL_FFDHE_3072; + #elif defined(HAVE_FFDHE_4096) + namedGroup = WOLFSSL_FFDHE_4096; + #elif defined(HAVE_FFDHE_6144) + namedGroup = WOLFSSL_FFDHE_6144; + #elif defined(HAVE_FFDHE_8192) + namedGroup = WOLFSSL_FFDHE_8192; + #else + return KEY_SHARE_ERROR; + #endif + } + ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL); + if (ret != 0) + return ret; + } + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap); + #endif + #if defined(HAVE_SESSION_TICKET) + if (ssl->options.resuming && ssl->session.ticketLen > 0) { + WOLFSSL_SESSION* sess = &ssl->session; + word32 milli; + + if (sess->ticketLen > MAX_PSK_ID_LEN) { + WOLFSSL_MSG("Session ticket length for PSK ext is too large"); + return BUFFER_ERROR; + } + + /* 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 || + ssl->options.client_psk_tls13_cb != NULL) { + /* Default ciphersuite. */ + byte cipherSuite0 = TLS13_BYTE; + byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER; + const char* cipherName = NULL; + + if (ssl->options.client_psk_tls13_cb != NULL) { + ssl->arrays->psk_keySz = ssl->options.client_psk_tls13_cb( + ssl, ssl->arrays->server_hint, + ssl->arrays->client_identity, MAX_PSK_ID_LEN, + ssl->arrays->psk_key, MAX_PSK_KEY_LEN, &cipherName); + if (GetCipherSuiteFromName(cipherName, &cipherSuite0, + &cipherSuite) != 0) { + return PSK_KEY_ERROR; + } + } + else { + 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) || \ + defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) + 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 } - if (offset > OPAQUE16_LEN) - c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ - } + #endif - return offset; + (void)isServer; + (void)public_key; + (void)public_key_len; + (void)ssl; + + return ret; } -#endif /* NO_WOLFSSL_CLIENT */ -#ifndef NO_WOLFSSL_SERVER +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT) -word16 TLSX_GetResponseSize(WOLFSSL* ssl) +/** Tells the buffered size of extensions to be sent into the client hello. */ +int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word16* pLength) { + int ret = 0; word16 length = 0; byte semaphore[SEMAPHORE_SIZE] = {0}; - if (TLSX_SupportExtensions(ssl)) - length += TLSX_GetSize(ssl->extensions, semaphore, 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); + WOLF_STK_VALIDATE_REQUEST(ssl); +#if !defined(WOLFSSL_NO_SIGALG) + if (ssl->suites->hashSigAlgoSz == 0) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#endif +#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); +#if !defined(WOLFSSL_NO_SIGALG) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#endif + /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, + * TLSX_CERTIFICATE_AUTHORITIES, OID_FILTERS + * TLSX_STATUS_REQUEST + */ + } + #endif +#endif + if (ssl->extensions) { + ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length); + if (ret != 0) + return ret; + } + if (ssl->ctx && ssl->ctx->extensions) { + ret = TLSX_GetSize(ssl->ctx->extensions, semaphore, msgType, &length); + if (ret != 0) + return ret; + } + +#ifdef HAVE_EXTENDED_MASTER + if (msgType == client_hello && ssl->options.haveEMS && + (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)) { + length += HELLO_EXT_SZ; + } +#endif + + if (length) + length += OPAQUE16_LEN; /* for total length storage. */ + + *pLength += length; + + return ret; +} + +/** Writes the extensions to be sent into the client hello. */ +int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset) +{ + int ret = 0; + word16 offset = 0; + byte semaphore[SEMAPHORE_SIZE] = {0}; + + if (!TLSX_SupportExtensions(ssl) || output == NULL) + return 0; + + offset += OPAQUE16_LEN; /* extensions length */ + + if (msgType == client_hello) { + EC_VALIDATE_REQUEST(ssl, semaphore); + PF_VALIDATE_REQUEST(ssl, semaphore); + WOLF_STK_VALIDATE_REQUEST(ssl); + QSH_VALIDATE_REQUEST(ssl, semaphore); +#if !defined(WOLFSSL_NO_SIGALG) + if (ssl->suites->hashSigAlgoSz == 0) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#endif +#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 + } + #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_CERTS + else if (msgType == certificate_request) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); +#if !defined(WOLFSSL_NO_SIGALG) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#endif + /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, + * TLSX_CERTIFICATE_AUTHORITIES, TLSX_OID_FILTERS + * TLSX_STATUS_REQUEST + */ + } + #endif +#endif + if (ssl->extensions) { + ret = TLSX_Write(ssl->extensions, output + offset, semaphore, + msgType, &offset); + if (ret != 0) + return ret; + } + if (ssl->ctx && ssl->ctx->extensions) { + ret = TLSX_Write(ssl->ctx->extensions, output + offset, semaphore, + msgType, &offset); + if (ret != 0) + return ret; + } + +#ifdef HAVE_EXTENDED_MASTER + if (msgType == client_hello && ssl->options.haveEMS && + (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)) { + WOLFSSL_MSG("EMS extension to write"); + 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)); + ret = TLSX_Write(ssl->extensions, output + offset, semaphore, + client_hello, &offset); + if (ret != 0) + return ret; + } + #endif +#endif + + if (offset > OPAQUE16_LEN || msgType != client_hello) + c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ + + *pOffset += offset; + + return ret; +} + +#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */ + +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER) + +/** Tells the buffered size of extensions to be sent into the server hello. */ +int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength) +{ + int ret = 0; + word16 length = 0; + byte semaphore[SEMAPHORE_SIZE] = {0}; + + switch (msgType) { +#ifndef NO_WOLFSSL_SERVER + case server_hello: + PF_VALIDATE_RESPONSE(ssl, semaphore); + #ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + #ifndef WOLFSSL_TLS13_DRAFT_18 + TURN_OFF(semaphore, + TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + #endif + if (!ssl->options.noPskDheKe) + 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); + #ifndef WOLFSSL_TLS13_DRAFT_18 + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + #endif + if (!ssl->options.noPskDheKe) + 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_SUPPORTED_VERSIONS)); + 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 + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + #endif + #if defined(HAVE_SECURE_RENEGOTIATION) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO)); + #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 + #endif +#endif + +#ifdef WOLFSSL_TLS13 + #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 +#endif + } + + #ifdef HAVE_QSH + /* change response if not using TLS_QSH */ + if (!ssl->options.haveQSH) { + TLSX* ext = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID); + if (ext) + ext->resp = 0; + } + #endif + +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS && msgType == server_hello && + !IsAtLeastTLSv1_3(ssl->version)) { + length += HELLO_EXT_SZ; + } +#endif + + if (TLSX_SupportExtensions(ssl)) { + ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length); + if (ret != 0) + return ret; + } /* All the response data is set at the ssl object only, so no ctx here. */ - if (length) - length += OPAQUE16_LEN; /* for total length storage */ + if (length || msgType != server_hello) + length += OPAQUE16_LEN; /* for total length storage. */ - return length; + *pLength += length; + + return ret; } -word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output) +/** Writes the server hello extensions into a buffer. */ +int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset) { + int ret = 0; word16 offset = 0; if (TLSX_SupportExtensions(ssl) && output) { byte semaphore[SEMAPHORE_SIZE] = {0}; + switch (msgType) { +#ifndef NO_WOLFSSL_SERVER + case server_hello: + PF_VALIDATE_RESPONSE(ssl, semaphore); + #ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + #ifndef WOLFSSL_TLS13_DRAFT_18 + TURN_OFF(semaphore, + TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + #endif + if (!ssl->options.noPskDheKe) + 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); + #ifndef WOLFSSL_TLS13_DRAFT_18 + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + #endif + if (!ssl->options.noPskDheKe) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + /* Cookie is written below as last extension. */ + break; + #endif + + #ifdef WOLFSSL_TLS13 + case encrypted_extensions: + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + 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 + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + #endif + #if defined(HAVE_SECURE_RENEGOTIATION) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO)); + #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 + #endif +#endif + + #ifdef WOLFSSL_TLS13 + #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 + #endif + } + offset += OPAQUE16_LEN; /* extensions length */ - offset += TLSX_Write(ssl->extensions, output + offset, semaphore, 0); + ret = TLSX_Write(ssl->extensions, output + offset, semaphore, + msgType, &offset); + if (ret != 0) + return ret; - if (offset > OPAQUE16_LEN) +#ifdef WOLFSSL_TLS13 + if (msgType == hello_retry_request) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE)); + ret = TLSX_Write(ssl->extensions, output + offset, semaphore, + msgType, &offset); + if (ret != 0) + return ret; + } +#endif + +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS && msgType == server_hello && + !IsAtLeastTLSv1_3(ssl->version)) { + WOLFSSL_MSG("EMS extension to write"); + c16toa(HELLO_EXT_EXTMS, output + offset); + offset += HELLO_EXT_TYPE_SZ; + c16toa(0, output + offset); + offset += HELLO_EXT_SZ_SZ; + } +#endif + + if (offset > OPAQUE16_LEN || msgType != server_hello) c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ } - return offset; + if (pOffset) + *pOffset += offset; + + return ret; } -#endif /* NO_WOLFSSL_SERVER */ +#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_SERVER */ -int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, +#ifdef WOLFSSL_TLS13 +int TLSX_ParseVersion(WOLFSSL* ssl, byte* input, word16 length, byte msgType, + int* found) +{ + int ret = 0; + int offset = 0; + + *found = 0; + while (offset < (int)length) { + word16 type; + word16 size; + + if (offset + (2 * OPAQUE16_LEN) > length) { + ret = BUFFER_ERROR; + break; + } + + ato16(input + offset, &type); + offset += HELLO_EXT_TYPE_SZ; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN; + + if (offset + size > length) { + ret = BUFFER_ERROR; + break; + } + + if (type == TLSX_SUPPORTED_VERSIONS) { + *found = 1; + + WOLFSSL_MSG("Supported Versions extension received"); + + ret = SV_PARSE(ssl, input + offset, size, msgType); + break; + } + + offset += size; + } + + return ret; +} +#endif + +/** Parses a buffer of TLS extensions. */ +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 +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) + int pskDone = 0; +#endif if (!ssl || !input || (isRequest && !suites)) return BAD_FUNC_ARG; @@ -2222,6 +10766,11 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, word16 type; word16 size; +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) + if (msgType == client_hello && pskDone) + return PSK_KEY_ERROR; +#endif + if (length - offset < HELLO_EXT_TYPE_SZ + OPAQUE16_LEN) return BUFFER_ERROR; @@ -2235,67 +10784,416 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, return BUFFER_ERROR; switch (type) { - case SERVER_NAME_INDICATION: + case TLSX_SERVER_NAME: WOLFSSL_MSG("SNI extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != server_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + else if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = SNI_PARSE(ssl, input + offset, size, isRequest); break; - case MAX_FRAGMENT_LENGTH: - WOLFSSL_MSG("Max Fragment Length extension received"); + case TLSX_TRUSTED_CA_KEYS: + WOLFSSL_MSG("Trusted CA extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif + ret = TCA_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_MAX_FRAGMENT_LENGTH: + WOLFSSL_MSG("Max Fragment Length extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + else if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = MFL_PARSE(ssl, input + offset, size, isRequest); break; - case TRUNCATED_HMAC: + case TLSX_TRUNCATED_HMAC: WOLFSSL_MSG("Truncated HMAC extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + break; +#endif ret = THM_PARSE(ssl, input + offset, size, isRequest); break; - case ELLIPTIC_CURVES: - WOLFSSL_MSG("Elliptic Curves extension received"); + case TLSX_SUPPORTED_GROUPS: + WOLFSSL_MSG("Supported Groups extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != server_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + else if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = EC_PARSE(ssl, input + offset, size, isRequest); break; - case SECURE_RENEGOTIATION: - WOLFSSL_MSG("Secure Renegotiation extension received"); + case TLSX_EC_POINT_FORMATS: + WOLFSSL_MSG("Point Formats extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + break; +#endif + ret = PF_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_STATUS_REQUEST: + WOLFSSL_MSG("Certificate Status Request extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + #ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != certificate_request && + msgType != certificate) { + break; + } + #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_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != certificate_request && + msgType != certificate) { + return EXT_NOT_ALLOWED; + } +#endif + ret = CSR2_PARSE(ssl, input + offset, size, isRequest); + break; + +#ifdef HAVE_EXTENDED_MASTER + case HELLO_EXT_EXTMS: + WOLFSSL_MSG("Extended Master Secret extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + break; +#endif + if (size != 0) + return BUFFER_ERROR; + +#ifndef NO_WOLFSSL_SERVER + if (isRequest) + ssl->options.haveEMS = 1; +#endif + pendingEMS = 1; + break; +#endif + + case TLSX_RENEGOTIATION_INFO: + WOLFSSL_MSG("Secure Renegotiation extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + break; +#endif ret = SCR_PARSE(ssl, input + offset, size, isRequest); break; - case SESSION_TICKET: + case TLSX_SESSION_TICKET: WOLFSSL_MSG("Session Ticket extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif - 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 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_QUANTUM_SAFE_HYBRID: + WOLFSSL_MSG("Quantum-Safe-Hybrid extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif - if (suites->hashSigAlgoSz > size - OPAQUE16_LEN) - return BUFFER_ERROR; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + break; +#endif + ret = QSH_PARSE(ssl, input + offset, size, isRequest); + 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."); + case TLSX_APPLICATION_LAYER_PROTOCOL: + WOLFSSL_MSG("ALPN extension received"); + + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != server_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + else if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif + ret = ALPN_PARSE(ssl, input + offset, size, isRequest); + break; +#if !defined(WOLFSSL_NO_SIGALG) + case TLSX_SIGNATURE_ALGORITHMS: + WOLFSSL_MSG("Signature Algorithms extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_2(ssl)) + break; +#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; +#endif + +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + case TLSX_ENCRYPT_THEN_MAC: + WOLFSSL_MSG("Encrypt-Then-Mac extension received"); + + /* Ignore for TLS 1.3+ */ + if (IsAtLeastTLSv1_3(ssl->version)) + break; + + ret = ETM_PARSE(ssl, input + offset, size, msgType); + break; +#endif /* HAVE_ENCRYPT_THEN_MAC */ + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + WOLFSSL_MSG("Skipping Supported Versions - already processed"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + break; + + case TLSX_COOKIE: + WOLFSSL_MSG("Cookie extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello && + msgType != hello_retry_request) { + return EXT_NOT_ALLOWED; } + ret = CKE_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"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello && msgType != server_hello) + return EXT_NOT_ALLOWED; + + ret = PSK_PARSE(ssl, input + offset, size, msgType); + pskDone = 1; + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + WOLFSSL_MSG("PSK Key Exchange Modes extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (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"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello && msgType != session_ticket && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + if (!IsAtLeastTLSv1_3(ssl->version) && + (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("Post Handshake Authentication extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello) + return EXT_NOT_ALLOWED; + + ret = PHA_PARSE(ssl, input + offset, size, msgType); + break; + #endif + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + case TLSX_SIGNATURE_ALGORITHMS_CERT: + WOLFSSL_MSG("Signature Algorithms extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello && + msgType != certificate_request) { + return EXT_NOT_ALLOWED; + } + if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == certificate_request) { + return EXT_NOT_ALLOWED; + } + + ret = SAC_PARSE(ssl, input + offset, size, isRequest); + break; + #endif + + case TLSX_KEY_SHARE: + WOLFSSL_MSG("Key Share extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello && msgType != server_hello && + msgType != hello_retry_request) { + return EXT_NOT_ALLOWED; + } + ret = KS_PARSE(ssl, input + offset, size, msgType); + break; +#endif + default: + WOLFSSL_MSG("Unknown TLS extension type"); } /* offset should be updated here! */ offset += size; } +#ifdef HAVE_EXTENDED_MASTER + if (!isRequest && ssl->options.haveEMS && !pendingEMS) + ssl->options.haveEMS = 0; +#endif + + if (ret == 0) + ret = SNI_VERIFY_PARSE(ssl, isRequest); + if (ret == 0) + ret = TCA_VERIFY_PARSE(ssl, isRequest); + return ret; } @@ -2304,143 +11202,554 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, #undef TURN_ON #undef SEMAPHORE_SIZE -#endif - +#endif /* HAVE_TLS_EXTENSIONS */ #ifndef NO_WOLFSSL_CLIENT -#ifndef NO_OLD_TLS - - WOLFSSL_METHOD* wolfTLSv1_client_method(void) + WOLFSSL_METHOD* wolfTLS_client_method(void) { - WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, - DYNAMIC_TYPE_METHOD); - if (method) - InitSSL_Method(method, MakeTLSv1()); - return method; + return wolfTLS_client_method_ex(NULL); } - - - WOLFSSL_METHOD* wolfTLSv1_1_client_method(void) + WOLFSSL_METHOD* wolfTLS_client_method_ex(void* heap) { WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, - DYNAMIC_TYPE_METHOD); - if (method) - InitSSL_Method(method, MakeTLSv1_1()); - return method; - } - -#endif /* !NO_OLD_TLS */ - -#ifndef NO_SHA256 /* can't use without SHA256 */ - - WOLFSSL_METHOD* wolfTLSv1_2_client_method(void) - { - WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, - DYNAMIC_TYPE_METHOD); - if (method) - InitSSL_Method(method, MakeTLSv1_2()); - return method; - } - -#endif - - - WOLFSSL_METHOD* wolfSSLv23_client_method(void) - { - WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, - DYNAMIC_TYPE_METHOD); + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLS_client_method_ex"); if (method) { -#ifndef NO_SHA256 /* 1.2 requires SHA256 */ + #if defined(WOLFSSL_TLS13) + InitSSL_Method(method, MakeTLSv1_3()); + #elif !defined(WOLFSSL_NO_TLS12) InitSSL_Method(method, MakeTLSv1_2()); -#else + #elif !defined(NO_OLD_TLS) InitSSL_Method(method, MakeTLSv1_1()); -#endif -#ifndef NO_OLD_TLS + #elif defined(WOLFSSL_ALLOW_TLSV10) + InitSSL_Method(method, MakeTLSv1()); + #else + #error No TLS version enabled! + #endif + method->downgrade = 1; -#endif + method->side = WOLFSSL_CLIENT_END; } return method; } +#ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 + WOLFSSL_METHOD* wolfTLSv1_client_method(void) + { + return wolfTLSv1_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_client_method_ex"); + if (method) + 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) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_1_client_method_ex"); + if (method) + InitSSL_Method(method, MakeTLSv1_1()); + return method; + } +#endif /* !NO_OLD_TLS */ + +#ifndef WOLFSSL_NO_TLS12 + WOLFSSL_ABI + WOLFSSL_METHOD* wolfTLSv1_2_client_method(void) + { + return wolfTLSv1_2_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_2_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_2_client_method_ex"); + if (method) + InitSSL_Method(method, MakeTLSv1_2()); + return method; + } +#endif /* WOLFSSL_NO_TLS12 */ + +#ifdef WOLFSSL_TLS13 + /* The TLS v1.3 client method data. + * + * returns the method data for a TLS v1.3 client. + */ + WOLFSSL_ABI + 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; + WOLFSSL_ENTER("TLSv1_3_client_method_ex"); + if (method) + InitSSL_Method(method, MakeTLSv1_3()); + return method; + } +#endif /* WOLFSSL_TLS13 */ + +#ifdef WOLFSSL_DTLS + + WOLFSSL_METHOD* wolfDTLS_client_method(void) + { + return wolfDTLS_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLS_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLS_client_method_ex"); + if (method) { + #if !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeDTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeDTLSv1()); + #else + #error No DTLS version enabled! + #endif + + method->downgrade = 1; + method->side = WOLFSSL_CLIENT_END; + } + return method; + } + + #ifndef NO_OLD_TLS + WOLFSSL_METHOD* wolfDTLSv1_client_method(void) + { + return wolfDTLSv1_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLSv1_client_method_ex"); + if (method) + InitSSL_Method(method, MakeDTLSv1()); + return method; + } + #endif /* NO_OLD_TLS */ + + #ifndef WOLFSSL_NO_TLS12 + WOLFSSL_METHOD* wolfDTLSv1_2_client_method(void) + { + return wolfDTLSv1_2_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_2_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLSv1_2_client_method_ex"); + if (method) + InitSSL_Method(method, MakeDTLSv1_2()); + (void)heap; + return method; + } + #endif /* !WOLFSSL_NO_TLS12 */ +#endif /* WOLFSSL_DTLS */ #endif /* NO_WOLFSSL_CLIENT */ +/* EITHER SIDE METHODS */ +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + #ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 + /* Gets a WOLFSL_METHOD type that is not set as client or server + * + * Returns a pointer to a WOLFSSL_METHOD struct + */ + WOLFSSL_METHOD* wolfTLSv1_method(void) + { + return wolfTLSv1_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("TLSv1_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfTLSv1_client_method_ex(heap); + #else + m = wolfTLSv1_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + + return m; + } + #endif /* WOLFSSL_ALLOW_TLSV10 */ + + /* Gets a WOLFSL_METHOD type that is not set as client or server + * + * Returns a pointer to a WOLFSSL_METHOD struct + */ + WOLFSSL_METHOD* wolfTLSv1_1_method(void) + { + return wolfTLSv1_1_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_1_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("TLSv1_1_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfTLSv1_1_client_method_ex(heap); + #else + m = wolfTLSv1_1_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* !NO_OLD_TLS */ + + #ifndef WOLFSSL_NO_TLS12 + /* Gets a WOLFSL_METHOD type that is not set as client or server + * + * Returns a pointer to a WOLFSSL_METHOD struct + */ + WOLFSSL_METHOD* wolfTLSv1_2_method(void) + { + return wolfTLSv1_2_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_2_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("TLSv1_2_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfTLSv1_2_client_method_ex(heap); + #else + m = wolfTLSv1_2_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* !WOLFSSL_NO_TLS12 */ + + #ifdef WOLFSSL_TLS13 + /* Gets a WOLFSL_METHOD type that is not set as client or server + * + * Returns a pointer to a WOLFSSL_METHOD struct + */ + WOLFSSL_METHOD* wolfTLSv1_3_method(void) + { + return wolfTLSv1_3_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_3_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("TLSv1_3_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfTLSv1_3_client_method_ex(heap); + #else + m = wolfTLSv1_3_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* WOLFSSL_TLS13 */ + +#ifdef WOLFSSL_DTLS + WOLFSSL_METHOD* wolfDTLS_method(void) + { + return wolfDTLS_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLS_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("DTLS_method_ex"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfDTLS_client_method_ex(heap); + #else + m = wolfDTLS_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + + #ifndef NO_OLD_TLS + WOLFSSL_METHOD* wolfDTLSv1_method(void) + { + return wolfDTLSv1_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("DTLSv1_method_ex"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfDTLSv1_client_method_ex(heap); + #else + m = wolfDTLSv1_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* !NO_OLD_TLS */ + #ifndef WOLFSSL_NO_TLS12 + WOLFSSL_METHOD* wolfDTLSv1_2_method(void) + { + return wolfDTLSv1_2_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_2_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("DTLSv1_2_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfDTLSv1_2_client_method_ex(heap); + #else + m = wolfDTLSv1_2_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* !WOLFSSL_NO_TLS12 */ +#endif /* WOLFSSL_DTLS */ +#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ + #ifndef NO_WOLFSSL_SERVER -#ifndef NO_OLD_TLS + WOLFSSL_METHOD* wolfTLS_server_method(void) + { + return wolfTLS_server_method_ex(NULL); + } - WOLFSSL_METHOD* wolfTLSv1_server_method(void) + WOLFSSL_METHOD* wolfTLS_server_method_ex(void* heap) { WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, - DYNAMIC_TYPE_METHOD); + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLS_server_method_ex"); + if (method) { + #if defined(WOLFSSL_TLS13) + InitSSL_Method(method, MakeTLSv1_3()); + #elif !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeTLSv1_1()); + #elif defined(WOLFSSL_ALLOW_TLSV10) + InitSSL_Method(method, MakeTLSv1()); + #else + #error No TLS version enabled! + #endif + + method->downgrade = 1; + method->side = WOLFSSL_SERVER_END; + } + return method; + } + +#ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 + WOLFSSL_METHOD* wolfTLSv1_server_method(void) + { + return wolfTLSv1_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_server_method_ex"); if (method) { InitSSL_Method(method, MakeTLSv1()); method->side = WOLFSSL_SERVER_END; } 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) { WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, - DYNAMIC_TYPE_METHOD); + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_1_server_method_ex"); if (method) { InitSSL_Method(method, MakeTLSv1_1()); method->side = WOLFSSL_SERVER_END; } return method; } - #endif /* !NO_OLD_TLS */ -#ifndef NO_SHA256 /* can't use without SHA256 */ +#ifndef WOLFSSL_NO_TLS12 WOLFSSL_METHOD* wolfTLSv1_2_server_method(void) + { + return wolfTLSv1_2_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_2_server_method_ex(void* heap) { WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), 0, - DYNAMIC_TYPE_METHOD); + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_2_server_method_ex"); if (method) { InitSSL_Method(method, MakeTLSv1_2()); method->side = WOLFSSL_SERVER_END; } return method; } +#endif /* !WOLFSSL_NO_TLS12 */ -#endif +#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); + } - - WOLFSSL_METHOD* wolfSSLv23_server_method(void) + /* 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), 0, - DYNAMIC_TYPE_METHOD); + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_3_server_method_ex"); if (method) { -#ifndef NO_SHA256 /* 1.2 requires SHA256 */ - InitSSL_Method(method, MakeTLSv1_2()); -#else - InitSSL_Method(method, MakeTLSv1_1()); -#endif - method->side = WOLFSSL_SERVER_END; -#ifndef NO_OLD_TLS + InitSSL_Method(method, MakeTLSv1_3()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } +#endif /* WOLFSSL_TLS13 */ + +#ifdef WOLFSSL_DTLS + WOLFSSL_METHOD* wolfDTLS_server_method(void) + { + return wolfDTLS_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLS_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLS_server_method_ex"); + if (method) { + #if !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeDTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeDTLSv1()); + #else + #error No DTLS version enabled! + #endif + method->downgrade = 1; -#endif /* !NO_OLD_TLS */ + method->side = WOLFSSL_SERVER_END; } return method; } + #ifndef NO_OLD_TLS + WOLFSSL_METHOD* wolfDTLSv1_server_method(void) + { + return wolfDTLSv1_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLSv1_server_method_ex"); + if (method) { + InitSSL_Method(method, MakeDTLSv1()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } + #endif /* !NO_OLD_TLS */ + #ifndef WOLFSSL_NO_TLS12 + WOLFSSL_METHOD* wolfDTLSv1_2_server_method(void) + { + return wolfDTLSv1_2_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_2_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + WOLFSSL_ENTER("DTLSv1_2_server_method_ex"); + (void)heap; + if (method) { + InitSSL_Method(method, MakeDTLSv1_2()); + method->side = WOLFSSL_SERVER_END; + } + (void)heap; + return method; + } + #endif /* !WOLFSSL_NO_TLS12 */ +#endif /* WOLFSSL_DTLS */ #endif /* NO_WOLFSSL_SERVER */ -#endif /* NO_TLS */ +#endif /* NO_TLS */ +#endif /* WOLFCRYPT_ONLY */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/tls13.c b/FreeRTOS-Plus/Source/WolfSSL/src/tls13.c new file mode 100644 index 000000000..9b9b1d1b9 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/src/tls13.c @@ -0,0 +1,9048 @@ +/* tls13.c + * + * Copyright (C) 2006-2020 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 + */ + + +/* + * BUILD_GCM + * Enables AES-GCM ciphersuites. + * HAVE_AESCCM + * Enables AES-CCM ciphersuites. + * HAVE_SESSION_TICKET + * Enables session tickets - required for TLS 1.3 resumption. + * NO_PSK + * Do not enable Pre-Shared Keys. + * TLS13_SUPPORTS_EXPORTERS + * Guard to compile out any code for exporter keys. + * Feature not supported yet. + * WOLFSSL_ASYNC_CRYPT + * Enables the use of asynchronous cryptographic operations. + * This is available for ciphers and certificates. + * HAVE_CHACHA && HAVE_POLY1305 + * Enables use of CHACHA20-POLY1305 ciphersuites. + * WOLFSSL_DEBUG_TLS + * Writes out details of TLS 1.3 protocol including handshake message buffers + * and key generation input and output. + * WOLFSSL_EARLY_DATA + * Allow 0-RTT Handshake using Early Data extensions and handshake message + * WOLFSSL_EARLY_DATA_GROUP + * Group EarlyData message with ClientHello when sending + * WOLFSSL_NO_SERVER_GROUPS_EXT + * Do not send the server's groups in an extension when the server's top + * preference is not in client's list. + * WOLFSSL_POST_HANDSHAKE_AUTH + * Allow TLS v1.3 code to perform post-handshake authentication of the + * client. + * WOLFSSL_SEND_HRR_COOKIE + * Send a cookie in hello_retry_request message to enable stateless tracking + * of ClientHello replies. + * WOLFSSL_TLS13 + * Enable TLS 1.3 protocol implementation. + * WOLFSSL_TLS13_DRAFT_18 + * Conform with Draft 18 of the TLS v1.3 specification. + * WOLFSSL_TLS13_DRAFT_22 + * Conform with Draft 22 of the TLS v1.3 specification. + * WOLFSSL_TLS13_DRAFT_23 + * Conform with Draft 23 of the TLS v1.3 specification. + * WOLFSSL_TLS13_MIDDLEBOX_COMPAT + * Enable middlebox compatibility in the TLS 1.3 handshake. + * This includes sending ChangeCipherSpec before encrypted messages and + * including a session id. + * WOLFSSL_TLS13_SHA512 + * Allow generation of SHA-512 digests in handshake - no ciphersuite + * requires SHA-512 at this time. + * WOLFSSL_TLS13_TICKET_BEFORE_FINISHED + * Allow a NewSessionTicket message to be sent by server before Client's + * Finished message. + * See TLS v1.3 specification, Section 4.6.1, Paragraph 4 (Note). + */ + +#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 + +#ifdef __sun + #include +#endif + +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef HAVE_HKDF + #error The build option HAVE_HKDF is required for TLS 1.3 +#endif + +#ifndef HAVE_TLS_EXTENSIONS + #ifndef _MSC_VER + #error "The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3" + #else + #pragma message("error: The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3") + #endif +#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_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++] = (byte)(okmLen >> 8); + data[idx++] = (byte)okmLen; + /* Length of protocol | label. */ + data[idx++] = (byte)(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++] = (byte)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[WC_MAX_DIGEST_SIZE]; + Digest digest; + word32 hashSz = 0; + const byte* protocol; + word32 protocolLen; + int digestAlg = -1; + 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 + default: + digestAlg = -1; + break; + } + + if (digestAlg < 0) + return HASH_TYPE_E; + + 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[WC_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) +{ + int ret; + WOLFSSL_MSG("Derive Early Traffic Secret"); + ret = DeriveKey(ssl, key, -1, ssl->arrays->secret, + earlyTrafficLabel, EARLY_TRAFFIC_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +#ifdef HAVE_SECRET_CALLBACK + if (ret == 0 && ssl->tls13SecretCb != NULL) { + ret = ssl->tls13SecretCb(ssl, CLIENT_EARLY_TRAFFIC_SECRET, key, + ssl->specs.hash_size, ssl->tls13SecretCtx); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* HAVE_SECRET_CALLBACK */ + return ret; +} + +#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) +{ + int ret; + WOLFSSL_MSG("Derive Early Exporter Secret"); + ret = DeriveKey(ssl, key, -1, ssl->arrays->secret, + earlyExporterLabel, EARLY_EXPORTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +#ifdef HAVE_SECRET_CALLBACK + if (ret == 0 && ssl->tls13SecretCb != NULL) { + ret = ssl->tls13SecretCb(ssl, EARLY_EXPORTER_SECRET, key + ssl->specs.hash_size, ssl->tls13SecretCtx); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* HAVE_SECRET_CALLBACK */ + return ret; +} +#endif +#endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the client handshake label. */ +#define CLIENT_HANDSHAKE_LABEL_SZ 31 +/* The client handshake label. */ +static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] = + "client handshake traffic secret"; +#else +/* The length of the client handshake label. */ +#define CLIENT_HANDSHAKE_LABEL_SZ 12 +/* The client handshake 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) +{ + int ret; + WOLFSSL_MSG("Derive Client Handshake Secret"); + ret = DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret, + clientHandshakeLabel, CLIENT_HANDSHAKE_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +#ifdef HAVE_SECRET_CALLBACK + if (ret == 0 && ssl->tls13SecretCb != NULL) { + ret = ssl->tls13SecretCb(ssl, CLIENT_HANDSHAKE_TRAFFIC_SECRET, key, + ssl->specs.hash_size, ssl->tls13SecretCtx); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* HAVE_SECRET_CALLBACK */ + return ret; +} + +#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) +{ + int ret; + WOLFSSL_MSG("Derive Server Handshake Secret"); + ret = DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret, + serverHandshakeLabel, SERVER_HANDSHAKE_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +#ifdef HAVE_SECRET_CALLBACK + if (ret == 0 && ssl->tls13SecretCb != NULL) { + ret = ssl->tls13SecretCb(ssl, SERVER_HANDSHAKE_TRAFFIC_SECRET, key, + ssl->specs.hash_size, ssl->tls13SecretCtx); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* HAVE_SECRET_CALLBACK */ + return ret; +} + +#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) +{ + int ret; + WOLFSSL_MSG("Derive Client Traffic Secret"); + ret = DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + clientAppLabel, CLIENT_APP_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +#ifdef HAVE_SECRET_CALLBACK + if (ret == 0 && ssl->tls13SecretCb != NULL) { + ret = ssl->tls13SecretCb(ssl, CLIENT_TRAFFIC_SECRET, key, + ssl->specs.hash_size, ssl->tls13SecretCtx); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* HAVE_SECRET_CALLBACK */ + return ret; +} + +#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) +{ + int ret; + WOLFSSL_MSG("Derive Server Traffic Secret"); + ret = DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + serverAppLabel, SERVER_APP_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +#ifdef HAVE_SECRET_CALLBACK + if (ret == 0 && ssl->tls13SecretCb != NULL) { + ret = ssl->tls13SecretCb(ssl, SERVER_TRAFFIC_SECRET, key, + ssl->specs.hash_size, ssl->tls13SecretCtx); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* HAVE_SECRET_CALLBACK */ + return ret; +} + +#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) +{ + int ret; + WOLFSSL_MSG("Derive Exporter Secret"); + ret = DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + exporterMasterLabel, EXPORTER_MASTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +#ifdef HAVE_SECRET_CALLBACK + if (ret == 0 && ssl->tls13SecretCb != NULL) { + ret = ssl->tls13SecretCb(ssl, EXPORTER_SECRET, key, + ssl->specs.hash_size, ssl->tls13SecretCtx); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* HAVE_SECRET_CALLBACK */ + return ret; +} +#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 associated with the ticket. */ +static const byte resumptionLabel[RESUMPTION_LABEL_SZ+1] = "resumption"; +/* Derive the PSK associated 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_SHA384; + break; + #endif + + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + digestAlg = WC_SHA512; + 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 = BAD_FUNC_ARG; /* Assume failure */ + 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->clientSecret); + if (ret != 0) + goto end; + break; +#endif + + case handshake_key: + if (provision & PROVISION_CLIENT) { + ret = DeriveClientHandshakeSecret(ssl, + ssl->clientSecret); + if (ret != 0) + goto end; + } + if (provision & PROVISION_SERVER) { + ret = DeriveServerHandshakeSecret(ssl, + ssl->serverSecret); + if (ret != 0) + goto end; + } + break; + + case traffic_key: + if (provision & PROVISION_CLIENT) { + ret = DeriveClientTrafficSecret(ssl, ssl->clientSecret); + if (ret != 0) + goto end; + } + if (provision & PROVISION_SERVER) { + ret = DeriveServerTrafficSecret(ssl, ssl->serverSecret); + if (ret != 0) + goto end; + } + break; + + case update_traffic_key: + if (provision & PROVISION_CLIENT) { + ret = DeriveTrafficSecret(ssl, ssl->clientSecret); + if (ret != 0) + goto end; + } + if (provision & PROVISION_SERVER) { + ret = DeriveTrafficSecret(ssl, ssl->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->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->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->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->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(XTIME_MS) + word32 TimeNowInMilliseconds(void) + { + return (word32)XTIME_MS(0); + } + +#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(WOLFSSL_DEOS) + word32 TimeNowInMilliseconds(void) + { + const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds(); + uint32_t *systemTickPtr = systemTickPointer(); + + return (word32) (*systemTickPtr/systemTickTimeInHz) * 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 handshake 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; +#ifdef WOLFSSL_TLS13_DRAFT_18 + rl->pvMinor = TLSv1_MINOR; +#else + /* NOTE: May be TLSv1_MINOR when sending first ClientHello. */ + rl->pvMinor = TLSv1_2_MINOR; +#endif + c16toa((word16)length, rl->length); +} + +/* Add handshake header to message. + * + * output The buffer to write the handshake 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 fragment 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 WC_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 WC_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. + * aad The additional authentication data. + * aadSz The size of the addition authentication data. + * 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, + const byte* aad, word16 aadSz, 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; + ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 1); + 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, (byte*)aad, aadSz, output, sz, + tag, POLY1305_AUTH_SZ); + + return ret; +} +#endif + +#ifdef HAVE_NULL_CIPHER +/* Create authenication tag and copy data over input. + * + * ssl The SSL/TLS object. + * output The buffer to copy data into. + * May be the same pointer as input. + * input The data. + * sz The number of bytes of data. + * nonce The nonce to use with authentication. + * aad The additional authentication data. + * aadSz The size of the addition authentication data. + * tag The authentication tag buffer. + * returns 0 on success, otherwise failure. + */ +static int Tls13IntegrityOnly_Encrypt(WOLFSSL* ssl, byte* output, + const byte* input, word16 sz, + const byte* nonce, + const byte* aad, word16 aadSz, byte* tag) +{ + int ret; + + /* HMAC: nonce | aad | input */ + ret = wc_HmacUpdate(ssl->encrypt.hmac, nonce, HMAC_NONCE_SZ); + if (ret == 0) + ret = wc_HmacUpdate(ssl->encrypt.hmac, aad, aadSz); + if (ret == 0) + ret = wc_HmacUpdate(ssl->encrypt.hmac, input, sz); + if (ret == 0) + ret = wc_HmacFinal(ssl->encrypt.hmac, tag); + /* Copy the input to output if not the same buffer */ + if (ret == 0 && output != input) + XMEMCPY(output, input, 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 record header and data to encrypt. + * sz The number of bytes to encrypt. + * aad The additional authentication data. + * aadSz The size of the addition authentication data. + * 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, const byte* aad, word16 aadSz, 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); +#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \ + !defined(WOLFSSL_TLS13_DRAFT_23) + WOLFSSL_MSG("Additional Authentication Data"); + WOLFSSL_BUFFER(aad, aadSz); +#endif + #endif + + #ifdef CIPHER_NONCE + 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); + #endif + + /* 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 + /* initialize event */ + asyncDev = &ssl->encrypt.aes->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) + break; + #endif + + nonceSz = AESGCM_NONCE_SZ; + #if ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) + ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input, + dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, aad, aadSz); + #else + ret = wc_AesGcmSetExtIV(ssl->encrypt.aes, + ssl->encrypt.nonce, nonceSz); + if (ret == 0) { + ret = wc_AesGcmEncrypt_ex(ssl->encrypt.aes, output, + input, dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, aad, aadSz); + } + #endif + break; + #endif + + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + asyncDev = &ssl->encrypt.aes->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) + break; + #endif + + nonceSz = AESCCM_NONCE_SZ; + #if ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) + ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input, + dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, aad, aadSz); + #else + ret = wc_AesCcmSetNonce(ssl->encrypt.aes, + ssl->encrypt.nonce, nonceSz); + if (ret == 0) { + ret = wc_AesCcmEncrypt_ex(ssl->encrypt.aes, output, + input, dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, aad, aadSz); + } + #endif + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz, + ssl->encrypt.nonce, aad, aadSz, output + dataSz); + break; + #endif + + #ifdef HAVE_NULL_CIPHER + case wolfssl_cipher_null: + ret = Tls13IntegrityOnly_Encrypt(ssl, output, input, dataSz, + ssl->encrypt.nonce, aad, aadSz, 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 + #ifdef CIPHER_NONCE + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(ssl->encrypt.nonce, ssl->specs.iv_size); + #endif + WOLFSSL_MSG("Encrypted data"); + WOLFSSL_BUFFER(output, dataSz); + WOLFSSL_MSG("Authentication Tag"); + WOLFSSL_BUFFER(output + dataSz, macSz); + #endif + + #ifdef CIPHER_NONCE + ForceZero(ssl->encrypt.nonce, AEAD_NONCE_SZ); + #endif + + 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. + * aad The additional authentication data. + * aadSz The size of the addition authentication data. + * 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* aad, word16 aadSz, + 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; + ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 1); + 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, (byte*)aad, aadSz, + (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 + +#ifdef HAVE_NULL_CIPHER +/* Check HMAC tag and copy over input. + * + * ssl The SSL/TLS object. + * output The buffer to copy data into. + * May be the same pointer as input. + * input The data. + * sz The number of bytes of data. + * nonce The nonce to use with authentication. + * aad The additional authentication data. + * aadSz The size of the addition authentication data. + * tagIn The authentication tag data from packet. + * returns 0 on success, otherwise failure. + */ +static int Tls13IntegrityOnly_Decrypt(WOLFSSL* ssl, byte* output, + const byte* input, word16 sz, + const byte* nonce, + const byte* aad, word16 aadSz, + const byte* tagIn) +{ + int ret; + byte hmac[WC_MAX_DIGEST_SIZE]; + + /* HMAC: nonce | aad | input */ + ret = wc_HmacUpdate(ssl->decrypt.hmac, nonce, HMAC_NONCE_SZ); + if (ret == 0) + ret = wc_HmacUpdate(ssl->decrypt.hmac, aad, aadSz); + if (ret == 0) + ret = wc_HmacUpdate(ssl->decrypt.hmac, input, sz); + if (ret == 0) + ret = wc_HmacFinal(ssl->decrypt.hmac, hmac); + /* Check authentication tag matches */ + if (ret == 0 && ConstantCompare(tagIn, hmac, ssl->specs.hash_size) != 0) + ret = DECRYPT_ERROR; + /* Copy the input to output if not the same buffer */ + if (ret == 0 && output != input) + XMEMCPY(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 decrypt and authentication tag. + * sz The length of the encrypted data plus authentication tag. + * aad The additional authentication data. + * aadSz The size of the addition authentication data. + * returns 0 on success, otherwise failure. + */ +int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, + const byte* aad, word16 aadSz) +{ + 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); +#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \ + !defined(WOLFSSL_TLS13_DRAFT_23) + WOLFSSL_MSG("Additional Authentication Data"); + WOLFSSL_BUFFER(aad, aadSz); +#endif + WOLFSSL_MSG("Authentication tag"); + WOLFSSL_BUFFER(input + dataSz, macSz); + #endif + + #ifdef CIPHER_NONCE + 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); + #endif + + /* 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 + /* initialize 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, aad, aadSz); + #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 + /* initialize 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, aad, aadSz); + #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, aad, aadSz, input + dataSz); + break; + #endif + + #ifdef HAVE_NULL_CIPHER + case wolfssl_cipher_null: + ret = Tls13IntegrityOnly_Decrypt(ssl, output, input, dataSz, + ssl->decrypt.nonce, aad, aadSz, 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 + #ifdef CIPHER_NONCE + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(ssl->decrypt.nonce, ssl->specs.iv_size); + #endif + WOLFSSL_MSG("Decrypted data"); + WOLFSSL_BUFFER(output, dataSz); + #endif + + #ifdef CIPHER_NONCE + ForceZero(ssl->decrypt.nonce, AEAD_NONCE_SZ); + #endif + + 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: + { + /* catch mistaken sizeOnly parameter */ + if (sizeOnly) { + if (output || input) { + WOLFSSL_MSG("BuildTls13Message with sizeOnly " + "doesn't need input or output"); + return BAD_FUNC_ARG; + } + } + else if (output == NULL || input == NULL) { + 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; + } + + /* The real record content type goes at the end of the data. */ + output[args->idx++] = (byte)type; + + ssl->options.buildMsgState = BUILD_MSG_ENCRYPT; + } + FALL_THROUGH; + + case BUILD_MSG_ENCRYPT: + { + #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 + { +#if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22) || \ + defined(WOLFSSL_TLS13_DRAFT_23) + output += args->headerSz; + ret = EncryptTls13(ssl, output, output, args->size, NULL, 0, + asyncOkay); +#else + const byte* aad = output; + output += args->headerSz; + ret = EncryptTls13(ssl, output, output, args->size, aad, + RECORD_HEADER_SZ, asyncOkay); +#endif + } + 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); +#ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = NULL; +#endif + + return ret; +} + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +/* Find the cipher suite in the suites set in the SSL. + * + * ssl SSL/TLS object. + * suite Cipher suite to look for. + * returns 1 when suite is found in SSL/TLS object's list and 0 otherwise. + */ +static int FindSuiteSSL(WOLFSSL* ssl, byte* suite) +{ + word16 i; + + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + if (ssl->suites->suites[i+0] == suite[0] && + ssl->suites->suites[i+1] == suite[1]) { + return 1; + } + } + + return 0; +} +#endif + +#ifndef WOLFSSL_TLS13_DRAFT_18 +#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) +/* 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[WC_MAX_DIGEST_SIZE] = {0}; + Hmac cookieHmac; + byte cookieType = 0; + byte macSz = 0; + +#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 */ + XMEMSET(&cookieHmac, 0, sizeof(Hmac)); + + 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 handshake 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] = {0}; + 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; + + /* check hash */ + if (hash == NULL && hashSz > 0) + return BAD_FUNC_ARG; + + AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl); + + WOLFSSL_MSG("Restart Hash"); + WOLFSSL_BUFFER(hash, hashSz); + +#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) + if (ssl->options.sendCookie) { + byte cookie[OPAQUE8_LEN + WC_MAX_DIGEST_SIZE + OPAQUE16_LEN * 2]; + TLSX* ext; + word32 idx = 0; + + /* Cookie Data = Hash Len | Hash | CS | KeyShare Group */ + cookie[idx++] = hashSz; + if (hash) + 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); +} + +/* The value in the random field of a ServerHello to indicate + * HelloRetryRequest. + */ +static byte helloRetryRequestRandom[] = { + 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, + 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, + 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, + 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C +}; +#endif /* WOLFSSL_TLS13_DRAFT_18 */ + +#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; + byte suite[2]; + + if (psk == NULL) + return BAD_FUNC_ARG; + + suite[0] = psk->cipherSuite0; + suite[1] = psk->cipherSuite; + if (!FindSuiteSSL(ssl, suite)) + return PSK_KEY_ERROR; + + 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 = no_early_data; + #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) { + #ifndef WOLFSSL_PSK_ONE_ID + const char* cipherName = NULL; + byte cipherSuite0 = TLS13_BYTE, cipherSuite = WOLFSSL_DEF_PSK_CIPHER; + + /* Get the pre-shared key. */ + if (ssl->options.client_psk_tls13_cb != NULL) { + ssl->arrays->psk_keySz = ssl->options.client_psk_tls13_cb(ssl, + (char *)psk->identity, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN, + &cipherName); + if (GetCipherSuiteFromName(cipherName, &cipherSuite0, + &cipherSuite) != 0) { + return PSK_KEY_ERROR; + } + } + else { + 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; + } + + if (psk->cipherSuite0 != cipherSuite0 || + psk->cipherSuite != cipherSuite) { + return PSK_KEY_ERROR; + } + #else + /* PSK information loaded during setting of default TLS extensions. */ + #endif + } +#endif + + if (ssl->options.noPskDheKe) + ssl->arrays->preMasterSz = 0; + + /* 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[WC_MAX_DIGEST_SIZE]; + word16 len; + + WOLFSSL_ENTER("WritePSKBinders"); + + 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. */ + ret = TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data, + client_hello, &len); + if (ret < 0) + return ret; + idx -= len; + + /* 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. */ + ret = TLSX_PreSharedKey_WriteBinders((PreSharedKey*)ext->data, output + idx, + client_hello, &len); + if (ret < 0) + return ret; + + /* 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 != no_early_data) { + 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 + + WOLFSSL_LEAVE("WritePSKBinders", ret); + + return ret; +} +#endif + +/* handle generation of TLS 1.3 client_hello (1) */ +/* 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; + word16 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + int ret; + + WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND); + 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)) { + #ifndef WOLFSSL_NO_TLS12 + if (ssl->session.version.major == ssl->version.major && + ssl->session.version.minor < ssl->version.minor) { + /* Cannot resume with a different protocol version. */ + ssl->options.resuming = 0; + ssl->version.major = ssl->session.version.major; + ssl->version.minor = ssl->session.version.minor; + return SendClientHello(ssl); + } + else + #endif + return VERSION_ERROR; + } +#endif + + if (ssl->suites == NULL) { + WOLFSSL_MSG("Bad suites pointer in SendTls13ClientHello"); + return SUITES_ERROR; + } + + /* Version | Random | Session Id | Cipher Suites | Compression */ + length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz + + SUITE_LEN + COMP_LEN + ENUM_LEN; +#ifndef WOLFSSL_TLS13_DRAFT_18 + #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + length += ID_LEN; + #else + if (ssl->session.sessionIDSz > 0) + length += ssl->session.sessionIDSz; + #endif +#endif + + /* 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_tls13_cb == NULL && + ssl->options.client_psk_cb == NULL) + #else + if (!ssl->options.resuming) + #endif + ssl->earlyData = no_early_data; + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) + ssl->earlyData = no_early_data; + if (ssl->earlyData == no_early_data) + TLSX_Remove(&ssl->extensions, TLSX_EARLY_DATA, ssl->heap); + if (ssl->earlyData != no_early_data && + (ret = TLSX_EarlyData_Use(ssl, 0)) < 0) { + return ret; + } +#endif + /* Include length of TLS extensions. */ + ret = TLSX_GetRequestSize(ssl, client_hello, &length); + if (ret != 0) + return ret; + + /* 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 - negotiation now in extension: supported_versions. */ + output[idx++] = SSLv3_MAJOR; + output[idx++] = TLSv1_2_MINOR; + /* Keep for downgrade. */ + 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; + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* TLS v1.3 does not use session id - 0 length. */ + output[idx++] = 0; +#else + if (ssl->session.sessionIDSz > 0) { + /* Session resumption for old versions of protocol. */ + output[idx++] = ID_LEN; + XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz); + idx += ID_LEN; + } + else { + #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT + output[idx++] = ID_LEN; + XMEMCPY(output + idx, ssl->arrays->clientRandom, ID_LEN); + idx += ID_LEN; + #else + /* TLS v1.3 does not use session id - 0 length. */ + output[idx++] = 0; + #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */ + } +#endif /* WOLFSSL_TLS13_DRAFT_18 */ + + /* 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. */ + length = 0; + ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &length); + if (ret != 0) + return ret; + idx += length; + +#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(ssl, "ClientHello"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + } +#endif + + ssl->buffers.outputBuffer.length += sendSz; + +#ifdef WOLFSSL_EARLY_DATA_GROUP + if (ssl->earlyData == no_early_data) +#endif + ret = SendBuffered(ssl); + + + WOLFSSL_LEAVE("SendTls13ClientHello", ret); + WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND); + + return ret; +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* handle rocessing of TLS 1.3 hello_retry_request (6) */ +/* 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(ssl, "HelloRetryRequest"); + 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; + + /* 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_COMPLETE; + + WOLFSSL_LEAVE("DoTls13HelloRetryRequest", ret); + + return ret; +} +#endif + + +/* handle processing of TLS 1.3 server_hello (2) and hello_retry_request (6) */ +/* 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, byte* extMsgType) +{ + ProtocolVersion pv; + word32 i = *inOutIdx; + word32 begin = i; + int ret; +#ifndef WOLFSSL_TLS13_DRAFT_18 + byte sessIdSz; + const byte* sessId; + byte b; + int foundVersion; +#endif + word16 totalExtSz; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TLSX* ext; + PreSharedKey* psk = NULL; +#endif + + WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO); + WOLFSSL_ENTER("DoTls13ServerHello"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello"); + 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; +#ifdef WOLFSSL_TLS13_DRAFT_18 + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; + if (!IsAtLeastTLSv1_3(pv) && pv.major != TLS_DRAFT_MAJOR) { +#ifndef WOLFSSL_NO_TLS12 + if (ssl->options.downgrade) { + ssl->version = pv; + return DoServerHello(ssl, input, inOutIdx, helloSz); + } +#endif + + WOLFSSL_MSG("Client using higher version, fatal error"); + return VERSION_ERROR; + } +#else +#ifndef WOLFSSL_NO_TLS12 + if (pv.major == ssl->version.major && pv.minor < TLSv1_2_MINOR && + ssl->options.downgrade) { + /* Force client hello version 1.2 to work for static RSA. */ + ssl->chVersion.minor = TLSv1_2_MINOR; + ssl->version.minor = TLSv1_2_MINOR; + return DoServerHello(ssl, input, inOutIdx, helloSz); + } +#endif + if (pv.major != ssl->version.major || pv.minor != TLSv1_2_MINOR) + return VERSION_ERROR; +#endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* Random length check */ + if ((i - begin) + RAN_LEN > helloSz) + return BUFFER_ERROR; +#else + /* Random and session id length check */ + if ((i - begin) + RAN_LEN + ENUM_LEN > helloSz) + return BUFFER_ERROR; + + if (XMEMCMP(input + i, helloRetryRequestRandom, RAN_LEN) == 0) + *extMsgType = hello_retry_request; +#endif + + /* Server random - keep for debugging. */ + XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); + i += RAN_LEN; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Session id */ + sessIdSz = input[i++]; + if ((i - begin) + sessIdSz > helloSz) + return BUFFER_ERROR; + sessId = input + i; + i += sessIdSz; +#endif /* WOLFSSL_TLS13_DRAFT_18 */ + ssl->options.haveSessionId = 1; + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* Ciphersuite check */ + if ((i - begin) + OPAQUE16_LEN + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; +#else + /* Ciphersuite and compression check */ + if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; +#endif + + /* Set the cipher suite from the message. */ + ssl->options.cipherSuite0 = input[i++]; + ssl->options.cipherSuite = input[i++]; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Compression */ + b = input[i++]; + if (b != 0) { + WOLFSSL_MSG("Must be no compression types in list"); + return INVALID_PARAMETER; + } +#endif + +#ifndef WOLFSSL_TLS13_DRAFT_18 + if ((i - begin) + OPAQUE16_LEN > helloSz) { + if (!ssl->options.downgrade) + return BUFFER_ERROR; +#ifndef WOLFSSL_NO_TLS12 + ssl->version.minor = TLSv1_2_MINOR; +#endif + ssl->options.haveEMS = 0; + } + if ((i - begin) < helloSz) +#endif + { + /* Get extension length and length check. */ + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Need to negotiate version first. */ + if ((ret = TLSX_ParseVersion(ssl, (byte*)input + i, totalExtSz, + *extMsgType, &foundVersion))) { + return ret; + } + if (!foundVersion) { + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Server trying to downgrade to version less than " + "TLS v1.3"); + return VERSION_ERROR; + } + + if (pv.minor < ssl->options.minDowngrade) + return VERSION_ERROR; + ssl->version.minor = pv.minor; + } +#endif + + /* Parse and handle extensions. */ + ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, *extMsgType, + 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 */ + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Version only negotiated in extensions for TLS v1.3. + * Only now do we know how to deal with session id. + */ + if (!IsAtLeastTLSv1_3(ssl->version)) { +#ifndef WOLFSSL_NO_TLS12 + ssl->arrays->sessionIDSz = sessIdSz; + + if (ssl->arrays->sessionIDSz > ID_LEN) { + WOLFSSL_MSG("Invalid session ID size"); + ssl->arrays->sessionIDSz = 0; + return BUFFER_ERROR; + } + else if (ssl->arrays->sessionIDSz) { + XMEMCPY(ssl->arrays->sessionID, sessId, ssl->arrays->sessionIDSz); + ssl->options.haveSessionId = 1; + } + + /* Force client hello version 1.2 to work for static RSA. */ + ssl->chVersion.minor = TLSv1_2_MINOR; + /* Complete TLS v1.2 processing of ServerHello. */ + ret = CompleteServerHello(ssl); +#else + WOLFSSL_MSG("Client using higher version, fatal error"); + ret = VERSION_ERROR; +#endif + + WOLFSSL_LEAVE("DoTls13ServerHello", ret); + + return ret; + } + + #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT + if (sessIdSz == 0) + return INVALID_PARAMETER; + if (ssl->session.sessionIDSz != 0) { + if (ssl->session.sessionIDSz != sessIdSz || + XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0) { + return INVALID_PARAMETER; + } + } + else if (XMEMCMP(ssl->arrays->clientRandom, sessId, sessIdSz) != 0) + return INVALID_PARAMETER; + #else + if (sessIdSz != ssl->session.sessionIDSz || (sessIdSz > 0 && + XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0)) { + WOLFSSL_MSG("Server sent different session id"); + return INVALID_PARAMETER; + } + #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */ +#endif + + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; +#ifdef HAVE_NULL_CIPHER + if (ssl->options.cipherSuite0 == ECC_BYTE && + (ssl->options.cipherSuite == TLS_SHA256_SHA256 || + ssl->options.cipherSuite == TLS_SHA384_SHA384)) { + ; + } + else +#endif + /* Check that the negotiated ciphersuite matches protocol version. */ + if (ssl->options.cipherSuite0 != TLS13_BYTE) { + WOLFSSL_MSG("Server sent non-TLS13 cipher suite in TLS 1.3 packet"); + return INVALID_PARAMETER; + } + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifndef WOLFSSL_TLS13_DRAFT_18 + if (*extMsgType == server_hello) +#endif + { + 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 + +#ifdef WOLFSSL_TLS13_DRAFT_18 + ssl->keys.encryptionOn = 1; +#else + if (*extMsgType == server_hello) { + ssl->keys.encryptionOn = 1; + ssl->options.serverState = SERVER_HELLO_COMPLETE; + } + else { + ssl->options.tls1_3 = 1; + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; + + ret = RestartHandshakeHash(ssl); + } +#endif + + WOLFSSL_LEAVE("DoTls13ServerHello", ret); + WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO); + + return ret; +} + +/* handle processing TLS 1.3 encrypted_extensions (8) */ +/* 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_START(WC_FUNC_ENCRYPTED_EXTENSIONS_DO); + WOLFSSL_ENTER("DoTls13EncryptedExtensions"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "EncryptedExtensions"); + 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 != no_early_data) { + TLSX* ext = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); + if (ext == NULL || !ext->val) + ssl->earlyData = no_early_data; + } +#endif + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData == no_early_data) { + ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY); + if (ret != 0) + return ret; + } +#endif + + ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE; + + WOLFSSL_LEAVE("DoTls13EncryptedExtensions", ret); + WOLFSSL_END(WC_FUNC_ENCRYPTED_EXTENSIONS_DO); + + return ret; +} + +/* handle processing TLS v1.3 certificate_request (13) */ +/* 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_START(WC_FUNC_CERTIFICATE_REQUEST_DO); + WOLFSSL_ENTER("DoTls13CertificateRequest"); + +#ifndef WOLFSSL_TLS13_DRAFT_18 + XMEMSET(&peerSuites, 0, sizeof(Suites)); +#endif +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "CertificateRequest"); + 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; + if (PickHashSigAlgo(ssl, input + *inOutIdx, len) != 0 && + ssl->buffers.certificate && ssl->buffers.certificate->buffer && + ssl->buffers.key && ssl->buffers.key->buffer) { + return INVALID_PARAMETER; + } + *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; +#endif + + if (ssl->buffers.certificate && ssl->buffers.certificate->buffer && + ((ssl->buffers.key && ssl->buffers.key->buffer) + #ifdef HAVE_PK_CALLBACKS + || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx) + #endif + )) { +#ifndef WOLFSSL_TLS13_DRAFT_18 + if (PickHashSigAlgo(ssl, peerSuites.hashSigAlgo, + peerSuites.hashSigAlgoSz) != 0) { + return INVALID_PARAMETER; + } +#endif + 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; + + WOLFSSL_LEAVE("DoTls13CertificateRequest", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO); + + return ret; +} + +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +/* Refine list of supported cipher suites to those common to server and client. + * + * ssl SSL/TLS object. + * peerSuites The peer's advertised list of supported cipher suites. + */ +static void RefineSuites(WOLFSSL* ssl, Suites* peerSuites) +{ + byte suites[WOLFSSL_MAX_SUITE_SZ]; + int suiteSz = 0; + word16 i, j; + + XMEMSET(suites, 0, WOLFSSL_MAX_SUITE_SZ); + + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + for (j = 0; j < peerSuites->suiteSz; j += 2) { + if (ssl->suites->suites[i+0] == peerSuites->suites[j+0] && + ssl->suites->suites[i+1] == peerSuites->suites[j+1]) { + suites[suiteSz++] = peerSuites->suites[j+0]; + suites[suiteSz++] = peerSuites->suites[j+1]; + } + } + } + + ssl->suites->suiteSz = suiteSz; + XMEMCPY(ssl->suites->suites, &suites, sizeof(suites)); +} + +/* 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[WC_MAX_DIGEST_SIZE]; + byte binder[WC_MAX_DIGEST_SIZE]; + word32 binderLen; + word16 modes; + byte suite[2]; +#ifdef WOLFSSL_EARLY_DATA + int pskCnt = 0; + TLSX* extEarlyData; +#endif +#ifndef NO_PSK + const char* cipherName = NULL; + byte cipherSuite0 = TLS13_BYTE; + byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER; +#endif + + WOLFSSL_ENTER("DoPreSharedKeys"); + + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext == NULL) { + /* Hash data up to binders for deriving binders in PSK extension. */ + ret = HashInput(ssl, input, helloSz); + return ret; + } + + /* 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. + */ + ret = TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data, + client_hello, &bindersLen); + if (ret < 0) + return ret; + + /* 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 + if (current->identityLen > MAX_PSK_ID_LEN) { + return BUFFER_ERROR; + } + 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; + } + + /* Check whether resumption is possible based on suites in SSL and + * ciphersuite in ticket. + */ + suite[0] = ssl->session.cipherSuite0; + suite[1] = ssl->session.cipherSuite; + if (!FindSuiteSSL(ssl, suite)) { + current = current->next; + continue; + } + + #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_tls13_cb != NULL && + (ssl->arrays->psk_keySz = ssl->options.server_psk_tls13_cb(ssl, + ssl->arrays->client_identity, ssl->arrays->psk_key, + MAX_PSK_KEY_LEN, &cipherName)) != 0 && + GetCipherSuiteFromName(cipherName, &cipherSuite0, + &cipherSuite) == 0) || + (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; + + /* Check whether PSK ciphersuite is in SSL. */ + suite[0] = cipherSuite0; + suite[1] = cipherSuite; + if (!FindSuiteSSL(ssl, suite)) { + current = current->next; + continue; + } + + /* Default to ciphersuite if cb doesn't specify. */ + ssl->options.resuming = 0; + + /* PSK age is always zero. */ + if (current->ticketAge != ssl->session.ticketAdd) + return PSK_KEY_ERROR; + + /* Set PSK ciphersuite into SSL. */ + ssl->options.cipherSuite0 = cipherSuite0; + ssl->options.cipherSuite = cipherSuite; + 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; + + if (current == NULL) { +#ifdef WOLFSSL_PSK_ID_PROTECTION + #ifndef NO_CERTS + if (ssl->buffers.certChainCnt != 0) + return 0; + #endif + return BAD_BINDER; +#else + return 0; +#endif + } + +#ifdef WOLFSSL_EARLY_DATA + extEarlyData = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); + if (extEarlyData != NULL) { + if (ssl->earlyData != no_early_data && 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 = process_early_data; + } + 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; + + /* Pick key share and Generate a new key if not present. */ + ret = TLSX_KeyShare_Establish(ssl); + if (ret == KEY_SHARE_ERROR) { + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; + ret = 0; + } + 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; + ssl->options.noPskDheKe = 1; + ssl->arrays->preMasterSz = 0; + } + + *usingPSK = 1; + + WOLFSSL_LEAVE("DoPreSharedKeys", ret); + + 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[WC_MAX_DIGEST_SIZE] = {0}; + Hmac cookieHmac; + byte cookieType = 0; + byte macSz = 0; + +#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; + XMEMSET(&cookieHmac, 0, sizeof(Hmac)); + + 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 Supported Vresions Extension */ +#define HRR_VERSIONS_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) +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* 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) +#else +/* PV | Random | Session Id | CipherSuite | Compression | Ext Len */ +#define HRR_BODY_SZ (VERSION_SZ + RAN_LEN + ENUM_LEN + ID_LEN + \ + SUITE_LEN + COMP_LEN + OPAQUE16_LEN) +/* HH | PV | CipherSuite | Ext Len | Key Share | Supported Version | Cookie */ +#define MAX_HRR_SZ (HANDSHAKE_HEADER_SZ + \ + HRR_BODY_SZ + \ + HRR_KEY_SHARE_SZ + \ + HRR_VERSIONS_SZ + \ + HRR_COOKIE_HDR_SZ) +#endif + +/* Restart the handshake 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] = {0}; + byte hrr[MAX_HRR_SZ] = {0}; + 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. */ +#ifdef WOLFSSL_TLS13_DRAFT_18 + length = HRR_BODY_SZ + HRR_COOKIE_HDR_SZ + cookie->len; +#else + length = HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz + + HRR_COOKIE_HDR_SZ + cookie->len; + length += HRR_VERSIONS_SZ; +#endif + if (cookieDataSz > hashSz + OPAQUE16_LEN) { + keyShareExt = 1; + length += HRR_KEY_SHARE_SZ; + } +#ifdef WOLFSSL_TLS13_DRAFT_18 + AddTls13HandShakeHeader(hrr, length, 0, 0, hello_retry_request, ssl); + + idx += hashSz; + hrrIdx = HANDSHAKE_HEADER_SZ; + /* 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; +#else + AddTls13HandShakeHeader(hrr, length, 0, 0, server_hello, ssl); + + idx += hashSz; + hrrIdx = HANDSHAKE_HEADER_SZ; + + /* The negotiated protocol version. */ + hrr[hrrIdx++] = ssl->version.major; + hrr[hrrIdx++] = TLSv1_2_MINOR; + + /* HelloRetryRequest message has fixed value for random. */ + XMEMCPY(hrr + hrrIdx, helloRetryRequestRandom, RAN_LEN); + hrrIdx += RAN_LEN; + + hrr[hrrIdx++] = ssl->session.sessionIDSz; + if (ssl->session.sessionIDSz > 0) { + XMEMCPY(hrr + hrrIdx, ssl->session.sessionID, ssl->session.sessionIDSz); + hrrIdx += ssl->session.sessionIDSz; + } + + /* Cipher Suite */ + hrr[hrrIdx++] = cookieData[idx++]; + hrr[hrrIdx++] = cookieData[idx++]; + + /* Compression not supported in TLS v1.3. */ + hrr[hrrIdx++] = 0; + + /* Extensions' length */ + length -= HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz; + c16toa(length, hrr + hrrIdx); + hrrIdx += 2; + +#endif + /* 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++]; + } +#ifndef WOLFSSL_TLS13_DRAFT_18 + c16toa(TLSX_SUPPORTED_VERSIONS, hrr + hrrIdx); + hrrIdx += 2; + c16toa(OPAQUE16_LEN, hrr + hrrIdx); + hrrIdx += 2; + #ifdef WOLFSSL_TLS13_DRAFT + hrr[hrrIdx++] = TLS_DRAFT_MAJOR; + hrr[hrrIdx++] = TLS_DRAFT_MINOR; + #else + hrr[hrrIdx++] = ssl->version.major; + hrr[hrrIdx++] = ssl->version.minor; + #endif +#endif + /* 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 + +/* Do SupportedVersion extension for TLS v1.3+ otherwise it is not. + * + * ssl The SSL/TLS object. + * input The message buffer. + * i The index into the message buffer of ClientHello. + * helloSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13SupportedVersions(WOLFSSL* ssl, const byte* input, word32 i, + word32 helloSz, int* wantDowngrade) +{ + int ret; + byte b; + word16 suiteSz; + word16 totalExtSz; + int foundVersion = 0; + + /* Client random */ + i += RAN_LEN; + /* Session id - not used in TLS v1.3 */ + b = input[i++]; + if (i + b > helloSz) { + return BUFFER_ERROR; + } + i += b; + /* Cipher suites */ + if (i + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(input + i, &suiteSz); + i += OPAQUE16_LEN; + if (i + suiteSz + 1 > helloSz) + return BUFFER_ERROR; + i += suiteSz; + /* Compression */ + b = input[i++]; + if (i + b > helloSz) + return BUFFER_ERROR; + i += b; + + /* TLS 1.3 must have extensions */ + if (i < helloSz) { + if (i + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if (totalExtSz != helloSz - i) + return BUFFER_ERROR; + + /* Need to negotiate version first. */ + if ((ret = TLSX_ParseVersion(ssl, (byte*)input + i, totalExtSz, + client_hello, &foundVersion))) { + return ret; + } + } + *wantDowngrade = !foundVersion || !IsAtLeastTLSv1_3(ssl->version); + + return 0; +} + +/* 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 = VERSION_ERROR; + byte b = 0; + ProtocolVersion pv; + Suites clSuites; + word32 i = *inOutIdx; + word32 begin = i; + word16 totalExtSz = 0; + int usingPSK = 0; + byte sessIdSz = 0; + int wantDowngrade = 0; + + WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO); + WOLFSSL_ENTER("DoTls13ClientHello"); + + XMEMSET(&pv, 0, sizeof(ProtocolVersion)); + XMEMSET(&clSuites, 0, sizeof(Suites)); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello"); + 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 (pv.major < SSLv3_MAJOR) { + WOLFSSL_MSG("Legacy version field contains unsupported value"); + #ifdef WOLFSSL_MYSQL_COMPATIBLE + SendAlert(ssl, alert_fatal, wc_protocol_version); + #else + SendAlert(ssl, alert_fatal, protocol_version); + #endif + return INVALID_PARAMETER; + } + /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */ + if (pv.major > SSLv3_MAJOR || (pv.major == SSLv3_MAJOR && + pv.minor >= TLSv1_3_MINOR)) { + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_2_MINOR; + wantDowngrade = 1; + ssl->version.minor = pv.minor; + } + /* Legacy version must be [ SSLv3_MAJOR, TLSv1_2_MINOR ] for TLS v1.3 */ + else if (pv.major == SSLv3_MAJOR && pv.minor < TLSv1_2_MINOR) { + wantDowngrade = 1; + ssl->version.minor = pv.minor; + } + else { + ret = DoTls13SupportedVersions(ssl, input + begin, i - begin, helloSz, + &wantDowngrade); + if (ret < 0) + return ret; + } + if (wantDowngrade) { +#ifndef WOLFSSL_NO_TLS12 + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Client trying to connect with lesser version than " + "TLS v1.3"); + return VERSION_ERROR; + } + + if (pv.minor < ssl->options.minDowngrade) + return VERSION_ERROR; + + if ((ret = HashInput(ssl, input + begin, helloSz)) != 0) + return ret; + return DoClientHello(ssl, input, inOutIdx, helloSz); +#else + WOLFSSL_MSG("Client trying to connect with lesser version than " + "TLS v1.3"); + return VERSION_ERROR; +#endif + } + + /* 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 + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* Session id - empty in TLS v1.3 */ + sessIdSz = input[i++]; + if (sessIdSz > 0 && !ssl->options.downgrade) { + WOLFSSL_MSG("Client sent session id - not supported"); + return BUFFER_ERROR; + } +#else + sessIdSz = input[i++]; + if (sessIdSz != ID_LEN && sessIdSz != 0) + return INVALID_PARAMETER; +#endif + + if (sessIdSz + i > helloSz) { + return BUFFER_ERROR; + } + + ssl->session.sessionIDSz = sessIdSz; + if (sessIdSz == ID_LEN) { + XMEMCPY(ssl->session.sessionID, input + i, sessIdSz); + i += ID_LEN; + } + + /* 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; + +#ifdef HAVE_SERVER_RENEGOTIATION_INFO + ret = FindSuite(&clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV); + if (ret == SUITES_ERROR) + return BUFFER_ERROR; + if (ret >= 0) { + TLSX* extension; + + /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */ + ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO); + if (extension) { + ssl->secure_renegotiation = (SecureRenegotiation*)extension->data; + ssl->secure_renegotiation->enabled = 1; + } + } +#endif /* HAVE_SERVER_RENEGOTIATION_INFO */ + + /* 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; + } + + /* Extensions */ + if ((i - begin) == helloSz) + 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; + + /* 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; + } + +#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) + if ((ret = SNI_Callback(ssl)) != 0) + return ret; + ssl->options.side = WOLFSSL_SERVER_END; +#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + + i += totalExtSz; + *inOutIdx = i; + + ssl->options.sendVerify = SEND_CERT; + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + ssl->options.haveSessionId = 1; + +#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE) + if (ssl->options.sendCookie && + ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + 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 + +#if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \ + defined(HAVE_TLS_EXTENSIONS) + if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY) != NULL) { + /* Refine list for PSK processing. */ + RefineSuites(ssl, &clSuites); + + /* Process the Pre-Shared Key extension if present. */ + ret = DoPreSharedKeys(ssl, input + begin, helloSz, &usingPSK); + if (ret != 0) + return ret; + } + else +#endif + { +#ifdef WOLFSSL_EARLY_DATA + ssl->earlyData = no_early_data; +#endif + if ((ret = HashInput(ssl, input + begin, helloSz)) != 0) + return ret; + + } + + if (!usingPSK) { + if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { + WOLFSSL_MSG("Client did not send a KeyShare extension"); + SendAlert(ssl, alert_fatal, missing_extension); + return INCOMPLETE_DATA; + } + if (TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS) == NULL) { + WOLFSSL_MSG("Client did not send a SignatureAlgorithms extension"); + SendAlert(ssl, alert_fatal, missing_extension); + return INCOMPLETE_DATA; + } + + if ((ret = MatchSuite(ssl, &clSuites)) < 0) { + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + SendAlert(ssl, alert_fatal, handshake_failure); + return ret; + } + +#ifdef HAVE_NULL_CIPHER + if (ssl->options.cipherSuite0 == ECC_BYTE && + (ssl->options.cipherSuite == TLS_SHA256_SHA256 || + ssl->options.cipherSuite == TLS_SHA384_SHA384)) { + ; + } + else +#endif + /* Check that the negotiated ciphersuite matches protocol version. */ + if (ssl->options.cipherSuite0 != TLS13_BYTE) { + WOLFSSL_MSG("Negotiated ciphersuite from lesser version than " + "TLS v1.3"); + SendAlert(ssl, alert_fatal, handshake_failure); + return VERSION_ERROR; + } + +#ifdef HAVE_SESSION_TICKET + if (ssl->options.resuming) { + ssl->options.resuming = 0; + XMEMSET(ssl->arrays->psk_key, 0, ssl->specs.hash_size); + } +#endif + + /* Derive early secret for handshake secret. */ + if ((ret = DeriveEarlySecret(ssl)) != 0) + return ret; + } + + WOLFSSL_LEAVE("DoTls13ClientHello", ret); + WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); + + return ret; +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* handle generation of TLS 1.3 hello_retry_request (6) */ +/* 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; + word16 len; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + + WOLFSSL_ENTER("SendTls13HelloRetryRequest"); + + /* Get the length of the extensions that will be written. */ + len = 0; + ret = TLSX_GetResponseSize(ssl, hello_retry_request, &len); + /* There must be extensions sent to indicate what client needs to do. */ + if (ret != 0) + return MISSING_HANDSHAKE_DATA; + + /* Protocol version + Extensions */ + length = OPAQUE16_LEN + len; + 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 handshake headers. */ + AddTls13Headers(output, length, hello_retry_request, ssl); + + /* The negotiated protocol version. */ + output[idx++] = TLS_DRAFT_MAJOR; + output[idx++] = TLS_DRAFT_MINOR; + + /* Add TLS extensions. */ + ret = TLSX_WriteResponse(ssl, output + idx, hello_retry_request, NULL); + if (ret != 0) + return ret; + idx += len; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "HelloRetryRequest"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "HelloRetryRequest", handshake, output, sendSz, + WRITE_PROTO, 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; +} +#endif /* WOLFSSL_TLS13_DRAFT_18 */ + +/* 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. + */ +#ifdef WOLFSSL_TLS13_DRAFT_18 +static +#endif +/* handle generation of TLS 1.3 server_hello (2) */ +int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) +{ + int ret; + byte* output; + word16 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + + WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND); + WOLFSSL_ENTER("SendTls13ServerHello"); + +#ifndef WOLFSSL_TLS13_DRAFT_18 + if (extMsgType == hello_retry_request) { + WOLFSSL_MSG("wolfSSL Doing HelloRetryRequest"); + if ((ret = RestartHandshakeHash(ssl)) < 0) + return ret; + } +#endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* Protocol version, server random, cipher suite and extensions. */ + length = VERSION_SZ + RAN_LEN + SUITE_LEN; + ret = TLSX_GetResponseSize(ssl, server_hello, &length); + if (ret != 0) + return ret; +#else + /* Protocol version, server random, session id, cipher suite, compression + * and extensions. + */ + length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->session.sessionIDSz + + SUITE_LEN + COMP_LEN; + ret = TLSX_GetResponseSize(ssl, extMsgType, &length); + if (ret != 0) + return ret; +#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; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, server_hello, ssl); + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* The negotiated protocol version. */ + output[idx++] = TLS_DRAFT_MAJOR; + output[idx++] = TLS_DRAFT_MINOR; +#else + /* The protocol version must be TLS v1.2 for middleboxes. */ + output[idx++] = ssl->version.major; + output[idx++] = TLSv1_2_MINOR; +#endif + + if (extMsgType == server_hello) { + /* Generate server random. */ + if ((ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN)) != 0) + return ret; + } +#ifndef WOLFSSL_TLS13_DRAFT_18 + else { + /* HelloRetryRequest message has fixed value for random. */ + XMEMCPY(output + idx, helloRetryRequestRandom, RAN_LEN); + } +#endif + /* 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 + +#ifndef WOLFSSL_TLS13_DRAFT_18 + output[idx++] = ssl->session.sessionIDSz; + if (ssl->session.sessionIDSz > 0) { + XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz); + idx += ssl->session.sessionIDSz; + } +#endif + + /* Chosen cipher suite */ + output[idx++] = ssl->options.cipherSuite0; + output[idx++] = ssl->options.cipherSuite; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Compression not supported in TLS v1.3. */ + output[idx++] = 0; +#endif + + /* Extensions */ + ret = TLSX_WriteResponse(ssl, output + idx, extMsgType, NULL); + if (ret != 0) + return ret; + + ssl->buffers.outputBuffer.length += sendSz; + + if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0) + return ret; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "ServerHello"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "ServerHello", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + } + #endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 + ssl->options.serverState = SERVER_HELLO_COMPLETE; +#else + if (extMsgType == server_hello) + ssl->options.serverState = SERVER_HELLO_COMPLETE; +#endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 + if (!ssl->options.groupMessages) +#else + if (!ssl->options.groupMessages || extMsgType != server_hello) +#endif + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13ServerHello", ret); + WOLFSSL_END(WC_FUNC_SERVER_HELLO_SEND); + + return ret; +} + +/* handle generation of TLS 1.3 encrypted_extensions (8) */ +/* 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; + word16 length = 0; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + + WOLFSSL_START(WC_FUNC_ENCRYPTED_EXTENSIONS_SEND); + WOLFSSL_ENTER("SendTls13EncryptedExtensions"); + + ssl->keys.encryptionOn = 1; + +#ifndef WOLFSSL_NO_SERVER_GROUPS_EXT + if ((ret = TLSX_SupportedCurve_CheckPriority(ssl)) != 0) + return ret; +#endif + + /* 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 != process_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 + + ret = TLSX_GetResponseSize(ssl, encrypted_extensions, &length); + if (ret != 0) + return ret; + + 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); + + ret = TLSX_WriteResponse(ssl, output + idx, encrypted_extensions, NULL); + if (ret != 0) + return ret; + idx += length; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "EncryptedExtensions"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "EncryptedExtensions", handshake, output, + sendSz, WRITE_PROTO, 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); + WOLFSSL_END(WC_FUNC_ENCRYPTED_EXTENSIONS_SEND); + + return ret; +} + +#ifndef NO_CERTS +/* handle generation TLS v1.3 certificate_request (13) */ +/* 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; + word16 reqSz; +#ifndef WOLFSSL_TLS13_DRAFT_18 + TLSX* ext; +#endif + + WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND); + 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 = (word16)(OPAQUE8_LEN + reqCtxLen); + ret = TLSX_GetRequestSize(ssl, certificate_request, &reqSz); + if (ret != 0) + return ret; + + 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++] = (byte)reqCtxLen; + if (reqCtxLen != 0) { + XMEMCPY(output + i, reqCtx, reqCtxLen); + i += reqCtxLen; + } + + /* Certificate extensions. */ + reqSz = 0; + ret = TLSX_WriteRequest(ssl, output + i, certificate_request, &reqSz); + if (ret != 0) + return ret; + i += reqSz; +#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(ssl, "CertificateRequest"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "CertificateRequest", handshake, output, + sendSz, WRITE_PROTO, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13CertificateRequest", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND); + + return ret; +} +#endif /* NO_CERTS */ +#endif /* NO_WOLFSSL_SERVER */ + +#ifndef NO_CERTS +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_ED448) +/* Encode the signature algorithm into buffer. + * + * hashalgo The hash algorithm. + * hsType The signature type. + * output The buffer to encode into. + */ +static WC_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 +#ifdef HAVE_ED448 + /* ED448: 0x0808 */ + case ed448_sa_algo: + output[0] = ED448_SA_MAJOR; + output[1] = ED448_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 + } +} + +/* Decode the signature algorithm. + * + * input The encoded signature algorithm. + * hashalgo The hash algorithm. + * hsType The signature type. + * returns INVALID_PARAMETER if not recognized and 0 otherwise. + */ +static WC_INLINE int DecodeTls13SigAlg(byte* input, byte* hashAlgo, + byte* hsType) +{ + int ret = 0; + + switch (input[0]) { + case NEW_SA_MAJOR: + /* PSS signatures: 0x080[4-6] */ + if (input[1] >= sha256_mac && input[1] <= sha512_mac) { + *hsType = input[0]; + *hashAlgo = input[1]; + } + #ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + else if (input[1] == ED25519_SA_MINOR) { + *hsType = ed25519_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + #endif + #ifdef HAVE_ED448 + /* ED448: 0x0808 */ + else if (input[1] == ED448_SA_MINOR) { + *hsType = ed448_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + #endif + else + ret = INVALID_PARAMETER; + break; + default: + *hashAlgo = input[0]; + *hsType = input[1]; + break; + } + + return ret; +} + +/* 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 WC_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 + \ + WC_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 = (word16)(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. + * sigAlgo 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-place */ + 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. + * + * ssl SSL/TLS object. + * cert The certificate data to write out. + * len The length of the certificate data. + * extSz Length of the extension data with the certificate. + * 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(WOLFSSL* ssl, byte* cert, word32 len, word16 extSz, + 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 == fragSz) + return i; + } + copySz = len + extSz - idx - i; + + if (extSz == OPAQUE16_LEN) { + if (copySz <= fragSz) { + /* Empty extension */ + output[i++] = 0; + output[i++] = 0; + } + } + else { + byte* certExts = ssl->buffers.certExts->buffer + idx + i - len; + /* Put out as much of the extensions' data as will fit in fragment. */ + if (copySz > fragSz - i) + copySz = fragSz - i; + XMEMCPY(output + i, certExts, copySz); + i += copySz; + } + + return i; +} + +/* handle generation TLS v1.3 certificate (11) */ +/* 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; + word16 extSz = 0; + word32 length, maxFragment; + word32 len = 0; + word32 idx = 0; + word32 offset = OPAQUE16_LEN; + byte* p = NULL; + byte certReqCtxLen = 0; + byte* certReqCtx = NULL; + + WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND); + 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; + + ret = TLSX_GetResponseSize(ssl, certificate, &extSz); + if (ret < 0) + return ret; + + /* Create extensions' data if none already present. */ + if (extSz > OPAQUE16_LEN && ssl->buffers.certExts == NULL) { + ret = AllocDer(&ssl->buffers.certExts, extSz, CERT_TYPE, ssl->heap); + if (ret < 0) + return ret; + + extSz = 0; + ret = TLSX_WriteResponse(ssl, ssl->buffers.certExts->buffer, + certificate, &extSz); + if (ret < 0) + return ret; + } + + /* Length of message data with one certificate and extensions. */ + length = headerSz + certSz + extSz; + /* Length of list data with one certificate and extensions. */ + listSz = CERT_HEADER_SZ + certSz + extSz; + + /* Send rest of chain if sending cert (chain has leading size/s). */ + if (certSz > 0 && ssl->buffers.certChainCnt > 0) { + 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 = wolfSSL_GetMaxRecordSize(ssl, MAX_RECORD_SIZE); + + 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 + extSz + certChainSz <= + maxFragment - HANDSHAKE_HEADER_SZ) { + fragSz = headerSz + certSz + extSz + 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 + extSz) { + /* Put in the leaf certificate with extensions. */ + word32 copySz = AddCertExt(ssl, ssl->buffers.certificate->buffer, + certSz, extSz, ssl->fragOffset, fragSz, output + i); + i += copySz; + ssl->fragOffset += copySz; + length -= copySz; + fragSz -= copySz; + if (ssl->fragOffset == certSz + extSz) + FreeDer(&ssl->buffers.certExts); + } + 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; + /* Point to the start of current cert in chain buffer. */ + p = ssl->buffers.certChain->buffer + idx; + len = NextCert(ssl->buffers.certChain->buffer, + ssl->buffers.certChain->length, &idx); + if (len == 0) + break; + } + + /* Write out certificate and empty extension. */ + l = AddCertExt(ssl, p, len, OPAQUE16_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(ssl, "Certificate"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "Certificate", handshake, output, + sendSz, WRITE_PROTO, 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); + WOLFSSL_END(WC_FUNC_CERTIFICATE_SEND); + + return ret; +} + +typedef struct Scv13Args { + byte* output; /* not allocated */ + 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; + + if (args->sigData) { + XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->sigData = NULL; + } +} + +/* handle generation TLS v1.3 certificate_verify (15) */ +/* 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_START(WC_FUNC_CERTIFICATE_VERIFY_SEND); + 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 + MAX_MSG_EXTRA; + /* 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]; + + if (ssl->buffers.key == NULL) { + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) + args->length = GetPrivateKeySigSize(ssl); + else + #endif + ERROR_OUT(NO_PRIVATE_KEY, exit_scv); + } + else { + ret = DecodePrivateKey(ssl, &args->length); + if (ret != 0) + goto exit_scv; + } + + if (args->length <= 0) { + ERROR_OUT(NO_PRIVATE_KEY, 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 + #ifdef HAVE_ED448 + else if (ssl->hsType == DYNAMIC_TYPE_ED448) + args->sigAlgo = ed448_sa_algo; + #endif + EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, args->verify); + + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + int sigLen = MAX_SIG_DATA_SZ; + if (args->length > MAX_SIG_DATA_SZ) + sigLen = args->length; + args->sigData = (byte*)XMALLOC(sigLen, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + } + else { + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + } + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + /* Create the data to be signed. */ + 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 = WC_MAX_DIGEST_SIZE; + 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 = (word16)ret; + ret = 0; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + ret = Ed25519CheckPubKey(ssl); + if (ret < 0) { + ERROR_OUT(ret, exit_scv); + } + sig->length = ED25519_SIG_SIZE; + } + #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED448 + if (ssl->hsType == DYNAMIC_TYPE_ED448) { + ret = Ed448CheckPubKey(ssl); + if (ret < 0) { + ERROR_OUT(ret, exit_scv); + } + sig->length = ED448_SIG_SIZE; + } + #endif /* HAVE_ED448 */ + + /* 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, + (word32*)&sig->length, (ecc_key*)ssl->hsKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + args->length = (word16)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, + (word32*)&sig->length, (ed25519_key*)ssl->hsKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + args->length = (word16)sig->length; + } + #endif + #ifdef HAVE_ED448 + if (ssl->hsType == DYNAMIC_TYPE_ED448) { + ret = Ed448Sign(ssl, args->sigData, args->sigDataSz, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + (word32*)&sig->length, (ed448_key*)ssl->hsKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + args->length = (word16)sig->length; + } + #endif + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + ret = RsaSign(ssl, sig->buffer, (word32)sig->length, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, &args->sigLen, + args->sigAlgo, ssl->suites->hashAlgo, + (RsaKey*)ssl->hsKey, + ssl->buffers.key + ); + if (ret == 0) { + args->length = (word16)args->sigLen; + + XMEMCPY(args->sigData, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + 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) { + /* check for signature faults */ + ret = VerifyRsaSign(ssl, args->sigData, args->sigLen, + sig->buffer, (word32)sig->length, args->sigAlgo, + ssl->suites->hashAlgo, (RsaKey*)ssl->hsKey, + ssl->buffers.key + ); + } + #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(ssl, "CertificateVerify"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "CertificateVerify", handshake, + args->output, args->sendSz, WRITE_PROTO, 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); + WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND); + +#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; +} + +/* handle processing TLS v1.3 certificate (11) */ +/* 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_START(WC_FUNC_CERTIFICATE_DO); + WOLFSSL_ENTER("DoTls13Certificate"); + + ret = ProcessPeerCerts(ssl, input, inOutIdx, totalSz); + if (ret == 0) { +#if !defined(NO_WOLFSSL_CLIENT) + if (ssl->options.side == WOLFSSL_CLIENT_END) + ssl->options.serverState = SERVER_CERT_COMPLETE; +#endif +#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (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); + WOLFSSL_END(WC_FUNC_CERTIFICATE_DO); + + return ret; +} + +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_ED448) + +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; +} + +/* handle processing TLS v1.3 certificate_verify (15) */ +/* 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_START(WC_FUNC_CERTIFICATE_VERIFY_DO); + 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(ssl, "CertificateVerify"); + 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); + } + ret = DecodeTls13SigAlg(input + args->idx, &args->hashAlgo, + &args->sigAlgo); + if (ret < 0) + goto exit_dcv; + 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_ED448 + if (args->sigAlgo == ed448_sa_algo && !ssl->peerEd448KeyPresent) { + WOLFSSL_MSG("Oops, peer sent ED448 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) { + WOLFSSL_MSG("Oops, peer sent PKCS#1.5 signature"); + ERROR_OUT(INVALID_PARAMETER, exit_dcv); + } + if (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 = (word16)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 + #ifdef HAVE_ED448 + if (ssl->peerEd448KeyPresent) { + WOLFSSL_MSG("Doing ED448 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 (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { + WOLFSSL_MSG("Doing RSA peer cert verify"); + + ret = RsaVerify(ssl, sig->buffer, (word32)sig->length, &args->output, + args->sigAlgo, args->hashAlgo, ssl->peerRsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerRsaKey + #else + 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 + #else + NULL + #endif + ); + + if (ret >= 0) { + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + } + } + #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 + #else + NULL + #endif + ); + + if (ret >= 0) { + FreeKey(ssl, DYNAMIC_TYPE_ED25519, + (void**)&ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; + } + } + #endif + #ifdef HAVE_ED448 + if (ssl->peerEd448KeyPresent) { + WOLFSSL_MSG("Doing ED448 peer cert verify"); + + ret = Ed448Verify(ssl, input + args->idx, args->sz, + args->sigData, args->sigDataSz, + ssl->peerEd448Key, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEd448Key + #else + NULL + #endif + ); + + if (ret >= 0) { + FreeKey(ssl, DYNAMIC_TYPE_ED448, + (void**)&ssl->peerEd448Key); + ssl->peerEd448KeyPresent = 0; + } + } + #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; + + FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; + } + #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); + WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_DO); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not received so it can process again */ + ssl->msgsReceived.got_certificate_verify = 0; + + return ret; + } + else +#endif /* WOLFSSL_ASYNC_CRYPT */ + if (ret != 0 && ret != INVALID_PARAMETER) + SendAlert(ssl, alert_fatal, decrypt_error); + + /* 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[WC_MAX_DIGEST_SIZE]; + + WOLFSSL_START(WC_FUNC_FINISHED_DO); + WOLFSSL_ENTER("DoTls13Finished"); + + /* check against totalSz */ + if (*inOutIdx + size + ssl->keys.padSz > totalSz) + return BUFFER_E; + + if (ssl->options.handShakeDone) { + ret = DeriveFinishedSecret(ssl, ssl->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.client_write_MAC_secret; + } + else 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->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + ret = DeriveFinishedSecret(ssl, ssl->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(ssl, "Finished"); + 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"); + SendAlert(ssl, alert_fatal, decrypt_error); + 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 != no_early_data) { + 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); + WOLFSSL_END(WC_FUNC_FINISHED_DO); + + 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_START(WC_FUNC_FINISHED_SEND); + WOLFSSL_ENTER("SendTls13Finished"); + + outputSz = WC_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.handShakeDone) { + ret = DeriveFinishedSecret(ssl, ssl->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.client_write_MAC_secret; + } + else 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->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + ret = DeriveFinishedSecret(ssl, ssl->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; + +#ifndef NO_SESSION_CACHE + if (!ssl->options.resuming && (ssl->options.side == WOLFSSL_SERVER_END || + (ssl->options.side == WOLFSSL_SERVER_END && ssl->arrays != NULL))) { + AddSession(ssl); /* just try */ + } +#endif + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "Finished"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "Finished", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + + 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 == no_early_data)) != 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 != no_early_data) { + 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); + if (ret != 0) + return ret; +#endif + } + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } +#endif +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + } +#endif + + if ((ret = SendBuffered(ssl)) != 0) + return ret; + + WOLFSSL_LEAVE("SendTls13Finished", ret); + WOLFSSL_END(WC_FUNC_FINISHED_SEND); + + return ret; +} + +/* handle generation TLS v1.3 key_update (24) */ +/* 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_START(WC_FUNC_KEY_UPDATE_SEND); + 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(ssl, "KeyUpdate"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "KeyUpdate", handshake, output, sendSz, + WRITE_PROTO, 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); + WOLFSSL_END(WC_FUNC_KEY_UPDATE_SEND); + + return ret; +} + +/* handle processing TLS v1.3 key_update (24) */ +/* 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_START(WC_FUNC_KEY_UPDATE_DO); + 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 outstanding 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; + } + + /* 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); + WOLFSSL_END(WC_FUNC_KEY_UPDATE_DO); + + 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_START(WC_FUNC_END_OF_EARLY_DATA_SEND); + 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); + WOLFSSL_END(WC_FUNC_END_OF_EARLY_DATA_SEND); + + return ret; +} +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER +/* handle processing of TLS 1.3 end_of_early_data (5) */ +/* 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_START(WC_FUNC_END_OF_EARLY_DATA_DO); + WOLFSSL_ENTER("DoTls13EndOfEarlyData"); + + if ((*inOutIdx - begin) != size) + return BUFFER_ERROR; + + if (ssl->earlyData == no_early_data) { + WOLFSSL_MSG("EndOfEarlyData received unexpectedly"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + ssl->earlyData = done_early_data; + + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY); + + WOLFSSL_LEAVE("DoTls13EndOfEarlyData", ret); + WOLFSSL_END(WC_FUNC_END_OF_EARLY_DATA_DO); + + 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. + * returns 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_START(WC_FUNC_NEW_SESSION_TICKET_DO); + 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 > 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 += nonceLength; +#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; + if (nonceLength > 0) + XMEMCPY(&ssl->session.ticketNonce.data, nonce, nonceLength); +#endif + ssl->session.namedGroup = ssl->namedGroup; + + 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); + WOLFSSL_END(WC_FUNC_NEW_SESSION_TICKET_DO); + + 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. + * returns 0 on success, otherwise failure. + */ +static int ExpectedResumptionSecret(WOLFSSL* ssl) +{ + int ret; + word32 finishedSz = 0; + byte mac[WC_MAX_DIGEST_SIZE]; + Digest digest; + static byte header[] = { 0x14, 0x00, 0x00, 0x00 }; + + /* Copy the running hash so we can 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 != no_early_data) { + 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. + * returns 0 on success, otherwise failure. + */ +static int SendTls13NewSessionTicket(WOLFSSL* ssl) +{ + byte* output; + int ret; + int sendSz; + word16 extSz; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + WOLFSSL_START(WC_FUNC_NEW_SESSION_TICKET_SEND); + 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 = 0; + ret = TLSX_GetResponseSize(ssl, session_ticket, &extSz); + if (ret != 0) + return ret; +#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 + extSz = 0; + ret = TLSX_WriteResponse(ssl, output + idx, session_ticket, &extSz); + if (ret != 0) + return ret; + idx += extSz; +#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); + WOLFSSL_END(WC_FUNC_NEW_SESSION_TICKET_SEND); + + 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: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_MSG("ClientHello received by client"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.clientState >= CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("ClientHello received out of order"); + return OUT_OF_ORDER_E; + } + 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: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("ServerHello received by server"); + return OUT_OF_ORDER_E; + } + #endif + #ifdef WOLFSSL_TLS13_DRAFT_18 + if (ssl->msgsReceived.got_server_hello) { + WOLFSSL_MSG("Duplicate ServerHello received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_hello = 1; + #else + if (ssl->msgsReceived.got_server_hello == 2) { + WOLFSSL_MSG("Duplicate ServerHello received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_hello++; + #endif + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case session_ticket: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("NewSessionTicket received by server"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) { + WOLFSSL_MSG("NewSessionTicket received out of order"); + return OUT_OF_ORDER_E; + } + ssl->msgsReceived.got_session_ticket = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_SERVER + #ifdef WOLFSSL_EARLY_DATA + case end_of_early_data: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_MSG("EndOfEarlyData received by client"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + WOLFSSL_MSG("EndOfEarlyData received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->options.clientState >= CLIENT_FINISHED_COMPLETE) { + WOLFSSL_MSG("EndOfEarlyData received out of order"); + return OUT_OF_ORDER_E; + } + 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 + +#ifdef WOLFSSL_TLS13_DRAFT_18 + #ifndef NO_WOLFSSL_CLIENT + case hello_retry_request: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("HelloRetryRequest received by server"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.clientState > CLIENT_FINISHED_COMPLETE) { + WOLFSSL_MSG("HelloRetryRequest received out of order"); + return OUT_OF_ORDER_E; + } + 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 +#endif + +#ifndef NO_WOLFSSL_CLIENT + case encrypted_extensions: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("EncryptedExtensions received by server"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.serverState != SERVER_HELLO_COMPLETE) { + WOLFSSL_MSG("EncryptedExtensions received out of order"); + return OUT_OF_ORDER_E; + } + 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: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.serverState != + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) { + WOLFSSL_MSG("Certificate received out of order - Client"); + return OUT_OF_ORDER_E; + } + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Server's authenticating with PSK must not send this. */ + if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.serverState == SERVER_CERT_COMPLETE && + ssl->arrays->psk_keySz != 0) { + WOLFSSL_MSG("Certificate received while using PSK"); + return SANITY_MSG_E; + } + #endif + #endif + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + WOLFSSL_MSG("Certificate received out of order - Server"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->msgsReceived.got_certificate) { + WOLFSSL_MSG("Duplicate Certificate received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate = 1; + + break; + +#ifndef NO_WOLFSSL_CLIENT + case certificate_request: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("CertificateRequest received by server"); + return OUT_OF_ORDER_E; + } + #endif + #ifndef WOLFSSL_POST_HANDSHAKE_AUTH + if (ssl->options.serverState != + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) { + WOLFSSL_MSG("CertificateRequest received out of order"); + return OUT_OF_ORDER_E; + } + #else + if (ssl->options.serverState != + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE && + (ssl->options.serverState != SERVER_FINISHED_COMPLETE || + ssl->options.clientState != CLIENT_FINISHED_COMPLETE)) { + WOLFSSL_MSG("CertificateRequest received out of order"); + return OUT_OF_ORDER_E; + } + #endif + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Server's authenticating with PSK must not send this. */ + if (ssl->options.serverState == + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE && + ssl->arrays->psk_keySz != 0) { + WOLFSSL_MSG("CertificateRequset received while using PSK"); + return SANITY_MSG_E; + } + #endif + #ifndef WOLFSSL_POST_HANDSHAKE_AUTH + if (ssl->msgsReceived.got_certificate_request) { + WOLFSSL_MSG("Duplicate CertificateRequest received"); + return DUPLICATE_MSG_E; + } + #endif + ssl->msgsReceived.got_certificate_request = 1; + + break; +#endif + + case certificate_verify: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->options.serverState != SERVER_CERT_COMPLETE) { + WOLFSSL_MSG("No Cert before CertVerify"); + return OUT_OF_ORDER_E; + } + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Server's authenticating with PSK must not send this. */ + if (ssl->options.serverState == SERVER_CERT_COMPLETE && + ssl->arrays->psk_keySz != 0) { + WOLFSSL_MSG("CertificateVerify received while using PSK"); + return SANITY_MSG_E; + } + #endif + } + #endif + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + WOLFSSL_MSG("CertificateVerify received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("CertificateVerify before ClientHello done"); + return OUT_OF_ORDER_E; + } + if (!ssl->msgsReceived.got_certificate) { + WOLFSSL_MSG("No Cert before CertificateVerify"); + return OUT_OF_ORDER_E; + } + } + #endif + if (ssl->msgsReceived.got_certificate_verify) { + WOLFSSL_MSG("Duplicate CertificateVerify received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_verify = 1; + + break; + + case finished: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->options.serverState < + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } + } + #endif + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } + #ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData == process_early_data) { + return OUT_OF_ORDER_E; + } + #endif + } + #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 we 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"); + SendAlert(ssl, alert_fatal, unexpected_message); + 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(ssl, 0, handshake, input + *inOutIdx - add, + size + add, READ_PROTO, 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 + /* Messages only received by client. */ + #ifdef WOLFSSL_TLS13_DRAFT_18 + case hello_retry_request: + WOLFSSL_MSG("processing hello retry request"); + ret = DoTls13HelloRetryRequest(ssl, input, inOutIdx, size); + break; + #endif + + case server_hello: + WOLFSSL_MSG("processing server hello"); + ret = DoTls13ServerHello(ssl, input, inOutIdx, size, &type); + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ + ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ + (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) + if (ssl->options.resuming || !IsAtLeastTLSv1_2(ssl) || + IsAtLeastTLSv1_3(ssl->version)) { + ssl->options.cacheMessages = 0; + if (ssl->hsHashes->messages != NULL) { + XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes->messages = NULL; + } + } + #endif + break; + + case encrypted_extensions: + WOLFSSL_MSG("processing encrypted extensions"); + ret = DoTls13EncryptedExtensions(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; +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER + /* Messages only received by server. */ + case client_hello: + WOLFSSL_MSG("processing client hello"); + ret = DoTls13ClientHello(ssl, input, inOutIdx, size); + break; + + #ifdef WOLFSSL_EARLY_DATA + case end_of_early_data: + WOLFSSL_MSG("processing end of early data"); + ret = DoTls13EndOfEarlyData(ssl, input, inOutIdx, size); + break; + #endif +#endif /* !NO_WOLFSSL_SERVER */ + + /* Messages received by both client and server. */ +#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) || \ + defined(HAVE_ED448) + case certificate_verify: + WOLFSSL_MSG("processing certificate verify"); + ret = DoTls13CertificateVerify(ssl, input, inOutIdx, size); + break; +#endif /* !NO_RSA || HAVE_ECC */ + + 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; + + 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) { + ret = HashInput(ssl, input + inIdx, size); + } + if (ret == 0 && ssl->buffers.inputBuffer.dynamicFlag) { + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + } + + if (ret == BUFFER_ERROR || ret == MISSING_HANDSHAKE_DATA) + SendAlert(ssl, alert_fatal, decode_error); + else 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 (ret == 0 && ssl->options.tls1_3) { + /* Need to hash input message before deriving secrets. */ + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (type == server_hello) { + 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 + } + + if (type == finished) { + if ((ret = DeriveMasterSecret(ssl)) != 0) + return ret; + #ifdef WOLFSSL_EARLY_DATA + if ((ret = DeriveTls13Keys(ssl, traffic_key, + ENCRYPT_AND_DECRYPT_SIDE, + ssl->earlyData == no_early_data)) != 0) { + return ret; + } + #else + if ((ret = DeriveTls13Keys(ssl, traffic_key, + ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) { + return ret; + } + #endif + } + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + if (type == certificate_request && + 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; + + if (wolfSSL_connect_TLSv13(ssl) != SSL_SUCCESS) + ret = POST_HAND_AUTH_ERROR; + } + #endif + } + #endif /* NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (ssl->options.side == WOLFSSL_SERVER_END && type == finished) { + ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); + if (ret != 0) + return ret; + } + #endif +#endif /* NO_WOLFSSL_SERVER */ + } + +#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) { + SendAlert(ssl, alert_fatal, unexpected_message); + 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) { + inputLength = ssl->arrays->pendingMsgSz - + ssl->arrays->pendingMsgOffset; + } + 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; +} + +#ifndef NO_WOLFSSL_CLIENT + +/* 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) +{ + 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 + #ifdef WOLFSSL_ASYNC_CRYPT + /* do not send buffered or advance state if last error was an + async pending operation */ + && ssl->error != WC_PENDING_E + #endif + ) { + 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 != no_early_data) { + #if !defined(WOLFSSL_TLS13_DRAFT_18) && \ + defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + if ((ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentChangeCipher = 1; + #endif + ssl->options.handShakeState = CLIENT_HELLO_COMPLETE; + return WOLFSSL_SUCCESS; + } + #endif + FALL_THROUGH; + + case CLIENT_HELLO_SENT: + /* Get the response/s from the server. */ + while (ssl->options.serverState < + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + 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) { + #ifndef WOLFSSL_NO_TLS12 + if (ssl->options.downgrade) + return wolfSSL_connect(ssl); + #endif + + WOLFSSL_MSG("Client using higher version, fatal error"); + return VERSION_ERROR; + } + + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + #if !defined(WOLFSSL_TLS13_DRAFT_18) && \ + defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + if (!ssl->options.sentChangeCipher) { + if ((ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentChangeCipher = 1; + } + #endif + /* 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: + /* Get the response/s from the server. */ + while (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + 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 != no_early_data) { + 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: + #if !defined(WOLFSSL_TLS13_DRAFT_18) && \ + defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + if (!ssl->options.sentChangeCipher) { + if ((ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentChangeCipher = 1; + } + #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 = SendTls13Certificate(ssl); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate"); + } + #endif + + ssl->options.connectState = FIRST_REPLY_THIRD; + WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD"); + FALL_THROUGH; + + case FIRST_REPLY_THIRD: + #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_FOURTH; + WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH"); + FALL_THROUGH; + + case FIRST_REPLY_FOURTH: + 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 */ + + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } + + WOLFSSL_LEAVE("wolfSSL_connect_TLSv13()", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; + + default: + WOLFSSL_MSG("Unknown connect state ERROR"); + return WOLFSSL_FATAL_ERROR; /* unknown connect state */ + } +} +#endif + +#if defined(WOLFSSL_SEND_HRR_COOKIE) +/* 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; + #ifndef NO_WOLFSSL_SERVER + 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; + + ret = WOLFSSL_SUCCESS; +#else + (void)secret; + (void)secretSz; + + ret = SIDE_ERROR; +#endif + + return ret; +} +#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; + + 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 client 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 client 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; +#ifndef NO_WOLFSSL_SERVER + CertReqCtx* certReqCtx; +#endif + + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; +#ifndef NO_WOLFSSL_SERVER + 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; + + ssl->msgsReceived.got_certificate = 0; + ssl->msgsReceived.got_certificate_verify = 0; + ssl->msgsReceived.got_finished = 0; + + ret = SendTls13CertificateRequest(ssl, &certReqCtx->ctx, certReqCtx->len); + if (ret == WANT_WRITE) + ret = WOLFSSL_ERROR_WANT_WRITE; + else if (ret == 0) + ret = WOLFSSL_SUCCESS; +#else + ret = SIDE_ERROR; +#endif + + return ret; +} +#endif /* !NO_CERTS && WOLFSSL_POST_HANDSHAKE_AUTH */ + +#if !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) +/* Get the preferred key exchange group. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL or not using TLS v1.3, + * SIDE_ERROR when not a client, NOT_READY_ERROR when handshake not complete + * and group number on success. + */ +int wolfSSL_preferred_group(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + if (ssl->options.handShakeState != HANDSHAKE_DONE) + return NOT_READY_ERROR; + + /* Return supported groups only. */ + return TLSX_SupportedCurve_Preferred(ssl, 1); +#else + return SIDE_ERROR; +#endif +} +#endif + +/* Sets the key exchange groups in rank order on a context. + * + * ctx SSL/TLS context object. + * groups Array of groups. + * count Number of groups in array. + * returns BAD_FUNC_ARG when ctx or groups is NULL, not using TLS v1.3 or + * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success. + */ +int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count) +{ + int i; + + if (ctx == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT) + return BAD_FUNC_ARG; + if (!IsAtLeastTLSv1_3(ctx->method->version)) + return BAD_FUNC_ARG; + + for (i = 0; i < count; i++) + ctx->group[i] = (word16)groups[i]; + ctx->numGroups = (byte)count; + + return WOLFSSL_SUCCESS; +} + +/* Sets the key exchange groups in rank order. + * + * ssl SSL/TLS object. + * groups Array of groups. + * count Number of groups in array. + * returns BAD_FUNC_ARG when ssl or groups is NULL, not using TLS v1.3 or + * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success. + */ +int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count) +{ + int i; + + if (ssl == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT) + return BAD_FUNC_ARG; + if (!IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + for (i = 0; i < count; i++) + ssl->group[i] = (word16)groups[i]; + ssl->numGroups = (byte)count; + + return WOLFSSL_SUCCESS; +} + +#ifndef NO_PSK +void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX* ctx, + wc_psk_client_tls13_callback cb) +{ + WOLFSSL_ENTER("SSL_CTX_set_psk_client_tls13_callback"); + + if (ctx == NULL) + return; + + ctx->havePSK = 1; + ctx->client_psk_tls13_cb = cb; +} + + +void wolfSSL_set_psk_client_tls13_callback(WOLFSSL* ssl, + wc_psk_client_tls13_callback cb) +{ + byte haveRSA = 1; + int keySz = 0; + + WOLFSSL_ENTER("SSL_set_psk_client_tls13_callback"); + + if (ssl == NULL) + return; + + ssl->options.havePSK = 1; + ssl->options.client_psk_tls13_cb = cb; + + #ifdef NO_RSA + haveRSA = 0; + #endif + #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); +} + + +void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX* ctx, + wc_psk_server_tls13_callback cb) +{ + WOLFSSL_ENTER("SSL_CTX_set_psk_server_tls13_callback"); + if (ctx == NULL) + return; + ctx->havePSK = 1; + ctx->server_psk_tls13_cb = cb; +} + + +void wolfSSL_set_psk_server_tls13_callback(WOLFSSL* ssl, + wc_psk_server_tls13_callback cb) +{ + byte haveRSA = 1; + int keySz = 0; + + WOLFSSL_ENTER("SSL_set_psk_server_tls13_callback"); + if (ssl == NULL) + return; + + ssl->options.havePSK = 1; + ssl->options.server_psk_tls13_cb = cb; + + #ifdef NO_RSA + haveRSA = 0; + #endif + #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); +} +#endif + + +#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; + 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; + + if (ssl->options.side != WOLFSSL_SERVER_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return WOLFSSL_FATAL_ERROR; + } + +#ifndef NO_CERTS + /* allow no private key if using PK callbacks and CB is set */ + if (!havePSK) { + if (!ssl->buffers.certificate || + !ssl->buffers.certificate->buffer) { + + WOLFSSL_MSG("accept error: server cert required"); + WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + return WOLFSSL_FATAL_ERROR; + } + + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + WOLFSSL_MSG("Using PK for server private key"); + } + else + #endif + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + WOLFSSL_MSG("accept error: server key required"); + WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + return WOLFSSL_FATAL_ERROR; + } + } +#endif + + if (ssl->buffers.outputBuffer.length > 0 + #ifdef WOLFSSL_ASYNC_CRYPT + /* do not send buffered or advance state if last error was an + async pending operation */ + && ssl->error != WC_PENDING_E + #endif + ) { + 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) { + +#ifdef HAVE_SECURE_RENEGOTIATION + case TLS13_ACCEPT_BEGIN_RENEG: +#endif + case TLS13_ACCEPT_BEGIN : + /* get client_hello */ + while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + ssl->options.acceptState = TLS13_ACCEPT_CLIENT_HELLO_DONE; + WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE"); + if (!IsAtLeastTLSv1_3(ssl->version)) + return wolfSSL_accept(ssl); + FALL_THROUGH; + + case TLS13_ACCEPT_CLIENT_HELLO_DONE : +#ifdef WOLFSSL_TLS13_DRAFT_18 + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + ssl->options.acceptState = TLS13_ACCEPT_FIRST_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; + + case TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE : +#else + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + if ((ssl->error = SendTls13ServerHello(ssl, + hello_retry_request)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + ssl->options.acceptState = TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE; + WOLFSSL_MSG("accept state ACCEPT_HELLO_RETRY_REQUEST_DONE"); + FALL_THROUGH; + + case TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE : + #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + if ((ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentChangeCipher = 1; + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; + } + #endif + ssl->options.acceptState = TLS13_ACCEPT_FIRST_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; +#endif + + case TLS13_ACCEPT_FIRST_REPLY_DONE : + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + ssl->options.clientState = CLIENT_HELLO_RETRY; + while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + } + + ssl->options.acceptState = TLS13_ACCEPT_SECOND_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE"); + FALL_THROUGH; + + case TLS13_ACCEPT_SECOND_REPLY_DONE : + if ((ssl->error = SendTls13ServerHello(ssl, server_hello)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = TLS13_SERVER_HELLO_SENT; + WOLFSSL_MSG("accept state SERVER_HELLO_SENT"); + FALL_THROUGH; + + case TLS13_SERVER_HELLO_SENT : + #if !defined(WOLFSSL_TLS13_DRAFT_18) && \ + defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + if (!ssl->options.sentChangeCipher) { + if ((ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentChangeCipher = 1; + } + #endif + + ssl->options.acceptState = TLS13_ACCEPT_THIRD_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE"); + FALL_THROUGH; + + case TLS13_ACCEPT_THIRD_REPLY_DONE : + if (!ssl->options.noPskDheKe) { + ssl->error = TLSX_KeyShare_DeriveSecret(ssl); + if (ssl->error != 0) + return WOLFSSL_FATAL_ERROR; + } + + if ((ssl->error = SendTls13EncryptedExtensions(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = TLS13_SERVER_EXTENSIONS_SENT; + WOLFSSL_MSG("accept state SERVER_EXTENSIONS_SENT"); + FALL_THROUGH; + + case TLS13_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 = TLS13_CERT_REQ_SENT; + WOLFSSL_MSG("accept state CERT_REQ_SENT"); + FALL_THROUGH; + + case TLS13_CERT_REQ_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 = TLS13_CERT_SENT; + WOLFSSL_MSG("accept state CERT_SENT"); + FALL_THROUGH; + + case TLS13_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 = TLS13_CERT_VERIFY_SENT; + WOLFSSL_MSG("accept state CERT_VERIFY_SENT"); + FALL_THROUGH; + + case TLS13_CERT_VERIFY_SENT : + if ((ssl->error = SendTls13Finished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + ssl->options.acceptState = TLS13_ACCEPT_FINISHED_SENT; + WOLFSSL_MSG("accept state ACCEPT_FINISHED_SENT"); +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + ssl->options.handShakeState = SERVER_FINISHED_COMPLETE; + return WOLFSSL_SUCCESS; + } +#endif + FALL_THROUGH; + + case TLS13_ACCEPT_FINISHED_SENT : +#ifdef HAVE_SESSION_TICKET + #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED + if (!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 = TLS13_PRE_TICKET_SENT; + WOLFSSL_MSG("accept state TICKET_SENT"); + FALL_THROUGH; + + case TLS13_PRE_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 = TLS13_ACCEPT_FINISHED_DONE; + WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); + FALL_THROUGH; + + case TLS13_ACCEPT_FINISHED_DONE : +#ifdef HAVE_SESSION_TICKET + #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED + if (!ssl->options.verifyPeer) { + } + else + #endif + if (!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 = TLS13_TICKET_SENT; + WOLFSSL_MSG("accept state TICKET_SENT"); + FALL_THROUGH; + + case TLS13_TICKET_SENT : +#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 */ + + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } + + 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; + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + + if (ssl->options.handShakeState == NULL_STATE) { + ssl->earlyData = expecting_early_data; + ret = wolfSSL_connect_TLSv13(ssl); + if (ret != WOLFSSL_SUCCESS) + return WOLFSSL_FATAL_ERROR; + } + if (ssl->options.handShakeState == CLIENT_HELLO_COMPLETE) { + ret = SendData(ssl, data, sz); + if (ret > 0) + *outSz = ret; + } +#else + return SIDE_ERROR; +#endif + + 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 = 0; + + 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; + +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + + if (ssl->options.handShakeState == NULL_STATE) { + ssl->earlyData = expecting_early_data; + 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; +#else + return SIDE_ERROR; +#endif + + WOLFSSL_LEAVE("wolfSSL_read_early_data()", ret); + + if (ret < 0) + ret = WOLFSSL_FATAL_ERROR; + return ret; +} +#endif + +#ifdef HAVE_SECRET_CALLBACK +int wolfSSL_set_tls13_secret_cb(WOLFSSL* ssl, Tls13SecretCb cb, void* ctx) +{ + WOLFSSL_ENTER("wolfSSL_set_tls13_secret_cb"); + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; + + ssl->tls13SecretCb = cb; + ssl->tls13SecretCtx = ctx; + + return WOLFSSL_SUCCESS; +} +#endif + +#undef ERROR_OUT + +#endif /* !WOLFCRYPT_ONLY */ + +#endif /* WOLFSSL_TLS13 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/src/wolfio.c b/FreeRTOS-Plus/Source/WolfSSL/src/wolfio.c new file mode 100644 index 000000000..b7032caee --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/src/wolfio.c @@ -0,0 +1,2375 @@ +/* wolfio.c + * + * Copyright (C) 2006-2020 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 /* strtol() */ +#endif + +/* +Possible IO enable options: + * WOLFSSL_USER_IO: Disables default Embed* callbacks and default: off + allows user to define their own using + wolfSSL_CTX_SetIORecv and wolfSSL_CTX_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 WC_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 WC_INLINE int wolfSSL_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 OPENSSL_EXTRA +/* Use the WOLFSSL read BIO for receiving data. This is set by the function + * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIORecv. + * + * ssl WOLFSSL struct passed in that has this function set as the receive + * callback. + * buf buffer to fill with data read + * sz size of buf buffer + * ctx a user set context + * + * returns the amount of data read or want read. See WOLFSSL_CBIO_ERR_* values. + */ +int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + int recvd = WOLFSSL_CBIO_ERR_GENERAL; + + WOLFSSL_ENTER("BioReceive"); + + if (ssl->biord == NULL) { + WOLFSSL_MSG("WOLFSSL biord not set"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + if (ssl->biord->method && ssl->biord->method->readCb) { + WOLFSSL_MSG("Calling custom biord"); + recvd = ssl->biord->method->readCb(ssl->biord, buf, sz); + if (recvd < 0 && recvd != WOLFSSL_CBIO_ERR_WANT_READ) + return WOLFSSL_CBIO_ERR_GENERAL; + return recvd; + } + + switch (ssl->biord->type) { + case WOLFSSL_BIO_MEMORY: + case WOLFSSL_BIO_BIO: + if (wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) { + WOLFSSL_MSG("BIO want read"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + recvd = wolfSSL_BIO_read(ssl->biord, buf, sz); + if (recvd <= 0) { + WOLFSSL_MSG("BIO general error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + break; + + default: + WOLFSSL_MSG("This BIO type is unknown / unsupported"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + (void)ctx; + return recvd; +} + + +/* Use the WOLFSSL write BIO for sending data. This is set by the function + * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIOSend. + * + * ssl WOLFSSL struct passed in that has this function set as the send callback. + * buf buffer with data to write out + * sz size of buf buffer + * ctx a user set context + * + * returns the amount of data sent or want send. See WOLFSSL_CBIO_ERR_* values. + */ +int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + int sent = WOLFSSL_CBIO_ERR_GENERAL; + + WOLFSSL_ENTER("BioSend"); + + if (ssl->biowr == NULL) { + WOLFSSL_MSG("WOLFSSL biowr not set"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + if (ssl->biowr->method && ssl->biowr->method->writeCb) { + WOLFSSL_MSG("Calling custom biowr"); + sent = ssl->biowr->method->writeCb(ssl->biowr, buf, sz); + if (sent < 0) { + return WOLFSSL_CBIO_ERR_GENERAL; + } + return sent; + } + + switch (ssl->biowr->type) { + case WOLFSSL_BIO_MEMORY: + case WOLFSSL_BIO_BIO: + sent = wolfSSL_BIO_write(ssl->biowr, buf, sz); + if (sent < 0) { + return WOLFSSL_CBIO_ERR_GENERAL; + } + break; + + default: + WOLFSSL_MSG("This BIO type is unknown / unsupported"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + (void)ctx; + + return sent; +} +#endif + + +#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; + + recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags); + if (recvd < 0) { + int err = wolfSSL_LastError(); + WOLFSSL_MSG("Embed Receive error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + 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_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; + +#ifdef WOLFSSL_MAX_SEND_SZ + if (sz > WOLFSSL_MAX_SEND_SZ) + sz = WOLFSSL_MAX_SEND_SZ; +#endif + + sent = wolfIO_Send(sd, buf, sz, ssl->wflags); + if (sent < 0) { + int err = wolfSSL_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 = wolfSSL_LastError(); + WOLFSSL_MSG("Embed Receive From error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + if (wolfSSL_dtls_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 err; + + WOLFSSL_ENTER("EmbedSendTo()"); + + sent = (int)SENDTO_FUNCTION(sd, buf, sz, ssl->wflags, + (const SOCKADDR*)dtlsCtx->peer.sa, + dtlsCtx->peer.sz); + + sent = TranslateReturnCode(sent, sd); + + if (sent < 0) { + err = wolfSSL_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 = wolfSSL_LastError(); + WOLFSSL_MSG("Embed Receive From error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + if (wolfSSL_dtls_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 overridden 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 overridden 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; + } + + int wolfIO_Select(SOCKET_T sockfd, int to_sec) + { + fd_set rfds, wfds; + int nfds = 0; + struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0}; + int ret; + + #ifndef USE_WINDOWS_API + nfds = (int)sockfd + 1; + #endif + + FD_ZERO(&rfds); + FD_SET(sockfd, &rfds); + wfds = rfds; + + ret = select(nfds, &rfds, &wfds, 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, &wfds)) { + if (!FD_ISSET(sockfd, &rfds)) { + 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); + /* use gethostbyname for c99 */ +#if defined(HAVE_GETADDRINFO) && !defined(WOLF_C99) + 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 + + /* use gethostbyname for c99 */ +#if defined(HAVE_GETADDRINFO) && !defined(WOLF_C99) + 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 (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0 && + url[cur] != ']') { + if (outName) + outName[i] = url[cur]; + i++; cur++; + } + cur++; /* skip ']' */ + } + else { + while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0 && + url[cur] != ':' && url[cur] != '/') { + 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 (i < 6 && cur < urlSz && url[cur] != 0 && url[cur] != '/') { + port[i] = url[cur]; + i++; 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 (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0) { + 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 + + (void)heap; + (void)dynType; + + if (chunkSz < 0 || len < 0) { + WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf invalid chunk or length size"); + return MEMORY_E; + } + + if (newRecvSz <= 0) { + WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf new receive size overflow"); + return MEMORY_E; + } + + 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) { + if (pos + len <= newRecvSz) { + XMEMCPY(&newRecvBuf[pos], start, len); + pos += len; + } + else { + WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf bad size"); + XFREE(newRecvBuf, heap, dynType); + return -1; + } + } + + /* 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 (XSTRLEN(start) < 15) { /* 15 is the length of the two + constant strings we're about to + compare against. */ + WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header too short."); + return -1; + } + 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 (XSTRLEN(start) < 13) { /* 13 is the shortest of the following + next lines we're checking for. */ + WOLFSSL_MSG("wolfIO_HttpProcessResponse content type is too short."); + return -1; + } + + if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { + int i; + + start += 13; + while (*start == ' ') 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++; + chunkSz = XATOI(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++; + 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) +{ + return wolfIO_HttpBuildRequest_ex(reqType, domainName, path, pathLen, reqSz, contentType, "", buf, bufSize); +} + + int wolfIO_HttpBuildRequest_ex(const char *reqType, const char *domainName, + const char *path, int pathLen, int reqSz, const char *contentType, + const char *exHdrs, byte *buf, int bufSize) + { + word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, exHdrsLen, 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* singleCrLfStr = "\r\n"; + const char* doubleCrLfStr = "\r\n\r\n"; + word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen, + contentTypeStrLen, singleCrLfStrLen, 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); + + if(exHdrs){ + singleCrLfStrLen = (word32)XSTRLEN(singleCrLfStr); + exHdrsLen = (word32)XSTRLEN(exHdrs); + } else { + singleCrLfStrLen = 0; + exHdrsLen = 0; + } + + doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr); + + /* determine max length and check it */ + maxLen = + reqTypeLen + + blankStrLen + + pathLen + + http11StrLen + + hostStrLen + + domainNameLen + + contentLenStrLen + + reqSzStrLen + + contentTypeStrLen + + contentTypeLen + + singleCrLfStrLen + + exHdrsLen + + doubleCrLfStrLen + + 1 /* null term */; + if (maxLen > (word32)bufSize) + return 0; + + XSTRNCPY((char*)buf, reqType, bufSize); + buf += reqTypeLen; bufSize -= reqTypeLen; + XSTRNCPY((char*)buf, blankStr, bufSize); + buf += blankStrLen; bufSize -= blankStrLen; + XSTRNCPY((char*)buf, path, bufSize); + buf += pathLen; bufSize -= pathLen; + XSTRNCPY((char*)buf, http11Str, bufSize); + buf += http11StrLen; bufSize -= http11StrLen; + if (domainNameLen > 0) { + XSTRNCPY((char*)buf, hostStr, bufSize); + buf += hostStrLen; bufSize -= hostStrLen; + XSTRNCPY((char*)buf, domainName, bufSize); + buf += domainNameLen; bufSize -= domainNameLen; + } + if (reqSz > 0 && reqSzStrLen > 0) { + XSTRNCPY((char*)buf, contentLenStr, bufSize); + buf += contentLenStrLen; bufSize -= contentLenStrLen; + XSTRNCPY((char*)buf, reqSzStr, bufSize); + buf += reqSzStrLen; bufSize -= reqSzStrLen; + } + if (contentTypeLen > 0) { + XSTRNCPY((char*)buf, contentTypeStr, bufSize); + buf += contentTypeStrLen; bufSize -= contentTypeStrLen; + XSTRNCPY((char*)buf, contentType, bufSize); + buf += contentTypeLen; bufSize -= contentTypeLen; + } + if (exHdrsLen > 0) + { + XSTRNCPY((char *)buf, singleCrLfStr, bufSize); + buf += singleCrLfStrLen; + bufSize -= singleCrLfStrLen; + XSTRNCPY((char *)buf, exHdrs, bufSize); + buf += exHdrsLen; + bufSize -= exHdrsLen; + } + XSTRNCPY((char*)buf, doubleCrLfStr, bufSize); + 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) +{ + const char *cacheCtl = "Cache-Control: no-cache"; + return wolfIO_HttpBuildRequest_ex("POST", domainName, path, (int)XSTRLEN(path), + ocspReqSz, "application/ocsp-request", cacheCtl, 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) || ((int)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); + } + + CloseSocket(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) +{ + const char *cacheCtl = "Cache-Control: no-cache"; + return wolfIO_HttpBuildRequest_ex("GET", domainName, url, urlSz, 0, "", + cacheCtl, 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); + } + + CloseSocket(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 */ + + + +void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv) +{ + if (ctx) { + ctx->CBIORecv = CBIORecv; + #ifdef OPENSSL_EXTRA + ctx->cbioFlag |= WOLFSSL_CBIO_RECV; + #endif + } +} + + +void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend) +{ + if (ctx) { + ctx->CBIOSend = CBIOSend; + #ifdef OPENSSL_EXTRA + ctx->cbioFlag |= WOLFSSL_CBIO_SEND; + #endif + } +} + + +/* sets the IO callback to use for receives at WOLFSSL level */ +void wolfSSL_SSLSetIORecv(WOLFSSL *ssl, CallbackIORecv CBIORecv) +{ + if (ssl) { + ssl->CBIORecv = CBIORecv; + #ifdef OPENSSL_EXTRA + ssl->cbioFlag |= WOLFSSL_CBIO_RECV; + #endif + } +} + + +/* sets the IO callback to use for sends at WOLFSSL level */ +void wolfSSL_SSLSetIOSend(WOLFSSL *ssl, CallbackIOSend CBIOSend) +{ + if (ssl) { + ssl->CBIOSend = CBIOSend; + #ifdef OPENSSL_EXTRA + ssl->cbioFlag |= WOLFSSL_CBIO_SEND; + #endif + } +} + + +void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx) +{ + if (ssl) + ssl->IOCB_ReadCtx = rctx; +} + + +void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx) +{ + if (ssl) + ssl->IOCB_WriteCtx = wctx; +} + + +void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->IOCB_ReadCtx; + + return NULL; +} + + +void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->IOCB_WriteCtx; + + return NULL; +} + + +void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags) +{ + if (ssl) + ssl->rflags = flags; +} + + +void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags) +{ + if (ssl) + ssl->wflags = flags; +} + + +#ifdef WOLFSSL_DTLS + +void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb) +{ + if (ctx) + ctx->CBIOCookie = cb; +} + + +void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->IOCB_CookieCtx = ctx; +} + + +void* wolfSSL_GetCookieCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->IOCB_CookieCtx; + + return NULL; +} + +#ifdef WOLFSSL_SESSION_EXPORT + +void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb) +{ + if (ctx) + ctx->CBGetPeer = cb; +} + + +void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb) +{ + if (ctx) + 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_dtls_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_dtls_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_dtls_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_dtls_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; + NET_ERR err; + + WOLFSSL_ENTER("MicriumSendTo()"); + + ret = NetSock_TxDataTo(sd, buf, sz, 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 */ + +#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + +#include +#include +#include + +#define MB_NAME "wolfssl_mb" + +typedef struct Mynewt_Ctx { + struct mn_socket *mnSocket; /* send/recv socket handler */ + struct mn_sockaddr_in mnSockAddrIn; /* socket address */ + struct os_mbuf *mnPacket; /* incoming packet handle + for short reads */ + int reading; /* reading flag */ + + /* private */ + void *mnMemBuffer; /* memory buffer for mempool */ + struct os_mempool mnMempool; /* mempool */ + struct os_mbuf_pool mnMbufpool; /* mbuf pool */ +} Mynewt_Ctx; + +void mynewt_ctx_clear(void *ctx) { + Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx; + if(!mynewt_ctx) return; + + if(mynewt_ctx->mnPacket) { + os_mbuf_free_chain(mynewt_ctx->mnPacket); + mynewt_ctx->mnPacket = NULL; + } + os_mempool_clear(&mynewt_ctx->mnMempool); + XFREE(mynewt_ctx->mnMemBuffer, 0, 0); + XFREE(mynewt_ctx, 0, 0); +} + +/* return Mynewt_Ctx instance */ +void* mynewt_ctx_new() { + int rc = 0; + Mynewt_Ctx *mynewt_ctx; + int mem_buf_count = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_COUNT); + int mem_buf_size = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_SIZE); + int mempool_bytes = OS_MEMPOOL_BYTES(mem_buf_count, mem_buf_size); + + mynewt_ctx = (Mynewt_Ctx *)XMALLOC(sizeof(struct Mynewt_Ctx), + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if(!mynewt_ctx) return NULL; + + XMEMSET(mynewt_ctx, 0, sizeof(Mynewt_Ctx)); + mynewt_ctx->mnMemBuffer = XMALLOC(mempool_bytes, 0, 0); + if(!mynewt_ctx->mnMemBuffer) { + mynewt_ctx_clear((void*)mynewt_ctx); + return NULL; + } + + rc = os_mempool_init(&mynewt_ctx->mnMempool, + mem_buf_count, mem_buf_size, + mynewt_ctx->mnMemBuffer, MB_NAME); + if(rc != 0) { + mynewt_ctx_clear((void*)mynewt_ctx); + return NULL; + } + rc = os_mbuf_pool_init(&mynewt_ctx->mnMbufpool, &mynewt_ctx->mnMempool, + mem_buf_count, mem_buf_size); + if(rc != 0) { + mynewt_ctx_clear((void*)mynewt_ctx); + return NULL; + } + + return mynewt_ctx; +} + +static void mynewt_sock_writable(void *arg, int err); +static void mynewt_sock_readable(void *arg, int err); +static const union mn_socket_cb mynewt_sock_cbs = { + .socket.writable = mynewt_sock_writable, + .socket.readable = mynewt_sock_readable, +}; +static void mynewt_sock_writable(void *arg, int err) +{ + /* do nothing */ +} +static void mynewt_sock_readable(void *arg, int err) +{ + Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)arg; + if (err && mynewt_ctx->reading) { + mynewt_ctx->reading = 0; + } +} + +/* The Mynewt receive callback + * return : bytes read, or error + */ +int Mynewt_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx; + int rc = 0; + struct mn_sockaddr_in from; + struct os_mbuf *m; + int read_sz = 0; + uint16_t total; + + if (mynewt_ctx == NULL || mynewt_ctx->mnSocket == NULL) { + WOLFSSL_MSG("Mynewt Recv NULL parameters"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + if(mynewt_ctx->mnPacket == NULL) { + mynewt_ctx->mnPacket = os_mbuf_get_pkthdr(&mynewt_ctx->mnMbufpool, 0); + if(mynewt_ctx->mnPacket == NULL) { + return MEMORY_E; + } + + mynewt_ctx->reading = 1; + while(mynewt_ctx->reading && rc == 0) { + rc = mn_recvfrom(mynewt_ctx->mnSocket, &m, (struct mn_sockaddr *) &from); + if(rc == MN_ECONNABORTED) { + rc = 0; + mynewt_ctx->reading = 0; + break; + } + if (!(rc == 0 || rc == MN_EAGAIN)) { + WOLFSSL_MSG("Mynewt Recv receive error"); + mynewt_ctx->reading = 0; + break; + } + if(rc == 0) { + int len = OS_MBUF_PKTLEN(m); + if(len == 0) { + break; + } + rc = os_mbuf_appendfrom(mynewt_ctx->mnPacket, m, 0, len); + if(rc != 0) { + WOLFSSL_MSG("Mynewt Recv os_mbuf_appendfrom error"); + break; + } + os_mbuf_free_chain(m); + m = NULL; + } else if(rc == MN_EAGAIN) { + /* continue to until reading all of packet data. */ + rc = 0; + break; + } + } + if(rc != 0) { + mynewt_ctx->reading = 0; + os_mbuf_free_chain(mynewt_ctx->mnPacket); + mynewt_ctx->mnPacket = NULL; + return rc; + } + } + + if(mynewt_ctx->mnPacket) { + total = OS_MBUF_PKTLEN(mynewt_ctx->mnPacket); + read_sz = (total >= sz)? sz : total; + + os_mbuf_copydata(mynewt_ctx->mnPacket, 0, read_sz, (void*)buf); + os_mbuf_adj(mynewt_ctx->mnPacket, read_sz); + + if (read_sz == total) { + WOLFSSL_MSG("Mynewt Recv Drained packet"); + os_mbuf_free_chain(mynewt_ctx->mnPacket); + mynewt_ctx->mnPacket = NULL; + } + } + + return read_sz; +} + +/* The Mynewt send callback + * return : bytes sent, or error + */ +int Mynewt_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx; + int rc = 0; + struct os_mbuf *m; + int write_sz = 0; + m = os_msys_get_pkthdr(sz, 0); + if (!m) { + WOLFSSL_MSG("Mynewt Send os_msys_get_pkthdr error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + rc = os_mbuf_copyinto(m, 0, buf, sz); + if (rc != 0) { + WOLFSSL_MSG("Mynewt Send os_mbuf_copyinto error"); + os_mbuf_free_chain(m); + return rc; + } + rc = mn_sendto(mynewt_ctx->mnSocket, m, (struct mn_sockaddr *)&mynewt_ctx->mnSockAddrIn); + if(rc != 0) { + WOLFSSL_MSG("Mynewt Send mn_sendto error"); + os_mbuf_free_chain(m); + return rc; + } + write_sz = sz; + return write_sz; +} + +/* like set_fd, but for default NetX context */ +void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket, struct mn_sockaddr_in* mnSockAddrIn) +{ + if (ssl && ssl->mnCtx) { + Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)ssl->mnCtx; + mynewt_ctx->mnSocket = mnSocket; + memcpy(&mynewt_ctx->mnSockAddrIn, mnSockAddrIn, sizeof(struct mn_sockaddr_in)); + mn_socket_set_cbs(mynewt_ctx->mnSocket, mnSocket, &mynewt_sock_cbs); + } +} + +#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */ + +#ifdef WOLFSSL_UIP +#include +#include + +/* uIP TCP/IP port, using the native tcp/udp socket api. + * TCP and UDP are currently supported with the callbacks below. + * + */ +/* The uIP tcp send callback + * return : bytes sent, or error + */ +int uIPSend(WOLFSSL* ssl, char* buf, int sz, void* _ctx) +{ + uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx; + int ret; + unsigned int max_sendlen; + int total_written = 0; + (void)ssl; + do { + unsigned int bytes_left = sz - total_written; + max_sendlen = tcp_socket_max_sendlen(&ctx->conn.tcp); + if (bytes_left > max_sendlen) { + printf("Send limited by buffer\r\n"); + bytes_left = max_sendlen; + } + if (bytes_left == 0) { + printf("Buffer full!\r\n"); + break; + } + ret = tcp_socket_send(&ctx->conn.tcp, (unsigned char *)buf + total_written, bytes_left); + if (ret <= 0) + break; + total_written += ret; + } while(total_written < sz); + if (total_written == 0) + return WOLFSSL_CBIO_ERR_WANT_WRITE; + return total_written; +} + +int uIPSendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx) +{ + uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx; + int ret = 0; + (void)ssl; + ret = udp_socket_sendto(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr, ctx->peer_port ); + if (ret == 0) + return WOLFSSL_CBIO_ERR_WANT_WRITE; + return ret; +} + +/* The uIP uTCP/IP receive callback + * return : nb bytes read, or error + */ +int uIPReceive(WOLFSSL *ssl, char *buf, int sz, void *_ctx) +{ + uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx; + if (!ctx || !ctx->ssl_rx_databuf) + return -1; + (void)ssl; + if (ctx->ssl_rb_len > 0) { + if (sz > ctx->ssl_rb_len - ctx->ssl_rb_off) + sz = ctx->ssl_rb_len - ctx->ssl_rb_off; + XMEMCPY(buf, ctx->ssl_rx_databuf + ctx->ssl_rb_off, sz); + ctx->ssl_rb_off += sz; + if (ctx->ssl_rb_off >= ctx->ssl_rb_len) { + ctx->ssl_rb_len = 0; + ctx->ssl_rb_off = 0; + } + return sz; + } else { + return WOLFSSL_CBIO_ERR_WANT_READ; + } +} + +/* uIP DTLS Generate Cookie callback + * return : number of bytes copied into buf, or error + */ +int uIPGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx) +{ + uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx; + byte token[32]; + byte digest[WC_SHA_DIGEST_SIZE]; + int ret = 0; + XMEMSET(token, 0, sizeof(token)); + XMEMCPY(token, &ctx->peer_addr, sizeof(uip_ipaddr_t)); + XMEMCPY(token + sizeof(uip_ipaddr_t), &ctx->peer_port, sizeof(word16)); + ret = wc_ShaHash(token, sizeof(uip_ipaddr_t) + sizeof(word16), digest); + if (ret != 0) + return ret; + if (sz > WC_SHA_DIGEST_SIZE) + sz = WC_SHA_DIGEST_SIZE; + XMEMCPY(buf, digest, sz); + return sz; +} + +#endif /* WOLFSSL_UIP */ + +#ifdef WOLFSSL_GNRC + +#include +#include +#include + +/* GNRC TCP/IP port, using the native tcp/udp socket api. + * TCP and UDP are currently supported with the callbacks below. + * + */ +/* The GNRC tcp send callback + * return : bytes sent, or error + */ + +int GNRC_SendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx) +{ + sock_tls_t *ctx = (sock_tls_t *)_ctx; + int ret = 0; + (void)ssl; + if (!ctx) + return WOLFSSL_CBIO_ERR_GENERAL; + ret = sock_udp_send(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr); + if (ret == 0) + return WOLFSSL_CBIO_ERR_WANT_WRITE; + return ret; +} + +/* The GNRC TCP/IP receive callback + * return : nb bytes read, or error + */ +int GNRC_ReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *_ctx) +{ + sock_udp_ep_t ep; + int ret; + uint32_t timeout = wolfSSL_dtls_get_current_timeout(ssl) * 1000000; + sock_tls_t *ctx = (sock_tls_t *)_ctx; + if (!ctx) + return WOLFSSL_CBIO_ERR_GENERAL; + (void)ssl; + if (wolfSSL_get_using_nonblock(ctx->ssl)) { + timeout = 0; + } + ret = sock_udp_recv(&ctx->conn.udp, buf, sz, timeout, &ep); + if (ret > 0) { + if (ctx->peer_addr.port == 0) + XMEMCPY(&ctx->peer_addr, &ep, sizeof(sock_udp_ep_t)); + } + if (ret == -ETIMEDOUT) { + return WOLFSSL_CBIO_ERR_WANT_READ; + } + return ret; +} + +/* GNRC DTLS Generate Cookie callback + * return : number of bytes copied into buf, or error + */ +#define GNRC_MAX_TOKEN_SIZE (32) +int GNRC_GenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx) +{ + sock_tls_t *ctx = (sock_tls_t *)_ctx; + if (!ctx) + return WOLFSSL_CBIO_ERR_GENERAL; + byte token[GNRC_MAX_TOKEN_SIZE]; + byte digest[WC_SHA_DIGEST_SIZE]; + int ret = 0; + size_t token_size = sizeof(sock_udp_ep_t); + (void)ssl; + if (token_size > GNRC_MAX_TOKEN_SIZE) + token_size = GNRC_MAX_TOKEN_SIZE; + XMEMSET(token, 0, GNRC_MAX_TOKEN_SIZE); + XMEMCPY(token, &ctx->peer_addr, token_size); + ret = wc_ShaHash(token, token_size, digest); + if (ret != 0) + return ret; + if (sz > WC_SHA_DIGEST_SIZE) + sz = WC_SHA_DIGEST_SIZE; + XMEMCPY(buf, digest, sz); + return sz; +} + +#endif /* WOLFSSL_GNRC */ + +#endif /* WOLFCRYPT_ONLY */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSniffer.vcproj b/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSniffer.vcproj index f485e87ae..d6d03a835 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSniffer.vcproj +++ b/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSniffer.vcproj @@ -41,8 +41,8 @@ + + @@ -196,7 +200,7 @@ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" > diff --git a/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSniffer.vcxproj b/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSniffer.vcxproj index 56404e997..bfbc7fc9d 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSniffer.vcxproj +++ b/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSniffer.vcxproj @@ -88,8 +88,8 @@ Disabled - ../;%(AdditionalIncludeDirectories) - OPENSSL_EXTRA;WOLFSSL_RIPEMD;WOLFSSL_SHA512;NO_PSK;WOLFSSL_SNIFFER;SSL_SNIFFER_EXPORTS;%(PreprocessorDefinitions) + ../;../IDE/WIN;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;SSL_SNIFFER_EXPORTS;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -108,8 +108,8 @@ Disabled - ../;%(AdditionalIncludeDirectories) - OPENSSL_EXTRA;WOLFSSL_RIPEMD;WOLFSSL_SHA512;NO_PSK;WOLFSSL_SNIFFER;SSL_SNIFFER_EXPORTS;%(PreprocessorDefinitions) + ../;../IDE/WIN;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;SSL_SNIFFER_EXPORTS;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -127,8 +127,8 @@ MaxSpeed true - ../;%(AdditionalIncludeDirectories) - OPENSSL_EXTRA;WOLFSSL_RIPEMD;WOLFSSL_SHA512;NO_PSK;WOLFSSL_SNIFFER;SSL_SNIFFER_EXPORTS;%(PreprocessorDefinitions) + ../;../IDE/WIN;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;SSL_SNIFFER_EXPORTS;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -149,8 +149,8 @@ MaxSpeed true - ../;%(AdditionalIncludeDirectories) - OPENSSL_EXTRA;WOLFSSL_RIPEMD;WOLFSSL_SHA512;NO_PSK;WOLFSSL_SNIFFER;SSL_SNIFFER_EXPORTS;%(PreprocessorDefinitions) + ../;../IDE/WIN;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;SSL_SNIFFER_EXPORTS;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -171,6 +171,7 @@ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSnifferTest/include.am b/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSnifferTest/include.am index 222777c7f..23de07f91 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSnifferTest/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSnifferTest/include.am @@ -5,7 +5,7 @@ if BUILD_SNIFFTEST noinst_PROGRAMS += sslSniffer/sslSnifferTest/snifftest sslSniffer_sslSnifferTest_snifftest_SOURCES = sslSniffer/sslSnifferTest/snifftest.c -sslSniffer_sslSnifferTest_snifftest_LDADD = src/libwolfssl.la -lpcap +sslSniffer_sslSnifferTest_snifftest_LDADD = src/libwolfssl.la -lpcap $(LIB_STATIC_ADD) sslSniffer_sslSnifferTest_snifftest_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += sslSniffer/sslSniffer.vcproj diff --git a/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSnifferTest/snifftest.c b/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSnifferTest/snifftest.c index 8ffe24d5a..1b4292af1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSnifferTest/snifftest.c +++ b/FreeRTOS-Plus/Source/WolfSSL/sslSniffer/sslSnifferTest/snifftest.c @@ -1,8 +1,8 @@ /* snifftest.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,15 +16,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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB + #include +#endif + #ifdef _WIN32 #define WOLFSSL_SNIFFER #endif @@ -53,6 +58,7 @@ int main(void) #include /* EXIT_SUCCESS */ #include /* strcmp */ #include /* signal */ +#include /* isprint */ #include @@ -60,6 +66,7 @@ int main(void) #ifndef _WIN32 #include /* AF_INET */ #include + #include #endif typedef unsigned char byte; @@ -70,6 +77,25 @@ enum { }; +/* A TLS record can be 16k and change. The chain is broken up into 2K chunks. + * This covers the TLS record, plus a chunk for TCP/IP headers. */ +#ifndef CHAIN_INPUT_CHUNK_SIZE + #define CHAIN_INPUT_CHUNK_SIZE 2048 +#elif (CHAIN_INPUT_CHUNK_SIZE < 256) + #undef CHAIN_INPUT_CHUNK_SIZE + #define CHAIN_INPUT_CHUNK_SIZE 256 +#elif (CHAIN_INPUT_CHUNK_SIZE > 16384) + #undef CHAIN_INPUT_CHUNK_SIZE + #define CHAIN_INPUT_CHUNK_SIZE 16384 +#endif +#define CHAIN_INPUT_COUNT ((16384 / CHAIN_INPUT_CHUNK_SIZE) + 1) + + +#ifndef STORE_DATA_BLOCK_SZ + #define STORE_DATA_BLOCK_SZ 1024 +#endif + + pcap_t* pcap = NULL; pcap_if_t* alldevs = NULL; @@ -85,10 +111,58 @@ static void FreeAll(void) #endif } -static void sig_handler(const int sig) + +#ifdef WOLFSSL_SNIFFER_STATS + +static void DumpStats(void) +{ + SSLStats sslStats; + ssl_ReadStatistics(&sslStats); + + printf("SSL Stats (sslStandardConns):%lu\n", + sslStats.sslStandardConns); + printf("SSL Stats (sslClientAuthConns):%lu\n", + sslStats.sslClientAuthConns); + printf("SSL Stats (sslResumedConns):%lu\n", + sslStats.sslResumedConns); + printf("SSL Stats (sslEphemeralMisses):%lu\n", + sslStats.sslEphemeralMisses); + printf("SSL Stats (sslResumeMisses):%lu\n", + sslStats.sslResumeMisses); + printf("SSL Stats (sslCiphersUnsupported):%lu\n", + sslStats.sslCiphersUnsupported); + printf("SSL Stats (sslKeysUnmatched):%lu\n", + sslStats.sslKeysUnmatched); + printf("SSL Stats (sslKeyFails):%lu\n", + sslStats.sslKeyFails); + printf("SSL Stats (sslDecodeFails):%lu\n", + sslStats.sslDecodeFails); + printf("SSL Stats (sslAlerts):%lu\n", + sslStats.sslAlerts); + printf("SSL Stats (sslDecryptedBytes):%lu\n", + sslStats.sslDecryptedBytes); + printf("SSL Stats (sslEncryptedBytes):%lu\n", + sslStats.sslEncryptedBytes); + printf("SSL Stats (sslEncryptedPackets):%lu\n", + sslStats.sslEncryptedPackets); + printf("SSL Stats (sslDecryptedPackets):%lu\n", + sslStats.sslDecryptedPackets); + printf("SSL Stats (sslKeyMatches):%lu\n", + sslStats.sslKeyMatches); + printf("SSL Stats (sslEncryptedConns):%lu\n", + sslStats.sslEncryptedConns); +} + +#endif + + +static void sig_handler(const int sig) { printf("SIGINT handled = %d.\n", sig); FreeAll(); +#ifdef WOLFSSL_SNIFFER_STATS + DumpStats(); +#endif if (sig) exit(EXIT_SUCCESS); } @@ -109,17 +183,114 @@ static void err_sys(const char* msg) #endif -static char* iptos(unsigned int addr) +static char* iptos(const struct in_addr* addr) { static char output[32]; - byte *p = (byte*)&addr; + byte *p = (byte*)&addr->s_addr; - SNPRINTF(output, sizeof(output), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + snprintf(output, sizeof(output), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); return output; } +static const char* ip6tos(const struct in6_addr* addr) +{ + static char output[42]; + return inet_ntop(AF_INET6, addr, output, 42); +} + + +#if defined(WOLFSSL_SNIFFER_STORE_DATA_CB) || defined(WOLFSSL_SNIFFER_CHAIN_INPUT) + +static inline unsigned int min(unsigned int a, unsigned int b) +{ + return a > b ? b : a; +} + +#endif + + +#ifdef WOLFSSL_SNIFFER_WATCH + +const byte rsaHash[] = { + 0xD1, 0xB6, 0x12, 0xAD, 0xB6, 0x50, 0x7B, 0x59, + 0x97, 0x83, 0x6B, 0xCB, 0x35, 0xF5, 0xB8, 0x67, + 0xEB, 0x83, 0x75, 0x40, 0x1B, 0x42, 0x61, 0xF1, + 0x03, 0x72, 0xDC, 0x09, 0x0D, 0x60, 0x83, 0x15 +}; + +const byte eccHash[] = { + 0xDA, 0x08, 0x6D, 0xB5, 0x0B, 0xC4, 0x9F, 0x8A, + 0x9E, 0x61, 0x9E, 0x87, 0x57, 0x5F, 0x00, 0xAA, + 0x76, 0xE5, 0x1C, 0x9C, 0x74, 0x2A, 0x19, 0xBE, + 0x22, 0xAE, 0x25, 0x3F, 0xA8, 0xAF, 0x8E, 0x7F +}; + + +static int myWatchCb(void* vSniffer, + const unsigned char* certHash, unsigned int certHashSz, + const unsigned char* certChain, unsigned int certChainSz, + void* ctx, char* error) +{ + const char* certName = NULL; + + (void)certChain; + (void)certChainSz; + (void)ctx; + + if (certHashSz == sizeof(rsaHash) && + memcmp(certHash, rsaHash, certHashSz) == 0) + certName = "../../certs/server-key.pem"; + if (certHashSz == sizeof(eccHash) && + memcmp(certHash, eccHash, certHashSz) == 0) + certName = "../../certs/ecc-key.pem"; + + if (certName == NULL) + return -1; + + return ssl_SetWatchKey_file(vSniffer, certName, FILETYPE_PEM, NULL, error); +} + +#endif + + +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB + +static int myStoreDataCb(const unsigned char* decryptBuf, + unsigned int decryptBufSz, unsigned int decryptBufOffset, void* ctx) +{ + byte** data = (byte**)ctx; + unsigned int qty; + + if (data == NULL) + return -1; + + if (decryptBufSz < decryptBufOffset) + return -1; + + qty = min(decryptBufSz - decryptBufOffset, STORE_DATA_BLOCK_SZ); + + if (*data == NULL) { + byte* tmpData; + tmpData = (byte*)XREALLOC(*data, decryptBufSz + 1, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpData == NULL) { + XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + *data = NULL; + return -1; + } + *data = tmpData; + } + + memcpy(*data + decryptBufOffset, decryptBuf + decryptBufOffset, qty); + + return qty; +} + +#endif + + int main(int argc, char** argv) { int ret = 0; @@ -128,13 +299,17 @@ 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; struct bpf_program fp; pcap_if_t *d; pcap_addr_t *a; +#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT + struct iovec chain[CHAIN_INPUT_COUNT]; + int chainSz; +#endif signal(SIGINT, sig_handler); @@ -142,6 +317,13 @@ int main(int argc, char** argv) ssl_InitSniffer(); /* dll load on Windows */ #endif ssl_Trace("./tracefile.txt", err); + ssl_EnableRecovery(1, -1, err); +#ifdef WOLFSSL_SNIFFER_WATCH + ssl_SetWatchKeyCallback(myWatchCb, err); +#endif +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB + ssl_SetStoreDataCallback(myStoreDataCb); +#endif if (argc == 1) { /* normal case, user chooses device and port */ @@ -163,8 +345,9 @@ int main(int argc, char** argv) printf("Enter the interface number (1-%d): ", i); ret = scanf("%d", &inum); - if (ret != 1) + if (ret != 1) { printf("scanf port failed\n"); + } if (inum < 1 || inum > i) err_sys("Interface number out of range"); @@ -176,34 +359,33 @@ int main(int argc, char** argv) if (pcap == NULL) printf("pcap_create failed %s\n", err); - /* get an IPv4 address */ + /* print out addresses for selected interface */ for (a = d->addresses; a; a = a->next) { - switch(a->addr->sa_family) - { - case AF_INET: - server = - iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr); - printf("server = %s\n", server); - break; - - default: - break; - } + if (a->addr->sa_family == AF_INET) { + server = + iptos(&((struct sockaddr_in *)a->addr)->sin_addr); + printf("server = %s\n", server); + } + else if (a->addr->sa_family == AF_INET6) { + server = + ip6tos(&((struct sockaddr_in6 *)a->addr)->sin6_addr); + printf("server = %s\n", server); + } } if (server == NULL) - err_sys("Unable to get device IPv4 address"); + err_sys("Unable to get device IPv4 or IPv6 address"); 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)); @@ -223,30 +405,48 @@ int main(int argc, char** argv) ret = pcap_setfilter(pcap, &fp); if (ret != 0) printf("pcap_setfilter failed %s\n", pcap_geterr(pcap)); - ret = ssl_SetPrivateKey(server, port, "../../certs/server-key.pem", - FILETYPE_PEM, NULL, err); - if (ret != 0) { - printf("Please run directly from sslSniffer/sslSnifferTest dir\n"); - } - -#ifdef HAVE_SNI - { - char altName[128]; - - printf("Enter alternate SNI: "); - ret = scanf("%s", altName); - - if (strnlen(altName, 128) > 0) { - ret = ssl_SetNamedPrivateKey(altName, - server, port, "../../certs/server-key.pem", - FILETYPE_PEM, NULL, err); - if (ret != 0) { - printf("Please run directly from " - "sslSniffer/sslSnifferTest dir\n"); - } + /* get IPv4 or IPv6 addresses for selected interface */ + for (a = d->addresses; a; a = a->next) { + server = NULL; + if (a->addr->sa_family == AF_INET) { + server = + iptos(&((struct sockaddr_in *)a->addr)->sin_addr); } - } -#endif + else if (a->addr->sa_family == AF_INET6) { + server = + ip6tos(&((struct sockaddr_in6 *)a->addr)->sin6_addr); + } + + if (server) { + #ifndef WOLFSSL_SNIFFER_WATCH + ret = ssl_SetPrivateKey(server, port, + "../../certs/server-key.pem", + FILETYPE_PEM, NULL, err); + if (ret != 0) { + printf("Please run directly from sslSniffer/sslSnifferTest" + "dir\n"); + } + #ifdef HAVE_SNI + { + char altName[128]; + + printf("Enter alternate SNI: "); + ret = scanf("%s", altName); + + if (strnlen(altName, 128) > 0) { + ret = ssl_SetNamedPrivateKey(altName, + server, port, "../../certs/server-key.pem", + FILETYPE_PEM, NULL, err); + if (ret != 0) { + printf("Please run directly from " + "sslSniffer/sslSnifferTest dir\n"); + } + } + } + #endif + #endif + } + } } else if (argc >= 3) { saveFile = 1; @@ -284,33 +484,72 @@ 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) { static int packetNumber = 0; struct pcap_pkthdr header; const unsigned char* packet = pcap_next(pcap, &header); + SSLInfo sslInfo; packetNumber++; if (packet) { - byte data[65535+16384]; /* may have a partial 16k record cached */ + byte* data = NULL; if (header.caplen > 40) { /* min ip(20) + min tcp(20) */ packet += frame; - header.caplen -= frame; + header.caplen -= frame; } else continue; +#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT + { + unsigned int j = 0; + unsigned int remainder = header.caplen; - ret = ssl_DecodePacket(packet, header.caplen, data, err); + chainSz = 0; + do { + unsigned int chunkSz; + + chunkSz = min(remainder, CHAIN_INPUT_CHUNK_SIZE); + chain[chainSz].iov_base = (void*)(packet + j); + chain[chainSz].iov_len = chunkSz; + j += chunkSz; + remainder -= chunkSz; + chainSz++; + } while (j < header.caplen); + } +#endif + +#if defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \ + defined(WOLFSSL_SNIFFER_STORE_DATA_CB) + ret = ssl_DecodePacketWithChainSessionInfoStoreData(chain, chainSz, + &data, &sslInfo, err); +#elif defined(WOLFSSL_SNIFFER_CHAIN_INPUT) + (void)sslInfo; + ret = ssl_DecodePacketWithChain(chain, chainSz, &data, err); +#elif defined(WOLFSSL_SNIFFER_STORE_DATA_CB) + ret = ssl_DecodePacketWithSessionInfoStoreData(packet, + header.caplen, &data, &sslInfo, err); +#else + ret = ssl_DecodePacketWithSessionInfo(packet, header.caplen, &data, + &sslInfo, err); +#endif if (ret < 0) { printf("ssl_Decode ret = %d, %s\n", ret, err); hadBadPacket = 1; } if (ret > 0) { + int j; + /* Convert non-printable data to periods. */ + for (j = 0; j < ret; j++) { + if (isprint(data[j]) || isspace(data[j])) continue; + data[j] = '.'; + } data[ret] = 0; - printf("SSL App Data(%d:%d):%s\n", packetNumber, ret, data); + printf("SSL App Data(%d:%d):%s\n", packetNumber, ret, data); + ssl_FreeZeroDecodeBuffer(&data, ret, err); } } else if (saveFile) diff --git a/FreeRTOS-Plus/Source/WolfSSL/support/wolfssl.pc b/FreeRTOS-Plus/Source/WolfSSL/support/wolfssl.pc index 277eb17bb..8550a98c0 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/support/wolfssl.pc +++ b/FreeRTOS-Plus/Source/WolfSSL/support/wolfssl.pc @@ -5,6 +5,6 @@ includedir=${prefix}/include Name: wolfssl Description: wolfssl C library. -Version: 3.6.0 +Version: 4.4.0 Libs: -L${libdir} -lwolfssl Cflags: -I${includedir} diff --git a/FreeRTOS-Plus/Source/WolfSSL/swig/README b/FreeRTOS-Plus/Source/WolfSSL/swig/README index d71cdb2b5..22f99c368 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/swig/README +++ b/FreeRTOS-Plus/Source/WolfSSL/swig/README @@ -15,6 +15,8 @@ Please send questions to support@wolfssl.com make sudo make install + NOTE: if you want to use pbkdf pkcs #12 algorithm you should build CyaSSL with --enable-pwdbased: + ./configure --disable-shared --enable-pwdbased CFLAGS=-fpic 2) start the example server from the root directory ./examples/server/server -d @@ -33,7 +35,7 @@ Please send questions to support@wolfssl.com directory path because swig doesn't like that 2) Have python for Windows installed, note install directory 3) Have swigwin installed, note install directory -4) Make sure swigwin install direcotry is added to PATH env. variable +4) Make sure swigwin install directory is added to PATH env. variable 5) Make sure env. variables PYTHON_INCLUDE and PYTHON_LIB are set correctly e.g. PYTHON_INCLUE="c:\Python26\include" PYTHON_LIB="c:\Python26\libs\python26.lib" @@ -41,4 +43,3 @@ Please send questions to support@wolfssl.com python library that isn't included by default 7) The outputs _wolfssl.pyd and wolfssl.py are the wolfssl import library 8) Can now run python runme.py from the swig directory - diff --git a/FreeRTOS-Plus/Source/WolfSSL/swig/wolfssl.i b/FreeRTOS-Plus/Source/WolfSSL/swig/wolfssl.i index a03e79cbc..2571cda3f 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/swig/wolfssl.i +++ b/FreeRTOS-Plus/Source/WolfSSL/swig/wolfssl.i @@ -1,8 +1,8 @@ /* wolfssl.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,18 +16,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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + %module wolfssl %{ #include #include + #include /* defn adds */ char* wolfSSL_error_string(int err); int wolfSSL_swig_connect(WOLFSSL*, const char* server, int port); - RNG* GetRng(void); + WC_RNG* GetRng(void); RsaKey* GetRsaPrivateKey(const char* file); void FillSignStr(unsigned char*, const char*, int); %} @@ -44,11 +46,14 @@ int wolfSSL_Init(void); char* wolfSSL_error_string(int); int wolfSSL_swig_connect(WOLFSSL*, const char* server, int port); -int wc_RsaSSL_Sign(const unsigned char* in, int inLen, unsigned char* out, int outLen, RsaKey* key, RNG* rng); +int wc_PKCS12_PBKDF(unsigned char* output, const unsigned char* passwd, int pLen, const unsigned char* salt, + int sLen, int iterations, int kLen, int hashType, int purpose); + +int wc_RsaSSL_Sign(const unsigned char* in, int inLen, unsigned char* out, int outLen, RsaKey* key, WC_RNG* rng); int wc_RsaSSL_Verify(const unsigned char* in, int inLen, unsigned char* out, int outLen, RsaKey* key); -RNG* GetRng(void); +WC_RNG* GetRng(void); RsaKey* GetRsaPrivateKey(const char* file); void FillSignStr(unsigned char*, const char*, int); diff --git a/FreeRTOS-Plus/Source/WolfSSL/swig/wolfssl_adds.c b/FreeRTOS-Plus/Source/WolfSSL/swig/wolfssl_adds.c index e12ccac74..fd055ff80 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/swig/wolfssl_adds.c +++ b/FreeRTOS-Plus/Source/WolfSSL/swig/wolfssl_adds.c @@ -1,8 +1,8 @@ /* wolfssl_adds.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -168,7 +169,8 @@ int wolfSSL_swig_connect(WOLFSSL* ssl, const char* server, int port) int ret = tcp_connect(&sockfd, server, port); if (ret != 0) return ret; - wolfSSL_set_fd(ssl, sockfd); + ret = wolfSSL_set_fd(ssl, sockfd); + if (ret != SSL_SUCCESS) return ret; return wolfSSL_connect(ssl); } @@ -182,9 +184,9 @@ char* wolfSSL_error_string(int err) } -RNG* GetRng(void) +WC_RNG* GetRng(void) { - RNG* rng = (RNG*)malloc(sizeof(RNG)); + WC_RNG* rng = (WC_RNG*)malloc(sizeof(WC_RNG)); if (rng) if (wc_InitRng(rng) != 0) { @@ -205,15 +207,16 @@ RsaKey* GetRsaPrivateKey(const char* keyFile) size_t bytes; int ret; word32 idx = 0; - FILE* file = fopen(keyFile, "rb"); + XFILE file = XFOPEN(keyFile, "rb"); - if (!file) { + if (file == XBADFILE) + { free(key); return 0; } - bytes = fread(tmp, 1, sizeof(tmp), file); - fclose(file); + bytes = XFREAD(tmp, 1, sizeof(tmp), file); + XFCLOSE(file); wc_InitRsaKey(key, 0); ret = wc_RsaPrivateKeyDecode(tmp, &idx, key, (word32)bytes); diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/api.c b/FreeRTOS-Plus/Source/WolfSSL/tests/api.c index 216a9addf..4975981e6 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/tests/api.c +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/api.c @@ -1,8 +1,8 @@ /* api.c API unit tests * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /*----------------------------------------------------------------------------* | Includes *----------------------------------------------------------------------------*/ @@ -28,8 +29,113 @@ #endif #include + +#ifndef FOURK_BUF + #define FOURK_BUF 4096 +#endif +#ifndef TWOK_BUF + #define TWOK_BUF 2048 +#endif +#ifndef ONEK_BUF + #define ONEK_BUF 1024 +#endif +#if defined(WOLFSSL_STATIC_MEMORY) + #include +#endif /* WOLFSSL_STATIC_MEMORY */ +#ifndef HEAP_HINT + #define HEAP_HINT NULL +#endif /* WOLFSSL_STAIC_MEMORY */ +#ifdef WOLFSSL_ASNC_CRYPT + #include +#endif #ifdef HAVE_ECC #include /* wc_ecc_fp_free */ + #ifndef ECC_ASN963_MAX_BUF_SZ + #define ECC_ASN963_MAX_BUF_SZ 133 + #endif + #ifndef ECC_PRIV_KEY_BUF + #define ECC_PRIV_KEY_BUF 66 /* For non user defined curves. */ + #endif + #ifdef HAVE_ALL_CURVES + /* ecc key sizes: 14, 16, 20, 24, 28, 30, 32, 40, 48, 64*/ + #ifndef KEY14 + #define KEY14 14 + #endif + #if !defined(KEY16) + #define KEY16 16 + #endif + #if !defined(KEY20) + #define KEY20 20 + #endif + #if !defined(KEY24) + #define KEY24 24 + #endif + #if !defined(KEY28) + #define KEY28 28 + #endif + #if !defined(KEY30) + #define KEY30 30 + #endif + #if !defined(KEY32) + #define KEY32 32 + #endif + #if !defined(KEY40) + #define KEY40 40 + #endif + #if !defined(KEY48) + #define KEY48 48 + #endif + #if !defined(KEY64) + #define KEY64 64 + #endif + #else + /* ecc key sizes: 14, 16, 20, 24, 28, 30, 32, 40, 48, 64*/ + #ifndef KEY14 + #define KEY14 32 + #endif + #if !defined(KEY16) + #define KEY16 32 + #endif + #if !defined(KEY20) + #define KEY20 32 + #endif + #if !defined(KEY24) + #define KEY24 32 + #endif + #if !defined(KEY28) + #define KEY28 32 + #endif + #if !defined(KEY30) + #define KEY30 32 + #endif + #if !defined(KEY32) + #define KEY32 32 + #endif + #if !defined(KEY40) + #define KEY40 32 + #endif + #if !defined(KEY48) + #define KEY48 32 + #endif + #if !defined(KEY64) + #define KEY64 32 + #endif + #endif + #if !defined(HAVE_COMP_KEY) + #if !defined(NOCOMP) + #define NOCOMP 0 + #endif + #else + #if !defined(COMP) + #define COMP 1 + #endif + #endif + #if !defined(DER_SZ) + #define DER_SZ (keySz * 2 + 1) + #endif +#endif +#ifndef NO_ASN + #include #endif #include @@ -37,6 +143,250 @@ #include /* compatibility layer */ #include #include +#include "examples/server/server.h" + /* for testing compatibility layer callbacks */ + +#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 + +#ifdef WOLFSSL_SHA3 + #include + #ifndef HEAP_HINT + #define HEAP_HINT NULL + #endif +#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 + +#ifdef HAVE_POLY1305 + #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 + +#ifdef HAVE_BLAKE2 + #include +#endif + +#include +#ifndef NO_RSA + #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 + +#ifndef NO_SIG_WRAPPER + #include +#endif + + +#ifdef HAVE_AESCCM + #include +#endif + +#ifdef HAVE_HC128 + #include +#endif + +#ifdef HAVE_PKCS7 + #include + #include +#endif + +#ifdef WOLFSSL_SMALL_CERT_VERIFY + #include +#endif + +#if defined(WOLFSSL_SHA3) || defined(HAVE_PKCS7) || (!defined(NO_RSA) && \ + !defined(NO_SIG_WRAPPER)) + static int devId = INVALID_DEVID; +#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 + #ifndef MAX_DSA_PARAM_SIZE + #define MAX_DSA_PARAM_SIZE 256 + #endif +#endif + +#ifdef WOLFSSL_CMAC + #include +#endif + +#ifdef HAVE_ED25519 + #include +#endif +#ifdef HAVE_CURVE25519 + #include +#endif +#ifdef HAVE_ED448 + #include +#endif +#ifdef HAVE_CURVE448 + #include +#endif + +#ifdef HAVE_PKCS12 + #include +#endif + +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_ALL)) + #include + #ifndef NO_ASN + /* for ASN_COMMON_NAME DN_tags enum */ + #include + #endif + #ifdef HAVE_OCSP + #include + #endif +#endif +#ifdef OPENSSL_EXTRA + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#ifndef NO_AES + #include +#endif +#ifndef NO_DES3 + #include +#endif +#ifdef HAVE_ECC + #include +#endif +#ifdef HAVE_PKCS7 + #include +#endif +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \ + && !defined(NO_SHA256) && !defined(RC_NO_RNG) + #include +#endif + +#if defined(SESSION_CERTS) && defined(TEST_PEER_CERT_CHAIN) +#include "wolfssl/internal.h" /* for testing SSL_get_peer_cert_chain */ +#endif + +/* force enable test buffers */ +#ifndef USE_CERT_BUFFERS_2048 + #define USE_CERT_BUFFERS_2048 +#endif +#ifndef USE_CERT_BUFFERS_256 + #define USE_CERT_BUFFERS_256 +#endif +#include + +typedef struct testVector { + const char* input; + const char* output; + size_t inLen; + size_t outLen; + +} testVector; + +#if defined(HAVE_PKCS7) + typedef struct { + const byte* content; + word32 contentSz; + int contentOID; + int encryptOID; + int keyWrapOID; + int keyAgreeOID; + byte* cert; + size_t certSz; + byte* privateKey; + word32 privateKeySz; + } pkcs7EnvelopedVector; + + #ifndef NO_PKCS7_ENCRYPTED_DATA + typedef struct { + const byte* content; + word32 contentSz; + int contentOID; + int encryptOID; + byte* encryptionKey; + word32 encryptionKeySz; + } pkcs7EncryptedVector; + #endif +#endif /* HAVE_PKCS7 */ + /*----------------------------------------------------------------------------* | Constants @@ -50,9 +400,22 @@ static const char* passed = "passed"; static const char* failed = "failed"; -#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) -static const char* bogusFile = "/dev/null"; -#endif +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ + (!defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)) + static const char* bogusFile = + #ifdef _WIN32 + "NUL" + #else + "/dev/null" + #endif + ; +#endif /* !NO_FILESYSTEM && !NO_CERTS && (!NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT) */ + +enum { + TESTING_RSA = 1, + TESTING_ECC = 2 +}; + /*----------------------------------------------------------------------------* | Setup @@ -64,7 +427,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; } @@ -76,11 +439,69 @@ 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; } + +/* Initialize the wolfCrypt state. + * POST: 0 success. + */ +static int test_wolfCrypt_Init(void) +{ + int result; + + printf(testingFmt, "wolfCrypt_Init()"); + result = wolfCrypt_Init(); + printf(resultFmt, result == 0 ? passed : failed); + + return result; + +} /* END test_wolfCrypt_Init */ + +/*----------------------------------------------------------------------------* + | Platform dependent function test + *----------------------------------------------------------------------------*/ + static int test_fileAccess() +{ +#if defined(WOLFSSL_TEST_PLATFORMDEPEND) && !defined(NO_FILESYSTEM) + const char *fname[] = { + svrCertFile, svrKeyFile, caCertFile, + eccCertFile, eccKeyFile, eccRsaCertFile, + cliCertFile, cliCertDerFile, cliKeyFile, + ntruCertFile, ntruKeyFile, dhParamFile, + cliEccKeyFile, cliEccCertFile, caEccCertFile, edCertFile, edKeyFile, + cliEdCertFile, cliEdKeyFile, caEdCertFile, + NULL + }; + const char derfile[] = "./certs/server-cert.der"; + XFILE f; + size_t sz; + byte *buff; + int i; + + printf(testingFmt, "test_fileAccess()"); + + AssertTrue(XFOPEN("badfilename", "rb") == XBADFILE); + for(i=0; fname[i] != NULL ; i++){ + AssertTrue((f = XFOPEN(fname[i], "rb")) != XBADFILE); + XFCLOSE(f); + } + + AssertTrue((f = XFOPEN(derfile, "rb")) != XBADFILE); + AssertTrue(XFSEEK(f, 0, XSEEK_END) == 0); + sz = (size_t) XFTELL(f); + XREWIND(f); + AssertTrue(sz == sizeof_server_cert_der_2048); + AssertTrue((buff = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)) != NULL) ; + AssertTrue(XFREAD(buff, 1, sz, f) == sz); + XMEMCMP(server_cert_der_2048, buff, sz); + printf(resultFmt, passed); +#endif + return WOLFSSL_SUCCESS; +} + /*----------------------------------------------------------------------------* | Method Allocators *----------------------------------------------------------------------------*/ @@ -101,71 +522,338 @@ static void test_wolfSSL_Method_Allocators(void) TEST_METHOD_ALLOCATOR(a, AssertNull) #ifndef NO_OLD_TLS - TEST_VALID_METHOD_ALLOCATOR(wolfSSLv3_server_method); - TEST_VALID_METHOD_ALLOCATOR(wolfSSLv3_client_method); - TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_server_method); - TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_client_method); - TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_1_server_method); - TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_1_client_method); + #ifdef WOLFSSL_ALLOW_SSLV3 + #ifndef NO_WOLFSSL_SERVER + TEST_VALID_METHOD_ALLOCATOR(wolfSSLv3_server_method); + #endif + #ifndef NO_WOLFSSL_CLIENT + TEST_VALID_METHOD_ALLOCATOR(wolfSSLv3_client_method); + #endif + #endif + #ifdef WOLFSSL_ALLOW_TLSV10 + #ifndef NO_WOLFSSL_SERVER + TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_server_method); + #endif + #ifndef NO_WOLFSSL_CLIENT + TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_client_method); + #endif + #endif + #ifndef NO_WOLFSSL_SERVER + TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_1_server_method); + #endif + #ifndef NO_WOLFSSL_CLIENT + TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_1_client_method); + #endif +#endif /* !NO_OLD_TLS */ + +#ifndef WOLFSSL_NO_TLS12 + #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); + #endif +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifdef WOLFSSL_TLS13 + #ifndef NO_WOLFSSL_SERVER + TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_3_server_method); + #endif + #ifndef NO_WOLFSSL_CLIENT + TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_3_client_method); + #endif +#endif /* WOLFSSL_TLS13 */ + +#ifndef NO_WOLFSSL_SERVER + TEST_VALID_METHOD_ALLOCATOR(wolfSSLv23_server_method); #endif - TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_2_server_method); - TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_2_client_method); +#ifndef NO_WOLFSSL_CLIENT TEST_VALID_METHOD_ALLOCATOR(wolfSSLv23_client_method); +#endif #ifdef WOLFSSL_DTLS #ifndef NO_OLD_TLS + #ifndef NO_WOLFSSL_SERVER TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_server_method); + #endif + #ifndef NO_WOLFSSL_CLIENT TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_client_method); + #endif + #endif + #ifndef WOLFSSL_NO_TLS12 + #ifndef NO_WOLFSSL_SERVER + TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_2_server_method); + #endif + #ifndef NO_WOLFSSL_CLIENT + TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_2_client_method); + #endif + #endif +#endif /* WOLFSSL_DTLS */ + +#if !defined(NO_OLD_TLS) && defined(OPENSSL_EXTRA) + /* Stubs */ + #ifndef NO_WOLFSSL_SERVER + TEST_INVALID_METHOD_ALLOCATOR(wolfSSLv2_server_method); + #endif + #ifndef NO_WOLFSSL_CLIENT + TEST_INVALID_METHOD_ALLOCATOR(wolfSSLv2_client_method); #endif - TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_2_server_method); - TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_2_client_method); #endif -#ifdef OPENSSL_EXTRA - TEST_INVALID_METHOD_ALLOCATOR(wolfSSLv2_server_method); - TEST_INVALID_METHOD_ALLOCATOR(wolfSSLv2_client_method); -#endif + /* Test Either Method (client or server) */ +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + TEST_VALID_METHOD_ALLOCATOR(wolfSSLv23_method); + #ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 + TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_method); + #endif + TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_1_method); + #endif /* !NO_OLD_TLS */ + #ifndef WOLFSSL_NO_TLS12 + TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_2_method); + #endif /* !WOLFSSL_NO_TLS12 */ + #ifdef WOLFSSL_TLS13 + TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_3_method); + #endif /* WOLFSSL_TLS13 */ + #ifdef WOLFSSL_DTLS + TEST_VALID_METHOD_ALLOCATOR(wolfDTLS_method); + #ifndef NO_OLD_TLS + TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_method); + #endif /* !NO_OLD_TLS */ + #ifndef WOLFSSL_NO_TLS12 + TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_2_method); + #endif /* !WOLFSSL_NO_TLS12 */ + #endif /* WOLFSSL_DTLS */ +#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ } + /*----------------------------------------------------------------------------* | Context *----------------------------------------------------------------------------*/ - +#ifndef NO_WOLFSSL_SERVER static void test_wolfSSL_CTX_new(WOLFSSL_METHOD *method) { WOLFSSL_CTX *ctx; - + AssertNull(ctx = wolfSSL_CTX_new(NULL)); - + AssertNotNull(method); AssertNotNull(ctx = wolfSSL_CTX_new(method)); - wolfSSL_CTX_free(ctx); } +#endif + +#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ +(!defined(NO_RSA) || defined(HAVE_ECC)) +static void test_for_double_Free(void) +{ + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + int skipTest = 0; + const char* testCertFile; + const char* testKeyFile; + char optionsCiphers[] = "RC4-SHA:RC4-MD5:DES-CBC3-SHA:AES128-SHA:AES256-SHA" +":NULL-SHA:NULL-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-PSK-AES256-GCM" +"-SHA384:DHE-PSK-AES128-GCM-SHA256:PSK-AES256-GCM-SHA384:PSK-AES128-GCM-SHA256:" +"DHE-PSK-AES256-CBC-SHA384:DHE-PSK-AES128-CBC-SHA256:PSK-AES256-CBC-SHA384:PSK-" +"AES128-CBC-SHA256:PSK-AES128-CBC-SHA:PSK-AES256-CBC-SHA:DHE-PSK-AES128-CCM:DHE" +"-PSK-AES256-CCM:PSK-AES128-CCM:PSK-AES256-CCM:PSK-AES128-CCM-8:PSK-AES256-CCM-" +"8:DHE-PSK-NULL-SHA384:DHE-PSK-NULL-SHA256:PSK-NULL-SHA384:PSK-NULL-SHA256:PSK-" +"NULL-SHA:HC128-MD5:HC128-SHA:RABBIT-SHA:AES128-CCM-8:AES256-CCM-8:ECDHE-ECDSA-" +"AES128-CCM:ECDHE-ECDSA-AES128-CCM-8:ECDHE-ECDSA-AES256-CCM-8:ECDHE-RSA-AES128-" +"SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-R" +"SA-RC4-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-ECDSA-DES-CBC3-SHA" +":AES128-SHA256:AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:ECDH-" +"RSA-AES128-SHA:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES128-SHA:ECDH-ECDSA-AES256-SHA" +":ECDH-RSA-RC4-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-RC4-SHA:ECDH-ECDSA-DES-CBC3" +"-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES" +"256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-E" +"CDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES128-GCM-SHA25" +"6:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-ECDSA-AES256-GC" +"M-SHA384:CAMELLIA128-SHA:DHE-RSA-CAMELLIA128-SHA:CAMELLIA256-SHA:DHE-RSA-CAMEL" +"LIA256-SHA:CAMELLIA128-SHA256:DHE-RSA-CAMELLIA128-SHA256:CAMELLIA256-SHA256:DH" +"E-RSA-CAMELLIA256-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECD" +"H-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-ECD" +"SA-AES256-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDHE-RSA-CHA" +"CHA20-POLY1305:ECDHE-ECDSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-R" +"SA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:DHE-RSA-CHACHA20-PO" +"LY1305-OLD:IDEA-CBC-SHA:ECDHE-ECDSA-NULL-SHA:ECDHE-PSK-NULL-SHA256:ECDHE-PSK-A" +"ES128-CBC-SHA256:PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:DHE-PSK-CHA" +"CHA20-POLY1305:EDH-RSA-DES-CBC3-SHA:TLS13-AES128-GCM-SHA256:TLS13-AES256-GCM-S" +"HA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES128-CCM-SHA256:TLS13-AES128-CCM-" +"8-SHA256:TLS13-SHA256-SHA256:TLS13-SHA384-SHA384"; +#ifndef NO_RSA + testCertFile = svrCertFile; + testKeyFile = svrKeyFile; +#elif defined(HAVE_ECC) + testCertFile = eccCertFile; + testKeyFile = eccKeyFile; +#else + skipTest = 1; +#endif + + if (skipTest != 1) { +#ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#endif + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, WOLFSSL_FILETYPE_PEM)); + + AssertNotNull(ssl = wolfSSL_new(ctx)); + + /* First test freeing SSL, then CTX */ + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + +#ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#endif + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, WOLFSSL_FILETYPE_PEM)); + + AssertNotNull(ssl = wolfSSL_new(ctx)); + + /* Next test freeing CTX then SSL */ + wolfSSL_CTX_free(ctx); + wolfSSL_free(ssl); + +#ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#endif + /* Test setting ciphers at ctx level */ + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_set_cipher_list(ctx, optionsCiphers)); + AssertNotNull(ssl = wolfSSL_new(ctx)); + wolfSSL_CTX_free(ctx); + wolfSSL_free(ssl); + +#ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#endif + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, WOLFSSL_FILETYPE_PEM)); + AssertNotNull(ssl = wolfSSL_new(ctx)); + /* test setting ciphers at SSL level */ + AssertTrue(wolfSSL_set_cipher_list(ssl, optionsCiphers)); + wolfSSL_CTX_free(ctx); + wolfSSL_free(ssl); + } +} +#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)); + AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, bogusFile, + 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); +#endif +} + +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)) && !defined(NO_RSA) +static int test_wolfSSL_CTX_use_certificate_ASN1(void) +{ +#if !defined(NO_CERTS) && !defined(NO_WOLFSSL_SERVER) && !defined(NO_ASN) + WOLFSSL_CTX* ctx; + int ret; + + printf(testingFmt, "wolfSSL_CTX_use_certificate_ASN1()"); + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + + ret = SSL_CTX_use_certificate_ASN1(ctx, sizeof_server_cert_der_2048, + server_cert_der_2048); + + printf(resultFmt, ret == WOLFSSL_SUCCESS ? passed : failed); + wolfSSL_CTX_free(ctx); + + return ret; +#else + return WOLFSSL_SUCCESS; +#endif +} +#endif /* (OPENSSL_ALL || WOLFSSL_ASIO) && !NO_RSA */ + +/* Test function for wolfSSL_CTX_use_certificate_buffer. Load cert into + * context using buffer. + * PRE: NO_CERTS not defined; USE_CERT_BUFFERS_2048 defined; compile with + * --enable-testcert flag. + */ +static int test_wolfSSL_CTX_use_certificate_buffer(void) +{ + #if !defined(NO_CERTS) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_RSA) && !defined(NO_WOLFSSL_SERVER) + WOLFSSL_CTX* ctx; + int ret; + + printf(testingFmt, "wolfSSL_CTX_use_certificate_buffer()"); + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + + ret = wolfSSL_CTX_use_certificate_buffer(ctx, server_cert_der_2048, + sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1); + + printf(resultFmt, ret == WOLFSSL_SUCCESS ? passed : failed); + wolfSSL_CTX_free(ctx); + + return ret; + #else + 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) && !defined(NO_WOLFSSL_SERVER) + WOLFSSL_CTX *ctx; + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + + /* invalid context */ + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(NULL, svrKeyFile, + WOLFSSL_FILETYPE_PEM)); + /* invalid key file */ + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, bogusFile, + WOLFSSL_FILETYPE_PEM)); + /* invalid key type */ + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, 9999)); + + /* success */ +#ifdef NO_RSA + /* rsa needed */ + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); +#else + /* success */ + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); #endif wolfSSL_CTX_free(ctx); @@ -173,31 +861,53 @@ static void test_wolfSSL_CTX_use_certificate_file(void) } -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_FILESYSTEM) && !defined(NO_CERTS) +#if !defined(NO_CERTS) && defined(WOLFSSL_TRUST_PEER_CERT) && \ + !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx; - AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); - /* invalid context */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(NULL, svrKey, - SSL_FILETYPE_PEM)); - /* invalid key file */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, bogusFile, - SSL_FILETYPE_PEM)); - /* invalid key type */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, 9999)); +#if !defined(NO_FILESYSTEM) + /* invalid file */ + assert(wolfSSL_CTX_trust_peer_cert(ctx, NULL, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS); + assert(wolfSSL_CTX_trust_peer_cert(ctx, bogusFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS); + assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, + WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS); /* success */ -#ifdef NO_RSA - /* rsa needed */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); -#else - /* success */ - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, WOLFSSL_FILETYPE_PEM) + == WOLFSSL_SUCCESS); + + /* unload cert */ + 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, + 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, 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, WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS); +#endif + + /* unload cert */ + assert(wolfSSL_CTX_Unload_trust_peers(NULL) != WOLFSSL_SUCCESS); + assert(wolfSSL_CTX_Unload_trust_peers(ctx) == WOLFSSL_SUCCESS); + wolfSSL_CTX_free(ctx); #endif } @@ -205,38 +915,635 @@ static void test_wolfSSL_CTX_use_PrivateKey_file(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; - - AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); - - /* invalid context */ - AssertFalse(wolfSSL_CTX_load_verify_locations(NULL, caCert, 0)); - - /* invalid ca file */ - AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, NULL, 0)); - AssertFalse(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)); */ +#ifndef NO_RSA + WOLFSSL_CERT_MANAGER* cm; +#ifdef PERSIST_CERT_CACHE + int cacheSz; +#endif +#endif +#if !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_TIRTOS) + const char* load_certs_path = "./certs/external"; + const char* load_no_certs_path = "./examples"; + const char* load_expired_path = "./certs/test/expired"; #endif - /* success */ - AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCert, 0)); + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + + /* invalid arguments */ + AssertIntEQ(wolfSSL_CTX_load_verify_locations(NULL, caCertFile, NULL), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, NULL, NULL), WOLFSSL_FAILURE); + + /* invalid ca file */ + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, bogusFile, NULL), WOLFSSL_BAD_FILE); + + +#if !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_TIRTOS) + /* invalid path */ + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, NULL, bogusFile), BAD_PATH_ERROR); +#endif + + /* load ca cert */ +#ifdef NO_RSA + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, NULL), ASN_UNKNOWN_OID_E); +#else /* Skip the following test without RSA certs. */ + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, NULL), WOLFSSL_SUCCESS); + +#ifdef PERSIST_CERT_CACHE + /* Get cert cache size */ + cacheSz = wolfSSL_CTX_get_cert_cache_memsize(ctx); +#endif + /* Test unloading CA's */ + AssertIntEQ(wolfSSL_CTX_UnloadCAs(ctx), WOLFSSL_SUCCESS); + +#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 */ + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, NULL), WOLFSSL_SUCCESS); + + /* Test getting CERT_MANAGER */ + AssertNotNull(cm = wolfSSL_CTX_GetCertManager(ctx)); + + /* Test unloading CA's using CM */ + AssertIntEQ(wolfSSL_CertManagerUnloadCAs(cm), WOLFSSL_SUCCESS); + +#ifdef PERSIST_CERT_CACHE + /* Verify no certs (result is less than cacheSz) */ + AssertIntGT(cacheSz, wolfSSL_CTX_get_cert_cache_memsize(ctx)); +#endif +#endif + +#if !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_TIRTOS) + /* Test loading CA certificates using a path */ + #ifdef NO_RSA + /* failure here okay since certs in external directory are RSA */ + AssertIntNE(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_certs_path, + WOLFSSL_LOAD_FLAG_PEM_CA_ONLY), WOLFSSL_SUCCESS); + #else + AssertIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_certs_path, + WOLFSSL_LOAD_FLAG_PEM_CA_ONLY), WOLFSSL_SUCCESS); + #endif + + /* Test loading path with no files */ + AssertIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_no_certs_path, + WOLFSSL_LOAD_FLAG_PEM_CA_ONLY), WOLFSSL_FAILURE); + + /* Test loading expired CA certificates */ + #ifdef NO_RSA + AssertIntNE(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_expired_path, + WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY | WOLFSSL_LOAD_FLAG_PEM_CA_ONLY), + WOLFSSL_SUCCESS); + #else + AssertIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_expired_path, + WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY | WOLFSSL_LOAD_FLAG_PEM_CA_ONLY), + WOLFSSL_SUCCESS); + #endif + + /* Test loading CA certificates and ignoring all errors */ + #ifdef NO_RSA + AssertIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_certs_path, + WOLFSSL_LOAD_FLAG_IGNORE_ERR), WOLFSSL_FAILURE); + #else + AssertIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_certs_path, + WOLFSSL_LOAD_FLAG_IGNORE_ERR), WOLFSSL_SUCCESS); + #endif +#endif wolfSSL_CTX_free(ctx); #endif } +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) +static int test_cm_load_ca_buffer(const byte* cert_buf, size_t cert_sz, int file_type) +{ + int ret; + WOLFSSL_CERT_MANAGER* cm; + + cm = wolfSSL_CertManagerNew(); + if (cm == NULL) { + printf("test_cm_load_ca failed\n"); + return -1; + } + + ret = wolfSSL_CertManagerLoadCABuffer(cm, cert_buf, cert_sz, file_type); + + wolfSSL_CertManagerFree(cm); + + return ret; +} + +static int test_cm_load_ca_file(const char* ca_cert_file) +{ + int ret = 0; + byte* cert_buf = NULL; + size_t cert_sz = 0; +#if defined(WOLFSSL_PEM_TO_DER) + DerBuffer* pDer = NULL; +#endif + + ret = load_file(ca_cert_file, &cert_buf, &cert_sz); + if (ret == 0) { + /* normal test */ + ret = test_cm_load_ca_buffer(cert_buf, cert_sz, WOLFSSL_FILETYPE_PEM); + + if (ret == 0) { + /* test including null terminator in length */ + ret = test_cm_load_ca_buffer(cert_buf, cert_sz+1, WOLFSSL_FILETYPE_PEM); + } + + #if defined(WOLFSSL_PEM_TO_DER) + if (ret == 0) { + /* test loading DER */ + ret = wc_PemToDer(cert_buf, cert_sz, CA_TYPE, &pDer, NULL, NULL, NULL); + if (ret == 0 && pDer != NULL) { + ret = test_cm_load_ca_buffer(pDer->buffer, pDer->length, + WOLFSSL_FILETYPE_ASN1); + + wc_FreeDer(&pDer); + } + } + #endif + + free(cert_buf); + } + return ret; +} +#endif /* !NO_FILESYSTEM && !NO_CERTS */ + +static int test_wolfSSL_CertManagerLoadCABuffer(void) +{ + int ret = 0; + +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) + const char* ca_cert = "./certs/ca-cert.pem"; + const char* ca_expired_cert = "./certs/test/expired/expired-ca.pem"; + + ret = test_cm_load_ca_file(ca_cert); + #ifdef NO_RSA + AssertIntEQ(ret, ASN_UNKNOWN_OID_E); + #else + AssertIntEQ(ret, WOLFSSL_SUCCESS); + #endif + + ret = test_cm_load_ca_file(ca_expired_cert); + #ifdef NO_RSA + AssertIntEQ(ret, ASN_UNKNOWN_OID_E); + #else + AssertIntEQ(ret, ASN_AFTER_DATE_E); + #endif +#endif + + return ret; +} + +static void test_wolfSSL_CertManagerGetCerts(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \ + defined(WOLFSSL_SIGNER_DER_CERT) + + WOLFSSL_CERT_MANAGER* cm = NULL; + WOLFSSL_STACK* sk = NULL; + X509* x509 = NULL; + X509* cert1 = NULL; + FILE* file1 = NULL; +#ifdef DEBUG_WOLFSSL_VERBOSE + WOLFSSL_BIO* bio = NULL; +#endif + int i = 0; + + printf(testingFmt, "wolfSSL_CertManagerGetCerts()"); + AssertNotNull(file1=fopen("./certs/ca-cert.pem", "rb")); + + AssertNotNull(cert1 = wolfSSL_PEM_read_X509(file1, NULL, NULL, NULL)); + fclose(file1); + + AssertNotNull(cm = wolfSSL_CertManagerNew_ex(NULL)); + AssertNull(sk = wolfSSL_CertManagerGetCerts(cm)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCA(cm, + "./certs/ca-cert.pem", NULL)); + + AssertNotNull(sk = wolfSSL_CertManagerGetCerts(cm)); + + for (i = 0; i < sk_X509_num(sk); i++) { + x509 = sk_X509_value(sk, i); + AssertIntEQ(0, wolfSSL_X509_cmp(x509, cert1)); + +#ifdef DEBUG_WOLFSSL_VERBOSE + bio = BIO_new(wolfSSL_BIO_s_file()); + if (bio != NULL) { + BIO_set_fp(bio, stdout, BIO_NOCLOSE); + X509_print(bio, x509); + BIO_free(bio); + } +#endif /* DEBUG_WOLFSSL_VERBOSE */ + } + wolfSSL_X509_free(cert1); + sk_X509_free(sk); + wolfSSL_CertManagerFree(cm); + printf(resultFmt, passed); +#endif /* defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \ + defined(WOLFSSL_SIGNER_DER_CERT) */ +} + +static int test_wolfSSL_CertManagerSetVerify(void) +{ + int ret = 0; +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ + !defined(NO_WOLFSSL_CM_VERIFY) && !defined(NO_RSA) + WOLFSSL_CERT_MANAGER* cm; + int tmp = myVerifyFail; + const char* ca_cert = "./certs/ca-cert.pem"; + const char* expiredCert = "./certs/test/expired/expired-cert.pem"; + + cm = wolfSSL_CertManagerNew(); + AssertNotNull(cm); + + wolfSSL_CertManagerSetVerify(cm, myVerify); + + ret = wolfSSL_CertManagerLoadCA(cm, ca_cert, NULL); + AssertIntEQ(ret, WOLFSSL_SUCCESS); + + /* Use the test CB that always accepts certs */ + myVerifyFail = 0; + + ret = wolfSSL_CertManagerVerify(cm, expiredCert, WOLFSSL_FILETYPE_PEM); + AssertIntEQ(ret, WOLFSSL_SUCCESS); + +#ifdef WOLFSSL_ALWAYS_VERIFY_CB + { + const char* verifyCert = "./certs/server-cert.pem"; + /* Use the test CB that always fails certs */ + myVerifyFail = 1; + + ret = wolfSSL_CertManagerVerify(cm, verifyCert, WOLFSSL_FILETYPE_PEM); + AssertIntEQ(ret, VERIFY_CERT_ERROR); + } +#endif + + wolfSSL_CertManagerFree(cm); + myVerifyFail = tmp; +#endif + + return ret; +} + +static void test_wolfSSL_CertManagerCRL(void) +{ +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && defined(HAVE_CRL) && \ + !defined(NO_RSA) + + const char* ca_cert = "./certs/ca-cert.pem"; + const char* crl1 = "./certs/crl/crl.pem"; + const char* crl2 = "./certs/crl/crl2.pem"; + + WOLFSSL_CERT_MANAGER* cm = NULL; + + AssertNotNull(cm = wolfSSL_CertManagerNew()); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CertManagerLoadCA(cm, ca_cert, NULL)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CertManagerLoadCRL(cm, crl1, WOLFSSL_FILETYPE_PEM, 0)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CertManagerLoadCRL(cm, crl2, WOLFSSL_FILETYPE_PEM, 0)); + wolfSSL_CertManagerFreeCRL(cm); + + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CertManagerLoadCRL(cm, crl1, WOLFSSL_FILETYPE_PEM, 0)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CertManagerLoadCA(cm, ca_cert, NULL)); + wolfSSL_CertManagerFree(cm); + +#endif +} + +static void test_wolfSSL_CTX_load_verify_locations_ex(void) +{ +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) && \ + !defined(NO_WOLFSSL_CLIENT) + WOLFSSL_CTX* ctx; + const char* ca_cert = "./certs/ca-cert.pem"; + const char* ca_expired_cert = "./certs/test/expired/expired-ca.pem"; + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + + /* test good CA */ + AssertTrue(WOLFSSL_SUCCESS == + wolfSSL_CTX_load_verify_locations_ex(ctx, ca_cert, NULL, + WOLFSSL_LOAD_FLAG_NONE)); + + /* test expired CA */ + AssertTrue(WOLFSSL_SUCCESS != + wolfSSL_CTX_load_verify_locations_ex(ctx, ca_expired_cert, NULL, + WOLFSSL_LOAD_FLAG_NONE)); + AssertTrue(WOLFSSL_SUCCESS == + wolfSSL_CTX_load_verify_locations_ex(ctx, ca_expired_cert, NULL, + WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY)); + + wolfSSL_CTX_free(ctx); + +#endif +} + +static void test_wolfSSL_CTX_load_verify_buffer_ex(void) +{ +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) && \ + defined(USE_CERT_BUFFERS_2048) + WOLFSSL_CTX* ctx; + const char* ca_expired_cert_file = "./certs/test/expired/expired-ca.der"; + byte ca_expired_cert[TWOK_BUF]; + word32 sizeof_ca_expired_cert; + XFILE fp; + +#ifndef NO_WOLFSSL_CLIENT + ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); +#else + ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()); +#endif + AssertNotNull(ctx); + + /* test good CA */ + AssertTrue(WOLFSSL_SUCCESS == + wolfSSL_CTX_load_verify_buffer_ex(ctx, ca_cert_der_2048, + sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1, 0, + WOLFSSL_LOAD_FLAG_NONE)); + + /* load expired CA */ + XMEMSET(ca_expired_cert, 0, sizeof(ca_expired_cert)); + fp = XFOPEN(ca_expired_cert_file, "rb"); + AssertTrue(fp != XBADFILE); + sizeof_ca_expired_cert = (word32)XFREAD(ca_expired_cert, 1, + sizeof(ca_expired_cert), fp); + XFCLOSE(fp); + + /* test expired CA failure */ + AssertTrue(WOLFSSL_SUCCESS != + wolfSSL_CTX_load_verify_buffer_ex(ctx, ca_expired_cert, + sizeof_ca_expired_cert, WOLFSSL_FILETYPE_ASN1, 0, + WOLFSSL_LOAD_FLAG_NONE)); + + /* test expired CA success */ + AssertTrue(WOLFSSL_SUCCESS == + wolfSSL_CTX_load_verify_buffer_ex(ctx, ca_expired_cert, + sizeof_ca_expired_cert, WOLFSSL_FILETYPE_ASN1, 0, + WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY)); + + wolfSSL_CTX_free(ctx); + +#endif +} + +static void test_wolfSSL_CTX_load_verify_chain_buffer_format(void) +{ +#if !defined(NO_CERTS) && !defined(NO_RSA) && defined(OPENSSL_EXTRA) && \ + defined(WOLFSSL_CERT_GEN) && defined(USE_CERT_BUFFERS_2048) + WOLFSSL_CTX* ctx; + + #ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + #else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + #endif + + AssertTrue(WOLFSSL_SUCCESS == + wolfSSL_CTX_load_verify_chain_buffer_format(ctx, ca_cert_chain_der, + sizeof_ca_cert_chain_der, + WOLFSSL_FILETYPE_ASN1)); + + wolfSSL_CTX_free(ctx); +#endif +} + +static int test_wolfSSL_CTX_use_certificate_chain_file_format(void) +{ + int ret = 0; +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) + const char* server_chain_der = "./certs/server-cert-chain.der"; + WOLFSSL_CTX* ctx; + + #ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + #else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + #endif + + AssertIntEQ(wolfSSL_CTX_use_certificate_chain_file_format(ctx, + server_chain_der, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + wolfSSL_CTX_free(ctx); +#endif + return ret; +} + +static void test_wolfSSL_CTX_SetTmpDH_file(void) +{ +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_DH) + WOLFSSL_CTX *ctx; + + #ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + #else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + #endif + + /* invalid context */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(NULL, + dhParamFile, WOLFSSL_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(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dhParamFile, + WOLFSSL_FILETYPE_PEM)); + + wolfSSL_CTX_free(ctx); +#endif +} + +static void test_wolfSSL_CTX_SetTmpDH_buffer(void) +{ +#if !defined(NO_CERTS) && !defined(NO_DH) + WOLFSSL_CTX *ctx; + + #ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + #else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + #endif + + /* invalid context */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(NULL, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_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(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + + wolfSSL_CTX_free(ctx); +#endif +} + +static void test_wolfSSL_CTX_SetMinMaxDhKey_Sz(void) +{ +#if !defined(NO_CERTS) && !defined(NO_DH) + WOLFSSL_CTX *ctx; + + #ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + #else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + #endif + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetMinDhKey_Sz(ctx, 3072)); + + AssertIntEQ(DH_KEY_SIZE_E, wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetMinDhKey_Sz(ctx, 2048)); + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetMaxDhKey_Sz(ctx, 1024)); + + AssertIntEQ(DH_KEY_SIZE_E, wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetMaxDhKey_Sz(ctx, 2048)); + + 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 +} + +static void test_wolfSSL_CTX_der_load_verify_locations(void) +{ +#ifdef WOLFSSL_DER_LOAD + WOLFSSL_CTX* ctx = NULL; + const char* derCert = "./certs/server-cert.der"; + const char* nullPath = NULL; + const char* invalidPath = "./certs/this-cert-does-not-exist.der"; + const char* emptyPath = ""; + + /* der load Case 1 ctx NULL */ + AssertIntEQ(wolfSSL_CTX_der_load_verify_locations(ctx, derCert, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_FAILURE); + + #ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + #else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + #endif + + /* Case 2 filePath NULL */ + AssertIntEQ(wolfSSL_CTX_der_load_verify_locations(ctx, nullPath, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_FAILURE); + /* Case 3 invalid format */ + AssertIntEQ(wolfSSL_CTX_der_load_verify_locations(ctx, derCert, + WOLFSSL_FILETYPE_PEM), WOLFSSL_FAILURE); + /* Case 4 filePath not valid */ + AssertIntEQ(wolfSSL_CTX_der_load_verify_locations(ctx, invalidPath, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_FAILURE); + /* Case 5 filePath empty */ + AssertIntEQ(wolfSSL_CTX_der_load_verify_locations(ctx, emptyPath, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_FAILURE); +#ifndef NO_RSA + /* Case 6 success case */ + AssertIntEQ(wolfSSL_CTX_der_load_verify_locations(ctx, derCert, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); +#endif + + wolfSSL_CTX_free(ctx); +#endif +} + +static void test_wolfSSL_CTX_enable_disable(void) +{ +#ifndef NO_CERTS + WOLFSSL_CTX* ctx = NULL; + + #ifdef HAVE_CRL + AssertIntEQ(wolfSSL_CTX_DisableCRL(ctx), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_EnableCRL(ctx, 0), BAD_FUNC_ARG); + #endif + + #ifdef HAVE_OCSP + AssertIntEQ(wolfSSL_CTX_DisableOCSP(ctx), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_EnableOCSP(ctx, 0), BAD_FUNC_ARG); + #endif + + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ + defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + AssertIntEQ(wolfSSL_CTX_DisableOCSPStapling(ctx), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), BAD_FUNC_ARG); + #endif + + #ifndef NO_WOLFSSL_CLIENT + + #ifdef HAVE_EXTENDED_MASTER + AssertIntEQ(wolfSSL_CTX_DisableExtendedMasterSecret(ctx), BAD_FUNC_ARG); + #endif + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + + #ifdef HAVE_EXTENDED_MASTER + AssertIntEQ(wolfSSL_CTX_DisableExtendedMasterSecret(ctx), WOLFSSL_SUCCESS); + #endif + + #elif !defined(NO_WOLFSSL_SERVER) + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + #else + return; + #endif + + #ifdef HAVE_CRL + AssertIntEQ(wolfSSL_CTX_DisableCRL(ctx), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_EnableCRL(ctx, 0), WOLFSSL_SUCCESS); + #endif + + #ifdef HAVE_OCSP + AssertIntEQ(wolfSSL_CTX_DisableOCSP(ctx), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_URL_OVERRIDE), + WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE), + WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_CHECKALL), + WOLFSSL_SUCCESS); + #endif + + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ + defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + AssertIntEQ(wolfSSL_CTX_DisableOCSPStapling(ctx), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), WOLFSSL_SUCCESS); + #endif + wolfSSL_CTX_free(ctx); +#endif /* NO_CERTS */ +} /*----------------------------------------------------------------------------* | SSL *----------------------------------------------------------------------------*/ 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; @@ -244,12 +1551,14 @@ 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)); +#ifndef WOLFSSL_SESSION_EXPORT AssertNull(ssl = wolfSSL_new(ctx_nocert)); +#endif /* success */ AssertNotNull(ssl = wolfSSL_new(ctx)); @@ -263,7 +1572,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; @@ -271,120 +1581,885 @@ 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)); /* success */ AssertNotNull(ssl = wolfSSL_new(ctx_nocert)); wolfSSL_free(ssl); - + /* success */ AssertNotNull(ssl = wolfSSL_new(ctx)); wolfSSL_free(ssl); - + wolfSSL_CTX_free(ctx); wolfSSL_CTX_free(ctx_nocert); #endif } +static void test_wolfSSL_SetTmpDH_file(void) +{ +#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, svrCertFile, + WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, + WOLFSSL_FILETYPE_PEM)); +#elif defined(HAVE_ECC) + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, eccCertFile, + WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, eccKeyFile, + WOLFSSL_FILETYPE_PEM)); +#elif defined(HAVE_ED25519) + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, edCertFile, + WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, edKeyFile, + WOLFSSL_FILETYPE_PEM)); +#elif defined(HAVE_ED448) + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, ed448CertFile, + WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, ed448KeyFile, + WOLFSSL_FILETYPE_PEM)); +#endif + AssertNotNull(ssl = wolfSSL_new(ctx)); + + /* invalid ssl */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_file(NULL, + dhParamFile, WOLFSSL_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(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, dhParamFile, + WOLFSSL_FILETYPE_PEM)); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif +} + +static void test_wolfSSL_SetTmpDH_buffer(void) +{ +#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, WOLFSSL_FILETYPE_ASN1)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_buffer(ctx, server_key_der_2048, + sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + AssertNotNull(ssl = wolfSSL_new(ctx)); + + /* invalid ssl */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(NULL, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_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(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); +#endif +} + +static void test_wolfSSL_SetMinMaxDhKey_Sz(void) +{ +#if !defined(NO_CERTS) && !defined(NO_DH) && !defined(NO_WOLFSSL_SERVER) + WOLFSSL_CTX *ctx, *ctx2; + WOLFSSL *ssl, *ssl2; + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + AssertTrue(wolfSSL_CTX_use_certificate_buffer(ctx, server_cert_der_2048, + sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_buffer(ctx, server_key_der_2048, + sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetMinDhKey_Sz(ctx, 3072)); + AssertNotNull(ssl = wolfSSL_new(ctx)); + AssertNotNull(ctx2 = wolfSSL_CTX_new(wolfSSLv23_server_method())); + AssertTrue(wolfSSL_CTX_use_certificate_buffer(ctx2, server_cert_der_2048, + sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_buffer(ctx2, server_key_der_2048, + sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetMaxDhKey_Sz(ctx, 1024)); + AssertNotNull(ssl2 = wolfSSL_new(ctx2)); + + AssertIntEQ(DH_KEY_SIZE_E, wolfSSL_SetTmpDH_buffer(ssl, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetMinDhKey_Sz(ssl, 2048)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetMinDhKey_Sz(ssl, 3072)); + AssertIntEQ(DH_KEY_SIZE_E, wolfSSL_SetTmpDH_buffer(ssl, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl2, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetMaxDhKey_Sz(ssl2, 2048)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl2, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetMaxDhKey_Sz(ssl2, 1024)); + AssertIntEQ(DH_KEY_SIZE_E, wolfSSL_SetTmpDH_buffer(ssl, dh_key_der_2048, + sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); + + wolfSSL_free(ssl2); + wolfSSL_CTX_free(ctx2); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif +} + + +/* Test function for wolfSSL_SetMinVersion. Sets the minimum downgrade version + * 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 itr; + + #ifndef NO_OLD_TLS + const int versions[] = { + #ifdef WOLFSSL_ALLOW_TLSV10 + WOLFSSL_TLSV1, + #endif + WOLFSSL_TLSV1_1, + WOLFSSL_TLSV1_2}; + #elif !defined(WOLFSSL_NO_TLS12) + const int versions[] = { WOLFSSL_TLSV1_2 }; + #else + const int versions[] = { WOLFSSL_TLSV1_3 }; + #endif + + ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + ssl = wolfSSL_new(ctx); + + printf(testingFmt, "wolfSSL_SetMinVersion()"); + + for (itr = 0; itr < (int)(sizeof(versions)/sizeof(int)); itr++){ + if(wolfSSL_SetMinVersion(ssl, *(versions + itr)) != WOLFSSL_SUCCESS){ + failFlag = WOLFSSL_FAILURE; + } + } + + printf(resultFmt, failFlag == WOLFSSL_SUCCESS ? passed : failed); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#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, EC_GROUP_order_bits + */ + +# if defined(OPENSSL_EXTRA) +static void test_wolfSSL_EC(void) +{ +#if defined(HAVE_ECC) && defined(ECC_SHAMIR) + BN_CTX *ctx; + EC_GROUP *group; + EC_POINT *Gxy, *new_point, *set_point; + BIGNUM *k = NULL, *Gx = NULL, *Gy = NULL, *Gz = NULL; + BIGNUM *X, *Y; + BIGNUM *set_point_bn; + char* hexStr; + int group_bits; + + const char* kTest = "F4F8338AFCC562C5C3F3E1E46A7EFECD17AF381913FF7A96314EA47055EA0FD0"; + /* NISTP256R1 Gx/Gy */ + const char* kGx = "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"; + const char* kGy = "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"; + +#ifndef HAVE_SELFTEST + EC_POINT *tmp; + size_t bin_len; + unsigned char* buf = NULL; + + const char* uncompG = "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"; + const unsigned char binUncompG[] = { + 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, + 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, + 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, + 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, + 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, + 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, + }; + +#ifdef HAVE_COMP_KEY + const char* compG = "036B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"; + const unsigned char binCompG[] = { + 0x03, 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, + }; +#endif +#endif + + AssertNotNull(ctx = BN_CTX_new()); + AssertNotNull(group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); + AssertIntEQ((group_bits = EC_GROUP_order_bits(group)), 256); + AssertNotNull(Gxy = EC_POINT_new(group)); + AssertNotNull(new_point = EC_POINT_new(group)); + AssertNotNull(set_point = EC_POINT_new(group)); + AssertNotNull(X = BN_new()); + AssertNotNull(Y = BN_new()); + AssertNotNull(set_point_bn = 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; + +#ifndef HAVE_SELFTEST + /* perform point multiplication */ + AssertIntEQ(EC_POINT_mul(group, new_point, Gx, Gxy, k, ctx), WOLFSSL_SUCCESS); + AssertIntEQ(EC_POINT_mul(group, new_point, NULL, Gxy, k, ctx), WOLFSSL_SUCCESS); + AssertIntEQ(EC_POINT_mul(group, new_point, Gx, NULL, NULL, ctx), WOLFSSL_SUCCESS); +#else + AssertIntEQ(EC_POINT_set_affine_coordinates_GFp(group, new_point, Gx, Gy, ctx), WOLFSSL_SUCCESS); +#endif + + /* check if point X coordinate is zero */ + AssertIntEQ(BN_is_zero(new_point->X), 0); + + /* Force non-affine coordinates */ + AssertIntEQ(BN_add(new_point->Z, (WOLFSSL_BIGNUM*)BN_value_one(), + (WOLFSSL_BIGNUM*)BN_value_one()), 1); + new_point->inSet = 0; + + /* 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); + + /* set the same X and Y points in another object */ + AssertIntEQ(EC_POINT_set_affine_coordinates_GFp(group, set_point, X, Y, ctx), WOLFSSL_SUCCESS); + + /* compare points as they should be the same */ + AssertIntEQ(EC_POINT_cmp(group, new_point, set_point, ctx), 0); + + /* Test copying */ + AssertIntEQ(EC_POINT_copy(new_point, set_point), 1); + + AssertPtrEq(EC_POINT_point2bn(group, set_point, POINT_CONVERSION_UNCOMPRESSED, + set_point_bn, ctx), set_point_bn); + + /* check bn2hex */ + hexStr = BN_bn2hex(k); + AssertStrEQ(hexStr, kTest); +#ifndef NO_FILESYSTEM + BN_print_fp(stdout, k); + printf("\n"); +#endif + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); + + hexStr = BN_bn2hex(Gx); + AssertStrEQ(hexStr, kGx); +#ifndef NO_FILESYSTEM + BN_print_fp(stdout, Gx); + printf("\n"); +#endif + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); + + hexStr = BN_bn2hex(Gy); + AssertStrEQ(hexStr, kGy); +#ifndef NO_FILESYSTEM + BN_print_fp(stdout, Gy); + printf("\n"); +#endif + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); + +#ifndef HAVE_SELFTEST + hexStr = EC_POINT_point2hex(group, Gxy, POINT_CONVERSION_UNCOMPRESSED, ctx); + AssertStrEQ(hexStr, uncompG); + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); + +#ifdef HAVE_COMP_KEY + hexStr = EC_POINT_point2hex(group, Gxy, POINT_CONVERSION_COMPRESSED, ctx); + AssertStrEQ(hexStr, compG); + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); +#endif + + bin_len = EC_POINT_point2oct(group, Gxy, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, ctx); + AssertIntEQ(bin_len, sizeof(binUncompG)); + AssertNotNull(buf = (unsigned char*)XMALLOC(bin_len, NULL, DYNAMIC_TYPE_ECC)); + AssertIntEQ(EC_POINT_point2oct(group, Gxy, POINT_CONVERSION_UNCOMPRESSED, buf, + bin_len, ctx), bin_len); + AssertIntEQ(XMEMCMP(buf, binUncompG, sizeof(binUncompG)), 0); + XFREE(buf, NULL, DYNAMIC_TYPE_ECC); + +#ifdef HAVE_COMP_KEY + bin_len = EC_POINT_point2oct(group, Gxy, POINT_CONVERSION_COMPRESSED, NULL, 0, ctx); + AssertIntEQ(bin_len, sizeof(binCompG)); + AssertNotNull(buf = (unsigned char*)XMALLOC(bin_len, NULL, DYNAMIC_TYPE_ECC)); + AssertIntEQ(EC_POINT_point2oct(group, Gxy, POINT_CONVERSION_COMPRESSED, buf, + bin_len, ctx), bin_len); + AssertIntEQ(XMEMCMP(buf, binCompG, sizeof(binCompG)), 0); + XFREE(buf, NULL, DYNAMIC_TYPE_ECC); +#endif + + AssertNotNull(tmp = EC_POINT_new(group)); + AssertIntEQ(EC_POINT_oct2point(group, tmp, binUncompG, sizeof(binUncompG), ctx), 1); + AssertIntEQ(EC_POINT_cmp(group, tmp, Gxy, ctx), 0); + EC_POINT_free(tmp); + +#ifdef HAVE_COMP_KEY + AssertNotNull(tmp = EC_POINT_new(group)); + AssertIntEQ(EC_POINT_oct2point(group, tmp, binCompG, sizeof(binCompG), ctx), 1); + AssertIntEQ(EC_POINT_cmp(group, tmp, Gxy, ctx), 0); + EC_POINT_free(tmp); +#endif +#endif + + /* test BN_mod_add */ + AssertIntEQ(BN_mod_add(new_point->Z, (WOLFSSL_BIGNUM*)BN_value_one(), + (WOLFSSL_BIGNUM*)BN_value_one(), + (WOLFSSL_BIGNUM*)BN_value_one(), NULL), 1); + AssertIntEQ(BN_is_zero(new_point->Z), 1); + /* cleanup */ + BN_free(X); + BN_free(Y); + BN_free(k); + BN_free(set_point_bn); + EC_POINT_free(new_point); + EC_POINT_free(set_point); + EC_POINT_free(Gxy); + EC_GROUP_free(group); + BN_CTX_free(ctx); +#endif /* HAVE_ECC */ +} +#endif + +static void test_wolfSSL_PEM_read_bio_ECPKParameters(void) +{ +#if defined(HAVE_ECC) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) + EC_GROUP *group; + BIO* bio; + + AssertNotNull(bio = BIO_new(BIO_s_file())); + AssertIntEQ(BIO_read_filename(bio, eccKeyFile), WOLFSSL_SUCCESS); + AssertNotNull(group = PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL)); + AssertIntEQ(EC_GROUP_get_curve_name(group), NID_X9_62_prime256v1); + EC_GROUP_free(group); + BIO_free(bio); +#endif /* HAVE_ECC */ +} + +# if defined(OPENSSL_EXTRA) +static void test_wolfSSL_ECDSA_SIG(void) +{ +#ifdef HAVE_ECC + WOLFSSL_ECDSA_SIG* sig = NULL; + WOLFSSL_ECDSA_SIG* sig2 = NULL; + const unsigned char* cp; + unsigned char* p; + unsigned char outSig[8]; + unsigned char sigData[8] = + { 0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01 }; + + AssertNull(wolfSSL_d2i_ECDSA_SIG(NULL, NULL, sizeof(sigData))); + cp = sigData; + AssertNotNull((sig = wolfSSL_d2i_ECDSA_SIG(NULL, &cp, sizeof(sigData)))); + AssertIntEQ((cp == sigData + 8), 1); + cp = sigData; + AssertNull(wolfSSL_d2i_ECDSA_SIG(&sig, NULL, sizeof(sigData))); + AssertNotNull((sig2 = wolfSSL_d2i_ECDSA_SIG(&sig, &cp, sizeof(sigData)))); + AssertIntEQ((sig == sig2), 1); + cp = outSig; + + p = outSig; + AssertIntEQ(wolfSSL_i2d_ECDSA_SIG(NULL, &p), 0); + AssertIntEQ(wolfSSL_i2d_ECDSA_SIG(NULL, NULL), 0); + AssertIntEQ(wolfSSL_i2d_ECDSA_SIG(sig, NULL), 8); + AssertIntEQ(wolfSSL_i2d_ECDSA_SIG(sig, &p), sizeof(sigData)); + AssertIntEQ((p == outSig + 8), 1); + AssertIntEQ(XMEMCMP(sigData, outSig, 8), 0); + + wolfSSL_ECDSA_SIG_free(sig); +#endif /* HAVE_ECC */ +} + +static void test_ECDSA_size_sign(void) +{ +#if defined(HAVE_ECC) && !defined(NO_ECC256) && !defined(NO_ECC_SECP) + EC_KEY *key; + int id; + byte hash[WC_MAX_DIGEST_SIZE]; + byte sig[ECC_BUFSIZE]; + unsigned int sigSz = sizeof(sig); + + + XMEMSET(hash, 123, sizeof(hash)); + + id = wc_ecc_get_curve_id_from_name("SECP256R1"); + AssertIntEQ(id, ECC_SECP256R1); + + AssertNotNull(key = wolfSSL_EC_KEY_new_by_curve_name(id)); + AssertIntEQ(EC_KEY_generate_key(key), 1); + AssertIntEQ(ECDSA_sign(0, hash, sizeof(hash), sig, &sigSz, key), 1); + AssertIntGE(ECDSA_size(key), sigSz); + EC_KEY_free(key); + +#endif /* HAVE_ECC && !NO_ECC256 && !NO_ECC_SECP */ +} +#endif /* OPENSSL_EXTRA */ + +#include +/*----------------------------------------------------------------------------* + | EVP + *----------------------------------------------------------------------------*/ + +/* Test function for wolfSSL_EVP_get_cipherbynid. + */ + +#ifdef OPENSSL_EXTRA +static void test_wolfSSL_EVP_get_cipherbynid(void) +{ +#ifndef NO_AES + const WOLFSSL_EVP_CIPHER* c; + + c = wolfSSL_EVP_get_cipherbynid(419); + #if defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) + AssertNotNull(c); + AssertNotNull(strcmp("EVP_AES_128_CBC", c)); + #else + AssertNull(c); + #endif + + c = wolfSSL_EVP_get_cipherbynid(423); + #if defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192) + AssertNotNull(c); + AssertNotNull(strcmp("EVP_AES_192_CBC", c)); + #else + AssertNull(c); + #endif + + c = wolfSSL_EVP_get_cipherbynid(427); + #if defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) + AssertNotNull(c); + AssertNotNull(strcmp("EVP_AES_256_CBC", c)); + #else + AssertNull(c); + #endif + + c = wolfSSL_EVP_get_cipherbynid(904); + #if defined(WOLFSSL_AES_COUNTER) && defined(WOLFSSL_AES_128) + AssertNotNull(c); + AssertNotNull(strcmp("EVP_AES_128_CTR", c)); + #else + AssertNull(c); + #endif + + c = wolfSSL_EVP_get_cipherbynid(905); + #if defined(WOLFSSL_AES_COUNTER) && defined(WOLFSSL_AES_192) + AssertNotNull(c); + AssertNotNull(strcmp("EVP_AES_192_CTR", c)); + #else + AssertNull(c); + #endif + + c = wolfSSL_EVP_get_cipherbynid(906); + #if defined(WOLFSSL_AES_COUNTER) && defined(WOLFSSL_AES_256) + AssertNotNull(c); + AssertNotNull(strcmp("EVP_AES_256_CTR", c)); + #else + AssertNull(c); + #endif + + c = wolfSSL_EVP_get_cipherbynid(418); + #if defined(HAVE_AES_ECB) && defined(WOLFSSL_AES_128) + AssertNotNull(c); + AssertNotNull(strcmp("EVP_AES_128_ECB", c)); + #else + AssertNull(c); + #endif + + c = wolfSSL_EVP_get_cipherbynid(422); + #if defined(HAVE_AES_ECB) && defined(WOLFSSL_AES_192) + AssertNotNull(c); + AssertNotNull(strcmp("EVP_AES_192_ECB", c)); + #else + AssertNull(c); + #endif + + c = wolfSSL_EVP_get_cipherbynid(426); + #if defined(HAVE_AES_ECB) && defined(WOLFSSL_AES_256) + AssertNotNull(c); + AssertNotNull(strcmp("EVP_AES_256_ECB", c)); + #else + AssertNull(c); + #endif +#endif /* !NO_AES */ + +#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)); + +} + +static void test_wolfSSL_EVP_CIPHER_CTX() +{ +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + const EVP_CIPHER *init = EVP_aes_128_cbc(); + const EVP_CIPHER *test; + byte key[AES_BLOCK_SIZE] = {0}; + byte iv[AES_BLOCK_SIZE] = {0}; + + AssertNotNull(ctx); + wolfSSL_EVP_CIPHER_CTX_init(ctx); + AssertIntEQ(EVP_CipherInit(ctx, init, key, iv, 1), WOLFSSL_SUCCESS); + test = EVP_CIPHER_CTX_cipher(ctx); + AssertTrue(init == test); + AssertIntEQ(EVP_CIPHER_nid(test), NID_aes_128_cbc); + + AssertIntEQ(EVP_CIPHER_CTX_reset(ctx), WOLFSSL_SUCCESS); + AssertIntEQ(EVP_CIPHER_CTX_reset(NULL), WOLFSSL_FAILURE); + + EVP_CIPHER_CTX_free(ctx); +#endif /* !NO_AES && HAVE_AES_CBC && WOLFSSL_AES_128 */ +} +#endif /* OPENSSL_EXTRA */ + /*----------------------------------------------------------------------------* | 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 /* helper functions */ #ifdef HAVE_IO_TESTS_DEPENDENCIES + +#ifdef WOLFSSL_SESSION_EXPORT +/* set up function for sending session information */ +static int test_export(WOLFSSL* inSsl, byte* buf, word32 sz, void* userCtx) +{ + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + + AssertNotNull(inSsl); + AssertNotNull(buf); + AssertIntNE(0, sz); + + /* Set ctx to DTLS 1.2 */ + ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method()); + AssertNotNull(ctx); + + ssl = wolfSSL_new(ctx); + AssertNotNull(ssl); + + AssertIntGE(wolfSSL_dtls_import(ssl, buf, sz), 0); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + (void)userCtx; + return WOLFSSL_SUCCESS; +} + +/* returns negative value on fail and positive (including 0) on success */ +static int nonblocking_accept_read(void* args, WOLFSSL* ssl, SOCKET_T* sockfd) +{ + int ret, err, loop_count, count, timeout = 10; + char msg[] = "I hear you fa shizzle!"; + char input[1024]; + + loop_count = ((func_args*)args)->argc; + 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 = wolfSSL_accept(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + if (err == WOLFSSL_ERROR_WANT_READ || + err == WOLFSSL_ERROR_WANT_WRITE) { + int select_ret; + + err = WC_PENDING_E; + select_ret = tcp_select(*sockfd, timeout); + if (select_ret == TEST_TIMEOUT) { + return WOLFSSL_FATAL_ERROR; + } + } + } + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); + + if (ret != WOLFSSL_SUCCESS) { + char buff[WOLFSSL_MAX_ERROR_SZ]; + printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); + return ret; + } + + for (count = 0; count < loop_count; count++) { + int select_ret; + + select_ret = tcp_select(*sockfd, timeout); + if (select_ret == TEST_TIMEOUT) { + ret = WOLFSSL_FATAL_ERROR; + break; + } + + do { + ret = wolfSSL_read(ssl, input, sizeof(input)-1); + if (ret > 0) { + input[ret] = '\0'; + printf("Client message: %s\n", input); + } + } while (err == WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_SUCCESS); + + do { + if ((ret = wolfSSL_write(ssl, msg, sizeof(msg))) != sizeof(msg)) { + return WOLFSSL_FATAL_ERROR; + } + err = wolfSSL_get_error(ssl, ret); + } while (err == WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_SUCCESS); + } + return ret; +} +#endif /* WOLFSSL_SESSION_EXPORT */ + static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) { SOCKET_T sockfd = 0; SOCKET_T clientfd = 0; - word16 port = wolfSSLPort; + word16 port; - WOLFSSL_METHOD* method = 0; + callback_functions* cbf; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; char msg[] = "I hear you fa shizzle!"; char input[1024]; int idx; + int ret, err = 0; + int sharedCtx = 0; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif ((func_args*)args)->return_code = TEST_FAIL; - method = wolfSSLv23_server_method(); - ctx = wolfSSL_CTX_new(method); + cbf = ((func_args*)args)->callbacks; -#if defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API) && \ - !defined(WOLFSSL_SNIFFER) && !defined(WOLFSSL_MDK_SHELL) && \ - !defined(WOLFSSL_TIRTOS) - port = 0; +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + if (cbf != NULL && cbf->ctx) { + ctx = cbf->ctx; + sharedCtx = 1; + } + else +#endif + { + WOLFSSL_METHOD* method = NULL; + if (cbf != NULL && cbf->method != NULL) { + method = cbf->method(); + } + else { + method = wolfSSLv23_server_method(); + } + ctx = wolfSSL_CTX_new(method); + } + +#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \ + defined(HAVE_POLY1305) + TicketInit(); + wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb); #endif - wolfSSL_CTX_set_verify(ctx, - SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); +#if defined(USE_WINDOWS_API) + port = ((func_args*)args)->signal->port; +#elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ + !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) + /* Let tcp_listen assign port */ + port = 0; +#else + /* Use default port */ + port = wolfSSLPort; +#endif -#ifdef OPENSSL_EXTRA + /* do it here to detect failure */ + tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1); + CloseSocket(sockfd); + + wolfSSL_CTX_set_verify(ctx, + WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + +#ifdef WOLFSSL_ENCRYPTED_KEYS 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 (!sharedCtx && 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 (!sharedCtx && 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");*/ goto done; } - + + /* call ctx setup callback */ + if (cbf != NULL && cbf->ctx_ready != NULL) { + cbf->ctx_ready(ctx); + } + ssl = wolfSSL_new(ctx); - tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0); - CloseSocket(sockfd); + if (ssl == NULL) { + goto done; + } - wolfSSL_set_fd(ssl, clientfd); - -#ifdef NO_PSK - #if !defined(NO_FILESYSTEM) && !defined(NO_DH) - wolfSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM); - #elif !defined(NO_DH) - SetDH(ssl); /* will repick suites with DHE, higher priority than PSK */ - #endif +#ifdef WOLFSSL_SESSION_EXPORT + /* only add in more complex nonblocking case with session export tests */ + if (args && ((func_args*)args)->argc > 0) { + /* set as nonblock and time out for waiting on read/write */ + tcp_set_nonblocking(&clientfd); + wolfSSL_dtls_set_using_nonblock(ssl, 1); + } #endif - if (wolfSSL_accept(ssl) != SSL_SUCCESS) - { - int err = wolfSSL_get_error(ssl, 0); - char buffer[WOLFSSL_MAX_ERROR_SZ]; - printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); + if (sharedCtx && wolfSSL_use_certificate_file(ssl, svrCertFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + /*err_sys("can't load server cert chain file, " + "Please run from wolfSSL home dir");*/ + goto done; + } + if (sharedCtx && wolfSSL_use_PrivateKey_file(ssl, svrKeyFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + /*err_sys("can't load server key file, " + "Please run from wolfSSL home dir");*/ + goto done; + } + + if (wolfSSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) { + /*err_sys("SSL_set_fd failed");*/ + goto done; + } + +#if !defined(NO_FILESYSTEM) && !defined(NO_DH) + wolfSSL_SetTmpDH_file(ssl, dhParamFile, WOLFSSL_FILETYPE_PEM); +#elif !defined(NO_DH) + SetDH(ssl); /* will repick suites with DHE, higher priority than PSK */ +#endif + + /* call ssl setup callback */ + if (cbf != NULL && cbf->ssl_ready != NULL) { + cbf->ssl_ready(ssl); + } + +#ifdef WOLFSSL_SESSION_EXPORT + /* only add in more complex nonblocking case with session export tests */ + if (((func_args*)args)->argc > 0) { + ret = nonblocking_accept_read(args, ssl, &clientfd); + if (ret >= 0) { + ((func_args*)args)->return_code = TEST_SUCCESS; + } + #ifdef WOLFSSL_TIRTOS + Task_yield(); + #endif + goto done; + } +#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 = wolfSSL_accept(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); + + if (ret != WOLFSSL_SUCCESS) { + char buff[WOLFSSL_MAX_ERROR_SZ]; + printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); /*err_sys("SSL_accept failed");*/ goto done; } idx = wolfSSL_read(ssl, input, sizeof(input)-1); if (idx > 0) { - input[idx] = 0; + input[idx] = '\0'; printf("Client message: %s\n", input); } - - if (wolfSSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) - { + + if (wolfSSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) { /*err_sys("SSL_write failed");*/ #ifdef WOLFSSL_TIRTOS return; @@ -397,14 +2472,212 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) Task_yield(); #endif + ((func_args*)args)->return_code = TEST_SUCCESS; + done: wolfSSL_shutdown(ssl); wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - + if (!sharedCtx) + wolfSSL_CTX_free(ctx); + CloseSocket(clientfd); + +#ifdef WOLFSSL_TIRTOS + fdCloseSession(Task_self()); +#endif + +#if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ + && defined(HAVE_THREAD_LS) + wc_ecc_fp_free(); /* free per thread cache */ +#endif + +#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \ + defined(HAVE_POLY1305) + TicketCleanup(); +#endif + +#ifndef WOLFSSL_TIRTOS + return 0; +#endif +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) +static THREAD_RETURN WOLFSSL_THREAD test_server_loop(void* args) +{ + SOCKET_T sockfd = 0; + SOCKET_T clientfd = 0; + word16 port; + + callback_functions* cbf; + WOLFSSL_CTX* ctx = 0; + WOLFSSL* ssl = 0; + + char msg[] = "I hear you fa shizzle!"; + char input[1024]; + int idx; + int ret, err = 0; + int sharedCtx = 0; + int loop_count = ((func_args*)args)->argc; + int count = 0; + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + ((func_args*)args)->return_code = TEST_FAIL; + cbf = ((func_args*)args)->callbacks; + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + if (cbf != NULL && cbf->ctx) { + ctx = cbf->ctx; + sharedCtx = 1; + } + else +#endif + { + WOLFSSL_METHOD* method = NULL; + if (cbf != NULL && cbf->method != NULL) { + method = cbf->method(); + } + else { + method = wolfSSLv23_server_method(); + } + ctx = wolfSSL_CTX_new(method); + } + +#if defined(USE_WINDOWS_API) + port = ((func_args*)args)->signal->port; +#elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ + !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) + /* Let tcp_listen assign port */ + port = 0; +#else + /* Use default port */ + port = wolfSSLPort; +#endif + + wolfSSL_CTX_set_verify(ctx, + WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + +#ifdef WOLFSSL_ENCRYPTED_KEYS + wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); +#endif + + 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 (!sharedCtx && 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 (!sharedCtx && 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");*/ + goto done; + } + /* call ctx setup callback */ + if (cbf != NULL && cbf->ctx_ready != NULL) { + cbf->ctx_ready(ctx); + } + + while(count != loop_count) { + ssl = wolfSSL_new(ctx); + if (ssl == NULL) { + goto done; + } + if (sharedCtx && wolfSSL_use_certificate_file(ssl, svrCertFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + /*err_sys("can't load server cert chain file, " + "Please run from wolfSSL home dir");*/ + goto done; + } + if (sharedCtx && wolfSSL_use_PrivateKey_file(ssl, svrKeyFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + /*err_sys("can't load server key file, " + "Please run from wolfSSL home dir");*/ + goto done; + } + +#if !defined(NO_FILESYSTEM) && !defined(NO_DH) + wolfSSL_SetTmpDH_file(ssl, dhParamFile, WOLFSSL_FILETYPE_PEM); +#elif !defined(NO_DH) + SetDH(ssl); /* will repick suites with DHE, higher priority than PSK */ +#endif + /* call ssl setup callback */ + if (cbf != NULL && cbf->ssl_ready != NULL) { + cbf->ssl_ready(ssl); + } + /* do it here to detect failure */ + tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1); + CloseSocket(sockfd); + if (wolfSSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) { + /*err_sys("SSL_set_fd failed");*/ + goto done; + } + + 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 = wolfSSL_accept(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); + + if (ret != WOLFSSL_SUCCESS) { + char buff[WOLFSSL_MAX_ERROR_SZ]; + printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); + /*err_sys("SSL_accept failed");*/ + goto done; + } + + idx = wolfSSL_read(ssl, input, sizeof(input)-1); + if (idx > 0) { + input[idx] = '\0'; + printf("Client message: %s\n", input); + } + + if (wolfSSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) { + /*err_sys("SSL_write failed");*/ + #ifdef WOLFSSL_TIRTOS + return; + #else + return 0; + #endif + } + /* free ssl for this connection */ + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); ssl = NULL; + CloseSocket(clientfd); + + count++; + } +#ifdef WOLFSSL_TIRTOS + Task_yield(); +#endif + ((func_args*)args)->return_code = TEST_SUCCESS; +done: + if(ssl != NULL) { + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + } + if (!sharedCtx) + wolfSSL_CTX_free(ctx); + + CloseSocket(clientfd); + #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif @@ -418,95 +2691,414 @@ done: return 0; #endif } +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) */ +typedef int (*cbType)(WOLFSSL_CTX *ctx, WOLFSSL *ssl); -static void test_client_nofail(void* args) +static void test_client_nofail(void* args, void *cb) { SOCKET_T sockfd = 0; + callback_functions* cbf; - WOLFSSL_METHOD* method = 0; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; + WOLFSSL_CIPHER* cipher; char msg[64] = "hello wolfssl!"; char reply[1024]; int input; - int msgSz = (int)strlen(msg); + int msgSz = (int)XSTRLEN(msg); + int ret, err = 0; + int cipherSuite; + int sharedCtx = 0; + const char* cipherName1, *cipherName2; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif ((func_args*)args)->return_code = TEST_FAIL; - method = wolfSSLv23_client_method(); - ctx = wolfSSL_CTX_new(method); + cbf = ((func_args*)args)->callbacks; -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + if (cbf != NULL && cbf->ctx) { + ctx = cbf->ctx; + sharedCtx = 1; + } + else +#endif + { + WOLFSSL_METHOD* method = NULL; + if (cbf != NULL && cbf->method != NULL) { + method = cbf->method(); + } + else { + method = wolfSSLv23_client_method(); + } + ctx = wolfSSL_CTX_new(method); + } + +#ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif - if (wolfSSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS) + /* Do connect here so server detects failures */ + tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, + 0, 0, NULL); + + 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; + goto done; } - if (wolfSSL_CTX_use_certificate_file(ctx, cliCert, SSL_FILETYPE_PEM) - != SSL_SUCCESS) - { + if (!sharedCtx && 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; + goto done; } - if (wolfSSL_CTX_use_PrivateKey_file(ctx, cliKey, SSL_FILETYPE_PEM) - != SSL_SUCCESS) - { + if (!sharedCtx && 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");*/ - goto done2; + goto done; } - tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, 0); + /* call ctx setup callback */ + if (cbf != NULL && cbf->ctx_ready != NULL) { + cbf->ctx_ready(ctx); + } ssl = wolfSSL_new(ctx); - wolfSSL_set_fd(ssl, sockfd); - if (wolfSSL_connect(ssl) != SSL_SUCCESS) - { - int err = wolfSSL_get_error(ssl, 0); - char buffer[WOLFSSL_MAX_ERROR_SZ]; - printf("err = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); - /*printf("SSL_connect failed");*/ - goto done2; + if (ssl == NULL) { + goto done; } - if (wolfSSL_write(ssl, msg, msgSz) != msgSz) - { + if (sharedCtx && wolfSSL_use_certificate_file(ssl, cliCertFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + /*err_sys("can't load client cert file, " + "Please run from wolfSSL home dir");*/ + goto done; + } + if (sharedCtx && wolfSSL_use_PrivateKey_file(ssl, cliKeyFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + /*err_sys("can't load client key file, " + "Please run from wolfSSL home dir");*/ + goto done; + } + + if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { + /*err_sys("SSL_set_fd failed");*/ + goto done; + } + + /* call ssl setup callback */ + if (cbf != NULL && cbf->ssl_ready != NULL) { + cbf->ssl_ready(ssl); + } + + 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 = wolfSSL_connect(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); + + if (ret != WOLFSSL_SUCCESS) { + char buff[WOLFSSL_MAX_ERROR_SZ]; + printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); + /*err_sys("SSL_connect failed");*/ + goto done; + } + + /* test the various get cipher methods */ + /* Internal cipher suite names */ + cipherSuite = wolfSSL_get_current_cipher_suite(ssl); + cipherName1 = wolfSSL_get_cipher_name(ssl); + cipherName2 = wolfSSL_get_cipher_name_from_suite( + (cipherSuite >> 8), cipherSuite & 0xFF); + AssertStrEQ(cipherName1, cipherName2); + + /* IANA Cipher Suites Names */ + /* Unless WOLFSSL_CIPHER_INTERNALNAME or NO_ERROR_STRINGS, + then it's the internal cipher suite name */ + cipher = wolfSSL_get_current_cipher(ssl); + cipherName1 = wolfSSL_CIPHER_get_name(cipher); + cipherName2 = wolfSSL_get_cipher(ssl); + AssertStrEQ(cipherName1, cipherName2); +#if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) && \ + !defined(WOLFSSL_QT) + cipherName1 = wolfSSL_get_cipher_name_iana_from_suite( + (cipherSuite >> 8), cipherSuite & 0xFF); + AssertStrEQ(cipherName1, cipherName2); +#endif + + if (cb != NULL) + ((cbType)cb)(ctx, ssl); + + if (wolfSSL_write(ssl, msg, msgSz) != msgSz) { /*err_sys("SSL_write failed");*/ - goto done2; + goto done; } input = wolfSSL_read(ssl, reply, sizeof(reply)-1); - if (input > 0) - { - reply[input] = 0; + if (input > 0) { + reply[input] = '\0'; printf("Server response: %s\n", reply); } -done2: - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - - CloseSocket(sockfd); ((func_args*)args)->return_code = TEST_SUCCESS; +done: + wolfSSL_free(ssl); + if (!sharedCtx) + wolfSSL_CTX_free(ctx); + + CloseSocket(sockfd); + +#ifdef WOLFSSL_TIRTOS + fdCloseSession(Task_self()); +#endif + +#if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ + && defined(HAVE_THREAD_LS) + wc_ecc_fp_free(); /* free per thread cache */ +#endif + + return; +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) +static void test_client_reuse_WOLFSSLobj(void* args, void *cb, void* server_args) +{ + SOCKET_T sockfd = 0; + callback_functions* cbf; + + WOLFSSL_CTX* ctx = 0; + WOLFSSL* ssl = 0; + WOLFSSL_SESSION* session = NULL; + + char msg[64] = "hello wolfssl!"; + char reply[1024]; + int input; + int msgSz = (int)XSTRLEN(msg); + int ret, err = 0; + int sharedCtx = 0; + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + ((func_args*)args)->return_code = TEST_FAIL; + cbf = ((func_args*)args)->callbacks; + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + if (cbf != NULL && cbf->ctx) { + ctx = cbf->ctx; + sharedCtx = 1; + } + else +#endif + { + WOLFSSL_METHOD* method = NULL; + if (cbf != NULL && cbf->method != NULL) { + method = cbf->method(); + } + else { + method = wolfSSLv23_client_method(); + } + ctx = wolfSSL_CTX_new(method); + } + +#ifdef WOLFSSL_ENCRYPTED_KEYS + wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); +#endif + + /* Do connect here so server detects failures */ + tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, + 0, 0, NULL); + + 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 done; + } + if (!sharedCtx && 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 done; + } + if (!sharedCtx && 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");*/ + goto done; + } + + /* call ctx setup callback */ + if (cbf != NULL && cbf->ctx_ready != NULL) { + cbf->ctx_ready(ctx); + } + + ssl = wolfSSL_new(ctx); + if (ssl == NULL) { + goto done; + } + /* keep handshakre resources for re-using WOLFSSL obj */ + wolfSSL_KeepArrays(ssl); + if(wolfSSL_KeepHandshakeResources(ssl)) { + /* err_sys("SSL_KeepHandshakeResources failed"); */ + goto done; + } + if (sharedCtx && wolfSSL_use_certificate_file(ssl, cliCertFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + /*err_sys("can't load client cert file, " + "Please run from wolfSSL home dir");*/ + goto done; + } + if (sharedCtx && wolfSSL_use_PrivateKey_file(ssl, cliKeyFile, + WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { + /*err_sys("can't load client key file, " + "Please run from wolfSSL home dir");*/ + goto done; + } + + if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { + /*err_sys("SSL_set_fd failed");*/ + goto done; + } + + /* call ssl setup callback */ + if (cbf != NULL && cbf->ssl_ready != NULL) { + cbf->ssl_ready(ssl); + } + + 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 = wolfSSL_connect(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); + + if (ret != WOLFSSL_SUCCESS) { + char buff[WOLFSSL_MAX_ERROR_SZ]; + printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); + /*err_sys("SSL_connect failed");*/ + goto done; + } + /* Build first session */ + if (cb != NULL) + ((cbType)cb)(ctx, ssl); + + if (wolfSSL_write(ssl, msg, msgSz) != msgSz) { + /*err_sys("SSL_write failed");*/ + goto done; + } + + input = wolfSSL_read(ssl, reply, sizeof(reply)-1); + if (input > 0) { + reply[input] = '\0'; + printf("Server response: %s\n", reply); + } + + /* Session Resumption by re-using WOLFSSL object */ + wolfSSL_set_quiet_shutdown(ssl, 1); + if (wolfSSL_shutdown(ssl) != WOLFSSL_SUCCESS) { + /* err_sys ("SSL shutdown failed"); */ + goto done; + } + session = wolfSSL_get_session(ssl); + if (wolfSSL_clear(ssl) != WOLFSSL_SUCCESS) { + /* err_sys ("SSL_clear failed"); */ + goto done; + } + wolfSSL_set_session(ssl, session); + /* close socket once */ + CloseSocket(sockfd); + sockfd = 0; + /* wait until server ready */ + wait_tcp_ready((func_args*)server_args); + printf("session resumption\n"); + /* Do re-connect */ + tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, + 0, 0, NULL); + if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { + /*err_sys("SSL_set_fd failed");*/ + goto done; + } + +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 = wolfSSL_connect(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); + + if (ret != WOLFSSL_SUCCESS) { + char buff[WOLFSSL_MAX_ERROR_SZ]; + printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); + /*err_sys("SSL_connect failed");*/ + goto done; + } + /* Build first session */ + if (cb != NULL) + ((cbType)cb)(ctx, ssl); + + if (wolfSSL_write(ssl, msg, msgSz) != msgSz) { + /*err_sys("SSL_write failed");*/ + goto done; + } + + input = wolfSSL_read(ssl, reply, sizeof(reply)-1); + if (input > 0) { + reply[input] = '\0'; + printf("Server response: %s\n", reply); + } + + ((func_args*)args)->return_code = TEST_SUCCESS; + +done: + wolfSSL_free(ssl); + if (!sharedCtx) + wolfSSL_CTX_free(ctx); + + CloseSocket(sockfd); + #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif return; } +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) */ -/* SNI helper functions */ -#ifdef HAVE_SNI +/* SNI / ALPN / session export helper functions */ +#if defined(HAVE_SNI) || defined(HAVE_ALPN) || defined(WOLFSSL_SESSION_EXPORT) static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) { @@ -516,53 +3108,76 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) WOLFSSL* ssl = NULL; SOCKET_T sfd = 0; SOCKET_T cfd = 0; - word16 port = wolfSSLPort; + word16 port; char msg[] = "I hear you fa shizzle!"; int len = (int) XSTRLEN(msg); char input[1024]; int idx; + int ret, err = 0; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif ((func_args*)args)->return_code = TEST_FAIL; -#if defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API) && \ - !defined(WOLFSSL_SNIFFER) && !defined(WOLFSSL_MDK_SHELL) && \ - !defined(WOLFSSL_TIRTOS) +#if defined(USE_WINDOWS_API) + port = ((func_args*)args)->signal->port; +#elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ + !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) + /* Let tcp_listen assign port */ port = 0; +#else + /* Use default port */ + port = wolfSSLPort; #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 +#ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif +#ifdef WOLFSSL_SESSION_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); ssl = wolfSSL_new(ctx); + if (wolfSSL_dtls(ssl)) { + SOCKADDR_IN_T cliAddr; + socklen_t cliLen; - tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0); - CloseSocket(sfd); + cliLen = sizeof(cliAddr); + tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 1, 0, 0, 0); + idx = (int)recvfrom(sfd, input, sizeof(input), MSG_PEEK, + (struct sockaddr*)&cliAddr, &cliLen); + AssertIntGT(idx, 0); + wolfSSL_dtls_set_peer(ssl, &cliAddr, cliLen); + } + else { + tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 0, 1); + CloseSocket(sfd); + } - 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 @@ -571,33 +3186,61 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) if (callbacks->ssl_ready) callbacks->ssl_ready(ssl); - /* AssertIntEQ(SSL_SUCCESS, wolfSSL_accept(ssl)); */ - if (wolfSSL_accept(ssl) != SSL_SUCCESS) { - int err = wolfSSL_get_error(ssl, 0); - char buffer[WOLFSSL_MAX_ERROR_SZ]; - printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); + 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 - } else { + err = 0; /* Reset error */ + ret = wolfSSL_accept(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); + + if (ret != WOLFSSL_SUCCESS) { + char buff[WOLFSSL_MAX_ERROR_SZ]; + printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); + /*err_sys("SSL_accept failed");*/ + } + else { if (0 < (idx = wolfSSL_read(ssl, input, sizeof(input)-1))) { input[idx] = 0; printf("Client message: %s\n", input); } AssertIntEQ(len, wolfSSL_write(ssl, msg, len)); +#if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IO_POOL) + if (wolfSSL_dtls(ssl)) { + byte* import; + word32 sz; + + wolfSSL_dtls_export(ssl, NULL, &sz); + import = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + AssertNotNull(import); + idx = wolfSSL_dtls_export(ssl, import, &sz); + AssertIntGE(idx, 0); + AssertIntGE(wolfSSL_dtls_import(ssl, import, idx), 0); + XFREE(import, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif #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()); @@ -613,7 +3256,6 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) #endif } - static void run_wolfssl_client(void* args) { callback_functions* callbacks = ((func_args*)args)->callbacks; @@ -626,6 +3268,7 @@ static void run_wolfssl_client(void* args) int len = (int) XSTRLEN(msg); char input[1024]; int idx; + int ret, err = 0; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); @@ -633,41 +3276,63 @@ static void run_wolfssl_client(void* args) ((func_args*)args)->return_code = TEST_FAIL; -#ifdef OPENSSL_EXTRA +#ifdef WOLFSSL_ENCRYPTED_KEYS 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); - tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 0); - ssl = wolfSSL_new(ctx); - wolfSSL_set_fd(ssl, sfd); + if (wolfSSL_dtls(ssl)) { + tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, + 1, 0, ssl); + } + else { + tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, + 0, 0, ssl); + } + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, sfd)); if (callbacks->ssl_ready) callbacks->ssl_ready(ssl); - if (wolfSSL_connect(ssl) != SSL_SUCCESS) { - int err = wolfSSL_get_error(ssl, 0); - char buffer[WOLFSSL_MAX_ERROR_SZ]; - printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); + 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 - } else { + err = 0; /* Reset error */ + ret = wolfSSL_connect(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); + + if (ret != WOLFSSL_SUCCESS) { + char buff[WOLFSSL_MAX_ERROR_SZ]; + printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); + /*err_sys("SSL_connect failed");*/ + } + else { AssertIntEQ(len, wolfSSL_write(ssl, msg, len)); if (0 < (idx = wolfSSL_read(ssl, input, sizeof(input)-1))) { input[idx] = 0; printf("Server response: %s\n", input); } + ((func_args*)args)->return_code = TEST_SUCCESS; } if (callbacks->on_result) @@ -676,21 +3341,18 @@ 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()); #endif } -#endif /* HAVE_SNI */ -#endif /* io tests dependencies */ - +#endif /* defined(HAVE_SNI) || defined(HAVE_ALPN) || + defined(WOLFSSL_SESSION_EXPORT) */ static void test_wolfSSL_read_write(void) { -#ifdef HAVE_IO_TESTS_DEPENDENCIES - /* The unit testing for read and write shall happen simutaneously, since + /* The unit testing for read and write shall happen simultaneously, since * one can't do anything with one without the other. (Except for a failure * test case.) This function will call all the others that will set up, * execute, and report their test findings. @@ -714,19 +3376,177 @@ static void test_wolfSSL_read_write(void) func_args server_args; THREAD_TYPE serverThread; + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif StartTCP(); InitTcpReady(&ready); - + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + server_args.signal = &ready; client_args.signal = &ready; - + start_thread(test_server_nofail, &server_args, &serverThread); wait_tcp_ready(&server_args); - test_client_nofail(&client_args); + test_client_nofail(&client_args, NULL); + join_thread(serverThread); + + AssertTrue(client_args.return_code); + AssertTrue(server_args.return_code); + + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) +static void test_wolfSSL_reuse_WOLFSSLobj(void) +{ + /* The unit test for session resumption by re-using WOLFSSL object. + * WOLFSSL object is not cleared after first session. It re-use the obeject + * for second connection. + */ + tcp_ready ready; + func_args client_args; + func_args server_args; + THREAD_TYPE serverThread; + + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + StartTCP(); + InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + + server_args.signal = &ready; + client_args.signal = &ready; + /* the var is used for loop number */ + server_args.argc = 2; + + start_thread(test_server_loop, &server_args, &serverThread); + wait_tcp_ready(&server_args); + test_client_reuse_WOLFSSLobj(&client_args, NULL, &server_args); + join_thread(serverThread); + + AssertTrue(client_args.return_code); + AssertTrue(server_args.return_code); + + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif +} +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) */ + +#if 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, 0x3b, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x80, 0x0C, 0x00, 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(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) */ + +static void test_wolfSSL_dtls_export(void) +{ +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) + tcp_ready ready; + func_args client_args; + func_args server_args; + THREAD_TYPE serverThread; + callback_functions server_cbf; + callback_functions client_cbf; +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + + /* set using dtls */ + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + XMEMSET(&server_cbf, 0, sizeof(callback_functions)); + XMEMSET(&client_cbf, 0, sizeof(callback_functions)); + server_cbf.method = wolfDTLSv1_2_server_method; + client_cbf.method = wolfDTLSv1_2_client_method; + server_args.callbacks = &server_cbf; + client_args.callbacks = &client_cbf; + + server_args.signal = &ready; + client_args.signal = &ready; + + start_thread(run_wolfssl_server, &server_args, &serverThread); + wait_tcp_ready(&server_args); + run_wolfssl_client(&client_args); join_thread(serverThread); AssertTrue(client_args.return_code); @@ -738,6 +3558,117 @@ static void test_wolfSSL_read_write(void) fdOpenSession(Task_self()); #endif + { + SOCKET_T sockfd = 0; + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + char msg[64] = "hello wolfssl!"; + char reply[1024]; + int msgSz = (int)XSTRLEN(msg); + byte *session, *window; + unsigned int sessionSz, windowSz; + struct sockaddr_in peerAddr; + int i; + + + /* 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); + + + /* check storing client state after connection and storing window only */ +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + + /* set using dtls */ + XMEMSET(&server_args, 0, sizeof(func_args)); + XMEMSET(&server_cbf, 0, sizeof(callback_functions)); + server_cbf.method = wolfDTLSv1_2_server_method; + server_args.callbacks = &server_cbf; + server_args.argc = 3; /* set loop_count to 3 */ + + + server_args.signal = &ready; + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + + /* create and connect with client */ + AssertNotNull(ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method())); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); + tcp_connect(&sockfd, wolfSSLIP, server_args.signal->port, 0, 0, NULL); + AssertNotNull(ssl = wolfSSL_new(ctx)); + AssertIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS); + + /* store server information connected too */ + XMEMSET(&peerAddr, 0, sizeof(peerAddr)); + peerAddr.sin_family = AF_INET; + peerAddr.sin_port = XHTONS(server_args.signal->port); + wolfSSL_dtls_set_peer(ssl, &peerAddr, sizeof(peerAddr)); + + AssertIntEQ(wolfSSL_connect(ssl), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_dtls_export(ssl, NULL, &sessionSz), 0); + session = (byte*)XMALLOC(sessionSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + AssertIntGT(wolfSSL_dtls_export(ssl, session, &sessionSz), 0); + AssertIntEQ(wolfSSL_write(ssl, msg, msgSz), msgSz); + AssertIntGT(wolfSSL_read(ssl, reply, sizeof(reply)), 0); + AssertIntEQ(wolfSSL_dtls_export_state_only(ssl, NULL, &windowSz), 0); + window = (byte*)XMALLOC(windowSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + AssertIntGT(wolfSSL_dtls_export_state_only(ssl, window, &windowSz), 0); + wolfSSL_free(ssl); + + for (i = 1; i < server_args.argc; i++) { + /* restore state */ + AssertNotNull(ssl = wolfSSL_new(ctx)); + AssertIntGT(wolfSSL_dtls_import(ssl, session, sessionSz), 0); + AssertIntGT(wolfSSL_dtls_import(ssl, window, windowSz), 0); + AssertIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_write(ssl, msg, msgSz), msgSz); + AssertIntGE(wolfSSL_read(ssl, reply, sizeof(reply)), 0); + AssertIntGT(wolfSSL_dtls_export_state_only(ssl, window, &windowSz), 0); + wolfSSL_free(ssl); + } + XFREE(session, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(window, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_CTX_free(ctx); + + printf("done and waiting for server\n"); + join_thread(serverThread); + AssertIntEQ(server_args.return_code, TEST_SUCCESS); + + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + } + + + printf(testingFmt, "wolfSSL_dtls_export()"); + printf(resultFmt, passed); #endif } @@ -745,69 +3676,148 @@ static void test_wolfSSL_read_write(void) | TLS extensions tests *----------------------------------------------------------------------------*/ +#if defined(HAVE_SNI) || defined(HAVE_ALPN) +/* connection test runner */ +static void test_wolfSSL_client_server(callback_functions* client_callbacks, + callback_functions* server_callbacks) +{ + tcp_ready ready; + func_args client_args; + func_args server_args; + THREAD_TYPE serverThread; + + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + + StartTCP(); + + client_args.callbacks = client_callbacks; + server_args.callbacks = server_callbacks; + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + /* RUN Server side */ + InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + + server_args.signal = &ready; + client_args.signal = &ready; + start_thread(run_wolfssl_server, &server_args, &serverThread); + wait_tcp_ready(&server_args); + + /* RUN Client side */ + run_wolfssl_client(&client_args); + join_thread(serverThread); + + FreeTcpReady(&ready); +#ifdef WOLFSSL_TIRTOS + fdCloseSession(Task_self()); +#endif +} +#endif /* defined(HAVE_SNI) || defined(HAVE_ALPN) */ + #ifdef HAVE_SNI +static void test_wolfSSL_UseSNI_params(void) +{ + WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + WOLFSSL *ssl = wolfSSL_new(ctx); + + AssertNotNull(ctx); + AssertNotNull(ssl); + + /* invalid [ctx|ssl] */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(NULL, 0, "ctx", 3)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSNI( NULL, 0, "ssl", 3)); + /* invalid type */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, -1, "ctx", 3)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSNI( ssl, -1, "ssl", 3)); + /* invalid data */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, 0, NULL, 3)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSNI( ssl, 0, NULL, 3)); + /* success case */ + 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); +} + +/* BEGIN of connection tests callbacks */ static void use_SNI_at_ctx(WOLFSSL_CTX* ctx) { - byte type = WOLFSSL_SNI_HOST_NAME; - char name[] = "www.yassl.com"; - - AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_UseSNI(ctx, type, (void *) name, XSTRLEN(name))); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_UseSNI(ctx, WOLFSSL_SNI_HOST_NAME, "www.wolfssl.com", 15)); } static void use_SNI_at_ssl(WOLFSSL* ssl) { - byte type = WOLFSSL_SNI_HOST_NAME; - char name[] = "www.yassl.com"; - - AssertIntEQ(SSL_SUCCESS, - wolfSSL_UseSNI(ssl, type, (void *) name, XSTRLEN(name))); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, "www.wolfssl.com", 15)); } static void different_SNI_at_ssl(WOLFSSL* ssl) { - byte type = WOLFSSL_SNI_HOST_NAME; - char name[] = "ww2.yassl.com"; - - AssertIntEQ(SSL_SUCCESS, - wolfSSL_UseSNI(ssl, type, (void *) name, XSTRLEN(name))); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, "ww2.wolfssl.com", 15)); } static void use_SNI_WITH_CONTINUE_at_ssl(WOLFSSL* ssl) { - byte type = WOLFSSL_SNI_HOST_NAME; - use_SNI_at_ssl(ssl); - - wolfSSL_SNI_SetOptions(ssl, type, WOLFSSL_SNI_CONTINUE_ON_MISMATCH); + wolfSSL_SNI_SetOptions(ssl, WOLFSSL_SNI_HOST_NAME, + WOLFSSL_SNI_CONTINUE_ON_MISMATCH); } static void use_SNI_WITH_FAKE_ANSWER_at_ssl(WOLFSSL* ssl) { - byte type = WOLFSSL_SNI_HOST_NAME; - use_SNI_at_ssl(ssl); - - wolfSSL_SNI_SetOptions(ssl, type, WOLFSSL_SNI_ANSWER_ON_MISMATCH); + wolfSSL_SNI_SetOptions(ssl, WOLFSSL_SNI_HOST_NAME, + WOLFSSL_SNI_ANSWER_ON_MISMATCH); } -static void verify_SNI_abort_on_client(WOLFSSL* ssl) +static void use_MANDATORY_SNI_at_ctx(WOLFSSL_CTX* ctx) { - AssertIntEQ(FATAL_ERROR, wolfSSL_get_error(ssl, 0)); + use_SNI_at_ctx(ctx); + wolfSSL_CTX_SNI_SetOptions(ctx, WOLFSSL_SNI_HOST_NAME, + WOLFSSL_SNI_ABORT_ON_ABSENCE); } -static void verify_SNI_abort_on_server(WOLFSSL* ssl) +static void use_MANDATORY_SNI_at_ssl(WOLFSSL* ssl) +{ + use_SNI_at_ssl(ssl); + wolfSSL_SNI_SetOptions(ssl, WOLFSSL_SNI_HOST_NAME, + WOLFSSL_SNI_ABORT_ON_ABSENCE); +} + +static void use_PSEUDO_MANDATORY_SNI_at_ctx(WOLFSSL_CTX* ctx) +{ + use_SNI_at_ctx(ctx); + wolfSSL_CTX_SNI_SetOptions(ctx, WOLFSSL_SNI_HOST_NAME, + WOLFSSL_SNI_ANSWER_ON_MISMATCH | WOLFSSL_SNI_ABORT_ON_ABSENCE); +} + +static void verify_UNKNOWN_SNI_on_server(WOLFSSL* ssl) { AssertIntEQ(UNKNOWN_SNI_HOST_NAME_E, wolfSSL_get_error(ssl, 0)); } +static void verify_SNI_ABSENT_on_server(WOLFSSL* ssl) +{ + AssertIntEQ(SNI_ABSENT_ERROR, wolfSSL_get_error(ssl, 0)); +} + static void verify_SNI_no_matching(WOLFSSL* ssl) { - byte type = WOLFSSL_SNI_HOST_NAME; - char* request = (char*) &type; /* to be overwriten */ + byte type = WOLFSSL_SNI_HOST_NAME; + char* request = (char*) &type; /* to be overwritten */ AssertIntEQ(WOLFSSL_SNI_NO_MATCH, wolfSSL_SNI_Status(ssl, type)); - AssertNotNull(request); AssertIntEQ(0, wolfSSL_SNI_GetRequest(ssl, type, (void**) &request)); AssertNull(request); @@ -815,30 +3825,82 @@ static void verify_SNI_no_matching(WOLFSSL* ssl) static void verify_SNI_real_matching(WOLFSSL* ssl) { - byte type = WOLFSSL_SNI_HOST_NAME; - char* request = NULL; - char name[] = "www.yassl.com"; - word16 length = XSTRLEN(name); + byte type = WOLFSSL_SNI_HOST_NAME; + char* request = NULL; AssertIntEQ(WOLFSSL_SNI_REAL_MATCH, wolfSSL_SNI_Status(ssl, type)); - - AssertIntEQ(length, wolfSSL_SNI_GetRequest(ssl, type, (void**) &request)); + AssertIntEQ(15, wolfSSL_SNI_GetRequest(ssl, type, (void**) &request)); AssertNotNull(request); - AssertStrEQ(name, request); + AssertStrEQ("www.wolfssl.com", request); } static void verify_SNI_fake_matching(WOLFSSL* ssl) { - byte type = WOLFSSL_SNI_HOST_NAME; - char* request = NULL; - char name[] = "ww2.yassl.com"; - word16 length = XSTRLEN(name); + byte type = WOLFSSL_SNI_HOST_NAME; + char* request = NULL; AssertIntEQ(WOLFSSL_SNI_FAKE_MATCH, wolfSSL_SNI_Status(ssl, type)); - - AssertIntEQ(length, wolfSSL_SNI_GetRequest(ssl, type, (void**) &request)); + AssertIntEQ(15, wolfSSL_SNI_GetRequest(ssl, type, (void**) &request)); AssertNotNull(request); - AssertStrEQ(name, request); + AssertStrEQ("ww2.wolfssl.com", request); +} + +static void verify_FATAL_ERROR_on_client(WOLFSSL* ssl) +{ + AssertIntEQ(FATAL_ERROR, wolfSSL_get_error(ssl, 0)); +} +/* END of connection tests callbacks */ + +static void test_wolfSSL_UseSNI_connection(void) +{ + unsigned long i; + callback_functions callbacks[] = { + /* success case at ctx */ + {0, use_SNI_at_ctx, 0, 0, 0}, + {0, use_SNI_at_ctx, 0, verify_SNI_real_matching, 0}, + + /* success case at ssl */ + {0, 0, use_SNI_at_ssl, verify_SNI_real_matching, 0}, + {0, 0, use_SNI_at_ssl, verify_SNI_real_matching, 0}, + + /* default mismatch behavior */ + {0, 0, different_SNI_at_ssl, verify_FATAL_ERROR_on_client, 0}, + {0, 0, use_SNI_at_ssl, verify_UNKNOWN_SNI_on_server, 0}, + + /* continue on mismatch */ + {0, 0, different_SNI_at_ssl, 0, 0}, + {0, 0, use_SNI_WITH_CONTINUE_at_ssl, verify_SNI_no_matching, 0}, + + /* fake answer on mismatch */ + {0, 0, different_SNI_at_ssl, 0, 0}, + {0, 0, use_SNI_WITH_FAKE_ANSWER_at_ssl, verify_SNI_fake_matching, 0}, + + /* sni abort - success */ + {0, use_SNI_at_ctx, 0, 0, 0}, + {0, use_MANDATORY_SNI_at_ctx, 0, verify_SNI_real_matching, 0}, + + /* sni abort - abort when absent (ctx) */ + {0, 0, 0, verify_FATAL_ERROR_on_client, 0}, + {0, use_MANDATORY_SNI_at_ctx, 0, verify_SNI_ABSENT_on_server, 0}, + + /* sni abort - abort when absent (ssl) */ + {0, 0, 0, verify_FATAL_ERROR_on_client, 0}, + {0, 0, use_MANDATORY_SNI_at_ssl, verify_SNI_ABSENT_on_server, 0}, + + /* sni abort - success when overwritten */ + {0, 0, 0, 0, 0}, + {0, use_MANDATORY_SNI_at_ctx, use_SNI_at_ssl, verify_SNI_no_matching, 0}, + + /* sni abort - success when allowing mismatches */ + {0, 0, different_SNI_at_ssl, 0, 0}, + {0, use_PSEUDO_MANDATORY_SNI_at_ctx, 0, verify_SNI_fake_matching, 0}, + }; + + for (i = 0; i < sizeof(callbacks) / sizeof(callback_functions); i += 2) { + callbacks[i ].method = wolfSSLv23_client_method; + callbacks[i + 1].method = wolfSSLv23_server_method; + test_wolfSSL_client_server(&callbacks[i], &callbacks[i + 1]); + } } static void test_wolfSSL_SNI_GetFromBuffer(void) @@ -905,6 +3967,14 @@ static void test_wolfSSL_SNI_GetFromBuffer(void) 0x12, 0x00, 0x00 }; + byte buffer5[] = { /* SSL v2.0 client hello */ + 0x00, 0x2b, 0x01, 0x03, 0x01, 0x00, 0x09, 0x00, 0x00, + /* dummy bytes bellow, just to pass size check */ + 0xb6, 0x03, 0x03, 0x83, 0xa3, 0xe6, 0xdc, 0x16, 0xa1, 0x43, 0xe9, 0x45, + 0x15, 0xbd, 0x64, 0xa9, 0xb6, 0x07, 0xb4, 0x50, 0xc6, 0xdd, 0xff, 0xc2, + 0xd3, 0x0d, 0x4f, 0x36, 0xb4, 0x41, 0x51, 0x61, 0xc1, 0xa5, 0x9e, 0x00, + }; + byte result[32] = {0}; word32 length = 32; @@ -925,7 +3995,7 @@ static void test_wolfSSL_SNI_GetFromBuffer(void) 0, result, &length)); buffer[1] = 0x03; - AssertIntEQ(SNI_UNSUPPORTED, wolfSSL_SNI_GetFromBuffer(buffer, + AssertIntEQ(SNI_UNSUPPORTED, wolfSSL_SNI_GetFromBuffer(buffer, sizeof(buffer), 0, result, &length)); buffer[2] = 0x03; @@ -933,57 +4003,33 @@ 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); -} -static void test_wolfSSL_client_server(callback_functions* client_callbacks, - callback_functions* server_callbacks) -{ -#ifdef HAVE_IO_TESTS_DEPENDENCIES - tcp_ready ready; - func_args client_args; - func_args server_args; - THREAD_TYPE serverThread; + /* SSL v2.0 tests */ + AssertIntEQ(SNI_UNSUPPORTED, wolfSSL_SNI_GetFromBuffer(buffer5, + sizeof(buffer5), 0, result, &length)); - StartTCP(); + buffer5[2] = 0x02; + AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buffer5, + sizeof(buffer5), 0, result, &length)); - client_args.callbacks = client_callbacks; - server_args.callbacks = server_callbacks; + buffer5[2] = 0x01; buffer5[6] = 0x08; + AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buffer5, + sizeof(buffer5), 0, result, &length)); -#ifdef WOLFSSL_TIRTOS - fdOpenSession(Task_self()); -#endif - - /* RUN Server side */ - InitTcpReady(&ready); - server_args.signal = &ready; - client_args.signal = &ready; - start_thread(run_wolfssl_server, &server_args, &serverThread); - wait_tcp_ready(&server_args); - - /* RUN Client side */ - run_wolfssl_client(&client_args); - join_thread(serverThread); - - FreeTcpReady(&ready); -#ifdef WOLFSSL_TIRTOS - fdCloseSession(Task_self()); -#endif - -#else - (void)client_callbacks; - (void)server_callbacks; -#endif + buffer5[6] = 0x09; buffer5[8] = 0x01; + AssertIntEQ(BUFFER_ERROR, wolfSSL_SNI_GetFromBuffer(buffer5, + sizeof(buffer5), 0, result, &length)); } #endif /* HAVE_SNI */ @@ -991,103 +4037,98 @@ static void test_wolfSSL_client_server(callback_functions* client_callbacks, static void test_wolfSSL_UseSNI(void) { #ifdef HAVE_SNI - callback_functions client_callbacks = {wolfSSLv23_client_method, 0, 0, 0}; - callback_functions server_callbacks = {wolfSSLv23_server_method, 0, 0, 0}; - - WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); - WOLFSSL *ssl = wolfSSL_new(ctx); - - AssertNotNull(ctx); - AssertNotNull(ssl); - - /* error cases */ - AssertIntNE(SSL_SUCCESS, - wolfSSL_CTX_UseSNI(NULL, 0, (void *) "ctx", XSTRLEN("ctx"))); - AssertIntNE(SSL_SUCCESS, - wolfSSL_UseSNI( NULL, 0, (void *) "ssl", XSTRLEN("ssl"))); - AssertIntNE(SSL_SUCCESS, - wolfSSL_CTX_UseSNI(ctx, -1, (void *) "ctx", XSTRLEN("ctx"))); - AssertIntNE(SSL_SUCCESS, - wolfSSL_UseSNI( ssl, -1, (void *) "ssl", XSTRLEN("ssl"))); - AssertIntNE(SSL_SUCCESS, - wolfSSL_CTX_UseSNI(ctx, 0, (void *) NULL, XSTRLEN("ctx"))); - AssertIntNE(SSL_SUCCESS, - wolfSSL_UseSNI( ssl, 0, (void *) NULL, XSTRLEN("ssl"))); - - /* success case */ - AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_UseSNI(ctx, 0, (void *) "ctx", XSTRLEN("ctx"))); - AssertIntEQ(SSL_SUCCESS, - wolfSSL_UseSNI( ssl, 0, (void *) "ssl", XSTRLEN("ssl"))); - - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - - /* Testing success case at ctx */ - client_callbacks.ctx_ready = server_callbacks.ctx_ready = use_SNI_at_ctx; - server_callbacks.on_result = verify_SNI_real_matching; - - test_wolfSSL_client_server(&client_callbacks, &server_callbacks); - - /* Testing success case at ssl */ - client_callbacks.ctx_ready = server_callbacks.ctx_ready = NULL; - client_callbacks.ssl_ready = server_callbacks.ssl_ready = use_SNI_at_ssl; - - test_wolfSSL_client_server(&client_callbacks, &server_callbacks); - - /* Testing default mismatch behaviour */ - client_callbacks.ssl_ready = different_SNI_at_ssl; - client_callbacks.on_result = verify_SNI_abort_on_client; - server_callbacks.on_result = verify_SNI_abort_on_server; - - test_wolfSSL_client_server(&client_callbacks, &server_callbacks); - client_callbacks.on_result = NULL; - - /* Testing continue on mismatch */ - client_callbacks.ssl_ready = different_SNI_at_ssl; - server_callbacks.ssl_ready = use_SNI_WITH_CONTINUE_at_ssl; - server_callbacks.on_result = verify_SNI_no_matching; - - test_wolfSSL_client_server(&client_callbacks, &server_callbacks); - - /* Testing fake answer on mismatch */ - server_callbacks.ssl_ready = use_SNI_WITH_FAKE_ANSWER_at_ssl; - server_callbacks.on_result = verify_SNI_fake_matching; - - test_wolfSSL_client_server(&client_callbacks, &server_callbacks); + test_wolfSSL_UseSNI_params(); + test_wolfSSL_UseSNI_connection(); test_wolfSSL_SNI_GetFromBuffer(); #endif } +#endif /* HAVE_IO_TESTS_DEPENDENCIES */ + +static void test_wolfSSL_UseTrustedCA(void) +{ +#if defined(HAVE_TRUSTED_CA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) + WOLFSSL_CTX *ctx; + WOLFSSL *ssl; + byte id[20]; + +#ifndef NO_WOLFSSL_SERVER + AssertNotNull((ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()))); + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); +#else + AssertNotNull((ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()))); +#endif + AssertNotNull((ssl = wolfSSL_new(ctx))); + XMEMSET(id, 0, sizeof(id)); + + /* error cases */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(NULL, 0, NULL, 0)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, + WOLFSSL_TRUSTED_CA_CERT_SHA1+1, NULL, 0)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, + WOLFSSL_TRUSTED_CA_CERT_SHA1, NULL, 0)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, + WOLFSSL_TRUSTED_CA_CERT_SHA1, id, 5)); +#ifdef NO_SHA + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, + WOLFSSL_TRUSTED_CA_KEY_SHA1, id, sizeof(id))); +#endif + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, + WOLFSSL_TRUSTED_CA_X509_NAME, id, 0)); + + /* success cases */ + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, + WOLFSSL_TRUSTED_CA_PRE_AGREED, NULL, 0)); +#ifndef NO_SHA + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, + WOLFSSL_TRUSTED_CA_KEY_SHA1, id, sizeof(id))); +#endif + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, + WOLFSSL_TRUSTED_CA_X509_NAME, id, 5)); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif /* HAVE_TRUSTED_CA */ +} + static void test_wolfSSL_UseMaxFragment(void) { -#ifdef HAVE_MAX_FRAGMENT - WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); +#if defined(HAVE_MAX_FRAGMENT) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) + #ifndef NO_WOLFSSL_SERVER + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()); + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + #else + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + #endif WOLFSSL *ssl = wolfSSL_new(ctx); AssertNotNull(ctx); 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, WOLFSSL_MFL_MIN-1)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseMaxFragment(ctx, WOLFSSL_MFL_MAX+1)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseMaxFragment(ssl, WOLFSSL_MFL_MIN-1)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseMaxFragment(ssl, WOLFSSL_MFL_MAX+1)); /* 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_8)); + 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_8)); + 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); @@ -1096,20 +4137,26 @@ static void test_wolfSSL_UseMaxFragment(void) static void test_wolfSSL_UseTruncatedHMAC(void) { -#ifdef HAVE_TRUNCATED_HMAC - WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); +#if defined(HAVE_TRUNCATED_HMAC) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) + #ifndef NO_WOLFSSL_SERVER + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()); + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + #else + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + #endif WOLFSSL *ssl = wolfSSL_new(ctx); AssertNotNull(ctx); 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); @@ -1118,34 +4165,27754 @@ 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) && !defined(NO_TLS) + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + WOLFSSL *ssl = wolfSSL_new(ctx); + + AssertNotNull(ctx); + AssertNotNull(ssl); + + /* error cases */ + AssertIntNE(WOLFSSL_SUCCESS, + wolfSSL_CTX_UseSupportedCurve(NULL, WOLFSSL_ECC_SECP256R1)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSupportedCurve(ctx, 0)); + + AssertIntNE(WOLFSSL_SUCCESS, + wolfSSL_UseSupportedCurve(NULL, WOLFSSL_ECC_SECP256R1)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSupportedCurve(ssl, 0)); + + /* success case */ + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_SECP256R1)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP256R1)); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif +} + +#if defined(HAVE_ALPN) && !defined(NO_WOLFSSL_SERVER) && \ + defined(HAVE_IO_TESTS_DEPENDENCIES) + +static void verify_ALPN_FATAL_ERROR_on_client(WOLFSSL* ssl) +{ + AssertIntEQ(UNKNOWN_ALPN_PROTOCOL_NAME_E, wolfSSL_get_error(ssl, 0)); +} + +static void use_ALPN_all(WOLFSSL* ssl) +{ + /* http/1.1,spdy/1,spdy/2,spdy/3 */ + char alpn_list[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x2c, + 0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c, + 0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c, + 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list), + WOLFSSL_ALPN_FAILED_ON_MISMATCH)); +} + +static void use_ALPN_all_continue(WOLFSSL* ssl) +{ + /* http/1.1,spdy/1,spdy/2,spdy/3 */ + char alpn_list[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x2c, + 0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c, + 0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c, + 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list), + WOLFSSL_ALPN_CONTINUE_ON_MISMATCH)); +} + +static void use_ALPN_one(WOLFSSL* ssl) +{ + /* spdy/2 */ + char proto[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x32}; + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto), + WOLFSSL_ALPN_FAILED_ON_MISMATCH)); +} + +static void use_ALPN_unknown(WOLFSSL* ssl) +{ + /* http/2.0 */ + char proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x32, 0x2e, 0x30}; + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto), + WOLFSSL_ALPN_FAILED_ON_MISMATCH)); +} + +static void use_ALPN_unknown_continue(WOLFSSL* ssl) +{ + /* http/2.0 */ + char proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x32, 0x2e, 0x30}; + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto), + WOLFSSL_ALPN_CONTINUE_ON_MISMATCH)); +} + +static void verify_ALPN_not_matching_spdy3(WOLFSSL* ssl) +{ + /* spdy/3 */ + char nego_proto[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; + + char *proto = NULL; + word16 protoSz = 0; + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); + + /* check value */ + AssertIntNE(1, sizeof(nego_proto) == protoSz); + if (proto) { + AssertIntNE(0, XMEMCMP(nego_proto, proto, sizeof(nego_proto))); + } +} + +static void verify_ALPN_not_matching_continue(WOLFSSL* ssl) +{ + char *proto = NULL; + word16 protoSz = 0; + + AssertIntEQ(WOLFSSL_ALPN_NOT_FOUND, + wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); + + /* check value */ + AssertIntEQ(1, (0 == protoSz)); + AssertIntEQ(1, (NULL == proto)); +} + +static void verify_ALPN_matching_http1(WOLFSSL* ssl) +{ + /* http/1.1 */ + char nego_proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31}; + char *proto; + word16 protoSz = 0; + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); + + /* check value */ + AssertIntEQ(1, sizeof(nego_proto) == protoSz); + AssertIntEQ(0, XMEMCMP(nego_proto, proto, protoSz)); +} + +static void verify_ALPN_matching_spdy2(WOLFSSL* ssl) +{ + /* spdy/2 */ + char nego_proto[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x32}; + char *proto; + word16 protoSz = 0; + + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); + + /* check value */ + AssertIntEQ(1, sizeof(nego_proto) == protoSz); + AssertIntEQ(0, XMEMCMP(nego_proto, proto, protoSz)); +} + +static void verify_ALPN_client_list(WOLFSSL* ssl) +{ + /* http/1.1,spdy/1,spdy/2,spdy/3 */ + char alpn_list[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x2c, + 0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c, + 0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c, + 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; + char *clist = NULL; + word16 clistSz = 0; + + 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(WOLFSSL_SUCCESS, wolfSSL_ALPN_FreePeerProtocol(ssl, &clist)); +} + +static void test_wolfSSL_UseALPN_connection(void) +{ + unsigned long i; + callback_functions callbacks[] = { + /* success case same list */ + {0, 0, use_ALPN_all, 0, 0}, + {0, 0, use_ALPN_all, verify_ALPN_matching_http1, 0}, + + /* success case only one for server */ + {0, 0, use_ALPN_all, 0, 0}, + {0, 0, use_ALPN_one, verify_ALPN_matching_spdy2, 0}, + + /* success case only one for client */ + {0, 0, use_ALPN_one, 0, 0}, + {0, 0, use_ALPN_all, verify_ALPN_matching_spdy2, 0}, + + /* success case none for client */ + {0, 0, 0, 0, 0}, + {0, 0, use_ALPN_all, 0, 0}, + + /* success case mismatch behavior but option 'continue' set */ + {0, 0, use_ALPN_all_continue, verify_ALPN_not_matching_continue, 0}, + {0, 0, use_ALPN_unknown_continue, 0, 0}, + + /* success case read protocol send by client */ + {0, 0, use_ALPN_all, 0, 0}, + {0, 0, use_ALPN_one, verify_ALPN_client_list, 0}, + + /* mismatch behavior with same list + * the first and only this one must be taken */ + {0, 0, use_ALPN_all, 0, 0}, + {0, 0, use_ALPN_all, verify_ALPN_not_matching_spdy3, 0}, + + /* default mismatch behavior */ + {0, 0, use_ALPN_all, 0, 0}, + {0, 0, use_ALPN_unknown, verify_ALPN_FATAL_ERROR_on_client, 0}, + }; + + for (i = 0; i < sizeof(callbacks) / sizeof(callback_functions); i += 2) { + callbacks[i ].method = wolfSSLv23_client_method; + callbacks[i + 1].method = wolfSSLv23_server_method; + test_wolfSSL_client_server(&callbacks[i], &callbacks[i + 1]); + } +} + +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" */ + char spdy1[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x31}; + /* "spdy/2" */ + char spdy2[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x32}; + /* "spdy/3" */ + char spdy3[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; + char buff[256]; + word32 idx; + 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, - wolfSSL_CTX_UseSupportedCurve(NULL, WOLFSSL_ECC_SECP256R1)); - AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_UseSupportedCurve(ctx, 0)); - - AssertIntNE(SSL_SUCCESS, - wolfSSL_UseSupportedCurve(NULL, WOLFSSL_ECC_SECP256R1)); - AssertIntNE(SSL_SUCCESS, wolfSSL_UseSupportedCurve(ssl, 0)); + AssertIntNE(WOLFSSL_SUCCESS, + wolfSSL_UseALPN(NULL, http1, sizeof(http1), + WOLFSSL_ALPN_FAILED_ON_MISMATCH)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, NULL, 0, + WOLFSSL_ALPN_FAILED_ON_MISMATCH)); /* success case */ - AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_SECP256R1)); - AssertIntEQ(SSL_SUCCESS, - wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP256R1)); -#endif + /* http1 only */ + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_UseALPN(ssl, http1, sizeof(http1), + WOLFSSL_ALPN_FAILED_ON_MISMATCH)); + + /* http1, spdy1 */ + XMEMCPY(buff, http1, sizeof(http1)); + idx = sizeof(http1); + buff[idx++] = ','; + XMEMCPY(buff+idx, spdy1, sizeof(spdy1)); + idx += sizeof(spdy1); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, + WOLFSSL_ALPN_FAILED_ON_MISMATCH)); + + /* http1, spdy2, spdy1 */ + XMEMCPY(buff, http1, sizeof(http1)); + idx = sizeof(http1); + buff[idx++] = ','; + XMEMCPY(buff+idx, spdy2, sizeof(spdy2)); + idx += sizeof(spdy2); + buff[idx++] = ','; + XMEMCPY(buff+idx, spdy1, sizeof(spdy1)); + idx += sizeof(spdy1); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, + WOLFSSL_ALPN_FAILED_ON_MISMATCH)); + + /* spdy3, http1, spdy2, spdy1 */ + XMEMCPY(buff, spdy3, sizeof(spdy3)); + idx = sizeof(spdy3); + buff[idx++] = ','; + XMEMCPY(buff+idx, http1, sizeof(http1)); + idx += sizeof(http1); + buff[idx++] = ','; + XMEMCPY(buff+idx, spdy2, sizeof(spdy2)); + idx += sizeof(spdy2); + buff[idx++] = ','; + XMEMCPY(buff+idx, spdy1, sizeof(spdy1)); + idx += sizeof(spdy1); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, + WOLFSSL_ALPN_CONTINUE_ON_MISMATCH)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif } +#endif /* HAVE_ALPN */ + +static void test_wolfSSL_UseALPN(void) +{ +#if defined(HAVE_ALPN) && !defined(NO_WOLFSSL_SERVER) &&\ + defined(HAVE_IO_TESTS_DEPENDENCIES) + test_wolfSSL_UseALPN_connection(); + test_wolfSSL_UseALPN_params(); +#endif +} + +static void test_wolfSSL_DisableExtendedMasterSecret(void) +{ +#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) + WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + WOLFSSL *ssl = wolfSSL_new(ctx); + + AssertNotNull(ctx); + AssertNotNull(ssl); + + /* error cases */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_DisableExtendedMasterSecret(NULL)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_DisableExtendedMasterSecret(NULL)); + + /* success cases */ + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_DisableExtendedMasterSecret(ctx)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_DisableExtendedMasterSecret(ssl)); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif +} + +static void test_wolfSSL_wolfSSL_UseSecureRenegotiation(void) +{ +#if defined(HAVE_SECURE_RENEGOTIATION) && !defined(NO_WOLFSSL_CLIENT) + WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + WOLFSSL *ssl = wolfSSL_new(ctx); + + AssertNotNull(ctx); + AssertNotNull(ssl); + + /* error cases */ + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(NULL)); + AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(NULL)); + + /* success cases */ + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(ctx)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl)); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif +} + + +/*----------------------------------------------------------------------------* + | X509 Tests + *----------------------------------------------------------------------------*/ +static void test_wolfSSL_X509_NAME_get_entry(void) +{ +#if !defined(NO_CERTS) && !defined(NO_RSA) +#if defined(OPENSSL_ALL) || \ + (defined(OPENSSL_EXTRA) && \ + (defined(KEEP_PEER_CERT) || defined(SESSION_CERTS))) + printf(testingFmt, "wolfSSL_X509_NAME_get_entry()"); + + { + /* use openssl like name to test mapping */ + X509_NAME_ENTRY* ne; + X509_NAME* name; + X509* x509; + #ifndef NO_FILESYSTEM + ASN1_STRING* asn; + char* subCN = NULL; + #endif + int idx; + ASN1_OBJECT *object = NULL; +#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + BIO* bio; +#endif + + #ifndef NO_FILESYSTEM + x509 = wolfSSL_X509_load_certificate_file(cliCertFile, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + name = X509_get_subject_name(x509); + idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1); + AssertIntGE(idx, 0); + ne = X509_NAME_get_entry(name, idx); + AssertNotNull(ne); + asn = X509_NAME_ENTRY_get_data(ne); + AssertNotNull(asn); + subCN = (char*)ASN1_STRING_data(asn); + AssertNotNull(subCN); + wolfSSL_FreeX509(x509); + #endif + + x509 = wolfSSL_X509_load_certificate_file(cliCertFile, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + name = X509_get_subject_name(x509); + idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1); + AssertIntGE(idx, 0); + +#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertIntEQ(X509_NAME_print_ex(bio, name, 4, + (XN_FLAG_RFC2253 & ~XN_FLAG_DN_REV)), WOLFSSL_SUCCESS); + BIO_free(bio); +#endif + + ne = X509_NAME_get_entry(name, idx); + AssertNotNull(ne); + AssertNotNull(object = X509_NAME_ENTRY_get_object(ne)); + wolfSSL_FreeX509(x509); + } + + printf(resultFmt, passed); +#endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (KEEP_PEER_CERT || SESSION_CERTS) */ +#endif /* !NO_CERTS && !NO_RSA */ +} + +/* Testing functions dealing with PKCS12 parsing out X509 certs */ +static void test_wolfSSL_PKCS12(void) +{ + /* .p12 file is encrypted with DES3 */ +#ifndef HAVE_FIPS /* Password used in cert "wolfSSL test" is only 12-bytes + * (96-bit) FIPS mode requires Minimum of 14-byte (112-bit) + * Password Key + */ +#if defined(OPENSSL_EXTRA) && !defined(NO_DES3) && !defined(NO_FILESYSTEM) && \ + !defined(NO_ASN) && !defined(NO_PWDBASED) && !defined(NO_RSA) && \ + !defined(NO_SHA) + byte buffer[5300]; + char file[] = "./certs/test-servercert.p12"; + char order[] = "./certs/ecc-rsa-server.p12"; + char pass[] = "a password"; +#ifdef HAVE_ECC + WOLFSSL_X509_NAME* subject; + WOLFSSL_X509 *x509; +#endif + XFILE f; + int bytes, ret; + WOLFSSL_BIO *bio; + WOLFSSL_EVP_PKEY *pkey; + WC_PKCS12 *pkcs12; + WC_PKCS12 *pkcs12_2; + WOLFSSL_X509 *cert; + WOLFSSL_X509 *tmp; + WOLF_STACK_OF(WOLFSSL_X509) *ca; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \ + || defined(WOLFSSL_NGINX) + WOLFSSL_CTX *ctx; + WOLFSSL *ssl; + WOLF_STACK_OF(WOLFSSL_X509) *tmp_ca = NULL; +#endif + + printf(testingFmt, "wolfSSL_PKCS12()"); + + f = XFOPEN(file, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + + bio = BIO_new_mem_buf((void*)buffer, bytes); + AssertNotNull(bio); + + pkcs12 = d2i_PKCS12_bio(bio, NULL); + AssertNotNull(pkcs12); + PKCS12_free(pkcs12); + + d2i_PKCS12_bio(bio, &pkcs12); + AssertNotNull(pkcs12); + BIO_free(bio); + + /* check verify MAC fail case */ + ret = PKCS12_parse(pkcs12, "bad", &pkey, &cert, NULL); + AssertIntEQ(ret, 0); + AssertNull(pkey); + AssertNull(cert); + + /* check parse with no extra certs kept */ + ret = PKCS12_parse(pkcs12, "wolfSSL test", &pkey, &cert, NULL); + AssertIntEQ(ret, 1); + AssertNotNull(pkey); + AssertNotNull(cert); + + wolfSSL_EVP_PKEY_free(pkey); + wolfSSL_X509_free(cert); + + /* check parse with extra certs kept */ + ret = PKCS12_parse(pkcs12, "wolfSSL test", &pkey, &cert, &ca); + AssertIntEQ(ret, 1); + AssertNotNull(pkey); + AssertNotNull(cert); + AssertNotNull(ca); + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \ + || defined(WOLFSSL_NGINX) + + /* Check that SSL_CTX_set0_chain correctly sets the certChain buffer */ +#ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#endif + /* Copy stack structure */ + AssertNotNull(tmp_ca = sk_X509_dup(ca)); + AssertIntEQ(SSL_CTX_set0_chain(ctx, tmp_ca), 1); + /* CTX now owns the tmp_ca stack structure */ + tmp_ca = NULL; + AssertIntEQ(wolfSSL_CTX_get_extra_chain_certs(ctx, &tmp_ca), 1); + AssertNotNull(tmp_ca); + AssertIntEQ(sk_X509_num(tmp_ca), sk_X509_num(ca)); + /* Check that the main cert is also set */ + AssertNotNull(ssl = SSL_new(ctx)); + AssertNotNull(SSL_get_certificate(ssl)); + SSL_free(ssl); + SSL_CTX_free(ctx); +#endif + + /* should be 2 other certs on stack */ + tmp = sk_X509_pop(ca); + AssertNotNull(tmp); + X509_free(tmp); + tmp = sk_X509_pop(ca); + AssertNotNull(tmp); + X509_free(tmp); + AssertNull(sk_X509_pop(ca)); + + EVP_PKEY_free(pkey); + X509_free(cert); + sk_X509_pop_free(ca, X509_free); + + /* check PKCS12_create */ + AssertNull(PKCS12_create(pass, NULL, NULL, NULL, NULL, -1, -1, -1, -1,0)); + AssertIntEQ(PKCS12_parse(pkcs12, "wolfSSL test", &pkey, &cert, &ca), + SSL_SUCCESS); + AssertNotNull((pkcs12_2 = PKCS12_create(pass, NULL, pkey, cert, ca, + -1, -1, 100, -1, 0))); + EVP_PKEY_free(pkey); + X509_free(cert); + sk_X509_free(ca); + + AssertIntEQ(PKCS12_parse(pkcs12_2, "a password", &pkey, &cert, &ca), + SSL_SUCCESS); + PKCS12_free(pkcs12_2); + AssertNotNull((pkcs12_2 = PKCS12_create(pass, NULL, pkey, cert, ca, + NID_pbe_WithSHA1And3_Key_TripleDES_CBC, + NID_pbe_WithSHA1And3_Key_TripleDES_CBC, + 2000, 1, 0))); + EVP_PKEY_free(pkey); + X509_free(cert); + sk_X509_free(ca); + + /* convert to DER then back and parse */ + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertIntEQ(i2d_PKCS12_bio(bio, pkcs12_2), SSL_SUCCESS); + PKCS12_free(pkcs12_2); + + AssertNotNull(pkcs12_2 = d2i_PKCS12_bio(bio, NULL)); + BIO_free(bio); + AssertIntEQ(PKCS12_parse(pkcs12_2, "a password", &pkey, &cert, &ca), + SSL_SUCCESS); + + /* should be 2 other certs on stack */ + tmp = sk_X509_pop(ca); + AssertNotNull(tmp); + X509_free(tmp); + tmp = sk_X509_pop(ca); + AssertNotNull(tmp); + X509_free(tmp); + AssertNull(sk_X509_pop(ca)); + + +#ifndef NO_RC4 + PKCS12_free(pkcs12_2); + AssertNotNull((pkcs12_2 = PKCS12_create(pass, NULL, pkey, cert, NULL, + NID_pbe_WithSHA1And128BitRC4, + NID_pbe_WithSHA1And128BitRC4, + 2000, 1, 0))); + EVP_PKEY_free(pkey); + X509_free(cert); + sk_X509_free(ca); + + AssertIntEQ(PKCS12_parse(pkcs12_2, "a password", &pkey, &cert, &ca), + SSL_SUCCESS); + +#endif /* NO_RC4 */ + + EVP_PKEY_free(pkey); + X509_free(cert); + PKCS12_free(pkcs12); + PKCS12_free(pkcs12_2); + sk_X509_free(ca); + +#ifdef HAVE_ECC + /* test order of parsing */ + f = XFOPEN(order, "rb"); + AssertTrue(f != XBADFILE); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + + AssertNotNull(bio = BIO_new_mem_buf((void*)buffer, bytes)); + AssertNotNull(pkcs12 = d2i_PKCS12_bio(bio, NULL)); + AssertIntEQ((ret = PKCS12_parse(pkcs12, "", &pkey, &cert, &ca)), + WOLFSSL_SUCCESS); + AssertNotNull(pkey); + AssertNotNull(cert); + AssertNotNull(ca); + + /* compare subject lines of certificates */ + AssertNotNull(subject = wolfSSL_X509_get_subject_name(cert)); + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(eccRsaCertFile, + SSL_FILETYPE_PEM)); + AssertIntEQ(wolfSSL_X509_NAME_cmp((const WOLFSSL_X509_NAME*)subject, + (const WOLFSSL_X509_NAME*)wolfSSL_X509_get_subject_name(x509)), 0); + X509_free(x509); + + /* test expected fail case */ + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(eccCertFile, + SSL_FILETYPE_PEM)); + AssertIntNE(wolfSSL_X509_NAME_cmp((const WOLFSSL_X509_NAME*)subject, + (const WOLFSSL_X509_NAME*)wolfSSL_X509_get_subject_name(x509)), 0); + X509_free(x509); + X509_free(cert); + + /* get subject line from ca stack */ + AssertNotNull(cert = sk_X509_pop(ca)); + AssertNotNull(subject = wolfSSL_X509_get_subject_name(cert)); + + /* compare subject from certificate in ca to expected */ + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(eccCertFile, + SSL_FILETYPE_PEM)); + AssertIntEQ(wolfSSL_X509_NAME_cmp((const WOLFSSL_X509_NAME*)subject, + (const WOLFSSL_X509_NAME*)wolfSSL_X509_get_subject_name(x509)), 0); + + EVP_PKEY_free(pkey); + X509_free(x509); + X509_free(cert); + BIO_free(bio); + PKCS12_free(pkcs12); + sk_X509_free(ca); /* TEST d2i_PKCS12_fp */ + + /* test order of parsing */ + f = XFOPEN(file, "rb"); + AssertTrue(f != XBADFILE); + AssertNotNull(pkcs12 = d2i_PKCS12_fp(f, NULL)); + XFCLOSE(f); + + /* check verify MAC fail case */ + ret = PKCS12_parse(pkcs12, "bad", &pkey, &cert, NULL); + AssertIntEQ(ret, 0); + AssertNull(pkey); + AssertNull(cert); + + /* check parse with no extra certs kept */ + ret = PKCS12_parse(pkcs12, "wolfSSL test", &pkey, &cert, NULL); + AssertIntEQ(ret, 1); + AssertNotNull(pkey); + AssertNotNull(cert); + + wolfSSL_EVP_PKEY_free(pkey); + wolfSSL_X509_free(cert); + + /* check parse with extra certs kept */ + ret = PKCS12_parse(pkcs12, "wolfSSL test", &pkey, &cert, &ca); + AssertIntEQ(ret, 1); + AssertNotNull(pkey); + AssertNotNull(cert); + AssertNotNull(ca); + + wolfSSL_EVP_PKEY_free(pkey); + wolfSSL_X509_free(cert); + sk_X509_free(ca); + + PKCS12_free(pkcs12); +#endif /* HAVE_ECC */ + + /* Test i2d_PKCS12_bio */ + f = XFOPEN(file, "rb"); + AssertTrue((f != XBADFILE)); + AssertNotNull(pkcs12 = d2i_PKCS12_fp(f, NULL)); + XFCLOSE(f); + + bio = BIO_new(BIO_s_mem()); + AssertNotNull(bio); + + ret = i2d_PKCS12_bio(bio, pkcs12); + AssertIntEQ(ret, 1); + + ret = i2d_PKCS12_bio(NULL, pkcs12); + AssertIntEQ(ret, 0); + + ret = i2d_PKCS12_bio(bio, NULL); + AssertIntEQ(ret, 0); + + PKCS12_free(pkcs12); + BIO_free(bio); + + (void)order; + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +#endif /* HAVE_FIPS */ +} + + +#if !defined(NO_FILESYSTEM) && !defined(NO_ASN) && defined(HAVE_PKCS8) && \ + defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_DES3) && !defined(NO_PWDBASED) && \ + (!defined(NO_RSA) || defined(HAVE_ECC)) && !defined(NO_MD5) + #define TEST_PKCS8_ENC +#endif + +#if !defined(NO_FILESYSTEM) && !defined(NO_ASN) && defined(HAVE_PKCS8) \ + && defined(HAVE_ECC) && defined(WOLFSSL_ENCRYPTED_KEYS) +static WC_INLINE int FailTestCallBack(char* passwd, int sz, int rw, void* userdata) +{ + (void)passwd; + (void)sz; + (void)rw; + (void)userdata; + Fail(("Password callback should not be called by default"), + ("Password callback was called without attempting " + "to first decipher private key without password.")); + return 0; +} +#endif + +static void test_wolfSSL_no_password_cb(void) +{ +#if !defined(NO_FILESYSTEM) && !defined(NO_ASN) && defined(HAVE_PKCS8) \ + && defined(HAVE_ECC) && defined(WOLFSSL_ENCRYPTED_KEYS) + WOLFSSL_CTX* ctx; + byte buffer[FOURK_BUF]; + const char eccPkcs8PrivKeyDerFile[] = "./certs/ecc-privkeyPkcs8.der"; + const char eccPkcs8PrivKeyPemFile[] = "./certs/ecc-privkeyPkcs8.pem"; + XFILE f; + int bytes; + + printf(testingFmt, "test_wolfSSL_no_password_cb()"); + +#ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLS_client_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLS_server_method())); +#endif + wolfSSL_CTX_set_default_passwd_cb(ctx, FailTestCallBack); + + AssertTrue((f = XFOPEN(eccPkcs8PrivKeyDerFile, "rb")) != XBADFILE); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + AssertIntLE(bytes, sizeof(buffer)); + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + AssertTrue((f = XFOPEN(eccPkcs8PrivKeyPemFile, "rb")) != XBADFILE); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + AssertIntLE(bytes, sizeof(buffer)); + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + + wolfSSL_CTX_free(ctx); + + printf(resultFmt, passed); +#endif +} + +#ifdef TEST_PKCS8_ENC +/* for PKCS8 test case */ +static int PKCS8TestCallBack(char* passwd, int sz, int rw, void* userdata) +{ + int flag = 0; + + (void)rw; + if (userdata != NULL) { + flag = *((int*)userdata); /* user set data */ + } + + switch (flag) { + case 1: /* flag set for specific WOLFSSL_CTX structure, note userdata + * can be anything the user wishes to be passed to the callback + * associated with the WOLFSSL_CTX */ + XSTRNCPY(passwd, "yassl123", sz); + return 8; + + default: + return BAD_FUNC_ARG; + } +} +#endif /* TEST_PKCS8_ENC */ + +/* Testing functions dealing with PKCS8 */ +static void test_wolfSSL_PKCS8(void) +{ +#if !defined(NO_FILESYSTEM) && !defined(NO_ASN) && defined(HAVE_PKCS8) + byte buffer[FOURK_BUF]; + byte der[FOURK_BUF]; + #ifndef NO_RSA + const char serverKeyPkcs8PemFile[] = "./certs/server-keyPkcs8.pem"; + const char serverKeyPkcs8DerFile[] = "./certs/server-keyPkcs8.der"; + #endif + const char eccPkcs8PrivKeyPemFile[] = "./certs/ecc-privkeyPkcs8.pem"; + #ifdef HAVE_ECC + const char eccPkcs8PrivKeyDerFile[] = "./certs/ecc-privkeyPkcs8.der"; + #endif + XFILE f; + int bytes; + WOLFSSL_CTX* ctx; +#ifdef HAVE_ECC + int ret; + ecc_key key; + word32 x = 0; +#endif +#ifdef TEST_PKCS8_ENC + #if !defined(NO_RSA) && !defined(NO_SHA) + const char serverKeyPkcs8EncPemFile[] = "./certs/server-keyPkcs8Enc.pem"; + const char serverKeyPkcs8EncDerFile[] = "./certs/server-keyPkcs8Enc.der"; + #endif + #if defined(HAVE_ECC) && !defined(NO_SHA) + const char eccPkcs8EncPrivKeyPemFile[] = "./certs/ecc-keyPkcs8Enc.pem"; + const char eccPkcs8EncPrivKeyDerFile[] = "./certs/ecc-keyPkcs8Enc.der"; + #endif + int flag; +#endif + + printf(testingFmt, "wolfSSL_PKCS8()"); + +#ifndef NO_WOLFSSL_CLIENT + #ifndef WOLFSSL_NO_TLS12 + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())); + #else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); + #endif +#else + #ifndef WOLFSSL_NO_TLS12 + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())); + #else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); + #endif +#endif + +#ifdef TEST_PKCS8_ENC + wolfSSL_CTX_set_default_passwd_cb(ctx, PKCS8TestCallBack); + wolfSSL_CTX_set_default_passwd_cb_userdata(ctx, (void*)&flag); + flag = 1; /* used by password callback as return code */ + + #if !defined(NO_RSA) && !defined(NO_SHA) + /* test loading PEM PKCS8 encrypted file */ + f = XFOPEN(serverKeyPkcs8EncPemFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + + /* this next case should fail because of password callback return code */ + flag = 0; /* used by password callback as return code */ + AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + + /* decrypt PKCS8 PEM to key in DER format with not using WOLFSSL_CTX */ + AssertIntGT(wc_KeyPemToDer(buffer, bytes, der, (word32)sizeof(der), + "yassl123"), 0); + + /* test that error value is returned with a bad password */ + AssertIntLT(wc_KeyPemToDer(buffer, bytes, der, (word32)sizeof(der), + "bad"), 0); + + /* test loading PEM PKCS8 encrypted file */ + f = XFOPEN(serverKeyPkcs8EncDerFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + flag = 1; /* used by password callback as return code */ + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + /* this next case should fail because of password callback return code */ + flag = 0; /* used by password callback as return code */ + AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + #endif /* !NO_RSA && !NO_SHA */ + + #if defined(HAVE_ECC) && !defined(NO_SHA) + /* test loading PEM PKCS8 encrypted ECC Key file */ + f = XFOPEN(eccPkcs8EncPrivKeyPemFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + flag = 1; /* used by password callback as return code */ + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + + /* this next case should fail because of password callback return code */ + flag = 0; /* used by password callback as return code */ + AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + + /* decrypt PKCS8 PEM to key in DER format with not using WOLFSSL_CTX */ + AssertIntGT(wc_KeyPemToDer(buffer, bytes, der, (word32)sizeof(der), + "yassl123"), 0); + + /* test that error value is returned with a bad password */ + AssertIntLT(wc_KeyPemToDer(buffer, bytes, der, (word32)sizeof(der), + "bad"), 0); + + /* test loading DER PKCS8 encrypted ECC Key file */ + f = XFOPEN(eccPkcs8EncPrivKeyDerFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + flag = 1; /* used by password callback as return code */ + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + /* this next case should fail because of password callback return code */ + flag = 0; /* used by password callback as return code */ + AssertIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + /* leave flag as "okay" */ + flag = 1; + #endif /* HAVE_ECC && !NO_SHA */ +#endif /* TEST_PKCS8_ENC */ + + +#ifndef NO_RSA + /* test loading ASN.1 (DER) PKCS8 private key file (not encrypted) */ + f = XFOPEN(serverKeyPkcs8DerFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + /* test loading PEM PKCS8 private key file (not encrypted) */ + f = XFOPEN(serverKeyPkcs8PemFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); +#endif /* !NO_RSA */ + + /* Test PKCS8 PEM ECC key no crypt */ + f = XFOPEN(eccPkcs8PrivKeyPemFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); +#ifdef HAVE_ECC + /* Test PKCS8 PEM ECC key no crypt */ + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + + /* decrypt PKCS8 PEM to key in DER format */ + AssertIntGT((bytes = wc_KeyPemToDer(buffer, bytes, der, + (word32)sizeof(der), NULL)), 0); + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_EccPrivateKeyDecode(der, &x, &key, bytes); + wc_ecc_free(&key); + } + AssertIntEQ(ret, 0); + + /* Test PKCS8 DER ECC key no crypt */ + f = XFOPEN(eccPkcs8PrivKeyDerFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + + /* Test using a PKCS8 ECC PEM */ + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buffer, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); +#else + /* if HAVE_ECC is not defined then BEGIN EC PRIVATE KEY is not found */ + AssertIntEQ((bytes = wc_KeyPemToDer(buffer, bytes, der, + (word32)sizeof(der), NULL)), ASN_NO_PEM_HEADER); +#endif /* HAVE_ECC */ + + wolfSSL_CTX_free(ctx); + + printf(resultFmt, passed); +#endif /* !NO_FILESYSTEM && !NO_ASN && HAVE_PKCS8 */ +} + +static void test_wolfSSL_PKCS8_ED25519(void) +{ +#if !defined(NO_ASN) && defined(HAVE_PKCS8) && \ + defined(WOLFSSL_ENCRYPTED_KEYS) && defined(HAVE_ED25519) + const byte encPrivKey[] = \ + "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" + "MIGbMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAheCGLmWGh7+AICCAAw\n" + "DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEC4L5P6GappsTyhOOoQfvh8EQJMX\n" + "OAdlsYKCOcFo4djg6AI1lRdeBRwVFWkha7gBdoCJOzS8wDvTbYcJMPvANu5ft3nl\n" + "2L9W4v7swXkV+X+a1ww=\n" + "-----END ENCRYPTED PRIVATE KEY-----\n"; + const char password[] = "abcdefghijklmnopqrstuvwxyz"; + byte der[FOURK_BUF]; + WOLFSSL_CTX* ctx; + int bytes; + + XMEMSET(der, 0, sizeof(der)); + AssertIntGT((bytes = wc_KeyPemToDer(encPrivKey, sizeof(encPrivKey), der, + (word32)sizeof(der), password)), 0); +#ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#endif + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + wolfSSL_CTX_free(ctx); +#endif +} + +static void test_wolfSSL_PKCS8_ED448(void) +{ +#if !defined(NO_ASN) && defined(HAVE_PKCS8) && \ + defined(WOLFSSL_ENCRYPTED_KEYS) && defined(HAVE_ED448) + const byte encPrivKey[] = \ + "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" + "MIGrMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAjSbZKnG4EPggICCAAw\n" + "DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEFvCFWBBHBlJBsYleBJlJWcEUNC7\n" + "Tf5pZviT5Btar4D/MNg6BsQHSDf5KW4ix871EsgDY2Zz+euaoWspiMntz7gU+PQu\n" + "T/JJcbD2Ly8BbE3l5WHMifAQqNLxJBfXrHkfYtAo\n" + "-----END ENCRYPTED PRIVATE KEY-----\n"; + const char password[] = "abcdefghijklmnopqrstuvwxyz"; + byte der[FOURK_BUF]; + WOLFSSL_CTX* ctx; + int bytes; + + XMEMSET(der, 0, sizeof(der)); + AssertIntGT((bytes = wc_KeyPemToDer(encPrivKey, sizeof(encPrivKey), der, + (word32)sizeof(der), password)), 0); +#ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#endif + AssertIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, bytes, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + wolfSSL_CTX_free(ctx); +#endif +} + +/* Testing functions dealing with PKCS5 */ +static void test_wolfSSL_PKCS5(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_SHA) && !defined(NO_PWDBASED) +#ifdef HAVE_FIPS /* Password minimum length is 14 (112-bit) in FIPS MODE */ + const char* passwd = "myfipsPa$$W0rd"; +#else + const char *passwd = "pass1234"; +#endif + 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); + +#ifdef WOLFSSL_SHA512 + ret = PKCS5_PBKDF2_HMAC(passwd,(int)XSTRLEN(passwd), salt, + (int)XSTRLEN((const char *) salt), 10, + wolfSSL_EVP_sha512(), WC_SHA_DIGEST_SIZE, out); + AssertIntEQ(ret, SSL_SUCCESS); +#endif + + XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_SHA) */ +} + +/* test parsing URI from certificate */ +static void test_wolfSSL_URI(void) +{ +#if !defined(NO_CERTS) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) \ + && (defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \ + defined(OPENSSL_EXTRA)) + WOLFSSL_X509* x509; + const char uri[] = "./certs/client-uri-cert.pem"; + const char badUri[] = "./certs/client-relative-uri.pem"; + + printf(testingFmt, "wolfSSL URI parse"); + + x509 = wolfSSL_X509_load_certificate_file(uri, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + + wolfSSL_FreeX509(x509); + + x509 = wolfSSL_X509_load_certificate_file(badUri, WOLFSSL_FILETYPE_PEM); +#ifndef IGNORE_NAME_CONSTRAINTS + AssertNull(x509); +#else + AssertNotNull(x509); +#endif + + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_TBS(void) +{ +#if !defined(NO_CERTS) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) \ + && defined(OPENSSL_EXTRA) + WOLFSSL_X509* x509; + const unsigned char* tbs; + int tbsSz; + + printf(testingFmt, "wolfSSL TBS"); + + AssertNotNull(x509 = + wolfSSL_X509_load_certificate_file(caCertFile, WOLFSSL_FILETYPE_PEM)); + + AssertNull(tbs = wolfSSL_X509_get_tbs(NULL, &tbsSz)); + AssertNull(tbs = wolfSSL_X509_get_tbs(x509, NULL)); + AssertNotNull(tbs = wolfSSL_X509_get_tbs(x509, &tbsSz)); + AssertIntEQ(tbsSz, 918); + + wolfSSL_FreeX509(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_verify(void) +{ +#if !defined(NO_CERTS) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) \ + && defined(OPENSSL_EXTRA) + WOLFSSL_X509* ca; + WOLFSSL_X509* server; + WOLFSSL_EVP_PKEY* pkey; + unsigned char buf[2048]; + const unsigned char* pt; + int bufSz; + + printf(testingFmt, "wolfSSL X509 verify"); + + AssertNotNull(ca = + wolfSSL_X509_load_certificate_file(caCertFile, WOLFSSL_FILETYPE_PEM)); + + AssertIntNE(wolfSSL_X509_get_pubkey_buffer(NULL, buf, &bufSz), + WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_X509_get_pubkey_buffer(ca, NULL, &bufSz), + WOLFSSL_SUCCESS); + AssertIntEQ(bufSz, 294); + + bufSz = 2048; + AssertIntEQ(wolfSSL_X509_get_pubkey_buffer(ca, buf, &bufSz), + WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_X509_get_pubkey_type(NULL), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_X509_get_pubkey_type(ca), RSAk); + + + AssertNotNull(server = + wolfSSL_X509_load_certificate_file(svrCertFile, WOLFSSL_FILETYPE_PEM)); + + /* success case */ + pt = buf; + AssertNotNull(pkey = wolfSSL_d2i_PUBKEY(NULL, &pt, bufSz)); + AssertIntEQ(wolfSSL_X509_verify(server, pkey), WOLFSSL_SUCCESS); + wolfSSL_EVP_PKEY_free(pkey); + + /* fail case */ + bufSz = 2048; + AssertIntEQ(wolfSSL_X509_get_pubkey_buffer(server, buf, &bufSz), + WOLFSSL_SUCCESS); + pt = buf; + AssertNotNull(pkey = wolfSSL_d2i_PUBKEY(NULL, &pt, bufSz)); + AssertIntEQ(wolfSSL_X509_verify(server, pkey), WOLFSSL_FAILURE); + + AssertIntEQ(wolfSSL_X509_verify(NULL, pkey), WOLFSSL_FATAL_ERROR); + AssertIntEQ(wolfSSL_X509_verify(server, NULL), WOLFSSL_FATAL_ERROR); + wolfSSL_EVP_PKEY_free(pkey); + + wolfSSL_FreeX509(ca); + wolfSSL_FreeX509(server); + + printf(resultFmt, passed); +#endif +} +/* Testing function wolfSSL_CTX_SetMinVersion; sets the minimum downgrade + * version allowed. + * POST: 1 on success. + */ +static int test_wolfSSL_CTX_SetMinVersion(void) +{ + int failFlag = WOLFSSL_SUCCESS; +#ifndef NO_WOLFSSL_CLIENT + WOLFSSL_CTX* ctx; + int itr; + + #ifndef NO_OLD_TLS + const int versions[] = { + #ifdef WOLFSSL_ALLOW_TLSV10 + WOLFSSL_TLSV1, + #endif + WOLFSSL_TLSV1_1, + WOLFSSL_TLSV1_2 }; + #elif !defined(WOLFSSL_NO_TLS12) + const int versions[] = { WOLFSSL_TLSV1_2 }; + #elif defined(WOLFSSL_TLS13) + const int versions[] = { WOLFSSL_TLSV1_3 }; + #else + const int versions[0]; + #endif + + ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + + printf(testingFmt, "wolfSSL_CTX_SetMinVersion()"); + + for (itr = 0; itr < (int)(sizeof(versions)/sizeof(int)); itr++){ + if(wolfSSL_CTX_SetMinVersion(ctx, *(versions + itr)) != WOLFSSL_SUCCESS){ + failFlag = WOLFSSL_FAILURE; + } + } + + printf(resultFmt, failFlag == WOLFSSL_SUCCESS ? passed : failed); + + wolfSSL_CTX_free(ctx); +#endif + return failFlag; + +} /* END test_wolfSSL_CTX_SetMinVersion */ + + +/*----------------------------------------------------------------------------* + | OCSP Stapling + *----------------------------------------------------------------------------*/ + + +/* Testing wolfSSL_UseOCSPStapling function. OCSP stapling eliminates the need + * need to contact the CA, lowering the cost of cert revocation checking. + * PRE: HAVE_OCSP and HAVE_CERTIFICATE_STATUS_REQUEST + * POST: 1 returned for success. + */ +static int test_wolfSSL_UseOCSPStapling(void) +{ + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) && defined(HAVE_OCSP) && \ + !defined(NO_WOLFSSL_CLIENT) + int ret; + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + +#ifndef NO_WOLFSSL_CLIENT + #ifndef WOLFSSL_NO_TLS12 + ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + #else + ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); + #endif +#else + #ifndef WOLFSSL_NO_TLS12 + ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()); + #else + ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); + #endif +#endif + ssl = wolfSSL_new(ctx); + printf(testingFmt, "wolfSSL_UseOCSPStapling()"); + + ret = wolfSSL_UseOCSPStapling(ssl, WOLFSSL_CSR2_OCSP, + WOLFSSL_CSR2_OCSP_USE_NONCE); + + printf(resultFmt, ret == WOLFSSL_SUCCESS ? passed : failed); + + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + + return ret; + #else + return WOLFSSL_SUCCESS; + #endif + +} /*END test_wolfSSL_UseOCSPStapling */ + + +/* Testing OCSP stapling version 2, wolfSSL_UseOCSPStaplingV2 function. OCSP + * stapling eliminates the need to contact the CA and lowers cert revocation + * check. + * PRE: HAVE_CERTIFICATE_STATUS_REQUEST_V2 and HAVE_OCSP defined. + */ +static int test_wolfSSL_UseOCSPStaplingV2 (void) +{ + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && defined(HAVE_OCSP) && \ + !defined(NO_WOLFSSL_CLIENT) + int ret; + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + +#ifndef NO_WOLFSSL_CLIENT + #ifndef WOLFSSL_NO_TLS12 + ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + #else + ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); + #endif +#else + #ifndef WOLFSSL_NO_TLS12 + ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()); + #else + ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); + #endif +#endif + ssl = wolfSSL_new(ctx); + printf(testingFmt, "wolfSSL_UseOCSPStaplingV2()"); + + ret = wolfSSL_UseOCSPStaplingV2(ssl, WOLFSSL_CSR2_OCSP, + WOLFSSL_CSR2_OCSP_USE_NONCE ); + + printf(resultFmt, ret == WOLFSSL_SUCCESS ? passed : failed); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + + return ret; + #else + 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_InitBlake2b() + */ +static int test_wc_InitBlake2b (void) +{ + int ret = 0; +#ifdef HAVE_BLAKE2 + + Blake2b blake2; + + printf(testingFmt, "wc_InitBlake2B()"); + + /* Test good arg. */ + ret = wc_InitBlake2b(&blake2, 64); + if (ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!ret) { + ret = wc_InitBlake2b(NULL, 64); + if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } + + if (!ret) { + ret = wc_InitBlake2b(NULL, 128); + if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } + + if (!ret) { + ret = wc_InitBlake2b(&blake2, 128); + if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } + + if (!ret) { + ret = wc_InitBlake2b(NULL, 0); + if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } + + if (!ret) { + ret = wc_InitBlake2b(&blake2, 0); + if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +} /*END test_wc_InitBlake2b*/ + + +/* + * 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); + + 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); + + 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); + + 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); + + ret = wc_Sha512Update(&sha512, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + + 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); + + 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); + + 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); + + 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 */ + + + + + +/* + * Testing wc_InitSha3_224, wc_InitSha3_256, wc_InitSha3_384, and + * wc_InitSha3_512 + */ +static int test_wc_InitSha3 (void) +{ + int ret = 0; +#if defined(WOLFSSL_SHA3) + wc_Sha3 sha3; + + (void)sha3; + + #if !defined(WOLFSSL_NOSHA3_224) + printf(testingFmt, "wc_InitSha3_224()"); + + ret = wc_InitSha3_224(&sha3, HEAP_HINT, devId); + + /* Test bad args. */ + if (ret == 0) { + ret = wc_InitSha3_224(NULL, HEAP_HINT, devId); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + wc_Sha3_224_Free(&sha3); + printf(resultFmt, ret == 0 ? passed : failed); + #endif /* NOSHA3_224 */ + #if !defined(WOLFSSL_NOSHA3_256) + if (ret == 0) { + printf(testingFmt, "wc_InitSha3_256()"); + + ret = wc_InitSha3_256(&sha3, HEAP_HINT, devId); + /* Test bad args. */ + if (ret == 0) { + ret = wc_InitSha3_256(NULL, HEAP_HINT, devId); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + wc_Sha3_256_Free(&sha3); + printf(resultFmt, ret == 0 ? passed : failed); + } /* END sha3_256 */ + #endif /* NOSHA3_256 */ + #if !defined(WOLFSSL_NOSHA3_384) + if (ret == 0) { + printf(testingFmt, "wc_InitSha3_384()"); + + ret = wc_InitSha3_384(&sha3, HEAP_HINT, devId); + /* Test bad args. */ + if (ret == 0) { + ret = wc_InitSha3_384(NULL, HEAP_HINT, devId); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + wc_Sha3_384_Free(&sha3); + printf(resultFmt, ret == 0 ? passed : failed); + } /* END sha3_384 */ + #endif /* NOSHA3_384 */ + #if !defined(WOLFSSL_NOSHA3_512) + if (ret == 0) { + printf(testingFmt, "wc_InitSha3_512()"); + + ret = wc_InitSha3_512(&sha3, HEAP_HINT, devId); + /* Test bad args. */ + if (ret == 0) { + ret = wc_InitSha3_512(NULL, HEAP_HINT, devId); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + wc_Sha3_512_Free(&sha3); + printf(resultFmt, ret == 0 ? passed : failed); + } /* END sha3_512 */ + #endif /* NOSHA3_512 */ +#endif + return ret; + +} /* END test_wc_InitSha3 */ + + +/* + * Testing wc_Sha3_Update() + */ +static int testing_wc_Sha3_Update (void) +{ + int ret = 0; + +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_XILINX_CRYPT) && \ + !defined(WOLFSSL_AFALG_XILINX) + wc_Sha3 sha3; + byte msg[] = "Everybody's working for the weekend."; + byte msg2[] = "Everybody gets Friday off."; + byte msgCmp[] = "\x45\x76\x65\x72\x79\x62\x6f\x64\x79\x27\x73\x20" + "\x77\x6f\x72\x6b\x69\x6e\x67\x20\x66\x6f\x72\x20\x74" + "\x68\x65\x20\x77\x65\x65\x6b\x65\x6e\x64\x2e\x45\x76" + "\x65\x72\x79\x62\x6f\x64\x79\x20\x67\x65\x74\x73\x20" + "\x46\x72\x69\x64\x61\x79\x20\x6f\x66\x66\x2e"; + word32 msglen = sizeof(msg) - 1; + word32 msg2len = sizeof(msg2); + word32 msgCmplen = sizeof(msgCmp); + + #if !defined(WOLFSSL_NOSHA3_224) + printf(testingFmt, "wc_Sha3_224_Update()"); + + ret = wc_InitSha3_224(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + + ret = wc_Sha3_224_Update(&sha3, msg, msglen); + if (XMEMCMP(msg, sha3.t, msglen) || sha3.i != msglen) { + ret = WOLFSSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_Sha3_224_Update(&sha3, msg2, msg2len); + if (ret == 0 && XMEMCMP(sha3.t, msgCmp, msgCmplen) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Pass bad args. */ + if (ret == 0) { + ret = wc_Sha3_224_Update(NULL, msg2, msg2len); + if (ret == BAD_FUNC_ARG) { + ret = wc_Sha3_224_Update(&sha3, NULL, 5); + } + if (ret == BAD_FUNC_ARG) { + wc_Sha3_224_Free(&sha3); + if (wc_InitSha3_224(&sha3, HEAP_HINT, devId)) { + return ret; + } + ret = wc_Sha3_224_Update(&sha3, NULL, 0); + if (ret == 0) { + ret = wc_Sha3_224_Update(&sha3, msg2, msg2len); + } + if (ret == 0 && XMEMCMP(msg2, sha3.t, msg2len) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + wc_Sha3_224_Free(&sha3); + + printf(resultFmt, ret == 0 ? passed : failed); + #endif /* SHA3_224 */ + + #if !defined(WOLFSSL_NOSHA3_256) + if (ret == 0) { + printf(testingFmt, "wc_Sha3_256_Update()"); + + ret = wc_InitSha3_256(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + ret = wc_Sha3_256_Update(&sha3, msg, msglen); + if (XMEMCMP(msg, sha3.t, msglen) || sha3.i != msglen) { + ret = WOLFSSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_Sha3_256_Update(&sha3, msg2, msg2len); + if (XMEMCMP(sha3.t, msgCmp, msgCmplen) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Pass bad args. */ + if (ret == 0) { + ret = wc_Sha3_256_Update(NULL, msg2, msg2len); + if (ret == BAD_FUNC_ARG) { + ret = wc_Sha3_256_Update(&sha3, NULL, 5); + } + if (ret == BAD_FUNC_ARG) { + wc_Sha3_256_Free(&sha3); + if (wc_InitSha3_256(&sha3, HEAP_HINT, devId)) { + return ret; + } + ret = wc_Sha3_256_Update(&sha3, NULL, 0); + if (ret == 0) { + ret = wc_Sha3_256_Update(&sha3, msg2, msg2len); + } + if (ret == 0 && XMEMCMP(msg2, sha3.t, msg2len) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + wc_Sha3_256_Free(&sha3); + + printf(resultFmt, ret == 0 ? passed : failed); + } + #endif /* SHA3_256 */ + + #if !defined(WOLFSSL_NOSHA3_384) + if (ret == 0) { + printf(testingFmt, "wc_Sha3_384_Update()"); + + ret = wc_InitSha3_384(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + ret = wc_Sha3_384_Update(&sha3, msg, msglen); + if (XMEMCMP(msg, sha3.t, msglen) || sha3.i != msglen) { + ret = WOLFSSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_Sha3_384_Update(&sha3, msg2, msg2len); + if (XMEMCMP(sha3.t, msgCmp, msgCmplen) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Pass bad args. */ + if (ret == 0) { + ret = wc_Sha3_384_Update(NULL, msg2, msg2len); + if (ret == BAD_FUNC_ARG) { + ret = wc_Sha3_384_Update(&sha3, NULL, 5); + } + if (ret == BAD_FUNC_ARG) { + wc_Sha3_384_Free(&sha3); + if (wc_InitSha3_384(&sha3, HEAP_HINT, devId)) { + return ret; + } + ret = wc_Sha3_384_Update(&sha3, NULL, 0); + if (ret == 0) { + ret = wc_Sha3_384_Update(&sha3, msg2, msg2len); + } + if (ret == 0 && XMEMCMP(msg2, sha3.t, msg2len) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + wc_Sha3_384_Free(&sha3); + + printf(resultFmt, ret == 0 ? passed : failed); + } + #endif /* SHA3_384 */ + + #if !defined(WOLFSSL_NOSHA3_512) + if (ret == 0) { + printf(testingFmt, "wc_Sha3_512_Update()"); + + ret = wc_InitSha3_512(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + ret = wc_Sha3_512_Update(&sha3, msg, msglen); + if (XMEMCMP(msg, sha3.t, msglen) || sha3.i != msglen) { + ret = WOLFSSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_Sha3_512_Update(&sha3, msg2, msg2len); + if (XMEMCMP(sha3.t, msgCmp, msgCmplen) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Pass bad args. */ + if (ret == 0) { + ret = wc_Sha3_512_Update(NULL, msg2, msg2len); + if (ret == BAD_FUNC_ARG) { + ret = wc_Sha3_512_Update(&sha3, NULL, 5); + } + if (ret == BAD_FUNC_ARG) { + wc_Sha3_512_Free(&sha3); + if (wc_InitSha3_512(&sha3, HEAP_HINT, devId)) { + return ret; + } + ret = wc_Sha3_512_Update(&sha3, NULL, 0); + if (ret == 0) { + ret = wc_Sha3_512_Update(&sha3, msg2, msg2len); + } + if (ret == 0 && XMEMCMP(msg2, sha3.t, msg2len) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + wc_Sha3_512_Free(&sha3); + printf(resultFmt, ret == 0 ? passed : failed); + } + #endif /* SHA3_512 */ +#endif /* WOLFSSL_SHA3 */ + return ret; + +} /* END testing_wc_Sha3_Update */ + +/* + * Testing wc_Sha3_224_Final() + */ +static int test_wc_Sha3_224_Final (void) +{ + int ret = 0; + +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + wc_Sha3 sha3; + const char* msg = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnom" + "nopnopq"; + const char* expOut = "\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"; + byte hash[WC_SHA3_224_DIGEST_SIZE]; + byte hashRet[WC_SHA3_224_DIGEST_SIZE]; + + /* Init stack variables. */ + XMEMSET(hash, 0, sizeof(hash)); + + printf(testingFmt, "wc_Sha3_224_Final()"); + + ret = wc_InitSha3_224(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + + ret= wc_Sha3_224_Update(&sha3, (byte*)msg, (word32)XSTRLEN(msg)); + if (ret == 0) { + ret = wc_Sha3_224_Final(&sha3, hash); + if (ret == 0 && XMEMCMP(expOut, hash, WC_SHA3_224_DIGEST_SIZE) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_Sha3_224_Final(NULL, hash); + if (ret == 0) { + ret = wc_Sha3_224_Final(&sha3, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + wc_Sha3_224_Free(&sha3); + printf(resultFmt, ret == 0 ? passed : failed); + + if (ret == 0) { + printf(testingFmt, "wc_Sha3_224_GetHash()"); + + ret = wc_InitSha3_224(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + + /* Init stack variables. */ + XMEMSET(hash, 0, sizeof(hash)); + XMEMSET(hashRet, 0, sizeof(hashRet)); + + ret= wc_Sha3_224_Update(&sha3, (byte*)msg, (word32)XSTRLEN(msg)); + if (ret == 0) { + ret = wc_Sha3_224_GetHash(&sha3, hashRet); + } + + if (ret == 0) { + ret = wc_Sha3_224_Final(&sha3, hash); + if (ret == 0 && XMEMCMP(hash, hashRet, WC_SHA3_224_DIGEST_SIZE) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (ret == 0) { + /* Test bad args. */ + ret = wc_Sha3_224_GetHash(NULL, hashRet); + if (ret == BAD_FUNC_ARG) { + ret = wc_Sha3_224_GetHash(&sha3, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + } + + wc_Sha3_224_Free(&sha3); +#endif + return ret; +} /* END test_wc_Sha3_224_Final */ + + +/* + * Testing wc_Sha3_256_Final() + */ +static int test_wc_Sha3_256_Final (void) +{ + int ret = 0; + +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + wc_Sha3 sha3; + const char* msg = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnom" + "nopnopq"; + const char* expOut = "\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"; + byte hash[WC_SHA3_256_DIGEST_SIZE]; + byte hashRet[WC_SHA3_256_DIGEST_SIZE]; + + /* Init stack variables. */ + XMEMSET(hash, 0, sizeof(hash)); + + printf(testingFmt, "wc_Sha3_256_Final()"); + + ret = wc_InitSha3_256(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + + ret= wc_Sha3_256_Update(&sha3, (byte*)msg, (word32)XSTRLEN(msg)); + if (ret == 0) { + ret = wc_Sha3_256_Final(&sha3, hash); + if (ret == 0 && XMEMCMP(expOut, hash, WC_SHA3_256_DIGEST_SIZE) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_Sha3_256_Final(NULL, hash); + if (ret == 0) { + ret = wc_Sha3_256_Final(&sha3, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + wc_Sha3_256_Free(&sha3); + printf(resultFmt, ret == 0 ? passed : failed); + + if (ret == 0) { + printf(testingFmt, "wc_Sha3_256_GetHash()"); + + ret = wc_InitSha3_256(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + /* Init stack variables. */ + XMEMSET(hash, 0, sizeof(hash)); + XMEMSET(hashRet, 0, sizeof(hashRet)); + + ret= wc_Sha3_256_Update(&sha3, (byte*)msg, (word32)XSTRLEN(msg)); + if (ret == 0) { + ret = wc_Sha3_256_GetHash(&sha3, hashRet); + } + if (ret == 0) { + ret = wc_Sha3_256_Final(&sha3, hash); + if (ret == 0 && XMEMCMP(hash, hashRet, WC_SHA3_256_DIGEST_SIZE) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (ret == 0) { + /* Test bad args. */ + ret = wc_Sha3_256_GetHash(NULL, hashRet); + if (ret == BAD_FUNC_ARG) { + ret = wc_Sha3_256_GetHash(&sha3, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + } + + wc_Sha3_256_Free(&sha3); +#endif + return ret; +} /* END test_wc_Sha3_256_Final */ + + +/* + * Testing wc_Sha3_384_Final() + */ +static int test_wc_Sha3_384_Final (void) +{ + int ret = 0; + +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + wc_Sha3 sha3; + const char* msg = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnom" + "nopnopq"; + const char* expOut = "\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"; + byte hash[WC_SHA3_384_DIGEST_SIZE]; + byte hashRet[WC_SHA3_384_DIGEST_SIZE]; + + /* Init stack variables. */ + XMEMSET(hash, 0, sizeof(hash)); + + printf(testingFmt, "wc_Sha3_384_Final()"); + + ret = wc_InitSha3_384(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + + ret= wc_Sha3_384_Update(&sha3, (byte*)msg, (word32)XSTRLEN(msg)); + if (ret == 0) { + ret = wc_Sha3_384_Final(&sha3, hash); + if (ret == 0 && XMEMCMP(expOut, hash, WC_SHA3_384_DIGEST_SIZE) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_Sha3_384_Final(NULL, hash); + if (ret == 0) { + ret = wc_Sha3_384_Final(&sha3, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + wc_Sha3_384_Free(&sha3); + printf(resultFmt, ret == 0 ? passed : failed); + + if (ret == 0) { + printf(testingFmt, "wc_Sha3_384_GetHash()"); + + ret = wc_InitSha3_384(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + /* Init stack variables. */ + XMEMSET(hash, 0, sizeof(hash)); + XMEMSET(hashRet, 0, sizeof(hashRet)); + + ret= wc_Sha3_384_Update(&sha3, (byte*)msg, (word32)XSTRLEN(msg)); + if (ret == 0) { + ret = wc_Sha3_384_GetHash(&sha3, hashRet); + } + if (ret == 0) { + ret = wc_Sha3_384_Final(&sha3, hash); + if (ret == 0 && XMEMCMP(hash, hashRet, WC_SHA3_384_DIGEST_SIZE) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (ret == 0) { + /* Test bad args. */ + ret = wc_Sha3_384_GetHash(NULL, hashRet); + if (ret == BAD_FUNC_ARG) { + ret = wc_Sha3_384_GetHash(&sha3, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + } + + wc_Sha3_384_Free(&sha3); +#endif + return ret; +} /* END test_wc_Sha3_384_Final */ + + + +/* + * Testing wc_Sha3_512_Final() + */ +static int test_wc_Sha3_512_Final (void) +{ + int ret = 0; + +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) && \ + !defined(WOLFSSL_NOSHA3_384) + wc_Sha3 sha3; + const char* msg = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnom" + "nopnopq"; + const char* expOut = "\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"; + byte hash[WC_SHA3_512_DIGEST_SIZE]; + byte hashRet[WC_SHA3_512_DIGEST_SIZE]; + + /* Init stack variables. */ + XMEMSET(hash, 0, sizeof(hash)); + + printf(testingFmt, "wc_Sha3_512_Final()"); + + ret = wc_InitSha3_512(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + + ret= wc_Sha3_512_Update(&sha3, (byte*)msg, (word32)XSTRLEN(msg)); + if (ret == 0) { + ret = wc_Sha3_512_Final(&sha3, hash); + if (ret == 0 && XMEMCMP(expOut, hash, WC_SHA3_512_DIGEST_SIZE) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_Sha3_512_Final(NULL, hash); + if (ret == 0) { + ret = wc_Sha3_384_Final(&sha3, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + wc_Sha3_512_Free(&sha3); + printf(resultFmt, ret == 0 ? passed : failed); + + if (ret == 0) { + printf(testingFmt, "wc_Sha3_512_GetHash()"); + + ret = wc_InitSha3_512(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + /* Init stack variables. */ + XMEMSET(hash, 0, sizeof(hash)); + XMEMSET(hashRet, 0, sizeof(hashRet)); + + ret= wc_Sha3_512_Update(&sha3, (byte*)msg, (word32)XSTRLEN(msg)); + if (ret == 0) { + ret = wc_Sha3_512_GetHash(&sha3, hashRet); + } + if (ret == 0) { + ret = wc_Sha3_512_Final(&sha3, hash); + if (ret == 0 && XMEMCMP(hash, hashRet, WC_SHA3_512_DIGEST_SIZE) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (ret == 0) { + /* Test bad args. */ + ret = wc_Sha3_512_GetHash(NULL, hashRet); + if (ret == BAD_FUNC_ARG) { + ret = wc_Sha3_512_GetHash(&sha3, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + } + + wc_Sha3_512_Free(&sha3); +#endif + return ret; +} /* END test_wc_Sha3_512_Final */ + + +/* + * Testing wc_Sha3_224_Copy() + */ +static int test_wc_Sha3_224_Copy (void) +{ + int ret = 0; +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + wc_Sha3 sha3, sha3Cpy; + const char* msg = "Everyone gets Friday off."; + word32 msglen = (word32)XSTRLEN(msg); + byte hash[WC_SHA3_224_DIGEST_SIZE]; + byte hashCpy[WC_SHA3_224_DIGEST_SIZE]; + + XMEMSET(hash, 0, sizeof(hash)); + XMEMSET(hashCpy, 0, sizeof(hashCpy)); + + printf(testingFmt, "wc_Sha3_224_Copy()"); + + ret = wc_InitSha3_224(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + + ret = wc_InitSha3_224(&sha3Cpy, HEAP_HINT, devId); + if (ret != 0) { + wc_Sha3_224_Free(&sha3); + return ret; + } + + ret = wc_Sha3_224_Update(&sha3, (byte*)msg, msglen); + + if (ret == 0) { + ret = wc_Sha3_224_Copy(&sha3Cpy, &sha3); + if (ret == 0) { + ret = wc_Sha3_224_Final(&sha3, hash); + if (ret == 0) { + ret = wc_Sha3_224_Final(&sha3Cpy, hashCpy); + } + } + if (ret == 0 && XMEMCMP(hash, hashCpy, sizeof(hash)) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_Sha3_224_Copy(NULL, &sha3); + if (ret == BAD_FUNC_ARG) { + ret = wc_Sha3_224_Copy(&sha3Cpy, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_Sha3_224_Copy */ + + + +/* + * Testing wc_Sha3_256_Copy() + */ +static int test_wc_Sha3_256_Copy (void) +{ + int ret = 0; +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + wc_Sha3 sha3, sha3Cpy; + const char* msg = "Everyone gets Friday off."; + word32 msglen = (word32)XSTRLEN(msg); + byte hash[WC_SHA3_256_DIGEST_SIZE]; + byte hashCpy[WC_SHA3_256_DIGEST_SIZE]; + + XMEMSET(hash, 0, sizeof(hash)); + XMEMSET(hashCpy, 0, sizeof(hashCpy)); + + printf(testingFmt, "wc_Sha3_256_Copy()"); + + ret = wc_InitSha3_256(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + + ret = wc_InitSha3_256(&sha3Cpy, HEAP_HINT, devId); + if (ret != 0) { + wc_Sha3_256_Free(&sha3); + return ret; + } + + ret = wc_Sha3_256_Update(&sha3, (byte*)msg, msglen); + + if (ret == 0) { + ret = wc_Sha3_256_Copy(&sha3Cpy, &sha3); + if (ret == 0) { + ret = wc_Sha3_256_Final(&sha3, hash); + if (ret == 0) { + ret = wc_Sha3_256_Final(&sha3Cpy, hashCpy); + } + } + if (ret == 0 && XMEMCMP(hash, hashCpy, sizeof(hash)) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_Sha3_256_Copy(NULL, &sha3); + if (ret == BAD_FUNC_ARG) { + ret = wc_Sha3_256_Copy(&sha3Cpy, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_Sha3_256_Copy */ + + + +/* + * Testing wc_Sha3_384_Copy() + */ +static int test_wc_Sha3_384_Copy (void) +{ + int ret = 0; +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + wc_Sha3 sha3, sha3Cpy; + const char* msg = "Everyone gets Friday off."; + word32 msglen = (word32)XSTRLEN(msg); + byte hash[WC_SHA3_384_DIGEST_SIZE]; + byte hashCpy[WC_SHA3_384_DIGEST_SIZE]; + + XMEMSET(hash, 0, sizeof(hash)); + XMEMSET(hashCpy, 0, sizeof(hashCpy)); + + printf(testingFmt, "wc_Sha3_384_Copy()"); + + ret = wc_InitSha3_384(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + + ret = wc_InitSha3_384(&sha3Cpy, HEAP_HINT, devId); + if (ret != 0) { + wc_Sha3_384_Free(&sha3); + return ret; + } + + ret = wc_Sha3_384_Update(&sha3, (byte*)msg, msglen); + + if (ret == 0) { + ret = wc_Sha3_384_Copy(&sha3Cpy, &sha3); + if (ret == 0) { + ret = wc_Sha3_384_Final(&sha3, hash); + if (ret == 0) { + ret = wc_Sha3_384_Final(&sha3Cpy, hashCpy); + } + } + if (ret == 0 && XMEMCMP(hash, hashCpy, sizeof(hash)) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_Sha3_384_Copy(NULL, &sha3); + if (ret == BAD_FUNC_ARG) { + ret = wc_Sha3_384_Copy(&sha3Cpy, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_Sha3_384_Copy */ + + +/* + * Testing wc_Sha3_512_Copy() + */ +static int test_wc_Sha3_512_Copy (void) +{ + int ret = 0; + +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + wc_Sha3 sha3, sha3Cpy; + const char* msg = "Everyone gets Friday off."; + word32 msglen = (word32)XSTRLEN(msg); + byte hash[WC_SHA3_512_DIGEST_SIZE]; + byte hashCpy[WC_SHA3_512_DIGEST_SIZE]; + + XMEMSET(hash, 0, sizeof(hash)); + XMEMSET(hashCpy, 0, sizeof(hashCpy)); + + + printf(testingFmt, "wc_Sha3_512_Copy()"); + + ret = wc_InitSha3_512(&sha3, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + + ret = wc_InitSha3_512(&sha3Cpy, HEAP_HINT, devId); + if (ret != 0) { + wc_Sha3_512_Free(&sha3); + return ret; + } + + ret = wc_Sha3_512_Update(&sha3, (byte*)msg, msglen); + + if (ret == 0) { + ret = wc_Sha3_512_Copy(&sha3Cpy, &sha3); + if (ret == 0) { + ret = wc_Sha3_512_Final(&sha3, hash); + if (ret == 0) { + ret = wc_Sha3_512_Final(&sha3Cpy, hashCpy); + } + } + if (ret == 0 && XMEMCMP(hash, hashCpy, sizeof(hash)) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_Sha3_512_Copy(NULL, &sha3); + if (ret == BAD_FUNC_ARG) { + ret = wc_Sha3_512_Copy(&sha3Cpy, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_Sha3_512_Copy */ + + + + +static int test_wc_InitShake256 (void) +{ + int ret = 0; +#if defined(WOLFSSL_SHAKE256) && !defined(WOLFSSL_NO_SHAKE256) + wc_Shake shake; + + printf(testingFmt, "wc_InitShake256()"); + + ret = wc_InitShake256(&shake, HEAP_HINT, devId); + /* Test bad args. */ + if (ret == 0) { + ret = wc_InitShake256(NULL, HEAP_HINT, devId); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + wc_Shake256_Free(&shake); + printf(resultFmt, ret == 0 ? passed : failed); +#endif + return ret; + +} /* END test_wc_InitSha3 */ + + +static int testing_wc_Shake256_Update (void) +{ + int ret = 0; + +#if defined(WOLFSSL_SHAKE256) && !defined(WOLFSSL_NO_SHAKE256) + wc_Shake shake; + byte msg[] = "Everybody's working for the weekend."; + byte msg2[] = "Everybody gets Friday off."; + byte msgCmp[] = "\x45\x76\x65\x72\x79\x62\x6f\x64\x79\x27\x73\x20" + "\x77\x6f\x72\x6b\x69\x6e\x67\x20\x66\x6f\x72\x20\x74" + "\x68\x65\x20\x77\x65\x65\x6b\x65\x6e\x64\x2e\x45\x76" + "\x65\x72\x79\x62\x6f\x64\x79\x20\x67\x65\x74\x73\x20" + "\x46\x72\x69\x64\x61\x79\x20\x6f\x66\x66\x2e"; + word32 msglen = sizeof(msg) - 1; + word32 msg2len = sizeof(msg2); + word32 msgCmplen = sizeof(msgCmp); + + printf(testingFmt, "wc_Shake256_Update()"); + + ret = wc_InitShake256(&shake, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + ret = wc_Shake256_Update(&shake, msg, msglen); + if (XMEMCMP(msg, shake.t, msglen) || shake.i != msglen) { + ret = WOLFSSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_Shake256_Update(&shake, msg2, msg2len); + if (XMEMCMP(shake.t, msgCmp, msgCmplen) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Pass bad args. */ + if (ret == 0) { + ret = wc_Shake256_Update(NULL, msg2, msg2len); + if (ret == BAD_FUNC_ARG) { + ret = wc_Shake256_Update(&shake, NULL, 5); + } + if (ret == BAD_FUNC_ARG) { + wc_Shake256_Free(&shake); + if (wc_InitShake256(&shake, HEAP_HINT, devId)) { + return ret; + } + ret = wc_Shake256_Update(&shake, NULL, 0); + if (ret == 0) { + ret = wc_Shake256_Update(&shake, msg2, msg2len); + } + if (ret == 0 && XMEMCMP(msg2, shake.t, msg2len) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + wc_Shake256_Free(&shake); + + printf(resultFmt, ret == 0 ? passed : failed); +#endif /* WOLFSSL_SHAKE256 && !WOLFSSL_NO_SHAKE256 */ + + return ret; + +} + +static int test_wc_Shake256_Final (void) +{ + int ret = 0; + +#if defined(WOLFSSL_SHAKE256) && !defined(WOLFSSL_NO_SHAKE256) + wc_Shake shake; + const char* msg = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnom" + "nopnopq"; + const char* expOut = "\x4d\x8c\x2d\xd2\x43\x5a\x01\x28\xee\xfb\xb8\xc3\x6f" + "\x6f\x87\x13\x3a\x79\x11\xe1\x8d\x97\x9e\xe1\xae\x6b" + "\xe5\xd4\xfd\x2e\x33\x29\x40\xd8\x68\x8a\x4e\x6a\x59" + "\xaa\x80\x60\xf1\xf9\xbc\x99\x6c\x05\xac\xa3\xc6\x96" + "\xa8\xb6\x62\x79\xdc\x67\x2c\x74\x0b\xb2\x24\xec\x37" + "\xa9\x2b\x65\xdb\x05\x39\xc0\x20\x34\x55\xf5\x1d\x97" + "\xcc\xe4\xcf\xc4\x91\x27\xd7\x26\x0a\xfc\x67\x3a\xf2" + "\x08\xba\xf1\x9b\xe2\x12\x33\xf3\xde\xbe\x78\xd0\x67" + "\x60\xcf\xa5\x51\xee\x1e\x07\x91\x41\xd4"; + byte hash[114]; + + /* Init stack variables. */ + XMEMSET(hash, 0, sizeof(hash)); + + printf(testingFmt, "wc_Shake256_Final()"); + + ret = wc_InitShake256(&shake, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + + ret= wc_Shake256_Update(&shake, (byte*)msg, (word32)XSTRLEN(msg)); + if (ret == 0) { + ret = wc_Shake256_Final(&shake, hash, (word32)sizeof(hash)); + if (ret == 0 && XMEMCMP(expOut, hash, (word32)sizeof(hash)) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_Shake256_Final(NULL, hash, (word32)sizeof(hash)); + if (ret == 0) { + ret = wc_Shake256_Final(&shake, NULL, (word32)sizeof(hash)); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + wc_Shake256_Free(&shake); + printf(resultFmt, ret == 0 ? passed : failed); +#endif + return ret; +} + + + +/* + * 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 minimum 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 minimum 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 minimum 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 minimum 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 minimum 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 */ + + + +/* + * Testing wc_InitCmac() + */ +static int test_wc_InitCmac (void) +{ + int ret = 0; + +#if defined(WOLFSSL_CMAC) && !defined(NO_AES) + Cmac cmac1, cmac2, cmac3; + /* AES 128 key. */ + byte key1[] = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x10\x11\x12\x13\x14\x15\x16"; + /* AES 192 key. */ + byte key2[] = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x01\x11\x12\x13\x14\x15\x16" + "\x01\x02\x03\x04\x05\x06\x07\x08"; + + /* AES 256 key. */ + byte key3[] = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x01\x11\x12\x13\x14\x15\x16" + "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x01\x11\x12\x13\x14\x15\x16"; + + word32 key1Sz = (word32)sizeof(key1) - 1; + word32 key2Sz = (word32)sizeof(key2) - 1; + word32 key3Sz = (word32)sizeof(key3) - 1; + int type = WC_CMAC_AES; + + printf(testingFmt, "wc_InitCmac()"); + +#ifdef WOLFSSL_AES_128 + ret = wc_InitCmac(&cmac1, key1, key1Sz, type, NULL); +#endif +#ifdef WOLFSSL_AES_192 + if (ret == 0) + ret = wc_InitCmac(&cmac2, key2, key2Sz, type, NULL); +#endif +#ifdef WOLFSSL_AES_256 + if (ret == 0) + ret = wc_InitCmac(&cmac3, key3, key3Sz, type, NULL); +#endif + + /* Test bad args. */ + if (ret == 0) { + ret = wc_InitCmac(NULL, key3, key3Sz, type, NULL); + if (ret == BAD_FUNC_ARG) { + ret = wc_InitCmac(&cmac3, NULL, key3Sz, type, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_InitCmac(&cmac3, key3, 0, type, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_InitCmac(&cmac3, key3, key3Sz, 0, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = SSL_FATAL_ERROR; + } + } + + (void)key1; + (void)key1Sz; + (void)key2; + (void)key2Sz; + (void)cmac1; + (void)cmac2; + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_InitCmac */ + + +/* + * Testing wc_CmacUpdate() + */ +static int test_wc_CmacUpdate (void) +{ + int ret = 0; + +#if defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_128) + Cmac cmac; + byte key[] = + { + 0x64, 0x4c, 0xbf, 0x12, 0x85, 0x9d, 0xf0, 0x55, + 0x7e, 0xa9, 0x1f, 0x08, 0xe0, 0x51, 0xff, 0x27 + }; + byte in[] = "\xe2\xb4\xb6\xf9\x48\x44\x02\x64" + "\x5c\x47\x80\x9e\xd5\xa8\x3a\x17" + "\xb3\x78\xcf\x85\x22\x41\x74\xd9" + "\xa0\x97\x39\x71\x62\xf1\x8e\x8f" + "\xf4"; + + word32 inSz = (word32)sizeof(in) - 1; + word32 keySz = (word32)sizeof(key); + int type = WC_CMAC_AES; + + ret = wc_InitCmac(&cmac, key, keySz, type, NULL); + if (ret != 0) { + return ret; + } + + printf(testingFmt, "wc_CmacUpdate()"); + + ret = wc_CmacUpdate(&cmac, in, inSz); + + /* Test bad args. */ + if (ret == 0) { + ret = wc_CmacUpdate(NULL, in, inSz); + if (ret == BAD_FUNC_ARG) { + ret = wc_CmacUpdate(&cmac, NULL, 30); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_CmacUpdate */ + + +/* + * Testing wc_CmacFinal() + */ +static int test_wc_CmacFinal (void) +{ + int ret = 0; + +#if defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_128) + Cmac cmac; + byte key[] = + { + 0x64, 0x4c, 0xbf, 0x12, 0x85, 0x9d, 0xf0, 0x55, + 0x7e, 0xa9, 0x1f, 0x08, 0xe0, 0x51, 0xff, 0x27 + }; + byte msg[] = + { + 0xe2, 0xb4, 0xb6, 0xf9, 0x48, 0x44, 0x02, 0x64, + 0x5c, 0x47, 0x80, 0x9e, 0xd5, 0xa8, 0x3a, 0x17, + 0xb3, 0x78, 0xcf, 0x85, 0x22, 0x41, 0x74, 0xd9, + 0xa0, 0x97, 0x39, 0x71, 0x62, 0xf1, 0x8e, 0x8f, + 0xf4 + }; + /* Test vectors from CMACGenAES128.rsp from + * http://csrc.nist.gov/groups/STM/cavp/block-cipher-modes.html#cmac + * Per RFC4493 truncation of lsb is possible. + */ + byte expMac[] = + { + 0x4e, 0x6e, 0xc5, 0x6f, 0xf9, 0x5d, 0x0e, 0xae, + 0x1c, 0xf8, 0x3e, 0xfc, 0xf4, 0x4b, 0xeb + }; + byte mac[AES_BLOCK_SIZE]; + word32 msgSz = (word32)sizeof(msg); + word32 keySz = (word32)sizeof(key); + word32 macSz = sizeof(mac); + word32 badMacSz = 17; + int expMacSz = sizeof(expMac); + int type = WC_CMAC_AES; + + XMEMSET(mac, 0, macSz); + + ret = wc_InitCmac(&cmac, key, keySz, type, NULL); + if (ret != 0) { + return ret; + } + ret = wc_CmacUpdate(&cmac, msg, msgSz); + + printf(testingFmt, "wc_CmacFinal()"); + if (ret == 0) { + ret = wc_CmacFinal(&cmac, mac, &macSz); + if (ret == 0 && XMEMCMP(mac, expMac, expMacSz) != 0) { + ret = SSL_FATAL_ERROR; + } + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_CmacFinal(NULL, mac, &macSz); + if (ret == BAD_FUNC_ARG) { + ret = wc_CmacFinal(&cmac, NULL, &macSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_CmacFinal(&cmac, mac, &badMacSz); + if (ret == BUFFER_E) { + ret = 0; + } + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + } + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_CmacFinal */ + + +/* + * Testing wc_AesCmacGenerate() && wc_AesCmacVerify() + */ +static int test_wc_AesCmacGenerate (void) +{ + int ret = 0; +#if defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_128) + Cmac cmac; + byte key[] = + { + 0x26, 0xef, 0x8b, 0x40, 0x34, 0x11, 0x7d, 0x9e, + 0xbe, 0xc0, 0xc7, 0xfc, 0x31, 0x08, 0x54, 0x69 + }; + byte msg[] = "\x18\x90\x49\xef\xfd\x7c\xf9\xc8" + "\xf3\x59\x65\xbc\xb0\x97\x8f\xd4"; + byte expMac[] = "\x29\x5f\x2f\x71\xfc\x58\xe6\xf6" + "\x3d\x32\x65\x4c\x66\x23\xc5"; + byte mac[AES_BLOCK_SIZE]; + word32 keySz = sizeof(key); + word32 macSz = sizeof(mac); + word32 msgSz = sizeof(msg) - 1; + word32 expMacSz = sizeof(expMac) - 1; + int type = WC_CMAC_AES; + + XMEMSET(mac, 0, macSz); + + ret = wc_InitCmac(&cmac, key, keySz, type, NULL); + if (ret != 0) { + return ret; + } + + ret = wc_CmacUpdate(&cmac, msg, msgSz); + if (ret != 0) { + return ret; + } + + printf(testingFmt, "wc_AesCmacGenerate()"); + + ret = wc_AesCmacGenerate(mac, &macSz, msg, msgSz, key, keySz); + if (ret == 0 && XMEMCMP(mac, expMac, expMacSz) != 0) { + ret = SSL_FATAL_ERROR; + } + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_AesCmacGenerate(NULL, &macSz, msg, msgSz, key, keySz); + if (ret == BAD_FUNC_ARG) { + ret = wc_AesCmacGenerate(mac, &macSz, msg, msgSz, NULL, keySz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_AesCmacGenerate(mac, &macSz, msg, msgSz, key, 0); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_AesCmacGenerate(mac, &macSz, NULL, msgSz, key, keySz); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + + if (ret == 0) { + printf(testingFmt, "wc_AesCmacVerify()"); + + ret = wc_AesCmacVerify(mac, macSz, msg, msgSz, key, keySz); + /* Test bad args. */ + if (ret == 0) { + ret = wc_AesCmacVerify(NULL, macSz, msg, msgSz, key, keySz); + if (ret == BAD_FUNC_ARG) { + ret = wc_AesCmacVerify(mac, 0, msg, msgSz, key, keySz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_AesCmacVerify(mac, macSz, msg, msgSz, NULL, keySz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_AesCmacVerify(mac, macSz, msg, msgSz, key, 0); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_AesCmacVerify(mac, macSz, NULL, msgSz, key, keySz); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + } + +#endif + return ret; + +} /* END test_wc_AesCmacGenerate */ + + + + +/* + * 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 */ + +/* + * unit test for wc_Poly1305SetKey() + */ +static int test_wc_Poly1305SetKey(void) +{ + int ret = 0; + +#ifdef HAVE_POLY1305 + Poly1305 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 + }; + + printf(testingFmt, "wc_Poly1305_SetKey()"); + + ret = wc_Poly1305SetKey(&ctx, key, (word32)(sizeof(key)/sizeof(byte))); + /* Test bad args. */ + if (ret == 0) { + ret = wc_Poly1305SetKey(NULL, key, (word32)(sizeof(key)/sizeof(byte))); + if(ret == BAD_FUNC_ARG) { + ret = wc_Poly1305SetKey(&ctx, NULL, (word32)(sizeof(key)/sizeof(byte))); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Poly1305SetKey(&ctx, key, 18); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; +} /* END test_wc_Poly1305_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); + AssertIntEQ(ret, 0); + ret = wc_Chacha_SetKey(&dec, key, keySz); + AssertIntEQ(ret, 0); + ret = wc_Chacha_SetIV(&enc, cipher, 0); + AssertIntEQ(ret, 0); + ret = wc_Chacha_SetIV(&dec, cipher, 0); + AssertIntEQ(ret, 0); + + ret = wc_Chacha_Process(&enc, cipher, (byte*)input, (word32)inlen); + AssertIntEQ(ret, 0); + ret = wc_Chacha_Process(&dec, plain, cipher, (word32)inlen); + AssertIntEQ(ret, 0); + ret = XMEMCMP(input, plain, (int)inlen); + AssertIntEQ(ret, 0); + +#if !defined(USE_INTEL_CHACHA_SPEEDUP) && !defined(WOLFSSL_ARMASM) + /* test checking and using leftovers, currently just in C code */ + ret = wc_Chacha_SetIV(&enc, cipher, 0); + AssertIntEQ(ret, 0); + ret = wc_Chacha_SetIV(&dec, cipher, 0); + AssertIntEQ(ret, 0); + + ret = wc_Chacha_Process(&enc, cipher, (byte*)input, (word32)inlen - 2); + AssertIntEQ(ret, 0); + ret = wc_Chacha_Process(&enc, cipher + (inlen - 2), + (byte*)input + (inlen - 2), 2); + AssertIntEQ(ret, 0); + ret = wc_Chacha_Process(&dec, plain, (byte*)cipher, (word32)inlen - 2); + AssertIntEQ(ret, 0); + ret = wc_Chacha_Process(&dec, cipher + (inlen - 2), + (byte*)input + (inlen - 2), 2); + AssertIntEQ(ret, 0); + ret = XMEMCMP(input, plain, (int)inlen); + AssertIntEQ(ret, 0); + + /* check edge cases with counter increment */ + { + /* expected results collected from wolfSSL 4.3.0 encrypted in one call*/ + const byte expected[] = { + 0x54,0xB1,0xE2,0xD4,0xA2,0x4D,0x52,0x5F, + 0x42,0x04,0x89,0x7C,0x6E,0x2D,0xFC,0x2D, + 0x10,0x25,0xB6,0x92,0x71,0xD5,0xC3,0x20, + 0xE3,0x0E,0xEC,0xF4,0xD8,0x10,0x70,0x29, + 0x2D,0x4C,0x2A,0x56,0x21,0xE1,0xC7,0x37, + 0x0B,0x86,0xF5,0x02,0x8C,0xB8,0xB8,0x38, + 0x41,0xFD,0xDF,0xD9,0xC3,0xE6,0xC8,0x88, + 0x06,0x82,0xD4,0x80,0x6A,0x50,0x69,0xD5, + 0xB9,0xB0,0x2F,0x44,0x36,0x5D,0xDA,0x5E, + 0xDE,0xF6,0xF5,0xFC,0x44,0xDC,0x07,0x51, + 0xA7,0x32,0x42,0xDB,0xCC,0xBD,0xE2,0xE5, + 0x0B,0xB1,0x14,0xFF,0x12,0x80,0x16,0x43, + 0xE7,0x40,0xD5,0xEA,0xC7,0x3F,0x69,0x07, + 0x64,0xD4,0x86,0x6C,0xE2,0x1F,0x8F,0x6E, + 0x35,0x41,0xE7,0xD3,0xB5,0x5D,0xD6,0xD4, + 0x9F,0x00,0xA9,0xAE,0x3D,0x28,0xA5,0x37, + 0x80,0x3D,0x11,0x25,0xE2,0xB6,0x99,0xD9, + 0x9B,0x98,0xE9,0x37,0xB9,0xF8,0xA0,0x04, + 0xDF,0x13,0x49,0x3F,0x19,0x6A,0x45,0x06, + 0x21,0xB4,0xC7,0x3B,0x49,0x45,0xB4,0xC8, + 0x03,0x5B,0x43,0x89,0xBD,0xB3,0x96,0x4B, + 0x17,0x6F,0x85,0xC6,0xCF,0xA6,0x05,0x35, + 0x1E,0x25,0x03,0xBB,0x55,0x0A,0xD5,0x54, + 0x41,0xEA,0xEB,0x50,0x40,0x1B,0x43,0x19, + 0x59,0x1B,0x0E,0x12,0x3E,0xA2,0x71,0xC3, + 0x1A,0xA7,0x11,0x50,0x43,0x9D,0x56,0x3B, + 0x63,0x2F,0x63,0xF1,0x8D,0xAE,0xF3,0x23, + 0xFA,0x1E,0xD8,0x6A,0xE1,0xB2,0x4B,0xF3, + 0xB9,0x13,0x7A,0x72,0x2B,0x6D,0xCC,0x41, + 0x1C,0x69,0x7C,0xCD,0x43,0x6F,0xE4,0xE2, + 0x38,0x99,0xFB,0xC3,0x38,0x92,0x62,0x35, + 0xC0,0x1D,0x60,0xE4,0x4B,0xDD,0x0C,0x14 + }; + const byte iv2[] = { + 0x9D,0xED,0xE7,0x0F,0xEC,0x81,0x51,0xD9, + 0x77,0x39,0x71,0xA6,0x21,0xDF,0xB8,0x93 + }; + byte input2[256]; + int i; + + for (i = 0; i < 256; i++) + input2[i] = i; + + ret = wc_Chacha_SetIV(&enc, iv2, 0); + AssertIntEQ(ret, 0); + + ret = wc_Chacha_Process(&enc, cipher, input2, 64); + AssertIntEQ(ret, 0); + AssertIntEQ(XMEMCMP(expected, cipher, 64), 0); + + ret = wc_Chacha_Process(&enc, cipher, input2 + 64, 128); + AssertIntEQ(ret, 0); + AssertIntEQ(XMEMCMP(expected + 64, cipher, 128), 0); + + /* partial */ + ret = wc_Chacha_Process(&enc, cipher, input2 + 192, 32); + AssertIntEQ(ret, 0); + AssertIntEQ(XMEMCMP(expected + 192, cipher, 32), 0); + + ret = wc_Chacha_Process(&enc, cipher, input2 + 224, 32); + AssertIntEQ(ret, 0); + AssertIntEQ(XMEMCMP(expected + 224, cipher, 32), 0); + } +#endif + + /* Test bad args. */ + ret = wc_Chacha_Process(NULL, cipher, (byte*)input, (word32)inlen); + AssertIntEQ(ret, BAD_FUNC_ARG); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } + + 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); + AssertIntEQ(ret, 0); + ret = XMEMCMP(generatedCiphertext, cipher, sizeof(cipher)/sizeof(byte)); + AssertIntEQ(ret, 0); + + /* Test bad args. */ + ret = wc_ChaCha20Poly1305_Encrypt(NULL, iv, aad, sizeof(aad), plaintext, + sizeof(plaintext), generatedCiphertext, generatedAuthTag); + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Encrypt(key, NULL, aad, sizeof(aad), + plaintext, sizeof(plaintext), + generatedCiphertext, generatedAuthTag); + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), NULL, + sizeof(plaintext), generatedCiphertext, generatedAuthTag); + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), + plaintext, 0, generatedCiphertext, generatedAuthTag); + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Encrypt(key, iv, aad, sizeof(aad), + plaintext, sizeof(plaintext), NULL, generatedAuthTag); + AssertIntEQ(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; + } + 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); + AssertIntEQ(ret, 0); + ret = XMEMCMP(generatedPlaintext, plaintext, + sizeof(plaintext)/sizeof(byte)); + AssertIntEQ(ret, 0); + + /* Test bad args. */ + ret = wc_ChaCha20Poly1305_Decrypt(NULL, iv, aad, sizeof(aad), cipher, + sizeof(cipher), authTag, generatedPlaintext); + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Decrypt(key, NULL, aad, sizeof(aad), + cipher, sizeof(cipher), authTag, generatedPlaintext); + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), NULL, + sizeof(cipher), authTag, generatedPlaintext); + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, + sizeof(cipher), NULL, generatedPlaintext); + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, + sizeof(cipher), authTag, NULL); + AssertIntEQ(ret, BAD_FUNC_ARG); + ret = wc_ChaCha20Poly1305_Decrypt(key, iv, aad, sizeof(aad), cipher, + 0, authTag, generatedPlaintext); + AssertIntEQ(ret, BAD_FUNC_ARG); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } + + 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; +#if !defined(NO_AES) && defined(WOLFSSL_AES_128) + 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 + }; +#ifdef WOLFSSL_AES_192 + 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 + }; +#endif +#ifdef WOLFSSL_AES_256 + 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 + }; +#endif + 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; + +#ifdef WOLFSSL_AES_128 + ret = wc_AesSetKey(&aes, key16, (word32) sizeof(key16) / sizeof(byte), + iv, AES_ENCRYPTION); +#endif +#ifdef WOLFSSL_AES_192 + if (ret == 0) { + ret = wc_AesSetKey (&aes, key24, (word32) sizeof(key24) / sizeof(byte), + iv, AES_ENCRYPTION); + } +#endif +#ifdef WOLFSSL_AES_256 + if (ret == 0) { + ret = wc_AesSetKey (&aes, key32, (word32) sizeof(key32) / sizeof(byte), + iv, AES_ENCRYPTION); + } +#endif + + /* 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)&& \ + defined(WOLFSSL_AES_256) + 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; + wc_AesFree(&aes); + 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 || 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) && defined(WOLFSSL_AES_256) + 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; +#ifdef WOLFSSL_AES_128 + byte key16[] = + { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 + }; +#endif +#ifdef WOLFSSL_AES_192 + 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 + }; +#endif +#ifdef WOLFSSL_AES_256 + 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 + }; +#endif + 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; + +#ifdef WOLFSSL_AES_128 + ret = wc_AesGcmSetKey(&aes, key16, sizeof(key16)/sizeof(byte)); +#endif +#ifdef WOLFSSL_AES_192 + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key24, sizeof(key24)/sizeof(byte)); + } +#endif +#ifdef WOLFSSL_AES_256 + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key32, sizeof(key32)/sizeof(byte)); + } +#endif + + /* 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; + /* WOLFSSL_AFALG requires 12 byte IV */ +#if !defined(NO_AES) && defined(HAVE_AESGCM) && defined(WOLFSSL_AES_256) && \ + !defined(WOLFSSL_AFALG) && !defined(WOLFSSL_DEVCRYPTO_AES) + + 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 (defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION == 2)) || defined(HAVE_SELFTEST) + /* FIPS does not check the lower bound of ivSz */ +#else + if (gcmE == BAD_FUNC_ARG) { + gcmE = wc_AesGcmEncrypt(&aes, enc, vector, + sizeof(vector), iv, 0, + resultT, sizeof(resultT), a, sizeof(a)); + } +#endif + if (gcmE == BAD_FUNC_ARG) { + gcmE = 0; + } else { + gcmE = WOLFSSL_FATAL_ERROR; + } + } + + /* This case is now considered good. Long IVs are now allowed. + * Except for the original FIPS release, it still has an upper + * bound on the IV length. */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + if (gcmE == 0) { + gcmE = wc_AesGcmEncrypt(&aes, enc, vector, sizeof(vector), longIV, + sizeof(longIV)/sizeof(byte), resultT, sizeof(resultT), + a, sizeof(a)); + } +#else + (void)longIV; +#endif /* Old FIPS */ + /* 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 (defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION == 2)) || defined(HAVE_SELFTEST) + /* FIPS does not check the lower bound of ivSz */ + #else + if (gcmD == BAD_FUNC_ARG) { + gcmD = wc_AesGcmDecrypt(&aes, dec, enc, sizeof(enc)/sizeof(byte), + iv, 0, resultT, + sizeof(resultT), a, sizeof(a)); + } + #endif + 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 + }; +#ifdef WOLFSSL_AES_192 + 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 + }; +#endif +#ifdef WOLFSSL_AES_256 + 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 + }; +#endif + 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; + +#ifdef WOLFSSL_AES_128 + ret = wc_GmacSetKey(&gmac, key16, sizeof(key16)/sizeof(byte)); +#endif +#ifdef WOLFSSL_AES_192 + if (ret == 0) { + ret = wc_GmacSetKey(&gmac, key24, sizeof(key24)/sizeof(byte)); + } +#endif +#ifdef WOLFSSL_AES_256 + if (ret == 0) { + ret = wc_GmacSetKey(&gmac, key32, sizeof(key32)/sizeof(byte)); + } +#endif + + /* 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; +#ifdef WOLFSSL_AES_128 + const byte key16[] = + { + 0x89, 0xc9, 0x49, 0xe9, 0xc8, 0x04, 0xaf, 0x01, + 0x4d, 0x56, 0x04, 0xb3, 0x94, 0x59, 0xf2, 0xc8 + }; +#endif +#ifdef WOLFSSL_AES_192 + 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 + }; +#endif +#ifdef WOLFSSL_AES_256 + 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 + }; +#endif +#ifdef WOLFSSL_AES_128 + const byte authIn[] = + { + 0x82, 0xad, 0xcd, 0x63, 0x8d, 0x3f, 0xa9, 0xd9, + 0xf3, 0xe8, 0x41, 0x00, 0xd6, 0x1e, 0x07, 0x77 + }; +#endif +#ifdef WOLFSSL_AES_192 + const byte authIn2[] = + { + 0x8b, 0x5c, 0x12, 0x4b, 0xef, 0x6e, 0x2f, 0x0f, + 0xe4, 0xd8, 0xc9, 0x5c, 0xd5, 0xfa, 0x4c, 0xf1 + }; +#endif + const byte authIn3[] = + { + 0xb9, 0x6b, 0xaa, 0x8c, 0x1c, 0x75, 0xa6, 0x71, + 0xbf, 0xb2, 0xd0, 0x8d, 0x06, 0xbe, 0x5f, 0x36 + }; +#ifdef WOLFSSL_AES_128 + const byte tag1[] = /* Known. */ + { + 0x88, 0xdb, 0x9d, 0x62, 0x17, 0x2e, 0xd0, 0x43, + 0xaa, 0x10, 0xf1, 0x6d, 0x22, 0x7d, 0xc4, 0x1b + }; +#endif +#ifdef WOLFSSL_AES_192 + const byte tag2[] = /* Known */ + { + 0x20, 0x4b, 0xdb, 0x1b, 0xd6, 0x21, 0x54, 0xbf, + 0x08, 0x92, 0x2a, 0xaa, 0x54, 0xee, 0xd7, 0x05 + }; +#endif + const byte tag3[] = /* Known */ + { + 0x3e, 0x5d, 0x48, 0x6a, 0xa2, 0xe3, 0x0b, 0x22, + 0xe0, 0x40, 0xb8, 0x57, 0x23, 0xa0, 0x6e, 0x76 + }; +#ifdef WOLFSSL_AES_128 + const byte iv[] = + { + 0xd1, 0xb1, 0x04, 0xc8, 0x15, 0xbf, 0x1e, 0x94, + 0xe2, 0x8c, 0x8f, 0x16 + }; +#endif +#ifdef WOLFSSL_AES_192 + const byte iv2[] = + { + 0x05, 0xad, 0x13, 0xa5, 0xe2, 0xc2, 0xab, 0x66, + 0x7e, 0x1a, 0x6f, 0xbc + }; +#endif + 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 variables. */ + 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; + +#ifdef WOLFSSL_AES_128 + 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)); + } + } +#endif + +#ifdef WOLFSSL_AES_192 + 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)); + } +#endif + +#ifdef WOLFSSL_AES_256 + 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)); + } +#endif + + /*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); /* NULL key */ + if (ret == BAD_FUNC_ARG) + ret = wc_Arc4SetKey(&arc, (byte*)key, 0); /* length == 0 */ + if (ret == BAD_FUNC_ARG) + ret = WOLFSSL_ERROR_NONE; + 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"; + int keyLen = 8; + 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, keyLen); + } + if (ret == 0) { + ret = wc_Arc4SetKey(&dec, (byte*)key, keyLen); + } + if (ret == 0) { + ret = wc_Arc4Process(&enc, cipher, (byte*)input, keyLen); + } + if (ret == 0) { + ret = wc_Arc4Process(&dec, plain, cipher, keyLen); + if (ret != 0 || XMEMCMP(plain, input, keyLen)) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } + } + + /* Bad args. */ + if (ret == 0) { + ret = wc_Arc4Process(NULL, plain, cipher, keyLen); + if (ret == BAD_FUNC_ARG) { + ret = wc_Arc4Process(&dec, NULL, cipher, keyLen); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Arc4Process(&dec, plain, NULL, keyLen); + } + 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; + word32 keySz = 0; + word32 tstKeySz = 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; + keySz = 1024; + #else + XMEMCPY(tmp, client_keypub_der_2048, sizeof_client_keypub_der_2048); + bytes = sizeof_client_keypub_der_2048; + keySz = 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 (wc_FreeRsaKey(&keyPub) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + if (ret == 0) { + /* Test for getting modulus key size */ + idx = 0; + ret = wc_RsaPublicKeyDecode_ex(tmp, &idx, (word32)bytes, NULL, + &tstKeySz, NULL, NULL); + ret = (ret == 0 && tstKeySz == keySz/8) ? 0 : WOLFSSL_FATAL_ERROR; + } + + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + 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 */ + + +#if (!defined(NO_RSA) || !defined(HAVE_FAST_RSA)) && defined(WOLFSSL_KEY_GEN) + /* In FIPS builds, wc_MakeRsaKey() will return an error if it cannot find + * a probable prime in 5*(modLen/2) attempts. In non-FIPS builds, it keeps + * trying until it gets a probable prime. */ + #ifdef HAVE_FIPS + static int MakeRsaKeyRetry(RsaKey* key, int size, long e, WC_RNG* rng) + { + int ret; + + for (;;) { + ret = wc_MakeRsaKey(key, size, e, rng); + if (ret != PRIME_GEN_E) break; + printf("MakeRsaKey couldn't find prime; trying again.\n"); + } + + return ret; + } + #define MAKE_RSA_KEY(a, b, c, d) MakeRsaKeyRetry(a, b, c, d) + #else + #define MAKE_RSA_KEY(a, b, c, d) wc_MakeRsaKey(a, b, c, d) + #endif +#endif + + +/* + * 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; + #ifndef WOLFSSL_SP_MATH + int bits = 1024; + #else + int bits = 2048; + #endif + + printf(testingFmt, "wc_MakeRsaKey()"); + + ret = wc_InitRsaKey(&genKey, NULL); + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = MAKE_RSA_KEY(&genKey, bits, 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 = MAKE_RSA_KEY(NULL, bits, WC_RSA_EXPONENT, &rng); + if (ret == BAD_FUNC_ARG) { + ret = MAKE_RSA_KEY(&genKey, bits, WC_RSA_EXPONENT, NULL); + } + if (ret == BAD_FUNC_ARG) { + /* e < 3 */ + ret = MAKE_RSA_KEY(&genKey, bits, 2, &rng); + } + if (ret == BAD_FUNC_ARG) { + /* e & 1 == 0 */ + ret = MAKE_RSA_KEY(&genKey, bits, 6, &rng); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #else + /* Test bad args. */ + if (ret == 0) { + ret = MAKE_RSA_KEY(NULL, bits, WC_RSA_EXPONENT, &rng); + if (ret == USER_CRYPTO_ERROR) { + ret = MAKE_RSA_KEY(&genKey, bits, WC_RSA_EXPONENT, NULL); + } + if (ret == USER_CRYPTO_ERROR) { + /* e < 3 */ + ret = MAKE_RSA_KEY(&genKey, bits, 2, &rng); + } + if (ret == USER_CRYPTO_ERROR) { + /* e & 1 == 0 */ + ret = MAKE_RSA_KEY(&genKey, bits, 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 */ + +/* + * Test the bounds checking on the cipher text versus the key modulus. + * 1. Make a new RSA key. + * 2. Set c to 1. + * 3. Decrypt c into k. (error) + * 4. Copy the key modulus to c and sub 1 from the copy. + * 5. Decrypt c into k. (error) + * Valid bounds test cases are covered by all the other RSA tests. + */ +static int test_RsaDecryptBoundsCheck(void) +{ + int ret = 0; +#if !defined(NO_RSA) && defined(WC_RSA_NO_PADDING) && \ + (defined(USE_CERT_BUFFERS_1024) || defined(USE_CERT_BUFFERS_2048)) && \ + defined(WOLFSSL_PUBLIC_MP) && !defined(NO_RSA_BOUNDS_CHECK) + RsaKey key; + byte flatC[256]; + word32 flatCSz; + byte out[256]; + word32 outSz = sizeof(out); + WC_RNG rng; + + printf(testingFmt, "RSA decrypt bounds check"); + + ret = wc_InitRng(&rng); + + if (ret == 0) + ret = wc_InitRsaKey(&key, NULL); + + if (ret == 0) { + const byte* derKey; + word32 derKeySz; + word32 idx = 0; + + #ifdef USE_CERT_BUFFERS_1024 + derKey = server_key_der_1024; + derKeySz = (word32)sizeof_server_key_der_1024; + flatCSz = 128; + #else + derKey = server_key_der_2048; + derKeySz = (word32)sizeof_server_key_der_2048; + flatCSz = 256; + #endif + + ret = wc_RsaPrivateKeyDecode(derKey, &idx, &key, derKeySz); + } + + if (ret == 0) { + XMEMSET(flatC, 0, flatCSz); + flatC[flatCSz-1] = 1; + + ret = wc_RsaDirect(flatC, flatCSz, out, &outSz, &key, + RSA_PRIVATE_DECRYPT, &rng); + } + if (ret == RSA_OUT_OF_RANGE_E) { + mp_int c; + mp_init_copy(&c, &key.n); + mp_sub_d(&c, 1, &c); + mp_to_unsigned_bin(&c, flatC); + ret = wc_RsaDirect(flatC, sizeof(flatC), out, &outSz, &key, + RSA_PRIVATE_DECRYPT, NULL); + mp_clear(&c); + } + if (ret == RSA_OUT_OF_RANGE_E) + ret = 0; + + if (wc_FreeRsaKey(&key) || wc_FreeRng(&rng) || ret != 0) + ret = WOLFSSL_FATAL_ERROR; + + printf(resultFmt, ret == 0 ? passed : failed); + + +#endif + return ret; + +} /* END test_wc_RsaDecryptBoundsCheck */ + +/* + * Testing wc_SetKeyUsage() + */ +static int test_wc_SetKeyUsage (void) +{ + int ret = 0; +#if !defined(NO_RSA) && defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) && !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; + #ifndef WOLFSSL_SP_MATH + int bits = 1024; + 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 */ + #else + int bits = 2048; + word32 derSz = 1196; + /* (2 x 256) + 2 (possible leading 00) + (5 x 128) + 5 (possible leading 00) + + 3 (e) + 8 (ASN tag) + 17 (ASN length) + 4 seqSz + 3 version */ + #endif + + 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 = MAKE_RSA_KEY(&genKey, bits, 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 good/bad args. */ + if (ret == 0) { + ret = wc_RsaKeyToDer(NULL, der, FOURK_BUF); + if (ret == BAD_FUNC_ARG) { + /* Get just the output length */ + ret = wc_RsaKeyToDer(&genKey, NULL, 0); + } + if (ret > 0) { + /* 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 good/bad args. */ + if (ret == 0) { + ret = wc_RsaKeyToDer(NULL, der, FOURK_BUF); + if (ret == USER_CRYPTO_ERROR) { + /* Get just the output length */ + ret = wc_RsaKeyToDer(&genKey, NULL, 0); + } + if (ret > 0) { + /* 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(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) &&\ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + RsaKey key; + WC_RNG rng; + byte* der; + #ifndef WOLFSSL_SP_MATH + int bits = 1024; + word32 derLen = 162; + #else + int bits = 2048; + word32 derLen = 290; + #endif + + 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 = MAKE_RSA_KEY(&key, bits, 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 plainLen = 25; + word32 inLen = (word32)XSTRLEN(inStr); + #ifndef WOLFSSL_SP_MATH + int bits = 1024; + word32 cipherLen = 128; + #else + int bits = 2048; + word32 cipherLen = 256; + #endif + + 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 = MAKE_RSA_KEY(&key, bits, 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) && !defined(HAVE_FIPS) + /* 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 plainSz = 25; + byte* res = NULL; + int idx = 0; + #ifndef WOLFSSL_SP_MATH + int bits = 1024; + const word32 cipherSz = 128; + #else + int bits = 2048; + const word32 cipherSz = 256; + #endif + + 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 = MAKE_RSA_KEY(&key, bits, 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; + } + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + /* Decrypt */ + printf(testingFmt, "wc_RsaPrivateDecrypt_ex()"); + #if defined(WC_RSA_BLINDING) && !defined(HAVE_FIPS) + 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; + } + } + } +#endif + + 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 plainSz = 25; + word32 inLen = (word32)XSTRLEN(inStr); + word32 idx = 0; + #ifndef WOLFSSL_SP_MATH + int bits = 1024; + const word32 outSz = 128; + #else + int bits = 2048; + const word32 outSz = 256; + #endif + + 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 = MAKE_RSA_KEY(&key, bits, 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; + + ret = wc_InitRsaKey(&key, NULL); + + if (ret == 0) { + ret = wc_InitRng(&rng); + } + + printf(testingFmt, "wc_RsaEncryptSize()"); +#ifndef WOLFSSL_SP_MATH + if (ret == 0) { + ret = MAKE_RSA_KEY(&key, 1024, WC_RSA_EXPONENT, &rng); + if (ret == 0) { + ret = wc_RsaEncryptSize(&key); + } + if (ret == 128) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (wc_FreeRsaKey(&key) || ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = 0; + } +#endif + + if (ret == 0) { + ret = MAKE_RSA_KEY(&key, 2048, WC_RSA_EXPONENT, &rng); + if (ret == 0) { + ret = wc_RsaEncryptSize(&key); + } + if (ret == 256) { + 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); + #ifndef WOLFSSL_SP_MATH + int bits = 1024; + #else + int bits = 2048; + #endif + + ret = wc_InitRsaKey(&key, NULL); + if (ret == 0) { + ret = wc_InitRng(&rng); + } + + if (ret == 0) { + ret = MAKE_RSA_KEY(&key, bits, 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; + +#ifdef WOLFSSL_AES_128 + ret = wc_AesCcmSetKey(&aes, key16, sizeof(key16)); +#endif +#ifdef WOLFSSL_AES_192 + if (ret == 0) { + ret = wc_AesCcmSetKey(&aes, key24, sizeof(key24)); + } +#endif +#ifdef WOLFSSL_AES_256 + if (ret == 0) { + ret = wc_AesCcmSetKey(&aes, key32, sizeof(key32)); + } +#endif + + /* 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; +#if defined(HAVE_AESCCM) && defined(WOLFSSL_AES_128) + 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) + 1; /* Add null terminator */ + 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)); + XFILE fp = XFOPEN("./certs/dsa2048.der", "rb"); + if (fp == XBADFILE) { + return WOLFSSL_BAD_FILE; + } + bytes = (word32) XFREAD(tmp, 1, sizeof(tmp), fp); + XFCLOSE(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)); + XFILE fp = XFOPEN("./certs/dsa2048.der", "rb"); + if (fp == XBADFILE) + { + return WOLFSSL_BAD_FILE; + } + bytes = (word32) XFREAD(tmp, 1, sizeof(tmp), fp); + XFCLOSE(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; + } + } + + 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)); + XFILE fp = XFOPEN("./certs/dsa2048.der", "rb"); + if (fp == XBADFILE) { + return WOLFSSL_BAD_FILE; + } + bytes = (word32) XFREAD(tmp, 1, sizeof(tmp), fp); + XFCLOSE(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 */ + +/* + * Testing wc_DsaKeyToPublicDer() + * (indirectly testing setDsaPublicKey()) + */ +static int test_wc_DsaKeyToPublicDer(void) +{ + int ret = 0; +#ifndef HAVE_SELFTEST +#if !defined(NO_DSA) && defined(WOLFSSL_KEY_GEN) + DsaKey genKey; + WC_RNG rng; + byte* der; + + printf(testingFmt, "wc_DsaKeyToPublicDer()"); + + der = (byte*)XMALLOC(ONEK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ret = WOLFSSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_InitDsaKey(&genKey); + } + if (ret == 0) { + ret = wc_InitRng(&rng); + } + if (ret == 0) { + ret = wc_MakeDsaParameters(&rng, ONEK_BUF, &genKey); + } + if (ret == 0) { + ret = wc_MakeDsaKey(&rng, &genKey); + } + + if (ret == 0) { + ret = wc_DsaKeyToPublicDer(&genKey, der, ONEK_BUF); + if (ret >= 0) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_DsaKeyToPublicDer(NULL, der, FOURK_BUF); + if (ret == BAD_FUNC_ARG) { + ret = wc_DsaKeyToPublicDer(&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); + + XFREE(der,NULL,DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeDsaKey(&genKey); +#endif /* !defined(NO_DSA) && defined(WOLFSSL_KEY_GEN) */ +#endif /* HAVE_SELFTEST */ + return ret; + +} /* END test_wc_DsaKeyToPublicDer */ + +/* + * Testing wc_DsaImportParamsRaw() + */ +static int test_wc_DsaImportParamsRaw (void) +{ + int ret = 0; + +#if !defined(NO_DSA) + DsaKey key; + + /* [mod = L=1024, N=160], from CAVP KeyPair */ + const char* p = "d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d" + "4b725ef341eabb47cf8a7a8a41e792a156b7ce97206c4f9c" + "5ce6fc5ae7912102b6b502e59050b5b21ce263dddb2044b6" + "52236f4d42ab4b5d6aa73189cef1ace778d7845a5c1c1c71" + "47123188f8dc551054ee162b634d60f097f719076640e209" + "80a0093113a8bd73"; + const char* q = "96c5390a8b612c0e422bb2b0ea194a3ec935a281"; + const char* g = "06b7861abbd35cc89e79c52f68d20875389b127361ca66822" + "138ce4991d2b862259d6b4548a6495b195aa0e0b6137ca37e" + "b23b94074d3c3d300042bdf15762812b6333ef7b07ceba786" + "07610fcc9ee68491dbc1e34cd12615474e52b18bc934fb00c" + "61d39e7da8902291c4434a4e2224c3f4fd9f93cd6f4f17fc0" + "76341a7e7d9"; + + /* invalid p and q parameters */ + const char* invalidP = "d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d"; + const char* invalidQ = "96c5390a"; + + printf(testingFmt, "wc_DsaImportParamsRaw()"); + + ret = wc_InitDsaKey(&key); + if (ret == 0) { + ret = wc_DsaImportParamsRaw(&key, p, q, g); + } + + /* test bad args */ + if (ret == 0) { + /* null key struct */ + ret = wc_DsaImportParamsRaw(NULL, p, q, g); + if (ret == BAD_FUNC_ARG) { + /* null param pointers */ + ret = wc_DsaImportParamsRaw(&key, NULL, NULL, NULL); + } + + if (ret == BAD_FUNC_ARG) { + /* illegal p length */ + ret = wc_DsaImportParamsRaw(&key, invalidP, q, g); + } + + if (ret == BAD_FUNC_ARG) { + /* illegal q length */ + ret = wc_DsaImportParamsRaw(&key, p, invalidQ, g); + if (ret == BAD_FUNC_ARG) + ret = 0; + } + + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_FreeDsaKey(&key); + +#endif + + return ret; + +} /* END test_wc_DsaImportParamsRaw */ + +/* + * Testing wc_DsaImportParamsRawCheck() + */ +static int test_wc_DsaImportParamsRawCheck (void) +{ + int ret = 0; + +#if !defined(NO_DSA) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + DsaKey key; + int trusted = 0; + /* [mod = L=1024, N=160], from CAVP KeyPair */ + const char* p = "d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d" + "4b725ef341eabb47cf8a7a8a41e792a156b7ce97206c4f9c" + "5ce6fc5ae7912102b6b502e59050b5b21ce263dddb2044b6" + "52236f4d42ab4b5d6aa73189cef1ace778d7845a5c1c1c71" + "47123188f8dc551054ee162b634d60f097f719076640e209" + "80a0093113a8bd73"; + const char* q = "96c5390a8b612c0e422bb2b0ea194a3ec935a281"; + const char* g = "06b7861abbd35cc89e79c52f68d20875389b127361ca66822" + "138ce4991d2b862259d6b4548a6495b195aa0e0b6137ca37e" + "b23b94074d3c3d300042bdf15762812b6333ef7b07ceba786" + "07610fcc9ee68491dbc1e34cd12615474e52b18bc934fb00c" + "61d39e7da8902291c4434a4e2224c3f4fd9f93cd6f4f17fc0" + "76341a7e7d9"; + + /* invalid p and q parameters */ + const char* invalidP = "d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d"; + const char* invalidQ = "96c5390a"; + + printf(testingFmt, "wc_DsaImportParamsRawCheck()"); + + ret = wc_InitDsaKey(&key); + if (ret == 0) { + ret = wc_DsaImportParamsRawCheck(&key, p, q, g, trusted, NULL); + } + + /* test bad args */ + if (ret == 0) { + /* null key struct */ + ret = wc_DsaImportParamsRawCheck(NULL, p, q, g, trusted, NULL); + if (ret == BAD_FUNC_ARG) { + /* null param pointers */ + ret = wc_DsaImportParamsRawCheck(&key, NULL, NULL, NULL, trusted, NULL); + } + + if (ret == BAD_FUNC_ARG) { + /* illegal p length */ + ret = wc_DsaImportParamsRawCheck(&key, invalidP, q, g, trusted, NULL); + } + + if (ret == BAD_FUNC_ARG) { + /* illegal q length */ + ret = wc_DsaImportParamsRawCheck(&key, p, invalidQ, g, trusted, NULL); + if (ret == BAD_FUNC_ARG) + ret = 0; + } + + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_FreeDsaKey(&key); + +#endif + + return ret; + +} /* END test_wc_DsaImportParamsRawCheck */ + +/* + * Testing wc_DsaExportParamsRaw() + */ +static int test_wc_DsaExportParamsRaw (void) +{ + int ret = 0; + +#if !defined(NO_DSA) + DsaKey key; + + /* [mod = L=1024, N=160], from CAVP KeyPair */ + const char* p = "d38311e2cd388c3ed698e82fdf88eb92b5a9a483dc88005d" + "4b725ef341eabb47cf8a7a8a41e792a156b7ce97206c4f9c" + "5ce6fc5ae7912102b6b502e59050b5b21ce263dddb2044b6" + "52236f4d42ab4b5d6aa73189cef1ace778d7845a5c1c1c71" + "47123188f8dc551054ee162b634d60f097f719076640e209" + "80a0093113a8bd73"; + const char* q = "96c5390a8b612c0e422bb2b0ea194a3ec935a281"; + const char* g = "06b7861abbd35cc89e79c52f68d20875389b127361ca66822" + "138ce4991d2b862259d6b4548a6495b195aa0e0b6137ca37e" + "b23b94074d3c3d300042bdf15762812b6333ef7b07ceba786" + "07610fcc9ee68491dbc1e34cd12615474e52b18bc934fb00c" + "61d39e7da8902291c4434a4e2224c3f4fd9f93cd6f4f17fc0" + "76341a7e7d9"; + + const char* pCompare = "\xd3\x83\x11\xe2\xcd\x38\x8c\x3e\xd6\x98\xe8\x2f" + "\xdf\x88\xeb\x92\xb5\xa9\xa4\x83\xdc\x88\x00\x5d" + "\x4b\x72\x5e\xf3\x41\xea\xbb\x47\xcf\x8a\x7a\x8a" + "\x41\xe7\x92\xa1\x56\xb7\xce\x97\x20\x6c\x4f\x9c" + "\x5c\xe6\xfc\x5a\xe7\x91\x21\x02\xb6\xb5\x02\xe5" + "\x90\x50\xb5\xb2\x1c\xe2\x63\xdd\xdb\x20\x44\xb6" + "\x52\x23\x6f\x4d\x42\xab\x4b\x5d\x6a\xa7\x31\x89" + "\xce\xf1\xac\xe7\x78\xd7\x84\x5a\x5c\x1c\x1c\x71" + "\x47\x12\x31\x88\xf8\xdc\x55\x10\x54\xee\x16\x2b" + "\x63\x4d\x60\xf0\x97\xf7\x19\x07\x66\x40\xe2\x09" + "\x80\xa0\x09\x31\x13\xa8\xbd\x73"; + const char* qCompare = "\x96\xc5\x39\x0a\x8b\x61\x2c\x0e\x42\x2b\xb2\xb0" + "\xea\x19\x4a\x3e\xc9\x35\xa2\x81"; + const char* gCompare = "\x06\xb7\x86\x1a\xbb\xd3\x5c\xc8\x9e\x79\xc5\x2f" + "\x68\xd2\x08\x75\x38\x9b\x12\x73\x61\xca\x66\x82" + "\x21\x38\xce\x49\x91\xd2\xb8\x62\x25\x9d\x6b\x45" + "\x48\xa6\x49\x5b\x19\x5a\xa0\xe0\xb6\x13\x7c\xa3" + "\x7e\xb2\x3b\x94\x07\x4d\x3c\x3d\x30\x00\x42\xbd" + "\xf1\x57\x62\x81\x2b\x63\x33\xef\x7b\x07\xce\xba" + "\x78\x60\x76\x10\xfc\xc9\xee\x68\x49\x1d\xbc\x1e" + "\x34\xcd\x12\x61\x54\x74\xe5\x2b\x18\xbc\x93\x4f" + "\xb0\x0c\x61\xd3\x9e\x7d\xa8\x90\x22\x91\xc4\x43" + "\x4a\x4e\x22\x24\xc3\xf4\xfd\x9f\x93\xcd\x6f\x4f" + "\x17\xfc\x07\x63\x41\xa7\xe7\xd9"; + + byte pOut[MAX_DSA_PARAM_SIZE]; + byte qOut[MAX_DSA_PARAM_SIZE]; + byte gOut[MAX_DSA_PARAM_SIZE]; + word32 pOutSz, qOutSz, gOutSz; + + printf(testingFmt, "wc_DsaExportParamsRaw()"); + + ret = wc_InitDsaKey(&key); + if (ret == 0) { + /* first test using imported raw parameters, for expected */ + ret = wc_DsaImportParamsRaw(&key, p, q, g); + } + + if (ret == 0) { + pOutSz = sizeof(pOut); + qOutSz = sizeof(qOut); + gOutSz = sizeof(gOut); + ret = wc_DsaExportParamsRaw(&key, pOut, &pOutSz, qOut, &qOutSz, + gOut, &gOutSz); + } + + if (ret == 0) { + /* validate exported parameters are correct */ + if ((XMEMCMP(pOut, pCompare, pOutSz) != 0) || + (XMEMCMP(qOut, qCompare, qOutSz) != 0) || + (XMEMCMP(gOut, gCompare, gOutSz) != 0) ) { + ret = -1; + } + } + + /* test bad args */ + if (ret == 0) { + /* null key struct */ + ret = wc_DsaExportParamsRaw(NULL, pOut, &pOutSz, qOut, &qOutSz, + gOut, &gOutSz); + + if (ret == BAD_FUNC_ARG) { + /* null output pointers */ + ret = wc_DsaExportParamsRaw(&key, NULL, &pOutSz, NULL, &qOutSz, + NULL, &gOutSz); + } + + if (ret == LENGTH_ONLY_E) { + /* null output size pointers */ + ret = wc_DsaExportParamsRaw(&key, pOut, NULL, qOut, NULL, + gOut, NULL); + } + + if (ret == BAD_FUNC_ARG) { + /* p output buffer size too small */ + pOutSz = 1; + ret = wc_DsaExportParamsRaw(&key, pOut, &pOutSz, qOut, &qOutSz, + gOut, &gOutSz); + pOutSz = sizeof(pOut); + } + + if (ret == BUFFER_E) { + /* q output buffer size too small */ + qOutSz = 1; + ret = wc_DsaExportParamsRaw(&key, pOut, &pOutSz, qOut, &qOutSz, + gOut, &gOutSz); + qOutSz = sizeof(qOut); + } + + if (ret == BUFFER_E) { + /* g output buffer size too small */ + gOutSz = 1; + ret = wc_DsaExportParamsRaw(&key, pOut, &pOutSz, qOut, &qOutSz, + gOut, &gOutSz); + if (ret == BUFFER_E) + ret = 0; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_FreeDsaKey(&key); + +#endif + + return ret; + +} /* END test_wc_DsaExportParamsRaw */ + +/* + * Testing wc_DsaExportKeyRaw() + */ +static int test_wc_DsaExportKeyRaw (void) +{ + int ret = 0; + +#if !defined(NO_DSA) && defined(WOLFSSL_KEY_GEN) + DsaKey key; + WC_RNG rng; + + byte xOut[MAX_DSA_PARAM_SIZE]; + byte yOut[MAX_DSA_PARAM_SIZE]; + word32 xOutSz, yOutSz; + + printf(testingFmt, "wc_DsaExportKeyRaw()"); + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_InitDsaKey(&key); + } + + if (ret == 0) { + ret = wc_MakeDsaParameters(&rng, 1024, &key); + + if (ret == 0) { + ret = wc_MakeDsaKey(&rng, &key); + } + } + + /* try successful export */ + if (ret == 0) { + xOutSz = sizeof(xOut); + yOutSz = sizeof(yOut); + ret = wc_DsaExportKeyRaw(&key, xOut, &xOutSz, yOut, &yOutSz); + } + + /* test bad args */ + if (ret == 0) { + /* null key struct */ + ret = wc_DsaExportKeyRaw(NULL, xOut, &xOutSz, yOut, &yOutSz); + + if (ret == BAD_FUNC_ARG) { + /* null output pointers */ + ret = wc_DsaExportKeyRaw(&key, NULL, &xOutSz, NULL, &yOutSz); + } + + if (ret == LENGTH_ONLY_E) { + /* null output size pointers */ + ret = wc_DsaExportKeyRaw(&key, xOut, NULL, yOut, NULL); + } + + if (ret == BAD_FUNC_ARG) { + /* x output buffer size too small */ + xOutSz = 1; + ret = wc_DsaExportKeyRaw(&key, xOut, &xOutSz, yOut, &yOutSz); + xOutSz = sizeof(xOut); + } + + if (ret == BUFFER_E) { + /* y output buffer size too small */ + yOutSz = 1; + ret = wc_DsaExportKeyRaw(&key, xOut, &xOutSz, yOut, &yOutSz); + + if (ret == BUFFER_E) + ret = 0; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_FreeDsaKey(&key); + wc_FreeRng(&rng); + +#endif + + return ret; + +} /* END test_wc_DsaExportParamsRaw */ + + +/* + * Testing wc_ed25519_make_key(). + */ +static int test_wc_ed25519_make_key (void) +{ + int ret = 0; + +#if defined(HAVE_ED25519) + ed25519_key key; + WC_RNG rng; + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ed25519_init(&key); + } + printf(testingFmt, "wc_ed25519_make_key()"); + if (ret == 0) { + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key); + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ed25519_make_key(NULL, ED25519_KEY_SIZE, &key); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE - 1, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE + 1, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed25519_free(&key); + +#endif + return ret; + +} /* END test_wc_ed25519_make_key */ + + +/* + * Testing wc_ed25519_init() + */ +static int test_wc_ed25519_init (void) +{ + int ret = 0; + +#if defined(HAVE_ED25519) + + ed25519_key key; + + printf(testingFmt, "wc_ed25519_init()"); + + ret = wc_ed25519_init(&key); + + /* Test bad args. */ + if (ret == 0) { + ret = wc_ed25519_init(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_ed25519_free(&key); + +#endif + return ret; + +} /* END test_wc_ed25519_init */ + +/* + * Test wc_ed25519_sign_msg() and wc_ed25519_verify_msg() + */ +static int test_wc_ed25519_sign_msg (void) +{ + int ret = 0; + +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_SIGN) + WC_RNG rng; + ed25519_key key; + byte msg[] = "Everybody gets Friday off.\n"; + byte sig[ED25519_SIG_SIZE]; + word32 msglen = sizeof(msg); + word32 siglen = sizeof(sig); + word32 badSigLen = sizeof(sig) - 1; + int verify_ok = 0; /*1 = Verify success.*/ + + /* Initialize stack variables. */ + XMEMSET(sig, 0, siglen); + + /* Initialize key. */ + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ed25519_init(&key); + if (ret == 0) { + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key); + } + } + + printf(testingFmt, "wc_ed25519_sign_msg()"); + + if (ret == 0) { + ret = wc_ed25519_sign_msg(msg, msglen, sig, &siglen, &key); + } + /* Test bad args. */ + if (ret == 0 && siglen == ED25519_SIG_SIZE) { + ret = wc_ed25519_sign_msg(NULL, msglen, sig, &siglen, &key); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_sign_msg(msg, msglen, NULL, &siglen, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_sign_msg(msg, msglen, sig, NULL, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_sign_msg(msg, msglen, sig, &siglen, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_sign_msg(msg, msglen, sig, &badSigLen, &key); + } + if (ret == BUFFER_E && badSigLen == ED25519_SIG_SIZE) { + badSigLen -= 1; + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } /* END sign */ + + printf(resultFmt, ret == 0 ? passed : failed); + #ifdef HAVE_ED25519_VERIFY + printf(testingFmt, "wc_ed25519_verify_msg()"); + + if (ret == 0) { + + ret = wc_ed25519_verify_msg(sig, siglen, msg, msglen, &verify_ok, &key); + if (ret == 0 && verify_ok == 1) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_ed25519_verify_msg(NULL, siglen, msg, msglen, &verify_ok, + &key); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_verify_msg(sig, siglen, NULL, msglen, + &verify_ok, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_verify_msg(sig, siglen, msg, msglen, + NULL, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_verify_msg(sig, siglen, msg, msglen, + &verify_ok, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_verify_msg(sig, badSigLen, msg, msglen, + &verify_ok, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + } /* END verify. */ + + printf(resultFmt, ret == 0 ? passed : failed); + #endif /* Verify. */ + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed25519_free(&key); + +#endif + return ret; + +} /* END test_wc_ed25519_sign_msg */ + +/* + * Testing wc_ed25519_import_public() + */ +static int test_wc_ed25519_import_public (void) +{ + int ret = 0; + +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) + WC_RNG rng; + ed25519_key pubKey; + const byte in[] = "Ed25519PublicKeyUnitTest......\n"; + word32 inlen = sizeof(in); + + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ed25519_init(&pubKey); + if (ret == 0) { + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &pubKey); + } + } + printf(testingFmt, "wc_ed25519_import_public()"); + + if (ret == 0) { + ret = wc_ed25519_import_public(in, inlen, &pubKey); + + if (ret == 0 && XMEMCMP(in, pubKey.p, inlen) == 0) { + ret = 0; + } else { + ret = SSL_FATAL_ERROR; + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_ed25519_import_public(NULL, inlen, &pubKey); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_import_public(in, inlen, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_import_public(in, inlen - 1, &pubKey); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed25519_free(&pubKey); + +#endif + return ret; + +} /* END wc_ed25519_import_public */ + +/* + * Testing wc_ed25519_import_private_key() + */ +static int test_wc_ed25519_import_private_key (void) +{ + int ret = 0; + +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) + WC_RNG rng; + ed25519_key key; + const byte privKey[] = "Ed25519PrivateKeyUnitTest.....\n"; + const byte pubKey[] = "Ed25519PublicKeyUnitTest......\n"; + word32 privKeySz = sizeof(privKey); + word32 pubKeySz = sizeof(pubKey); + + ret = wc_InitRng(&rng); + if (ret != 0) { + return ret; + } + ret = wc_ed25519_init(&key); + if (ret != 0) { + wc_FreeRng(&rng); + return ret; + } + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key); + + printf(testingFmt, "wc_ed25519_import_private_key()"); + + if (ret == 0) { + ret = wc_ed25519_import_private_key(privKey, privKeySz, pubKey, + pubKeySz, &key); + if (ret == 0 && (XMEMCMP(pubKey, key.p, privKeySz) != 0 + || XMEMCMP(privKey, key.k, pubKeySz) != 0)) { + ret = SSL_FATAL_ERROR; + } + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_ed25519_import_private_key(NULL, privKeySz, pubKey, pubKeySz, + &key); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_import_private_key(privKey, privKeySz, NULL, + pubKeySz, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_import_private_key(privKey, privKeySz, pubKey, + pubKeySz, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_import_private_key(privKey, privKeySz - 1, pubKey, + pubKeySz, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_import_private_key(privKey, privKeySz, pubKey, + pubKeySz - 1, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed25519_free(&key); + +#endif + return ret; + +} /* END test_wc_ed25519_import_private_key */ + +/* + * Testing wc_ed25519_export_public() and wc_ed25519_export_private_only() + */ +static int test_wc_ed25519_export (void) +{ + int ret = 0; + +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) + WC_RNG rng; + ed25519_key key; + byte priv[ED25519_PRV_KEY_SIZE]; + byte pub[ED25519_PUB_KEY_SIZE]; + word32 privSz = sizeof(priv); + word32 pubSz = sizeof(pub); + + ret = wc_InitRng(&rng); + if (ret != 0) { + return ret; + } + + ret = wc_ed25519_init(&key); + if (ret != 0) { + wc_FreeRng(&rng); + return ret; + } + + if (ret == 0) { + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key); + } + + printf(testingFmt, "wc_ed25519_export_public()"); + + if (ret == 0) { + ret = wc_ed25519_export_public(&key, pub, &pubSz); + if (ret == 0 && (pubSz != ED25519_KEY_SIZE + || XMEMCMP(key.p, pub, pubSz) != 0)) { + ret = SSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_ed25519_export_public(NULL, pub, &pubSz); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_export_public(&key, NULL, &pubSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_export_public(&key, pub, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + printf(testingFmt, "wc_ed25519_export_private_only()"); + + if (ret == 0) { + ret = wc_ed25519_export_private_only(&key, priv, &privSz); + if (ret == 0 && (privSz != ED25519_KEY_SIZE + || XMEMCMP(key.k, priv, privSz) != 0)) { + ret = SSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_ed25519_export_private_only(NULL, priv, &privSz); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_export_private_only(&key, NULL, &privSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_export_private_only(&key, priv, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed25519_free(&key); + +#endif + return ret; + +} /* END test_wc_ed25519_export */ + +/* + * Testing wc_ed25519_size() + */ +static int test_wc_ed25519_size (void) +{ + int ret = 0; +#if defined(HAVE_ED25519) + WC_RNG rng; + ed25519_key key; + + ret = wc_InitRng(&rng); + if (ret != 0) { + return ret; + } + ret = wc_ed25519_init(&key); + if (ret != 0) { + wc_FreeRng(&rng); + return ret; + } + + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key); + if (ret != 0) { + wc_FreeRng(&rng); + wc_ed25519_free(&key); + return ret; + } + + printf(testingFmt, "wc_ed25519_size()"); + ret = wc_ed25519_size(&key); + /* Test bad args. */ + if (ret == ED25519_KEY_SIZE) { + ret = wc_ed25519_size(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + + if (ret == 0) { + printf(testingFmt, "wc_ed25519_sig_size()"); + + ret = wc_ed25519_sig_size(&key); + if (ret == ED25519_SIG_SIZE) { + ret = 0; + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ed25519_sig_size(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + } /* END wc_ed25519_sig_size() */ + + if (ret == 0) { + printf(testingFmt, "wc_ed25519_pub_size"); + ret = wc_ed25519_pub_size(&key); + if (ret == ED25519_PUB_KEY_SIZE) { + ret = 0; + } + if (ret == 0) { + ret = wc_ed25519_pub_size(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + } /* END wc_ed25519_pub_size */ + + if (ret == 0) { + printf(testingFmt, "wc_ed25519_priv_size"); + ret = wc_ed25519_priv_size(&key); + if (ret == ED25519_PRV_KEY_SIZE) { + ret = 0; + } + if (ret == 0) { + ret = wc_ed25519_priv_size(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + } /* END wc_ed25519_pub_size */ + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed25519_free(&key); + +#endif + return ret; + +} /* END test_wc_ed25519_size */ + +/* + * Testing wc_ed25519_export_private() and wc_ed25519_export_key() + */ +static int test_wc_ed25519_exportKey (void) +{ + int ret = 0; +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) + WC_RNG rng; + ed25519_key key; + byte priv[ED25519_PRV_KEY_SIZE]; + byte pub[ED25519_PUB_KEY_SIZE]; + byte privOnly[ED25519_PRV_KEY_SIZE]; + word32 privSz = sizeof(priv); + word32 pubSz = sizeof(pub); + word32 privOnlySz = sizeof(privOnly); + + ret = wc_InitRng(&rng); + if (ret != 0) { + return ret; + } + ret = wc_ed25519_init(&key); + if (ret != 0) { + wc_FreeRng(&rng); + return ret; + } + + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key); + if (ret != 0) { + wc_FreeRng(&rng); + wc_ed25519_free(&key); + return ret; + } + + printf(testingFmt, "wc_ed25519_export_private()"); + + ret = wc_ed25519_export_private(&key, privOnly, &privOnlySz); + if (ret == 0) { + ret = wc_ed25519_export_private(NULL, privOnly, &privOnlySz); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_export_private(&key, NULL, &privOnlySz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_export_private(&key, privOnly, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (ret == 0) { + printf(testingFmt, "wc_ed25519_export_key()"); + + ret = wc_ed25519_export_key(&key, priv, &privSz, pub, &pubSz); + if (ret == 0) { + ret = wc_ed25519_export_key(NULL, priv, &privSz, pub, &pubSz); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_export_key(&key, NULL, &privSz, pub, &pubSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_export_key(&key, priv, NULL, pub, &pubSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_export_key(&key, priv, &privSz, NULL, &pubSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed25519_export_key(&key, priv, &privSz, pub, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + } /* END wc_ed25519_export_key() */ + + /* Cross check output. */ + if (ret == 0 && XMEMCMP(priv, privOnly, privSz) != 0) { + ret = SSL_FATAL_ERROR; + } + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed25519_free(&key); + +#endif + return ret; + +} /* END test_wc_ed25519_exportKey */ + +/* + * Testing wc_Ed25519PublicKeyToDer + */ +static int test_wc_Ed25519PublicKeyToDer (void) +{ + int ret = 0; + +#if defined(HAVE_ED25519) && (defined(WOLFSSL_CERT_GEN) || \ + defined(WOLFSSL_KEY_GEN)) + int tmp; + ed25519_key key; + byte derBuf[1024]; + + printf(testingFmt, "wc_Ed25519PublicKeyToDer()"); + + /* Test bad args */ + tmp = wc_Ed25519PublicKeyToDer(NULL, NULL, 0, 0); + if (tmp != BAD_FUNC_ARG) { + ret = SSL_FATAL_ERROR; + } + + if (ret == 0) { + wc_ed25519_init(&key); + tmp = wc_Ed25519PublicKeyToDer(&key, derBuf, 0, 0); + if (tmp != BUFFER_E) { + ret = SSL_FATAL_ERROR; + } + wc_ed25519_free(&key); + } + + /* Test good args */ + if (ret == 0) { + WC_RNG rng; + ret = wc_InitRng(&rng); + if (ret != 0) { + return ret; + } + ret = wc_ed25519_init(&key); + if (ret != 0) { + wc_FreeRng(&rng); + return ret; + } + + ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key); + if (ret != 0) { + wc_FreeRng(&rng); + wc_ed25519_free(&key); + return ret; + } + + tmp = wc_Ed25519PublicKeyToDer(&key, derBuf, 1024, 1); + if (tmp <= 0) { + ret = SSL_FATAL_ERROR; + } + + wc_FreeRng(&rng); + wc_ed25519_free(&key); + } + printf(resultFmt, ret == 0 ? passed : failed); +#endif + return ret; + +} /* END testing wc_Ed25519PublicKeyToDer */ + +/* + * Testing wc_curve25519_init and wc_curve25519_free. + */ +static int test_wc_curve25519_init (void) +{ + int ret = 0; + +#if defined(HAVE_CURVE25519) + + curve25519_key key; + + printf(testingFmt, "wc_curve25519_init()"); + ret = wc_curve25519_init(&key); + + /* Test bad args for wc_curve25519_init */ + if (ret == 0) { + ret = wc_curve25519_init(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + /* Test good args for wc_curve_25519_free */ + wc_curve25519_free(&key); + + wc_curve25519_free(NULL); + +#endif + return ret; + +} /* END test_wc_curve25519_init and wc_curve_25519_free*/ +/* + * Testing test_wc_curve25519_size. + */ +static int test_wc_curve25519_size (void) +{ + int ret = 0; + +#if defined(HAVE_CURVE25519) + + curve25519_key key; + + printf(testingFmt, "wc_curve25519_size()"); + + ret = wc_curve25519_init(&key); + + /* Test good args for wc_curve25519_size */ + if (ret == 0) { + ret = wc_curve25519_size(&key); + } + + /* Test bad args for wc_curve25519_size */ + if (ret != 0) { + ret = wc_curve25519_size(NULL); + } + + printf(resultFmt, ret == 0 ? passed : failed); + wc_curve25519_free(&key); +#endif + return ret; + +} /* END test_wc_curve25519_size*/ + +/* + * Testing wc_ed448_make_key(). + */ +static int test_wc_ed448_make_key (void) +{ + int ret = 0; + +#if defined(HAVE_ED448) + ed448_key key; + WC_RNG rng; + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ed448_init(&key); + } + printf(testingFmt, "wc_ed448_make_key()"); + if (ret == 0) { + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key); + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ed448_make_key(NULL, ED448_KEY_SIZE, &key); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE - 1, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE + 1, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed448_free(&key); + +#endif + return ret; + +} /* END test_wc_ed448_make_key */ + + +/* + * Testing wc_ed448_init() + */ +static int test_wc_ed448_init (void) +{ + int ret = 0; + +#if defined(HAVE_ED448) + + ed448_key key; + + printf(testingFmt, "wc_ed448_init()"); + + ret = wc_ed448_init(&key); + + /* Test bad args. */ + if (ret == 0) { + ret = wc_ed448_init(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_ed448_free(&key); + +#endif + return ret; + +} /* END test_wc_ed448_init */ + +/* + * Test wc_ed448_sign_msg() and wc_ed448_verify_msg() + */ +static int test_wc_ed448_sign_msg (void) +{ + int ret = 0; + +#if defined(HAVE_ED448) && defined(HAVE_ED448_SIGN) + WC_RNG rng; + ed448_key key; + byte msg[] = "Everybody gets Friday off.\n"; + byte sig[ED448_SIG_SIZE]; + word32 msglen = sizeof(msg); + word32 siglen = sizeof(sig); + word32 badSigLen = sizeof(sig) - 1; + int verify_ok = 0; /*1 = Verify success.*/ + + /* Initialize stack variables. */ + XMEMSET(sig, 0, siglen); + + /* Initialize key. */ + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ed448_init(&key); + if (ret == 0) { + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key); + } + } + + printf(testingFmt, "wc_ed448_sign_msg()"); + + if (ret == 0) { + ret = wc_ed448_sign_msg(msg, msglen, sig, &siglen, &key, NULL, 0); + } + /* Test bad args. */ + if (ret == 0 && siglen == ED448_SIG_SIZE) { + ret = wc_ed448_sign_msg(NULL, msglen, sig, &siglen, &key, NULL, 0); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_sign_msg(msg, msglen, NULL, &siglen, &key, NULL, 0); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_sign_msg(msg, msglen, sig, NULL, &key, NULL, 0); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_sign_msg(msg, msglen, sig, &siglen, NULL, NULL, 0); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_sign_msg(msg, msglen, sig, &badSigLen, &key, + NULL, 0); + } + if (ret == BUFFER_E && badSigLen == ED448_SIG_SIZE) { + badSigLen -= 1; + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } /* END sign */ + + printf(resultFmt, ret == 0 ? passed : failed); + #ifdef HAVE_ED448_VERIFY + printf(testingFmt, "wc_ed448_verify_msg()"); + + if (ret == 0) { + + ret = wc_ed448_verify_msg(sig, siglen, msg, msglen, &verify_ok, + &key, NULL, 0); + if (ret == 0 && verify_ok == 1) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_ed448_verify_msg(NULL, siglen, msg, msglen, &verify_ok, + &key, NULL, 0); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_verify_msg(sig, siglen, NULL, msglen, + &verify_ok, &key, NULL, 0); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_verify_msg(sig, siglen, msg, msglen, + NULL, &key, NULL, 0); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_verify_msg(sig, siglen, msg, msglen, + &verify_ok, NULL, NULL, 0); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_verify_msg(sig, badSigLen, msg, msglen, + &verify_ok, &key, NULL, 0); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + } /* END verify. */ + + printf(resultFmt, ret == 0 ? passed : failed); + #endif /* Verify. */ + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed448_free(&key); + +#endif + return ret; + +} /* END test_wc_ed448_sign_msg */ + +/* + * Testing wc_ed448_import_public() + */ +static int test_wc_ed448_import_public (void) +{ + int ret = 0; + +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) + WC_RNG rng; + ed448_key pubKey; + const byte in[] = + "Ed448PublicKeyUnitTest.................................\n"; + word32 inlen = sizeof(in); + + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ed448_init(&pubKey); + if (ret == 0) { + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE, &pubKey); + } + } + printf(testingFmt, "wc_ed448_import_public()"); + + if (ret == 0) { + ret = wc_ed448_import_public(in, inlen, &pubKey); + + if (ret == 0 && XMEMCMP(in, pubKey.p, inlen) == 0) { + ret = 0; + } else { + ret = SSL_FATAL_ERROR; + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_ed448_import_public(NULL, inlen, &pubKey); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_import_public(in, inlen, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_import_public(in, inlen - 1, &pubKey); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed448_free(&pubKey); + +#endif + return ret; + +} /* END wc_ed448_import_public */ + +/* + * Testing wc_ed448_import_private_key() + */ +static int test_wc_ed448_import_private_key (void) +{ + int ret = 0; + +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) + WC_RNG rng; + ed448_key key; + const byte privKey[] = + "Ed448PrivateKeyUnitTest................................\n"; + const byte pubKey[] = + "Ed448PublicKeyUnitTest.................................\n"; + word32 privKeySz = sizeof(privKey); + word32 pubKeySz = sizeof(pubKey); + + ret = wc_InitRng(&rng); + if (ret != 0) { + return ret; + } + ret = wc_ed448_init(&key); + if (ret != 0) { + wc_FreeRng(&rng); + return ret; + } + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key); + + printf(testingFmt, "wc_ed448_import_private_key()"); + + if (ret == 0) { + ret = wc_ed448_import_private_key(privKey, privKeySz, pubKey, pubKeySz, + &key); + if (ret == 0 && (XMEMCMP(pubKey, key.p, privKeySz) != 0 || + XMEMCMP(privKey, key.k, pubKeySz) != 0)) { + ret = SSL_FATAL_ERROR; + } + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_ed448_import_private_key(NULL, privKeySz, pubKey, pubKeySz, + &key); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_import_private_key(privKey, privKeySz, NULL, + pubKeySz, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_import_private_key(privKey, privKeySz, pubKey, + pubKeySz, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_import_private_key(privKey, privKeySz - 1, pubKey, + pubKeySz, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_import_private_key(privKey, privKeySz, pubKey, + pubKeySz - 1, &key); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed448_free(&key); + +#endif + return ret; + +} /* END test_wc_ed448_import_private_key */ + +/* + * Testing wc_ed448_export_public() and wc_ed448_export_private_only() + */ +static int test_wc_ed448_export (void) +{ + int ret = 0; + +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) + WC_RNG rng; + ed448_key key; + byte priv[ED448_PRV_KEY_SIZE]; + byte pub[ED448_PUB_KEY_SIZE]; + word32 privSz = sizeof(priv); + word32 pubSz = sizeof(pub); + + ret = wc_InitRng(&rng); + if (ret != 0) { + return ret; + } + + ret = wc_ed448_init(&key); + if (ret != 0) { + wc_FreeRng(&rng); + return ret; + } + + if (ret == 0) { + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key); + } + + printf(testingFmt, "wc_ed448_export_public()"); + + if (ret == 0) { + ret = wc_ed448_export_public(&key, pub, &pubSz); + if (ret == 0 && (pubSz != ED448_KEY_SIZE || + XMEMCMP(key.p, pub, pubSz) != 0)) { + ret = SSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_ed448_export_public(NULL, pub, &pubSz); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_export_public(&key, NULL, &pubSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_export_public(&key, pub, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + printf(testingFmt, "wc_ed448_export_private_only()"); + + if (ret == 0) { + ret = wc_ed448_export_private_only(&key, priv, &privSz); + if (ret == 0 && (privSz != ED448_KEY_SIZE || + XMEMCMP(key.k, priv, privSz) != 0)) { + ret = SSL_FATAL_ERROR; + } + if (ret == 0) { + ret = wc_ed448_export_private_only(NULL, priv, &privSz); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_export_private_only(&key, NULL, &privSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_export_private_only(&key, priv, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed448_free(&key); + +#endif + return ret; + +} /* END test_wc_ed448_export */ + +/* + * Testing wc_ed448_size() + */ +static int test_wc_ed448_size (void) +{ + int ret = 0; +#if defined(HAVE_ED448) + WC_RNG rng; + ed448_key key; + + ret = wc_InitRng(&rng); + if (ret != 0) { + return ret; + } + ret = wc_ed448_init(&key); + if (ret != 0) { + wc_FreeRng(&rng); + return ret; + } + + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key); + if (ret != 0) { + wc_FreeRng(&rng); + wc_ed448_free(&key); + return ret; + } + + printf(testingFmt, "wc_ed448_size()"); + ret = wc_ed448_size(&key); + /* Test bad args. */ + if (ret == ED448_KEY_SIZE) { + ret = wc_ed448_size(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + + if (ret == 0) { + printf(testingFmt, "wc_ed448_sig_size()"); + + ret = wc_ed448_sig_size(&key); + if (ret == ED448_SIG_SIZE) { + ret = 0; + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ed448_sig_size(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + } /* END wc_ed448_sig_size() */ + + if (ret == 0) { + printf(testingFmt, "wc_ed448_pub_size"); + ret = wc_ed448_pub_size(&key); + if (ret == ED448_PUB_KEY_SIZE) { + ret = 0; + } + if (ret == 0) { + ret = wc_ed448_pub_size(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + } /* END wc_ed448_pub_size */ + + if (ret == 0) { + printf(testingFmt, "wc_ed448_priv_size"); + ret = wc_ed448_priv_size(&key); + if (ret == ED448_PRV_KEY_SIZE) { + ret = 0; + } + if (ret == 0) { + ret = wc_ed448_priv_size(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + } /* END wc_ed448_pub_size */ + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed448_free(&key); + +#endif + return ret; + +} /* END test_wc_ed448_size */ + +/* + * Testing wc_ed448_export_private() and wc_ed448_export_key() + */ +static int test_wc_ed448_exportKey (void) +{ + int ret = 0; +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) + WC_RNG rng; + ed448_key key; + byte priv[ED448_PRV_KEY_SIZE]; + byte pub[ED448_PUB_KEY_SIZE]; + byte privOnly[ED448_PRV_KEY_SIZE]; + word32 privSz = sizeof(priv); + word32 pubSz = sizeof(pub); + word32 privOnlySz = sizeof(privOnly); + + ret = wc_InitRng(&rng); + if (ret != 0) { + return ret; + } + ret = wc_ed448_init(&key); + if (ret != 0) { + wc_FreeRng(&rng); + return ret; + } + + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key); + if (ret != 0) { + wc_FreeRng(&rng); + wc_ed448_free(&key); + return ret; + } + + printf(testingFmt, "wc_ed448_export_private()"); + + ret = wc_ed448_export_private(&key, privOnly, &privOnlySz); + if (ret == 0) { + ret = wc_ed448_export_private(NULL, privOnly, &privOnlySz); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_export_private(&key, NULL, &privOnlySz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_export_private(&key, privOnly, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (ret == 0) { + printf(testingFmt, "wc_ed448_export_key()"); + + ret = wc_ed448_export_key(&key, priv, &privSz, pub, &pubSz); + if (ret == 0) { + ret = wc_ed448_export_key(NULL, priv, &privSz, pub, &pubSz); + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_export_key(&key, NULL, &privSz, pub, &pubSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_export_key(&key, priv, NULL, pub, &pubSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_export_key(&key, priv, &privSz, NULL, &pubSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ed448_export_key(&key, priv, &privSz, pub, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + } /* END wc_ed448_export_key() */ + + /* Cross check output. */ + if (ret == 0 && XMEMCMP(priv, privOnly, privSz) != 0) { + ret = SSL_FATAL_ERROR; + } + + if (wc_FreeRng(&rng) && ret == 0) { + ret = SSL_FATAL_ERROR; + } + wc_ed448_free(&key); + +#endif + return ret; + +} /* END test_wc_ed448_exportKey */ + +/* + * Testing wc_Ed448PublicKeyToDer + */ +static int test_wc_Ed448PublicKeyToDer (void) +{ + int ret = 0; + +#if defined(HAVE_ED448) && (defined(WOLFSSL_CERT_GEN) || \ + defined(WOLFSSL_KEY_GEN)) + int tmp; + ed448_key key; + byte derBuf[1024]; + + printf(testingFmt, "wc_Ed448PublicKeyToDer()"); + + /* Test bad args */ + tmp = wc_Ed448PublicKeyToDer(NULL, NULL, 0, 0); + if (tmp != BAD_FUNC_ARG) { + ret = SSL_FATAL_ERROR; + } + + if (ret == 0) { + wc_ed448_init(&key); + tmp = wc_Ed448PublicKeyToDer(&key, derBuf, 0, 0); + if (tmp != BUFFER_E) { + ret = SSL_FATAL_ERROR; + } + wc_ed448_free(&key); + } + + /* Test good args */ + if (ret == 0) { + WC_RNG rng; + ret = wc_InitRng(&rng); + if (ret != 0) { + return ret; + } + ret = wc_ed448_init(&key); + if (ret != 0) { + wc_FreeRng(&rng); + return ret; + } + + ret = wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key); + if (ret != 0) { + wc_FreeRng(&rng); + wc_ed448_free(&key); + return ret; + } + + tmp = wc_Ed448PublicKeyToDer(&key, derBuf, 1024, 1); + if (tmp <= 0) { + ret = SSL_FATAL_ERROR; + } + + wc_FreeRng(&rng); + wc_ed448_free(&key); + } + printf(resultFmt, ret == 0 ? passed : failed); +#endif + return ret; + +} /* END testing wc_Ed448PublicKeyToDer */ + +/* + * Testing wc_curve448_init and wc_curve448_free. + */ +static int test_wc_curve448_init (void) +{ + int ret = 0; + +#if defined(HAVE_CURVE448) + + curve448_key key; + + printf(testingFmt, "wc_curve448_init()"); + ret = wc_curve448_init(&key); + + /* Test bad args for wc_curve448_init */ + if (ret == 0) { + ret = wc_curve448_init(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + /* Test good args for wc_curve_448_free */ + wc_curve448_free(&key); + + wc_curve448_free(NULL); + +#endif + return ret; + +} /* END test_wc_curve448_init and wc_curve_448_free*/ +/* + * Testing test_wc_curve448_size. + */ +static int test_wc_curve448_size (void) +{ + int ret = 0; + +#if defined(HAVE_CURVE448) + + curve448_key key; + + printf(testingFmt, "wc_curve448_size()"); + + ret = wc_curve448_init(&key); + + /* Test good args for wc_curve448_size */ + if (ret == 0) { + ret = wc_curve448_size(&key); + } + + /* Test bad args for wc_curve448_size */ + if (ret != 0) { + ret = wc_curve448_size(NULL); + } + + printf(resultFmt, ret == 0 ? passed : failed); + wc_curve448_free(&key); +#endif + return ret; + +} /* END test_wc_curve448_size*/ + +/* + * Testing wc_ecc_make_key. + */ +static int test_wc_ecc_make_key (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && !defined(WC_NO_RNG) + WC_RNG rng; + ecc_key key; + + printf(testingFmt, "wc_ecc_make_key()"); + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, KEY14, &key); + + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_ecc_make_key(NULL, KEY14, &key); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_make_key(&rng, KEY14, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + wc_ecc_free(&key); + } + + if (wc_FreeRng(&rng) != 0 && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif + + printf(resultFmt, ret == 0 ? passed : failed); +#endif + + return ret; + +} /* END test_wc_ecc_make_key */ + + +/* + * Testing wc_ecc_init() + */ +static int test_wc_ecc_init (void) +{ + int ret = 0; + +#ifdef HAVE_ECC + ecc_key key; + + printf(testingFmt, "wc_ecc_init()"); + + ret = wc_ecc_init(&key); + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_ecc_init(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_ecc_free(&key); + +#endif + return ret; + +} /* END test_wc_ecc_init */ + +/* + * Testing wc_ecc_check_key() + */ +static int test_wc_ecc_check_key (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && !defined(WC_NO_RNG) + WC_RNG rng; + ecc_key key; + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, KEY14, &key); + } + } + + printf(testingFmt, "wc_ecc_check_key()"); + + if (ret == 0) { + ret = wc_ecc_check_key(&key); + } + + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_ecc_check_key(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&key); + +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif + +#endif + return ret; + +} /* END test_wc_ecc_check_key */ + +/* + * Testing wc_ecc_get_generator() + */ +static int test_wc_ecc_get_generator(void) +{ + int ret = 0; +#if defined(HAVE_ECC) && !defined(WC_NO_RNG) && !defined(HAVE_SELFTEST) && \ + !defined(HAVE_FIPS) && defined(OPENSSL_EXTRA) + ecc_point* pt; + + printf(testingFmt, "wc_ecc_new_point()"); + + pt = wc_ecc_new_point(); + if (!pt) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(testingFmt, "wc_ecc_get_generator()"); + + if (ret == 0) { + ret = wc_ecc_get_generator(pt, wc_ecc_get_curve_idx(ECC_SECP256R1)); + } + + /* Test bad args. */ + if (ret == MP_OKAY) { + /* Returns Zero for bad arg. */ + ret = wc_ecc_get_generator(pt, -1); + if (ret != MP_OKAY) + wc_ecc_get_generator(NULL, wc_ecc_get_curve_idx(ECC_SECP256R1)); + if (ret != MP_OKAY) + wc_ecc_get_generator(pt, 1000); /* If we ever get to 1000 curves + * increase this number */ + if (ret != MP_OKAY) + wc_ecc_get_generator(NULL, -1); + ret = ret == MP_OKAY ? WOLFSSL_FATAL_ERROR : 0; + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_ecc_del_point(pt); +#endif + return ret; +} /* END test_wc_ecc_get_generator */ + +/* + * Testing wc_ecc_size() + */ +static int test_wc_ecc_size (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && !defined(WC_NO_RNG) + WC_RNG rng; + ecc_key key; + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, KEY14, &key); + } + } + + printf(testingFmt, "wc_ecc_size()"); + + if (ret == 0) { + ret = wc_ecc_size(&key); + if (ret == KEY14) { + ret = 0; + } else if (ret == 0){ + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Test bad args. */ + if (ret == 0) { + /* Returns Zero for bad arg. */ + ret = wc_ecc_size(NULL); + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&key); + +#endif + return ret; +} /* END test_wc_ecc_size */ + +static void test_wc_ecc_params(void) +{ + /* FIPS/CAVP self-test modules do not have `wc_ecc_get_curve_params`. + It was added after certifications */ +#if defined(HAVE_ECC) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + const ecc_set_type* ecc_set; +#if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + /* Test for SECP256R1 curve */ + int curve_id = ECC_SECP256R1; + int curve_idx = wc_ecc_get_curve_idx(curve_id); + AssertIntNE(curve_idx, ECC_CURVE_INVALID); + ecc_set = wc_ecc_get_curve_params(curve_idx); + AssertNotNull(ecc_set); + AssertIntEQ(ecc_set->id, curve_id); +#endif + /* Test case when SECP256R1 is not enabled */ + /* Test that we get curve params for index 0 */ + ecc_set = wc_ecc_get_curve_params(0); + AssertNotNull(ecc_set); +#endif /* HAVE_ECC && !HAVE_FIPS && !HAVE_SELFTEST */ +} + +/* + * Testing wc_ecc_sign_hash() and wc_ecc_verify_hash() + */ +static int test_wc_ecc_signVerify_hash (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_SIGN) && !defined(NO_ASN) && !defined(WC_NO_RNG) + WC_RNG rng; + ecc_key key; + int signH = WOLFSSL_FATAL_ERROR; + #ifdef HAVE_ECC_VERIFY + int verifyH = WOLFSSL_FATAL_ERROR; + int verify = 0; + #endif + word32 siglen = ECC_BUFSIZE; + byte sig[ECC_BUFSIZE]; + byte digest[] = "Everyone gets Friday off."; + word32 digestlen = (word32)XSTRLEN((char*)digest); + + /* Init stack var */ + XMEMSET(sig, 0, siglen); + + /* Init structs. */ + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, KEY14, &key); + } + } + + printf(testingFmt, "wc_ecc_sign_hash()"); + + if (ret == 0) { + ret = wc_ecc_sign_hash(digest, digestlen, sig, &siglen, &rng, &key); + } + + /* Check bad args. */ + if (ret == 0) { + signH = wc_ecc_sign_hash(NULL, digestlen, sig, &siglen, &rng, &key); + if (signH == ECC_BAD_ARG_E) { + signH = wc_ecc_sign_hash(digest, digestlen, NULL, &siglen, + &rng, &key); + } + if (signH == ECC_BAD_ARG_E) { + signH = wc_ecc_sign_hash(digest, digestlen, sig, NULL, + &rng, &key); + } + if (signH == ECC_BAD_ARG_E) { + signH = wc_ecc_sign_hash(digest, digestlen, sig, &siglen, + NULL, &key); + } + if (signH == ECC_BAD_ARG_E) { + signH = wc_ecc_sign_hash(digest, digestlen, sig, &siglen, + &rng, NULL); + } + if (signH == ECC_BAD_ARG_E) { + signH = 0; + } else if (ret == 0) { + signH = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, signH == 0 ? passed : failed); + + #ifdef HAVE_ECC_VERIFY + printf(testingFmt, "wc_ecc_verify_hash()"); + + ret = wc_ecc_verify_hash(sig, siglen, digest, digestlen, &verify, &key); + if (verify != 1 && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + /* Test bad args. */ + if (ret == 0) { + verifyH = wc_ecc_verify_hash(NULL, siglen, digest, digestlen, + &verify, &key); + if (verifyH == ECC_BAD_ARG_E) { + verifyH = wc_ecc_verify_hash(sig, siglen, NULL, digestlen, + &verify, &key); + } + if (verifyH == ECC_BAD_ARG_E) { + verifyH = wc_ecc_verify_hash(sig, siglen, digest, digestlen, + NULL, &key); + } + if (verifyH == ECC_BAD_ARG_E) { + verifyH = wc_ecc_verify_hash(sig, siglen, digest, digestlen, + &verify, NULL); + } + if (verifyH == ECC_BAD_ARG_E) { + verifyH = 0; + } else if (ret == 0) { + verifyH = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, verifyH == 0 ? passed : failed); + + #endif /* HAVE_ECC_VERIFY */ + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&key); + + #ifdef FP_ECC + wc_ecc_fp_free(); + #endif + +#endif + return ret; + +} /* END test_wc_ecc_sign_hash */ + + +/* + * Testing wc_ecc_shared_secret() + */ +static int test_wc_ecc_shared_secret (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_DHE) && !defined(WC_NO_RNG) + ecc_key key, pubKey; + WC_RNG rng; + int keySz = KEY16; + byte out[KEY16]; + word32 outlen = (word32)sizeof(out); + + /* Initialize variables. */ + XMEMSET(out, 0, keySz); + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_init(&pubKey); + } + } + if (ret == 0) { + ret = wc_ecc_make_key(&rng, keySz, &key); + } + if (ret == 0) { + ret = wc_ecc_make_key(&rng, keySz, &pubKey); + } + + printf(testingFmt, "wc_ecc_shared_secret()"); + if (ret == 0) { + ret = wc_ecc_shared_secret(&key, &pubKey, out, &outlen); + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_shared_secret(NULL, &pubKey, out, &outlen); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_shared_secret(&key, NULL, out, &outlen); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_shared_secret(&key, &pubKey, NULL, &outlen); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_shared_secret(&key, &pubKey, out, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&key); + wc_ecc_free(&pubKey); + +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif + +#endif + return ret; + +} /* END tests_wc_ecc_shared_secret */ + +/* + * testint wc_ecc_export_x963() + */ +static int test_wc_ecc_export_x963 (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) + ecc_key key; + WC_RNG rng; + byte out[ECC_ASN963_MAX_BUF_SZ]; + word32 outlen = sizeof(out); + + /* Initialize variables. */ + XMEMSET(out, 0, outlen); + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, KEY20, &key); + } + } + printf(testingFmt, "wc_ecc_export_x963()"); + + if (ret == 0) { + ret = wc_ecc_export_x963(&key, out, &outlen); + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_export_x963(NULL, out, &outlen); + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_export_x963(&key, NULL, &outlen); + } + if (ret == LENGTH_ONLY_E) { + ret = wc_ecc_export_x963(&key, out, NULL); + } + if (ret == ECC_BAD_ARG_E) { + key.idx = -4; + ret = wc_ecc_export_x963(&key, out, &outlen); + } + if (ret == ECC_BAD_ARG_E) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&key); + +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif + +#endif + return ret; + +} /* END test_wc_ecc_export_x963 */ + +/* + * Testing wc_ecc_export_x963_ex() + * compile with --enable-compkey will use compression. + */ +static int test_wc_ecc_export_x963_ex (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) + ecc_key key; + WC_RNG rng; + byte out[ECC_ASN963_MAX_BUF_SZ]; + word32 outlen = sizeof(out); + #ifdef HAVE_COMP_KEY + word32 badOutLen = 5; + #endif + + /* Init stack variables. */ + XMEMSET(out, 0, outlen); + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, KEY64, &key); + } + } + + printf(testingFmt, "wc_ecc_export_x963_ex()"); + + #ifdef HAVE_COMP_KEY + if (ret == 0) { + ret = wc_ecc_export_x963_ex(&key, out, &outlen, COMP); + } + #else + if (ret == 0) { + ret = wc_ecc_export_x963_ex(&key, out, &outlen, NOCOMP); + } + #endif + + /* Test bad args. */ + #ifdef HAVE_COMP_KEY + if (ret == 0) { + ret = wc_ecc_export_x963_ex(NULL, out, &outlen, COMP); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_export_x963_ex(&key, NULL, &outlen, COMP); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_export_x963_ex(&key, out, NULL, COMP); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_export_x963_ex(&key, out, &badOutLen, COMP); + } + if (ret == BUFFER_E) { + key.idx = -4; + ret = wc_ecc_export_x963_ex(&key, out, &outlen, COMP); + } + if (ret == ECC_BAD_ARG_E) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + #else + if (ret == 0) { + ret = wc_ecc_export_x963_ex(NULL, out, &outlen, NOCOMP); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_export_x963_ex(&key, NULL, &outlen, NOCOMP); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_export_x963_ex(&key, out, &outlen, 1); + } + if (ret == NOT_COMPILED_IN) { + ret = wc_ecc_export_x963_ex(&key, out, NULL, NOCOMP); + } + if (ret == BAD_FUNC_ARG) { + key.idx = -4; + ret = wc_ecc_export_x963_ex(&key, out, &outlen, NOCOMP); + } + if (ret == ECC_BAD_ARG_E) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + #endif + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&key); + +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif + +#endif + return ret; + +} /* END test_wc_ecc_export_x963_ex */ + +/* + * testing wc_ecc_import_x963() + */ +static int test_wc_ecc_import_x963 (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_IMPORT) && \ + defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) + ecc_key pubKey, key; + WC_RNG rng; + byte x963[ECC_ASN963_MAX_BUF_SZ]; + word32 x963Len = (word32)sizeof(x963); + + /* Init stack variables. */ + XMEMSET(x963, 0, x963Len); + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&pubKey); + if (ret == 0) { + ret = wc_ecc_init(&key); + } + if (ret == 0) { + ret = wc_ecc_make_key(&rng, KEY24, &key); + } + if (ret == 0) { + ret = wc_ecc_export_x963(&key, x963, &x963Len); + } + } + + printf(testingFmt, "wc_ecc_import_x963()"); + if (ret == 0) { + ret = wc_ecc_import_x963(x963, x963Len, &pubKey); + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_import_x963(NULL, x963Len, &pubKey); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_import_x963(x963, x963Len, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_import_x963(x963, x963Len + 1, &pubKey); + } + if (ret == ECC_BAD_ARG_E) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&key); + wc_ecc_free(&pubKey); + +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif + +#endif + return ret; + +} /* END wc_ecc_import_x963 */ + +/* + * testing wc_ecc_import_private_key() + */ +static int ecc_import_private_key (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_IMPORT) && \ + defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) + ecc_key key, keyImp; + WC_RNG rng; + byte privKey[ECC_PRIV_KEY_BUF]; /* Raw private key.*/ + byte x963Key[ECC_ASN963_MAX_BUF_SZ]; + word32 privKeySz = (word32)sizeof(privKey); + word32 x963KeySz = (word32)sizeof(x963Key); + + /* Init stack variables. */ + XMEMSET(privKey, 0, privKeySz); + XMEMSET(x963Key, 0, x963KeySz); + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_init(&keyImp); + } + if (ret == 0) { + ret = wc_ecc_make_key(&rng, KEY48, &key); + } + if (ret == 0) { + ret = wc_ecc_export_x963(&key, x963Key, &x963KeySz); + } + if (ret == 0) { + ret = wc_ecc_export_private_only(&key, privKey, &privKeySz); + } + } + + printf(testingFmt, "wc_ecc_import_private_key()"); + + if (ret == 0) { + ret = wc_ecc_import_private_key(privKey, privKeySz, x963Key, + x963KeySz, &keyImp); + } + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_ecc_import_private_key(privKey, privKeySz, x963Key, + x963KeySz, NULL); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_import_private_key(NULL, privKeySz, x963Key, + x963KeySz, &keyImp); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&key); + wc_ecc_free(&keyImp); + +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif + +#endif + return ret; + +} /* END wc_ecc_import_private_key */ + + +/* + * Testing wc_ecc_export_private_only() + */ +static int test_wc_ecc_export_private_only (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) + ecc_key key; + WC_RNG rng; + byte out[ECC_PRIV_KEY_BUF]; + word32 outlen = sizeof(out); + + /* Init stack variables. */ + XMEMSET(out, 0, outlen); + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, KEY32, &key); + } + } + printf(testingFmt, "wc_ecc_export_private_only()"); + + if (ret == 0) { + ret = wc_ecc_export_private_only(&key, out, &outlen); + } + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_ecc_export_private_only(NULL, out, &outlen); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_export_private_only(&key, NULL, &outlen); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_export_private_only(&key, out, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&key); + +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif + +#endif + return ret; + +} /* END test_wc_ecc_export_private_only */ + + +/* + * Testing wc_ecc_rs_to_sig() + */ +static int test_wc_ecc_rs_to_sig (void) +{ + + int ret = 0; + +#if defined(HAVE_ECC) && !defined(NO_ASN) + /* first [P-192,SHA-1] vector from FIPS 186-3 NIST vectors */ + const char* R = "6994d962bdd0d793ffddf855ec5bf2f91a9698b46258a63e"; + const char* S = "02ba6465a234903744ab02bc8521405b73cf5fc00e1a9f41"; + byte sig[ECC_MAX_SIG_SIZE]; + word32 siglen = (word32)sizeof(sig); + /*R and S max size is the order of curve. 2^192.*/ + int keySz = KEY24; + byte r[KEY24]; + byte s[KEY24]; + word32 rlen = (word32)sizeof(r); + word32 slen = (word32)sizeof(s); + + /* Init stack variables. */ + XMEMSET(sig, 0, ECC_MAX_SIG_SIZE); + XMEMSET(r, 0, keySz); + XMEMSET(s, 0, keySz); + + printf(testingFmt, "wc_ecc_rs_to_sig()"); + + ret = wc_ecc_rs_to_sig(R, S, sig, &siglen); + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_rs_to_sig(NULL, S, sig, &siglen); + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_rs_to_sig(R, NULL, sig, &siglen); + } + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_rs_to_sig(R, S, sig, NULL); + } + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_rs_to_sig(R, S, NULL, &siglen); + } + if (ret == ECC_BAD_ARG_E) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + printf(testingFmt, "wc_ecc_sig_to_rs()"); + if (ret == 0) { + ret = wc_ecc_sig_to_rs(sig, siglen, r, &rlen, s, &slen); + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_sig_to_rs(NULL, siglen, r, &rlen, s, &slen); + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_sig_to_rs(sig, siglen, NULL, &rlen, s, &slen); + } + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_sig_to_rs(sig, siglen, r, NULL, s, &slen); + } + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_sig_to_rs(sig, siglen, r, &rlen, NULL, &slen); + } + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_sig_to_rs(sig, siglen, r, &rlen, s, NULL); + } + if (ret == ECC_BAD_ARG_E) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return ret; + +} /* END test_wc_ecc_rs_to_sig */ + +static int test_wc_ecc_import_raw (void) +{ + int ret = 0; + +#ifdef HAVE_ECC + ecc_key key; +#ifdef HAVE_ALL_CURVES + const char* qx = "07008ea40b08dbe76432096e80a2494c94982d2d5bcf98e6"; + const char* qy = "76fab681d00b414ea636ba215de26d98c41bd7f2e4d65477"; + const char* d = "e14f37b3d1374ff8b03f41b9b3fdd2f0ebccf275d660d7f3"; + const char* curveName = "SECP192R1"; +#else + const char* qx = + "6c450448386596485678dcf46ccf75e80ff292443cddab1ff216d0c72cd9341"; + const char* qy = + "9cac72ff8a90e4939e37714bfa07ae4612588535c3fdeab63ceb29b1d80f0d1"; + const char* d = + "1e1dd938e15bdd036b0b0e2a6dc62fe7b46dbe042ac42310c6d5db0cda63e807"; + const char* curveName = "SECP256R1"; +#endif + + ret = wc_ecc_init(&key); + + printf(testingFmt, "wc_ecc_import_raw()"); + + if (ret == 0) { + ret = wc_ecc_import_raw(&key, qx, qy, d, curveName); + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_import_raw(NULL, qx, qy, d, curveName); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_import_raw(&key, NULL, qy, d, curveName); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_import_raw(&key, qx, NULL, d, curveName); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_import_raw(&key, qx, qy, d, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_ecc_free(&key); + +#endif + + return ret; + +} /* END test_wc_ecc_import_raw */ + + +/* + * Testing wc_ecc_sig_size() + */ +static int test_wc_ecc_sig_size (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && !defined(WC_NO_RNG) + ecc_key key; + WC_RNG rng; + int keySz = KEY16; + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, keySz, &key); + } + } + + printf(testingFmt, "wc_ecc_sig_size()"); + + if (ret == 0) { + ret = wc_ecc_sig_size(&key); + if (ret <= (2 * keySz + SIG_HEADER_SZ + ECC_MAX_PAD_SZ)) { + ret = 0; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&key); + +#endif + return ret; + +} /* END test_wc_ecc_sig_size */ + +/* + * Testing wc_ecc_ctx_new() + */ +static int test_wc_ecc_ctx_new (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_ENCRYPT) && !defined(WC_NO_RNG) + WC_RNG rng; + ecEncCtx* cli = NULL; + ecEncCtx* srv = NULL; + + ret = wc_InitRng(&rng); + + printf(testingFmt, "wc_ecc_ctx_new()"); + if (ret == 0) { + cli = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng); + srv = wc_ecc_ctx_new(REQ_RESP_SERVER, &rng); + } + if (ret == 0 && (cli == NULL || srv == NULL)) { + ret = WOLFSSL_FATAL_ERROR; + } + + wc_ecc_ctx_free(cli); + wc_ecc_ctx_free(srv); + + /* Test bad args. */ + if (ret == 0) { + /* wc_ecc_ctx_new_ex() will free if returned NULL. */ + cli = wc_ecc_ctx_new(0, &rng); + if (cli != NULL) { + ret = WOLFSSL_FATAL_ERROR; + } + cli = wc_ecc_ctx_new(REQ_RESP_CLIENT, NULL); + if (cli != NULL) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_ctx_free(cli); + +#endif + return ret; + +} /* END test_wc_ecc_ctx_new */ + +/* + * Tesing wc_ecc_reset() + */ +static int test_wc_ecc_ctx_reset (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_ENCRYPT) && !defined(WC_NO_RNG) + ecEncCtx* ctx = NULL; + WC_RNG rng; + + ret = wc_InitRng(&rng); + if (ret == 0) { + if ( (ctx = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng)) == NULL ) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(testingFmt, "wc_ecc_ctx_reset()"); + + if (ret == 0) { + ret = wc_ecc_ctx_reset(ctx, &rng); + } + + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_ecc_ctx_reset(NULL, &rng); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_ctx_reset(ctx, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_ctx_free(ctx); + +#endif + return ret; + +} /* END test_wc_ecc_ctx_reset */ + +/* + * Testing wc_ecc_ctx_set_peer_salt() and wc_ecc_ctx_get_own_salt() + */ +static int test_wc_ecc_ctx_set_peer_salt (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_ENCRYPT) && !defined(WC_NO_RNG) + WC_RNG rng; + ecEncCtx* cliCtx = NULL; + ecEncCtx* servCtx = NULL; + const byte* cliSalt = NULL; + const byte* servSalt = NULL; + + ret = wc_InitRng(&rng); + if (ret == 0) { + if ( ( (cliCtx = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng)) == NULL ) || + ( (servCtx = wc_ecc_ctx_new(REQ_RESP_SERVER, &rng)) == NULL) ) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(testingFmt, "wc_ecc_ctx_get_own_salt()"); + + /* Test bad args. */ + if (ret == 0) { + cliSalt = wc_ecc_ctx_get_own_salt(NULL); + if (cliSalt != NULL) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + if (ret == 0) { + cliSalt = wc_ecc_ctx_get_own_salt(cliCtx); + servSalt = wc_ecc_ctx_get_own_salt(servCtx); + if (cliSalt == NULL || servSalt == NULL) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + printf(testingFmt, "wc_ecc_ctx_set_peer_salt()"); + + if (ret == 0) { + ret = wc_ecc_ctx_set_peer_salt(cliCtx, servSalt); + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_ctx_set_peer_salt(NULL, servSalt); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_ctx_set_peer_salt(cliCtx, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_ctx_free(cliCtx); + wc_ecc_ctx_free(servCtx); + +#endif + return ret; + +} /* END test_wc_ecc_ctx_set_peer_salt */ + +/* + * Testing wc_ecc_ctx_set_info() + */ +static int test_wc_ecc_ctx_set_info (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_ENCRYPT) && !defined(WC_NO_RNG) + ecEncCtx* ctx = NULL; + WC_RNG rng; + const char* optInfo = "Optional Test Info."; + int optInfoSz = (int)XSTRLEN(optInfo); + const char* badOptInfo = NULL; + + ret = wc_InitRng(&rng); + if ( (ctx = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng)) == NULL || ret != 0 ) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(testingFmt, "wc_ecc_ctx_set_info()"); + + if (ret == 0) { + ret = wc_ecc_ctx_set_info(ctx, (byte*)optInfo, optInfoSz); + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_ctx_set_info(NULL, (byte*)optInfo, optInfoSz); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_ctx_set_info(ctx, (byte*)badOptInfo, optInfoSz); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_ctx_set_info(ctx, (byte*)optInfo, -1); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_ctx_free(ctx); + +#endif + return ret; + +} /* END test_wc_ecc_ctx_set_info */ + +/* + * Testing wc_ecc_encrypt() and wc_ecc_decrypt() + */ +static int test_wc_ecc_encryptDecrypt (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_ENCRYPT) && defined(WOLFSSL_AES_128) \ + && !defined(WC_NO_RNG) + ecc_key srvKey, cliKey; + WC_RNG rng; + const char* msg = "EccBlock Size 16"; + word32 msgSz = (word32)XSTRLEN(msg); + byte out[XSTRLEN(msg) + WC_SHA256_DIGEST_SIZE]; + word32 outSz = (word32)sizeof(out); + byte plain[XSTRLEN(msg) + 1]; + word32 plainSz = (word32)sizeof(plain); + int keySz = KEY20; + + /* Init stack variables. */ + XMEMSET(out, 0, outSz); + XMEMSET(plain, 0, plainSz); + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&cliKey); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, keySz, &cliKey); + } + if (ret == 0) { + ret = wc_ecc_init(&srvKey); + } + if (ret == 0) { + ret = wc_ecc_make_key(&rng, keySz, &srvKey); + } + } + + printf(testingFmt, "wc_ecc_encrypt()"); + + if (ret == 0) { + ret = wc_ecc_encrypt(&cliKey, &srvKey, (byte*)msg, msgSz, out, + &outSz, NULL); + } + if (ret == 0) { + ret = wc_ecc_encrypt(NULL, &srvKey, (byte*)msg, msgSz, out, + &outSz, NULL); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_encrypt(&cliKey, NULL, (byte*)msg, msgSz, out, + &outSz, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_encrypt(&cliKey, &srvKey, NULL, msgSz, out, + &outSz, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_encrypt(&cliKey, &srvKey, (byte*)msg, msgSz, NULL, + &outSz, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_encrypt(&cliKey, &srvKey, (byte*)msg, msgSz, out, + NULL, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + printf(testingFmt, "wc_ecc_decrypt()"); + + if (ret == 0) { + ret = wc_ecc_decrypt(&srvKey, &cliKey, out, outSz, plain, + &plainSz, NULL); + } + if (ret == 0) { + ret = wc_ecc_decrypt(NULL, &cliKey, out, outSz, plain, + &plainSz, NULL); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_decrypt(&srvKey, NULL, out, outSz, plain, + &plainSz, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_decrypt(&srvKey, &cliKey, NULL, outSz, plain, + &plainSz, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_decrypt(&srvKey, &cliKey, out, outSz, NULL, + &plainSz, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_decrypt(&srvKey, &cliKey, out, outSz, + plain, NULL, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + if (XMEMCMP(msg, plain, msgSz) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&cliKey); + wc_ecc_free(&srvKey); + +#endif + return ret; + +} /* END test_wc_ecc_encryptDecrypt */ + +/* + * Testing wc_ecc_del_point() and wc_ecc_new_point() + */ +static int test_wc_ecc_del_point (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) + ecc_point* pt; + + printf(testingFmt, "wc_ecc_new_point()"); + + pt = wc_ecc_new_point(); + if (!pt) { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_ecc_del_point(pt); + +#endif + return ret; + +} /* END test_wc_ecc_del_point */ + +/* + * Testing wc_ecc_point_is_at_infinity(), wc_ecc_export_point_der(), + * wc_ecc_import_point_der(), wc_ecc_copy_point(), and wc_ecc_cmp_point() + */ +static int test_wc_ecc_pointFns (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && \ + !defined(WC_NO_RNG) && !defined(WOLFSSL_ATECC508A) + ecc_key key; + WC_RNG rng; + ecc_point* point = NULL; + ecc_point* cpypt = NULL; + int idx = 0; + int keySz = KEY32; + byte der[DER_SZ]; + word32 derlenChk = 0; + word32 derSz = (int)sizeof(der); + + /* Init stack variables. */ + XMEMSET(der, 0, derSz); + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, keySz, &key); + } + } + + if (ret == 0) { + point = wc_ecc_new_point(); + if (!point) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + if (ret == 0) { + cpypt = wc_ecc_new_point(); + if (!cpypt) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + /* Export */ + printf(testingFmt, "wc_ecc_export_point_der()"); + if (ret == 0) { + ret = wc_ecc_export_point_der((idx = key.idx), &key.pubkey, + NULL, &derlenChk); + /* Check length value. */ + if (derSz == derlenChk && ret == LENGTH_ONLY_E) { + ret = wc_ecc_export_point_der((idx = key.idx), &key.pubkey, + der, &derSz); + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_export_point_der(-2, &key.pubkey, der, &derSz); + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_export_point_der((idx = key.idx), NULL, der, &derSz); + } + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_export_point_der((idx = key.idx), &key.pubkey, + der, NULL); + } + if (ret == ECC_BAD_ARG_E) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + /* Import */ + printf(testingFmt, "wc_ecc_import_point_der()"); + + if (ret == 0) { + ret = wc_ecc_import_point_der(der, derSz, idx, point); + /* Condition double checks wc_ecc_cmp_point(). */ + if (ret == 0 && XMEMCMP(&key.pubkey, point, sizeof(key.pubkey))) { + ret = wc_ecc_cmp_point(&key.pubkey, point); + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_import_point_der(NULL, derSz, idx, point); + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_import_point_der(der, derSz, idx, NULL); + } + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_import_point_der(der, derSz, -1, point); + } + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_import_point_der(der, derSz + 1, idx, point); + } + if (ret == ECC_BAD_ARG_E) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + + /* Copy */ + printf(testingFmt, "wc_ecc_copy_point()"); + + if (ret == 0) { + ret = wc_ecc_copy_point(point, cpypt); + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_copy_point(NULL, cpypt); + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_copy_point(point, NULL); + } + if (ret == ECC_BAD_ARG_E) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + printf(testingFmt, "wc_ecc_cmp_point()"); + /* Compare point */ + if (ret == 0) { + ret = wc_ecc_cmp_point(point, cpypt); + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_cmp_point(NULL, cpypt); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_cmp_point(point, NULL); + } + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + printf(resultFmt, ret == 0 ? passed : failed); + + printf(testingFmt, "wc_ecc_point_is_at_infinity()"); + /* At infinity if return == 1, otherwise return == 0. */ + if (ret == 0) { + ret = wc_ecc_point_is_at_infinity(point); + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_point_is_at_infinity(NULL); + if (ret == BAD_FUNC_ARG) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + /* Free */ + wc_ecc_del_point(point); + wc_ecc_del_point(cpypt); + wc_ecc_free(&key); + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + +#endif + return ret; + +} /* END test_wc_ecc_pointFns */ + + +/* + * Testing wc_ecc_sahred_secret_ssh() + */ +static int test_wc_ecc_shared_secret_ssh (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_DHE) && \ + !defined(WC_NO_RNG) && !defined(WOLFSSL_ATECC508A) + ecc_key key, key2; + WC_RNG rng; + int keySz = KEY32; + int key2Sz = KEY24; + byte secret[KEY32]; + word32 secretLen = keySz; + + /* Init stack variables. */ + XMEMSET(secret, 0, secretLen); + + /* Make keys */ + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, keySz, &key); + } + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key2); + } + if (ret == 0) { + ret = wc_ecc_make_key(&rng, key2Sz, &key2); + } + } + + printf(testingFmt, "ecc_shared_secret_ssh()"); + + if (ret == 0) { + ret = wc_ecc_shared_secret_ssh(&key, &key2.pubkey, secret, &secretLen); + } + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_ecc_shared_secret_ssh(NULL, &key2.pubkey, secret, &secretLen); + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_shared_secret_ssh(&key, NULL, secret, &secretLen); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_shared_secret_ssh(&key, &key2.pubkey, NULL, &secretLen); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_ecc_shared_secret_ssh(&key, &key2.pubkey, secret, NULL); + } + if (ret == BAD_FUNC_ARG) { + key.type = ECC_PUBLICKEY; + ret = wc_ecc_shared_secret_ssh(&key, &key2.pubkey, secret, &secretLen); + if (ret == ECC_BAD_ARG_E) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&key); + wc_ecc_free(&key2); + +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif + +#endif + return ret; + +} /* END test_wc_ecc_shared_secret_ssh */ + +/* + * Testing wc_ecc_verify_hash_ex() and wc_ecc_verify_hash_ex() + */ +static int test_wc_ecc_verify_hash_ex (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && defined(HAVE_ECC_SIGN) && defined(WOLFSSL_PUBLIC_MP) \ + && !defined(WC_NO_RNG) && !defined(WOLFSSL_ATECC508A) + ecc_key key; + WC_RNG rng; + mp_int r; + mp_int s; + unsigned char hash[] = "Everyone gets Friday off.EccSig"; + unsigned char iHash[] = "Everyone gets Friday off......."; + unsigned char shortHash[] = "Everyone gets Friday off."; + word32 hashlen = sizeof(hash); + word32 iHashLen = sizeof(iHash); + word32 shortHashLen = sizeof(shortHash); + int keySz = KEY32; + int sig = WOLFSSL_FATAL_ERROR; + int ver = WOLFSSL_FATAL_ERROR; + int verify_ok = 0; + + /* Initialize r and s. */ + ret = mp_init_multi(&r, &s, NULL, NULL, NULL, NULL); + if (ret != MP_OKAY) { + return MP_INIT_E; + } + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, keySz, &key); + } + } + if (ret == 0) { + ret = wc_ecc_sign_hash_ex(hash, hashlen, &rng, &key, &r, &s); + if (ret == 0) { + /* verify_ok should be 1. */ + ret = wc_ecc_verify_hash_ex(&r, &s, hash, hashlen, &verify_ok, &key); + if (verify_ok != 1 && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (ret == 0) { + /* verify_ok should be 0 */ + ret = wc_ecc_verify_hash_ex(&r, &s, iHash, iHashLen, + &verify_ok, &key); + if (verify_ok != 0 && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (ret == 0) { + /* verify_ok should be 0. */ + ret = wc_ecc_verify_hash_ex(&r, &s, shortHash, shortHashLen, + &verify_ok, &key); + if (verify_ok != 0 && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + } + + printf(testingFmt, "wc_ecc_sign_hash_ex()"); + /* Test bad args. */ + if (ret == 0) { + if (wc_ecc_sign_hash_ex(NULL, hashlen, &rng, &key, &r, &s) + == ECC_BAD_ARG_E) { + sig = 0; + } + if (sig == 0 && wc_ecc_sign_hash_ex(hash, hashlen, NULL, &key, &r, &s) + != ECC_BAD_ARG_E) { + sig = WOLFSSL_FATAL_ERROR; + } + if (sig == 0 && wc_ecc_sign_hash_ex(hash, hashlen, &rng, NULL, &r, &s) + != ECC_BAD_ARG_E) { + sig = WOLFSSL_FATAL_ERROR; + } + if (sig == 0 && wc_ecc_sign_hash_ex(hash, hashlen, &rng, &key, NULL, &s) + != ECC_BAD_ARG_E) { + sig = WOLFSSL_FATAL_ERROR; + } + if (sig == 0 && wc_ecc_sign_hash_ex(hash, hashlen, &rng, &key, &r, NULL) + != ECC_BAD_ARG_E) { + sig = WOLFSSL_FATAL_ERROR; + } + } + printf(resultFmt, sig == 0 ? passed : failed); + printf(testingFmt, "wc_ecc_verify_hash_ex()"); + /* Test bad args. */ + if (ret == 0) { + if (wc_ecc_verify_hash_ex(NULL, &s, shortHash, shortHashLen, &verify_ok, &key) + == ECC_BAD_ARG_E) { + ver = 0; + } + if (ver == 0 && wc_ecc_verify_hash_ex(&r, NULL, shortHash, shortHashLen, + &verify_ok, &key) != ECC_BAD_ARG_E) { + ver = WOLFSSL_FATAL_ERROR; + } + if (ver == 0 && wc_ecc_verify_hash_ex(&r, &s, NULL, shortHashLen, &verify_ok, + &key) != ECC_BAD_ARG_E) { + ver = WOLFSSL_FATAL_ERROR; + } + if (ver == 0 && wc_ecc_verify_hash_ex(&r, &s, shortHash, shortHashLen, + NULL, &key) != ECC_BAD_ARG_E) { + ver = WOLFSSL_FATAL_ERROR; + } + if (ver == 0 && wc_ecc_verify_hash_ex(&r, &s, shortHash, shortHashLen, + &verify_ok, NULL) != ECC_BAD_ARG_E) { + ver = WOLFSSL_FATAL_ERROR; + } + } + printf(resultFmt, ver == 0 ? passed : failed); + + wc_ecc_free(&key); + mp_free(&r); + mp_free(&s); + if (wc_FreeRng(&rng)) { + return WOLFSSL_FATAL_ERROR; + } + if (ret == 0 && (sig != 0 || ver != 0)) { + ret = WOLFSSL_FATAL_ERROR; + } +#endif + return ret; + +} /* END test_wc_ecc_verify_hash_ex */ + +/* + * Testing wc_ecc_mulmod() + */ + +static int test_wc_ecc_mulmod (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && !defined(WC_NO_RNG) && \ + !(defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_VALIDATE_ECC_IMPORT)) + ecc_key key1, key2, key3; + WC_RNG rng; + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key1); + if (ret == 0) { + ret = wc_ecc_init(&key2); + } + if (ret == 0) { + ret = wc_ecc_init(&key3); + } + if (ret == 0) { + ret = wc_ecc_make_key(&rng, KEY32, &key1); + } + wc_FreeRng(&rng); + } + if (ret == 0) { + ret = wc_ecc_import_raw_ex(&key2, key1.dp->Gx, key1.dp->Gy, key1.dp->Af, + ECC_SECP256R1); + if (ret == 0) { + ret = wc_ecc_import_raw_ex(&key3, key1.dp->Gx, key1.dp->Gy, + key1.dp->prime, ECC_SECP256R1); + } + } + + printf(testingFmt, "wc_ecc_mulmod()"); + if (ret == 0) { + ret = wc_ecc_mulmod(&key1.k, &key2.pubkey, &key3.pubkey, &key2.k, + &key3.k, 1); + } + + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_mulmod(NULL, &key2.pubkey, &key3.pubkey, &key2.k, + &key3.k, 1); + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_mulmod(&key1.k, NULL, &key3.pubkey, &key2.k, + &key3.k, 1); + } + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_mulmod(&key1.k, &key2.pubkey, NULL, &key2.k, + &key3.k, 1); + } + if (ret == ECC_BAD_ARG_E) { + ret = wc_ecc_mulmod(&key1.k, &key2.pubkey, &key3.pubkey, + &key2.k, NULL, 1); + } + if (ret == ECC_BAD_ARG_E) { + ret = 0; + } else if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + wc_ecc_free(&key1); + wc_ecc_free(&key2); + wc_ecc_free(&key3); + +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif + +#endif /* HAVE_ECC && !WOLFSSL_ATECC508A */ + return ret; + + +} /* END test_wc_ecc_mulmod */ + +/* + * Testing wc_ecc_is_valid_idx() + */ +static int test_wc_ecc_is_valid_idx (void) +{ + int ret = 0; + +#if defined(HAVE_ECC) && !defined(WC_NO_RNG) + ecc_key key; + WC_RNG rng; + int iVal = -2; + int iVal2 = 3000; + + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_init(&key); + if (ret == 0) { + ret = wc_ecc_make_key(&rng, 32, &key); + } + } + + printf(testingFmt, "wc_ecc_is_valid_idx()"); + if (ret == 0) { + ret = wc_ecc_is_valid_idx(key.idx); + if (ret == 1) { + ret = 0; + } else { + ret = WOLFSSL_FATAL_ERROR; + } + } + /* Test bad args. */ + if (ret == 0) { + ret = wc_ecc_is_valid_idx(iVal); /* should return 0 */ + if (ret == 0) { + ret = wc_ecc_is_valid_idx(iVal2); + } + if (ret != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + if (wc_FreeRng(&rng) && ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&key); +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif + +#endif + return ret; + + +} /* END test_wc_ecc_is_valid_idx */ + + +/* + * Testing wc_PKCS7_New() + */ +static void test_wc_PKCS7_New (void) +{ +#if defined(HAVE_PKCS7) + PKCS7* pkcs7; + void* heap = NULL; + + printf(testingFmt, "wc_PKCS7_New()"); + + pkcs7 = wc_PKCS7_New(heap, devId); + AssertNotNull(pkcs7); + + printf(resultFmt, passed); + wc_PKCS7_Free(pkcs7); +#endif +} /* END test-wc_PKCS7_New */ + +/* + * Testing wc_PKCS7_Init() + */ +static void test_wc_PKCS7_Init (void) +{ +#if defined(HAVE_PKCS7) + PKCS7* pkcs7; + void* heap = NULL; + + printf(testingFmt, "wc_PKCS7_Init()"); + + pkcs7 = wc_PKCS7_New(heap, devId); + AssertNotNull(pkcs7); + + AssertIntEQ(wc_PKCS7_Init(pkcs7, heap, devId), 0); + + /* Pass in bad args. */ + AssertIntEQ(wc_PKCS7_Init(NULL, heap, devId), BAD_FUNC_ARG); + + printf(resultFmt, passed); + wc_PKCS7_Free(pkcs7); +#endif +} /* END test-wc_PKCS7_Init */ + + +/* + * Testing wc_PKCS7_InitWithCert() + */ +static void test_wc_PKCS7_InitWithCert (void) +{ +#if defined(HAVE_PKCS7) + PKCS7* pkcs7; + +#ifndef NO_RSA + #if defined(USE_CERT_BUFFERS_2048) + unsigned char cert[sizeof_client_cert_der_2048]; + int certSz = (int)sizeof(cert); + XMEMSET(cert, 0, certSz); + XMEMCPY(cert, client_cert_der_2048, sizeof_client_cert_der_2048); + #elif defined(USE_CERT_BUFFERS_1024) + unsigned char cert[sizeof_client_cert_der_1024]; + int certSz = (int)sizeof(cert); + XMEMSET(cert, 0, certSz); + XMEMCPY(cert, client_cert_der_1024, sizeof_client_cert_der_1024); + #else + unsigned char cert[ONEK_BUF]; + XFILE fp; + int certSz; + fp = XFOPEN("./certs/1024/client-cert.der", "rb"); + AssertTrue(fp != XBADFILE); + + certSz = (int)XFREAD(cert, 1, sizeof_client_cert_der_1024, fp); + XFCLOSE(fp); + #endif +#elif defined(HAVE_ECC) + #if defined(USE_CERT_BUFFERS_256) + unsigned char cert[sizeof_cliecc_cert_der_256]; + int certSz = (int)sizeof(cert); + XMEMSET(cert, 0, certSz); + XMEMCPY(cert, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); + #else + unsigned char cert[ONEK_BUF]; + XFILE fp; + int certSz; + fp = XFOPEN("./certs/client-ecc-cert.der", "rb"); + + AssertTrue(fp != XBADFILE); + + certSz = (int)XFREAD(cert, 1, sizeof_cliecc_cert_der_256, fp); + XFCLOSE(fp); + #endif +#else + #error PKCS7 requires ECC or RSA +#endif + printf(testingFmt, "wc_PKCS7_InitWithCert()"); + + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + /* If initialization is not successful, it's free'd in init func. */ + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)cert, (word32)certSz), 0); + + wc_PKCS7_Free(pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + + /* Valid initialization usage. */ + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + + /* Pass in bad args. No need free for null checks, free at end.*/ + AssertIntEQ(wc_PKCS7_InitWithCert(NULL, (byte*)cert, (word32)certSz), + BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, (word32)certSz), + BAD_FUNC_ARG); + + printf(resultFmt, passed); + + wc_PKCS7_Free(pkcs7); +#endif +} /* END test_wc_PKCS7_InitWithCert */ + + +/* + * Testing wc_PKCS7_EncodeData() + */ +static void test_wc_PKCS7_EncodeData (void) +{ +#if defined(HAVE_PKCS7) + PKCS7* pkcs7; + byte output[FOURK_BUF]; + byte data[] = "My encoded DER cert."; + +#ifndef NO_RSA + #if defined(USE_CERT_BUFFERS_2048) + unsigned char cert[sizeof_client_cert_der_2048]; + unsigned char key[sizeof_client_key_der_2048]; + int certSz = (int)sizeof(cert); + int keySz = (int)sizeof(key); + XMEMSET(cert, 0, certSz); + XMEMSET(key, 0, keySz); + XMEMCPY(cert, client_cert_der_2048, certSz); + XMEMCPY(key, client_key_der_2048, keySz); + + #elif defined(USE_CERT_BUFFERS_1024) + unsigned char cert[sizeof_client_cert_der_1024]; + unsigned char key[sizeof_client_key_der_1024]; + int certSz = (int)sizeof(cert); + int keySz = (int)sizeof(key); + XMEMSET(cert, 0, certSz); + XMEMSET(key, 0, keySz); + XMEMCPY(cert, client_cert_der_1024, certSz); + XMEMCPY(key, client_key_der_1024, keySz); + #else + unsigned char cert[ONEK_BUF]; + unsigned char key[ONEK_BUF]; + XFILE fp; + int certSz; + int keySz; + + fp = XFOPEN("./certs/1024/client-cert.der", "rb"); + AssertTrue(fp != XBADFILE); + certSz = (int)XFREAD(cert, 1, sizeof_client_cert_der_1024, fp); + XFCLOSE(fp); + + fp = XFOPEN("./certs/1024/client-key.der", "rb"); + AssertTrue(fp != XBADFILE); + keySz = (int)XFREAD(key, 1, sizeof_client_key_der_1024, fp); + XFCLOSE(fp); + #endif +#elif defined(HAVE_ECC) + #if defined(USE_CERT_BUFFERS_256) + unsigned char cert[sizeof_cliecc_cert_der_256]; + unsigned char key[sizeof_ecc_clikey_der_256]; + int certSz = (int)sizeof(cert); + int keySz = (int)sizeof(key); + XMEMSET(cert, 0, certSz); + XMEMSET(key, 0, keySz); + XMEMCPY(cert, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); + XMEMCPY(key, ecc_clikey_der_256, sizeof_ecc_clikey_der_256); + #else + unsigned char cert[ONEK_BUF]; + unsigned char key[ONEK_BUF]; + XFILE fp; + int certSz, keySz; + + fp = XFOPEN("./certs/client-ecc-cert.der", "rb"); + AssertTrue(fp != XBADFILE); + certSz = (int)XFREAD(cert, 1, sizeof_cliecc_cert_der_256, fp); + XFCLOSE(fp); + + fp = XFOPEN("./certs/client-ecc-key.der", "rb"); + AssertTrue(fp != XBADFILE); + keySz = (int)XFREAD(key, 1, sizeof_ecc_clikey_der_256, fp); + XFCLOSE(fp); + #endif +#endif + + XMEMSET(output, 0, sizeof(output)); + + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); + + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)cert, certSz), 0); + + printf(testingFmt, "wc_PKCS7_EncodeData()"); + + pkcs7->content = data; + pkcs7->contentSz = sizeof(data); + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + AssertIntGT(wc_PKCS7_EncodeData(pkcs7, output, (word32)sizeof(output)), 0); + + /* Test bad args. */ + AssertIntEQ(wc_PKCS7_EncodeData(NULL, output, (word32)sizeof(output)), + BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeData(pkcs7, NULL, (word32)sizeof(output)), + BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeData(pkcs7, output, 5), BUFFER_E); + + printf(resultFmt, passed); + + wc_PKCS7_Free(pkcs7); +#endif +} /* END test_wc_PKCS7_EncodeData */ + + +#if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && \ + !defined(NO_RSA) && !defined(NO_SHA256) +/* RSA sign raw digest callback */ +static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz, + byte* out, word32 outSz, byte* privateKey, + word32 privateKeySz, int devid, int hashOID) +{ + /* specific DigestInfo ASN.1 encoding prefix for a SHA2565 digest */ + byte digInfoEncoding[] = { + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, + 0x00, 0x04, 0x20 + }; + + int ret; + byte digestInfo[ONEK_BUF]; + byte sig[FOURK_BUF]; + word32 digestInfoSz = 0; + word32 idx = 0; + RsaKey rsa; + + /* SHA-256 required only for this example callback due to above + * digInfoEncoding[] */ + if (pkcs7 == NULL || digest == NULL || out == NULL || + (sizeof(digestInfo) < sizeof(digInfoEncoding) + digestSz) || + (hashOID != SHA256h)) { + return -1; + } + + /* build DigestInfo */ + XMEMCPY(digestInfo, digInfoEncoding, sizeof(digInfoEncoding)); + digestInfoSz += sizeof(digInfoEncoding); + XMEMCPY(digestInfo + digestInfoSz, digest, digestSz); + digestInfoSz += digestSz; + + /* set up RSA key */ + ret = wc_InitRsaKey_ex(&rsa, pkcs7->heap, devid); + if (ret != 0) { + return ret; + } + + ret = wc_RsaPrivateKeyDecode(privateKey, &idx, &rsa, privateKeySz); + + /* sign DigestInfo */ + if (ret == 0) { + ret = wc_RsaSSL_Sign(digestInfo, digestInfoSz, sig, sizeof(sig), + &rsa, pkcs7->rng); + if (ret > 0) { + if (ret > (int)outSz) { + /* output buffer too small */ + ret = -1; + } else { + /* success, ret holds sig size */ + XMEMCPY(out, sig, ret); + } + } + } + + wc_FreeRsaKey(&rsa); + + return ret; +} +#endif + + +/* + * Testing wc_PKCS7_EncodeSignedData() + */ +static void test_wc_PKCS7_EncodeSignedData(void) +{ +#if defined(HAVE_PKCS7) + PKCS7* pkcs7; + WC_RNG rng; + byte output[FOURK_BUF]; + byte badOut[0]; + word32 outputSz = (word32)sizeof(output); + word32 badOutSz = (word32)sizeof(badOut); + byte data[] = "Test data to encode."; + +#ifndef NO_RSA + #if defined(USE_CERT_BUFFERS_2048) + byte key[sizeof_client_key_der_2048]; + byte cert[sizeof_client_cert_der_2048]; + word32 keySz = (word32)sizeof(key); + word32 certSz = (word32)sizeof(cert); + XMEMSET(key, 0, keySz); + XMEMSET(cert, 0, certSz); + XMEMCPY(key, client_key_der_2048, keySz); + XMEMCPY(cert, client_cert_der_2048, certSz); + #elif defined(USE_CERT_BUFFERS_1024) + byte key[sizeof_client_key_der_1024]; + byte cert[sizeof_client_cert_der_1024]; + word32 keySz = (word32)sizeof(key); + word32 certSz = (word32)sizeof(cert); + XMEMSET(key, 0, keySz); + XMEMSET(cert, 0, certSz); + XMEMCPY(key, client_key_der_1024, keySz); + XMEMCPY(cert, client_cert_der_1024, certSz); + #else + unsigned char cert[ONEK_BUF]; + unsigned char key[ONEK_BUF]; + XFILE fp; + int certSz; + int keySz; + + fp = XFOPEN("./certs/1024/client-cert.der", "rb"); + AssertTrue(fp != XBADFILE); + certSz = (int)XFREAD(cert, 1, sizeof_client_cert_der_1024, fp); + XFCLOSE(fp); + + fp = XFOPEN("./certs/1024/client-key.der", "rb"); + AssertTrue(fp != XBADFILE); + keySz = (int)XFREAD(key, 1, sizeof_client_key_der_1024, fp); + XFCLOSE(fp); + #endif +#elif defined(HAVE_ECC) + #if defined(USE_CERT_BUFFERS_256) + unsigned char cert[sizeof_cliecc_cert_der_256]; + unsigned char key[sizeof_ecc_clikey_der_256]; + int certSz = (int)sizeof(cert); + int keySz = (int)sizeof(key); + XMEMSET(cert, 0, certSz); + XMEMSET(key, 0, keySz); + XMEMCPY(cert, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); + XMEMCPY(key, ecc_clikey_der_256, sizeof_ecc_clikey_der_256); + #else + unsigned char cert[ONEK_BUF]; + unsigned char key[ONEK_BUF]; + XFILE fp; + int certSz, keySz; + + fp = XOPEN("./certs/client-ecc-cert.der", "rb"); + AssertTrue(fp != XBADFILE); + certSz = (int)XFREAD(cert, 1, sizeof_cliecc_cert_der_256, fp); + XFCLOSE(fp); + + fp = XFOPEN("./certs/client-ecc-key.der", "rb"); + AssertTrue(fp != XBADFILE); + keySz = (int)XFREAD(key, 1, sizeof_ecc_clikey_der_256, fp); + XFCLOSE(fp); + #endif +#endif + + XMEMSET(output, 0, outputSz); + AssertIntEQ(wc_InitRng(&rng), 0); + + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); + + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + + printf(testingFmt, "wc_PKCS7_EncodeSignedData()"); + + pkcs7->content = data; + pkcs7->contentSz = (word32)sizeof(data); + pkcs7->privateKey = key; + pkcs7->privateKeySz = (word32)sizeof(key); + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHAh; + pkcs7->rng = &rng; + + AssertIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0); + + wc_PKCS7_Free(pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, outputSz), 0); + + /* Pass in bad args. */ + AssertIntEQ(wc_PKCS7_EncodeSignedData(NULL, output, outputSz), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeSignedData(pkcs7, NULL, outputSz), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeSignedData(pkcs7, badOut, + badOutSz), BAD_FUNC_ARG); + pkcs7->hashOID = 0; /* bad hashOID */ + AssertIntEQ(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), BAD_FUNC_ARG); + +#if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && \ + !defined(NO_RSA) && !defined(NO_SHA256) + /* test RSA sign raw digest callback, if using RSA and compiled in. + * Example callback assumes SHA-256, so only run test if compiled in. */ + wc_PKCS7_Free(pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + + pkcs7->content = data; + pkcs7->contentSz = (word32)sizeof(data); + pkcs7->privateKey = key; + pkcs7->privateKeySz = (word32)sizeof(key); + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHA256h; + pkcs7->rng = &rng; + + AssertIntEQ(wc_PKCS7_SetRsaSignRawDigestCb(pkcs7, rsaSignRawDigestCb), 0); + + AssertIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0); +#endif + + printf(resultFmt, passed); + + wc_PKCS7_Free(pkcs7); + wc_FreeRng(&rng); + +#endif +} /* END test_wc_PKCS7_EncodeSignedData */ + + +/* + * Testing wc_PKCS7_EncodeSignedData_ex() and wc_PKCS7_VerifySignedData_ex() + */ +static void test_wc_PKCS7_EncodeSignedData_ex(void) +{ +#if defined(HAVE_PKCS7) + int ret, i; + PKCS7* pkcs7; + WC_RNG rng; + byte outputHead[FOURK_BUF/2]; + byte outputFoot[FOURK_BUF/2]; + word32 outputHeadSz = (word32)sizeof(outputHead); + word32 outputFootSz = (word32)sizeof(outputFoot); + byte data[FOURK_BUF]; + wc_HashAlg hash; + enum wc_HashType hashType = WC_HASH_TYPE_SHA; + byte hashBuf[WC_MAX_DIGEST_SIZE]; + word32 hashSz = wc_HashGetDigestSize(hashType); + +#ifndef NO_RSA + #if defined(USE_CERT_BUFFERS_2048) + byte key[sizeof_client_key_der_2048]; + byte cert[sizeof_client_cert_der_2048]; + word32 keySz = (word32)sizeof(key); + word32 certSz = (word32)sizeof(cert); + XMEMSET(key, 0, keySz); + XMEMSET(cert, 0, certSz); + XMEMCPY(key, client_key_der_2048, keySz); + XMEMCPY(cert, client_cert_der_2048, certSz); + #elif defined(USE_CERT_BUFFERS_1024) + byte key[sizeof_client_key_der_1024]; + byte cert[sizeof_client_cert_der_1024]; + word32 keySz = (word32)sizeof(key); + word32 certSz = (word32)sizeof(cert); + XMEMSET(key, 0, keySz); + XMEMSET(cert, 0, certSz); + XMEMCPY(key, client_key_der_1024, keySz); + XMEMCPY(cert, client_cert_der_1024, certSz); + #else + unsigned char cert[ONEK_BUF]; + unsigned char key[ONEK_BUF]; + XFILE fp; + int certSz; + int keySz; + + fp = XFOPEN("./certs/1024/client-cert.der", "rb"); + AssertTrue((fp != XBADFILE)); + certSz = (int)XFREAD(cert, 1, sizeof_client_cert_der_1024, fp); + XFCLOSE(fp); + + fp = XFOPEN("./certs/1024/client-key.der", "rb"); + AssertTrue(fp != XBADFILE); + keySz = (int)XFREAD(key, 1, sizeof_client_key_der_1024, fp); + XFCLOSE(fp); + #endif +#elif defined(HAVE_ECC) + #if defined(USE_CERT_BUFFERS_256) + unsigned char cert[sizeof_cliecc_cert_der_256]; + unsigned char key[sizeof_ecc_clikey_der_256]; + int certSz = (int)sizeof(cert); + int keySz = (int)sizeof(key); + XMEMSET(cert, 0, certSz); + XMEMSET(key, 0, keySz); + XMEMCPY(cert, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); + XMEMCPY(key, ecc_clikey_der_256, sizeof_ecc_clikey_der_256); + #else + unsigned char cert[ONEK_BUF]; + unsigned char key[ONEK_BUF]; + XFILE fp; + int certSz, keySz; + + fp = XFOPEN("./certs/client-ecc-cert.der", "rb"); + AssertTrue(fp != XBADFILE); + certSz = (int)XFREAD(cert, 1, sizeof_cliecc_cert_der_256, fp); + XFCLOSE(fp); + + fp = XFOPEN("./certs/client-ecc-key.der", "rb"); + AssertTrue(fp != XBADFILE); + keySz = (int)XFREAD(key, 1, sizeof_ecc_clikey_der_256, fp); + XFCLOSE(fp); + #endif +#endif + + /* initialize large data with sequence */ + for (i=0; i<(int)sizeof(data); i++) + data[i] = i & 0xff; + + XMEMSET(outputHead, 0, outputHeadSz); + XMEMSET(outputFoot, 0, outputFootSz); + AssertIntEQ(wc_InitRng(&rng), 0); + + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); + + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + + printf(testingFmt, "wc_PKCS7_EncodeSignedData()"); + + pkcs7->content = NULL; /* not used for ex */ + pkcs7->contentSz = (word32)sizeof(data); + pkcs7->privateKey = key; + pkcs7->privateKeySz = (word32)sizeof(key); + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHAh; + pkcs7->rng = &rng; + + /* calculate hash for content */ + ret = wc_HashInit(&hash, hashType); + if (ret == 0) { + ret = wc_HashUpdate(&hash, hashType, data, sizeof(data)); + if (ret == 0) { + ret = wc_HashFinal(&hash, hashType, hashBuf); + } + wc_HashFree(&hash, hashType); + } + AssertIntEQ(ret, 0); + + /* Perform PKCS7 sign using hash directly */ + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, &outputHeadSz, outputFoot, &outputFootSz), 0); + AssertIntGT(outputHeadSz, 0); + AssertIntGT(outputFootSz, 0); + + wc_PKCS7_Free(pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + + /* required parameter even on verify when using _ex */ + pkcs7->contentSz = (word32)sizeof(data); + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, outputHeadSz, outputFoot, outputFootSz), 0); + + wc_PKCS7_Free(pkcs7); + + /* assembly complete PKCS7 sign and use normal verify */ + { + byte* output = (byte*)XMALLOC(outputHeadSz + sizeof(data) + outputFootSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + word32 outputSz = 0; + AssertNotNull(output); + XMEMCPY(&output[outputSz], outputHead, outputHeadSz); + outputSz += outputHeadSz; + XMEMCPY(&output[outputSz], data, sizeof(data)); + outputSz += sizeof(data); + XMEMCPY(&output[outputSz], outputFoot, outputFootSz); + outputSz += outputFootSz; + + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, outputSz), 0); + XFREE(output, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + + /* Pass in bad args. */ + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(NULL, hashBuf, hashSz, outputHead, + &outputHeadSz, outputFoot, &outputFootSz), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, NULL, hashSz, outputHead, + &outputHeadSz, outputFoot, &outputFootSz), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, 0, outputHead, + &outputHeadSz, outputFoot, &outputFootSz), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, hashSz, NULL, + &outputHeadSz, outputFoot, &outputFootSz), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, NULL, outputFoot, &outputFootSz), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, &outputHeadSz, NULL, &outputFootSz), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, &outputHeadSz, outputFoot, NULL), BAD_FUNC_ARG); + pkcs7->hashOID = 0; /* bad hashOID */ + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, &outputHeadSz, outputFoot, &outputFootSz), BAD_FUNC_ARG); + + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(NULL, hashBuf, hashSz, outputHead, + outputHeadSz, outputFoot, outputFootSz), BAD_FUNC_ARG); + + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, NULL, hashSz, outputHead, + outputHeadSz, outputFoot, outputFootSz), BAD_FUNC_ARG); +#ifndef NO_PKCS7_STREAM + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, 0, outputHead, + outputHeadSz, outputFoot, outputFootSz), WC_PKCS7_WANT_READ_E); +#else + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, 0, outputHead, + outputHeadSz, outputFoot, outputFootSz), BUFFER_E); +#endif + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, NULL, + outputHeadSz, outputFoot, outputFootSz), BAD_FUNC_ARG); +#ifndef NO_PKCS7_STREAM + /* can pass in 0 buffer length with streaming API */ + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, 0, outputFoot, outputFootSz), WC_PKCS7_WANT_READ_E); +#else + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, 0, outputFoot, outputFootSz), BAD_FUNC_ARG); +#endif + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, outputHeadSz, NULL, outputFootSz), BAD_FUNC_ARG); +#ifndef NO_PKCS7_STREAM + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, outputHeadSz, outputFoot, 0), WC_PKCS7_WANT_READ_E); +#else + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, outputHeadSz, outputFoot, 0), ASN_PARSE_E); +#endif + + printf(resultFmt, passed); + + wc_PKCS7_Free(pkcs7); + wc_FreeRng(&rng); + +#endif +} /* END test_wc_PKCS7_EncodeSignedData_ex */ + + +#if defined(HAVE_PKCS7) +static int CreatePKCS7SignedData(unsigned char* output, int outputSz, + byte* data, word32 dataSz, + int withAttribs, int detachedSig) +{ + PKCS7* pkcs7; + WC_RNG rng; + + static byte messageTypeOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x02 }; + static byte messageType[] = { 0x13, 2, '1', '9' }; + + PKCS7Attrib attribs[] = + { + { messageTypeOid, sizeof(messageTypeOid), messageType, + sizeof(messageType) } + }; + +#ifndef NO_RSA + #if defined(USE_CERT_BUFFERS_2048) + byte key[sizeof_client_key_der_2048]; + byte cert[sizeof_client_cert_der_2048]; + word32 keySz = (word32)sizeof(key); + word32 certSz = (word32)sizeof(cert); + XMEMSET(key, 0, keySz); + XMEMSET(cert, 0, certSz); + XMEMCPY(key, client_key_der_2048, keySz); + XMEMCPY(cert, client_cert_der_2048, certSz); + #elif defined(USE_CERT_BUFFERS_1024) + byte key[sizeof_client_key_der_1024]; + byte cert[sizeof_client_cert_der_1024]; + word32 keySz = (word32)sizeof(key); + word32 certSz = (word32)sizeof(cert); + XMEMSET(key, 0, keySz); + XMEMSET(cert, 0, certSz); + XMEMCPY(key, client_key_der_1024, keySz); + XMEMCPY(cert, client_cert_der_1024, certSz); + #else + unsigned char cert[ONEK_BUF]; + unsigned char key[ONEK_BUF]; + FILE* fp; + int certSz; + int keySz; + + fp = fopen("./certs/1024/client-cert.der", "rb"); + AssertNotNull(fp); + certSz = fread(cert, 1, sizeof_client_cert_der_1024, fp); + fclose(fp); + + fp = fopen("./certs/1024/client-key.der", "rb"); + AssertNotNull(fp); + keySz = fread(key, 1, sizeof_client_key_der_1024, fp); + fclose(fp); + #endif +#elif defined(HAVE_ECC) + #if defined(USE_CERT_BUFFERS_256) + unsigned char cert[sizeof_cliecc_cert_der_256]; + unsigned char key[sizeof_ecc_clikey_der_256]; + int certSz = (int)sizeof(cert); + int keySz = (int)sizeof(key); + XMEMSET(cert, 0, certSz); + XMEMSET(key, 0, keySz); + XMEMCPY(cert, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); + XMEMCPY(key, ecc_clikey_der_256, sizeof_ecc_clikey_der_256); + #else + unsigned char cert[ONEK_BUF]; + unsigned char key[ONEK_BUF]; + FILE* fp; + int certSz, keySz; + + fp = fopen("./certs/client-ecc-cert.der", "rb"); + AssertNotNull(fp); + certSz = fread(cert, 1, sizeof_cliecc_cert_der_256, fp); + fclose(fp); + + fp = fopen("./certs/client-ecc-key.der", "rb"); + AssertNotNull(fp); + keySz = fread(key, 1, sizeof_ecc_clikey_der_256, fp); + fclose(fp); + #endif +#endif + + XMEMSET(output, 0, outputSz); + AssertIntEQ(wc_InitRng(&rng), 0); + + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); + + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + + printf(testingFmt, "wc_PKCS7_VerifySignedData()"); + + pkcs7->content = data; + pkcs7->contentSz = dataSz; + pkcs7->privateKey = key; + pkcs7->privateKeySz = (word32)sizeof(key); + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHAh; + pkcs7->rng = &rng; + if (withAttribs) { + /* include a signed attribute */ + pkcs7->signedAttribs = attribs; + pkcs7->signedAttribsSz = (sizeof(attribs)/sizeof(PKCS7Attrib)); + } + + if (detachedSig) { + AssertIntEQ(wc_PKCS7_SetDetached(pkcs7, 1), 0); + } + + AssertIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0); + wc_PKCS7_Free(pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + if (detachedSig) { + pkcs7->content = data; + pkcs7->contentSz = dataSz; + } + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, outputSz), 0); + + wc_PKCS7_Free(pkcs7); + wc_FreeRng(&rng); + + return outputSz; +} +#endif + +/* + * Testing wc_PKCS_VerifySignedData() + */ +static void test_wc_PKCS7_VerifySignedData(void) +{ +#if defined(HAVE_PKCS7) + PKCS7* pkcs7; + byte output[FOURK_BUF]; + word32 outputSz = sizeof(output); + byte data[] = "Test data to encode."; + byte badOut[0]; + word32 badOutSz = (word32)sizeof(badOut); + byte badContent[] = "This is different content than was signed"; + + AssertIntGT((outputSz = CreatePKCS7SignedData(output, outputSz, data, + (word32)sizeof(data), + 0, 0)), 0); + + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, outputSz), 0); + + /* Test bad args. */ + AssertIntEQ(wc_PKCS7_VerifySignedData(NULL, output, outputSz), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, NULL, outputSz), BAD_FUNC_ARG); +#ifndef NO_PKCS7_STREAM + /* can pass in 0 buffer length with streaming API */ + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, badOut, + badOutSz), WC_PKCS7_WANT_READ_E); +#else + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, badOut, + badOutSz), BAD_FUNC_ARG); +#endif + + wc_PKCS7_Free(pkcs7); + + /* Invalid content should error, use detached signature so we can + * easily change content */ + AssertIntGT((outputSz = CreatePKCS7SignedData(output, outputSz, data, + (word32)sizeof(data), + 1, 1)), 0); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + pkcs7->content = badContent; + pkcs7->contentSz = sizeof(badContent); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, outputSz), SIG_VERIFY_E); + wc_PKCS7_Free(pkcs7); + + /* Test success case with detached signature and valid content */ + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + pkcs7->content = data; + pkcs7->contentSz = sizeof(data); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, outputSz), 0); + wc_PKCS7_Free(pkcs7); + + printf(resultFmt, passed); +#endif +} /* END test_wc_PKCS7_VerifySignedData() */ + + +#if defined(HAVE_PKCS7) && !defined(NO_AES) && !defined(NO_AES_256) +static const byte defKey[] = { + 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 +}; +static byte aesHandle[32]; /* simulated hardware key handle */ + +/* return 0 on success */ +static int myDecryptionFunc(PKCS7* pkcs7, int encryptOID, byte* iv, int ivSz, + byte* aad, word32 aadSz, byte* authTag, word32 authTagSz, + byte* in, int inSz, byte* out, void* usrCtx) +{ + int ret; + Aes aes; + + if (usrCtx == NULL) { + /* no simulated handle passed in */ + return -1; + } + + switch (encryptOID) { + case AES256CBCb: + if (ivSz != AES_BLOCK_SIZE) + return BAD_FUNC_ARG; + break; + + default: + WOLFSSL_MSG("Unsupported content cipher type for test"); + return ALGO_ID_E; + }; + + /* simulate using handle to get key */ + ret = wc_AesInit(&aes, HEAP_HINT, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesSetKey(&aes, (byte*)usrCtx, 32, iv, AES_DECRYPTION); + if (ret == 0) + ret = wc_AesCbcDecrypt(&aes, out, in, inSz); + wc_AesFree(&aes); + } + + (void)aad; + (void)aadSz; + (void)authTag; + (void)authTagSz; + (void)pkcs7; + return ret; +} + + +/* returns key size on success */ +static int myCEKwrapFunc(PKCS7* pkcs7, byte* cek, word32 cekSz, byte* keyId, + word32 keyIdSz, byte* orginKey, word32 orginKeySz, + byte* out, word32 outSz, int keyWrapAlgo, int type, int direction) +{ + int ret = -1; + + if (out == NULL) + return BAD_FUNC_ARG; + + if (keyId[0] != 0x00) { + return -1; + } + + if (type != (int)PKCS7_KEKRI) { + return -1; + } + + switch (keyWrapAlgo) { + case AES256_WRAP: + /* simulate setting a handle for later decryption but use key + * as handle in the test case here */ + ret = wc_AesKeyUnWrap(defKey, sizeof(defKey), cek, cekSz, + aesHandle, sizeof(aesHandle), NULL); + if (ret < 0) + return ret; + + ret = wc_PKCS7_SetDecodeEncryptedCtx(pkcs7, (void*)aesHandle); + if (ret < 0) + return ret; + + /* return key size on success */ + return sizeof(defKey); + + default: + WOLFSSL_MSG("Unsupported key wrap algorithm in example"); + return BAD_KEYWRAP_ALG_E; + }; + + (void)cekSz; + (void)cek; + (void)outSz; + (void)keyIdSz; + (void)direction; + (void)orginKey; /* used with KAKRI */ + (void)orginKeySz; + return ret; +} +#endif /* HAVE_PKCS7 && !NO_AES && !NO_AES_256 */ + + +/* + * Testing wc_PKCS7_EncodeEnvelopedData() + */ +static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void) +{ +#if defined(HAVE_PKCS7) + PKCS7* pkcs7; + word32 tempWrd32 = 0; + byte* tmpBytePtr = NULL; + const char input[] = "Test data to encode."; + int i; + int testSz = 0; + #if !defined(NO_RSA) && (!defined(NO_AES) || (!defined(NO_SHA) || \ + !defined(NO_SHA256) || defined(WOLFSSL_SHA512))) + + byte* rsaCert = NULL; + byte* rsaPrivKey = NULL; + word32 rsaCertSz; + word32 rsaPrivKeySz; + #if !defined(NO_FILESYSTEM) && (!defined(USE_CERT_BUFFERS_1024) && \ + !defined(USE_CERT_BUFFERS_2048) ) + static const char* rsaClientCert = "./certs/client-cert.der"; + static const char* rsaClientKey = "./certs/client-key.der"; + rsaCertSz = (word32)sizeof(rsaClientCert); + rsaPrivKeySz = (word32)sizeof(rsaClientKey); + #endif + #endif + #if defined(HAVE_ECC) && (!defined(NO_AES) || (!defined(NO_SHA) ||\ + !defined(NO_SHA256) || defined(WOLFSSL_SHA512))) + + byte* eccCert = NULL; + byte* eccPrivKey = NULL; + word32 eccCertSz; + word32 eccPrivKeySz; + #if !defined(NO_FILESYSTEM) && !defined(USE_CERT_BUFFERS_256) + static const char* eccClientCert = "./certs/client-ecc-cert.der"; + static const char* eccClientKey = "./certs/ecc-client-key.der"; + #endif + #endif + /* Generic buffer size. */ + byte output[ONEK_BUF]; + byte decoded[sizeof(input)/sizeof(char)]; + int decodedSz = 0; +#ifndef NO_FILESYSTEM + XFILE certFile; + XFILE keyFile; +#endif + +#if !defined(NO_RSA) && (!defined(NO_AES) || (!defined(NO_SHA) ||\ + !defined(NO_SHA256) || defined(WOLFSSL_SHA512))) + /* RSA certs and keys. */ + #if defined(USE_CERT_BUFFERS_1024) + /* Allocate buffer space. */ + AssertNotNull(rsaCert = + (byte*)XMALLOC(ONEK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + /* Init buffer. */ + rsaCertSz = (word32)sizeof_client_cert_der_1024; + XMEMCPY(rsaCert, client_cert_der_1024, rsaCertSz); + AssertNotNull(rsaPrivKey = (byte*)XMALLOC(ONEK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER)); + rsaPrivKeySz = (word32)sizeof_client_key_der_1024; + XMEMCPY(rsaPrivKey, client_key_der_1024, rsaPrivKeySz); + + #elif defined(USE_CERT_BUFFERS_2048) + /* Allocate buffer */ + AssertNotNull(rsaCert = + (byte*)XMALLOC(TWOK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + /* Init buffer. */ + rsaCertSz = (word32)sizeof_client_cert_der_2048; + XMEMCPY(rsaCert, client_cert_der_2048, rsaCertSz); + AssertNotNull(rsaPrivKey = (byte*)XMALLOC(TWOK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER)); + rsaPrivKeySz = (word32)sizeof_client_key_der_2048; + XMEMCPY(rsaPrivKey, client_key_der_2048, rsaPrivKeySz); + + #else + /* File system. */ + certFile = XFOPEN(rsaClientCert, "rb"); + AssertTrue(certFile != XBADFILE); + rsaCertSz = (word32)FOURK_BUF; + AssertNotNull(rsaCert = + (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + rsaCertSz = (word32)XFREAD(rsaCert, 1, rsaCertSz, certFile); + XFCLOSE(certFile); + keyFile = XFOPEN(rsaClientKey, "rb"); + AssertTrue(keyFile != XBADFILE); + AssertNotNull(rsaPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER)); + rsaPrivKeySz = (word32)FOURK_BUF; + rsaPrivKeySz = (word32)XFREAD(rsaPrivKey, 1, rsaPrivKeySz, keyFile); + XFCLOSE(keyFile); + #endif /* USE_CERT_BUFFERS */ +#endif /* NO_RSA */ + +/* ECC */ +#if defined(HAVE_ECC) && (!defined(NO_AES) || (!defined(NO_SHA) ||\ + !defined(NO_SHA256) || defined(WOLFSSL_SHA512))) + + #ifdef USE_CERT_BUFFERS_256 + AssertNotNull(eccCert = + (byte*)XMALLOC(TWOK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + /* Init buffer. */ + eccCertSz = (word32)sizeof_cliecc_cert_der_256; + XMEMCPY(eccCert, cliecc_cert_der_256, eccCertSz); + AssertNotNull(eccPrivKey = (byte*)XMALLOC(TWOK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER)); + eccPrivKeySz = (word32)sizeof_ecc_clikey_der_256; + XMEMCPY(eccPrivKey, ecc_clikey_der_256, eccPrivKeySz); + #else /* File system. */ + certFile = XFOPEN(eccClientCert, "rb"); + AssertTrue(certFile != XBADFILE); + eccCertSz = (word32)FOURK_BUF; + AssertNotNull(eccCert = + (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + eccCertSz = (word32)XFREAD(eccCert, 1, eccCertSz, certFile); + XFCLOSE(certFile); + keyFile = XFOPEN(eccClientKey, "rb"); + AssertTrue(keyFile != XBADFILE); + eccPrivKeySz = (word32)FOURK_BUF; + AssertNotNull(eccPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER)); + eccPrivKeySz = (word32)XFREAD(eccPrivKey, 1, eccPrivKeySz, keyFile); + XFCLOSE(keyFile); + #endif /* USE_CERT_BUFFERS_256 */ +#endif /* END HAVE_ECC */ + + /* Silence. */ + (void)keyFile; + (void)certFile; + + const pkcs7EnvelopedVector testVectors[] = { + /* DATA is a global variable defined in the makefile. */ +#if !defined(NO_RSA) + #ifndef NO_DES3 + {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, DES3b, 0, 0, + rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz}, + #endif /* NO_DES3 */ + #ifndef NO_AES + #ifndef NO_AES_128 + {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, AES128CBCb, + 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz}, + #endif + #ifndef NO_AES_192 + {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, AES192CBCb, + 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz}, + #endif + #ifndef NO_AES_256 + {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, AES256CBCb, + 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz}, + #endif + #endif /* NO_AES */ + +#endif /* NO_RSA */ +#if defined(HAVE_ECC) + #ifndef NO_AES + #if !defined(NO_SHA) && !defined(NO_AES_128) + {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, AES128CBCb, + AES128_WRAP, dhSinglePass_stdDH_sha1kdf_scheme, eccCert, + eccCertSz, eccPrivKey, eccPrivKeySz}, + #endif + #if !defined(NO_SHA256) && !defined(NO_AES_256) + {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, AES256CBCb, + AES256_WRAP, dhSinglePass_stdDH_sha256kdf_scheme, eccCert, + eccCertSz, eccPrivKey, eccPrivKeySz}, + #endif + #if defined(WOLFSSL_SHA512) && !defined(NO_AES_256) + {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, AES256CBCb, + AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, + eccCertSz, eccPrivKey, eccPrivKeySz}, + #endif + #endif /* NO_AES */ +#endif /* END HAVE_ECC */ + }; /* END pkcs7EnvelopedVector */ + + printf(testingFmt, "wc_PKCS7_EncodeEnvelopedData()"); + + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, devId), 0); + + testSz = (int)sizeof(testVectors)/(int)sizeof(pkcs7EnvelopedVector); + for (i = 0; i < testSz; i++) { + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, (testVectors + i)->cert, + (word32)(testVectors + i)->certSz), 0); + + pkcs7->content = (byte*)(testVectors + i)->content; + pkcs7->contentSz = (testVectors + i)->contentSz; + pkcs7->contentOID = (testVectors + i)->contentOID; + pkcs7->encryptOID = (testVectors + i)->encryptOID; + pkcs7->keyWrapOID = (testVectors + i)->keyWrapOID; + pkcs7->keyAgreeOID = (testVectors + i)->keyAgreeOID; + pkcs7->privateKey = (testVectors + i)->privateKey; + pkcs7->privateKeySz = (testVectors + i)->privateKeySz; + + AssertIntGE(wc_PKCS7_EncodeEnvelopedData(pkcs7, output, + (word32)sizeof(output)), 0); + + decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, output, + (word32)sizeof(output), decoded, (word32)sizeof(decoded)); + AssertIntGE(decodedSz, 0); + /* Verify the size of each buffer. */ + AssertIntEQ((word32)sizeof(input)/sizeof(char), decodedSz); + /* Don't free the last time through the loop. */ + if (i < testSz - 1 ){ + wc_PKCS7_Free(pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + } + } /* END test loop. */ + + /* Test bad args. */ + AssertIntEQ(wc_PKCS7_EncodeEnvelopedData(NULL, output, + (word32)sizeof(output)), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeEnvelopedData(pkcs7, NULL, + (word32)sizeof(output)), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeEnvelopedData(pkcs7, output, 0), BAD_FUNC_ARG); + printf(resultFmt, passed); + + /* Decode. */ + printf(testingFmt, "wc_PKCS7_DecodeEnvelopedData()"); + + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(NULL, output, + (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, + (word32)sizeof(output), NULL, (word32)sizeof(decoded)), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, + (word32)sizeof(output), decoded, 0), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, NULL, + (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, 0, decoded, + (word32)sizeof(decoded)), BAD_FUNC_ARG); + /* Should get a return of BAD_FUNC_ARG with structure data. Order matters.*/ +#if defined(HAVE_ECC) && !defined(NO_AES) + /* only a failure for KARI test cases */ + tempWrd32 = pkcs7->singleCertSz; + pkcs7->singleCertSz = 0; + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, + (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); + pkcs7->singleCertSz = tempWrd32; + + tmpBytePtr = pkcs7->singleCert; + pkcs7->singleCert = NULL; + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, + (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); + pkcs7->singleCert = tmpBytePtr; +#endif + tempWrd32 = pkcs7->privateKeySz; + pkcs7->privateKeySz = 0; + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, + (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); + pkcs7->privateKeySz = tempWrd32; + + tmpBytePtr = pkcs7->privateKey; + pkcs7->privateKey = NULL; + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, + (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); + pkcs7->privateKey = tmpBytePtr; + wc_PKCS7_Free(pkcs7); + +#if !defined(NO_AES) && !defined(NO_AES_256) + /* test of decrypt callback with KEKRI enveloped data */ + { + int envelopedSz; + const byte keyId[] = { 0x00 }; + + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + pkcs7->content = (byte*)input; + pkcs7->contentSz = (word32)(sizeof(input)/sizeof(char)); + pkcs7->contentOID = DATA; + pkcs7->encryptOID = AES256CBCb; + AssertIntGT(wc_PKCS7_AddRecipient_KEKRI(pkcs7, AES256_WRAP, + (byte*)defKey, sizeof(defKey), (byte*)keyId, + sizeof(keyId), NULL, NULL, 0, NULL, 0, 0), 0); + AssertIntEQ(wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID), 0); + AssertIntGT((envelopedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, output, + (word32)sizeof(output))), 0); + wc_PKCS7_Free(pkcs7); + + /* decode envelopedData */ + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_SetWrapCEKCb(pkcs7, myCEKwrapFunc), 0); + AssertIntEQ(wc_PKCS7_SetDecodeEncryptedCb(pkcs7, myDecryptionFunc), 0); + AssertIntGT((decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, output, + envelopedSz, decoded, sizeof(decoded))), 0); + wc_PKCS7_Free(pkcs7); + } +#endif /* !NO_AES && !NO_AES_256 */ + + + printf(resultFmt, passed); +#ifndef NO_RSA + if (rsaCert) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + if (rsaPrivKey) { + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif /*NO_RSA */ +#ifdef HAVE_ECC + if (eccCert) { + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + if (eccPrivKey) { + XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif /* HAVE_ECC */ + +#endif /* HAVE_PKCS7 */ +} /* END test_wc_PKCS7_EncodeEnvelopedData() */ + + +/* + * Testing wc_PKCS7_EncodeEncryptedData() + */ +static void test_wc_PKCS7_EncodeEncryptedData (void) +{ +#if defined(HAVE_PKCS7) && !defined(NO_PKCS7_ENCRYPTED_DATA) + PKCS7* pkcs7; + byte* tmpBytePtr = NULL; + byte encrypted[TWOK_BUF]; + byte decoded[TWOK_BUF]; + word32 tmpWrd32 = 0; + int tmpInt = 0; + int decodedSz; + int encryptedSz; + int testSz; + int i; + + const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 + }; + + #ifndef NO_DES3 + byte desKey[] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef + }; + byte des3Key[] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 + }; + #endif + + #ifndef NO_AES + #ifndef NO_AES_128 + byte aes128Key[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 + }; + #endif + #ifndef NO_AES_192 + byte aes192Key[] = { + 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 + #ifndef NO_AES_256 + byte aes256Key[] = { + 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 + #endif + const pkcs7EncryptedVector testVectors[] = + { + #ifndef NO_DES3 + {data, (word32)sizeof(data), DATA, DES3b, des3Key, sizeof(des3Key)}, + + {data, (word32)sizeof(data), DATA, DESb, desKey, sizeof(desKey)}, + #endif /* NO_DES3 */ + #ifndef NO_AES + #ifndef NO_AES_128 + {data, (word32)sizeof(data), DATA, AES128CBCb, aes128Key, + sizeof(aes128Key)}, + #endif + + #ifndef NO_AES_192 + {data, (word32)sizeof(data), DATA, AES192CBCb, aes192Key, + sizeof(aes192Key)}, + #endif + + #ifndef NO_AES_256 + {data, (word32)sizeof(data), DATA, AES256CBCb, aes256Key, + sizeof(aes256Key)}, + #endif + + #endif /* NO_AES */ + }; + + testSz = sizeof(testVectors) / sizeof(pkcs7EncryptedVector); + + for (i = 0; i < testSz; i++) { + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, devId), 0); + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->encryptionKey = testVectors[i].encryptionKey; + pkcs7->encryptionKeySz = testVectors[i].encryptionKeySz; + pkcs7->heap = HEAP_HINT; + + /* encode encryptedData */ + encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, + sizeof(encrypted)); + AssertIntGT(encryptedSz, 0); + + /* Decode encryptedData */ + decodedSz = wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz, + decoded, sizeof(decoded)); + + AssertIntEQ(XMEMCMP(decoded, data, decodedSz), 0); + /* Keep values for last itr. */ + if (i < testSz - 1) { + wc_PKCS7_Free(pkcs7); + } + } + + printf(testingFmt, "wc_PKCS7_EncodeEncryptedData()"); + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(NULL, encrypted, + sizeof(encrypted)),BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, NULL, + sizeof(encrypted)), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, + 0), BAD_FUNC_ARG); + /* Testing the struct. */ + tmpBytePtr = pkcs7->content; + pkcs7->content = NULL; + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, + sizeof(encrypted)), BAD_FUNC_ARG); + pkcs7->content = tmpBytePtr; + tmpWrd32 = pkcs7->contentSz; + pkcs7->contentSz = 0; + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, + sizeof(encrypted)), BAD_FUNC_ARG); + pkcs7->contentSz = tmpWrd32; + tmpInt = pkcs7->encryptOID; + pkcs7->encryptOID = 0; + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, + sizeof(encrypted)), BAD_FUNC_ARG); + pkcs7->encryptOID = tmpInt; + tmpBytePtr = pkcs7->encryptionKey; + pkcs7->encryptionKey = NULL; + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, + sizeof(encrypted)), BAD_FUNC_ARG); + pkcs7->encryptionKey = tmpBytePtr; + tmpWrd32 = pkcs7->encryptionKeySz; + pkcs7->encryptionKeySz = 0; + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, + sizeof(encrypted)), BAD_FUNC_ARG); + pkcs7->encryptionKeySz = tmpWrd32; + + printf(resultFmt, passed); + + printf(testingFmt, "wc_PKCS7_EncodeEncryptedData()"); + + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(NULL, encrypted, encryptedSz, + decoded, sizeof(decoded)), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(pkcs7, NULL, encryptedSz, + decoded, sizeof(decoded)), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, 0, + decoded, sizeof(decoded)), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz, + NULL, sizeof(decoded)), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz, + decoded, 0), BAD_FUNC_ARG); + /* Test struct fields */ + + tmpBytePtr = pkcs7->encryptionKey; + pkcs7->encryptionKey = NULL; + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz, + decoded, sizeof(decoded)), BAD_FUNC_ARG); + pkcs7->encryptionKey = tmpBytePtr; + pkcs7->encryptionKeySz = 0; + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz, + decoded, sizeof(decoded)), BAD_FUNC_ARG); + + printf(resultFmt, passed); + wc_PKCS7_Free(pkcs7); +#endif +} /* END test_wc_PKCS7_EncodeEncryptedData() */ + +/* + * Testing wc_PKCS7_Degenerate() + */ +static void test_wc_PKCS7_Degenerate(void) +{ +#if defined(HAVE_PKCS7) && !defined(NO_FILESYSTEM) + PKCS7* pkcs7; + char fName[] = "./certs/test-degenerate.p7b"; + XFILE f; + byte der[4096]; + word32 derSz; + int ret; + + printf(testingFmt, "wc_PKCS7_Degenerate()"); + + AssertNotNull(f = XFOPEN(fName, "rb")); + AssertIntGT((ret = (int)fread(der, 1, sizeof(der), f)), 0); + derSz = (word32)ret; + XFCLOSE(f); + + /* test degenerate success */ + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); +#ifndef NO_RSA + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, der, derSz), 0); +#else + AssertIntNE(wc_PKCS7_VerifySignedData(pkcs7, der, derSz), 0); +#endif + wc_PKCS7_Free(pkcs7); + + /* test with turning off degenerate cases */ + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + wc_PKCS7_AllowDegenerate(pkcs7, 0); /* override allowing degenerate case */ + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, der, derSz), PKCS7_NO_SIGNER_E); + wc_PKCS7_Free(pkcs7); + + printf(resultFmt, passed); +#endif +} /* END test_wc_PKCS7_Degenerate() */ + +#if defined(HAVE_PKCS7) && !defined(NO_FILESYSTEM) && \ + defined(ASN_BER_TO_DER) && !defined(NO_DES3) +static byte berContent[] = { + 0x30, 0x80, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x07, 0x03, 0xA0, 0x80, 0x30, + 0x80, 0x02, 0x01, 0x00, 0x31, 0x82, 0x01, 0x48, + 0x30, 0x82, 0x01, 0x44, 0x02, 0x01, 0x00, 0x30, + 0x81, 0xAC, 0x30, 0x81, 0x9E, 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, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, + 0x5F, 0x31, 0x30, 0x32, 0x34, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, + 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, + 0x69, 0x6E, 0x67, 0x2D, 0x31, 0x30, 0x32, 0x34, + 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, 0x02, 0x09, 0x00, 0xBB, 0xD3, + 0x10, 0x03, 0xE6, 0x9D, 0x28, 0x03, 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x81, 0x80, + 0x2F, 0xF9, 0x77, 0x4F, 0x04, 0x5C, 0x16, 0x62, + 0xF0, 0x77, 0x8D, 0x95, 0x4C, 0xB1, 0x44, 0x9A, + 0x8C, 0x3C, 0x8C, 0xE4, 0xD1, 0xC1, 0x14, 0x72, + 0xD0, 0x4A, 0x1A, 0x94, 0x27, 0x0F, 0xAA, 0xE8, + 0xD0, 0xA2, 0xE7, 0xED, 0x4C, 0x7F, 0x0F, 0xC7, + 0x1B, 0xFB, 0x81, 0x0E, 0x76, 0x8F, 0xDD, 0x32, + 0x11, 0x68, 0xA0, 0x13, 0xD2, 0x8D, 0x95, 0xEF, + 0x80, 0x53, 0x81, 0x0E, 0x1F, 0xC8, 0xD6, 0x76, + 0x5C, 0x31, 0xD3, 0x77, 0x33, 0x29, 0xA6, 0x1A, + 0xD3, 0xC6, 0x14, 0x36, 0xCA, 0x8E, 0x7D, 0x72, + 0xA0, 0x29, 0x4C, 0xC7, 0x3A, 0xAF, 0xFE, 0xF7, + 0xFC, 0xD7, 0xE2, 0x8F, 0x6A, 0x20, 0x46, 0x09, + 0x40, 0x22, 0x2D, 0x79, 0x38, 0x11, 0xB1, 0x4A, + 0xE3, 0x48, 0xE8, 0x10, 0x37, 0xA0, 0x22, 0xF7, + 0xB4, 0x79, 0xD1, 0xA9, 0x3D, 0xC2, 0xAB, 0x37, + 0xAE, 0x82, 0x68, 0x1A, 0x16, 0xEF, 0x33, 0x0C, + 0x30, 0x80, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x07, 0x01, 0x30, 0x14, 0x06, + 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, + 0x07, 0x04, 0x08, 0xAD, 0xD0, 0x38, 0x9B, 0x16, + 0x4B, 0x7F, 0x99, 0xA0, 0x80, 0x04, 0x82, 0x03, + 0xE8, 0x6D, 0x48, 0xFB, 0x8A, 0xBD, 0xED, 0x6C, + 0xCD, 0xC6, 0x48, 0xFD, 0xB7, 0xB0, 0x7C, 0x86, + 0x2C, 0x8D, 0xF0, 0x23, 0x12, 0xD8, 0xA3, 0x2A, + 0x21, 0x6F, 0x8B, 0x75, 0xBB, 0x47, 0x7F, 0xC9, + 0xBA, 0xBA, 0xFF, 0x91, 0x09, 0x01, 0x7A, 0x5C, + 0x96, 0x02, 0xB8, 0x8E, 0xF8, 0x67, 0x7E, 0x8F, + 0xF9, 0x51, 0x0E, 0xFF, 0x8E, 0xE2, 0x61, 0xC0, + 0xDF, 0xFA, 0xE2, 0x4C, 0x50, 0x90, 0xAE, 0xA1, + 0x15, 0x38, 0x3D, 0xBE, 0x88, 0xD7, 0x57, 0xC0, + 0x11, 0x44, 0xA2, 0x61, 0x05, 0x49, 0x6A, 0x94, + 0x04, 0x10, 0xD9, 0xC2, 0x2D, 0x15, 0x20, 0x0D, + 0xBD, 0xA2, 0xEF, 0xE4, 0x68, 0xFA, 0x39, 0x75, + 0x7E, 0xD8, 0x64, 0x44, 0xCB, 0xE0, 0x00, 0x6D, + 0x57, 0x4E, 0x8A, 0x17, 0xA9, 0x83, 0x6C, 0x7F, + 0xFE, 0x01, 0xEE, 0xDE, 0x99, 0x3A, 0xB2, 0xFF, + 0xD3, 0x72, 0x78, 0xBA, 0xF1, 0x23, 0x54, 0x48, + 0x02, 0xD8, 0x38, 0xA9, 0x54, 0xE5, 0x4A, 0x81, + 0xB9, 0xC0, 0x67, 0xB2, 0x7D, 0x3C, 0x6F, 0xCE, + 0xA4, 0xDD, 0x34, 0x5F, 0x60, 0xB1, 0xA3, 0x7A, + 0xE4, 0x43, 0xF2, 0x89, 0x64, 0x35, 0x09, 0x32, + 0x51, 0xFB, 0x5C, 0x67, 0x0C, 0x3B, 0xFC, 0x36, + 0x6B, 0x37, 0x43, 0x6C, 0x03, 0xCD, 0x44, 0xC7, + 0x2B, 0x62, 0xD6, 0xD1, 0xF4, 0x07, 0x7B, 0x19, + 0x91, 0xF0, 0xD7, 0xF5, 0x54, 0xBC, 0x0F, 0x42, + 0x6B, 0x69, 0xF7, 0xA3, 0xC8, 0xEE, 0xB9, 0x7A, + 0x9E, 0x3D, 0xDF, 0x53, 0x47, 0xF7, 0x50, 0x67, + 0x00, 0xCF, 0x2B, 0x3B, 0xE9, 0x85, 0xEE, 0xBD, + 0x4C, 0x64, 0x66, 0x0B, 0x77, 0x80, 0x9D, 0xEF, + 0x11, 0x32, 0x77, 0xA8, 0xA4, 0x5F, 0xEE, 0x2D, + 0xE0, 0x43, 0x87, 0x76, 0x87, 0x53, 0x4E, 0xD7, + 0x1A, 0x04, 0x7B, 0xE1, 0xD1, 0xE1, 0xF5, 0x87, + 0x51, 0x13, 0xE0, 0xC2, 0xAA, 0xA3, 0x4B, 0xAA, + 0x9E, 0xB4, 0xA6, 0x1D, 0x4E, 0x28, 0x57, 0x0B, + 0x80, 0x90, 0x81, 0x4E, 0x04, 0xF5, 0x30, 0x8D, + 0x51, 0xCE, 0x57, 0x2F, 0x88, 0xC5, 0x70, 0xC4, + 0x06, 0x8F, 0xDD, 0x37, 0xC1, 0x34, 0x1E, 0x0E, + 0x15, 0x32, 0x23, 0x92, 0xAB, 0x40, 0xEA, 0xF7, + 0x43, 0xE2, 0x1D, 0xE2, 0x4B, 0xC9, 0x91, 0xF4, + 0x63, 0x21, 0x34, 0xDB, 0xE9, 0x86, 0x83, 0x1A, + 0xD2, 0x52, 0xEF, 0x7A, 0xA2, 0xEE, 0xA4, 0x11, + 0x56, 0xD3, 0x6C, 0xF5, 0x6D, 0xE4, 0xA5, 0x2D, + 0x99, 0x02, 0x10, 0xDF, 0x29, 0xC5, 0xE3, 0x0B, + 0xC4, 0xA1, 0xEE, 0x5F, 0x4A, 0x10, 0xEE, 0x85, + 0x73, 0x2A, 0x92, 0x15, 0x2C, 0xC8, 0xF4, 0x8C, + 0xD7, 0x3D, 0xBC, 0xAD, 0x18, 0xE0, 0x59, 0xD3, + 0xEE, 0x75, 0x90, 0x1C, 0xCC, 0x76, 0xC6, 0x64, + 0x17, 0xD2, 0xD0, 0x91, 0xA6, 0xD0, 0xC1, 0x4A, + 0xAA, 0x58, 0x22, 0xEC, 0x45, 0x98, 0xF2, 0xCC, + 0x4C, 0xE4, 0xBF, 0xED, 0xF6, 0x44, 0x72, 0x36, + 0x65, 0x3F, 0xE3, 0xB5, 0x8B, 0x3E, 0x54, 0x9C, + 0x82, 0x86, 0x5E, 0xB0, 0xF2, 0x12, 0xE5, 0x69, + 0xFA, 0x46, 0xA2, 0x54, 0xFC, 0xF5, 0x4B, 0xE0, + 0x24, 0x3B, 0x99, 0x04, 0x1A, 0x7A, 0xF7, 0xD1, + 0xFF, 0x68, 0x97, 0xB2, 0x85, 0x82, 0x95, 0x27, + 0x2B, 0xF4, 0xE7, 0x1A, 0x74, 0x19, 0xEC, 0x8C, + 0x4E, 0xA7, 0x0F, 0xAD, 0x4F, 0x5A, 0x02, 0x80, + 0xC1, 0x6A, 0x9E, 0x54, 0xE4, 0x8E, 0xA3, 0x41, + 0x3F, 0x6F, 0x9C, 0x82, 0x9F, 0x83, 0xB0, 0x44, + 0x01, 0x5F, 0x10, 0x9D, 0xD3, 0xB6, 0x33, 0x5B, + 0xAF, 0xAC, 0x6B, 0x57, 0x2A, 0x01, 0xED, 0x0E, + 0x17, 0xB9, 0x80, 0x76, 0x12, 0x1C, 0x51, 0x56, + 0xDD, 0x6D, 0x94, 0xAB, 0xD2, 0xE5, 0x15, 0x2D, + 0x3C, 0xC5, 0xE8, 0x62, 0x05, 0x8B, 0x40, 0xB1, + 0xC2, 0x83, 0xCA, 0xAC, 0x4B, 0x8B, 0x39, 0xF7, + 0xA0, 0x08, 0x43, 0x5C, 0xF7, 0xE8, 0xED, 0x40, + 0x72, 0x73, 0xE3, 0x6B, 0x18, 0x67, 0xA0, 0xB6, + 0x0F, 0xED, 0x8F, 0x9A, 0xE4, 0x27, 0x62, 0x23, + 0xAA, 0x6D, 0x6C, 0x31, 0xC9, 0x9D, 0x6B, 0xE0, + 0xBF, 0x9D, 0x7D, 0x2E, 0x76, 0x71, 0x06, 0x39, + 0xAC, 0x96, 0x1C, 0xAF, 0x30, 0xF2, 0x62, 0x9C, + 0x84, 0x3F, 0x43, 0x5E, 0x19, 0xA8, 0xE5, 0x3C, + 0x9D, 0x43, 0x3C, 0x43, 0x41, 0xE8, 0x82, 0xE7, + 0x5B, 0xF3, 0xE2, 0x15, 0xE3, 0x52, 0x20, 0xFD, + 0x0D, 0xB2, 0x4D, 0x48, 0xAD, 0x53, 0x7E, 0x0C, + 0xF0, 0xB9, 0xBE, 0xC9, 0x58, 0x4B, 0xC8, 0xA8, + 0xA3, 0x36, 0xF1, 0x2C, 0xD2, 0xE1, 0xC8, 0xC4, + 0x3C, 0x48, 0x70, 0xC2, 0x6D, 0x6C, 0x3D, 0x99, + 0xAC, 0x43, 0x19, 0x69, 0xCA, 0x67, 0x1A, 0xC9, + 0xE1, 0x47, 0xFA, 0x0A, 0xE6, 0x5B, 0x6F, 0x61, + 0xD0, 0x03, 0xE4, 0x03, 0x4B, 0xFD, 0xE2, 0xA5, + 0x8D, 0x83, 0x01, 0x7E, 0xC0, 0x7B, 0x2E, 0x0B, + 0x29, 0xDD, 0xD6, 0xDC, 0x71, 0x46, 0xBD, 0x9A, + 0x40, 0x46, 0x1E, 0x0A, 0xB1, 0x00, 0xE7, 0x71, + 0x29, 0x77, 0xFC, 0x9A, 0x76, 0x8A, 0x5F, 0x66, + 0x9B, 0x63, 0x91, 0x12, 0x78, 0xBF, 0x67, 0xAD, + 0xA1, 0x72, 0x9E, 0xC5, 0x3E, 0xE5, 0xCB, 0xAF, + 0xD6, 0x5A, 0x0D, 0xB6, 0x9B, 0xA3, 0x78, 0xE8, + 0xB0, 0x8F, 0x69, 0xED, 0xC1, 0x73, 0xD5, 0xE5, + 0x1C, 0x18, 0xA0, 0x58, 0x4C, 0x49, 0xBD, 0x91, + 0xCE, 0x15, 0x0D, 0xAA, 0x5A, 0x07, 0xEA, 0x1C, + 0xA7, 0x4B, 0x11, 0x31, 0x80, 0xAF, 0xA1, 0x0A, + 0xED, 0x6C, 0x70, 0xE4, 0xDB, 0x75, 0x86, 0xAE, + 0xBF, 0x4A, 0x05, 0x72, 0xDE, 0x84, 0x8C, 0x7B, + 0x59, 0x81, 0x58, 0xE0, 0xC0, 0x15, 0xB5, 0xF3, + 0xD5, 0x73, 0x78, 0x83, 0x53, 0xDA, 0x92, 0xC1, + 0xE6, 0x71, 0x74, 0xC7, 0x7E, 0xAA, 0x36, 0x06, + 0xF0, 0xDF, 0xBA, 0xFB, 0xEF, 0x54, 0xE8, 0x11, + 0xB2, 0x33, 0xA3, 0x0B, 0x9E, 0x0C, 0x59, 0x75, + 0x13, 0xFA, 0x7F, 0x88, 0xB9, 0x86, 0xBD, 0x1A, + 0xDB, 0x52, 0x12, 0xFB, 0x6D, 0x1A, 0xCB, 0x49, + 0x94, 0x94, 0xC4, 0xA9, 0x99, 0xC0, 0xA4, 0xB6, + 0x60, 0x36, 0x09, 0x94, 0x2A, 0xD5, 0xC4, 0x26, + 0xF4, 0xA3, 0x6A, 0x0E, 0x57, 0x8B, 0x7C, 0xA4, + 0x1D, 0x75, 0xE8, 0x2A, 0xF3, 0xC4, 0x3C, 0x7D, + 0x45, 0x6D, 0xD8, 0x24, 0xD1, 0x3B, 0xF7, 0xCF, + 0xE4, 0x45, 0x2A, 0x55, 0xE5, 0xA9, 0x1F, 0x1C, + 0x8F, 0x55, 0x8D, 0xC1, 0xF7, 0x74, 0xCC, 0x26, + 0xC7, 0xBA, 0x2E, 0x5C, 0xC1, 0x71, 0x0A, 0xAA, + 0xD9, 0x6D, 0x76, 0xA7, 0xF9, 0xD1, 0x18, 0xCB, + 0x5A, 0x52, 0x98, 0xA8, 0x0D, 0x3F, 0x06, 0xFC, + 0x49, 0x11, 0x21, 0x5F, 0x86, 0x19, 0x33, 0x81, + 0xB5, 0x7A, 0xDA, 0xA1, 0x47, 0xBF, 0x7C, 0xD7, + 0x05, 0x96, 0xC7, 0xF5, 0xC1, 0x61, 0xE5, 0x18, + 0xA5, 0x38, 0x68, 0xED, 0xB4, 0x17, 0x62, 0x0D, + 0x01, 0x5E, 0xC3, 0x04, 0xA6, 0xBA, 0xB1, 0x01, + 0x60, 0x5C, 0xC1, 0x3A, 0x34, 0x97, 0xD6, 0xDB, + 0x67, 0x73, 0x4D, 0x33, 0x96, 0x01, 0x67, 0x44, + 0xEA, 0x47, 0x5E, 0x44, 0xB5, 0xE5, 0xD1, 0x6C, + 0x20, 0xA9, 0x6D, 0x4D, 0xBC, 0x02, 0xF0, 0x70, + 0xE4, 0xDD, 0xE9, 0xD5, 0x5C, 0x28, 0x29, 0x0B, + 0xB4, 0x60, 0x2A, 0xF1, 0xF7, 0x1A, 0xF0, 0x36, + 0xAE, 0x51, 0x3A, 0xAE, 0x6E, 0x48, 0x7D, 0xC7, + 0x5C, 0xF3, 0xDC, 0xF6, 0xED, 0x27, 0x4E, 0x8E, + 0x48, 0x18, 0x3E, 0x08, 0xF1, 0xD8, 0x3D, 0x0D, + 0xE7, 0x2F, 0x65, 0x8A, 0x6F, 0xE2, 0x1E, 0x06, + 0xC1, 0x04, 0x58, 0x7B, 0x4A, 0x75, 0x60, 0x92, + 0x13, 0xC6, 0x40, 0x2D, 0x3A, 0x8A, 0xD1, 0x03, + 0x05, 0x1F, 0x28, 0x66, 0xC2, 0x57, 0x2A, 0x4C, + 0xE1, 0xA3, 0xCB, 0xA1, 0x95, 0x30, 0x10, 0xED, + 0xDF, 0xAE, 0x70, 0x49, 0x4E, 0xF6, 0xB4, 0x5A, + 0xB6, 0x22, 0x56, 0x37, 0x05, 0xE7, 0x3E, 0xB2, + 0xE3, 0x96, 0x62, 0xEC, 0x09, 0x53, 0xC0, 0x50, + 0x3D, 0xA7, 0xBC, 0x9B, 0x39, 0x02, 0x26, 0x16, + 0xB5, 0x34, 0x17, 0xD4, 0xCA, 0xFE, 0x1D, 0xE4, + 0x5A, 0xDA, 0x4C, 0xC2, 0xCA, 0x8E, 0x79, 0xBF, + 0xD8, 0x4C, 0xBB, 0xFA, 0x30, 0x7B, 0xA9, 0x3E, + 0x52, 0x19, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif /* HAVE_PKCS7 && !NO_FILESYSTEM && ASN_BER_TO_DER && !NO_DES3 */ + +/* + * Testing wc_PKCS7_BER() + */ +static void test_wc_PKCS7_BER(void) +{ +#if defined(HAVE_PKCS7) && !defined(NO_FILESYSTEM) && \ + defined(ASN_BER_TO_DER) + PKCS7* pkcs7; + char fName[] = "./certs/test-ber-exp02-05-2022.p7b"; + XFILE f; + byte der[4096]; +#ifndef NO_DES3 + byte decoded[2048]; +#endif + word32 derSz; + int ret; + + printf(testingFmt, "wc_PKCS7_BER()"); + + AssertNotNull(f = XFOPEN(fName, "rb")); + AssertIntGT((ret = (int)fread(der, 1, sizeof(der), f)), 0); + derSz = (word32)ret; + XFCLOSE(f); + + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); +#ifndef NO_RSA + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, der, derSz), 0); +#else + AssertIntNE(wc_PKCS7_VerifySignedData(pkcs7, der, derSz), 0); +#endif + wc_PKCS7_Free(pkcs7); + +#ifndef NO_DES3 + /* decode BER content */ + AssertNotNull(f = XFOPEN("./certs/1024/client-cert.der", "rb")); + AssertIntGT((ret = (int)fread(der, 1, sizeof(der), f)), 0); + derSz = (word32)ret; + XFCLOSE(f); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); +#ifndef NO_RSA + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, der, derSz), 0); +#else + AssertIntNE(wc_PKCS7_InitWithCert(pkcs7, der, derSz), 0); +#endif + + AssertNotNull(f = XFOPEN("./certs/1024/client-key.der", "rb")); + AssertIntGT((ret = (int)fread(der, 1, sizeof(der), f)), 0); + derSz = (word32)ret; + XFCLOSE(f); + pkcs7->privateKey = der; + pkcs7->privateKeySz = derSz; +#ifndef NO_RSA + AssertIntGT(wc_PKCS7_DecodeEnvelopedData(pkcs7, berContent, + sizeof(berContent), decoded, sizeof(decoded)), 0); +#else + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, berContent, + sizeof(berContent), decoded, sizeof(decoded)), NOT_COMPILED_IN); +#endif + wc_PKCS7_Free(pkcs7); +#endif /* !NO_DES3 */ + + printf(resultFmt, passed); +#endif +} /* END test_wc_PKCS7_BER() */ + +static void test_PKCS7_signed_enveloped(void) +{ +#if defined(HAVE_PKCS7) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) \ + && !defined(NO_AES) + XFILE f; + PKCS7* pkcs7; + PKCS7* inner; + void* pt; + WC_RNG rng; + unsigned char key[FOURK_BUF/2]; + unsigned char cert[FOURK_BUF/2]; + unsigned char env[FOURK_BUF]; + int envSz = FOURK_BUF; + int keySz; + int certSz; + + unsigned char sig[FOURK_BUF * 2]; + int sigSz = FOURK_BUF * 2; + unsigned char decoded[FOURK_BUF]; + int decodedSz = FOURK_BUF; + + printf(testingFmt, "PKCS7_signed_enveloped"); + + /* load cert */ + AssertNotNull(f = XFOPEN(cliCertDerFile, "rb")); + AssertIntGT((certSz = (int)XFREAD(cert, 1, sizeof(cert), f)), 0); + XFCLOSE(f); + + /* load key */ + AssertNotNull(f = XFOPEN(cliKeyFile, "rb")); + AssertIntGT((keySz = (int)XFREAD(key, 1, sizeof(key), f)), 0); + XFCLOSE(f); + keySz = wolfSSL_KeyPemToDer(key, keySz, key, keySz, NULL); + + /* sign cert for envelope */ + AssertNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + AssertIntEQ(wc_InitRng(&rng), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + pkcs7->content = cert; + pkcs7->contentSz = certSz; + pkcs7->contentOID = DATA; + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHA256h; + pkcs7->rng = &rng; + AssertIntGT((sigSz = wc_PKCS7_EncodeSignedData(pkcs7, sig, sigSz)), 0); + wc_PKCS7_Free(pkcs7); + wc_FreeRng(&rng); + + /* create envelope */ + AssertNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + pkcs7->content = sig; + pkcs7->contentSz = sigSz; + pkcs7->contentOID = DATA; + pkcs7->encryptOID = AES256CBCb; + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + AssertIntGT((envSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, env, envSz)), 0); + wc_PKCS7_Free(pkcs7); + + /* create bad signed enveloped data */ + sigSz = FOURK_BUF * 2; + AssertNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + AssertIntEQ(wc_InitRng(&rng), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + pkcs7->content = env; + pkcs7->contentSz = envSz; + pkcs7->contentOID = DATA; + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHA256h; + pkcs7->rng = &rng; + + /* Set no certs in bundle for this test. Hang on to the pointer though to + * free it later. */ + pt = (void*)pkcs7->certList; + pkcs7->certList = NULL; /* no certs in bundle */ + AssertIntGT((sigSz = wc_PKCS7_EncodeSignedData(pkcs7, sig, sigSz)), 0); + pkcs7->certList = (Pkcs7Cert*)pt; /* restore pointer for PKCS7 free call */ + wc_PKCS7_Free(pkcs7); + + /* check verify fails */ + AssertNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, sig, sigSz), + PKCS7_SIGNEEDS_CHECK); + + /* try verifying the signature manually */ + { + RsaKey rKey; + word32 idx = 0; + byte digest[MAX_SEQ_SZ + MAX_ALGO_SZ + MAX_OCTET_STR_SZ + + WC_MAX_DIGEST_SIZE]; + int digestSz; + + AssertIntEQ(wc_InitRsaKey(&rKey, HEAP_HINT), 0); + AssertIntEQ(wc_RsaPrivateKeyDecode(key, &idx, &rKey, keySz), 0); + digestSz = wc_RsaSSL_Verify(pkcs7->signature, pkcs7->signatureSz, + digest, sizeof(digest), &rKey); + AssertIntGT(digestSz, 0); + AssertIntEQ(digestSz, pkcs7->pkcs7DigestSz); + AssertIntEQ(XMEMCMP(digest, pkcs7->pkcs7Digest, digestSz), 0); + AssertIntEQ(wc_FreeRsaKey(&rKey), 0); + /* verify was success */ + } + + wc_PKCS7_Free(pkcs7); + + /* initializing the PKCS7 struct with the signing certificate should pass */ + AssertNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, sig, sigSz), 0); + wc_PKCS7_Free(pkcs7); + + /* create valid degenerate bundle */ + sigSz = FOURK_BUF * 2; + AssertNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + pkcs7->content = env; + pkcs7->contentSz = envSz; + pkcs7->contentOID = DATA; + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHA256h; + pkcs7->rng = &rng; + AssertIntEQ(wc_PKCS7_SetSignerIdentifierType(pkcs7, DEGENERATE_SID), 0); + AssertIntGT((sigSz = wc_PKCS7_EncodeSignedData(pkcs7, sig, sigSz)), 0); + wc_PKCS7_Free(pkcs7); + wc_FreeRng(&rng); + + /* check verify */ + AssertNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, devId), 0); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, sig, sigSz), 0); + AssertNotNull(pkcs7->content); + + /* check decode */ + AssertNotNull(inner = wc_PKCS7_New(NULL, 0)); + AssertIntEQ(wc_PKCS7_InitWithCert(inner, cert, certSz), 0); + inner->privateKey = key; + inner->privateKeySz = keySz; + AssertIntGT((decodedSz = wc_PKCS7_DecodeEnvelopedData(inner, pkcs7->content, + pkcs7->contentSz, decoded, decodedSz)), 0); + wc_PKCS7_Free(inner); + wc_PKCS7_Free(pkcs7); + + /* check cert set */ + AssertNotNull(pkcs7 = wc_PKCS7_New(NULL, 0)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, decoded, decodedSz), 0); + AssertNotNull(pkcs7->singleCert); + AssertIntNE(pkcs7->singleCertSz, 0); + wc_PKCS7_Free(pkcs7); + + printf(resultFmt, passed); + +#endif +} + +static void test_wc_i2d_PKCS12(void) +{ +#if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12) \ + && !defined(NO_FILESYSTEM) && !defined(NO_RSA) \ + && !defined(NO_AES) && !defined(NO_DES3) && !defined(NO_SHA) + WC_PKCS12* pkcs12 = NULL; + unsigned char der[FOURK_BUF * 2]; + unsigned char* pt; + int derSz; + unsigned char out[FOURK_BUF * 2]; + int outSz = FOURK_BUF * 2; + + const char p12_f[] = "./certs/test-servercert.p12"; + XFILE f; + + printf(testingFmt, "wc_i2d_PKCS12"); + + f = XFOPEN(p12_f, "rb"); + AssertNotNull(f); + derSz = (int)XFREAD(der, 1, sizeof(der), f); + AssertIntGT(derSz, 0); + XFCLOSE(f); + + AssertNotNull(pkcs12 = wc_PKCS12_new()); + AssertIntEQ(wc_d2i_PKCS12(der, derSz, pkcs12), 0); + AssertIntEQ(wc_i2d_PKCS12(pkcs12, NULL, &outSz), LENGTH_ONLY_E); + AssertIntEQ(outSz, derSz); + + outSz = derSz - 1; + pt = out; + AssertIntLE(wc_i2d_PKCS12(pkcs12, &pt, &outSz), 0); + + outSz = derSz; + AssertIntEQ(wc_i2d_PKCS12(pkcs12, &pt, &outSz), derSz); + AssertIntEQ((pt == out), 0); + + pt = NULL; + AssertIntEQ(wc_i2d_PKCS12(pkcs12, &pt, NULL), derSz); + XFREE(pt, NULL, DYNAMIC_TYPE_PKCS); + wc_PKCS12_free(pkcs12); + + printf(resultFmt, passed); + +#endif +} + + +/* Testing wc_SignatureGetSize() for signature type ECC */ +static int test_wc_SignatureGetSize_ecc(void) +{ + int ret = 0; + #ifndef NO_SIG_WRAPPER + #if defined(HAVE_ECC) && !defined(NO_ECC256) + enum wc_SignatureType sig_type; + word32 key_len; + + /* Initialize ECC Key */ + ecc_key ecc; + const char* qx = + "fa2737fb93488d19caef11ae7faf6b7f4bcd67b286e3fc54e8a65c2b74aeccb0"; + const char* qy = + "d4ccd6dae698208aa8c3a6f39e45510d03be09b2f124bfc067856c324f9b4d09"; + const char* d = + "be34baa8d040a3b991f9075b56ba292f755b90e4b6dc10dad36715c33cfdac25"; + + ret = wc_ecc_init(&ecc); + if (ret == 0) { + ret = wc_ecc_import_raw(&ecc, qx, qy, d, "SECP256R1"); + } + printf(testingFmt, "wc_SigntureGetSize_ecc()"); + if (ret == 0) { + /* Input for signature type ECC */ + sig_type = WC_SIGNATURE_TYPE_ECC; + key_len = sizeof(ecc_key); + ret = wc_SignatureGetSize(sig_type, &ecc, key_len); + + /* Test bad args */ + if (ret > 0) { + sig_type = (enum wc_SignatureType) 100; + ret = wc_SignatureGetSize(sig_type, &ecc, key_len); + if (ret == BAD_FUNC_ARG) { + sig_type = WC_SIGNATURE_TYPE_ECC; + ret = wc_SignatureGetSize(sig_type, NULL, key_len); + } + if (ret >= 0) { + key_len = (word32) 0; + ret = wc_SignatureGetSize(sig_type, &ecc, key_len); + } + if (ret == BAD_FUNC_ARG) { + ret = SIG_TYPE_E; + } + } + } else { + ret = WOLFSSL_FATAL_ERROR; + } + wc_ecc_free(&ecc); + #else + ret = SIG_TYPE_E; + #endif + + if (ret == SIG_TYPE_E) { + ret = 0; + } + else { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + #endif /* NO_SIG_WRAPPER */ + return ret; +}/* END test_wc_SignatureGetSize_ecc() */ + +/* Testing wc_SignatureGetSize() for signature type rsa */ +static int test_wc_SignatureGetSize_rsa(void) +{ + int ret = 0; + #ifndef NO_SIG_WRAPPER + #ifndef NO_RSA + enum wc_SignatureType sig_type; + word32 key_len; + word32 idx = 0; + + /* Initialize RSA Key */ + RsaKey rsa_key; + byte* tmp = NULL; + size_t bytes; + + #ifdef USE_CERT_BUFFERS_1024 + bytes = (size_t)sizeof_client_key_der_1024; + if (bytes < (size_t)sizeof_client_key_der_1024) + bytes = (size_t)sizeof_client_cert_der_1024; + #elif defined(USE_CERT_BUFFERS_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 + bytes = FOURK_BUF; + #endif + + tmp = (byte*)XMALLOC(bytes, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp != NULL) { + #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 = XFOPEN(clientKey, "rb"); + if (file != XBADFILE) { + bytes = (size_t)XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); + } + else { + ret = WOLFSSL_FATAL_ERROR; + } + #else + ret = WOLFSSL_FATAL_ERROR; + #endif + } else { + ret = WOLFSSL_FATAL_ERROR; + } + + if (ret == 0) { + ret = wc_InitRsaKey_ex(&rsa_key, HEAP_HINT, devId); + } + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(tmp, &idx, &rsa_key, (word32)bytes); + } + + printf(testingFmt, "wc_SigntureGetSize_rsa()"); + if (ret == 0) { + /* Input for signature type RSA */ + sig_type = WC_SIGNATURE_TYPE_RSA; + key_len = sizeof(RsaKey); + ret = wc_SignatureGetSize(sig_type, &rsa_key, key_len); + + /* Test bad args */ + if (ret > 0) { + sig_type = (enum wc_SignatureType) 100; + ret = wc_SignatureGetSize(sig_type, &rsa_key, key_len); + if (ret == BAD_FUNC_ARG) { + sig_type = WC_SIGNATURE_TYPE_RSA; + ret = wc_SignatureGetSize(sig_type, NULL, key_len); + } + #ifndef HAVE_USER_RSA + if (ret == BAD_FUNC_ARG) { + #else + if (ret == 0) { + #endif + key_len = (word32)0; + ret = wc_SignatureGetSize(sig_type, &rsa_key, key_len); + } + if (ret == BAD_FUNC_ARG) { + ret = SIG_TYPE_E; + } + } + } else { + ret = WOLFSSL_FATAL_ERROR; + } + wc_FreeRsaKey(&rsa_key); + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + #else + ret = SIG_TYPE_E; + #endif + + if (ret == SIG_TYPE_E) { + ret = 0; + }else { + ret = WOLFSSL_FATAL_ERROR; + } + + printf(resultFmt, ret == 0 ? passed : failed); + #endif /* NO_SIG_WRAPPER */ + return ret; +}/* END test_wc_SignatureGetSize_rsa(void) */ + +/*----------------------------------------------------------------------------* + | hash.h Tests + *----------------------------------------------------------------------------*/ + +static int test_wc_HashInit(void) +{ + int ret = 0, i; /* 0 indicates tests passed, 1 indicates failure */ + + wc_HashAlg hash; + + /* enum for holding supported algorithms, #ifndef's restrict if disabled */ + enum wc_HashType enumArray[] = { + #ifndef NO_MD5 + WC_HASH_TYPE_MD5, + #endif + #ifndef NO_SHA + WC_HASH_TYPE_SHA, + #endif + #ifndef WOLFSSL_SHA224 + WC_HASH_TYPE_SHA224, + #endif + #ifndef NO_SHA256 + WC_HASH_TYPE_SHA256, + #endif + #ifndef WOLFSSL_SHA384 + WC_HASH_TYPE_SHA384, + #endif + #ifndef WOLFSSL_SHA512 + WC_HASH_TYPE_SHA512, + #endif + }; + /* dynamically finds the length */ + int enumlen = (sizeof(enumArray)/sizeof(enum wc_HashType)); + + /* For loop to test various arguments... */ + for (i = 0; i < enumlen; i++) { + /* check for bad args */ + if (wc_HashInit(&hash, enumArray[i]) == BAD_FUNC_ARG) { + ret = 1; + break; + } + wc_HashFree(&hash, enumArray[i]); + + /* check for null ptr */ + if (wc_HashInit(NULL, enumArray[i]) != BAD_FUNC_ARG) { + ret = 1; + break; + } + + } /* end of for loop */ + + printf(testingFmt, "wc_HashInit()"); + if (ret==0) { /* all tests have passed */ + printf(resultFmt, passed); + } + else { /* a test has failed */ + printf(resultFmt, failed); + } + return ret; +} /* end of test_wc_HashInit */ + +/*----------------------------------------------------------------------------* + | Compatibility Tests + *----------------------------------------------------------------------------*/ + +static void test_wolfSSL_X509_NAME(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) \ + && !defined(NO_RSA) && defined(WOLFSSL_CERT_GEN) + X509* x509; + const unsigned char* c; + unsigned char buf[4096]; + int bytes; + XFILE f; + const X509_NAME* a; + const X509_NAME* b; + int sz; + unsigned char* tmp; + char file[] = "./certs/ca-cert.der"; + + printf(testingFmt, "wolfSSL_X509_NAME()"); + + /* test compile of deprecated function, returns 0 */ + AssertIntEQ(CRYPTO_thread_id(), 0); + + AssertNotNull(a = X509_NAME_new()); + X509_NAME_free((X509_NAME*)a); + + f = XFOPEN(file, "rb"); + AssertTrue(f != XBADFILE); + bytes = (int)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + c = buf; + AssertNotNull(x509 = wolfSSL_X509_load_certificate_buffer(c, bytes, + SSL_FILETYPE_ASN1)); + + /* test cmp function */ + AssertNotNull(a = X509_get_issuer_name(x509)); + AssertNotNull(b = X509_get_subject_name(x509)); + + AssertIntEQ(X509_NAME_cmp(a, b), 0); /* self signed should be 0 */ + + tmp = buf; + AssertIntGT((sz = i2d_X509_NAME((X509_NAME*)a, &tmp)), 0); + if (sz > 0 && tmp == buf) { + printf("\nERROR - %s line %d failed with:", __FILE__, __LINE__); \ + printf(" Expected pointer to be incremented\n"); + abort(); + } + + /* retry but with the function creating a buffer */ + tmp = NULL; + AssertIntGT((sz = i2d_X509_NAME((X509_NAME*)b, &tmp)), 0); + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + + + AssertNotNull(b = X509_NAME_dup((X509_NAME*)a)); + AssertIntEQ(X509_NAME_cmp(a, b), 0); + X509_NAME_free((X509_NAME*)b); + + X509_free(x509); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_DES3) */ +} + +static void test_wolfSSL_X509_INFO(void) +{ +#if defined(OPENSSL_ALL) + STACK_OF(X509_INFO) *info_stack; + X509_INFO *info; + BIO *cert; + int i; + + printf(testingFmt, "wolfSSL_X509_INFO"); + + AssertNotNull(cert = BIO_new_file(cliCertFileExt, "r")); + AssertNotNull(info_stack = PEM_X509_INFO_read_bio(cert, NULL, NULL, NULL)); + for (i = 0; i < sk_X509_INFO_num(info_stack); i++) { + AssertNotNull(info = sk_X509_INFO_value(info_stack, i)); + AssertNotNull(info->x509); + AssertNull(info->crl); + } + sk_X509_INFO_pop_free(info_stack, X509_INFO_free); + BIO_free(cert); + + AssertNotNull(cert = BIO_new_file(cliCertFileExt, "r")); + AssertNotNull(info_stack = PEM_X509_INFO_read_bio(cert, NULL, NULL, NULL)); + sk_X509_INFO_free(info_stack); + BIO_free(cert); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_subject_name_hash(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) \ + && !defined(NO_SHA) && !defined(NO_RSA) + + X509* x509; + X509_NAME* subjectName = NULL; + unsigned long ret = 0; + + printf(testingFmt, "wolfSSL_X509_subject_name_hash()"); + + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(cliCertFile, + SSL_FILETYPE_PEM)); + + AssertNotNull(subjectName = wolfSSL_X509_get_subject_name(x509)); + + ret = X509_subject_name_hash(x509); + + AssertIntNE(ret, WOLFSSL_FAILURE); + + X509_free(x509); + printf(resultFmt, passed); + +#endif +} + +static void test_wolfSSL_DES(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_DES3) + const_DES_cblock myDes; + DES_cblock iv; + DES_key_schedule key; + word32 i; + DES_LONG dl; + unsigned char msg[] = "hello wolfssl"; + + printf(testingFmt, "wolfSSL_DES()"); + + DES_check_key(1); + DES_set_key(&myDes, &key); + + /* check, check of odd parity */ + XMEMSET(myDes, 4, sizeof(const_DES_cblock)); myDes[0] = 6; /*set even parity*/ + XMEMSET(key, 5, sizeof(DES_key_schedule)); + AssertIntEQ(DES_set_key_checked(&myDes, &key), -1); + AssertIntNE(key[0], myDes[0]); /* should not have copied over key */ + + /* set odd parity for success case */ + DES_set_odd_parity(&myDes); + AssertIntEQ(DES_check_key_parity(&myDes), 1); + printf("%02x %02x %02x %02x", myDes[0], myDes[1], myDes[2], myDes[3]); + AssertIntEQ(DES_set_key_checked(&myDes, &key), 0); + for (i = 0; i < sizeof(DES_key_schedule); i++) { + AssertIntEQ(key[i], myDes[i]); + } + AssertIntEQ(DES_is_weak_key(&myDes), 0); + + /* check weak key */ + XMEMSET(myDes, 1, sizeof(const_DES_cblock)); + XMEMSET(key, 5, sizeof(DES_key_schedule)); + AssertIntEQ(DES_set_key_checked(&myDes, &key), -2); + AssertIntNE(key[0], myDes[0]); /* should not have copied over key */ + + /* now do unchecked copy of a weak key over */ + DES_set_key_unchecked(&myDes, &key); + /* compare arrays, should be the same */ + for (i = 0; i < sizeof(DES_key_schedule); i++) { + AssertIntEQ(key[i], myDes[i]); + } + AssertIntEQ(DES_is_weak_key(&myDes), 1); + + /* check DES_key_sched API */ + XMEMSET(key, 1, sizeof(DES_key_schedule)); + AssertIntEQ(DES_key_sched(&myDes, NULL), 0); + AssertIntEQ(DES_key_sched(NULL, &key), 0); + AssertIntEQ(DES_key_sched(&myDes, &key), 0); + /* compare arrays, should be the same */ + for (i = 0; i < sizeof(DES_key_schedule); i++) { + AssertIntEQ(key[i], myDes[i]); + } + + /* DES_cbc_cksum should return the last 4 of the last 8 bytes after + * DES_cbc_encrypt on the input */ + XMEMSET(iv, 0, sizeof(DES_cblock)); + XMEMSET(myDes, 5, sizeof(DES_key_schedule)); + AssertIntGT((dl = DES_cbc_cksum(msg, &key, sizeof(msg), &myDes, &iv)), 0); + AssertIntEQ(dl, 480052723); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_DES3) */ +} + +static void test_wc_PemToDer(void) +{ +#if !defined(NO_CERTS) && defined(WOLFSSL_PEM_TO_DER) + int ret; + DerBuffer* pDer = NULL; + const char* ca_cert = "./certs/server-cert.pem"; + byte* cert_buf = NULL; + size_t cert_sz = 0; + int eccKey = 0; + EncryptedInfo info; + + printf(testingFmt, "wc_PemToDer()"); + + XMEMSET(&info, 0, sizeof(info)); + + ret = load_file(ca_cert, &cert_buf, &cert_sz); + if (ret == 0) { + ret = wc_PemToDer(cert_buf, cert_sz, CERT_TYPE, + &pDer, NULL, &info, &eccKey); + AssertIntEQ(ret, 0); + + wc_FreeDer(&pDer); + } + + if (cert_buf) + free(cert_buf); + printf(resultFmt, passed); +#endif +} + +static void test_wc_AllocDer(void) +{ +#if !defined(NO_CERTS) + int ret; + DerBuffer* pDer = NULL; + word32 testSize = 1024; + + printf(testingFmt, "wc_AllocDer()"); + + ret = wc_AllocDer(&pDer, testSize, CERT_TYPE, HEAP_HINT); + AssertIntEQ(ret, 0); + AssertNotNull(pDer); + wc_FreeDer(&pDer); + printf(resultFmt, passed); +#endif +} + +static void test_wc_CertPemToDer(void) +{ +#if !defined(NO_CERTS) && defined(WOLFSSL_PEM_TO_DER) + int ret; + const char* ca_cert = "./certs/ca-cert.pem"; + byte* cert_buf = NULL; + size_t cert_sz = 0, cert_dersz = 0; + byte* cert_der = NULL; + + printf(testingFmt, "wc_CertPemToDer()"); + + ret = load_file(ca_cert, &cert_buf, &cert_sz); + if (ret == 0) { + cert_dersz = cert_sz; /* DER will be smaller than PEM */ + cert_der = (byte*)malloc(cert_dersz); + if (cert_der) { + ret = wc_CertPemToDer(cert_buf, (int)cert_sz, + cert_der, (int)cert_dersz, CERT_TYPE); + AssertIntGE(ret, 0); + } + } + + if (cert_der) + free(cert_der); + if (cert_buf) + free(cert_buf); +#endif +} + +static void test_wc_PubKeyPemToDer(void) +{ +#ifdef WOLFSSL_PEM_TO_DER +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER) + int ret; + const char* key = "./certs/ecc-client-keyPub.pem"; + byte* cert_buf = NULL; + size_t cert_sz = 0, cert_dersz = 0; + byte* cert_der = NULL; + + printf(testingFmt, "wc_PubKeyPemToDer()"); + + + ret = wc_PubKeyPemToDer(cert_buf, (int)cert_sz, + cert_der, (int)cert_dersz); + AssertIntGE(ret, BAD_FUNC_ARG); + + ret = load_file(key, &cert_buf, &cert_sz); + if (ret == 0) { + cert_dersz = cert_sz; /* DER will be smaller than PEM */ + cert_der = (byte*)malloc(cert_dersz); + if (cert_der) { + ret = wc_PubKeyPemToDer(cert_buf, (int)cert_sz, + cert_der, (int)cert_dersz); + AssertIntGE(ret, 0); + } + } + + if (cert_der) + free(cert_der); + if (cert_buf) + free(cert_buf); +#endif +#endif +} + +static void test_wc_PemPubKeyToDer(void) +{ +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER) + int ret; + const char* key = "./certs/ecc-client-keyPub.pem"; + size_t cert_dersz = 1024; + byte* cert_der = (byte*)malloc(cert_dersz); + + printf(testingFmt, "wc_PemPubKeyToDer()"); + + ret = wc_PemPubKeyToDer(NULL, cert_der, (int)cert_dersz); + AssertIntGE(ret, BAD_FUNC_ARG); + + if (cert_der) { + ret = wc_PemPubKeyToDer(key, cert_der, (int)cert_dersz); + AssertIntGE(ret, 0); + + free(cert_der); + } +#endif +} + + +static void test_wolfSSL_certs(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ + !defined(NO_RSA) + X509* x509; + WOLFSSL* ssl; + WOLFSSL_CTX* ctx; + STACK_OF(ASN1_OBJECT)* sk; + ASN1_BIT_STRING* bit_str; + int crit; + + printf(testingFmt, "wolfSSL_certs()"); + +#ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(SSLv23_server_method())); +#else + AssertNotNull(ctx = SSL_CTX_new(SSLv23_client_method())); +#endif + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + #ifndef HAVE_USER_RSA + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); + AssertIntEQ(SSL_CTX_check_private_key(ctx), SSL_FAILURE); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + AssertIntEQ(SSL_CTX_check_private_key(ctx), SSL_SUCCESS); + #endif + AssertNotNull(ssl = SSL_new(ctx)); + + AssertIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); + + #ifdef HAVE_PK_CALLBACKS + 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(cliCertFileExt, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + 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), 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), WOLFSSL_SUCCESS); + #endif + + #if !defined(NO_SHA) && !defined(NO_SHA256) + /************* Get Digest of Certificate ******************/ + { + byte digest[64]; /* max digest size */ + word32 digestSz; + + XMEMSET(digest, 0, sizeof(digest)); + AssertIntEQ(X509_digest(x509, wolfSSL_EVP_sha1(), digest, &digestSz), + WOLFSSL_SUCCESS); + AssertIntEQ(X509_digest(x509, wolfSSL_EVP_sha256(), digest, &digestSz), + WOLFSSL_SUCCESS); + + AssertIntEQ(X509_digest(NULL, wolfSSL_EVP_sha1(), digest, &digestSz), + 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, + &crit, NULL); + AssertNotNull(sk); + AssertIntEQ(crit, 0); + sk_ASN1_OBJECT_free(sk); + + bit_str = (ASN1_BIT_STRING*)X509_get_ext_d2i(x509, NID_key_usage, &crit, NULL); + AssertNotNull(bit_str); + AssertIntEQ(crit, 1); + AssertIntEQ(bit_str->type, NID_key_usage); + ASN1_BIT_STRING_free(bit_str); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_ext_key_usage, + &crit, NULL); + /* AssertNotNull(sk); no extension set */ + sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, + NID_authority_key_identifier, &crit, NULL); + AssertNotNull(sk); + sk_ASN1_OBJECT_free(sk); + + sk = (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); + sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(x509, NID_subject_alt_name, + &crit, NULL); + /* AssertNotNull(sk); no alt names set */ + sk_GENERAL_NAME_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_issuer_alt_name, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_info_access, &crit, + NULL); + /* AssertNotNull(sk); no auth info set */ + sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_sinfo_access, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_name_constraints, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, + NID_certificate_policies, &crit, NULL); + #if !defined(WOLFSSL_SEP) && !defined(WOLFSSL_CERT_EXT) + AssertNull(sk); + #else + /* AssertNotNull(sk); no cert policy set */ + #endif + sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_policy_mappings, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_policy_constraints, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_inhibit_any_policy, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_tlsfeature, &crit, + NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + sk_ASN1_OBJECT_free(sk); + + /* test invalid cases */ + crit = 0; + sk = (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, + NULL, NULL); + AssertNull(sk); + + AssertIntEQ(SSL_get_hit(ssl), 0); + X509_free(x509); + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && !NO_CERTS */ +} + + +static void test_wolfSSL_ASN1_TIME_print(void) +{ + #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, "Apr 13 15:23:09 2018 GMT", sizeof(buf) - 1), 0); + + /* create a bad time and test results */ + AssertNotNull(t = X509_get_notAfter(x509)); + AssertIntEQ(ASN1_TIME_check(t), WOLFSSL_SUCCESS); + t->data[8] = 0; + t->data[3] = 0; + AssertIntNE(ASN1_TIME_print(bio, t), 1); + AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 14); + AssertIntEQ(XMEMCMP(buf, "Bad time value", 14), 0); + AssertIntEQ(ASN1_TIME_check(t), WOLFSSL_FAILURE); + + BIO_free(bio); + X509_free(x509); + + printf(resultFmt, passed); + #endif +} + +static void test_wolfSSL_ASN1_UTCTIME_print(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) + BIO* bio; + ASN1_UTCTIME* utc = NULL; + unsigned char buf[25]; + const char* validDate = "190424111501Z"; /* UTC = YYMMDDHHMMSSZ */ + const char* invalidDate = "190424111501X"; /* UTC = YYMMDDHHMMSSZ */ + + printf(testingFmt, "ASN1_UTCTIME_print()"); + + /* NULL parameter check */ + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertIntEQ(ASN1_UTCTIME_print(bio, utc), 0); + BIO_free(bio); + + /* Valid date */ + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertNotNull(utc = (ASN1_UTCTIME*)XMALLOC(sizeof(ASN1_UTCTIME), NULL, + DYNAMIC_TYPE_ASN1)); + utc->type = ASN_UTC_TIME; + utc->length = ASN_UTC_TIME_SIZE; + XMEMCPY(utc->data, (byte*)validDate, ASN_UTC_TIME_SIZE); + AssertIntEQ(ASN1_UTCTIME_print(bio, utc), 1); + AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 24); + AssertIntEQ(XMEMCMP(buf, "Apr 24 11:15:01 2019 GMT", sizeof(buf)-1), 0); + + XMEMSET(buf, 0, sizeof(buf)); + BIO_free(bio); + + /* Invalid format */ + AssertNotNull(bio = BIO_new(BIO_s_mem())); + utc->type = ASN_UTC_TIME; + utc->length = ASN_UTC_TIME_SIZE; + XMEMCPY(utc->data, (byte*)invalidDate, ASN_UTC_TIME_SIZE); + AssertIntEQ(ASN1_UTCTIME_print(bio, utc), 0); + AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 14); + AssertIntEQ(XMEMCMP(buf, "Bad time value", 14), 0); + + XFREE(utc, NULL, DYNAMIC_TYPE_ASN1); + BIO_free(bio); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && !NO_ASN_TIME */ +} + + +static void test_wolfSSL_ASN1_GENERALIZEDTIME_free(void) +{ + #if defined(OPENSSL_EXTRA) + WOLFSSL_ASN1_GENERALIZEDTIME* asn1_gtime; + unsigned char nullstr[32]; + + XMEMSET(nullstr, 0, 32); + asn1_gtime = (WOLFSSL_ASN1_GENERALIZEDTIME*)XMALLOC( + sizeof(WOLFSSL_ASN1_GENERALIZEDTIME), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (asn1_gtime) { + XMEMCPY(asn1_gtime->data,"20180504123500Z",ASN_GENERALIZED_TIME_SIZE); + + wolfSSL_ASN1_GENERALIZEDTIME_free(asn1_gtime); + AssertIntEQ(0, XMEMCMP(asn1_gtime->data, nullstr, 32)); + + XFREE(asn1_gtime, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + #endif /* OPENSSL_EXTRA */ +} + + +static void test_wolfSSL_private_keys(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) + WOLFSSL* ssl; + WOLFSSL_CTX* ctx; + EVP_PKEY* pkey = NULL; + + printf(testingFmt, "wolfSSL_private_keys()"); + + OpenSSL_add_all_digests(); + OpenSSL_add_all_algorithms(); + +#ifndef NO_RSA + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); + #endif + 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), WOLFSSL_SUCCESS); + +#ifdef USE_CERT_BUFFERS_2048 + { + const unsigned char* server_key = (const unsigned char*)server_key_der_2048; + unsigned char buf[FOURK_BUF]; + word32 bufSz; + + AssertIntEQ(SSL_use_RSAPrivateKey_ASN1(ssl, + (unsigned char*)client_key_der_2048, + sizeof_client_key_der_2048), WOLFSSL_SUCCESS); +#ifndef HAVE_USER_RSA + /* Should mismatch now that a different private key loaded */ + 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), WOLFSSL_SUCCESS); + /* After loading back in DER format of original key, should match */ + AssertIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); + + /* test loading private key to the WOLFSSL_CTX */ + AssertIntEQ(SSL_CTX_use_PrivateKey_ASN1(0, ctx, + (unsigned char*)client_key_der_2048, + sizeof_client_key_der_2048), WOLFSSL_SUCCESS); +#ifndef NO_CHECK_PRIVATE_KEY +#ifndef HAVE_USER_RSA + /* Should mismatch now that a different private key loaded */ + AssertIntNE(wolfSSL_CTX_check_private_key(ctx), WOLFSSL_SUCCESS); +#endif + + AssertIntEQ(SSL_CTX_use_PrivateKey_ASN1(0, ctx, + (unsigned char*)server_key, + sizeof_server_key_der_2048), WOLFSSL_SUCCESS); + /* After loading back in DER format of original key, should match */ + AssertIntEQ(wolfSSL_CTX_check_private_key(ctx), WOLFSSL_SUCCESS); +#endif /* !NO_CHECK_PRIVATE_KEY */ + + /* pkey not set yet, expecting to fail */ + 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), WOLFSSL_SUCCESS); + + /* reuse PKEY structure and test + * this should be checked with a memory management sanity checker */ + AssertFalse(server_key == (const unsigned char*)server_key_der_2048); + server_key = (const unsigned char*)server_key_der_2048; + AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, + &server_key, (long)sizeof_server_key_der_2048)); + AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), WOLFSSL_SUCCESS); + + /* check striping PKCS8 header with wolfSSL_d2i_PrivateKey */ + bufSz = FOURK_BUF; + AssertIntGT((bufSz = wc_CreatePKCS8Key(buf, &bufSz, + (byte*)server_key_der_2048, sizeof_server_key_der_2048, + RSAk, NULL, 0)), 0); + server_key = (const unsigned char*)buf; + AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &server_key, + (long)bufSz)); + } +#endif + + + EVP_PKEY_free(pkey); + SSL_free(ssl); /* frees x509 also since loaded into ssl */ + SSL_CTX_free(ctx); +#endif /* end of RSA private key match tests */ + + +#ifdef HAVE_ECC + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); + #endif + AssertTrue(SSL_CTX_use_certificate_file(ctx, eccCertFile, + WOLFSSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, eccKeyFile, + WOLFSSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + AssertIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); + SSL_free(ssl); + + + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, cliEccKeyFile, + WOLFSSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + AssertIntNE(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); + + SSL_free(ssl); + SSL_CTX_free(ctx); +#endif /* end of ECC private key match tests */ + +#ifdef HAVE_ED25519 + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); + #endif + AssertTrue(SSL_CTX_use_certificate_file(ctx, edCertFile, + WOLFSSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, edKeyFile, + WOLFSSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + AssertIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); + SSL_free(ssl); + + + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, cliEdKeyFile, + WOLFSSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + AssertIntNE(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); + + SSL_free(ssl); + SSL_CTX_free(ctx); +#endif /* end of Ed25519 private key match tests */ + +#ifdef HAVE_ED448 + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); + #endif + AssertTrue(SSL_CTX_use_certificate_file(ctx, ed448CertFile, + WOLFSSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, ed448KeyFile, + WOLFSSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + AssertIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); + SSL_free(ssl); + + + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, cliEd448KeyFile, + WOLFSSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + AssertIntNE(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); + + SSL_free(ssl); + SSL_CTX_free(ctx); +#endif /* end of Ed448 private key match tests */ + + EVP_cleanup(); + + /* test existence of no-op macros in wolfssl/openssl/ssl.h */ + CONF_modules_free(); + ENGINE_cleanup(); + CONF_modules_unload(); + + (void)ssl; + (void)ctx; + (void)pkey; + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ +} + + +static void test_wolfSSL_PEM_PrivateKey(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + (!defined(NO_RSA) || defined(HAVE_ECC)) && defined(USE_CERT_BUFFERS_2048) + + BIO* bio = NULL; + EVP_PKEY* pkey = NULL; + const unsigned char* server_key = (const unsigned char*)server_key_der_2048; + + /* test creating new EVP_PKEY with bad arg */ + AssertNull((pkey = PEM_read_bio_PrivateKey(NULL, NULL, NULL, NULL))); + + /* test loading RSA key using BIO */ +#if !defined(NO_RSA) && !defined(NO_FILESYSTEM) + { + XFILE file; + const char* fname = "./certs/server-key.pem"; + size_t sz; + byte* buf; + + file = XFOPEN(fname, "rb"); + AssertTrue((file != XBADFILE)); + AssertTrue(XFSEEK(file, 0, XSEEK_END) == 0); + sz = XFTELL(file); + XREWIND(file); + AssertNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); + if (buf) { + AssertIntEQ(XFREAD(buf, 1, sz, file), sz); + } + XFCLOSE(file); + + /* Test using BIO new mem and loading PEM private key */ + AssertNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + AssertNotNull((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); + XFREE(buf, NULL, DYNAMIC_TYPE_FILE); + BIO_free(bio); + bio = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + } +#endif + + /* test loading ECC key using BIO */ +#if defined(HAVE_ECC) && !defined(NO_FILESYSTEM) + { + XFILE file; + const char* fname = "./certs/ecc-key.pem"; + size_t sz; + byte* buf; + + file = XFOPEN(fname, "rb"); + AssertTrue((file != XBADFILE)); + AssertTrue(XFSEEK(file, 0, XSEEK_END) == 0); + sz = XFTELL(file); + XREWIND(file); + AssertNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); + if (buf) + AssertIntEQ(XFREAD(buf, 1, sz, file), sz); + XFCLOSE(file); + + /* Test using BIO new mem and loading PEM private key */ + AssertNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + AssertNotNull((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); + XFREE(buf, NULL, DYNAMIC_TYPE_FILE); + BIO_free(bio); + bio = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + } +#endif + +#if !defined(NO_RSA) && (defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)) + { + #define BIO_PEM_TEST_CHAR 'a' + EVP_PKEY* pkey2 = NULL; + unsigned char extra[10]; + int i; + + printf(testingFmt, "wolfSSL_PEM_PrivateKey()"); + + XMEMSET(extra, BIO_PEM_TEST_CHAR, sizeof(extra)); + + AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + AssertIntEQ(BIO_set_write_buf_size(bio, 4096), SSL_FAILURE); + + AssertNull(d2i_PrivateKey(EVP_PKEY_EC, &pkey, + &server_key, (long)sizeof_server_key_der_2048)); + AssertNull(pkey); + + 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), + WOLFSSL_SUCCESS); + + /* test creating new EVP_PKEY with good args */ + AssertNotNull((pkey2 = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); + if (pkey && pkey->pkey.ptr && pkey2 && pkey2->pkey.ptr) + AssertIntEQ((int)XMEMCMP(pkey->pkey.ptr, pkey2->pkey.ptr, pkey->pkey_sz), 0); + + /* test of reuse of EVP_PKEY */ + AssertNull(PEM_read_bio_PrivateKey(bio, &pkey, NULL, NULL)); + AssertIntEQ(BIO_pending(bio), 0); + AssertIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), + SSL_SUCCESS); + AssertIntEQ(BIO_write(bio, extra, 10), 10); /* add 10 extra bytes after PEM */ + AssertNotNull(PEM_read_bio_PrivateKey(bio, &pkey, NULL, NULL)); + AssertNotNull(pkey); + if (pkey && pkey->pkey.ptr && pkey2 && pkey2->pkey.ptr) { + AssertIntEQ((int)XMEMCMP(pkey->pkey.ptr, pkey2->pkey.ptr, pkey->pkey_sz),0); + } + AssertIntEQ(BIO_pending(bio), 10); /* check 10 extra bytes still there */ + AssertIntEQ(BIO_read(bio, extra, 10), 10); + for (i = 0; i < 10; i++) { + AssertIntEQ(extra[i], BIO_PEM_TEST_CHAR); + } + + BIO_free(bio); + bio = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + EVP_PKEY_free(pkey2); + } + #endif + + /* key is DES encrypted */ + #if !defined(NO_DES3) && defined(WOLFSSL_ENCRYPTED_KEYS) && \ + !defined(NO_RSA) && !defined(NO_FILESYSTEM) && !defined(NO_MD5) + { + XFILE f; + pem_password_cb* passwd_cb; + void* passwd_cb_userdata; + SSL_CTX* ctx; + char passwd[] = "bad password"; + + #ifndef WOLFSSL_NO_TLS12 + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(TLSv1_2_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(TLSv1_2_client_method())); + #endif + #else + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfTLSv1_3_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(wolfTLSv1_3_client_method())); + #endif + #endif + + AssertNotNull(bio = BIO_new_file("./certs/server-keyEnc.pem", "rb")); + SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); + AssertNotNull(passwd_cb = SSL_CTX_get_default_passwd_cb(ctx)); + AssertNull(passwd_cb_userdata = + SSL_CTX_get_default_passwd_cb_userdata(ctx)); + + /* fail case with password call back */ + AssertNull(pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, + (void*)passwd)); + BIO_free(bio); + AssertNotNull(bio = BIO_new_file("./certs/server-keyEnc.pem", "rb")); + AssertNull(pkey = PEM_read_bio_PrivateKey(bio, NULL, passwd_cb, + (void*)passwd)); + BIO_free(bio); + + f = XFOPEN("./certs/server-keyEnc.pem", "rb"); + AssertNotNull(bio = BIO_new_fp(f, BIO_CLOSE)); + + /* use callback that works */ + AssertNotNull(pkey = PEM_read_bio_PrivateKey(bio, NULL, passwd_cb, + (void*)"yassl123")); + + AssertIntEQ(SSL_CTX_use_PrivateKey(ctx, pkey), SSL_SUCCESS); + + EVP_PKEY_free(pkey); + pkey = NULL; + BIO_free(bio); + bio = NULL; + SSL_CTX_free(ctx); + } + #endif /* !defined(NO_DES3) */ + + #if defined(HAVE_ECC) && !defined(NO_FILESYSTEM) + { + unsigned char buf[2048]; + size_t bytes; + XFILE f; + SSL_CTX* ctx; + + #ifndef WOLFSSL_NO_TLS12 + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(TLSv1_2_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(TLSv1_2_client_method())); + #endif + #else + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfTLSv1_3_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(wolfTLSv1_3_client_method())); + #endif + #endif + + f = XFOPEN("./certs/ecc-key.der", "rb"); + AssertTrue((f != XBADFILE)); + bytes = (size_t)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + server_key = buf; + pkey = NULL; + AssertNull(d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &server_key, bytes)); + AssertNull(pkey); + AssertNotNull(d2i_PrivateKey(EVP_PKEY_EC, &pkey, &server_key, bytes)); + AssertIntEQ(SSL_CTX_use_PrivateKey(ctx, pkey), SSL_SUCCESS); + + EVP_PKEY_free(pkey); + pkey = NULL; + SSL_CTX_free(ctx); + } + #endif + + printf(resultFmt, passed); + + (void)bio; + (void)pkey; + (void)server_key; + +#endif /* OPENSSL_EXTRA && !NO_CERTS && !NO_RSA && USE_CERT_BUFFERS_2048 */ +} + +static void test_wolfSSL_PEM_bio_RSAKey(void) +{ +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && \ + defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && \ + !defined(HAVE_USER_RSA) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) + RSA* rsa = NULL; + BIO* bio = NULL; + + printf(testingFmt, "wolfSSL_PEM_bio_RSAKey"); + + /* PrivateKey */ + AssertNotNull(bio = BIO_new_file(svrKeyFile, "rb")); + AssertNull((rsa = PEM_read_bio_RSAPrivateKey(NULL, NULL, NULL, NULL))); + AssertNotNull((rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL))); + AssertIntEQ(RSA_size(rsa), 256); + AssertIntEQ(PEM_write_bio_RSAPrivateKey(NULL, NULL, NULL, NULL, 0, NULL, \ + NULL), WOLFSSL_FAILURE); + BIO_free(bio); + AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + AssertIntEQ(PEM_write_bio_RSAPrivateKey(bio, rsa, NULL, NULL, 0, NULL, \ + NULL), WOLFSSL_SUCCESS); + BIO_free(bio); + RSA_free(rsa); + + /* PUBKEY */ + AssertNotNull(bio = BIO_new_file("./certs/rsa-pub-2048.pem", "rb")); + AssertNull((rsa = PEM_read_bio_RSA_PUBKEY(NULL, NULL, NULL, NULL))); + AssertNotNull((rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL))); + AssertIntEQ(RSA_size(rsa), 256); + AssertIntEQ(PEM_write_bio_RSA_PUBKEY(NULL, NULL), WOLFSSL_FAILURE); + BIO_free(bio); + AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + AssertIntEQ(PEM_write_bio_RSA_PUBKEY(bio, rsa), WOLFSSL_SUCCESS); + BIO_free(bio); + RSA_free(rsa); + + #ifdef HAVE_ECC + /* ensure that non-rsa keys do not work */ + AssertNotNull(bio = BIO_new_file(eccKeyFile, "rb")); /* ecc key */ + AssertNull((rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL))); + AssertNull((rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL))); + BIO_free(bio); + RSA_free(rsa); + #endif /* HAVE_ECC */ + + printf(resultFmt, passed); +#endif /* defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && \ + (defined(WOLFSSL_KEY_GEN) || WOLFSSL_CERT_GEN) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) && !defined(NO_CERTS) */ +} + +static void test_wolfSSL_PEM_RSAPrivateKey(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + RSA* rsa = NULL; + RSA* rsa_dup = NULL; + BIO* bio = NULL; + + printf(testingFmt, "wolfSSL_PEM_RSAPrivateKey()"); + + AssertNotNull(bio = BIO_new_file(svrKeyFile, "rb")); + AssertNotNull((rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL))); + AssertIntEQ(RSA_size(rsa), 256); + +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) + AssertNotNull(rsa_dup = RSAPublicKey_dup(rsa)); + AssertPtrNE(rsa_dup, rsa); +#endif + + /* test if valgrind complains about unreleased memory */ + RSA_up_ref(rsa); + RSA_free(rsa); + + BIO_free(bio); + RSA_free(rsa); + RSA_free(rsa_dup); + +#ifdef HAVE_ECC + AssertNotNull(bio = BIO_new_file(eccKeyFile, "rb")); + AssertNull((rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL))); + + BIO_free(bio); +#endif /* HAVE_ECC */ + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ +} + +static void test_wolfSSL_PEM_bio_DSAKey(void) +{ +#ifndef HAVE_SELFTEST +#if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) && !defined(NO_CERTS) && \ + defined(WOLFSSL_KEY_GEN) && !defined(NO_FILESYSTEM) && !defined(NO_DSA) + DSA* dsa = NULL; + BIO* bio = NULL; + + printf(testingFmt, "wolfSSL_PEM_bio_DSAKey"); + + /* PrivateKey */ + AssertNotNull(bio = BIO_new_file("./certs/1024/dsa1024.pem", "rb")); + AssertNull((dsa = PEM_read_bio_DSAPrivateKey(NULL, NULL, NULL, NULL))); + AssertNotNull((dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, NULL))); + AssertIntEQ(BN_num_bytes(dsa->g), 128); + AssertIntEQ(PEM_write_bio_DSAPrivateKey(NULL, NULL, NULL, NULL, 0, NULL, NULL), + WOLFSSL_FAILURE); + BIO_free(bio); + AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + AssertIntEQ(PEM_write_bio_DSAPrivateKey(bio, dsa, NULL, NULL, 0, NULL, NULL), + WOLFSSL_SUCCESS); + BIO_free(bio); + DSA_free(dsa); + + /* PUBKEY */ + AssertNotNull(bio = BIO_new_file("./certs/1024/dsa-pub-1024.pem", "rb")); + AssertNull((dsa = PEM_read_bio_DSA_PUBKEY(NULL, NULL, NULL, NULL))); + AssertNotNull((dsa = PEM_read_bio_DSA_PUBKEY(bio, NULL, NULL, NULL))); + AssertIntEQ(BN_num_bytes(dsa->g), 128); + AssertIntEQ(PEM_write_bio_DSA_PUBKEY(NULL, NULL), WOLFSSL_FAILURE); + BIO_free(bio); + AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + AssertIntEQ(PEM_write_bio_DSA_PUBKEY(bio, dsa), WOLFSSL_SUCCESS); + BIO_free(bio); + DSA_free(dsa); + + #ifdef HAVE_ECC + /* ensure that non-dsa keys do not work */ + AssertNotNull(bio = BIO_new_file(eccKeyFile, "rb")); /* ecc key */ + AssertNull((dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, NULL))); + AssertNull((dsa = PEM_read_bio_DSA_PUBKEY(bio, NULL, NULL, NULL))); + BIO_free(bio); + DSA_free(dsa); + #endif /* HAVE_ECC */ + + printf(resultFmt, passed); +#endif /* defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) && \ + !defined(NO_CERTS) && defined(WOLFSSL_KEY_GEN) && \ + !defined(NO_FILESYSTEM) && !defined(NO_DSA) */ +#endif /* HAVE_SELFTEST */ +} + +static void test_wolfSSL_PEM_bio_ECKey(void) +{ +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && \ + defined(WOLFSSL_KEY_GEN) && !defined(NO_FILESYSTEM) && defined(HAVE_ECC) + EC_KEY* ec = NULL; + BIO* bio = NULL; + + printf(testingFmt, "wolfSSL_PEM_bio_ECKey"); + + /* PrivateKey */ + AssertNotNull(bio = BIO_new_file("./certs/ecc-key.pem", "rb")); + AssertNull((ec = PEM_read_bio_ECPrivateKey(NULL, NULL, NULL, NULL))); + AssertNotNull((ec = PEM_read_bio_ECPrivateKey(bio, NULL, NULL, NULL))); + AssertIntEQ(wc_ecc_size((ecc_key*)ec->internal), 32); + AssertIntEQ(PEM_write_bio_ECPrivateKey(NULL, NULL, NULL, NULL, 0, NULL, \ + NULL),WOLFSSL_FAILURE); + BIO_free(bio); + AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + AssertIntEQ(PEM_write_bio_ECPrivateKey(bio, ec, NULL, NULL, 0, NULL, \ + NULL), WOLFSSL_SUCCESS); + BIO_free(bio); + EC_KEY_free(ec); + + /* PUBKEY */ + AssertNotNull(bio = BIO_new_file("./certs/ecc-client-keyPub.pem", "rb")); + AssertNull((ec = PEM_read_bio_EC_PUBKEY(NULL, NULL, NULL, NULL))); + AssertNotNull((ec = PEM_read_bio_EC_PUBKEY(bio, NULL, NULL, NULL))); + AssertIntEQ(wc_ecc_size((ecc_key*)ec->internal), 32); + AssertIntEQ(PEM_write_bio_EC_PUBKEY(NULL, NULL), WOLFSSL_FAILURE); + BIO_free(bio); + AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + AssertIntEQ(PEM_write_bio_EC_PUBKEY(bio, ec), WOLFSSL_SUCCESS); + BIO_free(bio); + EC_KEY_free(ec); + + #ifndef NO_RSA + /* ensure that non-ec keys do not work */ + AssertNotNull(bio = BIO_new_file(svrKeyFile, "rb")); /* rsa key */ + AssertNull((ec = PEM_read_bio_ECPrivateKey(bio, NULL, NULL, NULL))); + AssertNull((ec = PEM_read_bio_EC_PUBKEY(bio, NULL, NULL, NULL))); + BIO_free(bio); + EC_KEY_free(ec); + #endif /* HAVE_ECC */ + + printf(resultFmt, passed); +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ +} + +static void test_wolfSSL_PEM_PUBKEY(void) +{ +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) + BIO* bio = NULL; + EVP_PKEY* pkey = NULL; + + /* test creating new EVP_PKEY with bad arg */ + AssertNull((pkey = PEM_read_bio_PUBKEY(NULL, NULL, NULL, NULL))); + + /* test loading ECC key using BIO */ +#if defined(HAVE_ECC) && !defined(NO_FILESYSTEM) + { + XFILE file; + const char* fname = "./certs/ecc-client-keyPub.pem"; + size_t sz; + byte* buf; + + file = XFOPEN(fname, "rb"); + AssertTrue((file != XBADFILE)); + XFSEEK(file, 0, XSEEK_END); + sz = XFTELL(file); + XREWIND(file); + AssertNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); + if (buf) + AssertIntEQ(XFREAD(buf, 1, sz, file), sz); + XFCLOSE(file); + + /* Test using BIO new mem and loading PEM private key */ + AssertNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + AssertNotNull((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL))); + XFREE(buf, NULL, DYNAMIC_TYPE_FILE); + BIO_free(bio); + bio = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + } +#endif + + (void)bio; + (void)pkey; +#endif +} + +static void test_DSA_do_sign_verify(void) +{ +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && \ + !defined(NO_DSA) + unsigned char digest[WC_SHA_DIGEST_SIZE]; + DSA_SIG* sig; + DSA* dsa; + word32 bytes; + byte sigBin[DSA_SIG_SIZE]; + int dsacheck; + +#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)); + XFILE fp = XFOPEN("./certs/dsa2048.der", "rb"); + if (fp == XBADFILE) { + return WOLFSSL_BAD_FILE; + } + bytes = (word32) XFREAD(tmp, 1, sizeof(tmp), fp); + XFCLOSE(fp); +#endif /* END USE_CERT_BUFFERS_1024 */ + + printf(testingFmt, "DSA_do_sign_verify()"); + XMEMSET(digest, 202, sizeof(digest)); + + AssertNotNull(dsa = DSA_new()); + AssertIntEQ(DSA_LoadDer(dsa, tmp, bytes), 1); + + AssertIntEQ(wolfSSL_DSA_do_sign(digest, sigBin, dsa), 1); + AssertIntEQ(wolfSSL_DSA_do_verify(digest, sigBin, dsa, &dsacheck), 1); + + AssertNotNull(sig = DSA_do_sign(digest, WC_SHA_DIGEST_SIZE, dsa)); + AssertIntEQ(DSA_do_verify(digest, WC_SHA_DIGEST_SIZE, sig, dsa), 1); + + DSA_SIG_free(sig); + DSA_free(dsa); +#endif +#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ +} + +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_DH) + byte buffer[5300]; + char file[] = "./certs/dsaparams.pem"; + XFILE f; + int bytes; + DSA* dsa; + DH* dh; + BIO* bio; + SSL* ssl; + SSL_CTX* ctx; + + printf(testingFmt, "wolfSSL_tmp_dh()"); + + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); + #endif + 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 = XFOPEN(file, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buffer, 1, sizeof(buffer), f); + XFCLOSE(f); + + bio = BIO_new_mem_buf((void*)buffer, bytes); + AssertNotNull(bio); + + dsa = wolfSSL_PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); + AssertNotNull(dsa); + + dh = wolfSSL_DSA_dup_DH(dsa); + AssertNotNull(dh); + + AssertIntEQ((int)SSL_CTX_set_tmp_dh(ctx, dh), WOLFSSL_SUCCESS); + #ifndef NO_WOLFSSL_SERVER + AssertIntEQ((int)SSL_set_tmp_dh(ssl, dh), WOLFSSL_SUCCESS); + #else + AssertIntEQ((int)SSL_set_tmp_dh(ssl, dh), SIDE_ERROR); + #endif + + BIO_free(bio); + DSA_free(dsa); + DH_free(dh); + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_ctrl(void) +{ +#if defined (OPENSSL_EXTRA) + byte buff[5300]; + BIO* bio; + int bytes; + BUF_MEM* ptr = NULL; + + printf(testingFmt, "wolfSSL_crtl()"); + + bytes = sizeof(buff); + bio = BIO_new_mem_buf((void*)buff, bytes); + AssertNotNull(bio); + AssertNotNull(BIO_s_socket()); + + AssertIntEQ((int)wolfSSL_BIO_get_mem_ptr(bio, &ptr), WOLFSSL_SUCCESS); + + /* needs tested after stubs filled out @TODO + SSL_ctrl + SSL_CTX_ctrl + */ + + BIO_free(bio); + printf(resultFmt, passed); +#endif /* defined(OPENSSL_EXTRA) */ +} + + +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)); + if (key) { + 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); + if (checkPw) { + 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)); + if (key) { + 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)); + if (key) { + 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_Digest(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_SHA256) + + + const char* in = "abc"; + int inLen = (int)XSTRLEN(in); + byte out[WC_SHA256_DIGEST_SIZE]; + unsigned int outLen; + const char* expOut = "\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"; + printf(testingFmt, "wolfSSL_EVP_Digest()"); + + AssertIntEQ(wolfSSL_EVP_Digest((unsigned char*)in, inLen, out, &outLen, "SHA256", NULL), 1); + AssertIntEQ(outLen, WC_SHA256_DIGEST_SIZE); + AssertIntEQ(XMEMCMP(out, expOut, WC_SHA256_DIGEST_SIZE), 0); + + printf(resultFmt, passed); + +#endif /* OPEN_EXTRA && ! NO_SHA256 */ +} + +static void test_wolfSSL_EVP_MD_size(void) +{ +#ifdef OPENSSL_EXTRA + + WOLFSSL_EVP_MD_CTX mdCtx; + + printf(testingFmt, "wolfSSL_EVP_MD_size()"); + +#ifndef NO_SHA256 + wolfSSL_EVP_MD_CTX_init(&mdCtx); + + AssertIntEQ(wolfSSL_EVP_DigestInit(&mdCtx, "SHA256"), 1); + AssertIntEQ(wolfSSL_EVP_MD_size(wolfSSL_EVP_MD_CTX_md(&mdCtx)), WC_SHA256_DIGEST_SIZE); + AssertIntEQ(wolfSSL_EVP_MD_CTX_block_size(&mdCtx), WC_SHA256_BLOCK_SIZE); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + +#endif + +#ifndef NO_MD5 + wolfSSL_EVP_MD_CTX_init(&mdCtx); + + AssertIntEQ(wolfSSL_EVP_DigestInit(&mdCtx, "MD5"), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_size(&mdCtx), WC_MD5_DIGEST_SIZE); + AssertIntEQ(wolfSSL_EVP_MD_CTX_block_size(&mdCtx), WC_MD5_BLOCK_SIZE); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + +#endif + +#ifdef WOLFSSL_SHA224 + wolfSSL_EVP_MD_CTX_init(&mdCtx); + + AssertIntEQ(wolfSSL_EVP_DigestInit(&mdCtx, "SHA224"), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_size(&mdCtx), WC_SHA224_DIGEST_SIZE); + AssertIntEQ(wolfSSL_EVP_MD_CTX_block_size(&mdCtx), WC_SHA224_BLOCK_SIZE); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + +#endif + +#ifdef WOLFSSL_SHA384 + wolfSSL_EVP_MD_CTX_init(&mdCtx); + + AssertIntEQ(wolfSSL_EVP_DigestInit(&mdCtx, "SHA384"), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_size(&mdCtx), WC_SHA384_DIGEST_SIZE); + AssertIntEQ(wolfSSL_EVP_MD_CTX_block_size(&mdCtx), WC_SHA384_BLOCK_SIZE); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + +#endif + +#ifdef WOLFSSL_SHA512 + wolfSSL_EVP_MD_CTX_init(&mdCtx); + + AssertIntEQ(wolfSSL_EVP_DigestInit(&mdCtx, "SHA512"), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_size(&mdCtx), WC_SHA512_DIGEST_SIZE); + AssertIntEQ(wolfSSL_EVP_MD_CTX_block_size(&mdCtx), WC_SHA512_BLOCK_SIZE); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + +#endif + +#ifndef NO_SHA + wolfSSL_EVP_MD_CTX_init(&mdCtx); + + AssertIntEQ(wolfSSL_EVP_DigestInit(&mdCtx, "SHA"), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_size(&mdCtx), WC_SHA_DIGEST_SIZE); + AssertIntEQ(wolfSSL_EVP_MD_CTX_block_size(&mdCtx), WC_SHA_BLOCK_SIZE); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + +#endif + /* error case */ + wolfSSL_EVP_MD_CTX_init(&mdCtx); + + AssertIntEQ(wolfSSL_EVP_DigestInit(&mdCtx, ""), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_EVP_MD_size(wolfSSL_EVP_MD_CTX_md(&mdCtx)), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_EVP_MD_CTX_block_size(&mdCtx), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 0); + + 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); + + AssertIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, key), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData, + (unsigned int)XSTRLEN(testData)), + 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, testResult, checkSz), 1); + + 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); + AssertIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, key), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData, 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData + 4, + (unsigned int)XSTRLEN(testData) - 4), + 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, testResult, checkSz), 1); + + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_PKEY_free(key); + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} + + +static void test_wolfSSL_EVP_MD_rsa_signing(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) && \ + defined(USE_CERT_BUFFERS_2048) + WOLFSSL_EVP_PKEY* privKey; + WOLFSSL_EVP_PKEY* pubKey; + const char testData[] = "Hi There"; + WOLFSSL_EVP_MD_CTX mdCtx; + size_t checkSz = -1; + int sz = 2048 / 8; + const unsigned char* cp; + const unsigned char* p; + unsigned char check[2048/8]; + + printf(testingFmt, "wolfSSL_EVP_MD_rsa_signing()"); + + cp = client_key_der_2048; + AssertNotNull((privKey = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, &cp, + sizeof_client_key_der_2048))); + p = client_keypub_der_2048; + AssertNotNull((pubKey = wolfSSL_d2i_PUBKEY(NULL, &p, + sizeof_client_keypub_der_2048))); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, privKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData, + (unsigned int)XSTRLEN(testData)), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + AssertIntEQ((int)checkSz, sz); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ((int)checkSz,sz); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pubKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData, + (unsigned int)XSTRLEN(testData)), + 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, check, checkSz), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, privKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData, 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + AssertIntEQ((int)checkSz, sz); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ((int)checkSz, sz); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData + 4, + (unsigned int)XSTRLEN(testData) - 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ((int)checkSz, sz); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pubKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData, 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData + 4, + (unsigned int)XSTRLEN(testData) - 4), + 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, check, checkSz), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_PKEY_free(pubKey); + wolfSSL_EVP_PKEY_free(privKey); + + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_EVP_MD_ecc_signing(void) +{ +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + WOLFSSL_EVP_PKEY* privKey; + WOLFSSL_EVP_PKEY* pubKey; + const char testData[] = "Hi There"; + WOLFSSL_EVP_MD_CTX mdCtx; + size_t checkSz = -1; + const unsigned char* cp; + const unsigned char* p; + unsigned char check[2048/8]; + + printf(testingFmt, "wolfSSL_EVP_MD_ecc_signing()"); + + cp = ecc_clikey_der_256; + AssertNotNull((privKey = wolfSSL_d2i_PrivateKey(EVP_PKEY_EC, NULL, &cp, + sizeof_ecc_clikey_der_256))); + p = ecc_clikeypub_der_256; + AssertNotNull((pubKey = wolfSSL_d2i_PUBKEY(NULL, &p, + sizeof_ecc_clikeypub_der_256))); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, privKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData, + (unsigned int)XSTRLEN(testData)), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pubKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData, + (unsigned int)XSTRLEN(testData)), + 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, check, checkSz), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, privKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData, 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData + 4, + (unsigned int)XSTRLEN(testData) - 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pubKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData, 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData + 4, + (unsigned int)XSTRLEN(testData) - 4), + 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, check, checkSz), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_PKEY_free(pubKey); + wolfSSL_EVP_PKEY_free(privKey); + + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_CTX_add_extra_chain_cert(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + char caFile[] = "./certs/client-ca.pem"; + char clientFile[] = "./certs/client-cert.pem"; + SSL_CTX* ctx; + X509* x509; + + printf(testingFmt, "wolfSSL_CTX_add_extra_chain_cert()"); + + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); + #endif + + x509 = wolfSSL_X509_load_certificate_file(caFile, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), WOLFSSL_SUCCESS); + + x509 = wolfSSL_X509_load_certificate_file(clientFile, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + + #if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + /* additional test of getting EVP_PKEY key size from X509 + * Do not run with user RSA because wolfSSL_RSA_size is not currently + * allowed with user RSA */ + { + EVP_PKEY* pkey; + #if defined(HAVE_ECC) + X509* ecX509; + #endif /* HAVE_ECC */ + + AssertNotNull(pkey = X509_get_pubkey(x509)); + /* current RSA key is 2048 bit (256 bytes) */ + AssertIntEQ(EVP_PKEY_size(pkey), 256); + + EVP_PKEY_free(pkey); + + #if defined(HAVE_ECC) + #if defined(USE_CERT_BUFFERS_256) + AssertNotNull(ecX509 = wolfSSL_X509_load_certificate_buffer( + cliecc_cert_der_256, sizeof_cliecc_cert_der_256, + SSL_FILETYPE_ASN1)); + #else + AssertNotNull(ecX509 = wolfSSL_X509_load_certificate_file(cliEccCertFile, + SSL_FILETYPE_PEM)); + #endif + AssertNotNull(pkey = X509_get_pubkey(ecX509)); + /* current ECC key is 256 bit (32 bytes) */ + AssertIntEQ(EVP_PKEY_size(pkey), 32); + + X509_free(ecX509); + EVP_PKEY_free(pkey); + #endif /* HAVE_ECC */ + } +#endif /* !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) */ + + AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), SSL_SUCCESS); + +#ifdef WOLFSSL_ENCRYPTED_KEYS + AssertNull(SSL_CTX_get_default_passwd_cb(ctx)); + AssertNull(SSL_CTX_get_default_passwd_cb_userdata(ctx)); +#endif + + SSL_CTX_free(ctx); + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + + +#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) +static void test_wolfSSL_ERR_peek_last_error_line(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && defined(DEBUG_WOLFSSL) && \ + !defined(NO_OLD_TLS) && !defined(WOLFSSL_NO_TLS12) && \ + defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(NO_ERROR_QUEUE) + 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; + int flag = ERR_TXT_STRING; + const char* file = NULL; + const char* data = NULL; + + printf(testingFmt, "wolfSSL_ERR_peek_last_error_line()"); + + /* create a failed connection and inspect the error */ +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + + StartTCP(); + InitTcpReady(&ready); + + XMEMSET(&client_cb, 0, sizeof(callback_functions)); + XMEMSET(&server_cb, 0, sizeof(callback_functions)); + client_cb.method = wolfTLSv1_1_client_method; + server_cb.method = wolfTLSv1_2_server_method; + + server_args.signal = &ready; + server_args.callbacks = &server_cb; + 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, NULL); + join_thread(serverThread); +#endif + + FreeTcpReady(&ready); + + AssertIntGT(ERR_get_error_line_data(NULL, NULL, &data, &flag), 0); + AssertNotNull(data); + + /* check clearing error state */ + ERR_remove_state(0); + AssertIntEQ((int)ERR_peek_last_error_line(NULL, NULL), 0); + ERR_peek_last_error_line(NULL, &line); + AssertIntEQ(line, 0); + ERR_peek_last_error_line(&file, NULL); + AssertNull(file); + + /* retry connection to fill error queue */ + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + + StartTCP(); + InitTcpReady(&ready); + + client_cb.method = wolfTLSv1_1_client_method; + server_cb.method = wolfTLSv1_2_server_method; + + server_args.signal = &ready; + server_args.callbacks = &server_cb; + client_args.signal = &ready; + client_args.callbacks = &client_cb; + + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + test_client_nofail(&client_args, NULL); + join_thread(serverThread); + + FreeTcpReady(&ready); + + /* check that error code was stored */ + AssertIntNE((int)ERR_peek_last_error_line(NULL, NULL), 0); + ERR_peek_last_error_line(NULL, &line); + AssertIntNE(line, 0); + ERR_peek_last_error_line(&file, NULL); + AssertNotNull(file); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + printf(resultFmt, passed); + + printf("\nTesting error print out\n"); + ERR_print_errors_fp(stdout); + printf("Done testing print out\n\n"); + fflush(stdout); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(DEBUG_WOLFSSL) */ +} +#endif + +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) +static int verify_cb(int ok, X509_STORE_CTX *ctx) +{ + (void) ok; + (void) ctx; + printf("ENTER verify_cb\n"); + return SSL_SUCCESS; +} +#endif + + +static void test_wolfSSL_X509_STORE_CTX_get0_current_issuer(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) + #ifdef WOLFSSL_SIGNER_DER_CERT + int cmp; + #endif + X509_STORE_CTX* ctx; + X509_STORE* str; + X509* x509Ca; + X509* x509Svr; + X509* issuer; + X509_NAME* caName; + X509_NAME* issuerName; + + printf(testingFmt, "wolfSSL_X509_STORE_CTX_get0_current_issuer()"); + + AssertNotNull(ctx = X509_STORE_CTX_new()); + AssertNotNull((str = wolfSSL_X509_STORE_new())); + AssertNotNull((x509Ca = + wolfSSL_X509_load_certificate_file(caCertFile, SSL_FILETYPE_PEM))); + AssertIntEQ(X509_STORE_add_cert(str, x509Ca), SSL_SUCCESS); + AssertNotNull((x509Svr = + wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM))); + + AssertIntEQ(X509_STORE_CTX_init(ctx, str, x509Svr, NULL), SSL_SUCCESS); + + AssertNull(X509_STORE_CTX_get0_current_issuer(NULL)); + issuer = X509_STORE_CTX_get0_current_issuer(ctx); + AssertNotNull(issuer); + + caName = X509_get_subject_name(x509Ca); + AssertNotNull(caName); + issuerName = X509_get_subject_name(issuer); + #ifdef WOLFSSL_SIGNER_DER_CERT + AssertNotNull(issuerName); + cmp = X509_NAME_cmp(caName, issuerName); + AssertIntEQ(cmp, 0); + #else + /* X509_STORE_CTX_get0_current_issuer() returns empty issuer */ + AssertNull(issuerName); + #endif + + X509_free(issuer); + X509_STORE_CTX_free(ctx); + #if defined(WOLFSSL_KEEP_STORE_CERTS) || defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + X509_free(x509Svr); + X509_STORE_free(str); + #endif + X509_free(x509Ca); + + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_X509_STORE_CTX(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + + X509_STORE_CTX* ctx; + X509_STORE* str; + X509* x509; +#ifdef OPENSSL_ALL + X509* x5092; + STACK_OF(X509) *sk, *sk2, *sk3; +#endif + + printf(testingFmt, "wolfSSL_X509_STORE_CTX()"); + AssertNotNull(ctx = X509_STORE_CTX_new()); + AssertNotNull((str = wolfSSL_X509_STORE_new())); + AssertNotNull((x509 = + wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM))); + AssertIntEQ(X509_STORE_add_cert(str, x509), SSL_SUCCESS); +#ifdef OPENSSL_ALL + /* sk_X509_new only in OPENSSL_ALL */ + AssertNotNull(sk = sk_X509_new()); + AssertIntEQ(X509_STORE_CTX_init(ctx, str, x509, sk), SSL_SUCCESS); +#else + AssertIntEQ(X509_STORE_CTX_init(ctx, str, x509, NULL), SSL_SUCCESS); +#endif + AssertIntEQ(SSL_get_ex_data_X509_STORE_CTX_idx(), 0); + X509_STORE_CTX_set_error(ctx, -5); + X509_STORE_CTX_set_error(NULL, -5); + + X509_STORE_CTX_free(ctx); +#ifdef OPENSSL_ALL + sk_X509_free(sk); +#endif + #if defined(WOLFSSL_KEEP_STORE_CERTS) || defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + X509_STORE_free(str); + X509_free(x509); + #endif + + AssertNotNull(ctx = X509_STORE_CTX_new()); + X509_STORE_CTX_set_verify_cb(ctx, verify_cb); + X509_STORE_CTX_free(ctx); + +#ifdef OPENSSL_ALL + /* test X509_STORE_CTX_get(1)_chain */ + AssertNotNull((x509 = X509_load_certificate_file(svrCertFile, + SSL_FILETYPE_PEM))); + AssertNotNull((x5092 = X509_load_certificate_file(cliCertFile, + SSL_FILETYPE_PEM))); + AssertNotNull((sk = sk_X509_new())); + AssertIntEQ(sk_X509_push(sk, x509), 1); + AssertNotNull((str = X509_STORE_new())); + AssertNotNull((ctx = X509_STORE_CTX_new())); + AssertIntEQ(X509_STORE_CTX_init(ctx, str, x5092, sk), 1); + AssertNull((sk2 = X509_STORE_CTX_get_chain(NULL))); + AssertNotNull((sk2 = X509_STORE_CTX_get_chain(ctx))); + AssertIntEQ(sk_num(sk2), 1); /* sanity, make sure chain has 1 cert */ + AssertNull((sk3 = X509_STORE_CTX_get1_chain(NULL))); + AssertNotNull((sk3 = X509_STORE_CTX_get1_chain(ctx))); + AssertIntEQ(sk_num(sk3), 1); /* sanity, make sure chain has 1 cert */ + X509_STORE_CTX_free(ctx); + sk_X509_free(sk); + #if defined(WOLFSSL_KEEP_STORE_CERTS) || defined(WOLFSSL_QT) + X509_STORE_free(str); + /* CTX certs not freed yet */ + X509_free(x5092); + #endif + /* sk2 freed as part of X509_STORE_CTX_free(), sk3 is dup so free here */ + sk_X509_free(sk3); +#endif + + /* test X509_STORE_CTX_get/set_ex_data */ + { + int i = 0, tmpData = 5; + void* tmpDataRet; + AssertNotNull(ctx = X509_STORE_CTX_new()); + #if defined(HAVE_EX_DATA) || defined(FORTRESS) + for (i = 0; i < MAX_EX_DATA; i++) { + AssertIntEQ(X509_STORE_CTX_set_ex_data(ctx, i, &tmpData), + WOLFSSL_SUCCESS); + tmpDataRet = (int*)X509_STORE_CTX_get_ex_data(ctx, i); + AssertNotNull(tmpDataRet); + AssertIntEQ(tmpData, *(int*)tmpDataRet); + } + #else + AssertIntEQ(X509_STORE_CTX_set_ex_data(ctx, i, &tmpData), + WOLFSSL_FAILURE); + tmpDataRet = (int*)X509_STORE_CTX_get_ex_data(ctx, i); + AssertNull(tmpDataRet); + #endif + X509_STORE_CTX_free(ctx); + } + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + +static void test_wolfSSL_X509_STORE_set_flags(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + + X509_STORE* store; + X509* x509; + + printf(testingFmt, "wolfSSL_X509_STORE_set_flags()"); + AssertNotNull((store = wolfSSL_X509_STORE_new())); + AssertNotNull((x509 = + 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), WOLFSSL_SUCCESS); +#else + AssertIntEQ(X509_STORE_set_flags(store, WOLFSSL_CRL_CHECKALL), + NOT_COMPILED_IN); +#endif + + wolfSSL_X509_free(x509); + wolfSSL_X509_STORE_free(store); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !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); + + if (store) { + 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); + if (store) { + 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 c_time; + + printf(testingFmt, "wolfSSL_X509_set_time()"); + AssertNotNull(ctx = wolfSSL_X509_STORE_CTX_new()); + c_time = 365*24*60*60; + wolfSSL_X509_STORE_CTX_set_time(ctx, 0, c_time); + AssertTrue( + (ctx->param->flags & WOLFSSL_USE_CHECK_TIME) == WOLFSSL_USE_CHECK_TIME); + AssertTrue(ctx->param->check_time == c_time); + wolfSSL_X509_STORE_CTX_free(ctx); + + printf(resultFmt, passed); + #endif /* OPENSSL_EXTRA */ +} + +static void test_wolfSSL_get0_param(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) + SSL_CTX* ctx; + SSL* ssl; + WOLFSSL_X509_VERIFY_PARAM* pParam; + + printf(testingFmt, "wolfSSL_get0_param()"); + + #ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + #else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); + #endif + 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)); + + pParam = SSL_get0_param(ssl); + + (void)pParam; + + SSL_free(ssl); + SSL_CTX_free(ctx); + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && !defined(NO_RSA)*/ +} + +static void test_wolfSSL_X509_VERIFY_PARAM_set1_host(void) +{ +#if defined(OPENSSL_EXTRA) + const char host[] = "www.example.com"; + WOLFSSL_X509_VERIFY_PARAM* pParam; + + printf(testingFmt, "wolfSSL_X509_VERIFY_PARAM_set1_host()"); + + AssertNotNull(pParam = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( + sizeof(WOLFSSL_X509_VERIFY_PARAM), + HEAP_HINT, DYNAMIC_TYPE_OPENSSL)); + + XMEMSET(pParam, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + + X509_VERIFY_PARAM_set1_host(pParam, host, sizeof(host)); + + AssertIntEQ(XMEMCMP(pParam->hostName, host, sizeof(host)), 0); + + XMEMSET(pParam, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + + AssertIntNE(XMEMCMP(pParam->hostName, host, sizeof(host)), 0); + + XFREE(pParam, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} + +static void test_wolfSSL_X509_STORE_CTX_get0_store(void) +{ + #if defined(OPENSSL_EXTRA) + X509_STORE* store; + X509_STORE_CTX* ctx; + X509_STORE_CTX* ctx_no_init; + + printf(testingFmt, "wolfSSL_X509_STORE_CTX_get0_store()"); + AssertNotNull((store = X509_STORE_new())); + AssertNotNull(ctx = X509_STORE_CTX_new()); + AssertNotNull(ctx_no_init = X509_STORE_CTX_new()); + AssertIntEQ(X509_STORE_CTX_init(ctx, store, NULL, NULL), SSL_SUCCESS); + + AssertNull(X509_STORE_CTX_get0_store(NULL)); + /* should return NULL if ctx has not bee initialized */ + AssertNull(X509_STORE_CTX_get0_store(ctx_no_init)); + AssertNotNull(X509_STORE_CTX_get0_store(ctx)); + + wolfSSL_X509_STORE_CTX_free(ctx); + wolfSSL_X509_STORE_CTX_free(ctx_no_init); +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + X509_STORE_free(store); +#endif + + printf(resultFmt, passed); + #endif /* OPENSSL_EXTRA */ +} + +static void test_wolfSSL_CTX_set_client_CA_list(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + !defined(NO_WOLFSSL_CLIENT) + WOLFSSL_CTX* ctx; + X509_NAME* name = NULL; + STACK_OF(X509_NAME)* names = NULL; + STACK_OF(X509_NAME)* ca_list = NULL; + int i, names_len; + + printf(testingFmt, "wolfSSL_CTX_set_client_CA_list()"); + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + names = SSL_load_client_CA_file(cliCertFile); + AssertNotNull(names); + SSL_CTX_set_client_CA_list(ctx,names); + AssertNotNull(ca_list = SSL_CTX_get_client_CA_list(ctx)); + + AssertIntGT((names_len = sk_X509_NAME_num(names)), 0); + for (i=0; icm, ca_file, NULL), WOLFSSL_SUCCESS); + + /* Test bad arguments */ + AssertIntEQ(X509_STORE_load_locations(NULL, ca_file, NULL), WOLFSSL_FAILURE); + AssertIntEQ(X509_STORE_load_locations(store, NULL, NULL), WOLFSSL_FAILURE); + AssertIntEQ(X509_STORE_load_locations(store, client_der_file, NULL), WOLFSSL_FAILURE); + AssertIntEQ(X509_STORE_load_locations(store, ecc_file, NULL), WOLFSSL_FAILURE); + AssertIntEQ(X509_STORE_load_locations(store, NULL, bad_path), WOLFSSL_FAILURE); + +#ifdef HAVE_CRL + /* Test with CRL */ + AssertIntEQ(X509_STORE_load_locations(store, crl_file, NULL), WOLFSSL_SUCCESS); + AssertIntEQ(X509_STORE_load_locations(store, NULL, crl_path), WOLFSSL_SUCCESS); +#endif + + /* Test with CA */ + AssertIntEQ(X509_STORE_load_locations(store, ca_file, NULL), WOLFSSL_SUCCESS); + + /* Test with client_cert and certs path */ + AssertIntEQ(X509_STORE_load_locations(store, client_pem_file, NULL), WOLFSSL_SUCCESS); + AssertIntEQ(X509_STORE_load_locations(store, NULL, certs_path), WOLFSSL_SUCCESS); + + SSL_CTX_free(ctx); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_BN(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + BIGNUM* a; + BIGNUM* b; + BIGNUM* c; + BIGNUM* d; + ASN1_INTEGER* ai; + unsigned char value[1]; + + printf(testingFmt, "wolfSSL_BN()"); + + AssertNotNull(b = BN_new()); + AssertNotNull(c = BN_new()); + AssertNotNull(d = BN_new()); + + value[0] = 0x03; + + AssertNotNull(ai = ASN1_INTEGER_new()); + /* at the moment hard setting since no set function */ + ai->data[0] = 0x02; /* tag for ASN_INTEGER */ + ai->data[1] = 0x01; /* length of integer */ + ai->data[2] = value[0]; + + AssertNotNull(a = ASN1_INTEGER_to_BN(ai, NULL)); + ASN1_INTEGER_free(ai); + + value[0] = 0x02; + AssertNotNull(BN_bin2bn(value, sizeof(value), b)); + + value[0] = 0x05; + AssertNotNull(BN_bin2bn(value, sizeof(value), c)); + + /* a^b mod c = */ + 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), sizeof(value)); + AssertIntEQ((int)(value[0]), 4); + + /* a*b mod c = */ + AssertIntEQ(BN_mod_mul(d, NULL, b, c, NULL), SSL_FAILURE); + AssertIntEQ(BN_mod_mul(d, a, b, c, NULL), SSL_SUCCESS); + + /* check result 3*2 mod 5 */ + value[0] = 0; + AssertIntEQ(BN_bn2bin(d, value), sizeof(value)); + AssertIntEQ((int)(value[0]), 1); + + /* 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); + + AssertIntEQ(BN_set_word(a, 1), SSL_SUCCESS); + AssertIntEQ(BN_set_word(b, 5), SSL_SUCCESS); + AssertIntEQ(BN_is_word(a, (WOLFSSL_BN_ULONG)BN_get_word(a)), SSL_SUCCESS); + AssertIntEQ(BN_is_word(a, 3), SSL_FAILURE); + AssertIntEQ(BN_sub(c, a, b), SSL_SUCCESS); +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) + { + char* ret; + AssertNotNull(ret = BN_bn2dec(c)); + AssertIntEQ(XMEMCMP(ret, "-4", sizeof("-4")), 0); + XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL); + } +#endif + AssertIntEQ(BN_get_word(c), 4); + + 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); + + AssertIntEQ(BN_set_word(a, 0), 1); + AssertIntEQ(BN_is_zero(a), 1); + AssertIntEQ(BN_set_bit(a, 0x45), 1); + AssertIntEQ(BN_is_zero(a), 0); + AssertIntEQ(BN_is_bit_set(a, 0x45), 1); + AssertIntEQ(BN_clear_bit(a, 0x45), 1); + AssertIntEQ(BN_is_bit_set(a, 0x45), 0); + AssertIntEQ(BN_is_zero(a), 1); + + BN_free(a); + BN_free(b); + BN_free(c); + + #if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) + { + BIGNUM *ap; + BIGNUM bv; + BIGNUM cv; + BIGNUM dv; + + AssertNotNull(ap = BN_new()); + BN_init(&bv); + BN_init(&cv); + BN_init(&dv); + + value[0] = 0x3; + AssertNotNull(BN_bin2bn(value, sizeof(value), ap)); + + value[0] = 0x02; + AssertNotNull(BN_bin2bn(value, sizeof(value), &bv)); + + value[0] = 0x05; + AssertNotNull(BN_bin2bn(value, sizeof(value), &cv)); + + /* a^b mod c = */ + AssertIntEQ(BN_mod_exp(&dv, NULL, &bv, &cv, NULL), WOLFSSL_FAILURE); + AssertIntEQ(BN_mod_exp(&dv, ap, &bv, &cv, NULL), WOLFSSL_SUCCESS); + + /* check result 3^2 mod 5 */ + value[0] = 0; + AssertIntEQ(BN_bn2bin(&dv, value), sizeof(value)); + AssertIntEQ((int)(value[0]), 4); + + /* a*b mod c = */ + AssertIntEQ(BN_mod_mul(&dv, NULL, &bv, &cv, NULL), SSL_FAILURE); + AssertIntEQ(BN_mod_mul(&dv, ap, &bv, &cv, NULL), SSL_SUCCESS); + + /* check result 3*2 mod 5 */ + value[0] = 0; + AssertIntEQ(BN_bn2bin(&dv, value), sizeof(value)); + AssertIntEQ((int)(value[0]), 1); + + BN_free(ap); + } + #endif + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_ASN) */ +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) +#define TEST_ARG 0x1234 +static void msg_cb(int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg) +{ + (void)write_p; + (void)version; + (void)content_type; + (void)buf; + (void)len; + (void)ssl; + + AssertTrue(arg == (void*)TEST_ARG); +} +#endif + +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && defined(DEBUG_WOLFSSL) && \ + defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(NO_WOLFSSL_CLIENT) && \ + !defined(NO_WOLFSSL_SERVER) +#ifndef SINGLE_THREADED +#if defined(SESSION_CERTS) +#include "wolfssl/internal.h" +#endif +static int msgCb(SSL_CTX *ctx, SSL *ssl) +{ + (void) ctx; + (void) ssl; + #ifdef WOLFSSL_QT + STACK_OF(X509)* sk; + X509* x509; + int i, num; + BIO* bio; + #endif + printf("\n===== msgcb called ====\n"); + #if defined(SESSION_CERTS) && defined(TEST_PEER_CERT_CHAIN) + AssertTrue(SSL_get_peer_cert_chain(ssl) != NULL); + AssertIntEQ(((WOLFSSL_X509_CHAIN *)SSL_get_peer_cert_chain(ssl))->count, 1); + #endif + + #ifdef WOLFSSL_QT + bio = BIO_new(BIO_s_file()); + BIO_set_fp(bio, stdout, BIO_NOCLOSE); + sk = SSL_get_peer_cert_chain(ssl); + AssertNotNull(sk); + if (!sk) { + BIO_free(bio); + return SSL_FAILURE; + } + num = sk_X509_num(sk); + AssertTrue(num > 0); + for (i = 0; i < num; i++) { + x509 = sk_X509_value(sk,i); + AssertNotNull(x509); + if (!x509) + break; + printf("Certificate at index [%d] = :\n",i); + X509_print(bio,x509); + printf("\n\n"); + } + BIO_free(bio); + #endif + return SSL_SUCCESS; +} +#endif +#endif + +static void test_wolfSSL_msgCb(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && defined(DEBUG_WOLFSSL) && \ + defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(NO_WOLFSSL_CLIENT) && \ + !defined(NO_WOLFSSL_SERVER) + + 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; + + printf(testingFmt, "test_wolfSSL_msgCb"); + +/* create a failed connection and inspect the error */ +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + + StartTCP(); + InitTcpReady(&ready); + + XMEMSET(&client_cb, 0, sizeof(callback_functions)); + XMEMSET(&server_cb, 0, sizeof(callback_functions)); +#ifndef WOLFSSL_NO_TLS12 + client_cb.method = wolfTLSv1_2_client_method; + server_cb.method = wolfTLSv1_2_server_method; +#else + client_cb.method = wolfTLSv1_3_client_method; + server_cb.method = wolfTLSv1_3_server_method; +#endif + + server_args.signal = &ready; + server_args.callbacks = &server_cb; + client_args.signal = &ready; + client_args.callbacks = &client_cb; + client_args.return_code = TEST_FAIL; + + #ifndef SINGLE_THREADED + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + test_client_nofail(&client_args, (void *)msgCb); + join_thread(serverThread); + AssertTrue(client_args.return_code); + AssertTrue(server_args.return_code); + #endif + + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + printf(resultFmt, passed); + +#endif +} + +static void test_wolfSSL_either_side(void) +{ +#if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)) && \ + !defined(NO_FILESYSTEM) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \ + !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) + + 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; + + printf(testingFmt, "test_wolfSSL_either_side"); + +/* create a failed connection and inspect the error */ +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + + StartTCP(); + InitTcpReady(&ready); + + XMEMSET(&client_cb, 0, sizeof(callback_functions)); + XMEMSET(&server_cb, 0, sizeof(callback_functions)); + + /* Use same CTX for both client and server */ + client_cb.ctx = wolfSSL_CTX_new(wolfSSLv23_method()); + AssertNotNull(client_cb.ctx); + server_cb.ctx = client_cb.ctx; + + server_args.signal = &ready; + server_args.callbacks = &server_cb; + client_args.signal = &ready; + client_args.callbacks = &client_cb; + client_args.return_code = TEST_FAIL; + + #ifndef SINGLE_THREADED + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + test_client_nofail(&client_args, NULL); + join_thread(serverThread); + AssertTrue(client_args.return_code); + AssertTrue(server_args.return_code); + #endif + + wolfSSL_CTX_free(client_cb.ctx); + + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + printf(resultFmt, passed); + +#endif +} + +static void test_wolfSSL_DTLS_either_side(void) +{ +#if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)) && \ + !defined(NO_FILESYSTEM) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \ + !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ + defined(WOLFSSL_DTLS) + + 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; + + printf(testingFmt, "test_wolfSSL_DTLS_either_side"); + +/* create a failed connection and inspect the error */ +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + + StartTCP(); + InitTcpReady(&ready); + + XMEMSET(&client_cb, 0, sizeof(callback_functions)); + XMEMSET(&server_cb, 0, sizeof(callback_functions)); + + /* Use same CTX for both client and server */ + client_cb.ctx = wolfSSL_CTX_new(wolfDTLS_method()); + AssertNotNull(client_cb.ctx); + server_cb.ctx = client_cb.ctx; + + server_args.signal = &ready; + server_args.callbacks = &server_cb; + client_args.signal = &ready; + client_args.callbacks = &client_cb; + client_args.return_code = TEST_FAIL; + + #ifndef SINGLE_THREADED + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + test_client_nofail(&client_args, NULL); + join_thread(serverThread); + AssertTrue(client_args.return_code); + AssertTrue(server_args.return_code); + #endif + + wolfSSL_CTX_free(client_cb.ctx); + + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + printf(resultFmt, passed); + +#endif +} + +static void test_generate_cookie(void) +{ +#if defined(WOLFSSL_DTLS) && defined(OPENSSL_EXTRA) + SSL_CTX* ctx; + SSL* ssl; + byte buf[FOURK_BUF] = {0}; + + printf(testingFmt, "test_generate_cookie"); + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfDTLS_method())); + AssertNotNull(ssl = SSL_new(ctx)); + + /* Test unconnected */ + AssertIntEQ(EmbedGenerateCookie(ssl, buf, FOURK_BUF, NULL), GEN_COOKIE_E); + + wolfSSL_CTX_SetGenCookie(ctx, EmbedGenerateCookie); + + wolfSSL_SetCookieCtx(ssl, ctx); + + AssertNotNull(wolfSSL_GetCookieCtx(ssl)); + + AssertNull(wolfSSL_GetCookieCtx(NULL)); + + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_set_options(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + SSL* ssl; + SSL_CTX* ctx; + char appData[] = "extra msg"; + + unsigned char protos[] = { + 7, 't', 'l', 's', '/', '1', '.', '2', + 8, 'h', 't', 't', 'p', '/', '1', '.', '1' + }; + unsigned int len = sizeof(protos); + + void *arg = (void *)TEST_ARG; + + printf(testingFmt, "wolfSSL_set_options()"); + +#ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); +#else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); +#endif + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + + AssertTrue(SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1); + AssertTrue(SSL_CTX_get_options(ctx) == SSL_OP_NO_TLSv1); + + AssertIntGT((int)SSL_CTX_set_options(ctx, (SSL_OP_COOKIE_EXCHANGE | + SSL_OP_NO_SSLv2)), 0); + AssertTrue((SSL_CTX_set_options(ctx, SSL_OP_COOKIE_EXCHANGE) & + SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE); + AssertTrue((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_2) & + SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2); + AssertTrue((SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION) & + SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION); + AssertNull((SSL_CTX_clear_options(ctx, SSL_OP_NO_COMPRESSION) & + SSL_OP_NO_COMPRESSION)); + + SSL_CTX_free(ctx); + +#ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); +#else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); +#endif + 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)); +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + AssertIntEQ(SSL_set_app_data(ssl, (void*)appData), SSL_SUCCESS); + AssertNotNull(SSL_get_app_data((const WOLFSSL*)ssl)); + if (ssl) { + AssertIntEQ(XMEMCMP(SSL_get_app_data((const WOLFSSL*)ssl), + appData, sizeof(appData)), 0); + } +#else + AssertIntEQ(SSL_set_app_data(ssl, (void*)appData), SSL_FAILURE); + AssertNull(SSL_get_app_data((const WOLFSSL*)ssl)); +#endif + + 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 | + 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) & + SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2); + AssertTrue((SSL_set_options(ssl, SSL_OP_NO_COMPRESSION) & + SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION); + AssertNull((SSL_clear_options(ssl, SSL_OP_NO_COMPRESSION) & + SSL_OP_NO_COMPRESSION)); + + AssertTrue(SSL_set_msg_callback(ssl, msg_cb) == SSL_SUCCESS); + SSL_set_msg_callback_arg(ssl, arg); + + AssertTrue(SSL_CTX_set_alpn_protos(ctx, protos, len) == SSL_SUCCESS); + + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + +static void test_wolfSSL_sk_SSL_CIPHER(void) +{ + #if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + SSL* ssl; + SSL_CTX* ctx; + STACK_OF(SSL_CIPHER) *sk, *dup; + + printf(testingFmt, "wolfSSL_sk_SSL_CIPHER_*()"); + +#ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); +#else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); +#endif + 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)); + AssertNotNull(sk = SSL_get_ciphers(ssl)); + AssertNotNull(dup = sk_SSL_CIPHER_dup(sk)); + AssertIntGT(sk_SSL_CIPHER_num(sk), 0); + AssertIntEQ(sk_SSL_CIPHER_num(sk), sk_SSL_CIPHER_num(dup)); + + /* error case because connection has not been established yet */ + AssertIntEQ(sk_SSL_CIPHER_find(sk, SSL_get_current_cipher(ssl)), -1); + sk_SSL_CIPHER_free(dup); + + /* sk is pointer to internal struct that should be free'd in SSL_free */ + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + +/* Testing wolfSSL_set_tlsext_status_type function. + * 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) && \ + !defined(NO_RSA) && !defined(NO_WOLFSSL_SERVER) + 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 && !NO_RSA */ +} + +static void test_wolfSSL_PEM_read_bio(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + byte buff[5300]; + XFILE f; + int bytes; + X509* x509; + BIO* bio = NULL; + BUF_MEM* buf; + + printf(testingFmt, "wolfSSL_PEM_read_bio()"); + + f = XFOPEN(cliCertFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); + XFCLOSE(f); + + AssertNull(x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL)); + AssertNotNull(bio = BIO_new_mem_buf((void*)buff, bytes)); + AssertNotNull(x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL)); + AssertIntEQ((int)BIO_set_fd(bio, 0, BIO_CLOSE), 1); + AssertIntEQ(BIO_set_close(bio, BIO_NOCLOSE), 1); + AssertIntEQ(BIO_set_close(NULL, BIO_NOCLOSE), 1); + AssertIntEQ(SSL_SUCCESS, BIO_get_mem_ptr(bio, &buf)); + + BIO_free(bio); + BUF_MEM_free(buf); + X509_free(x509); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + + +#if defined(OPENSSL_EXTRA) +static long bioCallback(BIO *bio, int cmd, const char* argp, int argi, + long argl, long ret) +{ + (void)bio; + (void)cmd; + (void)argp; + (void)argi; + (void)argl; + return ret; +} +#endif + + +static void test_wolfSSL_BIO(void) +{ + #if defined(OPENSSL_EXTRA) + const unsigned char* p; + byte buff[20]; + BIO* bio1; + BIO* bio2; + BIO* bio3; + char* bufPt; + int i; + + printf(testingFmt, "wolfSSL_BIO()"); + + for (i = 0; i < 20; i++) { + buff[i] = i; + } + + /* Creating and testing type BIO_s_bio */ + AssertNotNull(bio1 = BIO_new(BIO_s_bio())); + AssertNotNull(bio2 = BIO_new(BIO_s_bio())); + AssertNotNull(bio3 = BIO_new(BIO_s_bio())); + + /* read/write before set up */ + AssertIntEQ(BIO_read(bio1, buff, 2), WOLFSSL_BIO_UNSET); + AssertIntEQ(BIO_write(bio1, buff, 2), WOLFSSL_BIO_UNSET); + + AssertIntEQ(BIO_set_nbio(bio1, 1), 1); + 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, buff, 10); + AssertIntEQ(BIO_write(bio1, buff + 10, 10), 10); + /* write buffer full */ + AssertIntEQ(BIO_write(bio1, buff, 10), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_flush(bio1), WOLFSSL_SUCCESS); + AssertIntEQ((int)BIO_ctrl_pending(bio1), 0); + + /* write the other direction with pair */ + AssertIntEQ((int)BIO_nwrite(bio2, &bufPt, 10), 8); + XMEMCPY(bufPt, buff, 8); + AssertIntEQ(BIO_write(bio2, buff, 10), WOLFSSL_BIO_ERROR); + + /* try read */ + AssertIntEQ((int)BIO_ctrl_pending(bio1), 8); + AssertIntEQ((int)BIO_ctrl_pending(bio2), 20); + + /* try read using ctrl function */ + AssertIntEQ((int)BIO_ctrl(bio1, BIO_CTRL_WPENDING, 0, NULL), 8); + AssertIntEQ((int)BIO_ctrl(bio1, BIO_CTRL_PENDING, 0, NULL), 8); + AssertIntEQ((int)BIO_ctrl(bio2, BIO_CTRL_WPENDING, 0, NULL), 20); + AssertIntEQ((int)BIO_ctrl(bio2, BIO_CTRL_PENDING, 0, NULL), 20); + + AssertIntEQ(BIO_nread(bio2, &bufPt, (int)BIO_ctrl_pending(bio2)), 20); + for (i = 0; i < 20; i++) { + AssertIntEQ((int)bufPt[i], i); + } + AssertIntEQ(BIO_nread(bio2, &bufPt, 1), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nread(bio1, &bufPt, (int)BIO_ctrl_pending(bio1)), 8); + for (i = 0; i < 8; i++) { + AssertIntEQ((int)bufPt[i], i); + } + AssertIntEQ(BIO_nread(bio1, &bufPt, 1), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_ctrl_reset_read_request(bio1), 1); + + /* new pair */ + AssertIntEQ(BIO_make_bio_pair(bio1, bio3), WOLFSSL_FAILURE); + BIO_free(bio2); /* free bio2 and automatically remove from pair */ + 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); + + /* test wrap around... */ + AssertIntEQ(BIO_reset(bio1), 0); + AssertIntEQ(BIO_reset(bio3), 0); + + /* fill write buffer, read only small amount then write again */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20); + XMEMCPY(bufPt, buff, 20); + AssertIntEQ(BIO_nread(bio3, &bufPt, 4), 4); + for (i = 0; i < 4; i++) { + AssertIntEQ(bufPt[i], i); + } + + /* try writing over read index */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 5), 4); + XMEMSET(bufPt, 0, 4); + AssertIntEQ((int)BIO_ctrl_pending(bio3), 20); + + /* read and write 0 bytes */ + AssertIntEQ(BIO_nread(bio3, &bufPt, 0), 0); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 0), 0); + + /* should read only to end of write buffer then need to read again */ + AssertIntEQ(BIO_nread(bio3, &bufPt, 20), 16); + for (i = 0; i < 16; i++) { + AssertIntEQ(bufPt[i], buff[4 + i]); + } + + AssertIntEQ(BIO_nread(bio3, NULL, 0), WOLFSSL_FAILURE); + AssertIntEQ(BIO_nread0(bio3, &bufPt), 4); + for (i = 0; i < 4; i++) { + AssertIntEQ(bufPt[i], 0); + } + + /* read index should not have advanced with nread0 */ + AssertIntEQ(BIO_nread(bio3, &bufPt, 5), 4); + for (i = 0; i < 4; i++) { + AssertIntEQ(bufPt[i], 0); + } + + /* write and fill up buffer checking reset of index state */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20); + XMEMCPY(bufPt, buff, 20); + + /* test reset on data in bio1 write buffer */ + AssertIntEQ(BIO_reset(bio1), 0); + AssertIntEQ((int)BIO_ctrl_pending(bio3), 0); + AssertIntEQ(BIO_nread(bio3, &bufPt, 3), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20); + AssertIntEQ((int)BIO_ctrl(bio1, BIO_CTRL_INFO, 0, &p), 20); + AssertNotNull(p); + XMEMCPY(bufPt, buff, 20); + AssertIntEQ(BIO_nread(bio3, &bufPt, 6), 6); + for (i = 0; i < 6; i++) { + AssertIntEQ(bufPt[i], i); + } + + /* test case of writing twice with offset read index */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 3), 3); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), 3); /* try overwriting */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nread(bio3, &bufPt, 0), 0); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nread(bio3, &bufPt, 1), 1); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), 1); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR); + + BIO_free(bio1); + BIO_free(bio3); + + #if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) + { + BIO* bioA = NULL; + BIO* bioB = NULL; + AssertIntEQ(BIO_new_bio_pair(NULL, 256, NULL, 256), BAD_FUNC_ARG); + AssertIntEQ(BIO_new_bio_pair(&bioA, 256, &bioB, 256), WOLFSSL_SUCCESS); + BIO_free(bioA); + bioA = NULL; + BIO_free(bioB); + bioB = NULL; + } + #endif /* OPENSSL_ALL || WOLFSSL_ASIO */ + + /* BIOs with file pointers */ + #if !defined(NO_FILESYSTEM) + { + XFILE f1; + XFILE f2; + BIO* f_bio1; + BIO* f_bio2; + unsigned char cert[300]; + char testFile[] = "tests/bio_write_test.txt"; + char msg[] = "bio_write_test.txt contains the first 300 bytes of certs/server-cert.pem\ncreated by tests/unit.test\n\n"; + + AssertNotNull(f_bio1 = BIO_new(BIO_s_file())); + AssertNotNull(f_bio2 = BIO_new(BIO_s_file())); + + AssertIntEQ((int)BIO_set_mem_eof_return(f_bio1, -1), 0); + AssertIntEQ((int)BIO_set_mem_eof_return(NULL, -1), 0); + + f1 = XFOPEN(svrCertFile, "rwb"); + AssertTrue((f1 != XBADFILE)); + AssertIntEQ((int)BIO_set_fp(f_bio1, f1, BIO_CLOSE), WOLFSSL_SUCCESS); + AssertIntEQ(BIO_write_filename(f_bio2, testFile), + 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), WOLFSSL_SUCCESS); + AssertIntEQ(BIO_reset(f_bio2), 0); + AssertIntEQ(BIO_seek(f_bio2, 4), 0); + + BIO_free(f_bio1); + BIO_free(f_bio2); + + AssertNotNull(f_bio1 = BIO_new_file(svrCertFile, "rwb")); + AssertIntEQ((int)BIO_set_mem_eof_return(f_bio1, -1), 0); + AssertIntEQ(BIO_read(f_bio1, cert, sizeof(cert)), sizeof(cert)); + BIO_free(f_bio1); + + } + #endif /* !defined(NO_FILESYSTEM) */ + + /* BIO info callback */ + { + const char* testArg = "test"; + BIO* cb_bio; + AssertNotNull(cb_bio = BIO_new(BIO_s_mem())); + + BIO_set_callback(cb_bio, bioCallback); + AssertNotNull(BIO_get_callback(cb_bio)); + BIO_set_callback(cb_bio, NULL); + AssertNull(BIO_get_callback(cb_bio)); + + BIO_set_callback_arg(cb_bio, (char*)testArg); + AssertStrEQ(BIO_get_callback_arg(cb_bio), testArg); + AssertNull(BIO_get_callback_arg(NULL)); + + BIO_free(cb_bio); + } + + /* BIO_vfree */ + AssertNotNull(bio1 = BIO_new(BIO_s_bio())); + BIO_vfree(NULL); + BIO_vfree(bio1); + + printf(resultFmt, passed); + #endif +} + + +static void test_wolfSSL_ASN1_STRING(void) +{ + #if defined(OPENSSL_EXTRA) + ASN1_STRING* str = NULL; + const char data[] = "hello wolfSSL"; + + printf(testingFmt, "wolfSSL_ASN1_STRING()"); + + AssertNotNull(str = ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); + AssertIntEQ(ASN1_STRING_type(str), V_ASN1_OCTET_STRING); + AssertIntEQ(ASN1_STRING_set(str, (const void*)data, sizeof(data)), 1); + AssertIntEQ(ASN1_STRING_set(str, (const void*)data, -1), 1); + AssertIntEQ(ASN1_STRING_set(str, NULL, -1), 0); + + ASN1_STRING_free(str); + + printf(resultFmt, passed); + #endif +} + +static void test_wolfSSL_ASN1_BIT_STRING(void) +{ +#ifdef OPENSSL_ALL + ASN1_BIT_STRING* str; + + printf(testingFmt, "test_wolfSSL_ASN1_BIT_STRING()"); + AssertNotNull(str = ASN1_BIT_STRING_new()); + + AssertIntEQ(ASN1_BIT_STRING_set_bit(str, 42, 1), 1); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 42), 1); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 41), 0); + AssertIntEQ(ASN1_BIT_STRING_set_bit(str, 84, 1), 1); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 84), 1); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 83), 0); + + ASN1_BIT_STRING_free(str); + printf(resultFmt, passed); +#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_ASN_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 mini = 60; + const byte asn_utc_time = ASN_UTC_TIME; +#if !defined(TIME_T_NOT_64BIT) && !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[CTC_DATE_SIZE + 1]; + time_t t; + + printf(testingFmt, "wolfSSL_ASN1_TIME_adj()"); + + s = wolfSSL_ASN1_TIME_new(); + /* UTC notation test */ + /* 2000/2/15 20:30:00 */ + t = (time_t)30 * year + 45 * day + 20 * hour + 30 * mini + 7 * day; + offset_day = 7; + offset_sec = 45 * mini; + /* offset_sec = -45 * min;*/ + asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); + AssertTrue(asn_time->type == asn_utc_time); + XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); + date_str[CTC_DATE_SIZE] = '\0'; + AssertIntEQ(0, XMEMCMP(date_str, "000222211500Z", 13)); + + /* negative offset */ + offset_sec = -45 * mini; + asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); + AssertTrue(asn_time->type == asn_utc_time); + XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); + date_str[CTC_DATE_SIZE] = '\0'; + 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_64BIT) && !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 * mini; + asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); + AssertTrue(asn_time->type == asn_gen_time); + XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); + date_str[CTC_DATE_SIZE] = '\0'; + AssertIntEQ(0, XMEMCMP(date_str, "20550313091000Z", 15)); + + XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); + XMEMSET(date_str, 0, sizeof(date_str)); +#endif /* !TIME_T_NOT_64BIT && !NO_64BIT */ + + /* if WOLFSSL_ASN1_TIME struct is not allocated */ + s = NULL; + + t = (time_t)30 * year + 45 * day + 20 * hour + 30 * mini + 15 + 7 * day; + offset_day = 7; + offset_sec = 45 * mini; + asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); + AssertTrue(asn_time->type == asn_utc_time); + XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); + date_str[CTC_DATE_SIZE] = '\0'; + 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->type == asn_utc_time); + XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); + date_str[CTC_DATE_SIZE] = '\0'; + AssertIntEQ(0, XMEMCMP(date_str, "000222211515Z", 13)); + XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL); + + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_X509_cmp_time(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) \ +&& !defined(USER_TIME) && !defined(TIME_OVERRIDES) + WOLFSSL_ASN1_TIME asn_time; + time_t t; + + printf(testingFmt, "wolfSSL_X509_cmp_time()"); + + AssertIntEQ(0, wolfSSL_X509_cmp_time(NULL, &t)); + XMEMSET(&asn_time, 0, sizeof(WOLFSSL_ASN1_TIME)); + AssertIntEQ(0, wolfSSL_X509_cmp_time(&asn_time, &t)); + + asn_time.type = ASN_UTC_TIME; + asn_time.length = ASN_UTC_TIME_SIZE; + XMEMCPY(&asn_time.data, "000222211515Z", 13); + AssertIntEQ(-1, wolfSSL_X509_cmp_time(&asn_time, NULL)); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_time_adj(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) && \ + !defined(USER_TIME) && !defined(TIME_OVERRIDES) && \ + defined(USE_CERT_BUFFERS_2048) && !defined(NO_RSA) && \ + !defined(NO_ASN_TIME) + X509* x509; + time_t t, not_before, not_after; + + printf(testingFmt, "wolfSSL_X509_time_adj()"); + + AssertNotNull(x509 = wolfSSL_X509_load_certificate_buffer( + client_cert_der_2048, sizeof_client_cert_der_2048, + WOLFSSL_FILETYPE_ASN1)); + + t = 0; + not_before = XTIME(0); + not_after = XTIME(0) + (60 * 24 * 30); /* 30 days after */ + AssertNotNull(X509_time_adj(X509_get_notBefore(x509), not_before, &t)); + AssertNotNull(X509_time_adj(X509_get_notAfter(x509), not_after, &t)); + + X509_free(x509); + + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_X509(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM)\ + && !defined(NO_RSA) + X509* x509; + BIO* bio; + X509_STORE_CTX* ctx; + X509_STORE* store; + + char der[] = "certs/ca-cert.der"; + XFILE fp; + + printf(testingFmt, "wolfSSL_X509()"); + + AssertNotNull(x509 = X509_new()); + X509_free(x509); + + x509 = wolfSSL_X509_load_certificate_file(cliCertFile, SSL_FILETYPE_PEM); + + AssertNotNull(bio = BIO_new(BIO_s_mem())); + + AssertIntEQ(i2d_X509_bio(bio, x509), SSL_SUCCESS); + + AssertNotNull(ctx = X509_STORE_CTX_new()); + + AssertIntEQ(X509_verify_cert(ctx), SSL_FATAL_ERROR); + + AssertNotNull(store = X509_STORE_new()); + AssertIntEQ(X509_STORE_add_cert(store, x509), SSL_SUCCESS); + AssertIntEQ(X509_STORE_CTX_init(ctx, store, x509, NULL), SSL_SUCCESS); + AssertIntEQ(X509_verify_cert(ctx), SSL_SUCCESS); + + + X509_STORE_CTX_free(ctx); + #if defined(WOLFSSL_KEEP_STORE_CERTS) || defined(WOLFSSL_QT) + X509_STORE_free(store); + X509_free(x509); + #endif + BIO_free(bio); + + /** d2i_X509_fp test **/ + fp = XFOPEN(der, "rb"); + AssertTrue((fp != XBADFILE)); + AssertNotNull(x509 = (X509 *)d2i_X509_fp(fp, (X509 **)NULL)); + AssertNotNull(x509); + X509_free(x509); + XFCLOSE(fp); + fp = XFOPEN(der, "rb"); + AssertTrue((fp != XBADFILE)); + AssertNotNull((X509 *)d2i_X509_fp(fp, (X509 **)&x509)); + AssertNotNull(x509); + X509_free(x509); + XFCLOSE(fp); + + /* X509_up_ref test */ + AssertIntEQ(X509_up_ref(NULL), 0); + AssertNotNull(x509 = X509_new()); /* refCount = 1 */ + AssertIntEQ(X509_up_ref(x509), 1); /* refCount = 2 */ + AssertIntEQ(X509_up_ref(x509), 1); /* refCount = 3 */ + X509_free(x509); /* refCount = 2 */ + X509_free(x509); /* refCount = 1 */ + X509_free(x509); /* refCount = 0, free */ + + printf(resultFmt, passed); + #endif +} + +static void test_wolfSSL_X509_get_ext_count(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) + int ret = 0; + WOLFSSL_X509* x509; + const char ocspRootCaFile[] = "./certs/ocsp/root-ca-cert.pem"; + FILE* f; + + printf(testingFmt, "wolfSSL_X509_get_ext_count()"); + + /* NULL parameter check */ + AssertIntEQ(X509_get_ext_count(NULL), WOLFSSL_FAILURE); + + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(svrCertFile, + SSL_FILETYPE_PEM)); + AssertIntEQ(X509_get_ext_count(x509), 3); + wolfSSL_X509_free(x509); + + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(ocspRootCaFile, + SSL_FILETYPE_PEM)); + AssertIntEQ(X509_get_ext_count(x509), 5); + wolfSSL_X509_free(x509); + + AssertNotNull(f = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); + fclose(f); + + printf(testingFmt, "wolfSSL_X509_get_ext_count() valid input"); + AssertIntEQ((ret = wolfSSL_X509_get_ext_count(x509)), 3); + printf(resultFmt, ret == 3 ? passed : failed); + + printf(testingFmt, "wolfSSL_X509_get_ext_count() NULL argument"); + AssertIntEQ((ret = wolfSSL_X509_get_ext_count(NULL)), WOLFSSL_FAILURE); + printf(resultFmt, ret == WOLFSSL_FAILURE ? passed : failed); + + wolfSSL_X509_free(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_sign(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) + int ret; + X509_NAME *name; + X509 *x509; + EVP_PKEY *pub; + EVP_PKEY *priv; +#if defined(USE_CERT_BUFFERS_1024) + const unsigned char* rsaPriv = client_key_der_1024; + const unsigned char* rsaPub = client_keypub_der_1024; + long clientKeySz = (long)sizeof_client_key_der_1024; + long clientPubKeySz = (long)sizeof_client_keypub_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + const unsigned char* rsaPriv = client_key_der_2048; + const unsigned char* rsaPub = client_keypub_der_2048; + long clientKeySz = (long)sizeof_client_key_der_2048; + long clientPubKeySz = (long)sizeof_client_keypub_der_2048; +#endif + + printf(testingFmt, "wolfSSL_X509_sign\n"); + + /* Set X509_NAME fields */ + AssertNotNull(name = X509_NAME_new()); + AssertIntEQ(X509_NAME_add_entry_by_txt(name, "country", MBSTRING_UTF8, + (byte*)"US", 2, -1, 0), SSL_SUCCESS); + AssertIntEQ(X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_UTF8, + (byte*)"wolfssl.com", 11, -1, 0), SSL_SUCCESS); + AssertIntEQ(X509_NAME_add_entry_by_txt(name, "emailAddress", MBSTRING_UTF8, + (byte*)"support@wolfssl.com", 19, -1, 0), SSL_SUCCESS); + + /* Get private and public keys */ + AssertNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, &rsaPriv, + clientKeySz)); + AssertNotNull(pub = wolfSSL_d2i_PUBKEY(NULL, &rsaPub, clientPubKeySz)); + AssertNotNull(x509 = X509_new()); + /* Set version 3 */ + AssertIntNE(X509_set_version(x509, 2L), 0); + /* Set subject name, add pubkey, and sign certificate */ + AssertIntEQ(X509_set_subject_name(x509, name), SSL_SUCCESS); + AssertIntEQ(X509_set_pubkey(x509, pub), SSL_SUCCESS); +#ifdef WOLFSSL_ALT_NAMES + /* Add some subject alt names */ + AssertIntNE(wolfSSL_X509_add_altname(NULL, + NULL, ASN_DNS_TYPE), SSL_SUCCESS); + AssertIntEQ(wolfSSL_X509_add_altname(x509, + NULL, ASN_DNS_TYPE), SSL_SUCCESS); + AssertIntEQ(wolfSSL_X509_add_altname(x509, + "sphygmomanometer", + ASN_DNS_TYPE), SSL_SUCCESS); + AssertIntEQ(wolfSSL_X509_add_altname(x509, + "supercalifragilisticexpialidocious", + ASN_DNS_TYPE), SSL_SUCCESS); + AssertIntEQ(wolfSSL_X509_add_altname(x509, + "Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch", + ASN_DNS_TYPE), SSL_SUCCESS); +#endif /* WOLFSSL_ALT_NAMES */ + /* Test invalid parameters */ + AssertIntEQ(X509_sign(NULL, priv, EVP_sha256()), 0); + AssertIntEQ(X509_sign(x509, NULL, EVP_sha256()), 0); + AssertIntEQ(X509_sign(x509, priv, NULL), 0); + + ret = X509_sign(x509, priv, EVP_sha256()); + +#if 0 + /* example for writing to file */ + XFILE tmpFile = XFOPEN("./signed.der", "wb"); + if (tmpFile) { + int derSz = 0; + const byte* der = wolfSSL_X509_get_der(x509, &derSz); + XFWRITE(der, 1, derSz, tmpFile); + } + XFCLOSE(tmpFile); +#endif + +#ifndef WOLFSSL_ALT_NAMES + /* Valid case - size should be 798 */ + AssertIntEQ(ret, 798); +#else /* WOLFSSL_ALT_NAMES */ + /* Valid case - size should be 927 */ + AssertIntEQ(ret, 927); +#endif /* WOLFSSL_ALT_NAMES */ + + X509_NAME_free(name); + EVP_PKEY_free(priv); + EVP_PKEY_free(pub); + X509_free(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_get0_tbs_sigalg(void) +{ +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) + X509* x509 = NULL; + const X509_ALGOR* alg; + printf(testingFmt, "wolfSSL_X509_get0_tbs_sigalg"); + + AssertNotNull(x509 = X509_new()); + + AssertNull(alg = X509_get0_tbs_sigalg(NULL)); + AssertNotNull(alg = X509_get0_tbs_sigalg(x509)); + + X509_free(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_ALGOR_get0(void) +{ +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) && !defined(NO_SHA256) + X509* x509 = NULL; + const ASN1_OBJECT* obj = NULL; + const X509_ALGOR* alg; + int pptype = 0; + const void *ppval = NULL; + printf(testingFmt, "wolfSSL_X509_ALGOR_get0"); + + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(cliCertFile, + SSL_FILETYPE_PEM)); + AssertNotNull(alg = X509_get0_tbs_sigalg(x509)); + + /* Invalid case */ + X509_ALGOR_get0(&obj, NULL, NULL, NULL); + AssertNull(obj); + + /* Valid case */ + X509_ALGOR_get0(&obj, &pptype, &ppval, alg); + AssertNotNull(obj); + AssertNotNull(ppval); + AssertIntNE(pptype, 0); + /* Make sure NID of X509_ALGOR is Sha256 with RSA */ + AssertIntEQ(OBJ_obj2nid(obj), CTC_SHA256wRSA); + + X509_free(x509); + + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_X509_VERIFY_PARAM(void) +{ +#if defined(OPENSSL_EXTRA) + WOLFSSL_X509_VERIFY_PARAM *param; + int ret; + char testIPv4[] = "127.0.0.1"; + char testIPv6[] = "0001:0000:0000:0000:0000:0000:0000:0000/32"; + + printf(testingFmt, "wolfSSL_X509()"); + + /* Initializer function is not ported */ + /* param = wolfSSL_X509_VERIFY_PARAM_new(); */ + + param = (WOLFSSL_X509_VERIFY_PARAM *)XMALLOC( + sizeof(WOLFSSL_X509_VERIFY_PARAM), NULL, DYNAMIC_TYPE_OPENSSL); + AssertNotNull(param); + + XMEMSET(param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM )); + + wolfSSL_X509_VERIFY_PARAM_set_hostflags(NULL, 0x00); + + wolfSSL_X509_VERIFY_PARAM_set_hostflags(param, 0x01); + AssertIntEQ(0x01, param->hostFlags); + + ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(NULL, testIPv4); + AssertIntEQ(0, ret); + + ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, testIPv4); + AssertIntEQ(1, ret); + AssertIntEQ(0, XSTRNCMP(param->ipasc, testIPv4, WOLFSSL_MAX_IPSTR)); + + ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, NULL); + AssertIntEQ(1, ret); + + ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, testIPv6); + AssertIntEQ(1, ret); + AssertIntEQ(0, XSTRNCMP(param->ipasc, testIPv6, WOLFSSL_MAX_IPSTR)); + + XFREE(param, NULL, DYNAMIC_TYPE_OPENSSL); + + printf(resultFmt, passed); + +#endif +} + +static void test_wolfSSL_X509_get_X509_PUBKEY(void) +{ +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) + X509* x509 = NULL; + X509_PUBKEY* pubKey; + printf(testingFmt, "wolfSSL_X509_get_X509_PUBKEY"); + + AssertNotNull(x509 = X509_new()); + + AssertNull(pubKey = wolfSSL_X509_get_X509_PUBKEY(NULL)); + AssertNotNull(pubKey = wolfSSL_X509_get_X509_PUBKEY(x509)); + + X509_free(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_PUBKEY(void) +{ +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) && !defined(NO_SHA256) + X509* x509 = NULL; + ASN1_OBJECT* obj = NULL; + X509_PUBKEY* pubKey; + X509_PUBKEY* pubKey2; + EVP_PKEY* evpKey; + + const unsigned char *pk; + int ppklen; + WOLFSSL_X509_ALGOR *pa; + + printf(testingFmt, "wolfSSL_X509_get_X509_PUBKEY"); + + AssertNotNull(x509 = X509_load_certificate_file(cliCertFile, + SSL_FILETYPE_PEM)); + + AssertNotNull(pubKey = X509_get_X509_PUBKEY(x509)); + AssertIntEQ(X509_PUBKEY_get0_param(&obj, &pk, &ppklen, &pa, pubKey), 1); + AssertNotNull(pk); + AssertNotNull(pa); + AssertNotNull(pubKey); + AssertIntGT(ppklen, 0); + + AssertIntEQ(OBJ_obj2nid(obj), RSAk); + + AssertNotNull(evpKey = X509_PUBKEY_get(pubKey)); + AssertNotNull(pubKey2 = X509_PUBKEY_new()); + AssertIntEQ(X509_PUBKEY_set(&pubKey2, evpKey), 1); + + X509_PUBKEY_free(pubKey2); + X509_free(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_RAND(void) +{ + #if defined(OPENSSL_EXTRA) + byte seed[16]; + + printf(testingFmt, "wolfSSL_RAND()"); + + RAND_seed(seed, sizeof(seed)); + AssertIntEQ(RAND_poll(), 1); + RAND_cleanup(); + + AssertIntEQ(RAND_egd(NULL), -1); +#ifndef NO_FILESYSTEM + { + char fname[100]; + + AssertNotNull(RAND_file_name(fname, (sizeof(fname) - 1))); + AssertIntEQ(RAND_write_file(NULL), 0); + } +#endif + + printf(resultFmt, passed); + #endif +} + + +static void test_wolfSSL_BUF(void) +{ + #if defined(OPENSSL_EXTRA) + BUF_MEM* buf; + AssertNotNull(buf = BUF_MEM_new()); + AssertIntEQ(BUF_MEM_grow(buf, 10), 10); + AssertIntEQ(BUF_MEM_grow(buf, -1), 0); + BUF_MEM_free(buf); + #endif /* OPENSSL_EXTRA */ +} + + +static void test_wolfSSL_pseudo_rand(void) +{ + #if defined(OPENSSL_EXTRA) + BIGNUM* bn; + unsigned char bin[8]; + int i; + + printf(testingFmt, "wolfSSL_pseudo_rand()"); + + /* BN_pseudo_rand returns 1 on success 0 on failure + * int BN_pseudo_rand(BIGNUM* bn, int bits, int top, int bottom) */ + for (i = 0; i < 10; i++) { + AssertNotNull(bn = BN_new()); + AssertIntEQ(BN_pseudo_rand(bn, 8, 0, 0), SSL_SUCCESS); + AssertIntGT(BN_bn2bin(bn, bin),0); + AssertIntEQ((bin[0] & 0x80), 0x80); /* top bit should be set */ + BN_free(bn); + } + + for (i = 0; i < 10; i++) { + AssertNotNull(bn = BN_new()); + AssertIntEQ(BN_pseudo_rand(bn, 8, 1, 1), SSL_SUCCESS); + AssertIntGT(BN_bn2bin(bn, bin),0); + AssertIntEQ((bin[0] & 0xc1), 0xc1); /* top bit should be set */ + BN_free(bn); + } + + printf(resultFmt, passed); + #endif +} + +static void test_wolfSSL_PKCS8_Compat(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && defined(HAVE_ECC) + PKCS8_PRIV_KEY_INFO* pt; + BIO* bio; + XFILE f; + int bytes; + char pkcs8_buffer[512]; + + printf(testingFmt, "wolfSSL_pkcs8()"); + + /* file from wolfssl/certs/ directory */ + f = XFOPEN("./certs/ecc-keyPkcs8.pem", "rb"); + AssertTrue(f != XBADFILE); + AssertIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), f)), 0); + XFCLOSE(f); + AssertNotNull(bio = BIO_new_mem_buf((void*)pkcs8_buffer, bytes)); + AssertNotNull(pt = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, NULL)); + BIO_free(bio); + PKCS8_PRIV_KEY_INFO_free(pt); + + printf(resultFmt, passed); + #endif +} + +static void test_wolfSSL_PKCS8_d2i(void) +{ +#ifndef HAVE_FIPS + /* This test ends up using HMAC as a part of PBKDF2, and HMAC + * requires a 12 byte password in FIPS mode. This test ends up + * trying to use an 8 byte password. */ +#ifdef OPENSSL_ALL + WOLFSSL_EVP_PKEY* pkey = NULL; +#ifndef NO_FILESYSTEM + unsigned char pkcs8_buffer[2048]; + const unsigned char* p; + int bytes; + XFILE file; + BIO* bio; + WOLFSSL_EVP_PKEY* evpPkey = NULL; +#endif + #ifndef NO_RSA + #ifndef NO_FILESYSTEM + const char rsaDerPkcs8File[] = "./certs/server-keyPkcs8.der"; + const char rsaPemPkcs8File[] = "./certs/server-keyPkcs8.pem"; +#ifndef NO_DES3 + const char rsaDerPkcs8EncFile[] = "./certs/server-keyPkcs8Enc.der"; +#endif + #endif + #ifdef USE_CERT_BUFFERS_1024 + const unsigned char* rsa = (unsigned char*)server_key_der_1024; + int rsaSz = sizeof_server_key_der_1024; + #else + const unsigned char* rsa = (unsigned char*)server_key_der_2048; + int rsaSz = sizeof_server_key_der_2048; + #endif + #endif + #ifdef HAVE_ECC + const unsigned char* ec = (unsigned char*)ecc_key_der_256; + int ecSz = sizeof_ecc_key_der_256; + #ifndef NO_FILESYSTEM + const char ecDerPkcs8File[] = "certs/ecc-keyPkcs8.der"; + const char ecPemPkcs8File[] = "certs/ecc-keyPkcs8.pem"; +#ifndef NO_DES3 + const char ecDerPkcs8EncFile[] = "certs/ecc-keyPkcs8Enc.der"; +#endif + #endif + #endif + +#ifndef NO_FILESYSTEM + (void)pkcs8_buffer; + (void)p; + (void)bytes; + (void)file; + (void)bio; +#endif + + #ifndef NO_RSA + /* Try to auto-detect normal RSA private key */ + AssertNotNull(pkey = d2i_AutoPrivateKey(NULL, &rsa, rsaSz)); + wolfSSL_EVP_PKEY_free(pkey); + #endif + #ifdef HAVE_ECC + /* Try to auto-detect normal EC private key */ + AssertNotNull(pkey = d2i_AutoPrivateKey(NULL, &ec, ecSz)); + wolfSSL_EVP_PKEY_free(pkey); + #endif + #ifndef NO_FILESYSTEM + #ifndef NO_RSA + /* Get DER encoded RSA PKCS#8 data. */ + file = XFOPEN(rsaDerPkcs8File, "rb"); + AssertTrue(file != XBADFILE); + AssertIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), + file)), 0); + XFCLOSE(file); + p = pkcs8_buffer; + /* Try to decode - auto-detect key type. */ + AssertNotNull(pkey = d2i_AutoPrivateKey(NULL, &p, bytes)); + /* Get PEM encoded RSA PKCS#8 data. */ + file = XFOPEN(rsaPemPkcs8File, "rb"); + AssertTrue(file != XBADFILE); + AssertIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), + file)), 0); + XFCLOSE(file); + AssertNotNull(bio = BIO_new(BIO_s_mem())); + /* Write PKCS#8 PEM to BIO. */ + AssertIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, NULL, NULL, 0, NULL, + NULL), bytes); + /* Compare file and written data */ + AssertIntEQ(wolfSSL_BIO_get_mem_data(bio, &p), bytes); + AssertIntEQ(XMEMCMP(p, pkcs8_buffer, bytes), 0); + BIO_free(bio); +#ifndef NO_DES3 + AssertNotNull(bio = BIO_new(BIO_s_mem())); + /* Write Encrypted PKCS#8 PEM to BIO. */ + bytes = 1834; + AssertIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_des_ede3_cbc(), + NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); + AssertNotNull(evpPkey = PEM_read_bio_PrivateKey(bio, NULL, PasswordCallBack, + (void*)"yassl123")); + wolfSSL_EVP_PKEY_free(evpPkey); + BIO_free(bio); +#endif + wolfSSL_EVP_PKEY_free(pkey); + + /* PKCS#8 encrypted RSA key */ +#ifndef NO_DES3 + file = XFOPEN(rsaDerPkcs8EncFile, "rb"); + AssertTrue(file != XBADFILE); + AssertIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), + file)), 0); + XFCLOSE(file); + AssertNotNull(bio = BIO_new_mem_buf((void*)pkcs8_buffer, bytes)); + AssertNotNull(pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, PasswordCallBack, + (void*)"yassl123")); + wolfSSL_EVP_PKEY_free(pkey); + BIO_free(bio); +#endif + #endif + #ifdef HAVE_ECC + /* PKCS#8 encode EC key */ + file = XFOPEN(ecDerPkcs8File, "rb"); + AssertTrue(file != XBADFILE); + AssertIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), + file)), 0); + XFCLOSE(file); + p = pkcs8_buffer; + /* Try to decode - auto-detect key type. */ + AssertNotNull(pkey = d2i_AutoPrivateKey(NULL, &p, bytes)); + /* Get PEM encoded RSA PKCS#8 data. */ + file = XFOPEN(ecPemPkcs8File, "rb"); + AssertTrue(file != XBADFILE); + AssertIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), + file)), 0); + XFCLOSE(file); + AssertNotNull(bio = BIO_new(BIO_s_mem())); + /* Write PKCS#8 PEM to BIO. */ + AssertIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, NULL, NULL, 0, NULL, + NULL), bytes); + /* Compare file and written data */ + AssertIntEQ(wolfSSL_BIO_get_mem_data(bio, &p), bytes); + AssertIntEQ(XMEMCMP(p, pkcs8_buffer, bytes), 0); + BIO_free(bio); + AssertNotNull(bio = BIO_new(BIO_s_mem())); + /* Write Encrypted PKCS#8 PEM to BIO. */ + bytes = 379; + AssertIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_aes_256_cbc(), + NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); + AssertNotNull(evpPkey = PEM_read_bio_PrivateKey(bio, NULL, PasswordCallBack, + (void*)"yassl123")); + wolfSSL_EVP_PKEY_free(evpPkey); + BIO_free(bio); + wolfSSL_EVP_PKEY_free(pkey); + + /* PKCS#8 encrypted EC key */ +#ifndef NO_DES3 + file = XFOPEN(ecDerPkcs8EncFile, "rb"); + AssertTrue(file != XBADFILE); + AssertIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), + file)), 0); + XFCLOSE(file); + AssertNotNull(bio = BIO_new_mem_buf((void*)pkcs8_buffer, bytes)); + AssertNotNull(pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, PasswordCallBack, + (void*)"yassl123")); + wolfSSL_EVP_PKEY_free(pkey); + BIO_free(bio); +#endif + #endif + #endif + + printf(resultFmt, passed); +#endif +#endif /* HAVE_FIPS */ +} + +static void test_wolfSSL_ERR_put_error(void) +{ + #if !defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && \ + defined(DEBUG_WOLFSSL) + const char* file; + int line; + + printf(testingFmt, "wolfSSL_ERR_put_error()"); + + + ERR_clear_error(); /* clear out any error nodes */ + ERR_put_error(0,SYS_F_ACCEPT, 0, "this file", 0); + AssertIntEQ(ERR_get_error_line(&file, &line), 0); + ERR_put_error(0,SYS_F_BIND, 1, "this file", 1); + AssertIntEQ(ERR_get_error_line(&file, &line), 1); + ERR_put_error(0,SYS_F_CONNECT, 2, "this file", 2); + AssertIntEQ(ERR_get_error_line(&file, &line), 2); + ERR_put_error(0,SYS_F_FOPEN, 3, "this file", 3); + AssertIntEQ(ERR_get_error_line(&file, &line), 3); + ERR_put_error(0,SYS_F_FREAD, 4, "this file", 4); + AssertIntEQ(ERR_get_error_line(&file, &line), 4); + ERR_put_error(0,SYS_F_GETADDRINFO, 5, "this file", 5); + AssertIntEQ(ERR_get_error_line(&file, &line), 5); + ERR_put_error(0,SYS_F_GETSOCKOPT, 6, "this file", 6); + AssertIntEQ(ERR_get_error_line(&file, &line), 6); + ERR_put_error(0,SYS_F_GETSOCKNAME, 7, "this file", 7); + AssertIntEQ(ERR_get_error_line(&file, &line), 7); + ERR_put_error(0,SYS_F_GETHOSTBYNAME, 8, "this file", 8); + AssertIntEQ(ERR_get_error_line(&file, &line), 8); + ERR_put_error(0,SYS_F_GETNAMEINFO, 9, "this file", 9); + AssertIntEQ(ERR_get_error_line(&file, &line), 9); + ERR_put_error(0,SYS_F_GETSERVBYNAME, 10, "this file", 10); + AssertIntEQ(ERR_get_error_line(&file, &line), 10); + ERR_put_error(0,SYS_F_IOCTLSOCKET, 11, "this file", 11); + AssertIntEQ(ERR_get_error_line(&file, &line), 11); + ERR_put_error(0,SYS_F_LISTEN, 12, "this file", 12); + AssertIntEQ(ERR_get_error_line(&file, &line), 12); + ERR_put_error(0,SYS_F_OPENDIR, 13, "this file", 13); + AssertIntEQ(ERR_get_error_line(&file, &line), 13); + ERR_put_error(0,SYS_F_SETSOCKOPT, 14, "this file", 14); + AssertIntEQ(ERR_get_error_line(&file, &line), 14); + ERR_put_error(0,SYS_F_SOCKET, 15, "this file", 15); + AssertIntEQ(ERR_get_error_line(&file, &line), 15); + + /* try reading past end of error queue */ + file = NULL; + AssertIntEQ(ERR_get_error_line(&file, &line), 0); + AssertNull(file); + AssertIntEQ(ERR_get_error_line_data(&file, &line, NULL, NULL), 0); + + PEMerr(4,4); + AssertIntEQ(ERR_get_error(), 4); + /* Empty and free up all error nodes */ + ERR_clear_error(); + + /* Verify all nodes are cleared */ + ERR_put_error(0,SYS_F_ACCEPT, 0, "this file", 0); + ERR_clear_error(); + AssertIntEQ(ERR_get_error_line(&file, &line), 0); + + printf(resultFmt, passed); + #endif +} + + +static void test_wolfSSL_ERR_print_errors(void) +{ + #if !defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && \ + defined(DEBUG_WOLFSSL) + BIO* bio; + char buf[1024]; + + printf(testingFmt, "wolfSSL_ERR_print_errors()"); + + + AssertNotNull(bio = BIO_new(BIO_s_mem())); + ERR_clear_error(); /* clear out any error nodes */ + ERR_put_error(0,SYS_F_ACCEPT, -173, "ssl.c", 0); + ERR_put_error(0,SYS_F_BIND, -275, "asn.c", 100); + + ERR_print_errors(bio); + AssertIntEQ(BIO_gets(bio, buf, sizeof(buf)), 56); + AssertIntEQ(XSTRNCMP("error:173:wolfSSL library:Bad function argument:ssl.c:0", + buf, 55), 0); + AssertIntEQ(BIO_gets(bio, buf, sizeof(buf)), 57); + AssertIntEQ(XSTRNCMP("error:275:wolfSSL library:unknown error number:asn.c:100", + buf, 56), 0); + AssertIntEQ(BIO_gets(bio, buf, sizeof(buf)), 0); + AssertIntEQ(ERR_get_error_line(NULL, NULL), 0); + + BIO_free(bio); + printf(resultFmt, passed); + #endif +} + +#if !defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && \ + defined(DEBUG_WOLFSSL) +static int test_wolfSSL_error_cb(const char *str, size_t len, void *u) +{ + wolfSSL_BIO_write((BIO*)u, str, (int)len); + return 0; +} +#endif + +static void test_wolfSSL_ERR_print_errors_cb(void) +{ + #if !defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && \ + defined(DEBUG_WOLFSSL) + BIO* bio; + char buf[1024]; + + printf(testingFmt, "wolfSSL_ERR_print_errors_cb()"); + + AssertNotNull(bio = BIO_new(BIO_s_mem())); + ERR_clear_error(); /* clear out any error nodes */ + ERR_put_error(0,SYS_F_ACCEPT, -173, "ssl.c", 0); + ERR_put_error(0,SYS_F_BIND, -275, "asn.c", 100); + + ERR_print_errors_cb(test_wolfSSL_error_cb, bio); + AssertIntEQ(BIO_gets(bio, buf, sizeof(buf)), 108); + AssertIntEQ(XSTRNCMP("wolfSSL error occurred, error = 173 line:0 file:ssl.c", + buf, 53), 0); + AssertIntEQ(XSTRNCMP("wolfSSL error occurred, error = 275 line:100 file:asn.c", + buf + 53, 55), 0); + AssertIntEQ(BIO_gets(bio, buf, sizeof(buf)), 0); + + BIO_free(bio); + printf(resultFmt, passed); + #endif +} + +static void test_wolfSSL_HMAC(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_SHA256) + HMAC_CTX* hmac; + ENGINE* e = NULL; + const unsigned char key[] = "simple test key"; + unsigned char hash[WC_MAX_DIGEST_SIZE]; + unsigned int len; + + + printf(testingFmt, "wolfSSL_HMAC()"); + + AssertNotNull(hmac = HMAC_CTX_new()); + HMAC_CTX_init(hmac); + AssertIntEQ(HMAC_Init_ex(hmac, (void*)key, (int)sizeof(key), + EVP_sha256(), e), SSL_SUCCESS); + + /* re-using test key as data to hash */ + AssertIntEQ(HMAC_Update(hmac, key, (int)sizeof(key)), SSL_SUCCESS); + AssertIntEQ(HMAC_Update(hmac, NULL, 0), SSL_SUCCESS); + AssertIntEQ(HMAC_Final(hmac, hash, &len), SSL_SUCCESS); + AssertIntEQ(len, (int)WC_SHA256_DIGEST_SIZE); + AssertIntEQ(HMAC_size(hmac), WC_SHA256_DIGEST_SIZE); + + HMAC_cleanup(hmac); + HMAC_CTX_free(hmac); +#endif + +#if defined(OPENSSL_EXTRA) && !defined(NO_SHA256) + len = 0; + AssertNotNull(HMAC(EVP_sha256(), key, (int)sizeof(key), NULL, 0, hash, &len)); + AssertIntEQ(len, (int)WC_SHA256_DIGEST_SIZE); +#endif +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SHA224) + len = 0; + AssertNotNull(HMAC(EVP_sha224(), key, (int)sizeof(key), NULL, 0, hash, &len)); + AssertIntEQ(len, (int)WC_SHA224_DIGEST_SIZE); +#endif +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SHA384) + len = 0; + AssertNotNull(HMAC(EVP_sha384(), key, (int)sizeof(key), NULL, 0, hash, &len)); + AssertIntEQ(len, (int)WC_SHA384_DIGEST_SIZE); +#endif +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SHA512) + len = 0; + AssertNotNull(HMAC(EVP_sha512(), key, (int)sizeof(key), NULL, 0, hash, &len)); + AssertIntEQ(len, (int)WC_SHA512_DIGEST_SIZE); +#endif + + printf(resultFmt, passed); + +} + + +static void test_wolfSSL_OBJ(void) +{ +/* Password "wolfSSL test" is only 12 (96-bit) too short for testing in FIPS + * mode + */ +#if defined(OPENSSL_EXTRA) && !defined(NO_SHA256) && !defined(NO_ASN) && \ + !defined(HAVE_FIPS) && !defined(NO_SHA) && defined(WOLFSSL_CERT_EXT) && \ + defined(WOLFSSL_CERT_GEN) + ASN1_OBJECT *obj = NULL; + char buf[50]; + + XFILE fp; + X509 *x509 = NULL; + X509_NAME *x509Name; + X509_NAME_ENTRY *x509NameEntry; + ASN1_OBJECT *asn1Name = NULL; + int numNames; + BIO *bio = NULL; + int nid; + int i, j; + const char *f[] = { + #ifndef NO_RSA + "./certs/ca-cert.der", + #endif + #ifdef HAVE_ECC + "./certs/ca-ecc-cert.der", + "./certs/ca-ecc384-cert.der", + #endif + NULL}; + ASN1_OBJECT *field_name_obj = NULL; + int lastpos = -1; + int tmp = -1; + ASN1_STRING *asn1 = NULL; + unsigned char *buf_dyn = NULL; + + PKCS12 *p12; + int boolRet; + EVP_PKEY *pkey = NULL; + const char *p12_f[] = { + #if !defined(NO_DES3) && !defined(NO_RSA) + "./certs/test-servercert.p12", + #endif + NULL}; + + printf(testingFmt, "wolfSSL_OBJ()"); + + AssertIntEQ(OBJ_obj2txt(buf, (int)sizeof(buf), obj, 1), SSL_FAILURE); + AssertNotNull(obj = OBJ_nid2obj(NID_any_policy)); + AssertIntEQ(OBJ_obj2nid(obj), NID_any_policy); + AssertIntEQ(OBJ_obj2txt(buf, (int)sizeof(buf), obj, 1), 11); + AssertIntGT(OBJ_obj2txt(buf, (int)sizeof(buf), obj, 0), 0); + ASN1_OBJECT_free(obj); + + AssertNotNull(obj = OBJ_nid2obj(NID_sha256)); + AssertIntEQ(OBJ_obj2nid(obj), NID_sha256); + AssertIntEQ(OBJ_obj2txt(buf, (int)sizeof(buf), obj, 1), 22); +#ifdef WOLFSSL_CERT_EXT + AssertIntEQ(OBJ_txt2nid(buf), NID_sha256); +#endif + AssertIntGT(OBJ_obj2txt(buf, (int)sizeof(buf), obj, 0), 0); + ASN1_OBJECT_free(obj); + + for (i = 0; f[i] != NULL; i++) + { + AssertTrue((fp = XFOPEN(f[i], "r")) != XBADFILE); + AssertNotNull(x509 = d2i_X509_fp(fp, NULL)); + XFCLOSE(fp); + AssertNotNull(x509Name = X509_get_issuer_name(x509)); + AssertIntNE((numNames = X509_NAME_entry_count(x509Name)), 0); + + /* Get the Common Name by using OBJ_txt2obj */ + AssertNotNull(field_name_obj = OBJ_txt2obj("CN", 0)); + do + { + lastpos = tmp; + tmp = X509_NAME_get_index_by_OBJ(x509Name, field_name_obj, lastpos); + } while (tmp > -1); + AssertIntNE(lastpos, -1); + ASN1_OBJECT_free(field_name_obj); + AssertNotNull(x509NameEntry = X509_NAME_get_entry(x509Name, lastpos)); + AssertNotNull(asn1 = X509_NAME_ENTRY_get_data(x509NameEntry)); + AssertIntGE(ASN1_STRING_to_UTF8(&buf_dyn, asn1), 0); + /* + * All Common Names should be www.wolfssl.com + * This makes testing easier as we can test for the expected value. + */ + AssertStrEQ((char*)buf_dyn, "www.wolfssl.com"); + OPENSSL_free(buf_dyn); + + AssertTrue((bio = BIO_new(BIO_s_mem())) != NULL); + for (j = 0; j < numNames; j++) + { + AssertNotNull(x509NameEntry = X509_NAME_get_entry(x509Name, j)); + AssertNotNull(asn1Name = X509_NAME_ENTRY_get_object(x509NameEntry)); + AssertTrue((nid = OBJ_obj2nid(asn1Name)) > 0); + } + BIO_free(bio); + ASN1_OBJECT_free(asn1Name); + X509_free(x509); + + } + + for (i = 0; p12_f[i] != NULL; i++) + { + AssertTrue((fp = XFOPEN(p12_f[i], "r")) != XBADFILE); + AssertNotNull(p12 = d2i_PKCS12_fp(fp, NULL)); + XFCLOSE(fp); + AssertTrue((boolRet = PKCS12_parse(p12, "wolfSSL test", &pkey, &x509, NULL)) > 0); + wc_PKCS12_free(p12); + EVP_PKEY_free(pkey); + AssertNotNull((x509Name = X509_get_issuer_name(x509)) != NULL); + AssertIntNE((numNames = X509_NAME_entry_count(x509Name)), 0); + AssertTrue((bio = BIO_new(BIO_s_mem())) != NULL); + for (j = 0; j < numNames; j++) + { + AssertNotNull(x509NameEntry = X509_NAME_get_entry(x509Name, j)); + AssertNotNull(asn1Name = X509_NAME_ENTRY_get_object(x509NameEntry)); + AssertTrue((nid = OBJ_obj2nid(asn1Name)) > 0); + } + BIO_free(bio); + ASN1_OBJECT_free(asn1Name); + X509_free(x509); + } + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_i2a_ASN1_OBJECT(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + ASN1_OBJECT *obj = NULL; + BIO *bio = NULL; + + AssertNotNull(obj = OBJ_nid2obj(NID_sha256)); + AssertTrue((bio = BIO_new(BIO_s_mem())) != NULL); + + AssertIntGT(wolfSSL_i2a_ASN1_OBJECT(bio, obj), 0); + AssertIntGT(wolfSSL_i2a_ASN1_OBJECT(bio, NULL), 0); + + AssertIntEQ(wolfSSL_i2a_ASN1_OBJECT(NULL, obj), 0); + + BIO_free(bio); + ASN1_OBJECT_free(obj); +#endif +} + +static void test_wolfSSL_OBJ_cmp(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_SHA256) + ASN1_OBJECT *obj = NULL; + ASN1_OBJECT *obj2 = NULL; + + printf(testingFmt, "wolfSSL_OBJ_cmp()"); + + AssertNotNull(obj = OBJ_nid2obj(NID_any_policy)); + AssertNotNull(obj2 = OBJ_nid2obj(NID_sha256)); + + AssertIntEQ(OBJ_cmp(NULL, NULL), WOLFSSL_FATAL_ERROR); + AssertIntEQ(OBJ_cmp(obj, NULL), WOLFSSL_FATAL_ERROR); + AssertIntEQ(OBJ_cmp(NULL, obj2), WOLFSSL_FATAL_ERROR); + AssertIntEQ(OBJ_cmp(obj, obj2), WOLFSSL_FATAL_ERROR); + AssertIntEQ(OBJ_cmp(obj, obj), 0); + AssertIntEQ(OBJ_cmp(obj2, obj2), 0); + + ASN1_OBJECT_free(obj); + ASN1_OBJECT_free(obj2); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_OBJ_txt2nid(void) +{ +#if !defined(NO_WOLFSSL_STUB) && defined(WOLFSSL_APACHE_HTTPD) + int i; + static const struct { + const char* sn; + const char* ln; + const char* oid; + int nid; + } testVals[] = { + { "tlsfeature", "TLS Feature", "1.3.6.1.5.5.7.1.24", NID_tlsfeature }, + { "id-on-dnsSRV", "SRVName", "1.3.6.1.5.5.7.8.7", + NID_id_on_dnsSRV }, + { "msUPN", "Microsoft User Principal Name", + "1.3.6.1.4.1.311.20.2.3", NID_ms_upn }, + { NULL, NULL, NULL, NID_undef } + }; + + printf(testingFmt, "wolfSSL_OBJ_txt2nid()"); + + /* Invalid cases */ + AssertIntEQ(OBJ_txt2nid(NULL), NID_undef); + AssertIntEQ(OBJ_txt2nid("Bad name"), NID_undef); + + /* Valid cases */ + for (i = 0; testVals[i].sn != NULL; i++) { + AssertIntEQ(OBJ_txt2nid(testVals[i].sn), testVals[i].nid); + AssertIntEQ(OBJ_txt2nid(testVals[i].ln), testVals[i].nid); + AssertIntEQ(OBJ_txt2nid(testVals[i].oid), testVals[i].nid); + } + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_OBJ_txt2obj(void) +{ +#if defined(WOLFSSL_APACHE_HTTPD) || (defined(OPENSSL_EXTRA) && \ + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)) + int i; + char buf[50]; + ASN1_OBJECT* obj; + static const struct { + const char* oidStr; + const char* sn; + const char* ln; + } objs_list[] = { + #if defined(WOLFSSL_APACHE_HTTPD) + { "1.3.6.1.5.5.7.1.24", "tlsfeature", "TLS Feature" }, + { "1.3.6.1.5.5.7.8.7", "id-on-dnsSRV", "SRVName" }, + #endif + { "2.5.29.19", "basicConstraints", "X509v3 Basic Constraints"}, + { NULL, NULL, NULL } + }; + + printf(testingFmt, "wolfSSL_OBJ_txt2obj()"); + + AssertNull(obj = OBJ_txt2obj("Bad name", 0)); + AssertNull(obj = OBJ_txt2obj(NULL, 0)); + + for (i = 0; objs_list[i].oidStr != NULL; i++) { + /* Test numerical value of oid (oidStr) */ + AssertNotNull(obj = OBJ_txt2obj(objs_list[i].oidStr, 1)); + /* Convert object back to text to confirm oid is correct */ + wolfSSL_OBJ_obj2txt(buf, (int)sizeof(buf), obj, 1); + AssertIntEQ(XSTRNCMP(buf, objs_list[i].oidStr, (int)XSTRLEN(buf)), 0); + ASN1_OBJECT_free(obj); + XMEMSET(buf, 0, sizeof(buf)); + + /* Test short name (sn) */ + AssertNull(obj = OBJ_txt2obj(objs_list[i].sn, 1)); + AssertNotNull(obj = OBJ_txt2obj(objs_list[i].sn, 0)); + /* Convert object back to text to confirm oid is correct */ + wolfSSL_OBJ_obj2txt(buf, (int)sizeof(buf), obj, 1); + AssertIntEQ(XSTRNCMP(buf, objs_list[i].oidStr, (int)XSTRLEN(buf)), 0); + ASN1_OBJECT_free(obj); + XMEMSET(buf, 0, sizeof(buf)); + + /* Test long name (ln) - should fail when no_name = 1 */ + AssertNull(obj = OBJ_txt2obj(objs_list[i].ln, 1)); + AssertNotNull(obj = OBJ_txt2obj(objs_list[i].ln, 0)); + /* Convert object back to text to confirm oid is correct */ + wolfSSL_OBJ_obj2txt(buf, (int)sizeof(buf), obj, 1); + AssertIntEQ(XSTRNCMP(buf, objs_list[i].oidStr, (int)XSTRLEN(buf)), 0); + ASN1_OBJECT_free(obj); + XMEMSET(buf, 0, sizeof(buf)); + } + + printf(resultFmt, passed); + +#endif +} + +static void test_wolfSSL_X509_NAME_ENTRY(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ + !defined(NO_RSA) && defined(WOLFSSL_CERT_GEN) + X509* x509; + BIO* bio; + X509_NAME* nm; + X509_NAME_ENTRY* entry; + unsigned char cn[] = "another name to add"; + + + printf(testingFmt, "wolfSSL_X509_NAME_ENTRY()"); + + AssertNotNull(x509 = + wolfSSL_X509_load_certificate_file(cliCertFile, SSL_FILETYPE_PEM)); + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertIntEQ(PEM_write_bio_X509_AUX(bio, x509), SSL_SUCCESS); + +#ifdef WOLFSSL_CERT_REQ + { + X509_REQ* req; + BIO* bReq; + + AssertNotNull(req = + wolfSSL_X509_load_certificate_file(cliCertFile, SSL_FILETYPE_PEM)); + AssertNotNull(bReq = BIO_new(BIO_s_mem())); + AssertIntEQ(PEM_write_bio_X509_REQ(bReq, req), SSL_SUCCESS); + + BIO_free(bReq); + X509_free(req); + } +#endif + + AssertNotNull(nm = X509_get_subject_name(x509)); + + /* Test add entry */ + AssertNotNull(entry = X509_NAME_ENTRY_create_by_NID(NULL, NID_commonName, + 0x0c, cn, (int)sizeof(cn))); + AssertIntEQ(X509_NAME_add_entry(nm, entry, -1, 0), SSL_SUCCESS); + +#ifdef WOLFSSL_CERT_EXT + AssertIntEQ(X509_NAME_add_entry_by_txt(nm, "emailAddress", MBSTRING_UTF8, + (byte*)"support@wolfssl.com", 19, -1, + 1), WOLFSSL_SUCCESS); +#endif + X509_NAME_ENTRY_free(entry); + + /* Test add entry by text */ + AssertNotNull(entry = X509_NAME_ENTRY_create_by_txt(NULL, "commonName", + 0x0c, cn, (int)sizeof(cn))); + #if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) \ + || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) + AssertNull(X509_NAME_ENTRY_create_by_txt(&entry, "unknown", + V_ASN1_UTF8STRING, cn, (int)sizeof(cn))); + #endif + AssertIntEQ(X509_NAME_add_entry(nm, entry, -1, 0), SSL_SUCCESS); + X509_NAME_ENTRY_free(entry); + + /* Test add entry by NID */ + AssertIntEQ(X509_NAME_add_entry_by_NID(nm, NID_commonName, MBSTRING_UTF8, + cn, -1, -1, 0), WOLFSSL_SUCCESS); + + BIO_free(bio); + X509_free(x509); /* free's nm */ + + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_X509_set_name(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) + X509* x509; + X509_NAME* name; + + printf(testingFmt, "wolfSSL_X509_set_name()"); + + AssertNotNull(name = X509_NAME_new()); + AssertIntEQ(X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_UTF8, + (byte*)"wolfssl.com", 11, 0, 1), + WOLFSSL_SUCCESS); + AssertIntEQ(X509_NAME_add_entry_by_txt(name, "emailAddress", MBSTRING_UTF8, + (byte*)"support@wolfssl.com", 19, -1, + 1), WOLFSSL_SUCCESS); + AssertNotNull(x509 = X509_new()); + + AssertIntEQ(X509_set_subject_name(NULL, NULL), WOLFSSL_FAILURE); + AssertIntEQ(X509_set_subject_name(x509, NULL), WOLFSSL_FAILURE); + AssertIntEQ(X509_set_subject_name(NULL, name), WOLFSSL_FAILURE); + AssertIntEQ(X509_set_subject_name(x509, name), WOLFSSL_SUCCESS); + + AssertIntEQ(X509_set_issuer_name(NULL, NULL), WOLFSSL_FAILURE); + AssertIntEQ(X509_set_issuer_name(x509, NULL), WOLFSSL_FAILURE); + AssertIntEQ(X509_set_issuer_name(NULL, name), WOLFSSL_FAILURE); + AssertIntEQ(X509_set_issuer_name(x509, name), WOLFSSL_SUCCESS); + + X509_free(x509); + X509_NAME_free(name); + + printf(resultFmt, passed); +#endif /* OPENSSL_ALL && !NO_CERTS */ +} + +static void test_wolfSSL_X509_set_notAfter(void) +{ +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) \ + && !defined(NO_ASN_TIME) && !defined(USER_TIME) && \ + !defined(TIME_OVERRIDES) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) &&\ + !defined(TIME_T_NOT_64BIT) && !defined(NO_64BIT) + /* Generalized time will overflow time_t if not long */ + + X509* x; + BIO* bio; + ASN1_TIME *asn_time, *time_check; + const int year = 365*24*60*60; + const int day = 24*60*60; + const int hour = 60*60; + const int mini = 60; + int offset_day; + unsigned char buf[25]; + time_t t; + + printf(testingFmt, "wolfSSL_X509_set_notAfter()"); + /* + * Setup asn_time. APACHE HTTPD uses time(NULL) + */ + t = (time_t)107 * year + 31 * day + 34 * hour + 30 * mini + 7 * day; + offset_day = 7; + /* + * Free these. + */ + asn_time = wolfSSL_ASN1_TIME_adj(NULL, t, offset_day, 0); + AssertNotNull(asn_time); + AssertNotNull(x = X509_new()); + AssertNotNull(bio = BIO_new(BIO_s_mem())); + /* + * Tests + */ + AssertTrue(wolfSSL_X509_set_notAfter(x, asn_time)); + /* time_check is simply (ANS1_TIME*)x->notAfter */ + AssertNotNull(time_check = X509_get_notAfter(x)); + /* ANS1_TIME_check validates by checking if argument can be parsed */ + AssertIntEQ(ASN1_TIME_check(time_check), WOLFSSL_SUCCESS); + /* Convert to human readable format and compare to intended date */ + AssertIntEQ(ASN1_TIME_print(bio, time_check), 1); + AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 24); + AssertIntEQ(XMEMCMP(buf, "Jan 20 10:30:00 2077 GMT", sizeof(buf) - 1), 0); + /* + * Cleanup + */ + XFREE(asn_time,NULL,DYNAMIC_TYPE_OPENSSL); + X509_free(x); + BIO_free(bio); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_set_notBefore(void) +{ +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) \ + && !defined(NO_ASN_TIME) && !defined(USER_TIME) && \ + !defined(TIME_OVERRIDES) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) + + X509* x; + BIO* bio; + ASN1_TIME *asn_time, *time_check; + const int year = 365*24*60*60; + const int day = 24*60*60; + const int hour = 60*60; + const int mini = 60; + int offset_day; + unsigned char buf[25]; + time_t t; + + printf(testingFmt, "wolfSSL_X509_set_notBefore()"); + /* + * Setup asn_time. APACHE HTTPD uses time(NULL) + */ + t = (time_t)49 * year + 125 * day + 20 * hour + 30 * mini + 7 * day; + offset_day = 7; + + /* + * Free these. + */ + asn_time = wolfSSL_ASN1_TIME_adj(NULL, t, offset_day, 0); + AssertNotNull(asn_time); + AssertNotNull(x = X509_new()); + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertIntEQ(ASN1_TIME_check(asn_time), WOLFSSL_SUCCESS); + + /* + * Main Tests + */ + AssertTrue(wolfSSL_X509_set_notBefore(x, asn_time)); + /* time_check == (ANS1_TIME*)x->notBefore */ + AssertNotNull(time_check = X509_get_notBefore(x)); + /* ANS1_TIME_check validates by checking if argument can be parsed */ + AssertIntEQ(ASN1_TIME_check(time_check), WOLFSSL_SUCCESS); + /* Convert to human readable format and compare to intended date */ + AssertIntEQ(ASN1_TIME_print(bio, time_check), 1); + AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 24); + AssertIntEQ(XMEMCMP(buf, "May 8 20:30:00 2019 GMT", sizeof(buf) - 1), 0); + /* + * Cleanup + */ + XFREE(asn_time,NULL,DYNAMIC_TYPE_OPENSSL); + X509_free(x); + BIO_free(bio); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_set_version(void) +{ +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) && \ + !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) + X509* x509; + long v = 2L; + long max = INT_MAX; + + AssertNotNull(x509 = X509_new()); + /* These should pass. */ + AssertTrue(wolfSSL_X509_set_version(x509, v)); + AssertIntEQ(v, wolfSSL_X509_get_version(x509)); + /* Fail Case: When v(long) is greater than x509->version(int). */ + v = max+1; + AssertFalse(wolfSSL_X509_set_version(x509, v)); + /* Cleanup */ + X509_free(x509); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_BIO_gets(void) +{ + #if defined(OPENSSL_EXTRA) + BIO* bio; + BIO* bio2; + char msg[] = "\nhello wolfSSL\n security plus\t---...**adf\na...b.c"; + char emp[] = ""; + char bio_buffer[20]; + int bufferSz = 20; + + printf(testingFmt, "wolfSSL_BIO_gets()"); + + /* try with bad args */ + AssertNull(bio = BIO_new_mem_buf(NULL, sizeof(msg))); + AssertNull(bio = BIO_new_mem_buf((void*)msg, -1)); + + /* try with real msg */ + AssertNotNull(bio = BIO_new_mem_buf((void*)msg, sizeof(msg))); + XMEMSET(bio_buffer, 0, bufferSz); + AssertNotNull(BIO_push(bio, BIO_new(BIO_s_bio()))); + AssertNull(bio2 = BIO_find_type(bio, BIO_TYPE_FILE)); + AssertNotNull(bio2 = BIO_find_type(bio, BIO_TYPE_BIO)); + AssertFalse(bio2 != BIO_next(bio)); + + /* make buffer filled with no terminating characters */ + XMEMSET(bio_buffer, 1, bufferSz); + + /* BIO_gets reads a line of data */ + AssertIntEQ(BIO_gets(bio, bio_buffer, -3), 0); + AssertIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 1); + AssertIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 14); + AssertStrEQ(bio_buffer, "hello wolfSSL\n"); + AssertIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 19); + AssertIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 8); + AssertIntEQ(BIO_gets(bio, bio_buffer, -1), 0); + + /* check not null terminated string */ + BIO_free(bio); + msg[0] = 0x33; + msg[1] = 0x33; + msg[2] = 0x33; + AssertNotNull(bio = BIO_new_mem_buf((void*)msg, 3)); + AssertIntEQ(BIO_gets(bio, bio_buffer, 3), 2); + AssertIntEQ(bio_buffer[0], msg[0]); + AssertIntEQ(bio_buffer[1], msg[1]); + AssertIntNE(bio_buffer[2], msg[2]); + + BIO_free(bio); + msg[3] = 0x33; + bio_buffer[3] = 0x33; + AssertNotNull(bio = BIO_new_mem_buf((void*)msg, 3)); + AssertIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 3); + AssertIntEQ(bio_buffer[0], msg[0]); + AssertIntEQ(bio_buffer[1], msg[1]); + AssertIntEQ(bio_buffer[2], msg[2]); + AssertIntNE(bio_buffer[3], 0x33); /* make sure null terminator was set */ + + /* check reading an empty string */ + BIO_free(bio); + AssertNotNull(bio = BIO_new_mem_buf((void*)emp, sizeof(emp))); + AssertIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 1); /* just terminator */ + AssertStrEQ(emp, bio_buffer); + AssertIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 0); /* Nothing to read */ + + /* check error cases */ + BIO_free(bio); + AssertIntEQ(BIO_gets(NULL, NULL, 0), SSL_FAILURE); + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertIntEQ(BIO_gets(bio, bio_buffer, 2), 0); /* nothing to read */ + +#if !defined(NO_FILESYSTEM) + { + BIO* f_bio; + XFILE f; + AssertNotNull(f_bio = BIO_new(BIO_s_file())); + AssertIntLE(BIO_gets(f_bio, bio_buffer, bufferSz), 0); + + f = XFOPEN(svrCertFile, "rb"); + AssertTrue((f != XBADFILE)); + AssertIntEQ((int)BIO_set_fp(f_bio, f, BIO_CLOSE), SSL_SUCCESS); + AssertIntGT(BIO_gets(f_bio, bio_buffer, bufferSz), 0); + + BIO_free(f_bio); + } +#endif /* NO_FILESYSTEM */ + + BIO_free(bio); + BIO_free(bio2); + + /* try with type BIO */ + XMEMCPY(msg, "\nhello wolfSSL\n security plus\t---...**adf\na...b.c", + sizeof(msg)); + AssertNotNull(bio = BIO_new(BIO_s_bio())); + AssertIntEQ(BIO_gets(bio, bio_buffer, 2), 0); /* nothing to read */ + AssertNotNull(bio2 = BIO_new(BIO_s_bio())); + + AssertIntEQ(BIO_set_write_buf_size(bio, 10), SSL_SUCCESS); + AssertIntEQ(BIO_set_write_buf_size(bio2, sizeof(msg)), SSL_SUCCESS); + AssertIntEQ(BIO_make_bio_pair(bio, bio2), SSL_SUCCESS); + + AssertIntEQ(BIO_write(bio2, msg, sizeof(msg)), sizeof(msg)); + AssertIntEQ(BIO_gets(bio, bio_buffer, -3), 0); + AssertIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 1); + AssertIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 14); + AssertStrEQ(bio_buffer, "hello wolfSSL\n"); + AssertIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 19); + AssertIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 8); + AssertIntEQ(BIO_gets(bio, bio_buffer, -1), 0); + + BIO_free(bio); + BIO_free(bio2); + + /* check reading an empty string */ + AssertNotNull(bio = BIO_new(BIO_s_bio())); + AssertIntEQ(BIO_set_write_buf_size(bio, sizeof(emp)), SSL_SUCCESS); + AssertIntEQ(BIO_gets(bio, bio_buffer, bufferSz), 0); /* Nothing to read */ + AssertStrEQ(emp, bio_buffer); + + BIO_free(bio); + + printf(resultFmt, passed); + #endif +} + + +static void test_wolfSSL_BIO_puts(void) +{ + #if defined(OPENSSL_EXTRA) + BIO* bio; + char input[] = "hello\0world\n.....ok\n\0"; + char output[128]; + + printf(testingFmt, "wolfSSL_BIO_puts()"); + + XMEMSET(output, 0, sizeof(output)); + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertIntEQ(BIO_puts(bio, input), 5); + AssertIntEQ(BIO_pending(bio), 5); + AssertIntEQ(BIO_puts(bio, input + 6), 14); + AssertIntEQ(BIO_pending(bio), 19); + AssertIntEQ(BIO_gets(bio, output, sizeof(output)), 11); + AssertStrEQ(output, "helloworld\n"); + AssertIntEQ(BIO_pending(bio), 8); + AssertIntEQ(BIO_gets(bio, output, sizeof(output)), 8); + AssertStrEQ(output, ".....ok\n"); + AssertIntEQ(BIO_pending(bio), 0); + AssertIntEQ(BIO_puts(bio, ""), -1); + + BIO_free(bio); + printf(resultFmt, passed); + #endif +} + +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ + !defined(NO_RSA) && defined(HAVE_EXT_CACHE) && \ + defined(HAVE_IO_TESTS_DEPENDENCIES) +static int forceWantRead(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + (void)ssl; + (void)buf; + (void)sz; + (void)ctx; + return WOLFSSL_CBIO_ERR_WANT_READ; +} +#endif + +static void test_wolfSSL_BIO_should_retry(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ + !defined(NO_RSA) && defined(HAVE_EXT_CACHE) && \ + defined(HAVE_IO_TESTS_DEPENDENCIES) + tcp_ready ready; + func_args server_args; + THREAD_TYPE serverThread; + SOCKET_T sockfd = 0; + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + char msg[64] = "hello wolfssl!"; + char reply[1024]; + int msgSz = (int)XSTRLEN(msg); + int ret; + BIO* bio; + + printf(testingFmt, "wolfSSL_BIO_should_retry()"); + + XMEMSET(&server_args, 0, sizeof(func_args)); +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + StartTCP(); + InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + + server_args.signal = &ready; + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); + tcp_connect(&sockfd, wolfSSLIP, server_args.signal->port, 0, 0, NULL); + + /* force retry */ + AssertNotNull(ssl = wolfSSL_new(ctx)); + AssertIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS); + wolfSSL_SSLSetIORecv(ssl, forceWantRead); + + AssertNotNull(bio = BIO_new(BIO_f_ssl())); + BIO_set_ssl(bio, ssl, BIO_CLOSE); + + AssertIntLE(BIO_write(bio, msg, msgSz), 0); + AssertIntNE(BIO_should_retry(bio), 0); + + + /* now perform successful connection */ + wolfSSL_SSLSetIORecv(ssl, EmbedReceive); + AssertIntEQ(BIO_write(bio, msg, msgSz), msgSz); + BIO_read(bio, reply, sizeof(reply)); + ret = wolfSSL_get_error(ssl, -1); + if (ret == WOLFSSL_ERROR_WANT_READ || ret == WOLFSSL_ERROR_WANT_WRITE) { + AssertIntNE(BIO_should_retry(bio), 0); + } + else { + AssertIntEQ(BIO_should_retry(bio), 0); + } + AssertIntEQ(XMEMCMP(reply, "I hear you fa shizzle!", + XSTRLEN("I hear you fa shizzle!")), 0); + BIO_free(bio); + wolfSSL_CTX_free(ctx); + + join_thread(serverThread); + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_BIO_write(void) +{ + #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_BASE64_ENCODE) + BIO* bio; + BIO* bio64; + BIO* ptr; + int sz; + char msg[] = "conversion test"; + char out[40]; + char expected[] = "Y29udmVyc2lvbiB0ZXN0AA==\n"; + BUF_MEM* buf = NULL; + + printf(testingFmt, "wolfSSL_BIO_write()"); + + AssertNotNull(bio64 = BIO_new(BIO_f_base64())); + AssertNotNull(bio = BIO_push(bio64, BIO_new(BIO_s_mem()))); + + /* now should convert to base64 then write to memory */ + AssertIntEQ(BIO_write(bio, msg, sizeof(msg)), sizeof(msg)); + BIO_flush(bio); + + /* test BIO chain */ + AssertIntEQ(SSL_SUCCESS, (int)BIO_get_mem_ptr(bio, &buf)); + AssertNotNull(buf); + AssertIntEQ(buf->length, 25); + + AssertNotNull(ptr = BIO_find_type(bio, BIO_TYPE_MEM)); + sz = sizeof(out); + XMEMSET(out, 0, sz); + AssertIntEQ((sz = BIO_read(ptr, out, sz)), 25); + AssertIntEQ(XMEMCMP(out, expected, sz), 0); + + /* write then read should return the same message */ + AssertIntEQ(BIO_write(bio, msg, sizeof(msg)), sizeof(msg)); + sz = sizeof(out); + XMEMSET(out, 0, sz); + AssertIntEQ(BIO_read(bio, out, sz), 16); + AssertIntEQ(XMEMCMP(out, msg, sizeof(msg)), 0); + + /* now try encoding with no line ending */ + BIO_set_flags(bio64, BIO_FLAG_BASE64_NO_NL); + #ifdef HAVE_EX_DATA + BIO_set_ex_data(bio64, 0, (void*) "data"); + AssertIntEQ(strcmp((const char*)BIO_get_ex_data(bio64, 0), "data"), 0); + #endif + AssertIntEQ(BIO_write(bio, msg, sizeof(msg)), sizeof(msg)); + BIO_flush(bio); + sz = sizeof(out); + XMEMSET(out, 0, sz); + AssertIntEQ((sz = BIO_read(ptr, out, sz)), 24); + AssertIntEQ(XMEMCMP(out, expected, sz), 0); + + BIO_free_all(bio); /* frees bio64 also */ + + /* test with more than one bio64 in list */ + AssertNotNull(bio64 = BIO_new(BIO_f_base64())); + AssertNotNull(bio = BIO_push(BIO_new(BIO_f_base64()), bio64)); + AssertNotNull(BIO_push(bio64, BIO_new(BIO_s_mem()))); + + /* now should convert to base64 when stored and then decode with read */ + AssertIntEQ(BIO_write(bio, msg, sizeof(msg)), 25); + BIO_flush(bio); + sz = sizeof(out); + XMEMSET(out, 0, sz); + AssertIntEQ((sz = BIO_read(bio, out, sz)), 16); + AssertIntEQ(XMEMCMP(out, msg, sz), 0); + BIO_clear_flags(bio64, ~0); + BIO_set_retry_read(bio); + BIO_free_all(bio); /* frees bio64s also */ + + printf(resultFmt, passed); + #endif +} + + +static void test_wolfSSL_BIO_printf(void) +{ + #if defined(OPENSSL_ALL) + BIO* bio; + int sz = 7; + char msg[] = "TLS 1.3 for the world"; + char out[60]; + char expected[] = "TLS 1.3 for the world : sz = 7"; + + printf(testingFmt, "wolfSSL_BIO_printf()"); + + XMEMSET(out, 0, sizeof(out)); + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertIntEQ(BIO_printf(bio, "%s : sz = %d", msg, sz), 30); + AssertIntEQ(BIO_printf(NULL, ""), WOLFSSL_FATAL_ERROR); + AssertIntEQ(BIO_read(bio, out, sizeof(out)), 30); + AssertIntEQ(XSTRNCMP(out, expected, sizeof(expected)), 0); + BIO_free(bio); + + printf(resultFmt, passed); + #endif +} + +static void test_wolfSSL_BIO_f_md(void) +{ + #if defined(OPENSSL_ALL) && !defined(NO_SHA256) + BIO *bio, *mem; + char msg[] = "message to hash"; + char out[60]; + EVP_MD_CTX* ctx; + 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 + }; + const unsigned char expectedHash[] = + { + 0x66, 0x49, 0x3C, 0xE8, 0x8A, 0x57, 0xB0, 0x60, + 0xDC, 0x55, 0x7D, 0xFC, 0x1F, 0xA5, 0xE5, 0x07, + 0x70, 0x5A, 0xF6, 0xD7, 0xC4, 0x1F, 0x1A, 0xE4, + 0x2D, 0xA6, 0xFD, 0xD1, 0x29, 0x7D, 0x60, 0x0D + }; + const unsigned char emptyHash[] = + { + 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, + 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, + 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, + 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55 + }; + unsigned char check[sizeof(testResult) + 1]; + size_t checkSz = -1; + EVP_PKEY* key; + + printf(testingFmt, "wolfSSL_BIO_f_md()"); + + XMEMSET(out, 0, sizeof(out)); + AssertNotNull(bio = BIO_new(BIO_f_md())); + AssertNotNull(mem = BIO_new(BIO_s_mem())); + + AssertIntEQ(BIO_get_md_ctx(bio, &ctx), 1); + AssertIntEQ(EVP_DigestInit(ctx, EVP_sha256()), 1); + + /* should not be able to write/read yet since just digest wrapper and no + * data is passing through the bio */ + AssertIntEQ(BIO_write(bio, msg, 0), 0); + AssertIntEQ(BIO_pending(bio), 0); + AssertIntEQ(BIO_read(bio, out, sizeof(out)), 0); + AssertIntEQ(BIO_gets(bio, out, 3), 0); + AssertIntEQ(BIO_gets(bio, out, sizeof(out)), 32); + AssertIntEQ(XMEMCMP(emptyHash, out, 32), 0); + BIO_reset(bio); + + /* append BIO mem to bio in order to read/write */ + AssertNotNull(bio = BIO_push(bio, mem)); + + XMEMSET(out, 0, sizeof(out)); + AssertIntEQ(BIO_write(mem, msg, sizeof(msg)), 16); + AssertIntEQ(BIO_pending(bio), 16); + + /* this just reads the message and does not hash it (gets calls final) */ + AssertIntEQ(BIO_read(bio, out, sizeof(out)), 16); + AssertIntEQ(XMEMCMP(out, msg, sizeof(msg)), 0); + + /* create a message digest using BIO */ + XMEMSET(out, 0, sizeof(out)); + AssertIntEQ(BIO_write(bio, msg, sizeof(msg)), 16); + AssertIntEQ(BIO_pending(mem), 16); + AssertIntEQ(BIO_pending(bio), 16); + AssertIntEQ(BIO_gets(bio, out, sizeof(out)), 32); + AssertIntEQ(XMEMCMP(expectedHash, out, 32), 0); + BIO_free(bio); + BIO_free(mem); + + /* test with HMAC */ + XMEMSET(out, 0, sizeof(out)); + AssertNotNull(bio = BIO_new(BIO_f_md())); + AssertNotNull(mem = BIO_new(BIO_s_mem())); + BIO_get_md_ctx(bio, &ctx); + AssertNotNull(key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, + testKey, (int)sizeof(testKey))); + EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, key); + AssertNotNull(bio = BIO_push(bio, mem)); + BIO_write(bio, testData, (int)strlen(testData)); + EVP_DigestSignFinal(ctx, NULL, &checkSz); + EVP_DigestSignFinal(ctx, check, &checkSz); + + AssertIntEQ(XMEMCMP(check, testResult, sizeof(testResult)), 0); + + EVP_PKEY_free(key); + BIO_free(bio); + BIO_free(mem); + + printf(resultFmt, passed); + #endif +} + + +static void test_wolfSSL_SESSION(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ + !defined(NO_RSA) && defined(HAVE_EXT_CACHE) && \ + defined(HAVE_IO_TESTS_DEPENDENCIES) + + WOLFSSL* ssl; + WOLFSSL_CTX* ctx; + WOLFSSL_SESSION* sess; + WOLFSSL_SESSION* sess_copy; + const unsigned char context[] = "user app context"; + unsigned char* sessDer = NULL; + unsigned char* ptr = NULL; + unsigned int contextSz = (unsigned int)sizeof(context); + int ret, err, sockfd, sz; + tcp_ready ready; + func_args server_args; + THREAD_TYPE serverThread; + char msg[80]; + + printf(testingFmt, "wolfSSL_SESSION()"); + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0), SSL_SUCCESS); +#ifdef WOLFSSL_ENCRYPTED_KEYS + wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); +#endif + + XMEMSET(&server_args, 0, sizeof(func_args)); +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + StartTCP(); + InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + + server_args.signal = &ready; + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + + /* client connection */ + ssl = wolfSSL_new(ctx); + tcp_connect(&sockfd, wolfSSLIP, ready.port, 0, 0, ssl); + AssertIntEQ(wolfSSL_set_fd(ssl, sockfd), SSL_SUCCESS); + + err = 0; /* Reset error */ + 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 + + ret = wolfSSL_connect(ssl); + if (ret != SSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != SSL_SUCCESS && err == WC_PENDING_E); + AssertIntEQ(ret, SSL_SUCCESS); + + AssertIntEQ(wolfSSL_write(ssl, "GET", 3), 3); + AssertIntEQ(wolfSSL_read(ssl, msg, sizeof(msg)), 23); + + sess = wolfSSL_get_session(ssl); + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + + join_thread(serverThread); + + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + +#if defined(SESSION_CERTS) + { + X509 *x509; + char buf[30]; + int bufSz; + + AssertNotNull(x509 = SSL_SESSION_get0_peer(sess)); + AssertIntGT((bufSz = X509_NAME_get_text_by_NID( + X509_get_subject_name(x509), NID_organizationalUnitName, + buf, sizeof(buf))), 0); + AssertIntNE((bufSz == 7 || bufSz == 16), 0); /* should be one of these*/ + if (bufSz == 7) { + AssertIntEQ(XMEMCMP(buf, "Support", bufSz), 0); + } + if (bufSz == 16) { + AssertIntEQ(XMEMCMP(buf, "Programming-2048", bufSz), 0); + } + } +#endif + + AssertNotNull(sess_copy = wolfSSL_SESSION_dup(sess)); + wolfSSL_SESSION_free(sess_copy); + + /* get session from DER and update the timeout */ + AssertIntEQ(wolfSSL_i2d_SSL_SESSION(NULL, &sessDer), BAD_FUNC_ARG); + AssertIntGT((sz = wolfSSL_i2d_SSL_SESSION(sess, &sessDer)), 0); + wolfSSL_SESSION_free(sess); + ptr = sessDer; + AssertNull(sess = wolfSSL_d2i_SSL_SESSION(NULL, NULL, sz)); + AssertNotNull(sess = wolfSSL_d2i_SSL_SESSION(NULL, + (const unsigned char**)&ptr, sz)); + XFREE(sessDer, NULL, DYNAMIC_TYPE_OPENSSL); + AssertIntGT(wolfSSL_SESSION_get_time(sess), 0); + AssertIntEQ(wolfSSL_SSL_SESSION_set_timeout(sess, 500), SSL_SUCCESS); + + /* successful set session test */ + AssertNotNull(ssl = wolfSSL_new(ctx)); + AssertIntEQ(wolfSSL_set_session(ssl, sess), SSL_SUCCESS); + +#ifdef HAVE_SESSION_TICKET + /* Test set/get session ticket */ + { + const char* ticket = "This is a session ticket"; + char buf[64] = {0}; + word32 bufSz = (word32)sizeof(buf); + + AssertIntEQ(SSL_SUCCESS, + wolfSSL_set_SessionTicket(ssl, (byte *)ticket, (word32)XSTRLEN(ticket))); + AssertIntEQ(SSL_SUCCESS, + wolfSSL_get_SessionTicket(ssl, (byte *)buf, &bufSz)); + AssertStrEQ(ticket, buf); + } +#endif + + /* fail case with miss match session context IDs (use compatibility API) */ + AssertIntEQ(SSL_set_session_id_context(ssl, context, contextSz), + SSL_SUCCESS); + AssertIntEQ(wolfSSL_set_session(ssl, sess), SSL_FAILURE); + wolfSSL_free(ssl); + AssertIntEQ(SSL_CTX_set_session_id_context(NULL, context, contextSz), + SSL_FAILURE); + AssertIntEQ(SSL_CTX_set_session_id_context(ctx, context, contextSz), + SSL_SUCCESS); + AssertNotNull(ssl = wolfSSL_new(ctx)); + AssertIntEQ(wolfSSL_set_session(ssl, sess), SSL_FAILURE); + wolfSSL_free(ssl); + + SSL_SESSION_free(sess); + wolfSSL_CTX_free(ctx); + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_d2i_PUBKEY(void) +{ + #if defined(OPENSSL_EXTRA) + BIO* bio; + EVP_PKEY* pkey; + + printf(testingFmt, "wolfSSL_d2i_PUBKEY()"); + + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertNull(d2i_PUBKEY_bio(NULL, NULL)); + +#if defined(USE_CERT_BUFFERS_2048) && !defined(NO_RSA) + /* RSA PUBKEY test */ + AssertIntGT(BIO_write(bio, client_keypub_der_2048, + sizeof_client_keypub_der_2048), 0); + AssertNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); + EVP_PKEY_free(pkey); +#endif + +#if defined(USE_CERT_BUFFERS_256) && defined(HAVE_ECC) + /* ECC PUBKEY test */ + AssertIntGT(BIO_write(bio, ecc_clikeypub_der_256, + sizeof_ecc_clikeypub_der_256), 0); + AssertNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); + EVP_PKEY_free(pkey); +#endif + + BIO_free(bio); + + (void)pkey; + printf(resultFmt, passed); + #endif +} + +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)) && !defined(NO_RSA) +static void test_wolfSSL_d2i_PrivateKeys_bio(void) +{ + BIO* bio = NULL; + EVP_PKEY* pkey = NULL; +#ifndef NO_RSA +#endif + WOLFSSL_CTX* ctx; + +#if defined(WOLFSSL_KEY_GEN) + unsigned char buff[4096]; + unsigned char* bufPtr = buff; +#endif + + printf(testingFmt, "wolfSSL_d2i_PrivateKeys_bio()"); + + /* test creating new EVP_PKEY with bad arg */ + AssertNull((pkey = d2i_PrivateKey_bio(NULL, NULL))); + + /* test loading RSA key using BIO */ +#if !defined(NO_RSA) && !defined(NO_FILESYSTEM) + { + XFILE file; + const char* fname = "./certs/server-key.der"; + size_t sz; + byte* buf; + + file = XFOPEN(fname, "rb"); + AssertTrue((file != XBADFILE)); + AssertTrue(XFSEEK(file, 0, XSEEK_END) == 0); + sz = XFTELL(file); + XREWIND(file); + AssertNotNull(buf = (byte*)XMALLOC(sz, HEAP_HINT, DYNAMIC_TYPE_FILE)); + AssertIntEQ(XFREAD(buf, 1, sz, file), sz); + XFCLOSE(file); + + /* Test using BIO new mem and loading DER private key */ + AssertNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + AssertNotNull((pkey = d2i_PrivateKey_bio(bio, NULL))); + XFREE(buf, HEAP_HINT, DYNAMIC_TYPE_FILE); + BIO_free(bio); + bio = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + } +#endif + + /* test loading ECC key using BIO */ +#if defined(HAVE_ECC) && !defined(NO_FILESYSTEM) + { + XFILE file; + const char* fname = "./certs/ecc-key.der"; + size_t sz; + byte* buf; + + file = XFOPEN(fname, "rb"); + AssertTrue((file != XBADFILE)); + AssertTrue(XFSEEK(file, 0, XSEEK_END) == 0); + sz = XFTELL(file); + XREWIND(file); + AssertNotNull(buf = (byte*)XMALLOC(sz, HEAP_HINT, DYNAMIC_TYPE_FILE)); + AssertIntEQ(XFREAD(buf, 1, sz, file), sz); + XFCLOSE(file); + + /* Test using BIO new mem and loading DER private key */ + AssertNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + AssertNotNull((pkey = d2i_PrivateKey_bio(bio, NULL))); + XFREE(buf, HEAP_HINT, DYNAMIC_TYPE_FILE); + BIO_free(bio); + bio = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + } +#endif + + AssertNotNull(bio = BIO_new(BIO_s_mem())); +#ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); +#else + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); +#endif + +#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \ + !defined(NO_RSA) && !defined(HAVE_USER_RSA) + { + RSA* rsa = NULL; + /* Tests bad parameters */ + AssertNull(d2i_RSAPrivateKey_bio(NULL, NULL)); + + /* RSA not set yet, expecting to fail*/ + AssertIntEQ(SSL_CTX_use_RSAPrivateKey(ctx, rsa), BAD_FUNC_ARG); + +#if defined(USE_CERT_BUFFERS_2048) && defined(WOLFSSL_KEY_GEN) + /* set RSA using bio*/ + AssertIntGT(BIO_write(bio, client_key_der_2048, + sizeof_client_key_der_2048), 0); + AssertNotNull(rsa = d2i_RSAPrivateKey_bio(bio, NULL)); + + AssertIntEQ(SSL_CTX_use_RSAPrivateKey(ctx, rsa), WOLFSSL_SUCCESS); + + /*i2d RSAprivate key tests */ + AssertIntEQ(wolfSSL_i2d_RSAPrivateKey(NULL, NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_i2d_RSAPrivateKey(rsa, NULL), 1192); + AssertIntEQ(wolfSSL_i2d_RSAPrivateKey(rsa, &bufPtr), + sizeof_client_key_der_2048); + bufPtr = NULL; + AssertIntEQ(wolfSSL_i2d_RSAPrivateKey(rsa, &bufPtr), + sizeof_client_key_der_2048); + AssertNotNull(bufPtr); + XFREE(bufPtr, NULL, DYNAMIC_TYPE_OPENSSL); +#endif /* USE_CERT_BUFFERS_2048 WOLFSSL_KEY_GEN */ + RSA_free(rsa); + } +#endif /* !HAVE_FAST_RSA && WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA*/ + SSL_CTX_free(ctx); + ctx = NULL; + BIO_free(bio); + bio = NULL; + printf(resultFmt, passed); +} +#endif /* OPENSSL_ALL || WOLFSSL_ASIO */ + + +static void test_wolfSSL_sk_GENERAL_NAME(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ + !defined(NO_RSA) + X509* x509; + GENERAL_NAME* gn; + unsigned char buf[4096]; + const unsigned char* bufPt; + int bytes, i; + XFILE f; + STACK_OF(GENERAL_NAME)* sk; + + printf(testingFmt, "wolfSSL_sk_GENERAL_NAME()"); + + f = XFOPEN(cliCertDerFileExt, "rb"); + AssertTrue((f != XBADFILE)); + AssertIntGT((bytes = (int)XFREAD(buf, 1, sizeof(buf), f)), 0); + XFCLOSE(f); + + bufPt = buf; + AssertNotNull(x509 = d2i_X509(NULL, &bufPt, bytes)); + + AssertNotNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, + NID_subject_alt_name, NULL, NULL)); + + AssertIntEQ(sk_GENERAL_NAME_num(sk), 1); + for (i = 0; i < sk_GENERAL_NAME_num(sk); i++) { + AssertNotNull(gn = sk_GENERAL_NAME_value(sk, i)); + + switch (gn->type) { + case GEN_DNS: + printf("found type GEN_DNS\n"); + break; + case GEN_EMAIL: + printf("found type GEN_EMAIL\n"); + break; + case GEN_URI: + printf("found type GEN_URI\n"); + break; + } + } + X509_free(x509); + sk_GENERAL_NAME_pop_free(sk, GENERAL_NAME_free); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_MD4(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_MD4) + MD4_CTX md4; + unsigned char out[16]; /* MD4_DIGEST_SIZE */ + const char* msg = "12345678901234567890123456789012345678901234567890123456" + "789012345678901234567890"; + const char* test = "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19\x9c\x3e\x7b\x16\x4f" + "\xcc\x05\x36"; + int msgSz = (int)XSTRLEN(msg); + + printf(testingFmt, "wolfSSL_MD4()"); + + XMEMSET(out, 0, sizeof(out)); + MD4_Init(&md4); + MD4_Update(&md4, (const void*)msg, (unsigned long)msgSz); + MD4_Final(out, &md4); + AssertIntEQ(XMEMCMP(out, test, sizeof(out)), 0); + + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_RSA(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) && \ + defined(WOLFSSL_KEY_GEN) + RSA* rsa; + const BIGNUM *n; + const BIGNUM *e; + const BIGNUM *d; + + printf(testingFmt, "wolfSSL_RSA()"); + + AssertNotNull(rsa = RSA_generate_key(2048, 3, NULL, NULL)); + AssertIntEQ(RSA_size(rsa), 256); + RSA_get0_key(rsa, &n, &e, &d); + AssertPtrEq(rsa->n, n); + AssertPtrEq(rsa->e, e); + AssertPtrEq(rsa->d, d); + AssertNotNull(n = BN_new()); + AssertNotNull(e = BN_new()); + AssertNotNull(d = BN_new()); + AssertIntEQ(RSA_set0_key(rsa, (BIGNUM*)n, (BIGNUM*)e, (BIGNUM*)d), 1); + AssertPtrEq(rsa->n, n); + AssertPtrEq(rsa->e, e); + AssertPtrEq(rsa->d, d); + RSA_free(rsa); + +#if !defined(USE_FAST_MATH) || (FP_MAX_BITS >= (3072*2)) + AssertNotNull(rsa = RSA_generate_key(3072, 17, NULL, NULL)); + AssertIntEQ(RSA_size(rsa), 384); + RSA_free(rsa); +#endif + + /* remove for now with odd key size until adjusting rsa key size check with + wc_MakeRsaKey() + AssertNotNull(rsa = RSA_generate_key(2999, 65537, NULL, NULL)); + RSA_free(rsa); + */ + + AssertNull(RSA_generate_key(-1, 3, NULL, NULL)); + AssertNull(RSA_generate_key(511, 3, NULL, NULL)); /* RSA_MIN_SIZE - 1 */ + AssertNull(RSA_generate_key(4097, 3, NULL, NULL)); /* RSA_MAX_SIZE + 1 */ + AssertNull(RSA_generate_key(2048, 0, NULL, NULL)); + + +#if !defined(NO_FILESYSTEM) && !defined(NO_ASN) + { + byte buff[FOURK_BUF]; + byte der[FOURK_BUF]; + const char PrivKeyPemFile[] = "certs/client-keyEnc.pem"; + + XFILE f; + int bytes; + + /* test loading encrypted RSA private pem w/o password */ + f = XFOPEN(PrivKeyPemFile, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buff, 1, sizeof(buff), f); + XFCLOSE(f); + XMEMSET(der, 0, sizeof(der)); + /* test that error value is returned with no password */ + AssertIntLT(wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), ""), 0); + } +#endif + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_RSA_DER(void) +{ +#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \ + !defined(NO_RSA) && !defined(HAVE_USER_RSA) && defined(OPENSSL_EXTRA) + + RSA *rsa; + int i; + const unsigned char *buff = NULL; + + struct tbl_s + { + const unsigned char *der; + int sz; + } tbl[] = { + +#ifdef USE_CERT_BUFFERS_1024 + {client_key_der_1024, sizeof_client_key_der_1024}, + {server_key_der_1024, sizeof_server_key_der_1024}, +#endif +#ifdef USE_CERT_BUFFERS_2048 + {client_key_der_2048, sizeof_client_key_der_2048}, + {server_key_der_2048, sizeof_server_key_der_2048}, +#endif + {NULL, 0} + }; + + /* Public Key DER */ + struct tbl_s pub[] = { +#ifdef USE_CERT_BUFFERS_1024 + {client_keypub_der_1024, sizeof_client_keypub_der_1024}, +#endif +#ifdef USE_CERT_BUFFERS_2048 + {client_keypub_der_2048, sizeof_client_keypub_der_2048}, +#endif + {NULL, 0} + }; + + printf(testingFmt, "test_wolfSSL_RSA_DER()"); + + for (i = 0; tbl[i].der != NULL; i++) + { + AssertNotNull(d2i_RSAPublicKey(&rsa, &tbl[i].der, tbl[i].sz)); + AssertNotNull(rsa); + RSA_free(rsa); + } + for (i = 0; tbl[i].der != NULL; i++) + { + AssertNotNull(d2i_RSAPrivateKey(&rsa, &tbl[i].der, tbl[i].sz)); + AssertNotNull(rsa); + RSA_free(rsa); + } + + for (i = 0; pub[i].der != NULL; i++) + { + AssertNotNull(d2i_RSAPublicKey(&rsa, &pub[i].der, pub[i].sz)); + AssertNotNull(rsa); + AssertIntEQ(i2d_RSAPublicKey(rsa, NULL), pub[i].sz); + buff = NULL; + AssertIntEQ(i2d_RSAPublicKey(rsa, &buff), pub[i].sz); + AssertNotNull(buff); + AssertIntEQ(0, memcmp((void *)buff, (void *)pub[i].der, pub[i].sz)); + XFREE((void *)buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + RSA_free(rsa); + } + + printf(resultFmt, passed); + +#endif +} + +static void test_wolfSSL_RSA_get0_key(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) + RSA *rsa = NULL; + const BIGNUM* n = NULL; + const BIGNUM* e = NULL; + const BIGNUM* d = NULL; + + const unsigned char* der; + int derSz; + +#ifdef USE_CERT_BUFFERS_1024 + der = client_key_der_1024; + derSz = sizeof_client_key_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + der = client_key_der_2048; + derSz = sizeof_client_key_der_2048; +#else + der = NULL; + derSz = 0; +#endif + + printf(testingFmt, "test_wolfSSL_RSA_get0_key()"); + + if (der != NULL) { + RSA_get0_key(NULL, NULL, NULL, NULL); + RSA_get0_key(rsa, NULL, NULL, NULL); + RSA_get0_key(NULL, &n, &e, &d); + AssertNull(n); + AssertNull(e); + AssertNull(d); + + AssertNotNull(d2i_RSAPrivateKey(&rsa, &der, derSz)); + AssertNotNull(rsa); + + RSA_get0_key(rsa, NULL, NULL, NULL); + RSA_get0_key(rsa, &n, NULL, NULL); + AssertNotNull(n); + RSA_get0_key(rsa, NULL, &e, NULL); + AssertNotNull(e); + RSA_get0_key(rsa, NULL, NULL, &d); + AssertNotNull(d); + RSA_get0_key(rsa, &n, &e, &d); + AssertNotNull(n); + AssertNotNull(e); + AssertNotNull(d); + + RSA_free(rsa); + } + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_RSA_meth(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(HAVE_FAST_RSA) + RSA *rsa; + RSA_METHOD *rsa_meth; + + printf(testingFmt, "test_wolfSSL_RSA_meth"); + +#ifdef WOLFSSL_KEY_GEN + AssertNotNull(rsa = RSA_generate_key(2048, 3, NULL, NULL)); + RSA_free(rsa); +#else + AssertNull(rsa = RSA_generate_key(2048, 3, NULL, NULL)); +#endif + + AssertNotNull(rsa_meth = + RSA_meth_new("placeholder RSA method", RSA_METHOD_FLAG_NO_CHECK)); + +#ifndef NO_WOLFSSL_STUB + AssertIntEQ(RSA_meth_set_pub_enc(rsa_meth, NULL), 1); + AssertIntEQ(RSA_meth_set_pub_dec(rsa_meth, NULL), 1); + AssertIntEQ(RSA_meth_set_priv_enc(rsa_meth, NULL), 1); + AssertIntEQ(RSA_meth_set_priv_dec(rsa_meth, NULL), 1); + AssertIntEQ(RSA_meth_set_init(rsa_meth, NULL), 1); + AssertIntEQ(RSA_meth_set_finish(rsa_meth, NULL), 1); + AssertIntEQ(RSA_meth_set0_app_data(rsa_meth, NULL), 1); +#endif + + AssertNotNull(rsa = RSA_new()); + AssertIntEQ(RSA_set_method(rsa, rsa_meth), 1); + AssertPtrEq(RSA_get_method(rsa), rsa_meth); + AssertIntEQ(RSA_flags(rsa), RSA_METHOD_FLAG_NO_CHECK); + RSA_set_flags(rsa, RSA_FLAG_CACHE_PUBLIC); + AssertIntEQ(RSA_flags(rsa), RSA_FLAG_CACHE_PUBLIC); + + /* rsa_meth is freed here */ + RSA_free(rsa); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_verify_depth(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_WOLFSSL_CLIENT) + WOLFSSL* ssl; + WOLFSSL_CTX* ctx; + long depth; + + printf(testingFmt, "test_wolfSSL_verify_depth()"); + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0), SSL_SUCCESS); + + AssertIntGT((depth = SSL_CTX_get_verify_depth(ctx)), 0); + AssertNotNull(ssl = SSL_new(ctx)); + AssertIntEQ(SSL_get_verify_depth(ssl), SSL_CTX_get_verify_depth(ctx)); + SSL_free(ssl); + + SSL_CTX_set_verify_depth(ctx, -1); + AssertIntEQ(depth, SSL_CTX_get_verify_depth(ctx)); + + SSL_CTX_set_verify_depth(ctx, 2); + AssertIntEQ(2, SSL_CTX_get_verify_depth(ctx)); + AssertNotNull(ssl = SSL_new(ctx)); + AssertIntEQ(2, SSL_get_verify_depth(ssl)); + + SSL_free(ssl); + SSL_CTX_free(ctx); + printf(resultFmt, passed); +#endif +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_HMAC) +/* helper function for test_wolfSSL_HMAC_CTX, digest size is expected to be a + * buffer of 64 bytes. + * + * returns the size of the digest buffer on success and a negative value on + * failure. + */ +static int test_HMAC_CTX_helper(const EVP_MD* type, unsigned char* digest) +{ + HMAC_CTX ctx1; + HMAC_CTX ctx2; + + unsigned char key[] = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; + unsigned char long_key[] = + "0123456789012345678901234567890123456789" + "0123456789012345678901234567890123456789" + "0123456789012345678901234567890123456789" + "0123456789012345678901234567890123456789"; + + unsigned char msg[] = "message to hash"; + unsigned int digestSz = 64; + int keySz = sizeof(key); + int long_keySz = sizeof(long_key); + int msgSz = sizeof(msg); + + unsigned char digest2[64]; + unsigned int digestSz2 = 64; + + HMAC_CTX_init(&ctx1); + + AssertIntEQ(HMAC_Init(&ctx1, (const void*)key, keySz, type), SSL_SUCCESS); + AssertIntEQ(HMAC_Update(&ctx1, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_CTX_copy(&ctx2, &ctx1), SSL_SUCCESS); + + AssertIntEQ(HMAC_Update(&ctx1, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Final(&ctx1, digest, &digestSz), SSL_SUCCESS); + HMAC_CTX_cleanup(&ctx1); + + AssertIntEQ(HMAC_Update(&ctx2, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Final(&ctx2, digest2, &digestSz2), SSL_SUCCESS); + HMAC_CTX_cleanup(&ctx2); + + AssertIntEQ(digestSz, digestSz2); + AssertIntEQ(XMEMCMP(digest, digest2, digestSz), 0); + + /* test HMAC_Init with NULL key */ + + /* init after copy */ + printf("test HMAC_Init with NULL key (0)\n"); + HMAC_CTX_init(&ctx1); + AssertIntEQ(HMAC_Init(&ctx1, (const void*)key, keySz, type), SSL_SUCCESS); + AssertIntEQ(HMAC_Update(&ctx1, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_CTX_copy(&ctx2, &ctx1), SSL_SUCCESS); + + AssertIntEQ(HMAC_Init(&ctx1, NULL, 0, NULL), SSL_SUCCESS); + + AssertIntEQ(HMAC_Update(&ctx1, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Update(&ctx1, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Final(&ctx1, digest, &digestSz), SSL_SUCCESS); + + AssertIntEQ(HMAC_Init(&ctx2, NULL, 0, NULL), SSL_SUCCESS); + + AssertIntEQ(HMAC_Update(&ctx2, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Update(&ctx2, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Final(&ctx2, digest2, &digestSz), SSL_SUCCESS); + + HMAC_CTX_cleanup(&ctx2); + AssertIntEQ(digestSz, digestSz2); + AssertIntEQ(XMEMCMP(digest, digest2, digestSz), 0); + + /* long key */ + printf("test HMAC_Init with NULL key (1)\n"); + HMAC_CTX_init(&ctx1); + AssertIntEQ(HMAC_Init(&ctx1, (const void*)long_key, long_keySz, type), SSL_SUCCESS); + AssertIntEQ(HMAC_Update(&ctx1, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_CTX_copy(&ctx2, &ctx1), SSL_SUCCESS); + + AssertIntEQ(HMAC_Init(&ctx1, NULL, 0, NULL), SSL_SUCCESS); + + AssertIntEQ(HMAC_Update(&ctx1, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Update(&ctx1, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Final(&ctx1, digest, &digestSz), SSL_SUCCESS); + + AssertIntEQ(HMAC_Init(&ctx2, NULL, 0, NULL), SSL_SUCCESS); + + AssertIntEQ(HMAC_Update(&ctx2, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Update(&ctx2, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Final(&ctx2, digest2, &digestSz), SSL_SUCCESS); + + HMAC_CTX_cleanup(&ctx2); + AssertIntEQ(digestSz, digestSz2); + AssertIntEQ(XMEMCMP(digest, digest2, digestSz), 0); + + /* init before copy */ + printf("test HMAC_Init with NULL key (2)\n"); + HMAC_CTX_init(&ctx1); + AssertIntEQ(HMAC_Init(&ctx1, (const void*)key, keySz, type), SSL_SUCCESS); + AssertIntEQ(HMAC_Update(&ctx1, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Init(&ctx1, NULL, 0, NULL), SSL_SUCCESS); + AssertIntEQ(HMAC_CTX_copy(&ctx2, &ctx1), SSL_SUCCESS); + + AssertIntEQ(HMAC_Update(&ctx1, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Update(&ctx1, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Final(&ctx1, digest, &digestSz), SSL_SUCCESS); + + AssertIntEQ(HMAC_Update(&ctx2, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Update(&ctx2, msg, msgSz), SSL_SUCCESS); + AssertIntEQ(HMAC_Final(&ctx2, digest2, &digestSz), SSL_SUCCESS); + + HMAC_CTX_cleanup(&ctx1); + HMAC_CTX_cleanup(&ctx2); + AssertIntEQ(digestSz, digestSz2); + AssertIntEQ(XMEMCMP(digest, digest2, digestSz), 0); + + return digestSz; +} +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_HMAC) */ + +static void test_wolfSSL_HMAC_CTX(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_HMAC) + unsigned char digest[64]; + int digestSz; + + printf(testingFmt, "wolfSSL_HMAC_CTX()"); + + #ifndef NO_SHA + AssertIntEQ((digestSz = test_HMAC_CTX_helper(EVP_sha1(), digest)), 20); + AssertIntEQ(XMEMCMP("\xD9\x68\x77\x23\x70\xFB\x53\x70\x53\xBA\x0E\xDC\xDA" + "\xBF\x03\x98\x31\x19\xB2\xCC", digest, digestSz), 0); + #endif /* !NO_SHA */ + #ifdef WOLFSSL_SHA224 + AssertIntEQ((digestSz = test_HMAC_CTX_helper(EVP_sha224(), digest)), 28); + AssertIntEQ(XMEMCMP("\x57\xFD\xF4\xE1\x2D\xB0\x79\xD7\x4B\x25\x7E\xB1\x95" + "\x9C\x11\xAC\x2D\x1E\x78\x94\x4F\x3A\x0F\xED\xF8\xAD" + "\x02\x0E", digest, digestSz), 0); + + #endif /* WOLFSSL_SHA224 */ + #ifndef NO_SHA256 + AssertIntEQ((digestSz = test_HMAC_CTX_helper(EVP_sha256(), digest)), 32); + AssertIntEQ(XMEMCMP("\x13\xAB\x76\x91\x0C\x37\x86\x8D\xB3\x7E\x30\x0C\xFC" + "\xB0\x2E\x8E\x4A\xD7\xD4\x25\xCC\x3A\xA9\x0F\xA2\xF2" + "\x47\x1E\x62\x6F\x5D\xF2", digest, digestSz), 0); + + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + AssertIntEQ((digestSz = test_HMAC_CTX_helper(EVP_sha384(), digest)), 48); + AssertIntEQ(XMEMCMP("\x9E\xCB\x07\x0C\x11\x76\x3F\x23\xC3\x25\x0E\xC4\xB7" + "\x28\x77\x95\x99\xD5\x9D\x7A\xBB\x1A\x9F\xB7\xFD\x25" + "\xC9\x72\x47\x9F\x8F\x86\x76\xD6\x20\x57\x87\xB7\xE7" + "\xCD\xFB\xC2\xCC\x9F\x2B\xC5\x41\xAB", + digest, digestSz), 0); + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + AssertIntEQ((digestSz = test_HMAC_CTX_helper(EVP_sha512(), digest)), 64); + AssertIntEQ(XMEMCMP("\xD4\x21\x0C\x8B\x60\x6F\xF4\xBF\x07\x2F\x26\xCC\xAD" + "\xBC\x06\x0B\x34\x78\x8B\x4F\xD6\xC0\x42\xF1\x33\x10" + "\x6C\x4F\x1E\x55\x59\xDD\x2A\x9F\x15\x88\x62\xF8\x60" + "\xA3\x99\x91\xE2\x08\x7B\xF7\x95\x3A\xB0\x92\x48\x60" + "\x88\x8B\x5B\xB8\x5F\xE9\xB6\xB1\x96\xE3\xB5\xF0", + digest, digestSz), 0); + #endif /* WOLFSSL_SHA512 */ + + #ifndef NO_MD5 + AssertIntEQ((digestSz = test_HMAC_CTX_helper(EVP_md5(), digest)), 16); + AssertIntEQ(XMEMCMP("\xB7\x27\xC4\x41\xE5\x2E\x62\xBA\x54\xED\x72\x70\x9F" + "\xE4\x98\xDD", digest, digestSz), 0); + #endif /* !NO_MD5 */ + + printf(resultFmt, passed); +#endif +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_WOLFSSL_CLIENT) +static void sslMsgCb(int w, int version, int type, const void* buf, + size_t sz, SSL* ssl, void* arg) +{ + int i; + unsigned char* pt = (unsigned char*)buf; + + printf("%s %d bytes of version %d , type %d : ", (w)?"Writing":"Reading", + (int)sz, version, type); + for (i = 0; i < (int)sz; i++) printf("%02X", pt[i]); + printf("\n"); + (void)ssl; + (void)arg; +} +#endif /* OPENSSL_EXTRA */ + +static void test_wolfSSL_msg_callback(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_WOLFSSL_CLIENT) + WOLFSSL* ssl; + WOLFSSL_CTX* ctx; + + printf(testingFmt, "wolfSSL_msg_callback()"); + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, + SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, + SSL_FILETYPE_PEM)); + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0), + SSL_SUCCESS); + + AssertNotNull(ssl = SSL_new(ctx)); + AssertIntEQ(SSL_set_msg_callback(ssl, NULL), SSL_SUCCESS); + AssertIntEQ(SSL_set_msg_callback(ssl, &sslMsgCb), SSL_SUCCESS); + AssertIntEQ(SSL_set_msg_callback(NULL, &sslMsgCb), SSL_FAILURE); + + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_SHA(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) + printf(testingFmt, "wolfSSL_SHA()"); + + #if !defined(NO_SHA) + { + const unsigned char in[] = "abc"; + unsigned char expected[] = "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E" + "\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D"; + unsigned char out[WC_SHA_DIGEST_SIZE]; + + XMEMSET(out, 0, WC_SHA_DIGEST_SIZE); + AssertNotNull(SHA1(in, XSTRLEN((char*)in), out)); + AssertIntEQ(XMEMCMP(out, expected, WC_SHA_DIGEST_SIZE), 0); + } + #endif + + #if !defined(NO_SHA256) + { + const unsigned char in[] = "abc"; + unsigned char expected[] = "\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"; + unsigned char out[WC_SHA256_DIGEST_SIZE]; + + XMEMSET(out, 0, WC_SHA256_DIGEST_SIZE); +#if !defined(NO_OLD_NAMES) && !defined(HAVE_FIPS) + AssertNotNull(SHA256(in, XSTRLEN((char*)in), out)); +#else + AssertNotNull(wolfSSL_SHA256(in, XSTRLEN((char*)in), out)); +#endif + AssertIntEQ(XMEMCMP(out, expected, WC_SHA256_DIGEST_SIZE), 0); + } + #endif + + #if defined(WOLFSSL_SHA384) + { + const unsigned char in[] = "abc"; + unsigned char expected[] = "\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"; + unsigned char out[WC_SHA384_DIGEST_SIZE]; + + XMEMSET(out, 0, WC_SHA384_DIGEST_SIZE); +#if !defined(NO_OLD_NAMES) && !defined(HAVE_FIPS) + AssertNotNull(SHA384(in, XSTRLEN((char*)in), out)); +#else + AssertNotNull(wolfSSL_SHA384(in, XSTRLEN((char*)in), out)); +#endif + AssertIntEQ(XMEMCMP(out, expected, WC_SHA384_DIGEST_SIZE), 0); + } + #endif + + #if defined(WOLFSSL_SHA512) + { + const unsigned char in[] = "abc"; + unsigned char expected[] = "\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"; + unsigned char out[WC_SHA512_DIGEST_SIZE]; + + XMEMSET(out, 0, WC_SHA512_DIGEST_SIZE); +#if !defined(NO_OLD_NAMES) && !defined(HAVE_FIPS) + AssertNotNull(SHA512(in, XSTRLEN((char*)in), out)); +#else + AssertNotNull(wolfSSL_SHA512(in, XSTRLEN((char*)in), out)); +#endif + AssertIntEQ(XMEMCMP(out, expected, WC_SHA512_DIGEST_SIZE), 0); + } + #endif + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_DH_1536_prime(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_DH) + BIGNUM* bn; + unsigned char bits[200]; + int sz = 192; /* known binary size */ + const byte expected[] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34, + 0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, + 0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74, + 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22, + 0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, + 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B, + 0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37, + 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45, + 0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6, + 0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B, + 0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, + 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5, + 0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6, + 0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D, + 0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05, + 0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A, + 0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, + 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96, + 0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB, + 0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D, + 0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04, + 0xF1,0x74,0x6C,0x08,0xCA,0x23,0x73,0x27, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + }; + + printf(testingFmt, "wolfSSL_DH_1536_prime()"); + + AssertNotNull(bn = get_rfc3526_prime_1536(NULL)); + AssertIntEQ(sz, BN_bn2bin((const BIGNUM*)bn, bits)); + AssertIntEQ(0, XMEMCMP(expected, bits, sz)); + + BN_free(bn); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_PEM_write_DHparams(void) +{ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +#if defined(OPENSSL_EXTRA) && !defined(NO_DH) && !defined(NO_FILESYSTEM) + DH* dh; + BIO* bio; + XFILE fp; + byte pem[2048]; + int pemSz; + const char expected[] = +"-----BEGIN DH PARAMETERS-----\n\ +MIIBCAKCAQEAsKEIBpwIE7pZBjy8MNX1AMFPRKfW70rGJScc6NKWUwpckd2iwpSE\n\ +v32yRJ+b0sGKxb5yXKfnkebUn3MHhVtmSMdw+rTuAsk9mkraPcFGPhlp0RdGB6NN\n\ +nyuWFzltMI0q85TTdc+gdebykh8acAWqBINXMPvadpM4UOgn/WPuPOW3yAmub1A1\n\ +joTOSgDpEn5aMdcz/CETdswWMNsM/MVipzW477ewrMA29tnJRkj5QJAAKxuqbOMa\n\ +wwsDnhvCRuRITiJzb8Nf1JrWMAdI1oyQq9T28eNI01hLprnNKb9oHwhLY4YvXGvW\n\ +tgZl96bcAGdru8OpQYP7x/rI4h5+rwA/kwIBAg==\n\ +-----END DH PARAMETERS-----\n"; + printf(testingFmt, "wolfSSL_PEM_write_DHparams()"); + + AssertNotNull(fp = XFOPEN(dhParamFile, "rb")); + AssertIntGT((pemSz = (int)XFREAD(pem, 1, sizeof(pem), fp)), 0); + XFCLOSE(fp); + + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertIntEQ(BIO_write(bio, pem, pemSz), pemSz); + AssertNotNull(dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL)); + BIO_free(bio); + + AssertNotNull(fp = XFOPEN("./test-write-dhparams.pem", "wb")); + AssertIntEQ(PEM_write_DHparams(fp, dh), WOLFSSL_SUCCESS); + AssertIntEQ(PEM_write_DHparams(fp, NULL), WOLFSSL_FAILURE); + XFCLOSE(fp); + DH_free(dh); + + /* check results */ + XMEMSET(pem, 0, sizeof(pem)); + AssertNotNull(fp = XFOPEN("./test-write-dhparams.pem", "rb")); + AssertIntGT((pemSz = (int)XFREAD(pem, 1, sizeof(pem), fp)), 0); + AssertIntEQ(XMEMCMP(pem, expected, pemSz), 0); + XFCLOSE(fp); + + printf(resultFmt, passed); +#endif /* OPENSSL_ALL || OPENSSL_QT */ +#endif +} + +static void test_wolfSSL_AES_ecb_encrypt(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_AES) && defined(HAVE_AES_ECB) + AES_KEY aes; + const byte msg[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte verify[] = + { + 0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c, + 0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8 + }; + + const 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 out[AES_BLOCK_SIZE]; + + printf(testingFmt, "wolfSSL_AES_ecb_encrypt()"); + + AssertIntEQ(AES_set_encrypt_key(key, sizeof(key)*8, &aes), 0); + XMEMSET(out, 0, AES_BLOCK_SIZE); + AES_ecb_encrypt(msg, out, &aes, AES_ENCRYPT); + AssertIntEQ(XMEMCMP(out, verify, AES_BLOCK_SIZE), 0); + +#ifdef HAVE_AES_DECRYPT + AssertIntEQ(AES_set_decrypt_key(key, sizeof(key)*8, &aes), 0); + XMEMSET(out, 0, AES_BLOCK_SIZE); + AES_ecb_encrypt(verify, out, &aes, AES_DECRYPT); + AssertIntEQ(XMEMCMP(out, msg, AES_BLOCK_SIZE), 0); +#endif + + /* test bad arguments */ + AES_ecb_encrypt(NULL, out, &aes, AES_DECRYPT); + AES_ecb_encrypt(verify, NULL, &aes, AES_DECRYPT); + AES_ecb_encrypt(verify, out, NULL, AES_DECRYPT); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_SHA256(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_SHA256) && \ + defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + unsigned char input[] = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + unsigned char 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"; + size_t inLen; + byte hash[WC_SHA256_DIGEST_SIZE]; + + printf(testingFmt, "wolfSSL_SHA256()"); + inLen = XSTRLEN((char*)input); + + XMEMSET(hash, 0, WC_SHA256_DIGEST_SIZE); + AssertNotNull(SHA256(input, inLen, hash)); + AssertIntEQ(XMEMCMP(hash, output, WC_SHA256_DIGEST_SIZE), 0); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_get_serialNumber(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_RSA) + ASN1_INTEGER* a; + BIGNUM* bn; + X509* x509; + char *serialHex; + + printf(testingFmt, "wolfSSL_X509_get_serialNumber()"); + + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(svrCertFile, + SSL_FILETYPE_PEM)); + AssertNotNull(a = X509_get_serialNumber(x509)); + + /* check on value of ASN1 Integer */ + AssertNotNull(bn = ASN1_INTEGER_to_BN(a, NULL)); + + X509_free(x509); /* free's a */ + + AssertNotNull(serialHex = BN_bn2hex(bn)); +#ifndef WC_DISABLE_RADIX_ZERO_PAD + AssertStrEQ(serialHex, "01"); +#else + AssertStrEQ(serialHex, "1"); +#endif + OPENSSL_free(serialHex); + + AssertIntEQ(BN_get_word(bn), 1); + + BN_free(bn); + + /* hard test free'ing with dynamic buffer to make sure there is no leaks */ + a = ASN1_INTEGER_new(); + if (a) { + AssertNotNull(a->data = (unsigned char*)XMALLOC(100, NULL, + DYNAMIC_TYPE_OPENSSL)); + a->isDynamic = 1; + ASN1_INTEGER_free(a); + } + + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_OpenSSL_add_all_algorithms(void){ +#if defined(OPENSSL_EXTRA) + printf(testingFmt, "wolfSSL_OpenSSL_add_all_algorithms()"); + + AssertIntEQ(wolfSSL_add_all_algorithms(),WOLFSSL_SUCCESS); + wolfSSL_Cleanup(); + + AssertIntEQ(wolfSSL_OpenSSL_add_all_algorithms_noconf(),WOLFSSL_SUCCESS); + wolfSSL_Cleanup(); + + AssertIntEQ(wolfSSL_OpenSSL_add_all_algorithms_conf(),WOLFSSL_SUCCESS); + wolfSSL_Cleanup(); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_ASN1_STRING_print_ex(void){ +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + ASN1_STRING* asn_str; + const char data[] = "Hello wolfSSL!"; + ASN1_STRING* esc_str; + const char esc_data[] = "a+;<>"; + BIO *bio; + unsigned long flags; + int p_len; + unsigned char rbuf[255]; + + printf(testingFmt, "wolfSSL_ASN1_STRING_print_ex()"); + + /* setup */ + XMEMSET(rbuf, 0, 255); + bio = BIO_new(BIO_s_mem()); + BIO_set_write_buf_size(bio,255); + + asn_str = ASN1_STRING_type_new(V_ASN1_OCTET_STRING); + ASN1_STRING_set(asn_str, (const void*)data, sizeof(data)); + esc_str = ASN1_STRING_type_new(V_ASN1_OCTET_STRING); + ASN1_STRING_set(esc_str, (const void*)esc_data, sizeof(esc_data)); + + /* no flags */ + XMEMSET(rbuf, 0, 255); + flags = 0; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); + AssertIntEQ(p_len, 15); + BIO_read(bio, (void*)rbuf, 15); + AssertStrEQ((char*)rbuf, "Hello wolfSSL!"); + + /* RFC2253 Escape */ + XMEMSET(rbuf, 0, 255); + flags = ASN1_STRFLGS_ESC_2253; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, esc_str, flags); + AssertIntEQ(p_len, 9); + BIO_read(bio, (void*)rbuf, 9); + AssertStrEQ((char*)rbuf, "a\\+\\;\\<\\>"); + + /* Show type */ + XMEMSET(rbuf, 0, 255); + flags = ASN1_STRFLGS_SHOW_TYPE; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); + AssertIntEQ(p_len, 28); + BIO_read(bio, (void*)rbuf, 28); + AssertStrEQ((char*)rbuf, "OCTET STRING:Hello wolfSSL!"); + + /* Dump All */ + XMEMSET(rbuf, 0, 255); + flags = ASN1_STRFLGS_DUMP_ALL; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); + AssertIntEQ(p_len, 31); + BIO_read(bio, (void*)rbuf, 31); + AssertStrEQ((char*)rbuf, "#48656C6C6F20776F6C6653534C2100"); + + /* Dump Der */ + XMEMSET(rbuf, 0, 255); + flags = ASN1_STRFLGS_DUMP_ALL | ASN1_STRFLGS_DUMP_DER; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); + AssertIntEQ(p_len, 35); + BIO_read(bio, (void*)rbuf, 35); + AssertStrEQ((char*)rbuf, "#040F48656C6C6F20776F6C6653534C2100"); + + /* Dump All + Show type */ + XMEMSET(rbuf, 0, 255); + flags = ASN1_STRFLGS_DUMP_ALL | ASN1_STRFLGS_SHOW_TYPE; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); + AssertIntEQ(p_len, 44); + BIO_read(bio, (void*)rbuf, 44); + AssertStrEQ((char*)rbuf, "OCTET STRING:#48656C6C6F20776F6C6653534C2100"); + + BIO_free(bio); + ASN1_STRING_free(asn_str); + ASN1_STRING_free(esc_str); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_ASN1_TIME_to_generalizedtime(void){ +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) + WOLFSSL_ASN1_TIME *t; + WOLFSSL_ASN1_TIME *out; + WOLFSSL_ASN1_TIME *gtime; + int tlen = 0; + unsigned char *data; + + printf(testingFmt, "wolfSSL_ASN1_TIME_to_generalizedtime()"); + + /* UTC Time test */ + AssertNotNull(t = wolfSSL_ASN1_TIME_new()); + XMEMSET(t->data, 0, ASN_GENERALIZED_TIME_SIZE); + AssertNotNull(out = wolfSSL_ASN1_TIME_new()); + t->type = ASN_UTC_TIME; + t->length = ASN_UTC_TIME_SIZE; + XMEMCPY(t->data, "050727123456Z", ASN_UTC_TIME_SIZE); + + tlen = wolfSSL_ASN1_TIME_get_length(t); + AssertIntEQ(tlen, ASN_UTC_TIME_SIZE); + data = wolfSSL_ASN1_TIME_get_data(t); + AssertStrEQ((char*)data, "050727123456Z"); + gtime = wolfSSL_ASN1_TIME_to_generalizedtime(t, &out); + AssertIntEQ(gtime->type, ASN_GENERALIZED_TIME); + AssertIntEQ(gtime->length, ASN_GENERALIZED_TIME_SIZE); + AssertStrEQ((char*)gtime->data, "20050727123456Z"); + + /* Generalized Time test */ + XMEMSET(t, 0, ASN_GENERALIZED_TIME_SIZE); + XMEMSET(out, 0, ASN_GENERALIZED_TIME_SIZE); + XMEMSET(data, 0, ASN_GENERALIZED_TIME_SIZE); + t->type = ASN_GENERALIZED_TIME; + t->length = ASN_GENERALIZED_TIME_SIZE; + XMEMCPY(t->data, "20050727123456Z", ASN_GENERALIZED_TIME_SIZE); + + tlen = wolfSSL_ASN1_TIME_get_length(t); + AssertIntEQ(tlen, ASN_GENERALIZED_TIME_SIZE); + data = wolfSSL_ASN1_TIME_get_data(t); + AssertStrEQ((char*)data, "20050727123456Z"); + gtime = wolfSSL_ASN1_TIME_to_generalizedtime(t, &out); + AssertIntEQ(gtime->type, ASN_GENERALIZED_TIME); + AssertIntEQ(gtime->length, ASN_GENERALIZED_TIME_SIZE); + AssertStrEQ((char*)gtime->data, "20050727123456Z"); + XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* Null parameter test */ + XMEMSET(t, 0, ASN_GENERALIZED_TIME_SIZE); + gtime = NULL; + out = NULL; + t->type = ASN_UTC_TIME; + t->length = ASN_UTC_TIME_SIZE; + XMEMCPY(t->data, "050727123456Z", ASN_UTC_TIME_SIZE); + AssertNotNull(gtime = wolfSSL_ASN1_TIME_to_generalizedtime(t, NULL)); + AssertIntEQ(gtime->type, ASN_GENERALIZED_TIME); + AssertIntEQ(gtime->length, ASN_GENERALIZED_TIME_SIZE); + AssertStrEQ((char*)gtime->data, "20050727123456Z"); + + XFREE(gtime, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_CA_num(void){ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ + defined(HAVE_ECC) && !defined(NO_RSA) + WOLFSSL_X509_STORE *store; + WOLFSSL_X509 *x509_1, *x509_2; + int ca_num = 0; + + printf(testingFmt, "wolfSSL_X509_CA_num()"); + + store = wolfSSL_X509_STORE_new(); + x509_1 = wolfSSL_X509_load_certificate_file(svrCertFile, WOLFSSL_FILETYPE_PEM); + wolfSSL_X509_STORE_add_cert(store, x509_1); + ca_num = wolfSSL_X509_CA_num(store); + AssertIntEQ(ca_num, 1); + + x509_2 = wolfSSL_X509_load_certificate_file(eccCertFile, WOLFSSL_FILETYPE_PEM); + wolfSSL_X509_STORE_add_cert(store, x509_2); + ca_num = wolfSSL_X509_CA_num(store); + AssertIntEQ(ca_num, 2); + + wolfSSL_X509_free(x509_1); + wolfSSL_X509_free(x509_2); + wolfSSL_X509_STORE_free(store); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_check_ca(void){ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) + WOLFSSL_X509 *x509; + + printf(testingFmt, "wolfSSL_X509_check_ca()"); + + x509 = wolfSSL_X509_load_certificate_file(svrCertFile, WOLFSSL_FILETYPE_PEM); + AssertIntEQ(wolfSSL_X509_check_ca(x509), 1); + wolfSSL_X509_free(x509); + + x509 = wolfSSL_X509_load_certificate_file(ntruCertFile, WOLFSSL_FILETYPE_PEM); + AssertIntEQ(wolfSSL_X509_check_ca(x509), 0); + wolfSSL_X509_free(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_DC_cert(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_KEY_GEN) && \ + defined(WOLFSSL_CERT_EXT) + Cert cert; + RsaKey key; + WC_RNG rng; + byte der[FOURK_BUF]; + int certSz; + int ret, idx; + const byte mySerial[8] = {1,2,3,4,5,6,7,8}; + const unsigned char* pt; + + X509* x509; + X509_NAME* x509name; + X509_NAME_ENTRY* entry; + ASN1_STRING* entryValue; + + CertName name; + printf(testingFmt, "wolfSSL Certs with DC"); + + XMEMSET(&name, 0, sizeof(CertName)); + + /* set up cert name */ + XMEMCPY(name.country, "US", sizeof("US")); + name.countryEnc = CTC_PRINTABLE; + XMEMCPY(name.state, "Oregon", sizeof("Oregon")); + name.stateEnc = CTC_UTF8; + XMEMCPY(name.locality, "Portland", sizeof("Portland")); + name.localityEnc = CTC_UTF8; + XMEMCPY(name.sur, "Test", sizeof("Test")); + name.surEnc = CTC_UTF8; + XMEMCPY(name.org, "wolfSSL", sizeof("wolfSSL")); + name.orgEnc = CTC_UTF8; + XMEMCPY(name.unit, "Development", sizeof("Development")); + name.unitEnc = CTC_UTF8; + XMEMCPY(name.commonName, "www.wolfssl.com", sizeof("www.wolfssl.com")); + name.commonNameEnc = CTC_UTF8; + XMEMCPY(name.serialDev, "wolfSSL12345", sizeof("wolfSSL12345")); + name.serialDevEnc = CTC_PRINTABLE; +#ifdef WOLFSSL_MULTI_ATTRIB + #if CTC_MAX_ATTRIB > 2 + { + NameAttrib* n; + n = &name.name[0]; + n->id = ASN_DOMAIN_COMPONENT; + n->type = CTC_UTF8; + n->sz = sizeof("com"); + XMEMCPY(n->value, "com", sizeof("com")); + + n = &name.name[1]; + n->id = ASN_DOMAIN_COMPONENT; + n->type = CTC_UTF8; + n->sz = sizeof("wolfssl"); + XMEMCPY(n->value, "wolfssl", sizeof("wolfssl")); + } + #endif +#endif /* WOLFSSL_MULTI_ATTRIB */ + + AssertIntEQ(wc_InitRsaKey(&key, HEAP_HINT), 0); +#ifndef HAVE_FIPS + AssertIntEQ(wc_InitRng_ex(&rng, HEAP_HINT, devId), 0); +#else + AssertIntEQ(wc_InitRng(&rng), 0); +#endif + AssertIntEQ(wc_MakeRsaKey(&key, 1024, 3, &rng), 0); + + + XMEMSET(&cert, 0 , sizeof(Cert)); + AssertIntEQ(wc_InitCert(&cert), 0); + + XMEMCPY(&cert.subject, &name, sizeof(CertName)); + XMEMCPY(cert.serial, mySerial, sizeof(mySerial)); + cert.serialSz = (int)sizeof(mySerial); + cert.isCA = 1; +#ifndef NO_SHA256 + cert.sigType = CTC_SHA256wRSA; +#else + cert.sigType = CTC_SHAwRSA; +#endif + + /* add SKID from the Public Key */ + AssertIntEQ(wc_SetSubjectKeyIdFromPublicKey(&cert, &key, NULL), 0); + + /* add AKID from the Public Key */ + AssertIntEQ(wc_SetAuthKeyIdFromPublicKey(&cert, &key, NULL), 0); + + 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(&cert, der, FOURK_BUF, &key, &rng); + } + } while (ret == WC_PENDING_E); + AssertIntGT(ret, 0); + certSz = ret; + + /* der holds a certificate with DC's now check X509 parsing of it */ + pt = der; + AssertNotNull(x509 = d2i_X509(NULL, &pt, certSz)); + AssertNotNull(x509name = X509_get_subject_name(x509)); +#ifdef WOLFSSL_MULTI_ATTRIB + AssertIntEQ((idx = X509_NAME_get_index_by_NID(x509name, NID_domainComponent, + -1)), 5); + AssertIntEQ((idx = X509_NAME_get_index_by_NID(x509name, NID_domainComponent, + idx)), 6); + AssertIntEQ((idx = X509_NAME_get_index_by_NID(x509name, NID_domainComponent, + idx)), -1); +#endif /* WOLFSSL_MULTI_ATTRIB */ + + /* compare DN at index 0 */ + AssertNotNull(entry = X509_NAME_get_entry(x509name, 0)); + AssertNotNull(entryValue = X509_NAME_ENTRY_get_data(entry)); + AssertIntEQ(ASN1_STRING_length(entryValue), 2); + AssertStrEQ((const char*)ASN1_STRING_data(entryValue), "US"); + +#ifdef WOLFSSL_MULTI_ATTRIB + /* get first and second DC and compare result */ + AssertIntEQ((idx = X509_NAME_get_index_by_NID(x509name, NID_domainComponent, + -1)), 5); + AssertNotNull(entry = X509_NAME_get_entry(x509name, idx)); + AssertNotNull(entryValue = X509_NAME_ENTRY_get_data(entry)); + AssertStrEQ((const char *)ASN1_STRING_data(entryValue), "com"); + + AssertIntEQ((idx = X509_NAME_get_index_by_NID(x509name, NID_domainComponent, + idx)), 6); + AssertNotNull(entry = X509_NAME_get_entry(x509name, idx)); + AssertNotNull(entryValue = X509_NAME_ENTRY_get_data(entry)); + AssertStrEQ((const char *)ASN1_STRING_data(entryValue), "wolfssl"); +#endif /* WOLFSSL_MULTI_ATTRIB */ + + /* try invalid index locations for regression test and sanity check */ + AssertNull(entry = X509_NAME_get_entry(x509name, 11)); + AssertNull(entry = X509_NAME_get_entry(x509name, 20)); + + (void)idx; + X509_free(x509); + wc_FreeRsaKey(&key); + wc_FreeRng(&rng); + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_X509_get_version(void){ +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) + WOLFSSL_X509 *x509; + + printf(testingFmt, "wolfSSL_X509_get_version()"); + + x509 = wolfSSL_X509_load_certificate_file(svrCertFile, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ((int)wolfSSL_X509_get_version(x509), 2); + wolfSSL_X509_free(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_DES_ncbc(void){ +#if defined(OPENSSL_EXTRA) && !defined(NO_DES3) + const_DES_cblock myDes; + DES_cblock iv = {1}; + DES_key_schedule key = {0}; + unsigned char msg[] = "hello wolfssl"; + unsigned char out[DES_BLOCK_SIZE * 2] = {0}; + unsigned char pln[DES_BLOCK_SIZE * 2] = {0}; + + unsigned char exp[] = {0x31, 0x98, 0x2F, 0x3A, 0x55, 0xBF, 0xD8, 0xC4}; + unsigned char exp2[] = {0xC7, 0x45, 0x8B, 0x28, 0x10, 0x53, 0xE0, 0x58}; + + printf(testingFmt, "wolfSSL_DES_ncbc()"); + + /* partial block test */ + DES_set_key(&key, &myDes); + DES_ncbc_encrypt(msg, out, 3, &myDes, &iv, DES_ENCRYPT); + AssertIntEQ(XMEMCMP(exp, out, DES_BLOCK_SIZE), 0); + AssertIntEQ(XMEMCMP(exp, iv, DES_BLOCK_SIZE), 0); + + DES_set_key(&key, &myDes); + XMEMSET((byte*)&iv, 0, DES_BLOCK_SIZE); + *((byte*)&iv) = 1; + DES_ncbc_encrypt(out, pln, 3, &myDes, &iv, DES_DECRYPT); + AssertIntEQ(XMEMCMP(msg, pln, 3), 0); + AssertIntEQ(XMEMCMP(exp, iv, DES_BLOCK_SIZE), 0); + + /* full block test */ + DES_set_key(&key, &myDes); + XMEMSET(pln, 0, DES_BLOCK_SIZE); + XMEMSET((byte*)&iv, 0, DES_BLOCK_SIZE); + *((byte*)&iv) = 1; + DES_ncbc_encrypt(msg, out, 8, &myDes, &iv, DES_ENCRYPT); + AssertIntEQ(XMEMCMP(exp2, out, DES_BLOCK_SIZE), 0); + AssertIntEQ(XMEMCMP(exp2, iv, DES_BLOCK_SIZE), 0); + + DES_set_key(&key, &myDes); + XMEMSET((byte*)&iv, 0, DES_BLOCK_SIZE); + *((byte*)&iv) = 1; + DES_ncbc_encrypt(out, pln, 8, &myDes, &iv, DES_DECRYPT); + AssertIntEQ(XMEMCMP(msg, pln, 8), 0); + AssertIntEQ(XMEMCMP(exp2, iv, DES_BLOCK_SIZE), 0); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_AES_cbc_encrypt() +{ +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(OPENSSL_EXTRA) + AES_KEY aes; + AES_KEY* aesN = NULL; + size_t len = 0; + size_t lenB = 0; + int keySz0 = 0; + int keySzN = -1; + byte out[AES_BLOCK_SIZE] = {0}; + byte* outN = NULL; + const int enc1 = AES_ENCRYPT; + const int enc2 = AES_DECRYPT; + + /* Test vectors retrieved from: + * + * https://csrc.nist.gov/ + * CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/ + * documents/aes/KAT_AES.zip + * + */ + const byte* pt128N = NULL; + byte* key128N = NULL; + byte* iv128N = NULL; + byte iv128tmp[AES_BLOCK_SIZE] = {0}; + + const byte pt128[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + + const byte ct128[] = { 0x87,0x85,0xb1,0xa7,0x5b,0x0f,0x3b,0xd9, + 0x58,0xdc,0xd0,0xe2,0x93,0x18,0xc5,0x21 }; + + const byte iv128[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + + byte key128[] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00 }; + + + len = sizeof(pt128); + + #define STRESS_T(a, b, c, d, e, f, g, h, i) \ + wolfSSL_AES_cbc_encrypt(a, b, c, d, e, f); \ + AssertIntNE(XMEMCMP(b, g, h), i) + + #define RESET_IV(x, y) XMEMCPY(x, y, AES_BLOCK_SIZE) + + printf(testingFmt, "Stressing wolfSSL_AES_cbc_encrypt()"); + STRESS_T(pt128N, out, len, &aes, iv128tmp, enc1, ct128, AES_BLOCK_SIZE, 0); + STRESS_T(pt128, out, len, &aes, iv128N, enc1, ct128, AES_BLOCK_SIZE, 0); + + wolfSSL_AES_cbc_encrypt(pt128, outN, len, &aes, iv128tmp, enc1); + AssertIntNE(XMEMCMP(out, ct128, AES_BLOCK_SIZE), 0); + wolfSSL_AES_cbc_encrypt(pt128, out, len, aesN, iv128tmp, enc1); + AssertIntNE(XMEMCMP(out, ct128, AES_BLOCK_SIZE), 0); + + STRESS_T(pt128, out, lenB, &aes, iv128tmp, enc1, ct128, AES_BLOCK_SIZE, 0); + printf(resultFmt, "Stress Tests: passed"); + + printf(testingFmt, "Stressing wolfSSL_AES_set_encrypt_key"); + AssertIntNE(wolfSSL_AES_set_encrypt_key(key128N, sizeof(key128)*8, &aes),0); + AssertIntNE(wolfSSL_AES_set_encrypt_key(key128, sizeof(key128)*8, aesN),0); + AssertIntNE(wolfSSL_AES_set_encrypt_key(key128, keySz0, &aes), 0); + AssertIntNE(wolfSSL_AES_set_encrypt_key(key128, keySzN, &aes), 0); + printf(resultFmt, "Stress Tests: passed"); + + printf(testingFmt, "Stressing wolfSSL_AES_set_decrypt_key"); + AssertIntNE(wolfSSL_AES_set_decrypt_key(key128N, sizeof(key128)*8, &aes),0); + AssertIntNE(wolfSSL_AES_set_decrypt_key(key128N, sizeof(key128)*8, aesN),0); + AssertIntNE(wolfSSL_AES_set_decrypt_key(key128, keySz0, &aes), 0); + AssertIntNE(wolfSSL_AES_set_decrypt_key(key128, keySzN, &aes), 0); + printf(resultFmt, "Stress Tests: passed"); + + #ifdef WOLFSSL_AES_128 + + printf(testingFmt, "wolfSSL_AES_cbc_encrypt() 128-bit"); + XMEMSET(out, 0, AES_BLOCK_SIZE); + RESET_IV(iv128tmp, iv128); + + AssertIntEQ(wolfSSL_AES_set_encrypt_key(key128, sizeof(key128)*8, &aes), 0); + wolfSSL_AES_cbc_encrypt(pt128, out, len, &aes, iv128tmp, enc1); + AssertIntEQ(XMEMCMP(out, ct128, AES_BLOCK_SIZE), 0); + printf(resultFmt, "passed"); + + #ifdef HAVE_AES_DECRYPT + + printf(testingFmt, "wolfSSL_AES_cbc_encrypt() 128-bit in decrypt mode"); + XMEMSET(out, 0, AES_BLOCK_SIZE); + RESET_IV(iv128tmp, iv128); + len = sizeof(ct128); + + AssertIntEQ(wolfSSL_AES_set_decrypt_key(key128, sizeof(key128)*8, &aes), 0); + wolfSSL_AES_cbc_encrypt(ct128, out, len, &aes, iv128tmp, enc2); + AssertIntEQ(XMEMCMP(out, pt128, AES_BLOCK_SIZE), 0); + printf(resultFmt, "passed"); + + #endif + + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + /* Test vectors from NIST Special Publication 800-38A, 2001 Edition + * Appendix F.2.3 */ + + byte iv192tmp[AES_BLOCK_SIZE] = {0}; + + const byte pt192[] = { 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a }; + + const byte ct192[] = { 0x4f,0x02,0x1d,0xb2,0x43,0xbc,0x63,0x3d, + 0x71,0x78,0x18,0x3a,0x9f,0xa0,0x71,0xe8 }; + + const byte iv192[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }; + + byte key192[] = { 0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0x52, + 0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5, + 0x62,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b }; + + len = sizeof(pt192); + + printf(testingFmt, "wolfSSL_AES_cbc_encrypt() 192-bit"); + XMEMSET(out, 0, AES_BLOCK_SIZE); + RESET_IV(iv192tmp, iv192); + + AssertIntEQ(wolfSSL_AES_set_encrypt_key(key192, sizeof(key192)*8, &aes), 0); + wolfSSL_AES_cbc_encrypt(pt192, out, len, &aes, iv192tmp, enc1); + AssertIntEQ(XMEMCMP(out, ct192, AES_BLOCK_SIZE), 0); + printf(resultFmt, "passed"); + + #ifdef HAVE_AES_DECRYPT + + printf(testingFmt, "wolfSSL_AES_cbc_encrypt() 192-bit in decrypt mode"); + len = sizeof(ct192); + RESET_IV(iv192tmp, iv192); + XMEMSET(out, 0, AES_BLOCK_SIZE); + + AssertIntEQ(wolfSSL_AES_set_decrypt_key(key192, sizeof(key192)*8, &aes), 0); + wolfSSL_AES_cbc_encrypt(ct192, out, len, &aes, iv192tmp, enc2); + AssertIntEQ(XMEMCMP(out, pt192, AES_BLOCK_SIZE), 0); + printf(resultFmt, "passed"); + + #endif + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + /* Test vectors from NIST Special Publication 800-38A, 2001 Edition, + * Appendix F.2.5 */ + byte iv256tmp[AES_BLOCK_SIZE] = {0}; + + const byte pt256[] = { 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a }; + + const byte ct256[] = { 0xf5,0x8c,0x4c,0x04,0xd6,0xe5,0xf1,0xba, + 0x77,0x9e,0xab,0xfb,0x5f,0x7b,0xfb,0xd6 }; + + const byte iv256[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }; + + byte key256[] = { 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 }; + + + len = sizeof(pt256); + + printf(testingFmt, "wolfSSL_AES_cbc_encrypt() 256-bit"); + XMEMSET(out, 0, AES_BLOCK_SIZE); + RESET_IV(iv256tmp, iv256); + + AssertIntEQ(wolfSSL_AES_set_encrypt_key(key256, sizeof(key256)*8, &aes), 0); + wolfSSL_AES_cbc_encrypt(pt256, out, len, &aes, iv256tmp, enc1); + AssertIntEQ(XMEMCMP(out, ct256, AES_BLOCK_SIZE), 0); + printf(resultFmt, "passed"); + + #ifdef HAVE_AES_DECRYPT + + printf(testingFmt, "wolfSSL_AES_cbc_encrypt() 256-bit in decrypt mode"); + len = sizeof(ct256); + RESET_IV(iv256tmp, iv256); + XMEMSET(out, 0, AES_BLOCK_SIZE); + + AssertIntEQ(wolfSSL_AES_set_decrypt_key(key256, sizeof(key256)*8, &aes), 0); + wolfSSL_AES_cbc_encrypt(ct256, out, len, &aes, iv256tmp, enc2); + AssertIntEQ(XMEMCMP(out, pt256, AES_BLOCK_SIZE), 0); + printf(resultFmt, "passed"); + + #endif + #endif /* WOLFSSL_AES_256 */ +#endif +} + +#if defined(WOLFSSL_QT) +#if !defined(NO_ASN) +static void test_wolfSSL_ASN1_STRING_to_UTF8(void) +{ + WOLFSSL_X509* x509; + WOLFSSL_X509_NAME* subject; + WOLFSSL_X509_NAME_ENTRY* e; + WOLFSSL_ASN1_STRING* a; + FILE* file; + int idx = 0; + char targetOutput[16] = "www.wolfssl.com"; + unsigned char* actual_output; + int len = 0; + int result = 0; + + AssertNotNull(file = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(file, NULL, NULL, NULL)); + fclose(file); + + printf(testingFmt, "wolfSSL_ASN1_STRING_to_UTF8(): NID_commonName"); + AssertNotNull(subject = wolfSSL_X509_get_subject_name(x509)); + AssertIntEQ((idx = wolfSSL_X509_NAME_get_index_by_NID(subject, + NID_commonName, -1)), 5); + AssertNotNull(e = wolfSSL_X509_NAME_get_entry(subject, idx)); + AssertNotNull(a = wolfSSL_X509_NAME_ENTRY_get_data(e)); + AssertIntEQ((len = wolfSSL_ASN1_STRING_to_UTF8(&actual_output, a)), 15); + result = strncmp((const char*)actual_output, targetOutput, len); + AssertIntEQ(result, 0); + printf(resultFmt, result == 0 ? passed : failed); + + printf(testingFmt, "wolfSSL_ASN1_STRING_to_UTF8(NULL, valid): "); + AssertIntEQ((len = wolfSSL_ASN1_STRING_to_UTF8(NULL, a)), + WOLFSSL_FATAL_ERROR); + printf(resultFmt, len == WOLFSSL_FATAL_ERROR ? passed : failed); + + printf(testingFmt, "wolfSSL_ASN1_STRING_to_UTF8(valid, NULL): "); + AssertIntEQ((len = wolfSSL_ASN1_STRING_to_UTF8(&actual_output, NULL)), + WOLFSSL_FATAL_ERROR); + printf(resultFmt, len == WOLFSSL_FATAL_ERROR ? passed : failed); + + printf(testingFmt, "wolfSSL_ASN1_STRING_to_UTF8(NULL, NULL): "); + AssertIntEQ((len = wolfSSL_ASN1_STRING_to_UTF8(NULL, NULL)), + WOLFSSL_FATAL_ERROR); + printf(resultFmt, len == WOLFSSL_FATAL_ERROR ? passed : failed); + + wolfSSL_X509_free(x509); + XFREE(actual_output, NULL, DYNAMIC_TYPE_TMP_BUFFER); +} +#endif /* !defined(NO_ASN) */ + +static void test_wolfSSL_sk_CIPHER_description(void) +{ + const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION; + int i,j,k; + int numCiphers = 0; + const SSL_METHOD *method = NULL; + const SSL_CIPHER *cipher = NULL; + STACK_OF(SSL_CIPHER) *supportedCiphers = NULL; + SSL_CTX *ctx = NULL; + SSL *ssl = NULL; + char buf[256]; + char test_str[9] = "0000000\0"; + const char badStr[] = "unknown\0"; + const char certPath[] = "./certs/client-cert.pem"; + XMEMSET(buf, 0, sizeof(buf)); + + printf(testingFmt, "wolfSSL_sk_CIPHER_description"); + + AssertNotNull(method = TLSv1_client_method()); + AssertNotNull(ctx = SSL_CTX_new(method)); + + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0); + SSL_CTX_set_verify_depth(ctx, 4); + + SSL_CTX_set_options(ctx, flags); + AssertIntEQ(SSL_CTX_load_verify_locations(ctx, certPath, NULL), + WOLFSSL_SUCCESS); + + AssertNotNull(ssl = SSL_new(ctx)); + /* SSL_get_ciphers returns a stack of all configured ciphers + * A flag, getCipherAtOffset, is set to later have SSL_CIPHER_description + */ + AssertNotNull(supportedCiphers = SSL_get_ciphers(ssl)); + + /* loop through the amount of supportedCiphers */ + numCiphers = sk_num(supportedCiphers); + for (i = 0; i < numCiphers; ++i) { + + /* sk_value increments "sk->data.cipher->cipherOffset". + * wolfSSL_sk_CIPHER_description sets the description for + * the cipher based on the provided offset. + */ + + if ((cipher = (const WOLFSSL_CIPHER*)sk_value(supportedCiphers, i))) { + SSL_CIPHER_description(cipher, buf, sizeof(buf)); + } + + /* Search cipher description string for "unknown" descriptor */ + for (j = 0; j < (int)XSTRLEN(buf); j++) { + k = 0; + while ((k < (int)XSTRLEN(badStr)) && (buf[j] == badStr[k])) { + test_str[k] = badStr[k]; + j++; + k++; + } + } + /* Fail if test_str == badStr == "unknown" */ + AssertStrNE(test_str,badStr); + } + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); +} + +static void test_wolfSSL_get_ciphers_compat(void) +{ + const SSL_METHOD *method = NULL; + const char certPath[] = "./certs/client-cert.pem"; + STACK_OF(SSL_CIPHER) *supportedCiphers = NULL; + SSL_CTX *ctx = NULL; + WOLFSSL *ssl = NULL; + const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION; + + printf(testingFmt, "wolfSSL_get_ciphers_compat"); + + AssertNotNull(method = TLSv1_client_method()); + AssertNotNull(ctx = SSL_CTX_new(method)); + + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0); + SSL_CTX_set_verify_depth(ctx, 4); + + SSL_CTX_set_options(ctx, flags); + AssertIntEQ(SSL_CTX_load_verify_locations(ctx, certPath, NULL), + WOLFSSL_SUCCESS); + + AssertNotNull(ssl = SSL_new(ctx)); + + /* Test Bad NULL input */ + AssertNull(supportedCiphers = SSL_get_ciphers(NULL)); + /* Test for Good input */ + AssertNotNull(supportedCiphers = SSL_get_ciphers(ssl)); + /* Further usage of SSL_get_ciphers/wolfSSL_get_ciphers_compat is + * tested in test_wolfSSL_sk_CIPHER_description according to Qt usage */ + + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); +} + +static void test_wolfSSL_X509_PUBKEY_get(void) +{ + WOLFSSL_X509_PUBKEY pubkey; + WOLFSSL_X509_PUBKEY* key; + WOLFSSL_EVP_PKEY evpkey; + WOLFSSL_EVP_PKEY* evpPkey; + WOLFSSL_EVP_PKEY* retEvpPkey; + + key = &pubkey; + evpPkey = &evpkey; + + evpPkey->type = WOLFSSL_SUCCESS; + key->pkey = evpPkey; + + printf(testingFmt, "wolfSSL_X509_PUBKEY_get()"); + AssertNotNull(retEvpPkey = wolfSSL_X509_PUBKEY_get(key)); + AssertIntEQ(retEvpPkey->type, WOLFSSL_SUCCESS); + + AssertNull(retEvpPkey = wolfSSL_X509_PUBKEY_get(NULL)); + + key->pkey = NULL; + AssertNull(retEvpPkey = wolfSSL_X509_PUBKEY_get(key)); + printf(resultFmt,retEvpPkey == NULL ? passed : failed); +} + +static void test_wolfSSL_d2i_DHparams() +{ +#if !defined(NO_DH) + FILE* f = NULL; + unsigned char buf[4096]; + const unsigned char* pt = buf; + const char* params1 = "./certs/dh2048.der"; + const char* params2 = "./certs/dh3072.der"; + long len = 0; + WOLFSSL_DH* dh = NULL; + XMEMSET(buf, 0, sizeof(buf)); + + /* Test 2048 bit parameters */ + printf(testingFmt, "wolfSSL_d2i_DHparams() 2048-bit"); + f = XFOPEN(params1, "rb"); + AssertTrue(f != XBADFILE); + len = (long)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + /* Valid case */ + AssertNotNull(dh = wolfSSL_d2i_DHparams(NULL, &pt, len)); + AssertNotNull(dh->p); + AssertNotNull(dh->g); + AssertTrue(pt != buf); + AssertIntEQ(DH_generate_key(dh), WOLFSSL_SUCCESS); + + /* Invalid cases */ + AssertNull(wolfSSL_d2i_DHparams(NULL, NULL, len)); + AssertNull(wolfSSL_d2i_DHparams(NULL, &pt, -1)); + AssertNull(wolfSSL_d2i_DHparams(NULL, &pt, 10)); + + DH_free(dh); + printf(resultFmt, passed); + + *buf = 0; + pt = buf; + + /* Test 3072 bit parameters */ + printf(testingFmt, "wolfSSL_d2i_DHparams() 3072-bit"); + f = XFOPEN(params2, "rb"); + AssertTrue(f != XBADFILE); + len = (long)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + /* Valid case */ + AssertNotNull(dh = wolfSSL_d2i_DHparams(NULL, &pt, len)); + AssertNotNull(dh->p); + AssertNotNull(dh->g); + AssertTrue(pt != buf); + AssertIntEQ(DH_generate_key(dh), 1); + + /* Invalid cases */ + AssertNull(wolfSSL_d2i_DHparams(NULL, NULL, len)); + AssertNull(wolfSSL_d2i_DHparams(NULL, &pt, -1)); + + DH_free(dh); + printf(resultFmt, passed); + +#endif +} + +static void test_wolfSSL_i2d_DHparams() +{ +#if !defined(NO_DH) + FILE* f; + unsigned char buf[4096]; + const unsigned char* pt = buf; + unsigned char* pt2 = buf; + const char* params1 = "./certs/dh2048.der"; + const char* params2 = "./certs/dh3072.der"; + long len; + WOLFSSL_DH* dh; + + /* Test 2048 bit parameters */ + printf(testingFmt, "wolfSSL_i2d_DHparams() 2048-bit"); + f = XFOPEN(params1, "rb"); + AssertTrue(f != XBADFILE); + len = (long)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + /* Valid case */ + AssertNotNull(dh = wolfSSL_d2i_DHparams(NULL, &pt, len)); + AssertTrue(pt != buf); + AssertIntEQ(DH_generate_key(dh), 1); + AssertIntEQ(wolfSSL_i2d_DHparams(dh, &pt2), 268); + + /* Invalid cases */ + AssertIntEQ(wolfSSL_i2d_DHparams(NULL, &pt2), 0); + AssertIntEQ(wolfSSL_i2d_DHparams(dh, NULL), 264); + + DH_free(dh); + printf(resultFmt, passed); + + *buf = 0; + pt = buf; + pt2 = buf; + + /* Test 3072 bit parameters */ + printf(testingFmt, "wolfSSL_i2d_DHparams() 3072-bit"); + f = XFOPEN(params2, "rb"); + AssertTrue(f != XBADFILE); + len = (long)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + /* Valid case */ + AssertNotNull(dh = wolfSSL_d2i_DHparams(NULL, &pt, len)); + AssertTrue(pt != buf); + AssertIntEQ(DH_generate_key(dh), 1); + AssertIntEQ(wolfSSL_i2d_DHparams(dh, &pt2), 396); + + /* Invalid cases */ + AssertIntEQ(wolfSSL_i2d_DHparams(NULL, &pt2), 0); + AssertIntEQ(wolfSSL_i2d_DHparams(dh, NULL), 392); + + DH_free(dh); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_EC_KEY_dup(void) +{ +#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL)) + + WOLFSSL_EC_KEY* ecKey; + WOLFSSL_EC_KEY* dupKey; + ecc_key* srcKey; + ecc_key* destKey; + + printf(testingFmt, "wolfSSL_EC_KEY_dup()"); + + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); + + /* Valid cases */ + AssertNotNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + AssertIntEQ(wc_ecc_check_key((ecc_key*)dupKey->internal), 0); + + /* Compare pubkey */ + srcKey = (ecc_key*)ecKey->internal; + destKey = (ecc_key*)dupKey->internal; + AssertIntEQ(wc_ecc_cmp_point(&srcKey->pubkey, &destKey->pubkey), 0); + + /* compare EC_GROUP */ + AssertIntEQ(wolfSSL_EC_GROUP_cmp(ecKey->group, dupKey->group, NULL), MP_EQ); + + /* compare EC_POINT */ + AssertIntEQ(wolfSSL_EC_POINT_cmp(ecKey->group, ecKey->pub_key, \ + dupKey->pub_key, NULL), MP_EQ); + + /* compare BIGNUM */ + AssertIntEQ(wolfSSL_BN_cmp(ecKey->priv_key, dupKey->priv_key), MP_EQ); + wolfSSL_EC_KEY_free(dupKey); + + /* Invalid cases */ + /* NULL key */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(NULL)); + /* NULL ecc_key */ + wc_ecc_free((ecc_key*)ecKey->internal); + XFREE(ecKey->internal, NULL, DYNAMIC_TYPE_ECC); + ecKey->internal = NULL; /* Set ecc_key to NULL */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + wolfSSL_EC_KEY_free(ecKey); + wolfSSL_EC_KEY_free(dupKey); + + /* NULL Group */ + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); + wolfSSL_EC_GROUP_free(ecKey->group); + ecKey->group = NULL; /* Set group to NULL */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + wolfSSL_EC_KEY_free(ecKey); + wolfSSL_EC_KEY_free(dupKey); + + /* NULL public key */ + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); + wc_ecc_del_point((ecc_point*)ecKey->pub_key->internal); + ecKey->pub_key->internal = NULL; /* Set ecc_point to NULL */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + + wolfSSL_EC_POINT_free(ecKey->pub_key); + ecKey->pub_key = NULL; /* Set pub_key to NULL */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + wolfSSL_EC_KEY_free(ecKey); + wolfSSL_EC_KEY_free(dupKey); + + /* NULL private key */ + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); +#if defined(WOLFSSL_PUBLIC_MP) + mp_int* mp = (mp_int*)ecKey->priv_key->internal; + mp_forcezero(mp); + mp_free(mp); + ecKey->priv_key->internal = NULL; /* Set internal key to NULL */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); +#endif + wolfSSL_BN_free(ecKey->priv_key); + ecKey->priv_key = NULL; /* Set priv_key to NULL */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + wolfSSL_EC_KEY_free(ecKey); + wolfSSL_EC_KEY_free(dupKey); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_EVP_PKEY_set1_get1_DSA(void) +{ +#if !defined(NO_DSA) + DSA *dsa = NULL; + DSA *setDsa = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY *set1Pkey = NULL; + + SHA_CTX sha; + byte signature[DSA_SIG_SIZE]; + byte hash[WC_SHA_DIGEST_SIZE]; + word32 bytes; + int answer; +#ifdef USE_CERT_BUFFERS_1024 + const unsigned char* dsaKeyDer = dsa_key_der1024; + int dsaKeySz = sizeof_dsa_key_der_1024; + byte tmp[ONEK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + XMEMCPY(tmp, dsaKeyDer , dsaKeySz); + bytes = dsa_key_der_sz; +#elif defined(USE_CERT_BUFFERS_2048) + const unsigned char* dsaKeyDer = dsa_key_der_2048; + int dsaKeySz = sizeof_dsa_key_der_2048; + byte tmp[TWOK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + XMEMCPY(tmp, dsaKeyDer , dsaKeySz); + bytes = dsaKeySz; +#else + const unsigned char* dsaKeyDer = dsa_key_der_2048; + int dsaKeySz = sizeof_dsa_key_der_2048; + byte tmp[TWOK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + XMEMCPY(tmp, dsaKeyDer , dsaKeySz); + XFILE fp = XOPEN("./certs/dsa2048.der", "rb"); + if (fp == XBADFILE) { + return WOLFSSL_BAD_FILE; + } + bytes = (word32) XFREAD(tmp, 1, sizeof(tmp), fp); + XFCLOSE(fp); +#endif /* END USE_CERT_BUFFERS_1024 */ + + printf(testingFmt, + "wolfSSL_EVP_PKEY_set1_DSA and wolfSSL_EVP_PKEY_get1_DSA"); + + /* Create hash to later Sign and Verify */ + AssertIntEQ(SHA1_Init(&sha), WOLFSSL_SUCCESS); + AssertIntEQ(SHA1_Update(&sha, tmp, bytes), WOLFSSL_SUCCESS); + AssertIntEQ(SHA1_Final(hash,&sha), WOLFSSL_SUCCESS); + + /* Initialize pkey with der format dsa key */ + AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_DSA, &pkey, + &dsaKeyDer ,(long)dsaKeySz)); + + /* Test wolfSSL_EVP_PKEY_get1_DSA */ + /* Should Fail: NULL argument */ + AssertNull(dsa = wolfSSL_EVP_PKEY_get1_DSA(NULL)); + /* Should Pass: Initialized pkey argument */ + AssertNotNull(dsa = wolfSSL_EVP_PKEY_get1_DSA(pkey)); + + /* Sign */ + AssertIntEQ(wolfSSL_DSA_do_sign(hash, signature, dsa), WOLFSSL_SUCCESS); + /* Verify. */ + AssertIntEQ(wolfSSL_DSA_do_verify(hash, signature, dsa, &answer), + WOLFSSL_SUCCESS); + + /* Test wolfSSL_EVP_PKEY_set1_DSA */ + /* Should Fail: set1Pkey not initialized */ + AssertIntNE(wolfSSL_EVP_PKEY_set1_DSA(set1Pkey, dsa), WOLFSSL_SUCCESS); + + /* Initialize set1Pkey */ + set1Pkey = wolfSSL_EVP_PKEY_new(); + + /* Should Fail Verify: setDsa not initialized from set1Pkey */ + AssertIntNE(wolfSSL_DSA_do_verify(hash,signature,setDsa,&answer), + WOLFSSL_SUCCESS); + + /* Should Pass: set dsa into set1Pkey */ + AssertIntEQ(wolfSSL_EVP_PKEY_set1_DSA(set1Pkey, dsa), WOLFSSL_SUCCESS); + printf(resultFmt, passed); + + DSA_free(dsa); + DSA_free(setDsa); + EVP_PKEY_free(pkey); + EVP_PKEY_free(set1Pkey); +#endif /* NO_DSA */ +} /* END test_EVP_PKEY_set1_get1_DSA */ + +static void test_wolfSSL_EVP_PKEY_set1_get1_EC_KEY (void) +{ +#ifdef HAVE_ECC + WOLFSSL_EC_KEY *ecKey = NULL; + WOLFSSL_EC_KEY *ecGet1 = NULL; + EVP_PKEY *pkey = NULL; + + printf(testingFmt, + "wolfSSL_EVP_PKEY_set1_EC_KEY and wolfSSL_EVP_PKEY_get1_EC_KEY"); + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertNotNull(pkey = wolfSSL_EVP_PKEY_new()); + + /* Test wolfSSL_EVP_PKEY_set1_EC_KEY */ + AssertIntEQ(wolfSSL_EVP_PKEY_set1_EC_KEY(NULL, ecKey), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EVP_PKEY_set1_EC_KEY(pkey, NULL), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EVP_PKEY_set1_EC_KEY(pkey, ecKey), WOLFSSL_SUCCESS); + + /* Test wolfSSL_EVP_PKEY_get1_EC_KEY */ + AssertNull(wolfSSL_EVP_PKEY_get1_EC_KEY(NULL)); + AssertNotNull(ecGet1 = wolfSSL_EVP_PKEY_get1_EC_KEY(pkey)); + + wolfSSL_EC_KEY_free(ecKey); + wolfSSL_EC_KEY_free(ecGet1); + EVP_PKEY_free(pkey); + + /* PASSED */ + printf(resultFmt, passed); +#endif /* HAVE_ECC */ +} /* END test_EVP_PKEY_set1_get1_EC_KEY */ + +static void test_wolfSSL_EVP_PKEY_set1_get1_DH (void) +{ +#if !defined(NO_DH) + DH *dh = NULL; + DH *setDh = NULL; + EVP_PKEY *pkey = NULL; + + FILE* f = NULL; + unsigned char buf[4096]; + const unsigned char* pt = buf; + const char* dh2048 = "./certs/dh2048.der"; + long len = 0; + int code = -1; + + printf(testingFmt,"wolfSSL_EVP_PKEY_set1_DH and wolfSSL_EVP_PKEY_get1_DH"); + + XMEMSET(buf, 0, sizeof(buf)); + + f = XFOPEN(dh2048, "rb"); + AssertTrue(f != XBADFILE); + len = (long)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + /* Load dh2048.der into DH with internal format */ + AssertNotNull(setDh = wolfSSL_d2i_DHparams(NULL, &pt, len)); + + AssertIntEQ(wolfSSL_DH_check(setDh, &code), WOLFSSL_SUCCESS); + AssertIntEQ(code, 0); + code = -1; + + pkey = wolfSSL_EVP_PKEY_new(); + + /* Set DH into PKEY */ + AssertIntEQ(wolfSSL_EVP_PKEY_set1_DH(pkey, setDh), WOLFSSL_SUCCESS); + + /* Get DH from PKEY */ + AssertNotNull(dh = wolfSSL_EVP_PKEY_get1_DH(pkey)); + + AssertIntEQ(wolfSSL_DH_check(dh, &code), WOLFSSL_SUCCESS); + AssertIntEQ(code, 0); + + EVP_PKEY_free(pkey); + DH_free(setDh); + DH_free(dh); + printf(resultFmt, passed); +#endif /* NO_DH */ +} /* END test_EVP_PKEY_set1_get1_DH */ + +static void test_wolfSSL_CTX_ctrl(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + char caFile[] = "./certs/client-ca.pem"; + char clientFile[] = "./certs/client-cert.pem"; + SSL_CTX* ctx; + X509* x509 = NULL; +#if !defined(NO_DH) && !defined(NO_DSA) + byte buf[5300]; + char file[] = "./certs/dsaparams.pem"; + XFILE f; + int bytes; + BIO* bio; + DSA* dsa; + DH* dh; +#endif +#ifdef HAVE_ECC + WOLFSSL_EC_KEY* ecKey; +#endif + printf(testingFmt, "wolfSSL_CTX_ctrl"); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + + x509 = wolfSSL_X509_load_certificate_file(caFile, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), WOLFSSL_SUCCESS); + + x509 = wolfSSL_X509_load_certificate_file(clientFile, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + +#if !defined(NO_DH) && !defined(NO_DSA) + /* Initialize DH */ + f = XFOPEN(file, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + bio = BIO_new_mem_buf((void*)buf, bytes); + AssertNotNull(bio); + + dsa = wolfSSL_PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); + AssertNotNull(dsa); + + dh = wolfSSL_DSA_dup_DH(dsa); + AssertNotNull(dh); +#endif +#ifdef HAVE_ECC + /* Initialize WOLFSSL_EC_KEY */ + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey),1); +#endif + +#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + /* additional test of getting EVP_PKEY key size from X509 + * Do not run with user RSA because wolfSSL_RSA_size is not currently + * allowed with user RSA */ + { + EVP_PKEY* pkey; +#if defined(HAVE_ECC) + X509* ecX509; +#endif /* HAVE_ECC */ + + AssertNotNull(pkey = X509_get_pubkey(x509)); + /* current RSA key is 2048 bit (256 bytes) */ + AssertIntEQ(EVP_PKEY_size(pkey), 256); + + EVP_PKEY_free(pkey); + +#if defined(HAVE_ECC) +#if defined(USE_CERT_BUFFERS_256) + AssertNotNull(ecX509 = wolfSSL_X509_load_certificate_buffer( + cliecc_cert_der_256, sizeof_cliecc_cert_der_256, + SSL_FILETYPE_ASN1)); +#else + AssertNotNull(ecX509 = wolfSSL_X509_load_certificate_file( + cliEccCertFile, SSL_FILETYPE_PEM)); +#endif + AssertNotNull(pkey = X509_get_pubkey(ecX509)); + /* current ECC key is 256 bit (32 bytes) */ + AssertIntEQ(EVP_PKEY_size(pkey), 32); + + X509_free(ecX509); + EVP_PKEY_free(pkey); +#endif /* HAVE_ECC */ + } +#endif /* !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) */ + + /* Tests should fail with passed in NULL pointer */ + AssertIntEQ((int)wolfSSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,NULL), + SSL_FAILURE); +#if !defined(NO_DH) && !defined(NO_DSA) + AssertIntEQ((int)wolfSSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,NULL), + SSL_FAILURE); +#endif +#ifdef HAVE_ECC + AssertIntEQ((int)wolfSSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,NULL), + SSL_FAILURE); +#endif + + /* Test with SSL_CTRL_EXTRA_CHAIN_CERT + * wolfSSL_CTX_ctrl should succesffuly call SSL_CTX_add_extra_chain_cert + */ + AssertIntEQ((int)wolfSSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,x509), + SSL_SUCCESS); + + /* Test with SSL_CTRL_OPTIONS + * wolfSSL_CTX_ctrl should succesffuly call SSL_CTX_set_options + */ + AssertTrue(wolfSSL_CTX_ctrl(ctx,SSL_CTRL_OPTIONS,SSL_OP_NO_TLSv1,NULL) + == SSL_OP_NO_TLSv1); + AssertTrue(SSL_CTX_get_options(ctx) == SSL_OP_NO_TLSv1); + + /* Test with SSL_CTRL_SET_TMP_DH + * wolfSSL_CTX_ctrl should succesffuly call wolfSSL_SSL_CTX_set_tmp_dh + */ +#if !defined(NO_DH) && !defined(NO_DSA) + AssertIntEQ((int)wolfSSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,dh), + SSL_SUCCESS); +#endif + + /* Test with SSL_CTRL_SET_TMP_ECDH + * wolfSSL_CTX_ctrl should succesffuly call wolfSSL_SSL_CTX_set_tmp_ecdh + */ +#ifdef HAVE_ECC + AssertIntEQ((int)wolfSSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,ecKey), + SSL_SUCCESS); +#endif + +#ifdef WOLFSSL_ENCRYPTED_KEYS + AssertNull(SSL_CTX_get_default_passwd_cb(ctx)); + AssertNull(SSL_CTX_get_default_passwd_cb_userdata(ctx)); +#endif + + /* Cleanup and Pass */ +#if !defined(NO_DH) && !defined(NO_DSA) + BIO_free(bio); + DSA_free(dsa); + DH_free(dh); +#endif +#ifdef HAVE_ECC + wolfSSL_EC_KEY_free(ecKey); +#endif + SSL_CTX_free(ctx); + printf(resultFmt, passed); +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + +static void test_wolfSSL_DH_check(void) +{ +#if !defined(NO_DH) && !defined(NO_DSA) + byte buf[5300]; + char file[] = "./certs/dsaparams.pem"; + XFILE f; + int bytes; + BIO* bio; + DSA* dsa; + DH* dh = NULL; + WOLFSSL_BIGNUM* pTmp = NULL; + WOLFSSL_BIGNUM* gTmp = NULL; + int codes = -1; + + printf(testingFmt, "wolfSSL_DH_check"); + + /* Initialize DH */ + f = XFOPEN(file, "rb"); + AssertTrue((f != XBADFILE)); + bytes = (int)XFREAD(buf, 1, sizeof(buf), f); + XFCLOSE(f); + + bio = BIO_new_mem_buf((void*)buf, bytes); + AssertNotNull(bio); + + dsa = wolfSSL_PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); + AssertNotNull(dsa); + + dh = wolfSSL_DSA_dup_DH(dsa); + AssertNotNull(dh); + + /* Test assumed to be valid dh. + * Should return WOLFSSL_SUCCESS + * codes should be 0 + * Invalid codes = {DH_NOT_SUITABLE_GENERATOR, DH_CHECK_P_NOT_PRIME} + */ + AssertIntEQ(wolfSSL_DH_check(dh, &codes), WOLFSSL_SUCCESS); + AssertIntEQ(codes, 0); + + /* Test NULL dh: expected BAD_FUNC_ARG */ + AssertIntEQ(wolfSSL_DH_check(NULL, &codes), WOLFSSL_FAILURE); + + /* Break dh prime to test if codes = DH_CHECK_P_NOT_PRIME */ + pTmp = dh->p; + dh->p = NULL; + AssertIntEQ(wolfSSL_DH_check(dh, &codes), WOLFSSL_FAILURE); + AssertIntEQ(codes, DH_CHECK_P_NOT_PRIME); + /* set dh->p back to normal so it wont fail on next tests */ + dh->p = pTmp; + pTmp = NULL; + + /* Break dh generator to test if codes = DH_NOT_SUITABLE_GENERATOR */ + gTmp = dh->g; + dh->g = NULL; + AssertIntEQ(wolfSSL_DH_check(dh, &codes), WOLFSSL_FAILURE); + AssertIntEQ(codes, DH_NOT_SUITABLE_GENERATOR); + dh->g = gTmp; + gTmp = NULL; + + /* Cleanup and Pass Test */ + BIO_free(bio); + DSA_free(dsa); + DH_free(dh); + printf(resultFmt, passed); +#endif /* !NO_DH && !NO_DSA */ +} + +static void test_wolfSSL_EVP_PKEY_assign(void) +{ +#if defined(OPENSSL_ALL) + int type; + WOLFSSL_EVP_PKEY* pkey; +#ifndef NO_RSA + WOLFSSL_RSA* rsa; +#endif +#ifndef NO_DSA + WOLFSSL_DSA* dsa; +#endif +#ifdef HAVE_ECC + WOLFSSL_EC_KEY* ecKey; +#endif + + printf(testingFmt, "wolfSSL_EVP_PKEY_assign"); +#ifndef NO_RSA + type = EVP_PKEY_RSA; + AssertNotNull(pkey = wolfSSL_EVP_PKEY_new()); + AssertNotNull(rsa = wolfSSL_RSA_new()); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(NULL,type,rsa), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,type,NULL), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,-1,rsa), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,type,rsa), WOLFSSL_SUCCESS); + wolfSSL_EVP_PKEY_free(pkey); +#endif /* NO_RSA */ + +#ifndef NO_DSA + type = EVP_PKEY_DSA; + AssertNotNull(pkey = wolfSSL_EVP_PKEY_new()); + AssertNotNull(dsa = wolfSSL_DSA_new()); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(NULL,type,dsa), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,type,NULL), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,-1,dsa), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,type,dsa), WOLFSSL_SUCCESS); + wolfSSL_EVP_PKEY_free(pkey); +#endif /* NO_DSA */ + +#ifdef HAVE_ECC + type = EVP_PKEY_EC; + AssertNotNull(pkey = wolfSSL_EVP_PKEY_new()); + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(NULL,type,ecKey), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,type,NULL), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,-1,ecKey), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,type,ecKey), WOLFSSL_SUCCESS); + wolfSSL_EVP_PKEY_free(pkey); +#endif /* HAVE_ECC */ + printf(resultFmt, passed); +#endif /* OPENSSL_ALL */ +} + +static void test_wolfSSL_OBJ_ln(void) +{ + const int nid_set[] = { + NID_commonName, + NID_serialNumber, + NID_countryName, + NID_localityName, + NID_stateOrProvinceName, + NID_organizationName, + NID_organizationalUnitName, + NID_domainComponent, + NID_businessCategory, + NID_jurisdictionCountryName, + NID_jurisdictionStateOrProvinceName, + NID_emailAddress + }; + const char* ln_set[] = { + "commonName", + "serialNumber", + "countryName", + "localityName", + "stateOrProvinceName", + "organizationName", + "organizationalUnitName", + "domainComponent", + "businessCategory", + "jurisdictionCountryName", + "jurisdictionStateOrProvinceName", + "emailAddress", + }; + int i = 0, maxIdx = sizeof(ln_set)/sizeof(char*); + + printf(testingFmt, "wolfSSL_OBJ_ln"); + + AssertIntEQ(OBJ_ln2nid(NULL), NID_undef); + +#ifdef HAVE_ECC + { + int nCurves = 27; + EC_builtin_curve r[nCurves]; + EC_get_builtin_curves(r,nCurves); + + for (i = 0; i < nCurves; i++) { + AssertIntEQ(OBJ_ln2nid(r[i].comment), r[i].nid); + AssertStrEQ(OBJ_nid2ln(r[i].nid), r[i].comment); + } + } +#endif + + for (i = 0; i < maxIdx; i++) { + AssertIntEQ(OBJ_ln2nid(ln_set[i]), nid_set[i]); + AssertStrEQ(OBJ_nid2ln(nid_set[i]), ln_set[i]); + } + + printf(resultFmt, passed); +} + +static void test_wolfSSL_OBJ_sn(void) +{ + int i = 0, maxIdx = 7; + const int nid_set[] = {NID_commonName,NID_countryName,NID_localityName, + NID_stateOrProvinceName,NID_organizationName, + NID_organizationalUnitName,NID_emailAddress}; + const char* sn_open_set[] = {"CN","C","L","ST","O","OU","emailAddress"}; + const char* sn_wolf_set[] = {WOLFSSL_COMMON_NAME,WOLFSSL_COUNTRY_NAME, + WOLFSSL_LOCALITY_NAME, WOLFSSL_STATE_NAME, + WOLFSSL_ORG_NAME, WOLFSSL_ORGUNIT_NAME, + WOLFSSL_EMAIL_ADDR}; + + printf(testingFmt, "wolfSSL_OBJ_sn"); + + AssertIntEQ(wolfSSL_OBJ_sn2nid(NULL), NID_undef); + for (i = 0; i < maxIdx; i++) { + AssertIntEQ(wolfSSL_OBJ_sn2nid(sn_wolf_set[i]), nid_set[i]); + AssertStrEQ(wolfSSL_OBJ_nid2sn(nid_set[i]), sn_open_set[i]); + } + + printf(resultFmt, passed); +} +#endif /* WOLFSSL_QT */ + + +static void test_wolfSSL_X509V3_EXT_get(void) { +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + FILE* f; + int numOfExt =0; + int extNid = 0; + int i = 0; + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* ext; + const WOLFSSL_v3_ext_method* method; + + AssertNotNull(f = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); + fclose(f); + + printf(testingFmt, "wolfSSL_X509V3_EXT_get() return struct and nid test"); + AssertIntEQ((numOfExt = wolfSSL_X509_get_ext_count(x509)), 3); + for (i = 0; i < numOfExt; i++) { + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, i)); + AssertNotNull(extNid = ext->obj->nid); + AssertNotNull(method = wolfSSL_X509V3_EXT_get(ext)); + AssertIntEQ(method->ext_nid, extNid); + } + printf(resultFmt, "passed"); + + printf(testingFmt, "wolfSSL_X509V3_EXT_get() NULL argument test"); + AssertNull(method = wolfSSL_X509V3_EXT_get(NULL)); + printf(resultFmt, "passed"); + + wolfSSL_X509_free(x509); +#endif +} + +static void test_wolfSSL_X509V3_EXT_d2i(void) { +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + FILE* f; + int numOfExt = 0, nid = 0, i = 0, expected, actual; + char* str; + unsigned char* data; + const WOLFSSL_v3_ext_method* method; + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* ext; + WOLFSSL_ASN1_OBJECT *obj, *adObj; + WOLFSSL_ASN1_STRING* asn1str; + WOLFSSL_AUTHORITY_KEYID* aKeyId; + WOLFSSL_AUTHORITY_INFO_ACCESS* aia; + WOLFSSL_BASIC_CONSTRAINTS* bc; + WOLFSSL_ACCESS_DESCRIPTION* ad; + WOLFSSL_GENERAL_NAME* gn; + + printf(testingFmt, "wolfSSL_X509V3_EXT_d2i()"); + + /* Check NULL argument */ + AssertNull(wolfSSL_X509V3_EXT_d2i(NULL)); + + /* Using OCSP cert with X509V3 extensions */ + AssertNotNull(f = fopen("./certs/ocsp/root-ca-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); + fclose(f); + + AssertIntEQ((numOfExt = wolfSSL_X509_get_ext_count(x509)), 5); + + /* Basic Constraints */ + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, i)); + AssertNotNull(obj = wolfSSL_X509_EXTENSION_get_object(ext)); + AssertIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_basic_constraints); + AssertNotNull(bc = (WOLFSSL_BASIC_CONSTRAINTS*)wolfSSL_X509V3_EXT_d2i(ext)); + + AssertIntEQ(bc->ca, 1); + AssertNull(bc->pathlen); + wolfSSL_BASIC_CONSTRAINTS_free(bc); + i++; + + /* Subject Key Identifier */ + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, i)); + AssertNotNull(obj = wolfSSL_X509_EXTENSION_get_object(ext)); + AssertIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_subject_key_identifier); + + AssertNotNull(asn1str = (WOLFSSL_ASN1_STRING*)wolfSSL_X509V3_EXT_d2i(ext)); + AssertNotNull(method = wolfSSL_X509V3_EXT_get(ext)); + AssertNotNull(method->i2s); + AssertNotNull(str = method->i2s((WOLFSSL_v3_ext_method*)method, asn1str)); + wolfSSL_ASN1_STRING_free(asn1str); + actual = strcmp(str, + "73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21"); + AssertIntEQ(actual, 0); + XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); + i++; + + /* Authority Key Identifier */ + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, i)); + AssertNotNull(obj = wolfSSL_X509_EXTENSION_get_object(ext)); + AssertIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_authority_key_identifier); + + AssertNotNull(aKeyId = + (WOLFSSL_AUTHORITY_KEYID*)wolfSSL_X509V3_EXT_d2i(ext)); + AssertNotNull(method = wolfSSL_X509V3_EXT_get(ext)); + AssertNotNull(asn1str = aKeyId->keyid); + AssertNotNull(str = + wolfSSL_i2s_ASN1_STRING((WOLFSSL_v3_ext_method*)method, asn1str)); + actual = strcmp(str, + "73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21"); + AssertIntEQ(actual, 0); + XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_AUTHORITY_KEYID_free(aKeyId); + i++; + + /* Key Usage */ + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, i)); + AssertNotNull(obj = wolfSSL_X509_EXTENSION_get_object(ext)); + AssertIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_key_usage); + + AssertNotNull(asn1str = (WOLFSSL_ASN1_STRING*)wolfSSL_X509V3_EXT_d2i(ext)); + AssertNotNull(data = wolfSSL_ASN1_STRING_data(asn1str)); + expected = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN; +#ifdef BIG_ENDIAN_ORDER + actual = data[1]; +#else + actual = data[0]; +#endif + AssertIntEQ(actual, expected); + wolfSSL_ASN1_STRING_free(asn1str); +#if 0 + i++; + + /* Authority Info Access */ + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, i)); + AssertNotNull(obj = wolfSSL_X509_EXTENSION_get_object(ext)); + AssertIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_info_access); + AssertNotNull(aia = wolfSSL_X509V3_EXT_d2i(ext)); + AssertIntEQ(wolfSSL_sk_num(aia), 1); /* Only one URI entry for this cert */ + + /* URI entry is an ACCESS_DESCRIPTION type */ + AssertNotNull(ad = wolfSSL_sk_value(aia, 0)); + AssertNotNull(adObj = ad->method); + /* Make sure nid is OCSP */ + AssertIntEQ(wolfSSL_OBJ_obj2nid(adObj), AIA_OCSP_OID); + + /* GENERAL_NAME stores URI as an ASN1_STRING */ + AssertNotNull(gn = ad->location); + AssertIntEQ(gn->type, GEN_URI); /* Type should always be GEN_URI */ + AssertNotNull(asn1str = gn->d.uniformResourceIdentifier); + AssertIntEQ(wolfSSL_ASN1_STRING_length(asn1str), 22); + str = (char*)wolfSSL_ASN1_STRING_data(asn1str); + actual = strcmp(str, "http://127.0.0.1:22220"); + AssertIntEQ(actual, 0); + + wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(aia, NULL); + XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT); +#else + (void) aia; (void) ad; (void) adObj; (void) gn; +#endif + wolfSSL_X509_free(x509); + printf(resultFmt, "passed"); +#endif +} + +static void test_wolfSSL_X509_get_ext(void){ +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + int ret = 0; + FILE* f; + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* foundExtension; + + AssertNotNull(f = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); + fclose(f); + AssertIntEQ((ret = wolfSSL_X509_get_ext_count(x509)), 3); + + printf(testingFmt, "wolfSSL_X509_get_ext() valid input"); + AssertNotNull(foundExtension = wolfSSL_X509_get_ext(x509, 0)); + printf(resultFmt, "passed"); + + printf(testingFmt, "wolfSSL_X509_get_ext() valid x509, idx out of bounds"); + AssertNull(foundExtension = wolfSSL_X509_get_ext(x509, -1)); + AssertNull(foundExtension = wolfSSL_X509_get_ext(x509, 100)); + printf(resultFmt, "passed"); + + printf(testingFmt, "wolfSSL_X509_get_ext() NULL x509, idx out of bounds"); + AssertNull(foundExtension = wolfSSL_X509_get_ext(NULL, -1)); + AssertNull(foundExtension = wolfSSL_X509_get_ext(NULL, 100)); + printf(resultFmt, "passed"); + + printf(testingFmt, "wolfSSL_X509_get_ext() NULL x509, valid idx"); + AssertNull(foundExtension = wolfSSL_X509_get_ext(NULL, 0)); + printf(resultFmt, "passed"); + + wolfSSL_X509_free(x509); +#endif +} + +static void test_wolfSSL_X509_get_ext_by_NID(void) +{ +#if defined(OPENSSL_ALL) + int rc; + FILE* f; + WOLFSSL_X509* x509; + + AssertNotNull(f = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); + fclose(f); + + rc = wolfSSL_X509_get_ext_by_NID(x509, NID_basic_constraints, -1); + AssertIntGE(rc, 0); + + /* Start search from last location (should fail) */ + rc = wolfSSL_X509_get_ext_by_NID(x509, NID_basic_constraints, rc); + AssertIntGE(rc, -1); + + rc = wolfSSL_X509_get_ext_by_NID(x509, NID_basic_constraints, -2); + AssertIntGE(rc, -1); + + rc = wolfSSL_X509_get_ext_by_NID(NULL, NID_basic_constraints, -1); + AssertIntEQ(rc, -1); + + rc = wolfSSL_X509_get_ext_by_NID(x509, NID_undef, -1); + AssertIntEQ(rc, -1); + + wolfSSL_X509_free(x509); + +#endif +} + +static void test_wolfSSL_X509_EXTENSION_new(void) +{ +#if defined (OPENSSL_ALL) + WOLFSSL_X509_EXTENSION* ext; + + AssertNotNull(ext = wolfSSL_X509_EXTENSION_new()); + AssertNotNull(ext->obj = wolfSSL_ASN1_OBJECT_new()); + ext->obj->nid = WOLFSSL_SUCCESS; + AssertIntEQ(WOLFSSL_SUCCESS, ext->obj->nid); + + wolfSSL_X509_EXTENSION_free(ext); +#endif +} + +static void test_wolfSSL_X509_EXTENSION_get_object(void) +{ +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* ext; + WOLFSSL_ASN1_OBJECT* o; + FILE* file; + int nid = 0; + + AssertNotNull(file = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(file, NULL, NULL, NULL)); + fclose(file); + + printf(testingFmt, "wolfSSL_X509_EXTENSION_get_object() testing ext idx 0"); + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, 0)); + AssertNotNull(o = wolfSSL_X509_EXTENSION_get_object(ext)); + AssertIntEQ(o->nid, 128); + nid = o->nid; + printf(resultFmt, nid == 128 ? passed : failed); + + printf(testingFmt, "wolfSSL_X509_EXTENSION_get_object() NULL argument"); + AssertNull(o = wolfSSL_X509_EXTENSION_get_object(NULL)); + printf(resultFmt, passed); + + wolfSSL_X509_free(x509); +#endif +} + +static void test_wolfSSL_X509_EXTENSION_get_data(void) +{ +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* ext; + WOLFSSL_ASN1_STRING* str; + FILE* file; + + printf(testingFmt, "wolfSSL_X509_EXTENSION_get_data"); + + AssertNotNull(file = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(file, NULL, NULL, NULL)); + fclose(file); + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, 0)); + + AssertNotNull(str = wolfSSL_X509_EXTENSION_get_data(ext)); + printf(resultFmt, passed); + + wolfSSL_X509_free(x509); +#endif +} + +static void test_wolfSSL_X509_EXTENSION_get_critical(void) +{ +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* ext; + FILE* file; + int crit; + + printf(testingFmt, "wolfSSL_X509_EXTENSION_get_critical"); + + AssertNotNull(file = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(file, NULL, NULL, NULL)); + fclose(file); + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, 0)); + + crit = wolfSSL_X509_EXTENSION_get_critical(ext); + AssertIntEQ(crit, 0); + printf(resultFmt, passed); + + wolfSSL_X509_free(x509); +#endif +} + +static void test_wolfSSL_X509V3_EXT_print(void) +{ +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + printf(testingFmt, "wolfSSL_X509V3_EXT_print"); + + { + FILE* f; + WOLFSSL_X509* x509; + X509_EXTENSION * ext = NULL; + int loc; + BIO *bio = NULL; + + AssertNotNull(f = fopen(svrCertFile, "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); + fclose(f); + + AssertNotNull(bio = wolfSSL_BIO_new(BIO_s_mem())); + + loc = wolfSSL_X509_get_ext_by_NID(x509, NID_basic_constraints, -1); + AssertIntGT(loc, -1); + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, loc)); + AssertIntEQ(wolfSSL_X509V3_EXT_print(bio, ext, 0, 0), WOLFSSL_SUCCESS); + + loc = wolfSSL_X509_get_ext_by_NID(x509, NID_subject_key_identifier, -1); + AssertIntGT(loc, -1); + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, loc)); + AssertIntEQ(wolfSSL_X509V3_EXT_print(bio, ext, 0, 0), WOLFSSL_SUCCESS); + + loc = wolfSSL_X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1); + AssertIntGT(loc, -1); + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, loc)); + AssertIntEQ(wolfSSL_X509V3_EXT_print(bio, ext, 0, 0), WOLFSSL_SUCCESS); + + wolfSSL_BIO_free(bio); + wolfSSL_X509_free(x509); + } + + { + X509 *x509; + BIO *bio; + X509_EXTENSION *ext; + unsigned int i; + unsigned int idx; + /* Some NIDs to test with */ + int nids[] = { + /* NID_key_usage, currently X509_get_ext returns this as a bit + * string, which messes up X509V3_EXT_print */ + /* NID_ext_key_usage, */ + NID_subject_alt_name, + }; + int* n; + + printf(testingFmt, "wolfSSL_X509V3_EXT_print"); + AssertNotNull(bio = BIO_new_fp(stderr, BIO_NOCLOSE)); + + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(cliCertFileExt, + WOLFSSL_FILETYPE_PEM)); + + printf("\nPrinting extension values:\n"); + + for (i = 0, n = nids; i<(sizeof(nids)/sizeof(int)); i++, n++) { + /* X509_get_ext_by_NID should return 3 for now. If that changes then + * update the index */ + AssertIntEQ((idx = X509_get_ext_by_NID(x509, *n, -1)), 3); + AssertNotNull(ext = X509_get_ext(x509, idx)); + AssertIntEQ(X509V3_EXT_print(bio, ext, 0, 0), 1); + printf("\n"); + } + + BIO_free(bio); + X509_free(x509); + } + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_cmp(void) +{ +#if defined(OPENSSL_ALL) + FILE* file1; + FILE* file2; + WOLFSSL_X509* cert1; + WOLFSSL_X509* cert2; + int ret = 0; + + AssertNotNull(file1=fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(file2=fopen("./certs/3072/client-cert.pem", "rb")); + + AssertNotNull(cert1 = wolfSSL_PEM_read_X509(file1, NULL, NULL, NULL)); + AssertNotNull(cert2 = wolfSSL_PEM_read_X509(file2, NULL, NULL, NULL)); + fclose(file1); + fclose(file2); + + printf(testingFmt, "wolfSSL_X509_cmp() testing matching certs"); + ret = wolfSSL_X509_cmp(cert1, cert1); + AssertIntEQ(0, wolfSSL_X509_cmp(cert1, cert1)); + printf(resultFmt, ret == 0 ? passed : failed); + + printf(testingFmt, "wolfSSL_X509_cmp() testing mismatched certs"); + ret = wolfSSL_X509_cmp(cert1, cert2); + AssertIntEQ(-1, wolfSSL_X509_cmp(cert1, cert2)); + printf(resultFmt, ret == -1 ? passed : failed); + + printf(testingFmt, "wolfSSL_X509_cmp() testing NULL, valid args"); + ret = wolfSSL_X509_cmp(NULL, cert2); + AssertIntEQ(BAD_FUNC_ARG, wolfSSL_X509_cmp(NULL, cert2)); + printf(resultFmt, ret == BAD_FUNC_ARG ? passed : failed); + + printf(testingFmt, "wolfSSL_X509_cmp() testing valid, NULL args"); + ret = wolfSSL_X509_cmp(cert1, NULL); + AssertIntEQ(BAD_FUNC_ARG, wolfSSL_X509_cmp(cert1, NULL)); + printf(resultFmt, ret == BAD_FUNC_ARG ? passed : failed); + + printf(testingFmt, "wolfSSL_X509_cmp() testing NULL, NULL args"); + ret = wolfSSL_X509_cmp(NULL, NULL); + AssertIntEQ(BAD_FUNC_ARG, wolfSSL_X509_cmp(NULL, NULL)); + printf(resultFmt, ret == BAD_FUNC_ARG ? passed : failed); + + wolfSSL_X509_free(cert1); + wolfSSL_X509_free(cert2); +#endif +} + +static void test_wolfSSL_PKEY_up_ref() +{ +#if defined(OPENSSL_ALL) + EVP_PKEY* pkey; + printf(testingFmt, "wolfSSL_PKEY_up_ref()"); + + pkey = EVP_PKEY_new(); + AssertIntEQ(EVP_PKEY_up_ref(NULL), 0); + AssertIntEQ(EVP_PKEY_up_ref(pkey), 1); + EVP_PKEY_free(pkey); + AssertIntEQ(EVP_PKEY_up_ref(pkey), 1); + EVP_PKEY_free(pkey); + EVP_PKEY_free(pkey); + + printf(resultFmt, "passed"); +#endif +} + +static void test_wolfSSL_i2d_PrivateKey() +{ +#if (!defined(NO_RSA) || defined(HAVE_ECC)) && defined(OPENSSL_EXTRA) + + printf(testingFmt, "wolfSSL_i2d_PrivateKey()"); +#if !defined(NO_RSA) && defined(USE_CERT_BUFFERS_2048) + { + EVP_PKEY* pkey; + const unsigned char* server_key = (const unsigned char*)server_key_der_2048; + unsigned char buf[FOURK_BUF]; + unsigned char* pt; + int bufSz; + + AssertNotNull(pkey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &server_key, + (long)sizeof_server_key_der_2048)); + AssertIntEQ(i2d_PrivateKey(pkey, NULL), 1193); + pt = buf; + AssertIntEQ((bufSz = i2d_PrivateKey(pkey, &pt)), 1193); + AssertIntNE((pt - buf), 0); + AssertIntEQ(XMEMCMP(buf, server_key_der_2048, bufSz), 0); + EVP_PKEY_free(pkey); + } +#endif +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + { + EVP_PKEY* pkey; + const unsigned char* client_key = + (const unsigned char*)ecc_clikey_der_256; + unsigned char buf[FOURK_BUF]; + unsigned char* pt; + int bufSz; + + AssertNotNull((pkey = d2i_PrivateKey(EVP_PKEY_EC, NULL, &client_key, + sizeof_ecc_clikey_der_256))); + AssertIntEQ(i2d_PrivateKey(pkey, NULL), 121); + pt = buf; + AssertIntEQ((bufSz = i2d_PrivateKey(pkey, &pt)), 121); + AssertIntNE((pt - buf), 0); + AssertIntEQ(XMEMCMP(buf, ecc_clikey_der_256, bufSz), 0); + EVP_PKEY_free(pkey); + } +#endif + + printf(resultFmt, "passed"); +#endif +} + +static void test_wolfSSL_OCSP_get0_info() +{ +#if defined(OPENSSL_ALL) && defined(HAVE_OCSP) && !defined(NO_FILESYSTEM) + X509* cert; + X509* issuer; + OCSP_CERTID* id; + + ASN1_STRING* name = NULL; + ASN1_OBJECT* pmd = NULL; + ASN1_STRING* keyHash = NULL; + ASN1_INTEGER* serial = NULL; + ASN1_INTEGER* x509Int; + + printf(testingFmt, "wolfSSL_OCSP_get0_info()"); + + AssertNotNull(cert = + wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM)); + AssertNotNull(issuer = + wolfSSL_X509_load_certificate_file(caCertFile, SSL_FILETYPE_PEM)); + + id = OCSP_cert_to_id(NULL, cert, issuer); + AssertNotNull(id); + + AssertIntEQ(OCSP_id_get0_info(NULL, NULL, NULL, NULL, NULL), 0); + AssertIntEQ(OCSP_id_get0_info(NULL, NULL, NULL, NULL, id), 1); + + /* name, pmd, keyHash not supported yet, expect failure if not NULL */ + AssertIntEQ(OCSP_id_get0_info(&name, NULL, NULL, NULL, id), 0); + AssertIntEQ(OCSP_id_get0_info(NULL, &pmd, NULL, NULL, id), 0); + AssertIntEQ(OCSP_id_get0_info(NULL, NULL, &keyHash, NULL, id), 0); + + AssertIntEQ(OCSP_id_get0_info(NULL, NULL, NULL, &serial, id), 1); + AssertNotNull(serial); + + /* compare serial number to one in cert, should be equal */ + x509Int = X509_get_serialNumber(cert); + AssertNotNull(x509Int); + AssertIntEQ(x509Int->dataMax, serial->dataMax); + AssertIntEQ(XMEMCMP(x509Int->data, serial->data, serial->dataMax), 0); + + OCSP_CERTID_free(id); + X509_free(cert); /* free's x509Int */ + X509_free(issuer); + + printf(resultFmt, "passed"); +#endif /* OPENSSL_EXTRA & HAVE_OCSP */ +} + +static void test_wolfSSL_EVP_PKEY_derive(void) +{ +#ifdef OPENSSL_ALL + EVP_PKEY_CTX *ctx; + unsigned char *skey; + size_t skeylen; + EVP_PKEY *pkey, *peerkey; + const unsigned char* key; + + /* DH */ + key = dh_key_der_2048; + AssertNotNull((pkey = d2i_PrivateKey(EVP_PKEY_DH, NULL, &key, + sizeof_dh_key_der_2048))); + AssertIntEQ(DH_generate_key(EVP_PKEY_get0_DH(pkey)), 1); + key = dh_key_der_2048; + AssertNotNull((peerkey = d2i_PrivateKey(EVP_PKEY_DH, NULL, &key, + sizeof_dh_key_der_2048))); + AssertIntEQ(DH_generate_key(EVP_PKEY_get0_DH(peerkey)), 1); + AssertNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + AssertIntEQ(EVP_PKEY_derive_init(ctx), 1); + AssertIntEQ(EVP_PKEY_derive_set_peer(ctx, peerkey), 1); + AssertIntEQ(EVP_PKEY_derive(ctx, NULL, &skeylen), 1); + AssertNotNull(skey = XMALLOC(skeylen, NULL, DYNAMIC_TYPE_OPENSSL)); + AssertIntEQ(EVP_PKEY_derive(ctx, skey, &skeylen), 1); + + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(peerkey); + EVP_PKEY_free(pkey); + XFREE(skey, NULL, DYNAMIC_TYPE_OPENSSL); + +#ifdef HAVE_ECC + /* ECDH */ + key = ecc_clikey_der_256; + AssertNotNull((pkey = d2i_PrivateKey(EVP_PKEY_EC, NULL, &key, + sizeof_ecc_clikey_der_256))); + key = ecc_clikeypub_der_256; + AssertNotNull((peerkey = d2i_PUBKEY(NULL, &key, + sizeof_ecc_clikeypub_der_256))); + AssertNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + AssertIntEQ(EVP_PKEY_derive_init(ctx), 1); + AssertIntEQ(EVP_PKEY_derive_set_peer(ctx, peerkey), 1); + AssertIntEQ(EVP_PKEY_derive(ctx, NULL, &skeylen), 1); + AssertNotNull(skey = XMALLOC(skeylen, NULL, DYNAMIC_TYPE_OPENSSL)); + AssertIntEQ(EVP_PKEY_derive(ctx, skey, &skeylen), 1); + + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(peerkey); + EVP_PKEY_free(pkey); + XFREE(skey, NULL, DYNAMIC_TYPE_OPENSSL); +#endif +#endif +} + +static void test_wolfSSL_RSA_padding_add_PKCS1_PSS(void) +{ +#if defined(OPENSSL_ALL) && defined(WC_RSA_PSS) && !defined(WC_NO_RNG) + RSA *rsa; + const unsigned char *derBuf = client_key_der_2048; + unsigned char em[256] = {0}; /* len = 2048/8 */ + /* Random data simulating a hash */ + const unsigned char mHash[WC_SHA256_DIGEST_SIZE] = { + 0x28, 0x6e, 0xfd, 0xf8, 0x76, 0xc7, 0x00, 0x3d, 0x91, 0x4e, 0x59, 0xe4, + 0x8e, 0xb7, 0x40, 0x7b, 0xd1, 0x0c, 0x98, 0x4b, 0xe3, 0x3d, 0xb3, 0xeb, + 0x6f, 0x8a, 0x3c, 0x42, 0xab, 0x21, 0xad, 0x28 + }; + + AssertNotNull(d2i_RSAPrivateKey(&rsa, &derBuf, sizeof_client_key_der_2048)); + AssertIntEQ(RSA_padding_add_PKCS1_PSS(rsa, em, mHash, EVP_sha256(), -1), 1); + AssertIntEQ(RSA_verify_PKCS1_PSS(rsa, mHash, EVP_sha256(), em, -1), 1); + + RSA_free(rsa); +#endif +} + +static void test_wolfSSL_EC_get_builtin_curves(void) +{ +#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) + EC_builtin_curve* curves = NULL; + size_t crv_len = 0; + size_t i = 0; + + printf(testingFmt, "wolfSSL_EC_get_builtin_curves"); + + AssertIntGT((crv_len = EC_get_builtin_curves(NULL, 0)), 0); + AssertNotNull(curves = (EC_builtin_curve*) + XMALLOC(sizeof(EC_builtin_curve)*crv_len, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + AssertIntEQ(EC_get_builtin_curves(curves, crv_len), crv_len); + + for (i = 0; i < crv_len; i++) + { + AssertStrEQ(OBJ_nid2sn(curves[i].nid), curves[i].comment); + } + + XFREE(curves, NULL, DYNAMIC_TYPE_TMP_BUFFER); + printf(resultFmt, passed); +#endif /* defined(HAVE_ECC) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) */ +} + +static void test_no_op_functions(void) +{ + #if defined(OPENSSL_EXTRA) + printf(testingFmt, "no_op_functions()"); + + /* this makes sure wolfSSL can compile and run these no-op functions */ + SSL_load_error_strings(); + ENGINE_load_builtin_engines(); + OpenSSL_add_all_ciphers(); + AssertIntEQ(CRYPTO_malloc_init(), 0); + + printf(resultFmt, passed); + #endif +} + + +/*----------------------------------------------------------------------------* + | wolfCrypt ASN + *----------------------------------------------------------------------------*/ + +static void test_wc_GetPkcs8TraditionalOffset(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(HAVE_PKCS8) + int length, derSz; + word32 inOutIdx; + const char* path = "./certs/server-keyPkcs8.der"; + XFILE file; + byte der[2048]; + + printf(testingFmt, "wc_GetPkcs8TraditionalOffset"); + + file = XFOPEN(path, "rb"); + AssertTrue(file != XBADFILE); + derSz = (int)XFREAD(der, 1, sizeof(der), file); + XFCLOSE(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 */ +} + +static void test_wc_SetSubjectRaw(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && !defined(NO_RSA) + const char* joiCertFile = "./certs/test/cert-ext-joi.pem"; + WOLFSSL_X509* x509; + int peerCertSz; + const byte* peerCertBuf; + Cert forgedCert; + + printf(testingFmt, "test_wc_SetSubjectRaw()"); + + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(joiCertFile, WOLFSSL_FILETYPE_PEM)); + + AssertNotNull(peerCertBuf = wolfSSL_X509_get_der(x509, &peerCertSz)); + + AssertIntEQ(0, wc_InitCert(&forgedCert)); + + AssertIntEQ(0, wc_SetSubjectRaw(&forgedCert, peerCertBuf, peerCertSz)); + + wolfSSL_FreeX509(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_wc_GetSubjectRaw(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) + Cert cert; + byte *subjectRaw; + + printf(testingFmt, "test_wc_GetSubjectRaw()"); + + AssertIntEQ(0, wc_InitCert(&cert)); + AssertIntEQ(0, wc_GetSubjectRaw(&subjectRaw, &cert)); + + printf(resultFmt, passed); +#endif +} + +static void test_wc_SetIssuerRaw(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && !defined(NO_RSA) + const char* joiCertFile = "./certs/test/cert-ext-joi.pem"; + WOLFSSL_X509* x509; + int peerCertSz; + const byte* peerCertBuf; + Cert forgedCert; + + printf(testingFmt, "test_wc_SetIssuerRaw()"); + + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(joiCertFile, WOLFSSL_FILETYPE_PEM)); + + AssertNotNull(peerCertBuf = wolfSSL_X509_get_der(x509, &peerCertSz)); + + AssertIntEQ(0, wc_InitCert(&forgedCert)); + + AssertIntEQ(0, wc_SetIssuerRaw(&forgedCert, peerCertBuf, peerCertSz)); + + wolfSSL_FreeX509(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_wc_SetIssueBuffer(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && !defined(NO_RSA) + const char* joiCertFile = "./certs/test/cert-ext-joi.pem"; + WOLFSSL_X509* x509; + int peerCertSz; + const byte* peerCertBuf; + Cert forgedCert; + + printf(testingFmt, "test_wc_SetIssuerBuffer()"); + + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(joiCertFile, WOLFSSL_FILETYPE_PEM)); + + AssertNotNull(peerCertBuf = wolfSSL_X509_get_der(x509, &peerCertSz)); + + AssertIntEQ(0, wc_InitCert(&forgedCert)); + + AssertIntEQ(0, wc_SetIssuerBuffer(&forgedCert, peerCertBuf, peerCertSz)); + + wolfSSL_FreeX509(x509); + + printf(resultFmt, passed); +#endif +} + +/* + * Testing wc_SetSubjectKeyId + */ +static void test_wc_SetSubjectKeyId(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) + Cert cert; + const char* file = "certs/ecc-client-keyPub.pem"; + + printf(testingFmt, "wc_SetSubjectKeyId()"); + + AssertIntEQ(0, wc_InitCert(&cert)); + AssertIntEQ(0, wc_SetSubjectKeyId(&cert, file)); + + AssertIntEQ(BAD_FUNC_ARG, wc_SetSubjectKeyId(NULL, file)); + AssertIntGT(0, wc_SetSubjectKeyId(&cert, "badfile.name")); + + printf(resultFmt, passed); +#endif +} /* END test_wc_SetSubjectKeyId */ + +/* + * Testing wc_SetSubject + */ +static void test_wc_SetSubject(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) + Cert cert; + const char* file = "./certs/ca-ecc-cert.pem"; + + printf(testingFmt, "wc_SetSubject()"); + + AssertIntEQ(0, wc_InitCert(&cert)); + AssertIntEQ(0, wc_SetSubject(&cert, file)); + + AssertIntEQ(BAD_FUNC_ARG, wc_SetSubject(NULL, file)); + AssertIntGT(0, wc_SetSubject(&cert, "badfile.name")); + + printf(resultFmt, passed); +#endif +} /* END test_wc_SetSubject */ + + +static void test_CheckCertSignature(void) +{ +#if !defined(NO_CERTS) && defined(WOLFSSL_SMALL_CERT_VERIFY) + WOLFSSL_CERT_MANAGER* cm = NULL; +#if !defined(NO_FILESYSTEM) && (!defined(NO_RSA) || defined(HAVE_ECC)) + FILE* fp; + byte cert[4096]; + int certSz; +#endif + + AssertIntEQ(BAD_FUNC_ARG, CheckCertSignature(NULL, 0, NULL, NULL)); + AssertNotNull(cm = wolfSSL_CertManagerNew_ex(NULL)); + AssertIntEQ(BAD_FUNC_ARG, CheckCertSignature(NULL, 0, NULL, cm)); + +#ifndef NO_RSA +#ifdef USE_CERT_BUFFERS_1024 + AssertIntEQ(ASN_NO_SIGNER_E, CheckCertSignature(server_cert_der_1024, + sizeof_server_cert_der_1024, NULL, cm)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCABuffer(cm, + ca_cert_der_1024, sizeof_ca_cert_der_1024, + WOLFSSL_FILETYPE_ASN1)); + AssertIntEQ(0, CheckCertSignature(server_cert_der_1024, + sizeof_server_cert_der_1024, NULL, cm)); +#elif defined(USE_CERT_BUFFERS_2048) + AssertIntEQ(ASN_NO_SIGNER_E, CheckCertSignature(server_cert_der_2048, + sizeof_server_cert_der_2048, NULL, cm)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCABuffer(cm, + ca_cert_der_2048, sizeof_ca_cert_der_2048, + WOLFSSL_FILETYPE_ASN1)); + AssertIntEQ(0, CheckCertSignature(server_cert_der_2048, + sizeof_server_cert_der_2048, NULL, cm)); +#endif +#endif + +#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + AssertIntEQ(ASN_NO_SIGNER_E, CheckCertSignature(serv_ecc_der_256, + sizeof_serv_ecc_der_256, NULL, cm)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCABuffer(cm, + ca_ecc_cert_der_256, sizeof_ca_ecc_cert_der_256, + WOLFSSL_FILETYPE_ASN1)); + AssertIntEQ(0, CheckCertSignature(serv_ecc_der_256, sizeof_serv_ecc_der_256, + NULL, cm)); +#endif + +#if !defined(NO_FILESYSTEM) + wolfSSL_CertManagerFree(cm); + AssertNotNull(cm = wolfSSL_CertManagerNew_ex(NULL)); +#ifndef NO_RSA + AssertNotNull(fp = XFOPEN("./certs/server-cert.der", "rb")); + AssertIntGT((certSz = (int)XFREAD(cert, 1, sizeof(cert), fp)), 0); + XFCLOSE(fp); + AssertIntEQ(ASN_NO_SIGNER_E, CheckCertSignature(cert, certSz, NULL, cm)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCA(cm, + "./certs/ca-cert.pem", NULL)); + AssertIntEQ(0, CheckCertSignature(cert, certSz, NULL, cm)); +#endif +#ifdef HAVE_ECC + AssertNotNull(fp = XFOPEN("./certs/server-ecc.der", "rb")); + AssertIntGT((certSz = (int)XFREAD(cert, 1, sizeof(cert), fp)), 0); + XFCLOSE(fp); + AssertIntEQ(ASN_NO_SIGNER_E, CheckCertSignature(cert, certSz, NULL, cm)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCA(cm, + "./certs/ca-ecc-cert.pem", NULL)); + AssertIntEQ(0, CheckCertSignature(cert, certSz, NULL, cm)); +#endif +#endif + +#if !defined(NO_FILESYSTEM) && (!defined(NO_RSA) || defined(HAVE_ECC)) + (void)fp; + (void)cert; + (void)certSz; +#endif + + wolfSSL_CertManagerFree(cm); +#endif +} + +/*----------------------------------------------------------------------------* + | 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 */ +} + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && \ + !defined(HAVE_SELFTEST) && \ + !(defined(HAVE_FIPS) || defined(HAVE_FIPS_VERSION)) + +static void test_wc_ecc_get_curve_id_from_dp_params(void) +{ + int id; +#if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + int curve_id; + ecc_key* key; + const ecc_set_type* params; + int ret; +#endif + WOLFSSL_EC_KEY *ecKey = NULL; + + printf(testingFmt, "wc_ecc_get_curve_id_from_dp_params"); + + #if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + id = wc_ecc_get_curve_id_from_name("SECP256R1"); + AssertIntEQ(id, ECC_SECP256R1); + + ecKey = wolfSSL_EC_KEY_new_by_curve_name(id); + AssertNotNull(ecKey); + + ret = wolfSSL_EC_KEY_generate_key(ecKey); + + if (ret == 0) { + /* normal test */ + key = (ecc_key*)ecKey->internal; + params = key->dp; + + curve_id = wc_ecc_get_curve_id_from_dp_params(params); + AssertIntEQ(curve_id, id); + } + #endif + /* invalid case, NULL input*/ + + id = wc_ecc_get_curve_id_from_dp_params(NULL); + AssertIntEQ(id, BAD_FUNC_ARG); + wolfSSL_EC_KEY_free(ecKey); + + printf(resultFmt, passed); +} +#endif /* defined(OPENSSL_EXTRA) && defined(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 +} +static void test_wolfSSL_EVP_PKEY_encrypt(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && \ + !defined(HAVE_FAST_RSA) + WOLFSSL_RSA* rsa = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; + WOLFSSL_EVP_PKEY_CTX* ctx = NULL; + const char* in = "What is easy to do is easy not to do."; + size_t inlen = XSTRLEN(in); + size_t outEncLen = 0; + byte* outEnc = NULL; + byte* outDec = NULL; + size_t outDecLen = 0; + size_t rsaKeySz = 2048/8; /* Bytes */ +#ifdef WC_RSA_NO_PADDING + byte* inTmp = NULL; + byte* outEncTmp = NULL; + byte* outDecTmp = NULL; +#endif + printf(testingFmt, "wolfSSL_EVP_PKEY_encrypt()"); + + AssertNotNull(outEnc = (byte*)XMALLOC(rsaKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + XMEMSET(outEnc, 0, rsaKeySz); + AssertNotNull(outDec = (byte*)XMALLOC(rsaKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + XMEMSET(outDec, 0, rsaKeySz); + + AssertNotNull(rsa = RSA_generate_key(2048, 3, NULL, NULL)); + AssertNotNull(pkey = wolfSSL_EVP_PKEY_new()); + AssertIntEQ(EVP_PKEY_assign_RSA(pkey, rsa), WOLFSSL_SUCCESS); + AssertNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + AssertIntEQ(EVP_PKEY_encrypt_init(ctx), WOLFSSL_SUCCESS); + AssertIntEQ(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING), + WOLFSSL_SUCCESS); + + /* Test pkey references count is decremented. pkey shouldn't be destroyed + since ctx uses it.*/ + AssertIntEQ(pkey->references, 2); + EVP_PKEY_free(pkey); + AssertIntEQ(pkey->references, 1); + + /* Encrypt data */ + AssertIntEQ(EVP_PKEY_encrypt(ctx, outEnc, &outEncLen, + (const unsigned char*)in, inlen), WOLFSSL_SUCCESS); + + /* Decrypt data */ + AssertIntEQ(EVP_PKEY_decrypt_init(ctx), WOLFSSL_SUCCESS); + + AssertIntEQ(EVP_PKEY_decrypt(ctx, outDec, &outDecLen, outEnc, outEncLen), + WOLFSSL_SUCCESS); + + AssertIntEQ(XMEMCMP(in, outDec, outDecLen), 0); + +#ifdef WC_RSA_NO_PADDING + /* The input length must be the same size as the RSA key.*/ + AssertNotNull(inTmp = (byte*)XMALLOC(rsaKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + XMEMSET(inTmp, 9, rsaKeySz); + AssertNotNull(outEncTmp = (byte*)XMALLOC(rsaKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + XMEMSET(outEncTmp, 0, rsaKeySz); + AssertNotNull(outDecTmp = (byte*)XMALLOC(rsaKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + XMEMSET(outDecTmp, 0, rsaKeySz); + AssertIntEQ(EVP_PKEY_encrypt_init(ctx), WOLFSSL_SUCCESS); + AssertIntEQ(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING), + WOLFSSL_SUCCESS); + AssertIntEQ(EVP_PKEY_encrypt(ctx, outEncTmp, &outEncLen, inTmp, rsaKeySz), + WOLFSSL_SUCCESS); + AssertIntEQ(EVP_PKEY_decrypt_init(ctx), WOLFSSL_SUCCESS); + AssertIntEQ(EVP_PKEY_decrypt(ctx, outDecTmp, &outDecLen, outEncTmp, outEncLen), + WOLFSSL_SUCCESS); + AssertIntEQ(XMEMCMP(inTmp, outDecTmp, outDecLen), 0); +#endif + EVP_PKEY_CTX_free(ctx); + XFREE(outEnc, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(outDec, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WC_RSA_NO_PADDING + XFREE(inTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(outEncTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(outDecTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#endif + printf(resultFmt, passed); +#endif +} +static void test_wolfSSL_EVP_PKEY_sign(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && \ + !defined(HAVE_FAST_RSA) && !defined(HAVE_SELFTEST) + WOLFSSL_RSA* rsa = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; + WOLFSSL_EVP_PKEY_CTX* ctx = NULL; + const char* in = "What is easy to do is easy not to do."; + size_t inlen = XSTRLEN(in); + byte hash[SHA256_DIGEST_LENGTH] = {0}; + SHA256_CTX c; + byte* sig = NULL; + byte* sigVerify = NULL; + size_t siglen = 0; + size_t rsaKeySz = 2048/8; /* Bytes */ + + printf(testingFmt, "wolfSSL_EVP_PKEY_sign()"); + + AssertNotNull(sig = (byte*)XMALLOC(rsaKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + XMEMSET(sig, 0, rsaKeySz); + AssertNotNull(sigVerify = (byte*)XMALLOC(rsaKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); + XMEMSET(sigVerify, 0, rsaKeySz); + + /* Generate hash */ + SHA256_Init(&c); + SHA256_Update(&c, in, inlen); + SHA256_Final(hash, &c); + + AssertNotNull(rsa = RSA_generate_key(2048, 3, NULL, NULL)); + AssertNotNull(pkey = wolfSSL_EVP_PKEY_new()); + AssertIntEQ(EVP_PKEY_assign_RSA(pkey, rsa), WOLFSSL_SUCCESS); + AssertNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + AssertIntEQ(EVP_PKEY_sign_init(ctx), WOLFSSL_SUCCESS); + AssertIntEQ(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING), + WOLFSSL_SUCCESS); + + /* Sign data */ + AssertIntEQ(EVP_PKEY_sign(ctx, sig, &siglen, hash, SHA256_DIGEST_LENGTH), + WOLFSSL_SUCCESS); + /* Verify signature. + EVP_PKEY_verify() doesn't exist yet, so use RSA_public_decrypt(). */ + AssertIntEQ(RSA_public_decrypt((int)siglen, sig, sigVerify, + rsa, RSA_PKCS1_PADDING), SHA256_DIGEST_LENGTH); + + AssertIntEQ(XMEMCMP(hash, sigVerify, SHA256_DIGEST_LENGTH), 0); + /* error cases */ + + AssertIntNE(EVP_PKEY_sign_init(NULL), WOLFSSL_SUCCESS); + ctx->pkey->type = EVP_PKEY_RSA2; + AssertIntNE(EVP_PKEY_sign_init(ctx), WOLFSSL_SUCCESS); + AssertIntNE(EVP_PKEY_sign(NULL, sig, &siglen, (byte*)in, inlen), + WOLFSSL_SUCCESS); + AssertIntNE(EVP_PKEY_sign(ctx, sig, &siglen, (byte*)in, inlen), + WOLFSSL_SUCCESS); + + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + wolfSSL_RSA_free(rsa); + XFREE(sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sigVerify, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + printf(resultFmt, passed); +#endif +} + +static void test_EVP_PKEY_rsa(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) + WOLFSSL_RSA* rsa; + WOLFSSL_EVP_PKEY* pkey; + + AssertNotNull(rsa = wolfSSL_RSA_new()); + AssertNotNull(pkey = wolfSSL_EVP_PKEY_new()); + AssertIntEQ(EVP_PKEY_assign_RSA(NULL, rsa), WOLFSSL_FAILURE); + AssertIntEQ(EVP_PKEY_assign_RSA(pkey, NULL), WOLFSSL_FAILURE); + AssertIntEQ(EVP_PKEY_assign_RSA(pkey, rsa), WOLFSSL_SUCCESS); + AssertPtrEq(EVP_PKEY_get0_RSA(pkey), rsa); + wolfSSL_EVP_PKEY_free(pkey); + + printf(resultFmt, passed); + +#endif +} + +static void test_EVP_PKEY_ec(void) +{ +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) + WOLFSSL_EC_KEY* ecKey; + WOLFSSL_EVP_PKEY* pkey; + + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertNotNull(pkey = wolfSSL_EVP_PKEY_new()); + AssertIntEQ(EVP_PKEY_assign_EC_KEY(NULL, ecKey), WOLFSSL_FAILURE); + AssertIntEQ(EVP_PKEY_assign_EC_KEY(pkey, NULL), WOLFSSL_FAILURE); + AssertIntEQ(EVP_PKEY_assign_EC_KEY(pkey, ecKey), WOLFSSL_SUCCESS); + wolfSSL_EVP_PKEY_free(pkey); + + printf(resultFmt, passed); +#endif +} + +static void test_EVP_PKEY_cmp(void) +{ +#if defined(OPENSSL_EXTRA) + EVP_PKEY *a, *b; + const unsigned char *in; + +#if !defined(NO_RSA) && defined(USE_CERT_BUFFERS_2048) + in = client_key_der_2048; + AssertNotNull(a = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, + &in, (long)sizeof_client_key_der_2048)); + in = client_key_der_2048; + AssertNotNull(b = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, + &in, (long)sizeof_client_key_der_2048)); + + /* Test success case RSA */ + AssertIntEQ(EVP_PKEY_cmp(a, b), 0); + + EVP_PKEY_free(b); + EVP_PKEY_free(a); +#endif + +#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + in = ecc_clikey_der_256; + AssertNotNull(a = wolfSSL_d2i_PrivateKey(EVP_PKEY_EC, NULL, + &in, (long)sizeof_ecc_clikey_der_256)); + in = ecc_clikey_der_256; + AssertNotNull(b = wolfSSL_d2i_PrivateKey(EVP_PKEY_EC, NULL, + &in, (long)sizeof_ecc_clikey_der_256)); + + /* Test success case ECC */ + AssertIntEQ(EVP_PKEY_cmp(a, b), 0); + + EVP_PKEY_free(b); + EVP_PKEY_free(a); +#endif + + /* Test failure cases */ +#if !defined(NO_RSA) && defined(USE_CERT_BUFFERS_2048) && \ + defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + + in = client_key_der_2048; + AssertNotNull(a = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, + &in, (long)sizeof_client_key_der_2048)); + in = ecc_clikey_der_256; + AssertNotNull(b = wolfSSL_d2i_PrivateKey(EVP_PKEY_EC, NULL, + &in, (long)sizeof_ecc_clikey_der_256)); + + AssertIntNE(EVP_PKEY_cmp(a, b), 0); + + EVP_PKEY_free(b); + EVP_PKEY_free(a); +#endif + + /* invalid or empty failure cases */ + a = EVP_PKEY_new(); + b = EVP_PKEY_new(); + AssertIntNE(EVP_PKEY_cmp(NULL, NULL), 0); + AssertIntNE(EVP_PKEY_cmp(a, NULL), 0); + AssertIntNE(EVP_PKEY_cmp(NULL, b), 0); + AssertIntNE(EVP_PKEY_cmp(a, b), 0); + EVP_PKEY_free(b); + EVP_PKEY_free(a); + + (void)in; + + printf(resultFmt, passed); +#endif +} + +static void test_ERR_load_crypto_strings(void) +{ +#if defined(OPENSSL_ALL) + ERR_load_crypto_strings(); + + printf(resultFmt, passed); +#endif +} + +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) +static void free_x509(X509* x) +{ + AssertIntEQ((x == (X509*)1 || x == (X509*)2), 1); +} +#endif + +static void test_sk_X509(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) + STACK_OF(X509)* s; + + AssertNotNull(s = sk_X509_new()); + AssertIntEQ(sk_X509_num(s), 0); + sk_X509_free(s); + + AssertNotNull(s = sk_X509_new_null()); + AssertIntEQ(sk_X509_num(s), 0); + sk_X509_free(s); + + AssertNotNull(s = sk_X509_new()); + sk_X509_push(s, (X509*)1); + AssertIntEQ(sk_X509_num(s), 1); + AssertIntEQ((sk_X509_value(s, 0) == (X509*)1), 1); + sk_X509_push(s, (X509*)2); + AssertIntEQ(sk_X509_num(s), 2); + AssertIntEQ((sk_X509_value(s, 0) == (X509*)2), 1); + AssertIntEQ((sk_X509_value(s, 1) == (X509*)1), 1); + sk_X509_push(s, (X509*)2); + sk_X509_pop_free(s, free_x509); + + printf(resultFmt, passed); +#endif +} + +static void test_X509_get_signature_nid(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) + X509* x509; + + AssertIntEQ(X509_get_signature_nid(NULL), 0); + AssertNotNull(x509 = wolfSSL_X509_load_certificate_file(svrCertFile, + SSL_FILETYPE_PEM)); + AssertIntEQ(X509_get_signature_nid(x509), CTC_SHA256wRSA); + X509_free(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_X509_REQ(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && \ + defined(WOLFSSL_CERT_REQ) + X509_NAME* name; +#if !defined(NO_RSA) || defined(HAVE_ECC) + X509_REQ* req; + EVP_PKEY* priv; + EVP_PKEY* pub; + unsigned char* der = NULL; +#endif +#ifndef NO_RSA + #ifdef USE_CERT_BUFFERS_1024 + const unsigned char* rsaPriv = (const unsigned char*)client_key_der_1024; + const unsigned char* rsaPub = (unsigned char*)client_keypub_der_1024; + #elif defined(USE_CERT_BUFFERS_2048) + const unsigned char* rsaPriv = (const unsigned char*)client_key_der_2048; + const unsigned char* rsaPub = (unsigned char*)client_keypub_der_2048; + #endif +#endif +#ifdef HAVE_ECC + const unsigned char* ecPriv = (const unsigned char*)ecc_clikey_der_256; + const unsigned char* ecPub = (unsigned char*)ecc_clikeypub_der_256; + int len; +#endif + + AssertNotNull(name = X509_NAME_new()); + AssertIntEQ(X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_UTF8, + (byte*)"wolfssl.com", 11, 0, 1), + WOLFSSL_SUCCESS); + AssertIntEQ(X509_NAME_add_entry_by_txt(name, "emailAddress", MBSTRING_UTF8, + (byte*)"support@wolfssl.com", 19, -1, + 1), WOLFSSL_SUCCESS); + +#ifndef NO_RSA + AssertNotNull(priv = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &rsaPriv, + (long)sizeof_client_key_der_2048)); + AssertNotNull(pub = d2i_PUBKEY(NULL, &rsaPub, + (long)sizeof_client_keypub_der_2048)); + AssertNotNull(req = X509_REQ_new()); + AssertIntEQ(X509_REQ_set_subject_name(NULL, name), WOLFSSL_FAILURE); + AssertIntEQ(X509_REQ_set_subject_name(req, NULL), WOLFSSL_FAILURE); + AssertIntEQ(X509_REQ_set_subject_name(req, name), WOLFSSL_SUCCESS); + AssertIntEQ(X509_REQ_set_pubkey(NULL, pub), WOLFSSL_FAILURE); + AssertIntEQ(X509_REQ_set_pubkey(req, NULL), WOLFSSL_FAILURE); + AssertIntEQ(X509_REQ_set_pubkey(req, pub), WOLFSSL_SUCCESS); + AssertIntEQ(X509_REQ_sign(NULL, priv, EVP_sha256()), WOLFSSL_FAILURE); + AssertIntEQ(X509_REQ_sign(req, NULL, EVP_sha256()), WOLFSSL_FAILURE); + AssertIntEQ(X509_REQ_sign(req, priv, NULL), WOLFSSL_FAILURE); + AssertIntEQ(X509_REQ_sign(req, priv, EVP_sha256()), WOLFSSL_SUCCESS); + AssertIntEQ(i2d_X509_REQ(req, &der), 643); + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + der = NULL; + X509_REQ_free(NULL); + X509_REQ_free(req); + EVP_PKEY_free(pub); + EVP_PKEY_free(priv); +#endif +#ifdef HAVE_ECC + AssertNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_EC, NULL, &ecPriv, + sizeof_ecc_clikey_der_256)); + AssertNotNull(pub = wolfSSL_d2i_PUBKEY(NULL, &ecPub, + sizeof_ecc_clikeypub_der_256)); + AssertNotNull(req = X509_REQ_new()); + AssertIntEQ(X509_REQ_set_subject_name(req, name), WOLFSSL_SUCCESS); + AssertIntEQ(X509_REQ_set_pubkey(req, pub), WOLFSSL_SUCCESS); + AssertIntEQ(X509_REQ_sign(req, priv, EVP_sha256()), WOLFSSL_SUCCESS); + /* Signature is random and may be shorter or longer. */ + AssertIntGE((len = i2d_X509_REQ(req, &der)), 245); + AssertIntLE(len, 253); + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + X509_REQ_free(req); + EVP_PKEY_free(pub); + EVP_PKEY_free(priv); + +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif +#endif /* HAVE_ECC */ + + X509_NAME_free(name); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfssl_PKCS7(void) +{ +#if defined(OPENSSL_ALL) && defined(HAVE_PKCS7) + PKCS7* pkcs7; + byte data[FOURK_BUF]; + word32 len = sizeof(data); + const byte* p = data; + byte content[] = "Test data to encode."; + + AssertIntGT((len = CreatePKCS7SignedData(data, len, content, + (word32)sizeof(content), + 0, 0)), 0); + + AssertNull(pkcs7 = d2i_PKCS7(NULL, NULL, len)); + AssertNull(pkcs7 = d2i_PKCS7(NULL, &p, 0)); + AssertNotNull(pkcs7 = d2i_PKCS7(NULL, &p, len)); + AssertIntEQ(wolfSSL_PKCS7_verify(NULL, NULL, NULL, NULL, NULL, + PKCS7_NOVERIFY), WOLFSSL_FAILURE); + PKCS7_free(pkcs7); + + /* fail case, without PKCS7_NOVERIFY */ + p = data; + AssertNotNull(pkcs7 = d2i_PKCS7(NULL, &p, len)); + AssertIntEQ(wolfSSL_PKCS7_verify(pkcs7, NULL, NULL, NULL, NULL, + 0), WOLFSSL_FAILURE); + PKCS7_free(pkcs7); + + /* success case, with PKCS7_NOVERIFY */ + p = data; + AssertNotNull(pkcs7 = d2i_PKCS7(NULL, &p, len)); + AssertIntEQ(wolfSSL_PKCS7_verify(pkcs7, NULL, NULL, NULL, NULL, + PKCS7_NOVERIFY), WOLFSSL_SUCCESS); + + PKCS7_free(NULL); + PKCS7_free(pkcs7); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_PKCS7_SIGNED_new(void) +{ +#if defined(OPENSSL_ALL) && defined(HAVE_PKCS7) + PKCS7_SIGNED* pkcs7; + + printf(testingFmt, "wolfSSL_PKCS7_SIGNED_new()"); + + pkcs7 = PKCS7_SIGNED_new(); + AssertNotNull(pkcs7); + AssertIntEQ(pkcs7->contentOID, SIGNED_DATA); + + PKCS7_SIGNED_free(pkcs7); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_PEM_write_bio_PKCS7(void) +{ +#if defined(OPENSSL_ALL) && defined(HAVE_PKCS7) && !defined(NO_FILESYSTEM) + PKCS7* pkcs7 = NULL; + BIO* bio = NULL; + const byte* cert_buf = NULL; + int ret = 0; + WC_RNG rng; + const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 + }; +#ifndef NO_RSA + #if defined(USE_CERT_BUFFERS_2048) + byte key[sizeof_client_key_der_2048]; + byte cert[sizeof_client_cert_der_2048]; + word32 keySz = (word32)sizeof(key); + word32 certSz = (word32)sizeof(cert); + XMEMSET(key, 0, keySz); + XMEMSET(cert, 0, certSz); + XMEMCPY(key, client_key_der_2048, keySz); + XMEMCPY(cert, client_cert_der_2048, certSz); + #elif defined(USE_CERT_BUFFERS_1024) + byte key[sizeof_client_key_der_1024]; + byte cert[sizeof_client_cert_der_1024]; + word32 keySz = (word32)sizeof(key); + word32 certSz = (word32)sizeof(cert); + XMEMSET(key, 0, keySz); + XMEMSET(cert, 0, certSz); + XMEMCPY(key, client_key_der_1024, keySz); + XMEMCPY(cert, client_cert_der_1024, certSz); + #else + unsigned char cert[ONEK_BUF]; + unsigned char key[ONEK_BUF]; + XFILE fp; + int certSz; + int keySz; + + fp = XFOPEN("./certs/1024/client-cert.der", "rb"); + AssertTrue((fp != XBADFILE)); + certSz = (int)XFREAD(cert, 1, sizeof_client_cert_der_1024, fp); + XFCLOSE(fp); + + fp = XFOPEN("./certs/1024/client-key.der", "rb"); + AssertTrue(fp != XBADFILE); + keySz = (int)XFREAD(key, 1, sizeof_client_key_der_1024, fp); + XFCLOSE(fp); + #endif +#elif defined(HAVE_ECC) + #if defined(USE_CERT_BUFFERS_256) + unsigned char cert[sizeof_cliecc_cert_der_256]; + unsigned char key[sizeof_ecc_clikey_der_256]; + int certSz = (int)sizeof(cert); + int keySz = (int)sizeof(key); + XMEMSET(cert, 0, certSz); + XMEMSET(key, 0, keySz); + XMEMCPY(cert, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); + XMEMCPY(key, ecc_clikey_der_256, sizeof_ecc_clikey_der_256); + #else + unsigned char cert[ONEK_BUF]; + unsigned char key[ONEK_BUF]; + XFILE fp; + int certSz, keySz; + + fp = XFOPEN("./certs/client-ecc-cert.der", "rb"); + AssertTrue(fp != XBADFILE); + certSz = (int)XFREAD(cert, 1, sizeof_cliecc_cert_der_256, fp); + XFCLOSE(fp); + + fp = XFOPEN("./certs/client-ecc-key.der", "rb"); + AssertTrue(fp != XBADFILE); + keySz = (int)XFREAD(key, 1, sizeof_ecc_clikey_der_256, fp); + XFCLOSE(fp); + #endif +#else + #error PKCS7 requires ECC or RSA +#endif + printf(testingFmt, "wolfSSL_PEM_write_bio_PKCS7()"); + + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + /* initialize with DER encoded cert */ + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)cert, (word32)certSz), 0); + + /* init rng */ + AssertIntEQ(wc_InitRng(&rng), 0); + + pkcs7->rng = &rng; + pkcs7->content = (byte*)data; /* not used for ex */ + pkcs7->contentSz = (word32)sizeof(data); + pkcs7->contentOID = SIGNED_DATA; + pkcs7->privateKey = key; + pkcs7->privateKeySz = (word32)sizeof(key); + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHAh; + pkcs7->signedAttribs = NULL; + pkcs7->signedAttribsSz = 0; + + AssertNotNull(bio = BIO_new(BIO_s_mem())); + /* Write PKCS#7 PEM to BIO, the function converts the DER to PEM cert*/ + AssertIntEQ(PEM_write_bio_PKCS7(bio, pkcs7), WOLFSSL_SUCCESS); + + /* Read PKCS#7 PEM from BIO */ + ret = wolfSSL_BIO_get_mem_data(bio, &cert_buf); + AssertIntGE(ret, 0); + + BIO_free(bio); + wc_PKCS7_Free(pkcs7); + wc_FreeRng(&rng); + + printf(resultFmt, passed); + +#endif +} + +/*----------------------------------------------------------------------------* + | Certificate 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); + +#ifdef FP_ECC + wc_ecc_fp_free(); +#endif + return ret; + } + +#endif /* NO_CERTS */ + +#ifdef WOLFSSL_TLS13 +#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) +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; +#ifndef WOLFSSL_NO_TLS12 +#ifndef NO_WOLFSSL_CLIENT + WOLFSSL_CTX* clientTls12Ctx; + WOLFSSL* clientTls12Ssl; +#endif +#ifndef NO_WOLFSSL_SERVER + WOLFSSL_CTX* serverTls12Ctx; + WOLFSSL* serverTls12Ssl; +#endif +#endif +#ifndef NO_WOLFSSL_CLIENT + WOLFSSL_CTX* clientCtx; + WOLFSSL* clientSsl; +#endif +#ifndef NO_WOLFSSL_SERVER + WOLFSSL_CTX* serverCtx; + WOLFSSL* serverSsl; +#ifndef NO_CERTS + const char* ourCert = svrCertFile; + const char* ourKey = svrKeyFile; +#endif +#endif +#ifdef WOLFSSL_EARLY_DATA + int outSz; +#endif + int groups[2] = { WOLFSSL_ECC_X25519, WOLFSSL_ECC_X448 }; + int numGroups = 2; +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) + char groupList[] = "P-521:P-384:P-256"; +#endif /* defined(OPENSSL_EXTRA) && defined(HAVE_ECC) */ + +#ifndef WOLFSSL_NO_TLS12 +#ifndef NO_WOLFSSL_CLIENT + clientTls12Ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + clientTls12Ssl = wolfSSL_new(clientTls12Ctx); +#endif +#ifndef NO_WOLFSSL_SERVER + 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); +#endif +#endif + +#ifndef NO_WOLFSSL_CLIENT + clientCtx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); + clientSsl = wolfSSL_new(clientCtx); +#endif +#ifndef NO_WOLFSSL_SERVER + 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); +#endif + +#ifdef WOLFSSL_SEND_HRR_COOKIE + AssertIntEQ(wolfSSL_send_hrr_cookie(NULL, NULL, 0), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT + AssertIntEQ(wolfSSL_send_hrr_cookie(clientSsl, NULL, 0), SIDE_ERROR); +#endif +#ifndef NO_WOLFSSL_SERVER +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_send_hrr_cookie(serverTls12Ssl, NULL, 0), BAD_FUNC_ARG); +#endif + + AssertIntEQ(wolfSSL_send_hrr_cookie(serverSsl, NULL, 0), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_send_hrr_cookie(serverSsl, fixedKey, sizeof(fixedKey)), + WOLFSSL_SUCCESS); +#endif +#endif + +#ifdef HAVE_ECC + AssertIntEQ(wolfSSL_UseKeyShare(NULL, WOLFSSL_ECC_SECP256R1), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_UseKeyShare(serverSsl, WOLFSSL_ECC_SECP256R1), + WOLFSSL_SUCCESS); +#endif +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_UseKeyShare(clientTls12Ssl, WOLFSSL_ECC_SECP256R1), + WOLFSSL_SUCCESS); +#endif + AssertIntEQ(wolfSSL_UseKeyShare(clientSsl, WOLFSSL_ECC_SECP256R1), + WOLFSSL_SUCCESS); +#endif +#elif defined(HAVE_CURVE25519) + AssertIntEQ(wolfSSL_UseKeyShare(NULL, WOLFSSL_ECC_X25519), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_UseKeyShare(serverSsl, WOLFSSL_ECC_X25519), + WOLFSSL_SUCCESS); +#endif +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_UseKeyShare(clientTls12Ssl, WOLFSSL_ECC_X25519), + WOLFSSL_SUCCESS); +#endif + AssertIntEQ(wolfSSL_UseKeyShare(clientSsl, WOLFSSL_ECC_X25519), + WOLFSSL_SUCCESS); +#endif +#elif defined(HAVE_CURVE448) + AssertIntEQ(wolfSSL_UseKeyShare(NULL, WOLFSSL_ECC_X448), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_UseKeyShare(serverSsl, WOLFSSL_ECC_X448), + WOLFSSL_SUCCESS); +#endif +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_UseKeyShare(clientTls12Ssl, WOLFSSL_ECC_X448), + WOLFSSL_SUCCESS); +#endif + AssertIntEQ(wolfSSL_UseKeyShare(clientSsl, WOLFSSL_ECC_X448), + WOLFSSL_SUCCESS); +#endif +#else + AssertIntEQ(wolfSSL_UseKeyShare(NULL, WOLFSSL_ECC_SECP256R1), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_UseKeyShare(clientTls12Ssl, WOLFSSL_ECC_SECP256R1), + NOT_COMPILED_IN); +#endif + AssertIntEQ(wolfSSL_UseKeyShare(clientSsl, WOLFSSL_ECC_SECP256R1), + NOT_COMPILED_IN); +#endif +#endif + + AssertIntEQ(wolfSSL_NoKeyShares(NULL), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_NoKeyShares(serverSsl), SIDE_ERROR); +#endif +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_NoKeyShares(clientTls12Ssl), WOLFSSL_SUCCESS); +#endif + AssertIntEQ(wolfSSL_NoKeyShares(clientSsl), WOLFSSL_SUCCESS); +#endif + + AssertIntEQ(wolfSSL_CTX_no_ticket_TLSv13(NULL), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT + AssertIntEQ(wolfSSL_CTX_no_ticket_TLSv13(clientCtx), SIDE_ERROR); +#endif +#ifndef NO_WOLFSSL_SERVER +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_CTX_no_ticket_TLSv13(serverTls12Ctx), BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_CTX_no_ticket_TLSv13(serverCtx), 0); +#endif + + AssertIntEQ(wolfSSL_no_ticket_TLSv13(NULL), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT + AssertIntEQ(wolfSSL_no_ticket_TLSv13(clientSsl), SIDE_ERROR); +#endif +#ifndef NO_WOLFSSL_SERVER +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_no_ticket_TLSv13(serverTls12Ssl), BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_no_ticket_TLSv13(serverSsl), 0); +#endif + + AssertIntEQ(wolfSSL_CTX_no_dhe_psk(NULL), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_CTX_no_dhe_psk(clientTls12Ctx), BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_CTX_no_dhe_psk(clientCtx), 0); +#endif +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_CTX_no_dhe_psk(serverCtx), 0); +#endif + + AssertIntEQ(wolfSSL_no_dhe_psk(NULL), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_no_dhe_psk(clientTls12Ssl), BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_no_dhe_psk(clientSsl), 0); +#endif +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_no_dhe_psk(serverSsl), 0); +#endif + + AssertIntEQ(wolfSSL_update_keys(NULL), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_update_keys(clientTls12Ssl), BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_update_keys(clientSsl), BUILD_MSG_ERROR); +#endif +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_update_keys(serverSsl), BUILD_MSG_ERROR); +#endif + +#if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + AssertIntEQ(wolfSSL_CTX_allow_post_handshake_auth(NULL), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_CTX_allow_post_handshake_auth(serverCtx), SIDE_ERROR); +#endif +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_CTX_allow_post_handshake_auth(clientTls12Ctx), + BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_CTX_allow_post_handshake_auth(clientCtx), 0); +#endif + + AssertIntEQ(wolfSSL_allow_post_handshake_auth(NULL), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_allow_post_handshake_auth(serverSsl), SIDE_ERROR); +#endif +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_allow_post_handshake_auth(clientTls12Ssl), + BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_allow_post_handshake_auth(clientSsl), 0); +#endif + + AssertIntEQ(wolfSSL_request_certificate(NULL), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT + AssertIntEQ(wolfSSL_request_certificate(clientSsl), SIDE_ERROR); +#endif +#ifndef NO_WOLFSSL_SERVER +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_request_certificate(serverTls12Ssl), + BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_request_certificate(serverSsl), NOT_READY_ERROR); +#endif +#endif + +#ifndef WOLFSSL_NO_SERVER_GROUPS_EXT + AssertIntEQ(wolfSSL_preferred_group(NULL), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_preferred_group(serverSsl), SIDE_ERROR); +#endif +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_preferred_group(clientTls12Ssl), BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_preferred_group(clientSsl), NOT_READY_ERROR); +#endif +#endif + + AssertIntEQ(wolfSSL_CTX_set_groups(NULL, NULL, 0), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT + AssertIntEQ(wolfSSL_CTX_set_groups(clientCtx, NULL, 0), BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_CTX_set_groups(NULL, groups, numGroups), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_CTX_set_groups(clientTls12Ctx, groups, numGroups), + BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_CTX_set_groups(clientCtx, groups, + WOLFSSL_MAX_GROUP_COUNT + 1), + BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_set_groups(clientCtx, groups, numGroups), + WOLFSSL_SUCCESS); +#endif +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_CTX_set_groups(serverCtx, groups, numGroups), + WOLFSSL_SUCCESS); +#endif + + AssertIntEQ(wolfSSL_set_groups(NULL, NULL, 0), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT + AssertIntEQ(wolfSSL_set_groups(clientSsl, NULL, 0), BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_set_groups(NULL, groups, numGroups), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_set_groups(clientTls12Ssl, groups, numGroups), + BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_set_groups(clientSsl, groups, + WOLFSSL_MAX_GROUP_COUNT + 1), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_set_groups(clientSsl, groups, numGroups), + WOLFSSL_SUCCESS); +#endif +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_set_groups(serverSsl, groups, numGroups), + WOLFSSL_SUCCESS); +#endif + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) + AssertIntEQ(wolfSSL_CTX_set1_groups_list(NULL, NULL), WOLFSSL_FAILURE); +#ifndef NO_WOLFSSL_CLIENT + AssertIntEQ(wolfSSL_CTX_set1_groups_list(clientCtx, NULL), WOLFSSL_FAILURE); +#endif + AssertIntEQ(wolfSSL_CTX_set1_groups_list(NULL, groupList), WOLFSSL_FAILURE); +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_CTX_set1_groups_list(clientTls12Ctx, groupList), + WOLFSSL_FAILURE); +#endif + AssertIntEQ(wolfSSL_CTX_set1_groups_list(clientCtx, groupList), + WOLFSSL_SUCCESS); +#endif +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_CTX_set1_groups_list(serverCtx, groupList), + WOLFSSL_SUCCESS); +#endif + + AssertIntEQ(wolfSSL_set1_groups_list(NULL, NULL), WOLFSSL_FAILURE); +#ifndef NO_WOLFSSL_CLIENT + AssertIntEQ(wolfSSL_set1_groups_list(clientSsl, NULL), WOLFSSL_FAILURE); +#endif + AssertIntEQ(wolfSSL_set1_groups_list(NULL, groupList), WOLFSSL_FAILURE); +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_set1_groups_list(clientTls12Ssl, groupList), + WOLFSSL_FAILURE); +#endif + AssertIntEQ(wolfSSL_set1_groups_list(clientSsl, groupList), + WOLFSSL_SUCCESS); +#endif +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_set1_groups_list(serverSsl, groupList), + WOLFSSL_SUCCESS); +#endif +#endif /* defined(OPENSSL_EXTRA) && defined(HAVE_ECC) */ + +#ifdef WOLFSSL_EARLY_DATA + AssertIntEQ(wolfSSL_CTX_set_max_early_data(NULL, 0), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT + AssertIntEQ(wolfSSL_CTX_set_max_early_data(clientCtx, 0), SIDE_ERROR); +#endif +#ifndef NO_WOLFSSL_SERVER +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_CTX_set_max_early_data(serverTls12Ctx, 0), + BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_CTX_set_max_early_data(serverCtx, 0), 0); +#endif + + AssertIntEQ(wolfSSL_set_max_early_data(NULL, 0), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT + AssertIntEQ(wolfSSL_set_max_early_data(clientSsl, 0), SIDE_ERROR); +#endif +#ifndef NO_WOLFSSL_SERVER +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_set_max_early_data(serverTls12Ssl, 0), BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_set_max_early_data(serverSsl, 0), 0); +#endif + + AssertIntEQ(wolfSSL_write_early_data(NULL, earlyData, sizeof(earlyData), + &outSz), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_CLIENT + 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); +#endif +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_write_early_data(serverSsl, earlyData, + sizeof(earlyData), &outSz), + SIDE_ERROR); +#endif +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_write_early_data(clientTls12Ssl, earlyData, + sizeof(earlyData), &outSz), + BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_write_early_data(clientSsl, earlyData, + sizeof(earlyData), &outSz), + WOLFSSL_FATAL_ERROR); +#endif + + AssertIntEQ(wolfSSL_read_early_data(NULL, earlyDataBuffer, + sizeof(earlyDataBuffer), &outSz), + BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_SERVER + 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); +#endif +#ifndef NO_WOLFSSL_CLIENT + AssertIntEQ(wolfSSL_read_early_data(clientSsl, earlyDataBuffer, + sizeof(earlyDataBuffer), &outSz), + SIDE_ERROR); +#endif +#ifndef NO_WOLFSSL_SERVER +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_read_early_data(serverTls12Ssl, earlyDataBuffer, + sizeof(earlyDataBuffer), &outSz), + BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_read_early_data(serverSsl, earlyDataBuffer, + sizeof(earlyDataBuffer), &outSz), + WOLFSSL_FATAL_ERROR); +#endif +#endif + +#ifndef NO_WOLFSSL_SERVER + wolfSSL_free(serverSsl); + wolfSSL_CTX_free(serverCtx); +#endif +#ifndef NO_WOLFSSL_CLIENT + wolfSSL_free(clientSsl); + wolfSSL_CTX_free(clientCtx); +#endif + +#ifndef WOLFSSL_NO_TLS12 +#ifndef NO_WOLFSSL_SERVER + wolfSSL_free(serverTls12Ssl); + wolfSSL_CTX_free(serverTls12Ctx); +#endif +#ifndef NO_WOLFSSL_CLIENT + wolfSSL_free(clientTls12Ssl); + wolfSSL_CTX_free(clientTls12Ctx); +#endif +#endif + + return ret; +} + +#endif + +#ifdef HAVE_PK_CALLBACKS +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) && \ + !defined(NO_WOLFSSL_CLIENT) && !defined(NO_DH) && !defined(NO_AES) && \ + defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(SINGLE_THREADED) +static int my_DhCallback(WOLFSSL* ssl, struct DhKey* key, + const unsigned char* priv, unsigned int privSz, + const unsigned char* pubKeyDer, unsigned int pubKeySz, + unsigned char* out, unsigned int* outlen, + void* ctx) +{ + /* Test fail when context associated with WOLFSSL is NULL */ + if (ctx == NULL) { + return -1; + } + + (void)ssl; + /* return 0 on success */ + return wc_DhAgree(key, out, outlen, priv, privSz, pubKeyDer, pubKeySz); +}; + +static void test_dh_ctx_setup(WOLFSSL_CTX* ctx) { + wolfSSL_CTX_SetDhAgreeCb(ctx, my_DhCallback); +#ifdef WOLFSSL_AES_128 + AssertIntEQ(wolfSSL_CTX_set_cipher_list(ctx, "DHE-RSA-AES128-SHA256"), + WOLFSSL_SUCCESS); +#endif +#ifdef WOLFSSL_AES_256 + AssertIntEQ(wolfSSL_CTX_set_cipher_list(ctx, "DHE-RSA-AES256-SHA256"), + WOLFSSL_SUCCESS); +#endif +} + +static void test_dh_ssl_setup(WOLFSSL* ssl) +{ + static int dh_test_ctx = 1; + int ret; + + wolfSSL_SetDhAgreeCtx(ssl, &dh_test_ctx); + AssertIntEQ(*((int*)wolfSSL_GetDhAgreeCtx(ssl)), dh_test_ctx); + ret = wolfSSL_SetTmpDH_file(ssl, dhParamFile, WOLFSSL_FILETYPE_PEM); + if (ret != WOLFSSL_SUCCESS && ret != SIDE_ERROR) { + AssertIntEQ(ret, WOLFSSL_SUCCESS); + } +} + +static void test_dh_ssl_setup_fail(WOLFSSL* ssl) +{ + int ret; + + wolfSSL_SetDhAgreeCtx(ssl, NULL); + AssertNull(wolfSSL_GetDhAgreeCtx(ssl)); + ret = wolfSSL_SetTmpDH_file(ssl, dhParamFile, WOLFSSL_FILETYPE_PEM); + if (ret != WOLFSSL_SUCCESS && ret != SIDE_ERROR) { + AssertIntEQ(ret, WOLFSSL_SUCCESS); + } +} +#endif + +static void test_DhCallbacks(void) +{ +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) && \ + !defined(NO_WOLFSSL_CLIENT) && !defined(NO_DH) && !defined(NO_AES) && \ + defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(SINGLE_THREADED) + WOLFSSL_CTX *ctx; + WOLFSSL *ssl; + tcp_ready ready; + func_args server_args; + func_args client_args; + THREAD_TYPE serverThread; + callback_functions func_cb_client; + callback_functions func_cb_server; + int test; + + printf(testingFmt, "test_DhCallbacks"); + +#ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#endif + + AssertIntEQ(wolfSSL_CTX_set_cipher_list(NULL, "NONE"), WOLFSSL_FAILURE); + + wolfSSL_CTX_SetDhAgreeCb(ctx, &my_DhCallback); + + /* load client ca cert */ + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0), + WOLFSSL_SUCCESS); + + /* test with NULL arguments */ + wolfSSL_SetDhAgreeCtx(NULL, &test); + AssertNull(wolfSSL_GetDhAgreeCtx(NULL)); + + /* test success case */ + test = 1; + AssertNotNull(ssl = wolfSSL_new(ctx)); + wolfSSL_SetDhAgreeCtx(ssl, &test); + AssertIntEQ(*((int*)wolfSSL_GetDhAgreeCtx(ssl)), test); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + + /* test a connection where callback is used */ +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + XMEMSET(&server_args, 0, sizeof(func_args)); + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&func_cb_client, 0, sizeof(callback_functions)); + XMEMSET(&func_cb_server, 0, sizeof(callback_functions)); + + StartTCP(); + InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + + server_args.signal = &ready; + client_args.signal = &ready; + server_args.return_code = TEST_FAIL; + client_args.return_code = TEST_FAIL; + + /* set callbacks to use DH functions */ + func_cb_client.ctx_ready = &test_dh_ctx_setup; + func_cb_client.ssl_ready = &test_dh_ssl_setup; +#ifndef WOLFSSL_NO_TLS12 + func_cb_client.method = wolfTLSv1_2_client_method; +#else + func_cb_client.method = wolfTLSv1_3_client_method; +#endif + client_args.callbacks = &func_cb_client; + + func_cb_server.ctx_ready = &test_dh_ctx_setup; + func_cb_server.ssl_ready = &test_dh_ssl_setup; +#ifndef WOLFSSL_NO_TLS12 + func_cb_server.method = wolfTLSv1_2_server_method; +#else + func_cb_server.method = wolfTLSv1_3_server_method; +#endif + server_args.callbacks = &func_cb_server; + + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + test_client_nofail(&client_args, NULL); + join_thread(serverThread); + + AssertTrue(client_args.return_code); + AssertTrue(server_args.return_code); + + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + /* now set user ctx to not be 1 so that the callback returns fail case */ +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + XMEMSET(&server_args, 0, sizeof(func_args)); + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&func_cb_client, 0, sizeof(callback_functions)); + XMEMSET(&func_cb_server, 0, sizeof(callback_functions)); + + StartTCP(); + InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + + server_args.signal = &ready; + client_args.signal = &ready; + server_args.return_code = TEST_FAIL; + client_args.return_code = TEST_FAIL; + + /* set callbacks to use DH functions */ + func_cb_client.ctx_ready = &test_dh_ctx_setup; + func_cb_client.ssl_ready = &test_dh_ssl_setup_fail; +#ifndef WOLFSSL_NO_TLS12 + func_cb_client.method = wolfTLSv1_2_client_method; +#else + func_cb_client.method = wolfTLSv1_3_client_method; +#endif + client_args.callbacks = &func_cb_client; + + func_cb_server.ctx_ready = &test_dh_ctx_setup; + func_cb_server.ssl_ready = &test_dh_ssl_setup_fail; +#ifndef WOLFSSL_NO_TLS12 + func_cb_server.method = wolfTLSv1_2_server_method; +#else + func_cb_server.method = wolfTLSv1_3_server_method; +#endif + server_args.callbacks = &func_cb_server; + + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + test_client_nofail(&client_args, NULL); + join_thread(serverThread); + + AssertIntEQ(client_args.return_code, TEST_FAIL); + AssertIntEQ(server_args.return_code, TEST_FAIL); + + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + printf(resultFmt, passed); +#endif +} +#endif /* HAVE_PK_CALLBACKS */ + +#ifdef HAVE_HASHDRBG + +#ifdef TEST_RESEED_INTERVAL +static int test_wc_RNG_GenerateBlock_Reseed(void) +{ + 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 /* TEST_RESEED_INTERVAL */ + +static int test_wc_RNG_GenerateBlock(void) +{ + int i, ret; + WC_RNG rng; + byte key[32]; + + ret = wc_InitRng(&rng); + + if (ret == 0) { + for(i = 0; i < 10; i++) { + ret = wc_RNG_GenerateBlock(&rng, key, sizeof(key)); + if (ret != 0) { + break; + } + } + } + + wc_FreeRng(&rng); + + (void)rng; /* for WC_NO_RNG case */ + (void)key; + + return ret; +} +#endif + +static void test_wolfSSL_X509_CRL(void) +{ +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) + + X509_CRL *crl; + char pem[][100] = { + "./certs/crl/crl.pem", + "./certs/crl/crl2.pem", + "./certs/crl/caEccCrl.pem", + "./certs/crl/eccCliCRL.pem", + "./certs/crl/eccSrvCRL.pem", + "" + }; + BIO *bio; + +#ifdef HAVE_TEST_d2i_X509_CRL_fp + char der[][100] = { + "./certs/crl/crl.der", + "./certs/crl/crl2.der", + ""}; +#endif + + XFILE fp; + int i; + + printf(testingFmt, "test_wolfSSL_X509_CRL"); + + for (i = 0; pem[i][0] != '\0'; i++) + { + fp = XFOPEN(pem[i], "rb"); + AssertTrue((fp != XBADFILE)); + AssertNotNull(crl = (X509_CRL *)PEM_read_X509_CRL(fp, (X509_CRL **)NULL, NULL, NULL)); + AssertNotNull(crl); + X509_CRL_free(crl); + XFCLOSE(fp); + fp = XFOPEN(pem[i], "rb"); + AssertTrue((fp != XBADFILE)); + AssertNotNull((X509_CRL *)PEM_read_X509_CRL(fp, (X509_CRL **)&crl, NULL, NULL)); + AssertNotNull(crl); + X509_CRL_free(crl); + XFCLOSE(fp); + } + + for (i = 0; pem[i][0] != '\0'; i++) + { + AssertNotNull(bio = BIO_new_file(pem[i], "r")); + AssertNotNull(crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)); + X509_CRL_free(crl); + BIO_free(bio); + } + +#ifdef HAVE_TEST_d2i_X509_CRL_fp + for(i = 0; der[i][0] != '\0'; i++){ + fp = XFOPEN(der[i], "rb"); + AssertTrue((fp != XBADFILE)); + AssertNotNull(crl = (X509_CRL *)d2i_X509_CRL_fp((fp, X509_CRL **)NULL)); + AssertNotNull(crl); + X509_CRL_free(crl); + XFCLOSE(fp); + fp = XFOPEN(der[i], "rb"); + AssertTrue((fp != XBADFILE)); + AssertNotNull((X509_CRL *)d2i_X509_CRL_fp(fp, (X509_CRL **)&crl)); + AssertNotNull(crl); + X509_CRL_free(crl); + XFCLOSE(fp); + } +#endif + + printf(resultFmt, passed); +#endif + return; +} + +static void test_wolfSSL_PEM_read_X509(void) +{ +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && !defined(NO_FILESYSTEM) && \ + !defined(NO_RSA) + X509 *x509 = NULL; + XFILE fp; + + printf(testingFmt, "wolfSSL_PEM_read_X509"); + fp = XFOPEN(svrCertFile, "rb"); + AssertTrue((fp != XBADFILE)); + AssertNotNull(x509 = (X509 *)PEM_read_X509(fp, (X509 **)NULL, NULL, NULL)); + X509_free(x509); + XFCLOSE(fp); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_PEM_read(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) + const char* filename = "./certs/server-keyEnc.pem"; + XFILE fp; + char* name = NULL; + char* header = NULL; + byte* data = NULL; + long len; + EVP_CIPHER_INFO cipher; + WOLFSSL_BIO* bio; + byte* fileData; + size_t fileDataSz; + byte* out; + + printf(testingFmt, "wolfSSL_PEM_read"); + fp = XFOPEN(filename, "rb"); + AssertTrue((fp != XBADFILE)); + + /* Fail cases. */ + AssertIntEQ(PEM_read(fp, NULL, &header, &data, &len), WOLFSSL_FAILURE); + AssertIntEQ(PEM_read(fp, &name, NULL, &data, &len), WOLFSSL_FAILURE); + AssertIntEQ(PEM_read(fp, &name, &header, NULL, &len), WOLFSSL_FAILURE); + AssertIntEQ(PEM_read(fp, &name, &header, &data, NULL), WOLFSSL_FAILURE); + + AssertIntEQ(PEM_read(fp, &name, &header, &data, &len), WOLFSSL_SUCCESS); + + AssertIntEQ(XSTRNCMP(name, "RSA PRIVATE KEY", 15), 0); + AssertIntGT(XSTRLEN(header), 0); + AssertIntGT(len, 0); + + AssertIntEQ(XFSEEK(fp, 0, SEEK_END), 0); + AssertIntGT((fileDataSz = XFTELL(fp)), 0); + AssertIntEQ(XFSEEK(fp, 0, SEEK_SET), 0); + AssertNotNull(fileData = (unsigned char*)XMALLOC(fileDataSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + AssertIntEQ(XFREAD(fileData, 1, fileDataSz, fp), fileDataSz); + XFCLOSE(fp); + + AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + + /* Fail cases. */ + AssertIntEQ(PEM_write_bio(NULL, name, header, data, len), 0); + AssertIntEQ(PEM_write_bio(bio, NULL, header, data, len), 0); + AssertIntEQ(PEM_write_bio(bio, name, NULL, data, len), 0); + AssertIntEQ(PEM_write_bio(bio, name, header, NULL, len), 0); + + AssertIntEQ(PEM_write_bio(bio, name, header, data, len), fileDataSz); + AssertIntEQ(wolfSSL_BIO_get_mem_data(bio, &out), fileDataSz); + AssertIntEQ(XMEMCMP(out, fileData, fileDataSz), 0); + + /* Fail cases. */ + AssertIntEQ(PEM_get_EVP_CIPHER_INFO(NULL, &cipher), WOLFSSL_FAILURE); + AssertIntEQ(PEM_get_EVP_CIPHER_INFO(header, NULL), WOLFSSL_FAILURE); + AssertIntEQ(PEM_get_EVP_CIPHER_INFO((char*)"", &cipher), WOLFSSL_FAILURE); + +#ifndef NO_DES3 + AssertIntEQ(PEM_get_EVP_CIPHER_INFO(header, &cipher), WOLFSSL_SUCCESS); +#endif + + /* Fail cases. */ + AssertIntEQ(PEM_do_header(&cipher, NULL, &len, PasswordCallBack, + (void*)"yassl123"), WOLFSSL_FAILURE); + AssertIntEQ(PEM_do_header(&cipher, data, NULL, PasswordCallBack, + (void*)"yassl123"), WOLFSSL_FAILURE); + AssertIntEQ(PEM_do_header(&cipher, data, &len, NULL, + (void*)"yassl123"), WOLFSSL_FAILURE); + +#if !defined(NO_DES3) && !defined(NO_MD5) + AssertIntEQ(PEM_do_header(&cipher, data, &len, PasswordCallBack, + (void*)"yassl123"), WOLFSSL_SUCCESS); +#endif + + BIO_free(bio); + XFREE(fileData, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + name = NULL; + header = NULL; + data = NULL; + fp = XFOPEN(svrKeyFile, "rb"); + AssertTrue((fp != XBADFILE)); + AssertIntEQ(PEM_read(fp, &name, &header, &data, &len), WOLFSSL_SUCCESS); + AssertIntEQ(XSTRNCMP(name, "RSA PRIVATE KEY", 15), 0); + AssertIntEQ(XSTRLEN(header), 0); + AssertIntGT(len, 0); + + AssertIntEQ(XFSEEK(fp, 0, SEEK_END), 0); + AssertIntGT((fileDataSz = XFTELL(fp)), 0); + AssertIntEQ(XFSEEK(fp, 0, SEEK_SET), 0); + AssertNotNull(fileData = (unsigned char*)XMALLOC(fileDataSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + AssertIntEQ(XFREAD(fileData, 1, fileDataSz, fp), fileDataSz); + XFCLOSE(fp); + + AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + AssertIntEQ(PEM_write_bio(bio, name, header, data, len), fileDataSz); + AssertIntEQ(wolfSSL_BIO_get_mem_data(bio, &out), fileDataSz); + AssertIntEQ(XMEMCMP(out, fileData, fileDataSz), 0); + + BIO_free(bio); + XFREE(fileData, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfssl_EVP_aes_gcm(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_AES) && defined(HAVE_AESGCM) && \ + !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + + /* A 256 bit key, AES_128 will use the first 128 bit*/ + byte *key = (byte*)"01234567890123456789012345678901"; + /* A 128 bit IV */ + byte *iv = (byte*)"0123456789012345"; + int ivSz = AES_BLOCK_SIZE; + /* Message to be encrypted */ + byte *plaintxt = (byte*)"for things to change you have to change"; + /* Additional non-confidential data */ + byte *aad = (byte*)"Don't spend major time on minor things."; + + unsigned char tag[AES_BLOCK_SIZE] = {0}; + int plaintxtSz = (int)XSTRLEN((char*)plaintxt); + int aadSz = (int)XSTRLEN((char*)aad); + byte ciphertxt[AES_BLOCK_SIZE * 4] = {0}; + byte decryptedtxt[AES_BLOCK_SIZE * 4] = {0}; + int ciphertxtSz = 0; + int decryptedtxtSz = 0; + int len = 0; + int i = 0; + EVP_CIPHER_CTX en[2]; + EVP_CIPHER_CTX de[2]; + + printf(testingFmt, "wolfssl_EVP_aes_gcm"); + + for (i = 0; i < 2; i++) { + + EVP_CIPHER_CTX_init(&en[i]); + + if (i == 0) { + /* Default uses 96-bits IV length */ +#ifdef WOLFSSL_AES_128 + AssertIntEQ(1, EVP_EncryptInit_ex(&en[i], EVP_aes_128_gcm(), NULL, key, iv)); +#elif defined(WOLFSSL_AES_192) + AssertIntEQ(1, EVP_EncryptInit_ex(&en[i], EVP_aes_192_gcm(), NULL, key, iv)); +#elif defined(WOLFSSL_AES_256) + AssertIntEQ(1, EVP_EncryptInit_ex(&en[i], EVP_aes_256_gcm(), NULL, key, iv)); +#endif + } + else { +#ifdef WOLFSSL_AES_128 + AssertIntEQ(1, EVP_EncryptInit_ex(&en[i], EVP_aes_128_gcm(), NULL, NULL, NULL)); +#elif defined(WOLFSSL_AES_192) + AssertIntEQ(1, EVP_EncryptInit_ex(&en[i], EVP_aes_192_gcm(), NULL, NULL, NULL)); +#elif defined(WOLFSSL_AES_256) + AssertIntEQ(1, EVP_EncryptInit_ex(&en[i], EVP_aes_256_gcm(), NULL, NULL, NULL)); +#endif + /* non-default must to set the IV length first */ + AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&en[i], EVP_CTRL_GCM_SET_IVLEN, ivSz, NULL)); + AssertIntEQ(1, EVP_EncryptInit_ex(&en[i], NULL, NULL, key, iv)); + } + AssertIntEQ(1, EVP_EncryptUpdate(&en[i], NULL, &len, aad, aadSz)); + AssertIntEQ(1, EVP_EncryptUpdate(&en[i], ciphertxt, &len, plaintxt, plaintxtSz)); + ciphertxtSz = len; + AssertIntEQ(1, EVP_EncryptFinal_ex(&en[i], ciphertxt, &len)); + ciphertxtSz += len; + AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&en[i], EVP_CTRL_GCM_GET_TAG, AES_BLOCK_SIZE, tag)); + + EVP_CIPHER_CTX_init(&de[i]); + if (i == 0) { + /* Default uses 96-bits IV length */ +#ifdef WOLFSSL_AES_128 + AssertIntEQ(1, EVP_DecryptInit_ex(&de[i], EVP_aes_128_gcm(), NULL, key, iv)); +#elif defined(WOLFSSL_AES_192) + AssertIntEQ(1, EVP_DecryptInit_ex(&de[i], EVP_aes_192_gcm(), NULL, key, iv)); +#elif defined(WOLFSSL_AES_256) + AssertIntEQ(1, EVP_DecryptInit_ex(&de[i], EVP_aes_256_gcm(), NULL, key, iv)); +#endif + } + else { +#ifdef WOLFSSL_AES_128 + AssertIntEQ(1, EVP_DecryptInit_ex(&de[i], EVP_aes_128_gcm(), NULL, NULL, NULL)); +#elif defined(WOLFSSL_AES_192) + AssertIntEQ(1, EVP_DecryptInit_ex(&de[i], EVP_aes_192_gcm(), NULL, NULL, NULL)); +#elif defined(WOLFSSL_AES_256) + AssertIntEQ(1, EVP_DecryptInit_ex(&de[i], EVP_aes_256_gcm(), NULL, NULL, NULL)); +#endif + /* non-default must to set the IV length first */ + AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&de[i], EVP_CTRL_GCM_SET_IVLEN, ivSz, NULL)); + AssertIntEQ(1, EVP_DecryptInit_ex(&de[i], NULL, NULL, key, iv)); + + } + AssertIntEQ(1, EVP_DecryptUpdate(&de[i], NULL, &len, aad, aadSz)); + AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&de[i], EVP_CTRL_GCM_SET_TAG, AES_BLOCK_SIZE, tag)); + AssertIntEQ(1, EVP_DecryptUpdate(&de[i], decryptedtxt, &len, ciphertxt, ciphertxtSz)); + decryptedtxtSz = len; + AssertIntGT(EVP_DecryptFinal_ex(&de[i], decryptedtxt, &len), 0); + decryptedtxtSz += len; + AssertIntEQ(ciphertxtSz, decryptedtxtSz); + AssertIntEQ(0, XMEMCMP(plaintxt, decryptedtxt, decryptedtxtSz)); + + /* modify tag*/ + tag[AES_BLOCK_SIZE-1]+=0xBB; + AssertIntEQ(1, EVP_DecryptUpdate(&de[i], NULL, &len, aad, aadSz)); + AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&de[i], EVP_CTRL_GCM_SET_TAG, AES_BLOCK_SIZE, tag)); + /* fail due to wrong tag */ + AssertIntEQ(0, EVP_DecryptUpdate(&de[i], decryptedtxt, &len, ciphertxt, ciphertxtSz)); + AssertIntEQ(0, len); + } + printf(resultFmt, passed); + +#endif /* OPENSSL_EXTRA && !NO_AES && HAVE_AESGCM */ +} + +static void test_wolfSSL_PEM_X509_INFO_read_bio(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) + BIO* bio; + X509_INFO* info; + STACK_OF(X509_INFO)* sk; + char* subject; + char exp1[] = "/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com"; + char exp2[] = "/C=US/ST=Montana/L=Bozeman/O=wolfSSL/OU=Support/CN=www.wolfssl.com/emailAddress=info@wolfssl.com"; + + printf(testingFmt, "wolfSSL_PEM_X509_INFO_read_bio"); + AssertNotNull(bio = BIO_new(BIO_s_file())); + AssertIntGT(BIO_read_filename(bio, svrCertFile), 0); + AssertNotNull(sk = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL)); + AssertIntEQ(sk_X509_INFO_num(sk), 2); + + /* using dereference to maintain testing for Apache port*/ + AssertNotNull(info = sk_X509_INFO_pop(sk)); + AssertNotNull(info->x_pkey); + AssertNotNull(info->x_pkey->dec_pkey); + AssertIntEQ(EVP_PKEY_bits(info->x_pkey->dec_pkey), 2048); + AssertNotNull(subject = + X509_NAME_oneline(X509_get_subject_name(info->x509), 0, 0)); + + AssertIntEQ(0, XSTRNCMP(subject, exp1, sizeof(exp1))); + XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL); + X509_INFO_free(info); + + AssertNotNull(info = sk_X509_INFO_pop(sk)); + AssertNotNull(subject = + X509_NAME_oneline(X509_get_subject_name(info->x509), 0, 0)); + + AssertIntEQ(0, XSTRNCMP(subject, exp2, sizeof(exp2))); + XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL); + X509_INFO_free(info); + AssertNull(info = sk_X509_INFO_pop(sk)); + + sk_X509_INFO_pop_free(sk, X509_INFO_free); + BIO_free(bio); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_NAME_ENTRY_get_object() +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) + X509 *x509; + X509_NAME* name; + int idx = 0; + X509_NAME_ENTRY *ne; + ASN1_OBJECT *object = NULL; + + printf(testingFmt, "wolfSSL_X509_NAME_ENTRY_get_object"); + x509 = wolfSSL_X509_load_certificate_file(cliCertFile, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + name = X509_get_subject_name(x509); + idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1); + AssertIntGE(idx, 0); + + ne = X509_NAME_get_entry(name, idx); + AssertNotNull(ne); + AssertNotNull(object = X509_NAME_ENTRY_get_object(ne)); + + X509_free(x509); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_ASN1_INTEGER_set() +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + ASN1_INTEGER *a; + long val; + int ret; + + printf(testingFmt, "wolfSSL_ASN1_INTEGER_set"); + + a = wolfSSL_ASN1_INTEGER_new(); + val = 0; + ret = ASN1_INTEGER_set(NULL, val); + AssertIntEQ(ret, 0); + wolfSSL_ASN1_INTEGER_free(a); + + /* 0 */ + a = wolfSSL_ASN1_INTEGER_new(); + val = 0; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + wolfSSL_ASN1_INTEGER_free(a); + + /* 40 */ + a = wolfSSL_ASN1_INTEGER_new(); + val = 40; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + wolfSSL_ASN1_INTEGER_free(a); + + /* -40 */ + a = wolfSSL_ASN1_INTEGER_new(); + val = -40; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + AssertIntEQ(a->negative, 1); + wolfSSL_ASN1_INTEGER_free(a); + + /* 128 */ + a = wolfSSL_ASN1_INTEGER_new(); + val = 128; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + wolfSSL_ASN1_INTEGER_free(a); + + /* -128 */ + a = wolfSSL_ASN1_INTEGER_new(); + val = -128; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + AssertIntEQ(a->negative, 1); + wolfSSL_ASN1_INTEGER_free(a); + + /* 200 */ + a = wolfSSL_ASN1_INTEGER_new(); + val = 200; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + wolfSSL_ASN1_INTEGER_free(a); + +#ifndef TIME_T_NOT_64BIT + /* 2147483648 */ + a = wolfSSL_ASN1_INTEGER_new(); + val = 2147483648; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + wolfSSL_ASN1_INTEGER_free(a); + + /* -2147483648 */ + a = wolfSSL_ASN1_INTEGER_new(); + val = -2147483648; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(a->negative, 1); + AssertIntEQ(ret, 1); + wolfSSL_ASN1_INTEGER_free(a); +#endif + + printf(resultFmt, passed); +#endif +} + +/* Testing code used in dpp.c in hostap */ +#ifdef OPENSSL_ALL +typedef struct { + /* AlgorithmIdentifier ecPublicKey with optional parameters present + * as an OID identifying the curve */ + X509_ALGOR *alg; + /* Compressed format public key per ANSI X9.63 */ + ASN1_BIT_STRING *pub_key; +} DPP_BOOTSTRAPPING_KEY; + +ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = { + ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR), + ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY); + +IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY); +#endif /* WOLFSSL_WPAS */ + +static void test_wolfSSL_IMPLEMENT_ASN1_FUNCTIONS() +{ + /* Testing code used in dpp.c in hostap */ +#if defined(OPENSSL_ALL) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + EC_KEY *eckey; + EVP_PKEY *key; + size_t len; + unsigned char *der = NULL; + DPP_BOOTSTRAPPING_KEY *bootstrap = NULL; + const unsigned char *in = ecc_clikey_der_256; + const EC_GROUP *group; + const EC_POINT *point; + int nid; + + AssertNotNull(bootstrap = DPP_BOOTSTRAPPING_KEY_new()); + + AssertNotNull(key = d2i_PrivateKey(EVP_PKEY_EC, NULL, &in, + (long)sizeof_ecc_clikey_der_256)); + AssertNotNull(eckey = EVP_PKEY_get1_EC_KEY(key)); + AssertNotNull(group = EC_KEY_get0_group(eckey)); + AssertNotNull(point = EC_KEY_get0_public_key(eckey)); + nid = EC_GROUP_get_curve_name(group); + + AssertIntEQ(X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC), + V_ASN1_OBJECT, OBJ_nid2obj(nid)), 1); +#ifdef HAVE_COMP_KEY + AssertIntGT((len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, + NULL, 0, NULL)), 0); +#else + AssertIntGT((len = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, + NULL, 0, NULL)), 0); +#endif + AssertNotNull(der = XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1)); +#ifdef HAVE_COMP_KEY + AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, + der, len, NULL), len); +#else + AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, + der, len, NULL), len); +#endif + bootstrap->pub_key->data = der; + bootstrap->pub_key->length = (int)len; + /* Not actually used */ + bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; + + der = NULL; + AssertIntGT(i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der), 0); + + XFREE(der, NULL, DYNAMIC_TYPE_ASN1); + EVP_PKEY_free(key); + EC_KEY_free(eckey); + DPP_BOOTSTRAPPING_KEY_free(bootstrap); +#endif /* WOLFSSL_WPAS && HAVE_ECC && USE_CERT_BUFFERS_256 */ +} + +static void test_wolfSSL_i2c_ASN1_INTEGER() +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + ASN1_INTEGER *a; + unsigned char *pp,*tpp; + int ret; + + printf(testingFmt, "wolfSSL_i2c_ASN1_INTEGER"); + + a = wolfSSL_ASN1_INTEGER_new(); + + /* 40 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 1; + a->intData[2] = 40; + ret = i2c_ASN1_INTEGER(a, NULL); + AssertIntEQ(ret, 1); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + i2c_ASN1_INTEGER(a, &pp); + pp--; + AssertIntEQ(*pp, 40); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* 128 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 1; + a->intData[2] = 128; + ret = wolfSSL_i2c_ASN1_INTEGER(a, NULL); + AssertIntEQ(ret, 2); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + wolfSSL_i2c_ASN1_INTEGER(a, &pp); + pp--; + AssertIntEQ(*(pp--), 128); + AssertIntEQ(*pp, 0); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* -40 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 1; + a->intData[2] = 40; + a->negative = 1; + ret = wolfSSL_i2c_ASN1_INTEGER(a, NULL); + AssertIntEQ(ret, 1); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + wolfSSL_i2c_ASN1_INTEGER(a, &pp); + pp--; + AssertIntEQ(*pp, 216); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* -128 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 1; + a->intData[2] = 128; + a->negative = 1; + ret = wolfSSL_i2c_ASN1_INTEGER(a, NULL); + AssertIntEQ(ret, 1); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + wolfSSL_i2c_ASN1_INTEGER(a, &pp); + pp--; + AssertIntEQ(*pp, 128); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* -200 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 1; + a->intData[2] = 200; + a->negative = 1; + ret = wolfSSL_i2c_ASN1_INTEGER(a, NULL); + AssertIntEQ(ret, 2); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + wolfSSL_i2c_ASN1_INTEGER(a, &pp); + pp--; + AssertIntEQ(*(pp--), 56); + AssertIntEQ(*pp, 255); + + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_ASN1_INTEGER_free(a); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && !NO_ASN */ +} + +#ifndef NO_INLINE +#define WOLFSSL_MISC_INCLUDED +#include +#else +#include +#endif + +static int test_ForceZero(void) +{ + unsigned char data[32]; + unsigned int i, j, len; + + /* Test case with 0 length */ + ForceZero(data, 0); + + /* Test ForceZero */ + for (i = 0; i < sizeof(data); i++) { + for (len = 1; len < sizeof(data) - i; len++) { + for (j = 0; j < sizeof(data); j++) + data[j] = j + 1; + + ForceZero(data + i, len); + + for (j = 0; j < sizeof(data); j++) { + if (j < i || j >= i + len) { + if (data[j] == 0x00) + return -10200; + } + else if (data[j] != 0x00) + return -10201; + } + } + } + + return 0; +} + +static void test_wolfSSL_X509_print() +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && \ + !defined(NO_RSA) && !defined(HAVE_FAST_RSA) && defined(XSNPRINTF) + X509 *x509; + BIO *bio; + + printf(testingFmt, "wolfSSL_X509_print"); + x509 = X509_load_certificate_file(svrCertFile, WOLFSSL_FILETYPE_PEM); + AssertNotNull(x509); + + /* print to memory */ + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertIntEQ(X509_print(bio, x509), SSL_SUCCESS); + +#if defined(WOLFSSL_QT) + AssertIntEQ(BIO_get_mem_data(bio, NULL), 3113); +#else + AssertIntEQ(BIO_get_mem_data(bio, NULL), 3103); +#endif + BIO_free(bio); + + /* print to stdout */ + AssertNotNull(bio = BIO_new(BIO_s_file())); + wolfSSL_BIO_set_fp(bio, stdout, BIO_NOCLOSE); + AssertIntEQ(X509_print(bio, x509), SSL_SUCCESS); + BIO_free(bio); + + X509_free(x509); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_RSA_print() +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && \ + !defined(NO_RSA) && !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \ + !defined(HAVE_FAST_RSA) + BIO *bio; + WOLFSSL_RSA* rsa = NULL; + printf(testingFmt, "wolfSSL_RSA_print"); + + AssertNotNull(rsa = RSA_generate_key(2048, 3, NULL, NULL)); + AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file())); + wolfSSL_BIO_set_fp(bio, stdout, BIO_NOCLOSE); + AssertIntEQ(RSA_print(bio, rsa, 0), SSL_SUCCESS); + + BIO_free(bio); + wolfSSL_RSA_free(rsa); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_BIO_get_len() +{ +#if defined(OPENSSL_EXTRA) + BIO *bio; + const char txt[] = "Some example text to push to the BIO."; + printf(testingFmt, "wolfSSL_BIO_get_len"); + + AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + AssertIntEQ(wolfSSL_BIO_write(bio, txt, sizeof(txt)), sizeof(txt)); + AssertIntEQ(wolfSSL_BIO_get_len(bio), sizeof(txt)); + + BIO_free(bio); + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_ASN1_STRING_print(void){ +#if defined(OPENSSL_ALL) && !defined(NO_ASN) && !defined(NO_CERTS) + ASN1_STRING* asnStr = NULL; + const char HELLO_DATA[]= \ + {'H','e','l','l','o',' ','w','o','l','f','S','S','L','!'}; + const unsigned int MAX_UNPRINTABLE_CHAR = 32; + const unsigned int MAX_BUF = 255; + const int LF = 10, CR = 13; + unsigned char unprintableData[MAX_UNPRINTABLE_CHAR + sizeof(HELLO_DATA)]; + unsigned char expected[sizeof(unprintableData)+1]; + unsigned char rbuf[MAX_BUF]; + + BIO *bio; + int p_len, i; + + printf(testingFmt, "wolfSSL_ASN1_STRING_print()"); + + /* setup */ + + for (i = 0; i < (int)sizeof(HELLO_DATA); i++) { + unprintableData[i] = HELLO_DATA[i]; + expected[i] = HELLO_DATA[i]; + } + + for (i = 0; i < (int)MAX_UNPRINTABLE_CHAR; i++) { + unprintableData[sizeof(HELLO_DATA)+i] = i; + + if (i == LF || i == CR) + expected[sizeof(HELLO_DATA)+i] = i; + else + expected[sizeof(HELLO_DATA)+i] = '.'; + } + + unprintableData[sizeof(unprintableData)-1] = '\0'; + expected[sizeof(expected)-1] = '\0'; + + XMEMSET(rbuf, 0, MAX_BUF); + bio = BIO_new(BIO_s_mem()); + BIO_set_write_buf_size(bio, MAX_BUF); + + asnStr = ASN1_STRING_type_new(V_ASN1_OCTET_STRING); + ASN1_STRING_set(asnStr,(const void*)unprintableData, + sizeof(unprintableData)); + /* test */ + p_len = wolfSSL_ASN1_STRING_print(bio, asnStr); + AssertIntEQ(p_len, 46); + BIO_read(bio, (void*)rbuf, 46); + + AssertStrEQ((char*)rbuf, (const char*)expected); + + BIO_free(bio); + ASN1_STRING_free(asnStr); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && !NO_ASN && !NO_CERTS */ +} + +static void test_wolfSSL_RSA_verify() +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(HAVE_FAST_RSA) && \ + !defined(NO_FILESYSTEM) && defined(HAVE_CRL) + XFILE fp; + RSA *pKey, *pubKey; + X509 *cert; + const char *text = "Hello wolfSSL !"; + unsigned char hash[SHA256_DIGEST_LENGTH]; + unsigned char signature[2048/8]; + unsigned int signatureLength; + byte *buf; + BIO *bio; + SHA256_CTX c; + EVP_PKEY *evpPkey, *evpPubkey; + size_t sz; + + printf(testingFmt, "wolfSSL_RSA_verify"); + + /* generate hash */ + SHA256_Init(&c); + SHA256_Update(&c, text, strlen(text)); + SHA256_Final(hash, &c); + + /* read privete key file */ + fp = XFOPEN(svrKeyFile, "r"); + AssertTrue((fp != XBADFILE)); + XFSEEK(fp, 0, XSEEK_END); + sz = XFTELL(fp); + XREWIND(fp); + AssertNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); + AssertIntEQ(XFREAD(buf, 1, sz, fp), sz); + XFCLOSE(fp); + + /* read private key and sign hash data */ + AssertNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + AssertNotNull(evpPkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)); + AssertNotNull(pKey = EVP_PKEY_get1_RSA(evpPkey)); + AssertIntEQ(RSA_sign(NID_sha256, hash, SHA256_DIGEST_LENGTH, + signature, &signatureLength, pKey), SSL_SUCCESS); + + /* read public key and verify signed data */ + fp = XFOPEN(svrCertFile,"r"); + AssertTrue((fp != XBADFILE)); + cert = PEM_read_X509(fp, 0, 0, 0 ); + XFCLOSE(fp); + evpPubkey = X509_get_pubkey(cert); + pubKey = EVP_PKEY_get1_RSA(evpPubkey); + AssertIntEQ(RSA_verify(NID_sha256, hash, SHA256_DIGEST_LENGTH, signature, + signatureLength, pubKey), SSL_SUCCESS); + + RSA_free(pKey); + EVP_PKEY_free(evpPkey); + RSA_free(pubKey); + EVP_PKEY_free(evpPubkey); + X509_free(cert); + BIO_free(bio); + XFREE(buf, NULL, DYNAMIC_TYPE_FILE); + printf(resultFmt, passed); +#endif +} + + +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) +static void test_openssl_make_self_signed_certificate(EVP_PKEY* pkey) +{ + X509* x509 = NULL; + BIGNUM* serial_number = NULL; + X509_NAME* name = NULL; + time_t epoch_off = 0; + ASN1_INTEGER* asn1_serial_number; + long not_before, not_after; + + AssertNotNull(x509 = X509_new()); + + AssertIntNE(X509_set_pubkey(x509, pkey), 0); + + AssertNotNull(serial_number = BN_new()); + AssertIntNE(BN_pseudo_rand(serial_number, 64, 0, 0), 0); + AssertNotNull(asn1_serial_number = X509_get_serialNumber(x509)); + AssertNotNull(BN_to_ASN1_INTEGER(serial_number, asn1_serial_number)); + + /* version 3 */ + AssertIntNE(X509_set_version(x509, 2L), 0); + + AssertNotNull(name = X509_NAME_new()); + + AssertIntNE(X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_UTF8, + (unsigned char*)"www.wolfssl.com", -1, -1, 0), 0); + + AssertIntNE(X509_set_subject_name(x509, name), 0); + AssertIntNE(X509_set_issuer_name(x509, name), 0); + + not_before = (long)XTIME(NULL); + not_after = not_before + (365 * 24 * 60 * 60); + AssertNotNull(X509_time_adj(X509_get_notBefore(x509), not_before, &epoch_off)); + AssertNotNull(X509_time_adj(X509_get_notAfter(x509), not_after, &epoch_off)); + + AssertIntNE(X509_sign(x509, pkey, EVP_sha256()), 0); + + BN_free(serial_number); + X509_NAME_free(name); + X509_free(x509); +} +#endif + +static void test_openssl_generate_key_and_cert(void) +{ +#if defined(OPENSSL_EXTRA) +#if !defined(NO_RSA) + { + EVP_PKEY* pkey = EVP_PKEY_new(); + int key_length = 2048; + BIGNUM* exponent = BN_new(); + RSA* rsa = RSA_new(); + + AssertNotNull(pkey); + AssertNotNull(exponent); + AssertNotNull(rsa); + + AssertIntNE(BN_set_word(exponent, WC_RSA_EXPONENT), 0); + #ifndef WOLFSSL_KEY_GEN + AssertIntEQ(RSA_generate_key_ex(rsa, key_length, exponent, NULL), WOLFSSL_FAILURE); + + #if defined(USE_CERT_BUFFERS_1024) + AssertIntNE(wolfSSL_RSA_LoadDer_ex(rsa, server_key_der_1024, + sizeof_server_key_der_1024, WOLFSSL_RSA_LOAD_PRIVATE), 0); + key_length = 1024; + #elif defined(USE_CERT_BUFFERS_2048) + AssertIntNE(wolfSSL_RSA_LoadDer_ex(rsa, server_key_der_2048, + sizeof_server_key_der_2048, WOLFSSL_RSA_LOAD_PRIVATE), 0); + #else + RSA_free(rsa); + rsa = NULL; + #endif + #else + AssertIntNE(RSA_generate_key_ex(rsa, key_length, exponent, NULL), 0); + #endif + + if (rsa) { + AssertIntNE(EVP_PKEY_assign_RSA(pkey, rsa), 0); + + BN_free(exponent); + + #if !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) + test_openssl_make_self_signed_certificate(pkey); + #endif + } + + EVP_PKEY_free(pkey); + } +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC + { + EVP_PKEY* pkey = EVP_PKEY_new(); + EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + + AssertNotNull(pkey); + AssertNotNull(ec_key); + + #ifndef NO_WOLFSSL_STUB + EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE); + #endif + + AssertIntNE(EC_KEY_generate_key(ec_key), 0); + AssertIntNE(EVP_PKEY_assign_EC_KEY(pkey, ec_key), 0); + + #if !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) + test_openssl_make_self_signed_certificate(pkey); + #endif + + EVP_PKEY_free(pkey); + } +#endif /* HAVE_ECC */ +#endif /* OPENSSL_EXTRA */ +} + +static void test_stubs_are_stubs() +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_STUB) + WOLFSSL_CTX* ctx = NULL; + WOLFSSL_CTX* ctxN = NULL; + #ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + #elif !defined(NO_WOLFSSL_SERVER) + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + #else + return; + #endif + + #define CHECKZERO_RET(x, y, z) AssertIntEQ((int) x(y), 0); \ + AssertIntEQ((int) x(z), 0) + /* test logic, all stubs return same result regardless of ctx being NULL + * as there are no sanity checks, it's just a stub! If at some + * point a stub is not a stub it should begin to return BAD_FUNC_ARG + * if invalid inputs are supplied. Test calling both + * with and without valid inputs, if a stub functionality remains unchanged. + */ + CHECKZERO_RET(wolfSSL_CTX_sess_accept, ctx, ctxN); + CHECKZERO_RET(wolfSSL_CTX_sess_connect, ctx, ctxN); + CHECKZERO_RET(wolfSSL_CTX_sess_accept_good, ctx, ctxN); + CHECKZERO_RET(wolfSSL_CTX_sess_connect_good, ctx, ctxN); + CHECKZERO_RET(wolfSSL_CTX_sess_accept_renegotiate, ctx, ctxN); + CHECKZERO_RET(wolfSSL_CTX_sess_connect_renegotiate, ctx, ctxN); + CHECKZERO_RET(wolfSSL_CTX_sess_hits, ctx, ctxN); + CHECKZERO_RET(wolfSSL_CTX_sess_cb_hits, ctx, ctxN); + CHECKZERO_RET(wolfSSL_CTX_sess_cache_full, ctx, ctxN); + CHECKZERO_RET(wolfSSL_CTX_sess_misses, ctx, ctxN); + CHECKZERO_RET(wolfSSL_CTX_sess_timeouts, ctx, ctxN); + wolfSSL_CTX_free(ctx); + ctx = NULL; +#endif /* OPENSSL_EXTRA && !NO_WOLFSSL_STUB */ +} + +static void test_wolfSSL_CTX_LoadCRL() +{ +#ifdef HAVE_CRL + WOLFSSL_CTX* ctx = NULL; + const char* badPath = "dummypath"; + const char* validPath = "./certs/crl"; + int derType = WOLFSSL_FILETYPE_ASN1; + int rawType = WOLFSSL_FILETYPE_RAW; + int pemType = WOLFSSL_FILETYPE_PEM; + int monitor = WOLFSSL_CRL_MONITOR; + + #define FAIL_T1(x, y, z, p, d) AssertIntEQ((int) x(y, z, p, d), \ + BAD_FUNC_ARG) + #define SUCC_T(x, y, z, p, d) AssertIntEQ((int) x(y, z, p, d), \ + WOLFSSL_SUCCESS) + + FAIL_T1(wolfSSL_CTX_LoadCRL, ctx, validPath, pemType, monitor); + + #ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + #elif !defined(NO_WOLFSSL_SERVER) + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + #else + return; + #endif + + SUCC_T (wolfSSL_CTX_LoadCRL, ctx, validPath, pemType, monitor); + SUCC_T (wolfSSL_CTX_LoadCRL, ctx, badPath, pemType, monitor); + SUCC_T (wolfSSL_CTX_LoadCRL, ctx, badPath, derType, monitor); + SUCC_T (wolfSSL_CTX_LoadCRL, ctx, badPath, rawType, monitor); + + wolfSSL_CTX_free(ctx); + ctx = NULL; +#endif +} + +static void test_SetTmpEC_DHE_Sz(void) +{ +#if defined(HAVE_ECC) && !defined(NO_WOLFSSL_CLIENT) + WOLFSSL_CTX *ctx; + WOLFSSL *ssl; + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpEC_DHE_Sz(ctx, 32)); + AssertNotNull(ssl = wolfSSL_new(ctx)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpEC_DHE_Sz(ssl, 32)); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif +} + +static void test_wolfSSL_dtls_set_mtu(void) +{ +#if (defined(WOLFSSL_DTLS_MTU) || defined(WOLFSSL_SCTP)) && \ + defined(WOLFSSL_DTLS) + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; + const char* testCertFile; + const char* testKeyFile; + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method())); +#ifndef NO_RSA + testCertFile = svrCertFile; + testKeyFile = svrKeyFile; +#elif defined(HAVE_ECC) + testCertFile = eccCertFile; + testKeyFile = eccKeyFile; +#endif + if (testCertFile != NULL && testKeyFile != NULL) { + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, + WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, + WOLFSSL_FILETYPE_PEM)); + } + AssertNotNull(ssl = wolfSSL_new(ctx)); + + AssertIntEQ(wolfSSL_CTX_dtls_set_mtu(NULL, 1488), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_dtls_set_mtu(NULL, 1488), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_dtls_set_mtu(ctx, 20000), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_dtls_set_mtu(ssl, 20000), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_get_error(ssl, WOLFSSL_FAILURE), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_CTX_dtls_set_mtu(ctx, 1488), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_dtls_set_mtu(ssl, 1488), WOLFSSL_SUCCESS); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + + printf(testingFmt, "wolfSSL_dtls_set_mtu()"); + printf(resultFmt, passed); +#endif +} + +#if !defined(NO_RSA) && !defined(NO_SHA) && !defined(NO_FILESYSTEM) && \ + !defined(NO_CERTS) +static int load_ca_into_cm(WOLFSSL_CERT_MANAGER* cm, char* certA) +{ + int ret; + + if ((ret = wolfSSL_CertManagerLoadCA(cm, certA, 0)) != WOLFSSL_SUCCESS) { + printf("loading cert %s failed\n", certA); + printf("Error: (%d): %s\n", ret, wolfSSL_ERR_reason_error_string(ret)); + return -1; + } + + return 0; +} + +static int verify_cert_with_cm(WOLFSSL_CERT_MANAGER* cm, char* certA) +{ + int ret; + if ((ret = wolfSSL_CertManagerVerify(cm, certA, WOLFSSL_FILETYPE_PEM)) + != WOLFSSL_SUCCESS) { + printf("could not verify the cert: %s\n", certA); + printf("Error: (%d): %s\n", ret, wolfSSL_ERR_reason_error_string(ret)); + return -1; + } else { + printf("successfully verified: %s\n", certA); + } + + return 0; +} +#define LOAD_ONE_CA(a, b, c, d) \ + do { \ + a = load_ca_into_cm(c, d); \ + if (a != 0) \ + return b; \ + else \ + b--; \ + } while(0) + +#define VERIFY_ONE_CERT(a, b, c, d) \ + do { \ + a = verify_cert_with_cm(c, d); \ + if (a != 0) \ + return b; \ + else \ + b--; \ + } while(0) + +static int test_chainG(WOLFSSL_CERT_MANAGER* cm) +{ + int ret; + int i = -1; + /* Chain G is a valid chain per RFC 5280 section 4.2.1.9 */ + char chainGArr[9][50] = {"certs/ca-cert.pem", + "certs/test-pathlen/chainG-ICA7-pathlen100.pem", + "certs/test-pathlen/chainG-ICA6-pathlen10.pem", + "certs/test-pathlen/chainG-ICA5-pathlen20.pem", + "certs/test-pathlen/chainG-ICA4-pathlen5.pem", + "certs/test-pathlen/chainG-ICA3-pathlen99.pem", + "certs/test-pathlen/chainG-ICA2-pathlen1.pem", + "certs/test-pathlen/chainG-ICA1-pathlen0.pem", + "certs/test-pathlen/chainG-entity.pem"}; + + LOAD_ONE_CA(ret, i, cm, chainGArr[0]); /* if failure, i = -1 here */ + LOAD_ONE_CA(ret, i, cm, chainGArr[1]); /* if failure, i = -2 here */ + LOAD_ONE_CA(ret, i, cm, chainGArr[2]); /* if failure, i = -3 here */ + LOAD_ONE_CA(ret, i, cm, chainGArr[3]); /* if failure, i = -4 here */ + LOAD_ONE_CA(ret, i, cm, chainGArr[4]); /* if failure, i = -5 here */ + LOAD_ONE_CA(ret, i, cm, chainGArr[5]); /* if failure, i = -6 here */ + LOAD_ONE_CA(ret, i, cm, chainGArr[6]); /* if failure, i = -7 here */ + LOAD_ONE_CA(ret, i, cm, chainGArr[7]); /* if failure, i = -8 here */ + VERIFY_ONE_CERT(ret, i, cm, chainGArr[1]); /* if failure, i = -9 here */ + VERIFY_ONE_CERT(ret, i, cm, chainGArr[2]); /* if failure, i = -10 here */ + VERIFY_ONE_CERT(ret, i, cm, chainGArr[3]); /* if failure, i = -11 here */ + VERIFY_ONE_CERT(ret, i, cm, chainGArr[4]); /* if failure, i = -12 here */ + VERIFY_ONE_CERT(ret, i, cm, chainGArr[5]); /* if failure, i = -13 here */ + VERIFY_ONE_CERT(ret, i, cm, chainGArr[6]); /* if failure, i = -14 here */ + VERIFY_ONE_CERT(ret, i, cm, chainGArr[7]); /* if failure, i = -15 here */ + VERIFY_ONE_CERT(ret, i, cm, chainGArr[8]); /* if failure, i = -16 here */ + +/* test validating the entity twice, should have no effect on pathLen since + * entity/leaf cert */ + VERIFY_ONE_CERT(ret, i, cm, chainGArr[8]); /* if failure, i = -17 here */ + + return ret; +} + +static int test_chainH(WOLFSSL_CERT_MANAGER* cm) +{ + int ret; + int i = -1; + /* Chain H is NOT a valid chain per RFC5280 section 4.2.1.9: + * ICA4-pathlen of 2 signing ICA3-pathlen of 2 (reduce max path len to 2) + * ICA3-pathlen of 2 signing ICA2-pathlen of 2 (reduce max path len to 1) + * ICA2-pathlen of 2 signing ICA1-pathlen of 0 (reduce max path len to 0) + * ICA1-pathlen of 0 signing entity (pathlen is already 0, ERROR) + * Test should successfully verify ICA4, ICA3, ICA2 and then fail on ICA1 + */ + char chainHArr[6][50] = {"certs/ca-cert.pem", + "certs/test-pathlen/chainH-ICA4-pathlen2.pem", + "certs/test-pathlen/chainH-ICA3-pathlen2.pem", + "certs/test-pathlen/chainH-ICA2-pathlen2.pem", + "certs/test-pathlen/chainH-ICA1-pathlen0.pem", + "certs/test-pathlen/chainH-entity.pem"}; + + LOAD_ONE_CA(ret, i, cm, chainHArr[0]); /* if failure, i = -1 here */ + LOAD_ONE_CA(ret, i, cm, chainHArr[1]); /* if failure, i = -2 here */ + LOAD_ONE_CA(ret, i, cm, chainHArr[2]); /* if failure, i = -3 here */ + LOAD_ONE_CA(ret, i, cm, chainHArr[3]); /* if failure, i = -4 here */ + LOAD_ONE_CA(ret, i, cm, chainHArr[4]); /* if failure, i = -5 here */ + VERIFY_ONE_CERT(ret, i, cm, chainHArr[1]); /* if failure, i = -6 here */ + VERIFY_ONE_CERT(ret, i, cm, chainHArr[2]); /* if failure, i = -7 here */ + VERIFY_ONE_CERT(ret, i, cm, chainHArr[3]); /* if failure, i = -8 here */ + VERIFY_ONE_CERT(ret, i, cm, chainHArr[4]); /* if failure, i = -9 here */ + VERIFY_ONE_CERT(ret, i, cm, chainHArr[5]); /* if failure, i = -10 here */ + + return ret; +} + +static int test_chainI(WOLFSSL_CERT_MANAGER* cm) +{ + int ret; + int i = -1; + /* Chain I is a valid chain per RFC5280 section 4.2.1.9: + * ICA3-pathlen of 2 signing ICA2 without a pathlen (reduce maxPathLen to 2) + * ICA2-no_pathlen signing ICA1-no_pathlen (reduce maxPathLen to 1) + * ICA1-no_pathlen signing entity (reduce maxPathLen to 0) + * Test should successfully verify ICA4, ICA3, ICA2 and then fail on ICA1 + */ + char chainIArr[5][50] = {"certs/ca-cert.pem", + "certs/test-pathlen/chainI-ICA3-pathlen2.pem", + "certs/test-pathlen/chainI-ICA2-no_pathlen.pem", + "certs/test-pathlen/chainI-ICA1-no_pathlen.pem", + "certs/test-pathlen/chainI-entity.pem"}; + + LOAD_ONE_CA(ret, i, cm, chainIArr[0]); /* if failure, i = -1 here */ + LOAD_ONE_CA(ret, i, cm, chainIArr[1]); /* if failure, i = -2 here */ + LOAD_ONE_CA(ret, i, cm, chainIArr[2]); /* if failure, i = -3 here */ + LOAD_ONE_CA(ret, i, cm, chainIArr[3]); /* if failure, i = -4 here */ + VERIFY_ONE_CERT(ret, i, cm, chainIArr[1]); /* if failure, i = -5 here */ + VERIFY_ONE_CERT(ret, i, cm, chainIArr[2]); /* if failure, i = -6 here */ + VERIFY_ONE_CERT(ret, i, cm, chainIArr[3]); /* if failure, i = -7 here */ + VERIFY_ONE_CERT(ret, i, cm, chainIArr[4]); /* if failure, i = -8 here */ + + return ret; +} + +static int test_chainJ(WOLFSSL_CERT_MANAGER* cm) +{ + int ret; + int i = -1; + /* Chain J is NOT a valid chain per RFC5280 section 4.2.1.9: + * ICA4-pathlen of 2 signing ICA3 without a pathlen (reduce maxPathLen to 2) + * ICA3-pathlen of 2 signing ICA2 without a pathlen (reduce maxPathLen to 1) + * ICA2-no_pathlen signing ICA1-no_pathlen (reduce maxPathLen to 0) + * ICA1-no_pathlen signing entity (ERROR, pathlen zero and non-leaf cert) + */ + char chainJArr[6][50] = {"certs/ca-cert.pem", + "certs/test-pathlen/chainJ-ICA4-pathlen2.pem", + "certs/test-pathlen/chainJ-ICA3-no_pathlen.pem", + "certs/test-pathlen/chainJ-ICA2-no_pathlen.pem", + "certs/test-pathlen/chainJ-ICA1-no_pathlen.pem", + "certs/test-pathlen/chainJ-entity.pem"}; + + LOAD_ONE_CA(ret, i, cm, chainJArr[0]); /* if failure, i = -1 here */ + LOAD_ONE_CA(ret, i, cm, chainJArr[1]); /* if failure, i = -2 here */ + LOAD_ONE_CA(ret, i, cm, chainJArr[2]); /* if failure, i = -3 here */ + LOAD_ONE_CA(ret, i, cm, chainJArr[3]); /* if failure, i = -4 here */ + LOAD_ONE_CA(ret, i, cm, chainJArr[4]); /* if failure, i = -5 here */ + VERIFY_ONE_CERT(ret, i, cm, chainJArr[1]); /* if failure, i = -6 here */ + VERIFY_ONE_CERT(ret, i, cm, chainJArr[2]); /* if failure, i = -7 here */ + VERIFY_ONE_CERT(ret, i, cm, chainJArr[3]); /* if failure, i = -8 here */ + VERIFY_ONE_CERT(ret, i, cm, chainJArr[4]); /* if failure, i = -9 here */ + VERIFY_ONE_CERT(ret, i, cm, chainJArr[5]); /* if failure, i = -10 here */ + + return ret; +} + +static int test_various_pathlen_chains(void) +{ + int ret; + WOLFSSL_CERT_MANAGER* cm; + + /* Test chain G (large chain with varying pathLens) */ + if ((cm = wolfSSL_CertManagerNew()) == NULL) { + printf("cert manager new failed\n"); + return -1; + } + + AssertIntEQ(test_chainG(cm), 0); + + ret = wolfSSL_CertManagerUnloadCAs(cm); + if (ret != WOLFSSL_SUCCESS) + return -1; + wolfSSL_CertManagerFree(cm); + /* end test chain G */ + + /* Test chain H (5 chain with same pathLens) */ + if ((cm = wolfSSL_CertManagerNew()) == NULL) { + printf("cert manager new failed\n"); + return -1; + } + AssertIntLT(test_chainH(cm), 0); + + wolfSSL_CertManagerUnloadCAs(cm); + wolfSSL_CertManagerFree(cm); + if ((cm = wolfSSL_CertManagerNew()) == NULL) { + printf("cert manager new failed\n"); + return -1; + } + + ret = wolfSSL_CertManagerUnloadCAs(cm); + if (ret != WOLFSSL_SUCCESS) + return -1; + wolfSSL_CertManagerFree(cm); + /* end test chain H */ + + /* Test chain I (only first ICA has pathLen set and it's set to 2, + * followed by 2 ICA's, should pass) */ + if ((cm = wolfSSL_CertManagerNew()) == NULL) { + printf("cert manager new failed\n"); + return -1; + } + AssertIntEQ(test_chainI(cm), 0); + + wolfSSL_CertManagerUnloadCAs(cm); + wolfSSL_CertManagerFree(cm); + if ((cm = wolfSSL_CertManagerNew()) == NULL) { + printf("cert manager new failed\n"); + return -1; + } + + ret = wolfSSL_CertManagerUnloadCAs(cm); + if (ret != WOLFSSL_SUCCESS) + return -1; + wolfSSL_CertManagerFree(cm); + + /* Test chain J (Again only first ICA has pathLen set and it's set to 2, + * this time followed by 3 ICA's, should fail */ + if ((cm = wolfSSL_CertManagerNew()) == NULL) { + printf("cert manager new failed\n"); + return -1; + } + AssertIntLT(test_chainJ(cm), 0); + + wolfSSL_CertManagerUnloadCAs(cm); + wolfSSL_CertManagerFree(cm); + if ((cm = wolfSSL_CertManagerNew()) == NULL) { + printf("cert manager new failed\n"); + return -1; + } + + ret = wolfSSL_CertManagerUnloadCAs(cm); + wolfSSL_CertManagerFree(cm); + + return ret; +} +#endif /* !NO_RSA && !NO_SHA && !NO_FILESYSTEM && !NO_CERTS */ /*----------------------------------------------------------------------------* | Main @@ -1153,24 +31920,563 @@ static void test_wolfSSL_UseSupportedCurve(void) void ApiTest(void) { - printf(" Begin API Tests\n"); - test_wolfSSL_Init(); + printf("\n-----------------Porting tests------------------\n"); + AssertTrue(test_fileAccess()); + printf(" Begin API Tests\n"); + AssertIntEQ(test_wolfSSL_Init(), WOLFSSL_SUCCESS); + /* wolfcrypt initialization tests */ test_wolfSSL_Method_Allocators(); +#ifndef NO_WOLFSSL_SERVER test_wolfSSL_CTX_new(wolfSSLv23_server_method()); +#endif +#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ +(!defined(NO_RSA) || defined(HAVE_ECC)) + test_for_double_Free(); +#endif test_wolfSSL_CTX_use_certificate_file(); + AssertIntEQ(test_wolfSSL_CTX_use_certificate_buffer(), WOLFSSL_SUCCESS); test_wolfSSL_CTX_use_PrivateKey_file(); test_wolfSSL_CTX_load_verify_locations(); + test_wolfSSL_CertManagerLoadCABuffer(); + test_wolfSSL_CertManagerGetCerts(); + test_wolfSSL_CertManagerSetVerify(); + test_wolfSSL_CertManagerCRL(); + test_wolfSSL_CTX_load_verify_locations_ex(); + test_wolfSSL_CTX_load_verify_buffer_ex(); + test_wolfSSL_CTX_load_verify_chain_buffer_format(); + test_wolfSSL_CTX_use_certificate_chain_file_format(); + test_wolfSSL_CTX_trust_peer_cert(); + test_wolfSSL_CTX_SetTmpDH_file(); + test_wolfSSL_CTX_SetTmpDH_buffer(); + test_wolfSSL_CTX_SetMinMaxDhKey_Sz(); + test_wolfSSL_CTX_der_load_verify_locations(); + test_wolfSSL_CTX_enable_disable(); test_server_wolfSSL_new(); test_client_wolfSSL_new(); + test_wolfSSL_SetTmpDH_file(); + test_wolfSSL_SetTmpDH_buffer(); + test_wolfSSL_SetMinMaxDhKey_Sz(); + test_SetTmpEC_DHE_Sz(); + test_wolfSSL_dtls_set_mtu(); +#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ + defined(HAVE_IO_TESTS_DEPENDENCIES) test_wolfSSL_read_write(); +#if defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) + test_wolfSSL_reuse_WOLFSSLobj(); +#endif + test_wolfSSL_dtls_export(); +#endif + AssertIntEQ(test_wolfSSL_SetMinVersion(), WOLFSSL_SUCCESS); + AssertIntEQ(test_wolfSSL_CTX_SetMinVersion(), WOLFSSL_SUCCESS); /* TLS extensions tests */ +#ifdef HAVE_IO_TESTS_DEPENDENCIES test_wolfSSL_UseSNI(); +#endif + test_wolfSSL_UseTrustedCA(); test_wolfSSL_UseMaxFragment(); test_wolfSSL_UseTruncatedHMAC(); test_wolfSSL_UseSupportedCurve(); + test_wolfSSL_UseALPN(); + test_wolfSSL_DisableExtendedMasterSecret(); + test_wolfSSL_wolfSSL_UseSecureRenegotiation(); + + /* X509 tests */ + test_wolfSSL_X509_NAME_get_entry(); + test_wolfSSL_PKCS12(); + test_wolfSSL_no_password_cb(); + test_wolfSSL_PKCS8(); + test_wolfSSL_PKCS8_ED25519(); + test_wolfSSL_PKCS8_ED448(); + test_wolfSSL_PKCS5(); + test_wolfSSL_URI(); + test_wolfSSL_TBS(); + test_wolfSSL_X509_verify(); + + test_wc_PemToDer(); + test_wc_AllocDer(); + test_wc_CertPemToDer(); + test_wc_PubKeyPemToDer(); + test_wc_PemPubKeyToDer(); + + /*OCSP Stapling. */ + AssertIntEQ(test_wolfSSL_UseOCSPStapling(), WOLFSSL_SUCCESS); + AssertIntEQ(test_wolfSSL_UseOCSPStaplingV2(), WOLFSSL_SUCCESS); + + /* Multicast */ + test_wolfSSL_mcast(); + + /* compatibility tests */ + test_wolfSSL_X509_NAME(); + test_wolfSSL_X509_INFO(); + test_wolfSSL_X509_subject_name_hash(); + test_wolfSSL_DES(); + test_wolfSSL_certs(); + test_wolfSSL_ASN1_TIME_print(); + test_wolfSSL_ASN1_UTCTIME_print(); + test_wolfSSL_ASN1_GENERALIZEDTIME_free(); + test_wolfSSL_private_keys(); + test_wolfSSL_PEM_PrivateKey(); + test_wolfSSL_PEM_bio_RSAKey(); + test_wolfSSL_PEM_bio_DSAKey(); + test_wolfSSL_PEM_bio_ECKey(); + test_wolfSSL_PEM_RSAPrivateKey(); + test_wolfSSL_PEM_PUBKEY(); + test_DSA_do_sign_verify(); + test_wolfSSL_tmp_dh(); + test_wolfSSL_ctrl(); + test_wolfSSL_EVP_MD_size(); + test_wolfSSL_EVP_Digest(); + test_wolfSSL_EVP_PKEY_new_mac_key(); + test_wolfSSL_EVP_MD_hmac_signing(); + test_wolfSSL_EVP_MD_rsa_signing(); + test_wolfSSL_EVP_MD_ecc_signing(); + test_wolfSSL_CTX_add_extra_chain_cert(); +#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) + test_wolfSSL_ERR_peek_last_error_line(); +#endif + test_wolfSSL_ERR_print_errors_cb(); + test_wolfSSL_set_options(); + test_wolfSSL_sk_SSL_CIPHER(); + test_wolfSSL_X509_STORE_CTX(); + test_wolfSSL_X509_STORE_CTX_get0_current_issuer(); + test_wolfSSL_msgCb(); + test_wolfSSL_either_side(); + test_wolfSSL_DTLS_either_side(); + test_generate_cookie(); + 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_get0_param(); + test_wolfSSL_X509_VERIFY_PARAM_set1_host(); + test_wolfSSL_X509_STORE_CTX_get0_store(); + test_wolfSSL_X509_STORE(); + test_wolfSSL_X509_STORE_load_locations(); + test_wolfSSL_BN(); + test_wolfSSL_PEM_read_bio(); + test_wolfSSL_BIO(); + test_wolfSSL_ASN1_STRING(); + test_wolfSSL_ASN1_BIT_STRING(); + test_wolfSSL_X509(); + test_wolfSSL_X509_VERIFY_PARAM(); + test_wolfSSL_X509_sign(); + test_wolfSSL_X509_get0_tbs_sigalg(); + test_wolfSSL_X509_ALGOR_get0(); + test_wolfSSL_X509_get_X509_PUBKEY(); + test_wolfSSL_X509_PUBKEY(); + test_wolfSSL_RAND(); + test_wolfSSL_BUF(); + test_wolfSSL_set_tlsext_status_type(); + test_wolfSSL_ASN1_TIME_adj(); + test_wolfSSL_X509_cmp_time(); + test_wolfSSL_X509_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(); + test_wolfSSL_pseudo_rand(); + test_wolfSSL_PKCS8_Compat(); + test_wolfSSL_PKCS8_d2i(); + test_wolfSSL_ERR_put_error(); + test_wolfSSL_ERR_print_errors(); + test_wolfSSL_HMAC(); + test_wolfSSL_OBJ(); + test_wolfSSL_i2a_ASN1_OBJECT(); + test_wolfSSL_OBJ_cmp(); + test_wolfSSL_OBJ_txt2nid(); + test_wolfSSL_OBJ_txt2obj(); + test_wolfSSL_X509_NAME_ENTRY(); + test_wolfSSL_X509_set_name(); + test_wolfSSL_X509_set_notAfter(); + test_wolfSSL_X509_set_notBefore(); + test_wolfSSL_X509_set_version(); + test_wolfSSL_BIO_gets(); + test_wolfSSL_BIO_puts(); + test_wolfSSL_BIO_should_retry(); + test_wolfSSL_d2i_PUBKEY(); + test_wolfSSL_BIO_write(); + test_wolfSSL_BIO_printf(); + test_wolfSSL_BIO_f_md(); + test_wolfSSL_SESSION(); + test_wolfSSL_DES_ecb_encrypt(); + test_wolfSSL_sk_GENERAL_NAME(); + test_wolfSSL_MD4(); + test_wolfSSL_RSA(); + test_wolfSSL_RSA_DER(); + test_wolfSSL_RSA_get0_key(); + test_wolfSSL_RSA_meth(); + test_wolfSSL_verify_depth(); + test_wolfSSL_HMAC_CTX(); + test_wolfSSL_msg_callback(); + test_wolfSSL_SHA(); + test_wolfSSL_DH_1536_prime(); + test_wolfSSL_PEM_write_DHparams(); + test_wolfSSL_AES_ecb_encrypt(); + test_wolfSSL_SHA256(); + test_wolfSSL_X509_get_serialNumber(); + test_wolfSSL_X509_CRL(); + test_wolfSSL_PEM_read_X509(); + test_wolfSSL_PEM_read(); + test_wolfSSL_PEM_X509_INFO_read_bio(); + test_wolfSSL_PEM_read_bio_ECPKParameters(); + test_wolfSSL_X509_NAME_ENTRY_get_object(); + test_wolfSSL_OpenSSL_add_all_algorithms(); + test_wolfSSL_ASN1_STRING_print_ex(); + test_wolfSSL_ASN1_TIME_to_generalizedtime(); + test_wolfSSL_ASN1_INTEGER_set(); + test_wolfSSL_IMPLEMENT_ASN1_FUNCTIONS(); + test_wolfSSL_i2c_ASN1_INTEGER(); + test_wolfSSL_X509_check_ca(); + test_wolfSSL_DC_cert(); + test_wolfSSL_DES_ncbc(); + test_wolfSSL_AES_cbc_encrypt(); + test_wolfssl_EVP_aes_gcm(); + test_wolfSSL_PKEY_up_ref(); + test_wolfSSL_i2d_PrivateKey(); + test_wolfSSL_OCSP_get0_info(); + test_wolfSSL_EVP_PKEY_derive(); + test_wolfSSL_RSA_padding_add_PKCS1_PSS(); + +#if defined(WOLFSSL_QT) + printf("\n----------------Qt Unit Tests-------------------\n"); + test_wolfSSL_X509_PUBKEY_get(); + test_wolfSSL_sk_CIPHER_description(); + test_wolfSSL_get_ciphers_compat(); + test_wolfSSL_d2i_DHparams(); + test_wolfSSL_i2d_DHparams(); + test_wolfSSL_ASN1_STRING_to_UTF8(); + test_wolfSSL_EC_KEY_dup(); + test_wolfSSL_EVP_PKEY_set1_get1_DSA(); + test_wolfSSL_EVP_PKEY_set1_get1_EC_KEY(); + test_wolfSSL_EVP_PKEY_set1_get1_DH(); + test_wolfSSL_CTX_ctrl(); + test_wolfSSL_DH_check(); + test_wolfSSL_EVP_PKEY_assign(); + test_wolfSSL_OBJ_ln(); + test_wolfSSL_OBJ_sn(); + + printf("\n-------------End Of Qt Unit Tests---------------\n"); + +#endif /* WOLFSSL_QT */ + +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)) && !defined(NO_RSA) + AssertIntEQ(test_wolfSSL_CTX_use_certificate_ASN1(), WOLFSSL_SUCCESS); + test_wolfSSL_d2i_PrivateKeys_bio(); +#endif /* OPENSSL_ALL || WOLFSSL_ASIO */ + + test_wolfSSL_X509_CA_num(); + test_wolfSSL_X509_get_version(); + test_wolfSSL_X509_print(); + test_wolfSSL_BIO_get_len(); + test_wolfSSL_RSA_verify(); + test_wolfSSL_X509V3_EXT_get(); + test_wolfSSL_X509V3_EXT_d2i(); + test_wolfSSL_X509_get_ext(); + test_wolfSSL_X509_get_ext_by_NID(); + test_wolfSSL_X509_get_ext_count(); + test_wolfSSL_X509_EXTENSION_new(); + test_wolfSSL_X509_EXTENSION_get_object(); + test_wolfSSL_X509_EXTENSION_get_data(); + test_wolfSSL_X509_EXTENSION_get_critical(); + test_wolfSSL_X509V3_EXT_print(); + test_wolfSSL_X509_cmp(); + test_wolfSSL_RSA_print(); + test_wolfSSL_ASN1_STRING_print(); + test_openssl_generate_key_and_cert(); + + test_wolfSSL_EC_get_builtin_curves(); + + /* test the no op functions for compatibility */ + test_no_op_functions(); + + /* OpenSSL EVP_PKEY API tests */ + test_EVP_PKEY_rsa(); + test_wolfSSL_EVP_PKEY_encrypt(); + test_wolfSSL_EVP_PKEY_sign(); + test_EVP_PKEY_ec(); + test_EVP_PKEY_cmp(); + /* OpenSSL error API tests */ + test_ERR_load_crypto_strings(); + /* OpenSSL sk_X509 API test */ + test_sk_X509(); + /* OpenSSL X509 API test */ + test_X509_get_signature_nid(); + /* OpenSSL X509 REQ API test */ + test_X509_REQ(); + /* OpenSSL PKCS7 API test */ + test_wolfssl_PKCS7(); + test_wolfSSL_PKCS7_SIGNED_new(); + test_wolfSSL_PEM_write_bio_PKCS7(); + + /* wolfCrypt ASN tests */ + test_wc_GetPkcs8TraditionalOffset(); + test_wc_SetSubjectRaw(); + test_wc_GetSubjectRaw(); + test_wc_SetIssuerRaw(); + test_wc_SetIssueBuffer(); + test_wc_SetSubjectKeyId(); + test_wc_SetSubject(); + test_CheckCertSignature(); + + /* 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 */ + +#ifdef HAVE_PK_CALLBACKS + /* public key callback tests */ + test_DhCallbacks(); +#endif + + /*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_InitBlake2b()); + AssertFalse(test_wc_InitRipeMd()); + AssertFalse(test_wc_RipeMdUpdate()); + AssertFalse(test_wc_RipeMdFinal()); + + AssertIntEQ(test_wc_InitSha3(), 0); + AssertIntEQ(testing_wc_Sha3_Update(), 0); + AssertIntEQ(test_wc_Sha3_224_Final(), 0); + AssertIntEQ(test_wc_Sha3_256_Final(), 0); + AssertIntEQ(test_wc_Sha3_384_Final(), 0); + AssertIntEQ(test_wc_Sha3_512_Final(), 0); + AssertIntEQ(test_wc_Sha3_224_Copy(), 0); + AssertIntEQ(test_wc_Sha3_256_Copy(), 0); + AssertIntEQ(test_wc_Sha3_384_Copy(), 0); + AssertIntEQ(test_wc_Sha3_512_Copy(), 0); + AssertIntEQ(test_wc_InitShake256(), 0); + AssertIntEQ(testing_wc_Shake256_Update(), 0); + AssertIntEQ(test_wc_Shake256_Final(), 0); + + 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_HashInit(), 0); + + AssertIntEQ(test_wc_InitCmac(), 0); + AssertIntEQ(test_wc_CmacUpdate(), 0); + AssertIntEQ(test_wc_CmacFinal(), 0); + AssertIntEQ(test_wc_AesCmacGenerate(), 0); + + 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_Poly1305SetKey(), 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_RsaDecryptBoundsCheck(), 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); + AssertIntEQ(test_wc_DsaKeyToPublicDer(), 0); + AssertIntEQ(test_wc_DsaImportParamsRaw(), 0); + AssertIntEQ(test_wc_DsaImportParamsRawCheck(), 0); + AssertIntEQ(test_wc_DsaExportParamsRaw(), 0); + AssertIntEQ(test_wc_DsaExportKeyRaw(), 0); + AssertIntEQ(test_wc_SignatureGetSize_ecc(), 0); + AssertIntEQ(test_wc_SignatureGetSize_rsa(), 0); + wolfCrypt_Cleanup(); + +#ifdef OPENSSL_EXTRA + /*wolfSSL_EVP_get_cipherbynid test*/ + test_wolfSSL_EVP_get_cipherbynid(); + test_wolfSSL_EVP_CIPHER_CTX(); + test_wolfSSL_EC(); + test_wolfSSL_ECDSA_SIG(); + test_ECDSA_size_sign(); +#endif +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && \ + !defined(HAVE_SELFTEST) && \ + !(defined(HAVE_FIPS) || defined(HAVE_FIPS_VERSION)) + test_wc_ecc_get_curve_id_from_dp_params(); +#endif + +#ifdef HAVE_HASHDRBG + #ifdef TEST_RESEED_INTERVAL + AssertIntEQ(test_wc_RNG_GenerateBlock_Reseed(), 0); + #endif + AssertIntEQ(test_wc_RNG_GenerateBlock(), 0); +#endif + + AssertIntEQ(test_wc_ed25519_make_key(), 0); + AssertIntEQ(test_wc_ed25519_init(), 0); + AssertIntEQ(test_wc_ed25519_sign_msg(), 0); + AssertIntEQ(test_wc_ed25519_import_public(), 0); + AssertIntEQ(test_wc_ed25519_import_private_key(), 0); + AssertIntEQ(test_wc_ed25519_export(), 0); + AssertIntEQ(test_wc_ed25519_size(), 0); + AssertIntEQ(test_wc_ed25519_exportKey(), 0); + AssertIntEQ(test_wc_Ed25519PublicKeyToDer(), 0); + AssertIntEQ(test_wc_curve25519_init(), 0); + AssertIntEQ(test_wc_curve25519_size (), 0); + AssertIntEQ(test_wc_ed448_make_key(), 0); + AssertIntEQ(test_wc_ed448_init(), 0); + AssertIntEQ(test_wc_ed448_sign_msg(), 0); + AssertIntEQ(test_wc_ed448_import_public(), 0); + AssertIntEQ(test_wc_ed448_import_private_key(), 0); + AssertIntEQ(test_wc_ed448_export(), 0); + AssertIntEQ(test_wc_ed448_size(), 0); + AssertIntEQ(test_wc_ed448_exportKey(), 0); + AssertIntEQ(test_wc_Ed448PublicKeyToDer(), 0); + AssertIntEQ(test_wc_curve448_init(), 0); + AssertIntEQ(test_wc_curve448_size (), 0); + AssertIntEQ(test_wc_ecc_make_key(), 0); + AssertIntEQ(test_wc_ecc_init(), 0); + AssertIntEQ(test_wc_ecc_check_key(), 0); + AssertIntEQ(test_wc_ecc_get_generator(), 0); + AssertIntEQ(test_wc_ecc_size(), 0); + test_wc_ecc_params(); + AssertIntEQ(test_wc_ecc_signVerify_hash(), 0); + AssertIntEQ(test_wc_ecc_shared_secret(), 0); + AssertIntEQ(test_wc_ecc_export_x963(), 0); + AssertIntEQ(test_wc_ecc_export_x963_ex(), 0); + AssertIntEQ(test_wc_ecc_import_x963(), 0); + AssertIntEQ(ecc_import_private_key(), 0); + AssertIntEQ(test_wc_ecc_export_private_only(), 0); + AssertIntEQ(test_wc_ecc_rs_to_sig(), 0); + AssertIntEQ(test_wc_ecc_import_raw(), 0); + AssertIntEQ(test_wc_ecc_sig_size(), 0); + AssertIntEQ(test_wc_ecc_ctx_new(), 0); + AssertIntEQ(test_wc_ecc_ctx_reset(), 0); + AssertIntEQ(test_wc_ecc_ctx_set_peer_salt(), 0); + AssertIntEQ(test_wc_ecc_ctx_set_info(), 0); + AssertIntEQ(test_wc_ecc_encryptDecrypt(), 0); + AssertIntEQ(test_wc_ecc_del_point(), 0); + AssertIntEQ(test_wc_ecc_pointFns(), 0); + AssertIntEQ(test_wc_ecc_shared_secret_ssh(), 0); + AssertIntEQ(test_wc_ecc_verify_hash_ex(), 0); + AssertIntEQ(test_wc_ecc_mulmod(), 0); + AssertIntEQ(test_wc_ecc_is_valid_idx(), 0); + + test_wc_PKCS7_New(); + test_wc_PKCS7_Init(); + test_wc_PKCS7_InitWithCert(); + test_wc_PKCS7_EncodeData(); + test_wc_PKCS7_EncodeSignedData(); + test_wc_PKCS7_EncodeSignedData_ex(); + test_wc_PKCS7_VerifySignedData(); + test_wc_PKCS7_EncodeDecodeEnvelopedData(); + test_wc_PKCS7_EncodeEncryptedData(); + test_wc_PKCS7_Degenerate(); + test_wc_PKCS7_BER(); + test_PKCS7_signed_enveloped(); + + test_wc_i2d_PKCS12(); + + test_wolfSSL_CTX_LoadCRL(); + + AssertIntEQ(test_ForceZero(), 0); + + AssertIntEQ(test_wolfSSL_Cleanup(), WOLFSSL_SUCCESS); + +#if !defined(NO_RSA) && !defined(NO_SHA) && !defined(NO_FILESYSTEM) && \ + !defined(NO_CERTS) + AssertIntEQ(test_various_pathlen_chains(), WOLFSSL_SUCCESS); +#endif + + /* If at some point a stub get implemented this test should fail indicating + * a need to implement a new test case + */ + test_stubs_are_stubs(); +#if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) \ + && (defined(NO_MAIN_DRIVER) || defined(HAVE_STACK_SIZE)) + wc_ecc_fp_free(); /* free per thread cache */ +#endif + wolfSSL_Cleanup(); - test_wolfSSL_Cleanup(); printf(" End API Tests\n"); + } diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/hash.c b/FreeRTOS-Plus/Source/WolfSSL/tests/hash.c index e28a71a03..be9966ac5 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/tests/hash.c +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/hash.c @@ -1,8 +1,8 @@ /* hash.c has unit tests * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -39,7 +40,7 @@ typedef struct testVector { const char* input; - const char* output; + const char* output; size_t inLen; size_t outLen; } testVector; @@ -47,12 +48,14 @@ typedef struct testVector { int md4_test(void); int md5_test(void); int sha_test(void); +int sha224_test(void); int sha256_test(void); int sha512_test(void); int sha384_test(void); int ripemd_test(void); int hmac_md5_test(void); int hmac_sha_test(void); +int hmac_sha224_test(void); int hmac_sha256_test(void); int hmac_sha384_test(void); @@ -65,7 +68,7 @@ int HashTest(void) #ifndef NO_MD4 if ( (ret = md4_test()) ) { printf( " MD4 test failed!\n"); - return ret; + return ret; } else printf( " MD4 test passed!\n"); #endif @@ -73,23 +76,31 @@ int HashTest(void) #ifndef NO_MD5 if ( (ret = md5_test()) ) { printf( " MD5 test failed!\n"); - return ret; + return ret; } else printf( " MD5 test passed!\n"); #endif - + #ifndef NO_SHA if ( (ret = sha_test()) ) { printf( " SHA test failed!\n"); - return ret; + return ret; } else printf( " SHA test passed!\n"); #endif - + +#ifdef WOLFSSL_SHA224 + if ( (ret = sha224_test()) ) { + printf( " SHA-224 test failed!\n"); + return ret; + } else + printf( " SHA-224 test passed!\n"); +#endif + #ifndef NO_SHA256 if ( (ret = sha256_test()) ) { printf( " SHA-256 test failed!\n"); - return ret; + return ret; } else printf( " SHA-256 test passed!\n"); #endif @@ -97,7 +108,7 @@ int HashTest(void) #ifdef WOLFSSL_SHA512 if ( (ret = sha512_test()) ) { printf( " SHA-512 test failed!\n"); - return ret; + return ret; } else printf( " SHA-512 test passed!\n"); #endif @@ -105,7 +116,7 @@ int HashTest(void) #ifdef WOLFSSL_SHA384 if ( (ret = sha384_test()) ) { printf( " SHA-384 test failed!\n"); - return ret; + return ret; } else printf( " SHA-384 test passed!\n"); #endif @@ -113,7 +124,7 @@ int HashTest(void) #ifdef WOLFSSL_RIPEMD if ( (ret = ripemd_test()) ) { printf( " RIPEMD test failed!\n"); - return ret; + return ret; } else printf( " RIPEMD test passed!\n"); #endif @@ -122,27 +133,34 @@ int HashTest(void) #ifndef NO_MD5 if ( (ret = hmac_md5_test()) ) { printf( " HMAC-MD5 test failed!\n"); - return ret; + return ret; } else printf( " HMAC-MD5 test passed!\n"); #endif #ifndef NO_SHA - if ( (ret = hmac_sha_test()) ) + if ( (ret = hmac_sha_test()) ) printf( " HMAC-SHA test failed!\n"); else printf( " HMAC-SHA test passed!\n"); #endif + #ifdef WOLFSSL_SHA224 + if ( (ret = hmac_sha224_test()) ) + printf( " HMAC-SHA224 test failed!\n"); + else + printf( " HMAC-SHA224 test passed!\n"); + #endif + #ifndef NO_SHA256 - if ( (ret = hmac_sha256_test()) ) + if ( (ret = hmac_sha256_test()) ) printf( " HMAC-SHA256 test failed!\n"); else printf( " HMAC-SHA256 test passed!\n"); #endif #ifdef WOLFSSL_SHA384 - if ( (ret = hmac_sha384_test()) ) + if ( (ret = hmac_sha384_test()) ) printf( " HMAC-SHA384 test failed!\n"); else printf( " HMAC-SHA384 test passed!\n"); @@ -150,7 +168,7 @@ int HashTest(void) #endif printf(" End HASH Tests\n"); - + return 0; } @@ -166,48 +184,48 @@ int md4_test(void) int times = sizeof(test_md4) / sizeof(testVector), i; a.input = ""; - a.output = "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89" + a.output = "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89" "\xc0"; - a.inLen = strlen(a.input); - a.outLen = strlen(a.output); + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); b.input = "a"; - b.output = "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb" + b.output = "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb" "\x24"; - b.inLen = strlen(b.input); - b.outLen = strlen(b.output); + b.inLen = XSTRLEN(b.input); + b.outLen = XSTRLEN(b.output); c.input = "abc"; - c.output = "\xa4\x48\x01\x7a\xaf\x21\xd8\x52\x5f\xc1\x0a\xe8\x7a\xa6\x72" + c.output = "\xa4\x48\x01\x7a\xaf\x21\xd8\x52\x5f\xc1\x0a\xe8\x7a\xa6\x72" "\x9d"; - c.inLen = strlen(c.input); - c.outLen = strlen(c.output); + c.inLen = XSTRLEN(c.input); + c.outLen = XSTRLEN(c.output); d.input = "message digest"; - d.output = "\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01" + d.output = "\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01" "\x4b"; - d.inLen = strlen(d.input); - d.outLen = strlen(d.output); + d.inLen = XSTRLEN(d.input); + d.outLen = XSTRLEN(d.output); e.input = "abcdefghijklmnopqrstuvwxyz"; - e.output = "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd\xee\xa8\xed\x63\xdf\x41\x2d" + e.output = "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd\xee\xa8\xed\x63\xdf\x41\x2d" "\xa9"; - e.inLen = strlen(e.input); - e.outLen = strlen(e.output); + e.inLen = XSTRLEN(e.input); + e.outLen = XSTRLEN(e.output); f.input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345" "6789"; - f.output = "\x04\x3f\x85\x82\xf2\x41\xdb\x35\x1c\xe6\x27\xe1\x53\xe7\xf0" + f.output = "\x04\x3f\x85\x82\xf2\x41\xdb\x35\x1c\xe6\x27\xe1\x53\xe7\xf0" "\xe4"; - f.inLen = strlen(f.input); - f.outLen = strlen(f.output); + f.inLen = XSTRLEN(f.input); + f.outLen = XSTRLEN(f.output); g.input = "1234567890123456789012345678901234567890123456789012345678" "9012345678901234567890"; - g.output = "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19\x9c\x3e\x7b\x16\x4f\xcc\x05" + g.output = "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19\x9c\x3e\x7b\x16\x4f\xcc\x05" "\x36"; - g.inLen = strlen(g.input); - g.outLen = strlen(g.output); + g.inLen = XSTRLEN(g.input); + g.outLen = XSTRLEN(g.output); test_md4[0] = a; test_md4[1] = b; @@ -223,7 +241,7 @@ int md4_test(void) wc_Md4Update(&md4, (byte*)test_md4[i].input, (word32)test_md4[i].inLen); wc_Md4Final(&md4, hash); - if (memcmp(hash, test_md4[i].output, MD4_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_md4[i].output, MD4_DIGEST_SIZE) != 0) return -205 - i; } @@ -236,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]; @@ -246,34 +265,34 @@ int md5_test(void) a.input = "abc"; a.output = "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f" "\x72"; - a.inLen = strlen(a.input); - a.outLen = strlen(a.output); + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); b.input = "message digest"; b.output = "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61" "\xd0"; - b.inLen = strlen(b.input); - b.outLen = strlen(b.output); + b.inLen = XSTRLEN(b.input); + b.outLen = XSTRLEN(b.output); c.input = "abcdefghijklmnopqrstuvwxyz"; c.output = "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1" "\x3b"; - c.inLen = strlen(c.input); - c.outLen = strlen(c.output); + c.inLen = XSTRLEN(c.input); + c.outLen = XSTRLEN(c.output); d.input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345" "6789"; d.output = "\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d" "\x9f"; - d.inLen = strlen(d.input); - d.outLen = strlen(d.output); + d.inLen = XSTRLEN(d.input); + d.outLen = XSTRLEN(d.output); e.input = "1234567890123456789012345678901234567890123456789012345678" "9012345678901234567890"; e.output = "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6" "\x7a"; - e.inLen = strlen(e.input); - e.outLen = strlen(e.output); + e.inLen = XSTRLEN(e.input); + e.outLen = XSTRLEN(e.output); test_md5[0] = a; test_md5[1] = b; @@ -281,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 (memcmp(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; } @@ -299,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]; @@ -310,29 +340,29 @@ int sha_test(void) 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 = strlen(a.input); - a.outLen = strlen(a.output); + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); 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.inLen = strlen(b.input); - b.outLen = strlen(b.output); + b.inLen = XSTRLEN(b.input); + b.outLen = XSTRLEN(b.output); 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.inLen = strlen(c.input); - c.outLen = strlen(c.output); + c.inLen = XSTRLEN(c.input); + c.outLen = XSTRLEN(c.output); d.input = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaa"; d.output = "\xAD\x5B\x3F\xDB\xCB\x52\x67\x78\xC2\x83\x9D\x2F\x15\x1E\xA7" "\x53\x99\x5E\x26\xA0"; - d.inLen = strlen(d.input); - d.outLen = strlen(d.output); + d.inLen = XSTRLEN(d.input); + d.outLen = XSTRLEN(d.output); test_sha[0] = a; test_sha[1] = b; @@ -347,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 (memcmp(hash, test_sha[i].output, SHA_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_sha[i].output, WC_SHA_DIGEST_SIZE) != 0) return -10 - i; } @@ -355,11 +385,57 @@ int sha_test(void) } #endif /* NO_SHA */ +#ifdef WOLFSSL_SHA224 +int sha224_test(void) +{ + wc_Sha224 sha; + byte hash[WC_SHA224_DIGEST_SIZE]; + + testVector a, b; + testVector test_sha[2]; + int ret; + 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.inLen = XSTRLEN(a.input); + 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 = WC_SHA224_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + + ret = wc_InitSha224(&sha); + if (ret != 0) + return -4005; + + for (i = 0; i < times; ++i) { + ret = wc_Sha224Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + if (ret != 0) + return ret; + ret = wc_Sha224Final(&sha, hash); + if (ret != 0) + return ret; + + if (XMEMCMP(hash, test_sha[i].output, WC_SHA224_DIGEST_SIZE) != 0) + return -10 - i; + } + + return 0; +} +#endif + #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]; @@ -370,15 +446,15 @@ int sha256_test(void) 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 = strlen(a.input); - a.outLen = strlen(a.output); + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; b.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 = strlen(b.input); - b.outLen = strlen(b.output); + b.inLen = XSTRLEN(b.input); + b.outLen = XSTRLEN(b.output); test_sha[0] = a; test_sha[1] = b; @@ -396,7 +472,7 @@ int sha256_test(void) if (ret != 0) return ret; - if (memcmp(hash, test_sha[i].output, SHA256_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_sha[i].output, WC_SHA256_DIGEST_SIZE) != 0) return -10 - i; } @@ -407,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]; @@ -421,8 +497,8 @@ int sha512_test(void) "\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 = strlen(a.input); - a.outLen = strlen(a.output); + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); b.input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; @@ -430,9 +506,9 @@ int sha512_test(void) "\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 = strlen(b.input); - b.outLen = strlen(b.output); + "\x87\x4b\xe9\x09"; + b.inLen = XSTRLEN(b.input); + b.outLen = XSTRLEN(b.output); test_sha[0] = a; test_sha[1] = b; @@ -450,7 +526,7 @@ int sha512_test(void) if (ret != 0) return ret; - if (memcmp(hash, test_sha[i].output, SHA512_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_sha[i].output, WC_SHA512_DIGEST_SIZE) != 0) return -10 - i; } @@ -459,10 +535,10 @@ int sha512_test(void) #endif #ifdef WOLFSSL_SHA384 -int sha384_test() +int sha384_test(void) { - Sha384 sha; - byte hash[SHA384_DIGEST_SIZE]; + wc_Sha384 sha; + byte hash[WC_SHA384_DIGEST_SIZE]; testVector a, b; testVector test_sha[2]; @@ -474,8 +550,8 @@ int sha384_test() "\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 = strlen(a.input); - a.outLen = strlen(a.output); + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); b.input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; @@ -483,8 +559,8 @@ int sha384_test() "\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 = strlen(b.input); - b.outLen = strlen(b.output); + b.inLen = XSTRLEN(b.input); + b.outLen = XSTRLEN(b.output); test_sha[0] = a; test_sha[1] = b; @@ -502,7 +578,7 @@ int sha384_test() if (ret != 0) return ret; - if (memcmp(hash, test_sha[i].output, SHA384_DIGEST_SIZE) != 0) + if (XMEMCMP(hash, test_sha[i].output, WC_SHA384_DIGEST_SIZE) != 0) return -10 - i; } @@ -514,6 +590,7 @@ int sha384_test() int ripemd_test(void) { RipeMd ripemd; + int ret; byte hash[RIPEMD_DIGEST_SIZE]; testVector a, b, c, d; @@ -523,41 +600,51 @@ int ripemd_test(void) 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 = strlen(a.input); - a.outLen = strlen(a.output); + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); b.input = "message digest"; b.output = "\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8\x81\xb1\x23\xa8" "\x5f\xfa\x21\x59\x5f\x36"; - b.inLen = strlen(b.input); - b.outLen = strlen(b.output); + b.inLen = XSTRLEN(b.input); + b.outLen = XSTRLEN(b.output); - c.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + c.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; c.output = "\x12\xa0\x53\x38\x4a\x9c\x0c\x88\xe4\x05\xa0\x6c\x27\xdc" "\xf4\x9a\xda\x62\xeb\x2b"; - c.inLen = strlen(c.input); - c.outLen = strlen(c.output); + c.inLen = XSTRLEN(c.input); + c.outLen = XSTRLEN(c.output); d.input = "12345678901234567890123456789012345678901234567890123456" "789012345678901234567890"; d.output = "\x9b\x75\x2e\x45\x57\x3d\x4b\x39\xf4\xdb\xd3\x32\x3c\xab" - "\x82\xbf\x63\x32\x6b\xfb"; - d.inLen = strlen(d.input); - d.outLen = strlen(d.output); + "\x82\xbf\x63\x32\x6b\xfb"; + d.inLen = XSTRLEN(d.input); + d.outLen = XSTRLEN(d.output); test_ripemd[0] = a; test_ripemd[1] = b; 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; + } - if (memcmp(hash, test_ripemd[i].output, RIPEMD_DIGEST_SIZE) != 0) + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret) { + return ret; + } + + if (XMEMCMP(hash, test_ripemd[i].output, RIPEMD_DIGEST_SIZE) != 0) return -10 - i; } @@ -569,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[]= { @@ -587,14 +674,14 @@ int hmac_md5_test(void) a.input = "Hi There"; a.output = "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc" "\x9d"; - a.inLen = strlen(a.input); - a.outLen = strlen(a.output); + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); 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 = strlen(b.input); - b.outLen = strlen(b.output); + b.inLen = XSTRLEN(b.input); + b.outLen = XSTRLEN(b.output); 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" @@ -602,19 +689,23 @@ int hmac_md5_test(void) "\xDD\xDD\xDD\xDD\xDD\xDD"; c.output = "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3" "\xf6"; - c.inLen = strlen(c.input); - c.outLen = strlen(c.output); + c.inLen = XSTRLEN(c.input); + c.outLen = XSTRLEN(c.output); 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) if (i == 1) continue; /* fips not allowed */ #endif - ret = wc_HmacSetKey(&hmac, MD5, (byte*)keys[i], (word32)strlen(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, @@ -625,10 +716,12 @@ int hmac_md5_test(void) if (ret != 0) return -4016; - if (memcmp(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 @@ -637,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[]= { @@ -657,14 +750,14 @@ int hmac_sha_test(void) 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 = strlen(a.input); - a.outLen = strlen(a.output); + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); 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 = strlen(b.input); - b.outLen = strlen(b.output); + b.inLen = XSTRLEN(b.input); + b.outLen = XSTRLEN(b.output); 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" @@ -672,19 +765,23 @@ int hmac_sha_test(void) "\xDD\xDD\xDD\xDD\xDD\xDD"; c.output = "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b" "\x4f\x63\xf1\x75\xd3"; - c.inLen = strlen(c.input); - c.outLen = strlen(c.output); + c.inLen = XSTRLEN(c.input); + c.outLen = XSTRLEN(c.output); 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) if (i == 1) continue; /* fips not allowed */ #endif - ret = wc_HmacSetKey(&hmac, SHA, (byte*)keys[i], (word32)strlen(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, @@ -695,19 +792,98 @@ int hmac_sha_test(void) if (ret != 0) return -4019; - if (memcmp(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 +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA224) +int hmac_sha224_test(void) +{ + Hmac hmac; + byte hash[WC_SHA224_DIGEST_SIZE]; + + const char* keys[]= + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "Jefe", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" + }; + + testVector a, b, c; + testVector test_hmac[3]; + + int ret; + int times = sizeof(test_hmac) / sizeof(testVector), i; + + 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 = 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 = 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" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD"; + 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 = 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, WC_SHA224, (byte*)keys[i],(word32)XSTRLEN(keys[i])); + if (ret != 0) + return -4021; + ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, + (word32)test_hmac[i].inLen); + if (ret != 0) + return -4022; + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) + return -4023; + + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA224_DIGEST_SIZE) != 0) + return -20 - i; + } + + wc_HmacFree(&hmac); + + return 0; +} +#endif + + #if !defined(NO_HMAC) && !defined(NO_SHA256) int hmac_sha256_test(void) { Hmac hmac; - byte hash[SHA256_DIGEST_SIZE]; + byte hash[WC_SHA256_DIGEST_SIZE]; const char* keys[]= { @@ -728,15 +904,15 @@ int hmac_sha256_test(void) 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 = strlen(a.input); - a.outLen = strlen(a.output); + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); 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 = strlen(b.input); - b.outLen = strlen(b.output); + b.inLen = XSTRLEN(b.input); + b.outLen = XSTRLEN(b.output); 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" @@ -745,19 +921,24 @@ int hmac_sha256_test(void) c.output = "\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81" "\xa7\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5" "\x65\xfe"; - c.inLen = strlen(c.input); - c.outLen = strlen(c.output); + c.inLen = XSTRLEN(c.input); + c.outLen = XSTRLEN(c.output); 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) if (i == 1) continue; /* fips not allowed */ #endif - ret = wc_HmacSetKey(&hmac,SHA256, (byte*)keys[i], (word32)strlen(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, @@ -768,10 +949,12 @@ int hmac_sha256_test(void) if (ret != 0) return -4022; - if (memcmp(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 @@ -781,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[]= { @@ -803,16 +986,16 @@ int hmac_sha384_test(void) "\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 = strlen(a.input); - a.outLen = strlen(a.output); + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); 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" "\x1b\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22" "\x44\x5e\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa" "\xb2\x16\x49"; - b.inLen = strlen(b.input); - b.outLen = strlen(b.output); + b.inLen = XSTRLEN(b.input); + b.outLen = XSTRLEN(b.output); 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" @@ -822,19 +1005,24 @@ int hmac_sha384_test(void) "\x6f\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66" "\x14\x4b\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01" "\xa3\x4f\x27"; - c.inLen = strlen(c.input); - c.outLen = strlen(c.output); + c.inLen = XSTRLEN(c.input); + c.outLen = XSTRLEN(c.output); 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) if (i == 1) continue; /* fips not allowed */ #endif - ret = wc_HmacSetKey(&hmac,SHA384, (byte*)keys[i], (word32)strlen(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, @@ -845,10 +1033,12 @@ int hmac_sha384_test(void) if (ret != 0) return -4025; - if (memcmp(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/FreeRTOS-Plus/Source/WolfSSL/tests/include.am b/FreeRTOS-Plus/Source/WolfSSL/tests/include.am index 006458523..ee4952667 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/tests/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/include.am @@ -3,7 +3,7 @@ # All paths should be given relative to the root -if BUILD_EXAMPLES +if BUILD_TESTS check_PROGRAMS += tests/unit.test noinst_PROGRAMS += tests/unit.test tests_unit_test_SOURCES = \ @@ -11,13 +11,38 @@ tests_unit_test_SOURCES = \ tests/api.c \ tests/suites.c \ tests/hash.c \ + tests/srp.c \ examples/client/client.c \ examples/server/server.c tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) -tests_unit_test_LDADD = src/libwolfssl.la +tests_unit_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) tests_unit_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += tests/unit.h EXTRA_DIST += tests/test.conf \ - tests/test-dtls.conf + tests/test-sha2.conf \ + tests/test-tls13.conf \ + tests/test-tls13-down.conf \ + tests/test-tls13-ecc.conf \ + tests/test-tls13-psk.conf \ + tests/test-qsh.conf \ + tests/test-qsh-sha2.conf \ + tests/test-psk.conf \ + tests/test-psk-no-id.conf \ + tests/test-psk-no-id-sha2.conf \ + tests/test-dtls.conf \ + tests/test-dtls-sha2.conf \ + tests/test-sctp.conf \ + tests/test-sctp-sha2.conf \ + tests/test-sig.conf \ + tests/test-ed25519.conf \ + tests/test-ed448.conf \ + tests/test-enckeys.conf \ + tests/test-maxfrag.conf \ + tests/test-maxfrag-dtls.conf \ + tests/test-fails.conf \ + tests/test-chains.conf \ + tests/test-altchains.conf \ + tests/test-trustpeer.conf \ + tests/test-dhprime.conf DISTCLEANFILES+= tests/.libs/unit.test diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/srp.c b/FreeRTOS-Plus/Source/WolfSSL/tests/srp.c new file mode 100644 index 000000000..504fbfb1c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/srp.c @@ -0,0 +1,838 @@ +/* srp.c SRP unit tests + * + * Copyright (C) 2006-2020 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 +#include +#include + +#if defined(WOLFCRYPT_HAVE_SRP) && defined(WOLFSSL_SHA512) + +static byte username[] = "user"; +static word32 usernameSz = 4; + +static byte password[] = "password"; +static word32 passwordSz = 8; + +static byte srp_N[] = { + 0xD4, 0xC7, 0xF8, 0xA2, 0xB3, 0x2C, 0x11, 0xB8, 0xFB, 0xA9, 0x58, 0x1E, + 0xC4, 0xBA, 0x4F, 0x1B, 0x04, 0x21, 0x56, 0x42, 0xEF, 0x73, 0x55, 0xE3, + 0x7C, 0x0F, 0xC0, 0x44, 0x3E, 0xF7, 0x56, 0xEA, 0x2C, 0x6B, 0x8E, 0xEB, + 0x75, 0x5A, 0x1C, 0x72, 0x30, 0x27, 0x66, 0x3C, 0xAA, 0x26, 0x5E, 0xF7, + 0x85, 0xB8, 0xFF, 0x6A, 0x9B, 0x35, 0x22, 0x7A, 0x52, 0xD8, 0x66, 0x33, + 0xDB, 0xDF, 0xCA, 0x43 +}; + +static byte srp_g[] = { + 0x02 +}; + +static byte srp_salt[] = { + 0x80, 0x66, 0x61, 0x5B, 0x7D, 0x33, 0xA2, 0x2E, 0x79, 0x18 +}; + +static byte srp_verifier[] = { + 0x24, 0x5F, 0xA5, 0x1B, 0x2A, 0x28, 0xF8, 0xFF, 0xE2, 0xA0, 0xF8, 0x61, + 0x7B, 0x0F, 0x3C, 0x05, 0xD6, 0x4A, 0x55, 0xDF, 0x74, 0x31, 0x54, 0x47, + 0xA1, 0xFA, 0x9D, 0x25, 0x7B, 0x02, 0x88, 0x0A, 0xE8, 0x5A, 0xBA, 0x8B, + 0xA2, 0xD3, 0x8A, 0x62, 0x46, 0x8C, 0xEC, 0x52, 0xBE, 0xDE, 0xFC, 0x75, + 0xF5, 0xDB, 0x9C, 0x8C, 0x9B, 0x34, 0x7A, 0xE7, 0x4A, 0x5F, 0xBB, 0x96, + 0x38, 0x19, 0xAB, 0x24 +}; + +static byte srp_a[] = { + 0x37, 0x95, 0xF2, 0xA6, 0xF1, 0x6F, 0x0D, 0x58, 0xBF, 0xED, 0x44, 0x87, + 0xE0, 0xB6, 0xCC, 0x1C, 0xA0, 0x50, 0xC6, 0x61, 0xBB, 0x36, 0xE0, 0x9A, + 0xF3, 0xF7, 0x1E, 0x7A, 0x61, 0x86, 0x5A, 0xF5 +}; + +static byte srp_A[] = { + 0x8D, 0x28, 0xC5, 0x6A, 0x46, 0x5C, 0x82, 0xDB, 0xC7, 0xF6, 0x8B, 0x62, + 0x1A, 0xAD, 0xA1, 0x76, 0x1B, 0x55, 0xFF, 0xAB, 0x10, 0x2F, 0xFF, 0x4A, + 0xAA, 0x46, 0xAD, 0x33, 0x64, 0xDE, 0x28, 0x2E, 0x82, 0x7A, 0xBE, 0xEA, + 0x32, 0xFC, 0xD6, 0x14, 0x01, 0x71, 0xE6, 0xC8, 0xC9, 0x53, 0x69, 0x55, + 0xE1, 0xF8, 0x3D, 0xDD, 0xC7, 0xD5, 0x21, 0xCE, 0xFF, 0x17, 0xFC, 0x23, + 0xBF, 0xCF, 0x2D, 0xB0 +}; + +static byte srp_b[] = { + 0x2B, 0xDD, 0x30, 0x30, 0x53, 0xAF, 0xD8, 0x3A, 0xE7, 0xE0, 0x17, 0x82, + 0x39, 0x44, 0x2C, 0xDB, 0x30, 0x88, 0x0F, 0xC8, 0x88, 0xC2, 0xB2, 0xC1, + 0x78, 0x43, 0x2F, 0xD5, 0x60, 0xD4, 0xDA, 0x43 +}; + +static byte srp_B[] = { + 0xB5, 0x80, 0x36, 0x7F, 0x50, 0x89, 0xC1, 0x04, 0x42, 0x98, 0xD7, 0x6A, + 0x37, 0x8E, 0xF1, 0x81, 0x52, 0xC5, 0x7A, 0xA1, 0xD5, 0xB7, 0x66, 0x84, + 0xA1, 0x3E, 0x32, 0x82, 0x2B, 0x3A, 0xB5, 0xD7, 0x3D, 0x50, 0xF1, 0x58, + 0xBD, 0x89, 0x75, 0xC7, 0x51, 0xCF, 0x6C, 0x03, 0xD4, 0xCA, 0xD5, 0x6E, + 0x97, 0x4D, 0xA3, 0x1E, 0x19, 0x0B, 0xF0, 0xAA, 0x7D, 0x14, 0x90, 0x80, + 0x0E, 0xC7, 0x92, 0xAD +}; + +static byte srp_key[] = { + 0x66, 0x00, 0x9D, 0x58, 0xB3, 0xD2, 0x0D, 0x4B, 0x69, 0x7F, 0xCF, 0x48, + 0xFF, 0x8F, 0x15, 0x81, 0x4C, 0x4B, 0xFE, 0x9D, 0x85, 0x77, 0x88, 0x60, + 0x1D, 0x1E, 0x51, 0xCF, 0x75, 0xCC, 0x58, 0x00, 0xE7, 0x8D, 0x22, 0x87, + 0x13, 0x6C, 0x88, 0x55 +}; + +static byte srp_client_proof[] = { + 0x0D, 0x49, 0xE1, 0x9C, 0x3A, 0x88, 0x43, 0x15, 0x45, 0xA8, 0xAC, 0xAB, + 0xEA, 0x15, 0x1A, 0xEE, 0xF9, 0x38, 0x4D, 0x21 +}; + +static byte srp_server_proof[] = { + 0xBD, 0xB1, 0x20, 0x70, 0x46, 0xC9, 0xD6, 0xCC, 0xE2, 0x1D, 0x75, 0xA2, + 0xD0, 0xAF, 0xC5, 0xBC, 0xAE, 0x12, 0xFC, 0x75 +}; + +static void test_SrpInit(void) +{ + Srp srp; + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(NULL, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, (SrpType)255, SRP_CLIENT_SIDE)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, SRP_TYPE_SHA, (SrpSide)255)); + + /* success */ + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + + wc_SrpTerm(&srp); +} + +static void test_SrpSetUsername(void) +{ + Srp srp; + + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(NULL, username, usernameSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(&srp, NULL, usernameSz)); + + /* success */ + AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); + AssertIntEQ((int) usernameSz, srp.userSz); + AssertIntEQ(0, XMEMCMP(srp.user, username, usernameSz)); + + wc_SrpTerm(&srp); +} + +static void test_SrpSetParams(void) +{ + Srp srp; + + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + + /* invalid call order */ + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpSetParams(&srp, + srp_N, sizeof(srp_N), + srp_g, sizeof(srp_g), + srp_salt, sizeof(srp_salt))); + + /* fix call order */ + AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(NULL, + srp_N, sizeof(srp_N), + srp_g, sizeof(srp_g), + srp_salt, sizeof(srp_salt))); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(&srp, + NULL, sizeof(srp_N), + srp_g, sizeof(srp_g), + srp_salt, sizeof(srp_salt))); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(&srp, + srp_N, sizeof(srp_N), + NULL, sizeof(srp_g), + srp_salt, sizeof(srp_salt))); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(&srp, + srp_N, sizeof(srp_N), + srp_g, sizeof(srp_g), + NULL, sizeof(srp_salt))); + + /* success */ + AssertIntEQ(0, wc_SrpSetParams(&srp, srp_N, sizeof(srp_N), + srp_g, sizeof(srp_g), + srp_salt, sizeof(srp_salt))); + + AssertIntEQ(sizeof(srp_salt), srp.saltSz); + AssertIntEQ(0, XMEMCMP(srp.salt, srp_salt, srp.saltSz)); + + wc_SrpTerm(&srp); +} + +static void test_SrpSetPassword(void) +{ + Srp srp; + byte v[64]; + word32 vSz = 0; + + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); + + /* invalid call order */ + AssertIntEQ(SRP_CALL_ORDER_E, + wc_SrpSetPassword(&srp, password, passwordSz)); + AssertIntEQ(SRP_CALL_ORDER_E, + wc_SrpGetVerifier(&srp, v, &vSz)); + + /* fix call order */ + AssertIntEQ(0, wc_SrpSetParams(&srp, srp_N, sizeof(srp_N), + srp_g, sizeof(srp_g), + srp_salt, sizeof(srp_salt))); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetPassword(NULL, password, passwordSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetPassword(&srp, NULL, passwordSz)); + + /* success */ + AssertIntEQ(0, wc_SrpSetPassword(&srp, password, passwordSz)); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetVerifier(NULL, v, &vSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetVerifier(&srp, NULL, &vSz)); + AssertIntEQ(BUFFER_E, wc_SrpGetVerifier(&srp, v, &vSz)); + + /* success */ + vSz = sizeof(v); + AssertIntEQ(0, wc_SrpGetVerifier(&srp, v, &vSz)); + AssertIntEQ(vSz, sizeof(srp_verifier)); + AssertIntEQ(0, XMEMCMP(srp_verifier, v, vSz)); + + /* invalid params - client side srp */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetVerifier(&srp, v, vSz)); + + wc_SrpTerm(&srp); + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_SERVER_SIDE)); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetVerifier(NULL, v, vSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetVerifier(&srp, NULL, vSz)); + + /* success */ + AssertIntEQ(0, wc_SrpSetVerifier(&srp, v, vSz)); + + wc_SrpTerm(&srp); +} + +static void test_SrpGetPublic(void) +{ + Srp srp; + byte pub[64]; + word32 pubSz = 0; + + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); + AssertIntEQ(0, wc_SrpSetParams(&srp, srp_N, sizeof(srp_N), + srp_g, sizeof(srp_g), + srp_salt, sizeof(srp_salt))); + + /* invalid call order */ + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGetPublic(&srp, pub, &pubSz)); + + /* fix call order */ + AssertIntEQ(0, wc_SrpSetPassword(&srp, password, passwordSz)); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(NULL, pub, &pubSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(&srp, NULL, &pubSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(&srp, pub, NULL)); + AssertIntEQ(BUFFER_E, wc_SrpGetPublic(&srp, pub, &pubSz)); + + /* success */ + pubSz = sizeof(pub); + AssertIntEQ(0, wc_SrpSetPrivate(&srp, srp_a, sizeof(srp_a))); + AssertIntEQ(0, wc_SrpGetPublic(&srp, pub, &pubSz)); + AssertIntEQ(pubSz, sizeof(srp_A)); + AssertIntEQ(0, XMEMCMP(pub, srp_A, pubSz)); + + wc_SrpTerm(&srp); + + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_SERVER_SIDE)); + AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); + AssertIntEQ(0, wc_SrpSetParams(&srp, srp_N, sizeof(srp_N), + srp_g, sizeof(srp_g), + srp_salt, sizeof(srp_salt))); + + /* invalid call order */ + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGetPublic(&srp, pub, &pubSz)); + + /* fix call order */ + AssertIntEQ(0, wc_SrpSetVerifier(&srp, srp_verifier, sizeof(srp_verifier))); + + /* success */ + AssertIntEQ(0, wc_SrpSetPrivate(&srp, srp_b, sizeof(srp_b))); + AssertIntEQ(0, wc_SrpGetPublic(&srp, pub, &pubSz)); + AssertIntEQ(pubSz, sizeof(srp_B)); + AssertIntEQ(0, XMEMCMP(pub, srp_B, pubSz)); + + wc_SrpTerm(&srp); +} + +static void test_SrpComputeKey(void) +{ + Srp cli, srv; + byte clientPubKey[64]; + byte serverPubKey[64]; + word32 clientPubKeySz = 64; + word32 serverPubKeySz = 64; + + AssertIntEQ(0, wc_SrpInit(&cli, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(0, wc_SrpInit(&srv, SRP_TYPE_SHA, SRP_SERVER_SIDE)); + + /* invalid call order */ + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpComputeKey(&cli, + clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + + /* fix call order */ + AssertIntEQ(0, wc_SrpSetUsername(&cli, username, usernameSz)); + AssertIntEQ(0, wc_SrpSetUsername(&srv, username, usernameSz)); + + AssertIntEQ(0, wc_SrpSetParams(&cli, srp_N, sizeof(srp_N), + srp_g, sizeof(srp_g), + srp_salt, sizeof(srp_salt))); + AssertIntEQ(0, wc_SrpSetParams(&srv, srp_N, sizeof(srp_N), + srp_g, sizeof(srp_g), + srp_salt, sizeof(srp_salt))); + + AssertIntEQ(0, wc_SrpSetPassword(&cli, password, passwordSz)); + AssertIntEQ(0, wc_SrpSetVerifier(&srv, srp_verifier, sizeof(srp_verifier))); + + AssertIntEQ(0, wc_SrpSetPrivate(&cli, srp_a, sizeof(srp_a))); + AssertIntEQ(0, wc_SrpGetPublic(&cli, clientPubKey, &clientPubKeySz)); + AssertIntEQ(0, XMEMCMP(clientPubKey, srp_A, clientPubKeySz)); + AssertIntEQ(0, wc_SrpSetPrivate(&srv, srp_b, sizeof(srp_b))); + AssertIntEQ(0, wc_SrpGetPublic(&srv, serverPubKey, &serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(serverPubKey, srp_B, serverPubKeySz)); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpComputeKey(NULL, + clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpComputeKey(&cli, + NULL, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpComputeKey(&cli, + clientPubKey, 0, + serverPubKey, serverPubKeySz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpComputeKey(&cli, + clientPubKey, clientPubKeySz, + NULL, serverPubKeySz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpComputeKey(&cli, + clientPubKey, clientPubKeySz, + serverPubKey, 0)); + + /* success */ + AssertIntEQ(0, wc_SrpComputeKey(&cli, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, wc_SrpComputeKey(&srv, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(cli.key, srp_key, sizeof(srp_key))); + AssertIntEQ(0, XMEMCMP(srv.key, srp_key, sizeof(srp_key))); + + wc_SrpTerm(&cli); + wc_SrpTerm(&srv); +} + +static void test_SrpGetProofAndVerify(void) +{ + Srp cli, srv; + byte clientPubKey[64]; + byte serverPubKey[64]; + word32 clientPubKeySz = 64; + word32 serverPubKeySz = 64; + byte clientProof[SRP_MAX_DIGEST_SIZE]; + byte serverProof[SRP_MAX_DIGEST_SIZE]; + word32 clientProofSz = SRP_MAX_DIGEST_SIZE; + word32 serverProofSz = SRP_MAX_DIGEST_SIZE; + + AssertIntEQ(0, wc_SrpInit(&cli, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(0, wc_SrpInit(&srv, SRP_TYPE_SHA, SRP_SERVER_SIDE)); + + AssertIntEQ(0, wc_SrpSetUsername(&cli, username, usernameSz)); + AssertIntEQ(0, wc_SrpSetUsername(&srv, username, usernameSz)); + + AssertIntEQ(0, wc_SrpSetParams(&cli, srp_N, sizeof(srp_N), + srp_g, sizeof(srp_g), + srp_salt, sizeof(srp_salt))); + AssertIntEQ(0, wc_SrpSetParams(&srv, srp_N, sizeof(srp_N), + srp_g, sizeof(srp_g), + srp_salt, sizeof(srp_salt))); + + AssertIntEQ(0, wc_SrpSetPassword(&cli, password, passwordSz)); + AssertIntEQ(0, wc_SrpSetVerifier(&srv, srp_verifier, sizeof(srp_verifier))); + + AssertIntEQ(0, wc_SrpSetPrivate(&cli, srp_a, sizeof(srp_a))); + AssertIntEQ(0, wc_SrpGetPublic(&cli, clientPubKey, &clientPubKeySz)); + AssertIntEQ(0, XMEMCMP(clientPubKey, srp_A, clientPubKeySz)); + + AssertIntEQ(0, wc_SrpSetPrivate(&srv, srp_b, sizeof(srp_b))); + AssertIntEQ(0, wc_SrpGetPublic(&srv, serverPubKey, &serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(serverPubKey, srp_B, serverPubKeySz)); + + AssertIntEQ(0, wc_SrpComputeKey(&cli, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(cli.key, srp_key, sizeof(srp_key))); + + AssertIntEQ(0, wc_SrpComputeKey(&srv, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(srv.key, srp_key, sizeof(srp_key))); + + /* invalid params */ + serverProofSz = 0; + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetProof(NULL, clientProof,&clientProofSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetProof(&cli, NULL, &clientProofSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetProof(&cli, clientProof,NULL)); + AssertIntEQ(BUFFER_E, wc_SrpGetProof(&srv, serverProof,&serverProofSz)); + + AssertIntEQ(BAD_FUNC_ARG, + wc_SrpVerifyPeersProof(NULL, clientProof, clientProofSz)); + AssertIntEQ(BAD_FUNC_ARG, + wc_SrpVerifyPeersProof(&cli, NULL, clientProofSz)); + AssertIntEQ(BUFFER_E, + wc_SrpVerifyPeersProof(&srv, serverProof, serverProofSz)); + serverProofSz = SRP_MAX_DIGEST_SIZE; + + /* success */ + AssertIntEQ(0, wc_SrpGetProof(&cli, clientProof, &clientProofSz)); + AssertIntEQ(0, XMEMCMP(clientProof, srp_client_proof, + sizeof(srp_client_proof))); + AssertIntEQ(0, wc_SrpVerifyPeersProof(&srv, clientProof, clientProofSz)); + AssertIntEQ(0, wc_SrpGetProof(&srv, serverProof, &serverProofSz)); + AssertIntEQ(0, XMEMCMP(serverProof, srp_server_proof, + sizeof(srp_server_proof))); + AssertIntEQ(0, wc_SrpVerifyPeersProof(&cli, serverProof, serverProofSz)); + + wc_SrpTerm(&cli); + wc_SrpTerm(&srv); +} + +static int sha512_key_gen(Srp* srp, byte* secret, word32 size) +{ + wc_Sha512 hash; + int r; + + srp->key = (byte*)XMALLOC(WC_SHA512_DIGEST_SIZE, NULL, DYNAMIC_TYPE_SRP); + if (srp->key == NULL) + return MEMORY_E; + + 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(wc_Sha512)); + + return r; +} + +static void test_SrpKeyGenFunc_cb(void) +{ + Srp cli, srv; + byte clientPubKey[1024]; + byte serverPubKey[1024]; + word32 clientPubKeySz = 1024; + word32 serverPubKeySz = 1024; + byte clientProof[SRP_MAX_DIGEST_SIZE]; + byte serverProof[SRP_MAX_DIGEST_SIZE]; + word32 clientProofSz = SRP_MAX_DIGEST_SIZE; + word32 serverProofSz = SRP_MAX_DIGEST_SIZE; + + byte username_[] = "alice"; + word32 usernameSz_ = 5; + + byte password_[] = "password123"; + word32 passwordSz_ = 11; + +#if !defined(FP_MAX_BITS) || FP_MAX_BITS > 3072 * 2 + byte N_[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, + 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, + 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, + 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, + 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, + 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, + 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, + 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, + 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, + 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, + 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, + 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, + 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, + 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, + 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, + 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, + 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + + byte g_[] = { + 0x05 + }; + + byte salt_[] = { + 0xBE, 0xB2, 0x53, 0x79, 0xD1, 0xA8, 0x58, 0x1E, 0xB5, 0xA7, 0x27, 0x67, + 0x3A, 0x24, 0x41, 0xEE + }; + + byte verifier_[] = { + 0x9B, 0x5E, 0x06, 0x17, 0x01, 0xEA, 0x7A, 0xEB, 0x39, 0xCF, 0x6E, 0x35, + 0x19, 0x65, 0x5A, 0x85, 0x3C, 0xF9, 0x4C, 0x75, 0xCA, 0xF2, 0x55, 0x5E, + 0xF1, 0xFA, 0xF7, 0x59, 0xBB, 0x79, 0xCB, 0x47, 0x70, 0x14, 0xE0, 0x4A, + 0x88, 0xD6, 0x8F, 0xFC, 0x05, 0x32, 0x38, 0x91, 0xD4, 0xC2, 0x05, 0xB8, + 0xDE, 0x81, 0xC2, 0xF2, 0x03, 0xD8, 0xFA, 0xD1, 0xB2, 0x4D, 0x2C, 0x10, + 0x97, 0x37, 0xF1, 0xBE, 0xBB, 0xD7, 0x1F, 0x91, 0x24, 0x47, 0xC4, 0xA0, + 0x3C, 0x26, 0xB9, 0xFA, 0xD8, 0xED, 0xB3, 0xE7, 0x80, 0x77, 0x8E, 0x30, + 0x25, 0x29, 0xED, 0x1E, 0xE1, 0x38, 0xCC, 0xFC, 0x36, 0xD4, 0xBA, 0x31, + 0x3C, 0xC4, 0x8B, 0x14, 0xEA, 0x8C, 0x22, 0xA0, 0x18, 0x6B, 0x22, 0x2E, + 0x65, 0x5F, 0x2D, 0xF5, 0x60, 0x3F, 0xD7, 0x5D, 0xF7, 0x6B, 0x3B, 0x08, + 0xFF, 0x89, 0x50, 0x06, 0x9A, 0xDD, 0x03, 0xA7, 0x54, 0xEE, 0x4A, 0xE8, + 0x85, 0x87, 0xCC, 0xE1, 0xBF, 0xDE, 0x36, 0x79, 0x4D, 0xBA, 0xE4, 0x59, + 0x2B, 0x7B, 0x90, 0x4F, 0x44, 0x2B, 0x04, 0x1C, 0xB1, 0x7A, 0xEB, 0xAD, + 0x1E, 0x3A, 0xEB, 0xE3, 0xCB, 0xE9, 0x9D, 0xE6, 0x5F, 0x4B, 0xB1, 0xFA, + 0x00, 0xB0, 0xE7, 0xAF, 0x06, 0x86, 0x3D, 0xB5, 0x3B, 0x02, 0x25, 0x4E, + 0xC6, 0x6E, 0x78, 0x1E, 0x3B, 0x62, 0xA8, 0x21, 0x2C, 0x86, 0xBE, 0xB0, + 0xD5, 0x0B, 0x5B, 0xA6, 0xD0, 0xB4, 0x78, 0xD8, 0xC4, 0xE9, 0xBB, 0xCE, + 0xC2, 0x17, 0x65, 0x32, 0x6F, 0xBD, 0x14, 0x05, 0x8D, 0x2B, 0xBD, 0xE2, + 0xC3, 0x30, 0x45, 0xF0, 0x38, 0x73, 0xE5, 0x39, 0x48, 0xD7, 0x8B, 0x79, + 0x4F, 0x07, 0x90, 0xE4, 0x8C, 0x36, 0xAE, 0xD6, 0xE8, 0x80, 0xF5, 0x57, + 0x42, 0x7B, 0x2F, 0xC0, 0x6D, 0xB5, 0xE1, 0xE2, 0xE1, 0xD7, 0xE6, 0x61, + 0xAC, 0x48, 0x2D, 0x18, 0xE5, 0x28, 0xD7, 0x29, 0x5E, 0xF7, 0x43, 0x72, + 0x95, 0xFF, 0x1A, 0x72, 0xD4, 0x02, 0x77, 0x17, 0x13, 0xF1, 0x68, 0x76, + 0xDD, 0x05, 0x0A, 0xE5, 0xB7, 0xAD, 0x53, 0xCC, 0xB9, 0x08, 0x55, 0xC9, + 0x39, 0x56, 0x64, 0x83, 0x58, 0xAD, 0xFD, 0x96, 0x64, 0x22, 0xF5, 0x24, + 0x98, 0x73, 0x2D, 0x68, 0xD1, 0xD7, 0xFB, 0xEF, 0x10, 0xD7, 0x80, 0x34, + 0xAB, 0x8D, 0xCB, 0x6F, 0x0F, 0xCF, 0x88, 0x5C, 0xC2, 0xB2, 0xEA, 0x2C, + 0x3E, 0x6A, 0xC8, 0x66, 0x09, 0xEA, 0x05, 0x8A, 0x9D, 0xA8, 0xCC, 0x63, + 0x53, 0x1D, 0xC9, 0x15, 0x41, 0x4D, 0xF5, 0x68, 0xB0, 0x94, 0x82, 0xDD, + 0xAC, 0x19, 0x54, 0xDE, 0xC7, 0xEB, 0x71, 0x4F, 0x6F, 0xF7, 0xD4, 0x4C, + 0xD5, 0xB8, 0x6F, 0x6B, 0xD1, 0x15, 0x81, 0x09, 0x30, 0x63, 0x7C, 0x01, + 0xD0, 0xF6, 0x01, 0x3B, 0xC9, 0x74, 0x0F, 0xA2, 0xC6, 0x33, 0xBA, 0x89 + }; + + byte a_[] = { + 0x60, 0x97, 0x55, 0x27, 0x03, 0x5C, 0xF2, 0xAD, 0x19, 0x89, 0x80, 0x6F, + 0x04, 0x07, 0x21, 0x0B, 0xC8, 0x1E, 0xDC, 0x04, 0xE2, 0x76, 0x2A, 0x56, + 0xAF, 0xD5, 0x29, 0xDD, 0xDA, 0x2D, 0x43, 0x93 + }; + + byte A_[] = { + 0xFA, 0xB6, 0xF5, 0xD2, 0x61, 0x5D, 0x1E, 0x32, 0x35, 0x12, 0xE7, 0x99, + 0x1C, 0xC3, 0x74, 0x43, 0xF4, 0x87, 0xDA, 0x60, 0x4C, 0xA8, 0xC9, 0x23, + 0x0F, 0xCB, 0x04, 0xE5, 0x41, 0xDC, 0xE6, 0x28, 0x0B, 0x27, 0xCA, 0x46, + 0x80, 0xB0, 0x37, 0x4F, 0x17, 0x9D, 0xC3, 0xBD, 0xC7, 0x55, 0x3F, 0xE6, + 0x24, 0x59, 0x79, 0x8C, 0x70, 0x1A, 0xD8, 0x64, 0xA9, 0x13, 0x90, 0xA2, + 0x8C, 0x93, 0xB6, 0x44, 0xAD, 0xBF, 0x9C, 0x00, 0x74, 0x5B, 0x94, 0x2B, + 0x79, 0xF9, 0x01, 0x2A, 0x21, 0xB9, 0xB7, 0x87, 0x82, 0x31, 0x9D, 0x83, + 0xA1, 0xF8, 0x36, 0x28, 0x66, 0xFB, 0xD6, 0xF4, 0x6B, 0xFC, 0x0D, 0xDB, + 0x2E, 0x1A, 0xB6, 0xE4, 0xB4, 0x5A, 0x99, 0x06, 0xB8, 0x2E, 0x37, 0xF0, + 0x5D, 0x6F, 0x97, 0xF6, 0xA3, 0xEB, 0x6E, 0x18, 0x20, 0x79, 0x75, 0x9C, + 0x4F, 0x68, 0x47, 0x83, 0x7B, 0x62, 0x32, 0x1A, 0xC1, 0xB4, 0xFA, 0x68, + 0x64, 0x1F, 0xCB, 0x4B, 0xB9, 0x8D, 0xD6, 0x97, 0xA0, 0xC7, 0x36, 0x41, + 0x38, 0x5F, 0x4B, 0xAB, 0x25, 0xB7, 0x93, 0x58, 0x4C, 0xC3, 0x9F, 0xC8, + 0xD4, 0x8D, 0x4B, 0xD8, 0x67, 0xA9, 0xA3, 0xC1, 0x0F, 0x8E, 0xA1, 0x21, + 0x70, 0x26, 0x8E, 0x34, 0xFE, 0x3B, 0xBE, 0x6F, 0xF8, 0x99, 0x98, 0xD6, + 0x0D, 0xA2, 0xF3, 0xE4, 0x28, 0x3C, 0xBE, 0xC1, 0x39, 0x3D, 0x52, 0xAF, + 0x72, 0x4A, 0x57, 0x23, 0x0C, 0x60, 0x4E, 0x9F, 0xBC, 0xE5, 0x83, 0xD7, + 0x61, 0x3E, 0x6B, 0xFF, 0xD6, 0x75, 0x96, 0xAD, 0x12, 0x1A, 0x87, 0x07, + 0xEE, 0xC4, 0x69, 0x44, 0x95, 0x70, 0x33, 0x68, 0x6A, 0x15, 0x5F, 0x64, + 0x4D, 0x5C, 0x58, 0x63, 0xB4, 0x8F, 0x61, 0xBD, 0xBF, 0x19, 0xA5, 0x3E, + 0xAB, 0x6D, 0xAD, 0x0A, 0x18, 0x6B, 0x8C, 0x15, 0x2E, 0x5F, 0x5D, 0x8C, + 0xAD, 0x4B, 0x0E, 0xF8, 0xAA, 0x4E, 0xA5, 0x00, 0x88, 0x34, 0xC3, 0xCD, + 0x34, 0x2E, 0x5E, 0x0F, 0x16, 0x7A, 0xD0, 0x45, 0x92, 0xCD, 0x8B, 0xD2, + 0x79, 0x63, 0x93, 0x98, 0xEF, 0x9E, 0x11, 0x4D, 0xFA, 0xAA, 0xB9, 0x19, + 0xE1, 0x4E, 0x85, 0x09, 0x89, 0x22, 0x4D, 0xDD, 0x98, 0x57, 0x6D, 0x79, + 0x38, 0x5D, 0x22, 0x10, 0x90, 0x2E, 0x9F, 0x9B, 0x1F, 0x2D, 0x86, 0xCF, + 0xA4, 0x7E, 0xE2, 0x44, 0x63, 0x54, 0x65, 0xF7, 0x10, 0x58, 0x42, 0x1A, + 0x01, 0x84, 0xBE, 0x51, 0xDD, 0x10, 0xCC, 0x9D, 0x07, 0x9E, 0x6F, 0x16, + 0x04, 0xE7, 0xAA, 0x9B, 0x7C, 0xF7, 0x88, 0x3C, 0x7D, 0x4C, 0xE1, 0x2B, + 0x06, 0xEB, 0xE1, 0x60, 0x81, 0xE2, 0x3F, 0x27, 0xA2, 0x31, 0xD1, 0x84, + 0x32, 0xD7, 0xD1, 0xBB, 0x55, 0xC2, 0x8A, 0xE2, 0x1F, 0xFC, 0xF0, 0x05, + 0xF5, 0x75, 0x28, 0xD1, 0x5A, 0x88, 0x88, 0x1B, 0xB3, 0xBB, 0xB7, 0xFE + }; + + byte b_[] = { + 0xE4, 0x87, 0xCB, 0x59, 0xD3, 0x1A, 0xC5, 0x50, 0x47, 0x1E, 0x81, 0xF0, + 0x0F, 0x69, 0x28, 0xE0, 0x1D, 0xDA, 0x08, 0xE9, 0x74, 0xA0, 0x04, 0xF4, + 0x9E, 0x61, 0xF5, 0xD1, 0x05, 0x28, 0x4D, 0x20 + }; + + byte B_[] = { + 0x40, 0xF5, 0x70, 0x88, 0xA4, 0x82, 0xD4, 0xC7, 0x73, 0x33, 0x84, 0xFE, + 0x0D, 0x30, 0x1F, 0xDD, 0xCA, 0x90, 0x80, 0xAD, 0x7D, 0x4F, 0x6F, 0xDF, + 0x09, 0xA0, 0x10, 0x06, 0xC3, 0xCB, 0x6D, 0x56, 0x2E, 0x41, 0x63, 0x9A, + 0xE8, 0xFA, 0x21, 0xDE, 0x3B, 0x5D, 0xBA, 0x75, 0x85, 0xB2, 0x75, 0x58, + 0x9B, 0xDB, 0x27, 0x98, 0x63, 0xC5, 0x62, 0x80, 0x7B, 0x2B, 0x99, 0x08, + 0x3C, 0xD1, 0x42, 0x9C, 0xDB, 0xE8, 0x9E, 0x25, 0xBF, 0xBD, 0x7E, 0x3C, + 0xAD, 0x31, 0x73, 0xB2, 0xE3, 0xC5, 0xA0, 0xB1, 0x74, 0xDA, 0x6D, 0x53, + 0x91, 0xE6, 0xA0, 0x6E, 0x46, 0x5F, 0x03, 0x7A, 0x40, 0x06, 0x25, 0x48, + 0x39, 0xA5, 0x6B, 0xF7, 0x6D, 0xA8, 0x4B, 0x1C, 0x94, 0xE0, 0xAE, 0x20, + 0x85, 0x76, 0x15, 0x6F, 0xE5, 0xC1, 0x40, 0xA4, 0xBA, 0x4F, 0xFC, 0x9E, + 0x38, 0xC3, 0xB0, 0x7B, 0x88, 0x84, 0x5F, 0xC6, 0xF7, 0xDD, 0xDA, 0x93, + 0x38, 0x1F, 0xE0, 0xCA, 0x60, 0x84, 0xC4, 0xCD, 0x2D, 0x33, 0x6E, 0x54, + 0x51, 0xC4, 0x64, 0xCC, 0xB6, 0xEC, 0x65, 0xE7, 0xD1, 0x6E, 0x54, 0x8A, + 0x27, 0x3E, 0x82, 0x62, 0x84, 0xAF, 0x25, 0x59, 0xB6, 0x26, 0x42, 0x74, + 0x21, 0x59, 0x60, 0xFF, 0xF4, 0x7B, 0xDD, 0x63, 0xD3, 0xAF, 0xF0, 0x64, + 0xD6, 0x13, 0x7A, 0xF7, 0x69, 0x66, 0x1C, 0x9D, 0x4F, 0xEE, 0x47, 0x38, + 0x26, 0x03, 0xC8, 0x8E, 0xAA, 0x09, 0x80, 0x58, 0x1D, 0x07, 0x75, 0x84, + 0x61, 0xB7, 0x77, 0xE4, 0x35, 0x6D, 0xDA, 0x58, 0x35, 0x19, 0x8B, 0x51, + 0xFE, 0xEA, 0x30, 0x8D, 0x70, 0xF7, 0x54, 0x50, 0xB7, 0x16, 0x75, 0xC0, + 0x8C, 0x7D, 0x83, 0x02, 0xFD, 0x75, 0x39, 0xDD, 0x1F, 0xF2, 0xA1, 0x1C, + 0xB4, 0x25, 0x8A, 0xA7, 0x0D, 0x23, 0x44, 0x36, 0xAA, 0x42, 0xB6, 0xA0, + 0x61, 0x5F, 0x3F, 0x91, 0x5D, 0x55, 0xCC, 0x3B, 0x96, 0x6B, 0x27, 0x16, + 0xB3, 0x6E, 0x4D, 0x1A, 0x06, 0xCE, 0x5E, 0x5D, 0x2E, 0xA3, 0xBE, 0xE5, + 0xA1, 0x27, 0x0E, 0x87, 0x51, 0xDA, 0x45, 0xB6, 0x0B, 0x99, 0x7B, 0x0F, + 0xFD, 0xB0, 0xF9, 0x96, 0x2F, 0xEE, 0x4F, 0x03, 0xBE, 0xE7, 0x80, 0xBA, + 0x0A, 0x84, 0x5B, 0x1D, 0x92, 0x71, 0x42, 0x17, 0x83, 0xAE, 0x66, 0x01, + 0xA6, 0x1E, 0xA2, 0xE3, 0x42, 0xE4, 0xF2, 0xE8, 0xBC, 0x93, 0x5A, 0x40, + 0x9E, 0xAD, 0x19, 0xF2, 0x21, 0xBD, 0x1B, 0x74, 0xE2, 0x96, 0x4D, 0xD1, + 0x9F, 0xC8, 0x45, 0xF6, 0x0E, 0xFC, 0x09, 0x33, 0x8B, 0x60, 0xB6, 0xB2, + 0x56, 0xD8, 0xCA, 0xC8, 0x89, 0xCC, 0xA3, 0x06, 0xCC, 0x37, 0x0A, 0x0B, + 0x18, 0xC8, 0xB8, 0x86, 0xE9, 0x5D, 0xA0, 0xAF, 0x52, 0x35, 0xFE, 0xF4, + 0x39, 0x30, 0x20, 0xD2, 0xB7, 0xF3, 0x05, 0x69, 0x04, 0x75, 0x90, 0x42 + }; + + byte key_[] = { + 0x5C, 0xBC, 0x21, 0x9D, 0xB0, 0x52, 0x13, 0x8E, 0xE1, 0x14, 0x8C, 0x71, + 0xCD, 0x44, 0x98, 0x96, 0x3D, 0x68, 0x25, 0x49, 0xCE, 0x91, 0xCA, 0x24, + 0xF0, 0x98, 0x46, 0x8F, 0x06, 0x01, 0x5B, 0xEB, 0x6A, 0xF2, 0x45, 0xC2, + 0x09, 0x3F, 0x98, 0xC3, 0x65, 0x1B, 0xCA, 0x83, 0xAB, 0x8C, 0xAB, 0x2B, + 0x58, 0x0B, 0xBF, 0x02, 0x18, 0x4F, 0xEF, 0xDF, 0x26, 0x14, 0x2F, 0x73, + 0xDF, 0x95, 0xAC, 0x50 + }; +#else + byte N_[] = { + 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, 0xF1, 0x66, 0xDE, 0x5E, + 0x13, 0x89, 0x58, 0x2F, 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, + 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50, 0xA3, 0x73, 0x29, 0xCB, + 0xB4, 0xA0, 0x99, 0xED, 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D, + 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D, 0xCD, 0x7F, 0x48, 0xA9, + 0xDA, 0x04, 0xFD, 0x50, 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0, + 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, 0x66, 0x1A, 0x05, 0xFB, + 0xD5, 0xFA, 0xAA, 0xE8, 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, + 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA, 0xA8, 0x0D, 0x74, 0x0A, + 0xDB, 0xF4, 0xFF, 0x74, 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7, + 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B, 0xCA, 0x97, 0xB4, 0x3A, + 0x23, 0xFB, 0x80, 0x16, 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81, + 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, 0x5B, 0x9D, 0x32, 0xE6, + 0x88, 0xF8, 0x77, 0x48, 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, + 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA, 0x03, 0x2C, 0xFB, 0xDB, + 0xF5, 0x2F, 0xB3, 0x78, 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6, + 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29, 0x9C, 0xCC, 0x04, 0x1C, + 0x7B, 0xC3, 0x08, 0xD8, 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82, + 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, 0x94, 0xB5, 0xC8, 0x03, + 0xD8, 0x9F, 0x7A, 0xE4, 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, + 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2, 0x0F, 0xA7, 0x11, 0x1F, + 0x9E, 0x4A, 0xFF, 0x73 + }; + + byte g_[] = { + 0x02 + }; + + byte salt_[] = { + 0xBE, 0xB2, 0x53, 0x79, 0xD1, 0xA8, 0x58, 0x1E, 0xB5, 0xA7, 0x27, 0x67, + 0x3A, 0x24, 0x41, 0xEE + }; + + byte verifier_[] = { + 0xab, 0x58, 0xc3, 0x49, 0x79, 0xda, 0x9c, 0x1c, 0x0c, 0x5f, 0x6a, 0xe8, + 0xa1, 0xc4, 0x20, 0x78, 0x16, 0xe0, 0x29, 0x6f, 0xdc, 0x09, 0x62, 0xe7, + 0x5d, 0x49, 0x09, 0xd2, 0xd3, 0x48, 0x0b, 0x03, 0xbb, 0xf4, 0x96, 0x58, + 0x93, 0xa5, 0x69, 0xd4, 0x89, 0x10, 0x7f, 0xe2, 0x23, 0x73, 0xf2, 0x8c, + 0xc6, 0x5b, 0x52, 0x5d, 0x2a, 0x2b, 0xa5, 0x23, 0x27, 0xa6, 0x5c, 0xf7, + 0x8d, 0x65, 0x1f, 0xcf, 0x5e, 0x18, 0x70, 0xb7, 0xfd, 0x08, 0x4e, 0xa8, + 0x42, 0xbe, 0x5f, 0x73, 0xf4, 0x8b, 0xa0, 0x4a, 0xf6, 0xfa, 0x85, 0xd2, + 0xd7, 0xf6, 0x4f, 0xc0, 0xc5, 0xba, 0x42, 0x32, 0xc5, 0xbb, 0x57, 0xb2, + 0x60, 0xdb, 0xc4, 0x27, 0x28, 0x4a, 0x7c, 0xdc, 0x5f, 0x64, 0x8a, 0xc2, + 0x51, 0x47, 0x96, 0xd9, 0x9f, 0xd7, 0x64, 0x29, 0x30, 0xe3, 0x64, 0xfa, + 0xd2, 0x42, 0xfa, 0x8b, 0xc9, 0xa0, 0x78, 0xc5, 0xcf, 0x3b, 0x1b, 0x60, + 0x2a, 0xcd, 0x35, 0x8b, 0xfd, 0xbd, 0x62, 0xd6, 0x3b, 0x22, 0x29, 0x1d, + 0xb0, 0xeb, 0xaa, 0x00, 0xdf, 0x99, 0x1f, 0x82, 0xef, 0x9d, 0x1a, 0xad, + 0xe2, 0x4d, 0xa1, 0xca, 0xb2, 0x8f, 0x1d, 0xed, 0x5e, 0xc2, 0xbc, 0x48, + 0xae, 0xe8, 0x5f, 0x52, 0xad, 0xb3, 0xcb, 0xa5, 0x4e, 0xff, 0x52, 0x8c, + 0x9b, 0x11, 0x58, 0xe2, 0xd9, 0x94, 0xcd, 0x6c, 0x66, 0x87, 0xf8, 0xc1, + 0x3c, 0x94, 0x87, 0xce, 0x2c, 0x4a, 0x05, 0x66, 0xc3, 0x20, 0x62, 0x67, + 0x79, 0xc0, 0x33, 0xf1, 0x6e, 0x3f, 0xee, 0xc8, 0xbe, 0x8e, 0x56, 0xc6, + 0x98, 0x72, 0x0e, 0x37, 0x4b, 0x89, 0x4c, 0xba, 0xd9, 0x45, 0xf4, 0x9e, + 0x78, 0x7a, 0x6e, 0x1e, 0xdf, 0xff, 0x23, 0xcf, 0xef, 0xdc, 0x7d, 0x1c, + 0xf1, 0x96, 0x70, 0x2a, 0xa8, 0x6c, 0x20, 0xde, 0xce, 0x6e, 0x3e, 0x89, + 0x11, 0x44, 0x2b, 0x02 + }; + + byte a_[] = { + 0x60, 0x97, 0x55, 0x27, 0x03, 0x5C, 0xF2, 0xAD, 0x19, 0x89, 0x80, 0x6F, + 0x04, 0x07, 0x21, 0x0B, 0xC8, 0x1E, 0xDC, 0x04, 0xE2, 0x76, 0x2A, 0x56, + 0xAF, 0xD5, 0x29, 0xDD, 0xDA, 0x2D, 0x43, 0x93 + }; + + byte A_[] = { + 0x4b, 0x70, 0x0f, 0x8d, 0x48, 0xe6, 0x9c, 0x9a, 0xae, 0x40, 0xc6, 0x84, + 0xac, 0x7c, 0x7c, 0x03, 0x12, 0x1e, 0x2b, 0x76, 0x02, 0xeb, 0x4c, 0x35, + 0x14, 0x80, 0x4c, 0xca, 0xda, 0x0e, 0xd4, 0x01, 0x91, 0x93, 0xa3, 0x51, + 0xec, 0xc6, 0x5a, 0x6f, 0x85, 0x4e, 0xde, 0x91, 0xeb, 0x09, 0x6e, 0x72, + 0x1b, 0x22, 0xd7, 0x01, 0xc7, 0xad, 0xc6, 0x4e, 0x9c, 0xed, 0xac, 0xd7, + 0x5f, 0x2e, 0x26, 0xbb, 0x2f, 0x5e, 0x45, 0xdd, 0x53, 0xdc, 0x8d, 0xbe, + 0xaf, 0xff, 0xe8, 0x2a, 0xa4, 0x9f, 0xca, 0x05, 0x73, 0x44, 0x46, 0x91, + 0x21, 0x25, 0x37, 0xa7, 0x3c, 0xf8, 0x0e, 0x25, 0x03, 0x92, 0x58, 0x20, + 0x5a, 0x7e, 0xdf, 0x47, 0x49, 0xb3, 0x0a, 0xda, 0xf2, 0x58, 0x77, 0xc6, + 0x2f, 0xcd, 0x09, 0xd6, 0x61, 0x35, 0x98, 0xbc, 0xd4, 0xba, 0xf2, 0xa9, + 0x72, 0x7a, 0x53, 0x70, 0x6a, 0x27, 0x81, 0x48, 0x99, 0x2b, 0x2a, 0xbb, + 0x23, 0xad, 0x5d, 0x51, 0x2d, 0x26, 0x9e, 0x16, 0xca, 0x11, 0xbc, 0x08, + 0x95, 0xb5, 0xa3, 0xb5, 0xec, 0x47, 0x21, 0xcd, 0xe4, 0x0a, 0x8c, 0x39, + 0xc7, 0x96, 0xe9, 0x4f, 0x0b, 0xe8, 0x6d, 0xbb, 0xeb, 0x33, 0xda, 0x70, + 0x37, 0x01, 0x89, 0x83, 0x92, 0x1a, 0xba, 0x3f, 0x50, 0x53, 0x19, 0x5d, + 0x5a, 0xc1, 0xda, 0x4e, 0x56, 0x7e, 0x3c, 0x0e, 0x75, 0xd9, 0xe0, 0x60, + 0x9f, 0x92, 0xe8, 0x50, 0x65, 0x7b, 0x2b, 0xe4, 0x77, 0x1f, 0x41, 0x5b, + 0x9c, 0xac, 0xc5, 0xc1, 0xec, 0xed, 0xc3, 0x01, 0x33, 0xbf, 0x64, 0x74, + 0xf5, 0x02, 0x2c, 0x65, 0x19, 0xd7, 0x80, 0x76, 0x0c, 0xa4, 0xd8, 0xd3, + 0xb9, 0x66, 0xb0, 0x34, 0xbd, 0x73, 0x87, 0x7c, 0x1b, 0x3b, 0x33, 0xf4, + 0x74, 0xb9, 0xc3, 0xc5, 0x29, 0x9a, 0x19, 0x68, 0xf3, 0xe6, 0xcd, 0x3b, + 0xfe, 0x84, 0x44, 0x5a + }; + + byte b_[] = { + 0xE4, 0x87, 0xCB, 0x59, 0xD3, 0x1A, 0xC5, 0x50, 0x47, 0x1E, 0x81, 0xF0, + 0x0F, 0x69, 0x28, 0xE0, 0x1D, 0xDA, 0x08, 0xE9, 0x74, 0xA0, 0x04, 0xF4, + 0x9E, 0x61, 0xF5, 0xD1, 0x05, 0x28, 0x4D, 0x20 + }; + + byte B_[] = { + 0x03, 0xaf, 0xa6, 0xe2, 0x14, 0xf3, 0x63, 0x35, 0xf5, 0x51, 0x1d, 0xae, + 0x57, 0x34, 0x24, 0xf4, 0xc2, 0x18, 0xaf, 0x11, 0xf8, 0xef, 0xc7, 0x14, + 0x44, 0xa6, 0x52, 0x19, 0x7b, 0xae, 0x65, 0xe9, 0x86, 0x5f, 0x45, 0x33, + 0xae, 0xeb, 0x71, 0xd3, 0xfe, 0xa9, 0x7d, 0x26, 0xe0, 0xc9, 0xc7, 0xf2, + 0x2e, 0x4f, 0x95, 0xea, 0xb0, 0x83, 0x1d, 0xad, 0x77, 0xca, 0x32, 0x82, + 0x01, 0x21, 0x00, 0xc5, 0x47, 0x52, 0x67, 0xf1, 0x1b, 0x5c, 0x64, 0xd3, + 0xae, 0x61, 0x1a, 0x7d, 0x76, 0x0e, 0x7d, 0x23, 0x1e, 0x9c, 0xa0, 0x02, + 0x7c, 0x44, 0xa8, 0x6f, 0xf9, 0x27, 0x52, 0xd0, 0xa9, 0xc7, 0xd4, 0xbb, + 0x31, 0x69, 0x39, 0xfc, 0xb7, 0xa7, 0xcd, 0x86, 0xa1, 0x55, 0x71, 0x8a, + 0xb7, 0x48, 0x02, 0x73, 0x16, 0xf5, 0x9d, 0x83, 0x2f, 0xa8, 0x7e, 0x08, + 0x2f, 0x2d, 0xc4, 0xc3, 0xae, 0x6c, 0x65, 0x72, 0x42, 0xc1, 0x74, 0xd9, + 0x95, 0xd0, 0x10, 0xa1, 0x25, 0x9c, 0x5a, 0xf9, 0xa5, 0x08, 0x0d, 0xa2, + 0xed, 0x3a, 0xf1, 0xf7, 0x69, 0xc6, 0x29, 0xf4, 0x47, 0x43, 0x40, 0x7e, + 0x6d, 0x8b, 0xff, 0xae, 0x04, 0xf0, 0x09, 0x1d, 0x5f, 0x64, 0xd4, 0x7c, + 0xb8, 0x47, 0xf3, 0x84, 0xf2, 0x0f, 0x4a, 0x16, 0x32, 0xd1, 0xaf, 0x80, + 0x5a, 0xd6, 0x0b, 0xd8, 0xc5, 0xa4, 0x07, 0x0e, 0xbe, 0x52, 0x35, 0x99, + 0x9a, 0xa1, 0x4f, 0x44, 0x5d, 0xb7, 0x4d, 0x5d, 0xb1, 0xe2, 0xf9, 0x84, + 0x33, 0x6c, 0x51, 0xd6, 0xff, 0x27, 0x64, 0x86, 0x45, 0x56, 0xab, 0x73, + 0x1e, 0xb0, 0x21, 0x6e, 0x65, 0x19, 0x21, 0xf9, 0x97, 0x09, 0xb3, 0xec, + 0x32, 0x38, 0x79, 0x28, 0xe2, 0xd2, 0x03, 0x3a, 0x8d, 0xed, 0x8b, 0x34, + 0xa7, 0xf8, 0x0e, 0x26, 0x5b, 0x60, 0x20, 0x76, 0x43, 0x67, 0xe9, 0xea, + 0x3b, 0x0b, 0xbf, 0x25 + }; + + byte key_[] = { + 0x25, 0x9f, 0xb6, 0xab, 0x17, 0xc4, 0xd8, 0x08, 0x07, 0x57, 0xa4, 0x90, + 0x57, 0x5a, 0x31, 0xff, 0x15, 0x98, 0xb4, 0x2e, 0x86, 0x4e, 0x7a, 0xcd, + 0xe3, 0x02, 0x58, 0x6f, 0xa8, 0x4b, 0x5c, 0xab, 0xcc, 0x91, 0xad, 0x8a, + 0xbd, 0xbe, 0x49, 0x51, 0x75, 0xed, 0x2d, 0xe9, 0x15, 0x8c, 0xfe, 0x19, + 0x68, 0x4a, 0xbf, 0x74, 0xf6, 0xe2, 0x60, 0xa7, 0xad, 0x89, 0x92, 0xdf, + 0x9d, 0x6d, 0x66, 0x4c + }; +#endif + + AssertIntEQ(0, wc_SrpInit(&cli, SRP_TYPE_SHA512, SRP_CLIENT_SIDE)); + AssertIntEQ(0, wc_SrpInit(&srv, SRP_TYPE_SHA512, SRP_SERVER_SIDE)); + + AssertIntEQ(0, wc_SrpSetUsername(&cli, username_, usernameSz_)); + AssertIntEQ(0, wc_SrpSetUsername(&srv, username_, usernameSz_)); + + AssertIntEQ(0, wc_SrpSetParams(&cli, N_, sizeof(N_), + g_, sizeof(g_), + salt_, sizeof(salt_))); + AssertIntEQ(0, wc_SrpSetParams(&srv, N_, sizeof(N_), + g_, sizeof(g_), + salt_, sizeof(salt_))); + + AssertIntEQ(0, wc_SrpSetPassword(&cli, password_, passwordSz_)); + AssertIntEQ(0, wc_SrpSetVerifier(&srv, verifier_, sizeof(verifier_))); + + AssertIntEQ(0, wc_SrpSetPrivate(&cli, a_, sizeof(a_))); + AssertIntEQ(0, wc_SrpGetPublic(&cli, clientPubKey, &clientPubKeySz)); + AssertIntEQ(0, XMEMCMP(clientPubKey, A_, clientPubKeySz)); + + AssertIntEQ(0, wc_SrpSetPrivate(&srv, b_, sizeof(b_))); + AssertIntEQ(0, wc_SrpGetPublic(&srv, serverPubKey, &serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(serverPubKey, B_, serverPubKeySz)); + + cli.keyGenFunc_cb = sha512_key_gen; + AssertIntEQ(0, wc_SrpComputeKey(&cli, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(cli.key, key_, sizeof(key_))); + + srv.keyGenFunc_cb = sha512_key_gen; + AssertIntEQ(0, wc_SrpComputeKey(&srv, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(srv.key, key_, sizeof(key_))); + + AssertIntEQ(0, wc_SrpGetProof(&cli, clientProof, &clientProofSz)); + AssertIntEQ(0, wc_SrpVerifyPeersProof(&srv, clientProof, clientProofSz)); + + AssertIntEQ(0, wc_SrpGetProof(&srv, serverProof, &serverProofSz)); + AssertIntEQ(0, wc_SrpVerifyPeersProof(&cli, serverProof, serverProofSz)); + + wc_SrpTerm(&cli); + wc_SrpTerm(&srv); +} + +#endif + +void SrpTest(void) +{ +#if defined(WOLFCRYPT_HAVE_SRP) && defined(WOLFSSL_SHA512) + wolfCrypt_Init(); + test_SrpInit(); + test_SrpSetUsername(); + test_SrpSetParams(); + test_SrpSetPassword(); + test_SrpGetPublic(); + test_SrpComputeKey(); + test_SrpGetProofAndVerify(); + test_SrpKeyGenFunc_cb(); + wolfCrypt_Cleanup(); +#endif +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/suites.c b/FreeRTOS-Plus/Source/WolfSSL/tests/suites.c index d1abc19c9..43a023550 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/tests/suites.c +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/suites.c @@ -1,8 +1,8 @@ /* suites.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -30,49 +31,90 @@ #include #include #include +#if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) \ + && (defined(NO_MAIN_DRIVER) || defined(HAVE_STACK_SIZE)) +#include +#endif #define MAX_ARGS 40 #define MAX_COMMAND_SZ 240 -#define MAX_SUITE_SZ 80 +#ifdef WOLFSSL_TLS13 + #define MAX_SUITE_SZ 200 +#else + #define MAX_SUITE_SZ 80 +#endif #define NOT_BUILT_IN -123 -#ifdef NO_OLD_TLS +#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"; -static char portFlag[] = "-p"; +static char disableEMSFlag[] = "-n"; static char flagSep[] = " "; -static char svrPort[] = "0"; +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) + static char portFlag[] = "-p"; + static char svrPort[] = "0"; +#endif +static char intTestFlag[] = "-H"; +static char forceDefCipherListFlag[] = "defCipherList"; +static char exitWithRetFlag[] = "exitWithRet"; +static char disableDHPrimeTest[] = "-2"; +#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) +{ + 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 "; - 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 */ @@ -90,7 +132,7 @@ static int IsValidCipherSuite(const char* line, char* suite) if (begin) { begin += 3; - end = strstr(begin, " "); + end = XSTRSTR(begin, " "); if (end) { long len = end - begin; @@ -98,28 +140,120 @@ static int IsValidCipherSuite(const char* line, char* suite) printf("suite too long!\n"); return 0; } - memcpy(suite, begin, len); + XMEMCPY(suite, begin, len); suite[len] = '\0'; } else - strncpy(suite, begin, MAX_SUITE_SZ); + XSTRNCPY(suite, begin, MAX_SUITE_SZ); suite[MAX_SUITE_SZ] = '\0'; found = 1; } + /* if QSH not enabled then do not use QSH suite */ + #ifdef HAVE_QSH + if (XSTRNCMP(suite, "QSH", 3) == 0) { + if (wolfSSL_CTX_set_cipher_list(cipherSuiteCtx, suite + 4) + != 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; } return valid; } +static int IsValidCert(const char* line) +{ + int ret = 1; +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) + WOLFSSL_CTX* ctx; + size_t i; + const char* begin; + char cert[80]; +#ifdef WOLFSSL_STATIC_MEMORY + FILE* fStream = NULL; + long chkSz = 0; +#endif + + begin = XSTRSTR(line, "-c "); + if (begin == NULL) + return 1; + + begin += 3; + for (i = 0; i < sizeof(cert) - 1 && *begin != ' ' && *begin != '\0'; i++) + cert[i] = *(begin++); + cert[i] = '\0'; +#ifdef WOLFSSL_STATIC_MEMORY + fStream = XFOPEN(cert, "rb"); + if (fStream == NULL) { + printf("Failed to open file %s\n", cert); + printf("Invalid cert, skipping test\n"); + return 0; + } else { + printf("Successfully opened file\n"); + } + + XFSEEK(fStream, 0L, SEEK_END); + chkSz = XFTELL(fStream); + XFCLOSE(fStream); + if (chkSz > LARGEST_MEM_BUCKET) { + printf("File is larger than largest bucket, skipping this test\n"); + return 0; + } +#endif + + ctx = wolfSSL_CTX_new(wolfSSLv23_server_method_ex(NULL)); + if (ctx == NULL) + return 0; + ret = wolfSSL_CTX_use_certificate_chain_file(ctx, cert) == WOLFSSL_SUCCESS; + wolfSSL_CTX_free(ctx); +#endif /* !NO_FILESYSTEM && !NO_CERTS */ + + (void)line; + + return ret; +} + +static int IsValidCA(const char* line) +{ + int ret = 1; +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) + WOLFSSL_CTX* ctx; + size_t i; + const char* begin; + char cert[80]; + + begin = XSTRSTR(line, "-A "); + if (begin == NULL) + return 1; + + begin += 3; + for (i = 0; i < sizeof(cert) - 1 && *begin != ' ' && *begin != '\0'; i++) + cert[i] = *(begin++); + cert[i] = '\0'; + + ctx = wolfSSL_CTX_new(wolfSSLv23_server_method_ex(NULL)); + if (ctx == NULL) + return 0; + ret = wolfSSL_CTX_use_certificate_chain_file(ctx, cert) == WOLFSSL_SUCCESS; + wolfSSL_CTX_free(ctx); +#endif /* !NO_FILESYSTEM && !NO_CERTS */ + + (void)line; + + return ret; +} static int execute_test_case(int svr_argc, char** svr_argv, - int cli_argc, char** cli_argv, - int addNoVerify, int addNonBlocking) + int cli_argc, char** cli_argv, + int addNoVerify, int addNonBlocking, + int addDisableEMS, int forceSrvDefCipherList, + int forceCliDefCipherList) { #ifdef WOLFSSL_TIRTOS func_args cliArgs = {0}; @@ -138,27 +272,55 @@ 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 + int cliTestShouldFail = 0, svrTestShouldFail = 0; + /* 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 += strlen(svr_argv[i]) + 2; + 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); #endif return NOT_BUILT_IN; } + if (!IsValidCert(commandLine)) { + #ifdef DEBUG_SUITE_TESTS + printf("certificate %s not supported in build\n", commandLine); + #endif + return NOT_BUILT_IN; + } +#ifndef WOLFSSL_ALLOW_SSLV3 + if (IsSslVersion(commandLine) == 1) { + #ifdef DEBUG_SUITE_TESTS + printf("protocol version on line %s is too old\n", commandLine); + #endif + 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 @@ -168,66 +330,63 @@ static int execute_test_case(int svr_argc, char** svr_argv, } #endif + /* Build Server 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 + 2 > MAX_ARGS) + printf("cannot add the force def cipher list flag to server\n"); + else { + svr_argv[svrArgs.argc++] = intTestFlag; + svr_argv[svrArgs.argc++] = forceDefCipherListFlag; + } + } +#ifdef TEST_PK_PRIVKEY + svr_argv[svrArgs.argc++] = (char*)"-P"; +#endif + + /* update server flags list */ commandLine[0] = '\0'; added = 0; - for (i = 0; i < cli_argc; i++) { - added += strlen(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; - } + printf("trying server command line[%d]: %s\n", tests, commandLine); + + tests++; /* test count */ + + /* determine based on args if this test is expected to fail */ + if (XSTRSTR(commandLine, exitWithRetFlag) != NULL) { + svrTestShouldFail = 1; } - printf("trying client command line[%d]: %s\n", tests++, commandLine); InitTcpReady(&ready); @@ -239,40 +398,98 @@ 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 + 2 > MAX_ARGS) + printf("cannot add the force def cipher list flag to client\n"); + else { + cli_argv[cliArgs.argc++] = intTestFlag; + cli_argv[cliArgs.argc++] = forceDefCipherListFlag; + } + } +#ifdef TEST_PK_PRIVKEY + cli_argv[cliArgs.argc++] = (char*)"-P"; +#endif + + 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); + } + if (!IsValidCA(commandLine)) { + #ifdef DEBUG_SUITE_TESTS + printf("certificate %s not supported in build\n", commandLine); + #endif + return NOT_BUILT_IN; + } + printf("trying client command line[%d]: %s\n", tests, commandLine); + + /* determine based on args if this test is expected to fail */ + if (XSTRSTR(commandLine, exitWithRetFlag) != NULL) { + cliTestShouldFail = 1; + } + /* start client */ client_test(&cliArgs); - /* verify results */ - if (cliArgs.return_code != 0) { + /* verify results */ + if ((cliArgs.return_code != 0 && cliTestShouldFail == 0) || + (cliArgs.return_code == 0 && cliTestShouldFail != 0)) { printf("client_test failed\n"); - exit(EXIT_FAILURE); + XEXIT(EXIT_FAILURE); } join_thread(serverThread); - if (svrArgs.return_code != 0) { + if ((svrArgs.return_code != 0 && svrTestShouldFail == 0) || + (svrArgs.return_code == 0 && svrTestShouldFail != 0)) { printf("server_test failed\n"); - exit(EXIT_FAILURE); + XEXIT(EXIT_FAILURE); } #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif FreeTcpReady(&ready); - + + /* only run the first test for expected failure cases */ + /* the example server/client are not designed to handle expected failure in + all cases, such as non-blocking, etc... */ + if (svrTestShouldFail || cliTestShouldFail) { + return NOT_BUILT_IN; + } + return 0; } @@ -291,20 +508,25 @@ static void test_harness(void* vargs) char* cursor; char* comment; const char* fname = "tests/test.conf"; + const char* addArgs = NULL; if (args->argc == 1) { printf("notice: using default file %s\n", fname); } - else if(args->argc != 2) { - printf("usage: harness [FILE]\n"); + else if (args->argc == 3) { + addArgs = args->argv[2]; + } + else if (args->argc > 3) { + printf("usage: harness [FILE] [ARG]\n"); args->return_code = 1; return; } - else { + + if (args->argc >= 2) { fname = args->argv[1]; } - file = fopen(fname, "r"); + file = fopen(fname, "rb"); if (file == NULL) { fprintf(stderr, "unable to open %s\n", fname); args->return_code = 1; @@ -322,7 +544,7 @@ static void test_harness(void* vargs) script = (char*)malloc(sz+1); if (script == 0) { - fprintf(stderr, "unable to allocte script buffer\n"); + fprintf(stderr, "unable to allocate script buffer\n"); fclose(file); args->return_code = 1; return; @@ -336,7 +558,7 @@ static void test_harness(void* vargs) args->return_code = 1; return; } - + fclose(file); script[sz] = 0; @@ -355,37 +577,31 @@ static void test_harness(void* vargs) to client mode if we don't have the client command yet */ if (cliMode == 0) cliMode = 1; /* switch to client mode processing */ + /* skip extra newlines */ else do_it = 1; /* Do It, we have server and client */ cursor++; break; case '#': - /* Ignore lines that start with a #. */ - comment = strsep(&cursor, "\n"); -#ifdef DEBUG_SUITE_TESTS + /* Ignore lines that start with a # */ + comment = XSTRSEP(&cursor, "\n"); + #ifdef DEBUG_SUITE_TESTS printf("%s\n", comment); -#else + #else (void)comment; -#endif + #endif break; case '-': + default: /* Parameters start with a -. They end in either a newline * or a space. Capture until either, save in Args list. */ if (cliMode) - cliArgs[cliArgsSz++] = strsep(&cursor, " \n"); + cliArgs[cliArgsSz++] = XSTRSEP(&cursor, " \n"); else - svrArgs[svrArgsSz++] = strsep(&cursor, " \n"); + svrArgs[svrArgsSz++] = XSTRSEP(&cursor, " \n"); + if (*cursor == '\0') /* eof */ + do_it = 1; break; - default: - /* Anything from cursor until end of line that isn't the above - * is data for a paramter. Just up until the next newline in - * the Args list. */ - if (cliMode) - cliArgs[cliArgsSz++] = strsep(&cursor, "\n"); - else - svrArgs[svrArgsSz++] = strsep(&cursor, "\n"); - if (*cursor == 0) /* eof */ - do_it = 1; } if (svrArgsSz == MAX_ARGS || cliArgsSz == MAX_ARGS) { @@ -394,12 +610,49 @@ static void test_harness(void* vargs) } if (do_it) { - ret = execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs,0,0); + /* additional arguments processing */ + if (cliArgsSz+2 < MAX_ARGS && svrArgsSz+2 < MAX_ARGS) { + if (addArgs == NULL || XSTRSTR(addArgs, "doDH") == NULL) { + /* The `-2` disable DH prime check is added to all tests by default */ + cliArgs[cliArgsSz++] = disableDHPrimeTest; + svrArgs[svrArgsSz++] = disableDHPrimeTest; + } + if (addArgs && XSTRSTR(addArgs, "expFail")) { + /* Tests should expect to fail */ + cliArgs[cliArgsSz++] = intTestFlag; + cliArgs[cliArgsSz++] = exitWithRetFlag; + svrArgs[svrArgsSz++] = intTestFlag; + svrArgs[svrArgsSz++] = exitWithRetFlag; + } + } + + ret = execute_test_case(svrArgsSz, svrArgs, + cliArgsSz, cliArgs, 0, 0, 0, 0, 0); /* don't repeat if not supported in build */ if (ret == 0) { - execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs, 0, 1); - execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs, 1, 0); - execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs, 1, 1); + /* test with default cipher list on server side */ + execute_test_case(svrArgsSz, svrArgs, + cliArgsSz, cliArgs, 0, 0, 0, 1, 0); + /* test with default cipher list on client side */ + execute_test_case(svrArgsSz, svrArgs, + cliArgsSz, cliArgs, 0, 0, 0, 0, 1); + + execute_test_case(svrArgsSz, svrArgs, + 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, 0, 0); + execute_test_case(svrArgsSz, svrArgs, + cliArgsSz, cliArgs, 0, 1, 1, 0, 0); + execute_test_case(svrArgsSz, svrArgs, + cliArgsSz, cliArgs, 1, 0, 1, 0, 0); + execute_test_case(svrArgsSz, svrArgs, + cliArgsSz, cliArgs, 1, 1, 1, 0, 0); +#endif } svrArgsSz = 1; cliArgsSz = 1; @@ -410,28 +663,71 @@ static void test_harness(void* vargs) free(script); args->return_code = 0; } +#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ -int SuiteTest(void) +int SuiteTest(int argc, char** argv) { +#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) func_args args; - char argv0[2][80]; - char* myArgv[2]; + char argv0[3][80]; + char* myArgv[3]; printf(" Begin Cipher Suite Tests\n"); /* setup */ myArgv[0] = argv0[0]; myArgv[1] = argv0[1]; + myArgv[2] = argv0[2]; args.argv = myArgv; strcpy(argv0[0], "SuiteTest"); - (void)test_harness; +#ifdef WOLFSSL_STATIC_MEMORY + byte memory[200000]; +#endif - cipherSuiteCtx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + cipherSuiteCtx = wolfSSL_CTX_new(wolfSSLv23_client_method()); if (cipherSuiteCtx == NULL) { printf("can't get cipher suite ctx\n"); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; + } + + /* load in static memory buffer if enabled */ +#ifdef WOLFSSL_STATIC_MEMORY + if (wolfSSL_CTX_load_static_memory(&cipherSuiteCtx, NULL, + memory, sizeof(memory), 0, 1) + != WOLFSSL_SUCCESS) { + printf("unable to load static memory and create ctx"); + 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 */ + + /* support for custom command line tests */ + if (argc > 1) { + /* Examples: + ./tests/unit.test tests/test-altchains.conf + ./tests/unit.test tests/test-fails.conf expFail + ./tests/unit.test tests/test-dhprime.conf doDH + */ + args.argc = argc; + args.argv = argv; + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + } + goto exit; } /* default case */ @@ -440,29 +736,296 @@ 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; } /* any extra cases will need another argument */ args.argc = 2; -#ifdef WOLFSSL_DTLS +#ifdef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + /* SHA-2 cipher suites in old TLS versions */ + strcpy(argv0[1], "tests/test-sha2.conf"); + printf("starting SHA-2 cipher suite in old TLS versions tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } +#endif + +#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); + args.return_code = EXIT_FAILURE; + goto exit; + } + #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); + args.return_code = EXIT_FAILURE; + goto exit; + } + #endif + #ifndef WOLFSSL_NO_TLS12 + /* add TLSv13 downgrade tets */ + strcpy(argv0[1], "tests/test-tls13-down.conf"); + printf("starting TLSv13 Downgrade extra tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + #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); + args.return_code = EXIT_FAILURE; + goto exit; + } +#endif +#if defined(HAVE_CURVE448) && defined(HAVE_ED448) + /* add ED448 certificate cipher suite tests */ + strcpy(argv0[1], "tests/test-ed448.conf"); + printf("starting ED448 extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } +#endif +#ifdef WOLFSSL_DTLS /* add dtls extra suites */ strcpy(argv0[1], "tests/test-dtls.conf"); printf("starting dtls 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); + args.return_code = EXIT_FAILURE; + goto exit; + } +#ifdef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + /* add dtls extra suites */ + strcpy(argv0[1], "tests/test-dtls-sha2.conf"); + printf("starting dtls extra cipher suite tests - old TLS sha-2 cs\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } +#endif +#endif +#ifdef WOLFSSL_SCTP + /* add dtls-sctp extra suites */ + strcpy(argv0[1], "tests/test-sctp.conf"); + printf("starting dtls-sctp extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } +#ifdef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + /* add dtls-sctp extra suites */ + strcpy(argv0[1], "tests/test-sctp-sha2.conf"); + printf("starting dtls-sctp extra cipher suite tests - old TLS sha-2 cs\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } +#endif +#endif +#ifndef WC_STRICT_SIG +#if !defined(NO_RSA) && defined(HAVE_ECC) /* testing mixed ECC/RSA cert */ + /* add extra signature test suites */ + strcpy(argv0[1], "tests/test-sig.conf"); + printf("starting sig extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } +#endif /* HAVE_RSA and HAVE_ECC */ +#endif /* !WC_STRICT_SIG */ +#ifdef HAVE_QSH + /* add QSH extra suites */ + strcpy(argv0[1], "tests/test-qsh.conf"); + printf("starting qsh extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } +#ifdef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES + strcpy(argv0[1], "tests/test-qsh-sha2.conf"); + printf("starting qsh extra cipher suite tests - old TLS sha-2 cs\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } +#endif +#endif +#ifndef NO_PSK + #ifndef WOLFSSL_NO_TLS12 + #if !defined(NO_RSA) || defined(HAVE_ECC) + /* add psk cipher suites */ + strcpy(argv0[1], "tests/test-psk.conf"); + printf("starting psk cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + #endif + #endif + #ifdef WOLFSSL_TLS13 + /* add psk extra suites */ + strcpy(argv0[1], "tests/test-tls13-psk.conf"); + printf("starting TLS 1.3 psk no identity extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + #endif +#endif +#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_DES3) && !defined(NO_MD5) &&\ + !defined(NO_SHA) + /* test encrypted keys */ + strcpy(argv0[1], "tests/test-enckeys.conf"); + printf("starting encrypted keys extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; } #endif +#ifdef HAVE_MAX_FRAGMENT + /* Max fragment cipher suite tests */ + strcpy(argv0[1], "tests/test-maxfrag.conf"); + printf("starting max fragment cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + + #ifdef WOLFSSL_DTLS + strcpy(argv0[1], "tests/test-maxfrag-dtls.conf"); + printf("starting dtls max fragment cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + #endif +#endif + +#ifdef WOLFSSL_ALT_CERT_CHAINS + /* tests for alt chains */ + strcpy(argv0[1], "tests/test-altchains.conf"); + printf("starting certificate alternate chain cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } +#else + /* tests for chains */ + strcpy(argv0[1], "tests/test-chains.conf"); + printf("starting certificate chain cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } +#endif + +#ifdef WOLFSSL_TRUST_PEER_CERT + /* tests for trusted peer cert */ + strcpy(argv0[1], "tests/test-trustpeer.conf"); + printf("starting trusted peer certificate cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } +#endif + + /* tests for dh prime */ + args.argc = 3; + strcpy(argv0[1], "tests/test-dhprime.conf"); + strcpy(argv0[2], "doDH"); /* add DH prime flag */ + printf("starting tests that expect failure\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + + /* failure tests */ + args.argc = 3; + strcpy(argv0[1], "tests/test-fails.conf"); + strcpy(argv0[2], "expFail"); /* tests are expected to fail */ + printf("starting tests that expect failure\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + +exit: printf(" End Cipher Suite Tests\n"); wolfSSL_CTX_free(cipherSuiteCtx); wolfSSL_Cleanup(); +#if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) \ + && (defined(NO_MAIN_DRIVER) || defined(HAVE_STACK_SIZE)) + wc_ecc_fp_free(); /* free per thread cache */ +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + return args.return_code; +#else + return NOT_COMPILED_IN; +#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ + (void)argc; + (void)argv; } - - diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-altchains.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-altchains.conf new file mode 100644 index 000000000..9bd52741d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-altchains.conf @@ -0,0 +1,245 @@ +# Tests will use complete chain with intermediate CA for testing +# The tests with chains have the CRL checking disabled +# CRL's only load for trusted CA's, for a chain you must load the root and intermediate as trusted +# For these tests we are loading root and sending intermediate and peer certs +# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Chain +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-chain.pem +-V + +# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Chain +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-chain.pem +-C + +# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Chain +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-chain.pem +-V + +# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Chain +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-chain.pem +-C + +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Chain +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-chain-ecc.pem +-V + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Chain +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-chain-ecc.pem +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-chain.pem +-V + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-chain.pem +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-chain-ecc.pem +-V + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-chain-ecc.pem +-C + +# Test will load intermediate CA as trusted and only present the peer cert (partial chain) +# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Partial Chain +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-int-cert.pem +-V + +# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Partial Chain +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-int-cert.pem +-C + +# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Partial Chain +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-int-cert.pem +-V + +# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Partial Chain +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-int-cert.pem +-C + +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Partial Chain +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-int-ecc-cert.pem +-V + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Partial Chain +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-int-ecc-cert.pem +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Partial Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-int-cert.pem +-V + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Partial Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-int-cert.pem +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Partial Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-int-ecc-cert.pem +-V + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Partial Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-int-ecc-cert.pem +-C + +# Test will use alternate chain where chain contains extra cert +# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Alt Chain +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-chain-alt.pem +-V + +# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Alt Chain +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-chain-alt.pem +-C + +# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Alt Chain +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-chain-alt.pem +-V + +# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Alt Chain +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-chain-alt.pem +-C + +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Alt Chain +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-chain-alt-ecc.pem +-V + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Alt Chain +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-chain-alt-ecc.pem +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Alt Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-chain-alt.pem +-V + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Alt Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-chain-alt.pem +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Alt Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-chain-alt-ecc.pem +-V + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Alt Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-chain-alt-ecc.pem +-C diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-chains.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-chains.conf new file mode 100644 index 000000000..879d9288d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-chains.conf @@ -0,0 +1,384 @@ +# Tests will use complete chain with intermediate CA for testing +# The tests with chains have the CRL checking disabled +# CRL's only load for trusted CA's, for a chain you must load the root and intermediate as trusted +# For these tests we are loading root and sending intermediate and peer certs +# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Chain +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-chain.pem +-V + +# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Chain +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-chain.pem +-C + +# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Chain +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-chain.pem +-V + +# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Chain +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-chain.pem +-C + +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Chain +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-chain-ecc.pem +-V + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Chain +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-chain-ecc.pem +-C + +# server TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/test-pathlen/chainA-entity-key.pem +-c ./certs/test-pathlen/chainA-assembled.pem +-V + +# client TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-C + +# server TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/test-pathlen/chainB-entity-key.pem +-c ./certs/test-pathlen/chainB-assembled.pem +-V + +# client TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-C + +# server TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/test-pathlen/chainC-entity-key.pem +-c ./certs/test-pathlen/chainC-assembled.pem +-V + +# client TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-C + +# server TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/test-pathlen/chainD-entity-key.pem +-c ./certs/test-pathlen/chainD-assembled.pem +-V + +# client TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-C + +# server TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/test-pathlen/chainE-entity-key.pem +-c ./certs/test-pathlen/chainE-assembled.pem +-H exitWithRet +-V + +# client TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-H exitWithRet +-C + +# server TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/test-pathlen/chainF-entity-key.pem +-c ./certs/test-pathlen/chainF-assembled.pem +-H exitWithRet +-V + +# client TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-H exitWithRet +-C + +# server TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/test-pathlen/chainG-entity-key.pem +-c ./certs/test-pathlen/chainG-assembled.pem +-V + +# client TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-C + +# server TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/test-pathlen/chainH-entity-key.pem +-c ./certs/test-pathlen/chainH-assembled.pem +-H exitWithRet +-V + +# client TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-H exitWithRet +-C + +# server TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/test-pathlen/chainI-entity-key.pem +-c ./certs/test-pathlen/chainI-assembled.pem +-V + +# client TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-C + +# server TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/test-pathlen/chainJ-entity-key.pem +-c ./certs/test-pathlen/chainJ-assembled.pem +-H exitWithRet +-V + +# client TLSv1.2 pathLen constraint test +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-H exitWithRet +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-chain.pem +-V + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-chain.pem +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-chain-ecc.pem +-V + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-chain-ecc.pem +-C + +# Test will load intermediate CA as trusted and only present the peer cert (partial chain) +# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Partial Chain +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-int-cert.pem +-V + +# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Partial Chain +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-int-cert.pem +-C + +# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Partial Chain +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-int-cert.pem +-V + +# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Partial Chain +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-int-cert.pem +-C + +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Partial Chain +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-int-ecc-cert.pem +-V + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Partial Chain +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-int-ecc-cert.pem +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Partial Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-int-cert.pem +-V + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Partial Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-int-cert.pem +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Partial Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-int-ecc-cert.pem +-V + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Partial Chain +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/intermediate/ca-int-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-int-ecc-cert.pem +-C + +# Test will use alternate chain where chain contains extra cert +# These tests should fail +# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Alt Chain Fail +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-chain-alt.pem +-H exitWithRet +-V + +# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Alt Chain Fail +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-chain-alt.pem +-H exitWithRet +-C + +# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Alt Chain Fail +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-chain-alt.pem +-H exitWithRet +-V + +# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Alt Chain Fail +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-chain-alt.pem +-H exitWithRet +-C + +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Alt Chain Fail +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-chain-alt-ecc.pem +-H exitWithRet +-V + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Alt Chain Fail +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-chain-alt-ecc.pem +-H exitWithRet +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Alt Chain Fail +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-chain-alt.pem +-H exitWithRet +-V + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Alt Chain Fail +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-chain-alt.pem +-H exitWithRet +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Alt Chain Fail +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-chain-alt-ecc.pem +-H exitWithRet +-V + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Alt Chain Fail +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-chain-alt-ecc.pem +-H exitWithRet +-C diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-dhprime.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-dhprime.conf new file mode 100644 index 000000000..f43739ed0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-dhprime.conf @@ -0,0 +1,25 @@ +# server TLSv1.2 DHE AES128 (DHE prime test) +-v 3 +-l DHE-RSA-AES128-SHA + +# client TLSv1.2 DHE AES128 (DHE prime test) +-v 3 +-l DHE-RSA-AES128-SHA + +# server TLSv1.2 DHE AES256-SHA256 (DHE prime test) +-v 3 +-l DHE-RSA-AES256-SHA256 + +# client TLSv1.2 DHE AES256-SHA256 (DHE prime test) +-v 3 +-l DHE-RSA-AES256-SHA256 + +# server TLSv1.2 DHE-PSK-AES128-CBC-SHA256 (DHE prime test) +-s +-v 3 +-l DHE-PSK-AES128-CBC-SHA256 + +# client TLSv1.2 DHE-PSK-AES128-CBC-SHA256 (DHE prime test) +-s +-v 3 +-l DHE-PSK-AES128-CBC-SHA256 diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-dtls-sha2.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-dtls-sha2.conf new file mode 100644 index 000000000..f5bf6e77c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-dtls-sha2.conf @@ -0,0 +1,66 @@ +# server DTLSv1 AES128-SHA256 +-u +-v 2 +-l AES128-SHA256 + +# client DTLSv1 AES128-SHA256 +-u +-v 2 +-l AES128-SHA256 + +# server DTLSv1 AES256-SHA256 +-u +-v 2 +-l AES256-SHA256 + +# client DTLSv1 AES256-SHA256 +-u +-v 2 +-l AES256-SHA256 + +# server TLSv1 ECDHE-PSK-AES128-SHA256 +-s +-u +-v 1 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1 ECDHE-PSK-AES128-SHA256 +-s +-u +-v 1 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1.1 ECDHE-PSK-AES128-SHA256 +-s +-u +-v 2 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1.1 ECDHE-PSK-AES128-SHA256 +-s +-u +-v 2 +-l ECDHE-PSK-AES128-SHA256 +# server TLSv1 ECDHE-PSK-NULL-SHA256 +-s +-u +-v 1 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1 ECDHE-PSK-NULL-SHA256 +-s +-u +-v 1 +-l ECDHE-PSK-NULL-SHA256 + +# server TLSv1.1 ECDHE-PSK-NULL-SHA256 +-s +-u +-v 2 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1.1 ECDHE-PSK-NULL-SHA256 +-s +-u +-v 2 +-l ECDHE-PSK-NULL-SHA256 diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-dtls.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-dtls.conf index 7a9c041e5..ddf658c54 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/tests/test-dtls.conf +++ b/FreeRTOS-Plus/Source/WolfSSL/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 @@ -43,7 +10,7 @@ # server DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 -u --v 3 +-v 3 -l ECDHE-RSA-CHACHA20-POLY1305 # client DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 @@ -62,27 +29,86 @@ -u -v 3 -l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem +-A ./certs/ca-ecc-cert.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 +# server TLSv1.2 DHE-PSK-CHACHA20-POLY1305 -u -v 3 --l RC4-SHA +-s +-l DHE-PSK-CHACHA20-POLY1305 -# client DTLSv1.2 RC4-SHA +# client TLSv1.2 DHE-PSK-CHACHA20-POLY1305 -u -v 3 --l RC4-SHA +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-u +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-u +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 PSK-CHACHA20-POLY1305 +-u +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# client TLSv1.2 PSK-CHACHA20-POLY1305 +-u +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-u +-v 3 +-l DHE-RSA-CHACHA20-POLY1305-OLD + +# client DTLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-u +-v 3 +-l DHE-RSA-CHACHA20-POLY1305-OLD + +# server DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-u +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305-OLD + +# client DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-u +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305-OLD + +# server DTLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305-OLD +-u +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-u +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1 IDEA-CBC-SHA +-u +-v 2 +-l IDEA-CBC-SHA + +# client DTLSv1 IDEA-CBC-SHA +-u +-v 2 +-l IDEA-CBC-SHA # server DTLSv1 DES-CBC3-SHA -u @@ -144,16 +170,6 @@ -v 3 -l AES256-SHA -# server DTLSv1 AES128-SHA256 --u --v 2 --l AES128-SHA256 - -# client DTLSv1 AES128-SHA256 --u --v 2 --l AES128-SHA256 - # server DTLSv1.2 AES128-SHA256 -u -v 3 @@ -164,16 +180,6 @@ -v 3 -l AES128-SHA256 -# server DTLSv1 AES256-SHA256 --u --v 2 --l AES256-SHA256 - -# client DTLSv1 AES256-SHA256 --u --v 2 --l AES256-SHA256 - # server DTLSv1.2 AES256-SHA256 -u -v 3 @@ -184,16 +190,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 @@ -204,12 +200,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 @@ -224,16 +220,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 @@ -244,12 +230,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 @@ -259,7 +245,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 @@ -274,18 +260,44 @@ -v 3 -l ECDHE-RSA-AES256-SHA -# server DTLSv1.1 ECDHE-EDCSA-RC4 +# server TLSv1 ECDHE-ECDSA-NULL-SHA -u --v 2 --l ECDHE-ECDSA-RC4-SHA +-v 1 +-l ECDHE-ECDSA-NULL-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.1 ECDHE-ECDSA-RC4 +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-u +-v 1 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDHE-ECDSA-NULL-SHA -u -v 2 --l ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-u +-v 2 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-NULL-SHA +-u +-v 3 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-NULL-SHA +-u +-v 3 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem # server DTLSv1.1 ECDHE-ECDSA-DES3 -u @@ -298,20 +310,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 @@ -324,20 +336,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 @@ -350,20 +349,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 @@ -376,7 +375,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 @@ -389,19 +388,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 @@ -415,14 +402,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 @@ -439,18 +426,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 @@ -463,26 +438,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 @@ -499,19 +474,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 @@ -523,20 +485,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 @@ -549,20 +511,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 @@ -575,20 +524,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 @@ -597,11 +546,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 @@ -614,14 +563,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 @@ -637,16 +586,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 @@ -658,11 +607,35 @@ -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.2 ECDHE-PSK-AES128-SHA256 +-s +-u +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-u +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-u +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-u +-v 3 +-l ECDHE-PSK-NULL-SHA256 # server DTLSv1 PSK-AES128 -s @@ -736,18 +709,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 @@ -760,20 +733,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 @@ -786,14 +759,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 @@ -808,14 +781,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 @@ -856,6 +829,19 @@ -v 3 -l PSK-AES256-GCM-SHA384 +# server DTLSv1.2 ECDHE-ECDSA-AES128-CCM +-u +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-CCM +-u +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-A ./certs/ca-ecc-cert.pem + # server DTLSv1.2 ECDHE-ECDSA-AES128-CCM-8 -u -v 3 @@ -867,7 +853,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 @@ -880,7 +866,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 @@ -905,4 +891,3 @@ -a -v 2 -l ADH-AES128-SHA - diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-ed25519.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-ed25519.conf new file mode 100644 index 000000000..8de0037bd --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-ed25519.conf @@ -0,0 +1,71 @@ +# 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 + +# 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-priv.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ed25519/root-ed25519.pem +-C + +# 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 +-V +# Remove -V when CRL for ED25519 certificates available. + +# 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 +-V +# Remove -V when CRL for ED25519 certificates available. + +# 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/FreeRTOS-Plus/Source/WolfSSL/tests/test-ed448.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-ed448.conf new file mode 100644 index 000000000..255e189a6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-ed448.conf @@ -0,0 +1,59 @@ +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/ed448/server-ed448.pem +-k ./certs/ed448/server-ed448-priv.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ed448/root-ed448.pem +-C + +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/ed448/server-ed448.pem +-k ./certs/ed448/server-ed448-priv.pem +-A ./certs/ed448/client-ed448.pem +-V +# Remove -V when CRL for ED448 certificates available. + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/ed448/client-ed448.pem +-k ./certs/ed448/client-ed448-priv.pem +-A ./certs/ed448/root-ed448.pem +-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/ed448/server-ed448.pem +-k ./certs/ed448/server-ed448-priv.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ed448/root-ed448.pem +-C + +# Enable when CRL for ED448 certificates available. +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/ed448/server-ed448.pem +-k ./certs/ed448/server-ed448-priv.pem +-A ./certs/ed448/client-ed448.pem +-V +# Remove -V when CRL for ED448 certificates available. + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/ed448/client-ed448.pem +-k ./certs/ed448/client-ed448-priv.pem +-A ./certs/ed448/root-ed448.pem +-C + diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-enckeys.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-enckeys.conf new file mode 100644 index 000000000..9e371c239 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-enckeys.conf @@ -0,0 +1,42 @@ +# server RSA encrypted key +-v 3 +-k ./certs/server-keyEnc.pem + +# client RSA encrypted key +-v 3 +-k ./certs/client-keyEnc.pem + +# server RSA encrypted key PKCS8 +-v 3 +-k ./certs/server-keyPkcs8Enc.pem + +# client RSA encrypted key +-v 3 +-k ./certs/client-keyEnc.pem + +# server RSA encrypted key PKCS8 2 +-v 3 +-k ./certs/server-keyPkcs8Enc2.pem + +# client RSA encrypted key +-v 3 +-k ./certs/client-keyEnc.pem + +# server RSA encrypted key PKCS8 12 +-v 3 +-k ./certs/server-keyPkcs8Enc12.pem + +# client RSA encrypted key +-v 3 +-k ./certs/client-keyEnc.pem + +# server TLSv1.2 ECDHE-ECDSA-AES128-SHA256 PKCS8 encrypted key +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-keyPkcs8Enc.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-A ./certs/ca-ecc-cert.pem diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-fails.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-fails.conf new file mode 100644 index 000000000..d8ea91fd4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-fails.conf @@ -0,0 +1,179 @@ +# server bad certificate common name has null +# DG: Have not found a way to properly encode null in common name +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/server-key.pem +-c ./certs/test/server-badcnnull.pem +-d + +# client bad certificate common name has null +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-h localhost +-A ./certs/test/server-badcnnull.pem +-m +-x + +# server bad certificate alternate name has null +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/server-key.pem +-c ./certs/test/server-badaltnull.pem +-d + +# client bad certificate alternate name has null +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-h localhost +-A ./certs/test/server-badaltnull.pem +-m +-x + +# server nomatch common name +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/server-key.pem +-c ./certs/test/server-badcn.pem +-d + +# client nomatch common name +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-h localhost +-A ./certs/test/server-badcn.pem +-m +-x + +# server nomatch alternate name +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/server-key.pem +-c ./certs/test/server-badaltname.pem +-d + +# client nomatch alternate name +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-h localhost +-A ./certs/test/server-badaltname.pem +-m +-x + +# server RSA no signer error +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# client RSA no signer error +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-A ./certs/client-cert.pem + +# server ECC no signer error +#-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client ECC no signer error +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/client-ecc-cert.pem + +# server RSA bad sig error +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-c ./certs/test/server-cert-rsa-badsig.pem + +# client RSA bad sig error +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# server ECC bad sig error +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/test/server-cert-ecc-badsig.pem + +# client ECC bad sig error +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 + +# server missing CN from alternate names list +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-c ./certs/test/server-garbage.pem + +# client missing CN from alternate names list +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-h localhost +-A ./certs/test/server-garbage.pem +-m + +# Verify Callback Failure Tests +# no error going into callback, return error +# server +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# client verify should fail +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-H verifyFail + +# server verify should fail +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-H verifyFail + +# client +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# server +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 + +# client verify should fail +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-H verifyFail + +# server verify should fail +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-H verifyFail + +# client +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 + +# error going into callback, return error +# server +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-c ./certs/test/server-cert-rsa-badsig.pem +-k ./certs/server-key.pem + +# client verify should fail +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-H verifyFail + +# server +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/test/server-cert-ecc-badsig.pem +-k ./certs/ecc-key.pem + +# client verify should fail +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-H verifyFail + +# server send alert on no mutual authentication +-v 3 +-F + +# client send alert on no mutual authentication +-v 3 +-x diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-maxfrag-dtls.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-maxfrag-dtls.conf new file mode 100644 index 000000000..67aef1776 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-maxfrag-dtls.conf @@ -0,0 +1,215 @@ +# server DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem +-F 1 + +# server DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-F 1 + +# server DTLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 +-F 1 + +# server DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem +-F 2 + +# server DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-F 2 + +# server DTLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 +-F 2 + +# server DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem +-F 3 + +# server DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-F 3 + +# server DTLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 +-F 3 + +# server DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem +-F 4 + +# server DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-F 4 + +# server DTLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 +-F 4 + +# server DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem +-F 5 + +# server DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-F 5 + +# server DTLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 +-F 5 + +# server DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem +-F 6 + +# server DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-F 6 + +# server DTLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-u +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 +-F 6 diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-maxfrag.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-maxfrag.conf new file mode 100644 index 000000000..2ca6cc8dd --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-maxfrag.conf @@ -0,0 +1,179 @@ +# server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem +-F 1 + +# server TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-F 1 + +# server TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 +-F 1 + +# server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem +-F 2 + +# server TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-F 2 + +# server TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 +-F 2 + +# server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem +-F 3 + +# server TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-F 3 + +# server TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 +-F 3 + +# server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem +-F 4 + +# server TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-F 4 + +# server TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 +-F 4 + +# server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem +-F 5 + +# server TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-F 5 + +# server TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 +-F 5 + +# server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem +-F 6 + +# server TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 +-F 6 + +# server TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 +-F 6 diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-psk-no-id-sha2.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-psk-no-id-sha2.conf new file mode 100644 index 000000000..73c6f073a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-psk-no-id-sha2.conf @@ -0,0 +1,87 @@ +# No Hint server TLSv1 ECDHE-PSK-AES128-SHA256 +-s +-I +-v 1 +-l ECDHE-PSK-AES128-SHA256 + +# No Hint client TLSv1 ECDHE-PSK-AES128-SHA256 +-s +-v 1 +-l ECDHE-PSK-AES128-SHA256 + +# No Hint server TLSv1.1 ECDHE-PSK-AES128-SHA256 +-s +-I +-v 2 +-l ECDHE-PSK-AES128-SHA256 + +# No Hint client TLSv1.1 ECDHE-PSK-AES128-SHA256 +-s +-v 2 +-l ECDHE-PSK-AES128-SHA256 + +# No Hint server TLSv1 ECDHE-PSK-NULL-SHA256 +-s +-I +-v 1 +-l ECDHE-PSK-NULL-SHA256 + +# No Hint client TLSv1 ECDHE-PSK-NULL-SHA256 +-s +-v 1 +-l ECDHE-PSK-NULL-SHA256 + +# No Hint server TLSv1.1 ECDHE-PSK-NULL-SHA256 +-s +-I +-v 2 +-l ECDHE-PSK-NULL-SHA256 + +# No Hint client TLSv1.1 ECDHE-PSK-NULL-SHA256 +-s +-v 2 +-l ECDHE-PSK-NULL-SHA256 + +# No Hint server TLSv1.0 PSK-AES128-SHA256 +-s +-I +-v 1 +-l PSK-AES128-CBC-SHA256 + +# No Hint client TLSv1.0 PSK-AES128-SHA256 +-s +-v 1 +-l PSK-AES128-CBC-SHA256 + +# No Hint server TLSv1.1 PSK-AES128-SHA256 +-s +-I +-v 2 +-l PSK-AES128-CBC-SHA256 + +# No Hint client TLSv1.1 PSK-AES128-SHA256 +-s +-v 2 +-l PSK-AES128-CBC-SHA256 + + No Hint server TLSv1.0 PSK-AES256-SHA384 +-s +-I +-v 1 +-l PSK-AES256-CBC-SHA384 + +# No Hint client TLSv1.0 PSK-AES256-SHA384 +-s +-v 1 +-l PSK-AES256-CBC-SHA384 + +# No Hint server TLSv1.1 PSK-AES256-SHA384 +-s +-I +-v 2 +-l PSK-AES256-CBC-SHA384 + +# No Hint client TLSv1.1 PSK-AES256-SHA384 +-s +-v 2 +-l PSK-AES256-CBC-SHA384 diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-psk-no-id.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-psk-no-id.conf new file mode 100644 index 000000000..fc9f74654 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-psk-no-id.conf @@ -0,0 +1,214 @@ +# No Hint server TLSv1.2 PSK-CHACHA20-POLY1305 +-s +-I +-v 3 +-l PSK-CHACHA20-POLY1305 + +# No Hint client TLSv1.2 PSK-CHACHA20-POLY1305 +-s +-v 3 +-l PSK-CHACHA20-POLY1305 + +# No Hint server TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-s +-I +-v 3 +-l DHE-PSK-CHACHA20-POLY1305 + +# No Hint client TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-s +-v 3 +-l DHE-PSK-CHACHA20-POLY1305 + +# No Hint server TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-s +-I +-v 3 +-l ECDHE-PSK-CHACHA20-POLY1305 + +# No Hint client TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-s +-v 3 +-l ECDHE-PSK-CHACHA20-POLY1305 + +# No Hint server TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-I +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# No Hint client TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# No Hint server TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-I +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# No Hint client TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# No Hint server TLSv1 PSK-AES128 +-s +-I +-v 1 +-l PSK-AES128-CBC-SHA + +# No Hint client TLSv1 PSK-AES128 +-s +-v 1 +-l PSK-AES128-CBC-SHA + +# No Hint server TLSv1 PSK-AES256 +-s +-I +-v 1 +-l PSK-AES256-CBC-SHA + +# No Hint client TLSv1 PSK-AES256 +-s +-v 1 +-l PSK-AES256-CBC-SHA + +# No Hint server TLSv1.1 PSK-AES128 +-s +-I +-v 2 +-l PSK-AES128-CBC-SHA + +# No Hint client TLSv1.1 PSK-AES128 +-s +-v 2 +-l PSK-AES128-CBC-SHA + +# No Hint server TLSv1.1 PSK-AES256 +-s +-I +-v 2 +-l PSK-AES256-CBC-SHA + +# No Hint client TLSv1.1 PSK-AES256 +-s +-v 2 +-l PSK-AES256-CBC-SHA + +# No Hint server TLSv1.2 PSK-AES128 +-s +-I +-v 3 +-l PSK-AES128-CBC-SHA + +# No Hint client TLSv1.2 PSK-AES128 +-s +-v 3 +-l PSK-AES128-CBC-SHA + +# No Hint server TLSv1.2 PSK-AES256 +-s +-I +-v 3 +-l PSK-AES256-CBC-SHA + +# No Hint client TLSv1.2 PSK-AES256 +-s +-v 3 +-l PSK-AES256-CBC-SHA + +# No Hint server TLSv1.2 PSK-AES128-SHA256 +-s +-I +-v 3 +-l PSK-AES128-CBC-SHA256 + +# No Hint client TLSv1.2 PSK-AES128-SHA256 +-s +-v 3 +-l PSK-AES128-CBC-SHA256 + +# No Hint server TLSv1.2 PSK-AES256-SHA384 +-s +-I +-v 3 +-l PSK-AES256-CBC-SHA384 + +# No Hint client TLSv1.2 PSK-AES256-SHA384 +-s +-v 3 +-l PSK-AES256-CBC-SHA384 + +# server TLSv1.2 PSK-AES128-GCM-SHA256 +-s +-I +-v 3 +-l PSK-AES128-GCM-SHA256 + +# client TLSv1.2 PSK-AES128-GCM-SHA256 +-s +-v 3 +-l PSK-AES128-GCM-SHA256 + +# server TLSv1.2 PSK-AES256-GCM-SHA384 +-s +-I +-v 3 +-l PSK-AES256-GCM-SHA384 + +# client TLSv1.2 PSK-AES256-GCM-SHA384 +-s +-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/FreeRTOS-Plus/Source/WolfSSL/tests/test-psk.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-psk.conf new file mode 100644 index 000000000..f4f11b298 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-psk.conf @@ -0,0 +1,7 @@ +# server - PSK plus certificates +-j +-l PSK-CHACHA20-POLY1305 + +# client- standard PSK +-s +-l PSK-CHACHA20-POLY1305 diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-qsh-sha2.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-qsh-sha2.conf new file mode 100644 index 000000000..921f098be --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-qsh-sha2.conf @@ -0,0 +1,303 @@ +# server TLSv1 AES128-SHA256 +-v 1 +-l QSH:AES128-SHA256 + +# client TLSv1 AES128-SHA256 +-v 1 +-l QSH:AES128-SHA256 + +# server TLSv1 AES256-SHA256 +-v 1 +-l QSH:AES256-SHA256 + +# client TLSv1 AES256-SHA256 +-v 1 +-l QSH:AES256-SHA256 + +# server TLSv1.1 AES128-SHA256 +-v 2 +-l QSH:AES128-SHA256 + +# client TLSv1.1 AES128-SHA256 +-v 2 +-l QSH:AES128-SHA256 + +# server TLSv1.1 AES256-SHA256 +-v 2 +-l QSH:AES256-SHA256 + +# client TLSv1.1 AES256-SHA256 +-v 2 +-l QSH:AES256-SHA256 + +# server TLSv1 DHE AES128-SHA256 +-v 1 +-l QSH:DHE-RSA-AES128-SHA256 + +# client TLSv1 DHE AES128-SHA256 +-v 1 +-l QSH:DHE-RSA-AES128-SHA256 + +# server TLSv1 DHE AES256-SHA256 +-v 1 +-l QSH:DHE-RSA-AES256-SHA256 + +# client TLSv1 DHE AES256-SHA256 +-v 1 +-l QSH:DHE-RSA-AES256-SHA256 + +# server TLSv1.1 DHE AES128-SHA256 +-v 2 +-l QSH:DHE-RSA-AES128-SHA256 + +# client TLSv1.1 DHE AES128-SHA256 +-v 2 +-l QSH:DHE-RSA-AES128-SHA256 + +# server TLSv1.1 DHE AES256-SHA256 +-v 2 +-l QSH:DHE-RSA-AES256-SHA256 + +# client TLSv1.1 DHE AES256-SHA256 +-v 2 +-l QSH:DHE-RSA-AES256-SHA256 + +# server TLSv1 ECDHE-PSK-AES128-SHA256 +-s +-v 1 +-l QSH:ECDHE-PSK-AES128-SHA256 + +# client TLSv1 ECDHE-PSK-AES128-SHA256 +-s +-v 1 +-l QSH:ECDHE-PSK-AES128-SHA256 + +# server TLSv1.1 ECDHE-PSK-AES128-SHA256 +-s +-v 2 +-l QSH:ECDHE-PSK-AES128-SHA256 + +# client TLSv1.1 ECDHE-PSK-AES128-SHA256 +-s +-v 2 +-l QSH:ECDHE-PSK-AES128-SHA256 + +# server TLSv1 ECDHE-PSK-NULL-SHA256 +-s +-v 1 +-l QSH:ECDHE-PSK-NULL-SHA256 + +# client TLSv1 ECDHE-PSK-NULL-SHA256 +-s +-v 1 +-l QSH:ECDHE-PSK-NULL-SHA256 + +# server TLSv1.1 ECDHE-PSK-NULL-SHA256 +-s +-v 2 +-l QSH:ECDHE-PSK-NULL-SHA256 + +# client TLSv1.1 ECDHE-PSK-NULL-SHA256 +-s +-v 2 +-l QSH:ECDHE-PSK-NULL-SHA256 + +# server TLSv1.0 PSK-AES128-SHA256 +-s +-v 1 +-l QSH:PSK-AES128-CBC-SHA256 + +# client TLSv1.0 PSK-AES128-SHA256 +-s +-v 1 +-l QSH:PSK-AES128-CBC-SHA256 + +# server TLSv1.1 PSK-AES128-SHA256 +-s +-v 2 +-l QSH:PSK-AES128-CBC-SHA256 + +# client TLSv1.1 PSK-AES128-SHA256 +-s +-v 2 +-l QSH:PSK-AES128-CBC-SHA256 + +# server TLSv1.0 PSK-AES256-SHA384 +-s +-v 1 +-l QSH:PSK-AES256-CBC-SHA384 + +# client TLSv1.0 PSK-AES256-SHA384 +-s +-v 1 +-l QSH:PSK-AES256-CBC-SHA384 + +# server TLSv1.1 PSK-AES256-SHA384 +-s +-v 2 +-l QSH:PSK-AES256-CBC-SHA384 + +# client TLSv1.1 PSK-AES256-SHA384 +-s +-v 2 +-l QSH:PSK-AES256-CBC-SHA384 + +# server TLSv1.0 RSA-NULL-SHA256 +-v 1 +-l QSH:NULL-SHA256 + +# client TLSv1.0 RSA-NULL-SHA256 +-v 1 +-l QSH:NULL-SHA256 + +# server TLSv1.1 RSA-NULL-SHA256 +-v 2 +-l QSH:NULL-SHA256 + +# client TLSv1.1 RSA-NULL-SHA256 +-v 2 +-l QSH:NULL-SHA256 + +# server TLSv1 CAMELLIA128-SHA256 +-v 1 +-l QSH:CAMELLIA128-SHA256 + +# client TLSv1 CAMELLIA128-SHA256 +-v 1 +-l QSH:CAMELLIA128-SHA256 + +# server TLSv1 CAMELLIA256-SHA256 +-v 1 +-l QSH:CAMELLIA256-SHA256 + +# client TLSv1 CAMELLIA256-SHA256 +-v 1 +-l QSH:CAMELLIA256-SHA256 + +# server TLSv1.1 CAMELLIA128-SHA256 +-v 2 +-l QSH:CAMELLIA128-SHA256 + +# client TLSv1.1 CAMELLIA128-SHA256 +-v 2 +-l QSH:CAMELLIA128-SHA256 + +# server TLSv1.1 CAMELLIA256-SHA256 +-v 2 +-l QSH:CAMELLIA256-SHA256 + +# client TLSv1.1 CAMELLIA256-SHA256 +-v 2 +-l QSH:CAMELLIA256-SHA256 + +# server TLSv1 DHE-RSA-CAMELLIA128-SHA256 +-v 1 +-l QSH:DHE-RSA-CAMELLIA128-SHA256 + +# client TLSv1 DHE-RSA-CAMELLIA128-SHA256 +-v 1 +-l QSH:DHE-RSA-CAMELLIA128-SHA256 + +# server TLSv1 DHE-RSA-CAMELLIA256-SHA256 +-v 1 +-l QSH:DHE-RSA-CAMELLIA256-SHA256 + +# client TLSv1 DHE-RSA-CAMELLIA256-SHA256 +-v 1 +-l QSH:DHE-RSA-CAMELLIA256-SHA256 + +# server TLSv1.1 DHE-RSA-CAMELLIA128-SHA256 +-v 2 +-l QSH:DHE-RSA-CAMELLIA128-SHA256 + +# client TLSv1.1 DHE-RSA-CAMELLIA128-SHA256 +-v 2 +-l QSH:DHE-RSA-CAMELLIA128-SHA256 + +# server TLSv1.1 DHE-RSA-CAMELLIA256-SHA256 +-v 2 +-l QSH:DHE-RSA-CAMELLIA256-SHA256 + +# client TLSv1.1 DHE-RSA-CAMELLIA256-SHA256 +-v 2 +-l QSH:DHE-RSA-CAMELLIA256-SHA256 + +# server TLSv1.0 DHE-PSK-AES128-CBC-SHA256 +-s +-v 1 +-l QSH:DHE-PSK-AES128-CBC-SHA256 + +# client TLSv1.0 DHE-PSK-AES128-CBC-SHA256 +-s +-v 1 +-l QSH:DHE-PSK-AES128-CBC-SHA256 + +# server TLSv1.1 DHE-PSK-AES128-CBC-SHA256 +-s +-v 2 +-l QSH:DHE-PSK-AES128-CBC-SHA256 + +# client TLSv1.1 DHE-PSK-AES128-CBC-SHA256 +-s +-v 2 +-l QSH:DHE-PSK-AES128-CBC-SHA256 + +# server TLSv1.0 DHE-PSK-AES256-CBC-SHA384 +-s +-v 1 +-l QSH:DHE-PSK-AES256-CBC-SHA384 + +# client TLSv1.0 DHE-PSK-AES256-CBC-SHA384 +-s +-v 1 +-l QSH:DHE-PSK-AES256-CBC-SHA384 + +# server TLSv1.1 DHE-PSK-AES256-CBC-SHA384 +-s +-v 2 +-l QSH:DHE-PSK-AES256-CBC-SHA384 + +# client TLSv1.1 DHE-PSK-AES256-CBC-SHA384 +-s +-v 2 +-l QSH:DHE-PSK-AES256-CBC-SHA384 + +# server TLSv1.0 DHE-PSK-NULL-SHA256 +-s +-v 1 +-l QSH:DHE-PSK-NULL-SHA256 + +# client TLSv1.0 DHE-PSK-NULL-SHA256 +-s +-v 1 +-l QSH:DHE-PSK-NULL-SHA256 + +# server TLSv1.1 DHE-PSK-NULL-SHA256 +-s +-v 2 +-l QSH:DHE-PSK-NULL-SHA256 + +# client TLSv1.1 DHE-PSK-NULL-SHA256 +-s +-v 2 +-l QSH:DHE-PSK-NULL-SHA256 + +# server TLSv1.0 DHE-PSK-NULL-SHA384 +-s +-v 1 +-l QSH:DHE-PSK-NULL-SHA384 + +# client TLSv1.0 DHE-PSK-NULL-SHA384 +-s +-v 1 +-l QSH:DHE-PSK-NULL-SHA384 + +# server TLSv1.1 DHE-PSK-NULL-SHA384 +-s +-v 2 +-l QSH:DHE-PSK-NULL-SHA384 + +# client TLSv1.1 DHE-PSK-NULL-SHA384 +-s +-v 2 +-l QSH:DHE-PSK-NULL-SHA384 diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-qsh.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-qsh.conf new file mode 100644 index 000000000..61f8ea031 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-qsh.conf @@ -0,0 +1,1778 @@ +# server TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-v 3 +-s +-l QSH:DHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-v 3 +-s +-l QSH:DHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-v 3 +-s +-l QSH:ECDHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-v 3 +-s +-l QSH:ECDHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 PSK-CHACHA20-POLY1305 +-v 3 +-s +-l QSH:PSK-CHACHA20-POLY1305 + +# client TLSv1.2 PSK-CHACHA20-POLY1305 +-v 3 +-s +-l QSH:PSK-CHACHA20-POLY1305 + +# server TLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-v 3 +-l QSH:DHE-RSA-CHACHA20-POLY1305-OLD + +# client TLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-v 3 +-l QSH:DHE-RSA-CHACHA20-POLY1305-OLD + +# server TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-v 3 +-l QSH:ECDHE-RSA-CHACHA20-POLY1305-OLD + +# client TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-v 3 +-l QSH:ECDHE-RSA-CHACHA20-POLY1305-OLD + +# server TLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305-OLD +-v 3 +-l QSH:ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-v 3 +-l QSH:ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 DHE-RSA-CHACHA20-POLY1305 +-v 3 +-l QSH:DHE-RSA-CHACHA20-POLY1305 + +# client TLSv1.2 DHE-RSA-CHACHA20-POLY1305 +-v 3 +-l QSH:DHE-RSA-CHACHA20-POLY1305 + +# server TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 +-v 3 +-l QSH:ECDHE-RSA-CHACHA20-POLY1305 + +# client TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 +-v 3 +-l QSH:ECDHE-RSA-CHACHA20-POLY1305 + +# server TLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305 +-v 3 +-l QSH:ECDHE-ECDSA-CHACHA20-POLY1305 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305 +-v 3 +-l QSH:ECDHE-ECDSA-CHACHA20-POLY1305 +-A ./certs/ca-ecc-cert.pem + +# server SSLv3 RC4-SHA +-v 0 +-l QSH:RC4-SHA + +# client SSLv3 RC4-SHA +-v 0 +-l QSH:RC4-SHA + +# server SSLv3 RC4-MD5 +-v 0 +-l QSH:RC4-MD5 + +# client SSLv3 RC4-MD5 +-v 0 +-l QSH:RC4-MD5 + +# server SSLv3 DES-CBC3-SHA +-v 0 +-l QSH:DES-CBC3-SHA + +# client SSLv3 DES-CBC3-SHA +-v 0 +-l QSH:DES-CBC3-SHA + +# server SSLv3 IDEA-CBC-SHA +-v 0 +-l QSH:IDEA-CBC-SHA + +# client SSLv3 IDEA-CBC-SHA +-v 0 +-l QSH:IDEA-CBC-SHA + +# server TLSv1 RC4-SHA +-v 1 +-l QSH:RC4-SHA + +# client TLSv1 RC4-SHA +-v 1 +-l QSH:RC4-SHA + +# server TLSv1 RC4-MD5 +-v 1 +-l QSH:RC4-MD5 + +# client TLSv1 RC4-MD5 +-v 1 +-l QSH:RC4-MD5 + +# server TLSv1 DES-CBC3-SHA +-v 1 +-l QSH:DES-CBC3-SHA + +# client TLSv1 DES-CBC3-SHA +-v 1 +-l QSH:DES-CBC3-SHA + +# server TLSv1 IDEA-CBC-SHA +-v 1 +-l QSH:IDEA-CBC-SHA + +# client TLSv1 IDEA-CBC-SHA +-v 1 +-l QSH:IDEA-CBC-SHA + +# server TLSv1 AES128-SHA +-v 1 +-l QSH:AES128-SHA + +# client TLSv1 AES128-SHA +-v 1 +-l QSH:AES128-SHA + +# server TLSv1 AES256-SHA +-v 1 +-l QSH:AES256-SHA + +# client TLSv1 AES256-SHA +-v 1 +-l QSH:AES256-SHA + +# server TLSv1.1 RC4-SHA +-v 2 +-l QSH:RC4-SHA + +# client TLSv1.1 RC4-SHA +-v 2 +-l QSH:RC4-SHA + +# server TLSv1.1 RC4-MD5 +-v 2 +-l QSH:RC4-MD5 + +# client TLSv1.1 RC4-MD5 +-v 2 +-l QSH:RC4-MD5 + +# server TLSv1.1 IDEA-CBC-SHA +-v 2 +-l QSH:IDEA-CBC-SHA + +# client TLSv1.1 IDEA-CBC-SHA +-v 2 +-l QSH:IDEA-CBC-SHA + +# server TLSv1.1 DES-CBC3-SHA +-v 2 +-l QSH:DES-CBC3-SHA + +# client TLSv1.1 DES-CBC3-SHA +-v 2 +-l QSH:DES-CBC3-SHA + +# server TLSv1.1 AES128-SHA +-v 2 +-l QSH:AES128-SHA + +# client TLSv1.1 AES128-SHA +-v 2 +-l QSH:AES128-SHA + +# server TLSv1.1 AES256-SHA +-v 2 +-l QSH:AES256-SHA + +# client TLSv1.1 AES256-SHA +-v 2 +-l QSH:AES256-SHA + +# server TLSv1.2 RC4-SHA +-v 3 +-l QSH:RC4-SHA + +# client TLSv1.2 RC4-SHA +-v 3 +-l QSH:RC4-SHA + +# server TLSv1.2 RC4-MD5 +-v 3 +-l QSH:RC4-MD5 + +# client TLSv1.2 RC4-MD5 +-v 3 +-l QSH:RC4-MD5 + +# server TLSv1.2 DES-CBC3-SHA +-v 3 +-l QSH:DES-CBC3-SHA + +# client TLSv1.2 DES-CBC3-SHA +-v 3 +-l QSH:DES-CBC3-SHA + +# server TLSv1.2 AES128-SHA +-v 3 +-l QSH:AES128-SHA + +# client TLSv1.2 AES128-SHA +-v 3 +-l QSH:AES128-SHA + +# server TLSv1.2 AES256-SHA +-v 3 +-l QSH:AES256-SHA + +# client TLSv1.2 AES256-SHA +-v 3 +-l QSH:AES256-SHA + +# server TLSv1.2 AES128-SHA256 +-v 3 +-l QSH:AES128-SHA256 + +# client TLSv1.2 AES128-SHA256 +-v 3 +-l QSH:AES128-SHA256 + +# server TLSv1.2 AES256-SHA256 +-v 3 +-l QSH:AES256-SHA256 + +# client TLSv1.2 AES256-SHA256 +-v 3 +-l QSH:AES256-SHA256 + +# server TLSv1 ECDHE-RSA-RC4 +-v 1 +-l QSH:ECDHE-RSA-RC4-SHA + +# client TLSv1 ECDHE-RSA-RC4 +-v 1 +-l QSH:ECDHE-RSA-RC4-SHA + +# server TLSv1 ECDHE-RSA-DES3 +-v 1 +-l QSH:ECDHE-RSA-DES-CBC3-SHA + +# client TLSv1 ECDHE-RSA-DES3 +-v 1 +-l QSH:ECDHE-RSA-DES-CBC3-SHA + +# server TLSv1 ECDHE-RSA-AES128 +-v 1 +-l QSH:ECDHE-RSA-AES128-SHA + +# client TLSv1 ECDHE-RSA-AES128 +-v 1 +-l QSH:ECDHE-RSA-AES128-SHA + +# server TLSv1 ECDHE-RSA-AES256 +-v 1 +-l QSH:ECDHE-RSA-AES256-SHA + +# client TLSv1 ECDHE-RSA-AES256 +-v 1 +-l QSH:ECDHE-RSA-AES256-SHA + +# server TLSv1 ECDHE-ECDSA-NULL-SHA +-v 1 +-l QSH:ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-v 1 +-l QSH:ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDHE-ECDSA-NULL-SHA +-v 2 +-l QSH:ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-v 2 +-l QSH:ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-NULL-SHA +-v 3 +-l QSH:ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-NULL-SHA +-v 3 +-l QSH:ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDHE-RSA-RC4 +-v 2 +-l QSH:ECDHE-RSA-RC4-SHA + +# client TLSv1.1 ECDHE-RSA-RC4 +-v 2 +-l QSH:ECDHE-RSA-RC4-SHA + +# server TLSv1.1 ECDHE-RSA-DES3 +-v 2 +-l QSH:ECDHE-RSA-DES-CBC3-SHA + +# client TLSv1.1 ECDHE-RSA-DES3 +-v 2 +-l QSH:ECDHE-RSA-DES-CBC3-SHA + +# server TLSv1.1 ECDHE-RSA-AES128 +-v 2 +-l QSH:ECDHE-RSA-AES128-SHA + +# client TLSv1.1 ECDHE-RSA-AES128 +-v 2 +-l QSH:ECDHE-RSA-AES128-SHA + +# server TLSv1.1 ECDHE-RSA-AES256 +-v 2 +-l QSH:ECDHE-RSA-AES256-SHA + +# client TLSv1.1 ECDHE-RSA-AES256 +-v 2 +-l QSH:ECDHE-RSA-AES256-SHA + +# server TLSv1.2 ECDHE-RSA-RC4 +-v 3 +-l QSH:ECDHE-RSA-RC4-SHA + +# client TLSv1.2 ECDHE-RSA-RC4 +-v 3 +-l QSH:ECDHE-RSA-RC4-SHA + +# server TLSv1.2 ECDHE-RSA-DES3 +-v 3 +-l QSH:ECDHE-RSA-DES-CBC3-SHA + +# client TLSv1.2 ECDHE-RSA-DES3 +-v 3 +-l QSH:ECDHE-RSA-DES-CBC3-SHA + +# server TLSv1.2 ECDHE-RSA-AES128 +-v 3 +-l QSH:ECDHE-RSA-AES128-SHA + +# client TLSv1.2 ECDHE-RSA-AES128 +-v 3 +-l QSH:ECDHE-RSA-AES128-SHA + +# server TLSv1.2 ECDHE-RSA-AES128-SHA256 +-v 3 +-l QSH:ECDHE-RSA-AES128-SHA256 + +# client TLSv1.2 ECDHE-RSA-AES128-SHA256 +-v 3 +-l QSH:ECDHE-RSA-AES128-SHA256 + +# server TLSv1.2 ECDHE-RSA-AES256 +-v 3 +-l QSH:ECDHE-RSA-AES256-SHA + +# client TLSv1.2 ECDHE-RSA-AES256 +-v 3 +-l QSH:ECDHE-RSA-AES256-SHA + +# server TLSv1 ECDHE-ECDSA-RC4 +-v 1 +-l QSH:ECDHE-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-RC4 +-v 1 +-l QSH:ECDHE-ECDSA-RC4-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1 ECDHE-ECDSA-DES3 +-v 1 +-l QSH:ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-DES3 +-v 1 +-l QSH:ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1 ECDHE-ECDSA-AES128 +-v 1 +-l QSH:ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-AES128 +-v 1 +-l QSH:ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1 ECDHE-ECDSA-AES256 +-v 1 +-l QSH:ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-AES256 +-v 1 +-l QSH:ECDHE-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDHE-EDCSA-RC4 +-v 2 +-l QSH:ECDHE-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDHE-ECDSA-RC4 +-v 2 +-l QSH:ECDHE-ECDSA-RC4-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDHE-ECDSA-DES3 +-v 2 +-l QSH:ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDHE-ECDSA-DES3 +-v 2 +-l QSH:ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDHE-ECDSA-AES128 +-v 2 +-l QSH:ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDHE-ECDSA-AES128 +-v 2 +-l QSH:ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDHE-ECDSA-AES256 +-v 2 +-l QSH:ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDHE-ECDSA-AES256 +-v 2 +-l QSH:ECDHE-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-RC4 +-v 3 +-l QSH:ECDHE-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-RC4 +-v 3 +-l QSH:ECDHE-ECDSA-RC4-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-DES3 +-v 3 +-l QSH:ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-DES3 +-v 3 +-l QSH:ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES128 +-v 3 +-l QSH:ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128 +-v 3 +-l QSH:ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-v 3 +-l QSH:ECDHE-ECDSA-AES128-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-v 3 +-l QSH:ECDHE-ECDSA-AES128-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES256 +-v 3 +-l QSH:ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256 +-v 3 +-l QSH:ECDHE-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1 ECDH-RSA-RC4 +-v 1 +-l QSH:ECDH-RSA-RC4-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDH-RSA-RC4 +-v 1 +-l QSH:ECDH-RSA-RC4-SHA + +# server TLSv1 ECDH-RSA-DES3 +-v 1 +-l QSH:ECDH-RSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDH-RSA-DES3 +-v 1 +-l QSH:ECDH-RSA-DES-CBC3-SHA + +# server TLSv1 ECDH-RSA-AES128 +-v 1 +-l QSH:ECDH-RSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDH-RSA-AES128 +-v 1 +-l QSH:ECDH-RSA-AES128-SHA + +# server TLSv1 ECDH-RSA-AES256 +-v 1 +-l QSH:ECDH-RSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDH-RSA-AES256 +-v 1 +-l QSH:ECDH-RSA-AES256-SHA + +# server TLSv1.1 ECDH-RSA-RC4 +-v 2 +-l QSH:ECDH-RSA-RC4-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDH-RSA-RC4 +-v 2 +-l QSH:ECDH-RSA-RC4-SHA + +# server TLSv1.1 ECDH-RSA-DES3 +-v 2 +-l QSH:ECDH-RSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDH-RSA-DES3 +-v 2 +-l QSH:ECDH-RSA-DES-CBC3-SHA + +# server TLSv1.1 ECDH-RSA-AES128 +-v 2 +-l QSH:ECDH-RSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDH-RSA-AES128 +-v 2 +-l QSH:ECDH-RSA-AES128-SHA + +# server TLSv1.1 ECDH-RSA-AES256 +-v 2 +-l QSH:ECDH-RSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDH-RSA-AES256 +-v 2 +-l QSH:ECDH-RSA-AES256-SHA + +# server TLSv1.2 ECDH-RSA-RC4 +-v 3 +-l QSH:ECDH-RSA-RC4-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-RSA-RC4 +-v 3 +-l QSH:ECDH-RSA-RC4-SHA + +# server TLSv1.2 ECDH-RSA-DES3 +-v 3 +-l QSH:ECDH-RSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-RSA-DES3 +-v 3 +-l QSH:ECDH-RSA-DES-CBC3-SHA + +# server TLSv1.2 ECDH-RSA-AES128 +-v 3 +-l QSH:ECDH-RSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-RSA-AES128 +-v 3 +-l QSH:ECDH-RSA-AES128-SHA + +# server TLSv1.2 ECDH-RSA-AES128-SHA256 +-v 3 +-l QSH:ECDH-RSA-AES128-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-RSA-AES128-SHA256 +-v 3 +-l QSH:ECDH-RSA-AES128-SHA256 + +# server TLSv1.2 ECDH-RSA-AES256 +-v 3 +-l QSH:ECDH-RSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-RSA-AES256 +-v 3 +-l QSH:ECDH-RSA-AES256-SHA + +# server TLSv1 ECDH-ECDSA-RC4 +-v 1 +-l QSH:ECDH-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDH-ECDSA-RC4 +-v 1 +-l QSH:ECDH-ECDSA-RC4-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1 ECDH-ECDSA-DES3 +-v 1 +-l QSH:ECDH-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDH-ECDSA-DES3 +-v 1 +-l QSH:ECDH-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1 ECDH-ECDSA-AES128 +-v 1 +-l QSH:ECDH-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDH-ECDSA-AES128 +-v 1 +-l QSH:ECDH-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1 ECDH-ECDSA-AES256 +-v 1 +-l QSH:ECDH-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDH-ECDSA-AES256 +-v 1 +-l QSH:ECDH-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDH-EDCSA-RC4 +-v 2 +-l QSH:ECDH-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDH-ECDSA-RC4 +-v 2 +-l QSH:ECDH-ECDSA-RC4-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDH-ECDSA-DES3 +-v 2 +-l QSH:ECDH-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDH-ECDSA-DES3 +-v 2 +-l QSH:ECDH-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDH-ECDSA-AES128 +-v 2 +-l QSH:ECDH-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDH-ECDSA-AES128 +-v 2 +-l QSH:ECDH-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDH-ECDSA-AES256 +-v 2 +-l QSH:ECDH-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDH-ECDSA-AES256 +-v 2 +-l QSH:ECDH-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-RC4 +-v 3 +-l QSH:ECDH-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-ECDSA-RC4 +-v 3 +-l QSH:ECDH-ECDSA-RC4-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDH-ECDSA-DES3 +-v 3 +-l QSH:ECDH-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-ECDSA-DES3 +-v 3 +-l QSH:ECDH-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDH-ECDSA-AES128 +-v 3 +-l QSH:ECDH-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-ECDSA-AES128 +-v 3 +-l QSH:ECDH-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDH-ECDSA-AES128-SHA256 +-v 3 +-l QSH:ECDH-ECDSA-AES128-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-ECDSA-AES128-SHA256 +-v 3 +-l QSH:ECDH-ECDSA-AES128-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDH-ECDSA-AES256 +-v 3 +-l QSH:ECDH-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-ECDSA-AES256 +-v 3 +-l QSH:ECDH-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-RSA-AES256-SHA384 +-v 3 +-l QSH:ECDHE-RSA-AES256-SHA384 + +# client TLSv1.2 ECDHE-RSA-AES256-SHA384 +-v 3 +-l QSH:ECDHE-RSA-AES256-SHA384 + +# server TLSv1.2 ECDHE-ECDSA-AES256-SHA384 +-v 3 +-l QSH:ECDHE-ECDSA-AES256-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256-SHA384 +-v 3 +-l QSH:ECDHE-ECDSA-AES256-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDH-RSA-AES256-SHA384 +-v 3 +-l QSH:ECDH-RSA-AES256-SHA384 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-RSA-AES256-SHA384 +-v 3 +-l QSH:ECDH-RSA-AES256-SHA384 + +# server TLSv1.2 ECDH-ECDSA-AES256-SHA384 +-v 3 +-l QSH:ECDH-ECDSA-AES256-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-ECDSA-AES256-SHA384 +-v 3 +-l QSH:ECDH-ECDSA-AES256-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1 HC128-SHA +-v 1 +-l QSH:HC128-SHA + +# client TLSv1 HC128-SHA +-v 1 +-l QSH:HC128-SHA + +# server TLSv1 HC128-MD5 +-v 1 +-l QSH:HC128-MD5 + +# client TLSv1 HC128-MD5 +-v 1 +-l QSH:HC128-MD5 + +# server TLSv1.1 HC128-SHA +-v 2 +-l QSH:HC128-SHA + +# client TLSv1.1 HC128-SHA +-v 2 +-l QSH:HC128-SHA + +# server TLSv1.1 HC128-MD5 +-v 2 +-l QSH:HC128-MD5 + +# client TLSv1.1 HC128-MD5 +-v 2 +-l QSH:HC128-MD5 + +# server TLSv1.2 HC128-SHA +-v 3 +-l QSH:HC128-SHA + +# client TLSv1.2 HC128-SHA +-v 3 +-l QSH:HC128-SHA + +# server TLSv1.2 HC128-MD5 +-v 3 +-l QSH:HC128-MD5 + +# client TLSv1.2 HC128-MD5 +-v 3 +-l QSH:HC128-MD5 + +# server TLSv1 RABBIT-SHA +-v 1 +-l QSH:RABBIT-SHA + +# client TLSv1 RABBIT-SHA +-v 1 +-l QSH:RABBIT-SHA + +# server TLSv1.1 RABBIT-SHA +-v 2 +-l QSH:RABBIT-SHA + +# client TLSv1.1 RABBIT-SHA +-v 2 +-l QSH:RABBIT-SHA + +# server TLSv1.2 RABBIT-SHA +-v 3 +-l QSH:RABBIT-SHA + +# client TLSv1.2 RABBIT-SHA +-v 3 +-l QSH:RABBIT-SHA + +# server TLSv1 DHE AES128 +-v 1 +-l QSH:DHE-RSA-AES128-SHA + +# client TLSv1 DHE AES128 +-v 1 +-l QSH:DHE-RSA-AES128-SHA + +# server TLSv1 DHE AES256 +-v 1 +-l QSH:DHE-RSA-AES256-SHA + +# client TLSv1 DHE AES256 +-v 1 +-l QSH:DHE-RSA-AES256-SHA + +# server TLSv1.1 DHE AES128 +-v 2 +-l QSH:DHE-RSA-AES128-SHA + +# client TLSv1.1 DHE AES128 +-v 2 +-l QSH:DHE-RSA-AES128-SHA + +# server TLSv1.1 DHE AES256 +-v 2 +-l QSH:DHE-RSA-AES256-SHA + +# client TLSv1.1 DHE AES256 +-v 2 +-l QSH:DHE-RSA-AES256-SHA + +# server TLSv1.2 DHE AES128 +-v 3 +-l QSH:DHE-RSA-AES128-SHA + +# client TLSv1.2 DHE AES128 +-v 3 +-l QSH:DHE-RSA-AES128-SHA + +# server TLSv1.2 DHE AES256 +-v 3 +-l QSH:DHE-RSA-AES256-SHA + +# client TLSv1.2 DHE AES256 +-v 3 +-l QSH:DHE-RSA-AES256-SHA + +# server TLSv1.2 DHE AES128-SHA256 +-v 3 +-l QSH:DHE-RSA-AES128-SHA256 + +# client TLSv1.2 DHE AES128-SHA256 +-v 3 +-l QSH:DHE-RSA-AES128-SHA256 + +# server TLSv1.2 DHE AES256-SHA256 +-v 3 +-l QSH:DHE-RSA-AES256-SHA256 + +# client TLSv1.2 DHE AES256-SHA256 +-v 3 +-l QSH:DHE-RSA-AES256-SHA256 + +# server TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-v 3 +-l QSH:ECDHE-PSK-AES128-SHA256 + +# client TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-v 3 +-l QSH:ECDHE-PSK-AES128-SHA256 + +# server TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-v 3 +-l QSH:ECDHE-PSK-NULL-SHA256 + +# client TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-v 3 +-l QSH:ECDHE-PSK-NULL-SHA256 + +# server TLSv1 PSK-AES128 +-s +-v 1 +-l QSH:PSK-AES128-CBC-SHA + +# client TLSv1 PSK-AES128 +-s +-v 1 +-l QSH:PSK-AES128-CBC-SHA + +# server TLSv1 PSK-AES256 +-s +-v 1 +-l QSH:PSK-AES256-CBC-SHA + +# client TLSv1 PSK-AES256 +-s +-v 1 +-l QSH:PSK-AES256-CBC-SHA + +# server TLSv1.1 PSK-AES128 +-s +-v 2 +-l QSH:PSK-AES128-CBC-SHA + +# client TLSv1.1 PSK-AES128 +-s +-v 2 +-l QSH:PSK-AES128-CBC-SHA + +# server TLSv1.1 PSK-AES256 +-s +-v 2 +-l QSH:PSK-AES256-CBC-SHA + +# client TLSv1.1 PSK-AES256 +-s +-v 2 +-l QSH:PSK-AES256-CBC-SHA + +# server TLSv1.2 PSK-AES128 +-s +-v 3 +-l QSH:PSK-AES128-CBC-SHA + +# client TLSv1.2 PSK-AES128 +-s +-v 3 +-l QSH:PSK-AES128-CBC-SHA + +# server TLSv1.2 PSK-AES256 +-s +-v 3 +-l QSH:PSK-AES256-CBC-SHA + +# client TLSv1.2 PSK-AES256 +-s +-v 3 +-l QSH:PSK-AES256-CBC-SHA + +# server TLSv1.2 PSK-AES128-SHA256 +-s +-v 3 +-l QSH:PSK-AES128-CBC-SHA256 + +# client TLSv1.2 PSK-AES128-SHA256 +-s +-v 3 +-l QSH:PSK-AES128-CBC-SHA256 + +# server TLSv1.2 PSK-AES256-SHA384 +-s +-v 3 +-l QSH:PSK-AES256-CBC-SHA384 + +# client TLSv1.2 PSK-AES256-SHA384 +-s +-v 3 +-l QSH:PSK-AES256-CBC-SHA384 + +# server TLSv1.0 PSK-NULL +-s +-v 1 +-l QSH:PSK-NULL-SHA + +# client TLSv1.0 PSK-NULL +-s +-v 1 +-l QSH:PSK-NULL-SHA + +# server TLSv1.1 PSK-NULL +-s +-v 2 +-l QSH:PSK-NULL-SHA + +# client TLSv1.1 PSK-NULL +-s +-v 2 +-l QSH:PSK-NULL-SHA + +# server TLSv1.2 PSK-NULL +-s +-v 3 +-l QSH:PSK-NULL-SHA + +# client TLSv1.2 PSK-NULL +-s +-v 3 +-l QSH:PSK-NULL-SHA + +# server TLSv1.2 PSK-NULL-SHA256 +-s +-v 3 +-l QSH:PSK-NULL-SHA256 + +# client TLSv1.2 PSK-NULL-SHA256 +-s +-v 3 +-l QSH:PSK-NULL-SHA256 + +# server TLSv1.2 PSK-NULL-SHA384 +-s +-v 3 +-l QSH:PSK-NULL-SHA384 + +# client TLSv1.2 PSK-NULL-SHA384 +-s +-v 3 +-l QSH:PSK-NULL-SHA384 + +# server TLSv1.2 PSK-NULL +-s +-v 3 +-l QSH:PSK-NULL-SHA + +# client TLSv1.2 PSK-NULL +-s +-v 3 +-l QSH:PSK-NULL-SHA + +# server TLSv1.2 PSK-NULL-SHA256 +-s +-v 3 +-l QSH:PSK-NULL-SHA256 + +# client TLSv1.2 PSK-NULL-SHA256 +-s +-v 3 +-l QSH:PSK-NULL-SHA256 + +# server TLSv1.0 RSA-NULL-SHA +-v 1 +-l QSH:NULL-SHA + +# client TLSv1.0 RSA-NULL-SHA +-v 1 +-l QSH:NULL-SHA + +# server TLSv1.1 RSA-NULL-SHA +-v 2 +-l QSH:NULL-SHA + +# client TLSv1.1 RSA-NULL-SHA +-v 2 +-l QSH:NULL-SHA + +# server TLSv1.2 RSA-NULL-SHA +-v 3 +-l QSH:NULL-SHA + +# client TLSv1.2 RSA-NULL-SHA +-v 3 +-l QSH:NULL-SHA + +# server TLSv1.2 RSA-NULL-SHA256 +-v 3 +-l QSH:NULL-SHA256 + +# client TLSv1.2 RSA-NULL-SHA256 +-v 3 +-l QSH:NULL-SHA256 + +# server TLSv1 CAMELLIA128-SHA +-v 1 +-l QSH:CAMELLIA128-SHA + +# client TLSv1 CAMELLIA128-SHA +-v 1 +-l QSH:CAMELLIA128-SHA + +# server TLSv1 CAMELLIA256-SHA +-v 1 +-l QSH:CAMELLIA256-SHA + +# client TLSv1 CAMELLIA256-SHA +-v 1 +-l QSH:CAMELLIA256-SHA + +# server TLSv1.1 CAMELLIA128-SHA +-v 2 +-l QSH:CAMELLIA128-SHA + +# client TLSv1.1 CAMELLIA128-SHA +-v 2 +-l QSH:CAMELLIA128-SHA + +# server TLSv1.1 CAMELLIA256-SHA +-v 2 +-l QSH:CAMELLIA256-SHA + +# client TLSv1.1 CAMELLIA256-SHA +-v 2 +-l QSH:CAMELLIA256-SHA + +# server TLSv1.2 CAMELLIA128-SHA +-v 3 +-l QSH:CAMELLIA128-SHA + +# client TLSv1.2 CAMELLIA128-SHA +-v 3 +-l QSH:CAMELLIA128-SHA + +# server TLSv1.2 CAMELLIA256-SHA +-v 3 +-l QSH:CAMELLIA256-SHA + +# client TLSv1.2 CAMELLIA256-SHA +-v 3 +-l QSH:CAMELLIA256-SHA + +# server TLSv1.2 CAMELLIA128-SHA256 +-v 3 +-l QSH:CAMELLIA128-SHA256 + +# client TLSv1.2 CAMELLIA128-SHA256 +-v 3 +-l QSH:CAMELLIA128-SHA256 + +# server TLSv1.2 CAMELLIA256-SHA256 +-v 3 +-l QSH:CAMELLIA256-SHA256 + +# client TLSv1.2 CAMELLIA256-SHA256 +-v 3 +-l QSH:CAMELLIA256-SHA256 + +# server TLSv1 DHE-RSA-CAMELLIA128-SHA +-v 1 +-l QSH:DHE-RSA-CAMELLIA128-SHA + +# client TLSv1 DHE-RSA-CAMELLIA128-SHA +-v 1 +-l QSH:DHE-RSA-CAMELLIA128-SHA + +# server TLSv1 DHE-RSA-CAMELLIA256-SHA +-v 1 +-l QSH:DHE-RSA-CAMELLIA256-SHA + +# client TLSv1 DHE-RSA-CAMELLIA256-SHA +-v 1 +-l QSH:DHE-RSA-CAMELLIA256-SHA + +# server TLSv1.1 DHE-RSA-CAMELLIA128-SHA +-v 2 +-l QSH:DHE-RSA-CAMELLIA128-SHA + +# client TLSv1.1 DHE-RSA-CAMELLIA128-SHA +-v 2 +-l QSH:DHE-RSA-CAMELLIA128-SHA + +# server TLSv1.1 DHE-RSA-CAMELLIA256-SHA +-v 2 +-l QSH:DHE-RSA-CAMELLIA256-SHA + +# client TLSv1.1 DHE-RSA-CAMELLIA256-SHA +-v 2 +-l QSH:DHE-RSA-CAMELLIA256-SHA + +# server TLSv1.2 DHE-RSA-CAMELLIA128-SHA +-v 3 +-l QSH:DHE-RSA-CAMELLIA128-SHA + +# client TLSv1.2 DHE-RSA-CAMELLIA128-SHA +-v 3 +-l QSH:DHE-RSA-CAMELLIA128-SHA + +# server TLSv1.2 DHE-RSA-CAMELLIA256-SHA +-v 3 +-l QSH:DHE-RSA-CAMELLIA256-SHA + +# client TLSv1.2 DHE-RSA-CAMELLIA256-SHA +-v 3 +-l QSH:DHE-RSA-CAMELLIA256-SHA + +# server TLSv1.2 DHE-RSA-CAMELLIA128-SHA256 +-v 3 +-l QSH:DHE-RSA-CAMELLIA128-SHA256 + +# client TLSv1.2 DHE-RSA-CAMELLIA128-SHA256 +-v 3 +-l QSH:DHE-RSA-CAMELLIA128-SHA256 + +# server TLSv1.2 DHE-RSA-CAMELLIA256-SHA256 +-v 3 +-l QSH:DHE-RSA-CAMELLIA256-SHA256 + +# client TLSv1.2 DHE-RSA-CAMELLIA256-SHA256 +-v 3 +-l QSH:DHE-RSA-CAMELLIA256-SHA256 + +# server TLSv1.2 RSA-AES128-GCM-SHA256 +-v 3 +-l QSH:AES128-GCM-SHA256 + +# client TLSv1.2 RSA-AES128-GCM-SHA256 +-v 3 +-l QSH:AES128-GCM-SHA256 + +# server TLSv1.2 RSA-AES256-GCM-SHA384 +-v 3 +-l QSH:AES256-GCM-SHA384 + +# client TLSv1.2 RSA-AES256-GCM-SHA384 +-v 3 +-l QSH:AES256-GCM-SHA384 + +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l QSH:ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l QSH:ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l QSH:ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l QSH:ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +-v 3 +-l QSH:ECDH-ECDSA-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +-v 3 +-l QSH:ECDH-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 +-v 3 +-l QSH:ECDH-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 +-v 3 +-l QSH:ECDH-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +-v 3 +-l QSH:ECDHE-RSA-AES128-GCM-SHA256 + +# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +-v 3 +-l QSH:ECDHE-RSA-AES128-GCM-SHA256 + +# server TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l QSH:ECDHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l QSH:ECDHE-RSA-AES256-GCM-SHA384 + +# server TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +-v 3 +-l QSH:ECDH-RSA-AES128-GCM-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +-v 3 +-l QSH:ECDH-RSA-AES128-GCM-SHA256 + +# server TLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +-v 3 +-l QSH:ECDH-RSA-AES256-GCM-SHA384 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +-v 3 +-l QSH:ECDH-RSA-AES256-GCM-SHA384 + +# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 +-v 3 +-l QSH:DHE-RSA-AES128-GCM-SHA256 + +# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 +-v 3 +-l QSH:DHE-RSA-AES128-GCM-SHA256 + +# server TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l QSH:DHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l QSH:DHE-RSA-AES256-GCM-SHA384 + +# server TLSv1.2 PSK-AES128-GCM-SHA256 +-s +-v 3 +-l QSH:PSK-AES128-GCM-SHA256 + +# client TLSv1.2 PSK-AES128-GCM-SHA256 +-s +-v 3 +-l QSH:PSK-AES128-GCM-SHA256 + +# server TLSv1.2 PSK-AES256-GCM-SHA384 +-s +-v 3 +-l QSH:PSK-AES256-GCM-SHA384 + +# client TLSv1.2 PSK-AES256-GCM-SHA384 +-s +-v 3 +-l QSH:PSK-AES256-GCM-SHA384 + +# server TLSv1.2 AES128-CCM-8 +-v 3 +-l QSH:AES128-CCM-8 + +# client TLSv1.2 AES128-CCM-8 +-v 3 +-l QSH:AES128-CCM-8 + +# server TLSv1.2 AES256-CCM-8 +-v 3 +-l QSH:AES256-CCM-8 + +# client TLSv1.2 AES256-CCM-8 +-v 3 +-l QSH:AES256-CCM-8 + +# server TLSv1.2 ECDHE-ECDSA-AES128-CCM +-v 3 +-l QSH:ECDHE-ECDSA-AES128-CCM +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-CCM +-v 3 +-l QSH:ECDHE-ECDSA-AES128-CCM +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-v 3 +-l QSH:ECDHE-ECDSA-AES128-CCM-8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-v 3 +-l QSH:ECDHE-ECDSA-AES128-CCM-8 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +-v 3 +-l QSH:ECDHE-ECDSA-AES256-CCM-8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +-v 3 +-l QSH:ECDHE-ECDSA-AES256-CCM-8 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 PSK-AES128-CCM +-s +-v 3 +-l QSH:PSK-AES128-CCM + +# client TLSv1.2 PSK-AES128-CCM +-s +-v 3 +-l QSH:PSK-AES128-CCM + +# server TLSv1.2 PSK-AES256-CCM +-s +-v 3 +-l QSH:PSK-AES256-CCM + +# client TLSv1.2 PSK-AES256-CCM +-s +-v 3 +-l QSH:PSK-AES256-CCM + +# server TLSv1.2 PSK-AES128-CCM-8 +-s +-v 3 +-l QSH:PSK-AES128-CCM-8 + +# client TLSv1.2 PSK-AES128-CCM-8 +-s +-v 3 +-l QSH:PSK-AES128-CCM-8 + +# server TLSv1.2 PSK-AES256-CCM-8 +-s +-v 3 +-l QSH:PSK-AES256-CCM-8 + +# client TLSv1.2 PSK-AES256-CCM-8 +-s +-v 3 +-l QSH:PSK-AES256-CCM-8 + +# server TLSv1.2 DHE-PSK-AES128-CBC-SHA256 +-s +-v 3 +-l QSH:DHE-PSK-AES128-CBC-SHA256 + +# client TLSv1.2 DHE-PSK-AES128-CBC-SHA256 +-s +-v 3 +-l QSH:DHE-PSK-AES128-CBC-SHA256 + +# server TLSv1.2 DHE-PSK-AES256-CBC-SHA384 +-s +-v 3 +-l QSH:DHE-PSK-AES256-CBC-SHA384 + +# client TLSv1.2 DHE-PSK-AES256-CBC-SHA384 +-s +-v 3 +-l QSH:DHE-PSK-AES256-CBC-SHA384 + +# server TLSv1.2 DHE-PSK-NULL-SHA256 +-s +-v 3 +-l QSH:DHE-PSK-NULL-SHA256 + +# client TLSv1.2 DHE-PSK-NULL-SHA256 +-s +-v 3 +-l QSH:DHE-PSK-NULL-SHA256 + +# server TLSv1.2 DHE-PSK-NULL-SHA384 +-s +-v 3 +-l QSH:DHE-PSK-NULL-SHA384 + +# client TLSv1.2 DHE-PSK-NULL-SHA384 +-s +-v 3 +-l QSH:DHE-PSK-NULL-SHA384 + +# server TLSv1.2 DHE-PSK-AES128-GCM-SHA256 +-s +-v 3 +-l QSH:DHE-PSK-AES128-GCM-SHA256 + +# client TLSv1.2 DHE-PSK-AES128-GCM-SHA256 +-s +-v 3 +-l QSH:DHE-PSK-AES128-GCM-SHA256 + +# server TLSv1.2 DHE-PSK-AES256-GCM-SHA384 +-s +-v 3 +-l QSH:DHE-PSK-AES256-GCM-SHA384 + +# client TLSv1.2 DHE-PSK-AES256-GCM-SHA384 +-s +-v 3 +-l QSH:DHE-PSK-AES256-GCM-SHA384 + +# server TLSv1.2 DHE-PSK-AES128-CCM +-s +-v 3 +-l QSH:DHE-PSK-AES128-CCM + +# client TLSv1.2 DHE-PSK-AES128-CCM +-s +-v 3 +-l QSH:DHE-PSK-AES128-CCM + +# server TLSv1.2 DHE-PSK-AES256-CCM +-s +-v 3 +-l QSH:DHE-PSK-AES256-CCM + +# client TLSv1.2 DHE-PSK-AES256-CCM +-s +-v 3 +-l QSH:DHE-PSK-AES256-CCM + +# server TLSv1.2 ADH-AES128-SHA +-a +-v 3 +-l QSH:ADH-AES128-SHA + +# client TLSv1.2 ADH-AES128-SHA +-a +-v 3 +-l QSH:ADH-AES128-SHA + +# server TLSv1.1 ADH-AES128-SHA +-a +-v 2 +-l QSH:ADH-AES128-SHA + +# client TLSv1.1 ADH-AES128-SHA +-a +-v 2 +-l QSH:ADH-AES128-SHA + +# server TLSv1.0 ADH-AES128-SHA +-a +-v 1 +-l QSH:ADH-AES128-SHA + +# client TLSv1.0 ADH-AES128-SHA +-a +-v 1 +-l QSH:ADH-AES128-SHA + +# server TLSv1 NTRU_RC4 +-v 1 +-l QSH:NTRU-RC4-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1 NTRU_RC4 +-v 1 +-l QSH:NTRU-RC4-SHA + +# server TLSv1 NTRU_DES3 +-v 1 +-l QSH:NTRU-DES-CBC3-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1 NTRU_DES3 +-v 1 +-l QSH:NTRU-DES-CBC3-SHA + +# server TLSv1 NTRU_AES128 +-v 1 +-l QSH:NTRU-AES128-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1 NTRU_AES128 +-v 1 +-l QSH:NTRU-AES128-SHA + +# server TLSv1 NTRU_AES256 +-v 1 +-l QSH:NTRU-AES256-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1 NTRU_AES256 +-v 1 +-l QSH:NTRU-AES256-SHA + +# server TLSv1.1 NTRU_RC4 +-v 2 +-l QSH:NTRU-RC4-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.1 NTRU_RC4 +-v 2 +-l QSH:NTRU-RC4-SHA + +# server TLSv1.1 NTRU_DES3 +-v 2 +-l QSH:NTRU-DES-CBC3-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.1 NTRU_DES3 +-v 2 +-l QSH:NTRU-DES-CBC3-SHA + +# server TLSv1.1 NTRU_AES128 +-v 2 +-l QSH:NTRU-AES128-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.1 NTRU_AES128 +-v 2 +-l QSH:NTRU-AES128-SHA + +# server TLSv1.1 NTRU_AES256 +-v 2 +-l QSH:NTRU-AES256-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.1 NTRU_AES256 +-v 2 +-l QSH:NTRU-AES256-SHA + +# server TLSv1.2 NTRU_RC4 +-v 3 +-l QSH:NTRU-RC4-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.2 NTRU_RC4 +-v 3 +-l QSH:NTRU-RC4-SHA + +# server TLSv1.2 NTRU_DES3 +-v 3 +-l QSH:NTRU-DES-CBC3-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.2 NTRU_DES3 +-v 3 +-l QSH:NTRU-DES-CBC3-SHA + +# server TLSv1.2 NTRU_AES128 +-v 3 +-l QSH:NTRU-AES128-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.2 NTRU_AES128 +-v 3 +-l QSH:NTRU-AES128-SHA diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-sctp-sha2.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-sctp-sha2.conf new file mode 100644 index 000000000..4c72d4b40 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-sctp-sha2.conf @@ -0,0 +1,67 @@ +# server DTLSv1 AES128-SHA256 +-G +-v 2 +-l AES128-SHA256 + +# client DTLSv1 AES128-SHA256 +-G +-v 2 +-l AES128-SHA256 + +# server DTLSv1 AES256-SHA256 +-G +-v 2 +-l AES256-SHA256 + +# client DTLSv1 AES256-SHA256 +-G +-v 2 +-l AES256-SHA256 + +# server TLSv1 ECDHE-PSK-AES128-SHA256 +-s +-G +-v 1 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1 ECDHE-PSK-AES128-SHA256 +-s +-G +-v 1 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1.1 ECDHE-PSK-AES128-SHA256 +-s +-G +-v 2 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1.1 ECDHE-PSK-AES128-SHA256 +-s +-G +-v 2 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1 ECDHE-PSK-NULL-SHA256 +-s +-G +-v 1 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1 ECDHE-PSK-NULL-SHA256 +-s +-G +-v 1 +-l ECDHE-PSK-NULL-SHA256 + +# server TLSv1.1 ECDHE-PSK-NULL-SHA256 +-s +-G +-v 2 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1.1 ECDHE-PSK-NULL-SHA256 +-s +-G +-v 2 +-l ECDHE-PSK-NULL-SHA256 diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-sctp.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-sctp.conf new file mode 100644 index 000000000..a2c2bc052 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-sctp.conf @@ -0,0 +1,1042 @@ +# server DTLSv1 DHE-RSA-CHACHA20-POLY1305 +-G +-v 2 +-l DHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1 DHE-RSA-CHACHA20-POLY1305 +-G +-v 2 +-l DHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1 ECDHE-RSA-CHACHA20-POLY1305 +-G +-v 2 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1 ECDHE-RSA-CHACHA20-POLY1305 +-G +-v 2 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1 ECDHE-EDCSA-CHACHA20-POLY1305 +-G +-v 2 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1 ECDHE-ECDSA-CHACHA20-POLY1305 +-G +-v 2 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 +-G +-v 3 +-l DHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 +-G +-v 3 +-l DHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 +-G +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 +-G +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305 +-G +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305 +-G +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-G +-v 3 +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-G +-v 3 +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-G +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-G +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 PSK-CHACHA20-POLY1305 +-G +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# client TLSv1.2 PSK-CHACHA20-POLY1305 +-G +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-G +-v 3 +-l DHE-RSA-CHACHA20-POLY1305-OLD + +# client DTLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-G +-v 3 +-l DHE-RSA-CHACHA20-POLY1305-OLD + +# server DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-G +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305-OLD + +# client DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-G +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305-OLD + +# server DTLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305-OLD +-G +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-G +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1 RC4-SHA +-G +-v 2 +-l RC4-SHA + +# client DTLSv1 RC4-SHA +-G +-v 2 +-l RC4-SHA + +# server DTLSv1.2 RC4-SHA +-G +-v 3 +-l RC4-SHA + +# client DTLSv1.2 RC4-SHA +-G +-v 3 +-l RC4-SHA + +# server DTLSv1 IDEA-CBC-SHA +-G +-v 2 +-l IDEA-CBC-SHA + +# client DTLSv1 IDEA-CBC-SHA +-G +-v 2 +-l IDEA-CBC-SHA + +# server DTLSv1 DES-CBC3-SHA +-G +-v 2 +-l DES-CBC3-SHA + +# client DTLSv1 DES-CBC3-SHA +-G +-v 2 +-l DES-CBC3-SHA + +# server DTLSv1.2 DES-CBC3-SHA +-G +-v 3 +-l DES-CBC3-SHA + +# client DTLSv1.2 DES-CBC3-SHA +-G +-v 3 +-l DES-CBC3-SHA + +# server DTLSv1 AES128-SHA +-G +-v 2 +-l AES128-SHA + +# client DTLSv1 AES128-SHA +-G +-v 2 +-l AES128-SHA + +# server DTLSv1.2 AES128-SHA +-G +-v 3 +-l AES128-SHA + +# client DTLSv1.2 AES128-SHA +-G +-v 3 +-l AES128-SHA + +# server DTLSv1 AES256-SHA +-G +-v 2 +-l AES256-SHA + +# client DTLSv1 AES256-SHA +-G +-v 2 +-l AES256-SHA + +# server DTLSv1.2 AES256-SHA +-G +-v 3 +-l AES256-SHA + +# client DTLSv1.2 AES256-SHA +-G +-v 3 +-l AES256-SHA + +# server DTLSv1.2 AES128-SHA256 +-G +-v 3 +-l AES128-SHA256 + +# client DTLSv1.2 AES128-SHA256 +-G +-v 3 +-l AES128-SHA256 + +# server DTLSv1.2 AES256-SHA256 +-G +-v 3 +-l AES256-SHA256 + +# client DTLSv1.2 AES256-SHA256 +-G +-v 3 +-l AES256-SHA256 + +# server DTLSv1 ECDHE-RSA-RC4 +-G +-v 2 +-l ECDHE-RSA-RC4-SHA + +# client DTLSv1 ECDHE-RSA-RC4 +-G +-v 2 +-l ECDHE-RSA-RC4-SHA + +# server DTLSv1.1 ECDHE-RSA-DES3 +-G +-v 2 +-l ECDHE-RSA-DES-CBC3-SHA + +# client DTLSv1.1 ECDHE-RSA-DES3 +-G +-v 2 +-l ECDHE-RSA-DES-CBC3-SHA + +# server DTLSv1.1 ECDHE-RSA-AES128 +-G +-v 2 +-l ECDHE-RSA-AES128-SHA + +# client DTLSv1.1 ECDHE-RSA-AES128 +-G +-v 2 +-l ECDHE-RSA-AES128-SHA + +# server DTLSv1.1 ECDHE-RSA-AES256 +-G +-v 2 +-l ECDHE-RSA-AES256-SHA + +# client DTLSv1.1 ECDHE-RSA-AES256 +-G +-v 2 +-l ECDHE-RSA-AES256-SHA + +# server DTLSv1.2 ECDHE-RSA-RC4 +-G +-v 3 +-l ECDHE-RSA-RC4-SHA + +# client DTLSv1.2 ECDHE-RSA-RC4 +-G +-v 3 +-l ECDHE-RSA-RC4-SHA + +# server DTLSv1.2 ECDHE-RSA-DES3 +-G +-v 3 +-l ECDHE-RSA-DES-CBC3-SHA + +# client DTLSv1.2 ECDHE-RSA-DES3 +-G +-v 3 +-l ECDHE-RSA-DES-CBC3-SHA + +# server DTLSv1.2 ECDHE-RSA-AES128 +-G +-v 3 +-l ECDHE-RSA-AES128-SHA + +# client DTLSv1.2 ECDHE-RSA-AES128 +-G +-v 3 +-l ECDHE-RSA-AES128-SHA + +# server DTLSv1.2 ECDHE-RSA-AES128-SHA256 +-G +-v 3 +-l ECDHE-RSA-AES128-SHA256 + +# client DTLSv1.2 ECDHE-RSA-AES128-SHA256 +-G +-v 3 +-l ECDHE-RSA-AES128-SHA256 + +# server DTLSv1.2 ECDHE-RSA-AES256 +-G +-v 3 +-l ECDHE-RSA-AES256-SHA + +# client DTLSv1.2 ECDHE-RSA-AES256 +-G +-v 3 +-l ECDHE-RSA-AES256-SHA + +# server TLSv1 ECDHE-ECDSA-NULL-SHA +-G +-v 1 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-G +-v 1 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDHE-ECDSA-NULL-SHA +-G +-v 2 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-G +-v 2 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-NULL-SHA +-G +-v 3 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-NULL-SHA +-G +-v 3 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDHE-EDCSA-RC4 +-G +-v 2 +-l ECDHE-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-RC4 +-G +-v 2 +-l ECDHE-ECDSA-RC4-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDHE-ECDSA-DES3 +-G +-v 2 +-l ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-DES3 +-G +-v 2 +-l ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDHE-ECDSA-AES128 +-G +-v 2 +-l ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-AES128 +-G +-v 2 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDHE-ECDSA-AES256 +-G +-v 2 +-l ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-AES256 +-G +-v 2 +-l ECDHE-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-RC4 +-G +-v 3 +-l ECDHE-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-RC4 +-G +-v 3 +-l ECDHE-ECDSA-RC4-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-DES3 +-G +-v 3 +-l ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-DES3 +-G +-v 3 +-l ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128 +-G +-v 3 +-l ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128 +-G +-v 3 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-G +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-G +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256 +-G +-v 3 +-l ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256 +-G +-v 3 +-l ECDHE-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDH-RSA-RC4 +-G +-v 2 +-l ECDH-RSA-RC4-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-RC4 +-G +-v 2 +-l ECDH-RSA-RC4-SHA + +# server DTLSv1.1 ECDH-RSA-DES3 +-G +-v 2 +-l ECDH-RSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-DES3 +-G +-v 2 +-l ECDH-RSA-DES-CBC3-SHA + +# server DTLSv1.1 ECDH-RSA-AES128 +-G +-v 2 +-l ECDH-RSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-AES128 +-G +-v 2 +-l ECDH-RSA-AES128-SHA + +# server DTLSv1.1 ECDH-RSA-AES256 +-G +-v 2 +-l ECDH-RSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-AES256 +-G +-v 2 +-l ECDH-RSA-AES256-SHA + +# server DTLSv1.2 ECDH-RSA-RC4 +-G +-v 3 +-l ECDH-RSA-RC4-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-RC4 +-G +-v 3 +-l ECDH-RSA-RC4-SHA + +# server DTLSv1.2 ECDH-RSA-DES3 +-G +-v 3 +-l ECDH-RSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-DES3 +-G +-v 3 +-l ECDH-RSA-DES-CBC3-SHA + +# server DTLSv1.2 ECDH-RSA-AES128 +-G +-v 3 +-l ECDH-RSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES128 +-G +-v 3 +-l ECDH-RSA-AES128-SHA + +# server DTLSv1.2 ECDH-RSA-AES128-SHA256 +-G +-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 +-G +-v 3 +-l ECDH-RSA-AES128-SHA256 + +# server DTLSv1.2 ECDH-RSA-AES256 +-G +-v 3 +-l ECDH-RSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES256 +-G +-v 3 +-l ECDH-RSA-AES256-SHA + +# server DTLSv1.1 ECDH-EDCSA-RC4 +-G +-v 2 +-l ECDH-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-RC4 +-G +-v 2 +-l ECDH-ECDSA-RC4-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDH-ECDSA-DES3 +-G +-v 2 +-l ECDH-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-DES3 +-G +-v 2 +-l ECDH-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDH-ECDSA-AES128 +-G +-v 2 +-l ECDH-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-AES128 +-G +-v 2 +-l ECDH-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.1 ECDH-ECDSA-AES256 +-G +-v 2 +-l ECDH-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-AES256 +-G +-v 2 +-l ECDH-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-RC4 +-G +-v 3 +-l ECDH-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-RC4 +-G +-v 3 +-l ECDH-ECDSA-RC4-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-DES3 +-G +-v 3 +-l ECDH-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-DES3 +-G +-v 3 +-l ECDH-ECDSA-DES-CBC3-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES128 +-G +-v 3 +-l ECDH-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES128 +-G +-v 3 +-l ECDH-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES128-SHA256 +-G +-v 3 +-l ECDH-ECDSA-AES128-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES128-SHA256 +-G +-v 3 +-l ECDH-ECDSA-AES128-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES256 +-G +-v 3 +-l ECDH-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES256 +-G +-v 3 +-l ECDH-ECDSA-AES256-SHA +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-RSA-AES256-SHA384 +-G +-v 3 +-l ECDHE-RSA-AES256-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-SHA384 +-G +-v 3 +-l ECDHE-RSA-AES256-SHA384 + +# server DTLSv1.2 ECDHE-ECDSA-AES256-SHA384 +-G +-v 3 +-l ECDHE-ECDSA-AES256-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-SHA384 +-G +-v 3 +-l ECDHE-ECDSA-AES256-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-RSA-AES256-SHA384 +-G +-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 +-G +-v 3 +-l ECDH-RSA-AES256-SHA384 + +# server DTLSv1.2 ECDH-ECDSA-AES256-SHA384 +-G +-v 3 +-l ECDH-ECDSA-AES256-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES256-SHA384 +-G +-v 3 +-l ECDH-ECDSA-AES256-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-G +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-G +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-G +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-G +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# server DTLSv1 PSK-AES128 +-s +-G +-v 2 +-l PSK-AES128-CBC-SHA + +# client DTLSv1 PSK-AES128 +-s +-G +-v 2 +-l PSK-AES128-CBC-SHA + +# server DTLSv1 PSK-AES256 +-s +-G +-v 2 +-l PSK-AES256-CBC-SHA + +# client DTLSv1 PSK-AES256 +-s +-G +-v 2 +-l PSK-AES256-CBC-SHA + +# server DTLSv1.2 PSK-AES128 +-s +-G +-v 3 +-l PSK-AES128-CBC-SHA + +# client DTLSv1.2 PSK-AES128 +-s +-G +-v 3 +-l PSK-AES128-CBC-SHA + +# server DTLSv1.2 PSK-AES256 +-s +-G +-v 3 +-l PSK-AES256-CBC-SHA + +# client DTLSv1.2 PSK-AES256 +-s +-G +-v 3 +-l PSK-AES256-CBC-SHA + +# server DTLSv1.2 PSK-AES128-SHA256 +-s +-G +-v 3 +-l PSK-AES128-CBC-SHA256 + +# client DTLSv1.2 PSK-AES128-SHA256 +-s +-G +-v 3 +-l PSK-AES128-CBC-SHA256 + +# server DTLSv1.2 PSK-AES256-SHA384 +-s +-G +-v 3 +-l PSK-AES256-CBC-SHA384 + +# client DTLSv1.2 PSK-AES256-SHA384 +-s +-G +-v 3 +-l PSK-AES256-CBC-SHA384 + +# server DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-G +-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 +-G +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +-G +-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 +-G +-v 3 +-l ECDH-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDH-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDH-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +-G +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# client DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +-G +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# server DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# server DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +-G +-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 +-G +-v 3 +-l ECDH-RSA-AES128-GCM-SHA256 + +# server DTLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDH-RSA-AES256-GCM-SHA384 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDH-RSA-AES256-GCM-SHA384 + +# server DTLSv1.2 PSK-AES128-GCM-SHA256 +-G +-s +-v 3 +-l PSK-AES128-GCM-SHA256 + +# client DTLSv1.2 PSK-AES128-GCM-SHA256 +-G +-s +-v 3 +-l PSK-AES128-GCM-SHA256 + +# server DTLSv1.2 PSK-AES256-GCM-SHA384 +-G +-s +-v 3 +-l PSK-AES256-GCM-SHA384 + +# client DTLSv1.2 PSK-AES256-GCM-SHA384 +-G +-s +-v 3 +-l PSK-AES256-GCM-SHA384 + +# server DTLSv1.2 ECDHE-ECDSA-AES128-CCM +-G +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-CCM +-G +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-G +-v 3 +-l ECDHE-ECDSA-AES128-CCM-8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-G +-v 3 +-l ECDHE-ECDSA-AES128-CCM-8 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +-G +-v 3 +-l ECDHE-ECDSA-AES256-CCM-8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +-G +-v 3 +-l ECDHE-ECDSA-AES256-CCM-8 +-A ./certs/ca-ecc-cert.pem + +# server DTLSv1.2 ADH-AES128-SHA +-G +-a +-v 3 +-l ADH-AES128-SHA + +# client DTLSv1.2 ADH-AES128-SHA +-G +-a +-v 3 +-l ADH-AES128-SHA + +# server DTLSv1.0 ADH-AES128-SHA +-G +-a +-v 2 +-l ADH-AES128-SHA + +# client DTLSv1.0 ADH-AES128-SHA +-G +-a +-v 2 +-l ADH-AES128-SHA diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-sha2.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-sha2.conf new file mode 100644 index 000000000..f9780eedd --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-sha2.conf @@ -0,0 +1,403 @@ +# server TLSv1 AES128-SHA256 +-v 1 +-l AES128-SHA256 + +# client TLSv1 AES128-SHA256 +-v 1 +-l AES128-SHA256 + +# server TLSv1 AES256-SHA256 +-v 1 +-l AES256-SHA256 + +# client TLSv1 AES256-SHA256 +-v 1 +-l AES256-SHA256 + +# server TLSv1.1 AES128-SHA256 +-v 2 +-l AES128-SHA256 + +# client TLSv1.1 AES128-SHA256 +-v 2 +-l AES128-SHA256 + +# server TLSv1.1 AES256-SHA256 +-v 2 +-l AES256-SHA256 + +# client TLSv1.1 AES256-SHA256 +-v 2 +-l AES256-SHA256 + +# server TLSv1 DHE AES128-SHA256 +-v 1 +-l DHE-RSA-AES128-SHA256 + +# client TLSv1 DHE AES128-SHA256 +-v 1 +-l DHE-RSA-AES128-SHA256 + +# server TLSv1 DHE AES256-SHA256 +-v 1 +-l DHE-RSA-AES256-SHA256 + +# client TLSv1 DHE AES256-SHA256 +-v 1 +-l DHE-RSA-AES256-SHA256 + +# server TLSv1.1 DHE AES128-SHA256 +-v 2 +-l DHE-RSA-AES128-SHA256 + +# client TLSv1.1 DHE AES128-SHA256 +-v 2 +-l DHE-RSA-AES128-SHA256 + +# server TLSv1.1 DHE AES256-SHA256 +-v 2 +-l DHE-RSA-AES256-SHA256 + +# client TLSv1.1 DHE AES256-SHA256 +-v 2 +-l DHE-RSA-AES256-SHA256 + +# server TLSv1 ECDHE-PSK-NULL-SHA256 +-s +-v 1 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1 ECDHE-PSK-NULL-SHA256 +-s +-v 1 +-l ECDHE-PSK-NULL-SHA256 + +# server TLSv1.1 ECDHE-PSK-NULL-SHA256 +-s +-v 2 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1.1 ECDHE-PSK-NULL-SHA256 +-s +-v 2 +-l ECDHE-PSK-NULL-SHA256 + +# server TLSv1 ECDHE-PSK-AES128-SHA256 +-s +-v 1 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1 ECDHE-PSK-AES128-SHA256 +-s +-v 1 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1.1 ECDHE-PSK-AES128-SHA256 +-s +-v 2 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1.1 ECDHE-PSK-AES128-SHA256 +-s +-v 2 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1.0 PSK-AES128-SHA256 +-s +-v 1 +-l PSK-AES128-CBC-SHA256 + +# client TLSv1.0 PSK-AES128-SHA256 +-s +-v 1 +-l PSK-AES128-CBC-SHA256 + +# server TLSv1.1 PSK-AES128-SHA256 +-s +-v 2 +-l PSK-AES128-CBC-SHA256 + +# client TLSv1.1 PSK-AES128-SHA256 +-s +-v 2 +-l PSK-AES128-CBC-SHA256 + +# server TLSv1.0 PSK-AES256-SHA384 +-s +-v 1 +-l PSK-AES256-CBC-SHA384 + +# client TLSv1.0 PSK-AES256-SHA384 +-s +-v 1 +-l PSK-AES256-CBC-SHA384 + +# server TLSv1.1 PSK-AES256-SHA384 +-s +-v 2 +-l PSK-AES256-CBC-SHA384 + +# client TLSv1.1 PSK-AES256-SHA384 +-s +-v 2 +-l PSK-AES256-CBC-SHA384 + +# server TLSv1.0 RSA-NULL-SHA256 +-v 1 +-l NULL-SHA256 + +# client TLSv1.0 RSA-NULL-SHA256 +-v 1 +-l NULL-SHA256 + +# server TLSv1.1 RSA-NULL-SHA256 +-v 2 +-l NULL-SHA256 + +# client TLSv1.1 RSA-NULL-SHA256 +-v 2 +-l NULL-SHA256 + +# server TLSv1 CAMELLIA128-SHA256 +-v 1 +-l CAMELLIA128-SHA256 + +# client TLSv1 CAMELLIA128-SHA256 +-v 1 +-l CAMELLIA128-SHA256 + +# server TLSv1 CAMELLIA256-SHA256 +-v 1 +-l CAMELLIA256-SHA256 + +# client TLSv1 CAMELLIA256-SHA256 +-v 1 +-l CAMELLIA256-SHA256 + +# server TLSv1.1 CAMELLIA128-SHA256 +-v 2 +-l CAMELLIA128-SHA256 + +# client TLSv1.1 CAMELLIA128-SHA256 +-v 2 +-l CAMELLIA128-SHA256 + +# server TLSv1.1 CAMELLIA256-SHA256 +-v 2 +-l CAMELLIA256-SHA256 + +# client TLSv1.1 CAMELLIA256-SHA256 +-v 2 +-l CAMELLIA256-SHA256 + +# server TLSv1 DHE-RSA-CAMELLIA128-SHA256 +-v 1 +-l DHE-RSA-CAMELLIA128-SHA256 + +# client TLSv1 DHE-RSA-CAMELLIA128-SHA256 +-v 1 +-l DHE-RSA-CAMELLIA128-SHA256 + +# server TLSv1 DHE-RSA-CAMELLIA256-SHA256 +-v 1 +-l DHE-RSA-CAMELLIA256-SHA256 + +# client TLSv1 DHE-RSA-CAMELLIA256-SHA256 +-v 1 +-l DHE-RSA-CAMELLIA256-SHA256 + +# server TLSv1.1 DHE-RSA-CAMELLIA128-SHA256 +-v 2 +-l DHE-RSA-CAMELLIA128-SHA256 + +# client TLSv1.1 DHE-RSA-CAMELLIA128-SHA256 +-v 2 +-l DHE-RSA-CAMELLIA128-SHA256 + +# server TLSv1.1 DHE-RSA-CAMELLIA256-SHA256 +-v 2 +-l DHE-RSA-CAMELLIA256-SHA256 + +# client TLSv1.1 DHE-RSA-CAMELLIA256-SHA256 +-v 2 +-l DHE-RSA-CAMELLIA256-SHA256 + +# server TLSv1.0 DHE-PSK-AES128-CBC-SHA256 +-s +-v 1 +-l DHE-PSK-AES128-CBC-SHA256 + +# client TLSv1.0 DHE-PSK-AES128-CBC-SHA256 +-s +-v 1 +-l DHE-PSK-AES128-CBC-SHA256 + +# server TLSv1.1 DHE-PSK-AES128-CBC-SHA256 +-s +-v 2 +-l DHE-PSK-AES128-CBC-SHA256 + +# client TLSv1.1 DHE-PSK-AES128-CBC-SHA256 +-s +-v 2 +-l DHE-PSK-AES128-CBC-SHA256 + +# server TLSv1.0 DHE-PSK-AES256-CBC-SHA384 +-s +-v 1 +-l DHE-PSK-AES256-CBC-SHA384 + +# client TLSv1.0 DHE-PSK-AES256-CBC-SHA384 +-s +-v 1 +-l DHE-PSK-AES256-CBC-SHA384 + +# server TLSv1.1 DHE-PSK-AES256-CBC-SHA384 +-s +-v 2 +-l DHE-PSK-AES256-CBC-SHA384 + +# client TLSv1.1 DHE-PSK-AES256-CBC-SHA384 +-s +-v 2 +-l DHE-PSK-AES256-CBC-SHA384 + +# server TLSv1.0 DHE-PSK-NULL-SHA256 +-s +-v 1 +-l DHE-PSK-NULL-SHA256 + +# client TLSv1.0 DHE-PSK-NULL-SHA256 +-s +-v 1 +-l DHE-PSK-NULL-SHA256 + +# server TLSv1.1 DHE-PSK-NULL-SHA256 +-s +-v 2 +-l DHE-PSK-NULL-SHA256 + +# client TLSv1.1 DHE-PSK-NULL-SHA256 +-s +-v 2 +-l DHE-PSK-NULL-SHA256 + +# server TLSv1.0 DHE-PSK-AES256-CBC-SHA384 +-s +-v 1 +-l DHE-PSK-AES256-CBC-SHA384 + +# client TLSv1.0 DHE-PSK-AES256-CBC-SHA384 +-s +-v 1 +-l DHE-PSK-AES256-CBC-SHA384 + +# server TLSv1.1 DHE-PSK-AES256-CBC-SHA384 +-s +-v 2 +-l DHE-PSK-AES256-CBC-SHA384 + +# client TLSv1.1 DHE-PSK-AES256-CBC-SHA384 +-s +-v 2 +-l DHE-PSK-AES256-CBC-SHA384 + +# server TLSv1.0 DHE-PSK-NULL-SHA256 +-s +-v 1 +-l DHE-PSK-NULL-SHA256 + +# client TLSv1.0 DHE-PSK-NULL-SHA256 +-s +-v 1 +-l DHE-PSK-NULL-SHA256 + +# server TLSv1.1 DHE-PSK-NULL-SHA256 +-s +-v 2 +-l DHE-PSK-NULL-SHA256 + +# client TLSv1.1 DHE-PSK-NULL-SHA256 +-s +-v 2 +-l DHE-PSK-NULL-SHA256 + +# server TLSv1.0 DHE-PSK-NULL-SHA384 +-s +-v 1 +-l DHE-PSK-NULL-SHA384 + +# client TLSv1.0 DHE-PSK-NULL-SHA384 +-s +-v 1 +-l DHE-PSK-NULL-SHA384 + +# server TLSv1.1 DHE-PSK-NULL-SHA384 +-s +-v 2 +-l DHE-PSK-NULL-SHA384 + +# client TLSv1.1 DHE-PSK-NULL-SHA384 +-s +-v 2 +-l DHE-PSK-NULL-SHA384 + +# server TLSv1.0 DHE-PSK-AES256-CBC-SHA384 +-s +-v 1 +-l DHE-PSK-AES256-CBC-SHA384 + +# client TLSv1.0 DHE-PSK-AES256-CBC-SHA384 +-s +-v 1 +-l DHE-PSK-AES256-CBC-SHA384 + +# server TLSv1.1 DHE-PSK-AES256-CBC-SHA384 +-s +-v 2 +-l DHE-PSK-AES256-CBC-SHA384 + +# client TLSv1.1 DHE-PSK-AES256-CBC-SHA384 +-s +-v 2 +-l DHE-PSK-AES256-CBC-SHA384 + +# server TLSv1.0 DHE-PSK-NULL-SHA256 +-s +-v 1 +-l DHE-PSK-NULL-SHA256 + +# client TLSv1.0 DHE-PSK-NULL-SHA256 +-s +-v 1 +-l DHE-PSK-NULL-SHA256 + +# server TLSv1.1 DHE-PSK-NULL-SHA256 +-s +-v 2 +-l DHE-PSK-NULL-SHA256 + +# client TLSv1.1 DHE-PSK-NULL-SHA256 +-s +-v 2 +-l DHE-PSK-NULL-SHA256 + +# server TLSv1.0 DHE-PSK-NULL-SHA384 +-s +-v 1 +-l DHE-PSK-NULL-SHA384 + +# client TLSv1.0 DHE-PSK-NULL-SHA384 +-s +-v 1 +-l DHE-PSK-NULL-SHA384 + +# server TLSv1.1 DHE-PSK-NULL-SHA384 +-s +-v 2 +-l DHE-PSK-NULL-SHA384 + +# client TLSv1.1 DHE-PSK-NULL-SHA384 +-s +-v 2 +-l DHE-PSK-NULL-SHA384 diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-sig.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-sig.conf new file mode 100644 index 000000000..680eb3506 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-sig.conf @@ -0,0 +1,219 @@ +# server TLSv1 ECDHE-ECDSA-DES3 +-v 1 +-l ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-DES3 +-v 1 +-l ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/ca-cert.pem + +# 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 +-v 1 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1 ECDHE-ECDSA-AES128 +-v 1 +-l ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-AES128 +-v 1 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-cert.pem + +# server TLSv1 ECDHE-ECDSA-AES256 +-v 1 +-l ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-AES256 +-v 1 +-l ECDHE-ECDSA-AES256-SHA +-A ./certs/ca-cert.pem + +# server TLSv1.1 ECDHE-ECDSA-DES3 +-v 2 +-l ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDHE-ECDSA-DES3 +-v 2 +-l ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/ca-cert.pem + +# 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 +-v 2 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDHE-ECDSA-AES128 +-v 2 +-l ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDHE-ECDSA-AES128 +-v 2 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-cert.pem + +# server TLSv1.1 ECDHE-ECDSA-AES256 +-v 2 +-l ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.1 ECDHE-ECDSA-AES256 +-v 2 +-l ECDHE-ECDSA-AES256-SHA +-A ./certs/ca-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-DES3 +-v 3 +-l ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-DES3 +-v 3 +-l ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/ca-cert.pem + +# 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 +-v 3 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-A ./certs/ca-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES256 +-v 3 +-l ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256 +-v 3 +-l ECDHE-ECDSA-AES256-SHA +-A ./certs/ca-cert.pem + +# server TLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305 +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305 +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-A ./certs/ca-cert.pem + +# server TLSv1.2 ECDH-ECDSA-AES128-SHA256 +-v 3 +-l ECDH-ECDSA-AES128-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-ECDSA-AES128-SHA256 +-v 3 +-l ECDH-ECDSA-AES128-SHA256 +-A ./certs/ca-cert.pem + +# server TLSv1.2 ECDH-ECDSA-AES256 +-v 3 +-l ECDH-ECDSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-ECDSA-AES256 +-v 3 +-l ECDH-ECDSA-AES256-SHA +-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-key.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-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 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES128-CCM +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-CCM +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-A ./certs/ca-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-v 3 +-l ECDHE-ECDSA-AES128-CCM-8 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-v 3 +-l ECDHE-ECDSA-AES128-CCM-8 +-A ./certs/ca-cert.pem diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13-down.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13-down.conf new file mode 100644 index 000000000..181b286eb --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13-down.conf @@ -0,0 +1,44 @@ +# THIS TEST IS BROKEN +# server TLSv1.3 downgrade +#-v d +#-l TLS13-CHACHA20-POLY1305-SHA256 + +# client TLSv1.2 +#-v 3 + +# server TLSv1.2 +-v 3 + +# client TLSv1.3 downgrade +-v d + +# server TLSv1.3 downgrade +-v d + +# client TLSv1.3 downgrade +-v d + +# server TLSv1.3 downgrade but don't and resume +-v d +-r + +# client TLSv1.3 downgrade but don't and resume +-v d +-r + +# server TLSv1.3 downgrade and resume +-v d +-r + +# client TLSv1.2 and resume +-v 3 +-r + +# server TLSv1.2 and resume +-v d +-r + +# lcient TLSv1.3 downgrade and resume +-v 3 +-r + diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13-ecc.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13-ecc.conf new file mode 100644 index 000000000..ee14f5406 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13-ecc.conf @@ -0,0 +1,93 @@ +# server TLSv1.3 TLS13-CHACHA20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACHA20-POLY1305-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-CHACHA20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACHA20-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 +-t + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-t + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem +-8 + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-8 + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem +-Y + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-y diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13-psk.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13-psk.conf new file mode 100644 index 000000000..b8b7e2607 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13-psk.conf @@ -0,0 +1,31 @@ +# server TLSv1.3 PSK +-v 4 +-s +-l TLS13-AES128-GCM-SHA256 +-d + +# client TLSv1.3 PSK +-v 4 +-s +-l TLS13-AES128-GCM-SHA256 + +# server TLSv1.3 PSK +-v 4 +-j +-l TLS13-AES128-GCM-SHA256 +-d + +# client TLSv1.3 PSK +-v 4 +-s +-l TLS13-AES128-GCM-SHA256 + +# server TLSv1.3 PSK +-v 4 +-j +-l TLS13-AES128-GCM-SHA256 +-d + +# client TLSv1.3 not-PSK +-v 4 +-l TLS13-AES128-GCM-SHA256 diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13.conf new file mode 100644 index 000000000..c75b27fe1 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-tls13.conf @@ -0,0 +1,211 @@ +# server TLSv1.3 TLS13-CHACHA20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACHA20-POLY1305-SHA256 + +# client TLSv1.3 TLS13-CHACHA20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACHA20-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 resumption +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r + +# client TLSv1.3 resumption +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r + +# server TLSv1.3 resumption - SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 +-r + +# client TLSv1.3 resumption - SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 +-r + +# server TLSv1.3 PSK without (EC)DHE +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r + +# client TLSv1.3 PSK without (EC)DHE +-v 4 +-l TLS13-AES128-GCM-SHA256 +-r +-K + +# 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 + +# server TLSv1.3 +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# client TLSv1.3 Fragments +-v 4 +-l TLS13-AES128-GCM-SHA256 +-F 1 + +# server TLSv1.3 +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# client TLSv1.3 HelloRetryRequest to negotiate Key Exchange algorithm +-v 4 +-l TLS13-AES128-GCM-SHA256 +-J + +# server TLSv1.3 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-J + +# client TLSv1.3 HelloRetryRequest with cookie +-v 4 +-l TLS13-AES128-GCM-SHA256 +-J + +# server TLSv1.3 +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# client TLSv1.3 no client certificate +-v 4 +-l TLS13-AES128-GCM-SHA256 +-x + +# server TLSv1.3 +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# client TLSv1.3 DH key exchange +-v 4 +-l TLS13-AES128-GCM-SHA256 +-y + +# server TLSv1.3 +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# client TLSv1.3 ECC key exchange +-v 4 +-l TLS13-AES128-GCM-SHA256 +-Y + +# server TLSv1.3 +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# client TLSv1.3 ECC key exchange +-v 4 +-l TLS13-AES128-GCM-SHA256 +-Y + +# server TLSv1.3 multiple cipher suites +-v 4 +-l TLS13-AES128-GCM-SHA256:TLS13-AES256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES128-CCM-SHA256:TLS13-AES128-CCM-8-SHA256 + +# client TLSv1.3 +-v 4 + +# server TLSv1.3 KeyUpdate +-v 4 +-l TLS13-AES128-GCM-SHA256 +-U + +# client TLSv1.3 KeyUpdate +-v 4 +-l TLS13-AES128-GCM-SHA256 +-I + +# server TLSv1.3 Post-Handshake Authentication +-v 4 +-l TLS13-AES128-GCM-SHA256 +-Q + +# client TLSv1.3 Post-Handshake Authentication +-v 4 +-l TLS13-AES128-GCM-SHA256 +-Q + +# server TLSv1.3 Integrity-only SHA256 +-v 4 +-l TLS13-SHA256-SHA256 + +# client TLSv1.3 Integrity-only SHA256 +-v 4 +-l TLS13-SHA256-SHA256 + +# server TLSv1.3 Integrity-only SHA384 +-v 4 +-l TLS13-SHA384-SHA384 + +# client TLSv1.3 Integrity-only SHA384 +-v 4 +-l TLS13-SHA384-SHA384 diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test-trustpeer.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test-trustpeer.conf new file mode 100644 index 000000000..c8df70416 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test-trustpeer.conf @@ -0,0 +1,99 @@ +# Both client and server use -E [path] for trusted peer +# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Trusted Peer +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-E ./certs/intermediate/client-int-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-int-cert.pem + +# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 RSA Trusted Peer +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 +-E ./certs/intermediate/server-int-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-int-cert.pem + +# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Trusted Peer +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-E ./certs/intermediate/client-int-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-int-cert.pem + +# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 RSA Trusted Peer +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-E ./certs/intermediate/server-int-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-int-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Trusted Peer +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-E ./certs/intermediate/client-int-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-int-ecc-cert.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Trusted Peer +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-E ./certs/intermediate/server-int-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-int-ecc-cert.pem + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Trusted Peer +-v 4 +-l TLS13-AES128-GCM-SHA256 +-E ./certs/intermediate/client-int-cert.pem +-k ./certs/server-key.pem +-c ./certs/intermediate/server-int-cert.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 RSA Trusted Peer +-v 4 +-l TLS13-AES128-GCM-SHA256 +-E ./certs/intermediate/server-int-cert.pem +-k ./certs/client-key.pem +-c ./certs/intermediate/client-int-cert.pem + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Trusted Peer +-v 4 +-l TLS13-AES128-GCM-SHA256 +-E ./certs/intermediate/client-int-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/intermediate/server-int-ecc-cert.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Trusted Peer +-v 4 +-l TLS13-AES128-GCM-SHA256 +-E ./certs/intermediate/server-int-ecc-cert.pem +-k ./certs/ecc-client-key.pem +-c ./certs/intermediate/client-int-ecc-cert.pem + +# Test for ECC self signed certificate as trusted peer +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Trusted Peer (self signed) +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-E ./certs/client-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/server-ecc-self.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 ECC Trusted Peer (self signed) +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-E ./certs/server-ecc-self.pem +-k ./certs/ecc-client-key.pem +-c ./certs/client-ecc-cert.pem + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Trusted Peer (self signed) +-v 4 +-l TLS13-AES128-GCM-SHA256 +-E ./certs/client-ecc-cert.pem +-k ./certs/ecc-key.pem +-c ./certs/server-ecc-self.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 ECC Trusted Peer (self signed) +-v 4 +-l TLS13-AES128-GCM-SHA256 +-E ./certs/server-ecc-self.pem +-k ./certs/ecc-client-key.pem +-c ./certs/client-ecc-cert.pem diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/test.conf b/FreeRTOS-Plus/Source/WolfSSL/tests/test.conf index c949c2024..83c228bc3 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/tests/test.conf +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/test.conf @@ -1,57 +1,3 @@ -# server TLSv1 DHE-RSA-CHACHA20-POLY1305 --v 1 --l DHE-RSA-CHACHA20-POLY1305 - -# client TLSv1 DHE-RSA-CHACHA20-POLY1305 --v 1 --l DHE-RSA-CHACHA20-POLY1305 - -# server TLSv1 ECDHE-EDCSA-CHACHA20-POLY1305 --v 1 --l ECDHE-ECDSA-CHACHA20-POLY1305 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client TLSv1 ECDHE-ECDSA-CHACHA20-POLY1305 --v 1 --l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem - -# server TLSv1 ECDHE-RSA-CHACHA20-POLY1305 --v 1 --l ECDHE-RSA-CHACHA20-POLY1305 - -# client TLSv1 ECDHE-RSA-CHACHA20-POLY1305 --v 1 --l ECDHE-RSA-CHACHA20-POLY1305 - -# 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 @@ -61,7 +7,7 @@ -l DHE-RSA-CHACHA20-POLY1305 # server TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 --v 3 +-v 3 -l ECDHE-RSA-CHACHA20-POLY1305 # client TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 @@ -77,7 +23,64 @@ # 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 +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-v 3 +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 PSK-CHACHA20-POLY1305 +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# client TLSv1.2 PSK-CHACHA20-POLY1305 +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# server TLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-v 3 +-l DHE-RSA-CHACHA20-POLY1305-OLD + +# client TLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-v 3 +-l DHE-RSA-CHACHA20-POLY1305-OLD + +# server TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305-OLD + +# client TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305-OLD + +# server TLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305-OLD +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-A ./certs/ca-ecc-cert.pem # server SSLv3 RC4-SHA -v 0 @@ -103,6 +106,14 @@ -v 0 -l DES-CBC3-SHA +# server SSLv3 IDEA-CBC-SHA +-v 0 +-l IDEA-CBC-SHA + +# client SSLv3 IDEA-CBC-SHA +-v 0 +-l IDEA-CBC-SHA + # server TLSv1 RC4-SHA -v 1 -l RC4-SHA @@ -127,6 +138,14 @@ -v 1 -l DES-CBC3-SHA +# server TLSv1 IDEA-CBC-SHA +-v 1 +-l IDEA-CBC-SHA + +# client TLSv1 IDEA-CBC-SHA +-v 1 +-l IDEA-CBC-SHA + # server TLSv1 AES128-SHA -v 1 -l AES128-SHA @@ -143,22 +162,6 @@ -v 1 -l AES256-SHA -# server TLSv1 AES128-SHA256 --v 1 --l AES128-SHA256 - -# client TLSv1 AES128-SHA256 --v 1 --l AES128-SHA256 - -# server TLSv1 AES256-SHA256 --v 1 --l AES256-SHA256 - -# client TLSv1 AES256-SHA256 --v 1 --l AES256-SHA256 - # server TLSv1.1 RC4-SHA -v 2 -l RC4-SHA @@ -175,6 +178,14 @@ -v 2 -l RC4-MD5 +# server TLSv1.1 IDEA-CBC-SHA +-v 2 +-l IDEA-CBC-SHA + +# client TLSv1.1 IDEA-CBC-SHA +-v 2 +-l IDEA-CBC-SHA + # server TLSv1.1 DES-CBC3-SHA -v 2 -l DES-CBC3-SHA @@ -199,22 +210,6 @@ -v 2 -l AES256-SHA -# server TLSv1.1 AES128-SHA256 --v 2 --l AES128-SHA256 - -# client TLSv1.1 AES128-SHA256 --v 2 --l AES128-SHA256 - -# server TLSv1.1 AES256-SHA256 --v 2 --l AES256-SHA256 - -# client TLSv1.1 AES256-SHA256 --v 2 --l AES256-SHA256 - # server TLSv1.2 RC4-SHA -v 3 -l RC4-SHA @@ -287,11 +282,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 @@ -319,11 +314,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 @@ -351,11 +346,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 @@ -363,7 +358,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 @@ -375,6 +370,39 @@ -v 3 -l ECDHE-RSA-AES256-SHA +# server TLSv1 ECDHE-ECDSA-NULL-SHA +-v 1 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-v 1 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.1 ECDHE-ECDSA-NULL-SHA +-v 2 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-v 2 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-NULL-SHA +-v 3 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-NULL-SHA +-v 3 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/ca-ecc-cert.pem + # server TLSv1 ECDHE-ECDSA-RC4 -v 1 -l ECDHE-ECDSA-RC4-SHA @@ -384,7 +412,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 @@ -395,18 +423,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 @@ -417,7 +445,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 @@ -428,7 +456,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 @@ -439,18 +467,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 @@ -461,7 +489,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 @@ -472,7 +500,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 @@ -483,18 +511,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 @@ -505,7 +533,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 @@ -516,7 +544,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 @@ -538,13 +566,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 @@ -578,13 +606,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 @@ -618,23 +646,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 @@ -657,7 +685,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 @@ -668,18 +696,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 @@ -690,7 +718,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 @@ -701,7 +729,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 @@ -712,18 +740,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 @@ -734,7 +762,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 @@ -745,7 +773,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 @@ -756,18 +784,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 @@ -775,10 +803,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 @@ -789,13 +817,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 @@ -808,15 +836,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 @@ -826,10 +854,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 @@ -847,30 +875,6 @@ -v 1 -l HC128-MD5 -# server TLSv1 HC128-B2B256 --v 1 --l HC128-B2B256 - -# client TLSv1 HC128-B2B256 --v 1 --l HC128-B2B256 - -# server TLSv1 AES128-B2B256 --v 1 --l AES128-B2B256 - -# client TLSv1 AES128-B2B256 --v 1 --l AES128-B2B256 - -# server TLSv1 AES256-B2B256 --v 1 --l AES256-B2B256 - -# client TLSv1 AES256-B2B256 --v 1 --l AES256-B2B256 - # server TLSv1.1 HC128-SHA -v 2 -l HC128-SHA @@ -887,30 +891,6 @@ -v 2 -l HC128-MD5 -# server TLSv1.1 HC128-B2B256 --v 2 --l HC128-B2B256 - -# client TLSv1.1 HC128-B2B256 --v 2 --l HC128-B2B256 - -# server TLSv1.1 AES128-B2B256 --v 2 --l AES128-B2B256 - -# client TLSv1.1 AES128-B2B256 --v 2 --l AES128-B2B256 - -# server TLSv1.1 AES256-B2B256 --v 2 --l AES256-B2B256 - -# client TLSv1.1 AES256-B2B256 --v 2 --l AES256-B2B256 - # server TLSv1.2 HC128-SHA -v 3 -l HC128-SHA @@ -927,30 +907,6 @@ -v 3 -l HC128-MD5 -# server TLSv1.2 HC128-B2B256 --v 3 --l HC128-B2B256 - -# client TLSv1.2 HC128-B2B256 --v 3 --l HC128-B2B256 - -# server TLSv1.2 AES128-B2B256 --v 3 --l AES128-B2B256 - -# client TLSv1.2 AES128-B2B256 --v 3 --l AES128-B2B256 - -# server TLSv1.2 AES256-B2B256 --v 3 --l AES256-B2B256 - -# client TLSv1.2 AES256-B2B256 --v 3 --l AES256-B2B256 - # server TLSv1 RABBIT-SHA -v 1 -l RABBIT-SHA @@ -975,6 +931,838 @@ -v 3 -l RABBIT-SHA +# server TLSv1 DHE AES128 +-v 1 +-l DHE-RSA-AES128-SHA + +# client TLSv1 DHE AES128 +-v 1 +-l DHE-RSA-AES128-SHA + +# server TLSv1 DHE AES256 +-v 1 +-l DHE-RSA-AES256-SHA + +# client TLSv1 DHE AES256 +-v 1 +-l DHE-RSA-AES256-SHA + +# server TLSv1.1 DHE AES128 +-v 2 +-l DHE-RSA-AES128-SHA + +# client TLSv1.1 DHE AES128 +-v 2 +-l DHE-RSA-AES128-SHA + +# server TLSv1.1 DHE AES256 +-v 2 +-l DHE-RSA-AES256-SHA + +# client TLSv1.1 DHE AES256 +-v 2 +-l DHE-RSA-AES256-SHA + +# server TLSv1.1 DHE 3DES +-v 2 +-l EDH-RSA-DES-CBC3-SHA + +# client TLSv1.1 DHE 3DES +-v 2 +-l EDH-RSA-DES-CBC3-SHA + +# server TLSv1.2 DHE 3DES +-v 3 +-l EDH-RSA-DES-CBC3-SHA + +# client TLSv1.2 DHE 3DES +-v 3 +-l EDH-RSA-DES-CBC3-SHA + +# server TLSv1.2 DHE AES128 +-v 3 +-l DHE-RSA-AES128-SHA + +# client TLSv1.2 DHE AES128 +-v 3 +-l DHE-RSA-AES128-SHA + +# server TLSv1.2 DHE AES256 +-v 3 +-l DHE-RSA-AES256-SHA + +# client TLSv1.2 DHE AES256 +-v 3 +-l DHE-RSA-AES256-SHA + +# server TLSv1.2 DHE AES128-SHA256 +-v 3 +-l DHE-RSA-AES128-SHA256 + +# client TLSv1.2 DHE AES128-SHA256 +-v 3 +-l DHE-RSA-AES128-SHA256 + +# server TLSv1.2 DHE AES256-SHA256 +-v 3 +-l DHE-RSA-AES256-SHA256 + +# client TLSv1.2 DHE AES256-SHA256 +-v 3 +-l DHE-RSA-AES256-SHA256 + +# server TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# server TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1 PSK-AES128 +-s +-v 1 +-l PSK-AES128-CBC-SHA + +# client TLSv1 PSK-AES128 +-s +-v 1 +-l PSK-AES128-CBC-SHA + +# server TLSv1 PSK-AES256 +-s +-v 1 +-l PSK-AES256-CBC-SHA + +# client TLSv1 PSK-AES256 +-s +-v 1 +-l PSK-AES256-CBC-SHA + +# server TLSv1.1 PSK-AES128 +-s +-v 2 +-l PSK-AES128-CBC-SHA + +# client TLSv1.1 PSK-AES128 +-s +-v 2 +-l PSK-AES128-CBC-SHA + +# server TLSv1.1 PSK-AES256 +-s +-v 2 +-l PSK-AES256-CBC-SHA + +# client TLSv1.1 PSK-AES256 +-s +-v 2 +-l PSK-AES256-CBC-SHA + +# server TLSv1.2 PSK-AES128 +-s +-v 3 +-l PSK-AES128-CBC-SHA + +# client TLSv1.2 PSK-AES128 +-s +-v 3 +-l PSK-AES128-CBC-SHA + +# server TLSv1.2 PSK-AES256 +-s +-v 3 +-l PSK-AES256-CBC-SHA + +# client TLSv1.2 PSK-AES256 +-s +-v 3 +-l PSK-AES256-CBC-SHA + +# server TLSv1.2 PSK-AES128-SHA256 +-s +-v 3 +-l PSK-AES128-CBC-SHA256 + +# client TLSv1.2 PSK-AES128-SHA256 +-s +-v 3 +-l PSK-AES128-CBC-SHA256 + +# server TLSv1.2 PSK-AES256-SHA384 +-s +-v 3 +-l PSK-AES256-CBC-SHA384 + +# client TLSv1.2 PSK-AES256-SHA384 +-s +-v 3 +-l PSK-AES256-CBC-SHA384 + +# server TLSv1.0 PSK-NULL +-s +-v 1 +-l PSK-NULL-SHA + +# client TLSv1.0 PSK-NULL +-s +-v 1 +-l PSK-NULL-SHA + +# server TLSv1.1 PSK-NULL +-s +-v 2 +-l PSK-NULL-SHA + +# client TLSv1.1 PSK-NULL +-s +-v 2 +-l PSK-NULL-SHA + +# server TLSv1.2 PSK-NULL +-s +-v 3 +-l PSK-NULL-SHA + +# client TLSv1.2 PSK-NULL +-s +-v 3 +-l PSK-NULL-SHA + +# server TLSv1.2 PSK-NULL-SHA256 +-s +-v 3 +-l PSK-NULL-SHA256 + +# client TLSv1.2 PSK-NULL-SHA256 +-s +-v 3 +-l PSK-NULL-SHA256 + +# server TLSv1.2 PSK-NULL-SHA384 +-s +-v 3 +-l PSK-NULL-SHA384 + +# client TLSv1.2 PSK-NULL-SHA384 +-s +-v 3 +-l PSK-NULL-SHA384 + +# server TLSv1.2 PSK-NULL +-s +-v 3 +-l PSK-NULL-SHA + +# client TLSv1.2 PSK-NULL +-s +-v 3 +-l PSK-NULL-SHA + +# server TLSv1.2 PSK-NULL-SHA256 +-s +-v 3 +-l PSK-NULL-SHA256 + +# client TLSv1.2 PSK-NULL-SHA256 +-s +-v 3 +-l PSK-NULL-SHA256 + +# server TLSv1.0 RSA-NULL-MD5 +-v 1 +-l NULL-MD5 + +# client TLSv1.0 RSA-NULL-MD5 +-v 1 +-l NULL-MD5 + +# server TLSv1.1 RSA-NULL-MD5 +-v 2 +-l NULL-MD5 + +# client TLSv1.1 RSA-NULL-MD5 +-v 2 +-l NULL-MD5 + +# server TLSv1.2 RSA-NULL-MD5 +-v 3 +-l NULL-MD5 + +# client TLSv1.2 RSA-NULL-MD5 +-v 3 +-l NULL-MD5 + +# server TLSv1.0 RSA-NULL-SHA +-v 1 +-l NULL-SHA + +# client TLSv1.0 RSA-NULL-SHA +-v 1 +-l NULL-SHA + +# server TLSv1.1 RSA-NULL-SHA +-v 2 +-l NULL-SHA + +# client TLSv1.1 RSA-NULL-SHA +-v 2 +-l NULL-SHA + +# server TLSv1.2 RSA-NULL-SHA +-v 3 +-l NULL-SHA + +# client TLSv1.2 RSA-NULL-SHA +-v 3 +-l NULL-SHA + +# server TLSv1.2 RSA-NULL-SHA256 +-v 3 +-l NULL-SHA256 + +# client TLSv1.2 RSA-NULL-SHA256 +-v 3 +-l NULL-SHA256 + +# server TLSv1 CAMELLIA128-SHA +-v 1 +-l CAMELLIA128-SHA + +# client TLSv1 CAMELLIA128-SHA +-v 1 +-l CAMELLIA128-SHA + +# server TLSv1 CAMELLIA256-SHA +-v 1 +-l CAMELLIA256-SHA + +# client TLSv1 CAMELLIA256-SHA +-v 1 +-l CAMELLIA256-SHA + +# server TLSv1.1 CAMELLIA128-SHA +-v 2 +-l CAMELLIA128-SHA + +# client TLSv1.1 CAMELLIA128-SHA +-v 2 +-l CAMELLIA128-SHA + +# server TLSv1.1 CAMELLIA256-SHA +-v 2 +-l CAMELLIA256-SHA + +# client TLSv1.1 CAMELLIA256-SHA +-v 2 +-l CAMELLIA256-SHA + +# server TLSv1.2 CAMELLIA128-SHA +-v 3 +-l CAMELLIA128-SHA + +# client TLSv1.2 CAMELLIA128-SHA +-v 3 +-l CAMELLIA128-SHA + +# server TLSv1.2 CAMELLIA256-SHA +-v 3 +-l CAMELLIA256-SHA + +# client TLSv1.2 CAMELLIA256-SHA +-v 3 +-l CAMELLIA256-SHA + +# server TLSv1.2 CAMELLIA128-SHA256 +-v 3 +-l CAMELLIA128-SHA256 + +# client TLSv1.2 CAMELLIA128-SHA256 +-v 3 +-l CAMELLIA128-SHA256 + +# server TLSv1.2 CAMELLIA256-SHA256 +-v 3 +-l CAMELLIA256-SHA256 + +# client TLSv1.2 CAMELLIA256-SHA256 +-v 3 +-l CAMELLIA256-SHA256 + +# server TLSv1 DHE-RSA-CAMELLIA128-SHA +-v 1 +-l DHE-RSA-CAMELLIA128-SHA + +# client TLSv1 DHE-RSA-CAMELLIA128-SHA +-v 1 +-l DHE-RSA-CAMELLIA128-SHA + +# server TLSv1 DHE-RSA-CAMELLIA256-SHA +-v 1 +-l DHE-RSA-CAMELLIA256-SHA + +# client TLSv1 DHE-RSA-CAMELLIA256-SHA +-v 1 +-l DHE-RSA-CAMELLIA256-SHA + +# server TLSv1.1 DHE-RSA-CAMELLIA128-SHA +-v 2 +-l DHE-RSA-CAMELLIA128-SHA + +# client TLSv1.1 DHE-RSA-CAMELLIA128-SHA +-v 2 +-l DHE-RSA-CAMELLIA128-SHA + +# server TLSv1.1 DHE-RSA-CAMELLIA256-SHA +-v 2 +-l DHE-RSA-CAMELLIA256-SHA + +# client TLSv1.1 DHE-RSA-CAMELLIA256-SHA +-v 2 +-l DHE-RSA-CAMELLIA256-SHA + +# server TLSv1.2 DHE-RSA-CAMELLIA128-SHA +-v 3 +-l DHE-RSA-CAMELLIA128-SHA + +# client TLSv1.2 DHE-RSA-CAMELLIA128-SHA +-v 3 +-l DHE-RSA-CAMELLIA128-SHA + +# server TLSv1.2 DHE-RSA-CAMELLIA256-SHA +-v 3 +-l DHE-RSA-CAMELLIA256-SHA + +# client TLSv1.2 DHE-RSA-CAMELLIA256-SHA +-v 3 +-l DHE-RSA-CAMELLIA256-SHA + +# server TLSv1.2 DHE-RSA-CAMELLIA128-SHA256 +-v 3 +-l DHE-RSA-CAMELLIA128-SHA256 + +# client TLSv1.2 DHE-RSA-CAMELLIA128-SHA256 +-v 3 +-l DHE-RSA-CAMELLIA128-SHA256 + +# server TLSv1.2 DHE-RSA-CAMELLIA256-SHA256 +-v 3 +-l DHE-RSA-CAMELLIA256-SHA256 + +# client TLSv1.2 DHE-RSA-CAMELLIA256-SHA256 +-v 3 +-l DHE-RSA-CAMELLIA256-SHA256 + +# server TLSv1.2 RSA-AES128-GCM-SHA256 +-v 3 +-l AES128-GCM-SHA256 + +# client TLSv1.2 RSA-AES128-GCM-SHA256 +-v 3 +-l AES128-GCM-SHA256 + +# server TLSv1.2 RSA-AES256-GCM-SHA384 +-v 3 +-l AES256-GCM-SHA384 + +# client TLSv1.2 RSA-AES256-GCM-SHA384 +-v 3 +-l AES256-GCM-SHA384 + +# 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 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem + +# 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 +-v 3 +-l ECDH-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDH-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 +-v 3 +-l ECDH-ECDSA-AES256-GCM-SHA384 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# server TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# 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 +-v 3 +-l ECDH-RSA-AES128-GCM-SHA256 + +# server TLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDH-RSA-AES256-GCM-SHA384 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +-v 3 +-l ECDH-RSA-AES256-GCM-SHA384 + +# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 + +# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 +-v 3 +-l DHE-RSA-AES128-GCM-SHA256 + +# server TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# client TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +-v 3 +-l DHE-RSA-AES256-GCM-SHA384 + +# server TLSv1.2 PSK-AES128-GCM-SHA256 +-s +-v 3 +-l PSK-AES128-GCM-SHA256 + +# client TLSv1.2 PSK-AES128-GCM-SHA256 +-s +-v 3 +-l PSK-AES128-GCM-SHA256 + +# server TLSv1.2 PSK-AES256-GCM-SHA384 +-s +-v 3 +-l PSK-AES256-GCM-SHA384 + +# client TLSv1.2 PSK-AES256-GCM-SHA384 +-s +-v 3 +-l PSK-AES256-GCM-SHA384 + +# server TLSv1.2 AES128-CCM-8 +-v 3 +-l AES128-CCM-8 + +# client TLSv1.2 AES128-CCM-8 +-v 3 +-l AES128-CCM-8 + +# server TLSv1.2 AES256-CCM-8 +-v 3 +-l AES256-CCM-8 + +# client TLSv1.2 AES256-CCM-8 +-v 3 +-l AES256-CCM-8 + +# server TLSv1.2 ECDHE-ECDSA-AES128-CCM +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-CCM +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-v 3 +-l ECDHE-ECDSA-AES128-CCM-8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-v 3 +-l ECDHE-ECDSA-AES128-CCM-8 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +-v 3 +-l ECDHE-ECDSA-AES256-CCM-8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +-v 3 +-l ECDHE-ECDSA-AES256-CCM-8 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 PSK-AES128-CCM +-s +-v 3 +-l PSK-AES128-CCM + +# client TLSv1.2 PSK-AES128-CCM +-s +-v 3 +-l PSK-AES128-CCM + +# server TLSv1.2 PSK-AES256-CCM +-s +-v 3 +-l PSK-AES256-CCM + +# client TLSv1.2 PSK-AES256-CCM +-s +-v 3 +-l PSK-AES256-CCM + +# server TLSv1.2 PSK-AES128-CCM-8 +-s +-v 3 +-l PSK-AES128-CCM-8 + +# client TLSv1.2 PSK-AES128-CCM-8 +-s +-v 3 +-l PSK-AES128-CCM-8 + +# server TLSv1.2 PSK-AES256-CCM-8 +-s +-v 3 +-l PSK-AES256-CCM-8 + +# client TLSv1.2 PSK-AES256-CCM-8 +-s +-v 3 +-l PSK-AES256-CCM-8 + +# server TLSv1.2 DHE-PSK-AES128-CBC-SHA256 +-s +-v 3 +-l DHE-PSK-AES128-CBC-SHA256 + +# client TLSv1.2 DHE-PSK-AES128-CBC-SHA256 +-s +-v 3 +-l DHE-PSK-AES128-CBC-SHA256 + +# server TLSv1.2 DHE-PSK-AES256-CBC-SHA384 +-s +-v 3 +-l DHE-PSK-AES256-CBC-SHA384 + +# client TLSv1.2 DHE-PSK-AES256-CBC-SHA384 +-s +-v 3 +-l DHE-PSK-AES256-CBC-SHA384 + +# server TLSv1.2 DHE-PSK-NULL-SHA256 +-s +-v 3 +-l DHE-PSK-NULL-SHA256 + +# client TLSv1.2 DHE-PSK-NULL-SHA256 +-s +-v 3 +-l DHE-PSK-NULL-SHA256 + +# server TLSv1.2 DHE-PSK-NULL-SHA384 +-s +-v 3 +-l DHE-PSK-NULL-SHA384 + +# client TLSv1.2 DHE-PSK-NULL-SHA384 +-s +-v 3 +-l DHE-PSK-NULL-SHA384 + +# server TLSv1.2 DHE-PSK-AES128-GCM-SHA256 +-s +-v 3 +-l DHE-PSK-AES128-GCM-SHA256 + +# client TLSv1.2 DHE-PSK-AES128-GCM-SHA256 +-s +-v 3 +-l DHE-PSK-AES128-GCM-SHA256 + +# server TLSv1.2 DHE-PSK-AES256-GCM-SHA384 +-s +-v 3 +-l DHE-PSK-AES256-GCM-SHA384 + +# client TLSv1.2 DHE-PSK-AES256-GCM-SHA384 +-s +-v 3 +-l DHE-PSK-AES256-GCM-SHA384 + +# server TLSv1.2 DHE-PSK-AES128-CCM +-s +-v 3 +-l DHE-PSK-AES128-CCM + +# client TLSv1.2 DHE-PSK-AES128-CCM +-s +-v 3 +-l DHE-PSK-AES128-CCM + +# server TLSv1.2 DHE-PSK-AES256-CCM +-s +-v 3 +-l DHE-PSK-AES256-CCM + +# client TLSv1.2 DHE-PSK-AES256-CCM +-s +-v 3 +-l DHE-PSK-AES256-CCM + +# server TLSv1.2 ADH-AES128-SHA +-a +-v 3 +-l ADH-AES128-SHA + +# client TLSv1.2 ADH-AES128-SHA +-a +-v 3 +-l ADH-AES128-SHA + +# server TLSv1.1 ADH-AES128-SHA +-a +-v 2 +-l ADH-AES128-SHA + +# client TLSv1.1 ADH-AES128-SHA +-a +-v 2 +-l ADH-AES128-SHA + +# server TLSv1.0 ADH-AES128-SHA +-a +-v 1 +-l ADH-AES128-SHA + +# client TLSv1.0 ADH-AES128-SHA +-a +-v 1 +-l ADH-AES128-SHA + +# server TLSv1.2 ADH-AES256-GCM-SHA384 +-a +-v 3 +-l ADH-AES256-GCM-SHA384 + +# client TLSv1.2 ADH-AES256-GCM-SHA384 +-a +-v 3 +-l ADH-AES256-GCM-SHA384 + +# server TLSv1.1 ADH-AES256-GCM-SHA384 +-a +-v 2 +-l ADH-AES256-GCM-SHA384 +-H exitWithRet + +# client TLSv1.1 ADH-AES256-GCM-SHA384 +-a +-v 2 +-l ADH-AES256-GCM-SHA384 +-H exitWithRet + +# server TLSv1.0 ADH-AES256-GCM-SHA384 +-a +-v 1 +-l ADH-AES256-GCM-SHA384 +-H exitWithRet + +# client TLSv1.0 ADH-AES256-GCM-SHA384 +-a +-v 1 +-l ADH-AES256-GCM-SHA384 +-H exitWithRet + +# server TLSv1.1 DHE-RSA-AES256-GCM-SHA384 +-a +-v 2 +-l DHE-RSA-AES256-GCM-SHA384 +-H exitWithRet + +# client TLSv1.1 DHE-RSA-AES256-GCM-SHA384 +-a +-v 2 +-l DHE-RSA-AES256-GCM-SHA384 +-H exitWithRet + +# server TLSv1.0 DHE-RSA-AES256-GCM-SHA384 +-a +-v 1 +-l DHE-RSA-AES256-GCM-SHA384 +-H exitWithRet + +# client TLSv1.0 DHE-RSA-AES256-GCM-SHA384 +-a +-v 1 +-l DHE-RSA-AES256-GCM-SHA384 +-H exitWithRet + +# server TLSv1.1 +-a +-v 2 + +# client TLSv1.1 DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA +-a +-v 2 +-l DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA + # server TLSv1 NTRU_RC4 -v 1 -l NTRU-RC4-SHA @@ -1096,940 +1884,325 @@ -v 3 -l NTRU-AES128-SHA -# server TLSv1.2 NTRU_AES256 --v 3 --l NTRU-AES256-SHA --n --c ./certs/ntru-cert.pem --k ./certs/ntru-key.raw - -# client TLSv1.2 NTRU_AES256 --v 3 --l NTRU-AES256-SHA - -# server TLSv1 DHE AES128 --v 1 --l DHE-RSA-AES128-SHA - -# client TLSv1 DHE AES128 --v 1 --l DHE-RSA-AES128-SHA - -# server TLSv1 DHE AES256 --v 1 --l DHE-RSA-AES256-SHA - -# client TLSv1 DHE AES256 --v 1 --l DHE-RSA-AES256-SHA - -# server TLSv1 DHE AES128-SHA256 --v 1 --l DHE-RSA-AES128-SHA256 - -# client TLSv1 DHE AES128-SHA256 --v 1 --l DHE-RSA-AES128-SHA256 - -# server TLSv1 DHE AES256-SHA256 --v 1 --l DHE-RSA-AES256-SHA256 - -# client TLSv1 DHE AES256-SHA256 --v 1 --l DHE-RSA-AES256-SHA256 - -# server TLSv1.1 DHE AES128 --v 2 --l DHE-RSA-AES128-SHA - -# client TLSv1.1 DHE AES128 --v 2 --l DHE-RSA-AES128-SHA - -# server TLSv1.1 DHE AES256 --v 2 --l DHE-RSA-AES256-SHA - -# client TLSv1.1 DHE AES256 --v 2 --l DHE-RSA-AES256-SHA - -# server TLSv1.1 DHE AES128-SHA256 --v 2 --l DHE-RSA-AES128-SHA256 - -# client TLSv1.1 DHE AES128-SHA256 --v 2 --l DHE-RSA-AES128-SHA256 - -# server TLSv1.1 DHE AES256-SHA256 --v 2 --l DHE-RSA-AES256-SHA256 - -# client TLSv1.1 DHE AES256-SHA256 --v 2 --l DHE-RSA-AES256-SHA256 - -# server TLSv1.2 DHE AES128 --v 3 --l DHE-RSA-AES128-SHA - -# client TLSv1.2 DHE AES128 --v 3 --l DHE-RSA-AES128-SHA - -# server TLSv1.2 DHE AES256 --v 3 --l DHE-RSA-AES256-SHA - -# client TLSv1.2 DHE AES256 --v 3 --l DHE-RSA-AES256-SHA - -# server TLSv1.2 DHE AES128-SHA256 --v 3 --l DHE-RSA-AES128-SHA256 - -# client TLSv1.2 DHE AES128-SHA256 --v 3 --l DHE-RSA-AES128-SHA256 - -# server TLSv1.2 DHE AES256-SHA256 --v 3 --l DHE-RSA-AES256-SHA256 - -# client TLSv1.2 DHE AES256-SHA256 --v 3 --l DHE-RSA-AES256-SHA256 - -# server TLSv1 PSK-AES128 --s --v 1 --l PSK-AES128-CBC-SHA - -# client TLSv1 PSK-AES128 --s --v 1 --l PSK-AES128-CBC-SHA - -# server TLSv1 PSK-AES256 --s --v 1 --l PSK-AES256-CBC-SHA - -# client TLSv1 PSK-AES256 --s --v 1 --l PSK-AES256-CBC-SHA - -# server TLSv1.1 PSK-AES128 --s --v 2 --l PSK-AES128-CBC-SHA - -# client TLSv1.1 PSK-AES128 --s --v 2 --l PSK-AES128-CBC-SHA - -# server TLSv1.1 PSK-AES256 --s --v 2 --l PSK-AES256-CBC-SHA - -# client TLSv1.1 PSK-AES256 --s --v 2 --l PSK-AES256-CBC-SHA - -# server TLSv1.2 PSK-AES128 --s --v 3 --l PSK-AES128-CBC-SHA - -# client TLSv1.2 PSK-AES128 --s --v 3 --l PSK-AES128-CBC-SHA - -# server TLSv1.2 PSK-AES256 --s --v 3 --l PSK-AES256-CBC-SHA - -# client TLSv1.2 PSK-AES256 --s --v 3 --l PSK-AES256-CBC-SHA - -# server TLSv1.0 PSK-AES128-SHA256 --s --v 1 --l PSK-AES128-CBC-SHA256 - -# client TLSv1.0 PSK-AES128-SHA256 --s --v 1 --l PSK-AES128-CBC-SHA256 - -# server TLSv1.1 PSK-AES128-SHA256 --s --v 2 --l PSK-AES128-CBC-SHA256 - -# client TLSv1.1 PSK-AES128-SHA256 --s --v 2 --l PSK-AES128-CBC-SHA256 - -# server TLSv1.2 PSK-AES128-SHA256 --s --v 3 --l PSK-AES128-CBC-SHA256 - -# client TLSv1.2 PSK-AES128-SHA256 --s --v 3 --l PSK-AES128-CBC-SHA256 - -# server TLSv1.0 PSK-AES256-SHA384 --s --v 1 --l PSK-AES256-CBC-SHA384 - -# client TLSv1.0 PSK-AES256-SHA384 --s --v 1 --l PSK-AES256-CBC-SHA384 - -# server TLSv1.1 PSK-AES256-SHA384 --s --v 2 --l PSK-AES256-CBC-SHA384 - -# client TLSv1.1 PSK-AES256-SHA384 --s --v 2 --l PSK-AES256-CBC-SHA384 - -# server TLSv1.2 PSK-AES256-SHA384 --s --v 3 --l PSK-AES256-CBC-SHA384 - -# client TLSv1.2 PSK-AES256-SHA384 --s --v 3 --l PSK-AES256-CBC-SHA384 - -# server TLSv1.0 PSK-NULL --s --v 1 --l PSK-NULL-SHA - -# client TLSv1.0 PSK-NULL --s --v 1 --l PSK-NULL-SHA - -# server TLSv1.1 PSK-NULL --s --v 2 --l PSK-NULL-SHA - -# client TLSv1.1 PSK-NULL --s --v 2 --l PSK-NULL-SHA - -# server TLSv1.2 PSK-NULL --s --v 3 --l PSK-NULL-SHA - -# client TLSv1.2 PSK-NULL --s --v 3 --l PSK-NULL-SHA - -# server TLSv1.2 PSK-NULL-SHA256 --s --v 3 --l PSK-NULL-SHA256 - -# client TLSv1.2 PSK-NULL-SHA256 --s --v 3 --l PSK-NULL-SHA256 - -# server TLSv1.2 PSK-NULL-SHA384 --s --v 3 --l PSK-NULL-SHA384 - -# client TLSv1.2 PSK-NULL-SHA384 --s --v 3 --l PSK-NULL-SHA384 - -# server TLSv1.2 PSK-NULL --s --v 3 --l PSK-NULL-SHA - -# client TLSv1.2 PSK-NULL --s --v 3 --l PSK-NULL-SHA - -# server TLSv1.2 PSK-NULL-SHA256 --s --v 3 --l PSK-NULL-SHA256 - -# client TLSv1.2 PSK-NULL-SHA256 --s --v 3 --l PSK-NULL-SHA256 - -# server TLSv1.0 RSA-NULL-SHA --v 1 --l NULL-SHA - -# client TLSv1.0 RSA-NULL-SHA --v 1 --l NULL-SHA - -# server TLSv1.1 RSA-NULL-SHA --v 2 --l NULL-SHA - -# client TLSv1.1 RSA-NULL-SHA --v 2 --l NULL-SHA - -# server TLSv1.2 RSA-NULL-SHA --v 3 --l NULL-SHA - -# client TLSv1.2 RSA-NULL-SHA --v 3 --l NULL-SHA - -# server TLSv1.0 RSA-NULL-SHA256 --v 1 --l NULL-SHA256 - -# client TLSv1.0 RSA-NULL-SHA256 --v 1 --l NULL-SHA256 - -# server TLSv1.1 RSA-NULL-SHA256 --v 2 --l NULL-SHA256 - -# client TLSv1.1 RSA-NULL-SHA256 --v 2 --l NULL-SHA256 - -# server TLSv1.2 RSA-NULL-SHA256 --v 3 --l NULL-SHA256 - -# client TLSv1.2 RSA-NULL-SHA256 --v 3 --l NULL-SHA256 - -# server TLSv1 CAMELLIA128-SHA --v 1 --l CAMELLIA128-SHA - -# client TLSv1 CAMELLIA128-SHA --v 1 --l CAMELLIA128-SHA - -# server TLSv1 CAMELLIA256-SHA --v 1 --l CAMELLIA256-SHA - -# client TLSv1 CAMELLIA256-SHA --v 1 --l CAMELLIA256-SHA - -# server TLSv1 CAMELLIA128-SHA256 --v 1 --l CAMELLIA128-SHA256 - -# client TLSv1 CAMELLIA128-SHA256 --v 1 --l CAMELLIA128-SHA256 - -# server TLSv1 CAMELLIA256-SHA256 --v 1 --l CAMELLIA256-SHA256 - -# client TLSv1 CAMELLIA256-SHA256 --v 1 --l CAMELLIA256-SHA256 - -# server TLSv1.1 CAMELLIA128-SHA --v 2 --l CAMELLIA128-SHA - -# client TLSv1.1 CAMELLIA128-SHA --v 2 --l CAMELLIA128-SHA - -# server TLSv1.1 CAMELLIA256-SHA --v 2 --l CAMELLIA256-SHA - -# client TLSv1.1 CAMELLIA256-SHA --v 2 --l CAMELLIA256-SHA - -# server TLSv1.1 CAMELLIA128-SHA256 --v 2 --l CAMELLIA128-SHA256 - -# client TLSv1.1 CAMELLIA128-SHA256 --v 2 --l CAMELLIA128-SHA256 - -# server TLSv1.1 CAMELLIA256-SHA256 --v 2 --l CAMELLIA256-SHA256 - -# client TLSv1.1 CAMELLIA256-SHA256 --v 2 --l CAMELLIA256-SHA256 - -# server TLSv1.2 CAMELLIA128-SHA --v 3 --l CAMELLIA128-SHA - -# client TLSv1.2 CAMELLIA128-SHA --v 3 --l CAMELLIA128-SHA - -# server TLSv1.2 CAMELLIA256-SHA --v 3 --l CAMELLIA256-SHA - -# client TLSv1.2 CAMELLIA256-SHA --v 3 --l CAMELLIA256-SHA - -# server TLSv1.2 CAMELLIA128-SHA256 --v 3 --l CAMELLIA128-SHA256 - -# client TLSv1.2 CAMELLIA128-SHA256 --v 3 --l CAMELLIA128-SHA256 - -# server TLSv1.2 CAMELLIA256-SHA256 --v 3 --l CAMELLIA256-SHA256 - -# client TLSv1.2 CAMELLIA256-SHA256 --v 3 --l CAMELLIA256-SHA256 - -# server TLSv1 DHE-RSA-CAMELLIA128-SHA --v 1 --l DHE-RSA-CAMELLIA128-SHA - -# client TLSv1 DHE-RSA-CAMELLIA128-SHA --v 1 --l DHE-RSA-CAMELLIA128-SHA - -# server TLSv1 DHE-RSA-CAMELLIA256-SHA --v 1 --l DHE-RSA-CAMELLIA256-SHA - -# client TLSv1 DHE-RSA-CAMELLIA256-SHA --v 1 --l DHE-RSA-CAMELLIA256-SHA - -# server TLSv1 DHE-RSA-CAMELLIA128-SHA256 --v 1 --l DHE-RSA-CAMELLIA128-SHA256 - -# client TLSv1 DHE-RSA-CAMELLIA128-SHA256 --v 1 --l DHE-RSA-CAMELLIA128-SHA256 - -# server TLSv1 DHE-RSA-CAMELLIA256-SHA256 --v 1 --l DHE-RSA-CAMELLIA256-SHA256 - -# client TLSv1 DHE-RSA-CAMELLIA256-SHA256 --v 1 --l DHE-RSA-CAMELLIA256-SHA256 - -# server TLSv1.1 DHE-RSA-CAMELLIA128-SHA --v 2 --l DHE-RSA-CAMELLIA128-SHA - -# client TLSv1.1 DHE-RSA-CAMELLIA128-SHA --v 2 --l DHE-RSA-CAMELLIA128-SHA - -# server TLSv1.1 DHE-RSA-CAMELLIA256-SHA --v 2 --l DHE-RSA-CAMELLIA256-SHA - -# client TLSv1.1 DHE-RSA-CAMELLIA256-SHA --v 2 --l DHE-RSA-CAMELLIA256-SHA - -# server TLSv1.1 DHE-RSA-CAMELLIA128-SHA256 --v 2 --l DHE-RSA-CAMELLIA128-SHA256 - -# client TLSv1.1 DHE-RSA-CAMELLIA128-SHA256 --v 2 --l DHE-RSA-CAMELLIA128-SHA256 - -# server TLSv1.1 DHE-RSA-CAMELLIA256-SHA256 --v 2 --l DHE-RSA-CAMELLIA256-SHA256 - -# client TLSv1.1 DHE-RSA-CAMELLIA256-SHA256 --v 2 --l DHE-RSA-CAMELLIA256-SHA256 - -# server TLSv1.2 DHE-RSA-CAMELLIA128-SHA --v 3 --l DHE-RSA-CAMELLIA128-SHA - -# client TLSv1.2 DHE-RSA-CAMELLIA128-SHA --v 3 --l DHE-RSA-CAMELLIA128-SHA - -# server TLSv1.2 DHE-RSA-CAMELLIA256-SHA --v 3 --l DHE-RSA-CAMELLIA256-SHA - -# client TLSv1.2 DHE-RSA-CAMELLIA256-SHA --v 3 --l DHE-RSA-CAMELLIA256-SHA - -# server TLSv1.2 DHE-RSA-CAMELLIA128-SHA256 --v 3 --l DHE-RSA-CAMELLIA128-SHA256 - -# client TLSv1.2 DHE-RSA-CAMELLIA128-SHA256 --v 3 --l DHE-RSA-CAMELLIA128-SHA256 - -# server TLSv1.2 DHE-RSA-CAMELLIA256-SHA256 --v 3 --l DHE-RSA-CAMELLIA256-SHA256 - -# client TLSv1.2 DHE-RSA-CAMELLIA256-SHA256 --v 3 --l DHE-RSA-CAMELLIA256-SHA256 - -# server TLSv1.2 RSA-AES128-GCM-SHA256 --v 3 --l AES128-GCM-SHA256 - -# client TLSv1.2 RSA-AES128-GCM-SHA256 --v 3 --l AES128-GCM-SHA256 - -# server TLSv1.2 RSA-AES256-GCM-SHA384 --v 3 --l AES256-GCM-SHA384 - -# client TLSv1.2 RSA-AES256-GCM-SHA384 --v 3 --l AES256-GCM-SHA384 - -# 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 --v 3 --l ECDHE-ECDSA-AES128-GCM-SHA256 --A ./certs/server-ecc.pem - -# server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 --v 3 --l ECDHE-ECDSA-AES256-GCM-SHA384 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 --v 3 --l ECDHE-ECDSA-AES256-GCM-SHA384 --A ./certs/server-ecc.pem - -# 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 --v 3 --l ECDH-ECDSA-AES128-GCM-SHA256 --A ./certs/server-ecc.pem - -# server TLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 --v 3 --l ECDH-ECDSA-AES256-GCM-SHA384 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client TLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 --v 3 --l ECDH-ECDSA-AES256-GCM-SHA384 --A ./certs/server-ecc.pem - -# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# error going into callback, return ok +# server TLSv1.2 verify callback override -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 +-c ./certs/test/server-cert-rsa-badsig.pem -# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# client TLSv1.2 verify callback override -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 +-j + +# server TLSv1.2 verify callback override +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/test/server-cert-ecc-badsig.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 verify callback override +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-ecc-cert.pem +-j + +# no error going into callback, return ok +# server TLSv1.2 verify callback override +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-c ./certs/server-cert.pem + +# client TLSv1.2 verify callback override +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-j + +# server TLSv1.2 verify callback override +#-v 3 +#-l ECDHE-ECDSA-AES128-GCM-SHA256 +#-c ./certs/test/server-ecc.pem #This cert no longer exists +#-k ./certs/ecc-key.pem + +# client TLSv1.2 verify callback override +#-v 3 +#-l ECDHE-ECDSA-AES128-GCM-SHA256 +#-A ./certs/ca-ecc-cert.pem +#-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 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 +-8 + +# 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/3072/client-cert.pem + +# client TLSv1.2 RSA 3072-bit DH 3072-bit +-v 3 +-D certs/dh3072.pem +-c certs/3072/client-cert.pem +-k certs/3072/client-key.pem + +# server good certificate common name +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/server-key.pem +-c ./certs/test/server-goodcn.pem +-d + +# client good certificate common name +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-h localhost +-A ./certs/test/server-goodcn.pem +-m +-C + +# server good certificate alt name +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/server-key.pem +-c ./certs/test/server-goodalt.pem +-d + +# client good certificate alt name +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-h localhost +-A ./certs/test/server-goodalt.pem +-m +-C + +# server good certificate common name wild +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/server-key.pem +-c ./certs/test/server-goodcnwild.pem +-d + +# client good certificate common name wild +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-h localhost +-A ./certs/test/server-goodcnwild.pem +-m +-C + +# server good certificate alt name wild +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-k ./certs/server-key.pem +-c ./certs/test/server-goodaltwild.pem +-d + +# client good certificate alt name wild +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-h localhost +-A ./certs/test/server-goodaltwild.pem +-m +-C + +# server CN in alternate names list +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-c ./certs/test/server-localhost.pem + +# client CN in alternate names list +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 +-h localhost +-A ./certs/test/server-localhost.pem +-m # server TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 -v 3 -l ECDHE-RSA-AES256-GCM-SHA384 -# client TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +# client TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 with user curve (384 or 256) -v 3 -l ECDHE-RSA-AES256-GCM-SHA384 +-H useSupCurve -# server TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 with P-384 Certs and CA -v 3 --l ECDH-RSA-AES128-GCM-SHA256 --c ./certs/server-ecc-rsa.pem --k ./certs/ecc-key.pem +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc384-cert.pem +-k ./certs/server-ecc384-key.pem +-A ./certs/ca-ecc384-cert.pem -# client TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 with P-384 Certs and CA -v 3 --l ECDH-RSA-AES128-GCM-SHA256 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/client-ecc384-cert.pem +-k ./certs/client-ecc384-key.pem +-A ./certs/ca-ecc384-cert.pem -# server TLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +# server TLSv1.2 default with secure renegotiation (renegotiation available) -v 3 --l ECDH-RSA-AES256-GCM-SHA384 --c ./certs/server-ecc-rsa.pem --k ./certs/ecc-key.pem +-l ECDHE-RSA-AES128-GCM-SHA256 +-M -# client TLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +# client TLSv1.2 default with secure renegotiation (client initiated) -v 3 --l ECDH-RSA-AES256-GCM-SHA384 +-l ECDHE-RSA-AES128-GCM-SHA256 +-i -# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 +# server TLSv1.2 default with secure renegotiation (renegotiation available) -v 3 --l DHE-RSA-AES128-GCM-SHA256 +-l ECDHE-RSA-AES128-GCM-SHA256 +-M -# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 +# client TLSv1.2 default with secure renegotiation (client initiated as resume) -v 3 --l DHE-RSA-AES128-GCM-SHA256 +-l ECDHE-RSA-AES128-GCM-SHA256 +-i -4 -# server TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +# server TLSv1.2 default with secure renegotiation (server initiated) -v 3 --l DHE-RSA-AES256-GCM-SHA384 +-l ECDHE-RSA-AES128-GCM-SHA256 +-m -# client TLSv1.2 DHE-RSA-AES256-GCM-SHA384 +# client TLSv1.2 default with secure renegotiation (renegotiation available) -v 3 --l DHE-RSA-AES256-GCM-SHA384 +-l ECDHE-RSA-AES128-GCM-SHA256 +-R -# server TLSv1.2 PSK-AES128-GCM-SHA256 --s +# server TLSv1.2 default with secure renegotiation (server initiated) -v 3 --l PSK-AES128-GCM-SHA256 +-l ECDHE-RSA-AES128-GCM-SHA256 +-m -# client TLSv1.2 PSK-AES128-GCM-SHA256 --s +# client TLSv1.2 default with secure renegotiation (renegotiation available as resume) -v 3 --l PSK-AES128-GCM-SHA256 +-l ECDHE-RSA-AES128-GCM-SHA256 +-R -4 -# server TLSv1.2 PSK-AES256-GCM-SHA384 --s +# server TLSv1.2 default with secure renegotiation (server initiated) -v 3 --l PSK-AES256-GCM-SHA384 +-l ECDHE-RSA-AES128-GCM-SHA256 +-m -# client TLSv1.2 PSK-AES256-GCM-SHA384 --s +# client TLSv1.2 default with secure renegotiation (client initiated) -v 3 --l PSK-AES256-GCM-SHA384 +-l ECDHE-RSA-AES128-GCM-SHA256 +-i -# server TLSv1.2 AES128-CCM-8 +# server TLSv1.2 default with secure renegotiation (server initiated) -v 3 --l AES128-CCM-8 +-l ECDHE-RSA-AES128-GCM-SHA256 +-m -# client TLSv1.2 AES128-CCM-8 +# client TLSv1.2 default with secure renegotiation (client initiated as resume) -v 3 --l AES128-CCM-8 +-l ECDHE-RSA-AES128-GCM-SHA256 +-i -4 -# server TLSv1.2 AES256-CCM-8 +# server TLSv1.2 with Trusted CA Indication (pre-shared) -v 3 --l AES256-CCM-8 +-5 -# client TLSv1.2 AES256-CCM-8 +# client TLSv1.2 with Trusted CA Indication (pre-shared) -v 3 --l AES256-CCM-8 +-5 -# server TLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +# server TLSv1.2 with block cipher and no ETM -v 3 --l ECDHE-ECDSA-AES128-CCM-8 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem +-l ECDHE-RSA-AES128-SHA256 +-H disallowETM -# client TLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +# client TLSv1.2 with block cipher -v 3 --l ECDHE-ECDSA-AES128-CCM-8 --A ./certs/server-ecc.pem +-l ECDHE-RSA-AES128-SHA256 -# server TLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +# server TLSv1.2 with block cipher -v 3 --l ECDHE-ECDSA-AES256-CCM-8 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem +-l ECDHE-RSA-AES128-SHA256 -# client TLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +# client TLSv1.2 with block cipher and no ETM -v 3 --l ECDHE-ECDSA-AES256-CCM-8 --A ./certs/server-ecc.pem +-l ECDHE-RSA-AES128-SHA256 +-H disallowETM -# server TLSv1.2 PSK-AES128-CCM --s +# server TLSv1.2 with block cipher and no ETM -v 3 --l PSK-AES128-CCM +-l ECDHE-RSA-AES128-SHA256 +-H disallowETM -# client TLSv1.2 PSK-AES128-CCM --s +# client TLSv1.2 with block cipher and no ETM -v 3 --l PSK-AES128-CCM +-l ECDHE-RSA-AES128-SHA256 +-H disallowETM -# server TLSv1.2 PSK-AES256-CCM --s +# server TLSv1.2 with block cipher and SHA-1 and no ETM -v 3 --l PSK-AES256-CCM +-l ECDHE-RSA-AES128-SHA +-H disallowETM -# client TLSv1.2 PSK-AES256-CCM --s +# client TLSv1.2 with block cipher and SHA-1 and no ETM -v 3 --l PSK-AES256-CCM +-l ECDHE-RSA-AES128-SHA +-H disallowETM -# server TLSv1.2 PSK-AES128-CCM-8 --s +# server TLSv1.2 with block cipher -v 3 --l PSK-AES128-CCM-8 +-l ECDHE-RSA-AES128-SHA256 -# client TLSv1.2 PSK-AES128-CCM-8 --s +# client TLSv1.2 with block cipher - atomic user (use callback) -v 3 --l PSK-AES128-CCM-8 +-l ECDHE-RSA-AES128-SHA256 +-U -# server TLSv1.2 PSK-AES256-CCM-8 --s +# server TLSv1.2 with block cipher and no ETM -v 3 --l PSK-AES256-CCM-8 +-l ECDHE-RSA-AES128-SHA256 +-H disallowETM -# client TLSv1.2 PSK-AES256-CCM-8 --s +# client TLSv1.2 with block cipher - atomic user (use callback) -v 3 --l PSK-AES256-CCM-8 +-l ECDHE-RSA-AES128-SHA256 +-U -# server TLSv1.0 DHE-PSK-AES128-CBC-SHA256 --s --v 1 --l DHE-PSK-AES128-CBC-SHA256 - -# client TLSv1.0 DHE-PSK-AES128-CBC-SHA256 --s --v 1 --l DHE-PSK-AES128-CBC-SHA256 - -# server TLSv1.1 DHE-PSK-AES128-CBC-SHA256 --s --v 2 --l DHE-PSK-AES128-CBC-SHA256 - -# client TLSv1.1 DHE-PSK-AES128-CBC-SHA256 --s --v 2 --l DHE-PSK-AES128-CBC-SHA256 - -# server TLSv1.2 DHE-PSK-AES128-CBC-SHA256 --s --v 3 --l DHE-PSK-AES128-CBC-SHA256 - -# client TLSv1.2 DHE-PSK-AES128-CBC-SHA256 --s --v 3 --l DHE-PSK-AES128-CBC-SHA256 - -# server TLSv1.0 DHE-PSK-AES256-CBC-SHA384 --s --v 1 --l DHE-PSK-AES256-CBC-SHA384 - -# client TLSv1.0 DHE-PSK-AES256-CBC-SHA384 --s --v 1 --l DHE-PSK-AES256-CBC-SHA384 - -# server TLSv1.1 DHE-PSK-AES256-CBC-SHA384 --s --v 2 --l DHE-PSK-AES256-CBC-SHA384 - -# client TLSv1.1 DHE-PSK-AES256-CBC-SHA384 --s --v 2 --l DHE-PSK-AES256-CBC-SHA384 - -# server TLSv1.2 DHE-PSK-AES256-CBC-SHA384 --s --v 3 --l DHE-PSK-AES256-CBC-SHA384 - -# client TLSv1.2 DHE-PSK-AES256-CBC-SHA384 --s --v 3 --l DHE-PSK-AES256-CBC-SHA384 - -# server TLSv1.0 DHE-PSK-NULL-SHA256 --s --v 1 --l DHE-PSK-NULL-SHA256 - -# client TLSv1.0 DHE-PSK-NULL-SHA256 --s --v 1 --l DHE-PSK-NULL-SHA256 - -# server TLSv1.1 DHE-PSK-NULL-SHA256 --s --v 2 --l DHE-PSK-NULL-SHA256 - -# client TLSv1.1 DHE-PSK-NULL-SHA256 --s --v 2 --l DHE-PSK-NULL-SHA256 - -# server TLSv1.2 DHE-PSK-NULL-SHA256 --s --v 3 --l DHE-PSK-NULL-SHA256 - -# client TLSv1.2 DHE-PSK-NULL-SHA256 --s --v 3 --l DHE-PSK-NULL-SHA256 - -# server TLSv1.0 DHE-PSK-NULL-SHA384 --s --v 1 --l DHE-PSK-NULL-SHA384 - -# client TLSv1.0 DHE-PSK-NULL-SHA384 --s --v 1 --l DHE-PSK-NULL-SHA384 - -# server TLSv1.1 DHE-PSK-NULL-SHA384 --s --v 2 --l DHE-PSK-NULL-SHA384 - -# client TLSv1.1 DHE-PSK-NULL-SHA384 --s --v 2 --l DHE-PSK-NULL-SHA384 - -# server TLSv1.2 DHE-PSK-NULL-SHA384 --s --v 3 --l DHE-PSK-NULL-SHA384 - -# client TLSv1.2 DHE-PSK-NULL-SHA384 --s --v 3 --l DHE-PSK-NULL-SHA384 - -# server TLSv1.2 DHE-PSK-AES128-GCM-SHA256 --s --v 3 --l DHE-PSK-AES128-GCM-SHA256 - -# client TLSv1.2 DHE-PSK-AES128-GCM-SHA256 --s --v 3 --l DHE-PSK-AES128-GCM-SHA256 - -# server TLSv1.2 DHE-PSK-AES256-GCM-SHA384 --s --v 3 --l DHE-PSK-AES256-GCM-SHA384 - -# client TLSv1.2 DHE-PSK-AES256-GCM-SHA384 --s --v 3 --l DHE-PSK-AES256-GCM-SHA384 - -# server TLSv1.2 DHE-PSK-AES128-CCM --s --v 3 --l DHE-PSK-AES128-CCM - -# client TLSv1.2 DHE-PSK-AES128-CCM --s --v 3 --l DHE-PSK-AES128-CCM - -# server TLSv1.2 DHE-PSK-AES256-CCM --s --v 3 --l DHE-PSK-AES256-CCM - -# client TLSv1.2 DHE-PSK-AES256-CCM --s --v 3 --l DHE-PSK-AES256-CCM - -# server TLSv1.2 ADH-AES128-SHA --a --v 3 --l ADH-AES128-SHA - -# client TLSv1.2 ADH-AES128-SHA --a --v 3 --l ADH-AES128-SHA - -# server TLSv1.1 ADH-AES128-SHA --a --v 2 --l ADH-AES128-SHA - -# client TLSv1.1 ADH-AES128-SHA --a --v 2 --l ADH-AES128-SHA - -# server TLSv1.0 ADH-AES128-SHA --a --v 1 --l ADH-AES128-SHA - -# client TLSv1.0 ADH-AES128-SHA --a --v 1 --l ADH-AES128-SHA +# server with bidirectional shutdown +-w +# client with bidirectional shutdown +-w diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/unit.c b/FreeRTOS-Plus/Source/WolfSSL/tests/unit.c index d66f84cf7..670e1d198 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/tests/unit.c +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/unit.c @@ -1,4 +1,24 @@ -/* unit.c unit tests driver */ +/* unit.c API unit tests driver + * + * Copyright (C) 2006-2020 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 + */ + /* Name change compatibility layer no longer need to be included here */ @@ -25,44 +45,59 @@ int main(int argc, char** argv) int unit_test(int argc, char** argv) { - int ret; + int ret = 0; (void)argc; (void)argv; + +#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST + if (argc > 1) { + word32 memFailCount = atoi(argv[1]); + printf("\n--- SET RNG MALLOC FAIL AT %d---\n", memFailCount); + wolfSSL_SetMemFailCount(memFailCount); + } +#endif + printf("starting unit tests...\n"); -#ifdef HAVE_CAVIUM - ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) - err_sys("Cavium OpenNitroxDevice failed"); -#endif /* HAVE_CAVIUM */ +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) + wolfSSL_Debugging_ON(); +#endif + +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) + err_sys("Whitewood netRandom global config failed"); +#endif /* HAVE_WNR */ #ifndef WOLFSSL_TIRTOS - if (CurrentDir("tests") || CurrentDir("_build")) - ChangeDirBack(1); - else if (CurrentDir("Debug") || CurrentDir("Release")) - ChangeDirBack(3); + ChangeToWolfRoot(); #endif ApiTest(); if ( (ret = HashTest()) != 0){ printf("hash test failed with %d\n", ret); - return ret; + goto exit; } +#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) #ifndef SINGLE_THREADED - if ( (ret = SuiteTest()) != 0){ + if ( (ret = SuiteTest(argc, argv)) != 0){ printf("suite test failed with %d\n", ret); - return ret; + goto exit; } #endif - -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); #endif - return 0; + SrpTest(); + +exit: +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context"); +#endif /* HAVE_WNR */ + + return ret; } @@ -73,7 +108,7 @@ void wait_tcp_ready(func_args* args) (void)args; #elif defined(_POSIX_THREADS) && !defined(__MINGW32__) pthread_mutex_lock(&args->signal->mutex); - + if (!args->signal->ready) pthread_cond_wait(&args->signal->cond, &args->signal->mutex); args->signal->ready = 0; /* reset */ @@ -130,31 +165,8 @@ void join_thread(THREAD_TYPE thread) assert(res == WAIT_OBJECT_0); res = CloseHandle((HANDLE)thread); assert(res); + (void)res; /* Suppress un-used variable warning */ #endif } -void InitTcpReady(tcp_ready* ready) -{ - ready->ready = 0; - ready->port = 0; -#ifdef SINGLE_THREADED -#elif defined(_POSIX_THREADS) && !defined(__MINGW32__) - pthread_mutex_init(&ready->mutex, 0); - pthread_cond_init(&ready->cond, 0); -#endif -} - - -void FreeTcpReady(tcp_ready* ready) -{ -#ifdef SINGLE_THREADED - (void)ready; -#elif defined(_POSIX_THREADS) && !defined(__MINGW32__) - pthread_mutex_destroy(&ready->mutex); - pthread_cond_destroy(&ready->cond); -#else - (void)ready; -#endif -} - diff --git a/FreeRTOS-Plus/Source/WolfSSL/tests/unit.h b/FreeRTOS-Plus/Source/WolfSSL/tests/unit.h index ab8fbc2ff..67f49f5f9 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/tests/unit.h +++ b/FreeRTOS-Plus/Source/WolfSSL/tests/unit.h @@ -1,4 +1,24 @@ -/* unit.h unit tests driver */ +/* unit.c API unit tests driver + * + * Copyright (C) 2006-2020 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 CyaSSL_UNIT_H #define CyaSSL_UNIT_H @@ -6,12 +26,26 @@ #include #include /* thread and tcp stuff */ +#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST +#define XABORT() +#else +#define XABORT() abort() +#endif + +#ifndef WOLFSSL_PASSTHRU_ERR #define Fail(description, result) do { \ printf("\nERROR - %s line %d failed with:", __FILE__, __LINE__); \ - printf("\n\n test: "); printf description; \ - printf("\n\n result: "); printf result; \ - abort(); \ + printf("\n expected: "); printf description; \ + printf("\n result: "); printf result; printf("\n\n"); \ + XABORT(); \ } while(0) +#else +#define Fail(description, result) do { \ + printf("\nERROR - %s line %d failed with:", __FILE__, __LINE__); \ + printf("\n expected: ");printf description; \ + printf("\n result: "); printf result; printf("\n\n"); \ +} while (0) +#endif #define Assert(test, description, result) if (!(test)) Fail(description, result) @@ -26,8 +60,8 @@ } while(0) #define AssertInt(x, y, op, er) do { \ - int _x = x; \ - int _y = y; \ + int _x = (int)x; \ + int _y = (int)y; \ \ Assert(_x op _y, ("%s " #op " %s", #x, #y), ("%d " #er " %d", _x, _y)); \ } while(0) @@ -42,7 +76,7 @@ #define AssertStr(x, y, op, er) do { \ const char* _x = x; \ const char* _y = y; \ - int _z = strcmp(_x, _y); \ + int _z = (_x && _y) ? strcmp(_x, _y) : -1; \ \ Assert(_z op 0, ("%s " #op " %s", #x, #y), \ ("\"%s\" " #er " \"%s\"", _x, _y));\ @@ -55,11 +89,24 @@ #define AssertStrGE(x, y) AssertStr(x, y, >=, <) #define AssertStrLE(x, y) AssertStr(x, y, <=, >) +#define AssertPtr(x, y, op, er) do { \ + void* _x = (void*)x; \ + void* _y = (void*)y; \ + Assert(_x op _y, ("%s " #op " %s", #x, #y), ("%p " #er " %p", _x, _y)); \ +} while(0) + +#define AssertPtrEq(x, y) AssertPtr(x, y, ==, !=) +#define AssertPtrNE(x, y) AssertPtr(x, y, !=, ==) +#define AssertPtrGT(x, y) AssertPtr(x, y, >, <=) +#define AssertPtrLT(x, y) AssertPtr(x, y, <, >=) +#define AssertPtrGE(x, y) AssertPtr(x, y, >=, <) +#define AssertPtrLE(x, y) AssertPtr(x, y, <=, >) + void ApiTest(void); -int SuiteTest(void); -int HashTest(void); +int SuiteTest(int argc, char** argv); +int HashTest(void); +void SrpTest(void); #endif /* CyaSSL_UNIT_H */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/testsuite/include.am b/FreeRTOS-Plus/Source/WolfSSL/testsuite/include.am index 62edb4a30..ed2604427 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/testsuite/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/testsuite/include.am @@ -3,7 +3,7 @@ # All paths should be given relative to the root -if BUILD_EXAMPLES +if BUILD_TESTS check_PROGRAMS += testsuite/testsuite.test noinst_PROGRAMS += testsuite/testsuite.test testsuite_testsuite_test_SOURCES = \ @@ -14,7 +14,7 @@ testsuite_testsuite_test_SOURCES = \ examples/server/server.c \ testsuite/testsuite.c testsuite_testsuite_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) -testsuite_testsuite_test_LDADD = src/libwolfssl.la +testsuite_testsuite_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) testsuite_testsuite_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += testsuite/testsuite.sln diff --git a/FreeRTOS-Plus/Source/WolfSSL/testsuite/testsuite.c b/FreeRTOS-Plus/Source/WolfSSL/testsuite/testsuite.c index 4146878de..8cd2cd291 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/testsuite/testsuite.c +++ b/FreeRTOS-Plus/Source/WolfSSL/testsuite/testsuite.c @@ -1,8 +1,8 @@ /* testsuite.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -27,21 +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 { @@ -49,11 +56,11 @@ enum { }; static const char *outputName; +#endif int myoptind = 0; char* myoptarg = NULL; - #ifndef NO_TESTSUITE_MAIN_DRIVER static int testsuite_test(int argc, char** argv); @@ -68,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; @@ -83,11 +91,12 @@ int testsuite_test(int argc, char** argv) int num = 6; #endif -#ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) - err_sys("Cavium OpenNitroxDevice failed"); -#endif /* HAVE_CAVIUM */ +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) { + err_sys("Whitewood netRandom global config failed"); + return -1237; + } +#endif /* HAVE_WNR */ StartTCP(); @@ -100,13 +109,7 @@ int testsuite_test(int argc, char** argv) #endif #if !defined(WOLFSSL_TIRTOS) - if (CurrentDir("testsuite") || CurrentDir("_build")) - ChangeDirBack(1); - else if (CurrentDir("Debug") || CurrentDir("Release")) - ChangeDirBack(3); /* Xcode->Preferences->Locations->Locations*/ - /* Derived Data Advanced -> Custom */ - /* Relative to Workspace, Build/Products */ - /* Debug or Release */ + ChangeToWolfRoot(); #endif #ifdef WOLFSSL_TIRTOS @@ -116,10 +119,12 @@ int testsuite_test(int argc, char** argv) server_args.signal = &ready; InitTcpReady(&ready); +#ifndef NO_CRYPT_TEST /* wc_ test */ wolfcrypt_test(&server_args); if (server_args.return_code != 0) return server_args.return_code; - +#endif + /* Simple wolfSSL client server test */ simple_test(&server_args); if (server_args.return_code != 0) return server_args.return_code; @@ -131,13 +136,11 @@ int testsuite_test(int argc, char** argv) func_args echo_args; char* myArgv[NUMARGS]; - char argc0[32]; - char argc1[32]; - char argc2[32]; + char arg[3][32]; - myArgv[0] = argc0; - myArgv[1] = argc1; - myArgv[2] = argc2; + myArgv[0] = arg[0]; + myArgv[1] = arg[1]; + myArgv[2] = arg[2]; echo_args.argc = 3; echo_args.argv = myArgv; @@ -149,9 +152,9 @@ int testsuite_test(int argc, char** argv) return EXIT_FAILURE; } - strcpy(echo_args.argv[0], "echoclient"); - strcpy(echo_args.argv[1], "input"); - strcpy(echo_args.argv[2], outputName); + strcpy(arg[0], "echoclient"); + strcpy(arg[1], "input"); + strcpy(arg[2], outputName); /* Share the signal, it has the new port number in it. */ echo_args.signal = server_args.signal; @@ -175,7 +178,7 @@ int testsuite_test(int argc, char** argv) /* show ciphers */ { - char ciphers[1024]; + char ciphers[WOLFSSL_CIPHER_LIST_MAX_SIZE]; XMEMSET(ciphers, 0, sizeof(ciphers)); wolfSSL_get_ciphers(ciphers, sizeof(ciphers)-1); printf("ciphers = %s\n", ciphers); @@ -183,14 +186,18 @@ int testsuite_test(int argc, char** argv) /* validate output equals input */ { - byte input[SHA256_DIGEST_SIZE]; - byte output[SHA256_DIGEST_SIZE]; + #ifndef NO_SHA256 + byte input[WC_SHA256_DIGEST_SIZE]; + byte output[WC_SHA256_DIGEST_SIZE]; file_test("input", input); file_test(outputName, output); + #endif remove(outputName); + #ifndef NO_SHA256 if (memcmp(input, output, sizeof(input)) != 0) return EXIT_FAILURE; + #endif } wolfSSL_Cleanup(); @@ -200,68 +207,49 @@ int testsuite_test(int argc, char** argv) fdCloseSession(Task_self()); #endif -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); -#endif +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context"); +#endif /* HAVE_WNR */ + printf("\nAll tests passed!\n"); + +#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; + int i; + func_args svrArgs; char *svrArgv[9]; - char argc0s[32]; - char argc1s[32]; - char argc2s[32]; - char argc3s[32]; - char argc4s[32]; - char argc5s[32]; - char argc6s[32]; - char argc7s[32]; - char argc8s[32]; + char argvs[9][32]; func_args cliArgs; char *cliArgv[NUMARGS]; - char argc0c[32]; - char argc1c[32]; - char argc2c[32]; + char argvc[3][32]; - svrArgv[0] = argc0s; - svrArgv[1] = argc1s; - svrArgv[2] = argc2s; - svrArgv[3] = argc3s; - svrArgv[4] = argc4s; - svrArgv[5] = argc5s; - svrArgv[6] = argc6s; - svrArgv[7] = argc7s; - svrArgv[8] = argc8s; - cliArgv[0] = argc0c; - cliArgv[1] = argc1c; - cliArgv[2] = argc2c; + for (i = 0; i < 9; i++) + svrArgv[i] = argvs[i]; + for (i = 0; i < 3; i++) + cliArgv[i] = argvc[i]; + strcpy(argvs[0], "SimpleServer"); svrArgs.argc = 1; svrArgs.argv = svrArgv; svrArgs.return_code = 0; - cliArgs.argc = 1; - cliArgs.argv = cliArgv; - cliArgs.return_code = 0; - - strcpy(svrArgs.argv[0], "SimpleServer"); #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_SNIFFER) && \ !defined(WOLFSSL_TIRTOS) - strcpy(svrArgs.argv[svrArgs.argc++], "-p"); - strcpy(svrArgs.argv[svrArgs.argc++], "0"); - #endif - #ifdef HAVE_NTRU - strcpy(svrArgs.argv[svrArgs.argc++], "-d"); - strcpy(svrArgs.argv[svrArgs.argc++], "-n"); - strcpy(svrArgs.argv[svrArgs.argc++], "-c"); - strcpy(svrArgs.argv[svrArgs.argc++], "./certs/ntru-cert.pem"); - strcpy(svrArgs.argv[svrArgs.argc++], "-k"); - strcpy(svrArgs.argv[svrArgs.argc++], "./certs/ntru-key.raw"); + strcpy(argvs[svrArgs.argc++], "-p"); + strcpy(argvs[svrArgs.argc++], "0"); #endif /* Set the last arg later, when it is known. */ @@ -271,11 +259,15 @@ void simple_test(func_args* args) wait_tcp_ready(&svrArgs); /* Setting the actual port number. */ - strcpy(cliArgs.argv[0], "SimpleClient"); + strcpy(argvc[0], "SimpleClient"); + cliArgs.argv = cliArgv; + cliArgs.return_code = 0; #ifndef USE_WINDOWS_API cliArgs.argc = NUMARGS; - strcpy(cliArgs.argv[1], "-p"); - snprintf(cliArgs.argv[2], sizeof(argc2c), "%d", svrArgs.signal->port); + strcpy(argvc[1], "-p"); + snprintf(argvc[2], sizeof(argvc[2]), "%d", svrArgs.signal->port); + #else + cliArgs.argc = 1; #endif client_test(&cliArgs); @@ -286,6 +278,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) @@ -333,7 +326,7 @@ void join_thread(THREAD_TYPE thread) #elif defined(WOLFSSL_TIRTOS) while(1) { if (Task_getMode(thread) == Task_Mode_TERMINATED) { - Task_sleep(5); + Task_sleep(5); break; } Task_yield(); @@ -343,39 +336,19 @@ void join_thread(THREAD_TYPE thread) assert(res == WAIT_OBJECT_0); res = CloseHandle((HANDLE)thread); assert(res); + (void)res; /* Suppress un-used variable warning */ #endif } -void InitTcpReady(tcp_ready* ready) -{ - ready->ready = 0; - ready->port = 0; -#if defined(_POSIX_THREADS) && !defined(__MINGW32__) - pthread_mutex_init(&ready->mutex, 0); - pthread_cond_init(&ready->cond, 0); -#endif -} - - -void FreeTcpReady(tcp_ready* ready) -{ -#if defined(_POSIX_THREADS) && !defined(__MINGW32__) - pthread_mutex_destroy(&ready->mutex); - pthread_cond_destroy(&ready->cond); -#else - (void)ready; -#endif -} - - +#ifndef NO_SHA256 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) { @@ -390,6 +363,7 @@ void file_test(const char* file, byte* check) ret = wc_Sha256Update(&sha256, buf, i); if (ret != 0) { printf("Can't wc_Sha256Update %d\n", ret); + fclose(f); return; } } @@ -397,19 +371,20 @@ void file_test(const char* file, byte* check) ret = wc_Sha256Final(&sha256, shasum); if (ret != 0) { printf("Can't wc_Sha256Final %d\n", ret); + fclose(f); return; } - memcpy(check, shasum, sizeof(shasum)); + 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); fclose(f); } - +#endif #else /* SINGLE_THREADED */ @@ -425,19 +400,16 @@ int main(int argc, char** argv) server_args.argc = argc; server_args.argv = argv; - if (CurrentDir("testsuite") || CurrentDir("_build")) - ChangeDirBack(1); - else if (CurrentDir("Debug") || CurrentDir("Release")) - ChangeDirBack(3); /* Xcode->Preferences->Locations->Locations*/ - /* Derived Data Advanced -> Custom */ - /* Relative to Workspace, Build/Products */ - /* Debug or Release */ + wolfSSL_Init(); + ChangeToWolfRoot(); wolfcrypt_test(&server_args); if (server_args.return_code != 0) return server_args.return_code; + wolfSSL_Cleanup(); printf("\nAll tests passed!\n"); - return EXIT_SUCCESS; + + EXIT_TEST(EXIT_SUCCESS); } diff --git a/FreeRTOS-Plus/Source/WolfSSL/testsuite/testsuite.vcproj b/FreeRTOS-Plus/Source/WolfSSL/testsuite/testsuite.vcproj index ce71e147d..dc1fad1a4 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/testsuite/testsuite.vcproj +++ b/FreeRTOS-Plus/Source/WolfSSL/testsuite/testsuite.vcproj @@ -41,8 +41,8 @@ + + Disabled - ../;%(AdditionalIncludeDirectories) - NO_MAIN_DRIVER;WOLFSSL_RIPEMD;WOLFSSL_SHA512;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../;../IDE/WIN;%(AdditionalIncludeDirectories) + NO_MAIN_DRIVER;WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -172,14 +172,14 @@ true Console MachineX86 - false + false Disabled - ../;%(AdditionalIncludeDirectories) - NO_MAIN_DRIVER;WOLFSSL_RIPEMD;WOLFSSL_SHA512;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../;../IDE/WIN;%(AdditionalIncludeDirectories) + NO_MAIN_DRIVER;WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;WOLFSSL_DLL;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -193,13 +193,14 @@ true Console MachineX86 + false Disabled - ../;%(AdditionalIncludeDirectories) - NO_MAIN_DRIVER;WOLFSSL_RIPEMD;WOLFSSL_SHA512;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../;../IDE/WIN;%(AdditionalIncludeDirectories) + NO_MAIN_DRIVER;WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -216,8 +217,8 @@ Disabled - ../;%(AdditionalIncludeDirectories) - NO_MAIN_DRIVER;WOLFSSL_RIPEMD;WOLFSSL_SHA512;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../;../IDE/WIN;%(AdditionalIncludeDirectories) + NO_MAIN_DRIVER;WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;WOLFSSL_DLL;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -235,8 +236,8 @@ MaxSpeed true - ../;%(AdditionalIncludeDirectories) - NO_MAIN_DRIVER;WOLFSSL_RIPEMD;WOLFSSL_SHA512;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../;../IDE/WIN;%(AdditionalIncludeDirectories) + NO_MAIN_DRIVER;WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -257,8 +258,8 @@ MaxSpeed true - ../;%(AdditionalIncludeDirectories) - NO_MAIN_DRIVER;WOLFSSL_RIPEMD;WOLFSSL_SHA512;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../;../IDE/WIN;%(AdditionalIncludeDirectories) + NO_MAIN_DRIVER;WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;WOLFSSL_DLL;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -279,8 +280,8 @@ MaxSpeed true - ../;%(AdditionalIncludeDirectories) - NO_MAIN_DRIVER;WOLFSSL_RIPEMD;WOLFSSL_SHA512;OPENSSL_EXTRA;NO_PSK;%(PreprocessorDefinitions) + ../;../IDE/WIN;%(AdditionalIncludeDirectories) + NO_MAIN_DRIVER;WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -300,8 +301,8 @@ MaxSpeed true - ../;%(AdditionalIncludeDirectories) - NO_MAIN_DRIVER;WOLFSSL_RIPEMD;WOLFSSL_SHA512;OPENSSL_EXTRA;NO_PSK;WOLFSSL_DLL;%(PreprocessorDefinitions) + ../;../IDE/WIN;%(AdditionalIncludeDirectories) + NO_MAIN_DRIVER;WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;WOLFSSL_DLL;%(PreprocessorDefinitions) MultiThreadedDLL true @@ -331,6 +332,9 @@ false + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/README b/FreeRTOS-Plus/Source/WolfSSL/tirtos/README new file mode 100644 index 000000000..dc7fbb114 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/README @@ -0,0 +1,17 @@ +# wolfSSL library for TI-RTOS + +This directory contains the files that build wolfSSL library for TI-RTOS. +Please follow the instructions in "Using wolfSSL with TI-RTOS" (http://processors.wiki.ti.com/index.php/Using_wolfSSL_with_TI-RTOS) to build the wolfSSL +library and the example applications. + +Also read TI-RTOS Getting Started Guide and TI-RTOS User Guide to learn more +about TI-RTOS (http://www.ti.com/tool/ti-rtos). + +For more information see: +(https://github.com/wolfSSL/wolfssl-examples/blob/master/tirtos_ccs_examples/README.md) + +## Example Application + +A simple "TCP echo server with TLS" example application is provided with TI-RTOS +product. Look in the TI-RTOS Getting Started Guide for instructions to build +examples. diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/include.am b/FreeRTOS-Plus/Source/WolfSSL/tirtos/include.am new file mode 100644 index 000000000..7299c438e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/include.am @@ -0,0 +1,23 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +EXTRA_DIST += \ + tirtos/README \ + tirtos/wolfssl.bld \ + tirtos/wolfssl.mak \ + tirtos/products.mak \ + tirtos/packages/ti/net/wolfssl/package.bld \ + tirtos/packages/ti/net/wolfssl/package.xdc \ + tirtos/packages/ti/net/wolfssl/package.xs \ + tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/package.bld.hide \ + tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/package.xdc \ + tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/test.cfg \ + tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/TM4C1294NC.icf \ + tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/main.c \ + tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/package.bld.hide \ + tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/package.xdc \ + tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/benchmark.cfg \ + tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/TM4C1294NC.icf \ + tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/main.c + diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/package.bld b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/package.bld new file mode 100644 index 000000000..7f2ef948d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/package.bld @@ -0,0 +1,65 @@ +/* + * ======== package.bld ======== + * Build script for wolfSSL library + */ +var Build = xdc.useModule('xdc.bld.BuildEnvironment'); +var Pkg = xdc.useModule('xdc.bld.PackageContents'); + +/* make command to search for the srcs */ +Pkg.makePrologue = "vpath %.c $(subst ;, ,$(XPKGPATH))"; + +/* WOLFSSL sources */ +var wolfSSLObjList = [ + "wolfcrypt/src/aes.c", + "wolfcrypt/src/arc4.c", + "wolfcrypt/src/asm.c", + "wolfcrypt/src/asn.c", + "wolfcrypt/src/blake2b.c", + "wolfcrypt/src/camellia.c", + "wolfcrypt/src/chacha.c", + "wolfcrypt/src/coding.c", + "wolfcrypt/src/des3.c", + "wolfcrypt/src/dh.c", + "wolfcrypt/src/dsa.c", + "wolfcrypt/src/ecc.c", + "wolfcrypt/src/error.c", + "wolfcrypt/src/hc128.c", + "wolfcrypt/src/hmac.c", + "wolfcrypt/src/hash.c", + "wolfcrypt/src/integer.c", + "wolfcrypt/src/logging.c", + "wolfcrypt/src/md4.c", + "wolfcrypt/src/md5.c", + "wolfcrypt/src/memory.c", + "wolfcrypt/src/poly1305.c", + "wolfcrypt/src/pwdbased.c", + "wolfcrypt/src/rabbit.c", + "wolfcrypt/src/random.c", + "wolfcrypt/src/rsa.c", + "wolfcrypt/src/sha.c", + "wolfcrypt/src/sha256.c", + "wolfcrypt/src/sha512.c", + "wolfcrypt/src/tfm.c", + "wolfcrypt/src/wc_port.c", + "wolfcrypt/src/wolfmath.c", + "wolfcrypt/src/wc_encrypt.c", + + "src/internal.c", + "src/wolfio.c", + "src/keys.c", + "src/ssl.c", + "src/tls.c", +]; + +for each (var targ in Build.targets) { + var libOptions = {incs: wolfsslPathInclude}; + var lib = Pkg.addLibrary("lib/wolfssl", targ, libOptions); + lib.addObjects(wolfSSLObjList); + + var hwLibptions = {incs: wolfsslPathInclude, defs: " -DWOLFSSL_TI_HASH " + + "-DWOLFSSL_TI_CRYPT -DTARGET_IS_SNOWFLAKE_RA2"}; + + var hwLib = Pkg.addLibrary("lib/wolfssl_tm4c_hw", targ, hwLibptions); + hwLib.addObjects(wolfSSLObjList); +} + diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/package.xdc b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/package.xdc new file mode 100644 index 000000000..5fe467d45 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/package.xdc @@ -0,0 +1,6 @@ +/*! + * ======== ti.net.wolfssl ======== + * wolfSSL library for TI-RTOS + */ +package ti.net.wolfssl [1, 0, 0] { +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/package.xs b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/package.xs new file mode 100644 index 000000000..7f5215d36 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/package.xs @@ -0,0 +1,12 @@ +/* + * ======== package.xs ======== + */ + +/* + * ======== getLibs ======== + * Contribute wolfSSL library. + */ +function getLibs(prog) +{ + return ("lib/wolfssl.a" + prog.build.target.suffix); +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/TM4C1294NC.icf b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/TM4C1294NC.icf new file mode 100644 index 000000000..f45398a3d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/TM4C1294NC.icf @@ -0,0 +1,29 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x00000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x00000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x000FFFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x2003FFFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x8000; +define symbol __ICFEDIT_size_heap__ = 0x10000; +/**** End of ICF editor section. ###ICF###*/ + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/benchmark.cfg b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/benchmark.cfg new file mode 100644 index 000000000..e259718d6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/benchmark.cfg @@ -0,0 +1,81 @@ +/* + * ======== benchmark.cfg ======== + */ + +/* ================ General configuration ================ */ +var Defaults = xdc.useModule('xdc.runtime.Defaults'); +var Diags = xdc.useModule('xdc.runtime.Diags'); +var Error = xdc.useModule('xdc.runtime.Error'); +var Log = xdc.useModule('xdc.runtime.Log'); +var Main = xdc.useModule('xdc.runtime.Main'); +var Memory = xdc.useModule('xdc.runtime.Memory'); +var System = xdc.useModule('xdc.runtime.System'); +var Text = xdc.useModule('xdc.runtime.Text'); +var Timestamp = xdc.useModule('xdc.runtime.Timestamp'); + +var BIOS = xdc.useModule('ti.sysbios.BIOS'); +var Clock = xdc.useModule('ti.sysbios.knl.Clock'); +var Task = xdc.useModule('ti.sysbios.knl.Task'); +var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore'); +var Hwi = xdc.useModule('ti.sysbios.hal.Hwi'); +var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem'); +var Timer = xdc.useModule('ti.sysbios.hal.Timer'); + +BIOS.heapSize = 86016; +Task.idleTaskStackSize = 768; + +/* + * Program.stack is ignored with IAR. Use the project options in + * IAR Embedded Workbench to alter the system stack size. + */ +if (!Program.build.target.$name.match(/iar/)) { + /* + * Reducing the system stack size (used by ISRs and Swis) to reduce + * RAM usage. + */ + Program.stack = 2048; +} + +/* ================ System configuration ================ */ +var SysMin = xdc.useModule('xdc.runtime.SysMin'); +SysMin.bufSize = 128; +System.SupportProxy = SysMin; + +/* Enable Semihosting for GNU targets to print to CCS console */ +if (Program.build.target.$name.match(/gnu/)) { + var SemiHost = xdc.useModule('ti.sysbios.rts.gnu.SemiHostSupport'); +} + +/* ================ NDK configuration ================ */ +var Ndk = xdc.loadPackage('ti.ndk.config'); +var Global = xdc.useModule('ti.ndk.config.Global'); +var Tcp = xdc.useModule('ti.ndk.config.Tcp'); + +Global.IPv6 = false; +Global.stackLibType = Global.MIN; + +Global.pktNumFrameBufs = 10; +Global.memRawPageCount = 6; +Global.ndkThreadStackSize = 1536; +Global.lowTaskStackSize = 1024; +Global.normTaskStackSize = 1024; +Global.highTaskStackSize = 1024; +Tcp.transmitBufSize = 1024; +Tcp.receiveBufSize = 1024; + + +/* ================ Driver configuration ================ */ +var TIRTOS = xdc.useModule('ti.tirtos.TIRTOS'); +TIRTOS.useEMAC = true; +TIRTOS.useGPIO = true; + +/* ================ wolfSSL configuration ================ */ +try { + var wolfSSL = xdc.loadPackage('ti.net.wolfssl'); +} +catch (e) { + print("Error: Could not find wolfSSL library! Make sure the wolfSSL library" + + " is built and package path is updated for the build tool" + + " to find the library. More detailed wolfSSL build instructions" + + " can be found in the TI-RTOS user guide."); +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/main.c b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/main.c new file mode 100644 index 000000000..eddd432f7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/main.c @@ -0,0 +1,106 @@ +/* + * ======== main.c ======== + * Entry point for Benchmark application + */ +/* BIOS Header files */ +#include +#include +#include +#include +#include + +static int initialized = 0; +static double msTicks = 0; +static Timer_Handle hdl = NULL; + +double current_time(int reset); +static void tick(unsigned int arg0); +void msTimer_init(void); +void runBenchmarks(UArg arg0, UArg arg1); +extern int benchmark_test(void* args); + +/* + * ======== runBenchmarks ======== + * Run the wolfSSL benchmark application + */ +void runBenchmarks(UArg arg0, UArg arg1) +{ + void *args = NULL; + msTimer_init(); + + System_printf("Running benchmarks...\n"); + System_flush(); + benchmark_test(args); + System_printf("Benchmarks completed.\n"); + + BIOS_exit(0); +} + +/* + * ======== ticks ======== + * Keeps track of time in millisec + */ +static void tick(unsigned int arg0) +{ + Swi_disable(); + msTicks++; + Swi_enable(); +} + +/* + * ======== current_time ======== + * Returns the time in sec (double precision) + */ +double current_time(int reset) +{ + if (reset) { + msTicks = 0; + } + + return (msTicks/1000); +} + +/* + * ======== msTimer_init ======== + * Sets up a BIOS timer with millisec period + */ +void msTimer_init(void) +{ + Timer_Params params; + + if (initialized) { + return; + } + + Timer_Params_init(¶ms); + params.period = 1000; + params.periodType = Timer_PeriodType_MICROSECS; + params.runMode = Timer_RunMode_CONTINUOUS; + params.startMode = Timer_StartMode_AUTO; + hdl = Timer_create(-1, (ti_sysbios_hal_Timer_FuncPtr)tick, + ¶ms, NULL); + if (!hdl) { + System_abort("msTimer_init: Timer creation failed.\n"); + } + + /* Set flag indicating that initialization has completed */ + initialized = 1; +} + +/* + * ======== main ======== + */ +int main(int argc, char** argv) +{ + /* Initialize the defaults and set the parameters. */ + Task_Handle handle; + Task_Params taskParams; + Task_Params_init(&taskParams); + taskParams.stackSize = 65535; + handle = Task_create(runBenchmarks, &taskParams, NULL); + if (handle == NULL) { + System_printf("main: Failed to create new Task.\n"); + } + + BIOS_start(); +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/package.bld.hide b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/package.bld.hide new file mode 100644 index 000000000..453fee738 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/package.bld.hide @@ -0,0 +1,53 @@ +/* + * ======== package.bld ======== + * Build script for benchmark application + */ + +if ((typeof(TivaWareDir) == undefined) || (TivaWareDir == "")) { + throw("ERROR: NO VALID TIVAWARE PATH DEFINED!!!"); +} + +var Build = xdc.useModule('xdc.bld.BuildEnvironment'); +var Pkg = xdc.useModule('xdc.bld.PackageContents'); + +/* make command to search for the srcs */ +Pkg.makePrologue = "vpath %.c $(subst ;, ,$(XPKGPATH))"; + +var srcs = [ + "main.c", + "wolfcrypt/benchmark/benchmark.c", + "examples/boards/EK_TM4C1294XL/EK_TM4C1294XL.c", +]; + +for each (var targ in Build.targets) { + + var lnkOpts = ""; + var platform = "ti.platforms.tiva:TM4C1294NCPDT:1"; + if (targ.$name.match(/^ti/)) { + lnkOpts = " -l" + TivaWareDir + "/driverlib/ccs/Debug/driverlib.lib"; + lnkOpts += " -x "; + } + else if (targ.$name.match(/^iar/)) { + lnkOpts = TivaWareDir + "/driverlib/ewarm/Exe/driverlib.a" + + " --config TM4C1294NC.icf"; + platform = "ti.platforms.tiva:TM4C1294NCPDT"; + + /* Floating point print support */ + var suffix = targ.$orig.lnkOpts.suffix; + targ.$orig.lnkOpts.suffix = suffix.replace(/PrintfSmall/, "PrintfFull"); + } + else if (targ.$name.match(/^gnu/)) { + targ.$orig.lnkOpts.suffix += " -L" + TivaWareDir + "/driverlib/gcc " + + " -Wl,--start-group -ldriver -Wl,--end-group "; + targ.$orig.bspLib = "rdimon"; + } + + var exeOptions = { incs: wolfsslPathInclude + + " -DNO_MAIN_DRIVER -D_INCLUDE_NIMU_CODE -DBENCH_EMBEDDED " + + " -DTIVAWARE -DPART_TM4C1294NCPDT", + lopts: lnkOpts + }; + + var exe = Pkg.addExecutable("benchmark", targ, platform, exeOptions); + exe.addObjects(srcs); +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/package.xdc b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/package.xdc new file mode 100644 index 000000000..6a93cc333 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/benchmark/package.xdc @@ -0,0 +1,6 @@ +/* + * ======== ti.net.wolfssl.tests.EK_TM4C1294XL.wolfcrypt.benchmark ======== + * wc_ Benchmark Application + */ +package ti.net.wolfssl.tests.EK_TM4C1294XL.wolfcrypt.benchmark [1, 0, 0] { +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/TM4C1294NC.icf b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/TM4C1294NC.icf new file mode 100644 index 000000000..f45398a3d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/TM4C1294NC.icf @@ -0,0 +1,29 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x00000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x00000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x000FFFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x2003FFFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x8000; +define symbol __ICFEDIT_size_heap__ = 0x10000; +/**** End of ICF editor section. ###ICF###*/ + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/main.c b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/main.c new file mode 100644 index 000000000..88023e4e1 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/main.c @@ -0,0 +1,55 @@ +/* + * ======== main.c ======== + * Entry point to wolfcrypt Test Application + */ + +/* XDCtools Header files */ +#include +#include +#include + +/* func_args from test.h, so don't have to pull in other junk */ +typedef struct func_args { + int argc; + char** argv; + int return_code; +} func_args; + +extern int wolfcrypt_test(void* args); + +/* + * ======== testwolfcrypt ======== + * Run the wolfcrypt test + */ +void testwolfcrypt(UArg arg0, UArg arg1) +{ + System_printf("Running wolfcrypt tests...\n"); + System_flush(); + wolfcrypt_test((void *)arg0); + System_printf("Tests completed.\n"); + + BIOS_exit(0); +} + +/* + * ======== main ======== + */ +int main(int argc, char** argv) +{ + func_args args; + args.argc = argc; + args.argv = argv; + /* Initialize the defaults and set the parameters. */ + Task_Handle handle; + Task_Params taskParams; + Task_Params_init(&taskParams); + taskParams.arg0 = (UArg)&args; + taskParams.stackSize = 65535; + handle =Task_create(testwolfcrypt, &taskParams, NULL); + if (handle == NULL) { + System_printf("main: Failed to create new Task.\n"); + return (-1); + } + + BIOS_start(); +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/package.bld.hide b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/package.bld.hide new file mode 100644 index 000000000..adfca1c9c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/package.bld.hide @@ -0,0 +1,49 @@ +/* + * ======== package.bld ======== + * Build script for wolfcrypt Test + */ + +if ((typeof(TivaWareDir) == undefined) || (TivaWareDir == "")) { + throw("ERROR: NO VALID TIVAWARE PATH DEFINED!!!"); +} + +var Build = xdc.useModule('xdc.bld.BuildEnvironment'); +var Pkg = xdc.useModule('xdc.bld.PackageContents'); + +/* make command to search for the srcs */ +Pkg.makePrologue = "vpath %.c $(subst ;, ,$(XPKGPATH))"; + +var srcs = [ + "main.c", + "wolfcrypt/test/test.c", + "examples/boards/EK_TM4C1294XL/EK_TM4C1294XL.c", +]; + +for each (var targ in Build.targets) { + + var lnkOpts = ""; + var platform = "ti.platforms.tiva:TM4C1294NCPDT:1"; + if (targ.$name.match(/^ti/)) { + lnkOpts = " -l" + TivaWareDir + "/driverlib/ccs/Debug/driverlib.lib"; + lnkOpts += " -x "; + } + else if (targ.$name.match(/^iar/)) { + lnkOpts = TivaWareDir + "/driverlib/ewarm/Exe/driverlib.a" + + " --config TM4C1294NC.icf"; + platform = "ti.platforms.tiva:TM4C1294NCPDT"; + } + else if (targ.$name.match(/^gnu/)) { + targ.$orig.lnkOpts.suffix += " -L" + TivaWareDir + "/driverlib/gcc " + + " -Wl,--start-group -ldriver -Wl,--end-group "; + targ.$orig.bspLib = "rdimon"; + } + + var exeOptions = { incs: wolfsslPathInclude + + " -DNO_MAIN_DRIVER -D_INCLUDE_NIMU_CODE -DBENCH_EMBEDDED " + + " -DTIVAWARE -DPART_TM4C1294NCPDT", + lopts: lnkOpts, + }; + + var exe = Pkg.addExecutable("test", targ, platform, exeOptions); + exe.addObjects(srcs); +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/package.xdc b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/package.xdc new file mode 100644 index 000000000..0b85d5786 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/package.xdc @@ -0,0 +1,6 @@ +/* + * ======== ti.net.wolfssl.tests.EK_TM4C1294XL.wolfcrypt.test ======== + * wolfcrypt Test Application + */ +package ti.net.wolfssl.tests.EK_TM4C1294XL.wolfcrypt.test [1, 0, 0] { +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/test.cfg b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/test.cfg new file mode 100644 index 000000000..dd8efc801 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/packages/ti/net/wolfssl/tests/EK_TM4C1294XL/wolfcrypt/test/test.cfg @@ -0,0 +1,80 @@ +/* + * ======== test.cfg ======== + */ + +/* ================ General configuration ================ */ +var Defaults = xdc.useModule('xdc.runtime.Defaults'); +var Diags = xdc.useModule('xdc.runtime.Diags'); +var Error = xdc.useModule('xdc.runtime.Error'); +var Log = xdc.useModule('xdc.runtime.Log'); +var Main = xdc.useModule('xdc.runtime.Main'); +var Memory = xdc.useModule('xdc.runtime.Memory'); +var System = xdc.useModule('xdc.runtime.System'); +var Text = xdc.useModule('xdc.runtime.Text'); +var Timestamp = xdc.useModule('xdc.runtime.Timestamp'); + +var BIOS = xdc.useModule('ti.sysbios.BIOS'); +var Clock = xdc.useModule('ti.sysbios.knl.Clock'); +var Task = xdc.useModule('ti.sysbios.knl.Task'); +var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore'); +var Hwi = xdc.useModule('ti.sysbios.hal.Hwi'); +var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem'); + +BIOS.heapSize = 86016; +Task.idleTaskStackSize = 768; + +/* + * Program.stack is ignored with IAR. Use the project options in + * IAR Embedded Workbench to alter the system stack size. + */ +if (!Program.build.target.$name.match(/iar/)) { + /* + * Reducing the system stack size (used by ISRs and Swis) to reduce + * RAM usage. + */ + Program.stack = 2048; +} + +/* ================ System configuration ================ */ +var SysMin = xdc.useModule('xdc.runtime.SysMin'); +SysMin.bufSize = 128; +System.SupportProxy = SysMin; + +/* Enable Semihosting for GNU targets to print to CCS console */ +if (Program.build.target.$name.match(/gnu/)) { + var SemiHost = xdc.useModule('ti.sysbios.rts.gnu.SemiHostSupport'); +} + +/* ================ NDK configuration ================ */ +var Ndk = xdc.loadPackage('ti.ndk.config'); +var Global = xdc.useModule('ti.ndk.config.Global'); +var Tcp = xdc.useModule('ti.ndk.config.Tcp'); + +Global.IPv6 = false; +Global.stackLibType = Global.MIN; + +Global.pktNumFrameBufs = 10; +Global.memRawPageCount = 6; +Global.ndkThreadStackSize = 1536; +Global.lowTaskStackSize = 1024; +Global.normTaskStackSize = 1024; +Global.highTaskStackSize = 1024; +Tcp.transmitBufSize = 1024; +Tcp.receiveBufSize = 1024; + + +/* ================ Driver configuration ================ */ +var TIRTOS = xdc.useModule('ti.tirtos.TIRTOS'); +TIRTOS.useEMAC = true; +TIRTOS.useGPIO = true; + +/* ================ wolfSSL configuration ================ */ +try { + var wolfSSL = xdc.loadPackage('ti.net.wolfssl'); +} +catch (e) { + print("Error: Could not find wolfSSL library! Make sure the wolfSSL library" + + " is built and package path is updated for the build tool" + + " to find the library. More detailed wolfSSL build instructions" + + " can be found in the TI-RTOS user guide."); +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/products.mak b/FreeRTOS-Plus/Source/WolfSSL/tirtos/products.mak new file mode 100644 index 000000000..8bf1823db --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/products.mak @@ -0,0 +1,30 @@ +# +# ======== products.mak ======== +# +# +# Read the http://processors.wiki.ti.com/index.php/Using_wolfSSL_with_TI-RTOS +# for instructions to download the software required. + +# XDC_INSTALL_DIR is the path to XDCtools directory. +XDC_INSTALL_DIR = + +# BIOS_INSTALL_DIR is the path to TI-RTOS Kernel (SYS/BIOS) directory. If you +# have installed TI-RTOS, it is located in the products/bios_* path. +BIOS_INSTALL_DIR = + +# NDK_INSTALL_DIR is the path to TI-RTOS NDK directory. If you have +# installed TI-RTOS, it is located in the products/ndk_* path. +NDK_INSTALL_DIR = + +# TIVAWARE_INSTALL_DIR is the path to Tivaware driverlib directory. If you have +# installed TI-RTOS, it is located in the products/TivaWare_* path. +TIVAWARE_INSTALL_DIR = + +# Define the code generation tools path for TI, IAR and GCC ARM compilers. +# If you have installed Code Composer Studio, the TI and GCC compiler are +# located in the ccsv*/tools/compiler/* path. +# +# Leave assignment empty to disable any toolchain. +ti.targets.arm.elf.M4F = +iar.targets.arm.M4F = +gnu.targets.arm.M4F = diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/wolfssl.bld b/FreeRTOS-Plus/Source/WolfSSL/tirtos/wolfssl.bld new file mode 100644 index 000000000..59e95103b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/wolfssl.bld @@ -0,0 +1,89 @@ +/* + * Generally there is no need to edit this file! + * + * This file controls which libraries are built, as well as compiler options + * to use. + * + * The contents of this file usually don't change, but having it in your + * ownership allows you to tweak your compiler options. If you do change + * this file, however, on the next upgrade of the product we recommend + * that you take "wolfssl.bld" file as supplied by the upgrade and then merge + * your changes with it. + */ + +/* + * ======== wolfssl.bld ======== + * This script is run prior to all build scripts. It sets host-system- + * independent values for targets and platforms, then it attempts to + * find the host-system-specific user.bld script that sets rootDirs. + * + * These settings may be a function of the following global variables: + * + * environment a hash table of environment strings + * + * arguments an array of string arguments to the _config.bld script + * initialized as follows: + * arguments[0] - the file name of the _config.bld script + * arguments[1] - the first argument specified in XDCARGS + * : + * arguments[n] - the n'th argument in XDCARGS + * + * Build an alias for xdc.om.xdc.bld.BuildEnvironment + */ + +var armOpts = " -ms "; +var gnuOpts = " -D_POSIX_SOURCE "; +var iarOpts = " --diag_suppress=Pa134 "; +var ndkDir = ""; + +/* Uncomment the following lines to build libraries for debug mode: */ +// Pkg.attrs.profile = "debug"; +// armOpts += " -g -o0 "; +// gnuOpts += " -g -D_POSIX_SOURCE "; +// iarOpts += " --debug "; + +var ccOpts = { + "ti.targets.arm.elf.M4" : armOpts, + "ti.targets.arm.elf.M4F" : armOpts, + + "gnu.targets.arm.M4" : gnuOpts, + "gnu.targets.arm.M4F" : gnuOpts, + + "iar.targets.arm.M4" : iarOpts, + "iar.targets.arm.M4F" : iarOpts, +}; + +/* initialize local vars with those set in xdcpaths.mak (via XDCARGS) */ +for (arg = 0; arg < arguments.length; arg++) { + /* + * Get the compiler's installation directory. + * For "ti.targets.arm.elf.M4F=/vendors/arm/6.1.0", + * we get "/vendors/arm/6.1.0" + */ + var targetName = arguments[arg].split("=")[0]; + var rootDir = arguments[arg].split("=")[1]; + + /* only build for the specified compilers */ + if (rootDir == "" || rootDir == undefined) { + continue; + } + + if (targetName.match(/^NDK/) ) { + ndkDir = rootDir; + continue; + } + + var target = xdc.useModule(targetName); + target.rootDir = rootDir; + target.ccOpts.suffix += ccOpts[targetName]; + + Build.targets.$add(target); +} + +/* Include Path (needed to find NDK headers) */ +var wolfsslPathInclude = " -I" + ndkDir + "/packages/ti/ndk/inc/bsd " + + "-DWOLFSSL_TIRTOS "; + +/* lib/ is a generated directory that 'xdc clean' should remove */ +var Pkg = xdc.useModule('xdc.bld.PackageContents'); +Pkg.generatedFiles.$add("lib/"); diff --git a/FreeRTOS-Plus/Source/WolfSSL/tirtos/wolfssl.mak b/FreeRTOS-Plus/Source/WolfSSL/tirtos/wolfssl.mak new file mode 100644 index 000000000..f3088857f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/tirtos/wolfssl.mak @@ -0,0 +1,64 @@ +# +# ======== wolfssl.mak ======== +# +include ./products.mak + +# Enable older TI-RTOS 2.14-based variables +ifeq ($(BIOS_INSTALL_DIR),) + BIOS_INSTALL_DIR=$(SYSBIOS_INSTALL_DIR) +endif +ifeq ($(TIVAWARE_INSTALL_DIR),) + TIVAWARE_INSTALL_DIR=$(TIVAWARE) +endif + +WOLFSSL_INSTALL_DIR=$(CURDIR)/../ + +# +# Set XDCARGS to some of the variables above. XDCARGS are passed +# to the XDC build engine... which will load wolfssl.bld... which will +# extract these variables and use them to determine what to build and which +# toolchains to use. +# +# Note that not all of these variables need to be set to something valid. +# Unfortunately, since these vars are unconditionally assigned, your build line +# will be longer and more noisy than necessary. +# +# Some background is here: +# http://rtsc.eclipse.org/docs-tip/Command_-_xdc#Environment_Variables +# +XDCARGS= \ + ti.targets.arm.elf.M4F=\"$(ti.targets.arm.elf.M4F)\" \ + gnu.targets.arm.M4F=\"$(gnu.targets.arm.M4F)\" \ + iar.targets.arm.M4F=\"$(iar.targets.arm.M4F)\" \ + NDK=\"$(NDK_INSTALL_DIR)\" + +# +# Set XDCPATH to contain necessary repositories. +# +XDCPATH = $(BIOS_INSTALL_DIR)/packages;$(NDK_INSTALL_DIR)/packages;$(WOLFSSL_INSTALL_DIR);$(TIVAWARE_INSTALL_DIR) +export XDCPATH + +# +# Set XDCOPTIONS. Use -v for a verbose build. +# +#XDCOPTIONS=v +export XDCOPTIONS + +# +# Set XDC executable command +# Note that XDCBUILDCFG points to the wolfssl.bld file which uses +# the arguments specified by XDCARGS +# +XDC = $(XDC_INSTALL_DIR)/xdc XDCARGS="$(XDCARGS)" XDCBUILDCFG=./wolfssl.bld + +####################################################### +## Shouldn't have to modify anything below this line ## +####################################################### + +all: + @ echo building wolfssl packages ... + @ $(XDC) -Pr ./packages + +clean: + @ echo cleaning wolfssl packages ... + @ $(XDC) clean -Pr ./packages diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/README.md b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/README.md new file mode 100644 index 000000000..fc01f377b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/README.md @@ -0,0 +1,103 @@ +# wolfCrypt Benchmarks + +Tool for performing cryptographic algorithm benchmarking. + +## Measurements + +* Symmetric algorithms like AES and ChaCha20 are measured in Killobytes (KB) or Megabytes (MB) per second. +* Asymmetric algorithms like RSA and ECC are measured using Operations Per Second (Ops) per second. + +## Usage + +```sh +./wolfcrypt/benchmark/benchmark -? +benchmark +-? Help, print this usage + 0: English, 1: Japanese +-csv Print terminal output in csv format +-base10 Display bytes as power of 10 (eg 1 kB = 1000 Bytes) +-no_aad No additional authentication data passed. +-dgst_full Full digest operation performed. +-rsa_sign Measure RSA sign/verify instead of encrypt/decrypt. + -rsa-sz + Measure RSA performance. +- Algorithm to benchmark. Available algorithms include: + cipher aes-cbc aes-gcm aes-ecb aes-xts aes-cfb aes-ctr aes-ccm + camellia arc4 hc128 rabbit chacha20 chacha20-poly1305 des idea + digest md5 poly1305 sha sha2 sha224 sha256 sha384 sha512 sha3 + sha3-224 sha3-256 sha3-384 sha3-512 ripemd + mac cmac hmac hmac-md5 hmac-sha hmac-sha224 hmac-sha256 + hmac-sha384 hmac-sha512 pbkdf2 + asym rsa-kg rsa rsa-sz dh ecc-kg ecc ecc-enc curve25519_kg x25519 + ed25519-kg ed25519 + other rng scrypt +-lng Display benchmark result by specified language. + 0: English, 1: Japanese + Size of block in bytes +``` + +The `-base10` option shows as thousands of bytes (kB). + +## Example Output + +Run on Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz. + +```sh +./configure --enable-intelasm --enable-aesni --enable-sp --enable-sp-asm && make + +./wolfcrypt/benchmark/benchmark +------------------------------------------------------------------------------ + wolfSSL version 4.0.0 +------------------------------------------------------------------------------ +wolfCrypt Benchmark (block bytes 1048576, min 1.0 sec each) +RNG 180 MB took 1.022 seconds, 176.201 MB/s Cycles per byte = 16.76 +AES-128-CBC-enc 1250 MB took 1.002 seconds, 1247.878 MB/s Cycles per byte = 2.37 +AES-128-CBC-dec 4595 MB took 1.001 seconds, 4591.703 MB/s Cycles per byte = 0.64 +AES-192-CBC-enc 1005 MB took 1.003 seconds, 1002.018 MB/s Cycles per byte = 2.95 +AES-192-CBC-dec 4345 MB took 1.000 seconds, 4344.744 MB/s Cycles per byte = 0.68 +AES-256-CBC-enc 905 MB took 1.005 seconds, 900.386 MB/s Cycles per byte = 3.28 +AES-256-CBC-dec 3255 MB took 1.001 seconds, 3251.618 MB/s Cycles per byte = 0.91 +AES-128-GCM-enc 4730 MB took 1.001 seconds, 4726.267 MB/s Cycles per byte = 0.62 +AES-128-GCM-dec 5140 MB took 1.000 seconds, 5137.596 MB/s Cycles per byte = 0.57 +AES-192-GCM-enc 4475 MB took 1.001 seconds, 4471.056 MB/s Cycles per byte = 0.66 +AES-192-GCM-dec 3405 MB took 1.001 seconds, 3403.179 MB/s Cycles per byte = 0.87 +AES-256-GCM-enc 2640 MB took 1.000 seconds, 2638.905 MB/s Cycles per byte = 1.12 +AES-256-GCM-dec 2780 MB took 1.001 seconds, 2776.632 MB/s Cycles per byte = 1.06 +CHACHA 2615 MB took 1.000 seconds, 2614.357 MB/s Cycles per byte = 1.13 +CHA-POLY 1490 MB took 1.001 seconds, 1488.344 MB/s Cycles per byte = 1.98 +MD5 440 MB took 1.010 seconds, 435.763 MB/s Cycles per byte = 6.78 +POLY1305 4900 MB took 1.001 seconds, 4896.430 MB/s Cycles per byte = 0.60 +SHA 515 MB took 1.011 seconds, 509.459 MB/s Cycles per byte = 5.80 +SHA-224 425 MB took 1.005 seconds, 422.737 MB/s Cycles per byte = 6.98 +SHA-256 420 MB took 1.006 seconds, 417.312 MB/s Cycles per byte = 7.08 +SHA-384 615 MB took 1.003 seconds, 613.018 MB/s Cycles per byte = 4.82 +SHA-512 560 MB took 1.007 seconds, 556.230 MB/s Cycles per byte = 5.31 +SHA3-224 295 MB took 1.003 seconds, 294.133 MB/s Cycles per byte = 10.04 +SHA3-256 280 MB took 1.003 seconds, 279.088 MB/s Cycles per byte = 10.58 +SHA3-384 215 MB took 1.002 seconds, 214.654 MB/s Cycles per byte = 13.76 +SHA3-512 145 MB took 1.005 seconds, 144.266 MB/s Cycles per byte = 20.47 +HMAC-MD5 485 MB took 1.004 seconds, 483.019 MB/s Cycles per byte = 6.11 +HMAC-SHA 505 MB took 1.006 seconds, 502.159 MB/s Cycles per byte = 5.88 +HMAC-SHA224 415 MB took 1.007 seconds, 411.965 MB/s Cycles per byte = 7.17 +HMAC-SHA256 380 MB took 1.002 seconds, 379.398 MB/s Cycles per byte = 7.78 +HMAC-SHA384 610 MB took 1.006 seconds, 606.370 MB/s Cycles per byte = 4.87 +HMAC-SHA512 620 MB took 1.001 seconds, 619.377 MB/s Cycles per byte = 4.77 +RSA 2048 public 52000 ops took 1.001 sec, avg 0.019 ms, 51932.223 ops/sec +RSA 2048 private 1700 ops took 1.022 sec, avg 0.601 ms, 1662.697 ops/sec +DH 2048 key gen 3491 ops took 1.000 sec, avg 0.286 ms, 3490.745 ops/sec +DH 2048 agree 3500 ops took 1.014 sec, avg 0.290 ms, 3452.191 ops/sec +ECC 256 key gen 88961 ops took 1.000 sec, avg 0.011 ms, 88960.279 ops/sec +ECDHE 256 agree 20700 ops took 1.005 sec, avg 0.049 ms, 20605.239 ops/sec +ECDSA 256 sign 53200 ops took 1.001 sec, avg 0.019 ms, 53157.214 ops/sec +ECDSA 256 verify 17200 ops took 1.004 sec, avg 0.058 ms, 17124.208 ops/sec +Benchmark complete +``` + + +## Windows Visual Studio + +For building wolfCrypt Benchmark project in Visual Studio open the `benchmark.sln`. For newer Visual Studio version it may prompt for a one-way upgrade. Then you may have to right-click on the solution and choose `Retarget solution` to update the project files for your Visual Studio version. + +If you see an error about `rc.exe` then you'll need to update the "Target Platform Version". You can do this by right-clicking on the benchmark project -> General -> "Target Platform Version" and changing to 8.1 (needs to match the wolfssl library project). + +This solution includes the wolfSSL library project at `wolfssl.vcxproj` and will compile the library, then the benchmark project. diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.c index f284774f3..f79f7c86f 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.c @@ -1,8 +1,8 @@ /* benchmark.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* wolfCrypt benchmark */ @@ -26,17 +27,104 @@ #include #endif +#ifndef WOLFSSL_USER_SETTINGS + #include +#endif #include +#include +#include -#include +/* Macro to disable benchmark */ +#ifndef NO_CRYPT_BENCHMARK -#ifdef FREESCALE_MQX - #include - #include -#else - #include +/* only for stack size check */ +#ifdef HAVE_STACK_SIZE + #include + #include #endif +#ifdef USE_FLAT_BENCHMARK_H + #include "benchmark.h" +#else + #include "wolfcrypt/benchmark/benchmark.h" +#endif + +/* printf mappings */ +#ifdef FREESCALE_MQX + #include + /* see wc_port.h for fio.h and nio.h includes */ +#elif defined(FREESCALE_KSDK_1_3) + #include "fsl_debug_console.h" + #include "fsl_os_abstraction.h" + + #undef printf + #define printf PRINTF +#elif defined(WOLFSSL_DEOS) + #include + #undef printf + #define printf printx +#elif defined(MICRIUM) + #include + void BSP_Ser_Printf (CPU_CHAR* format, ...); + #undef printf + #define printf BSP_Ser_Printf +#elif defined(WOLFSSL_ZEPHYR) + #include + #define BENCH_EMBEDDED + #define printf printfk + static int printfk(const char *fmt, ...) + { + int ret; + char line[150]; + va_list ap; + + va_start(ap, fmt); + + ret = vsnprintf(line, sizeof(line), fmt, ap); + line[sizeof(line)-1] = '\0'; + printk("%s", line); + + va_end(ap); + + return ret; + } + +#elif defined(WOLFSSL_TELIT_M2MB) + #include + #include + #include + #include "m2m_log.h" /* for M2M_LOG_INFO - not standard API */ + /* remap printf */ + #undef printf + #define printf M2M_LOG_INFO + /* OS requires occasional sleep() */ + #ifndef TEST_SLEEP_MS + #define TEST_SLEEP_MS 50 + #endif + #define TEST_SLEEP() m2mb_os_taskSleep(M2MB_OS_MS2TICKS(TEST_SLEEP_MS)) + /* don't use file system for these tests, since ./certs dir isn't loaded */ + #undef NO_FILESYSTEM + #define NO_FILESYSTEM + +#else + #if defined(XMALLOC_USER) || defined(FREESCALE_MQX) + /* MQX classic needs for EXIT_FAILURE */ + #include /* we're using malloc / free direct here */ + #endif + + #ifndef STRING_USER + #include + #include + #endif + + /* enable way for customer to override test/bench printf */ + #ifdef XPRINTF + #undef printf + #define printf XPRINTF + #endif +#endif + +#include #include #include #include @@ -51,68 +139,554 @@ #include #include #include +#include #include #include #include +#include +#ifndef NO_HMAC + #include +#endif +#ifndef NO_PWDBASED + #include +#endif #ifdef HAVE_ECC #include #endif +#ifdef HAVE_IDEA + #include +#endif #ifdef HAVE_CURVE25519 #include #endif #ifdef HAVE_ED25519 #include #endif +#ifdef HAVE_CURVE448 + #include +#endif +#ifdef HAVE_ED448 + #include +#endif #include -#ifdef HAVE_CAVIUM - #include "cavium_sysdep.h" - #include "cavium_common.h" - #include "cavium_ioctl.h" -#endif #ifdef HAVE_NTRU - #include "ntru_crypto.h" + #include "libntruencrypt/ntru_crypto.h" #endif +#include +#include +#include -#if defined(WOLFSSL_MDK_ARM) - extern FILE * wolfSSL_fopen(const char *fname, const char *mode) ; - #define fopen wolfSSL_fopen -#endif - -#if defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM) - #define HAVE_GET_CYCLES - static INLINE word64 get_intel_cycles(void); - static word64 total_cycles; - #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))); -#else - #define BEGIN_INTEL_CYCLES - #define END_INTEL_CYCLES - #define SHOW_INTEL_CYCLES -#endif - -/* let's use buffers, we have them */ -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) - #define USE_CERT_BUFFERS_2048 -#endif - -#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 */ - #if defined(WOLFSSL_MDK_ARM) - #include "cert_data.h" /* use certs_test.c for initial data, - so other commands can share the data. */ - #else - #include +#ifdef WOLF_CRYPTO_CB + #include + #ifdef HAVE_INTEL_QA_SYNC + #include + #endif + #ifdef HAVE_CAVIUM_OCTEON_SYNC + #include #endif #endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifdef WOLFSSL_STATIC_MEMORY + static WOLFSSL_HEAP_HINT* HEAP_HINT; +#else + #define HEAP_HINT NULL +#endif /* WOLFSSL_STATIC_MEMORY */ + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + +/* optional macro to add sleep between tests */ +#ifndef TEST_SLEEP + /* stub the sleep macro */ + #define TEST_SLEEP() +#endif + + +/* 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 +#define BENCH_AES_CFB 0x00010000 +#define BENCH_AES_OFB 0x00020000 +/* 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_BLAKE2B 0x00002000 +#define BENCH_BLAKE2S 0x00004000 + +/* 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) +#define BENCH_PBKDF2 0x00000100 + +/* Asymmetric algorithms. */ +#define BENCH_RSA_KEYGEN 0x00000001 +#define BENCH_RSA 0x00000002 +#define BENCH_RSA_SZ 0x00000004 +#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 +#define BENCH_CURVE448_KEYGEN 0x00100000 +#define BENCH_CURVE448_KA 0x00200000 +#define BENCH_ED448_KEYGEN 0x00400000 +#define BENCH_ED448_SIGN 0x00800000 +/* 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; + +#ifndef MAIN_NO_ARGS +/* 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_CFB + { "-aes-cfb", BENCH_AES_CFB }, +#endif +#ifdef WOLFSSL_AES_OFB + { "-aes-ofb", BENCH_AES_OFB }, +#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 + { "-blake2b", BENCH_BLAKE2B }, +#endif +#ifdef HAVE_BLAKE2S + { "-blake2s", BENCH_BLAKE2S }, +#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 + #ifndef NO_PWDBASED + { "-pbkdf2", BENCH_PBKDF2 }, + #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 }, + { "-rsa-sz", BENCH_RSA_SZ }, +#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 +#ifdef HAVE_CURVE448 + { "-curve448-kg", BENCH_CURVE448_KEYGEN }, + #ifdef HAVE_CURVE448_SHARED_SECRET + { "-x448", BENCH_CURVE448_KA }, + #endif +#endif +#ifdef HAVE_ED448 + { "-ed448-kg", BENCH_ED448_KEYGEN }, + { "-ed448", BENCH_ED448_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 /* MAIN_NO_ARGS */ + +#endif /* !WOLFSSL_BENCHMARK_ALL && !NO_MAIN_DRIVER */ + + +#ifdef HAVE_WNR + const char* wnrConfigFile = "wnr-example.conf"; +#endif + +#if defined(WOLFSSL_MDK_ARM) + extern XFILE wolfSSL_fopen(const char *fname, const char *mode); + #define fopen wolfSSL_fopen +#endif + +static int lng_index = 0; + +#ifndef NO_MAIN_DRIVER +#ifndef MAIN_NO_ARGS +static const char* bench_Usage_msg1[][16] = { + /* 0 English */ + { "-? Help, print this usage\n 0: English, 1: Japanese\n", + "-csv Print terminal output in csv format\n", + "-base10 Display bytes as power of 10 (eg 1 kB = 1000 Bytes)\n", + "-no_aad No additional authentication data passed.\n", + "-dgst_full Full digest operation performed.\n", + "-rsa_sign Measure RSA sign/verify instead of encrypt/decrypt.\n", + " -rsa-sz\n Measure RSA performance.\n", + "-ffhdhe2048 Measure DH using FFDHE 2048-bit parameters.\n", + "-ffhdhe3072 Measure DH using FFDHE 3072-bit parameters.\n", + "-p256 Measure ECC using P-256 curve.\n", + "-p384 Measure ECC using P-384 curve.\n", + "- Algorithm to benchmark. Available algorithms include:\n", + "-lng Display benchmark result by specified language.\n 0: English, 1: Japanese\n", + " Size of block in bytes\n", + "-threads Number of threads to run\n", + "-print Show benchmark stats summary\n" + }, +#ifndef NO_MULTIBYTE_PRINT + /* 1 Japanese */ + { "-? ヘルプ, 使い方を表示します。\n 0: 英語、 1: 日本語\n", + "-csv csv 形式で端末に出力します。\n", + "-base10 バイトを10のべき乗で表示します。(例 1 kB = 1000 Bytes)\n", + "-no_aad 追加の認証データを使用しません.\n", + "-dgst_full フルの digest 暗号操作を実施します。\n", + "-rsa_sign 暗号/復号化の代わりに RSA の署名/検証を測定します。\n", + " -rsa-sz\n RSA の性能を測定します。\n", + "-ffhdhe2048 Measure DH using FFDHE 2048-bit parameters.\n", + "-ffhdhe3072 Measure DH using FFDHE 3072-bit parameters.\n", + "-p256 Measure ECC using P-256 curve.\n", + "-p384 Measure ECC using P-384 curve.\n", + "- アルゴリズムのベンチマークを実施します。\n 利用可能なアルゴリズムは下記を含みます:\n", + "-lng 指定された言語でベンチマーク結果を表示します。\n 0: 英語、 1: 日本語\n", + " ブロックサイズをバイト単位で指定します。\n", + "-threads 実行するスレッド数\n", + "-print ベンチマーク統計の要約を表示する\n" + }, +#endif +}; +#endif /* MAIN_NO_ARGS */ +#endif + +static const char* bench_result_words1[][4] = { + { "took", "seconds" , "Cycles per byte", NULL }, /* 0 English */ +#ifndef NO_MULTIBYTE_PRINT + { "を" , "秒で処理", "1バイトあたりのサイクル数", NULL }, /* 1 Japanese */ +#endif +}; + +#if !defined(NO_RSA) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_NTRU) || \ + defined(HAVE_ECC) || !defined(NO_DH) || defined(HAVE_ECC_ENCRYPT) || \ + defined(HAVE_CURVE25519) || defined(HAVE_CURVE25519_SHARED_SECRET) || \ + defined(HAVE_ED25519) || defined(HAVE_CURVE448) || \ + defined(HAVE_CURVE448_SHARED_SECRET) || defined(HAVE_ED448) +#if defined(HAVE_ECC) || !defined(WOLFSSL_RSA_PUBLIC_ONLY) || \ + defined(WOLFSSL_PUBLIC_MP) || !defined(NO_DH) + +static const char* bench_desc_words[][9] = { + /* 0 1 2 3 4 5 6 7 8 */ + {"public", "private", "key gen", "agree" , "sign", "verify", "encryption", "decryption", NULL}, /* 0 English */ +#ifndef NO_MULTIBYTE_PRINT + {"公開鍵", "秘密鍵" ,"鍵生成" , "鍵共有" , "署名", "検証" , "暗号化" , "復号化" , NULL}, /* 1 Japanese */ +#endif +}; + +#endif +#endif + +#if defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM) && !defined(WOLFSSL_SGX) + #define HAVE_GET_CYCLES + static WC_INLINE word64 get_intel_cycles(void); + 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; + /* 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), " %s = %6.2f\n", \ + bench_result_words1[lng_index][2], \ + count == 0 ? 0 : (float)total_cycles / ((word64)count*s)) + #define SHOW_INTEL_CYCLES_CSV(b, n, s) \ + XSNPRINTF(b + XSTRLEN(b), n - XSTRLEN(b), "%.2f,\n", \ + count == 0 ? 0 : (float)total_cycles / ((word64)count*s)) +#elif defined(LINUX_CYCLE_COUNT) + #include + #include + #include + + 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; \ + atr.config = PERF_COUNT_HW_CPU_CYCLES; \ + cycles = (int)syscall(__NR_perf_event_open, &atr, 0, -1, -1, 0); \ + } while (0); + + #define BEGIN_INTEL_CYCLES read(cycles, &begin_cycles, sizeof(begin_cycles)); + #define END_INTEL_CYCLES do { \ + read(cycles, &total_cycles, sizeof(total_cycles)); \ + total_cycles = total_cycles - begin_cycles; \ + } while (0); + + /* 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), " %s = %6.2f\n", \ + bench_result_words1[lng_index][2], \ + (float)total_cycles / (count*s)) + #define SHOW_INTEL_CYCLES_CSV(b, n, s) \ + XSNPRINTF(b + XSTRLEN(b), n - XSTRLEN(b), "%.2f,\n", \ + (float)total_cycles / (count*s)) + +#elif defined(SYNERGY_CYCLE_COUNT) + #include "hal_data.h" + static THREAD_LS_T word64 begin_cycles; + static THREAD_LS_T word64 total_cycles; + + #define INIT_CYCLE_COUNTER + #define BEGIN_INTEL_CYCLES begin_cycles = DWT->CYCCNT = 0; + #define END_INTEL_CYCLES total_cycles = DWT->CYCCNT - begin_cycles; + + /* 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), " %s = %6.2f\n", \ + bench_result_words1[lng_index][2], \ + (float)total_cycles / (count*s)) + #define SHOW_INTEL_CYCLES_CSV(b, n, s) \ + XSNPRINTF(b + XSTRLEN(b), n - XSTRLEN(b), "%.2f,\n", \ + (float)total_cycles / (count*s)) + +#else + #define INIT_CYCLE_COUNTER + #define BEGIN_INTEL_CYCLES + #define END_INTEL_CYCLES + #define SHOW_INTEL_CYCLES(b, n, s) b[XSTRLEN(b)] = '\n' + #define SHOW_INTEL_CYCLES_CSV(b, n, s) b[XSTRLEN(b)] = '\n' +#endif + +/* determine benchmark buffer to use (if NO_FILESYSTEM) */ +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ + !defined(USE_CERT_BUFFERS_3072) + #define USE_CERT_BUFFERS_2048 /* default to 2048 */ +#endif + +#if defined(USE_CERT_BUFFERS_1024) || defined(USE_CERT_BUFFERS_2048) || \ + defined(USE_CERT_BUFFERS_3072) || !defined(NO_DH) + /* include test cert and key buffers for use with NO_FILESYSTEM */ + #include +#endif + +#if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) #include - void bench_blake2(void); #endif #ifdef _MSC_VER @@ -121,469 +695,2060 @@ #endif -void bench_des(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_sha256(void); -void bench_sha384(void); -void bench_sha512(void); -void bench_ripemd(void); - -void bench_rsa(void); -void bench_rsaKeyGen(void); -void bench_dh(void); -#ifdef HAVE_ECC -void bench_eccKeyGen(void); -void bench_eccKeyAgree(void); -#endif -#ifdef HAVE_CURVE25519 -void bench_curve25519KeyGen(void); -void bench_curve25519KeyAgree(void); -#endif -#ifdef HAVE_ED25519 -void bench_ed25519KeyGen(void); -void bench_ed25519KeySign(void); -#endif -#ifdef HAVE_NTRU -void bench_ntru(void); -void bench_ntruKeyGen(void); +#ifdef WOLFSSL_CURRTIME_REMAP + #define current_time WOLFSSL_CURRTIME_REMAP +#elif !defined(HAVE_STACK_SIZE) + double current_time(int); #endif -double current_time(int); - - -#ifdef HAVE_CAVIUM - -static int OpenNitroxDevice(int dma_mode,int dev_id) -{ - 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); - - return CspInitialize(dma_mode, dev_id); -} - +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && \ + !defined(HAVE_STACK_SIZE) +#ifdef __cplusplus + extern "C" { +#endif + WOLFSSL_API int wolfSSL_Debugging_ON(void); + WOLFSSL_API void wolfSSL_Debugging_OFF(void); +#ifdef __cplusplus + } /* extern "C" */ +#endif #endif -#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) +#if (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || !defined(NO_DH) \ + || defined(WOLFSSL_KEY_GEN) || defined(HAVE_ECC) \ + || defined(HAVE_CURVE25519) || defined(HAVE_ED25519) \ + || defined(HAVE_CURVE448) || defined(HAVE_ED448) #define HAVE_LOCAL_RNG - static RNG rng; + static THREAD_LS_T WC_RNG gRng; #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_CURVE448) || defined(HAVE_ED448) || \ + defined(HAVE_ECC) || defined(HAVE_NTRU) || !defined(NO_DH) || \ + !defined(NO_RSA) || defined(HAVE_SCRYPT) + #define BENCH_ASYM +#endif + +#if defined(BENCH_ASYM) +#if defined(HAVE_ECC) || !defined(WOLFSSL_RSA_PUBLIC_ONLY) || \ + defined(WOLFSSL_PUBLIC_MP) || !defined(NO_DH) +static const char* bench_result_words2[][5] = { + { "ops took", "sec" , "avg" , "ops/sec", NULL }, /* 0 English */ +#ifndef NO_MULTIBYTE_PRINT + { "回処理を", "秒で実施", "平均", "処理/秒", NULL }, /* 1 Japanese */ +#endif +}; +#endif +#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 WC_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 WC_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 WC_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 + static word32 aesAuthAddSz = AES_AUTH_ADD_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 { + scryptCnt = 1, + ntimes = 2, + genTimes = BENCH_MAX_PENDING, + agreeTimes = 2 + }; + static int numBlocks = 25; /* how many kB to test (en/de)cryption */ + static word32 bench_size = (1024ul); #else - static byte cipher[1024*1024]; + enum BenchmarkBounds { + scryptCnt = 10, + ntimes = 100, + genTimes = BENCH_MAX_PENDING, /* must be at least BENCH_MAX_PENDING */ + agreeTimes = 100 + }; + static int numBlocks = 5; /* how many megs to test (en/de)cryption */ + static word32 bench_size = (1024*1024ul); +#endif +static int base2 = 1; +static int digest_stream = 1; +#ifndef NO_RSA +/* Don't measure RSA sign/verify by default */ +static int rsa_sign_verify = 0; +#endif +#ifndef NO_DH +/* Use the FFDHE parameters */ +static int use_ffdhe = 0; #endif +/* Don't print out in CSV format by default */ +static int csv_format = 0; +#ifdef BENCH_ASYM +static int csv_header_count = 0; +#endif -static const XGEN_ALIGN byte key[] = +/* for compatibility */ +#define BENCH_SIZE bench_size + +/* 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, - 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67, + 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 }; +static THREAD_LS_T byte* bench_key = NULL; +static THREAD_LS_T byte* bench_iv = NULL; - -/* 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) -{ +#ifdef WOLFSSL_STATIC_MEMORY + #ifdef BENCH_EMBEDDED + static byte gBenchMemory[50000]; + #else + static byte gBenchMemory[400000]; + #endif #endif - #if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) - wolfSSL_Debugging_ON(); + +/* This code handles cases with systems where static (non cost) ram variables + aren't properly initialized with data */ +static int gBenchStaticInit = 0; +static void benchmark_static_init(void) +{ + if (gBenchStaticInit == 0) { + gBenchStaticInit = 1; + + /* Init static variables */ + bench_all = 1; + #ifdef BENCH_EMBEDDED + numBlocks = 25; /* how many kB to test (en/de)cryption */ + bench_size = (1024ul); + #else + numBlocks = 5; /* how many megs to test (en/de)cryption */ + bench_size = (1024*1024ul); #endif - - (void)plain; - (void)cipher; - (void)key; - (void)iv; - - #ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) { - printf("Cavium OpenNitroxDevice failed\n"); - exit(-1); + #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + aesAuthAddSz = AES_AUTH_ADD_SZ; + #endif + base2 = 1; + digest_stream = 1; } -#endif /* HAVE_CAVIUM */ +} + + + +/******************************************************************************/ +/* Begin Stats Functions */ +/******************************************************************************/ +static int gPrintStats = 0; +typedef enum bench_stat_type { + BENCH_STAT_ASYM, + BENCH_STAT_SYM, +} bench_stat_type_t; +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + 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; + const char* perftype; + } 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, const char* perftype, int ret) + { + bench_stats_t* bstat; + + /* protect bench_stats_head and bench_stats_tail access */ + pthread_mutex_lock(&bench_lock); + + /* locate existing in list */ + for (bstat = bench_stats_head; bstat != NULL; bstat = bstat->next) { + /* match based on algo, strength and desc */ + if (bstat->algo == algo && bstat->strength == strength && bstat->desc == desc && bstat->doAsync == doAsync) { + break; + } + } + + if (bstat == NULL) { + /* allocate new and put on list */ + bstat = (bench_stats_t*)XMALLOC(sizeof(bench_stats_t), NULL, DYNAMIC_TYPE_INFO); + if (bstat) { + XMEMSET(bstat, 0, sizeof(bench_stats_t)); + + /* add to list */ + bstat->next = NULL; + if (bench_stats_tail == NULL) { + bench_stats_head = bstat; + } + else { + bench_stats_tail->next = bstat; + bstat->prev = bench_stats_tail; + } + bench_stats_tail = bstat; /* add to the end either way */ + } + } + + if (bstat) { + bstat->type = type; + bstat->algo = algo; + bstat->strength = strength; + bstat->desc = desc; + bstat->doAsync = doAsync; + bstat->perfsec += perfsec; + bstat->finishCount++; + bstat->perftype = perftype; + if (bstat->lastRet > ret) + bstat->lastRet = ret; /* track last error */ + + pthread_mutex_unlock(&bench_lock); + + /* wait until remaining are complete */ + while (bstat->finishCount < g_threadCount) { + wc_AsyncThreadYield(); + } + } + else { + pthread_mutex_unlock(&bench_lock); + } + + return bstat; + } + + void bench_stats_print(void) + { + bench_stats_t* bstat; + + /* protect bench_stats_head and bench_stats_tail access */ + pthread_mutex_lock(&bench_lock); + + for (bstat = bench_stats_head; bstat != NULL; ) { + if (bstat->type == BENCH_STAT_SYM) { + printf("%-16s%s %8.3f %s/s\n", bstat->desc, + BENCH_ASYNC_GET_NAME(bstat->doAsync), bstat->perfsec, + base2 ? "MB" : "mB"); + } + else { + printf("%-5s %4d %-9s %s %.3f ops/sec\n", + bstat->algo, bstat->strength, bstat->desc, + BENCH_ASYNC_GET_NAME(bstat->doAsync), bstat->perfsec); + } + + bstat = bstat->next; + } + + pthread_mutex_unlock(&bench_lock); + } + +#else + + typedef struct bench_stats { + const char* algo; + const char* desc; + double perfsec; + const char* perftype; + int strength; + bench_stat_type_t type; + int ret; + } bench_stats_t; + #define MAX_BENCH_STATS 50 + static bench_stats_t gStats[MAX_BENCH_STATS]; + static int gStatsCount; + + static bench_stats_t* bench_stats_add(bench_stat_type_t type, + const char* algo, int strength, const char* desc, int doAsync, + double perfsec, const char* perftype, int ret) + { + bench_stats_t* bstat = NULL; + if (gStatsCount >= MAX_BENCH_STATS) + return bstat; + + bstat = &gStats[gStatsCount++]; + bstat->algo = algo; + bstat->desc = desc; + bstat->perfsec = perfsec; + bstat->perftype = perftype; + bstat->strength = strength; + bstat->type = type; + bstat->ret = ret; + + (void)doAsync; + + return bstat; + } + + void bench_stats_print(void) + { + int i; + bench_stats_t* bstat; + for (i=0; itype == BENCH_STAT_SYM) { + printf("%-16s %8.3f %s/s\n", bstat->desc, bstat->perfsec, + base2 ? "MB" : "mB"); + } + else { + printf("%-5s %4d %-9s %.3f ops/sec\n", + bstat->algo, bstat->strength, bstat->desc, bstat->perfsec); + } + } + } +#endif /* WOLFSSL_ASYNC_CRYPT && !WC_NO_ASYNC_THREADING */ + +static WC_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 + INIT_CYCLE_COUNTER +} + +static WC_INLINE void bench_stats_start(int* count, double* start) +{ + *count = 0; + *start = current_time(1); + BEGIN_INTEL_CYCLES +} + +static WC_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}; + const char** word = bench_result_words1[lng_index]; + + 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 > (1024ul * 1024ul)) { + blocks /= (1024ul * 1024ul); + 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 > (1000ul * 1000ul)) { + blocks /= (1000ul * 1000ul); + 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; + } + + /* format and print to terminal */ + if (csv_format == 1) { + XSNPRINTF(msg, sizeof(msg), "%s,%.3f,", desc, persec); + SHOW_INTEL_CYCLES_CSV(msg, sizeof(msg), countSz); + } else { + XSNPRINTF(msg, sizeof(msg), "%-16s%s %5.0f %s %s %5.3f %s, %8.3f %s/s", + desc, BENCH_ASYNC_GET_NAME(doAsync), blocks, blockType, word[0], total, word[1], + 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); + } + + /* Add to thread stats */ + bench_stats_add(BENCH_STAT_SYM, NULL, 0, desc, doAsync, persec, blockType, ret); + + (void)doAsync; + (void)ret; + + TEST_SLEEP(); +} + +#ifdef BENCH_ASYM +#if defined(HAVE_ECC) || !defined(WOLFSSL_RSA_PUBLIC_ONLY) || \ + defined(WOLFSSL_PUBLIC_MP) || !defined(NO_DH) +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; + const char **word = bench_result_words2[lng_index]; + const char* kOpsSec = "Ops/Sec"; + char msg[128] = {0}; + + total = current_time(0) - start; + if (count > 0) + each = total / count; /* per second */ + opsSec = count / total; /* ops second */ + milliEach = each * 1000; /* milliseconds */ + + /* format and print to terminal */ + if (csv_format == 1) { + /* only print out header once */ + if (csv_header_count == 1) { + printf("\nAsymmetric Ciphers:\n\n"); + printf("Algorithm,avg ms,ops/sec,\n"); + csv_header_count++; + } + XSNPRINTF(msg, sizeof(msg), "%s %d %s,%.3f,%.3f,\n", algo, strength, desc, milliEach, opsSec); + } else { + XSNPRINTF(msg, sizeof(msg), "%-6s %5d %-9s %s %6d %s %5.3f %s, %s %5.3f ms," + " %.3f %s\n", algo, strength, desc, BENCH_ASYNC_GET_NAME(doAsync), + count, word[0], total, word[1], word[2], milliEach, opsSec, word[3]); + } + printf("%s", msg); + + /* show errors */ + if (ret < 0) { + printf("Benchmark %s %s %d failed: %d\n", algo, desc, strength, ret); + } + + /* Add to thread stats */ + bench_stats_add(BENCH_STAT_ASYM, algo, strength, desc, doAsync, opsSec, kOpsSec, ret); + + (void)doAsync; + (void)ret; + + TEST_SLEEP(); +} +#endif +#endif /* BENCH_ASYM */ + +static WC_INLINE void bench_stats_free(void) +{ +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + bench_stats_t* bstat; + for (bstat = bench_stats_head; bstat != NULL; ) { + bench_stats_t* next = bstat->next; + XFREE(bstat, NULL, DYNAMIC_TYPE_INFO); + bstat = 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 +#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 */ + + (void)args; + +#ifdef WOLFSSL_ASYNC_CRYPT + if (wolfEventQueue_Init(&eventQueue) != 0) { + printf("Async event queue init failure!\n"); + } +#endif + +#ifdef WOLF_CRYPTO_CB +#ifdef HAVE_INTEL_QA_SYNC + devId = wc_CryptoCb_InitIntelQa(); + if (devId == INVALID_DEVID) { + printf("Couldn't init the Intel QA\n"); + } +#endif +#ifdef HAVE_CAVIUM_OCTEON_SYNC + devId = wc_CryptoCb_InitOcteon(); + if (devId == INVALID_DEVID) { + printf("Couldn't get the Octeon device ID\n"); + } +#endif +#endif #if defined(HAVE_LOCAL_RNG) { - int rngRet = wc_InitRng(&rng); + int rngRet; + +#ifndef HAVE_FIPS + rngRet = wc_InitRng_ex(&gRng, HEAP_HINT, devId); +#else + rngRet = wc_InitRng(&gRng); +#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); + +#ifdef WOLFSSL_AFALG_XILINX_AES + bench_plain = (byte*)aligned_alloc(64, (size_t)bench_buf_size + 16); + bench_cipher = (byte*)aligned_alloc(64, (size_t)bench_buf_size + 16); +#else + bench_plain = (byte*)XMALLOC((size_t)bench_buf_size + 16, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + bench_cipher = (byte*)XMALLOC((size_t)bench_buf_size + 16, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); +#endif + 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); + +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(HAVE_INTEL_QA_SYNC) + 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 + if (bench_all || (bench_other_algs & BENCH_RNG)) + bench_rng(); +#endif /* WC_NO_RNG */ #ifndef NO_AES - bench_aes(0); - bench_aes(1); +#ifdef HAVE_AES_CBC + 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_3DES)) || \ + defined(HAVE_INTEL_QA_SYNC) || defined(HAVE_CAVIUM_OCTEON_SYNC)) && \ + !defined(NO_HW_BENCH) + 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_3DES)) || \ + defined(HAVE_INTEL_QA_SYNC) || defined(HAVE_CAVIUM_OCTEON_SYNC)) && \ + !defined(NO_HW_BENCH) + 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) && \ + !defined(NO_HW_BENCH) + bench_aesecb(1); + #endif + } +#endif +#ifdef WOLFSSL_AES_XTS + if (bench_all || (bench_cipher_algs & BENCH_AES_XTS)) + bench_aesxts(); +#endif +#ifdef WOLFSSL_AES_CFB + if (bench_all || (bench_cipher_algs & BENCH_AES_CFB)) + bench_aescfb(); +#endif +#ifdef WOLFSSL_AES_OFB + if (bench_all || (bench_cipher_algs & BENCH_AES_OFB)) + bench_aesofb(); #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) && \ + !defined(NO_HW_BENCH) + 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)) || \ + defined(HAVE_INTEL_QA_SYNC) || defined(HAVE_CAVIUM_OCTEON_SYNC)) && \ + !defined(NO_HW_BENCH) + bench_des(1); + #endif + } +#endif +#ifdef HAVE_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) && \ + !defined(NO_HW_BENCH) + 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) && \ + !defined(NO_HW_BENCH) + bench_sha(1); + #endif + } +#endif +#ifdef WOLFSSL_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) && \ + !defined(NO_HW_BENCH) + 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) && \ + !defined(NO_HW_BENCH) + 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) && \ + !defined(NO_HW_BENCH) + 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) && \ + !defined(NO_HW_BENCH) + 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) && \ + !defined(NO_HW_BENCH) + 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) && \ + !defined(NO_HW_BENCH) + 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) && \ + !defined(NO_HW_BENCH) + 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_SHA3) && \ + !defined(NO_HW_BENCH) + 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_BLAKE2B)) + bench_blake2b(); +#endif +#ifdef HAVE_BLAKE2S + if (bench_all || (bench_digest_algs & BENCH_BLAKE2S)) + bench_blake2s(); +#endif +#ifdef WOLFSSL_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) && \ + defined(WC_ASYNC_ENABLE_MD5) && !defined(NO_HW_BENCH) + 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_HMAC) && \ + defined(WC_ASYNC_ENABLE_SHA) && !defined(NO_HW_BENCH) + 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_HMAC) && \ + defined(WC_ASYNC_ENABLE_SHA224) && !defined(NO_HW_BENCH) + 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_HMAC) && \ + defined(WC_ASYNC_ENABLE_SHA256) && !defined(NO_HW_BENCH) + 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_HMAC) && \ + defined(WC_ASYNC_ENABLE_SHA384) && !defined(NO_HW_BENCH) + 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_HMAC) && \ + defined(WC_ASYNC_ENABLE_SHA512) && !defined(NO_HW_BENCH) + bench_hmac_sha512(1); + #endif + } + #endif + #ifndef NO_PWDBASED + if (bench_all || (bench_mac_algs & BENCH_PBKDF2)) { + bench_pbkdf2(); + } + #endif +#endif /* NO_HMAC */ + +#ifdef HAVE_SCRYPT + if (bench_all || (bench_other_algs & BENCH_SCRYPT)) + bench_scrypt(); +#endif #ifndef NO_RSA - bench_rsa(); -#endif + #ifdef WOLFSSL_KEY_GEN + if (bench_all || (bench_asym_algs & BENCH_RSA_KEYGEN)) { + #ifndef NO_SW_BENCH + if (bench_asym_algs & BENCH_RSA_SZ) { + bench_rsaKeyGen_size(0, bench_size); + } + else { + bench_rsaKeyGen(0); + } + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA_KEYGEN) \ + && !defined(NO_HW_BENCH) + if (bench_asym_algs & BENCH_RSA_SZ) { + bench_rsaKeyGen_size(1, bench_size); + } + else { + bench_rsaKeyGen(1); + } + #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) && \ + !defined(NO_HW_BENCH) + bench_rsa(1); + #endif + } -#ifdef HAVE_NTRU - bench_ntru(); + #ifdef WOLFSSL_KEY_GEN + if (bench_asym_algs & BENCH_RSA_SZ) { + #ifndef NO_SW_BENCH + bench_rsa_key(0, bench_size); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + !defined(NO_HW_BENCH) + bench_rsa_key(1, bench_size); + #endif + } + #endif #endif #ifndef NO_DH - bench_dh(); -#endif - -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) - bench_rsaKeyGen(); + 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) && \ + !defined(NO_HW_BENCH) + bench_dh(1); + #endif + } #endif #ifdef HAVE_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 defined(FP_ECC) - wc_ecc_fp_free(); + 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) && \ + !defined(NO_HW_BENCH) + bench_eccMakeKey(1); + #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) && \ + !defined(NO_HW_BENCH) + bench_ecc(1); + #endif + } + #ifdef HAVE_ECC_ENCRYPT + if (bench_all || (bench_asym_algs & BENCH_ECC_ENCRYPT)) + bench_eccEncrypt(); #endif #endif #ifdef HAVE_CURVE25519 - bench_curve25519KeyGen(); - bench_curve25519KeyAgree(); + 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 + +#ifdef HAVE_CURVE448 + if (bench_all || (bench_asym_algs & BENCH_CURVE448_KEYGEN)) + bench_curve448KeyGen(); + #ifdef HAVE_CURVE448_SHARED_SECRET + if (bench_all || (bench_asym_algs & BENCH_CURVE448_KA)) + bench_curve448KeyAgree(); + #endif +#endif + +#ifdef HAVE_ED448 + if (bench_all || (bench_asym_algs & BENCH_ED448_KEYGEN)) + bench_ed448KeyGen(); + if (bench_all || (bench_asym_algs & BENCH_ED448_SIGN)) + bench_ed448KeySign(); +#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 WOLF_CRYPTO_CB +#ifdef HAVE_INTEL_QA_SYNC + wc_CryptoCb_CleanupIntelQa(&devId); +#endif +#ifdef HAVE_CAVIUM_OCTEON_SYNC + wc_CryptoCb_CleanupOcteon(&devId); +#endif +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + /* free event queue */ + wolfEventQueue_Free(&eventQueue); #endif #if defined(HAVE_LOCAL_RNG) - wc_FreeRng(&rng); + wc_FreeRng(&gRng); #endif - return 0; +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + +/* cleanup the thread if fixed point cache is enabled and have thread local */ +#if defined(HAVE_THREAD_LS) && defined(HAVE_ECC) && defined(FP_ECC) + wc_ecc_fp_free(); +#endif + + (void)bench_cipher_algs; + (void)bench_digest_algs; + (void)bench_mac_algs; + (void)bench_asym_algs; + (void)bench_other_algs; + + return NULL; +} + +int benchmark_init(void) +{ + int ret = 0; + + benchmark_static_init(); + +#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 + + if (csv_format == 1) { + printf("wolfCrypt Benchmark (block bytes %d, min %.1f sec each)\n", + (int)BENCH_SIZE, BENCH_MIN_RUNTIME_SEC); + printf("This format allows you to easily copy the output to a csv file."); + printf("\n\nSymmetric Ciphers:\n\n"); + printf("Algorithm,MB/s,Cycles per byte,\n"); + } else { + printf("wolfCrypt Benchmark (block bytes %d, min %.1f sec each)\n", + (int)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 + + if (gPrintStats || devId != INVALID_DEVID) { + bench_stats_print(); + } + + 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; + + printf("------------------------------------------------------------------------------\n"); + printf(" wolfSSL version %s\n", LIBWOLFSSL_VERSION_STRING); + printf("------------------------------------------------------------------------------\n"); + + ret = benchmark_init(); + if (ret != 0) + EXIT_TEST(ret); + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) +{ + int i; + + if (g_threadCount == 0) { + #ifdef WC_ASYNC_BENCH_THREAD_COUNT + g_threadCount = WC_ASYNC_BENCH_THREAD_COUNT; + #else + g_threadCount = wc_AsyncGetNumberOfCpus(); + #endif + } + + printf("CPUs: %d\n", g_threadCount); + + g_threadData = (ThreadData*)XMALLOC(sizeof(ThreadData) * g_threadCount, + HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (g_threadData == NULL) { + printf("Thread data alloc failed!\n"); + EXIT_TEST(EXIT_FAILURE); + } + + /* Create threads */ + for (i = 0; i < g_threadCount; 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 < g_threadCount; i++) { + wc_AsyncThreadJoin(&g_threadData[i].thread_id); + } + + XFREE(g_threadData, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +} +#else + benchmarks_do(NULL); +#endif + + printf("Benchmark complete\n"); + + ret = benchmark_free(); + + EXIT_TEST(ret); } -#ifdef BENCH_EMBEDDED -enum BenchmarkBounds { - numBlocks = 25, /* how many kB to test (en/de)cryption */ - ntimes = 1, - genTimes = 5, /* public key iterations */ - agreeTimes = 5 -}; -static const char blockType[] = "kB"; /* used in printf output */ +#ifndef WC_NO_RNG +void bench_rng(void) +{ + int ret, i, count; + double start; + long pos, len, remain; + WC_RNG myrng; + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&myrng, HEAP_HINT, devId); #else -enum BenchmarkBounds { - numBlocks = 50, /* how many megs to test (en/de)cryption */ - ntimes = 100, - genTimes = 100, - agreeTimes = 100 -}; -static const char blockType[] = "megs"; /* used in printf output */ + ret = wc_InitRng(&myrng); #endif + if (ret < 0) { + printf("InitRNG failed %d\n", ret); + return; + } + + 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; + + 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); + + wc_FreeRng(&myrng); +} +#endif /* WC_NO_RNG */ #ifndef NO_AES -void bench_aes(int show) +#ifdef HAVE_AES_CBC +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 HAVE_CAVIUM - if (wc_AesInitCavium(&enc, CAVIUM_DEV_ID) != 0) { - printf("aes init cavium failed\n"); - 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; + } + } + + 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; + } + +#ifdef HAVE_AES_DECRYPT + /* 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; + } + } + + 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_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); + +#endif /* HAVE_AES_DECRYPT */ + + (void)decLabel; +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_AesFree(&enc[i]); + } +} + +void bench_aescbc(int doAsync) +{ +#ifdef WOLFSSL_AES_128 + bench_aescbc_internal(doAsync, bench_key, 16, bench_iv, + "AES-128-CBC-enc", "AES-128-CBC-dec"); +#endif +#ifdef WOLFSSL_AES_192 + bench_aescbc_internal(doAsync, bench_key, 24, bench_iv, + "AES-192-CBC-enc", "AES-192-CBC-dec"); +#endif +#ifdef WOLFSSL_AES_256 + bench_aescbc_internal(doAsync, bench_key, 32, bench_iv, + "AES-256-CBC-enc", "AES-256-CBC-dec"); +#endif +} + +#endif /* HAVE_AES_CBC */ + +#ifdef HAVE_AESGCM +static void bench_aesgcm_internal(int doAsync, const byte* key, word32 keySz, + const byte* iv, word32 ivSz, + const char* encLabel, const char* decLabel) +{ + int ret = 0, i, count = 0, times, pending = 0; + Aes enc[BENCH_MAX_PENDING]; +#ifdef HAVE_AES_DECRYPT + Aes dec[BENCH_MAX_PENDING]; +#endif + double start; + + DECLARE_VAR(bench_additional, byte, AES_AUTH_ADD_SZ, HEAP_HINT); + DECLARE_VAR(bench_tag, byte, AES_AUTH_TAG_SZ, HEAP_HINT); + + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); +#ifdef HAVE_AES_DECRYPT + XMEMSET(dec, 0, sizeof(dec)); +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + if (bench_additional) +#endif + XMEMSET(bench_additional, 0, AES_AUTH_ADD_SZ); +#ifdef WOLFSSL_ASYNC_CRYPT + if (bench_tag) +#endif + XMEMSET(bench_tag, 0, AES_AUTH_TAG_SZ); + + /* 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, aesAuthAddSz); + 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); + +#ifdef HAVE_AES_DECRYPT + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_AesInit(&dec[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("AesInit failed, ret = %d\n", ret); + goto exit; + } + + ret = wc_AesGcmSetKey(&dec[i], key, keySz); + if (ret != 0) { + printf("AesGcmSetKey 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(&dec[i]), 0, ×, numBlocks, &pending)) { + ret = wc_AesGcmDecrypt(&dec[i], bench_plain, + bench_cipher, BENCH_SIZE, + iv, ivSz, bench_tag, AES_AUTH_TAG_SZ, + bench_additional, aesAuthAddSz); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&dec[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); +#endif /* HAVE_AES_DECRYPT */ + + (void)decLabel; + +exit: + + if (ret < 0) { + printf("bench_aesgcm failed: %d\n", ret); + } +#ifdef HAVE_AES_DECRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_AesFree(&dec[i]); } #endif + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_AesFree(&enc[i]); + } - ret = wc_AesSetKey(&enc, key, 16, iv, AES_ENCRYPTION); + FREE_VAR(bench_additional, HEAP_HINT); + FREE_VAR(bench_tag, HEAP_HINT); +} + +void bench_aesgcm(int doAsync) +{ +#if defined(WOLFSSL_AES_128) && !defined(WOLFSSL_AFALG_XILINX_AES) + bench_aesgcm_internal(doAsync, bench_key, 16, bench_iv, 12, + "AES-128-GCM-enc", "AES-128-GCM-dec"); +#endif +#if defined(WOLFSSL_AES_192) && !defined(WOLFSSL_AFALG_XILINX_AES) + bench_aesgcm_internal(doAsync, bench_key, 24, bench_iv, 12, + "AES-192-GCM-enc", "AES-192-GCM-dec"); +#endif +#ifdef WOLFSSL_AES_256 + bench_aesgcm_internal(doAsync, bench_key, 32, bench_iv, 12, + "AES-256-GCM-enc", "AES-256-GCM-dec"); +#endif +} +#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) +{ +#ifdef WOLFSSL_AES_128 + bench_aesecb_internal(doAsync, bench_key, 16, + "AES-128-ECB-enc", "AES-128-ECB-dec"); +#endif +#ifdef WOLFSSL_AES_192 + bench_aesecb_internal(doAsync, bench_key, 24, + "AES-192-ECB-enc", "AES-192-ECB-dec"); +#endif +#ifdef WOLFSSL_AES_256 + bench_aesecb_internal(doAsync, bench_key, 32, + "AES-256-ECB-enc", "AES-256-ECB-dec"); +#endif +} +#endif /* WOLFSSL_AES_DIRECT */ + +#ifdef WOLFSSL_AES_CFB +static void bench_aescfb_internal(const byte* key, word32 keySz, const byte* iv, + const char* label) +{ + Aes enc; + double start; + int i, ret, count; + + ret = wc_AesSetKey(&enc, key, keySz, iv, AES_ENCRYPTION); if (ret != 0) { printf("AesSetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_AesCbcEncrypt(&enc, plain, cipher, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + if((ret = wc_AesCfbEncrypt(&enc, bench_plain, bench_cipher, + BENCH_SIZE)) != 0) { + printf("wc_AesCfbEncrypt 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; +void bench_aescfb(void) +{ +#ifdef WOLFSSL_AES_128 + bench_aescfb_internal(bench_key, 16, bench_iv, "AES-128-CFB"); #endif - - if (show) { - printf("AES %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); - } -#ifdef HAVE_CAVIUM - wc_AesFreeCavium(&enc); +#ifdef WOLFSSL_AES_192 + bench_aescfb_internal(bench_key, 24, bench_iv, "AES-192-CFB"); +#endif +#ifdef WOLFSSL_AES_256 + bench_aescfb_internal(bench_key, 32, bench_iv, "AES-256-CFB"); #endif } -#endif +#endif /* WOLFSSL_AES_CFB */ -#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) - static byte additional[13]; - static byte tag[16]; -#endif - - -#ifdef HAVE_AESGCM -void bench_aesgcm(void) +#ifdef WOLFSSL_AES_OFB +static void bench_aesofb_internal(const byte* key, word32 keySz, const byte* iv, + const char* label) { Aes enc; - double start, total, persec; - int i; + double start; + int i, ret, count; - wc_AesGcmSetKey(&enc, key, 16); - start = current_time(1); - BEGIN_INTEL_CYCLES + ret = wc_AesSetKey(&enc, key, keySz, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("AesSetKey failed, ret = %d\n", ret); + return; + } - 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; -#endif - - printf("AES-GCM %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++) { + if((ret = wc_AesOfbEncrypt(&enc, bench_plain, bench_cipher, + BENCH_SIZE)) != 0) { + printf("wc_AesCfbEncrypt 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); } + +void bench_aesofb(void) +{ +#ifdef WOLFSSL_AES_128 + bench_aesofb_internal(bench_key, 16, bench_iv, "AES-128-OFB"); #endif +#ifdef WOLFSSL_AES_192 + bench_aesofb_internal(bench_key, 24, bench_iv, "AES-192-OFB"); +#endif +#ifdef WOLFSSL_AES_256 + bench_aesofb_internal(bench_key, 32, bench_iv, "AES-256-OFB"); +#endif +} +#endif /* WOLFSSL_AES_CFB */ + + +#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 = 0; - 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)); - - 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"); + 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); } -#endif +void bench_aesctr(void) +{ +#ifdef WOLFSSL_AES_128 + bench_aesctr_internal(bench_key, 16, bench_iv, "AES-128-CTR"); +#endif +#ifdef WOLFSSL_AES_192 + bench_aesctr_internal(bench_key, 24, bench_iv, "AES-192-CTR"); +#endif +#ifdef WOLFSSL_AES_256 + bench_aesctr_internal(bench_key, 32, bench_iv, "AES-256-CTR"); +#endif +} +#endif /* WOLFSSL_AES_COUNTER */ #ifdef HAVE_AESCCM void bench_aesccm(void) { Aes enc; - double start, total, persec; - int i; + double start; + int ret, i, count; - wc_AesCcmSetKey(&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_AesCcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12, - tag, 16, additional, 13); + XMEMSET(bench_tag, 0, AES_AUTH_TAG_SZ); + XMEMSET(bench_additional, 0, AES_AUTH_ADD_SZ); - END_INTEL_CYCLES - total = current_time(0) - start; + if ((ret = wc_AesCcmSetKey(&enc, bench_key, 16)) != 0) { + printf("wc_AesCcmSetKey failed, ret = %d\n", ret); + return; + } - 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 (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, aesAuthAddSz); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("AES-CCM-Enc", 0, count, bench_size, start, ret); - printf("AES-CCM %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_AesCcmDecrypt(&enc, bench_plain, bench_cipher, BENCH_SIZE, + bench_iv, 12, bench_tag, AES_AUTH_TAG_SZ, + bench_additional, aesAuthAddSz); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("AES-CCM-Dec", 0, count, bench_size, start, ret); + + + FREE_VAR(bench_additional, HEAP_HINT); + FREE_VAR(bench_tag, HEAP_HINT); } -#endif +#endif /* HAVE_AESCCM */ +#endif /* !NO_AES */ #ifdef HAVE_POLY1305 -void bench_poly1305() +void bench_poly1305(void) { - Poly1305 enc; - byte mac[16]; - double start, total, persec; - int i; - int ret; + Poly1305 enc; + byte mac[16]; + double start; + int ret = 0, i, count; + if (digest_stream) { + ret = wc_Poly1305SetKey(&enc, bench_key, 32); + if (ret != 0) { + printf("Poly1305SetKey failed, ret = %d\n", ret); + return; + } - ret = wc_Poly1305SetKey(&enc, key, 32); - if (ret != 0) { - printf("Poly1305SetKey failed, ret = %d\n", ret); - return; + 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); + } + else { + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_Poly1305SetKey(&enc, bench_key, 32); + if (ret != 0) { + printf("Poly1305SetKey failed, ret = %d\n", ret); + return; + } + 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); } - 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"); } #endif /* HAVE_POLY1305 */ @@ -592,143 +2757,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 HAVE_CAVIUM - if (wc_Des3_InitCavium(&enc, CAVIUM_DEV_ID) != 0) - printf("des3 init cavium failed\n"); -#endif - ret = wc_Des3_SetKey(&enc, key, iv, DES_ENCRYPTION); + /* 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; + } + } + + 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_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); + +exit: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Des3Free(&enc[i]); + } +} +#endif /* !NO_DES3 */ + + +#ifdef HAVE_IDEA +void bench_idea(void) +{ + Idea enc; + double start; + int ret = 0, i, count; + + 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_Des3_CbcEncrypt(&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("3DES %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); -#ifdef HAVE_CAVIUM - wc_Des3_FreeCavium(&enc); -#endif + 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 +#endif /* HAVE_IDEA */ #ifndef NO_RC4 -void bench_arc4(void) +void bench_arc4(int doAsync) { - Arc4 enc; - double start, total, persec; - int i; - -#ifdef HAVE_CAVIUM - if (wc_Arc4InitCavium(&enc, CAVIUM_DEV_ID) != 0) - printf("arc4 init cavium failed\n"); -#endif + int ret = 0, i, count = 0, times, pending = 0; + Arc4 enc[BENCH_MAX_PENDING]; + double start; - wc_Arc4SetKey(&enc, key, 16); - start = current_time(1); - BEGIN_INTEL_CYCLES + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); - for(i = 0; i < numBlocks; i++) - wc_Arc4Process(&enc, cipher, plain, sizeof(plain)); + /* 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; + } - 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 + ret = wc_Arc4SetKey(&enc[i], bench_key, 16); + if (ret != 0) { + printf("Arc4SetKey failed, ret = %d\n", ret); + goto exit; + } + } - printf("ARC4 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); -#ifdef HAVE_CAVIUM - wc_Arc4FreeCavium(&enc); -#endif + 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_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; - - wc_Hc128_SetKey(&enc, key, iv); - start = current_time(1); - BEGIN_INTEL_CYCLES + double start; + int i, count; - for(i = 0; i < numBlocks; i++) - wc_Hc128_Process(&enc, cipher, plain, sizeof(plain)); + wc_Hc128_SetKey(&enc, bench_key, bench_iv); - 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 */ @@ -736,29 +2943,20 @@ void bench_hc128(void) #ifndef NO_RABBIT void bench_rabbit(void) { - Rabbit enc; - double start, total, persec; - int i; - - wc_RabbitSetKey(&enc, key, iv); - start = current_time(1); - BEGIN_INTEL_CYCLES + Rabbit enc; + double start; + int i, count; - for(i = 0; i < numBlocks; i++) - wc_RabbitProcess(&enc, cipher, plain, sizeof(plain)); + wc_RabbitSetKey(&enc, bench_key, bench_iv); - 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 */ @@ -767,356 +2965,1391 @@ 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 ) ) +#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)); - - wc_Md5Final(&hash, digest); + if (digest_stream) { + /* 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 + } - 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; + 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_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)); + } + else { + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks; times++) { + ret = wc_InitMd5_ex(hash, HEAP_HINT, INVALID_DEVID); + ret |= wc_Md5Update(hash, bench_plain, BENCH_SIZE); + ret |= wc_Md5Final(hash, digest[0]); + if (ret != 0) + goto exit_md5; + } /* for times */ + count += times; + } 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; - - ret = wc_InitSha(&hash); - if (ret != 0) { - printf("InitSha failed, ret = %d\n", ret); - return; + 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); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + if (digest_stream) { + /* 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 + } + + 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_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; + + 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_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)); } - start = current_time(1); - BEGIN_INTEL_CYCLES - - for(i = 0; i < numBlocks; i++) - wc_ShaUpdate(&hash, plain, sizeof(plain)); - - wc_ShaFinal(&hash, digest); + else { + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks; times++) { + ret = wc_InitSha_ex(hash, HEAP_HINT, INVALID_DEVID); + ret |= wc_ShaUpdate(hash, bench_plain, BENCH_SIZE); + ret |= wc_ShaFinal(hash, digest[0]); + if (ret != 0) + goto exit_sha; + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); + } +exit_sha: + bench_stats_sym_finish("SHA", doAsync, 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 +exit: - 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++) { + wc_ShaFree(&hash[i]); + } + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); } #endif /* NO_SHA */ -#ifndef NO_SHA256 -void bench_sha256(void) +#ifdef WOLFSSL_SHA224 +void bench_sha224(int doAsync) { - Sha256 hash; - byte digest[SHA256_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + wc_Sha224 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_SHA224_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)); - if (ret != 0) { - printf("Sha256Update failed, ret = %d\n", ret); - return; + if (digest_stream) { + /* 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("InitSha224_ex 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_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)); + } + else { + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks; times++) { + ret = wc_InitSha224_ex(hash, HEAP_HINT, INVALID_DEVID); + ret |= wc_Sha224Update(hash, bench_plain, BENCH_SIZE); + ret |= wc_Sha224Final(hash, digest[0]); + if (ret != 0) + goto exit_sha224; + } /* for times */ + count += times; + } 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]); } - ret = wc_Sha256Final(&hash, digest); - if (ret != 0) { - printf("Sha256Final 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; + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); +} #endif - printf("SHA-256 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); +#ifndef NO_SHA256 +void bench_sha256(int doAsync) +{ + 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); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + if (digest_stream) { + /* 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("InitSha256_ex failed, ret = %d\n", ret); + goto exit; + } + #ifdef WOLFSSL_PIC32MZ_HASH + wc_Sha256SizeSet(&hash[i], numBlocks * BENCH_SIZE); + #endif + } + + 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)); + } + else { + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks; times++) { + ret = wc_InitSha256_ex(hash, HEAP_HINT, INVALID_DEVID); + ret |= wc_Sha256Update(hash, bench_plain, BENCH_SIZE); + ret |= wc_Sha256Final(hash, digest[0]); + if (ret != 0) + goto exit_sha256; + } /* for times */ + count += times; + } 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]); + } + + 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)); - if (ret != 0) { - printf("Sha384Update failed, ret = %d\n", ret); - return; + if (digest_stream) { + /* 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("InitSha384_ex 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_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)); + } + else { + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks; times++) { + ret = wc_InitSha384_ex(hash, HEAP_HINT, INVALID_DEVID); + ret |= wc_Sha384Update(hash, bench_plain, BENCH_SIZE); + ret |= wc_Sha384Final(hash, digest[0]); + if (ret != 0) + goto exit_sha384; + } /* for times */ + count += times; + } 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]); } - ret = wc_Sha384Final(&hash, digest); - if (ret != 0) { - printf("Sha384Final 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("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; - - ret = wc_InitSha512(&hash); - if (ret != 0) { - printf("InitSha512 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES - - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha512Update(&hash, plain, sizeof(plain)); - if (ret != 0) { - printf("Sha512Update failed, ret = %d\n", ret); - return; + 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); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + if (digest_stream) { + /* 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("InitSha512_ex 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_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)); + } + else { + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks; times++) { + ret = wc_InitSha512_ex(hash, HEAP_HINT, INVALID_DEVID); + ret |= wc_Sha512Update(hash, bench_plain, BENCH_SIZE); + ret |= wc_Sha512Final(hash, digest[0]); + if (ret != 0) + goto exit_sha512; + } /* for times */ + count += times; + } 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]); } - ret = wc_Sha512Final(&hash, digest); - if (ret != 0) { - printf("Sha512Final 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("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) +{ + wc_Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_SHA3_224_DIGEST_SIZE, HEAP_HINT); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + if (digest_stream) { + /* 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)); + } + else { + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks; times++) { + ret = wc_InitSha3_224(hash, HEAP_HINT, INVALID_DEVID); + ret |= wc_Sha3_224_Update(hash, bench_plain, BENCH_SIZE); + ret |= wc_Sha3_224_Final(hash, digest[0]); + if (ret != 0) + goto exit_sha3_224; + } /* for times */ + count += times; + } 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) +{ + wc_Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_SHA3_256_DIGEST_SIZE, HEAP_HINT); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + if (digest_stream) { + /* 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)); + } + else { + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks; times++) { + ret = wc_InitSha3_256(hash, HEAP_HINT, INVALID_DEVID); + ret |= wc_Sha3_256_Update(hash, bench_plain, BENCH_SIZE); + ret |= wc_Sha3_256_Final(hash, digest[0]); + if (ret != 0) + goto exit_sha3_256; + } /* for times */ + count += times; + } 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) +{ + wc_Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_SHA3_384_DIGEST_SIZE, HEAP_HINT); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + if (digest_stream) { + /* 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)); + } + else { + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks; times++) { + ret = wc_InitSha3_384(hash, HEAP_HINT, INVALID_DEVID); + ret |= wc_Sha3_384_Update(hash, bench_plain, BENCH_SIZE); + ret |= wc_Sha3_384_Final(hash, digest[0]); + if (ret != 0) + goto exit_sha3_384; + } /* for times */ + count += times; + } 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) +{ + wc_Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_SHA3_512_DIGEST_SIZE, HEAP_HINT); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + if (digest_stream) { + /* 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)); + } + else { + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks; times++) { + ret = wc_InitSha3_512(hash, HEAP_HINT, INVALID_DEVID); + ret |= wc_Sha3_512_Update(hash, bench_plain, BENCH_SIZE); + ret |= wc_Sha3_512_Final(hash, digest[0]); + if (ret != 0) + goto exit_sha3_512; + } /* for times */ + count += times; + } 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; - - wc_InitRipeMd(&hash); - start = current_time(1); - BEGIN_INTEL_CYCLES - - for(i = 0; i < numBlocks; i++) - wc_RipeMdUpdate(&hash, plain, sizeof(plain)); - - wc_RipeMdFinal(&hash, digest); + double start; + int i, count, ret = 0; - 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 (digest_stream) { + ret = wc_InitRipeMd(&hash); + if (ret != 0) { + return ret; + } - printf("RIPEMD %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_RipeMdUpdate(&hash, bench_plain, BENCH_SIZE); + if (ret != 0) { + return ret; + } + } + ret = wc_RipeMdFinal(&hash, digest); + if (ret != 0) { + return ret; + } + + count += i; + } while (bench_stats_sym_check(start)); + } + else { + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_InitRipeMd(&hash); + if (ret != 0) { + return ret; + } + ret = wc_RipeMdUpdate(&hash, bench_plain, BENCH_SIZE); + if (ret != 0) { + return ret; + } + ret = wc_RipeMdFinal(&hash, digest); + if (ret != 0) { + return ret; + } + } + count += i; + } while (bench_stats_sym_check(start)); + } + bench_stats_sym_finish("RIPEMD", 0, count, bench_size, start, ret); + + return 0; } #endif #ifdef HAVE_BLAKE2 -void bench_blake2(void) +void bench_blake2b(void) { Blake2b b2b; byte digest[64]; - double start, total, persec; - int i, ret; - - 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)); + double start; + int ret = 0, i, count; + + if (digest_stream) { + ret = wc_InitBlake2b(&b2b, 64); if (ret != 0) { - printf("Blake2bUpdate failed, ret = %d\n", ret); + printf("InitBlake2b 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; + 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("Blake2bFinal failed, ret = %d\n", ret); + return; + } + count += i; + } while (bench_stats_sym_check(start)); + } + else { + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_InitBlake2b(&b2b, 64); + if (ret != 0) { + printf("InitBlake2b failed, ret = %d\n", ret); + return; + } + 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("Blake2bFinal failed, ret = %d\n", ret); + return; + } + } + count += i; + } while (bench_stats_sym_check(start)); + } + bench_stats_sym_finish("BLAKE2b", 0, count, bench_size, start, ret); +} #endif - printf("BLAKE2b %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); +#if defined(HAVE_BLAKE2S) +void bench_blake2s(void) +{ + Blake2s b2s; + byte digest[32]; + double start; + int ret = 0, i, count; + + if (digest_stream) { + ret = wc_InitBlake2s(&b2s, 32); + if (ret != 0) { + printf("InitBlake2s failed, ret = %d\n", ret); + return; + } + + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_Blake2sUpdate(&b2s, bench_plain, BENCH_SIZE); + if (ret != 0) { + printf("Blake2sUpdate failed, ret = %d\n", ret); + return; + } + } + ret = wc_Blake2sFinal(&b2s, digest, 32); + if (ret != 0) { + printf("Blake2sFinal failed, ret = %d\n", ret); + return; + } + count += i; + } while (bench_stats_sym_check(start)); + } + else { + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_InitBlake2s(&b2s, 32); + if (ret != 0) { + printf("InitBlake2b failed, ret = %d\n", ret); + return; + } + ret = wc_Blake2sUpdate(&b2s, bench_plain, BENCH_SIZE); + if (ret != 0) { + printf("Blake2bUpdate failed, ret = %d\n", ret); + return; + } + ret = wc_Blake2sFinal(&b2s, digest, 32); + if (ret != 0) { + printf("Blake2sFinal failed, ret = %d\n", ret); + return; + } + } + count += i; + } while (bench_stats_sym_check(start)); + } + bench_stats_sym_finish("BLAKE2s", 0, count, bench_size, start, ret); } #endif +#ifdef WOLFSSL_CMAC + +static void bench_cmac_helper(int keySz, const char* outMsg) +{ + Cmac cmac; + byte digest[AES_BLOCK_SIZE]; + word32 digestSz = sizeof(digest); + double start; + int ret, i, count; + + bench_stats_start(&count, &start); + do { + ret = wc_InitCmac(&cmac, bench_key, keySz, WC_CMAC_AES, NULL); + if (ret != 0) { + printf("InitCmac failed, ret = %d\n", ret); + return; + } + + 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(outMsg, 0, count, bench_size, start, ret); +} + +void bench_cmac(void) +{ +#ifdef WOLFSSL_AES_128 + bench_cmac_helper(16, "AES-128-CMAC"); +#endif +#ifdef WOLFSSL_AES_256 + bench_cmac_helper(32, "AES-256-CMAC"); +#endif + +} +#endif /* WOLFSSL_CMAC */ + +#ifdef HAVE_SCRYPT + +void bench_scrypt(void) +{ + byte derived[64]; + double start; + int ret, i, count; + + 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; + } + } + 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; +#ifdef WOLFSSL_ASYNC_CRYPT + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_MAX_DIGEST_SIZE, HEAP_HINT); +#else + byte digest[BENCH_MAX_PENDING][WC_MAX_DIGEST_SIZE]; +#endif + + (void)digestSz; + + /* 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: + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_HmacFree(&hmac[i]); + } + +#ifdef WOLFSSL_ASYNC_CRYPT + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); +#endif +} + +#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 */ + +#ifndef NO_PWDBASED +void bench_pbkdf2(void) +{ + double start; + int ret = 0, count = 0; + const char* passwd32 = "passwordpasswordpasswordpassword"; + const byte salt32[] = { 0x78, 0x57, 0x8E, 0x5a, 0x5d, 0x63, 0xcb, 0x06, + 0x78, 0x57, 0x8E, 0x5a, 0x5d, 0x63, 0xcb, 0x06, + 0x78, 0x57, 0x8E, 0x5a, 0x5d, 0x63, 0xcb, 0x06, + 0x78, 0x57, 0x8E, 0x5a, 0x5d, 0x63, 0xcb, 0x06 }; + byte derived[32]; + + bench_stats_start(&count, &start); + do { + ret = wc_PBKDF2(derived, (const byte*)passwd32, (int)XSTRLEN(passwd32), + salt32, (int)sizeof(salt32), 1000, 32, WC_SHA256); + count++; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("PBKDF2", 32, count, 32, start, ret); +} +#endif /* !NO_PWDBASED */ + +#endif /* NO_HMAC */ + #ifndef NO_RSA +#if defined(WOLFSSL_KEY_GEN) +static void bench_rsaKeyGen_helper(int doAsync, int keySz) +{ + RsaKey genKey[BENCH_MAX_PENDING]; + double start; + int ret = 0, i, count = 0, times, pending = 0; + const long rsa_e_val = WC_RSA_EXPONENT; + const char**desc = bench_desc_words[lng_index]; -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) + /* clear for done cleanup */ + XMEMSET(genKey, 0, sizeof(genKey)); + + 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, &gRng); + 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, desc[2], doAsync, count, start, ret); + + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_FreeRsaKey(&genKey[i]); + } +} + +void bench_rsaKeyGen(int doAsync) +{ + int k, keySz; +#ifndef WOLFSSL_SP_MATH + const int keySizes[2] = {1024, 2048}; +#else + const int keySizes[1] = {2048}; +#endif + + for (k = 0; k < (int)(sizeof(keySizes)/sizeof(int)); k++) { + keySz = keySizes[k]; + bench_rsaKeyGen_helper(doAsync, keySz); + } +} + + +void bench_rsaKeyGen_size(int doAsync, int keySz) +{ + bench_rsaKeyGen_helper(doAsync, keySz); +} +#endif /* WOLFSSL_KEY_GEN */ + +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ + !defined(USE_CERT_BUFFERS_3072) #if defined(WOLFSSL_MDK_SHELL) static char *certRSAname = "certs/rsa2048.der"; /* set by shell command */ @@ -1128,88 +4361,442 @@ void bench_blake2(void) #endif #endif -void bench_rsa(void) +#define RSA_BUF_SIZE 384 /* for up to 3072 bit */ + +#if !defined(WOLFSSL_RSA_VERIFY_INLINE) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#elif defined(WOLFSSL_PUBLIC_MP) || !defined(WOLFSSL_RSA_PUBLIC_ONLY) + #if defined(USE_CERT_BUFFERS_2048) +static unsigned char rsa_2048_sig[] = { + 0x8c, 0x9e, 0x37, 0xbf, 0xc3, 0xa6, 0xba, 0x1c, + 0x53, 0x22, 0x40, 0x4b, 0x8b, 0x0d, 0x3c, 0x0e, + 0x2e, 0x8c, 0x31, 0x2c, 0x47, 0xbf, 0x03, 0x48, + 0x18, 0x46, 0x73, 0x8d, 0xd7, 0xdd, 0x17, 0x64, + 0x0d, 0x7f, 0xdc, 0x74, 0xed, 0x80, 0xc3, 0xe8, + 0x9a, 0x18, 0x33, 0xd4, 0xe6, 0xc5, 0xe1, 0x54, + 0x75, 0xd1, 0xbb, 0x40, 0xde, 0xa8, 0xb9, 0x1b, + 0x14, 0xe8, 0xc1, 0x39, 0xeb, 0xa0, 0x69, 0x8a, + 0xc6, 0x9b, 0xef, 0x53, 0xb5, 0x23, 0x2b, 0x78, + 0x06, 0x43, 0x37, 0x11, 0x81, 0x84, 0x73, 0x33, + 0x33, 0xfe, 0xf7, 0x5d, 0x2b, 0x84, 0xd6, 0x83, + 0xd6, 0xdd, 0x55, 0x33, 0xef, 0xd1, 0xf7, 0x12, + 0xb0, 0xc2, 0x0e, 0xb1, 0x78, 0xd4, 0xa8, 0xa3, + 0x25, 0xeb, 0xed, 0x9a, 0xb3, 0xee, 0xc3, 0x7e, + 0xce, 0x13, 0x18, 0x86, 0x31, 0xe1, 0xef, 0x01, + 0x0f, 0x6e, 0x67, 0x24, 0x74, 0xbd, 0x0b, 0x7f, + 0xa9, 0xca, 0x6f, 0xaa, 0x83, 0x28, 0x90, 0x40, + 0xf1, 0xb5, 0x10, 0x0e, 0x26, 0x03, 0x05, 0x5d, + 0x87, 0xb4, 0xe0, 0x4c, 0x98, 0xd8, 0xc6, 0x42, + 0x89, 0x77, 0xeb, 0xb6, 0xd4, 0xe6, 0x26, 0xf3, + 0x31, 0x25, 0xde, 0x28, 0x38, 0x58, 0xe8, 0x2c, + 0xf4, 0x56, 0x7c, 0xb6, 0xfd, 0x99, 0xb0, 0xb0, + 0xf4, 0x83, 0xb6, 0x74, 0xa9, 0x5b, 0x9f, 0xe8, + 0xe9, 0xf1, 0xa1, 0x2a, 0xbd, 0xf6, 0x83, 0x28, + 0x09, 0xda, 0xa6, 0xd6, 0xcd, 0x61, 0x60, 0xf7, + 0x13, 0x4e, 0x46, 0x57, 0x38, 0x1e, 0x11, 0x92, + 0x6b, 0x6b, 0xcf, 0xd3, 0xf4, 0x8b, 0x66, 0x03, + 0x25, 0xa3, 0x7a, 0x2f, 0xce, 0xc1, 0x85, 0xa5, + 0x48, 0x91, 0x8a, 0xb3, 0x4f, 0x5d, 0x98, 0xb1, + 0x69, 0x58, 0x47, 0x69, 0x0c, 0x52, 0xdc, 0x42, + 0x4c, 0xef, 0xe8, 0xd4, 0x4d, 0x6a, 0x33, 0x7d, + 0x9e, 0xd2, 0x51, 0xe6, 0x41, 0xbf, 0x4f, 0xa2 +}; + #elif defined(USE_CERT_BUFFERS_3072) +static unsigned char rsa_3072_sig[] = { + 0x1a, 0xd6, 0x0d, 0xfd, 0xe3, 0x41, 0x95, 0x76, + 0x27, 0x16, 0x7d, 0xc7, 0x94, 0x16, 0xca, 0xa8, + 0x26, 0x08, 0xbe, 0x78, 0x87, 0x72, 0x4c, 0xd9, + 0xa7, 0xfc, 0x33, 0x77, 0x2d, 0x53, 0x07, 0xb5, + 0x8c, 0xce, 0x48, 0x17, 0x9b, 0xff, 0x9f, 0x9b, + 0x17, 0xc4, 0xbb, 0x72, 0xed, 0xdb, 0xa0, 0x34, + 0x69, 0x5b, 0xc7, 0x4e, 0xbf, 0xec, 0x13, 0xc5, + 0x98, 0x71, 0x9a, 0x4e, 0x18, 0x0e, 0xcb, 0xe7, + 0xc6, 0xd5, 0x21, 0x31, 0x7c, 0x0d, 0xae, 0x14, + 0x2b, 0x87, 0x4f, 0x77, 0x95, 0x2e, 0x26, 0xe2, + 0x83, 0xfe, 0x49, 0x1e, 0x87, 0x19, 0x4a, 0x63, + 0x73, 0x75, 0xf1, 0xf5, 0x71, 0xd2, 0xce, 0xd4, + 0x39, 0x2b, 0xd9, 0xe0, 0x76, 0x70, 0xc8, 0xf8, + 0xed, 0xdf, 0x90, 0x57, 0x17, 0xb9, 0x16, 0xf6, + 0xe9, 0x49, 0x48, 0xce, 0x5a, 0x8b, 0xe4, 0x84, + 0x7c, 0xf3, 0x31, 0x68, 0x97, 0x45, 0x68, 0x38, + 0x50, 0x3a, 0x70, 0xbd, 0xb3, 0xd3, 0xd2, 0xe0, + 0x56, 0x5b, 0xc2, 0x0c, 0x2c, 0x10, 0x70, 0x7b, + 0xd4, 0x99, 0xf9, 0x38, 0x31, 0xb1, 0x86, 0xa0, + 0x07, 0xf1, 0xf6, 0x53, 0xb0, 0x44, 0x82, 0x40, + 0xd2, 0xab, 0x0e, 0x71, 0x5d, 0xe1, 0xea, 0x3a, + 0x77, 0xc9, 0xef, 0xfe, 0x54, 0x65, 0xa3, 0x49, + 0xfd, 0xa5, 0x33, 0xaa, 0x16, 0x1a, 0x38, 0xe7, + 0xaa, 0xb7, 0x13, 0xb2, 0x3b, 0xc7, 0x00, 0x87, + 0x12, 0xfe, 0xfd, 0xf4, 0x55, 0x6d, 0x1d, 0x4a, + 0x0e, 0xad, 0xd0, 0x4c, 0x55, 0x91, 0x60, 0xd9, + 0xef, 0x74, 0x69, 0x22, 0x8c, 0x51, 0x65, 0xc2, + 0x04, 0xac, 0xd3, 0x8d, 0xf7, 0x35, 0x29, 0x13, + 0x6d, 0x61, 0x7c, 0x39, 0x2f, 0x41, 0x4c, 0xdf, + 0x38, 0xfd, 0x1a, 0x7d, 0x42, 0xa7, 0x6f, 0x3f, + 0x3d, 0x9b, 0xd1, 0x97, 0xab, 0xc0, 0xa7, 0x28, + 0x1c, 0xc0, 0x02, 0x26, 0xeb, 0xce, 0xf9, 0xe1, + 0x34, 0x45, 0xaf, 0xbf, 0x8d, 0xb8, 0xe0, 0xff, + 0xd9, 0x6f, 0x77, 0xf3, 0xf7, 0xed, 0x6a, 0xbb, + 0x03, 0x52, 0xfb, 0x38, 0xfc, 0xea, 0x9f, 0xc9, + 0x98, 0xed, 0x21, 0x45, 0xaf, 0x43, 0x2b, 0x64, + 0x96, 0x82, 0x30, 0xe9, 0xb4, 0x36, 0x89, 0x77, + 0x07, 0x4a, 0xc6, 0x1f, 0x38, 0x7a, 0xee, 0xb6, + 0x86, 0xf6, 0x2f, 0x03, 0xec, 0xa2, 0xe5, 0x48, + 0xe5, 0x5a, 0xf5, 0x1c, 0xd2, 0xd9, 0xd8, 0x2d, + 0x9d, 0x06, 0x07, 0xc9, 0x8b, 0x5d, 0xe0, 0x0f, + 0x5e, 0x0c, 0x53, 0x27, 0xff, 0x23, 0xee, 0xca, + 0x5e, 0x4d, 0xf1, 0x95, 0x77, 0x78, 0x1f, 0xf2, + 0x44, 0x5b, 0x7d, 0x01, 0x49, 0x61, 0x6f, 0x6d, + 0xbf, 0xf5, 0x19, 0x06, 0x39, 0xe9, 0xe9, 0x29, + 0xde, 0x47, 0x5e, 0x2e, 0x1f, 0x68, 0xf4, 0x32, + 0x5e, 0xe9, 0xd0, 0xa7, 0xb4, 0x2a, 0x45, 0xdf, + 0x15, 0x7d, 0x0d, 0x5b, 0xef, 0xc6, 0x23, 0xac +}; + #else + #error Not Supported Yet! + #endif +#endif + +#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) || defined(WOLFSSL_PUBLIC_MP) +static void bench_rsa_helper(int doAsync, RsaKey rsaKey[BENCH_MAX_PENDING], + int rsaKeySz) { - int i; - int ret; - size_t bytes; - word32 idx = 0; + int ret = 0, i, times, count = 0, pending = 0; + word32 idx = 0; +#ifndef WOLFSSL_RSA_VERIFY_ONLY + const char* messageStr = "Everyone gets Friday off."; + const int len = (int)XSTRLEN((char*)messageStr); +#endif + double start = 0.0f; + const char**desc = bench_desc_words[lng_index]; +#ifndef WOLFSSL_RSA_VERIFY_ONLY + DECLARE_VAR_INIT(message, byte, len, messageStr, HEAP_HINT); +#endif + #if !defined(WOLFSSL_MDK5_COMPLv5) + /* MDK5 compiler regard this as a executable statement, and does not allow declarations after the line. */ + DECLARE_ARRAY_DYNAMIC_DEC(enc, byte, BENCH_MAX_PENDING, rsaKeySz, HEAP_HINT); + #else + byte* enc[BENCH_MAX_PENDING]; + #endif + #if !defined(WOLFSSL_RSA_VERIFY_INLINE) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY) + #if !defined(WOLFSSL_MDK5_COMPLv5) + /* MDK5 compiler regard this as a executable statement, and does not allow declarations after the line. */ + DECLARE_ARRAY_DYNAMIC_DEC(out, byte, BENCH_MAX_PENDING, rsaKeySz, HEAP_HINT); + #else + int idxout; + byte* out[BENCH_MAX_PENDING]; + #endif + #else + byte* out[BENCH_MAX_PENDING]; + #endif + + DECLARE_ARRAY_DYNAMIC_EXE(enc, byte, BENCH_MAX_PENDING, rsaKeySz, HEAP_HINT); + #if !defined(WOLFSSL_RSA_VERIFY_INLINE) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY) + DECLARE_ARRAY_DYNAMIC_EXE(out, byte, BENCH_MAX_PENDING, rsaKeySz, HEAP_HINT); + #endif + + if (!rsa_sign_verify) { +#ifndef WOLFSSL_RSA_VERIFY_ONLY + /* begin public 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_RsaPublicEncrypt(message, (word32)len, enc[i], + rsaKeySz/8, &rsaKey[i], + &gRng); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV( + &rsaKey[i]), 1, ×, &pending)) { + goto exit_rsa_pub; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_rsa_pub: + bench_stats_asym_finish("RSA", rsaKeySz, desc[0], doAsync, count, + start, ret); +#endif + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + if (ret < 0) { + goto exit; + } + + /* capture resulting encrypt length */ + idx = (word32)(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_RsaPrivateDecrypt(enc[i], idx, out[i], + rsaKeySz/8, &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, desc[1], doAsync, count, + start, ret); +#endif + } + else { +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + /* begin RSA sign */ + 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_Sign(message, len, enc[i], + rsaKeySz/8, &rsaKey[i], &gRng); + if (!bench_async_handle(&ret, + BENCH_ASYNC_GET_DEV(&rsaKey[i]), + 1, ×, &pending)) { + goto exit_rsa_sign; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_rsa_sign: + bench_stats_asym_finish("RSA", rsaKeySz, desc[4], doAsync, count, start, + ret); + + if (ret < 0) { + goto exit; + } +#endif + + /* capture resulting encrypt length */ + idx = rsaKeySz/8; + + /* begin RSA verify */ + 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)) { + #if !defined(WOLFSSL_RSA_VERIFY_INLINE) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY) + ret = wc_RsaSSL_Verify(enc[i], idx, out[i], + rsaKeySz/8, &rsaKey[i]); + #elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(enc[i], rsa_2048_sig, sizeof(rsa_2048_sig)); + idx = sizeof(rsa_2048_sig); + out[i] = NULL; + ret = wc_RsaSSL_VerifyInline(enc[i], idx, &out[i], + &rsaKey[i]); + if (ret > 0) + ret = 0; + #elif defined(USE_CERT_BUFFERS_3072) + XMEMCPY(enc[i], rsa_3072_sig, sizeof(rsa_3072_sig)); + idx = sizeof(rsa_3072_sig); + out[i] = NULL; + ret = wc_RsaSSL_VerifyInline(enc[i], idx, &out[i], + &rsaKey[i]); + if (ret > 0) + ret = 0; + #endif + if (!bench_async_handle(&ret, + BENCH_ASYNC_GET_DEV(&rsaKey[i]), + 1, ×, &pending)) { + goto exit_rsa_verify; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_rsa_verify: + bench_stats_asym_finish("RSA", rsaKeySz, desc[5], doAsync, count, + start, ret); + } + + FREE_ARRAY_DYNAMIC(enc, BENCH_MAX_PENDING, HEAP_HINT); +#if !defined(WOLFSSL_RSA_VERIFY_INLINE) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) + FREE_ARRAY_DYNAMIC(out, BENCH_MAX_PENDING, HEAP_HINT); +#endif + FREE_VAR(message, HEAP_HINT); +} +#endif + +void bench_rsa(int doAsync) +{ + int ret = 0, i; + RsaKey rsaKey[BENCH_MAX_PENDING]; +#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) || defined(WOLFSSL_PUBLIC_MP) + int rsaKeySz; /* used in printf */ + size_t bytes; const byte* tmp; - - 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 */ + word32 idx; #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; + rsaKeySz = 2048; +#elif defined(USE_CERT_BUFFERS_3072) + tmp = rsa_key_der_3072; + bytes = (size_t)sizeof_rsa_key_der_3072; + rsaKeySz = 3072; #else #error "need a cert buffer size" #endif /* USE_CERT_BUFFERS */ - - -#ifdef HAVE_CAVIUM - if (wc_RsaInitCavium(&rsaKey, CAVIUM_DEV_ID) != 0) - printf("RSA init cavium failed\n"); #endif - ret = wc_InitRsaKey(&rsaKey, 0); - if (ret < 0) { - printf("InitRsaKey failed\n"); - return; - } - ret = wc_RsaPrivateKeyDecode(tmp, &idx, &rsaKey, (word32)bytes); - start = current_time(1); + /* clear for done cleanup */ + XMEMSET(rsaKey, 0, sizeof(rsaKey)); - for (i = 0; i < ntimes; i++) - ret = wc_RsaPublicEncrypt(message,len,enc,sizeof(enc), &rsaKey, &rng); + /* 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, + doAsync ? devId : INVALID_DEVID)) < 0) { + goto exit_bench_rsa; + } - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("RSA %d encryption took %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); - - if (ret < 0) { - printf("Rsa Public Encrypt failed\n"); - return; - } - - start = current_time(1); - - for (i = 0; i < ntimes; i++) { - byte out[256]; /* for up to 2048 bit */ - wc_RsaPrivateDecrypt(enc, (word32)ret, out, sizeof(out), &rsaKey); - } - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("RSA %d decryption took %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); - - wc_FreeRsaKey(&rsaKey); -#ifdef HAVE_CAVIUM - wc_RsaFreeCavium(&rsaKey); +#ifndef WOLFSSL_RSA_VERIFY_ONLY + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(&rsaKey[i], &gRng); + if (ret != 0) + goto exit_bench_rsa; + #endif #endif + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + /* 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 exit_bench_rsa; + } +#elif defined(WOLFSSL_PUBLIC_MP) + #ifdef USE_CERT_BUFFERS_2048 + ret = mp_read_unsigned_bin(&rsaKey[i].n, &tmp[12], 256); + if (ret != 0) { + printf("wc_RsaPrivateKeyDecode failed! %d\n", ret); + goto exit_bench_rsa; + } + ret = mp_set_int(&rsaKey[i].e, WC_RSA_EXPONENT); + if (ret != 0) { + printf("wc_RsaPrivateKeyDecode failed! %d\n", ret); + goto exit_bench_rsa; + } + #else + #error Not supported yet! + #endif + (void)idx; + (void)bytes; +#endif + + } + +#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) || defined(WOLFSSL_PUBLIC_MP) + bench_rsa_helper(doAsync, rsaKey, rsaKeySz); +#endif +exit_bench_rsa: + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_FreeRsaKey(&rsaKey[i]); + } } -#endif + + +#ifdef WOLFSSL_KEY_GEN +/* bench any size of RSA key */ +void bench_rsa_key(int doAsync, int rsaKeySz) +{ + int ret = 0, i, pending = 0; + RsaKey rsaKey[BENCH_MAX_PENDING]; + int isPending[BENCH_MAX_PENDING]; + long exp = 65537l; + + /* clear for done cleanup */ + XMEMSET(rsaKey, 0, sizeof(rsaKey)); + XMEMSET(isPending, 0, sizeof(isPending)); + + /* init keys */ + do { + pending = 0; + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (!isPending[i]) { /* if making the key is pending then just call + * wc_MakeRsaKey again */ + /* setup an async context for each key */ + if ((ret = wc_InitRsaKey_ex(&rsaKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) < 0) { + goto exit_bench_rsa_key; + } + + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(&rsaKey[i], &gRng); + if (ret != 0) + goto exit_bench_rsa_key; + #endif + } + + /* create the RSA key */ + ret = wc_MakeRsaKey(&rsaKey[i], rsaKeySz, exp, &gRng); + if (ret == WC_PENDING_E) { + isPending[i] = 1; + pending = 1; + } + else if (ret != 0) { + printf("wc_MakeRsaKey failed! %d\n", ret); + goto exit_bench_rsa_key; + } + } /* for i */ + } while (pending > 0); + + bench_rsa_helper(doAsync, rsaKey, rsaKeySz); +exit_bench_rsa_key: + + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_FreeRsaKey(&rsaKey[i]); + } +} +#endif /* WOLFSSL_KEY_GEN */ +#endif /* !NO_RSA */ #ifndef NO_DH - -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ + !defined(USE_CERT_BUFFERS_3072) #if defined(WOLFSSL_MDK_SHELL) static char *certDHname = "certs/dh2048.der"; /* set by shell command */ @@ -1223,134 +4810,186 @@ void bench_rsa(void) #endif #endif -void bench_dh(void) +#define BENCH_DH_KEY_SIZE 384 /* for 3072 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; - const byte* tmp; + int ret = 0, i; + int count = 0, times, pending = 0; + const byte* tmp = NULL; + double start = 0.0f; + DhKey dhKey[BENCH_MAX_PENDING]; + int dhKeySz = BENCH_DH_KEY_SIZE * 8; /* used in printf */ + const char**desc = bench_desc_words[lng_index]; +#ifndef NO_ASN + size_t bytes = 0; + word32 idx; +#endif + word32 pubSz[BENCH_MAX_PENDING]; + word32 privSz[BENCH_MAX_PENDING]; + word32 pubSz2; + word32 privSz2; + word32 agreeSz[BENCH_MAX_PENDING]; +#ifdef HAVE_FFDHE_2048 + const DhParams *params = NULL; +#endif - 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 */ + 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); - double start, total, each, milliEach; - DhKey dhKey; - int dhKeySz = 2048; /* used in printf */ - - (void)idx; (void)tmp; - -#ifdef USE_CERT_BUFFERS_1024 - tmp = dh_key_der_1024; - bytes = sizeof_dh_key_der_1024; - dhKeySz = 1024; + if (!use_ffdhe) { +#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 = (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; -#elif defined(NO_ASN) - dhKeySz = 1024; - /* do nothing, but don't use default FILE */ + tmp = dh_key_der_2048; + bytes = (size_t)sizeof_dh_key_der_2048; + dhKeySz = 2048; +#elif defined(USE_CERT_BUFFERS_3072) + tmp = dh_key_der_3072; + bytes = (size_t)sizeof_dh_key_der_3072; + dhKeySz = 3072; #else #error "need to define a cert buffer size" #endif /* USE_CERT_BUFFERS */ - - - 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; } - - start = current_time(1); - - for (i = 0; i < ntimes; i++) - wc_DhGenerateKeyPair(&dhKey, &rng, priv, &privSz, pub, &pubSz); - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - 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); -} +#ifdef HAVE_FFDHE_2048 + else if (use_ffdhe == 2048) { + params = wc_Dh_ffdhe2048_Get(); + dhKeySz = 2048; + } +#endif +#ifdef HAVE_FFDHE_3072 + else if (use_ffdhe == 3072) { + params = wc_Dh_ffdhe3072_Get(); + dhKeySz = 3072; + } #endif -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) -void bench_rsaKeyGen(void) -{ - RsaKey genKey; - double start, total, each, milliEach; - int i; - - /* 1024 bit */ - start = current_time(1); + /* clear for done cleanup */ + XMEMSET(dhKey, 0, sizeof(dhKey)); - for(i = 0; i < genTimes; i++) { - wc_InitRsaKey(&genKey, 0); - wc_MakeRsaKey(&genKey, 1024, 65537, &rng); - wc_FreeRsaKey(&genKey); + /* 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 */ + if (!use_ffdhe) { + #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 defined(HAVE_FFDHE_2048) || defined(HAVE_FFDHE_3072) + else if (params != NULL) { + ret = wc_DhSetKey(&dhKey[i], params->p, params->p_len, params->g, + params->g_len); + } + #endif + if (ret != 0) { + printf("DhKeyDecode failed %d, can't benchmark\n", ret); + goto exit; + } } - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* millisconds */ - printf("\n"); - printf("RSA 1024 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); + /* 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); - /* 2048 bit */ - start = current_time(1); + 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], &gRng, 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, desc[2], doAsync, count, start, ret); - for(i = 0; i < genTimes; i++) { - wc_InitRsaKey(&genKey, 0); - wc_MakeRsaKey(&genKey, 2048, 65537, &rng); - wc_FreeRsaKey(&genKey); + if (ret < 0) { + goto exit; } - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* millisconds */ - printf("RSA 2048 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); + /* Generate key to use as other public */ + ret = wc_DhGenerateKeyPair(&dhKey[0], &gRng, priv2, &privSz2, pub2, &pubSz2); +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &dhKey[0].asyncDev, WC_ASYNC_FLAG_NONE); +#endif + + /* Key Agree */ + 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(&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, desc[3], doAsync, count, start, ret); + + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_FreeDhKey(&dhKey[i]); + } + + 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); byte GetEntropy(ENTROPY_CMD cmd, byte* out) { if (cmd == INIT) - return (wc_InitRng(&rng) == 0) ? 1 : 0; + return 1; /* using local rng */ if (out == NULL) return 0; if (cmd == GET_BYTE_OF_ENTROPY) - return (wc_RNG_GenerateBlock(&rng, out, 1) == 0) ? 1 : 0; + return (wc_RNG_GenerateBlock(&gRng, out, 1) == 0) ? 1 : 0; if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY) { *out = 1; @@ -1363,17 +5002,21 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) void bench_ntru(void) { int i; - double start, total, each, milliEach; + double start; - byte public_key[557]; + byte public_key[1027]; word16 public_key_len = sizeof(public_key); - byte private_key[607]; + byte private_key[1120]; word16 private_key_len = sizeof(private_key); + word16 ntruBits = 128; + word16 type = 0; + word32 ret; - byte ciphertext[552]; + byte ciphertext[1022]; word16 ciphertext_len; byte plaintext[16]; word16 plaintext_len; + const char**desc = bench_desc_words[lng_index]; DRBG_HANDLE drbg; static byte const aes_key[] = { @@ -1381,425 +5024,799 @@ void bench_ntru(void) 0x7b, 0x12, 0x49, 0x88, 0xaf, 0xb3, 0x22, 0xd8 }; - static byte const cyasslStr[] = { - 'C', 'y', 'a', 'S', 'S', 'L', ' ', 'N', 'T', 'R', 'U' + static byte const wolfsslStr[] = { + 'w', 'o', 'l', 'f', 'S', 'S', 'L', ' ', 'N', 'T', 'R', 'U' }; - word32 rc = ntru_crypto_drbg_instantiate(112, cyasslStr, sizeof(cyasslStr), - (ENTROPY_FN) GetEntropy, &drbg); - if(rc != DRBG_OK) { - printf("NTRU drbg instantiate failed\n"); - return; - } + for (ntruBits = 128; ntruBits < 257; ntruBits += 64) { + switch (ntruBits) { + case 128: + type = NTRU_EES439EP1; + break; + case 192: + type = NTRU_EES593EP1; + break; + case 256: + type = NTRU_EES743EP1; + break; + } - rc = ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2, - &public_key_len, NULL, &private_key_len, NULL); - if (rc != NTRU_OK) { - ntru_crypto_drbg_uninstantiate(drbg); - printf("NTRU failed to get key lengths\n"); - return; - } - - rc = ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2, &public_key_len, - public_key, &private_key_len, - private_key); - - ntru_crypto_drbg_uninstantiate(drbg); - - if (rc != NTRU_OK) { - ntru_crypto_drbg_uninstantiate(drbg); - printf("NTRU keygen failed\n"); - return; - } - - rc = ntru_crypto_drbg_instantiate(112, NULL, 0, (ENTROPY_FN)GetEntropy, - &drbg); - if (rc != DRBG_OK) { - printf("NTRU error occurred during DRBG instantiation\n"); - return; - } - - rc = ntru_crypto_ntru_encrypt(drbg, public_key_len, public_key, sizeof( - aes_key), aes_key, &ciphertext_len, NULL); - - if (rc != NTRU_OK) { - printf("NTRU error occurred requesting the buffer size needed\n"); - return; - } - start = current_time(1); - - for (i = 0; i < ntimes; i++) { - - rc = ntru_crypto_ntru_encrypt(drbg, public_key_len, public_key, sizeof( - aes_key), aes_key, &ciphertext_len, ciphertext); - - if (rc != NTRU_OK) { - printf("NTRU encrypt error\n"); + ret = ntru_crypto_drbg_instantiate(ntruBits, wolfsslStr, + sizeof(wolfsslStr), (ENTROPY_FN) GetEntropy, &drbg); + if(ret != DRBG_OK) { + printf("NTRU drbg instantiate failed\n"); return; } - } - rc = ntru_crypto_drbg_uninstantiate(drbg); + /* set key sizes */ + ret = ntru_crypto_ntru_encrypt_keygen(drbg, type, &public_key_len, + NULL, &private_key_len, NULL); + if (ret != NTRU_OK) { + ntru_crypto_drbg_uninstantiate(drbg); + printf("NTRU failed to get key lengths\n"); + return; + } - if (rc != DRBG_OK) { - printf("NTRU error occurred uninstantiating the DRBG\n"); - return; - } + ret = ntru_crypto_ntru_encrypt_keygen(drbg, type, &public_key_len, + public_key, &private_key_len, + private_key); - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ + ntru_crypto_drbg_uninstantiate(drbg); - printf("NTRU 112 encryption took %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, ntimes); + if (ret != NTRU_OK) { + printf("NTRU keygen failed\n"); + return; + } + ret = ntru_crypto_drbg_instantiate(ntruBits, NULL, 0, + (ENTROPY_FN)GetEntropy, &drbg); + if (ret != DRBG_OK) { + printf("NTRU error occurred during DRBG instantiation\n"); + return; + } - rc = ntru_crypto_ntru_decrypt(private_key_len, private_key, ciphertext_len, - ciphertext, &plaintext_len, NULL); + ret = ntru_crypto_ntru_encrypt(drbg, public_key_len, public_key, + sizeof(aes_key), aes_key, &ciphertext_len, NULL); - if (rc != NTRU_OK) { - printf("NTRU decrypt error occurred getting the buffer size needed\n"); - return; - } + if (ret != NTRU_OK) { + printf("NTRU error occurred requesting the buffer size needed\n"); + return; + } - plaintext_len = sizeof(plaintext); - 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); + if (ret != NTRU_OK) { + printf("NTRU encrypt error\n"); + return; + } + } + bench_stats_asym_finish("NTRU", ntruBits, desc[6], 0, i, start, ret); - for (i = 0; i < ntimes; i++) { - rc = ntru_crypto_ntru_decrypt(private_key_len, private_key, + ret = ntru_crypto_drbg_uninstantiate(drbg); + if (ret != DRBG_OK) { + printf("NTRU error occurred uninstantiating the DRBG\n"); + return; + } + + ret = ntru_crypto_ntru_decrypt(private_key_len, private_key, + ciphertext_len, ciphertext, &plaintext_len, NULL); + + if (ret != NTRU_OK) { + printf("NTRU decrypt error occurred getting the buffer size needed\n"); + return; + } + + plaintext_len = sizeof(plaintext); + + bench_stats_start(&i, &start); + for (i = 0; i < ntimes; i++) { + ret = ntru_crypto_ntru_decrypt(private_key_len, private_key, ciphertext_len, ciphertext, &plaintext_len, plaintext); - if (rc != NTRU_OK) { - printf("NTRU error occurred decrypting the key\n"); - return; + if (ret != NTRU_OK) { + printf("NTRU error occurred decrypting the key\n"); + return; + } } + bench_stats_asym_finish("NTRU", ntruBits, desc[7], 0, i, start, ret); } - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("NTRU 112 decryption took %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, ntimes); } void bench_ntruKeyGen(void) { - double start, total, each, milliEach; + double start; int i; - byte public_key[557]; /* 2048 key equivalent to rsa */ + byte public_key[1027]; word16 public_key_len = sizeof(public_key); - byte private_key[607]; + byte private_key[1120]; word16 private_key_len = sizeof(private_key); + word16 ntruBits = 128; + word16 type = 0; + word32 ret; + const char**desc = bench_desc_words[lng_index]; DRBG_HANDLE drbg; static uint8_t const pers_str[] = { - 'C', 'y', 'a', 'S', 'S', 'L', ' ', 't', 'e', 's', 't' + 'w', 'o', 'l', 'f', 'S', 'S', 'L', ' ', 't', 'e', 's', 't' }; - word32 rc = ntru_crypto_drbg_instantiate(112, pers_str, sizeof(pers_str), - GetEntropy, &drbg); - if(rc != DRBG_OK) { - printf("NTRU drbg instantiate failed\n"); - return; - } + for (ntruBits = 128; ntruBits < 257; ntruBits += 64) { + ret = ntru_crypto_drbg_instantiate(ntruBits, pers_str, + sizeof(pers_str), GetEntropy, &drbg); + if (ret != DRBG_OK) { + printf("NTRU drbg instantiate failed\n"); + return; + } - start = current_time(1); + switch (ntruBits) { + case 128: + type = NTRU_EES439EP1; + break; + case 192: + type = NTRU_EES593EP1; + break; + case 256: + type = NTRU_EES743EP1; + break; + } - for(i = 0; i < genTimes; i++) { - ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2, &public_key_len, - public_key, &private_key_len, - private_key); - } + /* set key sizes */ + ret = ntru_crypto_ntru_encrypt_keygen(drbg, type, &public_key_len, + NULL, &private_key_len, NULL); - total = current_time(0) - start; + 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); + } + bench_stats_asym_finish("NTRU", ntruBits, desc[2], 0, i, start, ret); - rc = ntru_crypto_drbg_uninstantiate(drbg); + if (ret != NTRU_OK) { + return; + } - if (rc != NTRU_OK) { - printf("NTRU drbg uninstantiate failed\n"); - return; - } + ret = ntru_crypto_drbg_uninstantiate(drbg); - each = total / genTimes; - milliEach = each * 1000; - - printf("\n"); - printf("NTRU 112 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); - -} -#endif - -#ifdef HAVE_ECC -void bench_eccKeyGen(void) -{ - ecc_key genKey; - double start, total, each, milliEach; - int i; - - /* 256 bit */ - start = current_time(1); - - for(i = 0; i < genTimes; i++) { - wc_ecc_init(&genKey); - wc_ecc_make_key(&rng, 32, &genKey); - wc_ecc_free(&genKey); - } - - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* millisconds */ - printf("\n"); - printf("ECC 256 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); -} - - -void bench_eccKeyAgree(void) -{ - ecc_key genKey, genKey2; - double start, total, each, milliEach; - int i, ret; - byte shared[32]; - byte sig[64+16]; /* der encoding too */ - byte digest[32]; - word32 x = 0; - - wc_ecc_init(&genKey); - wc_ecc_init(&genKey2); - - 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"); + if (ret != NTRU_OK) { + printf("NTRU drbg uninstantiate failed\n"); return; } } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* millisconds */ - 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; - - - 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; /* millisconds */ - 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; - } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* millisconds */ - printf("EC-DSA verify time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); - - wc_ecc_free(&genKey2); - wc_ecc_free(&genKey); } +#endif + +#ifdef HAVE_ECC + +#ifndef BENCH_ECC_SIZE + #ifdef HAVE_ECC384 + #define BENCH_ECC_SIZE 48 + #else + #define BENCH_ECC_SIZE 32 + #endif +#endif + +/* Default to testing P-256 */ +static int bench_ecc_size = 32; + +void bench_eccMakeKey(int doAsync) +{ + int ret = 0, i, times, count, pending = 0; + const int keySize = bench_ecc_size; + ecc_key genKey[BENCH_MAX_PENDING]; + double start; + const char**desc = bench_desc_words[lng_index]; + + /* clear for done cleanup */ + XMEMSET(&genKey, 0, sizeof(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(&gRng, 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, desc[2], 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; + const char**desc = bench_desc_words[lng_index]; + +#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); + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, BENCH_ECC_SIZE, HEAP_HINT); +#endif + + /* 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(&gRng, 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(&gRng, keySize, &genKey2[i])) > 0) { + goto exit; + } + #endif + } + +#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, desc[3], 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], + &gRng, &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, desc[4], 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, desc[5], 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); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); +#endif +} + + +#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 bench_plainSz = BENCH_SIZE; + int ret, i, count; + double start; + const char**desc = bench_desc_words[lng_index]; + + ret = wc_ecc_init_ex(&userA, HEAP_HINT, devId); + if (ret != 0) { + printf("wc_ecc_encrypt make key A failed: %d\n", ret); + return; + } + + ret = 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; + } + + ret = wc_ecc_make_key(&gRng, 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(&gRng, 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; + + 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, desc[6], 0, count, start, ret); + + 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, desc[7], 0, count, start, ret); + +exit: + + /* cleanup */ + wc_ecc_free(&userB); + wc_ecc_free(&userA); +} +#endif #endif /* HAVE_ECC */ #ifdef HAVE_CURVE25519 void bench_curve25519KeyGen(void) { curve25519_key genKey; - double start, total, each, milliEach; - int i; + double start; + int ret = 0, i, count; + const char**desc = bench_desc_words[lng_index]; - /* 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; /* millisconds */ - 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(&gRng, 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, desc[2], 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]; + const char**desc = bench_desc_words[lng_index]; word32 x = 0; wc_curve25519_init(&genKey); wc_curve25519_init(&genKey2); - ret = wc_curve25519_make_key(&rng, 32, &genKey); + ret = wc_curve25519_make_key(&gRng, 32, &genKey); if (ret != 0) { printf("curve25519_make_key failed\n"); return; } - ret = wc_curve25519_make_key(&rng, 32, &genKey2); + ret = wc_curve25519_make_key(&gRng, 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; /* millisconds */ - 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, desc[3], 0, count, start, ret); wc_curve25519_free(&genKey2); wc_curve25519_free(&genKey); } +#endif /* HAVE_CURVE25519_SHARED_SECRET */ #endif /* HAVE_CURVE25519 */ #ifdef HAVE_ED25519 void bench_ed25519KeyGen(void) { ed25519_key genKey; - double start, total, each, milliEach; - int i; + double start; + int i, count; + const char**desc = bench_desc_words[lng_index]; - /* 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; /* millisconds */ - 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); + (void)wc_ed25519_make_key(&gRng, 32, &genKey); + wc_ed25519_free(&genKey); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("ED", 25519, desc[2], 0, count, start, 0); } void bench_ed25519KeySign(void) { + int ret; ed25519_key genKey; - double start, total, each, milliEach; - int i, ret; +#ifdef HAVE_ED25519_SIGN + double start; + int i, count; byte sig[ED25519_SIG_SIZE]; byte msg[512]; word32 x = 0; +#endif + const char**desc = bench_desc_words[lng_index]; wc_ed25519_init(&genKey); - ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &genKey); + ret = wc_ed25519_make_key(&gRng, ED25519_KEY_SIZE, &genKey); if (ret != 0) { printf("ed25519_make_key failed\n"); return; } + +#ifdef HAVE_ED25519_SIGN /* make dummy msg */ 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; + } } - } + count += i; + } while (bench_stats_sym_check(start)); +exit_ed_sign: + bench_stats_asym_finish("ED", 25519, desc[4], 0, count, start, ret); - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* millisconds */ - printf("ED25519 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_ed25519_verify_msg(sig, x, msg, sizeof(msg), &verify, - &genKey); - if (ret != 0 || verify != 1) { - printf("ed25519_verify_msg failed\n"); - return; +#ifdef HAVE_ED25519_VERIFY + 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; /* millisconds */ - 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, desc[5], 0, count, start, ret); +#endif /* HAVE_ED25519_VERIFY */ +#endif /* HAVE_ED25519_SIGN */ wc_ed25519_free(&genKey); } #endif /* HAVE_ED25519 */ +#ifdef HAVE_CURVE448 +void bench_curve448KeyGen(void) +{ + curve448_key genKey; + double start; + int ret = 0, i, count; + const char**desc = bench_desc_words[lng_index]; -#ifdef _WIN32 + /* Key Gen */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + ret = wc_curve448_make_key(&gRng, 56, &genKey); + wc_curve448_free(&genKey); + if (ret != 0) { + printf("wc_curve448_make_key failed: %d\n", ret); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("CURVE", 448, desc[2], 0, count, start, ret); +} + +#ifdef HAVE_CURVE448_SHARED_SECRET +void bench_curve448KeyAgree(void) +{ + curve448_key genKey, genKey2; + double start; + int ret, i, count; + byte shared[56]; + const char**desc = bench_desc_words[lng_index]; + word32 x = 0; + + wc_curve448_init(&genKey); + wc_curve448_init(&genKey2); + + ret = wc_curve448_make_key(&gRng, 56, &genKey); + if (ret != 0) { + printf("curve448_make_key failed\n"); + return; + } + ret = wc_curve448_make_key(&gRng, 56, &genKey2); + if (ret != 0) { + printf("curve448_make_key failed: %d\n", ret); + wc_curve448_free(&genKey); + return; + } + + /* Shared secret */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + x = sizeof(shared); + ret = wc_curve448_shared_secret(&genKey, &genKey2, shared, &x); + if (ret != 0) { + printf("curve448_shared_secret failed: %d\n", ret); + goto exit; + } + } + count += i; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("CURVE", 448, desc[3], 0, count, start, ret); + + wc_curve448_free(&genKey2); + wc_curve448_free(&genKey); +} +#endif /* HAVE_CURVE448_SHARED_SECRET */ +#endif /* HAVE_CURVE448 */ + +#ifdef HAVE_ED448 +void bench_ed448KeyGen(void) +{ + ed448_key genKey; + double start; + int i, count; + const char**desc = bench_desc_words[lng_index]; + + /* Key Gen */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + wc_ed448_init(&genKey); + (void)wc_ed448_make_key(&gRng, ED448_KEY_SIZE, &genKey); + wc_ed448_free(&genKey); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("ED", 448, desc[2], 0, count, start, 0); +} + + +void bench_ed448KeySign(void) +{ + int ret; + ed448_key genKey; +#ifdef HAVE_ED448_SIGN + double start; + int i, count; + byte sig[ED448_SIG_SIZE]; + byte msg[512]; + word32 x = 0; +#endif + const char**desc = bench_desc_words[lng_index]; + + wc_ed448_init(&genKey); + + ret = wc_ed448_make_key(&gRng, ED448_KEY_SIZE, &genKey); + if (ret != 0) { + printf("ed448_make_key failed\n"); + return; + } + +#ifdef HAVE_ED448_SIGN + /* make dummy msg */ + for (i = 0; i < (int)sizeof(msg); i++) + msg[i] = (byte)i; + + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + x = sizeof(sig); + ret = wc_ed448_sign_msg(msg, sizeof(msg), sig, &x, &genKey, + NULL, 0); + if (ret != 0) { + printf("ed448_sign_msg failed\n"); + goto exit_ed_sign; + } + } + count += i; + } while (bench_stats_sym_check(start)); +exit_ed_sign: + bench_stats_asym_finish("ED", 448, desc[4], 0, count, start, ret); + +#ifdef HAVE_ED448_VERIFY + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + int verify = 0; + ret = wc_ed448_verify_msg(sig, x, msg, sizeof(msg), &verify, + &genKey, NULL, 0); + if (ret != 0 || verify != 1) { + printf("ed448_verify_msg failed\n"); + goto exit_ed_verify; + } + } + count += i; + } while (bench_stats_sym_check(start)); +exit_ed_verify: + bench_stats_asym_finish("ED", 448, desc[5], 0, count, start, ret); +#endif /* HAVE_ED448_VERIFY */ +#endif /* HAVE_ED448_SIGN */ + + wc_ed448_free(&genKey); +} +#endif /* HAVE_ED448 */ + +#ifndef HAVE_STACK_SIZE +#if defined(_WIN32) && !defined(INTIME_RTOS) #define WIN32_LEAN_AND_MEAN #include @@ -1808,7 +5825,7 @@ void bench_ed25519KeySign(void) { static int init = 0; static LARGE_INTEGER freq; - + LARGE_INTEGER count; (void)reset; @@ -1827,10 +5844,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; @@ -1846,11 +5863,19 @@ void bench_ed25519KeySign(void) return ( ns / CLOCK * 2.0); } -#elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) || defined(WOLFSSL_USER_CURRTIME) - extern double current_time(int reset); - -#elif defined FREERTOS +#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) + + #include "task.h" +#if defined(WOLFSSL_ESPIDF) + /* proto type definition */ + int construct_argv(); + extern char* __argv[22]; +#endif double current_time(int reset) { portTickType tickCount; @@ -1876,6 +5901,107 @@ 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" + + double current_time(int reset) + { + double time_now; + double current_s = OS_GetTime() / 1000.0; + double current_us = OS_GetTime_us() / 1000000.0; + time_now = (double)( current_s + current_us); + + (void) reset; + + return time_now; + } +#elif defined(WOLFSSL_SGX) + double current_time(int reset); + +#elif defined(WOLFSSL_DEOS) + double current_time(int reset) + { + const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds(); + uint32_t *systemTickPtr = systemTickPointer(); + + (void)reset; + + return (double) *systemTickPtr/systemTickTimeInHz; + } + +#elif defined(MICRIUM) + double current_time(int reset) + { + CPU_ERR err; + + (void)reset; + return (double) CPU_TS_Get32()/CPU_TS_TmrFreqGet(&err); + } +#elif defined(WOLFSSL_ZEPHYR) + + #include + + double current_time(int reset) + { + (void)reset; + + #if defined(CONFIG_ARCH_POSIX) + k_cpu_idle(); + #endif + + return (double)k_uptime_get() / 1000; + } + +#elif defined(WOLFSSL_NETBURNER) + #include + #include + #include + + double current_time(int reset) + { + DWORD ticks = TimeTick; /* ticks since system start */ + (void)reset; + + return (double) ticks/TICKS_PER_SECOND; + } + +#elif defined(THREADX) + #include "tx_api.h" + double current_time(int reset) + { + (void)reset; + return (double) tx_time_get() / TX_TIMER_TICKS_PER_SECOND; + } + +#elif defined(WOLFSSL_XILINX) + #ifndef XPAR_CPU_CORTEXA53_0_TIMESTAMP_CLK_FREQ + #define XPAR_CPU_CORTEXA53_0_TIMESTAMP_CLK_FREQ 50000000 + #endif + #ifndef COUNTS_PER_SECOND + #define COUNTS_PER_SECOND XPAR_CPU_CORTEXA53_0_TIMESTAMP_CLK_FREQ + #endif + + double current_time(int reset) + { + double timer; + uint64_t cntPct = 0; + asm volatile("mrs %0, CNTPCT_EL0" : "=r" (cntPct)); + + /* Convert to milliseconds */ + timer = (double)(cntPct / (COUNTS_PER_SECOND / 1000)); + /* Convert to seconds.millisecond */ + timer /= 1000; + return timer; + } + #else #include @@ -1892,10 +6018,11 @@ void bench_ed25519KeySign(void) } #endif /* _WIN32 */ +#endif /* !HAVE_STACK_SIZE */ -#ifdef HAVE_GET_CYCLES +#if defined(HAVE_GET_CYCLES) -static INLINE word64 get_intel_cycles(void) +static WC_INLINE word64 get_intel_cycles(void) { unsigned int lo_c, hi_c; __asm__ __volatile__ ( @@ -1908,3 +6035,294 @@ 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) { + numBlocks = numBlocks * bench_size / block_size; + bench_size = (word32)block_size; + } +} + +#ifndef NO_MAIN_DRIVER + +#ifndef MAIN_NO_ARGS + +#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("%s", bench_Usage_msg1[lng_index][0]); /* option -? */ + printf("%s", bench_Usage_msg1[lng_index][1]); /* option -csv */ + printf("%s", bench_Usage_msg1[lng_index][2]); /* option -base10 */ +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + printf("%s", bench_Usage_msg1[lng_index][3]); /* option -no_add */ +#endif + printf("%s", bench_Usage_msg1[lng_index][4]); /* option -dgst_full */ +#ifndef NO_RSA + printf("%s", bench_Usage_msg1[lng_index][5]); /* option -ras_sign */ + #ifdef WOLFSSL_KEY_GEN + printf("%s", bench_Usage_msg1[lng_index][6]); /* option -rsa-sz */ + #endif +#endif +#if !defined(NO_DH) && defined(HAVE_FFDHE_2048) + printf("%s", bench_Usage_msg1[lng_index][7]); /* option -ffdhe2048 */ +#endif +#if !defined(NO_DH) && defined(HAVE_FFDHE_3072) + printf("%s", bench_Usage_msg1[lng_index][8]); /* option -ffdhe3072 */ +#endif +#if defined(HAVE_ECC) && !defined(NO_ECC256) + printf("%s", bench_Usage_msg1[lng_index][9]); /* option -p256 */ +#endif +#if defined(HAVE_ECC) && defined(HAVE_ECC384) + printf("%s", bench_Usage_msg1[lng_index][10]); /* option -p384 */ +#endif +#ifndef WOLFSSL_BENCHMARK_ALL + printf("%s", bench_Usage_msg1[lng_index][11]); /* option - */ + 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("%s", bench_Usage_msg1[lng_index][12]); /* option -lng */ + printf("%s", bench_Usage_msg1[lng_index][13]); /* option */ +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + printf("%s", bench_Usage_msg1[lng_index][14]); /* option -threads */ +#endif + printf("%s", bench_Usage_msg1[lng_index][15]); /* option -print */ +} + +/* 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; +} +#endif /* MAIN_NO_ARGS */ + +#ifdef WOLFSSL_ESPIDF +int wolf_benchmark_task( ) +#elif defined(MAIN_NO_ARGS) +int main() +#else +int main(int argc, char** argv) +#endif +{ + int ret = 0; +#ifndef MAIN_NO_ARGS + int optMatched; +#ifdef WOLFSSL_ESPIDF + int argc = construct_argv(); + char** argv = (char**)__argv; +#endif +#ifndef WOLFSSL_BENCHMARK_ALL + int i; +#endif +#endif + + benchmark_static_init(); + +#ifndef MAIN_NO_ARGS + while (argc > 1) { + if (string_matches(argv[1], "-?")) { + if(--argc>1){ + lng_index = XATOI((++argv)[1]); + if(lng_index<0||lng_index>1) { + lng_index = 0; + } + } + Usage(); + return 0; + } + else if (string_matches(argv[1], "-v")) { + printf("-----------------------------------------------------------" + "-------------------\n wolfSSL version %s\n-----------------" + "-----------------------------------------------------------" + "--\n", LIBWOLFSSL_VERSION_STRING); + return 0; + } + else if (string_matches(argv[1], "-lng")) { + argc--; + argv++; + if(argc>1) { + lng_index = XATOI(argv[1]); + if(lng_index<0||lng_index>1){ + printf("invalid number(%d) is specified. [ :0-1]\n",lng_index); + lng_index = 0; + } + } + } + else if (string_matches(argv[1], "-base10")) + base2 = 0; +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + else if (string_matches(argv[1], "-no_aad")) + aesAuthAddSz = 0; +#endif + else if (string_matches(argv[1], "-dgst_full")) + digest_stream = 0; +#ifndef NO_RSA + else if (string_matches(argv[1], "-rsa_sign")) + rsa_sign_verify = 1; +#endif +#if !defined(NO_DH) && defined(HAVE_FFDHE_2048) + else if (string_matches(argv[1], "-ffdhe2048")) + use_ffdhe = 2048; +#endif +#if !defined(NO_DH) && defined(HAVE_FFDHE_3072) + else if (string_matches(argv[1], "-ffdhe3072")) + use_ffdhe = 3072; +#endif +#if defined(HAVE_ECC) && !defined(NO_ECC256) + else if (string_matches(argv[1], "-p256")) + bench_ecc_size = 32; +#endif +#if defined(HAVE_ECC) && defined(HAVE_ECC384) + else if (string_matches(argv[1], "-p384")) + bench_ecc_size = 48; +#endif +#ifdef BENCH_ASYM + else if (string_matches(argv[1], "-csv")) { + csv_format = 1; + csv_header_count = 1; + } +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + else if (string_matches(argv[1], "-threads")) { + argc--; + argv++; + if (argc > 1) { + g_threadCount = XATOI(argv[1]); + if (g_threadCount < 1 || lng_index > 128){ + printf("invalid number(%d) is specified. [ :1-128]\n", + g_threadCount); + g_threadCount = 0; + } + } + } +#endif + else if (string_matches(argv[1], "-print")) { + gPrintStats = 1; + } + 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(XATOI(argv[1])); + } + argc--; + argv++; + } +#endif /* MAIN_NO_ARGS */ + +#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; } + #endif +#endif /* !NO_CRYPT_BENCHMARK */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.h b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.h new file mode 100644 index 000000000..c2771bb59 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.h @@ -0,0 +1,111 @@ +/* wolfcrypt/benchmark/benchmark.h + * + * Copyright (C) 2006-2020 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 WOLFCRYPT_BENCHMARK_H +#define WOLFCRYPT_BENCHMARK_H + + +#ifdef __cplusplus + extern "C" { +#endif + +/* 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_aescfb(void); +void bench_aesofb(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_rsaKeyGen_size(int, int); +void bench_rsa(int); +void bench_rsa_key(int, 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_curve448KeyGen(void); +void bench_curve448KeyAgree(void); +void bench_ed448KeyGen(void); +void bench_ed448KeySign(void); +void bench_ntru(void); +void bench_ntruKeyGen(void); +void bench_rng(void); +void bench_blake2b(void); +void bench_blake2s(void); +void bench_pbkdf2(void); + +void bench_stats_print(void); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLFCRYPT_BENCHMARK_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.sln b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.sln index e3e9483b8..6c555724a 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.sln +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.sln @@ -2,17 +2,56 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C++ Express 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "benchmark", "benchmark.vcproj", "{615AEC46-5595-4DEA-9490-DBD5DE0F8772}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfssl", "..\..\wolfssl.vcxproj", "{73973223-5EE8-41CA-8E88-1D60E89A237B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + DLL Debug|Win32 = DLL Debug|Win32 + DLL Debug|x64 = DLL Debug|x64 + DLL Release|Win32 = DLL Release|Win32 + DLL Release|x64 = DLL Release|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.Debug|Win32.ActiveCfg = Debug|Win32 {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.Debug|Win32.Build.0 = Debug|Win32 + {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.Debug|x64.ActiveCfg = Debug|x64 + {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.Debug|x64.Build.0 = Debug|x64 + {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.DLL Debug|Win32.ActiveCfg = Debug|Win32 + {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.DLL Debug|Win32.Build.0 = Debug|Win32 + {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.DLL Debug|x64.ActiveCfg = Debug|x64 + {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.DLL Debug|x64.Build.0 = Debug|x64 + {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.DLL Release|Win32.ActiveCfg = Release|Win32 + {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.DLL Release|Win32.Build.0 = Release|Win32 + {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.DLL Release|x64.ActiveCfg = Release|x64 + {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.DLL Release|x64.Build.0 = Release|x64 {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.Release|Win32.ActiveCfg = Release|Win32 {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.Release|Win32.Build.0 = Release|Win32 + {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.Release|x64.ActiveCfg = Release|x64 + {615AEC46-5595-4DEA-9490-DBD5DE0F8772}.Release|x64.Build.0 = Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.ActiveCfg = Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.Build.0 = Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|x64.ActiveCfg = Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|x64.Build.0 = Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|x64.Build.0 = DLL Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.ActiveCfg = Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.Build.0 = Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|x64.ActiveCfg = Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.vcproj b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.vcproj index 5db23c372..86c58c985 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.vcproj +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/benchmark/benchmark.vcproj @@ -38,8 +38,8 @@ #endif #include +#include -#ifndef NO_AES +#if !defined(NO_AES) + +/* Tip: Locate the software cipher modes by searching for "Software AES" */ + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$g") + #pragma const_seg(".fipsB$g") + #endif +#endif #include +#include -#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_AesSetIV(Aes* aes, const byte* iv) -{ - return AesSetIV_fips(aes, iv); -} - - -int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - return AesCbcEncrypt_fips(aes, out, in, sz); -} - - -int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - return AesCbcDecrypt_fips(aes, out, in, sz); -} - - -int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, - const byte* key, word32 keySz, const byte* iv) -{ - return AesCbcDecryptWithKey(out, in, inSz, key, keySz, iv); -} - - -/* AES-CTR */ -#ifdef WOLFSSL_AES_COUNTER -void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - 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); -} - - -void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) -{ - AesDecryptDirect(aes, out, in); -} - - -int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, - const byte* iv, int dir) -{ - return AesSetKeyDirect(aes, key, len, iv, dir); -} +#ifdef WOLF_CRYPTO_CB + #include #endif -#ifdef HAVE_AESGCM -int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) -{ - return AesGcmSetKey_fips(aes, key, len); -} +/* fips wrapper calls, user can call direct */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + + 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; + } + + 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; + } + + 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; + } + + 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); + } + + #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 /* 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; + } + + 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 == 0 || ivSz > AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + 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 == 0 || ivSz > AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + 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) + { + 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; + } + + return GmacUpdate(gmac, iv, ivSz, authIn, authInSz, + authTag, authTagSz); + } + #endif /* HAVE_AESGCM */ + + /* AES-CCM */ + #if defined(HAVE_AESCCM) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) + { + return 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; + } + + #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) + { + + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) { + return BAD_FUNC_ARG; + } + + return AesCcmDecrypt(aes, out, in, inSz, nonce, nonceSz, + authTag, authTagSz, authIn, authInSz); + } + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AESCCM && HAVE_FIPS_VERSION 2 */ + + int wc_AesInit(Aes* aes, void* h, int i) + { + if (aes == NULL) + return BAD_FUNC_ARG; + + (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); */ + } + +#else /* else build without fips, or for FIPS v2 */ -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); -} - - -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); -} - - -int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) -{ - return GmacSetKey(gmac, key, len); -} - - -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); -} - -#endif /* HAVE_AESGCM */ -#ifdef HAVE_AESCCM -void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) -{ - AesCcmSetKey(aes, key, keySz); -} - - -void 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) -{ - AesCcmEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, - authIn, authInSz); -} - - -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_AESCCM */ - -#ifdef HAVE_CAVIUM -int wc_AesInitCavium(Aes* aes, int i) -{ - return AesInitCavium(aes, i); -} - - -void wc_AesFreeCavium(Aes* aes) -{ - AesFreeCavium(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 + +#if !defined(WOLFSSL_ARMASM) + +#ifdef WOLFSSL_IMX6_CAAM_BLOB + /* case of possibly not using hardware acceleration for AES but using key + blobs */ + #include +#endif + #ifdef DEBUG_AESNI #include #endif - #ifdef _MSC_VER /* 4127 warning constant while(1) */ #pragma warning(disable: 4127) #endif -#if defined(STM32F2_CRYPTO) - /* STM32F2 hardware AES support for CBC, CTR modes through the STM32F2 - * Standard Peripheral Library. Documentation located in STM32F2xx - * Standard Peripheral Library document (See note in README). - * NOTE: no support for AES-GCM/CCM/Direct */ - #include "stm32f2xx.h" - #include "stm32f2xx_cryp.h" +/* Define AES implementation includes and functions */ +#if defined(STM32_CRYPTO) + /* STM32F2/F4/F7/L4 hardware AES support for ECB, CBC, CTR and GCM modes */ + +#if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + int ret = 0; + #ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; + #else + CRYP_InitTypeDef cryptInit; + CRYP_KeyInitTypeDef keyInit; + #endif + + #ifdef WOLFSSL_STM32_CUBEMX + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; + + #ifdef STM32_CRYPTO_AES_ONLY + hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT; + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_ECB; + hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE; + #elif defined(STM32_HAL_V2) + hcryp.Init.Algorithm = CRYP_AES_ECB; + #endif + HAL_CRYP_Init(&hcryp); + + #ifdef STM32_CRYPTO_AES_ONLY + ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE, + outBlock, STM32_HAL_TIMEOUT); + #elif defined(STM32_HAL_V2) + ret = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)inBlock, AES_BLOCK_SIZE, + (uint32_t*)outBlock, STM32_HAL_TIMEOUT); + #else + ret = HAL_CRYP_AESECB_Encrypt(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE, + outBlock, STM32_HAL_TIMEOUT); + #endif + if (ret != HAL_OK) { + ret = WC_TIMEOUT_E; + } + HAL_CRYP_DeInit(&hcryp); + + #else /* STD_PERI_LIB */ + ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit); + if (ret != 0) + return ret; + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* setup key */ + CRYP_KeyInit(&keyInit); + + /* set direction and mode */ + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_ECB; + CRYP_Init(&cryptInit); + + /* 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; + } +#endif /* WOLFSSL_AES_DIRECT || HAVE_AESGCM || HAVE_AESCCM */ + +#ifdef HAVE_AES_DECRYPT + #if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESCCM) + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + int ret = 0; + #ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; + #else + CRYP_InitTypeDef cryptInit; + CRYP_KeyInitTypeDef keyInit; + #endif + + #ifdef WOLFSSL_STM32_CUBEMX + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; + + #ifdef STM32_CRYPTO_AES_ONLY + hcryp.Init.OperatingMode = CRYP_ALGOMODE_DECRYPT; + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_ECB; + hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE; + #elif defined(STM32_HAL_V2) + hcryp.Init.Algorithm = CRYP_AES_ECB; + #endif + HAL_CRYP_Init(&hcryp); + + #ifdef STM32_CRYPTO_AES_ONLY + ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE, + outBlock, STM32_HAL_TIMEOUT); + #elif defined(STM32_HAL_V2) + ret = HAL_CRYP_Decrypt(&hcryp, (uint32_t*)inBlock, AES_BLOCK_SIZE, + (uint32_t*)outBlock, STM32_HAL_TIMEOUT); + #else + ret = HAL_CRYP_AESECB_Decrypt(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE, + outBlock, STM32_HAL_TIMEOUT); + #endif + if (ret != HAL_OK) { + ret = WC_TIMEOUT_E; + } + HAL_CRYP_DeInit(&hcryp); + + #else /* STD_PERI_LIB */ + ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit); + if (ret != 0) + return ret; + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* set direction and key */ + CRYP_KeyInit(&keyInit); + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key; + CRYP_Init(&cryptInit); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + /* wait until decrypt key has been initialized */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + /* set direction and mode */ + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_ECB; + CRYP_Init(&cryptInit); + + /* 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; + } + #endif /* WOLFSSL_AES_DIRECT || HAVE_AESCCM */ +#endif /* HAVE_AES_DECRYPT */ + #elif defined(HAVE_COLDFIRE_SEC) /* Freescale Coldfire SEC support for CBC mode. * NOTE: no support for AES-CTR/GCM/CCM/Direct */ @@ -211,34 +475,453 @@ void wc_AesFreeCavium(Aes* aes) #include "sec.h" #include "mcf5475_sec.h" #include "mcf5475_siu.h" +#elif defined(FREESCALE_LTC) + #include "fsl_ltc.h" + #if defined(FREESCALE_LTC_AES_GCM) + #undef NEED_AES_TABLES + #undef GCM_TABLE + #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; + } + #endif #elif defined(FREESCALE_MMCAU) /* Freescale mmCAU hardware AES support for Direct, CBC, CCM, GCM modes * through the CAU/mmCAU library. Documentation located in * ColdFire/ColdFire+ CAU and Kinetis mmCAU Software Library User - * Guide (See note in README). - * NOTE: no support for AES-CTR */ - #include "cau_api.h" + * Guide (See note in README). */ + #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; + + #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) { + #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; + } + #ifdef HAVE_AES_DECRYPT + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + 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) { + #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) - #include - #include "cavium_common.h" - /* still leave SW crypto available */ + #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" + + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + 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_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES) + + #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h" + + #if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_DIRECT) + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + return wc_esp32AesEncrypt(aes, inBlock, outBlock); + } + #endif + + #if defined(HAVE_AES_DECRYPT) && defined(WOLFSSL_AES_DIRECT) + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + return wc_esp32AesDecrypt(aes, inBlock, outBlock); + } + #endif + +#elif defined(WOLFSSL_AESNI) + #define NEED_AES_TABLES - static int wc_AesCaviumSetKey(Aes* aes, const byte* key, word32 length, - const byte* iv); - static int wc_AesCaviumCbcEncrypt(Aes* aes, byte* out, const byte* in, - word32 length); - static int wc_AesCaviumCbcDecrypt(Aes* aes, byte* out, const byte* in, - word32 length); + /* 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 + + #ifdef _MSC_VER + #define XASM_LINK(f) + #elif defined(__APPLE__) + #define XASM_LINK(f) asm("_" f) + #else + #define XASM_LINK(f) asm(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 */ + +#elif (defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES)) || \ + ((defined(WOLFSSL_AFALG) || defined(WOLFSSL_DEVCRYPTO_AES)) && \ + defined(HAVE_AESCCM)) + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + wc_AesEncryptDirect(aes, outBlock, inBlock); + return 0; + } + +#elif defined(WOLFSSL_AFALG) +#elif defined(WOLFSSL_DEVCRYPTO_AES) + +#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES) + #include "hal_data.h" + + #ifndef WOLFSSL_SCE_AES256_HANDLE + #define WOLFSSL_SCE_AES256_HANDLE g_sce_aes_256 + #endif + + #ifndef WOLFSSL_SCE_AES192_HANDLE + #define WOLFSSL_SCE_AES192_HANDLE g_sce_aes_192 + #endif + + #ifndef WOLFSSL_SCE_AES128_HANDLE + #define WOLFSSL_SCE_AES128_HANDLE g_sce_aes_128 + #endif + + static int AES_ECB_encrypt(Aes* aes, const byte* inBlock, byte* outBlock, + int sz) + { + uint32_t ret; + + if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == + CRYPTO_WORD_ENDIAN_BIG) { + ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz); + } + + switch (aes->keylen) { + #ifdef WOLFSSL_AES_128 + case AES_128_KEY_SIZE: + ret = WOLFSSL_SCE_AES128_HANDLE.p_api->encrypt( + WOLFSSL_SCE_AES128_HANDLE.p_ctrl, aes->key, + NULL, (sz / sizeof(word32)), (word32*)inBlock, + (word32*)outBlock); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES_192_KEY_SIZE: + ret = WOLFSSL_SCE_AES192_HANDLE.p_api->encrypt( + WOLFSSL_SCE_AES192_HANDLE.p_ctrl, aes->key, + NULL, (sz / sizeof(word32)), (word32*)inBlock, + (word32*)outBlock); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES_256_KEY_SIZE: + ret = WOLFSSL_SCE_AES256_HANDLE.p_api->encrypt( + WOLFSSL_SCE_AES256_HANDLE.p_ctrl, aes->key, + NULL, (sz / sizeof(word32)), (word32*)inBlock, + (word32*)outBlock); + break; + #endif + default: + WOLFSSL_MSG("Unknown key size"); + return BAD_FUNC_ARG; + } + + if (ret != SSP_SUCCESS) { + /* revert input */ + ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz); + return WC_HW_E; + } + + if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == + CRYPTO_WORD_ENDIAN_BIG) { + ByteReverseWords((word32*)outBlock, (word32*)outBlock, sz); + if (inBlock != outBlock) { + /* revert input */ + ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz); + } + } + return 0; + } + + #if defined(HAVE_AES_DECRYPT) + static int AES_ECB_decrypt(Aes* aes, const byte* inBlock, byte* outBlock, + int sz) + { + uint32_t ret; + + if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == + CRYPTO_WORD_ENDIAN_BIG) { + ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz); + } + + switch (aes->keylen) { + #ifdef WOLFSSL_AES_128 + case AES_128_KEY_SIZE: + ret = WOLFSSL_SCE_AES128_HANDLE.p_api->decrypt( + WOLFSSL_SCE_AES128_HANDLE.p_ctrl, aes->key, aes->reg, + (sz / sizeof(word32)), (word32*)inBlock, + (word32*)outBlock); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES_192_KEY_SIZE: + ret = WOLFSSL_SCE_AES192_HANDLE.p_api->decrypt( + WOLFSSL_SCE_AES192_HANDLE.p_ctrl, aes->key, aes->reg, + (sz / sizeof(word32)), (word32*)inBlock, + (word32*)outBlock); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES_256_KEY_SIZE: + ret = WOLFSSL_SCE_AES256_HANDLE.p_api->decrypt( + WOLFSSL_SCE_AES256_HANDLE.p_ctrl, aes->key, aes->reg, + (sz / sizeof(word32)), (word32*)inBlock, + (word32*)outBlock); + break; + #endif + default: + WOLFSSL_MSG("Unknown key size"); + return BAD_FUNC_ARG; + } + if (ret != SSP_SUCCESS) { + return WC_HW_E; + } + + if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == + CRYPTO_WORD_ENDIAN_BIG) { + ByteReverseWords((word32*)outBlock, (word32*)outBlock, sz); + if (inBlock != outBlock) { + /* revert input */ + ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz); + } + } + + return 0; + } + + #endif + + #if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_DIRECT) + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + return AES_ECB_encrypt(aes, inBlock, outBlock, AES_BLOCK_SIZE); + } + #endif + + #if defined(HAVE_AES_DECRYPT) && defined(WOLFSSL_AES_DIRECT) + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + return AES_ECB_decrypt(aes, inBlock, outBlock, AES_BLOCK_SIZE); + } + #endif #else - /* using CTaoCrypt software AES implementation */ + + /* using wolfCrypt software implementation */ #define NEED_AES_TABLES -#endif /* STM32F2_CRYPTO */ +#endif + #ifdef NEED_AES_TABLES @@ -250,7 +933,8 @@ static const word32 rcon[] = { /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; -static const word32 Te[5][256] = { +#ifndef WOLFSSL_AES_SMALL_TABLES +static const word32 Te[4][256] = { { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, @@ -514,76 +1198,11 @@ static const word32 Te[5][256] = { 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, -}, -{ - 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, - 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, - 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, - 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, - 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, - 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, - 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, - 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, - 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, - 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, - 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, - 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, - 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, - 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, - 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, - 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, - 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, - 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, - 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, - 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, - 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, - 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, - 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, - 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, - 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, - 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, - 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, - 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, - 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, - 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, - 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, - 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, - 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, - 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, - 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, - 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, - 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, - 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, - 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, - 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, - 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, - 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, - 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, - 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, - 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, - 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, - 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, - 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, - 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, - 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, - 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, - 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, - 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, - 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, - 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, - 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, - 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, - 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, - 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, - 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, - 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, - 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, - 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, - 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, } }; -static const word32 Td[5][256] = { +#ifdef HAVE_AES_DECRYPT +static const word32 Td[4][256] = { { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, @@ -848,232 +1467,166 @@ static const word32 Td[5][256] = { 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, -}, -{ - 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, - 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, - 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, - 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, - 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, - 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, - 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, - 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, - 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, - 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, - 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, - 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, - 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, - 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, - 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, - 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, - 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, - 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, - 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, - 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, - 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, - 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, - 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, - 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, - 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, - 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, - 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, - 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, - 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, - 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, - 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, - 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, - 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, - 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, - 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, - 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, - 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, - 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, - 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, - 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, - 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, - 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, - 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, - 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, - 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, - 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, - 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, - 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, - 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, - 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, - 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, - 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, - 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, - 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, - 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, - 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, - 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, - 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, - 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, - 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, - 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, - 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, - 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, - 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, } }; +#endif /* HAVE_AES_DECRYPT */ +#endif + +#ifdef HAVE_AES_DECRYPT +#if (defined(HAVE_AES_CBC) && !defined(WOLFSSL_DEVCRYPTO_CBC)) \ + || defined(WOLFSSL_AES_DIRECT) +static const byte Td4[256] = +{ + 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, + 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, + 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, + 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, + 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, + 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, + 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, + 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, + 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, + 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, + 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, + 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, + 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, + 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, + 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, + 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, + 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, + 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, + 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, + 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, + 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, + 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, + 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, + 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, + 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, + 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, + 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, + 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, + 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, + 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, + 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, + 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, +}; +#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */ +#endif /* HAVE_AES_DECRYPT */ #define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y)))) -#ifdef WOLFSSL_AESNI +#ifdef WOLFSSL_AES_SMALL_TABLES +static const byte Tsbox[256] = { + 0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U, + 0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U, + 0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U, + 0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U, + 0xb7U, 0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU, + 0x34U, 0xa5U, 0xe5U, 0xf1U, 0x71U, 0xd8U, 0x31U, 0x15U, + 0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U, 0x9aU, + 0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U, + 0x09U, 0x83U, 0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U, + 0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U, 0xe3U, 0x2fU, 0x84U, + 0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU, + 0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU, + 0xd0U, 0xefU, 0xaaU, 0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U, + 0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU, 0x9fU, 0xa8U, + 0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U, + 0xbcU, 0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U, + 0xcdU, 0x0cU, 0x13U, 0xecU, 0x5fU, 0x97U, 0x44U, 0x17U, + 0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U, 0x73U, + 0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U, + 0x46U, 0xeeU, 0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU, + 0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U, 0x06U, 0x24U, 0x5cU, + 0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U, + 0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U, + 0x6cU, 0x56U, 0xf4U, 0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U, + 0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U, 0xb4U, 0xc6U, + 0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU, + 0x70U, 0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU, + 0x61U, 0x35U, 0x57U, 0xb9U, 0x86U, 0xc1U, 0x1dU, 0x9eU, + 0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU, 0x94U, + 0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU, + 0x8cU, 0xa1U, 0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U, + 0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U, 0x54U, 0xbbU, 0x16U +}; -/* 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 - */ +#define AES_XTIME(x) ((byte)((byte)((x) << 1) ^ ((0 - ((x) >> 7)) & 0x1b))) -#ifndef _MSC_VER +static word32 col_mul(word32 t, int i2, int i3, int ia, int ib) +{ + byte t3 = GETBYTE(t, i3); + byte tm = AES_XTIME(GETBYTE(t, i2) ^ t3); - #define cpuid(reg, func)\ - __asm__ __volatile__ ("cpuid":\ - "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ - "a" (func)); + return GETBYTE(t, ia) ^ GETBYTE(t, ib) ^ t3 ^ tm; +} - #define XASM_LINK(f) asm(f) +static word32 inv_col_mul(word32 t, int i9, int ib, int id, int ie) +{ + byte t9 = GETBYTE(t, i9); + byte tb = GETBYTE(t, ib); + byte td = GETBYTE(t, id); + byte te = GETBYTE(t, ie); + byte t0 = t9 ^ tb ^ td; + return t0 ^ AES_XTIME(AES_XTIME(AES_XTIME(t0 ^ te) ^ td ^ te) ^ tb ^ te); +} +#endif + +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM) + +#ifndef WC_CACHE_LINE_SZ + #if defined(__x86_64__) || defined(_M_X64) || \ + (defined(__ILP32__) && (__ILP32__ >= 1)) + #define WC_CACHE_LINE_SZ 64 + #else + /* default cache line size */ + #define WC_CACHE_LINE_SZ 32 + #endif +#endif + + +#ifndef WOLFSSL_AES_SMALL_TABLES +/* load 4 Te Tables into cache by cache line stride */ +static WC_INLINE word32 PreFetchTe(void) +{ + word32 x = 0; + int i,j; + + for (i = 0; i < 4; i++) { + /* 256 elements, each one is 4 bytes */ + for (j = 0; j < 256; j += WC_CACHE_LINE_SZ/4) { + x &= Te[i][j]; + } + } + return x; +} #else - - #include - #define cpuid(a,b) __cpuid((int*)a,b) - - #define XASM_LINK(f) - -#endif /* _MSC_VER */ - - -static int Check_CPU_support_AES(void) +/* load sbox into cache by cache line stride */ +static WC_INLINE word32 PreFetchSBox(void) { - unsigned int reg[4]; /* put a,b,c,d into 0,1,2,3 */ - cpuid(reg, 1); /* query info 1 */ + word32 x = 0; + int i; - if (reg[2] & 0x2000000) - return 1; - - return 0; + for (i = 0; i < 256; i += WC_CACHE_LINE_SZ/4) { + x &= Tsbox[i]; + } + return x; } +#endif -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 */ -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"); - - -void AES_CBC_decrypt(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_decrypt"); - -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"); - - -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"); - -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; -} - - -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 /* WOLFSSL_AESNI */ - - +/* Software AES - ECB Encrypt */ 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! */ + return; /* stop instead of seg-faulting, set up your keys! */ } + #ifdef WOLFSSL_AESNI if (haveAESNI && aes->use_aesni) { #ifdef DEBUG_AESNI @@ -1086,17 +1639,20 @@ 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, NULL, + 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, - aes->rounds); - XMEMCPY(outBlock, tmp, AES_BLOCK_SIZE); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + 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_align, AES_BLOCK_SIZE); + XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); return; #else WOLFSSL_MSG("AES-ECB encrypt with bad alignment"); @@ -1115,6 +1671,10 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) #endif } #endif +#if defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES) + AES_ECB_encrypt(aes, inBlock, outBlock, AES_BLOCK_SIZE); + return; +#endif /* * map byte array block to cipher state @@ -1125,46 +1685,50 @@ 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 + /* AddRoundKey */ s0 ^= rk[0]; s1 ^= rk[1]; s2 ^= rk[2]; s3 ^= rk[3]; +#ifndef WOLFSSL_AES_SMALL_TABLES + s0 |= PreFetchTe(); + /* * Nr - 1 full rounds: */ for (;;) { t0 = - Te[0][GETBYTE(s0, 3)] ^ - Te[1][GETBYTE(s1, 2)] ^ - Te[2][GETBYTE(s2, 1)] ^ - Te[3][GETBYTE(s3, 0)] ^ + Te[0][GETBYTE(s0, 3)] ^ + Te[1][GETBYTE(s1, 2)] ^ + Te[2][GETBYTE(s2, 1)] ^ + Te[3][GETBYTE(s3, 0)] ^ rk[4]; t1 = - Te[0][GETBYTE(s1, 3)] ^ - Te[1][GETBYTE(s2, 2)] ^ - Te[2][GETBYTE(s3, 1)] ^ - Te[3][GETBYTE(s0, 0)] ^ + Te[0][GETBYTE(s1, 3)] ^ + Te[1][GETBYTE(s2, 2)] ^ + Te[2][GETBYTE(s3, 1)] ^ + Te[3][GETBYTE(s0, 0)] ^ rk[5]; t2 = Te[0][GETBYTE(s2, 3)] ^ - Te[1][GETBYTE(s3, 2)] ^ - Te[2][GETBYTE(s0, 1)] ^ - Te[3][GETBYTE(s1, 0)] ^ + Te[1][GETBYTE(s3, 2)] ^ + Te[2][GETBYTE(s0, 1)] ^ + Te[3][GETBYTE(s1, 0)] ^ rk[6]; t3 = Te[0][GETBYTE(s3, 3)] ^ - Te[1][GETBYTE(s0, 2)] ^ - Te[2][GETBYTE(s1, 1)] ^ - Te[3][GETBYTE(s2, 0)] ^ + Te[1][GETBYTE(s0, 2)] ^ + Te[2][GETBYTE(s1, 1)] ^ + Te[3][GETBYTE(s2, 0)] ^ rk[7]; rk += 8; @@ -1204,44 +1768,158 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) */ s0 = - (Te[4][GETBYTE(t0, 3)] & 0xff000000) ^ - (Te[4][GETBYTE(t1, 2)] & 0x00ff0000) ^ - (Te[4][GETBYTE(t2, 1)] & 0x0000ff00) ^ - (Te[4][GETBYTE(t3, 0)] & 0x000000ff) ^ + (Te[2][GETBYTE(t0, 3)] & 0xff000000) ^ + (Te[3][GETBYTE(t1, 2)] & 0x00ff0000) ^ + (Te[0][GETBYTE(t2, 1)] & 0x0000ff00) ^ + (Te[1][GETBYTE(t3, 0)] & 0x000000ff) ^ rk[0]; s1 = - (Te[4][GETBYTE(t1, 3)] & 0xff000000) ^ - (Te[4][GETBYTE(t2, 2)] & 0x00ff0000) ^ - (Te[4][GETBYTE(t3, 1)] & 0x0000ff00) ^ - (Te[4][GETBYTE(t0, 0)] & 0x000000ff) ^ + (Te[2][GETBYTE(t1, 3)] & 0xff000000) ^ + (Te[3][GETBYTE(t2, 2)] & 0x00ff0000) ^ + (Te[0][GETBYTE(t3, 1)] & 0x0000ff00) ^ + (Te[1][GETBYTE(t0, 0)] & 0x000000ff) ^ rk[1]; s2 = - (Te[4][GETBYTE(t2, 3)] & 0xff000000) ^ - (Te[4][GETBYTE(t3, 2)] & 0x00ff0000) ^ - (Te[4][GETBYTE(t0, 1)] & 0x0000ff00) ^ - (Te[4][GETBYTE(t1, 0)] & 0x000000ff) ^ + (Te[2][GETBYTE(t2, 3)] & 0xff000000) ^ + (Te[3][GETBYTE(t3, 2)] & 0x00ff0000) ^ + (Te[0][GETBYTE(t0, 1)] & 0x0000ff00) ^ + (Te[1][GETBYTE(t1, 0)] & 0x000000ff) ^ rk[2]; s3 = - (Te[4][GETBYTE(t3, 3)] & 0xff000000) ^ - (Te[4][GETBYTE(t0, 2)] & 0x00ff0000) ^ - (Te[4][GETBYTE(t1, 1)] & 0x0000ff00) ^ - (Te[4][GETBYTE(t2, 0)] & 0x000000ff) ^ + (Te[2][GETBYTE(t3, 3)] & 0xff000000) ^ + (Te[3][GETBYTE(t0, 2)] & 0x00ff0000) ^ + (Te[0][GETBYTE(t1, 1)] & 0x0000ff00) ^ + (Te[1][GETBYTE(t2, 0)] & 0x000000ff) ^ rk[3]; +#else + s0 |= PreFetchSBox(); + + r *= 2; + /* Two rounds at a time */ + for (rk += 4; r > 1; r--, rk += 4) { + t0 = + ((word32)Tsbox[GETBYTE(s0, 3)] << 24) ^ + ((word32)Tsbox[GETBYTE(s1, 2)] << 16) ^ + ((word32)Tsbox[GETBYTE(s2, 1)] << 8) ^ + ((word32)Tsbox[GETBYTE(s3, 0)]); + t1 = + ((word32)Tsbox[GETBYTE(s1, 3)] << 24) ^ + ((word32)Tsbox[GETBYTE(s2, 2)] << 16) ^ + ((word32)Tsbox[GETBYTE(s3, 1)] << 8) ^ + ((word32)Tsbox[GETBYTE(s0, 0)]); + t2 = + ((word32)Tsbox[GETBYTE(s2, 3)] << 24) ^ + ((word32)Tsbox[GETBYTE(s3, 2)] << 16) ^ + ((word32)Tsbox[GETBYTE(s0, 1)] << 8) ^ + ((word32)Tsbox[GETBYTE(s1, 0)]); + t3 = + ((word32)Tsbox[GETBYTE(s3, 3)] << 24) ^ + ((word32)Tsbox[GETBYTE(s0, 2)] << 16) ^ + ((word32)Tsbox[GETBYTE(s1, 1)] << 8) ^ + ((word32)Tsbox[GETBYTE(s2, 0)]); + + s0 = + (col_mul(t0, 3, 2, 0, 1) << 24) ^ + (col_mul(t0, 2, 1, 0, 3) << 16) ^ + (col_mul(t0, 1, 0, 2, 3) << 8) ^ + (col_mul(t0, 0, 3, 2, 1) ) ^ + rk[0]; + s1 = + (col_mul(t1, 3, 2, 0, 1) << 24) ^ + (col_mul(t1, 2, 1, 0, 3) << 16) ^ + (col_mul(t1, 1, 0, 2, 3) << 8) ^ + (col_mul(t1, 0, 3, 2, 1) ) ^ + rk[1]; + s2 = + (col_mul(t2, 3, 2, 0, 1) << 24) ^ + (col_mul(t2, 2, 1, 0, 3) << 16) ^ + (col_mul(t2, 1, 0, 2, 3) << 8) ^ + (col_mul(t2, 0, 3, 2, 1) ) ^ + rk[2]; + s3 = + (col_mul(t3, 3, 2, 0, 1) << 24) ^ + (col_mul(t3, 2, 1, 0, 3) << 16) ^ + (col_mul(t3, 1, 0, 2, 3) << 8) ^ + (col_mul(t3, 0, 3, 2, 1) ) ^ + rk[3]; + } + + t0 = + ((word32)Tsbox[GETBYTE(s0, 3)] << 24) ^ + ((word32)Tsbox[GETBYTE(s1, 2)] << 16) ^ + ((word32)Tsbox[GETBYTE(s2, 1)] << 8) ^ + ((word32)Tsbox[GETBYTE(s3, 0)]); + t1 = + ((word32)Tsbox[GETBYTE(s1, 3)] << 24) ^ + ((word32)Tsbox[GETBYTE(s2, 2)] << 16) ^ + ((word32)Tsbox[GETBYTE(s3, 1)] << 8) ^ + ((word32)Tsbox[GETBYTE(s0, 0)]); + t2 = + ((word32)Tsbox[GETBYTE(s2, 3)] << 24) ^ + ((word32)Tsbox[GETBYTE(s3, 2)] << 16) ^ + ((word32)Tsbox[GETBYTE(s0, 1)] << 8) ^ + ((word32)Tsbox[GETBYTE(s1, 0)]); + t3 = + ((word32)Tsbox[GETBYTE(s3, 3)] << 24) ^ + ((word32)Tsbox[GETBYTE(s0, 2)] << 16) ^ + ((word32)Tsbox[GETBYTE(s1, 1)] << 8) ^ + ((word32)Tsbox[GETBYTE(s2, 0)]); + s0 = t0 ^ rk[0]; + s1 = t1 ^ rk[1]; + s2 = t2 ^ rk[2]; + s3 = t3 ^ rk[3]; +#endif /* 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_CBC || WOLFSSL_AES_DIRECT || HAVE_AESGCM */ + +#if defined(HAVE_AES_DECRYPT) +#if (defined(HAVE_AES_CBC) && !defined(WOLFSSL_DEVCRYPTO_CBC)) || \ + defined(WOLFSSL_AES_DIRECT) + +#ifndef WOLFSSL_AES_SMALL_TABLES +/* load 4 Td Tables into cache by cache line stride */ +static WC_INLINE word32 PreFetchTd(void) +{ + word32 x = 0; + int i,j; + + for (i = 0; i < 4; i++) { + /* 256 elements, each one is 4 bytes */ + for (j = 0; j < 256; j += WC_CACHE_LINE_SZ/4) { + x &= Td[i][j]; + } + } + return x; +} +#endif + +/* load Td Table4 into cache by cache line stride */ +static WC_INLINE word32 PreFetchTd4(void) +{ + word32 x = 0; + int i; + + for (i = 0; i < 256; i += WC_CACHE_LINE_SZ) { + x &= (word32)Td4[i]; + } + return x; } +/* Software AES - ECB Decrypt */ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) { word32 s0, s1, s2, s3; @@ -1251,7 +1929,7 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) const word32* rk = aes->key; if (r > 7 || r == 0) { WOLFSSL_MSG("AesDecrypt encountered improper key, set it up"); - return; /* stop instead of segfaulting, set up your keys! */ + return; /* stop instead of seg-faulting, set up your keys! */ } #ifdef WOLFSSL_AESNI if (haveAESNI && aes->use_aesni) { @@ -1265,7 +1943,8 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) #endif /* if input and output same will overwrite input iv */ - XMEMCPY(aes->tmp, inBlock, AES_BLOCK_SIZE); + if ((const byte*)aes->tmp != inBlock) + XMEMCPY(aes->tmp, inBlock, AES_BLOCK_SIZE); AES_ECB_decrypt(inBlock, outBlock, AES_BLOCK_SIZE, (byte*)aes->key, aes->rounds); return; @@ -1275,6 +1954,9 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) printf("Skipping AES-NI\n"); #endif } +#endif /* WOLFSSL_AESNI */ +#if defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES) + return AES_ECB_decrypt(aes, inBlock, outBlock, AES_BLOCK_SIZE); #endif /* @@ -1286,18 +1968,21 @@ 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]; s2 ^= rk[2]; s3 ^= rk[3]; +#ifndef WOLFSSL_AES_SMALL_TABLES + s0 |= PreFetchTd(); + /* * Nr - 1 full rounds: */ @@ -1362,70 +2047,170 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) * apply last round and * map cipher state to byte array block: */ + + t0 |= PreFetchTd4(); + s0 = - (Td[4][GETBYTE(t0, 3)] & 0xff000000) ^ - (Td[4][GETBYTE(t3, 2)] & 0x00ff0000) ^ - (Td[4][GETBYTE(t2, 1)] & 0x0000ff00) ^ - (Td[4][GETBYTE(t1, 0)] & 0x000000ff) ^ + ((word32)Td4[GETBYTE(t0, 3)] << 24) ^ + ((word32)Td4[GETBYTE(t3, 2)] << 16) ^ + ((word32)Td4[GETBYTE(t2, 1)] << 8) ^ + ((word32)Td4[GETBYTE(t1, 0)]) ^ rk[0]; s1 = - (Td[4][GETBYTE(t1, 3)] & 0xff000000) ^ - (Td[4][GETBYTE(t0, 2)] & 0x00ff0000) ^ - (Td[4][GETBYTE(t3, 1)] & 0x0000ff00) ^ - (Td[4][GETBYTE(t2, 0)] & 0x000000ff) ^ + ((word32)Td4[GETBYTE(t1, 3)] << 24) ^ + ((word32)Td4[GETBYTE(t0, 2)] << 16) ^ + ((word32)Td4[GETBYTE(t3, 1)] << 8) ^ + ((word32)Td4[GETBYTE(t2, 0)]) ^ rk[1]; s2 = - (Td[4][GETBYTE(t2, 3)] & 0xff000000) ^ - (Td[4][GETBYTE(t1, 2)] & 0x00ff0000) ^ - (Td[4][GETBYTE(t0, 1)] & 0x0000ff00) ^ - (Td[4][GETBYTE(t3, 0)] & 0x000000ff) ^ + ((word32)Td4[GETBYTE(t2, 3)] << 24) ^ + ((word32)Td4[GETBYTE(t1, 2)] << 16) ^ + ((word32)Td4[GETBYTE(t0, 1)] << 8) ^ + ((word32)Td4[GETBYTE(t3, 0)]) ^ rk[2]; s3 = - (Td[4][GETBYTE(t3, 3)] & 0xff000000) ^ - (Td[4][GETBYTE(t2, 2)] & 0x00ff0000) ^ - (Td[4][GETBYTE(t1, 1)] & 0x0000ff00) ^ - (Td[4][GETBYTE(t0, 0)] & 0x000000ff) ^ + ((word32)Td4[GETBYTE(t3, 3)] << 24) ^ + ((word32)Td4[GETBYTE(t2, 2)] << 16) ^ + ((word32)Td4[GETBYTE(t1, 1)] << 8) ^ + ((word32)Td4[GETBYTE(t0, 0)]) ^ rk[3]; +#else + s0 |= PreFetchTd4(); + + r *= 2; + for (rk += 4; r > 1; r--, rk += 4) { + t0 = + ((word32)Td4[GETBYTE(s0, 3)] << 24) ^ + ((word32)Td4[GETBYTE(s3, 2)] << 16) ^ + ((word32)Td4[GETBYTE(s2, 1)] << 8) ^ + ((word32)Td4[GETBYTE(s1, 0)]) ^ + rk[0]; + t1 = + ((word32)Td4[GETBYTE(s1, 3)] << 24) ^ + ((word32)Td4[GETBYTE(s0, 2)] << 16) ^ + ((word32)Td4[GETBYTE(s3, 1)] << 8) ^ + ((word32)Td4[GETBYTE(s2, 0)]) ^ + rk[1]; + t2 = + ((word32)Td4[GETBYTE(s2, 3)] << 24) ^ + ((word32)Td4[GETBYTE(s1, 2)] << 16) ^ + ((word32)Td4[GETBYTE(s0, 1)] << 8) ^ + ((word32)Td4[GETBYTE(s3, 0)]) ^ + rk[2]; + t3 = + ((word32)Td4[GETBYTE(s3, 3)] << 24) ^ + ((word32)Td4[GETBYTE(s2, 2)] << 16) ^ + ((word32)Td4[GETBYTE(s1, 1)] << 8) ^ + ((word32)Td4[GETBYTE(s0, 0)]) ^ + rk[3]; + + s0 = + (inv_col_mul(t0, 0, 2, 1, 3) << 24) ^ + (inv_col_mul(t0, 3, 1, 0, 2) << 16) ^ + (inv_col_mul(t0, 2, 0, 3, 1) << 8) ^ + (inv_col_mul(t0, 1, 3, 2, 0) ); + s1 = + (inv_col_mul(t1, 0, 2, 1, 3) << 24) ^ + (inv_col_mul(t1, 3, 1, 0, 2) << 16) ^ + (inv_col_mul(t1, 2, 0, 3, 1) << 8) ^ + (inv_col_mul(t1, 1, 3, 2, 0) ); + s2 = + (inv_col_mul(t2, 0, 2, 1, 3) << 24) ^ + (inv_col_mul(t2, 3, 1, 0, 2) << 16) ^ + (inv_col_mul(t2, 2, 0, 3, 1) << 8) ^ + (inv_col_mul(t2, 1, 3, 2, 0) ); + s3 = + (inv_col_mul(t3, 0, 2, 1, 3) << 24) ^ + (inv_col_mul(t3, 3, 1, 0, 2) << 16) ^ + (inv_col_mul(t3, 2, 0, 3, 1) << 8) ^ + (inv_col_mul(t3, 1, 3, 2, 0) ); + } + + t0 = + ((word32)Td4[GETBYTE(s0, 3)] << 24) ^ + ((word32)Td4[GETBYTE(s3, 2)] << 16) ^ + ((word32)Td4[GETBYTE(s2, 1)] << 8) ^ + ((word32)Td4[GETBYTE(s1, 0)]); + t1 = + ((word32)Td4[GETBYTE(s1, 3)] << 24) ^ + ((word32)Td4[GETBYTE(s0, 2)] << 16) ^ + ((word32)Td4[GETBYTE(s3, 1)] << 8) ^ + ((word32)Td4[GETBYTE(s2, 0)]); + t2 = + ((word32)Td4[GETBYTE(s2, 3)] << 24) ^ + ((word32)Td4[GETBYTE(s1, 2)] << 16) ^ + ((word32)Td4[GETBYTE(s0, 1)] << 8) ^ + ((word32)Td4[GETBYTE(s3, 0)]); + t3 = + ((word32)Td4[GETBYTE(s3, 3)] << 24) ^ + ((word32)Td4[GETBYTE(s2, 2)] << 16) ^ + ((word32)Td4[GETBYTE(s1, 1)] << 8) ^ + ((word32)Td4[GETBYTE(s0, 0)]); + s0 = t0 ^ rk[0]; + s1 = t1 ^ rk[1]; + s2 = t2 ^ rk[2]; + s3 = t3 ^ rk[3]; +#endif /* 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_CBC || WOLFSSL_AES_DIRECT */ +#endif /* HAVE_AES_DECRYPT */ #endif /* NEED_AES_TABLES */ + /* wc_AesSetKey */ -#ifdef STM32F2_CRYPTO - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) +#if defined(STM32_CRYPTO) + + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { - word32 *rk = aes->key; + word32 *rk; - if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) + (void)dir; + + if (aes == NULL || (keylen != 16 && + #ifdef WOLFSSL_AES_192 + keylen != 24 && + #endif + keylen != 32)) { return BAD_FUNC_ARG; + } + rk = aes->key; + aes->keylen = keylen; aes->rounds = keylen/4 + 6; XMEMCPY(rk, userKey, keylen); + #if !defined(WOLFSSL_STM32_CUBEMX) || defined(STM32_HAL_V2) ByteReverseWords(rk, rk, keylen); + #endif + #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \ + defined(WOLFSSL_AES_OFB) + aes->left = 0; + #endif return wc_AesSetIV(aes, iv); } - - int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, - const byte* iv, int dir) - { - return wc_AesSetKey(aes, userKey, keylen, iv, dir); - } + #if defined(WOLFSSL_AES_DIRECT) + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKey(aes, userKey, keylen, iv, dir); + } + #endif #elif defined(HAVE_COLDFIRE_SEC) #if defined (HAVE_THREADX) @@ -1447,30 +2232,30 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) 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 - InitMutex(&Mutex_AesSEC); + wc_InitMutex(&Mutex_AesSEC); } if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) @@ -1479,28 +2264,34 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) if (aes == NULL) return BAD_FUNC_ARG; + aes->keylen = keylen; aes->rounds = keylen/4 + 6; XMEMCPY(aes->key, userKey, keylen); if (iv) XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); + #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \ + defined(WOLFSSL_AES_OFB) + aes->left = 0; + #endif + return 0; } -#elif defined(FREESCALE_MMCAU) +#elif defined(FREESCALE_LTC) int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) { - byte *rk = (byte*)aes->key; - - if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) - return BAD_FUNC_ARG; - - if (rk == NULL) + if (aes == NULL || !((keylen == 16) || (keylen == 24) || (keylen == 32))) return BAD_FUNC_ARG; aes->rounds = keylen/4 + 6; - cau_aes_set_key(userKey, keylen*8, rk); + XMEMCPY(aes->key, userKey, keylen); + + #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \ + defined(WOLFSSL_AES_OFB) + aes->left = 0; + #endif return wc_AesSetIV(aes, iv); } @@ -1510,51 +2301,271 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) { 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 ret; + byte* rk; + byte* tmpKey = (byte*)userKey; + int tmpKeyDynamic = 0; + word32 alignOffset = 0; + + (void)dir; + + if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) + return BAD_FUNC_ARG; + if (aes == NULL) + return BAD_FUNC_ARG; + + rk = (byte*)aes->key; + if (rk == NULL) + return BAD_FUNC_ARG; + + #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \ + defined(WOLFSSL_AES_OFB) + aes->left = 0; + #endif + + aes->rounds = keylen/4 + 6; + + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)userKey % WOLFSSL_MMCAU_ALIGNMENT) { + #ifndef NO_WOLFSSL_ALLOC_ALIGN + byte* tmp = (byte*)XMALLOC(keylen + WOLFSSL_MMCAU_ALIGNMENT, + aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + alignOffset = WOLFSSL_MMCAU_ALIGNMENT - + ((wolfssl_word)tmp % WOLFSSL_MMCAU_ALIGNMENT); + tmpKey = tmp + alignOffset; + XMEMCPY(tmpKey, userKey, keylen); + tmpKeyDynamic = 1; + #else + WOLFSSL_MSG("Bad cau_aes_set_key alignment"); + return BAD_ALIGN_E; + #endif + } + #endif + + ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC + cau_aes_set_key(tmpKey, keylen*8, rk); + #else + MMCAU_AES_SetKey(tmpKey, keylen, rk); + #endif + wolfSSL_CryptHwMutexUnLock(); + + ret = wc_AesSetIV(aes, iv); + } + + if (tmpKeyDynamic == 1) { + XFREE(tmpKey - alignOffset, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + return ret; + } + + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + 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 ret; + + (void)dir; + (void)iv; + + if (aes == NULL || keylen != 16) + return BAD_FUNC_ARG; + + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + ret = nrf51_aes_set_key(userKey); + + #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \ + defined(WOLFSSL_AES_OFB) + aes->left = 0; + #endif + + return ret; + } + + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKey(aes, userKey, keylen, iv, dir); + } +#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES) + + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + (void)dir; + (void)iv; + + if (aes == NULL || (keylen != 16 && keylen != 24 && keylen != 32)) { + return BAD_FUNC_ARG; + } + + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + + XMEMCPY(aes->key, userKey, keylen); + #if defined(WOLFSSL_AES_COUNTER) + aes->left = 0; + #endif + return wc_AesSetIV(aes, iv); + } + + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKey(aes, userKey, keylen, iv, dir); + } +#elif defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES) + + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, + int dir) + { + SaSiError_t ret = SASI_OK; + SaSiAesIv_t iv_aes; + + if (aes == NULL || + (keylen != AES_128_KEY_SIZE && + keylen != AES_192_KEY_SIZE && + keylen != AES_256_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + #if defined(AES_MAX_KEY_SIZE) + if (keylen > (AES_MAX_KEY_SIZE/8)) { + return BAD_FUNC_ARG; + } + #endif + if (dir != AES_ENCRYPTION && + dir != AES_DECRYPTION) { + return BAD_FUNC_ARG; + } + + if (dir == AES_ENCRYPTION) { + aes->ctx.mode = SASI_AES_ENCRYPT; + SaSi_AesInit(&aes->ctx.user_ctx, + SASI_AES_ENCRYPT, + SASI_AES_MODE_CBC, + SASI_AES_PADDING_NONE); + } + else { + aes->ctx.mode = SASI_AES_DECRYPT; + SaSi_AesInit(&aes->ctx.user_ctx, + SASI_AES_DECRYPT, + SASI_AES_MODE_CBC, + SASI_AES_PADDING_NONE); + } + + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + XMEMCPY(aes->key, userKey, keylen); + + aes->ctx.key.pKey = (uint8_t*)aes->key; + aes->ctx.key.keySize= keylen; + + ret = SaSi_AesSetKey(&aes->ctx.user_ctx, + SASI_AES_USER_KEY, + &aes->ctx.key, + sizeof(aes->ctx.key)); + if (ret != SASI_OK) { + return BAD_FUNC_ARG; + } + + ret = wc_AesSetIV(aes, iv); + + if (iv) + XMEMCPY(iv_aes, iv, AES_BLOCK_SIZE); + else + XMEMSET(iv_aes, 0, AES_BLOCK_SIZE); + + + ret = SaSi_AesSetIv(&aes->ctx.user_ctx, iv_aes); + if (ret != SASI_OK) { + return ret; + } + return ret; + } + #if defined(WOLFSSL_AES_DIRECT) + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKey(aes, userKey, keylen, iv, dir); + } + #endif + +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ + +#elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */ + +#elif defined(WOLFSSL_DEVCRYPTO_AES) + /* implemented in wolfcrypt/src/port/devcrypto/devcrypto_aes.c */ + #else + + /* Software AES - SetKey */ 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 + #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \ + defined(WOLFSSL_AES_OFB) aes->left = 0; - #endif /* WOLFSSL_AES_COUNTER */ + #endif - 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) && \ + (!defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES)) + 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 - - switch(keylen) - { +#ifdef NEED_AES_TABLES + switch (keylen) { + #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 128 && \ + defined(WOLFSSL_AES_128) case 16: while (1) { temp = rk[3]; rk[4] = rk[0] ^ - (Te[4][GETBYTE(temp, 2)] & 0xff000000) ^ - (Te[4][GETBYTE(temp, 1)] & 0x00ff0000) ^ - (Te[4][GETBYTE(temp, 0)] & 0x0000ff00) ^ - (Te[4][GETBYTE(temp, 3)] & 0x000000ff) ^ + #ifndef WOLFSSL_AES_SMALL_TABLES + (Te[2][GETBYTE(temp, 2)] & 0xff000000) ^ + (Te[3][GETBYTE(temp, 1)] & 0x00ff0000) ^ + (Te[0][GETBYTE(temp, 0)] & 0x0000ff00) ^ + (Te[1][GETBYTE(temp, 3)] & 0x000000ff) ^ + #else + ((word32)Tsbox[GETBYTE(temp, 2)] << 24) ^ + ((word32)Tsbox[GETBYTE(temp, 1)] << 16) ^ + ((word32)Tsbox[GETBYTE(temp, 0)] << 8) ^ + ((word32)Tsbox[GETBYTE(temp, 3)]) ^ + #endif rcon[i]; rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; @@ -1564,17 +2575,27 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) rk += 4; } break; + #endif /* 128 */ + #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 192 && \ + defined(WOLFSSL_AES_192) case 24: /* for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack */ while (1) { temp = rk[ 5]; rk[ 6] = rk[ 0] ^ - (Te[4][GETBYTE(temp, 2)] & 0xff000000) ^ - (Te[4][GETBYTE(temp, 1)] & 0x00ff0000) ^ - (Te[4][GETBYTE(temp, 0)] & 0x0000ff00) ^ - (Te[4][GETBYTE(temp, 3)] & 0x000000ff) ^ + #ifndef WOLFSSL_AES_SMALL_TABLES + (Te[2][GETBYTE(temp, 2)] & 0xff000000) ^ + (Te[3][GETBYTE(temp, 1)] & 0x00ff0000) ^ + (Te[0][GETBYTE(temp, 0)] & 0x0000ff00) ^ + (Te[1][GETBYTE(temp, 3)] & 0x000000ff) ^ + #else + ((word32)Tsbox[GETBYTE(temp, 2)] << 24) ^ + ((word32)Tsbox[GETBYTE(temp, 1)] << 16) ^ + ((word32)Tsbox[GETBYTE(temp, 0)] << 8) ^ + ((word32)Tsbox[GETBYTE(temp, 3)]) ^ + #endif rcon[i]; rk[ 7] = rk[ 1] ^ rk[ 6]; rk[ 8] = rk[ 2] ^ rk[ 7]; @@ -1586,16 +2607,26 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) rk += 6; } break; + #endif /* 192 */ + #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 256 && \ + defined(WOLFSSL_AES_256) case 32: while (1) { temp = rk[ 7]; rk[ 8] = rk[ 0] ^ - (Te[4][GETBYTE(temp, 2)] & 0xff000000) ^ - (Te[4][GETBYTE(temp, 1)] & 0x00ff0000) ^ - (Te[4][GETBYTE(temp, 0)] & 0x0000ff00) ^ - (Te[4][GETBYTE(temp, 3)] & 0x000000ff) ^ + #ifndef WOLFSSL_AES_SMALL_TABLES + (Te[2][GETBYTE(temp, 2)] & 0xff000000) ^ + (Te[3][GETBYTE(temp, 1)] & 0x00ff0000) ^ + (Te[0][GETBYTE(temp, 0)] & 0x0000ff00) ^ + (Te[1][GETBYTE(temp, 3)] & 0x000000ff) ^ + #else + ((word32)Tsbox[GETBYTE(temp, 2)] << 24) ^ + ((word32)Tsbox[GETBYTE(temp, 1)] << 16) ^ + ((word32)Tsbox[GETBYTE(temp, 0)] << 8) ^ + ((word32)Tsbox[GETBYTE(temp, 3)]) ^ + #endif rcon[i]; rk[ 9] = rk[ 1] ^ rk[ 8]; rk[10] = rk[ 2] ^ rk[ 9]; @@ -1604,10 +2635,17 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) break; temp = rk[11]; rk[12] = rk[ 4] ^ - (Te[4][GETBYTE(temp, 3)] & 0xff000000) ^ - (Te[4][GETBYTE(temp, 2)] & 0x00ff0000) ^ - (Te[4][GETBYTE(temp, 1)] & 0x0000ff00) ^ - (Te[4][GETBYTE(temp, 0)] & 0x000000ff); + #ifndef WOLFSSL_AES_SMALL_TABLES + (Te[2][GETBYTE(temp, 3)] & 0xff000000) ^ + (Te[3][GETBYTE(temp, 2)] & 0x00ff0000) ^ + (Te[0][GETBYTE(temp, 1)] & 0x0000ff00) ^ + (Te[1][GETBYTE(temp, 0)] & 0x000000ff); + #else + ((word32)Tsbox[GETBYTE(temp, 3)] << 24) ^ + ((word32)Tsbox[GETBYTE(temp, 2)] << 16) ^ + ((word32)Tsbox[GETBYTE(temp, 1)] << 8) ^ + ((word32)Tsbox[GETBYTE(temp, 0)]); + #endif rk[13] = rk[ 5] ^ rk[12]; rk[14] = rk[ 6] ^ rk[13]; rk[15] = rk[ 7] ^ rk[14]; @@ -1615,13 +2653,14 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) rk += 8; } break; + #endif /* 256 */ default: return BAD_FUNC_ARG; - } + } /* switch */ - if (dir == AES_DECRYPTION) - { + #if defined(HAVE_AES_DECRYPT) + if (dir == AES_DECRYPTION) { unsigned int j; rk = aes->key; @@ -1632,78 +2671,169 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; } + #if !defined(WOLFSSL_AES_SMALL_TABLES) /* apply the inverse MixColumn transform to all round keys but the first and the last: */ for (i = 1; i < aes->rounds; i++) { rk += 4; rk[0] = - Td[0][Te[4][GETBYTE(rk[0], 3)] & 0xff] ^ - Td[1][Te[4][GETBYTE(rk[0], 2)] & 0xff] ^ - Td[2][Te[4][GETBYTE(rk[0], 1)] & 0xff] ^ - Td[3][Te[4][GETBYTE(rk[0], 0)] & 0xff]; + Td[0][Te[1][GETBYTE(rk[0], 3)] & 0xff] ^ + Td[1][Te[1][GETBYTE(rk[0], 2)] & 0xff] ^ + Td[2][Te[1][GETBYTE(rk[0], 1)] & 0xff] ^ + Td[3][Te[1][GETBYTE(rk[0], 0)] & 0xff]; rk[1] = - Td[0][Te[4][GETBYTE(rk[1], 3)] & 0xff] ^ - Td[1][Te[4][GETBYTE(rk[1], 2)] & 0xff] ^ - Td[2][Te[4][GETBYTE(rk[1], 1)] & 0xff] ^ - Td[3][Te[4][GETBYTE(rk[1], 0)] & 0xff]; + Td[0][Te[1][GETBYTE(rk[1], 3)] & 0xff] ^ + Td[1][Te[1][GETBYTE(rk[1], 2)] & 0xff] ^ + Td[2][Te[1][GETBYTE(rk[1], 1)] & 0xff] ^ + Td[3][Te[1][GETBYTE(rk[1], 0)] & 0xff]; rk[2] = - Td[0][Te[4][GETBYTE(rk[2], 3)] & 0xff] ^ - Td[1][Te[4][GETBYTE(rk[2], 2)] & 0xff] ^ - Td[2][Te[4][GETBYTE(rk[2], 1)] & 0xff] ^ - Td[3][Te[4][GETBYTE(rk[2], 0)] & 0xff]; + Td[0][Te[1][GETBYTE(rk[2], 3)] & 0xff] ^ + Td[1][Te[1][GETBYTE(rk[2], 2)] & 0xff] ^ + Td[2][Te[1][GETBYTE(rk[2], 1)] & 0xff] ^ + Td[3][Te[1][GETBYTE(rk[2], 0)] & 0xff]; rk[3] = - Td[0][Te[4][GETBYTE(rk[3], 3)] & 0xff] ^ - Td[1][Te[4][GETBYTE(rk[3], 2)] & 0xff] ^ - Td[2][Te[4][GETBYTE(rk[3], 1)] & 0xff] ^ - Td[3][Te[4][GETBYTE(rk[3], 0)] & 0xff]; + Td[0][Te[1][GETBYTE(rk[3], 3)] & 0xff] ^ + Td[1][Te[1][GETBYTE(rk[3], 2)] & 0xff] ^ + Td[2][Te[1][GETBYTE(rk[3], 1)] & 0xff] ^ + Td[3][Te[1][GETBYTE(rk[3], 0)] & 0xff]; } + #endif } + #else + (void)dir; + #endif /* HAVE_AES_DECRYPT */ + (void)temp; +#endif /* NEED_AES_TABLES */ + +#if defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES) + XMEMCPY((byte*)aes->key, userKey, keylen); + if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == CRYPTO_WORD_ENDIAN_BIG) { + ByteReverseWords(aes->key, aes->key, 32); + } +#endif 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) { + int ret; + #if defined(AES_MAX_KEY_SIZE) + const word32 max_key_len = (AES_MAX_KEY_SIZE / 8); + #endif - if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) + #ifdef WOLFSSL_IMX6_CAAM_BLOB + byte local[32]; + word32 localSz = 32; + + if (keylen == (16 + WC_CAAM_BLOB_SZ) || + keylen == (24 + WC_CAAM_BLOB_SZ) || + keylen == (32 + WC_CAAM_BLOB_SZ)) { + if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz) != 0) { + return BAD_FUNC_ARG; + } + + /* set local values */ + userKey = local; + keylen = localSz; + } + #endif + if (aes == NULL || + !((keylen == 16) || (keylen == 24) || (keylen == 32))) { return BAD_FUNC_ARG; + } - #ifdef HAVE_CAVIUM - if (aes->magic == WOLFSSL_AES_CAVIUM_MAGIC) - return wc_AesCaviumSetKey(aes, userKey, keylen, iv); + #if defined(AES_MAX_KEY_SIZE) + /* Check key length */ + if (keylen > max_key_len) { + return BAD_FUNC_ARG; + } + #endif + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + + #if defined(WOLF_CRYPTO_CB) || (defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))) || \ + (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)) + #ifdef WOLF_CRYPTO_CB + if (aes->devId != INVALID_DEVID) #endif + { + XMEMCPY(aes->devKey, userKey, keylen); + } + #endif - #ifdef WOLFSSL_AESNI + #ifdef WOLFSSL_AESNI if (checkAESNI == 0) { haveAESNI = Check_CPU_support_AES(); checkAESNI = 1; } if (haveAESNI) { + #if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \ + defined(WOLFSSL_AES_OFB) + aes->left = 0; + #endif /* WOLFSSL_AES_COUNTER */ aes->use_aesni = 1; if (iv) XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); + else + XMEMSET(aes->reg, 0, AES_BLOCK_SIZE); if (dir == AES_ENCRYPTION) return AES_set_encrypt_key(userKey, keylen * 8, aes); + #ifdef HAVE_AES_DECRYPT else return AES_set_decrypt_key(userKey, keylen * 8, aes); + #endif } - #endif /* WOLFSSL_AESNI */ + #endif /* WOLFSSL_AESNI */ - return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + + #if defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC)) + aes->ctx.cfd = -1; + #endif + #ifdef WOLFSSL_IMX6_CAAM_BLOB + ForceZero(local, sizeof(local)); + #endif + return ret; } #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) + { + int ret; - /* 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); - } + #ifdef WOLFSSL_IMX6_CAAM_BLOB + byte local[32]; + word32 localSz = 32; + if (keylen == (16 + WC_CAAM_BLOB_SZ) || + keylen == (24 + WC_CAAM_BLOB_SZ) || + keylen == (32 + WC_CAAM_BLOB_SZ)) { + if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz) + != 0) { + return BAD_FUNC_ARG; + } + + /* set local values */ + userKey = local; + keylen = localSz; + } + #endif + ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + + #ifdef WOLFSSL_IMX6_CAAM_BLOB + ForceZero(local, sizeof(local)); + #endif + + return ret; + } #endif /* WOLFSSL_AES_DIRECT || WOLFSSL_AES_COUNTER */ -#endif /* STM32F2_CRYPTO, wc_AesSetKey block */ +#endif /* wc_AesSetKey block */ /* wc_AesSetIV is shared between software and hardware */ @@ -1720,160 +2850,265 @@ int wc_AesSetIV(Aes* aes, const byte* iv) return 0; } - -int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, - const byte* key, word32 keySz, const byte* iv) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Aes* aes = NULL; -#else - Aes aes[1]; -#endif - -#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); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - - /* AES-DIRECT */ #if defined(WOLFSSL_AES_DIRECT) - #if defined(FREESCALE_MMCAU) + #if defined(HAVE_COLDFIRE_SEC) + #error "Coldfire SEC 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) { - byte* key; - key = (byte*)aes->key; + byte *key; + uint32_t keySize; - return cau_aes_encrypt(in, key, aes->rounds, out); + key = (byte*)aes->key; + wc_AesGetKeySize(aes, &keySize); + + LTC_AES_EncryptEcb(LTC_BASE, in, out, AES_BLOCK_SIZE, + key, keySize); } /* Allow direct access to one block decrypt */ void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) { - byte* key; - key = (byte*)aes->key; + byte *key; + uint32_t keySize; - return cau_aes_decrypt(in, key, aes->rounds, out); + key = (byte*)aes->key; + wc_AesGetKeySize(aes, &keySize); + + LTC_AES_DecryptEcb(LTC_BASE, in, out, AES_BLOCK_SIZE, + key, keySize, kLTC_EncryptKey); } - #elif defined(STM32F2_CRYPTO) - #error "STM32F2 crypto doesn't yet support AES direct" + #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ - #elif defined(HAVE_COLDFIRE_SEC) - #error "Coldfire SEC doesn't yet support AES direct" + #elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */ - #elif defined(WOLFSSL_PIC32MZ_CRYPT) - #error "PIC32MZ doesn't yet support AES direct" + #elif defined(WOLFSSL_DEVCRYPTO_AES) + /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */ + #elif defined(STM32_CRYPTO) + /* Allow direct access to one block encrypt */ + void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) + { + if (wolfSSL_CryptHwMutexLock() == 0) { + wc_AesEncrypt(aes, in, out); + wolfSSL_CryptHwMutexUnLock(); + } + } + #ifdef HAVE_AES_DECRYPT + /* Allow direct access to one block decrypt */ + void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) + { + if (wolfSSL_CryptHwMutexLock() == 0) { + wc_AesDecrypt(aes, in, out); + wolfSSL_CryptHwMutexUnLock(); + } + } + #endif /* HAVE_AES_DECRYPT */ + + #elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES) + + /* Allow direct access to one block encrypt */ + void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) + { + wc_AesEncrypt(aes, in, out); + } + #ifdef HAVE_AES_DECRYPT + /* Allow direct access to one block decrypt */ + void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) + { + wc_AesDecrypt(aes, in, out); + } + #endif /* HAVE_AES_DECRYPT */ #else /* Allow direct access to one block encrypt */ void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) { wc_AesEncrypt(aes, in, out); } - + #ifdef HAVE_AES_DECRYPT /* Allow direct access to one block decrypt */ void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) { wc_AesDecrypt(aes, in, out); } - - #endif /* FREESCALE_MMCAU, AES direct block */ + #endif /* HAVE_AES_DECRYPT */ + #endif /* AES direct block */ #endif /* WOLFSSL_AES_DIRECT */ /* AES-CBC */ -#ifdef STM32F2_CRYPTO +#ifdef HAVE_AES_CBC +#if defined(STM32_CRYPTO) + +#ifdef WOLFSSL_STM32_CUBEMX int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - word32 *enc_key, *iv; - CRYP_InitTypeDef AES_CRYP_InitStructure; - CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure; - CRYP_IVInitTypeDef AES_CRYP_IVInitStructure; + int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + CRYP_HandleTypeDef hcryp; - enc_key = aes->key; - iv = aes->reg; + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; - /* crypto structure initialization */ - CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure); - CRYP_StructInit(&AES_CRYP_InitStructure); - CRYP_IVStructInit(&AES_CRYP_IVInitStructure); + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + #ifdef STM32_CRYPTO_AES_ONLY + hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT; + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_CBC; + hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE; + #elif defined(STM32_HAL_V2) + hcryp.Init.Algorithm = CRYP_AES_CBC; + ByteReverseWords(aes->reg, aes->reg, AES_BLOCK_SIZE); + #endif + hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)aes->reg; + HAL_CRYP_Init(&hcryp); + + while (blocks--) { + #ifdef STM32_CRYPTO_AES_ONLY + ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE, + out, STM32_HAL_TIMEOUT); + #elif defined(STM32_HAL_V2) + ret = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)in, AES_BLOCK_SIZE, + (uint32_t*)out, STM32_HAL_TIMEOUT); + #else + ret = HAL_CRYP_AESCBC_Encrypt(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE, + out, STM32_HAL_TIMEOUT); + #endif + if (ret != HAL_OK) { + ret = WC_TIMEOUT_E; + break; + } + + /* 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; + } + + HAL_CRYP_DeInit(&hcryp); + + wolfSSL_CryptHwMutexUnLock(); + + return ret; + } + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + CRYP_HandleTypeDef hcryp; + + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; + + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + /* if input and output same will overwrite input iv */ + XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + #ifdef STM32_CRYPTO_AES_ONLY + hcryp.Init.OperatingMode = CRYP_ALGOMODE_KEYDERIVATION_DECRYPT; + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_CBC; + hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE; + #elif defined(STM32_HAL_V2) + hcryp.Init.Algorithm = CRYP_AES_CBC; + ByteReverseWords(aes->reg, aes->reg, AES_BLOCK_SIZE); + #endif + + hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)aes->reg; + HAL_CRYP_Init(&hcryp); + + while (blocks--) { + #ifdef STM32_CRYPTO_AES_ONLY + ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE, + out, STM32_HAL_TIMEOUT); + #elif defined(STM32_HAL_V2) + ret = HAL_CRYP_Decrypt(&hcryp, (uint32_t*)in, AES_BLOCK_SIZE, + (uint32_t*)out, STM32_HAL_TIMEOUT); + #else + ret = HAL_CRYP_AESCBC_Decrypt(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE, + out, STM32_HAL_TIMEOUT); + #endif + if (ret != HAL_OK) { + ret = WC_TIMEOUT_E; + break; + } + + /* store iv for next call */ + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + HAL_CRYP_DeInit(&hcryp); + wolfSSL_CryptHwMutexUnLock(); + + return ret; + } + #endif /* HAVE_AES_DECRYPT */ + +#else /* STD_PERI_LIB */ + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + int ret; + word32 *iv; + word32 blocks = (sz / AES_BLOCK_SIZE); + CRYP_InitTypeDef cryptInit; + CRYP_KeyInitTypeDef keyInit; + CRYP_IVInitTypeDef ivInit; + + ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit); + if (ret != 0) + return ret; + + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } /* 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 key */ + CRYP_KeyInit(&keyInit); /* set iv */ + iv = aes->reg; + CRYP_IVStructInit(&ivInit); 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]; - CRYP_IVInit(&AES_CRYP_IVInitStructure); + ivInit.CRYP_IV0Left = iv[0]; + ivInit.CRYP_IV0Right = iv[1]; + ivInit.CRYP_IV1Left = iv[2]; + ivInit.CRYP_IV1Right = iv[3]; + CRYP_IVInit(&ivInit); - /* set direction, mode, and datatype */ - AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; - AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC; - AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; - CRYP_Init(&AES_CRYP_InitStructure); + /* set direction and mode */ + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC; + CRYP_Init(&cryptInit); /* enable crypto processor */ CRYP_Cmd(ENABLE); - while (sz > 0) - { + while (blocks--) { /* flush IN/OUT FIFOs */ CRYP_FIFOFlush(); @@ -1883,7 +3118,7 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, 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(); @@ -1893,31 +3128,36 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, /* store iv for next call */ XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - sz -= 16; - in += 16; - out += 16; + sz -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; } /* disable crypto processor */ CRYP_Cmd(DISABLE); + wolfSSL_CryptHwMutexUnLock(); - return 0; + return ret; } + #ifdef HAVE_AES_DECRYPT int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - word32 *dec_key, *iv; - CRYP_InitTypeDef AES_CRYP_InitStructure; - CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure; - CRYP_IVInitTypeDef AES_CRYP_IVInitStructure; + int ret; + word32 *iv; + word32 blocks = (sz / AES_BLOCK_SIZE); + CRYP_InitTypeDef cryptInit; + CRYP_KeyInitTypeDef keyInit; + CRYP_IVInitTypeDef ivInit; - dec_key = aes->key; - iv = aes->reg; + ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit); + if (ret != 0) + return ret; - /* crypto structure initialization */ - CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure); - CRYP_StructInit(&AES_CRYP_InitStructure); - CRYP_IVStructInit(&AES_CRYP_IVInitStructure); + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } /* if input and output same will overwrite input iv */ XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); @@ -1925,76 +3165,37 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, /* 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 = dec_key[0]; - AES_CRYP_KeyInitStructure.CRYP_Key2Right = dec_key[1]; - AES_CRYP_KeyInitStructure.CRYP_Key3Left = dec_key[2]; - AES_CRYP_KeyInitStructure.CRYP_Key3Right = dec_key[3]; - break; - - case 12: /* 192-bit key */ - AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_192b; - AES_CRYP_KeyInitStructure.CRYP_Key1Left = dec_key[0]; - AES_CRYP_KeyInitStructure.CRYP_Key1Right = dec_key[1]; - AES_CRYP_KeyInitStructure.CRYP_Key2Left = dec_key[2]; - AES_CRYP_KeyInitStructure.CRYP_Key2Right = dec_key[3]; - AES_CRYP_KeyInitStructure.CRYP_Key3Left = dec_key[4]; - AES_CRYP_KeyInitStructure.CRYP_Key3Right = dec_key[5]; - break; - - case 14: /* 256-bit key */ - AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_256b; - AES_CRYP_KeyInitStructure.CRYP_Key0Left = dec_key[0]; - AES_CRYP_KeyInitStructure.CRYP_Key0Right = dec_key[1]; - AES_CRYP_KeyInitStructure.CRYP_Key1Left = dec_key[2]; - AES_CRYP_KeyInitStructure.CRYP_Key1Right = dec_key[3]; - AES_CRYP_KeyInitStructure.CRYP_Key2Left = dec_key[4]; - AES_CRYP_KeyInitStructure.CRYP_Key2Right = dec_key[5]; - AES_CRYP_KeyInitStructure.CRYP_Key3Left = dec_key[6]; - AES_CRYP_KeyInitStructure.CRYP_Key3Right = dec_key[7]; - break; - - default: - break; - } - - /* set direction, mode, and datatype for key preparation */ - AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; - AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key; - AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_32b; - CRYP_Init(&AES_CRYP_InitStructure); - CRYP_KeyInit(&AES_CRYP_KeyInitStructure); + /* set direction and key */ + CRYP_KeyInit(&keyInit); + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key; + CRYP_Init(&cryptInit); /* enable crypto processor */ 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; - AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC; - AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; - CRYP_Init(&AES_CRYP_InitStructure); + /* set direction and mode */ + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC; + CRYP_Init(&cryptInit); /* set iv */ + iv = aes->reg; + CRYP_IVStructInit(&ivInit); 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]; - CRYP_IVInit(&AES_CRYP_IVInitStructure); + ivInit.CRYP_IV0Left = iv[0]; + ivInit.CRYP_IV0Right = iv[1]; + ivInit.CRYP_IV1Left = iv[2]; + ivInit.CRYP_IV1Right = iv[3]; + CRYP_IVInit(&ivInit); /* enable crypto processor */ CRYP_Cmd(ENABLE); - while (sz > 0) - { + while (blocks--) { /* flush IN/OUT FIFOs */ CRYP_FIFOFlush(); @@ -2004,7 +3205,7 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, 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(); @@ -2014,24 +3215,26 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, /* store iv for next call */ XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); - sz -= 16; - in += 16; - out += 16; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; } /* disable crypto processor */ CRYP_Cmd(DISABLE); + wolfSSL_CryptHwMutexUnLock(); - return 0; + return ret; } + #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_STM32_CUBEMX */ #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; - #endif + #endif int size; volatile int v; @@ -2039,7 +3242,7 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, if ((pi == NULL) || (po == NULL)) return BAD_FUNC_ARG; /*wrong pointer*/ - LockMutex(&Mutex_AesSEC); + wc_LockMutex(&Mutex_AesSEC); /* Set descriptor for SEC */ secDesc->length1 = 0x0; @@ -2049,9 +3252,9 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, 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); @@ -2115,7 +3318,7 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, po += size; } - UnLockMutex(&Mutex_AesSEC); + wc_UnLockMutex(&Mutex_AesSEC); return 0; } @@ -2124,40 +3327,92 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, return (wc_AesCbcCrypt(aes, po, pi, sz, SEC_DESC_AES_CBC_ENCRYPT)); } + #ifdef HAVE_AES_DECRYPT int wc_AesCbcDecrypt(Aes* aes, byte* po, const byte* pi, word32 sz) { return (wc_AesCbcCrypt(aes, po, pi, sz, SEC_DESC_AES_CBC_DECRYPT)); } + #endif /* HAVE_AES_DECRYPT */ + +#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; + + status = wc_AesGetKeySize(aes, &keySize); + if (status != 0) { + return status; + } + + status = LTC_AES_EncryptCbc(LTC_BASE, in, out, blocks * AES_BLOCK_SIZE, + iv, enc_key, keySize); + + /* store iv for next call */ + if (status == kStatus_Success) { + XMEMCPY(iv, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + } + + return (status == kStatus_Success) ? 0 : -1; + } + + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + uint32_t keySize; + status_t status; + byte* iv, *dec_key; + word32 blocks = (sz / AES_BLOCK_SIZE); + byte temp_block[AES_BLOCK_SIZE]; + + iv = (byte*)aes->reg; + dec_key = (byte*)aes->key; + + status = wc_AesGetKeySize(aes, &keySize); + if (status != 0) { + return status; + } + + /* get IV for next call */ + XMEMCPY(temp_block, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + status = LTC_AES_DecryptCbc(LTC_BASE, in, out, blocks * AES_BLOCK_SIZE, + iv, dec_key, keySize, kLTC_EncryptKey); + + /* store IV for next call */ + if (status == kStatus_Success) { + XMEMCPY(iv, temp_block, AES_BLOCK_SIZE); + } + + return (status == kStatus_Success) ? 0 : -1; + } + #endif /* HAVE_AES_DECRYPT */ #elif defined(FREESCALE_MMCAU) int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { int i; int offset = 0; - int len = sz; - - byte *iv, *enc_key; + word32 blocks = (sz / AES_BLOCK_SIZE); + byte *iv; byte temp_block[AES_BLOCK_SIZE]; iv = (byte*)aes->reg; - enc_key = (byte*)aes->key; - if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { - WOLFSSL_MSG("Bad cau_aes_encrypt alignment"); - return BAD_ALIGN_E; - } - - while (len > 0) - { + while (blocks--) { XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE); /* XOR block with IV for CBC */ for (i = 0; i < AES_BLOCK_SIZE; i++) temp_block[i] ^= iv[i]; - cau_aes_encrypt(temp_block, enc_key, aes->rounds, out + offset); + wc_AesEncrypt(aes, temp_block, out + offset); - len -= AES_BLOCK_SIZE; offset += AES_BLOCK_SIZE; /* store IV for next block */ @@ -2166,29 +3421,21 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, return 0; } - + #ifdef HAVE_AES_DECRYPT int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { int i; int offset = 0; - int len = sz; - - byte* iv, *dec_key; + word32 blocks = (sz / AES_BLOCK_SIZE); + byte* iv; byte temp_block[AES_BLOCK_SIZE]; iv = (byte*)aes->reg; - dec_key = (byte*)aes->key; - if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { - WOLFSSL_MSG("Bad cau_aes_decrypt alignment"); - return BAD_ALIGN_E; - } - - while (len > 0) - { + while (blocks--) { XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE); - cau_aes_decrypt(in + offset, dec_key, aes->rounds, out + offset); + wc_AesDecrypt(aes, in + offset, out + offset); /* XOR block with IV for CBC */ for (i = 0; i < AES_BLOCK_SIZE; i++) @@ -2197,132 +3444,131 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, /* 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 ; - } + int ret; + /* hardware fails on input that is not a multiple of AES block size */ + if (sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + ret = wc_Pic32AesCrypt( + aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE, + out, in, sz, PIC32_ENCRYPTION, + PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC); + + /* store iv for next call */ + if (ret == 0) { + XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + } + + return ret; + } + #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 ; - } + int ret; + byte scratch[AES_BLOCK_SIZE]; + + /* hardware fails on input that is not a multiple of AES block size */ + if (sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + XMEMCPY(scratch, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + ret = wc_Pic32AesCrypt( + aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE, + out, in, sz, PIC32_DECRYPTION, + PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC); + + /* store iv for next call */ + if (ret == 0) { + XMEMCPY((byte*)aes->reg, scratch, AES_BLOCK_SIZE); + } + + return ret; + } + #endif /* HAVE_AES_DECRYPT */ +#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES) -#else int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - word32 blocks = sz / AES_BLOCK_SIZE; + return wc_esp32AesCbcEncrypt(aes, out, in, sz); + } + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return wc_esp32AesCbcDecrypt(aes, out, in, sz); + } +#elif defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES) + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return SaSi_AesBlock(&aes->ctx.user_ctx, (uint8_t* )in, sz, out); + } + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return SaSi_AesBlock(&aes->ctx.user_ctx, (uint8_t* )in, sz, out); + } +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ - #ifdef HAVE_CAVIUM - if (aes->magic == WOLFSSL_AES_CAVIUM_MAGIC) - return wc_AesCaviumCbcEncrypt(aes, out, in, sz); +#elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */ + +#elif defined(WOLFSSL_DEVCRYPTO_CBC) + /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */ + +#else + + /* Software AES - CBC Encrypt */ + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + word32 blocks = (sz / AES_BLOCK_SIZE); + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + #ifdef WOLF_CRYPTO_CB + if (aes->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_AesCbcEncrypt(aes, out, in, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } #endif + #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); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesCbcEncrypt(&aes->asyncDev, out, in, sz, + (const byte*)aes->devKey, aes->keylen, + (byte*)aes->reg, 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) { @@ -2337,22 +3583,25 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, #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, NULL, 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); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + 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 } @@ -2378,13 +3627,46 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, return 0; } + #ifdef HAVE_AES_DECRYPT + /* Software AES - CBC Decrypt */ int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - word32 blocks = sz / AES_BLOCK_SIZE; + word32 blocks; - #ifdef HAVE_CAVIUM - if (aes->magic == WOLFSSL_AES_CAVIUM_MAGIC) - return wc_AesCaviumCbcDecrypt(aes, out, in, sz); + if (aes == NULL || out == NULL || in == NULL + || sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + #ifdef WOLF_CRYPTO_CB + if (aes->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_AesCbcDecrypt(aes, out, in, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } + #endif + #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->devKey, aes->keylen, + (byte*)aes->reg, 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 #ifdef WOLFSSL_AESNI @@ -2401,18 +3683,28 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, /* if input and output same will overwrite input iv */ XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - AES_CBC_decrypt(in, out, (byte*)aes->reg, sz, (byte*)aes->key, + #if defined(WOLFSSL_AESNI_BY4) + AES_CBC_decrypt_by4(in, out, (byte*)aes->reg, sz, (byte*)aes->key, aes->rounds); + #elif defined(WOLFSSL_AESNI_BY6) + AES_CBC_decrypt_by6(in, out, (byte*)aes->reg, sz, (byte*)aes->key, + aes->rounds); + #else /* WOLFSSL_AESNI_BYx */ + AES_CBC_decrypt_by8(in, out, (byte*)aes->reg, sz, (byte*)aes->key, + aes->rounds); + #endif /* WOLFSSL_AESNI_BYx */ /* store iv for next call */ XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); return 0; } #endif + blocks = sz / AES_BLOCK_SIZE; while (blocks--) { XMEMCPY(aes->tmp, in, AES_BLOCK_SIZE); wc_AesDecrypt(aes, (byte*)aes->tmp, out); xorbuf(out, (byte*)aes->reg, AES_BLOCK_SIZE); + /* store iv for next call */ XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); out += AES_BLOCK_SIZE; @@ -2421,198 +3713,226 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, return 0; } + #endif -#endif /* STM32F2_CRYPTO, AES-CBC block */ +#endif /* AES-CBC block */ +#endif /* HAVE_AES_CBC */ /* AES-CTR */ -#ifdef WOLFSSL_AES_COUNTER +#if defined(WOLFSSL_AES_COUNTER) - #ifdef STM32F2_CRYPTO - 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) { - word32 *enc_key, *iv; - CRYP_InitTypeDef AES_CRYP_InitStructure; - CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure; - CRYP_IVInitTypeDef AES_CRYP_IVInitStructure; + int ret = 0; + #ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; + #ifdef STM32_HAL_V2 + word32 iv[AES_BLOCK_SIZE/sizeof(word32)]; + #endif + #else + word32 *iv; + CRYP_InitTypeDef cryptInit; + CRYP_KeyInitTypeDef keyInit; + CRYP_IVInitTypeDef ivInit; + #endif - enc_key = aes->key; - iv = aes->reg; + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } - /* crypto structure initialization */ - CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure); - CRYP_StructInit(&AES_CRYP_InitStructure); - CRYP_IVStructInit(&AES_CRYP_IVInitStructure); + #ifdef WOLFSSL_STM32_CUBEMX + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) { + wolfSSL_CryptHwMutexUnLock(); + return ret; + } + + #ifdef STM32_CRYPTO_AES_ONLY + hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT; + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_CTR; + hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE; + hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)aes->reg; + #elif defined(STM32_HAL_V2) + hcryp.Init.Algorithm = CRYP_AES_CTR; + ByteReverseWords(iv, aes->reg, AES_BLOCK_SIZE); + hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)iv; + #else + hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)aes->reg; + #endif + HAL_CRYP_Init(&hcryp); + + #ifdef STM32_CRYPTO_AES_ONLY + ret = HAL_CRYPEx_AES(&hcryp, (byte*)in, AES_BLOCK_SIZE, + out, STM32_HAL_TIMEOUT); + #elif defined(STM32_HAL_V2) + ret = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)in, AES_BLOCK_SIZE, + (uint32_t*)out, STM32_HAL_TIMEOUT); + #else + ret = HAL_CRYP_AESCTR_Encrypt(&hcryp, (byte*)in, AES_BLOCK_SIZE, + out, STM32_HAL_TIMEOUT); + #endif + if (ret != HAL_OK) { + ret = WC_TIMEOUT_E; + } + HAL_CRYP_DeInit(&hcryp); + + #else /* STD_PERI_LIB */ + ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit); + if (ret != 0) { + wolfSSL_CryptHwMutexUnLock(); + return ret; + } /* 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 key */ + CRYP_KeyInit(&keyInit); /* 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]; - CRYP_IVInit(&AES_CRYP_IVInitStructure); + iv = aes->reg; + CRYP_IVStructInit(&ivInit); + ivInit.CRYP_IV0Left = ByteReverseWord32(iv[0]); + ivInit.CRYP_IV0Right = ByteReverseWord32(iv[1]); + ivInit.CRYP_IV1Left = ByteReverseWord32(iv[2]); + ivInit.CRYP_IV1Right = ByteReverseWord32(iv[3]); + CRYP_IVInit(&ivInit); - /* set direction, mode, and datatype */ - AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; - AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CTR; - AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; - CRYP_Init(&AES_CRYP_InitStructure); + /* set direction and mode */ + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_CTR; + CRYP_Init(&cryptInit); /* 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 -= 16; - in += 16; - out += 16; - } + *(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 */ + + wolfSSL_CryptHwMutexUnLock(); + 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 flagment */ - 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 ; - } + #elif defined(WOLFSSL_PIC32MZ_CRYPT) + + #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_MMCAU) - #error "Freescale mmCAU doesn't currently support AES-CTR mode" + #elif defined(FREESCALE_LTC) + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + uint32_t keySize; + byte *iv, *enc_key; + 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--; + sz--; + } + + if (sz) { + iv = (byte*)aes->reg; + enc_key = (byte*)aes->key; + + wc_AesGetKeySize(aes, &keySize); + + LTC_AES_CryptCtr(LTC_BASE, in, out, sz, + iv, enc_key, keySize, (byte*)aes->tmp, + (uint32_t*)&aes->left); + } + + return 0; + } + + #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ + + #elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */ + + #elif defined(WOLFSSL_DEVCRYPTO_AES) + /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */ + + #elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES) + /* esp32 doesn't support CRT mode by hw. */ + /* use aes ecnryption plus sw implementation */ + #define NEED_AES_CTR_SOFT #else - /* Increment AES counter */ - static INLINE void IncrementAesCounter(byte* inOutCtr) - { - int i; + /* Use software based AES counter */ + #define NEED_AES_CTR_SOFT + #endif + + #ifdef NEED_AES_CTR_SOFT + /* Increment AES counter */ + static WC_INLINE void IncrementAesCounter(byte* inOutCtr) + { /* 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) + /* Software AES - CTR Encrypt */ + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - byte* tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + byte* tmp; + byte scratch[AES_BLOCK_SIZE]; + + 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--; @@ -2621,17 +3941,23 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, /* do as many block size ops as possible */ while (sz >= AES_BLOCK_SIZE) { - wc_AesEncrypt(aes, (byte*)aes->reg, out); + #ifdef XTRANSFORM_AESCTRBLOCK + XTRANSFORM_AESCTRBLOCK(aes, out, in); + #else + wc_AesEncrypt(aes, (byte*)aes->reg, scratch); + xorbuf(scratch, in, AES_BLOCK_SIZE); + XMEMCPY(out, scratch, AES_BLOCK_SIZE); + #endif IncrementAesCounter((byte*)aes->reg); - xorbuf(out, in, AES_BLOCK_SIZE); out += AES_BLOCK_SIZE; in += AES_BLOCK_SIZE; sz -= AES_BLOCK_SIZE; aes->left = 0; } + ForceZero(scratch, AES_BLOCK_SIZE); - /* handle non block size remaining and sotre unused byte count in left */ + /* handle non block size remaining and store unused byte count in left */ if (sz) { wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->tmp); IncrementAesCounter((byte*)aes->reg); @@ -2644,49 +3970,63 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, aes->left--; } } + + return 0; } - #endif /* STM32F2_CRYPTO, AES-CTR block */ + #endif /* NEED_AES_CTR_SOFT */ #endif /* WOLFSSL_AES_COUNTER */ +#endif /* !WOLFSSL_ARMASM */ + + +/* + * The IV for AES GCM and CCM, stored in struct Aes's member reg, is comprised + * of two parts in order: + * 1. The fixed field which may be 0 or 4 bytes long. In TLS, this is set + * to the implicit IV. + * 2. The explicit IV is generated by wolfCrypt. It needs to be managed + * by wolfCrypt to ensure the IV is unique for each call to encrypt. + * The IV may be a 96-bit random value, or the 32-bit fixed value and a + * 64-bit set of 0 or random data. The final 32-bits of reg is used as a + * block counter during the encryption. + */ + +#if (defined(HAVE_AESGCM) && !defined(WC_NO_RNG)) || defined(HAVE_AESCCM) +static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz) +{ + int i; + for (i = ctrSz-1; i >= 0; i--) { + if (++ctr[i]) + break; + } +} +#endif /* HAVE_AESGCM || HAVE_AESCCM */ + #ifdef HAVE_AESGCM -/* - * The IV for AES GCM, stored in struct Aes's member reg, is comprised of - * three parts in order: - * 1. The implicit IV. This is generated from the PRF using the shared - * secrets between endpoints. It is 4 bytes long. - * 2. The explicit IV. This is set by the user of the AES. It needs to be - * unique for each call to encrypt. The explicit IV is shared with the - * other end of the transaction in the clear. - * 3. The counter. Each block of data is encrypted with its own sequence - * number counter. - */ - -#ifdef STM32F2_CRYPTO - #error "STM32F2 crypto doesn't currently support AES-GCM mode" - -#elif defined(HAVE_COLDFIRE_SEC) +#if defined(HAVE_COLDFIRE_SEC) #error "Coldfire SEC doesn't currently support AES-GCM mode" +#elif defined(WOLFSSL_NRF51_AES) + #error "nRF51 doesn't currently support AES-GCM mode" + #endif -enum { - CTR_SZ = 4 -}; +#ifdef WOLFSSL_ARMASM + /* implementation is located in wolfcrypt/src/port/arm/armv8-aes.c */ +#elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/afalg/afalg_aes.c */ -static INLINE void InitGcmCounter(byte* inOutCtr) -{ - inOutCtr[AES_BLOCK_SIZE - 4] = 0; - inOutCtr[AES_BLOCK_SIZE - 3] = 0; - inOutCtr[AES_BLOCK_SIZE - 2] = 0; - inOutCtr[AES_BLOCK_SIZE - 1] = 1; -} +#elif defined(WOLFSSL_DEVCRYPTO_AES) + /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */ +#else /* software + AESNI implementation */ -static INLINE void IncrementGcmCounter(byte* inOutCtr) +#if !defined(FREESCALE_LTC_AES_GCM) +static WC_INLINE void IncrementGcmCounter(byte* inOutCtr) { int i; @@ -2696,11 +4036,23 @@ static INLINE void IncrementGcmCounter(byte* inOutCtr) return; } } +#ifdef STM32_CRYPTO_AES_GCM +static WC_INLINE void DecrementGcmCounter(byte* inOutCtr) +{ + int i; + /* in network byte order so start at end and work back */ + for (i = AES_BLOCK_SIZE - 1; i >= AES_BLOCK_SIZE - CTR_SZ; i--) { + if (--inOutCtr[i] != 0xFF) /* we're done unless we underflow */ + return; + } +} +#endif /* STM32_CRYPTO_AES_GCM */ +#endif /* !FREESCALE_LTC_AES_GCM */ #if defined(GCM_SMALL) || defined(GCM_TABLE) -static INLINE void FlattenSzInBits(byte* buf, word32 sz) +static WC_INLINE void FlattenSzInBits(byte* buf, word32 sz) { /* Multiply the sz by 8 */ word32 szHi = (sz >> (8*sizeof(sz) - 3)); @@ -2718,7 +4070,7 @@ static INLINE void FlattenSzInBits(byte* buf, word32 sz) } -static INLINE void RIGHTSHIFTX(byte* x) +static WC_INLINE void RIGHTSHIFTX(byte* x) { int i; int carryOut = 0; @@ -2762,39 +4114,1250 @@ static void GenerateM0(Aes* aes) #endif /* GCM_TABLE */ - +/* Software AES - GCM SetKey */ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) { int ret; byte iv[AES_BLOCK_SIZE]; - #ifdef FREESCALE_MMCAU - byte* rk = (byte*)aes->key; + #ifdef WOLFSSL_IMX6_CAAM_BLOB + byte local[32]; + word32 localSz = 32; + + if (len == (16 + WC_CAAM_BLOB_SZ) || + len == (24 + WC_CAAM_BLOB_SZ) || + len == (32 + WC_CAAM_BLOB_SZ)) { + if (wc_caamOpenBlob((byte*)key, len, local, &localSz) != 0) { + return BAD_FUNC_ARG; + } + + /* set local values */ + key = local; + len = localSz; + } #endif if (!((len == 16) || (len == 24) || (len == 32))) return BAD_FUNC_ARG; +#ifdef OPENSSL_EXTRA + if (aes != NULL) { + XMEMSET(aes->aadH, 0, sizeof(aes->aadH)); + aes->aadLen = 0; + } +#endif XMEMSET(iv, 0, AES_BLOCK_SIZE); ret = wc_AesSetKey(aes, key, len, iv, AES_ENCRYPTION); + #ifdef WOLFSSL_AESNI + /* AES-NI code generates its own H value. */ + if (haveAESNI) + return ret; + #endif /* WOLFSSL_AESNI */ + +#if !defined(FREESCALE_LTC_AES_GCM) if (ret == 0) { - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(iv, rk, aes->rounds, aes->H); - #else wc_AesEncrypt(aes, iv, aes->H); - #endif #ifdef GCM_TABLE GenerateM0(aes); #endif /* GCM_TABLE */ } +#endif /* FREESCALE_LTC_AES_GCM */ + +#if defined(WOLFSSL_XILINX_CRYPT) + wc_AesGcmSetKey_ex(aes, key, len, XSECURE_CSU_AES_KEY_SRC_KUP); +#elif defined(WOLFSSL_AFALG_XILINX_AES) + wc_AesGcmSetKey_ex(aes, key, len, 0); +#endif + +#ifdef WOLF_CRYPTO_CB + if (aes->devId != INVALID_DEVID) { + XMEMCPY(aes->devKey, key, len); + } +#endif + +#ifdef WOLFSSL_IMX6_CAAM_BLOB + ForceZero(local, sizeof(local)); +#endif return ret; } -#if defined(GCM_SMALL) +#ifdef WOLFSSL_AESNI +#if defined(USE_INTEL_SPEEDUP) + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 +#endif /* USE_INTEL_SPEEDUP */ + +#ifndef _MSC_VER + +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, + unsigned int tbytes, const unsigned char* key, int nr) + XASM_LINK("AES_GCM_encrypt"); +#ifdef HAVE_INTEL_AVX1 +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, + unsigned int tbytes, const unsigned char* key, + int nr) + XASM_LINK("AES_GCM_encrypt_avx1"); +#ifdef HAVE_INTEL_AVX2 +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, + unsigned int tbytes, const unsigned char* key, + int nr) + XASM_LINK("AES_GCM_encrypt_avx2"); +#endif /* HAVE_INTEL_AVX2 */ +#endif /* HAVE_INTEL_AVX1 */ + +#ifdef HAVE_AES_DECRYPT +void 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, int tbytes, const unsigned char* key, int nr, + int* res) + XASM_LINK("AES_GCM_decrypt"); +#ifdef HAVE_INTEL_AVX1 +void 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, int tbytes, const unsigned char* key, + int nr, int* res) + XASM_LINK("AES_GCM_decrypt_avx1"); +#ifdef HAVE_INTEL_AVX2 +void 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, int tbytes, const unsigned char* key, + int nr, int* res) + XASM_LINK("AES_GCM_decrypt_avx2"); +#endif /* HAVE_INTEL_AVX2 */ +#endif /* HAVE_INTEL_AVX1 */ +#endif /* HAVE_AES_DECRYPT */ + +#else /* _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) } + +static const __m128i MOD2_128 = + M128_INIT(0x1, (long long int)0xc200000000000000UL); + + +/* 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 */ + + +/* Figure 9. AES-GCM – Encrypt With Single Block Ghash at a Time */ + +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); + + +/* The following are for MSC based builds which do not allow + * inline assembly. Intrinsic functions are used instead. */ + +#define aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T) \ +do \ +{ \ + word32 iv12[4]; \ + iv12[0] = *(word32*)&ivec[0]; \ + iv12[1] = *(word32*)&ivec[4]; \ + iv12[2] = *(word32*)&ivec[8]; \ + iv12[3] = 0x01000000; \ + Y = _mm_loadu_si128((__m128i*)iv12); \ + \ + /* (Compute E[ZERO, KS] and E[Y0, KS] together */ \ + tmp1 = _mm_load_si128(&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) \ +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_load_si128(&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); + + +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 + + +static 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, + unsigned int tbytes, + 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(); + __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 == GCM_NONCE_MID_SZ) + aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T); + else + aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T); + + 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); + +#ifndef AES_GCM_AESNI_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]); + + 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]); + 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]; + } + } + 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); + 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++) { + 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); + X = gfmul_shifted(X, H); + } +#else /* AES_GCM_AESNI_NO_UNROLL */ + 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 /* AES_GCM_AESNI_NO_UNROLL */ + + /* 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);*/ + XMEMCPY(tag, &T, tbytes); +} + +#ifdef HAVE_AES_DECRYPT + +static void 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, word32 tbytes, const unsigned char* key, + int nr, int* res) +{ + 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(); + __m128i tmp1, tmp2, XV; +#ifndef AES_GCM_AESNI_NO_UNROLL + __m128i HT[8]; + __m128i r0, r1; + __m128i tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; +#endif /* AES_GCM_AESNI_NO_UNROLL */ + + if (ibytes == GCM_NONCE_MID_SZ) + aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T); + else + aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T); + + 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 /* AES_GCM_AESNI_NO_UNROLL */ + + 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[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); + /* 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)))) */ + if (XMEMCMP(tag, &T, tbytes) != 0) + *res = 0; /* in case the authentication failed */ + else + *res = 1; /* when successful returns 1 */ +} + +#endif /* HAVE_AES_DECRYPT */ +#endif /* _MSC_VER */ +#endif /* WOLFSSL_AESNI */ + + +#if defined(GCM_SMALL) static void GMULT(byte* X, byte* Y) { byte Z[AES_BLOCK_SIZE]; @@ -2820,8 +5383,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]; @@ -2969,8 +5532,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]; @@ -3025,12 +5588,13 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, /* end GCM_TABLE */ #elif defined(WORD64_AVAILABLE) && !defined(GCM_WORD32) +#if !defined(FREESCALE_LTC_AES_GCM) 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++) { @@ -3044,13 +5608,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; @@ -3061,8 +5627,8 @@ static void GMULT(word64* X, word64* 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) { word64 x[2] = {0,0}; word32 blocks, partial; @@ -3070,7 +5636,7 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE); #ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords64(bigH, bigH, AES_BLOCK_SIZE); + ByteReverseWords64(bigH, bigH, AES_BLOCK_SIZE); #endif /* Hash in A, the Additional Authentication Data */ @@ -3098,6 +5664,13 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, x[1] ^= bigA[1]; GMULT(x, bigH); } +#ifdef OPENSSL_EXTRA + /* store AAD partial tag for next call */ + aes->aadH[0] = (word32)((x[0] & 0xFFFFFFFF00000000) >> 32); + aes->aadH[1] = (word32)(x[0] & 0xFFFFFFFF); + aes->aadH[2] = (word32)((x[1] & 0xFFFFFFFF00000000) >> 32); + aes->aadH[3] = (word32)(x[1] & 0xFFFFFFFF); +#endif } /* Hash in C, the Ciphertext */ @@ -3105,6 +5678,13 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, word64 bigC[2]; blocks = cSz / AES_BLOCK_SIZE; partial = cSz % AES_BLOCK_SIZE; +#ifdef OPENSSL_EXTRA + /* Start from last AAD partial tag */ + if(aes->aadLen) { + x[0] = ((word64)aes->aadH[0]) << 32 | aes->aadH[1]; + x[1] = ((word64)aes->aadH[2]) << 32 | aes->aadH[3]; + } +#endif while (blocks--) { XMEMCPY(bigC, c, AES_BLOCK_SIZE); #ifdef LITTLE_ENDIAN_ORDER @@ -3129,9 +5709,12 @@ 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; +#ifdef OPENSSL_EXTRA + if (aes->aadLen) + len[0] = (word64)aes->aadLen; +#endif /* Lengths are in bytes. Convert to bits. */ len[0] *= 8; len[1] *= 8; @@ -3145,6 +5728,7 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, #endif XMEMCPY(s, x, sSz); } +#endif /* !FREESCALE_LTC_AES_GCM */ /* end defined(WORD64_AVAILABLE) && !defined(GCM_WORD32) */ #else /* GCM_WORD32 */ @@ -3152,7 +5736,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]; @@ -3197,8 +5781,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; @@ -3296,165 +5880,1071 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, #endif /* end GCM_WORD32 */ +#if !defined(WOLFSSL_XILINX_CRYPT) && !defined(WOLFSSL_AFALG_XILINX_AES) +#ifdef FREESCALE_LTC_AES_GCM 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) { + status_t status; + word32 keySize; + + /* argument checks */ + if (aes == NULL || authTagSz > AES_BLOCK_SIZE || ivSz == 0) { + return BAD_FUNC_ARG; + } + + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + + status = wc_AesGetKeySize(aes, &keySize); + if (status) + return status; + + status = LTC_AES_EncryptTagGcm(LTC_BASE, in, out, sz, iv, ivSz, + authIn, authInSz, (byte*)aes->key, keySize, authTag, authTagSz); + + return (status == kStatus_Success) ? 0 : AES_GCM_AUTH_E; +} + +#else + +#ifdef STM32_CRYPTO_AES_GCM + +/* this function supports inline encrypt */ +static int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret; +#ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; +#else + word32 keyCopy[AES_256_KEY_SIZE/sizeof(word32)]; +#endif + word32 keySize; + int status = HAL_OK; + word32 blocks = sz / AES_BLOCK_SIZE; + word32 partial = sz % AES_BLOCK_SIZE; + byte tag[AES_BLOCK_SIZE]; + byte partialBlock[AES_BLOCK_SIZE]; + byte ctr[AES_BLOCK_SIZE]; + byte* authInPadded = NULL; + int authPadSz; + + ret = wc_AesGetKeySize(aes, &keySize); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_STM32_CUBEMX + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; +#endif + + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + XMEMSET(ctr, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(ctr, iv, ivSz); + ctr[AES_BLOCK_SIZE - 1] = 1; + } + else { + GHASH(aes, NULL, 0, iv, ivSz, ctr, AES_BLOCK_SIZE); + } + /* Hardware requires counter + 1 */ + IncrementGcmCounter(ctr); + + if (authInSz == 0 || (authInSz % AES_BLOCK_SIZE) != 0) { + /* Need to pad the AAD to a full block with zeros. */ + authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; + authInPadded = (byte*)XMALLOC(authPadSz, aes->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (authInPadded == NULL) { + wolfSSL_CryptHwMutexUnLock(); + return MEMORY_E; + } + XMEMSET(authInPadded, 0, authPadSz); + XMEMCPY(authInPadded, authIn, authInSz); + } else { + authPadSz = authInSz; + authInPadded = (byte*)authIn; + } + +#ifdef WOLFSSL_STM32_CUBEMX + hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)ctr; + hcryp.Init.Header = (STM_CRYPT_TYPE*)authInPadded; + hcryp.Init.HeaderSize = authInSz; + +#ifdef STM32_CRYPTO_AES_ONLY + /* Set the CRYP parameters */ + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_GCM_GMAC; + hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT; + hcryp.Init.GCMCMACPhase = CRYP_INIT_PHASE; + HAL_CRYP_Init(&hcryp); + + /* GCM init phase */ + status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT); + if (status == HAL_OK) { + /* GCM header phase */ + hcryp.Init.GCMCMACPhase = CRYP_HEADER_PHASE; + status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT); + } + if (status == HAL_OK) { + /* GCM payload phase - blocks */ + hcryp.Init.GCMCMACPhase = CRYP_PAYLOAD_PHASE; + if (blocks) { + status = HAL_CRYPEx_AES_Auth(&hcryp, (byte*)in, + (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT); + } + } + if (status == HAL_OK && (partial != 0 || blocks == 0)) { + /* GCM payload phase - partial remainder */ + XMEMSET(partialBlock, 0, sizeof(partialBlock)); + XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial); + status = HAL_CRYPEx_AES_Auth(&hcryp, partialBlock, partial, + partialBlock, STM32_HAL_TIMEOUT); + XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial); + } + if (status == HAL_OK) { + /* GCM final phase */ + hcryp.Init.GCMCMACPhase = CRYP_FINAL_PHASE; + status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, tag, STM32_HAL_TIMEOUT); + } +#elif defined(STM32_HAL_V2) + hcryp.Init.Algorithm = CRYP_AES_GCM; + ByteReverseWords((word32*)partialBlock, (word32*)ctr, AES_BLOCK_SIZE); + hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)partialBlock; + HAL_CRYP_Init(&hcryp); + + /* GCM payload phase - can handle partial blocks */ + status = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)in, + (blocks * AES_BLOCK_SIZE) + partial, (uint32_t*)out, STM32_HAL_TIMEOUT); + if (status == HAL_OK) { + /* Compute the authTag */ + status = HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag, + STM32_HAL_TIMEOUT); + } +#else + HAL_CRYP_Init(&hcryp); + if (blocks) { + /* GCM payload phase - blocks */ + status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, (byte*)in, + (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT); + } + if (status == HAL_OK && (partial != 0 || blocks == 0)) { + /* GCM payload phase - partial remainder */ + XMEMSET(partialBlock, 0, sizeof(partialBlock)); + XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial); + status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, partialBlock, partial, + partialBlock, STM32_HAL_TIMEOUT); + XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial); + } + if (status == HAL_OK) { + /* Compute the authTag */ + status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, tag, STM32_HAL_TIMEOUT); + } +#endif + + if (status != HAL_OK) + ret = AES_GCM_AUTH_E; + HAL_CRYP_DeInit(&hcryp); + +#else /* STD_PERI_LIB */ + ByteReverseWords(keyCopy, (word32*)aes->key, keySize); + status = CRYP_AES_GCM(MODE_ENCRYPT, (uint8_t*)ctr, + (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 */ + + if (ret == 0) { + /* return authTag */ + if (authTag) { + /* STM32 GCM won't compute Auth correctly for partial or + when IV != 12, so use software here */ + if (sz == 0 || partial != 0 || ivSz != GCM_NONCE_MID_SZ) { + DecrementGcmCounter(ctr); /* hardware requires +1, so subtract it */ + GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz); + wc_AesEncrypt(aes, ctr, tag); + xorbuf(authTag, tag, authTagSz); + } + else { + XMEMCPY(authTag, tag, authTagSz); + } + } + } + + /* Free memory if not a multiple of AES_BLOCK_SZ */ + if (authInPadded != authIn) { + XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + wolfSSL_CryptHwMutexUnLock(); + + return ret; +} + +#endif /* STM32_CRYPTO_AES_GCM */ + +#ifdef WOLFSSL_AESNI +int AES_GCM_encrypt_C(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#else +static +#endif +int AES_GCM_encrypt_C(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = 0; 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 *ctr ; + byte initialCounter[AES_BLOCK_SIZE]; + byte *ctr; byte scratch[AES_BLOCK_SIZE]; - -#ifdef FREESCALE_MMCAU - byte* key = (byte*)aes->key; +#ifdef OPENSSL_EXTRA + word32 aadTemp; #endif - - WOLFSSL_ENTER("AesGcmEncrypt"); + ctr = counter; + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[AES_BLOCK_SIZE - 1] = 1; + } + else { +#ifdef OPENSSL_EXTRA + aadTemp = aes->aadLen; + aes->aadLen = 0; +#endif + GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE); +#ifdef OPENSSL_EXTRA + aes->aadLen = aadTemp; +#endif + } + XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE); #ifdef WOLFSSL_PIC32MZ_CRYPT - ctr = (char *)aes->iv_ce ; -#else - ctr = counter ; + if (blocks) { + /* use initial IV for 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 - XMEMSET(ctr, 0, AES_BLOCK_SIZE); - XMEMCPY(ctr, iv, ivSz); - InitGcmCounter(ctr); +#if defined(HAVE_AES_ECB) && !defined(WOLFSSL_PIC32MZ_CRYPT) + /* some hardware acceleration can gain performance from doing AES encryption + * of the whole buffer at once */ + if (c != p && blocks > 0) { /* can not handle inline encryption */ + while (blocks--) { + IncrementGcmCounter(ctr); + XMEMCPY(c, ctr, AES_BLOCK_SIZE); + c += AES_BLOCK_SIZE; + } + + /* reset number of blocks and then do encryption */ + blocks = sz / AES_BLOCK_SIZE; + wc_AesEcbEncrypt(aes, out, out, AES_BLOCK_SIZE * blocks); + xorbuf(out, p, AES_BLOCK_SIZE * blocks); + p += AES_BLOCK_SIZE * blocks; + } + else +#endif /* HAVE_AES_ECB && !WOLFSSL_PIC32MZ_CRYPT */ -#ifdef WOLFSSL_PIC32MZ_CRYPT - if(blocks) - wc_AesCrypt(aes, out, in, blocks*AES_BLOCK_SIZE, - PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM ); -#endif while (blocks--) { IncrementGcmCounter(ctr); - #ifndef WOLFSSL_PIC32MZ_CRYPT - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(ctr, key, aes->rounds, scratch); - #else - wc_AesEncrypt(aes, ctr, scratch); - #endif + #if !defined(WOLFSSL_PIC32MZ_CRYPT) + wc_AesEncrypt(aes, ctr, scratch); xorbuf(scratch, p, AES_BLOCK_SIZE); XMEMCPY(c, scratch, AES_BLOCK_SIZE); - #endif + #endif p += AES_BLOCK_SIZE; c += AES_BLOCK_SIZE; } if (partial != 0) { IncrementGcmCounter(ctr); - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(ctr, key, aes->rounds, scratch); - #else - wc_AesEncrypt(aes, ctr, scratch); - #endif + wc_AesEncrypt(aes, ctr, scratch); xorbuf(scratch, p, partial); XMEMCPY(c, scratch, partial); - + } + if (authTag) { + GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz); + wc_AesEncrypt(aes, initialCounter, scratch); + xorbuf(authTag, scratch, authTagSz); +#ifdef OPENSSL_EXTRA + if (!in && !sz) + /* store AAD size for next call */ + aes->aadLen = authInSz; +#endif } - GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz); - InitGcmCounter(ctr); - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(ctr, key, aes->rounds, scratch); - #else - wc_AesEncrypt(aes, ctr, scratch); - #endif - xorbuf(authTag, scratch, authTagSz); - - return 0; + return ret; } +/* Software AES - GCM Encrypt */ +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) +{ + /* argument checks */ + if (aes == NULL || authTagSz > AES_BLOCK_SIZE || ivSz == 0) { + return BAD_FUNC_ARG; + } + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (aes->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_AesGcmEncrypt(aes, out, in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + /* only 12-byte IV is supported in HW */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_GCM && ivSz == GCM_NONCE_MID_SZ) { + #if defined(HAVE_CAVIUM) + #ifdef HAVE_CAVIUM_V + if (authInSz == 20) { /* Nitrox V GCM is only working with 20 byte AAD */ + return NitroxAesGcmEncrypt(aes, out, in, sz, + (const byte*)aes->devKey, aes->keylen, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + } + #endif + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesGcmEncrypt(&aes->asyncDev, out, in, sz, + (const byte*)aes->devKey, 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 STM32_CRYPTO_AES_GCM + /* The STM standard peripheral library API's doesn't support partial blocks */ + #ifdef STD_PERI_LIB + if (partial == 0) + #endif + { + return wc_AesGcmEncrypt_STM32( + aes, out, in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + } +#endif /* STM32_CRYPTO_AES_GCM */ + +#ifdef WOLFSSL_AESNI + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_encrypt_avx2(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + authTagSz, (const byte*)aes->key, aes->rounds); + return 0; + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_encrypt_avx1(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + authTagSz, (const byte*)aes->key, aes->rounds); + return 0; + } + else + #endif + if (haveAESNI) { + AES_GCM_encrypt(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + authTagSz, (const byte*)aes->key, aes->rounds); + return 0; + } + else +#endif + { + return AES_GCM_encrypt_C(aes, out, in, sz, iv, ivSz, authTag, authTagSz, + authIn, authInSz); + } +} +#endif + + + +/* AES GCM Decrypt */ +#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT) +#ifdef FREESCALE_LTC_AES_GCM 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) { + int ret; + word32 keySize; + status_t status; + + /* argument checks */ + /* If the sz is non-zero, both in and out must be set. If sz is 0, + * in and out are don't cares, as this is is the GMAC case. */ + if (aes == NULL || iv == NULL || (sz != 0 && (in == NULL || out == NULL)) || + authTag == NULL || authTagSz > AES_BLOCK_SIZE || authTagSz == 0 || + ivSz == 0) { + + return BAD_FUNC_ARG; + } + + ret = wc_AesGetKeySize(aes, &keySize); + if (ret != 0) { + return ret; + } + + status = LTC_AES_DecryptTagGcm(LTC_BASE, in, out, sz, iv, ivSz, + authIn, authInSz, (byte*)aes->key, keySize, authTag, authTagSz); + + return (status == kStatus_Success) ? 0 : AES_GCM_AUTH_E; +} + +#else + +#ifdef STM32_CRYPTO_AES_GCM +/* this function supports inline decrypt */ +static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret; +#ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; +#else + word32 keyCopy[AES_256_KEY_SIZE/sizeof(word32)]; +#endif + word32 keySize; + int status = HAL_OK; + word32 blocks = sz / AES_BLOCK_SIZE; + word32 partial = sz % AES_BLOCK_SIZE; + byte tag[AES_BLOCK_SIZE]; + byte partialBlock[AES_BLOCK_SIZE]; + byte ctr[AES_BLOCK_SIZE]; + byte* authInPadded = NULL; + int authPadSz; + + ret = wc_AesGetKeySize(aes, &keySize); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_STM32_CUBEMX + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; +#endif + + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + XMEMSET(ctr, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(ctr, iv, ivSz); + ctr[AES_BLOCK_SIZE - 1] = 1; + } + else { + GHASH(aes, NULL, 0, iv, ivSz, ctr, AES_BLOCK_SIZE); + } + /* Hardware requires counter + 1 */ + IncrementGcmCounter(ctr); + + if (authInSz == 0 || (authInSz % AES_BLOCK_SIZE) != 0) { + /* Need to pad the AAD to a full block with zeros. */ + authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; + authInPadded = (byte*)XMALLOC(authPadSz, aes->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (authInPadded == NULL) { + wolfSSL_CryptHwMutexUnLock(); + return MEMORY_E; + } + XMEMSET(authInPadded, 0, authPadSz); + XMEMCPY(authInPadded, authIn, authInSz); + } else { + authPadSz = authInSz; + authInPadded = (byte*)authIn; + } + +#ifdef WOLFSSL_STM32_CUBEMX + hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)ctr; + hcryp.Init.Header = (STM_CRYPT_TYPE*)authInPadded; + hcryp.Init.HeaderSize = authInSz; + +#ifdef STM32_CRYPTO_AES_ONLY + /* Set the CRYP parameters */ + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_GCM_GMAC; + hcryp.Init.OperatingMode = CRYP_ALGOMODE_DECRYPT; + hcryp.Init.GCMCMACPhase = CRYP_INIT_PHASE; + HAL_CRYP_Init(&hcryp); + + /* GCM init phase */ + status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT); + if (status == HAL_OK) { + /* GCM header phase */ + hcryp.Init.GCMCMACPhase = CRYP_HEADER_PHASE; + status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT); + } + if (status == HAL_OK) { + /* GCM payload phase - blocks */ + hcryp.Init.GCMCMACPhase = CRYP_PAYLOAD_PHASE; + if (blocks) { + status = HAL_CRYPEx_AES_Auth(&hcryp, (byte*)in, + (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT); + } + } + if (status == HAL_OK && (partial != 0 || blocks == 0)) { + /* GCM payload phase - partial remainder */ + XMEMSET(partialBlock, 0, sizeof(partialBlock)); + XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial); + status = HAL_CRYPEx_AES_Auth(&hcryp, partialBlock, partial, + partialBlock, STM32_HAL_TIMEOUT); + XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial); + } + if (status == HAL_OK) { + /* GCM final phase */ + hcryp.Init.GCMCMACPhase = CRYP_FINAL_PHASE; + status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, tag, STM32_HAL_TIMEOUT); + } +#elif defined(STM32_HAL_V2) + hcryp.Init.Algorithm = CRYP_AES_GCM; + ByteReverseWords((word32*)partialBlock, (word32*)ctr, AES_BLOCK_SIZE); + hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)partialBlock; + HAL_CRYP_Init(&hcryp); + + /* GCM payload phase - can handle partial blocks */ + status = HAL_CRYP_Decrypt(&hcryp, (uint32_t*)in, + (blocks * AES_BLOCK_SIZE) + partial, (uint32_t*)out, STM32_HAL_TIMEOUT); + if (status == HAL_OK) { + /* Compute the authTag */ + status = HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag, + STM32_HAL_TIMEOUT); + } +#else + HAL_CRYP_Init(&hcryp); + if (blocks) { + /* GCM payload phase - blocks */ + status = HAL_CRYPEx_AESGCM_Decrypt(&hcryp, (byte*)in, + (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT); + } + if (status == HAL_OK && (partial != 0 || blocks == 0)) { + /* GCM payload phase - partial remainder */ + XMEMSET(partialBlock, 0, sizeof(partialBlock)); + XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial); + status = HAL_CRYPEx_AESGCM_Decrypt(&hcryp, partialBlock, partial, + partialBlock, STM32_HAL_TIMEOUT); + XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial); + } + if (status == HAL_OK) { + /* Compute the authTag */ + status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, tag, STM32_HAL_TIMEOUT); + } +#endif + + if (status != HAL_OK) + ret = AES_GCM_AUTH_E; + + HAL_CRYP_DeInit(&hcryp); + +#else /* STD_PERI_LIB */ + ByteReverseWords(keyCopy, (word32*)aes->key, aes->keylen); + + /* 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. */ + status = CRYP_AES_GCM(MODE_DECRYPT, (uint8_t*)ctr, + (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 */ + + /* STM32 GCM hardware only supports IV of 12 bytes, so use software for auth */ + if (sz == 0 || ivSz != GCM_NONCE_MID_SZ) { + DecrementGcmCounter(ctr); /* hardware requires +1, so subtract it */ + GHASH(aes, authIn, authInSz, in, sz, tag, sizeof(tag)); + wc_AesEncrypt(aes, ctr, partialBlock); + xorbuf(tag, partialBlock, sizeof(tag)); + } + + if (ConstantCompare(authTag, tag, authTagSz) != 0) { + ret = AES_GCM_AUTH_E; + } + + /* Free memory if not a multiple of AES_BLOCK_SZ */ + if (authInPadded != authIn) { + XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + wolfSSL_CryptHwMutexUnLock(); + + return ret; +} + +#endif /* STM32_CRYPTO_AES_GCM */ + +#ifdef WOLFSSL_AESNI +int AES_GCM_decrypt_C(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#else +static +#endif +int AES_GCM_decrypt_C(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = 0; 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 *ctr ; + byte initialCounter[AES_BLOCK_SIZE]; + byte *ctr; byte scratch[AES_BLOCK_SIZE]; - -#ifdef FREESCALE_MMCAU - byte* key = (byte*)aes->key; + byte Tprime[AES_BLOCK_SIZE]; + byte EKY0[AES_BLOCK_SIZE]; +#ifdef OPENSSL_EXTRA + word32 aadTemp; #endif - - WOLFSSL_ENTER("AesGcmDecrypt"); - -#ifdef WOLFSSL_PIC32MZ_CRYPT - ctr = (char *)aes->iv_ce ; -#else - ctr = counter ; + ctr = counter; + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[AES_BLOCK_SIZE - 1] = 1; + } + else { +#ifdef OPENSSL_EXTRA + aadTemp = aes->aadLen; + aes->aadLen = 0; #endif + GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE); +#ifdef OPENSSL_EXTRA + aes->aadLen = aadTemp; +#endif + } + XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE); - XMEMSET(ctr, 0, AES_BLOCK_SIZE); - XMEMCPY(ctr, iv, ivSz); - InitGcmCounter(ctr); + /* 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)); - /* Calculate the authTag again using the received auth data and the - * cipher text. */ - { - byte Tprime[AES_BLOCK_SIZE]; - byte EKY0[AES_BLOCK_SIZE]; - - GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime)); - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(ctr, key, aes->rounds, EKY0); - #else - wc_AesEncrypt(aes, ctr, EKY0); - #endif - xorbuf(Tprime, EKY0, sizeof(Tprime)); - - if (ConstantCompare(authTag, Tprime, authTagSz) != 0) { - return AES_GCM_AUTH_E; - } +#ifdef OPENSSL_EXTRA + if (!out) { + /* authenticated, non-confidential data */ + /* store AAD size for next call */ + aes->aadLen = authInSz; + } +#endif + 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 defined(WOLFSSL_PIC32MZ_CRYPT) + if (blocks) { + /* use initial IV for 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 +#if defined(HAVE_AES_ECB) && !defined(WOLFSSL_PIC32MZ_CRYPT) + /* some hardware acceleration can gain performance from doing AES encryption + * of the whole buffer at once */ + if (c != p && blocks > 0) { /* can not handle inline decryption */ + while (blocks--) { + IncrementGcmCounter(ctr); + XMEMCPY(p, ctr, AES_BLOCK_SIZE); + p += AES_BLOCK_SIZE; + } + + /* reset number of blocks and then do encryption */ + blocks = sz / AES_BLOCK_SIZE; + + wc_AesEcbEncrypt(aes, out, out, AES_BLOCK_SIZE * blocks); + xorbuf(out, c, AES_BLOCK_SIZE * blocks); + c += AES_BLOCK_SIZE * blocks; + } + else +#endif /* HAVE_AES_ECB && !PIC32MZ */ while (blocks--) { IncrementGcmCounter(ctr); - #ifndef WOLFSSL_PIC32MZ_CRYPT - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(ctr, key, aes->rounds, scratch); - #else - wc_AesEncrypt(aes, ctr, scratch); - #endif + #if !defined(WOLFSSL_PIC32MZ_CRYPT) + wc_AesEncrypt(aes, ctr, scratch); xorbuf(scratch, c, AES_BLOCK_SIZE); XMEMCPY(p, scratch, AES_BLOCK_SIZE); - #endif + #endif p += AES_BLOCK_SIZE; c += AES_BLOCK_SIZE; } + if (partial != 0) { IncrementGcmCounter(ctr); - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(ctr, key, aes->rounds, scratch); - #else - wc_AesEncrypt(aes, ctr, scratch); - #endif + wc_AesEncrypt(aes, ctr, scratch); xorbuf(scratch, c, partial); XMEMCPY(p, scratch, partial); } - return 0; + + return ret; } +/* Software AES - GCM 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) +{ +#ifdef WOLFSSL_AESNI + int res = AES_GCM_AUTH_E; +#endif + + /* argument checks */ + /* If the sz is non-zero, both in and out must be set. If sz is 0, + * in and out are don't cares, as this is is the GMAC case. */ + if (aes == NULL || iv == NULL || (sz != 0 && (in == NULL || out == NULL)) || + authTag == NULL || authTagSz > AES_BLOCK_SIZE || authTagSz == 0 || + ivSz == 0) { + + return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (aes->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_AesGcmDecrypt(aes, out, in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + /* only 12-byte IV is supported in HW */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_GCM && ivSz == GCM_NONCE_MID_SZ) { + #if defined(HAVE_CAVIUM) + #ifdef HAVE_CAVIUM_V + if (authInSz == 20) { /* Nitrox V GCM is only working with 20 byte AAD */ + return NitroxAesGcmDecrypt(aes, out, in, sz, + (const byte*)aes->devKey, aes->keylen, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + } + #endif + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesGcmDecrypt(&aes->asyncDev, out, in, sz, + (const byte*)aes->devKey, 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 STM32_CRYPTO_AES_GCM + /* The STM standard peripheral library API's doesn't support partial blocks */ + #ifdef STD_PERI_LIB + if (partial == 0) + #endif + { + return wc_AesGcmDecrypt_STM32( + aes, out, in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + } +#endif /* STM32_CRYPTO_AES_GCM */ + +#ifdef WOLFSSL_AESNI + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_decrypt_avx2(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + authTagSz, (byte*)aes->key, aes->rounds, &res); + if (res == 0) + return AES_GCM_AUTH_E; + return 0; + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_decrypt_avx1(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + authTagSz, (byte*)aes->key, aes->rounds, &res); + if (res == 0) + return AES_GCM_AUTH_E; + return 0; + } + else + #endif + if (haveAESNI) { + AES_GCM_decrypt(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + authTagSz, (byte*)aes->key, aes->rounds, &res); + if (res == 0) + return AES_GCM_AUTH_E; + return 0; + } + else +#endif + { + return AES_GCM_decrypt_C(aes, out, in, sz, iv, ivSz, authTag, authTagSz, + authIn, authInSz); + } +} +#endif +#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */ +#endif /* WOLFSSL_XILINX_CRYPT */ +#endif /* end of block for AESGCM implementation selection */ + + +/* Common to all, abstract functions that build off of lower level AESGCM + * functions */ +#ifndef WC_NO_RNG + +int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz) +{ + int ret = 0; + + if (aes == NULL || iv == NULL || + (ivSz != GCM_NONCE_MIN_SZ && ivSz != GCM_NONCE_MID_SZ && + ivSz != GCM_NONCE_MAX_SZ)) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + XMEMCPY((byte*)aes->reg, iv, ivSz); + + /* If the IV is 96, allow for a 2^64 invocation counter. + * For any other size for the nonce, limit the invocation + * counter to 32-bits. (SP 800-38D 8.3) */ + aes->invokeCtr[0] = 0; + aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF; + aes->nonceSz = ivSz; + } + + return ret; +} + + +int wc_AesGcmSetIV(Aes* aes, word32 ivSz, + const byte* ivFixed, word32 ivFixedSz, + WC_RNG* rng) +{ + int ret = 0; + + if (aes == NULL || rng == NULL || + (ivSz != GCM_NONCE_MIN_SZ && ivSz != GCM_NONCE_MID_SZ && + ivSz != GCM_NONCE_MAX_SZ) || + (ivFixed == NULL && ivFixedSz != 0) || + (ivFixed != NULL && ivFixedSz != AES_IV_FIXED_SZ)) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + byte* iv = (byte*)aes->reg; + + if (ivFixedSz) + XMEMCPY(iv, ivFixed, ivFixedSz); + + ret = wc_RNG_GenerateBlock(rng, iv + ivFixedSz, ivSz - ivFixedSz); + } + + if (ret == 0) { + /* If the IV is 96, allow for a 2^64 invocation counter. + * For any other size for the nonce, limit the invocation + * counter to 32-bits. (SP 800-38D 8.3) */ + aes->invokeCtr[0] = 0; + aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF; + aes->nonceSz = ivSz; + } + + return ret; +} + + +int wc_AesGcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz, + byte* ivOut, word32 ivOutSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = 0; + + if (aes == NULL || (sz != 0 && (in == NULL || out == NULL)) || + ivOut == NULL || ivOutSz != aes->nonceSz || + (authIn == NULL && authInSz != 0)) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + aes->invokeCtr[0]++; + if (aes->invokeCtr[0] == 0) { + aes->invokeCtr[1]++; + if (aes->invokeCtr[1] == 0) + ret = AES_GCM_OVERFLOW_E; + } + } + + if (ret == 0) { + XMEMCPY(ivOut, aes->reg, ivOutSz); + ret = wc_AesGcmEncrypt(aes, out, in, sz, + (byte*)aes->reg, ivOutSz, + authTag, authTagSz, + authIn, authInSz); + if (ret == 0) + IncCtr((byte*)aes->reg, ivOutSz); + } + + return ret; +} + +int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz, WC_RNG* rng) +{ + Aes aes; + int ret; + + if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) || + authTag == NULL || authTagSz == 0 || rng == NULL) { + + return BAD_FUNC_ARG; + } + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesGcmSetIV(&aes, ivSz, NULL, 0, rng); + if (ret == 0) + ret = wc_AesGcmEncrypt_ex(&aes, NULL, NULL, 0, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + wc_AesFree(&aes); + } + ForceZero(&aes, sizeof(aes)); + + return ret; +} + +int wc_GmacVerify(const byte* key, word32 keySz, + const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + const byte* authTag, word32 authTagSz) +{ + int ret; +#ifndef NO_AES_DECRYPT + Aes aes; + + if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) || + authTag == NULL || authTagSz == 0 || authTagSz > AES_BLOCK_SIZE) { + + return BAD_FUNC_ARG; + } + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesGcmDecrypt(&aes, NULL, NULL, 0, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + wc_AesFree(&aes); + } + ForceZero(&aes, sizeof(aes)); +#else + (void)key; + (void)keySz; + (void)iv; + (void)ivSz; + (void)authIn; + (void)authInSz; + (void)authTag; + (void)authTagSz; + ret = NOT_COMPILED_IN; +#endif + return ret; +} + +#endif /* WC_NO_RNG */ 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); } @@ -3472,69 +6962,114 @@ WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, #ifdef HAVE_AESCCM -#ifdef STM32F2_CRYPTO - #error "STM32F2 crypto doesn't currently support AES-CCM mode" +int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) +{ + if (!((keySz == 16) || (keySz == 24) || (keySz == 32))) + return BAD_FUNC_ARG; + + return wc_AesSetKey(aes, key, keySz, NULL, AES_ENCRYPTION); +} + +#ifdef WOLFSSL_ARMASM + /* implementation located in wolfcrypt/src/port/arm/armv8-aes.c */ #elif 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(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + /* implemented in wolfcrypt/src/port/caam_aes.c */ -#endif +#elif defined(FREESCALE_LTC) -void 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))) - return; + /* 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)); - 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 */ + +#else + +/* Software CCM */ static void roll_x(Aes* aes, const byte* in, word32 inSz, byte* out) { - #ifdef FREESCALE_MMCAU - byte* key = (byte*)aes->key; - #endif - /* process the bulk of the data */ while (inSz >= AES_BLOCK_SIZE) { xorbuf(out, in, AES_BLOCK_SIZE); in += AES_BLOCK_SIZE; inSz -= AES_BLOCK_SIZE; - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(out, key, aes->rounds, out); - #else - wc_AesEncrypt(aes, out, out); - #endif + wc_AesEncrypt(aes, out, out); } /* process remainder of the data */ if (inSz > 0) { xorbuf(out, in, inSz); - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(out, key, aes->rounds, out); - #else - wc_AesEncrypt(aes, out, out); - #endif + wc_AesEncrypt(aes, out, out); } } - static void roll_auth(Aes* aes, const byte* in, word32 inSz, byte* out) { word32 authLenSz; word32 remainder; - #ifdef FREESCALE_MMCAU - byte* key = (byte*)aes->key; - #endif - /* encode the length in */ if (inSz <= 0xFEFF) { authLenSz = 2; @@ -3568,18 +7103,14 @@ static void roll_auth(Aes* aes, const byte* in, word32 inSz, byte* out) xorbuf(out + authLenSz, in, inSz); inSz = 0; } - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(out, key, aes->rounds, out); - #else - wc_AesEncrypt(aes, out, out); - #endif + wc_AesEncrypt(aes, out, out); if (inSz > 0) roll_x(aes, in, inSz, out); } -static INLINE void AesCcmCtrInc(byte* B, word32 lenSz) +static WC_INLINE void AesCcmCtrInc(byte* B, word32 lenSz) { word32 i; @@ -3588,34 +7119,85 @@ static INLINE void AesCcmCtrInc(byte* B, word32 lenSz) } } +#ifdef WOLFSSL_AESNI +static WC_INLINE void AesCcmCtrIncSet4(byte* B, word32 lenSz) +{ + word32 i; -void wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + /* B+1 = B */ + XMEMCPY(B + AES_BLOCK_SIZE * 1, B, AES_BLOCK_SIZE); + /* B+2,B+3 = B,B+1 */ + XMEMCPY(B + AES_BLOCK_SIZE * 2, B, AES_BLOCK_SIZE * 2); + + for (i = 0; i < lenSz; i++) { + if (++B[AES_BLOCK_SIZE * 1 - 1 - i] != 0) break; + } + B[AES_BLOCK_SIZE * 2 - 1] += 2; + if (B[AES_BLOCK_SIZE * 2 - 1] < 2) { + for (i = 1; i < lenSz; i++) { + if (++B[AES_BLOCK_SIZE * 2 - 1 - i] != 0) break; + } + } + B[AES_BLOCK_SIZE * 3 - 1] += 3; + if (B[AES_BLOCK_SIZE * 3 - 1] < 3) { + for (i = 1; i < lenSz; i++) { + if (++B[AES_BLOCK_SIZE * 3 - 1 - i] != 0) break; + } + } +} + +static WC_INLINE void AesCcmCtrInc4(byte* B, word32 lenSz) +{ + word32 i; + + B[AES_BLOCK_SIZE - 1] += 4; + if (B[AES_BLOCK_SIZE - 1] < 4) { + for (i = 1; i < lenSz; i++) { + if (++B[AES_BLOCK_SIZE - 1 - i] != 0) break; + } + } +} +#endif + +/* Software AES - CCM Encrypt */ +/* 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) { +#ifndef WOLFSSL_AESNI byte A[AES_BLOCK_SIZE]; byte B[AES_BLOCK_SIZE]; +#else + ALIGN128 byte A[AES_BLOCK_SIZE * 4]; + ALIGN128 byte B[AES_BLOCK_SIZE * 4]; +#endif byte lenSz; word32 i; + byte mask = 0xFF; + const word32 wordSz = (word32)sizeof(word32); - #ifdef FREESCALE_MMCAU - byte* key = (byte*)aes->key; - #endif + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13 || + authTagSz > AES_BLOCK_SIZE) + return BAD_FUNC_ARG; + XMEMSET(A, 0, sizeof(A)); XMEMCPY(B+1, nonce, nonceSz); lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz; B[0] = (authInSz > 0 ? 64 : 0) + (8 * (((byte)authTagSz - 2) / 2)) + (lenSz - 1); - for (i = 0; i < lenSz; i++) - B[AES_BLOCK_SIZE - 1 - i] = (inSz >> (8 * i)) & 0xFF; + for (i = 0; i < lenSz; i++) { + if (mask && i >= wordSz) + mask = 0x00; + B[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask; + } + + wc_AesEncrypt(aes, B, A); - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(B, key, aes->rounds, A); - #else - wc_AesEncrypt(aes, B, A); - #endif if (authInSz > 0) roll_auth(aes, authIn, authInSz, A); if (inSz > 0) @@ -3625,20 +7207,32 @@ void wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, B[0] = lenSz - 1; for (i = 0; i < lenSz; i++) B[AES_BLOCK_SIZE - 1 - i] = 0; - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(B, key, aes->rounds, A); - #else - wc_AesEncrypt(aes, B, A); - #endif + wc_AesEncrypt(aes, B, A); xorbuf(authTag, A, authTagSz); B[15] = 1; +#ifdef WOLFSSL_AESNI + if (haveAESNI && aes->use_aesni) { + while (inSz >= AES_BLOCK_SIZE * 4) { + AesCcmCtrIncSet4(B, lenSz); + + AES_ECB_encrypt(B, A, AES_BLOCK_SIZE * 4, (byte*)aes->key, + aes->rounds); + xorbuf(A, in, AES_BLOCK_SIZE * 4); + XMEMCPY(out, A, AES_BLOCK_SIZE * 4); + + inSz -= AES_BLOCK_SIZE * 4; + in += AES_BLOCK_SIZE * 4; + out += AES_BLOCK_SIZE * 4; + + if (inSz < AES_BLOCK_SIZE * 4) { + AesCcmCtrInc4(B, lenSz); + } + } + } +#endif while (inSz >= AES_BLOCK_SIZE) { - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(B, key, aes->rounds, A); - #else - wc_AesEncrypt(aes, B, A); - #endif + wc_AesEncrypt(aes, B, A); xorbuf(A, in, AES_BLOCK_SIZE); XMEMCPY(out, A, AES_BLOCK_SIZE); @@ -3648,35 +7242,43 @@ void wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, out += AES_BLOCK_SIZE; } if (inSz > 0) { - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(B, key, aes->rounds, A); - #else - wc_AesEncrypt(aes, B, A); - #endif + wc_AesEncrypt(aes, B, A); xorbuf(A, in, inSz); XMEMCPY(out, A, inSz); } ForceZero(A, AES_BLOCK_SIZE); ForceZero(B, AES_BLOCK_SIZE); + + return 0; } - +#ifdef HAVE_AES_DECRYPT +/* Software AES - CCM 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) { +#ifndef WOLFSSL_AESNI byte A[AES_BLOCK_SIZE]; byte B[AES_BLOCK_SIZE]; +#else + ALIGN128 byte B[AES_BLOCK_SIZE * 4]; + ALIGN128 byte A[AES_BLOCK_SIZE * 4]; +#endif byte* o; byte lenSz; word32 i, oSz; int result = 0; + byte mask = 0xFF; + const word32 wordSz = (word32)sizeof(word32); - #ifdef FREESCALE_MMCAU - byte* key = (byte*)aes->key; - #endif + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13 || + authTagSz > AES_BLOCK_SIZE) + return BAD_FUNC_ARG; o = out; oSz = inSz; @@ -3688,12 +7290,28 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, B[AES_BLOCK_SIZE - 1 - i] = 0; B[15] = 1; +#ifdef WOLFSSL_AESNI + if (haveAESNI && aes->use_aesni) { + while (oSz >= AES_BLOCK_SIZE * 4) { + AesCcmCtrIncSet4(B, lenSz); + + AES_ECB_encrypt(B, A, AES_BLOCK_SIZE * 4, (byte*)aes->key, + aes->rounds); + xorbuf(A, in, AES_BLOCK_SIZE * 4); + XMEMCPY(o, A, AES_BLOCK_SIZE * 4); + + oSz -= AES_BLOCK_SIZE * 4; + in += AES_BLOCK_SIZE * 4; + o += AES_BLOCK_SIZE * 4; + + if (oSz < AES_BLOCK_SIZE * 4) { + AesCcmCtrInc4(B, lenSz); + } + } + } +#endif while (oSz >= AES_BLOCK_SIZE) { - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(B, key, aes->rounds, A); - #else - wc_AesEncrypt(aes, B, A); - #endif + wc_AesEncrypt(aes, B, A); xorbuf(A, in, AES_BLOCK_SIZE); XMEMCPY(o, A, AES_BLOCK_SIZE); @@ -3703,22 +7321,14 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, o += AES_BLOCK_SIZE; } if (inSz > 0) { - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(B, key, aes->rounds, A); - #else - wc_AesEncrypt(aes, B, A); - #endif + wc_AesEncrypt(aes, B, A); xorbuf(A, in, oSz); XMEMCPY(o, A, oSz); } for (i = 0; i < lenSz; i++) B[AES_BLOCK_SIZE - 1 - i] = 0; - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(B, key, aes->rounds, A); - #else - wc_AesEncrypt(aes, B, A); - #endif + wc_AesEncrypt(aes, B, A); o = out; oSz = inSz; @@ -3726,14 +7336,14 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, B[0] = (authInSz > 0 ? 64 : 0) + (8 * (((byte)authTagSz - 2) / 2)) + (lenSz - 1); - for (i = 0; i < lenSz; i++) - B[AES_BLOCK_SIZE - 1 - i] = (inSz >> (8 * i)) & 0xFF; + for (i = 0; i < lenSz; i++) { + if (mask && i >= wordSz) + mask = 0x00; + B[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask; + } + + wc_AesEncrypt(aes, B, A); - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(B, key, aes->rounds, A); - #else - wc_AesEncrypt(aes, B, A); - #endif if (authInSz > 0) roll_auth(aes, authIn, authInSz, A); if (inSz > 0) @@ -3742,11 +7352,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, B[0] = lenSz - 1; for (i = 0; i < lenSz; i++) B[AES_BLOCK_SIZE - 1 - i] = 0; - #ifdef FREESCALE_MMCAU - cau_aes_encrypt(B, key, aes->rounds, B); - #else - wc_AesEncrypt(aes, B, B); - #endif + wc_AesEncrypt(aes, B, B); xorbuf(A, B, authTagSz); if (ConstantCompare(A, authTag, authTagSz) != 0) { @@ -3764,134 +7370,1335 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, return result; } +#endif /* HAVE_AES_DECRYPT */ +#endif /* software CCM */ + +/* abstract functions that call lower level AESCCM functions */ +#ifndef WC_NO_RNG + +int wc_AesCcmSetNonce(Aes* aes, const byte* nonce, word32 nonceSz) +{ + int ret = 0; + + if (aes == NULL || nonce == NULL || + nonceSz < CCM_NONCE_MIN_SZ || nonceSz > CCM_NONCE_MAX_SZ) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + XMEMCPY(aes->reg, nonce, nonceSz); + aes->nonceSz = nonceSz; + + /* Invocation counter should be 2^61 */ + aes->invokeCtr[0] = 0; + aes->invokeCtr[1] = 0xE0000000; + } + + return ret; +} + + +int wc_AesCcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz, + byte* ivOut, word32 ivOutSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = 0; + + if (aes == NULL || out == NULL || + (in == NULL && sz != 0) || + ivOut == NULL || + (authIn == NULL && authInSz != 0) || + (ivOutSz != aes->nonceSz)) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + aes->invokeCtr[0]++; + if (aes->invokeCtr[0] == 0) { + aes->invokeCtr[1]++; + if (aes->invokeCtr[1] == 0) + ret = AES_CCM_OVERFLOW_E; + } + } + + if (ret == 0) { + ret = wc_AesCcmEncrypt(aes, out, in, sz, + (byte*)aes->reg, aes->nonceSz, + authTag, authTagSz, + authIn, authInSz); + if (ret == 0) { + XMEMCPY(ivOut, aes->reg, aes->nonceSz); + IncCtr((byte*)aes->reg, aes->nonceSz); + } + } + + return ret; +} + +#endif /* WC_NO_RNG */ + #endif /* HAVE_AESCCM */ -#ifdef HAVE_CAVIUM - -#include -#include "cavium_common.h" - -/* Initiliaze Aes for use with Nitrox device */ -int wc_AesInitCavium(Aes* aes, int devId) +/* Initialize Aes for use with async hardware */ +int wc_AesInit(Aes* aes, void* heap, int devId) { + int ret = 0; + if (aes == NULL) - return -1; + return BAD_FUNC_ARG; - if (CspAllocContext(CONTEXT_SSL, &aes->contextHandle, devId) != 0) - return -1; + aes->heap = heap; +#ifdef WOLF_CRYPTO_CB aes->devId = devId; - aes->magic = WOLFSSL_AES_CAVIUM_MAGIC; + aes->devCtx = NULL; +#else + (void)devId; +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + ret = wolfAsync_DevCtxInit(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES, + aes->heap, devId); +#endif /* WOLFSSL_ASYNC_CRYPT */ - return 0; +#ifdef WOLFSSL_AFALG + aes->alFd = -1; + aes->rdFd = -1; +#endif +#if defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC)) + aes->ctx.cfd = -1; +#endif +#if defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES) + XMEMSET(&aes->ctx, 0, sizeof(aes->ctx)); +#endif +#ifdef HAVE_AESGCM +#ifdef OPENSSL_EXTRA + XMEMSET(aes->aadH, 0, sizeof(aes->aadH)); + aes->aadLen = 0; +#endif +#endif + return ret; } +#ifdef HAVE_PKCS11 +int wc_AesInit_Id(Aes* aes, unsigned char* id, int len, void* heap, int devId) +{ + int ret = 0; -/* Free Aes from use with Nitrox device */ -void wc_AesFreeCavium(Aes* aes) + if (aes == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0 && (len < 0 || len > AES_MAX_ID_LEN)) + ret = BUFFER_E; + + if (ret == 0) + ret = wc_AesInit(aes, heap, devId); + if (ret == 0) { + XMEMCPY(aes->id, id, len); + aes->idLen = len; + } + + return ret; +} +#endif + +/* Free Aes from use with async hardware */ +void wc_AesFree(Aes* aes) { if (aes == NULL) return; - if (aes->magic != WOLFSSL_AES_CAVIUM_MAGIC) - return; - - CspFreeContext(CONTEXT_SSL, aes->contextHandle, aes->devId); - aes->magic = 0; -} - - -static int wc_AesCaviumSetKey(Aes* aes, const byte* key, word32 length, - const byte* iv) -{ - if (aes == NULL) - return -1; - - XMEMCPY(aes->key, key, length); /* key still holds key, iv still in reg */ - if (length == 16) - aes->type = AES_128; - else if (length == 24) - aes->type = AES_192; - else if (length == 32) - aes->type = AES_256; - - return wc_AesSetIV(aes, iv); -} - - -static int AesCaviumCbcEncrypt(Aes* aes, byte* out, const byte* in, - word32 length) -{ - wolfssl_word offset = 0; - word32 requestId; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - if (CspEncryptAes(CAVIUM_BLOCKING, aes->contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &requestId, - aes->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Aes Encrypt"); - return -1; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(aes->reg, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + wolfAsync_DevCtxFree(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES); +#endif /* WOLFSSL_ASYNC_CRYPT */ +#if defined(WOLFSSL_AFALG) || defined(WOLFSSL_AFALG_XILINX_AES) + if (aes->rdFd > 0) { /* negative is error case */ + close(aes->rdFd); } - if (length) { - word16 slen = (word16)length; - if (CspEncryptAes(CAVIUM_BLOCKING, aes->contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &requestId, - aes->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Aes Encrypt"); - return -1; - } - XMEMCPY(aes->reg, out + offset+length - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + if (aes->alFd > 0) { + close(aes->alFd); + } +#endif /* WOLFSSL_AFALG */ +#if defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC)) + wc_DevCryptoFree(&aes->ctx); +#endif +#if defined(WOLF_CRYPTO_CB) || (defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))) || \ + (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)) + ForceZero((byte*)aes->devKey, AES_MAX_KEY_SIZE/WOLFSSL_BIT_SIZE); +#endif +} + + +int wc_AesGetKeySize(Aes* aes, word32* keySize) +{ + int ret = 0; + + if (aes == NULL || keySize == NULL) { + return BAD_FUNC_ARG; + } +#if defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES) + *keySize = aes->ctx.key.keySize; + return ret; +#endif + switch (aes->rounds) { +#ifdef WOLFSSL_AES_128 + case 10: + *keySize = 16; + break; +#endif +#ifdef WOLFSSL_AES_192 + case 12: + *keySize = 24; + break; +#endif +#ifdef WOLFSSL_AES_256 + case 14: + *keySize = 32; + break; +#endif + default: + *keySize = 0; + ret = BAD_FUNC_ARG; + } + + return ret; +} + +#endif /* !WOLFSSL_TI_CRYPT */ + +#ifdef HAVE_AES_ECB +#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ + +#elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */ + +#elif defined(WOLFSSL_DEVCRYPTO_AES) + /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */ + +#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES) + +/* Software AES - ECB */ +int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + if ((in == NULL) || (out == NULL) || (aes == NULL)) + return BAD_FUNC_ARG; + + return AES_ECB_encrypt(aes, in, out, sz); +} + + +int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + if ((in == NULL) || (out == NULL) || (aes == NULL)) + return BAD_FUNC_ARG; + + return AES_ECB_decrypt(aes, in, out, sz); +} + +#else + +/* Software 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 (blocks>0) { + wc_AesEncryptDirect(aes, out, in); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + blocks--; } return 0; } -static int AesCaviumCbcDecrypt(Aes* aes, byte* out, const byte* in, - word32 length) -{ - word32 requestId; - wolfssl_word offset = 0; - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - XMEMCPY(aes->tmp, in + offset + slen - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - if (CspDecryptAes(CAVIUM_BLOCKING, aes->contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &requestId, - aes->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Aes Decrypt"); - return -1; - } - 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); - if (CspDecryptAes(CAVIUM_BLOCKING, aes->contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &requestId, - aes->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Aes Decrypt"); - return -1; - } - XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); +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 (blocks>0) { + wc_AesDecryptDirect(aes, out, in); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + blocks--; } return 0; } +#endif +#endif /* HAVE_AES_ECB */ -#endif /* HAVE_CAVIUM */ +#if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_OFB) +/* Feedback AES mode + * + * aes structure holding key to use for encryption + * out buffer to hold result of encryption (must be at least as large as input + * buffer) + * in buffer to encrypt + * sz size of input buffer + * mode flag to specify AES mode + * + * returns 0 on success and negative error values on failure + */ +/* Software AES - CFB Encrypt */ +static int wc_AesFeedbackEncrypt(Aes* aes, byte* out, const byte* in, + word32 sz, byte mode) +{ + byte* tmp = NULL; +#ifdef WOLFSSL_AES_CFB + byte* reg = NULL; +#endif -#endif /* WOLFSSL_TI_CRYPT */ + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_AES_CFB + if (aes->left && sz) { + reg = (byte*)aes->reg + AES_BLOCK_SIZE - aes->left; + } +#endif + + /* consume any unused bytes left in aes->tmp */ + tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + while (aes->left && sz) { + *(out) = *(in++) ^ *(tmp++); + #ifdef WOLFSSL_AES_CFB + if (mode == AES_CFB_MODE) { + *(reg++) = *out; + } + #endif + out++; + aes->left--; + sz--; + } + + while (sz >= AES_BLOCK_SIZE) { + /* Using aes->tmp here for inline case i.e. in=out */ + wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg); + #ifdef WOLFSSL_AES_OFB + if (mode == AES_OFB_MODE) { + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + } + #endif + xorbuf((byte*)aes->tmp, in, AES_BLOCK_SIZE); + #ifdef WOLFSSL_AES_CFB + if (mode == AES_CFB_MODE) { + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + } + #endif + XMEMCPY(out, aes->tmp, AES_BLOCK_SIZE); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + aes->left = 0; + } + + /* encrypt left over data */ + if (sz) { + wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg); + aes->left = AES_BLOCK_SIZE; + tmp = (byte*)aes->tmp; + #ifdef WOLFSSL_AES_OFB + if (mode == AES_OFB_MODE) { + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + } + #endif + #ifdef WOLFSSL_AES_CFB + reg = (byte*)aes->reg; + #endif + + while (sz--) { + *(out) = *(in++) ^ *(tmp++); + #ifdef WOLFSSL_AES_CFB + if (mode == AES_CFB_MODE) { + *(reg++) = *out; + } + #endif + out++; + aes->left--; + } + } + + return 0; +} + + +#ifdef HAVE_AES_DECRYPT +/* CFB 128 + * + * aes structure holding key to use for decryption + * out buffer to hold result of decryption (must be at least as large as input + * buffer) + * in buffer to decrypt + * sz size of input buffer + * + * returns 0 on success and negative error values on failure + */ +/* Software AES - CFB Decrypt */ +static int wc_AesFeedbackDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + byte mode) +{ + byte* tmp; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + #ifdef WOLFSSL_AES_CFB + /* check if more input needs copied over to aes->reg */ + if (aes->left && sz && mode == AES_CFB_MODE) { + int size = min(aes->left, sz); + XMEMCPY((byte*)aes->reg + AES_BLOCK_SIZE - aes->left, in, size); + } + #endif + + /* 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--; + sz--; + } + + while (sz > AES_BLOCK_SIZE) { + /* Using aes->tmp here for inline case i.e. in=out */ + wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg); + #ifdef WOLFSSL_AES_OFB + if (mode == AES_OFB_MODE) { + XMEMCPY((byte*)aes->reg, (byte*)aes->tmp, AES_BLOCK_SIZE); + } + #endif + xorbuf((byte*)aes->tmp, in, AES_BLOCK_SIZE); + #ifdef WOLFSSL_AES_CFB + if (mode == AES_CFB_MODE) { + XMEMCPY(aes->reg, in, AES_BLOCK_SIZE); + } + #endif + XMEMCPY(out, (byte*)aes->tmp, AES_BLOCK_SIZE); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + aes->left = 0; + } + + /* decrypt left over data */ + if (sz) { + wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg); + #ifdef WOLFSSL_AES_CFB + if (mode == AES_CFB_MODE) { + XMEMCPY(aes->reg, in, sz); + } + #endif + #ifdef WOLFSSL_AES_OFB + if (mode == AES_OFB_MODE) { + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + } + #endif + + aes->left = AES_BLOCK_SIZE; + tmp = (byte*)aes->tmp; + + while (sz--) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + } + } + + return 0; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_CFB */ + +#ifdef WOLFSSL_AES_CFB +/* CFB 128 + * + * aes structure holding key to use for encryption + * out buffer to hold result of encryption (must be at least as large as input + * buffer) + * in buffer to encrypt + * sz size of input buffer + * + * returns 0 on success and negative error values on failure + */ +/* Software AES - CFB Encrypt */ +int wc_AesCfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_AesFeedbackEncrypt(aes, out, in, sz, AES_CFB_MODE); +} + + +#ifdef HAVE_AES_DECRYPT +/* CFB 128 + * + * aes structure holding key to use for decryption + * out buffer to hold result of decryption (must be at least as large as input + * buffer) + * in buffer to decrypt + * sz size of input buffer + * + * returns 0 on success and negative error values on failure + */ +/* Software AES - CFB Decrypt */ +int wc_AesCfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_AesFeedbackDecrypt(aes, out, in, sz, AES_CFB_MODE); +} +#endif /* HAVE_AES_DECRYPT */ + + +/* shift the whole AES_BLOCK_SIZE array left by 8 or 1 bits */ +static void shiftLeftArray(byte* ary, byte shift) +{ + int i; + + if (shift == WOLFSSL_BIT_SIZE) { + /* shifting over by 8 bits */ + for (i = 0; i < AES_BLOCK_SIZE - 1; i++) { + ary[i] = ary[i+1]; + } + ary[i] = 0; + } + else { + byte carry = 0; + + /* shifting over by 7 or less bits */ + for (i = 0; i < AES_BLOCK_SIZE - 1; i++) { + carry = ary[i+1] & (0XFF << (WOLFSSL_BIT_SIZE - shift)); + carry >>= (WOLFSSL_BIT_SIZE - shift); + ary[i] = (ary[i] << shift) + carry; + } + ary[i] = ary[i] << shift; + } +} + + +/* returns 0 on success and negative values on failure */ +static int wc_AesFeedbackCFB8(Aes* aes, byte* out, const byte* in, + word32 sz, byte dir) +{ + byte *pt; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + if (sz == 0) { + return 0; + } + + while (sz > 0) { + wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg); + if (dir == AES_DECRYPTION) { + pt = (byte*)aes->reg; + + /* LSB + CAT */ + shiftLeftArray(pt, WOLFSSL_BIT_SIZE); + pt[AES_BLOCK_SIZE - 1] = in[0]; + } + + /* MSB + XOR */ + out[0] = aes->tmp[0] ^ in[0]; + if (dir == AES_ENCRYPTION) { + pt = (byte*)aes->reg; + + /* LSB + CAT */ + shiftLeftArray(pt, WOLFSSL_BIT_SIZE); + pt[AES_BLOCK_SIZE - 1] = out[0]; + } + + out += 1; + in += 1; + sz -= 1; + } + + return 0; +} + + +/* returns 0 on success and negative values on failure */ +static int wc_AesFeedbackCFB1(Aes* aes, byte* out, const byte* in, + word32 sz, byte dir) +{ + byte tmp; + byte cur = 0; /* hold current work in order to handle inline in=out */ + byte* pt; + int bit = 7; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + if (sz == 0) { + return 0; + } + + while (sz > 0) { + wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg); + if (dir == AES_DECRYPTION) { + pt = (byte*)aes->reg; + + /* LSB + CAT */ + tmp = (0X01 << bit) & in[0]; + tmp = tmp >> bit; + tmp &= 0x01; + shiftLeftArray((byte*)aes->reg, 1); + pt[AES_BLOCK_SIZE - 1] |= tmp; + } + + /* MSB + XOR */ + tmp = (0X01 << bit) & in[0]; + pt = (byte*)aes->tmp; + tmp = (pt[0] >> 7) ^ (tmp >> bit); + tmp &= 0x01; + cur |= (tmp << bit); + + + if (dir == AES_ENCRYPTION) { + pt = (byte*)aes->reg; + + /* LSB + CAT */ + shiftLeftArray((byte*)aes->reg, 1); + pt[AES_BLOCK_SIZE - 1] |= tmp; + } + + bit--; + if (bit < 0) { + out[0] = cur; + out += 1; + in += 1; + sz -= 1; + bit = 7; + cur = 0; + } + else { + sz -= 1; + } + } + + if (bit > 0 && bit < 7) { + out[0] = cur; + } + + return 0; +} + + +/* CFB 1 + * + * aes structure holding key to use for encryption + * out buffer to hold result of encryption (must be at least as large as input + * buffer) + * in buffer to encrypt (packed to left, i.e. 101 is 0x90) + * sz size of input buffer in bits (0x1 would be size of 1 and 0xFF size of 8) + * + * returns 0 on success and negative values on failure + */ +int wc_AesCfb1Encrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_AesFeedbackCFB1(aes, out, in, sz, AES_ENCRYPTION); +} + + +/* CFB 8 + * + * aes structure holding key to use for encryption + * out buffer to hold result of encryption (must be at least as large as input + * buffer) + * in buffer to encrypt + * sz size of input buffer + * + * returns 0 on success and negative values on failure + */ +int wc_AesCfb8Encrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_AesFeedbackCFB8(aes, out, in, sz, AES_ENCRYPTION); +} +#ifdef HAVE_AES_DECRYPT + +/* CFB 1 + * + * aes structure holding key to use for encryption + * out buffer to hold result of encryption (must be at least as large as input + * buffer) + * in buffer to encrypt + * sz size of input buffer in bits (0x1 would be size of 1 and 0xFF size of 8) + * + * returns 0 on success and negative values on failure + */ +int wc_AesCfb1Decrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_AesFeedbackCFB1(aes, out, in, sz, AES_DECRYPTION); +} + + +/* CFB 8 + * + * aes structure holding key to use for encryption + * out buffer to hold result of encryption (must be at least as large as input + * buffer) + * in buffer to encrypt + * sz size of input buffer + * + * returns 0 on success and negative values on failure + */ +int wc_AesCfb8Decrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_AesFeedbackCFB8(aes, out, in, sz, AES_DECRYPTION); +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_CFB */ + +#ifdef WOLFSSL_AES_OFB +/* OFB + * + * aes structure holding key to use for encryption + * out buffer to hold result of encryption (must be at least as large as input + * buffer) + * in buffer to encrypt + * sz size of input buffer + * + * returns 0 on success and negative error values on failure + */ +/* Software AES - CFB Encrypt */ +int wc_AesOfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_AesFeedbackEncrypt(aes, out, in, sz, AES_OFB_MODE); +} + + +#ifdef HAVE_AES_DECRYPT +/* OFB + * + * aes structure holding key to use for decryption + * out buffer to hold result of decryption (must be at least as large as input + * buffer) + * in buffer to decrypt + * sz size of input buffer + * + * returns 0 on success and negative error values on failure + */ +/* Software AES - OFB Decrypt */ +int wc_AesOfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_AesFeedbackDecrypt(aes, out, in, sz, AES_OFB_MODE); +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_OFB */ + + +#ifdef HAVE_AES_KEYWRAP + +/* Initialize key wrap counter with value */ +static WC_INLINE void InitKeyWrapCounter(byte* inOutCtr, word32 value) +{ + int i; + word32 bytes; + + bytes = sizeof(word32); + for (i = 0; i < (int)sizeof(word32); i++) { + inOutCtr[i+sizeof(word32)] = (value >> ((bytes - 1) * 8)) & 0xFF; + bytes--; + } +} + +/* Increment key wrap counter */ +static WC_INLINE void IncrementKeyWrapCounter(byte* inOutCtr) +{ + int i; + + /* in network byte order so start at end and work back */ + for (i = KEYWRAP_BLOCK_SIZE - 1; i >= 0; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } +} + +/* Decrement key wrap counter */ +static WC_INLINE void DecrementKeyWrapCounter(byte* inOutCtr) +{ + int i; + + for (i = KEYWRAP_BLOCK_SIZE - 1; i >= 0; i--) { + if (--inOutCtr[i] != 0xFF) /* we're done unless we underflow */ + return; + } +} + +/* perform AES key wrap (RFC3394), return out sz on success, negative on err */ +int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, + byte* out, word32 outSz, const byte* iv) +{ + Aes aes; + byte* r; + word32 i; + int ret, j; + + byte t[KEYWRAP_BLOCK_SIZE]; + byte tmp[AES_BLOCK_SIZE]; + + /* n must be at least 2, output size is n + 8 bytes */ + if (key == NULL || in == NULL || inSz < 2 || + out == NULL || outSz < (inSz + KEYWRAP_BLOCK_SIZE)) + return BAD_FUNC_ARG; + + /* input must be multiple of 64-bits */ + if (inSz % KEYWRAP_BLOCK_SIZE != 0) + return BAD_FUNC_ARG; + + /* user IV is optional */ + if (iv == NULL) { + XMEMSET(tmp, 0xA6, KEYWRAP_BLOCK_SIZE); + } else { + XMEMCPY(tmp, iv, KEYWRAP_BLOCK_SIZE); + } + + r = out + 8; + 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; + + for (j = 0; j <= 5; j++) { + for (i = 1; i <= inSz / KEYWRAP_BLOCK_SIZE; i++) { + + /* load R[i] */ + XMEMCPY(tmp + KEYWRAP_BLOCK_SIZE, r, KEYWRAP_BLOCK_SIZE); + + wc_AesEncryptDirect(&aes, tmp, tmp); + + /* calculate new A */ + IncrementKeyWrapCounter(t); + xorbuf(tmp, t, KEYWRAP_BLOCK_SIZE); + + /* save R[i] */ + XMEMCPY(r, tmp + KEYWRAP_BLOCK_SIZE, KEYWRAP_BLOCK_SIZE); + r += KEYWRAP_BLOCK_SIZE; + } + r = out + KEYWRAP_BLOCK_SIZE; + } + + /* 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) +{ + Aes aes; + byte* r; + word32 i, n; + int ret, j; + + byte t[KEYWRAP_BLOCK_SIZE]; + byte tmp[AES_BLOCK_SIZE]; + + const byte* expIv; + const byte defaultIV[] = { + 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; + + /* input must be multiple of 64-bits */ + if (inSz % KEYWRAP_BLOCK_SIZE != 0) + return BAD_FUNC_ARG; + + /* user IV optional */ + if (iv != NULL) { + expIv = iv; + } else { + expIv = defaultIV; + } + + /* A = C[0], R[i] = C[i] */ + XMEMCPY(tmp, in, KEYWRAP_BLOCK_SIZE); + 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; + + /* initialize counter to 6n */ + n = (inSz - 1) / KEYWRAP_BLOCK_SIZE; + InitKeyWrapCounter(t, 6 * n); + + for (j = 5; j >= 0; j--) { + for (i = n; i >= 1; i--) { + + /* calculate A */ + xorbuf(tmp, t, KEYWRAP_BLOCK_SIZE); + DecrementKeyWrapCounter(t); + + /* load R[i], starting at end of R */ + r = out + ((i - 1) * KEYWRAP_BLOCK_SIZE); + XMEMCPY(tmp + KEYWRAP_BLOCK_SIZE, r, KEYWRAP_BLOCK_SIZE); + wc_AesDecryptDirect(&aes, tmp, tmp); + + /* save R[i] */ + XMEMCPY(r, tmp + KEYWRAP_BLOCK_SIZE, KEYWRAP_BLOCK_SIZE); + } + } + + wc_AesFree(&aes); + + /* verify IV */ + if (XMEMCMP(tmp, expIv, KEYWRAP_BLOCK_SIZE) != 0) + return BAD_KEYWRAP_IV_E; + + return inSz - KEYWRAP_BLOCK_SIZE; +} + +#endif /* HAVE_AES_KEYWRAP */ + +#ifdef WOLFSSL_AES_XTS + +/* Galios Field to use */ +#define GF_XTS 0x87 + +/* 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) +{ + word32 keySz; + int ret = 0; + + if (aes == NULL || key == NULL) { + return 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; +} + + +/* 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); +} + +#ifdef HAVE_AES_ECB +/* helper function for encrypting / decrypting full buffer at once */ +static int _AesXtsHelper(Aes* aes, byte* out, const byte* in, word32 sz, int dir) +{ + word32 outSz = sz; + word32 totalSz = (sz / AES_BLOCK_SIZE) * AES_BLOCK_SIZE; /* total bytes */ + byte* pt = out; + + outSz -= AES_BLOCK_SIZE; + + while (outSz > 0) { + word32 j; + byte carry = 0; + + /* multiply by shift left and propagate carry */ + for (j = 0; j < AES_BLOCK_SIZE && outSz > 0; j++, outSz--) { + byte tmpC; + + tmpC = (pt[j] >> 7) & 0x01; + pt[j+AES_BLOCK_SIZE] = ((pt[j] << 1) + carry) & 0xFF; + carry = tmpC; + } + if (carry) { + pt[AES_BLOCK_SIZE] ^= GF_XTS; + } + + pt += AES_BLOCK_SIZE; + } + + xorbuf(out, in, totalSz); + if (dir == AES_ENCRYPTION) { + return wc_AesEcbEncrypt(aes, out, out, totalSz); + } + else { + return wc_AesEcbDecrypt(aes, out, out, totalSz); + } +} +#endif /* HAVE_AES_ECB */ + + +/* 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 + */ +/* Software AES - XTS Encrypt */ +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); + + #ifdef HAVE_AES_ECB + /* encrypt all of buffer at once when possible */ + if (in != out) { /* can not handle inline */ + XMEMCPY(out, tmp, AES_BLOCK_SIZE); + if ((ret = _AesXtsHelper(aes, out, in, sz, AES_ENCRYPTION)) != 0) { + return ret; + } + } + #endif + + while (blocks > 0) { + word32 j; + byte carry = 0; + byte buf[AES_BLOCK_SIZE]; + + #ifdef HAVE_AES_ECB + if (in == out) { /* check for if inline */ + #endif + XMEMCPY(buf, in, AES_BLOCK_SIZE); + xorbuf(buf, tmp, AES_BLOCK_SIZE); + wc_AesEncryptDirect(aes, out, buf); + #ifdef HAVE_AES_ECB + } + #endif + xorbuf(out, tmp, AES_BLOCK_SIZE); + + /* multiply by shift left and propagate 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 + */ +/* Software AES - XTS Decrypt */ +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--; + } + + #ifdef HAVE_AES_ECB + /* decrypt all of buffer at once when possible */ + if (in != out) { /* can not handle inline */ + XMEMCPY(out, tmp, AES_BLOCK_SIZE); + if ((ret = _AesXtsHelper(aes, out, in, sz, AES_DECRYPTION)) != 0) { + return ret; + } + } + #endif + + while (blocks > 0) { + byte buf[AES_BLOCK_SIZE]; + + #ifdef HAVE_AES_ECB + if (in == out) { /* check for if inline */ + #endif + XMEMCPY(buf, in, AES_BLOCK_SIZE); + xorbuf(buf, tmp, AES_BLOCK_SIZE); + wc_AesDecryptDirect(aes, out, buf); + #ifdef HAVE_AES_ECB + } + #endif + xorbuf(out, tmp, AES_BLOCK_SIZE); + + /* multiply by shift left and propagate 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 propagate 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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_asm.S b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_asm.S new file mode 100644 index 000000000..ae1c801d6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_asm.S @@ -0,0 +1,1338 @@ +/* aes_asm.S + * + * Copyright (C) 2006-2020 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 + */ + + + +/* This file is in at&t asm syntax, see .asm for intel syntax */ + +/* See Intel® Advanced Encryption Standard (AES) Instructions Set White Paper + * by Intel Mobility Group, Israel Development Center, Israel Shay Gueron + */ + + +/* +AES_CBC_encrypt (const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + const unsigned char *KS, + int nr) +*/ +#ifndef __APPLE__ +.globl AES_CBC_encrypt +AES_CBC_encrypt: +#else +.globl _AES_CBC_encrypt +_AES_CBC_encrypt: +#endif +# parameter 1: %rdi +# parameter 2: %rsi +# parameter 3: %rdx +# parameter 4: %rcx +# parameter 5: %r8 +# parameter 6: %r9d +movq %rcx, %r10 +shrq $4, %rcx +shlq $60, %r10 +je NO_PARTS +addq $1, %rcx +NO_PARTS: +subq $16, %rsi +movdqa (%rdx), %xmm1 +LOOP: +pxor (%rdi), %xmm1 +pxor (%r8), %xmm1 +addq $16,%rsi +addq $16,%rdi +cmpl $12, %r9d +aesenc 16(%r8),%xmm1 +aesenc 32(%r8),%xmm1 +aesenc 48(%r8),%xmm1 +aesenc 64(%r8),%xmm1 +aesenc 80(%r8),%xmm1 +aesenc 96(%r8),%xmm1 +aesenc 112(%r8),%xmm1 +aesenc 128(%r8),%xmm1 +aesenc 144(%r8),%xmm1 +movdqa 160(%r8),%xmm2 +jb LAST +cmpl $14, %r9d + +aesenc 160(%r8),%xmm1 +aesenc 176(%r8),%xmm1 +movdqa 192(%r8),%xmm2 +jb LAST +aesenc 192(%r8),%xmm1 +aesenc 208(%r8),%xmm1 +movdqa 224(%r8),%xmm2 +LAST: +decq %rcx +aesenclast %xmm2,%xmm1 +movdqu %xmm1,(%rsi) +jne LOOP +ret + + +#if defined(WOLFSSL_AESNI_BY4) + +/* +AES_CBC_decrypt_by4 (const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + const unsigned char *KS, + int nr) +*/ +#ifndef __APPLE__ +.globl AES_CBC_decrypt_by4 +AES_CBC_decrypt_by4: +#else +.globl _AES_CBC_decrypt_by4 +_AES_CBC_decrypt_by4: +#endif +# parameter 1: %rdi +# parameter 2: %rsi +# parameter 3: %rdx +# parameter 4: %rcx +# parameter 5: %r8 +# parameter 6: %r9d + + movq %rcx, %r10 + shrq $4, %rcx + shlq $60, %r10 + je DNO_PARTS_4 + addq $1, %rcx +DNO_PARTS_4: + movq %rcx, %r10 + shlq $62, %r10 + shrq $62, %r10 + shrq $2, %rcx + movdqu (%rdx),%xmm5 + je DREMAINDER_4 + subq $64, %rsi +DLOOP_4: + movdqu (%rdi), %xmm1 + movdqu 16(%rdi), %xmm2 + movdqu 32(%rdi), %xmm3 + movdqu 48(%rdi), %xmm4 + movdqa %xmm1, %xmm6 + movdqa %xmm2, %xmm7 + movdqa %xmm3, %xmm8 + movdqa %xmm4, %xmm15 + movdqa (%r8), %xmm9 + movdqa 16(%r8), %xmm10 + movdqa 32(%r8), %xmm11 + movdqa 48(%r8), %xmm12 + pxor %xmm9, %xmm1 + pxor %xmm9, %xmm2 + pxor %xmm9, %xmm3 + pxor %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + movdqa 64(%r8), %xmm9 + movdqa 80(%r8), %xmm10 + movdqa 96(%r8), %xmm11 + movdqa 112(%r8), %xmm12 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + movdqa 128(%r8), %xmm9 + movdqa 144(%r8), %xmm10 + movdqa 160(%r8), %xmm11 + cmpl $12, %r9d + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + jb DLAST_4 + movdqa 160(%r8), %xmm9 + movdqa 176(%r8), %xmm10 + movdqa 192(%r8), %xmm11 + cmpl $14, %r9d + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + jb DLAST_4 + movdqa 192(%r8), %xmm9 + movdqa 208(%r8), %xmm10 + movdqa 224(%r8), %xmm11 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 +DLAST_4: + addq $64, %rdi + addq $64, %rsi + decq %rcx + aesdeclast %xmm11, %xmm1 + aesdeclast %xmm11, %xmm2 + aesdeclast %xmm11, %xmm3 + aesdeclast %xmm11, %xmm4 + pxor %xmm5, %xmm1 + pxor %xmm6, %xmm2 + pxor %xmm7, %xmm3 + pxor %xmm8, %xmm4 + movdqu %xmm1, (%rsi) + movdqu %xmm2, 16(%rsi) + movdqu %xmm3, 32(%rsi) + movdqu %xmm4, 48(%rsi) + movdqa %xmm15,%xmm5 + jne DLOOP_4 + addq $64, %rsi +DREMAINDER_4: + cmpq $0, %r10 + je DEND_4 +DLOOP_4_2: + movdqu (%rdi), %xmm1 + movdqa %xmm1, %xmm15 + addq $16, %rdi + pxor (%r8), %xmm1 + movdqu 160(%r8), %xmm2 + cmpl $12, %r9d + aesdec 16(%r8), %xmm1 + aesdec 32(%r8), %xmm1 + aesdec 48(%r8), %xmm1 + aesdec 64(%r8), %xmm1 + aesdec 80(%r8), %xmm1 + aesdec 96(%r8), %xmm1 + aesdec 112(%r8), %xmm1 + aesdec 128(%r8), %xmm1 + aesdec 144(%r8), %xmm1 + jb DLAST_4_2 + movdqu 192(%r8), %xmm2 + cmpl $14, %r9d + aesdec 160(%r8), %xmm1 + aesdec 176(%r8), %xmm1 + jb DLAST_4_2 + movdqu 224(%r8), %xmm2 + aesdec 192(%r8), %xmm1 + aesdec 208(%r8), %xmm1 +DLAST_4_2: + aesdeclast %xmm2, %xmm1 + pxor %xmm5, %xmm1 + movdqa %xmm15, %xmm5 + movdqu %xmm1, (%rsi) + addq $16, %rsi + decq %r10 + jne DLOOP_4_2 +DEND_4: + ret + +#elif defined(WOLFSSL_AESNI_BY6) + +/* +AES_CBC_decrypt_by6 (const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + const unsigned char *KS, + int nr) +*/ +#ifndef __APPLE__ +.globl AES_CBC_decrypt_by6 +AES_CBC_decrypt_by6: +#else +.globl _AES_CBC_decrypt_by6 +_AES_CBC_decrypt_by6: +#endif +# parameter 1: %rdi - in +# parameter 2: %rsi - out +# parameter 3: %rdx - ivec +# parameter 4: %rcx - length +# parameter 5: %r8 - KS +# parameter 6: %r9d - nr + + movq %rcx, %r10 + shrq $4, %rcx + shlq $60, %r10 + je DNO_PARTS_6 + addq $1, %rcx +DNO_PARTS_6: + movq %rax, %r12 + movq %rdx, %r13 + movq %rbx, %r14 + movq $0, %rdx + movq %rcx, %rax + movq $6, %rbx + div %rbx + movq %rax, %rcx + movq %rdx, %r10 + movq %r12, %rax + movq %r13, %rdx + movq %r14, %rbx + cmpq $0, %rcx + movdqu (%rdx), %xmm7 + je DREMAINDER_6 + subq $96, %rsi +DLOOP_6: + movdqu (%rdi), %xmm1 + movdqu 16(%rdi), %xmm2 + movdqu 32(%rdi), %xmm3 + movdqu 48(%rdi), %xmm4 + movdqu 64(%rdi), %xmm5 + movdqu 80(%rdi), %xmm6 + movdqa (%r8), %xmm8 + movdqa 16(%r8), %xmm9 + movdqa 32(%r8), %xmm10 + movdqa 48(%r8), %xmm11 + pxor %xmm8, %xmm1 + pxor %xmm8, %xmm2 + pxor %xmm8, %xmm3 + pxor %xmm8, %xmm4 + pxor %xmm8, %xmm5 + pxor %xmm8, %xmm6 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm9, %xmm5 + aesdec %xmm9, %xmm6 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm10, %xmm5 + aesdec %xmm10, %xmm6 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + movdqa 64(%r8), %xmm8 + movdqa 80(%r8), %xmm9 + movdqa 96(%r8), %xmm10 + movdqa 112(%r8), %xmm11 + aesdec %xmm8, %xmm1 + aesdec %xmm8, %xmm2 + aesdec %xmm8, %xmm3 + aesdec %xmm8, %xmm4 + aesdec %xmm8, %xmm5 + aesdec %xmm8, %xmm6 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm9, %xmm5 + aesdec %xmm9, %xmm6 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm10, %xmm5 + aesdec %xmm10, %xmm6 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + movdqa 128(%r8), %xmm8 + movdqa 144(%r8), %xmm9 + movdqa 160(%r8), %xmm10 + cmpl $12, %r9d + aesdec %xmm8, %xmm1 + aesdec %xmm8, %xmm2 + aesdec %xmm8, %xmm3 + aesdec %xmm8, %xmm4 + aesdec %xmm8, %xmm5 + aesdec %xmm8, %xmm6 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm9, %xmm5 + aesdec %xmm9, %xmm6 + jb DLAST_6 + movdqa 160(%r8), %xmm8 + movdqa 176(%r8), %xmm9 + movdqa 192(%r8), %xmm10 + cmpl $14, %r9d + aesdec %xmm8, %xmm1 + aesdec %xmm8, %xmm2 + aesdec %xmm8, %xmm3 + aesdec %xmm8, %xmm4 + aesdec %xmm8, %xmm5 + aesdec %xmm8, %xmm6 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm9, %xmm5 + aesdec %xmm9, %xmm6 + jb DLAST_6 + movdqa 192(%r8), %xmm8 + movdqa 208(%r8), %xmm9 + movdqa 224(%r8), %xmm10 + aesdec %xmm8, %xmm1 + aesdec %xmm8, %xmm2 + aesdec %xmm8, %xmm3 + aesdec %xmm8, %xmm4 + aesdec %xmm8, %xmm5 + aesdec %xmm8, %xmm6 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm9, %xmm5 + aesdec %xmm9, %xmm6 +DLAST_6: + addq $96, %rsi + aesdeclast %xmm10, %xmm1 + aesdeclast %xmm10, %xmm2 + aesdeclast %xmm10, %xmm3 + aesdeclast %xmm10, %xmm4 + aesdeclast %xmm10, %xmm5 + aesdeclast %xmm10, %xmm6 + movdqu (%rdi), %xmm8 + movdqu 16(%rdi), %xmm9 + movdqu 32(%rdi), %xmm10 + movdqu 48(%rdi), %xmm11 + movdqu 64(%rdi), %xmm12 + movdqu 80(%rdi), %xmm13 + pxor %xmm7, %xmm1 + pxor %xmm8, %xmm2 + pxor %xmm9, %xmm3 + pxor %xmm10, %xmm4 + pxor %xmm11, %xmm5 + pxor %xmm12, %xmm6 + movdqu %xmm13, %xmm7 + movdqu %xmm1, (%rsi) + movdqu %xmm2, 16(%rsi) + movdqu %xmm3, 32(%rsi) + movdqu %xmm4, 48(%rsi) + movdqu %xmm5, 64(%rsi) + movdqu %xmm6, 80(%rsi) + addq $96, %rdi + decq %rcx + jne DLOOP_6 + addq $96, %rsi +DREMAINDER_6: + cmpq $0, %r10 + je DEND_6 +DLOOP_6_2: + movdqu (%rdi), %xmm1 + movdqa %xmm1, %xmm10 + addq $16, %rdi + pxor (%r8), %xmm1 + movdqu 160(%r8), %xmm2 + cmpl $12, %r9d + aesdec 16(%r8), %xmm1 + aesdec 32(%r8), %xmm1 + aesdec 48(%r8), %xmm1 + aesdec 64(%r8), %xmm1 + aesdec 80(%r8), %xmm1 + aesdec 96(%r8), %xmm1 + aesdec 112(%r8), %xmm1 + aesdec 128(%r8), %xmm1 + aesdec 144(%r8), %xmm1 + jb DLAST_6_2 + movdqu 192(%r8), %xmm2 + cmpl $14, %r9d + aesdec 160(%r8), %xmm1 + aesdec 176(%r8), %xmm1 + jb DLAST_6_2 + movdqu 224(%r8), %xmm2 + aesdec 192(%r8), %xmm1 + aesdec 208(%r8), %xmm1 +DLAST_6_2: + aesdeclast %xmm2, %xmm1 + pxor %xmm7, %xmm1 + movdqa %xmm10, %xmm7 + movdqu %xmm1, (%rsi) + addq $16, %rsi + decq %r10 + jne DLOOP_6_2 +DEND_6: + ret + +#else /* WOLFSSL_AESNI_BYx */ + +/* +AES_CBC_decrypt_by8 (const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + const unsigned char *KS, + int nr) +*/ +#ifndef __APPLE__ +.globl AES_CBC_decrypt_by8 +AES_CBC_decrypt_by8: +#else +.globl _AES_CBC_decrypt_by8 +_AES_CBC_decrypt_by8: +#endif +# parameter 1: %rdi - in +# parameter 2: %rsi - out +# parameter 3: %rdx - ivec +# parameter 4: %rcx - length +# parameter 5: %r8 - KS +# parameter 6: %r9d - nr + + movq %rcx, %r10 + shrq $4, %rcx + shlq $60, %r10 + je DNO_PARTS_8 + addq $1, %rcx +DNO_PARTS_8: + movq %rcx, %r10 + shlq $61, %r10 + shrq $61, %r10 + shrq $3, %rcx + movdqu (%rdx), %xmm9 + je DREMAINDER_8 + subq $128, %rsi +DLOOP_8: + movdqu (%rdi), %xmm1 + movdqu 16(%rdi), %xmm2 + movdqu 32(%rdi), %xmm3 + movdqu 48(%rdi), %xmm4 + movdqu 64(%rdi), %xmm5 + movdqu 80(%rdi), %xmm6 + movdqu 96(%rdi), %xmm7 + movdqu 112(%rdi), %xmm8 + movdqa (%r8), %xmm10 + movdqa 16(%r8), %xmm11 + movdqa 32(%r8), %xmm12 + movdqa 48(%r8), %xmm13 + pxor %xmm10, %xmm1 + pxor %xmm10, %xmm2 + pxor %xmm10, %xmm3 + pxor %xmm10, %xmm4 + pxor %xmm10, %xmm5 + pxor %xmm10, %xmm6 + pxor %xmm10, %xmm7 + pxor %xmm10, %xmm8 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + aesdec %xmm11, %xmm7 + aesdec %xmm11, %xmm8 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + aesdec %xmm12, %xmm5 + aesdec %xmm12, %xmm6 + aesdec %xmm12, %xmm7 + aesdec %xmm12, %xmm8 + aesdec %xmm13, %xmm1 + aesdec %xmm13, %xmm2 + aesdec %xmm13, %xmm3 + aesdec %xmm13, %xmm4 + aesdec %xmm13, %xmm5 + aesdec %xmm13, %xmm6 + aesdec %xmm13, %xmm7 + aesdec %xmm13, %xmm8 + movdqa 64(%r8), %xmm10 + movdqa 80(%r8), %xmm11 + movdqa 96(%r8), %xmm12 + movdqa 112(%r8), %xmm13 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm10, %xmm5 + aesdec %xmm10, %xmm6 + aesdec %xmm10, %xmm7 + aesdec %xmm10, %xmm8 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + aesdec %xmm11, %xmm7 + aesdec %xmm11, %xmm8 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + aesdec %xmm12, %xmm5 + aesdec %xmm12, %xmm6 + aesdec %xmm12, %xmm7 + aesdec %xmm12, %xmm8 + aesdec %xmm13, %xmm1 + aesdec %xmm13, %xmm2 + aesdec %xmm13, %xmm3 + aesdec %xmm13, %xmm4 + aesdec %xmm13, %xmm5 + aesdec %xmm13, %xmm6 + aesdec %xmm13, %xmm7 + aesdec %xmm13, %xmm8 + movdqa 128(%r8), %xmm10 + movdqa 144(%r8), %xmm11 + movdqa 160(%r8), %xmm12 + cmpl $12, %r9d + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm10, %xmm5 + aesdec %xmm10, %xmm6 + aesdec %xmm10, %xmm7 + aesdec %xmm10, %xmm8 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + aesdec %xmm11, %xmm7 + aesdec %xmm11, %xmm8 + jb DLAST_8 + movdqa 160(%r8), %xmm10 + movdqa 176(%r8), %xmm11 + movdqa 192(%r8), %xmm12 + cmpl $14, %r9d + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm10, %xmm5 + aesdec %xmm10, %xmm6 + aesdec %xmm10, %xmm7 + aesdec %xmm10, %xmm8 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + aesdec %xmm11, %xmm7 + aesdec %xmm11, %xmm8 + jb DLAST_8 + movdqa 192(%r8), %xmm10 + movdqa 208(%r8), %xmm11 + movdqa 224(%r8), %xmm12 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm10, %xmm5 + aesdec %xmm10, %xmm6 + aesdec %xmm10, %xmm7 + aesdec %xmm10, %xmm8 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + aesdec %xmm11, %xmm7 + aesdec %xmm11, %xmm8 +DLAST_8: + addq $128, %rsi + aesdeclast %xmm12, %xmm1 + aesdeclast %xmm12, %xmm2 + aesdeclast %xmm12, %xmm3 + aesdeclast %xmm12, %xmm4 + aesdeclast %xmm12, %xmm5 + aesdeclast %xmm12, %xmm6 + aesdeclast %xmm12, %xmm7 + aesdeclast %xmm12, %xmm8 + movdqu (%rdi), %xmm10 + movdqu 16(%rdi), %xmm11 + movdqu 32(%rdi), %xmm12 + movdqu 48(%rdi), %xmm13 + pxor %xmm9, %xmm1 + pxor %xmm10, %xmm2 + pxor %xmm11, %xmm3 + pxor %xmm12, %xmm4 + pxor %xmm13, %xmm5 + movdqu 64(%rdi), %xmm10 + movdqu 80(%rdi), %xmm11 + movdqu 96(%rdi), %xmm12 + movdqu 112(%rdi), %xmm9 + pxor %xmm10, %xmm6 + pxor %xmm11, %xmm7 + pxor %xmm12, %xmm8 + movdqu %xmm1, (%rsi) + movdqu %xmm2, 16(%rsi) + movdqu %xmm3, 32(%rsi) + movdqu %xmm4, 48(%rsi) + movdqu %xmm5, 64(%rsi) + movdqu %xmm6, 80(%rsi) + movdqu %xmm7, 96(%rsi) + movdqu %xmm8, 112(%rsi) + addq $128, %rdi + decq %rcx + jne DLOOP_8 + addq $128, %rsi +DREMAINDER_8: + cmpq $0, %r10 + je DEND_8 +DLOOP_8_2: + movdqu (%rdi), %xmm1 + movdqa %xmm1, %xmm10 + addq $16, %rdi + pxor (%r8), %xmm1 + movdqu 160(%r8), %xmm2 + cmpl $12, %r9d + aesdec 16(%r8), %xmm1 + aesdec 32(%r8), %xmm1 + aesdec 48(%r8), %xmm1 + aesdec 64(%r8), %xmm1 + aesdec 80(%r8), %xmm1 + aesdec 96(%r8), %xmm1 + aesdec 112(%r8), %xmm1 + aesdec 128(%r8), %xmm1 + aesdec 144(%r8), %xmm1 + jb DLAST_8_2 + movdqu 192(%r8), %xmm2 + cmpl $14, %r9d + aesdec 160(%r8), %xmm1 + aesdec 176(%r8), %xmm1 + jb DLAST_8_2 + movdqu 224(%r8), %xmm2 + aesdec 192(%r8), %xmm1 + aesdec 208(%r8), %xmm1 +DLAST_8_2: + aesdeclast %xmm2, %xmm1 + pxor %xmm9, %xmm1 + movdqa %xmm10, %xmm9 + movdqu %xmm1, (%rsi) + addq $16, %rsi + decq %r10 + jne DLOOP_8_2 +DEND_8: + ret + +#endif /* WOLFSSL_AESNI_BYx */ + + +/* +AES_ECB_encrypt (const unsigned char *in, + unsigned char *out, + unsigned long length, + const unsigned char *KS, + int nr) +*/ +#ifndef __APPLE__ +.globl AES_ECB_encrypt +AES_ECB_encrypt: +#else +.globl _AES_ECB_encrypt +_AES_ECB_encrypt: +#endif +# parameter 1: %rdi +# parameter 2: %rsi +# parameter 3: %rdx +# parameter 4: %rcx +# parameter 5: %r8d + movq %rdx, %r10 + shrq $4, %rdx + shlq $60, %r10 + je EECB_NO_PARTS_4 + addq $1, %rdx +EECB_NO_PARTS_4: + movq %rdx, %r10 + shlq $62, %r10 + shrq $62, %r10 + shrq $2, %rdx + je EECB_REMAINDER_4 + subq $64, %rsi +EECB_LOOP_4: + movdqu (%rdi), %xmm1 + movdqu 16(%rdi), %xmm2 + movdqu 32(%rdi), %xmm3 + movdqu 48(%rdi), %xmm4 + movdqa (%rcx), %xmm9 + movdqa 16(%rcx), %xmm10 + movdqa 32(%rcx), %xmm11 + movdqa 48(%rcx), %xmm12 + pxor %xmm9, %xmm1 + pxor %xmm9, %xmm2 + pxor %xmm9, %xmm3 + pxor %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 + aesenc %xmm11, %xmm1 + aesenc %xmm11, %xmm2 + aesenc %xmm11, %xmm3 + aesenc %xmm11, %xmm4 + aesenc %xmm12, %xmm1 + aesenc %xmm12, %xmm2 + aesenc %xmm12, %xmm3 + aesenc %xmm12, %xmm4 + movdqa 64(%rcx), %xmm9 + movdqa 80(%rcx), %xmm10 + movdqa 96(%rcx), %xmm11 + movdqa 112(%rcx), %xmm12 + aesenc %xmm9, %xmm1 + aesenc %xmm9, %xmm2 + aesenc %xmm9, %xmm3 + aesenc %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 + aesenc %xmm11, %xmm1 + aesenc %xmm11, %xmm2 + aesenc %xmm11, %xmm3 + aesenc %xmm11, %xmm4 + aesenc %xmm12, %xmm1 + aesenc %xmm12, %xmm2 + aesenc %xmm12, %xmm3 + aesenc %xmm12, %xmm4 + movdqa 128(%rcx), %xmm9 + movdqa 144(%rcx), %xmm10 + movdqa 160(%rcx), %xmm11 + cmpl $12, %r8d + aesenc %xmm9, %xmm1 + aesenc %xmm9, %xmm2 + aesenc %xmm9, %xmm3 + aesenc %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 + jb EECB_LAST_4 + movdqa 160(%rcx), %xmm9 + movdqa 176(%rcx), %xmm10 + movdqa 192(%rcx), %xmm11 + cmpl $14, %r8d + aesenc %xmm9, %xmm1 + aesenc %xmm9, %xmm2 + aesenc %xmm9, %xmm3 + aesenc %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 + jb EECB_LAST_4 + movdqa 192(%rcx), %xmm9 + movdqa 208(%rcx), %xmm10 + movdqa 224(%rcx), %xmm11 + aesenc %xmm9, %xmm1 + aesenc %xmm9, %xmm2 + aesenc %xmm9, %xmm3 + aesenc %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 +EECB_LAST_4: + addq $64, %rdi + addq $64, %rsi + decq %rdx + aesenclast %xmm11, %xmm1 + aesenclast %xmm11, %xmm2 + aesenclast %xmm11, %xmm3 + aesenclast %xmm11, %xmm4 + movdqu %xmm1, (%rsi) + movdqu %xmm2, 16(%rsi) + movdqu %xmm3, 32(%rsi) + movdqu %xmm4, 48(%rsi) + jne EECB_LOOP_4 + addq $64, %rsi +EECB_REMAINDER_4: + cmpq $0, %r10 + je EECB_END_4 +EECB_LOOP_4_2: + movdqu (%rdi), %xmm1 + addq $16, %rdi + pxor (%rcx), %xmm1 + movdqu 160(%rcx), %xmm2 + aesenc 16(%rcx), %xmm1 + aesenc 32(%rcx), %xmm1 + aesenc 48(%rcx), %xmm1 + aesenc 64(%rcx), %xmm1 + aesenc 80(%rcx), %xmm1 + aesenc 96(%rcx), %xmm1 + aesenc 112(%rcx), %xmm1 + aesenc 128(%rcx), %xmm1 + aesenc 144(%rcx), %xmm1 + cmpl $12, %r8d + jb EECB_LAST_4_2 + movdqu 192(%rcx), %xmm2 + aesenc 160(%rcx), %xmm1 + aesenc 176(%rcx), %xmm1 + cmpl $14, %r8d + jb EECB_LAST_4_2 + movdqu 224(%rcx), %xmm2 + aesenc 192(%rcx), %xmm1 + aesenc 208(%rcx), %xmm1 +EECB_LAST_4_2: + aesenclast %xmm2, %xmm1 + movdqu %xmm1, (%rsi) + addq $16, %rsi + decq %r10 + jne EECB_LOOP_4_2 +EECB_END_4: + ret + + +/* +AES_ECB_decrypt (const unsigned char *in, + unsigned char *out, + unsigned long length, + const unsigned char *KS, + int nr) +*/ +#ifndef __APPLE__ +.globl AES_ECB_decrypt +AES_ECB_decrypt: +#else +.globl _AES_ECB_decrypt +_AES_ECB_decrypt: +#endif +# parameter 1: %rdi +# parameter 2: %rsi +# parameter 3: %rdx +# parameter 4: %rcx +# parameter 5: %r8d + + movq %rdx, %r10 + shrq $4, %rdx + shlq $60, %r10 + je DECB_NO_PARTS_4 + addq $1, %rdx +DECB_NO_PARTS_4: + movq %rdx, %r10 + shlq $62, %r10 + shrq $62, %r10 + shrq $2, %rdx + je DECB_REMAINDER_4 + subq $64, %rsi +DECB_LOOP_4: + movdqu (%rdi), %xmm1 + movdqu 16(%rdi), %xmm2 + movdqu 32(%rdi), %xmm3 + movdqu 48(%rdi), %xmm4 + movdqa (%rcx), %xmm9 + movdqa 16(%rcx), %xmm10 + movdqa 32(%rcx), %xmm11 + movdqa 48(%rcx), %xmm12 + pxor %xmm9, %xmm1 + pxor %xmm9, %xmm2 + pxor %xmm9, %xmm3 + pxor %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + movdqa 64(%rcx), %xmm9 + movdqa 80(%rcx), %xmm10 + movdqa 96(%rcx), %xmm11 + movdqa 112(%rcx), %xmm12 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + movdqa 128(%rcx), %xmm9 + movdqa 144(%rcx), %xmm10 + movdqa 160(%rcx), %xmm11 + cmpl $12, %r8d + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + jb DECB_LAST_4 + movdqa 160(%rcx), %xmm9 + movdqa 176(%rcx), %xmm10 + movdqa 192(%rcx), %xmm11 + cmpl $14, %r8d + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + jb DECB_LAST_4 + movdqa 192(%rcx), %xmm9 + movdqa 208(%rcx), %xmm10 + movdqa 224(%rcx), %xmm11 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 +DECB_LAST_4: + addq $64, %rdi + addq $64, %rsi + decq %rdx + aesdeclast %xmm11, %xmm1 + aesdeclast %xmm11, %xmm2 + aesdeclast %xmm11, %xmm3 + aesdeclast %xmm11, %xmm4 + movdqu %xmm1, (%rsi) + movdqu %xmm2, 16(%rsi) + movdqu %xmm3, 32(%rsi) + movdqu %xmm4, 48(%rsi) + jne DECB_LOOP_4 + addq $64, %rsi +DECB_REMAINDER_4: + cmpq $0, %r10 + je DECB_END_4 +DECB_LOOP_4_2: + movdqu (%rdi), %xmm1 + addq $16, %rdi + pxor (%rcx), %xmm1 + movdqu 160(%rcx), %xmm2 + cmpl $12, %r8d + aesdec 16(%rcx), %xmm1 + aesdec 32(%rcx), %xmm1 + aesdec 48(%rcx), %xmm1 + aesdec 64(%rcx), %xmm1 + aesdec 80(%rcx), %xmm1 + aesdec 96(%rcx), %xmm1 + aesdec 112(%rcx), %xmm1 + aesdec 128(%rcx), %xmm1 + aesdec 144(%rcx), %xmm1 + jb DECB_LAST_4_2 + cmpl $14, %r8d + movdqu 192(%rcx), %xmm2 + aesdec 160(%rcx), %xmm1 + aesdec 176(%rcx), %xmm1 + jb DECB_LAST_4_2 + movdqu 224(%rcx), %xmm2 + aesdec 192(%rcx), %xmm1 + aesdec 208(%rcx), %xmm1 +DECB_LAST_4_2: + aesdeclast %xmm2, %xmm1 + movdqu %xmm1, (%rsi) + addq $16, %rsi + decq %r10 + jne DECB_LOOP_4_2 +DECB_END_4: + ret + + + + +/* +void AES_128_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule); +*/ +.align 16,0x90 +#ifndef __APPLE__ +.globl AES_128_Key_Expansion +AES_128_Key_Expansion: +#else +.globl _AES_128_Key_Expansion +_AES_128_Key_Expansion: +#endif +# parameter 1: %rdi +# parameter 2: %rsi +movl $10, 240(%rsi) + +movdqu (%rdi), %xmm1 +movdqa %xmm1, (%rsi) + + +ASSISTS: +aeskeygenassist $1, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 16(%rsi) +aeskeygenassist $2, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 32(%rsi) +aeskeygenassist $4, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 48(%rsi) +aeskeygenassist $8, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 64(%rsi) +aeskeygenassist $16, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 80(%rsi) +aeskeygenassist $32, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 96(%rsi) +aeskeygenassist $64, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 112(%rsi) +aeskeygenassist $0x80, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 128(%rsi) +aeskeygenassist $0x1b, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 144(%rsi) +aeskeygenassist $0x36, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 160(%rsi) +ret + +PREPARE_ROUNDKEY_128: +pshufd $255, %xmm2, %xmm2 +movdqa %xmm1, %xmm3 +pslldq $4, %xmm3 +pxor %xmm3, %xmm1 +pslldq $4, %xmm3 +pxor %xmm3, %xmm1 +pslldq $4, %xmm3 +pxor %xmm3, %xmm1 +pxor %xmm2, %xmm1 +ret + + +/* +void AES_192_Key_Expansion (const unsigned char *userkey, + unsigned char *key) +*/ +#ifndef __APPLE__ +.globl AES_192_Key_Expansion +AES_192_Key_Expansion: +#else +.globl _AES_192_Key_Expansion +_AES_192_Key_Expansion: +#endif +# parameter 1: %rdi +# parameter 2: %rsi + +movdqu (%rdi), %xmm1 +movq 16(%rdi), %xmm3 +movdqa %xmm1, (%rsi) +movdqa %xmm3, %xmm5 + +aeskeygenassist $0x1, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +shufpd $0, %xmm1, %xmm5 +movdqa %xmm5, 16(%rsi) +movdqa %xmm1, %xmm6 +shufpd $1, %xmm3, %xmm6 +movdqa %xmm6, 32(%rsi) + +aeskeygenassist $0x2, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +movdqa %xmm1, 48(%rsi) +movdqa %xmm3, %xmm5 + +aeskeygenassist $0x4, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +shufpd $0, %xmm1, %xmm5 +movdqa %xmm5, 64(%rsi) +movdqa %xmm1, %xmm6 +shufpd $1, %xmm3, %xmm6 +movdqa %xmm6, 80(%rsi) + +aeskeygenassist $0x8, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +movdqa %xmm1, 96(%rsi) +movdqa %xmm3, %xmm5 + +aeskeygenassist $0x10, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +shufpd $0, %xmm1, %xmm5 +movdqa %xmm5, 112(%rsi) +movdqa %xmm1, %xmm6 +shufpd $1, %xmm3, %xmm6 +movdqa %xmm6, 128(%rsi) + +aeskeygenassist $0x20, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +movdqa %xmm1, 144(%rsi) +movdqa %xmm3, %xmm5 + +aeskeygenassist $0x40, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +shufpd $0, %xmm1, %xmm5 +movdqa %xmm5, 160(%rsi) +movdqa %xmm1, %xmm6 +shufpd $1, %xmm3, %xmm6 +movdqa %xmm6, 176(%rsi) + +aeskeygenassist $0x80, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +movdqa %xmm1, 192(%rsi) +movdqa %xmm3, 208(%rsi) +ret + +PREPARE_ROUNDKEY_192: +pshufd $0x55, %xmm2, %xmm2 +movdqu %xmm1, %xmm4 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 + +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pxor %xmm2, %xmm1 +pshufd $0xff, %xmm1, %xmm2 +movdqu %xmm3, %xmm4 +pslldq $4, %xmm4 +pxor %xmm4, %xmm3 +pxor %xmm2, %xmm3 +ret + + +/* +void AES_256_Key_Expansion (const unsigned char *userkey, + unsigned char *key) +*/ +#ifndef __APPLE__ +.globl AES_256_Key_Expansion +AES_256_Key_Expansion: +#else +.globl _AES_256_Key_Expansion +_AES_256_Key_Expansion: +#endif +# parameter 1: %rdi +# parameter 2: %rsi + +movdqu (%rdi), %xmm1 +movdqu 16(%rdi), %xmm3 +movdqa %xmm1, (%rsi) +movdqa %xmm3, 16(%rsi) + +aeskeygenassist $0x1, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 32(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 48(%rsi) +aeskeygenassist $0x2, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 64(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 80(%rsi) +aeskeygenassist $0x4, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 96(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 112(%rsi) +aeskeygenassist $0x8, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 128(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 144(%rsi) +aeskeygenassist $0x10, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 160(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 176(%rsi) +aeskeygenassist $0x20, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 192(%rsi) + +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 208(%rsi) +aeskeygenassist $0x40, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 224(%rsi) + +ret + +MAKE_RK256_a: +pshufd $0xff, %xmm2, %xmm2 +movdqa %xmm1, %xmm4 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pxor %xmm2, %xmm1 +ret + +MAKE_RK256_b: +pshufd $0xaa, %xmm2, %xmm2 +movdqa %xmm3, %xmm4 +pslldq $4, %xmm4 +pxor %xmm4, %xmm3 +pslldq $4, %xmm4 +pxor %xmm4, %xmm3 +pslldq $4, %xmm4 +pxor %xmm4, %xmm3 +pxor %xmm2, %xmm3 +ret + +#if defined(__linux__) && defined(__ELF__) + .section .note.GNU-stack,"",%progbits +#endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_asm.asm b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_asm.asm index 1e3d2d99e..b3cc94d9e 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_asm.asm +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_asm.asm @@ -1,31 +1,49 @@ -; /*aes_asm . asm -; * -; *Copyright[C]2006 -2014 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 -; */ +; /* aes_asm.asm +; * +; * Copyright (C) 2006-2020 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 +; */ + ; ; -; /*See IntelA dvanced Encryption Standard[AES]Instructions Set White Paper -; *by Israel,Intel Mobility Group Development Center,Israel Shay Gueron -; */ +; /* See Intel Advanced Encryption Standard (AES) Instructions Set White Paper +; * by Israel, Intel Mobility Group Development Center, Israel Shay Gueron +; */ ; ; /* This file is in intel asm syntax, see .s for at&t syntax */ ; + + +fips_version = 0 +IFDEF HAVE_FIPS + fips_version = 1 + IFDEF HAVE_FIPS_VERSION + fips_version = HAVE_FIPS_VERSION + ENDIF +ENDIF + +IF fips_version GE 2 + fipsAh SEGMENT ALIAS(".fipsA$h") 'CODE' +ELSE + _text SEGMENT +ENDIF + + ; /* ; AES_CBC_encrypt[const ,unsigned char*in ; unsigned ,char*out @@ -34,7 +52,6 @@ ; const ,unsigned char*KS ; int nr] ; */ -_text SEGMENT AES_CBC_encrypt PROC ;# parameter 1: rdi ;# parameter 2: rsi @@ -101,220 +118,753 @@ LAST: AES_CBC_encrypt ENDP +; void AES_CBC_decrypt_by4(const unsigned char* in, +; unsigned char* out, +; unsigned char ivec[16], +; unsigned long length, +; const unsigned char* KS, +; int nr) +AES_CBC_decrypt_by4 PROC +; parameter 1: rdi +; parameter 2: rsi +; parameter 3: rdx +; parameter 4: rcx +; parameter 5: r8 +; parameter 6: r9d -; /* -; AES_CBC_decrypt[const ,unsigned char*in -; unsigned ,char*out -; unsigned ,char ivec+16 -; unsigned ,long length -; const ,unsigned char*KS -; int nr] -; */ -; . globl AES_CBC_decrypt -AES_CBC_decrypt PROC -;# parameter 1: rdi -;# parameter 2: rsi -;# parameter 3: rdx -;# parameter 4: rcx -;# parameter 5: r8 -;# parameter 6: r9d - -; save rdi and rsi to rax and r11, restore before ret - mov rax,rdi - mov r11,rsi - -; convert to what we had for att&t convention - mov rdi,rcx - mov rsi,rdx - mov rdx,r8 - mov rcx,r9 - mov r8,[rsp+40] - mov r9d,[rsp+48] - -; on microsoft xmm6-xmm15 are non volaitle, let's save on stack and restore at end - sub rsp,8+8*16 ; 8 = align stack , 8 xmm6-12,15 16 bytes each - movdqa [rsp+0], xmm6 - movdqa [rsp+16], xmm7 - movdqa [rsp+32], xmm8 - movdqa [rsp+48], xmm9 - movdqa [rsp+64], xmm10 - movdqa [rsp+80], xmm11 - movdqa [rsp+96], xmm12 - movdqa [rsp+112], xmm15 - - mov r10,rcx - shr rcx,4 - shl r10,60 - je DNO_PARTS_4 - add rcx,1 + ; save rdi and rsi to rax and r11, restore before ret + mov rax, rdi + mov r11, rsi + ; convert to what we had for att&t convention + mov rdi, rcx + mov rsi, rdx + mov rdx, r8 + mov rcx,r9 + mov r8, [rsp+40] + mov r9d, [rsp+48] + ; on microsoft xmm6-xmm15 are non volatile, + ; let's save on stack and restore at end + sub rsp, 8+8*16 ; 8 = align stack , 8 xmm6-12,15 16 bytes each + movdqa [rsp+0], xmm6 + movdqa [rsp+16], xmm7 + movdqa [rsp+32], xmm8 + movdqa [rsp+48], xmm9 + movdqa [rsp+64], xmm10 + movdqa [rsp+80], xmm11 + movdqa [rsp+96], xmm12 + movdqa [rsp+112], xmm15 + ; back to our original code, more or less + mov r10, rcx + shr rcx, 4 + shl r10, 60 + je DNO_PARTS_4 + add rcx, 1 DNO_PARTS_4: - mov r10,rcx - shl r10,62 - shr r10,62 - shr rcx,2 - movdqu xmm5,[rdx] - je DREMAINDER_4 - sub rsi,64 + mov r10, rcx + shl r10, 62 + shr r10, 62 + shr rcx, 2 + movdqu xmm5, [rdx] + je DREMAINDER_4 + sub rsi, 64 DLOOP_4: - movdqu xmm1,[rdi] - movdqu xmm2,16[rdi] - movdqu xmm3,32[rdi] - movdqu xmm4,48[rdi] - movdqa xmm6,xmm1 - movdqa xmm7,xmm2 - movdqa xmm8,xmm3 - movdqa xmm15,xmm4 - movdqa xmm9,[r8] - movdqa xmm10,16[r8] - movdqa xmm11,32[r8] - movdqa xmm12,48[r8] - pxor xmm1,xmm9 - pxor xmm2,xmm9 - pxor xmm3,xmm9 - - pxor xmm4,xmm9 - aesdec xmm1,xmm10 - aesdec xmm2,xmm10 - aesdec xmm3,xmm10 - aesdec xmm4,xmm10 - aesdec xmm1,xmm11 - aesdec xmm2,xmm11 - aesdec xmm3,xmm11 - aesdec xmm4,xmm11 - aesdec xmm1,xmm12 - aesdec xmm2,xmm12 - aesdec xmm3,xmm12 - aesdec xmm4,xmm12 - movdqa xmm9,64[r8] - movdqa xmm10,80[r8] - movdqa xmm11,96[r8] - movdqa xmm12,112[r8] - aesdec xmm1,xmm9 - aesdec xmm2,xmm9 - aesdec xmm3,xmm9 - aesdec xmm4,xmm9 - aesdec xmm1,xmm10 - aesdec xmm2,xmm10 - aesdec xmm3,xmm10 - aesdec xmm4,xmm10 - aesdec xmm1,xmm11 - aesdec xmm2,xmm11 - aesdec xmm3,xmm11 - aesdec xmm4,xmm11 - aesdec xmm1,xmm12 - aesdec xmm2,xmm12 - aesdec xmm3,xmm12 - aesdec xmm4,xmm12 - movdqa xmm9,128[r8] - movdqa xmm10,144[r8] - movdqa xmm11,160[r8] - cmp r9d,12 - aesdec xmm1,xmm9 - aesdec xmm2,xmm9 - aesdec xmm3,xmm9 - aesdec xmm4,xmm9 - aesdec xmm1,xmm10 - aesdec xmm2,xmm10 - aesdec xmm3,xmm10 - aesdec xmm4,xmm10 - jb DLAST_4 - movdqa xmm9,160[r8] - movdqa xmm10,176[r8] - movdqa xmm11,192[r8] - cmp r9d,14 - aesdec xmm1,xmm9 - aesdec xmm2,xmm9 - aesdec xmm3,xmm9 - aesdec xmm4,xmm9 - aesdec xmm1,xmm10 - aesdec xmm2,xmm10 - aesdec xmm3,xmm10 - aesdec xmm4,xmm10 - jb DLAST_4 - - movdqa xmm9,192[r8] - movdqa xmm10,208[r8] - movdqa xmm11,224[r8] - aesdec xmm1,xmm9 - aesdec xmm2,xmm9 - aesdec xmm3,xmm9 - aesdec xmm4,xmm9 - aesdec xmm1,xmm10 - aesdec xmm2,xmm10 - aesdec xmm3,xmm10 - aesdec xmm4,xmm10 + movdqu xmm1, [rdi] + movdqu xmm2, 16[rdi] + movdqu xmm3, 32[rdi] + movdqu xmm4, 48[rdi] + movdqa xmm6, xmm1 + movdqa xmm7, xmm2 + movdqa xmm8, xmm3 + movdqa xmm15, xmm4 + movdqa xmm9, [r8] + movdqa xmm10, 16[r8] + movdqa xmm11, 32[r8] + movdqa xmm12, 48[r8] + pxor xmm1, xmm9 + pxor xmm2, xmm9 + pxor xmm3, xmm9 + pxor xmm4, xmm9 + aesdec xmm1, xmm10 + aesdec xmm2, xmm10 + aesdec xmm3, xmm10 + aesdec xmm4, xmm10 + aesdec xmm1, xmm11 + aesdec xmm2, xmm11 + aesdec xmm3, xmm11 + aesdec xmm4, xmm11 + aesdec xmm1, xmm12 + aesdec xmm2, xmm12 + aesdec xmm3, xmm12 + aesdec xmm4, xmm12 + movdqa xmm9, 64[r8] + movdqa xmm10, 80[r8] + movdqa xmm11, 96[r8] + movdqa xmm12, 112[r8] + aesdec xmm1, xmm9 + aesdec xmm2, xmm9 + aesdec xmm3, xmm9 + aesdec xmm4, xmm9 + aesdec xmm1, xmm10 + aesdec xmm2, xmm10 + aesdec xmm3, xmm10 + aesdec xmm4, xmm10 + aesdec xmm1, xmm11 + aesdec xmm2, xmm11 + aesdec xmm3, xmm11 + aesdec xmm4, xmm11 + aesdec xmm1, xmm12 + aesdec xmm2, xmm12 + aesdec xmm3, xmm12 + aesdec xmm4, xmm12 + movdqa xmm9, 128[r8] + movdqa xmm10, 144[r8] + movdqa xmm11, 160[r8] + cmp r9d, 12 + aesdec xmm1, xmm9 + aesdec xmm2, xmm9 + aesdec xmm3, xmm9 + aesdec xmm4, xmm9 + aesdec xmm1, xmm10 + aesdec xmm2, xmm10 + aesdec xmm3, xmm10 + aesdec xmm4, xmm10 + jb DLAST_4 + movdqa xmm9, 160[r8] + movdqa xmm10, 176[r8] + movdqa xmm11, 192[r8] + cmp r9d, 14 + aesdec xmm1, xmm9 + aesdec xmm2, xmm9 + aesdec xmm3, xmm9 + aesdec xmm4, xmm9 + aesdec xmm1, xmm10 + aesdec xmm2, xmm10 + aesdec xmm3, xmm10 + aesdec xmm4, xmm10 + jb DLAST_4 + movdqa xmm9, 192[r8] + movdqa xmm10, 208[r8] + movdqa xmm11, 224[r8] + aesdec xmm1, xmm9 + aesdec xmm2, xmm9 + aesdec xmm3, xmm9 + aesdec xmm4, xmm9 + aesdec xmm1, xmm10 + aesdec xmm2, xmm10 + aesdec xmm3, xmm10 + aesdec xmm4, xmm10 DLAST_4: - add rdi,64 - add rsi,64 - dec rcx - aesdeclast xmm1,xmm11 - aesdeclast xmm2,xmm11 - aesdeclast xmm3,xmm11 - aesdeclast xmm4,xmm11 - pxor xmm1,xmm5 - pxor xmm2,xmm6 - pxor xmm3,xmm7 - pxor xmm4,xmm8 - movdqu [rsi],xmm1 - movdqu 16[rsi],xmm2 - movdqu 32[rsi],xmm3 - movdqu 48[rsi],xmm4 - movdqa xmm5,xmm15 - jne DLOOP_4 - add rsi,64 + add rdi, 64 + add rsi, 64 + dec rcx + aesdeclast xmm1, xmm11 + aesdeclast xmm2, xmm11 + aesdeclast xmm3, xmm11 + aesdeclast xmm4, xmm11 + pxor xmm1, xmm5 + pxor xmm2, xmm6 + pxor xmm3, xmm7 + pxor xmm4, xmm8 + movdqu [rsi], xmm1 + movdqu 16[rsi], xmm2 + movdqu 32[rsi], xmm3 + movdqu 48[rsi], xmm4 + movdqa xmm5, xmm15 + jne DLOOP_4 + add rsi, 64 DREMAINDER_4: - cmp r10,0 - je DEND_4 + cmp r10, 0 + je DEND_4 DLOOP_4_2: - movdqu xmm1,[rdi] - movdqa xmm15,xmm1 - add rdi,16 - pxor xmm1,[r8] - movdqu xmm2,160[r8] - cmp r9d,12 - aesdec xmm1,16[r8] - aesdec xmm1,32[r8] - aesdec xmm1,48[r8] - aesdec xmm1,64[r8] - aesdec xmm1,80[r8] - aesdec xmm1,96[r8] - aesdec xmm1,112[r8] - aesdec xmm1,128[r8] - aesdec xmm1,144[r8] - jb DLAST_4_2 - movdqu xmm2,192[r8] - cmp r9d,14 - aesdec xmm1,160[r8] - aesdec xmm1,176[r8] - jb DLAST_4_2 - movdqu xmm2,224[r8] - aesdec xmm1,192[r8] - aesdec xmm1,208[r8] + movdqu xmm1, [rdi] + movdqa xmm15, xmm1 + add rdi, 16 + pxor xmm1, [r8] + movdqu xmm2, 160[r8] + cmp r9d, 12 + aesdec xmm1, 16[r8] + aesdec xmm1, 32[r8] + aesdec xmm1, 48[r8] + aesdec xmm1, 64[r8] + aesdec xmm1, 80[r8] + aesdec xmm1, 96[r8] + aesdec xmm1, 112[r8] + aesdec xmm1, 128[r8] + aesdec xmm1, 144[r8] + jb DLAST_4_2 + movdqu xmm2, 192[r8] + cmp r9d, 14 + aesdec xmm1, 160[r8] + aesdec xmm1, 176[r8] + jb DLAST_4_2 + movdqu xmm2, 224[r8] + aesdec xmm1, 192[r8] + aesdec xmm1, 208[r8] DLAST_4_2: - aesdeclast xmm1,xmm2 - pxor xmm1,xmm5 - movdqa xmm5,xmm15 - movdqu [rsi],xmm1 - - add rsi,16 - dec r10 - jne DLOOP_4_2 + aesdeclast xmm1, xmm2 + pxor xmm1, xmm5 + movdqa xmm5, xmm15 + movdqu [rsi], xmm1 + add rsi, 16 + dec r10 + jne DLOOP_4_2 DEND_4: - ; restore non volatile rdi,rsi - mov rdi,rax - mov rsi,r11 - ; restore non volatile xmms from stack - movdqa xmm6, [rsp+0] - movdqa xmm7, [rsp+16] - movdqa xmm8, [rsp+32] - movdqa xmm9, [rsp+48] - movdqa xmm10, [rsp+64] - movdqa xmm11, [rsp+80] - movdqa xmm12, [rsp+96] - movdqa xmm15, [rsp+112] - add rsp,8+8*16 ; 8 = align stack , 8 xmm6-12,15 16 bytes each - ret -AES_CBC_decrypt ENDP + ; restore non volatile rdi,rsi + mov rdi, rax + mov rsi, r11 + ; restore non volatile xmms from stack + movdqa xmm6, [rsp+0] + movdqa xmm7, [rsp+16] + movdqa xmm8, [rsp+32] + movdqa xmm9, [rsp+48] + movdqa xmm10, [rsp+64] + movdqa xmm11, [rsp+80] + movdqa xmm12, [rsp+96] + movdqa xmm15, [rsp+112] + add rsp, 8+8*16 ; 8 = align stack , 8 xmm6-12,15 16 bytes each + ret +AES_CBC_decrypt_by4 ENDP + + +; void AES_CBC_decrypt_by6(const unsigned char *in, +; unsigned char *out, +; unsigned char ivec[16], +; unsigned long length, +; const unsigned char *KS, +; int nr) +AES_CBC_decrypt_by6 PROC +; parameter 1: rdi - in +; parameter 2: rsi - out +; parameter 3: rdx - ivec +; parameter 4: rcx - length +; parameter 5: r8 - KS +; parameter 6: r9d - nr + + ; save rdi and rsi to rax and r11, restore before ret + mov rax, rdi + mov r11, rsi + ; convert to what we had for att&t convention + mov rdi, rcx + mov rsi, rdx + mov rdx, r8 + mov rcx, r9 + mov r8, [rsp+40] + mov r9d, [rsp+48] + ; on microsoft xmm6-xmm15 are non volatile, + ; let's save on stack and restore at end + sub rsp, 8+9*16 ; 8 = align stack , 9 xmm6-14 16 bytes each + movdqa [rsp+0], xmm6 + movdqa [rsp+16], xmm7 + movdqa [rsp+32], xmm8 + movdqa [rsp+48], xmm9 + movdqa [rsp+64], xmm10 + movdqa [rsp+80], xmm11 + movdqa [rsp+96], xmm12 + movdqa [rsp+112], xmm13 + movdqa [rsp+128], xmm14 + ; back to our original code, more or less + mov r10, rcx + shr rcx, 4 + shl r10, 60 + je DNO_PARTS_6 + add rcx, 1 +DNO_PARTS_6: + mov r12, rax + mov r13, rdx + mov r14, rbx + mov rdx, 0 + mov rax, rcx + mov rbx, 6 + div rbx + mov rcx, rax + mov r10, rdx + mov rax, r12 + mov rdx, r13 + mov rbx, r14 + cmp rcx, 0 + movdqu xmm7, [rdx] + je DREMAINDER_6 + sub rsi, 96 +DLOOP_6: + movdqu xmm1, [rdi] + movdqu xmm2, 16[rdi] + movdqu xmm3, 32[rdi] + movdqu xmm4, 48[rdi] + movdqu xmm5, 64[rdi] + movdqu xmm6, 80[rdi] + movdqa xmm8, [r8] + movdqa xmm9, 16[r8] + movdqa xmm10, 32[r8] + movdqa xmm11, 48[r8] + pxor xmm1, xmm8 + pxor xmm2, xmm8 + pxor xmm3, xmm8 + pxor xmm4, xmm8 + pxor xmm5, xmm8 + pxor xmm6, xmm8 + aesdec xmm1, xmm9 + aesdec xmm2, xmm9 + aesdec xmm3, xmm9 + aesdec xmm4, xmm9 + aesdec xmm5, xmm9 + aesdec xmm6, xmm9 + aesdec xmm1, xmm10 + aesdec xmm2, xmm10 + aesdec xmm3, xmm10 + aesdec xmm4, xmm10 + aesdec xmm5, xmm10 + aesdec xmm6, xmm10 + aesdec xmm1, xmm11 + aesdec xmm2, xmm11 + aesdec xmm3, xmm11 + aesdec xmm4, xmm11 + aesdec xmm5, xmm11 + aesdec xmm6, xmm11 + movdqa xmm8, 64[r8] + movdqa xmm9, 80[r8] + movdqa xmm10, 96[r8] + movdqa xmm11, 112[r8] + aesdec xmm1, xmm8 + aesdec xmm2, xmm8 + aesdec xmm3, xmm8 + aesdec xmm4, xmm8 + aesdec xmm5, xmm8 + aesdec xmm6, xmm8 + aesdec xmm1, xmm9 + aesdec xmm2, xmm9 + aesdec xmm3, xmm9 + aesdec xmm4, xmm9 + aesdec xmm5, xmm9 + aesdec xmm6, xmm9 + aesdec xmm1, xmm10 + aesdec xmm2, xmm10 + aesdec xmm3, xmm10 + aesdec xmm4, xmm10 + aesdec xmm5, xmm10 + aesdec xmm6, xmm10 + aesdec xmm1, xmm11 + aesdec xmm2, xmm11 + aesdec xmm3, xmm11 + aesdec xmm4, xmm11 + aesdec xmm5, xmm11 + aesdec xmm6, xmm11 + movdqa xmm8, 128[r8] + movdqa xmm9, 144[r8] + movdqa xmm10, 160[r8] + cmp r9d, 12 + aesdec xmm1, xmm8 + aesdec xmm2, xmm8 + aesdec xmm3, xmm8 + aesdec xmm4, xmm8 + aesdec xmm5, xmm8 + aesdec xmm6, xmm8 + aesdec xmm1, xmm9 + aesdec xmm2, xmm9 + aesdec xmm3, xmm9 + aesdec xmm4, xmm9 + aesdec xmm5, xmm9 + aesdec xmm6, xmm9 + jb DLAST_6 + movdqa xmm8, 160[r8] + movdqa xmm9, 176[r8] + movdqa xmm10, 192[r8] + cmp r9d, 14 + aesdec xmm1, xmm8 + aesdec xmm2, xmm8 + aesdec xmm3, xmm8 + aesdec xmm4, xmm8 + aesdec xmm5, xmm8 + aesdec xmm6, xmm8 + aesdec xmm1, xmm9 + aesdec xmm2, xmm9 + aesdec xmm3, xmm9 + aesdec xmm4, xmm9 + aesdec xmm5, xmm9 + aesdec xmm6, xmm9 + jb DLAST_6 + movdqa xmm8, 192[r8] + movdqa xmm9, 208[r8] + movdqa xmm10, 224[r8] + aesdec xmm1, xmm8 + aesdec xmm2, xmm8 + aesdec xmm3, xmm8 + aesdec xmm4, xmm8 + aesdec xmm5, xmm8 + aesdec xmm6, xmm8 + aesdec xmm1, xmm9 + aesdec xmm2, xmm9 + aesdec xmm3, xmm9 + aesdec xmm4, xmm9 + aesdec xmm5, xmm9 + aesdec xmm6, xmm9 +DLAST_6: + add rsi, 96 + aesdeclast xmm1, xmm10 + aesdeclast xmm2, xmm10 + aesdeclast xmm3, xmm10 + aesdeclast xmm4, xmm10 + aesdeclast xmm5, xmm10 + aesdeclast xmm6, xmm10 + movdqu xmm8, [rdi] + movdqu xmm9, 16[rdi] + movdqu xmm10, 32[rdi] + movdqu xmm11, 48[rdi] + movdqu xmm12, 64[rdi] + movdqu xmm13, 80[rdi] + pxor xmm1, xmm7 + pxor xmm2, xmm8 + pxor xmm3, xmm9 + pxor xmm4, xmm10 + pxor xmm5, xmm11 + pxor xmm6, xmm12 + movdqu xmm7, xmm13 + movdqu [rsi], xmm1 + movdqu 16[rsi], xmm2 + movdqu 32[rsi], xmm3 + movdqu 48[rsi], xmm4 + movdqu 64[rsi], xmm5 + movdqu 80[rsi], xmm6 + add rdi, 96 + dec rcx + jne DLOOP_6 + add rsi, 96 +DREMAINDER_6: + cmp r10, 0 + je DEND_6 +DLOOP_6_2: + movdqu xmm1, [rdi] + movdqa xmm10, xmm1 + add rdi, 16 + pxor xmm1, [r8] + movdqu xmm2, 160[r8] + cmp r9d, 12 + aesdec xmm1, 16[r8] + aesdec xmm1, 32[r8] + aesdec xmm1, 48[r8] + aesdec xmm1, 64[r8] + aesdec xmm1, 80[r8] + aesdec xmm1, 96[r8] + aesdec xmm1, 112[r8] + aesdec xmm1, 128[r8] + aesdec xmm1, 144[r8] + jb DLAST_6_2 + movdqu xmm2, 192[r8] + cmp r9d, 14 + aesdec xmm1, 160[r8] + aesdec xmm1, 176[r8] + jb DLAST_6_2 + movdqu xmm2, 224[r8] + aesdec xmm1, 192[r8] + aesdec xmm1, 208[r8] +DLAST_6_2: + aesdeclast xmm1, xmm2 + pxor xmm1, xmm7 + movdqa xmm7, xmm10 + movdqu [rsi], xmm1 + add rsi, 16 + dec r10 + jne DLOOP_6_2 +DEND_6: + ; restore non volatile rdi,rsi + mov rdi, rax + mov rsi, r11 + ; restore non volatile xmms from stack + movdqa xmm6, [rsp+0] + movdqa xmm7, [rsp+16] + movdqa xmm8, [rsp+32] + movdqa xmm9, [rsp+48] + movdqa xmm10, [rsp+64] + movdqa xmm11, [rsp+80] + movdqa xmm12, [rsp+96] + movdqa xmm13, [rsp+112] + movdqa xmm14, [rsp+128] + add rsp, 8+9*16 ; 8 = align stack , 9 xmm6-14 16 bytes each + ret +AES_CBC_decrypt_by6 ENDP + + +; void AES_CBC_decrypt_by8(const unsigned char *in, +; unsigned char *out, +; unsigned char ivec[16], +; unsigned long length, +; const unsigned char *KS, +; int nr) +AES_CBC_decrypt_by8 PROC +; parameter 1: rdi - in +; parameter 2: rsi - out +; parameter 3: rdx - ivec +; parameter 4: rcx - length +; parameter 5: r8 - KS +; parameter 6: r9d - nr + + ; save rdi and rsi to rax and r11, restore before ret + mov rax, rdi + mov r11, rsi + ; convert to what we had for att&t convention + mov rdi, rcx + mov rsi, rdx + mov rdx, r8 + mov rcx,r9 + mov r8, [rsp+40] + mov r9d, [rsp+48] + ; on microsoft xmm6-xmm15 are non volatile, + ; let's save on stack and restore at end + sub rsp, 8+8*16 ; 8 = align stack , 8 xmm6-13 16 bytes each + movdqa [rsp+0], xmm6 + movdqa [rsp+16], xmm7 + movdqa [rsp+32], xmm8 + movdqa [rsp+48], xmm9 + movdqa [rsp+64], xmm10 + movdqa [rsp+80], xmm11 + movdqa [rsp+96], xmm12 + movdqa [rsp+112], xmm13 + ; back to our original code, more or less + mov r10, rcx + shr rcx, 4 + shl r10, 60 + je DNO_PARTS_8 + add rcx, 1 +DNO_PARTS_8: + mov r10, rcx + shl r10, 61 + shr r10, 61 + shr rcx, 3 + movdqu xmm9, [rdx] + je DREMAINDER_8 + sub rsi, 128 +DLOOP_8: + movdqu xmm1, [rdi] + movdqu xmm2, 16[rdi] + movdqu xmm3, 32[rdi] + movdqu xmm4, 48[rdi] + movdqu xmm5, 64[rdi] + movdqu xmm6, 80[rdi] + movdqu xmm7, 96[rdi] + movdqu xmm8, 112[rdi] + movdqa xmm10, [r8] + movdqa xmm11, 16[r8] + movdqa xmm12, 32[r8] + movdqa xmm13, 48[r8] + pxor xmm1, xmm10 + pxor xmm2, xmm10 + pxor xmm3, xmm10 + pxor xmm4, xmm10 + pxor xmm5, xmm10 + pxor xmm6, xmm10 + pxor xmm7, xmm10 + pxor xmm8, xmm10 + aesdec xmm1, xmm11 + aesdec xmm2, xmm11 + aesdec xmm3, xmm11 + aesdec xmm4, xmm11 + aesdec xmm5, xmm11 + aesdec xmm6, xmm11 + aesdec xmm7, xmm11 + aesdec xmm8, xmm11 + aesdec xmm1, xmm12 + aesdec xmm2, xmm12 + aesdec xmm3, xmm12 + aesdec xmm4, xmm12 + aesdec xmm5, xmm12 + aesdec xmm6, xmm12 + aesdec xmm7, xmm12 + aesdec xmm8, xmm12 + aesdec xmm1, xmm13 + aesdec xmm2, xmm13 + aesdec xmm3, xmm13 + aesdec xmm4, xmm13 + aesdec xmm5, xmm13 + aesdec xmm6, xmm13 + aesdec xmm7, xmm13 + aesdec xmm8, xmm13 + movdqa xmm10, 64[r8] + movdqa xmm11, 80[r8] + movdqa xmm12, 96[r8] + movdqa xmm13, 112[r8] + aesdec xmm1, xmm10 + aesdec xmm2, xmm10 + aesdec xmm3, xmm10 + aesdec xmm4, xmm10 + aesdec xmm5, xmm10 + aesdec xmm6, xmm10 + aesdec xmm7, xmm10 + aesdec xmm8, xmm10 + aesdec xmm1, xmm11 + aesdec xmm2, xmm11 + aesdec xmm3, xmm11 + aesdec xmm4, xmm11 + aesdec xmm5, xmm11 + aesdec xmm6, xmm11 + aesdec xmm7, xmm11 + aesdec xmm8, xmm11 + aesdec xmm1, xmm12 + aesdec xmm2, xmm12 + aesdec xmm3, xmm12 + aesdec xmm4, xmm12 + aesdec xmm5, xmm12 + aesdec xmm6, xmm12 + aesdec xmm7, xmm12 + aesdec xmm8, xmm12 + aesdec xmm1, xmm13 + aesdec xmm2, xmm13 + aesdec xmm3, xmm13 + aesdec xmm4, xmm13 + aesdec xmm5, xmm13 + aesdec xmm6, xmm13 + aesdec xmm7, xmm13 + aesdec xmm8, xmm13 + movdqa xmm10, 128[r8] + movdqa xmm11, 144[r8] + movdqa xmm12, 160[r8] + cmp r9d, 12 + aesdec xmm1, xmm10 + aesdec xmm2, xmm10 + aesdec xmm3, xmm10 + aesdec xmm4, xmm10 + aesdec xmm5, xmm10 + aesdec xmm6, xmm10 + aesdec xmm7, xmm10 + aesdec xmm8, xmm10 + aesdec xmm1, xmm11 + aesdec xmm2, xmm11 + aesdec xmm3, xmm11 + aesdec xmm4, xmm11 + aesdec xmm5, xmm11 + aesdec xmm6, xmm11 + aesdec xmm7, xmm11 + aesdec xmm8, xmm11 + jb DLAST_8 + movdqa xmm10, 160[r8] + movdqa xmm11, 176[r8] + movdqa xmm12, 192[r8] + cmp r9d, 14 + aesdec xmm1, xmm10 + aesdec xmm2, xmm10 + aesdec xmm3, xmm10 + aesdec xmm4, xmm10 + aesdec xmm5, xmm10 + aesdec xmm6, xmm10 + aesdec xmm7, xmm10 + aesdec xmm8, xmm10 + aesdec xmm1, xmm11 + aesdec xmm2, xmm11 + aesdec xmm3, xmm11 + aesdec xmm4, xmm11 + aesdec xmm5, xmm11 + aesdec xmm6, xmm11 + aesdec xmm7, xmm11 + aesdec xmm8, xmm11 + jb DLAST_8 + movdqa xmm10, 192[r8] + movdqa xmm11, 208[r8] + movdqa xmm12, 224[r8] + aesdec xmm1, xmm10 + aesdec xmm2, xmm10 + aesdec xmm3, xmm10 + aesdec xmm4, xmm10 + aesdec xmm5, xmm10 + aesdec xmm6, xmm10 + aesdec xmm7, xmm10 + aesdec xmm8, xmm10 + aesdec xmm1, xmm11 + aesdec xmm2, xmm11 + aesdec xmm3, xmm11 + aesdec xmm4, xmm11 + aesdec xmm5, xmm11 + aesdec xmm6, xmm11 + aesdec xmm7, xmm11 + aesdec xmm8, xmm11 +DLAST_8: + add rsi, 128 + aesdeclast xmm1, xmm12 + aesdeclast xmm2, xmm12 + aesdeclast xmm3, xmm12 + aesdeclast xmm4, xmm12 + aesdeclast xmm5, xmm12 + aesdeclast xmm6, xmm12 + aesdeclast xmm7, xmm12 + aesdeclast xmm8, xmm12 + movdqu xmm10, [rdi] + movdqu xmm11, 16[rdi] + movdqu xmm12, 32[rdi] + movdqu xmm13, 48[rdi] + pxor xmm1, xmm9 + pxor xmm2, xmm10 + pxor xmm3, xmm11 + pxor xmm4, xmm12 + pxor xmm5, xmm13 + movdqu xmm10, 64[rdi] + movdqu xmm11, 80[rdi] + movdqu xmm12, 96[rdi] + movdqu xmm9, 112[rdi] + pxor xmm6, xmm10 + pxor xmm7, xmm11 + pxor xmm8, xmm12 + movdqu [rsi], xmm1 + movdqu 16[rsi], xmm2 + movdqu 32[rsi], xmm3 + movdqu 48[rsi], xmm4 + movdqu 64[rsi], xmm5 + movdqu 80[rsi], xmm6 + movdqu 96[rsi], xmm7 + movdqu 112[rsi], xmm8 + add rdi, 128 + dec rcx + jne DLOOP_8 + add rsi, 128 +DREMAINDER_8: + cmp r10, 0 + je DEND_8 +DLOOP_8_2: + movdqu xmm1, [rdi] + movdqa xmm10, xmm1 + add rdi, 16 + pxor xmm1, [r8] + movdqu xmm2, 160[r8] + cmp r9d, 12 + aesdec xmm1, 16[r8] + aesdec xmm1, 32[r8] + aesdec xmm1, 48[r8] + aesdec xmm1, 64[r8] + aesdec xmm1, 80[r8] + aesdec xmm1, 96[r8] + aesdec xmm1, 112[r8] + aesdec xmm1, 128[r8] + aesdec xmm1, 144[r8] + jb DLAST_8_2 + movdqu xmm2, 192[r8] + cmp r9d, 14 + aesdec xmm1, 160[r8] + aesdec xmm1, 176[r8] + jb DLAST_8_2 + movdqu xmm2, 224[r8] + aesdec xmm1, 192[r8] + aesdec xmm1, 208[r8] +DLAST_8_2: + aesdeclast xmm1, xmm2 + pxor xmm1, xmm9 + movdqa xmm9, xmm10 + movdqu [rsi], xmm1 + add rsi, 16 + dec r10 + jne DLOOP_8_2 +DEND_8: + ; restore non volatile rdi,rsi + mov rdi, rax + mov rsi, r11 + ; restore non volatile xmms from stack + movdqa xmm6, [rsp+0] + movdqa xmm7, [rsp+16] + movdqa xmm8, [rsp+32] + movdqa xmm9, [rsp+48] + movdqa xmm10, [rsp+64] + movdqa xmm11, [rsp+80] + movdqa xmm12, [rsp+96] + movdqa xmm13, [rsp+112] + add rsp, 8+8*16 ; 8 = align stack , 8 xmm6-13 16 bytes each + ret +AES_CBC_decrypt_by8 ENDP + ; /* ; AES_ECB_encrypt[const ,unsigned char*in @@ -794,7 +1344,7 @@ AES_192_Key_Expansion PROC movdqa [rsp+0], xmm6 movdqu xmm1,[rdi] - movdqu xmm3,16[rdi] + movq xmm3,qword ptr 16[rdi] movdqa [rsi],xmm1 movdqa xmm5,xmm3 @@ -969,4 +1519,11 @@ MAKE_RK256_b: pxor xmm3,xmm2 ret + +IF fips_version GE 2 + fipsAh ENDS +ELSE + _text ENDS +ENDIF + END diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_asm.s b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_asm.s deleted file mode 100644 index b50c7ff95..000000000 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_asm.s +++ /dev/null @@ -1,816 +0,0 @@ -/* aes_asm.s - * - * Copyright (C) 2006-2015 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 - */ - - -/* See Intel® Advanced Encryption Standard (AES) Instructions Set White Paper - * by Intel Mobility Group, Israel Development Center, Israel Shay Gueron - */ - -/* This file is in at&t asm syntax, see .asm for intel syntax */ - - -/* -AES_CBC_encrypt (const unsigned char *in, - unsigned char *out, - unsigned char ivec[16], - unsigned long length, - const unsigned char *KS, - int nr) -*/ -.globl AES_CBC_encrypt -AES_CBC_encrypt: -# parameter 1: %rdi -# parameter 2: %rsi -# parameter 3: %rdx -# parameter 4: %rcx -# parameter 5: %r8 -# parameter 6: %r9d -movq %rcx, %r10 -shrq $4, %rcx -shlq $60, %r10 -je NO_PARTS -addq $1, %rcx -NO_PARTS: -subq $16, %rsi -movdqa (%rdx), %xmm1 -LOOP: -pxor (%rdi), %xmm1 -pxor (%r8), %xmm1 -addq $16,%rsi -addq $16,%rdi -cmpl $12, %r9d -aesenc 16(%r8),%xmm1 -aesenc 32(%r8),%xmm1 -aesenc 48(%r8),%xmm1 -aesenc 64(%r8),%xmm1 -aesenc 80(%r8),%xmm1 -aesenc 96(%r8),%xmm1 -aesenc 112(%r8),%xmm1 -aesenc 128(%r8),%xmm1 -aesenc 144(%r8),%xmm1 -movdqa 160(%r8),%xmm2 -jb LAST -cmpl $14, %r9d - -aesenc 160(%r8),%xmm1 -aesenc 176(%r8),%xmm1 -movdqa 192(%r8),%xmm2 -jb LAST -aesenc 192(%r8),%xmm1 -aesenc 208(%r8),%xmm1 -movdqa 224(%r8),%xmm2 -LAST: -decq %rcx -aesenclast %xmm2,%xmm1 -movdqu %xmm1,(%rsi) -jne LOOP -ret - - - - -/* -AES_CBC_decrypt (const unsigned char *in, - unsigned char *out, - unsigned char ivec[16], - unsigned long length, - const unsigned char *KS, - int nr) -*/ -.globl AES_CBC_decrypt -AES_CBC_decrypt: -# parameter 1: %rdi -# parameter 2: %rsi -# parameter 3: %rdx -# parameter 4: %rcx -# parameter 5: %r8 -# parameter 6: %r9d - -movq %rcx, %r10 -shrq $4, %rcx -shlq $60, %r10 -je DNO_PARTS_4 -addq $1, %rcx -DNO_PARTS_4: -movq %rcx, %r10 -shlq $62, %r10 -shrq $62, %r10 -shrq $2, %rcx -movdqu (%rdx),%xmm5 -je DREMAINDER_4 -subq $64, %rsi -DLOOP_4: -movdqu (%rdi), %xmm1 -movdqu 16(%rdi), %xmm2 -movdqu 32(%rdi), %xmm3 -movdqu 48(%rdi), %xmm4 -movdqa %xmm1, %xmm6 -movdqa %xmm2, %xmm7 -movdqa %xmm3, %xmm8 -movdqa %xmm4, %xmm15 -movdqa (%r8), %xmm9 -movdqa 16(%r8), %xmm10 -movdqa 32(%r8), %xmm11 -movdqa 48(%r8), %xmm12 -pxor %xmm9, %xmm1 -pxor %xmm9, %xmm2 -pxor %xmm9, %xmm3 - -pxor %xmm9, %xmm4 -aesdec %xmm10, %xmm1 -aesdec %xmm10, %xmm2 -aesdec %xmm10, %xmm3 -aesdec %xmm10, %xmm4 -aesdec %xmm11, %xmm1 -aesdec %xmm11, %xmm2 -aesdec %xmm11, %xmm3 -aesdec %xmm11, %xmm4 -aesdec %xmm12, %xmm1 -aesdec %xmm12, %xmm2 -aesdec %xmm12, %xmm3 -aesdec %xmm12, %xmm4 -movdqa 64(%r8), %xmm9 -movdqa 80(%r8), %xmm10 -movdqa 96(%r8), %xmm11 -movdqa 112(%r8), %xmm12 -aesdec %xmm9, %xmm1 -aesdec %xmm9, %xmm2 -aesdec %xmm9, %xmm3 -aesdec %xmm9, %xmm4 -aesdec %xmm10, %xmm1 -aesdec %xmm10, %xmm2 -aesdec %xmm10, %xmm3 -aesdec %xmm10, %xmm4 -aesdec %xmm11, %xmm1 -aesdec %xmm11, %xmm2 -aesdec %xmm11, %xmm3 -aesdec %xmm11, %xmm4 -aesdec %xmm12, %xmm1 -aesdec %xmm12, %xmm2 -aesdec %xmm12, %xmm3 -aesdec %xmm12, %xmm4 -movdqa 128(%r8), %xmm9 -movdqa 144(%r8), %xmm10 -movdqa 160(%r8), %xmm11 -cmpl $12, %r9d -aesdec %xmm9, %xmm1 -aesdec %xmm9, %xmm2 -aesdec %xmm9, %xmm3 -aesdec %xmm9, %xmm4 -aesdec %xmm10, %xmm1 -aesdec %xmm10, %xmm2 -aesdec %xmm10, %xmm3 -aesdec %xmm10, %xmm4 -jb DLAST_4 -movdqa 160(%r8), %xmm9 -movdqa 176(%r8), %xmm10 -movdqa 192(%r8), %xmm11 -cmpl $14, %r9d -aesdec %xmm9, %xmm1 -aesdec %xmm9, %xmm2 -aesdec %xmm9, %xmm3 -aesdec %xmm9, %xmm4 -aesdec %xmm10, %xmm1 -aesdec %xmm10, %xmm2 -aesdec %xmm10, %xmm3 -aesdec %xmm10, %xmm4 -jb DLAST_4 - -movdqa 192(%r8), %xmm9 -movdqa 208(%r8), %xmm10 -movdqa 224(%r8), %xmm11 -aesdec %xmm9, %xmm1 -aesdec %xmm9, %xmm2 -aesdec %xmm9, %xmm3 -aesdec %xmm9, %xmm4 -aesdec %xmm10, %xmm1 -aesdec %xmm10, %xmm2 -aesdec %xmm10, %xmm3 -aesdec %xmm10, %xmm4 -DLAST_4: -addq $64, %rdi -addq $64, %rsi -decq %rcx -aesdeclast %xmm11, %xmm1 -aesdeclast %xmm11, %xmm2 -aesdeclast %xmm11, %xmm3 -aesdeclast %xmm11, %xmm4 -pxor %xmm5 ,%xmm1 -pxor %xmm6 ,%xmm2 -pxor %xmm7 ,%xmm3 -pxor %xmm8 ,%xmm4 -movdqu %xmm1, (%rsi) -movdqu %xmm2, 16(%rsi) -movdqu %xmm3, 32(%rsi) -movdqu %xmm4, 48(%rsi) -movdqa %xmm15,%xmm5 -jne DLOOP_4 -addq $64, %rsi -DREMAINDER_4: -cmpq $0, %r10 -je DEND_4 -DLOOP_4_2: -movdqu (%rdi), %xmm1 -movdqa %xmm1 ,%xmm15 -addq $16, %rdi -pxor (%r8), %xmm1 -movdqu 160(%r8), %xmm2 -cmpl $12, %r9d -aesdec 16(%r8), %xmm1 -aesdec 32(%r8), %xmm1 -aesdec 48(%r8), %xmm1 -aesdec 64(%r8), %xmm1 -aesdec 80(%r8), %xmm1 -aesdec 96(%r8), %xmm1 -aesdec 112(%r8), %xmm1 -aesdec 128(%r8), %xmm1 -aesdec 144(%r8), %xmm1 -jb DLAST_4_2 -movdqu 192(%r8), %xmm2 -cmpl $14, %r9d -aesdec 160(%r8), %xmm1 -aesdec 176(%r8), %xmm1 -jb DLAST_4_2 -movdqu 224(%r8), %xmm2 -aesdec 192(%r8), %xmm1 -aesdec 208(%r8), %xmm1 -DLAST_4_2: -aesdeclast %xmm2, %xmm1 -pxor %xmm5, %xmm1 -movdqa %xmm15, %xmm5 -movdqu %xmm1, (%rsi) - -addq $16, %rsi -decq %r10 -jne DLOOP_4_2 -DEND_4: -ret - - -/* -AES_ECB_encrypt (const unsigned char *in, - unsigned char *out, - unsigned long length, - const unsigned char *KS, - int nr) -*/ -.globl AES_ECB_encrypt -AES_ECB_encrypt: -# parameter 1: %rdi -# parameter 2: %rsi -# parameter 3: %rdx -# parameter 4: %rcx -# parameter 5: %r8d - movq %rdx, %r10 - shrq $4, %rdx - shlq $60, %r10 - je EECB_NO_PARTS_4 - addq $1, %rdx -EECB_NO_PARTS_4: - movq %rdx, %r10 - shlq $62, %r10 - shrq $62, %r10 - shrq $2, %rdx - je EECB_REMAINDER_4 - subq $64, %rsi -EECB_LOOP_4: - movdqu (%rdi), %xmm1 - movdqu 16(%rdi), %xmm2 - movdqu 32(%rdi), %xmm3 - movdqu 48(%rdi), %xmm4 - movdqa (%rcx), %xmm9 - movdqa 16(%rcx), %xmm10 - movdqa 32(%rcx), %xmm11 - movdqa 48(%rcx), %xmm12 - pxor %xmm9, %xmm1 - pxor %xmm9, %xmm2 - pxor %xmm9, %xmm3 - pxor %xmm9, %xmm4 - aesenc %xmm10, %xmm1 - aesenc %xmm10, %xmm2 - aesenc %xmm10, %xmm3 - aesenc %xmm10, %xmm4 - aesenc %xmm11, %xmm1 - aesenc %xmm11, %xmm2 - aesenc %xmm11, %xmm3 - aesenc %xmm11, %xmm4 - aesenc %xmm12, %xmm1 - aesenc %xmm12, %xmm2 - aesenc %xmm12, %xmm3 - aesenc %xmm12, %xmm4 - movdqa 64(%rcx), %xmm9 - movdqa 80(%rcx), %xmm10 - movdqa 96(%rcx), %xmm11 - movdqa 112(%rcx), %xmm12 - aesenc %xmm9, %xmm1 - aesenc %xmm9, %xmm2 - aesenc %xmm9, %xmm3 - aesenc %xmm9, %xmm4 - aesenc %xmm10, %xmm1 - aesenc %xmm10, %xmm2 - aesenc %xmm10, %xmm3 - aesenc %xmm10, %xmm4 - aesenc %xmm11, %xmm1 - aesenc %xmm11, %xmm2 - aesenc %xmm11, %xmm3 - aesenc %xmm11, %xmm4 - aesenc %xmm12, %xmm1 - aesenc %xmm12, %xmm2 - aesenc %xmm12, %xmm3 - aesenc %xmm12, %xmm4 - movdqa 128(%rcx), %xmm9 - movdqa 144(%rcx), %xmm10 - movdqa 160(%rcx), %xmm11 - cmpl $12, %r8d - aesenc %xmm9, %xmm1 - aesenc %xmm9, %xmm2 - aesenc %xmm9, %xmm3 - aesenc %xmm9, %xmm4 - aesenc %xmm10, %xmm1 - aesenc %xmm10, %xmm2 - aesenc %xmm10, %xmm3 - aesenc %xmm10, %xmm4 - jb EECB_LAST_4 - movdqa 160(%rcx), %xmm9 - movdqa 176(%rcx), %xmm10 - movdqa 192(%rcx), %xmm11 - cmpl $14, %r8d - aesenc %xmm9, %xmm1 - aesenc %xmm9, %xmm2 - aesenc %xmm9, %xmm3 - aesenc %xmm9, %xmm4 - aesenc %xmm10, %xmm1 - aesenc %xmm10, %xmm2 - aesenc %xmm10, %xmm3 - aesenc %xmm10, %xmm4 - jb EECB_LAST_4 - movdqa 192(%rcx), %xmm9 - movdqa 208(%rcx), %xmm10 - movdqa 224(%rcx), %xmm11 - aesenc %xmm9, %xmm1 - aesenc %xmm9, %xmm2 - aesenc %xmm9, %xmm3 - aesenc %xmm9, %xmm4 - aesenc %xmm10, %xmm1 - aesenc %xmm10, %xmm2 - aesenc %xmm10, %xmm3 - aesenc %xmm10, %xmm4 -EECB_LAST_4: - addq $64, %rdi - addq $64, %rsi - decq %rdx - aesenclast %xmm11, %xmm1 - aesenclast %xmm11, %xmm2 - aesenclast %xmm11, %xmm3 - aesenclast %xmm11, %xmm4 - movdqu %xmm1, (%rsi) - movdqu %xmm2, 16(%rsi) - movdqu %xmm3, 32(%rsi) - movdqu %xmm4, 48(%rsi) - jne EECB_LOOP_4 - addq $64, %rsi -EECB_REMAINDER_4: - cmpq $0, %r10 - je EECB_END_4 -EECB_LOOP_4_2: - movdqu (%rdi), %xmm1 - addq $16, %rdi - pxor (%rcx), %xmm1 - movdqu 160(%rcx), %xmm2 - aesenc 16(%rcx), %xmm1 - aesenc 32(%rcx), %xmm1 - aesenc 48(%rcx), %xmm1 - aesenc 64(%rcx), %xmm1 - aesenc 80(%rcx), %xmm1 - aesenc 96(%rcx), %xmm1 - aesenc 112(%rcx), %xmm1 - aesenc 128(%rcx), %xmm1 - aesenc 144(%rcx), %xmm1 - cmpl $12, %r8d - jb EECB_LAST_4_2 - movdqu 192(%rcx), %xmm2 - aesenc 160(%rcx), %xmm1 - aesenc 176(%rcx), %xmm1 - cmpl $14, %r8d - jb EECB_LAST_4_2 - movdqu 224(%rcx), %xmm2 - aesenc 192(%rcx), %xmm1 - aesenc 208(%rcx), %xmm1 -EECB_LAST_4_2: - aesenclast %xmm2, %xmm1 - movdqu %xmm1, (%rsi) - addq $16, %rsi - decq %r10 - jne EECB_LOOP_4_2 -EECB_END_4: - ret - - -/* -AES_ECB_decrypt (const unsigned char *in, - unsigned char *out, - unsigned long length, - const unsigned char *KS, - int nr) -*/ -.globl AES_ECB_decrypt -AES_ECB_decrypt: -# parameter 1: %rdi -# parameter 2: %rsi -# parameter 3: %rdx -# parameter 4: %rcx -# parameter 5: %r8d - - movq %rdx, %r10 - shrq $4, %rdx - shlq $60, %r10 - je DECB_NO_PARTS_4 - addq $1, %rdx -DECB_NO_PARTS_4: - movq %rdx, %r10 - shlq $62, %r10 - shrq $62, %r10 - shrq $2, %rdx - je DECB_REMAINDER_4 - subq $64, %rsi -DECB_LOOP_4: - movdqu (%rdi), %xmm1 - movdqu 16(%rdi), %xmm2 - movdqu 32(%rdi), %xmm3 - movdqu 48(%rdi), %xmm4 - movdqa (%rcx), %xmm9 - movdqa 16(%rcx), %xmm10 - movdqa 32(%rcx), %xmm11 - movdqa 48(%rcx), %xmm12 - pxor %xmm9, %xmm1 - pxor %xmm9, %xmm2 - pxor %xmm9, %xmm3 - pxor %xmm9, %xmm4 - aesdec %xmm10, %xmm1 - aesdec %xmm10, %xmm2 - aesdec %xmm10, %xmm3 - aesdec %xmm10, %xmm4 - aesdec %xmm11, %xmm1 - aesdec %xmm11, %xmm2 - aesdec %xmm11, %xmm3 - aesdec %xmm11, %xmm4 - aesdec %xmm12, %xmm1 - aesdec %xmm12, %xmm2 - aesdec %xmm12, %xmm3 - aesdec %xmm12, %xmm4 - movdqa 64(%rcx), %xmm9 - movdqa 80(%rcx), %xmm10 - movdqa 96(%rcx), %xmm11 - movdqa 112(%rcx), %xmm12 - aesdec %xmm9, %xmm1 - aesdec %xmm9, %xmm2 - aesdec %xmm9, %xmm3 - aesdec %xmm9, %xmm4 - aesdec %xmm10, %xmm1 - aesdec %xmm10, %xmm2 - aesdec %xmm10, %xmm3 - aesdec %xmm10, %xmm4 - aesdec %xmm11, %xmm1 - aesdec %xmm11, %xmm2 - aesdec %xmm11, %xmm3 - aesdec %xmm11, %xmm4 - aesdec %xmm12, %xmm1 - aesdec %xmm12, %xmm2 - aesdec %xmm12, %xmm3 - aesdec %xmm12, %xmm4 - movdqa 128(%rcx), %xmm9 - movdqa 144(%rcx), %xmm10 - movdqa 160(%rcx), %xmm11 - cmpl $12, %r8d - aesdec %xmm9, %xmm1 - aesdec %xmm9, %xmm2 - aesdec %xmm9, %xmm3 - aesdec %xmm9, %xmm4 - aesdec %xmm10, %xmm1 - aesdec %xmm10, %xmm2 - aesdec %xmm10, %xmm3 - aesdec %xmm10, %xmm4 - jb DECB_LAST_4 - movdqa 160(%rcx), %xmm9 - movdqa 176(%rcx), %xmm10 - movdqa 192(%rcx), %xmm11 - cmpl $14, %r8d - aesdec %xmm9, %xmm1 - aesdec %xmm9, %xmm2 - aesdec %xmm9, %xmm3 - aesdec %xmm9, %xmm4 - aesdec %xmm10, %xmm1 - aesdec %xmm10, %xmm2 - aesdec %xmm10, %xmm3 - aesdec %xmm10, %xmm4 - jb DECB_LAST_4 - movdqa 192(%rcx), %xmm9 - movdqa 208(%rcx), %xmm10 - movdqa 224(%rcx), %xmm11 - aesdec %xmm9, %xmm1 - aesdec %xmm9, %xmm2 - aesdec %xmm9, %xmm3 - aesdec %xmm9, %xmm4 - aesdec %xmm10, %xmm1 - aesdec %xmm10, %xmm2 - aesdec %xmm10, %xmm3 - aesdec %xmm10, %xmm4 -DECB_LAST_4: - addq $64, %rdi - addq $64, %rsi - decq %rdx - aesdeclast %xmm11, %xmm1 - aesdeclast %xmm11, %xmm2 - aesdeclast %xmm11, %xmm3 - aesdeclast %xmm11, %xmm4 - movdqu %xmm1, (%rsi) - movdqu %xmm2, 16(%rsi) - movdqu %xmm3, 32(%rsi) - movdqu %xmm4, 48(%rsi) - jne DECB_LOOP_4 - addq $64, %rsi -DECB_REMAINDER_4: - cmpq $0, %r10 - je DECB_END_4 -DECB_LOOP_4_2: - movdqu (%rdi), %xmm1 - addq $16, %rdi - pxor (%rcx), %xmm1 - movdqu 160(%rcx), %xmm2 - cmpl $12, %r8d - aesdec 16(%rcx), %xmm1 - aesdec 32(%rcx), %xmm1 - aesdec 48(%rcx), %xmm1 - aesdec 64(%rcx), %xmm1 - aesdec 80(%rcx), %xmm1 - aesdec 96(%rcx), %xmm1 - aesdec 112(%rcx), %xmm1 - aesdec 128(%rcx), %xmm1 - aesdec 144(%rcx), %xmm1 - jb DECB_LAST_4_2 - cmpl $14, %r8d - movdqu 192(%rcx), %xmm2 - aesdec 160(%rcx), %xmm1 - aesdec 176(%rcx), %xmm1 - jb DECB_LAST_4_2 - movdqu 224(%rcx), %xmm2 - aesdec 192(%rcx), %xmm1 - aesdec 208(%rcx), %xmm1 -DECB_LAST_4_2: - aesdeclast %xmm2, %xmm1 - movdqu %xmm1, (%rsi) - addq $16, %rsi - decq %r10 - jne DECB_LOOP_4_2 -DECB_END_4: - ret - - - - -/* -void AES_128_Key_Expansion(const unsigned char* userkey, - unsigned char* key_schedule); -*/ -.align 16,0x90 -.globl AES_128_Key_Expansion -AES_128_Key_Expansion: -# parameter 1: %rdi -# parameter 2: %rsi -movl $10, 240(%rsi) - -movdqu (%rdi), %xmm1 -movdqa %xmm1, (%rsi) - - -ASSISTS: -aeskeygenassist $1, %xmm1, %xmm2 -call PREPARE_ROUNDKEY_128 -movdqa %xmm1, 16(%rsi) -aeskeygenassist $2, %xmm1, %xmm2 -call PREPARE_ROUNDKEY_128 -movdqa %xmm1, 32(%rsi) -aeskeygenassist $4, %xmm1, %xmm2 -call PREPARE_ROUNDKEY_128 -movdqa %xmm1, 48(%rsi) -aeskeygenassist $8, %xmm1, %xmm2 -call PREPARE_ROUNDKEY_128 -movdqa %xmm1, 64(%rsi) -aeskeygenassist $16, %xmm1, %xmm2 -call PREPARE_ROUNDKEY_128 -movdqa %xmm1, 80(%rsi) -aeskeygenassist $32, %xmm1, %xmm2 -call PREPARE_ROUNDKEY_128 -movdqa %xmm1, 96(%rsi) -aeskeygenassist $64, %xmm1, %xmm2 -call PREPARE_ROUNDKEY_128 -movdqa %xmm1, 112(%rsi) -aeskeygenassist $0x80, %xmm1, %xmm2 -call PREPARE_ROUNDKEY_128 -movdqa %xmm1, 128(%rsi) -aeskeygenassist $0x1b, %xmm1, %xmm2 -call PREPARE_ROUNDKEY_128 -movdqa %xmm1, 144(%rsi) -aeskeygenassist $0x36, %xmm1, %xmm2 -call PREPARE_ROUNDKEY_128 -movdqa %xmm1, 160(%rsi) -ret - -PREPARE_ROUNDKEY_128: -pshufd $255, %xmm2, %xmm2 -movdqa %xmm1, %xmm3 -pslldq $4, %xmm3 -pxor %xmm3, %xmm1 -pslldq $4, %xmm3 -pxor %xmm3, %xmm1 -pslldq $4, %xmm3 -pxor %xmm3, %xmm1 -pxor %xmm2, %xmm1 -ret - - -/* -void AES_192_Key_Expansion (const unsigned char *userkey, - unsigned char *key) -*/ -.globl AES_192_Key_Expansion -AES_192_Key_Expansion: -# parameter 1: %rdi -# parameter 2: %rsi - -movdqu (%rdi), %xmm1 -movdqu 16(%rdi), %xmm3 -movdqa %xmm1, (%rsi) -movdqa %xmm3, %xmm5 - -aeskeygenassist $0x1, %xmm3, %xmm2 -call PREPARE_ROUNDKEY_192 -shufpd $0, %xmm1, %xmm5 -movdqa %xmm5, 16(%rsi) -movdqa %xmm1, %xmm6 -shufpd $1, %xmm3, %xmm6 -movdqa %xmm6, 32(%rsi) - -aeskeygenassist $0x2, %xmm3, %xmm2 -call PREPARE_ROUNDKEY_192 -movdqa %xmm1, 48(%rsi) -movdqa %xmm3, %xmm5 - -aeskeygenassist $0x4, %xmm3, %xmm2 -call PREPARE_ROUNDKEY_192 -shufpd $0, %xmm1, %xmm5 -movdqa %xmm5, 64(%rsi) -movdqa %xmm1, %xmm6 -shufpd $1, %xmm3, %xmm6 -movdqa %xmm6, 80(%rsi) - -aeskeygenassist $0x8, %xmm3, %xmm2 -call PREPARE_ROUNDKEY_192 -movdqa %xmm1, 96(%rsi) -movdqa %xmm3, %xmm5 - -aeskeygenassist $0x10, %xmm3, %xmm2 -call PREPARE_ROUNDKEY_192 -shufpd $0, %xmm1, %xmm5 -movdqa %xmm5, 112(%rsi) -movdqa %xmm1, %xmm6 -shufpd $1, %xmm3, %xmm6 -movdqa %xmm6, 128(%rsi) - -aeskeygenassist $0x20, %xmm3, %xmm2 -call PREPARE_ROUNDKEY_192 -movdqa %xmm1, 144(%rsi) -movdqa %xmm3, %xmm5 - -aeskeygenassist $0x40, %xmm3, %xmm2 -call PREPARE_ROUNDKEY_192 -shufpd $0, %xmm1, %xmm5 -movdqa %xmm5, 160(%rsi) -movdqa %xmm1, %xmm6 -shufpd $1, %xmm3, %xmm6 -movdqa %xmm6, 176(%rsi) - -aeskeygenassist $0x80, %xmm3, %xmm2 -call PREPARE_ROUNDKEY_192 -movdqa %xmm1, 192(%rsi) -movdqa %xmm3, 208(%rsi) -ret - -PREPARE_ROUNDKEY_192: -pshufd $0x55, %xmm2, %xmm2 -movdqu %xmm1, %xmm4 -pslldq $4, %xmm4 -pxor %xmm4, %xmm1 - -pslldq $4, %xmm4 -pxor %xmm4, %xmm1 -pslldq $4, %xmm4 -pxor %xmm4, %xmm1 -pxor %xmm2, %xmm1 -pshufd $0xff, %xmm1, %xmm2 -movdqu %xmm3, %xmm4 -pslldq $4, %xmm4 -pxor %xmm4, %xmm3 -pxor %xmm2, %xmm3 -ret - - -/* -void AES_256_Key_Expansion (const unsigned char *userkey, - unsigned char *key) -*/ -.globl AES_256_Key_Expansion -AES_256_Key_Expansion: -# parameter 1: %rdi -# parameter 2: %rsi - -movdqu (%rdi), %xmm1 -movdqu 16(%rdi), %xmm3 -movdqa %xmm1, (%rsi) -movdqa %xmm3, 16(%rsi) - -aeskeygenassist $0x1, %xmm3, %xmm2 -call MAKE_RK256_a -movdqa %xmm1, 32(%rsi) -aeskeygenassist $0x0, %xmm1, %xmm2 -call MAKE_RK256_b -movdqa %xmm3, 48(%rsi) -aeskeygenassist $0x2, %xmm3, %xmm2 -call MAKE_RK256_a -movdqa %xmm1, 64(%rsi) -aeskeygenassist $0x0, %xmm1, %xmm2 -call MAKE_RK256_b -movdqa %xmm3, 80(%rsi) -aeskeygenassist $0x4, %xmm3, %xmm2 -call MAKE_RK256_a -movdqa %xmm1, 96(%rsi) -aeskeygenassist $0x0, %xmm1, %xmm2 -call MAKE_RK256_b -movdqa %xmm3, 112(%rsi) -aeskeygenassist $0x8, %xmm3, %xmm2 -call MAKE_RK256_a -movdqa %xmm1, 128(%rsi) -aeskeygenassist $0x0, %xmm1, %xmm2 -call MAKE_RK256_b -movdqa %xmm3, 144(%rsi) -aeskeygenassist $0x10, %xmm3, %xmm2 -call MAKE_RK256_a -movdqa %xmm1, 160(%rsi) -aeskeygenassist $0x0, %xmm1, %xmm2 -call MAKE_RK256_b -movdqa %xmm3, 176(%rsi) -aeskeygenassist $0x20, %xmm3, %xmm2 -call MAKE_RK256_a -movdqa %xmm1, 192(%rsi) - -aeskeygenassist $0x0, %xmm1, %xmm2 -call MAKE_RK256_b -movdqa %xmm3, 208(%rsi) -aeskeygenassist $0x40, %xmm3, %xmm2 -call MAKE_RK256_a -movdqa %xmm1, 224(%rsi) - -ret - -MAKE_RK256_a: -pshufd $0xff, %xmm2, %xmm2 -movdqa %xmm1, %xmm4 -pslldq $4, %xmm4 -pxor %xmm4, %xmm1 -pslldq $4, %xmm4 -pxor %xmm4, %xmm1 -pslldq $4, %xmm4 -pxor %xmm4, %xmm1 -pxor %xmm2, %xmm1 -ret - -MAKE_RK256_b: -pshufd $0xaa, %xmm2, %xmm2 -movdqa %xmm3, %xmm4 -pslldq $4, %xmm4 -pxor %xmm4, %xmm3 -pslldq $4, %xmm4 -pxor %xmm4, %xmm3 -pslldq $4, %xmm4 -pxor %xmm4, %xmm3 -pxor %xmm2, %xmm3 -ret - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_gcm_asm.S b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_gcm_asm.S new file mode 100644 index 000000000..e878690e8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/aes_gcm_asm.S @@ -0,0 +1,8733 @@ +/* aes_gcm_asm + * + * Copyright (C) 2006-2020 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 HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX1 +#endif /* HAVE_INTEL_AVX1 */ +#ifndef NO_AVX2_SUPPORT +#define HAVE_INTEL_AVX2 +#endif /* NO_AVX2_SUPPORT */ + +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_one: +.quad 0x0, 0x1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_two: +.quad 0x0, 0x2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_three: +.quad 0x0, 0x3 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_four: +.quad 0x0, 0x4 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_five: +.quad 0x0, 0x5 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_six: +.quad 0x0, 0x6 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_seven: +.quad 0x0, 0x7 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_eight: +.quad 0x0, 0x8 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_bswap_epi64: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_bswap_mask: +.quad 0x8090a0b0c0d0e0f, 0x1020304050607 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_mod2_128: +.quad 0x1, 0xc200000000000000 +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt +.type AES_GCM_encrypt,@function +.align 4 +AES_GCM_encrypt: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt +.p2align 2 +_AES_GCM_encrypt: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %rbx + pushq %r14 + pushq %r15 + movq %rdx, %r12 + movq %rcx, %rax + movl 48(%rsp), %r11d + movl 56(%rsp), %ebx + movl 64(%rsp), %r14d + movq 72(%rsp), %r15 + movl 80(%rsp), %r10d + subq $0xa0, %rsp + pxor %xmm4, %xmm4 + pxor %xmm6, %xmm6 + cmpl $12, %ebx + movl %ebx, %edx + jne L_AES_GCM_encrypt_iv_not_12 + # # Calculate values when IV is 12 bytes + # Set counter based on IV + movl $0x1000000, %ecx + pinsrq $0x00, (%rax), %xmm4 + pinsrd $2, 8(%rax), %xmm4 + pinsrd $3, %ecx, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + movdqa %xmm4, %xmm1 + movdqa (%r15), %xmm5 + pxor %xmm5, %xmm1 + movdqa 16(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 32(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 48(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 64(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 80(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 96(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 112(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 128(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 144(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + cmpl $11, %r10d + movdqa 160(%r15), %xmm7 + jl L_AES_GCM_encrypt_calc_iv_12_last + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 176(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + cmpl $13, %r10d + movdqa 192(%r15), %xmm7 + jl L_AES_GCM_encrypt_calc_iv_12_last + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 208(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 224(%r15), %xmm7 +L_AES_GCM_encrypt_calc_iv_12_last: + aesenclast %xmm7, %xmm5 + aesenclast %xmm7, %xmm1 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm5 + movdqa %xmm1, 144(%rsp) + jmp L_AES_GCM_encrypt_iv_done +L_AES_GCM_encrypt_iv_not_12: + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + movdqa (%r15), %xmm5 + aesenc 16(%r15), %xmm5 + aesenc 32(%r15), %xmm5 + aesenc 48(%r15), %xmm5 + aesenc 64(%r15), %xmm5 + aesenc 80(%r15), %xmm5 + aesenc 96(%r15), %xmm5 + aesenc 112(%r15), %xmm5 + aesenc 128(%r15), %xmm5 + aesenc 144(%r15), %xmm5 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_calc_iv_1_aesenc_avx_last + aesenc %xmm9, %xmm5 + aesenc 176(%r15), %xmm5 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_calc_iv_1_aesenc_avx_last + aesenc %xmm9, %xmm5 + aesenc 208(%r15), %xmm5 + movdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_calc_iv_1_aesenc_avx_last: + aesenclast %xmm9, %xmm5 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_encrypt_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_encrypt_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_encrypt_calc_iv_16_loop: + movdqu (%rax,%rcx,1), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_calc_iv_16_loop + movl %ebx, %edx + cmpl %edx, %ecx + je L_AES_GCM_encrypt_calc_iv_done +L_AES_GCM_encrypt_calc_iv_lt16: + subq $16, %rsp + pxor %xmm8, %xmm8 + xorl %ebx, %ebx + movdqa %xmm8, (%rsp) +L_AES_GCM_encrypt_calc_iv_loop: + movzbl (%rax,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_calc_iv_loop + movdqa (%rsp), %xmm8 + addq $16, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 +L_AES_GCM_encrypt_calc_iv_done: + # T = Encrypt counter + pxor %xmm0, %xmm0 + shll $3, %edx + pinsrq $0x00, %rdx, %xmm0 + pxor %xmm0, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm4 + # Encrypt counter + movdqa (%r15), %xmm8 + pxor %xmm4, %xmm8 + aesenc 16(%r15), %xmm8 + aesenc 32(%r15), %xmm8 + aesenc 48(%r15), %xmm8 + aesenc 64(%r15), %xmm8 + aesenc 80(%r15), %xmm8 + aesenc 96(%r15), %xmm8 + aesenc 112(%r15), %xmm8 + aesenc 128(%r15), %xmm8 + aesenc 144(%r15), %xmm8 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_calc_iv_2_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 176(%r15), %xmm8 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_calc_iv_2_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 208(%r15), %xmm8 + movdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_calc_iv_2_aesenc_avx_last: + aesenclast %xmm9, %xmm8 + movdqa %xmm8, 144(%rsp) +L_AES_GCM_encrypt_iv_done: + # Additional authentication data + movl %r11d, %edx + cmpl $0x00, %edx + je L_AES_GCM_encrypt_calc_aad_done + xorl %ecx, %ecx + cmpl $16, %edx + jl L_AES_GCM_encrypt_calc_aad_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_encrypt_calc_aad_16_loop: + movdqu (%r12,%rcx,1), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + pshufd $0x4e, %xmm6, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm6, %xmm3 + pclmulqdq $0x00, %xmm6, %xmm0 + pxor %xmm6, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm6, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm6 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm6 + por %xmm0, %xmm7 + por %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm6 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_calc_aad_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_encrypt_calc_aad_done +L_AES_GCM_encrypt_calc_aad_lt16: + subq $16, %rsp + pxor %xmm8, %xmm8 + xorl %ebx, %ebx + movdqa %xmm8, (%rsp) +L_AES_GCM_encrypt_calc_aad_loop: + movzbl (%r12,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_calc_aad_loop + movdqa (%rsp), %xmm8 + addq $16, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + pshufd $0x4e, %xmm6, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm6, %xmm3 + pclmulqdq $0x00, %xmm6, %xmm0 + pxor %xmm6, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm6, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm6 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm6 + por %xmm0, %xmm7 + por %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm6 +L_AES_GCM_encrypt_calc_aad_done: + # Calculate counter and H + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm4 + movdqa %xmm5, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm4 + movdqa %xmm5, %xmm8 + movdqa %xmm4, 128(%rsp) + psrlq $63, %xmm9 + psllq $0x01, %xmm8 + pslldq $8, %xmm9 + por %xmm9, %xmm8 + pshufd $0xff, %xmm5, %xmm5 + psrad $31, %xmm5 + pand L_aes_gcm_mod2_128(%rip), %xmm5 + pxor %xmm8, %xmm5 + xorq %rbx, %rbx + cmpl $0x80, %r9d + movl %r9d, %r13d + jl L_AES_GCM_encrypt_done_128 + andl $0xffffff80, %r13d + movdqa %xmm6, %xmm2 + # H ^ 1 + movdqa %xmm5, (%rsp) + # H ^ 2 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm5, %xmm10 + movdqa %xmm5, %xmm11 + movdqa %xmm5, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm5, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm0 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm0 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm0 + movdqa %xmm0, 16(%rsp) + # H ^ 3 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm0, %xmm10 + movdqa %xmm0, %xmm11 + movdqa %xmm0, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm0, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm1 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm1 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm1 + movdqa %xmm1, 32(%rsp) + # H ^ 4 + pshufd $0x4e, %xmm0, %xmm9 + pshufd $0x4e, %xmm0, %xmm10 + movdqa %xmm0, %xmm11 + movdqa %xmm0, %xmm8 + pclmulqdq $0x11, %xmm0, %xmm11 + pclmulqdq $0x00, %xmm0, %xmm8 + pxor %xmm0, %xmm9 + pxor %xmm0, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm3 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm3 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm3 + movdqa %xmm3, 48(%rsp) + # H ^ 5 + pshufd $0x4e, %xmm0, %xmm9 + pshufd $0x4e, %xmm1, %xmm10 + movdqa %xmm1, %xmm11 + movdqa %xmm1, %xmm8 + pclmulqdq $0x11, %xmm0, %xmm11 + pclmulqdq $0x00, %xmm0, %xmm8 + pxor %xmm0, %xmm9 + pxor %xmm1, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 64(%rsp) + # H ^ 6 + pshufd $0x4e, %xmm1, %xmm9 + pshufd $0x4e, %xmm1, %xmm10 + movdqa %xmm1, %xmm11 + movdqa %xmm1, %xmm8 + pclmulqdq $0x11, %xmm1, %xmm11 + pclmulqdq $0x00, %xmm1, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm1, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 80(%rsp) + # H ^ 7 + pshufd $0x4e, %xmm1, %xmm9 + pshufd $0x4e, %xmm3, %xmm10 + movdqa %xmm3, %xmm11 + movdqa %xmm3, %xmm8 + pclmulqdq $0x11, %xmm1, %xmm11 + pclmulqdq $0x00, %xmm1, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm3, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 96(%rsp) + # H ^ 8 + pshufd $0x4e, %xmm3, %xmm9 + pshufd $0x4e, %xmm3, %xmm10 + movdqa %xmm3, %xmm11 + movdqa %xmm3, %xmm8 + pclmulqdq $0x11, %xmm3, %xmm11 + pclmulqdq $0x00, %xmm3, %xmm8 + pxor %xmm3, %xmm9 + pxor %xmm3, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 112(%rsp) + # First 128 bytes of input + movdqa 128(%rsp), %xmm8 + movdqa L_aes_gcm_bswap_epi64(%rip), %xmm1 + movdqa %xmm8, %xmm0 + pshufb %xmm1, %xmm8 + movdqa %xmm0, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm9 + pshufb %xmm1, %xmm9 + movdqa %xmm0, %xmm10 + paddd L_aes_gcm_two(%rip), %xmm10 + pshufb %xmm1, %xmm10 + movdqa %xmm0, %xmm11 + paddd L_aes_gcm_three(%rip), %xmm11 + pshufb %xmm1, %xmm11 + movdqa %xmm0, %xmm12 + paddd L_aes_gcm_four(%rip), %xmm12 + pshufb %xmm1, %xmm12 + movdqa %xmm0, %xmm13 + paddd L_aes_gcm_five(%rip), %xmm13 + pshufb %xmm1, %xmm13 + movdqa %xmm0, %xmm14 + paddd L_aes_gcm_six(%rip), %xmm14 + pshufb %xmm1, %xmm14 + movdqa %xmm0, %xmm15 + paddd L_aes_gcm_seven(%rip), %xmm15 + pshufb %xmm1, %xmm15 + paddd L_aes_gcm_eight(%rip), %xmm0 + movdqa (%r15), %xmm7 + movdqa %xmm0, 128(%rsp) + pxor %xmm7, %xmm8 + pxor %xmm7, %xmm9 + pxor %xmm7, %xmm10 + pxor %xmm7, %xmm11 + pxor %xmm7, %xmm12 + pxor %xmm7, %xmm13 + pxor %xmm7, %xmm14 + pxor %xmm7, %xmm15 + movdqa 16(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 32(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 48(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 64(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 80(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 96(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 112(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 128(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 144(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + cmpl $11, %r10d + movdqa 160(%r15), %xmm7 + jl L_AES_GCM_encrypt_enc_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 176(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + cmpl $13, %r10d + movdqa 192(%r15), %xmm7 + jl L_AES_GCM_encrypt_enc_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 208(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 224(%r15), %xmm7 +L_AES_GCM_encrypt_enc_done: + aesenclast %xmm7, %xmm8 + aesenclast %xmm7, %xmm9 + movdqu (%rdi), %xmm0 + movdqu 16(%rdi), %xmm1 + pxor %xmm0, %xmm8 + pxor %xmm1, %xmm9 + movdqu %xmm8, (%rsi) + movdqu %xmm9, 16(%rsi) + aesenclast %xmm7, %xmm10 + aesenclast %xmm7, %xmm11 + movdqu 32(%rdi), %xmm0 + movdqu 48(%rdi), %xmm1 + pxor %xmm0, %xmm10 + pxor %xmm1, %xmm11 + movdqu %xmm10, 32(%rsi) + movdqu %xmm11, 48(%rsi) + aesenclast %xmm7, %xmm12 + aesenclast %xmm7, %xmm13 + movdqu 64(%rdi), %xmm0 + movdqu 80(%rdi), %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + movdqu %xmm12, 64(%rsi) + movdqu %xmm13, 80(%rsi) + aesenclast %xmm7, %xmm14 + aesenclast %xmm7, %xmm15 + movdqu 96(%rdi), %xmm0 + movdqu 112(%rdi), %xmm1 + pxor %xmm0, %xmm14 + pxor %xmm1, %xmm15 + movdqu %xmm14, 96(%rsi) + movdqu %xmm15, 112(%rsi) + cmpl $0x80, %r13d + movl $0x80, %ebx + jle L_AES_GCM_encrypt_end_128 + # More 128 bytes of input +L_AES_GCM_encrypt_ghash_128: + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + movdqa 128(%rsp), %xmm8 + movdqa L_aes_gcm_bswap_epi64(%rip), %xmm1 + movdqa %xmm8, %xmm0 + pshufb %xmm1, %xmm8 + movdqa %xmm0, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm9 + pshufb %xmm1, %xmm9 + movdqa %xmm0, %xmm10 + paddd L_aes_gcm_two(%rip), %xmm10 + pshufb %xmm1, %xmm10 + movdqa %xmm0, %xmm11 + paddd L_aes_gcm_three(%rip), %xmm11 + pshufb %xmm1, %xmm11 + movdqa %xmm0, %xmm12 + paddd L_aes_gcm_four(%rip), %xmm12 + pshufb %xmm1, %xmm12 + movdqa %xmm0, %xmm13 + paddd L_aes_gcm_five(%rip), %xmm13 + pshufb %xmm1, %xmm13 + movdqa %xmm0, %xmm14 + paddd L_aes_gcm_six(%rip), %xmm14 + pshufb %xmm1, %xmm14 + movdqa %xmm0, %xmm15 + paddd L_aes_gcm_seven(%rip), %xmm15 + pshufb %xmm1, %xmm15 + paddd L_aes_gcm_eight(%rip), %xmm0 + movdqa (%r15), %xmm7 + movdqa %xmm0, 128(%rsp) + pxor %xmm7, %xmm8 + pxor %xmm7, %xmm9 + pxor %xmm7, %xmm10 + pxor %xmm7, %xmm11 + pxor %xmm7, %xmm12 + pxor %xmm7, %xmm13 + pxor %xmm7, %xmm14 + pxor %xmm7, %xmm15 + movdqa 112(%rsp), %xmm7 + movdqu -128(%rdx), %xmm0 + aesenc 16(%r15), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + pxor %xmm2, %xmm0 + pshufd $0x4e, %xmm7, %xmm1 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm7, %xmm1 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm3 + pclmulqdq $0x11, %xmm7, %xmm3 + aesenc 16(%r15), %xmm9 + aesenc 16(%r15), %xmm10 + movdqa %xmm0, %xmm2 + pclmulqdq $0x00, %xmm7, %xmm2 + aesenc 16(%r15), %xmm11 + aesenc 16(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm1 + aesenc 16(%r15), %xmm13 + aesenc 16(%r15), %xmm14 + aesenc 16(%r15), %xmm15 + pxor %xmm2, %xmm1 + pxor %xmm3, %xmm1 + movdqa 96(%rsp), %xmm7 + movdqu -112(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 32(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 32(%r15), %xmm9 + aesenc 32(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 32(%r15), %xmm11 + aesenc 32(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 32(%r15), %xmm13 + aesenc 32(%r15), %xmm14 + aesenc 32(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 80(%rsp), %xmm7 + movdqu -96(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 48(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 48(%r15), %xmm9 + aesenc 48(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 48(%r15), %xmm11 + aesenc 48(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 48(%r15), %xmm13 + aesenc 48(%r15), %xmm14 + aesenc 48(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 64(%rsp), %xmm7 + movdqu -80(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 64(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 64(%r15), %xmm9 + aesenc 64(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 64(%r15), %xmm11 + aesenc 64(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 64(%r15), %xmm13 + aesenc 64(%r15), %xmm14 + aesenc 64(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 48(%rsp), %xmm7 + movdqu -64(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 80(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 80(%r15), %xmm9 + aesenc 80(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 80(%r15), %xmm11 + aesenc 80(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 80(%r15), %xmm13 + aesenc 80(%r15), %xmm14 + aesenc 80(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 32(%rsp), %xmm7 + movdqu -48(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 96(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 96(%r15), %xmm9 + aesenc 96(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 96(%r15), %xmm11 + aesenc 96(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 96(%r15), %xmm13 + aesenc 96(%r15), %xmm14 + aesenc 96(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 16(%rsp), %xmm7 + movdqu -32(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 112(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 112(%r15), %xmm9 + aesenc 112(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 112(%r15), %xmm11 + aesenc 112(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 112(%r15), %xmm13 + aesenc 112(%r15), %xmm14 + aesenc 112(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa (%rsp), %xmm7 + movdqu -16(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 128(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 128(%r15), %xmm9 + aesenc 128(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 128(%r15), %xmm11 + aesenc 128(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 128(%r15), %xmm13 + aesenc 128(%r15), %xmm14 + aesenc 128(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa %xmm1, %xmm5 + psrldq $8, %xmm1 + pslldq $8, %xmm5 + aesenc 144(%r15), %xmm8 + pxor %xmm5, %xmm2 + pxor %xmm1, %xmm3 + movdqa %xmm2, %xmm7 + movdqa %xmm2, %xmm4 + movdqa %xmm2, %xmm5 + aesenc 144(%r15), %xmm9 + pslld $31, %xmm7 + pslld $30, %xmm4 + pslld $25, %xmm5 + aesenc 144(%r15), %xmm10 + pxor %xmm4, %xmm7 + pxor %xmm5, %xmm7 + aesenc 144(%r15), %xmm11 + movdqa %xmm7, %xmm4 + pslldq $12, %xmm7 + psrldq $4, %xmm4 + aesenc 144(%r15), %xmm12 + pxor %xmm7, %xmm2 + movdqa %xmm2, %xmm5 + movdqa %xmm2, %xmm1 + movdqa %xmm2, %xmm0 + aesenc 144(%r15), %xmm13 + psrld $0x01, %xmm5 + psrld $2, %xmm1 + psrld $7, %xmm0 + aesenc 144(%r15), %xmm14 + pxor %xmm1, %xmm5 + pxor %xmm0, %xmm5 + aesenc 144(%r15), %xmm15 + pxor %xmm4, %xmm5 + pxor %xmm5, %xmm2 + pxor %xmm3, %xmm2 + cmpl $11, %r10d + movdqa 160(%r15), %xmm7 + jl L_AES_GCM_encrypt_aesenc_128_ghash_avx_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 176(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + cmpl $13, %r10d + movdqa 192(%r15), %xmm7 + jl L_AES_GCM_encrypt_aesenc_128_ghash_avx_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 208(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 224(%r15), %xmm7 +L_AES_GCM_encrypt_aesenc_128_ghash_avx_done: + aesenclast %xmm7, %xmm8 + aesenclast %xmm7, %xmm9 + movdqu (%rcx), %xmm0 + movdqu 16(%rcx), %xmm1 + pxor %xmm0, %xmm8 + pxor %xmm1, %xmm9 + movdqu %xmm8, (%rdx) + movdqu %xmm9, 16(%rdx) + aesenclast %xmm7, %xmm10 + aesenclast %xmm7, %xmm11 + movdqu 32(%rcx), %xmm0 + movdqu 48(%rcx), %xmm1 + pxor %xmm0, %xmm10 + pxor %xmm1, %xmm11 + movdqu %xmm10, 32(%rdx) + movdqu %xmm11, 48(%rdx) + aesenclast %xmm7, %xmm12 + aesenclast %xmm7, %xmm13 + movdqu 64(%rcx), %xmm0 + movdqu 80(%rcx), %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + movdqu %xmm12, 64(%rdx) + movdqu %xmm13, 80(%rdx) + aesenclast %xmm7, %xmm14 + aesenclast %xmm7, %xmm15 + movdqu 96(%rcx), %xmm0 + movdqu 112(%rcx), %xmm1 + pxor %xmm0, %xmm14 + pxor %xmm1, %xmm15 + movdqu %xmm14, 96(%rdx) + movdqu %xmm15, 112(%rdx) + addl $0x80, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_encrypt_ghash_128 +L_AES_GCM_encrypt_end_128: + movdqa L_aes_gcm_bswap_mask(%rip), %xmm4 + pshufb %xmm4, %xmm8 + pshufb %xmm4, %xmm9 + pshufb %xmm4, %xmm10 + pshufb %xmm4, %xmm11 + pxor %xmm2, %xmm8 + pshufb %xmm4, %xmm12 + pshufb %xmm4, %xmm13 + pshufb %xmm4, %xmm14 + pshufb %xmm4, %xmm15 + movdqa 112(%rsp), %xmm7 + pshufd $0x4e, %xmm8, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm8, %xmm3 + pclmulqdq $0x00, %xmm8, %xmm0 + pxor %xmm8, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm4 + movdqa %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 96(%rsp), %xmm7 + pshufd $0x4e, %xmm9, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm9, %xmm3 + pclmulqdq $0x00, %xmm9, %xmm0 + pxor %xmm9, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 80(%rsp), %xmm7 + pshufd $0x4e, %xmm10, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm10, %xmm3 + pclmulqdq $0x00, %xmm10, %xmm0 + pxor %xmm10, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 64(%rsp), %xmm7 + pshufd $0x4e, %xmm11, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm11, %xmm3 + pclmulqdq $0x00, %xmm11, %xmm0 + pxor %xmm11, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 48(%rsp), %xmm7 + pshufd $0x4e, %xmm12, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm12, %xmm3 + pclmulqdq $0x00, %xmm12, %xmm0 + pxor %xmm12, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 32(%rsp), %xmm7 + pshufd $0x4e, %xmm13, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm13, %xmm3 + pclmulqdq $0x00, %xmm13, %xmm0 + pxor %xmm13, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 16(%rsp), %xmm7 + pshufd $0x4e, %xmm14, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm14, %xmm3 + pclmulqdq $0x00, %xmm14, %xmm0 + pxor %xmm14, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa (%rsp), %xmm7 + pshufd $0x4e, %xmm15, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm15, %xmm3 + pclmulqdq $0x00, %xmm15, %xmm0 + pxor %xmm15, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa %xmm4, %xmm0 + movdqa %xmm4, %xmm1 + movdqa %xmm4, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm4 + movdqa %xmm4, %xmm2 + movdqa %xmm4, %xmm3 + movdqa %xmm4, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm4, %xmm2 + pxor %xmm2, %xmm6 + movdqa (%rsp), %xmm5 +L_AES_GCM_encrypt_done_128: + movl %r9d, %edx + cmpl %edx, %ebx + jge L_AES_GCM_encrypt_done_enc + movl %r9d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %ebx + jge L_AES_GCM_encrypt_last_block_done + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + movdqa 128(%rsp), %xmm8 + movdqa %xmm8, %xmm9 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm8 + paddd L_aes_gcm_one(%rip), %xmm9 + pxor (%r15), %xmm8 + movdqa %xmm9, 128(%rsp) + aesenc 16(%r15), %xmm8 + aesenc 32(%r15), %xmm8 + aesenc 48(%r15), %xmm8 + aesenc 64(%r15), %xmm8 + aesenc 80(%r15), %xmm8 + aesenc 96(%r15), %xmm8 + aesenc 112(%r15), %xmm8 + aesenc 128(%r15), %xmm8 + aesenc 144(%r15), %xmm8 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_aesenc_block_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 176(%r15), %xmm8 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_aesenc_block_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 208(%r15), %xmm8 + movdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_aesenc_block_aesenc_avx_last: + aesenclast %xmm9, %xmm8 + movdqu (%rcx), %xmm9 + pxor %xmm9, %xmm8 + movdqu %xmm8, (%rdx) + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + addl $16, %ebx + cmpl %r13d, %ebx + jge L_AES_GCM_encrypt_last_block_ghash +L_AES_GCM_encrypt_last_block_start: + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + movdqa 128(%rsp), %xmm8 + movdqa %xmm8, %xmm9 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm8 + paddd L_aes_gcm_one(%rip), %xmm9 + pxor (%r15), %xmm8 + movdqa %xmm9, 128(%rsp) + movdqa %xmm6, %xmm10 + pclmulqdq $16, %xmm5, %xmm10 + aesenc 16(%r15), %xmm8 + aesenc 32(%r15), %xmm8 + movdqa %xmm6, %xmm11 + pclmulqdq $0x01, %xmm5, %xmm11 + aesenc 48(%r15), %xmm8 + aesenc 64(%r15), %xmm8 + movdqa %xmm6, %xmm12 + pclmulqdq $0x00, %xmm5, %xmm12 + aesenc 80(%r15), %xmm8 + movdqa %xmm6, %xmm1 + pclmulqdq $0x11, %xmm5, %xmm1 + aesenc 96(%r15), %xmm8 + pxor %xmm11, %xmm10 + movdqa %xmm10, %xmm2 + psrldq $8, %xmm10 + pslldq $8, %xmm2 + aesenc 112(%r15), %xmm8 + movdqa %xmm1, %xmm3 + pxor %xmm12, %xmm2 + pxor %xmm10, %xmm3 + movdqa L_aes_gcm_mod2_128(%rip), %xmm0 + movdqa %xmm2, %xmm11 + pclmulqdq $16, %xmm0, %xmm11 + aesenc 128(%r15), %xmm8 + pshufd $0x4e, %xmm2, %xmm10 + pxor %xmm11, %xmm10 + movdqa %xmm10, %xmm11 + pclmulqdq $16, %xmm0, %xmm11 + aesenc 144(%r15), %xmm8 + pshufd $0x4e, %xmm10, %xmm6 + pxor %xmm11, %xmm6 + pxor %xmm3, %xmm6 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_aesenc_gfmul_last + aesenc %xmm9, %xmm8 + aesenc 176(%r15), %xmm8 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_aesenc_gfmul_last + aesenc %xmm9, %xmm8 + aesenc 208(%r15), %xmm8 + movdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_aesenc_gfmul_last: + aesenclast %xmm9, %xmm8 + movdqu (%rcx), %xmm9 + pxor %xmm9, %xmm8 + movdqu %xmm8, (%rdx) + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + addl $16, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_encrypt_last_block_start +L_AES_GCM_encrypt_last_block_ghash: + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm6, %xmm10 + movdqa %xmm6, %xmm11 + movdqa %xmm6, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm6, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm6 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm6 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm6 +L_AES_GCM_encrypt_last_block_done: + movl %r9d, %ecx + movl %ecx, %edx + andl $15, %ecx + jz L_AES_GCM_encrypt_aesenc_last15_enc_avx_done + movdqa 128(%rsp), %xmm4 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm4 + pxor (%r15), %xmm4 + aesenc 16(%r15), %xmm4 + aesenc 32(%r15), %xmm4 + aesenc 48(%r15), %xmm4 + aesenc 64(%r15), %xmm4 + aesenc 80(%r15), %xmm4 + aesenc 96(%r15), %xmm4 + aesenc 112(%r15), %xmm4 + aesenc 128(%r15), %xmm4 + aesenc 144(%r15), %xmm4 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_aesenc_last15_enc_avx_aesenc_avx_last + aesenc %xmm9, %xmm4 + aesenc 176(%r15), %xmm4 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_aesenc_last15_enc_avx_aesenc_avx_last + aesenc %xmm9, %xmm4 + aesenc 208(%r15), %xmm4 + movdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_aesenc_last15_enc_avx_aesenc_avx_last: + aesenclast %xmm9, %xmm4 + subq $16, %rsp + xorl %ecx, %ecx + movdqa %xmm4, (%rsp) +L_AES_GCM_encrypt_aesenc_last15_enc_avx_loop: + movzbl (%rdi,%rbx,1), %r13d + xorb (%rsp,%rcx,1), %r13b + movb %r13b, (%rsi,%rbx,1) + movb %r13b, (%rsp,%rcx,1) + incl %ebx + incl %ecx + cmpl %edx, %ebx + jl L_AES_GCM_encrypt_aesenc_last15_enc_avx_loop + xorq %r13, %r13 + cmpl $16, %ecx + je L_AES_GCM_encrypt_aesenc_last15_enc_avx_finish_enc +L_AES_GCM_encrypt_aesenc_last15_enc_avx_byte_loop: + movb %r13b, (%rsp,%rcx,1) + incl %ecx + cmpl $16, %ecx + jl L_AES_GCM_encrypt_aesenc_last15_enc_avx_byte_loop +L_AES_GCM_encrypt_aesenc_last15_enc_avx_finish_enc: + movdqa (%rsp), %xmm4 + addq $16, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm4 + pxor %xmm4, %xmm6 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm6, %xmm10 + movdqa %xmm6, %xmm11 + movdqa %xmm6, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm6, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm6 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm6 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm6 +L_AES_GCM_encrypt_aesenc_last15_enc_avx_done: +L_AES_GCM_encrypt_done_enc: + movl %r9d, %edx + movl %r11d, %ecx + shlq $3, %rdx + shlq $3, %rcx + pinsrq $0x00, %rdx, %xmm0 + pinsrq $0x01, %rcx, %xmm0 + pxor %xmm0, %xmm6 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm6, %xmm10 + movdqa %xmm6, %xmm11 + movdqa %xmm6, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm6, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm6 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm6 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm6 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm6 + movdqa 144(%rsp), %xmm0 + pxor %xmm6, %xmm0 + cmpl $16, %r14d + je L_AES_GCM_encrypt_store_tag_16 + xorq %rcx, %rcx + movdqa %xmm0, (%rsp) +L_AES_GCM_encrypt_store_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + movb %r13b, (%r8,%rcx,1) + incl %ecx + cmpl %r14d, %ecx + jne L_AES_GCM_encrypt_store_tag_loop + jmp L_AES_GCM_encrypt_store_tag_done +L_AES_GCM_encrypt_store_tag_16: + movdqu %xmm0, (%r8) +L_AES_GCM_encrypt_store_tag_done: + addq $0xa0, %rsp + popq %r15 + popq %r14 + popq %rbx + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt,.-AES_GCM_encrypt +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_decrypt +.type AES_GCM_decrypt,@function +.align 4 +AES_GCM_decrypt: +#else +.section __TEXT,__text +.globl _AES_GCM_decrypt +.p2align 2 +_AES_GCM_decrypt: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %rbx + pushq %r14 + pushq %r15 + pushq %rbp + movq %rdx, %r12 + movq %rcx, %rax + movl 56(%rsp), %r11d + movl 64(%rsp), %ebx + movl 72(%rsp), %r14d + movq 80(%rsp), %r15 + movl 88(%rsp), %r10d + movq 96(%rsp), %rbp + subq $0xa8, %rsp + pxor %xmm4, %xmm4 + pxor %xmm6, %xmm6 + cmpl $12, %ebx + movl %ebx, %edx + jne L_AES_GCM_decrypt_iv_not_12 + # # Calculate values when IV is 12 bytes + # Set counter based on IV + movl $0x1000000, %ecx + pinsrq $0x00, (%rax), %xmm4 + pinsrd $2, 8(%rax), %xmm4 + pinsrd $3, %ecx, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + movdqa %xmm4, %xmm1 + movdqa (%r15), %xmm5 + pxor %xmm5, %xmm1 + movdqa 16(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 32(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 48(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 64(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 80(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 96(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 112(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 128(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 144(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + cmpl $11, %r10d + movdqa 160(%r15), %xmm7 + jl L_AES_GCM_decrypt_calc_iv_12_last + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 176(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + cmpl $13, %r10d + movdqa 192(%r15), %xmm7 + jl L_AES_GCM_decrypt_calc_iv_12_last + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 208(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 224(%r15), %xmm7 +L_AES_GCM_decrypt_calc_iv_12_last: + aesenclast %xmm7, %xmm5 + aesenclast %xmm7, %xmm1 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm5 + movdqa %xmm1, 144(%rsp) + jmp L_AES_GCM_decrypt_iv_done +L_AES_GCM_decrypt_iv_not_12: + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + movdqa (%r15), %xmm5 + aesenc 16(%r15), %xmm5 + aesenc 32(%r15), %xmm5 + aesenc 48(%r15), %xmm5 + aesenc 64(%r15), %xmm5 + aesenc 80(%r15), %xmm5 + aesenc 96(%r15), %xmm5 + aesenc 112(%r15), %xmm5 + aesenc 128(%r15), %xmm5 + aesenc 144(%r15), %xmm5 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_calc_iv_1_aesenc_avx_last + aesenc %xmm9, %xmm5 + aesenc 176(%r15), %xmm5 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_calc_iv_1_aesenc_avx_last + aesenc %xmm9, %xmm5 + aesenc 208(%r15), %xmm5 + movdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_calc_iv_1_aesenc_avx_last: + aesenclast %xmm9, %xmm5 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_decrypt_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_decrypt_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_decrypt_calc_iv_16_loop: + movdqu (%rax,%rcx,1), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_calc_iv_16_loop + movl %ebx, %edx + cmpl %edx, %ecx + je L_AES_GCM_decrypt_calc_iv_done +L_AES_GCM_decrypt_calc_iv_lt16: + subq $16, %rsp + pxor %xmm8, %xmm8 + xorl %ebx, %ebx + movdqa %xmm8, (%rsp) +L_AES_GCM_decrypt_calc_iv_loop: + movzbl (%rax,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_calc_iv_loop + movdqa (%rsp), %xmm8 + addq $16, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 +L_AES_GCM_decrypt_calc_iv_done: + # T = Encrypt counter + pxor %xmm0, %xmm0 + shll $3, %edx + pinsrq $0x00, %rdx, %xmm0 + pxor %xmm0, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm4 + # Encrypt counter + movdqa (%r15), %xmm8 + pxor %xmm4, %xmm8 + aesenc 16(%r15), %xmm8 + aesenc 32(%r15), %xmm8 + aesenc 48(%r15), %xmm8 + aesenc 64(%r15), %xmm8 + aesenc 80(%r15), %xmm8 + aesenc 96(%r15), %xmm8 + aesenc 112(%r15), %xmm8 + aesenc 128(%r15), %xmm8 + aesenc 144(%r15), %xmm8 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_calc_iv_2_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 176(%r15), %xmm8 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_calc_iv_2_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 208(%r15), %xmm8 + movdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_calc_iv_2_aesenc_avx_last: + aesenclast %xmm9, %xmm8 + movdqa %xmm8, 144(%rsp) +L_AES_GCM_decrypt_iv_done: + # Additional authentication data + movl %r11d, %edx + cmpl $0x00, %edx + je L_AES_GCM_decrypt_calc_aad_done + xorl %ecx, %ecx + cmpl $16, %edx + jl L_AES_GCM_decrypt_calc_aad_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_decrypt_calc_aad_16_loop: + movdqu (%r12,%rcx,1), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + pshufd $0x4e, %xmm6, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm6, %xmm3 + pclmulqdq $0x00, %xmm6, %xmm0 + pxor %xmm6, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm6, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm6 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm6 + por %xmm0, %xmm7 + por %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm6 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_calc_aad_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_decrypt_calc_aad_done +L_AES_GCM_decrypt_calc_aad_lt16: + subq $16, %rsp + pxor %xmm8, %xmm8 + xorl %ebx, %ebx + movdqa %xmm8, (%rsp) +L_AES_GCM_decrypt_calc_aad_loop: + movzbl (%r12,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_calc_aad_loop + movdqa (%rsp), %xmm8 + addq $16, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + pshufd $0x4e, %xmm6, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm6, %xmm3 + pclmulqdq $0x00, %xmm6, %xmm0 + pxor %xmm6, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm6, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm6 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm6 + por %xmm0, %xmm7 + por %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm6 +L_AES_GCM_decrypt_calc_aad_done: + # Calculate counter and H + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm4 + movdqa %xmm5, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm4 + movdqa %xmm5, %xmm8 + movdqa %xmm4, 128(%rsp) + psrlq $63, %xmm9 + psllq $0x01, %xmm8 + pslldq $8, %xmm9 + por %xmm9, %xmm8 + pshufd $0xff, %xmm5, %xmm5 + psrad $31, %xmm5 + pand L_aes_gcm_mod2_128(%rip), %xmm5 + pxor %xmm8, %xmm5 + xorl %ebx, %ebx + cmpl $0x80, %r9d + movl %r9d, %r13d + jl L_AES_GCM_decrypt_done_128 + andl $0xffffff80, %r13d + movdqa %xmm6, %xmm2 + # H ^ 1 + movdqa %xmm5, (%rsp) + # H ^ 2 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm5, %xmm10 + movdqa %xmm5, %xmm11 + movdqa %xmm5, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm5, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm0 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm0 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm0 + movdqa %xmm0, 16(%rsp) + # H ^ 3 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm0, %xmm10 + movdqa %xmm0, %xmm11 + movdqa %xmm0, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm0, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm1 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm1 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm1 + movdqa %xmm1, 32(%rsp) + # H ^ 4 + pshufd $0x4e, %xmm0, %xmm9 + pshufd $0x4e, %xmm0, %xmm10 + movdqa %xmm0, %xmm11 + movdqa %xmm0, %xmm8 + pclmulqdq $0x11, %xmm0, %xmm11 + pclmulqdq $0x00, %xmm0, %xmm8 + pxor %xmm0, %xmm9 + pxor %xmm0, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm3 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm3 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm3 + movdqa %xmm3, 48(%rsp) + # H ^ 5 + pshufd $0x4e, %xmm0, %xmm9 + pshufd $0x4e, %xmm1, %xmm10 + movdqa %xmm1, %xmm11 + movdqa %xmm1, %xmm8 + pclmulqdq $0x11, %xmm0, %xmm11 + pclmulqdq $0x00, %xmm0, %xmm8 + pxor %xmm0, %xmm9 + pxor %xmm1, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 64(%rsp) + # H ^ 6 + pshufd $0x4e, %xmm1, %xmm9 + pshufd $0x4e, %xmm1, %xmm10 + movdqa %xmm1, %xmm11 + movdqa %xmm1, %xmm8 + pclmulqdq $0x11, %xmm1, %xmm11 + pclmulqdq $0x00, %xmm1, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm1, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 80(%rsp) + # H ^ 7 + pshufd $0x4e, %xmm1, %xmm9 + pshufd $0x4e, %xmm3, %xmm10 + movdqa %xmm3, %xmm11 + movdqa %xmm3, %xmm8 + pclmulqdq $0x11, %xmm1, %xmm11 + pclmulqdq $0x00, %xmm1, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm3, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 96(%rsp) + # H ^ 8 + pshufd $0x4e, %xmm3, %xmm9 + pshufd $0x4e, %xmm3, %xmm10 + movdqa %xmm3, %xmm11 + movdqa %xmm3, %xmm8 + pclmulqdq $0x11, %xmm3, %xmm11 + pclmulqdq $0x00, %xmm3, %xmm8 + pxor %xmm3, %xmm9 + pxor %xmm3, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 112(%rsp) +L_AES_GCM_decrypt_ghash_128: + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + movdqa 128(%rsp), %xmm8 + movdqa L_aes_gcm_bswap_epi64(%rip), %xmm1 + movdqa %xmm8, %xmm0 + pshufb %xmm1, %xmm8 + movdqa %xmm0, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm9 + pshufb %xmm1, %xmm9 + movdqa %xmm0, %xmm10 + paddd L_aes_gcm_two(%rip), %xmm10 + pshufb %xmm1, %xmm10 + movdqa %xmm0, %xmm11 + paddd L_aes_gcm_three(%rip), %xmm11 + pshufb %xmm1, %xmm11 + movdqa %xmm0, %xmm12 + paddd L_aes_gcm_four(%rip), %xmm12 + pshufb %xmm1, %xmm12 + movdqa %xmm0, %xmm13 + paddd L_aes_gcm_five(%rip), %xmm13 + pshufb %xmm1, %xmm13 + movdqa %xmm0, %xmm14 + paddd L_aes_gcm_six(%rip), %xmm14 + pshufb %xmm1, %xmm14 + movdqa %xmm0, %xmm15 + paddd L_aes_gcm_seven(%rip), %xmm15 + pshufb %xmm1, %xmm15 + paddd L_aes_gcm_eight(%rip), %xmm0 + movdqa (%r15), %xmm7 + movdqa %xmm0, 128(%rsp) + pxor %xmm7, %xmm8 + pxor %xmm7, %xmm9 + pxor %xmm7, %xmm10 + pxor %xmm7, %xmm11 + pxor %xmm7, %xmm12 + pxor %xmm7, %xmm13 + pxor %xmm7, %xmm14 + pxor %xmm7, %xmm15 + movdqa 112(%rsp), %xmm7 + movdqu (%rcx), %xmm0 + aesenc 16(%r15), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + pxor %xmm2, %xmm0 + pshufd $0x4e, %xmm7, %xmm1 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm7, %xmm1 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm3 + pclmulqdq $0x11, %xmm7, %xmm3 + aesenc 16(%r15), %xmm9 + aesenc 16(%r15), %xmm10 + movdqa %xmm0, %xmm2 + pclmulqdq $0x00, %xmm7, %xmm2 + aesenc 16(%r15), %xmm11 + aesenc 16(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm1 + aesenc 16(%r15), %xmm13 + aesenc 16(%r15), %xmm14 + aesenc 16(%r15), %xmm15 + pxor %xmm2, %xmm1 + pxor %xmm3, %xmm1 + movdqa 96(%rsp), %xmm7 + movdqu 16(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 32(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 32(%r15), %xmm9 + aesenc 32(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 32(%r15), %xmm11 + aesenc 32(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 32(%r15), %xmm13 + aesenc 32(%r15), %xmm14 + aesenc 32(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 80(%rsp), %xmm7 + movdqu 32(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 48(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 48(%r15), %xmm9 + aesenc 48(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 48(%r15), %xmm11 + aesenc 48(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 48(%r15), %xmm13 + aesenc 48(%r15), %xmm14 + aesenc 48(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 64(%rsp), %xmm7 + movdqu 48(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 64(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 64(%r15), %xmm9 + aesenc 64(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 64(%r15), %xmm11 + aesenc 64(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 64(%r15), %xmm13 + aesenc 64(%r15), %xmm14 + aesenc 64(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 48(%rsp), %xmm7 + movdqu 64(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 80(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 80(%r15), %xmm9 + aesenc 80(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 80(%r15), %xmm11 + aesenc 80(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 80(%r15), %xmm13 + aesenc 80(%r15), %xmm14 + aesenc 80(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 32(%rsp), %xmm7 + movdqu 80(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 96(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 96(%r15), %xmm9 + aesenc 96(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 96(%r15), %xmm11 + aesenc 96(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 96(%r15), %xmm13 + aesenc 96(%r15), %xmm14 + aesenc 96(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 16(%rsp), %xmm7 + movdqu 96(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 112(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 112(%r15), %xmm9 + aesenc 112(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 112(%r15), %xmm11 + aesenc 112(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 112(%r15), %xmm13 + aesenc 112(%r15), %xmm14 + aesenc 112(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa (%rsp), %xmm7 + movdqu 112(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 128(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 128(%r15), %xmm9 + aesenc 128(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 128(%r15), %xmm11 + aesenc 128(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 128(%r15), %xmm13 + aesenc 128(%r15), %xmm14 + aesenc 128(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa %xmm1, %xmm5 + psrldq $8, %xmm1 + pslldq $8, %xmm5 + aesenc 144(%r15), %xmm8 + pxor %xmm5, %xmm2 + pxor %xmm1, %xmm3 + movdqa %xmm2, %xmm7 + movdqa %xmm2, %xmm4 + movdqa %xmm2, %xmm5 + aesenc 144(%r15), %xmm9 + pslld $31, %xmm7 + pslld $30, %xmm4 + pslld $25, %xmm5 + aesenc 144(%r15), %xmm10 + pxor %xmm4, %xmm7 + pxor %xmm5, %xmm7 + aesenc 144(%r15), %xmm11 + movdqa %xmm7, %xmm4 + pslldq $12, %xmm7 + psrldq $4, %xmm4 + aesenc 144(%r15), %xmm12 + pxor %xmm7, %xmm2 + movdqa %xmm2, %xmm5 + movdqa %xmm2, %xmm1 + movdqa %xmm2, %xmm0 + aesenc 144(%r15), %xmm13 + psrld $0x01, %xmm5 + psrld $2, %xmm1 + psrld $7, %xmm0 + aesenc 144(%r15), %xmm14 + pxor %xmm1, %xmm5 + pxor %xmm0, %xmm5 + aesenc 144(%r15), %xmm15 + pxor %xmm4, %xmm5 + pxor %xmm5, %xmm2 + pxor %xmm3, %xmm2 + cmpl $11, %r10d + movdqa 160(%r15), %xmm7 + jl L_AES_GCM_decrypt_aesenc_128_ghash_avx_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 176(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + cmpl $13, %r10d + movdqa 192(%r15), %xmm7 + jl L_AES_GCM_decrypt_aesenc_128_ghash_avx_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 208(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 224(%r15), %xmm7 +L_AES_GCM_decrypt_aesenc_128_ghash_avx_done: + aesenclast %xmm7, %xmm8 + aesenclast %xmm7, %xmm9 + movdqu (%rcx), %xmm0 + movdqu 16(%rcx), %xmm1 + pxor %xmm0, %xmm8 + pxor %xmm1, %xmm9 + movdqu %xmm8, (%rdx) + movdqu %xmm9, 16(%rdx) + aesenclast %xmm7, %xmm10 + aesenclast %xmm7, %xmm11 + movdqu 32(%rcx), %xmm0 + movdqu 48(%rcx), %xmm1 + pxor %xmm0, %xmm10 + pxor %xmm1, %xmm11 + movdqu %xmm10, 32(%rdx) + movdqu %xmm11, 48(%rdx) + aesenclast %xmm7, %xmm12 + aesenclast %xmm7, %xmm13 + movdqu 64(%rcx), %xmm0 + movdqu 80(%rcx), %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + movdqu %xmm12, 64(%rdx) + movdqu %xmm13, 80(%rdx) + aesenclast %xmm7, %xmm14 + aesenclast %xmm7, %xmm15 + movdqu 96(%rcx), %xmm0 + movdqu 112(%rcx), %xmm1 + pxor %xmm0, %xmm14 + pxor %xmm1, %xmm15 + movdqu %xmm14, 96(%rdx) + movdqu %xmm15, 112(%rdx) + addl $0x80, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_decrypt_ghash_128 + movdqa %xmm2, %xmm6 + movdqa (%rsp), %xmm5 +L_AES_GCM_decrypt_done_128: + movl %r9d, %edx + cmpl %edx, %ebx + jge L_AES_GCM_decrypt_done_dec + movl %r9d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %ebx + jge L_AES_GCM_decrypt_last_block_done +L_AES_GCM_decrypt_last_block_start: + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + movdqu (%rcx), %xmm1 + movdqa %xmm5, %xmm0 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm1 + pxor %xmm6, %xmm1 + movdqa 128(%rsp), %xmm8 + movdqa %xmm8, %xmm9 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm8 + paddd L_aes_gcm_one(%rip), %xmm9 + pxor (%r15), %xmm8 + movdqa %xmm9, 128(%rsp) + movdqa %xmm1, %xmm10 + pclmulqdq $16, %xmm0, %xmm10 + aesenc 16(%r15), %xmm8 + aesenc 32(%r15), %xmm8 + movdqa %xmm1, %xmm11 + pclmulqdq $0x01, %xmm0, %xmm11 + aesenc 48(%r15), %xmm8 + aesenc 64(%r15), %xmm8 + movdqa %xmm1, %xmm12 + pclmulqdq $0x00, %xmm0, %xmm12 + aesenc 80(%r15), %xmm8 + movdqa %xmm1, %xmm1 + pclmulqdq $0x11, %xmm0, %xmm1 + aesenc 96(%r15), %xmm8 + pxor %xmm11, %xmm10 + movdqa %xmm10, %xmm2 + psrldq $8, %xmm10 + pslldq $8, %xmm2 + aesenc 112(%r15), %xmm8 + movdqa %xmm1, %xmm3 + pxor %xmm12, %xmm2 + pxor %xmm10, %xmm3 + movdqa L_aes_gcm_mod2_128(%rip), %xmm0 + movdqa %xmm2, %xmm11 + pclmulqdq $16, %xmm0, %xmm11 + aesenc 128(%r15), %xmm8 + pshufd $0x4e, %xmm2, %xmm10 + pxor %xmm11, %xmm10 + movdqa %xmm10, %xmm11 + pclmulqdq $16, %xmm0, %xmm11 + aesenc 144(%r15), %xmm8 + pshufd $0x4e, %xmm10, %xmm6 + pxor %xmm11, %xmm6 + pxor %xmm3, %xmm6 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_aesenc_gfmul_last + aesenc %xmm9, %xmm8 + aesenc 176(%r15), %xmm8 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_aesenc_gfmul_last + aesenc %xmm9, %xmm8 + aesenc 208(%r15), %xmm8 + movdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_aesenc_gfmul_last: + aesenclast %xmm9, %xmm8 + movdqu (%rcx), %xmm9 + pxor %xmm9, %xmm8 + movdqu %xmm8, (%rdx) + addl $16, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_decrypt_last_block_start +L_AES_GCM_decrypt_last_block_done: + movl %r9d, %ecx + movl %ecx, %edx + andl $15, %ecx + jz L_AES_GCM_decrypt_aesenc_last15_dec_avx_done + movdqa 128(%rsp), %xmm4 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm4 + pxor (%r15), %xmm4 + aesenc 16(%r15), %xmm4 + aesenc 32(%r15), %xmm4 + aesenc 48(%r15), %xmm4 + aesenc 64(%r15), %xmm4 + aesenc 80(%r15), %xmm4 + aesenc 96(%r15), %xmm4 + aesenc 112(%r15), %xmm4 + aesenc 128(%r15), %xmm4 + aesenc 144(%r15), %xmm4 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_aesenc_last15_dec_avx_aesenc_avx_last + aesenc %xmm9, %xmm4 + aesenc 176(%r15), %xmm4 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_aesenc_last15_dec_avx_aesenc_avx_last + aesenc %xmm9, %xmm4 + aesenc 208(%r15), %xmm4 + movdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_aesenc_last15_dec_avx_aesenc_avx_last: + aesenclast %xmm9, %xmm4 + subq $32, %rsp + xorl %ecx, %ecx + movdqa %xmm4, (%rsp) + pxor %xmm0, %xmm0 + movdqa %xmm0, 16(%rsp) +L_AES_GCM_decrypt_aesenc_last15_dec_avx_loop: + movzbl (%rdi,%rbx,1), %r13d + movb %r13b, 16(%rsp,%rcx,1) + xorb (%rsp,%rcx,1), %r13b + movb %r13b, (%rsi,%rbx,1) + incl %ebx + incl %ecx + cmpl %edx, %ebx + jl L_AES_GCM_decrypt_aesenc_last15_dec_avx_loop + movdqa 16(%rsp), %xmm4 + addq $32, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm4 + pxor %xmm4, %xmm6 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm6, %xmm10 + movdqa %xmm6, %xmm11 + movdqa %xmm6, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm6, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm6 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm6 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm6 +L_AES_GCM_decrypt_aesenc_last15_dec_avx_done: +L_AES_GCM_decrypt_done_dec: + movl %r9d, %edx + movl %r11d, %ecx + shlq $3, %rdx + shlq $3, %rcx + pinsrq $0x00, %rdx, %xmm0 + pinsrq $0x01, %rcx, %xmm0 + pxor %xmm0, %xmm6 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm6, %xmm10 + movdqa %xmm6, %xmm11 + movdqa %xmm6, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm6, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm6 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm6 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm6 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm6 + movdqa 144(%rsp), %xmm0 + pxor %xmm6, %xmm0 + cmpl $16, %r14d + je L_AES_GCM_decrypt_cmp_tag_16 + subq $16, %rsp + xorq %rcx, %rcx + xorq %rbx, %rbx + movdqa %xmm0, (%rsp) +L_AES_GCM_decrypt_cmp_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + xorb (%r8,%rcx,1), %r13b + orb %r13b, %bl + incl %ecx + cmpl %r14d, %ecx + jne L_AES_GCM_decrypt_cmp_tag_loop + cmpb $0x00, %bl + sete %bl + addq $16, %rsp + xorq %rcx, %rcx + jmp L_AES_GCM_decrypt_cmp_tag_done +L_AES_GCM_decrypt_cmp_tag_16: + movdqu (%r8), %xmm1 + pcmpeqb %xmm1, %xmm0 + pmovmskb %xmm0, %rdx + # %%edx == 0xFFFF then return 1 else => return 0 + xorl %ebx, %ebx + cmpl $0xffff, %edx + sete %bl +L_AES_GCM_decrypt_cmp_tag_done: + movl %ebx, (%rbp) + addq $0xa8, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %rbx + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_decrypt,.-AES_GCM_decrypt +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_one: +.quad 0x0, 0x1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_two: +.quad 0x0, 0x2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_three: +.quad 0x0, 0x3 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_four: +.quad 0x0, 0x4 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_five: +.quad 0x0, 0x5 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_six: +.quad 0x0, 0x6 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_seven: +.quad 0x0, 0x7 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_eight: +.quad 0x0, 0x8 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_bswap_epi64: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_bswap_mask: +.quad 0x8090a0b0c0d0e0f, 0x1020304050607 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_mod2_128: +.quad 0x1, 0xc200000000000000 +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_avx1 +.type AES_GCM_encrypt_avx1,@function +.align 4 +AES_GCM_encrypt_avx1: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_avx1 +.p2align 2 +_AES_GCM_encrypt_avx1: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %rbx + pushq %r14 + pushq %r15 + movq %rdx, %r12 + movq %rcx, %rax + movl 48(%rsp), %r11d + movl 56(%rsp), %ebx + movl 64(%rsp), %r14d + movq 72(%rsp), %r15 + movl 80(%rsp), %r10d + subq $0xa0, %rsp + vpxor %xmm4, %xmm4, %xmm4 + vpxor %xmm6, %xmm6, %xmm6 + movl %ebx, %edx + cmpl $12, %edx + jne L_AES_GCM_encrypt_avx1_iv_not_12 + # # Calculate values when IV is 12 bytes + # Set counter based on IV + movl $0x1000000, %ecx + vpinsrq $0x00, (%rax), %xmm4, %xmm4 + vpinsrd $2, 8(%rax), %xmm4, %xmm4 + vpinsrd $3, %ecx, %xmm4, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + vmovdqa (%r15), %xmm5 + vpxor %xmm5, %xmm4, %xmm1 + vmovdqa 16(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 32(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 48(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 64(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 80(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 96(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 112(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 128(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 144(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm7 + jl L_AES_GCM_encrypt_avx1_calc_iv_12_last + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 176(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm7 + jl L_AES_GCM_encrypt_avx1_calc_iv_12_last + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 208(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 224(%r15), %xmm7 +L_AES_GCM_encrypt_avx1_calc_iv_12_last: + vaesenclast %xmm7, %xmm5, %xmm5 + vaesenclast %xmm7, %xmm1, %xmm1 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + vmovdqa %xmm1, 144(%rsp) + jmp L_AES_GCM_encrypt_avx1_iv_done +L_AES_GCM_encrypt_avx1_iv_not_12: + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + vmovdqa (%r15), %xmm5 + vaesenc 16(%r15), %xmm5, %xmm5 + vaesenc 32(%r15), %xmm5, %xmm5 + vaesenc 48(%r15), %xmm5, %xmm5 + vaesenc 64(%r15), %xmm5, %xmm5 + vaesenc 80(%r15), %xmm5, %xmm5 + vaesenc 96(%r15), %xmm5, %xmm5 + vaesenc 112(%r15), %xmm5, %xmm5 + vaesenc 128(%r15), %xmm5, %xmm5 + vaesenc 144(%r15), %xmm5, %xmm5 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_calc_iv_1_aesenc_avx_last + vaesenc %xmm9, %xmm5, %xmm5 + vaesenc 176(%r15), %xmm5, %xmm5 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_calc_iv_1_aesenc_avx_last + vaesenc %xmm9, %xmm5, %xmm5 + vaesenc 208(%r15), %xmm5, %xmm5 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_avx1_calc_iv_1_aesenc_avx_last: + vaesenclast %xmm9, %xmm5, %xmm5 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_encrypt_avx1_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_encrypt_avx1_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_encrypt_avx1_calc_iv_16_loop: + vmovdqu (%rax,%rcx,1), %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx1_calc_iv_16_loop + movl %ebx, %edx + cmpl %edx, %ecx + je L_AES_GCM_encrypt_avx1_calc_iv_done +L_AES_GCM_encrypt_avx1_calc_iv_lt16: + subq $16, %rsp + vpxor %xmm8, %xmm8, %xmm8 + xorl %ebx, %ebx + vmovdqa %xmm8, (%rsp) +L_AES_GCM_encrypt_avx1_calc_iv_loop: + movzbl (%rax,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx1_calc_iv_loop + vmovdqa (%rsp), %xmm8 + addq $16, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 +L_AES_GCM_encrypt_avx1_calc_iv_done: + # T = Encrypt counter + vpxor %xmm0, %xmm0, %xmm0 + shll $3, %edx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + # Encrypt counter + vmovdqa (%r15), %xmm8 + vpxor %xmm4, %xmm8, %xmm8 + vaesenc 16(%r15), %xmm8, %xmm8 + vaesenc 32(%r15), %xmm8, %xmm8 + vaesenc 48(%r15), %xmm8, %xmm8 + vaesenc 64(%r15), %xmm8, %xmm8 + vaesenc 80(%r15), %xmm8, %xmm8 + vaesenc 96(%r15), %xmm8, %xmm8 + vaesenc 112(%r15), %xmm8, %xmm8 + vaesenc 128(%r15), %xmm8, %xmm8 + vaesenc 144(%r15), %xmm8, %xmm8 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_calc_iv_2_aesenc_avx_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%r15), %xmm8, %xmm8 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_calc_iv_2_aesenc_avx_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%r15), %xmm8, %xmm8 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_avx1_calc_iv_2_aesenc_avx_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqa %xmm8, 144(%rsp) +L_AES_GCM_encrypt_avx1_iv_done: + # Additional authentication data + movl %r11d, %edx + cmpl $0x00, %edx + je L_AES_GCM_encrypt_avx1_calc_aad_done + xorl %ecx, %ecx + cmpl $16, %edx + jl L_AES_GCM_encrypt_avx1_calc_aad_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_encrypt_avx1_calc_aad_16_loop: + vmovdqu (%r12,%rcx,1), %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm6, %xmm6 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm6, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm6, %xmm6 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm6, %xmm6 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx1_calc_aad_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_encrypt_avx1_calc_aad_done +L_AES_GCM_encrypt_avx1_calc_aad_lt16: + subq $16, %rsp + vpxor %xmm8, %xmm8, %xmm8 + xorl %ebx, %ebx + vmovdqa %xmm8, (%rsp) +L_AES_GCM_encrypt_avx1_calc_aad_loop: + movzbl (%r12,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx1_calc_aad_loop + vmovdqa (%rsp), %xmm8 + addq $16, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm6, %xmm6 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm6, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm6, %xmm6 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm6, %xmm6 +L_AES_GCM_encrypt_avx1_calc_aad_done: + # Calculate counter and H + vpsrlq $63, %xmm5, %xmm9 + vpsllq $0x01, %xmm5, %xmm8 + vpslldq $8, %xmm9, %xmm9 + vpor %xmm9, %xmm8, %xmm8 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpand L_avx1_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm4, %xmm4 + vpxor %xmm8, %xmm5, %xmm5 + vmovdqa %xmm4, 128(%rsp) + xorl %ebx, %ebx + cmpl $0x80, %r9d + movl %r9d, %r13d + jl L_AES_GCM_encrypt_avx1_done_128 + andl $0xffffff80, %r13d + vmovdqa %xmm6, %xmm2 + # H ^ 1 + vmovdqa %xmm5, (%rsp) + # H ^ 2 + vpclmulqdq $0x00, %xmm5, %xmm5, %xmm8 + vpclmulqdq $0x11, %xmm5, %xmm5, %xmm0 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm0, %xmm0 + vmovdqa %xmm0, 16(%rsp) + # H ^ 3 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm0, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm0, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm1 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm1, %xmm1 + vmovdqa %xmm1, 32(%rsp) + # H ^ 4 + vpclmulqdq $0x00, %xmm0, %xmm0, %xmm8 + vpclmulqdq $0x11, %xmm0, %xmm0, %xmm3 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm3, %xmm3 + vmovdqa %xmm3, 48(%rsp) + # H ^ 5 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm0, %xmm9 + vpshufd $0x4e, %xmm1, %xmm10 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm11 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm8 + vpxor %xmm0, %xmm9, %xmm9 + vpxor %xmm1, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 64(%rsp) + # H ^ 6 + vpclmulqdq $0x00, %xmm1, %xmm1, %xmm8 + vpclmulqdq $0x11, %xmm1, %xmm1, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 80(%rsp) + # H ^ 7 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm1, %xmm9 + vpshufd $0x4e, %xmm3, %xmm10 + vpclmulqdq $0x11, %xmm1, %xmm3, %xmm11 + vpclmulqdq $0x00, %xmm1, %xmm3, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm3, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 96(%rsp) + # H ^ 8 + vpclmulqdq $0x00, %xmm3, %xmm3, %xmm8 + vpclmulqdq $0x11, %xmm3, %xmm3, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 112(%rsp) + # First 128 bytes of input + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx1_aes_gcm_bswap_epi64(%rip), %xmm1 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx1_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx1_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx1_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx1_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx1_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx1_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm15, %xmm15 + vpaddd L_avx1_aes_gcm_eight(%rip), %xmm0, %xmm0 + vmovdqa (%r15), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + vmovdqa 16(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 32(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 48(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 64(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 80(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 96(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 112(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 128(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 144(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm7 + jl L_AES_GCM_encrypt_avx1_aesenc_128_enc_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm7 + jl L_AES_GCM_encrypt_avx1_aesenc_128_enc_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%r15), %xmm7 +L_AES_GCM_encrypt_avx1_aesenc_128_enc_done: + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vmovdqu (%rdi), %xmm0 + vmovdqu 16(%rdi), %xmm1 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vmovdqu %xmm8, (%rsi) + vmovdqu %xmm9, 16(%rsi) + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu 32(%rdi), %xmm0 + vmovdqu 48(%rdi), %xmm1 + vpxor %xmm0, %xmm10, %xmm10 + vpxor %xmm1, %xmm11, %xmm11 + vmovdqu %xmm10, 32(%rsi) + vmovdqu %xmm11, 48(%rsi) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vmovdqu 64(%rdi), %xmm0 + vmovdqu 80(%rdi), %xmm1 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vmovdqu %xmm12, 64(%rsi) + vmovdqu %xmm13, 80(%rsi) + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 96(%rdi), %xmm0 + vmovdqu 112(%rdi), %xmm1 + vpxor %xmm0, %xmm14, %xmm14 + vpxor %xmm1, %xmm15, %xmm15 + vmovdqu %xmm14, 96(%rsi) + vmovdqu %xmm15, 112(%rsi) + cmpl $0x80, %r13d + movl $0x80, %ebx + jle L_AES_GCM_encrypt_avx1_end_128 + # More 128 bytes of input +L_AES_GCM_encrypt_avx1_ghash_128: + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx1_aes_gcm_bswap_epi64(%rip), %xmm1 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx1_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx1_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx1_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx1_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx1_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx1_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm15, %xmm15 + vpaddd L_avx1_aes_gcm_eight(%rip), %xmm0, %xmm0 + vmovdqa (%r15), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + vmovdqa 112(%rsp), %xmm7 + vmovdqu -128(%rdx), %xmm0 + vaesenc 16(%r15), %xmm8, %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm3 + vaesenc 16(%r15), %xmm9, %xmm9 + vaesenc 16(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm2 + vaesenc 16(%r15), %xmm11, %xmm11 + vaesenc 16(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm1, %xmm1 + vaesenc 16(%r15), %xmm13, %xmm13 + vaesenc 16(%r15), %xmm14, %xmm14 + vaesenc 16(%r15), %xmm15, %xmm15 + vpxor %xmm2, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa 96(%rsp), %xmm7 + vmovdqu -112(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 32(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 32(%r15), %xmm9, %xmm9 + vaesenc 32(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 32(%r15), %xmm11, %xmm11 + vaesenc 32(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 32(%r15), %xmm13, %xmm13 + vaesenc 32(%r15), %xmm14, %xmm14 + vaesenc 32(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 80(%rsp), %xmm7 + vmovdqu -96(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 48(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 48(%r15), %xmm9, %xmm9 + vaesenc 48(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 48(%r15), %xmm11, %xmm11 + vaesenc 48(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 48(%r15), %xmm13, %xmm13 + vaesenc 48(%r15), %xmm14, %xmm14 + vaesenc 48(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 64(%rsp), %xmm7 + vmovdqu -80(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 64(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 64(%r15), %xmm9, %xmm9 + vaesenc 64(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 64(%r15), %xmm11, %xmm11 + vaesenc 64(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 64(%r15), %xmm13, %xmm13 + vaesenc 64(%r15), %xmm14, %xmm14 + vaesenc 64(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 48(%rsp), %xmm7 + vmovdqu -64(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 80(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 80(%r15), %xmm9, %xmm9 + vaesenc 80(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 80(%r15), %xmm11, %xmm11 + vaesenc 80(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 80(%r15), %xmm13, %xmm13 + vaesenc 80(%r15), %xmm14, %xmm14 + vaesenc 80(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 32(%rsp), %xmm7 + vmovdqu -48(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 96(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 96(%r15), %xmm9, %xmm9 + vaesenc 96(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 96(%r15), %xmm11, %xmm11 + vaesenc 96(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 96(%r15), %xmm13, %xmm13 + vaesenc 96(%r15), %xmm14, %xmm14 + vaesenc 96(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 16(%rsp), %xmm7 + vmovdqu -32(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 112(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 112(%r15), %xmm9, %xmm9 + vaesenc 112(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 112(%r15), %xmm11, %xmm11 + vaesenc 112(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 112(%r15), %xmm13, %xmm13 + vaesenc 112(%r15), %xmm14, %xmm14 + vaesenc 112(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa (%rsp), %xmm7 + vmovdqu -16(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 128(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 128(%r15), %xmm9, %xmm9 + vaesenc 128(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 128(%r15), %xmm11, %xmm11 + vaesenc 128(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 128(%r15), %xmm13, %xmm13 + vaesenc 128(%r15), %xmm14, %xmm14 + vaesenc 128(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vpslldq $8, %xmm1, %xmm5 + vpsrldq $8, %xmm1, %xmm1 + vaesenc 144(%r15), %xmm8, %xmm8 + vpxor %xmm5, %xmm2, %xmm2 + vpxor %xmm1, %xmm3, %xmm3 + vaesenc 144(%r15), %xmm9, %xmm9 + vpslld $31, %xmm2, %xmm7 + vpslld $30, %xmm2, %xmm4 + vpslld $25, %xmm2, %xmm5 + vaesenc 144(%r15), %xmm10, %xmm10 + vpxor %xmm4, %xmm7, %xmm7 + vpxor %xmm5, %xmm7, %xmm7 + vaesenc 144(%r15), %xmm11, %xmm11 + vpsrldq $4, %xmm7, %xmm4 + vpslldq $12, %xmm7, %xmm7 + vaesenc 144(%r15), %xmm12, %xmm12 + vpxor %xmm7, %xmm2, %xmm2 + vpsrld $0x01, %xmm2, %xmm5 + vaesenc 144(%r15), %xmm13, %xmm13 + vpsrld $2, %xmm2, %xmm1 + vpsrld $7, %xmm2, %xmm0 + vaesenc 144(%r15), %xmm14, %xmm14 + vpxor %xmm1, %xmm5, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vaesenc 144(%r15), %xmm15, %xmm15 + vpxor %xmm4, %xmm5, %xmm5 + vpxor %xmm5, %xmm2, %xmm2 + vpxor %xmm3, %xmm2, %xmm2 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm7 + jl L_AES_GCM_encrypt_avx1_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm7 + jl L_AES_GCM_encrypt_avx1_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%r15), %xmm7 +L_AES_GCM_encrypt_avx1_aesenc_128_ghash_avx_done: + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vmovdqu %xmm8, (%rdx) + vmovdqu %xmm9, 16(%rdx) + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu 32(%rcx), %xmm0 + vmovdqu 48(%rcx), %xmm1 + vpxor %xmm0, %xmm10, %xmm10 + vpxor %xmm1, %xmm11, %xmm11 + vmovdqu %xmm10, 32(%rdx) + vmovdqu %xmm11, 48(%rdx) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vmovdqu 64(%rcx), %xmm0 + vmovdqu 80(%rcx), %xmm1 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vmovdqu %xmm12, 64(%rdx) + vmovdqu %xmm13, 80(%rdx) + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 96(%rcx), %xmm0 + vmovdqu 112(%rcx), %xmm1 + vpxor %xmm0, %xmm14, %xmm14 + vpxor %xmm1, %xmm15, %xmm15 + vmovdqu %xmm14, 96(%rdx) + vmovdqu %xmm15, 112(%rdx) + addl $0x80, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_encrypt_avx1_ghash_128 +L_AES_GCM_encrypt_avx1_end_128: + vmovdqa L_avx1_aes_gcm_bswap_mask(%rip), %xmm4 + vpshufb %xmm4, %xmm8, %xmm8 + vpshufb %xmm4, %xmm9, %xmm9 + vpshufb %xmm4, %xmm10, %xmm10 + vpshufb %xmm4, %xmm11, %xmm11 + vpxor %xmm2, %xmm8, %xmm8 + vpshufb %xmm4, %xmm12, %xmm12 + vpshufb %xmm4, %xmm13, %xmm13 + vpshufb %xmm4, %xmm14, %xmm14 + vpshufb %xmm4, %xmm15, %xmm15 + vmovdqa (%rsp), %xmm7 + vmovdqa 16(%rsp), %xmm5 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm15, %xmm1 + vpshufd $0x4e, %xmm7, %xmm2 + vpclmulqdq $0x11, %xmm15, %xmm7, %xmm3 + vpclmulqdq $0x00, %xmm15, %xmm7, %xmm0 + vpxor %xmm15, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm4 + vmovdqa %xmm3, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm14, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm14, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm14, %xmm5, %xmm0 + vpxor %xmm14, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + vmovdqa 32(%rsp), %xmm7 + vmovdqa 48(%rsp), %xmm5 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm13, %xmm1 + vpshufd $0x4e, %xmm7, %xmm2 + vpclmulqdq $0x11, %xmm13, %xmm7, %xmm3 + vpclmulqdq $0x00, %xmm13, %xmm7, %xmm0 + vpxor %xmm13, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm12, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm12, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm12, %xmm5, %xmm0 + vpxor %xmm12, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + vmovdqa 64(%rsp), %xmm7 + vmovdqa 80(%rsp), %xmm5 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm11, %xmm1 + vpshufd $0x4e, %xmm7, %xmm2 + vpclmulqdq $0x11, %xmm11, %xmm7, %xmm3 + vpclmulqdq $0x00, %xmm11, %xmm7, %xmm0 + vpxor %xmm11, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm10, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm10, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm10, %xmm5, %xmm0 + vpxor %xmm10, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + vmovdqa 96(%rsp), %xmm7 + vmovdqa 112(%rsp), %xmm5 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm9, %xmm1 + vpshufd $0x4e, %xmm7, %xmm2 + vpclmulqdq $0x11, %xmm9, %xmm7, %xmm3 + vpclmulqdq $0x00, %xmm9, %xmm7, %xmm0 + vpxor %xmm9, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm8, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm8, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm8, %xmm5, %xmm0 + vpxor %xmm8, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + vpslld $31, %xmm4, %xmm0 + vpslld $30, %xmm4, %xmm1 + vpslld $25, %xmm4, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + vpsrld $0x01, %xmm4, %xmm2 + vpsrld $2, %xmm4, %xmm3 + vpsrld $7, %xmm4, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm4, %xmm2, %xmm2 + vpxor %xmm2, %xmm6, %xmm6 + vmovdqa (%rsp), %xmm5 +L_AES_GCM_encrypt_avx1_done_128: + movl %r9d, %edx + cmpl %edx, %ebx + jge L_AES_GCM_encrypt_avx1_done_enc + movl %r9d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %ebx + jge L_AES_GCM_encrypt_avx1_last_block_done + vmovdqa 128(%rsp), %xmm9 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm9, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm9, %xmm9 + vmovdqa %xmm9, 128(%rsp) + vpxor (%r15), %xmm8, %xmm8 + vaesenc 16(%r15), %xmm8, %xmm8 + vaesenc 32(%r15), %xmm8, %xmm8 + vaesenc 48(%r15), %xmm8, %xmm8 + vaesenc 64(%r15), %xmm8, %xmm8 + vaesenc 80(%r15), %xmm8, %xmm8 + vaesenc 96(%r15), %xmm8, %xmm8 + vaesenc 112(%r15), %xmm8, %xmm8 + vaesenc 128(%r15), %xmm8, %xmm8 + vaesenc 144(%r15), %xmm8, %xmm8 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_aesenc_block_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%r15), %xmm8, %xmm8 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_aesenc_block_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%r15), %xmm8, %xmm8 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_avx1_aesenc_block_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqu (%rdi,%rbx,1), %xmm9 + vpxor %xmm9, %xmm8, %xmm8 + vmovdqu %xmm8, (%rsi,%rbx,1) + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm6, %xmm6 + addl $16, %ebx + cmpl %r13d, %ebx + jge L_AES_GCM_encrypt_avx1_last_block_ghash +L_AES_GCM_encrypt_avx1_last_block_start: + vmovdqu (%rdi,%rbx,1), %xmm13 + vmovdqa 128(%rsp), %xmm9 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm9, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm9, %xmm9 + vmovdqa %xmm9, 128(%rsp) + vpxor (%r15), %xmm8, %xmm8 + vpclmulqdq $16, %xmm5, %xmm6, %xmm10 + vaesenc 16(%r15), %xmm8, %xmm8 + vaesenc 32(%r15), %xmm8, %xmm8 + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm11 + vaesenc 48(%r15), %xmm8, %xmm8 + vaesenc 64(%r15), %xmm8, %xmm8 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm12 + vaesenc 80(%r15), %xmm8, %xmm8 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm1 + vaesenc 96(%r15), %xmm8, %xmm8 + vpxor %xmm11, %xmm10, %xmm10 + vpslldq $8, %xmm10, %xmm2 + vpsrldq $8, %xmm10, %xmm10 + vaesenc 112(%r15), %xmm8, %xmm8 + vpxor %xmm12, %xmm2, %xmm2 + vpxor %xmm10, %xmm1, %xmm3 + vmovdqa L_avx1_aes_gcm_mod2_128(%rip), %xmm0 + vpclmulqdq $16, %xmm0, %xmm2, %xmm11 + vaesenc 128(%r15), %xmm8, %xmm8 + vpshufd $0x4e, %xmm2, %xmm10 + vpxor %xmm11, %xmm10, %xmm10 + vpclmulqdq $16, %xmm0, %xmm10, %xmm11 + vaesenc 144(%r15), %xmm8, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpxor %xmm11, %xmm10, %xmm10 + vpxor %xmm3, %xmm10, %xmm6 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_aesenc_gfmul_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%r15), %xmm8, %xmm8 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_aesenc_gfmul_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%r15), %xmm8, %xmm8 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_avx1_aesenc_gfmul_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqa %xmm13, %xmm0 + vpxor %xmm0, %xmm8, %xmm8 + vmovdqu %xmm8, (%rsi,%rbx,1) + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + addl $16, %ebx + vpxor %xmm8, %xmm6, %xmm6 + cmpl %r13d, %ebx + jl L_AES_GCM_encrypt_avx1_last_block_start +L_AES_GCM_encrypt_avx1_last_block_ghash: + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm6, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm6, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm6 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm6, %xmm6 +L_AES_GCM_encrypt_avx1_last_block_done: + movl %r9d, %ecx + movl %ecx, %edx + andl $15, %ecx + jz L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_done + vmovdqa 128(%rsp), %xmm4 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpxor (%r15), %xmm4, %xmm4 + vaesenc 16(%r15), %xmm4, %xmm4 + vaesenc 32(%r15), %xmm4, %xmm4 + vaesenc 48(%r15), %xmm4, %xmm4 + vaesenc 64(%r15), %xmm4, %xmm4 + vaesenc 80(%r15), %xmm4, %xmm4 + vaesenc 96(%r15), %xmm4, %xmm4 + vaesenc 112(%r15), %xmm4, %xmm4 + vaesenc 128(%r15), %xmm4, %xmm4 + vaesenc 144(%r15), %xmm4, %xmm4 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_aesenc_avx_last + vaesenc %xmm9, %xmm4, %xmm4 + vaesenc 176(%r15), %xmm4, %xmm4 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_aesenc_avx_last + vaesenc %xmm9, %xmm4, %xmm4 + vaesenc 208(%r15), %xmm4, %xmm4 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_aesenc_avx_last: + vaesenclast %xmm9, %xmm4, %xmm4 + subq $16, %rsp + xorl %ecx, %ecx + vmovdqa %xmm4, (%rsp) +L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_loop: + movzbl (%rdi,%rbx,1), %r13d + xorb (%rsp,%rcx,1), %r13b + movb %r13b, (%rsi,%rbx,1) + movb %r13b, (%rsp,%rcx,1) + incl %ebx + incl %ecx + cmpl %edx, %ebx + jl L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_loop + xorq %r13, %r13 + cmpl $16, %ecx + je L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_finish_enc +L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_byte_loop: + movb %r13b, (%rsp,%rcx,1) + incl %ecx + cmpl $16, %ecx + jl L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_byte_loop +L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_finish_enc: + vmovdqa (%rsp), %xmm4 + addq $16, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + vpxor %xmm4, %xmm6, %xmm6 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm6, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm6, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm6 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm6, %xmm6 +L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_done: +L_AES_GCM_encrypt_avx1_done_enc: + movl %r9d, %edx + movl %r11d, %ecx + shlq $3, %rdx + shlq $3, %rcx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpinsrq $0x01, %rcx, %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm6, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm6, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm6 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm6, %xmm6 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm6, %xmm6 + vpxor 144(%rsp), %xmm6, %xmm0 + cmpl $16, %r14d + je L_AES_GCM_encrypt_avx1_store_tag_16 + xorq %rcx, %rcx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_encrypt_avx1_store_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + movb %r13b, (%r8,%rcx,1) + incl %ecx + cmpl %r14d, %ecx + jne L_AES_GCM_encrypt_avx1_store_tag_loop + jmp L_AES_GCM_encrypt_avx1_store_tag_done +L_AES_GCM_encrypt_avx1_store_tag_16: + vmovdqu %xmm0, (%r8) +L_AES_GCM_encrypt_avx1_store_tag_done: + vzeroupper + addq $0xa0, %rsp + popq %r15 + popq %r14 + popq %rbx + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_avx1,.-AES_GCM_encrypt_avx1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_decrypt_avx1 +.type AES_GCM_decrypt_avx1,@function +.align 4 +AES_GCM_decrypt_avx1: +#else +.section __TEXT,__text +.globl _AES_GCM_decrypt_avx1 +.p2align 2 +_AES_GCM_decrypt_avx1: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %rbx + pushq %r14 + pushq %r15 + pushq %rbp + movq %rdx, %r12 + movq %rcx, %rax + movl 56(%rsp), %r11d + movl 64(%rsp), %ebx + movl 72(%rsp), %r14d + movq 80(%rsp), %r15 + movl 88(%rsp), %r10d + movq 96(%rsp), %rbp + subq $0xa8, %rsp + vpxor %xmm4, %xmm4, %xmm4 + vpxor %xmm6, %xmm6, %xmm6 + cmpl $12, %ebx + movl %ebx, %edx + jne L_AES_GCM_decrypt_avx1_iv_not_12 + # # Calculate values when IV is 12 bytes + # Set counter based on IV + movl $0x1000000, %ecx + vpinsrq $0x00, (%rax), %xmm4, %xmm4 + vpinsrd $2, 8(%rax), %xmm4, %xmm4 + vpinsrd $3, %ecx, %xmm4, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + vmovdqa (%r15), %xmm5 + vpxor %xmm5, %xmm4, %xmm1 + vmovdqa 16(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 32(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 48(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 64(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 80(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 96(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 112(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 128(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 144(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm7 + jl L_AES_GCM_decrypt_avx1_calc_iv_12_last + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 176(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm7 + jl L_AES_GCM_decrypt_avx1_calc_iv_12_last + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 208(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 224(%r15), %xmm7 +L_AES_GCM_decrypt_avx1_calc_iv_12_last: + vaesenclast %xmm7, %xmm5, %xmm5 + vaesenclast %xmm7, %xmm1, %xmm1 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + vmovdqa %xmm1, 144(%rsp) + jmp L_AES_GCM_decrypt_avx1_iv_done +L_AES_GCM_decrypt_avx1_iv_not_12: + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + vmovdqa (%r15), %xmm5 + vaesenc 16(%r15), %xmm5, %xmm5 + vaesenc 32(%r15), %xmm5, %xmm5 + vaesenc 48(%r15), %xmm5, %xmm5 + vaesenc 64(%r15), %xmm5, %xmm5 + vaesenc 80(%r15), %xmm5, %xmm5 + vaesenc 96(%r15), %xmm5, %xmm5 + vaesenc 112(%r15), %xmm5, %xmm5 + vaesenc 128(%r15), %xmm5, %xmm5 + vaesenc 144(%r15), %xmm5, %xmm5 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_calc_iv_1_aesenc_avx_last + vaesenc %xmm9, %xmm5, %xmm5 + vaesenc 176(%r15), %xmm5, %xmm5 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_calc_iv_1_aesenc_avx_last + vaesenc %xmm9, %xmm5, %xmm5 + vaesenc 208(%r15), %xmm5, %xmm5 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_avx1_calc_iv_1_aesenc_avx_last: + vaesenclast %xmm9, %xmm5, %xmm5 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_decrypt_avx1_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_decrypt_avx1_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_decrypt_avx1_calc_iv_16_loop: + vmovdqu (%rax,%rcx,1), %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx1_calc_iv_16_loop + movl %ebx, %edx + cmpl %edx, %ecx + je L_AES_GCM_decrypt_avx1_calc_iv_done +L_AES_GCM_decrypt_avx1_calc_iv_lt16: + subq $16, %rsp + vpxor %xmm8, %xmm8, %xmm8 + xorl %ebx, %ebx + vmovdqa %xmm8, (%rsp) +L_AES_GCM_decrypt_avx1_calc_iv_loop: + movzbl (%rax,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx1_calc_iv_loop + vmovdqa (%rsp), %xmm8 + addq $16, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 +L_AES_GCM_decrypt_avx1_calc_iv_done: + # T = Encrypt counter + vpxor %xmm0, %xmm0, %xmm0 + shll $3, %edx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + # Encrypt counter + vmovdqa (%r15), %xmm8 + vpxor %xmm4, %xmm8, %xmm8 + vaesenc 16(%r15), %xmm8, %xmm8 + vaesenc 32(%r15), %xmm8, %xmm8 + vaesenc 48(%r15), %xmm8, %xmm8 + vaesenc 64(%r15), %xmm8, %xmm8 + vaesenc 80(%r15), %xmm8, %xmm8 + vaesenc 96(%r15), %xmm8, %xmm8 + vaesenc 112(%r15), %xmm8, %xmm8 + vaesenc 128(%r15), %xmm8, %xmm8 + vaesenc 144(%r15), %xmm8, %xmm8 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_calc_iv_2_aesenc_avx_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%r15), %xmm8, %xmm8 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_calc_iv_2_aesenc_avx_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%r15), %xmm8, %xmm8 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_avx1_calc_iv_2_aesenc_avx_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqa %xmm8, 144(%rsp) +L_AES_GCM_decrypt_avx1_iv_done: + # Additional authentication data + movl %r11d, %edx + cmpl $0x00, %edx + je L_AES_GCM_decrypt_avx1_calc_aad_done + xorl %ecx, %ecx + cmpl $16, %edx + jl L_AES_GCM_decrypt_avx1_calc_aad_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_decrypt_avx1_calc_aad_16_loop: + vmovdqu (%r12,%rcx,1), %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm6, %xmm6 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm6, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm6, %xmm6 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm6, %xmm6 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx1_calc_aad_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_decrypt_avx1_calc_aad_done +L_AES_GCM_decrypt_avx1_calc_aad_lt16: + subq $16, %rsp + vpxor %xmm8, %xmm8, %xmm8 + xorl %ebx, %ebx + vmovdqa %xmm8, (%rsp) +L_AES_GCM_decrypt_avx1_calc_aad_loop: + movzbl (%r12,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx1_calc_aad_loop + vmovdqa (%rsp), %xmm8 + addq $16, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm6, %xmm6 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm6, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm6, %xmm6 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm6, %xmm6 +L_AES_GCM_decrypt_avx1_calc_aad_done: + # Calculate counter and H + vpsrlq $63, %xmm5, %xmm9 + vpsllq $0x01, %xmm5, %xmm8 + vpslldq $8, %xmm9, %xmm9 + vpor %xmm9, %xmm8, %xmm8 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpand L_avx1_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm4, %xmm4 + vpxor %xmm8, %xmm5, %xmm5 + vmovdqa %xmm4, 128(%rsp) + xorl %ebx, %ebx + cmpl $0x80, %r9d + movl %r9d, %r13d + jl L_AES_GCM_decrypt_avx1_done_128 + andl $0xffffff80, %r13d + vmovdqa %xmm6, %xmm2 + # H ^ 1 + vmovdqa %xmm5, (%rsp) + # H ^ 2 + vpclmulqdq $0x00, %xmm5, %xmm5, %xmm8 + vpclmulqdq $0x11, %xmm5, %xmm5, %xmm0 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm0, %xmm0 + vmovdqa %xmm0, 16(%rsp) + # H ^ 3 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm0, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm0, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm1 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm1, %xmm1 + vmovdqa %xmm1, 32(%rsp) + # H ^ 4 + vpclmulqdq $0x00, %xmm0, %xmm0, %xmm8 + vpclmulqdq $0x11, %xmm0, %xmm0, %xmm3 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm3, %xmm3 + vmovdqa %xmm3, 48(%rsp) + # H ^ 5 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm0, %xmm9 + vpshufd $0x4e, %xmm1, %xmm10 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm11 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm8 + vpxor %xmm0, %xmm9, %xmm9 + vpxor %xmm1, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 64(%rsp) + # H ^ 6 + vpclmulqdq $0x00, %xmm1, %xmm1, %xmm8 + vpclmulqdq $0x11, %xmm1, %xmm1, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 80(%rsp) + # H ^ 7 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm1, %xmm9 + vpshufd $0x4e, %xmm3, %xmm10 + vpclmulqdq $0x11, %xmm1, %xmm3, %xmm11 + vpclmulqdq $0x00, %xmm1, %xmm3, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm3, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 96(%rsp) + # H ^ 8 + vpclmulqdq $0x00, %xmm3, %xmm3, %xmm8 + vpclmulqdq $0x11, %xmm3, %xmm3, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 112(%rsp) +L_AES_GCM_decrypt_avx1_ghash_128: + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx1_aes_gcm_bswap_epi64(%rip), %xmm1 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx1_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx1_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx1_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx1_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx1_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx1_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm15, %xmm15 + vpaddd L_avx1_aes_gcm_eight(%rip), %xmm0, %xmm0 + vmovdqa (%r15), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + vmovdqa 112(%rsp), %xmm7 + vmovdqu (%rcx), %xmm0 + vaesenc 16(%r15), %xmm8, %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm3 + vaesenc 16(%r15), %xmm9, %xmm9 + vaesenc 16(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm2 + vaesenc 16(%r15), %xmm11, %xmm11 + vaesenc 16(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm1, %xmm1 + vaesenc 16(%r15), %xmm13, %xmm13 + vaesenc 16(%r15), %xmm14, %xmm14 + vaesenc 16(%r15), %xmm15, %xmm15 + vpxor %xmm2, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa 96(%rsp), %xmm7 + vmovdqu 16(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 32(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 32(%r15), %xmm9, %xmm9 + vaesenc 32(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 32(%r15), %xmm11, %xmm11 + vaesenc 32(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 32(%r15), %xmm13, %xmm13 + vaesenc 32(%r15), %xmm14, %xmm14 + vaesenc 32(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 80(%rsp), %xmm7 + vmovdqu 32(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 48(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 48(%r15), %xmm9, %xmm9 + vaesenc 48(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 48(%r15), %xmm11, %xmm11 + vaesenc 48(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 48(%r15), %xmm13, %xmm13 + vaesenc 48(%r15), %xmm14, %xmm14 + vaesenc 48(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 64(%rsp), %xmm7 + vmovdqu 48(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 64(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 64(%r15), %xmm9, %xmm9 + vaesenc 64(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 64(%r15), %xmm11, %xmm11 + vaesenc 64(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 64(%r15), %xmm13, %xmm13 + vaesenc 64(%r15), %xmm14, %xmm14 + vaesenc 64(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 48(%rsp), %xmm7 + vmovdqu 64(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 80(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 80(%r15), %xmm9, %xmm9 + vaesenc 80(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 80(%r15), %xmm11, %xmm11 + vaesenc 80(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 80(%r15), %xmm13, %xmm13 + vaesenc 80(%r15), %xmm14, %xmm14 + vaesenc 80(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 32(%rsp), %xmm7 + vmovdqu 80(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 96(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 96(%r15), %xmm9, %xmm9 + vaesenc 96(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 96(%r15), %xmm11, %xmm11 + vaesenc 96(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 96(%r15), %xmm13, %xmm13 + vaesenc 96(%r15), %xmm14, %xmm14 + vaesenc 96(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 16(%rsp), %xmm7 + vmovdqu 96(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 112(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 112(%r15), %xmm9, %xmm9 + vaesenc 112(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 112(%r15), %xmm11, %xmm11 + vaesenc 112(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 112(%r15), %xmm13, %xmm13 + vaesenc 112(%r15), %xmm14, %xmm14 + vaesenc 112(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa (%rsp), %xmm7 + vmovdqu 112(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 128(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 128(%r15), %xmm9, %xmm9 + vaesenc 128(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 128(%r15), %xmm11, %xmm11 + vaesenc 128(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 128(%r15), %xmm13, %xmm13 + vaesenc 128(%r15), %xmm14, %xmm14 + vaesenc 128(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vpslldq $8, %xmm1, %xmm5 + vpsrldq $8, %xmm1, %xmm1 + vaesenc 144(%r15), %xmm8, %xmm8 + vpxor %xmm5, %xmm2, %xmm2 + vpxor %xmm1, %xmm3, %xmm3 + vaesenc 144(%r15), %xmm9, %xmm9 + vpslld $31, %xmm2, %xmm7 + vpslld $30, %xmm2, %xmm4 + vpslld $25, %xmm2, %xmm5 + vaesenc 144(%r15), %xmm10, %xmm10 + vpxor %xmm4, %xmm7, %xmm7 + vpxor %xmm5, %xmm7, %xmm7 + vaesenc 144(%r15), %xmm11, %xmm11 + vpsrldq $4, %xmm7, %xmm4 + vpslldq $12, %xmm7, %xmm7 + vaesenc 144(%r15), %xmm12, %xmm12 + vpxor %xmm7, %xmm2, %xmm2 + vpsrld $0x01, %xmm2, %xmm5 + vaesenc 144(%r15), %xmm13, %xmm13 + vpsrld $2, %xmm2, %xmm1 + vpsrld $7, %xmm2, %xmm0 + vaesenc 144(%r15), %xmm14, %xmm14 + vpxor %xmm1, %xmm5, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vaesenc 144(%r15), %xmm15, %xmm15 + vpxor %xmm4, %xmm5, %xmm5 + vpxor %xmm5, %xmm2, %xmm2 + vpxor %xmm3, %xmm2, %xmm2 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm7 + jl L_AES_GCM_decrypt_avx1_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm7 + jl L_AES_GCM_decrypt_avx1_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%r15), %xmm7 +L_AES_GCM_decrypt_avx1_aesenc_128_ghash_avx_done: + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vmovdqu %xmm8, (%rdx) + vmovdqu %xmm9, 16(%rdx) + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu 32(%rcx), %xmm0 + vmovdqu 48(%rcx), %xmm1 + vpxor %xmm0, %xmm10, %xmm10 + vpxor %xmm1, %xmm11, %xmm11 + vmovdqu %xmm10, 32(%rdx) + vmovdqu %xmm11, 48(%rdx) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vmovdqu 64(%rcx), %xmm0 + vmovdqu 80(%rcx), %xmm1 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vmovdqu %xmm12, 64(%rdx) + vmovdqu %xmm13, 80(%rdx) + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 96(%rcx), %xmm0 + vmovdqu 112(%rcx), %xmm1 + vpxor %xmm0, %xmm14, %xmm14 + vpxor %xmm1, %xmm15, %xmm15 + vmovdqu %xmm14, 96(%rdx) + vmovdqu %xmm15, 112(%rdx) + addl $0x80, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_decrypt_avx1_ghash_128 + vmovdqa %xmm2, %xmm6 + vmovdqa (%rsp), %xmm5 +L_AES_GCM_decrypt_avx1_done_128: + movl %r9d, %edx + cmpl %edx, %ebx + jge L_AES_GCM_decrypt_avx1_done_dec + movl %r9d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %ebx + jge L_AES_GCM_decrypt_avx1_last_block_done +L_AES_GCM_decrypt_avx1_last_block_start: + vmovdqu (%rdi,%rbx,1), %xmm13 + vmovdqa %xmm5, %xmm0 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm13, %xmm1 + vpxor %xmm6, %xmm1, %xmm1 + vmovdqa 128(%rsp), %xmm9 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm9, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm9, %xmm9 + vmovdqa %xmm9, 128(%rsp) + vpxor (%r15), %xmm8, %xmm8 + vpclmulqdq $16, %xmm0, %xmm1, %xmm10 + vaesenc 16(%r15), %xmm8, %xmm8 + vaesenc 32(%r15), %xmm8, %xmm8 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm11 + vaesenc 48(%r15), %xmm8, %xmm8 + vaesenc 64(%r15), %xmm8, %xmm8 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm12 + vaesenc 80(%r15), %xmm8, %xmm8 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vaesenc 96(%r15), %xmm8, %xmm8 + vpxor %xmm11, %xmm10, %xmm10 + vpslldq $8, %xmm10, %xmm2 + vpsrldq $8, %xmm10, %xmm10 + vaesenc 112(%r15), %xmm8, %xmm8 + vpxor %xmm12, %xmm2, %xmm2 + vpxor %xmm10, %xmm1, %xmm3 + vmovdqa L_avx1_aes_gcm_mod2_128(%rip), %xmm0 + vpclmulqdq $16, %xmm0, %xmm2, %xmm11 + vaesenc 128(%r15), %xmm8, %xmm8 + vpshufd $0x4e, %xmm2, %xmm10 + vpxor %xmm11, %xmm10, %xmm10 + vpclmulqdq $16, %xmm0, %xmm10, %xmm11 + vaesenc 144(%r15), %xmm8, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpxor %xmm11, %xmm10, %xmm10 + vpxor %xmm3, %xmm10, %xmm6 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_aesenc_gfmul_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%r15), %xmm8, %xmm8 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_aesenc_gfmul_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%r15), %xmm8, %xmm8 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_avx1_aesenc_gfmul_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqa %xmm13, %xmm0 + vpxor %xmm0, %xmm8, %xmm8 + vmovdqu %xmm8, (%rsi,%rbx,1) + addl $16, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_decrypt_avx1_last_block_start +L_AES_GCM_decrypt_avx1_last_block_done: + movl %r9d, %ecx + movl %ecx, %edx + andl $15, %ecx + jz L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_done + vmovdqa 128(%rsp), %xmm4 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpxor (%r15), %xmm4, %xmm4 + vaesenc 16(%r15), %xmm4, %xmm4 + vaesenc 32(%r15), %xmm4, %xmm4 + vaesenc 48(%r15), %xmm4, %xmm4 + vaesenc 64(%r15), %xmm4, %xmm4 + vaesenc 80(%r15), %xmm4, %xmm4 + vaesenc 96(%r15), %xmm4, %xmm4 + vaesenc 112(%r15), %xmm4, %xmm4 + vaesenc 128(%r15), %xmm4, %xmm4 + vaesenc 144(%r15), %xmm4, %xmm4 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_aesenc_avx_last + vaesenc %xmm9, %xmm4, %xmm4 + vaesenc 176(%r15), %xmm4, %xmm4 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_aesenc_avx_last + vaesenc %xmm9, %xmm4, %xmm4 + vaesenc 208(%r15), %xmm4, %xmm4 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_aesenc_avx_last: + vaesenclast %xmm9, %xmm4, %xmm4 + subq $32, %rsp + xorl %ecx, %ecx + vmovdqa %xmm4, (%rsp) + vpxor %xmm0, %xmm0, %xmm0 + vmovdqa %xmm0, 16(%rsp) +L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_loop: + movzbl (%rdi,%rbx,1), %r13d + movb %r13b, 16(%rsp,%rcx,1) + xorb (%rsp,%rcx,1), %r13b + movb %r13b, (%rsi,%rbx,1) + incl %ebx + incl %ecx + cmpl %edx, %ebx + jl L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_loop + vmovdqa 16(%rsp), %xmm4 + addq $32, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + vpxor %xmm4, %xmm6, %xmm6 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm6, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm6, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm6 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm6, %xmm6 +L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_done: +L_AES_GCM_decrypt_avx1_done_dec: + movl %r9d, %edx + movl %r11d, %ecx + shlq $3, %rdx + shlq $3, %rcx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpinsrq $0x01, %rcx, %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm6, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm6, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm6 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm6, %xmm6 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm6, %xmm6 + vpxor 144(%rsp), %xmm6, %xmm0 + cmpl $16, %r14d + je L_AES_GCM_decrypt_avx1_cmp_tag_16 + subq $16, %rsp + xorq %rcx, %rcx + xorq %rbx, %rbx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_decrypt_avx1_cmp_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + xorb (%r8,%rcx,1), %r13b + orb %r13b, %bl + incl %ecx + cmpl %r14d, %ecx + jne L_AES_GCM_decrypt_avx1_cmp_tag_loop + cmpb $0x00, %bl + sete %bl + addq $16, %rsp + xorq %rcx, %rcx + jmp L_AES_GCM_decrypt_avx1_cmp_tag_done +L_AES_GCM_decrypt_avx1_cmp_tag_16: + vmovdqu (%r8), %xmm1 + vpcmpeqb %xmm1, %xmm0, %xmm0 + vpmovmskb %xmm0, %rdx + # %%edx == 0xFFFF then return 1 else => return 0 + xorl %ebx, %ebx + cmpl $0xffff, %edx + sete %bl +L_AES_GCM_decrypt_avx1_cmp_tag_done: + movl %ebx, (%rbp) + vzeroupper + addq $0xa8, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %rbx + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_decrypt_avx1,.-AES_GCM_decrypt_avx1 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX1 */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_one: +.quad 0x0, 0x1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_two: +.quad 0x0, 0x2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_three: +.quad 0x0, 0x3 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_four: +.quad 0x0, 0x4 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_five: +.quad 0x0, 0x5 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_six: +.quad 0x0, 0x6 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_seven: +.quad 0x0, 0x7 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_eight: +.quad 0x0, 0x8 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_bswap_one: +.quad 0x0, 0x100000000000000 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_bswap_epi64: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_bswap_mask: +.quad 0x8090a0b0c0d0e0f, 0x1020304050607 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_mod2_128: +.quad 0x1, 0xc200000000000000 +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_avx2 +.type AES_GCM_encrypt_avx2,@function +.align 4 +AES_GCM_encrypt_avx2: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_avx2 +.p2align 2 +_AES_GCM_encrypt_avx2: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %r15 + pushq %rbx + pushq %r14 + movq %rdx, %r12 + movq %rcx, %rax + movq %r8, %r15 + movq %rsi, %r8 + movl %r9d, %r10d + movl 48(%rsp), %r11d + movl 56(%rsp), %ebx + movl 64(%rsp), %r14d + movq 72(%rsp), %rsi + movl 80(%rsp), %r9d + subq $0xa0, %rsp + vpxor %xmm4, %xmm4, %xmm4 + vpxor %xmm6, %xmm6, %xmm6 + movl %ebx, %edx + cmpl $12, %edx + je L_AES_GCM_encrypt_avx2_iv_12 + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + vmovdqa (%rsi), %xmm5 + vaesenc 16(%rsi), %xmm5, %xmm5 + vaesenc 32(%rsi), %xmm5, %xmm5 + vaesenc 48(%rsi), %xmm5, %xmm5 + vaesenc 64(%rsi), %xmm5, %xmm5 + vaesenc 80(%rsi), %xmm5, %xmm5 + vaesenc 96(%rsi), %xmm5, %xmm5 + vaesenc 112(%rsi), %xmm5, %xmm5 + vaesenc 128(%rsi), %xmm5, %xmm5 + vaesenc 144(%rsi), %xmm5, %xmm5 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_calc_iv_1_aesenc_avx_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc 176(%rsi), %xmm5, %xmm5 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_calc_iv_1_aesenc_avx_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc 208(%rsi), %xmm5, %xmm5 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_encrypt_avx2_calc_iv_1_aesenc_avx_last: + vaesenclast %xmm0, %xmm5, %xmm5 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_encrypt_avx2_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_encrypt_avx2_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_encrypt_avx2_calc_iv_16_loop: + vmovdqu (%rax,%rcx,1), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx2_calc_iv_16_loop + movl %ebx, %edx + cmpl %edx, %ecx + je L_AES_GCM_encrypt_avx2_calc_iv_done +L_AES_GCM_encrypt_avx2_calc_iv_lt16: + vpxor %xmm0, %xmm0, %xmm0 + xorl %ebx, %ebx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_encrypt_avx2_calc_iv_loop: + movzbl (%rax,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx2_calc_iv_loop + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 +L_AES_GCM_encrypt_avx2_calc_iv_done: + # T = Encrypt counter + vpxor %xmm0, %xmm0, %xmm0 + shll $3, %edx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + # Encrypt counter + vmovdqa (%rsi), %xmm15 + vpxor %xmm4, %xmm15, %xmm15 + vaesenc 16(%rsi), %xmm15, %xmm15 + vaesenc 32(%rsi), %xmm15, %xmm15 + vaesenc 48(%rsi), %xmm15, %xmm15 + vaesenc 64(%rsi), %xmm15, %xmm15 + vaesenc 80(%rsi), %xmm15, %xmm15 + vaesenc 96(%rsi), %xmm15, %xmm15 + vaesenc 112(%rsi), %xmm15, %xmm15 + vaesenc 128(%rsi), %xmm15, %xmm15 + vaesenc 144(%rsi), %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_calc_iv_2_aesenc_avx_last + vaesenc %xmm0, %xmm15, %xmm15 + vaesenc 176(%rsi), %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_calc_iv_2_aesenc_avx_last + vaesenc %xmm0, %xmm15, %xmm15 + vaesenc 208(%rsi), %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_encrypt_avx2_calc_iv_2_aesenc_avx_last: + vaesenclast %xmm0, %xmm15, %xmm15 + jmp L_AES_GCM_encrypt_avx2_iv_done +L_AES_GCM_encrypt_avx2_iv_12: + # # Calculate values when IV is 12 bytes + # Set counter based on IV + vmovdqa L_avx2_aes_gcm_bswap_one(%rip), %xmm4 + vmovdqa (%rsi), %xmm5 + vpblendd $7, (%rax), %xmm4, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + vmovdqa 16(%rsi), %xmm7 + vpxor %xmm5, %xmm4, %xmm15 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 32(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 48(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 64(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 80(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 96(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 112(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 128(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 144(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_calc_iv_12_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 176(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_calc_iv_12_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 208(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_encrypt_avx2_calc_iv_12_last: + vaesenclast %xmm0, %xmm5, %xmm5 + vaesenclast %xmm0, %xmm15, %xmm15 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 +L_AES_GCM_encrypt_avx2_iv_done: + # Additional authentication data + movl %r11d, %edx + cmpl $0x00, %edx + je L_AES_GCM_encrypt_avx2_calc_aad_done + xorl %ecx, %ecx + cmpl $16, %edx + jl L_AES_GCM_encrypt_avx2_calc_aad_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_encrypt_avx2_calc_aad_16_loop: + vmovdqu (%r12,%rcx,1), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm6, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm6, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm6 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm6, %xmm6 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx2_calc_aad_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_encrypt_avx2_calc_aad_done +L_AES_GCM_encrypt_avx2_calc_aad_lt16: + vpxor %xmm0, %xmm0, %xmm0 + xorl %ebx, %ebx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_encrypt_avx2_calc_aad_loop: + movzbl (%r12,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx2_calc_aad_loop + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm6, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm6, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm6 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm6, %xmm6 +L_AES_GCM_encrypt_avx2_calc_aad_done: + # Calculate counter and H + vpsrlq $63, %xmm5, %xmm1 + vpsllq $0x01, %xmm5, %xmm0 + vpslldq $8, %xmm1, %xmm1 + vpor %xmm1, %xmm0, %xmm0 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpand L_avx2_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm4, %xmm4 + vpxor %xmm0, %xmm5, %xmm5 + xorl %ebx, %ebx + cmpl $0x80, %r10d + movl %r10d, %r13d + jl L_AES_GCM_encrypt_avx2_done_128 + andl $0xffffff80, %r13d + vmovdqa %xmm4, 128(%rsp) + vmovdqa %xmm15, 144(%rsp) + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm3 + # H ^ 1 and H ^ 2 + vpclmulqdq $0x00, %xmm5, %xmm5, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm5, %xmm10 + vpclmulqdq $16, %xmm3, %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpclmulqdq $16, %xmm3, %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm9, %xmm10, %xmm0 + vmovdqa %xmm5, (%rsp) + vmovdqa %xmm0, 16(%rsp) + # H ^ 3 and H ^ 4 + vpclmulqdq $16, %xmm5, %xmm0, %xmm11 + vpclmulqdq $0x01, %xmm5, %xmm0, %xmm10 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm12 + vpclmulqdq $0x00, %xmm0, %xmm0, %xmm13 + vpclmulqdq $0x11, %xmm0, %xmm0, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm2 + vpxor %xmm9, %xmm10, %xmm1 + vmovdqa %xmm1, 32(%rsp) + vmovdqa %xmm2, 48(%rsp) + # H ^ 5 and H ^ 6 + vpclmulqdq $16, %xmm0, %xmm1, %xmm11 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm10 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm9 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm12 + vpclmulqdq $0x00, %xmm1, %xmm1, %xmm13 + vpclmulqdq $0x11, %xmm1, %xmm1, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm0 + vpxor %xmm9, %xmm10, %xmm7 + vmovdqa %xmm7, 64(%rsp) + vmovdqa %xmm0, 80(%rsp) + # H ^ 7 and H ^ 8 + vpclmulqdq $16, %xmm1, %xmm2, %xmm11 + vpclmulqdq $0x01, %xmm1, %xmm2, %xmm10 + vpclmulqdq $0x00, %xmm1, %xmm2, %xmm9 + vpclmulqdq $0x11, %xmm1, %xmm2, %xmm12 + vpclmulqdq $0x00, %xmm2, %xmm2, %xmm13 + vpclmulqdq $0x11, %xmm2, %xmm2, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm0 + vpxor %xmm9, %xmm10, %xmm7 + vmovdqa %xmm7, 96(%rsp) + vmovdqa %xmm0, 112(%rsp) + # First 128 bytes of input + # aesenc_128 + # aesenc_ctr + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx2_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx2_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx2_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx2_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx2_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx2_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx2_aes_gcm_eight(%rip), %xmm0, %xmm0 + vpshufb %xmm1, %xmm15, %xmm15 + # aesenc_xor + vmovdqa (%rsi), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + vmovdqa 16(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 32(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 48(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 64(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 80(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 96(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 112(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 128(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 144(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm7 + jl L_AES_GCM_encrypt_avx2_aesenc_128_enc_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm7 + jl L_AES_GCM_encrypt_avx2_aesenc_128_enc_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm7 +L_AES_GCM_encrypt_avx2_aesenc_128_enc_done: + # aesenc_last + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu (%rdi), %xmm0 + vmovdqu 16(%rdi), %xmm1 + vmovdqu 32(%rdi), %xmm2 + vmovdqu 48(%rdi), %xmm3 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm2, %xmm10, %xmm10 + vpxor %xmm3, %xmm11, %xmm11 + vmovdqu %xmm8, (%r8) + vmovdqu %xmm9, 16(%r8) + vmovdqu %xmm10, 32(%r8) + vmovdqu %xmm11, 48(%r8) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 64(%rdi), %xmm0 + vmovdqu 80(%rdi), %xmm1 + vmovdqu 96(%rdi), %xmm2 + vmovdqu 112(%rdi), %xmm3 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vpxor %xmm2, %xmm14, %xmm14 + vpxor %xmm3, %xmm15, %xmm15 + vmovdqu %xmm12, 64(%r8) + vmovdqu %xmm13, 80(%r8) + vmovdqu %xmm14, 96(%r8) + vmovdqu %xmm15, 112(%r8) + cmpl $0x80, %r13d + movl $0x80, %ebx + jle L_AES_GCM_encrypt_avx2_end_128 + # More 128 bytes of input +L_AES_GCM_encrypt_avx2_ghash_128: + # aesenc_128_ghash + leaq (%rdi,%rbx,1), %rcx + leaq (%r8,%rbx,1), %rdx + # aesenc_ctr + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx2_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx2_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx2_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx2_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx2_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx2_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx2_aes_gcm_eight(%rip), %xmm0, %xmm0 + vpshufb %xmm1, %xmm15, %xmm15 + # aesenc_xor + vmovdqa (%rsi), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + # aesenc_pclmul_1 + vmovdqu -128(%rdx), %xmm1 + vmovdqu 16(%rsi), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vmovdqa 112(%rsp), %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm5 + vpclmulqdq $0x01, %xmm2, %xmm1, %xmm3 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm6 + vpclmulqdq $0x11, %xmm2, %xmm1, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_2 + vmovdqu -112(%rdx), %xmm1 + vmovdqa 96(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 32(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -96(%rdx), %xmm1 + vmovdqa 80(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 48(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -80(%rdx), %xmm1 + vmovdqa 64(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 64(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -64(%rdx), %xmm1 + vmovdqa 48(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 80(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -48(%rdx), %xmm1 + vmovdqa 32(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 96(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -32(%rdx), %xmm1 + vmovdqa 16(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 112(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -16(%rdx), %xmm1 + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 128(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_l + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm4, %xmm6, %xmm6 + vpxor %xmm3, %xmm5, %xmm5 + vpslldq $8, %xmm5, %xmm1 + vpsrldq $8, %xmm5, %xmm5 + vmovdqa 144(%rsi), %xmm4 + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm0 + vaesenc %xmm4, %xmm8, %xmm8 + vpxor %xmm1, %xmm6, %xmm6 + vpxor %xmm5, %xmm7, %xmm7 + vpclmulqdq $16, %xmm0, %xmm6, %xmm3 + vaesenc %xmm4, %xmm9, %xmm9 + vaesenc %xmm4, %xmm10, %xmm10 + vaesenc %xmm4, %xmm11, %xmm11 + vpshufd $0x4e, %xmm6, %xmm6 + vpxor %xmm3, %xmm6, %xmm6 + vpclmulqdq $16, %xmm0, %xmm6, %xmm3 + vaesenc %xmm4, %xmm12, %xmm12 + vaesenc %xmm4, %xmm13, %xmm13 + vaesenc %xmm4, %xmm14, %xmm14 + vpshufd $0x4e, %xmm6, %xmm6 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm7, %xmm6, %xmm6 + vaesenc %xmm4, %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm7 + jl L_AES_GCM_encrypt_avx2_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm7 + jl L_AES_GCM_encrypt_avx2_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm7 +L_AES_GCM_encrypt_avx2_aesenc_128_ghash_avx_done: + # aesenc_last + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vmovdqu 32(%rcx), %xmm2 + vmovdqu 48(%rcx), %xmm3 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm2, %xmm10, %xmm10 + vpxor %xmm3, %xmm11, %xmm11 + vmovdqu %xmm8, (%rdx) + vmovdqu %xmm9, 16(%rdx) + vmovdqu %xmm10, 32(%rdx) + vmovdqu %xmm11, 48(%rdx) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 64(%rcx), %xmm0 + vmovdqu 80(%rcx), %xmm1 + vmovdqu 96(%rcx), %xmm2 + vmovdqu 112(%rcx), %xmm3 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vpxor %xmm2, %xmm14, %xmm14 + vpxor %xmm3, %xmm15, %xmm15 + vmovdqu %xmm12, 64(%rdx) + vmovdqu %xmm13, 80(%rdx) + vmovdqu %xmm14, 96(%rdx) + vmovdqu %xmm15, 112(%rdx) + # aesenc_128_ghash - end + addl $0x80, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_encrypt_avx2_ghash_128 +L_AES_GCM_encrypt_avx2_end_128: + vmovdqa L_avx2_aes_gcm_bswap_mask(%rip), %xmm4 + vpshufb %xmm4, %xmm8, %xmm8 + vpshufb %xmm4, %xmm9, %xmm9 + vpshufb %xmm4, %xmm10, %xmm10 + vpshufb %xmm4, %xmm11, %xmm11 + vpshufb %xmm4, %xmm12, %xmm12 + vpshufb %xmm4, %xmm13, %xmm13 + vpshufb %xmm4, %xmm14, %xmm14 + vpshufb %xmm4, %xmm15, %xmm15 + vpxor %xmm6, %xmm8, %xmm8 + vmovdqu (%rsp), %xmm7 + vpclmulqdq $16, %xmm15, %xmm7, %xmm5 + vpclmulqdq $0x01, %xmm15, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm15, %xmm7, %xmm4 + vpclmulqdq $0x11, %xmm15, %xmm7, %xmm6 + vpxor %xmm1, %xmm5, %xmm5 + vmovdqu 16(%rsp), %xmm7 + vpclmulqdq $16, %xmm14, %xmm7, %xmm2 + vpclmulqdq $0x01, %xmm14, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm14, %xmm7, %xmm0 + vpclmulqdq $0x11, %xmm14, %xmm7, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vmovdqu 32(%rsp), %xmm15 + vmovdqu 48(%rsp), %xmm7 + vpclmulqdq $16, %xmm13, %xmm15, %xmm2 + vpclmulqdq $0x01, %xmm13, %xmm15, %xmm1 + vpclmulqdq $0x00, %xmm13, %xmm15, %xmm0 + vpclmulqdq $0x11, %xmm13, %xmm15, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vpclmulqdq $16, %xmm12, %xmm7, %xmm2 + vpclmulqdq $0x01, %xmm12, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm12, %xmm7, %xmm0 + vpclmulqdq $0x11, %xmm12, %xmm7, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vmovdqu 64(%rsp), %xmm15 + vmovdqu 80(%rsp), %xmm7 + vpclmulqdq $16, %xmm11, %xmm15, %xmm2 + vpclmulqdq $0x01, %xmm11, %xmm15, %xmm1 + vpclmulqdq $0x00, %xmm11, %xmm15, %xmm0 + vpclmulqdq $0x11, %xmm11, %xmm15, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vpclmulqdq $16, %xmm10, %xmm7, %xmm2 + vpclmulqdq $0x01, %xmm10, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm10, %xmm7, %xmm0 + vpclmulqdq $0x11, %xmm10, %xmm7, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vmovdqu 96(%rsp), %xmm15 + vmovdqu 112(%rsp), %xmm7 + vpclmulqdq $16, %xmm9, %xmm15, %xmm2 + vpclmulqdq $0x01, %xmm9, %xmm15, %xmm1 + vpclmulqdq $0x00, %xmm9, %xmm15, %xmm0 + vpclmulqdq $0x11, %xmm9, %xmm15, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vpclmulqdq $16, %xmm8, %xmm7, %xmm2 + vpclmulqdq $0x01, %xmm8, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm8, %xmm7, %xmm0 + vpclmulqdq $0x11, %xmm8, %xmm7, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vpslldq $8, %xmm5, %xmm7 + vpsrldq $8, %xmm5, %xmm5 + vpxor %xmm7, %xmm4, %xmm4 + vpxor %xmm5, %xmm6, %xmm6 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm4, %xmm0 + vpshufd $0x4e, %xmm4, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm6, %xmm6 + vmovdqa (%rsp), %xmm5 + vmovdqu 128(%rsp), %xmm4 + vmovdqu 144(%rsp), %xmm15 +L_AES_GCM_encrypt_avx2_done_128: + cmpl %r10d, %ebx + je L_AES_GCM_encrypt_avx2_done_enc + movl %r10d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %ebx + jge L_AES_GCM_encrypt_avx2_last_block_done + # aesenc_block + vmovdqa %xmm4, %xmm1 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1, %xmm0 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm1, %xmm1 + vpxor (%rsi), %xmm0, %xmm0 + vmovdqa 16(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 32(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 48(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 64(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 80(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 96(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 112(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 128(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 144(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa %xmm1, %xmm4 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm1 + jl L_AES_GCM_encrypt_avx2_aesenc_block_last + vaesenc %xmm1, %xmm0, %xmm0 + vmovdqa 176(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm1 + jl L_AES_GCM_encrypt_avx2_aesenc_block_last + vaesenc %xmm1, %xmm0, %xmm0 + vmovdqa 208(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 224(%rsi), %xmm1 +L_AES_GCM_encrypt_avx2_aesenc_block_last: + vaesenclast %xmm1, %xmm0, %xmm0 + vmovdqu (%rdi,%rbx,1), %xmm1 + vpxor %xmm1, %xmm0, %xmm0 + vmovdqu %xmm0, (%r8,%rbx,1) + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + addl $16, %ebx + cmpl %r13d, %ebx + jge L_AES_GCM_encrypt_avx2_last_block_ghash +L_AES_GCM_encrypt_avx2_last_block_start: + vmovdqu (%rdi,%rbx,1), %xmm12 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm11 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm4, %xmm4 + # aesenc_gfmul_sb + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm2 + vpclmulqdq $16, %xmm5, %xmm6, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm1 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm8 + vpxor (%rsi), %xmm11, %xmm11 + vaesenc 16(%rsi), %xmm11, %xmm11 + vpxor %xmm2, %xmm3, %xmm3 + vpslldq $8, %xmm3, %xmm2 + vpsrldq $8, %xmm3, %xmm3 + vaesenc 32(%rsi), %xmm11, %xmm11 + vpxor %xmm1, %xmm2, %xmm2 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm2, %xmm1 + vaesenc 48(%rsi), %xmm11, %xmm11 + vaesenc 64(%rsi), %xmm11, %xmm11 + vaesenc 80(%rsi), %xmm11, %xmm11 + vpshufd $0x4e, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm2, %xmm1 + vaesenc 96(%rsi), %xmm11, %xmm11 + vaesenc 112(%rsi), %xmm11, %xmm11 + vaesenc 128(%rsi), %xmm11, %xmm11 + vpshufd $0x4e, %xmm2, %xmm2 + vaesenc 144(%rsi), %xmm11, %xmm11 + vpxor %xmm3, %xmm8, %xmm8 + vpxor %xmm8, %xmm2, %xmm2 + vmovdqa 160(%rsi), %xmm0 + cmpl $11, %r9d + jl L_AES_GCM_encrypt_avx2_aesenc_gfmul_sb_last + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc 176(%rsi), %xmm11, %xmm11 + vmovdqa 192(%rsi), %xmm0 + cmpl $13, %r9d + jl L_AES_GCM_encrypt_avx2_aesenc_gfmul_sb_last + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc 208(%rsi), %xmm11, %xmm11 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_encrypt_avx2_aesenc_gfmul_sb_last: + vaesenclast %xmm0, %xmm11, %xmm11 + vpxor %xmm1, %xmm2, %xmm6 + vpxor %xmm12, %xmm11, %xmm11 + vmovdqu %xmm11, (%r8,%rbx,1) + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm11, %xmm11 + vpxor %xmm11, %xmm6, %xmm6 + addl $16, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_encrypt_avx2_last_block_start +L_AES_GCM_encrypt_avx2_last_block_ghash: + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm6, %xmm10 + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm9 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm9, %xmm10, %xmm10 + vpslldq $8, %xmm10, %xmm9 + vpsrldq $8, %xmm10, %xmm10 + vpxor %xmm8, %xmm9, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm6 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm10, %xmm6, %xmm6 + vpxor %xmm9, %xmm6, %xmm6 + vpxor %xmm8, %xmm6, %xmm6 +L_AES_GCM_encrypt_avx2_last_block_done: + movl %r10d, %ecx + movl %r10d, %edx + andl $15, %ecx + jz L_AES_GCM_encrypt_avx2_done_enc + # aesenc_last15_enc + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpxor (%rsi), %xmm4, %xmm4 + vaesenc 16(%rsi), %xmm4, %xmm4 + vaesenc 32(%rsi), %xmm4, %xmm4 + vaesenc 48(%rsi), %xmm4, %xmm4 + vaesenc 64(%rsi), %xmm4, %xmm4 + vaesenc 80(%rsi), %xmm4, %xmm4 + vaesenc 96(%rsi), %xmm4, %xmm4 + vaesenc 112(%rsi), %xmm4, %xmm4 + vaesenc 128(%rsi), %xmm4, %xmm4 + vaesenc 144(%rsi), %xmm4, %xmm4 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_aesenc_avx_last + vaesenc %xmm0, %xmm4, %xmm4 + vaesenc 176(%rsi), %xmm4, %xmm4 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_aesenc_avx_last + vaesenc %xmm0, %xmm4, %xmm4 + vaesenc 208(%rsi), %xmm4, %xmm4 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_aesenc_avx_last: + vaesenclast %xmm0, %xmm4, %xmm4 + xorl %ecx, %ecx + vpxor %xmm0, %xmm0, %xmm0 + vmovdqa %xmm4, (%rsp) + vmovdqa %xmm0, 16(%rsp) +L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_loop: + movzbl (%rdi,%rbx,1), %r13d + xorb (%rsp,%rcx,1), %r13b + movb %r13b, 16(%rsp,%rcx,1) + movb %r13b, (%r8,%rbx,1) + incl %ebx + incl %ecx + cmpl %edx, %ebx + jl L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_loop +L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_finish_enc: + vmovdqa 16(%rsp), %xmm4 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + vpxor %xmm4, %xmm6, %xmm6 + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm6, %xmm2 + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm1 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm0 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm6 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm2, %xmm6, %xmm6 + vpxor %xmm1, %xmm6, %xmm6 + vpxor %xmm0, %xmm6, %xmm6 +L_AES_GCM_encrypt_avx2_done_enc: + # calc_tag + shlq $3, %r10 + vpinsrq $0x00, %r10, %xmm0, %xmm0 + shlq $3, %r11 + vpinsrq $0x01, %r11, %xmm1, %xmm1 + vpblendd $12, %xmm1, %xmm0, %xmm0 + vpxor %xmm6, %xmm0, %xmm0 + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm0, %xmm4 + vpclmulqdq $0x01, %xmm5, %xmm0, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm2 + vpxor %xmm3, %xmm4, %xmm4 + vpslldq $8, %xmm4, %xmm3 + vpsrldq $8, %xmm4, %xmm4 + vpxor %xmm2, %xmm3, %xmm3 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm0 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm2, %xmm3, %xmm3 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm4, %xmm0, %xmm0 + vpxor %xmm3, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm15, %xmm0, %xmm0 + # store_tag + cmpl $16, %r14d + je L_AES_GCM_encrypt_avx2_store_tag_16 + xorq %rcx, %rcx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_encrypt_avx2_store_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + movb %r13b, (%r15,%rcx,1) + incl %ecx + cmpl %r14d, %ecx + jne L_AES_GCM_encrypt_avx2_store_tag_loop + jmp L_AES_GCM_encrypt_avx2_store_tag_done +L_AES_GCM_encrypt_avx2_store_tag_16: + vmovdqu %xmm0, (%r15) +L_AES_GCM_encrypt_avx2_store_tag_done: + vzeroupper + addq $0xa0, %rsp + popq %r14 + popq %rbx + popq %r15 + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_avx2,.-AES_GCM_encrypt_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_decrypt_avx2 +.type AES_GCM_decrypt_avx2,@function +.align 4 +AES_GCM_decrypt_avx2: +#else +.section __TEXT,__text +.globl _AES_GCM_decrypt_avx2 +.p2align 2 +_AES_GCM_decrypt_avx2: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %r14 + pushq %rbx + pushq %r15 + pushq %rbp + movq %rdx, %r12 + movq %rcx, %rax + movq %r8, %r14 + movq %rsi, %r8 + movl %r9d, %r10d + movl 56(%rsp), %r11d + movl 64(%rsp), %ebx + movl 72(%rsp), %r15d + movq 80(%rsp), %rsi + movl 88(%rsp), %r9d + movq 96(%rsp), %rbp + subq $0xa8, %rsp + vpxor %xmm4, %xmm4, %xmm4 + vpxor %xmm6, %xmm6, %xmm6 + movl %ebx, %edx + cmpl $12, %edx + je L_AES_GCM_decrypt_avx2_iv_12 + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + vmovdqa (%rsi), %xmm5 + vaesenc 16(%rsi), %xmm5, %xmm5 + vaesenc 32(%rsi), %xmm5, %xmm5 + vaesenc 48(%rsi), %xmm5, %xmm5 + vaesenc 64(%rsi), %xmm5, %xmm5 + vaesenc 80(%rsi), %xmm5, %xmm5 + vaesenc 96(%rsi), %xmm5, %xmm5 + vaesenc 112(%rsi), %xmm5, %xmm5 + vaesenc 128(%rsi), %xmm5, %xmm5 + vaesenc 144(%rsi), %xmm5, %xmm5 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_decrypt_avx2_calc_iv_1_aesenc_avx_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc 176(%rsi), %xmm5, %xmm5 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_decrypt_avx2_calc_iv_1_aesenc_avx_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc 208(%rsi), %xmm5, %xmm5 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_decrypt_avx2_calc_iv_1_aesenc_avx_last: + vaesenclast %xmm0, %xmm5, %xmm5 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_decrypt_avx2_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_decrypt_avx2_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_decrypt_avx2_calc_iv_16_loop: + vmovdqu (%rax,%rcx,1), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx2_calc_iv_16_loop + movl %ebx, %edx + cmpl %edx, %ecx + je L_AES_GCM_decrypt_avx2_calc_iv_done +L_AES_GCM_decrypt_avx2_calc_iv_lt16: + vpxor %xmm0, %xmm0, %xmm0 + xorl %ebx, %ebx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_decrypt_avx2_calc_iv_loop: + movzbl (%rax,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx2_calc_iv_loop + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 +L_AES_GCM_decrypt_avx2_calc_iv_done: + # T = Encrypt counter + vpxor %xmm0, %xmm0, %xmm0 + shll $3, %edx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + # Encrypt counter + vmovdqa (%rsi), %xmm15 + vpxor %xmm4, %xmm15, %xmm15 + vaesenc 16(%rsi), %xmm15, %xmm15 + vaesenc 32(%rsi), %xmm15, %xmm15 + vaesenc 48(%rsi), %xmm15, %xmm15 + vaesenc 64(%rsi), %xmm15, %xmm15 + vaesenc 80(%rsi), %xmm15, %xmm15 + vaesenc 96(%rsi), %xmm15, %xmm15 + vaesenc 112(%rsi), %xmm15, %xmm15 + vaesenc 128(%rsi), %xmm15, %xmm15 + vaesenc 144(%rsi), %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_decrypt_avx2_calc_iv_2_aesenc_avx_last + vaesenc %xmm0, %xmm15, %xmm15 + vaesenc 176(%rsi), %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_decrypt_avx2_calc_iv_2_aesenc_avx_last + vaesenc %xmm0, %xmm15, %xmm15 + vaesenc 208(%rsi), %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_decrypt_avx2_calc_iv_2_aesenc_avx_last: + vaesenclast %xmm0, %xmm15, %xmm15 + jmp L_AES_GCM_decrypt_avx2_iv_done +L_AES_GCM_decrypt_avx2_iv_12: + # # Calculate values when IV is 12 bytes + # Set counter based on IV + vmovdqa L_avx2_aes_gcm_bswap_one(%rip), %xmm4 + vmovdqa (%rsi), %xmm5 + vpblendd $7, (%rax), %xmm4, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + vmovdqa 16(%rsi), %xmm7 + vpxor %xmm5, %xmm4, %xmm15 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 32(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 48(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 64(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 80(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 96(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 112(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 128(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 144(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_decrypt_avx2_calc_iv_12_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 176(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_decrypt_avx2_calc_iv_12_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 208(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_decrypt_avx2_calc_iv_12_last: + vaesenclast %xmm0, %xmm5, %xmm5 + vaesenclast %xmm0, %xmm15, %xmm15 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 +L_AES_GCM_decrypt_avx2_iv_done: + # Additional authentication data + movl %r11d, %edx + cmpl $0x00, %edx + je L_AES_GCM_decrypt_avx2_calc_aad_done + xorl %ecx, %ecx + cmpl $16, %edx + jl L_AES_GCM_decrypt_avx2_calc_aad_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_decrypt_avx2_calc_aad_16_loop: + vmovdqu (%r12,%rcx,1), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm6, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm6, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm6 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm6, %xmm6 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx2_calc_aad_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_decrypt_avx2_calc_aad_done +L_AES_GCM_decrypt_avx2_calc_aad_lt16: + vpxor %xmm0, %xmm0, %xmm0 + xorl %ebx, %ebx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_decrypt_avx2_calc_aad_loop: + movzbl (%r12,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx2_calc_aad_loop + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm6, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm6, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm6 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm6, %xmm6 +L_AES_GCM_decrypt_avx2_calc_aad_done: + # Calculate counter and H + vpsrlq $63, %xmm5, %xmm1 + vpsllq $0x01, %xmm5, %xmm0 + vpslldq $8, %xmm1, %xmm1 + vpor %xmm1, %xmm0, %xmm0 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpand L_avx2_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm4, %xmm4 + vpxor %xmm0, %xmm5, %xmm5 + xorl %ebx, %ebx + cmpl $0x80, %r10d + movl %r10d, %r13d + jl L_AES_GCM_decrypt_avx2_done_128 + andl $0xffffff80, %r13d + vmovdqa %xmm4, 128(%rsp) + vmovdqa %xmm15, 144(%rsp) + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm3 + # H ^ 1 and H ^ 2 + vpclmulqdq $0x00, %xmm5, %xmm5, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm5, %xmm10 + vpclmulqdq $16, %xmm3, %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpclmulqdq $16, %xmm3, %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm9, %xmm10, %xmm0 + vmovdqa %xmm5, (%rsp) + vmovdqa %xmm0, 16(%rsp) + # H ^ 3 and H ^ 4 + vpclmulqdq $16, %xmm5, %xmm0, %xmm11 + vpclmulqdq $0x01, %xmm5, %xmm0, %xmm10 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm12 + vpclmulqdq $0x00, %xmm0, %xmm0, %xmm13 + vpclmulqdq $0x11, %xmm0, %xmm0, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm2 + vpxor %xmm9, %xmm10, %xmm1 + vmovdqa %xmm1, 32(%rsp) + vmovdqa %xmm2, 48(%rsp) + # H ^ 5 and H ^ 6 + vpclmulqdq $16, %xmm0, %xmm1, %xmm11 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm10 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm9 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm12 + vpclmulqdq $0x00, %xmm1, %xmm1, %xmm13 + vpclmulqdq $0x11, %xmm1, %xmm1, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm0 + vpxor %xmm9, %xmm10, %xmm7 + vmovdqa %xmm7, 64(%rsp) + vmovdqa %xmm0, 80(%rsp) + # H ^ 7 and H ^ 8 + vpclmulqdq $16, %xmm1, %xmm2, %xmm11 + vpclmulqdq $0x01, %xmm1, %xmm2, %xmm10 + vpclmulqdq $0x00, %xmm1, %xmm2, %xmm9 + vpclmulqdq $0x11, %xmm1, %xmm2, %xmm12 + vpclmulqdq $0x00, %xmm2, %xmm2, %xmm13 + vpclmulqdq $0x11, %xmm2, %xmm2, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm0 + vpxor %xmm9, %xmm10, %xmm7 + vmovdqa %xmm7, 96(%rsp) + vmovdqa %xmm0, 112(%rsp) +L_AES_GCM_decrypt_avx2_ghash_128: + # aesenc_128_ghash + leaq (%rdi,%rbx,1), %rcx + leaq (%r8,%rbx,1), %rdx + # aesenc_ctr + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx2_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx2_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx2_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx2_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx2_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx2_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx2_aes_gcm_eight(%rip), %xmm0, %xmm0 + vpshufb %xmm1, %xmm15, %xmm15 + # aesenc_xor + vmovdqa (%rsi), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + # aesenc_pclmul_1 + vmovdqu (%rcx), %xmm1 + vmovdqu 16(%rsi), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vmovdqa 112(%rsp), %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm5 + vpclmulqdq $0x01, %xmm2, %xmm1, %xmm3 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm6 + vpclmulqdq $0x11, %xmm2, %xmm1, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_2 + vmovdqu 16(%rcx), %xmm1 + vmovdqa 96(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 32(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 32(%rcx), %xmm1 + vmovdqa 80(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 48(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 48(%rcx), %xmm1 + vmovdqa 64(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 64(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 64(%rcx), %xmm1 + vmovdqa 48(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 80(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 80(%rcx), %xmm1 + vmovdqa 32(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 96(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 96(%rcx), %xmm1 + vmovdqa 16(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 112(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 112(%rcx), %xmm1 + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 128(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_l + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm4, %xmm6, %xmm6 + vpxor %xmm3, %xmm5, %xmm5 + vpslldq $8, %xmm5, %xmm1 + vpsrldq $8, %xmm5, %xmm5 + vmovdqa 144(%rsi), %xmm4 + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm0 + vaesenc %xmm4, %xmm8, %xmm8 + vpxor %xmm1, %xmm6, %xmm6 + vpxor %xmm5, %xmm7, %xmm7 + vpclmulqdq $16, %xmm0, %xmm6, %xmm3 + vaesenc %xmm4, %xmm9, %xmm9 + vaesenc %xmm4, %xmm10, %xmm10 + vaesenc %xmm4, %xmm11, %xmm11 + vpshufd $0x4e, %xmm6, %xmm6 + vpxor %xmm3, %xmm6, %xmm6 + vpclmulqdq $16, %xmm0, %xmm6, %xmm3 + vaesenc %xmm4, %xmm12, %xmm12 + vaesenc %xmm4, %xmm13, %xmm13 + vaesenc %xmm4, %xmm14, %xmm14 + vpshufd $0x4e, %xmm6, %xmm6 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm7, %xmm6, %xmm6 + vaesenc %xmm4, %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm7 + jl L_AES_GCM_decrypt_avx2_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm7 + jl L_AES_GCM_decrypt_avx2_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm7 +L_AES_GCM_decrypt_avx2_aesenc_128_ghash_avx_done: + # aesenc_last + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vmovdqu 32(%rcx), %xmm2 + vmovdqu 48(%rcx), %xmm3 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm2, %xmm10, %xmm10 + vpxor %xmm3, %xmm11, %xmm11 + vmovdqu %xmm8, (%rdx) + vmovdqu %xmm9, 16(%rdx) + vmovdqu %xmm10, 32(%rdx) + vmovdqu %xmm11, 48(%rdx) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 64(%rcx), %xmm0 + vmovdqu 80(%rcx), %xmm1 + vmovdqu 96(%rcx), %xmm2 + vmovdqu 112(%rcx), %xmm3 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vpxor %xmm2, %xmm14, %xmm14 + vpxor %xmm3, %xmm15, %xmm15 + vmovdqu %xmm12, 64(%rdx) + vmovdqu %xmm13, 80(%rdx) + vmovdqu %xmm14, 96(%rdx) + vmovdqu %xmm15, 112(%rdx) + # aesenc_128_ghash - end + addl $0x80, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_decrypt_avx2_ghash_128 + vmovdqa (%rsp), %xmm5 + vmovdqa 128(%rsp), %xmm4 + vmovdqa 144(%rsp), %xmm15 +L_AES_GCM_decrypt_avx2_done_128: + cmpl %r10d, %ebx + jge L_AES_GCM_decrypt_avx2_done_dec + movl %r10d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %ebx + jge L_AES_GCM_decrypt_avx2_last_block_done +L_AES_GCM_decrypt_avx2_last_block_start: + vmovdqu (%rdi,%rbx,1), %xmm11 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm10 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm11, %xmm12 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm4, %xmm4 + vpxor %xmm6, %xmm12, %xmm12 + # aesenc_gfmul_sb + vpclmulqdq $0x01, %xmm5, %xmm12, %xmm2 + vpclmulqdq $16, %xmm5, %xmm12, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm12, %xmm1 + vpclmulqdq $0x11, %xmm5, %xmm12, %xmm8 + vpxor (%rsi), %xmm10, %xmm10 + vaesenc 16(%rsi), %xmm10, %xmm10 + vpxor %xmm2, %xmm3, %xmm3 + vpslldq $8, %xmm3, %xmm2 + vpsrldq $8, %xmm3, %xmm3 + vaesenc 32(%rsi), %xmm10, %xmm10 + vpxor %xmm1, %xmm2, %xmm2 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm2, %xmm1 + vaesenc 48(%rsi), %xmm10, %xmm10 + vaesenc 64(%rsi), %xmm10, %xmm10 + vaesenc 80(%rsi), %xmm10, %xmm10 + vpshufd $0x4e, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm2, %xmm1 + vaesenc 96(%rsi), %xmm10, %xmm10 + vaesenc 112(%rsi), %xmm10, %xmm10 + vaesenc 128(%rsi), %xmm10, %xmm10 + vpshufd $0x4e, %xmm2, %xmm2 + vaesenc 144(%rsi), %xmm10, %xmm10 + vpxor %xmm3, %xmm8, %xmm8 + vpxor %xmm8, %xmm2, %xmm2 + vmovdqa 160(%rsi), %xmm0 + cmpl $11, %r9d + jl L_AES_GCM_decrypt_avx2_aesenc_gfmul_sb_last + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc 176(%rsi), %xmm10, %xmm10 + vmovdqa 192(%rsi), %xmm0 + cmpl $13, %r9d + jl L_AES_GCM_decrypt_avx2_aesenc_gfmul_sb_last + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc 208(%rsi), %xmm10, %xmm10 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_decrypt_avx2_aesenc_gfmul_sb_last: + vaesenclast %xmm0, %xmm10, %xmm10 + vpxor %xmm1, %xmm2, %xmm6 + vpxor %xmm11, %xmm10, %xmm10 + vmovdqu %xmm10, (%r8,%rbx,1) + addl $16, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_decrypt_avx2_last_block_start +L_AES_GCM_decrypt_avx2_last_block_done: + movl %r10d, %ecx + movl %r10d, %edx + andl $15, %ecx + jz L_AES_GCM_decrypt_avx2_done_dec + # aesenc_last15_dec + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpxor (%rsi), %xmm4, %xmm4 + vaesenc 16(%rsi), %xmm4, %xmm4 + vaesenc 32(%rsi), %xmm4, %xmm4 + vaesenc 48(%rsi), %xmm4, %xmm4 + vaesenc 64(%rsi), %xmm4, %xmm4 + vaesenc 80(%rsi), %xmm4, %xmm4 + vaesenc 96(%rsi), %xmm4, %xmm4 + vaesenc 112(%rsi), %xmm4, %xmm4 + vaesenc 128(%rsi), %xmm4, %xmm4 + vaesenc 144(%rsi), %xmm4, %xmm4 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm1 + jl L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_aesenc_avx_last + vaesenc %xmm1, %xmm4, %xmm4 + vaesenc 176(%rsi), %xmm4, %xmm4 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm1 + jl L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_aesenc_avx_last + vaesenc %xmm1, %xmm4, %xmm4 + vaesenc 208(%rsi), %xmm4, %xmm4 + vmovdqa 224(%rsi), %xmm1 +L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_aesenc_avx_last: + vaesenclast %xmm1, %xmm4, %xmm4 + xorl %ecx, %ecx + vpxor %xmm0, %xmm0, %xmm0 + vmovdqa %xmm4, (%rsp) + vmovdqa %xmm0, 16(%rsp) +L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_loop: + movzbl (%rdi,%rbx,1), %r13d + movb %r13b, 16(%rsp,%rcx,1) + xorb (%rsp,%rcx,1), %r13b + movb %r13b, (%r8,%rbx,1) + incl %ebx + incl %ecx + cmpl %edx, %ebx + jl L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_loop + vmovdqa 16(%rsp), %xmm4 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + vpxor %xmm4, %xmm6, %xmm6 + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm6, %xmm2 + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm1 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm0 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm6 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm2, %xmm6, %xmm6 + vpxor %xmm1, %xmm6, %xmm6 + vpxor %xmm0, %xmm6, %xmm6 +L_AES_GCM_decrypt_avx2_done_dec: + # calc_tag + shlq $3, %r10 + vpinsrq $0x00, %r10, %xmm0, %xmm0 + shlq $3, %r11 + vpinsrq $0x01, %r11, %xmm1, %xmm1 + vpblendd $12, %xmm1, %xmm0, %xmm0 + vpxor %xmm6, %xmm0, %xmm0 + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm0, %xmm4 + vpclmulqdq $0x01, %xmm5, %xmm0, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm2 + vpxor %xmm3, %xmm4, %xmm4 + vpslldq $8, %xmm4, %xmm3 + vpsrldq $8, %xmm4, %xmm4 + vpxor %xmm2, %xmm3, %xmm3 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm0 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm2, %xmm3, %xmm3 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm4, %xmm0, %xmm0 + vpxor %xmm3, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm15, %xmm0, %xmm0 + # cmp_tag + cmpl $16, %r15d + je L_AES_GCM_decrypt_avx2_cmp_tag_16 + xorq %rdx, %rdx + xorq %rax, %rax + vmovdqa %xmm0, (%rsp) +L_AES_GCM_decrypt_avx2_cmp_tag_loop: + movzbl (%rsp,%rdx,1), %r13d + xorb (%r14,%rdx,1), %r13b + orb %r13b, %al + incl %edx + cmpl %r15d, %edx + jne L_AES_GCM_decrypt_avx2_cmp_tag_loop + cmpb $0x00, %al + sete %al + jmp L_AES_GCM_decrypt_avx2_cmp_tag_done +L_AES_GCM_decrypt_avx2_cmp_tag_16: + vmovdqu (%r14), %xmm1 + vpcmpeqb %xmm1, %xmm0, %xmm0 + vpmovmskb %xmm0, %rdx + # %%edx == 0xFFFF then return 1 else => return 0 + xorl %eax, %eax + cmpl $0xffff, %edx + sete %al +L_AES_GCM_decrypt_avx2_cmp_tag_done: + movl %eax, (%rbp) + vzeroupper + addq $0xa8, %rsp + popq %rbp + popq %r15 + popq %rbx + popq %r14 + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_decrypt_avx2,.-AES_GCM_decrypt_avx2 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/arc4.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/arc4.c index 21ed2e79d..7eb8268e3 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/arc4.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/arc4.c @@ -1,8 +1,8 @@ /* arc4.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -27,23 +28,25 @@ #ifndef NO_RC4 +#include #include -#ifdef HAVE_CAVIUM - static void wc_Arc4CaviumSetKey(Arc4* arc4, const byte* key, word32 length); - static void wc_Arc4CaviumProcess(Arc4* arc4, byte* out, const byte* in, - word32 length); -#endif - -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; -#ifdef HAVE_CAVIUM - if (arc4->magic == WOLFSSL_ARC4_CAVIUM_MAGIC) - return wc_Arc4CaviumSetKey(arc4, key, length); + if (arc4 == NULL || key == NULL || length == 0) { + 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); + } #endif arc4->x = 1; @@ -62,10 +65,12 @@ void wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) if (++keyIndex >= length) keyIndex = 0; } + + return ret; } -static INLINE byte MakeByte(word32* x, word32* y, byte* s) +static WC_INLINE byte MakeByte(word32* x, word32* y, byte* s) { word32 a = s[*x], b; *y = (*y+a) & 0xff; @@ -79,14 +84,21 @@ 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; -#ifdef HAVE_CAVIUM - if (arc4->magic == WOLFSSL_ARC4_CAVIUM_MAGIC) - return wc_Arc4CaviumProcess(arc4, out, in, length); + 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); + } #endif x = arc4->x; @@ -97,82 +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 HAVE_CAVIUM - -#include -#include "cavium_common.h" - -/* Initiliaze Arc4 for use with Nitrox device */ -int wc_Arc4InitCavium(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 -1; + return BAD_FUNC_ARG; - if (CspAllocContext(CONTEXT_SSL, &arc4->contextHandle, devId) != 0) - return -1; + arc4->heap = heap; - arc4->devId = devId; - arc4->magic = WOLFSSL_ARC4_CAVIUM_MAGIC; +#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 0; + return ret; } -/* Free Arc4 from use with Nitrox device */ -void wc_Arc4FreeCavium(Arc4* arc4) +/* Free Arc4 from use with async device */ +void wc_Arc4Free(Arc4* arc4) { if (arc4 == NULL) return; - if (arc4->magic != WOLFSSL_ARC4_CAVIUM_MAGIC) - return; - - CspFreeContext(CONTEXT_SSL, arc4->contextHandle, arc4->devId); - arc4->magic = 0; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) + wolfAsync_DevCtxFree(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4); +#endif /* WOLFSSL_ASYNC_CRYPT */ } - -static void wc_Arc4CaviumSetKey(Arc4* arc4, const byte* key, word32 length) -{ - word32 requestId; - - if (CspInitializeRc4(CAVIUM_BLOCKING, arc4->contextHandle, length, - (byte*)key, &requestId, arc4->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Arc4 Init"); - } -} - - -static void wc_Arc4CaviumProcess(Arc4* arc4, byte* out, const byte* in, - word32 length) -{ - wolfssl_word offset = 0; - word32 requestId; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - if (CspEncryptRc4(CAVIUM_BLOCKING, arc4->contextHandle,CAVIUM_UPDATE, - slen, (byte*)in + offset, out + offset, &requestId, - arc4->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Arc4 Encrypt"); - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - } - if (length) { - word16 slen = (word16)length; - if (CspEncryptRc4(CAVIUM_BLOCKING, arc4->contextHandle,CAVIUM_UPDATE, - slen, (byte*)in + offset, out + offset, &requestId, - arc4->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Arc4 Encrypt"); - } - } -} - -#endif /* HAVE_CAVIUM */ - #endif /* NO_RC4 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asm.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asm.c index 9f8458588..0af4447c7 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asm.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asm.c @@ -1,8 +1,8 @@ /* asm.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -50,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) @@ -58,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 @@ -74,30 +75,40 @@ #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]; - + int got_intel_cpu = 0; + int got_amd_cpu = 0; + 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; - } - if (got_intel_cpu) { + cpuid(reg, 0, 0); + + /* check for intel cpu */ + 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; + } + + /* check for AMD cpu */ + if( memcmp((char *)&(reg[EBX]), "Auth", 4) == 0 && + memcmp((char *)&(reg[EDX]), "enti", 4) == 0 && + memcmp((char *)&(reg[ECX]), "cAMD", 4) == 0) { + got_amd_cpu = 1; + } + if (got_intel_cpu || got_amd_cpu) { cpuid(reg, leaf, sub); return((reg[num]>>bit)&0x1) ; } return 0 ; } -INLINE static int set_cpuid_flags(void) { +WC_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 ; } @@ -116,17 +127,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" \ @@ -135,11 +146,11 @@ __asm__( \ "adcl $0,%%edx \n\t" \ "movl %%edx,%1 \n\t" \ :"=g"(_c[LO]), "=r"(cy) \ -:"0"(_c[LO]), "1"(cy), "g"(mu), "g"(*tmpm++) \ +:"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \ : "%eax", "%edx", "cc") #define PROPCARRY \ -__asm__( \ +__asm__( \ "addl %1,%0 \n\t" \ "setb %%al \n\t" \ "movzbl %%al,%1 \n\t" \ @@ -151,14 +162,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" \ @@ -171,70 +182,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);\ @@ -242,7 +246,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" \ @@ -332,10 +336,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" \ @@ -344,7 +348,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++) @@ -361,7 +365,7 @@ __asm__( \ __asm__("emms") #define LOOP_START \ -__asm__( \ +__asm__( \ "movd %0,%%mm1 \n\t" \ "pxor %%mm3,%%mm3 \n\t" \ "pmuludq %%mm2,%%mm1 \n\t" \ @@ -369,7 +373,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" \ @@ -380,7 +384,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" \ @@ -453,7 +457,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" \ @@ -465,7 +469,7 @@ __asm__( \ #elif defined(TFM_ARM) /* ARMv4 code */ -#define MONT_START +#define MONT_START #define MONT_FINI #define LOOP_END #define LOOP_START \ @@ -475,7 +479,7 @@ __asm__( \ #ifdef __thumb__ #define INNERMUL \ -__asm__( \ +__asm__( \ " LDR r0,%1 \n\t" \ " ADDS r0,r0,%0 \n\t" \ " ITE CS \n\t" \ @@ -486,7 +490,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" \ @@ -502,7 +506,7 @@ __asm__( \ #else /* __thumb__ */ #define INNERMUL \ -__asm__( \ +__asm__( \ " LDR r0,%1 \n\t" \ " ADDS r0,r0,%0 \n\t" \ " MOVCS %0,#1 \n\t" \ @@ -512,7 +516,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" \ @@ -525,76 +529,72 @@ __asm__( \ #elif defined(TFM_PPC32) /* PPC32 */ -#define MONT_START +#define MONT_START #define MONT_FINI #define LOOP_END #define LOOP_START \ mu = c[x] * mp #define INNERMUL \ -__asm__( \ +__asm__( \ " mullw 16,%3,%4 \n\t" \ " mulhwu 17,%3,%4 \n\t" \ - " addc 16,16,%0 \n\t" \ + " addc 16,16,%2 \n\t" \ " addze 17,17 \n\t" \ - " lwz 18,%1 \n\t" \ - " addc 16,16,18 \n\t" \ + " addc %1,16,%5 \n\t" \ " addze %0,17 \n\t" \ - " stw 16,%1 \n\t" \ -:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"16", "17", "18","cc"); ++tmpm; +:"=r"(cy),"=r"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"16", "17", "cc"); ++tmpm; #define PROPCARRY \ -__asm__( \ - " lwz 16,%1 \n\t" \ - " addc 16,16,%0 \n\t" \ - " stw 16,%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"); +__asm__( \ + " addc %1,%3,%2 \n\t" \ + " xor %0,%2,%2 \n\t" \ + " addze %0,%2 \n\t" \ +:"=r"(cy),"=r"(_c[0]):"0"(cy),"1"(_c[0]):"cc"); #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" \ @@ -605,7 +605,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" \ @@ -613,10 +613,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 \ @@ -663,7 +697,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" \ @@ -672,7 +706,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" \ @@ -692,10 +726,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" \ @@ -704,7 +736,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" \ @@ -733,16 +765,16 @@ __asm__( \ #define COMBA_FINI #define SQRADD(i, j) \ -__asm__( \ +__asm__( \ "movq %6,%%rax \n\t" \ "mulq %%rax \n\t" \ "addq %%rax,%0 \n\t" \ "adcq %%rdx,%1 \n\t" \ "adcq $0,%2 \n\t" \ - :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i) :"%rax","%rdx","cc"); + :"=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" \ @@ -754,7 +786,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" \ @@ -762,10 +794,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" \ @@ -774,7 +804,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" \ @@ -804,7 +834,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" \ @@ -816,7 +846,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" \ @@ -832,7 +862,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" \ @@ -845,7 +875,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" \ @@ -858,7 +888,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" \ @@ -889,16 +919,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" \ @@ -909,7 +939,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"); @@ -917,7 +947,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" \ @@ -925,7 +955,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" \ @@ -956,7 +986,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" \ @@ -966,7 +996,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" \ @@ -978,14 +1008,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" \ @@ -994,7 +1024,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" \ @@ -1023,46 +1053,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" \ @@ -1094,7 +1124,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" \ @@ -1103,7 +1133,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" \ @@ -1114,7 +1144,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" \ @@ -1122,7 +1152,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" \ @@ -1130,7 +1160,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" \ @@ -1139,6 +1169,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 @@ -1169,7 +1305,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) \ @@ -1177,10 +1313,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) \ @@ -1210,46 +1346,46 @@ __asm__( \ #include "fp_sqr_comba_small_set.i" #endif -#if defined(TFM_SQR3) +#if defined(TFM_SQR3) && FP_SIZE >= 6 #include "fp_sqr_comba_3.i" #endif -#if defined(TFM_SQR4) +#if defined(TFM_SQR4) && FP_SIZE >= 8 #include "fp_sqr_comba_4.i" #endif -#if defined(TFM_SQR6) +#if defined(TFM_SQR6) && FP_SIZE >= 12 #include "fp_sqr_comba_6.i" #endif -#if defined(TFM_SQR7) +#if defined(TFM_SQR7) && FP_SIZE >= 14 #include "fp_sqr_comba_7.i" #endif -#if defined(TFM_SQR8) +#if defined(TFM_SQR8) && FP_SIZE >= 16 #include "fp_sqr_comba_8.i" #endif -#if defined(TFM_SQR9) +#if defined(TFM_SQR9) && FP_SIZE >= 18 #include "fp_sqr_comba_9.i" #endif -#if defined(TFM_SQR12) +#if defined(TFM_SQR12) && FP_SIZE >= 24 #include "fp_sqr_comba_12.i" #endif -#if defined(TFM_SQR17) +#if defined(TFM_SQR17) && FP_SIZE >= 34 #include "fp_sqr_comba_17.i" #endif -#if defined(TFM_SQR20) +#if defined(TFM_SQR20) && FP_SIZE >= 40 #include "fp_sqr_comba_20.i" #endif -#if defined(TFM_SQR24) +#if defined(TFM_SQR24) && FP_SIZE >= 48 #include "fp_sqr_comba_24.i" #endif -#if defined(TFM_SQR28) +#if defined(TFM_SQR28) && FP_SIZE >= 56 #include "fp_sqr_comba_28.i" #endif -#if defined(TFM_SQR32) +#if defined(TFM_SQR32) && FP_SIZE >= 64 #include "fp_sqr_comba_32.i" #endif -#if defined(TFM_SQR48) +#if defined(TFM_SQR48) && FP_SIZE >= 96 #include "fp_sqr_comba_48.i" #endif -#if defined(TFM_SQR64) +#if defined(TFM_SQR64) && FP_SIZE >= 128 #include "fp_sqr_comba_64.i" #endif /* end fp_sqr_comba.c asm */ @@ -1283,7 +1419,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" \ @@ -1318,7 +1454,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" \ @@ -1328,61 +1464,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) @@ -1413,7 +1542,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" \ @@ -1428,7 +1557,7 @@ __asm__( \ #elif defined(TFM_ARM) /* ARM code */ -#define COMBA_START +#define COMBA_START #define COMBA_CLEAR \ c0 = c1 = c2 = 0; @@ -1445,7 +1574,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" \ @@ -1469,11 +1598,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" \ @@ -1498,17 +1627,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) @@ -1528,16 +1657,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 */ @@ -1555,13 +1718,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 @@ -1571,46 +1736,46 @@ ____asm__( \ #include "fp_mul_comba_small_set.i" #endif -#if defined(TFM_MUL3) +#if defined(TFM_MUL3) && FP_SIZE >= 6 #include "fp_mul_comba_3.i" #endif -#if defined(TFM_MUL4) +#if defined(TFM_MUL4) && FP_SIZE >= 8 #include "fp_mul_comba_4.i" #endif -#if defined(TFM_MUL6) +#if defined(TFM_MUL6) && FP_SIZE >= 12 #include "fp_mul_comba_6.i" #endif -#if defined(TFM_MUL7) +#if defined(TFM_MUL7) && FP_SIZE >= 14 #include "fp_mul_comba_7.i" #endif -#if defined(TFM_MUL8) +#if defined(TFM_MUL8) && FP_SIZE >= 16 #include "fp_mul_comba_8.i" #endif -#if defined(TFM_MUL9) +#if defined(TFM_MUL9) && FP_SIZE >= 18 #include "fp_mul_comba_9.i" #endif -#if defined(TFM_MUL12) +#if defined(TFM_MUL12) && FP_SIZE >= 24 #include "fp_mul_comba_12.i" #endif -#if defined(TFM_MUL17) +#if defined(TFM_MUL17) && FP_SIZE >= 34 #include "fp_mul_comba_17.i" #endif -#if defined(TFM_MUL20) +#if defined(TFM_MUL20) && FP_SIZE >= 40 #include "fp_mul_comba_20.i" #endif -#if defined(TFM_MUL24) +#if defined(TFM_MUL24) && FP_SIZE >= 48 #include "fp_mul_comba_24.i" #endif -#if defined(TFM_MUL28) +#if defined(TFM_MUL28) && FP_SIZE >= 56 #include "fp_mul_comba_28.i" #endif -#if defined(TFM_MUL32) +#if defined(TFM_MUL32) && FP_SIZE >= 64 #include "fp_mul_comba_32.i" #endif -#if defined(TFM_MUL48) +#if defined(TFM_MUL48) && FP_SIZE >= 96 #include "fp_mul_comba_48.i" #endif -#if defined(TFM_MUL64) +#if defined(TFM_MUL64) && FP_SIZE >= 128 #include "fp_mul_comba_64.i" #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c index e3d9ff44b..c4e60043f 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c @@ -1,8 +1,8 @@ /* asn.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,21 +16,47 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include -#ifndef NO_ASN +/* +ASN Options: + * NO_ASN_TIME: Disables time parts of the ASN code for systems without an RTC + or wishing to save space. + * IGNORE_NAME_CONSTRAINTS: Skip ASN name checks. + * 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_ASN_STRICT: Disable strict RFC compliance checks to + restore 3.13.0 behavior. + * 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_SMALL_CERT_VERIFY: Verify the certificate signature without using + DecodedCert. Doubles up on some code but allows smaller dynamic memory + usage. + * WOLFSSL_NO_OCSP_DATE_CHECK: Disable date checks for OCSP responses. This + may be required when the system's real-time clock is not very accurate. + It is recommended to enforce the nonce check instead if possible. + * WOLFSSL_FORCE_OCSP_NONCE_CHECK: Require nonces to be available in OCSP + responses. The nonces are optional and may not be supported by all + responders. If it can be ensured that the used responder sends nonces this + option may improve security. +*/ -#ifdef HAVE_RTP_SYS - #include "os.h" /* dc_rtc_api needs */ - #include "dc_rtc_api.h" /* to get current time */ -#endif +#ifndef NO_ASN #include #include @@ -39,17 +65,25 @@ #include #include #include +#include +#include #include #include - +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif #ifndef NO_RC4 #include #endif #ifdef HAVE_NTRU - #include "ntru_crypto.h" + #include "libntruencrypt/ntru_crypto.h" #endif #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) @@ -64,12 +98,27 @@ #include #endif -#ifdef WOLFSSL_DEBUG_ENCODING - #ifdef FREESCALE_MQX - #include - #else - #include - #endif +#ifdef HAVE_ED25519 + #include +#endif + +#ifdef HAVE_ED448 + #include +#endif + +#ifndef NO_RSA + #include +#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL) +extern int wc_InitRsaHw(RsaKey* key); +#endif +#endif + +#ifdef WOLF_CRYPTO_CB + #include +#endif + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + #include #endif #ifdef _MSC_VER @@ -77,416 +126,82 @@ #pragma warning(disable: 4996) #endif +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } -#ifndef TRUE - #define TRUE 1 -#endif -#ifndef FALSE - #define FALSE 0 -#endif - - -#ifdef HAVE_RTP_SYS - /* uses parital structures */ - #define XTIME(tl) (0) - #define XGMTIME(c, t) my_gmtime((c)) - #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) -#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)) - #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) -#elif defined(FREESCALE_MQX) - #define XTIME(t1) mqx_time((t1)) - #define XGMTIME(c, t) mqx_gmtime((c), (t)) - #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) -#elif defined(WOLFSSL_MDK_ARM) - #if defined(WOLFSSL_MDK5) - #include "cmsis_os.h" - #else - #include - #endif - #undef RNG - #include "wolfssl_MDK_ARM.h" - #undef RNG - #define RNG wolfSSL_RNG /*for avoiding name conflict in "stm32f2xx.h" */ - #define XTIME(tl) (0) - #define XGMTIME(c, t) wolfssl_MDK_gmtime((c)) - #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) -#elif defined(USER_TIME) - /* user time, and gmtime compatible functions, there is a gmtime - implementation here that WINCE uses, so really just need some ticks - since the EPOCH - */ - - 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 */ +#if defined(HAVE_SELFTEST) || ( !defined(NO_SKID) && \ + ( !defined(HAVE_FIPS) || \ + !defined(HAVE_FIPS_VERSION) )) + #ifndef WOLFSSL_AES_KEY_SIZE_ENUM + #define WOLFSSL_AES_KEY_SIZE_ENUM + enum Asn_Misc { + AES_IV_SIZE = 16, + AES_128_KEY_SIZE = 16, + AES_192_KEY_SIZE = 24, + AES_256_KEY_SIZE = 32 }; - typedef long time_t; - - /* forward declaration */ - struct tm* gmtime(const time_t* timer); - extern time_t XTIME(time_t * timer); - - #define XGMTIME(c, t) gmtime((c)) - #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) - - #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) - /* user would like to override time() and gmtime() functionality */ - - #ifndef HAVE_TIME_T_TYPE - typedef long time_t; #endif - extern time_t XTIME(time_t * timer); - - #ifndef HAVE_TM_TYPE - 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 - extern struct tm* XGMTIME(const time_t* timer, struct tm* tmp); - - #ifndef HAVE_VALIDATE_DATE - #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) - #endif -#else - /* default */ - /* uses complete facility */ - #include - #define XTIME(tl) time((tl)) - #define XGMTIME(c, t) gmtime((c)) - #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) #endif - - -#ifdef _WIN32_WCE -/* no time() or gmtime() even though in time.h header?? */ - -#include - - -time_t 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( _WIN32_WCE ) || defined( USER_TIME ) - -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 /* _WIN32_WCE || USER_TIME */ - - -#ifdef HAVE_RTP_SYS - -#define YEAR0 1900 - -struct tm* my_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; +#ifdef WOLFSSL_RENESAS_TSIP_TLS +void tsip_inform_key_position(const word32 key_n_start, + const word32 key_n_len, const word32 key_e_start, + const word32 key_e_len); +int tsip_tls_CertVerify(const byte *cert, word32 certSz, + const byte *signature, word32 sigSz, + word32 key_n_start, word32 key_n_len, + word32 key_e_start, word32 key_e_len, + byte *tsip_encRsaKeyIdx); #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 */ - - -#ifdef FREESCALE_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; -} - -/* CodeWarrior GCC toolchain only has gmtime_r(), no gmtime() */ -struct tm* mqx_gmtime(const time_t* clock, struct tm* tmpTime) -{ - return gmtime_r(clock, tmpTime); -} - -#endif /* FREESCALE_MQX */ - -#ifdef 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 b - 0x30; -} - - -/* two byte date/time, add to value */ -static INLINE void GetTime(int* value, const byte* date, int* idx) -{ - int i = *idx; - - *value += btoi(date[i++]) * 10; - *value += btoi(date[i++]); - - *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 */ - - -WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, +int GetLength(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) +{ + return GetLength_ex(input, inOutIdx, len, maxIdx, 1); +} + + +/* give option to check length value found against index. 1 to check 0 to not */ +int GetLength_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check) { int length = 0; - word32 i = *inOutIdx; + word32 idx = *inOutIdx; byte b; *len = 0; /* default length */ - if ( (i+1) > maxIdx) { /* for first read */ + if ((idx + 1) > maxIdx) { /* for first read */ WOLFSSL_MSG("GetLength bad index on input"); return BUFFER_E; } - b = input[i++]; - if (b >= ASN_LONG_LENGTH) { + b = input[idx++]; + if (b >= ASN_LONG_LENGTH) { word32 bytes = b & 0x7F; - if ( (i+bytes) > maxIdx) { /* for reading bytes */ + if ((idx + bytes) > maxIdx) { /* for reading bytes */ WOLFSSL_MSG("GetLength bad long length"); return BUFFER_E; } + if (bytes > sizeof(length)) { + return ASN_PARSE_E; + } while (bytes--) { - b = input[i++]; + b = input[idx++]; length = (length << 8) | b; } + if (length < 0) { + return ASN_PARSE_E; + } } else length = b; - - if ( (i+length) > maxIdx) { /* for user of length */ + + if (check && (idx + length) > maxIdx) { /* for user of length */ WOLFSSL_MSG("GetLength value exceeds buffer length"); return BUFFER_E; } - *inOutIdx = i; + *inOutIdx = idx; if (length > 0) *len = length; @@ -494,48 +209,529 @@ WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, } -WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, - word32 maxIdx) +/* input : buffer to read from + * inOutIdx : index to start reading from, gets advanced by 1 if successful + * maxIdx : maximum index value + * tag : ASN tag value found + * + * returns 0 on success + */ +int GetASNTag(const byte* input, word32* inOutIdx, byte* tag, word32 maxIdx) { - int length = -1; - word32 idx = *inOutIdx; + word32 idx; - if (input[idx++] != (ASN_SEQUENCE | ASN_CONSTRUCTED) || - GetLength(input, &idx, &length, maxIdx) < 0) - return ASN_PARSE_E; + if (tag == NULL || inOutIdx == NULL || input == NULL) { + return BAD_FUNC_ARG; + } - *len = length; - *inOutIdx = idx; + idx = *inOutIdx; + if (idx + ASN_TAG_SZ > maxIdx) { + WOLFSSL_MSG("Buffer too small for ASN tag"); + return BUFFER_E; + } - return length; + *tag = input[idx]; + *inOutIdx = idx + ASN_TAG_SZ; + return 0; } -WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, - word32 maxIdx) -{ - int length = -1; - word32 idx = *inOutIdx; - - if (input[idx++] != (ASN_SET | ASN_CONSTRUCTED) || - GetLength(input, &idx, &length, maxIdx) < 0) - return ASN_PARSE_E; - - *len = length; - *inOutIdx = idx; - - return length; -} - - -/* winodws header clash for WinCE using GetVersion */ -WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, int* version) +static int GetASNHeader_ex(const byte* input, byte tag, word32* inOutIdx, int* len, + word32 maxIdx, int check) { word32 idx = *inOutIdx; + byte tagFound; + int length; - WOLFSSL_ENTER("GetMyVersion"); + if (GetASNTag(input, &idx, &tagFound, maxIdx) != 0) + return ASN_PARSE_E; - if (input[idx++] != ASN_INTEGER) + if (tagFound != tag) + return ASN_PARSE_E; + + if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0) + return ASN_PARSE_E; + + *len = length; + *inOutIdx = idx; + return length; +} + + +/* 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) +{ + return GetASNHeader_ex(input, tag, inOutIdx, len, maxIdx, 1); +} + +static int GetHeader(const byte* input, byte* tag, word32* inOutIdx, int* len, + word32 maxIdx, int check) +{ + word32 idx = *inOutIdx; + int length; + + if ((idx + 1) > maxIdx) + return BUFFER_E; + + *tag = input[idx++]; + + if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0) + return ASN_PARSE_E; + + *len = length; + *inOutIdx = idx; + return length; +} + +int GetSequence(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetASNHeader(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx); +} + + +int GetSequence_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check) +{ + return GetASNHeader_ex(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx, check); +} + + +int GetSet(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetASNHeader(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx); +} + + +int GetSet_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check) +{ + return GetASNHeader_ex(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx, check); +} + +/* 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. + */ +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; + } + } + + 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 (GetASNTag(input, &idx, &b, maxIdx) != 0) + return ASN_PARSE_E; + if (b != 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(NO_SHA) +static const char sigSha1wDsaName[] = "SHAwDSA"; +#endif /* NO_DSA */ +#ifndef NO_RSA +#ifdef WOLFSSL_MD2 + static const char sigMd2wRsaName[] = "md2WithRSAEncryption"; +#endif +#ifndef NO_MD5 + static const char sigMd5wRsaName[] = "md5WithRSAEncryption"; +#endif +#ifndef NO_SHA + static const char sigSha1wRsaName[] = "sha1WithRSAEncryption"; +#endif +#ifdef WOLFSSL_SHA224 + static const char sigSha224wRsaName[] = "sha224WithRSAEncryption"; +#endif +#ifndef NO_SHA256 + static const char sigSha256wRsaName[] = "sha256WithRSAEncryption"; +#endif +#ifdef WOLFSSL_SHA384 + static const char sigSha384wRsaName[] = "sha384WithRSAEncryption"; +#endif +#ifdef WOLFSSL_SHA512 + static const char sigSha512wRsaName[] = "sha512WithRSAEncryption"; +#endif +#endif /* NO_RSA */ +#ifdef HAVE_ECC +#ifndef NO_SHA + static const char sigSha1wEcdsaName[] = "SHAwECDSA"; +#endif +#ifdef WOLFSSL_SHA224 + static const char sigSha224wEcdsaName[] = "SHA224wECDSA"; +#endif +#ifndef NO_SHA256 + static const char sigSha256wEcdsaName[] = "SHA256wECDSA"; +#endif +#ifdef WOLFSSL_SHA384 + static const char sigSha384wEcdsaName[] = "SHA384wECDSA"; +#endif +#ifdef WOLFSSL_SHA512 + static const char sigSha512wEcdsaName[] = "SHA512wECDSA"; +#endif +#endif /* HAVE_ECC */ +static const char sigUnknownName[] = "Unknown"; + + +/* Get the human readable string for a signature type + * + * oid Oid value for signature + */ +const char* GetSigName(int oid) { + switch (oid) { + #if !defined(NO_DSA) && !defined(NO_SHA) + case CTC_SHAwDSA: + return sigSha1wDsaName; + #endif /* NO_DSA && NO_SHA */ + #ifndef NO_RSA + #ifdef WOLFSSL_MD2 + case CTC_MD2wRSA: + return sigMd2wRsaName; + #endif + #ifndef NO_MD5 + case CTC_MD5wRSA: + return sigMd5wRsaName; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + return sigSha1wRsaName; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wRSA: + return sigSha224wRsaName; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + return sigSha256wRsaName; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wRSA: + return sigSha384wRsaName; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + return sigSha512wRsaName; + #endif + #endif /* NO_RSA */ + #ifdef HAVE_ECC + #ifndef NO_SHA + case CTC_SHAwECDSA: + return sigSha1wEcdsaName; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wECDSA: + return sigSha224wEcdsaName; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wECDSA: + return sigSha256wEcdsaName; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wECDSA: + return sigSha384wEcdsaName; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wECDSA: + return sigSha512wEcdsaName; + #endif + #endif /* HAVE_ECC */ + default: + return sigUnknownName; + } +} + + +#if !defined(NO_DSA) || defined(HAVE_ECC) || !defined(NO_CERTS) || \ + (!defined(NO_RSA) && \ + (defined(WOLFSSL_CERT_GEN) || \ + ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !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; + + if (output) + output[idx] = ASN_INTEGER; + idx++; + if (firstByte & 0x80) + len++; + idx += SetLength(len, output ? output + idx : NULL); + if (firstByte & 0x80) { + if (output) + output[idx] = 0x00; + idx++; + } + + return idx; +} +#endif + +#if !defined(NO_DSA) || defined(HAVE_ECC) || (defined(WOLFSSL_CERT_GEN) && \ + !defined(NO_RSA)) || ((defined(WOLFSSL_KEY_GEN) || \ + defined(OPENSSL_EXTRA)) && !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; + + if (output) { + 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) || defined(OPENSSL_EXTRA)) +/* 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(void* 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; + + if (output) { + 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 */ +int GetMyVersion(const byte* input, word32* inOutIdx, + int* version, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte tag; + + if ((idx + MIN_VERSION_SZ) > maxIdx) + return ASN_PARSE_E; + + if (GetASNTag(input, &idx, &tag, maxIdx) != 0) + return ASN_PARSE_E; + + if (tag != ASN_INTEGER) return ASN_PARSE_E; if (input[idx++] != 0x01) @@ -550,20 +746,31 @@ WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, int* version #ifndef NO_PWDBASED /* Get small count integer, 32 bits or less */ -static int GetShortInt(const byte* input, word32* inOutIdx, int* number) +int GetShortInt(const byte* input, word32* inOutIdx, int* number, word32 maxIdx) { word32 idx = *inOutIdx; word32 len; + byte tag; *number = 0; - if (input[idx++] != ASN_INTEGER) + /* check for type and length bytes */ + if ((idx + 2) > maxIdx) + return BUFFER_E; + + if (GetASNTag(input, &idx, &tag, maxIdx) != 0) + return ASN_PARSE_E; + + if (tag != ASN_INTEGER) return ASN_PARSE_E; len = input[idx++]; if (len > 4) return ASN_PARSE_E; + if (len + idx > maxIdx) + return ASN_PARSE_E; + while (len--) { *number = *number << 8 | input[idx++]; } @@ -572,18 +779,68 @@ static int GetShortInt(const byte* input, word32* inOutIdx, int* number) return *number; } -#endif /* !NO_PWDBASED */ -/* May not have one, not an error */ -static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version) +/* Set small integer, 32 bits or less. DER encoding with no leading 0s + * returns total amount written including ASN tag and length byte on success */ +int SetShortInt(byte* input, word32* inOutIdx, word32 number, word32 maxIdx) { word32 idx = *inOutIdx; + word32 len = 0; + int i; + byte ar[MAX_LENGTH_SZ]; + + /* check for room for type and length bytes */ + if ((idx + 2) > maxIdx) + return BUFFER_E; + + input[idx++] = ASN_INTEGER; + idx++; /* place holder for length byte */ + if (MAX_LENGTH_SZ + idx > maxIdx) + return ASN_PARSE_E; + + /* find first non zero byte */ + XMEMSET(ar, 0, MAX_LENGTH_SZ); + c32toa(number, ar); + for (i = 0; i < MAX_LENGTH_SZ; i++) { + if (ar[i] != 0) { + break; + } + } + + /* handle case of 0 */ + if (i == MAX_LENGTH_SZ) { + input[idx++] = 0; len++; + } + + for (; i < MAX_LENGTH_SZ && idx < maxIdx; i++) { + input[idx++] = ar[i]; len++; + } + + /* jump back to beginning of input buffer using unaltered inOutIdx value + * and set number of bytes for integer, then update the index value */ + input[*inOutIdx + 1] = (byte)len; + *inOutIdx = idx; + + return len + 2; /* size of integer bytes plus ASN TAG and length byte */ +} +#endif /* !NO_PWDBASED */ + +/* May not have one, not an error */ +static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version, + word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte tag; WOLFSSL_ENTER("GetExplicitVersion"); - if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { - *inOutIdx = ++idx; /* eat header */ - return GetMyVersion(input, inOutIdx, version); + + if (GetASNTag(input, &idx, &tag, maxIdx) != 0) + return ASN_PARSE_E; + + if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + *inOutIdx = ++idx; /* skip header */ + return GetMyVersion(input, inOutIdx, version, maxIdx); } /* go back as is */ @@ -592,257 +849,2267 @@ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version) return 0; } - -WOLFSSL_LOCAL 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 i = *inOutIdx; - byte b = input[i++]; + word32 idx = *inOutIdx; + int ret; int length; - if (b != ASN_INTEGER) - return ASN_PARSE_E; - - if (GetLength(input, &i, &length, maxIdx) < 0) - return ASN_PARSE_E; - - if ( (b = input[i++]) == 0x00) - length--; - else - i--; + ret = GetASNInt(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; if (mp_init(mpi) != MP_OKAY) return MP_INIT_E; - if (mp_read_unsigned_bin(mpi, (byte*)input + i, length) != 0) { + if (mp_read_unsigned_bin(mpi, (byte*)input + idx, length) != 0) { mp_clear(mpi); return ASN_GETINT_E; } - *inOutIdx = i + length; +#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; } - -static int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, - word32 maxIdx) +#if (!defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM)) \ + || defined(WOLFSSL_RSA_PUBLIC_ONLY) || (!defined(NO_DSA) && defined(WOLFSSL_QT)) +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) +static int SkipInt(const byte* input, word32* inOutIdx, word32 maxIdx) { + word32 idx = *inOutIdx; + int ret; + int length; + + ret = GetASNInt(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; + + *inOutIdx = idx + length; + + return 0; +} +#endif +#endif + +static int CheckBitString(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int zeroBits, byte* unusedBits) +{ + word32 idx = *inOutIdx; int length; - word32 i = *inOutIdx; byte b; - *oid = 0; - - b = input[i++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; - - if (GetLength(input, &i, &length, maxIdx) < 0) + + if (GetASNTag(input, &idx, &b, maxIdx) != 0) { + return ASN_BITSTR_E; + } + + if (b != ASN_BIT_STRING) { + return ASN_BITSTR_E; + } + + if (GetLength(input, &idx, &length, maxIdx) < 0) return ASN_PARSE_E; - - while(length--) - *oid += input[i++]; - /* just sum it up for now */ - - *inOutIdx = i; - + + /* extra sanity check that length is greater than 0 */ + if (length <= 0) { + WOLFSSL_MSG("Error length was 0 in CheckBitString"); + return BUFFER_E; + } + + if (idx + 1 > maxIdx) { + WOLFSSL_MSG("Attempted buffer read larger than input buffer"); + return BUFFER_E; + } + + 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; } +/* RSA (with CertGen or KeyGen) OR ECC OR ED25519 OR ED448 (with CertGen or + * KeyGen) */ +#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && \ + (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) || \ + (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)) || \ + ((defined(HAVE_ED25519) || defined(HAVE_ED448)) && \ + (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) -WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, - word32 maxIdx) +/* 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. + */ +word32 SetBitString(word32 len, byte unusedBits, byte* output) +{ + word32 idx = 0; + + if (output) + output[idx] = ASN_BIT_STRING; + idx++; + + idx += SetLength(len + 1, output ? output + idx : NULL); + if (output) + output[idx] = unusedBits; + idx++; + + return idx; +} +#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 || HAVE_ED448 */ + +#ifdef ASN_BER_TO_DER +/* Pull informtation from the ASN.1 BER encoded item header */ +static int GetBerHeader(const byte* data, word32* idx, word32 maxIdx, + byte* pTag, word32* pLen, int* indef) +{ + int len = 0; + byte tag; + word32 i = *idx; + + *indef = 0; + + /* Check there is enough data for a minimal header */ + if (i + 2 > maxIdx) { + return ASN_PARSE_E; + } + + /* Retrieve tag */ + tag = data[i++]; + + /* Indefinite length handled specially */ + if (data[i] == 0x80) { + /* Check valid tag for indefinite */ + if (((tag & 0xc0) == 0) && ((tag & ASN_CONSTRUCTED) == 0x00)) { + return ASN_PARSE_E; + } + i++; + *indef = 1; + } + else if (GetLength(data, &i, &len, maxIdx) < 0) { + return ASN_PARSE_E; + } + + /* Return tag, length and index after BER item header */ + *pTag = tag; + *pLen = len; + *idx = i; + return 0; +} + +#ifndef INDEF_ITEMS_MAX +#define INDEF_ITEMS_MAX 20 +#endif + +/* Indef length item data */ +typedef struct Indef { + word32 start; + int depth; + int headerLen; + word32 len; +} Indef; + +/* Indef length items */ +typedef struct IndefItems +{ + Indef len[INDEF_ITEMS_MAX]; + int cnt; + int idx; + int depth; +} IndefItems; + + +/* Get header length of current item */ +static int IndefItems_HeaderLen(IndefItems* items) +{ + return items->len[items->idx].headerLen; +} + +/* Get data length of current item */ +static word32 IndefItems_Len(IndefItems* items) +{ + return items->len[items->idx].len; +} + +/* Add a indefinite length item */ +static int IndefItems_AddItem(IndefItems* items, word32 start) +{ + int ret = 0; + int i; + + if (items->cnt == INDEF_ITEMS_MAX) { + ret = MEMORY_E; + } + else { + i = items->cnt++; + items->len[i].start = start; + items->len[i].depth = items->depth++; + items->len[i].headerLen = 1; + items->len[i].len = 0; + items->idx = i; + } + + return ret; +} + +/* Increase data length of current item */ +static void IndefItems_AddData(IndefItems* items, word32 length) +{ + items->len[items->idx].len += length; +} + +/* Update header length of current item to reflect data length */ +static void IndefItems_UpdateHeaderLen(IndefItems* items) +{ + items->len[items->idx].headerLen += + SetLength(items->len[items->idx].len, NULL); +} + +/* Go to indefinite parent of current item */ +static void IndefItems_Up(IndefItems* items) +{ + int i; + int depth = items->len[items->idx].depth - 1; + + for (i = items->cnt - 1; i >= 0; i--) { + if (items->len[i].depth == depth) { + break; + } + } + items->idx = i; + items->depth = depth + 1; +} + +/* Calculate final length by adding length of indefinite child items */ +static void IndefItems_CalcLength(IndefItems* items) +{ + int i; + int idx = items->idx; + + for (i = idx + 1; i < items->cnt; i++) { + if (items->len[i].depth == items->depth) { + items->len[idx].len += items->len[i].headerLen; + items->len[idx].len += items->len[i].len; + } + } + items->len[idx].headerLen += SetLength(items->len[idx].len, NULL); +} + +/* Add more data to indefinite length item */ +static void IndefItems_MoreData(IndefItems* items, word32 length) +{ + if (items->cnt > 0 && items->idx >= 0) { + items->len[items->idx].len += length; + } +} + +/* Convert a BER encoding with indefinite length items to DER. + * + * ber BER encoded data. + * berSz Length of BER encoded data. + * der Buffer to hold DER encoded version of data. + * NULL indicates only the length is required. + * derSz The size of the buffer to hold the DER encoded data. + * Will be set if der is NULL, otherwise the value is checked as der is + * filled. + * returns ASN_PARSE_E if the BER data is invalid and BAD_FUNC_ARG if ber or + * derSz are NULL. + */ +int wc_BerToDer(const byte* ber, word32 berSz, byte* der, word32* derSz) +{ + int ret = 0; + word32 i, j; +#ifdef WOLFSSL_SMALL_STACK + IndefItems* indefItems = NULL; +#else + IndefItems indefItems[1]; +#endif + byte tag, basic; + word32 length; + int indef; + + if (ber == NULL || derSz == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + indefItems = XMALLOC(sizeof(IndefItems), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (indefItems == NULL) { + ret = MEMORY_E; + goto end; + } +#endif + + XMEMSET(indefItems, 0, sizeof(*indefItems)); + + /* Calculate indefinite item lengths */ + for (i = 0; i < berSz; ) { + word32 start = i; + + /* Get next BER item */ + ret = GetBerHeader(ber, &i, berSz, &tag, &length, &indef); + if (ret != 0) { + goto end; + } + + if (indef) { + /* Indefinite item - add to list */ + ret = IndefItems_AddItem(indefItems, i); + if (ret != 0) { + goto end; + } + + if ((tag & 0xC0) == 0 && + tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) && + tag != (ASN_SET | ASN_CONSTRUCTED)) { + /* Constructed basic type - get repeating tag */ + basic = tag & (~ASN_CONSTRUCTED); + + /* Add up lengths of each item below */ + for (; i < berSz; ) { + /* Get next BER_item */ + ret = GetBerHeader(ber, &i, berSz, &tag, &length, &indef); + if (ret != 0) { + goto end; + } + + /* End of content closes item */ + if (tag == ASN_EOC) { + /* Must be zero length */ + if (length != 0) { + ret = ASN_PARSE_E; + goto end; + } + break; + } + + /* Must not be indefinite and tag must match parent */ + if (indef || tag != basic) { + ret = ASN_PARSE_E; + goto end; + } + + /* Add to length */ + IndefItems_AddData(indefItems, length); + /* Skip data */ + i += length; + } + + /* Ensure we got an EOC and not end of data */ + if (tag != ASN_EOC) { + ret = ASN_PARSE_E; + goto end; + } + + /* Set the header length to include the length field */ + IndefItems_UpdateHeaderLen(indefItems); + /* Go to indefinte parent item */ + IndefItems_Up(indefItems); + } + } + else if (tag == ASN_EOC) { + /* End-of-content must be 0 length */ + if (length != 0) { + ret = ASN_PARSE_E; + goto end; + } + /* Check there is an item to close - missing EOC */ + if (indefItems->depth == 0) { + ret = ASN_PARSE_E; + goto end; + } + + /* Finish calculation of data length for indefinite item */ + IndefItems_CalcLength(indefItems); + /* Go to indefinte parent item */ + IndefItems_Up(indefItems); + } + else { + /* Known length item to add in - make sure enough data for it */ + if (i + length > berSz) { + ret = ASN_PARSE_E; + goto end; + } + + /* Include all data - can't have indefinite inside definite */ + i += length; + /* Add entire item to current indefinite item */ + IndefItems_MoreData(indefItems, i - start); + } + } + /* Check we had a EOC for each indefinite item */ + if (indefItems->depth != 0) { + ret = ASN_PARSE_E; + goto end; + } + + /* Write out DER */ + + j = 0; + /* Reset index */ + indefItems->idx = 0; + for (i = 0; i < berSz; ) { + word32 start = i; + + /* Get item - checked above */ + (void)GetBerHeader(ber, &i, berSz, &tag, &length, &indef); + if (indef) { + if (der != NULL) { + /* Check enough space for header */ + if (j + IndefItems_HeaderLen(indefItems) > *derSz) { + ret = BUFFER_E; + goto end; + } + + if ((tag & 0xC0) == 0 && + tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) && + tag != (ASN_SET | ASN_CONSTRUCTED)) { + /* Remove constructed tag for basic types */ + tag &= ~ASN_CONSTRUCTED; + } + /* Add tag and length */ + der[j] = tag; + (void)SetLength(IndefItems_Len(indefItems), der + j + 1); + } + /* Add header length of indefinite item */ + j += IndefItems_HeaderLen(indefItems); + + if ((tag & 0xC0) == 0 && + tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) && + tag != (ASN_SET | ASN_CONSTRUCTED)) { + /* For basic type - get each child item and add data */ + for (; i < berSz; ) { + (void)GetBerHeader(ber, &i, berSz, &tag, &length, &indef); + if (tag == ASN_EOC) { + break; + } + if (der != NULL) { + if (j + length > *derSz) { + ret = BUFFER_E; + goto end; + } + XMEMCPY(der + j, ber + i, length); + } + j += length; + i += length; + } + } + + /* Move to next indef item in list */ + indefItems->idx++; + } + else if (tag == ASN_EOC) { + /* End-Of-Content is not written out in DER */ + } + else { + /* Write out definite length item as is. */ + i += length; + if (der != NULL) { + /* Ensure space for item */ + if (j + i - start > *derSz) { + ret = BUFFER_E; + goto end; + } + /* Copy item as is */ + XMEMCPY(der + j, ber + start, i - start); + } + j += i - start; + } + } + + /* Return the length of the DER encoded ASN.1 */ + *derSz = j; + if (der == NULL) { + ret = LENGTH_ONLY_E; + } +end: +#ifdef WOLFSSL_SMALL_STACK + if (indefItems != NULL) { + XFREE(indefItems, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + return ret; +} +#endif + +#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) + +#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || \ + defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + +#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 || defined(HAVE_ED448) */ +#endif /* WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN */ + + + +/* hashType */ +#ifdef WOLFSSL_MD2 + static const byte hashMd2hOid[] = {42, 134, 72, 134, 247, 13, 2, 2}; +#endif +#ifndef NO_MD5 + static const byte hashMd5hOid[] = {42, 134, 72, 134, 247, 13, 2, 5}; +#endif +#ifndef NO_SHA + static const byte hashSha1hOid[] = {43, 14, 3, 2, 26}; +#endif +#ifdef WOLFSSL_SHA224 + static const byte hashSha224hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 4}; +#endif +#ifndef NO_SHA256 + static const byte hashSha256hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 1}; +#endif +#ifdef WOLFSSL_SHA384 + static const byte hashSha384hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 2}; +#endif +#ifdef WOLFSSL_SHA512 + static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3}; +#endif + +/* hmacType */ +#ifndef NO_HMAC + #ifdef WOLFSSL_SHA224 + static const byte hmacSha224Oid[] = {42, 134, 72, 134, 247, 13, 2, 8}; + #endif + #ifndef NO_SHA256 + static const byte hmacSha256Oid[] = {42, 134, 72, 134, 247, 13, 2, 9}; + #endif + #ifdef WOLFSSL_SHA384 + static const byte hmacSha384Oid[] = {42, 134, 72, 134, 247, 13, 2, 10}; + #endif + #ifdef WOLFSSL_SHA512 + static const byte hmacSha512Oid[] = {42, 134, 72, 134, 247, 13, 2, 11}; + #endif +#endif + +/* sigType */ +#if !defined(NO_DSA) && !defined(NO_SHA) + static const byte sigSha1wDsaOid[] = {42, 134, 72, 206, 56, 4, 3}; +#endif /* NO_DSA */ +#ifndef NO_RSA + #ifdef WOLFSSL_MD2 + static const byte sigMd2wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 2}; + #endif + #ifndef NO_MD5 + static const byte sigMd5wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 4}; + #endif + #ifndef NO_SHA + static const byte sigSha1wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 5}; + #endif + #ifdef WOLFSSL_SHA224 + static const byte sigSha224wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,14}; + #endif + #ifndef NO_SHA256 + static const byte sigSha256wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,11}; + #endif + #ifdef WOLFSSL_SHA384 + static const byte sigSha384wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,12}; + #endif + #ifdef WOLFSSL_SHA512 + static const byte sigSha512wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,13}; + #endif +#endif /* NO_RSA */ +#ifdef HAVE_ECC + #ifndef NO_SHA + static const byte sigSha1wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 1}; + #endif + #ifdef WOLFSSL_SHA224 + static const byte sigSha224wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 1}; + #endif + #ifndef NO_SHA256 + static const byte sigSha256wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 2}; + #endif + #ifdef WOLFSSL_SHA384 + static const byte sigSha384wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 3}; + #endif + #ifdef WOLFSSL_SHA512 + static const byte sigSha512wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 4}; + #endif +#endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + static const byte sigEd25519Oid[] = {43, 101, 112}; +#endif /* HAVE_ED25519 */ +#ifdef HAVE_ED448 + static const byte sigEd448Oid[] = {43, 101, 113}; +#endif /* HAVE_ED448 */ + +/* keyType */ +#ifndef NO_DSA + static const byte keyDsaOid[] = {42, 134, 72, 206, 56, 4, 1}; +#endif /* NO_DSA */ +#ifndef NO_RSA + static const byte keyRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 1}; +#endif /* NO_RSA */ +#ifdef HAVE_NTRU + static const byte keyNtruOid[] = {43, 6, 1, 4, 1, 193, 22, 1, 1, 1, 1}; +#endif /* HAVE_NTRU */ +#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 */ +#ifdef HAVE_ED448 + static const byte keyEd448Oid[] = {43, 101, 113}; +#endif /* HAVE_ED448 */ +#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) + static const byte keyDhOid[] = {42, 134, 72, 134, 247, 13, 1, 3, 1}; +#endif /* ! NO_DH ... */ + +/* curveType */ +#ifdef HAVE_ECC + /* See "ecc_sets" table in ecc.c */ +#endif /* HAVE_ECC */ + +#ifdef HAVE_AES_CBC +/* blkType */ + #ifdef WOLFSSL_AES_128 + static const byte blkAes128CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 2}; + #endif + #ifdef WOLFSSL_AES_192 + static const byte blkAes192CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 22}; + #endif + #ifdef WOLFSSL_AES_256 + static const byte blkAes256CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 42}; + #endif +#endif /* HAVE_AES_CBC */ +#ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + static const byte blkAes128GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 6}; + #endif + #ifdef WOLFSSL_AES_192 + static const byte blkAes192GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 26}; + #endif + #ifdef WOLFSSL_AES_256 + static const byte blkAes256GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 46}; + #endif +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + static const byte blkAes128CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 7}; + #endif + #ifdef WOLFSSL_AES_192 + static const byte blkAes192CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 27}; + #endif + #ifdef WOLFSSL_AES_256 + static const byte blkAes256CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 47}; + #endif +#endif /* HAVE_AESCCM */ + +#ifndef NO_DES3 + static const byte blkDesCbcOid[] = {43, 14, 3, 2, 7}; + static const byte blkDes3CbcOid[] = {42, 134, 72, 134, 247, 13, 3, 7}; +#endif + +/* keyWrapType */ +#ifdef WOLFSSL_AES_128 + static const byte wrapAes128Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 5}; +#endif +#ifdef WOLFSSL_AES_192 + static const byte wrapAes192Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 25}; +#endif +#ifdef WOLFSSL_AES_256 + static const byte wrapAes256Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 45}; +#endif +#ifdef HAVE_PKCS7 +/* From RFC 3211 */ +static const byte wrapPwriKekOid[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3,9}; +#endif + +/* cmsKeyAgreeType */ +#ifndef NO_SHA + static const byte dhSinglePass_stdDH_sha1kdf_Oid[] = + {43, 129, 5, 16, 134, 72, 63, 0, 2}; +#endif +#ifdef WOLFSSL_SHA224 + static const byte dhSinglePass_stdDH_sha224kdf_Oid[] = {43, 129, 4, 1, 11, 0}; +#endif +#ifndef NO_SHA256 + static const byte dhSinglePass_stdDH_sha256kdf_Oid[] = {43, 129, 4, 1, 11, 1}; +#endif +#ifdef WOLFSSL_SHA384 + static const byte dhSinglePass_stdDH_sha384kdf_Oid[] = {43, 129, 4, 1, 11, 2}; +#endif +#ifdef WOLFSSL_SHA512 + static const byte dhSinglePass_stdDH_sha512kdf_Oid[] = {43, 129, 4, 1, 11, 3}; +#endif + +/* ocspType */ +#ifdef HAVE_OCSP + static const byte ocspBasicOid[] = {43, 6, 1, 5, 5, 7, 48, 1, 1}; + static const byte ocspNonceOid[] = {43, 6, 1, 5, 5, 7, 48, 1, 2}; +#endif /* HAVE_OCSP */ + +/* certExtType */ +static const byte extBasicCaOid[] = {85, 29, 19}; +static const byte extAltNamesOid[] = {85, 29, 17}; +static const byte extCrlDistOid[] = {85, 29, 31}; +static const byte extAuthInfoOid[] = {43, 6, 1, 5, 5, 7, 1, 1}; +static const byte extAuthKeyOid[] = {85, 29, 35}; +static const byte extSubjKeyOid[] = {85, 29, 14}; +static const byte extCertPolicyOid[] = {85, 29, 32}; +static const byte extKeyUsageOid[] = {85, 29, 15}; +static const byte extInhibitAnyOid[] = {85, 29, 54}; +static const byte extExtKeyUsageOid[] = {85, 29, 37}; +#ifndef IGNORE_NAME_CONSTRAINTS + static const byte extNameConsOid[] = {85, 29, 30}; +#endif + +/* certAuthInfoType */ +#ifdef HAVE_OCSP + static const byte extAuthInfoOcspOid[] = {43, 6, 1, 5, 5, 7, 48, 1}; +#endif +static const byte extAuthInfoCaIssuerOid[] = {43, 6, 1, 5, 5, 7, 48, 2}; + +/* certPolicyType */ +static const byte extCertPolicyAnyOid[] = {85, 29, 32, 0}; + +/* certKeyUseType */ +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 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}; + +/* PKCS5 */ +#if !defined(NO_DES3) && !defined(NO_SHA) +static const byte pbeSha1Des[] = {42, 134, 72, 134, 247, 13, 1, 5, 10}; +#endif +static const byte pbes2[] = {42, 134, 72, 134, 247, 13, 1, 5, 13}; + +/* PKCS12 */ +#if !defined(NO_RC4) && !defined(NO_SHA) +static const byte pbeSha1RC4128[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 1}; +#endif +#if !defined(NO_DES3) && !defined(NO_SHA) +static const byte pbeSha1Des3[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 3}; +#endif + +#ifdef HAVE_LIBZ +/* zlib compression */ +static const byte zlibCompress[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3, 8}; +#endif +#ifdef WOLFSSL_APACHE_HTTPD +/* tlsExtType */ +static const byte tlsFeatureOid[] = {43, 6, 1, 5, 5, 7, 1, 24}; +/* certNameType */ +static const byte dnsSRVOid[] = {43, 6, 1, 5, 5, 7, 8, 7}; +#endif + + +/* returns a pointer to the OID string on success and NULL on fail */ +const byte* OidFromId(word32 id, word32 type, word32* oidSz) +{ + const byte* oid = NULL; + + *oidSz = 0; + + switch (type) { + + case oidHashType: + switch (id) { + #ifdef WOLFSSL_MD2 + case MD2h: + oid = hashMd2hOid; + *oidSz = sizeof(hashMd2hOid); + break; + #endif + #ifndef NO_MD5 + case MD5h: + oid = hashMd5hOid; + *oidSz = sizeof(hashMd5hOid); + break; + #endif + #ifndef NO_SHA + case SHAh: + oid = hashSha1hOid; + *oidSz = sizeof(hashSha1hOid); + break; + #endif + #ifdef WOLFSSL_SHA224 + case SHA224h: + oid = hashSha224hOid; + *oidSz = sizeof(hashSha224hOid); + break; + #endif + #ifndef NO_SHA256 + case SHA256h: + oid = hashSha256hOid; + *oidSz = sizeof(hashSha256hOid); + break; + #endif + #ifdef WOLFSSL_SHA384 + case SHA384h: + oid = hashSha384hOid; + *oidSz = sizeof(hashSha384hOid); + break; + #endif + #ifdef WOLFSSL_SHA512 + case SHA512h: + oid = hashSha512hOid; + *oidSz = sizeof(hashSha512hOid); + break; + #endif + } + break; + + case oidSigType: + switch (id) { + #if !defined(NO_DSA) && !defined(NO_SHA) + case CTC_SHAwDSA: + oid = sigSha1wDsaOid; + *oidSz = sizeof(sigSha1wDsaOid); + break; + #endif /* NO_DSA */ + #ifndef NO_RSA + #ifdef WOLFSSL_MD2 + case CTC_MD2wRSA: + oid = sigMd2wRsaOid; + *oidSz = sizeof(sigMd2wRsaOid); + break; + #endif + #ifndef NO_MD5 + case CTC_MD5wRSA: + oid = sigMd5wRsaOid; + *oidSz = sizeof(sigMd5wRsaOid); + break; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + oid = sigSha1wRsaOid; + *oidSz = sizeof(sigSha1wRsaOid); + break; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wRSA: + oid = sigSha224wRsaOid; + *oidSz = sizeof(sigSha224wRsaOid); + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + oid = sigSha256wRsaOid; + *oidSz = sizeof(sigSha256wRsaOid); + break; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wRSA: + oid = sigSha384wRsaOid; + *oidSz = sizeof(sigSha384wRsaOid); + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + oid = sigSha512wRsaOid; + *oidSz = sizeof(sigSha512wRsaOid); + break; + #endif /* WOLFSSL_SHA512 */ + #endif /* NO_RSA */ + #ifdef HAVE_ECC + #ifndef NO_SHA + case CTC_SHAwECDSA: + oid = sigSha1wEcdsaOid; + *oidSz = sizeof(sigSha1wEcdsaOid); + break; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wECDSA: + oid = sigSha224wEcdsaOid; + *oidSz = sizeof(sigSha224wEcdsaOid); + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wECDSA: + oid = sigSha256wEcdsaOid; + *oidSz = sizeof(sigSha256wEcdsaOid); + break; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wECDSA: + oid = sigSha384wEcdsaOid; + *oidSz = sizeof(sigSha384wEcdsaOid); + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wECDSA: + oid = sigSha512wEcdsaOid; + *oidSz = sizeof(sigSha512wEcdsaOid); + break; + #endif + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case CTC_ED25519: + oid = sigEd25519Oid; + *oidSz = sizeof(sigEd25519Oid); + break; + #endif + #ifdef HAVE_ED448 + case CTC_ED448: + oid = sigEd448Oid; + *oidSz = sizeof(sigEd448Oid); + break; + #endif + default: + break; + } + break; + + case oidKeyType: + switch (id) { + #ifndef NO_DSA + case DSAk: + oid = keyDsaOid; + *oidSz = sizeof(keyDsaOid); + break; + #endif /* NO_DSA */ + #ifndef NO_RSA + case RSAk: + oid = keyRsaOid; + *oidSz = sizeof(keyRsaOid); + break; + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + case NTRUk: + oid = keyNtruOid; + *oidSz = sizeof(keyNtruOid); + break; + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ECDSAk: + oid = keyEcdsaOid; + *oidSz = sizeof(keyEcdsaOid); + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + oid = keyEd25519Oid; + *oidSz = sizeof(keyEd25519Oid); + break; + #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED448 + case ED448k: + oid = keyEd448Oid; + *oidSz = sizeof(keyEd448Oid); + break; + #endif /* HAVE_ED448 */ + #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) + case DHk: + oid = keyDhOid; + *oidSz = sizeof(keyDhOid); + break; + #endif /* ! NO_DH && (WOLFSSL_QT || OPENSSL_ALL */ + default: + break; + } + break; + + #ifdef HAVE_ECC + case oidCurveType: + if (wc_ecc_get_oid(id, &oid, oidSz) < 0) { + WOLFSSL_MSG("ECC OID not found"); + } + break; + #endif /* HAVE_ECC */ + + case oidBlkType: + switch (id) { + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + oid = blkAes128CbcOid; + *oidSz = sizeof(blkAes128CbcOid); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + oid = blkAes192CbcOid; + *oidSz = sizeof(blkAes192CbcOid); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + oid = blkAes256CbcOid; + *oidSz = sizeof(blkAes256CbcOid); + break; + #endif + #endif /* HAVE_AES_CBC */ + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + oid = blkAes128GcmOid; + *oidSz = sizeof(blkAes128GcmOid); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + oid = blkAes192GcmOid; + *oidSz = sizeof(blkAes192GcmOid); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + oid = blkAes256GcmOid; + *oidSz = sizeof(blkAes256GcmOid); + break; + #endif + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + oid = blkAes128CcmOid; + *oidSz = sizeof(blkAes128CcmOid); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + oid = blkAes192CcmOid; + *oidSz = sizeof(blkAes192CcmOid); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + oid = blkAes256CcmOid; + *oidSz = sizeof(blkAes256CcmOid); + break; + #endif + #endif /* HAVE_AESCCM */ + #ifndef NO_DES3 + case DESb: + oid = blkDesCbcOid; + *oidSz = sizeof(blkDesCbcOid); + break; + case DES3b: + oid = blkDes3CbcOid; + *oidSz = sizeof(blkDes3CbcOid); + break; + #endif /* !NO_DES3 */ + } + break; + + #ifdef HAVE_OCSP + case oidOcspType: + switch (id) { + case OCSP_BASIC_OID: + oid = ocspBasicOid; + *oidSz = sizeof(ocspBasicOid); + break; + case OCSP_NONCE_OID: + oid = ocspNonceOid; + *oidSz = sizeof(ocspNonceOid); + break; + } + break; + #endif /* HAVE_OCSP */ + + case oidCertExtType: + switch (id) { + case BASIC_CA_OID: + oid = extBasicCaOid; + *oidSz = sizeof(extBasicCaOid); + break; + case ALT_NAMES_OID: + oid = extAltNamesOid; + *oidSz = sizeof(extAltNamesOid); + break; + case CRL_DIST_OID: + oid = extCrlDistOid; + *oidSz = sizeof(extCrlDistOid); + break; + case AUTH_INFO_OID: + oid = extAuthInfoOid; + *oidSz = sizeof(extAuthInfoOid); + break; + case AUTH_KEY_OID: + oid = extAuthKeyOid; + *oidSz = sizeof(extAuthKeyOid); + break; + case SUBJ_KEY_OID: + oid = extSubjKeyOid; + *oidSz = sizeof(extSubjKeyOid); + break; + case CERT_POLICY_OID: + oid = extCertPolicyOid; + *oidSz = sizeof(extCertPolicyOid); + break; + case KEY_USAGE_OID: + oid = extKeyUsageOid; + *oidSz = sizeof(extKeyUsageOid); + break; + case INHIBIT_ANY_OID: + oid = extInhibitAnyOid; + *oidSz = sizeof(extInhibitAnyOid); + break; + case EXT_KEY_USAGE_OID: + oid = extExtKeyUsageOid; + *oidSz = sizeof(extExtKeyUsageOid); + break; + #ifndef IGNORE_NAME_CONSTRAINTS + case NAME_CONS_OID: + oid = extNameConsOid; + *oidSz = sizeof(extNameConsOid); + break; + #endif + } + break; + + case oidCrlExtType: + #ifdef HAVE_CRL + switch (id) { + case AUTH_KEY_OID: + oid = extAuthKeyOid; + *oidSz = sizeof(extAuthKeyOid); + break; + } + #endif + break; + + case oidCertAuthInfoType: + switch (id) { + #ifdef HAVE_OCSP + case AIA_OCSP_OID: + oid = extAuthInfoOcspOid; + *oidSz = sizeof(extAuthInfoOcspOid); + break; + #endif + case AIA_CA_ISSUER_OID: + oid = extAuthInfoCaIssuerOid; + *oidSz = sizeof(extAuthInfoCaIssuerOid); + break; + } + break; + + case oidCertPolicyType: + switch (id) { + case CP_ANY_OID: + oid = extCertPolicyAnyOid; + *oidSz = sizeof(extCertPolicyAnyOid); + break; + } + break; + + case oidCertAltNameType: + switch (id) { + case HW_NAME_OID: + oid = extAltNamesHwNameOid; + *oidSz = sizeof(extAltNamesHwNameOid); + break; + } + break; + + case oidCertKeyUseType: + switch (id) { + case EKU_ANY_OID: + oid = extExtKeyUsageAnyOid; + *oidSz = sizeof(extExtKeyUsageAnyOid); + break; + case EKU_SERVER_AUTH_OID: + oid = extExtKeyUsageServerAuthOid; + *oidSz = sizeof(extExtKeyUsageServerAuthOid); + break; + case EKU_CLIENT_AUTH_OID: + 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); + break; + } + break; + + case oidKdfType: + switch (id) { + case PBKDF2_OID: + oid = pbkdf2Oid; + *oidSz = sizeof(pbkdf2Oid); + break; + } + break; + + case oidPBEType: + switch (id) { + #if !defined(NO_SHA) && !defined(NO_RC4) + case PBE_SHA1_RC4_128: + oid = pbeSha1RC4128; + *oidSz = sizeof(pbeSha1RC4128); + break; + #endif + #if !defined(NO_SHA) && !defined(NO_DES3) + case PBE_SHA1_DES: + oid = pbeSha1Des; + *oidSz = sizeof(pbeSha1Des); + break; + + #endif + #if !defined(NO_SHA) && !defined(NO_DES3) + case PBE_SHA1_DES3: + oid = pbeSha1Des3; + *oidSz = sizeof(pbeSha1Des3); + break; + #endif + case PBES2: + oid = pbes2; + *oidSz = sizeof(pbes2); + break; + } + break; + + case oidKeyWrapType: + switch (id) { + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + oid = wrapAes128Oid; + *oidSz = sizeof(wrapAes128Oid); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + oid = wrapAes192Oid; + *oidSz = sizeof(wrapAes192Oid); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + oid = wrapAes256Oid; + *oidSz = sizeof(wrapAes256Oid); + break; + #endif + #ifdef HAVE_PKCS7 + case PWRI_KEK_WRAP: + oid = wrapPwriKekOid; + *oidSz = sizeof(wrapPwriKekOid); + break; + #endif + } + break; + + case oidCmsKeyAgreeType: + switch (id) { + #ifndef NO_SHA + case dhSinglePass_stdDH_sha1kdf_scheme: + oid = dhSinglePass_stdDH_sha1kdf_Oid; + *oidSz = sizeof(dhSinglePass_stdDH_sha1kdf_Oid); + break; + #endif + #ifdef WOLFSSL_SHA224 + case dhSinglePass_stdDH_sha224kdf_scheme: + oid = dhSinglePass_stdDH_sha224kdf_Oid; + *oidSz = sizeof(dhSinglePass_stdDH_sha224kdf_Oid); + break; + #endif + #ifndef NO_SHA256 + case dhSinglePass_stdDH_sha256kdf_scheme: + oid = dhSinglePass_stdDH_sha256kdf_Oid; + *oidSz = sizeof(dhSinglePass_stdDH_sha256kdf_Oid); + break; + #endif + #ifdef WOLFSSL_SHA384 + case dhSinglePass_stdDH_sha384kdf_scheme: + oid = dhSinglePass_stdDH_sha384kdf_Oid; + *oidSz = sizeof(dhSinglePass_stdDH_sha384kdf_Oid); + break; + #endif + #ifdef WOLFSSL_SHA512 + case dhSinglePass_stdDH_sha512kdf_scheme: + oid = dhSinglePass_stdDH_sha512kdf_Oid; + *oidSz = sizeof(dhSinglePass_stdDH_sha512kdf_Oid); + break; + #endif + } + break; + +#ifndef NO_HMAC + case oidHmacType: + switch (id) { + #ifdef WOLFSSL_SHA224 + case HMAC_SHA224_OID: + oid = hmacSha224Oid; + *oidSz = sizeof(hmacSha224Oid); + break; + #endif + #ifndef NO_SHA256 + case HMAC_SHA256_OID: + oid = hmacSha256Oid; + *oidSz = sizeof(hmacSha256Oid); + break; + #endif + #ifdef WOLFSSL_SHA384 + case HMAC_SHA384_OID: + oid = hmacSha384Oid; + *oidSz = sizeof(hmacSha384Oid); + break; + #endif + #ifdef WOLFSSL_SHA512 + case HMAC_SHA512_OID: + oid = hmacSha512Oid; + *oidSz = sizeof(hmacSha512Oid); + break; + #endif + } + break; +#endif /* !NO_HMAC */ + +#ifdef HAVE_LIBZ + case oidCompressType: + switch (id) { + case ZLIBc: + oid = zlibCompress; + *oidSz = sizeof(zlibCompress); + break; + } + break; +#endif /* HAVE_LIBZ */ +#ifdef WOLFSSL_APACHE_HTTPD + case oidCertNameType: + switch (id) { + case NID_id_on_dnsSRV: + oid = dnsSRVOid; + *oidSz = sizeof(dnsSRVOid); + break; + } + break; + case oidTlsExtType: + switch (id) { + case TLS_FEATURE_OID: + oid = tlsFeatureOid; + *oidSz = sizeof(tlsFeatureOid); + break; + } + break; +#endif /* WOLFSSL_APACHE_HTTPD */ + case oidIgnoreType: + default: + break; + } + + return oid; +} + +#ifdef HAVE_OID_ENCODING +int EncodeObjectId(const word16* in, word32 inSz, byte* out, word32* outSz) +{ + int i, x, len; + word32 d, t; + + /* check args */ + if (in == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* compute length of encoded OID */ + d = (in[0] * 40) + in[1]; + len = 0; + for (i = 1; i < (int)inSz; i++) { + x = 0; + t = d; + while (t) { + x++; + t >>= 1; + } + len += (x / 7) + ((x % 7) ? 1 : 0) + (d == 0 ? 1 : 0); + + if (i < (int)inSz - 1) { + d = in[i + 1]; + } + } + + if (out) { + /* verify length */ + if ((int)*outSz < len) { + return BUFFER_E; /* buffer provided is not large enough */ + } + + /* calc first byte */ + d = (in[0] * 40) + in[1]; + + /* encode bytes */ + x = 0; + for (i = 1; i < (int)inSz; i++) { + if (d) { + int y = x, z; + byte mask = 0; + while (d) { + out[x++] = (byte)((d & 0x7F) | mask); + d >>= 7; + mask |= 0x80; /* upper bit is set on all but the last byte */ + } + /* now swap bytes y...x-1 */ + z = x - 1; + while (y < z) { + mask = out[y]; + out[y] = out[z]; + out[z] = mask; + ++y; + --z; + } + } + else { + out[x++] = 0x00; /* zero value */ + } + + /* next word */ + if (i < (int)inSz - 1) { + d = in[i + 1]; + } + } + } + + /* return length */ + *outSz = len; + + return 0; +} +#endif /* HAVE_OID_ENCODING */ + +#ifdef HAVE_OID_DECODING +int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz) +{ + int x = 0, y = 0; + word32 t = 0; + + /* check args */ + if (in == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* decode bytes */ + while (inSz--) { + t = (t << 7) | (in[x] & 0x7F); + if (!(in[x] & 0x80)) { + if (y >= (int)*outSz) { + return BUFFER_E; + } + if (y == 0) { + out[0] = (t / 40); + out[1] = (t % 40); + y = 2; + } + else { + out[y++] = t; + } + t = 0; /* reset tmp */ + } + x++; + } + + /* return length */ + *outSz = y; + + return 0; +} +#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. + */ +int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + word32 idx = *inOutIdx; + int length; + byte tag; + + if ((idx + 1) > maxIdx) + return BUFFER_E; + + if (GetASNTag(input, &idx, &tag, maxIdx) != 0) + return ASN_PARSE_E; + + if (tag != 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. + */ +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) +{ + int ret = 0, length; + word32 idx = *inOutIdx; +#ifndef NO_VERIFY_OID + word32 actualOidSz = 0; + const byte* actualOid; +#endif /* NO_VERIFY_OID */ + + (void)oidType; + WOLFSSL_ENTER("GetObjectId()"); + *oid = 0; + + ret = GetASNObjectId(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; + +#ifndef NO_VERIFY_OID + actualOid = &input[idx]; + if (length > 0) + actualOidSz = (word32)length; +#endif /* NO_VERIFY_OID */ + + while (length--) { + /* odd HC08 compiler behavior here when input[idx++] */ + *oid += (word32)input[idx]; + idx++; + } + /* just sum it up for now */ + + *inOutIdx = idx; + +#ifndef NO_VERIFY_OID + { + const byte* checkOid = NULL; + word32 checkOidSz; + #ifdef ASN_DUMP_OID + word32 i; + #endif + + if (oidType != oidIgnoreType) { + checkOid = OidFromId(*oid, oidType, &checkOidSz); + + #ifdef ASN_DUMP_OID + /* support for dumping OID information */ + printf("OID (Type %d, Sz %d, Sum %d): ", oidType, actualOidSz, *oid); + for (i=0; iheap; - - if (GetSequence(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; - - if (GetMyVersion(input, inOutIdx, &version) < 0) - return ASN_PARSE_E; - - key->type = RSA_PRIVATE; - - if (GetCaviumInt(&key->c_n, &key->c_nSz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_e, &key->c_eSz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_d, &key->c_dSz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_p, &key->c_pSz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_q, &key->c_qSz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_dP, &key->c_dP_Sz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_dQ, &key->c_dQ_Sz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_u, &key->c_uSz, input, inOutIdx, inSz, h) < 0 ) - return ASN_RSA_KEY_E; - - return 0; -} - - -#endif /* HAVE_CAVIUM */ - +#ifndef HAVE_USER_RSA int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { - int version, length; - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return CaviumRsaPrivateKeyDecode(input, inOutIdx, key, inSz); -#endif + int version, length; + if (inOutIdx == NULL) { + return BAD_FUNC_ARG; + } if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; - if (GetMyVersion(input, inOutIdx, &version) < 0) + if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) return ASN_PARSE_E; key->type = RSA_PRIVATE; if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || GetInt(&key->e, input, inOutIdx, inSz) < 0 || +#ifndef WOLFSSL_RSA_PUBLIC_ONLY 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->q, input, inOutIdx, inSz) < 0) +#else + SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 ) + +#endif + return ASN_RSA_KEY_E; +#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)) \ + && !defined(WOLFSSL_RSA_PUBLIC_ONLY) + if (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; +#else + if (SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; +#endif + +#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL) + if (wc_InitRsaHw(key) != 0) { + return BAD_STATE_E; + } +#endif return 0; } - +#endif /* HAVE_USER_RSA */ #endif /* NO_RSA */ -/* Remove PKCS8 header, move beginning of traditional to beginning of input */ -int ToTraditional(byte* input, word32 sz) +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + +/* Remove PKCS8 header, place inOutIdx at beginning of traditional, + * return traditional length on success, negative on error */ +int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, word32 sz, + word32* algId) { - word32 inOutIdx = 0, oid; + word32 idx; int version, length; + int ret; + byte tag; - if (GetSequence(input, &inOutIdx, &length, sz) < 0) + 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, &inOutIdx, &version) < 0) + if (GetMyVersion(input, &idx, &version, sz) < 0) return ASN_PARSE_E; - if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0) + if (GetAlgoId(input, &idx, algId, 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) + if (GetASNTag(input, &idx, &tag, sz) < 0) + return ASN_PARSE_E; + idx = idx - 1; /* reset idx after finding tag */ + + if (tag == ASN_OBJECT_ID) { + if (SkipObjectId(input, &idx, 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; + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) { + if (ret == BUFFER_E) + return ASN_PARSE_E; + /* Some private keys don't expect an octet string */ + WOLFSSL_MSG("Couldn't find Octet string"); + } - if (GetLength(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + *inOutIdx = idx; + + return length; +} + +int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 sz) +{ + word32 oid; + + return ToTraditionalInline_ex(input, inOutIdx, sz, &oid); +} + +/* Remove PKCS8 header, move beginning of traditional to beginning of input */ +int ToTraditional_ex(byte* input, word32 sz, word32* algId) +{ + word32 inOutIdx = 0; + int length; + + if (input == NULL) + return BAD_FUNC_ARG; + + length = ToTraditionalInline_ex(input, &inOutIdx, sz, algId); + if (length < 0) + return length; XMEMMOVE(input, input + inOutIdx, length); return length; } +int ToTraditional(byte* input, word32 sz) +{ + word32 oid; + + return ToTraditional_ex(input, sz, &oid); +} + +#endif /* HAVE_PKCS8 || HAVE_PKCS12 */ + +#ifdef HAVE_PKCS8 + +/* 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; + word32 algId; + + if (input == NULL || inOutIdx == NULL || (*inOutIdx > sz)) + return BAD_FUNC_ARG; + + length = ToTraditionalInline_ex(input, inOutIdx, sz, &algId); + + 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; +} + +#endif /* HAVE_PKCS8 */ + +#if defined(HAVE_PKCS12) || !defined(NO_CHECK_PRIVATE_KEY) +/* 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 + * + * key : buffer holding DER format key + * keySz : size of key buffer + * 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) && !defined(NO_ASN_CRYPT) + /* test if RSA key */ + if (der->keyOID == RSAk) { + #ifdef WOLFSSL_SMALL_STACK + RsaKey* a; + RsaKey* b = NULL; + #else + RsaKey a[1], b[1]; + #endif + word32 keyIdx = 0; + + #ifdef WOLFSSL_SMALL_STACK + a = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (a == NULL) + return MEMORY_E; + b = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (b == NULL) { + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + return MEMORY_E; + } + #endif + + if ((ret = wc_InitRsaKey(a, NULL)) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_RSA); + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + return ret; + } + if ((ret = wc_InitRsaKey(b, NULL)) < 0) { + wc_FreeRsaKey(a); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_RSA); + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + 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); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_RSA); + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } + else + #endif /* !NO_RSA && !NO_ASN_CRYPT */ + + #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) + if (der->keyOID == ECDSAk) { + #ifdef WOLFSSL_SMALL_STACK + ecc_key* key_pair; + byte* privDer; + #else + ecc_key key_pair[1]; + byte privDer[MAX_ECC_BYTES]; + #endif + word32 privSz = MAX_ECC_BYTES; + word32 keyIdx = 0; + + #ifdef WOLFSSL_SMALL_STACK + key_pair = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC); + if (key_pair == NULL) + return MEMORY_E; + privDer = (byte*)XMALLOC(MAX_ECC_BYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (privDer == NULL) { + XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif + + if ((ret = wc_ecc_init(key_pair)) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC); + #endif + return ret; + } + + if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, key_pair, + keySz)) == 0) { + WOLFSSL_MSG("Checking ECC key pair"); + + if ((ret = wc_ecc_export_private_only(key_pair, privDer, &privSz)) + == 0) { + wc_ecc_free(key_pair); + ret = wc_ecc_init(key_pair); + if (ret == 0) { + ret = wc_ecc_import_private_key((const byte*)privDer, + privSz, (const byte*)der->publicKey, + der->pubKeySize, key_pair); + } + + /* public and private extracted successfully now 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 == 0) { + if ((ret = wc_ecc_check_key(key_pair)) == 0) { + ret = 1; + } + } + ForceZero(privDer, privSz); + } + } + wc_ecc_free(key_pair); + #ifdef WOLFSSL_SMALL_STACK + XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC); + #endif + } + else + #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */ + + #if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT) + if (der->keyOID == ED25519k) { + #ifdef WOLFSSL_SMALL_STACK + ed25519_key* key_pair; + #else + ed25519_key key_pair[1]; + #endif + word32 keyIdx = 0; + + #ifdef WOLFSSL_SMALL_STACK + key_pair = (ed25519_key*)XMALLOC(sizeof(ed25519_key), NULL, + DYNAMIC_TYPE_ED25519); + if (key_pair == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_ed25519_init(key_pair)) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519); + #endif + 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 successfully 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); + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519); + #endif + } + else + #endif /* HAVE_ED25519 && !NO_ASN_CRYPT */ + + #if defined(HAVE_ED448) && !defined(NO_ASN_CRYPT) + if (der->keyOID == ED448k) { + #ifdef WOLFSSL_SMALL_STACK + ed448_key* key_pair = NULL; + #else + ed448_key key_pair[1]; + #endif + word32 keyIdx = 0; + + #ifdef WOLFSSL_SMALL_STACK + key_pair = (ed448_key*)XMALLOC(sizeof(ed448_key), NULL, + DYNAMIC_TYPE_ED448); + if (key_pair == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_ed448_init(key_pair)) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_ED448); + #endif + return ret; + } + if ((ret = wc_Ed448PrivateKeyDecode(key, &keyIdx, key_pair, + keySz)) == 0) { + WOLFSSL_MSG("Checking ED448 key pair"); + keyIdx = 0; + if ((ret = wc_ed448_import_public(der->publicKey, der->pubKeySize, + key_pair)) == 0) { + /* public and private extracted successfully 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_ed448_check_key(key_pair)) == 0) + ret = 1; + } + } + wc_ed448_free(key_pair); + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_ED448); + #endif + } + else + #endif /* HAVE_ED448 && !NO_ASN_CRYPT */ + { + ret = 0; + } + + (void)keySz; + + return ret; +} + +#endif /* HAVE_PKCS12 || !NO_CHECK_PRIVATE_KEY */ #ifndef NO_PWDBASED +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) /* Check To see if PKCS version algo is supported, set id if it is return 0 < 0 on error */ -static int CheckAlgo(int first, int second, int* id, int* version) +static int CheckAlgo(int first, int second, int* id, int* version, int* blockSz) { *id = ALGO_ID_E; *version = PKCS5; /* default */ + if (blockSz) *blockSz = 8; /* default */ if (first == 1) { switch (second) { - case 1: +#if !defined(NO_SHA) + #ifndef NO_RC4 + case PBE_SHA1_RC4_128: *id = PBE_SHA1_RC4_128; - *version = PKCS12; + *version = PKCS12v1; return 0; - case 3: + #endif + #ifndef NO_DES3 + case PBE_SHA1_DES3: *id = PBE_SHA1_DES3; - *version = PKCS12; + *version = PKCS12v1; + if (blockSz) *blockSz = DES_BLOCK_SIZE; return 0; + case PBE_SHA1_DES: + *id = PBE_SHA1_DES; + *version = PKCS12v1; + if (blockSz) *blockSz = DES_BLOCK_SIZE; + return 0; + #endif +#endif /* !NO_SHA */ default: return ALGO_ID_E; } @@ -857,213 +3124,655 @@ static int CheckAlgo(int first, int second, int* id, int* version) } switch (second) { +#ifndef NO_DES3 + #ifndef NO_MD5 case 3: /* see RFC 2898 for ids */ *id = PBE_MD5_DES; + if (blockSz) *blockSz = DES_BLOCK_SIZE; return 0; + #endif + #ifndef NO_SHA case 10: *id = PBE_SHA1_DES; + if (blockSz) *blockSz = DES_BLOCK_SIZE; return 0; + #endif +#endif /* !NO_DES3 */ default: return ALGO_ID_E; } } - /* Check To see if PKCS v2 algo is supported, set id if it is return 0 < 0 on error */ -static int CheckAlgoV2(int oid, int* id) +static int CheckAlgoV2(int oid, int* id, int* blockSz) { + if (blockSz) *blockSz = 8; /* default */ + (void)id; /* not used if AES and DES3 disabled */ switch (oid) { - case 69: +#if !defined(NO_DES3) && !defined(NO_SHA) + case DESb: *id = PBE_SHA1_DES; + if (blockSz) *blockSz = DES_BLOCK_SIZE; return 0; - case 652: + case DES3b: *id = PBE_SHA1_DES3; + if (blockSz) *blockSz = DES_BLOCK_SIZE; return 0; +#endif +#ifdef WOLFSSL_AES_256 + case AES256CBCb: + *id = PBE_AES256_CBC; + if (blockSz) *blockSz = AES_BLOCK_SIZE; + return 0; +#endif +#ifdef WOLFSSL_AES_128 + case AES128CBCb: + *id = PBE_AES128_CBC; + if (blockSz) *blockSz = AES_BLOCK_SIZE; + return 0; +#endif default: + WOLFSSL_MSG("No PKCS v2 algo found"); return ALGO_ID_E; } } +#endif /* HAVE_PKCS8 || HAVE_PKCS12 */ -/* Decrypt intput in place from parameters based on id */ -static int DecryptKey(const char* password, int passwordSz, byte* salt, - int saltSz, int iterations, int id, byte* input, - int length, int version, byte* cbcIv) +#ifdef HAVE_PKCS8 + +int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, + int* algoID, void* heap) { - int typeH; - int derivedLen; - int decryptionType; - int ret = 0; + word32 tmpIdx = 0; + + if (key == NULL || algoID == NULL) + return BAD_FUNC_ARG; + + *algoID = 0; + + #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT) + { + RsaKey rsa; + + wc_InitRsaKey(&rsa, heap); + if (wc_RsaPrivateKeyDecode(key, &tmpIdx, &rsa, keySz) == 0) { + *algoID = RSAk; + } + else { + WOLFSSL_MSG("Not RSA DER key"); + } + wc_FreeRsaKey(&rsa); + } + #endif /* !NO_RSA && !NO_ASN_CRYPT */ + #if defined(HAVE_ECC) && !defined(NO_ASN_CRYPT) + if (*algoID == 0) { + ecc_key ecc; + + tmpIdx = 0; + wc_ecc_init_ex(&ecc, heap, INVALID_DEVID); + if (wc_EccPrivateKeyDecode(key, &tmpIdx, &ecc, keySz) == 0) { + *algoID = ECDSAk; + + /* 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); + } +#endif /* HAVE_ECC && !NO_ASN_CRYPT */ +#if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT) + if (*algoID != RSAk && *algoID != ECDSAk) { + ed25519_key ed25519; + + tmpIdx = 0; + 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 /* HAVE_ED25519 && !NO_ASN_CRYPT */ +#if defined(HAVE_ED448) && !defined(NO_ASN_CRYPT) + if (*algoID != RSAk && *algoID != ECDSAk && *algoID != ED25519k) { + ed448_key ed448; + + tmpIdx = 0; + if (wc_ed448_init(&ed448) == 0) { + if (wc_Ed448PrivateKeyDecode(key, &tmpIdx, &ed448, keySz) == 0) { + *algoID = ED448k; + } + else { + WOLFSSL_MSG("Not ED448 DER key"); + } + wc_ed448_free(&ed448); + } + else { + WOLFSSL_MSG("GetKeyOID wc_ed448_init failed"); + } + } +#endif /* HAVE_ED448 && !NO_ASN_CRYPT */ + + /* 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)tmpIdx; + (void)curveOID; + (void)oidSz; + (void)keySz; + (void)heap; + + return 1; +} + +#endif /* HAVE_PKCS8 */ + +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + +#define PKCS8_MIN_BLOCK_SIZE 8 +static int Pkcs8Pad(byte* buf, int sz, int blockSz) +{ + int i, padSz; + + /* calculate pad size */ + padSz = blockSz - (sz & (blockSz - 1)); + + /* pad with padSz value */ + if (buf) { + for (i = 0; i < padSz; i++) { + buf[sz+i] = (byte)(padSz & 0xFF); + } + } + + /* return adjusted length */ + return sz + padSz; +} + +#endif /* HAVE_PKCS8 || HAVE_PKCS12 */ + +#ifdef HAVE_PKCS8 + +/* + * Used when creating PKCS12 shrouded key bags + * vPKCS is the version of PKCS to use + * vAlgo is the algorithm version to use + * + * if salt is NULL a random number is generated + * + * returns the size of encrypted data on success + */ +int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, + const char* password, int passwordSz, int vPKCS, int vAlgo, + byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap) +{ + int algoID = 0; + byte* tmp; + word32 tmpSz = 0; + word32 sz; + word32 seqSz; + word32 inOutIdx = 0; + word32 totalSz = 0; + int version, id; + int ret; + int blockSz = 0; + + const byte* curveOID = NULL; + word32 oidSz = 0; + #ifdef WOLFSSL_SMALL_STACK - byte* key; + byte* saltTmp = NULL; + byte* cbcIv = NULL; #else - byte key[MAX_KEY_SIZE]; + byte saltTmp[MAX_IV_SIZE]; + byte cbcIv[MAX_IV_SIZE]; #endif - switch (id) { - case PBE_MD5_DES: - typeH = MD5; - derivedLen = 16; /* may need iv for v1.5 */ - decryptionType = DES_TYPE; - break; + WOLFSSL_ENTER("UnTraditionalEnc()"); - case PBE_SHA1_DES: - typeH = SHA; - derivedLen = 16; /* may need iv for v1.5 */ - decryptionType = DES_TYPE; - break; + if (saltSz > MAX_SALT_SIZE) + return ASN_PARSE_E; - case PBE_SHA1_DES3: - typeH = SHA; - derivedLen = 32; /* may need iv for v1.5 */ - decryptionType = DES3_TYPE; - break; - case PBE_SHA1_RC4_128: - typeH = SHA; - derivedLen = 16; - decryptionType = RC4_TYPE; - break; - - default: - return ALGO_ID_E; + inOutIdx += MAX_SEQ_SZ; /* leave room for size of finished shroud */ + if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0) { + WOLFSSL_MSG("Bad/Unsupported algorithm ID"); + return ASN_INPUT_E; /* Algo ID error */ } -#ifdef WOLFSSL_SMALL_STACK - key = (byte*)XMALLOC(MAX_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (key == NULL) - return MEMORY_E; -#endif + if (out != NULL) { + if (*outSz < inOutIdx + MAX_ALGO_SZ + MAX_SALT_SIZE + MAX_SEQ_SZ + 1 + + MAX_LENGTH_SZ + MAX_SHORT_SZ + 1) + return BUFFER_E; - if (version == PKCS5v2) - ret = wc_PBKDF2(key, (byte*)password, passwordSz, salt, saltSz, iterations, - derivedLen, typeH); -#ifndef NO_SHA - else if (version == PKCS5) - ret = wc_PBKDF1(key, (byte*)password, passwordSz, salt, saltSz, iterations, - derivedLen, typeH); -#endif - else if (version == PKCS12) { - int i, idx = 0; - byte unicodePasswd[MAX_UNICODE_SZ]; - - if ( (passwordSz * 2 + 2) > (int)sizeof(unicodePasswd)) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return UNICODE_SIZE_E; + if (version == PKCS5v2) { + WOLFSSL_MSG("PKCS5v2 Not supported yet\n"); + return ASN_VERSION_E; } - for (i = 0; i < passwordSz; i++) { - unicodePasswd[idx++] = 0x00; - unicodePasswd[idx++] = (byte)password[i]; + if (salt == NULL || saltSz == 0) { + saltSz = 8; + #ifdef WOLFSSL_SMALL_STACK + saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (saltTmp == NULL) + return MEMORY_E; + #endif + salt = saltTmp; + + if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) { + WOLFSSL_MSG("Error generating random salt"); + #ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } } - /* add trailing NULL */ - unicodePasswd[idx++] = 0x00; - unicodePasswd[idx++] = 0x00; - ret = wc_PKCS12_PBKDF(key, unicodePasswd, idx, salt, saltSz, - iterations, derivedLen, typeH, 1); - if (decryptionType != RC4_TYPE) - ret += wc_PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt, saltSz, - iterations, 8, typeH, 2); - } - else { -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ALGO_ID_E; + + /* leave room for a sequence (contains salt and iterations int) */ + inOutIdx += MAX_SEQ_SZ; sz = 0; + inOutIdx += MAX_ALGO_SZ; + + /* place salt in buffer */ + out[inOutIdx++] = ASN_OCTET_STRING; sz++; + tmpSz = SetLength(saltSz, out + inOutIdx); + inOutIdx += tmpSz; sz += tmpSz; + XMEMCPY(out + inOutIdx, salt, saltSz); + inOutIdx += saltSz; sz += saltSz; + + /* place iteration count in buffer */ + ret = SetShortInt(out, &inOutIdx, itt, *outSz); + if (ret < 0) { + return ret; + } + sz += (word32)ret; + + /* wind back index and set sequence then clean up buffer */ + inOutIdx -= (sz + MAX_SEQ_SZ); + tmpSz = SetSequence(sz, out + inOutIdx); + XMEMMOVE(out + inOutIdx + tmpSz, out + inOutIdx + MAX_SEQ_SZ, sz); + totalSz += tmpSz + sz; sz += tmpSz; + + /* add in algo ID */ + inOutIdx -= MAX_ALGO_SZ; + tmpSz = SetAlgoID(id, out + inOutIdx, oidPBEType, sz); + XMEMMOVE(out + inOutIdx + tmpSz, out + inOutIdx + MAX_ALGO_SZ, sz); + totalSz += tmpSz; inOutIdx += tmpSz + sz; + + /* octet string containing encrypted key */ + out[inOutIdx++] = ASN_OCTET_STRING; totalSz++; } - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* check key type and get OID if ECC */ + if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap))< 0) { + WOLFSSL_MSG("Error getting key OID"); return ret; } - switch (decryptionType) { -#ifndef NO_DES3 - case DES_TYPE: - { - Des dec; - byte* desIv = key + 8; - - if (version == PKCS5v2 || version == PKCS12) - desIv = cbcIv; - - ret = wc_Des_SetKey(&dec, key, desIv, DES_DECRYPTION); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - - wc_Des_CbcDecrypt(&dec, input, input, length); - break; - } - - case DES3_TYPE: - { - Des3 dec; - byte* desIv = key + 24; - - if (version == PKCS5v2 || version == PKCS12) - desIv = cbcIv; - ret = wc_Des3_SetKey(&dec, key, desIv, DES_DECRYPTION); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - ret = wc_Des3_CbcDecrypt(&dec, input, input, length); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - break; - } -#endif -#ifndef NO_RC4 - case RC4_TYPE: - { - Arc4 dec; - - wc_Arc4SetKey(&dec, key, derivedLen); - wc_Arc4Process(&dec, input, input, length); - break; - } -#endif - - default: -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ALGO_ID_E; + /* PKCS#8 wrapping around key */ + if (wc_CreatePKCS8Key(NULL, &tmpSz, key, keySz, algoID, curveOID, oidSz) + != LENGTH_ONLY_E) { + #ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; } + /* check if should return max size */ + if (out == NULL) { + /* account for salt size */ + if (salt == NULL || saltSz == 0) { + tmpSz += MAX_SALT_SIZE; + } + else { + tmpSz += saltSz; + } + + /* plus 3 for tags */ + *outSz = tmpSz + MAX_ALGO_SZ + MAX_LENGTH_SZ +MAX_LENGTH_SZ + MAX_SEQ_SZ + + MAX_LENGTH_SZ + MAX_SEQ_SZ + 3; + return LENGTH_ONLY_E; + } + + /* reserve buffer for crypto and make sure it supports full blocks */ + tmp = (byte*)XMALLOC(tmpSz + (blockSz-1), heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + #ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + + if ((ret = wc_CreatePKCS8Key(tmp, &tmpSz, key, keySz, algoID, curveOID, + oidSz)) < 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Error wrapping key with PKCS#8"); + #ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + tmpSz = ret; + + /* adjust size to pad */ + tmpSz = Pkcs8Pad(tmp, tmpSz, blockSz); + #ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cbcIv == NULL) { + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(salt, heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } #endif - return 0; + /* encrypt PKCS#8 wrapped key */ + if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id, + tmp, tmpSz, version, cbcIv, 1, 0)) < 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Error encrypting key"); + #ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cbcIv != NULL) + XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; /* encryption failure */ + } + totalSz += tmpSz; + +#ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cbcIv != NULL) + XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (*outSz < inOutIdx + tmpSz + MAX_LENGTH_SZ) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return BUFFER_E; + } + + /* set length of key and copy over encrypted key */ + seqSz = SetLength(tmpSz, out + inOutIdx); + inOutIdx += seqSz; totalSz += seqSz; + XMEMCPY(out + inOutIdx, tmp, tmpSz); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + + /* set total size at beginning */ + sz = SetSequence(totalSz, out); + XMEMMOVE(out + sz, out + MAX_SEQ_SZ, totalSz); + + (void)rng; + + return totalSz + sz; } - -/* Remove Encrypted PKCS8 header, move beginning of traditional to beginning - of input */ -int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) +static int GetAlgoV2(int encAlgId, const byte** oid, int *len, int* id, + int *blkSz) { - word32 inOutIdx = 0, oid; - int first, second, length, version, saltSz, id; - int iterations = 0; + int ret = 0; + + switch (encAlgId) { +#if !defined(NO_DES3) && !defined(NO_SHA) + case DESb: + *len = sizeof(blkDesCbcOid); + *oid = blkDesCbcOid; + *id = PBE_SHA1_DES; + *blkSz = 8; + break; + case DES3b: + *len = sizeof(blkDes3CbcOid); + *oid = blkDes3CbcOid; + *id = PBE_SHA1_DES3; + *blkSz = 8; + break; +#endif +#if defined(WOLFSSL_AES_256) && defined(HAVE_AES_CBC) + case AES256CBCb: + *len = sizeof(blkAes256CbcOid); + *oid = blkAes256CbcOid; + *id = PBE_AES256_CBC; + *blkSz = 16; + break; +#endif + default: + (void)len; + (void)oid; + (void)id; + (void)blkSz; + ret = ALGO_ID_E; + } + + return ret; +} + +/* Converts Encrypted PKCS#8 to 'traditional' (i.e. PKCS#8 removed from + * decrypted key.) + */ +int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, + const char* password, int passwordSz, int vPKCS, int vAlgo, + int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng, + void* heap) +{ + int ret = 0; + int version, blockSz, id; + word32 idx = 0, encIdx; +#ifdef WOLFSSL_SMALL_STACK + byte* saltTmp = NULL; +#else + byte saltTmp[MAX_SALT_SIZE]; +#endif + byte cbcIv[MAX_IV_SIZE]; + byte *pkcs8Key = NULL; + word32 pkcs8KeySz = 0, padSz = 0; + int algId = 0; + const byte* curveOid = NULL; + word32 curveOidSz = 0; + const byte* pbeOid = NULL; + word32 pbeOidSz = 0; + const byte* encOid = NULL; + int encOidSz = 0; + word32 pbeLen = 0, kdfLen = 0, encLen = 0; + word32 innerLen = 0, outerLen; + + ret = CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz); + /* create random salt if one not provided */ + if (ret == 0 && (salt == NULL || saltSz == 0)) { + saltSz = 8; + #ifdef WOLFSSL_SMALL_STACK + saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (saltTmp == NULL) + return MEMORY_E; + #endif + salt = saltTmp; + + if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) { + WOLFSSL_MSG("Error generating random salt"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + } + + if (ret == 0) { + /* check key type and get OID if ECC */ + ret = wc_GetKeyOID(key, keySz, &curveOid, &curveOidSz, &algId, heap); + if (ret == 1) + ret = 0; + } + if (ret == 0) { + ret = wc_CreatePKCS8Key(NULL, &pkcs8KeySz, key, keySz, algId, curveOid, + curveOidSz); + if (ret == LENGTH_ONLY_E) + ret = 0; + } + if (ret == 0) { + pkcs8Key = (byte*)XMALLOC(pkcs8KeySz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pkcs8Key == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + ret = wc_CreatePKCS8Key(pkcs8Key, &pkcs8KeySz, key, keySz, algId, + curveOid, curveOidSz); + if (ret >= 0) { + pkcs8KeySz = ret; + ret = 0; + } + } + + if (ret == 0 && version == PKCS5v2) + ret = GetAlgoV2(encAlgId, &encOid, &encOidSz, &id, &blockSz); + + if (ret == 0) { + padSz = (blockSz - (pkcs8KeySz & (blockSz - 1))) & (blockSz - 1); + /* inner = OCT salt INT itt */ + innerLen = 2 + saltSz + 2 + (itt < 256 ? 1 : 2); + + if (version != PKCS5v2) { + pbeOid = OidFromId(id, oidPBEType, &pbeOidSz); + /* pbe = OBJ pbse1 SEQ [ inner ] */ + pbeLen = 2 + pbeOidSz + 2 + innerLen; + } + else { + pbeOid = pbes2; + pbeOidSz = sizeof(pbes2); + /* kdf = OBJ pbkdf2 [ SEQ innerLen ] */ + kdfLen = 2 + sizeof(pbkdf2Oid) + 2 + innerLen; + /* enc = OBJ enc_alg OCT iv */ + encLen = 2 + encOidSz + 2 + blockSz; + /* pbe = OBJ pbse2 SEQ [ SEQ [ kdf ] SEQ [ enc ] ] */ + pbeLen = 2 + sizeof(pbes2) + 2 + 2 + kdfLen + 2 + encLen; + + ret = wc_RNG_GenerateBlock(rng, cbcIv, blockSz); + } + } + if (ret == 0) { + /* outer = SEQ [ pbe ] OCT encrypted_PKCS#8_key */ + outerLen = 2 + pbeLen; + outerLen += SetOctetString(pkcs8KeySz + padSz, out); + outerLen += pkcs8KeySz + padSz; + + idx += SetSequence(outerLen, out + idx); + + encIdx = idx + outerLen - pkcs8KeySz - padSz; + /* Put Encrypted content in place. */ + XMEMCPY(out + encIdx, pkcs8Key, pkcs8KeySz); + if (padSz > 0) { + XMEMSET(out + encIdx + pkcs8KeySz, padSz, padSz); + pkcs8KeySz += padSz; + } + ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id, + out + encIdx, pkcs8KeySz, version, cbcIv, 1, 0); + } + if (ret == 0) { + if (version != PKCS5v2) { + /* PBE algorithm */ + idx += SetSequence(pbeLen, out + idx); + idx += SetObjectId(pbeOidSz, out + idx); + XMEMCPY(out + idx, pbeOid, pbeOidSz); + idx += pbeOidSz; + } + else { + /* PBES2 algorithm identifier */ + idx += SetSequence(pbeLen, out + idx); + idx += SetObjectId(pbeOidSz, out + idx); + XMEMCPY(out + idx, pbeOid, pbeOidSz); + idx += pbeOidSz; + /* PBES2 Parameters: SEQ [ kdf ] SEQ [ enc ] */ + idx += SetSequence(2 + kdfLen + 2 + encLen, out + idx); + /* KDF Algorithm Identifier */ + idx += SetSequence(kdfLen, out + idx); + idx += SetObjectId(sizeof(pbkdf2Oid), out + idx); + XMEMCPY(out + idx, pbkdf2Oid, sizeof(pbkdf2Oid)); + idx += sizeof(pbkdf2Oid); + } + idx += SetSequence(innerLen, out + idx); + idx += SetOctetString(saltSz, out + idx); + XMEMCPY(out + idx, salt, saltSz); idx += saltSz; + ret = SetShortInt(out, &idx, itt, *outSz); + if (ret > 0) + ret = 0; + } + if (ret == 0) { + if (version == PKCS5v2) { + /* Encryption Algorithm Identifier */ + idx += SetSequence(encLen, out + idx); + idx += SetObjectId(encOidSz, out + idx); + XMEMCPY(out + idx, encOid, encOidSz); + idx += encOidSz; + /* Encryption Algorithm Parameter: CBC IV */ + idx += SetOctetString(blockSz, out + idx); + XMEMCPY(out + idx, cbcIv, blockSz); + idx += blockSz; + } + idx += SetOctetString(pkcs8KeySz, out + idx); + /* Default PRF - no need to write out OID */ + idx += pkcs8KeySz; + + ret = idx; + } + + if (pkcs8Key != NULL) { + ForceZero(pkcs8Key, pkcs8KeySz); + XFREE(pkcs8Key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) { + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + (void)rng; + + return ret; +} + +#endif /* HAVE_PKCS8 */ + +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) +/* decrypt PKCS + * + * NOTE: input buffer is overwritten with decrypted data! + * + * input[in/out] data to decrypt and results are written to + * sz size of input buffer + * password password if used. Can be NULL for no password + * passwordSz size of password buffer + * + * returns the total size of decrypted content on success. + */ +int DecryptContent(byte* input, word32 sz, const char* password, int passwordSz) +{ + word32 inOutIdx = 0, seqEnd, oid, shaOid = 0; + int ret = 0, first, second, length = 0, version, saltSz, id; + int iterations = 0, keySz = 0; #ifdef WOLFSSL_SMALL_STACK byte* salt = NULL; byte* cbcIv = NULL; @@ -1071,205 +3780,560 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) byte salt[MAX_SALT_SIZE]; byte cbcIv[MAX_IV_SIZE]; #endif - - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + byte tag; - if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0) - return ASN_PARSE_E; - - first = input[inOutIdx - 2]; /* PKCS version alwyas 2nd to last byte */ - second = input[inOutIdx - 1]; /* version.algo, algo id last byte */ - - if (CheckAlgo(first, second, &id, &version) < 0) - return ASN_INPUT_E; /* Algo ID error */ - - if (version == PKCS5v2) { - - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; - - if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0) - return ASN_PARSE_E; - - if (oid != PBKDF2_OID) - return ASN_PARSE_E; + if (passwordSz < 0) { + WOLFSSL_MSG("Bad password size"); + return BAD_FUNC_ARG; } - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + if (GetAlgoId(input, &inOutIdx, &oid, oidIgnoreType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } - if (input[inOutIdx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - - if (GetLength(input, &inOutIdx, &saltSz, sz) < 0) - return ASN_PARSE_E; + first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */ + second = input[inOutIdx - 1]; /* version.algo, algo id last byte */ + + if (CheckAlgo(first, second, &id, &version, NULL) < 0) { + ERROR_OUT(ASN_INPUT_E, exit_dc); /* Algo ID error */ + } + + if (version == PKCS5v2) { + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + if (oid != PBKDF2_OID) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + } + + 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; + + ret = GetOctetString(input, &inOutIdx, &saltSz, sz); + if (ret < 0) + goto exit_dc; + + if (saltSz > MAX_SALT_SIZE) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } - if (saltSz > MAX_SALT_SIZE) - return ASN_PARSE_E; - #ifdef WOLFSSL_SMALL_STACK salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (salt == NULL) - return MEMORY_E; + if (salt == NULL) { + ERROR_OUT(MEMORY_E, exit_dc); + } #endif XMEMCPY(salt, &input[inOutIdx], saltSz); inOutIdx += saltSz; - if (GetShortInt(input, &inOutIdx, &iterations) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + /* OPTIONAL key length */ + if (seqEnd > inOutIdx) { + word32 localIdx = inOutIdx; + + if (GetASNTag(input, &localIdx, &tag, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + if (tag == ASN_INTEGER && + 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); + } + + shaOid = oid; } #ifdef WOLFSSL_SMALL_STACK cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (cbcIv == NULL) { - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_dc); } #endif if (version == PKCS5v2) { /* get encryption algo */ - if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); } - if (CheckAlgoV2(oid, &id) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; /* PKCS v2 algo id error */ + if (CheckAlgoV2(oid, &id, NULL) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); /* PKCS v2 algo id error */ } - if (input[inOutIdx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (GetLength(input, &inOutIdx, &length, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + if (shaOid == 0) + shaOid = oid; + + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_dc; + + if (length > MAX_IV_SIZE) { + ERROR_OUT(ASN_PARSE_E, exit_dc); } XMEMCPY(cbcIv, &input[inOutIdx], length); inOutIdx += length; } - if (input[inOutIdx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + if (GetASNTag(input, &inOutIdx, &tag, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + if (tag != (ASN_CONTEXT_SPECIFIC | 0) && tag != ASN_OCTET_STRING) { + ERROR_OUT(ASN_PARSE_E, exit_dc); } if (GetLength(input, &inOutIdx, &length, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_dc); } - if (DecryptKey(password, passwordSz, salt, saltSz, iterations, id, - input + inOutIdx, length, version, cbcIv) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_INPUT_E; /* decrypt failure */ - } + ret = wc_CryptKey(password, passwordSz, salt, saltSz, iterations, id, + input + inOutIdx, length, version, cbcIv, 0, shaOid); +exit_dc: #ifdef WOLFSSL_SMALL_STACK XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - XMEMMOVE(input, input + inOutIdx, length); - return ToTraditional(input, length); + if (ret == 0) { + XMEMMOVE(input, input + inOutIdx, length); + ret = length; + } + + return ret; } + +/* Remove Encrypted PKCS8 header, move beginning of traditional to beginning + of input */ +int ToTraditionalEnc(byte* input, word32 sz,const char* password, + int passwordSz, word32* algId) +{ + int ret, length; + word32 inOutIdx = 0; + + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { + ret = ASN_PARSE_E; + } + else { + ret = DecryptContent(input + inOutIdx, sz - inOutIdx, password, + passwordSz); + if (ret > 0) { + XMEMMOVE(input, input + inOutIdx, ret); + ret = ToTraditional_ex(input, ret, algId); + } + } + + return ret; +} + +#endif /* HAVE_PKCS8 || HAVE_PKCS12 */ + +#ifdef HAVE_PKCS12 + +/* encrypt PKCS 12 content + * + * NOTE: if out is NULL then outSz is set with the total buffer size needed and + * the error value LENGTH_ONLY_E is returned. + * + * input data to encrypt + * inputSz size of input buffer + * out buffer to hold the result + * outSz size of out buffer + * password password if used. Can be NULL for no password + * passwordSz size of password buffer + * vPKCS version of PKCS i.e. PKCS5v2 + * vAlgo algorithm version + * salt buffer holding salt if used. If NULL then a random salt is created + * saltSz size of salt buffer if it is not NULL + * itt number of iterations used + * rng random number generator to use + * heap possible heap hint for mallocs/frees + * + * returns the total size of encrypted content on success. + * + * data returned is : + * [ seq - obj [ seq -salt,itt]] , construct with encrypted data + */ +int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, + const char* password, int passwordSz, int vPKCS, int vAlgo, + byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap) +{ + word32 sz; + word32 inOutIdx = 0; + word32 tmpIdx = 0; + word32 totalSz = 0; + word32 seqSz; + word32 innerSz; + int ret; + int version, id, blockSz = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* saltTmp = NULL; + byte* cbcIv = NULL; +#else + byte saltTmp[MAX_SALT_SIZE]; + byte cbcIv[MAX_IV_SIZE]; +#endif + byte seq[MAX_SEQ_SZ]; + byte shr[MAX_SHORT_SZ]; + word32 maxShr = MAX_SHORT_SZ; + word32 algoSz; + const byte* algoName; + + (void)heap; + + WOLFSSL_ENTER("EncryptContent()"); + + if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0) + return ASN_INPUT_E; /* Algo ID error */ + + if (version == PKCS5v2) { + WOLFSSL_MSG("PKCS#5 version 2 not supported yet"); + return BAD_FUNC_ARG; + } + + if (saltSz > MAX_SALT_SIZE) + return ASN_PARSE_E; + + if (outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* calculate size */ + /* size of constructed string at end */ + sz = Pkcs8Pad(NULL, inputSz, blockSz); + totalSz = ASN_TAG_SZ; + totalSz += SetLength(sz, seq); + totalSz += sz; + + /* size of sequence holding object id and sub sequence of salt and itt */ + algoName = OidFromId(id, oidPBEType, &algoSz); + if (algoName == NULL) { + WOLFSSL_MSG("Unknown Algorithm"); + return 0; + } + innerSz = SetObjectId(algoSz, seq); + innerSz += algoSz; + + /* get subsequence of salt and itt */ + if (salt == NULL || saltSz == 0) { + sz = 8; + } + else { + sz = saltSz; + } + seqSz = SetOctetString(sz, seq); + seqSz += sz; + + tmpIdx = 0; + seqSz += SetShortInt(shr, &tmpIdx, itt, maxShr); + innerSz += seqSz + SetSequence(seqSz, seq); + totalSz += innerSz + SetSequence(innerSz, seq); + + if (out == NULL) { + *outSz = totalSz; + return LENGTH_ONLY_E; + } + + inOutIdx = 0; + if (totalSz > *outSz) + return BUFFER_E; + + inOutIdx += SetSequence(innerSz, out + inOutIdx); + inOutIdx += SetObjectId(algoSz, out + inOutIdx); + XMEMCPY(out + inOutIdx, algoName, algoSz); + inOutIdx += algoSz; + inOutIdx += SetSequence(seqSz, out + inOutIdx); + + /* create random salt if one not provided */ + if (salt == NULL || saltSz == 0) { + saltSz = 8; + #ifdef WOLFSSL_SMALL_STACK + saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (saltTmp == NULL) + return MEMORY_E; + #endif + salt = saltTmp; + + if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) { + WOLFSSL_MSG("Error generating random salt"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + } + inOutIdx += SetOctetString(saltSz, out + inOutIdx); + if (saltSz + inOutIdx > *outSz) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + XMEMCPY(out + inOutIdx, salt, saltSz); + inOutIdx += saltSz; + + /* place iteration setting in buffer */ + ret = SetShortInt(out, &inOutIdx, itt, *outSz); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + if (inOutIdx + 1 > *outSz) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + out[inOutIdx++] = ASN_CONTEXT_SPECIFIC | 0; + + /* get pad size and verify buffer room */ + sz = Pkcs8Pad(NULL, inputSz, blockSz); + if (sz + inOutIdx > *outSz) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + inOutIdx += SetLength(sz, out + inOutIdx); + + /* copy input to output buffer and pad end */ + XMEMCPY(out + inOutIdx, input, inputSz); + sz = Pkcs8Pad(out + inOutIdx, inputSz, blockSz); +#ifdef WOLFSSL_SMALL_STACK + cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cbcIv == NULL) { + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + /* encrypt */ + if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id, + out + inOutIdx, sz, version, cbcIv, 1, 0)) < 0) { + + #ifdef WOLFSSL_SMALL_STACK + XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; /* encrypt failure */ + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + (void)rng; + + return inOutIdx + sz; +} + + +#endif /* HAVE_PKCS12 */ #endif /* NO_PWDBASED */ #ifndef NO_RSA -int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, - word32 inSz) +#ifndef HAVE_USER_RSA +#ifdef WOLFSSL_RENESAS_TSIP +/* This function is to retrieve key position information in a cert.* + * The information will be used to call TSIP TLS-linked API for * + * certificate verification. */ +static int RsaPublicKeyDecodeRawIndex(const byte* input, word32* inOutIdx, + word32 inSz, word32* key_n, + word32* key_n_len, word32* key_e, + word32* key_e_len) { - int length; + + int ret = 0; + int length = 0; +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + byte b; +#endif + + if (input == NULL || inOutIdx == NULL) + return BAD_FUNC_ARG; if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; - key->type = RSA_PUBLIC; - #if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) - { - byte b = input[*inOutIdx]; + if ((*inOutIdx + 1) > inSz) + return BUFFER_E; + + 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; - - b = input[(*inOutIdx)++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; - - if (GetLength(input, inOutIdx, &length, inSz) < 0) + + if (SkipObjectId(input, inOutIdx, inSz) < 0) return ASN_PARSE_E; - - *inOutIdx += length; /* skip past */ - - /* 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; + + /* Option NULL ASN.1 tag */ + if (*inOutIdx >= inSz) { + return BUFFER_E; } - else - /* go back, didn't have it */ - (*inOutIdx)--; - + 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; - } /* end if */ - } /* openssl var block */ + } #endif /* OPENSSL_EXTRA */ - if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || - GetInt(&key->e, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; + /* Get modulus */ + ret = GetASNInt(input, inOutIdx, &length, inSz); + *key_n += *inOutIdx; + if (ret < 0) { + return ASN_RSA_KEY_E; + } + if (key_n_len) + *key_n_len = length; + *inOutIdx += length; - return 0; + /* Get exponent */ + ret = GetASNInt(input, inOutIdx, &length, inSz); + *key_e += *inOutIdx; + if (ret < 0) { + return ASN_RSA_KEY_E; + } + if (key_e_len) + *key_e_len = length; + + return ret; +} +#endif /* WOLFSSL_RENESAS_TSIP */ + +int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz, + const byte** n, word32* nSz, const byte** e, word32* eSz) +{ + int ret = 0; + int length = 0; +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + word32 localIdx; + byte tag; +#endif + + if (input == NULL || inOutIdx == NULL) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + localIdx = *inOutIdx; + if (GetASNTag(input, &localIdx, &tag, inSz) < 0) + return BUFFER_E; + + if (tag != ASN_INTEGER) { + /* not from decoded cert, will have algo id, skip past */ + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (SkipObjectId(input, inOutIdx, inSz) < 0) + return ASN_PARSE_E; + + /* Option NULL ASN.1 tag */ + if (*inOutIdx >= inSz) { + return BUFFER_E; + } + + localIdx = *inOutIdx; + if (GetASNTag(input, &localIdx, &tag, inSz) < 0) + return ASN_PARSE_E; + + if (tag == ASN_TAG_NULL) { + ret = GetASNNull(input, inOutIdx, inSz); + if (ret != 0) + return ret; + } + + /* should have bit tag length and seq next */ + 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 */ + + /* Get modulus */ + ret = GetASNInt(input, inOutIdx, &length, inSz); + if (ret < 0) { + return ASN_RSA_KEY_E; + } + if (nSz) + *nSz = length; + if (n) + *n = &input[*inOutIdx]; + *inOutIdx += length; + + /* Get exponent */ + ret = GetASNInt(input, inOutIdx, &length, inSz); + if (ret < 0) { + return ASN_RSA_KEY_E; + } + if (eSz) + *eSz = length; + if (e) + *e = &input[*inOutIdx]; + *inOutIdx += length; + + return ret; +} + +int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, + word32 inSz) +{ + int ret; + const byte *n = NULL, *e = NULL; + word32 nSz = 0, eSz = 0; + + if (key == NULL) + return BAD_FUNC_ARG; + + ret = wc_RsaPublicKeyDecode_ex(input, inOutIdx, inSz, &n, &nSz, &e, &eSz); + if (ret == 0) { + ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, key); + } + + return ret; } /* import RSA public key elements (n, e) into RsaKey structure (key) */ @@ -1288,6 +4352,12 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, mp_clear(&key->n); return ASN_GETINT_E; } +#ifdef HAVE_WOLF_BIGINT + if ((int)nSz > 0 && wc_bigint_from_unsigned_bin(&key->n.raw, n, nSz) != 0) { + mp_clear(&key->n); + return ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ if (mp_init(&key->e) != MP_OKAY) { mp_clear(&key->n); @@ -1299,76 +4369,143 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, mp_clear(&key->e); return ASN_GETINT_E; } +#ifdef HAVE_WOLF_BIGINT + if ((int)eSz > 0 && wc_bigint_from_unsigned_bin(&key->e.raw, e, eSz) != 0) { + mp_clear(&key->n); + mp_clear(&key->e); + return ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ + +#ifdef WOLFSSL_XILINX_CRYPT + if (wc_InitRsaHw(key) != 0) { + return BAD_STATE_E; + } +#endif return 0; } - -#endif +#endif /* HAVE_USER_RSA */ +#endif /* !NO_RSA */ #ifndef NO_DH int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) { - int length; + int ret = 0; + int length; + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + word32 oid = 0, temp = 0; + #endif + + WOLFSSL_ENTER("wc_DhKeyDecode"); + + if (inOutIdx == NULL) + return BAD_FUNC_ARG; if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; - if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || - GetInt(&key->g, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E; + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + temp = *inOutIdx; + #endif - return 0; + /* Assume input started after 1.2.840.113549.1.3.1 dhKeyAgreement */ + if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || + GetInt(&key->g, input, inOutIdx, inSz) < 0) { + ret = ASN_DH_KEY_E; + } + + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + /* If ASN_DH_KEY_E: Check if input started at beginning of key */ + if (ret == ASN_DH_KEY_E) { + /* rewind back to after the first sequence */ + *inOutIdx = temp; + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + /* Check for dhKeyAgreement */ + ret = GetObjectId(input, inOutIdx, &oid, oidKeyType, inSz); + if (oid != DHk || ret < 0) + return ASN_DH_KEY_E; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || + GetInt(&key->g, input, inOutIdx, inSz) < 0) { + return ASN_DH_KEY_E; + } + } + + temp = *inOutIdx; + ret = (CheckBitString(input, inOutIdx, &length, inSz, 0, NULL) == 0); + if (ret > 0) { + /* Found Bit String */ + if (GetInt(&key->pub, input, inOutIdx, inSz) == 0) { + WOLFSSL_MSG("Found Public Key"); + ret = 0; + } + } else { + *inOutIdx = temp; + ret = (GetOctetString(input, inOutIdx, &length, inSz) >= 0); + if (ret > 0) { + /* Found Octet String */ + if (GetInt(&key->priv, input, inOutIdx, inSz) == 0) { + WOLFSSL_MSG("Found Private Key"); + ret = 0; + } + } else { + /* Don't use length from failed CheckBitString/GetOctetString */ + *inOutIdx = temp; + ret = 0; + } + } + #endif /* WOLFSSL_QT || OPENSSL_ALL */ + + WOLFSSL_MSG("wc_DhKeyDecode Success"); + + return ret; } int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, byte* g, word32* gInOutSz) { - word32 i = 0; - byte b; + word32 idx = 0; + int ret; int length; - if (GetSequence(input, &i, &length, inSz) < 0) + if (GetSequence(input, &idx, &length, inSz) <= 0) return ASN_PARSE_E; - b = input[i++]; - if (b != ASN_INTEGER) - return ASN_PARSE_E; - - if (GetLength(input, &i, &length, inSz) < 0) - return ASN_PARSE_E; - - if ( (b = input[i++]) == 0x00) - length--; - else - i--; + ret = GetASNInt(input, &idx, &length, inSz); + if (ret != 0) + return ret; if (length <= (int)*pInOutSz) { - XMEMCPY(p, &input[i], length); + XMEMCPY(p, &input[idx], length); *pInOutSz = length; } - else + else { return BUFFER_E; + } + idx += length; - i += length; - - b = input[i++]; - if (b != ASN_INTEGER) - return ASN_PARSE_E; - - if (GetLength(input, &i, &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[i], length); + XMEMCPY(g, &input[idx], length); *gInOutSz = length; } - else + else { return BUFFER_E; + } return 0; } - #endif /* NO_DH */ @@ -1378,6 +4515,11 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, word32 inSz) { int length; + int ret = 0; + word32 oid; + + if (input == NULL || inOutIdx == NULL || key == NULL) + return BAD_FUNC_ARG; if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -1385,148 +4527,431 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || GetInt(&key->q, input, inOutIdx, inSz) < 0 || GetInt(&key->g, input, inOutIdx, inSz) < 0 || - GetInt(&key->y, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E; + GetInt(&key->y, input, inOutIdx, inSz) < 0 ) + ret = ASN_DH_KEY_E; + + if (ret != 0) { + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + ret = GetObjectId(input, inOutIdx, &oid, oidIgnoreType, inSz); + if (ret != 0) + return ret; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || + GetInt(&key->q, input, inOutIdx, inSz) < 0 || + GetInt(&key->g, input, inOutIdx, inSz) < 0) + return ASN_DH_KEY_E; + + if (CheckBitString(input, inOutIdx, &length, inSz, 0, NULL) < 0) + return ASN_PARSE_E; + + if (GetInt(&key->y, input, inOutIdx, inSz) < 0 ) + return ASN_DH_KEY_E; + + ret = 0; + } key->type = DSA_PUBLIC; - return 0; + return ret; } int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, word32 inSz) { - int length, version; + int length, version, ret = 0, temp = 0; + + /* 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; - if (GetMyVersion(input, inOutIdx, &version) < 0) - return ASN_PARSE_E; + temp = (int)*inOutIdx; - if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || - GetInt(&key->q, input, inOutIdx, inSz) < 0 || - GetInt(&key->g, input, inOutIdx, inSz) < 0 || - GetInt(&key->y, input, inOutIdx, inSz) < 0 || - GetInt(&key->x, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E; + /* Default case expects a certificate with OctetString but no version ID */ + ret = GetInt(&key->p, input, inOutIdx, inSz); + if (ret < 0) { + mp_clear(&key->p); + ret = ASN_PARSE_E; + } + else { + ret = GetInt(&key->q, input, inOutIdx, inSz); + if (ret < 0) { + mp_clear(&key->p); + mp_clear(&key->q); + ret = ASN_PARSE_E; + } + else { + ret = GetInt(&key->g, input, inOutIdx, inSz); + if (ret < 0) { + mp_clear(&key->p); + mp_clear(&key->q); + mp_clear(&key->g); + ret = ASN_PARSE_E; + } + else { + ret = GetOctetString(input, inOutIdx, &length, inSz); + if (ret < 0) { + mp_clear(&key->p); + mp_clear(&key->q); + mp_clear(&key->g); + ret = ASN_PARSE_E; + } + else { + ret = GetInt(&key->y, input, inOutIdx, inSz); + if (ret < 0) { + mp_clear(&key->p); + mp_clear(&key->q); + mp_clear(&key->g); + mp_clear(&key->y); + ret = ASN_PARSE_E; + } + } + } + } + } + /* An alternate pass if default certificate fails parsing */ + if (ret == ASN_PARSE_E) { + *inOutIdx = temp; + if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) + return ASN_PARSE_E; + + if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || + GetInt(&key->q, input, inOutIdx, inSz) < 0 || + GetInt(&key->g, input, inOutIdx, inSz) < 0 || + GetInt(&key->y, input, inOutIdx, inSz) < 0 || + GetInt(&key->x, input, inOutIdx, inSz) < 0 ) + return ASN_DH_KEY_E; + } key->type = DSA_PRIVATE; return 0; } +static mp_int* GetDsaInt(DsaKey* key, int idx) +{ + if (idx == 0) + return &key->p; + if (idx == 1) + return &key->q; + if (idx == 2) + return &key->g; + if (idx == 3) + return &key->y; + if (idx == 4) + return &key->x; + + return NULL; +} + +/* Release Tmp DSA resources */ +static WC_INLINE void FreeTmpDsas(byte** tmps, void* heap) +{ + int i; + + for (i = 0; i < DSA_INTS; i++) + XFREE(tmps[i], heap, DYNAMIC_TYPE_DSA); + + (void)heap; +} + +#if !defined(HAVE_SELFTEST) && defined(WOLFSSL_KEY_GEN) +/* Write a public DSA key to output */ +int wc_SetDsaPublicKey(byte* output, DsaKey* key, + int outLen, int with_header) +{ + /* p, g, q = DSA params, y = public exponent */ +#ifdef WOLFSSL_SMALL_STACK + byte* p = NULL; + byte* g = NULL; + byte* q = NULL; + byte* y = NULL; +#else + byte p[MAX_DSA_INT_SZ]; + byte g[MAX_DSA_INT_SZ]; + byte q[MAX_DSA_INT_SZ]; + byte y[MAX_DSA_INT_SZ]; +#endif + byte innerSeq[MAX_SEQ_SZ]; + byte outerSeq[MAX_SEQ_SZ]; + byte bitString[1 + MAX_LENGTH_SZ + 1]; + int idx, pSz, gSz, qSz, ySz, innerSeqSz, outerSeqSz, bitStringSz = 0; + + WOLFSSL_ENTER("wc_SetDsaPublicKey"); + + if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) { + return BAD_FUNC_ARG; + } + + /* p */ +#ifdef WOLFSSL_SMALL_STACK + p = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (p == NULL) + return MEMORY_E; +#endif + if ((pSz = SetASNIntMP(&key->p, MAX_DSA_INT_SZ, p)) < 0) { + WOLFSSL_MSG("SetASNIntMP Error with p"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return pSz; + } + + /* q */ +#ifdef WOLFSSL_SMALL_STACK + q = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (q == NULL) + return MEMORY_E; +#endif + if ((qSz = SetASNIntMP(&key->q, MAX_DSA_INT_SZ, q)) < 0) { + WOLFSSL_MSG("SetASNIntMP Error with q"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return qSz; + } + + /* g */ +#ifdef WOLFSSL_SMALL_STACK + g = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (g == NULL) + return MEMORY_E; +#endif + if ((gSz = SetASNIntMP(&key->g, MAX_DSA_INT_SZ, g)) < 0) { + WOLFSSL_MSG("SetASNIntMP Error with g"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return gSz; + } + + /* y */ +#ifdef WOLFSSL_SMALL_STACK + y = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (y == NULL) + return MEMORY_E; +#endif + if ((ySz = SetASNIntMP(&key->y, MAX_DSA_INT_SZ, y)) < 0) { + WOLFSSL_MSG("SetASNIntMP Error with y"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ySz; + } + + innerSeqSz = SetSequence(pSz + qSz + gSz, innerSeq); + + /* check output size */ + if ((innerSeqSz + pSz + qSz + gSz) > outLen) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + WOLFSSL_MSG("Error, output size smaller than outlen"); + return BUFFER_E; + } + + if (with_header) { + int algoSz; +#ifdef WOLFSSL_SMALL_STACK + byte* algo = NULL; + + algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#else + byte algo[MAX_ALGO_SZ]; +#endif + algoSz = SetAlgoID(DSAk, algo, oidKeyType, 0); + bitStringSz = SetBitString(ySz, 0, bitString); + outerSeqSz = SetSequence(algoSz + innerSeqSz + pSz + qSz + gSz, + outerSeq); + + idx = SetSequence(algoSz + innerSeqSz + pSz + qSz + gSz + bitStringSz + + ySz + outerSeqSz, output); + + /* check output size */ + if ((idx + algoSz + bitStringSz + innerSeqSz + pSz + qSz + gSz + ySz) > + outLen) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + WOLFSSL_MSG("Error, output size smaller than outlen"); + return BUFFER_E; + } + + /* outerSeq */ + XMEMCPY(output + idx, outerSeq, outerSeqSz); + idx += outerSeqSz; + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; +#ifdef WOLFSSL_SMALL_STACK + XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } else { + idx = 0; + } + + /* innerSeq */ + XMEMCPY(output + idx, innerSeq, innerSeqSz); + idx += innerSeqSz; + /* p */ + XMEMCPY(output + idx, p, pSz); + idx += pSz; + /* q */ + XMEMCPY(output + idx, q, qSz); + idx += qSz; + /* g */ + XMEMCPY(output + idx, g, gSz); + idx += gSz; + /* bit string */ + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; + /* y */ + XMEMCPY(output + idx, y, ySz); + idx += ySz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return idx; +} + +/* Convert DSA Public key to DER format, write to output (inLen), return bytes + written */ +int wc_DsaKeyToPublicDer(DsaKey* key, byte* output, word32 inLen) +{ + return wc_SetDsaPublicKey(output, key, inLen, 1); +} +#endif /* !HAVE_SELFTEST && WOLFSSL_KEY_GEN */ + +/* Convert private DsaKey key to DER format, write to output (inLen), + return bytes written */ +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, mpSz; + + byte seq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + byte* tmps[DSA_INTS]; + + if (!key || !output) + return BAD_FUNC_ARG; + + if (key->type != DSA_PRIVATE) + return BAD_FUNC_ARG; + + for (i = 0; i < DSA_INTS; i++) + tmps[i] = NULL; + + /* write all big ints from key to DER tmps */ + for (i = 0; i < DSA_INTS; i++) { + mp_int* keyInt = GetDsaInt(key, i); + + rawLen = mp_unsigned_bin_size(keyInt) + 1; + tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, + DYNAMIC_TYPE_DSA); + if (tmps[i] == NULL) { + ret = MEMORY_E; + break; + } + + mpSz = SetASNIntMP(keyInt, -1, tmps[i]); + if (mpSz < 0) { + ret = mpSz; + break; + } + intTotalLen += (sizes[i] = mpSz); + } + + if (ret != 0) { + FreeTmpDsas(tmps, key->heap); + return ret; + } + + /* make headers */ + verSz = SetMyVersion(0, ver, FALSE); + seqSz = SetSequence(verSz + intTotalLen, seq); + + outLen = seqSz + verSz + intTotalLen; + if (outLen > (int)inLen) { + FreeTmpDsas(tmps, key->heap); + return BAD_FUNC_ARG; + } + + /* write to output */ + XMEMCPY(output, seq, seqSz); + j = seqSz; + XMEMCPY(output + j, ver, verSz); + j += verSz; + + for (i = 0; i < DSA_INTS; i++) { + XMEMCPY(output + j, tmps[i], sizes[i]); + j += sizes[i]; + } + FreeTmpDsas(tmps, key->heap); + + return outLen; +} + #endif /* NO_DSA */ - -void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) +void InitDecodedCert(DecodedCert* cert, + const byte* source, word32 inSz, void* heap) { - cert->publicKey = 0; - cert->pubKeySize = 0; - cert->pubKeyStored = 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; -#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->extBasicConstSet = 0; - cert->extBasicConstCrit = 0; - cert->extBasicConstPlSet = 0; - cert->pathLength = 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 */ + 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; + cert->maxPathLen = WOLFSSL_MAX_PATH_LEN; + #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 */ + + #ifndef NO_CERTS + InitSignatureCtx(&cert->sigCtx, heap, INVALID_DEVID); + #endif + } } @@ -1562,10 +4987,12 @@ void FreeNameSubtrees(Base_entry* names, void* heap) void FreeDecodedCert(DecodedCert* cert) { + if (cert == NULL) + return; if (cert->subjectCNStored == 1) XFREE(cert->subjectCN, cert->heap, DYNAMIC_TYPE_SUBJECT_CN); if (cert->pubKeyStored == 1) - XFREE(cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE((void*)cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (cert->weOwnAltNames && cert->altNames) FreeAltNames(cert->altNames, cert->heap); #ifndef IGNORE_NAME_CONSTRAINTS @@ -1577,126 +5004,92 @@ void FreeDecodedCert(DecodedCert* cert) FreeNameSubtrees(cert->excludedNames, cert->heap); #endif /* IGNORE_NAME_CONSTRAINTS */ #ifdef WOLFSSL_SEP - XFREE(cert->deviceType, cert->heap, 0); - XFREE(cert->hwType, cert->heap, 0); - XFREE(cert->hwSerialNum, cert->heap, 0); + XFREE(cert->deviceType, cert->heap, DYNAMIC_TYPE_X509_EXT); + XFREE(cert->hwType, cert->heap, DYNAMIC_TYPE_X509_EXT); + XFREE(cert->hwSerialNum, cert->heap, DYNAMIC_TYPE_X509_EXT); #endif /* WOLFSSL_SEP */ -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) if (cert->issuerName.fullName != NULL) - XFREE(cert->issuerName.fullName, NULL, DYNAMIC_TYPE_X509); + XFREE(cert->issuerName.fullName, cert->heap, DYNAMIC_TYPE_X509); if (cert->subjectName.fullName != NULL) - XFREE(cert->subjectName.fullName, NULL, DYNAMIC_TYPE_X509); + XFREE(cert->subjectName.fullName, cert->heap, DYNAMIC_TYPE_X509); #endif /* OPENSSL_EXTRA */ +#ifdef WOLFSSL_RENESAS_TSIP_TLS + if (cert->tsip_encRsaKeyIdx != NULL) + XFREE(cert->tsip_encRsaKeyIdx, cert->heap, DYNAMIC_TYPE_RSA); +#endif +#ifndef NO_CERTS + FreeSignatureCtx(&cert->sigCtx); +#endif } - static int GetCertHeader(DecodedCert* cert) { int ret = 0, len; - byte serialTmp[EXTERNAL_SERIAL_SIZE]; -#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH) - mp_int* mpi = NULL; -#else - mp_int stack_mpi; - mp_int* mpi = &stack_mpi; -#endif if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0) return ASN_PARSE_E; + /* Reset the max index for the size indicated in the outer wrapper. */ + cert->maxIdx = len + cert->srcIdx; cert->certBegin = cert->srcIdx; if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0) return ASN_PARSE_E; + cert->sigIndex = len + cert->srcIdx; - - if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version) < 0) + if (cert->sigIndex > cert->maxIdx) return ASN_PARSE_E; -#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH) - mpi = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (mpi == NULL) - return MEMORY_E; -#endif - - if (GetInt(mpi, cert->source, &cert->srcIdx, cert->maxIdx) < 0) { -#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH) - XFREE(mpi, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version, + cert->sigIndex) < 0) return ASN_PARSE_E; - } - len = mp_unsigned_bin_size(mpi); - if (len < (int)sizeof(serialTmp)) { - if ( (ret = mp_to_unsigned_bin(mpi, serialTmp)) == MP_OKAY) { - XMEMCPY(cert->serial, serialTmp, len); - cert->serialSz = len; - } - } - mp_clear(mpi); - -#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH) - XFREE(mpi, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + if (GetSerialNumber(cert->source, &cert->srcIdx, cert->serial, + &cert->serialSz, cert->sigIndex) < 0) + return ASN_PARSE_E; return ret; } #if !defined(NO_RSA) /* Store Rsa Key, may save later, Dsa could use in future */ -static int StoreRsaKey(DecodedCert* cert) +static int StoreRsaKey(DecodedCert* cert, word32 bitStringEnd) { int length; word32 recvd = cert->srcIdx; - if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + if (GetSequence(cert->source, &cert->srcIdx, &length, bitStringEnd) < 0) return ASN_PARSE_E; - + recvd = cert->srcIdx - recvd; length += recvd; while (recvd--) cert->srcIdx--; - +#if defined(WOLFSSL_RENESAS_TSIP) + cert->sigCtx.pubkey_n_start = cert->sigCtx.pubkey_e_start = cert->srcIdx; +#endif cert->pubKeySize = length; cert->publicKey = cert->source + cert->srcIdx; cert->srcIdx += length; return 0; } -#endif - +#endif /* !NO_RSA */ #ifdef HAVE_ECC - /* return 0 on sucess if the ECC curve oid sum is supported */ + /* return 0 on success if the ECC curve oid sum is supported */ static int CheckCurve(word32 oid) { int ret = 0; + word32 oidSz = 0; - switch (oid) { -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) - case ECC_160R1: -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) - case ECC_192R1: -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) - case ECC_224R1: -#endif -#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) - case ECC_256R1: -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) - case ECC_384R1: -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) - case ECC_521R1: -#endif - break; - - default: - ret = ALGO_ID_E; + ret = wc_ecc_get_oid(oid, NULL, &oidSz); + if (ret < 0 || oidSz == 0) { + WOLFSSL_MSG("CheckCurve not found"); + ret = ALGO_ID_E; } return ret; @@ -1704,35 +5097,46 @@ static int StoreRsaKey(DecodedCert* cert) #endif /* HAVE_ECC */ - static int GetKey(DecodedCert* cert) { int length; -#ifdef HAVE_NTRU +#if !defined(NO_DSA) && defined(WOLFSSL_QT) + int tmpLen; +#endif +#if defined(HAVE_ECC) || defined(HAVE_NTRU) int tmpIdx = cert->srcIdx; #endif if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) return ASN_PARSE_E; - - if (GetAlgoId(cert->source, &cert->srcIdx, &cert->keyOID, cert->maxIdx) < 0) + +#if !defined(NO_DSA) && defined(WOLFSSL_QT) + tmpLen = length + 4; +#endif + + if (GetAlgoId(cert->source, &cert->srcIdx, + &cert->keyOID, oidKeyType, cert->maxIdx) < 0) return ASN_PARSE_E; switch (cert->keyOID) { #ifndef NO_RSA case RSAk: { - byte b = cert->source[cert->srcIdx++]; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; + int ret; - 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; - - return StoreRsaKey(cert); + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; + + #ifdef HAVE_OCSP + ret = CalcHashId(cert->source + cert->srcIdx, length, + cert->subjectKeyHash); + if (ret != 0) + return ret; + #endif + + return StoreRsaKey(cert, cert->srcIdx + length); } #endif /* NO_RSA */ @@ -1744,6 +5148,7 @@ static int GetKey(DecodedCert* cert) word16 keyLen; word32 rc; word32 remaining = cert->maxIdx - cert->srcIdx; + byte* publicKey; #ifdef WOLFSSL_SMALL_STACK byte* keyBlob = NULL; #else @@ -1757,8 +5162,8 @@ static int GetKey(DecodedCert* cert) return ASN_NTRU_KEY_E; #ifdef WOLFSSL_SMALL_STACK - keyBlob = (byte*)XMALLOC(MAX_NTRU_KEY_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + keyBlob = (byte*)XMALLOC(MAX_NTRU_KEY_SZ, cert->heap, + DYNAMIC_TYPE_TMP_BUFFER); if (keyBlob == NULL) return MEMORY_E; #endif @@ -1767,34 +5172,35 @@ static int GetKey(DecodedCert* cert) &keyLen, keyBlob, &next, &remaining); if (rc != NTRU_OK) { #ifdef WOLFSSL_SMALL_STACK - XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ASN_NTRU_KEY_E; } if ( (next - key) < 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ASN_NTRU_KEY_E; } cert->srcIdx = tmpIdx + (int)(next - key); - cert->publicKey = (byte*) XMALLOC(keyLen, cert->heap, - DYNAMIC_TYPE_PUBLIC_KEY); - if (cert->publicKey == NULL) { + publicKey = (byte*)XMALLOC(keyLen, cert->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (publicKey == NULL) { #ifdef WOLFSSL_SMALL_STACK - XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return MEMORY_E; } - XMEMCPY(cert->publicKey, keyBlob, keyLen); + XMEMCPY(publicKey, keyBlob, keyLen); + cert->publicKey = publicKey; cert->pubKeyStored = 1; cert->pubKeySize = keyLen; #ifdef WOLFSSL_SMALL_STACK - XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return 0; @@ -1803,40 +5209,78 @@ static int GetKey(DecodedCert* cert) #ifdef HAVE_ECC case ECDSAk: { - int oidSz = 0; - byte b = cert->source[cert->srcIdx++]; - - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; + int ret; + byte seq[5]; + int pubLen = length + 1 + SetLength(length, seq); + word32 localIdx; + byte* publicKey; + byte tag; - if (GetLength(cert->source,&cert->srcIdx,&oidSz,cert->maxIdx) < 0) + localIdx = cert->srcIdx; + if (GetASNTag(cert->source, &localIdx, &tag, cert->maxIdx) < 0) return ASN_PARSE_E; - while(oidSz--) - cert->pkCurveOID += cert->source[cert->srcIdx++]; + if (tag != (ASN_SEQUENCE | ASN_CONSTRUCTED)) { + if (GetObjectId(cert->source, &cert->srcIdx, + &cert->pkCurveOID, oidCurveType, cert->maxIdx) < 0) + return ASN_PARSE_E; - if (CheckCurve(cert->pkCurveOID) < 0) - return ECC_CURVE_OID_E; + if (CheckCurve(cert->pkCurveOID) < 0) + return ECC_CURVE_OID_E; - /* key header */ - b = cert->source[cert->srcIdx++]; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; + /* key header */ + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; + #ifdef HAVE_OCSP + ret = CalcHashId(cert->source + cert->srcIdx, length, + cert->subjectKeyHash); + if (ret != 0) + return ret; + #endif + } - 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; - - /* actual key, use length - 1 since ate preceding 0 */ - length -= 1; - - cert->publicKey = (byte*) XMALLOC(length, cert->heap, - DYNAMIC_TYPE_PUBLIC_KEY); - if (cert->publicKey == NULL) + publicKey = (byte*)XMALLOC(pubLen, cert->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (publicKey == NULL) return MEMORY_E; - XMEMCPY(cert->publicKey, &cert->source[cert->srcIdx], length); + XMEMCPY(publicKey, &cert->source[tmpIdx], pubLen); + cert->publicKey = publicKey; + cert->pubKeyStored = 1; + cert->pubKeySize = pubLen; + + cert->srcIdx = tmpIdx + pubLen; + + return 0; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + byte* publicKey; + int ret; + + cert->pkCurveOID = ED25519k; + + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; + + #ifdef HAVE_OCSP + ret = CalcHashId(cert->source + cert->srcIdx, length, + cert->subjectKeyHash); + if (ret != 0) + return ret; + #endif + + publicKey = (byte*) XMALLOC(length, cert->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (publicKey == NULL) + return MEMORY_E; + XMEMCPY(publicKey, &cert->source[cert->srcIdx], length); + cert->publicKey = publicKey; cert->pubKeyStored = 1; cert->pubKeySize = length; @@ -1844,25 +5288,238 @@ static int GetKey(DecodedCert* cert) return 0; } - #endif /* HAVE_ECC */ + #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED448 + case ED448k: + { + byte* publicKey; + int ret; + + cert->pkCurveOID = ED448k; + + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; + + #ifdef HAVE_OCSP + ret = CalcHashId(cert->source + cert->srcIdx, length, + cert->subjectKeyHash); + if (ret != 0) + return ret; + #endif + + publicKey = (byte*) XMALLOC(length, cert->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (publicKey == NULL) + return MEMORY_E; + XMEMCPY(publicKey, &cert->source[cert->srcIdx], length); + cert->publicKey = publicKey; + cert->pubKeyStored = 1; + cert->pubKeySize = length; + + cert->srcIdx += length; + + return 0; + } + #endif /* HAVE_ED448 */ + #if !defined(NO_DSA) && defined(WOLFSSL_QT) + case DSAk: + { + int ret; + ret = GetSequence(cert->source, &cert->srcIdx, &length, + cert->maxIdx); + if (ret < 0) + return ret; + + ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx); + if (ret != 0) + return ret; + ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx); + if (ret != 0) + return ret; + ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx); + if (ret != 0) + return ret; + + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; + + ret = GetASNInt(cert->source, &cert->srcIdx, &length, cert->maxIdx); + if (ret !=0) + return ASN_PARSE_E; + + cert->publicKey = cert->source + tmpIdx; + cert->pubKeySize = tmpLen; + cert->srcIdx += length; + return 0; + } + #endif /* NO_DSA && QT */ default: return ASN_UNKNOWN_OID_E; } } +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +#if defined(HAVE_ECC) +/* Converts ECC curve enum values in ecc_curve_id to the associated OpenSSL NID + value */ +WOLFSSL_API int EccEnumToNID(int n) +{ + WOLFSSL_ENTER("EccEnumToNID()"); + + switch(n) { + case ECC_SECP192R1: + return NID_X9_62_prime192v1; + case ECC_PRIME192V2: + return NID_X9_62_prime192v2; + case ECC_PRIME192V3: + return NID_X9_62_prime192v3; + case ECC_PRIME239V1: + return NID_X9_62_prime239v1; + case ECC_PRIME239V2: + return NID_X9_62_prime239v2; + case ECC_PRIME239V3: + return NID_X9_62_prime239v3; + case ECC_SECP256R1: + return NID_X9_62_prime256v1; + case ECC_SECP112R1: + return NID_secp112r1; + case ECC_SECP112R2: + return NID_secp112r2; + case ECC_SECP128R1: + return NID_secp128r1; + case ECC_SECP128R2: + return NID_secp128r2; + case ECC_SECP160R1: + return NID_secp160r1; + case ECC_SECP160R2: + return NID_secp160r2; + case ECC_SECP224R1: + return NID_secp224r1; + case ECC_SECP384R1: + return NID_secp384r1; + case ECC_SECP521R1: + return NID_secp521r1; + case ECC_SECP160K1: + return NID_secp160k1; + case ECC_SECP192K1: + return NID_secp192k1; + case ECC_SECP224K1: + return NID_secp224k1; + case ECC_SECP256K1: + return NID_secp256k1; + case ECC_BRAINPOOLP160R1: + return NID_brainpoolP160r1; + case ECC_BRAINPOOLP192R1: + return NID_brainpoolP192r1; + case ECC_BRAINPOOLP224R1: + return NID_brainpoolP224r1; + case ECC_BRAINPOOLP256R1: + return NID_brainpoolP256r1; + case ECC_BRAINPOOLP320R1: + return NID_brainpoolP320r1; + case ECC_BRAINPOOLP384R1: + return NID_brainpoolP384r1; + case ECC_BRAINPOOLP512R1: + return NID_brainpoolP512r1; + default: + WOLFSSL_MSG("NID not found"); + return -1; + } +} +#endif /* HAVE_ECC */ +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +int wc_OBJ_sn2nid(const char *sn) +{ + const struct { + const char *sn; + int nid; + } sn2nid[] = { + {WOLFSSL_COMMON_NAME, NID_commonName}, + {WOLFSSL_COUNTRY_NAME, NID_countryName}, + {WOLFSSL_LOCALITY_NAME, NID_localityName}, + {WOLFSSL_STATE_NAME, NID_stateOrProvinceName}, + {WOLFSSL_ORG_NAME, NID_organizationName}, + {WOLFSSL_ORGUNIT_NAME, NID_organizationalUnitName}, + {WOLFSSL_EMAIL_ADDR, NID_emailAddress}, + {NULL, -1}}; + + int i; + #ifdef HAVE_ECC + int eccEnum; + #endif + WOLFSSL_ENTER("OBJ_sn2nid"); + for(i=0; sn2nid[i].sn != NULL; i++) { + if(XSTRNCMP(sn, sn2nid[i].sn, XSTRLEN(sn2nid[i].sn)) == 0) { + return sn2nid[i].nid; + } + } + #ifdef HAVE_ECC + /* 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; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++) { + if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) { + eccEnum = ecc_sets[i].id; + /* Convert enum value in ecc_curve_id to OpenSSL NID */ + return EccEnumToNID(eccEnum); + } + } + #endif + + return NID_undef; +} +#endif + +/* Routine for calculating hashId */ +int CalcHashId(const byte* data, word32 len, byte* hash) +{ + int ret; + +#ifdef WOLF_CRYPTO_CB + /* try to use a registered crypto callback */ + ret = wc_CryptoCb_Sha256Hash(NULL, data, len, hash); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ +#endif + +#if defined(NO_SHA) && !defined(NO_SHA256) + ret = wc_Sha256Hash(data, len, hash); +#elif !defined(NO_SHA) + ret = wc_ShaHash(data, len, hash); +#else + ret = NOT_COMPILED_IN; +#endif + + return ret; +} /* process NAME, either issuer or subject */ -static int GetName(DecodedCert* cert, int nameType) +static int GetName(DecodedCert* cert, int nameType, int maxIdx) { int length; /* length of all distinguished names */ int dummy; int ret; char* full; byte* hash; - word32 idx; - #ifdef OPENSSL_EXTRA + word32 idx, localIdx = 0; + byte tag; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) DecodedName* dName = (nameType == ISSUER) ? &cert->issuerName : &cert->subjectName; + int dcnum = 0; + #ifdef OPENSSL_EXTRA + int count = 0; + #endif #endif /* OPENSSL_EXTRA */ WOLFSSL_MSG("Getting Cert Name"); @@ -1876,13 +5533,20 @@ static int GetName(DecodedCert* cert, int nameType) hash = cert->subjectHash; } - if (cert->source[cert->srcIdx] == ASN_OBJECT_ID) { + if (cert->srcIdx >= (word32)maxIdx) { + return BUFFER_E; + } + + localIdx = cert->srcIdx; + if (GetASNTag(cert->source, &localIdx, &tag, maxIdx) < 0) { + return ASN_PARSE_E; + } + + if (tag == ASN_OBJECT_ID) { WOLFSSL_MSG("Trying optional prefix..."); - if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + if (SkipObjectId(cert->source, &cert->srcIdx, maxIdx) < 0) return ASN_PARSE_E; - - cert->srcIdx += length; WOLFSSL_MSG("Got optional prefix"); } @@ -1890,21 +5554,17 @@ static int GetName(DecodedCert* cert, int nameType) * calculated over the entire DER encoding of the Name field, including * the tag and length. */ idx = cert->srcIdx; - if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + if (GetSequence(cert->source, &cert->srcIdx, &length, maxIdx) < 0) return ASN_PARSE_E; -#ifdef NO_SHA - ret = wc_Sha256Hash(&cert->source[idx], length + cert->srcIdx - idx, hash); -#else - ret = wc_ShaHash(&cert->source[idx], length + cert->srcIdx - idx, hash); -#endif + ret = CalcHashId(&cert->source[idx], length + cert->srcIdx - idx, hash); if (ret != 0) return ret; length += cert->srcIdx; idx = 0; -#ifdef HAVE_PKCS7 +#if defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT) /* store pointer to raw issuer */ if (nameType == ISSUER) { cert->issuerRaw = &cert->source[cert->srcIdx]; @@ -1919,45 +5579,39 @@ static int GetName(DecodedCert* cert, int nameType) #endif while (cert->srcIdx < (word32)length) { - byte b; - byte joint[2]; - byte tooBig = FALSE; - int oidSz; + byte b = 0; + byte joint[3]; + byte tooBig = FALSE; + int oidSz; + const char* copy = NULL; + int copyLen = 0; + int strLen = 0; + byte id = 0; - if (GetSet(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0) { + if (GetSet(cert->source, &cert->srcIdx, &dummy, maxIdx) < 0) { WOLFSSL_MSG("Cert name lacks set header, trying sequence"); } - if (GetSequence(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0) + if (GetSequence(cert->source, &cert->srcIdx, &dummy, maxIdx) <= 0) return ASN_PARSE_E; - b = cert->source[cert->srcIdx++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; + ret = GetASNObjectId(cert->source, &cert->srcIdx, &oidSz, maxIdx); + if (ret != 0) + return ret; - if (GetLength(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx) < 0) + /* make sure there is room for joint */ + if ((cert->srcIdx + sizeof(joint)) > (word32)maxIdx) return ASN_PARSE_E; XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint)); /* v1 name types */ if (joint[0] == 0x55 && joint[1] == 0x04) { - byte id; - byte copy = FALSE; - int strLen; - - cert->srcIdx += 2; - id = cert->source[cert->srcIdx++]; - b = cert->source[cert->srcIdx++]; /* encoding */ - - if (GetLength(cert->source, &cert->srcIdx, &strLen, - cert->maxIdx) < 0) + cert->srcIdx += 3; + id = joint[2]; + if (GetHeader(cert->source, &b, &cert->srcIdx, &strLen, + maxIdx, 1) < 0) { return ASN_PARSE_E; - - if ( (strLen + 14) > (int)(ASN_NAME_MAX - idx)) { - /* include biggest pre fix header too 4 = "/serialNumber=" */ - WOLFSSL_MSG("ASN Name too big, skipping"); - tooBig = TRUE; } if (id == ASN_COMMON_NAME) { @@ -1967,22 +5621,16 @@ static int GetName(DecodedCert* cert, int nameType) cert->subjectCNEnc = b; } - if (!tooBig) { - XMEMCPY(&full[idx], "/CN=", 4); - idx += 4; - copy = TRUE; - } - #ifdef OPENSSL_EXTRA + copy = WOLFSSL_COMMON_NAME; + copyLen = sizeof(WOLFSSL_COMMON_NAME) - 1; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) dName->cnIdx = cert->srcIdx; dName->cnLen = strLen; #endif /* OPENSSL_EXTRA */ } else if (id == ASN_SUR_NAME) { - if (!tooBig) { - XMEMCPY(&full[idx], "/SN=", 4); - idx += 4; - copy = TRUE; - } + copy = WOLFSSL_SUR_NAME; + copyLen = sizeof(WOLFSSL_SUR_NAME) - 1; #ifdef WOLFSSL_CERT_GEN if (nameType == SUBJECT) { cert->subjectSN = (char*)&cert->source[cert->srcIdx]; @@ -1990,17 +5638,14 @@ static int GetName(DecodedCert* cert, int nameType) cert->subjectSNEnc = b; } #endif /* WOLFSSL_CERT_GEN */ - #ifdef OPENSSL_EXTRA + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) dName->snIdx = cert->srcIdx; dName->snLen = strLen; #endif /* OPENSSL_EXTRA */ } else if (id == ASN_COUNTRY_NAME) { - if (!tooBig) { - XMEMCPY(&full[idx], "/C=", 3); - idx += 3; - copy = TRUE; - } + copy = WOLFSSL_COUNTRY_NAME; + copyLen = sizeof(WOLFSSL_COUNTRY_NAME) - 1; #ifdef WOLFSSL_CERT_GEN if (nameType == SUBJECT) { cert->subjectC = (char*)&cert->source[cert->srcIdx]; @@ -2008,17 +5653,14 @@ static int GetName(DecodedCert* cert, int nameType) cert->subjectCEnc = b; } #endif /* WOLFSSL_CERT_GEN */ - #ifdef OPENSSL_EXTRA + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) dName->cIdx = cert->srcIdx; dName->cLen = strLen; #endif /* OPENSSL_EXTRA */ } else if (id == ASN_LOCALITY_NAME) { - if (!tooBig) { - XMEMCPY(&full[idx], "/L=", 3); - idx += 3; - copy = TRUE; - } + copy = WOLFSSL_LOCALITY_NAME; + copyLen = sizeof(WOLFSSL_LOCALITY_NAME) - 1; #ifdef WOLFSSL_CERT_GEN if (nameType == SUBJECT) { cert->subjectL = (char*)&cert->source[cert->srcIdx]; @@ -2026,17 +5668,14 @@ static int GetName(DecodedCert* cert, int nameType) cert->subjectLEnc = b; } #endif /* WOLFSSL_CERT_GEN */ - #ifdef OPENSSL_EXTRA + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) dName->lIdx = cert->srcIdx; dName->lLen = strLen; #endif /* OPENSSL_EXTRA */ } else if (id == ASN_STATE_NAME) { - if (!tooBig) { - XMEMCPY(&full[idx], "/ST=", 4); - idx += 4; - copy = TRUE; - } + copy = WOLFSSL_STATE_NAME; + copyLen = sizeof(WOLFSSL_STATE_NAME) - 1; #ifdef WOLFSSL_CERT_GEN if (nameType == SUBJECT) { cert->subjectST = (char*)&cert->source[cert->srcIdx]; @@ -2044,17 +5683,14 @@ static int GetName(DecodedCert* cert, int nameType) cert->subjectSTEnc = b; } #endif /* WOLFSSL_CERT_GEN */ - #ifdef OPENSSL_EXTRA + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) dName->stIdx = cert->srcIdx; dName->stLen = strLen; #endif /* OPENSSL_EXTRA */ } else if (id == ASN_ORG_NAME) { - if (!tooBig) { - XMEMCPY(&full[idx], "/O=", 3); - idx += 3; - copy = TRUE; - } + copy = WOLFSSL_ORG_NAME; + copyLen = sizeof(WOLFSSL_ORG_NAME) - 1; #ifdef WOLFSSL_CERT_GEN if (nameType == SUBJECT) { cert->subjectO = (char*)&cert->source[cert->srcIdx]; @@ -2062,17 +5698,14 @@ static int GetName(DecodedCert* cert, int nameType) cert->subjectOEnc = b; } #endif /* WOLFSSL_CERT_GEN */ - #ifdef OPENSSL_EXTRA + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) dName->oIdx = cert->srcIdx; dName->oLen = strLen; #endif /* OPENSSL_EXTRA */ } else if (id == ASN_ORGUNIT_NAME) { - if (!tooBig) { - XMEMCPY(&full[idx], "/OU=", 4); - idx += 4; - copy = TRUE; - } + copy = WOLFSSL_ORGUNIT_NAME; + copyLen = sizeof(WOLFSSL_ORGUNIT_NAME) - 1; #ifdef WOLFSSL_CERT_GEN if (nameType == SUBJECT) { cert->subjectOU = (char*)&cert->source[cert->srcIdx]; @@ -2080,75 +5713,148 @@ static int GetName(DecodedCert* cert, int nameType) cert->subjectOUEnc = b; } #endif /* WOLFSSL_CERT_GEN */ - #ifdef OPENSSL_EXTRA + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) dName->ouIdx = cert->srcIdx; dName->ouLen = strLen; #endif /* OPENSSL_EXTRA */ } else if (id == ASN_SERIAL_NUMBER) { - if (!tooBig) { - XMEMCPY(&full[idx], "/serialNumber=", 14); - idx += 14; - copy = TRUE; - } - #ifdef OPENSSL_EXTRA + copy = WOLFSSL_SERIAL_NUMBER; + copyLen = sizeof(WOLFSSL_SERIAL_NUMBER) - 1; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectSND = (char*)&cert->source[cert->srcIdx]; + cert->subjectSNDLen = strLen; + cert->subjectSNDEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) dName->snIdx = cert->srcIdx; dName->snLen = strLen; #endif /* OPENSSL_EXTRA */ } + #ifdef WOLFSSL_CERT_EXT + else if (id == ASN_BUS_CAT) { + copy = WOLFSSL_BUS_CAT; + copyLen = sizeof(WOLFSSL_BUS_CAT) - 1; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectBC = (char*)&cert->source[cert->srcIdx]; + cert->subjectBCLen = strLen; + cert->subjectBCEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->bcIdx = cert->srcIdx; + dName->bcLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + #endif /* WOLFSSL_CERT_EXT */ + } + #ifdef WOLFSSL_CERT_EXT + else if ((cert->srcIdx + ASN_JOI_PREFIX_SZ + 2 <= (word32)maxIdx) && + (0 == XMEMCMP(&cert->source[cert->srcIdx], ASN_JOI_PREFIX, + ASN_JOI_PREFIX_SZ)) && + ((cert->source[cert->srcIdx+ASN_JOI_PREFIX_SZ] == ASN_JOI_C) || + (cert->source[cert->srcIdx+ASN_JOI_PREFIX_SZ] == ASN_JOI_ST))) + { + cert->srcIdx += ASN_JOI_PREFIX_SZ; + id = cert->source[cert->srcIdx++]; + b = cert->source[cert->srcIdx++]; /* encoding */ - if (copy && !tooBig) { - XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen); - idx += strLen; + if (GetLength(cert->source, &cert->srcIdx, &strLen, + maxIdx) < 0) + return ASN_PARSE_E; + + /* Check for jurisdiction of incorporation country name */ + if (id == ASN_JOI_C) { + copy = WOLFSSL_JOI_C; + copyLen = sizeof(WOLFSSL_JOI_C) - 1; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectJC = (char*)&cert->source[cert->srcIdx]; + cert->subjectJCLen = strLen; + cert->subjectJCEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->jcIdx = cert->srcIdx; + dName->jcLen = strLen; + #endif /* OPENSSL_EXTRA */ } - cert->srcIdx += strLen; + /* Check for jurisdiction of incorporation state name */ + else if (id == ASN_JOI_ST) { + copy = WOLFSSL_JOI_ST; + copyLen = sizeof(WOLFSSL_JOI_ST) - 1; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectJS = (char*)&cert->source[cert->srcIdx]; + cert->subjectJSLen = strLen; + cert->subjectJSEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->jsIdx = cert->srcIdx; + dName->jsLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + + if ((strLen + copyLen) > (int)(ASN_NAME_MAX - idx)) { + WOLFSSL_MSG("ASN Name too big, skipping"); + tooBig = TRUE; + } } + #endif /* WOLFSSL_CERT_EXT */ else { /* skip */ byte email = FALSE; - byte uid = FALSE; - int adv; + byte pilot = FALSE; - if (joint[0] == 0x2a && joint[1] == 0x86) /* email id hdr */ + if (joint[0] == 0x2a && joint[1] == 0x86) { /* email id hdr */ + id = ASN_EMAIL_NAME; email = TRUE; + } - if (joint[0] == 0x9 && joint[1] == 0x92) /* uid id hdr */ - uid = TRUE; + if (joint[0] == 0x9 && joint[1] == 0x92) { /* uid id hdr */ + /* last value of OID is the type of pilot attribute */ + id = cert->source[cert->srcIdx + oidSz - 1]; + pilot = TRUE; + } cert->srcIdx += oidSz + 1; - if (GetLength(cert->source, &cert->srcIdx, &adv, cert->maxIdx) < 0) + if (GetLength(cert->source, &cert->srcIdx, &strLen, maxIdx) < 0) return ASN_PARSE_E; - if (adv > (int)(ASN_NAME_MAX - idx)) { + if (strLen > (int)(ASN_NAME_MAX - idx)) { WOLFSSL_MSG("ASN name too big, skipping"); tooBig = TRUE; } if (email) { - if ( (14 + adv) > (int)(ASN_NAME_MAX - idx)) { + copyLen = sizeof(WOLFSSL_EMAIL_ADDR) - 1; + if ((copyLen + strLen) > (int)(ASN_NAME_MAX - idx)) { WOLFSSL_MSG("ASN name too big, skipping"); tooBig = TRUE; } - if (!tooBig) { - XMEMCPY(&full[idx], "/emailAddress=", 14); - idx += 14; + else { + copy = WOLFSSL_EMAIL_ADDR; } #ifdef WOLFSSL_CERT_GEN if (nameType == SUBJECT) { cert->subjectEmail = (char*)&cert->source[cert->srcIdx]; - cert->subjectEmailLen = adv; + cert->subjectEmailLen = strLen; } #endif /* WOLFSSL_CERT_GEN */ - #ifdef OPENSSL_EXTRA + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) dName->emailIdx = cert->srcIdx; - dName->emailLen = adv; + dName->emailLen = strLen; #endif /* OPENSSL_EXTRA */ #ifndef IGNORE_NAME_CONSTRAINTS { - DNS_entry* emailName = NULL; + DNS_entry* emailName; emailName = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap, DYNAMIC_TYPE_ALTNAME); @@ -2156,52 +5862,85 @@ static int GetName(DecodedCert* cert, int nameType) WOLFSSL_MSG("\tOut of Memory"); return MEMORY_E; } - emailName->name = (char*)XMALLOC(adv + 1, + emailName->type = 0; + emailName->name = (char*)XMALLOC(strLen + 1, cert->heap, DYNAMIC_TYPE_ALTNAME); if (emailName->name == NULL) { WOLFSSL_MSG("\tOut of Memory"); + XFREE(emailName, cert->heap, DYNAMIC_TYPE_ALTNAME); return MEMORY_E; } - XMEMCPY(emailName->name, - &cert->source[cert->srcIdx], adv); - emailName->name[adv] = 0; + emailName->len = strLen; + XMEMCPY(emailName->name, &cert->source[cert->srcIdx], + strLen); + emailName->name[strLen] = '\0'; emailName->next = cert->altEmailNames; cert->altEmailNames = emailName; } #endif /* IGNORE_NAME_CONSTRAINTS */ - if (!tooBig) { - XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv); - idx += adv; - } } - if (uid) { - if ( (5 + adv) > (int)(ASN_NAME_MAX - idx)) { - WOLFSSL_MSG("ASN name too big, skipping"); - tooBig = TRUE; - } - if (!tooBig) { - XMEMCPY(&full[idx], "/UID=", 5); - idx += 5; + if (pilot) { + switch (id) { + case ASN_USER_ID: + copy = WOLFSSL_USER_ID; + copyLen = sizeof(WOLFSSL_USER_ID) - 1; + #if defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) + dName->uidIdx = cert->srcIdx; + dName->uidLen = strLen; + #endif /* OPENSSL_EXTRA */ + break; - XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv); - idx += adv; + case ASN_DOMAIN_COMPONENT: + copy = WOLFSSL_DOMAIN_COMPONENT; + copyLen = sizeof(WOLFSSL_DOMAIN_COMPONENT) - 1; + #if defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) + dName->dcIdx[dcnum] = cert->srcIdx; + dName->dcLen[dcnum] = strLen; + dName->dcNum = dcnum + 1; + dcnum++; + #endif /* OPENSSL_EXTRA */ + break; + + default: + WOLFSSL_MSG("Unknown pilot attribute type"); + return ASN_PARSE_E; } - #ifdef OPENSSL_EXTRA - dName->uidIdx = cert->srcIdx; - dName->uidLen = adv; - #endif /* OPENSSL_EXTRA */ } - - cert->srcIdx += adv; } + if ((copyLen + strLen) > (int)(ASN_NAME_MAX - idx)) + { + WOLFSSL_MSG("ASN Name too big, skipping"); + tooBig = TRUE; + } + if ((copy != NULL) && !tooBig) { + XMEMCPY(&full[idx], copy, copyLen); + idx += copyLen; + XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen); + idx += strLen; + + #ifdef OPENSSL_EXTRA + if (count < DOMAIN_COMPONENT_MAX) { + /* store order that DN was parsed */ + dName->loc[count++] = id; + } + #endif + } + cert->srcIdx += strLen; } full[idx++] = 0; +#if defined(OPENSSL_EXTRA) + /* store order that DN was parsed */ + dName->locSz = count; +#endif - #ifdef OPENSSL_EXTRA + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) { int totalLen = 0; + int i = 0; if (dName->cnLen != 0) totalLen += dName->cnLen + 4; @@ -2223,14 +5962,20 @@ static int GetName(DecodedCert* cert, int nameType) totalLen += dName->uidLen + 5; if (dName->serialLen != 0) totalLen += dName->serialLen + 14; + if (dName->dcNum != 0){ + for (i = 0;i < dName->dcNum;i++) + totalLen += dName->dcLen[i] + 4; + } - dName->fullName = (char*)XMALLOC(totalLen + 1, NULL, DYNAMIC_TYPE_X509); + dName->fullName = (char*)XMALLOC(totalLen + 1, cert->heap, + DYNAMIC_TYPE_X509); if (dName->fullName != NULL) { idx = 0; if (dName->cnLen != 0) { dName->entryCount++; - XMEMCPY(&dName->fullName[idx], "/CN=", 4); + XMEMCPY(&dName->fullName[idx], WOLFSSL_COMMON_NAME, 4); + dName->cnNid = wc_OBJ_sn2nid((const char *)WOLFSSL_COMMON_NAME); idx += 4; XMEMCPY(&dName->fullName[idx], &cert->source[dName->cnIdx], dName->cnLen); @@ -2239,7 +5984,8 @@ static int GetName(DecodedCert* cert, int nameType) } if (dName->snLen != 0) { dName->entryCount++; - XMEMCPY(&dName->fullName[idx], "/SN=", 4); + XMEMCPY(&dName->fullName[idx], WOLFSSL_SUR_NAME, 4); + dName->snNid = wc_OBJ_sn2nid((const char *)WOLFSSL_SUR_NAME); idx += 4; XMEMCPY(&dName->fullName[idx], &cert->source[dName->snIdx], dName->snLen); @@ -2248,7 +5994,8 @@ static int GetName(DecodedCert* cert, int nameType) } if (dName->cLen != 0) { dName->entryCount++; - XMEMCPY(&dName->fullName[idx], "/C=", 3); + XMEMCPY(&dName->fullName[idx], WOLFSSL_COUNTRY_NAME, 3); + dName->cNid = wc_OBJ_sn2nid((const char *)WOLFSSL_COUNTRY_NAME); idx += 3; XMEMCPY(&dName->fullName[idx], &cert->source[dName->cIdx], dName->cLen); @@ -2257,7 +6004,8 @@ static int GetName(DecodedCert* cert, int nameType) } if (dName->lLen != 0) { dName->entryCount++; - XMEMCPY(&dName->fullName[idx], "/L=", 3); + XMEMCPY(&dName->fullName[idx], WOLFSSL_LOCALITY_NAME, 3); + dName->lNid = wc_OBJ_sn2nid((const char *)WOLFSSL_LOCALITY_NAME); idx += 3; XMEMCPY(&dName->fullName[idx], &cert->source[dName->lIdx], dName->lLen); @@ -2266,7 +6014,8 @@ static int GetName(DecodedCert* cert, int nameType) } if (dName->stLen != 0) { dName->entryCount++; - XMEMCPY(&dName->fullName[idx], "/ST=", 4); + XMEMCPY(&dName->fullName[idx], WOLFSSL_STATE_NAME, 4); + dName->stNid = wc_OBJ_sn2nid((const char *)WOLFSSL_STATE_NAME); idx += 4; XMEMCPY(&dName->fullName[idx], &cert->source[dName->stIdx], dName->stLen); @@ -2275,7 +6024,8 @@ static int GetName(DecodedCert* cert, int nameType) } if (dName->oLen != 0) { dName->entryCount++; - XMEMCPY(&dName->fullName[idx], "/O=", 3); + XMEMCPY(&dName->fullName[idx], WOLFSSL_ORG_NAME, 3); + dName->oNid = wc_OBJ_sn2nid((const char *)WOLFSSL_ORG_NAME); idx += 3; XMEMCPY(&dName->fullName[idx], &cert->source[dName->oIdx], dName->oLen); @@ -2284,7 +6034,8 @@ static int GetName(DecodedCert* cert, int nameType) } if (dName->ouLen != 0) { dName->entryCount++; - XMEMCPY(&dName->fullName[idx], "/OU=", 4); + XMEMCPY(&dName->fullName[idx], WOLFSSL_ORGUNIT_NAME, 4); + dName->ouNid = wc_OBJ_sn2nid((const char *)WOLFSSL_ORGUNIT_NAME); idx += 4; XMEMCPY(&dName->fullName[idx], &cert->source[dName->ouIdx], dName->ouLen); @@ -2294,15 +6045,28 @@ static int GetName(DecodedCert* cert, int nameType) if (dName->emailLen != 0) { dName->entryCount++; XMEMCPY(&dName->fullName[idx], "/emailAddress=", 14); + dName->emailNid = wc_OBJ_sn2nid((const char *)"/emailAddress="); idx += 14; XMEMCPY(&dName->fullName[idx], &cert->source[dName->emailIdx], dName->emailLen); dName->emailIdx = idx; idx += dName->emailLen; } + for (i = 0;i < dName->dcNum;i++){ + if (dName->dcLen[i] != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], WOLFSSL_DOMAIN_COMPONENT, 4); + idx += 4; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->dcIdx[i]], dName->dcLen[i]); + dName->dcIdx[i] = idx; + idx += dName->dcLen[i]; + } + } if (dName->uidLen != 0) { dName->entryCount++; XMEMCPY(&dName->fullName[idx], "/UID=", 5); + dName->uidNid = wc_OBJ_sn2nid((const char *)"/UID="); idx += 5; XMEMCPY(&dName->fullName[idx], &cert->source[dName->uidIdx], dName->uidLen); @@ -2311,7 +6075,8 @@ static int GetName(DecodedCert* cert, int nameType) } if (dName->serialLen != 0) { dName->entryCount++; - XMEMCPY(&dName->fullName[idx], "/serialNumber=", 14); + XMEMCPY(&dName->fullName[idx], WOLFSSL_SERIAL_NUMBER, 14); + dName->serialNid = wc_OBJ_sn2nid((const char *)WOLFSSL_SERIAL_NUMBER); idx += 14; XMEMCPY(&dName->fullName[idx], &cert->source[dName->serialIdx], dName->serialLen); @@ -2328,17 +6093,203 @@ static int GetName(DecodedCert* cert, int nameType) } -#ifndef NO_TIME_H +#ifndef NO_ASN_TIME + +/* two byte date/time, add to value */ +static WC_INLINE int GetTime(int* value, const byte* date, int* idx) +{ + int i = *idx; + + if (date[i] < 0x30 || date[i] > 0x39 || date[i+1] < 0x30 || + date[i+1] > 0x39) { + return ASN_PARSE_E; + } + + *value += btoi(date[i++]) * 10; + *value += btoi(date[i++]); + + *idx = i; + + return 0; +} + +int ExtractDate(const unsigned char* date, unsigned char format, + struct tm* certTime, int* idx) +{ + XMEMSET(certTime, 0, sizeof(struct tm)); + + if (format == ASN_UTC_TIME) { + if (btoi(date[*idx]) >= 5) + certTime->tm_year = 1900; + else + certTime->tm_year = 2000; + } + else { /* format == GENERALIZED_TIME */ + if (GetTime(&certTime->tm_year, date, idx) != 0) return 0; + certTime->tm_year *= 100; + } + + /* adjust tm_year, tm_mon */ + if (GetTime(&certTime->tm_year, date, idx) != 0) return 0; + certTime->tm_year -= 1900; + if (GetTime(&certTime->tm_mon , date, idx) != 0) return 0; + certTime->tm_mon -= 1; + if (GetTime(&certTime->tm_mday, date, idx) != 0) return 0; + if (GetTime(&certTime->tm_hour, date, idx) != 0) return 0; + if (GetTime(&certTime->tm_min , date, idx) != 0) return 0; + if (GetTime(&certTime->tm_sec , date, idx) != 0) return 0; + + return 1; +} + + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(OPENSSL_EXTRA) || 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, (unsigned char)format, &t, &idx)) { + return 0; + } + + if (date[idx] != 'Z') { + WOLFSSL_MSG("UTCtime, not Zulu") ; + return 0; + } + + /* place month in buffer */ + buf[0] = '\0'; + switch(t.tm_mon) { + case 0: XSTRNCAT(buf, "Jan ", 5); break; + case 1: XSTRNCAT(buf, "Feb ", 5); break; + case 2: XSTRNCAT(buf, "Mar ", 5); break; + case 3: XSTRNCAT(buf, "Apr ", 5); break; + case 4: XSTRNCAT(buf, "May ", 5); break; + case 5: XSTRNCAT(buf, "Jun ", 5); break; + case 6: XSTRNCAT(buf, "Jul ", 5); break; + case 7: XSTRNCAT(buf, "Aug ", 5); break; + case 8: XSTRNCAT(buf, "Sep ", 5); break; + case 9: XSTRNCAT(buf, "Oct ", 5); break; + case 10: XSTRNCAT(buf, "Nov ", 5); break; + case 11: XSTRNCAT(buf, "Dec ", 5); break; + default: + return 0; + + } + idx = 4; /* use idx now for char buffer */ + + XSNPRINTF(buf + idx, len - idx, "%2d %02d:%02d:%02d %d GMT", + t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, t.tm_year + 1900); + + return 1; +} +#endif /* OPENSSL_ALL || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + + +#if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7) + +/* Set current time string, either UTC or GeneralizedTime. + * (void*) tm should be a pointer to time_t, output is placed in buf. + * + * Return time string length placed in buf on success, negative on error */ +int GetAsnTimeString(void* currTime, byte* buf, word32 len) +{ + struct tm* ts = NULL; + struct tm* tmpTime = NULL; +#if defined(NEED_TMP_TIME) + struct tm tmpTimeStorage; + tmpTime = &tmpTimeStorage; +#else + (void)tmpTime; +#endif + byte* data_ptr = buf; + word32 data_len = 0; + int year, mon, day, hour, mini, sec; + + WOLFSSL_ENTER("SetAsnTimeString"); + + if (buf == NULL || len == 0) + return BAD_FUNC_ARG; + + ts = (struct tm *)XGMTIME((time_t*)currTime, tmpTime); + if (ts == NULL){ + WOLFSSL_MSG("failed to get time data."); + return ASN_TIME_E; + } + + /* Note ASN_UTC_TIME_SIZE and ASN_GENERALIZED_TIME_SIZE include space for + * the null terminator. ASN encoded values leave off the terminator. */ + + if (ts->tm_year >= 50 && ts->tm_year < 150) { + /* UTC Time */ + char utc_str[ASN_UTC_TIME_SIZE]; + data_len = ASN_UTC_TIME_SIZE - 1 + 2; + + if (len < data_len) + return BUFFER_E; + + if (ts->tm_year >= 50 && ts->tm_year < 100) { + year = ts->tm_year; + } else if (ts->tm_year >= 100 && ts->tm_year < 150) { + year = ts->tm_year - 100; + } + else { + WOLFSSL_MSG("unsupported year range"); + return BAD_FUNC_ARG; + } + mon = ts->tm_mon + 1; + day = ts->tm_mday; + hour = ts->tm_hour; + mini = ts->tm_min; + sec = ts->tm_sec; + XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE, + "%02d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec); + *data_ptr = (byte) ASN_UTC_TIME; data_ptr++; + /* -1 below excludes null terminator */ + *data_ptr = (byte) ASN_UTC_TIME_SIZE - 1; data_ptr++; + XMEMCPY(data_ptr,(byte *)utc_str, ASN_UTC_TIME_SIZE - 1); + + } else { + /* GeneralizedTime */ + char gt_str[ASN_GENERALIZED_TIME_SIZE]; + data_len = ASN_GENERALIZED_TIME_SIZE - 1 + 2; + + if (len < data_len) + return BUFFER_E; + + year = ts->tm_year + 1900; + mon = ts->tm_mon + 1; + day = ts->tm_mday; + hour = ts->tm_hour; + mini = ts->tm_min; + sec = ts->tm_sec; + XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_SIZE, + "%4d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec); + *data_ptr = (byte) ASN_GENERALIZED_TIME; data_ptr++; + /* -1 below excludes null terminator */ + *data_ptr = (byte) ASN_GENERALIZED_TIME_SIZE - 1; data_ptr++; + XMEMCPY(data_ptr,(byte *)gt_str, ASN_GENERALIZED_TIME_SIZE - 1); + } + + return data_len; +} + +#endif /* !NO_ASN_TIME && HAVE_PKCS7 */ + + +#if defined(USE_WOLF_VALIDDATE) /* to the second */ -static int DateGreaterThan(const struct tm* a, const struct tm* b) +int DateGreaterThan(const struct tm* a, const struct tm* b) { if (a->tm_year > b->tm_year) return 1; if (a->tm_year == b->tm_year && a->tm_mon > b->tm_mon) return 1; - + if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon && a->tm_mday > b->tm_mday) return 1; @@ -2361,12 +6312,11 @@ static int DateGreaterThan(const struct tm* a, const struct tm* b) } -static INLINE int DateLessThan(const struct tm* a, const struct tm* b) +static WC_INLINE int DateLessThan(const struct tm* a, const struct tm* b) { return DateGreaterThan(b,a); } - /* like atoi but only use first byte */ /* Make sure before and after dates are valid */ int ValidateDate(const byte* date, byte format, int dateType) @@ -2374,64 +6324,142 @@ int ValidateDate(const byte* date, byte format, int dateType) time_t ltime; struct tm certTime; struct tm* localTime; - struct tm* tmpTime = NULL; + struct tm* tmpTime; int i = 0; + int timeDiff = 0 ; + int diffHH = 0 ; int diffMM = 0 ; + int diffSign = 0 ; -#if defined(FREESCALE_MQX) || defined(TIME_OVERRIDES) +#if defined(NEED_TMP_TIME) struct tm tmpTimeStorage; tmpTime = &tmpTimeStorage; #else - (void)tmpTime; + tmpTime = NULL; #endif + (void)tmpTime; ltime = XTIME(0); - XMEMSET(&certTime, 0, sizeof(certTime)); - if (format == ASN_UTC_TIME) { - if (btoi(date[0]) >= 5) - certTime.tm_year = 1900; - else - certTime.tm_year = 2000; +#ifdef WOLFSSL_BEFORE_DATE_CLOCK_SKEW + if (dateType == BEFORE) { + WOLFSSL_MSG("Skewing local time for before date check"); + ltime += WOLFSSL_BEFORE_DATE_CLOCK_SKEW; } - else { /* format == GENERALIZED_TIME */ - certTime.tm_year += btoi(date[i++]) * 1000; - certTime.tm_year += btoi(date[i++]) * 100; +#endif + +#ifdef WOLFSSL_AFTER_DATE_CLOCK_SKEW + if (dateType == AFTER) { + WOLFSSL_MSG("Skewing local time for after date check"); + ltime -= WOLFSSL_AFTER_DATE_CLOCK_SKEW; } +#endif - /* adjust tm_year, tm_mon */ - GetTime((int*)&certTime.tm_year, date, &i); certTime.tm_year -= 1900; - GetTime((int*)&certTime.tm_mon, date, &i); certTime.tm_mon -= 1; - GetTime((int*)&certTime.tm_mday, date, &i); - GetTime((int*)&certTime.tm_hour, date, &i); - GetTime((int*)&certTime.tm_min, date, &i); - GetTime((int*)&certTime.tm_sec, date, &i); - - if (date[i] != 'Z') { /* only Zulu supported for this profile */ - WOLFSSL_MSG("Only Zulu time supported for this profile"); + if (!ExtractDate(date, format, &certTime, &i)) { + WOLFSSL_MSG("Error extracting the date"); return 0; } + if ((date[i] == '+') || (date[i] == '-')) { + WOLFSSL_MSG("Using time differential, not Zulu") ; + diffSign = date[i++] == '+' ? 1 : -1 ; + if (GetTime(&diffHH, date, &i) != 0) + return 0; + if (GetTime(&diffMM, date, &i) != 0) + return 0; + timeDiff = diffSign * (diffHH*60 + diffMM) * 60 ; + } else if (date[i] != 'Z') { + WOLFSSL_MSG("UTCtime, neither Zulu or time differential") ; + return 0; + } + + ltime -= (time_t)timeDiff ; localTime = XGMTIME(<ime, tmpTime); - if (dateType == BEFORE) { - if (DateLessThan(localTime, &certTime)) - return 0; + if (localTime == NULL) { + WOLFSSL_MSG("XGMTIME failed"); + return 0; } - else - if (DateGreaterThan(localTime, &certTime)) + + if (dateType == BEFORE) { + if (DateLessThan(localTime, &certTime)) { + WOLFSSL_MSG("Date BEFORE check failed"); return 0; + } + } + else { /* dateType == AFTER */ + if (DateGreaterThan(localTime, &certTime)) { + WOLFSSL_MSG("Date AFTER check failed"); + return 0; + } + } return 1; } +#endif /* USE_WOLF_VALIDDATE */ -#endif /* NO_TIME_H */ - - -static int GetDate(DecodedCert* cert, int dateType) +int wc_GetTime(void* timePtr, word32 timeSize) { - int length; + time_t* ltime = (time_t*)timePtr; + + if (timePtr == NULL) { + return BAD_FUNC_ARG; + } + + if ((word32)sizeof(time_t) > timeSize) { + return BUFFER_E; + } + + *ltime = XTIME(0); + + return 0; +} + +#endif /* !NO_ASN_TIME */ + + +/* Get date buffer, format and length. Returns 0=success or error */ +static int GetDateInfo(const byte* source, word32* idx, const byte** pDate, + byte* pFormat, int* pLength, word32 maxIdx) +{ + int length; + byte format; + + if (source == NULL || idx == NULL) + return BAD_FUNC_ARG; + + /* get ASN format header */ + if (*idx+1 > maxIdx) + return BUFFER_E; + format = source[*idx]; + *idx += 1; + if (format != ASN_UTC_TIME && format != ASN_GENERALIZED_TIME) + return ASN_TIME_E; + + /* get length */ + if (GetLength(source, idx, &length, maxIdx) < 0) + return ASN_PARSE_E; + if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE) + return ASN_DATE_SZ_E; + + /* return format, date and length */ + if (pFormat) + *pFormat = format; + if (pDate) + *pDate = &source[*idx]; + if (pLength) + *pLength = length; + + *idx += length; + + return 0; +} + +static int GetDate(DecodedCert* cert, int dateType, int verify, int maxIdx) +{ + int ret, length; + const byte *datePtr = NULL; byte date[MAX_DATE_SIZE]; - byte b; + byte format; word32 startIdx = 0; if (dateType == BEFORE) @@ -2440,49 +6468,50 @@ static int GetDate(DecodedCert* cert, int dateType) cert->afterDate = &cert->source[cert->srcIdx]; startIdx = cert->srcIdx; - b = cert->source[cert->srcIdx++]; - if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME) - return ASN_TIME_E; + ret = GetDateInfo(cert->source, &cert->srcIdx, &datePtr, &format, + &length, maxIdx); + if (ret < 0) + return ret; - if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) - return ASN_PARSE_E; - - if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE) - return ASN_DATE_SZ_E; - - XMEMCPY(date, &cert->source[cert->srcIdx], length); - cert->srcIdx += length; + XMEMSET(date, 0, MAX_DATE_SIZE); + XMEMCPY(date, datePtr, length); if (dateType == BEFORE) cert->beforeDateLen = cert->srcIdx - startIdx; else cert->afterDateLen = cert->srcIdx - startIdx; - if (!XVALIDATE_DATE(date, b, dateType)) { +#ifndef NO_ASN_TIME + if (verify != NO_VERIFY && verify != VERIFY_SKIP_DATE && + !XVALIDATE_DATE(date, format, dateType)) { if (dateType == BEFORE) return ASN_BEFORE_DATE_E; else return ASN_AFTER_DATE_E; } +#else + (void)verify; +#endif return 0; } - -static int GetValidity(DecodedCert* cert, int verify) +static int GetValidity(DecodedCert* cert, int verify, int maxIdx) { int length; int badDate = 0; - if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + if (GetSequence(cert->source, &cert->srcIdx, &length, maxIdx) < 0) return ASN_PARSE_E; - if (GetDate(cert, BEFORE) < 0 && verify) - badDate = ASN_BEFORE_DATE_E; /* continue parsing */ - - if (GetDate(cert, AFTER) < 0 && verify) + maxIdx = cert->srcIdx + length; + + if (GetDate(cert, BEFORE, verify, maxIdx) < 0) + badDate = ASN_BEFORE_DATE_E; /* continue parsing */ + + if (GetDate(cert, AFTER, verify, maxIdx) < 0) return ASN_AFTER_DATE_E; - + if (badDate != 0) return badDate; @@ -2490,32 +6519,111 @@ static int GetValidity(DecodedCert* cert, int verify) } -int DecodeToKey(DecodedCert* cert, int verify) +int wc_GetDateInfo(const byte* certDate, int certDateSz, const byte** date, + byte* format, int* length) +{ + int ret; + word32 idx = 0; + + ret = GetDateInfo(certDate, &idx, date, format, length, certDateSz); + if (ret < 0) + return ret; + + return 0; +} + +#ifndef NO_ASN_TIME +int wc_GetDateAsCalendarTime(const byte* date, int length, byte format, + struct tm* timearg) +{ + int idx = 0; + (void)length; + if (!ExtractDate(date, format, timearg, &idx)) + return ASN_TIME_E; + return 0; +} + +#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_ALT_NAMES) +int wc_GetCertDates(Cert* cert, struct tm* before, struct tm* after) +{ + int ret = 0; + const byte* date; + byte format; + int length; + + if (cert == NULL) + return BAD_FUNC_ARG; + + if (before && cert->beforeDateSz > 0) { + ret = wc_GetDateInfo(cert->beforeDate, cert->beforeDateSz, &date, + &format, &length); + if (ret == 0) + ret = wc_GetDateAsCalendarTime(date, length, format, before); + } + if (after && cert->afterDateSz > 0) { + ret = wc_GetDateInfo(cert->afterDate, cert->afterDateSz, &date, + &format, &length); + if (ret == 0) + ret = wc_GetDateAsCalendarTime(date, length, format, after); + } + + return ret; +} +#endif /* WOLFSSL_CERT_GEN && WOLFSSL_ALT_NAMES */ +#endif /* !NO_ASN_TIME */ + +/* parses certificate up to point of X.509 public key + * + * if cert date is invalid then badDate gets set to error value, otherwise is 0 + * + * returns a negative value on fail case + */ +int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate) { - int badDate = 0; int ret; + if (cert == NULL || badDate == NULL) + return BAD_FUNC_ARG; + + *badDate = 0; if ( (ret = GetCertHeader(cert)) < 0) return ret; WOLFSSL_MSG("Got Cert Header"); + /* Using the sigIndex as the upper bound because that's where the + * actual certificate data ends. */ if ( (ret = GetAlgoId(cert->source, &cert->srcIdx, &cert->signatureOID, - cert->maxIdx)) < 0) + oidSigType, cert->sigIndex)) < 0) return ret; WOLFSSL_MSG("Got Algo ID"); - if ( (ret = GetName(cert, ISSUER)) < 0) + if ( (ret = GetName(cert, ISSUER, cert->sigIndex)) < 0) return ret; - if ( (ret = GetValidity(cert, verify)) < 0) - badDate = ret; + if ( (ret = GetValidity(cert, verify, cert->sigIndex)) < 0) + *badDate = ret; - if ( (ret = GetName(cert, SUBJECT)) < 0) + if ( (ret = GetName(cert, SUBJECT, cert->sigIndex)) < 0) return ret; WOLFSSL_MSG("Got Subject Name"); + return ret; +} + +int DecodeToKey(DecodedCert* cert, int verify) +{ + int badDate = 0; + int ret; + + if ( (ret = wc_GetPubX509(cert, verify, &badDate)) < 0) + return ret; + + /* Determine if self signed */ + cert->selfSigned = XMEMCMP(cert->issuerHash, + cert->subjectHash, + KEYID_SIZE) == 0 ? 1 : 0; if ( (ret = GetKey(cert)) < 0) return ret; @@ -2528,40 +6636,36 @@ int DecodeToKey(DecodedCert* cert, int verify) return ret; } - 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; - - 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 SetOctetString8Bit(word32 len, byte* output) +{ + output[0] = ASN_OCTET_STRING; + output[1] = (byte)len; + return 2; +} static word32 SetDigest(const byte* digest, word32 digSz, byte* output) { - output[0] = ASN_OCTET_STRING; - output[1] = (byte)digSz; - XMEMCPY(&output[2], digest, digSz); + word32 idx = SetOctetString8Bit(digSz, output); + XMEMCPY(&output[idx], digest, digSz); - return digSz + 2; -} + return idx + digSz; +} static word32 BytePrecision(word32 value) @@ -2575,17 +6679,23 @@ static word32 BytePrecision(word32 value) } -WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output) +word32 SetLength(word32 length, byte* output) { word32 i = 0, j; - if (length < ASN_LONG_LENGTH) - output[i++] = (byte)length; + if (length < ASN_LONG_LENGTH) { + if (output) + output[i] = (byte)length; + i++; + } else { - output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH); - + if (output) + output[i] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH); + i++; + for (j = BytePrecision(length); j; --j) { - output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE)); + if (output) + output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE)); i++; } } @@ -2593,27 +6703,27 @@ WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output) return i; } - -WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output) +word32 SetSequence(word32 len, byte* output) { - output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED; - return SetLength(len, output + 1) + 1; + if (output) + output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED; + return SetLength(len, output ? output + 1 : NULL) + 1; } -WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output) +word32 SetOctetString(word32 len, byte* output) { output[0] = ASN_OCTET_STRING; return SetLength(len, output + 1) + 1; } /* Write a set header to output */ -WOLFSSL_LOCAL word32 SetSet(word32 len, byte* output) +word32 SetSet(word32 len, byte* output) { output[0] = ASN_SET | ASN_CONSTRUCTED; return SetLength(len, output + 1) + 1; } -WOLFSSL_LOCAL word32 SetImplicit(byte tag, byte number, word32 len, byte* output) +word32 SetImplicit(byte tag, byte number, word32 len, byte* output) { output[0] = ((tag == ASN_SEQUENCE || tag == ASN_SET) ? ASN_CONSTRUCTED : 0) @@ -2621,323 +6731,121 @@ WOLFSSL_LOCAL word32 SetImplicit(byte tag, byte number, word32 len, byte* output return SetLength(len, output + 1) + 1; } -WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output) +word32 SetExplicit(byte number, word32 len, byte* output) { output[0] = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | number; return SetLength(len, output + 1) + 1; } -#if defined(HAVE_ECC) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) -static word32 SetCurve(ecc_key* key, byte* output) +static int SetCurve(ecc_key* key, byte* output) { +#ifdef HAVE_OID_ENCODING + int ret; +#endif + int idx = 0; + word32 oidSz = 0; - /* curve types */ -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) - static const byte ECC_192v1_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d, - 0x03, 0x01, 0x01}; -#endif -#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) - static const byte ECC_256v1_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d, - 0x03, 0x01, 0x07}; -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) - static const byte ECC_160r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00, - 0x02}; -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) - static const byte ECC_224r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00, - 0x21}; -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) - static const byte ECC_384r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00, - 0x22}; -#endif -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) - static const byte ECC_521r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00, - 0x23}; -#endif - - int oidSz = 0; - int idx = 0; - int lenSz = 0; - const byte* oid = 0; - - output[0] = ASN_OBJECT_ID; - idx++; - - switch (key->dp->size) { -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160) - case 20: - oidSz = sizeof(ECC_160r1_AlgoID); - oid = ECC_160r1_AlgoID; - break; -#endif - -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192) - case 24: - oidSz = sizeof(ECC_192v1_AlgoID); - oid = ECC_192v1_AlgoID; - break; -#endif - -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224) - case 28: - oidSz = sizeof(ECC_224r1_AlgoID); - oid = ECC_224r1_AlgoID; - break; -#endif - -#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256) - case 32: - oidSz = sizeof(ECC_256v1_AlgoID); - oid = ECC_256v1_AlgoID; - break; -#endif - -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384) - case 48: - oidSz = sizeof(ECC_384r1_AlgoID); - oid = ECC_384r1_AlgoID; - break; -#endif - -#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521) - case 66: - oidSz = sizeof(ECC_521r1_AlgoID); - oid = ECC_521r1_AlgoID; - break; -#endif - - default: - return ASN_UNKNOWN_OID_E; + /* validate key */ + if (key == NULL || key->dp == NULL) { + return BAD_FUNC_ARG; } - lenSz = SetLength(oidSz, output+idx); - idx += lenSz; - XMEMCPY(output+idx, oid, oidSz); +#ifdef HAVE_OID_ENCODING + ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, NULL, &oidSz); + if (ret != 0) { + return ret; + } +#else + oidSz = key->dp->oidSz; +#endif + + idx += SetObjectId(oidSz, output); + +#ifdef HAVE_OID_ENCODING + ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, output+idx, &oidSz); + if (ret != 0) { + return ret; + } +#else + XMEMCPY(output+idx, key->dp->oid, oidSz); +#endif idx += oidSz; return idx; } -#endif /* HAVE_ECC && WOLFSSL_CERT_GEN */ +#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */ -WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) +#ifdef HAVE_ECC +static WC_INLINE int IsSigAlgoECDSA(int algoOID) { - /* adding TAG_NULL and 0 to end */ - - /* hashTypes */ - static const byte shaAlgoID[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a, - 0x05, 0x00 }; - static const byte sha256AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x01, 0x05, 0x00 }; - static const byte sha384AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x02, 0x05, 0x00 }; - static const byte sha512AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x03, 0x05, 0x00 }; - static const byte md5AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x02, 0x05, 0x05, 0x00 }; - static const byte md2AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x02, 0x02, 0x05, 0x00}; + /* ECDSA sigAlgo must not have ASN1 NULL parameters */ + if (algoOID == CTC_SHAwECDSA || algoOID == CTC_SHA256wECDSA || + algoOID == CTC_SHA384wECDSA || algoOID == CTC_SHA512wECDSA) { + return 1; + } - /* blkTypes, no NULL tags because IV is there instead */ - static const byte desCbcAlgoID[] = { 0x2B, 0x0E, 0x03, 0x02, 0x07 }; - static const byte des3CbcAlgoID[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, - 0x0D, 0x03, 0x07 }; + return 0; +} +#endif - /* RSA sigTypes */ - #ifndef NO_RSA - static const byte md5wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00}; - static const byte shawRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00}; - static const byte sha256wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00}; - static const byte sha384wRSA_AlgoID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00}; - static const byte sha512wRSA_AlgoID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00}; - #endif /* NO_RSA */ - - /* ECDSA sigTypes */ - #ifdef HAVE_ECC - static const byte shawECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d, - 0x04, 0x01, 0x05, 0x00}; - static const byte sha256wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d, - 0x04, 0x03, 0x02, 0x05, 0x00}; - static const byte sha384wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d, - 0x04, 0x03, 0x03, 0x05, 0x00}; - static const byte sha512wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d, - 0x04, 0x03, 0x04, 0x05, 0x00}; - #endif /* HAVE_ECC */ - - /* RSA keyType */ - #ifndef NO_RSA - static const byte RSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x01, 0x05, 0x00}; - #endif /* NO_RSA */ - - #ifdef HAVE_ECC - /* ECC keyType */ - /* no tags, so set tagSz smaller later */ - static const byte ECC_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d, - 0x02, 0x01}; - #endif /* HAVE_ECC */ - - int algoSz = 0; - int tagSz = 2; /* tag null and terminator */ - word32 idSz, seqSz; +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 seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ + byte ID_Length[1 + MAX_LENGTH_SZ]; + byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ + int length = 0; - if (type == hashType) { - switch (algoOID) { - case SHAh: - algoSz = sizeof(shaAlgoID); - algoName = shaAlgoID; - break; + tagSz = (type == oidHashType || + (type == oidSigType + #ifdef HAVE_ECC + && !IsSigAlgoECDSA(algoOID) + #endif + #ifdef HAVE_ED25519 + && algoOID != ED25519k + #endif + #ifdef HAVE_ED448 + && algoOID != ED448k + #endif + ) || + (type == oidKeyType && algoOID == RSAk)) ? 2 : 0; - case SHA256h: - algoSz = sizeof(sha256AlgoID); - algoName = sha256AlgoID; - break; + algoName = OidFromId(algoOID, type, &algoSz); - case SHA384h: - algoSz = sizeof(sha384AlgoID); - algoName = sha384AlgoID; - break; - - case SHA512h: - algoSz = sizeof(sha512AlgoID); - algoName = sha512AlgoID; - break; - - case MD2h: - algoSz = sizeof(md2AlgoID); - algoName = md2AlgoID; - break; - - case MD5h: - algoSz = sizeof(md5AlgoID); - algoName = md5AlgoID; - break; - - default: - WOLFSSL_MSG("Unknown Hash Algo"); - return 0; /* UNKOWN_HASH_E; */ - } - } - else if (type == blkType) { - switch (algoOID) { - case DESb: - algoSz = sizeof(desCbcAlgoID); - algoName = desCbcAlgoID; - tagSz = 0; - break; - case DES3b: - algoSz = sizeof(des3CbcAlgoID); - algoName = des3CbcAlgoID; - tagSz = 0; - break; - default: - WOLFSSL_MSG("Unknown Block Algo"); - return 0; - } - } - else if (type == sigType) { /* sigType */ - switch (algoOID) { - #ifndef NO_RSA - case CTC_MD5wRSA: - algoSz = sizeof(md5wRSA_AlgoID); - algoName = md5wRSA_AlgoID; - break; - - case CTC_SHAwRSA: - algoSz = sizeof(shawRSA_AlgoID); - algoName = shawRSA_AlgoID; - break; - - case CTC_SHA256wRSA: - algoSz = sizeof(sha256wRSA_AlgoID); - algoName = sha256wRSA_AlgoID; - break; - - case CTC_SHA384wRSA: - algoSz = sizeof(sha384wRSA_AlgoID); - algoName = sha384wRSA_AlgoID; - break; - - case CTC_SHA512wRSA: - algoSz = sizeof(sha512wRSA_AlgoID); - algoName = sha512wRSA_AlgoID; - break; - #endif /* NO_RSA */ - #ifdef HAVE_ECC - case CTC_SHAwECDSA: - algoSz = sizeof(shawECDSA_AlgoID); - algoName = shawECDSA_AlgoID; - break; - - case CTC_SHA256wECDSA: - algoSz = sizeof(sha256wECDSA_AlgoID); - algoName = sha256wECDSA_AlgoID; - break; - - case CTC_SHA384wECDSA: - algoSz = sizeof(sha384wECDSA_AlgoID); - algoName = sha384wECDSA_AlgoID; - break; - - case CTC_SHA512wECDSA: - algoSz = sizeof(sha512wECDSA_AlgoID); - algoName = sha512wECDSA_AlgoID; - break; - #endif /* HAVE_ECC */ - default: - WOLFSSL_MSG("Unknown Signature Algo"); - return 0; - } - } - else if (type == keyType) { /* keyType */ - switch (algoOID) { - #ifndef NO_RSA - case RSAk: - algoSz = sizeof(RSA_AlgoID); - algoName = RSA_AlgoID; - break; - #endif /* NO_RSA */ - #ifdef HAVE_ECC - case ECDSAk: - algoSz = sizeof(ECC_AlgoID); - algoName = ECC_AlgoID; - tagSz = 0; - break; - #endif /* HAVE_ECC */ - default: - WOLFSSL_MSG("Unknown Key Algo"); - return 0; - } - } - else { - WOLFSSL_MSG("Unknown Algo type"); + if (algoName == NULL) { + WOLFSSL_MSG("Unknown Algorithm"); return 0; } - idSz = SetLength(algoSz - tagSz, ID_Length); /* don't include tags */ - seqSz = SetSequence(idSz + algoSz + 1 + 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); + /* Copy only algo to output for DSA keys */ + if (algoOID == DSAk && output) { + XMEMCPY(output, ID_Length, idSz); + XMEMCPY(output + idSz, algoName, algoSz); + if (tagSz == 2) + SetASNNull(&output[seqSz + idSz + algoSz]); + } + else if (output) { + XMEMCPY(output, seqArray, seqSz); + XMEMCPY(output + seqSz, ID_Length, idSz); + XMEMCPY(output + seqSz + idSz, algoName, algoSz); + if (tagSz == 2) + SetASNNull(&output[seqSz + idSz + algoSz]); + } - return seqSz + idSz + algoSz; + if (algoOID == DSAk) + length = idSz + algoSz + tagSz; + else + length = seqSz + idSz + algoSz + tagSz; + return length; } @@ -2950,7 +6858,7 @@ word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz, word32 encDigSz, algoSz, seqSz; encDigSz = SetDigest(digest, digSz, digArray); - algoSz = SetAlgoID(hashOID, algoArray, hashType, 0); + algoSz = SetAlgoID(hashOID, algoArray, oidHashType, 0); seqSz = SetSequence(encDigSz + algoSz, seqArray); XMEMCPY(out, seqArray, seqSz); @@ -2961,288 +6869,569 @@ word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz, } +#ifndef NO_CERTS + int wc_GetCTC_HashOID(int type) { - switch (type) { -#ifdef WOLFSSL_MD2 - case MD2: - return MD2h; -#endif -#ifndef NO_MD5 - case MD5: - return MD5h; -#endif -#ifndef NO_SHA - case SHA: - return SHAh; -#endif -#ifndef NO_SHA256 - case SHA256: - return SHA256h; -#endif -#ifdef WOLFSSL_SHA384 - case SHA384: - return SHA384h; -#endif -#ifdef WOLFSSL_SHA512 - case SHA512: - return SHA512h; -#endif - default: - return 0; - }; + int ret; + enum wc_HashType hType; + + hType = wc_HashTypeConvert(type); + ret = wc_HashGetOID(hType); + if (ret < 0) + ret = 0; /* backwards compatibility */ + + return ret; } - -/* 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[MAX_DIGEST_SIZE]; + if (sigCtx) { + XMEMSET(sigCtx, 0, sizeof(SignatureCtx)); + sigCtx->devId = devId; + sigCtx->heap = heap; + } +} + +void FreeSignatureCtx(SignatureCtx* sigCtx) +{ + if (sigCtx == NULL) + return; + + 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 +#ifndef NO_ASN_CRYPT + 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 */ + #ifdef HAVE_ED448 + case ED448k: + wc_ed448_free(sigCtx->key.ed448); + XFREE(sigCtx->key.ed448, sigCtx->heap, DYNAMIC_TYPE_ED448); + break; + #endif /* HAVE_ED448 */ + default: + break; + } /* switch (keyOID) */ + sigCtx->key.ptr = NULL; + } #endif -#ifdef WOLFSSL_SMALL_STACK - digest = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (digest == NULL) - return 0; /* not confirmed */ -#endif + /* reset state, we are done */ + sigCtx->state = SIG_STATE_BEGIN; +} - (void)key; - (void)keySz; - (void)sig; - (void)sigSz; - (void)heap; +#ifndef NO_ASN_CRYPT +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 ((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 + #ifdef HAVE_ED25519 + case CTC_ED25519: + /* Hashes done in signing operation. + * Two dependent hashes with prefixes performed. + */ + break; + #endif + #ifdef HAVE_ED448 + case CTC_ED448: + /* Hashes done in signing operation. + * Two dependent hashes with prefixes performed. + */ + break; #endif default: - WOLFSSL_MSG("Verify Signautre has unsupported type"); - } - - if (typeH == 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return 0; /* not confirmed */ + ret = HASH_TYPE_E; + WOLFSSL_MSG("Hash for Signature has unsupported type"); } - switch (keyOID) { - #ifndef NO_RSA - case RSAk: + return ret; +} +#endif /* !NO_ASN_CRYPT */ + +/* 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, byte* rsaKeyIdx) +{ + int ret = 0; +#ifndef WOLFSSL_RENESAS_TSIP_TLS + (void)rsaKeyIdx; +#endif + if (sigCtx == NULL || buf == NULL || bufSz == 0 || key == NULL || + keySz == 0 || sig == NULL || sigSz == 0) { + return BAD_FUNC_ARG; + } + + (void)key; + (void)keySz; + (void)sig; + (void)sigSz; + + WOLFSSL_ENTER("ConfirmSignature"); + +#ifndef NO_ASN_CRYPT + 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 + sigCtx->keyOID = keyOID; /* must set early for cleanup */ -#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 (sigSz > MAX_ENCODED_SIG_SZ) { - WOLFSSL_MSG("Verify Signautre is too big"); - } - else if (wc_InitRsaKey(pubKey, heap) != 0) { - WOLFSSL_MSG("InitRsaKey failed"); - } - else if (wc_RsaPublicKeyDecode(key, &idx, pubKey, keySz) < 0) { - WOLFSSL_MSG("ASN Key decode error RSA"); - } - else { - XMEMCPY(plain, sig, sigSz); + sigCtx->state = SIG_STATE_HASH; + } /* SIG_STATE_BEGIN */ + FALL_THROUGH; - if ((verifySz = wc_RsaSSL_VerifyInline(plain, sigSz, &out, - pubKey)) < 0) { - WOLFSSL_MSG("Rsa SSL verify error"); + 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: + { + 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 + break; } - else { - /* 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: + { + word32 idx = 0; + + 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); + } + if ((ret = wc_ecc_init_ex(sigCtx->key.ecc, sigCtx->heap, + sigCtx->devId)) < 0) { + goto exit_cs; + } + ret = wc_EccPublicKeyDecode(key, &idx, sigCtx->key.ecc, + keySz); + if (ret < 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 + #ifdef HAVE_ED448 + case ED448k: + { + sigCtx->verify = 0; + sigCtx->key.ed448 = (ed448_key*)XMALLOC( + sizeof(ed448_key), sigCtx->heap, + DYNAMIC_TYPE_ED448); + if (sigCtx->key.ed448 == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_ed448_init(sigCtx->key.ed448)) < 0) { + goto exit_cs; + } + if ((ret = wc_ed448_import_public(key, keySz, + sigCtx->key.ed448)) < 0) { + WOLFSSL_MSG("ASN Key import error ED448"); + goto exit_cs; + } + #ifdef WOLFSSL_ASYNC_CRYPT + sigCtx->asyncDev = &sigCtx->key.ed448->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; + } + + sigCtx->state = SIG_STATE_DO; + + #ifdef WOLFSSL_ASYNC_CRYPT + if (sigCtx->devId != INVALID_DEVID && sigCtx->asyncDev && sigCtx->asyncCtx) { + /* make sure event is initialized */ + 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; + + case SIG_STATE_DO: + { + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + #ifdef HAVE_PK_CALLBACKS + if (sigCtx->pkCbRsa) { + ret = sigCtx->pkCbRsa( + sigCtx->plain, sigSz, &sigCtx->out, + key, keySz, + sigCtx->pkCtxRsa); } else - ret = 1; /* match */ - - #ifdef WOLFSSL_DEBUG_ENCODING + #endif /* HAVE_PK_CALLBACKS */ { - int x; + #ifdef WOLFSSL_RENESAS_TSIP_TLS + if (rsaKeyIdx != NULL) + { + ret = tsip_tls_CertVerify(buf, bufSz, sigCtx->plain, + sigSz, + sigCtx->pubkey_n_start - sigCtx->certBegin, + sigCtx->pubkey_n_len - 1, + sigCtx->pubkey_e_start - sigCtx->certBegin, + sigCtx->pubkey_e_len - 1, + rsaKeyIdx); - 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 == 0){ + sigCtx->verifyByTSIP = 1; + ret = 0; + } else { + WOLFSSL_MSG("RSA Verify by tsip didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + } else + #endif + ret = wc_RsaSSL_VerifyInline(sigCtx->plain, sigSz, + &sigCtx->out, sigCtx->key.rsa); } - #endif /* WOLFSSL_DEBUG_ENCODING */ - + break; } + #endif /* !NO_RSA */ + #if defined(HAVE_ECC) + case ECDSAk: + { + #ifdef HAVE_PK_CALLBACKS + if (sigCtx->pkCbEcc) { + ret = sigCtx->pkCbEcc( + sig, sigSz, + sigCtx->digest, sigCtx->digestSz, + key, keySz, &sigCtx->verify, + sigCtx->pkCtxEcc); + } + else + #endif /* HAVE_PK_CALLBACKS */ + { + 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 + #ifdef HAVE_ED448 + case ED448k: + { + ret = wc_ed448_verify_msg(sig, sigSz, buf, bufSz, + &sigCtx->verify, sigCtx->key.ed448, + NULL, 0); + break; + } + #endif + default: + break; + } /* switch (keyOID) */ + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + goto exit_cs; + } + #endif + + if (ret < 0) { + /* treat all RSA errors as ASN_SIG_CONFIRM_E */ + ret = ASN_SIG_CONFIRM_E; + goto exit_cs; } - wc_FreeRsaKey(pubKey); + sigCtx->state = SIG_STATE_CHECK; + } /* SIG_STATE_DO */ + FALL_THROUGH; -#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; - } - - #endif /* NO_RSA */ - #ifdef HAVE_ECC - case ECDSAk: + case SIG_STATE_CHECK: { - int verify = 0; -#ifdef WOLFSSL_SMALL_STACK - ecc_key* pubKey; -#else - ecc_key pubKey[1]; -#endif + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + int encodedSigSz, verifySz; + #ifdef WOLFSSL_RENESAS_TSIP + if (sigCtx->verifyByTSIP == 1) break; + #endif + #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 -#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 + verifySz = ret; - 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"); + /* make sure we're right justified */ + encodedSigSz = wc_EncodeSignature(encodedSig, + sigCtx->digest, sigCtx->digestSz, sigCtx->typeH); + if (encodedSigSz == verifySz && sigCtx->out != NULL && + 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; } - else if (1 != verify) { - WOLFSSL_MSG("ECC Verify didn't match"); - } else - ret = 1; /* match */ + #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 */ + #ifdef HAVE_ED448 + case ED448k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("ED448 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + #endif /* HAVE_ED448 */ + default: + break; + } /* switch (keyOID) */ - } - wc_ecc_free(pubKey); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif break; - } - #endif /* HAVE_ECC */ - default: - WOLFSSL_MSG("Verify Key type unknown"); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } /* SIG_STATE_CHECK */ + } /* switch (sigCtx->state) */ + +exit_cs: + +#endif /* !NO_ASN_CRYPT */ + + (void)keyOID; + (void)sigOID; + + WOLFSSL_LEAVE("ConfirmSignature", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; #endif + FreeSignatureCtx(sigCtx); + return ret; } @@ -3250,7 +7439,7 @@ static int ConfirmSignature(const byte* buf, word32 bufSz, #ifndef IGNORE_NAME_CONSTRAINTS static int MatchBaseName(int type, const char* name, int nameSz, - const char* base, int baseSz) + const char* base, int baseSz) { if (base == NULL || baseSz <= 0 || name == NULL || nameSz <= 0 || name[0] == '.' || nameSz < baseSz || @@ -3302,7 +7491,7 @@ static int MatchBaseName(int type, const char* name, int nameSz, } while (nameSz > 0) { - if (XTOLOWER((unsigned char)*name++) != + if (XTOLOWER((unsigned char)*name++) != XTOLOWER((unsigned char)*base++)) return 0; nameSz--; @@ -3322,34 +7511,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, - name->name, (int)XSTRLEN(name->name), - base->name, base->nameSz)) + switch (base->type) { + case ASN_DNS_TYPE: + { + DNS_entry* name = cert->altNames; + while (name != NULL) { + if (MatchBaseName(ASN_DNS_TYPE, + name->name, name->len, + base->name, base->nameSz)) { + return 0; + } + name = name->next; + } + break; + } + case ASN_RFC822_TYPE: + { + DNS_entry* name = cert->altEmailNames; + while (name != NULL) { + if (MatchBaseName(ASN_RFC822_TYPE, + name->name, name->len, + 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_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)) - return 0; - - name = name->next; - } - } - 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; } } @@ -3365,47 +7564,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, - name->name, (int)XSTRLEN(name->name), + while (name != NULL) { + matchDns = MatchBaseName(ASN_DNS_TYPE, + name->name, name->len, 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, - name->name, (int)XSTRLEN(name->name), + while (name != NULL) { + matchEmail = MatchBaseName(ASN_DNS_TYPE, + name->name, name->len, 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; } } @@ -3415,8 +7623,7 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert) #endif /* IGNORE_NAME_CONSTRAINTS */ - -static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) +static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length = 0; @@ -3428,10 +7635,17 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } + if (length == 0) { + /* RFC 5280 4.2.1.6. Subject Alternative Name + If the subjectAltName extension is present, the sequence MUST + contain at least one entry. */ + return ASN_PARSE_E; + } + cert->weOwnAltNames = 1; while (length > 0) { - byte b = input[idx++]; + byte b = input[idx++]; length--; @@ -3452,17 +7666,18 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) DYNAMIC_TYPE_ALTNAME); if (dnsEntry == NULL) { WOLFSSL_MSG("\tOut of Memory"); - return ASN_PARSE_E; + return MEMORY_E; } + dnsEntry->type = ASN_DNS_TYPE; dnsEntry->name = (char*)XMALLOC(strLen + 1, cert->heap, DYNAMIC_TYPE_ALTNAME); if (dnsEntry->name == NULL) { WOLFSSL_MSG("\tOut of Memory"); XFREE(dnsEntry, cert->heap, DYNAMIC_TYPE_ALTNAME); - return ASN_PARSE_E; + return MEMORY_E; } - + dnsEntry->len = strLen; XMEMCPY(dnsEntry->name, &input[idx], strLen); dnsEntry->name[strLen] = '\0'; @@ -3472,7 +7687,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; @@ -3488,17 +7703,18 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) DYNAMIC_TYPE_ALTNAME); if (emailEntry == NULL) { WOLFSSL_MSG("\tOut of Memory"); - return ASN_PARSE_E; + return MEMORY_E; } + emailEntry->type = ASN_RFC822_TYPE; emailEntry->name = (char*)XMALLOC(strLen + 1, cert->heap, DYNAMIC_TYPE_ALTNAME); if (emailEntry->name == NULL) { WOLFSSL_MSG("\tOut of Memory"); XFREE(emailEntry, cert->heap, DYNAMIC_TYPE_ALTNAME); - return ASN_PARSE_E; + return MEMORY_E; } - + emailEntry->len = strLen; XMEMCPY(emailEntry->name, &input[idx], strLen); emailEntry->name[strLen] = '\0'; @@ -3508,6 +7724,120 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) length -= strLen; idx += strLen; } + else if (b == (ASN_CONTEXT_SPECIFIC | ASN_URI_TYPE)) { + DNS_entry* uriEntry; + int strLen; + word32 lenStartIdx = idx; + + WOLFSSL_MSG("\tPutting URI into list but not using"); + if (GetLength(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tfail: str length"); + return ASN_PARSE_E; + } + length -= (idx - lenStartIdx); + + /* check that strLen at index is not past input buffer */ + if (strLen + (int)idx > sz) { + return BUFFER_E; + } + + #ifndef WOLFSSL_NO_ASN_STRICT + /* Verify RFC 5280 Sec 4.2.1.6 rule: + "The name MUST NOT be a relative URI" */ + + { + int i; + + /* skip past scheme (i.e http,ftp,...) finding first ':' char */ + for (i = 0; i < strLen; i++) { + if (input[idx + i] == ':') { + break; + } + if (input[idx + i] == '/') { + i = strLen; /* error, found relative path since '/' was + * encountered before ':'. Returning error + * value in next if statement. */ + } + } + + /* test if no ':' char was found and test that the next two + * chars are // to match the pattern "://" */ + if (i >= strLen - 2 || (input[idx + i + 1] != '/' || + input[idx + i + 2] != '/')) { + WOLFSSL_MSG("\tAlt Name must be absolute URI"); + return ASN_ALT_NAME_E; + } + } + #endif + + uriEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap, + DYNAMIC_TYPE_ALTNAME); + if (uriEntry == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + uriEntry->type = ASN_URI_TYPE; + uriEntry->name = (char*)XMALLOC(strLen + 1, cert->heap, + DYNAMIC_TYPE_ALTNAME); + if (uriEntry->name == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + XFREE(uriEntry, cert->heap, DYNAMIC_TYPE_ALTNAME); + return MEMORY_E; + } + uriEntry->len = strLen; + XMEMCPY(uriEntry->name, &input[idx], strLen); + uriEntry->name[strLen] = '\0'; + + uriEntry->next = cert->altNames; + cert->altNames = uriEntry; + + length -= strLen; + idx += strLen; + } +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + else if (b == (ASN_CONTEXT_SPECIFIC | ASN_IP_TYPE)) { + DNS_entry* ipAddr; + int strLen; + word32 lenStartIdx = idx; + WOLFSSL_MSG("Decoding Subject Alt. Name: IP Address"); + + if (GetLength(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tfail: str length"); + return ASN_PARSE_E; + } + length -= (idx - lenStartIdx); + /* check that strLen at index is not past input buffer */ + if (strLen + (int)idx > sz) { + return BUFFER_E; + } + + ipAddr = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap, + DYNAMIC_TYPE_ALTNAME); + if (ipAddr == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + ipAddr->type = ASN_IP_TYPE; + ipAddr->name = (char*)XMALLOC(strLen + 1, cert->heap, + DYNAMIC_TYPE_ALTNAME); + if (ipAddr->name == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + XFREE(ipAddr, cert->heap, DYNAMIC_TYPE_ALTNAME); + return MEMORY_E; + } + ipAddr->len = strLen; + XMEMCPY(ipAddr->name, &input[idx], strLen); + ipAddr->name[strLen] = '\0'; + + ipAddr->next = cert->altNames; + cert->altNames = ipAddr; + + length -= strLen; + idx += strLen; + } +#endif /* WOLFSSL_QT || OPENSSL_ALL */ #endif /* IGNORE_NAME_CONSTRAINTS */ #ifdef WOLFSSL_SEP else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE)) @@ -3515,6 +7845,8 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) int strLen; word32 lenStartIdx = idx; word32 oid = 0; + int ret; + byte tag; if (GetLength(input, &idx, &strLen, sz) < 0) { WOLFSSL_MSG("\tfail: other name length"); @@ -3523,7 +7855,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) /* Consume the rest of this sequence. */ length -= (strLen + idx - lenStartIdx); - if (GetObjectId(input, &idx, &oid, sz) < 0) { + if (GetObjectId(input, &idx, &oid, oidCertAltNameType, sz) < 0) { WOLFSSL_MSG("\tbad OID"); return ASN_PARSE_E; } @@ -3533,7 +7865,11 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - if (input[idx++] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + if (GetASNTag(input, &idx, &tag, sz) < 0) { + return ASN_PARSE_E; + } + + if (tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { WOLFSSL_MSG("\twrong type"); return ASN_PARSE_E; } @@ -3548,17 +7884,14 @@ 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; + ret = GetASNObjectId(input, &idx, &strLen, sz); + if (ret != 0) { + WOLFSSL_MSG("\tbad OID"); + return ret; } - if (GetLength(input, &idx, &strLen, sz) < 0) { - WOLFSSL_MSG("\tfailed: str len"); - return ASN_PARSE_E; - } - - cert->hwType = (byte*)XMALLOC(strLen, cert->heap, 0); + cert->hwType = (byte*)XMALLOC(strLen, cert->heap, + DYNAMIC_TYPE_X509_EXT); if (cert->hwType == NULL) { WOLFSSL_MSG("\tOut of Memory"); return MEMORY_E; @@ -3568,17 +7901,12 @@ 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; - } + ret = GetOctetString(input, &idx, &strLen, sz); + if (ret < 0) + return ret; - if (GetLength(input, &idx, &strLen, sz) < 0) { - WOLFSSL_MSG("\tfailed: str len"); - return ASN_PARSE_E; - } - - cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap, 0); + cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap, + DYNAMIC_TYPE_X509_EXT); if (cert->hwSerialNum == NULL) { WOLFSSL_MSG("\tOut of Memory"); return MEMORY_E; @@ -3589,7 +7917,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; @@ -3607,13 +7935,14 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) return 0; } - -static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert) +static int DecodeBasicCaConstraint(const byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length = 0; + int ret; WOLFSSL_ENTER("DecodeBasicCaConstraint"); + if (GetSequence(input, &idx, &length, sz) < 0) { WOLFSSL_MSG("\tfail: bad SEQUENCE"); return ASN_PARSE_E; @@ -3625,40 +7954,35 @@ 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); + +#ifndef WOLFSSL_X509_BASICCONS_INT + 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; + cert->isCA = (byte)ret; +#else + if (ret < 0) { + if(input[idx] == ASN_INTEGER) { + /* For OpenSSL compatibility, if ASN_INTEGER it is valid format */ + cert->isCA = FALSE; + } else return ret; + } else + cert->isCA = (byte)ret; +#endif + + /* If there isn't any more data, return. */ + if (idx >= (word32)sz) { + return 0; } - if (input[idx++]) - cert->isCA = 1; - - #ifdef OPENSSL_EXTRA - /* 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; - } - - if (input[idx++] != 1) { - WOLFSSL_MSG("\tfail: pathlen too long"); - return ASN_PARSE_E; - } - - cert->pathLength = input[idx]; - cert->extBasicConstPlSet = 1; - #endif /* OPENSSL_EXTRA */ + ret = GetInteger7Bit(input, &idx, sz); + if (ret < 0) + return ret; + cert->pathLength = (byte)ret; + cert->pathLengthSet = 1; return 0; } @@ -3669,10 +7993,11 @@ static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert) #define GENERALNAME_URI 6 /* From RFC3280 SS4.2.1.7, GeneralName */ -static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert) +static int DecodeCrlDist(const byte* input, int sz, DecodedCert* cert) { - word32 idx = 0; + word32 idx = 0, localIdx; int length = 0; + byte tag = 0; WOLFSSL_ENTER("DecodeCrlDist"); @@ -3687,20 +8012,26 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert) /* The Distribution Point has three explicit optional members * First check for a DistributionPointName */ - if (input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + localIdx = idx; + if (GetASNTag(input, &localIdx, &tag, sz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { idx++; if (GetLength(input, &idx, &length, sz) < 0) return ASN_PARSE_E; - if (input[idx] == - (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CRLDP_FULL_NAME)) + localIdx = idx; + if (GetASNTag(input, &localIdx, &tag, sz) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | + CRLDP_FULL_NAME)) { idx++; if (GetLength(input, &idx, &length, sz) < 0) return ASN_PARSE_E; - if (input[idx] == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI)) + localIdx = idx; + if (GetASNTag(input, &localIdx, &tag, sz) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI)) { idx++; if (GetLength(input, &idx, &length, sz) < 0) @@ -3714,14 +8045,17 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert) /* This isn't a URI, skip it. */ idx += length; } - else + else { /* This isn't a FULLNAME, skip it. */ idx += length; + } } /* Check for reasonFlags */ + localIdx = idx; if (idx < (word32)sz && - input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) + GetASNTag(input, &localIdx, &tag, sz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { idx++; if (GetLength(input, &idx, &length, sz) < 0) @@ -3730,8 +8064,10 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert) } /* Check for cRLIssuer */ + localIdx = idx; if (idx < (word32)sz && - input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2)) + GetASNTag(input, &localIdx, &tag, sz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2)) { idx++; if (GetLength(input, &idx, &length, sz) < 0) @@ -3749,15 +8085,16 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert) } -static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert) +static int DecodeAuthInfo(const byte* input, int sz, DecodedCert* cert) /* - * Read the first of the Authority Information Access records. If there are + * Read Authority Information Access records. If there are * any issues, return without saving the record. */ { word32 idx = 0; int length = 0; - byte b; + int count = 0; + byte b = 0; word32 oid; WOLFSSL_ENTER("DecodeAuthInfo"); @@ -3766,27 +8103,43 @@ static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert) if (GetSequence(input, &idx, &length, sz) < 0) return ASN_PARSE_E; - while (idx < (word32)sz) { + while ((idx < (word32)sz) && (count < MAX_AIA_SZ)) { /* Unwrap a single AIA */ if (GetSequence(input, &idx, &length, sz) < 0) return ASN_PARSE_E; oid = 0; - if (GetObjectId(input, &idx, &oid, sz) < 0) + if (GetObjectId(input, &idx, &oid, oidCertAuthInfoType, sz) < 0) return ASN_PARSE_E; /* Only supporting URIs right now. */ - b = input[idx++]; + if (GetASNTag(input, &idx, &b, sz) < 0) + return ASN_PARSE_E; + if (GetLength(input, &idx, &length, sz) < 0) return ASN_PARSE_E; + /* Set ocsp entry */ if (b == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI) && oid == AIA_OCSP_OID) { cert->extAuthInfoSz = length; cert->extAuthInfo = input + idx; + count++; + #if !defined(OPENSSL_ALL) || !defined(WOLFSSL_QT) break; + #endif } + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + /* Set CaIssuers entry */ + else if ((b == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI)) && + oid == AIA_CA_ISSUER_OID) + { + cert->extAuthInfoCaIssuerSz = length; + cert->extAuthInfoCaIssuer = input + idx; + count++; + } + #endif idx += length; } @@ -3794,10 +8147,11 @@ static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert) } -static int DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert) +static int DecodeAuthKeyId(const byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length = 0, ret = 0; + byte tag; WOLFSSL_ENTER("DecodeAuthKeyId"); @@ -3806,124 +8160,107 @@ static int DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - if (input[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) { + if (GetASNTag(input, &idx, &tag, sz) < 0) { + return ASN_PARSE_E; + } + + if (tag != (ASN_CONTEXT_SPECIFIC | 0)) { WOLFSSL_MSG("\tinfo: OPTIONAL item 0, not available\n"); + cert->extAuthKeyIdSet = 0; return 0; } - if (GetLength(input, &idx, &length, sz) < 0) { + if (GetLength(input, &idx, &length, sz) <= 0) { WOLFSSL_MSG("\tfail: extension data length"); return ASN_PARSE_E; } - #ifdef OPENSSL_EXTRA - cert->extAuthKeyIdSrc = &input[idx]; - cert->extAuthKeyIdSz = length; - #endif /* OPENSSL_EXTRA */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extAuthKeyIdSrc = &input[idx]; + cert->extAuthKeyIdSz = length; +#endif /* OPENSSL_EXTRA */ if (length == KEYID_SIZE) { XMEMCPY(cert->extAuthKeyId, input + idx, length); } - else { - #ifdef NO_SHA - ret = wc_Sha256Hash(input + idx, length, cert->extAuthKeyId); - #else - ret = wc_ShaHash(input + idx, length, cert->extAuthKeyId); - #endif - } + else + ret = CalcHashId(input + idx, length, cert->extAuthKeyId); return ret; } -static int DecodeSubjKeyId(byte* input, int sz, DecodedCert* cert) +static int DecodeSubjKeyId(const byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length = 0, ret = 0; WOLFSSL_ENTER("DecodeSubjKeyId"); - if (input[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); + if (sz <= 0) 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 + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) cert->extSubjKeyIdSrc = &input[idx]; cert->extSubjKeyIdSz = length; #endif /* OPENSSL_EXTRA */ - if (length == SIGNER_DIGEST_SIZE) { + if (length == KEYID_SIZE) { XMEMCPY(cert->extSubjKeyId, input + idx, length); } - else { - #ifdef NO_SHA - ret = wc_Sha256Hash(input + idx, length, cert->extSubjKeyId); - #else - ret = wc_ShaHash(input + idx, length, cert->extSubjKeyId); - #endif - } + else + ret = CalcHashId(input + idx, length, cert->extSubjKeyId); return ret; } -static int DecodeKeyUsage(byte* input, int sz, DecodedCert* cert) +static int DecodeKeyUsage(const byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length; - byte unusedBits; + int ret; WOLFSSL_ENTER("DecodeKeyUsage"); - if (input[idx++] != ASN_BIT_STRING) { - WOLFSSL_MSG("\tfail: key usage expected bit string"); - return ASN_PARSE_E; - } + ret = CheckBitString(input, &idx, &length, sz, 0, NULL); + if (ret != 0) + return ret; - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: key usage bad length"); - return ASN_PARSE_E; - } - - unusedBits = input[idx++]; - length--; - - if (length == 2) { - cert->extKeyUsage = (word16)((input[idx] << 8) | input[idx+1]); - cert->extKeyUsage >>= unusedBits; - } - else if (length == 1) - cert->extKeyUsage = (word16)(input[idx] << 1); + cert->extKeyUsage = (word16)(input[idx]); + if (length == 2) + cert->extKeyUsage |= (word16)(input[idx+1] << 8); return 0; } -static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert) +static int DecodeExtKeyUsage(const byte* input, int sz, DecodedCert* cert) { word32 idx = 0, oid; - int length; + int length, ret; - WOLFSSL_ENTER("DecodeExtKeyUsage"); + WOLFSSL_MSG("DecodeExtKeyUsage"); if (GetSequence(input, &idx, &length, sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE"); return ASN_PARSE_E; } - #ifdef OPENSSL_EXTRA - cert->extExtKeyUsageSrc = input + idx; - cert->extExtKeyUsageSz = length; - #endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extExtKeyUsageSrc = input + idx; + cert->extExtKeyUsageSz = length; +#endif while (idx < (word32)sz) { - if (GetObjectId(input, &idx, &oid, sz) < 0) - return ASN_PARSE_E; + ret = GetObjectId(input, &idx, &oid, oidCertKeyUseType, sz); + if (ret == ASN_UNKNOWN_OID_E) + continue; + else if (ret < 0) + return ret; switch (oid) { case EKU_ANY_OID: @@ -3935,14 +8272,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 + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extExtKeyUsageCount++; + #endif } return 0; @@ -3950,7 +8296,9 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert) #ifndef IGNORE_NAME_CONSTRAINTS -static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap) +#define ASN_TYPE_MASK 0xF +static int DecodeSubtree(const byte* input, int sz, + Base_entry** head, void* heap) { word32 idx = 0; @@ -3959,27 +8307,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; @@ -3988,12 +8346,13 @@ static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap) entry->name = (char*)XMALLOC(strLength, heap, DYNAMIC_TYPE_ALTNAME); if (entry->name == NULL) { WOLFSSL_MSG("allocate error"); + XFREE(entry, heap, DYNAMIC_TYPE_ALTNAME); return MEMORY_E; } XMEMCPY(entry->name, &input[nameIdx], strLength); entry->nameSz = strLength; - entry->type = b & 0x0F; + entry->type = bType; entry->next = *head; *head = entry; @@ -4006,7 +8365,7 @@ static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap) } -static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert) +static int DecodeNameConstraints(const byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length = 0; @@ -4045,51 +8404,176 @@ static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert) } #endif /* IGNORE_NAME_CONSTRAINTS */ +#if (defined(WOLFSSL_CERT_EXT) && !defined(WOLFSSL_SEP)) || defined(OPENSSL_EXTRA) -#ifdef WOLFSSL_SEP - static int DecodeCertPolicy(byte* input, int sz, DecodedCert* cert) +/* Decode ITU-T X.690 OID format to a string representation + * return string length */ +int DecodePolicyOID(char *out, word32 outSz, const byte *in, word32 inSz) +{ + word32 val, inIdx = 0, outIdx = 0; + int w = 0; + + if (out == NULL || in == NULL || outSz < 4 || inSz < 2) + return BAD_FUNC_ARG; + + /* The first byte expands into b/40 dot b%40. */ + val = in[inIdx++]; + + w = XSNPRINTF(out, outSz, "%u.%u", val / 40, val % 40); + if (w < 0) + goto exit; + outIdx += w; + val = 0; + + while (inIdx < inSz && outIdx < outSz) { + /* extract the next OID digit from in to val */ + /* first bit is used to set if value is coded on 1 or multiple bytes */ + if (in[inIdx] & 0x80) { + val += in[inIdx] & 0x7F; + val *= 128; + } + else { + /* write val as text into out */ + val += in[inIdx]; + w = XSNPRINTF(out + outIdx, outSz - outIdx, ".%u", val); + if (w < 0) + goto exit; + outIdx += w; + val = 0; + } + inIdx++; + } + if (outIdx == outSz) + outIdx--; + out[outIdx] = 0; + + w = (int)outIdx; + +exit: + return w; +} +#endif /* WOLFSSL_CERT_EXT && !WOLFSSL_SEP */ + +#if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_QT) + /* Reference: https://tools.ietf.org/html/rfc5280#section-4.2.1.4 */ + static int DecodeCertPolicy(const byte* input, int sz, DecodedCert* cert) { word32 idx = 0; - int length = 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"); + #if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) + /* Check if cert is null before dereferencing below */ + if (cert == NULL) + return BAD_FUNC_ARG; + #endif + + #if defined(WOLFSSL_CERT_EXT) + cert->extCertPoliciesNb = 0; + #endif + + if (GetSequence(input, &idx, &total_length, sz) < 0) { + WOLFSSL_MSG("\tGet CertPolicy total seq failed"); + return ASN_PARSE_E; + } + + /* Validate total length */ + if (total_length > (sz - (int)idx)) { + WOLFSSL_MSG("\tCertPolicy length mismatch"); + return ASN_PARSE_E; + } /* Unwrap certificatePolicies */ - if (GetSequence(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tdeviceType isn't OID"); - return ASN_PARSE_E; - } - - if (GetSequence(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tdeviceType isn't OID"); - return ASN_PARSE_E; - } - - if (input[idx++] != ASN_OBJECT_ID) { - WOLFSSL_MSG("\tdeviceType isn't OID"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tCouldn't read length of deviceType"); - return ASN_PARSE_E; - } - - if (length > 0) { - cert->deviceType = (byte*)XMALLOC(length, cert->heap, 0); - if (cert->deviceType == NULL) { - WOLFSSL_MSG("\tCouldn't alloc memory for deviceType"); - return MEMORY_E; + do { + if (GetSequence(input, &idx, &policy_length, sz) < 0) { + WOLFSSL_MSG("\tGet CertPolicy seq failed"); + return ASN_PARSE_E; } - cert->deviceTypeSz = length; - XMEMCPY(cert->deviceType, input + idx, 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 */ + if (length > (sz - (int)idx)) { + WOLFSSL_MSG("\tCertPolicy length exceeds input buffer"); + return ASN_PARSE_E; + } + + #if defined(WOLFSSL_SEP) + cert->deviceType = (byte*)XMALLOC(length, cert->heap, + DYNAMIC_TYPE_X509_EXT); + if (cert->deviceType == NULL) { + WOLFSSL_MSG("\tCouldn't alloc memory for deviceType"); + return MEMORY_E; + } + cert->deviceTypeSz = length; + XMEMCPY(cert->deviceType, input + idx, length); + break; + #elif defined(WOLFSSL_CERT_EXT) + /* decode cert policy */ + 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 separate 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 + WOLFSSL_LEAVE("DecodeCertPolicy : unsupported mode", 0); + return 0; + #endif + } + idx += policy_length; + } while((int)idx < total_length + #if defined(WOLFSSL_CERT_EXT) + && cert->extCertPoliciesNb < MAX_CERTPOL_NB + #endif + ); WOLFSSL_LEAVE("DecodeCertPolicy", 0); return 0; } #endif /* WOLFSSL_SEP */ +/* Macro to check if bit is set, if not sets and return success. + Otherwise returns failure */ +/* Macro required here because bit-field operation */ +#ifndef WOLFSSL_NO_ASN_STRICT + #define VERIFY_AND_SET_OID(bit) \ + if (bit == 0) \ + bit = 1; \ + else \ + return ASN_OBJECT_ID_E; +#else + /* With no strict defined, the verify is skipped */ +#define VERIFY_AND_SET_OID(bit) bit = 1; +#endif static int DecodeCertExtensions(DecodedCert* cert) /* @@ -4097,68 +8581,85 @@ static int DecodeCertExtensions(DecodedCert* cert) * index. It is works starting with the recorded extensions pointer. */ { + int ret = 0; word32 idx = 0; int sz = cert->extensionsSz; - byte* input = cert->extensions; + const byte* input = cert->extensions; int length; word32 oid; byte critical = 0; byte criticalFail = 0; + byte tag = 0; WOLFSSL_ENTER("DecodeCertExtensions"); if (input == NULL || sz == 0) return BAD_FUNC_ARG; - if (input[idx++] != ASN_EXTENSIONS) + if (GetASNTag(input, &idx, &tag, sz) < 0) { return ASN_PARSE_E; + } - if (GetLength(input, &idx, &length, sz) < 0) + if (tag != ASN_EXTENSIONS) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); return ASN_PARSE_E; + } - if (GetSequence(input, &idx, &length, sz) < 0) + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: invalid length"); return ASN_PARSE_E; - + } + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)"); + return ASN_PARSE_E; + } + while (idx < (word32)sz) { + word32 localIdx; + if (GetSequence(input, &idx, &length, sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE"); return ASN_PARSE_E; } oid = 0; - if (GetObjectId(input, &idx, &oid, sz) < 0) { + if ((ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz)) < 0) { WOLFSSL_MSG("\tfail: OBJECT ID"); - return ASN_PARSE_E; + return ret; } /* 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; + if ((idx + 1) > (word32)sz) { + WOLFSSL_MSG("\tfail: malformed buffer"); + return BUFFER_E; + } + + localIdx = idx; + if (GetASNTag(input, &localIdx, &tag, sz) == 0) { + if (tag == ASN_BOOLEAN) { + ret = GetBoolean(input, &idx, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: critical boolean"); + return ret; + } + + critical = (byte)ret; } - if (input[idx++]) - critical = 1; } /* 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) { case BASIC_CA_OID: - #ifdef OPENSSL_EXTRA - cert->extBasicConstSet = 1; + VERIFY_AND_SET_OID(cert->extBasicConstSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) cert->extBasicConstCrit = critical; #endif if (DecodeBasicCaConstraint(&input[idx], length, cert) < 0) @@ -4166,57 +8667,95 @@ static int DecodeCertExtensions(DecodedCert* cert) break; case CRL_DIST_OID: + VERIFY_AND_SET_OID(cert->extCRLdistSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extCRLdistCrit = critical; + #endif if (DecodeCrlDist(&input[idx], length, cert) < 0) return ASN_PARSE_E; break; case AUTH_INFO_OID: + VERIFY_AND_SET_OID(cert->extAuthInfoSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extAuthInfoCrit = critical; + #endif if (DecodeAuthInfo(&input[idx], length, cert) < 0) return ASN_PARSE_E; break; case ALT_NAMES_OID: - #ifdef OPENSSL_EXTRA - cert->extSubjAltNameSet = 1; + VERIFY_AND_SET_OID(cert->extSubjAltNameSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) cert->extSubjAltNameCrit = critical; #endif - if (DecodeAltNames(&input[idx], length, cert) < 0) - return ASN_PARSE_E; + ret = DecodeAltNames(&input[idx], length, cert); + if (ret < 0) + return ret; break; case AUTH_KEY_OID: - cert->extAuthKeyIdSet = 1; - #ifdef OPENSSL_EXTRA + VERIFY_AND_SET_OID(cert->extAuthKeyIdSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) cert->extAuthKeyIdCrit = critical; #endif + #ifndef WOLFSSL_ALLOW_CRIT_SKID + /* This check is added due to RFC 5280 section 4.2.1.1 + * 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 Auth Key ID is not allowed"); + WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted"); + return ASN_CRIT_EXT_E; + } + #endif if (DecodeAuthKeyId(&input[idx], length, cert) < 0) return ASN_PARSE_E; break; case SUBJ_KEY_OID: - cert->extSubjKeyIdSet = 1; - #ifdef OPENSSL_EXTRA + VERIFY_AND_SET_OID(cert->extSubjKeyIdSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) 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; case CERT_POLICY_OID: - WOLFSSL_MSG("Certificate Policy extension not supported yet."); - #ifdef WOLFSSL_SEP - #ifdef OPENSSL_EXTRA - cert->extCertPolicySet = 1; + #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT) + VERIFY_AND_SET_OID(cert->extCertPolicySet); + #if defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) cert->extCertPolicyCrit = critical; #endif - if (DecodeCertPolicy(&input[idx], length, cert) < 0) + #endif + #if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) || \ + defined(WOLFSSL_QT) + if (DecodeCertPolicy(&input[idx], length, cert) < 0) { return ASN_PARSE_E; + } + #else + WOLFSSL_MSG("Certificate Policy extension not supported yet."); #endif break; case KEY_USAGE_OID: - cert->extKeyUsageSet = 1; - #ifdef OPENSSL_EXTRA + VERIFY_AND_SET_OID(cert->extKeyUsageSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) cert->extKeyUsageCrit = critical; #endif if (DecodeKeyUsage(&input[idx], length, cert) < 0) @@ -4224,8 +8763,8 @@ static int DecodeCertExtensions(DecodedCert* cert) break; case EXT_KEY_USAGE_OID: - cert->extExtKeyUsageSet = 1; - #ifdef OPENSSL_EXTRA + VERIFY_AND_SET_OID(cert->extExtKeyUsageSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) cert->extExtKeyUsageCrit = critical; #endif if (DecodeExtKeyUsage(&input[idx], length, cert) < 0) @@ -4234,8 +8773,17 @@ static int DecodeCertExtensions(DecodedCert* cert) #ifndef IGNORE_NAME_CONSTRAINTS case NAME_CONS_OID: - cert->extNameConstraintSet = 1; - #ifdef OPENSSL_EXTRA + #ifndef WOLFSSL_NO_ASN_STRICT + /* Verify RFC 5280 Sec 4.2.1.10 rule: + "The name constraints extension, + which MUST be used only in a CA certificate" */ + if (!cert->isCA) { + WOLFSSL_MSG("Name constraints allowed only for CA certs"); + return ASN_NAME_INVALID_E; + } + #endif + VERIFY_AND_SET_OID(cert->extNameConstraintSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) cert->extNameConstraintCrit = critical; #endif if (DecodeNameConstraints(&input[idx], length, cert) < 0) @@ -4244,17 +8792,31 @@ static int DecodeCertExtensions(DecodedCert* cert) #endif /* IGNORE_NAME_CONSTRAINTS */ case INHIBIT_ANY_OID: + VERIFY_AND_SET_OID(cert->inhibitAnyOidSet); WOLFSSL_MSG("Inhibit anyPolicy extension not supported yet."); break; + #ifndef IGNORE_NETSCAPE_CERT_TYPE + case NETSCAPE_CT_OID: + WOLFSSL_MSG("Netscape certificate type extension not supported " + "yet."); + if (CheckBitString(input, &idx, &length, idx + length, 0, + NULL) < 0) { + return ASN_PARSE_E; + } + break; + #endif + default: + #ifndef WOLFSSL_NO_ASN_STRICT /* While it is a failure to not support critical extensions, * still parse the certificate ignoring the unsupported - * extention to allow caller to accept it with the verify + * extension to allow caller to accept it with the verify * callback. */ if (critical) criticalFail = 1; - break; + #endif + break; } idx += length; } @@ -4262,7 +8824,6 @@ static int DecodeCertExtensions(DecodedCert* cert) return criticalFail ? ASN_CRIT_EXT_E : 0; } - int ParseCert(DecodedCert* cert, int type, int verify, void* cm) { int ret; @@ -4297,126 +8858,662 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) return ret; } - /* from SSL proper, for locking can't do find here anymore */ #ifdef __cplusplus extern "C" { #endif - WOLFSSL_LOCAL Signer* GetCA(void* signers, byte* hash); + Signer* GetCA(void* signers, byte* hash); #ifndef NO_SKID - WOLFSSL_LOCAL Signer* GetCAByName(void* signers, byte* hash); + Signer* GetCAByName(void* signers, byte* hash); #endif #ifdef __cplusplus - } + } #endif +#if defined(WOLFCRYPT_ONLY) || defined(NO_CERTS) + +/* dummy functions, not using wolfSSL so don't need actual ones */ +Signer* GetCA(void* signers, byte* hash) +{ + (void)hash; + + return (Signer*)signers; +} + +#ifndef NO_SKID +Signer* GetCAByName(void* signers, byte* hash) +{ + (void)hash; + + return (Signer*)signers; +} +#endif /* NO_SKID */ + +#endif /* WOLFCRYPT_ONLY || NO_CERTS */ + +#if 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 + +#if defined(WOLFSSL_SMALL_CERT_VERIFY) || defined(OPENSSL_EXTRA) +/* Only quick step through the certificate to find fields that are then used + * in certificate signature verification. + * Must use the signature OID from the signed part of the certificate. + * + * This is only for minimizing dynamic memory usage during TLS certificate + * chain processing. + * Doesn't support: + * OCSP Only: alt lookup using subject and pub key w/o sig check + */ +static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap, + void* cm, const byte* pubKey, word32 pubKeySz, int pubKeyOID) +{ +#ifndef WOLFSSL_SMALL_STACK + SignatureCtx sigCtx[1]; +#else + SignatureCtx* sigCtx; +#endif + byte hash[KEYID_SIZE]; + Signer* ca = NULL; + word32 idx = 0; + int len; + word32 tbsCertIdx = 0; + word32 sigIndex = 0; + word32 signatureOID = 0; + word32 oid = 0; + word32 issuerIdx = 0; + word32 issuerSz = 0; +#ifndef NO_SKID + int extLen = 0; + word32 extIdx = 0; + word32 extEndIdx = 0; + int extAuthKeyIdSet = 0; +#endif + int ret = 0; + word32 localIdx; + byte tag; + + + if (cert == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + sigCtx = (SignatureCtx*)XMALLOC(sizeof(*sigCtx), heap, DYNAMIC_TYPE_SIGNATURE); + if (sigCtx == NULL) + return MEMORY_E; +#endif + InitSignatureCtx(sigCtx, heap, INVALID_DEVID); + + /* Certificate SEQUENCE */ + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0) { + tbsCertIdx = idx; + + /* TBSCertificate SEQUENCE */ + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + sigIndex = len + idx; + + if ((idx + 1) > certSz) + ret = BUFFER_E; + } + if (ret == 0) { + /* version - optional */ + localIdx = idx; + if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) { + if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + idx++; + if (GetLength(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + idx += len; + } + } + } + + if (ret == 0) { + /* serialNumber */ + if (GetASNHeader(cert, ASN_INTEGER, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + idx += len; + + /* signature */ + if (GetAlgoId(cert, &idx, &signatureOID, oidSigType, certSz) < 0) + ret = ASN_PARSE_E; + } + + if (ret == 0) { + issuerIdx = idx; + /* issuer */ + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + issuerSz = len + idx - issuerIdx; + } +#ifndef NO_SKID + if (ret == 0) { + idx += len; + + /* validity */ + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + idx += len; + + /* subject */ + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + idx += len; + + /* subjectPublicKeyInfo */ + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + idx += len; + + if ((idx + 1) > certSz) + ret = BUFFER_E; + } + if (ret == 0) { + /* issuerUniqueID - optional */ + localIdx = idx; + if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) { + if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + idx++; + if (GetLength(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + idx += len; + } + } + } + if (ret == 0) { + if ((idx + 1) > certSz) + ret = BUFFER_E; + } + if (ret == 0) { + /* subjectUniqueID - optional */ + localIdx = idx; + if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) { + if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) { + idx++; + if (GetLength(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + idx += len; + } + } + } + + if (ret == 0) { + if ((idx + 1) > certSz) + ret = BUFFER_E; + } + /* extensions - optional */ + localIdx = idx; + if (ret == 0 && GetASNTag(cert, &localIdx, &tag, certSz) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)) { + idx++; + if (GetLength(cert, &idx, &extLen, certSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0) { + if (GetSequence(cert, &idx, &extLen, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + extEndIdx = idx + extLen; + + /* Check each extension for the ones we want. */ + while (ret == 0 && idx < extEndIdx) { + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0) { + extIdx = idx; + if (GetObjectId(cert, &extIdx, &oid, oidCertExtType, + certSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0) { + if ((extIdx + 1) > certSz) + ret = BUFFER_E; + } + } + + if (ret == 0) { + localIdx = extIdx; + if (GetASNTag(cert, &localIdx, &tag, certSz) == 0 && + tag == ASN_BOOLEAN) { + if (GetBoolean(cert, &extIdx, certSz) < 0) + ret = ASN_PARSE_E; + } + } + if (ret == 0) { + if (GetOctetString(cert, &extIdx, &extLen, certSz) < 0) + ret = ASN_PARSE_E; + } + + if (ret == 0) { + switch (oid) { + case AUTH_KEY_OID: + if (GetSequence(cert, &extIdx, &extLen, certSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && (extIdx + 1) >= certSz) + ret = BUFFER_E; + + if (ret == 0 && + GetASNTag(cert, &extIdx, &tag, certSz) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | 0)) { + if (GetLength(cert, &extIdx, &extLen, certSz) <= 0) + ret = ASN_PARSE_E; + if (ret == 0) { + extAuthKeyIdSet = 1; + if (extLen == KEYID_SIZE) + XMEMCPY(hash, cert + extIdx, extLen); + else { + ret = CalcHashId(cert + extIdx, extLen, + hash); + } + } + } + break; + + default: + break; + } + } + idx += len; + } + } + } + + if (ret == 0 && pubKey == NULL) { + if (extAuthKeyIdSet) + ca = GetCA(cm, hash); + if (ca == NULL) { + ret = CalcHashId(cert + issuerIdx, issuerSz, hash); + if (ret == 0) + ca = GetCAByName(cm, hash); + } + } +#else + if (ret == 0 && pubKey == NULL) { + ret = CalcHashId(cert + issuerIdx, issuerSz, hash); + if (ret == 0) + ca = GetCA(cm, hash); + } +#endif /* !NO_SKID */ + if (ca == NULL && pubKey == NULL) + ret = ASN_NO_SIGNER_E; + + if (ret == 0) { + idx = sigIndex; + /* signatureAlgorithm */ + if (GetAlgoId(cert, &idx, &oid, oidSigType, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + if (oid != signatureOID) + ret = ASN_SIG_OID_E; + } + if (ret == 0) { + /* signatureValue */ + if (CheckBitString(cert, &idx, &len, certSz, 1, NULL) < 0) + ret = ASN_PARSE_E; + } + + if (ret == 0) { + if (pubKey != NULL) { + ret = ConfirmSignature(sigCtx, cert + tbsCertIdx, + sigIndex - tbsCertIdx, + pubKey, pubKeySz, pubKeyOID, + cert + idx, len, signatureOID, NULL); + } + else { + ret = ConfirmSignature(sigCtx, cert + tbsCertIdx, + sigIndex - tbsCertIdx, + ca->publicKey, ca->pubKeySize, ca->keyOID, + cert + idx, len, signatureOID, NULL); + } + if (ret != 0) { + WOLFSSL_MSG("Confirm signature failed"); + } + } + + FreeSignatureCtx(sigCtx); +#ifdef WOLFSSL_SMALL_STACK + if (sigCtx != NULL) + XFREE(sigCtx, heap, DYNAMIC_TYPE_SIGNATURE); +#endif + return ret; +} + +#ifdef OPENSSL_EXTRA +/* Call CheckCertSignature_ex using a public key buffer for verification + */ +int CheckCertSignaturePubKey(const byte* cert, word32 certSz, void* heap, + const byte* pubKey, word32 pubKeySz, int pubKeyOID) +{ + return CheckCertSignature_ex(cert, certSz, heap, NULL, + pubKey, pubKeySz, pubKeyOID); +} +#endif /* OPENSSL_EXTRA */ +#ifdef WOLFSSL_SMALL_CERT_VERIFY +/* Call CheckCertSignature_ex using a certificate manager (cm) + */ +int CheckCertSignature(const byte* cert, word32 certSz, void* heap, void* cm) +{ + return CheckCertSignature_ex(cert, certSz, heap, cm, NULL, 0, 0); +} +#endif /* WOLFSSL_SMALL_CERT_VERIFY */ +#endif /* WOLFSSL_SMALL_CERT_VERIFY || OPENSSL_EXTRA */ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) { + int ret = 0; + int checkPathLen = 0; + int decrementMaxPathLen = 0; word32 confirmOID; - int ret; - int badDate = 0; - int criticalExt = 0; +#if defined(WOLFSSL_RENESAS_TSIP) + int idx = 0; +#endif + byte* tsip_encRsaKeyIdx; - 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) { + cert->badDate = 0; + cert->criticalExt = 0; + if ((ret = DecodeToKey(cert, verify)) < 0) { + if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) + cert->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, - 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) + cert->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) { - #ifdef NO_SHA - ret = wc_Sha256Hash(cert->publicKey, cert->pubKeySize, + if (cert->extSubjKeyIdSet == 0 && cert->publicKey != NULL && + cert->pubKeySize > 0) { + ret = CalcHashId(cert->publicKey, cert->pubKeySize, cert->extSubjKeyId); - #else - ret = wc_ShaHash(cert->publicKey, cert->pubKeySize, - cert->extSubjKeyId); - #endif if (ret != 0) return ret; } - #endif + #endif /* !NO_SKID */ - if (verify && type != CA_TYPE) { - Signer* 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"); - - if (ca) { -#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 */ - /* try to confirm/verify signature */ - if (!ConfirmSignature(cert->source + cert->certBegin, + if (!cert->selfSigned || (verify != NO_VERIFY && type != CA_TYPE && + type != TRUSTED_PEER_TYPE)) { + cert->ca = NULL; + #ifndef NO_SKID + if (cert->extAuthKeyIdSet) { + cert->ca = GetCA(cm, cert->extAuthKeyId); + } + if (cert->ca == NULL && cert->extSubjKeyIdSet + && verify != VERIFY_OCSP) { + cert->ca = GetCA(cm, cert->extSubjKeyId); + } + if (cert->ca != NULL && XMEMCMP(cert->issuerHash, + cert->ca->subjectNameHash, KEYID_SIZE) != 0) { + cert->ca = NULL; + } + if (cert->ca == NULL) { + cert->ca = GetCAByName(cm, cert->issuerHash); + /* If AKID is available then this CA doesn't have the public + * key required */ + if (cert->ca && cert->extAuthKeyIdSet) { + WOLFSSL_MSG("CA SKID doesn't match AKID"); + cert->ca = NULL; + } + } + + /* 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 */ + #else + cert->ca = GetCA(cm, cert->issuerHash); + #endif /* !NO_SKID */ + } + + if (cert->selfSigned) { + cert->maxPathLen = WOLFSSL_MAX_PATH_LEN; + } else { + /* RFC 5280 Section 4.2.1.9: + * + * load/receive check + * + * 1) Is CA boolean set? + * No - SKIP CHECK + * Yes - Check key usage + * 2) Is Key usage extension present? + * No - goto 3 + * Yes - check keyCertSign assertion + * 2.a) Is keyCertSign asserted? + * No - goto 4 + * Yes - goto 3 + * 3) Is pathLen set? + * No - goto 4 + * Yes - check pathLen against maxPathLen. + * 3.a) Is pathLen less than maxPathLen? + * No - goto 4 + * Yes - set maxPathLen to pathLen and EXIT + * 4) Is maxPathLen > 0? + * Yes - Reduce by 1 + * No - ERROR + */ + + if (cert->ca && cert->pathLengthSet) { + cert->maxPathLen = cert->pathLength; + if (cert->isCA) { + WOLFSSL_MSG("\tCA boolean set"); + if (cert->extKeyUsageSet) { + WOLFSSL_MSG("\tExtension Key Usage Set"); + if ((cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) != 0) { + checkPathLen = 1; + } else { + decrementMaxPathLen = 1; + } + } else { + checkPathLen = 1; + } /* !cert->ca check */ + } /* cert is not a CA (assuming entity cert) */ + + if (checkPathLen && cert->pathLengthSet) { + if (cert->pathLength < cert->ca->maxPathLen) { + WOLFSSL_MSG("\tmaxPathLen status: set to pathLength"); + cert->maxPathLen = cert->pathLength; + } else { + decrementMaxPathLen = 1; + } + } + + if (decrementMaxPathLen && cert->ca->maxPathLen > 0) { + WOLFSSL_MSG("\tmaxPathLen status: reduce by 1"); + cert->maxPathLen = cert->ca->maxPathLen - 1; + if (verify != NO_VERIFY && type != CA_TYPE && + type != TRUSTED_PEER_TYPE) { + WOLFSSL_MSG("\tmaxPathLen status: OK"); + } + } else if (decrementMaxPathLen && cert->ca->maxPathLen == 0) { + cert->maxPathLen = 0; + if (verify != NO_VERIFY && type != CA_TYPE && + type != TRUSTED_PEER_TYPE) { + WOLFSSL_MSG("\tNon-entity cert, maxPathLen is 0"); + WOLFSSL_MSG("\tmaxPathLen status: ERROR"); + return ASN_PATHLEN_INV_E; + } + } + } else if (cert->ca && cert->isCA) { + /* case where cert->pathLength extension is not set */ + if (cert->ca->maxPathLen > 0) { + cert->maxPathLen = cert->ca->maxPathLen - 1; + } else { + cert->maxPathLen = 0; + if (verify != NO_VERIFY && type != CA_TYPE && + type != TRUSTED_PEER_TYPE) { + WOLFSSL_MSG("\tNon-entity cert, maxPathLen is 0"); + WOLFSSL_MSG("\tmaxPathLen status: ERROR"); + return ASN_PATHLEN_INV_E; + } + } + } + #ifdef HAVE_OCSP + if (verify != NO_VERIFY && type != CA_TYPE && + type != TRUSTED_PEER_TYPE) { + if (cert->ca) { + /* Need the CA's public key hash for OCSP */ + XMEMCPY(cert->issuerKeyHash, cert->ca->subjectKeyHash, + KEYID_SIZE); + } + + } + #endif /* HAVE_OCSP */ + } + } +#if defined(WOLFSSL_RENESAS_TSIP) + /* prepare for TSIP TLS cert verification API use */ + if (cert->keyOID == RSAk) { + /* to call TSIP API, it needs keys position info in bytes */ + if ((ret = RsaPublicKeyDecodeRawIndex(cert->publicKey, (word32*)&idx, + cert->pubKeySize, + &cert->sigCtx.pubkey_n_start, + &cert->sigCtx.pubkey_n_len, + &cert->sigCtx.pubkey_e_start, + &cert->sigCtx.pubkey_e_len)) != 0) { + WOLFSSL_MSG("Decoding index from cert failed."); + return ret; + } + cert->sigCtx.certBegin = cert->certBegin; + } + /* check if we can use TSIP for cert verification */ + /* if the ca is verified as tsip root ca. */ + /* TSIP can only handle 2048 bits(256 byte) key. */ + if (cert->ca && tsip_checkCA(cert->ca->cm_idx) != 0 && + cert->sigCtx.pubkey_n_len == 256) { + + /* assign memory to encrypted tsip Rsa key index */ + if (!cert->tsip_encRsaKeyIdx) + cert->tsip_encRsaKeyIdx = + (byte*)XMALLOC(TSIP_TLS_ENCPUBKEY_SZ_BY_CERTVRFY, + cert->heap, DYNAMIC_TYPE_RSA); + if (cert->tsip_encRsaKeyIdx == NULL) + return MEMORY_E; + } else { + if (cert->ca) { + /* TSIP isn't usable */ + if (tsip_checkCA(cert->ca->cm_idx) == 0) + WOLFSSL_MSG("TSIP isn't usable because the ca isn't verified " + "by TSIP."); + else if (cert->sigCtx.pubkey_n_len != 256) + WOLFSSL_MSG("TSIP isn't usable because the ca isn't signed by " + "RSA 2048."); + else + WOLFSSL_MSG("TSIP isn't usable"); + } + cert->tsip_encRsaKeyIdx = NULL; + } + + tsip_encRsaKeyIdx = cert->tsip_encRsaKeyIdx; +#else + tsip_encRsaKeyIdx = NULL; +#endif + + if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { + if (cert->ca) { + if (verify == VERIFY || verify == VERIFY_OCSP || + verify == VERIFY_SKIP_DATE) { + /* try to confirm/verify signature */ + if ((ret = ConfirmSignature(&cert->sigCtx, + 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; + cert->ca->publicKey, cert->ca->pubKeySize, + cert->ca->keyOID, cert->signature, + cert->sigLength, cert->signatureOID, + tsip_encRsaKeyIdx)) != 0) { + if (ret != 0 && 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)) { - WOLFSSL_MSG("Confirm name constraint failed"); - return ASN_NAME_INVALID_E; + #ifndef IGNORE_NAME_CONSTRAINTS + if (verify == VERIFY || verify == VERIFY_OCSP || + verify == VERIFY_NAME || verify == VERIFY_SKIP_DATE) { + /* check that this cert's name is permitted by the signer's + * name constraints */ + 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 { /* no signer */ @@ -4425,32 +9522,30 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) } } - if (badDate != 0) - return badDate; +#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID) +exit_pcr: +#endif - if (criticalExt != 0) - return criticalExt; + if (cert->badDate != 0) { + if (verify != VERIFY_SKIP_DATE) { + return cert->badDate; + } + WOLFSSL_MSG("Date error: Verify option is skipping"); + } - return 0; + if (cert->criticalExt != 0) + return cert->criticalExt; + + return ret; } - /* Create and init an new signer */ Signer* MakeSigner(void* heap) { Signer* signer = (Signer*) XMALLOC(sizeof(Signer), heap, DYNAMIC_TYPE_SIGNER); if (signer) { - signer->pubKeySize = 0; - signer->keyOID = 0; - signer->publicKey = NULL; - signer->nameLen = 0; - signer->name = NULL; - #ifndef IGNORE_NAME_CONSTRAINTS - signer->permittedNames = NULL; - signer->excludedNames = NULL; - #endif /* IGNORE_NAME_CONSTRAINTS */ - signer->next = NULL; + XMEMSET(signer, 0, sizeof(Signer)); } (void)heap; @@ -4462,13 +9557,16 @@ Signer* MakeSigner(void* heap) 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 + XFREE((void*)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 +#ifdef WOLFSSL_SIGNER_DER_CERT + FreeDer(&signer->derCert); +#endif XFREE(signer, heap, DYNAMIC_TYPE_SIGNER); (void)heap; @@ -4491,14 +9589,59 @@ void FreeSignerTable(Signer** table, int rows, void* heap) } } +#ifdef WOLFSSL_TRUST_PEER_CERT +/* Free an individual trusted peer cert */ +void FreeTrustedPeer(TrustedPeerCert* tp, void* heap) +{ + if (tp == NULL) { + return; + } -WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header) + if (tp->name) { + XFREE(tp->name, heap, DYNAMIC_TYPE_SUBJECT_CN); + } + + 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 + XFREE(tp, heap, DYNAMIC_TYPE_CERT); + + (void)heap; +} + +/* Free the whole Trusted Peer linked list */ +void FreeTrustedPeerTable(TrustedPeerCert** table, int rows, void* heap) +{ + int i; + + for (i = 0; i < rows; i++) { + TrustedPeerCert* tp = table[i]; + while (tp) { + TrustedPeerCert* next = tp->next; + FreeTrustedPeer(tp, heap); + tp = next; + } + table[i] = NULL; + } +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + +int SetMyVersion(word32 version, byte* output, int header) { int i = 0; + if (output == NULL) + return BAD_FUNC_ARG; + if (header) { output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED; - output[i++] = ASN_BIT_STRING; + output[i++] = 3; } output[i++] = ASN_INTEGER; output[i++] = 0x01; @@ -4507,65 +9650,558 @@ WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header) return i; } +int SetSerialNumber(const byte* sn, word32 snSz, byte* output, + word32 outputSz, int maxSnSz) +{ + int i; + int snSzInt = (int)snSz; -WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output) + if (sn == NULL || output == NULL || snSzInt < 0) + return BAD_FUNC_ARG; + + /* remove leading zeros */ + while (snSzInt > 0 && sn[0] == 0) { + snSzInt--; + sn++; + } + /* RFC 5280 - 4.1.2.2: + * Serial numbers must be a positive value (and not zero) */ + if (snSzInt == 0) + return BAD_FUNC_ARG; + + if (sn[0] & 0x80) + maxSnSz--; + /* truncate if input is too long */ + if (snSzInt > maxSnSz) + snSzInt = maxSnSz; + + i = SetASNInt(snSzInt, sn[0], NULL); + /* truncate if input is too long */ + if (snSzInt > (int)outputSz - i) + snSzInt = (int)outputSz - i; + /* sanity check number of bytes to copy */ + if (snSzInt <= 0) { + return BUFFER_E; + } + + /* write out ASN.1 Integer */ + (void)SetASNInt(snSzInt, sn[0], output); + XMEMCPY(output + i, sn, snSzInt); + + /* compute final length */ + i += snSzInt; + + return i; +} + +#endif /* !NO_CERTS */ + +int GetSerialNumber(const byte* input, word32* inOutIdx, + byte* serial, int* serialSz, word32 maxIdx) { int result = 0; + int ret; - WOLFSSL_ENTER("SetSerialNumber"); + WOLFSSL_ENTER("GetSerialNumber"); - 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; - } + if (serial == NULL || input == NULL || serialSz == NULL) { + return BAD_FUNC_ARG; } + + /* First byte is ASN type */ + if ((*inOutIdx+1) > maxIdx) { + WOLFSSL_MSG("Bad idx first"); + return BUFFER_E; + } + + ret = GetASNInt(input, inOutIdx, serialSz, maxIdx); + if (ret != 0) + return ret; + + if (*serialSz > EXTERNAL_SERIAL_SIZE) { + WOLFSSL_MSG("Serial size bad"); + return ASN_PARSE_E; + } + + /* return serial */ + XMEMCPY(serial, &input[*inOutIdx], *serialSz); + *inOutIdx += *serialSz; + return result; } +#ifndef NO_CERTS + +int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) +{ + int ret = BAD_FUNC_ARG; + if (pDer) { + int dynType = 0; + DerBuffer* der; + + /* Determine dynamic type */ + switch (type) { + case CA_TYPE: dynType = DYNAMIC_TYPE_CA; break; + case CERT_TYPE: dynType = DYNAMIC_TYPE_CERT; break; + case CRL_TYPE: dynType = DYNAMIC_TYPE_CRL; break; + case DSA_TYPE: dynType = DYNAMIC_TYPE_DSA; break; + case ECC_TYPE: dynType = DYNAMIC_TYPE_ECC; break; + case RSA_TYPE: dynType = DYNAMIC_TYPE_RSA; break; + default: dynType = DYNAMIC_TYPE_KEY; break; + } + + /* Setup new buffer */ + *pDer = (DerBuffer*)XMALLOC(sizeof(DerBuffer) + length, heap, dynType); + if (*pDer == NULL) { + return MEMORY_E; + } + XMEMSET(*pDer, 0, sizeof(DerBuffer) + length); + + der = *pDer; + der->type = type; + der->dynType = dynType; /* Cache this for FreeDer */ + der->heap = heap; + der->buffer = (byte*)der + sizeof(DerBuffer); + der->length = length; + ret = 0; /* Success */ + } + return ret; +} + +void FreeDer(DerBuffer** pDer) +{ + if (pDer && *pDer) + { + DerBuffer* der = (DerBuffer*)*pDer; + + /* ForceZero private keys */ + if (der->type == PRIVATEKEY_TYPE) { + ForceZero(der->buffer, der->length); + } + der->buffer = NULL; + der->length = 0; + XFREE(der, der->heap, der->dynType); + + *pDer = NULL; + } +} + +int wc_AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) +{ + return AllocDer(pDer, length, type, heap); +} +void wc_FreeDer(DerBuffer** pDer) +{ + FreeDer(pDer); +} +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) -#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) +/* Max X509 header length indicates the max length + 2 ('\n', '\0') */ +#define MAX_X509_HEADER_SZ (37 + 2) + +wcchar BEGIN_CERT = "-----BEGIN CERTIFICATE-----"; +wcchar END_CERT = "-----END CERTIFICATE-----"; +#ifdef WOLFSSL_CERT_REQ + wcchar BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----"; + wcchar END_CERT_REQ = "-----END CERTIFICATE REQUEST-----"; +#endif +#ifndef NO_DH + wcchar BEGIN_DH_PARAM = "-----BEGIN DH PARAMETERS-----"; + wcchar END_DH_PARAM = "-----END DH PARAMETERS-----"; +#endif +#ifndef NO_DSA + wcchar BEGIN_DSA_PARAM = "-----BEGIN DSA PARAMETERS-----"; + wcchar END_DSA_PARAM = "-----END DSA PARAMETERS-----"; +#endif +wcchar BEGIN_X509_CRL = "-----BEGIN X509 CRL-----"; +wcchar END_X509_CRL = "-----END X509 CRL-----"; +wcchar BEGIN_RSA_PRIV = "-----BEGIN RSA PRIVATE KEY-----"; +wcchar END_RSA_PRIV = "-----END RSA PRIVATE KEY-----"; +wcchar BEGIN_PRIV_KEY = "-----BEGIN PRIVATE KEY-----"; +wcchar END_PRIV_KEY = "-----END PRIVATE KEY-----"; +wcchar BEGIN_ENC_PRIV_KEY = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; +wcchar END_ENC_PRIV_KEY = "-----END ENCRYPTED PRIVATE KEY-----"; +#ifdef HAVE_ECC + wcchar BEGIN_EC_PRIV = "-----BEGIN EC PRIVATE KEY-----"; + wcchar END_EC_PRIV = "-----END EC PRIVATE KEY-----"; +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + !defined(NO_DSA) + wcchar BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----"; + wcchar END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; +#endif +#ifdef OPENSSL_EXTRA + const char BEGIN_PRIV_KEY_PREFIX[] = "-----BEGIN"; + const char PRIV_KEY_SUFFIX[] = "PRIVATE KEY-----"; + const char END_PRIV_KEY_PREFIX[] = "-----END"; +#endif +wcchar BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----"; +wcchar END_PUB_KEY = "-----END PUBLIC KEY-----"; +#if defined(HAVE_ED25519) || defined(HAVE_ED448) + wcchar BEGIN_EDDSA_PRIV = "-----BEGIN EDDSA PRIVATE KEY-----"; + wcchar END_EDDSA_PRIV = "-----END EDDSA PRIVATE KEY-----"; +#endif +#ifdef HAVE_CRL + const char *const BEGIN_CRL = "-----BEGIN X509 CRL-----"; + wcchar END_CRL = "-----END X509 CRL-----"; +#endif + + +static WC_INLINE char* SkipEndOfLineChars(char* line, const char* endOfLine) +{ + /* eat end of line characters */ + while (line < endOfLine && + (line[0] == '\r' || line[0] == '\n')) { + line++; + } + return line; +} + +int wc_PemGetHeaderFooter(int type, const char** header, const char** footer) +{ + int ret = BAD_FUNC_ARG; + + switch (type) { + case CA_TYPE: /* same as below */ + case TRUSTED_PEER_TYPE: + case CERT_TYPE: + if (header) *header = BEGIN_CERT; + if (footer) *footer = END_CERT; + ret = 0; + break; + + case CRL_TYPE: + if (header) *header = BEGIN_X509_CRL; + if (footer) *footer = END_X509_CRL; + ret = 0; + break; + #ifndef NO_DH + case DH_PARAM_TYPE: + if (header) *header = BEGIN_DH_PARAM; + if (footer) *footer = END_DH_PARAM; + ret = 0; + break; + #endif + #ifndef NO_DSA + case DSA_PARAM_TYPE: + if (header) *header = BEGIN_DSA_PARAM; + if (footer) *footer = END_DSA_PARAM; + ret = 0; + break; + #endif + #ifdef WOLFSSL_CERT_REQ + case CERTREQ_TYPE: + if (header) *header = BEGIN_CERT_REQ; + if (footer) *footer = END_CERT_REQ; + ret = 0; + break; + #endif + #ifndef NO_DSA + case DSA_TYPE: + case DSA_PRIVATEKEY_TYPE: + if (header) *header = BEGIN_DSA_PRIV; + if (footer) *footer = END_DSA_PRIV; + ret = 0; + break; + #endif + #ifdef HAVE_ECC + case ECC_TYPE: + case ECC_PRIVATEKEY_TYPE: + if (header) *header = BEGIN_EC_PRIV; + if (footer) *footer = END_EC_PRIV; + ret = 0; + break; + #endif + case RSA_TYPE: + case PRIVATEKEY_TYPE: + if (header) *header = BEGIN_RSA_PRIV; + if (footer) *footer = END_RSA_PRIV; + ret = 0; + break; + #ifdef HAVE_ED25519 + case ED25519_TYPE: + #endif + #ifdef HAVE_ED448 + case ED448_TYPE: + #endif + #if defined(HAVE_ED25519) || defined(HAVE_ED448) + case EDDSA_PRIVATEKEY_TYPE: + if (header) *header = BEGIN_EDDSA_PRIV; + if (footer) *footer = END_EDDSA_PRIV; + ret = 0; + break; + #endif + case PUBLICKEY_TYPE: + case ECC_PUBLICKEY_TYPE: + if (header) *header = BEGIN_PUB_KEY; + if (footer) *footer = END_PUB_KEY; + ret = 0; + break; + #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) + case DH_PRIVATEKEY_TYPE: + #endif + case PKCS8_PRIVATEKEY_TYPE: + if (header) *header = BEGIN_PRIV_KEY; + if (footer) *footer = END_PRIV_KEY; + ret = 0; + break; + case PKCS8_ENC_PRIVATEKEY_TYPE: + if (header) *header = BEGIN_ENC_PRIV_KEY; + if (footer) *footer = END_ENC_PRIV_KEY; + ret = 0; + break; + default: + break; + } + return ret; +} + +#ifdef WOLFSSL_ENCRYPTED_KEYS + +static wcchar kProcTypeHeader = "Proc-Type"; +static wcchar kDecInfoHeader = "DEK-Info"; + +#ifdef WOLFSSL_PEM_TO_DER +#ifndef NO_DES3 + static wcchar kEncTypeDes = "DES-CBC"; + static wcchar kEncTypeDes3 = "DES-EDE3-CBC"; +#endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) + static wcchar kEncTypeAesCbc128 = "AES-128-CBC"; +#endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192) + static wcchar kEncTypeAesCbc192 = "AES-192-CBC"; +#endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) + static wcchar kEncTypeAesCbc256 = "AES-256-CBC"; +#endif + +int wc_EncryptedInfoGet(EncryptedInfo* info, const char* cipherInfo) +{ + int ret = 0; + + if (info == NULL || cipherInfo == NULL) + return BAD_FUNC_ARG; + + /* determine cipher information */ +#ifndef NO_DES3 + if (XSTRNCMP(cipherInfo, kEncTypeDes, XSTRLEN(kEncTypeDes)) == 0) { + info->cipherType = WC_CIPHER_DES; + info->keySz = DES_KEY_SIZE; + if (info->ivSz == 0) info->ivSz = DES_IV_SIZE; + } + else if (XSTRNCMP(cipherInfo, kEncTypeDes3, XSTRLEN(kEncTypeDes3)) == 0) { + info->cipherType = WC_CIPHER_DES3; + info->keySz = DES3_KEY_SIZE; + if (info->ivSz == 0) info->ivSz = DES_IV_SIZE; + } + else +#endif /* !NO_DES3 */ +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) + if (XSTRNCMP(cipherInfo, kEncTypeAesCbc128, XSTRLEN(kEncTypeAesCbc128)) == 0) { + info->cipherType = WC_CIPHER_AES_CBC; + info->keySz = AES_128_KEY_SIZE; + if (info->ivSz == 0) info->ivSz = AES_IV_SIZE; + } + else +#endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192) + if (XSTRNCMP(cipherInfo, kEncTypeAesCbc192, XSTRLEN(kEncTypeAesCbc192)) == 0) { + info->cipherType = WC_CIPHER_AES_CBC; + info->keySz = AES_192_KEY_SIZE; + if (info->ivSz == 0) info->ivSz = AES_IV_SIZE; + } + else +#endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) + if (XSTRNCMP(cipherInfo, kEncTypeAesCbc256, XSTRLEN(kEncTypeAesCbc256)) == 0) { + info->cipherType = WC_CIPHER_AES_CBC; + info->keySz = AES_256_KEY_SIZE; + if (info->ivSz == 0) info->ivSz = AES_IV_SIZE; + } + else +#endif + { + ret = NOT_COMPILED_IN; + } + return ret; +} + +int wc_EncryptedInfoParse(EncryptedInfo* info, char** pBuffer, size_t bufSz) +{ + int err = 0; + char* bufferStart; + char* bufferEnd; + char* line; + word32 lineSz; + char* finish; + word32 finishSz; + char* start = NULL; + word32 startSz; + char* newline = NULL; + + if (info == NULL || pBuffer == NULL || bufSz == 0) + return BAD_FUNC_ARG; + + bufferStart = *pBuffer; + bufferEnd = bufferStart + bufSz; + + /* find encrypted info marker */ + line = XSTRNSTR(bufferStart, kProcTypeHeader, + min((word32)bufSz, PEM_LINE_LEN)); + if (line != NULL) { + if (line >= bufferEnd) { + return BUFFER_E; + } + + lineSz = (word32)(bufferEnd - line); + + /* find DEC-Info marker */ + start = XSTRNSTR(line, kDecInfoHeader, min(lineSz, PEM_LINE_LEN)); + + if (start == NULL) + return BUFFER_E; + + /* skip dec-info and ": " */ + start += XSTRLEN(kDecInfoHeader); + if (start >= bufferEnd) + return BUFFER_E; + + if (start[0] == ':') { + start++; + if (start >= bufferEnd) + return BUFFER_E; + } + if (start[0] == ' ') + start++; + + startSz = (word32)(bufferEnd - start); + finish = XSTRNSTR(start, ",", min(startSz, PEM_LINE_LEN)); + + if ((start != NULL) && (finish != NULL) && (start < finish)) { + if (finish >= bufferEnd) { + return BUFFER_E; + } + + finishSz = (word32)(bufferEnd - finish); + newline = XSTRNSTR(finish, "\r", min(finishSz, PEM_LINE_LEN)); + + /* get cipher name */ + if (NAME_SZ < (finish - start)) /* buffer size of info->name */ + return BUFFER_E; + if (XMEMCPY(info->name, start, finish - start) == NULL) + return BUFFER_E; + info->name[finish - start] = '\0'; /* null term */ + + /* populate info */ + err = wc_EncryptedInfoGet(info, info->name); + if (err != 0) + return err; + + /* get IV */ + if (finishSz < info->ivSz + 1) + return BUFFER_E; + + if (newline == NULL) { + newline = XSTRNSTR(finish, "\n", min(finishSz, + PEM_LINE_LEN)); + } + if ((newline != NULL) && (newline > finish)) { + finish++; + info->ivSz = (word32)(newline - finish); + if (info->ivSz > IV_SZ) + return BUFFER_E; + if (XMEMCPY(info->iv, finish, info->ivSz) == NULL) + return BUFFER_E; + info->set = 1; + } + else + return BUFFER_E; + } + else + return BUFFER_E; + + /* eat end of line characters */ + newline = SkipEndOfLineChars(newline, bufferEnd); + + /* return new headerEnd */ + + *pBuffer = newline; + } + + return err; +} +#endif /* WOLFSSL_PEM_TO_DER */ + +#ifdef WOLFSSL_DER_TO_PEM +static int wc_EncryptedInfoAppend(char* dest, int destSz, char* cipherInfo) +{ + if (cipherInfo != NULL) { + int cipherInfoStrLen = (int)XSTRLEN((char*)cipherInfo); + + if (cipherInfoStrLen > HEADER_ENCRYPTED_KEY_SIZE - (9+14+10+3)) + cipherInfoStrLen = HEADER_ENCRYPTED_KEY_SIZE - (9+14+10+3); + + if (destSz - (int)XSTRLEN(dest) >= cipherInfoStrLen + (9+14+8+2+2+1)) { + /* strncat's src length needs to include the NULL */ + XSTRNCAT(dest, kProcTypeHeader, 10); + XSTRNCAT(dest, ": 4,ENCRYPTED\n", 15); + XSTRNCAT(dest, kDecInfoHeader, 9); + XSTRNCAT(dest, ": ", 3); + XSTRNCAT(dest, cipherInfo, destSz - (int)XSTRLEN(dest) - 1); + XSTRNCAT(dest, "\n\n", 4); + } + } + return 0; +} +#endif /* WOLFSSL_DER_TO_PEM */ +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + +#ifdef WOLFSSL_DER_TO_PEM + +/* Used for compatibility API */ +int wc_DerToPem(const byte* der, word32 derSz, + byte* output, word32 outSz, int type) +{ + return wc_DerToPemEx(der, derSz, output, outSz, NULL, type); +} /* convert der buffer to pem into output, can't do inplace, der and output need to be different */ -int wc_DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz, - int type) +int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, + byte *cipher_info, int type) { + const char* headerStr = NULL; + const char* footerStr = NULL; #ifdef WOLFSSL_SMALL_STACK char* header = NULL; char* footer = NULL; #else - char header[80]; - char footer[80]; + char header[MAX_X509_HEADER_SZ + HEADER_ENCRYPTED_KEY_SIZE]; + char footer[MAX_X509_HEADER_SZ]; #endif - - int headerLen = 80; - int footerLen = 80; + int headerLen = MAX_X509_HEADER_SZ + HEADER_ENCRYPTED_KEY_SIZE; + int footerLen = MAX_X509_HEADER_SZ; int i; int err; int outLen; /* return length or error */ + (void)cipher_info; + if (der == output) /* no in place conversion */ return BAD_FUNC_ARG; + err = wc_PemGetHeaderFooter(type, &headerStr, &footerStr); + if (err != 0) + return err; + #ifdef WOLFSSL_SMALL_STACK header = (char*)XMALLOC(headerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (header == NULL) return MEMORY_E; - + footer = (char*)XMALLOC(footerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (footer == NULL) { XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -4573,39 +10209,44 @@ int wc_DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz, } #endif - if (type == CERT_TYPE) { - XSTRNCPY(header, "-----BEGIN CERTIFICATE-----\n", headerLen); - XSTRNCPY(footer, "-----END CERTIFICATE-----\n", footerLen); - } - else if (type == PRIVATEKEY_TYPE) { - XSTRNCPY(header, "-----BEGIN RSA PRIVATE KEY-----\n", headerLen); - XSTRNCPY(footer, "-----END RSA PRIVATE KEY-----\n", footerLen); - } - #ifdef HAVE_ECC - else if (type == ECC_PRIVATEKEY_TYPE) { - XSTRNCPY(header, "-----BEGIN EC PRIVATE KEY-----\n", headerLen); - XSTRNCPY(footer, "-----END EC PRIVATE KEY-----\n", footerLen); - } + /* build header and footer based on type */ + XSTRNCPY(header, headerStr, headerLen - 1); + header[headerLen - 2] = 0; + XSTRNCPY(footer, footerStr, footerLen - 1); + footer[footerLen - 2] = 0; + + /* add new line to end */ + XSTRNCAT(header, "\n", 2); + XSTRNCAT(footer, "\n", 2); + +#ifdef WOLFSSL_ENCRYPTED_KEYS + err = wc_EncryptedInfoAppend(header, headerLen, (char*)cipher_info); + if (err != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - #ifdef WOLFSSL_CERT_REQ - else if (type == CERTREQ_TYPE) - { - XSTRNCPY(header, - "-----BEGIN CERTIFICATE REQUEST-----\n", headerLen); - XSTRNCPY(footer, "-----END CERTIFICATE REQUEST-----\n", footerLen); + return err; } - #endif - else { +#endif + + headerLen = (int)XSTRLEN(header); + footerLen = (int)XSTRLEN(footer); + + /* if null output and 0 size passed in then return size needed */ + if (!output && outSz == 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return BAD_FUNC_ARG; + outLen = 0; + if ((err = Base64_Encode(der, derSz, NULL, (word32*)&outLen)) + != LENGTH_ONLY_E) { + return err; + } + return headerLen + footerLen + outLen; } - headerLen = (int)XSTRLEN(header); - footerLen = (int)XSTRLEN(footer); - if (!der || !output) { #ifdef WOLFSSL_SMALL_STACK XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -4657,12 +10298,846 @@ int wc_DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz, return outLen + headerLen + footerLen; } +#endif /* WOLFSSL_DER_TO_PEM */ -#endif /* WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN */ +#ifdef WOLFSSL_PEM_TO_DER + +/* Remove PEM header/footer, convert to ASN1, store any encrypted data + info->consumed tracks of PEM bytes consumed in case multiple parts */ +int PemToDer(const unsigned char* buff, long longSz, int type, + DerBuffer** pDer, void* heap, EncryptedInfo* info, int* keyFormat) +{ + const char* header = NULL; + const char* footer = NULL; + char* headerEnd; + char* footerEnd; + char* consumedEnd; + char* bufferEnd = (char*)(buff + longSz); + long neededSz; + int ret = 0; + int sz = (int)longSz; + int encrypted_key = 0; + DerBuffer* der; +#if defined(HAVE_PKCS8) || defined(WOLFSSL_ENCRYPTED_KEYS) + word32 algId = 0; + #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_DES3) && !defined(NO_WOLFSSL_SKIP_TRAILING_PAD) + int padVal = 0; + #endif +#endif +#ifdef OPENSSL_EXTRA + char beginBuf[PEM_LINE_LEN + 1]; /* add 1 for null terminator */ + char endBuf[PEM_LINE_LEN + 1]; /* add 1 for null terminator */ +#endif + + WOLFSSL_ENTER("PemToDer"); + + /* get PEM header and footer based on type */ + ret = wc_PemGetHeaderFooter(type, &header, &footer); + if (ret != 0) + return ret; + + /* map header if not found for type */ + for (;;) { + headerEnd = XSTRNSTR((char*)buff, header, sz); + + if (headerEnd) { + break; + } else + if (type == PRIVATEKEY_TYPE) { + if (header == BEGIN_RSA_PRIV) { + header = BEGIN_PRIV_KEY; footer = END_PRIV_KEY; + } else + if (header == BEGIN_PRIV_KEY) { + header = BEGIN_ENC_PRIV_KEY; footer = END_ENC_PRIV_KEY; + } else + #ifdef HAVE_ECC + if (header == BEGIN_ENC_PRIV_KEY) { + header = BEGIN_EC_PRIV; footer = END_EC_PRIV; + } else + if (header == BEGIN_EC_PRIV) { + header = BEGIN_DSA_PRIV; footer = END_DSA_PRIV; + } else + #endif + #if defined(HAVE_ED25519) || defined(HAVE_ED448) + #ifdef HAVE_ECC + if (header == BEGIN_DSA_PRIV) + #else + if (header == BEGIN_ENC_PRIV_KEY) + #endif + { + header = BEGIN_EDDSA_PRIV; footer = END_EDDSA_PRIV; + } else + #endif + { + break; + } + } else +#ifdef HAVE_CRL + if ((type == CRL_TYPE) && (header != BEGIN_CRL)) { + header = BEGIN_CRL; footer = END_CRL; + } else +#endif + { + break; + } + } + + if (!headerEnd) { +#ifdef OPENSSL_EXTRA + char* beginEnd; + int endLen; + /* see if there is a -----BEGIN * PRIVATE KEY----- header */ + headerEnd = XSTRNSTR((char*)buff, PRIV_KEY_SUFFIX, sz); + if (headerEnd) { + beginEnd = headerEnd + XSTR_SIZEOF(PRIV_KEY_SUFFIX); + /* back up to BEGIN_PRIV_KEY_PREFIX */ + headerEnd -= XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX); + while (headerEnd > (char*)buff && + XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX, + XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0) { + headerEnd--; + } + if (headerEnd <= (char*)buff || + XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX, + XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0 || + beginEnd - headerEnd > PEM_LINE_LEN) { + WOLFSSL_MSG("Couldn't find PEM header"); + return ASN_NO_PEM_HEADER; + } + /* headerEnd now points to beginning of header */ + XMEMCPY(beginBuf, headerEnd, beginEnd - headerEnd); + beginBuf[beginEnd - headerEnd] = '\0'; + /* look for matching footer */ + footer = XSTRNSTR(beginEnd, + beginBuf + XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX), + (unsigned int)((char*)buff + sz - beginEnd)); + if (!footer) { + WOLFSSL_MSG("Couldn't find PEM footer"); + return ASN_NO_PEM_HEADER; + } + footer -= XSTR_SIZEOF(END_PRIV_KEY_PREFIX); + endLen = (unsigned int)(beginEnd - headerEnd - + (XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX) - + XSTR_SIZEOF(END_PRIV_KEY_PREFIX))); + XMEMCPY(endBuf, footer, endLen); + endBuf[endLen] = '\0'; + + header = beginBuf; + footer = endBuf; + headerEnd = beginEnd; + } else { + WOLFSSL_MSG("Couldn't find PEM header"); + return ASN_NO_PEM_HEADER; + } +#else + WOLFSSL_MSG("Couldn't find PEM header"); + return ASN_NO_PEM_HEADER; +#endif + } else { + headerEnd += XSTRLEN(header); + } + + /* eat end of line characters */ + headerEnd = SkipEndOfLineChars(headerEnd, bufferEnd); + + if (type == PRIVATEKEY_TYPE) { + /* keyFormat is Key_Sum enum */ + if (keyFormat) { + #ifdef HAVE_ECC + if (header == BEGIN_EC_PRIV) + *keyFormat = ECDSAk; + #endif + #if !defined(NO_DSA) + if (header == BEGIN_DSA_PRIV) + *keyFormat = DSAk; + #endif + } + } + +#ifdef WOLFSSL_ENCRYPTED_KEYS + if (info) { + ret = wc_EncryptedInfoParse(info, &headerEnd, bufferEnd - headerEnd); + if (ret < 0) + return ret; + if (info->set) + encrypted_key = 1; + } +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + + /* find footer */ + footerEnd = XSTRNSTR(headerEnd, footer, (unsigned int)((char*)buff + sz - headerEnd)); + if (!footerEnd) { + if (info) + info->consumed = longSz; /* No more certs if no footer */ + return BUFFER_E; + } + + consumedEnd = footerEnd + XSTRLEN(footer); + + if (consumedEnd < bufferEnd) { /* handle no end of line on last line */ + /* eat end of line characters */ + consumedEnd = SkipEndOfLineChars(consumedEnd, bufferEnd); + /* skip possible null term */ + if (consumedEnd < bufferEnd && consumedEnd[0] == '\0') + consumedEnd++; + } + + if (info) + info->consumed = (long)(consumedEnd - (char*)buff); + + /* set up der buffer */ + neededSz = (long)(footerEnd - headerEnd); + if (neededSz > sz || neededSz <= 0) + return BUFFER_E; + + ret = AllocDer(pDer, (word32)neededSz, type, heap); + if (ret < 0) { + return ret; + } + der = *pDer; + + if (Base64_Decode((byte*)headerEnd, (word32)neededSz, + der->buffer, &der->length) < 0) + return BUFFER_E; + + if ((header == BEGIN_PRIV_KEY +#ifdef OPENSSL_EXTRA + || header == beginBuf +#endif +#ifdef HAVE_ECC + || header == BEGIN_EC_PRIV +#endif + ) && !encrypted_key) + { + #ifdef HAVE_PKCS8 + /* pkcs8 key, convert and adjust length */ + if ((ret = ToTraditional_ex(der->buffer, der->length, &algId)) > 0) { + der->length = ret; + if (keyFormat) { + *keyFormat = algId; + } + } + else { + /* ignore failure here and assume key is not pkcs8 wrapped */ + } + #endif + + return 0; + } + +#ifdef WOLFSSL_ENCRYPTED_KEYS + if (encrypted_key || header == BEGIN_ENC_PRIV_KEY) { + int passwordSz = NAME_SZ; + #ifdef WOLFSSL_SMALL_STACK + char* password = NULL; + #else + char password[NAME_SZ]; + #endif + + if (!info || !info->passwd_cb) { + WOLFSSL_MSG("No password callback set"); + return NO_PASSWORD; + } + + #ifdef WOLFSSL_SMALL_STACK + password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING); + if (password == NULL) + return MEMORY_E; + #endif + + /* get password */ + ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ, + info->passwd_userdata); + if (ret >= 0) { + passwordSz = ret; + + /* convert and adjust length */ + if (header == BEGIN_ENC_PRIV_KEY) { + #ifndef NO_PWDBASED + ret = ToTraditionalEnc(der->buffer, der->length, + password, passwordSz, &algId); + + if (ret >= 0) { + der->length = ret; + if (keyFormat) { + *keyFormat = algId; + } + ret = 0; + } + #else + ret = NOT_COMPILED_IN; + #endif + } + /* decrypt the key */ + else { + if (passwordSz == 0) { + /* The key is encrypted but does not have a password */ + WOLFSSL_MSG("No password for encrypted key"); + ret = NO_PASSWORD; + } + else { + ret = wc_BufferKeyDecrypt(info, der->buffer, der->length, + (byte*)password, passwordSz, WC_MD5); + +#ifndef NO_WOLFSSL_SKIP_TRAILING_PAD + #ifndef NO_DES3 + if (info->cipherType == WC_CIPHER_DES3) { + padVal = der->buffer[der->length-1]; + if (padVal <= DES_BLOCK_SIZE) { + der->length -= padVal; + } + } + #endif /* !NO_DES3 */ +#endif /* !NO_WOLFSSL_SKIP_TRAILING_PAD */ + } + } +#ifdef OPENSSL_EXTRA + if (ret) { + PEMerr(0, PEM_R_BAD_DECRYPT); + } +#endif + ForceZero(password, passwordSz); + } +#ifdef OPENSSL_EXTRA + else { + PEMerr(0, PEM_R_BAD_PASSWORD_READ); + } +#endif + + #ifdef WOLFSSL_SMALL_STACK + XFREE(password, heap, DYNAMIC_TYPE_STRING); + #endif + } +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + + return ret; +} + +int wc_PemToDer(const unsigned char* buff, long longSz, int type, + DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey) +{ + return PemToDer(buff, longSz, type, pDer, heap, info, eccKey); +} -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) +/* our KeyPemToDer password callback, password in userData */ +static WC_INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata) +{ + (void)rw; + if (userdata == NULL) + return 0; + + XSTRNCPY(passwd, (char*)userdata, sz); + return min((word32)sz, (word32)XSTRLEN((char*)userdata)); +} + +/* Return bytes written to buff or < 0 for error */ +int wc_KeyPemToDer(const unsigned char* pem, int pemSz, + unsigned char* buff, int buffSz, const char* pass) +{ + int eccKey = 0; + int ret; + DerBuffer* der = NULL; +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; +#else + EncryptedInfo info[1]; +#endif + + WOLFSSL_ENTER("wc_KeyPemToDer"); + + if (pem == NULL || buff == NULL || buffSz <= 0) { + WOLFSSL_MSG("Bad pem der args"); + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_ENCRYPTEDINFO); + if (info == NULL) + return MEMORY_E; +#endif + + XMEMSET(info, 0, sizeof(EncryptedInfo)); + info->passwd_cb = OurPasswordCb; + info->passwd_userdata = (void*)pass; + + ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, info, &eccKey); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); +#endif + + if (ret < 0 || der == NULL) { + 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; +} + + +/* Return bytes written to buff or < 0 for error */ +int wc_CertPemToDer(const unsigned char* pem, int pemSz, + unsigned char* buff, int buffSz, int type) +{ + int eccKey = 0; + int ret; + DerBuffer* der = NULL; + + WOLFSSL_ENTER("wc_CertPemToDer"); + + if (pem == NULL || buff == NULL || buffSz <= 0) { + WOLFSSL_MSG("Bad pem der args"); + return BAD_FUNC_ARG; + } + + if (type != CERT_TYPE && type != CA_TYPE && type != CERTREQ_TYPE) { + WOLFSSL_MSG("Bad cert type"); + return BAD_FUNC_ARG; + } + + + ret = PemToDer(pem, pemSz, type, &der, NULL, NULL, &eccKey); + if (ret < 0 || der == NULL) { + 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_PEM_TO_DER */ +#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ + + +#ifdef WOLFSSL_PEM_TO_DER +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER) +/* Return bytes written to buff or < 0 for error */ +int wc_PubKeyPemToDer(const unsigned char* pem, int pemSz, + unsigned char* buff, int buffSz) +{ + int ret; + DerBuffer* der = NULL; + + WOLFSSL_ENTER("wc_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 || der == NULL) { + 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 */ +#endif /* WOLFSSL_PEM_TO_DER */ + +#ifndef NO_FILESYSTEM + +#ifdef WOLFSSL_CERT_GEN +/* load pem cert from file into der buffer, return der size or error */ +int wc_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) +{ +#ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force XMALLOC */ +#else + byte staticBuffer[FILE_BUFFER_SIZE]; +#endif + byte* fileBuf = staticBuffer; + int dynamic = 0; + int ret = 0; + long sz = 0; + XFILE file; + DerBuffer* converted = NULL; + + WOLFSSL_ENTER("wc_PemCertToDer"); + + if (fileName == NULL) { + ret = BAD_FUNC_ARG; + } + else { + file = XFOPEN(fileName, "rb"); + if (file == XBADFILE) { + ret = BUFFER_E; + } + } + + if (ret == 0) { + if(XFSEEK(file, 0, XSEEK_END) != 0) + ret = BUFFER_E; + sz = XFTELL(file); + XREWIND(file); + + if (sz <= 0) { + ret = BUFFER_E; + } + else if (sz > (long)sizeof(staticBuffer)) { + #ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MSG("File was larger then static buffer"); + return MEMORY_E; + #endif + fileBuf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); + if (fileBuf == NULL) + ret = MEMORY_E; + else + dynamic = 1; + } + + if (ret == 0) { + if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) { + ret = BUFFER_E; + } + #ifdef WOLFSSL_PEM_TO_DER + else { + ret = PemToDer(fileBuf, sz, CA_TYPE, &converted, 0, NULL,NULL); + } + #endif + + if (ret == 0) { + if (converted->length < (word32)derSz) { + XMEMCPY(derBuf, converted->buffer, converted->length); + ret = converted->length; + } + else + ret = BUFFER_E; + } + + FreeDer(&converted); + } + + XFCLOSE(file); + if (dynamic) + XFREE(fileBuf, NULL, DYNAMIC_TYPE_FILE); + } + + return ret; +} +#endif /* WOLFSSL_CERT_GEN */ + +#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 wc_PemPubKeyToDer(const char* fileName, + unsigned char* derBuf, int derSz) +{ +#ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force XMALLOC */ +#else + byte staticBuffer[FILE_BUFFER_SIZE]; +#endif + byte* fileBuf = staticBuffer; + int dynamic = 0; + int ret = 0; + long sz = 0; + XFILE file; + DerBuffer* converted = NULL; + + WOLFSSL_ENTER("wc_PemPubKeyToDer"); + + if (fileName == NULL) { + ret = BAD_FUNC_ARG; + } + else { + file = XFOPEN(fileName, "rb"); + if (file == XBADFILE) { + ret = BUFFER_E; + } + } + + if (ret == 0) { + if(XFSEEK(file, 0, XSEEK_END) != 0) + ret = BUFFER_E; + sz = XFTELL(file); + XREWIND(file); + + if (sz <= 0) { + ret = BUFFER_E; + } + else if (sz > (long)sizeof(staticBuffer)) { + #ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MSG("File was larger then static buffer"); + return MEMORY_E; + #endif + fileBuf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); + if (fileBuf == NULL) + ret = MEMORY_E; + else + dynamic = 1; + } + if (ret == 0) { + if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) { + ret = BUFFER_E; + } + #ifdef WOLFSSL_PEM_TO_DER + else { + ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted, + 0, NULL, NULL); + } + #endif + + if (ret == 0) { + if (converted->length < (word32)derSz) { + XMEMCPY(derBuf, converted->buffer, converted->length); + ret = converted->length; + } + else + ret = BUFFER_E; + } + + FreeDer(&converted); + } + + XFCLOSE(file); + if (dynamic) + XFREE(fileBuf, NULL, DYNAMIC_TYPE_FILE); + } + + return ret; +} +#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */ + +#endif /* !NO_FILESYSTEM */ + + +#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || \ + ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !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 */ +static int SetRsaPublicKey(byte* output, RsaKey* key, + int outLen, int with_header) +{ +#ifdef WOLFSSL_SMALL_STACK + byte* n = NULL; + byte* e = NULL; +#else + byte n[MAX_RSA_INT_SZ]; + byte e[MAX_RSA_E_SZ]; +#endif + byte seq[MAX_SEQ_SZ]; + byte bitString[1 + MAX_LENGTH_SZ + 1]; + int nSz; + int eSz; + int seqSz; + int bitStringSz; + int idx; + + if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) + return BAD_FUNC_ARG; + + /* n */ +#ifdef WOLFSSL_SMALL_STACK + n = (byte*)XMALLOC(MAX_RSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (n == NULL) + return MEMORY_E; +#endif + +#ifdef HAVE_USER_RSA + nSz = SetASNIntRSA(key->n, n); +#else + nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, n); +#endif + if (nSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return nSz; + } + + /* e */ +#ifdef WOLFSSL_SMALL_STACK + e = (byte*)XMALLOC(MAX_RSA_E_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (e == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } +#endif + +#ifdef HAVE_USER_RSA + eSz = SetASNIntRSA(key->e, e); +#else + eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, e); +#endif + if (eSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return eSz; + } + + seqSz = SetSequence(nSz + eSz, seq); + + /* check output size */ + if ( (seqSz + nSz + eSz) > outLen) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BUFFER_E; + } + + /* headers */ + if (with_header) { + int algoSz; +#ifdef WOLFSSL_SMALL_STACK + byte* algo; + + algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#else + byte algo[MAX_ALGO_SZ]; +#endif + algoSz = SetAlgoID(RSAk, algo, oidKeyType, 0); + bitStringSz = SetBitString(seqSz + nSz + eSz, 0, bitString); + + idx = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, output); + + /* check output size */ + if ( (idx + algoSz + bitStringSz + seqSz + nSz + eSz) > outLen) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return BUFFER_E; + } + + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* bit string */ + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; +#ifdef WOLFSSL_SMALL_STACK + XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } + else + idx = 0; + + /* seq */ + XMEMCPY(output + idx, seq, seqSz); + idx += seqSz; + /* n */ + XMEMCPY(output + idx, n, nSz); + idx += nSz; + /* e */ + XMEMCPY(output + idx, e, eSz); + idx += eSz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + +#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN && + !HAVE_USER_RSA))) */ + +#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA)) +int wc_RsaPublicKeyDerSize(RsaKey* key, int with_header) +{ + int idx = 0; + int nSz, eSz, seqSz, bitStringSz, algoSz; + + if (key == NULL) + return BAD_FUNC_ARG; + + /* n */ +#ifdef HAVE_USER_RSA + nSz = SetASNIntRSA(key->n, NULL); +#else + nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, NULL); +#endif + if (nSz < 0) { + return nSz; + } + + /* e */ +#ifdef HAVE_USER_RSA + eSz = SetASNIntRSA(key->e, NULL); +#else + eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, NULL); +#endif + if (eSz < 0) { + return eSz; + } + + seqSz = SetSequence(nSz + eSz, NULL); + + /* headers */ + if (with_header) { + algoSz = SetAlgoID(RSAk, NULL, oidKeyType, 0); + bitStringSz = SetBitString(seqSz + nSz + eSz, 0, NULL); + + idx += SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, NULL); + + /* algo */ + idx += algoSz; + /* bit string */ + idx += bitStringSz; + } + + /* seq */ + idx += seqSz; + /* n */ + idx += nSz; + /* e */ + idx += eSz; + + return idx; +} + +#endif /* !NO_RSA && WOLFSSL_CERT_GEN */ + + +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) static mp_int* GetRsaInt(RsaKey* key, int idx) { @@ -4688,13 +11163,13 @@ static mp_int* GetRsaInt(RsaKey* key, int idx) /* Release Tmp RSA resources */ -static INLINE void FreeTmpRsas(byte** tmps, void* heap) +static WC_INLINE void FreeTmpRsas(byte** tmps, void* heap) { int i; (void)heap; - for (i = 0; i < RSA_INTS; i++) + for (i = 0; i < RSA_INTS; i++) XFREE(tmps[i], heap, DYNAMIC_TYPE_RSA); } @@ -4705,13 +11180,13 @@ 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; + int i, j, outLen, ret = 0, mpSz; byte seq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; byte* tmps[RSA_INTS]; - if (!key || !output) + if (!key) return BAD_FUNC_ARG; if (key->type != RSA_PRIVATE) @@ -4723,7 +11198,8 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) /* write all big ints from key to DER tmps */ for (i = 0; i < RSA_INTS; i++) { mp_int* keyInt = GetRsaInt(key, i); - rawLen = mp_unsigned_bin_size(keyInt); + + rawLen = mp_unsigned_bin_size(keyInt) + 1; tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, DYNAMIC_TYPE_RSA); if (tmps[i] == NULL) { @@ -4731,24 +11207,12 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) break; } - tmps[i][0] = ASN_INTEGER; - sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1; /* int tag */ - - if (sizes[i] <= MAX_SEQ_SZ) { - int err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]); - if (err == MP_OKAY) { - sizes[i] += 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) { @@ -4761,42 +11225,43 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) seqSz = SetSequence(verSz + intTotalLen, seq); outLen = seqSz + verSz + intTotalLen; - if (outLen > (int)inLen) - return BAD_FUNC_ARG; + if (output) { + if (outLen > (int)inLen) { + FreeTmpRsas(tmps, key->heap); + return BAD_FUNC_ARG; + } - /* write to output */ - XMEMCPY(output, seq, seqSz); - j = seqSz; - XMEMCPY(output + j, ver, verSz); - j += verSz; + /* write to output */ + XMEMCPY(output, seq, seqSz); + j = seqSz; + XMEMCPY(output + j, ver, verSz); + j += verSz; - for (i = 0; i < RSA_INTS; i++) { - XMEMCPY(output + j, tmps[i], sizes[i]); - j += sizes[i]; + for (i = 0; i < RSA_INTS; i++) { + XMEMCPY(output + j, tmps[i], sizes[i]); + j += sizes[i]; + } } FreeTmpRsas(tmps, key->heap); return outLen; } +#endif -#endif /* WOLFSSL_KEY_GEN && !NO_RSA */ +#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) +/* Convert Rsa Public key to DER format, write to output (inLen), return bytes + written */ +int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen) +{ + return SetRsaPublicKey(output, key, inLen, 1); +} + +#endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !NO_RSA && !HAVE_USER_RSA */ -#if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) +#ifdef WOLFSSL_CERT_GEN - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - -/* Initialize and Set Certficate defaults: +/* Initialize and Set Certificate defaults: version = 3 (0x2) serial = 0 sigType = SHA_WITH_RSA @@ -4805,57 +11270,57 @@ int wc_RsaKeyToDer(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) { +#ifdef WOLFSSL_MULTI_ATTRIB + int i = 0; +#endif + if (cert == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(cert, 0, sizeof(Cert)); + cert->version = 2; /* version 3 is hex 2 */ +#ifndef NO_SHA cert->sigType = CTC_SHAwRSA; +#elif !defined(NO_SHA256) + cert->sigType = CTC_SHA256wRSA; +#else + cert->sigType = 0; +#endif cert->daysValid = 500; cert->selfSigned = 1; - cert->isCA = 0; - cert->bodySz = 0; -#ifdef WOLFSSL_ALT_NAMES - cert->altNamesSz = 0; - cert->beforeDateSz = 0; - cert->afterDateSz = 0; -#endif cert->keyType = RSA_KEY; - XMEMSET(cert->serial, 0, CTC_SERIAL_SIZE); - cert->issuer.country[0] = '\0'; cert->issuer.countryEnc = CTC_PRINTABLE; - cert->issuer.state[0] = '\0'; cert->issuer.stateEnc = CTC_UTF8; - cert->issuer.locality[0] = '\0'; cert->issuer.localityEnc = CTC_UTF8; - cert->issuer.sur[0] = '\0'; cert->issuer.surEnc = CTC_UTF8; - cert->issuer.org[0] = '\0'; cert->issuer.orgEnc = CTC_UTF8; - cert->issuer.unit[0] = '\0'; cert->issuer.unitEnc = CTC_UTF8; - cert->issuer.commonName[0] = '\0'; cert->issuer.commonNameEnc = CTC_UTF8; - cert->issuer.email[0] = '\0'; - cert->subject.country[0] = '\0'; cert->subject.countryEnc = CTC_PRINTABLE; - cert->subject.state[0] = '\0'; cert->subject.stateEnc = CTC_UTF8; - cert->subject.locality[0] = '\0'; cert->subject.localityEnc = CTC_UTF8; - cert->subject.sur[0] = '\0'; cert->subject.surEnc = CTC_UTF8; - cert->subject.org[0] = '\0'; cert->subject.orgEnc = CTC_UTF8; - cert->subject.unit[0] = '\0'; cert->subject.unitEnc = CTC_UTF8; - cert->subject.commonName[0] = '\0'; cert->subject.commonNameEnc = CTC_UTF8; - cert->subject.email[0] = '\0'; -#ifdef WOLFSSL_CERT_REQ - cert->challengePw[0] ='\0'; +#ifdef WOLFSSL_MULTI_ATTRIB + for (i = 0; i < CTC_MAX_ATTRIB; i++) { + cert->issuer.name[i].type = CTC_UTF8; + cert->subject.name[i].type = CTC_UTF8; + } +#endif /* WOLFSSL_MULTI_ATTRIB */ + +#ifdef WOLFSSL_HEAP_TEST + cert->heap = (void*)WOLFSSL_HEAP_TEST; #endif + + return 0; } @@ -4863,26 +11328,46 @@ void wc_InitCert(Cert* cert) typedef struct DerCert { byte size[MAX_LENGTH_SZ]; /* length encoded */ byte version[MAX_VERSION_SZ]; /* version encoded */ - byte serial[CTC_SERIAL_SIZE + MAX_LENGTH_SZ]; /* serial number encoded */ + byte serial[(int)CTC_SERIAL_SIZE + (int)MAX_LENGTH_SZ]; /* serial number encoded */ byte sigAlgo[MAX_ALGO_SZ]; /* signature algo encoded */ byte issuer[ASN_NAME_MAX]; /* issuer encoded */ byte subject[ASN_NAME_MAX]; /* subject encoded */ byte validity[MAX_DATE_SIZE*2 + MAX_SEQ_SZ*2]; /* before and after dates */ byte publicKey[MAX_PUBLIC_KEY_SZ]; /* rsa / ntru public key encoded */ byte ca[MAX_CA_SZ]; /* basic constraint CA true size */ - byte extensions[MAX_EXTENSIONS_SZ]; /* all extensions */ + byte extensions[MAX_EXTENSIONS_SZ]; /* all extensions */ +#ifdef WOLFSSL_CERT_EXT + 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 byte attrib[MAX_ATTRIB_SZ]; /* Cert req attributes encoded */ +#endif +#ifdef WOLFSSL_ALT_NAMES + byte altNames[CTC_MAX_ALT_SIZE]; /* Alternative Names encoded */ #endif int sizeSz; /* encoded size length */ int versionSz; /* encoded version length */ int serialSz; /* encoded serial length */ - int sigAlgoSz; /* enocded sig alog length */ + int sigAlgoSz; /* encoded sig algo length */ int issuerSz; /* encoded issuer length */ int subjectSz; /* encoded subject length */ int validitySz; /* encoded validity length */ int publicKeySz; /* encoded public key length */ int caSz; /* encoded CA extension length */ +#ifdef WOLFSSL_CERT_EXT + 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 + int altNamesSz; /* encoded AltNames extension length */ +#endif int extensionsSz; /* encoded extensions total length */ int total; /* total encoded lengths */ #ifdef WOLFSSL_CERT_REQ @@ -4894,6 +11379,12 @@ typedef struct DerCert { #ifdef WOLFSSL_CERT_REQ /* Write a set header to output */ +static word32 SetPrintableString(word32 len, byte* output) +{ + output[0] = ASN_PRINTABLE_STRING; + return SetLength(len, output + 1) + 1; +} + static word32 SetUTF8String(word32 len, byte* output) { output[0] = ASN_UTF8STRING; @@ -4903,40 +11394,249 @@ static word32 SetUTF8String(word32 len, byte* output) #endif /* WOLFSSL_CERT_REQ */ -/* Write a serial number to output */ -static int SetSerial(const byte* serial, byte* output) +#ifndef WOLFSSL_CERT_GEN_CACHE +/* wc_SetCert_Free is only public when WOLFSSL_CERT_GEN_CACHE is not defined */ +static +#endif +void wc_SetCert_Free(Cert* cert) { - int length = 0; + if (cert != NULL) { + cert->der = NULL; + if (cert->decodedCert) { + FreeDecodedCert((DecodedCert*)cert->decodedCert); - output[length++] = ASN_INTEGER; - length += SetLength(CTC_SERIAL_SIZE, &output[length]); - XMEMCPY(&output[length], serial, CTC_SERIAL_SIZE); - - return length + CTC_SERIAL_SIZE; + XFREE(cert->decodedCert, cert->heap, DYNAMIC_TYPE_DCERT); + cert->decodedCert = NULL; + } + } } +static int wc_SetCert_LoadDer(Cert* cert, const byte* der, word32 derSz) +{ + int ret; -#ifdef HAVE_ECC + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Allocate DecodedCert struct and Zero */ + cert->decodedCert = (void*)XMALLOC(sizeof(DecodedCert), cert->heap, + DYNAMIC_TYPE_DCERT); + if (cert->decodedCert == NULL) { + ret = MEMORY_E; + } + else { + XMEMSET(cert->decodedCert, 0, sizeof(DecodedCert)); + + InitDecodedCert((DecodedCert*)cert->decodedCert, der, derSz, + cert->heap); + ret = ParseCertRelative((DecodedCert*)cert->decodedCert, + CERT_TYPE, 0, NULL); + if (ret >= 0) { + cert->der = (byte*)der; + } + else { + wc_SetCert_Free(cert); + } + } + } + + return ret; +} + +#endif /* WOLFSSL_CERT_GEN */ + + +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) /* Write a public ECC key to output */ -static int SetEccPublicKey(byte* output, ecc_key* key) +static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) { - byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */ + 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 byte* algo = NULL; byte* curve = NULL; - byte* pub = NULL; + byte* pub; #else byte algo[MAX_ALGO_SZ]; byte curve[MAX_ALGO_SZ]; byte pub[ECC_BUFSIZE]; #endif + int ret; + +#ifdef WOLFSSL_SMALL_STACK + pub = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) + return MEMORY_E; +#endif + +#ifdef HAVE_SELFTEST + /* older version of ecc.c can not handle dp being NULL */ + if (key != NULL && key->dp == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_ecc_export_x963(key, pub, &pubSz); + } +#else + ret = wc_ecc_export_x963(key, pub, &pubSz); +#endif + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* headers */ + if (with_header) { +#ifdef WOLFSSL_SMALL_STACK + curve = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (curve == NULL) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + curveSz = SetCurve(key, curve); + if (curveSz <= 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return curveSz; + } + +#ifdef WOLFSSL_SMALL_STACK + algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + algoSz = SetAlgoID(ECDSAk, algo, oidKeyType, curveSz); + + bitStringSz = SetBitString(pubSz, 0, bitString); + + idx = SetSequence(pubSz + curveSz + bitStringSz + algoSz, output); + /* algo */ + if (output) + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* curve */ + if (output) + XMEMCPY(output + idx, curve, curveSz); + idx += curveSz; + /* bit string */ + if (output) + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; + } + else + idx = 0; + + /* pub */ + if (output) + XMEMCPY(output + idx, pub, pubSz); + idx += pubSz; + +#ifdef WOLFSSL_SMALL_STACK + if (with_header) { + XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + + +/* returns the size of buffer used, the public ECC key in DER format is stored + in output buffer + with_AlgCurve is a flag for when to include a header that has the Algorithm + and Curve information */ +int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen, + int with_AlgCurve) +{ + word32 infoSz = 0; + word32 keySz = 0; + int ret; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (with_AlgCurve) { + /* buffer space for algorithm/curve */ + infoSz += MAX_SEQ_SZ; + infoSz += 2 * MAX_ALGO_SZ; + + /* buffer space for public key sequence */ + infoSz += MAX_SEQ_SZ; + infoSz += TRAILING_ZERO; + } + +#ifdef HAVE_SELFTEST + /* older version of ecc.c can not handle dp being NULL */ + if (key != NULL && key->dp == NULL) { + keySz = 1 + 2 * MAX_ECC_BYTES; + ret = LENGTH_ONLY_E; + } + else { + ret = wc_ecc_export_x963(key, NULL, &keySz); + } +#else + ret = wc_ecc_export_x963(key, NULL, &keySz); +#endif + if (ret != LENGTH_ONLY_E) { + WOLFSSL_MSG("Error in getting ECC public key size"); + return ret; + } + + /* if output null then just return size */ + if (output == NULL) { + return keySz + infoSz; + } + + if (inLen < keySz + infoSz) { + return BUFFER_E; + } + + return SetEccPublicKey(output, key, with_AlgCurve); +} + +int wc_EccPublicKeyDerSize(ecc_key* key, int with_AlgCurve) +{ + return wc_EccPublicKeyToDer(key, NULL, 0, with_AlgCurve); +} + +#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */ + +#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; +#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); @@ -4944,217 +11644,194 @@ static int SetEccPublicKey(byte* output, ecc_key* key) return MEMORY_E; #endif - int ret = wc_ecc_export_x963(key, pub, &pubSz); - if (ret != 0) { + idx = wc_ed25519_export_public(key, pub, &pubSz); + if (idx != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return ret; + return idx; } -#ifdef WOLFSSL_SMALL_STACK - curve = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (curve == NULL) { - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - /* headers */ - curveSz = SetCurve(key, curve); - if (curveSz <= 0) { + if (with_header) { #ifdef WOLFSSL_SMALL_STACK - XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } #endif - return curveSz; + 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; -#ifdef WOLFSSL_SMALL_STACK - algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (algo == NULL) { - XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - algoSz = SetAlgoID(ECDSAk, algo, keyType, curveSz); - lenSz = SetLength(pubSz + 1, len); - len[lenSz++] = 0; /* trailing 0 */ - - /* write */ - idx = SetSequence(pubSz + curveSz + lenSz + 1 + algoSz, output); - /* 1 is for ASN_BIT_STRING */ - /* algo */ - XMEMCPY(output + idx, algo, algoSz); - idx += algoSz; - /* curve */ - XMEMCPY(output + idx, curve, curveSz); - idx += curveSz; - /* bit string */ - output[idx++] = ASN_BIT_STRING; - /* length */ - XMEMCPY(output + idx, len, lenSz); - idx += lenSz; /* pub */ XMEMCPY(output + idx, pub, pubSz); idx += pubSz; #ifdef WOLFSSL_SMALL_STACK - XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (with_header) { + XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return idx; } - -#endif /* HAVE_ECC */ - - -/* Write a public RSA key to output */ -static int SetRsaPublicKey(byte* output, RsaKey* key) +int wc_Ed25519PublicKeyToDer(ed25519_key* key, byte* output, word32 inLen, + int withAlg) { -#ifdef WOLFSSL_SMALL_STACK - byte* n = NULL; - byte* e = NULL; - byte* algo = NULL; -#else - byte n[MAX_RSA_INT_SZ]; - byte e[MAX_RSA_E_SZ]; - byte algo[MAX_ALGO_SZ]; -#endif - byte seq[MAX_SEQ_SZ]; - byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */ - int nSz; - int eSz; + 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) */ +#if defined(HAVE_ED448) && (defined(WOLFSSL_CERT_GEN) || \ + defined(WOLFSSL_KEY_GEN)) + +/* Write a public ECC key to output */ +static int SetEd448PublicKey(byte* output, ed448_key* key, int with_header) +{ + byte bitString[1 + MAX_LENGTH_SZ + 1]; int algoSz; - int seqSz; - int lenSz; + int bitStringSz; int idx; - int rawLen; - int leadingBit; - int err; - - /* n */ + word32 pubSz = ED448_PUB_KEY_SIZE; #ifdef WOLFSSL_SMALL_STACK - n = (byte*)XMALLOC(MAX_RSA_INT_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (n == NULL) + byte* algo = NULL; + byte* pub = NULL; +#else + byte algo[MAX_ALGO_SZ]; + byte pub[ED448_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 - leadingBit = mp_leading_bit(&key->n); - rawLen = mp_unsigned_bin_size(&key->n) + leadingBit; - n[0] = ASN_INTEGER; - nSz = SetLength(rawLen, n + 1) + 1; /* int tag */ - - if ( (nSz + rawLen) < MAX_RSA_INT_SZ) { - if (leadingBit) - n[nSz] = 0; - err = mp_to_unsigned_bin(&key->n, n + nSz + leadingBit); - if (err == MP_OKAY) - nSz += rawLen; - else { + idx = wc_ed448_export_public(key, pub, &pubSz); + if (idx != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return MP_TO_E; - } + return idx; } - else { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return BUFFER_E; - } - - /* e */ -#ifdef WOLFSSL_SMALL_STACK - e = (byte*)XMALLOC(MAX_RSA_E_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (e == NULL) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return MEMORY_E; - } -#endif - - leadingBit = mp_leading_bit(&key->e); - rawLen = mp_unsigned_bin_size(&key->e) + leadingBit; - e[0] = ASN_INTEGER; - eSz = SetLength(rawLen, e + 1) + 1; /* int tag */ - - if ( (eSz + rawLen) < MAX_RSA_E_SZ) { - if (leadingBit) - e[eSz] = 0; - err = mp_to_unsigned_bin(&key->e, e + eSz + leadingBit); - 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 { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return BUFFER_E; - } - -#ifdef WOLFSSL_SMALL_STACK - algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (algo == NULL) { - XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif /* headers */ - algoSz = SetAlgoID(RSAk, algo, keyType, 0); - seqSz = SetSequence(nSz + eSz, seq); - lenSz = SetLength(seqSz + nSz + eSz + 1, len); - len[lenSz++] = 0; /* trailing 0 */ + if (with_header) { +#ifdef WOLFSSL_SMALL_STACK + algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + algoSz = SetAlgoID(ED448k, algo, oidKeyType, 0); - /* write */ - idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output); - /* 1 is for ASN_BIT_STRING */ - /* algo */ - XMEMCPY(output + idx, algo, algoSz); - idx += algoSz; - /* bit string */ - output[idx++] = ASN_BIT_STRING; - /* length */ - XMEMCPY(output + idx, len, lenSz); - idx += lenSz; - /* seq */ - XMEMCPY(output + idx, seq, seqSz); - idx += seqSz; - /* n */ - XMEMCPY(output + idx, n, nSz); - idx += nSz; - /* e */ - XMEMCPY(output + idx, e, eSz); - idx += eSz; + 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 - XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (with_header) { + XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return idx; } +int wc_Ed448PublicKeyToDer(ed448_key* key, byte* output, word32 inLen, + int withAlg) +{ + word32 infoSz = 0; + word32 keySz = 0; + int ret; -static INLINE byte itob(int number) + 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_ed448_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 SetEd448PublicKey(output, key, withAlg); +} +#endif /* HAVE_ED448 && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */ + + +#ifdef WOLFSSL_CERT_GEN + +static WC_INLINE byte itob(int number) { return (byte)number + 0x30; } @@ -5184,7 +11861,7 @@ static void SetTime(struct tm* date, byte* output) output[i++] = itob(date->tm_sec / 10); output[i++] = itob(date->tm_sec % 10); - + output[i] = 'Z'; /* Zulu profile */ } @@ -5200,28 +11877,19 @@ static int CopyValidity(byte* output, Cert* cert) /* headers and output */ seqSz = SetSequence(cert->beforeDateSz + cert->afterDateSz, output); - XMEMCPY(output + seqSz, cert->beforeDate, cert->beforeDateSz); - XMEMCPY(output + seqSz + cert->beforeDateSz, cert->afterDate, - cert->afterDateSz); + if (output) { + XMEMCPY(output + seqSz, cert->beforeDate, cert->beforeDateSz); + XMEMCPY(output + seqSz + cert->beforeDateSz, cert->afterDate, + cert->afterDateSz); + } return seqSz + cert->beforeDateSz + cert->afterDateSz; } #endif -/* for systems where mktime() doesn't normalize fully */ -static void RebuildTime(time_t* in, struct tm* out) -{ - #ifdef FREESCALE_MQX - out = localtime_r(in, out); - #else - (void)in; - (void)out; - #endif -} - - -/* Set Date validity from now until now + daysValid */ +/* Set Date validity from now until now + daysValid + * return size in bytes written to output, 0 on error */ static int SetValidity(byte* output, int daysValid) { byte before[MAX_DATE_SIZE]; @@ -5231,55 +11899,60 @@ static int SetValidity(byte* output, int daysValid) int afterSz; int seqSz; - time_t ticks; - time_t normalTime; - struct tm* now; - struct tm* tmpTime = NULL; - struct tm local; + time_t now; + time_t then; + struct tm* tmpTime; + struct tm* expandedTime; + struct tm localTime; -#if defined(FREESCALE_MQX) || defined(TIME_OVERRIDES) +#if defined(NEED_TMP_TIME) /* for use with gmtime_r */ struct tm tmpTimeStorage; tmpTime = &tmpTimeStorage; #else - (void)tmpTime; + tmpTime = NULL; #endif + (void)tmpTime; - ticks = XTIME(0); - now = XGMTIME(&ticks, tmpTime); + now = XTIME(0); /* before now */ - local = *now; before[0] = ASN_GENERALIZED_TIME; - beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1; /* gen tag */ + beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1; /* gen tag */ - /* subtract 1 day for more compliance */ - local.tm_mday -= 1; - normalTime = mktime(&local); - RebuildTime(&normalTime, &local); + /* subtract 1 day of seconds for more compliance */ + then = now - 86400; + expandedTime = XGMTIME(&then, tmpTime); + if (expandedTime == NULL) { + WOLFSSL_MSG("XGMTIME failed"); + return 0; /* error */ + } + localTime = *expandedTime; /* adjust */ - local.tm_year += 1900; - local.tm_mon += 1; + localTime.tm_year += 1900; + localTime.tm_mon += 1; - SetTime(&local, before + beforeSz); + SetTime(&localTime, before + beforeSz); beforeSz += ASN_GEN_TIME_SZ; - /* after now + daysValid */ - local = *now; after[0] = ASN_GENERALIZED_TIME; afterSz = SetLength(ASN_GEN_TIME_SZ, after + 1) + 1; /* gen tag */ - /* add daysValid */ - local.tm_mday += daysValid; - normalTime = mktime(&local); - RebuildTime(&normalTime, &local); + /* add daysValid of seconds */ + then = now + (daysValid * (time_t)86400); + expandedTime = XGMTIME(&then, tmpTime); + if (expandedTime == NULL) { + WOLFSSL_MSG("XGMTIME failed"); + return 0; /* error */ + } + localTime = *expandedTime; /* adjust */ - local.tm_year += 1900; - local.tm_mon += 1; + localTime.tm_year += 1900; + localTime.tm_mon += 1; - SetTime(&local, after + afterSz); + SetTime(&localTime, after + afterSz); afterSz += ASN_GEN_TIME_SZ; /* headers and output */ @@ -5327,6 +12000,16 @@ static const char* GetOneName(CertName* name, int idx) return name->commonName; case 7: + return name->serialDev; + +#ifdef WOLFSSL_CERT_EXT + case 8: + return name->busCat; + + case 9: +#else + case 8: +#endif return name->email; default: @@ -5360,6 +12043,20 @@ static char GetNameType(CertName* name, int idx) case 6: return name->commonNameEnc; + case 7: + return name->serialDevEnc; + +#ifdef WOLFSSL_CERT_EXT + case 8: + return name->busCatEnc; + + case 9: +#else + case 8: +#endif + /* FALL THROUGH */ + /* The last index, email name, does not have encoding type. + The empty case here is to keep track of it for future reference. */ default: return 0; } @@ -5392,54 +12089,589 @@ static byte GetNameId(int idx) return ASN_COMMON_NAME; case 7: - /* email uses different id type */ - return 0; + return ASN_SERIAL_NUMBER; + +#ifdef WOLFSSL_CERT_EXT + case 8: + return ASN_BUS_CAT; + + case 9: +#else + case 8: +#endif + return ASN_EMAIL_NAME; default: return 0; } } +/* + Extensions ::= SEQUENCE OF Extension + + Extension ::= SEQUENCE { + extnId OBJECT IDENTIFIER, + critical BOOLEAN DEFAULT FALSE, + extnValue OCTET STRING } + */ /* encode all extensions, return total bytes written */ -static int SetExtensions(byte* output, const byte* ext, int extSz, int header) +static int SetExtensions(byte* out, word32 outSz, int *IdxInOut, + const byte* ext, int extSz) +{ + if (out == NULL || IdxInOut == NULL || ext == NULL) + return BAD_FUNC_ARG; + + if (outSz < (word32)(*IdxInOut+extSz)) + return BUFFER_E; + + XMEMCPY(&out[*IdxInOut], ext, extSz); /* extensions */ + *IdxInOut += extSz; + + return *IdxInOut; +} + +/* encode extensions header, return total bytes written */ +static int SetExtensionsHeader(byte* out, word32 outSz, int extSz) { byte sequence[MAX_SEQ_SZ]; byte len[MAX_LENGTH_SZ]; + int seqSz, lenSz, idx = 0; - int sz = 0; - int seqSz = SetSequence(extSz, sequence); + if (out == NULL) + return BAD_FUNC_ARG; - if (header) { - int lenSz = SetLength(seqSz + extSz, len); - output[0] = ASN_EXTENSIONS; /* extensions id */ - sz++; - XMEMCPY(&output[sz], len, lenSz); /* length */ - sz += lenSz; - } - XMEMCPY(&output[sz], sequence, seqSz); /* sequence */ - sz += seqSz; - XMEMCPY(&output[sz], ext, extSz); /* extensions */ - sz += extSz; + if (outSz < 3) + return BUFFER_E; - return sz; + seqSz = SetSequence(extSz, sequence); + + /* encode extensions length provided */ + lenSz = SetLength(extSz+seqSz, len); + + if (outSz < (word32)(lenSz+seqSz+1)) + return BUFFER_E; + + out[idx++] = ASN_EXTENSIONS; /* extensions id */ + XMEMCPY(&out[idx], len, lenSz); /* length */ + idx += lenSz; + + XMEMCPY(&out[idx], sequence, seqSz); /* sequence */ + idx += seqSz; + + return idx; } /* encode CA basic constraint true, return total bytes written */ -static int SetCa(byte* output) +static int SetCa(byte* out, word32 outSz) { - static const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff }; - - XMEMCPY(output, ca, sizeof(ca)); + + if (out == NULL) + return BAD_FUNC_ARG; + + if (outSz < sizeof(ca)) + return BUFFER_E; + + XMEMCPY(out, ca, sizeof(ca)); return (int)sizeof(ca); } +#ifdef WOLFSSL_CERT_EXT +/* encode OID and associated value, return total bytes written */ +static int SetOidValue(byte* out, word32 outSz, const byte *oid, word32 oidSz, + byte *in, word32 inSz) +{ + int idx = 0; + + if (out == NULL || oid == NULL || in == NULL) + return BAD_FUNC_ARG; + + if (outSz < 3) + return BUFFER_E; + + /* sequence, + 1 => byte to put value size */ + idx = SetSequence(inSz + oidSz + 1, out); + + if ((idx + inSz + oidSz + 1) > outSz) + return BUFFER_E; + + XMEMCPY(out+idx, oid, oidSz); + idx += oidSz; + out[idx++] = (byte)inSz; + XMEMCPY(out+idx, in, inSz); + + return (idx+inSz); +} + +/* encode Subject Key Identifier, return total bytes written + * RFC5280 : non-critical */ +static int SetSKID(byte* output, word32 outSz, const byte *input, word32 length) +{ + byte skid_len[1 + MAX_LENGTH_SZ]; + byte skid_enc_len[MAX_LENGTH_SZ]; + int idx = 0, skid_lenSz, skid_enc_lenSz; + const byte skid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04 }; + + if (output == NULL || input == NULL) + return BAD_FUNC_ARG; + + /* Octet String header */ + skid_lenSz = SetOctetString(length, skid_len); + + /* length of encoded value */ + skid_enc_lenSz = SetLength(length + skid_lenSz, skid_enc_len); + + if (outSz < 3) + return BUFFER_E; + + idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz, + output); + + if ((length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz) > outSz) + return BUFFER_E; + + /* put oid */ + XMEMCPY(output+idx, skid_oid, sizeof(skid_oid)); + idx += sizeof(skid_oid); + + /* put encoded len */ + XMEMCPY(output+idx, skid_enc_len, skid_enc_lenSz); + idx += skid_enc_lenSz; + + /* put octet header */ + XMEMCPY(output+idx, skid_len, skid_lenSz); + idx += skid_lenSz; + + /* put value */ + XMEMCPY(output+idx, input, length); + idx += length; + + return idx; +} + +/* encode Authority Key Identifier, return total bytes written + * RFC5280 : non-critical */ +static int SetAKID(byte* output, word32 outSz, + byte *input, word32 length, void* heap) +{ + byte *enc_val; + int ret, enc_valSz; + const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04 }; + const byte akid_cs[] = { 0x80 }; + + (void)heap; + + if (output == NULL || input == NULL) + return BAD_FUNC_ARG; + + 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 */ + 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); + } + + XFREE(enc_val, heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + +/* encode Key Usage, return total bytes written + * RFC5280 : critical */ +static int SetKeyUsage(byte* output, word32 outSz, word16 input) +{ + byte ku[5]; + int idx; + 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(Cert* cert, byte* output, word32 outSz, byte input) +{ + int idx = 0, oidListSz = 0, totalSz, ret = 0; + const byte extkeyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x25 }; + + if (output == NULL) + return BAD_FUNC_ARG; + + /* Skip to OID List */ + totalSz = 2 + sizeof(extkeyusage_oid) + 4; + idx = totalSz; + + /* Build OID List */ + /* If any set, then just use it */ + if (input & EXTKEYUSE_ANY) { + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageAnyOid, sizeof(extExtKeyUsageAnyOid)); + } + else { + 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)); + #ifdef WOLFSSL_EKU_OID + /* iterate through OID values */ + if (input & EXTKEYUSE_USER) { + int i, sz; + for (i = 0; i < CTC_MAX_EKU_NB; i++) { + sz = cert->extKeyUsageOIDSz[i]; + if (sz > 0) { + ret |= SetOjectIdValue(output, outSz, &idx, + cert->extKeyUsageOID[i], sz); + } + } + } + #endif /* WOLFSSL_EKU_OID */ + } + if (ret != 0) + return ASN_PARSE_E; + + /* Calculate Sizes */ + oidListSz = idx - totalSz; + totalSz = idx - 2; /* exclude first seq/len (2) */ + + /* 1. Seq + Total Len (2) */ + idx = SetSequence(totalSz, output); + + /* 2. Object ID (2) */ + XMEMCPY(&output[idx], extkeyusage_oid, sizeof(extkeyusage_oid)); + idx += sizeof(extkeyusage_oid); + + /* 3. Octet 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; + + (void)cert; + return idx; +} + +/* encode Certificate Policies, return total bytes written + * each input value must be ITU-T X.690 formatted : a.b.c... + * input must be an array of values with a NULL terminated for the latest + * RFC5280 : non-critical */ +static int SetCertificatePolicies(byte *output, + word32 outputSz, + char input[MAX_CERTPOL_NB][MAX_CERTPOL_SZ], + word16 nb_certpol, + void* heap) +{ + byte oid[MAX_OID_SZ], + der_oid[MAX_CERTPOL_NB][MAX_OID_SZ], + out[MAX_CERTPOL_SZ]; + word32 oidSz; + word32 outSz, i = 0, der_oidSz[MAX_CERTPOL_NB]; + int ret; + + const byte certpol_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04 }; + const byte oid_oid[] = { 0x06 }; + + if (output == NULL || input == NULL || nb_certpol > MAX_CERTPOL_NB) + return BAD_FUNC_ARG; + + for (i = 0; i < nb_certpol; i++) { + oidSz = sizeof(oid); + XMEMSET(oid, 0, oidSz); + + ret = EncodePolicyOID(oid, &oidSz, input[i], heap); + if (ret != 0) + return ret; + + /* compute sequence value for the oid */ + ret = SetOidValue(der_oid[i], MAX_OID_SZ, oid_oid, + sizeof(oid_oid), oid, oidSz); + if (ret <= 0) + return ret; + else + der_oidSz[i] = (word32)ret; + } + + /* concatenate oid, keep two byte for sequence/size of the created value */ + for (i = 0, outSz = 2; i < nb_certpol; i++) { + XMEMCPY(out+outSz, der_oid[i], der_oidSz[i]); + outSz += der_oidSz[i]; + } + + /* add sequence */ + ret = SetSequence(outSz-2, out); + if (ret <= 0) + return ret; + + /* add Policy OID to compute final value */ + return SetOidValue(output, outputSz, certpol_oid, sizeof(certpol_oid), + out, outSz); +} +#endif /* WOLFSSL_CERT_EXT */ + + +#ifdef WOLFSSL_ALT_NAMES + +/* encode Alternative Names, return total bytes written */ +static int SetAltNames(byte *output, word32 outSz, + const byte *input, word32 length) +{ + byte san_len[1 + MAX_LENGTH_SZ]; + int idx = 0, san_lenSz; + const byte san_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x11 }; + + if (output == NULL || input == NULL) + return BAD_FUNC_ARG; + + if (outSz < length) + return BUFFER_E; + + /* Octet String header */ + san_lenSz = SetOctetString(length, san_len); + + if (outSz < MAX_SEQ_SZ) + return BUFFER_E; + + idx = SetSequence(length + sizeof(san_oid) + san_lenSz, output); + + if ((length + sizeof(san_oid) + san_lenSz) > outSz) + return BUFFER_E; + + /* put oid */ + XMEMCPY(output+idx, san_oid, sizeof(san_oid)); + idx += sizeof(san_oid); + + /* put octet header */ + XMEMCPY(output+idx, san_len, san_lenSz); + idx += san_lenSz; + + /* put value */ + XMEMCPY(output+idx, input, length); + idx += length; + + return idx; +} + + +#ifdef WOLFSSL_CERT_GEN + +int FlattenAltNames(byte* output, word32 outputSz, const DNS_entry* names) +{ + word32 idx; + const DNS_entry* curName; + word32 namesSz = 0; + + if (output == NULL) + return BAD_FUNC_ARG; + + if (names == NULL) + return 0; + + curName = names; + do { + namesSz += curName->len + 2 + + ((curName->len < ASN_LONG_LENGTH) ? 0 + : BytePrecision(curName->len)); + curName = curName->next; + } while (curName != NULL); + + if (outputSz < MAX_SEQ_SZ + namesSz) + return BUFFER_E; + + idx = SetSequence(namesSz, output); + + curName = names; + do { + output[idx++] = ASN_CONTEXT_SPECIFIC | curName->type; + idx += SetLength(curName->len, output + idx); + XMEMCPY(output + idx, curName->name, curName->len); + idx += curName->len; + curName = curName->next; + } while (curName != NULL); + + return idx; +} + +#endif /* WOLFSSL_CERT_GEN */ + +#endif /* WOLFSSL_ALT_NAMES */ + +/* Encodes one attribute of the name (issuer/subject) + * + * name structure to hold result of encoding + * nameStr value to be encoded + * nameType type of encoding i.e CTC_UTF8 + * type id of attribute i.e ASN_COMMON_NAME + * + * returns length on success + */ +static int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType, + byte type) +{ + word32 idx = 0; + + if (nameStr) { + /* bottom up */ + byte firstLen[1 + MAX_LENGTH_SZ]; + byte secondLen[MAX_LENGTH_SZ]; + byte sequence[MAX_SEQ_SZ]; + byte set[MAX_SET_SZ]; + + int strLen = (int)XSTRLEN(nameStr); + int thisLen = strLen; + int firstSz, secondSz, seqSz, setSz; + + if (strLen == 0) { /* no user data for this item */ + name->used = 0; + return 0; + } + + /* Restrict country code size */ + if (ASN_COUNTRY_NAME == type && strLen != CTC_COUNTRY_SIZE) { + return ASN_COUNTRY_SIZE_E; + } + + secondSz = SetLength(strLen, secondLen); + thisLen += secondSz; + switch (type) { + case ASN_EMAIL_NAME: /* email */ + thisLen += EMAIL_JOINT_LEN; + firstSz = EMAIL_JOINT_LEN; + break; + + case ASN_DOMAIN_COMPONENT: + thisLen += PILOT_JOINT_LEN; + firstSz = PILOT_JOINT_LEN; + break; + + default: + thisLen++; /* str type */ + thisLen += JOINT_LEN; + firstSz = JOINT_LEN + 1; + } + thisLen++; /* id type */ + firstSz = SetObjectId(firstSz, firstLen); + thisLen += firstSz; + + seqSz = SetSequence(thisLen, sequence); + thisLen += seqSz; + setSz = SetSet(thisLen, set); + thisLen += setSz; + + if (thisLen > (int)sizeof(name->encoded)) { + return BUFFER_E; + } + + /* store it */ + idx = 0; + /* set */ + XMEMCPY(name->encoded, set, setSz); + idx += setSz; + /* seq */ + XMEMCPY(name->encoded + idx, sequence, seqSz); + idx += seqSz; + /* asn object id */ + XMEMCPY(name->encoded + idx, firstLen, firstSz); + idx += firstSz; + switch (type) { + case ASN_EMAIL_NAME: + { + const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x09, 0x01, 0x16 }; + /* email joint id */ + XMEMCPY(name->encoded + idx, EMAIL_OID, sizeof(EMAIL_OID)); + idx += (int)sizeof(EMAIL_OID); + } + break; + + case ASN_DOMAIN_COMPONENT: + { + const byte PILOT_OID[] = { 0x09, 0x92, 0x26, 0x89, + 0x93, 0xF2, 0x2C, 0x64, 0x01 + }; + + XMEMCPY(name->encoded + idx, PILOT_OID, + sizeof(PILOT_OID)); + idx += (int)sizeof(PILOT_OID); + /* id type */ + name->encoded[idx++] = type; + /* str type */ + name->encoded[idx++] = nameType; + } + break; + + default: + name->encoded[idx++] = 0x55; + name->encoded[idx++] = 0x04; + /* id type */ + name->encoded[idx++] = type; + /* str type */ + name->encoded[idx++] = nameType; + } + /* second length */ + XMEMCPY(name->encoded + idx, secondLen, secondSz); + idx += secondSz; + /* str value */ + XMEMCPY(name->encoded + idx, nameStr, strLen); + idx += strLen; + + name->type = type; + name->totalLen = idx; + name->used = 1; + } + else + name->used = 0; + + return idx; +} + /* encode CertName into output, return total bytes written */ -static int SetName(byte* output, CertName* name) +int SetName(byte* output, word32 outputSz, CertName* name) { int totalBytes = 0, i, idx; #ifdef WOLFSSL_SMALL_STACK @@ -5447,6 +12679,16 @@ static int SetName(byte* output, CertName* name) #else EncodedName names[NAME_ENTRIES]; #endif +#ifdef WOLFSSL_MULTI_ATTRIB + EncodedName addNames[CTC_MAX_ATTRIB]; + int j, type; +#endif + + if (output == NULL || name == NULL) + return BAD_FUNC_ARG; + + if (outputSz < 3) + return BUFFER_E; #ifdef WOLFSSL_SMALL_STACK names = (EncodedName*)XMALLOC(sizeof(EncodedName) * NAME_ENTRIES, NULL, @@ -5456,96 +12698,38 @@ static int SetName(byte* output, CertName* name) #endif for (i = 0; i < NAME_ENTRIES; i++) { + int ret; const char* nameStr = GetOneName(name, i); - if (nameStr) { - /* bottom up */ - byte firstLen[MAX_LENGTH_SZ]; - byte secondLen[MAX_LENGTH_SZ]; - byte sequence[MAX_SEQ_SZ]; - byte set[MAX_SET_SZ]; - int email = i == (NAME_ENTRIES - 1) ? 1 : 0; - int strLen = (int)XSTRLEN(nameStr); - int thisLen = strLen; - int firstSz, secondSz, seqSz, setSz; - - if (strLen == 0) { /* no user data for this item */ - names[i].used = 0; - continue; - } - - secondSz = SetLength(strLen, secondLen); - thisLen += secondSz; - if (email) { - thisLen += EMAIL_JOINT_LEN; - thisLen ++; /* id type */ - firstSz = SetLength(EMAIL_JOINT_LEN, firstLen); - } - else { - thisLen++; /* str type */ - thisLen++; /* id type */ - thisLen += JOINT_LEN; - firstSz = SetLength(JOINT_LEN + 1, firstLen); - } - thisLen += firstSz; - thisLen++; /* object id */ - - seqSz = SetSequence(thisLen, sequence); - thisLen += seqSz; - setSz = SetSet(thisLen, set); - thisLen += setSz; - - if (thisLen > (int)sizeof(names[i].encoded)) { -#ifdef WOLFSSL_SMALL_STACK + ret = wc_EncodeName(&names[i], nameStr, GetNameType(name, i), + GetNameId(i)); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + #endif + return BUFFER_E; + } + totalBytes += ret; + } +#ifdef WOLFSSL_MULTI_ATTRIB + for (i = 0; i < CTC_MAX_ATTRIB; i++) { + if (name->name[i].sz > 0) { + int ret; + ret = wc_EncodeName(&addNames[i], name->name[i].value, + name->name[i].type, name->name[i].id); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif return BUFFER_E; } - - /* store it */ - idx = 0; - /* set */ - XMEMCPY(names[i].encoded, set, setSz); - idx += setSz; - /* seq */ - 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) { - const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x09, 0x01, 0x16 }; - /* email joint id */ - XMEMCPY(names[i].encoded + idx, EMAIL_OID, sizeof(EMAIL_OID)); - idx += (int)sizeof(EMAIL_OID); - } - else { - /* joint id */ - byte bType = GetNameId(i); - names[i].encoded[idx++] = 0x55; - names[i].encoded[idx++] = 0x04; - /* id type */ - names[i].encoded[idx++] = bType; - /* str type */ - names[i].encoded[idx++] = GetNameType(name, i); - } - /* second length */ - XMEMCPY(names[i].encoded + idx, secondLen, secondSz); - idx += secondSz; - /* str value */ - XMEMCPY(names[i].encoded + idx, nameStr, strLen); - idx += strLen; - - totalBytes += idx; - names[i].totalLen = idx; - names[i].used = 1; + totalBytes += ret; + } + else { + addNames[i].used = 0; } - else - names[i].used = 0; } +#endif /* WOLFSSL_MULTI_ATTRIB */ /* header */ idx = SetSequence(totalBytes, output); @@ -5558,7 +12742,54 @@ static int SetName(byte* output, CertName* name) } for (i = 0; i < NAME_ENTRIES; i++) { + #ifdef WOLFSSL_MULTI_ATTRIB + type = GetNameId(i); + + /* list all DC values before OUs */ + if (type == ASN_ORGUNIT_NAME) { + type = ASN_DOMAIN_COMPONENT; + for (j = 0; j < CTC_MAX_ATTRIB; j++) { + if (name->name[j].sz > 0 && type == name->name[j].id) { + if (outputSz < (word32)(idx+addNames[j].totalLen)) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + + XMEMCPY(output + idx, addNames[j].encoded, + addNames[j].totalLen); + idx += addNames[j].totalLen; + } + } + type = ASN_ORGUNIT_NAME; + } + + /* write all similar types to the buffer */ + for (j = 0; j < CTC_MAX_ATTRIB; j++) { + if (name->name[j].sz > 0 && type == name->name[j].id) { + if (outputSz < (word32)(idx+addNames[j].totalLen)) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + + XMEMCPY(output + idx, addNames[j].encoded, + addNames[j].totalLen); + idx += addNames[j].totalLen; + } + } + #endif /* WOLFSSL_MULTI_ATTRIB */ + if (names[i].used) { + if (outputSz < (word32)(idx+names[i].totalLen)) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BUFFER_E; + } + XMEMCPY(output + idx, names[i].encoded, names[i].totalLen); idx += names[i].totalLen; } @@ -5573,13 +12804,19 @@ static int SetName(byte* output, CertName* name) /* encode info from cert into DER encoded format */ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, - RNG* rng, const byte* ntruKey, word16 ntruSz) + WC_RNG* rng, const byte* ntruKey, word16 ntruSz, + ed25519_key* ed25519Key, ed448_key* ed448Key) { 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 && + ed448Key == NULL && ntruKey == NULL) { + return PUBLIC_KEY_E; + } /* init */ XMEMSET(der, 0, sizeof(DerCert)); @@ -5587,65 +12824,95 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, /* 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_GEN_SERIAL_SZ; + ret = wc_RNG_GenerateBlock(rng, cert->serial, cert->serialSz); + if (ret != 0) + return ret; + /* Clear the top bit to avoid a negative value */ + cert->serial[0] &= 0x7f; + } + der->serialSz = SetSerialNumber(cert->serial, cert->serialSz, der->serial, + sizeof(der->serial), CTC_SERIAL_SIZE); + if (der->serialSz < 0) + return der->serialSz; /* signature algo */ - der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, sigType, 0); - if (der->sigAlgoSz == 0) + der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, oidSigType, 0); + if (der->sigAlgoSz <= 0) 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); - if (der->publicKeySz <= 0) - return PUBLIC_KEY_E; + der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey, + sizeof(der->publicKey), 1); } +#endif #ifdef HAVE_ECC if (cert->keyType == ECC_KEY) { if (eccKey == NULL) return PUBLIC_KEY_E; - der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey); - if (der->publicKeySz <= 0) - return PUBLIC_KEY_E; + der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1); } -#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_ED448 + if (cert->keyType == ED448_KEY) { + if (ed448Key == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEd448PublicKey(der->publicKey, ed448Key, 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 ? */ if (cert->beforeDateSz && cert->afterDateSz) { der->validitySz = CopyValidity(der->validity, cert); - if (der->validitySz == 0) + if (der->validitySz <= 0) return DATE_E; } #endif @@ -5653,49 +12920,247 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, /* date validity */ if (der->validitySz == 0) { der->validitySz = SetValidity(der->validity, cert->daysValid); - if (der->validitySz == 0) + if (der->validitySz <= 0) return DATE_E; } /* subject name */ - der->subjectSz = SetName(der->subject, &cert->subject); - if (der->subjectSz == 0) +#ifdef WOLFSSL_CERT_EXT + if (XSTRLEN((const char*)cert->sbjRaw) > 0) { + /* Use the raw subject */ + int idx; + + der->subjectSz = min(sizeof(der->subject), + (word32)XSTRLEN((const char*)cert->sbjRaw)); + /* header */ + idx = SetSequence(der->subjectSz, der->subject); + if (der->subjectSz + idx > (int)sizeof(der->subject)) { + return SUBJECT_E; + } + + XMEMCPY((char*)der->subject + idx, (const char*)cert->sbjRaw, + der->subjectSz); + der->subjectSz += idx; + } + else +#endif + { + /* Use the name structure */ + der->subjectSz = SetName(der->subject, sizeof(der->subject), + &cert->subject); + } + if (der->subjectSz <= 0) return SUBJECT_E; /* issuer name */ - der->issuerSz = SetName(der->issuer, cert->selfSigned ? - &cert->subject : &cert->issuer); - if (der->issuerSz == 0) +#ifdef WOLFSSL_CERT_EXT + if (XSTRLEN((const char*)cert->issRaw) > 0) { + /* Use the raw issuer */ + int idx; + + der->issuerSz = min(sizeof(der->issuer), + (word32)XSTRLEN((const char*)cert->issRaw)); + /* header */ + idx = SetSequence(der->issuerSz, der->issuer); + if (der->issuerSz + idx > (int)sizeof(der->issuer)) { + return ISSUER_E; + } + + XMEMCPY((char*)der->issuer + idx, (const char*)cert->issRaw, + der->issuerSz); + der->issuerSz += idx; + } + else +#endif + { + /* Use the name structure */ + der->issuerSz = SetName(der->issuer, sizeof(der->issuer), + cert->selfSigned ? &cert->subject : &cert->issuer); + } + if (der->issuerSz <= 0) return ISSUER_E; + /* set the extensions */ + der->extensionsSz = 0; + /* CA */ if (cert->isCA) { - der->caSz = SetCa(der->ca); - if (der->caSz == 0) + der->caSz = SetCa(der->ca, sizeof(der->ca)); + if (der->caSz <= 0) return CA_TRUE_E; + + der->extensionsSz += der->caSz; } else der->caSz = 0; - /* extensions, just CA now */ - if (cert->isCA) { - der->extensionsSz = SetExtensions(der->extensions, - der->ca, der->caSz, TRUE); - if (der->extensionsSz == 0) - return EXTENSIONS_E; +#ifdef WOLFSSL_ALT_NAMES + /* Alternative Name */ + if (cert->altNamesSz) { + der->altNamesSz = SetAltNames(der->altNames, sizeof(der->altNames), + cert->altNames, cert->altNamesSz); + if (der->altNamesSz <= 0) + return ALT_NAME_E; + + der->extensionsSz += der->altNamesSz; } else - der->extensionsSz = 0; + der->altNamesSz = 0; +#endif + +#ifdef WOLFSSL_CERT_EXT + /* SKID */ + if (cert->skidSz) { + /* check the provided SKID size */ + if (cert->skidSz > (int)min(CTC_MAX_SKID_SIZE, 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) + return SKID_E; + + der->extensionsSz += der->skidSz; + } + else + der->skidSz = 0; + + /* AKID */ + if (cert->akidSz) { + /* check the provided AKID size */ + if (cert->akidSz > (int)min(CTC_MAX_AKID_SIZE, sizeof(der->akid))) + return AKID_E; + + der->akidSz = SetAKID(der->akid, sizeof(der->akid), + cert->akid, cert->akidSz, cert->heap); + if (der->akidSz <= 0) + return AKID_E; + + der->extensionsSz += der->akidSz; + } + else + der->akidSz = 0; + + /* Key Usage */ + if (cert->keyUsage != 0){ + der->keyUsageSz = SetKeyUsage(der->keyUsage, sizeof(der->keyUsage), + cert->keyUsage); + if (der->keyUsageSz <= 0) + return KEYUSAGE_E; + + der->extensionsSz += der->keyUsageSz; + } + else + der->keyUsageSz = 0; + + /* Extended Key Usage */ + if (cert->extKeyUsage != 0){ + der->extKeyUsageSz = SetExtKeyUsage(cert, 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, + sizeof(der->certPolicies), + cert->certPolicies, + cert->certPoliciesNb, + cert->heap); + if (der->certPoliciesSz <= 0) + return CERTPOLICIES_E; + + der->extensionsSz += der->certPoliciesSz; + } + else + der->certPoliciesSz = 0; +#endif /* WOLFSSL_CERT_EXT */ + + /* put extensions */ + if (der->extensionsSz > 0) { + + /* put the start of extensions sequence (ID, Size) */ + der->extensionsSz = SetExtensionsHeader(der->extensions, + sizeof(der->extensions), + der->extensionsSz); + if (der->extensionsSz <= 0) + return EXTENSIONS_E; + + /* put CA */ + if (der->caSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->ca, der->caSz); + if (ret == 0) + return EXTENSIONS_E; + } #ifdef WOLFSSL_ALT_NAMES - if (der->extensionsSz == 0 && cert->altNamesSz) { - der->extensionsSz = SetExtensions(der->extensions, cert->altNames, - cert->altNamesSz, TRUE); - if (der->extensionsSz == 0) - return EXTENSIONS_E; - } + /* put Alternative Names */ + if (der->altNamesSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->altNames, der->altNamesSz); + if (ret <= 0) + return EXTENSIONS_E; + } #endif +#ifdef WOLFSSL_CERT_EXT + /* put SKID */ + if (der->skidSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->skid, der->skidSz); + if (ret <= 0) + return EXTENSIONS_E; + } + + /* put AKID */ + if (der->akidSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->akid, der->akidSz); + if (ret <= 0) + return EXTENSIONS_E; + } + + /* put KeyUsage */ + if (der->keyUsageSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->keyUsage, der->keyUsageSz); + if (ret <= 0) + 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), + &der->extensionsSz, + der->certPolicies, der->certPoliciesSz); + if (ret <= 0) + return EXTENSIONS_E; + } +#endif /* WOLFSSL_CERT_EXT */ + } + der->total = der->versionSz + der->serialSz + der->sigAlgoSz + der->publicKeySz + der->validitySz + der->subjectSz + der->issuerSz + der->extensionsSz; @@ -5705,37 +13170,37 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, /* write DER encoded cert to buffer, size already checked */ -static int WriteCertBody(DerCert* der, byte* buffer) +static int WriteCertBody(DerCert* der, byte* buf) { int idx; /* signed part header */ - idx = SetSequence(der->total, buffer); + idx = SetSequence(der->total, buf); /* version */ - XMEMCPY(buffer + idx, der->version, der->versionSz); + XMEMCPY(buf + idx, der->version, der->versionSz); idx += der->versionSz; /* serial */ - XMEMCPY(buffer + idx, der->serial, der->serialSz); + XMEMCPY(buf + idx, der->serial, der->serialSz); idx += der->serialSz; /* sig algo */ - XMEMCPY(buffer + idx, der->sigAlgo, der->sigAlgoSz); + XMEMCPY(buf + idx, der->sigAlgo, der->sigAlgoSz); idx += der->sigAlgoSz; /* issuer */ - XMEMCPY(buffer + idx, der->issuer, der->issuerSz); + XMEMCPY(buf + idx, der->issuer, der->issuerSz); idx += der->issuerSz; /* validity */ - XMEMCPY(buffer + idx, der->validity, der->validitySz); + XMEMCPY(buf + idx, der->validity, der->validitySz); idx += der->validitySz; /* subject */ - XMEMCPY(buffer + idx, der->subject, der->subjectSz); + XMEMCPY(buf + idx, der->subject, der->subjectSz); idx += der->subjectSz; /* public key */ - XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz); + XMEMCPY(buf + idx, der->publicKey, der->publicKeySz); idx += der->publicKeySz; if (der->extensionsSz) { /* extensions */ - XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz, - sizeof(der->extensions))); + XMEMCPY(buf + idx, der->extensions, min(der->extensionsSz, + (int)sizeof(der->extensions))); idx += der->extensionsSz; } @@ -5744,97 +13209,126 @@ 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, RNG* rng, - int sigAlgoType) +static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, int sz, + byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey, + ed25519_key* ed25519Key, ed448_key* ed448Key, WC_RNG* rng, int sigAlgoType, + void* heap) { - int encSigSz, digestSz, typeH = 0, ret = 0; - byte digest[SHA256_DIGEST_SIZE]; /* max size */ -#ifdef WOLFSSL_SMALL_STACK - byte* encSig; -#else - byte encSig[MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ]; -#endif + int digestSz = 0, typeH = 0, ret = 0; - (void)digest; (void)digestSz; - (void)encSig; - (void)encSigSz; (void)typeH; - - (void)buffer; + (void)buf; (void)sz; (void)sig; (void)sigSz; (void)rsaKey; (void)eccKey; + (void)ed25519Key; + (void)ed448Key; (void)rng; + (void)heap; - switch (sigAlgoType) { - #ifndef NO_MD5 - case CTC_MD5wRSA: - if ((ret = wc_Md5Hash(buffer, sz, digest)) == 0) { - typeH = MD5h; - digestSz = MD5_DIGEST_SIZE; + switch (certSignCtx->state) { + case CERTSIGN_STATE_BEGIN: + case CERTSIGN_STATE_DIGEST: + + 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(buf, sz, sigAlgoType, certSignCtx->digest, + &typeH, &digestSz, 0); + /* set next state, since WC_PENDING_E rentry for these are not "call again" */ + certSignCtx->state = CERTSIGN_STATE_ENCODE; + if (ret != 0) { + goto exit_ms; } - 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; + 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); } + #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); + } + #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; + } + #endif /* HAVE_ECC */ + + #ifdef HAVE_ED25519 + if (!rsaKey && !eccKey && ed25519Key) { + word32 outSz = sigSz; + + ret = wc_ed25519_sign_msg(buf, sz, sig, &outSz, ed25519Key); + if (ret == 0) + ret = outSz; + } + #endif /* HAVE_ECC */ + + #ifdef HAVE_ED448 + if (!rsaKey && !eccKey && !ed25519Key && ed448Key) { + word32 outSz = sigSz; + + ret = wc_ed448_sign_msg(buf, sz, sig, &outSz, ed448Key, NULL, 0); + 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) + +exit_ms: + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { return ret; - -#ifdef WOLFSSL_SMALL_STACK - encSig = (byte*)XMALLOC(MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ, - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (encSig == NULL) - return MEMORY_E; + } #endif - - ret = ALGO_ID_E; - + #ifndef NO_RSA if (rsaKey) { - /* signature */ - encSigSz = wc_EncodeSignature(encSig, digest, digestSz, typeH); - ret = wc_RsaSSL_Sign(encSig, encSigSz, sig, sigSz, rsaKey, rng); + XFREE(certSignCtx->encSig, heap, DYNAMIC_TYPE_TMP_BUFFER); } -#endif - -#ifdef HAVE_ECC - if (!rsaKey && eccKey) { - word32 outSz = sigSz; - ret = wc_ecc_sign_hash(digest, digestSz, sig, &outSz, rng, eccKey); +#endif /* !NO_RSA */ - if (ret == 0) - ret = outSz; - } -#endif + XFREE(certSignCtx->digest, heap, DYNAMIC_TYPE_TMP_BUFFER); + certSignCtx->digest = NULL; -#ifdef WOLFSSL_SMALL_STACK - XFREE(encSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* reset state */ + certSignCtx->state = CERTSIGN_STATE_BEGIN; return ret; } @@ -5842,27 +13336,27 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, /* add signature to end of buffer, size of buffer assumed checked, return new length */ -static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz, +static int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz, int sigAlgoType) { byte seq[MAX_SEQ_SZ]; int idx = bodySz, seqSz; /* algo */ - idx += SetAlgoID(sigAlgoType, buffer + idx, sigType, 0); + idx += SetAlgoID(sigAlgoType, buf ? buf + idx : NULL, 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, buf ? buf + idx : NULL); /* signature */ - XMEMCPY(buffer + idx, sig, sigSz); + if (buf) + XMEMCPY(buf + idx, sig, sigSz); idx += sigSz; /* make room for overall header */ seqSz = SetSequence(idx, seq); - XMEMMOVE(buffer + seqSz, buffer, idx); - XMEMCPY(buffer, seq, seqSz); + if (buf) { + XMEMMOVE(buf + seqSz, buf, idx); + XMEMCPY(buf, seq, seqSz); + } return idx + seqSz; } @@ -5870,8 +13364,9 @@ 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, RNG* rng, - const byte* ntruKey, word16 ntruSz) + RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, + const byte* ntruKey, word16 ntruSz, + ed25519_key* ed25519Key, ed448_key* ed448Key) { int ret; #ifdef WOLFSSL_SMALL_STACK @@ -5880,16 +13375,21 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, DerCert der[1]; #endif - cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : NTRU_KEY); + if (derBuffer == NULL) { + return BAD_FUNC_ARG; + } + + cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : + (ed25519Key ? ED25519_KEY : (ed448Key ? ED448_KEY : NTRU_KEY))); #ifdef WOLFSSL_SMALL_STACK - der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER); + der = (DerCert*)XMALLOC(sizeof(DerCert), cert->heap, DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) return MEMORY_E; #endif - ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz); - + ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz, + ed25519Key, ed448Key); if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) ret = BUFFER_E; @@ -5898,7 +13398,7 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, } #ifdef WOLFSSL_SMALL_STACK - XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(der, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; @@ -5906,19 +13406,41 @@ 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(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, - ecc_key* eccKey, RNG* rng) +int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, + void* key, WC_RNG* rng) { - return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0); + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + ed448_key* ed448Key = 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; + else if (keyType == ED448_TYPE) + ed448Key = (ed448_key*)key; + + return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0, + ed25519Key, ed448Key); +} +/* 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, + NULL, NULL); } #ifdef HAVE_NTRU int wc_MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz, - const byte* ntruKey, word16 keySz, RNG* rng) + const byte* ntruKey, word16 keySz, WC_RNG* rng) { - return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, ntruKey, keySz); + return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, ntruKey, keySz, NULL); } #endif /* HAVE_NTRU */ @@ -5926,12 +13448,13 @@ int wc_MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz, #ifdef WOLFSSL_CERT_REQ -static int SetReqAttrib(byte* output, char* pw, int extSz) +static int SetReqAttrib(byte* output, char* pw, int pwPrintableString, + int extSz) { - static const byte cpOid[] = + const byte cpOid[] = { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x07 }; - static const byte erOid[] = + const byte erOid[] = { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x0e }; @@ -5955,7 +13478,11 @@ static int SetReqAttrib(byte* output, char* pw, int extSz) if (pw && pw[0]) { pwSz = (int)XSTRLEN(pw); - cpStrSz = SetUTF8String(pwSz, cpStr); + if (pwPrintableString) { + cpStrSz = SetPrintableString(pwSz, cpStr); + } else { + cpStrSz = SetUTF8String(pwSz, cpStr); + } cpSetSz = SetSet(cpStrSz + pwSz, cpSet); cpSeqSz = SetSequence(sizeof(cpOid) + cpSetSz + cpStrSz + pwSz, cpSeq); cpSz = cpSeqSz + sizeof(cpOid) + cpSetSz + cpStrSz + pwSz; @@ -5998,10 +13525,21 @@ 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, + ed448_key* ed448Key) { (void)eccKey; + (void)ed25519Key; + (void)ed448Key; + + if (cert == NULL || der == NULL) + return BAD_FUNC_ARG; + + if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL && + ed448Key == NULL) { + return PUBLIC_KEY_E; + } /* init */ XMEMSET(der, 0, sizeof(DerCert)); @@ -6010,51 +13548,163 @@ static int EncodeCertReq(Cert* cert, DerCert* der, der->versionSz = SetMyVersion(cert->version, der->version, FALSE); /* subject name */ - der->subjectSz = SetName(der->subject, &cert->subject); - if (der->subjectSz == 0) + der->subjectSz = SetName(der->subject, sizeof(der->subject), &cert->subject); + if (der->subjectSz <= 0) 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); - if (der->publicKeySz <= 0) - return PUBLIC_KEY_E; + der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey, + sizeof(der->publicKey), 1); } +#endif #ifdef HAVE_ECC if (cert->keyType == ECC_KEY) { - if (eccKey == NULL) - return PUBLIC_KEY_E; - der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey); - if (der->publicKeySz <= 0) - return PUBLIC_KEY_E; + der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1); } -#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_ED448 + if (cert->keyType == ED448_KEY) { + if (ed448Key == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEd448PublicKey(der->publicKey, ed448Key, 1); + } +#endif + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; + + /* set the extensions */ + der->extensionsSz = 0; /* CA */ if (cert->isCA) { - der->caSz = SetCa(der->ca); - if (der->caSz == 0) + der->caSz = SetCa(der->ca, sizeof(der->ca)); + if (der->caSz <= 0) return CA_TRUE_E; + + der->extensionsSz += der->caSz; } else der->caSz = 0; - /* extensions, just CA now */ - if (cert->isCA) { - der->extensionsSz = SetExtensions(der->extensions, - der->ca, der->caSz, FALSE); - if (der->extensionsSz == 0) - return EXTENSIONS_E; +#ifdef WOLFSSL_CERT_EXT + /* SKID */ + if (cert->skidSz) { + /* check the provided SKID size */ + if (cert->skidSz > (int)min(CTC_MAX_SKID_SIZE, sizeof(der->skid))) + return SKID_E; + + der->skidSz = SetSKID(der->skid, sizeof(der->skid), + cert->skid, cert->skidSz); + if (der->skidSz <= 0) + return SKID_E; + + der->extensionsSz += der->skidSz; } else - der->extensionsSz = 0; + der->skidSz = 0; - der->attribSz = SetReqAttrib(der->attrib, - cert->challengePw, der->extensionsSz); - if (der->attribSz == 0) + /* Key Usage */ + if (cert->keyUsage != 0){ + der->keyUsageSz = SetKeyUsage(der->keyUsage, sizeof(der->keyUsage), + cert->keyUsage); + if (der->keyUsageSz <= 0) + return KEYUSAGE_E; + + der->extensionsSz += der->keyUsageSz; + } + else + der->keyUsageSz = 0; + + /* Extended Key Usage */ + if (cert->extKeyUsage != 0){ + der->extKeyUsageSz = SetExtKeyUsage(cert, 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 */ + if (der->extensionsSz > 0) { + int ret; + + /* put the start of sequence (ID, Size) */ + der->extensionsSz = SetSequence(der->extensionsSz, der->extensions); + if (der->extensionsSz <= 0) + return EXTENSIONS_E; + + /* put CA */ + if (der->caSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->ca, der->caSz); + if (ret <= 0) + return EXTENSIONS_E; + } + +#ifdef WOLFSSL_CERT_EXT + /* put SKID */ + if (der->skidSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->skid, der->skidSz); + if (ret <= 0) + return EXTENSIONS_E; + } + + /* put AKID */ + if (der->akidSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->akid, der->akidSz); + if (ret <= 0) + return EXTENSIONS_E; + } + + /* put KeyUsage */ + if (der->keyUsageSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->keyUsage, der->keyUsageSz); + if (ret <= 0) + 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 */ + } + + der->attribSz = SetReqAttrib(der->attrib, cert->challengePw, + cert->challengePwPrintableString, + der->extensionsSz); + if (der->attribSz <= 0) return REQ_ATTRIBUTE_E; der->total = der->versionSz + der->subjectSz + der->publicKeySz + @@ -6065,28 +13715,33 @@ static int EncodeCertReq(Cert* cert, DerCert* der, /* write DER encoded cert req to buffer, size already checked */ -static int WriteCertReqBody(DerCert* der, byte* buffer) +static int WriteCertReqBody(DerCert* der, byte* buf) { int idx; /* signed part header */ - idx = SetSequence(der->total, buffer); + idx = SetSequence(der->total, buf); /* version */ - XMEMCPY(buffer + idx, der->version, der->versionSz); + if (buf) + XMEMCPY(buf + idx, der->version, der->versionSz); idx += der->versionSz; /* subject */ - XMEMCPY(buffer + idx, der->subject, der->subjectSz); + if (buf) + XMEMCPY(buf + idx, der->subject, der->subjectSz); idx += der->subjectSz; /* public key */ - XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz); + if (buf) + XMEMCPY(buf + idx, der->publicKey, der->publicKeySz); idx += der->publicKeySz; /* attributes */ - XMEMCPY(buffer + idx, der->attrib, der->attribSz); + if (buf) + XMEMCPY(buf + idx, der->attrib, der->attribSz); idx += der->attribSz; /* extensions */ if (der->extensionsSz) { - XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz, - sizeof(der->extensions))); + if (buf) + XMEMCPY(buf + idx, der->extensions, min(der->extensionsSz, + (int)sizeof(der->extensions))); idx += der->extensionsSz; } @@ -6094,8 +13749,9 @@ 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, + ed448_key* ed448Key) { int ret; #ifdef WOLFSSL_SMALL_STACK @@ -6104,15 +13760,17 @@ 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 : + (ed448Key ? ED448_KEY: RSA_KEY)); #ifdef WOLFSSL_SMALL_STACK - der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER); + der = (DerCert*)XMALLOC(sizeof(DerCert), cert->heap, + DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) return MEMORY_E; #endif - ret = EncodeCertReq(cert, der, rsaKey, eccKey); + ret = EncodeCertReq(cert, der, rsaKey, eccKey, ed25519Key, ed448Key); if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) @@ -6122,100 +13780,669 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, } #ifdef WOLFSSL_SMALL_STACK - XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(der, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif 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; + ed448_key* ed448Key = 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; + else if (keyType == ED448_TYPE) + ed448Key = (ed448_key*)key; + + return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, ed25519Key, + ed448Key); +} + +int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, + RsaKey* rsaKey, ecc_key* eccKey) +{ + return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, NULL, NULL); +} #endif /* WOLFSSL_CERT_REQ */ -int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, - RsaKey* rsaKey, ecc_key* eccKey, RNG* rng) +static int SignCert(int requestSz, int sType, byte* buf, word32 buffSz, + RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key, + ed448_key* ed448Key, WC_RNG* rng) { - int sigSz; -#ifdef WOLFSSL_SMALL_STACK - byte* sig; + int sigSz = 0; + void* heap = NULL; + CertSignCtx* certSignCtx; +#ifndef WOLFSSL_ASYNC_CRYPT + CertSignCtx certSignCtx_lcl; + + certSignCtx = &certSignCtx_lcl; + XMEMSET(certSignCtx, 0, sizeof(CertSignCtx)); #else - byte sig[MAX_ENCODED_SIG_SZ]; + certSignCtx = NULL; #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, buf, requestSz, certSignCtx->sig, + MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, ed448Key, rng, sType, + heap); +#ifdef WOLFSSL_ASYNC_CRYPT + if (sigSz == WC_PENDING_E) { + /* Not free'ing certSignCtx->sig here because it could still be in use + * with async operations. */ + return sigSz; + } +#endif 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(buf, 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_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng) +int wc_SignCert_ex(int requestSz, int sType, byte* buf, word32 buffSz, + int keyType, void* key, WC_RNG* rng) { - int ret = wc_MakeCert(cert, buffer, buffSz, key, NULL, rng); + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + ed448_key* ed448Key = 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; + else if (keyType == ED448_TYPE) + ed448Key = (ed448_key*)key; + + return SignCert(requestSz, sType, buf, buffSz, rsaKey, eccKey, ed25519Key, + ed448Key, rng); +} + +int wc_SignCert(int requestSz, int sType, byte* buf, word32 buffSz, + RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) +{ + return SignCert(requestSz, sType, buf, buffSz, rsaKey, eccKey, NULL, NULL, + rng); +} + +int wc_MakeSelfCert(Cert* cert, byte* buf, word32 buffSz, + RsaKey* key, WC_RNG* rng) +{ + int ret; + + ret = wc_MakeCert(cert, buf, buffSz, key, NULL, rng); if (ret < 0) return ret; - return wc_SignCert(cert->bodySz, cert->sigType, buffer, buffSz, key, NULL,rng); + return wc_SignCert(cert->bodySz, cert->sigType, + buf, buffSz, key, NULL, rng); } -#ifdef WOLFSSL_ALT_NAMES +#ifdef WOLFSSL_CERT_EXT -/* Set Alt Names from der cert, return 0 on success */ -static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) +/* Get raw subject from cert, which may contain OIDs not parsed by Decode. + The raw subject pointer will only be valid while "cert" is valid. */ +int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert) { - int ret; -#ifdef WOLFSSL_SMALL_STACK - DecodedCert* decoded; -#else - DecodedCert decoded[1]; -#endif - - if (derSz < 0) - return derSz; - -#ifdef WOLFSSL_SMALL_STACK - decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (decoded == NULL) - return MEMORY_E; -#endif - - InitDecodedCert(decoded, (byte*)der, derSz, 0); - ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); - - if (ret < 0) { - WOLFSSL_MSG("ParseCertRelative error"); + int rc = BAD_FUNC_ARG; + if ((subjectRaw != NULL) && (cert != NULL)) { + *subjectRaw = cert->sbjRaw; + rc = 0; } - else if (decoded->extensions) { - byte b; + return rc; +} + +/* Set KID from public key */ +static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, + byte *ntruKey, word16 ntruKeySz, + ed25519_key* ed25519Key, ed448_key* ed448Key, + int kid_type) +{ + byte *buf; + int bufferSz, ret; + + if (cert == NULL || + (rsakey == NULL && eckey == NULL && ntruKey == NULL && + ed25519Key == NULL && ed448Key == NULL) || + (kid_type != SKID_TYPE && kid_type != AKID_TYPE)) + return BAD_FUNC_ARG; + + buf = (byte *)XMALLOC(MAX_PUBLIC_KEY_SZ, cert->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) + return MEMORY_E; + + /* Public Key */ + bufferSz = -1; +#ifndef NO_RSA + /* RSA public key */ + if (rsakey != NULL) + bufferSz = SetRsaPublicKey(buf, rsakey, MAX_PUBLIC_KEY_SZ, 0); +#endif +#ifdef HAVE_ECC + /* ECC public key */ + if (eckey != NULL) + bufferSz = SetEccPublicKey(buf, eckey, 0); +#endif +#ifdef HAVE_NTRU + /* NTRU public key */ + if (ntruKey != NULL) { + bufferSz = MAX_PUBLIC_KEY_SZ; + ret = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( + ntruKeySz, ntruKey, (word16 *)(&bufferSz), buf); + if (ret != NTRU_OK) + bufferSz = -1; + } +#else + (void)ntruKeySz; +#endif +#ifdef HAVE_ED25519 + /* ED25519 public key */ + if (ed25519Key != NULL) + bufferSz = SetEd25519PublicKey(buf, ed25519Key, 0); +#endif +#ifdef HAVE_ED448 + /* ED448 public key */ + if (ed448Key != NULL) + bufferSz = SetEd448PublicKey(buffer, ed448Key, 0); +#endif + + if (bufferSz <= 0) { + XFREE(buf, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + return PUBLIC_KEY_E; + } + + /* Compute SKID by hashing public key */ + if (kid_type == SKID_TYPE) { + ret = CalcHashId(buf, bufferSz, cert->skid); + cert->skidSz = KEYID_SIZE; + } + else if (kid_type == AKID_TYPE) { + ret = CalcHashId(buf, bufferSz, cert->akid); + cert->akidSz = KEYID_SIZE; + } + else + ret = BAD_FUNC_ARG; + + XFREE(buf, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + +int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + ed448_key* ed448Key = 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; + else if (keyType == ED448_TYPE) + ed448Key = (ed448_key*)key; + + return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key, + ed448Key, 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, NULL, NULL, + SKID_TYPE); +} + +#ifdef HAVE_NTRU +/* Set SKID from NTRU public key */ +int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, + byte *ntruKey, word16 ntruKeySz) +{ + return SetKeyIdFromPublicKey(cert, NULL,NULL,ntruKey, ntruKeySz, NULL, 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; + ed448_key* ed448Key = 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; + else if (keyType == ED448_TYPE) + ed448Key = (ed448_key*)key; + + return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key, + ed448Key, 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, NULL, NULL, + AKID_TYPE); +} + + +#if !defined(NO_FILESYSTEM) && !defined(NO_ASN_CRYPT) + +/* Set SKID from public key file in PEM */ +int wc_SetSubjectKeyId(Cert *cert, const char* file) +{ + int ret, derSz; + byte* der; + word32 idx; + RsaKey *rsakey = NULL; + ecc_key *eckey = NULL; + + if (cert == NULL || file == NULL) + return BAD_FUNC_ARG; + + der = (byte*)XMALLOC(MAX_PUBLIC_KEY_SZ, cert->heap, DYNAMIC_TYPE_CERT); + if (der == NULL) { + WOLFSSL_MSG("wc_SetSubjectKeyId memory Problem"); + return MEMORY_E; + } + derSz = MAX_PUBLIC_KEY_SZ; + + XMEMSET(der, 0, derSz); + derSz = wc_PemPubKeyToDer(file, der, derSz); + if (derSz <= 0) { + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return derSz; + } + + /* 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); + return MEMORY_E; + } + + if (wc_InitRsaKey(rsakey, cert->heap) != 0) { + WOLFSSL_MSG("wc_InitRsaKey failure"); + XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return MEMORY_E; + } + + idx = 0; + ret = wc_RsaPublicKeyDecode(der, &idx, rsakey, derSz); + 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, + DYNAMIC_TYPE_ECC); + if (eckey == NULL) { + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return MEMORY_E; + } + + if (wc_ecc_init(eckey) != 0) { + WOLFSSL_MSG("wc_ecc_init failure"); + wc_ecc_free(eckey); + XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return MEMORY_E; + } + + idx = 0; + ret = wc_EccPublicKeyDecode(der, &idx, eckey, derSz); + if (ret != 0) { + WOLFSSL_MSG("wc_EccPublicKeyDecode failed"); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + wc_ecc_free(eckey); + XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC); + return PUBLIC_KEY_E; + } +#else + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return PUBLIC_KEY_E; +#endif /* HAVE_ECC */ + } + + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + + 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); +#endif + return ret; +} + +#endif /* !NO_FILESYSTEM && !NO_ASN_CRYPT */ + +static int SetAuthKeyIdFromDcert(Cert* cert, DecodedCert* decoded) +{ + int ret = 0; + + /* Subject Key Id not found !! */ + if (decoded->extSubjKeyIdSet == 0) { + ret = ASN_NO_SKID; + } + + /* SKID invalid size */ + else if (sizeof(cert->akid) < sizeof(decoded->extSubjKeyId)) { + ret = MEMORY_E; + } + + else { + /* Put the SKID of CA to AKID of certificate */ + XMEMCPY(cert->akid, decoded->extSubjKeyId, KEYID_SIZE); + cert->akidSz = KEYID_SIZE; + } + + return ret; +} + +/* Set AKID from certificate contains in buffer (DER encoded) */ +int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + ret = SetAuthKeyIdFromDcert(cert, (DecodedCert*)cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return ret; +} + + +#ifndef NO_FILESYSTEM + +/* Set AKID from certificate file in PEM */ +int wc_SetAuthKeyId(Cert *cert, const char* file) +{ + int ret; + int derSz; + byte* der; + + if (cert == NULL || file == NULL) + return BAD_FUNC_ARG; + + der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT); + if (der == NULL) { + WOLFSSL_MSG("wc_SetAuthKeyId OOF Problem"); + return MEMORY_E; + } + + derSz = wc_PemCertToDer(file, der, EIGHTK_BUF); + if (derSz <= 0) + { + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return derSz; + } + + ret = wc_SetAuthKeyIdFromCert(cert, der, derSz); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + + return ret; +} + +#endif /* !NO_FILESYSTEM */ + +/* Set KeyUsage from human readable string */ +int wc_SetKeyUsage(Cert *cert, const char *value) +{ + int ret = 0; + char *token, *str, *ptr; + word32 len; + + if (cert == NULL || value == NULL) + return BAD_FUNC_ARG; + + cert->keyUsage = 0; + + /* duplicate string (including terminator) */ + len = (word32)XSTRLEN(value); + str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) + return MEMORY_E; + XMEMCPY(str, value, len+1); + + /* parse value, and set corresponding Key Usage value */ + if ((token = XSTRTOK(str, ",", &ptr)) == NULL) { + XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + return KEYUSAGE_E; + } + while (token != NULL) + { + len = (word32)XSTRLEN(token); + + if (!XSTRNCASECMP(token, "digitalSignature", len)) + cert->keyUsage |= KEYUSE_DIGITAL_SIG; + else if (!XSTRNCASECMP(token, "nonRepudiation", len) || + !XSTRNCASECMP(token, "contentCommitment", len)) + cert->keyUsage |= KEYUSE_CONTENT_COMMIT; + else if (!XSTRNCASECMP(token, "keyEncipherment", len)) + cert->keyUsage |= KEYUSE_KEY_ENCIPHER; + else if (!XSTRNCASECMP(token, "dataEncipherment", len)) + cert->keyUsage |= KEYUSE_DATA_ENCIPHER; + else if (!XSTRNCASECMP(token, "keyAgreement", len)) + cert->keyUsage |= KEYUSE_KEY_AGREE; + else if (!XSTRNCASECMP(token, "keyCertSign", len)) + cert->keyUsage |= KEYUSE_KEY_CERT_SIGN; + else if (!XSTRNCASECMP(token, "cRLSign", len)) + cert->keyUsage |= KEYUSE_CRL_SIGN; + else if (!XSTRNCASECMP(token, "encipherOnly", len)) + cert->keyUsage |= KEYUSE_ENCIPHER_ONLY; + else if (!XSTRNCASECMP(token, "decipherOnly", len)) + cert->keyUsage |= KEYUSE_DECIPHER_ONLY; + else { + ret = KEYUSAGE_E; + break; + } + + token = XSTRTOK(NULL, ",", &ptr); + } + + XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + 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; + + /* duplicate string (including terminator) */ + len = (word32)XSTRLEN(value); + str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) + return MEMORY_E; + XMEMCPY(str, value, len+1); + + /* 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; +} + +#ifdef WOLFSSL_EKU_OID +/* + * cert structure to set EKU oid in + * oid the oid in byte representation + * sz size of oid buffer + * idx index of array to place oid + * + * returns 0 on success + */ +int wc_SetExtKeyUsageOID(Cert *cert, const char *in, word32 sz, byte idx, + void* heap) +{ + byte oid[MAX_OID_SZ]; + word32 oidSz = MAX_OID_SZ; + + if (idx >= CTC_MAX_EKU_NB || sz >= CTC_MAX_EKU_OID_SZ) { + WOLFSSL_MSG("Either idx or sz was too large"); + return BAD_FUNC_ARG; + } + + if (EncodePolicyOID(oid, &oidSz, in, heap) != 0) { + return BUFFER_E; + } + + XMEMCPY(cert->extKeyUsageOID[idx], oid, oidSz); + cert->extKeyUsageOIDSz[idx] = oidSz; + cert->extKeyUsage |= EXTKEYUSE_USER; + + return 0; +} +#endif /* WOLFSSL_EKU_OID */ +#endif /* WOLFSSL_CERT_EXT */ + + +#ifdef WOLFSSL_ALT_NAMES + +static int SetAltNamesFromDcert(Cert* cert, DecodedCert* decoded) +{ + int ret = 0; + byte tag; + + if (decoded->extensions) { int length; word32 maxExtensionsIdx; decoded->srcIdx = decoded->extensionsIdx; - b = decoded->source[decoded->srcIdx++]; - - if (b != ASN_EXTENSIONS) { + if (GetASNTag(decoded->source, &decoded->srcIdx, &tag, decoded->maxIdx) + != 0) { + return ASN_PARSE_E; + } + + if (tag != ASN_EXTENSIONS) { ret = ASN_PARSE_E; } else if (GetLength(decoded->source, &decoded->srcIdx, &length, @@ -6244,7 +14471,7 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) decoded->srcIdx = startIdx; if (GetAlgoId(decoded->source, &decoded->srcIdx, &oid, - decoded->maxIdx) < 0) { + oidCertExtType, decoded->maxIdx) < 0) { ret = ASN_PARSE_E; break; } @@ -6267,17 +14494,13 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) } } - FreeDecodedCert(decoded); -#ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret < 0 ? ret : 0; + return ret; } +#ifndef NO_FILESYSTEM -/* Set Dates from der cert, return 0 on success */ -static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) +/* Set Alt Names from der cert, return 0 on success */ +static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) { int ret; #ifdef WOLFSSL_SMALL_STACK @@ -6286,28 +14509,45 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) DecodedCert decoded[1]; #endif - WOLFSSL_ENTER("SetDatesFromCert"); if (derSz < 0) return derSz; - + #ifdef WOLFSSL_SMALL_STACK - decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cert->heap, DYNAMIC_TYPE_TMP_BUFFER); if (decoded == NULL) return MEMORY_E; #endif - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, der, derSz, NULL); ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { WOLFSSL_MSG("ParseCertRelative error"); } - else if (decoded->beforeDate == NULL || decoded->afterDate == NULL) { + else { + ret = SetAltNamesFromDcert(cert, decoded); + } + + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret < 0 ? ret : 0; +} + +#endif + +static int SetDatesFromDcert(Cert* cert, DecodedCert* decoded) +{ + int ret = 0; + + if (decoded->beforeDate == NULL || decoded->afterDate == NULL) { WOLFSSL_MSG("Couldn't extract dates"); ret = -1; } - else if (decoded->beforeDateLen > MAX_DATE_SIZE || + else if (decoded->beforeDateLen > MAX_DATE_SIZE || decoded->afterDateLen > MAX_DATE_SIZE) { WOLFSSL_MSG("Bad date size"); ret = -1; @@ -6320,23 +14560,108 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) cert->afterDateSz = decoded->afterDateLen; } - FreeDecodedCert(decoded); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret < 0 ? ret : 0; + return ret; } +#endif /* WOLFSSL_ALT_NAMES */ -#endif /* WOLFSSL_ALT_NAMES && !NO_RSA */ +static void SetNameFromDcert(CertName* cn, DecodedCert* decoded) +{ + int sz; + if (decoded->subjectCN) { + sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->commonName, decoded->subjectCN, sz); + cn->commonName[sz] = '\0'; + cn->commonNameEnc = decoded->subjectCNEnc; + } + if (decoded->subjectC) { + sz = (decoded->subjectCLen < CTC_NAME_SIZE) ? decoded->subjectCLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->country, decoded->subjectC, sz); + cn->country[sz] = '\0'; + cn->countryEnc = decoded->subjectCEnc; + } + if (decoded->subjectST) { + sz = (decoded->subjectSTLen < CTC_NAME_SIZE) ? decoded->subjectSTLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->state, decoded->subjectST, sz); + cn->state[sz] = '\0'; + cn->stateEnc = decoded->subjectSTEnc; + } + if (decoded->subjectL) { + sz = (decoded->subjectLLen < CTC_NAME_SIZE) ? decoded->subjectLLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->locality, decoded->subjectL, sz); + cn->locality[sz] = '\0'; + cn->localityEnc = decoded->subjectLEnc; + } + if (decoded->subjectO) { + sz = (decoded->subjectOLen < CTC_NAME_SIZE) ? decoded->subjectOLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->org, decoded->subjectO, sz); + cn->org[sz] = '\0'; + cn->orgEnc = decoded->subjectOEnc; + } + if (decoded->subjectOU) { + sz = (decoded->subjectOULen < CTC_NAME_SIZE) ? decoded->subjectOULen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->unit, decoded->subjectOU, sz); + cn->unit[sz] = '\0'; + cn->unitEnc = decoded->subjectOUEnc; + } + if (decoded->subjectSN) { + sz = (decoded->subjectSNLen < CTC_NAME_SIZE) ? decoded->subjectSNLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->sur, decoded->subjectSN, sz); + cn->sur[sz] = '\0'; + cn->surEnc = decoded->subjectSNEnc; + } + if (decoded->subjectSND) { + sz = (decoded->subjectSNDLen < CTC_NAME_SIZE) ? decoded->subjectSNDLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->serialDev, decoded->subjectSND, sz); + cn->serialDev[sz] = '\0'; + cn->serialDevEnc = decoded->subjectSNDEnc; + } +#ifdef WOLFSSL_CERT_EXT + if (decoded->subjectBC) { + sz = (decoded->subjectBCLen < CTC_NAME_SIZE) ? decoded->subjectBCLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->busCat, decoded->subjectBC, sz); + cn->busCat[sz] = '\0'; + cn->busCatEnc = decoded->subjectBCEnc; + } + if (decoded->subjectJC) { + sz = (decoded->subjectJCLen < CTC_NAME_SIZE) ? decoded->subjectJCLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->joiC, decoded->subjectJC, sz); + cn->joiC[sz] = '\0'; + cn->joiCEnc = decoded->subjectJCEnc; + } + if (decoded->subjectJS) { + sz = (decoded->subjectJSLen < CTC_NAME_SIZE) ? decoded->subjectJSLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->joiSt, decoded->subjectJS, sz); + cn->joiSt[sz] = '\0'; + cn->joiStEnc = decoded->subjectJSEnc; + } +#endif + if (decoded->subjectEmail) { + sz = (decoded->subjectEmailLen < CTC_NAME_SIZE) + ? decoded->subjectEmailLen : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->email, decoded->subjectEmail, sz); + cn->email[sz] = '\0'; + } +} + +#ifndef NO_FILESYSTEM /* Set cn name from der buffer, return 0 on success */ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) { - int ret, sz; + int ret; #ifdef WOLFSSL_SMALL_STACK DecodedCert* decoded; #else @@ -6353,68 +14678,14 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) return MEMORY_E; #endif - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, der, derSz, NULL); ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { WOLFSSL_MSG("ParseCertRelative error"); } else { - if (decoded->subjectCN) { - sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen - : CTC_NAME_SIZE - 1; - strncpy(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); - 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); - 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); - 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); - 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); - 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); - 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); - cn->email[sz] = 0; - } + SetNameFromDcert(cn, decoded); } FreeDecodedCert(decoded); @@ -6426,24 +14697,26 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) return ret < 0 ? ret : 0; } - -#ifndef NO_FILESYSTEM - /* Set cert issuer from issuerFile in PEM */ int wc_SetIssuer(Cert* cert, const char* issuerFile) { int ret; int derSz; - byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT); + byte* der; + if (cert == NULL) { + return BAD_FUNC_ARG; + } + + der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT); if (der == NULL) { WOLFSSL_MSG("wc_SetIssuer OOF Problem"); return MEMORY_E; } - derSz = wolfSSL_PemCertToDer(issuerFile, der, EIGHTK_BUF); + derSz = wc_PemCertToDer(issuerFile, der, EIGHTK_BUF); cert->selfSigned = 0; ret = SetNameFromCert(&cert->issuer, der, derSz); - XFREE(der, NULL, DYNAMIC_TYPE_CERT); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); return ret; } @@ -6454,77 +14727,367 @@ int wc_SetSubject(Cert* cert, const char* subjectFile) { int ret; int derSz; - byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT); + byte* der; + if (cert == NULL) { + return BAD_FUNC_ARG; + } + + der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT); if (der == NULL) { WOLFSSL_MSG("wc_SetSubject OOF Problem"); return MEMORY_E; } - derSz = wolfSSL_PemCertToDer(subjectFile, der, EIGHTK_BUF); + + derSz = wc_PemCertToDer(subjectFile, der, EIGHTK_BUF); ret = SetNameFromCert(&cert->subject, der, derSz); - XFREE(der, NULL, DYNAMIC_TYPE_CERT); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); return ret; } - #ifdef WOLFSSL_ALT_NAMES -/* Set atl names from file in PEM */ +/* Set alt names from file in PEM */ int wc_SetAltNames(Cert* cert, const char* file) { int ret; int derSz; - byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT); + byte* der; + if (cert == NULL) { + return BAD_FUNC_ARG; + } + + der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT); if (der == NULL) { WOLFSSL_MSG("wc_SetAltNames OOF Problem"); return MEMORY_E; } - derSz = wolfSSL_PemCertToDer(file, der, EIGHTK_BUF); + derSz = wc_PemCertToDer(file, der, EIGHTK_BUF); ret = SetAltNamesFromCert(cert, der, derSz); - XFREE(der, NULL, DYNAMIC_TYPE_CERT); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); return ret; } #endif /* WOLFSSL_ALT_NAMES */ -#endif /* NO_FILESYSTEM */ +#endif /* !NO_FILESYSTEM */ /* Set cert issuer from DER buffer */ int wc_SetIssuerBuffer(Cert* cert, const byte* der, int derSz) { - cert->selfSigned = 0; - return SetNameFromCert(&cert->issuer, der, derSz); -} + int ret = 0; + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + cert->selfSigned = 0; + + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + SetNameFromDcert(&cert->issuer, (DecodedCert*)cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return ret; +} /* Set cert subject from DER buffer */ int wc_SetSubjectBuffer(Cert* cert, const byte* der, int derSz) { - return SetNameFromCert(&cert->subject, der, derSz); + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + SetNameFromDcert(&cert->subject, (DecodedCert*)cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return ret; +} +#ifdef WOLFSSL_CERT_EXT +/* Set cert raw subject from DER buffer */ +int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + if ((((DecodedCert*)cert->decodedCert)->subjectRaw) && + (((DecodedCert*)cert->decodedCert)->subjectRawLen <= + (int)sizeof(CertName))) { + XMEMCPY(cert->sbjRaw, + ((DecodedCert*)cert->decodedCert)->subjectRaw, + ((DecodedCert*)cert->decodedCert)->subjectRawLen); + } +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return ret; } +/* Set cert raw issuer from DER buffer */ +int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + if ((((DecodedCert*)cert->decodedCert)->issuerRaw) && + (((DecodedCert*)cert->decodedCert)->issuerRawLen <= + (int)sizeof(CertName))) { + XMEMCPY(cert->issRaw, + ((DecodedCert*)cert->decodedCert)->issuerRaw, + ((DecodedCert*)cert->decodedCert)->issuerRawLen); + } +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + return ret; +} +#endif #ifdef WOLFSSL_ALT_NAMES /* Set cert alt names from DER buffer */ int wc_SetAltNamesBuffer(Cert* cert, const byte* der, int derSz) { - return SetAltNamesFromCert(cert, der, derSz); + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + ret = SetAltNamesFromDcert(cert, (DecodedCert*)cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return(ret); } /* Set cert dates from DER buffer */ int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz) { - return SetDatesFromCert(cert, der, derSz); + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + ret = SetDatesFromDcert(cert, (DecodedCert*)cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return(ret); } #endif /* WOLFSSL_ALT_NAMES */ #endif /* WOLFSSL_CERT_GEN */ +#if (defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT)) \ + || defined(OPENSSL_EXTRA) +/* Encode OID string representation to ITU-T X.690 format */ +int EncodePolicyOID(byte *out, word32 *outSz, const char *in, void* heap) +{ + word32 val, idx = 0, nb_val; + char *token, *str, *ptr; + word32 len; + + (void)heap; + + if (out == NULL || outSz == NULL || *outSz < 2 || in == NULL) + return BAD_FUNC_ARG; + + /* duplicate string (including terminator) */ + len = (word32)XSTRLEN(in); + str = (char *)XMALLOC(len+1, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) + return MEMORY_E; + XMEMCPY(str, in, len+1); + + nb_val = 0; + + /* parse value, and set corresponding Policy OID value */ + token = XSTRTOK(str, ".", &ptr); + while (token != NULL) + { + val = (word32)XATOI(token); + + if (nb_val == 0) { + if (val > 2) { + XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER); + return ASN_OBJECT_ID_E; + } + + out[idx] = (byte)(40 * val); + } + else if (nb_val == 1) { + if (val > 127) { + XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER); + return ASN_OBJECT_ID_E; + } + + if (idx > *outSz) { + XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER); + return BUFFER_E; + } + + out[idx++] += (byte)val; + } + else { + word32 tb = 0, x; + int i = 0; + byte oid[MAX_OID_SZ]; + + while (val >= 128) { + x = val % 128; + val /= 128; + oid[i++] = (byte) (((tb++) ? 0x80 : 0) | x); + } + + if ((idx+(word32)i) > *outSz) { + XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER); + return BUFFER_E; + } + + oid[i] = (byte) (((tb++) ? 0x80 : 0) | val); + + /* push value in the right order */ + while (i >= 0) + out[idx++] = oid[i--]; + } + + token = XSTRTOK(NULL, ".", &ptr); + nb_val++; + } + + *outSz = idx; + + XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER); + return 0; +} +#endif /* WOLFSSL_CERT_EXT || OPENSSL_EXTRA */ + +#endif /* !NO_CERTS */ + +#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) +/* Helper function for wolfSSL_i2d_DHparams */ +int StoreDHparams(byte* out, word32* outLen, mp_int* p, mp_int* g) +{ + word32 idx = 0; + int pSz; + int gSz; + unsigned int tmp; + word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */ + + /* If the leading bit on the INTEGER is a 1, add a leading zero */ + int pLeadingZero = mp_leading_bit(p); + int gLeadingZero = mp_leading_bit(g); + int pLen = mp_unsigned_bin_size(p); + int gLen = mp_unsigned_bin_size(g); + + WOLFSSL_ENTER("StoreDHparams"); + if (out == NULL) { + WOLFSSL_MSG("Null buffer error"); + return BUFFER_E; + } + + tmp = pLeadingZero + gLeadingZero + pLen + gLen; + if (*outLen < (tmp + headerSz)) { + return BUFFER_E; + } + + /* Set sequence */ + idx = SetSequence(tmp + headerSz + 2, out); + + /* Encode p */ + pSz = SetASNIntMP(p, -1, &out[idx]); + if (pSz < 0) { + WOLFSSL_MSG("SetASNIntMP failed"); + return pSz; + } + idx += pSz; + + /* Encode g */ + gSz = SetASNIntMP(g, -1, &out[idx]); + if (gSz < 0) { + WOLFSSL_MSG("SetASNIntMP failed"); + return gSz; + } + idx += gSz; + + *outLen = idx; + + return 0; +} +#endif /* !NO_DH && WOLFSSL_QT || OPENSSL_ALL */ #ifdef HAVE_ECC @@ -6532,8 +15095,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 */ @@ -6541,33 +15104,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 BAD_FUNC_ARG; + 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; @@ -6575,23 +15129,35 @@ int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s) } -/* Der Decode ECC-DSA Signautre, r & s stored as big ints */ +/* Der Decode ECC-DSA Signature, r & s stored as big ints */ 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)) +#ifndef NO_STRICT_ECDSA_LEN + /* enable strict length checking for signature */ + if (sigLen != idx + (word32)len) { return ASN_ECC_KEY_E; + } +#else + /* allow extra signature bytes at end */ + if ((word32)len > (sigLen - idx)) { + return ASN_ECC_KEY_E; + } +#endif - 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; } @@ -6600,18 +15166,20 @@ 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 oid = 0; + word32 oidSum; int version, length; - int privSz, pubSz; + int privSz, pubSz = 0; byte b; int ret = 0; + int curve_id = ECC_CURVE_DEF; #ifdef WOLFSSL_SMALL_STACK byte* priv; byte* pub; #else - byte priv[ECC_MAXSIZE]; - byte pub[ECC_MAXSIZE * 2 + 1]; /* public key has two parts plus header */ + 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; @@ -6619,14 +15187,17 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; - if (GetMyVersion(input, inOutIdx, &version) < 0) + if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) + return ASN_PARSE_E; + + if (*inOutIdx >= inSz) return ASN_PARSE_E; b = input[*inOutIdx]; *inOutIdx += 1; /* priv type */ - if (b != 4 && b != 6 && b != 7) + if (b != 4 && b != 6 && b != 7) return ASN_PARSE_E; if (GetLength(input, inOutIdx, &length, inSz) < 0) @@ -6636,13 +15207,13 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, return BUFFER_E; #ifdef WOLFSSL_SMALL_STACK - priv = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + priv = (byte*)XMALLOC(ECC_MAXSIZE+1, key->heap, DYNAMIC_TYPE_TMP_BUFFER); if (priv == NULL) return MEMORY_E; - - pub = (byte*)XMALLOC(ECC_MAXSIZE * 2 + 1, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + pub = (byte*)XMALLOC(2*(ECC_MAXSIZE+1), key->heap, DYNAMIC_TYPE_TMP_BUFFER); if (pub == NULL) { - XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } #endif @@ -6652,36 +15223,30 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, XMEMCPY(priv, &input[*inOutIdx], privSz); *inOutIdx += length; - /* 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 ((*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--) { - oid += input[*inOutIdx]; - *inOutIdx += 1; + 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 (CheckCurve(oid) < 0) - ret = ECC_CURVE_OID_E; } } } - if (ret == 0) { + if (ret == 0 && (*inOutIdx + 1) < inSz) { /* prefix 1 */ b = input[*inOutIdx]; *inOutIdx += 1; @@ -6689,142 +15254,879 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, if (b != ECC_PREFIX_1) { ret = ASN_ECC_KEY_E; } - else if (GetLength(input, inOutIdx, &length, inSz) < 0) { + else if (GetLength(input, inOutIdx, &length, inSz) <= 0) { ret = ASN_PARSE_E; } 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 < (ECC_MAXSIZE*2 + 1)) { - XMEMCPY(pub, &input[*inOutIdx], pubSz); - *inOutIdx += length; - ret = wc_ecc_import_private_key(priv, privSz, pub, pubSz, - key); - } 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); + XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } -#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) +#ifdef WOLFSSL_CUSTOM_CURVES +static void ByteToHex(byte n, char* str) { - byte curve[MAX_ALGO_SZ]; + const char hexChar[] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + str[0] = hexChar[n >> 4]; + str[1] = hexChar[n & 0xf]; +} + +/* returns 0 on success */ +static int ASNToHexString(const byte* input, word32* inOutIdx, char** out, + word32 inSz, void* heap, int heapType) +{ + int len; + int i; + char* str; + word32 localIdx; + byte tag; + + if (*inOutIdx >= inSz) { + return BUFFER_E; + } + + localIdx = *inOutIdx; + if (GetASNTag(input, &localIdx, &tag, inSz) == 0 && tag == ASN_INTEGER) { + if (GetASNInt(input, inOutIdx, &len, inSz) < 0) + return ASN_PARSE_E; + } + else { + if (GetOctetString(input, inOutIdx, &len, inSz) < 0) + return ASN_PARSE_E; + } + + str = (char*)XMALLOC(len * 2 + 1, heap, heapType); + for (i=0; i MAX_ECC_STRING) { + WOLFSSL_MSG("ECC Param too large for buffer"); + ret = BUFFER_E; + } + else { + XSTRNCPY(*dst, src, length); + } + XFREE(src, key->heap, DYNAMIC_TYPE_ECC_BUFFER); +#endif + + return ret; +} +#endif /* WOLFSSL_CUSTOM_CURVES */ + +int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, + ecc_key* key, word32 inSz) +{ + int length; + int ret; + int curve_id = ECC_CURVE_DEF; + word32 oidSum, localIdx; + byte tag; + + 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; + + if (*inOutIdx >= inSz) { + return BUFFER_E; + } + + localIdx = *inOutIdx; + if (GetASNTag(input, &localIdx, &tag, inSz) == 0 && + tag == (ASN_SEQUENCE | ASN_CONSTRUCTED)) { +#ifdef WOLFSSL_CUSTOM_CURVES + ecc_set_type* curve; + int len; + char* point = NULL; + + ret = 0; + + curve = (ecc_set_type*)XMALLOC(sizeof(*curve), key->heap, + DYNAMIC_TYPE_ECC_BUFFER); + if (curve == NULL) + ret = MEMORY_E; + + if (ret == 0) { + static const char customName[] = "Custom"; + XMEMSET(curve, 0, sizeof(*curve)); + #ifndef WOLFSSL_ECC_CURVE_STATIC + curve->name = customName; + #else + XMEMCPY((void*)curve->name, customName, sizeof(customName)); + #endif + curve->id = ECC_CURVE_CUSTOM; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + ret = ASN_PARSE_E; + } + + if (ret == 0) { + GetInteger7Bit(input, inOutIdx, inSz); + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + char* p = NULL; + SkipObjectId(input, inOutIdx, inSz); + ret = ASNToHexString(input, inOutIdx, &p, inSz, + key->heap, DYNAMIC_TYPE_ECC_BUFFER); + if (ret == 0) + ret = EccKeyParamCopy((char**)&curve->prime, p); + } + if (ret == 0) { + curve->size = (int)XSTRLEN(curve->prime) / 2; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + char* af = NULL; + ret = ASNToHexString(input, inOutIdx, &af, inSz, + key->heap, DYNAMIC_TYPE_ECC_BUFFER); + if (ret == 0) + ret = EccKeyParamCopy((char**)&curve->Af, af); + } + if (ret == 0) { + char* bf = NULL; + ret = ASNToHexString(input, inOutIdx, &bf, inSz, + key->heap, DYNAMIC_TYPE_ECC_BUFFER); + if (ret == 0) + ret = EccKeyParamCopy((char**)&curve->Bf, bf); + } + if (ret == 0) { + localIdx = *inOutIdx; + if (*inOutIdx < inSz && GetASNTag(input, &localIdx, &tag, inSz) + == 0 && tag == ASN_BIT_STRING) { + len = 0; + ret = GetASNHeader(input, ASN_BIT_STRING, inOutIdx, &len, inSz); + *inOutIdx += len; + } + } + if (ret == 0) { + ret = ASNToHexString(input, inOutIdx, (char**)&point, inSz, + key->heap, DYNAMIC_TYPE_ECC_BUFFER); + + /* sanity check that point buffer is not smaller than the expected + * size to hold ( 0 4 || Gx || Gy ) + * where Gx and Gy are each the size of curve->size * 2 */ + if (ret == 0 && (int)XSTRLEN(point) < (curve->size * 4) + 2) { + XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER); + ret = BUFFER_E; + } + } + if (ret == 0) { + #ifndef WOLFSSL_ECC_CURVE_STATIC + curve->Gx = (const char*)XMALLOC(curve->size * 2 + 2, key->heap, + DYNAMIC_TYPE_ECC_BUFFER); + curve->Gy = (const char*)XMALLOC(curve->size * 2 + 2, key->heap, + DYNAMIC_TYPE_ECC_BUFFER); + if (curve->Gx == NULL || curve->Gy == NULL) { + XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER); + ret = MEMORY_E; + } + #else + if (curve->size * 2 + 2 > MAX_ECC_STRING) { + WOLFSSL_MSG("curve size is too large to fit in buffer"); + ret = BUFFER_E; + } + #endif + } + if (ret == 0) { + char* o = NULL; + + XMEMCPY((char*)curve->Gx, point + 2, curve->size * 2); + XMEMCPY((char*)curve->Gy, point + curve->size * 2 + 2, + curve->size * 2); + ((char*)curve->Gx)[curve->size * 2] = '\0'; + ((char*)curve->Gy)[curve->size * 2] = '\0'; + XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER); + ret = ASNToHexString(input, inOutIdx, &o, inSz, + key->heap, DYNAMIC_TYPE_ECC_BUFFER); + if (ret == 0) + ret = EccKeyParamCopy((char**)&curve->order, o); + } + if (ret == 0) { + curve->cofactor = GetInteger7Bit(input, inOutIdx, inSz); + + #ifndef WOLFSSL_ECC_CURVE_STATIC + curve->oid = NULL; + #else + XMEMSET((void*)curve->oid, 0, sizeof(curve->oid)); + #endif + curve->oidSz = 0; + curve->oidSum = 0; + + if (wc_ecc_set_custom_curve(key, curve) < 0) { + ret = ASN_PARSE_E; + } + #ifdef WOLFSSL_CUSTOM_CURVES + key->deallocSet = 1; + #endif + curve = NULL; + } + if (curve != NULL) + wc_ecc_free_curve(curve, key->heap); + + if (ret < 0) + return ret; +#else + return ASN_PARSE_E; +#endif /* WOLFSSL_CUSTOM_CURVES */ + } + else { + /* ecc params information */ + ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, inSz); + if (ret != 0) + return ret; + + /* get curve id */ + curve_id = wc_ecc_get_oid(oidSum, NULL, 0); + if (curve_id < 0) + return ECC_CURVE_OID_E; + } + + /* key header */ + ret = CheckBitString(input, inOutIdx, &length, inSz, 1, NULL); + if (ret != 0) + return ret; + + /* This is the raw point data compressed or uncompressed. */ + if (wc_ecc_import_x963_ex(input + *inOutIdx, length, key, + curve_id) != 0) { + return ASN_ECC_KEY_E; + } + + *inOutIdx += length; + + return 0; +} + +#if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) +/* 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]; - int ret; - int curveSz; - int verSz; + 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; - int curveHdrSz = ASN_ECC_CONTEXT_SZ; - word32 seqSz; - word32 idx = 0; - word32 pubSz = ECC_BUFSIZE; - word32 privSz; - word32 totalSz; + + word32 idx = 0, prvidx = 0, pubidx = 0, curveidx = 0; + word32 seqSz, privSz, pubSz = ECC_BUFSIZE; if (key == NULL || output == NULL || inLen == 0) return BAD_FUNC_ARG; - ret = wc_ecc_export_x963(key, NULL, &pubSz); - if (ret != LENGTH_ONLY_E) { + /* curve */ + curve[curveidx++] = ECC_PREFIX_0; + curveidx++ /* to put the size after computation */; + curveSz = SetCurve(key, curve+curveidx); + if (curveSz < 0) + return curveSz; + /* set computed size */ + curve[1] = (byte)curveSz; + curveidx += curveSz; + + /* private */ + privSz = key->dp->size; + prv = (byte*)XMALLOC(privSz + privHdrSz + MAX_SEQ_SZ, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (prv == NULL) { + return MEMORY_E; + } + 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); return ret; } - curveSz = SetCurve(key, curve); - if (curveSz < 0) { - return curveSz; + prvidx += privSz; + + /* 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[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; } - privSz = key->dp->size; - + /* make headers */ verSz = SetMyVersion(1, ver, FALSE); - if (verSz < 0) { - return verSz; + seqSz = SetSequence(verSz + prvidx + pubidx + curveidx, seq); + + totalSz = prvidx + pubidx + curveidx + verSz + seqSz; + if (totalSz > (int)inLen) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pubIn) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + return BAD_FUNC_ARG; } - totalSz = verSz + privSz + privHdrSz + curveSz + curveHdrSz + - pubSz + pubHdrSz + 1; /* plus null byte b4 public */ - seqSz = SetSequence(totalSz, seq); - totalSz += seqSz; - - if (totalSz > inLen) { - return BUFFER_E; - } - - /* write it out */ + /* write out */ /* seq */ XMEMCPY(output + idx, seq, seqSz); - idx += seqSz; + idx = seqSz; - /* ver */ + /* ver */ XMEMCPY(output + idx, ver, verSz); idx += verSz; /* private */ - output[idx++] = ASN_OCTET_STRING; - output[idx++] = (byte)privSz; - ret = wc_ecc_export_private_only(key, output + idx, &privSz); - if (ret < 0) { - return ret; - } - idx += privSz; + XMEMCPY(output + idx, prv, prvidx); + idx += prvidx; + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); /* curve */ - output[idx++] = ECC_PREFIX_0; - output[idx++] = (byte)curveSz; - XMEMCPY(output + idx, curve, curveSz); - idx += curveSz; + XMEMCPY(output + idx, curve, curveidx); + idx += curveidx; - /* public */ - output[idx++] = ECC_PREFIX_1; - output[idx++] = (byte)pubSz + ASN_ECC_CONTEXT_SZ + 1; /* plus null byte */ - output[idx++] = ASN_BIT_STRING; - output[idx++] = (byte)pubSz + 1; /* plus null byte */ - output[idx++] = (byte)0; /* null byte */ - ret = wc_ecc_export_x963(key, output + idx, &pubSz); - if (ret != 0) { - return ret; + /* 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); } - /* idx += pubSz if do more later */ return totalSz; } +/* 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); +} + +#ifdef HAVE_PKCS8 +/* 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_PKCS8 */ +#endif /* HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */ +#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) { + 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; + } + else { + if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0) + return ASN_PARSE_E; + + if (privSz != 32) + return ASN_PARSE_E; + + priv = input + *inOutIdx; + *inOutIdx += privSz; + endKeyIdx = *inOutIdx; + } + + 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; + + 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_ECC */ +#endif /* HAVE_ED25519 */ +#ifdef HAVE_ED448 + +int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx, + ed448_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) { + endKeyIdx = *inOutIdx + length; + + if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) + return ASN_PARSE_E; + if (version != 0) { + WOLFSSL_MSG("Unrecognized version of ED448 private key"); + return ASN_PARSE_E; + } + + if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0) + return ASN_PARSE_E; + if (oid != ED448k) + 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; + } + else { + if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0) + return ASN_PARSE_E; + + if (privSz != 57) + return ASN_PARSE_E; + + priv = input + *inOutIdx; + *inOutIdx += privSz; + endKeyIdx = *inOutIdx; + } + + if (endKeyIdx == (int)*inOutIdx) { + ret = wc_ed448_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_ed448_import_private_key(priv, privSz, pub, pubSz, key); + } + if (ret == 0 && endKeyIdx != (int)*inOutIdx) + return ASN_PARSE_E; + + return ret; +} + + +int wc_Ed448PublicKeyDecode(const byte* input, word32* inOutIdx, + ed448_key* key, word32 inSz) +{ + int length; + int ret; + + 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_ed448_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0) + return ASN_ECC_KEY_E; + + return 0; +} + + +#ifdef WOLFSSL_KEY_GEN + +/* build DER formatted ED448 key, + * return length on success, negative on error */ +static int wc_BuildEd448KeyDer(ed448_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 + ED448_PUB_KEY_SIZE; + } + privSz = 2 + 2 + ED448_KEY_SIZE; + algoSz = SetAlgoID(ED448k, 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 + ED448_KEY_SIZE, output + idx); + idx += SetOctetString(ED448_KEY_SIZE, output + idx); + ret = wc_ed448_export_private_only(key, output + idx, &privSz); + if (ret != 0) + return ret; + idx += privSz; + /* pubKey */ + if (pubOut) { + idx += SetExplicit(1, 2 + ED448_PUB_KEY_SIZE, output + idx); + idx += SetOctetString(ED448_KEY_SIZE, output + idx); + ret = wc_ed448_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_Ed448KeyToDer(ed448_key* key, byte* output, word32 inLen) +{ + return wc_BuildEd448KeyDer(key, output, inLen, 1); +} + + + +/* Write only private ecc key to DER format, + * length on success else < 0 */ +int wc_Ed448PrivateKeyToDer(ed448_key* key, byte* output, word32 inLen) +{ + return wc_BuildEd448KeyDer(key, output, inLen, 0); +} + +#endif /* WOLFSSL_KEY_GEN */ + +#endif /* HAVE_ED448 */ #if defined(HAVE_OCSP) || defined(HAVE_CRL) @@ -6832,46 +16134,47 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) static int GetBasicDate(const byte* source, word32* idx, byte* date, byte* format, int maxIdx) { - int length; + int ret, length; + const byte *datePtr = NULL; WOLFSSL_ENTER("GetBasicDate"); - *format = source[*idx]; - *idx += 1; - if (*format != ASN_UTC_TIME && *format != ASN_GENERALIZED_TIME) - return ASN_TIME_E; + ret = GetDateInfo(source, idx, &datePtr, format, &length, maxIdx); + if (ret < 0) + return ret; - if (GetLength(source, idx, &length, maxIdx) < 0) - return ASN_PARSE_E; - - if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE) - return ASN_DATE_SZ_E; - - XMEMCPY(date, &source[*idx], length); - *idx += length; + XMEMCPY(date, datePtr, length); return 0; } -#endif +#endif /* HAVE_OCSP || HAVE_CRL */ #ifdef HAVE_OCSP -static int GetEnumerated(const byte* input, word32* inOutIdx, int *value) +static int GetEnumerated(const byte* input, word32* inOutIdx, int *value, + int sz) { word32 idx = *inOutIdx; word32 len; + byte tag; WOLFSSL_ENTER("GetEnumerated"); *value = 0; - if (input[idx++] != ASN_ENUMERATED) + if (GetASNTag(input, &idx, &tag, sz) < 0) return ASN_PARSE_E; + if (tag != ASN_ENUMERATED) + return ASN_PARSE_E; + + if ((int)idx >= sz) + return BUFFER_E; + len = input[idx++]; - if (len > 4) + if (len > 4 || (int)(len + idx) > sz) return ASN_PARSE_E; while (len--) { @@ -6887,9 +16190,11 @@ static int GetEnumerated(const byte* input, word32* inOutIdx, int *value) static int DecodeSingleResponse(byte* source, word32* ioIndex, OcspResponse* resp, word32 size) { - word32 idx = *ioIndex, prevIndex, oid; + word32 idx = *ioIndex, prevIndex, oid, localIdx; int length, wrapperSz; CertStatus* cs = resp->status; + int ret; + byte tag; WOLFSSL_ENTER("DecodeSingleResponse"); @@ -6910,45 +16215,27 @@ static int DecodeSingleResponse(byte* source, if (GetSequence(source, &idx, &length, size) < 0) return ASN_PARSE_E; /* Skip the hash algorithm */ - if (GetAlgoId(source, &idx, &oid, size) < 0) + 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; - /* Read the serial number, it is handled as a string, not as a - * proper number. Just XMEMCPY the data over, rather than load it - * as an mp_int. */ - if (source[idx++] != ASN_INTEGER) + /* Get serial number */ + if (GetSerialNumber(source, &idx, cs->serial, &cs->serialSz, size) < 0) return ASN_PARSE_E; - if (GetLength(source, &idx, &length, size) < 0) - return ASN_PARSE_E; - if (length <= EXTERNAL_SERIAL_SIZE) - { - if (source[idx] == 0) - { - idx++; - length--; - } - XMEMCPY(cs->serial, source + idx, length); - cs->serialSz = length; - } - else - { - return ASN_GETINT_E; - } - idx += length; + + if ( idx >= size ) + return BUFFER_E; /* CertStatus */ switch (source[idx++]) @@ -6971,27 +16258,66 @@ static int DecodeSingleResponse(byte* source, return ASN_PARSE_E; } +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + cs->thisDateAsn = source + idx; + localIdx = 0; + if (GetDateInfo(cs->thisDateAsn, &localIdx, NULL, + (byte*)&cs->thisDateParsed.type, + &cs->thisDateParsed.length, size) < 0) + return ASN_PARSE_E; + XMEMCPY(cs->thisDateParsed.data, + cs->thisDateAsn + localIdx - cs->thisDateParsed.length, + cs->thisDateParsed.length); +#endif if (GetBasicDate(source, &idx, cs->thisDate, &cs->thisDateFormat, size) < 0) return ASN_PARSE_E; + +#ifndef NO_ASN_TIME +#ifndef WOLFSSL_NO_OCSP_DATE_CHECK if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE)) return ASN_BEFORE_DATE_E; - +#endif +#endif + /* The following items are optional. Only check for them if there is more * unprocessed data in the singleResponse wrapper. */ - + + localIdx = idx; if (((int)(idx - prevIndex) < wrapperSz) && - (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))) + GetASNTag(source, &localIdx, &tag, size) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { idx++; if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + cs->nextDateAsn = source + idx; + localIdx = 0; + if (GetDateInfo(cs->nextDateAsn, &localIdx, NULL, + (byte*)&cs->nextDateParsed.type, + &cs->nextDateParsed.length, size) < 0) + return ASN_PARSE_E; + XMEMCPY(cs->nextDateParsed.data, + cs->nextDateAsn + localIdx - cs->nextDateParsed.length, + cs->nextDateParsed.length); +#endif if (GetBasicDate(source, &idx, cs->nextDate, &cs->nextDateFormat, size) < 0) return ASN_PARSE_E; + +#ifndef NO_ASN_TIME +#ifndef WOLFSSL_NO_OCSP_DATE_CHECK + if (!XVALIDATE_DATE(cs->nextDate, cs->nextDateFormat, AFTER)) + return ASN_AFTER_DATE_E; +#endif +#endif } + + localIdx = idx; if (((int)(idx - prevIndex) < wrapperSz) && - (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))) + GetASNTag(source, &localIdx, &tag, size) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { idx++; if (GetLength(source, &idx, &length, size) < 0) @@ -7011,48 +16337,66 @@ static int DecodeOcspRespExtensions(byte* source, int length; int ext_bound; /* boundary index for the sequence of extensions */ word32 oid; + int ret; + byte tag; WOLFSSL_ENTER("DecodeOcspRespExtensions"); - if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) + if ((idx + 1) > sz) + return BUFFER_E; + + if (GetASNTag(source, &idx, &tag, sz) < 0) return ASN_PARSE_E; - if (GetLength(source, &idx, &length, sz) < 0) return ASN_PARSE_E; + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) + return ASN_PARSE_E; + + if (GetLength(source, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (GetSequence(source, &idx, &length, sz) < 0) + return ASN_PARSE_E; - if (GetSequence(source, &idx, &length, sz) < 0) return ASN_PARSE_E; - ext_bound = idx + length; while (idx < (word32)ext_bound) { + word32 localIdx; + if (GetSequence(source, &idx, &length, sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE"); return ASN_PARSE_E; } oid = 0; - if (GetObjectId(source, &idx, &oid, sz) < 0) { + if (GetObjectId(source, &idx, &oid, oidOcspType, sz) < 0) { WOLFSSL_MSG("\tfail: OBJECT ID"); return ASN_PARSE_E; } /* check for critical flag */ - if (source[idx] == ASN_BOOLEAN) { + if ((idx + 1) > (word32)sz) { + WOLFSSL_MSG("\tfail: malformed buffer"); + return BUFFER_E; + } + + localIdx = idx; + if (GetASNTag(source, &localIdx, &tag, sz) == 0 && tag == 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 */ + ret = GetOctetString(source, &idx, &length, sz); + if (ret < 0) + return ret; + resp->nonce = source + idx; resp->nonceSz = length; } @@ -7068,10 +16412,11 @@ static int DecodeOcspRespExtensions(byte* source, static int DecodeResponseData(byte* source, word32* ioIndex, OcspResponse* resp, word32 size) { - word32 idx = *ioIndex, prev_idx; + word32 idx = *ioIndex, prev_idx, localIdx; int length; int version; - word32 responderId = 0; + int ret; + byte tag; WOLFSSL_ENTER("DecodeResponseData"); @@ -7085,49 +16430,64 @@ static int DecodeResponseData(byte* source, * item isn't an EXPLICIT[0], then set version to zero and move * onto the next item. */ - if (source[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) - { + localIdx = idx; + if (GetASNTag(source, &localIdx, &tag, size) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) + { idx += 2; /* Eat the value and length */ - if (GetMyVersion(source, &idx, &version) < 0) + if (GetMyVersion(source, &idx, &version, size) < 0) return ASN_PARSE_E; } else version = 0; - responderId = source[idx++]; - if ((responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) || - (responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2))) + localIdx = idx; + if (GetASNTag(source, &localIdx, &tag, size) == 0 && + ( tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1) || + tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2) )) { + idx++; /* advance past ASN tag */ if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; idx += length; } else return ASN_PARSE_E; - + /* save pointer to the producedAt time */ if (GetBasicDate(source, &idx, resp->producedDate, &resp->producedDateFormat, size) < 0) return ASN_PARSE_E; - if (DecodeSingleResponse(source, &idx, resp, size) < 0) - return ASN_PARSE_E; + if ((ret = DecodeSingleResponse(source, &idx, resp, size)) < 0) + return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */ - if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0) - return ASN_PARSE_E; + /* + * Check the length of the ResponseData against the current index to + * see if there are extensions, they are optional. + */ + if (idx - prev_idx < resp->responseSz) + if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0) + return ASN_PARSE_E; *ioIndex = idx; return 0; } +#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS + static int DecodeCerts(byte* source, word32* ioIndex, OcspResponse* resp, word32 size) { word32 idx = *ioIndex; + byte tag; WOLFSSL_ENTER("DecodeCerts"); - if (source[idx++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) + if (GetASNTag(source, &idx, &tag, size) < 0) + return ASN_PARSE_E; + + if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { int length; @@ -7146,14 +16506,20 @@ static int DecodeCerts(byte* source, return 0; } -static int DecodeBasicOcspResponse(byte* source, - word32* ioIndex, OcspResponse* resp, word32 size) +#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */ + + +static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, + 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; if (GetSequence(source, &idx, &length, size) < 0) return ASN_PARSE_E; @@ -7162,52 +16528,103 @@ static int DecodeBasicOcspResponse(byte* source, return ASN_INPUT_E; end_index = idx + length; - if (DecodeResponseData(source, &idx, resp, size) < 0) - return ASN_PARSE_E; - + if ((ret = DecodeResponseData(source, &idx, resp, size)) < 0) + return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */ + /* Get the signature algorithm */ - if (GetAlgoId(source, &idx, &resp->sigOID, size) < 0) + 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; - if (GetLength(source, &idx, &sigLength, size) < 0) - return ASN_PARSE_E; - resp->sigSz = sigLength; - resp->sig = source + idx; - idx += sigLength; - } + ret = CheckBitString(source, &idx, &sigLength, size, 1, NULL); + if (ret != 0) + return ret; + + resp->sigSz = sigLength; + resp->sig = source + idx; + idx += sigLength; /* * Check the length of the BasicOcspResponse against the current index to * see if there are certificates, they are optional. */ +#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS 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, 0); - ret = ParseCertRelative(&cert, CA_TYPE, NO_VERIFY, 0); - if (ret < 0) - return ret; + InitDecodedCert(&cert, resp->cert, resp->certSz, heap); + + /* 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; + } + +#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"); + #ifdef OPENSSL_EXTRA + resp->verifyError = OCSP_BAD_ISSUER; + #else + FreeDecodedCert(&cert); + return BAD_OCSP_RESPONDER; + #endif + } + } +#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, NULL); - ret = ConfirmSignature(resp->response, resp->responseSz, - cert.publicKey, cert.pubKeySize, cert.keyOID, - resp->sig, resp->sigSz, resp->sigOID, NULL); FreeDecodedCert(&cert); - if (ret == 0) - { + if (ret != 0) { WOLFSSL_MSG("\tOCSP Confirm signature failed"); return ASN_OCSP_CONFIRM_E; } } + else +#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */ + { + Signer* ca; + int sigValid = -1; + + #ifndef NO_SKID + ca = GetCA(cm, resp->issuerKeyHash); + #else + ca = GetCA(cm, resp->issuerHash); + #endif + + 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, NULL); + } + if (ca == NULL || sigValid != 0) { + WOLFSSL_MSG("\tOCSP Confirm signature failed"); + return ASN_OCSP_CONFIRM_E; + } + + (void)noVerify; + } *ioIndex = idx; return 0; @@ -7219,39 +16636,34 @@ void InitOcspResponse(OcspResponse* resp, CertStatus* status, { WOLFSSL_ENTER("InitOcspResponse"); + XMEMSET(status, 0, sizeof(CertStatus)); + XMEMSET(resp, 0, sizeof(OcspResponse)); + resp->responseStatus = -1; - resp->response = NULL; - resp->responseSz = 0; - resp->producedDateFormat = 0; - resp->issuerHash = NULL; - resp->issuerKeyHash = NULL; - resp->sig = NULL; - resp->sigSz = 0; - resp->sigOID = 0; - resp->status = status; - resp->nonce = NULL; - resp->nonceSz = 0; - resp->source = source; - resp->maxIdx = inSz; + resp->status = status; + resp->source = source; + resp->maxIdx = inSz; } -int OcspResponseDecode(OcspResponse* resp) +int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify) { + int ret; int length = 0; word32 idx = 0; byte* source = resp->source; word32 size = resp->maxIdx; word32 oid; + byte tag; WOLFSSL_ENTER("OcspResponseDecode"); /* peel the outer SEQUENCE wrapper */ if (GetSequence(source, &idx, &length, size) < 0) return ASN_PARSE_E; - + /* First get the responseStatus, an ENUMERATED */ - if (GetEnumerated(source, &idx, &resp->responseStatus) < 0) + if (GetEnumerated(source, &idx, &resp->responseStatus, size) < 0) return ASN_PARSE_E; if (resp->responseStatus != OCSP_SUCCESSFUL) @@ -7260,7 +16672,9 @@ int OcspResponseDecode(OcspResponse* resp) /* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */ if (idx >= size) return ASN_INPUT_E; - if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) + if (GetASNTag(source, &idx, &tag, size) < 0) + return ASN_PARSE_E; + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) return ASN_PARSE_E; if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; @@ -7270,77 +16684,72 @@ int OcspResponseDecode(OcspResponse* resp) return ASN_PARSE_E; /* Check ObjectID for the resposeBytes */ - if (GetObjectId(source, &idx, &oid, size) < 0) + if (GetObjectId(source, &idx, &oid, oidOcspType, size) < 0) 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; + ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap, noVerify); + if (ret < 0) + return ret; - if (DecodeBasicOcspResponse(source, &idx, resp, size) < 0) - return ASN_PARSE_E; - return 0; } -static word32 SetOcspReqExtensions(word32 extSz, byte* output, - const byte* nonce, word32 nonceSz) +word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) { - static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02 }; byte seqArray[5][MAX_SEQ_SZ]; - word32 seqSz[5], totalSz; + word32 seqSz[5], totalSz = (word32)sizeof(NonceObjId); WOLFSSL_ENTER("SetOcspReqExtensions"); - if (nonce == NULL || nonceSz == 0) return 0; - - seqArray[0][0] = ASN_OCTET_STRING; - seqSz[0] = 1 + SetLength(nonceSz, &seqArray[0][1]); + if (!req || !output || !req->nonceSz) + return 0; - seqArray[1][0] = ASN_OBJECT_ID; - seqSz[1] = 1 + SetLength(sizeof(NonceObjId), &seqArray[1][1]); + totalSz += req->nonceSz; + totalSz += seqSz[0] = SetOctetString(req->nonceSz, seqArray[0]); + totalSz += seqSz[1] = SetOctetString(req->nonceSz + seqSz[0], seqArray[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[0] + seqSz[1] + nonceSz + (word32)sizeof(NonceObjId); + if (totalSz > size) + return 0; - seqSz[2] = SetSequence(totalSz, seqArray[2]); - totalSz += seqSz[2]; + totalSz = 0; - seqSz[3] = SetSequence(totalSz, seqArray[3]); - totalSz += seqSz[3]; - - seqArray[4][0] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2); - seqSz[4] = 1 + SetLength(totalSz, &seqArray[4][1]); + XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); totalSz += seqSz[4]; - if (totalSz < extSz) - { - totalSz = 0; - XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); - totalSz += seqSz[4]; - XMEMCPY(output + totalSz, seqArray[3], seqSz[3]); - totalSz += seqSz[3]; - XMEMCPY(output + totalSz, seqArray[2], seqSz[2]); - totalSz += seqSz[2]; - XMEMCPY(output + totalSz, seqArray[1], seqSz[1]); - totalSz += seqSz[1]; - XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId)); - totalSz += (word32)sizeof(NonceObjId); - XMEMCPY(output + totalSz, seqArray[0], seqSz[0]); - totalSz += seqSz[0]; - XMEMCPY(output + totalSz, nonce, nonceSz); - totalSz += nonceSz; - } + XMEMCPY(output + totalSz, seqArray[3], seqSz[3]); + totalSz += seqSz[3]; + + XMEMCPY(output + totalSz, seqArray[2], seqSz[2]); + totalSz += seqSz[2]; + + XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId)); + totalSz += (word32)sizeof(NonceObjId); + + XMEMCPY(output + totalSz, seqArray[1], seqSz[1]); + totalSz += seqSz[1]; + + XMEMCPY(output + totalSz, seqArray[0], seqSz[0]); + totalSz += seqSz[0]; + + XMEMCPY(output + totalSz, req->nonce, req->nonceSz); + totalSz += req->nonceSz; return totalSz; } -int EncodeOcspRequest(OcspRequest* req) +int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) { byte seqArray[5][MAX_SEQ_SZ]; /* The ASN.1 of the OCSP Request is an onion of sequences */ @@ -7349,66 +16758,65 @@ int EncodeOcspRequest(OcspRequest* req) byte issuerKeyArray[MAX_ENCODED_DIG_SZ]; byte snArray[MAX_SN_SZ]; byte extArray[MAX_OCSP_EXT_SZ]; - byte* output = req->dest; - 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"); #ifdef NO_SHA - algoSz = SetAlgoID(SHA256h, algoArray, hashType, 0); + algoSz = SetAlgoID(SHA256h, algoArray, oidHashType, 0); #else - algoSz = SetAlgoID(SHAh, algoArray, hashType, 0); + algoSz = SetAlgoID(SHAh, algoArray, oidHashType, 0); #endif - req->issuerHash = req->cert->issuerHash; - issuerSz = SetDigest(req->cert->issuerHash, KEYID_SIZE, issuerArray); + issuerSz = SetDigest(req->issuerHash, KEYID_SIZE, issuerArray); + issuerKeySz = SetDigest(req->issuerKeyHash, KEYID_SIZE, issuerKeyArray); + snSz = SetSerialNumber(req->serial, req->serialSz, snArray, + MAX_SN_SZ, MAX_SN_SZ); + extSz = 0; - req->issuerKeyHash = req->cert->issuerKeyHash; - issuerKeySz = SetDigest(req->cert->issuerKeyHash, - KEYID_SIZE, issuerKeyArray); + if (snSz < 0) + return snSz; - req->serial = req->cert->serial; - req->serialSz = req->cert->serialSz; - snSz = SetSerialNumber(req->cert->serial, req->cert->serialSz, snArray); - - extSz = 0; - if (req->useNonce) { - RNG rng; - if (wc_InitRng(&rng) != 0) { - WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce."); - } else { - if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0) - WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce."); - else { - req->nonceSz = MAX_OCSP_NONCE_SZ; - extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray, - req->nonce, req->nonceSz); - } - wc_FreeRng(&rng); - } + 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--) { seqSz[i] = SetSequence(totalSz, seqArray[i]); totalSz += seqSz[i]; if (i == 2) totalSz += extSz; } + + if (output == NULL) + return totalSz; + if (totalSz > size) + return BUFFER_E; + totalSz = 0; for (i = 0; i < 5; i++) { XMEMCPY(output + totalSz, seqArray[i], seqSz[i]); totalSz += seqSz[i]; } + XMEMCPY(output + totalSz, algoArray, algoSz); totalSz += algoSz; + XMEMCPY(output + totalSz, issuerArray, issuerSz); totalSz += issuerSz; + XMEMCPY(output + totalSz, issuerKeyArray, issuerKeySz); totalSz += issuerKeySz; + XMEMCPY(output + totalSz, snArray, snSz); totalSz += snSz; + if (extSz != 0) { XMEMCPY(output + totalSz, extArray, extSz); totalSz += extSz; @@ -7418,19 +16826,91 @@ int EncodeOcspRequest(OcspRequest* req) } -void InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, - byte* dest, word32 destSz) +int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, + void* heap) { + int ret; + WOLFSSL_ENTER("InitOcspRequest"); - req->cert = cert; - req->useNonce = useNonce; - req->nonceSz = 0; - req->issuerHash = NULL; - req->issuerKeyHash = NULL; - req->serial = NULL; - req->dest = dest; - req->destSz = destSz; + if (req == NULL) + return BAD_FUNC_ARG; + + ForceZero(req, sizeof(OcspRequest)); + req->heap = heap; + + if (cert) { + XMEMCPY(req->issuerHash, cert->issuerHash, KEYID_SIZE); + XMEMCPY(req->issuerKeyHash, cert->issuerKeyHash, KEYID_SIZE); + + req->serial = (byte*)XMALLOC(cert->serialSz, req->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + if (req->serial == NULL) + return MEMORY_E; + + XMEMCPY(req->serial, cert->serial, cert->serialSz); + req->serialSz = cert->serialSz; + + if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) { + req->url = (byte*)XMALLOC(cert->extAuthInfoSz + 1, req->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + if (req->url == NULL) { + XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP); + return MEMORY_E; + } + + XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz); + req->urlSz = cert->extAuthInfoSz; + req->url[req->urlSz] = 0; + } + } + + if (useNonce) { + WC_RNG rng; + + #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) + WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce."); + else + req->nonceSz = MAX_OCSP_NONCE_SZ; + + wc_FreeRng(&rng); + } + } + + return 0; +} + +void FreeOcspRequest(OcspRequest* req) +{ + WOLFSSL_ENTER("FreeOcspRequest"); + + if (req) { + if (req->serial) + XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP_REQUEST); + req->serial = NULL; + +#ifdef OPENSSL_EXTRA + if (req->serialInt) { + if (req->serialInt->isDynamic) { + XFREE(req->serialInt->data, NULL, DYNAMIC_TYPE_OPENSSL); + } + XFREE(req->serialInt, NULL, DYNAMIC_TYPE_OPENSSL); + } + req->serialInt = NULL; +#endif + + if (req->url) + XFREE(req->url, req->heap, DYNAMIC_TYPE_OCSP_REQUEST); + req->url = NULL; + } } @@ -7454,14 +16934,18 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) /* Nonces are not critical. The responder may not necessarily add * the nonce to the response. */ - if (req->useNonce && resp->nonceSz != 0) { + if (req->nonceSz +#ifndef WOLFSSL_FORCE_OCSP_NONCE_CHECK + && resp->nonceSz != 0 +#endif + ) { cmp = req->nonceSz - resp->nonceSz; if (cmp != 0) { WOLFSSL_MSG("\tnonceSz mismatch"); return cmp; } - + cmp = XMEMCMP(req->nonce, resp->nonce, req->nonceSz); if (cmp != 0) { @@ -7501,20 +16985,22 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) return 0; } -#endif +#endif /* HAVE_OCSP */ -/* store SHA hash of NAME */ -WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, +/* store WC_SHA hash of NAME */ +int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx) { int length; /* length of all distinguished names */ int ret; word32 dummy; + byte tag; WOLFSSL_ENTER("GetNameHash"); - if (source[*idx] == ASN_OBJECT_ID) { + dummy = *idx; + if (GetASNTag(source, &dummy, &tag, maxIdx) == 0 && tag == ASN_OBJECT_ID) { WOLFSSL_MSG("Trying optional prefix..."); if (GetLength(source, idx, &length, maxIdx) < 0) @@ -7531,11 +17017,7 @@ WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, if (GetSequence(source, idx, &length, maxIdx) < 0) return ASN_PARSE_E; -#ifdef NO_SHA - ret = wc_Sha256Hash(source + dummy, length + *idx - dummy, hash); -#else - ret = wc_ShaHash(source + dummy, length + *idx - dummy, hash); -#endif + ret = CalcHashId(source + dummy, length + *idx - dummy, hash); *idx += length; @@ -7546,16 +17028,15 @@ WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, #ifdef HAVE_CRL /* initialize decoded CRL */ -void InitDecodedCRL(DecodedCRL* dcrl) +void InitDecodedCRL(DecodedCRL* dcrl, void* heap) { WOLFSSL_MSG("InitDecodedCRL"); - dcrl->certBegin = 0; - dcrl->sigIndex = 0; - dcrl->sigLength = 0; - dcrl->signatureOID = 0; - dcrl->certs = NULL; - dcrl->totalCerts = 0; + XMEMSET(dcrl, 0, sizeof(DecodedCRL)); + dcrl->heap = heap; + #ifdef WOLFSSL_HEAP_TEST + dcrl->heap = (void*)WOLFSSL_HEAP_TEST; + #endif } @@ -7568,7 +17049,7 @@ void FreeDecodedCRL(DecodedCRL* dcrl) while(tmp) { RevokedCert* next = tmp->next; - XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED); + XFREE(tmp, dcrl->heap, DYNAMIC_TYPE_REVOKED); tmp = next; } } @@ -7578,7 +17059,7 @@ void FreeDecodedCRL(DecodedCRL* dcrl) static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl, int maxIdx) { - int len; + int ret, len; word32 end; byte b; RevokedCert* rc; @@ -7590,56 +17071,33 @@ static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl, end = *idx + len; - /* get serial number */ - b = buff[*idx]; - *idx += 1; - - if (b != ASN_INTEGER) { - WOLFSSL_MSG("Expecting Integer"); - return ASN_PARSE_E; - } - - if (GetLength(buff, idx, &len, maxIdx) < 0) - return ASN_PARSE_E; - - if (len > EXTERNAL_SERIAL_SIZE) { - WOLFSSL_MSG("Serial Size too big"); - return ASN_PARSE_E; - } - - rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), NULL, DYNAMIC_TYPE_CRL); + rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), dcrl->heap, + DYNAMIC_TYPE_REVOKED); if (rc == NULL) { WOLFSSL_MSG("Alloc Revoked Cert failed"); return MEMORY_E; } - XMEMCPY(rc->serialNumber, &buff[*idx], len); - rc->serialSz = len; + if (GetSerialNumber(buff, idx, rc->serialNumber, &rc->serialSz, + maxIdx) < 0) { + XFREE(rc, dcrl->heap, DYNAMIC_TYPE_REVOKED); + return ASN_PARSE_E; + } /* add to list */ rc->next = dcrl->certs; dcrl->certs = rc; dcrl->totalCerts++; - *idx += len; - /* get date */ - b = buff[*idx]; - *idx += 1; - - if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME) { + ret = GetDateInfo(buff, idx, NULL, &b, NULL, maxIdx); + if (ret < 0) { WOLFSSL_MSG("Expecting Date"); - return ASN_PARSE_E; + return ret; } - if (GetLength(buff, idx, &len, maxIdx) < 0) - return ASN_PARSE_E; - - /* skip for now */ - *idx += len; - - if (*idx != end) /* skip extensions */ - *idx = end; + /* skip extensions */ + *idx = end; return 0; } @@ -7650,46 +17108,262 @@ 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; - 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, NULL) != 0) { + WOLFSSL_MSG("CRL Confirm signature failed"); + return ASN_CRL_CONFIRM_E; + } + + return 0; +} + + +static int ParseCRL_CertList(DecodedCRL* dcrl, const byte* buf, + word32* inOutIdx, int sz) +{ + word32 oid, dateIdx, idx, checkIdx; + int version, doNextDate = 1; + byte tag; + + if (dcrl == NULL || inOutIdx == NULL || buf == NULL) { + return BAD_FUNC_ARG; + } + + /* may have version */ + idx = *inOutIdx; + + checkIdx = idx; + if (GetASNTag(buf, &checkIdx, &tag, sz) == 0 && tag == ASN_INTEGER) { + if (GetMyVersion(buf, &idx, &version, sz) < 0) + return ASN_PARSE_E; + } + + if (GetAlgoId(buf, &idx, &oid, oidIgnoreType, sz) < 0) + return ASN_PARSE_E; + + if (GetNameHash(buf, &idx, dcrl->issuerHash, sz) < 0) + return ASN_PARSE_E; + + if (GetBasicDate(buf, &idx, dcrl->lastDate, &dcrl->lastDateFormat, sz) < 0) + return ASN_PARSE_E; + + dateIdx = idx; + + if (GetBasicDate(buf, &idx, dcrl->nextDate, &dcrl->nextDateFormat, sz) < 0) + { +#ifndef WOLFSSL_NO_CRL_NEXT_DATE + (void)dateIdx; + return ASN_PARSE_E; +#else + dcrl->nextDateFormat = ASN_OTHER_TYPE; /* skip flag */ + doNextDate = 0; + idx = dateIdx; +#endif + } + + 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 + } + + checkIdx = idx; + if (idx != dcrl->sigIndex && + GetASNTag(buf, &checkIdx, &tag, sz) == 0 && tag != CRL_EXTENSIONS) { + + int len; + + if (GetSequence(buf, &idx, &len, sz) < 0) + return ASN_PARSE_E; + len += idx; + + while (idx < (word32)len) { + if (GetRevoked(buf, &idx, dcrl, len) < 0) + return ASN_PARSE_E; + } + } + + *inOutIdx = idx; + + return 0; +} + + +#ifndef NO_SKID +static int ParseCRL_AuthKeyIdExt(const byte* input, int sz, DecodedCRL* dcrl) +{ + word32 idx = 0; + int length = 0, ret = 0; + byte tag; + + WOLFSSL_ENTER("ParseCRL_AuthKeyIdExt"); + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE\n"); + return ASN_PARSE_E; + } + + if (GetASNTag(input, &idx, &tag, sz) < 0) { + return ASN_PARSE_E; + } + + if (tag != (ASN_CONTEXT_SPECIFIC | 0)) { + WOLFSSL_MSG("\tinfo: OPTIONAL item 0, not available\n"); + return 0; + } + + if (GetLength(input, &idx, &length, sz) <= 0) { + WOLFSSL_MSG("\tfail: extension data length"); + return ASN_PARSE_E; + } + + dcrl->extAuthKeyIdSet = 1; + if (length == KEYID_SIZE) { + XMEMCPY(dcrl->extAuthKeyId, input + idx, length); + } + else { + ret = CalcHashId(input + idx, length, dcrl->extAuthKeyId); + } + + return ret; +} +#endif + + +static int ParseCRL_Extensions(DecodedCRL* dcrl, const byte* buf, + word32* inOutIdx, word32 sz) +{ + int length; + word32 idx; + word32 ext_bound; /* boundary index for the sequence of extensions */ + word32 oid; + byte tag; + + WOLFSSL_ENTER("ParseCRL_Extensions"); + (void)dcrl; + + if (inOutIdx == NULL) + return BAD_FUNC_ARG; + + idx = *inOutIdx; + + /* CRL Extensions are optional */ + if ((idx + 1) > sz) + return 0; + + /* CRL Extensions are optional */ + if (GetASNTag(buf, &idx, &tag, sz) < 0) + return 0; + + /* CRL Extensions are optional */ + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return 0; + + if (GetLength(buf, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (GetSequence(buf, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + ext_bound = idx + length; + + while (idx < (word32)ext_bound) { + word32 localIdx; + int ret; + + if (GetSequence(buf, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE"); + return ASN_PARSE_E; + } + + oid = 0; + if (GetObjectId(buf, &idx, &oid, oidCrlExtType, sz) < 0) { + WOLFSSL_MSG("\tfail: OBJECT ID"); + return ASN_PARSE_E; + } + + /* check for critical flag */ + if ((idx + 1) > (word32)sz) { + WOLFSSL_MSG("\tfail: malformed buffer"); + return BUFFER_E; + } + + localIdx = idx; + if (GetASNTag(buf, &localIdx, &tag, sz) == 0 && tag == ASN_BOOLEAN) { + WOLFSSL_MSG("\tfound optional critical flag, moving past"); + ret = GetBoolean(buf, &idx, sz); + if (ret < 0) + return ret; + } + + ret = GetOctetString(buf, &idx, &length, sz); + if (ret < 0) + return ret; + + if (oid == AUTH_KEY_OID) { + #ifndef NO_SKID + ret = ParseCRL_AuthKeyIdExt(buf + idx, length, dcrl); + if (ret < 0) { + WOLFSSL_MSG("\tcouldn't parse AuthKeyId extension"); + return ret; + } + #endif + } + + idx += length; + } + + *inOutIdx = idx; + + 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; - word32 oid, idx = 0; - Signer* ca = NULL; + int len; + word32 idx = 0; + 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); */ @@ -7698,98 +17372,154 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) return ASN_PARSE_E; dcrl->certBegin = idx; + /* Normalize sz for the length inside the outer sequence. */ + sz = len + idx; if (GetSequence(buff, &idx, &len, sz) < 0) return ASN_PARSE_E; dcrl->sigIndex = len + idx; - /* may have version */ - if (buff[idx] == ASN_INTEGER) { - if (GetMyVersion(buff, &idx, &version) < 0) - return ASN_PARSE_E; - } - - if (GetAlgoId(buff, &idx, &oid, sz) < 0) + if (ParseCRL_CertList(dcrl, buff, &idx, idx + len) < 0) return ASN_PARSE_E; - if (GetNameHash(buff, &idx, dcrl->issuerHash, sz) < 0) + if (ParseCRL_Extensions(dcrl, buff, &idx, idx + len) < 0) return ASN_PARSE_E; - if (GetBasicDate(buff, &idx, dcrl->lastDate, &dcrl->lastDateFormat, sz) < 0) - return ASN_PARSE_E; + idx = dcrl->sigIndex; - if (GetBasicDate(buff, &idx, dcrl->nextDate, &dcrl->nextDateFormat, sz) < 0) - return ASN_PARSE_E; - - if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) { - WOLFSSL_MSG("CRL after date is no longer valid"); - return ASN_AFTER_DATE_E; - } - - if (idx != dcrl->sigIndex && buff[idx] != CRL_EXTENSIONS) { - if (GetSequence(buff, &idx, &len, sz) < 0) - return ASN_PARSE_E; - - len += idx; - - while (idx < (word32)len) { - if (GetRevoked(buff, &idx, dcrl, sz) < 0) - return ASN_PARSE_E; - } - } - - if (idx != dcrl->sigIndex) - idx = dcrl->sigIndex; /* skip extensions */ - - if (GetAlgoId(buff, &idx, &dcrl->signatureOID, sz) < 0) + if (GetAlgoId(buff, &idx, &dcrl->signatureOID, oidSigType, sz) < 0) return ASN_PARSE_E; if (GetCRL_Signature(buff, &idx, dcrl, sz) < 0) return ASN_PARSE_E; /* 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 */ - 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; + if experiencing issues uncomment NO_SKID define in CRL section of + wolfssl/wolfcrypt/settings.h */ +#ifndef NO_SKID + if (dcrl->extAuthKeyIdSet) { + ca = GetCA(cm, dcrl->extAuthKeyId); /* more unique than issuerHash */ + } + if (ca != NULL && XMEMCMP(dcrl->issuerHash, ca->subjectNameHash, + KEYID_SIZE) != 0) { + ca = NULL; + } + if (ca == NULL) { + ca = GetCAByName(cm, dcrl->issuerHash); /* last resort */ + /* If AKID is available then this CA doesn't have the public + * key required */ + if (ca && dcrl->extAuthKeyIdSet) { + WOLFSSL_MSG("CA SKID doesn't match AKID"); + ca = NULL; } } - else { +#else + ca = GetCA(cm, dcrl->issuerHash); +#endif /* !NO_SKID */ + WOLFSSL_MSG("About to verify CRL signature"); + + if (ca == NULL) { WOLFSSL_MSG("Did NOT find CRL issuer CA"); return ASN_CRL_NO_SIGNER_E; } + 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 */ + + + +#ifdef WOLFSSL_CERT_PIV + +int wc_ParseCertPIV(wc_CertPIV* piv, const byte* buf, word32 totalSz) +{ + int length = 0; + word32 idx = 0; + + WOLFSSL_ENTER("wc_ParseCertPIV"); + + if (piv == NULL || buf == NULL || totalSz == 0) + return BAD_FUNC_ARG; + + XMEMSET(piv, 0, sizeof(wc_CertPIV)); + + /* Detect Identiv PIV (with 0x0A, 0x0B and 0x0C sections) */ + /* Certificate (0A 82 05FA) */ + if (GetASNHeader(buf, ASN_PIV_CERT, &idx, &length, totalSz) >= 0) { + /* Identiv Type PIV card */ + piv->isIdentiv = 1; + + piv->cert = &buf[idx]; + piv->certSz = length; + idx += length; + + /* Nonce (0B 14) */ + if (GetASNHeader(buf, ASN_PIV_NONCE, &idx, &length, totalSz) >= 0) { + piv->nonce = &buf[idx]; + piv->nonceSz = length; + idx += length; + } + + /* Signed Nonce (0C 82 0100) */ + if (GetASNHeader(buf, ASN_PIV_SIGNED_NONCE, &idx, &length, totalSz) >= 0) { + piv->signedNonce = &buf[idx]; + piv->signedNonceSz = length; + } + + idx = 0; + buf = piv->cert; + totalSz = piv->certSz; + } + + /* Certificate Buffer Total Size (53 82 05F6) */ + if (GetASNHeader(buf, ASN_APPLICATION | ASN_PRINTABLE_STRING, &idx, + &length, totalSz) < 0) { + return ASN_PARSE_E; + } + /* PIV Certificate (70 82 05ED) */ + if (GetASNHeader(buf, ASN_PIV_TAG_CERT, &idx, &length, + totalSz) < 0) { + return ASN_PARSE_E; + } + + /* Capture certificate buffer pointer and length */ + piv->cert = &buf[idx]; + piv->certSz = length; + idx += length; + + /* PIV Certificate Info (71 01 00) */ + if (GetASNHeader(buf, ASN_PIV_TAG_CERT_INFO, &idx, &length, + totalSz) >= 0) { + if (length >= 1) { + piv->compression = (buf[idx] & ASN_PIV_CERT_INFO_COMPRESSED); + piv->isX509 = (buf[idx] & ASN_PIV_CERT_INFO_ISX509); + } + idx += length; + } + + /* PIV Error Detection (FE 00) */ + if (GetASNHeader(buf, ASN_PIV_TAG_ERR_DET, &idx, &length, + totalSz) >= 0) { + piv->certErrDet = &buf[idx]; + piv->certErrDetSz = length; + idx += length; + } + return 0; } -#endif /* HAVE_CRL */ -#endif +#endif /* WOLFSSL_CERT_PIV */ + + +#undef ERROR_OUT + +#endif /* !NO_ASN */ #ifdef WOLFSSL_SEP - #endif /* WOLFSSL_SEP */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/NEWS b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/async.c similarity index 100% rename from FreeRTOS-Plus/Source/WolfSSL/NEWS rename to FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/async.c diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/blake2b.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/blake2b.c index 6ae5afd23..1541947dd 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/blake2b.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/blake2b.c @@ -12,9 +12,9 @@ */ /* blake2b.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -28,10 +28,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -69,14 +70,14 @@ static const byte blake2b_sigma[12][16] = }; -static INLINE int blake2b_set_lastnode( blake2b_state *S ) +static WC_INLINE int blake2b_set_lastnode( blake2b_state *S ) { S->f[1] = ~0ULL; return 0; } /* Some helper functions, not necessarily useful */ -static INLINE int blake2b_set_lastblock( blake2b_state *S ) +static WC_INLINE int blake2b_set_lastblock( blake2b_state *S ) { if( S->last_node ) blake2b_set_lastnode( S ); @@ -84,7 +85,7 @@ static INLINE int blake2b_set_lastblock( blake2b_state *S ) return 0; } -static INLINE int blake2b_increment_counter( blake2b_state *S, const word64 +static WC_INLINE int blake2b_increment_counter( blake2b_state *S, const word64 inc ) { S->t[0] += inc; @@ -92,7 +93,7 @@ static INLINE int blake2b_increment_counter( blake2b_state *S, const word64 return 0; } -static INLINE int blake2b_init0( blake2b_state *S ) +static WC_INLINE int blake2b_init0( blake2b_state *S ) { int i; XMEMSET( S, 0, sizeof( blake2b_state ) ); @@ -106,8 +107,9 @@ static INLINE int blake2b_init0( blake2b_state *S ) int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) { word32 i; + byte *p ; blake2b_init0( S ); - byte *p = ( byte * )( P ); + p = ( byte * )( P ); /* IV XOR ParamBlock */ for( i = 0; i < 8; ++i ) @@ -124,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; @@ -135,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 ); } @@ -148,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; @@ -159,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; @@ -300,8 +317,7 @@ int blake2b_update( blake2b_state *S, const byte *in, word64 inlen ) { XMEMCPY( S->buf + left, in, (wolfssl_word)inlen ); S->buflen += inlen; /* Be lazy, do not compress */ - in += inlen; - inlen -= inlen; + inlen = 0; } } @@ -387,7 +403,7 @@ int main( int argc, char **argv ) return -1; } - if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) + if( 0 != XMEMCMP( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) { puts( "error" ); return -1; @@ -402,9 +418,12 @@ int main( int argc, char **argv ) /* wolfCrypt API */ -/* Init Blake2b digest, track size incase final doesn't want to "remember" */ +/* Init Blake2b digest, track size in case final doesn't want to "remember" */ int wc_InitBlake2b(Blake2b* b2b, word32 digestSz) { + if (b2b == NULL){ + return -1; + } b2b->digestSz = digestSz; return blake2b_init(b2b->S, (byte)digestSz); diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/blake2s.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/blake2s.c new file mode 100644 index 000000000..651a1d18d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/blake2s.c @@ -0,0 +1,446 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Written in 2012 by Samuel Neves + + To the extent possible under law, the author(s) have dedicated all copyright + and related and neighboring rights to this software to the public domain + worldwide. This software is distributed without any warranty. + + You should have received a copy of the CC0 Public Domain Dedication along with + this software. If not, see . +*/ +/* blake2s.c + * + * Copyright (C) 2006-2020 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 HAVE_BLAKE2S + +#include +#include + + +static const word32 blake2s_IV[8] = +{ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 +}; + +static const byte blake2s_sigma[10][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } +}; + + +static WC_INLINE int blake2s_set_lastnode( blake2s_state *S ) +{ + S->f[1] = ~0; + return 0; +} + +/* Some helper functions, not necessarily useful */ +static WC_INLINE int blake2s_set_lastblock( blake2s_state *S ) +{ + if( S->last_node ) blake2s_set_lastnode( S ); + + S->f[0] = ~0; + return 0; +} + +static WC_INLINE int blake2s_increment_counter( blake2s_state *S, const word32 + inc ) +{ + S->t[0] += inc; + S->t[1] += ( S->t[0] < inc ); + return 0; +} + +static WC_INLINE int blake2s_init0( blake2s_state *S ) +{ + int i; + XMEMSET( S, 0, sizeof( blake2s_state ) ); + + for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i]; + + return 0; +} + +/* init xors IV with input parameter block */ +int blake2s_init_param( blake2s_state *S, const blake2s_param *P ) +{ + word32 i; + byte *p ; + blake2s_init0( S ); + p = ( byte * )( P ); + + /* IV XOR ParamBlock */ + for( i = 0; i < 8; ++i ) + S->h[i] ^= load32( p + sizeof( S->h[i] ) * i ); + + return 0; +} + + + +int blake2s_init( blake2s_state *S, const byte outlen ) +{ + blake2s_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; + +#ifdef WOLFSSL_BLAKE2S_INIT_EACH_FIELD + P->digest_length = outlen; + P->key_length = 0; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + P->node_depth = 0; + P->inner_length = 0; + 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 blake2s_init_param( S, P ); +} + + +int blake2s_init_key( blake2s_state *S, const byte outlen, const void *key, + const byte keylen ) +{ + blake2s_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; + + if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1; + +#ifdef WOLFSSL_BLAKE2S_INIT_EACH_FIELD + P->digest_length = outlen; + P->key_length = keylen; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store64( &P->node_offset, 0 ); + P->node_depth = 0; + P->inner_length = 0; + 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( blake2s_init_param( S, P ) < 0 ) return -1; + + { +#ifdef WOLFSSL_SMALL_STACK + byte* block; + + block = (byte*)XMALLOC(BLAKE2S_BLOCKBYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if ( block == NULL ) return -1; +#else + byte block[BLAKE2S_BLOCKBYTES]; +#endif + + XMEMSET( block, 0, BLAKE2S_BLOCKBYTES ); + XMEMCPY( block, key, keylen ); + blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); + secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from */ + /* memory */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(block, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } + return 0; +} + +static int blake2s_compress( blake2s_state *S, + const byte block[BLAKE2S_BLOCKBYTES] ) +{ + int i; + +#ifdef WOLFSSL_SMALL_STACK + word32* m; + word32* v; + + m = (word32*)XMALLOC(sizeof(word32) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if ( m == NULL ) return -1; + + v = (word32*)XMALLOC(sizeof(word32) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if ( v == NULL ) + { + XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return -1; + } +#else + word32 m[16]; + word32 v[16]; +#endif + + for( i = 0; i < 16; ++i ) + m[i] = load32( block + i * sizeof( m[i] ) ); + + for( i = 0; i < 8; ++i ) + v[i] = S->h[i]; + + v[ 8] = blake2s_IV[0]; + v[ 9] = blake2s_IV[1]; + v[10] = blake2s_IV[2]; + v[11] = blake2s_IV[3]; + v[12] = S->t[0] ^ blake2s_IV[4]; + v[13] = S->t[1] ^ blake2s_IV[5]; + v[14] = S->f[0] ^ blake2s_IV[6]; + v[15] = S->f[1] ^ blake2s_IV[7]; +#define G(r,i,a,b,c,d) \ + do { \ + a = a + b + m[blake2s_sigma[r][2*i+0]]; \ + d = rotr32(d ^ a, 16); \ + c = c + d; \ + b = rotr32(b ^ c, 12); \ + a = a + b + m[blake2s_sigma[r][2*i+1]]; \ + d = rotr32(d ^ a, 8); \ + c = c + d; \ + b = rotr32(b ^ c, 7); \ + } while(0) +#define ROUND(r) \ + do { \ + G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ + G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ + G(r,2,v[ 2],v[ 6],v[10],v[14]); \ + G(r,3,v[ 3],v[ 7],v[11],v[15]); \ + G(r,4,v[ 0],v[ 5],v[10],v[15]); \ + G(r,5,v[ 1],v[ 6],v[11],v[12]); \ + G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ + G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ + } while(0) + ROUND( 0 ); + ROUND( 1 ); + ROUND( 2 ); + ROUND( 3 ); + ROUND( 4 ); + ROUND( 5 ); + ROUND( 6 ); + ROUND( 7 ); + ROUND( 8 ); + ROUND( 9 ); + + for( i = 0; i < 8; ++i ) + S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; + +#undef G +#undef ROUND + +#ifdef WOLFSSL_SMALL_STACK + XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + +/* inlen now in bytes */ +int blake2s_update( blake2s_state *S, const byte *in, word32 inlen ) +{ + while( inlen > 0 ) + { + word32 left = S->buflen; + word32 fill = 2 * BLAKE2S_BLOCKBYTES - left; + + if( inlen > fill ) + { + XMEMCPY( S->buf + left, in, (wolfssl_word)fill ); /* Fill buffer */ + S->buflen += fill; + blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); + + if ( blake2s_compress( S, S->buf ) < 0 ) return -1; /* Compress */ + + XMEMCPY( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); + /* Shift buffer left */ + S->buflen -= BLAKE2S_BLOCKBYTES; + in += fill; + inlen -= fill; + } + else /* inlen <= fill */ + { + XMEMCPY( S->buf + left, in, (wolfssl_word)inlen ); + S->buflen += inlen; /* Be lazy, do not compress */ + inlen = 0; + } + } + + return 0; +} + +/* Is this correct? */ +int blake2s_final( blake2s_state *S, byte *out, byte outlen ) +{ + int i; + byte buffer[BLAKE2S_BLOCKBYTES]; + + if( S->buflen > BLAKE2S_BLOCKBYTES ) + { + blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); + + if ( blake2s_compress( S, S->buf ) < 0 ) return -1; + + S->buflen -= BLAKE2S_BLOCKBYTES; + XMEMCPY( S->buf, S->buf + BLAKE2S_BLOCKBYTES, (wolfssl_word)S->buflen ); + } + + blake2s_increment_counter( S, S->buflen ); + blake2s_set_lastblock( S ); + XMEMSET( S->buf + S->buflen, 0, (wolfssl_word)(2 * BLAKE2S_BLOCKBYTES - S->buflen) ); + /* Padding */ + if ( blake2s_compress( S, S->buf ) < 0 ) return -1; + + for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ + store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); + + XMEMCPY( out, buffer, outlen ); + return 0; +} + +/* inlen, at least, should be word32. Others can be size_t. */ +int blake2s( byte *out, const void *in, const void *key, const byte outlen, + const word32 inlen, byte keylen ) +{ + blake2s_state S[1]; + + /* Verify parameters */ + if ( NULL == in ) return -1; + + if ( NULL == out ) return -1; + + if( NULL == key ) keylen = 0; + + if( keylen > 0 ) + { + if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1; + } + else + { + if( blake2s_init( S, outlen ) < 0 ) return -1; + } + + if ( blake2s_update( S, ( byte * )in, inlen ) < 0) return -1; + + return blake2s_final( S, out, outlen ); +} + +#if defined(BLAKE2S_SELFTEST) +#include +#include "blake2-kat.h" +int main( int argc, char **argv ) +{ + byte key[BLAKE2S_KEYBYTES]; + byte buf[KAT_LENGTH]; + + for( word32 i = 0; i < BLAKE2S_KEYBYTES; ++i ) + key[i] = ( byte )i; + + for( word32 i = 0; i < KAT_LENGTH; ++i ) + buf[i] = ( byte )i; + + for( word32 i = 0; i < KAT_LENGTH; ++i ) + { + byte hash[BLAKE2S_OUTBYTES]; + if ( blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ) < 0 ) + { + puts( "error" ); + return -1; + } + + if( 0 != XMEMCMP( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) ) + { + puts( "error" ); + return -1; + } + } + + puts( "ok" ); + return 0; +} +#endif + + +/* wolfCrypt API */ + +/* Init Blake2s digest, track size in case final doesn't want to "remember" */ +int wc_InitBlake2s(Blake2s* b2s, word32 digestSz) +{ + if (b2s == NULL){ + return -1; + } + b2s->digestSz = digestSz; + + return blake2s_init(b2s->S, (byte)digestSz); +} + + +/* Blake2s Update */ +int wc_Blake2sUpdate(Blake2s* b2s, const byte* data, word32 sz) +{ + return blake2s_update(b2s->S, data, sz); +} + + +/* Blake2s Final, if pass in zero size we use init digestSz */ +int wc_Blake2sFinal(Blake2s* b2s, byte* final, word32 requestSz) +{ + word32 sz = requestSz ? requestSz : b2s->digestSz; + + return blake2s_final(b2s->S, final, (byte)sz); +} + + +/* end CTaoCrypt API */ + +#endif /* HAVE_BLAKE2S */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/camellia.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/camellia.c index 071019c6c..89ee6617a 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/camellia.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/camellia.c @@ -27,9 +27,9 @@ /* camellia.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -43,11 +43,12 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* - * Algorithm Specification + * Algorithm Specification * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html */ @@ -66,6 +67,7 @@ #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif @@ -510,7 +512,7 @@ static int camellia_setup128(const unsigned char *key, u32 *subkey) #endif /** - * k == kll || klr || krl || krr (|| is concatination) + * k == kll || klr || krl || krr (|| is concatenation) */ kll = GETU32(key ); klr = GETU32(key + 4); @@ -744,7 +746,7 @@ static int camellia_setup256(const unsigned char *key, u32 *subkey) /** * key = (kll || klr || krl || krr || krll || krlr || krrl || krrr) - * (|| is concatination) + * (|| is concatenation) */ kll = GETU32(key ); @@ -1015,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); @@ -1029,13 +1031,13 @@ static int camellia_setup192(const unsigned char *key, u32 *subkey) unsigned char kk[32]; u32 krll, krlr, krrl,krrr; - memcpy(kk, key, 24); - memcpy((unsigned char *)&krll, key+16,4); - memcpy((unsigned char *)&krlr, key+20,4); + XMEMCPY(kk, key, 24); + XMEMCPY((unsigned char *)&krll, key+16,4); + XMEMCPY((unsigned char *)&krlr, key+20,4); krrl = ~krll; krrr = ~krlr; - memcpy(kk+24, (unsigned char *)&krrl, 4); - memcpy(kk+28, (unsigned char *)&krrr, 4); + XMEMCPY(kk+24, (unsigned char *)&krrl, 4); + XMEMCPY(kk+28, (unsigned char *)&krrr, 4); return camellia_setup256(kk, subkey); } @@ -1132,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 valiables */ - + u32 il,ir,t0,t1; /* temporary variables */ + /* pre whitening but absorb kw2*/ io[0] ^= CamelliaSubkeyL(24); io[1] ^= CamelliaSubkeyR(24); @@ -1231,7 +1233,7 @@ static void camellia_decrypt128(const u32 *subkey, u32 *io) */ static void camellia_encrypt256(const u32 *subkey, u32 *io) { - u32 il,ir,t0,t1; /* temporary valiables */ + u32 il,ir,t0,t1; /* temporary variables */ /* pre whitening but absorb kw2*/ io[0] ^= CamelliaSubkeyL(0); @@ -1345,12 +1347,12 @@ static void camellia_encrypt256(const u32 *subkey, u32 *io) static void camellia_decrypt256(const u32 *subkey, u32 *io) { - u32 il,ir,t0,t1; /* temporary valiables */ + u32 il,ir,t0,t1; /* temporary variables */ /* 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), @@ -1462,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]; @@ -1493,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]; @@ -1572,21 +1574,35 @@ 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) { - word32 blocks = sz / CAMELLIA_BLOCK_SIZE; + word32 blocks; + if (cam == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + blocks = sz / CAMELLIA_BLOCK_SIZE; while (blocks--) { xorbuf((byte*)cam->reg, in, CAMELLIA_BLOCK_SIZE); @@ -1597,12 +1613,18 @@ 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) { - word32 blocks = sz / CAMELLIA_BLOCK_SIZE; + word32 blocks; + if (cam == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + blocks = sz / CAMELLIA_BLOCK_SIZE; while (blocks--) { XMEMCPY(cam->tmp, in, CAMELLIA_BLOCK_SIZE); @@ -1613,6 +1635,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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha.c index 4e95bdbd0..38a1ede7d 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha.c @@ -1,8 +1,8 @@ /* chacha.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,8 +16,10 @@ * * 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 - * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* * based from * chacha-ref.c version 20080118 * D. J. Bernstein @@ -25,20 +27,26 @@ */ +#ifdef WOLFSSL_ARMASM + /* implementation is located in wolfcrypt/src/port/arm/armv8-chacha.c */ + +#else #ifdef HAVE_CONFIG_H #include #endif #include -#ifdef HAVE_CHACHA +#if defined(HAVE_CHACHA) && !defined(WOLFSSL_ARMASM) #include #include #include +#include #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif @@ -46,6 +54,31 @@ #include #endif +#ifdef USE_INTEL_CHACHA_SPEEDUP + #include + #include + + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #undef NO_AVX2_SUPPORT + #define NO_AVX2_SUPPORT + #endif + #if defined(__clang__) && ((__clang_major__ < 3) || \ + (__clang_major__ == 3 && __clang_minor__ <= 5)) + #undef NO_AVX2_SUPPORT + #define NO_AVX2_SUPPORT + #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) + #undef NO_AVX2_SUPPORT + #endif + + #ifndef NO_AVX2_SUPPORT + #define HAVE_INTEL_AVX2 + #endif + + static int cpuidFlagsSet = 0; + static int cpuidFlags = 0; +#endif + #ifdef BIG_ENDIAN_ORDER #define LITTLE32(x) ByteReverseWord32(x) #else @@ -77,12 +110,12 @@ */ int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter) { - word32 temp[3]; /* used for alignment of memory */ + word32 temp[CHACHA_IV_WORDS];/* used for alignment of memory */ #ifdef CHACHA_AEAD_TEST word32 i; printf("NONCE : "); - for (i = 0; i < 12; i++) { + for (i = 0; i < CHACHA_IV_BYTES; i++) { printf("%02x", inIv[i]); } printf("\n\n"); @@ -91,12 +124,13 @@ int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter) if (ctx == NULL) return BAD_FUNC_ARG; - XMEMCPY(temp, inIv, 12); + XMEMCPY(temp, inIv, CHACHA_IV_BYTES); - ctx->X[12] = LITTLE32(counter); /* block counter */ - ctx->X[13] = LITTLE32(temp[0]); /* fixed variable from nonce */ - ctx->X[14] = LITTLE32(temp[1]); /* counter from nonce */ - ctx->X[15] = LITTLE32(temp[2]); /* counter from nonce */ + ctx->left = 0; /* resets state */ + ctx->X[CHACHA_IV_BYTES+0] = counter; /* block counter */ + ctx->X[CHACHA_IV_BYTES+1] = LITTLE32(temp[0]); /* fixed variable from nonce */ + ctx->X[CHACHA_IV_BYTES+2] = LITTLE32(temp[1]); /* counter from nonce */ + ctx->X[CHACHA_IV_BYTES+3] = LITTLE32(temp[2]); /* counter from nonce */ return 0; } @@ -121,7 +155,7 @@ int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz) if (ctx == NULL) return BAD_FUNC_ARG; - if (keySz != 16 && keySz != 32) + if (keySz != (CHACHA_MAX_KEY_SZ/2) && keySz != CHACHA_MAX_KEY_SZ) return BAD_FUNC_ARG; #ifdef XSTREAM_ALIGN @@ -152,7 +186,7 @@ int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz) ctx->X[5] = U8TO32_LITTLE(k + 4); ctx->X[6] = U8TO32_LITTLE(k + 8); ctx->X[7] = U8TO32_LITTLE(k + 12); - if (keySz == 32) { + if (keySz == CHACHA_MAX_KEY_SZ) { k += 16; constants = sigma; } @@ -167,6 +201,7 @@ int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz) ctx->X[ 1] = constants[1]; ctx->X[ 2] = constants[2]; ctx->X[ 3] = constants[3]; + ctx->left = 0; /* resets state */ return 0; } @@ -174,12 +209,13 @@ int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz) /** * Converts word into bytes with rotations having been done. */ -static INLINE void wc_Chacha_wordtobyte(word32 output[16], const word32 input[16]) +static WC_INLINE void wc_Chacha_wordtobyte(word32 output[CHACHA_CHUNK_WORDS], + const word32 input[CHACHA_CHUNK_WORDS]) { - word32 x[16]; + word32 x[CHACHA_CHUNK_WORDS]; word32 i; - for (i = 0; i < 16; i++) { + for (i = 0; i < CHACHA_CHUNK_WORDS; i++) { x[i] = input[i]; } @@ -194,54 +230,114 @@ static INLINE void wc_Chacha_wordtobyte(word32 output[16], const word32 input[16 QUARTERROUND(3, 4, 9, 14) } - for (i = 0; i < 16; i++) { + for (i = 0; i < CHACHA_CHUNK_WORDS; i++) { x[i] = PLUS(x[i], input[i]); } - for (i = 0; i < 16; i++) { + for (i = 0; i < CHACHA_CHUNK_WORDS; i++) { output[i] = LITTLE32(x[i]); } } +#ifdef __cplusplus + extern "C" { +#endif + +extern void chacha_encrypt_x64(ChaCha* ctx, const byte* m, byte* c, + word32 bytes); +extern void chacha_encrypt_avx1(ChaCha* ctx, const byte* m, byte* c, + word32 bytes); +extern void chacha_encrypt_avx2(ChaCha* ctx, const byte* m, byte* c, + word32 bytes); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + /** * 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[16]; /* used to make sure aligned */ + word32 temp[CHACHA_CHUNK_WORDS]; /* used to make sure aligned */ word32 i; - output = (byte*)temp; - - if (!bytes) return; - for (;;) { - wc_Chacha_wordtobyte(temp, ctx->X); - ctx->X[12] = PLUSONE(ctx->X[12]); - if (bytes <= 64) { - for (i = 0; i < bytes; ++i) { - c[i] = m[i] ^ output[i]; - } - return; - } - for (i = 0; i < 64; ++i) { + /* handle left overs */ + if (bytes > 0 && ctx->left > 0) { + wc_Chacha_wordtobyte(temp, ctx->X); /* recreate the stream */ + output = (byte*)temp + CHACHA_CHUNK_BYTES - ctx->left; + for (i = 0; i < bytes && i < ctx->left; i++) { c[i] = m[i] ^ output[i]; } - bytes -= 64; - c += 64; - m += 64; + ctx->left = ctx->left - i; + + /* Used up all of the stream that was left, increment the counter */ + if (ctx->left == 0) { + ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]); + } + bytes = bytes - i; + c += i; + m += i; + } + + output = (byte*)temp; + while (bytes >= CHACHA_CHUNK_BYTES) { + wc_Chacha_wordtobyte(temp, ctx->X); + ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]); + 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; + } + + if (bytes) { + /* in this case there will always be some left over since bytes is less + * than CHACHA_CHUNK_BYTES, so do not increment counter after getting + * stream in order for the stream to be recreated on next call */ + wc_Chacha_wordtobyte(temp, ctx->X); + for (i = 0; i < bytes; ++i) { + c[i] = m[i] ^ output[i]; + } + ctx->left = CHACHA_CHUNK_BYTES - i; } } + /** * 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 + if (!cpuidFlagsSet) { + cpuidFlags = cpuid_get_flags(); + cpuidFlagsSet = 1; + } + + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(cpuidFlags)) { + chacha_encrypt_avx2(ctx, input, output, msglen); + return 0; + } + #endif + if (IS_INTEL_AVX1(cpuidFlags)) { + chacha_encrypt_avx1(ctx, input, output, msglen); + return 0; + } + else { + chacha_encrypt_x64(ctx, input, output, msglen); + return 0; + } +#endif wc_Chacha_encrypt_bytes(ctx, input, output, msglen); return 0; @@ -249,3 +345,4 @@ int wc_Chacha_Process(ChaCha* ctx, byte* output, const byte* input, word32 msgle #endif /* HAVE_CHACHA*/ +#endif /* WOLFSSL_ARMASM */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha20_poly1305.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha20_poly1305.c index 4a2b1be22..64bc4c199 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha20_poly1305.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha20_poly1305.c @@ -1,8 +1,8 @@ /* chacha.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -31,29 +32,15 @@ #include #include #include -#include -#include #ifdef NO_INLINE #include #else +#define WOLFSSL_MISC_INCLUDED #include #endif -#ifdef CHACHA_AEAD_TEST -#include -#endif - #define CHACHA20_POLY1305_AEAD_INITIAL_COUNTER 0 -#define CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT 16 - -static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]); -static int calculateAuthTag( - const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE], - const byte* inAAD, const word32 inAADLen, - const byte *inCiphertext, const word32 inCiphertextLen, - byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]); - int wc_ChaCha20Poly1305_Encrypt( const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], @@ -62,12 +49,10 @@ int wc_ChaCha20Poly1305_Encrypt( byte* outCiphertext, byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) { - int err; - byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE]; - ChaCha chaChaCtx; + int ret; + ChaChaPoly_Aead aead; /* Validate function arguments */ - if (!inKey || !inIV || !inPlaintext || !inPlaintextLen || !outCiphertext || @@ -76,35 +61,18 @@ int wc_ChaCha20Poly1305_Encrypt( return BAD_FUNC_ARG; } - XMEMSET(poly1305Key, 0, sizeof(poly1305Key)); - - /* Create the Poly1305 key */ - err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE); - if (err != 0) return err; - - err = wc_Chacha_SetIV(&chaChaCtx, inIV, - CHACHA20_POLY1305_AEAD_INITIAL_COUNTER); - if (err != 0) return err; - - err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key, - CHACHA20_POLY1305_AEAD_KEYSIZE); - if (err != 0) return err; - - /* Encrypt the plaintext using ChaCha20 */ - err = wc_Chacha_Process(&chaChaCtx, outCiphertext, inPlaintext, - inPlaintextLen); - /* Calculate the Poly1305 auth tag */ - if (err == 0) - err = calculateAuthTag(poly1305Key, - inAAD, inAADLen, - outCiphertext, inPlaintextLen, - outAuthTag); - ForceZero(poly1305Key, sizeof(poly1305Key)); - - return err; + ret = wc_ChaCha20Poly1305_Init(&aead, inKey, inIV, + CHACHA20_POLY1305_AEAD_ENCRYPT); + if (ret == 0) + ret = wc_ChaCha20Poly1305_UpdateAad(&aead, inAAD, inAADLen); + if (ret == 0) + ret = wc_ChaCha20Poly1305_UpdateData(&aead, inPlaintext, outCiphertext, + inPlaintextLen); + if (ret == 0) + ret = wc_ChaCha20Poly1305_Final(&aead, outAuthTag); + return ret; } - int wc_ChaCha20Poly1305_Decrypt( const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], @@ -113,13 +81,11 @@ int wc_ChaCha20Poly1305_Decrypt( const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE], byte* outPlaintext) { - int err; - byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE]; - ChaCha chaChaCtx; + int ret; + ChaChaPoly_Aead aead; byte calculatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]; /* Validate function arguments */ - if (!inKey || !inIV || !inCiphertext || !inCiphertextLen || !inAuthTag || @@ -129,146 +95,192 @@ int wc_ChaCha20Poly1305_Decrypt( } XMEMSET(calculatedAuthTag, 0, sizeof(calculatedAuthTag)); - XMEMSET(poly1305Key, 0, sizeof(poly1305Key)); - /* Create the Poly1305 key */ - err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE); - if (err != 0) return err; - - err = wc_Chacha_SetIV(&chaChaCtx, inIV, - CHACHA20_POLY1305_AEAD_INITIAL_COUNTER); - if (err != 0) return err; - - err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key, - CHACHA20_POLY1305_AEAD_KEYSIZE); - if (err != 0) return err; - - /* Calculate the Poly1305 auth tag */ - err = calculateAuthTag(poly1305Key, - inAAD, inAADLen, - inCiphertext, inCiphertextLen, - calculatedAuthTag); - - /* Compare the calculated auth tag with the received one */ - if (err == 0 && ConstantCompare(inAuthTag, calculatedAuthTag, - CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) != 0) - { - err = MAC_CMP_FAILED_E; - } - - /* Decrypt the received ciphertext */ - if (err == 0) - err = wc_Chacha_Process(&chaChaCtx, outPlaintext, inCiphertext, - inCiphertextLen); - ForceZero(poly1305Key, sizeof(poly1305Key)); - - return err; + ret = wc_ChaCha20Poly1305_Init(&aead, inKey, inIV, + CHACHA20_POLY1305_AEAD_DECRYPT); + if (ret == 0) + ret = wc_ChaCha20Poly1305_UpdateAad(&aead, inAAD, inAADLen); + if (ret == 0) + ret = wc_ChaCha20Poly1305_UpdateData(&aead, inCiphertext, outPlaintext, + inCiphertextLen); + if (ret == 0) + ret = wc_ChaCha20Poly1305_Final(&aead, calculatedAuthTag); + if (ret == 0) + ret = wc_ChaCha20Poly1305_CheckTag(inAuthTag, calculatedAuthTag); + return ret; } - -static int calculateAuthTag( - const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE], - const byte *inAAD, const word32 inAADLen, - const byte *inCiphertext, const word32 inCiphertextLen, - byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) +int wc_ChaCha20Poly1305_CheckTag( + const byte authTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE], + const byte authTagChk[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) { - int err; - Poly1305 poly1305Ctx; - byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1]; - word32 paddingLen; - byte little64[8]; + int ret = 0; + if (authTag == NULL || authTagChk == NULL) { + return BAD_FUNC_ARG; + } + if (ConstantCompare(authTag, authTagChk, + CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) != 0) { + ret = MAC_CMP_FAILED_E; + } + return ret; +} - XMEMSET(padding, 0, sizeof(padding)); +int wc_ChaCha20Poly1305_Init(ChaChaPoly_Aead* aead, + const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], + const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], + int isEncrypt) +{ + int ret; + byte authKey[CHACHA20_POLY1305_AEAD_KEYSIZE]; - /* Initialize Poly1305 */ - - err = wc_Poly1305SetKey(&poly1305Ctx, inAuthKey, - CHACHA20_POLY1305_AEAD_KEYSIZE); - if (err) - { - return err; + /* check arguments */ + if (aead == NULL || inKey == NULL || inIV == NULL) { + return BAD_FUNC_ARG; } - /* Create the authTag by MAC'ing the following items: */ + /* setup aead context */ + XMEMSET(aead, 0, sizeof(ChaChaPoly_Aead)); + XMEMSET(authKey, 0, sizeof(authKey)); + aead->isEncrypt = isEncrypt; - /* -- AAD */ + /* Initialize the ChaCha20 context (key and iv) */ + ret = wc_Chacha_SetKey(&aead->chacha, inKey, + CHACHA20_POLY1305_AEAD_KEYSIZE); + if (ret == 0) { + ret = wc_Chacha_SetIV(&aead->chacha, inIV, + CHACHA20_POLY1305_AEAD_INITIAL_COUNTER); + } - if (inAAD && inAADLen) - { - err = wc_Poly1305Update(&poly1305Ctx, inAAD, inAADLen); + /* Create the Poly1305 key */ + if (ret == 0) { + ret = wc_Chacha_Process(&aead->chacha, authKey, authKey, + CHACHA20_POLY1305_AEAD_KEYSIZE); + } - /* -- padding1: pad the AAD to 16 bytes */ + /* Initialize Poly1305 context */ + if (ret == 0) { + ret = wc_Poly1305SetKey(&aead->poly, authKey, + CHACHA20_POLY1305_AEAD_KEYSIZE); + } - paddingLen = -inAADLen & (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1); - if (paddingLen) - { - err += wc_Poly1305Update(&poly1305Ctx, padding, paddingLen); - } + /* advance counter by 1 after creating Poly1305 key */ + if (ret == 0) { + ret = wc_Chacha_SetIV(&aead->chacha, inIV, + CHACHA20_POLY1305_AEAD_INITIAL_COUNTER + 1); + } - if (err) - { - return err; + if (ret == 0) { + aead->state = CHACHA20_POLY1305_STATE_READY; + } + + return ret; +} + +/* optional additional authentication data */ +int wc_ChaCha20Poly1305_UpdateAad(ChaChaPoly_Aead* aead, + const byte* inAAD, word32 inAADLen) +{ + int ret = 0; + + if (aead == NULL || (inAAD == NULL && inAADLen > 0)) { + return BAD_FUNC_ARG; + } + if (aead->state != CHACHA20_POLY1305_STATE_READY && + aead->state != CHACHA20_POLY1305_STATE_AAD) { + return BAD_STATE_E; + } + + if (inAAD && inAADLen > 0) { + ret = wc_Poly1305Update(&aead->poly, inAAD, inAADLen); + if (ret == 0) { + aead->aadLen += inAADLen; + aead->state = CHACHA20_POLY1305_STATE_AAD; } } - /* -- Ciphertext */ + return ret; +} - err = wc_Poly1305Update(&poly1305Ctx, inCiphertext, inCiphertextLen); - if (err) - { - return err; +/* inData and outData can be same pointer (inline) */ +int wc_ChaCha20Poly1305_UpdateData(ChaChaPoly_Aead* aead, + const byte* inData, byte* outData, word32 dataLen) +{ + int ret = 0; + + if (aead == NULL || inData == NULL || outData == NULL) { + return BAD_FUNC_ARG; + } + if (aead->state != CHACHA20_POLY1305_STATE_READY && + aead->state != CHACHA20_POLY1305_STATE_AAD && + aead->state != CHACHA20_POLY1305_STATE_DATA) { + return BAD_STATE_E; } - /* -- padding2: pad the ciphertext to 16 bytes */ + /* Pad the AAD */ + if (aead->state == CHACHA20_POLY1305_STATE_AAD) { + ret = wc_Poly1305_Pad(&aead->poly, aead->aadLen); + } - paddingLen = -inCiphertextLen & - (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1); - if (paddingLen) - { - err = wc_Poly1305Update(&poly1305Ctx, padding, paddingLen); - if (err) - { - return err; + /* advance state */ + aead->state = CHACHA20_POLY1305_STATE_DATA; + + /* Perform ChaCha20 encrypt/decrypt and Poly1305 auth calc */ + if (ret == 0) { + if (aead->isEncrypt) { + ret = wc_Chacha_Process(&aead->chacha, outData, inData, dataLen); + if (ret == 0) + ret = wc_Poly1305Update(&aead->poly, outData, dataLen); + } + else { + ret = wc_Poly1305Update(&aead->poly, inData, dataLen); + if (ret == 0) + ret = wc_Chacha_Process(&aead->chacha, outData, inData, dataLen); } } + if (ret == 0) { + aead->dataLen += dataLen; + } + return ret; +} - /* -- AAD length as a 64-bit little endian integer */ +int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead, + byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) +{ + int ret = 0; - word32ToLittle64(inAADLen, little64); - - err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64)); - if (err) - { - return err; + if (aead == NULL || outAuthTag == NULL) { + return BAD_FUNC_ARG; + } + if (aead->state != CHACHA20_POLY1305_STATE_AAD && + aead->state != CHACHA20_POLY1305_STATE_DATA) { + return BAD_STATE_E; } - /* -- Ciphertext length as a 64-bit little endian integer */ + /* Pad the AAD - Make sure it is done */ + if (aead->state == CHACHA20_POLY1305_STATE_AAD) { + ret = wc_Poly1305_Pad(&aead->poly, aead->aadLen); + } - word32ToLittle64(inCiphertextLen, little64); + /* Pad the ciphertext to 16 bytes */ + if (ret == 0) { + ret = wc_Poly1305_Pad(&aead->poly, aead->dataLen); + } - err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64)); - if (err) - { - return err; + /* Add the aad length and plaintext/ciphertext length */ + if (ret == 0) { + ret = wc_Poly1305_EncodeSizes(&aead->poly, aead->aadLen, + aead->dataLen); } /* Finalize the auth tag */ + if (ret == 0) { + ret = wc_Poly1305Final(&aead->poly, outAuthTag); + } - err = wc_Poly1305Final(&poly1305Ctx, outAuthTag); + /* reset and cleanup sensitive context */ + ForceZero(aead, sizeof(ChaChaPoly_Aead)); - return err; + return ret; } - -static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]) -{ - XMEMSET(outLittle64, 0, 8); - - outLittle64[0] = (inLittle32 & 0x000000FF); - outLittle64[1] = (inLittle32 & 0x0000FF00) >> 8; - outLittle64[2] = (inLittle32 & 0x00FF0000) >> 16; - outLittle64[3] = (inLittle32 & 0xFF000000) >> 24; -} - - #endif /* HAVE_CHACHA && HAVE_POLY1305 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha_asm.S b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha_asm.S new file mode 100644 index 000000000..f9d5fff81 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha_asm.S @@ -0,0 +1,1420 @@ +/* chacha_asm + * + * Copyright (C) 2006-2020 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 HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX1 +#endif /* HAVE_INTEL_AVX1 */ +#ifndef NO_AVX2_SUPPORT +#define HAVE_INTEL_AVX2 +#endif /* NO_AVX2_SUPPORT */ + +#ifndef __APPLE__ +.text +.globl chacha_encrypt_x64 +.type chacha_encrypt_x64,@function +.align 4 +chacha_encrypt_x64: +#else +.section __TEXT,__text +.globl _chacha_encrypt_x64 +.p2align 2 +_chacha_encrypt_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x40, %rsp + cmpl $0x40, %ecx + jl L_chacha_x64_small +L_chacha_x64_start: + subq $48, %rsp + movq %rdx, 24(%rsp) + movq %rsi, 32(%rsp) + movq %rcx, 40(%rsp) + movq 32(%rdi), %rax + movq 40(%rdi), %rbx + movq %rax, 8(%rsp) + movq %rbx, 16(%rsp) + movl (%rdi), %eax + movl 4(%rdi), %ebx + movl 8(%rdi), %ecx + movl 12(%rdi), %edx + movl 16(%rdi), %r8d + movl 20(%rdi), %r9d + movl 24(%rdi), %r10d + movl 28(%rdi), %r11d + movl 48(%rdi), %r12d + movl 52(%rdi), %r13d + movl 56(%rdi), %r14d + movl 60(%rdi), %r15d + movb $10, (%rsp) + movl 8(%rsp), %esi + movl 12(%rsp), %ebp +L_chacha_x64_block_crypt_start: + addl %r8d, %eax + addl %r9d, %ebx + xorl %eax, %r12d + xorl %ebx, %r13d + roll $16, %r12d + roll $16, %r13d + addl %r12d, %esi + addl %r13d, %ebp + xorl %esi, %r8d + xorl %ebp, %r9d + roll $12, %r8d + roll $12, %r9d + addl %r8d, %eax + addl %r9d, %ebx + xorl %eax, %r12d + xorl %ebx, %r13d + roll $8, %r12d + roll $8, %r13d + addl %r12d, %esi + addl %r13d, %ebp + xorl %esi, %r8d + xorl %ebp, %r9d + roll $7, %r8d + roll $7, %r9d + movl %esi, 8(%rsp) + movl %ebp, 12(%rsp) + movl 16(%rsp), %esi + movl 20(%rsp), %ebp + addl %r10d, %ecx + addl %r11d, %edx + xorl %ecx, %r14d + xorl %edx, %r15d + roll $16, %r14d + roll $16, %r15d + addl %r14d, %esi + addl %r15d, %ebp + xorl %esi, %r10d + xorl %ebp, %r11d + roll $12, %r10d + roll $12, %r11d + addl %r10d, %ecx + addl %r11d, %edx + xorl %ecx, %r14d + xorl %edx, %r15d + roll $8, %r14d + roll $8, %r15d + addl %r14d, %esi + addl %r15d, %ebp + xorl %esi, %r10d + xorl %ebp, %r11d + roll $7, %r10d + roll $7, %r11d + addl %r9d, %eax + addl %r10d, %ebx + xorl %eax, %r15d + xorl %ebx, %r12d + roll $16, %r15d + roll $16, %r12d + addl %r15d, %esi + addl %r12d, %ebp + xorl %esi, %r9d + xorl %ebp, %r10d + roll $12, %r9d + roll $12, %r10d + addl %r9d, %eax + addl %r10d, %ebx + xorl %eax, %r15d + xorl %ebx, %r12d + roll $8, %r15d + roll $8, %r12d + addl %r15d, %esi + addl %r12d, %ebp + xorl %esi, %r9d + xorl %ebp, %r10d + roll $7, %r9d + roll $7, %r10d + movl %esi, 16(%rsp) + movl %ebp, 20(%rsp) + movl 8(%rsp), %esi + movl 12(%rsp), %ebp + addl %r11d, %ecx + addl %r8d, %edx + xorl %ecx, %r13d + xorl %edx, %r14d + roll $16, %r13d + roll $16, %r14d + addl %r13d, %esi + addl %r14d, %ebp + xorl %esi, %r11d + xorl %ebp, %r8d + roll $12, %r11d + roll $12, %r8d + addl %r11d, %ecx + addl %r8d, %edx + xorl %ecx, %r13d + xorl %edx, %r14d + roll $8, %r13d + roll $8, %r14d + addl %r13d, %esi + addl %r14d, %ebp + xorl %esi, %r11d + xorl %ebp, %r8d + roll $7, %r11d + roll $7, %r8d + decb (%rsp) + jnz L_chacha_x64_block_crypt_start + movl %esi, 8(%rsp) + movl %ebp, 12(%rsp) + movq 32(%rsp), %rsi + movq 24(%rsp), %rbp + addl (%rdi), %eax + addl 4(%rdi), %ebx + addl 8(%rdi), %ecx + addl 12(%rdi), %edx + addl 16(%rdi), %r8d + addl 20(%rdi), %r9d + addl 24(%rdi), %r10d + addl 28(%rdi), %r11d + addl 48(%rdi), %r12d + addl 52(%rdi), %r13d + addl 56(%rdi), %r14d + addl 60(%rdi), %r15d + xorl (%rsi), %eax + xorl 4(%rsi), %ebx + xorl 8(%rsi), %ecx + xorl 12(%rsi), %edx + xorl 16(%rsi), %r8d + xorl 20(%rsi), %r9d + xorl 24(%rsi), %r10d + xorl 28(%rsi), %r11d + xorl 48(%rsi), %r12d + xorl 52(%rsi), %r13d + xorl 56(%rsi), %r14d + xorl 60(%rsi), %r15d + movl %eax, (%rbp) + movl %ebx, 4(%rbp) + movl %ecx, 8(%rbp) + movl %edx, 12(%rbp) + movl %r8d, 16(%rbp) + movl %r9d, 20(%rbp) + movl %r10d, 24(%rbp) + movl %r11d, 28(%rbp) + movl %r12d, 48(%rbp) + movl %r13d, 52(%rbp) + movl %r14d, 56(%rbp) + movl %r15d, 60(%rbp) + movl 8(%rsp), %eax + movl 12(%rsp), %ebx + movl 16(%rsp), %ecx + movl 20(%rsp), %edx + addl 32(%rdi), %eax + addl 36(%rdi), %ebx + addl 40(%rdi), %ecx + addl 44(%rdi), %edx + xorl 32(%rsi), %eax + xorl 36(%rsi), %ebx + xorl 40(%rsi), %ecx + xorl 44(%rsi), %edx + movl %eax, 32(%rbp) + movl %ebx, 36(%rbp) + movl %ecx, 40(%rbp) + movl %edx, 44(%rbp) + movq 24(%rsp), %rdx + movq 40(%rsp), %rcx + addl $0x01, 48(%rdi) + addq $48, %rsp + subl $0x40, %ecx + addq $0x40, %rsi + addq $0x40, %rdx + cmpl $0x40, %ecx + jge L_chacha_x64_start +L_chacha_x64_small: + cmpl $0x00, %ecx + je L_chacha_x64_done + subq $48, %rsp + movq %rdx, 24(%rsp) + movq %rsi, 32(%rsp) + movq %rcx, 40(%rsp) + movq 32(%rdi), %rax + movq 40(%rdi), %rbx + movq %rax, 8(%rsp) + movq %rbx, 16(%rsp) + movl (%rdi), %eax + movl 4(%rdi), %ebx + movl 8(%rdi), %ecx + movl 12(%rdi), %edx + movl 16(%rdi), %r8d + movl 20(%rdi), %r9d + movl 24(%rdi), %r10d + movl 28(%rdi), %r11d + movl 48(%rdi), %r12d + movl 52(%rdi), %r13d + movl 56(%rdi), %r14d + movl 60(%rdi), %r15d + movb $10, (%rsp) + movl 8(%rsp), %esi + movl 12(%rsp), %ebp +L_chacha_x64_partial_crypt_start: + addl %r8d, %eax + addl %r9d, %ebx + xorl %eax, %r12d + xorl %ebx, %r13d + roll $16, %r12d + roll $16, %r13d + addl %r12d, %esi + addl %r13d, %ebp + xorl %esi, %r8d + xorl %ebp, %r9d + roll $12, %r8d + roll $12, %r9d + addl %r8d, %eax + addl %r9d, %ebx + xorl %eax, %r12d + xorl %ebx, %r13d + roll $8, %r12d + roll $8, %r13d + addl %r12d, %esi + addl %r13d, %ebp + xorl %esi, %r8d + xorl %ebp, %r9d + roll $7, %r8d + roll $7, %r9d + movl %esi, 8(%rsp) + movl %ebp, 12(%rsp) + movl 16(%rsp), %esi + movl 20(%rsp), %ebp + addl %r10d, %ecx + addl %r11d, %edx + xorl %ecx, %r14d + xorl %edx, %r15d + roll $16, %r14d + roll $16, %r15d + addl %r14d, %esi + addl %r15d, %ebp + xorl %esi, %r10d + xorl %ebp, %r11d + roll $12, %r10d + roll $12, %r11d + addl %r10d, %ecx + addl %r11d, %edx + xorl %ecx, %r14d + xorl %edx, %r15d + roll $8, %r14d + roll $8, %r15d + addl %r14d, %esi + addl %r15d, %ebp + xorl %esi, %r10d + xorl %ebp, %r11d + roll $7, %r10d + roll $7, %r11d + addl %r9d, %eax + addl %r10d, %ebx + xorl %eax, %r15d + xorl %ebx, %r12d + roll $16, %r15d + roll $16, %r12d + addl %r15d, %esi + addl %r12d, %ebp + xorl %esi, %r9d + xorl %ebp, %r10d + roll $12, %r9d + roll $12, %r10d + addl %r9d, %eax + addl %r10d, %ebx + xorl %eax, %r15d + xorl %ebx, %r12d + roll $8, %r15d + roll $8, %r12d + addl %r15d, %esi + addl %r12d, %ebp + xorl %esi, %r9d + xorl %ebp, %r10d + roll $7, %r9d + roll $7, %r10d + movl %esi, 16(%rsp) + movl %ebp, 20(%rsp) + movl 8(%rsp), %esi + movl 12(%rsp), %ebp + addl %r11d, %ecx + addl %r8d, %edx + xorl %ecx, %r13d + xorl %edx, %r14d + roll $16, %r13d + roll $16, %r14d + addl %r13d, %esi + addl %r14d, %ebp + xorl %esi, %r11d + xorl %ebp, %r8d + roll $12, %r11d + roll $12, %r8d + addl %r11d, %ecx + addl %r8d, %edx + xorl %ecx, %r13d + xorl %edx, %r14d + roll $8, %r13d + roll $8, %r14d + addl %r13d, %esi + addl %r14d, %ebp + xorl %esi, %r11d + xorl %ebp, %r8d + roll $7, %r11d + roll $7, %r8d + decb (%rsp) + jnz L_chacha_x64_partial_crypt_start + movl %esi, 8(%rsp) + movl %ebp, 12(%rsp) + movq 32(%rsp), %rsi + addl (%rdi), %eax + addl 4(%rdi), %ebx + addl 8(%rdi), %ecx + addl 12(%rdi), %edx + addl 16(%rdi), %r8d + addl 20(%rdi), %r9d + addl 24(%rdi), %r10d + addl 28(%rdi), %r11d + addl 48(%rdi), %r12d + addl 52(%rdi), %r13d + addl 56(%rdi), %r14d + addl 60(%rdi), %r15d + movl %eax, 48(%rsp) + movl %ebx, 52(%rsp) + movl %ecx, 56(%rsp) + movl %edx, 60(%rsp) + movl %r8d, 64(%rsp) + movl %r9d, 68(%rsp) + movl %r10d, 72(%rsp) + movl %r11d, 76(%rsp) + movl %r12d, 96(%rsp) + movl %r13d, 100(%rsp) + movl %r14d, 104(%rsp) + movl %r15d, 108(%rsp) + movl 8(%rsp), %eax + movl 12(%rsp), %ebx + movl 16(%rsp), %ecx + movl 20(%rsp), %edx + addl 32(%rdi), %eax + addl 36(%rdi), %ebx + addl 40(%rdi), %ecx + addl 44(%rdi), %edx + movl %eax, 80(%rsp) + movl %ebx, 84(%rsp) + movl %ecx, 88(%rsp) + movl %edx, 92(%rsp) + movq 24(%rsp), %rdx + movq 40(%rsp), %rcx + addl $0x01, 48(%rdi) + addq $48, %rsp + movl %ecx, %r8d + xorq %rbx, %rbx + andl $7, %r8d + jz L_chacha_x64_partial_start64 +L_chacha_x64_partial_start8: + movzbl (%rsp,%rbx,1), %eax + xorb (%rsi,%rbx,1), %al + movb %al, (%rdx,%rbx,1) + incl %ebx + cmpl %r8d, %ebx + jne L_chacha_x64_partial_start8 + je L_chacha_x64_partial_end64 +L_chacha_x64_partial_start64: + movq (%rsp,%rbx,1), %rax + xorq (%rsi,%rbx,1), %rax + movq %rax, (%rdx,%rbx,1) + addl $8, %ebx +L_chacha_x64_partial_end64: + cmpl %ecx, %ebx + jne L_chacha_x64_partial_start64 +L_chacha_x64_done: + addq $0x40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbp + popq %rbx + repz retq +#ifndef __APPLE__ +.size chacha_encrypt_x64,.-chacha_encrypt_x64 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_chacha20_avx1_rotl8: +.quad 0x605040702010003, 0xe0d0c0f0a09080b +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_chacha20_avx1_rotl16: +.quad 0x504070601000302, 0xd0c0f0e09080b0a +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_chacha20_avx1_add: +.quad 0x100000000, 0x300000002 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_chacha20_avx1_four: +.quad 0x400000004, 0x400000004 +#ifndef __APPLE__ +.text +.globl chacha_encrypt_avx1 +.type chacha_encrypt_avx1,@function +.align 4 +chacha_encrypt_avx1: +#else +.section __TEXT,__text +.globl _chacha_encrypt_avx1 +.p2align 2 +_chacha_encrypt_avx1: +#endif /* __APPLE__ */ + subq $0x190, %rsp + movq %rsp, %r9 + leaq 256(%rsp), %r10 + andq $-16, %r9 + andq $-16, %r10 + movl %ecx, %eax + shrl $8, %eax + jz L_chacha20_avx1_end128 + vpshufd $0x00, (%rdi), %xmm0 + vpshufd $0x00, 4(%rdi), %xmm1 + vpshufd $0x00, 8(%rdi), %xmm2 + vpshufd $0x00, 12(%rdi), %xmm3 + vpshufd $0x00, 16(%rdi), %xmm4 + vpshufd $0x00, 20(%rdi), %xmm5 + vpshufd $0x00, 24(%rdi), %xmm6 + vpshufd $0x00, 28(%rdi), %xmm7 + vpshufd $0x00, 32(%rdi), %xmm8 + vpshufd $0x00, 36(%rdi), %xmm9 + vpshufd $0x00, 40(%rdi), %xmm10 + vpshufd $0x00, 44(%rdi), %xmm11 + vpshufd $0x00, 48(%rdi), %xmm12 + vpshufd $0x00, 52(%rdi), %xmm13 + vpshufd $0x00, 56(%rdi), %xmm14 + vpshufd $0x00, 60(%rdi), %xmm15 + vpaddd L_chacha20_avx1_add(%rip), %xmm12, %xmm12 + vmovdqa %xmm0, (%r9) + vmovdqa %xmm1, 16(%r9) + vmovdqa %xmm2, 32(%r9) + vmovdqa %xmm3, 48(%r9) + vmovdqa %xmm4, 64(%r9) + vmovdqa %xmm5, 80(%r9) + vmovdqa %xmm6, 96(%r9) + vmovdqa %xmm7, 112(%r9) + vmovdqa %xmm8, 128(%r9) + vmovdqa %xmm9, 144(%r9) + vmovdqa %xmm10, 160(%r9) + vmovdqa %xmm11, 176(%r9) + vmovdqa %xmm12, 192(%r9) + vmovdqa %xmm13, 208(%r9) + vmovdqa %xmm14, 224(%r9) + vmovdqa %xmm15, 240(%r9) +L_chacha20_avx1_start128: + vmovdqa %xmm11, 48(%r10) + movb $10, %r8b +L_chacha20_avx1_loop128: + vpaddd %xmm4, %xmm0, %xmm0 + vpxor %xmm0, %xmm12, %xmm12 + vmovdqa 48(%r10), %xmm11 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm12, %xmm12 + vpaddd %xmm12, %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + vpaddd %xmm5, %xmm1, %xmm1 + vpxor %xmm1, %xmm13, %xmm13 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm13, %xmm13 + vpaddd %xmm13, %xmm9, %xmm9 + vpxor %xmm9, %xmm5, %xmm5 + vpaddd %xmm6, %xmm2, %xmm2 + vpxor %xmm2, %xmm14, %xmm14 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm14, %xmm14 + vpaddd %xmm14, %xmm10, %xmm10 + vpxor %xmm10, %xmm6, %xmm6 + vpaddd %xmm7, %xmm3, %xmm3 + vpxor %xmm3, %xmm15, %xmm15 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm15, %xmm15 + vpaddd %xmm15, %xmm11, %xmm11 + vpxor %xmm11, %xmm7, %xmm7 + vmovdqa %xmm11, 48(%r10) + vpsrld $20, %xmm4, %xmm11 + vpslld $12, %xmm4, %xmm4 + vpxor %xmm11, %xmm4, %xmm4 + vpsrld $20, %xmm5, %xmm11 + vpslld $12, %xmm5, %xmm5 + vpxor %xmm11, %xmm5, %xmm5 + vpsrld $20, %xmm6, %xmm11 + vpslld $12, %xmm6, %xmm6 + vpxor %xmm11, %xmm6, %xmm6 + vpsrld $20, %xmm7, %xmm11 + vpslld $12, %xmm7, %xmm7 + vpxor %xmm11, %xmm7, %xmm7 + vpaddd %xmm4, %xmm0, %xmm0 + vpxor %xmm0, %xmm12, %xmm12 + vmovdqa 48(%r10), %xmm11 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm12, %xmm12 + vpaddd %xmm12, %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + vpaddd %xmm5, %xmm1, %xmm1 + vpxor %xmm1, %xmm13, %xmm13 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm13, %xmm13 + vpaddd %xmm13, %xmm9, %xmm9 + vpxor %xmm9, %xmm5, %xmm5 + vpaddd %xmm6, %xmm2, %xmm2 + vpxor %xmm2, %xmm14, %xmm14 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm14, %xmm14 + vpaddd %xmm14, %xmm10, %xmm10 + vpxor %xmm10, %xmm6, %xmm6 + vpaddd %xmm7, %xmm3, %xmm3 + vpxor %xmm3, %xmm15, %xmm15 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm15, %xmm15 + vpaddd %xmm15, %xmm11, %xmm11 + vpxor %xmm11, %xmm7, %xmm7 + vmovdqa %xmm11, 48(%r10) + vpsrld $25, %xmm4, %xmm11 + vpslld $7, %xmm4, %xmm4 + vpxor %xmm11, %xmm4, %xmm4 + vpsrld $25, %xmm5, %xmm11 + vpslld $7, %xmm5, %xmm5 + vpxor %xmm11, %xmm5, %xmm5 + vpsrld $25, %xmm6, %xmm11 + vpslld $7, %xmm6, %xmm6 + vpxor %xmm11, %xmm6, %xmm6 + vpsrld $25, %xmm7, %xmm11 + vpslld $7, %xmm7, %xmm7 + vpxor %xmm11, %xmm7, %xmm7 + vpaddd %xmm5, %xmm0, %xmm0 + vpxor %xmm0, %xmm15, %xmm15 + vmovdqa 48(%r10), %xmm11 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm15, %xmm15 + vpaddd %xmm15, %xmm10, %xmm10 + vpxor %xmm10, %xmm5, %xmm5 + vpaddd %xmm6, %xmm1, %xmm1 + vpxor %xmm1, %xmm12, %xmm12 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm12, %xmm12 + vpaddd %xmm12, %xmm11, %xmm11 + vpxor %xmm11, %xmm6, %xmm6 + vpaddd %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm13, %xmm13 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm13, %xmm13 + vpaddd %xmm13, %xmm8, %xmm8 + vpxor %xmm8, %xmm7, %xmm7 + vpaddd %xmm4, %xmm3, %xmm3 + vpxor %xmm3, %xmm14, %xmm14 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm14, %xmm14 + vpaddd %xmm14, %xmm9, %xmm9 + vpxor %xmm9, %xmm4, %xmm4 + vmovdqa %xmm11, 48(%r10) + vpsrld $20, %xmm5, %xmm11 + vpslld $12, %xmm5, %xmm5 + vpxor %xmm11, %xmm5, %xmm5 + vpsrld $20, %xmm6, %xmm11 + vpslld $12, %xmm6, %xmm6 + vpxor %xmm11, %xmm6, %xmm6 + vpsrld $20, %xmm7, %xmm11 + vpslld $12, %xmm7, %xmm7 + vpxor %xmm11, %xmm7, %xmm7 + vpsrld $20, %xmm4, %xmm11 + vpslld $12, %xmm4, %xmm4 + vpxor %xmm11, %xmm4, %xmm4 + vpaddd %xmm5, %xmm0, %xmm0 + vpxor %xmm0, %xmm15, %xmm15 + vmovdqa 48(%r10), %xmm11 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm15, %xmm15 + vpaddd %xmm15, %xmm10, %xmm10 + vpxor %xmm10, %xmm5, %xmm5 + vpaddd %xmm6, %xmm1, %xmm1 + vpxor %xmm1, %xmm12, %xmm12 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm12, %xmm12 + vpaddd %xmm12, %xmm11, %xmm11 + vpxor %xmm11, %xmm6, %xmm6 + vpaddd %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm13, %xmm13 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm13, %xmm13 + vpaddd %xmm13, %xmm8, %xmm8 + vpxor %xmm8, %xmm7, %xmm7 + vpaddd %xmm4, %xmm3, %xmm3 + vpxor %xmm3, %xmm14, %xmm14 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm14, %xmm14 + vpaddd %xmm14, %xmm9, %xmm9 + vpxor %xmm9, %xmm4, %xmm4 + vmovdqa %xmm11, 48(%r10) + vpsrld $25, %xmm5, %xmm11 + vpslld $7, %xmm5, %xmm5 + vpxor %xmm11, %xmm5, %xmm5 + vpsrld $25, %xmm6, %xmm11 + vpslld $7, %xmm6, %xmm6 + vpxor %xmm11, %xmm6, %xmm6 + vpsrld $25, %xmm7, %xmm11 + vpslld $7, %xmm7, %xmm7 + vpxor %xmm11, %xmm7, %xmm7 + vpsrld $25, %xmm4, %xmm11 + vpslld $7, %xmm4, %xmm4 + vpxor %xmm11, %xmm4, %xmm4 + decb %r8b + jnz L_chacha20_avx1_loop128 + vmovdqa 48(%r10), %xmm11 + vpaddd (%r9), %xmm0, %xmm0 + vpaddd 16(%r9), %xmm1, %xmm1 + vpaddd 32(%r9), %xmm2, %xmm2 + vpaddd 48(%r9), %xmm3, %xmm3 + vpaddd 64(%r9), %xmm4, %xmm4 + vpaddd 80(%r9), %xmm5, %xmm5 + vpaddd 96(%r9), %xmm6, %xmm6 + vpaddd 112(%r9), %xmm7, %xmm7 + vpaddd 128(%r9), %xmm8, %xmm8 + vpaddd 144(%r9), %xmm9, %xmm9 + vpaddd 160(%r9), %xmm10, %xmm10 + vpaddd 176(%r9), %xmm11, %xmm11 + vpaddd 192(%r9), %xmm12, %xmm12 + vpaddd 208(%r9), %xmm13, %xmm13 + vpaddd 224(%r9), %xmm14, %xmm14 + vpaddd 240(%r9), %xmm15, %xmm15 + vmovdqa %xmm8, (%r10) + vmovdqa %xmm9, 16(%r10) + vmovdqa %xmm10, 32(%r10) + vmovdqa %xmm11, 48(%r10) + vmovdqa %xmm12, 64(%r10) + vmovdqa %xmm13, 80(%r10) + vmovdqa %xmm14, 96(%r10) + vmovdqa %xmm15, 112(%r10) + vpunpckldq %xmm1, %xmm0, %xmm8 + vpunpckldq %xmm3, %xmm2, %xmm9 + vpunpckhdq %xmm1, %xmm0, %xmm12 + vpunpckhdq %xmm3, %xmm2, %xmm13 + vpunpckldq %xmm5, %xmm4, %xmm10 + vpunpckldq %xmm7, %xmm6, %xmm11 + vpunpckhdq %xmm5, %xmm4, %xmm14 + vpunpckhdq %xmm7, %xmm6, %xmm15 + vpunpcklqdq %xmm9, %xmm8, %xmm0 + vpunpcklqdq %xmm11, %xmm10, %xmm1 + vpunpckhqdq %xmm9, %xmm8, %xmm2 + vpunpckhqdq %xmm11, %xmm10, %xmm3 + vpunpcklqdq %xmm13, %xmm12, %xmm4 + vpunpcklqdq %xmm15, %xmm14, %xmm5 + vpunpckhqdq %xmm13, %xmm12, %xmm6 + vpunpckhqdq %xmm15, %xmm14, %xmm7 + vmovdqu (%rsi), %xmm8 + vmovdqu 16(%rsi), %xmm9 + vmovdqu 64(%rsi), %xmm10 + vmovdqu 80(%rsi), %xmm11 + vmovdqu 128(%rsi), %xmm12 + vmovdqu 144(%rsi), %xmm13 + vmovdqu 192(%rsi), %xmm14 + vmovdqu 208(%rsi), %xmm15 + vpxor %xmm8, %xmm0, %xmm0 + vpxor %xmm9, %xmm1, %xmm1 + vpxor %xmm10, %xmm2, %xmm2 + vpxor %xmm11, %xmm3, %xmm3 + vpxor %xmm12, %xmm4, %xmm4 + vpxor %xmm13, %xmm5, %xmm5 + vpxor %xmm14, %xmm6, %xmm6 + vpxor %xmm15, %xmm7, %xmm7 + vmovdqu %xmm0, (%rdx) + vmovdqu %xmm1, 16(%rdx) + vmovdqu %xmm2, 64(%rdx) + vmovdqu %xmm3, 80(%rdx) + vmovdqu %xmm4, 128(%rdx) + vmovdqu %xmm5, 144(%rdx) + vmovdqu %xmm6, 192(%rdx) + vmovdqu %xmm7, 208(%rdx) + vmovdqa (%r10), %xmm0 + vmovdqa 16(%r10), %xmm1 + vmovdqa 32(%r10), %xmm2 + vmovdqa 48(%r10), %xmm3 + vmovdqa 64(%r10), %xmm4 + vmovdqa 80(%r10), %xmm5 + vmovdqa 96(%r10), %xmm6 + vmovdqa 112(%r10), %xmm7 + vpunpckldq %xmm1, %xmm0, %xmm8 + vpunpckldq %xmm3, %xmm2, %xmm9 + vpunpckhdq %xmm1, %xmm0, %xmm12 + vpunpckhdq %xmm3, %xmm2, %xmm13 + vpunpckldq %xmm5, %xmm4, %xmm10 + vpunpckldq %xmm7, %xmm6, %xmm11 + vpunpckhdq %xmm5, %xmm4, %xmm14 + vpunpckhdq %xmm7, %xmm6, %xmm15 + vpunpcklqdq %xmm9, %xmm8, %xmm0 + vpunpcklqdq %xmm11, %xmm10, %xmm1 + vpunpckhqdq %xmm9, %xmm8, %xmm2 + vpunpckhqdq %xmm11, %xmm10, %xmm3 + vpunpcklqdq %xmm13, %xmm12, %xmm4 + vpunpcklqdq %xmm15, %xmm14, %xmm5 + vpunpckhqdq %xmm13, %xmm12, %xmm6 + vpunpckhqdq %xmm15, %xmm14, %xmm7 + vmovdqu 32(%rsi), %xmm8 + vmovdqu 48(%rsi), %xmm9 + vmovdqu 96(%rsi), %xmm10 + vmovdqu 112(%rsi), %xmm11 + vmovdqu 160(%rsi), %xmm12 + vmovdqu 176(%rsi), %xmm13 + vmovdqu 224(%rsi), %xmm14 + vmovdqu 240(%rsi), %xmm15 + vpxor %xmm8, %xmm0, %xmm0 + vpxor %xmm9, %xmm1, %xmm1 + vpxor %xmm10, %xmm2, %xmm2 + vpxor %xmm11, %xmm3, %xmm3 + vpxor %xmm12, %xmm4, %xmm4 + vpxor %xmm13, %xmm5, %xmm5 + vpxor %xmm14, %xmm6, %xmm6 + vpxor %xmm15, %xmm7, %xmm7 + vmovdqu %xmm0, 32(%rdx) + vmovdqu %xmm1, 48(%rdx) + vmovdqu %xmm2, 96(%rdx) + vmovdqu %xmm3, 112(%rdx) + vmovdqu %xmm4, 160(%rdx) + vmovdqu %xmm5, 176(%rdx) + vmovdqu %xmm6, 224(%rdx) + vmovdqu %xmm7, 240(%rdx) + vmovdqa 192(%r9), %xmm12 + addq $0x100, %rsi + addq $0x100, %rdx + vpaddd L_chacha20_avx1_four(%rip), %xmm12, %xmm12 + subl $0x100, %ecx + vmovdqa %xmm12, 192(%r9) + cmpl $0x100, %ecx + jl L_chacha20_avx1_done128 + vmovdqa (%r9), %xmm0 + vmovdqa 16(%r9), %xmm1 + vmovdqa 32(%r9), %xmm2 + vmovdqa 48(%r9), %xmm3 + vmovdqa 64(%r9), %xmm4 + vmovdqa 80(%r9), %xmm5 + vmovdqa 96(%r9), %xmm6 + vmovdqa 112(%r9), %xmm7 + vmovdqa 128(%r9), %xmm8 + vmovdqa 144(%r9), %xmm9 + vmovdqa 160(%r9), %xmm10 + vmovdqa 176(%r9), %xmm11 + vmovdqa 192(%r9), %xmm12 + vmovdqa 208(%r9), %xmm13 + vmovdqa 224(%r9), %xmm14 + vmovdqa 240(%r9), %xmm15 + jmp L_chacha20_avx1_start128 +L_chacha20_avx1_done128: + shl $2, %eax + addl %eax, 48(%rdi) +L_chacha20_avx1_end128: + cmpl $0x40, %ecx + jl L_chacha20_avx1_block_done +L_chacha20_avx1_block_start: + vmovdqu (%rdi), %xmm0 + vmovdqu 16(%rdi), %xmm1 + vmovdqu 32(%rdi), %xmm2 + vmovdqu 48(%rdi), %xmm3 + vmovdqa %xmm0, %xmm5 + vmovdqa %xmm1, %xmm6 + vmovdqa %xmm2, %xmm7 + vmovdqa %xmm3, %xmm8 + movb $10, %al +L_chacha20_avx1_block_crypt_start: + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $20, %xmm1, %xmm4 + vpslld $12, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $25, %xmm1, %xmm4 + vpslld $7, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpshufd $57, %xmm1, %xmm1 + vpshufd $0x4e, %xmm2, %xmm2 + vpshufd $0x93, %xmm3, %xmm3 + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $20, %xmm1, %xmm4 + vpslld $12, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $25, %xmm1, %xmm4 + vpslld $7, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpshufd $0x93, %xmm1, %xmm1 + vpshufd $0x4e, %xmm2, %xmm2 + vpshufd $57, %xmm3, %xmm3 + decb %al + jnz L_chacha20_avx1_block_crypt_start + vpaddd %xmm5, %xmm0, %xmm0 + vpaddd %xmm6, %xmm1, %xmm1 + vpaddd %xmm7, %xmm2, %xmm2 + vpaddd %xmm8, %xmm3, %xmm3 + vmovdqu (%rsi), %xmm5 + vmovdqu 16(%rsi), %xmm6 + vmovdqu 32(%rsi), %xmm7 + vmovdqu 48(%rsi), %xmm8 + vpxor %xmm5, %xmm0, %xmm0 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm8, %xmm3, %xmm3 + vmovdqu %xmm0, (%rdx) + vmovdqu %xmm1, 16(%rdx) + vmovdqu %xmm2, 32(%rdx) + vmovdqu %xmm3, 48(%rdx) + addl $0x01, 48(%rdi) + subl $0x40, %ecx + addq $0x40, %rsi + addq $0x40, %rdx + cmpl $0x40, %ecx + jge L_chacha20_avx1_block_start +L_chacha20_avx1_block_done: + cmpl $0x00, %ecx + je L_chacha20_avx1_partial_done + vmovdqu (%rdi), %xmm0 + vmovdqu 16(%rdi), %xmm1 + vmovdqu 32(%rdi), %xmm2 + vmovdqu 48(%rdi), %xmm3 + vmovdqa %xmm0, %xmm5 + vmovdqa %xmm1, %xmm6 + vmovdqa %xmm2, %xmm7 + vmovdqa %xmm3, %xmm8 + movb $10, %al +L_chacha20_avx1_partial_crypt_start: + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $20, %xmm1, %xmm4 + vpslld $12, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $25, %xmm1, %xmm4 + vpslld $7, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpshufd $57, %xmm1, %xmm1 + vpshufd $0x4e, %xmm2, %xmm2 + vpshufd $0x93, %xmm3, %xmm3 + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $20, %xmm1, %xmm4 + vpslld $12, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $25, %xmm1, %xmm4 + vpslld $7, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpshufd $0x93, %xmm1, %xmm1 + vpshufd $0x4e, %xmm2, %xmm2 + vpshufd $57, %xmm3, %xmm3 + decb %al + jnz L_chacha20_avx1_partial_crypt_start + vpaddd %xmm5, %xmm0, %xmm0 + vpaddd %xmm6, %xmm1, %xmm1 + vpaddd %xmm7, %xmm2, %xmm2 + vpaddd %xmm8, %xmm3, %xmm3 + vmovdqu %xmm0, (%r10) + vmovdqu %xmm1, 16(%r10) + vmovdqu %xmm2, 32(%r10) + vmovdqu %xmm3, 48(%r10) + addl $0x01, 48(%rdi) + movl %ecx, %r8d + xorq %r11, %r11 + andl $7, %r8d + jz L_chacha20_avx1_partial_start64 +L_chacha20_avx1_partial_start8: + movzbl (%r10,%r11,1), %eax + xorb (%rsi,%r11,1), %al + movb %al, (%rdx,%r11,1) + incl %r11d + cmpl %r8d, %r11d + jne L_chacha20_avx1_partial_start8 + je L_chacha20_avx1_partial_end64 +L_chacha20_avx1_partial_start64: + movq (%r10,%r11,1), %rax + xorq (%rsi,%r11,1), %rax + movq %rax, (%rdx,%r11,1) + addl $8, %r11d +L_chacha20_avx1_partial_end64: + cmpl %ecx, %r11d + jne L_chacha20_avx1_partial_start64 +L_chacha20_avx1_partial_done: + addq $0x190, %rsp + repz retq +#ifndef __APPLE__ +.size chacha_encrypt_avx1,.-chacha_encrypt_avx1 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX1 */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_chacha20_avx2_rotl8: +.quad 0x605040702010003, 0xe0d0c0f0a09080b +.quad 0x605040702010003, 0xe0d0c0f0a09080b +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_chacha20_avx2_rotl16: +.quad 0x504070601000302, 0xd0c0f0e09080b0a +.quad 0x504070601000302, 0xd0c0f0e09080b0a +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_chacha20_avx2_add: +.quad 0x100000000, 0x300000002 +.quad 0x500000004, 0x700000006 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_chacha20_avx2_eight: +.quad 0x800000008, 0x800000008 +.quad 0x800000008, 0x800000008 +#ifndef __APPLE__ +.text +.globl chacha_encrypt_avx2 +.type chacha_encrypt_avx2,@function +.align 4 +chacha_encrypt_avx2: +#else +.section __TEXT,__text +.globl _chacha_encrypt_avx2 +.p2align 2 +_chacha_encrypt_avx2: +#endif /* __APPLE__ */ + subq $0x310, %rsp + movq %rsp, %r9 + leaq 512(%rsp), %r10 + andq $-32, %r9 + andq $-32, %r10 + movl %ecx, %eax + shrl $9, %eax + jz L_chacha20_avx2_end256 + vpbroadcastd (%rdi), %ymm0 + vpbroadcastd 4(%rdi), %ymm1 + vpbroadcastd 8(%rdi), %ymm2 + vpbroadcastd 12(%rdi), %ymm3 + vpbroadcastd 16(%rdi), %ymm4 + vpbroadcastd 20(%rdi), %ymm5 + vpbroadcastd 24(%rdi), %ymm6 + vpbroadcastd 28(%rdi), %ymm7 + vpbroadcastd 32(%rdi), %ymm8 + vpbroadcastd 36(%rdi), %ymm9 + vpbroadcastd 40(%rdi), %ymm10 + vpbroadcastd 44(%rdi), %ymm11 + vpbroadcastd 48(%rdi), %ymm12 + vpbroadcastd 52(%rdi), %ymm13 + vpbroadcastd 56(%rdi), %ymm14 + vpbroadcastd 60(%rdi), %ymm15 + vpaddd L_chacha20_avx2_add(%rip), %ymm12, %ymm12 + vmovdqa %ymm0, (%r9) + vmovdqa %ymm1, 32(%r9) + vmovdqa %ymm2, 64(%r9) + vmovdqa %ymm3, 96(%r9) + vmovdqa %ymm4, 128(%r9) + vmovdqa %ymm5, 160(%r9) + vmovdqa %ymm6, 192(%r9) + vmovdqa %ymm7, 224(%r9) + vmovdqa %ymm8, 256(%r9) + vmovdqa %ymm9, 288(%r9) + vmovdqa %ymm10, 320(%r9) + vmovdqa %ymm11, 352(%r9) + vmovdqa %ymm12, 384(%r9) + vmovdqa %ymm13, 416(%r9) + vmovdqa %ymm14, 448(%r9) + vmovdqa %ymm15, 480(%r9) +L_chacha20_avx2_start256: + movb $10, %r8b + vmovdqa %ymm11, 96(%r10) +L_chacha20_avx2_loop256: + vpaddd %ymm4, %ymm0, %ymm0 + vpxor %ymm0, %ymm12, %ymm12 + vmovdqa 96(%r10), %ymm11 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm12, %ymm12 + vpaddd %ymm12, %ymm8, %ymm8 + vpxor %ymm8, %ymm4, %ymm4 + vpaddd %ymm5, %ymm1, %ymm1 + vpxor %ymm1, %ymm13, %ymm13 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm13, %ymm13 + vpaddd %ymm13, %ymm9, %ymm9 + vpxor %ymm9, %ymm5, %ymm5 + vpaddd %ymm6, %ymm2, %ymm2 + vpxor %ymm2, %ymm14, %ymm14 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm14, %ymm14 + vpaddd %ymm14, %ymm10, %ymm10 + vpxor %ymm10, %ymm6, %ymm6 + vpaddd %ymm7, %ymm3, %ymm3 + vpxor %ymm3, %ymm15, %ymm15 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm15, %ymm15 + vpaddd %ymm15, %ymm11, %ymm11 + vpxor %ymm11, %ymm7, %ymm7 + vmovdqa %ymm11, 96(%r10) + vpsrld $20, %ymm4, %ymm11 + vpslld $12, %ymm4, %ymm4 + vpxor %ymm11, %ymm4, %ymm4 + vpsrld $20, %ymm5, %ymm11 + vpslld $12, %ymm5, %ymm5 + vpxor %ymm11, %ymm5, %ymm5 + vpsrld $20, %ymm6, %ymm11 + vpslld $12, %ymm6, %ymm6 + vpxor %ymm11, %ymm6, %ymm6 + vpsrld $20, %ymm7, %ymm11 + vpslld $12, %ymm7, %ymm7 + vpxor %ymm11, %ymm7, %ymm7 + vpaddd %ymm4, %ymm0, %ymm0 + vpxor %ymm0, %ymm12, %ymm12 + vmovdqa 96(%r10), %ymm11 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm12, %ymm12 + vpaddd %ymm12, %ymm8, %ymm8 + vpxor %ymm8, %ymm4, %ymm4 + vpaddd %ymm5, %ymm1, %ymm1 + vpxor %ymm1, %ymm13, %ymm13 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm13, %ymm13 + vpaddd %ymm13, %ymm9, %ymm9 + vpxor %ymm9, %ymm5, %ymm5 + vpaddd %ymm6, %ymm2, %ymm2 + vpxor %ymm2, %ymm14, %ymm14 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm14, %ymm14 + vpaddd %ymm14, %ymm10, %ymm10 + vpxor %ymm10, %ymm6, %ymm6 + vpaddd %ymm7, %ymm3, %ymm3 + vpxor %ymm3, %ymm15, %ymm15 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm15, %ymm15 + vpaddd %ymm15, %ymm11, %ymm11 + vpxor %ymm11, %ymm7, %ymm7 + vmovdqa %ymm11, 96(%r10) + vpsrld $25, %ymm4, %ymm11 + vpslld $7, %ymm4, %ymm4 + vpxor %ymm11, %ymm4, %ymm4 + vpsrld $25, %ymm5, %ymm11 + vpslld $7, %ymm5, %ymm5 + vpxor %ymm11, %ymm5, %ymm5 + vpsrld $25, %ymm6, %ymm11 + vpslld $7, %ymm6, %ymm6 + vpxor %ymm11, %ymm6, %ymm6 + vpsrld $25, %ymm7, %ymm11 + vpslld $7, %ymm7, %ymm7 + vpxor %ymm11, %ymm7, %ymm7 + vpaddd %ymm5, %ymm0, %ymm0 + vpxor %ymm0, %ymm15, %ymm15 + vmovdqa 96(%r10), %ymm11 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm15, %ymm15 + vpaddd %ymm15, %ymm10, %ymm10 + vpxor %ymm10, %ymm5, %ymm5 + vpaddd %ymm6, %ymm1, %ymm1 + vpxor %ymm1, %ymm12, %ymm12 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm12, %ymm12 + vpaddd %ymm12, %ymm11, %ymm11 + vpxor %ymm11, %ymm6, %ymm6 + vpaddd %ymm7, %ymm2, %ymm2 + vpxor %ymm2, %ymm13, %ymm13 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm13, %ymm13 + vpaddd %ymm13, %ymm8, %ymm8 + vpxor %ymm8, %ymm7, %ymm7 + vpaddd %ymm4, %ymm3, %ymm3 + vpxor %ymm3, %ymm14, %ymm14 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm14, %ymm14 + vpaddd %ymm14, %ymm9, %ymm9 + vpxor %ymm9, %ymm4, %ymm4 + vmovdqa %ymm11, 96(%r10) + vpsrld $20, %ymm5, %ymm11 + vpslld $12, %ymm5, %ymm5 + vpxor %ymm11, %ymm5, %ymm5 + vpsrld $20, %ymm6, %ymm11 + vpslld $12, %ymm6, %ymm6 + vpxor %ymm11, %ymm6, %ymm6 + vpsrld $20, %ymm7, %ymm11 + vpslld $12, %ymm7, %ymm7 + vpxor %ymm11, %ymm7, %ymm7 + vpsrld $20, %ymm4, %ymm11 + vpslld $12, %ymm4, %ymm4 + vpxor %ymm11, %ymm4, %ymm4 + vpaddd %ymm5, %ymm0, %ymm0 + vpxor %ymm0, %ymm15, %ymm15 + vmovdqa 96(%r10), %ymm11 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm15, %ymm15 + vpaddd %ymm15, %ymm10, %ymm10 + vpxor %ymm10, %ymm5, %ymm5 + vpaddd %ymm6, %ymm1, %ymm1 + vpxor %ymm1, %ymm12, %ymm12 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm12, %ymm12 + vpaddd %ymm12, %ymm11, %ymm11 + vpxor %ymm11, %ymm6, %ymm6 + vpaddd %ymm7, %ymm2, %ymm2 + vpxor %ymm2, %ymm13, %ymm13 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm13, %ymm13 + vpaddd %ymm13, %ymm8, %ymm8 + vpxor %ymm8, %ymm7, %ymm7 + vpaddd %ymm4, %ymm3, %ymm3 + vpxor %ymm3, %ymm14, %ymm14 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm14, %ymm14 + vpaddd %ymm14, %ymm9, %ymm9 + vpxor %ymm9, %ymm4, %ymm4 + vmovdqa %ymm11, 96(%r10) + vpsrld $25, %ymm5, %ymm11 + vpslld $7, %ymm5, %ymm5 + vpxor %ymm11, %ymm5, %ymm5 + vpsrld $25, %ymm6, %ymm11 + vpslld $7, %ymm6, %ymm6 + vpxor %ymm11, %ymm6, %ymm6 + vpsrld $25, %ymm7, %ymm11 + vpslld $7, %ymm7, %ymm7 + vpxor %ymm11, %ymm7, %ymm7 + vpsrld $25, %ymm4, %ymm11 + vpslld $7, %ymm4, %ymm4 + vpxor %ymm11, %ymm4, %ymm4 + decb %r8b + jnz L_chacha20_avx2_loop256 + vmovdqa 96(%r10), %ymm11 + vpaddd (%r9), %ymm0, %ymm0 + vpaddd 32(%r9), %ymm1, %ymm1 + vpaddd 64(%r9), %ymm2, %ymm2 + vpaddd 96(%r9), %ymm3, %ymm3 + vpaddd 128(%r9), %ymm4, %ymm4 + vpaddd 160(%r9), %ymm5, %ymm5 + vpaddd 192(%r9), %ymm6, %ymm6 + vpaddd 224(%r9), %ymm7, %ymm7 + vpaddd 256(%r9), %ymm8, %ymm8 + vpaddd 288(%r9), %ymm9, %ymm9 + vpaddd 320(%r9), %ymm10, %ymm10 + vpaddd 352(%r9), %ymm11, %ymm11 + vpaddd 384(%r9), %ymm12, %ymm12 + vpaddd 416(%r9), %ymm13, %ymm13 + vpaddd 448(%r9), %ymm14, %ymm14 + vpaddd 480(%r9), %ymm15, %ymm15 + vmovdqa %ymm8, (%r10) + vmovdqa %ymm9, 32(%r10) + vmovdqa %ymm10, 64(%r10) + vmovdqa %ymm11, 96(%r10) + vmovdqa %ymm12, 128(%r10) + vmovdqa %ymm13, 160(%r10) + vmovdqa %ymm14, 192(%r10) + vmovdqa %ymm15, 224(%r10) + vpunpckldq %ymm1, %ymm0, %ymm8 + vpunpckldq %ymm3, %ymm2, %ymm9 + vpunpckhdq %ymm1, %ymm0, %ymm12 + vpunpckhdq %ymm3, %ymm2, %ymm13 + vpunpckldq %ymm5, %ymm4, %ymm10 + vpunpckldq %ymm7, %ymm6, %ymm11 + vpunpckhdq %ymm5, %ymm4, %ymm14 + vpunpckhdq %ymm7, %ymm6, %ymm15 + vpunpcklqdq %ymm9, %ymm8, %ymm0 + vpunpcklqdq %ymm11, %ymm10, %ymm1 + vpunpckhqdq %ymm9, %ymm8, %ymm2 + vpunpckhqdq %ymm11, %ymm10, %ymm3 + vpunpcklqdq %ymm13, %ymm12, %ymm4 + vpunpcklqdq %ymm15, %ymm14, %ymm5 + vpunpckhqdq %ymm13, %ymm12, %ymm6 + vpunpckhqdq %ymm15, %ymm14, %ymm7 + vperm2i128 $32, %ymm1, %ymm0, %ymm8 + vperm2i128 $32, %ymm3, %ymm2, %ymm9 + vperm2i128 $49, %ymm1, %ymm0, %ymm12 + vperm2i128 $49, %ymm3, %ymm2, %ymm13 + vperm2i128 $32, %ymm5, %ymm4, %ymm10 + vperm2i128 $32, %ymm7, %ymm6, %ymm11 + vperm2i128 $49, %ymm5, %ymm4, %ymm14 + vperm2i128 $49, %ymm7, %ymm6, %ymm15 + vmovdqu (%rsi), %ymm0 + vmovdqu 64(%rsi), %ymm1 + vmovdqu 128(%rsi), %ymm2 + vmovdqu 192(%rsi), %ymm3 + vmovdqu 256(%rsi), %ymm4 + vmovdqu 320(%rsi), %ymm5 + vmovdqu 384(%rsi), %ymm6 + vmovdqu 448(%rsi), %ymm7 + vpxor %ymm0, %ymm8, %ymm8 + vpxor %ymm1, %ymm9, %ymm9 + vpxor %ymm2, %ymm10, %ymm10 + vpxor %ymm3, %ymm11, %ymm11 + vpxor %ymm4, %ymm12, %ymm12 + vpxor %ymm5, %ymm13, %ymm13 + vpxor %ymm6, %ymm14, %ymm14 + vpxor %ymm7, %ymm15, %ymm15 + vmovdqu %ymm8, (%rdx) + vmovdqu %ymm9, 64(%rdx) + vmovdqu %ymm10, 128(%rdx) + vmovdqu %ymm11, 192(%rdx) + vmovdqu %ymm12, 256(%rdx) + vmovdqu %ymm13, 320(%rdx) + vmovdqu %ymm14, 384(%rdx) + vmovdqu %ymm15, 448(%rdx) + vmovdqa (%r10), %ymm0 + vmovdqa 32(%r10), %ymm1 + vmovdqa 64(%r10), %ymm2 + vmovdqa 96(%r10), %ymm3 + vmovdqa 128(%r10), %ymm4 + vmovdqa 160(%r10), %ymm5 + vmovdqa 192(%r10), %ymm6 + vmovdqa 224(%r10), %ymm7 + vpunpckldq %ymm1, %ymm0, %ymm8 + vpunpckldq %ymm3, %ymm2, %ymm9 + vpunpckhdq %ymm1, %ymm0, %ymm12 + vpunpckhdq %ymm3, %ymm2, %ymm13 + vpunpckldq %ymm5, %ymm4, %ymm10 + vpunpckldq %ymm7, %ymm6, %ymm11 + vpunpckhdq %ymm5, %ymm4, %ymm14 + vpunpckhdq %ymm7, %ymm6, %ymm15 + vpunpcklqdq %ymm9, %ymm8, %ymm0 + vpunpcklqdq %ymm11, %ymm10, %ymm1 + vpunpckhqdq %ymm9, %ymm8, %ymm2 + vpunpckhqdq %ymm11, %ymm10, %ymm3 + vpunpcklqdq %ymm13, %ymm12, %ymm4 + vpunpcklqdq %ymm15, %ymm14, %ymm5 + vpunpckhqdq %ymm13, %ymm12, %ymm6 + vpunpckhqdq %ymm15, %ymm14, %ymm7 + vperm2i128 $32, %ymm1, %ymm0, %ymm8 + vperm2i128 $32, %ymm3, %ymm2, %ymm9 + vperm2i128 $49, %ymm1, %ymm0, %ymm12 + vperm2i128 $49, %ymm3, %ymm2, %ymm13 + vperm2i128 $32, %ymm5, %ymm4, %ymm10 + vperm2i128 $32, %ymm7, %ymm6, %ymm11 + vperm2i128 $49, %ymm5, %ymm4, %ymm14 + vperm2i128 $49, %ymm7, %ymm6, %ymm15 + vmovdqu 32(%rsi), %ymm0 + vmovdqu 96(%rsi), %ymm1 + vmovdqu 160(%rsi), %ymm2 + vmovdqu 224(%rsi), %ymm3 + vmovdqu 288(%rsi), %ymm4 + vmovdqu 352(%rsi), %ymm5 + vmovdqu 416(%rsi), %ymm6 + vmovdqu 480(%rsi), %ymm7 + vpxor %ymm0, %ymm8, %ymm8 + vpxor %ymm1, %ymm9, %ymm9 + vpxor %ymm2, %ymm10, %ymm10 + vpxor %ymm3, %ymm11, %ymm11 + vpxor %ymm4, %ymm12, %ymm12 + vpxor %ymm5, %ymm13, %ymm13 + vpxor %ymm6, %ymm14, %ymm14 + vpxor %ymm7, %ymm15, %ymm15 + vmovdqu %ymm8, 32(%rdx) + vmovdqu %ymm9, 96(%rdx) + vmovdqu %ymm10, 160(%rdx) + vmovdqu %ymm11, 224(%rdx) + vmovdqu %ymm12, 288(%rdx) + vmovdqu %ymm13, 352(%rdx) + vmovdqu %ymm14, 416(%rdx) + vmovdqu %ymm15, 480(%rdx) + vmovdqa 384(%r9), %ymm12 + addq $0x200, %rsi + addq $0x200, %rdx + vpaddd L_chacha20_avx2_eight(%rip), %ymm12, %ymm12 + subl $0x200, %ecx + vmovdqa %ymm12, 384(%r9) + cmpl $0x200, %ecx + jl L_chacha20_avx2_done256 + vmovdqa (%r9), %ymm0 + vmovdqa 32(%r9), %ymm1 + vmovdqa 64(%r9), %ymm2 + vmovdqa 96(%r9), %ymm3 + vmovdqa 128(%r9), %ymm4 + vmovdqa 160(%r9), %ymm5 + vmovdqa 192(%r9), %ymm6 + vmovdqa 224(%r9), %ymm7 + vmovdqa 256(%r9), %ymm8 + vmovdqa 288(%r9), %ymm9 + vmovdqa 320(%r9), %ymm10 + vmovdqa 352(%r9), %ymm11 + vmovdqa 384(%r9), %ymm12 + vmovdqa 416(%r9), %ymm13 + vmovdqa 448(%r9), %ymm14 + vmovdqa 480(%r9), %ymm15 + jmp L_chacha20_avx2_start256 +L_chacha20_avx2_done256: + shl $3, %eax + addl %eax, 48(%rdi) +L_chacha20_avx2_end256: +#ifndef __APPLE__ + callq chacha_encrypt_avx1@plt +#else + callq _chacha_encrypt_avx1 +#endif /* __APPLE__ */ + addq $0x310, %rsp + repz retq +#ifndef __APPLE__ +.size chacha_encrypt_avx2,.-chacha_encrypt_avx2 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/cmac.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/cmac.c new file mode 100644 index 000000000..9d30bb5f3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/cmac.c @@ -0,0 +1,215 @@ +/* cmac.c + * + * Copyright (C) 2006-2020 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_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT) + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$n") + #pragma const_seg(".fipsB$n") + #endif +#endif + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#include +#include +#include + + +static void ShiftAndXorRb(byte* out, byte* in) +{ + int i, j, xorRb; + int mask = 0, last = 0; + byte Rb = 0x87; + + xorRb = (in[0] & 0x80) != 0; + + for (i = 1, j = AES_BLOCK_SIZE - 1; i <= AES_BLOCK_SIZE; i++, j--) { + last = (in[j] & 0x80) ? 1 : 0; + out[j] = (byte)((in[j] << 1) | mask); + mask = last; + if (xorRb) { + out[j] ^= Rb; + Rb = 0; + } + } +} + + +int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz, + int type, void* unused) +{ + int ret; + + (void)unused; + + if (cmac == NULL || key == NULL || keySz == 0 || type != WC_CMAC_AES) + return BAD_FUNC_ARG; + + XMEMSET(cmac, 0, sizeof(Cmac)); + ret = wc_AesSetKey(&cmac->aes, key, keySz, NULL, AES_ENCRYPTION); + if (ret == 0) { + byte l[AES_BLOCK_SIZE]; + + XMEMSET(l, 0, AES_BLOCK_SIZE); + wc_AesEncryptDirect(&cmac->aes, l, l); + ShiftAndXorRb(cmac->k1, l); + ShiftAndXorRb(cmac->k2, cmac->k1); + ForceZero(l, AES_BLOCK_SIZE); + } + return ret; +} + + +int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz) +{ + if ((cmac == NULL) || (in == NULL && inSz != 0)) + return BAD_FUNC_ARG; + + while (inSz != 0) { + word32 add = min(inSz, AES_BLOCK_SIZE - cmac->bufferSz); + XMEMCPY(&cmac->buffer[cmac->bufferSz], in, add); + + cmac->bufferSz += add; + in += add; + inSz -= add; + + if (cmac->bufferSz == AES_BLOCK_SIZE && inSz != 0) { + if (cmac->totalSz != 0) + xorbuf(cmac->buffer, cmac->digest, AES_BLOCK_SIZE); + wc_AesEncryptDirect(&cmac->aes, + cmac->digest, + cmac->buffer); + cmac->totalSz += AES_BLOCK_SIZE; + cmac->bufferSz = 0; + } + } + + return 0; +} + + +int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz) +{ + const byte* subKey; + + if (cmac == NULL || out == NULL || outSz == NULL) + return BAD_FUNC_ARG; + + if (*outSz < WC_CMAC_TAG_MIN_SZ || *outSz > WC_CMAC_TAG_MAX_SZ) + return BUFFER_E; + + if (cmac->bufferSz == AES_BLOCK_SIZE) { + subKey = cmac->k1; + } + else { + word32 remainder = AES_BLOCK_SIZE - cmac->bufferSz; + + if (remainder == 0) + remainder = AES_BLOCK_SIZE; + + if (remainder > 1) + XMEMSET(cmac->buffer + AES_BLOCK_SIZE - remainder, 0, remainder); + cmac->buffer[AES_BLOCK_SIZE - remainder] = 0x80; + subKey = cmac->k2; + } + xorbuf(cmac->buffer, cmac->digest, AES_BLOCK_SIZE); + xorbuf(cmac->buffer, subKey, AES_BLOCK_SIZE); + wc_AesEncryptDirect(&cmac->aes, cmac->digest, cmac->buffer); + + XMEMCPY(out, cmac->digest, *outSz); + + ForceZero(cmac, sizeof(Cmac)); + + return 0; +} + + +int wc_AesCmacGenerate(byte* out, word32* outSz, + const byte* in, word32 inSz, + const byte* key, word32 keySz) +{ + Cmac cmac; + int ret; + + if (out == NULL || (in == NULL && inSz > 0) || key == NULL || keySz == 0) + return BAD_FUNC_ARG; + + ret = wc_InitCmac(&cmac, key, keySz, WC_CMAC_AES, NULL); + if (ret != 0) + return ret; + + ret = wc_CmacUpdate(&cmac, in, inSz); + if (ret != 0) + return ret; + + ret = wc_CmacFinal(&cmac, out, outSz); + if (ret != 0) + return ret; + + return 0; +} + + +int wc_AesCmacVerify(const byte* check, word32 checkSz, + const byte* in, word32 inSz, + const byte* key, word32 keySz) +{ + byte a[AES_BLOCK_SIZE]; + word32 aSz = sizeof(a); + int result; + int compareRet; + + if (check == NULL || checkSz == 0 || (in == NULL && inSz != 0) || + key == NULL || keySz == 0) + + return BAD_FUNC_ARG; + + XMEMSET(a, 0, aSz); + result = wc_AesCmacGenerate(a, &aSz, in, inSz, key, keySz); + compareRet = ConstantCompare(check, a, min(checkSz, aSz)); + + if (result == 0) + result = compareRet ? 1 : 0; + + return result; +} + + +#endif /* WOLFSSL_CMAC && NO_AES && WOLFSSL_AES_DIRECT */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/coding.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/coding.c index 6ead79caf..f6c814e01 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/coding.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/coding.c @@ -1,8 +1,8 @@ /* coding.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -35,10 +36,14 @@ enum { BAD = 0xFF, /* invalid encoding */ PAD = '=', - PEM_LINE_SZ = 64 + PEM_LINE_SZ = 64, + BASE64_MIN = 0x2B, + BASE16_MIN = 0x30, }; +#ifdef WOLFSSL_BASE64_DECODE + static const byte base64Decode[] = { 62, BAD, BAD, BAD, 63, /* + starts at 0x2B */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, @@ -52,27 +57,81 @@ const byte base64Decode[] = { 62, BAD, BAD, BAD, 63, /* + starts at 0x2B */ 46, 47, 48, 49, 50, 51 }; +static WC_INLINE int Base64_SkipNewline(const byte* in, word32 *inLen, word32 *outJ) +{ + word32 len = *inLen; + word32 j = *outJ; + if (len && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) { + byte endLine = in[j++]; + len--; + while (len && endLine == ' ') { /* allow trailing whitespace */ + endLine = in[j++]; + len--; + } + if (endLine == '\r') { + if (len) { + endLine = in[j++]; + len--; + } + } + if (endLine != '\n') { + WOLFSSL_MSG("Bad end of line in Base64 Decode"); + return ASN_INPUT_E; + } + } + if (!len) { + return BUFFER_E; + } + *inLen = len; + *outJ = j; + return 0; +} int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) { word32 i = 0; word32 j = 0; word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ ); - const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1; + int ret; + const byte maxIdx = (byte)sizeof(base64Decode) + BASE64_MIN - 1; plainSz = (plainSz * 3 + 3) / 4; if (plainSz > *outLen) return BAD_FUNC_ARG; while (inLen > 3) { - byte b1, b2, b3; - byte e1 = in[j++]; - byte e2 = in[j++]; - byte e3 = in[j++]; - byte e4 = in[j++]; - int pad3 = 0; int pad4 = 0; + byte b1, b2, b3; + byte e1, e2, e3, e4; + if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) { + if (ret == BUFFER_E) { + /* Running out of buffer here is not an error */ + break; + } + return ret; + } + e1 = in[j++]; + if (e1 == '\0') { + break; + } + inLen--; + if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) { + return ret; + } + e2 = in[j++]; + inLen--; + if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) { + return ret; + } + e3 = in[j++]; + inLen--; + if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) { + return ret; + } + e4 = in[j++]; + inLen--; + if (e1 == 0) /* end file 0's */ break; if (e3 == PAD) @@ -80,7 +139,7 @@ int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) if (e4 == PAD) pad4 = 1; - if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) { + if (e1 < BASE64_MIN || e2 < BASE64_MIN || e3 < BASE64_MIN || e4 < BASE64_MIN) { WOLFSSL_MSG("Bad Base64 Decode data, too small"); return ASN_INPUT_E; } @@ -90,10 +149,15 @@ int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) return ASN_INPUT_E; } - e1 = base64Decode[e1 - 0x2B]; - e2 = base64Decode[e2 - 0x2B]; - e3 = (e3 == PAD) ? 0 : base64Decode[e3 - 0x2B]; - e4 = (e4 == PAD) ? 0 : base64Decode[e4 - 0x2B]; + if (i + 1 + !pad3 + !pad4 > *outLen) { + WOLFSSL_MSG("Bad Base64 Decode out buffer, too small"); + return BAD_FUNC_ARG; + } + + e1 = base64Decode[e1 - BASE64_MIN]; + e2 = base64Decode[e2 - BASE64_MIN]; + e3 = (e3 == PAD) ? 0 : base64Decode[e3 - BASE64_MIN]; + e4 = (e4 == PAD) ? 0 : base64Decode[e4 - BASE64_MIN]; b1 = (byte)((e1 << 2) | (e2 >> 4)); b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2)); @@ -106,32 +170,17 @@ int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) out[i++] = b3; else break; - - inLen -= 4; - if (inLen && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) { - byte endLine = in[j++]; - inLen--; - while (inLen && endLine == ' ') { /* allow trailing whitespace */ - endLine = in[j++]; - inLen--; - } - if (endLine == '\r') { - if (inLen) { - endLine = in[j++]; - inLen--; - } - } - if (endLine != '\n') { - WOLFSSL_MSG("Bad end of line in Base64 Decode"); - return ASN_INPUT_E; - } - } } +/* If the output buffer has a room for an extra byte, add a null terminator */ + if (out && *outLen > i) + out[i]= '\0'; + *outLen = i; return 0; } +#endif /* WOLFSSL_BASE64_DECODE */ #if defined(WOLFSSL_BASE64_ENCODE) @@ -150,7 +199,7 @@ const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* make sure *i (idx) won't exceed max, store and possibly escape to out, * raw means use e w/o decode, 0 on success */ static int CEscape(int escaped, byte e, byte* out, word32* i, word32 max, - int raw) + int raw, int getSzOnly) { int doEscape = 0; word32 needed = 1; @@ -166,8 +215,8 @@ static int CEscape(int escaped, byte e, byte* out, word32* i, word32 max, else basic = base64Encode[e]; - /* check whether to escape */ - if (escaped) { + /* check whether to escape. Only escape for EncodeEsc */ + if (escaped == WC_ESC_NL_ENC) { switch ((char)basic) { case '+' : plus = 1; @@ -191,31 +240,37 @@ static int CEscape(int escaped, byte e, byte* out, word32* i, word32 max, } /* check size */ - if ( (idx+needed) > max) { + if ( (idx+needed) > max && !getSzOnly) { WOLFSSL_MSG("Escape buffer max too small"); return BUFFER_E; } /* store it */ if (doEscape == 0) { - out[idx++] = basic; + if(getSzOnly) + idx++; + else + out[idx++] = basic; } else { - out[idx++] = '%'; /* start escape */ + if(getSzOnly) + idx+=3; + else { + out[idx++] = '%'; /* start escape */ - if (plus) { - out[idx++] = '2'; - out[idx++] = 'B'; + if (plus) { + out[idx++] = '2'; + out[idx++] = 'B'; + } + else if (equals) { + out[idx++] = '3'; + out[idx++] = 'D'; + } + else if (newline) { + out[idx++] = '0'; + out[idx++] = 'A'; + } } - else if (equals) { - out[idx++] = '3'; - out[idx++] = 'D'; - } - else if (newline) { - out[idx++] = '0'; - out[idx++] = 'A'; - } - } *i = idx; @@ -223,7 +278,8 @@ static int CEscape(int escaped, byte e, byte* out, word32* i, word32 max, } -/* internal worker, handles both escaped and normal line endings */ +/* internal worker, handles both escaped and normal line endings. + If out buffer is NULL, will return sz needed in outLen */ static int DoBase64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen, int escaped) { @@ -232,18 +288,23 @@ static int DoBase64_Encode(const byte* in, word32 inLen, byte* out, j = 0, n = 0; /* new line counter */ + int getSzOnly = (out == NULL); + word32 outSz = (inLen + 3 - 1) / 3 * 4; word32 addSz = (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ; /* new lines */ - if (escaped) + if (escaped == WC_ESC_NL_ENC) addSz *= 3; /* instead of just \n, we're doing %0A triplet */ + else if (escaped == WC_NO_NL_ENC) + addSz = 0; /* encode without \n */ outSz += addSz; /* if escaped we can't predetermine size for one pass encoding, but - * make sure we have enough if no escapes are in input */ - if (outSz > *outLen) return BAD_FUNC_ARG; - + * make sure we have enough if no escapes are in input + * Also need to ensure outLen valid before dereference */ + if (!outLen || (outSz > *outLen && !getSzOnly)) return BAD_FUNC_ARG; + while (inLen > 2) { byte b1 = in[j++]; byte b2 = in[j++]; @@ -256,19 +317,20 @@ static int DoBase64_Encode(const byte* in, word32 inLen, byte* out, byte e4 = b3 & 0x3F; /* store */ - ret = CEscape(escaped, e1, out, &i, *outLen, 0); + ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly); if (ret != 0) break; - ret = CEscape(escaped, e2, out, &i, *outLen, 0); + ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly); if (ret != 0) break; - ret = CEscape(escaped, e3, out, &i, *outLen, 0); + ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly); if (ret != 0) break; - ret = CEscape(escaped, e4, out, &i, *outLen, 0); + ret = CEscape(escaped, e4, out, &i, *outLen, 0, getSzOnly); if (ret != 0) break; inLen -= 3; - if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen) { - ret = CEscape(escaped, '\n', out, &i, *outLen, 1); + /* Insert newline after PEM_LINE_SZ, unless no \n requested */ + if (escaped != WC_NO_NL_ENC && (++n % (PEM_LINE_SZ/4)) == 0 && inLen) { + ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly); if (ret != 0) break; } } @@ -284,50 +346,61 @@ static int DoBase64_Encode(const byte* in, word32 inLen, byte* out, byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4)); byte e3 = (byte)((b2 & 0xF) << 2); - ret = CEscape(escaped, e1, out, &i, *outLen, 0); - if (ret == 0) - ret = CEscape(escaped, e2, out, &i, *outLen, 0); + ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly); + if (ret == 0) + ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly); if (ret == 0) { /* third */ if (twoBytes) - ret = CEscape(escaped, e3, out, &i, *outLen, 0); - else - ret = CEscape(escaped, '=', out, &i, *outLen, 1); + ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly); + else + ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly); } /* fourth always pad */ if (ret == 0) - ret = CEscape(escaped, '=', out, &i, *outLen, 1); - } + ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly); + } - if (ret == 0) - ret = CEscape(escaped, '\n', out, &i, *outLen, 1); + if (ret == 0 && escaped != WC_NO_NL_ENC) + ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly); - if (i != outSz && escaped == 0 && ret == 0) - return ASN_INPUT_E; + if (i != outSz && escaped != 1 && ret == 0) + return ASN_INPUT_E; +/* If the output buffer has a room for an extra byte, add a null terminator */ + if (out && *outLen > i) + out[i]= '\0'; *outLen = i; - return ret; + + if (ret == 0) + return getSzOnly ? LENGTH_ONLY_E : 0; + + return ret; } /* Base64 Encode, PEM style, with \n line endings */ int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen) { - return DoBase64_Encode(in, inLen, out, outLen, 0); + return DoBase64_Encode(in, inLen, out, outLen, WC_STD_ENC); } -/* Base64 Encode, with %0A esacped line endings instead of \n */ +/* Base64 Encode, with %0A escaped line endings instead of \n */ int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen) { - return DoBase64_Encode(in, inLen, out, outLen, 1); + return DoBase64_Encode(in, inLen, out, outLen, WC_ESC_NL_ENC); } +int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen) +{ + return DoBase64_Encode(in, inLen, out, outLen, WC_NO_NL_ENC); +} -#endif /* defined(WOLFSSL_BASE64_ENCODE) */ +#endif /* WOLFSSL_BASE64_ENCODE */ -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) +#ifdef WOLFSSL_BASE16 static const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, @@ -345,8 +418,11 @@ int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) word32 inIdx = 0; word32 outIdx = 0; + if (in == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; + if (inLen == 1 && *outLen && in) { - byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */ + byte b = in[inIdx++] - BASE16_MIN; /* 0 starts at 0x30 */ /* sanity check */ if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) @@ -356,7 +432,7 @@ int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) if (b == BAD) return ASN_INPUT_E; - + out[outIdx++] = b; *outLen = outIdx; @@ -370,8 +446,8 @@ int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) return BAD_FUNC_ARG; while (inLen) { - byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */ - byte b2 = in[inIdx++] - 0x30; + byte b = in[inIdx++] - BASE16_MIN; /* 0 starts at 0x30 */ + byte b2 = in[inIdx++] - BASE16_MIN; /* sanity checks */ if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) @@ -384,7 +460,7 @@ int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) if (b == BAD || b2 == BAD) return ASN_INPUT_E; - + out[outIdx++] = (byte)((b << 4) | b2); inLen -= 2; } @@ -393,7 +469,43 @@ int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) return 0; } +int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen) +{ + word32 outIdx = 0; + word32 i; + byte hb, lb; -#endif /* (OPENSSL_EXTRA) || (HAVE_WEBSERVER) || (HAVE_FIPS) */ + if (in == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; -#endif /* NO_CODING */ + if (*outLen < (2 * inLen + 1)) + return BAD_FUNC_ARG; + + for (i = 0; i < inLen; i++) { + hb = in[i] >> 4; + lb = in[i] & 0x0f; + + /* ASCII value */ + hb += '0'; + if (hb > '9') + hb += 7; + + /* ASCII value */ + lb += '0'; + if (lb>'9') + lb += 7; + + out[outIdx++] = hb; + out[outIdx++] = lb; + } + + /* force 0 at this end */ + out[outIdx++] = 0; + + *outLen = outIdx; + return 0; +} + +#endif /* WOLFSSL_BASE16 */ + +#endif /* !NO_CODING */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/compress.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/compress.c index a01c071dc..28d04f02d 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/compress.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/compress.c @@ -1,9 +1,9 @@ /* compress.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. * - * This file is part of wolfSSL. (formerly known as CyaSSL) - wc_* * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -35,6 +36,7 @@ #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif @@ -65,23 +67,24 @@ static void myFree(void* opaque, void* memory) #endif -int wc_Compress(byte* out, word32 outSz, const byte* in, word32 inSz, word32 flags) /* * out - pointer to destination buffer * 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 * buffer should be srcSz + 0.1% + 12. */ +int wc_Compress_ex(byte* out, word32 outSz, const byte* in, word32 inSz, + word32 flags, word32 windowBits) { z_stream stream; int result = 0; @@ -101,7 +104,8 @@ int wc_Compress(byte* out, word32 outSz, const byte* in, word32 inSz, word32 fla stream.opaque = (voidpf)0; if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, - DEFLATE_DEFAULT_WINDOWBITS, DEFLATE_DEFAULT_MEMLEVEL, + DEFLATE_DEFAULT_WINDOWBITS | windowBits, + DEFLATE_DEFAULT_MEMLEVEL, flags ? Z_FIXED : Z_DEFAULT_STRATEGY) != Z_OK) return COMPRESS_INIT_E; @@ -118,19 +122,37 @@ int wc_Compress(byte* out, word32 outSz, const byte* in, word32 inSz, word32 fla return result; } +int wc_Compress(byte* out, word32 outSz, const byte* in, word32 inSz, word32 flags) +{ + return wc_Compress_ex(out, outSz, in, inSz, flags, 0); +} -int wc_DeCompress(byte* out, word32 outSz, const byte* in, word32 inSz) + +/* windowBits: +* deflateInit() and inflateInit(), as well as deflateInit2() and inflateInit2() + with windowBits in 0..15 all process zlib-wrapped deflate data. + (See RFC 1950 and RFC 1951.) +* deflateInit2() and inflateInit2() with negative windowBits in -1..-15 process + raw deflate data with no header or trailer. +* deflateInit2() and inflateInit2() with windowBits in 16..31, i.e. 16 + added to 0..15, process gzip-wrapped deflate data (RFC 1952). +* inflateInit2() with windowBits in 32..47 (32 added to 0..15) will + automatically detect either a gzip or zlib header (but not raw deflate + data), and decompress accordingly. +*/ +int wc_DeCompress_ex(byte* out, word32 outSz, const byte* in, word32 inSz, + int windowBits) /* * out - pointer to destination buffer * 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 + * windowBits - flags to control how decompress operates * * return: * negative - error code * positive - bytes stored in out buffer - */ + */ { z_stream stream; int result = 0; @@ -148,14 +170,15 @@ int wc_DeCompress(byte* out, word32 outSz, const byte* in, word32 inSz) stream.zfree = (free_func)myFree; stream.opaque = (voidpf)0; - if (inflateInit2(&stream, DEFLATE_DEFAULT_WINDOWBITS) != Z_OK) + if (inflateInit2(&stream, DEFLATE_DEFAULT_WINDOWBITS | windowBits) != Z_OK) return DECOMPRESS_INIT_E; - if (inflate(&stream, Z_FINISH) != Z_STREAM_END) { + result = inflate(&stream, Z_FINISH); + if (result != Z_STREAM_END) { inflateEnd(&stream); return DECOMPRESS_E; } - + result = (int)stream.total_out; if (inflateEnd(&stream) != Z_OK) @@ -165,5 +188,11 @@ int wc_DeCompress(byte* out, word32 outSz, const byte* in, word32 inSz) } +int wc_DeCompress(byte* out, word32 outSz, const byte* in, word32 inSz) +{ + return wc_DeCompress_ex(out, outSz, in, inSz, 0); +} + + #endif /* HAVE_LIBZ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/cpuid.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/cpuid.c new file mode 100644 index 000000000..85c4bf2d6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/cpuid.c @@ -0,0 +1,110 @@ +/* cpuid.c + * + * Copyright (C) 2006-2020 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; + int got_amd_cpu = 0; + unsigned int reg[5]; + reg[4] = '\0'; + cpuid(reg, 0, 0); + + /* check for Intel cpu */ + 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; + } + + /* check for AMD cpu */ + if (XMEMCMP((char *)&(reg[EBX]), "Auth", 4) == 0 && + XMEMCMP((char *)&(reg[EDX]), "enti", 4) == 0 && + XMEMCMP((char *)&(reg[ECX]), "cAMD", 4) == 0) { + got_amd_cpu = 1; + } + + if (got_intel_cpu || got_amd_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, 25)) { 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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/cryptocb.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/cryptocb.c new file mode 100644 index 000000000..79f89dbb1 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/cryptocb.c @@ -0,0 +1,648 @@ +/* cryptocb.c + * + * Copyright (C) 2006-2020 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 3 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, see . + */ + +/* This framework provides a central place for crypto hardware integration + using the devId scheme. If not supported return `CRYPTOCB_UNAVAILABLE`. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLF_CRYPTO_CB + +#include +#include +#include + + +/* TODO: Consider linked list with mutex */ +#ifndef MAX_CRYPTO_DEVID_CALLBACKS +#define MAX_CRYPTO_DEVID_CALLBACKS 8 +#endif + +typedef struct CryptoCb { + int devId; + CryptoDevCallbackFunc cb; + void* ctx; +} CryptoCb; +static WOLFSSL_GLOBAL CryptoCb gCryptoDev[MAX_CRYPTO_DEVID_CALLBACKS]; + +static CryptoCb* wc_CryptoCb_FindDevice(int devId) +{ + int i; + for (i=0; idevId = devId; + dev->cb = cb; + dev->ctx = ctx; + + return 0; +} + +void wc_CryptoCb_UnRegisterDevice(int devId) +{ + CryptoCb* dev = wc_CryptoCb_FindDevice(devId); + if (dev) { + XMEMSET(dev, 0, sizeof(*dev)); + dev->devId = INVALID_DEVID; + } +} + +#ifndef NO_RSA +int wc_CryptoCb_Rsa(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_RSA; + cryptoInfo.pk.rsa.in = in; + cryptoInfo.pk.rsa.inLen = inLen; + cryptoInfo.pk.rsa.out = out; + cryptoInfo.pk.rsa.outLen = outLen; + cryptoInfo.pk.rsa.type = type; + cryptoInfo.pk.rsa.key = key; + cryptoInfo.pk.rsa.rng = rng; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +#ifdef WOLFSSL_KEY_GEN +int wc_CryptoCb_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_RSA_KEYGEN; + cryptoInfo.pk.rsakg.key = key; + cryptoInfo.pk.rsakg.size = size; + cryptoInfo.pk.rsakg.e = e; + cryptoInfo.pk.rsakg.rng = rng; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +int wc_CryptoCb_MakeEccKey(WC_RNG* rng, int keySize, ecc_key* key, int curveId) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_EC_KEYGEN; + cryptoInfo.pk.eckg.rng = rng; + cryptoInfo.pk.eckg.size = keySize; + cryptoInfo.pk.eckg.key = key; + cryptoInfo.pk.eckg.curveId = curveId; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_Ecdh(ecc_key* private_key, ecc_key* public_key, + byte* out, word32* outlen) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (private_key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(private_key->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_ECDH; + cryptoInfo.pk.ecdh.private_key = private_key; + cryptoInfo.pk.ecdh.public_key = public_key; + cryptoInfo.pk.ecdh.out = out; + cryptoInfo.pk.ecdh.outlen = outlen; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_EccSign(const byte* in, word32 inlen, byte* out, + word32 *outlen, WC_RNG* rng, ecc_key* key) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_ECDSA_SIGN; + cryptoInfo.pk.eccsign.in = in; + cryptoInfo.pk.eccsign.inlen = inlen; + cryptoInfo.pk.eccsign.out = out; + cryptoInfo.pk.eccsign.outlen = outlen; + cryptoInfo.pk.eccsign.rng = rng; + cryptoInfo.pk.eccsign.key = key; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_EccVerify(const byte* sig, word32 siglen, + const byte* hash, word32 hashlen, int* res, ecc_key* key) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_ECDSA_VERIFY; + cryptoInfo.pk.eccverify.sig = sig; + cryptoInfo.pk.eccverify.siglen = siglen; + cryptoInfo.pk.eccverify.hash = hash; + cryptoInfo.pk.eccverify.hashlen = hashlen; + cryptoInfo.pk.eccverify.res = res; + cryptoInfo.pk.eccverify.key = key; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* HAVE_ECC */ + +#ifndef NO_AES +#ifdef HAVE_AESGCM +int wc_CryptoCb_AesGcmEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_GCM; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.aesgcm_enc.aes = aes; + cryptoInfo.cipher.aesgcm_enc.out = out; + cryptoInfo.cipher.aesgcm_enc.in = in; + cryptoInfo.cipher.aesgcm_enc.sz = sz; + cryptoInfo.cipher.aesgcm_enc.iv = iv; + cryptoInfo.cipher.aesgcm_enc.ivSz = ivSz; + cryptoInfo.cipher.aesgcm_enc.authTag = authTag; + cryptoInfo.cipher.aesgcm_enc.authTagSz = authTagSz; + cryptoInfo.cipher.aesgcm_enc.authIn = authIn; + cryptoInfo.cipher.aesgcm_enc.authInSz = authInSz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_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) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_GCM; + cryptoInfo.cipher.enc = 0; + cryptoInfo.cipher.aesgcm_dec.aes = aes; + cryptoInfo.cipher.aesgcm_dec.out = out; + cryptoInfo.cipher.aesgcm_dec.in = in; + cryptoInfo.cipher.aesgcm_dec.sz = sz; + cryptoInfo.cipher.aesgcm_dec.iv = iv; + cryptoInfo.cipher.aesgcm_dec.ivSz = ivSz; + cryptoInfo.cipher.aesgcm_dec.authTag = authTag; + cryptoInfo.cipher.aesgcm_dec.authTagSz = authTagSz; + cryptoInfo.cipher.aesgcm_dec.authIn = authIn; + cryptoInfo.cipher.aesgcm_dec.authInSz = authInSz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* HAVE_AESGCM */ + +#ifdef HAVE_AES_CBC +int wc_CryptoCb_AesCbcEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_CBC; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.aescbc.aes = aes; + cryptoInfo.cipher.aescbc.out = out; + cryptoInfo.cipher.aescbc.in = in; + cryptoInfo.cipher.aescbc.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_AesCbcDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_CBC; + cryptoInfo.cipher.enc = 0; + cryptoInfo.cipher.aescbc.aes = aes; + cryptoInfo.cipher.aescbc.out = out; + cryptoInfo.cipher.aescbc.in = in; + cryptoInfo.cipher.aescbc.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* HAVE_AES_CBC */ +#endif /* !NO_AES */ + +#ifndef NO_DES3 +int wc_CryptoCb_Des3Encrypt(Des3* des3, byte* out, + const byte* in, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (des3) { + dev = wc_CryptoCb_FindDevice(des3->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_DES3; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.des3.des = des3; + cryptoInfo.cipher.des3.out = out; + cryptoInfo.cipher.des3.in = in; + cryptoInfo.cipher.des3.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_Des3Decrypt(Des3* des3, byte* out, + const byte* in, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (des3) { + dev = wc_CryptoCb_FindDevice(des3->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_DES3; + cryptoInfo.cipher.enc = 0; + cryptoInfo.cipher.des3.des = des3; + cryptoInfo.cipher.des3.out = out; + cryptoInfo.cipher.des3.in = in; + cryptoInfo.cipher.des3.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* !NO_DES3 */ + +#ifndef NO_SHA +int wc_CryptoCb_ShaHash(wc_Sha* sha, const byte* in, + word32 inSz, byte* digest) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (sha) { + dev = wc_CryptoCb_FindDevice(sha->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_HASH; + cryptoInfo.hash.type = WC_HASH_TYPE_SHA; + cryptoInfo.hash.sha1 = sha; + cryptoInfo.hash.in = in; + cryptoInfo.hash.inSz = inSz; + cryptoInfo.hash.digest = digest; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* !NO_SHA */ + +#ifndef NO_SHA256 +int wc_CryptoCb_Sha256Hash(wc_Sha256* sha256, const byte* in, + word32 inSz, byte* digest) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (sha256) { + dev = wc_CryptoCb_FindDevice(sha256->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_HASH; + cryptoInfo.hash.type = WC_HASH_TYPE_SHA256; + cryptoInfo.hash.sha256 = sha256; + cryptoInfo.hash.in = in; + cryptoInfo.hash.inSz = inSz; + cryptoInfo.hash.digest = digest; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* !NO_SHA256 */ + +#ifndef NO_HMAC +int wc_CryptoCb_Hmac(Hmac* hmac, int macType, const byte* in, word32 inSz, + byte* digest) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (hmac == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(hmac->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_HMAC; + cryptoInfo.hmac.macType = macType; + cryptoInfo.hmac.in = in; + cryptoInfo.hmac.inSz = inSz; + cryptoInfo.hmac.digest = digest; + cryptoInfo.hmac.hmac = hmac; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* !NO_HMAC */ + +#ifndef WC_NO_RNG +int wc_CryptoCb_RandomBlock(WC_RNG* rng, byte* out, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (rng) { + dev = wc_CryptoCb_FindDevice(rng->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_RNG; + cryptoInfo.rng.rng = rng; + cryptoInfo.rng.out = out; + cryptoInfo.rng.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_RandomSeed(OS_Seed* os, byte* seed, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(os->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_SEED; + cryptoInfo.seed.os = os; + cryptoInfo.seed.seed = seed; + cryptoInfo.seed.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* !WC_NO_RNG */ + +#endif /* WOLF_CRYPTO_CB */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/curve25519.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/curve25519.c index b745a046c..39e1216a0 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/curve25519.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/curve25519.c @@ -1,8 +1,8 @@ /* curve25519.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Based On Daniel J Bernstein's curve25519 Public Domain ref10 work. */ @@ -35,202 +36,449 @@ #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif +#if defined(FREESCALE_LTC_ECC) + #include +#endif + const curve25519_set_type curve25519_sets[] = { -{ - 32, + { + CURVE25519_KEYSIZE, "CURVE25519", -} + } }; - - -int wc_curve25519_make_key(RNG* rng, int keysize, curve25519_key* key) +int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key) { - unsigned char basepoint[CURVE25519_KEYSIZE] = {9}; - unsigned char n[CURVE25519_KEYSIZE]; - unsigned char p[CURVE25519_KEYSIZE]; - int i; - int ret; +#ifdef FREESCALE_LTC_ECC + const ECPoint* basepoint = wc_curve25519_GetBasePoint(); +#else + unsigned char basepoint[CURVE25519_KEYSIZE] = {9}; +#endif + int ret; - if (key == NULL || rng == NULL) - return ECC_BAD_ARG_E; + if (key == NULL || rng == NULL) + return BAD_FUNC_ARG; - /* currently only a key size of 32 bytes is used */ - if (keysize != CURVE25519_KEYSIZE) - return ECC_BAD_ARG_E; + /* currently only a key size of 32 bytes is used */ + if (keysize != CURVE25519_KEYSIZE) + return ECC_BAD_ARG_E; - /* get random number from RNG */ - ret = wc_RNG_GenerateBlock(rng, n, keysize); - if (ret != 0) - return ret; +#ifndef FREESCALE_LTC_ECC + fe_init(); +#endif - for (i = 0; i < keysize; ++i) key->k.point[i] = n[i]; - key->k.point[ 0] &= 248; - key->k.point[31] &= 127; - key->k.point[31] |= 64; + /* random number for private key */ + ret = wc_RNG_GenerateBlock(rng, key->k.point, keysize); + if (ret != 0) + return ret; - /* compute public key */ - ret = curve25519(p, key->k.point, basepoint); + /* Clamp the private key */ + key->k.point[0] &= 248; + key->k.point[CURVE25519_KEYSIZE-1] &= 63; /* same &=127 because |=64 after */ + key->k.point[CURVE25519_KEYSIZE-1] |= 64; - /* store keys in big endian format */ - for (i = 0; i < keysize; ++i) n[i] = key->k.point[i]; - for (i = 0; i < keysize; ++i) { - key->p.point[keysize - i - 1] = p[i]; - key->k.point[keysize - i - 1] = n[i]; - } + /* compute public key */ + #ifdef FREESCALE_LTC_ECC + ret = wc_curve25519(&key->p, key->k.point, basepoint, kLTC_Weierstrass); /* input basepoint on Weierstrass curve */ + #else + ret = curve25519(key->p.point, key->k.point, basepoint); + #endif + if (ret != 0) { + ForceZero(key->k.point, keysize); + ForceZero(key->p.point, keysize); + return ret; + } - ForceZero(n, keysize); - ForceZero(p, keysize); - - return ret; + return ret; } +#ifdef HAVE_CURVE25519_SHARED_SECRET int wc_curve25519_shared_secret(curve25519_key* private_key, curve25519_key* public_key, byte* out, word32* outlen) { - unsigned char k[CURVE25519_KEYSIZE]; - unsigned char p[CURVE25519_KEYSIZE]; - unsigned char o[CURVE25519_KEYSIZE]; + return wc_curve25519_shared_secret_ex(private_key, public_key, + out, outlen, EC25519_BIG_ENDIAN); +} + +int wc_curve25519_shared_secret_ex(curve25519_key* private_key, + curve25519_key* public_key, + byte* out, word32* outlen, int endian) +{ + #ifdef FREESCALE_LTC_ECC + ECPoint o = {{0}}; + #else + unsigned char o[CURVE25519_KEYSIZE]; + #endif int ret = 0; - int i; /* sanity check */ - if (private_key == NULL || public_key == NULL || out == NULL || - outlen == NULL) + 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[0] > 0x7F) + if (public_key->p.point[CURVE25519_KEYSIZE-1] > 0x7F) return ECC_BAD_ARG_E; - XMEMSET(p, 0, sizeof(p)); - XMEMSET(k, 0, sizeof(k)); - XMEMSET(out, 0, CURVE25519_KEYSIZE); - - for (i = 0; i < CURVE25519_KEYSIZE; ++i) { - p[i] = public_key->p.point [CURVE25519_KEYSIZE - i - 1]; - k[i] = private_key->k.point[CURVE25519_KEYSIZE - i - 1]; + #ifdef FREESCALE_LTC_ECC + ret = wc_curve25519(&o, private_key->k.point, &public_key->p, kLTC_Curve25519 /* input point P on Curve25519 */); + #else + ret = curve25519(o, private_key->k.point, public_key->p.point); + #endif + if (ret != 0) { + #ifdef FREESCALE_LTC_ECC + ForceZero(o.point, CURVE25519_KEYSIZE); + ForceZero(o.pointY, CURVE25519_KEYSIZE); + #else + ForceZero(o, CURVE25519_KEYSIZE); + #endif + return ret; } - ret = curve25519(o , k, p); + if (endian == EC25519_BIG_ENDIAN) { + int i; + /* put shared secret key in Big Endian format */ + for (i = 0; i < CURVE25519_KEYSIZE; i++) + #ifdef FREESCALE_LTC_ECC + out[i] = o.point[CURVE25519_KEYSIZE - i -1]; + #else + out[i] = o[CURVE25519_KEYSIZE - i -1]; + #endif + } + else /* put shared secret key in Little Endian format */ + #ifdef FREESCALE_LTC_ECC + XMEMCPY(out, o.point, CURVE25519_KEYSIZE); + #else + XMEMCPY(out, o, CURVE25519_KEYSIZE); + #endif + *outlen = CURVE25519_KEYSIZE; - for (i = 0; i < CURVE25519_KEYSIZE; ++i) { - out[i] = o[CURVE25519_KEYSIZE - i -1]; - } - - ForceZero(p, sizeof(p)); - ForceZero(k, sizeof(k)); - ForceZero(o, sizeof(o)); + #ifdef FREESCALE_LTC_ECC + ForceZero(o.point, CURVE25519_KEYSIZE); + ForceZero(o.pointY, CURVE25519_KEYSIZE); + #else + ForceZero(o, CURVE25519_KEYSIZE); + #endif return ret; } +#endif /* HAVE_CURVE25519_SHARED_SECRET */ -/* curve25519 uses a serialized string for key representation */ +#ifdef HAVE_CURVE25519_KEY_EXPORT + +/* export curve25519 public key (Big endian) + * return 0 on success */ int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen) { - word32 keySz; + return wc_curve25519_export_public_ex(key, out, outLen, EC25519_BIG_ENDIAN); +} +/* export curve25519 public key (Big or Little endian) + * return 0 on success */ +int wc_curve25519_export_public_ex(curve25519_key* key, byte* out, + word32* outLen, int endian) +{ if (key == NULL || out == NULL || outLen == NULL) return BAD_FUNC_ARG; - /* check size of outgoing key */ - keySz = wc_curve25519_size(key); + /* check and set outgoing key size */ + if (*outLen < CURVE25519_KEYSIZE) { + *outLen = CURVE25519_KEYSIZE; + return ECC_BAD_ARG_E; + } + *outLen = CURVE25519_KEYSIZE; - /* copy in public key */ - XMEMCPY(out, key->p.point, keySz); - *outLen = keySz; + if (endian == EC25519_BIG_ENDIAN) { + int i; + + /* read keys in Big Endian format */ + for (i = 0; i < CURVE25519_KEYSIZE; i++) + out[i] = key->p.point[CURVE25519_KEYSIZE - i - 1]; + } + else + XMEMCPY(out, key->p.point, CURVE25519_KEYSIZE); return 0; } -/* import curve25519 public key - return 0 on success */ +#endif /* HAVE_CURVE25519_KEY_EXPORT */ + +#ifdef HAVE_CURVE25519_KEY_IMPORT + +/* import curve25519 public key (Big endian) + * return 0 on success */ int wc_curve25519_import_public(const byte* in, word32 inLen, curve25519_key* key) { - word32 keySz; + return wc_curve25519_import_public_ex(in, inLen, key, EC25519_BIG_ENDIAN); +} +/* import curve25519 public key (Big or Little endian) + * return 0 on success */ +int wc_curve25519_import_public_ex(const byte* in, word32 inLen, + curve25519_key* key, int endian) +{ /* sanity check */ if (key == NULL || in == NULL) - return ECC_BAD_ARG_E; + return BAD_FUNC_ARG; /* check size of incoming keys */ - keySz = wc_curve25519_size(key); - if (inLen != keySz) + if (inLen != CURVE25519_KEYSIZE) return ECC_BAD_ARG_E; - XMEMCPY(key->p.point, in, inLen); + if (endian == EC25519_BIG_ENDIAN) { + int i; + + /* read keys in Big Endian format */ + for (i = 0; i < CURVE25519_KEYSIZE; i++) + key->p.point[i] = in[CURVE25519_KEYSIZE - i - 1]; + } + else + 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; + ltcPoint.X = &key->p.point[0]; + ltcPoint.Y = &key->p.pointY[0]; + LTC_PKHA_Curve25519ComputeY(<cPoint); + #endif + return 0; } +/* Check the public key value (big or little endian) + * + * pub Public key bytes. + * pubSz Size of public key in bytes. + * endian Public key bytes passed in as big-endian or little-endian. + * returns BAD_FUNC_ARGS when pub is NULL, + * BUFFER_E when size of public key is zero; + * ECC_OUT_OF_RANGE_E if the high bit is set; + * ECC_BAD_ARG_E if key length is not 32 bytes, public key value is + * zero or one; and + * 0 otherwise. + */ +int wc_curve25519_check_public(const byte* pub, word32 pubSz, int endian) +{ + word32 i; -/* export curve25519 private key only raw, outLen is in/out size - return 0 on success */ + if (pub == NULL) + return BAD_FUNC_ARG; + + /* Check for empty key data */ + if (pubSz == 0) + return BUFFER_E; + + /* Check key length */ + if (pubSz != CURVE25519_KEYSIZE) + return ECC_BAD_ARG_E; + + + if (endian == EC25519_LITTLE_ENDIAN) { + /* Check for value of zero or one */ + for (i = pubSz - 1; i > 0; i--) { + if (pub[i] != 0) + break; + } + if (i == 0 && (pub[0] == 0 || pub[0] == 1)) + return ECC_BAD_ARG_E; + + /* Check high bit set */ + if (pub[CURVE25519_KEYSIZE-1] & 0x80) + return ECC_OUT_OF_RANGE_E; + } + else { + /* Check for value of zero or one */ + for (i = 0; i < pubSz-1; i++) { + if (pub[i] != 0) + break; + } + if (i == pubSz - 1 && (pub[i] == 0 || pub[i] == 1)) + return ECC_BAD_ARG_E; + + /* Check high bit set */ + if (pub[0] & 0x80) + return ECC_OUT_OF_RANGE_E; + } + + return 0; +} + +#endif /* HAVE_CURVE25519_KEY_IMPORT */ + + +#ifdef HAVE_CURVE25519_KEY_EXPORT + +/* export curve25519 private key only raw (Big endian) + * outLen is in/out size + * return 0 on success */ int wc_curve25519_export_private_raw(curve25519_key* key, byte* out, word32* outLen) { - word32 keySz; + return wc_curve25519_export_private_raw_ex(key, out, outLen, + EC25519_BIG_ENDIAN); +} +/* export curve25519 private key only raw (Big or Little endian) + * outLen is in/out size + * return 0 on success */ +int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out, + word32* outLen, int endian) +{ /* sanity check */ if (key == NULL || out == NULL || outLen == NULL) - return ECC_BAD_ARG_E; + return BAD_FUNC_ARG; - keySz = wc_curve25519_size(key); - *outLen = keySz; - XMEMSET(out, 0, keySz); - XMEMCPY(out, key->k.point, keySz); + /* check size of outgoing buffer */ + if (*outLen < CURVE25519_KEYSIZE) { + *outLen = CURVE25519_KEYSIZE; + return ECC_BAD_ARG_E; + } + *outLen = CURVE25519_KEYSIZE; + + if (endian == EC25519_BIG_ENDIAN) { + int i; + + /* put the key in Big Endian format */ + for (i = 0; i < CURVE25519_KEYSIZE; i++) + out[i] = key->k.point[CURVE25519_KEYSIZE - i - 1]; + } + else + XMEMCPY(out, key->k.point, CURVE25519_KEYSIZE); return 0; } - -/* curve25519 private key import. - Public key to match private key needs to be imported too */ -int wc_curve25519_import_private_raw(const byte* priv, word32 privSz, - const byte* pub, word32 pubSz, curve25519_key* key) +/* curve25519 key pair export (Big or Little endian) + * return 0 on success */ +int wc_curve25519_export_key_raw(curve25519_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz) { - int ret = 0; - word32 keySz; + return wc_curve25519_export_key_raw_ex(key, priv, privSz, + pub, pubSz, EC25519_BIG_ENDIAN); +} +/* curve25519 key pair export (Big or Little endian) + * return 0 on success */ +int wc_curve25519_export_key_raw_ex(curve25519_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz, + int endian) +{ + int ret; + + /* export private part */ + ret = wc_curve25519_export_private_raw_ex(key, priv, privSz, endian); + if (ret != 0) + return ret; + + /* export public part */ + return wc_curve25519_export_public_ex(key, pub, pubSz, endian); +} + +#endif /* HAVE_CURVE25519_KEY_EXPORT */ + +#ifdef HAVE_CURVE25519_KEY_IMPORT + +/* curve25519 private key import (Big endian) + * Public key to match private key needs to be imported too + * return 0 on success */ +int wc_curve25519_import_private_raw(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + curve25519_key* key) +{ + return wc_curve25519_import_private_raw_ex(priv, privSz, pub, pubSz, + key, EC25519_BIG_ENDIAN); +} + +/* curve25519 private key import (Big or Little endian) + * Public key to match private key needs to be imported too + * return 0 on success */ +int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + curve25519_key* key, int endian) +{ + int ret; + + /* import private part */ + ret = wc_curve25519_import_private_ex(priv, privSz, key, endian); + if (ret != 0) + return ret; + + /* import public part */ + return wc_curve25519_import_public_ex(pub, pubSz, key, endian); +} + +/* curve25519 private key import only. (Big endian) + * return 0 on success */ +int wc_curve25519_import_private(const byte* priv, word32 privSz, + curve25519_key* key) +{ + return wc_curve25519_import_private_ex(priv, privSz, + key, EC25519_BIG_ENDIAN); +} + +/* curve25519 private key import only. (Big or Little endian) + * return 0 on success */ +int wc_curve25519_import_private_ex(const byte* priv, word32 privSz, + curve25519_key* key, int endian) +{ /* sanity check */ - if (key == NULL || priv == NULL || pub == NULL) - return ECC_BAD_ARG_E; + if (key == NULL || priv == NULL) + return BAD_FUNC_ARG; /* check size of incoming keys */ - keySz = wc_curve25519_size(key); - if (privSz != keySz || pubSz != keySz) - return ECC_BAD_ARG_E; + if ((int)privSz != CURVE25519_KEYSIZE) + return ECC_BAD_ARG_E; - XMEMCPY(key->k.point, priv, privSz); - XMEMCPY(key->p.point, pub, pubSz); + if (endian == EC25519_BIG_ENDIAN) { + int i; - return ret; + /* read the key in Big Endian format */ + for (i = 0; i < CURVE25519_KEYSIZE; i++) + key->k.point[i] = priv[CURVE25519_KEYSIZE - i - 1]; + } + else + XMEMCPY(key->k.point, priv, CURVE25519_KEYSIZE); + + key->dp = &curve25519_sets[0]; + + /* Clamp the key */ + key->k.point[0] &= 248; + key->k.point[privSz-1] &= 63; /* same &=127 because |=64 after */ + key->k.point[privSz-1] |= 64; + + return 0; } +#endif /* HAVE_CURVE25519_KEY_IMPORT */ + int wc_curve25519_init(curve25519_key* key) { - word32 keySz; - if (key == NULL) - return ECC_BAD_ARG_E; + return BAD_FUNC_ARG; + + XMEMSET(key, 0, sizeof(*key)); /* currently the format for curve25519 */ key->dp = &curve25519_sets[0]; - keySz = key->dp->size; - XMEMSET(key->k.point, 0, keySz); - XMEMSET(key->p.point, 0, keySz); +#ifndef FREESCALE_LTC_ECC + fe_init(); +#endif return 0; } @@ -245,13 +493,18 @@ void wc_curve25519_free(curve25519_key* key) key->dp = NULL; ForceZero(key->p.point, sizeof(key->p.point)); ForceZero(key->k.point, sizeof(key->k.point)); + #ifdef FREESCALE_LTC_ECC + ForceZero(key->p.point, sizeof(key->p.pointY)); + ForceZero(key->k.point, sizeof(key->k.pointY)); + #endif } /* get key size */ int wc_curve25519_size(curve25519_key* key) { - if (key == NULL) return 0; + if (key == NULL) + return 0; return key->dp->size; } diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/curve448.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/curve448.c new file mode 100644 index 000000000..135f2380e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/curve448.c @@ -0,0 +1,635 @@ +/* curve448.c + * + * Copyright (C) 2006-2020 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 + */ + +/* Implemented to: RFC 7748 */ + +/* Based On Daniel J Bernstein's curve25519 Public Domain ref10 work. + * Reworked for curve448 by Sean Parkinson. + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_CURVE448 + +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +/* Make a new curve448 private/public key. + * + * rng [in] Random number generator. + * keysize [in] Size of the key to generate. + * key [in] Curve448 key object. + * returns BAD_FUNC_ARG when rng or key are NULL, + * ECC_BAD_ARG_E when keysize is not CURVE448_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_make_key(WC_RNG* rng, int keysize, curve448_key* key) +{ + unsigned char basepoint[CURVE448_KEY_SIZE] = {5}; + int ret = 0; + + if ((key == NULL) || (rng == NULL)) { + ret = BAD_FUNC_ARG; + } + + /* currently only a key size of 56 bytes is used */ + if ((ret == 0) && (keysize != CURVE448_KEY_SIZE)) { + ret = ECC_BAD_ARG_E; + } + + if (ret == 0) { + fe448_init(); + + /* random number for private key */ + ret = wc_RNG_GenerateBlock(rng, key->k, keysize); + } + if (ret == 0) { + /* Clamp the private key */ + key->k[0] &= 0xfc; + key->k[CURVE448_KEY_SIZE-1] |= 0x80; + + /* compute public key */ + ret = curve448(key->p, key->k, basepoint); + if (ret != 0) { + ForceZero(key->k, keysize); + ForceZero(key->p, keysize); + } + } + + return ret; +} + +#ifdef HAVE_CURVE448_SHARED_SECRET + +/* Calculate the shared secret from the private key and peer's public key. + * Calculation over curve448. + * Secret encoded big-endian. + * + * private_key [in] Curve448 private key. + * public_key [in] Curve448 public key. + * out [in] Array to hold shared secret. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL or outLen is less than + * CURVE448_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_shared_secret(curve448_key* private_key, + curve448_key* public_key, + byte* out, word32* outLen) +{ + return wc_curve448_shared_secret_ex(private_key, public_key, out, outLen, + EC448_BIG_ENDIAN); +} + +/* Calculate the shared secret from the private key and peer's public key. + * Calculation over curve448. + * + * private_key [in] Curve448 private key. + * public_key [in] Curve448 public key. + * out [in] Array to hold shared secret. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * endian [in] Endianness to use when encoding number in array. + * returns BAD_FUNC_ARG when a parameter is NULL or outLen is less than + * CURVE448_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_shared_secret_ex(curve448_key* private_key, + curve448_key* public_key, + byte* out, word32* outLen, int endian) +{ + unsigned char o[CURVE448_PUB_KEY_SIZE]; + int ret = 0; + int i; + + /* sanity check */ + if ((private_key == NULL) || (public_key == NULL) || (out == NULL) || + (outLen == NULL) || (*outLen < CURVE448_PUB_KEY_SIZE)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + ret = curve448(o, private_key->k, public_key->p); + } + if (ret == 0) { + if (endian == EC448_BIG_ENDIAN) { + /* put shared secret key in Big Endian format */ + for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) { + out[i] = o[CURVE448_PUB_KEY_SIZE - i -1]; + } + } + else { + /* put shared secret key in Little Endian format */ + XMEMCPY(out, o, CURVE448_PUB_KEY_SIZE); + } + + *outLen = CURVE448_PUB_KEY_SIZE; + } + + ForceZero(o, CURVE448_PUB_KEY_SIZE); + + return ret; +} + +#endif /* HAVE_CURVE448_SHARED_SECRET */ + +#ifdef HAVE_CURVE448_KEY_EXPORT + +/* Export the curve448 public key. + * Public key encoded big-endian. + * + * key [in] Curve448 public key. + * out [in] Array to hold public key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when outLen is less than CURVE448_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_export_public(curve448_key* key, byte* out, word32* outLen) +{ + return wc_curve448_export_public_ex(key, out, outLen, EC448_BIG_ENDIAN); +} + +/* Export the curve448 public key. + * + * key [in] Curve448 public key. + * out [in] Array to hold public key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * endian [in] Endianness to use when encoding number in array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when outLen is less than CURVE448_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_export_public_ex(curve448_key* key, byte* out, word32* outLen, + int endian) +{ + int ret = 0; + int i; + + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + ret = BAD_FUNC_ARG; + } + + /* check and set outgoing key size */ + if ((ret == 0) && (*outLen < CURVE448_PUB_KEY_SIZE)) { + *outLen = CURVE448_PUB_KEY_SIZE; + ret = ECC_BAD_ARG_E; + } + if (ret == 0) { + *outLen = CURVE448_PUB_KEY_SIZE; + + if (endian == EC448_BIG_ENDIAN) { + /* read keys in Big Endian format */ + for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) { + out[i] = key->p[CURVE448_PUB_KEY_SIZE - i - 1]; + } + } + else { + XMEMCPY(out, key->p, CURVE448_PUB_KEY_SIZE); + } + } + + return ret; +} + +#endif /* HAVE_CURVE448_KEY_EXPORT */ + +#ifdef HAVE_CURVE448_KEY_IMPORT + +/* Import a curve448 public key from a byte array. + * Public key encoded in big-endian. + * + * in [in] Array holding public key. + * inLen [in] Number of bytes of data in array. + * key [in] Curve448 public key. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when inLen is less than CURVE448_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_import_public(const byte* in, word32 inLen, curve448_key* key) +{ + return wc_curve448_import_public_ex(in, inLen, key, EC448_BIG_ENDIAN); +} + +/* Import a curve448 public key from a byte array. + * + * in [in] Array holding public key. + * inLen [in] Number of bytes of data in array. + * key [in] Curve448 public key. + * endian [in] Endianness of encoded number in byte array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when inLen is less than CURVE448_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_import_public_ex(const byte* in, word32 inLen, + curve448_key* key, int endian) +{ + int ret = 0; + int i; + + /* sanity check */ + if ((key == NULL) || (in == NULL)) { + ret = BAD_FUNC_ARG; + } + + /* check size of incoming keys */ + if ((ret == 0) && (inLen != CURVE448_PUB_KEY_SIZE)) { + ret = ECC_BAD_ARG_E; + } + + if (ret == 0) { + if (endian == EC448_BIG_ENDIAN) { + /* read keys in Big Endian format */ + for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) { + key->p[i] = in[CURVE448_PUB_KEY_SIZE - i - 1]; + } + } + else + XMEMCPY(key->p, in, inLen); + } + + return ret; +} + +/* Check the public key value (big or little endian) + * + * pub [in] Public key bytes. + * pubSz [in] Size of public key in bytes. + * endian [in] Public key bytes passed in as big-endian or little-endian. + * returns BAD_FUNC_ARGS when pub is NULL, + * ECC_BAD_ARG_E when key length is not 56 bytes, public key value is + * zero or one; + * BUFFER_E when size of public key is zero; + * 0 otherwise. + */ +int wc_curve448_check_public(const byte* pub, word32 pubSz, int endian) +{ + int ret = 0; + word32 i; + + if (pub == NULL) { + ret = BAD_FUNC_ARG; + } + + /* Check for empty key data */ + if ((ret == 0) && (pubSz == 0)) { + ret = BUFFER_E; + } + + /* Check key length */ + if ((ret == 0) && (pubSz != CURVE448_PUB_KEY_SIZE)) { + ret = ECC_BAD_ARG_E; + } + + if (ret == 0) { + if (endian == EC448_LITTLE_ENDIAN) { + /* Check for value of zero or one */ + for (i = pubSz - 1; i > 0; i--) { + if (pub[i] != 0) { + break; + } + } + if ((i == 0) && (pub[0] == 0 || pub[0] == 1)) { + return ECC_BAD_ARG_E; + } + } + else { + /* Check for value of zero or one */ + for (i = 0; i < pubSz-1; i++) { + if (pub[i] != 0) { + break; + } + } + if ((i == pubSz - 1) && (pub[i] == 0 || pub[i] == 1)) { + ret = ECC_BAD_ARG_E; + } + } + } + + return ret; +} + +#endif /* HAVE_CURVE448_KEY_IMPORT */ + + +#ifdef HAVE_CURVE448_KEY_EXPORT + +/* Export the curve448 private key raw form. + * Private key encoded big-endian. + * + * key [in] Curve448 private key. + * out [in] Array to hold private key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when outLen is less than CURVE448_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_export_private_raw(curve448_key* key, byte* out, word32* outLen) +{ + return wc_curve448_export_private_raw_ex(key, out, outLen, + EC448_BIG_ENDIAN); +} + +/* Export the curve448 private key raw form. + * + * key [in] Curve448 private key. + * out [in] Array to hold private key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * endian [in] Endianness to use when encoding number in array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when outLen is less than CURVE448_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_export_private_raw_ex(curve448_key* key, byte* out, + word32* outLen, int endian) +{ + int ret = 0; + int i; + + /* sanity check */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + ret = BAD_FUNC_ARG; + } + + /* check size of outgoing buffer */ + if ((ret == 0) && (*outLen < CURVE448_KEY_SIZE)) { + *outLen = CURVE448_KEY_SIZE; + ret = ECC_BAD_ARG_E; + } + if (ret == 0) { + *outLen = CURVE448_KEY_SIZE; + + if (endian == EC448_BIG_ENDIAN) { + /* put the key in Big Endian format */ + for (i = 0; i < CURVE448_KEY_SIZE; i++) { + out[i] = key->k[CURVE448_KEY_SIZE - i - 1]; + } + } + else { + XMEMCPY(out, key->k, CURVE448_KEY_SIZE); + } + } + + return ret; +} + +/* Export the curve448 private and public keys in raw form. + * Private and public key encoded big-endian. + * + * key [in] Curve448 private key. + * priv [in] Array to hold private key. + * privSz [in/out] On in, the number of bytes in private key array. + * On out, the number bytes put into private key array. + * pub [in] Array to hold public key. + * pubSz [in/out] On in, the number of bytes in public key array. + * On out, the number bytes put into public key array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE or pubSz is + * less than CURVE448_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_export_key_raw(curve448_key* key, byte* priv, word32 *privSz, + byte* pub, word32 *pubSz) +{ + return wc_curve448_export_key_raw_ex(key, priv, privSz, pub, pubSz, + EC448_BIG_ENDIAN); +} + +/* Export the curve448 private and public keys in raw form. + * + * key [in] Curve448 private key. + * priv [in] Array to hold private key. + * privSz [in/out] On in, the number of bytes in private key array. + * On out, the number bytes put into private key array. + * pub [in] Array to hold public key. + * pubSz [in/out] On in, the number of bytes in public key array. + * On out, the number bytes put into public key array. + * endian [in] Endianness to use when encoding number in array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE or pubSz is + * less than CURVE448_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_export_key_raw_ex(curve448_key* key, byte* priv, word32 *privSz, + byte* pub, word32 *pubSz, int endian) +{ + int ret; + + /* export private part */ + ret = wc_curve448_export_private_raw_ex(key, priv, privSz, endian); + if (ret == 0) { + /* export public part */ + ret = wc_curve448_export_public_ex(key, pub, pubSz, endian); + } + + return ret; +} + +#endif /* HAVE_CURVE448_KEY_EXPORT */ + +#ifdef HAVE_CURVE448_KEY_IMPORT + +/* Import curve448 private and public keys from a byte arrays. + * Private and public keys encoded in big-endian. + * + * piv [in] Array holding private key. + * privSz [in] Number of bytes of data in private key array. + * pub [in] Array holding public key. + * pubSz [in] Number of bytes of data in public key array. + * key [in] Curve448 private/public key. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE or pubSz is + * less than CURVE448_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_import_private_raw(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + curve448_key* key) +{ + return wc_curve448_import_private_raw_ex(priv, privSz, pub, pubSz, key, + EC448_BIG_ENDIAN); +} + +/* Import curve448 private and public keys from a byte arrays. + * + * piv [in] Array holding private key. + * privSz [in] Number of bytes of data in private key array. + * pub [in] Array holding public key. + * pubSz [in] Number of bytes of data in public key array. + * key [in] Curve448 private/public key. + * endian [in] Endianness of encoded numbers in byte arrays. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE or pubSz is + * less than CURVE448_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_import_private_raw_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + curve448_key* key, int endian) +{ + int ret; + + /* import private part */ + ret = wc_curve448_import_private_ex(priv, privSz, key, endian); + if (ret == 0) { + /* import public part */ + return wc_curve448_import_public_ex(pub, pubSz, key, endian); + } + + return ret; +} + +/* Import curve448 private key from a byte array. + * Private key encoded in big-endian. + * + * piv [in] Array holding private key. + * privSz [in] Number of bytes of data in private key array. + * key [in] Curve448 private/public key. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_import_private(const byte* priv, word32 privSz, + curve448_key* key) +{ + return wc_curve448_import_private_ex(priv, privSz, key, EC448_BIG_ENDIAN); +} + +/* Import curve448 private key from a byte array. + * + * piv [in] Array holding private key. + * privSz [in] Number of bytes of data in private key array. + * key [in] Curve448 private/public key. + * endian [in] Endianness of encoded number in byte array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE, + * 0 otherwise. + */ +int wc_curve448_import_private_ex(const byte* priv, word32 privSz, + curve448_key* key, int endian) +{ + int ret = 0; + int i; + + /* sanity check */ + if ((key == NULL) || (priv == NULL)) { + ret = BAD_FUNC_ARG; + } + + /* check size of incoming keys */ + if ((ret == 0) && ((int)privSz != CURVE448_KEY_SIZE)) { + ret = ECC_BAD_ARG_E; + } + + if (ret == 0) { + if (endian == EC448_BIG_ENDIAN) { + /* read the key in Big Endian format */ + for (i = 0; i < CURVE448_KEY_SIZE; i++) { + key->k[i] = priv[CURVE448_KEY_SIZE - i - 1]; + } + } + else { + XMEMCPY(key->k, priv, CURVE448_KEY_SIZE); + } + + /* Clamp the key */ + key->k[0] &= 0xfc; + key->k[CURVE448_KEY_SIZE-1] |= 0x80; + } + + return ret; +} + +#endif /* HAVE_CURVE448_KEY_IMPORT */ + + +/* Initialize the curve448 key. + * + * key [in] Curve448 key object. + * returns BAD_FUNC_ARG when key is NULL, + * 0 otherwise. + */ +int wc_curve448_init(curve448_key* key) +{ + int ret = 0; + + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + XMEMSET(key, 0, sizeof(*key)); + + fe448_init(); + } + + return ret; +} + + +/* Clears the curve448 key data. + * + * key [in] Curve448 key object. + */ +void wc_curve448_free(curve448_key* key) +{ + if (key != NULL) { + ForceZero(key->p, sizeof(key->p)); + ForceZero(key->k, sizeof(key->k)); + } +} + + +/* Get the curve448 key's size. + * + * key [in] Curve448 key object. + * returns 0 if key is NULL, + * CURVE448_KEY_SIZE otherwise. + */ +int wc_curve448_size(curve448_key* key) +{ + int ret = 0; + + if (key != NULL) { + ret = CURVE448_KEY_SIZE; + } + + return ret; +} + +#endif /* HAVE_CURVE448 */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/des3.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/des3.c index f886ecdc7..b4b0187cd 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/des3.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/des3.c @@ -1,8 +1,8 @@ /* des3.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,160 +16,149 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include +#include +#include + #ifndef NO_DES3 -#include +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) -#ifdef HAVE_FIPS -#ifdef HAVE_CAVIUM - static int wc_Des3_CaviumSetKey(Des3* des3, const byte* key, const byte* iv); - static int wc_Des3_CaviumCbcEncrypt(Des3* des3, byte* out, const byte* in, - word32 length); - static int wc_Des3_CaviumCbcDecrypt(Des3* des3, byte* out, const byte* in, - word32 length); + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$i") + #pragma const_seg(".fipsB$i") + #endif #endif -int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) -{ - return Des_SetKey(des, key, iv, dir); -} +#include +#ifdef WOLF_CRYPTO_CB + #include +#endif -int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) -{ - return Des3_SetKey_fips(des, key, iv, dir); -} +/* fips wrapper calls, user can call direct */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + 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_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - return Des_CbcEncrypt(des, out, in, sz); -} + 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_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - return Des_CbcDecrypt(des, out, in, sz); -} + 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_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); */ + } -int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - return Des3_CbcEncrypt_fips(des, out, in, sz); -} +#else /* else build without fips, or for FIPS v2 */ -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); -} - -#endif /* WOLFSSL_DES_ECB */ - - -void wc_Des_SetIV(Des* des, const byte* iv) -{ - Des_SetIV(des, iv); -} - - -int wc_Des_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, - const byte* key, const byte* iv) -{ - return Des_CbcDecryptWithKey(out, in, sz, key, iv); -} - - -int wc_Des3_SetIV(Des3* des, const byte* iv) -{ - return Des3_SetIV_fips(des, iv); -} - - -int wc_Des3_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, - const byte* key, const byte* iv) -{ - return Des3_CbcDecryptWithKey(out, in, sz, key, iv); -} - - -#ifdef HAVE_CAVIUM - -/* Initiliaze Des3 for use with Nitrox device */ -int wc_Des3_InitCavium(Des3* des3, int devId) -{ - return Des3_InitCavium(des3, devId); -} - - -/* Free Des3 from use with Nitrox device */ -void wc_Des3_FreeCavium(Des3* des3) -{ - Des3_FreeCavium(des3); -} - - -#endif /* HAVE_CAVIUM */ -#else /* build without fips */ - #if defined(WOLFSSL_TI_CRYPT) #include #else -#include -#include #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif -#ifdef HAVE_CAVIUM - static int wc_Des3_CaviumSetKey(Des3* des3, const byte* key, const byte* iv); - static int wc_Des3_CaviumCbcEncrypt(Des3* des3, byte* out, const byte* in, - word32 length); - static int wc_Des3_CaviumCbcDecrypt(Des3* des3, byte* out, const byte* in, - word32 length); -#endif +/* Hardware Acceleration */ +#if defined(STM32_CRYPTO) - - - -#ifdef STM32F2_CRYPTO /* - * STM32F2 hardware DES/3DES support through the STM32F2 standard - * peripheral library. Documentation located in STM32F2xx Standard - * Peripheral Library document (See note in README). + * STM32F2/F4 hardware DES/3DES support through the standard + * peripheral library. (See note in README). */ - #include "stm32f2xx.h" - #include "stm32f2xx_cryp.h" int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) { word32 *dkey = des->key; + (void)dir; + XMEMCPY(dkey, key, 8); + #ifndef WOLFSSL_STM32_CUBEMX ByteReverseWords(dkey, dkey, 8); + #endif wc_Des_SetIV(des, iv); @@ -178,29 +167,95 @@ void wc_Des3_FreeCavium(Des3* des3) int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) { - word32 *dkey1 = des->key[0]; - word32 *dkey2 = des->key[1]; - word32 *dkey3 = des->key[2]; + if (des == NULL || key == NULL) + return BAD_FUNC_ARG; - XMEMCPY(dkey1, key, 8); /* set key 1 */ - XMEMCPY(dkey2, key + 8, 8); /* set key 2 */ - XMEMCPY(dkey3, key + 16, 8); /* set key 3 */ + (void)dir; - ByteReverseWords(dkey1, dkey1, 8); - ByteReverseWords(dkey2, dkey2, 8); - ByteReverseWords(dkey3, dkey3, 8); + #ifndef WOLFSSL_STM32_CUBEMX + { + word32 *dkey1 = des->key[0]; + word32 *dkey2 = des->key[1]; + word32 *dkey3 = des->key[2]; + + XMEMCPY(dkey1, key, 8); /* set key 1 */ + XMEMCPY(dkey2, key + 8, 8); /* set key 2 */ + XMEMCPY(dkey3, key + 16, 8); /* set key 3 */ + + ByteReverseWords(dkey1, dkey1, 8); + ByteReverseWords(dkey2, dkey2, 8); + ByteReverseWords(dkey3, dkey3, 8); + } + #else + XMEMCPY(des->key[0], key, DES3_KEYLEN); /* CUBEMX wants keys in sequential memory */ + #endif return wc_Des3_SetIV(des, iv); } - void DesCrypt(Des* des, byte* out, const byte* in, word32 sz, + static void DesCrypt(Des* des, byte* out, const byte* in, word32 sz, int dir, int mode) { + int ret; + #ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; + #else word32 *dkey, *iv; CRYP_InitTypeDef DES_CRYP_InitStructure; CRYP_KeyInitTypeDef DES_CRYP_KeyInitStructure; CRYP_IVInitTypeDef DES_CRYP_IVInitStructure; + #endif + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return; + } + + #ifdef WOLFSSL_STM32_CUBEMX + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); + hcryp.Instance = CRYP; + hcryp.Init.KeySize = CRYP_KEYSIZE_128B; + hcryp.Init.DataType = CRYP_DATATYPE_8B; + hcryp.Init.pKey = (uint8_t*)des->key; + hcryp.Init.pInitVect = (uint8_t*)des->reg; + + HAL_CRYP_Init(&hcryp); + + while (sz > 0) { + /* if input and output same will overwrite input iv */ + XMEMCPY(des->tmp, in + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + + if (mode == DES_CBC) { + if (dir == DES_ENCRYPTION) { + HAL_CRYP_DESCBC_Encrypt(&hcryp, (uint8_t*)in, + DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT); + } + else { + HAL_CRYP_DESCBC_Decrypt(&hcryp, (uint8_t*)in, + DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT); + } + } + else { + if (dir == DES_ENCRYPTION) { + HAL_CRYP_DESECB_Encrypt(&hcryp, (uint8_t*)in, + DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT); + } + else { + HAL_CRYP_DESECB_Decrypt(&hcryp, (uint8_t*)in, + DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT); + } + } + + /* store iv for next call */ + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + + sz -= DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + } + + HAL_CRYP_DeInit(&hcryp); + #else dkey = des->key; iv = des->reg; @@ -242,8 +297,7 @@ void wc_Des3_FreeCavium(Des3* des3) /* enable crypto processor */ CRYP_Cmd(ENABLE); - while (sz > 0) - { + while (sz > 0) { /* flush IN/OUT FIFOs */ CRYP_FIFOFlush(); @@ -269,6 +323,8 @@ void wc_Des3_FreeCavium(Des3* des3) /* disable crypto processor */ CRYP_Cmd(DISABLE); + #endif /* WOLFSSL_STM32_CUBEMX */ + wolfSSL_CryptHwMutexUnLock(); } int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) @@ -289,81 +345,121 @@ void wc_Des3_FreeCavium(Des3* des3) return 0; } - void Des3Crypt(Des3* des, byte* out, const byte* in, word32 sz, + static void Des3Crypt(Des3* des, byte* out, const byte* in, word32 sz, int dir) { - word32 *dkey1, *dkey2, *dkey3, *iv; - CRYP_InitTypeDef DES3_CRYP_InitStructure; - CRYP_KeyInitTypeDef DES3_CRYP_KeyInitStructure; - CRYP_IVInitTypeDef DES3_CRYP_IVInitStructure; + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; - dkey1 = des->key[0]; - dkey2 = des->key[1]; - dkey3 = des->key[2]; - iv = des->reg; - - /* crypto structure initialization */ - CRYP_KeyStructInit(&DES3_CRYP_KeyInitStructure); - CRYP_StructInit(&DES3_CRYP_InitStructure); - CRYP_IVStructInit(&DES3_CRYP_IVInitStructure); - - /* reset registers to their default values */ - CRYP_DeInit(); - - /* set direction, mode, and datatype */ - if (dir == DES_ENCRYPTION) { - DES3_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; - } else { - DES3_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; - } - - DES3_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_TDES_CBC; - DES3_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; - CRYP_Init(&DES3_CRYP_InitStructure); - - /* load key into correct registers */ - DES3_CRYP_KeyInitStructure.CRYP_Key1Left = dkey1[0]; - DES3_CRYP_KeyInitStructure.CRYP_Key1Right = dkey1[1]; - DES3_CRYP_KeyInitStructure.CRYP_Key2Left = dkey2[0]; - DES3_CRYP_KeyInitStructure.CRYP_Key2Right = dkey2[1]; - DES3_CRYP_KeyInitStructure.CRYP_Key3Left = dkey3[0]; - DES3_CRYP_KeyInitStructure.CRYP_Key3Right = dkey3[1]; - CRYP_KeyInit(&DES3_CRYP_KeyInitStructure); - - /* set iv */ - ByteReverseWords(iv, iv, DES_BLOCK_SIZE); - DES3_CRYP_IVInitStructure.CRYP_IV0Left = iv[0]; - DES3_CRYP_IVInitStructure.CRYP_IV0Right = iv[1]; - CRYP_IVInit(&DES3_CRYP_IVInitStructure); - - /* enable crypto processor */ - CRYP_Cmd(ENABLE); - - while (sz > 0) + #ifdef WOLFSSL_STM32_CUBEMX { - /* flush IN/OUT FIFOs */ - CRYP_FIFOFlush(); + CRYP_HandleTypeDef hcryp; - CRYP_DataIn(*(uint32_t*)&in[0]); - CRYP_DataIn(*(uint32_t*)&in[4]); + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); + hcryp.Instance = CRYP; + hcryp.Init.KeySize = CRYP_KEYSIZE_128B; + hcryp.Init.DataType = CRYP_DATATYPE_8B; + hcryp.Init.pKey = (uint8_t*)des->key; + hcryp.Init.pInitVect = (uint8_t*)des->reg; - /* wait until the complete message has been processed */ - while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + HAL_CRYP_Init(&hcryp); - *(uint32_t*)&out[0] = CRYP_DataOut(); - *(uint32_t*)&out[4] = CRYP_DataOut(); + while (sz > 0) + { + if (dir == DES_ENCRYPTION) { + HAL_CRYP_TDESCBC_Encrypt(&hcryp, (byte*)in, + DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT); + } + else { + HAL_CRYP_TDESCBC_Decrypt(&hcryp, (byte*)in, + DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT); + } - /* store iv for next call */ - XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + /* store iv for next call */ + XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - sz -= DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; - out += DES_BLOCK_SIZE; + sz -= DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + } + + HAL_CRYP_DeInit(&hcryp); } + #else + { + word32 *dkey1, *dkey2, *dkey3, *iv; + CRYP_InitTypeDef DES3_CRYP_InitStructure; + CRYP_KeyInitTypeDef DES3_CRYP_KeyInitStructure; + CRYP_IVInitTypeDef DES3_CRYP_IVInitStructure; - /* disable crypto processor */ - CRYP_Cmd(DISABLE); + dkey1 = des->key[0]; + dkey2 = des->key[1]; + dkey3 = des->key[2]; + iv = des->reg; + /* crypto structure initialization */ + CRYP_KeyStructInit(&DES3_CRYP_KeyInitStructure); + CRYP_StructInit(&DES3_CRYP_InitStructure); + CRYP_IVStructInit(&DES3_CRYP_IVInitStructure); + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* set direction, mode, and datatype */ + if (dir == DES_ENCRYPTION) { + DES3_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + } else { + DES3_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + } + + DES3_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_TDES_CBC; + DES3_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; + CRYP_Init(&DES3_CRYP_InitStructure); + + /* load key into correct registers */ + DES3_CRYP_KeyInitStructure.CRYP_Key1Left = dkey1[0]; + DES3_CRYP_KeyInitStructure.CRYP_Key1Right = dkey1[1]; + DES3_CRYP_KeyInitStructure.CRYP_Key2Left = dkey2[0]; + DES3_CRYP_KeyInitStructure.CRYP_Key2Right = dkey2[1]; + DES3_CRYP_KeyInitStructure.CRYP_Key3Left = dkey3[0]; + DES3_CRYP_KeyInitStructure.CRYP_Key3Right = dkey3[1]; + CRYP_KeyInit(&DES3_CRYP_KeyInitStructure); + + /* set iv */ + ByteReverseWords(iv, iv, DES_BLOCK_SIZE); + DES3_CRYP_IVInitStructure.CRYP_IV0Left = iv[0]; + DES3_CRYP_IVInitStructure.CRYP_IV0Right = iv[1]; + CRYP_IVInit(&DES3_CRYP_IVInitStructure); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + while (sz > 0) + { + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + CRYP_DataIn(*(uint32_t*)&in[0]); + CRYP_DataIn(*(uint32_t*)&in[4]); + + /* 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(); + + /* store iv for next call */ + XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + + sz -= DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + } + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + } + #endif /* WOLFSSL_STM32_CUBEMX */ } int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) @@ -380,238 +476,333 @@ void wc_Des3_FreeCavium(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 + #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 ; + #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 ; + 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 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 + #define DES_IVLEN 8 + #define DES_KEYLEN 8 + #define DES3_IVLEN 8 + #define DES3_KEYLEN 24 -extern volatile unsigned char __MBAR[]; + 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 ; - #endif - int size ; - volatile int v ; - - 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 ; - } - 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) ; - - 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 - - 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 ; - - } - 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; + } -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" + XMEMCPY(desBuffIn, in, size); + XMEMCPY(secKey, key, secDesc->length3); + + 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 - - 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; -} -int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) -{ - - if(desBuffIn == NULL) { + 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; + } + 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 - - 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; -} + InitMutex(&Mutex_DesSEC); + } -#elif defined FREESCALE_MMCAU + 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; + } + + int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) + { + if (des3 == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + 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; + + } +#elif defined(FREESCALE_LTC_DES) + + #include "fsl_ltc.h" + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + byte* dkey; + + if (des == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + dkey = (byte*)des->key; + + XMEMCPY(dkey, key, 8); + + wc_Des_SetIV(des, iv); + + return 0; + } + + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + int ret = 0; + byte* dkey1 = (byte*)des->key[0]; + byte* dkey2 = (byte*)des->key[1]; + byte* dkey3 = (byte*)des->key[2]; + + XMEMCPY(dkey1, key, 8); /* set key 1 */ + XMEMCPY(dkey2, key + 8, 8); /* set key 2 */ + XMEMCPY(dkey3, key + 16, 8); /* set key 3 */ + + ret = wc_Des3_SetIV(des, iv); + if (ret != 0) + return ret; + + return ret; + } + + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + status_t status; + status = LTC_DES_EncryptCbc(LTC_BASE, in, out, sz, (byte*)des->reg, (byte*)des->key); + if (status == kStatus_Success) + return 0; + else + return -1; + } + + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + status_t status; + status = LTC_DES_DecryptCbc(LTC_BASE, in, out, sz, (byte*)des->reg, (byte*)des->key); + if (status == kStatus_Success) + return 0; + else + return -1; + } + + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + status_t status; + status = LTC_DES3_EncryptCbc(LTC_BASE, + in, + out, + sz, + (byte*)des->reg, + (byte*)des->key[0], + (byte*)des->key[1], + (byte*)des->key[2]); + if (status == kStatus_Success) + return 0; + else + return -1; + } + + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + status_t status; + status = LTC_DES3_DecryptCbc(LTC_BASE, + in, + out, + sz, + (byte*)des->reg, + (byte*)des->key[0], + (byte*)des->key[1], + (byte*)des->key[2]); + if (status == kStatus_Success) + return 0; + else + return -1; + + } + +#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 "cau_api.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, @@ -621,7 +812,14 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) { int i = 0; - byte* dkey = (byte*)des->key; + byte* dkey; + + + if (des == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + dkey = (byte*)des->key; XMEMCPY(dkey, key, 8); @@ -668,15 +866,18 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) int i; int offset = 0; int len = sz; + int ret = 0; byte *iv; 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"); + WOLFSSL_MSG("Bad cau_des_encrypt alignment"); return BAD_ALIGN_E; } + #endif while (len > 0) { @@ -686,7 +887,16 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) for (i = 0; i < DES_BLOCK_SIZE; i++) temp_block[i] ^= iv[i]; + ret = wolfSSL_CryptHwMutexLock(); + 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; offset += DES_BLOCK_SIZE; @@ -695,7 +905,7 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) XMEMCPY(iv, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE); } - return 0; + return ret; } int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) @@ -703,21 +913,34 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) int i; int offset = 0; int len = sz; + int ret = 0; byte* iv; 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_decrypt alignment"); + WOLFSSL_MSG("Bad cau_des_decrypt alignment"); return BAD_ALIGN_E; } + #endif while (len > 0) { XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); + ret = wolfSSL_CryptHwMutexLock(); + 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 */ for (i = 0; i < DES_BLOCK_SIZE; i++) @@ -730,7 +953,7 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) offset += DES_BLOCK_SIZE; } - return 0; + return ret; } int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) @@ -738,16 +961,19 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) int i; int offset = 0; int len = sz; + int ret = 0; byte *iv; 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"); + WOLFSSL_MSG("Bad 3ede cau_des_encrypt alignment"); return BAD_ALIGN_E; } + #endif while (len > 0) { @@ -757,9 +983,20 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) for (i = 0; i < DES_BLOCK_SIZE; i++) temp_block[i] ^= iv[i]; - cau_des_encrypt(temp_block , (byte*)des->key[0], out + offset); + ret = wolfSSL_CryptHwMutexLock(); + 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; offset += DES_BLOCK_SIZE; @@ -768,7 +1005,7 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) XMEMCPY(iv, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE); } - return 0; + return ret; } int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) @@ -776,24 +1013,38 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) int i; int offset = 0; int len = sz; + int ret = 0; byte* iv; 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_decrypt 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); - cau_des_decrypt(in + offset , (byte*)des->key[2], out + offset); + ret = wolfSSL_CryptHwMutexLock(); + 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 */ for (i = 0; i < DES_BLOCK_SIZE; i++) @@ -806,680 +1057,707 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) offset += DES_BLOCK_SIZE; } - return 0; + return ret; } #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 ; - - /* get uncached address */ + word32 blocks = sz / DES_BLOCK_SIZE; - 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); - - if(PIC32MZ_IF_RAM(in_p)) - XMEMCPY((void *)in_p, (void *)in, sz); - XMEMSET((void *)out_p, 0, sz); + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; - /* 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); + 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); + } - 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; - - 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 ; - - /* Fire in the hole! */ - CECON = 1 << 6; - while (CECON); - - /* Run the engine */ - CEBDPADDR = (unsigned int)KVA_TO_PA(&bd) ; /* (unsigned int)bd_p ; */ - CEINTEN = 0x07; - CECON = 0x27; + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; - WAIT_ENGINE ; + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; - 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); - } + 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); + } + int wc_Des3_CbcEncrypt(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_TCBC); + } + + int wc_Des3_CbcDecrypt(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_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 WC_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 WC_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(WOLF_CRYPTO_CB) || \ + (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES)) + #ifdef WOLF_CRYPTO_CB + if (des->devId != INVALID_DEVID) + #endif + { + XMEMCPY(des->devKey, key, DES3_KEYLEN); + } + #endif + + 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; + } + + #ifdef WOLF_CRYPTO_CB + if (des->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_Des3Encrypt(des, out, in, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } + #endif + + #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, + (const byte*)des->devKey, DES3_KEYLEN, (byte*)des->reg, 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; + } + + #ifdef WOLF_CRYPTO_CB + if (des->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_Des3Decrypt(des, out, in, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } + #endif + + #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 NitroxDes3CbcDecrypt(des, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymDes3CbcDecrypt(&des->asyncDev, out, in, sz, + (const byte*)des->devKey, DES3_KEYLEN, (byte*)des->reg, 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 /* CTaoCrypt software implementation */ -/* 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, + #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; - 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 */ +#endif /* NEED_SOFT_DES */ -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; - -#ifdef HAVE_CAVIUM - if (des->magic == WOLFSSL_3DES_CAVIUM_MAGIC) - return wc_Des3_CaviumSetKey(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; - byte hold[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(hold, des->reg, DES_BLOCK_SIZE); - XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); - XMEMCPY(des->tmp, hold, 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; - -#ifdef HAVE_CAVIUM - if (des->magic == WOLFSSL_3DES_CAVIUM_MAGIC) - return wc_Des3_CaviumCbcEncrypt(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; - -#ifdef HAVE_CAVIUM - if (des->magic == WOLFSSL_3DES_CAVIUM_MAGIC) - return wc_Des3_CaviumCbcDecrypt(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; - - while (blocks--) { - DesProcessBlock(des, in, out); - - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; - } - return 0; -} - -#endif /* WOLFSSL_DES_ECB */ - -#endif /* STM32F2_CRYPTO */ void wc_Des_SetIV(Des* des, const byte* iv) { @@ -1489,37 +1767,11 @@ void wc_Des_SetIV(Des* des, const byte* iv) XMEMSET(des->reg, 0, DES_BLOCK_SIZE); } - -int wc_Des_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, - const byte* key, const byte* iv) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Des* des = NULL; -#else - Des des[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - des = (Des*)XMALLOC(sizeof(Des), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (des == NULL) - return MEMORY_E; -#endif - - ret = wc_Des_SetKey(des, key, iv, DES_DECRYPTION); - if (ret == 0) - ret = wc_Des_CbcDecrypt(des, out, in, sz); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(des, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - - 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) @@ -1529,150 +1781,45 @@ int wc_Des3_SetIV(Des3* des, const byte* iv) } -int wc_Des3_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, - const byte* key, const byte* iv) +/* Initialize Des3 for use with async device */ +int wc_Des3Init(Des3* des3, void* heap, int devId) { - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Des3* des3 = NULL; -#else - Des3 des3[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - des3 = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER); + int ret = 0; if (des3 == NULL) - return MEMORY_E; + return BAD_FUNC_ARG; + + des3->heap = heap; + +#ifdef WOLF_CRYPTO_CB + des3->devId = devId; + des3->devCtx = NULL; +#else + (void)devId; #endif - ret = wc_Des3_SetKey(des3, key, iv, DES_DECRYPTION); - if (ret == 0) - ret = wc_Des3_CbcDecrypt(des3, out, in, sz); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(des3, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + ret = wolfAsync_DevCtxInit(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES, + des3->heap, devId); #endif return ret; } - -#ifdef HAVE_CAVIUM - -#include "cavium_common.h" - -/* Initiliaze Des3 for use with Nitrox device */ -int wc_Des3_InitCavium(Des3* des3, int devId) -{ - if (des3 == NULL) - return -1; - - if (CspAllocContext(CONTEXT_SSL, &des3->contextHandle, devId) != 0) - return -1; - - des3->devId = devId; - des3->magic = WOLFSSL_3DES_CAVIUM_MAGIC; - - return 0; -} - - -/* Free Des3 from use with Nitrox device */ -void wc_Des3_FreeCavium(Des3* des3) +/* Free Des3 from use with async device */ +void wc_Des3Free(Des3* des3) { if (des3 == NULL) return; - if (des3->magic != WOLFSSL_3DES_CAVIUM_MAGIC) - return; - - CspFreeContext(CONTEXT_SSL, des3->contextHandle, des3->devId); - des3->magic = 0; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + wolfAsync_DevCtxFree(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES); +#endif /* WOLFSSL_ASYNC_CRYPT */ +#if defined(WOLF_CRYPTO_CB) || \ + (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES)) + ForceZero(des3->devKey, sizeof(des3->devKey)); +#endif } - -static int wc_Des3_CaviumSetKey(Des3* des3, const byte* key, const byte* iv) -{ - if (des3 == NULL) - return -1; - - /* key[0] holds key, iv in reg */ - XMEMCPY(des3->key[0], key, DES_BLOCK_SIZE*3); - - return wc_Des3_SetIV(des3, iv); -} - - -static int wc_Des3_CaviumCbcEncrypt(Des3* des3, byte* out, const byte* in, - word32 length) -{ - wolfssl_word offset = 0; - word32 requestId; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - if (CspEncrypt3Des(CAVIUM_BLOCKING, des3->contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in + offset, - out + offset, (byte*)des3->reg, (byte*)des3->key[0], - &requestId, des3->devId) != 0) { - WOLFSSL_MSG("Bad Cavium 3DES Cbc Encrypt"); - return -1; - } - 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; - - if (CspEncrypt3Des(CAVIUM_BLOCKING, des3->contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in + offset, - out + offset, (byte*)des3->reg, (byte*)des3->key[0], - &requestId, des3->devId) != 0) { - WOLFSSL_MSG("Bad Cavium 3DES Cbc Encrypt"); - return -1; - } - XMEMCPY(des3->reg, out+offset+length - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - } - return 0; -} - -static int wc_Des3_CaviumCbcDecrypt(Des3* des3, byte* out, const byte* in, - word32 length) -{ - word32 requestId; - wolfssl_word offset = 0; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - XMEMCPY(des3->tmp, in + offset + slen - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - if (CspDecrypt3Des(CAVIUM_BLOCKING, des3->contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in+offset, out+offset, - (byte*)des3->reg, (byte*)des3->key[0], &requestId, - des3->devId) != 0) { - WOLFSSL_MSG("Bad Cavium 3Des Decrypt"); - return -1; - } - 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); - if (CspDecrypt3Des(CAVIUM_BLOCKING, des3->contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in+offset, out+offset, - (byte*)des3->reg, (byte*)des3->key[0], &requestId, - des3->devId) != 0) { - WOLFSSL_MSG("Bad Cavium 3Des Decrypt"); - return -1; - } - XMEMCPY(des3->reg, des3->tmp, DES_BLOCK_SIZE); - } - return 0; -} - -#endif /* HAVE_CAVIUM */ #endif /* WOLFSSL_TI_CRYPT */ #endif /* HAVE_FIPS */ #endif /* NO_DES3 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/dh.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/dh.c index bc4ce11d3..6c53be8f3 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/dh.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/dh.c @@ -1,8 +1,8 @@ /* dh.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -27,10 +28,46 @@ #ifndef NO_DH +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$m") + #pragma const_seg(".fipsB$m") + #endif +#endif + #include #include +#include -#ifndef USER_MATH_LIB +#ifdef WOLFSSL_HAVE_SP_DH +#include +#endif + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +/* +Possible DH enable options: + * NO_RSA: Overall control of DH default: on (not defined) + * WOLFSSL_OLD_PRIME_CHECK: Disables the new prime number check. It does not + directly effect this file, but it does speed up DH + removing the testing. It is not recommended to + disable the prime checking. default: off + +*/ + + +#if !defined(USER_MATH_LIB) && !defined(WOLFSSL_DH_CONST) #include #define XPOW(x,y) pow((x),(y)) #define XLOG(x) log((x)) @@ -38,179 +75,2417 @@ /* 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 }; +#ifdef HAVE_FFDHE_Q +static const byte dh_ffdhe2048_q[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D, + 0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78, + 0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A, + 0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD, + 0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C, + 0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC, + 0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD, + 0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0, + 0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68, + 0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79, + 0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A, + 0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB, + 0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39, + 0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A, + 0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD, + 0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0, + 0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD, + 0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34, + 0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA, + 0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C, + 0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8, + 0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76, + 0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0, + 0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF, + 0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1, + 0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9, + 0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02, + 0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9, + 0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD, + 0x44, 0x35, 0xA1, 0x1C, 0x30, 0x94, 0x2E, 0x4B, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +#endif /* HAVE_FFDHE_Q */ -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN +const DhParams* wc_Dh_ffdhe2048_Get(void) +{ + static const DhParams ffdhe2048 = { + #ifdef HAVE_FFDHE_Q + dh_ffdhe2048_q, sizeof(dh_ffdhe2048_q), + #endif /* HAVE_FFDHE_Q */ + dh_ffdhe2048_p, sizeof(dh_ffdhe2048_p), + dh_ffdhe2048_g, sizeof(dh_ffdhe2048_g) + }; + return &ffdhe2048; +} +#endif - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; +#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 }; +#ifdef HAVE_FFDHE_Q +static const byte dh_ffdhe3072_q[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D, + 0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78, + 0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A, + 0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD, + 0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C, + 0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC, + 0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD, + 0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0, + 0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68, + 0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79, + 0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A, + 0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB, + 0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39, + 0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A, + 0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD, + 0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0, + 0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD, + 0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34, + 0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA, + 0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C, + 0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8, + 0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76, + 0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0, + 0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF, + 0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1, + 0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9, + 0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02, + 0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9, + 0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD, + 0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE, + 0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD, + 0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C, + 0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83, + 0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7, + 0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E, + 0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38, + 0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2, + 0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9, + 0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF, + 0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F, + 0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06, + 0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D, + 0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27, + 0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7, + 0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE, + 0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x63, 0x17, 0x1B, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +#endif /* HAVE_FFDHE_Q */ + +const DhParams* wc_Dh_ffdhe3072_Get(void) +{ + static const DhParams ffdhe3072 = { + #ifdef HAVE_FFDHE_Q + dh_ffdhe3072_q, sizeof(dh_ffdhe3072_q), + #endif /* HAVE_FFDHE_Q */ + 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 }; +#ifdef HAVE_FFDHE_Q +static const byte dh_ffdhe4096_q[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D, + 0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78, + 0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A, + 0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD, + 0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C, + 0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC, + 0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD, + 0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0, + 0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68, + 0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79, + 0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A, + 0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB, + 0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39, + 0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A, + 0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD, + 0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0, + 0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD, + 0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34, + 0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA, + 0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C, + 0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8, + 0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76, + 0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0, + 0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF, + 0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1, + 0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9, + 0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02, + 0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9, + 0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD, + 0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE, + 0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD, + 0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C, + 0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83, + 0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7, + 0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E, + 0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38, + 0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2, + 0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9, + 0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF, + 0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F, + 0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06, + 0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D, + 0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27, + 0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7, + 0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE, + 0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x4F, 0x0F, 0x78, + 0xB7, 0x37, 0xA9, 0x61, 0x8B, 0x26, 0xFA, 0x7D, + 0xBC, 0x98, 0x74, 0xF2, 0x72, 0xC4, 0x2B, 0xDB, + 0x56, 0x3E, 0xAF, 0xA1, 0x6B, 0x4F, 0xB6, 0x8C, + 0x3B, 0xB1, 0xE7, 0x8E, 0xAA, 0x81, 0xA0, 0x02, + 0x43, 0xFA, 0xAD, 0xD2, 0xBF, 0x18, 0xE6, 0x3D, + 0x38, 0x9A, 0xE4, 0x43, 0x77, 0xDA, 0x18, 0xC5, + 0x76, 0xB5, 0x0F, 0x00, 0x96, 0xCF, 0x34, 0x19, + 0x54, 0x83, 0xB0, 0x05, 0x48, 0xC0, 0x98, 0x62, + 0x36, 0xE3, 0xBC, 0x7C, 0xB8, 0xD6, 0x80, 0x1C, + 0x04, 0x94, 0xCC, 0xD1, 0x99, 0xE5, 0xC5, 0xBD, + 0x0D, 0x0E, 0xDC, 0x9E, 0xB8, 0xA0, 0x00, 0x1E, + 0x15, 0x27, 0x67, 0x54, 0xFC, 0xC6, 0x85, 0x66, + 0x05, 0x41, 0x48, 0xE6, 0xE7, 0x64, 0xBE, 0xE7, + 0xC7, 0x64, 0xDA, 0xAD, 0x3F, 0xC4, 0x52, 0x35, + 0xA6, 0xDA, 0xD4, 0x28, 0xFA, 0x20, 0xC1, 0x70, + 0xE3, 0x45, 0x00, 0x3F, 0x2F, 0x32, 0xAF, 0xB5, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +#endif /* HAVE_FFDHE_Q */ + +const DhParams* wc_Dh_ffdhe4096_Get(void) +{ + static const DhParams ffdhe4096 = { + #ifdef HAVE_FFDHE_Q + dh_ffdhe4096_q, sizeof(dh_ffdhe4096_q), + #endif /* HAVE_FFDHE_Q */ + 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 }; +#ifdef HAVE_FFDHE_Q +static const byte dh_ffdhe6144_q[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D, + 0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78, + 0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A, + 0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD, + 0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C, + 0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC, + 0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD, + 0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0, + 0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68, + 0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79, + 0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A, + 0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB, + 0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39, + 0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A, + 0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD, + 0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0, + 0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD, + 0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34, + 0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA, + 0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C, + 0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8, + 0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76, + 0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0, + 0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF, + 0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1, + 0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9, + 0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02, + 0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9, + 0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD, + 0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE, + 0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD, + 0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C, + 0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83, + 0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7, + 0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E, + 0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38, + 0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2, + 0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9, + 0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF, + 0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F, + 0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06, + 0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D, + 0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27, + 0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7, + 0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE, + 0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x4F, 0x0F, 0x78, + 0xB7, 0x37, 0xA9, 0x61, 0x8B, 0x26, 0xFA, 0x7D, + 0xBC, 0x98, 0x74, 0xF2, 0x72, 0xC4, 0x2B, 0xDB, + 0x56, 0x3E, 0xAF, 0xA1, 0x6B, 0x4F, 0xB6, 0x8C, + 0x3B, 0xB1, 0xE7, 0x8E, 0xAA, 0x81, 0xA0, 0x02, + 0x43, 0xFA, 0xAD, 0xD2, 0xBF, 0x18, 0xE6, 0x3D, + 0x38, 0x9A, 0xE4, 0x43, 0x77, 0xDA, 0x18, 0xC5, + 0x76, 0xB5, 0x0F, 0x00, 0x96, 0xCF, 0x34, 0x19, + 0x54, 0x83, 0xB0, 0x05, 0x48, 0xC0, 0x98, 0x62, + 0x36, 0xE3, 0xBC, 0x7C, 0xB8, 0xD6, 0x80, 0x1C, + 0x04, 0x94, 0xCC, 0xD1, 0x99, 0xE5, 0xC5, 0xBD, + 0x0D, 0x0E, 0xDC, 0x9E, 0xB8, 0xA0, 0x00, 0x1E, + 0x15, 0x27, 0x67, 0x54, 0xFC, 0xC6, 0x85, 0x66, + 0x05, 0x41, 0x48, 0xE6, 0xE7, 0x64, 0xBE, 0xE7, + 0xC7, 0x64, 0xDA, 0xAD, 0x3F, 0xC4, 0x52, 0x35, + 0xA6, 0xDA, 0xD4, 0x28, 0xFA, 0x20, 0xC1, 0x70, + 0xE3, 0x45, 0x00, 0x3F, 0x2F, 0x06, 0xEC, 0x81, + 0x05, 0xFE, 0xB2, 0x5B, 0x22, 0x81, 0xB6, 0x3D, + 0x27, 0x33, 0xBE, 0x96, 0x1C, 0x29, 0x95, 0x1D, + 0x11, 0xDD, 0x22, 0x21, 0x65, 0x7A, 0x9F, 0x53, + 0x1D, 0xDA, 0x2A, 0x19, 0x4D, 0xBB, 0x12, 0x64, + 0x48, 0xBD, 0xEE, 0xB2, 0x58, 0xE0, 0x7E, 0xA6, + 0x59, 0xC7, 0x46, 0x19, 0xA6, 0x38, 0x0E, 0x1D, + 0x66, 0xD6, 0x83, 0x2B, 0xFE, 0x67, 0xF6, 0x38, + 0xCD, 0x8F, 0xAE, 0x1F, 0x27, 0x23, 0x02, 0x0F, + 0x9C, 0x40, 0xA3, 0xFD, 0xA6, 0x7E, 0xDA, 0x3B, + 0xD2, 0x92, 0x38, 0xFB, 0xD4, 0xD4, 0xB4, 0x88, + 0x5C, 0x2A, 0x99, 0x17, 0x6D, 0xB1, 0xA0, 0x6C, + 0x50, 0x07, 0x78, 0x49, 0x1A, 0x82, 0x88, 0xF1, + 0x85, 0x5F, 0x60, 0xFF, 0xFC, 0xF1, 0xD1, 0x37, + 0x3F, 0xD9, 0x4F, 0xC6, 0x0C, 0x18, 0x11, 0xE1, + 0xAC, 0x3F, 0x1C, 0x6D, 0x00, 0x3B, 0xEC, 0xDA, + 0x3B, 0x1F, 0x27, 0x25, 0xCA, 0x59, 0x5D, 0xE0, + 0xCA, 0x63, 0x32, 0x8F, 0x3B, 0xE5, 0x7C, 0xC9, + 0x77, 0x55, 0x60, 0x11, 0x95, 0x14, 0x0D, 0xFB, + 0x59, 0xD3, 0x9C, 0xE0, 0x91, 0x30, 0x8B, 0x41, + 0x05, 0x74, 0x6D, 0xAC, 0x23, 0xD3, 0x3E, 0x5F, + 0x7C, 0xE4, 0x84, 0x8D, 0xA3, 0x16, 0xA9, 0xC6, + 0x6B, 0x95, 0x81, 0xBA, 0x35, 0x73, 0xBF, 0xAF, + 0x31, 0x14, 0x96, 0x18, 0x8A, 0xB1, 0x54, 0x23, + 0x28, 0x2E, 0xE4, 0x16, 0xDC, 0x2A, 0x19, 0xC5, + 0x72, 0x4F, 0xA9, 0x1A, 0xE4, 0xAD, 0xC8, 0x8B, + 0xC6, 0x67, 0x96, 0xEA, 0xE5, 0x67, 0x7A, 0x01, + 0xF6, 0x4E, 0x8C, 0x08, 0x63, 0x13, 0x95, 0x82, + 0x2D, 0x9D, 0xB8, 0xFC, 0xEE, 0x35, 0xC0, 0x6B, + 0x1F, 0xEE, 0xA5, 0x47, 0x4D, 0x6D, 0x8F, 0x34, + 0xB1, 0x53, 0x4A, 0x93, 0x6A, 0x18, 0xB0, 0xE0, + 0xD2, 0x0E, 0xAB, 0x86, 0xBC, 0x9C, 0x6D, 0x6A, + 0x52, 0x07, 0x19, 0x4E, 0x68, 0x72, 0x07, 0x32, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +#endif /* HAVE_FFDHE_Q */ + +const DhParams* wc_Dh_ffdhe6144_Get(void) +{ + static const DhParams ffdhe6144 = { + #ifdef HAVE_FFDHE_Q + dh_ffdhe6144_q, sizeof(dh_ffdhe6144_q), + #endif /* HAVE_FFDHE_Q */ + 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 }; +#ifdef HAVE_FFDHE_Q +static const byte dh_ffdhe8192_q[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D, + 0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78, + 0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A, + 0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD, + 0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C, + 0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC, + 0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD, + 0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0, + 0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68, + 0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79, + 0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A, + 0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB, + 0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39, + 0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A, + 0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD, + 0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0, + 0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD, + 0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34, + 0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA, + 0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C, + 0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8, + 0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76, + 0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0, + 0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF, + 0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1, + 0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9, + 0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02, + 0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9, + 0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD, + 0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE, + 0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD, + 0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C, + 0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83, + 0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7, + 0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E, + 0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38, + 0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2, + 0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9, + 0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF, + 0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F, + 0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06, + 0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D, + 0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27, + 0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7, + 0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE, + 0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x4F, 0x0F, 0x78, + 0xB7, 0x37, 0xA9, 0x61, 0x8B, 0x26, 0xFA, 0x7D, + 0xBC, 0x98, 0x74, 0xF2, 0x72, 0xC4, 0x2B, 0xDB, + 0x56, 0x3E, 0xAF, 0xA1, 0x6B, 0x4F, 0xB6, 0x8C, + 0x3B, 0xB1, 0xE7, 0x8E, 0xAA, 0x81, 0xA0, 0x02, + 0x43, 0xFA, 0xAD, 0xD2, 0xBF, 0x18, 0xE6, 0x3D, + 0x38, 0x9A, 0xE4, 0x43, 0x77, 0xDA, 0x18, 0xC5, + 0x76, 0xB5, 0x0F, 0x00, 0x96, 0xCF, 0x34, 0x19, + 0x54, 0x83, 0xB0, 0x05, 0x48, 0xC0, 0x98, 0x62, + 0x36, 0xE3, 0xBC, 0x7C, 0xB8, 0xD6, 0x80, 0x1C, + 0x04, 0x94, 0xCC, 0xD1, 0x99, 0xE5, 0xC5, 0xBD, + 0x0D, 0x0E, 0xDC, 0x9E, 0xB8, 0xA0, 0x00, 0x1E, + 0x15, 0x27, 0x67, 0x54, 0xFC, 0xC6, 0x85, 0x66, + 0x05, 0x41, 0x48, 0xE6, 0xE7, 0x64, 0xBE, 0xE7, + 0xC7, 0x64, 0xDA, 0xAD, 0x3F, 0xC4, 0x52, 0x35, + 0xA6, 0xDA, 0xD4, 0x28, 0xFA, 0x20, 0xC1, 0x70, + 0xE3, 0x45, 0x00, 0x3F, 0x2F, 0x06, 0xEC, 0x81, + 0x05, 0xFE, 0xB2, 0x5B, 0x22, 0x81, 0xB6, 0x3D, + 0x27, 0x33, 0xBE, 0x96, 0x1C, 0x29, 0x95, 0x1D, + 0x11, 0xDD, 0x22, 0x21, 0x65, 0x7A, 0x9F, 0x53, + 0x1D, 0xDA, 0x2A, 0x19, 0x4D, 0xBB, 0x12, 0x64, + 0x48, 0xBD, 0xEE, 0xB2, 0x58, 0xE0, 0x7E, 0xA6, + 0x59, 0xC7, 0x46, 0x19, 0xA6, 0x38, 0x0E, 0x1D, + 0x66, 0xD6, 0x83, 0x2B, 0xFE, 0x67, 0xF6, 0x38, + 0xCD, 0x8F, 0xAE, 0x1F, 0x27, 0x23, 0x02, 0x0F, + 0x9C, 0x40, 0xA3, 0xFD, 0xA6, 0x7E, 0xDA, 0x3B, + 0xD2, 0x92, 0x38, 0xFB, 0xD4, 0xD4, 0xB4, 0x88, + 0x5C, 0x2A, 0x99, 0x17, 0x6D, 0xB1, 0xA0, 0x6C, + 0x50, 0x07, 0x78, 0x49, 0x1A, 0x82, 0x88, 0xF1, + 0x85, 0x5F, 0x60, 0xFF, 0xFC, 0xF1, 0xD1, 0x37, + 0x3F, 0xD9, 0x4F, 0xC6, 0x0C, 0x18, 0x11, 0xE1, + 0xAC, 0x3F, 0x1C, 0x6D, 0x00, 0x3B, 0xEC, 0xDA, + 0x3B, 0x1F, 0x27, 0x25, 0xCA, 0x59, 0x5D, 0xE0, + 0xCA, 0x63, 0x32, 0x8F, 0x3B, 0xE5, 0x7C, 0xC9, + 0x77, 0x55, 0x60, 0x11, 0x95, 0x14, 0x0D, 0xFB, + 0x59, 0xD3, 0x9C, 0xE0, 0x91, 0x30, 0x8B, 0x41, + 0x05, 0x74, 0x6D, 0xAC, 0x23, 0xD3, 0x3E, 0x5F, + 0x7C, 0xE4, 0x84, 0x8D, 0xA3, 0x16, 0xA9, 0xC6, + 0x6B, 0x95, 0x81, 0xBA, 0x35, 0x73, 0xBF, 0xAF, + 0x31, 0x14, 0x96, 0x18, 0x8A, 0xB1, 0x54, 0x23, + 0x28, 0x2E, 0xE4, 0x16, 0xDC, 0x2A, 0x19, 0xC5, + 0x72, 0x4F, 0xA9, 0x1A, 0xE4, 0xAD, 0xC8, 0x8B, + 0xC6, 0x67, 0x96, 0xEA, 0xE5, 0x67, 0x7A, 0x01, + 0xF6, 0x4E, 0x8C, 0x08, 0x63, 0x13, 0x95, 0x82, + 0x2D, 0x9D, 0xB8, 0xFC, 0xEE, 0x35, 0xC0, 0x6B, + 0x1F, 0xEE, 0xA5, 0x47, 0x4D, 0x6D, 0x8F, 0x34, + 0xB1, 0x53, 0x4A, 0x93, 0x6A, 0x18, 0xB0, 0xE0, + 0xD2, 0x0E, 0xAB, 0x86, 0xBC, 0x9C, 0x6D, 0x6A, + 0x52, 0x07, 0x19, 0x4E, 0x67, 0xFA, 0x35, 0x55, + 0x1B, 0x56, 0x80, 0x26, 0x7B, 0x00, 0x64, 0x1C, + 0x0F, 0x21, 0x2D, 0x18, 0xEC, 0xA8, 0xD7, 0x32, + 0x7E, 0xD9, 0x1F, 0xE7, 0x64, 0xA8, 0x4E, 0xA1, + 0xB4, 0x3F, 0xF5, 0xB4, 0xF6, 0xE8, 0xE6, 0x2F, + 0x05, 0xC6, 0x61, 0xDE, 0xFB, 0x25, 0x88, 0x77, + 0xC3, 0x5B, 0x18, 0xA1, 0x51, 0xD5, 0xC4, 0x14, + 0xAA, 0xAD, 0x97, 0xBA, 0x3E, 0x49, 0x93, 0x32, + 0xE5, 0x96, 0x07, 0x8E, 0x60, 0x0D, 0xEB, 0x81, + 0x14, 0x9C, 0x44, 0x1C, 0xE9, 0x57, 0x82, 0xF2, + 0x2A, 0x28, 0x25, 0x63, 0xC5, 0xBA, 0xC1, 0x41, + 0x14, 0x23, 0x60, 0x5D, 0x1A, 0xE1, 0xAF, 0xAE, + 0x2C, 0x8B, 0x06, 0x60, 0x23, 0x7E, 0xC1, 0x28, + 0xAA, 0x0F, 0xE3, 0x46, 0x4E, 0x43, 0x58, 0x11, + 0x5D, 0xB8, 0x4C, 0xC3, 0xB5, 0x23, 0x07, 0x3A, + 0x28, 0xD4, 0x54, 0x98, 0x84, 0xB8, 0x1F, 0xF7, + 0x0E, 0x10, 0xBF, 0x36, 0x1C, 0x13, 0x72, 0x96, + 0x28, 0xD5, 0x34, 0x8F, 0x07, 0x21, 0x1E, 0x7E, + 0x4C, 0xF4, 0xF1, 0x8B, 0x28, 0x60, 0x90, 0xBD, + 0xB1, 0x24, 0x0B, 0x66, 0xD6, 0xCD, 0x4A, 0xFC, + 0xEA, 0xDC, 0x00, 0xCA, 0x44, 0x6C, 0xE0, 0x50, + 0x50, 0xFF, 0x18, 0x3A, 0xD2, 0xBB, 0xF1, 0x18, + 0xC1, 0xFC, 0x0E, 0xA5, 0x1F, 0x97, 0xD2, 0x2B, + 0x8F, 0x7E, 0x46, 0x70, 0x5D, 0x45, 0x27, 0xF4, + 0x5B, 0x42, 0xAE, 0xFF, 0x39, 0x58, 0x53, 0x37, + 0x6F, 0x69, 0x7D, 0xD5, 0xFD, 0xF2, 0xC5, 0x18, + 0x7D, 0x7D, 0x5F, 0x0E, 0x2E, 0xB8, 0xD4, 0x3F, + 0x17, 0xBA, 0x0F, 0x7C, 0x60, 0xFF, 0x43, 0x7F, + 0x53, 0x5D, 0xFE, 0xF2, 0x98, 0x33, 0xBF, 0x86, + 0xCB, 0xE8, 0x8E, 0xA4, 0xFB, 0xD4, 0x22, 0x1E, + 0x84, 0x11, 0x72, 0x83, 0x54, 0xFA, 0x30, 0xA7, + 0x00, 0x8F, 0x15, 0x4A, 0x41, 0xC7, 0xFC, 0x46, + 0x6B, 0x46, 0x45, 0xDB, 0xE2, 0xE3, 0x21, 0x26, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +#endif /* HAVE_FFDHE_Q */ + +const DhParams* wc_Dh_ffdhe8192_Get(void) +{ + static const DhParams ffdhe8192 = { + #ifdef HAVE_FFDHE_Q + dh_ffdhe8192_q, sizeof(dh_ffdhe8192_q), + #endif /* HAVE_FFDHE_Q */ + 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 !defined(WOLFSSL_QT) && !defined(OPENSSL_ALL) + if (mp_init_multi(&key->p, &key->g, &key->q, NULL, NULL, NULL) != MP_OKAY) +#else + if (mp_init_multi(&key->p,&key->g,&key->q,&key->pub,&key->priv,NULL) != MP_OKAY) +#endif + 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); +} + + +int wc_FreeDhKey(DhKey* key) +{ + if (key) { + mp_clear(&key->p); + mp_clear(&key->g); + mp_clear(&key->q); + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH); + #endif } - -#endif /* WOLFSSL_HAVE_MIN */ - - -void wc_InitDhKey(DhKey* key) -{ - (void)key; -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH - key->p.dp = 0; - key->g.dp = 0; -#endif -} - - -void wc_FreeDhKey(DhKey* key) -{ - (void)key; -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH - mp_clear(&key->p); - mp_clear(&key->g); -#endif -} - - -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 int GeneratePrivate(DhKey* key, RNG* rng, byte* priv, word32* privSz) -{ - int ret; - word32 sz = mp_unsigned_bin_size(&key->p); - sz = min(sz, 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) / - WOLFSSL_BIT_SIZE + 1); - - ret = wc_RNG_GenerateBlock(rng, priv, sz); - if (ret != 0) - return ret; - - priv[0] |= 0x0C; - - *privSz = sz; - return 0; } -static int GeneratePublic(DhKey* key, const byte* priv, word32 privSz, - byte* pub, word32* pubSz) +#ifndef WC_NO_RNG +/* 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); + } +#endif /* WOLFSSL_DH_CONST*/ + + +/* if not using fixed points use DiscreteLogWorkFactor function for unusual size + otherwise round up on size needed */ +#ifndef WOLFSSL_DH_CONST + #define WOLFSSL_DH_ROUND(x) +#else + #define WOLFSSL_DH_ROUND(x) \ + do { \ + if (x % 128) { \ + x &= 0xffffff80;\ + x += 128; \ + } \ + } \ + while (0) +#endif + + +#ifndef WOLFSSL_NO_DH186 +/* validate that (L,N) match allowed sizes from SP 800-56A, Section 5.5.1.1. + * modLen - represents L, the size of p in bits + * divLen - represents N, the size of q in bits + * return 0 on success, -1 on error */ +static int CheckDhLN(int modLen, int divLen) { - int ret = 0; + int ret = -1; - mp_int x; - mp_int y; - - if (mp_init_multi(&x, &y, 0, 0, 0, 0) != MP_OKAY) - return MP_INIT_E; - - if (mp_read_unsigned_bin(&x, priv, privSz) != MP_OKAY) - ret = MP_READ_E; - - if (ret == 0 && mp_exptmod(&key->g, &x, &key->p, &y) != MP_OKAY) - ret = MP_EXPTMOD_E; - - if (ret == 0 && mp_to_unsigned_bin(&y, pub) != MP_OKAY) - ret = MP_TO_E; - - if (ret == 0) - *pubSz = mp_unsigned_bin_size(&y); - - mp_clear(&y); - mp_clear(&x); + switch (modLen) { + /* FA */ + case 1024: + if (divLen == 160) + ret = 0; + break; + /* FB, FC */ + case 2048: + if (divLen == 224 || divLen == 256) + ret = 0; + break; + default: + break; + } return ret; } -int wc_DhGenerateKeyPair(DhKey* key, RNG* rng, byte* priv, word32* privSz, - byte* pub, word32* pubSz) +/* Create DH private key + * + * Based on NIST FIPS 186-4, + * "B.1.1 Key Pair Generation Using Extra Random Bits" + * + * dh - pointer to initialized DhKey structure, needs to have dh->q + * rng - pointer to initialized WC_RNG structure + * priv - output location for generated private key + * privSz - IN/OUT, size of priv buffer, size of generated private key + * + * return 0 on success, negative on error */ +static int GeneratePrivateDh186(DhKey* key, WC_RNG* rng, byte* priv, + word32* privSz) { - int ret = GeneratePrivate(key, rng, priv, privSz); + byte* cBuf; + int qSz, pSz, cSz, err; +#ifdef WOLFSSL_SMALL_STACK + mp_int* tmpQ = NULL; + mp_int* tmpX = NULL; +#else + mp_int tmpQ[1], tmpX[1]; +#endif - return (ret != 0) ? ret : GeneratePublic(key, priv, *privSz, pub, pubSz); + /* Parameters validated in calling functions. */ + + if (mp_iszero(&key->q) == MP_YES) { + WOLFSSL_MSG("DH q parameter needed for FIPS 186-4 key generation"); + return BAD_FUNC_ARG; + } + + qSz = mp_unsigned_bin_size(&key->q); + pSz = mp_unsigned_bin_size(&key->p); + + /* verify (L,N) pair bit lengths */ + if (CheckDhLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0) { + WOLFSSL_MSG("DH param sizes do not match SP 800-56A requirements"); + return BAD_FUNC_ARG; + } + + /* generate extra 64 bits so that bias from mod function is negligible */ + cSz = qSz + (64 / WOLFSSL_BIT_SIZE); + cBuf = (byte*)XMALLOC(cSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cBuf == NULL) { + return MEMORY_E; + } +#ifdef WOLFSSL_SMALL_STACK + tmpQ = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (tmpQ == NULL) { + XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + tmpX = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (tmpX == NULL) { + XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } +#endif + + + if ((err = mp_init_multi(tmpX, tmpQ, NULL, NULL, NULL, NULL)) + != MP_OKAY) { + XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH); + XFREE(tmpX, key->heap, DYNAMIC_TYPE_DH); +#endif + return err; + } + + do { + /* generate N+64 bits (c) from RBG into tmpX, making sure positive. + * Hash_DRBG uses SHA-256 which matches maximum + * requested_security_strength of (L,N) */ + err = wc_RNG_GenerateBlock(rng, cBuf, cSz); + if (err == MP_OKAY) + err = mp_read_unsigned_bin(tmpX, cBuf, cSz); + if (err != MP_OKAY) { + mp_clear(tmpX); + mp_clear(tmpQ); + XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH); + XFREE(tmpX, key->heap, DYNAMIC_TYPE_DH); +#endif + return err; + } + } while (mp_cmp_d(tmpX, 1) != MP_GT); + + ForceZero(cBuf, cSz); + XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + + /* tmpQ = q - 1 */ + if (err == MP_OKAY) + err = mp_copy(&key->q, tmpQ); + + if (err == MP_OKAY) + err = mp_sub_d(tmpQ, 1, tmpQ); + + /* x = c mod (q-1), tmpX holds c */ + if (err == MP_OKAY) + err = mp_mod(tmpX, tmpQ, tmpX); + + /* x = c mod (q-1) + 1 */ + if (err == MP_OKAY) + err = mp_add_d(tmpX, 1, tmpX); + + /* copy tmpX into priv */ + if (err == MP_OKAY) { + pSz = mp_unsigned_bin_size(tmpX); + if (pSz > (int)*privSz) { + WOLFSSL_MSG("DH private key output buffer too small"); + err = BAD_FUNC_ARG; + } else { + *privSz = pSz; + err = mp_to_unsigned_bin(tmpX, priv); + } + } + + mp_forcezero(tmpX); + mp_clear(tmpX); + mp_clear(tmpQ); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH); + XFREE(tmpX, key->heap, DYNAMIC_TYPE_DH); +#endif + + return err; } +#endif /* WOLFSSL_NO_DH186 */ +#endif /* !WC_NO_RNG */ + +static int GeneratePrivateDh(DhKey* key, WC_RNG* rng, byte* priv, + word32* privSz) +{ +#ifndef WC_NO_RNG + int ret = 0; + word32 sz = 0; + +#ifndef WOLFSSL_NO_DH186 + if (mp_iszero(&key->q) == MP_NO) { + + /* q param available, use NIST FIPS 186-4, "B.1.1 Key Pair + * Generation Using Extra Random Bits" */ + ret = GeneratePrivateDh186(key, rng, priv, privSz); + + } else +#endif + { + + sz = mp_unsigned_bin_size(&key->p); + + /* Table of predetermined values from the operation + 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) / + WOLFSSL_BIT_SIZE + 1 + Sizes in table checked against RFC 3526 + */ + WOLFSSL_DH_ROUND(sz); /* if using fixed points only, then round up */ + switch (sz) { + case 128: sz = 21; break; + case 256: sz = 29; break; + case 384: sz = 34; break; + case 512: sz = 39; break; + case 640: sz = 42; break; + case 768: sz = 46; break; + 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 + } + + ret = wc_RNG_GenerateBlock(rng, priv, sz); + + if (ret == 0) { + priv[0] |= 0x0C; + *privSz = sz; + } + } + + return ret; +#else + (void)key; + (void)rng; + (void)priv; + (void)privSz; + return NOT_COMPILED_IN; +#endif /* WC_NO_RNG */ +} + + +static int GeneratePublicDh(DhKey* key, byte* priv, word32 privSz, + byte* pub, word32* pubSz) +{ + int ret = 0; +#ifndef WOLFSSL_SP_MATH +#ifdef WOLFSSL_SMALL_STACK + mp_int* x; + mp_int* y; +#else + mp_int x[1]; + mp_int y[1]; +#endif +#endif + +#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 +#ifdef WOLFSSL_SP_4096 + if (mp_count_bits(&key->p) == 4096) + return sp_DhExp_4096(&key->g, priv, privSz, &key->p, pub, pubSz); +#endif +#endif + +#ifndef WOLFSSL_SP_MATH +#ifdef WOLFSSL_SMALL_STACK + x = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (x == NULL) + return MEMORY_E; + y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (y == NULL) { + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } +#endif + if (mp_init_multi(x, y, 0, 0, 0, 0) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + #endif + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(x, priv, privSz) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0 && mp_exptmod(&key->g, x, &key->p, y) != MP_OKAY) + ret = MP_EXPTMOD_E; + + if (ret == 0 && mp_to_unsigned_bin(y, pub) != MP_OKAY) + ret = MP_TO_E; + + if (ret == 0) + *pubSz = mp_unsigned_bin_size(y); + + mp_clear(y); + mp_clear(x); +#ifdef WOLFSSL_SMALL_STACK + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); +#endif +#else + ret = WC_KEY_SIZE_E; +#endif + + return ret; +} + +static int wc_DhGenerateKeyPair_Sync(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; + } + + ret = GeneratePrivateDh(key, rng, priv, privSz); + + return (ret != 0) ? ret : GeneratePublicDh(key, priv, *privSz, pub, 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 pBits; + + /* QAT DH sizes: 768, 1024, 1536, 2048, 3072 and 4096 bits */ + pBits = mp_unsigned_bin_size(&key->p) * 8; + if (pBits == 768 || pBits == 1024 || pBits == 1536 || + pBits == 2048 || pBits == 3072 || pBits == 4096) { + 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, optionally allowing + * the public key to be checked against the large prime (q). + * Check per process in SP 800-56Ar3, section 5.6.2.3.1. + * + * key DH key group parameters. + * pub Public Key. + * pubSz Public Key size. + * prime Large prime (q), optionally NULL to skip check + * primeSz Size of large prime + * + * returns 0 on success or error code + */ +int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz, + const byte* prime, word32 primeSz) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + mp_int* y = NULL; + mp_int* p = NULL; + mp_int* q = NULL; +#else + mp_int y[1]; + mp_int p[1]; + mp_int q[1]; +#endif + + if (key == NULL || pub == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (y == NULL) + return MEMORY_E; + p = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (p == NULL) { + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } + q = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (q == NULL) { + XFREE(p, key->heap, DYNAMIC_TYPE_DH); + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } +#endif + + if (mp_init_multi(y, p, q, NULL, NULL, NULL) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, key->heap, DYNAMIC_TYPE_DH); + XFREE(p, key->heap, DYNAMIC_TYPE_DH); + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + #endif + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(y, pub, pubSz) != MP_OKAY) { + ret = MP_READ_E; + } + + if (ret == 0 && prime != NULL) { + if (mp_read_unsigned_bin(q, prime, primeSz) != MP_OKAY) + ret = MP_READ_E; + + } else if (mp_iszero(&key->q) == MP_NO) { + /* use q available in DhKey */ + if (mp_copy(&key->q, q) != MP_OKAY) + ret = MP_INIT_E; + } + + /* SP 800-56Ar3, section 5.6.2.3.1, process step 1 */ + /* pub (y) should not be 0 or 1 */ + if (ret == 0 && mp_cmp_d(y, 2) == MP_LT) { + ret = MP_CMP_E; + } + + /* pub (y) shouldn't be greater than or equal to p - 1 */ + if (ret == 0 && mp_copy(&key->p, p) != MP_OKAY) { + ret = MP_INIT_E; + } + if (ret == 0 && mp_sub_d(p, 2, p) != MP_OKAY) { + ret = MP_SUB_E; + } + if (ret == 0 && mp_cmp(y, p) == MP_GT) { + ret = MP_CMP_E; + } + + if (ret == 0 && (prime != NULL || (mp_iszero(&key->q) == MP_NO) )) { + + /* restore key->p into p */ + if (mp_copy(&key->p, p) != MP_OKAY) + ret = MP_INIT_E; + } + + if (ret == 0 && prime != NULL) { +#ifdef WOLFSSL_HAVE_SP_DH +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->p) == 2048) { + ret = sp_ModExp_2048(y, q, p, y); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->p) == 3072) { + ret = sp_ModExp_3072(y, q, p, y); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#ifdef WOLFSSL_SP_NO_4096 + if (mp_count_bits(&key->p) == 4096) { + ret = sp_ModExp_4096(y, q, p, y); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#endif + + { + /* SP 800-56Ar3, section 5.6.2.3.1, process step 2 */ +#ifndef WOLFSSL_SP_MATH + /* calculate (y^q) mod(p), store back into y */ + if (mp_exptmod(y, q, p, y) != MP_OKAY) + ret = MP_EXPTMOD_E; +#else + ret = WC_KEY_SIZE_E; +#endif + } + + /* verify above == 1 */ + if (ret == 0 && mp_cmp_d(y, 1) != MP_EQ) + ret = MP_CMP_E; + } + + mp_clear(y); + mp_clear(p); + mp_clear(q); +#ifdef WOLFSSL_SMALL_STACK + XFREE(q, key->heap, DYNAMIC_TYPE_DH); + XFREE(p, key->heap, DYNAMIC_TYPE_DH); + XFREE(y, key->heap, DYNAMIC_TYPE_DH); +#endif + + return ret; +} + + +/* 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) +{ + return wc_DhCheckPubKey_ex(key, pub, pubSz, NULL, 0); +} + + +/** + * Quick validity check of public key value against prime. + * Checks are: + * - Public key not 0 or 1 + * - Public key not equal to prime or prime - 1 + * - Public key not bigger than prime. + * + * prime Big-endian encoding of prime in bytes. + * primeSz Size of prime in bytes. + * pub Big-endian encoding of public key in bytes. + * pubSz Size of public key in bytes. + */ +int wc_DhCheckPubValue(const byte* prime, word32 primeSz, const byte* pub, + word32 pubSz) +{ + int ret = 0; + word32 i; + + for (i = 0; i < pubSz && pub[i] == 0; i++) { + } + pubSz -= i; + pub += i; + + if (pubSz == 0 || (pubSz == 1 && pub[0] == 1)) + ret = MP_VAL; + else if (pubSz == primeSz) { + for (i = 0; i < pubSz-1 && pub[i] == prime[i]; i++) { + } + if (i == pubSz-1 && (pub[i] == prime[i] || pub[i] == prime[i] - 1)) + ret = MP_VAL; + else if (pub[i] > prime[i]) + ret = MP_VAL; + } + else if (pubSz > primeSz) + ret = MP_VAL; + + return ret; +} + + +/* Check DH Private Key for invalid numbers, optionally allowing + * the private key to be checked against the large prime (q). + * Check per process in SP 800-56Ar3, section 5.6.2.1.2. + * + * key DH key group parameters. + * priv Private Key. + * privSz Private Key size. + * prime Large prime (q), optionally NULL to skip check + * primeSz Size of large prime + * + * returns 0 on success or error code + */ +int wc_DhCheckPrivKey_ex(DhKey* key, const byte* priv, word32 privSz, + const byte* prime, word32 primeSz) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + mp_int* x = NULL; + mp_int* q = NULL; +#else + mp_int x[1]; + mp_int q[1]; +#endif + + if (key == NULL || priv == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + x = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (x == NULL) + return MEMORY_E; + q = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (q == NULL) { + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } +#endif + + if (mp_init_multi(x, q, NULL, NULL, NULL, NULL) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + #endif + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(x, priv, privSz) != MP_OKAY) { + ret = MP_READ_E; + } + + if (ret == 0) { + if (prime != NULL) { + if (mp_read_unsigned_bin(q, prime, primeSz) != MP_OKAY) + ret = MP_READ_E; + } + else if (mp_iszero(&key->q) == MP_NO) { + /* use q available in DhKey */ + if (mp_copy(&key->q, q) != MP_OKAY) + ret = MP_INIT_E; + } + } + + /* priv (x) should not be 0 */ + if (ret == 0) { + if (mp_cmp_d(x, 0) == MP_EQ) + ret = MP_CMP_E; + } + + if (ret == 0) { + if (mp_iszero(q) == MP_NO) { + /* priv (x) shouldn't be greater than q - 1 */ + if (ret == 0) { + if (mp_copy(&key->q, q) != MP_OKAY) + ret = MP_INIT_E; + } + if (ret == 0) { + if (mp_sub_d(q, 1, q) != MP_OKAY) + ret = MP_SUB_E; + } + if (ret == 0) { + if (mp_cmp(x, q) == MP_GT) + ret = DH_CHECK_PRIV_E; + } + } + } + + mp_clear(x); + mp_clear(q); +#ifdef WOLFSSL_SMALL_STACK + XFREE(q, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); +#endif + + return ret; +} + + +/* Check DH Private Key for invalid numbers + * + * key DH key group parameters. + * priv Private Key. + * privSz Private Key size. + * + * returns 0 on success or error code + */ +int wc_DhCheckPrivKey(DhKey* key, const byte* priv, word32 privSz) +{ + return wc_DhCheckPrivKey_ex(key, priv, privSz, NULL, 0); +} + + +/* Check DH Keys for pair-wise consistency per process in + * SP 800-56Ar3, section 5.6.2.1.4, method (b) for FFC. + * + * key DH key group parameters. + * pub Public Key. + * pubSz Public Key size. + * priv Private Key. + * privSz Private Key size. + * + * returns 0 on success or error code + */ +int wc_DhCheckKeyPair(DhKey* key, const byte* pub, word32 pubSz, + const byte* priv, word32 privSz) +{ +#ifdef WOLFSSL_SMALL_STACK + mp_int* publicKey = NULL; + mp_int* privateKey = NULL; + mp_int* checkKey = NULL; +#else + mp_int publicKey[1]; + mp_int privateKey[1]; + mp_int checkKey[1]; +#endif + int ret = 0; + + if (key == NULL || pub == NULL || priv == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + publicKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (publicKey == NULL) + return MEMORY_E; + privateKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (privateKey == NULL) { + XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } + checkKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (checkKey == NULL) { + XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH); + XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } +#endif + + if (mp_init_multi(publicKey, privateKey, checkKey, + NULL, NULL, NULL) != MP_OKAY) { + + #ifdef WOLFSSL_SMALL_STACK + XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH); + XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH); + XFREE(checkKey, key->heap, DYNAMIC_TYPE_DH); + #endif + return MP_INIT_E; + } + + /* Load the private and public keys into big integers. */ + if (mp_read_unsigned_bin(publicKey, pub, pubSz) != MP_OKAY || + mp_read_unsigned_bin(privateKey, priv, privSz) != MP_OKAY) { + + ret = MP_READ_E; + } + + /* Calculate checkKey = g^privateKey mod p */ + if (ret == 0) { +#ifdef WOLFSSL_HAVE_SP_DH +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->p) == 2048) { + ret = sp_ModExp_2048(&key->g, privateKey, &key->p, checkKey); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->p) == 3072) { + ret = sp_ModExp_3072(&key->g, privateKey, &key->p, checkKey); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#ifdef WOLFSSL_SP_4096 + if (mp_count_bits(&key->p) == 4096) { + ret = sp_ModExp_4096(&key->g, privateKey, &key->p, checkKey); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#endif + { +#ifndef WOLFSSL_SP_MATH + if (mp_exptmod(&key->g, privateKey, &key->p, checkKey) != MP_OKAY) + ret = MP_EXPTMOD_E; +#else + ret = WC_KEY_SIZE_E; +#endif + } + } + + /* Compare the calculated public key to the supplied check value. */ + if (ret == 0) { + if (mp_cmp(checkKey, publicKey) != MP_EQ) + ret = MP_CMP_E; + } + + mp_forcezero(privateKey); + mp_clear(privateKey); + mp_clear(publicKey); + mp_clear(checkKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(checkKey, key->heap, DYNAMIC_TYPE_DH); + XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH); + XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH); +#endif + + 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; +#ifdef WOLFSSL_SMALL_STACK + mp_int* y; +#ifndef WOLFSSL_SP_MATH + mp_int* x; + mp_int* z; +#endif +#else + mp_int y[1]; +#ifndef WOLFSSL_SP_MATH + mp_int x[1]; + mp_int z[1]; +#endif +#endif + +#ifdef WOLFSSL_VALIDATE_FFC_IMPORT + if (wc_DhCheckPrivKey(key, priv, privSz) != 0) { + WOLFSSL_MSG("wc_DhAgree wc_DhCheckPrivKey failed"); + return DH_CHECK_PRIV_E; + } + + if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) { + WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed"); + return DH_CHECK_PUB_E; + } +#endif + +#ifdef WOLFSSL_SMALL_STACK + y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (y == NULL) + return MEMORY_E; +#ifndef WOLFSSL_SP_MATH + x = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (x == NULL) { + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } + z = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (z == NULL) { + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } +#endif +#endif + +#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); + #ifdef WOLFSSL_SMALL_STACK + #ifndef WOLFSSL_SP_MATH + XFREE(z, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + #endif + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + #endif + 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); + #ifdef WOLFSSL_SMALL_STACK + #ifndef WOLFSSL_SP_MATH + XFREE(z, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + #endif + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + #endif + return ret; + } +#endif +#ifdef WOLFSSL_SP_4096 + if (mp_count_bits(&key->p) == 4096) { + 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_4096(y, priv, privSz, &key->p, agree, agreeSz); + + mp_clear(y); + #ifdef WOLFSSL_SMALL_STACK + #ifndef WOLFSSL_SP_MATH + XFREE(z, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + #endif + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + #endif + return ret; + } +#endif +#endif + +#ifndef WOLFSSL_SP_MATH + if (mp_init_multi(x, y, z, 0, 0, 0) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(z, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + #endif + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(x, priv, privSz) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0 && mp_exptmod(y, x, &key->p, z) != MP_OKAY) + ret = MP_EXPTMOD_E; + + /* make sure z is not one (SP800-56A, 5.7.1.1) */ + if (ret == 0 && (mp_cmp_d(z, 1) == MP_EQ)) + ret = MP_VAL; + + if (ret == 0 && mp_to_unsigned_bin(z, agree) != MP_OKAY) + ret = MP_TO_E; + + if (ret == 0) + *agreeSz = mp_unsigned_bin_size(z); + + mp_clear(z); + mp_clear(y); + mp_forcezero(x); +#endif + +#ifdef WOLFSSL_SMALL_STACK +#ifndef WOLFSSL_SP_MATH + XFREE(z, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); +#endif + XFREE(y, key->heap, DYNAMIC_TYPE_DH); +#endif + + 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; + +#if defined(HAVE_INTEL_QA) + word32 pBits; + + /* QAT DH sizes: 768, 1024, 1536, 2048, 3072 and 4096 bits */ + pBits = mp_unsigned_bin_size(&key->p) * 8; + if (pBits == 768 || pBits == 1024 || pBits == 1536 || + pBits == 2048 || pBits == 3072 || pBits == 4096) { + 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); + 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_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; + } +#endif + + /* otherwise use software DH */ + ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + + 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; - mp_int x; - mp_int y; - mp_int z; + if (key == NULL || agree == NULL || agreeSz == NULL || priv == NULL || + otherPub == NULL) { + return BAD_FUNC_ARG; + } - if (mp_init_multi(&x, &y, &z, 0, 0, 0) != MP_OKAY) - return MP_INIT_E; - - if (mp_read_unsigned_bin(&x, priv, privSz) != MP_OKAY) - ret = MP_READ_E; - - if (ret == 0 && mp_read_unsigned_bin(&y, otherPub, pubSz) != MP_OKAY) - ret = MP_READ_E; - - if (ret == 0 && mp_exptmod(&y, &x, &key->p, &z) != MP_OKAY) - ret = MP_EXPTMOD_E; - - if (ret == 0 && mp_to_unsigned_bin(&z, agree) != MP_OKAY) - ret = MP_TO_E; - - if (ret == 0) - *agreeSz = mp_unsigned_bin_size(&z); - - mp_clear(&z); - mp_clear(&y); - mp_clear(&x); +#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; } +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +/* Sets private and public key in DhKey if both are available, otherwise sets + either private or public key, depending on which is available. + Returns WOLFSSL_SUCCESS if at least one of the keys was set. */ +WOLFSSL_LOCAL int wc_DhSetFullKeys(DhKey* key,const byte* priv_key,word32 privSz, + const byte* pub_key, word32 pubSz) +{ + byte havePriv = 0; + byte havePub = 0; + mp_int* keyPriv = NULL; + mp_int* keyPub = NULL; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + havePriv = ( (priv_key != NULL) && (privSz > 0) ); + havePub = ( (pub_key != NULL) && (pubSz > 0) ); + + if (!havePub && !havePriv) { + WOLFSSL_MSG("No Public or Private Key to Set"); + return BAD_FUNC_ARG; + } + /* Set Private Key */ + if (havePriv == TRUE) { + /* may have leading 0 */ + if (priv_key[0] == 0) { + privSz--; priv_key++; + } + if (mp_init(&key->priv) != MP_OKAY) + havePriv = FALSE; + } + + if (havePriv == TRUE) { + if (mp_read_unsigned_bin(&key->priv, priv_key, privSz) != MP_OKAY) { + havePriv = FALSE; + } else { + keyPriv = &key->priv; + WOLFSSL_MSG("DH Private Key Set."); + } + } + + /* Set Public Key */ + if (havePub == TRUE) { + /* may have leading 0 */ + if (pub_key[0] == 0) { + pubSz--; pub_key++; + } + if (mp_init(&key->pub) != MP_OKAY) + havePub = FALSE; + } + + if (havePub == TRUE) { + if (mp_read_unsigned_bin(&key->pub, pub_key, pubSz) != MP_OKAY) { + havePub = FALSE; + } else { + keyPub = &key->pub; + WOLFSSL_MSG("DH Public Key Set."); + } + } + /* Free Memory if error occured */ + if (havePriv == FALSE && keyPriv != NULL) + mp_clear(keyPriv); + if (havePub == FALSE && keyPub != NULL) + mp_clear(keyPub); + + /* WOLFSSL_SUCCESS if private or public was set else WOLFSSL_FAILURE */ + return havePriv || havePub; +} +#endif + +static int _DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, + word32 gSz, const byte* q, word32 qSz, int trusted, + WC_RNG* rng) +{ + int ret = 0; + mp_int* keyP = NULL; + mp_int* keyG = NULL; + + if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* may have leading 0 */ + if (p[0] == 0) { + pSz--; p++; + } + + if (g[0] == 0) { + gSz--; g++; + } + + if (q != NULL) { + if (q[0] == 0) { + qSz--; q++; + } + } + + if (mp_init(&key->p) != MP_OKAY) + ret = MP_INIT_E; + } + + if (ret == 0) { + if (mp_read_unsigned_bin(&key->p, p, pSz) != MP_OKAY) + ret = ASN_DH_KEY_E; + else + keyP = &key->p; + } + + if (ret == 0 && !trusted) { + int isPrime = 0; + if (rng != NULL) + ret = mp_prime_is_prime_ex(keyP, 8, &isPrime, rng); + else + ret = mp_prime_is_prime(keyP, 8, &isPrime); + + if (ret == 0 && isPrime == 0) + ret = DH_CHECK_PUB_E; + } + + if (ret == 0 && mp_init(&key->g) != MP_OKAY) + ret = MP_INIT_E; + if (ret == 0) { + if (mp_read_unsigned_bin(&key->g, g, gSz) != MP_OKAY) + ret = ASN_DH_KEY_E; + else + keyG = &key->g; + } + + if (ret == 0 && q != NULL) { + if (mp_init(&key->q) != MP_OKAY) + ret = MP_INIT_E; + } + if (ret == 0 && q != NULL) { + if (mp_read_unsigned_bin(&key->q, q, qSz) != MP_OKAY) + ret = MP_INIT_E; + } + + if (ret != 0 && key != NULL) { + if (keyG) + mp_clear(keyG); + if (keyP) + mp_clear(keyP); + } + + return ret; +} + + +int wc_DhSetCheckKey(DhKey* key, const byte* p, word32 pSz, const byte* g, + word32 gSz, const byte* q, word32 qSz, int trusted, + WC_RNG* rng) +{ + return _DhSetKey(key, p, pSz, g, gSz, q, qSz, trusted, rng); +} + + +int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, const byte* g, + word32 gSz, const byte* q, word32 qSz) +{ + return _DhSetKey(key, p, pSz, g, gSz, q, qSz, 1, NULL); +} + /* not in asn anymore since no actual asn types used */ 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) - return BAD_FUNC_ARG; - - /* may have leading 0 */ - if (p[0] == 0) { - pSz--; p++; - } - - if (g[0] == 0) { - gSz--; g++; - } - - if (mp_init(&key->p) != MP_OKAY) - return MP_INIT_E; - if (mp_read_unsigned_bin(&key->p, p, pSz) != 0) { - mp_clear(&key->p); - return ASN_DH_KEY_E; - } - - if (mp_init(&key->g) != MP_OKAY) { - mp_clear(&key->p); - return MP_INIT_E; - } - if (mp_read_unsigned_bin(&key->g, g, gSz) != 0) { - mp_clear(&key->g); - mp_clear(&key->p); - return ASN_DH_KEY_E; - } - - return 0; + return _DhSetKey(key, p, pSz, g, gSz, NULL, 0, 1, NULL); } -#endif /* NO_DH */ +#ifdef WOLFSSL_KEY_GEN +/* modulus_size in bits */ +int wc_DhGenerateParams(WC_RNG *rng, int modSz, DhKey *dh) +{ + mp_int tmp, tmp2; + int groupSz = 0, bufSz = 0, + primeCheckCount = 0, + primeCheck = MP_NO, + ret = 0; + unsigned char *buf = NULL; + + if (rng == NULL || dh == NULL) + ret = BAD_FUNC_ARG; + + /* set group size in bytes from modulus size + * FIPS 186-4 defines valid values (1024, 160) (2048, 256) (3072, 256) + */ + if (ret == 0) { + switch (modSz) { + case 1024: + groupSz = 20; + break; + case 2048: + case 3072: + groupSz = 32; + break; + default: + ret = BAD_FUNC_ARG; + break; + } + } + + if (ret == 0) { + /* modulus size in bytes */ + modSz /= WOLFSSL_BIT_SIZE; + bufSz = modSz - groupSz; + + /* allocate ram */ + buf = (unsigned char *)XMALLOC(bufSz, + dh->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) + ret = MEMORY_E; + } + + /* make a random string that will be multiplied against q */ + if (ret == 0) + ret = wc_RNG_GenerateBlock(rng, buf, bufSz); + + if (ret == 0) { + /* force magnitude */ + buf[0] |= 0xC0; + /* force even */ + buf[bufSz - 1] &= ~1; + + if (mp_init_multi(&tmp, &tmp2, &dh->p, &dh->q, &dh->g, 0) + != MP_OKAY) { + ret = MP_INIT_E; + } + } + + if (ret == 0) { + if (mp_read_unsigned_bin(&tmp2, buf, bufSz) != MP_OKAY) + ret = MP_READ_E; + } + + /* make our prime q */ + if (ret == 0) { + if (mp_rand_prime(&dh->q, groupSz, rng, NULL) != MP_OKAY) + ret = PRIME_GEN_E; + } + + /* p = random * q */ + if (ret == 0) { + if (mp_mul(&dh->q, &tmp2, &dh->p) != MP_OKAY) + ret = MP_MUL_E; + } + + /* p = random * q + 1, so q is a prime divisor of p-1 */ + if (ret == 0) { + if (mp_add_d(&dh->p, 1, &dh->p) != MP_OKAY) + ret = MP_ADD_E; + } + + /* tmp = 2q */ + if (ret == 0) { + if (mp_add(&dh->q, &dh->q, &tmp) != MP_OKAY) + ret = MP_ADD_E; + } + + /* loop until p is prime */ + if (ret == 0) { + do { + if (mp_prime_is_prime_ex(&dh->p, 8, &primeCheck, rng) != MP_OKAY) + ret = PRIME_GEN_E; + + if (primeCheck != MP_YES) { + /* p += 2q */ + if (mp_add(&tmp, &dh->p, &dh->p) != MP_OKAY) + ret = MP_ADD_E; + else + primeCheckCount++; + } + } while (ret == 0 && primeCheck == MP_NO); + } + + /* tmp2 += (2*loop_check_prime) + * to have p = (q * tmp2) + 1 prime + */ + if ((ret == 0) && (primeCheckCount)) { + if (mp_add_d(&tmp2, 2 * primeCheckCount, &tmp2) != MP_OKAY) + ret = MP_ADD_E; + } + + /* find a value g for which g^tmp2 != 1 */ + if ((ret == 0) && (mp_set(&dh->g, 1) != MP_OKAY)) + ret = MP_ZERO_E; + + if (ret == 0) { + do { + if (mp_add_d(&dh->g, 1, &dh->g) != MP_OKAY) + ret = MP_ADD_E; + else if (mp_exptmod(&dh->g, &tmp2, &dh->p, &tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + } while (ret == 0 && mp_cmp_d(&tmp, 1) == MP_EQ); + } + + if (ret == 0) { + /* at this point tmp generates a group of order q mod p */ + mp_exch(&tmp, &dh->g); + } + + /* clear the parameters if there was an error */ + if ((ret != 0) && (dh != NULL)) { + mp_clear(&dh->q); + mp_clear(&dh->p); + mp_clear(&dh->g); + } + + if (buf != NULL) { + ForceZero(buf, bufSz); + if (dh != NULL) { + XFREE(buf, dh->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + } + mp_clear(&tmp); + mp_clear(&tmp2); + + return ret; +} + + +/* Export raw DH parameters from DhKey structure + * + * dh - pointer to initialized DhKey structure + * p - output location for DH (p) parameter + * pSz - [IN/OUT] size of output buffer for p, size of p + * q - output location for DH (q) parameter + * qSz - [IN/OUT] size of output buffer for q, size of q + * g - output location for DH (g) parameter + * gSz - [IN/OUT] size of output buffer for g, size of g + * + * If p, q, and g pointers are all passed in as NULL, the function + * will set pSz, qSz, and gSz to the required output buffer sizes for p, + * q, and g. In this case, the function will return LENGTH_ONLY_E. + * + * returns 0 on success, negative upon failure + */ +int wc_DhExportParamsRaw(DhKey* dh, byte* p, word32* pSz, + byte* q, word32* qSz, byte* g, word32* gSz) +{ + int ret = 0; + word32 pLen = 0, qLen = 0, gLen = 0; + + if (dh == NULL || pSz == NULL || qSz == NULL || gSz == NULL) + ret = BAD_FUNC_ARG; + + /* get required output buffer sizes */ + if (ret == 0) { + pLen = mp_unsigned_bin_size(&dh->p); + qLen = mp_unsigned_bin_size(&dh->q); + gLen = mp_unsigned_bin_size(&dh->g); + + /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */ + if (p == NULL && q == NULL && g == NULL) { + *pSz = pLen; + *qSz = qLen; + *gSz = gLen; + ret = LENGTH_ONLY_E; + } + } + + if (ret == 0) { + if (p == NULL || q == NULL || g == NULL) + ret = BAD_FUNC_ARG; + } + + /* export p */ + if (ret == 0) { + if (*pSz < pLen) { + WOLFSSL_MSG("Output buffer for DH p parameter too small, " + "required size placed into pSz"); + *pSz = pLen; + ret = BUFFER_E; + } + } + + if (ret == 0) { + *pSz = pLen; + if (mp_to_unsigned_bin(&dh->p, p) != MP_OKAY) + ret = MP_TO_E; + } + + /* export q */ + if (ret == 0) { + if (*qSz < qLen) { + WOLFSSL_MSG("Output buffer for DH q parameter too small, " + "required size placed into qSz"); + *qSz = qLen; + ret = BUFFER_E; + } + } + + if (ret == 0) { + *qSz = qLen; + if (mp_to_unsigned_bin(&dh->q, q) != MP_OKAY) + ret = MP_TO_E; + } + + /* export g */ + if (ret == 0) { + if (*gSz < gLen) { + WOLFSSL_MSG("Output buffer for DH g parameter too small, " + "required size placed into gSz"); + *gSz = gLen; + ret = BUFFER_E; + } + } + + if (ret == 0) { + *gSz = gLen; + if (mp_to_unsigned_bin(&dh->g, g) != MP_OKAY) + ret = MP_TO_E; + } + + return ret; +} + +#endif /* WOLFSSL_KEY_GEN */ + +#endif /* NO_DH */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/dsa.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/dsa.c index f2124b197..4b83a571d 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/dsa.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/dsa.c @@ -1,8 +1,8 @@ /* dsa.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -27,97 +28,703 @@ #ifndef NO_DSA -#include -#include #include +#include #include +#include +#include +#include - -enum { - DSA_HALF_SIZE = 20, /* r and s size */ - DSA_SIG_SIZE = 40 /* signature size */ -}; - - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - -void wc_InitDsaKey(DsaKey* key) -{ - key->type = -1; /* haven't decided yet */ - -/* 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; - - key->x.dp = 0; /* private alloc parts */ +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include #endif + +int wc_InitDsaKey(DsaKey* key) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + key->type = -1; /* haven't decided yet */ + key->heap = NULL; + + return mp_init_multi( + /* public alloc parts */ + &key->p, + &key->q, + &key->g, + &key->y, + + /* private alloc parts */ + &key->x, + NULL + ); +} + + +int wc_InitDsaKey_h(DsaKey* key, void* h) +{ + int ret = wc_InitDsaKey(key); + if (ret == 0) + key->heap = h; + + 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 } -int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, RNG* rng) +/* validate that (L,N) match allowed sizes from FIPS 186-4, Section 4.2. + * modLen - represents L, the size of p (prime modulus) in bits + * divLen - represents N, the size of q (prime divisor) in bits + * return 0 on success, -1 on error */ +static int CheckDsaLN(int modLen, int divLen) { - mp_int k, kInv, r, s, H; - int ret, sz; - byte buffer[DSA_HALF_SIZE]; + int ret = -1; - sz = min(sizeof(buffer), mp_unsigned_bin_size(&key->q)); + switch (modLen) { + case 1024: + if (divLen == 160) + ret = 0; + break; + case 2048: + if (divLen == 224 || divLen == 256) + ret = 0; + break; + case 3072: + if (divLen == 256) + ret = 0; + break; + default: + break; + } - /* generate k */ - ret = wc_RNG_GenerateBlock(rng, buffer, sz); - if (ret != 0) - return ret; + return ret; +} - buffer[0] |= 0x0C; - if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY) +#ifdef WOLFSSL_KEY_GEN + +/* Create DSA key pair (&dsa->x, &dsa->y) + * + * Based on NIST FIPS 186-4, + * "B.1.1 Key Pair Generation Using Extra Random Bits" + * + * rng - pointer to initialized WC_RNG structure + * dsa - pointer to initialized DsaKey structure, will hold generated key + * + * return 0 on success, negative on error */ +int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa) +{ + byte* cBuf; + int qSz, pSz, cSz, err; + mp_int tmpQ; + + if (rng == NULL || dsa == NULL) + return BAD_FUNC_ARG; + + qSz = mp_unsigned_bin_size(&dsa->q); + pSz = mp_unsigned_bin_size(&dsa->p); + + /* verify (L,N) pair bit lengths */ + if (CheckDsaLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0) + return BAD_FUNC_ARG; + + /* generate extra 64 bits so that bias from mod function is negligible */ + cSz = qSz + (64 / WOLFSSL_BIT_SIZE); + cBuf = (byte*)XMALLOC(cSz, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cBuf == NULL) { + return MEMORY_E; + } + + if ((err = mp_init_multi(&dsa->x, &dsa->y, &tmpQ, NULL, NULL, NULL)) + != MP_OKAY) { + XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + + do { + /* generate N+64 bits (c) from RBG into &dsa->x, making sure positive. + * Hash_DRBG uses SHA-256 which matches maximum + * requested_security_strength of (L,N) */ + err = wc_RNG_GenerateBlock(rng, cBuf, cSz); + if (err != MP_OKAY) { + mp_clear(&dsa->x); + mp_clear(&dsa->y); + mp_clear(&tmpQ); + XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + + err = mp_read_unsigned_bin(&dsa->x, cBuf, cSz); + if (err != MP_OKAY) { + mp_clear(&dsa->x); + mp_clear(&dsa->y); + mp_clear(&tmpQ); + XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + } while (mp_cmp_d(&dsa->x, 1) != MP_GT); + + XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + + /* tmpQ = q - 1 */ + if (err == MP_OKAY) + err = mp_copy(&dsa->q, &tmpQ); + + if (err == MP_OKAY) + err = mp_sub_d(&tmpQ, 1, &tmpQ); + + /* x = c mod (q-1), &dsa->x holds c */ + if (err == MP_OKAY) + err = mp_mod(&dsa->x, &tmpQ, &dsa->x); + + /* x = c mod (q-1) + 1 */ + if (err == MP_OKAY) + err = mp_add_d(&dsa->x, 1, &dsa->x); + + /* public key : y = g^x mod p */ + if (err == MP_OKAY) + err = mp_exptmod_ex(&dsa->g, &dsa->x, dsa->q.used, &dsa->p, &dsa->y); + + if (err == MP_OKAY) + dsa->type = DSA_PRIVATE; + + if (err != MP_OKAY) { + mp_clear(&dsa->x); + mp_clear(&dsa->y); + } + mp_clear(&tmpQ); + + return err; +} + + +/* modulus_size in bits */ +int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa) +{ + mp_int tmp, tmp2; + int err, msize, qsize, + loop_check_prime = 0, + check_prime = MP_NO; + unsigned char *buf; + + if (rng == NULL || dsa == NULL) + return BAD_FUNC_ARG; + + /* set group size in bytes from modulus size + * FIPS 186-4 defines valid values (1024, 160) (2048, 256) (3072, 256) + */ + switch (modulus_size) { + case 1024: + qsize = 20; + break; + case 2048: + case 3072: + qsize = 32; + break; + default: + return BAD_FUNC_ARG; + } + + /* modulus size in bytes */ + msize = modulus_size / WOLFSSL_BIT_SIZE; + + /* allocate ram */ + buf = (unsigned char *)XMALLOC(msize - qsize, + dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + return MEMORY_E; + } + + /* make a random string that will be multiplied against q */ + err = wc_RNG_GenerateBlock(rng, buf, msize - qsize); + if (err != MP_OKAY) { + XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + + /* force magnitude */ + buf[0] |= 0xC0; + + /* force even */ + buf[msize - qsize - 1] &= ~1; + + if (mp_init_multi(&tmp2, &dsa->p, &dsa->q, 0, 0, 0) != MP_OKAY) { + mp_clear(&dsa->q); + XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); return MP_INIT_E; + } - if (mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY) - ret = MP_READ_E; + err = mp_read_unsigned_bin(&tmp2, buf, msize - qsize); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp2); + XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (ret == 0 && mp_cmp_d(&k, 1) != MP_GT) - ret = MP_CMP_E; + /* make our prime q */ + err = mp_rand_prime(&dsa->q, qsize, rng, NULL); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp2); + return err; + } + /* p = random * q */ + err = mp_mul(&dsa->q, &tmp2, &dsa->p); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp2); + return err; + } + + /* p = random * q + 1, so q is a prime divisor of p-1 */ + err = mp_add_d(&dsa->p, 1, &dsa->p); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp2); + return err; + } + + if (mp_init(&tmp) != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp2); + return MP_INIT_E; + } + + /* tmp = 2q */ + err = mp_add(&dsa->q, &dsa->q, &tmp); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return err; + } + + /* loop until p is prime */ + while (check_prime == MP_NO) { + err = mp_prime_is_prime_ex(&dsa->p, 8, &check_prime, rng); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return err; + } + + if (check_prime != MP_YES) { + /* p += 2q */ + err = mp_add(&tmp, &dsa->p, &dsa->p); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return err; + } + + loop_check_prime++; + } + } + + /* tmp2 += (2*loop_check_prime) + * to have p = (q * tmp2) + 1 prime + */ + if (loop_check_prime) { + err = mp_add_d(&tmp2, 2*loop_check_prime, &tmp2); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return err; + } + } + + if (mp_init(&dsa->g) != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return MP_INIT_E; + } + + /* find a value g for which g^tmp2 != 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); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&dsa->g); + mp_clear(&tmp); + mp_clear(&tmp2); + return err; + } + + err = mp_exptmod(&dsa->g, &tmp2, &dsa->p, &tmp); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&dsa->g); + mp_clear(&tmp); + mp_clear(&tmp2); + return err; + } + + } while (mp_cmp_d(&tmp, 1) == MP_EQ); + + /* at this point tmp generates a group of order q mod p */ + mp_exch(&tmp, &dsa->g); + + mp_clear(&tmp); + mp_clear(&tmp2); + + return MP_OKAY; +} +#endif /* WOLFSSL_KEY_GEN */ + + +static int _DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q, + const char* g, int trusted, WC_RNG* rng) +{ + int err; + word32 pSz, qSz; + + if (dsa == NULL || p == NULL || q == NULL || g == NULL) + return BAD_FUNC_ARG; + + /* read p */ + err = mp_read_radix(&dsa->p, p, MP_RADIX_HEX); + if (err == MP_OKAY && !trusted) { + int isPrime = 1; + if (rng == NULL) + err = mp_prime_is_prime(&dsa->p, 8, &isPrime); + else + err = mp_prime_is_prime_ex(&dsa->p, 8, &isPrime, rng); + + if (err == MP_OKAY) { + if (!isPrime) + err = DH_CHECK_PUB_E; + } + } + + /* read q */ + if (err == MP_OKAY) + err = mp_read_radix(&dsa->q, q, MP_RADIX_HEX); + + /* read g */ + if (err == MP_OKAY) + err = mp_read_radix(&dsa->g, g, MP_RADIX_HEX); + + /* verify (L,N) pair bit lengths */ + pSz = mp_unsigned_bin_size(&dsa->p); + qSz = mp_unsigned_bin_size(&dsa->q); + + if (CheckDsaLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0) { + WOLFSSL_MSG("Invalid DSA p or q parameter size"); + err = BAD_FUNC_ARG; + } + + if (err != MP_OKAY) { + mp_clear(&dsa->p); + mp_clear(&dsa->q); + mp_clear(&dsa->g); + } + + return err; +} + + +/* Import raw DSA parameters into DsaKey structure for use with wc_MakeDsaKey(), + * input parameters (p,q,g) should be represented as ASCII hex values. + * + * dsa - pointer to initialized DsaKey structure + * p - DSA (p) parameter, ASCII hex string + * pSz - length of p + * q - DSA (q) parameter, ASCII hex string + * qSz - length of q + * g - DSA (g) parameter, ASCII hex string + * gSz - length of g + * + * returns 0 on success, negative upon failure + */ +int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q, + const char* g) +{ + return _DsaImportParamsRaw(dsa, p, q, g, 1, NULL); +} + + +/* Import raw DSA parameters into DsaKey structure for use with wc_MakeDsaKey(), + * input parameters (p,q,g) should be represented as ASCII hex values. Check + * that the p value is probably prime. + * + * dsa - pointer to initialized DsaKey structure + * p - DSA (p) parameter, ASCII hex string + * pSz - length of p + * q - DSA (q) parameter, ASCII hex string + * qSz - length of q + * g - DSA (g) parameter, ASCII hex string + * gSz - length of g + * trusted - trust that p is OK + * rng - random number generator for the prime test + * + * returns 0 on success, negative upon failure + */ +int wc_DsaImportParamsRawCheck(DsaKey* dsa, const char* p, const char* q, + const char* g, int trusted, WC_RNG* rng) +{ + return _DsaImportParamsRaw(dsa, p, q, g, trusted, rng); +} + + +/* Export raw DSA parameters from DsaKey structure + * + * dsa - pointer to initialized DsaKey structure + * p - output location for DSA (p) parameter + * pSz - [IN/OUT] size of output buffer for p, size of p + * q - output location for DSA (q) parameter + * qSz - [IN/OUT] size of output buffer for q, size of q + * g - output location for DSA (g) parameter + * gSz - [IN/OUT] size of output buffer for g, size of g + * + * If p, q, and g pointers are all passed in as NULL, the function + * will set pSz, qSz, and gSz to the required output buffer sizes for p, + * q, and g. In this case, the function will return LENGTH_ONLY_E. + * + * returns 0 on success, negative upon failure + */ +int wc_DsaExportParamsRaw(DsaKey* dsa, byte* p, word32* pSz, + byte* q, word32* qSz, byte* g, word32* gSz) +{ + int err; + word32 pLen, qLen, gLen; + + if (dsa == NULL || pSz == NULL || qSz == NULL || gSz == NULL) + return BAD_FUNC_ARG; + + /* get required output buffer sizes */ + pLen = mp_unsigned_bin_size(&dsa->p); + qLen = mp_unsigned_bin_size(&dsa->q); + gLen = mp_unsigned_bin_size(&dsa->g); + + /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */ + if (p == NULL && q == NULL && g == NULL) { + *pSz = pLen; + *qSz = qLen; + *gSz = gLen; + return LENGTH_ONLY_E; + } + + if (p == NULL || q == NULL || g == NULL) + return BAD_FUNC_ARG; + + /* export p */ + if (*pSz < pLen) { + WOLFSSL_MSG("Output buffer for DSA p parameter too small, " + "required size placed into pSz"); + *pSz = pLen; + return BUFFER_E; + } + *pSz = pLen; + err = mp_to_unsigned_bin(&dsa->p, p); + + /* export q */ + if (err == MP_OKAY) { + if (*qSz < qLen) { + WOLFSSL_MSG("Output buffer for DSA q parameter too small, " + "required size placed into qSz"); + *qSz = qLen; + return BUFFER_E; + } + *qSz = qLen; + err = mp_to_unsigned_bin(&dsa->q, q); + } + + /* export g */ + if (err == MP_OKAY) { + if (*gSz < gLen) { + WOLFSSL_MSG("Output buffer for DSA g parameter too small, " + "required size placed into gSz"); + *gSz = gLen; + return BUFFER_E; + } + *gSz = gLen; + err = mp_to_unsigned_bin(&dsa->g, g); + } + + return err; +} + + +/* Export raw DSA key (x, y) from DsaKey structure + * + * dsa - pointer to initialized DsaKey structure + * x - output location for private key + * xSz - [IN/OUT] size of output buffer for x, size of x + * y - output location for public key + * ySz - [IN/OUT] size of output buffer for y, size of y + * + * If x and y pointers are all passed in as NULL, the function + * will set xSz and ySz to the required output buffer sizes for x + * and y. In this case, the function will return LENGTH_ONLY_E. + * + * returns 0 on success, negative upon failure + */ +int wc_DsaExportKeyRaw(DsaKey* dsa, byte* x, word32* xSz, byte* y, word32* ySz) +{ + int err; + word32 xLen, yLen; + + if (dsa == NULL || xSz == NULL || ySz == NULL) + return BAD_FUNC_ARG; + + /* get required output buffer sizes */ + xLen = mp_unsigned_bin_size(&dsa->x); + yLen = mp_unsigned_bin_size(&dsa->y); + + /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */ + if (x == NULL && y == NULL) { + *xSz = xLen; + *ySz = yLen; + return LENGTH_ONLY_E; + } + + if (x == NULL || y == NULL) + return BAD_FUNC_ARG; + + /* export x */ + if (*xSz < xLen) { + WOLFSSL_MSG("Output buffer for DSA private key (x) too small, " + "required size placed into xSz"); + *xSz = xLen; + return BUFFER_E; + } + *xSz = xLen; + err = mp_to_unsigned_bin(&dsa->x, x); + + /* export y */ + if (err == MP_OKAY) { + if (*ySz < yLen) { + WOLFSSL_MSG("Output buffer to DSA public key (y) too small, " + "required size placed into ySz"); + *ySz = yLen; + return BUFFER_E; + } + *ySz = yLen; + err = mp_to_unsigned_bin(&dsa->y, y); + } + + return err; +} + + +int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) +{ + mp_int k, kInv, r, s, H; +#ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME + mp_int b; +#endif + mp_int* qMinus1; + int ret = 0, sz; + byte buffer[DSA_HALF_SIZE]; + 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)); + +#ifdef WOLFSSL_MP_INVMOD_CONSTANT_TIME + if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY) +#else + if (mp_init_multi(&k, &kInv, &r, &s, &H, &b) != MP_OKAY) +#endif + { + return MP_INIT_E; + } + qMinus1 = &kInv; + + /* NIST FIPS 186-4: B.2.2 + * Per-Message Secret Number Generation by Testing Candidates + * Generate k in range [1, q-1]. + * Check that k is less than q-1: range [0, q-2]. + * Add 1 to k: range [1, q-1]. + */ + if (mp_sub_d(&key->q, 1, qMinus1)) + ret = MP_SUB_E; + + if (ret == 0) { + do { + /* Step 4: generate k */ + ret = wc_RNG_GenerateBlock(rng, buffer, sz); + + /* Step 5 */ + if (ret == 0 && 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-1 + * if k greater than repeat + */ + /* Step 6 */ + } while (ret == 0 && mp_cmp(&k, qMinus1) != MP_LT); + } + /* Step 7 */ + if (ret == 0 && mp_add_d(&k, 1, &k) != MP_OKAY) + ret = MP_MOD_E; + +#ifdef WOLFSSL_MP_INVMOD_CONSTANT_TIME /* inverse k mod q */ if (ret == 0 && mp_invmod(&k, &key->q, &kInv) != MP_OKAY) ret = MP_INVMOD_E; /* generate r, r = (g exp k mod p) mod q */ - if (ret == 0 && mp_exptmod(&key->g, &k, &key->p, &r) != MP_OKAY) + if (ret == 0 && mp_exptmod_ex(&key->g, &k, key->q.used, &key->p, + &r) != MP_OKAY) { ret = MP_EXPTMOD_E; + } if (ret == 0 && mp_mod(&r, &key->q, &r) != MP_OKAY) 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 */ @@ -129,28 +736,105 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, RNG* rng) if (ret == 0 && mp_mulmod(&s, &kInv, &key->q, &s) != MP_OKAY) ret = MP_MULMOD_E; +#else + /* Blinding value + * Generate b in range [1, q-1]. + */ + if (ret == 0) { + do { + ret = wc_RNG_GenerateBlock(rng, buffer, sz); + if (ret == 0 && mp_read_unsigned_bin(&b, buffer, sz) != MP_OKAY) + ret = MP_READ_E; + } while (ret == 0 && mp_cmp(&b, qMinus1) != MP_LT); + } + if (ret == 0 && mp_add_d(&b, 1, &b) != MP_OKAY) + ret = MP_MOD_E; + + /* set H from sha digest */ + if (ret == 0 && mp_read_unsigned_bin(&H, digest, + WC_SHA_DIGEST_SIZE) != MP_OKAY) { + ret = MP_READ_E; + } + + /* generate r, r = (g exp k mod p) mod q */ + if (ret == 0 && mp_exptmod_ex(&key->g, &k, key->q.used, &key->p, + &r) != MP_OKAY) { + ret = MP_EXPTMOD_E; + } + + /* calculate s = (H + xr)/k + = b.(H/k.b + x.r/k.b) */ + + /* k = k.b */ + if (ret == 0 && mp_mulmod(&k, &b, &key->q, &k) != MP_OKAY) + ret = MP_MULMOD_E; + + /* kInv = 1/k.b mod q */ + if (ret == 0 && mp_invmod(&k, &key->q, &kInv) != MP_OKAY) + ret = MP_INVMOD_E; + + if (ret == 0 && mp_mod(&r, &key->q, &r) != MP_OKAY) + ret = MP_MOD_E; + + /* s = x.r */ + if (ret == 0 && mp_mul(&key->x, &r, &s) != MP_OKAY) + ret = MP_MUL_E; + + /* s = x.r/k.b */ + if (ret == 0 && mp_mulmod(&s, &kInv, &key->q, &s) != MP_OKAY) + ret = MP_MULMOD_E; + + /* H = H/k.b */ + if (ret == 0 && mp_mulmod(&H, &kInv, &key->q, &H) != MP_OKAY) + ret = MP_MULMOD_E; + + /* s = H/k.b + x.r/k.b + = (H + x.r)/k.b */ + if (ret == 0 && mp_add(&s, &H, &s) != MP_OKAY) + ret = MP_ADD_E; + + /* s = b.(e + x.r)/k.b + = (e + x.r)/k */ + if (ret == 0 && mp_mulmod(&s, &b, &key->q, &s) != MP_OKAY) + ret = MP_MULMOD_E; + + /* s = (e + x.r)/k */ + if (ret == 0 && mp_mod(&s, &key->q, &s) != MP_OKAY) + ret = MP_MOD_E; +#endif + + /* detect zero r or s */ + if (ret == 0 && (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES)) + ret = MP_ZERO_E; /* write out */ if (ret == 0) { int rSz = mp_unsigned_bin_size(&r); int sSz = mp_unsigned_bin_size(&s); - if (rSz == DSA_HALF_SIZE - 1) { - out[0] = 0; - out++; + while (rSz++ < DSA_HALF_SIZE) { + *out++ = 0x00; /* pad front with zeros */ } if (mp_to_unsigned_bin(&r, out) != MP_OKAY) ret = MP_TO_E; else { - if (sSz == DSA_HALF_SIZE - 1) { - out[rSz] = 0; - out++; - } - ret = mp_to_unsigned_bin(&s, out + rSz); + out = tmp + DSA_HALF_SIZE; /* advance to s in output */ + while (sSz++ < DSA_HALF_SIZE) { + *out++ = 0x00; /* pad front with zeros */ + } + ret = mp_to_unsigned_bin(&s, out); } } + ForceZero(buffer, sz); + mp_forcezero(&kInv); + mp_forcezero(&k); +#ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME + mp_forcezero(&b); + + mp_clear(&b); +#endif mp_clear(&H); mp_clear(&s); mp_clear(&r); @@ -166,6 +850,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; @@ -183,7 +871,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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ecc.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ecc.c index 897d46adf..22db7f167 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ecc.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ecc.c @@ -1,8 +1,8 @@ /* ecc.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -27,31 +28,149 @@ /* in case user set HAVE_ECC there */ #include +/* public ASN interface */ +#include + +/* +Possible ECC enable options: + * HAVE_ECC: Overall control of ECC default: on + * HAVE_ECC_ENCRYPT: ECC encrypt/decrypt w/AES and HKDF default: off + * 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 + * HAVE_COMP_KEY: Enables compressed key default: off + * WOLFSSL_VALIDATE_ECC_IMPORT: Validate ECC key on import default: off + * WOLFSSL_VALIDATE_ECC_KEYGEN: Validate ECC key gen default: off + * WOLFSSL_CUSTOM_CURVES: Allow non-standard curves. default: off + * Includes the curve "a" variable in calculation + * ECC_DUMP_OID: Enables dump of OID encoding and sum default: off + * ECC_CACHE_CURVE: Enables cache of curve info to improve perofrmance + default: off + * FP_ECC: ECC Fixed Point Cache default: off + * USE_ECC_B_PARAM: Enable ECC curve B param default: off + (on for HAVE_COMP_KEY) + * WOLFSSL_ECC_CURVE_STATIC: default off (on for windows) + For the ECC curve paramaters `ecc_set_type` use fixed + array for hex string + */ + +/* +ECC Curve Types: + * NO_ECC_SECP Disables SECP curves default: off (not defined) + * HAVE_ECC_SECPR2 Enables SECP R2 curves default: off + * HAVE_ECC_SECPR3 Enables SECP R3 curves default: off + * HAVE_ECC_BRAINPOOL Enables Brainpool curves default: off + * HAVE_ECC_KOBLITZ Enables Koblitz curves default: off + */ + +/* +ECC Curve Sizes: + * ECC_USER_CURVES: Allows custom combination of key sizes below + * HAVE_ALL_CURVES: Enable all key sizes (on unless ECC_USER_CURVES is defined) + * HAVE_ECC112: 112 bit key + * HAVE_ECC128: 128 bit key + * HAVE_ECC160: 160 bit key + * HAVE_ECC192: 192 bit key + * HAVE_ECC224: 224 bit key + * HAVE_ECC239: 239 bit key + * NO_ECC256: Disables 256 bit key (on by default) + * HAVE_ECC320: 320 bit key + * HAVE_ECC384: 384 bit key + * HAVE_ECC512: 512 bit key + * HAVE_ECC521: 521 bit key + */ + + #ifdef HAVE_ECC +/* Make sure custom curves is enabled for Brainpool or Koblitz curve types */ +#if (defined(HAVE_ECC_BRAINPOOL) || defined(HAVE_ECC_KOBLITZ)) &&\ + !defined(WOLFSSL_CUSTOM_CURVES) + #error Brainpool and Koblitz curves requires WOLFSSL_CUSTOM_CURVES +#endif + +#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$f") + #pragma const_seg(".fipsB$f") + #endif +#endif + #include #include #include +#include +#include + +#ifdef WOLFSSL_HAVE_SP_ECC +#include +#endif #ifdef HAVE_ECC_ENCRYPT #include #include #endif +#ifdef HAVE_X963_KDF + #include +#endif + +#ifdef WOLF_CRYPTO_CB + #include +#endif + #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif +#if defined(FREESCALE_LTC_ECC) + #include +#endif + +#if defined(WOLFSSL_STM32_PKA) + #include +#endif + +#ifdef WOLFSSL_SP_MATH + #define GEN_MEM_ERR MP_MEM +#elif defined(USE_FAST_MATH) + #define GEN_MEM_ERR FP_MEM +#else + #define GEN_MEM_ERR MP_MEM +#endif + + +/* internal ECC states */ +enum { + ECC_STATE_NONE = 0, + + ECC_STATE_SHARED_SEC_GEN, + ECC_STATE_SHARED_SEC_RES, + + ECC_STATE_SIGN_DO, + ECC_STATE_SIGN_ENCODE, + + ECC_STATE_VERIFY_DECODE, + ECC_STATE_VERIFY_DO, + ECC_STATE_VERIFY_RES, +}; + + /* map - ptmul -> mulmod - */ - -/* p256 curve on by default whether user curves or not */ +/* 256-bit curve on by default whether user curves or not */ #if defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES) #define ECC112 #endif @@ -67,939 +186,2334 @@ #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) #define ECC224 #endif +#if defined(HAVE_ECC239) || defined(HAVE_ALL_CURVES) + #define ECC239 +#endif #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) #define ECC256 #endif +#if defined(HAVE_ECC320) || defined(HAVE_ALL_CURVES) + #define ECC320 +#endif #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) #define ECC384 #endif +#if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + #define ECC512 +#endif #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) #define ECC521 #endif +/* The encoded OID's for ECC curves */ +#ifdef ECC112 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP112R1 {1,3,132,0,6} + #define CODED_SECP112R1_SZ 5 + #else + #define CODED_SECP112R1 {0x2B,0x81,0x04,0x00,0x06} + #define CODED_SECP112R1_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp112r1[] = CODED_SECP112R1; + #else + #define ecc_oid_secp112r1 CODED_SECP112R1 + #endif + #define ecc_oid_secp112r1_sz CODED_SECP112R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + #ifdef HAVE_OID_ENCODING + #define CODED_SECP112R2 {1,3,132,0,7} + #define CODED_SECP112R2_SZ 5 + #else + #define CODED_SECP112R2 {0x2B,0x81,0x04,0x00,0x07} + #define CODED_SECP112R2_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp112r2[] = CODED_SECP112R2; + #else + #define ecc_oid_secp112r2 CODED_SECP112R2 + #endif + #define ecc_oid_secp112r2_sz CODED_SECP112R2_SZ + #endif /* HAVE_ECC_SECPR2 */ +#endif /* ECC112 */ +#ifdef ECC128 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP128R1 {1,3,132,0,28} + #define CODED_SECP128R1_SZ 5 + #else + #define CODED_SECP128R1 {0x2B,0x81,0x04,0x00,0x1C} + #define CODED_SECP128R1_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp128r1[] = CODED_SECP128R1; + #else + #define ecc_oid_secp128r1 CODED_SECP128R1 + #endif + #define ecc_oid_secp128r1_sz CODED_SECP128R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + #ifdef HAVE_OID_ENCODING + #define CODED_SECP128R2 {1,3,132,0,29} + #define CODED_SECP128R2_SZ 5 + #else + #define CODED_SECP128R2 {0x2B,0x81,0x04,0x00,0x1D} + #define CODED_SECP128R2_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp128r2[] = CODED_SECP128R2; + #else + #define ecc_oid_secp128r2 CODED_SECP128R2 + #endif + #define ecc_oid_secp128r2_sz CODED_SECP128R2_SZ + #endif /* HAVE_ECC_SECPR2 */ +#endif /* ECC128 */ +#ifdef ECC160 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP160R1 {1,3,132,0,8} + #define CODED_SECP160R1_SZ 5 + #else + #define CODED_SECP160R1 {0x2B,0x81,0x04,0x00,0x08} + #define CODED_SECP160R1_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp160r1[] = CODED_SECP160R1; + #else + #define ecc_oid_secp160r1 CODED_SECP160R1 + #endif + #define ecc_oid_secp160r1_sz CODED_SECP160R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + #ifdef HAVE_OID_ENCODING + #define CODED_SECP160R2 {1,3,132,0,30} + #define CODED_SECP160R2_SZ 5 + #else + #define CODED_SECP160R2 {0x2B,0x81,0x04,0x00,0x1E} + #define CODED_SECP160R2_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp160r2[] = CODED_SECP160R2; + #else + #define ecc_oid_secp160r2 CODED_SECP160R2 + #endif + #define ecc_oid_secp160r2_sz CODED_SECP160R2_SZ + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_KOBLITZ + #ifdef HAVE_OID_ENCODING + #define CODED_SECP160K1 {1,3,132,0,9} + #define CODED_SECP160K1_SZ 5 + #else + #define CODED_SECP160K1 {0x2B,0x81,0x04,0x00,0x09} + #define CODED_SECP160K1_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp160k1[] = CODED_SECP160K1; + #else + #define ecc_oid_secp160k1 CODED_SECP160K1 + #endif + #define ecc_oid_secp160k1_sz CODED_SECP160K1_SZ + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP160R1 {1,3,36,3,3,2,8,1,1,1} + #define CODED_BRAINPOOLP160R1_SZ 10 + #else + #define CODED_BRAINPOOLP160R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x01} + #define CODED_BRAINPOOLP160R1_SZ 9 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_brainpoolp160r1[] = CODED_BRAINPOOLP160R1; + #else + #define ecc_oid_brainpoolp160r1 CODED_BRAINPOOLP160R1 + #endif + #define ecc_oid_brainpoolp160r1_sz CODED_BRAINPOOLP160R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC160 */ +#ifdef ECC192 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP192R1 {1,2,840,10045,3,1,1} + #define CODED_SECP192R1_SZ 7 + #else + #define CODED_SECP192R1 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x01} + #define CODED_SECP192R1_SZ 8 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp192r1[] = CODED_SECP192R1; + #else + #define ecc_oid_secp192r1 CODED_SECP192R1 + #endif + #define ecc_oid_secp192r1_sz CODED_SECP192R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + #ifdef HAVE_OID_ENCODING + #define CODED_PRIME192V2 {1,2,840,10045,3,1,2} + #define CODED_PRIME192V2_SZ 7 + #else + #define CODED_PRIME192V2 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x02} + #define CODED_PRIME192V2_SZ 8 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_prime192v2[] = CODED_PRIME192V2; + #else + #define ecc_oid_prime192v2 CODED_PRIME192V2 + #endif + #define ecc_oid_prime192v2_sz CODED_PRIME192V2_SZ + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_SECPR3 + #ifdef HAVE_OID_ENCODING + #define CODED_PRIME192V3 {1,2,840,10045,3,1,3} + #define CODED_PRIME192V3_SZ 7 + #else + #define CODED_PRIME192V3 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x03} + #define CODED_PRIME192V3_SZ 8 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_prime192v3[] = CODED_PRIME192V3; + #else + #define ecc_oid_prime192v3 CODED_PRIME192V3 + #endif + #define ecc_oid_prime192v3_sz CODED_PRIME192V3_SZ + #endif /* HAVE_ECC_SECPR3 */ + #ifdef HAVE_ECC_KOBLITZ + #ifdef HAVE_OID_ENCODING + #define CODED_SECP192K1 {1,3,132,0,31} + #define CODED_SECP192K1_SZ 5 + #else + #define CODED_SECP192K1 {0x2B,0x81,0x04,0x00,0x1F} + #define CODED_SECP192K1_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp192k1[] = CODED_SECP192K1; + #else + #define ecc_oid_secp192k1 CODED_SECP192K1 + #endif + #define ecc_oid_secp192k1_sz CODED_SECP192K1_SZ + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP192R1 {1,3,36,3,3,2,8,1,1,3} + #define CODED_BRAINPOOLP192R1_SZ 10 + #else + #define CODED_BRAINPOOLP192R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x03} + #define CODED_BRAINPOOLP192R1_SZ 9 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_brainpoolp192r1[] = CODED_BRAINPOOLP192R1; + #else + #define ecc_oid_brainpoolp192r1 CODED_BRAINPOOLP192R1 + #endif + #define ecc_oid_brainpoolp192r1_sz CODED_BRAINPOOLP192R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC192 */ +#ifdef ECC224 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP224R1 {1,3,132,0,33} + #define CODED_SECP224R1_SZ 5 + #else + #define CODED_SECP224R1 {0x2B,0x81,0x04,0x00,0x21} + #define CODED_SECP224R1_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp224r1[] = CODED_SECP224R1; + #else + #define ecc_oid_secp224r1 CODED_SECP224R1 + #endif + #define ecc_oid_secp224r1_sz CODED_SECP224R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + #ifdef HAVE_OID_ENCODING + #define CODED_SECP224K1 {1,3,132,0,32} + #define CODED_SECP224K1_SZ 5 + #else + #define CODED_SECP224K1 {0x2B,0x81,0x04,0x00,0x20} + #define CODED_SECP224K1_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp224k1[] = CODED_SECP224K1; + #else + #define ecc_oid_secp224k1 CODED_SECP224K1 + #endif + #define ecc_oid_secp224k1_sz CODED_SECP224K1_SZ + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP224R1 {1,3,36,3,3,2,8,1,1,5} + #define CODED_BRAINPOOLP224R1_SZ 10 + #else + #define CODED_BRAINPOOLP224R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x05} + #define CODED_BRAINPOOLP224R1_SZ 9 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_brainpoolp224r1[] = CODED_BRAINPOOLP224R1; + #else + #define ecc_oid_brainpoolp224r1 CODED_BRAINPOOLP224R1 + #endif + #define ecc_oid_brainpoolp224r1_sz CODED_BRAINPOOLP224R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC224 */ +#ifdef ECC239 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_PRIME239V1 {1,2,840,10045,3,1,4} + #define CODED_PRIME239V1_SZ 7 + #else + #define CODED_PRIME239V1 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x04} + #define CODED_PRIME239V1_SZ 8 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_prime239v1[] = CODED_PRIME239V1; + #else + #define ecc_oid_prime239v1 CODED_PRIME239V1 + #endif + #define ecc_oid_prime239v1_sz CODED_PRIME239V1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + #ifdef HAVE_OID_ENCODING + #define CODED_PRIME239V2 {1,2,840,10045,3,1,5} + #define CODED_PRIME239V2_SZ 7 + #else + #define CODED_PRIME239V2 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x05} + #define CODED_PRIME239V2_SZ 8 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_prime239v2[] = CODED_PRIME239V2; + #else + #define ecc_oid_prime239v2 CODED_PRIME239V2 + #endif + #define ecc_oid_prime239v2_sz CODED_PRIME239V2_SZ + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_SECPR3 + #ifdef HAVE_OID_ENCODING + #define CODED_PRIME239V3 {1,2,840,10045,3,1,6} + #define CODED_PRIME239V3_SZ 7 + #else + #define CODED_PRIME239V3 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x06} + #define CODED_PRIME239V3_SZ 8 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_prime239v3[] = CODED_PRIME239V3; + #else + #define ecc_oid_prime239v3 CODED_PRIME239V3 + #endif + #define ecc_oid_prime239v3_sz CODED_PRIME239V3_SZ + #endif /* HAVE_ECC_SECPR3 */ +#endif /* ECC239 */ +#ifdef ECC256 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP256R1 {1,2,840,10045,3,1,7} + #define CODED_SECP256R1_SZ 7 + #else + #define CODED_SECP256R1 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07} + #define CODED_SECP256R1_SZ 8 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp256r1[] = CODED_SECP256R1; + #else + #define ecc_oid_secp256r1 CODED_SECP256R1 + #endif + #define ecc_oid_secp256r1_sz CODED_SECP256R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + #ifdef HAVE_OID_ENCODING + #define CODED_SECP256K1 {1,3,132,0,10} + #define CODED_SECP256K1_SZ 5 + #else + #define CODED_SECP256K1 {0x2B,0x81,0x04,0x00,0x0A} + #define CODED_SECP256K1_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp256k1[] = CODED_SECP256K1; + #else + #define ecc_oid_secp256k1 CODED_SECP256K1 + #endif + #define ecc_oid_secp256k1_sz CODED_SECP256K1_SZ + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP256R1 {1,3,36,3,3,2,8,1,1,7} + #define CODED_BRAINPOOLP256R1_SZ 10 + #else + #define CODED_BRAINPOOLP256R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07} + #define CODED_BRAINPOOLP256R1_SZ 9 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_brainpoolp256r1[] = CODED_BRAINPOOLP256R1; + #else + #define ecc_oid_brainpoolp256r1 CODED_BRAINPOOLP256R1 + #endif + #define ecc_oid_brainpoolp256r1_sz CODED_BRAINPOOLP256R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC256 */ +#ifdef ECC320 + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP320R1 {1,3,36,3,3,2,8,1,1,9} + #define CODED_BRAINPOOLP320R1_SZ 10 + #else + #define CODED_BRAINPOOLP320R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x09} + #define CODED_BRAINPOOLP320R1_SZ 9 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_brainpoolp320r1[] = CODED_BRAINPOOLP320R1; + #else + #define ecc_oid_brainpoolp320r1 CODED_BRAINPOOLP320R1 + #endif + #define ecc_oid_brainpoolp320r1_sz CODED_BRAINPOOLP320R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC320 */ +#ifdef ECC384 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP384R1 {1,3,132,0,34} + #define CODED_SECP384R1_SZ 5 + #else + #define CODED_SECP384R1 {0x2B,0x81,0x04,0x00,0x22} + #define CODED_SECP384R1_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp384r1[] = CODED_SECP384R1; + #define CODED_SECP384R1_OID ecc_oid_secp384r1 + #else + #define ecc_oid_secp384r1 CODED_SECP384R1 + #endif + #define ecc_oid_secp384r1_sz CODED_SECP384R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP384R1 {1,3,36,3,3,2,8,1,1,11} + #define CODED_BRAINPOOLP384R1_SZ 10 + #else + #define CODED_BRAINPOOLP384R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0B} + #define CODED_BRAINPOOLP384R1_SZ 9 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_brainpoolp384r1[] = CODED_BRAINPOOLP384R1; + #else + #define ecc_oid_brainpoolp384r1 CODED_BRAINPOOLP384R1 + #endif + #define ecc_oid_brainpoolp384r1_sz CODED_BRAINPOOLP384R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC384 */ +#ifdef ECC512 + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP512R1 {1,3,36,3,3,2,8,1,1,13} + #define CODED_BRAINPOOLP512R1_SZ 10 + #else + #define CODED_BRAINPOOLP512R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0D} + #define CODED_BRAINPOOLP512R1_SZ 9 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_brainpoolp512r1[] = CODED_BRAINPOOLP512R1; + #else + #define ecc_oid_brainpoolp512r1 CODED_BRAINPOOLP512R1 + #endif + #define ecc_oid_brainpoolp512r1_sz CODED_BRAINPOOLP512R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC512 */ +#ifdef ECC521 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP521R1 {1,3,132,0,35} + #define CODED_SECP521R1_SZ 5 + #else + #define CODED_SECP521R1 {0x2B,0x81,0x04,0x00,0x23} + #define CODED_SECP521R1_SZ 5 + #endif + #ifndef WOLFSSL_ECC_CURVE_STATIC + static const ecc_oid_t ecc_oid_secp521r1[] = CODED_SECP521R1; + #else + #define ecc_oid_secp521r1 CODED_SECP521R1 + #endif + #define ecc_oid_secp521r1_sz CODED_SECP521R1_SZ + #endif /* !NO_ECC_SECP */ +#endif /* ECC521 */ -/* This holds the key settings. ***MUST*** be organized by size from - smallest to largest. */ +/* This holds the key settings. + ***MUST*** be organized by size from smallest to largest. */ const ecc_set_type ecc_sets[] = { #ifdef ECC112 -{ - 14, - "SECP112R1", - "DB7C2ABF62E35E668076BEAD208B", - "DB7C2ABF62E35E668076BEAD2088", - "659EF8BA043916EEDE8911702B22", - "DB7C2ABF62E35E7628DFAC6561C5", - "09487239995A5EE76B55F9C2F098", - "A89CE5AF8724C0A23E0E0FF77500" -}, -#endif + #ifndef NO_ECC_SECP + { + 14, /* size/bytes */ + ECC_SECP112R1, /* ID */ + "SECP112R1", /* curve name */ + "DB7C2ABF62E35E668076BEAD208B", /* prime */ + "DB7C2ABF62E35E668076BEAD2088", /* A */ + "659EF8BA043916EEDE8911702B22", /* B */ + "DB7C2ABF62E35E7628DFAC6561C5", /* order */ + "9487239995A5EE76B55F9C2F098", /* Gx */ + "A89CE5AF8724C0A23E0E0FF77500", /* Gy */ + ecc_oid_secp112r1, /* oid/oidSz */ + ecc_oid_secp112r1_sz, + ECC_SECP112R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + { + 14, /* size/bytes */ + ECC_SECP112R2, /* ID */ + "SECP112R2", /* curve name */ + "DB7C2ABF62E35E668076BEAD208B", /* prime */ + "6127C24C05F38A0AAAF65C0EF02C", /* A */ + "51DEF1815DB5ED74FCC34C85D709", /* B */ + "36DF0AAFD8B8D7597CA10520D04B", /* order */ + "4BA30AB5E892B4E1649DD0928643", /* Gx */ + "ADCD46F5882E3747DEF36E956E97", /* Gy */ + ecc_oid_secp112r2, /* oid/oidSz */ + ecc_oid_secp112r2_sz, + ECC_SECP112R2_OID, /* oid sum */ + 4, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR2 */ +#endif /* ECC112 */ #ifdef ECC128 -{ - 16, - "SECP128R1", - "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", - "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", - "E87579C11079F43DD824993C2CEE5ED3", - "FFFFFFFE0000000075A30D1B9038A115", - "161FF7528B899B2D0C28607CA52C5B86", - "CF5AC8395BAFEB13C02DA292DDED7A83", -}, -#endif + #ifndef NO_ECC_SECP + { + 16, /* size/bytes */ + ECC_SECP128R1, /* ID */ + "SECP128R1", /* curve name */ + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", /* A */ + "E87579C11079F43DD824993C2CEE5ED3", /* B */ + "FFFFFFFE0000000075A30D1B9038A115", /* order */ + "161FF7528B899B2D0C28607CA52C5B86", /* Gx */ + "CF5AC8395BAFEB13C02DA292DDED7A83", /* Gy */ + ecc_oid_secp128r1, /* oid/oidSz */ + ecc_oid_secp128r1_sz, + ECC_SECP128R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + { + 16, /* size/bytes */ + ECC_SECP128R2, /* ID */ + "SECP128R2", /* curve name */ + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", /* prime */ + "D6031998D1B3BBFEBF59CC9BBFF9AEE1", /* A */ + "5EEEFCA380D02919DC2C6558BB6D8A5D", /* B */ + "3FFFFFFF7FFFFFFFBE0024720613B5A3", /* order */ + "7B6AA5D85E572983E6FB32A7CDEBC140", /* Gx */ + "27B6916A894D3AEE7106FE805FC34B44", /* Gy */ + ecc_oid_secp128r2, /* oid/oidSz */ + ecc_oid_secp128r2_sz, + ECC_SECP128R2_OID, /* oid sum */ + 4, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR2 */ +#endif /* ECC128 */ #ifdef ECC160 -{ - 20, - "SECP160R1", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", - "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", - "0100000000000000000001F4C8F927AED3CA752257", - "4A96B5688EF573284664698968C38BB913CBFC82", - "23A628553168947D59DCC912042351377AC5FB32", -}, -#endif + #ifndef NO_ECC_SECP + { + 20, /* size/bytes */ + ECC_SECP160R1, /* ID */ + "SECP160R1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", /* A */ + "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", /* B */ + "100000000000000000001F4C8F927AED3CA752257",/* order */ + "4A96B5688EF573284664698968C38BB913CBFC82", /* Gx */ + "23A628553168947D59DCC912042351377AC5FB32", /* Gy */ + ecc_oid_secp160r1, /* oid/oidSz */ + ecc_oid_secp160r1_sz, + ECC_SECP160R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + { + 20, /* size/bytes */ + ECC_SECP160R2, /* ID */ + "SECP160R2", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", /* A */ + "B4E134D3FB59EB8BAB57274904664D5AF50388BA", /* B */ + "100000000000000000000351EE786A818F3A1A16B",/* order */ + "52DCB034293A117E1F4FF11B30F7199D3144CE6D", /* Gx */ + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", /* Gy */ + ecc_oid_secp160r2, /* oid/oidSz */ + ecc_oid_secp160r2_sz, + ECC_SECP160R2_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_KOBLITZ + { + 20, /* size/bytes */ + ECC_SECP160K1, /* ID */ + "SECP160K1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", /* prime */ + "0000000000000000000000000000000000000000", /* A */ + "0000000000000000000000000000000000000007", /* B */ + "100000000000000000001B8FA16DFAB9ACA16B6B3",/* order */ + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", /* Gx */ + "938CF935318FDCED6BC28286531733C3F03C4FEE", /* Gy */ + ecc_oid_secp160k1, /* oid/oidSz */ + ecc_oid_secp160k1_sz, + ECC_SECP160K1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + { + 20, /* size/bytes */ + ECC_BRAINPOOLP160R1, /* ID */ + "BRAINPOOLP160R1", /* curve name */ + "E95E4A5F737059DC60DFC7AD95B3D8139515620F", /* prime */ + "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", /* A */ + "1E589A8595423412134FAA2DBDEC95C8D8675E58", /* B */ + "E95E4A5F737059DC60DF5991D45029409E60FC09", /* order */ + "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3", /* Gx */ + "1667CB477A1A8EC338F94741669C976316DA6321", /* Gy */ + ecc_oid_brainpoolp160r1, /* oid/oidSz */ + ecc_oid_brainpoolp160r1_sz, + ECC_BRAINPOOLP160R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC160 */ #ifdef ECC192 -{ - 24, - "ECC-192", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", - "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", - "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", - "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811", -}, -#endif + #ifndef NO_ECC_SECP + { + 24, /* size/bytes */ + ECC_SECP192R1, /* ID */ + "SECP192R1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A */ + "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", /* order */ + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", /* Gx */ + "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811", /* Gy */ + ecc_oid_secp192r1, /* oid/oidSz */ + ecc_oid_secp192r1_sz, + ECC_SECP192R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + { + 24, /* size/bytes */ + ECC_PRIME192V2, /* ID */ + "PRIME192V2", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A */ + "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", /* order */ + "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", /* Gx */ + "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", /* Gy */ + ecc_oid_prime192v2, /* oid/oidSz */ + ecc_oid_prime192v2_sz, + ECC_PRIME192V2_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_SECPR3 + { + 24, /* size/bytes */ + ECC_PRIME192V3, /* ID */ + "PRIME192V3", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A */ + "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", /* order */ + "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", /* Gx */ + "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", /* Gy */ + ecc_oid_prime192v3, /* oid/oidSz */ + ecc_oid_prime192v3_sz, + ECC_PRIME192V3_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR3 */ + #ifdef HAVE_ECC_KOBLITZ + { + 24, /* size/bytes */ + ECC_SECP192K1, /* ID */ + "SECP192K1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", /* prime */ + "000000000000000000000000000000000000000000000000", /* A */ + "000000000000000000000000000000000000000000000003", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", /* order */ + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", /* Gx */ + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", /* Gy */ + ecc_oid_secp192k1, /* oid/oidSz */ + ecc_oid_secp192k1_sz, + ECC_SECP192K1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + { + 24, /* size/bytes */ + ECC_BRAINPOOLP192R1, /* ID */ + "BRAINPOOLP192R1", /* curve name */ + "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", /* prime */ + "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", /* A */ + "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", /* B */ + "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", /* order */ + "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6", /* Gx */ + "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", /* Gy */ + ecc_oid_brainpoolp192r1, /* oid/oidSz */ + ecc_oid_brainpoolp192r1_sz, + ECC_BRAINPOOLP192R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC192 */ #ifdef ECC224 -{ - 28, - "ECC-224", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", - "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", - "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", - "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", -}, -#endif + #ifndef NO_ECC_SECP + { + 28, /* size/bytes */ + ECC_SECP224R1, /* ID */ + "SECP224R1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* A */ + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", /* order */ + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", /* Gx */ + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* Gy */ + ecc_oid_secp224r1, /* oid/oidSz */ + ecc_oid_secp224r1_sz, + ECC_SECP224R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + { + 28, /* size/bytes */ + ECC_SECP224K1, /* ID */ + "SECP224K1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", /* prime */ + "00000000000000000000000000000000000000000000000000000000", /* A */ + "00000000000000000000000000000000000000000000000000000005", /* B */ + "10000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",/* order */ + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", /* Gx */ + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", /* Gy */ + ecc_oid_secp224k1, /* oid/oidSz */ + ecc_oid_secp224k1_sz, + ECC_SECP224K1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + { + 28, /* size/bytes */ + ECC_BRAINPOOLP224R1, /* ID */ + "BRAINPOOLP224R1", /* curve name */ + "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", /* prime */ + "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", /* A */ + "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", /* B */ + "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", /* order */ + "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", /* Gx */ + "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", /* Gy */ + ecc_oid_brainpoolp224r1, /* oid/oidSz */ + ecc_oid_brainpoolp224r1_sz, + ECC_BRAINPOOLP224R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC224 */ +#ifdef ECC239 + #ifndef NO_ECC_SECP + { + 30, /* size/bytes */ + ECC_PRIME239V1, /* ID */ + "PRIME239V1", /* curve name */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* prime */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* A */ + "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", /* B */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", /* order */ + "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", /* Gx */ + "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", /* Gy */ + ecc_oid_prime239v1, /* oid/oidSz */ + ecc_oid_prime239v1_sz, + ECC_PRIME239V1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + { + 30, /* size/bytes */ + ECC_PRIME239V2, /* ID */ + "PRIME239V2", /* curve name */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* prime */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* A */ + "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", /* B */ + "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", /* order */ + "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", /* Gx */ + "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", /* Gy */ + ecc_oid_prime239v2, /* oid/oidSz */ + ecc_oid_prime239v2_sz, + ECC_PRIME239V2_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_SECPR3 + { + 30, /* size/bytes */ + ECC_PRIME239V3, /* ID */ + "PRIME239V3", /* curve name */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* prime */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* A */ + "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", /* B */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", /* order */ + "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", /* Gx */ + "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", /* Gy */ + ecc_oid_prime239v3, /* oid/oidSz */ + ecc_oid_prime239v3_sz, + ECC_PRIME239V3_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR3 */ +#endif /* ECC239 */ #ifdef ECC256 -{ - 32, - "ECC-256", - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", - "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", - "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", - "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", -}, -#endif + #ifndef NO_ECC_SECP + { + 32, /* size/bytes */ + ECC_SECP256R1, /* ID */ + "SECP256R1", /* curve name */ + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", /* A */ + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", /* B */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", /* order */ + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", /* Gx */ + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", /* Gy */ + ecc_oid_secp256r1, /* oid/oidSz */ + ecc_oid_secp256r1_sz, + ECC_SECP256R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + { + 32, /* size/bytes */ + ECC_SECP256K1, /* ID */ + "SECP256K1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", /* prime */ + "0000000000000000000000000000000000000000000000000000000000000000", /* A */ + "0000000000000000000000000000000000000000000000000000000000000007", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", /* order */ + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", /* Gx */ + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", /* Gy */ + ecc_oid_secp256k1, /* oid/oidSz */ + ecc_oid_secp256k1_sz, + ECC_SECP256K1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + { + 32, /* size/bytes */ + ECC_BRAINPOOLP256R1, /* ID */ + "BRAINPOOLP256R1", /* curve name */ + "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", /* prime */ + "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", /* A */ + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", /* B */ + "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", /* order */ + "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", /* Gx */ + "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", /* Gy */ + ecc_oid_brainpoolp256r1, /* oid/oidSz */ + ecc_oid_brainpoolp256r1_sz, + ECC_BRAINPOOLP256R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC256 */ +#ifdef ECC320 + #ifdef HAVE_ECC_BRAINPOOL + { + 40, /* size/bytes */ + ECC_BRAINPOOLP320R1, /* ID */ + "BRAINPOOLP320R1", /* curve name */ + "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", /* prime */ + "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", /* A */ + "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", /* B */ + "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", /* order */ + "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", /* Gx */ + "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", /* Gy */ + ecc_oid_brainpoolp320r1, ecc_oid_brainpoolp320r1_sz, /* oid/oidSz */ + ECC_BRAINPOOLP320R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC320 */ #ifdef ECC384 -{ - 48, - "ECC-384", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", - "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", - "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", - "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", -}, -#endif + #ifndef NO_ECC_SECP + { + 48, /* size/bytes */ + ECC_SECP384R1, /* ID */ + "SECP384R1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", /* A */ + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", /* order */ + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", /* Gx */ + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", /* Gy */ + ecc_oid_secp384r1, ecc_oid_secp384r1_sz, /* oid/oidSz */ + ECC_SECP384R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_BRAINPOOL + { + 48, /* size/bytes */ + ECC_BRAINPOOLP384R1, /* ID */ + "BRAINPOOLP384R1", /* curve name */ + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", /* prime */ + "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", /* A */ + "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", /* B */ + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", /* order */ + "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", /* Gx */ + "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", /* Gy */ + ecc_oid_brainpoolp384r1, ecc_oid_brainpoolp384r1_sz, /* oid/oidSz */ + ECC_BRAINPOOLP384R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC384 */ +#ifdef ECC512 + #ifdef HAVE_ECC_BRAINPOOL + { + 64, /* size/bytes */ + ECC_BRAINPOOLP512R1, /* ID */ + "BRAINPOOLP512R1", /* curve name */ + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", /* prime */ + "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", /* A */ + "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", /* B */ + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", /* order */ + "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", /* Gx */ + "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", /* Gy */ + ecc_oid_brainpoolp512r1, ecc_oid_brainpoolp512r1_sz, /* oid/oidSz */ + ECC_BRAINPOOLP512R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC512 */ #ifdef ECC521 -{ - 66, - "ECC-521", - "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", - "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", - "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", - "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", - "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", -}, + #ifndef NO_ECC_SECP + { + 66, /* size/bytes */ + ECC_SECP521R1, /* ID */ + "SECP521R1", /* curve name */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* prime */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", /* A */ + "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", /* B */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", /* order */ + "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", /* Gx */ + "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", /* Gy */ + ecc_oid_secp521r1, ecc_oid_secp521r1_sz, /* oid/oidSz */ + ECC_SECP521R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #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, + #ifndef WOLFSSL_ECC_CURVE_STATIC + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + #else + {0},{0},{0},{0},{0},{0},{0},{0}, + #endif + 0, 0, 0 + }, #endif -{ - 0, - NULL, NULL, NULL, NULL, NULL, NULL, NULL -} + { + 0, + ECC_CURVE_INVALID, + #ifndef WOLFSSL_ECC_CURVE_STATIC + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + #else + {0},{0},{0},{0},{0},{0},{0},{0}, + #endif + 0, 0, 0 + } }; +#define ECC_SET_COUNT (sizeof(ecc_sets)/sizeof(ecc_set_type)) +const size_t ecc_sets_count = ECC_SET_COUNT - 1; -ecc_point* ecc_new_point(void); -void ecc_del_point(ecc_point* p); -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* modulus, mp_digit* mp); -int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* modulus, - mp_digit* mp); -static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, - int map); -static int ecc_check_pubkey_order(ecc_key* key, 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* modulus); +#ifdef HAVE_OID_ENCODING + /* encoded OID cache */ + typedef struct { + word32 oidSz; + byte oid[ECC_MAX_OID_LEN]; + } oid_cache_t; + static oid_cache_t ecc_oid_cache[ECC_SET_COUNT]; #endif -int mp_jacobi(mp_int* a, mp_int* p, int* c); -int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret); -int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d); #ifdef HAVE_COMP_KEY static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen); #endif -/* helper for either lib */ -static int get_digit_count(mp_int* a) -{ - if (a == NULL) - return 0; - return a->used; +#if (defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || !defined(WOLFSSL_SP_MATH)) && \ + !defined(WOLFSSL_ATECC508A) +static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, + mp_int* prime, mp_int* order); +#endif + +int mp_jacobi(mp_int* a, mp_int* n, int* c); +int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret); + + +/* Curve Specs */ +typedef struct ecc_curve_spec { + const ecc_set_type* dp; + + mp_int* prime; + mp_int* Af; + #ifdef USE_ECC_B_PARAM + mp_int* Bf; + #endif + mp_int* order; + mp_int* Gx; + mp_int* Gy; + +#ifdef ECC_CACHE_CURVE + mp_int prime_lcl; + mp_int Af_lcl; + #ifdef USE_ECC_B_PARAM + mp_int Bf_lcl; + #endif + mp_int order_lcl; + mp_int Gx_lcl; + mp_int Gy_lcl; +#else + mp_int* spec_ints; + word32 spec_count; + word32 spec_use; +#endif + + byte load_mask; +} ecc_curve_spec; + +enum ecc_curve_load_mask { + ECC_CURVE_FIELD_NONE = 0x00, + ECC_CURVE_FIELD_PRIME = 0x01, + ECC_CURVE_FIELD_AF = 0x02, +#ifdef USE_ECC_B_PARAM + ECC_CURVE_FIELD_BF = 0x04, +#endif + ECC_CURVE_FIELD_ORDER = 0x08, + ECC_CURVE_FIELD_GX = 0x10, + ECC_CURVE_FIELD_GY = 0x20, +#ifdef USE_ECC_B_PARAM + ECC_CURVE_FIELD_ALL = 0x3F, + ECC_CURVE_FIELD_COUNT = 6, +#else + ECC_CURVE_FIELD_ALL = 0x3B, + ECC_CURVE_FIELD_COUNT = 5, +#endif +}; + +#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(curve, intcount) ecc_curve_spec* curve = NULL + #define ALLOC_CURVE_SPECS(intcount) + #define FREE_CURVE_SPECS() +#elif defined(WOLFSSL_SMALL_STACK) + #define DECLARE_CURVE_SPECS(curve, intcount) \ + mp_int* spec_ints = NULL; \ + ecc_curve_spec curve_lcl; \ + ecc_curve_spec* curve = &curve_lcl; \ + XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ + curve->spec_count = intcount + + #define ALLOC_CURVE_SPECS(intcount) \ + spec_ints = (mp_int*)XMALLOC(sizeof(mp_int) * (intcount), NULL, \ + DYNAMIC_TYPE_ECC); \ + if (spec_ints == NULL) \ + return MEMORY_E; \ + curve->spec_ints = spec_ints + #define FREE_CURVE_SPECS() \ + XFREE(spec_ints, NULL, DYNAMIC_TYPE_ECC) +#else + #define DECLARE_CURVE_SPECS(curve, intcount) \ + mp_int spec_ints[(intcount)]; \ + ecc_curve_spec curve_lcl; \ + ecc_curve_spec* curve = &curve_lcl; \ + XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ + curve->spec_ints = spec_ints; \ + curve->spec_count = intcount + #define ALLOC_CURVE_SPECS(intcount) + #define FREE_CURVE_SPECS() +#endif /* ECC_CACHE_CURVE */ + +static void _wc_ecc_curve_free(ecc_curve_spec* curve) +{ + if (curve == NULL) { + return; + } + + if (curve->load_mask & ECC_CURVE_FIELD_PRIME) + mp_clear(curve->prime); + if (curve->load_mask & ECC_CURVE_FIELD_AF) + mp_clear(curve->Af); +#ifdef USE_ECC_B_PARAM + if (curve->load_mask & ECC_CURVE_FIELD_BF) + mp_clear(curve->Bf); +#endif + if (curve->load_mask & ECC_CURVE_FIELD_ORDER) + mp_clear(curve->order); + if (curve->load_mask & ECC_CURVE_FIELD_GX) + mp_clear(curve->Gx); + if (curve->load_mask & ECC_CURVE_FIELD_GY) + mp_clear(curve->Gy); + + curve->load_mask = 0; } -/* helper for either lib */ -static mp_digit get_digit(mp_int* a, int n) +static void wc_ecc_curve_free(ecc_curve_spec* curve) { - if (a == NULL) - return 0; + /* don't free cached curves */ +#ifndef ECC_CACHE_CURVE + _wc_ecc_curve_free(curve); +#endif + (void)curve; +} - return (n >= a->used || n < 0) ? 0 : a->dp[n]; +static int wc_ecc_curve_load_item(const char* src, mp_int** dst, + ecc_curve_spec* curve, byte mask) +{ + int err; + +#ifndef ECC_CACHE_CURVE + /* get mp_int from temp */ + if (curve->spec_use >= curve->spec_count) { + WOLFSSL_MSG("Invalid DECLARE_CURVE_SPECS count"); + return ECC_BAD_ARG_E; + } + *dst = &curve->spec_ints[curve->spec_use++]; +#endif + + err = mp_init(*dst); + if (err == MP_OKAY) { + curve->load_mask |= mask; + + 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; +} + +static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve, + byte load_mask) +{ + int ret = 0, x; + ecc_curve_spec* curve; + byte load_items = 0; /* mask of items to load */ + + if (dp == NULL || pCurve == NULL) + return BAD_FUNC_ARG; + +#ifdef ECC_CACHE_CURVE + 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 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)); + } + + /* set curve pointer to cache */ + *pCurve = ecc_curve_spec_cache[x]; + +#endif /* ECC_CACHE_CURVE */ + curve = *pCurve; + + /* make sure the curve is initialized */ + if (curve->dp != dp) { + curve->load_mask = 0; + + #ifdef ECC_CACHE_CURVE + curve->prime = &curve->prime_lcl; + curve->Af = &curve->Af_lcl; + #ifdef USE_ECC_B_PARAM + curve->Bf = &curve->Bf_lcl; + #endif + curve->order = &curve->order_lcl; + curve->Gx = &curve->Gx_lcl; + curve->Gy = &curve->Gy_lcl; + #endif + } + curve->dp = dp; /* set dp info */ + + /* determine items to load */ + load_items = (((byte)~(word32)curve->load_mask) & load_mask); + curve->load_mask |= load_items; + + /* load items */ + x = 0; + if (load_items & ECC_CURVE_FIELD_PRIME) + x += wc_ecc_curve_load_item(dp->prime, &curve->prime, curve, + ECC_CURVE_FIELD_PRIME); + if (load_items & ECC_CURVE_FIELD_AF) + x += wc_ecc_curve_load_item(dp->Af, &curve->Af, curve, + ECC_CURVE_FIELD_AF); +#ifdef USE_ECC_B_PARAM + if (load_items & ECC_CURVE_FIELD_BF) + x += wc_ecc_curve_load_item(dp->Bf, &curve->Bf, curve, + ECC_CURVE_FIELD_BF); +#endif + if (load_items & ECC_CURVE_FIELD_ORDER) + x += wc_ecc_curve_load_item(dp->order, &curve->order, curve, + ECC_CURVE_FIELD_ORDER); + if (load_items & ECC_CURVE_FIELD_GX) + x += wc_ecc_curve_load_item(dp->Gx, &curve->Gx, curve, + ECC_CURVE_FIELD_GX); + if (load_items & ECC_CURVE_FIELD_GY) + x += wc_ecc_curve_load_item(dp->Gy, &curve->Gy, curve, + ECC_CURVE_FIELD_GY); + + /* check for error */ + if (x != 0) { + wc_ecc_curve_free(curve); + 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; + + /* free all ECC curve caches */ + for (x = 0; x < (int)ECC_SET_COUNT; x++) { + if (ecc_curve_spec_cache[x]) { + _wc_ecc_curve_free(ecc_curve_spec_cache[x]); + XFREE(ecc_curve_spec_cache[x], NULL, DYNAMIC_TYPE_ECC); + 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 */ + + +/* 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) +{ + 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; + } + + if (keysize > ECC_MAXSIZE) { + return ECC_BAD_ARG_E; + } + + /* handle custom case */ + 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) { + if (curve_id == ecc_sets[x].id) + break; + } + else if (keysize <= ecc_sets[x].size) { + break; + } + } + if (ecc_sets[x].size == 0) { + WOLFSSL_MSG("ECC Curve not found"); + return ECC_CURVE_OID_E; + } + + key->idx = x; + key->dp = &ecc_sets[x]; + } + + return 0; } -#if defined(USE_FAST_MATH) +#ifdef ALT_ECC_SIZE +static void alt_fp_init(mp_int* a) +{ + a->size = FP_SIZE_ECC; + mp_zero(a); +} +#endif /* ALT_ECC_SIZE */ -/* fast math accelerated version, but not for fp ecc yet */ - -/** - Add two ECC points - P The point to add - Q The point to add - R [out] The destination of the double - modulus The modulus of the field the ECC curve is in - mp The "b" value from montgomery_setup() - return MP_OKAY on success -*/ -int ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, - mp_int* modulus, mp_digit* mp) -{ - fp_int t1, t2, x, y, z; - int err; - - if (P == NULL || Q == NULL || R == NULL || modulus == NULL || mp == NULL) - return ECC_BAD_ARG_E; - - if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) { - return err; - } - - /* should we dbl instead? */ - fp_sub(modulus, Q->y, &t1); - if ( (fp_cmp(P->x, Q->x) == FP_EQ) && - (get_digit_count(Q->z) && fp_cmp(P->z, Q->z) == FP_EQ) && - (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) { - return ecc_projective_dbl_point(P, R, modulus, mp); - } - - fp_copy(P->x, &x); - fp_copy(P->y, &y); - fp_copy(P->z, &z); - - /* if Z is one then these are no-operations */ - if (get_digit_count(Q->z)) { - /* T1 = Z' * Z' */ - fp_sqr(Q->z, &t1); - fp_montgomery_reduce(&t1, modulus, *mp); - /* X = X * T1 */ - fp_mul(&t1, &x, &x); - fp_montgomery_reduce(&x, modulus, *mp); - /* T1 = Z' * T1 */ - fp_mul(Q->z, &t1, &t1); - fp_montgomery_reduce(&t1, modulus, *mp); - /* Y = Y * T1 */ - fp_mul(&t1, &y, &y); - fp_montgomery_reduce(&y, modulus, *mp); - } - - /* T1 = Z*Z */ - fp_sqr(&z, &t1); - fp_montgomery_reduce(&t1, modulus, *mp); - /* T2 = X' * T1 */ - fp_mul(Q->x, &t1, &t2); - fp_montgomery_reduce(&t2, modulus, *mp); - /* T1 = Z * T1 */ - fp_mul(&z, &t1, &t1); - fp_montgomery_reduce(&t1, modulus, *mp); - /* T1 = Y' * T1 */ - fp_mul(Q->y, &t1, &t1); - fp_montgomery_reduce(&t1, modulus, *mp); - - /* Y = Y - T1 */ - fp_sub(&y, &t1, &y); - if (fp_cmp_d(&y, 0) == FP_LT) { - fp_add(&y, modulus, &y); - } - /* T1 = 2T1 */ - fp_add(&t1, &t1, &t1); - if (fp_cmp(&t1, modulus) != FP_LT) { - fp_sub(&t1, modulus, &t1); - } - /* T1 = Y + T1 */ - fp_add(&t1, &y, &t1); - if (fp_cmp(&t1, modulus) != FP_LT) { - fp_sub(&t1, modulus, &t1); - } - /* X = X - T2 */ - fp_sub(&x, &t2, &x); - if (fp_cmp_d(&x, 0) == FP_LT) { - fp_add(&x, modulus, &x); - } - /* T2 = 2T2 */ - fp_add(&t2, &t2, &t2); - if (fp_cmp(&t2, modulus) != FP_LT) { - fp_sub(&t2, modulus, &t2); - } - /* T2 = X + T2 */ - fp_add(&t2, &x, &t2); - if (fp_cmp(&t2, modulus) != FP_LT) { - fp_sub(&t2, modulus, &t2); - } - - /* if Z' != 1 */ - if (get_digit_count(Q->z)) { - /* Z = Z * Z' */ - fp_mul(&z, Q->z, &z); - fp_montgomery_reduce(&z, modulus, *mp); - } - - /* Z = Z * X */ - fp_mul(&z, &x, &z); - fp_montgomery_reduce(&z, modulus, *mp); - - /* T1 = T1 * X */ - fp_mul(&t1, &x, &t1); - fp_montgomery_reduce(&t1, modulus, *mp); - /* X = X * X */ - fp_sqr(&x, &x); - fp_montgomery_reduce(&x, modulus, *mp); - /* T2 = T2 * x */ - fp_mul(&t2, &x, &t2); - fp_montgomery_reduce(&t2, modulus, *mp); - /* T1 = T1 * X */ - fp_mul(&t1, &x, &t1); - fp_montgomery_reduce(&t1, modulus, *mp); - - /* X = Y*Y */ - fp_sqr(&y, &x); - fp_montgomery_reduce(&x, modulus, *mp); - /* X = X - T2 */ - fp_sub(&x, &t2, &x); - if (fp_cmp_d(&x, 0) == FP_LT) { - fp_add(&x, modulus, &x); - } - - /* T2 = T2 - X */ - fp_sub(&t2, &x, &t2); - if (fp_cmp_d(&t2, 0) == FP_LT) { - fp_add(&t2, modulus, &t2); - } - /* T2 = T2 - X */ - fp_sub(&t2, &x, &t2); - if (fp_cmp_d(&t2, 0) == FP_LT) { - fp_add(&t2, modulus, &t2); - } - /* T2 = T2 * Y */ - fp_mul(&t2, &y, &t2); - fp_montgomery_reduce(&t2, modulus, *mp); - /* Y = T2 - T1 */ - fp_sub(&t2, &t1, &y); - if (fp_cmp_d(&y, 0) == FP_LT) { - fp_add(&y, modulus, &y); - } - /* Y = Y/2 */ - if (fp_isodd(&y)) { - fp_add(&y, modulus, &y); - } - fp_div_2(&y, &y); - - fp_copy(&x, R->x); - fp_copy(&y, R->y); - fp_copy(&z, R->z); - - return MP_OKAY; -} - - -/** - Double an ECC point - P The point to double - R [out] The destination of the double - modulus The modulus of the field the ECC curve is in - mp The "b" value from montgomery_setup() - return MP_OKAY on success -*/ -int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus, - mp_digit* mp) -{ - fp_int t1, t2; - int err; - - if (P == NULL || R == NULL || modulus == NULL || mp == NULL) - return ECC_BAD_ARG_E; - - if (P != R) { - fp_copy(P->x, R->x); - fp_copy(P->y, R->y); - fp_copy(P->z, R->z); - } - - if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { - return err; - } - - /* t1 = Z * Z */ - fp_sqr(R->z, &t1); - fp_montgomery_reduce(&t1, modulus, *mp); - /* Z = Y * Z */ - fp_mul(R->z, R->y, R->z); - fp_montgomery_reduce(R->z, modulus, *mp); - /* Z = 2Z */ - fp_add(R->z, R->z, R->z); - if (fp_cmp(R->z, modulus) != FP_LT) { - fp_sub(R->z, modulus, R->z); - } - - /* &t2 = X - T1 */ - fp_sub(R->x, &t1, &t2); - if (fp_cmp_d(&t2, 0) == FP_LT) { - fp_add(&t2, modulus, &t2); - } - /* T1 = X + T1 */ - fp_add(&t1, R->x, &t1); - if (fp_cmp(&t1, modulus) != FP_LT) { - fp_sub(&t1, modulus, &t1); - } - /* T2 = T1 * T2 */ - fp_mul(&t1, &t2, &t2); - fp_montgomery_reduce(&t2, modulus, *mp); - /* T1 = 2T2 */ - fp_add(&t2, &t2, &t1); - if (fp_cmp(&t1, modulus) != FP_LT) { - fp_sub(&t1, modulus, &t1); - } - /* T1 = T1 + T2 */ - fp_add(&t1, &t2, &t1); - if (fp_cmp(&t1, modulus) != FP_LT) { - fp_sub(&t1, modulus, &t1); - } - - /* Y = 2Y */ - fp_add(R->y, R->y, R->y); - if (fp_cmp(R->y, modulus) != FP_LT) { - fp_sub(R->y, modulus, R->y); - } - /* Y = Y * Y */ - fp_sqr(R->y, R->y); - fp_montgomery_reduce(R->y, modulus, *mp); - /* T2 = Y * Y */ - fp_sqr(R->y, &t2); - fp_montgomery_reduce(&t2, modulus, *mp); - /* T2 = T2/2 */ - if (fp_isodd(&t2)) { - fp_add(&t2, modulus, &t2); - } - fp_div_2(&t2, &t2); - /* Y = Y * X */ - fp_mul(R->y, R->x, R->y); - fp_montgomery_reduce(R->y, modulus, *mp); - - /* X = T1 * T1 */ - fp_sqr(&t1, R->x); - fp_montgomery_reduce(R->x, modulus, *mp); - /* X = X - Y */ - fp_sub(R->x, R->y, R->x); - if (fp_cmp_d(R->x, 0) == FP_LT) { - fp_add(R->x, modulus, R->x); - } - /* X = X - Y */ - fp_sub(R->x, R->y, R->x); - if (fp_cmp_d(R->x, 0) == FP_LT) { - fp_add(R->x, modulus, R->x); - } - - /* Y = Y - X */ - fp_sub(R->y, R->x, R->y); - if (fp_cmp_d(R->y, 0) == FP_LT) { - fp_add(R->y, modulus, R->y); - } - /* Y = Y * T1 */ - fp_mul(R->y, &t1, R->y); - fp_montgomery_reduce(R->y, modulus, *mp); - /* Y = Y - T2 */ - fp_sub(R->y, &t2, R->y); - if (fp_cmp_d(R->y, 0) == FP_LT) { - fp_add(R->y, modulus, R->y); - } - - return MP_OKAY; -} - -#else /* USE_FAST_MATH */ + +#ifndef WOLFSSL_ATECC508A + +#if !defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_PUBLIC_ECC_ADD_DBL) /** Add two ECC points P The point to add Q The point to add R [out] The destination of the double + a ECC curve parameter a modulus The modulus of the field the ECC curve is in mp The "b" value from montgomery_setup() return MP_OKAY on success */ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, - mp_int* modulus, mp_digit* mp) + mp_int* a, mp_int* modulus, mp_digit mp) { - mp_int t1; - mp_int t2; - mp_int x; - mp_int y; - mp_int z; - int err; +#ifndef WOLFSSL_SP_MATH +#ifdef WOLFSSL_SMALL_STACK + mp_int* t1 = NULL; + mp_int* t2 = NULL; +#ifdef ALT_ECC_SIZE + mp_int* rx = NULL; + mp_int* ry = NULL; + mp_int* rz = NULL; +#endif +#else + mp_int t1[1], t2[1]; +#ifdef ALT_ECC_SIZE + mp_int rx[1], ry[1], rz[1]; +#endif +#endif + mp_int *x, *y, *z; + int err; - if (P == NULL || Q == NULL || R == NULL || modulus == NULL || mp == NULL) + if (P == NULL || Q == NULL || R == NULL || modulus == NULL) { return ECC_BAD_ARG_E; + } - if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) { + /* if Q == R then swap P and Q, so we don't require a local x,y,z */ + if (Q == R) { + ecc_point* tPt = P; + P = Q; + Q = tPt; + } + +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key != NULL) { + t1 = R->key->t1; + t2 = R->key->t2; +#ifdef ALT_ECC_SIZE + rx = R->key->x; + ry = R->key->y; + rz = R->key->z; +#endif + } + else +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + { + t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL || t2 == NULL) { + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#ifdef ALT_ECC_SIZE + rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rx == NULL || ry == NULL || rz == NULL) { + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + } +#endif /* WOLFSSL_SMALL_STACK */ + + if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) + #endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif return err; } - + /* should we dbl instead? */ - err = mp_sub(modulus, Q->y, &t1); - + if (err == MP_OKAY) + err = mp_sub(modulus, Q->y, t1); if (err == MP_OKAY) { - if ( (mp_cmp(P->x, Q->x) == MP_EQ) && + 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)) { - mp_clear(&t1); - mp_clear(&t2); - mp_clear(&x); - mp_clear(&y); - mp_clear(&z); - - return ecc_projective_dbl_point(P, R, modulus, mp); + (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, t1) == MP_EQ)) { + mp_clear(t1); + mp_clear(t2); + #ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) + #endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } + #endif + return ecc_projective_dbl_point(P, R, a, modulus, mp); } } + if (err != MP_OKAY) { + goto done; + } + +/* If use ALT_ECC_SIZE we need to use local stack variable since + ecc_point x,y,z is reduced size */ +#ifdef ALT_ECC_SIZE + /* Use local stack variable */ + x = rx; + y = ry; + z = rz; + + if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { + goto done; + } +#else + /* Use destination directly */ + x = R->x; + y = R->y; + z = R->z; +#endif + if (err == MP_OKAY) - err = mp_copy(P->x, &x); + err = mp_copy(P->x, x); if (err == MP_OKAY) - err = mp_copy(P->y, &y); + err = mp_copy(P->y, y); if (err == MP_OKAY) - err = mp_copy(P->z, &z); + err = mp_copy(P->z, z); /* if Z is one then these are no-operations */ if (err == MP_OKAY) { - if (get_digit_count(Q->z)) { + if (!mp_iszero(Q->z)) { /* T1 = Z' * Z' */ - err = mp_sqr(Q->z, &t1); + err = mp_sqr(Q->z, t1); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t1, modulus, *mp); + err = mp_montgomery_reduce(t1, modulus, mp); /* X = X * T1 */ if (err == MP_OKAY) - err = mp_mul(&t1, &x, &x); + err = mp_mul(t1, x, x); if (err == MP_OKAY) - err = mp_montgomery_reduce(&x, modulus, *mp); + err = mp_montgomery_reduce(x, modulus, mp); /* T1 = Z' * T1 */ if (err == MP_OKAY) - err = mp_mul(Q->z, &t1, &t1); + err = mp_mul(Q->z, t1, t1); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t1, modulus, *mp); + err = mp_montgomery_reduce(t1, modulus, mp); /* Y = Y * T1 */ if (err == MP_OKAY) - err = mp_mul(&t1, &y, &y); + err = mp_mul(t1, y, y); if (err == MP_OKAY) - err = mp_montgomery_reduce(&y, modulus, *mp); + err = mp_montgomery_reduce(y, modulus, mp); } } /* T1 = Z*Z */ if (err == MP_OKAY) - err = mp_sqr(&z, &t1); + err = mp_sqr(z, t1); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t1, modulus, *mp); + err = mp_montgomery_reduce(t1, modulus, mp); /* T2 = X' * T1 */ if (err == MP_OKAY) - err = mp_mul(Q->x, &t1, &t2); + err = mp_mul(Q->x, t1, t2); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t2, modulus, *mp); + err = mp_montgomery_reduce(t2, modulus, mp); /* T1 = Z * T1 */ if (err == MP_OKAY) - err = mp_mul(&z, &t1, &t1); + err = mp_mul(z, t1, t1); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t1, modulus, *mp); + err = mp_montgomery_reduce(t1, modulus, mp); /* T1 = Y' * T1 */ if (err == MP_OKAY) - err = mp_mul(Q->y, &t1, &t1); + err = mp_mul(Q->y, t1, t1); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t1, modulus, *mp); + err = mp_montgomery_reduce(t1, modulus, mp); /* Y = Y - T1 */ if (err == MP_OKAY) - err = mp_sub(&y, &t1, &y); + err = mp_sub(y, t1, y); if (err == MP_OKAY) { - if (mp_cmp_d(&y, 0) == MP_LT) - err = mp_add(&y, modulus, &y); + if (mp_isneg(y)) + err = mp_add(y, modulus, y); } /* T1 = 2T1 */ if (err == MP_OKAY) - err = mp_add(&t1, &t1, &t1); + err = mp_add(t1, t1, t1); if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); } /* T1 = Y + T1 */ if (err == MP_OKAY) - err = mp_add(&t1, &y, &t1); + err = mp_add(t1, y, t1); if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); } /* X = X - T2 */ if (err == MP_OKAY) - err = mp_sub(&x, &t2, &x); + err = mp_sub(x, t2, x); if (err == MP_OKAY) { - if (mp_cmp_d(&x, 0) == MP_LT) - err = mp_add(&x, modulus, &x); + if (mp_isneg(x)) + err = mp_add(x, modulus, x); } /* T2 = 2T2 */ if (err == MP_OKAY) - err = mp_add(&t2, &t2, &t2); + err = mp_add(t2, t2, t2); if (err == MP_OKAY) { - if (mp_cmp(&t2, modulus) != MP_LT) - err = mp_sub(&t2, modulus, &t2); + if (mp_cmp(t2, modulus) != MP_LT) + err = mp_sub(t2, modulus, t2); } /* T2 = X + T2 */ if (err == MP_OKAY) - err = mp_add(&t2, &x, &t2); + err = mp_add(t2, x, t2); if (err == MP_OKAY) { - if (mp_cmp(&t2, modulus) != MP_LT) - err = mp_sub(&t2, modulus, &t2); + if (mp_cmp(t2, modulus) != MP_LT) + err = mp_sub(t2, modulus, t2); } if (err == MP_OKAY) { - if (get_digit_count(Q->z)) { + if (!mp_iszero(Q->z)) { /* Z = Z * Z' */ - err = mp_mul(&z, Q->z, &z); + err = mp_mul(z, Q->z, z); if (err == MP_OKAY) - err = mp_montgomery_reduce(&z, modulus, *mp); + err = mp_montgomery_reduce(z, modulus, mp); } } /* Z = Z * X */ if (err == MP_OKAY) - err = mp_mul(&z, &x, &z); + err = mp_mul(z, x, z); if (err == MP_OKAY) - err = mp_montgomery_reduce(&z, modulus, *mp); + err = mp_montgomery_reduce(z, modulus, mp); /* T1 = T1 * X */ if (err == MP_OKAY) - err = mp_mul(&t1, &x, &t1); + err = mp_mul(t1, x, t1); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t1, modulus, *mp); + err = mp_montgomery_reduce(t1, modulus, mp); /* X = X * X */ if (err == MP_OKAY) - err = mp_sqr(&x, &x); + err = mp_sqr(x, x); if (err == MP_OKAY) - err = mp_montgomery_reduce(&x, modulus, *mp); - + err = mp_montgomery_reduce(x, modulus, mp); + /* T2 = T2 * x */ if (err == MP_OKAY) - err = mp_mul(&t2, &x, &t2); + err = mp_mul(t2, x, t2); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t2, modulus, *mp); + err = mp_montgomery_reduce(t2, modulus, mp); /* T1 = T1 * X */ if (err == MP_OKAY) - err = mp_mul(&t1, &x, &t1); + err = mp_mul(t1, x, t1); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t1, modulus, *mp); - + err = mp_montgomery_reduce(t1, modulus, mp); + /* X = Y*Y */ if (err == MP_OKAY) - err = mp_sqr(&y, &x); + err = mp_sqr(y, x); if (err == MP_OKAY) - err = mp_montgomery_reduce(&x, modulus, *mp); + err = mp_montgomery_reduce(x, modulus, mp); /* X = X - T2 */ if (err == MP_OKAY) - err = mp_sub(&x, &t2, &x); + err = mp_sub(x, t2, x); if (err == MP_OKAY) { - if (mp_cmp_d(&x, 0) == MP_LT) - err = mp_add(&x, modulus, &x); + if (mp_isneg(x)) + err = mp_add(x, modulus, x); } /* T2 = T2 - X */ if (err == MP_OKAY) - err = mp_sub(&t2, &x, &t2); + err = mp_sub(t2, x, t2); if (err == MP_OKAY) { - if (mp_cmp_d(&t2, 0) == MP_LT) - err = mp_add(&t2, modulus, &t2); - } + if (mp_isneg(t2)) + err = mp_add(t2, modulus, t2); + } /* T2 = T2 - X */ if (err == MP_OKAY) - err = mp_sub(&t2, &x, &t2); + err = mp_sub(t2, x, t2); if (err == MP_OKAY) { - if (mp_cmp_d(&t2, 0) == MP_LT) - err = mp_add(&t2, modulus, &t2); + if (mp_isneg(t2)) + err = mp_add(t2, modulus, t2); } /* T2 = T2 * Y */ if (err == MP_OKAY) - err = mp_mul(&t2, &y, &t2); + err = mp_mul(t2, y, t2); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t2, modulus, *mp); + err = mp_montgomery_reduce(t2, modulus, mp); /* Y = T2 - T1 */ if (err == MP_OKAY) - err = mp_sub(&t2, &t1, &y); + err = mp_sub(t2, t1, y); if (err == MP_OKAY) { - if (mp_cmp_d(&y, 0) == MP_LT) - err = mp_add(&y, modulus, &y); + if (mp_isneg(y)) + err = mp_add(y, modulus, y); } /* Y = Y/2 */ if (err == MP_OKAY) { - if (mp_isodd(&y)) - err = mp_add(&y, modulus, &y); + if (mp_isodd(y) == MP_YES) + err = mp_add(y, modulus, y); } if (err == MP_OKAY) - err = mp_div_2(&y, &y); + err = mp_div_2(y, y); +#ifdef ALT_ECC_SIZE if (err == MP_OKAY) - err = mp_copy(&x, R->x); + err = mp_copy(x, R->x); if (err == MP_OKAY) - err = mp_copy(&y, R->y); + err = mp_copy(y, R->y); if (err == MP_OKAY) - err = mp_copy(&z, R->z); + err = mp_copy(z, R->z); +#endif + +done: /* clean up */ - mp_clear(&t1); - mp_clear(&t2); - mp_clear(&x); - mp_clear(&y); - mp_clear(&z); + mp_clear(t1); + mp_clear(t2); +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif return err; +#else + if (P == NULL || Q == NULL || R == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + (void)a; + (void)mp; + +#ifndef WOLFSSL_SP_NO_256 + if (mp_count_bits(modulus) == 256) { + return sp_ecc_proj_add_point_256(P->x, P->y, P->z, Q->x, Q->y, Q->z, + R->x, R->y, R->z); + } +#endif +#ifdef WOLFSSL_SP_384 + if (mp_count_bits(modulus) == 384) { + return sp_ecc_proj_add_point_384(P->x, P->y, P->z, Q->x, Q->y, Q->z, + R->x, R->y, R->z); + } +#endif + return ECC_BAD_ARG_E; +#endif } +/* ### Point doubling in Jacobian coordinate system ### + * + * let us have a curve: y^2 = x^3 + a*x + b + * in Jacobian coordinates it becomes: y^2 = x^3 + a*x*z^4 + b*z^6 + * + * The doubling of P = (Xp, Yp, Zp) is given by R = (Xr, Yr, Zr) where: + * Xr = M^2 - 2*S + * Yr = M * (S - Xr) - 8*T + * Zr = 2 * Yp * Zp + * + * M = 3 * Xp^2 + a*Zp^4 + * T = Yp^4 + * S = 4 * Xp * Yp^2 + * + * SPECIAL CASE: when a == 3 we can compute M as + * M = 3 * (Xp^2 - Zp^4) = 3 * (Xp + Zp^2) * (Xp - Zp^2) + */ /** Double an ECC point P The point to double R [out] The destination of the double + a ECC curve parameter a modulus The modulus of the field the ECC curve is in mp The "b" value from montgomery_setup() return MP_OKAY on success */ -int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, 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) { - mp_int t1; - mp_int t2; +#ifndef WOLFSSL_SP_MATH +#ifdef WOLFSSL_SMALL_STACK + mp_int* t1 = NULL; + mp_int* t2 = NULL; +#ifdef ALT_ECC_SIZE + mp_int* rx = NULL; + mp_int* ry = NULL; + mp_int* rz = NULL; +#endif +#else + mp_int t1[1], t2[1]; +#ifdef ALT_ECC_SIZE + mp_int rx[1], ry[1], rz[1]; +#endif +#endif + mp_int *x, *y, *z; int err; - if (P == NULL || R == NULL || modulus == NULL || mp == NULL) + if (P == NULL || R == NULL || modulus == NULL) return ECC_BAD_ARG_E; - if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key != NULL) { + t1 = R->key->t1; + t2 = R->key->t2; + #ifdef ALT_ECC_SIZE + rx = R->key->x; + ry = R->key->y; + rz = R->key->z; + #endif + } + else +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + { + t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL || t2 == NULL) { + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #ifdef ALT_ECC_SIZE + rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rx == NULL || ry == NULL || rz == NULL) { + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif + } +#endif + + if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif return err; } - if (P != R) { - err = mp_copy(P->x, R->x); - if (err == MP_OKAY) - err = mp_copy(P->y, R->y); - if (err == MP_OKAY) - err = mp_copy(P->z, R->z); - } +/* If use ALT_ECC_SIZE we need to use local stack variable since + ecc_point x,y,z is reduced size */ +#ifdef ALT_ECC_SIZE + /* Use local stack variable */ + x = rx; + y = ry; + z = rz; + + if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { + mp_clear(t1); + mp_clear(t2); + #ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) + #endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } + #endif + return err; + } +#else + /* Use destination directly */ + x = R->x; + y = R->y; + z = R->z; +#endif - /* t1 = Z * Z */ if (err == MP_OKAY) - err = mp_sqr(R->z, &t1); + err = mp_copy(P->x, x); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t1, modulus, *mp); + err = mp_copy(P->y, y); + if (err == MP_OKAY) + err = mp_copy(P->z, z); + + /* T1 = Z * Z */ + if (err == MP_OKAY) + err = mp_sqr(z, t1); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t1, modulus, mp); /* Z = Y * Z */ if (err == MP_OKAY) - err = mp_mul(R->z, R->y, R->z); + err = mp_mul(z, y, z); if (err == MP_OKAY) - err = mp_montgomery_reduce(R->z, modulus, *mp); + err = mp_montgomery_reduce(z, modulus, mp); /* Z = 2Z */ if (err == MP_OKAY) - err = mp_add(R->z, R->z, R->z); + err = mp_add(z, z, z); if (err == MP_OKAY) { - if (mp_cmp(R->z, modulus) != MP_LT) - err = mp_sub(R->z, modulus, R->z); + if (mp_cmp(z, modulus) != MP_LT) + err = mp_sub(z, modulus, z); } - /* T2 = X - T1 */ - if (err == MP_OKAY) - err = mp_sub(R->x, &t1, &t2); + /* Determine if curve "a" should be used in calc */ +#ifdef WOLFSSL_CUSTOM_CURVES if (err == MP_OKAY) { - if (mp_cmp_d(&t2, 0) == MP_LT) - err = mp_add(&t2, modulus, &t2); + /* Use a and prime to determine if a == 3 */ + err = mp_submod(modulus, a, modulus, t2); } - /* T1 = X + T1 */ - if (err == MP_OKAY) - err = mp_add(&t1, R->x, &t1); - if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); - } - /* T2 = T1 * T2 */ - if (err == MP_OKAY) - err = mp_mul(&t1, &t2, &t2); - if (err == MP_OKAY) - err = mp_montgomery_reduce(&t2, modulus, *mp); + if (err == MP_OKAY && mp_cmp_d(t2, 3) != MP_EQ) { + /* use "a" in calc */ - /* T1 = 2T2 */ - if (err == MP_OKAY) - err = mp_add(&t2, &t2, &t1); - if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); + /* T2 = T1 * T1 */ + if (err == MP_OKAY) + err = mp_sqr(t1, t2); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t2, modulus, mp); + /* T1 = T2 * a */ + if (err == MP_OKAY) + err = mp_mulmod(t2, a, modulus, t1); + /* T2 = X * X */ + if (err == MP_OKAY) + err = mp_sqr(x, t2); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t2, modulus, mp); + /* T1 = T2 + T1 */ + if (err == MP_OKAY) + err = mp_add(t1, t2, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } + /* T1 = T2 + T1 */ + if (err == MP_OKAY) + err = mp_add(t1, t2, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } + /* T1 = T2 + T1 */ + if (err == MP_OKAY) + err = mp_add(t1, t2, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } } - /* T1 = T1 + T2 */ - if (err == MP_OKAY) - err = mp_add(&t1, &t2, &t1); - if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); + else +#endif /* WOLFSSL_CUSTOM_CURVES */ + { + /* assumes "a" == 3 */ + (void)a; + + /* T2 = X - T1 */ + if (err == MP_OKAY) + err = mp_sub(x, t1, t2); + if (err == MP_OKAY) { + if (mp_isneg(t2)) + err = mp_add(t2, modulus, t2); + } + /* T1 = X + T1 */ + if (err == MP_OKAY) + err = mp_add(t1, x, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } + /* T2 = T1 * T2 */ + if (err == MP_OKAY) + err = mp_mul(t1, t2, t2); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t2, modulus, mp); + + /* T1 = 2T2 */ + if (err == MP_OKAY) + err = mp_add(t2, t2, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } + /* T1 = T1 + T2 */ + if (err == MP_OKAY) + err = mp_add(t1, t2, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } } + /* Y = 2Y */ if (err == MP_OKAY) - err = mp_add(R->y, R->y, R->y); + err = mp_add(y, y, y); if (err == MP_OKAY) { - if (mp_cmp(R->y, modulus) != MP_LT) - err = mp_sub(R->y, modulus, R->y); + if (mp_cmp(y, modulus) != MP_LT) + err = mp_sub(y, modulus, y); } /* Y = Y * Y */ if (err == MP_OKAY) - err = mp_sqr(R->y, R->y); + err = mp_sqr(y, y); if (err == MP_OKAY) - err = mp_montgomery_reduce(R->y, modulus, *mp); - + err = mp_montgomery_reduce(y, modulus, mp); + /* T2 = Y * Y */ if (err == MP_OKAY) - err = mp_sqr(R->y, &t2); + err = mp_sqr(y, t2); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t2, modulus, *mp); + err = mp_montgomery_reduce(t2, modulus, mp); /* T2 = T2/2 */ if (err == MP_OKAY) { - if (mp_isodd(&t2)) - err = mp_add(&t2, modulus, &t2); + if (mp_isodd(t2) == MP_YES) + err = mp_add(t2, modulus, t2); } if (err == MP_OKAY) - err = mp_div_2(&t2, &t2); - + err = mp_div_2(t2, t2); + /* Y = Y * X */ if (err == MP_OKAY) - err = mp_mul(R->y, R->x, R->y); + err = mp_mul(y, x, y); if (err == MP_OKAY) - err = mp_montgomery_reduce(R->y, modulus, *mp); + err = mp_montgomery_reduce(y, modulus, mp); - /* X = T1 * T1 */ + /* X = T1 * T1 */ if (err == MP_OKAY) - err = mp_sqr(&t1, R->x); + err = mp_sqr(t1, x); if (err == MP_OKAY) - err = mp_montgomery_reduce(R->x, modulus, *mp); + err = mp_montgomery_reduce(x, modulus, mp); /* X = X - Y */ if (err == MP_OKAY) - err = mp_sub(R->x, R->y, R->x); + err = mp_sub(x, y, x); if (err == MP_OKAY) { - if (mp_cmp_d(R->x, 0) == MP_LT) - err = mp_add(R->x, modulus, R->x); + if (mp_isneg(x)) + err = mp_add(x, modulus, x); } /* X = X - Y */ if (err == MP_OKAY) - err = mp_sub(R->x, R->y, R->x); + err = mp_sub(x, y, x); if (err == MP_OKAY) { - if (mp_cmp_d(R->x, 0) == MP_LT) - err = mp_add(R->x, modulus, R->x); + if (mp_isneg(x)) + err = mp_add(x, modulus, x); } - /* Y = Y - X */ + + /* Y = Y - X */ if (err == MP_OKAY) - err = mp_sub(R->y, R->x, R->y); + err = mp_sub(y, x, y); if (err == MP_OKAY) { - if (mp_cmp_d(R->y, 0) == MP_LT) - err = mp_add(R->y, modulus, R->y); + if (mp_isneg(y)) + err = mp_add(y, modulus, y); } /* Y = Y * T1 */ if (err == MP_OKAY) - err = mp_mul(R->y, &t1, R->y); + err = mp_mul(y, t1, y); if (err == MP_OKAY) - err = mp_montgomery_reduce(R->y, modulus, *mp); + err = mp_montgomery_reduce(y, modulus, mp); /* Y = Y - T2 */ if (err == MP_OKAY) - err = mp_sub(R->y, &t2, R->y); + err = mp_sub(y, t2, y); if (err == MP_OKAY) { - if (mp_cmp_d(R->y, 0) == MP_LT) - err = mp_add(R->y, modulus, R->y); + if (mp_isneg(y)) + err = mp_add(y, modulus, y); } - /* clean up */ - mp_clear(&t1); - mp_clear(&t2); +#ifdef ALT_ECC_SIZE + if (err == MP_OKAY) + err = mp_copy(x, R->x); + if (err == MP_OKAY) + err = mp_copy(y, R->y); + if (err == MP_OKAY) + err = mp_copy(z, R->z); +#endif + + /* clean up */ + mp_clear(t1); + mp_clear(t2); + +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif return err; +#else + if (P == NULL || R == NULL || modulus == NULL) + return ECC_BAD_ARG_E; + + (void)a; + (void)mp; + +#ifndef WOLFSSL_SP_NO_256 + if (mp_count_bits(modulus) == 256) { + return sp_ecc_proj_dbl_point_256(P->x, P->y, P->z, R->x, R->y, R->z); + } +#endif +#ifdef WOLFSSL_SP_384 + if (mp_count_bits(modulus) == 384) { + return sp_ecc_proj_dbl_point_384(P->x, P->y, P->z, R->x, R->y, R->z); + } +#endif + return ECC_BAD_ARG_E; +#endif } -#endif /* USE_FAST_MATH */ /** - Map a projective jacbobian point back to affine space + Map a projective Jacobian point back to affine space P [in/out] The point to map modulus The modulus of the field the ECC curve is in mp The "b" value from montgomery_setup() + ct Operation should be constant time. return MP_OKAY on success */ -int ecc_map(ecc_point* P, mp_int* modulus, mp_digit* mp) +int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct) { - mp_int t1; - mp_int t2; +#ifndef WOLFSSL_SP_MATH +#ifdef WOLFSSL_SMALL_STACK + mp_int* t1 = NULL; + mp_int* t2 = NULL; +#ifdef ALT_ECC_SIZE + mp_int* rx = NULL; + mp_int* ry = NULL; + mp_int* rz = NULL; +#endif +#else + mp_int t1[1], t2[1]; +#ifdef ALT_ECC_SIZE + mp_int rx[1], ry[1], rz[1]; +#endif +#endif /* WOLFSSL_SMALL_STACK */ + mp_int *x, *y, *z; int err; - if (P == NULL || mp == NULL || modulus == NULL) + (void)ct; + + if (P == NULL || modulus == NULL) return ECC_BAD_ARG_E; /* 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) { +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (P->key != NULL) { + t1 = P->key->t1; + t2 = P->key->t2; + #ifdef ALT_ECC_SIZE + rx = P->key->x; + ry = P->key->y; + rz = P->key->z; + #endif + } + else +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + { + t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL || t2 == NULL) { + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#ifdef ALT_ECC_SIZE + rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rx == NULL || ry == NULL || rz == NULL) { + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + } +#endif /* WOLFSSL_SMALL_STACK */ + + if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (P->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif return MEMORY_E; } - /* first map z back to normal */ - err = mp_montgomery_reduce(P->z, modulus, *mp); +#ifdef ALT_ECC_SIZE + /* Use local stack variable */ + x = rx; + y = ry; + z = rz; + + if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { + goto done; + } + + if (err == MP_OKAY) + err = mp_copy(P->x, x); + if (err == MP_OKAY) + 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; + y = P->y; + z = P->z; +#endif /* get 1/z */ - if (err == MP_OKAY) - err = mp_invmod(P->z, modulus, &t1); - + if (err == MP_OKAY) { +#if defined(ECC_TIMING_RESISTANT) && defined(USE_FAST_MATH) + if (ct) { + err = mp_invmod_mont_ct(z, modulus, t1, mp); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t1, modulus, mp); + } + else +#endif + { + /* first map z back to normal */ + err = mp_montgomery_reduce(z, modulus, mp); + if (err == MP_OKAY) + err = mp_invmod(z, modulus, t1); + } + } + /* get 1/z^2 and 1/z^3 */ if (err == MP_OKAY) - err = mp_sqr(&t1, &t2); + err = mp_sqr(t1, t2); if (err == MP_OKAY) - err = mp_mod(&t2, modulus, &t2); + err = mp_mod(t2, modulus, t2); if (err == MP_OKAY) - err = mp_mul(&t1, &t2, &t1); + err = mp_mul(t1, t2, t1); if (err == MP_OKAY) - err = mp_mod(&t1, modulus, &t1); + err = mp_mod(t1, modulus, t1); /* multiply against x/y */ if (err == MP_OKAY) - err = mp_mul(P->x, &t2, P->x); + err = mp_mul(x, t2, x); if (err == MP_OKAY) - err = mp_montgomery_reduce(P->x, modulus, *mp); + err = mp_montgomery_reduce(x, modulus, mp); if (err == MP_OKAY) - err = mp_mul(P->y, &t1, P->y); + err = mp_mul(y, t1, y); if (err == MP_OKAY) - err = mp_montgomery_reduce(P->y, modulus, *mp); - + err = mp_montgomery_reduce(y, modulus, mp); + if (err == MP_OKAY) - mp_set(P->z, 1); + err = mp_set(z, 1); + +#ifdef ALT_ECC_SIZE + /* return result */ + 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: +#endif /* clean up */ - mp_clear(&t1); - mp_clear(&t2); + mp_clear(t1); + mp_clear(t2); + +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (P->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif return err; +#else + if (P == NULL || modulus == NULL) + return ECC_BAD_ARG_E; + + (void)mp; + +#ifndef WOLFSSL_SP_NO_256 + if (mp_count_bits(modulus) == 256) { + return sp_ecc_map_256(P->x, P->y, P->z); + } +#endif +#ifdef WOLFSSL_SP_384 + if (mp_count_bits(modulus) == 384) { + return sp_ecc_map_384(P->x, P->y, P->z); + } +#endif + return ECC_BAD_ARG_E; +#endif } +int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) +{ + return ecc_map_ex(P, modulus, mp, 0); +} +#endif /* !WOLFSSL_SP_MATH || WOLFSSL_PUBLIC_ECC_ADD_DBL */ -#ifndef ECC_TIMING_RESISTANT - -/* size of sliding window, don't change this! */ -#define WINSIZE 4 +#if !defined(FREESCALE_LTC_ECC) && !defined(WOLFSSL_STM32_PKA) +#if !defined(FP_ECC) || !defined(WOLFSSL_SP_MATH) /** - Perform a point multiplication + Perform a point multiplication k The scalar to multiply by G The base point R [out] Destination for kG + a ECC curve parameter a modulus The modulus of the field the ECC curve is in map Boolean whether to map back to affine or not (1==map, 0 == leave in projective) @@ -1007,83 +2521,182 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit* mp) */ #ifdef FP_ECC static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* modulus, int map) + mp_int* a, mp_int* modulus, int map, + void* heap) #else -static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, - int map) +int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, + mp_int* a, mp_int* modulus, int map, + void* heap) #endif { - ecc_point *tG, *M[8]; - int i, j, err; - mp_int mu; +#ifndef WOLFSSL_SP_MATH +#ifndef ECC_TIMING_RESISTANT + /* size of sliding window, don't change this! */ + #define WINSIZE 4 + #define M_POINTS 8 + int first = 1, bitbuf = 0, bitcpy = 0, j; +#elif defined(WC_NO_CACHE_RESISTANT) + #define M_POINTS 4 +#else + #define M_POINTS 5 +#endif + + ecc_point *tG, *M[M_POINTS]; + int i, err; +#ifdef WOLFSSL_SMALL_STACK_CACHE + ecc_key key; +#endif +#ifdef WOLFSSL_SMALL_STACK + mp_int* mu = NULL; +#else + mp_int mu[1]; +#endif mp_digit mp; mp_digit buf; - int first = 1, bitbuf = 0, bitcpy = 0, bitcnt = 0, mode = 0, - digidx = 0; + int bitcnt = 0, mode = 0, digidx = 0; - if (k == NULL || G == NULL || R == NULL || modulus == NULL) + if (k == NULL || G == NULL || R == NULL || modulus == NULL) { return ECC_BAD_ARG_E; + } + + /* init variables */ + tG = NULL; + XMEMSET(M, 0, sizeof(M)); +#ifdef WOLFSSL_SMALL_STACK + mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + if (mu == NULL) + return MEMORY_E; +#endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#ifdef ALT_ECC_SIZE + key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#endif + if (key.t1 == NULL || key.t2 == NULL +#ifdef ALT_ECC_SIZE + || key.x == NULL || key.y == NULL || key.z == NULL +#endif + ) { +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); + XFREE(mu, heap, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif /* WOLFSSL_SMALL_STACK_CACHE */ /* init montgomery reduction */ if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) { - return err; +#ifdef WOLFSSL_SMALL_STACK_CACHE +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif + return err; } - if ((err = mp_init(&mu)) != MP_OKAY) { - return err; + + if ((err = mp_init(mu)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK_CACHE +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif + return err; } - if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) { - mp_clear(&mu); - return err; + if ((err = mp_montgomery_calc_normalization(mu, modulus)) != MP_OKAY) { + mp_clear(mu); +#ifdef WOLFSSL_SMALL_STACK_CACHE +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif + return err; } - + /* alloc ram for window temps */ - for (i = 0; i < 8; i++) { - M[i] = ecc_new_point(); + for (i = 0; i < M_POINTS; i++) { + M[i] = wc_ecc_new_point_h(heap); if (M[i] == NULL) { - for (j = 0; j < i; j++) { - ecc_del_point(M[j]); - } - mp_clear(&mu); - return MEMORY_E; + mp_clear(mu); + err = MEMORY_E; goto exit; } +#ifdef WOLFSSL_SMALL_STACK_CACHE + M[i]->key = &key; +#endif } - /* make a copy of G incase R==G */ - tG = ecc_new_point(); + /* make a copy of G in case R==G */ + tG = wc_ecc_new_point_h(heap); if (tG == NULL) err = MEMORY_E; /* tG = G and convert to montgomery */ if (err == MP_OKAY) { - if (mp_cmp_d(&mu, 1) == MP_EQ) { + if (mp_cmp_d(mu, 1) == MP_EQ) { err = mp_copy(G->x, tG->x); if (err == MP_OKAY) err = mp_copy(G->y, tG->y); if (err == MP_OKAY) err = mp_copy(G->z, tG->z); } else { - err = mp_mulmod(G->x, &mu, modulus, tG->x); + err = mp_mulmod(G->x, mu, modulus, tG->x); if (err == MP_OKAY) - err = mp_mulmod(G->y, &mu, modulus, tG->y); + err = mp_mulmod(G->y, mu, modulus, tG->y); if (err == MP_OKAY) - err = mp_mulmod(G->z, &mu, modulus, tG->z); + err = mp_mulmod(G->z, mu, modulus, tG->z); } } - mp_clear(&mu); - + + /* done with mu */ + mp_clear(mu); + +#ifdef WOLFSSL_SMALL_STACK_CACHE + R->key = &key; +#endif +#ifndef ECC_TIMING_RESISTANT + /* calc the M tab, which holds kG for k==8..15 */ /* M[0] == 8G */ if (err == MP_OKAY) - err = ecc_projective_dbl_point(tG, M[0], modulus, &mp); + err = ecc_projective_dbl_point(tG, M[0], a, modulus, mp); if (err == MP_OKAY) - err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp); + err = ecc_projective_dbl_point(M[0], M[0], a, modulus, mp); if (err == MP_OKAY) - err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp); + err = ecc_projective_dbl_point(M[0], M[0], a, modulus, mp); /* now find (8+k)G for k=1..7 */ if (err == MP_OKAY) for (j = 9; j < 16; j++) { - err = ecc_projective_add_point(M[j-9], tG, M[j-8], modulus, &mp); + err = ecc_projective_add_point(M[j-9], tG, M[j-M_POINTS], a, modulus, + mp); if (err != MP_OKAY) break; } @@ -1104,7 +2717,7 @@ static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, break; } buf = get_digit(k, digidx); - bitcnt = (int) DIGIT_BIT; + bitcnt = (int) DIGIT_BIT; --digidx; } @@ -1118,7 +2731,7 @@ static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, /* if the bit is zero and mode == 1 then we double */ if (mode == 1 && i == 0) { - err = ecc_projective_dbl_point(R, R, modulus, &mp); + err = ecc_projective_dbl_point(R, R, a, modulus, mp); if (err != MP_OKAY) break; continue; } @@ -1131,26 +2744,27 @@ static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, /* if this is the first window we do a simple copy */ if (first == 1) { /* R = kG [k = first window] */ - err = mp_copy(M[bitbuf-8]->x, R->x); + err = mp_copy(M[bitbuf-M_POINTS]->x, R->x); if (err != MP_OKAY) break; - err = mp_copy(M[bitbuf-8]->y, R->y); + err = mp_copy(M[bitbuf-M_POINTS]->y, R->y); if (err != MP_OKAY) break; - err = mp_copy(M[bitbuf-8]->z, R->z); + err = mp_copy(M[bitbuf-M_POINTS]->z, R->z); first = 0; } else { /* normal window */ /* ok window is filled so double as required and add */ /* double first */ for (j = 0; j < WINSIZE; j++) { - err = ecc_projective_dbl_point(R, R, modulus, &mp); + err = ecc_projective_dbl_point(R, R, a, modulus, mp); if (err != MP_OKAY) break; } if (err != MP_OKAY) break; /* out of first for(;;) */ - /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranted */ - err = ecc_projective_add_point(R,M[bitbuf-8],R,modulus,&mp); + /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ + err = ecc_projective_add_point(R, M[bitbuf-M_POINTS], R, a, + modulus, mp); } if (err != MP_OKAY) break; /* empty window and reset */ @@ -1167,7 +2781,7 @@ static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, for (j = 0; j < bitcpy; j++) { /* only double if we have had at least one add first */ if (first == 0) { - err = ecc_projective_dbl_point(R, R, modulus, &mp); + err = ecc_projective_dbl_point(R, R, a, modulus, mp); if (err != MP_OKAY) break; } @@ -1186,7 +2800,7 @@ static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, first = 0; } else { /* then add */ - err = ecc_projective_add_point(R, tG, R, modulus, &mp); + err = ecc_projective_add_point(R, tG, R, a, modulus, mp); if (err != MP_OKAY) break; } } @@ -1194,89 +2808,10 @@ static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, } } - /* map R back from projective space */ - if (err == MP_OKAY && map) - err = ecc_map(R, modulus, &mp); - - mp_clear(&mu); - ecc_del_point(tG); - for (i = 0; i < 8; i++) { - ecc_del_point(M[i]); - } - return err; -} - -#undef WINSIZE + #undef WINSIZE #else /* ECC_TIMING_RESISTANT */ -/** - Perform a point multiplication (timing resistant) - k The scalar to multiply by - G The base point - R [out] Destination for kG - modulus The modulus of the field the ECC curve is in - map Boolean whether to map back to affine or not - (1==map, 0 == leave in projective) - return MP_OKAY on success -*/ -#ifdef FP_ECC -static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* modulus, int map) -#else -static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, - int map) -#endif -{ - ecc_point *tG, *M[3]; - int i, j, err; - mp_int mu; - mp_digit mp; - mp_digit buf; - int bitcnt = 0, mode = 0, digidx = 0; - - if (k == NULL || G == NULL || R == NULL || modulus == NULL) - return ECC_BAD_ARG_E; - - /* init montgomery reduction */ - if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) { - return err; - } - if ((err = mp_init(&mu)) != MP_OKAY) { - return err; - } - if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) { - mp_clear(&mu); - return err; - } - - /* alloc ram for window temps */ - for (i = 0; i < 3; i++) { - M[i] = ecc_new_point(); - if (M[i] == NULL) { - for (j = 0; j < i; j++) { - ecc_del_point(M[j]); - } - mp_clear(&mu); - return MEMORY_E; - } - } - - /* make a copy of G incase R==G */ - tG = ecc_new_point(); - if (tG == NULL) - err = MEMORY_E; - - /* tG = G and convert to montgomery */ - if (err == MP_OKAY) { - err = mp_mulmod(G->x, &mu, modulus, tG->x); - if (err == MP_OKAY) - err = mp_mulmod(G->y, &mu, modulus, tG->y); - if (err == MP_OKAY) - err = mp_mulmod(G->z, &mu, modulus, tG->z); - } - mp_clear(&mu); - /* calc the M tab */ /* M[0] == G */ if (err == MP_OKAY) @@ -1288,13 +2823,24 @@ static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, /* M[1] == 2G */ if (err == MP_OKAY) - err = ecc_projective_dbl_point(tG, M[1], modulus, &mp); + err = ecc_projective_dbl_point(tG, M[1], a, modulus, mp); +#ifdef WC_NO_CACHE_RESISTANT + if (err == MP_OKAY) + err = wc_ecc_copy_point(M[0], M[2]); +#else + if (err == MP_OKAY) + err = wc_ecc_copy_point(M[0], M[3]); + if (err == MP_OKAY) + err = wc_ecc_copy_point(M[1], M[4]); +#endif /* setup sliding window */ mode = 0; bitcnt = 1; buf = 0; - digidx = get_digit_count(k) - 1; + digidx = get_digit_count(modulus) - 1; + /* The order MAY be 1 bit longer than the modulus. */ + digidx += (modulus->dp[digidx] >> (DIGIT_BIT-1)); /* perform ops */ if (err == MP_OKAY) { @@ -1305,43 +2851,92 @@ static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, break; } buf = get_digit(k, digidx); - bitcnt = (int) DIGIT_BIT; + bitcnt = (int)DIGIT_BIT; --digidx; } - /* grab the next msb from the ltiplicand */ + /* grab the next msb from the multiplicand */ i = (buf >> (DIGIT_BIT - 1)) & 1; buf <<= 1; - if (mode == 0 && i == 0) { - /* dummy operations */ +#ifdef WC_NO_CACHE_RESISTANT + if (mode == 0) { + /* timing resistant - dummy operations */ if (err == MP_OKAY) - err = ecc_projective_add_point(M[0], M[1], M[2], modulus, - &mp); + err = ecc_projective_add_point(M[1], M[2], M[2], a, modulus, + mp); if (err == MP_OKAY) - err = ecc_projective_dbl_point(M[1], M[2], modulus, &mp); - if (err == MP_OKAY) - continue; + err = ecc_projective_dbl_point(M[2], M[3], a, modulus, mp); } - - if (mode == 0 && i == 1) { - mode = 1; - /* dummy operations */ + else { if (err == MP_OKAY) - err = ecc_projective_add_point(M[0], M[1], M[2], modulus, - &mp); + err = ecc_projective_add_point(M[0], M[1], M[i^1], a, + modulus, mp); if (err == MP_OKAY) - err = ecc_projective_dbl_point(M[1], M[2], modulus, &mp); - if (err == MP_OKAY) - continue; + err = ecc_projective_dbl_point(M[i], M[i], a, modulus, mp); } +#else + if (err == MP_OKAY) + err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus, mp); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->x, i, M[0]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->y, i, M[0]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->z, i, M[0]->z); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->x, i ^ 1, M[1]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->y, i ^ 1, M[1]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->z, i ^ 1, M[1]->z); if (err == MP_OKAY) - err = ecc_projective_add_point(M[0], M[1], M[i^1], modulus, &mp); + err = mp_cond_copy(M[0]->x, i ^ 1, M[2]->x); if (err == MP_OKAY) - err = ecc_projective_dbl_point(M[i], M[i], modulus, &mp); + err = mp_cond_copy(M[0]->y, i ^ 1, M[2]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[0]->z, i ^ 1, M[2]->z); + if (err == MP_OKAY) + err = mp_cond_copy(M[1]->x, i, M[2]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[1]->y, i, M[2]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[1]->z, i, M[2]->z); + + if (err == MP_OKAY) + err = ecc_projective_dbl_point(M[2], M[2], a, modulus, mp); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->x, i ^ 1, M[0]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->y, i ^ 1, M[0]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->z, i ^ 1, M[0]->z); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->x, i, M[1]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->y, i, M[1]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[2]->z, i, M[1]->z); + + if (err == MP_OKAY) + err = mp_cond_copy(M[3]->x, (mode ^ 1) & i, M[0]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[3]->y, (mode ^ 1) & i, M[0]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[3]->z, (mode ^ 1) & i, M[0]->z); + if (err == MP_OKAY) + err = mp_cond_copy(M[4]->x, (mode ^ 1) & i, M[1]->x); + if (err == MP_OKAY) + err = mp_cond_copy(M[4]->y, (mode ^ 1) & i, M[1]->y); + if (err == MP_OKAY) + err = mp_cond_copy(M[4]->z, (mode ^ 1) & i, M[1]->z); +#endif /* WC_NO_CACHE_RESISTANT */ + if (err != MP_OKAY) break; + + mode |= i; } /* end for */ } @@ -1353,56 +2948,96 @@ static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, if (err == MP_OKAY) err = mp_copy(M[0]->z, R->z); - /* map R back from projective space */ - if (err == MP_OKAY && map) - err = ecc_map(R, modulus, &mp); - - /* done */ - mp_clear(&mu); - ecc_del_point(tG); - for (i = 0; i < 3; i++) { - ecc_del_point(M[i]); - } - return err; -} - #endif /* ECC_TIMING_RESISTANT */ + /* map R back from projective space */ + if (err == MP_OKAY && map) + err = ecc_map(R, modulus, mp); +exit: + + /* done */ + wc_ecc_del_point_h(tG, heap); + for (i = 0; i < M_POINTS; i++) { + wc_ecc_del_point_h(M[i], heap); + } +#ifdef WOLFSSL_SMALL_STACK_CACHE + R->key = NULL; #ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif -static void alt_fp_init(fp_int* a) -{ - a->size = FP_SIZE_ECC; - fp_zero(a); + return err; +#else + if (k == NULL || G == NULL || R == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + (void)a; + +#ifndef WOLFSSL_SP_NO_256 + if (mp_count_bits(modulus) == 256) { + return sp_ecc_mulmod_256(k, G, R, map, heap); + } +#endif +#ifdef WOLFSSL_SP_384 + if (mp_count_bits(modulus) == 384) { + return sp_ecc_mulmod_384(k, G, R, map, heap); + } +#endif + return ECC_BAD_ARG_E; +#endif } -#endif /* ALT_ECC_SIZE */ +#endif /* !FP_ECC || !WOLFSSL_SP_MATH */ +#endif /* !FREESCALE_LTC_ECC && !WOLFSSL_STM32_PKA */ + +/** ECC Fixed Point mulmod global + k The multiplicand + G Base point to multiply + R [out] Destination of product + a ECC curve parameter a + modulus The modulus for the curve + map [boolean] If non-zero maps the point back to affine coordinates, + otherwise it's left in jacobian-montgomery form + return MP_OKAY if successful +*/ +int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, int map) +{ + return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); +} + +#endif /* !WOLFSSL_ATECC508A */ /** - Allocate a new ECC point - return A newly allocated point or NULL on error -*/ -ecc_point* ecc_new_point(void) + * use a heap hint when creating new ecc_point + * return an allocated point on success or NULL on failure + */ +ecc_point* wc_ecc_new_point_h(void* heap) { ecc_point* p; - p = (ecc_point*)XMALLOC(sizeof(ecc_point), 0, DYNAMIC_TYPE_ECC); + (void)heap; + + p = (ecc_point*)XMALLOC(sizeof(ecc_point), heap, DYNAMIC_TYPE_ECC); if (p == NULL) { return NULL; } 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, 0, DYNAMIC_TYPE_ECC); + XFREE(p, heap, DYNAMIC_TYPE_ECC); return NULL; } #else @@ -1417,26 +3052,97 @@ ecc_point* ecc_new_point(void) return p; } -/** Free an ECC point from memory - p The point to free + +/** + Allocate a new ECC point + return A newly allocated point or NULL on error */ -void ecc_del_point(ecc_point* p) +ecc_point* wc_ecc_new_point(void) +{ + return wc_ecc_new_point_h(NULL); +} + + +void wc_ecc_del_point_h(ecc_point* p, void* heap) { /* prevents free'ing null arguments */ if (p != NULL) { mp_clear(p->x); mp_clear(p->y); mp_clear(p->z); - XFREE(p, 0, DYNAMIC_TYPE_ECC); + XFREE(p, heap, DYNAMIC_TYPE_ECC); } + (void)heap; +} + + +/** Free an ECC point from memory + p The point to free +*/ +void wc_ecc_del_point(ecc_point* p) +{ + wc_ecc_del_point_h(p, NULL); +} + + +/** Copy the value of a point to an other one + p The point to copy + r The created point +*/ +int wc_ecc_copy_point(ecc_point* p, ecc_point *r) +{ + int ret; + + /* prevents null arguments */ + if (p == NULL || r == NULL) + return ECC_BAD_ARG_E; + + ret = mp_copy(p->x, r->x); + if (ret != MP_OKAY) + return ret; + ret = mp_copy(p->y, r->y); + if (ret != MP_OKAY) + return ret; + ret = mp_copy(p->z, r->z); + if (ret != MP_OKAY) + return ret; + + return MP_OKAY; +} + +/** Compare the value of a point with an other one + a The point to compare + b The other point to compare + + return MP_EQ if equal, MP_LT/MP_GT if not, < 0 in case of error + */ +int wc_ecc_cmp_point(ecc_point* a, ecc_point *b) +{ + int ret; + + /* prevents null arguments */ + if (a == NULL || b == NULL) + return BAD_FUNC_ARG; + + ret = mp_cmp(a->x, b->x); + if (ret != MP_EQ) + return ret; + ret = mp_cmp(a->y, b->y); + if (ret != MP_EQ) + return ret; + ret = mp_cmp(a->z, b->z); + if (ret != MP_EQ) + return ret; + + return MP_EQ; } /** Returns whether an ECC idx is valid or not n The idx number to check return 1 if valid, 0 if not -*/ -static int ecc_is_valid_idx(int n) +*/ +int wc_ecc_is_valid_idx(int n) { int x; @@ -1444,84 +3150,741 @@ static int ecc_is_valid_idx(int n) ; /* -1 is a valid index --- indicating that the domain params were supplied by the user */ - if ((n >= -1) && (n < x)) { + if ((n >= ECC_CUSTOM_IDX) && (n < x)) { return 1; } + return 0; } +int wc_ecc_get_curve_idx(int curve_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[curve_idx].size == 0) { + return ECC_CURVE_INVALID; + } + 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 curve_id) +{ + 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 ( + #ifndef WOLFSSL_ECC_CURVE_STATIC + ecc_sets[curve_idx].name && + #endif + 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 for equality. + * encType is WC_TYPE_UNSIGNED_BIN or WC_TYPE_HEX_STR + * Returns MP_EQ on success, negative on error */ +static int wc_ecc_cmp_param(const char* curveParam, + const byte* param, word32 paramSz, int encType) +{ + int err = MP_OKAY; +#ifdef WOLFSSL_SMALL_STACK + mp_int* a = NULL; + mp_int* b = NULL; +#else + mp_int a[1], b[1]; +#endif + + if (param == NULL || curveParam == NULL) + return BAD_FUNC_ARG; + + if (encType == WC_TYPE_HEX_STR) + return XSTRNCMP(curveParam, (char*) param, paramSz); + +#ifdef WOLFSSL_SMALL_STACK + a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (a == NULL) + return MEMORY_E; + b = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (b == NULL) { + XFREE(a, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + + if ((err = mp_init_multi(a, b, NULL, NULL, NULL, NULL)) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(a, NULL, DYNAMIC_TYPE_ECC); + XFREE(b, NULL, DYNAMIC_TYPE_ECC); + #endif + 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; + } + } + + mp_clear(a); + mp_clear(b); +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_ECC); + XFREE(a, NULL, DYNAMIC_TYPE_ECC); +#endif + + 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, WC_TYPE_UNSIGNED_BIN) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Af, Af, AfSz, + WC_TYPE_UNSIGNED_BIN) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Bf, Bf, BfSz, + WC_TYPE_UNSIGNED_BIN) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].order, order, + orderSz, WC_TYPE_UNSIGNED_BIN) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gx, Gx, GxSz, + WC_TYPE_UNSIGNED_BIN) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gy, Gy, GySz, + WC_TYPE_UNSIGNED_BIN) == MP_EQ) && + (cofactor == ecc_sets[idx].cofactor)) { + break; + } + } + } + + if (ecc_sets[idx].size == 0) + return ECC_CURVE_INVALID; + + return ecc_sets[idx].id; +} + +/* Returns the curve id in ecc_sets[] that corresponds + * to a given domain parameters pointer. + * + * dp domain parameters pointer + * + * return curve id, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_id_from_dp_params(const ecc_set_type* dp) +{ + int idx; + + if (dp == NULL + #ifndef WOLFSSL_ECC_CURVE_STATIC + || dp->prime == NULL || dp->Af == NULL || + dp->Bf == NULL || dp->order == NULL || dp->Gx == NULL || dp->Gy == NULL + #endif + ) { + return BAD_FUNC_ARG; + } + + for (idx = 0; ecc_sets[idx].size != 0; idx++) { + if (dp->size == ecc_sets[idx].size) { + if ((wc_ecc_cmp_param(ecc_sets[idx].prime, (const byte*)dp->prime, + (word32)XSTRLEN(dp->prime), WC_TYPE_HEX_STR) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Af, (const byte*)dp->Af, + (word32)XSTRLEN(dp->Af),WC_TYPE_HEX_STR) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Bf, (const byte*)dp->Bf, + (word32)XSTRLEN(dp->Bf),WC_TYPE_HEX_STR) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].order, (const byte*)dp->order, + (word32)XSTRLEN(dp->order),WC_TYPE_HEX_STR) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gx, (const byte*)dp->Gx, + (word32)XSTRLEN(dp->Gx),WC_TYPE_HEX_STR) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gy, (const byte*)dp->Gy, + (word32)XSTRLEN(dp->Gy),WC_TYPE_HEX_STR) == MP_EQ) && + (dp->cofactor == ecc_sets[idx].cofactor)) { + break; + } + } + } + + if (ecc_sets[idx].size == 0) + return ECC_CURVE_INVALID; + + return ecc_sets[idx].id; +} + +/* Returns the curve id that corresponds to a given OID, + * as listed in ecc_sets[] of ecc.c. + * + * oid OID, from ecc_sets[].name in ecc.c + * len OID len, 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_oid(const byte* oid, word32 len) +{ + int curve_idx; + + if (oid == NULL) + return BAD_FUNC_ARG; + + for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) { + if ( + #ifndef WOLFSSL_ECC_CURVE_STATIC + ecc_sets[curve_idx].oid && + #endif + ecc_sets[curve_idx].oidSz == len && + XMEMCMP(ecc_sets[curve_idx].oid, oid, len) == 0) { + break; + } + } + if (ecc_sets[curve_idx].size == 0) { + WOLFSSL_MSG("ecc_set curve name not found"); + return ECC_CURVE_INVALID; + } + + return ecc_sets[curve_idx].id; +} + +/* Get curve parameters using curve index */ +const ecc_set_type* wc_ecc_get_curve_params(int curve_idx) +{ + const ecc_set_type* ecc_set = NULL; + + if (curve_idx >= 0 && curve_idx < (int)ECC_SET_COUNT) { + ecc_set = &ecc_sets[curve_idx]; + } + return ecc_set; +} + + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) +static WC_INLINE int wc_ecc_alloc_mpint(ecc_key* key, mp_int** mp) +{ + if (key == NULL || mp == NULL) + return BAD_FUNC_ARG; + if (*mp == NULL) { + *mp = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT); + if (*mp == NULL) { + return MEMORY_E; + } + XMEMSET(*mp, 0, sizeof(mp_int)); + } + return 0; +} +static WC_INLINE void wc_ecc_free_mpint(ecc_key* key, mp_int** mp) +{ + if (key && mp && *mp) { + mp_clear(*mp); + XFREE(*mp, key->heap, DYNAMIC_TYPE_BIGINT); + *mp = NULL; + } +} + +static int wc_ecc_alloc_async(ecc_key* key) +{ + int err = wc_ecc_alloc_mpint(key, &key->r); + if (err == 0) + err = wc_ecc_alloc_mpint(key, &key->s); + return err; +} + +static void wc_ecc_free_async(ecc_key* key) +{ + wc_ecc_free_mpint(key, &key->r); + wc_ecc_free_mpint(key, &key->s); +#ifdef HAVE_CAVIUM_V + wc_ecc_free_mpint(key, &key->e); + wc_ecc_free_mpint(key, &key->signK); +#endif /* HAVE_CAVIUM_V */ +} +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + + +#ifdef HAVE_ECC_DHE /** Create an ECC shared secret between two keys - private_key The private ECC key + private_key The private ECC key (heap hint based off of private key) public_key The public key out [out] Destination of the shared secret - Conforms to EC-DH from ANSI X9.63 + Conforms to EC-DH from ANSI X9.63 outlen [in/out] The max size and resulting size of the shared secret return MP_OKAY if successful */ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, word32* outlen) { - word32 x = 0; - ecc_point* result; - mp_int prime; - int err; - + int err; +#if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A) + CRYS_ECDH_TempData_t tempBuff; +#endif if (private_key == NULL || public_key == NULL || out == NULL || - outlen == NULL) + outlen == NULL) { return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (private_key->devId != INVALID_DEVID) { + err = wc_CryptoCb_Ecdh(private_key, public_key, out, outlen); + if (err != CRYPTOCB_UNAVAILABLE) + return err; + /* fall-through when unavailable */ + } +#endif /* 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; } - if (ecc_is_valid_idx(private_key->idx) == 0 || - ecc_is_valid_idx(public_key->idx) == 0) + /* Verify domain params supplied */ + if (wc_ecc_is_valid_idx(private_key->idx) == 0 || + wc_ecc_is_valid_idx(public_key->idx) == 0) { return ECC_BAD_ARG_E; + } - if (XSTRNCMP(private_key->dp->name, public_key->dp->name, ECC_MAXNAME) != 0) + /* Verify curve id matches */ + if (private_key->dp->id != public_key->dp->id) { return ECC_BAD_ARG_E; - - /* make new point */ - result = ecc_new_point(); - if (result == NULL) { - return MEMORY_E; } - if ((err = mp_init(&prime)) != MP_OKAY) { - ecc_del_point(result); - return err; +#ifdef WOLFSSL_ATECC508A + /* For SECP256R1 use hardware */ + if (private_key->dp->id == ECC_SECP256R1) { + err = atmel_ecc_create_pms(private_key->slot, public_key->pubkey_raw, out); + *outlen = private_key->dp->size; } - - err = mp_read_radix(&prime, (char *)private_key->dp->prime, 16); - - if (err == MP_OKAY) - err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime,1); - - if (err == MP_OKAY) { - x = mp_unsigned_bin_size(&prime); - if (*outlen < x) - err = BUFFER_E; + else { + err = NOT_COMPILED_IN; } +#elif defined(WOLFSSL_CRYPTOCELL) - 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; - } + /* generate a secret*/ + err = CRYS_ECDH_SVDP_DH(&public_key->ctx.pubKey, + &private_key->ctx.privKey, + out, + outlen, + &tempBuff); - mp_clear(&prime); - ecc_del_point(result); + if (err != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECDH_SVDP_DH for secret failed"); + return err; + } + +#else + err = wc_ecc_shared_secret_ex(private_key, &public_key->pubkey, out, outlen); +#endif /* WOLFSSL_ATECC508A */ return err; } +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) + +static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, + byte* out, word32* outlen, ecc_curve_spec* curve) +{ + int err; +#ifndef WOLFSSL_SP_MATH + ecc_point* result = NULL; + word32 x = 0; +#endif + mp_int* k = &private_key->k; +#ifdef HAVE_ECC_CDH + mp_int k_lcl; + + /* 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 + +#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); + } + else +#endif +#ifdef WOLFSSL_SP_384 + if (private_key->idx != ECC_CUSTOM_IDX && + ecc_sets[private_key->idx].id == ECC_SECP384R1) { + err = sp_ecc_secret_gen_384(k, point, out, outlen, private_key->heap); + } + else +#endif +#endif +#ifdef WOLFSSL_SP_MATH + { + err = WC_KEY_SIZE_E; + + (void)curve; + } +#else + { + mp_digit mp = 0; + + /* 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; + } + + /* Map in a separate call as this should be constant time */ + err = wc_ecc_mulmod_ex(k, point, result, curve->Af, curve->prime, 0, + private_key->heap); + if (err == MP_OKAY) { + err = mp_montgomery_setup(curve->prime, &mp); + } + if (err == MP_OKAY) { + /* Use constant time map if compiled in */ + err = ecc_map_ex(result, curve->prime, mp, 1); + } + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(curve->prime); + if (*outlen < x || (int)x < mp_unsigned_bin_size(result->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); + } +#endif +#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; + +#if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA) +#ifdef HAVE_CAVIUM_V + /* verify the curve is supported by hardware */ + if (NitroxEccIsCurveSupported(private_key)) +#endif + { + word32 keySz = private_key->dp->size; + + /* sync public key x/y */ + err = wc_mp_to_bigint_sz(&private_key->k, &private_key->k.raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(point->x, &point->x->raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(point->y, &point->y->raw, keySz); + #ifdef HAVE_CAVIUM_V + /* allocate buffer for output */ + if (err == MP_OKAY) + err = wc_ecc_alloc_mpint(private_key, &private_key->e); + if (err == MP_OKAY) + err = wc_bigint_alloc(&private_key->e->raw, + NitroxEccGetSize(private_key)*2); + if (err == MP_OKAY) + err = NitroxEcdh(private_key, + &private_key->k.raw, &point->x->raw, &point->y->raw, + private_key->e->raw.buf, &private_key->e->raw.len, + &curve->prime->raw); + #else + if (err == MP_OKAY) + err = wc_ecc_curve_load(private_key->dp, &curve, ECC_CURVE_FIELD_BF); + 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); + #endif + return err; + } +#elif defined(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; + } +#endif + + /* use sync in other cases */ + err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen, curve); + + return err; +} +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + +int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen) +{ + int err; + DECLARE_CURVE_SPECS(curve, 2); + + if (private_key == NULL || point == NULL || out == NULL || + outlen == NULL) { + return BAD_FUNC_ARG; + } + + /* load curve info */ + ALLOC_CURVE_SPECS(2); + err = wc_ecc_curve_load(private_key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); + if (err != MP_OKAY) { + FREE_CURVE_SPECS(); + return err; + } + +#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); + FREE_CURVE_SPECS(); + + return err; +} + +/** + Create an ECC shared secret between private key and public point + private_key The private ECC key (heap hint based on private key) + point The point to use (public key) + out [out] Destination of the shared secret + Conforms to EC-DH from ANSI X9.63 + outlen [in/out] The max size and resulting size of the shared secret + return MP_OKAY if successful +*/ +int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen) +{ + int err; + + if (private_key == NULL || point == NULL || out == NULL || + outlen == NULL) { + return BAD_FUNC_ARG; + } + + /* type valid? */ + if (private_key->type != ECC_PRIVATEKEY && + private_key->type != ECC_PRIVATEKEY_ONLY) { + return ECC_BAD_ARG_E; + } + + /* Verify domain params supplied */ + if (wc_ecc_is_valid_idx(private_key->idx) == 0) + return ECC_BAD_ARG_E; + + switch(private_key->state) { + case ECC_STATE_NONE: + case ECC_STATE_SHARED_SEC_GEN: + private_key->state = ECC_STATE_SHARED_SEC_GEN; + + err = wc_ecc_shared_secret_gen(private_key, point, out, outlen); + if (err < 0) { + break; + } + FALL_THROUGH; + + case ECC_STATE_SHARED_SEC_RES: + private_key->state = ECC_STATE_SHARED_SEC_RES; + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM_V + /* verify the curve is supported by hardware */ + if (NitroxEccIsCurveSupported(private_key)) { + /* copy output */ + *outlen = private_key->dp->size; + XMEMCPY(out, private_key->e->raw.buf, *outlen); + } + #endif /* HAVE_CAVIUM_V */ + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + err = 0; + break; + + default: + err = BAD_STATE_E; + } /* switch */ + + /* if async pending then return and skip done cleanup below */ + if (err == WC_PENDING_E) { + private_key->state++; + return err; + } + + /* cleanup */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + wc_ecc_free_async(private_key); +#endif + private_key->state = ECC_STATE_NONE; + + return err; +} +#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCELL */ +#endif /* HAVE_ECC_DHE */ + + +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) /* return 1 if point is at infinity, 0 if not, < 0 on error */ -static int ecc_point_is_at_infinity(ecc_point* p) +int wc_ecc_point_is_at_infinity(ecc_point* p) { if (p == NULL) return BAD_FUNC_ARG; @@ -1532,317 +3895,1461 @@ static int ecc_point_is_at_infinity(ecc_point* p) return 0; } - -int wc_ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp); - -/** - Make a new ECC key - rng An active RNG state - keysize The keysize for the new key (in octets from 20 to 65 bytes) - key [out] Destination of the newly created key - return MP_OKAY if successful, - upon error all allocated memory will be freed -*/ -int wc_ecc_make_key(RNG* rng, int keysize, ecc_key* key) +/* generate random and ensure its greater than 0 and less than order */ +int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) { - int x, err; +#ifndef WC_NO_RNG + int err; + byte buf[ECC_MAXSIZE_GEN]; - if (key == NULL || rng == NULL) - return ECC_BAD_ARG_E; + /*generate 8 extra bytes to mitigate bias from the modulo operation below*/ + /*see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)'*/ + size += 8; - /* find key size */ - for (x = 0; (keysize > ecc_sets[x].size) && (ecc_sets[x].size != 0); x++) - ; - keysize = ecc_sets[x].size; + /* make up random string */ + err = wc_RNG_GenerateBlock(rng, buf, size); - if (keysize > ECC_MAXSIZE || ecc_sets[x].size == 0) { - return BAD_FUNC_ARG; - } - err = wc_ecc_make_key_ex(rng, key, &ecc_sets[x]); - key->idx = x; + /* load random buffer data into k */ + if (err == 0) + err = mp_read_unsigned_bin(k, (byte*)buf, size); - return err; + /* the key should be smaller than the order of base point */ + if (err == MP_OKAY) { + if (mp_cmp(k, order) != MP_LT) { + err = mp_mod(k, order, k); + } + } + + /* quick sanity check to make sure we're not dealing with a 0 key */ + if (err == MP_OKAY) { + if (mp_iszero(k) == MP_YES) + err = MP_ZERO_E; + } + + ForceZero(buf, ECC_MAXSIZE); + + return err; +#else + (void)rng; + (void)size; + (void)k; + (void)order; + return NOT_COMPILED_IN; +#endif /* !WC_NO_RNG */ +} +#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCELL */ + +static WC_INLINE void wc_ecc_reset(ecc_key* key) +{ + /* make sure required key variables are reset */ + key->state = ECC_STATE_NONE; } -int wc_ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp) + +/* 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; - ecc_point* base; - mp_int prime; - mp_int order; -#ifdef WOLFSSL_SMALL_STACK - byte* buf; + int err = MP_OKAY; +#ifndef WOLFSSL_ATECC508A +#ifndef WOLFSSL_SP_MATH + ecc_point* base = NULL; +#endif + ecc_point* pub; + DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT); +#endif /* !WOLFSSL_ATECC508A */ + + 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) { + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + 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 + } + + + if (err != MP_OKAY) { + } + else +#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_base_256(&key->k, pub, 1, key->heap); + } + else +#endif +#ifdef WOLFSSL_SP_384 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { + err = sp_ecc_mulmod_base_384(&key->k, pub, 1, key->heap); + } + else +#endif +#endif +#ifdef WOLFSSL_SP_MATH + err = WC_KEY_SIZE_E; #else - byte buf[ECC_MAXSIZE]; + { + mp_digit mp; + + 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) { + /* Map in a separate call as this should be constant time */ + err = wc_ecc_mulmod_ex(&key->k, base, pub, curve->Af, curve->prime, + 0, key->heap); + if (err == MP_MEM) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + err = mp_montgomery_setup(curve->prime, &mp); + } + if (err == MP_OKAY) { + /* Use constant time map if compiled in */ + err = ecc_map_ex(pub, curve->prime, mp, 1); + } + + wc_ecc_del_point_h(base, key->heap); + } #endif - int keysize; - int po_init = 0; /* prime order Init flag for clear */ - - if (key == NULL || rng == NULL || dp == NULL) - return ECC_BAD_ARG_E; - -#ifdef WOLFSSL_SMALL_STACK - buf = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (buf == NULL) - return MEMORY_E; -#endif - - key->idx = -1; - key->dp = dp; - keysize = dp->size; - - /* allocate ram */ - base = NULL; - - /* make up random string */ - err = wc_RNG_GenerateBlock(rng, buf, keysize); - if (err == 0) - buf[0] |= 0x0c; - - /* setup the key variables */ - if (err == 0) { -#ifndef ALT_ECC_SIZE - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, - &key->k, &prime, &order); -#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); - err = mp_init_multi(&key->k, &prime, &order, NULL, NULL, NULL); -#endif - if (err != MP_OKAY) - err = MEMORY_E; - else - po_init = 1; - } - - if (err == MP_OKAY) { - base = ecc_new_point(); - if (base == NULL) - err = MEMORY_E; - } - - /* read in the specs for this key */ - if (err == MP_OKAY) - err = mp_read_radix(&prime, (char *)key->dp->prime, 16); - if (err == MP_OKAY) - err = mp_read_radix(&order, (char *)key->dp->order, 16); - if (err == MP_OKAY) - err = mp_read_radix(base->x, (char *)key->dp->Gx, 16); - if (err == MP_OKAY) - err = mp_read_radix(base->y, (char *)key->dp->Gy, 16); - - if (err == MP_OKAY) - mp_set(base->z, 1); - if (err == MP_OKAY) - err = mp_read_unsigned_bin(&key->k, (byte*)buf, keysize); - - /* the key should be smaller than the order of base point */ - if (err == MP_OKAY) { - if (mp_cmp(&key->k, &order) != MP_LT) - err = mp_mod(&key->k, &order, &key->k); - } - /* make the public key */ - if (err == MP_OKAY) - err = ecc_mulmod(&key->k, base, &key->pubkey, &prime, 1); #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - /* validate the public key, order * pubkey = point at infinity */ - if (err == MP_OKAY) - err = ecc_check_pubkey_order(key, &prime, &order); + /* 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) - key->type = ECC_PRIVATEKEY; + 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 + } - if (err != MP_OKAY) { - /* clean up */ - mp_clear(key->pubkey.x); - mp_clear(key->pubkey.y); - mp_clear(key->pubkey.z); - mp_clear(&key->k); - } - ecc_del_point(base); - if (po_init) { - mp_clear(&prime); - mp_clear(&order); - } + /* free up local curve */ + if (curveIn == NULL) { + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + } - ForceZero(buf, ECC_MAXSIZE); -#ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif +#else + (void)curveIn; + err = NOT_COMPILED_IN; +#endif /* WOLFSSL_ATECC508A */ - return err; + /* change key state if public part is cached */ + if (key->type == ECC_PRIVATEKEY_ONLY && pubOut == NULL) { + key->type = ECC_PRIVATEKEY; + } + + return err; } -/* Setup dynamic pointers is using normal math for proper freeing */ -int wc_ecc_init(ecc_key* key) +/* 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) { - (void)key; + WOLFSSL_ENTER("wc_ecc_make_pub"); -#ifndef USE_FAST_MATH - key->pubkey.x->dp = NULL; - key->pubkey.y->dp = NULL; - key->pubkey.z->dp = NULL; + return wc_ecc_make_pub_ex(key, NULL, pubOut); +} - key->k.dp = NULL; + +WOLFSSL_ABI +int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) +{ + int err; +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) +#ifndef WOLFSSL_SP_MATH + DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT); +#endif +#endif /* !WOLFSSL_ATECC508A */ +#if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A) + const CRYS_ECPKI_Domain_t* pDomain; + CRYS_ECPKI_KG_TempData_t tempBuff; + CRYS_ECPKI_KG_FipsContext_t fipsCtx; + byte ucompressed_key[ECC_MAX_CRYPTO_HW_SIZE*2 + 1]; + word32 raw_size = 0; +#endif + if (key == NULL || rng == NULL) { + 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 WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + err = wc_CryptoCb_MakeEccKey(rng, keysize, key, curve_id); + if (err != CRYPTOCB_UNAVAILABLE) + return err; + /* fall-through when unavailable */ + } #endif -#ifdef ALT_ECC_SIZE - if (mp_init(&key->k) != MP_OKAY) - return MEMORY_E; +#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 + 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; + testDev->eccMake.curve_id = curve_id; + return WC_PENDING_E; + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ +#ifdef WOLFSSL_ATECC508A + if (key->dp->id == ECC_SECP256R1) { + key->type = ECC_PRIVATEKEY; + key->slot = atmel_ecc_alloc(ATMEL_SLOT_ECDHE); + err = atmel_ecc_create_key(key->slot, key->pubkey_raw); + + /* populate key->pubkey */ + if (err == 0 + #ifdef ALT_ECC_SIZE + && key->pubkey.x + #endif + ) { + err = mp_read_unsigned_bin(key->pubkey.x, key->pubkey_raw, + ECC_MAX_CRYPTO_HW_SIZE); + } + if (err == 0 + #ifdef ALT_ECC_SIZE + && key->pubkey.y + #endif + ) { + err = mp_read_unsigned_bin(key->pubkey.y, + key->pubkey_raw + ECC_MAX_CRYPTO_HW_SIZE, + ECC_MAX_CRYPTO_HW_SIZE); + } + } + else { + err = NOT_COMPILED_IN; + } +#elif defined(WOLFSSL_CRYPTOCELL) + + pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id)); + raw_size = (word32)(key->dp->size)*2 + 1; + + /* generate first key pair */ + err = CRYS_ECPKI_GenKeyPair(&wc_rndState, + wc_rndGenVectFunc, + pDomain, + &key->ctx.privKey, + &key->ctx.pubKey, + &tempBuff, + &fipsCtx); + + if (err != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECPKI_GenKeyPair for key pair failed"); + return err; + } + key->type = ECC_PRIVATEKEY; + + err = CRYS_ECPKI_ExportPublKey(&key->ctx.pubKey, + CRYS_EC_PointUncompressed, + &ucompressed_key[0], + &raw_size); + + if (err == SA_SILIB_RET_OK && key->pubkey.x && key->pubkey.y) { + err = mp_read_unsigned_bin(key->pubkey.x, + &ucompressed_key[1], key->dp->size); + if (err == MP_OKAY) { + err = mp_read_unsigned_bin(key->pubkey.y, + &ucompressed_key[1+key->dp->size],key->dp->size); + } + } + raw_size = key->dp->size; + if (err == MP_OKAY) { + err = CRYS_ECPKI_ExportPrivKey(&key->ctx.privKey, + ucompressed_key, + &raw_size); + } + + if (err == SA_SILIB_RET_OK) { + err = mp_read_unsigned_bin(&key->k, ucompressed_key, raw_size); + } + +#else + +#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 +#ifdef WOLFSSL_SP_384 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { + err = sp_ecc_make_key_384(rng, &key->k, &key->pubkey, key->heap); + if (err == MP_OKAY) { + key->type = ECC_PRIVATEKEY; + } + } + else +#endif +#endif /* WOLFSSL_HAVE_SP_ECC */ + + { /* software key gen */ +#ifdef WOLFSSL_SP_MATH + err = WC_KEY_SIZE_E; +#else + + /* setup the key variables */ + err = mp_init(&key->k); + + /* load curve info */ + if (err == MP_OKAY) { + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + 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); + FREE_CURVE_SPECS(); +#endif /* WOLFSSL_SP_MATH */ + } + +#ifdef HAVE_WOLF_BIGINT + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->k, &key->k.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 = wc_mp_to_bigint(key->pubkey.z, &key->pubkey.z->raw); +#endif + +#endif /* WOLFSSL_ATECC508A */ + + return err; +} + +#ifdef ECC_DUMP_OID +/* Optional dump of encoded OID for adding new curves */ +static int mOidDumpDone; +static void wc_ecc_dump_oids(void) +{ + int x; + + if (mOidDumpDone) { + return; + } + + /* find matching OID sum (based on encoded value) */ + for (x = 0; ecc_sets[x].size != 0; x++) { + int i; + byte* oid; + word32 oidSz, sum = 0; + + printf("ECC %s (%d):\n", ecc_sets[x].name, x); + + #ifdef HAVE_OID_ENCODING + byte oidEnc[ECC_MAX_OID_LEN]; + + oid = oidEnc; + oidSz = ECC_MAX_OID_LEN; + + printf("OID: "); + for (i = 0; i < (int)ecc_sets[x].oidSz; i++) { + printf("%d.", ecc_sets[x].oid[i]); + } + printf("\n"); + + EncodeObjectId(ecc_sets[x].oid, ecc_sets[x].oidSz, oidEnc, &oidSz); + #else + oid = (byte*)ecc_sets[x].oid; + oidSz = ecc_sets[x].oidSz; + #endif + + printf("OID Encoded: "); + for (i = 0; i < (int)oidSz; i++) { + printf("0x%02X,", oid[i]); + } + printf("\n"); + + for (i = 0; i < (int)oidSz; i++) { + sum += oid[i]; + } + printf("Sum: %d\n", sum); + + /* validate sum */ + if (ecc_sets[x].oidSum != sum) { + printf(" Sum %d Not Valid!\n", ecc_sets[x].oidSum); + } + } + mOidDumpDone = 1; +} +#endif /* ECC_DUMP_OID */ + + +WOLFSSL_ABI +ecc_key* wc_ecc_key_new(void* heap) +{ + ecc_key* key; + + key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC); + if (key) { + if (wc_ecc_init_ex(key, heap, INVALID_DEVID) != 0) { + XFREE(key, heap, DYNAMIC_TYPE_ECC); + key = NULL; + } + } + + return key; +} + + +WOLFSSL_ABI +void wc_ecc_key_free(ecc_key* key) +{ + if (key) { + void* heap = key->heap; + + wc_ecc_free(key); + ForceZero(key, sizeof(ecc_key)); + XFREE(key, heap, DYNAMIC_TYPE_ECC); + (void)heap; + } +} + + +/** + Make a new ECC key + rng An active RNG state + keysize The keysize for the new key (in octets from 20 to 65 bytes) + key [out] Destination of the newly created key + return MP_OKAY if successful, + upon error all allocated memory will be freed + */ +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); +} + +/* Setup dynamic pointers if using normal math for proper freeing */ +WOLFSSL_ABI +int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) +{ + int ret = 0; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef ECC_DUMP_OID + wc_ecc_dump_oids(); +#endif + + XMEMSET(key, 0, sizeof(ecc_key)); + key->state = ECC_STATE_NONE; + +#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_CB) + key->devId = devId; +#else + (void)devId; +#endif + +#ifdef WOLFSSL_ATECC508A + key->slot = ATECC_INVALID_SLOT; +#else +#ifdef ALT_ECC_SIZE 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); + if (ret != MP_OKAY) { + return MEMORY_E; + } +#else + ret = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, + NULL, NULL); + if (ret != MP_OKAY) { + return MEMORY_E; + } +#endif /* ALT_ECC_SIZE */ +#endif /* WOLFSSL_ATECC508A */ + +#ifdef WOLFSSL_HEAP_TEST + key->heap = (void*)WOLFSSL_HEAP_TEST; +#else + key->heap = heap; #endif +#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); +#endif + +#if defined(WOLFSSL_DSP) + key->handle = -1; +#endif + return ret; +} + +int wc_ecc_init(ecc_key* key) +{ + return wc_ecc_init_ex(key, NULL, INVALID_DEVID); +} + +#ifdef HAVE_PKCS11 +int wc_ecc_init_id(ecc_key* key, unsigned char* id, int len, void* heap, + int devId) +{ + int ret = 0; + + if (key == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0 && (len < 0 || len > ECC_MAX_ID_LEN)) + ret = BUFFER_E; + + if (ret == 0) + ret = wc_ecc_init_ex(key, heap, devId); + + if (ret == 0 && id != NULL && len != 0) { + XMEMCPY(key->id, id, len); + key->idLen = len; + } + + return ret; +} +#endif + +int wc_ecc_set_flags(ecc_key* key, word32 flags) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + key->flags |= flags; return 0; } +static int wc_ecc_get_curve_order_bit_count(const ecc_set_type* dp) +{ + int err; + word32 orderBits; + DECLARE_CURVE_SPECS(curve, 1); + + ALLOC_CURVE_SPECS(1); + err = wc_ecc_curve_load(dp, &curve, ECC_CURVE_FIELD_ORDER); + if (err != 0) { + FREE_CURVE_SPECS(); + return err; + } + orderBits = mp_count_bits(curve->order); + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + return (int)orderBits; +} + +#ifdef HAVE_ECC_SIGN + +#ifndef NO_ASN + +#if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC) || \ + defined(WOLFSSL_CRYPTOCELL) +static int wc_ecc_sign_hash_hw(const byte* in, word32 inlen, + mp_int* r, mp_int* s, byte* out, word32 *outlen, WC_RNG* rng, + ecc_key* key) +{ + int err; +#ifdef PLUTON_CRYPTO_ECC + if (key->devId != INVALID_DEVID) /* use hardware */ +#endif + { + #if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A) + CRYS_ECDSA_SignUserContext_t sigCtxTemp; + word32 raw_sig_size = *outlen; + word32 msgLenInBytes = inlen; + CRYS_ECPKI_HASH_OpMode_t hash_mode; + #endif + word32 keysize = (word32)key->dp->size; + word32 orderBits = wc_ecc_get_curve_order_bit_count(key->dp); + + /* Check args */ + if (keysize > ECC_MAX_CRYPTO_HW_SIZE || *outlen < keysize*2) { + return ECC_BAD_ARG_E; + } + + #if defined(WOLFSSL_ATECC508A) + key->slot = atmel_ecc_alloc(ATMEL_SLOT_DEVICE); + if (key->slot == ATECC_INVALID_SLOT) { + return ECC_BAD_ARG_E; + } + + /* Sign: Result is 32-bytes of R then 32-bytes of S */ + err = atmel_ecc_sign(key->slot, in, out); + if (err != 0) { + return err; + } + #elif defined(PLUTON_CRYPTO_ECC) + { + /* if the input is larger than curve order, we must truncate */ + if ((inlen * WOLFSSL_BIT_SIZE) > orderBits) { + inlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; + } + + /* perform ECC sign */ + word32 raw_sig_size = *outlen; + err = Crypto_EccSign(in, inlen, out, &raw_sig_size); + if (err != CRYPTO_RES_SUCCESS || raw_sig_size != keysize*2){ + return BAD_COND_E; + } + } + #elif defined(WOLFSSL_CRYPTOCELL) + + hash_mode = cc310_hashModeECC(msgLenInBytes); + if (hash_mode == CRYS_ECPKI_HASH_OpModeLast) { + hash_mode = cc310_hashModeECC(keysize); + hash_mode = CRYS_ECPKI_HASH_SHA256_mode; + } + + /* truncate if hash is longer than key size */ + if (msgLenInBytes > keysize) { + msgLenInBytes = keysize; + } + + /* create signature from an input buffer using a private key*/ + err = CRYS_ECDSA_Sign(&wc_rndState, + wc_rndGenVectFunc, + &sigCtxTemp, + &key->ctx.privKey, + hash_mode, + (byte*)in, + msgLenInBytes, + out, + &raw_sig_size); + + if (err != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECDSA_Sign failed"); + return err; + } + #endif + + /* Load R and S */ + err = mp_read_unsigned_bin(r, &out[0], keysize); + if (err != MP_OKAY) { + return err; + } + err = mp_read_unsigned_bin(s, &out[keysize], keysize); + if (err != MP_OKAY) { + return err; + } + + /* Check for zeros */ + if (mp_iszero(r) || mp_iszero(s)) { + return MP_ZERO_E; + } + } +#ifdef PLUTON_CRYPTO_ECC + else { + err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s); + } +#endif + (void)rng; + + return err; +} +#endif /* WOLFSSL_ATECC508A || PLUTON_CRYPTO_ECC || WOLFSSL_CRYPTOCELL */ + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) +static int wc_ecc_sign_hash_async(const byte* in, word32 inlen, byte* out, + word32 *outlen, WC_RNG* rng, ecc_key* key) +{ + int err; + mp_int *r = NULL, *s = NULL; + + if (in == NULL || out == NULL || outlen == NULL || key == NULL || + rng == NULL) { + return ECC_BAD_ARG_E; + } + + err = wc_ecc_alloc_async(key); + if (err != 0) { + return err; + } + r = key->r; + s = key->s; + + switch(key->state) { + case ECC_STATE_NONE: + case ECC_STATE_SIGN_DO: + key->state = ECC_STATE_SIGN_DO; + + if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){ + break; + } + + err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s); + if (err < 0) { + break; + } + + FALL_THROUGH; + + case ECC_STATE_SIGN_ENCODE: + key->state = ECC_STATE_SIGN_ENCODE; + + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM_V + /* Nitrox requires r and s in sep buffer, so split it */ + NitroxEccRsSplit(key, &r->raw, &s->raw); + #endif + #ifndef WOLFSSL_ASYNC_CRYPT_TEST + /* only do this if not simulator, since it overwrites result */ + wc_bigint_to_mp(&r->raw, r); + wc_bigint_to_mp(&s->raw, s); + #endif + } + + /* encoded with DSA header */ + err = StoreECC_DSA_Sig(out, outlen, r, s); + + /* done with R/S */ + mp_clear(r); + mp_clear(s); + break; + + default: + err = BAD_STATE_E; + break; + } + + /* if async pending then return and skip done cleanup below */ + if (err == WC_PENDING_E) { + key->state++; + return err; + } + + /* cleanup */ + wc_ecc_free_async(key); + key->state = ECC_STATE_NONE; + + return err; +} +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + +/** + Sign a message digest + in The message digest to sign + inlen The length of the digest + out [out] The destination for the signature + outlen [in/out] The max size and resulting size of the signature + key A private ECC key + return MP_OKAY if successful + */ +WOLFSSL_ABI +int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, + WC_RNG* rng, ecc_key* key) +{ + int err; +#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(WC_ASYNC_ENABLE_ECC) +#ifdef WOLFSSL_SMALL_STACK + mp_int *r = NULL, *s = NULL; +#else + mp_int r[1], s[1]; +#endif +#endif + + if (in == NULL || out == NULL || outlen == NULL || key == NULL || + rng == NULL) { + return ECC_BAD_ARG_E; + } + +#ifdef WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + err = wc_CryptoCb_EccSign(in, inlen, out, outlen, rng, key); + if (err != CRYPTOCB_UNAVAILABLE) + return err; + /* fall-through when unavailable */ + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + /* handle async cases */ + err = wc_ecc_sign_hash_async(in, inlen, out, outlen, rng, key); +#else + +#ifdef WOLFSSL_SMALL_STACK + r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (r == NULL) + return MEMORY_E; + s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (s == NULL) { + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + XMEMSET(r, 0, sizeof(mp_int)); + XMEMSET(s, 0, sizeof(mp_int)); + + if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){ + #ifdef WOLFSSL_SMALL_STACK + XFREE(s, key->heap, DYNAMIC_TYPE_ECC); + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + #endif + return err; + } + +/* hardware crypto */ +#if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC) || defined(WOLFSSL_CRYPTOCELL) + err = wc_ecc_sign_hash_hw(in, inlen, r, s, out, outlen, rng, key); +#else + err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s); +#endif + if (err < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(s, key->heap, DYNAMIC_TYPE_ECC); + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + #endif + return err; + } + + /* encoded with DSA header */ + err = StoreECC_DSA_Sig(out, outlen, r, s); + + /* cleanup */ + mp_clear(r); + mp_clear(s); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(s, key->heap, DYNAMIC_TYPE_ECC); + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); +#endif +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return err; +} +#endif /* !NO_ASN */ + +#if defined(WOLFSSL_STM32_PKA) +int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, + ecc_key* key, mp_int *r, mp_int *s) +{ + return stm32_ecc_sign_hash_ex(in, inlen, rng, key, r, s); +} +#elif !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) /** Sign a message digest in The message digest to sign inlen The length of the digest - out [out] The destination for the signature - outlen [in/out] The max size and resulting size of the signature key A private ECC key + r [out] The destination for r component of the signature + s [out] The destination for s component of the signature return MP_OKAY if successful */ -int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, - RNG* rng, ecc_key* key) +int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, + ecc_key* key, mp_int *r, mp_int *s) { - mp_int r; - mp_int s; - mp_int e; - mp_int p; - int err; + int err = 0; +#ifndef WOLFSSL_SP_MATH + mp_int* e; +#if (!defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)) && \ + !defined(WOLFSSL_SMALL_STACK) + mp_int e_lcl; +#endif - if (in == NULL || out == NULL || outlen == NULL || key == NULL || rng ==NULL) +#if defined(WOLFSSL_ECDSA_SET_K) || \ + (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + (defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA))) + DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT); +#else + DECLARE_CURVE_SPECS(curve, 1); +#endif +#endif /* !WOLFSSL_SP_MATH */ + + if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL) { 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; } - + /* is the IDX valid ? */ - if (ecc_is_valid_idx(key->idx) != 1) { + if (wc_ecc_is_valid_idx(key->idx) != 1) { return ECC_BAD_ARG_E; } +#ifdef WOLFSSL_SP_MATH +#ifndef WOLFSSL_SP_NO_256 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + #ifndef WOLFSSL_ECDSA_SET_K + return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, NULL, key->heap); + #else + return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->sign_k, + key->heap); + #endif + } +#endif +#ifdef WOLFSSL_SP_384 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { + #ifndef WOLFSSL_ECDSA_SET_K + return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, NULL, key->heap); + #else + return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, key->sign_k, + key->heap); + #endif + } +#endif + return WC_KEY_SIZE_E; +#else +#ifdef WOLFSSL_HAVE_SP_ECC + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + 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) { + #ifndef WOLFSSL_ECDSA_SET_K + return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, NULL, + key->heap); + #else + return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->sign_k, + key->heap); + #endif + } +#endif +#ifdef WOLFSSL_SP_384 + if (key->idx != ECC_CUSTOM_IDX && + ecc_sets[key->idx].id == ECC_SECP384R1) { + #ifndef WOLFSSL_ECDSA_SET_K + return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, NULL, + key->heap); + #else + return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, key->sign_k, + key->heap); + #endif + } +#endif + } +#endif /* 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) { + 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 + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V) + err = wc_ecc_alloc_mpint(key, &key->e); + if (err != 0) { + return err; + } + e = key->e; +#elif !defined(WOLFSSL_SMALL_STACK) + e = &e_lcl; +#else + e = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (e == NULL) { + return MEMORY_E; + } +#endif + /* get the hash and load it as a bignum into 'e' */ /* init the bignums */ - if ((err = mp_init_multi(&r, &s, &p, &e, NULL, NULL)) != MP_OKAY) { + if ((err = mp_init(e)) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(e, key->heap, DYNAMIC_TYPE_ECC); + #endif return err; } - err = mp_read_radix(&p, (char *)key->dp->order, 16); + /* load curve info */ +#if defined(WOLFSSL_ECDSA_SET_K) + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); +#else + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + (defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + } + else + #endif + { + ALLOC_CURVE_SPECS(1); + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER); + } +#endif + + /* load digest into e */ if (err == MP_OKAY) { /* we may need to truncate if hash is longer than key size */ - word32 orderBits = mp_count_bits(&p); + word32 orderBits = mp_count_bits(curve->order); /* truncate down to byte size, may be all that's needed */ - if ( (WOLFSSL_BIT_SIZE * inlen) > orderBits) - inlen = (orderBits + WOLFSSL_BIT_SIZE - 1)/WOLFSSL_BIT_SIZE; - err = mp_read_unsigned_bin(&e, (byte*)in, inlen); + if ((WOLFSSL_BIT_SIZE * inlen) > orderBits) + inlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; + err = mp_read_unsigned_bin(e, (byte*)in, inlen); /* may still need bit truncation too */ if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * inlen) > orderBits) - mp_rshb(&e, WOLFSSL_BIT_SIZE - (orderBits & 0x7)); + mp_rshb(e, WOLFSSL_BIT_SIZE - (orderBits & 0x7)); } /* make up a key and export the public copy */ if (err == MP_OKAY) { - int loop_check = 0; - ecc_key pubkey; - wc_ecc_init(&pubkey); - for (;;) { - if (++loop_check > 64) { - err = RNG_FAILURE_E; - break; + int loop_check = 0; + #ifdef WOLFSSL_SMALL_STACK + ecc_key* pubkey; + #else + ecc_key pubkey[1]; + #endif + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA) + #ifdef HAVE_CAVIUM_V + if (NitroxEccIsCurveSupported(key)) + #endif + { + word32 keySz = key->dp->size; + mp_int* k; + #ifdef HAVE_CAVIUM_V + err = wc_ecc_alloc_mpint(key, &key->signK); + if (err != 0) + return err; + k = key->signK; + #else + mp_int k_lcl; + k = &k_lcl; + #endif + + err = mp_init(k); + + /* make sure r and s are allocated */ + #ifdef HAVE_CAVIUM_V + /* Nitrox V needs single buffer for R and S */ + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->r->raw, NitroxEccGetSize(key)*2); + /* Nitrox V only needs Prime and Order */ + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_ORDER)); + #else + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->r->raw, key->dp->size); + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + #endif + 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_sz(e, &e->raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(&key->k, &key->k.raw, keySz); + 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_sz(k, &k->raw, keySz); + + #ifdef HAVE_CAVIUM_V + if (err == MP_OKAY) + err = NitroxEcdsaSign(key, &e->raw, &key->k.raw, &k->raw, + &r->raw, &s->raw, &curve->prime->raw, &curve->order->raw); + #else + 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); + #endif + + #ifndef HAVE_CAVIUM_V + mp_clear(e); + mp_clear(k); + #endif + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + + return err; } - err = wc_ecc_make_key_ex(rng, &pubkey, key->dp); - if (err != MP_OKAY) break; - - /* find r = x1 mod n */ - err = mp_mod(pubkey.pubkey.x, &p, &r); - if (err != MP_OKAY) break; - - if (mp_iszero(&r) == MP_YES) { - mp_clear(pubkey.pubkey.x); - mp_clear(pubkey.pubkey.y); - mp_clear(pubkey.pubkey.z); - mp_clear(&pubkey.k); - } - else { - /* find s = (e + xr)/k */ - err = mp_invmod(&pubkey.k, &p, &pubkey.k); - if (err != MP_OKAY) break; - - err = mp_mulmod(&key->k, &r, &p, &s); /* s = xr */ - if (err != MP_OKAY) break; - - err = mp_add(&e, &s, &s); /* s = e + xr */ - if (err != MP_OKAY) break; - - err = mp_mod(&s, &p, &s); /* s = e + xr */ - if (err != MP_OKAY) break; - - err = mp_mulmod(&s, &pubkey.k, &p, &s); /* s = (e + xr)/k */ - if (err != MP_OKAY) break; - - if (mp_iszero(&s) == MP_NO) - break; - } + #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */ + } + #endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + + #ifdef WOLFSSL_SMALL_STACK + pubkey = (ecc_key*)XMALLOC(sizeof(ecc_key), key->heap, DYNAMIC_TYPE_ECC); + if (pubkey == NULL) + err = MEMORY_E; + #endif + + /* don't use async for key, since we don't support async return here */ + if (err == MP_OKAY && (err = wc_ecc_init_ex(pubkey, key->heap, + INVALID_DEVID)) == MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + mp_int* b = NULL; + #else + mp_int b[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, + DYNAMIC_TYPE_ECC); + if (b == NULL) + err = MEMORY_E; + } + #endif + + if (err == MP_OKAY) { + err = mp_init(b); + } + + #ifdef WOLFSSL_CUSTOM_CURVES + /* if custom curve, apply params to pubkey */ + if (err == MP_OKAY && key->idx == ECC_CUSTOM_IDX) { + err = wc_ecc_set_custom_curve(pubkey, key->dp); + } + #endif + + if (err == MP_OKAY) { + /* Generate blinding value - non-zero value. */ + do { + if (++loop_check > 64) { + err = RNG_FAILURE_E; + break; + } + + err = wc_ecc_gen_k(rng, key->dp->size, b, curve->order); + } + while (err == MP_ZERO_E); + loop_check = 0; + } + + for (; err == MP_OKAY;) { + if (++loop_check > 64) { + err = RNG_FAILURE_E; + break; + } + #ifdef WOLFSSL_ECDSA_SET_K + if (key->sign_k != NULL) { + if (loop_check > 1) { + err = RNG_FAILURE_E; + break; + } + + err = mp_copy(key->sign_k, &pubkey->k); + if (err != MP_OKAY) break; + + mp_forcezero(key->sign_k); + mp_free(key->sign_k); + XFREE(key->sign_k, key->heap, DYNAMIC_TYPE_ECC); + key->sign_k = NULL; + err = wc_ecc_make_pub_ex(pubkey, curve, NULL); + } + else + #endif + { + err = wc_ecc_make_key_ex(rng, key->dp->size, pubkey, + key->dp->id); + } + if (err != MP_OKAY) break; + + /* find r = x1 mod n */ + err = mp_mod(pubkey->pubkey.x, curve->order, r); + if (err != MP_OKAY) break; + + if (mp_iszero(r) == MP_YES) { + #ifndef ALT_ECC_SIZE + mp_clear(pubkey->pubkey.x); + mp_clear(pubkey->pubkey.y); + mp_clear(pubkey->pubkey.z); + #endif + mp_forcezero(&pubkey->k); + } + else { + /* find s = (e + xr)/k + = b.(e/k.b + x.r/k.b) */ + + /* k = k.b */ + err = mp_mulmod(&pubkey->k, b, curve->order, &pubkey->k); + if (err != MP_OKAY) break; + + /* k = 1/k.b */ + err = mp_invmod(&pubkey->k, curve->order, &pubkey->k); + if (err != MP_OKAY) break; + + /* s = x.r */ + err = mp_mulmod(&key->k, r, curve->order, s); + if (err != MP_OKAY) break; + + /* s = x.r/k.b */ + err = mp_mulmod(&pubkey->k, s, curve->order, s); + if (err != MP_OKAY) break; + + /* e = e/k.b */ + err = mp_mulmod(&pubkey->k, e, curve->order, e); + if (err != MP_OKAY) break; + + /* s = e/k.b + x.r/k.b + = (e + x.r)/k.b */ + err = mp_add(e, s, s); + if (err != MP_OKAY) break; + + /* s = b.(e + x.r)/k.b + = (e + x.r)/k */ + err = mp_mulmod(s, b, curve->order, s); + if (err != MP_OKAY) break; + + /* s = (e + xr)/k */ + err = mp_mod(s, curve->order, s); + if (err != MP_OKAY) break; + + if (mp_iszero(s) == MP_NO) + break; + } + } + mp_clear(b); + mp_free(b); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, key->heap, DYNAMIC_TYPE_ECC); + #endif + wc_ecc_free(pubkey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(pubkey, key->heap, DYNAMIC_TYPE_ECC); + #endif } - wc_ecc_free(&pubkey); } - /* store as SEQUENCE { r, s -- integer } */ - if (err == MP_OKAY) - err = StoreECC_DSA_Sig(out, outlen, &r, &s); - - mp_clear(&r); - mp_clear(&s); - mp_clear(&p); - mp_clear(&e); + mp_clear(e); + wc_ecc_curve_free(curve); +#ifdef WOLFSSL_SMALL_STACK + XFREE(e, key->heap, DYNAMIC_TYPE_ECC); +#endif + FREE_CURVE_SPECS(); +#endif /* WOLFSSL_SP_MATH */ return err; } +#ifdef WOLFSSL_ECDSA_SET_K +int wc_ecc_sign_set_k(const byte* k, word32 klen, ecc_key* key) +{ + int ret = 0; + + if (k == NULL || klen == 0 || key == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if (key->sign_k == NULL) { + key->sign_k = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, + DYNAMIC_TYPE_ECC); + if (key->sign_k == NULL) { + ret = MEMORY_E; + } + } + } + + if (ret == 0) { + ret = mp_init(key->sign_k); + } + if (ret == 0) { + ret = mp_read_unsigned_bin(key->sign_k, k, klen); + } + + return ret; +} +#endif /* WOLFSSL_ECDSA_SET_K */ +#endif /* WOLFSSL_ATECC508A && WOLFSSL_CRYPTOCELL*/ + +#endif /* HAVE_ECC_SIGN */ + +#ifdef WOLFSSL_CUSTOM_CURVES +void wc_ecc_free_curve(const ecc_set_type* curve, void* heap) +{ +#ifndef WOLFSSL_ECC_CURVE_STATIC + if (curve->prime != NULL) + XFREE((void*)curve->prime, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (curve->Af != NULL) + XFREE((void*)curve->Af, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (curve->Bf != NULL) + XFREE((void*)curve->Bf, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (curve->order != NULL) + XFREE((void*)curve->order, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (curve->Gx != NULL) + XFREE((void*)curve->Gx, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (curve->Gy != NULL) + XFREE((void*)curve->Gy, heap, DYNAMIC_TYPE_ECC_BUFFER); +#endif + + XFREE((void*)curve, heap, DYNAMIC_TYPE_ECC_BUFFER); + + (void)heap; +} +#endif /* WOLFSSL_CUSTOM_CURVES */ /** Free an ECC key from memory key The key you wish to free */ -void wc_ecc_free(ecc_key* key) +WOLFSSL_ABI +int wc_ecc_free(ecc_key* key) { - if (key == NULL) - return; + if (key == NULL) { + return 0; + } - mp_clear(key->pubkey.x); - mp_clear(key->pubkey.y); - mp_clear(key->pubkey.z); - mp_clear(&key->k); -} - - -#ifdef USE_FAST_MATH - #define GEN_MEM_ERR FP_MEM -#else - #define GEN_MEM_ERR MP_MEM +#ifdef WOLFSSL_ECDSA_SET_K + if (key->sign_k != NULL) { + mp_forcezero(key->sign_k); + mp_free(key->sign_k); + XFREE(key->sign_k, key->heap, DYNAMIC_TYPE_ECC); + } #endif +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + #ifdef WC_ASYNC_ENABLE_ECC + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC); + #endif + wc_ecc_free_async(key); +#endif + +#ifdef WOLFSSL_ATECC508A + atmel_ecc_free(key->slot); + key->slot = ATECC_INVALID_SLOT; +#endif /* WOLFSSL_ATECC508A */ + + mp_clear(key->pubkey.x); + mp_clear(key->pubkey.y); + mp_clear(key->pubkey.z); + + mp_forcezero(&key->k); + +#ifdef WOLFSSL_CUSTOM_CURVES + if (key->deallocSet && key->dp != NULL) + wc_ecc_free_curve(key->dp, key->heap); +#endif + + return 0; +} + +#if !defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) #ifdef ECC_SHAMIR /** Computes kA*A + kB*B = C using Shamir's Trick @@ -1851,47 +5358,97 @@ void wc_ecc_free(ecc_key* key) B Second point to multiply kB What to multiple B by C [out] Destination point (can overlap with A or B) - modulus Modulus for curve + a ECC curve parameter a + modulus Modulus for curve return MP_OKAY on success */ #ifdef FP_ECC static int normal_ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, - ecc_point* C, mp_int* modulus) + ecc_point* C, mp_int* a, mp_int* modulus, + void* heap) #else -static int ecc_mul2add(ecc_point* A, mp_int* kA, +int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, - ecc_point* C, mp_int* modulus) + ecc_point* C, mp_int* a, mp_int* modulus, + void* heap) #endif { - ecc_point* precomp[16]; - unsigned bitbufA, bitbufB, lenA, lenB, len, x, y, nA, nB, nibble; +#ifdef WOLFSSL_SMALL_STACK_CACHE + ecc_key key; +#endif +#ifdef WOLFSSL_SMALL_STACK + ecc_point** precomp = NULL; +#else + ecc_point* precomp[SHAMIR_PRECOMP_SZ]; +#endif + unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble; unsigned char* tA; unsigned char* tB; - int err = MP_OKAY, first; - int muInit = 0; - int tableInit = 0; - mp_digit mp; - mp_int mu; - - /* argchks */ - if (A == NULL || kA == NULL || B == NULL || kB == NULL || C == NULL || - modulus == NULL) - return ECC_BAD_ARG_E; + int err = MP_OKAY, first, x, y; + mp_digit mp = 0; + /* argchks */ + if (A == NULL || kA == NULL || B == NULL || kB == NULL || C == NULL || + modulus == NULL) { + return ECC_BAD_ARG_E; + } /* allocate memory */ - tA = (unsigned char*)XMALLOC(ECC_BUFSIZE, NULL, 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + tB = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_ECC_BUFFER); if (tB == NULL) { - XFREE(tA, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); return GEN_MEM_ERR; } +#ifdef WOLFSSL_SMALL_STACK + precomp = (ecc_point**)XMALLOC(sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ, heap, + DYNAMIC_TYPE_ECC_BUFFER); + if (precomp == NULL) { + XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); + return GEN_MEM_ERR; + } +#endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#ifdef ALT_ECC_SIZE + key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#endif + if (key.t1 == NULL || key.t2 == NULL +#ifdef ALT_ECC_SIZE + || key.x == NULL || key.y == NULL || key.z == NULL +#endif + ) { +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); + XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); + return MEMORY_E; + } + C->key = &key; +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + + /* init variables */ XMEMSET(tA, 0, ECC_BUFSIZE); XMEMSET(tB, 0, ECC_BUFSIZE); +#ifndef WOLFSSL_SMALL_STACK + XMEMSET(precomp, 0, sizeof(precomp)); +#else + XMEMSET(precomp, 0, sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ); +#endif /* get sizes */ lenA = mp_unsigned_bin_size(kA); @@ -1900,7 +5457,7 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, /* sanity check */ if ((lenA > ECC_BUFSIZE) || (lenB > ECC_BUFSIZE)) { - err = BAD_FUNC_ARG; + err = BAD_FUNC_ARG; } if (err == MP_OKAY) { @@ -1913,75 +5470,92 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, /* allocate the table */ if (err == MP_OKAY) { - for (x = 0; x < 16; x++) { - precomp[x] = ecc_new_point(); + for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) { + precomp[x] = wc_ecc_new_point_h(heap); if (precomp[x] == NULL) { - for (y = 0; y < x; ++y) { - ecc_del_point(precomp[y]); - } err = GEN_MEM_ERR; break; } + #ifdef WOLFSSL_SMALL_STACK_CACHE + precomp[x]->key = &key; + #endif } } } if (err == MP_OKAY) - tableInit = 1; + /* init montgomery reduction */ + err = mp_montgomery_setup(modulus, &mp); - if (err == MP_OKAY) - /* init montgomery reduction */ - err = mp_montgomery_setup(modulus, &mp); + if (err == MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + mp_int* mu; + #else + mp_int mu[1]; + #endif + #ifdef WOLFSSL_SMALL_STACK + mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + if (mu == NULL) + err = MEMORY_E; + #endif + if (err == MP_OKAY) { + err = mp_init(mu); + } + if (err == MP_OKAY) { + err = mp_montgomery_calc_normalization(mu, modulus); - if (err == MP_OKAY) - err = mp_init(&mu); - if (err == MP_OKAY) - muInit = 1; + if (err == MP_OKAY) + /* copy ones ... */ + err = mp_mulmod(A->x, mu, modulus, precomp[1]->x); - if (err == MP_OKAY) - err = mp_montgomery_calc_normalization(&mu, modulus); + if (err == MP_OKAY) + err = mp_mulmod(A->y, mu, modulus, precomp[1]->y); + if (err == MP_OKAY) + err = mp_mulmod(A->z, mu, modulus, precomp[1]->z); - if (err == MP_OKAY) - /* copy ones ... */ - err = mp_mulmod(A->x, &mu, modulus, precomp[1]->x); + if (err == MP_OKAY) + err = mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x); + if (err == MP_OKAY) + err = mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y); + if (err == MP_OKAY) + err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z); - if (err == MP_OKAY) - err = mp_mulmod(A->y, &mu, modulus, precomp[1]->y); - if (err == MP_OKAY) - err = mp_mulmod(A->z, &mu, modulus, precomp[1]->z); - - if (err == MP_OKAY) - err = mp_mulmod(B->x, &mu, modulus, precomp[1<<2]->x); - if (err == MP_OKAY) - err = mp_mulmod(B->y, &mu, modulus, precomp[1<<2]->y); - if (err == MP_OKAY) - err = mp_mulmod(B->z, &mu, modulus, precomp[1<<2]->z); + /* done with mu */ + mp_clear(mu); + } + #ifdef WOLFSSL_SMALL_STACK + if (mu != NULL) { + XFREE(mu, heap, DYNAMIC_TYPE_ECC); + } + #endif + } if (err == MP_OKAY) /* precomp [i,0](A + B) table */ - err = ecc_projective_dbl_point(precomp[1], precomp[2], modulus, &mp); + err = ecc_projective_dbl_point(precomp[1], precomp[2], a, modulus, mp); if (err == MP_OKAY) err = ecc_projective_add_point(precomp[1], precomp[2], precomp[3], - modulus, &mp); + a, modulus, mp); if (err == MP_OKAY) /* precomp [0,i](A + B) table */ - err = ecc_projective_dbl_point(precomp[1<<2], precomp[2<<2], modulus, &mp); + err = ecc_projective_dbl_point(precomp[1<<2], precomp[2<<2], a, modulus, mp); if (err == MP_OKAY) err = ecc_projective_add_point(precomp[1<<2], precomp[2<<2], precomp[3<<2], - modulus, &mp); + a, modulus, mp); if (err == MP_OKAY) { /* precomp [i,j](A + B) table (i != 0, j != 0) */ for (x = 1; x < 4; x++) { - for (y = 1; y < 4; y++) { - if (err == MP_OKAY) - err = ecc_projective_add_point(precomp[x], precomp[(y<<2)], - precomp[x+(y<<2)], modulus, &mp); + for (y = 1; y < 4; y++) { + if (err == MP_OKAY) { + err = ecc_projective_add_point(precomp[x], precomp[(y<<2)], + precomp[x+(y<<2)], a, modulus, mp); } - } - } + } + } + } if (err == MP_OKAY) { nibble = 3; @@ -1990,20 +5564,21 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, bitbufB = tB[0]; /* for every byte of the multiplicands */ - for (x = -1;; ) { + for (x = 0;; ) { /* grab a nibble */ if (++nibble == 4) { - ++x; if (x == len) break; + if (x == (int)len) break; bitbufA = tA[x]; bitbufB = tB[x]; nibble = 0; + x++; } /* extract two bits from both, shift/update */ nA = (bitbufA >> 6) & 0x03; nB = (bitbufB >> 6) & 0x03; - bitbufA = (bitbufA << 2) & 0xFF; - bitbufB = (bitbufB << 2) & 0xFF; + bitbufA = (bitbufA << 2) & 0xFF; + bitbufB = (bitbufB << 2) & 0xFF; /* if both zero, if first, continue */ if ((nA == 0) && (nB == 0) && (first == 1)) { @@ -2014,9 +5589,9 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, if (first == 0) { /* double twice */ if (err == MP_OKAY) - err = ecc_projective_dbl_point(C, C, modulus, &mp); + err = ecc_projective_dbl_point(C, C, a, modulus, mp); if (err == MP_OKAY) - err = ecc_projective_dbl_point(C, C, modulus, &mp); + err = ecc_projective_dbl_point(C, C, a, modulus, mp); else break; } @@ -2040,165 +5615,553 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, /* if not first, add from table */ if (err == MP_OKAY) err = ecc_projective_add_point(C, precomp[nA + (nB<<2)], C, - modulus, &mp); - else + a, modulus, mp); + if (err != MP_OKAY) break; + if (mp_iszero(C->z)) { + /* When all zero then should have done an add */ + if (mp_iszero(C->x) && mp_iszero(C->y)) { + err = ecc_projective_dbl_point(precomp[nA + (nB<<2)], C, + a, modulus, mp); + if (err != MP_OKAY) + break; + } + /* When only Z zero then result is infinity */ + else { + err = mp_set(C->x, 0); + if (err != MP_OKAY) + break; + err = mp_set(C->y, 0); + if (err != MP_OKAY) + break; + err = mp_set(C->z, 1); + if (err != MP_OKAY) + break; + first = 1; + } + } } } } } + /* reduce to affine */ if (err == MP_OKAY) - /* reduce to affine */ - err = ecc_map(C, modulus, &mp); + err = ecc_map(C, modulus, mp); /* clean up */ - if (muInit) - mp_clear(&mu); - - if (tableInit) { - for (x = 0; x < 16; x++) { - ecc_del_point(precomp[x]); - } + for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) { + wc_ecc_del_point_h(precomp[x], heap); } - ForceZero(tA, ECC_BUFSIZE); - ForceZero(tB, ECC_BUFSIZE); - XFREE(tA, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tB, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return err; + ForceZero(tA, ECC_BUFSIZE); + ForceZero(tB, ECC_BUFSIZE); +#ifdef WOLFSSL_SMALL_STACK_CACHE +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); + C->key = NULL; +#endif +#ifdef WOLFSSL_SMALL_STACK + XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER); +#endif + XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); + + return err; } - #endif /* ECC_SHAMIR */ +#endif /* !WOLFSSL_SP_MATH && !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCEL*/ - -/* verify +#ifdef HAVE_ECC_VERIFY +#ifndef NO_ASN +/* verify * * w = s^-1 mod n - * u1 = xw + * u1 = xw * u2 = rw * X = u1*G + u2*Q * v = X_x1 mod n * accept if v == r */ +/** + Verify an ECC signature + sig The signature to verify + siglen The length of the signature (octets) + hash The hash (message digest) that was signed + hashlen The length of the hash (octets) + 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* res, ecc_key* key) +{ + int err; + mp_int *r = NULL, *s = NULL; +#if (!defined(WOLFSSL_ASYNC_CRYPT) || !defined(WC_ASYNC_ENABLE_ECC)) && \ + !defined(WOLFSSL_SMALL_STACK) + mp_int r_lcl, s_lcl; +#endif + + if (sig == NULL || hash == NULL || res == NULL || key == NULL) { + return ECC_BAD_ARG_E; + } + +#ifdef WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + err = wc_CryptoCb_EccVerify(sig, siglen, hash, hashlen, res, key); + if (err != CRYPTOCB_UNAVAILABLE) + return err; + /* fall-through when unavailable */ + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + err = wc_ecc_alloc_async(key); + if (err != 0) + return err; + r = key->r; + s = key->s; +#else + #ifndef WOLFSSL_SMALL_STACK + r = &r_lcl; + s = &s_lcl; + #else + r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (r == NULL) + return MEMORY_E; + s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (s == NULL) { + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif + XMEMSET(r, 0, sizeof(mp_int)); + XMEMSET(s, 0, sizeof(mp_int)); +#endif /* WOLFSSL_ASYNC_CRYPT */ + + switch (key->state) { + case ECC_STATE_NONE: + case ECC_STATE_VERIFY_DECODE: + key->state = ECC_STATE_VERIFY_DECODE; + + /* default to invalid signature */ + *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. */ + /* decode DSA header */ + err = DecodeECC_DSA_Sig(sig, siglen, r, s); + if (err < 0) { + break; + } + FALL_THROUGH; + + case ECC_STATE_VERIFY_DO: + key->state = ECC_STATE_VERIFY_DO; + + err = wc_ecc_verify_hash_ex(r, s, hash, hashlen, res, key); + + #ifndef WOLFSSL_ASYNC_CRYPT + /* done with R/S */ + mp_clear(r); + mp_clear(s); + #ifdef WOLFSSL_SMALL_STACK + XFREE(s, key->heap, DYNAMIC_TYPE_ECC); + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + r = NULL; + s = NULL; + #endif + #endif + + if (err < 0) { + break; + } + FALL_THROUGH; + + case ECC_STATE_VERIFY_RES: + key->state = ECC_STATE_VERIFY_RES; + err = 0; + break; + + default: + err = BAD_STATE_E; + } + + /* if async pending then return and skip done cleanup below */ + if (err == WC_PENDING_E) { + key->state++; + return err; + } + + /* cleanup */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + wc_ecc_free_async(key); +#elif defined(WOLFSSL_SMALL_STACK) + XFREE(s, key->heap, DYNAMIC_TYPE_ECC); + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + r = NULL; + s = NULL; +#endif + + key->state = ECC_STATE_NONE; + + return err; +} +#endif /* !NO_ASN */ + + /** Verify an ECC signature - sig The signature to verify - siglen The length of the signature (octets) + r The signature R component to verify + 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(const byte* sig, word32 siglen, const byte* hash, - word32 hashlen, int* stat, ecc_key* key) -{ - ecc_point *mG, *mQ; - mp_int r; - mp_int s; - mp_int v; - mp_int w; - mp_int u1; - mp_int u2; - mp_int e; - mp_int p; - mp_int m; - int err; - if (sig == NULL || hash == NULL || stat == NULL || key == NULL) - return ECC_BAD_ARG_E; +int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, + word32 hashlen, int* res, ecc_key* key) +#if defined(WOLFSSL_STM32_PKA) +{ + return stm32_ecc_verify_hash_ex(r, s, hash, hashlen, res, key); +} +#else +{ + int err; + word32 keySz; +#ifdef WOLFSSL_ATECC508A + byte sigRS[ATECC_KEY_SIZE*2]; +#elif defined(WOLFSSL_CRYPTOCELL) + byte sigRS[ECC_MAX_CRYPTO_HW_SIZE*2]; + CRYS_ECDSA_VerifyUserContext_t sigCtxTemp; + word32 msgLenInBytes = hashlen; + CRYS_ECPKI_HASH_OpMode_t hash_mode; +#elif !defined(WOLFSSL_SP_MATH) || defined(FREESCALE_LTC_ECC) + int did_init = 0; + ecc_point *mG = NULL, *mQ = NULL; + #ifdef WOLFSSL_SMALL_STACK + mp_int* v = NULL; + mp_int* w = NULL; + mp_int* u1 = NULL; + mp_int* u2 = NULL; + #if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) + mp_int* e_lcl = NULL; + #endif + #else /* WOLFSSL_SMALL_STACK */ + mp_int v[1]; + mp_int w[1]; + mp_int u1[1]; + mp_int u2[1]; + #if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) + mp_int e_lcl[1]; + #endif + #endif /* WOLFSSL_SMALL_STACK */ + mp_int* e; + DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT); +#endif + + 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 (ecc_is_valid_idx(key->idx) != 1) { + if (wc_ecc_is_valid_idx(key->idx) != 1) { return ECC_BAD_ARG_E; } - /* allocate ints */ - if ((err = mp_init_multi(&v, &w, &u1, &u2, &p, &e)) != MP_OKAY) { - return MEMORY_E; + keySz = key->dp->size; + +#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]); + if (err != MP_OKAY) { + return err; + } + err = mp_to_unsigned_bin(s, &sigRS[keySz]); + if (err != MP_OKAY) { + return err; + } + + err = atmel_ecc_verify(hash, sigRS, key->pubkey_raw, res); + if (err != 0) { + return err; + } + (void)hashlen; +#elif defined(WOLFSSL_CRYPTOCELL) + + /* Extract R and S */ + + err = mp_to_unsigned_bin(r, &sigRS[0]); + if (err != MP_OKAY) { + return err; + } + err = mp_to_unsigned_bin(s, &sigRS[keySz]); + if (err != MP_OKAY) { + return err; } - if ((err = mp_init(&m)) != MP_OKAY) { - mp_clear(&v); - mp_clear(&w); - mp_clear(&u1); - mp_clear(&u2); - mp_clear(&p); - mp_clear(&e); - return MEMORY_E; + hash_mode = cc310_hashModeECC(msgLenInBytes); + if (hash_mode == CRYS_ECPKI_HASH_OpModeLast) { + /* hash_mode = */ cc310_hashModeECC(keySz); + hash_mode = CRYS_ECPKI_HASH_SHA256_mode; + } + /* truncate if hash is longer than key size */ + if (msgLenInBytes > keySz) { + msgLenInBytes = keySz; } - /* allocate points */ - mG = ecc_new_point(); - mQ = ecc_new_point(); - if (mQ == NULL || mG == NULL) - err = MEMORY_E; + /* verify the signature using the public key */ + err = CRYS_ECDSA_Verify(&sigCtxTemp, + &key->ctx.pubKey, + hash_mode, + &sigRS[0], + keySz*2, + (byte*)hash, + msgLenInBytes); - /* 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. */ - XMEMSET(&r, 0, sizeof(r)); - XMEMSET(&s, 0, sizeof(s)); - if (err == MP_OKAY) - err = DecodeECC_DSA_Sig(sig, siglen, &r, &s); + if (err != SA_SILIB_RET_OK) { + WOLFSSL_MSG("CRYS_ECDSA_Verify failed"); + return err; + } + /* valid signature if we get to this point */ + *res = 1; +#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; + } + } - /* get the order */ - if (err == MP_OKAY) - err = mp_read_radix(&p, (char *)key->dp->order, 16); +#if defined(WOLFSSL_DSP) && !defined(FREESCALE_LTC_ECC) + if (key->handle != -1) { + return sp_dsp_ecc_verify_256(key->handle, hash, hashlen, key->pubkey.x, key->pubkey.y, + key->pubkey.z, r, s, res, key->heap); + } + if (wolfSSL_GetHandleCbSet() == 1) { + return sp_dsp_ecc_verify_256(0, hash, hashlen, key->pubkey.x, key->pubkey.y, + key->pubkey.z, r, s, res, key->heap); + } +#endif +#if defined(WOLFSSL_SP_MATH) && !defined(FREESCALE_LTC_ECC) +#ifndef WOLFSSL_SP_NO_256 + 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 +#ifdef WOLFSSL_SP_384 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { + return sp_ecc_verify_384(hash, hashlen, key->pubkey.x, key->pubkey.y, + key->pubkey.z, r, s, res, key->heap); + } +#endif + return WC_KEY_SIZE_E; +#else +#if defined WOLFSSL_HAVE_SP_ECC && !defined(FREESCALE_LTC_ECC) + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + 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_verify_256(hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z,r, s, res, + key->heap); + } +#endif /* WOLFSSL_SP_NO_256 */ +#ifdef WOLFSSL_SP_384 + if (key->idx != ECC_CUSTOM_IDX && + ecc_sets[key->idx].id == ECC_SECP384R1) { + return sp_ecc_verify_384(hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z,r, s, res, + key->heap); + } +#endif /* WOLFSSL_SP_384 */ + } +#endif /* WOLFSSL_HAVE_SP_ECC */ - /* get the modulus */ - if (err == MP_OKAY) - err = mp_read_radix(&m, (char *)key->dp->prime, 16); + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V) + err = wc_ecc_alloc_mpint(key, &key->e); + if (err != 0) { + FREE_CURVE_SPECS(); + return err; + } + e = key->e; +#else +#ifdef WOLFSSL_SMALL_STACK + e_lcl = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (e_lcl == NULL) { + FREE_CURVE_SPECS(); + return MEMORY_E; + } +#endif + e = e_lcl; +#endif /* WOLFSSL_ASYNC_CRYPT && HAVE_CAVIUM_V */ + + err = mp_init(e); + if (err != MP_OKAY) + return MEMORY_E; + + /* read in the specs for this curve */ + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); /* check for zero */ if (err == MP_OKAY) { - if (mp_iszero(&r) || mp_iszero(&s) || mp_cmp(&r, &p) != MP_LT || - mp_cmp(&s, &p) != MP_LT) - err = MP_ZERO_E; + if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || + mp_cmp(r, curve->order) != MP_LT || + mp_cmp(s, curve->order) != MP_LT) { + err = MP_ZERO_E; + } } + /* read hash */ if (err == MP_OKAY) { /* we may need to truncate if hash is longer than key size */ - unsigned int orderBits = mp_count_bits(&p); + unsigned int orderBits = mp_count_bits(curve->order); /* truncate down to byte size, may be all that's needed */ if ( (WOLFSSL_BIT_SIZE * hashlen) > orderBits) - hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1)/WOLFSSL_BIT_SIZE; - err = mp_read_unsigned_bin(&e, hash, hashlen); + hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; + err = mp_read_unsigned_bin(e, hash, hashlen); /* may still need bit truncation too */ if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * hashlen) > orderBits) - mp_rshb(&e, WOLFSSL_BIT_SIZE - (orderBits & 0x7)); + 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) { + #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA) + #ifdef HAVE_CAVIUM_V + if (NitroxEccIsCurveSupported(key)) + #endif + { + err = wc_mp_to_bigint_sz(e, &e->raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(key->pubkey.x, &key->pubkey.x->raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(key->pubkey.y, &key->pubkey.y->raw, keySz); + if (err == MP_OKAY) + #ifdef HAVE_CAVIUM_V + err = NitroxEcdsaVerify(key, &e->raw, &key->pubkey.x->raw, + &key->pubkey.y->raw, &r->raw, &s->raw, + &curve->prime->raw, &curve->order->raw, res); + #else + 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); + #endif + + #ifndef HAVE_CAVIUM_V + mp_clear(e); + #endif + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + + return err; + } + #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */ + } +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + v = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (v == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + w = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (w == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u2 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (u2 == NULL) + err = MEMORY_E; + } +#endif + + /* allocate ints */ + 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 */ + if (err == MP_OKAY) { + mG = wc_ecc_new_point_h(key->heap); + mQ = wc_ecc_new_point_h(key->heap); + if (mQ == NULL || mG == NULL) + err = MEMORY_E; } /* w = s^-1 mod n */ if (err == MP_OKAY) - err = mp_invmod(&s, &p, &w); + err = mp_invmod(s, curve->order, w); /* u1 = ew */ if (err == MP_OKAY) - err = mp_mulmod(&e, &w, &p, &u1); + err = mp_mulmod(e, w, curve->order, u1); /* u2 = rw */ if (err == MP_OKAY) - err = mp_mulmod(&r, &w, &p, &u2); + err = mp_mulmod(r, w, curve->order, u2); /* find mG and mQ */ if (err == MP_OKAY) - err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16); - + err = mp_copy(curve->Gx, mG->x); if (err == MP_OKAY) - err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16); + 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); @@ -2207,75 +6170,458 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, if (err == MP_OKAY) err = mp_copy(key->pubkey.z, mQ->z); +#if defined(FREESCALE_LTC_ECC) + /* use PKHA to compute u1*mG + u2*mQ */ + 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); + if (err == MP_OKAY) + err = wc_ecc_point_add(mG, mQ, mG, curve->prime); +#else #ifndef ECC_SHAMIR + if (err == MP_OKAY) { - mp_digit mp; + mp_digit mp = 0; - /* compute u1*mG + u2*mQ = mG */ - if (err == MP_OKAY) - err = ecc_mulmod(&u1, mG, mG, &m, 0); - if (err == MP_OKAY) - err = ecc_mulmod(&u2, mQ, mQ, &m, 0); - - /* find the montgomery mp */ - if (err == MP_OKAY) - err = mp_montgomery_setup(&m, &mp); + if (!mp_iszero(u1)) { + /* compute u1*mG + u2*mQ = mG */ + 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); + } - /* add them */ - if (err == MP_OKAY) - err = ecc_projective_add_point(mQ, mG, mG, &m, &mp); - - /* reduce */ - if (err == MP_OKAY) - err = ecc_map(mG, &m, &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); + if (err == MP_OKAY && mp_iszero(mG->z)) { + /* When all zero then should have done an add */ + if (mp_iszero(mG->x) && mp_iszero(mG->y)) { + err = ecc_projective_dbl_point(mQ, mG, curve->Af, + curve->prime, mp); + } + /* When only Z zero then result is infinity */ + else { + err = mp_set(mG->x, 0); + if (err == MP_OKAY) + err = mp_set(mG->y, 0); + if (err == MP_OKAY) + err = mp_set(mG->z, 1); + } + } + } + else { + /* compute 0*mG + u2*mQ = mG */ + err = wc_ecc_mulmod_ex(u2, mQ, mG, curve->Af, curve->prime, 0, + key->heap); + /* find the montgomery mp */ + if (err == MP_OKAY) + err = mp_montgomery_setup(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, &m); -#endif /* ECC_SHAMIR */ - + /* 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, + key->heap); + } +#endif /* ECC_SHAMIR */ +#endif /* FREESCALE_LTC_ECC */ /* v = X_x1 mod n */ if (err == MP_OKAY) - err = mp_mod(mG->x, &p, &v); + err = mp_mod(mG->x, curve->order, v); /* does v == r */ if (err == MP_OKAY) { - if (mp_cmp(&v, &r) == MP_EQ) - *stat = 1; + if (mp_cmp(v, r) == MP_EQ) + *res = 1; } - ecc_del_point(mG); - ecc_del_point(mQ); + /* cleanup */ + wc_ecc_del_point_h(mG, key->heap); + wc_ecc_del_point_h(mQ, key->heap); - mp_clear(&r); - mp_clear(&s); - mp_clear(&v); - mp_clear(&w); - mp_clear(&u1); - mp_clear(&u2); - mp_clear(&p); - mp_clear(&e); - mp_clear(&m); + mp_clear(e); + if (did_init) { + mp_clear(v); + mp_clear(w); + mp_clear(u1); + mp_clear(u2); + } +#ifdef WOLFSSL_SMALL_STACK + XFREE(u2, key->heap, DYNAMIC_TYPE_ECC); + XFREE(u1, key->heap, DYNAMIC_TYPE_ECC); + XFREE(w, key->heap, DYNAMIC_TYPE_ECC); + XFREE(v, key->heap, DYNAMIC_TYPE_ECC); +#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) + XFREE(e_lcl, key->heap, DYNAMIC_TYPE_ECC); +#endif +#endif + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + +#endif /* WOLFSSL_SP_MATH */ +#endif /* WOLFSSL_ATECC508A */ + + (void)keySz; + (void)hashlen; return err; } +#endif /* WOLFSSL_STM32_PKA */ +#endif /* HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_KEY_IMPORT +/* import point from der + * if shortKeySize != 0 then keysize is always (inLen-1)>>1 */ +int wc_ecc_import_point_der_ex(byte* in, word32 inLen, const int curve_idx, + ecc_point* point, int shortKeySize) +{ + int err = 0; +#ifdef HAVE_COMP_KEY + int compressed = 0; +#endif + int keysize; + byte pointType; + +#ifndef HAVE_COMP_KEY + (void)shortKeySize; +#endif + + if (in == NULL || point == NULL || (curve_idx < 0) || + (wc_ecc_is_valid_idx(curve_idx) == 0)) + return ECC_BAD_ARG_E; + + /* must be odd */ + if ((inLen & 1) == 0) { + return ECC_BAD_ARG_E; + } + + /* init point */ +#ifdef ALT_ECC_SIZE + point->x = (mp_int*)&point->xyz[0]; + point->y = (mp_int*)&point->xyz[1]; + point->z = (mp_int*)&point->xyz[2]; + alt_fp_init(point->x); + alt_fp_init(point->y); + alt_fp_init(point->z); +#else + err = mp_init_multi(point->x, point->y, point->z, NULL, NULL, NULL); +#endif + if (err != MP_OKAY) + return MEMORY_E; + + /* check for point type (4, 2, or 3) */ + pointType = in[0]; + if (pointType != ECC_POINT_UNCOMP && pointType != ECC_POINT_COMP_EVEN && + pointType != ECC_POINT_COMP_ODD) { + err = ASN_PARSE_E; + } + + if (pointType == ECC_POINT_COMP_EVEN || pointType == ECC_POINT_COMP_ODD) { +#ifdef HAVE_COMP_KEY + compressed = 1; +#else + err = NOT_COMPILED_IN; +#endif + } + + /* adjust to skip first byte */ + inLen -= 1; + in += 1; + + /* calculate key size based on inLen / 2 if uncompressed or shortKeySize + * is true */ +#ifdef HAVE_COMP_KEY + keysize = compressed && !shortKeySize ? inLen : inLen>>1; +#else + keysize = inLen>>1; +#endif + + /* read data */ + if (err == MP_OKAY) + err = mp_read_unsigned_bin(point->x, (byte*)in, keysize); + +#ifdef HAVE_COMP_KEY + if (err == MP_OKAY && compressed == 1) { /* build y */ +#ifndef WOLFSSL_SP_MATH + int did_init = 0; + mp_int t1, t2; + DECLARE_CURVE_SPECS(curve, 3); + + ALLOC_CURVE_SPECS(3); + + if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) + err = MEMORY_E; + else + did_init = 1; + + /* 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)); + + /* compute x^3 */ + if (err == MP_OKAY) + err = mp_sqr(point->x, &t1); + if (err == MP_OKAY) + err = mp_mulmod(&t1, point->x, curve->prime, &t1); + + /* compute x^3 + a*x */ + if (err == MP_OKAY) + err = mp_mulmod(curve->Af, point->x, curve->prime, &t2); + if (err == MP_OKAY) + err = mp_add(&t1, &t2, &t1); + + /* compute x^3 + a*x + b */ + if (err == MP_OKAY) + err = mp_add(&t1, curve->Bf, &t1); + + /* compute sqrt(x^3 + a*x + b) */ + if (err == MP_OKAY) + err = mp_sqrtmod_prime(&t1, curve->prime, &t2); + + /* adjust y */ + if (err == MP_OKAY) { + if ((mp_isodd(&t2) == MP_YES && pointType == ECC_POINT_COMP_ODD) || + (mp_isodd(&t2) == MP_NO && pointType == ECC_POINT_COMP_EVEN)) { + err = mp_mod(&t2, curve->prime, point->y); + } + else { + err = mp_submod(curve->prime, &t2, curve->prime, point->y); + } + } + + if (did_init) { + mp_clear(&t2); + mp_clear(&t1); + } + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); +#else + #ifndef WOLFSSL_SP_NO_256 + if (curve_idx != ECC_CUSTOM_IDX && + ecc_sets[curve_idx].id == ECC_SECP256R1) { + sp_ecc_uncompress_256(point->x, pointType, point->y); + } + else + #endif + #ifdef WOLFSSL_SP_384 + if (curve_idx != ECC_CUSTOM_IDX && + ecc_sets[curve_idx].id == ECC_SECP384R1) { + sp_ecc_uncompress_384(point->x, pointType, point->y); + } + else + #endif + { + err = WC_KEY_SIZE_E; + } +#endif + } +#endif + + if (err == MP_OKAY) { +#ifdef HAVE_COMP_KEY + if (compressed == 0) +#endif + err = mp_read_unsigned_bin(point->y, (byte*)in + keysize, keysize); + } + if (err == MP_OKAY) + err = mp_set(point->z, 1); + + if (err != MP_OKAY) { + mp_clear(point->x); + mp_clear(point->y); + mp_clear(point->z); + } + + return err; +} + +/* function for backwards compatiblity with previous implementations */ +int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, + ecc_point* point) +{ + return wc_ecc_import_point_der_ex(in, inLen, curve_idx, point, 1); +} +#endif /* HAVE_ECC_KEY_IMPORT */ + +#ifdef HAVE_ECC_KEY_EXPORT +/* export point to der */ + +int wc_ecc_export_point_der_ex(const int curve_idx, ecc_point* point, byte* out, + word32* outLen, int compressed) +{ + if (compressed == 0) + return wc_ecc_export_point_der(curve_idx, point, out, outLen); +#ifdef HAVE_COMP_KEY + else + return wc_ecc_export_point_der_compressed(curve_idx, point, out, outLen); +#else + return NOT_COMPILED_IN; +#endif +} + +int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, byte* out, + word32* outLen) +{ + int ret = MP_OKAY; + word32 numlen; +#ifdef WOLFSSL_SMALL_STACK + byte* buf; +#else + byte buf[ECC_BUFSIZE]; +#endif + + if ((curve_idx < 0) || (wc_ecc_is_valid_idx(curve_idx) == 0)) + return ECC_BAD_ARG_E; + + numlen = ecc_sets[curve_idx].size; + + /* return length needed only */ + if (point != NULL && out == NULL && outLen != NULL) { + *outLen = 1 + 2*numlen; + return LENGTH_ONLY_E; + } + + if (point == NULL || out == NULL || outLen == NULL) + return ECC_BAD_ARG_E; + + if (*outLen < (1 + 2*numlen)) { + *outLen = 1 + 2*numlen; + return BUFFER_E; + } + + /* store byte point type */ + out[0] = ECC_POINT_UNCOMP; + +#ifdef WOLFSSL_SMALL_STACK + buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (buf == NULL) + return MEMORY_E; +#endif + + /* pad and store x */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(point->x, buf + + (numlen - mp_unsigned_bin_size(point->x))); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1, buf, numlen); + + /* pad and store y */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(point->y, buf + + (numlen - mp_unsigned_bin_size(point->y))); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1+numlen, buf, numlen); + + *outLen = 1 + 2*numlen; + +done: +#ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER); +#endif + + return ret; +} + + +/* export point to der */ +#ifdef HAVE_COMP_KEY +int wc_ecc_export_point_der_compressed(const int curve_idx, ecc_point* point, + byte* out, word32* outLen) +{ + int ret = MP_OKAY; + word32 numlen; + word32 output_len; +#ifdef WOLFSSL_SMALL_STACK + byte* buf; +#else + byte buf[ECC_BUFSIZE]; +#endif + + if ((curve_idx < 0) || (wc_ecc_is_valid_idx(curve_idx) == 0)) + return ECC_BAD_ARG_E; + + numlen = ecc_sets[curve_idx].size; + output_len = 1 + numlen; /* y point type + x */ + + /* return length needed only */ + if (point != NULL && out == NULL && outLen != NULL) { + *outLen = output_len; + return LENGTH_ONLY_E; + } + + if (point == NULL || out == NULL || outLen == NULL) + return ECC_BAD_ARG_E; + + + if (*outLen < output_len) { + *outLen = output_len; + return BUFFER_E; + } + + /* store byte point type */ + out[0] = mp_isodd(point->y) == MP_YES ? ECC_POINT_COMP_ODD : + ECC_POINT_COMP_EVEN; + +#ifdef WOLFSSL_SMALL_STACK + buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (buf == NULL) + return MEMORY_E; +#endif + + /* pad and store x */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(point->x, buf + + (numlen - mp_unsigned_bin_size(point->x))); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1, buf, numlen); + + *outLen = output_len; + +done: +#ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER); +#endif + + return ret; +} +#endif /* HAVE_COMP_KEY */ /* export public ECC key in ANSI X9.63 format */ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) { + int ret = MP_OKAY; + word32 numlen; #ifdef WOLFSSL_SMALL_STACK byte* buf; #else byte buf[ECC_BUFSIZE]; #endif - word32 numlen; - int ret = MP_OKAY; + word32 pubxlen, pubylen; /* return length needed only */ if (key != NULL && out == NULL && outLen != NULL) { - numlen = key->dp->size; + /* if key hasn't been setup assume max bytes for size estimation */ + numlen = key->dp ? key->dp->size : MAX_ECC_BYTES; *outLen = 1 + 2*numlen; return LENGTH_ONLY_E; } @@ -2283,47 +6629,56 @@ 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 (ecc_is_valid_idx(key->idx) == 0) { + if (key->type == ECC_PRIVATEKEY_ONLY) + return ECC_PRIVATEONLY_E; + + if (wc_ecc_is_valid_idx(key->idx) == 0 || key->dp == NULL) { return ECC_BAD_ARG_E; } numlen = key->dp->size; + /* verify room in out buffer */ if (*outLen < (1 + 2*numlen)) { *outLen = 1 + 2*numlen; return BUFFER_E; } - /* store byte 0x04 */ - out[0] = 0x04; + /* 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); + if ((pubxlen > numlen) || (pubylen > numlen)) { + WOLFSSL_MSG("Public key x/y invalid!"); + return BUFFER_E; + } + + /* store byte point type */ + out[0] = ECC_POINT_UNCOMP; #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 - do { - /* pad and store x */ - XMEMSET(buf, 0, ECC_BUFSIZE); - ret = mp_to_unsigned_bin(key->pubkey.x, - buf + (numlen - mp_unsigned_bin_size(key->pubkey.x))); - if (ret != MP_OKAY) - break; - XMEMCPY(out+1, buf, numlen); + /* pad and store x */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - pubxlen)); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1, buf, numlen); - /* pad and store y */ - XMEMSET(buf, 0, ECC_BUFSIZE); - ret = mp_to_unsigned_bin(key->pubkey.y, - buf + (numlen - mp_unsigned_bin_size(key->pubkey.y))); - if (ret != MP_OKAY) - break; - XMEMCPY(out+1+numlen, buf, numlen); + /* pad and store y */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - pubylen)); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1+numlen, buf, numlen); - *outLen = 1 + 2*numlen; - } while (0); + *outLen = 1 + 2*numlen; +done: #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER); #endif return ret; @@ -2332,158 +6687,264 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) /* export public ECC key in ANSI X9.63 format, extended with * compression option */ -int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, int compressed) +int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, + int compressed) { if (compressed == 0) return wc_ecc_export_x963(key, out, outLen); #ifdef HAVE_COMP_KEY else return wc_ecc_export_x963_compressed(key, out, outLen); +#else + return NOT_COMPILED_IN; +#endif +} +#endif /* HAVE_ECC_KEY_EXPORT */ + + +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) + +/* is ecc point on curve described by dp ? */ +int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime) +{ +#ifndef WOLFSSL_SP_MATH + int err; +#ifdef WOLFSSL_SMALL_STACK + mp_int* t1; + mp_int* t2; +#else + mp_int t1[1], t2[1]; #endif - return NOT_COMPILED_IN; -} +#ifdef WOLFSSL_SMALL_STACK + t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) + return MEMORY_E; + t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t2 == NULL) { + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif - -/* is ec point on curve descriped by dp ? */ -static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) -{ - mp_int b, t1, t2; - int err; - - if ((err = mp_init_multi(&b, &t1, &t2, NULL, NULL, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + #endif return err; } - /* load b */ - err = mp_read_radix(&b, dp->Bf, 16); - /* compute y^2 */ if (err == MP_OKAY) - err = mp_sqr(ecp->y, &t1); + err = mp_sqr(ecp->y, t1); /* compute x^3 */ if (err == MP_OKAY) - err = mp_sqr(ecp->x, &t2); + err = mp_sqr(ecp->x, t2); if (err == MP_OKAY) - err = mp_mod(&t2, prime, &t2); + err = mp_mod(t2, prime, t2); if (err == MP_OKAY) - err = mp_mul(ecp->x, &t2, &t2); + err = mp_mul(ecp->x, t2, t2); /* compute y^2 - x^3 */ if (err == MP_OKAY) - err = mp_sub(&t1, &t2, &t1); + err = mp_sub(t1, t2, t1); - /* compute y^2 - x^3 + 3x */ - if (err == MP_OKAY) - err = mp_add(&t1, ecp->x, &t1); - if (err == MP_OKAY) - err = mp_add(&t1, ecp->x, &t1); - if (err == MP_OKAY) - err = mp_add(&t1, ecp->x, &t1); - if (err == MP_OKAY) - err = mp_mod(&t1, prime, &t1); - - while (err == MP_OKAY && mp_cmp_d(&t1, 0) == MP_LT) { - err = mp_add(&t1, prime, &t1); + /* Determine if curve "a" should be used in calc */ +#ifdef WOLFSSL_CUSTOM_CURVES + if (err == MP_OKAY) { + /* Use a and prime to determine if a == 3 */ + err = mp_set(t2, 0); + if (err == MP_OKAY) + err = mp_submod(prime, a, prime, t2); } - while (err == MP_OKAY && mp_cmp(&t1, prime) != MP_LT) { - err = mp_sub(&t1, prime, &t1); + if (err == MP_OKAY && mp_cmp_d(t2, 3) != MP_EQ) { + /* compute y^2 - x^3 + a*x */ + if (err == MP_OKAY) + err = mp_mulmod(t2, ecp->x, prime, t2); + if (err == MP_OKAY) + err = mp_addmod(t1, t2, prime, t1); + } + else +#endif /* WOLFSSL_CUSTOM_CURVES */ + { + /* assumes "a" == 3 */ + (void)a; + + /* compute y^2 - x^3 + 3x */ + if (err == MP_OKAY) + err = mp_add(t1, ecp->x, t1); + if (err == MP_OKAY) + err = mp_add(t1, ecp->x, t1); + if (err == MP_OKAY) + err = mp_add(t1, ecp->x, t1); + if (err == MP_OKAY) + err = mp_mod(t1, prime, t1); + } + + /* adjust range (0, prime) */ + while (err == MP_OKAY && mp_isneg(t1)) { + err = mp_add(t1, prime, t1); + } + while (err == MP_OKAY && mp_cmp(t1, prime) != MP_LT) { + err = mp_sub(t1, prime, t1); } /* compare to b */ if (err == MP_OKAY) { - if (mp_cmp(&t1, &b) != MP_EQ) { + if (mp_cmp(t1, b) != MP_EQ) { err = MP_VAL; } else { err = MP_OKAY; } } - mp_clear(&b); - mp_clear(&t1); - mp_clear(&t2); + mp_clear(t1); + mp_clear(t2); +#ifdef WOLFSSL_SMALL_STACK + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); +#endif return err; +#else + (void)a; + (void)b; + +#ifndef WOLFSSL_SP_NO_256 + if (mp_count_bits(prime) == 256) { + return sp_ecc_is_point_256(ecp->x, ecp->y); + } +#endif +#ifdef WOLFSSL_SP_384 + if (mp_count_bits(prime) == 384) { + return sp_ecc_is_point_384(ecp->x, ecp->y); + } +#endif + return WC_KEY_SIZE_E; +#endif } - +#ifndef WOLFSSL_SP_MATH /* validate privkey * generator == pubkey, 0 on success */ -static int ecc_check_privkey_gen(ecc_key* key, mp_int* prime) +static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) { + int err = MP_OKAY; ecc_point* base = NULL; ecc_point* res = NULL; - int err; + DECLARE_CURVE_SPECS(curve, 2); if (key == NULL) return BAD_FUNC_ARG; - base = ecc_new_point(); - if (base == NULL) - return MEMORY_E; + ALLOC_CURVE_SPECS(2); - /* set up base generator */ - err = mp_read_radix(base->x, (char*)key->dp->Gx, 16); - if (err == MP_OKAY) - err = mp_read_radix(base->y, (char*)key->dp->Gy, 16); - if (err == MP_OKAY) - mp_set(base->z, 1); + res = wc_ecc_new_point_h(key->heap); + if (res == NULL) + err = MEMORY_E; + +#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 +#ifdef WOLFSSL_SP_384 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { + if (err == MP_OKAY) { + err = sp_ecc_mulmod_base_384(&key->k, res, 1, key->heap); + } + } + else +#endif +#endif + { + base = wc_ecc_new_point_h(key->heap); + if (base == NULL) + err = MEMORY_E; + + 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 = ecc_new_point(); - if (res == NULL) - err = MEMORY_E; - else { - err = ecc_mulmod(&key->k, base, res, prime, 1); - 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; } } - ecc_del_point(res); - ecc_del_point(base); + wc_ecc_curve_free(curve); + wc_ecc_del_point_h(res, key->heap); + wc_ecc_del_point_h(base, key->heap); + FREE_CURVE_SPECS(); return err; } - +#endif #ifdef WOLFSSL_VALIDATE_ECC_IMPORT /* check privkey generator helper, creates prime needed */ static int ecc_check_privkey_gen_helper(ecc_key* key) { - mp_int prime; int err; +#ifndef WOLFSSL_ATECC508A + DECLARE_CURVE_SPECS(curve, 2); +#endif if (key == NULL) return BAD_FUNC_ARG; - err = mp_init(&prime); - if (err != MP_OKAY) - return err; +#ifdef WOLFSSL_ATECC508A + /* Hardware based private key, so this operation is not supported */ + err = MP_OKAY; /* just report success */ - err = mp_read_radix(&prime, (char*)key->dp->prime, 16); +#else + ALLOC_CURVE_SPECS(2); - if (err == MP_OKAY); - err = ecc_check_privkey_gen(key, &prime); + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); - mp_clear(&prime); + if (err == MP_OKAY) + err = ecc_check_privkey_gen(key, curve->Af, curve->prime); + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + +#endif /* WOLFSSL_ATECC508A */ return err; } #endif /* WOLFSSL_VALIDATE_ECC_IMPORT */ - +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || !defined(WOLFSSL_SP_MATH) /* validate order * pubkey = point at infinity, 0 on success */ -static int ecc_check_pubkey_order(ecc_key* key, 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; @@ -2491,258 +6952,613 @@ static int ecc_check_pubkey_order(ecc_key* key, mp_int* prime, mp_int* order) if (key == NULL) return BAD_FUNC_ARG; - inf = ecc_new_point(); + inf = wc_ecc_new_point_h(key->heap); if (inf == NULL) err = MEMORY_E; else { - err = ecc_mulmod(order, &key->pubkey, inf, prime, 1); - if (err == MP_OKAY && !ecc_point_is_at_infinity(inf)) +#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 +#ifdef WOLFSSL_SP_384 + if (key->idx != ECC_CUSTOM_IDX && + ecc_sets[key->idx].id == ECC_SECP384R1) { + err = sp_ecc_mulmod_384(order, pubkey, inf, 1, key->heap); + } + else +#endif +#endif +#ifndef WOLFSSL_SP_MATH + 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; +#else + (void)a; + (void)prime; + + err = WC_KEY_SIZE_E; +#endif } - ecc_del_point(inf); + wc_ecc_del_point_h(inf, key->heap); return err; } +#endif +#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCELL*/ +#ifdef OPENSSL_EXTRA +int wc_ecc_get_generator(ecc_point* ecp, int curve_idx) +{ + int err = MP_OKAY; + DECLARE_CURVE_SPECS(curve, 2); -/* perform sanity checks on ec key validity, 0 on success */ + if (!ecp || curve_idx < 0 || curve_idx > (int)(ECC_SET_COUNT-1)) + return BAD_FUNC_ARG; + + ALLOC_CURVE_SPECS(2); + + err = wc_ecc_curve_load(&ecc_sets[curve_idx], &curve, + (ECC_CURVE_FIELD_GX | ECC_CURVE_FIELD_GY)); + if (err == MP_OKAY) + err = mp_copy(curve->Gx, ecp->x); + if (err == MP_OKAY) + err = mp_copy(curve->Gy, ecp->y); + if (err == MP_OKAY) + err = mp_set(ecp->z, 1); + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + + return err; +} +#endif /* OPENSSLALL */ + +/* perform sanity checks on ecc key validity, 0 on success */ int wc_ecc_check_key(ecc_key* key) { - mp_int prime; /* used by multiple calls so let's cache */ - mp_int order; /* other callers have, so let's gen here */ int err; +#ifndef WOLFSSL_SP_MATH +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) + mp_int* b = NULL; +#ifdef USE_ECC_B_PARAM + DECLARE_CURVE_SPECS(curve, 4); +#else +#ifndef WOLFSSL_SMALL_STACK + mp_int b_lcl; +#endif + DECLARE_CURVE_SPECS(curve, 3); +#endif /* USE_ECC_B_PARAM */ +#endif /* WOLFSSL_ATECC508A */ if (key == NULL) return BAD_FUNC_ARG; - /* pubkey point cannot be at inifinity */ - if (ecc_point_is_at_infinity(&key->pubkey)) +#if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_CRYPTOCELL) + + err = 0; /* consider key check success on ATECC508A */ + +#else + #ifdef USE_ECC_B_PARAM + ALLOC_CURVE_SPECS(4); + #else + ALLOC_CURVE_SPECS(3); + #ifndef WOLFSSL_SMALL_STACK + b = &b_lcl; + #else + b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (b == NULL) { + FREE_CURVE_SPECS(); + return MEMORY_E; + } + #endif + XMEMSET(b, 0, sizeof(mp_int)); + #endif + + /* SP 800-56Ar3, section 5.6.2.3.3, process step 1 */ + /* pubkey point cannot be at infinity */ + if (wc_ecc_point_is_at_infinity(&key->pubkey)) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, key->heap, DYNAMIC_TYPE_ECC); + #endif + FREE_CURVE_SPECS(); return ECC_INF_E; + } - err = mp_init_multi(&prime, &order, NULL, NULL, NULL, NULL); - if (err != MP_OKAY) - return err; + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_PRIME | + ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_ORDER +#ifdef USE_ECC_B_PARAM + | ECC_CURVE_FIELD_BF +#endif + )); - err = mp_read_radix(&prime, (char*)key->dp->prime, 16); +#ifndef USE_ECC_B_PARAM + /* load curve b parameter */ + if (err == MP_OKAY) + err = mp_init(b); + if (err == MP_OKAY) + err = mp_read_radix(b, key->dp->Bf, MP_RADIX_HEX); +#else + if (err == MP_OKAY) + b = curve->Bf; +#endif + /* SP 800-56Ar3, section 5.6.2.3.3, process step 2 */ + /* Qx must be in the range [0, p-1] */ + if (err == MP_OKAY) { + if (mp_cmp(key->pubkey.x, curve->prime) != MP_LT) + err = ECC_OUT_OF_RANGE_E; + } + + /* Qy must be in the range [0, p-1] */ + if (err == MP_OKAY) { + if (mp_cmp(key->pubkey.y, curve->prime) != MP_LT) + err = ECC_OUT_OF_RANGE_E; + } + + /* SP 800-56Ar3, section 5.6.2.3.3, process steps 3 */ /* make sure point is actually on curve */ if (err == MP_OKAY) - err = ecc_is_point(key->dp, &key->pubkey, &prime); - - if (err == MP_OKAY) - err = mp_read_radix(&order, (char*)key->dp->order, 16); + err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime); + /* SP 800-56Ar3, section 5.6.2.3.3, process steps 4 */ /* pubkey * order must be at infinity */ if (err == MP_OKAY) - err = ecc_check_pubkey_order(key, &prime, &order); + err = ecc_check_pubkey_order(key, &key->pubkey, curve->Af, curve->prime, + curve->order); + /* SP 800-56Ar3, section 5.6.2.1.4, method (b) for ECC */ /* private * base generator must equal pubkey */ if (err == MP_OKAY && key->type == ECC_PRIVATEKEY) - err = ecc_check_privkey_gen(key, &prime); + err = ecc_check_privkey_gen(key, curve->Af, curve->prime); - mp_clear(&order); - mp_clear(&prime); + wc_ecc_curve_free(curve); + +#ifndef USE_ECC_B_PARAM + mp_clear(b); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, key->heap, DYNAMIC_TYPE_ECC); + #endif +#endif + + FREE_CURVE_SPECS(); + +#endif /* WOLFSSL_ATECC508A */ +#else + if (key == NULL) + return BAD_FUNC_ARG; + + /* pubkey point cannot be at infinity */ +#ifndef WOLFSSL_SP_NO_256 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + err = sp_ecc_check_key_256(key->pubkey.x, key->pubkey.y, &key->k, + key->heap); + } + else +#endif +#ifdef WOLFSSL_SP_384 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { + err = sp_ecc_check_key_384(key->pubkey.x, key->pubkey.y, &key->k, + key->heap); + } + else +#endif + { + err = WC_KEY_SIZE_E; + } +#endif return err; } - +#ifdef HAVE_ECC_KEY_IMPORT /* import public ECC key in ANSI X9.63 format */ -int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) +int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, + int curve_id) { - int x, err; - int compressed = 0; - - if (in == NULL || key == NULL) - return ECC_BAD_ARG_E; - - /* must be odd */ - if ((inLen & 1) == 0) { - return ECC_BAD_ARG_E; - } - - /* init key */ -#ifdef ALT_ECC_SIZE - 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); - err = mp_init(&key->k); -#else - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k, - NULL, NULL); -#endif - if (err != MP_OKAY) - return MEMORY_E; - - /* check for 4, 2, or 3 */ - if (in[0] != 0x04 && in[0] != 0x02 && in[0] != 0x03) { - err = ASN_PARSE_E; - } - - if (in[0] == 0x02 || in[0] == 0x03) { + int err = MP_OKAY; #ifdef HAVE_COMP_KEY - compressed = 1; -#else - err = NOT_COMPILED_IN; + int compressed = 0; #endif - } + int keysize = 0; + byte pointType; - if (err == MP_OKAY) { - /* determine the idx */ + if (in == NULL || key == NULL) + return BAD_FUNC_ARG; - if (compressed) - inLen = (inLen-1)*2 + 1; /* used uncompressed len */ + /* must be odd */ + if ((inLen & 1) == 0) { + return ECC_BAD_ARG_E; + } - for (x = 0; ecc_sets[x].size != 0; x++) { - if ((unsigned)ecc_sets[x].size >= ((inLen-1)>>1)) { - break; - } - } - if (ecc_sets[x].size == 0) { - err = ASN_PARSE_E; - } else { - /* set the idx */ - key->idx = x; - key->dp = &ecc_sets[x]; - key->type = ECC_PUBLICKEY; - } - } + /* make sure required variables are reset */ + wc_ecc_reset(key); - /* read data */ - if (err == MP_OKAY) - err = mp_read_unsigned_bin(key->pubkey.x, (byte*)in+1, (inLen-1)>>1); + /* init key */ + #ifdef ALT_ECC_SIZE + 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); + err = mp_init(&key->k); + #else + 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; + + /* check for point type (4, 2, or 3) */ + pointType = in[0]; + if (pointType != ECC_POINT_UNCOMP && pointType != ECC_POINT_COMP_EVEN && + pointType != ECC_POINT_COMP_ODD) { + err = ASN_PARSE_E; + } + + if (pointType == ECC_POINT_COMP_EVEN || pointType == ECC_POINT_COMP_ODD) { + #ifdef HAVE_COMP_KEY + compressed = 1; + #else + err = NOT_COMPILED_IN; + #endif + } + + /* adjust to skip first byte */ + inLen -= 1; + in += 1; + +#ifdef WOLFSSL_ATECC508A + /* For SECP256R1 only save raw public key for hardware */ + if (curve_id == ECC_SECP256R1 && inLen <= sizeof(key->pubkey_raw)) { + #ifdef HAVE_COMP_KEY + if (!compressed) + #endif + XMEMCPY(key->pubkey_raw, (byte*)in, inLen); + } +#endif + + if (err == MP_OKAY) { + #ifdef HAVE_COMP_KEY + /* adjust inLen if compressed */ + if (compressed) + inLen = inLen*2 + 1; /* used uncompressed len */ + #endif + + /* determine key size */ + keysize = (inLen>>1); + err = wc_ecc_set_curve(key, keysize, curve_id); + key->type = ECC_PUBLICKEY; + } + + /* read data */ + if (err == MP_OKAY) + err = mp_read_unsigned_bin(key->pubkey.x, (byte*)in, keysize); #ifdef HAVE_COMP_KEY - if (err == MP_OKAY && compressed == 1) { /* build y */ - mp_int t1, t2, prime, a, b; + if (err == MP_OKAY && compressed == 1) { /* build y */ +#ifndef WOLFSSL_SP_MATH + mp_int t1, t2; + int did_init = 0; - if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY) + DECLARE_CURVE_SPECS(curve, 3); + ALLOC_CURVE_SPECS(3); + + if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) err = MEMORY_E; + else + did_init = 1; - /* load prime */ + /* load curve info */ if (err == MP_OKAY) - err = mp_read_radix(&prime, (char *)key->dp->prime, 16); - - /* load a */ - if (err == MP_OKAY) - err = mp_read_radix(&a, (char *)key->dp->Af, 16); - - /* load b */ - if (err == MP_OKAY) - err = mp_read_radix(&b, (char *)key->dp->Bf, 16); + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | + ECC_CURVE_FIELD_BF)); /* compute x^3 */ if (err == MP_OKAY) err = mp_sqr(key->pubkey.x, &t1); - if (err == MP_OKAY) - err = mp_mulmod(&t1, key->pubkey.x, &prime, &t1); + err = mp_mulmod(&t1, key->pubkey.x, curve->prime, &t1); /* compute x^3 + a*x */ if (err == MP_OKAY) - err = mp_mulmod(&a, key->pubkey.x, &prime, &t2); - + err = mp_mulmod(curve->Af, key->pubkey.x, curve->prime, &t2); if (err == MP_OKAY) err = mp_add(&t1, &t2, &t1); /* compute x^3 + a*x + b */ if (err == MP_OKAY) - err = mp_add(&t1, &b, &t1); + err = mp_add(&t1, curve->Bf, &t1); /* compute sqrt(x^3 + a*x + b) */ if (err == MP_OKAY) - err = mp_sqrtmod_prime(&t1, &prime, &t2); + err = mp_sqrtmod_prime(&t1, curve->prime, &t2); /* adjust y */ if (err == MP_OKAY) { - if ((mp_isodd(&t2) && in[0] == 0x03) || - (!mp_isodd(&t2) && in[0] == 0x02)) { - err = mp_mod(&t2, &prime, key->pubkey.y); + if ((mp_isodd(&t2) == MP_YES && pointType == ECC_POINT_COMP_ODD) || + (mp_isodd(&t2) == MP_NO && pointType == ECC_POINT_COMP_EVEN)) { + err = mp_mod(&t2, curve->prime, &t2); } else { - err = mp_submod(&prime, &t2, &prime, key->pubkey.y); + err = mp_submod(curve->prime, &t2, curve->prime, &t2); } + if (err == MP_OKAY) + err = mp_copy(&t2, key->pubkey.y); } - mp_clear(&a); - mp_clear(&b); - mp_clear(&prime); - mp_clear(&t2); - mp_clear(&t1); - } -#endif + if (did_init) { + mp_clear(&t2); + mp_clear(&t1); + } - if (err == MP_OKAY && compressed == 0) - 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); + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); +#else + #ifndef WOLFSSL_SP_NO_256 + if (key->dp->id == ECC_SECP256R1) { + sp_ecc_uncompress_256(key->pubkey.x, pointType, key->pubkey.y); + } + else + #endif + #ifdef WOLFSSL_SP_384 + if (key->dp->id == ECC_SECP384R1) { + sp_ecc_uncompress_384(key->pubkey.x, pointType, key->pubkey.y); + } + else + #endif + { + err = WC_KEY_SIZE_E; + } +#endif + } +#endif /* HAVE_COMP_KEY */ + + if (err == MP_OKAY) { + #ifdef HAVE_COMP_KEY + if (compressed == 0) + #endif + { + err = mp_read_unsigned_bin(key->pubkey.y, (byte*)in + keysize, + keysize); + } + } + if (err == MP_OKAY) + err = mp_set(key->pubkey.z, 1); #ifdef WOLFSSL_VALIDATE_ECC_IMPORT - if (err == MP_OKAY) - err = wc_ecc_check_key(key); + if (err == MP_OKAY) + err = wc_ecc_check_key(key); #endif - if (err != MP_OKAY) { - mp_clear(key->pubkey.x); - mp_clear(key->pubkey.y); - mp_clear(key->pubkey.z); - mp_clear(&key->k); - } + if (err != MP_OKAY) { + mp_clear(key->pubkey.x); + mp_clear(key->pubkey.y); + mp_clear(key->pubkey.z); + mp_clear(&key->k); + } - return err; + return err; +} + +WOLFSSL_ABI +int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) +{ + return wc_ecc_import_x963_ex(in, inLen, key, ECC_CURVE_DEF); +} +#endif /* HAVE_ECC_KEY_IMPORT */ + +#ifdef HAVE_ECC_KEY_EXPORT + +/* export ecc key to component form, d is optional if only exporting public + * encType is WC_TYPE_UNSIGNED_BIN or WC_TYPE_HEX_STR + * return MP_OKAY on success */ +int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen, int encType) +{ + int err = 0; + word32 keySz; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (wc_ecc_is_valid_idx(key->idx) == 0) { + return ECC_BAD_ARG_E; + } + keySz = key->dp->size; + + /* private key, d */ + if (d != NULL) { + if (dLen == NULL || + (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY)) + return BAD_FUNC_ARG; + + #ifdef WOLFSSL_ATECC508A + /* Hardware cannot export private portion */ + return NOT_COMPILED_IN; + #else + err = wc_export_int(&key->k, d, dLen, keySz, encType); + if (err != MP_OKAY) + return err; + #endif + } + + /* public x component */ + if (qx != NULL) { + if (qxLen == NULL || key->type == ECC_PRIVATEKEY_ONLY) + return BAD_FUNC_ARG; + + err = wc_export_int(key->pubkey.x, qx, qxLen, keySz, encType); + if (err != MP_OKAY) + return err; + } + + /* public y component */ + if (qy != NULL) { + if (qyLen == NULL || key->type == ECC_PRIVATEKEY_ONLY) + return BAD_FUNC_ARG; + + err = wc_export_int(key->pubkey.y, qy, qyLen, keySz, encType); + if (err != MP_OKAY) + return err; + } + + return err; } -/* export ecc private key only raw, outLen is in/out size +/* export ecc private key only raw, outLen is in/out size as unsigned bin return MP_OKAY on success */ int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) { - word32 numlen; + if (out == NULL || outLen == NULL) { + return BAD_FUNC_ARG; + } - if (key == NULL || out == NULL || outLen == NULL) - return ECC_BAD_ARG_E; - - if (ecc_is_valid_idx(key->idx) == 0) { - return ECC_BAD_ARG_E; - } - numlen = key->dp->size; - - if (*outLen < numlen) { - *outLen = numlen; - return BUFFER_E; - } - *outLen = numlen; - XMEMSET(out, 0, *outLen); - return mp_to_unsigned_bin(&key->k, out + (numlen - - mp_unsigned_bin_size(&key->k))); + return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen, + WC_TYPE_UNSIGNED_BIN); } - -/* ecc private key import, public key in ANSI X9.63 format, private raw */ -int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub, - word32 pubSz, ecc_key* key) +/* export public key to raw elements including public (Qx,Qy) as unsigned bin + * return MP_OKAY on success, negative on error */ +int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen) { - int ret = wc_ecc_import_x963(pub, pubSz, key); + if (qx == NULL || qxLen == NULL || qy == NULL || qyLen == NULL) { + return BAD_FUNC_ARG; + } + + return wc_ecc_export_ex(key, qx, qxLen, qy, qyLen, NULL, NULL, + WC_TYPE_UNSIGNED_BIN); +} + +/* export ecc key to raw elements including public (Qx,Qy) and + * private (d) as unsigned bin + * return MP_OKAY on success, negative on error */ +int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen) +{ + return wc_ecc_export_ex(key, qx, qxLen, qy, qyLen, d, dLen, + WC_TYPE_UNSIGNED_BIN); +} + +#endif /* HAVE_ECC_KEY_EXPORT */ + +#ifdef HAVE_ECC_KEY_IMPORT +/* 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; +#if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A) + const CRYS_ECPKI_Domain_t* pDomain; + CRYS_ECPKI_BUILD_TempData_t tempBuff; +#endif + if (key == NULL || priv == NULL) + return BAD_FUNC_ARG; + + /* public optional, NULL if only importing private */ + if (pub != NULL) { + #ifndef NO_ASN + word32 idx = 0; + ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id); + if (ret < 0) + ret = wc_EccPublicKeyDecode(pub, &idx, key, pubSz); + key->type = ECC_PRIVATEKEY; + #else + ret = NOT_COMPILED_IN; + #endif + } + 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 + /* Hardware does not support loading private keys */ + return NOT_COMPILED_IN; +#elif defined(WOLFSSL_CRYPTOCELL) + pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id)); + + if (pub != NULL && pub[0] != '\0') { + /* create public key from external key buffer */ + ret = CRYS_ECPKI_BuildPublKeyFullCheck(pDomain, + (byte*)pub, + pubSz, + &key->ctx.pubKey, + &tempBuff); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECPKI_BuildPublKeyFullCheck failed"); + return ret; + } + } + /* import private key */ + if (priv != NULL && priv[0] != '\0') { + + /* Create private key from external key buffer*/ + ret = CRYS_ECPKI_BuildPrivKey(pDomain, + priv, + privSz, + &key->ctx.privKey); + + if (ret != SA_SILIB_RET_OK) { + WOLFSSL_MSG("CRYS_ECPKI_BuildPrivKey failed"); + return ret; + } + + ret = mp_read_unsigned_bin(&key->k, priv, privSz); + } + +#else ret = mp_read_unsigned_bin(&key->k, priv, privSz); +#ifdef HAVE_WOLF_BIGINT + if (ret == 0 && + wc_bigint_from_unsigned_bin(&key->k.raw, priv, privSz) != 0) { + mp_clear(&key->k); + ret = ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ + + +#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 return ret; } +/* ecc private key import, public key in ANSI X9.63 format, private raw */ +int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub, + word32 pubSz, ecc_key* key) +{ + return wc_ecc_import_private_key_ex(priv, privSz, pub, pubSz, key, + ECC_CURVE_DEF); +} +#endif /* HAVE_ECC_KEY_IMPORT */ + +#ifndef NO_ASN /** Convert ECC R,S to signature r R component of signature @@ -2754,53 +7570,232 @@ int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub, int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen) { int err; - mp_int rtmp; - mp_int stmp; +#ifdef WOLFSSL_SMALL_STACK + mp_int* rtmp = NULL; + mp_int* stmp = NULL; +#else + mp_int rtmp[1]; + mp_int stmp[1]; +#endif if (r == NULL || s == NULL || out == NULL || outlen == NULL) return ECC_BAD_ARG_E; - err = mp_init_multi(&rtmp, &stmp, NULL, NULL, NULL, NULL); - if (err != MP_OKAY) - return err; +#ifdef WOLFSSL_SMALL_STACK + rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rtmp == NULL) + return MEMORY_E; + stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (stmp == NULL) { + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif - err = mp_read_radix(&rtmp, r, 16); + err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL); + if (err != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + #endif + return err; + } + + 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) - err = StoreECC_DSA_Sig(out, outlen, &rtmp, &stmp); + err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp); if (err == MP_OKAY) { - if (mp_iszero(&rtmp) || mp_iszero(&stmp)) + if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES) err = MP_ZERO_E; } - mp_clear(&rtmp); - mp_clear(&stmp); + mp_clear(rtmp); + mp_clear(stmp); +#ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } /** - Import raw ECC key - key The destination ecc_key structure - qx x component of base point, as ASCII hex string - qy y component of base point, as ASCII hex string - d private key, as ASCII hex string - curveName ECC curve name, from ecc_sets[] - return MP_OKAY on success + Convert ECC R,S raw unsigned bin to signature + r R component of signature + rSz R size + s S component of signature + sSz S size + out DER-encoded ECDSA signature + outlen [in/out] output buffer size, output signature size + return MP_OKAY on success */ -int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, - const char* d, const char* curveName) +int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz, + byte* out, word32* outlen) { - int err, x; + int err; +#ifdef WOLFSSL_SMALL_STACK + mp_int* rtmp = NULL; + mp_int* stmp = NULL; +#else + mp_int rtmp[1]; + mp_int stmp[1]; +#endif - if (key == NULL || qx == NULL || qy == NULL || d == NULL || - curveName == NULL) + if (r == NULL || s == NULL || out == NULL || outlen == NULL) return ECC_BAD_ARG_E; +#ifdef WOLFSSL_SMALL_STACK + rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rtmp == NULL) + return MEMORY_E; + stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (stmp == NULL) { + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + + err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL); + if (err != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + #endif + return err; + } + + err = mp_read_unsigned_bin(rtmp, r, rSz); + if (err == MP_OKAY) + err = mp_read_unsigned_bin(stmp, s, sSz); + + /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */ + if (err == MP_OKAY) + err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp); + + if (err == MP_OKAY) { + if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES) + err = MP_ZERO_E; + } + + mp_clear(rtmp); + mp_clear(stmp); +#ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/** + Convert ECC signature to R,S + sig DER-encoded ECDSA signature + sigLen length of signature in octets + r R component of signature + rLen [in/out] output "r" buffer size, output "r" size + s S component of signature + sLen [in/out] output "s" buffer size, output "s" size + return MP_OKAY on success, negative on error +*/ +int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, + byte* s, word32* sLen) +{ + int err; + int tmp_valid = 0; + word32 x = 0; +#ifdef WOLFSSL_SMALL_STACK + mp_int* rtmp = NULL; + mp_int* stmp = NULL; +#else + mp_int rtmp[1]; + mp_int stmp[1]; +#endif + + if (sig == NULL || r == NULL || rLen == NULL || s == NULL || sLen == NULL) + return ECC_BAD_ARG_E; + +#ifdef WOLFSSL_SMALL_STACK + rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rtmp == NULL) + return MEMORY_E; + stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (stmp == NULL) { + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + + err = DecodeECC_DSA_Sig(sig, sigLen, rtmp, stmp); + + /* rtmp and stmp are initialized */ + if (err == MP_OKAY) { + tmp_valid = 1; + + /* extract r */ + x = mp_unsigned_bin_size(rtmp); + if (*rLen < x) + err = BUFFER_E; + } + if (err == MP_OKAY) { + *rLen = x; + err = mp_to_unsigned_bin(rtmp, r); + } + + /* extract s */ + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(stmp); + if (*sLen < x) + err = BUFFER_E; + + if (err == MP_OKAY) { + *sLen = x; + err = mp_to_unsigned_bin(stmp, s); + } + } + + if (tmp_valid) { + mp_clear(rtmp); + mp_clear(stmp); + } +#ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif /* !NO_ASN */ + +#ifdef HAVE_ECC_KEY_IMPORT +static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, + const char* qy, const char* d, int curve_id, int encType) +{ + int err = MP_OKAY; +#if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A) + const CRYS_ECPKI_Domain_t* pDomain; + CRYS_ECPKI_BUILD_TempData_t tempBuff; + byte key_raw[ECC_MAX_CRYPTO_HW_SIZE*2 + 1]; + word32 keySz = 0; +#endif + /* if d is NULL, only import as public key using Qx,Qy */ + if (key == NULL || qx == NULL || qy == NULL) { + 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) { + return err; + } + /* init key */ #ifdef ALT_ECC_SIZE key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; @@ -2811,45 +7806,120 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, 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); + if (err == MP_OKAY) { + if (encType == WC_TYPE_HEX_STR) + err = mp_read_radix(key->pubkey.x, qx, MP_RADIX_HEX); + else + err = mp_read_unsigned_bin(key->pubkey.x, (const byte*)qx, + key->dp->size); + } /* read Qy */ - if (err == MP_OKAY) - err = mp_read_radix(key->pubkey.y, qy, 16); - - if (err == MP_OKAY) - mp_set(key->pubkey.z, 1); - - /* read and set the curve */ if (err == MP_OKAY) { - for (x = 0; ecc_sets[x].size != 0; x++) { - if (XSTRNCMP(ecc_sets[x].name, curveName, - XSTRLEN(curveName)) == 0) { - break; - } + if (encType == WC_TYPE_HEX_STR) + err = mp_read_radix(key->pubkey.y, qy, MP_RADIX_HEX); + else + err = mp_read_unsigned_bin(key->pubkey.y, (const byte*)qy, + key->dp->size); + + } + + if (err == MP_OKAY) + err = mp_set(key->pubkey.z, 1); + +#ifdef WOLFSSL_ATECC508A + /* For SECP256R1 only save raw public key for hardware */ + if (err == MP_OKAY && curve_id == ECC_SECP256R1) { + word32 keySz = key->dp->size; + err = wc_export_int(key->pubkey.x, key->pubkey_raw, + &keySz, keySz, WC_TYPE_UNSIGNED_BIN); + if (err == MP_OKAY) + err = wc_export_int(key->pubkey.y, &key->pubkey_raw[keySz], + &keySz, keySz, WC_TYPE_UNSIGNED_BIN); + } +#elif defined(WOLFSSL_CRYPTOCELL) + if (err == MP_OKAY) { + key_raw[0] = ECC_POINT_UNCOMP; + keySz = (word32)key->dp->size; + err = wc_export_int(key->pubkey.x, &key_raw[1], &keySz, keySz, + WC_TYPE_UNSIGNED_BIN); + if (err == MP_OKAY) { + err = wc_export_int(key->pubkey.y, &key_raw[1+keySz], + &keySz, keySz, WC_TYPE_UNSIGNED_BIN); } - if (ecc_sets[x].size == 0) { - err = ASN_PARSE_E; - } else { - /* set the curve */ - key->idx = x; - key->dp = &ecc_sets[x]; - key->type = ECC_PUBLICKEY; + + if (err == MP_OKAY) { + pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id)); + + /* create public key from external key buffer */ + err = CRYS_ECPKI_BuildPublKeyFullCheck(pDomain, + key_raw, + keySz*2 + 1, + &key->ctx.pubKey, + &tempBuff); + } + + if (err != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECPKI_BuildPublKeyFullCheck failed"); + return err; } } +#endif + /* import private key */ if (err == MP_OKAY) { - key->type = ECC_PRIVATEKEY; - err = mp_read_radix(&key->k, d, 16); + if (d != NULL && d[0] != '\0') { + #ifdef WOLFSSL_ATECC508A + /* Hardware doesn't support loading private key */ + err = NOT_COMPILED_IN; + + #elif defined(WOLFSSL_CRYPTOCELL) + + key->type = ECC_PRIVATEKEY; + + if (encType == WC_TYPE_HEX_STR) + err = mp_read_radix(&key->k, d, MP_RADIX_HEX); + else + err = mp_read_unsigned_bin(&key->k, (const byte*)d, + key->dp->size); + if (err == MP_OKAY) { + err = wc_export_int(&key->k, &key_raw[0], &keySz, keySz, + WC_TYPE_UNSIGNED_BIN); + } + + if (err == MP_OKAY) { + /* Create private key from external key buffer*/ + err = CRYS_ECPKI_BuildPrivKey(pDomain, + key_raw, + keySz, + &key->ctx.privKey); + + if (err != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECPKI_BuildPrivKey failed"); + return err; + } + } + + #else + key->type = ECC_PRIVATEKEY; + + if (encType == WC_TYPE_HEX_STR) + err = mp_read_radix(&key->k, d, MP_RADIX_HEX); + else + err = mp_read_unsigned_bin(&key->k, (const byte*)d, + key->dp->size); + #endif /* WOLFSSL_ATECC508A */ + } else { + key->type = ECC_PUBLICKEY; + } } #ifdef WOLFSSL_VALIDATE_ECC_IMPORT @@ -2867,25 +7937,127 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, return err; } +/** + Import raw ECC key + key The destination ecc_key structure + qx x component of the public key, as ASCII hex string + qy y component of the public key, as ASCII hex string + d private key, as ASCII hex string, optional if importing public + key only + dp Custom ecc_set_type + return MP_OKAY on success +*/ +int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, + const char* d, int curve_id) +{ + return wc_ecc_import_raw_private(key, qx, qy, d, curve_id, + WC_TYPE_HEX_STR); + +} + +/* Import x, y and optional private (d) as unsigned binary */ +int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy, + byte* d, int curve_id) +{ + return wc_ecc_import_raw_private(key, (const char*)qx, (const char*)qy, + (const char*)d, curve_id, WC_TYPE_UNSIGNED_BIN); +} + +/** + Import raw ECC key + key The destination ecc_key structure + qx x component of the public key, as ASCII hex string + qy y component of the public key, as ASCII hex string + d private key, as ASCII hex string, optional if importing public + key only + curveName ECC curve name, from ecc_sets[] + return MP_OKAY on success +*/ +int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, + const char* d, const char* curveName) +{ + int err, x; + + /* if d is NULL, only import as public key using Qx,Qy */ + if (key == NULL || qx == NULL || qy == NULL || curveName == NULL) { + return BAD_FUNC_ARG; + } + + /* set curve type and index */ + for (x = 0; ecc_sets[x].size != 0; x++) { + if (XSTRNCMP(ecc_sets[x].name, curveName, + XSTRLEN(curveName)) == 0) { + break; + } + } + + if (ecc_sets[x].size == 0) { + WOLFSSL_MSG("ecc_set curve name not found"); + err = ASN_PARSE_E; + } else { + return wc_ecc_import_raw_private(key, qx, qy, d, ecc_sets[x].id, + WC_TYPE_HEX_STR); + } + + return err; +} +#endif /* HAVE_ECC_KEY_IMPORT */ /* key size in octets */ int wc_ecc_size(ecc_key* key) { - if (key == NULL) return 0; + if (key == NULL) + return 0; return key->dp->size; } +/* maximum signature size based on key size */ +int wc_ecc_sig_size_calc(int sz) +{ + int maxSigSz = 0; -/* worst case estimate, check actual return from wc_ecc_sign_hash for actual value - of signature size in octets */ + /* calculate based on key bits */ + /* maximum possible signature header size is 7 bytes plus 2 bytes padding */ + maxSigSz = (sz * 2) + SIG_HEADER_SZ + ECC_MAX_PAD_SZ; + + /* if total length is less than 128 + SEQ(1)+LEN(1) then subtract 1 */ + if (maxSigSz < (128 + 2)) { + maxSigSz -= 1; + } + + return maxSigSz; +} + +/* maximum signature size based on actual key curve */ int wc_ecc_sig_size(ecc_key* key) { - int sz = wc_ecc_size(key); - if (sz <= 0) - return sz; + int maxSigSz; + int orderBits, keySz; - return sz * 2 + SIG_HEADER_SZ + 4; /* (4) worst case estimate */ + if (key == NULL || key->dp == NULL) + return 0; + + /* the signature r and s will always be less than order */ + /* if the order MSB (top bit of byte) is set then ASN encoding needs + extra byte for r and s, so add 2 */ + keySz = key->dp->size; + orderBits = wc_ecc_get_curve_order_bit_count(key->dp); + if (orderBits > keySz * 8) { + keySz = (orderBits + 7) / 8; + } + /* maximum possible signature header size is 7 bytes */ + maxSigSz = (keySz * 2) + SIG_HEADER_SZ; + if ((orderBits % 8) == 0) { + /* MSB can be set, so add 2 */ + maxSigSz += ECC_MAX_PAD_SZ; + } + /* if total length is less than 128 + SEQ(1)+LEN(1) then subtract 1 */ + if (maxSigSz < (128 + 2)) { + maxSigSz -= 1; + } + + return maxSigSz; } @@ -2894,7 +8066,7 @@ int wc_ecc_sig_size(ecc_key* key) /* fixed point ECC cache */ /* number of entries in the cache */ #ifndef FP_ENTRIES - #define FP_ENTRIES 16 + #define FP_ENTRIES 15 #endif /* number of bits in LUT */ @@ -2914,10 +8086,12 @@ int wc_ecc_sig_size(ecc_key* key) #endif +#ifndef WOLFSSL_SP_MATH + /** Our FP cache */ typedef struct { ecc_point* g; /* cached COPY of base point */ - ecc_point* LUT[1U< 6 - { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 }, - { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 }, - { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 }, - { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 }, - { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 }, - { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 }, - { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 }, - { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 }, + { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 }, + { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 }, + { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 }, + { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 }, + { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 }, + { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 }, + { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 }, + { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 }, #if FP_LUT > 7 - { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 }, - { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 }, - { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 }, - { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 }, - { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 }, - { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 }, - { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 }, - { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 }, - { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 }, - { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 }, - { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 }, - { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 }, - { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 }, - { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 }, - { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 }, - { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 }, + { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 }, + { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 }, + { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 }, + { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 }, + { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 }, + { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 }, + { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 }, + { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 }, + { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 }, + { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 }, + { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 }, + { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 }, + { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 }, + { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 }, + { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 }, + { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 }, #if FP_LUT > 8 - { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 }, - { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 }, - { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 }, - { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 }, - { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 }, - { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 }, - { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 }, - { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 }, - { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 }, - { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 }, - { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 }, - { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 }, - { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 }, - { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 }, - { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 }, - { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 }, - { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 }, - { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 }, - { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 }, - { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 }, - { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 }, - { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 }, - { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 }, - { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 }, - { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 }, - { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 }, - { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 }, - { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 }, - { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 }, - { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 }, - { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 }, - { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 }, + { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 }, + { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 }, + { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 }, + { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 }, + { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 }, + { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 }, + { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 }, + { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 }, + { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 }, + { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 }, + { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 }, + { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 }, + { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 }, + { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 }, + { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 }, + { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 }, + { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 }, + { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 }, + { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 }, + { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 }, + { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 }, + { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 }, + { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 }, + { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 }, + { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 }, + { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 }, + { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 }, + { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 }, + { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 }, + { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 }, + { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 }, + { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 }, #if FP_LUT > 9 - { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 }, - { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 }, - { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 }, - { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 }, - { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 }, - { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 }, - { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 }, - { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 }, - { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 }, - { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 }, - { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 }, - { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 }, - { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 }, - { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 }, - { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 }, - { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 }, - { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 }, - { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 }, - { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 }, - { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 }, - { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 }, - { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 }, - { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 }, - { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 }, - { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 }, - { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 }, - { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 }, - { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 }, - { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 }, - { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 }, - { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 }, - { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 }, - { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 }, - { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 }, - { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 }, - { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 }, - { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 }, - { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 }, - { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 }, - { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 }, - { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 }, - { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 }, - { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 }, - { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 }, - { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 }, - { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 }, - { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 }, - { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 }, - { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 }, - { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 }, - { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 }, - { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 }, - { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 }, - { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 }, - { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 }, - { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 }, - { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 }, - { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 }, - { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 }, - { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 }, - { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 }, - { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 }, - { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 }, - { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 }, + { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 }, + { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 }, + { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 }, + { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 }, + { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 }, + { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 }, + { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 }, + { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 }, + { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 }, + { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 }, + { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 }, + { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 }, + { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 }, + { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 }, + { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 }, + { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 }, + { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 }, + { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 }, + { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 }, + { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 }, + { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 }, + { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 }, + { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 }, + { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 }, + { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 }, + { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 }, + { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 }, + { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 }, + { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 }, + { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 }, + { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 }, + { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 }, + { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 }, + { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 }, + { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 }, + { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 }, + { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 }, + { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 }, + { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 }, + { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 }, + { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 }, + { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 }, + { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 }, + { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 }, + { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 }, + { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 }, + { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 }, + { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 }, + { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 }, + { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 }, + { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 }, + { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 }, + { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 }, + { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 }, + { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 }, + { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 }, + { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 }, + { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 }, + { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 }, + { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 }, + { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 }, + { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 }, + { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 }, + { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 }, #if FP_LUT > 10 - { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 }, - { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 }, - { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 }, - { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 }, - { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 }, - { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 }, - { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 }, - { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 }, - { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 }, - { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 }, - { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 }, - { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 }, - { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 }, - { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 }, - { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 }, - { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 }, - { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 }, - { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 }, - { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 }, - { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 }, - { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 }, - { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 }, - { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 }, - { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 }, - { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 }, - { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 }, - { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 }, - { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 }, - { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 }, - { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 }, - { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 }, - { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 }, - { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 }, - { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 }, - { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 }, - { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 }, - { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 }, - { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 }, - { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 }, - { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 }, - { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 }, - { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 }, - { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 }, - { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 }, - { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 }, - { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 }, - { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 }, - { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 }, - { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 }, - { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 }, - { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 }, - { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 }, - { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 }, - { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 }, - { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 }, - { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 }, - { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 }, - { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 }, - { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 }, - { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 }, - { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 }, - { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 }, - { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 }, - { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 }, - { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 }, - { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 }, - { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 }, - { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 }, - { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 }, - { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 }, - { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 }, - { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 }, - { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 }, - { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 }, - { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 }, - { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 }, - { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 }, - { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 }, - { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 }, - { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 }, - { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 }, - { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 }, - { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 }, - { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 }, - { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 }, - { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 }, - { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 }, - { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 }, - { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 }, - { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 }, - { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 }, - { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 }, - { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 }, - { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 }, - { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 }, - { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 }, - { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 }, - { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 }, - { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 }, - { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 }, - { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 }, - { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 }, - { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 }, - { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 }, - { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 }, - { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 }, - { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 }, - { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 }, - { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 }, - { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 }, - { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 }, - { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 }, - { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 }, - { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 }, - { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 }, - { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 }, - { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 }, - { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 }, - { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 }, - { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 }, - { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 }, - { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 }, - { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 }, - { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 }, - { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 }, - { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 }, - { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 }, - { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 }, + { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 }, + { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 }, + { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 }, + { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 }, + { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 }, + { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 }, + { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 }, + { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 }, + { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 }, + { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 }, + { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 }, + { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 }, + { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 }, + { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 }, + { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 }, + { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 }, + { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 }, + { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 }, + { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 }, + { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 }, + { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 }, + { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 }, + { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 }, + { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 }, + { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 }, + { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 }, + { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 }, + { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 }, + { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 }, + { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 }, + { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 }, + { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 }, + { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 }, + { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 }, + { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 }, + { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 }, + { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 }, + { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 }, + { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 }, + { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 }, + { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 }, + { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 }, + { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 }, + { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 }, + { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 }, + { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 }, + { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 }, + { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 }, + { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 }, + { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 }, + { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 }, + { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 }, + { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 }, + { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 }, + { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 }, + { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 }, + { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 }, + { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 }, + { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 }, + { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 }, + { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 }, + { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 }, + { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 }, + { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 }, + { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 }, + { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 }, + { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 }, + { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 }, + { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 }, + { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 }, + { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 }, + { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 }, + { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 }, + { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 }, + { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 }, + { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 }, + { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 }, + { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 }, + { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 }, + { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 }, + { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 }, + { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 }, + { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 }, + { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 }, + { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 }, + { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 }, + { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 }, + { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 }, + { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 }, + { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 }, + { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 }, + { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 }, + { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 }, + { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 }, + { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 }, + { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 }, + { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 }, + { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 }, + { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 }, + { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 }, + { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 }, + { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 }, + { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 }, + { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 }, + { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 }, + { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 }, + { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 }, + { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 }, + { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 }, + { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 }, + { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 }, + { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 }, + { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 }, + { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 }, + { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 }, + { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 }, + { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 }, + { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 }, + { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 }, + { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 }, + { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 }, + { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 }, + { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 }, + { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 }, + { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 }, + { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 }, + { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 }, + { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 }, #if FP_LUT > 11 - { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 }, - { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 }, - { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 }, - { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 }, - { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 }, - { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 }, - { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 }, - { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 }, - { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 }, - { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 }, - { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 }, - { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 }, - { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 }, - { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 }, - { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 }, - { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 }, - { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 }, - { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 }, - { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 }, - { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 }, - { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 }, - { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 }, - { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 }, - { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 }, - { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 }, - { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 }, - { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 }, - { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 }, - { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 }, - { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 }, - { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 }, - { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 }, - { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 }, - { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 }, - { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 }, - { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 }, - { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 }, - { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 }, - { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 }, - { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 }, - { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 }, - { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 }, - { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 }, - { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 }, - { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 }, - { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 }, - { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 }, - { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 }, - { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 }, - { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 }, - { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 }, - { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 }, - { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 }, - { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 }, - { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 }, - { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 }, - { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 }, - { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 }, - { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 }, - { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 }, - { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 }, - { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 }, - { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 }, - { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 }, - { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 }, - { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 }, - { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 }, - { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 }, - { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 }, - { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 }, - { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 }, - { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 }, - { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 }, - { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 }, - { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 }, - { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 }, - { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 }, - { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 }, - { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 }, - { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 }, - { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 }, - { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 }, - { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 }, - { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 }, - { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 }, - { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 }, - { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 }, - { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 }, - { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 }, - { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 }, - { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 }, - { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 }, - { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 }, - { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 }, - { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 }, - { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 }, - { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 }, - { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 }, - { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 }, - { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 }, - { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 }, - { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 }, - { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 }, - { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 }, - { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 }, - { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 }, - { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 }, - { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 }, - { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 }, - { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 }, - { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 }, - { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 }, - { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 }, - { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 }, - { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 }, - { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 }, - { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 }, - { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 }, - { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 }, - { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 }, - { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 }, - { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 }, - { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 }, - { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 }, - { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 }, - { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 }, - { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 }, - { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 }, - { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 }, - { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 }, - { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 }, - { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 }, - { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 }, - { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 }, - { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 }, - { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 }, - { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 }, - { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 }, - { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 }, - { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 }, - { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 }, - { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 }, - { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 }, - { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 }, - { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 }, - { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 }, - { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 }, - { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 }, - { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 }, - { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 }, - { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 }, - { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 }, - { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 }, - { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 }, - { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 }, - { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 }, - { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 }, - { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 }, - { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 }, - { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 }, - { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 }, - { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 }, - { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 }, - { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 }, - { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 }, - { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 }, - { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 }, - { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 }, - { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 }, - { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 }, - { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 }, - { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 }, - { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 }, - { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 }, - { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 }, - { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 }, - { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 }, - { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 }, - { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 }, - { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 }, - { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 }, - { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 }, - { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 }, - { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 }, - { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 }, - { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 }, - { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 }, - { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 }, - { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 }, - { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 }, - { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 }, - { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 }, - { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 }, - { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 }, - { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 }, - { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 }, - { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 }, - { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 }, - { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 }, - { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 }, - { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 }, - { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 }, - { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 }, - { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 }, - { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 }, - { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 }, - { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 }, - { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 }, - { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 }, - { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 }, - { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 }, - { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 }, - { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 }, - { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 }, - { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 }, - { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 }, - { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 }, - { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 }, - { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 }, - { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 }, - { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 }, - { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 }, - { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 }, - { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 }, - { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 }, - { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 }, - { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 }, - { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 }, - { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 }, - { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 }, - { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 }, - { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 }, - { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 }, - { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 }, - { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 }, - { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 }, - { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 }, - { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 }, - { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 }, - { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 }, - { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 }, - { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 }, - { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 }, - { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 }, - { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 }, - { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 }, - { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 }, - { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 }, - { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 }, - { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 }, - { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 }, - { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 }, - { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 }, - { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 }, - { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 }, - { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 }, + { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 }, + { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 }, + { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 }, + { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 }, + { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 }, + { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 }, + { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 }, + { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 }, + { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 }, + { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 }, + { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 }, + { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 }, + { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 }, + { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 }, + { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 }, + { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 }, + { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 }, + { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 }, + { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 }, + { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 }, + { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 }, + { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 }, + { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 }, + { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 }, + { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 }, + { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 }, + { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 }, + { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 }, + { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 }, + { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 }, + { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 }, + { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 }, + { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 }, + { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 }, + { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 }, + { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 }, + { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 }, + { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 }, + { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 }, + { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 }, + { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 }, + { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 }, + { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 }, + { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 }, + { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 }, + { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 }, + { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 }, + { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 }, + { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 }, + { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 }, + { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 }, + { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 }, + { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 }, + { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 }, + { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 }, + { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 }, + { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 }, + { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 }, + { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 }, + { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 }, + { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 }, + { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 }, + { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 }, + { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 }, + { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 }, + { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 }, + { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 }, + { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 }, + { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 }, + { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 }, + { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 }, + { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 }, + { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 }, + { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 }, + { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 }, + { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 }, + { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 }, + { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 }, + { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 }, + { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 }, + { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 }, + { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 }, + { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 }, + { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 }, + { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 }, + { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 }, + { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 }, + { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 }, + { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 }, + { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 }, + { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 }, + { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 }, + { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 }, + { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 }, + { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 }, + { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 }, + { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 }, + { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 }, + { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 }, + { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 }, + { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 }, + { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 }, + { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 }, + { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 }, + { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 }, + { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 }, + { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 }, + { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 }, + { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 }, + { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 }, + { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 }, + { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 }, + { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 }, + { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 }, + { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 }, + { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 }, + { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 }, + { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 }, + { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 }, + { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 }, + { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 }, + { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 }, + { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 }, + { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 }, + { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 }, + { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 }, + { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 }, + { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 }, + { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 }, + { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 }, + { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 }, + { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 }, + { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 }, + { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 }, + { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 }, + { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 }, + { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 }, + { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 }, + { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 }, + { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 }, + { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 }, + { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 }, + { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 }, + { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 }, + { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 }, + { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 }, + { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 }, + { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 }, + { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 }, + { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 }, + { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 }, + { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 }, + { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 }, + { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 }, + { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 }, + { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 }, + { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 }, + { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 }, + { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 }, + { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 }, + { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 }, + { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 }, + { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 }, + { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 }, + { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 }, + { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 }, + { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 }, + { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 }, + { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 }, + { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 }, + { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 }, + { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 }, + { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 }, + { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 }, + { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 }, + { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 }, + { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 }, + { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 }, + { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 }, + { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 }, + { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 }, + { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 }, + { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 }, + { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 }, + { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 }, + { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 }, + { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 }, + { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 }, + { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 }, + { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 }, + { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 }, + { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 }, + { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 }, + { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 }, + { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 }, + { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 }, + { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 }, + { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 }, + { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 }, + { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 }, + { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 }, + { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 }, + { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 }, + { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 }, + { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 }, + { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 }, + { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 }, + { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 }, + { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 }, + { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 }, + { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 }, + { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 }, + { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 }, + { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 }, + { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 }, + { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 }, + { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 }, + { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 }, + { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 }, + { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 }, + { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 }, + { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 }, + { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 }, + { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 }, + { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 }, + { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 }, + { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 }, + { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 }, + { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 }, + { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 }, + { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 }, + { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 }, + { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 }, + { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 }, + { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 }, + { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 }, + { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 }, + { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 }, + { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 }, + { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 }, + { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 }, + { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 }, + { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 }, + { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 }, + { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 }, + { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 }, + { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 }, + { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 }, + { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 }, + { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 }, + { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 }, + { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 }, + { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 }, + { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 }, + { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 }, + { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 }, #endif #endif #endif @@ -3462,6 +8636,7 @@ static const struct { #endif }; + /* find a hole and free as required, return -1 if no hole found */ static int find_hole(void) { @@ -3484,10 +8659,10 @@ static int find_hole(void) /* free entry z */ if (z >= 0 && fp_cache[z].g) { mp_clear(&fp_cache[z].mu); - ecc_del_point(fp_cache[z].g); + wc_ecc_del_point(fp_cache[z].g); fp_cache[z].g = NULL; for (x = 0; x < (1U<x, g->x) == MP_EQ && - mp_cmp(fp_cache[x].g->y, g->y) == MP_EQ && + if (fp_cache[x].g != NULL && + mp_cmp(fp_cache[x].g->x, g->x) == MP_EQ && + mp_cmp(fp_cache[x].g->y, g->y) == MP_EQ && mp_cmp(fp_cache[x].g->z, g->z) == MP_EQ) { break; } @@ -3519,7 +8694,7 @@ static int add_entry(int idx, ecc_point *g) unsigned x, y; /* allocate base and LUT */ - fp_cache[idx].g = ecc_new_point(); + fp_cache[idx].g = wc_ecc_new_point(); if (fp_cache[idx].g == NULL) { return GEN_MEM_ERR; } @@ -3528,38 +8703,42 @@ static int add_entry(int idx, ecc_point *g) if ((mp_copy(g->x, fp_cache[idx].g->x) != MP_OKAY) || (mp_copy(g->y, fp_cache[idx].g->y) != MP_OKAY) || (mp_copy(g->z, fp_cache[idx].g->z) != MP_OKAY)) { - ecc_del_point(fp_cache[idx].g); + wc_ecc_del_point(fp_cache[idx].g); fp_cache[idx].g = NULL; return GEN_MEM_ERR; - } + } for (x = 0; x < (1U<x, mu, modulus, - fp_cache[idx].LUT[1]->x) != MP_OKAY) || + fp_cache[idx].LUT[1]->x) != MP_OKAY) || (mp_mulmod(fp_cache[idx].g->y, mu, modulus, - fp_cache[idx].LUT[1]->y) != MP_OKAY) || + fp_cache[idx].LUT[1]->y) != MP_OKAY) || (mp_mulmod(fp_cache[idx].g->z, mu, modulus, fp_cache[idx].LUT[1]->z) != MP_OKAY)) { - err = MP_MULMOD_E; + err = MP_MULMOD_E; } } - + /* make all single bit entries */ for (x = 1; x < FP_LUT; x++) { if (err != MP_OKAY) break; if ((mp_copy(fp_cache[idx].LUT[1<<(x-1)]->x, - fp_cache[idx].LUT[1<x) != MP_OKAY) || + fp_cache[idx].LUT[1<x) != MP_OKAY) || (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->y, - fp_cache[idx].LUT[1<y) != MP_OKAY) || + fp_cache[idx].LUT[1<y) != MP_OKAY) || (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z, fp_cache[idx].LUT[1<z) != MP_OKAY)){ err = MP_INIT_E; break; } else { - + /* now double it bitlen/FP_LUT times */ for (y = 0; y < lut_gap; y++) { if ((err = ecc_projective_dbl_point(fp_cache[idx].LUT[1<z, modulus, *mp); - + err = mp_montgomery_reduce(fp_cache[idx].LUT[x]->z, modulus, mp); + /* invert it */ if (err == MP_OKAY) err = mp_invmod(fp_cache[idx].LUT[x]->z, modulus, @@ -3654,7 +8831,7 @@ static int build_lut(int idx, mp_int* modulus, mp_digit* mp, mp_int* mu) if (err == MP_OKAY) /* now square it */ err = mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, &tmp); - + if (err == MP_OKAY) /* fix x */ err = mp_mulmod(fp_cache[idx].LUT[x]->x, &tmp, modulus, @@ -3673,6 +8850,7 @@ static int build_lut(int idx, mp_int* modulus, mp_digit* mp, mp_int* mu) /* free z */ mp_clear(fp_cache[idx].LUT[x]->z); } + mp_clear(&tmp); if (err == MP_OKAY) @@ -3680,107 +8858,99 @@ static int build_lut(int idx, mp_int* modulus, mp_digit* mp, mp_int* mu) /* err cleanup */ for (y = 0; y < (1U< mp_unsigned_bin_size(modulus)) { - mp_int order; - if (mp_init(&order) != MP_OKAY) { - mp_clear(&tk); - return MP_INIT_E; - } - /* find order */ y = mp_unsigned_bin_size(modulus); for (x = 0; ecc_sets[x].size; x++) { if (y <= (unsigned)ecc_sets[x].size) break; } - + /* 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) { - mp_clear(&order); - mp_clear(&tk); - return err; + + if ((err = mp_read_radix(&order, ecc_sets[x].order, + MP_RADIX_HEX)) != MP_OKAY) { + goto done; } /* k must be less than modulus */ if (mp_cmp(k, &order) != MP_LT) { if ((err = mp_mod(k, &order, &tk)) != MP_OKAY) { - mp_clear(&tk); - mp_clear(&order); - return err; + goto done; } } else { - mp_copy(k, &tk); + if ((err = mp_copy(k, &tk)) != MP_OKAY) { + goto done; + } } - mp_clear(&order); } 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 */ bitlen = mp_unsigned_bin_size(modulus) << 3; x = bitlen % FP_LUT; if (x) { bitlen += FP_LUT - x; - } + } lut_gap = bitlen / FP_LUT; - + /* get the k value */ if (mp_unsigned_bin_size(&tk) > (int)(KB_SIZE - 2)) { - mp_clear(&tk); - return BUFFER_E; + err = BUFFER_E; goto done; } - + /* store k */ #ifdef WOLFSSL_SMALL_STACK - kb = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (kb == NULL) - return MEMORY_E; + kb = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (kb == NULL) { + err = MEMORY_E; goto done; + } #endif XMEMSET(kb, 0, KB_SIZE); - if ((err = mp_to_unsigned_bin(&tk, kb)) != MP_OKAY) { - mp_clear(&tk); - } - else { + if ((err = mp_to_unsigned_bin(&tk, kb)) == MP_OKAY) { /* let's reverse kb so it's little endian */ x = 0; - y = mp_unsigned_bin_size(&tk) - 1; - mp_clear(&tk); + y = mp_unsigned_bin_size(&tk); + if (y > 0) { + y -= 1; + } 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; } @@ -3798,7 +8968,7 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus, /* double if not first */ if (!first) { - if ((err = ecc_projective_dbl_point(R, R, modulus, + if ((err = ecc_projective_dbl_point(R, R, a, modulus, mp)) != MP_OKAY) { break; } @@ -3806,10 +8976,35 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus, /* add if not first, otherwise copy */ if (!first && z) { - if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R, + if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R, a, modulus, mp)) != MP_OKAY) { break; } + if (mp_iszero(R->z)) { + /* When all zero then should have done an add */ + if (mp_iszero(R->x) && mp_iszero(R->y)) { + if ((err = ecc_projective_dbl_point(fp_cache[idx].LUT[z], + R, a, modulus, mp)) != MP_OKAY) { + break; + } + } + /* When only Z zero then result is infinity */ + else { + err = mp_set(R->x, 0); + if (err != MP_OKAY) { + break; + } + err = mp_set(R->y, 0); + if (err != MP_OKAY) { + break; + } + err = mp_copy(&fp_cache[idx].mu, R->z); + if (err != MP_OKAY) { + break; + } + first = 1; + } + } } else if (z) { if ((mp_copy(fp_cache[idx].LUT[z]->x, R->x) != MP_OKAY) || (mp_copy(fp_cache[idx].LUT[z]->y, R->y) != MP_OKAY) || @@ -3817,14 +9012,15 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus, err = GEN_MEM_ERR; break; } - first = 0; + first = 0; } } } if (err == MP_OKAY) { - z = 0; + (void) z; /* Acknowledge the unused assignment */ ForceZero(kb, KB_SIZE); + /* map R back from projective space */ if (map) { err = ecc_map(R, modulus, mp); @@ -3833,35 +9029,41 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus, } } +done: + /* cleanup */ + mp_clear(&order); + mp_clear(&tk); + #ifdef WOLFSSL_SMALL_STACK - XFREE(kb, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(kb, NULL, DYNAMIC_TYPE_ECC_BUFFER); #endif #undef KB_SIZE return err; } +#endif #ifdef ECC_SHAMIR +#ifndef WOLFSSL_SP_MATH /* perform a fixed point ECC mulmod */ -static int accel_fp_mul2add(int idx1, int idx2, +static int accel_fp_mul2add(int idx1, int idx2, mp_int* kA, mp_int* kB, - ecc_point *R, mp_int* modulus, mp_digit* mp) + ecc_point *R, mp_int* a, + mp_int* modulus, mp_digit mp) { #define KB_SIZE 128 #ifdef WOLFSSL_SMALL_STACK - unsigned char* kb[2]; + unsigned char* kb[2] = {NULL, NULL}; #else - unsigned char kb[2][128]; + unsigned char kb[2][KB_SIZE]; #endif - int x; - unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB; - mp_int tka; - mp_int tkb; - mp_int order; + int x, err; + unsigned y, z, bitlen, bitpos, lut_gap, first, zA, zB; + mp_int tka, tkb, order; - if (mp_init_multi(&tka, &tkb, 0, 0, 0, 0) != MP_OKAY) + if (mp_init_multi(&tka, &tkb, &order, NULL, NULL, NULL) != MP_OKAY) return MP_INIT_E; /* if it's smaller than modulus we fine */ @@ -3871,37 +9073,30 @@ static int accel_fp_mul2add(int idx1, int idx2, for (x = 0; ecc_sets[x].size; x++) { if (y <= (unsigned)ecc_sets[x].size) break; } - + /* back off if we are on the 521 bit curve */ if (y == 66) --x; - - if ((err = mp_init(&order)) != MP_OKAY) { - mp_clear(&tkb); - mp_clear(&tka); - return err; - } - if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) { - mp_clear(&tkb); - mp_clear(&tka); - mp_clear(&order); - return err; + + if ((err = mp_read_radix(&order, ecc_sets[x].order, + MP_RADIX_HEX)) != MP_OKAY) { + goto done; } /* kA must be less than modulus */ if (mp_cmp(kA, &order) != MP_LT) { if ((err = mp_mod(kA, &order, &tka)) != MP_OKAY) { - mp_clear(&tkb); - mp_clear(&tka); - mp_clear(&order); - return err; + goto done; } } else { - mp_copy(kA, &tka); + if ((err = mp_copy(kA, &tka)) != MP_OKAY) { + goto done; + } } - mp_clear(&order); } else { - mp_copy(kA, &tka); - } + if ((err = mp_copy(kA, &tka)) != MP_OKAY) { + goto done; + } + } /* if it's smaller than modulus we fine */ if (mp_unsigned_bin_size(kB) > mp_unsigned_bin_size(modulus)) { @@ -3910,97 +9105,88 @@ static int accel_fp_mul2add(int idx1, int idx2, for (x = 0; ecc_sets[x].size; x++) { if (y <= (unsigned)ecc_sets[x].size) break; } - + /* back off if we are on the 521 bit curve */ if (y == 66) --x; - - if ((err = mp_init(&order)) != MP_OKAY) { - mp_clear(&tkb); - mp_clear(&tka); - return err; - } - if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) { - mp_clear(&tkb); - mp_clear(&tka); - mp_clear(&order); - return err; + + if ((err = mp_read_radix(&order, ecc_sets[x].order, + MP_RADIX_HEX)) != MP_OKAY) { + goto done; } /* kB must be less than modulus */ if (mp_cmp(kB, &order) != MP_LT) { if ((err = mp_mod(kB, &order, &tkb)) != MP_OKAY) { - mp_clear(&tkb); - mp_clear(&tka); - mp_clear(&order); - return err; + goto done; } } else { - mp_copy(kB, &tkb); + if ((err = mp_copy(kB, &tkb)) != MP_OKAY) { + goto done; + } } - mp_clear(&order); } 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 */ bitlen = mp_unsigned_bin_size(modulus) << 3; x = bitlen % FP_LUT; if (x) { bitlen += FP_LUT - x; - } + } lut_gap = bitlen / FP_LUT; - + /* get the k value */ if ((mp_unsigned_bin_size(&tka) > (int)(KB_SIZE - 2)) || (mp_unsigned_bin_size(&tkb) > (int)(KB_SIZE - 2)) ) { - mp_clear(&tka); - mp_clear(&tkb); - return BUFFER_E; + err = BUFFER_E; goto done; } - + /* store k */ #ifdef WOLFSSL_SMALL_STACK - kb[0] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (kb[0] == NULL) - return MEMORY_E; + kb[0] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (kb[0] == NULL) { + err = MEMORY_E; goto done; + } #endif XMEMSET(kb[0], 0, KB_SIZE); if ((err = mp_to_unsigned_bin(&tka, kb[0])) != MP_OKAY) { - mp_clear(&tka); - mp_clear(&tkb); - XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER); - return err; + goto done; } - + /* let's reverse kb so it's little endian */ x = 0; - y = mp_unsigned_bin_size(&tka) - 1; + y = mp_unsigned_bin_size(&tka); + if (y > 0) { + y -= 1; + } 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) { - XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; + err = MEMORY_E; goto done; } #endif XMEMSET(kb[1], 0, KB_SIZE); - if ((err = mp_to_unsigned_bin(&tkb, kb[1])) != MP_OKAY) { - mp_clear(&tkb); - } - else { + if ((err = mp_to_unsigned_bin(&tkb, kb[1])) == MP_OKAY) { x = 0; - y = mp_unsigned_bin_size(&tkb) - 1; - mp_clear(&tkb); + y = mp_unsigned_bin_size(&tkb); + if (y > 0) { + y -= 1; + } + 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; } @@ -4019,31 +9205,82 @@ static int accel_fp_mul2add(int idx1, int idx2, /* double if not first */ if (!first) { - if ((err = ecc_projective_dbl_point(R, R, modulus, + if ((err = ecc_projective_dbl_point(R, R, a, modulus, mp)) != MP_OKAY) { break; } - } - /* add if not first, otherwise copy */ - if (!first) { + /* add if not first, otherwise copy */ if (zA) { if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA], - R, modulus, mp)) != MP_OKAY) { + R, a, modulus, mp)) != MP_OKAY) { break; } + if (mp_iszero(R->z)) { + /* When all zero then should have done an add */ + if (mp_iszero(R->x) && mp_iszero(R->y)) { + if ((err = ecc_projective_dbl_point( + fp_cache[idx1].LUT[zA], R, + a, modulus, mp)) != MP_OKAY) { + break; + } + } + /* When only Z zero then result is infinity */ + else { + err = mp_set(R->x, 0); + if (err != MP_OKAY) { + break; + } + err = mp_set(R->y, 0); + if (err != MP_OKAY) { + break; + } + err = mp_copy(&fp_cache[idx1].mu, R->z); + if (err != MP_OKAY) { + break; + } + first = 1; + } + } } + if (zB) { if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB], - R, modulus, mp)) != MP_OKAY) { + R, a, modulus, mp)) != MP_OKAY) { break; } + if (mp_iszero(R->z)) { + /* When all zero then should have done an add */ + if (mp_iszero(R->x) && mp_iszero(R->y)) { + if ((err = ecc_projective_dbl_point( + fp_cache[idx2].LUT[zB], R, + a, modulus, mp)) != MP_OKAY) { + break; + } + } + /* When only Z zero then result is infinity */ + else { + err = mp_set(R->x, 0); + if (err != MP_OKAY) { + break; + } + err = mp_set(R->y, 0); + if (err != MP_OKAY) { + break; + } + err = mp_copy(&fp_cache[idx2].mu, R->z); + if (err != MP_OKAY) { + break; + } + first = 1; + } + } } } else { if (zA) { if ((mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != MP_OKAY) || - (mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != MP_OKAY) || - (mp_copy(&fp_cache[idx1].mu, R->z) != MP_OKAY)) { + (mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != MP_OKAY) || + (mp_copy(&fp_cache[idx1].mu, R->z) != MP_OKAY)) { err = GEN_MEM_ERR; break; } @@ -4052,14 +9289,40 @@ static int accel_fp_mul2add(int idx1, int idx2, if (zB && first == 0) { if (zB) { if ((err = ecc_projective_add_point(R, - fp_cache[idx2].LUT[zB], R, modulus, mp)) != MP_OKAY){ + fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != MP_OKAY){ break; } + if (mp_iszero(R->z)) { + /* When all zero then should have done an add */ + if (mp_iszero(R->x) && mp_iszero(R->y)) { + if ((err = ecc_projective_dbl_point( + fp_cache[idx2].LUT[zB], R, + a, modulus, mp)) != MP_OKAY) { + break; + } + } + /* When only Z zero then result is infinity */ + else { + err = mp_set(R->x, 0); + if (err != MP_OKAY) { + break; + } + err = mp_set(R->y, 0); + if (err != MP_OKAY) { + break; + } + err = mp_copy(&fp_cache[idx2].mu, R->z); + if (err != MP_OKAY) { + break; + } + first = 1; + } + } } } else if (zB && first == 1) { if ((mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != MP_OKAY) || - (mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != MP_OKAY) || - (mp_copy(&fp_cache[idx2].mu, R->z) != MP_OKAY)) { + (mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != MP_OKAY) || + (mp_copy(&fp_cache[idx2].mu, R->z) != MP_OKAY)) { err = GEN_MEM_ERR; break; } @@ -4069,47 +9332,64 @@ static int accel_fp_mul2add(int idx1, int idx2, } } - ForceZero(kb[0], KB_SIZE); - ForceZero(kb[1], KB_SIZE); +done: + /* cleanup */ + mp_clear(&tkb); + mp_clear(&tka); + mp_clear(&order); #ifdef WOLFSSL_SMALL_STACK - XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(kb[1], NULL, DYNAMIC_TYPE_TMP_BUFFER); + 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_ECC_BUFFER); + XFREE(kb[1], NULL, DYNAMIC_TYPE_ECC_BUFFER); #endif #undef KB_SIZE + if (err != MP_OKAY) + return err; + return ecc_map(R, modulus, mp); } -/** ECC Fixed Point mulmod global + +/** ECC Fixed Point mulmod global with heap hint used Computes kA*A + kB*B = C using Shamir's Trick A First point to multiply kA What to multiple A by B Second point to multiply kB What to multiple B by C [out] Destination point (can overlap with A or B) - modulus Modulus for curve + a ECC curve parameter a + modulus Modulus for curve return MP_OKAY on success -*/ +*/ int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, - ecc_point* C, mp_int* modulus) + ecc_point* C, mp_int* a, mp_int* modulus, void* heap) { - int idx1 = -1, idx2 = -1, err = MP_OKAY, mpInit = 0; + int idx1 = -1, idx2 = -1, err, mpInit = 0; mp_digit mp; mp_int mu; - + err = mp_init(&mu); if (err != MP_OKAY) return err; #ifndef HAVE_THREAD_LS if (initMutex == 0) { - InitMutex(&ecc_fp_lock); + wc_InitMutex(&ecc_fp_lock); initMutex = 1; } - if (LockMutex(&ecc_fp_lock) != 0) + if (wc_LockMutex(&ecc_fp_lock) != 0) return BAD_MUTEX_E; #endif /* HAVE_THREAD_LS */ @@ -4128,11 +9408,10 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, ++(fp_cache[idx1].lru_count); } - if (err == MP_OKAY) + if (err == MP_OKAY) { /* find point */ idx2 = find_base(B); - if (err == MP_OKAY) { /* no entry? */ if (idx2 == -1) { /* find hole and add it */ @@ -4156,10 +9435,10 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, mpInit = 1; err = mp_montgomery_calc_normalization(&mu, modulus); } - + if (err == MP_OKAY) /* build the LUT */ - err = build_lut(idx1, modulus, &mp, &mu); + err = build_lut(idx1, a, modulus, mp, &mu); } } @@ -4174,10 +9453,10 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, err = mp_montgomery_calc_normalization(&mu, modulus); } } - - if (err == MP_OKAY) + + if (err == MP_OKAY) /* build the LUT */ - err = build_lut(idx2, modulus, &mp, &mu); + err = build_lut(idx2, a, modulus, mp, &mu); } } @@ -4190,48 +9469,55 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, err = mp_montgomery_setup(modulus, &mp); } if (err == MP_OKAY) - err = accel_fp_mul2add(idx1, idx2, kA, kB, C, modulus, &mp); + err = accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp); } else { - err = normal_ecc_mul2add(A, kA, B, kB, C, modulus); + err = normal_ecc_mul2add(A, kA, B, kB, C, a, modulus, heap); } } #ifndef HAVE_THREAD_LS - UnLockMutex(&ecc_fp_lock); + wc_UnLockMutex(&ecc_fp_lock); #endif /* HAVE_THREAD_LS */ mp_clear(&mu); return err; } #endif +#endif /* ECC_SHAMIR */ /** ECC Fixed Point mulmod global k The multiplicand G Base point to multiply R [out] Destination of product + a ECC curve parameter a modulus The modulus for the curve - map [boolean] If non-zero maps the point back to affine co-ordinates, + map [boolean] If non-zero maps the point back to affine coordinates, otherwise it's left in jacobian-montgomery form return MP_OKAY if successful -*/ -int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, - int map) +*/ +int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, int map, void* heap) { +#ifndef WOLFSSL_SP_MATH int idx, err = MP_OKAY; mp_digit mp; mp_int mu; int mpSetup = 0; + if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + if (mp_init(&mu) != MP_OKAY) return MP_INIT_E; - + #ifndef HAVE_THREAD_LS if (initMutex == 0) { - InitMutex(&ecc_fp_lock); + wc_InitMutex(&ecc_fp_lock); initMutex = 1; } - - if (LockMutex(&ecc_fp_lock) != 0) + + if (wc_LockMutex(&ecc_fp_lock) != 0) return BAD_MUTEX_E; #endif /* HAVE_THREAD_LS */ @@ -4252,7 +9538,7 @@ int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, } - if (err == MP_OKAY) { + if (err == MP_OKAY) { /* if it's 2 build the LUT, if it's higher just use the LUT */ if (idx >= 0 && fp_cache[idx].lru_count == 2) { /* compute mp */ @@ -4263,34 +9549,52 @@ int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, mpSetup = 1; err = mp_montgomery_calc_normalization(&mu, modulus); } - - if (err == MP_OKAY) + + if (err == MP_OKAY) /* build the LUT */ - err = build_lut(idx, modulus, &mp, &mu); + err = build_lut(idx, a, modulus, mp, &mu); } } - if (err == MP_OKAY) { + if (err == MP_OKAY) { if (idx >= 0 && fp_cache[idx].lru_count >= 2) { if (mpSetup == 0) { /* compute mp */ err = mp_montgomery_setup(modulus, &mp); } if (err == MP_OKAY) - err = accel_fp_mul(idx, k, R, modulus, &mp, map); + err = accel_fp_mul(idx, k, R, a, modulus, mp, map); } else { - err = normal_ecc_mulmod(k, G, R, modulus, map); + err = normal_ecc_mulmod(k, G, R, a, modulus, map, heap); } } #ifndef HAVE_THREAD_LS - UnLockMutex(&ecc_fp_lock); + wc_UnLockMutex(&ecc_fp_lock); #endif /* HAVE_THREAD_LS */ mp_clear(&mu); return err; +#else + if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + +#ifndef WOLFSSL_SP_NO_256 + if (mp_count_bits(modulus) == 256) { + return sp_ecc_mulmod_256(k, G, R, map, heap); + } +#endif +#ifdef WOLFSSL_SP_384 + if (mp_count_bits(modulus) == 384) { + return sp_ecc_mulmod_384(k, G, R, map, heap); + } +#endif + return WC_KEY_SIZE_E; +#endif } +#ifndef WOLFSSL_SP_MATH /* helper function for freeing the cache ... must be called with the cache mutex locked */ static void wc_ecc_fp_free_cache(void) @@ -4299,38 +9603,41 @@ static void wc_ecc_fp_free_cache(void) for (x = 0; x < FP_ENTRIES; x++) { if (fp_cache[x].g != NULL) { for (y = 0; y < (1U<cliSt = ecCLI_SALT_SET; else { ctx->cliSt = ecCLI_BAD_STATE; - return BAD_ENC_STATE_E; + return BAD_STATE_E; } } else { @@ -4444,7 +9752,7 @@ int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt) ctx->srvSt = ecSRV_SALT_SET; else { ctx->srvSt = ecSRV_BAD_STATE; - return BAD_ENC_STATE_E; + return BAD_STATE_E; } } @@ -4470,11 +9778,11 @@ int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt) } -static int ecc_ctx_set_salt(ecEncCtx* ctx, int flags, RNG* rng) +static int ecc_ctx_set_salt(ecEncCtx* ctx, int flags, WC_RNG* rng) { byte* saltBuffer = NULL; - if (ctx == NULL || rng == NULL || flags == 0) + if (ctx == NULL || rng == NULL || flags == 0) return BAD_FUNC_ARG; saltBuffer = (flags == REQ_RESP_CLIENT) ? ctx->clientSalt : ctx->serverSalt; @@ -4501,8 +9809,8 @@ static void ecc_ctx_init(ecEncCtx* ctx, int flags) } -/* allow ecc context reset so user doesn't have to init/free for resue */ -int wc_ecc_ctx_reset(ecEncCtx* ctx, RNG* rng) +/* allow ecc context reset so user doesn't have to init/free for reuse */ +int wc_ecc_ctx_reset(ecEncCtx* ctx, WC_RNG* rng) { if (ctx == NULL || rng == NULL) return BAD_FUNC_ARG; @@ -4512,14 +9820,16 @@ int wc_ecc_ctx_reset(ecEncCtx* ctx, RNG* rng) } -/* alloc/init and set defaults, return new Context */ -ecEncCtx* wc_ecc_ctx_new(int flags, RNG* rng) +ecEncCtx* wc_ecc_ctx_new_ex(int flags, WC_RNG* rng, void* heap) { int ret = 0; - ecEncCtx* ctx = (ecEncCtx*)XMALLOC(sizeof(ecEncCtx), 0, DYNAMIC_TYPE_ECC); + ecEncCtx* ctx = (ecEncCtx*)XMALLOC(sizeof(ecEncCtx), heap, + DYNAMIC_TYPE_ECC); - if (ctx) + if (ctx) { ctx->protocol = (byte)flags; + ctx->heap = heap; + } ret = wc_ecc_ctx_reset(ctx, rng); if (ret != 0) { @@ -4531,12 +9841,19 @@ ecEncCtx* wc_ecc_ctx_new(int flags, RNG* rng) } +/* alloc/init and set defaults, return new Context */ +ecEncCtx* wc_ecc_ctx_new(int flags, WC_RNG* rng) +{ + return wc_ecc_ctx_new_ex(flags, rng, NULL); +} + + /* free any resources, clear any keys */ void wc_ecc_ctx_free(ecEncCtx* ctx) { if (ctx) { ForceZero(ctx, sizeof(ecEncCtx)); - XFREE(ctx, 0, DYNAMIC_TYPE_ECC); + XFREE(ctx, ctx->heap, DYNAMIC_TYPE_ECC); } } @@ -4548,7 +9865,7 @@ static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz, switch (ctx->encAlgo) { case ecAES_128_CBC: *encKeySz = KEY_SIZE_128; - *ivSz = IV_SIZE_64; + *ivSz = IV_SIZE_128; *blockSz = AES_BLOCK_SIZE; break; default: @@ -4557,7 +9874,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; @@ -4573,12 +9890,12 @@ static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz, /* ecc encrypt with shared secret run through kdf ctx holds non default algos and inputs - msgSz should be the right size for encAlgo, i.e., already padded + msgSz should be the right size for encAlgo, i.e., already padded return 0 on success */ 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; @@ -4604,9 +9921,9 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ctx == NULL) { /* use defaults */ ecc_ctx_init(&localCtx, 0); - ctx = &localCtx; + ctx = &localCtx; } - + ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz, &blockSz); if (ret != 0) @@ -4617,20 +9934,20 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, keysLen *= 2; if (ctx->srvSt != ecSRV_RECV_REQ) - return BAD_ENC_STATE_E; + return BAD_STATE_E; ctx->srvSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */ } else if (ctx->protocol == REQ_RESP_CLIENT) { if (ctx->cliSt != ecCLI_SALT_SET) - return BAD_ENC_STATE_E; + return BAD_STATE_E; ctx->cliSt = ecCLI_SENT_REQ; /* only do this once */ } - + if (keysLen > ECC_BUFSIZE) /* keys size */ return BUFFER_E; - + if ( (msgSz%blockSz) != 0) return BAD_PADDING_E; @@ -4638,23 +9955,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) && defined(WC_ASYNC_ENABLE_ECC) + 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; @@ -4674,11 +9997,21 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, case ecAES_128_CBC: { Aes aes; - ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv, + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv, AES_ENCRYPTION); + if (ret == 0) { + ret = wc_AesCbcEncrypt(&aes, out, msg, msgSz); + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + ret = wc_AsyncWait(ret, &aes.asyncDev, + WC_ASYNC_FLAG_NONE); + #endif + } + wc_AesFree(&aes); + } if (ret != 0) - break; - ret = wc_AesCbcEncrypt(&aes, out, msg, msgSz); + break; } break; @@ -4693,16 +10026,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; @@ -4716,8 +10050,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; @@ -4730,7 +10064,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; @@ -4756,33 +10090,33 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ctx == NULL) { /* use defaults */ ecc_ctx_init(&localCtx, 0); - ctx = &localCtx; + ctx = &localCtx; } - + ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz, &blockSz); if (ret != 0) return ret; - + if (ctx->protocol == REQ_RESP_CLIENT) { offset = keysLen; keysLen *= 2; if (ctx->cliSt != ecCLI_SENT_REQ) - return BAD_ENC_STATE_E; + return BAD_STATE_E; ctx->cliSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */ } else if (ctx->protocol == REQ_RESP_SERVER) { if (ctx->srvSt != ecSRV_SALT_SET) - return BAD_ENC_STATE_E; + return BAD_STATE_E; ctx->srvSt = ecSRV_RECV_REQ; /* only do this once */ } - + if (keysLen > ECC_BUFSIZE) /* keys size */ return BUFFER_E; - + if ( ((msgSz-digestSz) % blockSz) != 0) return BAD_PADDING_E; @@ -4790,23 +10124,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) && defined(WC_ASYNC_ENABLE_ECC) + 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; @@ -4824,25 +10164,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 (memcmp(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; @@ -4852,6 +10195,7 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret == 0) { switch (ctx->encAlgo) { + #ifdef HAVE_AES_CBC case ecAES_128_CBC: { Aes aes; @@ -4860,9 +10204,12 @@ 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) && defined(WC_ASYNC_ENABLE_AES) + ret = wc_AsyncWait(ret, &aes.asyncDev, WC_ASYNC_FLAG_NONE); + #endif } break; - + #endif default: ret = BAD_FUNC_ARG; break; @@ -4873,8 +10220,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; @@ -4885,25 +10232,36 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, #ifdef HAVE_COMP_KEY +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) -/* computes the jacobi c = (a | n) (or Legendre if n is prime) - * HAC pp. 73 Algorithm 2.149 - */ -int mp_jacobi(mp_int* a, mp_int* p, int* c) +#ifndef WOLFSSL_SP_MATH +int do_mp_jacobi(mp_int* a, mp_int* n, int* c); + +int do_mp_jacobi(mp_int* a, mp_int* n, int* c) { - mp_int a1, p1; - int k, s, r, res; + int k, s, res; + int r = 0; /* initialize to help static analysis out */ mp_digit residue; - /* if p <= 0 return MP_VAL */ - if (mp_cmp_d(p, 0) != MP_GT) { + /* if a < 0 return MP_VAL */ + if (mp_isneg(a) == MP_YES) { return MP_VAL; } - /* step 1. if a == 0, return 0 */ - if (mp_iszero (a) == 1) { - *c = 0; - return MP_OKAY; + /* if n <= 0 return MP_VAL */ + if (mp_cmp_d(n, 0) != MP_GT) { + return MP_VAL; + } + + /* step 1. handle case of a == 0 */ + if (mp_iszero (a) == MP_YES) { + /* special case of a == 0 and n == 1 */ + if (mp_cmp_d (n, 1) == MP_EQ) { + *c = 1; + } else { + *c = 0; + } + return MP_OKAY; } /* step 2. if a == 1, return 1 */ @@ -4915,19 +10273,9 @@ int mp_jacobi(mp_int* a, mp_int* p, int* c) /* default */ s = 0; - /* step 3. write a = a1 * 2**k */ - if ((res = mp_init_copy (&a1, a)) != MP_OKAY) { - return res; - } - - if ((res = mp_init (&p1)) != MP_OKAY) { - mp_clear(&a1); - return res; - } - /* divide out larger power of two */ - k = mp_cnt_lsb(&a1); - res = mp_div_2d(&a1, k, &a1, NULL); + k = mp_cnt_lsb(a); + res = mp_div_2d(a, k, a, NULL); if (res == MP_OKAY) { /* step 4. if e is even set s=1 */ @@ -4935,7 +10283,7 @@ int mp_jacobi(mp_int* a, mp_int* p, int* c) s = 1; } else { /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */ - residue = p->dp[0] & 7; + residue = n->dp[0] & 7; if (residue == 1 || residue == 7) { s = 1; @@ -4944,50 +10292,114 @@ int mp_jacobi(mp_int* a, mp_int* p, int* c) } } - /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */ - if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) { + /* step 5. if p == 3 (mod 4) *and* a == 3 (mod 4) then s = -s */ + if ( ((n->dp[0] & 3) == 3) && ((a->dp[0] & 3) == 3)) { s = -s; } } if (res == MP_OKAY) { - /* if a1 == 1 we're done */ - if (mp_cmp_d (&a1, 1) == MP_EQ) { + /* if a == 1 we're done */ + if (mp_cmp_d(a, 1) == MP_EQ) { *c = s; } else { - /* n1 = n mod a1 */ - res = mp_mod (p, &a1, &p1); + /* n1 = n mod a */ + res = mp_mod (n, a, n); if (res == MP_OKAY) - res = mp_jacobi (&p1, &a1, &r); + res = do_mp_jacobi(n, a, &r); if (res == MP_OKAY) - *c = s * r; + *c = s * r; } } - /* done */ - mp_clear (&p1); - mp_clear (&a1); - return res; } +/* computes the jacobi c = (a | n) (or Legendre if n is prime) + * HAC pp. 73 Algorithm 2.149 + * HAC is wrong here, as the special case of (0 | 1) is not + * handled correctly. + */ +int mp_jacobi(mp_int* a, mp_int* n, int* c) +{ + mp_int a1, n1; + int res; + + /* step 3. write a = a1 * 2**k */ + if ((res = mp_init_multi(&a1, &n1, NULL, NULL, NULL, NULL)) != MP_OKAY) { + return res; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto done; + } + + if ((res = mp_copy(n, &n1)) != MP_OKAY) { + goto done; + } + + res = do_mp_jacobi(&a1, &n1, c); + +done: + /* cleanup */ + mp_clear(&n1); + mp_clear(&a1); + + return res; +} + + +/* Solves the modular equation x^2 = n (mod p) + * where prime number is greater than 2 (odd prime). + * The result is returned in the third argument x + * the function returns MP_OKAY on success, MP_VAL or another error on failure + */ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) { +#ifdef SQRTMOD_USE_MOD_EXP + int res; + + mp_int e; + + res = mp_init(&e); + if (res == MP_OKAY) + res = mp_add_d(prime, 1, &e); + if (res == MP_OKAY) + res = mp_div_2d(&e, 2, &e, NULL); + if (res == MP_OKAY) + res = mp_exptmod(n, &e, prime, ret); + + mp_clear(&e); + + return res; +#else int res, legendre, done = 0; mp_int t1, C, Q, S, Z, M, T, R, two; mp_digit i; - /* first handle the simple cases */ + /* first handle the simple cases n = 0 or n = 1 */ if (mp_cmp_d(n, 0) == MP_EQ) { mp_zero(ret); return MP_OKAY; } - if (mp_cmp_d(prime, 2) == MP_EQ) return MP_VAL; /* prime must be odd */ - /* TAO removed - if ((res = mp_jacobi(n, prime, &legendre)) != MP_OKAY) return res; - if (legendre == -1) return MP_VAL; */ /* quadratic non-residue mod prime */ + if (mp_cmp_d(n, 1) == MP_EQ) { + return mp_set(ret, 1); + } + + /* prime must be odd */ + if (mp_cmp_d(prime, 2) == MP_EQ) { + return MP_VAL; + } + + /* is quadratic non-residue mod prime */ + if ((res = mp_jacobi(n, prime, &legendre)) != MP_OKAY) { + return res; + } + if (legendre == -1) { + return MP_VAL; + } if ((res = mp_init_multi(&t1, &C, &Q, &S, &Z, &M)) != MP_OKAY) return res; @@ -5018,61 +10430,72 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) } /* NOW: TonelliShanks algorithm */ + if (res == MP_OKAY && done == 0) { - if (res == MP_OKAY && done == 0) { - - /* factor out powers of 2 from prime-1, defining Q and S + /* factor out powers of 2 from prime-1, defining Q and S * as: prime-1 = Q*2^S */ + /* Q = prime - 1 */ res = mp_copy(prime, &Q); if (res == MP_OKAY) res = mp_sub_d(&Q, 1, &Q); - /* Q = prime - 1 */ + + /* S = 0 */ if (res == MP_OKAY) mp_zero(&S); - /* S = 0 */ - while (res == MP_OKAY && mp_iseven(&Q)) { - res = mp_div_2(&Q, &Q); + + while (res == MP_OKAY && mp_iseven(&Q) == MP_YES) { /* Q = Q / 2 */ + res = mp_div_2(&Q, &Q); + + /* S = S + 1 */ if (res == MP_OKAY) res = mp_add_d(&S, 1, &S); - /* S = S + 1 */ } /* find a Z such that the Legendre symbol (Z|prime) == -1 */ + /* Z = 2 */ if (res == MP_OKAY) res = mp_set_int(&Z, 2); - /* Z = 2 */ + while (res == MP_OKAY) { res = mp_jacobi(&Z, prime, &legendre); if (res == MP_OKAY && legendre == -1) break; + + /* Z = Z + 1 */ if (res == MP_OKAY) res = mp_add_d(&Z, 1, &Z); - /* Z = Z + 1 */ } + /* C = Z ^ Q mod prime */ if (res == MP_OKAY) res = mp_exptmod(&Z, &Q, prime, &C); - /* C = Z ^ Q mod prime */ + + /* t1 = (Q + 1) / 2 */ if (res == MP_OKAY) res = mp_add_d(&Q, 1, &t1); if (res == MP_OKAY) res = mp_div_2(&t1, &t1); - /* t1 = (Q + 1) / 2 */ - if (res == MP_OKAY) - res = mp_exptmod(n, &t1, prime, &R); + /* R = n ^ ((Q + 1) / 2) mod prime */ if (res == MP_OKAY) - res = mp_exptmod(n, &Q, prime, &T); + res = mp_exptmod(n, &t1, prime, &R); + /* T = n ^ Q mod prime */ if (res == MP_OKAY) - res = mp_copy(&S, &M); + res = mp_exptmod(n, &Q, prime, &T); + /* M = S */ + if (res == MP_OKAY) + res = mp_copy(&S, &M); + if (res == MP_OKAY) res = mp_set_int(&two, 2); while (res == MP_OKAY && done == 0) { res = mp_copy(&T, &t1); + + /* reduce to 1 and count */ i = 0; while (res == MP_OKAY) { if (mp_cmp_d(&t1, 1) == MP_EQ) @@ -5082,34 +10505,38 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) i++; } if (res == MP_OKAY && i == 0) { - mp_copy(&R, ret); - res = MP_OKAY; + res = mp_copy(&R, ret); done = 1; } if (done == 0) { + /* t1 = 2 ^ (M - i - 1) */ if (res == MP_OKAY) res = mp_sub_d(&M, i, &t1); if (res == MP_OKAY) res = mp_sub_d(&t1, 1, &t1); if (res == MP_OKAY) res = mp_exptmod(&two, &t1, prime, &t1); - /* t1 = 2 ^ (M - i - 1) */ - if (res == MP_OKAY) - res = mp_exptmod(&C, &t1, prime, &t1); + /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */ if (res == MP_OKAY) - res = mp_sqrmod(&t1, prime, &C); + res = mp_exptmod(&C, &t1, prime, &t1); + /* C = (t1 * t1) mod prime */ if (res == MP_OKAY) - res = mp_mulmod(&R, &t1, prime, &R); + res = mp_sqrmod(&t1, prime, &C); + /* R = (R * t1) mod prime */ if (res == MP_OKAY) - res = mp_mulmod(&T, &C, prime, &T); + res = mp_mulmod(&R, &t1, prime, &R); + /* T = (T * C) mod prime */ if (res == MP_OKAY) - mp_set(&M, i); + res = mp_mulmod(&T, &C, prime, &T); + /* M = i */ + if (res == MP_OKAY) + res = mp_set(&M, i); } } } @@ -5126,19 +10553,22 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) mp_clear(&two); return res; +#endif } +#endif +#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCELL */ /* export public ECC key in ANSI X9.63 format compressed */ -int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen) +static int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen) { word32 numlen; int ret = MP_OKAY; if (key == NULL || out == NULL || outLen == NULL) - return ECC_BAD_ARG_E; + return BAD_FUNC_ARG; - if (ecc_is_valid_idx(key->idx) == 0) { + if (wc_ecc_is_valid_idx(key->idx) == 0) { return ECC_BAD_ARG_E; } numlen = key->dp->size; @@ -5149,38 +10579,183 @@ int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen) } /* store first byte */ - out[0] = mp_isodd(key->pubkey.y) ? 0x03 : 0x02; + out[0] = mp_isodd(key->pubkey.y) == MP_YES ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN; /* pad and store x */ XMEMSET(out+1, 0, numlen); ret = mp_to_unsigned_bin(key->pubkey.x, out+1 + (numlen - mp_unsigned_bin_size(key->pubkey.x))); *outLen = 1 + numlen; + return ret; } - -/* d = a - b (mod c) */ -int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d) -{ - int res; - mp_int t; - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_sub (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - res = mp_mod (&t, c, d); - mp_clear (&t); - - return res; -} - - #endif /* HAVE_COMP_KEY */ + +int wc_ecc_get_oid(word32 oidSum, const byte** oid, word32* oidSz) +{ + int x; + + if (oidSum == 0) { + return BAD_FUNC_ARG; + } + + /* find matching OID sum (based on encoded value) */ + for (x = 0; ecc_sets[x].size != 0; x++) { + if (ecc_sets[x].oidSum == oidSum) { + int ret; + #ifdef HAVE_OID_ENCODING + ret = 0; + /* check cache */ + oid_cache_t* o = &ecc_oid_cache[x]; + if (o->oidSz == 0) { + o->oidSz = sizeof(o->oid); + ret = EncodeObjectId(ecc_sets[x].oid, ecc_sets[x].oidSz, + o->oid, &o->oidSz); + } + if (oidSz) { + *oidSz = o->oidSz; + } + if (oid) { + *oid = o->oid; + } + /* on success return curve id */ + if (ret == 0) { + ret = ecc_sets[x].id; + } + #else + if (oidSz) { + *oidSz = ecc_sets[x].oidSz; + } + if (oid) { + *oid = ecc_sets[x].oid; + } + ret = ecc_sets[x].id; + #endif + return ret; + } + } + + return NOT_COMPILED_IN; +} + +#ifdef WOLFSSL_CUSTOM_CURVES +int wc_ecc_set_custom_curve(ecc_key* key, const ecc_set_type* dp) +{ + if (key == NULL || dp == NULL) { + return BAD_FUNC_ARG; + } + + key->idx = ECC_CUSTOM_IDX; + key->dp = dp; + + return 0; +} +#endif /* WOLFSSL_CUSTOM_CURVES */ + +#ifdef HAVE_X963_KDF + +static WC_INLINE void IncrementX963KdfCounter(byte* inOutCtr) +{ + int i; + + /* in network byte order so start at end and work back */ + for (i = 3; i >= 0; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } +} + +/* ASN X9.63 Key Derivation Function (SEC1) */ +int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, + const byte* sinfo, word32 sinfoSz, byte* out, word32 outSz) +{ + int ret, i; + int digestSz, copySz; + int remaining = outSz; + byte* outIdx; + byte counter[4]; + byte tmp[WC_MAX_DIGEST_SIZE]; + +#ifdef WOLFSSL_SMALL_STACK + wc_HashAlg* hash; +#else + wc_HashAlg hash[1]; +#endif + + if (secret == NULL || secretSz == 0 || out == NULL) + return BAD_FUNC_ARG; + + /* X9.63 allowed algos only */ + if (type != WC_HASH_TYPE_SHA && type != WC_HASH_TYPE_SHA224 && + type != WC_HASH_TYPE_SHA256 && type != WC_HASH_TYPE_SHA384 && + type != WC_HASH_TYPE_SHA512) + return BAD_FUNC_ARG; + + digestSz = wc_HashGetDigestSize(type); + if (digestSz < 0) + return digestSz; + +#ifdef WOLFSSL_SMALL_STACK + hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), NULL, + DYNAMIC_TYPE_HASHES); + if (hash == NULL) + return MEMORY_E; +#endif + + ret = wc_HashInit(hash, type); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash, NULL, DYNAMIC_TYPE_HASHES); +#endif + return ret; + } + + outIdx = out; + XMEMSET(counter, 0, sizeof(counter)); + + for (i = 1; remaining > 0; i++) { + + IncrementX963KdfCounter(counter); + + ret = wc_HashUpdate(hash, type, secret, secretSz); + if (ret != 0) { + break; + } + + ret = wc_HashUpdate(hash, type, counter, sizeof(counter)); + if (ret != 0) { + break; + } + + if (sinfo) { + ret = wc_HashUpdate(hash, type, sinfo, sinfoSz); + if (ret != 0) { + break; + } + } + + ret = wc_HashFinal(hash, type, tmp); + if (ret != 0) { + break; + } + + copySz = min(remaining, digestSz); + XMEMCPY(outIdx, tmp, copySz); + + remaining -= copySz; + outIdx += copySz; + } + + wc_HashFree(hash, type); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash, NULL, DYNAMIC_TYPE_HASHES); +#endif + + return ret; +} +#endif /* HAVE_X963_KDF */ + #endif /* HAVE_ECC */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ed25519.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ed25519.c index ba0dcbe53..8057caa7c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ed25519.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ed25519.c @@ -1,8 +1,8 @@ /* ed25519.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. */ #ifdef HAVE_CONFIG_H @@ -32,22 +33,67 @@ #include #include +#include #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif +#ifdef FREESCALE_LTC_ECC + #include +#endif -/* - generate an ed25519 key pair. - returns 0 on success - */ -int wc_ed25519_make_key(RNG* rng, int keySz, ed25519_key* key) +#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_VERIFY) +#define ED25519CTX_SIZE 32 + +static const byte ed25519Ctx[ED25519CTX_SIZE+1] = + "SigEd25519 no Ed25519 collisions"; +#endif + +int wc_ed25519_make_public(ed25519_key* key, unsigned char* pubKey, + word32 pubKeySz) { - byte az[64]; - int ret; + int ret = 0; + byte az[ED25519_PRV_KEY_SIZE]; +#if !defined(FREESCALE_LTC_ECC) ge_p3 A; +#endif + + if (key == NULL || pubKeySz != ED25519_PUB_KEY_SIZE) + ret = BAD_FUNC_ARG; + + if (ret == 0) + ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az); + if (ret == 0) { + /* apply clamp */ + az[0] &= 248; + az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ + az[31] |= 64; + + #ifdef FREESCALE_LTC_ECC + ltc_pkha_ecc_point_t publicKey = {0}; + publicKey.X = key->pointX; + publicKey.Y = key->pointY; + LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), az, + ED25519_KEY_SIZE, &publicKey, kLTC_Ed25519 /* result on Ed25519 */); + LTC_PKHA_Ed25519_Compress(&publicKey, pubKey); + #else + ge_scalarmult_base(&A, az); + ge_p3_tobytes(pubKey, &A); + #endif + } + + return ret; +} + +/* generate an ed25519 key pair. + * returns 0 on success + */ +int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key) +{ + int ret; if (rng == NULL || key == NULL) return BAD_FUNC_ARG; @@ -56,142 +102,412 @@ int wc_ed25519_make_key(RNG* rng, int keySz, ed25519_key* key) if (keySz != ED25519_KEY_SIZE) return BAD_FUNC_ARG; - ret = 0; - ret |= wc_RNG_GenerateBlock(rng, key->k, 32); - ret |= wc_Sha512Hash(key->k, 32, az); - az[0] &= 248; - az[31] &= 63; - az[31] |= 64; + ret = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE); + if (ret != 0) + return ret; - ge_scalarmult_base(&A, az); - ge_p3_tobytes(key->p, &A); - XMEMMOVE(key->k + 32, key->p, 32); + ret = wc_ed25519_make_public(key, key->p, ED25519_PUB_KEY_SIZE); + if (ret != 0) { + ForceZero(key->k, ED25519_KEY_SIZE); + return ret; + } + + /* put public key after private key, on the same buffer */ + XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE); + + key->pubKeySet = 1; return ret; } +#ifdef HAVE_ED25519_SIGN /* - in contains the message to sign - inlen is the length of the message to sign - out is the buffer to write the signature - outlen [in/out] input size of out buf - output gets set as the final length of out - key is the ed25519 key to use when signing + in contains the message to sign + inLen is the length of the message to sign + out is the buffer to write the signature + outLen [in/out] input size of out buf + output gets set as the final length of out + key is the ed25519 key to use when signing + type one of Ed25519, Ed25519ctx or Ed25519ph + context extra signing data + contextLen length of extra signing data return 0 on success */ -int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, - word32 *outlen, ed25519_key* key) +static int ed25519_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key, byte type, + const byte* context, byte contextLen) { +#ifdef FREESCALE_LTC_ECC + byte tempBuf[ED25519_PRV_KEY_SIZE]; +#else ge_p3 R; - byte nonce[SHA512_DIGEST_SIZE]; - byte hram[SHA512_DIGEST_SIZE]; - byte az[64]; - word32 sigSz; - Sha512 sha; - int ret = 0; +#endif + byte nonce[WC_SHA512_DIGEST_SIZE]; + byte hram[WC_SHA512_DIGEST_SIZE]; + byte az[ED25519_PRV_KEY_SIZE]; + wc_Sha512 sha; + int ret; /* sanity check on arguments */ - if (in == NULL || out == NULL || outlen == NULL || key == NULL) + if (in == NULL || out == NULL || outLen == NULL || key == NULL || + (context == NULL && contextLen != 0)) { + return BAD_FUNC_ARG; + } + if (!key->pubKeySet) return BAD_FUNC_ARG; /* check and set up out length */ - ret = 0; - sigSz = wc_ed25519_sig_size(key); - if (*outlen < sigSz) - return BAD_FUNC_ARG; - *outlen = sigSz; + if (*outLen < ED25519_SIG_SIZE) { + *outLen = ED25519_SIG_SIZE; + return BUFFER_E; + } + *outLen = ED25519_SIG_SIZE; /* step 1: create nonce to use where nonce is r in r = H(h_b, ... ,h_2b-1,M) */ - ret |= wc_Sha512Hash(key->k,32,az); + ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az); + if (ret != 0) + return ret; + + /* apply clamp */ az[0] &= 248; - az[31] &= 63; + az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ az[31] |= 64; - ret |= wc_InitSha512(&sha); - ret |= wc_Sha512Update(&sha, az + 32, 32); - ret |= wc_Sha512Update(&sha, in, inlen); - ret |= wc_Sha512Final(&sha, nonce); + + ret = wc_InitSha512(&sha); + if (ret != 0) + return ret; + if (type == Ed25519ctx || type == Ed25519ph) { + ret = wc_Sha512Update(&sha, ed25519Ctx, ED25519CTX_SIZE); + if (ret == 0) + ret = wc_Sha512Update(&sha, &type, sizeof(type)); + if (ret == 0) + ret = wc_Sha512Update(&sha, &contextLen, sizeof(contextLen)); + if (ret == 0 && context != NULL) + ret = wc_Sha512Update(&sha, context, contextLen); + } + if (ret == 0) + ret = wc_Sha512Update(&sha, az + ED25519_KEY_SIZE, ED25519_KEY_SIZE); + if (ret == 0) + ret = wc_Sha512Update(&sha, in, inLen); + if (ret == 0) + ret = wc_Sha512Final(&sha, nonce); + wc_Sha512Free(&sha); + if (ret != 0) + return ret; + +#ifdef FREESCALE_LTC_ECC + ltc_pkha_ecc_point_t ltcPoint = {0}; + ltcPoint.X = &tempBuf[0]; + ltcPoint.Y = &tempBuf[32]; + LTC_PKHA_sc_reduce(nonce); + LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), nonce, + ED25519_KEY_SIZE, <cPoint, kLTC_Ed25519 /* result on Ed25519 */); + LTC_PKHA_Ed25519_Compress(<cPoint, out); +#else sc_reduce(nonce); /* step 2: computing R = rB where rB is the scalar multiplication of r and B */ ge_scalarmult_base(&R,nonce); ge_p3_tobytes(out,&R); +#endif /* step 3: hash R + public key + message getting H(R,A,M) then creating S = (r + H(R,A,M)a) mod l */ - ret |= wc_InitSha512(&sha); - ret |= wc_Sha512Update(&sha, out, 32); - ret |= wc_Sha512Update(&sha, key->p, 32); - ret |= wc_Sha512Update(&sha, in, inlen); - ret |= wc_Sha512Final(&sha, hram); + ret = wc_InitSha512(&sha); + if (ret != 0) + return ret; + if (type == Ed25519ctx || type == Ed25519ph) { + ret = wc_Sha512Update(&sha, ed25519Ctx, ED25519CTX_SIZE); + if (ret == 0) + ret = wc_Sha512Update(&sha, &type, sizeof(type)); + if (ret == 0) + ret = wc_Sha512Update(&sha, &contextLen, sizeof(contextLen)); + if (ret == 0 && context != NULL) + ret = wc_Sha512Update(&sha, context, contextLen); + } + if (ret == 0) + ret = wc_Sha512Update(&sha, out, ED25519_SIG_SIZE/2); + if (ret == 0) + ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE); + if (ret == 0) + ret = wc_Sha512Update(&sha, in, inLen); + if (ret == 0) + ret = wc_Sha512Final(&sha, hram); + wc_Sha512Free(&sha); + if (ret != 0) + return ret; + +#ifdef FREESCALE_LTC_ECC + LTC_PKHA_sc_reduce(hram); + LTC_PKHA_sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); +#else sc_reduce(hram); - sc_muladd(out + 32, hram, az, nonce); + sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); +#endif return ret; } +/* + in contains the message to sign + inLen is the length of the message to sign + out is the buffer to write the signature + outLen [in/out] input size of out buf + output gets set as the final length of out + key is the ed25519 key to use when signing + return 0 on success + */ +int wc_ed25519_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key) +{ + return ed25519_sign_msg(in, inLen, out, outLen, key, (byte)Ed25519, NULL, 0); +} + +/* + in contains the message to sign + inLen is the length of the message to sign + out is the buffer to write the signature + outLen [in/out] input size of out buf + output gets set as the final length of out + key is the ed25519 key to use when signing + context extra signing data + contextLen length of extra signing data + return 0 on success + */ +int wc_ed25519ctx_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key, + const byte* context, byte contextLen) +{ + return ed25519_sign_msg(in, inLen, out, outLen, key, Ed25519ctx, context, + contextLen); +} + +/* + hash contains the SHA-512 hash of the message to sign + hashLen is the length of the SHA-512 hash of the message to sign + out is the buffer to write the signature + outLen [in/out] input size of out buf + output gets set as the final length of out + key is the ed25519 key to use when signing + context extra signing data + contextLen length of extra signing data + return 0 on success + */ +int wc_ed25519ph_sign_hash(const byte* hash, word32 hashLen, byte* out, + word32 *outLen, ed25519_key* key, + const byte* context, byte contextLen) +{ + return ed25519_sign_msg(hash, hashLen, out, outLen, key, Ed25519ph, context, + contextLen); +} + +/* + in contains the message to sign + inLen is the length of the message to sign + out is the buffer to write the signature + outLen [in/out] input size of out buf + output gets set as the final length of out + key is the ed25519 key to use when signing + context extra signing data + contextLen length of extra signing data + return 0 on success + */ +int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key, + const byte* context, byte contextLen) +{ + int ret; + byte hash[WC_SHA512_DIGEST_SIZE]; + + ret = wc_Sha512Hash(in, inLen, hash); + if (ret != 0) + return ret; + + return wc_ed25519ph_sign_hash(hash, sizeof(hash), out, outLen, key, context, + contextLen); +} +#endif /* HAVE_ED25519_SIGN */ + +#ifdef HAVE_ED25519_VERIFY /* sig is array of bytes containing the signature - siglen is the length of sig byte array + 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 + msgLen length of msg array + res will be 1 on successful verify and 0 on unsuccessful + key Ed25519 public key + 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) +static int ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, ed25519_key* key, + byte type, const byte* context, byte contextLen) { - byte rcheck[32]; - byte h[SHA512_DIGEST_SIZE]; + byte rcheck[ED25519_KEY_SIZE]; + byte h[WC_SHA512_DIGEST_SIZE]; +#ifndef FREESCALE_LTC_ECC ge_p3 A; ge_p2 R; - word32 sigSz; +#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 || + (context == NULL && contextLen != 0)) { return BAD_FUNC_ARG; + } - ret = 0; - *stat = 0; - sigSz = wc_ed25519_size(key); + /* set verification failed by default */ + *res = 0; /* check on basics needed to verify signature */ - if (siglen < sigSz) - return BAD_FUNC_ARG; - if (sig[63] & 224) + 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 if (ge_frombytes_negate_vartime(&A, key->p) != 0) return BAD_FUNC_ARG; +#endif /* find H(R,A,M) and store it as h */ - ret |= wc_InitSha512(&sha); - ret |= wc_Sha512Update(&sha, sig, 32); - ret |= wc_Sha512Update(&sha, key->p, 32); - ret |= wc_Sha512Update(&sha, msg, msglen); - ret |= wc_Sha512Final(&sha, h); + ret = wc_InitSha512(&sha); + if (ret != 0) + return ret; + if (type == Ed25519ctx || type == Ed25519ph) { + ret = wc_Sha512Update(&sha, ed25519Ctx, ED25519CTX_SIZE); + if (ret == 0) + ret = wc_Sha512Update(&sha, &type, sizeof(type)); + if (ret == 0) + ret = wc_Sha512Update(&sha, &contextLen, sizeof(contextLen)); + if (ret == 0 && context != NULL) + ret = wc_Sha512Update(&sha, context, contextLen); + } + if (ret == 0) + ret = wc_Sha512Update(&sha, sig, ED25519_SIG_SIZE/2); + if (ret == 0) + ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE); + if (ret == 0) + ret = wc_Sha512Update(&sha, msg, msgLen); + if (ret == 0) + ret = wc_Sha512Final(&sha, h); + wc_Sha512Free(&sha); + if (ret != 0) + return ret; + +#ifdef FREESCALE_LTC_ECC + LTC_PKHA_sc_reduce(h); + LTC_PKHA_SignatureForVerify(rcheck, h, sig + (ED25519_SIG_SIZE/2), key); +#else sc_reduce(h); /* Uses a fast single-signature verification SB = R + H(R,A,M)A becomes SB - H(R,A,M)A saving decompression of R */ - ret |= ge_double_scalarmult_vartime(&R, h, &A, sig + 32); + ret = ge_double_scalarmult_vartime(&R, h, &A, sig + (ED25519_SIG_SIZE/2)); + if (ret != 0) + return ret; + ge_tobytes(rcheck, &R); +#endif /* FREESCALE_LTC_ECC */ /* comparison of R created to R in sig */ - ret |= ConstantCompare(rcheck, sig, 32); + ret = ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2); + if (ret != 0) + return SIG_VERIFY_E; - *stat = (ret == 0)? 1: 0; + /* set the verification status */ + *res = 1; return ret; } +/* + sig is array of bytes containing the signature + sigLen is the length of sig byte array + msg the array of bytes containing the message + msgLen length of msg array + res will be 1 on successful verify and 0 on unsuccessful + key Ed25519 public key + return 0 and res of 1 on success +*/ +int wc_ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, ed25519_key* key) +{ + return ed25519_verify_msg(sig, sigLen, msg, msgLen, res, key, (byte)Ed25519, + NULL, 0); +} + +/* + sig is array of bytes containing the signature + sigLen is the length of sig byte array + msg the array of bytes containing the message + msgLen length of msg array + res will be 1 on successful verify and 0 on unsuccessful + key Ed25519 public key + context extra sigining data + contextLen length of extra sigining data + return 0 and res of 1 on success +*/ +int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, ed25519_key* key, + const byte* context, byte contextLen) +{ + return ed25519_verify_msg(sig, sigLen, msg, msgLen, res, key, Ed25519ctx, + context, contextLen); +} + +/* + sig is array of bytes containing the signature + sigLen is the length of sig byte array + hash the array of bytes containing the SHA-512 hash of the message + hashLen length of hash array + res will be 1 on successful verify and 0 on unsuccessful + key Ed25519 public key + context extra sigining data + contextLen length of extra sigining data + return 0 and res of 1 on success +*/ +int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash, + word32 hashLen, int* res, ed25519_key* key, + const byte* context, byte contextLen) +{ + return ed25519_verify_msg(sig, sigLen, hash, hashLen, res, key, Ed25519ph, + context, contextLen); +} + +/* + sig is array of bytes containing the signature + sigLen is the length of sig byte array + msg the array of bytes containing the message + msgLen length of msg array + res will be 1 on successful verify and 0 on unsuccessful + key Ed25519 public key + context extra sigining data + contextLen length of extra sigining data + return 0 and res of 1 on success +*/ +int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, ed25519_key* key, + const byte* context, byte contextLen) +{ + int ret; + byte hash[WC_SHA512_DIGEST_SIZE]; + + ret = wc_Sha512Hash(msg, msgLen, hash); + if (ret != 0) + return ret; + + return wc_ed25519ph_verify_hash(sig, sigLen, hash, sizeof(hash), res, key, + context, contextLen); +} +#endif /* HAVE_ED25519_VERIFY */ + /* initialize information and memory for key */ int wc_ed25519_init(ed25519_key* key) @@ -201,6 +517,10 @@ int wc_ed25519_init(ed25519_key* key) XMEMSET(key, 0, sizeof(ed25519_key)); +#ifndef FREESCALE_LTC_ECC + fe_init(); +#endif + return 0; } @@ -215,6 +535,8 @@ void wc_ed25519_free(ed25519_key* key) } +#ifdef HAVE_ED25519_KEY_EXPORT + /* outLen should contain the size of out buffer when input. outLen is than set to the final output length. @@ -222,24 +544,25 @@ void wc_ed25519_free(ed25519_key* key) */ int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen) { - word32 keySz; - /* sanity check on arguments */ if (key == NULL || out == NULL || outLen == NULL) return BAD_FUNC_ARG; - keySz = wc_ed25519_size(key); - if (*outLen < keySz) { - *outLen = keySz; + if (*outLen < ED25519_PUB_KEY_SIZE) { + *outLen = ED25519_PUB_KEY_SIZE; return BUFFER_E; } - *outLen = keySz; - XMEMCPY(out, key->p, keySz); + + *outLen = ED25519_PUB_KEY_SIZE; + XMEMCPY(out, key->p, ED25519_PUB_KEY_SIZE); return 0; } +#endif /* HAVE_ED25519_KEY_EXPORT */ + +#ifdef HAVE_ED25519_KEY_IMPORT /* Imports a compressed/uncompressed public key. in the byte array containing the public key @@ -248,37 +571,65 @@ int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen) */ int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key) { - word32 keySz; int ret; /* sanity check on arguments */ if (in == NULL || key == NULL) return BAD_FUNC_ARG; - keySz = wc_ed25519_size(key); - - if (inLen < keySz) + if (inLen < ED25519_PUB_KEY_SIZE) return BAD_FUNC_ARG; /* compressed prefix according to draft http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */ - if (in[0] == 0x40) { + if (in[0] == 0x40 && inLen > ED25519_PUB_KEY_SIZE) { /* key is stored in compressed format so just copy in */ - XMEMCPY(key->p, (in + 1), keySz); + XMEMCPY(key->p, (in + 1), ED25519_PUB_KEY_SIZE); +#ifdef FREESCALE_LTC_ECC + /* recover X coordinate */ + ltc_pkha_ecc_point_t pubKey; + pubKey.X = key->pointX; + pubKey.Y = key->pointY; + LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey); +#endif + key->pubKeySet = 1; return 0; } /* importing uncompressed public key */ - if (in[0] == 0x04) { + if (in[0] == 0x04 && inLen > 2*ED25519_PUB_KEY_SIZE) { +#ifdef FREESCALE_LTC_ECC + /* reverse bytes for little endian byte order */ + for (int i = 0; i < ED25519_KEY_SIZE; i++) + { + key->pointX[i] = *(in + ED25519_KEY_SIZE - i); + key->pointY[i] = *(in + 2*ED25519_KEY_SIZE - i); + } + XMEMCPY(key->p, key->pointY, ED25519_KEY_SIZE); + key->pubKeySet = 1; + ret = 0; +#else /* pass in (x,y) and store compressed key */ - ret = ge_compress_key(key->p, (in+1), (in+1+keySz), keySz); + ret = ge_compress_key(key->p, in+1, + in+1+ED25519_PUB_KEY_SIZE, ED25519_PUB_KEY_SIZE); + if (ret == 0) + key->pubKeySet = 1; +#endif /* FREESCALE_LTC_ECC */ return ret; } /* if not specified compressed or uncompressed check key size if key size is equal to compressed key size copy in key */ - if (inLen == keySz) { - XMEMCPY(key->p, in, keySz); + if (inLen == ED25519_PUB_KEY_SIZE) { + XMEMCPY(key->p, in, ED25519_PUB_KEY_SIZE); +#ifdef FREESCALE_LTC_ECC + /* recover X coordinate */ + ltc_pkha_ecc_point_t pubKey; + pubKey.X = key->pointX; + pubKey.Y = key->pointY; + LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey); +#endif + key->pubKeySet = 1; return 0; } @@ -287,83 +638,176 @@ 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. */ int wc_ed25519_import_private_key(const byte* priv, word32 privSz, const byte* pub, word32 pubSz, ed25519_key* key) { - word32 keySz; int ret; /* sanity check on arguments */ if (priv == NULL || pub == NULL || key == NULL) return BAD_FUNC_ARG; - keySz = wc_ed25519_size(key); - /* key size check */ - if (privSz < keySz || pubSz < keySz) + if (privSz < ED25519_KEY_SIZE || pubSz < ED25519_PUB_KEY_SIZE) return BAD_FUNC_ARG; - XMEMCPY(key->k, priv, keySz); + /* import public key */ ret = wc_ed25519_import_public(pub, pubSz, key); - XMEMCPY((key->k + keySz), key->p, keySz); + if (ret != 0) + return ret; + + /* make the private key (priv + pub) */ + XMEMCPY(key->k, priv, ED25519_KEY_SIZE); + XMEMCPY(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE); return ret; } +#endif /* HAVE_ED25519_KEY_IMPORT */ + + +#ifdef HAVE_ED25519_KEY_EXPORT /* - outLen should contain the size of out buffer when input. outLen is than set - to the final output length. - returns 0 on success + export private key only (secret part so 32 bytes) + outLen should contain the size of out buffer when input. outLen is than set + to the final output length. + returns 0 on success */ int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen) { - word32 keySz; - /* sanity checks on arguments */ if (key == NULL || out == NULL || outLen == NULL) return BAD_FUNC_ARG; - keySz = wc_ed25519_size(key); - if (*outLen < keySz) { - *outLen = keySz; + if (*outLen < ED25519_KEY_SIZE) { + *outLen = ED25519_KEY_SIZE; return BUFFER_E; } - *outLen = keySz; - XMEMCPY(out, key->k, keySz); + + *outLen = ED25519_KEY_SIZE; + XMEMCPY(out, key->k, ED25519_KEY_SIZE); return 0; } +/* + export private key, including public part + outLen should contain the size of out buffer when input. outLen is than set + to the final output length. + returns 0 on success + */ +int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen) +{ + /* sanity checks on arguments */ + if (key == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; -/* is the compressed key size in bytes */ + if (*outLen < ED25519_PRV_KEY_SIZE) { + *outLen = ED25519_PRV_KEY_SIZE; + return BUFFER_E; + } + + *outLen = ED25519_PRV_KEY_SIZE; + XMEMCPY(out, key->k, ED25519_PRV_KEY_SIZE); + + return 0; +} + +/* export full private key and public key + return 0 on success + */ +int wc_ed25519_export_key(ed25519_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz) +{ + int ret; + + /* export 'full' private part */ + ret = wc_ed25519_export_private(key, priv, privSz); + if (ret != 0) + return ret; + + /* export public part */ + ret = wc_ed25519_export_public(key, pub, pubSz); + + return ret; +} + +#endif /* HAVE_ED25519_KEY_EXPORT */ + +/* check the private and public keys match */ +int wc_ed25519_check_key(ed25519_key* key) +{ + int ret = 0; + unsigned char pubKey[ED25519_PUB_KEY_SIZE]; + + if (!key->pubKeySet) + ret = PUBLIC_KEY_E; + if (ret == 0) + ret = wc_ed25519_make_public(key, pubKey, sizeof(pubKey)); + if (ret == 0 && XMEMCMP(pubKey, key->p, ED25519_PUB_KEY_SIZE) != 0) + ret = PUBLIC_KEY_E; + + return ret; +} + +/* returns the private key size (secret only) in bytes */ int wc_ed25519_size(ed25519_key* key) { - word32 keySz; - if (key == NULL) return BAD_FUNC_ARG; - keySz = ED25519_KEY_SIZE; - - return keySz; + return ED25519_KEY_SIZE; } +/* returns the private key size (secret + public) in bytes */ +int wc_ed25519_priv_size(ed25519_key* key) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + return ED25519_PRV_KEY_SIZE; +} + +/* returns the compressed key size in bytes (public key) */ +int wc_ed25519_pub_size(ed25519_key* key) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + return ED25519_PUB_KEY_SIZE; +} /* returns the size of signature in bytes */ int wc_ed25519_sig_size(ed25519_key* key) { - word32 sigSz; - if (key == NULL) return BAD_FUNC_ARG; - sigSz = ED25519_SIG_SIZE; - - return sigSz; + return ED25519_SIG_SIZE; } #endif /* HAVE_ED25519 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ed448.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ed448.c new file mode 100644 index 000000000..125ee3852 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ed448.c @@ -0,0 +1,917 @@ +/* ed448.c + * + * Copyright (C) 2006-2020 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 + */ + +/* Implemented to: RFC 8032 */ + +/* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. + * Reworked for curve448 by Sean Parkinson. + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +/* in case user set HAVE_ED448 there */ +#include + +#ifdef HAVE_ED448 + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(HAVE_ED448_SIGN) || defined(HAVE_ED448_VERIFY) +/* Size of context bytes to use with hash when signing and verifying. */ +#define ED448CTX_SIZE 8 +/* Context to pass to hash when signing and verifying. */ +static const byte ed448Ctx[ED448CTX_SIZE+1] = "SigEd448"; +#endif + +/* Derive the public key for the private key. + * + * key [in] Ed448 key object. + * pubKey [in] Byte array to hold te public key. + * pubKeySz [in] Size of the array in bytes. + * returns BAD_FUNC_ARG when key is NULL or pubKeySz is not equal to + * ED448_PUB_KEY_SIZE, + * other -ve value on hash failure, + * 0 otherwise. + */ +int wc_ed448_make_public(ed448_key* key, unsigned char* pubKey, word32 pubKeySz) +{ + int ret = 0; + byte az[ED448_PRV_KEY_SIZE]; + ge448_p2 A; + + if ((key == NULL) || (pubKeySz != ED448_PUB_KEY_SIZE)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + ret = wc_Shake256Hash(key->k, ED448_KEY_SIZE, az, sizeof(az)); + } + if (ret == 0) { + /* apply clamp */ + az[0] &= 0xfc; + az[55] |= 0x80; + az[56] = 0x00; + + ge448_scalarmult_base(&A, az); + ge448_to_bytes(pubKey, &A); + } + + return ret; +} + +/* Make a new ed448 private/public key. + * + * rng [in] Random number generator. + * keysize [in] Size of the key to generate. + * key [in] Ed448 key object. + * returns BAD_FUNC_ARG when rng or key is NULL or keySz is not equal to + * ED448_KEY_SIZE, + * other -ve value on random number or hash failure, + * 0 otherwise. + */ +int wc_ed448_make_key(WC_RNG* rng, int keySz, ed448_key* key) +{ + int ret = 0; + + if ((rng == NULL) || (key == NULL)) { + ret = BAD_FUNC_ARG; + } + + /* ed448 has 57 byte key sizes */ + if ((ret == 0) && (keySz != ED448_KEY_SIZE)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + ret = wc_RNG_GenerateBlock(rng, key->k, ED448_KEY_SIZE); + } + if (ret == 0) { + ret = wc_ed448_make_public(key, key->p, ED448_PUB_KEY_SIZE); + if (ret != 0) { + ForceZero(key->k, ED448_KEY_SIZE); + } + } + if (ret == 0) { + /* put public key after private key, on the same buffer */ + XMEMMOVE(key->k + ED448_KEY_SIZE, key->p, ED448_PUB_KEY_SIZE); + + key->pubKeySet = 1; + } + + return ret; +} + + +#ifdef HAVE_ED448_SIGN +/* Sign the message using the ed448 private key. + * + * in [in] Message to sign. + * inLen [in] Length of the message in bytes. + * out [in] Buffer to write signature into. + * outLen [in/out] On in, size of buffer. + * On out, the length of the signature in bytes. + * key [in] Ed448 key to use when signing + * type [in] Type of signature to perform: Ed448 or Ed448ph + * context [in] Context of signing. + * contextLen [in] Length of context in bytes. + * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and + * context is not NULL or public key not set, + * BUFFER_E when outLen is less than ED448_SIG_SIZE, + * other -ve values when hash fails, + * 0 otherwise. + */ +static int ed448_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed448_key* key, byte type, + const byte* context, byte contextLen) +{ + ge448_p2 R; + byte nonce[ED448_SIG_SIZE]; + byte hram[ED448_SIG_SIZE]; + byte az[ED448_PRV_KEY_SIZE]; + wc_Shake sha; + int ret = 0; + + /* sanity check on arguments */ + if ((in == NULL) || (out == NULL) || (outLen == NULL) || (key == NULL) || + ((context == NULL) && (contextLen != 0))) { + ret = BAD_FUNC_ARG; + } + if ((ret == 0) && (!key->pubKeySet)) { + ret = BAD_FUNC_ARG; + } + + /* check and set up out length */ + if ((ret == 0) && (*outLen < ED448_SIG_SIZE)) { + *outLen = ED448_SIG_SIZE; + ret = BUFFER_E; + } + + if (ret == 0) { + *outLen = ED448_SIG_SIZE; + + /* step 1: create nonce to use where nonce is r in + r = H(h_b, ... ,h_2b-1,M) */ + ret = wc_Shake256Hash(key->k, ED448_KEY_SIZE, az, sizeof(az)); + } + if (ret == 0) { + /* apply clamp */ + az[0] &= 0xfc; + az[55] |= 0x80; + az[56] = 0x00; + + ret = wc_InitShake256(&sha, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Shake256_Update(&sha, ed448Ctx, ED448CTX_SIZE); + } + if (ret == 0) { + ret = wc_Shake256_Update(&sha, &type, sizeof(type)); + } + if (ret == 0) { + ret = wc_Shake256_Update(&sha, &contextLen, sizeof(contextLen)); + } + if (ret == 0 && context != NULL) { + ret = wc_Shake256_Update(&sha, context, contextLen); + } + if (ret == 0) { + ret = wc_Shake256_Update(&sha, az + ED448_KEY_SIZE, ED448_KEY_SIZE); + } + if (ret == 0) { + ret = wc_Shake256_Update(&sha, in, inLen); + } + if (ret == 0) { + ret = wc_Shake256_Final(&sha, nonce, sizeof(nonce)); + } + wc_Shake256_Free(&sha); + } + if (ret == 0) { + sc448_reduce(nonce); + + /* step 2: computing R = rB where rB is the scalar multiplication of + r and B */ + ge448_scalarmult_base(&R,nonce); + ge448_to_bytes(out,&R); + + /* step 3: hash R + public key + message getting H(R,A,M) then + creating S = (r + H(R,A,M)a) mod l */ + ret = wc_InitShake256(&sha, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Shake256_Update(&sha, ed448Ctx, ED448CTX_SIZE); + if (ret == 0) { + ret = wc_Shake256_Update(&sha, &type, sizeof(type)); + } + if (ret == 0) { + ret = wc_Shake256_Update(&sha, &contextLen, sizeof(contextLen)); + } + if (ret == 0 && context != NULL) { + ret = wc_Shake256_Update(&sha, context, contextLen); + } + if (ret == 0) { + ret = wc_Shake256_Update(&sha, out, ED448_SIG_SIZE/2); + } + if (ret == 0) { + ret = wc_Shake256_Update(&sha, key->p, ED448_PUB_KEY_SIZE); + } + if (ret == 0) { + ret = wc_Shake256_Update(&sha, in, inLen); + } + if (ret == 0) { + ret = wc_Shake256_Final(&sha, hram, sizeof(hram)); + } + wc_Shake256_Free(&sha); + } + } + + if (ret == 0) { + sc448_reduce(hram); + sc448_muladd(out + (ED448_SIG_SIZE/2), hram, az, nonce); + } + + return ret; +} + +/* Sign the message using the ed448 private key. + * Signature type is Ed448. + * + * in [in] Message to sign. + * inLen [in] Length of the message in bytes. + * out [in] Buffer to write signature into. + * outLen [in/out] On in, size of buffer. + * On out, the length of the signature in bytes. + * key [in] Ed448 key to use when signing + * context [in] Context of signing. + * contextLen [in] Length of context in bytes. + * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and + * context is not NULL or public key not set, + * BUFFER_E when outLen is less than ED448_SIG_SIZE, + * other -ve values when hash fails, + * 0 otherwise. + */ +int wc_ed448_sign_msg(const byte* in, word32 inLen, byte* out, word32 *outLen, + ed448_key* key, const byte* context, byte contextLen) +{ + return ed448_sign_msg(in, inLen, out, outLen, key, Ed448, context, + contextLen); +} + +/* Sign the hash using the ed448 private key. + * Signature type is Ed448ph. + * + * hash [in] Hash of message to sign. + * hashLen [in] Length of hash of message in bytes. + * out [in] Buffer to write signature into. + * outLen [in/out] On in, size of buffer. + * On out, the length of the signature in bytes. + * key [in] Ed448 key to use when signing + * context [in] Context of signing. + * contextLen [in] Length of context in bytes. + * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and + * context is not NULL or public key not set, + * BUFFER_E when outLen is less than ED448_SIG_SIZE, + * other -ve values when hash fails, + * 0 otherwise. + */ +int wc_ed448ph_sign_hash(const byte* hash, word32 hashLen, byte* out, + word32 *outLen, ed448_key* key, + const byte* context, byte contextLen) +{ + return ed448_sign_msg(hash, hashLen, out, outLen, key, Ed448ph, context, + contextLen); +} + +/* Sign the message using the ed448 private key. + * Signature type is Ed448ph. + * + * in [in] Message to sign. + * inLen [in] Length of the message to sign in bytes. + * out [in] Buffer to write signature into. + * outLen [in/out] On in, size of buffer. + * On out, the length of the signature in bytes. + * key [in] Ed448 key to use when signing + * context [in] Context of signing. + * contextLen [in] Length of context in bytes. + * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and + * context is not NULL or public key not set, + * BUFFER_E when outLen is less than ED448_SIG_SIZE, + * other -ve values when hash fails, + * 0 otherwise. + */ +int wc_ed448ph_sign_msg(const byte* in, word32 inLen, byte* out, word32 *outLen, + ed448_key* key, const byte* context, byte contextLen) +{ + int ret = 0; + byte hash[64]; + + ret = wc_Shake256Hash(in, inLen, hash, sizeof(hash)); + if (ret == 0) { + ret = wc_ed448ph_sign_hash(hash, sizeof(hash), out, outLen, key, + context, contextLen); + } + + return ret; +} +#endif /* HAVE_ED448_SIGN */ + +#ifdef HAVE_ED448_VERIFY + +/* Verify the message using the ed448 public key. + * + * sig [in] Signature to verify. + * sigLen [in] Size of signature in bytes. + * msg [in] Message to verify. + * msgLen [in] Length of the message in bytes. + * key [in] Ed448 key to use to verify. + * type [in] Type of signature to verify: Ed448 or Ed448ph + * context [in] Context of verification. + * contextLen [in] Length of context in bytes. + * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and + * context is not NULL or public key not set, + * BUFFER_E when sigLen is less than ED448_SIG_SIZE, + * other -ve values when hash fails, + * 0 otherwise. + */ +static int ed448_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, ed448_key* key, + byte type, const byte* context, byte contextLen) +{ + byte rcheck[ED448_KEY_SIZE]; + byte h[ED448_SIG_SIZE]; + ge448_p2 A; + ge448_p2 R; + int ret = 0; + wc_Shake sha; + + /* sanity check on arguments */ + if ((sig == NULL) || (msg == NULL) || (res == NULL) || (key == NULL) || + ((context == NULL) && (contextLen != 0))) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* set verification failed by default */ + *res = 0; + + /* check on basics needed to verify signature */ + if (sigLen < ED448_SIG_SIZE) { + ret = BAD_FUNC_ARG; + } + } + + /* uncompress A (public key), test if valid, and negate it */ + if ((ret == 0) && (ge448_from_bytes_negate_vartime(&A, key->p) != 0)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* find H(R,A,M) and store it as h */ + ret = wc_InitShake256(&sha, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Shake256_Update(&sha, ed448Ctx, ED448CTX_SIZE); + if (ret == 0) { + ret = wc_Shake256_Update(&sha, &type, sizeof(type)); + } + if (ret == 0) { + ret = wc_Shake256_Update(&sha, &contextLen, sizeof(contextLen)); + } + if (ret == 0 && context != NULL) { + ret = wc_Shake256_Update(&sha, context, contextLen); + } + if (ret == 0) { + ret = wc_Shake256_Update(&sha, sig, ED448_SIG_SIZE/2); + } + if (ret == 0) { + ret = wc_Shake256_Update(&sha, key->p, ED448_PUB_KEY_SIZE); + } + if (ret == 0) { + ret = wc_Shake256_Update(&sha, msg, msgLen); + } + if (ret == 0) { + ret = wc_Shake256_Final(&sha, h, sizeof(h)); + } + wc_Shake256_Free(&sha); + } + } + if (ret == 0) { + sc448_reduce(h); + + /* Uses a fast single-signature verification SB = R + H(R,A,M)A becomes + * SB - H(R,A,M)A saving decompression of R + */ + ret = ge448_double_scalarmult_vartime(&R, h, &A, + sig + (ED448_SIG_SIZE/2)); + } + + if (ret == 0) { + ge448_to_bytes(rcheck, &R); + + /* comparison of R created to R in sig */ + if (ConstantCompare(rcheck, sig, ED448_SIG_SIZE/2) != 0) { + ret = SIG_VERIFY_E; + } + else { + /* set the verification status */ + *res = 1; + } + } + + return ret; +} + +/* Verify the message using the ed448 public key. + * Signature type is Ed448. + * + * sig [in] Signature to verify. + * sigLen [in] Size of signature in bytes. + * msg [in] Message to verify. + * msgLen [in] Length of the message in bytes. + * key [in] Ed448 key to use to verify. + * context [in] Context of verification. + * contextLen [in] Length of context in bytes. + * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and + * context is not NULL or public key not set, + * BUFFER_E when sigLen is less than ED448_SIG_SIZE, + * other -ve values when hash fails, + * 0 otherwise. + */ +int wc_ed448_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, ed448_key* key, + const byte* context, byte contextLen) +{ + return ed448_verify_msg(sig, sigLen, msg, msgLen, res, key, Ed448, + context, contextLen); +} + +/* Verify the hash using the ed448 public key. + * Signature type is Ed448ph. + * + * sig [in] Signature to verify. + * sigLen [in] Size of signature in bytes. + * hash [in] Hash of message to verify. + * hashLen [in] Length of the hash in bytes. + * key [in] Ed448 key to use to verify. + * context [in] Context of verification. + * contextLen [in] Length of context in bytes. + * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and + * context is not NULL or public key not set, + * BUFFER_E when sigLen is less than ED448_SIG_SIZE, + * other -ve values when hash fails, + * 0 otherwise. + */ +int wc_ed448ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash, + word32 hashLen, int* res, ed448_key* key, + const byte* context, byte contextLen) +{ + return ed448_verify_msg(sig, sigLen, hash, hashLen, res, key, Ed448ph, + context, contextLen); +} + +/* Verify the message using the ed448 public key. + * Signature type is Ed448ph. + * + * sig [in] Signature to verify. + * sigLen [in] Size of signature in bytes. + * msg [in] Message to verify. + * msgLen [in] Length of the message in bytes. + * key [in] Ed448 key to use to verify. + * context [in] Context of verification. + * contextLen [in] Length of context in bytes. + * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and + * context is not NULL or public key not set, + * BUFFER_E when sigLen is less than ED448_SIG_SIZE, + * other -ve values when hash fails, + * 0 otherwise. + */ +int wc_ed448ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, ed448_key* key, + const byte* context, byte contextLen) +{ + int ret = 0; + byte hash[64]; + + ret = wc_Shake256Hash(msg, msgLen, hash, sizeof(hash)); + if (ret == 0) { + ret = wc_ed448ph_verify_hash(sig, sigLen, hash, sizeof(hash), res, key, + context, contextLen); + } + + return ret; +} +#endif /* HAVE_ED448_VERIFY */ + +/* Initialize the ed448 private/public key. + * + * key [in] Ed448 key. + * returns BAD_FUNC_ARG when key is NULL + */ +int wc_ed448_init(ed448_key* key) +{ + int ret = 0; + + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + else { + XMEMSET(key, 0, sizeof(ed448_key)); + + fe448_init(); + } + + return ret; +} + + +/* Clears the ed448 key data + * + * key [in] Ed448 key. + */ +void wc_ed448_free(ed448_key* key) +{ + if (key != NULL) { + ForceZero(key, sizeof(ed448_key)); + } +} + + +#ifdef HAVE_ED448_KEY_EXPORT + +/* Export the ed448 public key. + * + * key [in] Ed448 public key. + * out [in] Array to hold public key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when outLen is less than ED448_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_ed448_export_public(ed448_key* key, byte* out, word32* outLen) +{ + int ret = 0; + + /* sanity check on arguments */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + ret = BAD_FUNC_ARG; + } + + if ((ret == 0) && (*outLen < ED448_PUB_KEY_SIZE)) { + *outLen = ED448_PUB_KEY_SIZE; + ret = BUFFER_E; + } + + if (ret == 0) { + *outLen = ED448_PUB_KEY_SIZE; + XMEMCPY(out, key->p, ED448_PUB_KEY_SIZE); + } + + return ret; +} + +#endif /* HAVE_ED448_KEY_EXPORT */ + + +#ifdef HAVE_ED448_KEY_IMPORT +/* Import a compressed or uncompressed ed448 public key from a byte array. + * Public key encoded in big-endian. + * + * in [in] Array holding public key. + * inLen [in] Number of bytes of data in array. + * key [in] Ed448 public key. + * returns BAD_FUNC_ARG when a parameter is NULL or key format is not supported, + * 0 otherwise. + */ +int wc_ed448_import_public(const byte* in, word32 inLen, ed448_key* key) +{ + int ret = 0; + + /* sanity check on arguments */ + if ((in == NULL) || (key == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* compressed prefix according to draft + * https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-06 */ + if (in[0] == 0x40 && inLen > ED448_PUB_KEY_SIZE) { + /* key is stored in compressed format so just copy in */ + XMEMCPY(key->p, (in + 1), ED448_PUB_KEY_SIZE); + key->pubKeySet = 1; + } + /* importing uncompressed public key */ + else if (in[0] == 0x04 && inLen > 2*ED448_PUB_KEY_SIZE) { + /* pass in (x,y) and store compressed key */ + ret = ge448_compress_key(key->p, in+1, in+1+ED448_PUB_KEY_SIZE); + if (ret == 0) + key->pubKeySet = 1; + } + else if (inLen == ED448_PUB_KEY_SIZE) { + /* if not specified compressed or uncompressed check key size + * if key size is equal to compressed key size copy in key */ + XMEMCPY(key->p, in, ED448_PUB_KEY_SIZE); + key->pubKeySet = 1; + } + else { + /* bad public key format */ + ret = BAD_FUNC_ARG; + } + } + + return ret; +} + + +/* Import an ed448 private key from a byte array. + * + * priv [in] Array holding private key. + * privSz [in] Number of bytes of data in array. + * key [in] Ed448 private key. + * returns BAD_FUNC_ARG when a parameter is NULL or privSz is less than + * ED448_KEY_SIZE, + * 0 otherwise. + */ +int wc_ed448_import_private_only(const byte* priv, word32 privSz, + ed448_key* key) +{ + int ret = 0; + + /* sanity check on arguments */ + if ((priv == NULL) || (key == NULL)) { + ret = BAD_FUNC_ARG; + } + + /* key size check */ + if ((ret == 0) && (privSz < ED448_KEY_SIZE)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + XMEMCPY(key->k, priv, ED448_KEY_SIZE); + } + + return ret; +} + +/* Import an ed448 private and public keys from a byte arrays. + * + * priv [in] Array holding private key. + * privSz [in] Number of bytes of data in private key array. + * pub [in] Array holding private key. + * pubSz [in] Number of bytes of data in public key array. + * key [in] Ed448 private/public key. + * returns BAD_FUNC_ARG when a parameter is NULL or privSz is less than + * ED448_KEY_SIZE or pubSz is less than ED448_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_ed448_import_private_key(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, ed448_key* key) +{ + int ret = 0; + + /* sanity check on arguments */ + if ((priv == NULL) || (pub == NULL) || (key == NULL)) { + ret = BAD_FUNC_ARG; + } + + /* key size check */ + if ((ret == 0) && (privSz < ED448_KEY_SIZE || pubSz < ED448_PUB_KEY_SIZE)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* import public key */ + ret = wc_ed448_import_public(pub, pubSz, key); + } + if (ret == 0) { + /* make the private key (priv + pub) */ + XMEMCPY(key->k, priv, ED448_KEY_SIZE); + XMEMCPY(key->k + ED448_KEY_SIZE, key->p, ED448_PUB_KEY_SIZE); + } + + return ret; +} + +#endif /* HAVE_ED448_KEY_IMPORT */ + + +#ifdef HAVE_ED448_KEY_EXPORT + +/* Export the ed448 private key. + * + * key [in] Ed448 private key. + * out [in] Array to hold private key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * ECC_BAD_ARG_E when outLen is less than ED448_KEY_SIZE, + * 0 otherwise. + */ +int wc_ed448_export_private_only(ed448_key* key, byte* out, word32* outLen) +{ + int ret = 0; + + /* sanity checks on arguments */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + ret = BAD_FUNC_ARG; + } + + if ((ret == 0) && (*outLen < ED448_KEY_SIZE)) { + *outLen = ED448_KEY_SIZE; + ret = BUFFER_E; + } + + if (ret == 0) { + *outLen = ED448_KEY_SIZE; + XMEMCPY(out, key->k, ED448_KEY_SIZE); + } + + return ret; +} + +/* Export the ed448 private and public key. + * + * key [in] Ed448 private/public key. + * out [in] Array to hold private and public key. + * outLen [in/out] On in, the number of bytes in array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * BUFFER_E when outLen is less than ED448_PRV_KEY_SIZE, + * 0 otherwise. + */ +int wc_ed448_export_private(ed448_key* key, byte* out, word32* outLen) +{ + int ret = 0; + + /* sanity checks on arguments */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + ret = BAD_FUNC_ARG; + } + + if ((ret == 0) && (*outLen < ED448_PRV_KEY_SIZE)) { + *outLen = ED448_PRV_KEY_SIZE; + ret = BUFFER_E; + } + + if (ret == 0) { + *outLen = ED448_PRV_KEY_SIZE; + XMEMCPY(out, key->k, ED448_PRV_KEY_SIZE); + } + + return ret; +} + +/* Export the ed448 private and public key. + * + * key [in] Ed448 private/public key. + * priv [in] Array to hold private key. + * privSz [in/out] On in, the number of bytes in private key array. + * pub [in] Array to hold public key. + * pubSz [in/out] On in, the number of bytes in public key array. + * On out, the number bytes put into array. + * returns BAD_FUNC_ARG when a parameter is NULL, + * BUFFER_E when privSz is less than ED448_PRV_KEY_SIZE or pubSz is less + * than ED448_PUB_KEY_SIZE, + * 0 otherwise. + */ +int wc_ed448_export_key(ed448_key* key, byte* priv, word32 *privSz, + byte* pub, word32 *pubSz) +{ + int ret = 0; + + /* export 'full' private part */ + ret = wc_ed448_export_private(key, priv, privSz); + if (ret == 0) { + /* export public part */ + ret = wc_ed448_export_public(key, pub, pubSz); + } + + return ret; +} + +#endif /* HAVE_ED448_KEY_EXPORT */ + +/* Check the public key of the ed448 key matches the private key. + * + * key [in] Ed448 private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * PUBLIC_KEY_E when the public key is not set or doesn't match, + * other -ve value on hash failure, + * 0 otherwise. + */ +int wc_ed448_check_key(ed448_key* key) +{ + int ret = 0; + unsigned char pubKey[ED448_PUB_KEY_SIZE]; + + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + + if (!key->pubKeySet) { + ret = PUBLIC_KEY_E; + } + if (ret == 0) { + ret = wc_ed448_make_public(key, pubKey, sizeof(pubKey)); + } + if ((ret == 0) && (XMEMCMP(pubKey, key->p, ED448_PUB_KEY_SIZE) != 0)) { + ret = PUBLIC_KEY_E; + } + + return ret; +} + +/* Returns the size of an ed448 private key. + * + * key [in] Ed448 private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * ED448_KEY_SIZE otherwise. + */ +int wc_ed448_size(ed448_key* key) +{ + int ret = ED448_KEY_SIZE; + + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + + return ret; +} + +/* Returns the size of an ed448 private plus public key. + * + * key [in] Ed448 private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * ED448_PRV_KEY_SIZE otherwise. + */ +int wc_ed448_priv_size(ed448_key* key) +{ + int ret = ED448_PRV_KEY_SIZE; + + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + + return ret; +} + +/* Returns the size of an ed448 public key. + * + * key [in] Ed448 private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * ED448_PUB_KEY_SIZE otherwise. + */ +int wc_ed448_pub_size(ed448_key* key) +{ + int ret = ED448_PUB_KEY_SIZE; + + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + + return ret; +} + +/* Returns the size of an ed448 signature. + * + * key [in] Ed448 private/public key. + * returns BAD_FUNC_ARG when key is NULL, + * ED448_SIG_SIZE otherwise. + */ +int wc_ed448_sig_size(ed448_key* key) +{ + int ret = ED448_SIG_SIZE; + + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + + return ret; +} + +#endif /* HAVE_ED448 */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/error.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/error.c index 7d1d5ebe7..87ded35d6 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/error.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/error.c @@ -1,8 +1,8 @@ /* error.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -32,15 +33,9 @@ #pragma warning(disable: 4996) #endif +#ifndef NO_ERROR_STRINGS const char* wc_GetErrorString(int error) { -#ifdef NO_ERROR_STRINGS - - (void)error; - return "no support for error strings built in"; - -#else - switch (error) { case OPEN_RAN_E : @@ -61,6 +56,15 @@ const char* wc_GetErrorString(int error) case BAD_MUTEX_E : return "Bad mutex, operation failed"; + case WC_TIMEOUT_E: + return "Timeout error"; + + case WC_PENDING_E: + return "wolfCrypt Operation Pending (would block / eagain) error"; + + case WC_NOT_PENDING_E: + return "wolfCrypt operation not pending error"; + case MP_INIT_E : return "mp_init error state"; @@ -100,6 +104,9 @@ const char* wc_GetErrorString(int error) case MEMORY_E : return "out of memory error"; + case VAR_STATE_CHANGE_E : + return "Variable state modified by different thread"; + case RSA_WRONG_TYPE_E : return "RSA wrong block type for RSA function"; @@ -110,7 +117,7 @@ const char* wc_GetErrorString(int error) return "Buffer error, output too small or input too big"; case ALGO_ID_E : - return "Setting Cert AlogID error"; + return "Setting Cert AlgoID error"; case PUBLIC_KEY_E : return "Setting Cert Public Key error"; @@ -170,7 +177,7 @@ const char* wc_GetErrorString(int error) return "ASN signature error, mismatched oid"; case ASN_TIME_E : - return "ASN time error, unkown time type"; + return "ASN time error, unknown time type"; case ASN_INPUT_E : return "ASN input error, not enough data"; @@ -191,7 +198,10 @@ 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 ASN_ALT_NAME_E: + return "ASN alternate name error"; case ECC_BAD_ARG_E : return "ECC input argument wrong type, invalid input"; @@ -223,8 +233,8 @@ const char* wc_GetErrorString(int error) case AES_CCM_AUTH_E: return "AES-CCM Authentication check fail"; - case CAVIUM_INIT_E: - return "Cavium Init type error"; + case ASYNC_INIT_E: + return "Async Init error"; case COMPRESS_INIT_E: return "Compress Init error"; @@ -253,8 +263,11 @@ const char* wc_GetErrorString(int error) case ASN_OCSP_CONFIRM_E : return "ASN OCSP sig error, confirm failure"; - case BAD_ENC_STATE_E: - return "Bad ecc encrypt state operation"; + case ASN_NO_PEM_HEADER: + return "ASN no PEM Header Error"; + + case BAD_STATE_E: + return "Bad state operation"; case BAD_PADDING_E: return "Bad padding, message wrong length"; @@ -268,6 +281,9 @@ const char* wc_GetErrorString(int error) case PKCS7_RECIP_E: return "PKCS#7 error: no matching recipient found"; + case WC_PKCS7_WANT_READ_E: + return "PKCS#7 operations wants more input, call again"; + case FIPS_NOT_ALLOWED_E: return "FIPS mode not allowed error"; @@ -325,19 +341,190 @@ const char* wc_GetErrorString(int error) case ECC_INF_E: return " ECC point at infinity error"; + case ECC_OUT_OF_RANGE_E: + return " ECC Qx or Qy out of range error"; + case ECC_PRIV_KEY_E: return " ECC private key is not valid error"; + case SRP_CALL_ORDER_E: + return "SRP function called in the wrong order error"; + + case SRP_VERIFY_E: + return "SRP proof verification error"; + + case SRP_BAD_KEY_E: + return "SRP bad key values error"; + + case ASN_NO_SKID: + return "ASN no Subject Key Identifier found error"; + + case ASN_NO_AKID: + return "ASN no Authority Key Identifier found error"; + + case ASN_NO_KEYUSAGE: + return "ASN no Key Usage found error"; + + case SKID_E: + return "Setting Subject Key Identifier error"; + + case AKID_E: + return "Setting Authority Key Identifier error"; + + case KEYUSAGE_E: + return "Key Usage value error"; + + case EXTKEYUSAGE_E: + return "Extended Key Usage value error"; + + case CERTPOLICIES_E: + return "Setting Certificate Policies error"; + + case WC_INIT_E: + return "wolfCrypt Initialize Failure error"; + + case SIG_VERIFY_E: + return "Signature verify error"; + + case BAD_COND_E: + return "Bad condition variable operation error"; + + case SIG_TYPE_E: + return "Signature type not enabled/available"; + + case HASH_TYPE_E: + return "Hash type not enabled/available"; + + case WC_KEY_SIZE_E: + return "Key size error, either too small or large"; + + case ASN_COUNTRY_SIZE_E: + return "Country code size error, either too small or large"; + + case MISSING_RNG_E: + return "RNG required but not provided"; + + case ASN_PATHLEN_SIZE_E: + return "ASN CA path length value too large error"; + + case ASN_PATHLEN_INV_E: + return "ASN CA path length larger than signer error"; + + case BAD_KEYWRAP_ALG_E: + return "Unsupported key wrap algorithm error"; + + case BAD_KEYWRAP_IV_E: + return "Decrypted AES key wrap IV does not match expected"; + + 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"; + + case WC_HW_E: + return "Error with hardware crypto use"; + + case WC_HW_WAIT_E: + return "Hardware waiting on resource"; + + case PSS_SALTLEN_E: + return "PSS - Length of salt is too big for hash algorithm"; + + case PRIME_GEN_E: + return "Unable to find a prime for RSA key"; + + case BER_INDEF_E: + return "Unable to decode an indefinite length encoded message"; + + case RSA_OUT_OF_RANGE_E: + return "Ciphertext to decrypt is out of range"; + + case RSAPSS_PAT_FIPS_E: + return "wolfcrypt FIPS RSA-PSS Pairwise Agreement Test Failure"; + + case ECDSA_PAT_FIPS_E: + return "wolfcrypt FIPS ECDSA Pairwise Agreement Test Failure"; + + case DH_KAT_FIPS_E: + return "wolfcrypt FIPS DH Known Answer Test Failure"; + + case AESCCM_KAT_FIPS_E: + return "AESCCM Known Answer Test check FIPS error"; + + case SHA3_KAT_FIPS_E: + return "SHA-3 Known Answer Test check FIPS error"; + + case ECDHE_KAT_FIPS_E: + return "wolfcrypt FIPS ECDHE Known Answer Test Failure"; + + case AES_GCM_OVERFLOW_E: + return "AES-GCM invocation counter overflow"; + + case AES_CCM_OVERFLOW_E: + return "AES-CCM invocation counter overflow"; + + case RSA_KEY_PAIR_E: + return "RSA Key Pair-Wise Consistency check fail"; + + case DH_CHECK_PRIV_E: + return "DH Check Private Key failure"; + + case WC_AFALG_SOCK_E: + return "AF_ALG socket error"; + + case WC_DEVCRYPTO_E: + return "Error with /dev/crypto"; + + case ZLIB_INIT_ERROR: + return "zlib init error"; + + case ZLIB_COMPRESS_ERROR: + return "zlib compress error"; + + case ZLIB_DECOMPRESS_ERROR: + return "zlib decompress error"; + + case PKCS7_NO_SIGNER_E: + return "No signer in PKCS#7 signed data"; + + case CRYPTOCB_UNAVAILABLE: + return "Crypto callback unavailable"; + + case PKCS7_SIGNEEDS_CHECK: + return "Signature found but no certificate to verify"; + + case PSS_SALTLEN_RECOVER_E: + return "PSS - Salt length unable to be recovered"; + + case ASN_SELF_SIGNED_E: + return "ASN self-signed certificate error"; + default: return "unknown error number"; } - -#endif /* NO_ERROR_STRINGS */ - } void wc_ErrorString(int error, char* buffer) { XSTRNCPY(buffer, wc_GetErrorString(error), WOLFSSL_MAX_ERROR_SZ); + buffer[WOLFSSL_MAX_ERROR_SZ-1] = 0; } +#endif /* !NO_ERROR_STRINGS */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/evp.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/evp.c new file mode 100644 index 000000000..7fffda210 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/evp.c @@ -0,0 +1,6595 @@ +/* evp.c + * + * Copyright (C) 2006-2020 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(WOLFSSL_EVP_INCLUDED) + #ifndef WOLFSSL_IGNORE_FILE_WARN +// #warning evp.c does not need to be compiled separately from ssl.c + #endif +#elif defined(WOLFCRYPT_ONLY) +#else + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#include +#include + +#if defined(OPENSSL_EXTRA) + +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_CBC = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_CBC = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_CBC = NULL; + #endif + #endif /* HAVE_AES_CBC */ + + #ifdef WOLFSSL_AES_OFB + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_OFB = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_OFB = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_OFB = NULL; + #endif + #endif /* WOLFSSL_AES_OFB */ + + #ifdef WOLFSSL_AES_XTS + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_XTS = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_XTS = NULL; + #endif + #endif /* WOLFSSL_AES_XTS */ + + #ifdef WOLFSSL_AES_CFB + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_CFB1 = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_CFB1 = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_CFB1 = NULL; + #endif + + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_CFB8 = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_CFB8 = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_CFB8 = NULL; + #endif + + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_CFB128 = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_CFB128 = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_CFB128 = NULL; + #endif + #endif /* WOLFSSL_AES_CFB */ + + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_GCM = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_GCM = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_GCM = NULL; + #endif + #endif /* HAVE_AESGCM */ + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_CTR = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_CTR = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_CTR = NULL; + #endif + + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_ECB = NULL; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_ECB = NULL; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_ECB = NULL; + #endif + #define EVP_AES_SIZE 11 + #ifdef WOLFSSL_AES_CFB + #define EVP_AESCFB_SIZE 14 + #endif +#endif + +#ifndef NO_DES3 + static char *EVP_DES_CBC = NULL; + static char *EVP_DES_ECB = NULL; + + static char *EVP_DES_EDE3_CBC = NULL; + static char *EVP_DES_EDE3_ECB = NULL; + + #define EVP_DES_SIZE 7 + #define EVP_DES_EDE3_SIZE 12 +#endif + +#ifdef HAVE_IDEA + static char *EVP_IDEA_CBC; + #define EVP_IDEA_SIZE 8 +#endif + +static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher); + + +/* Getter function for cipher key length + * + * c WOLFSSL_EVP_CIPHER structure to get key length from + * + * NOTE: OpenSSL_add_all_ciphers() should be called first before using this + * function + * + * Returns size of key in bytes + */ +int wolfSSL_EVP_Cipher_key_length(const WOLFSSL_EVP_CIPHER* c) +{ + WOLFSSL_ENTER("wolfSSL_EVP_Cipher_key_length"); + + if (c == NULL) { + return 0; + } + + switch (cipherType(c)) { +#if !defined(NO_AES) + #if defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: return 16; + case AES_192_CBC_TYPE: return 24; + case AES_256_CBC_TYPE: return 32; + #endif + #if defined(WOLFSSL_AES_CFB) + case AES_128_CFB1_TYPE: return 16; + case AES_192_CFB1_TYPE: return 24; + case AES_256_CFB1_TYPE: return 32; + case AES_128_CFB8_TYPE: return 16; + case AES_192_CFB8_TYPE: return 24; + case AES_256_CFB8_TYPE: return 32; + case AES_128_CFB128_TYPE: return 16; + case AES_192_CFB128_TYPE: return 24; + case AES_256_CFB128_TYPE: return 32; + #endif + #if defined(WOLFSSL_AES_OFB) + case AES_128_OFB_TYPE: return 16; + case AES_192_OFB_TYPE: return 24; + case AES_256_OFB_TYPE: return 32; + #endif + #if defined(WOLFSSL_AES_XTS) + case AES_128_XTS_TYPE: return 16; + case AES_256_XTS_TYPE: return 32; + #endif + #if defined(HAVE_AESGCM) + case AES_128_GCM_TYPE: return 16; + case AES_192_GCM_TYPE: return 24; + case AES_256_GCM_TYPE: return 32; + #endif + #if defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: return 16; + case AES_192_CTR_TYPE: return 24; + case AES_256_CTR_TYPE: return 32; + #endif + #if defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: return 16; + case AES_192_ECB_TYPE: return 24; + case AES_256_ECB_TYPE: return 32; + #endif +#endif /* !NO_AES */ + #ifndef NO_DES3 + case DES_CBC_TYPE: return 8; + case DES_EDE3_CBC_TYPE: return 24; + case DES_ECB_TYPE: return 8; + case DES_EDE3_ECB_TYPE: return 24; + #endif + default: + return 0; + } +} + + +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); +} + +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); +} + +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); +} + +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); +} + + +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_EVP_CIPHER_CTX_init(ctx); + } + return ctx; +} + +void wolfSSL_EVP_CIPHER_CTX_free(WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx) { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_free"); + wolfSSL_EVP_CIPHER_CTX_cleanup(ctx); + XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +} + +int wolfSSL_EVP_CIPHER_CTX_reset(WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + int ret = WOLFSSL_FAILURE; + + if (ctx != NULL) { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_reset"); + wolfSSL_EVP_CIPHER_CTX_cleanup(ctx); + ret = WOLFSSL_SUCCESS; + } + + return ret; +} + +unsigned long wolfSSL_EVP_CIPHER_CTX_mode(const WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx == NULL) return 0; + return ctx->flags & WOLFSSL_EVP_CIPH_MODE; +} + +int wolfSSL_EVP_EncryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc) { + WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else + return WOLFSSL_FAILURE; +} + + +int wolfSSL_EVP_CipherInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + const unsigned char* key, + const unsigned char* iv, + int enc) +{ + (void)impl; + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, enc); +} + +int wolfSSL_EVP_EncryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc) { + WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal_ex"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else + return WOLFSSL_FAILURE; +} + +int wolfSSL_EVP_DecryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && !ctx->enc) { + WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else { + return WOLFSSL_FAILURE; + } +} + +int wolfSSL_EVP_DecryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && !ctx->enc) { + WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal_ex"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else { + return WOLFSSL_FAILURE; + } +} + + +int wolfSSL_EVP_DigestInit_ex(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* type, + WOLFSSL_ENGINE *impl) +{ + (void) impl; + WOLFSSL_ENTER("wolfSSL_EVP_DigestInit_ex"); + return wolfSSL_EVP_DigestInit(ctx, type); +} + +#ifdef DEBUG_WOLFSSL_EVP +#define PRINT_BUF(b, sz) { int _i; for(_i=0; _i<(sz); _i++) { \ + printf("%02x(%c),", (b)[_i], (b)[_i]); if ((_i+1)%8==0)printf("\n");}} +#else +#define PRINT_BUF(b, sz) +#endif + +static int fillBuff(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int sz) +{ + int fill; + + if (sz > 0) { + if ((sz+ctx->bufUsed) > ctx->block_size) { + fill = ctx->block_size - ctx->bufUsed; + } else { + fill = sz; + } + XMEMCPY(&(ctx->buf[ctx->bufUsed]), in, fill); + ctx->bufUsed += fill; + return fill; + } else return 0; +} + +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) + #if defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + if (ctx->enc) + ret = wc_AesCbcEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesCbcDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if defined(HAVE_AESGCM) + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: + if (ctx->enc) { + if (out){ + /* encrypt confidential data*/ + ret = wc_AesGcmEncrypt(&ctx->cipher.aes, out, in, inl, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + NULL, 0); + } + else { + /* authenticated, non-confidential data */ + ret = wc_AesGcmEncrypt(&ctx->cipher.aes, NULL, NULL, 0, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + in, inl); + /* Reset partial authTag error for AAD*/ + if (ret == AES_GCM_AUTH_E) + ret = 0; + } + } + else { + if (out){ + /* decrypt confidential data*/ + ret = wc_AesGcmDecrypt(&ctx->cipher.aes, out, in, inl, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + NULL, 0); + } + else { + /* authenticated, non-confidential data*/ + ret = wc_AesGcmDecrypt(&ctx->cipher.aes, NULL, NULL, 0, + ctx->iv, ctx->ivSz, + ctx->authTag, ctx->authTagSz, + in, inl); + /* Reset partial authTag error for AAD*/ + if (ret == AES_GCM_AUTH_E) + ret = 0; + } + } + break; + #endif + #if defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + ret = wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + if (ctx->enc) + ret = wc_AesEcbEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesEcbDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if defined(WOLFSSL_AES_OFB) + case AES_128_OFB_TYPE: + case AES_192_OFB_TYPE: + case AES_256_OFB_TYPE: + if (ctx->enc) + ret = wc_AesOfbEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesOfbDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if defined(WOLFSSL_AES_CFB) + #if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + case AES_128_CFB1_TYPE: + case AES_192_CFB1_TYPE: + case AES_256_CFB1_TYPE: + if (ctx->enc) + ret = wc_AesCfb1Encrypt(&ctx->cipher.aes, out, in, + inl * WOLFSSL_BIT_SIZE); + else + ret = wc_AesCfb1Decrypt(&ctx->cipher.aes, out, in, + inl * WOLFSSL_BIT_SIZE); + break; + + case AES_128_CFB8_TYPE: + case AES_192_CFB8_TYPE: + case AES_256_CFB8_TYPE: + if (ctx->enc) + ret = wc_AesCfb8Encrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesCfb8Decrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif /* !HAVE_SELFTEST && !HAVE_FIPS */ + + case AES_128_CFB128_TYPE: + case AES_192_CFB128_TYPE: + case AES_256_CFB128_TYPE: + if (ctx->enc) + ret = wc_AesCfbEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesCfbDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif +#if defined(WOLFSSL_AES_XTS) + case AES_128_XTS_TYPE: + case AES_256_XTS_TYPE: + if (ctx->enc) + ret = wc_AesXtsEncrypt(&ctx->cipher.xts, out, in, inl, + ctx->iv, ctx->ivSz); + else + ret = wc_AesXtsDecrypt(&ctx->cipher.xts, out, in, inl, + ctx->iv, ctx->ivSz); + break; +#endif +#endif /* !NO_AES */ + #ifndef NO_DES3 + case DES_CBC_TYPE: + if (ctx->enc) + ret = wc_Des_CbcEncrypt(&ctx->cipher.des, out, in, inl); + else + ret = wc_Des_CbcDecrypt(&ctx->cipher.des, out, in, inl); + break; + case DES_EDE3_CBC_TYPE: + if (ctx->enc) + ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, out, in, inl); + else + ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, out, in, inl); + break; + #if defined(WOLFSSL_DES_ECB) + case DES_ECB_TYPE: + ret = wc_Des_EcbEncrypt(&ctx->cipher.des, out, in, inl); + break; + case DES_EDE3_ECB_TYPE: + ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, out, in, inl); + break; + #endif + #endif + #ifndef NO_RC4 + case ARC4_TYPE: + wc_Arc4Process(&ctx->cipher.arc4, out, in, inl); + break; + #endif + default: + return WOLFSSL_FAILURE; + } + + if (ret != 0) + return WOLFSSL_FAILURE; /* failure */ + + (void)in; + (void)inl; + (void)out; + + return WOLFSSL_SUCCESS; /* success */ +} + +#if defined(HAVE_AESGCM) +static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + /* process blocks */ + if (evpCipherBlock(ctx, out, in, inl) == 0) + return WOLFSSL_FAILURE; + *outl = inl; + return WOLFSSL_SUCCESS; +} +#endif + +/* returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ +WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + int blocks; + int fill; + + WOLFSSL_ENTER("wolfSSL_EVP_CipherUpdate"); + if ((ctx == NULL) || (inl < 0) || (outl == NULL)|| (in == NULL)) { + WOLFSSL_MSG("Bad argument"); + return WOLFSSL_FAILURE; + } + + *outl = 0; + if (inl == 0) { + return WOLFSSL_SUCCESS; + } + +#if !defined(NO_AES) && defined(HAVE_AESGCM) + switch (ctx->cipherType) { + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: +/* if out == NULL, in/inl contains the additional authenticated data for GCM */ + return wolfSSL_EVP_CipherUpdate_GCM(ctx, out, outl, in, inl); + default: + /* fall-through */ + break; + } +#endif /* !defined(NO_AES) && defined(HAVE_AESGCM) */ + + if (out == NULL) { + return WOLFSSL_FAILURE; + } + + + if (ctx->bufUsed > 0) { /* concatenate them if there is anything */ + fill = fillBuff(ctx, in, inl); + inl -= fill; + in += fill; + } + + /* check if the buff is full, and if so flash it out */ + if (ctx->bufUsed == ctx->block_size) { + byte* output = out; + + /* During decryption we save the last block to check padding on Final. + * Update the last block stored if one has already been stored */ + if (ctx->enc == 0) { + if (ctx->lastUsed == 1) { + XMEMCPY(out, ctx->lastBlock, ctx->block_size); + *outl+= ctx->block_size; + out += ctx->block_size; + } + output = ctx->lastBlock; /* redirect output to last block buffer */ + ctx->lastUsed = 1; + } + + PRINT_BUF(ctx->buf, ctx->block_size); + if (evpCipherBlock(ctx, output, ctx->buf, ctx->block_size) == 0) { + return WOLFSSL_FAILURE; + } + PRINT_BUF(out, ctx->block_size); + ctx->bufUsed = 0; + + /* if doing encryption update the new output block, decryption will + * always have the last block saved for when Final is called */ + if ((ctx->enc != 0)) { + *outl+= ctx->block_size; + out += ctx->block_size; + } + } + + blocks = inl / ctx->block_size; + if (blocks > 0) { + /* During decryption we save the last block to check padding on Final. + * Update the last block stored if one has already been stored */ + if ((ctx->enc == 0) && (ctx->lastUsed == 1)) { + PRINT_BUF(ctx->lastBlock, ctx->block_size); + XMEMCPY(out, ctx->lastBlock, ctx->block_size); + *outl += ctx->block_size; + out += ctx->block_size; + ctx->lastUsed = 0; + } + + /* process blocks */ + if (evpCipherBlock(ctx, out, in, blocks * ctx->block_size) == 0) { + return WOLFSSL_FAILURE; + } + PRINT_BUF(in, ctx->block_size*blocks); + PRINT_BUF(out,ctx->block_size*blocks); + inl -= ctx->block_size * blocks; + in += ctx->block_size * blocks; + if (ctx->enc == 0) { + if ((ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) || + (ctx->block_size == 1)) { + ctx->lastUsed = 0; + *outl += ctx->block_size * blocks; + } else { + /* in the case of decryption and padding, store the last block + * here in order to verify the padding when Final is called */ + if (inl == 0) { /* if not 0 then we know leftovers are checked*/ + ctx->lastUsed = 1; + blocks = blocks - 1; /* save last block to check padding in + * EVP_CipherFinal call */ + XMEMCPY(ctx->lastBlock, &out[ctx->block_size * blocks], + ctx->block_size); + } + *outl += ctx->block_size * blocks; + } + } else { + *outl += ctx->block_size * blocks; + } + } + + + if (inl > 0) { + /* put fraction into buff */ + fillBuff(ctx, in, inl); + /* no increase of outl */ + } + (void)out; /* silence warning in case not read */ + + return WOLFSSL_SUCCESS; +} + +static void padBlock(WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + int i; + for (i = ctx->bufUsed; i < ctx->block_size; i++) + ctx->buf[i] = (byte)(ctx->block_size - ctx->bufUsed); +} + +static int checkPad(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *buff) +{ + int i; + int n; + n = buff[ctx->block_size-1]; + if (n > ctx->block_size) return -1; + for (i = 0; i < n; i++) { + if (buff[ctx->block_size-i-1] != n) + return -1; + } + return ctx->block_size - n; +} + +int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + int fl; + int ret = WOLFSSL_SUCCESS; + if (!ctx || !outl) + return WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal"); + +#if !defined(NO_AES) && defined(HAVE_AESGCM) + switch (ctx->cipherType) { + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: + *outl = 0; + /* Clear IV, since IV reuse is not recommended for AES GCM. */ + XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE); + return WOLFSSL_SUCCESS; + default: + /* fall-through */ + break; + } +#endif /* !NO_AES && HAVE_AESGCM */ + + if (!out) + return WOLFSSL_FAILURE; + + if (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) { + if (ctx->bufUsed != 0) return WOLFSSL_FAILURE; + *outl = 0; + } + else if (ctx->enc) { + if (ctx->block_size == 1) { + *outl = 0; + } + else 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) { + WOLFSSL_MSG("Final Cipher Block failed"); + ret = WOLFSSL_FAILURE; + } + else { + PRINT_BUF(out, ctx->block_size); + *outl = ctx->block_size; + } + } + } + else { + if (ctx->block_size == 1) { + *outl = 0; + } + else if ((ctx->bufUsed % ctx->block_size) != 0) { + *outl = 0; + /* not enough padding for decrypt */ + WOLFSSL_MSG("Final Cipher Block not enough padding"); + ret = WOLFSSL_FAILURE; + } + else if (ctx->lastUsed) { + PRINT_BUF(ctx->lastBlock, ctx->block_size); + if ((fl = checkPad(ctx, ctx->lastBlock)) >= 0) { + XMEMCPY(out, ctx->lastBlock, fl); + *outl = fl; + if (ctx->lastUsed == 0 && ctx->bufUsed == 0) { + /* return error in cases where the block length is incorrect */ + WOLFSSL_MSG("Final Cipher Block bad length"); + ret = WOLFSSL_FAILURE; + } + } + else { + ret = WOLFSSL_FAILURE; + } + } + else if (ctx->lastUsed == 0 && ctx->bufUsed == 0) { + /* return error in cases where the block length is incorrect */ + ret = WOLFSSL_FAILURE; + } + } + if (ret == WOLFSSL_SUCCESS) { + /* reset cipher state after final */ + wolfSSL_EVP_CipherInit(ctx, NULL, NULL, NULL, -1); + } + return ret; +} + + +#ifdef WOLFSSL_EVP_DECRYPT_LEGACY +/* This is a version of DecryptFinal to work with data encrypted with + * wolfSSL_EVP_EncryptFinal() with the broken padding. (pre-v3.12.0) + * Only call this after wolfSSL_EVP_CipherFinal() fails on a decrypt. + * Note, you don't know if the padding is good or bad with the old + * encrypt, but it is likely to be or bad. It will update the output + * length with the block_size so the last block is still captured. */ +WOLFSSL_API int wolfSSL_EVP_DecryptFinal_legacy(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + int fl; + if (ctx == NULL || out == NULL || outl == NULL) + return BAD_FUNC_ARG; + + WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal_legacy"); + if (ctx->block_size == 1) { + *outl = 0; + return WOLFSSL_SUCCESS; + } + if ((ctx->bufUsed % ctx->block_size) != 0) { + *outl = 0; + /* not enough padding for decrypt */ + return WOLFSSL_FAILURE; + } + /* The original behavior of CipherFinal() was like it is now, + * but checkPad would return 0 in case of a bad pad. It would + * treat the pad as 0, and leave the data in the output buffer, + * and not try to copy anything. This converts checkPad's -1 error + * code to block_size. + */ + if (ctx->lastUsed) { + PRINT_BUF(ctx->lastBlock, ctx->block_size); + if ((fl = checkPad(ctx, ctx->lastBlock)) < 0) { + fl = ctx->block_size; + } + else { + XMEMCPY(out, ctx->lastBlock, fl); + } + *outl = fl; + } + /* return error in cases where the block length is incorrect */ + if (ctx->lastUsed == 0 && ctx->bufUsed == 0) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +#endif + + +int wolfSSL_EVP_CIPHER_CTX_block_size(const WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx == NULL) return BAD_FUNC_ARG; + switch (ctx->cipherType) { +#if !defined(NO_AES) || !defined(NO_DES3) +#if !defined(NO_AES) +#if defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: +#endif +#if defined(HAVE_AESGCM) + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: +#endif +#if defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: +#endif +#if defined(WOLFSSL_AES_CFB) + case AES_128_CFB1_TYPE: + case AES_192_CFB1_TYPE: + case AES_256_CFB1_TYPE: + case AES_128_CFB8_TYPE: + case AES_192_CFB8_TYPE: + case AES_256_CFB8_TYPE: + case AES_128_CFB128_TYPE: + case AES_192_CFB128_TYPE: + case AES_256_CFB128_TYPE: +#endif +#if defined(WOLFSSL_AES_OFB) + case AES_128_OFB_TYPE: + case AES_192_OFB_TYPE: + case AES_256_OFB_TYPE: +#endif +#if defined(WOLFSSL_AES_XTS) + case AES_128_XTS_TYPE: + case AES_256_XTS_TYPE: +#endif + + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: +#endif /* !NO_AES */ +#ifndef NO_DES3 + case DES_CBC_TYPE: + case DES_ECB_TYPE: + case DES_EDE3_CBC_TYPE: + case DES_EDE3_ECB_TYPE: +#endif + return ctx->block_size; +#endif /* !NO_AES || !NO_DES3 */ + default: + return 0; + } +} + +static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; /* dummy for #ifdef */ +#ifndef NO_DES3 + else if (EVP_DES_CBC && XSTRNCMP(cipher, EVP_DES_CBC, EVP_DES_SIZE) == 0) + return DES_CBC_TYPE; + else if (EVP_DES_EDE3_CBC && XSTRNCMP(cipher, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0) + return DES_EDE3_CBC_TYPE; +#if !defined(NO_DES3) + else if (EVP_DES_ECB && XSTRNCMP(cipher, EVP_DES_ECB, EVP_DES_SIZE) == 0) + return DES_ECB_TYPE; + else if (EVP_DES_EDE3_ECB && XSTRNCMP(cipher, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0) + return DES_EDE3_ECB_TYPE; +#endif /* NO_DES3 && HAVE_AES_ECB */ +#endif +#if !defined(NO_AES) +#if defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_CBC && XSTRNCMP(cipher, EVP_AES_128_CBC, EVP_AES_SIZE) == 0) + return AES_128_CBC_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_CBC && XSTRNCMP(cipher, EVP_AES_192_CBC, EVP_AES_SIZE) == 0) + return AES_192_CBC_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_CBC && XSTRNCMP(cipher, EVP_AES_256_CBC, EVP_AES_SIZE) == 0) + return AES_256_CBC_TYPE; + #endif +#endif /* HAVE_AES_CBC */ +#if defined(HAVE_AESGCM) + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_GCM && XSTRNCMP(cipher, EVP_AES_128_GCM, EVP_AES_SIZE) == 0) + return AES_128_GCM_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_GCM && XSTRNCMP(cipher, EVP_AES_192_GCM, EVP_AES_SIZE) == 0) + return AES_192_GCM_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_GCM && XSTRNCMP(cipher, EVP_AES_256_GCM, EVP_AES_SIZE) == 0) + return AES_256_GCM_TYPE; + #endif +#endif /* HAVE_AESGCM */ +#if defined(WOLFSSL_AES_COUNTER) + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_CTR && XSTRNCMP(cipher, EVP_AES_128_CTR, EVP_AES_SIZE) == 0) + return AES_128_CTR_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_CTR && XSTRNCMP(cipher, EVP_AES_192_CTR, EVP_AES_SIZE) == 0) + return AES_192_CTR_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_CTR && XSTRNCMP(cipher, EVP_AES_256_CTR, EVP_AES_SIZE) == 0) + return AES_256_CTR_TYPE; + #endif +#endif /* HAVE_AES_CBC */ +#if defined(HAVE_AES_ECB) + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_ECB && XSTRNCMP(cipher, EVP_AES_128_ECB, EVP_AES_SIZE) == 0) + return AES_128_ECB_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_ECB && XSTRNCMP(cipher, EVP_AES_192_ECB, EVP_AES_SIZE) == 0) + return AES_192_ECB_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_ECB && XSTRNCMP(cipher, EVP_AES_256_ECB, EVP_AES_SIZE) == 0) + return AES_256_ECB_TYPE; + #endif +#endif /*HAVE_AES_CBC */ +#if defined(WOLFSSL_AES_XTS) + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_XTS && XSTRNCMP(cipher, EVP_AES_128_XTS, EVP_AES_SIZE) == 0) + return AES_128_XTS_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_XTS && XSTRNCMP(cipher, EVP_AES_256_XTS, EVP_AES_SIZE) == 0) + return AES_256_XTS_TYPE; + #endif +#endif /* WOLFSSL_AES_XTS */ +#if defined(WOLFSSL_AES_CFB) + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_CFB1 && XSTRNCMP(cipher, EVP_AES_128_CFB1, EVP_AESCFB_SIZE) == 0) + return AES_128_CFB1_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_CFB1 && XSTRNCMP(cipher, EVP_AES_192_CFB1, EVP_AESCFB_SIZE) == 0) + return AES_192_CFB1_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_CFB1 && XSTRNCMP(cipher, EVP_AES_256_CFB1, EVP_AESCFB_SIZE) == 0) + return AES_256_CFB1_TYPE; + #endif + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_CFB8 && XSTRNCMP(cipher, EVP_AES_128_CFB8, EVP_AESCFB_SIZE) == 0) + return AES_128_CFB8_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_CFB8 && XSTRNCMP(cipher, EVP_AES_192_CFB8, EVP_AESCFB_SIZE) == 0) + return AES_192_CFB8_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_CFB8 && XSTRNCMP(cipher, EVP_AES_256_CFB8, EVP_AESCFB_SIZE) == 0) + return AES_256_CFB8_TYPE; + #endif + #ifdef WOLFSSL_AES_128 + else if (EVP_AES_128_CFB128 && XSTRNCMP(cipher, EVP_AES_128_CFB128, EVP_AESCFB_SIZE) == 0) + return AES_128_CFB128_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (EVP_AES_192_CFB128 && XSTRNCMP(cipher, EVP_AES_192_CFB128, EVP_AESCFB_SIZE) == 0) + return AES_192_CFB128_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (EVP_AES_256_CFB128 && XSTRNCMP(cipher, EVP_AES_256_CFB128, EVP_AESCFB_SIZE) == 0) + return AES_256_CFB128_TYPE; + #endif +#endif /*HAVE_AES_CBC */ +#endif /* !NO_AES */ + else return 0; +} + +int wolfSSL_EVP_CIPHER_block_size(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return BAD_FUNC_ARG; + switch (cipherType(cipher)) { +#if !defined(NO_AES) + #if defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + return AES_BLOCK_SIZE; + #endif + #if defined(HAVE_AESGCM) + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: + return AES_BLOCK_SIZE; + #endif + #if defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + return AES_BLOCK_SIZE; + #endif + #if defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + return AES_BLOCK_SIZE; + #endif +#endif /* NO_AES */ + #ifndef NO_DES3 + case DES_CBC_TYPE: return 8; + case DES_EDE3_CBC_TYPE: return 8; + case DES_ECB_TYPE: return 8; + case DES_EDE3_ECB_TYPE: return 8; + #endif + default: + return 0; + } +} + +unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) +{ + switch (cipherType(cipher)) { +#if !defined(NO_AES) + #if defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + return WOLFSSL_EVP_CIPH_CBC_MODE; + #endif + #if defined(HAVE_AESGCM) + case AES_128_GCM_TYPE: + case AES_192_GCM_TYPE: + case AES_256_GCM_TYPE: + return WOLFSSL_EVP_CIPH_GCM_MODE; + #endif + #if defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + return WOLFSSL_EVP_CIPH_CTR_MODE; + #endif + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + return WOLFSSL_EVP_CIPH_ECB_MODE; +#endif /* NO_ASE */ + #ifndef NO_DES3 + case DES_CBC_TYPE: + case DES_EDE3_CBC_TYPE: + return WOLFSSL_EVP_CIPH_CBC_MODE; + case DES_ECB_TYPE: + case DES_EDE3_ECB_TYPE: + return WOLFSSL_EVP_CIPH_ECB_MODE; + #endif + #ifndef NO_RC4 + case ARC4_TYPE: + return EVP_CIPH_STREAM_CIPHER; + #endif + default: + return 0; + } +} + +unsigned long WOLFSSL_EVP_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; + return WOLFSSL_CIPHER_mode(cipher); +} + +void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags) +{ + if (ctx != NULL) { + ctx->flags |= flags; + } +} + +void wolfSSL_EVP_CIPHER_CTX_clear_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags) +{ + if (ctx != NULL) { + ctx->flags &= ~flags; + } +} + +unsigned long wolfSSL_EVP_CIPHER_flags(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; + return WOLFSSL_CIPHER_mode(cipher); +} + +int wolfSSL_EVP_CIPHER_CTX_set_padding(WOLFSSL_EVP_CIPHER_CTX *ctx, int padding) +{ + if (ctx == NULL) return BAD_FUNC_ARG; + if (padding) { + ctx->flags &= ~WOLFSSL_EVP_CIPH_NO_PADDING; + } + else { + ctx->flags |= WOLFSSL_EVP_CIPH_NO_PADDING; + } + return 1; +} + +int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest) +{ + (void)digest; + /* nothing to do */ + return 0; +} + + +/* Frees the WOLFSSL_EVP_PKEY_CTX passed in. + * + * return WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + if (ctx == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_CTX_free"); + if (ctx->pkey != NULL) + wolfSSL_EVP_PKEY_free(ctx->pkey); + if (ctx->peerKey != NULL) + wolfSSL_EVP_PKEY_free(ctx->peerKey); + XFREE(ctx, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + return WOLFSSL_SUCCESS; +} + + +/* Creates a new WOLFSSL_EVP_PKEY_CTX structure. + * + * pkey key structure to use with new WOLFSSL_EVP_PEKY_CTX + * e engine to use. It should be NULL at this time. + * + * return the new structure on success and NULL if failed. + */ +WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_ENGINE *e) +{ + WOLFSSL_EVP_PKEY_CTX* ctx; + int type = NID_undef; + + if (pkey == NULL) return 0; + if (e != NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_CTX_new"); + + ctx = (WOLFSSL_EVP_PKEY_CTX*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY_CTX), NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (ctx == NULL) return NULL; + XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_PKEY_CTX)); + ctx->pkey = pkey; +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + ctx->padding = RSA_PKCS1_PADDING; +#endif + type = wolfSSL_EVP_PKEY_type(pkey->type); + + if (type != NID_undef) { + if (wc_LockMutex(&pkey->refMutex) != 0) { + WOLFSSL_MSG("Couldn't lock pkey mutex"); + } + pkey->references++; + + wc_UnLockMutex(&pkey->refMutex); + } + return ctx; +} + + +/* Sets the type of RSA padding to use. + * + * ctx structure to set padding in. + * padding RSA padding type + * + * returns WOLFSSL_SUCCESS on success. + */ +int wolfSSL_EVP_PKEY_CTX_set_rsa_padding(WOLFSSL_EVP_PKEY_CTX *ctx, int padding) +{ + if (ctx == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_CTX_set_rsa_padding"); + ctx->padding = padding; + return WOLFSSL_SUCCESS; +} + +/* create a PKEY contxt and return it */ +WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new_id(int id, WOLFSSL_ENGINE *e) +{ + WOLFSSL_EVP_PKEY* pkey; + WOLFSSL_EVP_PKEY_CTX* ctx = NULL; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_CTX_new_id"); + + pkey = wolfSSL_EVP_PKEY_new_ex(NULL); + if (pkey) { + pkey->type = id; + ctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e); + if (ctx == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + } + } + return ctx; +} + +/* Returns WOLFSSL_SUCCESS or error */ +int wolfSSL_EVP_PKEY_CTX_set_rsa_keygen_bits(WOLFSSL_EVP_PKEY_CTX *ctx, int bits) +{ + if (ctx) { + ctx->nbits = bits; + } + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_EVP_PKEY_derive_init(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_derive_init"); + + if (!ctx) { + return WOLFSSL_FAILURE; + } + wolfSSL_EVP_PKEY_free(ctx->peerKey); + ctx->op = EVP_PKEY_OP_DERIVE; + ctx->padding = 0; + ctx->nbits = 0; + return WOLFSSL_SUCCESS; +} + +int wolfSSL_EVP_PKEY_derive_set_peer(WOLFSSL_EVP_PKEY_CTX *ctx, WOLFSSL_EVP_PKEY *peer) +{ + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_derive_set_peer"); + + if (!ctx || ctx->op != EVP_PKEY_OP_DERIVE) { + return WOLFSSL_FAILURE; + } + wolfSSL_EVP_PKEY_free(ctx->peerKey); + ctx->peerKey = peer; + if (!wolfSSL_EVP_PKEY_up_ref(peer)) { + ctx->peerKey = NULL; + return WOLFSSL_FAILURE; + } + return WOLFSSL_SUCCESS; +} + +#if !defined(NO_DH) && defined(HAVE_ECC) +int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) +{ + int len; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_derive"); + + if (!ctx || ctx->op != EVP_PKEY_OP_DERIVE || !ctx->pkey || !ctx->peerKey || !keylen + || ctx->pkey->type != ctx->peerKey->type) { + return WOLFSSL_FAILURE; + } + switch (ctx->pkey->type) { +#ifndef NO_DH + case EVP_PKEY_DH: + /* Use DH */ + if (!ctx->pkey->dh || !ctx->peerKey->dh || !ctx->peerKey->dh->pub_key) { + return WOLFSSL_FAILURE; + } + if ((len = wolfSSL_DH_size(ctx->pkey->dh)) <= 0) { + return WOLFSSL_FAILURE; + } + if (key) { + if (*keylen < (size_t)len) { + return WOLFSSL_FAILURE; + } + if (wolfSSL_DH_compute_key(key, ctx->peerKey->dh->pub_key, + ctx->pkey->dh) != len) { + return WOLFSSL_FAILURE; + } + } + *keylen = (size_t)len; + break; +#endif +#ifdef HAVE_ECC + case EVP_PKEY_EC: + /* Use ECDH */ + if (!ctx->pkey->ecc || !ctx->peerKey->ecc) { + return WOLFSSL_FAILURE; + } + /* set internal key if not done */ + if (!ctx->pkey->ecc->inSet) { + if (SetECKeyInternal(ctx->pkey->ecc) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FAILURE; + } + } + if (!ctx->peerKey->ecc->exSet || !ctx->peerKey->ecc->pub_key->internal) { + if (SetECKeyExternal(ctx->peerKey->ecc) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyExternal failed"); + return WOLFSSL_FAILURE; + } + } + if (!(len = wc_ecc_size((ecc_key*)ctx->pkey->ecc->internal))) { + return WOLFSSL_FAILURE; + } + if (key) { + word32 len32 = (word32)len; + if (*keylen < len32) { + WOLFSSL_MSG("buffer too short"); + return WOLFSSL_FAILURE; + } + if (wc_ecc_shared_secret_ssh((ecc_key*)ctx->pkey->ecc->internal, + (ecc_point*)ctx->peerKey->ecc->pub_key->internal, + key, &len32) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_shared_secret failed"); + return WOLFSSL_FAILURE; + } + len = (int)len32; + } + *keylen = (size_t)len; + break; +#endif + default: + WOLFSSL_MSG("Unknown key type"); + return WOLFSSL_FAILURE; + } + return WOLFSSL_SUCCESS; +} +#endif + +/* Uses the WOLFSSL_EVP_PKEY_CTX to decrypt a buffer. + * + * ctx structure to decrypt with + * out buffer to hold the results + * outlen initially holds size of out buffer and gets set to decrypt result size + * in buffer decrypt + * inlen length of in buffer + * + * returns WOLFSSL_SUCCESS on success. + */ +int wolfSSL_EVP_PKEY_decrypt(WOLFSSL_EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + int len = 0; + + if (ctx == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_decrypt"); + + (void)out; + (void)outlen; + (void)in; + (void)inlen; + (void)len; + + switch (ctx->pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: + len = wolfSSL_RSA_private_decrypt((int)inlen, (unsigned char*)in, out, + ctx->pkey->rsa, ctx->padding); + if (len < 0) break; + else { + *outlen = len; + return WOLFSSL_SUCCESS; + } +#endif /* NO_RSA */ + + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Initialize a WOLFSSL_EVP_PKEY_CTX structure for decryption + * + * ctx WOLFSSL_EVP_PKEY_CTX structure to use with decryption + * + * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_PKEY_decrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_PKEY_decrypt_init"); + switch (ctx->pkey->type) { + case EVP_PKEY_RSA: + ctx->op = EVP_PKEY_OP_DECRYPT; + return WOLFSSL_SUCCESS; + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Use a WOLFSSL_EVP_PKEY_CTX structure to encrypt data + * + * ctx WOLFSSL_EVP_PKEY_CTX structure to use with encryption + * out buffer to hold encrypted data + * outlen length of out buffer + * in data to be encrypted + * inlen length of in buffer + * + * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_PKEY_encrypt(WOLFSSL_EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + int len = 0; + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_PKEY_encrypt"); + if (ctx->op != EVP_PKEY_OP_ENCRYPT) return WOLFSSL_FAILURE; + + (void)out; + (void)outlen; + (void)in; + (void)inlen; + (void)len; + switch (ctx->pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: + len = wolfSSL_RSA_public_encrypt((int)inlen, (unsigned char *)in, out, + ctx->pkey->rsa, ctx->padding); + if (len < 0) + break; + else { + *outlen = len; + return WOLFSSL_SUCCESS; + } +#endif /* NO_RSA */ + + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Initialize a WOLFSSL_EVP_PKEY_CTX structure to encrypt data + * + * ctx WOLFSSL_EVP_PKEY_CTX structure to use with encryption + * + * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_PKEY_encrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_PKEY_encrypt_init"); + + switch (ctx->pkey->type) { + case EVP_PKEY_RSA: + ctx->op = EVP_PKEY_OP_ENCRYPT; + return WOLFSSL_SUCCESS; + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} +/****************************************************************************** +* wolfSSL_EVP_PKEY_sign_init - initializes a public key algorithm context for +* a signing operation. +* +* RETURNS: +* returns WOLFSSL_SUCCESS on success, otherwise returns -2 +*/ +WOLFSSL_API int wolfSSL_EVP_PKEY_sign_init(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + int ret = -2; + + WOLFSSL_MSG("wolfSSL_EVP_PKEY_sign_init"); + if (!ctx || !ctx->pkey) + return ret; + + switch (ctx->pkey->type) { + case EVP_PKEY_RSA: + ctx->op = EVP_PKEY_OP_SIGN; + ret = WOLFSSL_SUCCESS; + break; + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + ret = -2; + } + return ret; +} +/****************************************************************************** +* wolfSSL_EVP_PKEY_sign - performs a public key signing operation using ctx +* The data to be signed should be hashed since the function does not hash the data. +* +* RETURNS: +* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE +*/ + +WOLFSSL_API int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *sig, + size_t *siglen, const unsigned char *tbs, size_t tbslen) +{ + int len = 0; + + WOLFSSL_MSG("wolfSSL_EVP_PKEY_sign"); + + if (!ctx || ctx->op != EVP_PKEY_OP_SIGN || !ctx->pkey) + return WOLFSSL_FAILURE; + + (void)sig; + (void)siglen; + (void)tbs; + (void)tbslen; + (void)len; + + switch (ctx->pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: + len = wolfSSL_RSA_private_encrypt((int)tbslen, (unsigned char*)tbs, sig, + ctx->pkey->rsa, ctx->padding); + if (len < 0) + break; + else { + *siglen = len; + return WOLFSSL_SUCCESS; + } +#endif /* NO_RSA */ + + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + +/* Get the size in bits for WOLFSSL_EVP_PKEY key + * + * pkey WOLFSSL_EVP_PKEY structure to get key size of + * + * returns the size in bits of key on success + */ +int wolfSSL_EVP_PKEY_bits(const WOLFSSL_EVP_PKEY *pkey) +{ + int bytes; + + if (pkey == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_bits"); + if ((bytes = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey)) ==0) return 0; + return bytes*8; +} + + +int wolfSSL_EVP_PKEY_keygen_init(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + (void)ctx; + return WOLFSSL_SUCCESS; +} + +int wolfSSL_EVP_PKEY_keygen(WOLFSSL_EVP_PKEY_CTX *ctx, + WOLFSSL_EVP_PKEY **ppkey) +{ + int ret = WOLFSSL_FAILURE; + int ownPkey = 0; + WOLFSSL_EVP_PKEY* pkey; + + if (ctx == NULL || ppkey == NULL) { + return BAD_FUNC_ARG; + } + + pkey = *ppkey; + if (pkey == NULL) { + ownPkey = 1; + pkey = wolfSSL_EVP_PKEY_new(); + + if (pkey == NULL) + return ret; + } + + switch (pkey->type) { +#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \ + !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: + pkey->rsa = wolfSSL_RSA_generate_key(ctx->nbits, WC_RSA_EXPONENT, + NULL, NULL); + if (pkey->rsa) { + pkey->ownRsa = 1; + pkey->pkey_sz = wolfSSL_i2d_RSAPrivateKey(pkey->rsa, + (unsigned char**)&pkey->pkey.ptr); + ret = WOLFSSL_SUCCESS; + } + break; +#endif +#ifdef HAVE_ECC + case EVP_PKEY_EC: + pkey->ecc = wolfSSL_EC_KEY_new(); + if (pkey->ecc) { + ret = wolfSSL_EC_KEY_generate_key(pkey->ecc); + if (ret == WOLFSSL_SUCCESS) { + pkey->ownEcc = 1; + } + } +#endif + default: + break; + } + + if (ret != WOLFSSL_SUCCESS && ownPkey) { + wolfSSL_EVP_PKEY_free(pkey); + pkey = NULL; + } + + *ppkey = pkey; + + return ret; +} + +/* Get the size in bytes for WOLFSSL_EVP_PKEY key + * + * pkey WOLFSSL_EVP_PKEY structure to get key size of + * + * returns the size of a key on success which is the maximum size of a + * signature + */ +int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey) +{ + if (pkey == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_size"); + + switch (pkey->type) { +#ifndef NO_RSA + case EVP_PKEY_RSA: + return (int)wolfSSL_RSA_size((const WOLFSSL_RSA*)(pkey->rsa)); +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC + case EVP_PKEY_EC: + if (pkey->ecc == NULL || pkey->ecc->internal == NULL) { + WOLFSSL_MSG("No ECC key has been set"); + break; + } + return wc_ecc_size((ecc_key*)(pkey->ecc->internal)); +#endif /* HAVE_ECC */ + + default: + break; + } + return 0; +} + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API int wolfSSL_EVP_PKEY_missing_parameters(WOLFSSL_EVP_PKEY *pkey) +{ + (void)pkey; + /* not using missing params callback and returning zero to indicate success */ + return 0; +} +#endif + +WOLFSSL_API int wolfSSL_EVP_PKEY_cmp(const WOLFSSL_EVP_PKEY *a, const WOLFSSL_EVP_PKEY *b) +{ + int ret = -1; /* failure */ + int a_sz = 0, b_sz = 0; + + if (a == NULL || b == NULL) + return ret; + + /* check its the same type of key */ + if (a->type != b->type) + return ret; + + /* get size based on key type */ + switch (a->type) { +#ifndef NO_RSA + case EVP_PKEY_RSA: + a_sz = (int)wolfSSL_RSA_size((const WOLFSSL_RSA*)(a->rsa)); + b_sz = (int)wolfSSL_RSA_size((const WOLFSSL_RSA*)(b->rsa)); + break; +#endif /* !NO_RSA */ +#ifdef HAVE_ECC + case EVP_PKEY_EC: + if (a->ecc == NULL || a->ecc->internal == NULL || + b->ecc == NULL || b->ecc->internal == NULL) { + return ret; + } + a_sz = wc_ecc_size((ecc_key*)(a->ecc->internal)); + b_sz = wc_ecc_size((ecc_key*)(b->ecc->internal)); + break; +#endif /* HAVE_ECC */ + default: + break; + } /* switch (a->type) */ + + /* check size */ + if (a_sz <= 0 || b_sz <= 0 || a_sz != b_sz) { + return ret; + } + + /* check public key size */ + if (a->pkey_sz > 0 && b->pkey_sz > 0 && a->pkey_sz != b->pkey_sz) { + return ret; + } + + /* check public key */ + if (a->pkey.ptr && b->pkey.ptr) { + if (XMEMCMP(a->pkey.ptr, b->pkey.ptr, a->pkey_sz) != 0) { + return ret; + } + } + ret = 0; /* success */ + + return ret; +} + +/* Initialize structure for signing + * + * ctx WOLFSSL_EVP_MD_CTX structure to initialize + * type is the type of message digest to use + * + * returns WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_SignInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_SignInit"); + return wolfSSL_EVP_DigestInit(ctx,type); +} + +WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* type, + WOLFSSL_ENGINE *impl) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_SignInit"); + return wolfSSL_EVP_DigestInit_ex(ctx,type,impl); +} + + +/* Update structure with data for signing + * + * ctx WOLFSSL_EVP_MD_CTX structure to update + * data buffer holding data to update with for sign + * len length of data buffer + * + * returns WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_SignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len) +{ + if (ctx == NULL) return 0; + WOLFSSL_ENTER("EVP_SignUpdate("); + return wolfSSL_EVP_DigestUpdate(ctx, data, len); +} + +static const struct s_ent { + const int macType; + const int nid; + const char *name; +} md_tbl[] = { +#ifndef NO_MD4 + {WC_HASH_TYPE_MD4, NID_md4, "MD4"}, +#endif /* NO_MD4 */ + +#ifndef NO_MD5 + {WC_HASH_TYPE_MD5, NID_md5, "MD5"}, +#endif /* NO_MD5 */ + +#ifndef NO_SHA + {WC_HASH_TYPE_SHA, NID_sha1, "SHA"}, +#endif /* NO_SHA */ + +#ifdef WOLFSSL_SHA224 + {WC_HASH_TYPE_SHA224, NID_sha224, "SHA224"}, +#endif /* WOLFSSL_SHA224 */ +#ifndef NO_SHA256 + {WC_HASH_TYPE_SHA256, NID_sha256, "SHA256"}, +#endif + +#ifdef WOLFSSL_SHA384 + {WC_HASH_TYPE_SHA384, NID_sha384, "SHA384"}, +#endif /* WOLFSSL_SHA384 */ +#ifdef WOLFSSL_SHA512 + {WC_HASH_TYPE_SHA512, NID_sha512, "SHA512"}, +#endif /* WOLFSSL_SHA512 */ +#ifndef WOLFSSL_NOSHA3_224 + {WC_HASH_TYPE_SHA3_224, NID_sha3_224, "SHA3_224"}, +#endif +#ifndef WOLFSSL_NOSHA3_256 + {WC_HASH_TYPE_SHA3_256, NID_sha3_256, "SHA3_256"}, +#endif + {WC_HASH_TYPE_SHA3_384, NID_sha3_384, "SHA3_384"}, +#ifndef WOLFSSL_NOSHA3_512 + {WC_HASH_TYPE_SHA3_512, NID_sha3_512, "SHA3_512"}, +#endif + {0, 0, NULL} +}; + +static int wolfSSL_EVP_md2macType(const WOLFSSL_EVP_MD *md) +{ + const struct s_ent *ent ; + + if (md != NULL) { + for( ent = md_tbl; ent->name != NULL; ent++) { + if(XSTRNCMP((const char *)md, ent->name, XSTRLEN(ent->name)+1) == 0) { + return ent->macType; + } + } + } + return WC_HASH_TYPE_NONE; +} + +/* Finalize structure for signing + * + * ctx WOLFSSL_EVP_MD_CTX structure to finalize + * sigret buffer to hold resulting signature + * siglen length of sigret buffer + * pkey key to sign with + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_SignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sigret, + unsigned int *siglen, WOLFSSL_EVP_PKEY *pkey) +{ + unsigned int mdsize; + unsigned char md[WC_MAX_DIGEST_SIZE]; + int ret; + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_SignFinal"); + + ret = wolfSSL_EVP_DigestFinal(ctx, md, &mdsize); + if (ret <= 0) return ret; + + (void)sigret; + (void)siglen; + + switch (pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx)); + if (nid < 0) break; + return wolfSSL_RSA_sign(nid, md, mdsize, sigret, + siglen, pkey->rsa); + } +#endif /* NO_RSA */ + + case EVP_PKEY_DSA: + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Initialize structure for verifying signature + * + * ctx WOLFSSL_EVP_MD_CTX structure to initialize + * type is the type of message digest to use + * + * returns WOLFSSL_SUCCESS on success + */ +int wolfSSL_EVP_VerifyInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_VerifyInit"); + return wolfSSL_EVP_DigestInit(ctx,type); +} + + +/* Update structure for verifying signature + * + * ctx WOLFSSL_EVP_MD_CTX structure to update + * data buffer holding data to update with for verify + * len length of data buffer + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_VerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_VerifyUpdate"); + return wolfSSL_EVP_DigestUpdate(ctx, data, len); +} + + +/* Finalize structure for verifying signature + * + * ctx WOLFSSL_EVP_MD_CTX structure to finalize + * sig buffer holding signature + * siglen length of sig buffer + * pkey key to verify with + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_VerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, + unsigned char*sig, unsigned int siglen, WOLFSSL_EVP_PKEY *pkey) +{ + int ret; + unsigned char md[WC_MAX_DIGEST_SIZE]; + unsigned int mdsize; + + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_VerifyFinal"); + ret = wolfSSL_EVP_DigestFinal(ctx, md, &mdsize); + if (ret <= 0) return ret; + + (void)sig; + (void)siglen; + + switch (pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx)); + if (nid < 0) break; + return wolfSSL_RSA_verify(nid, md, mdsize, sig, + (unsigned int)siglen, pkey->rsa); + } +#endif /* NO_RSA */ + + case EVP_PKEY_DSA: + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + +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_EVP_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; +} + + +/* Initialize an EVP_DigestSign/Verify operation. + * Initialize a digest for RSA and ECC keys, or HMAC for HMAC key. + */ +static int wolfSSL_evp_digest_pk_init(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey) +{ + if (pkey->type == EVP_PKEY_HMAC) { + int hashType; + const unsigned char* key; + size_t keySz; + + 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 WOLFSSL_FAILURE; + + if (wc_HmacSetKey(&ctx->hash.hmac, hashType, key, (word32)keySz) != 0) + return WOLFSSL_FAILURE; + + ctx->macType = NID_hmac; + } + else { + int ret; + + if (ctx->pctx == NULL) { + ctx->pctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e); + if (ctx->pctx == NULL) + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_EVP_DigestInit(ctx, type); + if (ret == WOLFSSL_SUCCESS && pctx != NULL) + *pctx = ctx->pctx; + return ret; + } + + return WOLFSSL_SUCCESS; +} + +/* Update an EVP_DigestSign/Verify operation. + * Update a digest for RSA and ECC keys, or HMAC for HMAC key. + */ +static int wolfssl_evp_digest_pk_update(WOLFSSL_EVP_MD_CTX *ctx, + const void *d, unsigned int cnt) +{ + if (ctx->pctx == NULL) { + if (ctx->macType != NID_hmac) + return WOLFSSL_FAILURE; + + if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, cnt) != 0) + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; + } + else + return wolfSSL_EVP_DigestUpdate(ctx, d, cnt); +} + +/* Finalize an EVP_DigestSign/Verify operation - common part only. + * Finalize a digest for RSA and ECC keys, or HMAC for HMAC key. + * Copies the digest so that you can keep updating. + */ +static int wolfssl_evp_digest_pk_final(WOLFSSL_EVP_MD_CTX *ctx, + unsigned char *md, unsigned int* mdlen) +{ + int ret; + + if (ctx->pctx == NULL) { + Hmac hmacCopy; + + if (ctx->macType != NID_hmac) + return WOLFSSL_FAILURE; + + if (wolfSSL_HmacCopy(&hmacCopy, &ctx->hash.hmac) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; + ret = wc_HmacFinal(&hmacCopy, md) == 0; + wc_HmacFree(&hmacCopy); + return ret; + } + else { + WOLFSSL_EVP_MD_CTX ctxCopy; + + if (wolfSSL_EVP_MD_CTX_copy_ex(&ctxCopy, ctx) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; + + ret = wolfSSL_EVP_DigestFinal(&ctxCopy, md, mdlen); + wolfSSL_EVP_MD_CTX_cleanup(&ctxCopy); + return ret; + } +} + +/* Get the length of the mac based on the digest algorithm. */ +static int wolfssl_mac_len(unsigned char macType) +{ + int hashLen; + + switch (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_SHA384 + case WC_SHA384: + hashLen = WC_SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + 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: + hashLen = 0; + } + + return hashLen; +} + +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_ENTER("EVP_DigestSignInit"); + + if (ctx == NULL || type == NULL || pkey == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_evp_digest_pk_init(ctx, pctx, type, e, pkey); +} + + +int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *d, + unsigned int cnt) +{ + WOLFSSL_ENTER("EVP_DigestSignUpdate"); + + if (ctx == NULL || d == NULL) + return BAD_FUNC_ARG; + + return wolfssl_evp_digest_pk_update(ctx, d, cnt); +} + +int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sig, + size_t *siglen) +{ + unsigned char digest[WC_MAX_DIGEST_SIZE]; + unsigned int hashLen; + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("EVP_DigestSignFinal"); + + if (ctx == NULL || siglen == NULL) + return WOLFSSL_FAILURE; + + /* Return the maximum size of the signaure when sig is NULL. */ + if (ctx->pctx == NULL) { + if (ctx->macType != NID_hmac) + return WOLFSSL_FAILURE; + + hashLen = wolfssl_mac_len(ctx->hash.hmac.macType); + + if (sig == NULL) { + *siglen = hashLen; + return WOLFSSL_SUCCESS; + } + } +#ifndef NO_RSA + else if (ctx->pctx->pkey->type == EVP_PKEY_RSA) { + if (sig == NULL) { + *siglen = wolfSSL_RSA_size(ctx->pctx->pkey->rsa); + return WOLFSSL_SUCCESS; + } + } +#endif /* !NO_RSA */ +#ifdef HAVE_ECC + else if (ctx->pctx->pkey->type == EVP_PKEY_EC) { + if (sig == NULL) { + /* SEQ + INT + INT */ + *siglen = ecc_sets[ctx->pctx->pkey->ecc->group->curve_idx].size * 2 + + 8; + return WOLFSSL_SUCCESS; + } + } +#endif + + if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0) + return WOLFSSL_FAILURE; + + if (ctx->pctx == NULL) { + /* Copy the HMAC result as signature. */ + if ((unsigned int)(*siglen) > hashLen) + *siglen = hashLen; + /* May be a truncated signature. */ + + XMEMCPY(sig, digest, *siglen); + ret = WOLFSSL_SUCCESS; + } + else { + /* Sign the digest. */ + switch (ctx->pctx->pkey->type) { + #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + unsigned int sigSz; + int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx)); + if (nid < 0) + break; + ret = wolfSSL_RSA_sign(nid, digest, hashLen, sig, &sigSz, + ctx->pctx->pkey->rsa); + if (ret >= 0) + *siglen = sigSz; + break; + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + case EVP_PKEY_EC: { + WOLFSSL_ECDSA_SIG *ecdsaSig; + ecdsaSig = wolfSSL_ECDSA_do_sign(digest, hashLen, + ctx->pctx->pkey->ecc); + if (ecdsaSig == NULL) + break; + *siglen = wolfSSL_i2d_ECDSA_SIG(ecdsaSig, &sig); + wolfSSL_ECDSA_SIG_free(ecdsaSig); + ret = WOLFSSL_SUCCESS; + break; + } + #endif + default: + break; + } + } + + ForceZero(digest, sizeof(digest)); + return ret; +} +int wolfSSL_EVP_DigestVerifyInit(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey) +{ + WOLFSSL_ENTER("EVP_DigestVerifyInit"); + + if (ctx == NULL || type == NULL || pkey == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_evp_digest_pk_init(ctx, pctx, type, e, pkey); +} + + +int wolfSSL_EVP_DigestVerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *d, + size_t cnt) +{ + WOLFSSL_ENTER("EVP_DigestVerifyUpdate"); + + if (ctx == NULL || d == NULL) + return BAD_FUNC_ARG; + + return wolfssl_evp_digest_pk_update(ctx, d, (unsigned int)cnt); +} + + +int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, + const unsigned char *sig, size_t siglen) +{ + unsigned char digest[WC_MAX_DIGEST_SIZE]; + unsigned int hashLen; + + WOLFSSL_ENTER("EVP_DigestVerifyFinal"); + + if (ctx == NULL || sig == NULL) + return WOLFSSL_FAILURE; + + if (ctx->pctx == NULL) { + if (ctx->macType != NID_hmac) + return WOLFSSL_FAILURE; + + hashLen = wolfssl_mac_len(ctx->hash.hmac.macType); + + if (siglen > hashLen) + return WOLFSSL_FAILURE; + /* May be a truncated signature. */ + } + + if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0) + return WOLFSSL_FAILURE; + + if (ctx->pctx == NULL) { + /* Check HMAC result matches the signature. */ + if (XMEMCMP(sig, digest, siglen) == 0) + return WOLFSSL_SUCCESS; + return WOLFSSL_FAILURE; + } + else { + /* Verify the signature with the digest. */ + switch (ctx->pctx->pkey->type) { + #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + int nid = wolfSSL_EVP_MD_type(wolfSSL_EVP_MD_CTX_md(ctx)); + if (nid < 0) + return WOLFSSL_FAILURE; + return wolfSSL_RSA_verify(nid, digest, hashLen, sig, + (unsigned int)siglen, + ctx->pctx->pkey->rsa); + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + case EVP_PKEY_EC: { + int ret; + WOLFSSL_ECDSA_SIG *ecdsaSig; + ecdsaSig = wolfSSL_d2i_ECDSA_SIG(NULL, &sig, (long)siglen); + if (ecdsaSig == NULL) + return WOLFSSL_FAILURE; + ret = wolfSSL_ECDSA_do_verify(digest, hashLen, ecdsaSig, + ctx->pctx->pkey->ecc); + wolfSSL_ECDSA_SIG_free(ecdsaSig); + return ret; + } + #endif + default: + break; + } + } + + return WOLFSSL_FAILURE; +} + + +#ifdef WOLFSSL_APACHE_HTTPD +#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32) + #include +#endif + +#ifndef XGETPASSWD + static int XGETPASSWD(char* buf, int bufSz) { + int ret = WOLFSSL_SUCCESS; + + /* turn off echo for passwords */ + #ifdef USE_WINDOWS_API + DWORD originalTerm; + DWORD newTerm; + CONSOLE_SCREEN_BUFFER_INFO screenOrig; + HANDLE stdinHandle = GetStdHandle(STD_INPUT_HANDLE); + if (GetConsoleMode(stdinHandle, &originalTerm) == 0) { + WOLFSSL_MSG("Couldn't get the original terminal settings"); + return WOLFSSL_FAILURE; + } + newTerm = originalTerm; + newTerm &= ~ENABLE_ECHO_INPUT; + if (SetConsoleMode(stdinHandle, newTerm) == 0) { + WOLFSSL_MSG("Couldn't turn off echo"); + return WOLFSSL_FAILURE; + } + #else + struct termios originalTerm; + struct termios newTerm; + if (tcgetattr(STDIN_FILENO, &originalTerm) != 0) { + WOLFSSL_MSG("Couldn't get the original terminal settings"); + return WOLFSSL_FAILURE; + } + XMEMCPY(&newTerm, &originalTerm, sizeof(struct termios)); + + newTerm.c_lflag &= ~ECHO; + newTerm.c_lflag |= (ICANON | ECHONL); + if (tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) != 0) { + WOLFSSL_MSG("Couldn't turn off echo"); + return WOLFSSL_FAILURE; + } + #endif + + if (XFGETS(buf, bufSz, stdin) == NULL) { + ret = WOLFSSL_FAILURE; + } + + /* restore default echo */ + #ifdef USE_WINDOWS_API + if (SetConsoleMode(stdinHandle, originalTerm) == 0) { + WOLFSSL_MSG("Couldn't restore the terminal settings"); + return WOLFSSL_FAILURE; + } + #else + if (tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm) != 0) { + WOLFSSL_MSG("Couldn't restore the terminal settings"); + return WOLFSSL_FAILURE; + } + #endif + return ret; + } +#endif + +/* returns 0 on success and -2 or -1 on failure */ +int wolfSSL_EVP_read_pw_string(char* buf, int bufSz, const char* banner, int v) +{ + printf("%s", banner); + if (XGETPASSWD(buf, bufSz) == WOLFSSL_FAILURE) { + return -1; + } + (void)v; /* fgets always sanity checks size of input vs buffer */ + return 0; +} +#endif /* WOLFSSL_APACHE_HTTPD */ + +#if !defined(NO_PWDBASED) && !defined(NO_SHA) +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 WOLFSSL_SUCCESS; + else + return WOLFSSL_FAILURE; +} +#endif /* !NO_PWDBASED !NO_SHA*/ + +#if !defined(NO_PWDBASED) +WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen, + const unsigned char *salt, + int saltlen, int iter, + const WOLFSSL_EVP_MD *digest, + 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, wolfSSL_EVP_md2macType(digest)); + if (ret == 0) + return WOLFSSL_SUCCESS; + else + return WOLFSSL_FAILURE; +} +#endif /* !NO_PWDBASED */ + +static const struct cipher{ + unsigned char type; + const char *name; + int nid; +} cipher_tbl[] = { + +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + {AES_128_CBC_TYPE, "AES-128-CBC", NID_aes_128_cbc}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_CBC_TYPE, "AES-192-CBC", NID_aes_192_cbc}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_CBC_TYPE, "AES-256-CBC", NID_aes_256_cbc}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_CFB1_TYPE, "AES-128-CFB1", NID_aes_128_cfb1}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_CFB1_TYPE, "AES-192-CFB1", NID_aes_192_cfb1}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_CFB1_TYPE, "AES-256-CFB1", NID_aes_256_cfb1}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_CFB8_TYPE, "AES-128-CFB8", NID_aes_128_cfb8}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_CFB8_TYPE, "AES-192-CFB8", NID_aes_192_cfb8}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_CFB8_TYPE, "AES-256-CFB8", NID_aes_256_cfb8}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_CFB128_TYPE, "AES-128-CFB128", NID_aes_128_cfb128}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_CFB128_TYPE, "AES-192-CFB128", NID_aes_192_cfb128}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_CFB128_TYPE, "AES-256-CFB128", NID_aes_256_cfb128}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_OFB_TYPE, "AES-128-OFB", NID_aes_128_ofb}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_OFB_TYPE, "AES-192-OFB", NID_aes_192_ofb}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_OFB_TYPE, "AES-256-OFB", NID_aes_256_ofb}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_XTS_TYPE, "AES-128-XTS", NID_aes_128_xts}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_XTS_TYPE, "AES-256-XTS", NID_aes_256_xts}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_GCM_TYPE, "AES-128-GCM", NID_aes_128_gcm}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_GCM_TYPE, "AES-192-GCM", NID_aes_192_gcm}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_GCM_TYPE, "AES-256-GCM", NID_aes_256_gcm}, + #endif + #ifdef WOLFSSL_AES_128 + {AES_128_CTR_TYPE, "AES-128-CTR", NID_aes_128_ctr}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_CTR_TYPE, "AES-192-CTR", NID_aes_192_ctr}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_CTR_TYPE, "AES-256-CTR", NID_aes_256_ctr}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_ECB_TYPE, "AES-128-ECB", NID_aes_128_ecb}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_ECB_TYPE, "AES-192-ECB", NID_aes_192_ecb}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_ECB_TYPE, "AES-256-ECB", NID_aes_256_ecb}, + #endif + +#endif + +#ifndef NO_DES3 + {DES_CBC_TYPE, "DES-CBC", NID_des_cbc}, + {DES_ECB_TYPE, "DES-ECB", NID_des_ecb}, + + {DES_EDE3_CBC_TYPE, "DES-EDE3-CBC", NID_des_ede3_cbc}, + {DES_EDE3_ECB_TYPE, "DES-EDE3-ECB", NID_des_ede3_ecb}, +#endif + +#ifndef NO_RC4 + {ARC4_TYPE, "ARC4", NID_undef}, +#endif + +#ifdef HAVE_IDEA + {IDEA_CBC_TYPE, "IDEA-CBC", NID_idea_cbc}, +#endif + { 0, NULL, 0} +}; + +/* returns cipher using provided ctx type */ +const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_CIPHER_CTX_cipher( + const WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + const struct cipher* c; + + if (!ctx || !ctx->cipherType) { + return NULL; + } + + for (c = cipher_tbl; c->type != 0; c++) { + if (ctx->cipherType == c->type) { + return wolfSSL_EVP_get_cipherbyname(c->name); + } + } + + return NULL; +} + +int wolfSSL_EVP_CIPHER_nid(const WOLFSSL_EVP_CIPHER *cipher) +{ + const struct cipher* c; + + if (!cipher) { + return 0; + } + + for (c = cipher_tbl; c->type != 0; c++) { + if (XSTRNCMP(cipher, c->name, XSTRLEN(c->name)+1) == 0) { + return c->nid; + } + } + + return 0; +} + +const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name) +{ + + static const struct alias { + const char *name; + const char *alias; + } alias_tbl[] = + { +#ifndef NO_DES3 + {"DES-CBC", "DES"}, + {"DES-CBC", "des"}, + {"DES-ECB", "DES-ECB"}, + {"DES-ECB", "des-ecb"}, + {"DES-EDE3-CBC", "DES3"}, + {"DES-EDE3-CBC", "des3"}, + {"DES-EDE3-ECB", "DES-EDE3"}, + {"DES-EDE3-ECB", "des-ede3"}, + {"DES-EDE3-ECB", "des-ede3-ecb"}, +#endif +#ifdef HAVE_IDEA + {"IDEA-CBC", "IDEA"}, + {"IDEA-CBC", "idea"}, +#endif +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + {"AES-128-CBC", "AES128-CBC"}, + {"AES-128-CBC", "aes128-cbc"}, + #endif + #ifdef WOLFSSL_AES_192 + {"AES-192-CBC", "AES192-CBC"}, + {"AES-192-CBC", "aes192-cbc"}, + #endif + #ifdef WOLFSSL_AES_256 + {"AES-256-CBC", "AES256-CBC"}, + {"AES-256-CBC", "aes256-cbc"}, + #endif + #endif + #ifdef WOLFSSL_AES_128 + {"AES-128-ECB", "AES128-ECB"}, + {"AES-128-ECB", "aes128-ecb"}, + #endif + #ifdef WOLFSSL_AES_192 + {"AES-192-ECB", "AES192-ECB"}, + {"AES-192-ECB", "aes192-ecb"}, + #endif + #ifdef WOLFSSL_AES_256 + {"AES-256-ECB", "AES256-ECB"}, + #endif + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + {"AES-128-GCM", "aes-128-gcm"}, + {"AES-128-GCM", "id-aes128-GCM"}, + #endif + #ifdef WOLFSSL_AES_192 + {"AES-192-GCM", "aes-192-gcm"}, + {"AES-192-GCM", "id-aes192-GCM"}, + #endif + #ifdef WOLFSSL_AES_256 + {"AES-256-GCM", "aes-256-gcm"}, + {"AES-256-GCM", "id-aes256-GCM"}, + #endif + #endif +#endif +#ifndef NO_RC4 + {"ARC4", "RC4"}, +#endif + { NULL, NULL} + }; + + const struct cipher *ent; + const struct alias *al; + + WOLFSSL_ENTER("EVP_get_cipherbyname"); + + for( al = alias_tbl; al->name != NULL; al++) + if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) { + name = al->name; + break; + } + + for( ent = cipher_tbl; ent->name != NULL; ent++) + if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) { + return (WOLFSSL_EVP_CIPHER *)ent->name; + } + + return NULL; +} + +/* + * return an EVP_CIPHER structure when cipher NID is passed. + * + * id cipher NID + * + * return WOLFSSL_EVP_CIPHER +*/ +const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbynid(int id) +{ + WOLFSSL_ENTER("EVP_get_cipherbynid"); + + switch(id) { + +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + case NID_aes_128_cbc: + return wolfSSL_EVP_aes_128_cbc(); + #endif + #ifdef WOLFSSL_AES_192 + case NID_aes_192_cbc: + return wolfSSL_EVP_aes_192_cbc(); + #endif + #ifdef WOLFSSL_AES_256 + case NID_aes_256_cbc: + return wolfSSL_EVP_aes_256_cbc(); + #endif + #endif + #ifdef WOLFSSL_AES_COUNTER + #ifdef WOLFSSL_AES_128 + case NID_aes_128_ctr: + return wolfSSL_EVP_aes_128_ctr(); + #endif + #ifdef WOLFSSL_AES_192 + case NID_aes_192_ctr: + return wolfSSL_EVP_aes_192_ctr(); + #endif + #ifdef WOLFSSL_AES_256 + case NID_aes_256_ctr: + return wolfSSL_EVP_aes_256_ctr(); + #endif + #endif /* WOLFSSL_AES_COUNTER */ + #ifdef HAVE_AES_ECB + #ifdef WOLFSSL_AES_128 + case NID_aes_128_ecb: + return wolfSSL_EVP_aes_128_ecb(); + #endif + #ifdef WOLFSSL_AES_192 + case NID_aes_192_ecb: + return wolfSSL_EVP_aes_192_ecb(); + #endif + #ifdef WOLFSSL_AES_256 + case NID_aes_256_ecb: + return wolfSSL_EVP_aes_256_ecb(); + #endif + #endif /* HAVE_AES_ECB */ + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case NID_aes_128_gcm: + return wolfSSL_EVP_aes_128_gcm(); + #endif + #ifdef WOLFSSL_AES_192 + case NID_aes_192_gcm: + return wolfSSL_EVP_aes_192_gcm(); + #endif + #ifdef WOLFSSL_AES_256 + case NID_aes_256_gcm: + return wolfSSL_EVP_aes_256_gcm(); + #endif + #endif +#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 + + default: + WOLFSSL_MSG("Bad cipher id value"); + } + + return NULL; +} + +void wolfSSL_EVP_init(void) +{ +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + EVP_AES_128_CBC = (char *)EVP_get_cipherbyname("AES-128-CBC"); + #endif + #ifdef WOLFSSL_AES_192 + EVP_AES_192_CBC = (char *)EVP_get_cipherbyname("AES-192-CBC"); + #endif + #ifdef WOLFSSL_AES_256 + EVP_AES_256_CBC = (char *)EVP_get_cipherbyname("AES-256-CBC"); + #endif + #endif /* HAVE_AES_CBC */ + + #ifdef WOLFSSL_AES_CFB + #ifdef WOLFSSL_AES_128 + EVP_AES_128_CFB1 = (char *)EVP_get_cipherbyname("AES-128-CFB1"); + #endif + + #ifdef WOLFSSL_AES_192 + EVP_AES_192_CFB1 = (char *)EVP_get_cipherbyname("AES-192-CFB1"); + #endif + + #ifdef WOLFSSL_AES_256 + EVP_AES_256_CFB1 = (char *)EVP_get_cipherbyname("AES-256-CFB1"); + #endif + + #ifdef WOLFSSL_AES_128 + EVP_AES_128_CFB8 = (char *)EVP_get_cipherbyname("AES-128-CFB8"); + #endif + + #ifdef WOLFSSL_AES_192 + EVP_AES_192_CFB8 = (char *)EVP_get_cipherbyname("AES-192-CFB8"); + #endif + + #ifdef WOLFSSL_AES_256 + EVP_AES_256_CFB8 = (char *)EVP_get_cipherbyname("AES-256-CFB8"); + #endif + + #ifdef WOLFSSL_AES_128 + EVP_AES_128_CFB128 = (char *)EVP_get_cipherbyname("AES-128-CFB128"); + #endif + + #ifdef WOLFSSL_AES_192 + EVP_AES_192_CFB128 = (char *)EVP_get_cipherbyname("AES-192-CFB128"); + #endif + + #ifdef WOLFSSL_AES_256 + EVP_AES_256_CFB128 = (char *)EVP_get_cipherbyname("AES-256-CFB128"); + #endif + #endif /* WOLFSSL_AES_CFB */ + + #ifdef WOLFSSL_AES_OFB + #ifdef WOLFSSL_AES_128 + EVP_AES_128_OFB = (char *)EVP_get_cipherbyname("AES-128-OFB"); + #endif + + #ifdef WOLFSSL_AES_192 + EVP_AES_192_OFB = (char *)EVP_get_cipherbyname("AES-192-OFB"); + #endif + + #ifdef WOLFSSL_AES_256 + EVP_AES_256_OFB = (char *)EVP_get_cipherbyname("AES-256-OFB"); + #endif + #endif /* WOLFSSL_AES_OFB */ + + #ifdef WOLFSSL_AES_XTS + #ifdef WOLFSSL_AES_128 + EVP_AES_128_XTS = (char *)EVP_get_cipherbyname("AES-128-XTS"); + #endif + + #ifdef WOLFSSL_AES_256 + EVP_AES_256_XTS = (char *)EVP_get_cipherbyname("AES-256-XTS"); + #endif + #endif /* WOLFSSL_AES_XTS */ + + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + EVP_AES_128_GCM = (char *)EVP_get_cipherbyname("AES-128-GCM"); + #endif + #ifdef WOLFSSL_AES_192 + EVP_AES_192_GCM = (char *)EVP_get_cipherbyname("AES-192-GCM"); + #endif + #ifdef WOLFSSL_AES_256 + EVP_AES_256_GCM = (char *)EVP_get_cipherbyname("AES-256-GCM"); + #endif + #endif /* HAVE_AESGCM*/ + #ifdef WOLFSSL_AES_128 + EVP_AES_128_CTR = (char *)EVP_get_cipherbyname("AES-128-CTR"); + #endif + #ifdef WOLFSSL_AES_192 + EVP_AES_192_CTR = (char *)EVP_get_cipherbyname("AES-192-CTR"); + #endif + #ifdef WOLFSSL_AES_256 + EVP_AES_256_CTR = (char *)EVP_get_cipherbyname("AES-256-CTR"); + #endif + + #ifdef WOLFSSL_AES_128 + EVP_AES_128_ECB = (char *)EVP_get_cipherbyname("AES-128-ECB"); + #endif + #ifdef WOLFSSL_AES_192 + EVP_AES_192_ECB = (char *)EVP_get_cipherbyname("AES-192-ECB"); + #endif + #ifdef WOLFSSL_AES_256 + EVP_AES_256_ECB = (char *)EVP_get_cipherbyname("AES-256-ECB"); + #endif +#endif /* ifndef NO_AES*/ + +#ifndef NO_DES3 + EVP_DES_CBC = (char *)EVP_get_cipherbyname("DES-CBC"); + EVP_DES_ECB = (char *)EVP_get_cipherbyname("DES-ECB"); + + EVP_DES_EDE3_CBC = (char *)EVP_get_cipherbyname("DES-EDE3-CBC"); + EVP_DES_EDE3_ECB = (char *)EVP_get_cipherbyname("DES-EDE3-ECB"); +#endif + +#ifdef HAVE_IDEA + EVP_IDEA_CBC = (char *)EVP_get_cipherbyname("IDEA-CBC"); +#endif +} + +#if !defined(NO_PWDBASED) +int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp, + int* pHash, int* pHashSz) +{ + enum wc_HashType hash = WC_HASH_TYPE_NONE; + int hashSz; + + if (XSTRLEN(evp) < 3) { + /* do not try comparing strings if size is too small */ + return WOLFSSL_FAILURE; + } + + if (XSTRNCMP("SHA", evp, 3) == 0) { + if (XSTRLEN(evp) > 3) { + #ifndef NO_SHA256 + if (XSTRNCMP("SHA256", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA256; + } + else + #endif + #ifdef WOLFSSL_SHA384 + if (XSTRNCMP("SHA384", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA384; + } + else + #endif + #ifdef WOLFSSL_SHA512 + if (XSTRNCMP("SHA512", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA512; + } + else + #endif + { + WOLFSSL_MSG("Unknown SHA hash"); + } + } + else { + hash = WC_HASH_TYPE_SHA; + } + } +#ifdef WOLFSSL_MD2 + else if (XSTRNCMP("MD2", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD2; + } +#endif +#ifndef NO_MD4 + else if (XSTRNCMP("MD4", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD4; + } +#endif +#ifndef NO_MD5 + else if (XSTRNCMP("MD5", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD5; + } +#endif + + if (pHash) + *pHash = hash; + + hashSz = wc_HashGetDigestSize(hash); + if (pHashSz) + *pHashSz = hashSz; + + if (hashSz < 0) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* this function makes the assumption that out buffer is big enough for digest*/ +int wolfSSL_EVP_Digest(const unsigned char* in, int inSz, unsigned char* out, + unsigned int* outSz, const WOLFSSL_EVP_MD* evp, + WOLFSSL_ENGINE* eng) +{ + int err; + int hashType = WC_HASH_TYPE_NONE; + int hashSz; + + WOLFSSL_ENTER("wolfSSL_EVP_Digest"); + if (in == NULL || out == NULL || evp == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return WOLFSSL_FAILURE; + } + + err = wolfSSL_EVP_get_hashinfo(evp, &hashType, &hashSz); + if (err != WOLFSSL_SUCCESS) + return err; + + if (wc_Hash((enum wc_HashType)hashType, in, inSz, out, hashSz) != 0) { + return WOLFSSL_FAILURE; + } + + if (outSz != NULL) + *outSz = hashSz; + + (void)eng; + return WOLFSSL_SUCCESS; +} +#endif + +const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name) +{ + static const struct alias { + const char *name; + const char *alias; + } alias_tbl[] = + { + {"MD4", "ssl3-md4"}, + {"MD5", "ssl3-md5"}, + {"SHA", "ssl3-sha1"}, + {"SHA", "SHA1"}, + { NULL, NULL} + }; + + const struct alias *al; + const struct s_ent *ent; + + + 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++) + if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) { + return (EVP_MD *)ent->name; + } + return NULL; +} + +int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) +{ + const struct s_ent *ent ; + WOLFSSL_ENTER("EVP_MD_type"); + for( ent = md_tbl; ent->name != NULL; ent++){ + if(XSTRNCMP((const char *)md, ent->name, XSTRLEN(ent->name)+1) == 0) { + return ent->nid; + } + } + return 0; +} + +#ifndef NO_MD4 + + /* return a pointer to MD4 EVP type */ + const WOLFSSL_EVP_MD* wolfSSL_EVP_md4(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_md4"); + return EVP_get_digestbyname("MD4"); + } + +#endif /* !NO_MD4 */ + + +#ifndef NO_MD5 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void) + { + WOLFSSL_ENTER("EVP_md5"); + return EVP_get_digestbyname("MD5"); + } + +#endif /* !NO_MD5 */ + + +#ifndef NO_WOLFSSL_STUB + const WOLFSSL_EVP_MD* wolfSSL_EVP_mdc2(void) + { + WOLFSSL_STUB("EVP_mdc2"); + return NULL; + } +#endif + +#ifndef NO_SHA + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void) + { + WOLFSSL_ENTER("EVP_sha1"); + return EVP_get_digestbyname("SHA"); + } +#endif /* NO_SHA */ + +#ifdef WOLFSSL_SHA224 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha224(void) + { + WOLFSSL_ENTER("EVP_sha224"); + return EVP_get_digestbyname("SHA224"); + } + +#endif /* WOLFSSL_SHA224 */ + + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void) + { + WOLFSSL_ENTER("EVP_sha256"); + return EVP_get_digestbyname("SHA256"); + } + +#ifdef WOLFSSL_SHA384 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void) + { + WOLFSSL_ENTER("EVP_sha384"); + return EVP_get_digestbyname("SHA384"); + } + +#endif /* WOLFSSL_SHA384 */ + +#ifdef WOLFSSL_SHA512 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void) + { + WOLFSSL_ENTER("EVP_sha512"); + return EVP_get_digestbyname("SHA512"); + } + +#endif /* WOLFSSL_SHA512 */ + +#ifdef WOLFSSL_SHA3 +#ifndef WOLFSSL_NOSHA3_224 + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_224(void) + { + WOLFSSL_ENTER("EVP_sha3_224"); + return EVP_get_digestbyname("SHA3_224"); + } +#endif /* WOLFSSL_NOSHA3_224 */ + + +#ifndef WOLFSSL_NOSHA3_256 + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_256(void) + { + WOLFSSL_ENTER("EVP_sha3_256"); + return EVP_get_digestbyname("SHA3_256"); + } +#endif /* WOLFSSL_NOSHA3_256 */ + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_384(void) + { + WOLFSSL_ENTER("EVP_sha3_384"); + return EVP_get_digestbyname("SHA3_384"); + } + +#ifndef WOLFSSL_NOSHA3_512 + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_512(void) + { + WOLFSSL_ENTER("EVP_sha3_512"); + return EVP_get_digestbyname("SHA3_512"); + } +#endif /* WOLFSSL_NOSHA3_512 */ +#endif /* WOLFSSL_SHA3 */ + + WOLFSSL_EVP_MD_CTX *wolfSSL_EVP_MD_CTX_new(void) + { + WOLFSSL_EVP_MD_CTX* ctx; + WOLFSSL_ENTER("EVP_MD_CTX_new"); + ctx = (WOLFSSL_EVP_MD_CTX*)XMALLOC(sizeof *ctx, NULL, + DYNAMIC_TYPE_OPENSSL); + if (ctx){ + wolfSSL_EVP_MD_CTX_init(ctx); + } + return ctx; + } + + WOLFSSL_API void wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX *ctx) + { + if (ctx) { + WOLFSSL_ENTER("EVP_MD_CTX_free"); + wolfSSL_EVP_MD_CTX_cleanup(ctx); + XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL); + } + } + + /* returns the NID of message digest used by the ctx */ + int wolfSSL_EVP_MD_CTX_type(const WOLFSSL_EVP_MD_CTX *ctx) { + const struct s_ent *ent; + + WOLFSSL_ENTER("EVP_MD_CTX_type"); + + if (ctx) { + for(ent = md_tbl; ent->name != NULL; ent++) { + if (ctx->macType == ent->macType) { + return ent->nid; + } + } + /* Return whatever we got */ + return ctx->macType; + } + return 0; + } + + + /* returns WOLFSSL_SUCCESS on success */ + int wolfSSL_EVP_MD_CTX_copy(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in) + { + return wolfSSL_EVP_MD_CTX_copy_ex(out, in); + } + + /* returns digest size */ + int wolfSSL_EVP_MD_CTX_size(const WOLFSSL_EVP_MD_CTX *ctx) { + return(wolfSSL_EVP_MD_size(wolfSSL_EVP_MD_CTX_md(ctx))); + } + /* returns block size */ + int wolfSSL_EVP_MD_CTX_block_size(const WOLFSSL_EVP_MD_CTX *ctx) { + return(wolfSSL_EVP_MD_block_size(wolfSSL_EVP_MD_CTX_md(ctx))); + } + + /* Deep copy of EVP_MD hasher + * return WOLFSSL_SUCCESS on success */ + static int wolfSSL_EVP_MD_Copy_Hasher(WOLFSSL_EVP_MD_CTX* des, + const WOLFSSL_EVP_MD_CTX* src) + { + if (src->macType == NID_hmac) { + wolfSSL_HmacCopy(&des->hash.hmac, (Hmac*)&src->hash.hmac); + } + else { + switch (src->macType) { + #ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + wc_Md5Copy((wc_Md5*)&src->hash.digest, + (wc_Md5*)&des->hash.digest); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wc_ShaCopy((wc_Sha*)&src->hash.digest, + (wc_Sha*)&des->hash.digest); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wc_Sha224Copy((wc_Sha224*)&src->hash.digest, + (wc_Sha224*)&des->hash.digest); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wc_Sha256Copy((wc_Sha256*)&src->hash.digest, + (wc_Sha256*)&des->hash.digest); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wc_Sha384Copy((wc_Sha384*)&src->hash.digest, + (wc_Sha384*)&des->hash.digest); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wc_Sha512Copy((wc_Sha512*)&src->hash.digest, + (wc_Sha512*)&des->hash.digest); + break; + #endif /* WOLFSSL_SHA512 */ + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_HASH_TYPE_SHA3_224: + wc_Sha3_224_Copy((wc_Sha3*)&src->hash.digest, + (wc_Sha3*)&des->hash.digest); + break; + #endif + + #ifndef WOLFSSL_NOSHA3_256 + case WC_HASH_TYPE_SHA3_256: + wc_Sha3_256_Copy((wc_Sha3*)&src->hash.digest, + (wc_Sha3*)&des->hash.digest); + break; + #endif + + case WC_HASH_TYPE_SHA3_384: + wc_Sha3_384_Copy((wc_Sha3*)&src->hash.digest, + (wc_Sha3*)&des->hash.digest); + break; + + #ifndef WOLFSSL_NOSHA3_512 + case WC_HASH_TYPE_SHA3_512: + wc_Sha3_512_Copy((wc_Sha3*)&src->hash.digest, + (wc_Sha3*)&des->hash.digest); + break; + #endif + #endif + default: + return WOLFSSL_FAILURE; + } + } + return WOLFSSL_SUCCESS; + } + + /* copies structure in to the structure out + * + * returns WOLFSSL_SUCCESS on success */ + int wolfSSL_EVP_MD_CTX_copy_ex(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in) + { + if ((out == NULL) || (in == NULL)) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_copy_ex"); + XMEMCPY(out, in, sizeof(WOLFSSL_EVP_MD_CTX)); + if (in->pctx != NULL) { + out->pctx = wolfSSL_EVP_PKEY_CTX_new(in->pctx->pkey, NULL); + if (out->pctx == NULL) + return WOLFSSL_FAILURE; + } + return wolfSSL_EVP_MD_Copy_Hasher(out, (WOLFSSL_EVP_MD_CTX*)in); + } + + void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx) + { + WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init"); + XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_MD_CTX)); + } + + const WOLFSSL_EVP_MD *wolfSSL_EVP_MD_CTX_md(const WOLFSSL_EVP_MD_CTX *ctx) + { + const struct s_ent *ent; + if (ctx == NULL) + return NULL; + WOLFSSL_ENTER("EVP_MD_CTX_md"); + for(ent = md_tbl; ent->name != NULL; ent++) { + if(ctx->macType == ent->macType) { + return (const WOLFSSL_EVP_MD *)ent->name; + } + } + return (WOLFSSL_EVP_MD *)NULL; + } + + #ifndef NO_AES + + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + 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; + } + #endif /* WOLFSSL_AES_128 */ + + + #ifdef WOLFSSL_AES_192 + 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; + } + #endif /* WOLFSSL_AES_192 */ + + + #ifdef WOLFSSL_AES_256 + 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; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AES_CBC */ + + #ifdef WOLFSSL_AES_CFB +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb1(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cfb1"); + if (EVP_AES_128_CFB1 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_CFB1; + } + #endif /* WOLFSSL_AES_128 */ + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb1(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cfb1"); + if (EVP_AES_192_CFB1 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_CFB1; + } + #endif /* WOLFSSL_AES_192 */ + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb1(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cfb1"); + if (EVP_AES_256_CFB1 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_CFB1; + } + #endif /* WOLFSSL_AES_256 */ + + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb8(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cfb8"); + if (EVP_AES_128_CFB8 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_CFB8; + } + #endif /* WOLFSSL_AES_128 */ + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb8(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cfb8"); + if (EVP_AES_192_CFB8 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_CFB8; + } + #endif /* WOLFSSL_AES_192 */ + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb8(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cfb8"); + if (EVP_AES_256_CFB8 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_CFB8; + } + #endif /* WOLFSSL_AES_256 */ +#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ + + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb128(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cfb128"); + if (EVP_AES_128_CFB128 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_CFB128; + } + #endif /* WOLFSSL_AES_128 */ + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb128(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cfb128"); + if (EVP_AES_192_CFB128 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_CFB128; + } + #endif /* WOLFSSL_AES_192 */ + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb128(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cfb128"); + if (EVP_AES_256_CFB128 == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_CFB128; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* WOLFSSL_AES_CFB */ + + #ifdef WOLFSSL_AES_OFB + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ofb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ofb"); + if (EVP_AES_128_OFB == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_OFB; + } + #endif /* WOLFSSL_AES_128 */ + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ofb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ofb"); + if (EVP_AES_192_OFB == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_OFB; + } + #endif /* WOLFSSL_AES_192 */ + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ofb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ofb"); + if (EVP_AES_256_OFB == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_OFB; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* WOLFSSL_AES_OFB */ + + #ifdef WOLFSSL_AES_XTS + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_xts(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_xts"); + if (EVP_AES_128_XTS == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_XTS; + } + #endif /* WOLFSSL_AES_128 */ + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_xts(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_xts"); + if (EVP_AES_256_XTS == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_XTS; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* WOLFSSL_AES_XTS */ + + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_gcm(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_gcm"); + if (EVP_AES_128_GCM == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_GCM; + } + #endif /* WOLFSSL_GCM_128 */ + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_gcm(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_gcm"); + if (EVP_AES_192_GCM == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_GCM; + } + #endif /* WOLFSSL_AES_192 */ + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_gcm(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_gcm"); + if (EVP_AES_256_GCM == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_GCM; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AESGCM */ + + #ifdef WOLFSSL_AES_128 + 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; + } + #endif /* WOLFSSL_AES_2128 */ + + + #ifdef WOLFSSL_AES_192 + 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; + } + #endif /* WOLFSSL_AES_192 */ + + + #ifdef WOLFSSL_AES_256 + 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; + } + #endif /* WOLFSSL_AES_256 */ + + #ifdef WOLFSSL_AES_128 + 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; + } + #endif /* WOLFSSL_AES_128 */ + + + #ifdef WOLFSSL_AES_192 + 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; + } + #endif /* WOLFSSL_AES_192*/ + + + #ifdef WOLFSSL_AES_256 + 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 /* WOLFSSL_AES_256 */ + #endif /* NO_AES */ + +#ifndef NO_DES3 + 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 +#endif /* NO_DES3 */ + +#ifndef NO_RC4 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void) + { + static const char* type = "ARC4"; + WOLFSSL_ENTER("wolfSSL_EVP_rc4"); + return type; + } +#endif + +#ifdef HAVE_IDEA + 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 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void) + { + static const char* type = "NULL"; + WOLFSSL_ENTER("wolfSSL_EVP_enc_null"); + return type; + } + + int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx) + { + WOLFSSL_ENTER("EVP_MD_CTX_cleanup"); + if (ctx->pctx != NULL) + wolfSSL_EVP_PKEY_CTX_free(ctx->pctx); + + if (ctx->macType == NID_hmac) { + wc_HmacFree(&ctx->hash.hmac); + } + else { + switch (ctx->macType) { + #ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + wc_Md5Free((wc_Md5*)&ctx->hash.digest); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wc_ShaFree((wc_Sha*)&ctx->hash.digest); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wc_Sha224Free((wc_Sha224*)&ctx->hash.digest); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wc_Sha256Free((wc_Sha256*)&ctx->hash.digest); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wc_Sha384Free((wc_Sha384*)&ctx->hash.digest); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wc_Sha512Free((wc_Sha512*)&ctx->hash.digest); + break; + #endif /* WOLFSSL_SHA512 */ + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_HASH_TYPE_SHA3_224: + wc_Sha3_224_Free((wc_Sha3*)&ctx->hash.digest); + break; + #endif + + #ifndef WOLFSSL_NOSHA3_256 + case WC_HASH_TYPE_SHA3_256: + wc_Sha3_256_Free((wc_Sha3*)&ctx->hash.digest); + break; + #endif + + case WC_HASH_TYPE_SHA3_384: + wc_Sha3_384_Free((wc_Sha3*)&ctx->hash.digest); + break; + + #ifndef WOLFSSL_NOSHA3_512 + case WC_HASH_TYPE_SHA3_512: + wc_Sha3_512_Free((wc_Sha3*)&ctx->hash.digest); + break; + #endif + #endif + default: + return WOLFSSL_FAILURE; + } + } + ForceZero(ctx, sizeof(*ctx)); + ctx->macType = WC_HASH_TYPE_NONE; + return 1; + } + + void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + WOLFSSL_ENTER("EVP_CIPHER_CTX_init"); + if (ctx) { + XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_CIPHER_CTX)); + ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT; /* not yet initialized */ + ctx->keyLen = 0; + ctx->enc = 1; /* start in encrypt mode */ + } + } + +#if defined(HAVE_AESGCM) && !defined(HAVE_SELFTEST) + static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz) + { + int i; + for (i = ctrSz-1; i >= 0; i--) { + if (++ctr[i]) + break; + } + } +#endif + + /* This function allows cipher specific parameters to be + determined and set. */ + int wolfSSL_EVP_CIPHER_CTX_ctrl(WOLFSSL_EVP_CIPHER_CTX *ctx, int type, \ + int arg, void *ptr) + { + int ret = WOLFSSL_FAILURE; +#if defined(HAVE_AESGCM) && !defined(HAVE_SELFTEST) && !defined(WC_NO_RNG) + WC_RNG rng; +#endif + if (ctx == NULL) + return WOLFSSL_FAILURE; + + (void)arg; + (void)ptr; + + WOLFSSL_ENTER("EVP_CIPHER_CTX_ctrl"); + + switch(type) { + case EVP_CTRL_INIT: + wolfSSL_EVP_CIPHER_CTX_init(ctx); + if(ctx) + ret = WOLFSSL_SUCCESS; + break; + case EVP_CTRL_SET_KEY_LENGTH: + ret = wolfSSL_EVP_CIPHER_CTX_set_key_length(ctx, arg); + break; +#if defined(HAVE_AESGCM) && !defined(HAVE_SELFTEST) && !defined(WC_NO_RNG) + case EVP_CTRL_GCM_SET_IVLEN: + if(arg <= 0 || arg > 16) + return WOLFSSL_FAILURE; + ret = wolfSSL_EVP_CIPHER_CTX_set_iv_length(ctx, arg); + break; + case EVP_CTRL_AEAD_SET_IV_FIXED: + if (arg == -1) { + /* arg == -1 copies ctx->ivSz from ptr */ + ret = wolfSSL_EVP_CIPHER_CTX_set_iv(ctx, (byte*)ptr, ctx->ivSz); + } + else { + /* + * Fixed field must be at least 4 bytes and invocation + * field at least 8. + */ + if ((arg < 4) || (ctx->ivSz - arg) < 8) { + WOLFSSL_MSG("Fixed field or invocation field too short"); + ret = WOLFSSL_FAILURE; + break; + } + if (wc_InitRng(&rng) != 0) { + WOLFSSL_MSG("wc_InitRng failed"); + ret = WOLFSSL_FAILURE; + break; + } + if (arg) { + XMEMCPY(ctx->iv, ptr, arg); + } + if (wc_RNG_GenerateBlock(&rng, ctx->iv + arg, + ctx->ivSz - arg) != 0) { + /* rng is freed immediately after if block so no need + * to do it here + */ + WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); + ret = WOLFSSL_FAILURE; + } + + if (wc_FreeRng(&rng) != 0) { + WOLFSSL_MSG("wc_FreeRng failed"); + ret = WOLFSSL_FAILURE; + break; + } + } + break; +#if !defined(_WIN32) && !defined(HAVE_FIPS) + case EVP_CTRL_GCM_IV_GEN: + if (ctx->cipher.aes.keylen == 0 || ctx->ivSz == 0) { + ret = WOLFSSL_FAILURE; + WOLFSSL_MSG("Key or IV not set"); + break; + } + if ((ret = wc_AesGcmSetExtIV(&ctx->cipher.aes, ctx->iv, ctx->ivSz)) != 0) { + WOLFSSL_MSG("wc_AesGcmSetIV failed"); + ret = WOLFSSL_FAILURE; + } + /* OpenSSL increments the IV. Not sure why */ + IncCtr(ctx->iv, ctx->ivSz); + break; +#endif + case EVP_CTRL_AEAD_SET_TAG: + if(arg <= 0 || arg > 16 || (ptr == NULL)) + return WOLFSSL_FAILURE; + + XMEMCPY(ctx->authTag, ptr, arg); + ctx->authTagSz = arg; + ret = WOLFSSL_SUCCESS; + + break; + case EVP_CTRL_AEAD_GET_TAG: + if(arg <= 0 || arg > 16) + return WOLFSSL_FAILURE; + + XMEMCPY(ptr, ctx->authTag, arg); + ret = WOLFSSL_SUCCESS; + break; +#endif /* HAVE_AESGCM && !HAVE_SELFTEST && !WC_NO_RNG */ + default: + WOLFSSL_MSG("EVP_CIPHER_CTX_ctrl operation not yet handled"); + ret = WOLFSSL_FAILURE; + } + return ret; + } + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + WOLFSSL_ENTER("EVP_CIPHER_CTX_cleanup"); + if (ctx) { + ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT; /* not yet initialized */ + ctx->keyLen = 0; + } + + return WOLFSSL_SUCCESS; + } + + /* Permanent stub for Qt compilation. */ + #if defined(WOLFSSL_QT) && !defined(NO_WOLFSSL_STUB) + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc2_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_rc2_cbc"); + WOLFSSL_STUB("EVP_rc2_cbc"); + return NULL; + } + #endif + +#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED) + + int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER* type, + const WOLFSSL_EVP_MD* md, const byte* salt, + const byte* data, int sz, int count, byte* key, byte* iv) + { + int ret; + int hashType = WC_HASH_TYPE_NONE; + #ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info; + #else + EncryptedInfo info[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_ENCRYPTEDINFO); + if (info == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + #endif + + XMEMSET(info, 0, sizeof(EncryptedInfo)); + + ret = wc_EncryptedInfoGet(info, type); + if (ret < 0) + goto end; + + if (data == NULL) { + ret = info->keySz; + goto end; + } + + ret = wolfSSL_EVP_get_hashinfo(md, &hashType, NULL); + if (ret == WOLFSSL_FAILURE) + goto end; + + ret = wc_PBKDF1_ex(key, info->keySz, iv, info->ivSz, data, sz, salt, + EVP_SALT_SIZE, count, hashType, NULL); + if (ret == 0) + ret = info->keySz; + + end: + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); + #endif + if (ret < 0) + return 0; /* failure - for compatibility */ + + return ret; + } + +#endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */ + +#ifndef NO_AES + static int AesSetKey_ex(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir, int direct) + { + int ret; + /* wc_AesSetKey clear aes.reg if iv == NULL. + Keep IV for openSSL compatibility */ + if (iv == NULL) + XMEMCPY((byte *)aes->tmp, (byte *)aes->reg, AES_BLOCK_SIZE); + if (direct) { + #if defined(WOLFSSL_AES_DIRECT) + ret = wc_AesSetKeyDirect(aes, key, len, iv, dir); + #else + ret = NOT_COMPILED_IN; + #endif + } + else { + ret = wc_AesSetKey(aes, key, len, iv, dir); + } + if (iv == NULL) + XMEMCPY((byte *)aes->reg, (byte *)aes->tmp, AES_BLOCK_SIZE); + return ret; + } +#endif + + /* 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, const byte* key, + const byte* iv, int enc) + { + int ret = 0; + (void)key; + (void)iv; + (void)enc; + + WOLFSSL_ENTER("wolfSSL_EVP_CipherInit"); + if (ctx == NULL) { + WOLFSSL_MSG("no ctx"); + return WOLFSSL_FAILURE; + } + + if (type == NULL && ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT) { + WOLFSSL_MSG("no type set"); + return WOLFSSL_FAILURE; + } + if (ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT){ + /* only first EVP_CipherInit invoke. ctx->cipherType is set below */ + XMEMSET(&ctx->cipher, 0, sizeof(ctx->cipher)); + ctx->flags = 0; + } + /* always clear buffer state */ + ctx->bufUsed = 0; + ctx->lastUsed = 0; + +#ifdef HAVE_WOLFSSL_EVP_CIPHER_CTX_IV + if (!iv && ctx->ivSz) { + iv = ctx->iv; + } +#endif + +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_CBC_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_CBC"); + ctx->cipherType = AES_128_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; + ctx->ivSz = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_CBC_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_CBC"); + ctx->cipherType = AES_192_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; + ctx->ivSz = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_CBC_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_CBC"); + ctx->cipherType = AES_256_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; + ctx->ivSz = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 0); + if (ret != 0){ + WOLFSSL_MSG("AesSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetIV() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AES_CBC */ +#if !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_GCM_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_GCM, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_GCM"); + ctx->cipherType = AES_128_GCM_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_GCM_MODE; + ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; + ctx->authTagSz = AES_BLOCK_SIZE; + ctx->ivSz = GCM_NONCE_MID_SZ; + + XMEMSET(ctx->authTag, 0, ctx->authTagSz); + if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { + WOLFSSL_MSG("wc_AesGcmSetKey() failed"); + return WOLFSSL_FAILURE; + } + if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) { + WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); + return WOLFSSL_FAILURE; + } + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_GCM_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_GCM, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_GCM"); + ctx->cipherType = AES_192_GCM_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_GCM_MODE; + ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; + ctx->authTagSz = AES_BLOCK_SIZE; + ctx->ivSz = GCM_NONCE_MID_SZ; + + XMEMSET(ctx->authTag, 0, ctx->authTagSz); + if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { + WOLFSSL_MSG("wc_AesGcmSetKey() failed"); + return WOLFSSL_FAILURE; + } + if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) { + WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); + return WOLFSSL_FAILURE; + } + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_GCM_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_GCM, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_GCM"); + ctx->cipherType = AES_256_GCM_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_GCM_MODE; + ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; + ctx->authTagSz = AES_BLOCK_SIZE; + ctx->ivSz = GCM_NONCE_MID_SZ; + + XMEMSET(ctx->authTag, 0, ctx->authTagSz); + if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { + WOLFSSL_MSG("wc_AesGcmSetKey() failed"); + return WOLFSSL_FAILURE; + } + if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) { + WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); + return WOLFSSL_FAILURE; + } + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AESGCM */ +#endif /* !defined(_WIN32) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) */ +#ifdef WOLFSSL_AES_COUNTER + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_CTR_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_CTR"); + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->cipherType = AES_128_CTR_TYPE; + ctx->flags |= WOLFSSL_EVP_CIPH_CTR_MODE; + ctx->keyLen = 16; + ctx->block_size = NO_PADDING_BLOCK_SIZE; + ctx->ivSz = AES_BLOCK_SIZE; +#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) + ctx->cipher.aes.left = 0; +#endif + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 1); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_CTR_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_CTR"); + ctx->cipherType = AES_192_CTR_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CTR_MODE; + ctx->keyLen = 24; + ctx->block_size = NO_PADDING_BLOCK_SIZE; + ctx->ivSz = AES_BLOCK_SIZE; +#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) + ctx->cipher.aes.left = 0; +#endif + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 1); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_CTR_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_CTR"); + ctx->cipherType = AES_256_CTR_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CTR_MODE; + ctx->keyLen = 32; + ctx->block_size = NO_PADDING_BLOCK_SIZE; + ctx->ivSz = AES_BLOCK_SIZE; +#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) + ctx->cipher.aes.left = 0; +#endif + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 1); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_256 */ +#endif /* WOLFSSL_AES_COUNTER */ + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_ECB"); + ctx->cipherType = AES_128_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 1); + } + if (ret != 0) + return WOLFSSL_FAILURE; + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_ECB"); + ctx->cipherType = AES_192_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 1); + } + if (ret != 0) + return WOLFSSL_FAILURE; + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_ECB"); + ctx->cipherType = AES_256_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 1); + } + if (ret != 0) + return WOLFSSL_FAILURE; + } + #endif /* WOLFSSL_AES_256 */ + #ifdef WOLFSSL_AES_CFB + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_CFB1_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_CFB1, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_CFB1"); + ctx->cipherType = AES_128_CFB1_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 16; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_CFB1_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_CFB1, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_CFB1"); + ctx->cipherType = AES_192_CFB1_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 24; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_CFB1_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_CFB1, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_CFB1"); + ctx->cipherType = AES_256_CFB1_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 32; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0){ + WOLFSSL_MSG("AesSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetIV() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_CFB8_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_CFB8, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_CFB8"); + ctx->cipherType = AES_128_CFB8_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 16; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_CFB8_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_CFB8, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_CFB8"); + ctx->cipherType = AES_192_CFB8_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 24; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_CFB8_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_CFB8, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_CFB8"); + ctx->cipherType = AES_256_CFB8_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 32; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0){ + WOLFSSL_MSG("AesSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetIV() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_CFB128_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_CFB128, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_CFB128"); + ctx->cipherType = AES_128_CFB128_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 16; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_CFB128_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_CFB128, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_CFB128"); + ctx->cipherType = AES_192_CFB128_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 24; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_CFB128_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_CFB128, EVP_AESCFB_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_CFB128"); + ctx->cipherType = AES_256_CFB128_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CFB_MODE; + ctx->keyLen = 32; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0){ + WOLFSSL_MSG("AesSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetIV() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AES_CFB */ + #ifdef WOLFSSL_AES_OFB + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_OFB_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_OFB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_OFB"); + ctx->cipherType = AES_128_OFB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_OFB_MODE; + ctx->keyLen = 16; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_OFB_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_OFB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_OFB"); + ctx->cipherType = AES_192_OFB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_OFB_MODE; + ctx->keyLen = 24; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_OFB_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_OFB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_OFB"); + ctx->cipherType = AES_256_OFB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_OFB_MODE; + ctx->keyLen = 32; + ctx->block_size = 1; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION, 0); + if (ret != 0){ + WOLFSSL_MSG("AesSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetIV() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AES_OFB */ + #ifdef WOLFSSL_AES_XTS + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_XTS_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_XTS, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_XTS"); + ctx->cipherType = AES_128_XTS_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_XTS_MODE; + ctx->keyLen = 32; + ctx->block_size = 1; + ctx->ivSz = AES_BLOCK_SIZE; + + if (iv != NULL) { + if (iv != ctx->iv) /* Valgrind error when src == dst */ + XMEMCPY(ctx->iv, iv, ctx->ivSz); + } + else + XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE); + + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_AesXtsSetKey(&ctx->cipher.xts, key, ctx->keyLen, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, NULL, 0); + if (ret != 0) { + WOLFSSL_MSG("wc_AesXtsSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_XTS_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_XTS, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_XTS"); + ctx->cipherType = AES_256_XTS_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_XTS_MODE; + ctx->keyLen = 64; + ctx->block_size = 1; + ctx->ivSz = AES_BLOCK_SIZE; + + if (iv != NULL) { + if (iv != ctx->iv) /* Valgrind error when src == dst */ + XMEMCPY(ctx->iv, iv, ctx->ivSz); + } + else + XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE); + + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_AesXtsSetKey(&ctx->cipher.xts, key, ctx->keyLen, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, NULL, 0); + if (ret != 0) { + WOLFSSL_MSG("wc_AesXtsSetKey() failed"); + return WOLFSSL_FAILURE; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AES_XTS */ +#endif /* NO_AES */ + +#ifndef NO_DES3 + if (ctx->cipherType == DES_CBC_TYPE || + (type && XSTRNCMP(type, EVP_DES_CBC, EVP_DES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_CBC"); + ctx->cipherType = DES_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 8; + ctx->block_size = DES_BLOCK_SIZE; + ctx->ivSz = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des_SetKey(&ctx->cipher.des, key, iv, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return WOLFSSL_FAILURE; + } + + if (iv && key == NULL) + wc_Des_SetIV(&ctx->cipher.des, iv); + } +#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"); + ctx->cipherType = DES_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 8; + ctx->block_size = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + WOLFSSL_MSG("Des_SetKey"); + ret = wc_Des_SetKey(&ctx->cipher.des, key, NULL, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } +#endif + 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"); + ctx->cipherType = DES_EDE3_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 24; + ctx->block_size = DES_BLOCK_SIZE; + ctx->ivSz = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des3_SetKey(&ctx->cipher.des3, key, iv, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return WOLFSSL_FAILURE; + } + + if (iv && key == NULL) { + ret = wc_Des3_SetIV(&ctx->cipher.des3, iv); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } + 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"); + ctx->cipherType = DES_EDE3_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 24; + ctx->block_size = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des3_SetKey(&ctx->cipher.des3, key, NULL, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return WOLFSSL_FAILURE; + } + } +#endif /* NO_DES3 */ +#ifndef NO_RC4 + if (ctx->cipherType == ARC4_TYPE || (type && + XSTRNCMP(type, "ARC4", 4) == 0)) { + WOLFSSL_MSG("ARC4"); + ctx->cipherType = ARC4_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_STREAM_CIPHER; + ctx->block_size = 1; + if (ctx->keyLen == 0) /* user may have already set */ + ctx->keyLen = 16; /* default to 128 */ + if (key) + wc_Arc4SetKey(&ctx->cipher.arc4, key, ctx->keyLen); + } +#endif /* NO_RC4 */ +#ifdef HAVE_IDEA + if (ctx->cipherType == IDEA_CBC_TYPE || + (type && XSTRNCMP(type, EVP_IDEA_CBC, EVP_IDEA_SIZE) == 0)) { + WOLFSSL_MSG("EVP_IDEA_CBC"); + ctx->cipherType = IDEA_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = IDEA_KEY_SIZE; + ctx->block_size = 8; + ctx->ivSz = IDEA_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_IdeaSetKey(&ctx->cipher.idea, key, (word16)ctx->keyLen, + iv, ctx->enc ? IDEA_ENCRYPTION : + IDEA_DECRYPTION); + if (ret != 0) + return WOLFSSL_FAILURE; + } + + if (iv && key == NULL) + wc_IdeaSetIV(&ctx->cipher.idea, iv); + } +#endif /* HAVE_IDEA */ + if (ctx->cipherType == NULL_CIPHER_TYPE || (type && + XSTRNCMP(type, "NULL", 4) == 0)) { + WOLFSSL_MSG("NULL cipher"); + ctx->cipherType = NULL_CIPHER_TYPE; + ctx->keyLen = 0; + ctx->block_size = 16; + } +#ifdef HAVE_WOLFSSL_EVP_CIPHER_CTX_IV + if (iv && iv != ctx->iv) { + if (wolfSSL_StoreExternalIV(ctx) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + } +#endif + (void)ret; /* remove warning. If execution reaches this point, ret=0 */ + return WOLFSSL_SUCCESS; + } + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_key_length"); + if (ctx) + return ctx->keyLen; + + return 0; /* failure */ + } + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx, + int keylen) + { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_key_length"); + if (ctx) + ctx->keyLen = keylen; + else + return 0; /* failure */ + + return WOLFSSL_SUCCESS; + } +#if defined(HAVE_AESGCM) + /* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE */ + int wolfSSL_EVP_CIPHER_CTX_set_iv_length(WOLFSSL_EVP_CIPHER_CTX* ctx, + int ivLen) + { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_iv_length"); + if (ctx) + ctx->ivSz= ivLen; + else + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; + } + + /* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE */ + int wolfSSL_EVP_CIPHER_CTX_set_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* iv, + int ivLen) + { + int expectedIvLen; + + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_iv_length"); + if (!ctx || !iv || !ivLen) { + return WOLFSSL_FAILURE; + } + + expectedIvLen = wolfSSL_EVP_CIPHER_CTX_iv_length(ctx); + + if (expectedIvLen == 0 || expectedIvLen != ivLen) { + WOLFSSL_MSG("Wrong ivLen value"); + return WOLFSSL_FAILURE; + } + + return wolfSSL_EVP_CipherInit(ctx, NULL, NULL, iv, -1); + } +#endif + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src, + word32 len) + { + int ret = 0; + WOLFSSL_ENTER("wolfSSL_EVP_Cipher"); + + if (ctx == NULL || src == NULL || + (dst == NULL && + ctx->cipherType != AES_128_GCM_TYPE && + ctx->cipherType != AES_192_GCM_TYPE && + ctx->cipherType != AES_256_GCM_TYPE)) { + WOLFSSL_MSG("Bad function argument"); + return 0; /* failure */ + } + + if (ctx->cipherType == 0xff) { + WOLFSSL_MSG("no init"); + return 0; /* failure */ + } + + switch (ctx->cipherType) { + +#ifndef NO_AES +#ifdef HAVE_AES_CBC + case AES_128_CBC_TYPE : + case AES_192_CBC_TYPE : + case AES_256_CBC_TYPE : + WOLFSSL_MSG("AES CBC"); + if (ctx->enc) + ret = wc_AesCbcEncrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesCbcDecrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif /* HAVE_AES_CBC */ + +#ifdef WOLFSSL_AES_CFB +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + case AES_128_CFB1_TYPE: + case AES_192_CFB1_TYPE: + case AES_256_CFB1_TYPE: + WOLFSSL_MSG("AES CFB1"); + if (ctx->enc) + ret = wc_AesCfb1Encrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesCfb1Decrypt(&ctx->cipher.aes, dst, src, len); + break; + case AES_128_CFB8_TYPE: + case AES_192_CFB8_TYPE: + case AES_256_CFB8_TYPE: + WOLFSSL_MSG("AES CFB8"); + if (ctx->enc) + ret = wc_AesCfb8Encrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesCfb8Decrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ + case AES_128_CFB128_TYPE: + case AES_192_CFB128_TYPE: + case AES_256_CFB128_TYPE: + WOLFSSL_MSG("AES CFB128"); + if (ctx->enc) + ret = wc_AesCfbEncrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesCfbDecrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif /* WOLFSSL_AES_CFB */ +#if defined(WOLFSSL_AES_OFB) + case AES_128_OFB_TYPE: + case AES_192_OFB_TYPE: + case AES_256_OFB_TYPE: + WOLFSSL_MSG("AES OFB"); + if (ctx->enc) + ret = wc_AesOfbEncrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesOfbDecrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif /* WOLFSSL_AES_OFB */ +#if defined(WOLFSSL_AES_XTS) + case AES_128_XTS_TYPE: + case AES_256_XTS_TYPE: + WOLFSSL_MSG("AES XTS"); + if (ctx->enc) + ret = wc_AesXtsEncrypt(&ctx->cipher.xts, dst, src, len, + ctx->iv, ctx->ivSz); + else + ret = wc_AesXtsDecrypt(&ctx->cipher.xts, dst, src, len, + ctx->iv, ctx->ivSz); + break; +#endif /* WOLFSSL_AES_XTS */ + +#ifdef HAVE_AESGCM + case AES_128_GCM_TYPE : + case AES_192_GCM_TYPE : + case AES_256_GCM_TYPE : + WOLFSSL_MSG("AES GCM"); + if (ctx->enc) { + if (dst){ + /* encrypt confidential data*/ + ret = wc_AesGcmEncrypt(&ctx->cipher.aes, dst, src, len, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + NULL, 0); + } + else { + /* authenticated, non-confidential data */ + ret = wc_AesGcmEncrypt(&ctx->cipher.aes, NULL, NULL, 0, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + src, len); + /* Reset partial authTag error for AAD*/ + if (ret == AES_GCM_AUTH_E) + ret = 0; + } + } + else { + if (dst){ + /* decrypt confidential data*/ + ret = wc_AesGcmDecrypt(&ctx->cipher.aes, dst, src, len, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + NULL, 0); + } + else { + /* authenticated, non-confidential data*/ + ret = wc_AesGcmDecrypt(&ctx->cipher.aes, NULL, NULL, 0, + ctx->iv, ctx->ivSz, + ctx->authTag, ctx->authTagSz, + src, len); + /* Reset partial authTag error for AAD*/ + if (ret == AES_GCM_AUTH_E) + ret = 0; + } + } + break; +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AES_ECB + case AES_128_ECB_TYPE : + case AES_192_ECB_TYPE : + case AES_256_ECB_TYPE : + WOLFSSL_MSG("AES ECB"); + if (ctx->enc) + ret = wc_AesEcbEncrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesEcbDecrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif +#ifdef WOLFSSL_AES_COUNTER + case AES_128_CTR_TYPE : + case AES_192_CTR_TYPE : + case AES_256_CTR_TYPE : + WOLFSSL_MSG("AES CTR"); + ret = wc_AesCtrEncrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif /* WOLFSSL_AES_COUNTER */ +#endif /* NO_AES */ + +#ifndef NO_DES3 + case DES_CBC_TYPE : + WOLFSSL_MSG("DES CBC"); + if (ctx->enc) + wc_Des_CbcEncrypt(&ctx->cipher.des, dst, src, len); + else + wc_Des_CbcDecrypt(&ctx->cipher.des, dst, src, len); + break; + case DES_EDE3_CBC_TYPE : + WOLFSSL_MSG("DES3 CBC"); + if (ctx->enc) + ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, dst, src, len); + else + ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, dst, src, len); + break; +#ifdef WOLFSSL_DES_ECB + case DES_ECB_TYPE : + WOLFSSL_MSG("DES ECB"); + ret = wc_Des_EcbEncrypt(&ctx->cipher.des, dst, src, len); + break; + case DES_EDE3_ECB_TYPE : + WOLFSSL_MSG("DES3 ECB"); + ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, dst, src, len); + break; +#endif +#endif /* !NO_DES3 */ + +#ifndef NO_RC4 + case ARC4_TYPE : + WOLFSSL_MSG("ARC4"); + wc_Arc4Process(&ctx->cipher.arc4, dst, src, len); + break; +#endif + +#ifdef HAVE_IDEA + case IDEA_CBC_TYPE : + WOLFSSL_MSG("IDEA CBC"); + if (ctx->enc) + wc_IdeaCbcEncrypt(&ctx->cipher.idea, dst, src, len); + else + wc_IdeaCbcDecrypt(&ctx->cipher.idea, dst, src, len); + break; +#endif + case NULL_CIPHER_TYPE : + WOLFSSL_MSG("NULL CIPHER"); + XMEMCPY(dst, src, len); + break; + + default: { + WOLFSSL_MSG("bad type"); + return 0; /* failure */ + } + } + + if (ret != 0) { + WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); + return 0; /* failure */ + } + + if (wolfSSL_StoreExternalIV(ctx) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + WOLFSSL_MSG("wolfSSL_EVP_Cipher success"); + return WOLFSSL_SUCCESS; /* success */ + } + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* md) + { + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("EVP_DigestInit"); + + if (ctx == NULL || md == 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 + + /* Set to 0 if no match */ + ctx->macType = wolfSSL_EVP_md2macType(md); + if (XSTRNCMP(md, "SHA256", 6) == 0) { + ret = wolfSSL_SHA256_Init(&(ctx->hash.digest.sha256)); + } + #ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(md, "SHA224", 6) == 0) { + ret = wolfSSL_SHA224_Init(&(ctx->hash.digest.sha224)); + } + #endif + #ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(md, "SHA384", 6) == 0) { + ret = wolfSSL_SHA384_Init(&(ctx->hash.digest.sha384)); + } + #endif + #ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(md, "SHA512", 6) == 0) { + ret = wolfSSL_SHA512_Init(&(ctx->hash.digest.sha512)); + } + #endif + #ifndef NO_MD4 + else if (XSTRNCMP(md, "MD4", 3) == 0) { + wolfSSL_MD4_Init(&(ctx->hash.digest.md4)); + } + #endif + #ifndef NO_MD5 + else if (XSTRNCMP(md, "MD5", 3) == 0) { + ret = wolfSSL_MD5_Init(&(ctx->hash.digest.md5)); + } + #endif +#ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + else if (XSTRNCMP(md, "SHA3_224", 8) == 0) { + ret = wolfSSL_SHA3_224_Init(&(ctx->hash.digest.sha3_224)); + } + #endif + #ifndef WOLFSSL_NOSHA3_256 + else if (XSTRNCMP(md, "SHA3_256", 8) == 0) { + ret = wolfSSL_SHA3_256_Init(&(ctx->hash.digest.sha3_256)); + } + #endif + else if (XSTRNCMP(md, "SHA3_384", 8) == 0) { + ret = wolfSSL_SHA3_384_Init(&(ctx->hash.digest.sha3_384)); + } + #ifndef WOLFSSL_NOSHA3_512 + else if (XSTRNCMP(md, "SHA3_512", 8) == 0) { + ret = wolfSSL_SHA3_512_Init(&(ctx->hash.digest.sha3_512)); + } + #endif +#endif + #ifndef NO_SHA + /* has to be last since would pick or 224, 256, 384, or 512 too */ + else if (XSTRNCMP(md, "SHA", 3) == 0) { + ret = wolfSSL_SHA_Init(&(ctx->hash.digest.sha)); + } + #endif /* NO_SHA */ + else { + ctx->macType = WC_HASH_TYPE_NONE; + return BAD_FUNC_ARG; + } + + return ret; + } + + /* WOLFSSL_SUCCESS on ok, WOLFSSL_FAILURE on failure */ + int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data, + size_t sz) + { + int macType; + + WOLFSSL_ENTER("EVP_DigestUpdate"); + + macType = wolfSSL_EVP_md2macType(EVP_MD_CTX_md(ctx)); + switch (macType) { +#ifndef NO_MD4 + case WC_HASH_TYPE_MD4: + wolfSSL_MD4_Update((MD4_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wolfSSL_SHA224_Update((SHA224_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif /* !NO_SHA256 */ +#ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif /* WOLFSSL_SHA512 */ + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_HASH_TYPE_SHA3_224: + wolfSSL_SHA3_224_Update((SHA3_224_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_HASH_TYPE_SHA3_256: + wolfSSL_SHA3_256_Update((SHA3_256_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; + #endif + case WC_HASH_TYPE_SHA3_384: + wolfSSL_SHA3_384_Update((SHA3_384_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; + #ifndef WOLFSSL_NOSHA3_512 + case WC_HASH_TYPE_SHA3_512: + wolfSSL_SHA3_512_Update((SHA3_512_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; + #endif + #endif + default: + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; + } + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, + unsigned int* s) + { + int macType; + + WOLFSSL_ENTER("EVP_DigestFinal"); + macType = wolfSSL_EVP_md2macType(EVP_MD_CTX_md(ctx)); + switch (macType) { +#ifndef NO_MD4 + case WC_HASH_TYPE_MD4: + wolfSSL_MD4_Final(md, (MD4_CTX*)&ctx->hash); + if (s) *s = MD4_DIGEST_SIZE; + break; +#endif +#ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash); + if (s) *s = WC_MD5_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash); + if (s) *s = WC_SHA_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wolfSSL_SHA224_Final(md, (SHA224_CTX*)&ctx->hash); + if (s) *s = WC_SHA224_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash); + if (s) *s = WC_SHA256_DIGEST_SIZE; + break; +#endif /* !NO_SHA256 */ +#ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash); + if (s) *s = WC_SHA384_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash); + if (s) *s = WC_SHA512_DIGEST_SIZE; + break; +#endif /* WOLFSSL_SHA512 */ + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_HASH_TYPE_SHA3_224: + wolfSSL_SHA3_224_Final(md, (SHA3_224_CTX*)&ctx->hash); + if (s) *s = WC_SHA3_224_DIGEST_SIZE; + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_HASH_TYPE_SHA3_256: + wolfSSL_SHA3_256_Final(md, (SHA3_256_CTX*)&ctx->hash); + if (s) *s = WC_SHA3_256_DIGEST_SIZE; + break; + #endif + case WC_HASH_TYPE_SHA3_384: + wolfSSL_SHA3_384_Final(md, (SHA3_384_CTX*)&ctx->hash); + if (s) *s = WC_SHA3_384_DIGEST_SIZE; + break; + #ifndef WOLFSSL_NOSHA3_512 + case WC_HASH_TYPE_SHA3_512: + wolfSSL_SHA3_512_Final(md, (SHA3_512_CTX*)&ctx->hash); + if (s) *s = WC_SHA3_512_DIGEST_SIZE; + break; + #endif + #endif + default: + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; + } + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, + unsigned int* s) + { + WOLFSSL_ENTER("EVP_DigestFinal_ex"); + return EVP_DigestFinal(ctx, md, s); + } + + void wolfSSL_EVP_cleanup(void) + { + /* nothing to do here */ + } + +const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int id) +{ + WOLFSSL_MSG("wolfSSL_get_digestbynid"); + + switch(id) { +#ifndef NO_MD5 + case NID_md5: + return wolfSSL_EVP_md5(); +#endif +#ifndef NO_SHA + case NID_sha1: + return wolfSSL_EVP_sha1(); +#endif + default: + WOLFSSL_MSG("Bad digest id value"); + } + + return NULL; +} + +#ifndef NO_RSA +WOLFSSL_RSA* wolfSSL_EVP_PKEY_get0_RSA(WOLFSSL_EVP_PKEY *pkey) +{ + if (!pkey) { + return NULL; + } + return pkey->rsa; +} + +WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* key) +{ + WOLFSSL_RSA* local; + + WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_RSA"); + + if (key == NULL) { + return NULL; + } + + local = wolfSSL_RSA_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_RSA structure"); + return NULL; + } + + if (key->type == EVP_PKEY_RSA) { + if (wolfSSL_RSA_LoadDer(local, (const unsigned char*)key->pkey.ptr, + key->pkey_sz) != SSL_SUCCESS) { + /* now try public key */ + if (wolfSSL_RSA_LoadDer_ex(local, + (const unsigned char*)key->pkey.ptr, key->pkey_sz, + WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) { + wolfSSL_RSA_free(local); + local = NULL; + } + } + } + else { + WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold an RSA key"); + wolfSSL_RSA_free(local); + local = NULL; + } + return local; +} + +/* with set1 functions the pkey struct does not own the RSA structure + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_PKEY_set1_RSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_RSA *key) +{ +#if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA) + int derMax = 0; + int derSz = 0; + byte* derBuf = NULL; + RsaKey* rsa = NULL; +#endif + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_RSA"); + if ((pkey == NULL) || (key == NULL)) + return WOLFSSL_FAILURE; + + if (pkey->rsa != NULL && pkey->ownRsa == 1) { + wolfSSL_RSA_free(pkey->rsa); + } + pkey->rsa = key; + pkey->ownRsa = 0; /* pkey does not own RSA */ + pkey->type = EVP_PKEY_RSA; + if (key->inSet == 0) { + if (SetRsaInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return WOLFSSL_FAILURE; + } + } + +#if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA) + rsa = (RsaKey*)key->internal; + /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional + * information */ + derMax = 5 * wolfSSL_RSA_size(key) + (2 * AES_BLOCK_SIZE); + + derBuf = (byte*)XMALLOC(derMax, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + + if (rsa->type == RSA_PRIVATE) { + /* Private key to DER */ + derSz = wc_RsaKeyToDer(rsa, derBuf, derMax); + } + else { + /* Public key to DER */ + derSz = wc_RsaKeyToPublicDer(rsa, derBuf, derMax); + } + + if (derSz < 0) { + if (rsa->type == RSA_PRIVATE) { + WOLFSSL_MSG("wc_RsaKeyToDer failed"); + } + else { + WOLFSSL_MSG("wc_RsaKeyToPublicDer failed"); + } + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + pkey->pkey.ptr = (char*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_DER); + if (pkey->pkey.ptr == NULL) { + WOLFSSL_MSG("key malloc failed"); + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + pkey->pkey_sz = derSz; + XMEMCPY(pkey->pkey.ptr, derBuf, derSz); + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif /* WOLFSSL_KEY_GEN && !HAVE_USER_RSA */ + +#ifdef WC_RSA_BLINDING + if (key->ownRng == 0) { + if (wc_RsaSetRNG((RsaKey*)(pkey->rsa->internal), &(pkey->rng)) != 0) { + WOLFSSL_MSG("Error setting RSA rng"); + return WOLFSSL_FAILURE; + } + } +#endif + return WOLFSSL_SUCCESS; +} +#endif /* !NO_RSA */ + +#if !defined (NO_DSA) && !defined(HAVE_SELFTEST) && defined(WOLFSSL_KEY_GEN) +/* with set1 functions the pkey struct does not own the DSA structure + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_PKEY_set1_DSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DSA *key) +{ + int derMax = 0; + int derSz = 0; + DsaKey* dsa = NULL; + byte* derBuf = NULL; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_DSA"); + + if((pkey == NULL) || (key == NULL))return WOLFSSL_FAILURE; + if (pkey->dsa != NULL && pkey->ownDsa == 1) { + wolfSSL_DSA_free(pkey->dsa); + } + pkey->dsa = key; + pkey->ownDsa = 0; /* pkey does not own DSA */ + pkey->type = EVP_PKEY_DSA; + if (key->inSet == 0) { + if (SetDsaInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return WOLFSSL_FAILURE; + } + } + dsa = (DsaKey*)key->internal; + + /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */ + derMax = 4 * wolfSSL_BN_num_bytes(key->g) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(derMax, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + + if (dsa->type == DSA_PRIVATE) { + /* Private key to DER */ + derSz = wc_DsaKeyToDer(dsa, derBuf, derMax); + } + else { + /* Public key to DER */ + derSz = wc_DsaKeyToPublicDer(dsa, derBuf, derMax); + } + + if (derSz < 0) { + if (dsa->type == DSA_PRIVATE) { + WOLFSSL_MSG("wc_DsaKeyToDer failed"); + } + else { + WOLFSSL_MSG("wc_DsaKeyToPublicDer failed"); + } + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + pkey->pkey.ptr = (char*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_DER); + if (pkey->pkey.ptr == NULL) { + WOLFSSL_MSG("key malloc failed"); + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + pkey->pkey_sz = derSz; + XMEMCPY(pkey->pkey.ptr, derBuf, derSz); + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return WOLFSSL_SUCCESS; +} + +WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key) +{ + WOLFSSL_DSA* local; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get1_DSA"); + + if (key == NULL) { + WOLFSSL_MSG("Bad function argument"); + return NULL; + } + + local = wolfSSL_DSA_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_DSA structure"); + return NULL; + } + + if (key->type == EVP_PKEY_DSA) { + if (wolfSSL_DSA_LoadDer(local, (const unsigned char*)key->pkey.ptr, + key->pkey_sz) != SSL_SUCCESS) { + /* now try public key */ + if (wolfSSL_DSA_LoadDer_ex(local, + (const unsigned char*)key->pkey.ptr, key->pkey_sz, + WOLFSSL_DSA_LOAD_PUBLIC) != SSL_SUCCESS) { + wolfSSL_DSA_free(local); + local = NULL; + } + } + } + else { + WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold a DSA key"); + wolfSSL_DSA_free(local); + local = NULL; + } + return local; +} +#endif /* !NO_DSA && !HAVE_SELFTEST && WOLFSSL_KEY_GEN */ + +#ifdef HAVE_ECC +WOLFSSL_EC_KEY *wolfSSL_EVP_PKEY_get0_EC_KEY(WOLFSSL_EVP_PKEY *pkey) +{ + WOLFSSL_EC_KEY *eckey = NULL; + if (pkey) { +#ifdef HAVE_ECC + eckey = pkey->ecc; +#endif + } + return eckey; +} + +WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key) +{ + WOLFSSL_EC_KEY* local; + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get1_EC_KEY"); + + if (key == NULL) { + return NULL; + } + + local = wolfSSL_EC_KEY_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_EC_KEY structure"); + return NULL; + } + + if (key->type == EVP_PKEY_EC) { + if (wolfSSL_EC_KEY_LoadDer(local, (const unsigned char*)key->pkey.ptr, + key->pkey_sz) != SSL_SUCCESS) { + /* now try public key */ + if (wolfSSL_EC_KEY_LoadDer_ex(local, + (const unsigned char*)key->pkey.ptr, + key->pkey_sz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != SSL_SUCCESS) { + + wolfSSL_EC_KEY_free(local); + local = NULL; + } + } + } + else { + WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold an EC key"); + wolfSSL_EC_KEY_free(local); + local = NULL; + } +#ifdef OPENSSL_ALL + if (!local && key->ecc) { + local = wolfSSL_EC_KEY_dup(key->ecc); + } +#endif + return local; +} +#endif /* HAVE_ECC */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +#if !defined(NO_DH) && !defined(NO_FILESYSTEM) +/* with set1 functions the pkey struct does not own the DH structure + * Build the following DH Key format from the passed in WOLFSSL_DH + * then store in WOLFSSL_EVP_PKEY in DER format. + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_PKEY_set1_DH(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DH *key) +{ + byte havePublic = 0, havePrivate = 0; + int ret; + word32 derSz = 0; + byte* derBuf = NULL; + DhKey* dhkey = NULL; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_DH"); + + if (pkey == NULL || key == NULL) + return WOLFSSL_FAILURE; + + if (pkey->dh != NULL && pkey->ownDh == 1) + wolfSSL_DH_free(pkey->dh); + + pkey->dh = key; + pkey->ownDh = 0; /* pkey does not own DH */ + pkey->type = EVP_PKEY_DH; + if (key->inSet == 0) { + if (SetDhInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDhInternal failed"); + return WOLFSSL_FAILURE; + } + } + + dhkey = (DhKey*)key->internal; + + havePublic = mp_unsigned_bin_size(&dhkey->pub) > 0; + havePrivate = mp_unsigned_bin_size(&dhkey->priv) > 0; + + /* Get size of DER buffer only */ + if (havePublic && !havePrivate) { + ret = wc_DhPubKeyToDer(dhkey, NULL, &derSz); + } else if (havePrivate && !havePublic) { + ret = wc_DhPrivKeyToDer(dhkey, NULL, &derSz); + } else { + ret = wc_DhParamsToDer(dhkey,NULL,&derSz); + } + + if (derSz <= 0 || ret != LENGTH_ONLY_E) { + WOLFSSL_MSG("Failed to get size of DH Key"); + return WOLFSSL_FAILURE; + } + + derBuf = (byte*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + + /* Fill DER buffer */ + if (havePublic && !havePrivate) { + ret = wc_DhPubKeyToDer(dhkey, derBuf, &derSz); + } else if (havePrivate && !havePublic) { + ret = wc_DhPrivKeyToDer(dhkey, derBuf, &derSz); + } else { + ret = wc_DhParamsToDer(dhkey,derBuf,&derSz); + } + + if (ret <= 0) { + WOLFSSL_MSG("Failed to export DH Key"); + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + /* Store DH key into pkey (DER format) */ + pkey->pkey.ptr = (char*)derBuf; + pkey->pkey_sz = derSz; + + return WOLFSSL_SUCCESS; +} + +WOLFSSL_DH* wolfSSL_EVP_PKEY_get0_DH(WOLFSSL_EVP_PKEY* key) +{ + if (!key) { + return NULL; + } + return key->dh; +} + +WOLFSSL_DH* wolfSSL_EVP_PKEY_get1_DH(WOLFSSL_EVP_PKEY* key) +{ + WOLFSSL_DH* local = NULL; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get1_DH"); + + if (key == NULL || key->dh == NULL) { + WOLFSSL_MSG("Bad function argument"); + return NULL; + } + + if (key->type == EVP_PKEY_DH) { + local = wolfSSL_DH_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_DH structure"); + return NULL; + } + + if (wolfSSL_DH_LoadDer(local, (const unsigned char*)key->pkey.ptr, + key->pkey_sz) != SSL_SUCCESS) { + wolfSSL_DH_free(local); + WOLFSSL_MSG("Error wolfSSL_DH_LoadDer"); + local = NULL; + } + } + else { + WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold a DH key"); + wolfSSL_DH_free(local); + return NULL; + } + + return local; +} +#endif /* NO_DH && NO_FILESYSTEM */ + +int wolfSSL_EVP_PKEY_assign(WOLFSSL_EVP_PKEY *pkey, int type, void *key) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_assign"); + + /* pkey and key checked if NULL in subsequent assign functions */ + switch(type) { + #ifndef NO_RSA + case EVP_PKEY_RSA: + ret = wolfSSL_EVP_PKEY_assign_RSA(pkey, (WOLFSSL_RSA*)key); + break; + #endif + #ifndef NO_DSA + case EVP_PKEY_DSA: + ret = wolfSSL_EVP_PKEY_assign_DSA(pkey, (WOLFSSL_DSA*)key); + break; + #endif + #ifdef HAVE_ECC + case EVP_PKEY_EC: + ret = wolfSSL_EVP_PKEY_assign_EC_KEY(pkey, (WOLFSSL_EC_KEY*)key); + break; + #endif + #ifdef NO_DH + case EVP_PKEY_DH: + ret = wolfSSL_EVP_PKEY_assign_DH(pkey, (WOLFSSL_DH*)key); + break; + #endif + default: + WOLFSSL_MSG("Unknown EVP_PKEY type in wolfSSL_EVP_PKEY_assign."); + ret = WOLFSSL_FAILURE; + } + + return ret; +} +#endif /* WOLFSSL_QT || OPENSSL_ALL */ + +#if defined(HAVE_ECC) +/* try and populate public pkey_sz and pkey.ptr */ +static void ECC_populate_EVP_PKEY(EVP_PKEY* pkey, ecc_key* ecc) +{ + int ret; + if (!pkey || !ecc) + return; + if ((ret = wc_EccPublicKeyDerSize(ecc, 1)) > 0) { + int derSz = ret; + char* derBuf = (char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf) { + ret = wc_EccPublicKeyToDer(ecc, (byte*)derBuf, derSz, 1); + if (ret >= 0) { + if (pkey->pkey.ptr) { + XFREE(pkey->pkey.ptr, NULL, DYNAMIC_TYPE_OPENSSL); + } + pkey->pkey_sz = ret; + pkey->pkey.ptr = derBuf; + } + else { /* failure - okay to ignore */ + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + derBuf = NULL; + } + } + } +} + +WOLFSSL_API int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_KEY *key) +{ +#ifdef HAVE_ECC + if((pkey == NULL) || (key ==NULL))return WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_EC_KEY"); +#ifndef NO_RSA + if (pkey->rsa != NULL && pkey->ownRsa == 1) { + wolfSSL_RSA_free(pkey->rsa); + } + pkey->ownRsa = 0; +#endif +#ifndef NO_DSA + if (pkey->dsa != NULL && pkey->ownDsa == 1) { + wolfSSL_DSA_free(pkey->dsa); + } + pkey->ownDsa = 0; +#endif +#ifndef NO_DH + if (pkey->dh != NULL && pkey->ownDh == 1) { + wolfSSL_DH_free(pkey->dh); + } + pkey->ownDh = 0; +#endif + if (pkey->ecc != NULL && pkey->ownEcc == 1) { + wolfSSL_EC_KEY_free(pkey->ecc); + } + pkey->ecc = key; + pkey->ownEcc = 0; /* pkey does not own EC key */ + pkey->type = EVP_PKEY_EC; + ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal); + return WOLFSSL_SUCCESS; +#else + (void)pkey; + (void)key; + return WOLFSSL_FAILURE; +#endif +} + +void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_EVP_X_STATE"); + + if (ctx) { + switch (ctx->cipherType) { + case ARC4_TYPE: + WOLFSSL_MSG("returning arc4 state"); + return (void*)&ctx->cipher.arc4.x; + + default: + WOLFSSL_MSG("bad x state type"); + return 0; + } + } + + return NULL; +} +int wolfSSL_EVP_PKEY_assign_EC_KEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY* key) +{ + if (pkey == NULL || key == NULL) + return WOLFSSL_FAILURE; + + pkey->type = EVP_PKEY_EC; + pkey->ecc = key; + pkey->ownEcc = 1; + + /* try and populate public pkey_sz and pkey.ptr */ + ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal); + + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_ECC */ + +#ifndef NO_WOLFSSL_STUB +const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void) +{ + WOLFSSL_MSG("wolfSSL_ripemd160"); + WOLFSSL_STUB("EVP_ripemd160"); + return NULL; +} +#endif + + +int wolfSSL_EVP_MD_block_size(const WOLFSSL_EVP_MD* type) +{ + WOLFSSL_MSG("wolfSSL_EVP_MD_block_size"); + + if (type == NULL) { + WOLFSSL_MSG("No md type arg"); + return BAD_FUNC_ARG; + } + + if (XSTRNCMP(type, "SHA256", 6) == 0) { + return WC_SHA256_BLOCK_SIZE; + } +#ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + return WC_MD5_BLOCK_SIZE; + } +#endif +#ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + return WC_SHA224_BLOCK_SIZE; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + return WC_SHA384_BLOCK_SIZE; + } +#endif +#ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + return WC_SHA512_BLOCK_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 WC_SHA_BLOCK_SIZE; + } +#endif + + return BAD_FUNC_ARG; +} + +int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* type) +{ + WOLFSSL_MSG("wolfSSL_EVP_MD_size"); + + if (type == NULL) { + WOLFSSL_MSG("No md type arg"); + return BAD_FUNC_ARG; + } + + if (XSTRNCMP(type, "SHA256", 6) == 0) { + return WC_SHA256_DIGEST_SIZE; + } +#ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + return WC_MD5_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + return WC_SHA224_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + return WC_SHA384_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + 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 WC_SHA_DIGEST_SIZE; + } +#endif + + return BAD_FUNC_ARG; +} + + +int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_EVP_CIPHER_CTX_iv_length"); + + switch (ctx->cipherType) { + +#ifdef HAVE_AES_CBC + case AES_128_CBC_TYPE : + case AES_192_CBC_TYPE : + case AES_256_CBC_TYPE : + WOLFSSL_MSG("AES CBC"); + return AES_BLOCK_SIZE; +#endif +#ifdef HAVE_AESGCM + case AES_128_GCM_TYPE : + case AES_192_GCM_TYPE : + case AES_256_GCM_TYPE : + WOLFSSL_MSG("AES GCM"); + return GCM_NONCE_MID_SZ; +#endif +#ifdef WOLFSSL_AES_COUNTER + case AES_128_CTR_TYPE : + case AES_192_CTR_TYPE : + case AES_256_CTR_TYPE : + WOLFSSL_MSG("AES CTR"); + return AES_BLOCK_SIZE; +#endif +#ifndef NO_DES3 + case DES_CBC_TYPE : + WOLFSSL_MSG("DES CBC"); + return DES_BLOCK_SIZE; + + case DES_EDE3_CBC_TYPE : + WOLFSSL_MSG("DES EDE3 CBC"); + return DES_BLOCK_SIZE; +#endif +#ifdef HAVE_IDEA + case IDEA_CBC_TYPE : + WOLFSSL_MSG("IDEA CBC"); + return IDEA_BLOCK_SIZE; +#endif +#ifndef NO_RC4 + case ARC4_TYPE : + WOLFSSL_MSG("ARC4"); + return 0; +#endif +#ifdef WOLFSSL_AES_CFB +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + case AES_128_CFB1_TYPE: + case AES_192_CFB1_TYPE: + case AES_256_CFB1_TYPE: + WOLFSSL_MSG("AES CFB1"); + return AES_BLOCK_SIZE; + case AES_128_CFB8_TYPE: + case AES_192_CFB8_TYPE: + case AES_256_CFB8_TYPE: + WOLFSSL_MSG("AES CFB8"); + return AES_BLOCK_SIZE; +#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ + case AES_128_CFB128_TYPE: + case AES_192_CFB128_TYPE: + case AES_256_CFB128_TYPE: + WOLFSSL_MSG("AES CFB128"); + return AES_BLOCK_SIZE; +#endif /* WOLFSSL_AES_CFB */ +#if defined(WOLFSSL_AES_OFB) + case AES_128_OFB_TYPE: + case AES_192_OFB_TYPE: + case AES_256_OFB_TYPE: + WOLFSSL_MSG("AES OFB"); + return AES_BLOCK_SIZE; +#endif /* WOLFSSL_AES_OFB */ +#ifdef WOLFSSL_AES_XTS + case AES_128_XTS_TYPE: + case AES_256_XTS_TYPE: + WOLFSSL_MSG("AES XTS"); + return AES_BLOCK_SIZE; +#endif /* WOLFSSL_AES_XTS */ + + case NULL_CIPHER_TYPE : + WOLFSSL_MSG("NULL"); + return 0; + + default: { + WOLFSSL_MSG("bad type"); + } + } + 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 +#ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + if (EVP_AES_128_CBC && XSTRNCMP(name, EVP_AES_128_CBC, XSTRLEN(EVP_AES_128_CBC)) == 0) + return AES_BLOCK_SIZE; + #endif + #ifdef WOLFSSL_AES_192 + if (EVP_AES_192_CBC && XSTRNCMP(name, EVP_AES_192_CBC, XSTRLEN(EVP_AES_192_CBC)) == 0) + return AES_BLOCK_SIZE; + #endif + #ifdef WOLFSSL_AES_256 + if (EVP_AES_256_CBC && XSTRNCMP(name, EVP_AES_256_CBC, XSTRLEN(EVP_AES_256_CBC)) == 0) + return AES_BLOCK_SIZE; + #endif +#endif /* HAVE_AES_CBC */ +#ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + if (EVP_AES_128_GCM && XSTRNCMP(name, EVP_AES_128_GCM, XSTRLEN(EVP_AES_128_GCM)) == 0) + return GCM_NONCE_MID_SZ; + #endif + #ifdef WOLFSSL_AES_192 + if (EVP_AES_192_GCM && XSTRNCMP(name, EVP_AES_192_GCM, XSTRLEN(EVP_AES_192_GCM)) == 0) + return GCM_NONCE_MID_SZ; + #endif + #ifdef WOLFSSL_AES_256 + if (EVP_AES_256_GCM && XSTRNCMP(name, EVP_AES_256_GCM, XSTRLEN(EVP_AES_256_GCM)) == 0) + return GCM_NONCE_MID_SZ; + #endif +#endif /* HAVE_AESGCM */ +#ifdef WOLFSSL_AES_COUNTER + #ifdef WOLFSSL_AES_128 + if (EVP_AES_128_CTR && XSTRNCMP(name, EVP_AES_128_CTR, XSTRLEN(EVP_AES_128_CTR)) == 0) + return AES_BLOCK_SIZE; + #endif + #ifdef WOLFSSL_AES_192 + if (EVP_AES_192_CTR && XSTRNCMP(name, EVP_AES_192_CTR, XSTRLEN(EVP_AES_192_CTR)) == 0) + return AES_BLOCK_SIZE; + #endif + #ifdef WOLFSSL_AES_256 + if (EVP_AES_256_CTR && XSTRNCMP(name, EVP_AES_256_CTR, XSTRLEN(EVP_AES_256_CTR)) == 0) + return AES_BLOCK_SIZE; + #endif +#endif +#ifdef WOLFSSL_AES_XTS + #ifdef WOLFSSL_AES_128 + if (EVP_AES_128_XTS && XSTRNCMP(name, EVP_AES_128_XTS, XSTRLEN(EVP_AES_128_XTS)) == 0) + return AES_BLOCK_SIZE; + #endif /* WOLFSSL_AES_128 */ + + #ifdef WOLFSSL_AES_256 + if (EVP_AES_256_XTS && XSTRNCMP(name, EVP_AES_256_XTS, XSTRLEN(EVP_AES_256_XTS)) == 0) + return AES_BLOCK_SIZE; + #endif /* WOLFSSL_AES_256 */ +#endif /* WOLFSSL_AES_XTS */ + +#endif + +#ifndef NO_DES3 + if ((EVP_DES_CBC && XSTRNCMP(name, EVP_DES_CBC, XSTRLEN(EVP_DES_CBC)) == 0) || + (EVP_DES_EDE3_CBC && XSTRNCMP(name, EVP_DES_EDE3_CBC, XSTRLEN(EVP_DES_EDE3_CBC)) == 0)) { + return DES_BLOCK_SIZE; + } +#endif + +#ifdef HAVE_IDEA + if (EVP_IDEA_CBC && XSTRNCMP(name, EVP_IDEA_CBC, XSTRLEN(EVP_IDEA_CBC)) == 0) + return IDEA_BLOCK_SIZE; +#endif + + (void)name; + + return 0; +} + + +int wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_EVP_X_STATE_LEN"); + + if (ctx) { + switch (ctx->cipherType) { + case ARC4_TYPE: + WOLFSSL_MSG("returning arc4 state size"); + return sizeof(Arc4); + + default: + WOLFSSL_MSG("bad x state type"); + return 0; + } + } + + return 0; +} + + +/* return of pkey->type which will be EVP_PKEY_RSA for example. + * + * type type of EVP_PKEY + * + * returns type or if type is not found then NID_undef + */ +int wolfSSL_EVP_PKEY_type(int type) +{ + WOLFSSL_MSG("wolfSSL_EVP_PKEY_type"); + + switch (type) { + case EVP_PKEY_RSA: + return EVP_PKEY_RSA; + case EVP_PKEY_DSA: + return EVP_PKEY_DSA; + case EVP_PKEY_EC: + return EVP_PKEY_EC; + case EVP_PKEY_DH: + return EVP_PKEY_DH; + default: + return NID_undef; + } +} + + +int wolfSSL_EVP_PKEY_id(const EVP_PKEY *pkey) +{ + if (pkey != NULL) + return pkey->type; + return 0; +} + + +int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey) +{ + if (pkey == NULL) + return NID_undef; + return wolfSSL_EVP_PKEY_type(pkey->type); +} + + +/* increments ref count of WOLFSSL_EVP_PKEY. Return 1 on success, 0 on error */ +int wolfSSL_EVP_PKEY_up_ref(WOLFSSL_EVP_PKEY* pkey) +{ + if (pkey) { + if (wc_LockMutex(&pkey->refMutex) != 0) { + WOLFSSL_MSG("Failed to lock pkey mutex"); + } + pkey->references++; + wc_UnLockMutex(&pkey->refMutex); + + return 1; + } + + return 0; +} + +#ifndef NO_RSA +int wolfSSL_EVP_PKEY_assign_RSA(EVP_PKEY* pkey, WOLFSSL_RSA* key) +{ + if (pkey == NULL || key == NULL) + return WOLFSSL_FAILURE; + + pkey->type = EVP_PKEY_RSA; + pkey->rsa = key; + pkey->ownRsa = 1; + + /* try and populate public pkey_sz and pkey.ptr */ + if (key->internal) { + RsaKey* rsa = (RsaKey*)key->internal; + int ret = wc_RsaPublicKeyDerSize(rsa, 1); + if (ret > 0) { + int derSz = ret; + char* derBuf = (char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf) { + ret = wc_RsaKeyToPublicDer(rsa, (byte*)derBuf, derSz); + if (ret >= 0) { + pkey->pkey_sz = ret; + pkey->pkey.ptr = derBuf; + } + else { /* failure - okay to ignore */ + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + derBuf = NULL; + } + } + } + } + + return WOLFSSL_SUCCESS; +} +#endif /* !NO_RSA */ + +#ifndef NO_DSA +int wolfSSL_EVP_PKEY_assign_DSA(EVP_PKEY* pkey, WOLFSSL_DSA* key) +{ + if (pkey == NULL || key == NULL) + return WOLFSSL_FAILURE; + + pkey->type = EVP_PKEY_DSA; + pkey->dsa = key; + pkey->ownDsa = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* !NO_DSA */ + +#ifndef NO_DH +int wolfSSL_EVP_PKEY_assign_DH(EVP_PKEY* pkey, WOLFSSL_DH* key) +{ + if (pkey == NULL || key == NULL) + return WOLFSSL_FAILURE; + + pkey->type = EVP_PKEY_DH; + pkey->dh = key; + pkey->ownDh = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* !NO_DH */ + +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA_X509_SMALL) +/* Subset of OPENSSL_EXTRA for PKEY operations PKEY free is needed by the + * subset of X509 API */ + +WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new(void){ + return wolfSSL_EVP_PKEY_new_ex(NULL); +} + +WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap) +{ + WOLFSSL_EVP_PKEY* pkey; + int ret; + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_new_ex"); + pkey = (WOLFSSL_EVP_PKEY*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY), heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey != NULL) { + XMEMSET(pkey, 0, sizeof(WOLFSSL_EVP_PKEY)); + pkey->heap = heap; + pkey->type = WOLFSSL_EVP_PKEY_DEFAULT; +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&pkey->rng, heap, INVALID_DEVID); +#else + ret = wc_InitRng(&pkey->rng); +#endif + if (ret != 0){ + wolfSSL_EVP_PKEY_free(pkey); + WOLFSSL_MSG("memory failure"); + return NULL; + } + pkey->references = 1; + wc_InitMutex(&pkey->refMutex); + } + else { + WOLFSSL_MSG("memory failure"); + } + + return pkey; +} + +void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key) +{ + int doFree = 0; + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_free"); + if (key != NULL) { + if (wc_LockMutex(&key->refMutex) != 0) { + WOLFSSL_MSG("Couldn't lock pkey mutex"); + } + + /* only free if all references to it are done */ + key->references--; + if (key->references == 0) { + doFree = 1; + } + wc_UnLockMutex(&key->refMutex); + + if (doFree) { + wc_FreeRng(&key->rng); + + if (key->pkey.ptr != NULL) { + XFREE(key->pkey.ptr, key->heap, DYNAMIC_TYPE_PUBLIC_KEY); + key->pkey.ptr = NULL; + } + switch(key->type) + { + #ifndef NO_RSA + case EVP_PKEY_RSA: + if (key->rsa != NULL && key->ownRsa == 1) { + wolfSSL_RSA_free(key->rsa); + key->rsa = NULL; + } + break; + #endif /* NO_RSA */ + + #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) + case EVP_PKEY_EC: + if (key->ecc != NULL && key->ownEcc == 1) { + wolfSSL_EC_KEY_free(key->ecc); + key->ecc = NULL; + } + break; + #endif /* HAVE_ECC && OPENSSL_EXTRA */ + + #ifndef NO_DSA + case EVP_PKEY_DSA: + if (key->dsa != NULL && key->ownDsa == 1) { + wolfSSL_DSA_free(key->dsa); + key->dsa = NULL; + } + break; + #endif /* NO_DSA */ + + #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) + case EVP_PKEY_DH: + if (key->dh != NULL && key->ownDh == 1) { + wolfSSL_DH_free(key->dh); + key->dh = NULL; + } + break; + #endif /* ! NO_DH ... */ + + default: + break; + } + + if (wc_FreeMutex(&key->refMutex) != 0) { + WOLFSSL_MSG("Couldn't free pkey mutex"); + } + XFREE(key, key->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + } +} + +#endif /* OPENSSL_EXTRA_X509_SMALL */ + +#endif /* WOLFSSL_EVP_INCLUDED */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_448.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_448.c new file mode 100644 index 000000000..bc38c112f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_448.c @@ -0,0 +1,2458 @@ +/* fe_448.c + * + * Copyright (C) 2006-2020 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 + */ + +/* Based On Daniel J Bernstein's curve25519 Public Domain ref10 work. + * Small implementation based on Daniel Beer's curve25519 public domain work. + * Reworked for curve448 by Sean Parkinson. + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(HAVE_CURVE448) || defined(HAVE_ED448) + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(CURVE448_SMALL) || defined(ED448_SMALL) + +/* Initialize the field element operations. + */ +void fe448_init(void) +{ +} + +/* Normalize the field element. + * Ensure result is in range: 0..2^448-2^224-2 + * + * a [in] Field element in range 0..2^448-1. + */ +void fe448_norm(uint8_t* a) +{ + int i; + int16_t c = 0; + int16_t o = 0; + + for (i = 0; i < 56; i++) { + c += a[i]; + if ((i == 0) || (i == 28)) + c += 1; + c >>= 8; + } + + for (i = 0; i < 56; i++) { + if ((i == 0) || (i == 28)) o += c; + o += a[i]; + a[i] = (uint8_t)o; + o >>= 8; + } +} + +/* Copy one field element into another: d = a. + * + * d [in] Destination field element. + * a [in] Source field element. + */ +void fe448_copy(uint8_t* d, const uint8_t* a) +{ + int i; + for (i = 0; i < 56; i++) { + d[i] = a[i]; + } +} + +/* Conditionally swap the elements. + * Constant time implementation. + * + * a [in] First field element. + * b [in] Second field element. + * c [in] Swap when 1. Valid values: 0, 1. + */ +static void fe448_cswap(uint8_t* a, uint8_t* b, int c) +{ + int i; + uint8_t mask = -(uint8_t)c; + uint8_t t[56]; + + for (i = 0; i < 56; i++) + t[i] = (a[i] ^ b[i]) & mask; + for (i = 0; i < 56; i++) + a[i] ^= t[i]; + for (i = 0; i < 56; i++) + b[i] ^= t[i]; +} + +/* Add two field elements. r = (a + b) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold sum. + * a [in] Field element to add. + * b [in] Field element to add. + */ +void fe448_add(uint8_t* r, const uint8_t* a, const uint8_t* b) +{ + int i; + int16_t c = 0; + int16_t o = 0; + + for (i = 0; i < 56; i++) { + c += a[i]; + c += b[i]; + r[i] = (uint8_t)c; + c >>= 8; + } + + for (i = 0; i < 56; i++) { + if ((i == 0) || (i == 28)) o += c; + o += r[i]; + r[i] = (uint8_t)o; + o >>= 8; + } +} + +/* Subtract a field element from another. r = (a - b) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold difference. + * a [in] Field element to subtract from. + * b [in] Field element to subtract. + */ +void fe448_sub(uint8_t* r, const uint8_t* a, const uint8_t* b) +{ + int i; + int16_t c = 0; + int16_t o = 0; + + for (i = 0; i < 56; i++) { + if (i == 28) + c += 0x1fc; + else + c += 0x1fe; + c += a[i]; + c -= b[i]; + r[i] = (uint8_t)c; + c >>= 8; + } + + for (i = 0; i < 56; i++) { + if ((i == 0) || (i == 28)) o += c; + o += r[i]; + r[i] = (uint8_t)o; + o >>= 8; + } +} + +/* Mulitply a field element by 39081. r = (39081 * a) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold result. + * a [in] Field element to multiply. + */ +void fe448_mul39081(uint8_t* r, const uint8_t* a) +{ + int i; + int32_t c = 0; + int32_t o = 0; + + for (i = 0; i < 56; i++) { + c += a[i] * (int32_t)39081; + r[i] = (uint8_t)c; + c >>= 8; + } + + for (i = 0; i < 56; i++) { + if ((i == 0) || (i == 28)) o += c; + o += r[i]; + r[i] = (uint8_t)o; + o >>= 8; + } +} + +/* Mulitply two field elements. r = (a * b) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold result. + * a [in] Field element to multiply. + * b [in] Field element to multiply. + */ +void fe448_mul(uint8_t* r, const uint8_t* a, const uint8_t* b) +{ + int i, k; + int32_t c = 0; + int16_t o = 0, cc = 0; + uint8_t t[112]; + + for (k = 0; k < 56; k++) { + i = 0; + for (; i <= k; i++) { + c += (int32_t)a[i] * b[k - i]; + } + t[k] = (uint8_t)c; + c >>= 8; + } + for (; k < 111; k++) { + i = k - 55; + for (; i < 56; i++) { + c += (int32_t)a[i] * b[k - i]; + } + t[k] = (uint8_t)c; + c >>= 8; + } + t[k] = (uint8_t)c; + + for (i = 0; i < 28; i++) { + o += t[i]; + o += t[i + 56]; + o += t[i + 84]; + r[i] = (uint8_t)o; + o >>= 8; + } + for (i = 28; i < 56; i++) { + o += t[i]; + o += t[i + 56]; + o += t[i + 28]; + o += t[i + 56]; + r[i] = (uint8_t)o; + o >>= 8; + } + for (i = 0; i < 56; i++) { + if ((i == 0) || (i == 28)) cc += o; + cc += r[i]; + r[i] = (uint8_t)cc; + cc >>= 8; + } +} + +/* Square a field element. r = (a * a) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold result. + * a [in] Field element to square. + */ +void fe448_sqr(uint8_t* r, const uint8_t* a) +{ + int i, k; + int32_t c = 0; + int32_t p; + int16_t o = 0, cc = 0; + uint8_t t[112]; + + for (k = 0; k < 56; k++) { + i = 0; + for (; i <= k; i++) { + if (k - i < i) + break; + p = (int32_t)a[i] * a[k - i]; + if (k - i != i) + p *= 2; + c += p; + } + t[k] = (uint8_t)c; + c >>= 8; + } + for (; k < 111; k++) { + i = k - 55; + for (; i < 56; i++) { + if (k - i < i) + break; + p = (int32_t)a[i] * a[k - i]; + if (k - i != i) + p *= 2; + c += p; + } + t[k] = (uint8_t)c; + c >>= 8; + } + t[k] = (uint8_t)c; + + for (i = 0; i < 28; i++) { + o += t[i]; + o += t[i + 56]; + o += t[i + 84]; + r[i] = (uint8_t)o; + o >>= 8; + } + for (i = 28; i < 56; i++) { + o += t[i]; + o += t[i + 56]; + o += t[i + 28]; + o += t[i + 56]; + r[i] = (uint8_t)o; + o >>= 8; + } + for (i = 0; i < 56; i++) { + if ((i == 0) || (i == 28)) cc += o; + cc += r[i]; + r[i] = (uint8_t)cc; + cc >>= 8; + } + fe448_norm(r); +} + +/* Invert the field element. (r * a) mod (2^448 - 2^224 - 1) = 1 + * Constant time implementation - using Fermat's little theorem: + * a^(p-1) mod p = 1 => a^(p-2) mod p = 1/a + * For curve448: p - 2 = 2^448 - 2^224 - 3 + * + * r [in] Field element to hold result. + * a [in] Field element to invert. + */ +void fe448_invert(uint8_t* r, const uint8_t* a) +{ + int i; + uint8_t t[56]; + + fe448_sqr(t, a); + fe448_mul(t, t, a); + for (i = 0; i < 221; i++) { + fe448_sqr(t, t); + fe448_mul(t, t, a); + } + fe448_sqr(t, t); + for (i = 0; i < 222; i++) { + fe448_sqr(t, t); + fe448_mul(t, t, a); + } + fe448_sqr(t, t); + fe448_sqr(t, t); + fe448_mul(r, t, a); +} + +/* Scalar multiply the point by a number. r = n.a + * Uses Montogmery ladder and only requires the x-ordinate. + * + * r [in] Field element to hold result. + * n [in] Scalar as an array of bytes. + * a [in] Point to multiply - x-ordinate only. + */ +int curve448(byte* r, const byte* n, const byte* a) +{ + uint8_t x1[56]; + uint8_t x2[56] = {1}; + uint8_t z2[56] = {0}; + uint8_t x3[56]; + uint8_t z3[56] = {1}; + uint8_t t0[56]; + uint8_t t1[56]; + int i; + unsigned int swap; + unsigned int b; + + fe448_copy(x1, a); + fe448_copy(x3, a); + + swap = 0; + for (i = 447; i >= 0; --i) { + b = (n[i >> 3] >> (i & 7)) & 1; + swap ^= b; + fe448_cswap(x2, x3, swap); + fe448_cswap(z2, z3, swap); + swap = b; + + /* Montgomery Ladder - double and add */ + fe448_add(t0, x2, z2); + fe448_add(t1, x3, z3); + fe448_sub(x2, x2, z2); + fe448_sub(x3, x3, z3); + fe448_mul(t1, t1, x2); + fe448_mul(z3, x3, t0); + fe448_sqr(t0, t0); + fe448_sqr(x2, x2); + fe448_add(x3, z3, t1); + fe448_sqr(x3, x3); + fe448_sub(z3, z3, t1); + fe448_sqr(z3, z3); + fe448_mul(z3, z3, x1); + fe448_sub(t1, t0, x2); + fe448_mul(x2, t0, x2); + fe448_mul39081(z2, t1); + fe448_add(z2, t0, z2); + fe448_mul(z2, z2, t1); + } + fe448_cswap(x2, x3, swap); + fe448_cswap(z2, z3, swap); + + fe448_invert(z2, z2); + fe448_mul(r, x2, z2); + fe448_norm(r); + + return 0; +} + +#ifdef HAVE_ED448 +/* Check whether field element is not 0. + * Field element must have been normalized before call. + * + * a [in] Field element. + * returns 0 when zero, and any other value otherwise. + */ +int fe448_isnonzero(const uint8_t* a) +{ + int i; + uint8_t c = 0; + for (i = 0; i < 56; i++) + c |= a[i]; + return c; +} + +/* Negates the field element. r = -a mod (2^448 - 2^224 - 1) + * Add 0x200 to each element and subtract 2 from next. + * Top element overflow handled by subtracting 2 from index 0 and 28. + * + * r [in] Field element to hold result. + * a [in] Field element. + */ +void fe448_neg(uint8_t* r, const uint8_t* a) +{ + int i; + int16_t c = 0; + int16_t o = 0; + + for (i = 0; i < 56; i++) { + if (i == 28) + c += 0x1fc; + else + c += 0x1fe; + c -= a[i]; + r[i] = (uint8_t)c; + c >>= 8; + } + + for (i = 0; i < 56; i++) { + if ((i == 0) || (i == 28)) o += c; + o += r[i]; + r[i] = (uint8_t)o; + o >>= 8; + } +} + +/* Raise field element to (p-3) / 4: 2^446 - 2^222 - 1 + * Used for calcualting y-ordinate from x-ordinate for Ed448. + * + * r [in] Field element to hold result. + * a [in] Field element to exponentiate. + */ +void fe448_pow_2_446_222_1(uint8_t* r, const uint8_t* a) +{ + int i; + uint8_t t[56]; + + fe448_sqr(t, a); + fe448_mul(t, t, a); + for (i = 0; i < 221; i++) { + fe448_sqr(t, t); + fe448_mul(t, t, a); + } + fe448_sqr(t, t); + for (i = 0; i < 221; i++) { + fe448_sqr(t, t); + fe448_mul(t, t, a); + } + fe448_sqr(t, t); + fe448_mul(r, t, a); +} + +/* 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 fe448_cmov(uint8_t* a, const uint8_t* b, int c) +{ + int i; + uint8_t m = -(uint8_t)c; + uint8_t t[56]; + + for (i = 0; i < 56; i++) + t[i] = m & (a[i] ^ b[i]); + for (i = 0; i < 56; i++) + a[i] ^= t[i]; +} + +#endif /* HAVE_ED448 */ +#elif defined(CURVED448_128BIT) + +/* Initialize the field element operations. + */ +void fe448_init(void) +{ +} + +/* Convert the field element from a byte array to an array of 56-bits. + * + * r [in] Array to encode into. + * b [in] Byte array. + */ +void fe448_from_bytes(int64_t* r, const unsigned char* b) +{ + r[ 0] = ((int64_t) (b[ 0]) << 0) + | ((int64_t) (b[ 1]) << 8) + | ((int64_t) (b[ 2]) << 16) + | ((int64_t) (b[ 3]) << 24) + | ((int64_t) (b[ 4]) << 32) + | ((int64_t) (b[ 5]) << 40) + | ((int64_t) (b[ 6]) << 48); + r[ 1] = ((int64_t) (b[ 7]) << 0) + | ((int64_t) (b[ 8]) << 8) + | ((int64_t) (b[ 9]) << 16) + | ((int64_t) (b[10]) << 24) + | ((int64_t) (b[11]) << 32) + | ((int64_t) (b[12]) << 40) + | ((int64_t) (b[13]) << 48); + r[ 2] = ((int64_t) (b[14]) << 0) + | ((int64_t) (b[15]) << 8) + | ((int64_t) (b[16]) << 16) + | ((int64_t) (b[17]) << 24) + | ((int64_t) (b[18]) << 32) + | ((int64_t) (b[19]) << 40) + | ((int64_t) (b[20]) << 48); + r[ 3] = ((int64_t) (b[21]) << 0) + | ((int64_t) (b[22]) << 8) + | ((int64_t) (b[23]) << 16) + | ((int64_t) (b[24]) << 24) + | ((int64_t) (b[25]) << 32) + | ((int64_t) (b[26]) << 40) + | ((int64_t) (b[27]) << 48); + r[ 4] = ((int64_t) (b[28]) << 0) + | ((int64_t) (b[29]) << 8) + | ((int64_t) (b[30]) << 16) + | ((int64_t) (b[31]) << 24) + | ((int64_t) (b[32]) << 32) + | ((int64_t) (b[33]) << 40) + | ((int64_t) (b[34]) << 48); + r[ 5] = ((int64_t) (b[35]) << 0) + | ((int64_t) (b[36]) << 8) + | ((int64_t) (b[37]) << 16) + | ((int64_t) (b[38]) << 24) + | ((int64_t) (b[39]) << 32) + | ((int64_t) (b[40]) << 40) + | ((int64_t) (b[41]) << 48); + r[ 6] = ((int64_t) (b[42]) << 0) + | ((int64_t) (b[43]) << 8) + | ((int64_t) (b[44]) << 16) + | ((int64_t) (b[45]) << 24) + | ((int64_t) (b[46]) << 32) + | ((int64_t) (b[47]) << 40) + | ((int64_t) (b[48]) << 48); + r[ 7] = ((int64_t) (b[49]) << 0) + | ((int64_t) (b[50]) << 8) + | ((int64_t) (b[51]) << 16) + | ((int64_t) (b[52]) << 24) + | ((int64_t) (b[53]) << 32) + | ((int64_t) (b[54]) << 40) + | ((int64_t) (b[55]) << 48); +} + +/* Convert the field element to a byte array from an array of 56-bits. + * + * b [in] Byte array. + * a [in] Array to encode into. + */ +void fe448_to_bytes(unsigned char* b, const int64_t* a) +{ + int128_t t; + /* Mod */ + int64_t in0 = a[0]; + int64_t in1 = a[1]; + int64_t in2 = a[2]; + int64_t in3 = a[3]; + int64_t in4 = a[4]; + int64_t in5 = a[5]; + int64_t in6 = a[6]; + int64_t in7 = a[7]; + int64_t o = in7 >> 56; + in7 -= o << 56; + in0 += o; + in4 += o; + o = (in0 + 1) >> 56; + o = (o + in1) >> 56; + o = (o + in2) >> 56; + o = (o + in3) >> 56; + o = (o + in4 + 1) >> 56; + o = (o + in5) >> 56; + o = (o + in6) >> 56; + o = (o + in7) >> 56; + in0 += o; + in4 += o; + in7 -= o << 56; + o = in0 >> 56; in1 += o; t = o << 56; in0 -= t; + o = in1 >> 56; in2 += o; t = o << 56; in1 -= t; + o = in2 >> 56; in3 += o; t = o << 56; in2 -= t; + o = in3 >> 56; in4 += o; t = o << 56; in3 -= t; + o = in4 >> 56; in5 += o; t = o << 56; in4 -= t; + o = in5 >> 56; in6 += o; t = o << 56; in5 -= t; + o = in6 >> 56; in7 += o; t = o << 56; in6 -= t; + o = in7 >> 56; in0 += o; + in4 += o; t = o << 56; in7 -= t; + + /* Output as bytes */ + b[ 0] = (in0 >> 0); + b[ 1] = (in0 >> 8); + b[ 2] = (in0 >> 16); + b[ 3] = (in0 >> 24); + b[ 4] = (in0 >> 32); + b[ 5] = (in0 >> 40); + b[ 6] = (in0 >> 48); + b[ 7] = (in1 >> 0); + b[ 8] = (in1 >> 8); + b[ 9] = (in1 >> 16); + b[10] = (in1 >> 24); + b[11] = (in1 >> 32); + b[12] = (in1 >> 40); + b[13] = (in1 >> 48); + b[14] = (in2 >> 0); + b[15] = (in2 >> 8); + b[16] = (in2 >> 16); + b[17] = (in2 >> 24); + b[18] = (in2 >> 32); + b[19] = (in2 >> 40); + b[20] = (in2 >> 48); + b[21] = (in3 >> 0); + b[22] = (in3 >> 8); + b[23] = (in3 >> 16); + b[24] = (in3 >> 24); + b[25] = (in3 >> 32); + b[26] = (in3 >> 40); + b[27] = (in3 >> 48); + b[28] = (in4 >> 0); + b[29] = (in4 >> 8); + b[30] = (in4 >> 16); + b[31] = (in4 >> 24); + b[32] = (in4 >> 32); + b[33] = (in4 >> 40); + b[34] = (in4 >> 48); + b[35] = (in5 >> 0); + b[36] = (in5 >> 8); + b[37] = (in5 >> 16); + b[38] = (in5 >> 24); + b[39] = (in5 >> 32); + b[40] = (in5 >> 40); + b[41] = (in5 >> 48); + b[42] = (in6 >> 0); + b[43] = (in6 >> 8); + b[44] = (in6 >> 16); + b[45] = (in6 >> 24); + b[46] = (in6 >> 32); + b[47] = (in6 >> 40); + b[48] = (in6 >> 48); + b[49] = (in7 >> 0); + b[50] = (in7 >> 8); + b[51] = (in7 >> 16); + b[52] = (in7 >> 24); + b[53] = (in7 >> 32); + b[54] = (in7 >> 40); + b[55] = (in7 >> 48); +} + +/* Set the field element to 0. + * + * a [in] Field element. + */ +void fe448_1(int64_t* a) +{ + a[0] = 1; + a[1] = 0; + a[2] = 0; + a[3] = 0; + a[4] = 0; + a[5] = 0; + a[6] = 0; + a[7] = 0; +} + +/* Set the field element to 0. + * + * a [in] Field element. + */ +void fe448_0(int64_t* a) +{ + a[0] = 0; + a[1] = 0; + a[2] = 0; + a[3] = 0; + a[4] = 0; + a[5] = 0; + a[6] = 0; + a[7] = 0; +} + +/* Copy one field element into another: d = a. + * + * d [in] Destination field element. + * a [in] Source field element. + */ +void fe448_copy(int64_t* d, const int64_t* a) +{ + d[0] = a[0]; + d[1] = a[1]; + d[2] = a[2]; + d[3] = a[3]; + d[4] = a[4]; + d[5] = a[5]; + d[6] = a[6]; + d[7] = a[7]; +} + +/* Conditionally swap the elements. + * Constant time implementation. + * + * a [in] First field element. + * b [in] Second field element. + * c [in] Swap when 1. Valid values: 0, 1. + */ +static void fe448_cswap(int64_t* a, int64_t* b, int c) +{ + int64_t mask = -(int64_t)c; + int64_t t0 = (a[0] ^ b[0]) & mask; + int64_t t1 = (a[1] ^ b[1]) & mask; + int64_t t2 = (a[2] ^ b[2]) & mask; + int64_t t3 = (a[3] ^ b[3]) & mask; + int64_t t4 = (a[4] ^ b[4]) & mask; + int64_t t5 = (a[5] ^ b[5]) & mask; + int64_t t6 = (a[6] ^ b[6]) & mask; + int64_t t7 = (a[7] ^ b[7]) & mask; + a[0] ^= t0; + a[1] ^= t1; + a[2] ^= t2; + a[3] ^= t3; + a[4] ^= t4; + a[5] ^= t5; + a[6] ^= t6; + a[7] ^= t7; + b[0] ^= t0; + b[1] ^= t1; + b[2] ^= t2; + b[3] ^= t3; + b[4] ^= t4; + b[5] ^= t5; + b[6] ^= t6; + b[7] ^= t7; +} + +/* Add two field elements. r = (a + b) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold sum. + * a [in] Field element to add. + * b [in] Field element to add. + */ +void fe448_add(int64_t* r, const int64_t* a, const int64_t* 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]; +} + +/* Subtract a field element from another. r = (a - b) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold difference. + * a [in] Field element to subtract from. + * b [in] Field element to subtract. + */ +void fe448_sub(int64_t* r, const int64_t* a, const int64_t* 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]; +} + +/* Mulitply a field element by 39081. r = (39081 * a) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold result. + * a [in] Field element to multiply. + */ +void fe448_mul39081(int64_t* r, const int64_t* a) +{ + int128_t t; + int64_t o; + int128_t t0 = a[0] * (int128_t)39081; + int128_t t1 = a[1] * (int128_t)39081; + int128_t t2 = a[2] * (int128_t)39081; + int128_t t3 = a[3] * (int128_t)39081; + int128_t t4 = a[4] * (int128_t)39081; + int128_t t5 = a[5] * (int128_t)39081; + int128_t t6 = a[6] * (int128_t)39081; + int128_t t7 = a[7] * (int128_t)39081; + o = t0 >> 56; t1 += o; t = (int128_t)o << 56; t0 -= t; + o = t1 >> 56; t2 += o; t = (int128_t)o << 56; t1 -= t; + o = t2 >> 56; t3 += o; t = (int128_t)o << 56; t2 -= t; + o = t3 >> 56; t4 += o; t = (int128_t)o << 56; t3 -= t; + o = t4 >> 56; t5 += o; t = (int128_t)o << 56; t4 -= t; + o = t5 >> 56; t6 += o; t = (int128_t)o << 56; t5 -= t; + o = t6 >> 56; t7 += o; t = (int128_t)o << 56; t6 -= t; + o = t7 >> 56; t0 += o; + t4 += o; t = (int128_t)o << 56; t7 -= t; + + /* Store */ + r[0] = t0; + r[1] = t1; + r[2] = t2; + r[3] = t3; + r[4] = t4; + r[5] = t5; + r[6] = t6; + r[7] = t7; +} + +/* Mulitply two field elements. r = (a * b) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold result. + * a [in] Field element to multiply. + * b [in] Field element to multiply. + */ +void fe448_mul(int64_t* r, const int64_t* a, const int64_t* b) +{ + int128_t t; + int64_t o; + int128_t t0 = (int128_t)a[ 0] * b[ 0]; + int128_t t1 = (int128_t)a[ 0] * b[ 1]; + int128_t t101 = (int128_t)a[ 1] * b[ 0]; + int128_t t2 = (int128_t)a[ 0] * b[ 2]; + int128_t t102 = (int128_t)a[ 1] * b[ 1]; + int128_t t202 = (int128_t)a[ 2] * b[ 0]; + int128_t t3 = (int128_t)a[ 0] * b[ 3]; + int128_t t103 = (int128_t)a[ 1] * b[ 2]; + int128_t t203 = (int128_t)a[ 2] * b[ 1]; + int128_t t303 = (int128_t)a[ 3] * b[ 0]; + int128_t t4 = (int128_t)a[ 0] * b[ 4]; + int128_t t104 = (int128_t)a[ 1] * b[ 3]; + int128_t t204 = (int128_t)a[ 2] * b[ 2]; + int128_t t304 = (int128_t)a[ 3] * b[ 1]; + int128_t t404 = (int128_t)a[ 4] * b[ 0]; + int128_t t5 = (int128_t)a[ 0] * b[ 5]; + int128_t t105 = (int128_t)a[ 1] * b[ 4]; + int128_t t205 = (int128_t)a[ 2] * b[ 3]; + int128_t t305 = (int128_t)a[ 3] * b[ 2]; + int128_t t405 = (int128_t)a[ 4] * b[ 1]; + int128_t t505 = (int128_t)a[ 5] * b[ 0]; + int128_t t6 = (int128_t)a[ 0] * b[ 6]; + int128_t t106 = (int128_t)a[ 1] * b[ 5]; + int128_t t206 = (int128_t)a[ 2] * b[ 4]; + int128_t t306 = (int128_t)a[ 3] * b[ 3]; + int128_t t406 = (int128_t)a[ 4] * b[ 2]; + int128_t t506 = (int128_t)a[ 5] * b[ 1]; + int128_t t606 = (int128_t)a[ 6] * b[ 0]; + int128_t t7 = (int128_t)a[ 0] * b[ 7]; + int128_t t107 = (int128_t)a[ 1] * b[ 6]; + int128_t t207 = (int128_t)a[ 2] * b[ 5]; + int128_t t307 = (int128_t)a[ 3] * b[ 4]; + int128_t t407 = (int128_t)a[ 4] * b[ 3]; + int128_t t507 = (int128_t)a[ 5] * b[ 2]; + int128_t t607 = (int128_t)a[ 6] * b[ 1]; + int128_t t707 = (int128_t)a[ 7] * b[ 0]; + int128_t t8 = (int128_t)a[ 1] * b[ 7]; + int128_t t108 = (int128_t)a[ 2] * b[ 6]; + int128_t t208 = (int128_t)a[ 3] * b[ 5]; + int128_t t308 = (int128_t)a[ 4] * b[ 4]; + int128_t t408 = (int128_t)a[ 5] * b[ 3]; + int128_t t508 = (int128_t)a[ 6] * b[ 2]; + int128_t t608 = (int128_t)a[ 7] * b[ 1]; + int128_t t9 = (int128_t)a[ 2] * b[ 7]; + int128_t t109 = (int128_t)a[ 3] * b[ 6]; + int128_t t209 = (int128_t)a[ 4] * b[ 5]; + int128_t t309 = (int128_t)a[ 5] * b[ 4]; + int128_t t409 = (int128_t)a[ 6] * b[ 3]; + int128_t t509 = (int128_t)a[ 7] * b[ 2]; + int128_t t10 = (int128_t)a[ 3] * b[ 7]; + int128_t t110 = (int128_t)a[ 4] * b[ 6]; + int128_t t210 = (int128_t)a[ 5] * b[ 5]; + int128_t t310 = (int128_t)a[ 6] * b[ 4]; + int128_t t410 = (int128_t)a[ 7] * b[ 3]; + int128_t t11 = (int128_t)a[ 4] * b[ 7]; + int128_t t111 = (int128_t)a[ 5] * b[ 6]; + int128_t t211 = (int128_t)a[ 6] * b[ 5]; + int128_t t311 = (int128_t)a[ 7] * b[ 4]; + int128_t t12 = (int128_t)a[ 5] * b[ 7]; + int128_t t112 = (int128_t)a[ 6] * b[ 6]; + int128_t t212 = (int128_t)a[ 7] * b[ 5]; + int128_t t13 = (int128_t)a[ 6] * b[ 7]; + int128_t t113 = (int128_t)a[ 7] * b[ 6]; + int128_t t14 = (int128_t)a[ 7] * b[ 7]; + t1 += t101; + t2 += t102; t2 += t202; + t3 += t103; t3 += t203; t3 += t303; + t4 += t104; t4 += t204; t4 += t304; t4 += t404; + t5 += t105; t5 += t205; t5 += t305; t5 += t405; t5 += t505; + t6 += t106; t6 += t206; t6 += t306; t6 += t406; t6 += t506; + t6 += t606; + t7 += t107; t7 += t207; t7 += t307; t7 += t407; t7 += t507; + t7 += t607; + t7 += t707; + t8 += t108; t8 += t208; t8 += t308; t8 += t408; t8 += t508; + t8 += t608; + t9 += t109; t9 += t209; t9 += t309; t9 += t409; t9 += t509; + t10 += t110; t10 += t210; t10 += t310; t10 += t410; + t11 += t111; t11 += t211; t11 += t311; + t12 += t112; t12 += t212; + t13 += t113; + + /* Reduce */ + t0 += t8 + t12; + t1 += t9 + t13; + t2 += t10 + t14; + t3 += t11; + t4 += t12 + t8 + t12; + t5 += t13 + t9 + t13; + t6 += t14 + t10 + t14; + t7 += t11; + o = t7 >> 56; t0 += o; + t4 += o; t = (int128_t)o << 56; t7 -= t; + o = t0 >> 56; t1 += o; t = (int128_t)o << 56; t0 -= t; + o = t1 >> 56; t2 += o; t = (int128_t)o << 56; t1 -= t; + o = t2 >> 56; t3 += o; t = (int128_t)o << 56; t2 -= t; + o = t3 >> 56; t4 += o; t = (int128_t)o << 56; t3 -= t; + o = t4 >> 56; t5 += o; t = (int128_t)o << 56; t4 -= t; + o = t5 >> 56; t6 += o; t = (int128_t)o << 56; t5 -= t; + o = t6 >> 56; t7 += o; t = (int128_t)o << 56; t6 -= t; + o = t7 >> 56; t0 += o; + t4 += o; t = (int128_t)o << 56; t7 -= t; + + /* Store */ + r[0] = t0; + r[1] = t1; + r[2] = t2; + r[3] = t3; + r[4] = t4; + r[5] = t5; + r[6] = t6; + r[7] = t7; +} + +/* Square a field element. r = (a * a) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold result. + * a [in] Field element to square. + */ +void fe448_sqr(int64_t* r, const int64_t* a) +{ + int128_t t; + int64_t o; + int128_t t0 = (int128_t)a[ 0] * a[ 0]; + int128_t t1 = 2 * (int128_t)a[ 0] * a[ 1]; + int128_t t2 = 2 * (int128_t)a[ 0] * a[ 2]; + int128_t t102 = (int128_t)a[ 1] * a[ 1]; + int128_t t3 = 2 * (int128_t)a[ 0] * a[ 3]; + int128_t t103 = 2 * (int128_t)a[ 1] * a[ 2]; + int128_t t4 = 2 * (int128_t)a[ 0] * a[ 4]; + int128_t t104 = 2 * (int128_t)a[ 1] * a[ 3]; + int128_t t204 = (int128_t)a[ 2] * a[ 2]; + int128_t t5 = 2 * (int128_t)a[ 0] * a[ 5]; + int128_t t105 = 2 * (int128_t)a[ 1] * a[ 4]; + int128_t t205 = 2 * (int128_t)a[ 2] * a[ 3]; + int128_t t6 = 2 * (int128_t)a[ 0] * a[ 6]; + int128_t t106 = 2 * (int128_t)a[ 1] * a[ 5]; + int128_t t206 = 2 * (int128_t)a[ 2] * a[ 4]; + int128_t t306 = (int128_t)a[ 3] * a[ 3]; + int128_t t7 = 2 * (int128_t)a[ 0] * a[ 7]; + int128_t t107 = 2 * (int128_t)a[ 1] * a[ 6]; + int128_t t207 = 2 * (int128_t)a[ 2] * a[ 5]; + int128_t t307 = 2 * (int128_t)a[ 3] * a[ 4]; + int128_t t8 = 2 * (int128_t)a[ 1] * a[ 7]; + int128_t t108 = 2 * (int128_t)a[ 2] * a[ 6]; + int128_t t208 = 2 * (int128_t)a[ 3] * a[ 5]; + int128_t t308 = (int128_t)a[ 4] * a[ 4]; + int128_t t9 = 2 * (int128_t)a[ 2] * a[ 7]; + int128_t t109 = 2 * (int128_t)a[ 3] * a[ 6]; + int128_t t209 = 2 * (int128_t)a[ 4] * a[ 5]; + int128_t t10 = 2 * (int128_t)a[ 3] * a[ 7]; + int128_t t110 = 2 * (int128_t)a[ 4] * a[ 6]; + int128_t t210 = (int128_t)a[ 5] * a[ 5]; + int128_t t11 = 2 * (int128_t)a[ 4] * a[ 7]; + int128_t t111 = 2 * (int128_t)a[ 5] * a[ 6]; + int128_t t12 = 2 * (int128_t)a[ 5] * a[ 7]; + int128_t t112 = (int128_t)a[ 6] * a[ 6]; + int128_t t13 = 2 * (int128_t)a[ 6] * a[ 7]; + int128_t t14 = (int128_t)a[ 7] * a[ 7]; + t2 += t102; + t3 += t103; + t4 += t104; t4 += t204; + t5 += t105; t5 += t205; + t6 += t106; t6 += t206; t6 += t306; + t7 += t107; t7 += t207; t7 += t307; + t8 += t108; t8 += t208; t8 += t308; + t9 += t109; t9 += t209; + t10 += t110; t10 += t210; + t11 += t111; + t12 += t112; + + /* Reduce */ + t0 += t8 + t12; + t1 += t9 + t13; + t2 += t10 + t14; + t3 += t11; + t4 += t12 + t8 + t12; + t5 += t13 + t9 + t13; + t6 += t14 + t10 + t14; + t7 += t11; + o = t7 >> 56; t0 += o; + t4 += o; t = (int128_t)o << 56; t7 -= t; + o = t0 >> 56; t1 += o; t = (int128_t)o << 56; t0 -= t; + o = t1 >> 56; t2 += o; t = (int128_t)o << 56; t1 -= t; + o = t2 >> 56; t3 += o; t = (int128_t)o << 56; t2 -= t; + o = t3 >> 56; t4 += o; t = (int128_t)o << 56; t3 -= t; + o = t4 >> 56; t5 += o; t = (int128_t)o << 56; t4 -= t; + o = t5 >> 56; t6 += o; t = (int128_t)o << 56; t5 -= t; + o = t6 >> 56; t7 += o; t = (int128_t)o << 56; t6 -= t; + o = t7 >> 56; t0 += o; + t4 += o; t = (int128_t)o << 56; t7 -= t; + + /* Store */ + r[0] = t0; + r[1] = t1; + r[2] = t2; + r[3] = t3; + r[4] = t4; + r[5] = t5; + r[6] = t6; + r[7] = t7; +} + +/* Invert the field element. (r * a) mod (2^448 - 2^224 - 1) = 1 + * Constant time implementation - using Fermat's little theorem: + * a^(p-1) mod p = 1 => a^(p-2) mod p = 1/a + * For curve448: p - 2 = 2^448 - 2^224 - 3 + * + * r [in] Field element to hold result. + * a [in] Field element to invert. + */ +void fe448_invert(int64_t* r, const int64_t* a) +{ + int64_t t1[8]; + int64_t t2[8]; + int64_t t3[8]; + int64_t t4[8]; + int i; + + fe448_sqr(t1, a); + /* t1 = 2 */ + fe448_mul(t1, t1, a); + /* t1 = 3 */ + fe448_sqr(t2, t1); for (i = 1; i < 2; ++i) fe448_sqr(t2, t2); + /* t2 = c */ + fe448_mul(t3, t2, a); + /* t3 = d */ + fe448_mul(t1, t2, t1); + /* t1 = f */ + fe448_sqr(t2, t1); + /* t2 = 1e */ + fe448_mul(t4, t2, a); + /* t4 = 1f */ + fe448_sqr(t2, t4); for (i = 1; i < 5; ++i) fe448_sqr(t2, t2); + /* t2 = 3e0 */ + fe448_mul(t1, t2, t4); + /* t1 = 3ff */ + fe448_sqr(t2, t1); for (i = 1; i < 10; ++i) fe448_sqr(t2, t2); + /* t2 = ffc00 */ + fe448_mul(t1, t2, t1); + /* t1 = fffff */ + fe448_sqr(t2, t1); for (i = 1; i < 5; ++i) fe448_sqr(t2, t2); + /* t2 = 1ffffe0 */ + fe448_mul(t1, t2, t4); + /* t1 = 1ffffff */ + fe448_sqr(t2, t1); for (i = 1; i < 25; ++i) fe448_sqr(t2, t2); + /* t2 = 3fffffe000000 */ + fe448_mul(t1, t2, t1); + /* t1 = 3ffffffffffff */ + fe448_sqr(t2, t1); for (i = 1; i < 5; ++i) fe448_sqr(t2, t2); + /* t2 = 7fffffffffffe0 */ + fe448_mul(t1, t2, t4); + /* t1 = 7fffffffffffff */ + fe448_sqr(t2, t1); for (i = 1; i < 55; ++i) fe448_sqr(t2, t2); + /* t2 = 3fffffffffffff80000000000000 */ + fe448_mul(t1, t2, t1); + /* t1 = 3fffffffffffffffffffffffffff */ + fe448_sqr(t2, t1); for (i = 1; i < 110; ++i) fe448_sqr(t2, t2); + /* t2 = fffffffffffffffffffffffffffc000000000000000000000000000 */ + fe448_mul(t1, t2, t1); + /* t1 = fffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + fe448_sqr(t2, t1); for (i = 1; i < 4; ++i) fe448_sqr(t2, t2); + /* t2 = fffffffffffffffffffffffffffffffffffffffffffffffffffffff0 */ + fe448_mul(t3, t3, t2); + /* t3 = fffffffffffffffffffffffffffffffffffffffffffffffffffffffd */ + fe448_mul(t1, t3, a); + /* t1 = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe */ + fe448_sqr(t1, t1); for (i = 1; i < 224; ++i) fe448_sqr(t1, t1); + /* t1 = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000000000000000000000000000000000000000000 */ + fe448_mul(r, t3, t1); + /* r = fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffd */ +} + +/* Scalar multiply the point by a number. r = n.a + * Uses Montogmery ladder and only requires the x-ordinate. + * + * r [in] Field element to hold result. + * n [in] Scalar as an array of bytes. + * a [in] Point to multiply - x-ordinate only. + */ +int curve448(byte* r, const byte* n, const byte* a) +{ + int64_t x1[8]; + int64_t x2[8]; + int64_t z2[8]; + int64_t x3[8]; + int64_t z3[8]; + int64_t t0[8]; + int64_t t1[8]; + int i; + unsigned int swap; + unsigned int b; + + fe448_from_bytes(x1, a); + fe448_1(x2); + fe448_0(z2); + fe448_copy(x3, x1); + fe448_1(z3); + + swap = 0; + for (i = 447; i >= 0; --i) { + b = (n[i >> 3] >> (i & 7)) & 1; + swap ^= b; + fe448_cswap(x2, x3, swap); + fe448_cswap(z2, z3, swap); + swap = b; + + /* Montgomery Ladder - double and add */ + fe448_add(t0, x2, z2); + fe448_reduce(t0); + fe448_add(t1, x3, z3); + fe448_reduce(t1); + fe448_sub(x2, x2, z2); + fe448_sub(x3, x3, z3); + fe448_mul(t1, t1, x2); + fe448_mul(z3, x3, t0); + fe448_sqr(t0, t0); + fe448_sqr(x2, x2); + fe448_add(x3, z3, t1); + fe448_reduce(x3); + fe448_sqr(x3, x3); + fe448_sub(z3, z3, t1); + fe448_sqr(z3, z3); + fe448_mul(z3, z3, x1); + fe448_sub(t1, t0, x2); + fe448_mul(x2, t0, x2); + fe448_mul39081(z2, t1); + fe448_add(z2, t0, z2); + fe448_mul(z2, z2, t1); + } + /* Last two bits are 0 - no final swap check required. */ + + fe448_invert(z2, z2); + fe448_mul(x2, x2, z2); + fe448_to_bytes(r, x2); + + return 0; +} + +#ifdef HAVE_ED448 +/* Check whether field element is not 0. + * Must convert to a normalized form before checking. + * + * a [in] Field element. + * returns 0 when zero, and any other value otherwise. + */ +int fe448_isnonzero(const int64_t* a) +{ + uint8_t b[56]; + int i; + uint8_t c = 0; + fe448_to_bytes(b, a); + for (i = 0; i < 56; i++) + c |= b[i]; + return c; +} + +/* Check whether field element is negative. + * Must convert to a normalized form before checking. + * + * a [in] Field element. + * returns 1 when negative, and 0 otherwise. + */ +int fe448_isnegative(const int64_t* a) +{ + uint8_t b[56]; + fe448_to_bytes(b, a); + return b[0] & 1; +} + +/* Negates the field element. r = -a + * + * r [in] Field element to hold result. + * a [in] Field element. + */ +void fe448_neg(int64_t* r, const int64_t* a) +{ + r[0] = -a[0]; + r[1] = -a[1]; + r[2] = -a[2]; + r[3] = -a[3]; + r[4] = -a[4]; + r[5] = -a[5]; + r[6] = -a[6]; + r[7] = -a[7]; +} + +/* Raise field element to (p-3) / 4: 2^446 - 2^222 - 1 + * Used for calcualting y-ordinate from x-ordinate for Ed448. + * + * r [in] Field element to hold result. + * a [in] Field element to exponentiate. + */ +void fe448_pow_2_446_222_1(int64_t* r, const int64_t* a) +{ + int64_t t1[8]; + int64_t t2[8]; + int64_t t3[8]; + int64_t t4[8]; + int64_t t5[8]; + int i; + + fe448_sqr(t3, a); + /* t3 = 2 */ + fe448_mul(t1, t3, a); + /* t1 = 3 */ + fe448_sqr(t5, t1); + /* t5 = 6 */ + fe448_mul(t5, t5, a); + /* t5 = 7 */ + fe448_sqr(t2, t1); for (i = 1; i < 2; ++i) fe448_sqr(t2, t2); + /* t2 = c */ + fe448_mul(t3, t2, t3); + /* t3 = e */ + fe448_mul(t1, t2, t1); + /* t1 = f */ + fe448_sqr(t2, t1); for (i = 1; i < 3; ++i) fe448_sqr(t2, t2); + /* t2 = 78 */ + fe448_mul(t5, t2, t5); + /* t5 = 7f */ + fe448_sqr(t2, t1); for (i = 1; i < 4; ++i) fe448_sqr(t2, t2); + /* t2 = f0 */ + fe448_mul(t1, t2, t1); + /* t1 = ff */ + fe448_mul(t3, t3, t2); + /* t3 = fe */ + fe448_sqr(t2, t1); for (i = 1; i < 7; ++i) fe448_sqr(t2, t2); + /* t2 = 7f80 */ + fe448_mul(t5, t2, t5); + /* t5 = 7fff */ + fe448_sqr(t2, t1); for (i = 1; i < 8; ++i) fe448_sqr(t2, t2); + /* t2 = ff00 */ + fe448_mul(t1, t2, t1); + /* t1 = ffff */ + fe448_mul(t3, t3, t2); + /* t3 = fffe */ + fe448_sqr(t2, t5); for (i = 1; i < 15; ++i) fe448_sqr(t2, t2); + /* t2 = 3fff8000 */ + fe448_mul(t5, t2, t5); + /* t5 = 3fffffff */ + fe448_sqr(t2, t1); for (i = 1; i < 16; ++i) fe448_sqr(t2, t2); + /* t2 = ffff0000 */ + fe448_mul(t1, t2, t1); + /* t1 = ffffffff */ + fe448_mul(t3, t3, t2); + /* t3 = fffffffe */ + fe448_sqr(t2, t1); for (i = 1; i < 32; ++i) fe448_sqr(t2, t2); + /* t2 = ffffffff00000000 */ + fe448_mul(t2, t2, t1); + /* t2 = ffffffffffffffff */ + fe448_sqr(t1, t2); for (i = 1; i < 64; ++i) fe448_sqr(t1, t1); + /* t1 = ffffffffffffffff0000000000000000 */ + fe448_mul(t1, t1, t2); + /* t1 = ffffffffffffffffffffffffffffffff */ + fe448_sqr(t1, t1); for (i = 1; i < 64; ++i) fe448_sqr(t1, t1); + /* t1 = ffffffffffffffffffffffffffffffff0000000000000000 */ + fe448_mul(t4, t1, t2); + /* t4 = ffffffffffffffffffffffffffffffffffffffffffffffff */ + fe448_sqr(t2, t4); for (i = 1; i < 32; ++i) fe448_sqr(t2, t2); + /* t2 = ffffffffffffffffffffffffffffffffffffffffffffffff00000000 */ + fe448_mul(t3, t3, t2); + /* t3 = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe */ + fe448_sqr(t1, t3); for (i = 1; i < 192; ++i) fe448_sqr(t1, t1); + /* t1 = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000 */ + fe448_mul(t1, t1, t4); + /* t1 = fffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff */ + fe448_sqr(t1, t1); for (i = 1; i < 30; ++i) fe448_sqr(t1, t1); + /* t1 = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffffffffffffffffffffffffffffffffffc0000000 */ + fe448_mul(r, t5, t1); + /* r = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffffffffffffffffffffffffffffffffffffffffff */ +} + +/* 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 fe448_cmov(int64_t* a, const int64_t* b, int c) +{ + int64_t m = -(int64_t)c; + int64_t t0 = m & (a[0] ^ b[0]); + int64_t t1 = m & (a[1] ^ b[1]); + int64_t t2 = m & (a[2] ^ b[2]); + int64_t t3 = m & (a[3] ^ b[3]); + int64_t t4 = m & (a[4] ^ b[4]); + int64_t t5 = m & (a[5] ^ b[5]); + int64_t t6 = m & (a[6] ^ b[6]); + int64_t t7 = m & (a[7] ^ b[7]); + + a[0] ^= t0; + a[1] ^= t1; + a[2] ^= t2; + a[3] ^= t3; + a[4] ^= t4; + a[5] ^= t5; + a[6] ^= t6; + a[7] ^= t7; +} + +#endif /* HAVE_ED448 */ +#else + +/* Initialize the field element operations. + */ +void fe448_init(void) +{ +} + +/* Convert the field element from a byte array to an array of 28-bits. + * + * r [in] Array to encode into. + * b [in] Byte array. + */ +void fe448_from_bytes(int32_t* r, const unsigned char* b) +{ + r[ 0] = (((int32_t)((b[ 0] ) >> 0)) << 0) + | (((int32_t)((b[ 1] ) >> 0)) << 8) + | (((int32_t)((b[ 2] ) >> 0)) << 16) + | ((((int32_t)((b[ 3] & 0xf )) >> 0)) << 24); + r[ 1] = (((int32_t)((b[ 3] ) >> 4)) << 0) + | (((int32_t)((b[ 4] ) >> 0)) << 4) + | (((int32_t)((b[ 5] ) >> 0)) << 12) + | (((int32_t)((b[ 6] ) >> 0)) << 20); + r[ 2] = (((int32_t)((b[ 7] ) >> 0)) << 0) + | (((int32_t)((b[ 8] ) >> 0)) << 8) + | (((int32_t)((b[ 9] ) >> 0)) << 16) + | ((((int32_t)((b[10] & 0xf )) >> 0)) << 24); + r[ 3] = (((int32_t)((b[10] ) >> 4)) << 0) + | (((int32_t)((b[11] ) >> 0)) << 4) + | (((int32_t)((b[12] ) >> 0)) << 12) + | (((int32_t)((b[13] ) >> 0)) << 20); + r[ 4] = (((int32_t)((b[14] ) >> 0)) << 0) + | (((int32_t)((b[15] ) >> 0)) << 8) + | (((int32_t)((b[16] ) >> 0)) << 16) + | ((((int32_t)((b[17] & 0xf )) >> 0)) << 24); + r[ 5] = (((int32_t)((b[17] ) >> 4)) << 0) + | (((int32_t)((b[18] ) >> 0)) << 4) + | (((int32_t)((b[19] ) >> 0)) << 12) + | (((int32_t)((b[20] ) >> 0)) << 20); + r[ 6] = (((int32_t)((b[21] ) >> 0)) << 0) + | (((int32_t)((b[22] ) >> 0)) << 8) + | (((int32_t)((b[23] ) >> 0)) << 16) + | ((((int32_t)((b[24] & 0xf )) >> 0)) << 24); + r[ 7] = (((int32_t)((b[24] ) >> 4)) << 0) + | (((int32_t)((b[25] ) >> 0)) << 4) + | (((int32_t)((b[26] ) >> 0)) << 12) + | (((int32_t)((b[27] ) >> 0)) << 20); + r[ 8] = (((int32_t)((b[28] ) >> 0)) << 0) + | (((int32_t)((b[29] ) >> 0)) << 8) + | (((int32_t)((b[30] ) >> 0)) << 16) + | ((((int32_t)((b[31] & 0xf )) >> 0)) << 24); + r[ 9] = (((int32_t)((b[31] ) >> 4)) << 0) + | (((int32_t)((b[32] ) >> 0)) << 4) + | (((int32_t)((b[33] ) >> 0)) << 12) + | (((int32_t)((b[34] ) >> 0)) << 20); + r[10] = (((int32_t)((b[35] ) >> 0)) << 0) + | (((int32_t)((b[36] ) >> 0)) << 8) + | (((int32_t)((b[37] ) >> 0)) << 16) + | ((((int32_t)((b[38] & 0xf )) >> 0)) << 24); + r[11] = (((int32_t)((b[38] ) >> 4)) << 0) + | (((int32_t)((b[39] ) >> 0)) << 4) + | (((int32_t)((b[40] ) >> 0)) << 12) + | (((int32_t)((b[41] ) >> 0)) << 20); + r[12] = (((int32_t)((b[42] ) >> 0)) << 0) + | (((int32_t)((b[43] ) >> 0)) << 8) + | (((int32_t)((b[44] ) >> 0)) << 16) + | ((((int32_t)((b[45] & 0xf )) >> 0)) << 24); + r[13] = (((int32_t)((b[45] ) >> 4)) << 0) + | (((int32_t)((b[46] ) >> 0)) << 4) + | (((int32_t)((b[47] ) >> 0)) << 12) + | (((int32_t)((b[48] ) >> 0)) << 20); + r[14] = (((int32_t)((b[49] ) >> 0)) << 0) + | (((int32_t)((b[50] ) >> 0)) << 8) + | (((int32_t)((b[51] ) >> 0)) << 16) + | ((((int32_t)((b[52] & 0xf )) >> 0)) << 24); + r[15] = (((int32_t)((b[52] ) >> 4)) << 0) + | (((int32_t)((b[53] ) >> 0)) << 4) + | (((int32_t)((b[54] ) >> 0)) << 12) + | (((int32_t)((b[55] ) >> 0)) << 20); +} + +/* Convert the field element to a byte array from an array of 28-bits. + * + * b [in] Byte array. + * a [in] Array to encode into. + */ +void fe448_to_bytes(unsigned char* b, const int32_t* a) +{ + int64_t t; + /* Mod */ + int32_t in0 = a[0]; + int32_t in1 = a[1]; + int32_t in2 = a[2]; + int32_t in3 = a[3]; + int32_t in4 = a[4]; + int32_t in5 = a[5]; + int32_t in6 = a[6]; + int32_t in7 = a[7]; + int32_t in8 = a[8]; + int32_t in9 = a[9]; + int32_t in10 = a[10]; + int32_t in11 = a[11]; + int32_t in12 = a[12]; + int32_t in13 = a[13]; + int32_t in14 = a[14]; + int32_t in15 = a[15]; + int32_t o = in15 >> 28; + in15 -= o << 28; + in0 += o; + in8 += o; + o = (in0 + 1) >> 28; + o = (o + in1) >> 28; + o = (o + in2) >> 28; + o = (o + in3) >> 28; + o = (o + in4) >> 28; + o = (o + in5) >> 28; + o = (o + in6) >> 28; + o = (o + in7) >> 28; + o = (o + in8 + 1) >> 28; + o = (o + in9) >> 28; + o = (o + in10) >> 28; + o = (o + in11) >> 28; + o = (o + in12) >> 28; + o = (o + in13) >> 28; + o = (o + in14) >> 28; + o = (o + in15) >> 28; + in0 += o; + in8 += o; + in15 -= o << 28; + o = in0 >> 28; in1 += o; t = o << 28; in0 -= t; + o = in1 >> 28; in2 += o; t = o << 28; in1 -= t; + o = in2 >> 28; in3 += o; t = o << 28; in2 -= t; + o = in3 >> 28; in4 += o; t = o << 28; in3 -= t; + o = in4 >> 28; in5 += o; t = o << 28; in4 -= t; + o = in5 >> 28; in6 += o; t = o << 28; in5 -= t; + o = in6 >> 28; in7 += o; t = o << 28; in6 -= t; + o = in7 >> 28; in8 += o; t = o << 28; in7 -= t; + o = in8 >> 28; in9 += o; t = o << 28; in8 -= t; + o = in9 >> 28; in10 += o; t = o << 28; in9 -= t; + o = in10 >> 28; in11 += o; t = o << 28; in10 -= t; + o = in11 >> 28; in12 += o; t = o << 28; in11 -= t; + o = in12 >> 28; in13 += o; t = o << 28; in12 -= t; + o = in13 >> 28; in14 += o; t = o << 28; in13 -= t; + o = in14 >> 28; in15 += o; t = o << 28; in14 -= t; + o = in15 >> 28; in0 += o; + in8 += o; t = o << 28; in15 -= t; + + /* Output as bytes */ + b[ 0] = (in0 >> 0); + b[ 1] = (in0 >> 8); + b[ 2] = (in0 >> 16); + b[ 3] = (in0 >> 24) + ((in1 >> 0) << 4); + b[ 4] = (in1 >> 4); + b[ 5] = (in1 >> 12); + b[ 6] = (in1 >> 20); + b[ 7] = (in2 >> 0); + b[ 8] = (in2 >> 8); + b[ 9] = (in2 >> 16); + b[10] = (in2 >> 24) + ((in3 >> 0) << 4); + b[11] = (in3 >> 4); + b[12] = (in3 >> 12); + b[13] = (in3 >> 20); + b[14] = (in4 >> 0); + b[15] = (in4 >> 8); + b[16] = (in4 >> 16); + b[17] = (in4 >> 24) + ((in5 >> 0) << 4); + b[18] = (in5 >> 4); + b[19] = (in5 >> 12); + b[20] = (in5 >> 20); + b[21] = (in6 >> 0); + b[22] = (in6 >> 8); + b[23] = (in6 >> 16); + b[24] = (in6 >> 24) + ((in7 >> 0) << 4); + b[25] = (in7 >> 4); + b[26] = (in7 >> 12); + b[27] = (in7 >> 20); + b[28] = (in8 >> 0); + b[29] = (in8 >> 8); + b[30] = (in8 >> 16); + b[31] = (in8 >> 24) + ((in9 >> 0) << 4); + b[32] = (in9 >> 4); + b[33] = (in9 >> 12); + b[34] = (in9 >> 20); + b[35] = (in10 >> 0); + b[36] = (in10 >> 8); + b[37] = (in10 >> 16); + b[38] = (in10 >> 24) + ((in11 >> 0) << 4); + b[39] = (in11 >> 4); + b[40] = (in11 >> 12); + b[41] = (in11 >> 20); + b[42] = (in12 >> 0); + b[43] = (in12 >> 8); + b[44] = (in12 >> 16); + b[45] = (in12 >> 24) + ((in13 >> 0) << 4); + b[46] = (in13 >> 4); + b[47] = (in13 >> 12); + b[48] = (in13 >> 20); + b[49] = (in14 >> 0); + b[50] = (in14 >> 8); + b[51] = (in14 >> 16); + b[52] = (in14 >> 24) + ((in15 >> 0) << 4); + b[53] = (in15 >> 4); + b[54] = (in15 >> 12); + b[55] = (in15 >> 20); +} + +/* Set the field element to 0. + * + * a [in] Field element. + */ +void fe448_1(int32_t* a) +{ + a[0] = 1; + a[1] = 0; + a[2] = 0; + a[3] = 0; + a[4] = 0; + a[5] = 0; + a[6] = 0; + a[7] = 0; + a[8] = 0; + a[9] = 0; + a[10] = 0; + a[11] = 0; + a[12] = 0; + a[13] = 0; + a[14] = 0; + a[15] = 0; +} + +/* Set the field element to 0. + * + * a [in] Field element. + */ +void fe448_0(int32_t* a) +{ + a[0] = 0; + a[1] = 0; + a[2] = 0; + a[3] = 0; + a[4] = 0; + a[5] = 0; + a[6] = 0; + a[7] = 0; + a[8] = 0; + a[9] = 0; + a[10] = 0; + a[11] = 0; + a[12] = 0; + a[13] = 0; + a[14] = 0; + a[15] = 0; +} + +/* Copy one field element into another: d = a. + * + * d [in] Destination field element. + * a [in] Source field element. + */ +void fe448_copy(int32_t* d, const int32_t* a) +{ + d[0] = a[0]; + d[1] = a[1]; + d[2] = a[2]; + d[3] = a[3]; + d[4] = a[4]; + d[5] = a[5]; + d[6] = a[6]; + d[7] = a[7]; + d[8] = a[8]; + d[9] = a[9]; + d[10] = a[10]; + d[11] = a[11]; + d[12] = a[12]; + d[13] = a[13]; + d[14] = a[14]; + d[15] = a[15]; +} + +/* Conditionally swap the elements. + * Constant time implementation. + * + * a [in] First field element. + * b [in] Second field element. + * c [in] Swap when 1. Valid values: 0, 1. + */ +static void fe448_cswap(int32_t* a, int32_t* b, int c) +{ + int32_t mask = -(int32_t)c; + int32_t t0 = (a[0] ^ b[0]) & mask; + int32_t t1 = (a[1] ^ b[1]) & mask; + int32_t t2 = (a[2] ^ b[2]) & mask; + int32_t t3 = (a[3] ^ b[3]) & mask; + int32_t t4 = (a[4] ^ b[4]) & mask; + int32_t t5 = (a[5] ^ b[5]) & mask; + int32_t t6 = (a[6] ^ b[6]) & mask; + int32_t t7 = (a[7] ^ b[7]) & mask; + int32_t t8 = (a[8] ^ b[8]) & mask; + int32_t t9 = (a[9] ^ b[9]) & mask; + int32_t t10 = (a[10] ^ b[10]) & mask; + int32_t t11 = (a[11] ^ b[11]) & mask; + int32_t t12 = (a[12] ^ b[12]) & mask; + int32_t t13 = (a[13] ^ b[13]) & mask; + int32_t t14 = (a[14] ^ b[14]) & mask; + int32_t t15 = (a[15] ^ b[15]) & mask; + a[0] ^= t0; + a[1] ^= t1; + a[2] ^= t2; + a[3] ^= t3; + a[4] ^= t4; + a[5] ^= t5; + a[6] ^= t6; + a[7] ^= t7; + a[8] ^= t8; + a[9] ^= t9; + a[10] ^= t10; + a[11] ^= t11; + a[12] ^= t12; + a[13] ^= t13; + a[14] ^= t14; + a[15] ^= t15; + b[0] ^= t0; + b[1] ^= t1; + b[2] ^= t2; + b[3] ^= t3; + b[4] ^= t4; + b[5] ^= t5; + b[6] ^= t6; + b[7] ^= t7; + b[8] ^= t8; + b[9] ^= t9; + b[10] ^= t10; + b[11] ^= t11; + b[12] ^= t12; + b[13] ^= t13; + b[14] ^= t14; + b[15] ^= t15; +} + +/* Add two field elements. r = (a + b) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold sum. + * a [in] Field element to add. + * b [in] Field element to add. + */ +void fe448_add(int32_t* r, const int32_t* a, const int32_t* 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]; + r[10] = a[10] + b[10]; + r[11] = a[11] + b[11]; + r[12] = a[12] + b[12]; + r[13] = a[13] + b[13]; + r[14] = a[14] + b[14]; + r[15] = a[15] + b[15]; +} + +/* Subtract a field element from another. r = (a - b) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold difference. + * a [in] Field element to subtract from. + * b [in] Field element to subtract. + */ +void fe448_sub(int32_t* r, const int32_t* a, const int32_t* 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]; + r[10] = a[10] - b[10]; + r[11] = a[11] - b[11]; + r[12] = a[12] - b[12]; + r[13] = a[13] - b[13]; + r[14] = a[14] - b[14]; + r[15] = a[15] - b[15]; +} + +void fe448_reduce(int32_t* a) +{ + int64_t o; + + o = a[0 ] >> 28; a[1 ] += o; a[0 ] -= o << 28; + o = a[1 ] >> 28; a[2 ] += o; a[1 ] -= o << 28; + o = a[2 ] >> 28; a[3 ] += o; a[2 ] -= o << 28; + o = a[3 ] >> 28; a[4 ] += o; a[3 ] -= o << 28; + o = a[4 ] >> 28; a[5 ] += o; a[4 ] -= o << 28; + o = a[5 ] >> 28; a[6 ] += o; a[5 ] -= o << 28; + o = a[6 ] >> 28; a[7 ] += o; a[6 ] -= o << 28; + o = a[7 ] >> 28; a[8 ] += o; a[7 ] -= o << 28; + o = a[8 ] >> 28; a[9 ] += o; a[8 ] -= o << 28; + o = a[9 ] >> 28; a[10] += o; a[9 ] -= o << 28; + o = a[10] >> 28; a[11] += o; a[10] -= o << 28; + o = a[11] >> 28; a[12] += o; a[11] -= o << 28; + o = a[12] >> 28; a[13] += o; a[12] -= o << 28; + o = a[13] >> 28; a[14] += o; a[13] -= o << 28; + o = a[14] >> 28; a[15] += o; a[14] -= o << 28; + o = a[15] >> 28; a[0] += o; + a[8] += o; a[15] -= o << 28; +} +/* Mulitply a field element by 39081. r = (39081 * a) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold result. + * a [in] Field element to multiply. + */ +void fe448_mul39081(int32_t* r, const int32_t* a) +{ + int64_t t; + int32_t o; + int64_t t0 = a[0] * (int64_t)39081; + int64_t t1 = a[1] * (int64_t)39081; + int64_t t2 = a[2] * (int64_t)39081; + int64_t t3 = a[3] * (int64_t)39081; + int64_t t4 = a[4] * (int64_t)39081; + int64_t t5 = a[5] * (int64_t)39081; + int64_t t6 = a[6] * (int64_t)39081; + int64_t t7 = a[7] * (int64_t)39081; + int64_t t8 = a[8] * (int64_t)39081; + int64_t t9 = a[9] * (int64_t)39081; + int64_t t10 = a[10] * (int64_t)39081; + int64_t t11 = a[11] * (int64_t)39081; + int64_t t12 = a[12] * (int64_t)39081; + int64_t t13 = a[13] * (int64_t)39081; + int64_t t14 = a[14] * (int64_t)39081; + int64_t t15 = a[15] * (int64_t)39081; + o = t0 >> 28; t1 += o; t = (int64_t)o << 28; t0 -= t; + o = t1 >> 28; t2 += o; t = (int64_t)o << 28; t1 -= t; + o = t2 >> 28; t3 += o; t = (int64_t)o << 28; t2 -= t; + o = t3 >> 28; t4 += o; t = (int64_t)o << 28; t3 -= t; + o = t4 >> 28; t5 += o; t = (int64_t)o << 28; t4 -= t; + o = t5 >> 28; t6 += o; t = (int64_t)o << 28; t5 -= t; + o = t6 >> 28; t7 += o; t = (int64_t)o << 28; t6 -= t; + o = t7 >> 28; t8 += o; t = (int64_t)o << 28; t7 -= t; + o = t8 >> 28; t9 += o; t = (int64_t)o << 28; t8 -= t; + o = t9 >> 28; t10 += o; t = (int64_t)o << 28; t9 -= t; + o = t10 >> 28; t11 += o; t = (int64_t)o << 28; t10 -= t; + o = t11 >> 28; t12 += o; t = (int64_t)o << 28; t11 -= t; + o = t12 >> 28; t13 += o; t = (int64_t)o << 28; t12 -= t; + o = t13 >> 28; t14 += o; t = (int64_t)o << 28; t13 -= t; + o = t14 >> 28; t15 += o; t = (int64_t)o << 28; t14 -= t; + o = t15 >> 28; t0 += o; + t8 += o; t = (int64_t)o << 28; t15 -= t; + + /* Store */ + r[0] = t0; + r[1] = t1; + r[2] = t2; + r[3] = t3; + r[4] = t4; + r[5] = t5; + r[6] = t6; + r[7] = t7; + r[8] = t8; + r[9] = t9; + r[10] = t10; + r[11] = t11; + r[12] = t12; + r[13] = t13; + r[14] = t14; + r[15] = t15; +} + +/* Mulitply two field elements. r = a * b + * + * r [in] Field element to hold result. + * a [in] Field element to multiply. + * b [in] Field element to multiply. + */ +static WC_INLINE void fe448_mul_8(int32_t* r, const int32_t* a, const int32_t* b) +{ + int64_t t; + int64_t t0 = (int64_t)a[ 0] * b[ 0]; + int64_t t1 = (int64_t)a[ 0] * b[ 1]; + int64_t t101 = (int64_t)a[ 1] * b[ 0]; + int64_t t2 = (int64_t)a[ 0] * b[ 2]; + int64_t t102 = (int64_t)a[ 1] * b[ 1]; + int64_t t202 = (int64_t)a[ 2] * b[ 0]; + int64_t t3 = (int64_t)a[ 0] * b[ 3]; + int64_t t103 = (int64_t)a[ 1] * b[ 2]; + int64_t t203 = (int64_t)a[ 2] * b[ 1]; + int64_t t303 = (int64_t)a[ 3] * b[ 0]; + int64_t t4 = (int64_t)a[ 0] * b[ 4]; + int64_t t104 = (int64_t)a[ 1] * b[ 3]; + int64_t t204 = (int64_t)a[ 2] * b[ 2]; + int64_t t304 = (int64_t)a[ 3] * b[ 1]; + int64_t t404 = (int64_t)a[ 4] * b[ 0]; + int64_t t5 = (int64_t)a[ 0] * b[ 5]; + int64_t t105 = (int64_t)a[ 1] * b[ 4]; + int64_t t205 = (int64_t)a[ 2] * b[ 3]; + int64_t t305 = (int64_t)a[ 3] * b[ 2]; + int64_t t405 = (int64_t)a[ 4] * b[ 1]; + int64_t t505 = (int64_t)a[ 5] * b[ 0]; + int64_t t6 = (int64_t)a[ 0] * b[ 6]; + int64_t t106 = (int64_t)a[ 1] * b[ 5]; + int64_t t206 = (int64_t)a[ 2] * b[ 4]; + int64_t t306 = (int64_t)a[ 3] * b[ 3]; + int64_t t406 = (int64_t)a[ 4] * b[ 2]; + int64_t t506 = (int64_t)a[ 5] * b[ 1]; + int64_t t606 = (int64_t)a[ 6] * b[ 0]; + int64_t t7 = (int64_t)a[ 0] * b[ 7]; + int64_t t107 = (int64_t)a[ 1] * b[ 6]; + int64_t t207 = (int64_t)a[ 2] * b[ 5]; + int64_t t307 = (int64_t)a[ 3] * b[ 4]; + int64_t t407 = (int64_t)a[ 4] * b[ 3]; + int64_t t507 = (int64_t)a[ 5] * b[ 2]; + int64_t t607 = (int64_t)a[ 6] * b[ 1]; + int64_t t707 = (int64_t)a[ 7] * b[ 0]; + int64_t t8 = (int64_t)a[ 1] * b[ 7]; + int64_t t108 = (int64_t)a[ 2] * b[ 6]; + int64_t t208 = (int64_t)a[ 3] * b[ 5]; + int64_t t308 = (int64_t)a[ 4] * b[ 4]; + int64_t t408 = (int64_t)a[ 5] * b[ 3]; + int64_t t508 = (int64_t)a[ 6] * b[ 2]; + int64_t t608 = (int64_t)a[ 7] * b[ 1]; + int64_t t9 = (int64_t)a[ 2] * b[ 7]; + int64_t t109 = (int64_t)a[ 3] * b[ 6]; + int64_t t209 = (int64_t)a[ 4] * b[ 5]; + int64_t t309 = (int64_t)a[ 5] * b[ 4]; + int64_t t409 = (int64_t)a[ 6] * b[ 3]; + int64_t t509 = (int64_t)a[ 7] * b[ 2]; + int64_t t10 = (int64_t)a[ 3] * b[ 7]; + int64_t t110 = (int64_t)a[ 4] * b[ 6]; + int64_t t210 = (int64_t)a[ 5] * b[ 5]; + int64_t t310 = (int64_t)a[ 6] * b[ 4]; + int64_t t410 = (int64_t)a[ 7] * b[ 3]; + int64_t t11 = (int64_t)a[ 4] * b[ 7]; + int64_t t111 = (int64_t)a[ 5] * b[ 6]; + int64_t t211 = (int64_t)a[ 6] * b[ 5]; + int64_t t311 = (int64_t)a[ 7] * b[ 4]; + int64_t t12 = (int64_t)a[ 5] * b[ 7]; + int64_t t112 = (int64_t)a[ 6] * b[ 6]; + int64_t t212 = (int64_t)a[ 7] * b[ 5]; + int64_t t13 = (int64_t)a[ 6] * b[ 7]; + int64_t t113 = (int64_t)a[ 7] * b[ 6]; + int64_t t14 = (int64_t)a[ 7] * b[ 7]; + t1 += t101; + t2 += t102; t2 += t202; + t3 += t103; t3 += t203; t3 += t303; + t4 += t104; t4 += t204; t4 += t304; t4 += t404; + t5 += t105; t5 += t205; t5 += t305; t5 += t405; t5 += t505; + t6 += t106; t6 += t206; t6 += t306; t6 += t406; t6 += t506; + t6 += t606; + t7 += t107; t7 += t207; t7 += t307; t7 += t407; t7 += t507; + t7 += t607; + t7 += t707; + t8 += t108; t8 += t208; t8 += t308; t8 += t408; t8 += t508; + t8 += t608; + t9 += t109; t9 += t209; t9 += t309; t9 += t409; t9 += t509; + t10 += t110; t10 += t210; t10 += t310; t10 += t410; + t11 += t111; t11 += t211; t11 += t311; + t12 += t112; t12 += t212; + t13 += t113; + int64_t o = t14 >> 28; + int64_t t15 = o; + t14 -= o << 28; + o = t0 >> 28; t1 += o; t = (int64_t)o << 28; t0 -= t; + o = t1 >> 28; t2 += o; t = (int64_t)o << 28; t1 -= t; + o = t2 >> 28; t3 += o; t = (int64_t)o << 28; t2 -= t; + o = t3 >> 28; t4 += o; t = (int64_t)o << 28; t3 -= t; + o = t4 >> 28; t5 += o; t = (int64_t)o << 28; t4 -= t; + o = t5 >> 28; t6 += o; t = (int64_t)o << 28; t5 -= t; + o = t6 >> 28; t7 += o; t = (int64_t)o << 28; t6 -= t; + o = t7 >> 28; t8 += o; t = (int64_t)o << 28; t7 -= t; + o = t8 >> 28; t9 += o; t = (int64_t)o << 28; t8 -= t; + o = t9 >> 28; t10 += o; t = (int64_t)o << 28; t9 -= t; + o = t10 >> 28; t11 += o; t = (int64_t)o << 28; t10 -= t; + o = t11 >> 28; t12 += o; t = (int64_t)o << 28; t11 -= t; + o = t12 >> 28; t13 += o; t = (int64_t)o << 28; t12 -= t; + o = t13 >> 28; t14 += o; t = (int64_t)o << 28; t13 -= t; + o = t14 >> 28; t15 += o; t = (int64_t)o << 28; t14 -= t; + o = t15 >> 28; t0 += o; + t8 += o; t = (int64_t)o << 28; t15 -= t; + + /* Store */ + r[0] = t0; + r[1] = t1; + r[2] = t2; + r[3] = t3; + r[4] = t4; + r[5] = t5; + r[6] = t6; + r[7] = t7; + r[8] = t8; + r[9] = t9; + r[10] = t10; + r[11] = t11; + r[12] = t12; + r[13] = t13; + r[14] = t14; + r[15] = t15; +} + +/* Mulitply two field elements. r = (a * b) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold result. + * a [in] Field element to multiply. + * b [in] Field element to multiply. + */ +void fe448_mul(int32_t* r, const int32_t* a, const int32_t* b) +{ + int32_t r0[16]; + int32_t r1[16]; + int32_t* a1 = r1; + int32_t b1[8]; + int32_t r2[16]; + a1[0] = a[0] + a[8]; + a1[1] = a[1] + a[9]; + a1[2] = a[2] + a[10]; + a1[3] = a[3] + a[11]; + a1[4] = a[4] + a[12]; + a1[5] = a[5] + a[13]; + a1[6] = a[6] + a[14]; + a1[7] = a[7] + a[15]; + b1[0] = b[0] + b[8]; + b1[1] = b[1] + b[9]; + b1[2] = b[2] + b[10]; + b1[3] = b[3] + b[11]; + b1[4] = b[4] + b[12]; + b1[5] = b[5] + b[13]; + b1[6] = b[6] + b[14]; + b1[7] = b[7] + b[15]; + fe448_mul_8(r2, a + 8, b + 8); + fe448_mul_8(r0, a, b); + fe448_mul_8(r1, a1, b1); + r[ 0] = r0[ 0] + r2[ 0] + r1[ 8] - r0[ 8]; + r[ 1] = r0[ 1] + r2[ 1] + r1[ 9] - r0[ 9]; + r[ 2] = r0[ 2] + r2[ 2] + r1[10] - r0[10]; + r[ 3] = r0[ 3] + r2[ 3] + r1[11] - r0[11]; + r[ 4] = r0[ 4] + r2[ 4] + r1[12] - r0[12]; + r[ 5] = r0[ 5] + r2[ 5] + r1[13] - r0[13]; + r[ 6] = r0[ 6] + r2[ 6] + r1[14] - r0[14]; + r[ 7] = r0[ 7] + r2[ 7] + r1[15] - r0[15]; + r[ 8] = r2[ 8] + r1[ 0] - r0[ 0] + r1[ 8]; + r[ 9] = r2[ 9] + r1[ 1] - r0[ 1] + r1[ 9]; + r[10] = r2[10] + r1[ 2] - r0[ 2] + r1[10]; + r[11] = r2[11] + r1[ 3] - r0[ 3] + r1[11]; + r[12] = r2[12] + r1[ 4] - r0[ 4] + r1[12]; + r[13] = r2[13] + r1[ 5] - r0[ 5] + r1[13]; + r[14] = r2[14] + r1[ 6] - r0[ 6] + r1[14]; + r[15] = r2[15] + r1[ 7] - r0[ 7] + r1[15]; +} + +/* Square a field element. r = a * a + * + * r [in] Field element to hold result. + * a [in] Field element to square. + */ +static WC_INLINE void fe448_sqr_8(int32_t* r, const int32_t* a) +{ + int64_t t; + int64_t t0 = (int64_t)a[ 0] * a[ 0]; + int64_t t1 = 2 * (int64_t)a[ 0] * a[ 1]; + int64_t t2 = 2 * (int64_t)a[ 0] * a[ 2]; + int64_t t102 = (int64_t)a[ 1] * a[ 1]; + int64_t t3 = 2 * (int64_t)a[ 0] * a[ 3]; + int64_t t103 = 2 * (int64_t)a[ 1] * a[ 2]; + int64_t t4 = 2 * (int64_t)a[ 0] * a[ 4]; + int64_t t104 = 2 * (int64_t)a[ 1] * a[ 3]; + int64_t t204 = (int64_t)a[ 2] * a[ 2]; + int64_t t5 = 2 * (int64_t)a[ 0] * a[ 5]; + int64_t t105 = 2 * (int64_t)a[ 1] * a[ 4]; + int64_t t205 = 2 * (int64_t)a[ 2] * a[ 3]; + int64_t t6 = 2 * (int64_t)a[ 0] * a[ 6]; + int64_t t106 = 2 * (int64_t)a[ 1] * a[ 5]; + int64_t t206 = 2 * (int64_t)a[ 2] * a[ 4]; + int64_t t306 = (int64_t)a[ 3] * a[ 3]; + int64_t t7 = 2 * (int64_t)a[ 0] * a[ 7]; + int64_t t107 = 2 * (int64_t)a[ 1] * a[ 6]; + int64_t t207 = 2 * (int64_t)a[ 2] * a[ 5]; + int64_t t307 = 2 * (int64_t)a[ 3] * a[ 4]; + int64_t t8 = 2 * (int64_t)a[ 1] * a[ 7]; + int64_t t108 = 2 * (int64_t)a[ 2] * a[ 6]; + int64_t t208 = 2 * (int64_t)a[ 3] * a[ 5]; + int64_t t308 = (int64_t)a[ 4] * a[ 4]; + int64_t t9 = 2 * (int64_t)a[ 2] * a[ 7]; + int64_t t109 = 2 * (int64_t)a[ 3] * a[ 6]; + int64_t t209 = 2 * (int64_t)a[ 4] * a[ 5]; + int64_t t10 = 2 * (int64_t)a[ 3] * a[ 7]; + int64_t t110 = 2 * (int64_t)a[ 4] * a[ 6]; + int64_t t210 = (int64_t)a[ 5] * a[ 5]; + int64_t t11 = 2 * (int64_t)a[ 4] * a[ 7]; + int64_t t111 = 2 * (int64_t)a[ 5] * a[ 6]; + int64_t t12 = 2 * (int64_t)a[ 5] * a[ 7]; + int64_t t112 = (int64_t)a[ 6] * a[ 6]; + int64_t t13 = 2 * (int64_t)a[ 6] * a[ 7]; + int64_t t14 = (int64_t)a[ 7] * a[ 7]; + t2 += t102; + t3 += t103; + t4 += t104; t4 += t204; + t5 += t105; t5 += t205; + t6 += t106; t6 += t206; t6 += t306; + t7 += t107; t7 += t207; t7 += t307; + t8 += t108; t8 += t208; t8 += t308; + t9 += t109; t9 += t209; + t10 += t110; t10 += t210; + t11 += t111; + t12 += t112; + int64_t o = t14 >> 28; + int64_t t15 = o; + t14 -= o << 28; + o = t0 >> 28; t1 += o; t = (int64_t)o << 28; t0 -= t; + o = t1 >> 28; t2 += o; t = (int64_t)o << 28; t1 -= t; + o = t2 >> 28; t3 += o; t = (int64_t)o << 28; t2 -= t; + o = t3 >> 28; t4 += o; t = (int64_t)o << 28; t3 -= t; + o = t4 >> 28; t5 += o; t = (int64_t)o << 28; t4 -= t; + o = t5 >> 28; t6 += o; t = (int64_t)o << 28; t5 -= t; + o = t6 >> 28; t7 += o; t = (int64_t)o << 28; t6 -= t; + o = t7 >> 28; t8 += o; t = (int64_t)o << 28; t7 -= t; + o = t8 >> 28; t9 += o; t = (int64_t)o << 28; t8 -= t; + o = t9 >> 28; t10 += o; t = (int64_t)o << 28; t9 -= t; + o = t10 >> 28; t11 += o; t = (int64_t)o << 28; t10 -= t; + o = t11 >> 28; t12 += o; t = (int64_t)o << 28; t11 -= t; + o = t12 >> 28; t13 += o; t = (int64_t)o << 28; t12 -= t; + o = t13 >> 28; t14 += o; t = (int64_t)o << 28; t13 -= t; + o = t14 >> 28; t15 += o; t = (int64_t)o << 28; t14 -= t; + o = t15 >> 28; t0 += o; + t8 += o; t = (int64_t)o << 28; t15 -= t; + + /* Store */ + r[0] = t0; + r[1] = t1; + r[2] = t2; + r[3] = t3; + r[4] = t4; + r[5] = t5; + r[6] = t6; + r[7] = t7; + r[8] = t8; + r[9] = t9; + r[10] = t10; + r[11] = t11; + r[12] = t12; + r[13] = t13; + r[14] = t14; + r[15] = t15; +} + +/* Square a field element. r = (a * a) mod (2^448 - 2^224 - 1) + * + * r [in] Field element to hold result. + * a [in] Field element to square. + */ +void fe448_sqr(int32_t* r, const int32_t* a) +{ + int32_t r0[16]; + int32_t r1[16]; + int32_t* a1 = r1; + int32_t r2[16]; + a1[0] = a[0] + a[8]; + a1[1] = a[1] + a[9]; + a1[2] = a[2] + a[10]; + a1[3] = a[3] + a[11]; + a1[4] = a[4] + a[12]; + a1[5] = a[5] + a[13]; + a1[6] = a[6] + a[14]; + a1[7] = a[7] + a[15]; + fe448_sqr_8(r2, a + 8); + fe448_sqr_8(r0, a); + fe448_sqr_8(r1, a1); + r[ 0] = r0[ 0] + r2[ 0] + r1[ 8] - r0[ 8]; + r[ 1] = r0[ 1] + r2[ 1] + r1[ 9] - r0[ 9]; + r[ 2] = r0[ 2] + r2[ 2] + r1[10] - r0[10]; + r[ 3] = r0[ 3] + r2[ 3] + r1[11] - r0[11]; + r[ 4] = r0[ 4] + r2[ 4] + r1[12] - r0[12]; + r[ 5] = r0[ 5] + r2[ 5] + r1[13] - r0[13]; + r[ 6] = r0[ 6] + r2[ 6] + r1[14] - r0[14]; + r[ 7] = r0[ 7] + r2[ 7] + r1[15] - r0[15]; + r[ 8] = r2[ 8] + r1[ 0] - r0[ 0] + r1[ 8]; + r[ 9] = r2[ 9] + r1[ 1] - r0[ 1] + r1[ 9]; + r[10] = r2[10] + r1[ 2] - r0[ 2] + r1[10]; + r[11] = r2[11] + r1[ 3] - r0[ 3] + r1[11]; + r[12] = r2[12] + r1[ 4] - r0[ 4] + r1[12]; + r[13] = r2[13] + r1[ 5] - r0[ 5] + r1[13]; + r[14] = r2[14] + r1[ 6] - r0[ 6] + r1[14]; + r[15] = r2[15] + r1[ 7] - r0[ 7] + r1[15]; +} + +/* Invert the field element. (r * a) mod (2^448 - 2^224 - 1) = 1 + * Constant time implementation - using Fermat's little theorem: + * a^(p-1) mod p = 1 => a^(p-2) mod p = 1/a + * For curve448: p - 2 = 2^448 - 2^224 - 3 + * + * r [in] Field element to hold result. + * a [in] Field element to invert. + */ +void fe448_invert(int32_t* r, const int32_t* a) +{ + int32_t t1[16]; + int32_t t2[16]; + int32_t t3[16]; + int32_t t4[16]; + int i; + + fe448_sqr(t1, a); + /* t1 = 2 */ + fe448_mul(t1, t1, a); + /* t1 = 3 */ + fe448_sqr(t2, t1); for (i = 1; i < 2; ++i) fe448_sqr(t2, t2); + /* t2 = c */ + fe448_mul(t3, t2, a); + /* t3 = d */ + fe448_mul(t1, t2, t1); + /* t1 = f */ + fe448_sqr(t2, t1); + /* t2 = 1e */ + fe448_mul(t4, t2, a); + /* t4 = 1f */ + fe448_sqr(t2, t4); for (i = 1; i < 5; ++i) fe448_sqr(t2, t2); + /* t2 = 3e0 */ + fe448_mul(t1, t2, t4); + /* t1 = 3ff */ + fe448_sqr(t2, t1); for (i = 1; i < 10; ++i) fe448_sqr(t2, t2); + /* t2 = ffc00 */ + fe448_mul(t1, t2, t1); + /* t1 = fffff */ + fe448_sqr(t2, t1); for (i = 1; i < 5; ++i) fe448_sqr(t2, t2); + /* t2 = 1ffffe0 */ + fe448_mul(t1, t2, t4); + /* t1 = 1ffffff */ + fe448_sqr(t2, t1); for (i = 1; i < 25; ++i) fe448_sqr(t2, t2); + /* t2 = 3fffffe000000 */ + fe448_mul(t1, t2, t1); + /* t1 = 3ffffffffffff */ + fe448_sqr(t2, t1); for (i = 1; i < 5; ++i) fe448_sqr(t2, t2); + /* t2 = 7fffffffffffe0 */ + fe448_mul(t1, t2, t4); + /* t1 = 7fffffffffffff */ + fe448_sqr(t2, t1); for (i = 1; i < 55; ++i) fe448_sqr(t2, t2); + /* t2 = 3fffffffffffff80000000000000 */ + fe448_mul(t1, t2, t1); + /* t1 = 3fffffffffffffffffffffffffff */ + fe448_sqr(t2, t1); for (i = 1; i < 110; ++i) fe448_sqr(t2, t2); + /* t2 = fffffffffffffffffffffffffffc000000000000000000000000000 */ + fe448_mul(t1, t2, t1); + /* t1 = fffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + fe448_sqr(t2, t1); for (i = 1; i < 4; ++i) fe448_sqr(t2, t2); + /* t2 = fffffffffffffffffffffffffffffffffffffffffffffffffffffff0 */ + fe448_mul(t3, t3, t2); + /* t3 = fffffffffffffffffffffffffffffffffffffffffffffffffffffffd */ + fe448_mul(t1, t3, a); + /* t1 = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe */ + fe448_sqr(t1, t1); for (i = 1; i < 224; ++i) fe448_sqr(t1, t1); + /* t1 = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000000000000000000000000000000000000000000 */ + fe448_mul(r, t3, t1); + /* r = fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffd */ +} + +/* Scalar multiply the point by a number. r = n.a + * Uses Montogmery ladder and only requires the x-ordinate. + * + * r [in] Field element to hold result. + * n [in] Scalar as an array of bytes. + * a [in] Point to multiply - x-ordinate only. + */ +int curve448(byte* r, const byte* n, const byte* a) +{ + int32_t x1[16]; + int32_t x2[16]; + int32_t z2[16]; + int32_t x3[16]; + int32_t z3[16]; + int32_t t0[16]; + int32_t t1[16]; + int i; + unsigned int swap; + unsigned int b; + + fe448_from_bytes(x1, a); + fe448_1(x2); + fe448_0(z2); + fe448_copy(x3, x1); + fe448_1(z3); + + swap = 0; + for (i = 447; i >= 0; --i) { + b = (n[i >> 3] >> (i & 7)) & 1; + swap ^= b; + fe448_cswap(x2, x3, swap); + fe448_cswap(z2, z3, swap); + swap = b; + + /* Montgomery Ladder - double and add */ + fe448_add(t0, x2, z2); + fe448_reduce(t0); + fe448_add(t1, x3, z3); + fe448_reduce(t1); + fe448_sub(x2, x2, z2); + fe448_sub(x3, x3, z3); + fe448_mul(t1, t1, x2); + fe448_mul(z3, x3, t0); + fe448_sqr(t0, t0); + fe448_sqr(x2, x2); + fe448_add(x3, z3, t1); + fe448_reduce(x3); + fe448_sqr(x3, x3); + fe448_sub(z3, z3, t1); + fe448_sqr(z3, z3); + fe448_mul(z3, z3, x1); + fe448_sub(t1, t0, x2); + fe448_mul(x2, t0, x2); + fe448_mul39081(z2, t1); + fe448_add(z2, t0, z2); + fe448_mul(z2, z2, t1); + } + /* Last two bits are 0 - no final swap check required. */ + + fe448_invert(z2, z2); + fe448_mul(x2, x2, z2); + fe448_to_bytes(r, x2); + + return 0; +} + +#ifdef HAVE_ED448 +/* Check whether field element is not 0. + * Must convert to a normalized form before checking. + * + * a [in] Field element. + * returns 0 when zero, and any other value otherwise. + */ +int fe448_isnonzero(const int32_t* a) +{ + uint8_t b[56]; + int i; + uint8_t c = 0; + fe448_to_bytes(b, a); + for (i = 0; i < 56; i++) + c |= b[i]; + return c; +} + +/* Check whether field element is negative. + * Must convert to a normalized form before checking. + * + * a [in] Field element. + * returns 1 when negative, and 0 otherwise. + */ +int fe448_isnegative(const int32_t* a) +{ + uint8_t b[56]; + fe448_to_bytes(b, a); + return b[0] & 1; +} + +/* Negates the field element. r = -a + * + * r [in] Field element to hold result. + * a [in] Field element. + */ +void fe448_neg(int32_t* r, const int32_t* a) +{ + r[0] = -a[0]; + r[1] = -a[1]; + r[2] = -a[2]; + r[3] = -a[3]; + r[4] = -a[4]; + r[5] = -a[5]; + r[6] = -a[6]; + r[7] = -a[7]; + r[8] = -a[8]; + r[9] = -a[9]; + r[10] = -a[10]; + r[11] = -a[11]; + r[12] = -a[12]; + r[13] = -a[13]; + r[14] = -a[14]; + r[15] = -a[15]; +} + +/* Raise field element to (p-3) / 4: 2^446 - 2^222 - 1 + * Used for calcualting y-ordinate from x-ordinate for Ed448. + * + * r [in] Field element to hold result. + * a [in] Field element to exponentiate. + */ +void fe448_pow_2_446_222_1(int32_t* r, const int32_t* a) +{ + int32_t t1[16]; + int32_t t2[16]; + int32_t t3[16]; + int32_t t4[16]; + int32_t t5[16]; + int i; + + fe448_sqr(t3, a); + /* t3 = 2 */ + fe448_mul(t1, t3, a); + /* t1 = 3 */ + fe448_sqr(t5, t1); + /* t5 = 6 */ + fe448_mul(t5, t5, a); + /* t5 = 7 */ + fe448_sqr(t2, t1); for (i = 1; i < 2; ++i) fe448_sqr(t2, t2); + /* t2 = c */ + fe448_mul(t3, t2, t3); + /* t3 = e */ + fe448_mul(t1, t2, t1); + /* t1 = f */ + fe448_sqr(t2, t1); for (i = 1; i < 3; ++i) fe448_sqr(t2, t2); + /* t2 = 78 */ + fe448_mul(t5, t2, t5); + /* t5 = 7f */ + fe448_sqr(t2, t1); for (i = 1; i < 4; ++i) fe448_sqr(t2, t2); + /* t2 = f0 */ + fe448_mul(t1, t2, t1); + /* t1 = ff */ + fe448_mul(t3, t3, t2); + /* t3 = fe */ + fe448_sqr(t2, t1); for (i = 1; i < 7; ++i) fe448_sqr(t2, t2); + /* t2 = 7f80 */ + fe448_mul(t5, t2, t5); + /* t5 = 7fff */ + fe448_sqr(t2, t1); for (i = 1; i < 8; ++i) fe448_sqr(t2, t2); + /* t2 = ff00 */ + fe448_mul(t1, t2, t1); + /* t1 = ffff */ + fe448_mul(t3, t3, t2); + /* t3 = fffe */ + fe448_sqr(t2, t5); for (i = 1; i < 15; ++i) fe448_sqr(t2, t2); + /* t2 = 3fff8000 */ + fe448_mul(t5, t2, t5); + /* t5 = 3fffffff */ + fe448_sqr(t2, t1); for (i = 1; i < 16; ++i) fe448_sqr(t2, t2); + /* t2 = ffff0000 */ + fe448_mul(t1, t2, t1); + /* t1 = ffffffff */ + fe448_mul(t3, t3, t2); + /* t3 = fffffffe */ + fe448_sqr(t2, t1); for (i = 1; i < 32; ++i) fe448_sqr(t2, t2); + /* t2 = ffffffff00000000 */ + fe448_mul(t2, t2, t1); + /* t2 = ffffffffffffffff */ + fe448_sqr(t1, t2); for (i = 1; i < 64; ++i) fe448_sqr(t1, t1); + /* t1 = ffffffffffffffff0000000000000000 */ + fe448_mul(t1, t1, t2); + /* t1 = ffffffffffffffffffffffffffffffff */ + fe448_sqr(t1, t1); for (i = 1; i < 64; ++i) fe448_sqr(t1, t1); + /* t1 = ffffffffffffffffffffffffffffffff0000000000000000 */ + fe448_mul(t4, t1, t2); + /* t4 = ffffffffffffffffffffffffffffffffffffffffffffffff */ + fe448_sqr(t2, t4); for (i = 1; i < 32; ++i) fe448_sqr(t2, t2); + /* t2 = ffffffffffffffffffffffffffffffffffffffffffffffff00000000 */ + fe448_mul(t3, t3, t2); + /* t3 = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe */ + fe448_sqr(t1, t3); for (i = 1; i < 192; ++i) fe448_sqr(t1, t1); + /* t1 = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000 */ + fe448_mul(t1, t1, t4); + /* t1 = fffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff */ + fe448_sqr(t1, t1); for (i = 1; i < 30; ++i) fe448_sqr(t1, t1); + /* t1 = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffffffffffffffffffffffffffffffffffc0000000 */ + fe448_mul(r, t5, t1); + /* r = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffffffffffffffffffffffffffffffffffffffffff */ +} + +/* 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 fe448_cmov(int32_t* a, const int32_t* b, int c) +{ + int32_t m = -(int32_t)c; + int32_t t0 = m & (a[0] ^ b[0]); + int32_t t1 = m & (a[1] ^ b[1]); + int32_t t2 = m & (a[2] ^ b[2]); + int32_t t3 = m & (a[3] ^ b[3]); + int32_t t4 = m & (a[4] ^ b[4]); + int32_t t5 = m & (a[5] ^ b[5]); + int32_t t6 = m & (a[6] ^ b[6]); + int32_t t7 = m & (a[7] ^ b[7]); + int32_t t8 = m & (a[8] ^ b[8]); + int32_t t9 = m & (a[9] ^ b[9]); + int32_t t10 = m & (a[10] ^ b[10]); + int32_t t11 = m & (a[11] ^ b[11]); + int32_t t12 = m & (a[12] ^ b[12]); + int32_t t13 = m & (a[13] ^ b[13]); + int32_t t14 = m & (a[14] ^ b[14]); + int32_t t15 = m & (a[15] ^ b[15]); + + a[0] ^= t0; + a[1] ^= t1; + a[2] ^= t2; + a[3] ^= t3; + a[4] ^= t4; + a[5] ^= t5; + a[6] ^= t6; + a[7] ^= t7; + a[8] ^= t8; + a[9] ^= t9; + a[10] ^= t10; + a[11] ^= t11; + a[12] ^= t12; + a[13] ^= t13; + a[14] ^= t14; + a[15] ^= t15; +} + +#endif /* HAVE_ED448 */ +#endif + +#endif /* HAVE_CURVE448 || HAVE_ED448 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_low_mem.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_low_mem.c index 80834f54c..13c88cbb4 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_low_mem.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_low_mem.c @@ -1,8 +1,8 @@ /* fe_low_mem.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* Based from Daniel Beer's public domain word. */ + +/* Based from Daniel Beer's public domain work. */ #ifdef HAVE_CONFIG_H #include @@ -27,17 +28,18 @@ #include -#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 #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif - void fprime_copy(byte *x, const byte *a) { int i; @@ -46,13 +48,24 @@ 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++) x[i] = a[i]; } +#if ((defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL)) || \ + (defined(HAVE_ED25519) && !defined(ED25519_SMALL))) && \ + !defined(FREESCALE_LTC_ECC) + /* to be Complementary to fe_low_mem.c */ +#else +void fe_init(void) +{ +} +#endif + +#ifdef CURVE25519_SMALL /* Double an X-coordinate */ static void xc_double(byte *x3, byte *z3, @@ -74,12 +87,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); } @@ -110,24 +123,24 @@ 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); } - +#ifndef FREESCALE_LTC_ECC int curve25519(byte *result, byte *e, byte *q) { /* Current point: P_m */ @@ -141,7 +154,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; @@ -171,6 +184,8 @@ int curve25519(byte *result, byte *e, byte *q) fe_normalize(result); return 0; } +#endif /* !FREESCALE_LTC_ECC */ +#endif /* CURVE25519_SMALL */ static void raw_add(byte *x, const byte *p) @@ -180,7 +195,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; } } @@ -194,11 +209,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); } @@ -211,7 +226,7 @@ static int prime_msb(const byte *p) /* Test for any hot bits. - As soon as one instance is incountered set shift to 0. + As soon as one instance is encountered set shift to 0. */ for (i = F25519_SIZE - 1; i >= 0; i--) { shift &= ((shift ^ ((-p[i] | p[i]) >> 7)) & 1); @@ -268,7 +283,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); @@ -307,7 +322,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; } @@ -319,12 +334,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); @@ -343,7 +358,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; @@ -352,7 +367,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 */ @@ -361,13 +376,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; @@ -392,7 +407,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; @@ -447,12 +462,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); } @@ -530,12 +545,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); } @@ -585,12 +600,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 /* CURVE25519_SMALL || ED25519_SMALL */ +#endif /* HAVE_CURVE25519 || HAVE_ED25519 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_operations.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_operations.c index da07c951c..1e1c92bf2 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_operations.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_operations.c @@ -1,8 +1,8 @@ /* fe_operations.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Based On Daniel J Bernstein's curve25519 Public Domain ref10 work. */ #ifdef HAVE_CONFIG_H @@ -27,7 +28,8 @@ #include -#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 @@ -35,9 +37,20 @@ #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif +#ifdef CURVED25519_X64 +/* Assembly code in fe_x25519_asm.* */ +#elif defined(WOLFSSL_ARMASM) +/* Assembly code in fe_armv[78]_x25519.* */ +#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). @@ -65,7 +78,7 @@ uint64_t load_4(const unsigned char *in) result |= ((uint64_t) in[3]) << 24; return result; } - +#endif /* h = 1 @@ -105,25 +118,43 @@ void fe_0(fe h) } +#if ((defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL)) || \ + (defined(HAVE_ED25519) && !defined(ED25519_SMALL))) && \ + !defined(FREESCALE_LTC_ECC) +/* to be Complementary to fe_low_mem.c */ +void fe_init(void) +{ +} +#endif + +#if defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL) && \ + !defined(FREESCALE_LTC_ECC) int curve25519(byte* q, byte* n, byte* p) { +#if 0 unsigned char e[32]; - unsigned int i; - fe x1; - fe x2; - fe z2; - fe x3; - fe z3; - fe tmp0; - fe tmp1; - int pos; - unsigned int swap; - unsigned int b; +#endif + fe x1 = {0}; + fe x2 = {0}; + fe z2 = {0}; + fe x3 = {0}; + fe z3 = {0}; + fe tmp0 = {0}; + fe tmp1 = {0}; + int pos = 0; + unsigned int swap = 0; + unsigned int b = 0; - for (i = 0;i < 32;++i) e[i] = n[i]; - e[0] &= 248; - e[31] &= 127; - e[31] |= 64; + /* Clamp already done during key generation and import */ +#if 0 + { + unsigned int i; + for (i = 0;i < 32;++i) e[i] = n[i]; + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + } +#endif fe_frombytes(x1,p); fe_1(x2); @@ -133,7 +164,11 @@ int curve25519(byte* q, byte* n, byte* p) swap = 0; for (pos = 254;pos >= 0;--pos) { +#if 0 b = e[pos / 8] >> (pos & 7); +#else + b = n[pos / 8] >> (pos & 7); +#endif b &= 1; swap ^= b; fe_cswap(x2,x3,swap); @@ -169,6 +204,7 @@ int curve25519(byte* q, byte* n, byte* p) return 0; } +#endif /* HAVE_CURVE25519 && !CURVE25519_SMALL && !FREESCALE_LTC_ECC */ /* @@ -287,24 +323,24 @@ void fe_sq(fe h,const fe f) int64_t carry8; int64_t carry9; - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry0 = (h0 + (int64_t) (1UL<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry4 = (h4 + (int64_t) (1UL<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + carry1 = (h1 + (int64_t) (1UL<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry5 = (h5 + (int64_t) (1UL<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + carry2 = (h2 + (int64_t) (1UL<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry6 = (h6 + (int64_t) (1UL<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + carry3 = (h3 + (int64_t) (1UL<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry7 = (h7 + (int64_t) (1UL<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + carry4 = (h4 + (int64_t) (1UL<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry8 = (h8 + (int64_t) (1UL<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + carry9 = (h9 + (int64_t) (1UL<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry0 = (h0 + (int64_t) (1UL<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; h[0] = (int32_t)h0; h[1] = (int32_t)h1; @@ -460,38 +496,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); } @@ -552,6 +588,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. */ @@ -579,17 +617,17 @@ void fe_frombytes(fe h,const unsigned char *s) int64_t carry8; int64_t carry9; - carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + carry9 = (h9 + (int64_t) (1UL<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + carry1 = (h1 + (int64_t) (1UL<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry3 = (h3 + (int64_t) (1UL<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry5 = (h5 + (int64_t) (1UL<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + carry7 = (h7 + (int64_t) (1UL<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + carry0 = (h0 + (int64_t) (1UL<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry2 = (h2 + (int64_t) (1UL<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry4 = (h4 + (int64_t) (1UL<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry6 = (h6 + (int64_t) (1UL<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + carry8 = (h8 + (int64_t) (1UL<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; h[0] = (int32_t)h0; h[1] = (int32_t)h1; @@ -602,15 +640,16 @@ 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) { - fe t0; - fe t1; - fe t2; - fe t3; - int i; + fe t0 = {0}; + fe t1 = {0}; + fe t2 = {0}; + fe t3 = {0}; + int i = 0; /* pow225521 */ fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0); @@ -865,46 +904,46 @@ void fe_mul(fe h,const fe f,const fe g) i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 */ - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry0 = (h0 + (int64_t) (1UL<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry4 = (h4 + (int64_t) (1UL<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; /* |h0| <= 2^25 */ /* |h4| <= 2^25 */ /* |h1| <= 1.71*2^59 */ /* |h5| <= 1.71*2^59 */ - carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + carry1 = (h1 + (int64_t) (1UL<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry5 = (h5 + (int64_t) (1UL<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; /* |h1| <= 2^24; from now on fits into int32 */ /* |h5| <= 2^24; from now on fits into int32 */ /* |h2| <= 1.41*2^60 */ /* |h6| <= 1.41*2^60 */ - carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + carry2 = (h2 + (int64_t) (1UL<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry6 = (h6 + (int64_t) (1UL<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; /* |h2| <= 2^25; from now on fits into int32 unchanged */ /* |h6| <= 2^25; from now on fits into int32 unchanged */ /* |h3| <= 1.71*2^59 */ /* |h7| <= 1.71*2^59 */ - carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + carry3 = (h3 + (int64_t) (1UL<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry7 = (h7 + (int64_t) (1UL<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; /* |h3| <= 2^24; from now on fits into int32 unchanged */ /* |h7| <= 2^24; from now on fits into int32 unchanged */ /* |h4| <= 1.72*2^34 */ /* |h8| <= 1.41*2^60 */ - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + carry4 = (h4 + (int64_t) (1UL<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry8 = (h8 + (int64_t) (1UL<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; /* |h4| <= 2^25; from now on fits into int32 unchanged */ /* |h8| <= 2^25; from now on fits into int32 unchanged */ /* |h5| <= 1.01*2^24 */ /* |h9| <= 1.71*2^59 */ - carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + carry9 = (h9 + (int64_t) (1UL<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; /* |h9| <= 2^24; from now on fits into int32 unchanged */ /* |h0| <= 1.1*2^39 */ - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry0 = (h0 + (int64_t) (1UL<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; /* |h0| <= 2^25; from now on fits into int32 unchanged */ /* |h1| <= 1.01*2^24 */ @@ -928,7 +967,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]; @@ -1038,17 +1077,17 @@ void fe_mul121666(fe h,fe f) int64_t carry8; int64_t carry9; - carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + carry9 = (h9 + (int64_t) (1UL<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + carry1 = (h1 + (int64_t) (1UL<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry3 = (h3 + (int64_t) (1UL<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry5 = (h5 + (int64_t) (1UL<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + carry7 = (h7 + (int64_t) (1UL<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + carry0 = (h0 + (int64_t) (1UL<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry2 = (h2 + (int64_t) (1UL<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry4 = (h4 + (int64_t) (1UL<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry6 = (h6 + (int64_t) (1UL<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + carry8 = (h8 + (int64_t) (1UL<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; h[0] = (int32_t)h0; h[1] = (int32_t)h1; @@ -1190,24 +1229,24 @@ void fe_sq2(fe h,const fe f) h8 += h8; h9 += h9; - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry0 = (h0 + (int64_t) (1UL<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry4 = (h4 + (int64_t) (1UL<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + carry1 = (h1 + (int64_t) (1UL<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry5 = (h5 + (int64_t) (1UL<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + carry2 = (h2 + (int64_t) (1UL<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry6 = (h6 + (int64_t) (1UL<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + carry3 = (h3 + (int64_t) (1UL<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry7 = (h7 + (int64_t) (1UL<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + carry4 = (h4 + (int64_t) (1UL<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry8 = (h8 + (int64_t) (1UL<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + carry9 = (h9 + (int64_t) (1UL<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry0 = (h0 + (int64_t) (1UL<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; h[0] = (int32_t)h0; h[1] = (int32_t)h1; @@ -1224,10 +1263,10 @@ void fe_sq2(fe h,const fe f) void fe_pow22523(fe out,const fe z) { - fe t0; - fe t1; - fe t2; - int i; + fe t0 = {0}; + fe t1 = {0}; + fe t2 = {0}; + int i = 0; fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0); fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1); @@ -1306,7 +1345,7 @@ Preconditions: |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ -static const unsigned char zero[32]; +static const unsigned char zero[32] = {0}; int fe_isnonzero(const fe f) { @@ -1339,7 +1378,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]; @@ -1393,5 +1432,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 +#endif /* !CURVE25519_SMALL || !ED25519_SMALL */ +#endif /* HAVE_CURVE25519 || HAVE_ED25519 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_x25519_128.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_x25519_128.i new file mode 100644 index 000000000..10e43d9cd --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_x25519_128.i @@ -0,0 +1,625 @@ +/* fe_x25519_128.i + * + * Copyright (C) 2006-2020 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(void) +{ +} + +/* 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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_x25519_asm.S b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_x25519_asm.S new file mode 100644 index 000000000..6d0f638b5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fe_x25519_asm.S @@ -0,0 +1,16542 @@ +/* fe_x25519_asm + * + * Copyright (C) 2006-2020 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 HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX1 +#endif /* HAVE_INTEL_AVX1 */ +#ifndef NO_AVX2_SUPPORT +#define HAVE_INTEL_AVX2 +#endif /* NO_AVX2_SUPPORT */ + +#ifndef __APPLE__ +.text +.globl fe_init +.type fe_init,@function +.align 4 +fe_init: +#else +.section __TEXT,__text +.globl _fe_init +.p2align 2 +_fe_init: +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ + movq cpuFlagsSet@GOTPCREL(%rip), %rax + movl (%rax), %eax +#else + movl _cpuFlagsSet(%rip), %eax +#endif /* __APPLE__ */ + testl %eax, %eax + je L_fe_init_get_flags + repz retq +L_fe_init_get_flags: +#ifndef __APPLE__ + callq cpuid_get_flags@plt +#else + callq _cpuid_get_flags +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq intelFlags@GOTPCREL(%rip), %rdx + movl %eax, (%rdx) +#else + movl %eax, _intelFlags(%rip) +#endif /* __APPLE__ */ + andl $0x50, %eax + cmpl $0x50, %eax + jne L_fe_init_flags_done +#ifndef __APPLE__ + movq fe_mul_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_mul_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_mul_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_mul_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_sq_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_sq_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_sq_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_sq_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_mul121666_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_mul121666_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_mul121666_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_mul121666_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_sq2_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_sq2_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_sq2_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_sq2_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_invert_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_invert_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_invert_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_invert_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq curve25519_avx2@GOTPCREL(%rip), %rax +#else + leaq _curve25519_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq curve25519_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _curve25519_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_pow22523_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_pow22523_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_pow22523_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_pow22523_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_to_p2_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_ge_to_p2_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_to_p2_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_ge_to_p2_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_to_p3_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_ge_to_p3_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_to_p3_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_ge_to_p3_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_dbl_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_ge_dbl_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_dbl_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_ge_dbl_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_madd_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_ge_madd_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_madd_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_ge_madd_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_msub_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_ge_msub_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_msub_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_ge_msub_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_add_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_ge_add_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_add_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_ge_add_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_sub_avx2@GOTPCREL(%rip), %rax +#else + leaq _fe_ge_sub_avx2(%rip), %rax +#endif /* __APPLE__ */ +#ifndef __APPLE__ + movq fe_ge_sub_p@GOTPCREL(%rip), %rdx + movq %rax, (%rdx) +#else + movq %rax, _fe_ge_sub_p(%rip) +#endif /* __APPLE__ */ +L_fe_init_flags_done: +#ifndef __APPLE__ + movq cpuFlagsSet@GOTPCREL(%rip), %rdx + movl $0x1, (%rdx) +#else + movl $0x1, _cpuFlagsSet(%rip) +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ + repz retq +#ifndef __APPLE__ +.size fe_init,.-fe_init +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_frombytes +.type fe_frombytes,@function +.align 4 +fe_frombytes: +#else +.section __TEXT,__text +.globl _fe_frombytes +.p2align 2 +_fe_frombytes: +#endif /* __APPLE__ */ + movq $0x7fffffffffffffff, %r9 + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + andq %r9, %r8 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_frombytes,.-fe_frombytes +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_tobytes +.type fe_tobytes,@function +.align 4 +fe_tobytes: +#else +.section __TEXT,__text +.globl _fe_tobytes +.p2align 2 +_fe_tobytes: +#endif /* __APPLE__ */ + movq $0x7fffffffffffffff, %r10 + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + addq $19, %rdx + adcq $0x00, %rax + adcq $0x00, %rcx + adcq $0x00, %r8 + shrq $63, %r8 + imulq $19, %r8, %r9 + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + addq %r9, %rdx + adcq $0x00, %rax + adcq $0x00, %rcx + adcq $0x00, %r8 + andq %r10, %r8 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_tobytes,.-fe_tobytes +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_1 +.type fe_1,@function +.align 4 +fe_1: +#else +.section __TEXT,__text +.globl _fe_1 +.p2align 2 +_fe_1: +#endif /* __APPLE__ */ + # Set one + movq $0x01, (%rdi) + movq $0x00, 8(%rdi) + movq $0x00, 16(%rdi) + movq $0x00, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_1,.-fe_1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_0 +.type fe_0,@function +.align 4 +fe_0: +#else +.section __TEXT,__text +.globl _fe_0 +.p2align 2 +_fe_0: +#endif /* __APPLE__ */ + # Set zero + movq $0x00, (%rdi) + movq $0x00, 8(%rdi) + movq $0x00, 16(%rdi) + movq $0x00, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_0,.-fe_0 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_copy +.type fe_copy,@function +.align 4 +fe_copy: +#else +.section __TEXT,__text +.globl _fe_copy +.p2align 2 +_fe_copy: +#endif /* __APPLE__ */ + # Copy + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_copy,.-fe_copy +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sub +.type fe_sub,@function +.align 4 +fe_sub: +#else +.section __TEXT,__text +.globl _fe_sub +.p2align 2 +_fe_sub: +#endif /* __APPLE__ */ + pushq %r12 + # Sub + movq (%rsi), %rax + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + subq (%rdx), %rax + movq $0x00, %r10 + sbbq 8(%rdx), %rcx + movq $-19, %r11 + sbbq 16(%rdx), %r8 + movq $0x7fffffffffffffff, %r12 + sbbq 24(%rdx), %r9 + sbbq $0x00, %r10 + # Mask the modulus + andq %r10, %r11 + andq %r10, %r12 + # Add modulus (if underflow) + addq %r11, %rax + adcq %r10, %rcx + adcq %r10, %r8 + adcq %r12, %r9 + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_sub,.-fe_sub +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_add +.type fe_add,@function +.align 4 +fe_add: +#else +.section __TEXT,__text +.globl _fe_add +.p2align 2 +_fe_add: +#endif /* __APPLE__ */ + pushq %r12 + # Add + movq (%rsi), %rax + movq 8(%rsi), %rcx + addq (%rdx), %rax + movq 16(%rsi), %r8 + adcq 8(%rdx), %rcx + movq 24(%rsi), %r10 + adcq 16(%rdx), %r8 + movq $-19, %r11 + adcq 24(%rdx), %r10 + movq $0x7fffffffffffffff, %r12 + movq %r10, %r9 + sarq $63, %r10 + # Mask the modulus + andq %r10, %r11 + andq %r10, %r12 + # Sub modulus (if overflow) + subq %r11, %rax + sbbq %r10, %rcx + sbbq %r10, %r8 + sbbq %r12, %r9 + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_add,.-fe_add +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_neg +.type fe_neg,@function +.align 4 +fe_neg: +#else +.section __TEXT,__text +.globl _fe_neg +.p2align 2 +_fe_neg: +#endif /* __APPLE__ */ + movq $-19, %rdx + movq $-1, %rax + movq $-1, %rcx + movq $0x7fffffffffffffff, %r8 + subq (%rsi), %rdx + sbbq 8(%rsi), %rax + sbbq 16(%rsi), %rcx + sbbq 24(%rsi), %r8 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_neg,.-fe_neg +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_cmov +.type fe_cmov,@function +.align 4 +fe_cmov: +#else +.section __TEXT,__text +.globl _fe_cmov +.p2align 2 +_fe_cmov: +#endif /* __APPLE__ */ + cmpl $0x01, %edx + movq (%rdi), %rcx + movq 8(%rdi), %r8 + movq 16(%rdi), %r9 + movq 24(%rdi), %r10 + cmoveq (%rsi), %rcx + cmoveq 8(%rsi), %r8 + cmoveq 16(%rsi), %r9 + cmoveq 24(%rsi), %r10 + movq %rcx, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_cmov,.-fe_cmov +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_isnonzero +.type fe_isnonzero,@function +.align 4 +fe_isnonzero: +#else +.section __TEXT,__text +.globl _fe_isnonzero +.p2align 2 +_fe_isnonzero: +#endif /* __APPLE__ */ + movq $0x7fffffffffffffff, %r10 + movq (%rdi), %rax + movq 8(%rdi), %rdx + movq 16(%rdi), %rcx + movq 24(%rdi), %r8 + addq $19, %rax + adcq $0x00, %rdx + adcq $0x00, %rcx + adcq $0x00, %r8 + shrq $63, %r8 + imulq $19, %r8, %r9 + movq (%rdi), %rax + movq 8(%rdi), %rdx + movq 16(%rdi), %rcx + movq 24(%rdi), %r8 + addq %r9, %rax + adcq $0x00, %rdx + adcq $0x00, %rcx + adcq $0x00, %r8 + andq %r10, %r8 + orq %rdx, %rax + orq %rcx, %rax + orq %r8, %rax + repz retq +#ifndef __APPLE__ +.size fe_isnonzero,.-fe_isnonzero +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_isnegative +.type fe_isnegative,@function +.align 4 +fe_isnegative: +#else +.section __TEXT,__text +.globl _fe_isnegative +.p2align 2 +_fe_isnegative: +#endif /* __APPLE__ */ + movq $0x7fffffffffffffff, %r11 + movq (%rdi), %rdx + movq 8(%rdi), %rcx + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 + movq %rdx, %rax + addq $19, %rdx + adcq $0x00, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + shrq $63, %r9 + imulq $19, %r9, %r10 + addq %r10, %rax + andq $0x01, %rax + repz retq +#ifndef __APPLE__ +.size fe_isnegative,.-fe_isnegative +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_cmov_table +.type fe_cmov_table,@function +.align 4 +fe_cmov_table: +#else +.section __TEXT,__text +.globl _fe_cmov_table +.p2align 2 +_fe_cmov_table: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + movq %rdx, %rcx + movsbq %cl, %rax + cdq + xorb %dl, %al + subb %dl, %al + movb %al, %r15b + movq $0x01, %rax + xorq %rdx, %rdx + xorq %r8, %r8 + xorq %r9, %r9 + movq $0x01, %r10 + xorq %r11, %r11 + xorq %r12, %r12 + xorq %r13, %r13 + cmpb $0x01, %r15b + movq (%rsi), %r14 + cmoveq %r14, %rax + movq 8(%rsi), %r14 + cmoveq %r14, %rdx + movq 16(%rsi), %r14 + cmoveq %r14, %r8 + movq 24(%rsi), %r14 + cmoveq %r14, %r9 + movq 32(%rsi), %r14 + cmoveq %r14, %r10 + movq 40(%rsi), %r14 + cmoveq %r14, %r11 + movq 48(%rsi), %r14 + cmoveq %r14, %r12 + movq 56(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $2, %r15b + movq 96(%rsi), %r14 + cmoveq %r14, %rax + movq 104(%rsi), %r14 + cmoveq %r14, %rdx + movq 112(%rsi), %r14 + cmoveq %r14, %r8 + movq 120(%rsi), %r14 + cmoveq %r14, %r9 + movq 128(%rsi), %r14 + cmoveq %r14, %r10 + movq 136(%rsi), %r14 + cmoveq %r14, %r11 + movq 144(%rsi), %r14 + cmoveq %r14, %r12 + movq 152(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $3, %r15b + movq 192(%rsi), %r14 + cmoveq %r14, %rax + movq 200(%rsi), %r14 + cmoveq %r14, %rdx + movq 208(%rsi), %r14 + cmoveq %r14, %r8 + movq 216(%rsi), %r14 + cmoveq %r14, %r9 + movq 224(%rsi), %r14 + cmoveq %r14, %r10 + movq 232(%rsi), %r14 + cmoveq %r14, %r11 + movq 240(%rsi), %r14 + cmoveq %r14, %r12 + movq 248(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $4, %r15b + movq 288(%rsi), %r14 + cmoveq %r14, %rax + movq 296(%rsi), %r14 + cmoveq %r14, %rdx + movq 304(%rsi), %r14 + cmoveq %r14, %r8 + movq 312(%rsi), %r14 + cmoveq %r14, %r9 + movq 320(%rsi), %r14 + cmoveq %r14, %r10 + movq 328(%rsi), %r14 + cmoveq %r14, %r11 + movq 336(%rsi), %r14 + cmoveq %r14, %r12 + movq 344(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $5, %r15b + movq 384(%rsi), %r14 + cmoveq %r14, %rax + movq 392(%rsi), %r14 + cmoveq %r14, %rdx + movq 400(%rsi), %r14 + cmoveq %r14, %r8 + movq 408(%rsi), %r14 + cmoveq %r14, %r9 + movq 416(%rsi), %r14 + cmoveq %r14, %r10 + movq 424(%rsi), %r14 + cmoveq %r14, %r11 + movq 432(%rsi), %r14 + cmoveq %r14, %r12 + movq 440(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $6, %r15b + movq 480(%rsi), %r14 + cmoveq %r14, %rax + movq 488(%rsi), %r14 + cmoveq %r14, %rdx + movq 496(%rsi), %r14 + cmoveq %r14, %r8 + movq 504(%rsi), %r14 + cmoveq %r14, %r9 + movq 512(%rsi), %r14 + cmoveq %r14, %r10 + movq 520(%rsi), %r14 + cmoveq %r14, %r11 + movq 528(%rsi), %r14 + cmoveq %r14, %r12 + movq 536(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $7, %r15b + movq 576(%rsi), %r14 + cmoveq %r14, %rax + movq 584(%rsi), %r14 + cmoveq %r14, %rdx + movq 592(%rsi), %r14 + cmoveq %r14, %r8 + movq 600(%rsi), %r14 + cmoveq %r14, %r9 + movq 608(%rsi), %r14 + cmoveq %r14, %r10 + movq 616(%rsi), %r14 + cmoveq %r14, %r11 + movq 624(%rsi), %r14 + cmoveq %r14, %r12 + movq 632(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $8, %r15b + movq 672(%rsi), %r14 + cmoveq %r14, %rax + movq 680(%rsi), %r14 + cmoveq %r14, %rdx + movq 688(%rsi), %r14 + cmoveq %r14, %r8 + movq 696(%rsi), %r14 + cmoveq %r14, %r9 + movq 704(%rsi), %r14 + cmoveq %r14, %r10 + movq 712(%rsi), %r14 + cmoveq %r14, %r11 + movq 720(%rsi), %r14 + cmoveq %r14, %r12 + movq 728(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $0x00, %cl + movq %rax, %r14 + cmovlq %r10, %rax + cmovlq %r14, %r10 + movq %rdx, %r14 + cmovlq %r11, %rdx + cmovlq %r14, %r11 + movq %r8, %r14 + cmovlq %r12, %r8 + cmovlq %r14, %r12 + movq %r9, %r14 + cmovlq %r13, %r9 + cmovlq %r14, %r13 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq %r10, 32(%rdi) + movq %r11, 40(%rdi) + movq %r12, 48(%rdi) + movq %r13, 56(%rdi) + xorq %rax, %rax + xorq %rdx, %rdx + xorq %r8, %r8 + xorq %r9, %r9 + cmpb $0x01, %r15b + movq 64(%rsi), %r14 + cmoveq %r14, %rax + movq 72(%rsi), %r14 + cmoveq %r14, %rdx + movq 80(%rsi), %r14 + cmoveq %r14, %r8 + movq 88(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $2, %r15b + movq 160(%rsi), %r14 + cmoveq %r14, %rax + movq 168(%rsi), %r14 + cmoveq %r14, %rdx + movq 176(%rsi), %r14 + cmoveq %r14, %r8 + movq 184(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $3, %r15b + movq 256(%rsi), %r14 + cmoveq %r14, %rax + movq 264(%rsi), %r14 + cmoveq %r14, %rdx + movq 272(%rsi), %r14 + cmoveq %r14, %r8 + movq 280(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $4, %r15b + movq 352(%rsi), %r14 + cmoveq %r14, %rax + movq 360(%rsi), %r14 + cmoveq %r14, %rdx + movq 368(%rsi), %r14 + cmoveq %r14, %r8 + movq 376(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $5, %r15b + movq 448(%rsi), %r14 + cmoveq %r14, %rax + movq 456(%rsi), %r14 + cmoveq %r14, %rdx + movq 464(%rsi), %r14 + cmoveq %r14, %r8 + movq 472(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $6, %r15b + movq 544(%rsi), %r14 + cmoveq %r14, %rax + movq 552(%rsi), %r14 + cmoveq %r14, %rdx + movq 560(%rsi), %r14 + cmoveq %r14, %r8 + movq 568(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $7, %r15b + movq 640(%rsi), %r14 + cmoveq %r14, %rax + movq 648(%rsi), %r14 + cmoveq %r14, %rdx + movq 656(%rsi), %r14 + cmoveq %r14, %r8 + movq 664(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $8, %r15b + movq 736(%rsi), %r14 + cmoveq %r14, %rax + movq 744(%rsi), %r14 + cmoveq %r14, %rdx + movq 752(%rsi), %r14 + cmoveq %r14, %r8 + movq 760(%rsi), %r14 + cmoveq %r14, %r9 + movq $-19, %r10 + movq $-1, %r11 + movq $-1, %r12 + movq $0x7fffffffffffffff, %r13 + subq %rax, %r10 + sbbq %rdx, %r11 + sbbq %r8, %r12 + sbbq %r9, %r13 + cmpb $0x00, %cl + cmovlq %r10, %rax + cmovlq %r11, %rdx + cmovlq %r12, %r8 + cmovlq %r13, %r9 + movq %rax, 64(%rdi) + movq %rdx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_cmov_table,.-fe_cmov_table +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_mul +.type fe_mul,@function +.align 4 +fe_mul: +#else +.section __TEXT,__text +.globl _fe_mul +.p2align 2 +_fe_mul: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_mul_p(%rip) +#else + jmpq *_fe_mul_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_mul,.-fe_mul +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq +.type fe_sq,@function +.align 4 +fe_sq: +#else +.section __TEXT,__text +.globl _fe_sq +.p2align 2 +_fe_sq: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_sq_p(%rip) +#else + jmpq *_fe_sq_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_sq,.-fe_sq +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_mul121666 +.type fe_mul121666,@function +.align 4 +fe_mul121666: +#else +.section __TEXT,__text +.globl _fe_mul121666 +.p2align 2 +_fe_mul121666: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_mul121666_p(%rip) +#else + jmpq *_fe_mul121666_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_mul121666,.-fe_mul121666 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq2 +.type fe_sq2,@function +.align 4 +fe_sq2: +#else +.section __TEXT,__text +.globl _fe_sq2 +.p2align 2 +_fe_sq2: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_sq2_p(%rip) +#else + jmpq *_fe_sq2_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_sq2,.-fe_sq2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_invert +.type fe_invert,@function +.align 4 +fe_invert: +#else +.section __TEXT,__text +.globl _fe_invert +.p2align 2 +_fe_invert: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_invert_p(%rip) +#else + jmpq *_fe_invert_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_invert,.-fe_invert +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl curve25519 +.type curve25519,@function +.align 4 +curve25519: +#else +.section __TEXT,__text +.globl _curve25519 +.p2align 2 +_curve25519: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *curve25519_p(%rip) +#else + jmpq *_curve25519_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size curve25519,.-curve25519 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_pow22523 +.type fe_pow22523,@function +.align 4 +fe_pow22523: +#else +.section __TEXT,__text +.globl _fe_pow22523 +.p2align 2 +_fe_pow22523: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_pow22523_p(%rip) +#else + jmpq *_fe_pow22523_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_pow22523,.-fe_pow22523 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_to_p2 +.type fe_ge_to_p2,@function +.align 4 +fe_ge_to_p2: +#else +.section __TEXT,__text +.globl _fe_ge_to_p2 +.p2align 2 +_fe_ge_to_p2: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_ge_to_p2_p(%rip) +#else + jmpq *_fe_ge_to_p2_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_ge_to_p2,.-fe_ge_to_p2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_to_p3 +.type fe_ge_to_p3,@function +.align 4 +fe_ge_to_p3: +#else +.section __TEXT,__text +.globl _fe_ge_to_p3 +.p2align 2 +_fe_ge_to_p3: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_ge_to_p3_p(%rip) +#else + jmpq *_fe_ge_to_p3_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_ge_to_p3,.-fe_ge_to_p3 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_dbl +.type fe_ge_dbl,@function +.align 4 +fe_ge_dbl: +#else +.section __TEXT,__text +.globl _fe_ge_dbl +.p2align 2 +_fe_ge_dbl: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_ge_dbl_p(%rip) +#else + jmpq *_fe_ge_dbl_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_ge_dbl,.-fe_ge_dbl +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_madd +.type fe_ge_madd,@function +.align 4 +fe_ge_madd: +#else +.section __TEXT,__text +.globl _fe_ge_madd +.p2align 2 +_fe_ge_madd: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_ge_madd_p(%rip) +#else + jmpq *_fe_ge_madd_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_ge_madd,.-fe_ge_madd +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_msub +.type fe_ge_msub,@function +.align 4 +fe_ge_msub: +#else +.section __TEXT,__text +.globl _fe_ge_msub +.p2align 2 +_fe_ge_msub: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_ge_msub_p(%rip) +#else + jmpq *_fe_ge_msub_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_ge_msub,.-fe_ge_msub +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_add +.type fe_ge_add,@function +.align 4 +fe_ge_add: +#else +.section __TEXT,__text +.globl _fe_ge_add +.p2align 2 +_fe_ge_add: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_ge_add_p(%rip) +#else + jmpq *_fe_ge_add_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_ge_add,.-fe_ge_add +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_sub +.type fe_ge_sub,@function +.align 4 +fe_ge_sub: +#else +.section __TEXT,__text +.globl _fe_ge_sub +.p2align 2 +_fe_ge_sub: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + jmpq *fe_ge_sub_p(%rip) +#else + jmpq *_fe_ge_sub_p(%rip) +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.size fe_ge_sub,.-fe_ge_sub +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type cpuFlagsSet, @object +.size cpuFlagsSet,4 +cpuFlagsSet: + .long 0 +#else +.section __DATA,__data +.p2align 2 +_cpuFlagsSet: + .long 0 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type intelFlags, @object +.size intelFlags,4 +intelFlags: + .long 0 +#else +.section __DATA,__data +.p2align 2 +_intelFlags: + .long 0 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_mul_p, @object +.size fe_mul_p,8 +fe_mul_p: + .quad fe_mul_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_mul_p: + .quad _fe_mul_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_sq_p, @object +.size fe_sq_p,8 +fe_sq_p: + .quad fe_sq_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_sq_p: + .quad _fe_sq_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_mul121666_p, @object +.size fe_mul121666_p,8 +fe_mul121666_p: + .quad fe_mul121666_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_mul121666_p: + .quad _fe_mul121666_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_sq2_p, @object +.size fe_sq2_p,8 +fe_sq2_p: + .quad fe_sq2_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_sq2_p: + .quad _fe_sq2_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_invert_p, @object +.size fe_invert_p,8 +fe_invert_p: + .quad fe_invert_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_invert_p: + .quad _fe_invert_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type curve25519_p, @object +.size curve25519_p,8 +curve25519_p: + .quad curve25519_x64 +#else +.section __DATA,__data +.p2align 2 +_curve25519_p: + .quad _curve25519_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_pow22523_p, @object +.size fe_pow22523_p,8 +fe_pow22523_p: + .quad fe_pow22523_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_pow22523_p: + .quad _fe_pow22523_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_ge_to_p2_p, @object +.size fe_ge_to_p2_p,8 +fe_ge_to_p2_p: + .quad fe_ge_to_p2_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_ge_to_p2_p: + .quad _fe_ge_to_p2_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_ge_to_p3_p, @object +.size fe_ge_to_p3_p,8 +fe_ge_to_p3_p: + .quad fe_ge_to_p3_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_ge_to_p3_p: + .quad _fe_ge_to_p3_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_ge_dbl_p, @object +.size fe_ge_dbl_p,8 +fe_ge_dbl_p: + .quad fe_ge_dbl_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_ge_dbl_p: + .quad _fe_ge_dbl_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_ge_madd_p, @object +.size fe_ge_madd_p,8 +fe_ge_madd_p: + .quad fe_ge_madd_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_ge_madd_p: + .quad _fe_ge_madd_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_ge_msub_p, @object +.size fe_ge_msub_p,8 +fe_ge_msub_p: + .quad fe_ge_msub_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_ge_msub_p: + .quad _fe_ge_msub_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_ge_add_p, @object +.size fe_ge_add_p,8 +fe_ge_add_p: + .quad fe_ge_add_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_ge_add_p: + .quad _fe_ge_add_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +.type fe_ge_sub_p, @object +.size fe_ge_sub_p,8 +fe_ge_sub_p: + .quad fe_ge_sub_x64 +#else +.section __DATA,__data +.p2align 2 +_fe_ge_sub_p: + .quad _fe_ge_sub_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_mul_x64 +.type fe_mul_x64,@function +.align 4 +fe_mul_x64: +#else +.section __TEXT,__text +.globl _fe_mul_x64 +.p2align 2 +_fe_mul_x64: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + movq %rdx, %rcx + # Multiply + # A[0] * B[0] + movq (%rcx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rcx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rcx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rcx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rcx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rcx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rcx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rcx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_mul_x64,.-fe_mul_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq_x64 +.type fe_sq_x64,@function +.align 4 +fe_sq_x64: +#else +.section __TEXT,__text +.globl _fe_sq_x64 +.p2align 2 +_fe_sq_x64: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + # Square + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r13, %r13 + addq %rax, %r12 + adcq %rdx, %r13 + # Double + xorq %r14, %r14 + addq %r8, %r8 + adcq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq $0x00, %r14 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %r15 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %r15, %r8 + adcq %rax, %r9 + adcq $0x00, %rdx + movq %rdx, %r15 + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %r15, %r10 + adcq %rax, %r11 + adcq $0x00, %rdx + movq %rdx, %r15 + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r13 + adcq %rdx, %r14 + addq %r15, %r12 + adcq $0x00, %r13 + adcq $0x00, %r14 + # Reduce + movq $0x7fffffffffffffff, %r15 + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + shldq $0x01, %r10, %r11 + andq %r15, %r10 + # Multiply top half by 19 + movq $19, %rax + mulq %r11 + xorq %r11, %r11 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r11 + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + # Add remaining product results in + addq %r11, %r8 + adcq %r12, %r9 + adcq %r13, %r10 + adcq %rax, %r10 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r10, %rdx + imulq $19, %rdx, %rax + andq %r15, %r10 + addq %rax, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + # Reduce if top bit set + movq %r10, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %r15, %r10 + addq %rax, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + # Store + movq %rcx, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_sq_x64,.-fe_sq_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq_n_x64 +.type fe_sq_n_x64,@function +.align 4 +fe_sq_n_x64: +#else +.section __TEXT,__text +.globl _fe_sq_n_x64 +.p2align 2 +_fe_sq_n_x64: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + movq %rdx, %rcx +L_fe_sq_n_x64: + # Square + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %r8 + movq %rdx, %rbx + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rbx, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rbx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rbx, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rbx + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rbx, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + decb %cl + jnz L_fe_sq_n_x64 + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_sq_n_x64,.-fe_sq_n_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_mul121666_x64 +.type fe_mul121666_x64,@function +.align 4 +fe_mul121666_x64: +#else +.section __TEXT,__text +.globl _fe_mul121666_x64 +.p2align 2 +_fe_mul121666_x64: +#endif /* __APPLE__ */ + pushq %r12 + # Multiply by 121666 + movq $0x1db42, %rax + mulq (%rsi) + xorq %r10, %r10 + movq %rax, %r8 + movq %rdx, %r9 + movq $0x1db42, %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + movq $0x1db42, %rax + mulq 16(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + movq $0x1db42, %rax + mulq 24(%rsi) + movq $0x7fffffffffffffff, %rcx + addq %rax, %r11 + adcq %rdx, %r12 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + movq $19, %rax + mulq %r12 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_mul121666_x64,.-fe_mul121666_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq2_x64 +.type fe_sq2_x64,@function +.align 4 +fe_sq2_x64: +#else +.section __TEXT,__text +.globl _fe_sq2_x64 +.p2align 2 +_fe_sq2_x64: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + # Square * 2 + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r13, %r13 + addq %rax, %r12 + adcq %rdx, %r13 + # Double + xorq %r14, %r14 + addq %r8, %r8 + adcq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq $0x00, %r14 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %r15 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %r15, %r8 + adcq %rax, %r9 + adcq $0x00, %rdx + movq %rdx, %r15 + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %r15, %r10 + adcq %rax, %r11 + adcq $0x00, %rdx + movq %rdx, %r15 + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r13 + adcq %rdx, %r14 + addq %r15, %r12 + adcq $0x00, %r13 + adcq $0x00, %r14 + # Reduce + movq $0x7fffffffffffffff, %rbx + xorq %rax, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $3, %r14, %rax + shldq $2, %r13, %r14 + shldq $2, %r12, %r13 + shldq $2, %r11, %r12 + shldq $2, %r10, %r11 + shldq $0x01, %r9, %r10 + shldq $0x01, %r8, %r9 + shldq $0x01, %rcx, %r8 + shlq $0x01, %rcx + andq %rbx, %r10 + # Two out left, one in right + andq %rbx, %r14 + # Multiply top bits by 19*19 + imulq $0x169, %rax, %r15 + # Multiply top half by 19 + movq $19, %rax + mulq %r11 + xorq %r11, %r11 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r11 + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + # Add remaining produce results in + addq %r15, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + adcq %r13, %r10 + adcq %rax, %r10 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r10, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r10 + addq %rax, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + # Reduce if top bit set + movq %r10, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r10 + addq %rax, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + # Store + movq %rcx, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_sq2_x64,.-fe_sq2_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_invert_x64 +.type fe_invert_x64,@function +.align 4 +fe_invert_x64: +#else +.section __TEXT,__text +.globl _fe_invert_x64 +.p2align 2 +_fe_invert_x64: +#endif /* __APPLE__ */ + subq $0x90, %rsp + # Invert + movq %rdi, 128(%rsp) + movq %rsi, 136(%rsp) + movq %rsp, %rdi + movq 136(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq 136(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $4, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $9, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $19, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $9, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $49, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $0x63, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $49, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq $4, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + movq 128(%rsp), %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq 136(%rsp), %rsi + movq 128(%rsp), %rdi + addq $0x90, %rsp + repz retq +#ifndef __APPLE__ +.text +.globl curve25519_x64 +.type curve25519_x64,@function +.align 4 +curve25519_x64: +#else +.section __TEXT,__text +.globl _curve25519_x64 +.p2align 2 +_curve25519_x64: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + pushq %rbp + movq %rdx, %r8 + subq $0xb8, %rsp + xorq %rbx, %rbx + movq %rdi, 176(%rsp) + # Set one + movq $0x01, (%rdi) + movq $0x00, 8(%rdi) + movq $0x00, 16(%rdi) + movq $0x00, 24(%rdi) + # Set zero + movq $0x00, (%rsp) + movq $0x00, 8(%rsp) + movq $0x00, 16(%rsp) + movq $0x00, 24(%rsp) + # Set one + movq $0x01, 32(%rsp) + movq $0x00, 40(%rsp) + movq $0x00, 48(%rsp) + movq $0x00, 56(%rsp) + # Copy + movq (%r8), %rcx + movq 8(%r8), %r9 + movq 16(%r8), %r10 + movq 24(%r8), %r11 + movq %rcx, 64(%rsp) + movq %r9, 72(%rsp) + movq %r10, 80(%rsp) + movq %r11, 88(%rsp) + movb $62, 168(%rsp) + movq $3, 160(%rsp) +L_curve25519_x64_words: +L_curve25519_x64_bits: + movq 160(%rsp), %r9 + movb 168(%rsp), %cl + movq (%rsi,%r9,8), %rbp + shrq %cl, %rbp + andq $0x01, %rbp + xorq %rbp, %rbx + negq %rbx + # Conditional Swap + movq (%rdi), %rcx + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + xorq 64(%rsp), %rcx + xorq 72(%rsp), %r9 + xorq 80(%rsp), %r10 + xorq 88(%rsp), %r11 + andq %rbx, %rcx + andq %rbx, %r9 + andq %rbx, %r10 + andq %rbx, %r11 + xorq %rcx, (%rdi) + xorq %r9, 8(%rdi) + xorq %r10, 16(%rdi) + xorq %r11, 24(%rdi) + xorq %rcx, 64(%rsp) + xorq %r9, 72(%rsp) + xorq %r10, 80(%rsp) + xorq %r11, 88(%rsp) + # Conditional Swap + movq (%rsp), %rcx + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + xorq 32(%rsp), %rcx + xorq 40(%rsp), %r9 + xorq 48(%rsp), %r10 + xorq 56(%rsp), %r11 + andq %rbx, %rcx + andq %rbx, %r9 + andq %rbx, %r10 + andq %rbx, %r11 + xorq %rcx, (%rsp) + xorq %r9, 8(%rsp) + xorq %r10, 16(%rsp) + xorq %r11, 24(%rsp) + xorq %rcx, 32(%rsp) + xorq %r9, 40(%rsp) + xorq %r10, 48(%rsp) + xorq %r11, 56(%rsp) + movq %rbp, %rbx + # Add + movq (%rdi), %rcx + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %rbp + movq %rcx, %r12 + addq (%rsp), %rcx + movq %r9, %r13 + adcq 8(%rsp), %r9 + movq %r10, %r14 + adcq 16(%rsp), %r10 + movq %rbp, %r15 + adcq 24(%rsp), %rbp + movq $-19, %rax + movq %rbp, %r11 + movq $0x7fffffffffffffff, %rdx + sarq $63, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Sub modulus (if overflow) + subq %rax, %rcx + sbbq %rbp, %r9 + sbbq %rbp, %r10 + sbbq %rdx, %r11 + # Sub + subq (%rsp), %r12 + movq $0x00, %rbp + sbbq 8(%rsp), %r13 + movq $-19, %rax + sbbq 16(%rsp), %r14 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rsp), %r15 + sbbq $0x00, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Add modulus (if underflow) + addq %rax, %r12 + adcq %rbp, %r13 + adcq %rbp, %r14 + adcq %rdx, %r15 + movq %rcx, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 128(%rsp) + movq %r13, 136(%rsp) + movq %r14, 144(%rsp) + movq %r15, 152(%rsp) + # Add + movq 64(%rsp), %rcx + movq 72(%rsp), %r9 + movq 80(%rsp), %r10 + movq 88(%rsp), %rbp + movq %rcx, %r12 + addq 32(%rsp), %rcx + movq %r9, %r13 + adcq 40(%rsp), %r9 + movq %r10, %r14 + adcq 48(%rsp), %r10 + movq %rbp, %r15 + adcq 56(%rsp), %rbp + movq $-19, %rax + movq %rbp, %r11 + movq $0x7fffffffffffffff, %rdx + sarq $63, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Sub modulus (if overflow) + subq %rax, %rcx + sbbq %rbp, %r9 + sbbq %rbp, %r10 + sbbq %rdx, %r11 + # Sub + subq 32(%rsp), %r12 + movq $0x00, %rbp + sbbq 40(%rsp), %r13 + movq $-19, %rax + sbbq 48(%rsp), %r14 + movq $0x7fffffffffffffff, %rdx + sbbq 56(%rsp), %r15 + sbbq $0x00, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Add modulus (if underflow) + addq %rax, %r12 + adcq %rbp, %r13 + adcq %rbp, %r14 + adcq %rdx, %r15 + movq %rcx, (%rsp) + movq %r9, 8(%rsp) + movq %r10, 16(%rsp) + movq %r11, 24(%rsp) + movq %r12, 96(%rsp) + movq %r13, 104(%rsp) + movq %r14, 112(%rsp) + movq %r15, 120(%rsp) + # Multiply + # A[0] * B[0] + movq (%rdi), %rax + mulq 96(%rsp) + movq %rax, %rcx + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rdi), %rax + mulq 96(%rsp) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rdi), %rax + mulq 104(%rsp) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rdi), %rax + mulq 96(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rdi), %rax + mulq 104(%rsp) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rdi), %rax + mulq 112(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rdi), %rax + mulq 96(%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rdi), %rax + mulq 104(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rdi), %rax + mulq 112(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rdi), %rax + mulq 120(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rdi), %rax + mulq 104(%rsp) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rdi), %rax + mulq 112(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rdi), %rax + mulq 120(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rdi), %rax + mulq 112(%rsp) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rdi), %rax + mulq 120(%rsp) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rdi), %rax + mulq 120(%rsp) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, 32(%rsp) + movq %r9, 40(%rsp) + movq %r10, 48(%rsp) + movq %r11, 56(%rsp) + # Multiply + # A[0] * B[0] + movq 128(%rsp), %rax + mulq (%rsp) + movq %rax, %rcx + movq %rdx, %r9 + # A[0] * B[1] + movq 136(%rsp), %rax + mulq (%rsp) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq 128(%rsp), %rax + mulq 8(%rsp) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 144(%rsp), %rax + mulq (%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 136(%rsp), %rax + mulq 8(%rsp) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq 128(%rsp), %rax + mulq 16(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 152(%rsp), %rax + mulq (%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 144(%rsp), %rax + mulq 8(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 136(%rsp), %rax + mulq 16(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq 128(%rsp), %rax + mulq 24(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 152(%rsp), %rax + mulq 8(%rsp) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 144(%rsp), %rax + mulq 16(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 136(%rsp), %rax + mulq 24(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 152(%rsp), %rax + mulq 16(%rsp) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 144(%rsp), %rax + mulq 24(%rsp) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 152(%rsp), %rax + mulq 24(%rsp) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, (%rsp) + movq %r9, 8(%rsp) + movq %r10, 16(%rsp) + movq %r11, 24(%rsp) + # Square + # A[0] * A[1] + movq 128(%rsp), %rax + mulq 136(%rsp) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq 128(%rsp), %rax + mulq 144(%rsp) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq 128(%rsp), %rax + mulq 152(%rsp) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 136(%rsp), %rax + mulq 144(%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 136(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 144(%rsp), %rax + mulq 152(%rsp) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq 128(%rsp), %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %rbp + # A[1] * A[1] + movq 136(%rsp), %rax + mulq %rax + addq %rbp, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[2] * A[2] + movq 144(%rsp), %rax + mulq %rax + addq %rbp, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[3] * A[3] + movq 152(%rsp), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rbp, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, 96(%rsp) + movq %r9, 104(%rsp) + movq %r10, 112(%rsp) + movq %r11, 120(%rsp) + # Square + # A[0] * A[1] + movq (%rdi), %rax + mulq 8(%rdi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rdi), %rax + mulq 16(%rdi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rdi), %rax + mulq 24(%rdi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rdi), %rax + mulq 16(%rdi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rdi), %rax + mulq 24(%rdi) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rdi), %rax + mulq 24(%rdi) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rdi), %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %rbp + # A[1] * A[1] + movq 8(%rdi), %rax + mulq %rax + addq %rbp, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[2] * A[2] + movq 16(%rdi), %rax + mulq %rax + addq %rbp, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[3] * A[3] + movq 24(%rdi), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rbp, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, 128(%rsp) + movq %r9, 136(%rsp) + movq %r10, 144(%rsp) + movq %r11, 152(%rsp) + # Add + movq 32(%rsp), %rcx + movq 40(%rsp), %r9 + movq 48(%rsp), %r10 + movq 56(%rsp), %rbp + movq %rcx, %r12 + addq (%rsp), %rcx + movq %r9, %r13 + adcq 8(%rsp), %r9 + movq %r10, %r14 + adcq 16(%rsp), %r10 + movq %rbp, %r15 + adcq 24(%rsp), %rbp + movq $-19, %rax + movq %rbp, %r11 + movq $0x7fffffffffffffff, %rdx + sarq $63, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Sub modulus (if overflow) + subq %rax, %rcx + sbbq %rbp, %r9 + sbbq %rbp, %r10 + sbbq %rdx, %r11 + # Sub + subq (%rsp), %r12 + movq $0x00, %rbp + sbbq 8(%rsp), %r13 + movq $-19, %rax + sbbq 16(%rsp), %r14 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rsp), %r15 + sbbq $0x00, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Add modulus (if underflow) + addq %rax, %r12 + adcq %rbp, %r13 + adcq %rbp, %r14 + adcq %rdx, %r15 + movq %rcx, 64(%rsp) + movq %r9, 72(%rsp) + movq %r10, 80(%rsp) + movq %r11, 88(%rsp) + movq %r12, (%rsp) + movq %r13, 8(%rsp) + movq %r14, 16(%rsp) + movq %r15, 24(%rsp) + # Multiply + # A[0] * B[0] + movq 96(%rsp), %rax + mulq 128(%rsp) + movq %rax, %rcx + movq %rdx, %r9 + # A[0] * B[1] + movq 104(%rsp), %rax + mulq 128(%rsp) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq 96(%rsp), %rax + mulq 136(%rsp) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 112(%rsp), %rax + mulq 128(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 104(%rsp), %rax + mulq 136(%rsp) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq 96(%rsp), %rax + mulq 144(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 120(%rsp), %rax + mulq 128(%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 112(%rsp), %rax + mulq 136(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 104(%rsp), %rax + mulq 144(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq 96(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 120(%rsp), %rax + mulq 136(%rsp) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 112(%rsp), %rax + mulq 144(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 104(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 120(%rsp), %rax + mulq 144(%rsp) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 112(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 120(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + # Sub + movq 128(%rsp), %rcx + movq 136(%rsp), %r9 + movq 144(%rsp), %r10 + movq 152(%rsp), %r11 + subq 96(%rsp), %rcx + movq $0x00, %rbp + sbbq 104(%rsp), %r9 + movq $-19, %rax + sbbq 112(%rsp), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 120(%rsp), %r11 + sbbq $0x00, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Add modulus (if underflow) + addq %rax, %rcx + adcq %rbp, %r9 + adcq %rbp, %r10 + adcq %rdx, %r11 + movq %rcx, 128(%rsp) + movq %r9, 136(%rsp) + movq %r10, 144(%rsp) + movq %r11, 152(%rsp) + # Square + # A[0] * A[1] + movq (%rsp), %rax + mulq 8(%rsp) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rsp), %rax + mulq 16(%rsp) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rsp), %rax + mulq 24(%rsp) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rsp), %rax + mulq 16(%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rsp), %rax + mulq 24(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rsp), %rax + mulq 24(%rsp) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rsp), %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %rbp + # A[1] * A[1] + movq 8(%rsp), %rax + mulq %rax + addq %rbp, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[2] * A[2] + movq 16(%rsp), %rax + mulq %rax + addq %rbp, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[3] * A[3] + movq 24(%rsp), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rbp, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, (%rsp) + movq %r9, 8(%rsp) + movq %r10, 16(%rsp) + movq %r11, 24(%rsp) + # Multiply by 121666 + movq $0x1db42, %rax + mulq 128(%rsp) + xorq %r10, %r10 + movq %rax, %rcx + movq %rdx, %r9 + movq $0x1db42, %rax + mulq 136(%rsp) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + movq $0x1db42, %rax + mulq 144(%rsp) + xorq %r13, %r13 + addq %rax, %r10 + adcq %rdx, %r11 + movq $0x1db42, %rax + mulq 152(%rsp) + movq $0x7fffffffffffffff, %r12 + addq %rax, %r11 + adcq %rdx, %r13 + shldq $0x01, %r11, %r13 + andq %r12, %r11 + movq $19, %rax + mulq %r13 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + movq %rcx, 32(%rsp) + movq %r9, 40(%rsp) + movq %r10, 48(%rsp) + movq %r11, 56(%rsp) + # Square + # A[0] * A[1] + movq 64(%rsp), %rax + mulq 72(%rsp) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq 64(%rsp), %rax + mulq 80(%rsp) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq 64(%rsp), %rax + mulq 88(%rsp) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 72(%rsp), %rax + mulq 80(%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 72(%rsp), %rax + mulq 88(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 80(%rsp), %rax + mulq 88(%rsp) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq 64(%rsp), %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %rbp + # A[1] * A[1] + movq 72(%rsp), %rax + mulq %rax + addq %rbp, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[2] * A[2] + movq 80(%rsp), %rax + mulq %rax + addq %rbp, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[3] * A[3] + movq 88(%rsp), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rbp, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, 64(%rsp) + movq %r9, 72(%rsp) + movq %r10, 80(%rsp) + movq %r11, 88(%rsp) + # Add + movq 96(%rsp), %rcx + movq 104(%rsp), %r9 + addq 32(%rsp), %rcx + movq 112(%rsp), %r10 + adcq 40(%rsp), %r9 + movq 120(%rsp), %rbp + adcq 48(%rsp), %r10 + movq $-19, %rax + adcq 56(%rsp), %rbp + movq $0x7fffffffffffffff, %rdx + movq %rbp, %r11 + sarq $63, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Sub modulus (if overflow) + subq %rax, %rcx + sbbq %rbp, %r9 + sbbq %rbp, %r10 + sbbq %rdx, %r11 + movq %rcx, 96(%rsp) + movq %r9, 104(%rsp) + movq %r10, 112(%rsp) + movq %r11, 120(%rsp) + # Multiply + # A[0] * B[0] + movq (%rsp), %rax + mulq (%r8) + movq %rax, %rcx + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rsp), %rax + mulq (%r8) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rsp), %rax + mulq 8(%r8) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rsp), %rax + mulq (%r8) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rsp), %rax + mulq 8(%r8) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rsp), %rax + mulq 16(%r8) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rsp), %rax + mulq (%r8) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rsp), %rax + mulq 8(%r8) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rsp), %rax + mulq 16(%r8) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rsp), %rax + mulq 24(%r8) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rsp), %rax + mulq 8(%r8) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rsp), %rax + mulq 16(%r8) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rsp), %rax + mulq 24(%r8) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rsp), %rax + mulq 16(%r8) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rsp), %rax + mulq 24(%r8) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rsp), %rax + mulq 24(%r8) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, 32(%rsp) + movq %r9, 40(%rsp) + movq %r10, 48(%rsp) + movq %r11, 56(%rsp) + # Multiply + # A[0] * B[0] + movq 96(%rsp), %rax + mulq 128(%rsp) + movq %rax, %rcx + movq %rdx, %r9 + # A[0] * B[1] + movq 104(%rsp), %rax + mulq 128(%rsp) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq 96(%rsp), %rax + mulq 136(%rsp) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 112(%rsp), %rax + mulq 128(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 104(%rsp), %rax + mulq 136(%rsp) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq 96(%rsp), %rax + mulq 144(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 120(%rsp), %rax + mulq 128(%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 112(%rsp), %rax + mulq 136(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 104(%rsp), %rax + mulq 144(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq 96(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 120(%rsp), %rax + mulq 136(%rsp) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 112(%rsp), %rax + mulq 144(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 104(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 120(%rsp), %rax + mulq 144(%rsp) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 112(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 120(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, (%rsp) + movq %r9, 8(%rsp) + movq %r10, 16(%rsp) + movq %r11, 24(%rsp) + decb 168(%rsp) + jge L_curve25519_x64_bits + movq $63, 168(%rsp) + decb 160(%rsp) + jge L_curve25519_x64_words + # Invert + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + movq %rsp, %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 96(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $4, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $9, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 128(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 128(%rsp), %rdi + leaq 128(%rsp), %rsi + movq $19, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 128(%rsp), %rsi + leaq 96(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $9, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $49, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 128(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 128(%rsp), %rdi + leaq 128(%rsp), %rsi + movq $0x63, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 128(%rsp), %rsi + leaq 96(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $49, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $4, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq 176(%rsp), %rdi + # Multiply + # A[0] * B[0] + movq (%rsp), %rax + mulq (%rdi) + movq %rax, %rcx + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rsp), %rax + mulq (%rdi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rsp), %rax + mulq 8(%rdi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rsp), %rax + mulq (%rdi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rsp), %rax + mulq 8(%rdi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rsp), %rax + mulq 16(%rdi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rsp), %rax + mulq (%rdi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rsp), %rax + mulq 8(%rdi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rsp), %rax + mulq 16(%rdi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rsp), %rax + mulq 24(%rdi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rsp), %rax + mulq 8(%rdi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rsp), %rax + mulq 16(%rdi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rsp), %rax + mulq 24(%rdi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rsp), %rax + mulq 16(%rdi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rsp), %rax + mulq 24(%rdi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rsp), %rax + mulq 24(%rdi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + xorq %rax, %rax + addq $0xb8, %rsp + popq %rbp + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size curve25519_x64,.-curve25519_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_pow22523_x64 +.type fe_pow22523_x64,@function +.align 4 +fe_pow22523_x64: +#else +.section __TEXT,__text +.globl _fe_pow22523_x64 +.p2align 2 +_fe_pow22523_x64: +#endif /* __APPLE__ */ + subq $0x70, %rsp + # pow22523 + movq %rdi, 96(%rsp) + movq %rsi, 104(%rsp) + movq %rsp, %rdi + movq 104(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq 104(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq $4, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq $9, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $19, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq $9, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq $49, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $0x63, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq $49, %rdx +#ifndef __APPLE__ + callq fe_sq_n_x64@plt +#else + callq _fe_sq_n_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movq 96(%rsp), %rdi + movq %rsp, %rsi + movq 104(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq 104(%rsp), %rsi + movq 96(%rsp), %rdi + addq $0x70, %rsp + repz retq +#ifndef __APPLE__ +.text +.globl fe_ge_to_p2_x64 +.type fe_ge_to_p2_x64,@function +.align 4 +fe_ge_to_p2_x64: +#else +.section __TEXT,__text +.globl _fe_ge_to_p2_x64 +.p2align 2 +_fe_ge_to_p2_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $40, %rsp + movq %rsi, (%rsp) + movq %rdx, 8(%rsp) + movq %rcx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) + movq 16(%rsp), %rsi + movq 88(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 24(%rsp), %rsi + movq 32(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 32(%rsp), %rsi + movq 88(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_to_p2_x64,.-fe_ge_to_p2_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_to_p3_x64 +.type fe_ge_to_p3_x64,@function +.align 4 +fe_ge_to_p3_x64: +#else +.section __TEXT,__text +.globl _fe_ge_to_p3_x64 +.p2align 2 +_fe_ge_to_p3_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $40, %rsp + movq %rsi, (%rsp) + movq %rdx, 8(%rsp) + movq %rcx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) + movq 24(%rsp), %rsi + movq 96(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 32(%rsp), %rsi + movq 88(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 88(%rsp), %rsi + movq 96(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq 24(%rsp), %rsi + movq 32(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_to_p3_x64,.-fe_ge_to_p3_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_dbl_x64 +.type fe_ge_dbl_x64,@function +.align 4 +fe_ge_dbl_x64: +#else +.section __TEXT,__text +.globl _fe_ge_dbl_x64 +.p2align 2 +_fe_ge_dbl_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsp), %rdi + movq 32(%rsp), %rsi + # Square + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %r8 + movq %rdx, %rcx + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rcx, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rcx, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rcx, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq 40(%rsp), %rsi + # Square + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %r8 + movq %rdx, %rcx + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rcx, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rcx, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rcx, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + movq 128(%rsp), %rsi + # Square * 2 + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %r8 + movq %rdx, %rcx + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rcx, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rcx, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rcx, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbx + xorq %rax, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $3, %r15, %rax + shldq $2, %r14, %r15 + shldq $2, %r13, %r14 + shldq $2, %r12, %r13 + shldq $2, %r11, %r12 + shldq $0x01, %r10, %r11 + shldq $0x01, %r9, %r10 + shldq $0x01, %r8, %r9 + shlq $0x01, %r8 + andq %rbx, %r11 + # Two out left, one in right + andq %rbx, %r15 + # Multiply top bits by 19*19 + imulq $0x169, %rax, %rcx + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining produce results in + addq %rcx, %r8 + adcq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 32(%rsp), %rsi + movq 40(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rdi + movq 8(%rsp), %rsi + # Square + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %r8 + movq %rdx, %rcx + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rcx, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rcx, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rcx, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 16(%rsp), %rsi + movq (%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq 16(%rsp), %rsi + movq (%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + leaq 48(%rsp), %rsi + movq 8(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + movq 24(%rsp), %rsi + movq 16(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_dbl_x64,.-fe_ge_dbl_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_madd_x64 +.type fe_ge_madd_x64,@function +.align 4 +fe_ge_madd_x64: +#else +.section __TEXT,__text +.globl _fe_ge_madd_x64 +.p2align 2 +_fe_ge_madd_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq (%rsp), %rsi + movq 152(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 8(%rsp), %rsi + movq 160(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + movq 144(%rsp), %rsi + movq 136(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rdi + movq 128(%rsp), %rsi + movq 128(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_madd_x64,.-fe_ge_madd_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_msub_x64 +.type fe_ge_msub_x64,@function +.align 4 +fe_ge_msub_x64: +#else +.section __TEXT,__text +.globl _fe_ge_msub_x64 +.p2align 2 +_fe_ge_msub_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq (%rsp), %rsi + movq 160(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 8(%rsp), %rsi + movq 152(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + movq 144(%rsp), %rsi + movq 136(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rdi + movq 128(%rsp), %rsi + movq 128(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_msub_x64,.-fe_ge_msub_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_add_x64 +.type fe_ge_add_x64,@function +.align 4 +fe_ge_add_x64: +#else +.section __TEXT,__text +.globl _fe_ge_add_x64 +.p2align 2 +_fe_ge_add_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq (%rsp), %rsi + movq 160(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 8(%rsp), %rsi + movq 168(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + movq 152(%rsp), %rsi + movq 136(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 128(%rsp), %rsi + movq 144(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rdi + movq (%rsp), %rsi + movq (%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_add_x64,.-fe_ge_add_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_sub_x64 +.type fe_ge_sub_x64,@function +.align 4 +fe_ge_sub_x64: +#else +.section __TEXT,__text +.globl _fe_ge_sub_x64 +.p2align 2 +_fe_ge_sub_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq (%rsp), %rsi + movq 168(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 8(%rsp), %rsi + movq 160(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + movq 152(%rsp), %rsi + movq 136(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 128(%rsp), %rsi + movq 144(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rdi + movq (%rsp), %rsi + movq (%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_sub_x64,.-fe_ge_sub_x64 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ +.text +.globl fe_mul_avx2 +.type fe_mul_avx2,@function +.align 4 +fe_mul_avx2: +#else +.section __TEXT,__text +.globl _fe_mul_avx2 +.p2align 2 +_fe_mul_avx2: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + movq %rdx, %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rax, %rcx + xorq %r15, %r15 + adcxq %rax, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rcx, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rax, %rcx + adoxq %rax, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rax, %r14 + adoxq %rcx, %r10 + adcxq %rax, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rax, %rcx + adcxq %r14, %r12 + adoxq %rax, %r11 + adcxq %r15, %r13 + adoxq %rcx, %r12 + # A[0] * B[2] + mulxq (%rsi), %rax, %rcx + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rax, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rax + adcxq %rcx, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rax, %r11 + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rax + adcxq %rcx, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rax, %r13 + mulxq 24(%rsi), %rax, %rcx + adoxq %r15, %r14 + adcxq %rax, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rax + adcxq %rcx, %r15 + xorq %rcx, %rcx + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rax, %r12 + mulxq 24(%rsi), %rdx, %rax + adoxq %rdx, %r11 + adoxq %rax, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rax + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rax, %r14 + mulxq 24(%rsi), %rax, %rdx + adcxq %rcx, %r15 + adoxq %rax, %r13 + adoxq %rdx, %r14 + adoxq %rcx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r12, %rax, %r12 + adcxq %rax, %r8 + adoxq %r12, %r9 + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_mul_avx2,.-fe_mul_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq_avx2 +.type fe_sq_avx2,@function +.align 4 +fe_sq_avx2: +#else +.section __TEXT,__text +.globl _fe_sq_avx2 +.p2align 2 +_fe_sq_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + # Square + # A[0] * A[1] + movq (%rsi), %rdx + mulxq 8(%rsi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rsi), %r11, %r12 + # A[2] * A[1] + movq 16(%rsi), %rdx + mulxq 8(%rsi), %rcx, %rbx + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rsi), %r13, %r14 + adoxq %rbx, %r12 + # A[2] * A[0] + mulxq (%rsi), %rcx, %rbx + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rsi), %rdx + mulxq 24(%rsi), %rax, %r8 + adcxq %rbx, %r11 + adcxq %rax, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rsi), %rdx + mulxq %rdx, %r8, %rax + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r10, %r10 + adoxq %rax, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r12, %r12 + adoxq %rbx, %r11 + adcxq %r13, %r13 + adoxq %rax, %r12 + # A[3] * A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rax, %r14 + adoxq %rbx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r12, %rax, %r12 + adcxq %rax, %r8 + adoxq %r12, %r9 + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_sq_avx2,.-fe_sq_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq_n_avx2 +.type fe_sq_n_avx2,@function +.align 4 +fe_sq_n_avx2: +#else +.section __TEXT,__text +.globl _fe_sq_n_avx2 +.p2align 2 +_fe_sq_n_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rdx, %rbp +L_fe_sq_n_avx2: + # Square + # A[0] * A[1] + movq (%rsi), %rdx + mulxq 8(%rsi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rsi), %r11, %r12 + # A[2] * A[1] + movq 16(%rsi), %rdx + mulxq 8(%rsi), %rcx, %rbx + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rsi), %r13, %r14 + adoxq %rbx, %r12 + # A[2] * A[0] + mulxq (%rsi), %rcx, %rbx + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rsi), %rdx + mulxq 24(%rsi), %rax, %r8 + adcxq %rbx, %r11 + adcxq %rax, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rsi), %rdx + mulxq %rdx, %r8, %rax + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r10, %r10 + adoxq %rax, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r12, %r12 + adoxq %rbx, %r11 + adcxq %r13, %r13 + adoxq %rax, %r12 + # A[3] * A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rax, %r14 + adoxq %rbx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r12, %rax, %r12 + adcxq %rax, %r8 + adoxq %r12, %r9 + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + decb %bpl + jnz L_fe_sq_n_avx2 + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_sq_n_avx2,.-fe_sq_n_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_mul121666_avx2 +.type fe_mul121666_avx2,@function +.align 4 +fe_mul121666_avx2: +#else +.section __TEXT,__text +.globl _fe_mul121666_avx2 +.p2align 2 +_fe_mul121666_avx2: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + movq $0x1db42, %rdx + mulxq (%rsi), %rax, %r13 + mulxq 8(%rsi), %rcx, %r12 + mulxq 16(%rsi), %r8, %r11 + mulxq 24(%rsi), %r9, %r10 + addq %r13, %rcx + adcq %r12, %r8 + adcq %r11, %r9 + adcq $0x00, %r10 + movq $0x7fffffffffffffff, %r13 + shldq $0x01, %r9, %r10 + andq %r13, %r9 + imulq $19, %r10, %r10 + addq %r10, %rax + adcq $0x00, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_mul121666_avx2,.-fe_mul121666_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq2_avx2 +.type fe_sq2_avx2,@function +.align 4 +fe_sq2_avx2: +#else +.section __TEXT,__text +.globl _fe_sq2_avx2 +.p2align 2 +_fe_sq2_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + # Square * 2 + # A[0] * A[1] + movq (%rsi), %rdx + mulxq 8(%rsi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rsi), %r11, %r12 + # A[2] * A[1] + movq 16(%rsi), %rdx + mulxq 8(%rsi), %rcx, %rbx + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rsi), %r13, %r14 + adoxq %rbx, %r12 + # A[2] * A[0] + mulxq (%rsi), %rcx, %rbx + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rsi), %rdx + mulxq 24(%rsi), %rax, %r8 + adcxq %rbx, %r11 + adcxq %rax, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rsi), %rdx + mulxq %rdx, %r8, %rax + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r10, %r10 + adoxq %rax, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r12, %r12 + adoxq %rbx, %r11 + adcxq %r13, %r13 + adoxq %rax, %r12 + # A[3] * A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rax, %r14 + adoxq %rbx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbx + xorq %rax, %rax + # Move top half into t4-t7 and remove top bit from t3 and double + shldq $3, %r15, %rax + shldq $2, %r14, %r15 + shldq $2, %r13, %r14 + shldq $2, %r12, %r13 + shldq $2, %r11, %r12 + shldq $0x01, %r10, %r11 + shldq $0x01, %r9, %r10 + shldq $0x01, %r8, %r9 + shlq $0x01, %r8 + andq %rbx, %r11 + # Two out left, one in right + andq %rbx, %r15 + # Multiply top bits by 19*19 + imulq $0x169, %rax, %rcx + xorq %rbx, %rbx + # Multiply top half by 19 + movq $19, %rdx + adoxq %rcx, %r8 + mulxq %r12, %rax, %r12 + adcxq %rax, %r8 + adoxq %r12, %r9 + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_sq2_avx2,.-fe_sq2_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_invert_avx2 +.type fe_invert_avx2,@function +.align 4 +fe_invert_avx2: +#else +.section __TEXT,__text +.globl _fe_invert_avx2 +.p2align 2 +_fe_invert_avx2: +#endif /* __APPLE__ */ + subq $0x90, %rsp + # Invert + movq %rdi, 128(%rsp) + movq %rsi, 136(%rsp) + movq %rsp, %rdi + movq 136(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq 136(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $4, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $9, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $19, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $9, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $49, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $0x63, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $49, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq $4, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + movq 128(%rsp), %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq 136(%rsp), %rsi + movq 128(%rsp), %rdi + addq $0x90, %rsp + repz retq +#ifndef __APPLE__ +.text +.globl curve25519_avx2 +.type curve25519_avx2,@function +.align 4 +curve25519_avx2: +#else +.section __TEXT,__text +.globl _curve25519_avx2 +.p2align 2 +_curve25519_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rdx, %r8 + subq $0xc0, %rsp + movq $0x00, 184(%rsp) + movq %rdi, 176(%rsp) + # Set one + movq $0x01, (%rdi) + movq $0x00, 8(%rdi) + movq $0x00, 16(%rdi) + movq $0x00, 24(%rdi) + # Set zero + movq $0x00, (%rsp) + movq $0x00, 8(%rsp) + movq $0x00, 16(%rsp) + movq $0x00, 24(%rsp) + # Set one + movq $0x01, 32(%rsp) + movq $0x00, 40(%rsp) + movq $0x00, 48(%rsp) + movq $0x00, 56(%rsp) + # Copy + movq (%r8), %r9 + movq 8(%r8), %r10 + movq 16(%r8), %r11 + movq 24(%r8), %r12 + movq %r9, 64(%rsp) + movq %r10, 72(%rsp) + movq %r11, 80(%rsp) + movq %r12, 88(%rsp) + movb $62, 168(%rsp) + movq $3, 160(%rsp) +L_curve25519_avx2_words: +L_curve25519_avx2_bits: + movq 184(%rsp), %rbx + movq 160(%rsp), %r9 + movb 168(%rsp), %cl + movq (%rsi,%r9,8), %rax + shrq %cl, %rax + andq $0x01, %rax + xorq %rax, %rbx + negq %rbx + # Conditional Swap + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + xorq 64(%rsp), %r9 + xorq 72(%rsp), %r10 + xorq 80(%rsp), %r11 + xorq 88(%rsp), %r12 + andq %rbx, %r9 + andq %rbx, %r10 + andq %rbx, %r11 + andq %rbx, %r12 + xorq %r9, (%rdi) + xorq %r10, 8(%rdi) + xorq %r11, 16(%rdi) + xorq %r12, 24(%rdi) + xorq %r9, 64(%rsp) + xorq %r10, 72(%rsp) + xorq %r11, 80(%rsp) + xorq %r12, 88(%rsp) + # Conditional Swap + movq (%rsp), %r9 + movq 8(%rsp), %r10 + movq 16(%rsp), %r11 + movq 24(%rsp), %r12 + xorq 32(%rsp), %r9 + xorq 40(%rsp), %r10 + xorq 48(%rsp), %r11 + xorq 56(%rsp), %r12 + andq %rbx, %r9 + andq %rbx, %r10 + andq %rbx, %r11 + andq %rbx, %r12 + xorq %r9, (%rsp) + xorq %r10, 8(%rsp) + xorq %r11, 16(%rsp) + xorq %r12, 24(%rsp) + xorq %r9, 32(%rsp) + xorq %r10, 40(%rsp) + xorq %r11, 48(%rsp) + xorq %r12, 56(%rsp) + movq %rax, 184(%rsp) + # Add + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %rax + movq %r9, %r13 + addq (%rsp), %r9 + movq %r10, %r14 + adcq 8(%rsp), %r10 + movq %r11, %r15 + adcq 16(%rsp), %r11 + movq %rax, %rbp + adcq 24(%rsp), %rax + movq $-19, %rcx + movq %rax, %r12 + movq $0x7fffffffffffffff, %rbx + sarq $63, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Sub modulus (if overflow) + subq %rcx, %r9 + sbbq %rax, %r10 + sbbq %rax, %r11 + sbbq %rbx, %r12 + # Sub + subq (%rsp), %r13 + movq $0x00, %rax + sbbq 8(%rsp), %r14 + movq $-19, %rcx + sbbq 16(%rsp), %r15 + movq $0x7fffffffffffffff, %rbx + sbbq 24(%rsp), %rbp + sbbq $0x00, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Add modulus (if underflow) + addq %rcx, %r13 + adcq %rax, %r14 + adcq %rax, %r15 + adcq %rbx, %rbp + movq %r9, (%rdi) + movq %r10, 8(%rdi) + movq %r11, 16(%rdi) + movq %r12, 24(%rdi) + movq %r13, 128(%rsp) + movq %r14, 136(%rsp) + movq %r15, 144(%rsp) + movq %rbp, 152(%rsp) + # Add + movq 64(%rsp), %r9 + movq 72(%rsp), %r10 + movq 80(%rsp), %r11 + movq 88(%rsp), %rax + movq %r9, %r13 + addq 32(%rsp), %r9 + movq %r10, %r14 + adcq 40(%rsp), %r10 + movq %r11, %r15 + adcq 48(%rsp), %r11 + movq %rax, %rbp + adcq 56(%rsp), %rax + movq $-19, %rcx + movq %rax, %r12 + movq $0x7fffffffffffffff, %rbx + sarq $63, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Sub modulus (if overflow) + subq %rcx, %r9 + sbbq %rax, %r10 + sbbq %rax, %r11 + sbbq %rbx, %r12 + # Sub + subq 32(%rsp), %r13 + movq $0x00, %rax + sbbq 40(%rsp), %r14 + movq $-19, %rcx + sbbq 48(%rsp), %r15 + movq $0x7fffffffffffffff, %rbx + sbbq 56(%rsp), %rbp + sbbq $0x00, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Add modulus (if underflow) + addq %rcx, %r13 + adcq %rax, %r14 + adcq %rax, %r15 + adcq %rbx, %rbp + movq %r9, (%rsp) + movq %r10, 8(%rsp) + movq %r11, 16(%rsp) + movq %r12, 24(%rsp) + movq %r13, 96(%rsp) + movq %r14, 104(%rsp) + movq %r15, 112(%rsp) + movq %rbp, 120(%rsp) + # Multiply + # A[0] * B[0] + movq (%rdi), %rdx + mulxq 96(%rsp), %r9, %r10 + # A[2] * B[0] + mulxq 112(%rsp), %r11, %r12 + # A[1] * B[0] + mulxq 104(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adcxq %rcx, %r10 + # A[1] * B[3] + movq 24(%rdi), %rdx + mulxq 104(%rsp), %r13, %r14 + adcxq %rbx, %r11 + # A[0] * B[1] + movq 8(%rdi), %rdx + mulxq 96(%rsp), %rcx, %rbx + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 112(%rsp), %rcx, %r15 + adoxq %rbx, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 16(%rdi), %rdx + mulxq 104(%rsp), %rcx, %rbx + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbp, %r14 + adoxq %rbx, %r13 + # A[0] * B[2] + mulxq 96(%rsp), %rcx, %rbx + adoxq %rbp, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 8(%rdi), %rdx + mulxq 104(%rsp), %rdx, %rcx + adcxq %rbx, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 8(%rdi), %rdx + adoxq %rcx, %r12 + mulxq 120(%rsp), %rcx, %rbx + adcxq %rcx, %r13 + # A[2] * B[2] + movq 16(%rdi), %rdx + mulxq 112(%rsp), %rdx, %rcx + adcxq %rbx, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 24(%rdi), %rdx + adoxq %rcx, %r14 + mulxq 120(%rsp), %rcx, %rbx + adoxq %rbp, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq 96(%rsp), %rdx, %rcx + adcxq %rbx, %rbp + xorq %rbx, %rbx + adcxq %rdx, %r12 + # A[3] * B[0] + movq (%rdi), %rdx + adcxq %rcx, %r13 + mulxq 120(%rsp), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 24(%rdi), %rdx + mulxq 112(%rsp), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 16(%rdi), %rdx + adcxq %rcx, %r15 + mulxq 120(%rsp), %rcx, %rdx + adcxq %rbx, %rbp + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rbx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rbx, %rbx + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %rcx, %r15 + adcxq %rcx, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, 32(%rsp) + movq %r10, 40(%rsp) + movq %r11, 48(%rsp) + movq %r12, 56(%rsp) + # Multiply + # A[0] * B[0] + movq 128(%rsp), %rdx + mulxq (%rsp), %r9, %r10 + # A[2] * B[0] + mulxq 16(%rsp), %r11, %r12 + # A[1] * B[0] + mulxq 8(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adcxq %rcx, %r10 + # A[1] * B[3] + movq 152(%rsp), %rdx + mulxq 8(%rsp), %r13, %r14 + adcxq %rbx, %r11 + # A[0] * B[1] + movq 136(%rsp), %rdx + mulxq (%rsp), %rcx, %rbx + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 16(%rsp), %rcx, %r15 + adoxq %rbx, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 144(%rsp), %rdx + mulxq 8(%rsp), %rcx, %rbx + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbp, %r14 + adoxq %rbx, %r13 + # A[0] * B[2] + mulxq (%rsp), %rcx, %rbx + adoxq %rbp, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 136(%rsp), %rdx + mulxq 8(%rsp), %rdx, %rcx + adcxq %rbx, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 136(%rsp), %rdx + adoxq %rcx, %r12 + mulxq 24(%rsp), %rcx, %rbx + adcxq %rcx, %r13 + # A[2] * B[2] + movq 144(%rsp), %rdx + mulxq 16(%rsp), %rdx, %rcx + adcxq %rbx, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 152(%rsp), %rdx + adoxq %rcx, %r14 + mulxq 24(%rsp), %rcx, %rbx + adoxq %rbp, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq (%rsp), %rdx, %rcx + adcxq %rbx, %rbp + xorq %rbx, %rbx + adcxq %rdx, %r12 + # A[3] * B[0] + movq 128(%rsp), %rdx + adcxq %rcx, %r13 + mulxq 24(%rsp), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 152(%rsp), %rdx + mulxq 16(%rsp), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 144(%rsp), %rdx + adcxq %rcx, %r15 + mulxq 24(%rsp), %rcx, %rdx + adcxq %rbx, %rbp + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rbx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rbx, %rbx + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %rcx, %r15 + adcxq %rcx, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, (%rsp) + movq %r10, 8(%rsp) + movq %r11, 16(%rsp) + movq %r12, 24(%rsp) + # Square + # A[0] * A[1] + movq 128(%rsp), %rdx + mulxq 136(%rsp), %r10, %r11 + # A[0] * A[3] + mulxq 152(%rsp), %r12, %r13 + # A[2] * A[1] + movq 144(%rsp), %rdx + mulxq 136(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adoxq %rcx, %r12 + # A[2] * A[3] + mulxq 152(%rsp), %r14, %r15 + adoxq %rbx, %r13 + # A[2] * A[0] + mulxq 128(%rsp), %rcx, %rbx + adoxq %rbp, %r14 + adcxq %rcx, %r11 + adoxq %rbp, %r15 + # A[1] * A[3] + movq 136(%rsp), %rdx + mulxq 152(%rsp), %rax, %r9 + adcxq %rbx, %r12 + adcxq %rax, %r13 + adcxq %r9, %r14 + adcxq %rbp, %r15 + # Double with Carry Flag + xorq %rbp, %rbp + # A[0] * A[0] + movq 128(%rsp), %rdx + mulxq %rdx, %r9, %rax + adcxq %r10, %r10 + # A[1] * A[1] + movq 136(%rsp), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r11, %r11 + adoxq %rax, %r10 + adcxq %r12, %r12 + adoxq %rcx, %r11 + # A[2] * A[2] + movq 144(%rsp), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r13, %r13 + adoxq %rbx, %r12 + adcxq %r14, %r14 + adoxq %rax, %r13 + # A[3] * A[3] + movq 152(%rsp), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r15, %r15 + adoxq %rcx, %r14 + adcxq %rbp, %rbp + adoxq %rax, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rcx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %rax, %r15 + adcxq %rax, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, 96(%rsp) + movq %r10, 104(%rsp) + movq %r11, 112(%rsp) + movq %r12, 120(%rsp) + # Square + # A[0] * A[1] + movq (%rdi), %rdx + mulxq 8(%rdi), %r10, %r11 + # A[0] * A[3] + mulxq 24(%rdi), %r12, %r13 + # A[2] * A[1] + movq 16(%rdi), %rdx + mulxq 8(%rdi), %rcx, %rbx + xorq %rbp, %rbp + adoxq %rcx, %r12 + # A[2] * A[3] + mulxq 24(%rdi), %r14, %r15 + adoxq %rbx, %r13 + # A[2] * A[0] + mulxq (%rdi), %rcx, %rbx + adoxq %rbp, %r14 + adcxq %rcx, %r11 + adoxq %rbp, %r15 + # A[1] * A[3] + movq 8(%rdi), %rdx + mulxq 24(%rdi), %rax, %r9 + adcxq %rbx, %r12 + adcxq %rax, %r13 + adcxq %r9, %r14 + adcxq %rbp, %r15 + # Double with Carry Flag + xorq %rbp, %rbp + # A[0] * A[0] + movq (%rdi), %rdx + mulxq %rdx, %r9, %rax + adcxq %r10, %r10 + # A[1] * A[1] + movq 8(%rdi), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r11, %r11 + adoxq %rax, %r10 + adcxq %r12, %r12 + adoxq %rcx, %r11 + # A[2] * A[2] + movq 16(%rdi), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r13, %r13 + adoxq %rbx, %r12 + adcxq %r14, %r14 + adoxq %rax, %r13 + # A[3] * A[3] + movq 24(%rdi), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r15, %r15 + adoxq %rcx, %r14 + adcxq %rbp, %rbp + adoxq %rax, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rcx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %rax, %r15 + adcxq %rax, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, 128(%rsp) + movq %r10, 136(%rsp) + movq %r11, 144(%rsp) + movq %r12, 152(%rsp) + # Add + movq 32(%rsp), %r9 + movq 40(%rsp), %r10 + movq 48(%rsp), %r11 + movq 56(%rsp), %rax + movq %r9, %r13 + addq (%rsp), %r9 + movq %r10, %r14 + adcq 8(%rsp), %r10 + movq %r11, %r15 + adcq 16(%rsp), %r11 + movq %rax, %rbp + adcq 24(%rsp), %rax + movq $-19, %rcx + movq %rax, %r12 + movq $0x7fffffffffffffff, %rbx + sarq $63, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Sub modulus (if overflow) + subq %rcx, %r9 + sbbq %rax, %r10 + sbbq %rax, %r11 + sbbq %rbx, %r12 + # Sub + subq (%rsp), %r13 + movq $0x00, %rax + sbbq 8(%rsp), %r14 + movq $-19, %rcx + sbbq 16(%rsp), %r15 + movq $0x7fffffffffffffff, %rbx + sbbq 24(%rsp), %rbp + sbbq $0x00, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Add modulus (if underflow) + addq %rcx, %r13 + adcq %rax, %r14 + adcq %rax, %r15 + adcq %rbx, %rbp + movq %r9, 64(%rsp) + movq %r10, 72(%rsp) + movq %r11, 80(%rsp) + movq %r12, 88(%rsp) + movq %r13, (%rsp) + movq %r14, 8(%rsp) + movq %r15, 16(%rsp) + movq %rbp, 24(%rsp) + # Multiply + # A[0] * B[0] + movq 96(%rsp), %rdx + mulxq 128(%rsp), %r9, %r10 + # A[2] * B[0] + mulxq 144(%rsp), %r11, %r12 + # A[1] * B[0] + mulxq 136(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adcxq %rcx, %r10 + # A[1] * B[3] + movq 120(%rsp), %rdx + mulxq 136(%rsp), %r13, %r14 + adcxq %rbx, %r11 + # A[0] * B[1] + movq 104(%rsp), %rdx + mulxq 128(%rsp), %rcx, %rbx + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 144(%rsp), %rcx, %r15 + adoxq %rbx, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 112(%rsp), %rdx + mulxq 136(%rsp), %rcx, %rbx + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbp, %r14 + adoxq %rbx, %r13 + # A[0] * B[2] + mulxq 128(%rsp), %rcx, %rbx + adoxq %rbp, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 104(%rsp), %rdx + mulxq 136(%rsp), %rdx, %rcx + adcxq %rbx, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 104(%rsp), %rdx + adoxq %rcx, %r12 + mulxq 152(%rsp), %rcx, %rbx + adcxq %rcx, %r13 + # A[2] * B[2] + movq 112(%rsp), %rdx + mulxq 144(%rsp), %rdx, %rcx + adcxq %rbx, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 120(%rsp), %rdx + adoxq %rcx, %r14 + mulxq 152(%rsp), %rcx, %rbx + adoxq %rbp, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq 128(%rsp), %rdx, %rcx + adcxq %rbx, %rbp + xorq %rbx, %rbx + adcxq %rdx, %r12 + # A[3] * B[0] + movq 96(%rsp), %rdx + adcxq %rcx, %r13 + mulxq 152(%rsp), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 120(%rsp), %rdx + mulxq 144(%rsp), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 112(%rsp), %rdx + adcxq %rcx, %r15 + mulxq 152(%rsp), %rcx, %rdx + adcxq %rbx, %rbp + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rbx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rbx, %rbx + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %rcx, %r15 + adcxq %rcx, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, (%rdi) + movq %r10, 8(%rdi) + movq %r11, 16(%rdi) + movq %r12, 24(%rdi) + # Sub + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + subq 96(%rsp), %r9 + movq $0x00, %rax + sbbq 104(%rsp), %r10 + movq $-19, %rcx + sbbq 112(%rsp), %r11 + movq $0x7fffffffffffffff, %rbx + sbbq 120(%rsp), %r12 + sbbq $0x00, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Add modulus (if underflow) + addq %rcx, %r9 + adcq %rax, %r10 + adcq %rax, %r11 + adcq %rbx, %r12 + movq %r9, 128(%rsp) + movq %r10, 136(%rsp) + movq %r11, 144(%rsp) + movq %r12, 152(%rsp) + # Square + # A[0] * A[1] + movq (%rsp), %rdx + mulxq 8(%rsp), %r10, %r11 + # A[0] * A[3] + mulxq 24(%rsp), %r12, %r13 + # A[2] * A[1] + movq 16(%rsp), %rdx + mulxq 8(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adoxq %rcx, %r12 + # A[2] * A[3] + mulxq 24(%rsp), %r14, %r15 + adoxq %rbx, %r13 + # A[2] * A[0] + mulxq (%rsp), %rcx, %rbx + adoxq %rbp, %r14 + adcxq %rcx, %r11 + adoxq %rbp, %r15 + # A[1] * A[3] + movq 8(%rsp), %rdx + mulxq 24(%rsp), %rax, %r9 + adcxq %rbx, %r12 + adcxq %rax, %r13 + adcxq %r9, %r14 + adcxq %rbp, %r15 + # Double with Carry Flag + xorq %rbp, %rbp + # A[0] * A[0] + movq (%rsp), %rdx + mulxq %rdx, %r9, %rax + adcxq %r10, %r10 + # A[1] * A[1] + movq 8(%rsp), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r11, %r11 + adoxq %rax, %r10 + adcxq %r12, %r12 + adoxq %rcx, %r11 + # A[2] * A[2] + movq 16(%rsp), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r13, %r13 + adoxq %rbx, %r12 + adcxq %r14, %r14 + adoxq %rax, %r13 + # A[3] * A[3] + movq 24(%rsp), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r15, %r15 + adoxq %rcx, %r14 + adcxq %rbp, %rbp + adoxq %rax, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rcx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %rax, %r15 + adcxq %rax, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, (%rsp) + movq %r10, 8(%rsp) + movq %r11, 16(%rsp) + movq %r12, 24(%rsp) + movq $0x1db42, %rdx + mulxq 128(%rsp), %r9, %rbp + mulxq 136(%rsp), %r10, %r15 + mulxq 144(%rsp), %r11, %r14 + mulxq 152(%rsp), %r12, %r13 + addq %rbp, %r10 + adcq %r15, %r11 + adcq %r14, %r12 + adcq $0x00, %r13 + movq $0x7fffffffffffffff, %rbp + shldq $0x01, %r12, %r13 + andq %rbp, %r12 + imulq $19, %r13, %r13 + addq %r13, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + movq %r9, 32(%rsp) + movq %r10, 40(%rsp) + movq %r11, 48(%rsp) + movq %r12, 56(%rsp) + # Square + # A[0] * A[1] + movq 64(%rsp), %rdx + mulxq 72(%rsp), %r10, %r11 + # A[0] * A[3] + mulxq 88(%rsp), %r12, %r13 + # A[2] * A[1] + movq 80(%rsp), %rdx + mulxq 72(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adoxq %rcx, %r12 + # A[2] * A[3] + mulxq 88(%rsp), %r14, %r15 + adoxq %rbx, %r13 + # A[2] * A[0] + mulxq 64(%rsp), %rcx, %rbx + adoxq %rbp, %r14 + adcxq %rcx, %r11 + adoxq %rbp, %r15 + # A[1] * A[3] + movq 72(%rsp), %rdx + mulxq 88(%rsp), %rax, %r9 + adcxq %rbx, %r12 + adcxq %rax, %r13 + adcxq %r9, %r14 + adcxq %rbp, %r15 + # Double with Carry Flag + xorq %rbp, %rbp + # A[0] * A[0] + movq 64(%rsp), %rdx + mulxq %rdx, %r9, %rax + adcxq %r10, %r10 + # A[1] * A[1] + movq 72(%rsp), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r11, %r11 + adoxq %rax, %r10 + adcxq %r12, %r12 + adoxq %rcx, %r11 + # A[2] * A[2] + movq 80(%rsp), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r13, %r13 + adoxq %rbx, %r12 + adcxq %r14, %r14 + adoxq %rax, %r13 + # A[3] * A[3] + movq 88(%rsp), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r15, %r15 + adoxq %rcx, %r14 + adcxq %rbp, %rbp + adoxq %rax, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rcx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %rax, %r15 + adcxq %rax, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, 64(%rsp) + movq %r10, 72(%rsp) + movq %r11, 80(%rsp) + movq %r12, 88(%rsp) + # Add + movq 96(%rsp), %r9 + movq 104(%rsp), %r10 + addq 32(%rsp), %r9 + movq 112(%rsp), %r11 + adcq 40(%rsp), %r10 + movq 120(%rsp), %rax + adcq 48(%rsp), %r11 + movq $-19, %rcx + adcq 56(%rsp), %rax + movq $0x7fffffffffffffff, %rbx + movq %rax, %r12 + sarq $63, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Sub modulus (if overflow) + subq %rcx, %r9 + sbbq %rax, %r10 + sbbq %rax, %r11 + sbbq %rbx, %r12 + movq %r9, 96(%rsp) + movq %r10, 104(%rsp) + movq %r11, 112(%rsp) + movq %r12, 120(%rsp) + # Multiply + # A[0] * B[0] + movq (%rsp), %rdx + mulxq (%r8), %r9, %r10 + # A[2] * B[0] + mulxq 16(%r8), %r11, %r12 + # A[1] * B[0] + mulxq 8(%r8), %rcx, %rbx + xorq %rbp, %rbp + adcxq %rcx, %r10 + # A[1] * B[3] + movq 24(%rsp), %rdx + mulxq 8(%r8), %r13, %r14 + adcxq %rbx, %r11 + # A[0] * B[1] + movq 8(%rsp), %rdx + mulxq (%r8), %rcx, %rbx + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 16(%r8), %rcx, %r15 + adoxq %rbx, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 16(%rsp), %rdx + mulxq 8(%r8), %rcx, %rbx + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbp, %r14 + adoxq %rbx, %r13 + # A[0] * B[2] + mulxq (%r8), %rcx, %rbx + adoxq %rbp, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 8(%rsp), %rdx + mulxq 8(%r8), %rdx, %rcx + adcxq %rbx, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 8(%rsp), %rdx + adoxq %rcx, %r12 + mulxq 24(%r8), %rcx, %rbx + adcxq %rcx, %r13 + # A[2] * B[2] + movq 16(%rsp), %rdx + mulxq 16(%r8), %rdx, %rcx + adcxq %rbx, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 24(%rsp), %rdx + adoxq %rcx, %r14 + mulxq 24(%r8), %rcx, %rbx + adoxq %rbp, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq (%r8), %rdx, %rcx + adcxq %rbx, %rbp + xorq %rbx, %rbx + adcxq %rdx, %r12 + # A[3] * B[0] + movq (%rsp), %rdx + adcxq %rcx, %r13 + mulxq 24(%r8), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 24(%rsp), %rdx + mulxq 16(%r8), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 16(%rsp), %rdx + adcxq %rcx, %r15 + mulxq 24(%r8), %rcx, %rdx + adcxq %rbx, %rbp + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rbx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rbx, %rbx + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %rcx, %r15 + adcxq %rcx, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, 32(%rsp) + movq %r10, 40(%rsp) + movq %r11, 48(%rsp) + movq %r12, 56(%rsp) + # Multiply + # A[0] * B[0] + movq 96(%rsp), %rdx + mulxq 128(%rsp), %r9, %r10 + # A[2] * B[0] + mulxq 144(%rsp), %r11, %r12 + # A[1] * B[0] + mulxq 136(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adcxq %rcx, %r10 + # A[1] * B[3] + movq 120(%rsp), %rdx + mulxq 136(%rsp), %r13, %r14 + adcxq %rbx, %r11 + # A[0] * B[1] + movq 104(%rsp), %rdx + mulxq 128(%rsp), %rcx, %rbx + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 144(%rsp), %rcx, %r15 + adoxq %rbx, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 112(%rsp), %rdx + mulxq 136(%rsp), %rcx, %rbx + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbp, %r14 + adoxq %rbx, %r13 + # A[0] * B[2] + mulxq 128(%rsp), %rcx, %rbx + adoxq %rbp, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 104(%rsp), %rdx + mulxq 136(%rsp), %rdx, %rcx + adcxq %rbx, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 104(%rsp), %rdx + adoxq %rcx, %r12 + mulxq 152(%rsp), %rcx, %rbx + adcxq %rcx, %r13 + # A[2] * B[2] + movq 112(%rsp), %rdx + mulxq 144(%rsp), %rdx, %rcx + adcxq %rbx, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 120(%rsp), %rdx + adoxq %rcx, %r14 + mulxq 152(%rsp), %rcx, %rbx + adoxq %rbp, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq 128(%rsp), %rdx, %rcx + adcxq %rbx, %rbp + xorq %rbx, %rbx + adcxq %rdx, %r12 + # A[3] * B[0] + movq 96(%rsp), %rdx + adcxq %rcx, %r13 + mulxq 152(%rsp), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 120(%rsp), %rdx + mulxq 144(%rsp), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 112(%rsp), %rdx + adcxq %rcx, %r15 + mulxq 152(%rsp), %rcx, %rdx + adcxq %rbx, %rbp + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rbx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rbx, %rbx + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %rcx, %r15 + adcxq %rcx, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, (%rsp) + movq %r10, 8(%rsp) + movq %r11, 16(%rsp) + movq %r12, 24(%rsp) + decb 168(%rsp) + jge L_curve25519_avx2_bits + movq $63, 168(%rsp) + decb 160(%rsp) + jge L_curve25519_avx2_words + # Invert + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + movq %rsp, %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 96(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $4, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $9, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 128(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 128(%rsp), %rdi + leaq 128(%rsp), %rsi + movq $19, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 128(%rsp), %rsi + leaq 96(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $9, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $49, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 128(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 128(%rsp), %rdi + leaq 128(%rsp), %rsi + movq $0x63, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 128(%rsp), %rsi + leaq 96(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + movq $49, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movq $4, %rdx +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq 176(%rsp), %rdi + # Multiply + # A[0] * B[0] + movq (%rsp), %rdx + mulxq (%rdi), %r9, %r10 + # A[2] * B[0] + mulxq 16(%rdi), %r11, %r12 + # A[1] * B[0] + mulxq 8(%rdi), %rcx, %rbx + xorq %rbp, %rbp + adcxq %rcx, %r10 + # A[1] * B[3] + movq 24(%rsp), %rdx + mulxq 8(%rdi), %r13, %r14 + adcxq %rbx, %r11 + # A[0] * B[1] + movq 8(%rsp), %rdx + mulxq (%rdi), %rcx, %rbx + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 16(%rdi), %rcx, %r15 + adoxq %rbx, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 16(%rsp), %rdx + mulxq 8(%rdi), %rcx, %rbx + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbp, %r14 + adoxq %rbx, %r13 + # A[0] * B[2] + mulxq (%rdi), %rcx, %rbx + adoxq %rbp, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 8(%rsp), %rdx + mulxq 8(%rdi), %rdx, %rcx + adcxq %rbx, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 8(%rsp), %rdx + adoxq %rcx, %r12 + mulxq 24(%rdi), %rcx, %rbx + adcxq %rcx, %r13 + # A[2] * B[2] + movq 16(%rsp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rbx, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 24(%rsp), %rdx + adoxq %rcx, %r14 + mulxq 24(%rdi), %rcx, %rbx + adoxq %rbp, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq (%rdi), %rdx, %rcx + adcxq %rbx, %rbp + xorq %rbx, %rbx + adcxq %rdx, %r12 + # A[3] * B[0] + movq (%rsp), %rdx + adcxq %rcx, %r13 + mulxq 24(%rdi), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 24(%rsp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 16(%rsp), %rdx + adcxq %rcx, %r15 + mulxq 24(%rdi), %rcx, %rdx + adcxq %rbx, %rbp + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rbx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rbx, %rbx + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %rcx, %r15 + adcxq %rcx, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, (%rdi) + movq %r10, 8(%rdi) + movq %r11, 16(%rdi) + movq %r12, 24(%rdi) + xorq %rax, %rax + addq $0xc0, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size curve25519_avx2,.-curve25519_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_pow22523_avx2 +.type fe_pow22523_avx2,@function +.align 4 +fe_pow22523_avx2: +#else +.section __TEXT,__text +.globl _fe_pow22523_avx2 +.p2align 2 +_fe_pow22523_avx2: +#endif /* __APPLE__ */ + subq $0x70, %rsp + # pow22523 + movq %rdi, 96(%rsp) + movq %rsi, 104(%rsp) + movq %rsp, %rdi + movq 104(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq 104(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movb $4, %dl +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movb $9, %dl +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movb $19, %dl +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movb $9, %dl +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movb $49, %dl +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + movb $0x63, %dl +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movb $49, %dl +#ifndef __APPLE__ + callq fe_sq_n_avx2@plt +#else + callq _fe_sq_n_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movq 96(%rsp), %rdi + movq %rsp, %rsi + movq 104(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq 104(%rsp), %rsi + movq 96(%rsp), %rdi + addq $0x70, %rsp + repz retq +#ifndef __APPLE__ +.text +.globl fe_ge_to_p2_avx2 +.type fe_ge_to_p2_avx2,@function +.align 4 +fe_ge_to_p2_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_to_p2_avx2 +.p2align 2 +_fe_ge_to_p2_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $40, %rsp + movq %rsi, (%rsp) + movq %rdx, 8(%rsp) + movq %rcx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) + movq 16(%rsp), %rsi + movq 88(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 24(%rsp), %rsi + movq 32(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 88(%rsp), %rsi + # Multiply + # A[0] * B[0] + movq (%rsi), %rdx + mulxq (%rbx), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rbx), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rbx), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rsi), %rdx + mulxq 8(%rbx), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rsi), %rdx + mulxq (%rbx), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rbx), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rsi), %rdx + mulxq 8(%rbx), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rbx), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rsi), %rdx + mulxq 8(%rbx), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rsi), %rdx + adoxq %rcx, %r11 + mulxq 24(%rbx), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rsi), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rsi), %rdx + adoxq %rcx, %r13 + mulxq 24(%rbx), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rbx), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rsi), %rdx + adcxq %rcx, %r12 + mulxq 24(%rbx), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rsi), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rsi), %rdx + adcxq %rcx, %r14 + mulxq 24(%rbx), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_to_p2_avx2,.-fe_ge_to_p2_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_to_p3_avx2 +.type fe_ge_to_p3_avx2,@function +.align 4 +fe_ge_to_p3_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_to_p3_avx2 +.p2align 2 +_fe_ge_to_p3_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $40, %rsp + movq %rsi, (%rsp) + movq %rdx, 8(%rsp) + movq %rcx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) + movq 24(%rsp), %rsi + movq 96(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 32(%rsp), %rsi + movq 88(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 96(%rsp), %rsi + # Multiply + # A[0] * B[0] + movq (%rsi), %rdx + mulxq (%rbx), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rbx), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rbx), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rsi), %rdx + mulxq 8(%rbx), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rsi), %rdx + mulxq (%rbx), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rbx), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rsi), %rdx + mulxq 8(%rbx), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rbx), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rsi), %rdx + mulxq 8(%rbx), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rsi), %rdx + adoxq %rcx, %r11 + mulxq 24(%rbx), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rsi), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rsi), %rdx + adoxq %rcx, %r13 + mulxq 24(%rbx), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rbx), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rsi), %rdx + adcxq %rcx, %r12 + mulxq 24(%rbx), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rsi), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rsi), %rdx + adcxq %rcx, %r14 + mulxq 24(%rbx), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq 24(%rsp), %rsi + movq 32(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_to_p3_avx2,.-fe_ge_to_p3_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_dbl_avx2 +.type fe_ge_dbl_avx2,@function +.align 4 +fe_ge_dbl_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_dbl_avx2 +.p2align 2 +_fe_ge_dbl_avx2: +#endif /* __APPLE__ */ + pushq %rbp + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $48, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 32(%rsp), %rsi + # Square + # A[0] * A[1] + movq (%rsi), %rdx + mulxq 8(%rsi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rsi), %r11, %r12 + # A[2] * A[1] + movq 16(%rsi), %rdx + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rsi), %r13, %r14 + adoxq %rax, %r12 + # A[2] * A[0] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rsi), %rdx + mulxq 24(%rsi), %rbp, %r8 + adcxq %rax, %r11 + adcxq %rbp, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rsi), %rdx + mulxq %rdx, %r8, %rbp + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rcx, %rax + adcxq %r10, %r10 + adoxq %rbp, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rbp, %rcx + adcxq %r12, %r12 + adoxq %rax, %r11 + adcxq %r13, %r13 + adoxq %rbp, %r12 + # A[3] * A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rbp, %rax + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rbp, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r12, %rbp, %r12 + adcxq %rbp, %r8 + adoxq %r12, %r9 + mulxq %r13, %rbp, %r13 + adcxq %rbp, %r9 + adoxq %r13, %r10 + mulxq %r14, %rbp, %r14 + adcxq %rbp, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rbp + andq %rcx, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rbp + andq %rcx, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq 40(%rsp), %rbx + # Square + # A[0] * A[1] + movq (%rbx), %rdx + mulxq 8(%rbx), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rbx), %r11, %r12 + # A[2] * A[1] + movq 16(%rbx), %rdx + mulxq 8(%rbx), %rcx, %rax + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rbx), %r13, %r14 + adoxq %rax, %r12 + # A[2] * A[0] + mulxq (%rbx), %rcx, %rax + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rbx), %rdx + mulxq 24(%rbx), %rbp, %r8 + adcxq %rax, %r11 + adcxq %rbp, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rbx), %rdx + mulxq %rdx, %r8, %rbp + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rbx), %rdx + mulxq %rdx, %rcx, %rax + adcxq %r10, %r10 + adoxq %rbp, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rbx), %rdx + mulxq %rdx, %rbp, %rcx + adcxq %r12, %r12 + adoxq %rax, %r11 + adcxq %r13, %r13 + adoxq %rbp, %r12 + # A[3] * A[3] + movq 24(%rbx), %rdx + mulxq %rdx, %rbp, %rax + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rbp, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r12, %rbp, %r12 + adcxq %rbp, %r8 + adoxq %r12, %r9 + mulxq %r13, %rbp, %r13 + adcxq %rbp, %r9 + adoxq %r13, %r10 + mulxq %r14, %rbp, %r14 + adcxq %rbp, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rbp + andq %rcx, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rbp + andq %rcx, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rdx + adcq 16(%rbx), %r10 + movq $-19, %rcx + adcq 24(%rbx), %rdx + movq $0x7fffffffffffffff, %rax + movq %rdx, %r11 + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rsi + # Square + # A[0] * A[1] + movq (%rdi), %rdx + mulxq 8(%rdi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rdi), %r11, %r12 + # A[2] * A[1] + movq 16(%rdi), %rdx + mulxq 8(%rdi), %rcx, %rax + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rdi), %r13, %r14 + adoxq %rax, %r12 + # A[2] * A[0] + mulxq (%rdi), %rcx, %rax + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rdi), %rdx + mulxq 24(%rdi), %rbp, %r8 + adcxq %rax, %r11 + adcxq %rbp, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rdi), %rdx + mulxq %rdx, %r8, %rbp + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rdi), %rdx + mulxq %rdx, %rcx, %rax + adcxq %r10, %r10 + adoxq %rbp, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rdi), %rdx + mulxq %rdx, %rbp, %rcx + adcxq %r12, %r12 + adoxq %rax, %r11 + adcxq %r13, %r13 + adoxq %rbp, %r12 + # A[3] * A[3] + movq 24(%rdi), %rdx + mulxq %rdx, %rbp, %rax + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rbp, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r12, %rbp, %r12 + adcxq %rbp, %r8 + adoxq %r12, %r9 + mulxq %r13, %rbp, %r13 + adcxq %rbp, %r9 + adoxq %r13, %r10 + mulxq %r14, %rbp, %r14 + adcxq %rbp, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rbp + andq %rcx, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rbp + andq %rcx, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 16(%rsp), %rsi + movq (%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %rdx + movq %r8, %r12 + addq (%rbx), %r8 + movq %r9, %r13 + adcq 8(%rbx), %r9 + movq %r10, %r14 + adcq 16(%rbx), %r10 + movq %rdx, %r15 + adcq 24(%rbx), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbx), %r12 + movq $0x00, %rdx + sbbq 8(%rbx), %r13 + movq $-19, %rcx + sbbq 16(%rbx), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbx), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rsi) + movq %r13, 8(%rsi) + movq %r14, 16(%rsi) + movq %r15, 24(%rsi) + movq 24(%rsp), %rsi + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rdi), %r8 + movq $0x00, %rdx + sbbq 8(%rdi), %r9 + movq $-19, %rcx + sbbq 16(%rdi), %r10 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r11 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r8 + adcq %rdx, %r9 + adcq %rdx, %r10 + adcq %rax, %r11 + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq 104(%rsp), %rdi + # Square * 2 + # A[0] * A[1] + movq (%rdi), %rdx + mulxq 8(%rdi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rdi), %r11, %r12 + # A[2] * A[1] + movq 16(%rdi), %rdx + mulxq 8(%rdi), %rcx, %rax + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rdi), %r13, %r14 + adoxq %rax, %r12 + # A[2] * A[0] + mulxq (%rdi), %rcx, %rax + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rdi), %rdx + mulxq 24(%rdi), %rbp, %r8 + adcxq %rax, %r11 + adcxq %rbp, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rdi), %rdx + mulxq %rdx, %r8, %rbp + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rdi), %rdx + mulxq %rdx, %rcx, %rax + adcxq %r10, %r10 + adoxq %rbp, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rdi), %rdx + mulxq %rdx, %rbp, %rcx + adcxq %r12, %r12 + adoxq %rax, %r11 + adcxq %r13, %r13 + adoxq %rbp, %r12 + # A[3] * A[3] + movq 24(%rdi), %rdx + mulxq %rdx, %rbp, %rax + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rbp, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + xorq %rbp, %rbp + # Move top half into t4-t7 and remove top bit from t3 and double + shldq $3, %r15, %rbp + shldq $2, %r14, %r15 + shldq $2, %r13, %r14 + shldq $2, %r12, %r13 + shldq $2, %r11, %r12 + shldq $0x01, %r10, %r11 + shldq $0x01, %r9, %r10 + shldq $0x01, %r8, %r9 + shlq $0x01, %r8 + andq %rax, %r11 + # Two out left, one in right + andq %rax, %r15 + # Multiply top bits by 19*19 + imulq $0x169, %rbp, %rcx + xorq %rax, %rax + # Multiply top half by 19 + movq $19, %rdx + adoxq %rcx, %r8 + mulxq %r12, %rbp, %r12 + adcxq %rbp, %r8 + adoxq %r12, %r9 + mulxq %r13, %rbp, %r13 + adcxq %rbp, %r9 + adoxq %r13, %r10 + mulxq %r14, %rbp, %r14 + adcxq %rbp, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rbp + andq %rax, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rbp + andq %rax, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 16(%rsp), %rdi + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rdi), %r8 + movq $0x00, %rdx + sbbq 8(%rdi), %r9 + movq $-19, %rcx + sbbq 16(%rdi), %r10 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r11 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r8 + adcq %rdx, %r9 + adcq %rdx, %r10 + adcq %rax, %r11 + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + addq $48, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + popq %rbp + repz retq +#ifndef __APPLE__ +.size fe_ge_dbl_avx2,.-fe_ge_dbl_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_madd_avx2 +.type fe_ge_madd_avx2,@function +.align 4 +fe_ge_madd_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_madd_avx2 +.p2align 2 +_fe_ge_madd_avx2: +#endif /* __APPLE__ */ + pushq %rbp + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $48, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 8(%rsp), %rsi + movq 40(%rsp), %rbx + movq 32(%rsp), %rbp + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rbp), %r8 + movq %r9, %r13 + adcq 8(%rbp), %r9 + movq %r10, %r14 + adcq 16(%rbp), %r10 + movq %rdx, %r15 + adcq 24(%rbp), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbp), %r12 + movq $0x00, %rdx + sbbq 8(%rbp), %r13 + movq $-19, %rcx + sbbq 16(%rbp), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbp), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rsi) + movq %r13, 8(%rsi) + movq %r14, 16(%rsi) + movq %r15, 24(%rsi) + movq 16(%rsp), %rbx + movq 128(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rdi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rdi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rdi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rdi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rdi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rdi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rdi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rdi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rdi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rdi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rdi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rdi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rdi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rdi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq 136(%rsp), %rdi + # Multiply + # A[0] * B[0] + movq (%rdi), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rdi), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rdi), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rdi), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rdi), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rdi), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rdi), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rdi), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rdi), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rdi), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rdi), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 24(%rsp), %rdi + movq 120(%rsp), %rsi + movq 112(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq (%rsp), %rsi + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rdi), %r8 + movq %r9, %r13 + adcq 8(%rdi), %r9 + movq %r10, %r14 + adcq 16(%rdi), %r10 + movq %rdx, %r15 + adcq 24(%rdi), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rdi), %r12 + movq $0x00, %rdx + sbbq 8(%rdi), %r13 + movq $-19, %rcx + sbbq 16(%rdi), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rsi) + movq %r13, 8(%rsi) + movq %r14, 16(%rsi) + movq %r15, 24(%rsi) + movq 104(%rsp), %rdi + # Double + movq (%rdi), %r8 + movq 8(%rdi), %r9 + addq %r8, %r8 + movq 16(%rdi), %r10 + adcq %r9, %r9 + movq 24(%rdi), %rdx + adcq %r10, %r10 + movq $-19, %rcx + adcq %rdx, %rdx + movq $0x7fffffffffffffff, %rax + movq %rdx, %r11 + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq 24(%rsp), %rdi + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rdi), %r8 + movq %r9, %r13 + adcq 8(%rdi), %r9 + movq %r10, %r14 + adcq 16(%rdi), %r10 + movq %rdx, %r15 + adcq 24(%rdi), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rdi), %r12 + movq $0x00, %rdx + sbbq 8(%rdi), %r13 + movq $-19, %rcx + sbbq 16(%rdi), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq %r12, (%rdi) + movq %r13, 8(%rdi) + movq %r14, 16(%rdi) + movq %r15, 24(%rdi) + addq $48, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + popq %rbp + repz retq +#ifndef __APPLE__ +.size fe_ge_madd_avx2,.-fe_ge_madd_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_msub_avx2 +.type fe_ge_msub_avx2,@function +.align 4 +fe_ge_msub_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_msub_avx2 +.p2align 2 +_fe_ge_msub_avx2: +#endif /* __APPLE__ */ + pushq %rbp + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $48, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 8(%rsp), %rsi + movq 40(%rsp), %rbx + movq 32(%rsp), %rbp + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rbp), %r8 + movq %r9, %r13 + adcq 8(%rbp), %r9 + movq %r10, %r14 + adcq 16(%rbp), %r10 + movq %rdx, %r15 + adcq 24(%rbp), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbp), %r12 + movq $0x00, %rdx + sbbq 8(%rbp), %r13 + movq $-19, %rcx + sbbq 16(%rbp), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbp), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rsi) + movq %r13, 8(%rsi) + movq %r14, 16(%rsi) + movq %r15, 24(%rsi) + movq 16(%rsp), %rbx + movq 136(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rdi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rdi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rdi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rdi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rdi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rdi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rdi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rdi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rdi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rdi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rdi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rdi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rdi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rdi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq 128(%rsp), %rdi + # Multiply + # A[0] * B[0] + movq (%rdi), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rdi), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rdi), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rdi), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rdi), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rdi), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rdi), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rdi), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rdi), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rdi), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rdi), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 24(%rsp), %rdi + movq 120(%rsp), %rsi + movq 112(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rsi + movq (%rsp), %rbp + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rsi), %r8 + movq %r9, %r13 + adcq 8(%rsi), %r9 + movq %r10, %r14 + adcq 16(%rsi), %r10 + movq %rdx, %r15 + adcq 24(%rsi), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rsi), %r12 + movq $0x00, %rdx + sbbq 8(%rsi), %r13 + movq $-19, %rcx + sbbq 16(%rsi), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rsi), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq %r12, (%rbp) + movq %r13, 8(%rbp) + movq %r14, 16(%rbp) + movq %r15, 24(%rbp) + movq 104(%rsp), %rsi + # Double + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq %r8, %r8 + movq 16(%rsi), %r10 + adcq %r9, %r9 + movq 24(%rsi), %rdx + adcq %r10, %r10 + movq $-19, %rcx + adcq %rdx, %rdx + movq $0x7fffffffffffffff, %rax + movq %rdx, %r11 + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rdi), %r8 + movq %r9, %r13 + adcq 8(%rdi), %r9 + movq %r10, %r14 + adcq 16(%rdi), %r10 + movq %rdx, %r15 + adcq 24(%rdi), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rdi), %r12 + movq $0x00, %rdx + sbbq 8(%rdi), %r13 + movq $-19, %rcx + sbbq 16(%rdi), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rbx) + movq %r13, 8(%rbx) + movq %r14, 16(%rbx) + movq %r15, 24(%rbx) + addq $48, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + popq %rbp + repz retq +#ifndef __APPLE__ +.size fe_ge_msub_avx2,.-fe_ge_msub_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_add_avx2 +.type fe_ge_add_avx2,@function +.align 4 +fe_ge_add_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_add_avx2 +.p2align 2 +_fe_ge_add_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 8(%rsp), %rsi + movq 40(%rsp), %rbx + movq 32(%rsp), %rbp + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rbp), %r8 + movq %r9, %r13 + adcq 8(%rbp), %r9 + movq %r10, %r14 + adcq 16(%rbp), %r10 + movq %rdx, %r15 + adcq 24(%rbp), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbp), %r12 + movq $0x00, %rdx + sbbq 8(%rbp), %r13 + movq $-19, %rcx + sbbq 16(%rbp), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbp), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rsi) + movq %r13, 8(%rsi) + movq %r14, 16(%rsi) + movq %r15, 24(%rsi) + movq 16(%rsp), %rbx + movq 168(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rdi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rdi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rdi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rdi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rdi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rdi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rdi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rdi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rdi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rdi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rdi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rdi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rdi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rdi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq 176(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 24(%rsp), %rsi + movq 160(%rsp), %rbx + movq 144(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rbx), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rbx), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rbx), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rbx), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rbx), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rbx), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rbx), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rbx), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rbx), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rbx), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rbx), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rbx), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rbx), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rbx), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 136(%rsp), %rsi + movq 152(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rsi + # Double + movq (%rdi), %r8 + movq 8(%rdi), %r9 + addq %r8, %r8 + movq 16(%rdi), %r10 + adcq %r9, %r9 + movq 24(%rdi), %rdx + adcq %r10, %r10 + movq $-19, %rcx + adcq %rdx, %rdx + movq $0x7fffffffffffffff, %rax + movq %rdx, %r11 + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 8(%rsp), %rbx + movq 16(%rsp), %rbp + # Add + movq (%rbp), %r8 + movq 8(%rbp), %r9 + movq 16(%rbp), %r10 + movq 24(%rbp), %rdx + movq %r8, %r12 + addq (%rbx), %r8 + movq %r9, %r13 + adcq 8(%rbx), %r9 + movq %r10, %r14 + adcq 16(%rbx), %r10 + movq %rdx, %r15 + adcq 24(%rbx), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbx), %r12 + movq $0x00, %rdx + sbbq 8(%rbx), %r13 + movq $-19, %rcx + sbbq 16(%rbx), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbx), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq %r12, (%rdi) + movq %r13, 8(%rdi) + movq %r14, 16(%rdi) + movq %r15, 24(%rdi) + movq 24(%rsp), %rdi + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %rdx + movq %r8, %r12 + addq (%rdi), %r8 + movq %r9, %r13 + adcq 8(%rdi), %r9 + movq %r10, %r14 + adcq 16(%rdi), %r10 + movq %rdx, %r15 + adcq 24(%rdi), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rdi), %r12 + movq $0x00, %rdx + sbbq 8(%rdi), %r13 + movq $-19, %rcx + sbbq 16(%rdi), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rbp) + movq %r9, 8(%rbp) + movq %r10, 16(%rbp) + movq %r11, 24(%rbp) + movq %r12, (%rdi) + movq %r13, 8(%rdi) + movq %r14, 16(%rdi) + movq %r15, 24(%rdi) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbp + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_add_avx2,.-fe_ge_add_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_sub_avx2 +.type fe_ge_sub_avx2,@function +.align 4 +fe_ge_sub_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_sub_avx2 +.p2align 2 +_fe_ge_sub_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 8(%rsp), %rsi + movq 40(%rsp), %rbx + movq 32(%rsp), %rbp + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rbp), %r8 + movq %r9, %r13 + adcq 8(%rbp), %r9 + movq %r10, %r14 + adcq 16(%rbp), %r10 + movq %rdx, %r15 + adcq 24(%rbp), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbp), %r12 + movq $0x00, %rdx + sbbq 8(%rbp), %r13 + movq $-19, %rcx + sbbq 16(%rbp), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbp), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rsi) + movq %r13, 8(%rsi) + movq %r14, 16(%rsi) + movq %r15, 24(%rsi) + movq 16(%rsp), %rbx + movq 176(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rdi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rdi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rdi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rdi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rdi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rdi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rdi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rdi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rdi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rdi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rdi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rdi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rdi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rdi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq 168(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 24(%rsp), %rsi + movq 160(%rsp), %rbx + movq 144(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rbx), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rbx), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rbx), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rbx), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rbx), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rbx), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rbx), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rbx), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rbx), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rbx), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rbx), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rbx), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rbx), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rbx), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 136(%rsp), %rsi + movq 152(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rsi + # Double + movq (%rdi), %r8 + movq 8(%rdi), %r9 + addq %r8, %r8 + movq 16(%rdi), %r10 + adcq %r9, %r9 + movq 24(%rdi), %rdx + adcq %r10, %r10 + movq $-19, %rcx + adcq %rdx, %rdx + movq $0x7fffffffffffffff, %rax + movq %rdx, %r11 + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 8(%rsp), %rbx + movq 16(%rsp), %rbp + # Add + movq (%rbp), %r8 + movq 8(%rbp), %r9 + movq 16(%rbp), %r10 + movq 24(%rbp), %rdx + movq %r8, %r12 + addq (%rbx), %r8 + movq %r9, %r13 + adcq 8(%rbx), %r9 + movq %r10, %r14 + adcq 16(%rbx), %r10 + movq %rdx, %r15 + adcq 24(%rbx), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbx), %r12 + movq $0x00, %rdx + sbbq 8(%rbx), %r13 + movq $-19, %rcx + sbbq 16(%rbx), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbx), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq %r12, (%rdi) + movq %r13, 8(%rdi) + movq %r14, 16(%rdi) + movq %r15, 24(%rdi) + movq 24(%rsp), %rdi + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %rdx + movq %r8, %r12 + addq (%rdi), %r8 + movq %r9, %r13 + adcq 8(%rdi), %r9 + movq %r10, %r14 + adcq 16(%rdi), %r10 + movq %rdx, %r15 + adcq 24(%rdi), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rdi), %r12 + movq $0x00, %rdx + sbbq 8(%rdi), %r13 + movq $-19, %rcx + sbbq 16(%rdi), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rbp) + movq %r13, 8(%rbp) + movq %r14, 16(%rbp) + movq %r15, 24(%rbp) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbp + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_sub_avx2,.-fe_ge_sub_avx2 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fips.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fips.c new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fips_test.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fips_test.c new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mont_small.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mont_small.i index c4a339b9b..380b0a25b 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mont_small.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mont_small.i @@ -1,8 +1,8 @@ /* fp_mont_small.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,21 +16,34 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SMALL_MONT_SET /* computes x/R == x (mod N) via Montgomery Reduction */ -void fp_montgomery_reduce_small(fp_int *a, fp_int *m, fp_digit mp) +int fp_montgomery_reduce_small(fp_int *a, fp_int *m, fp_digit mp) { - fp_digit c[FP_SIZE], *_c, *tmpm, mu, cy; +#ifndef WOLFSSL_SMALL_STACK + fp_digit c[FP_SIZE]; +#else + fp_digit *c; +#endif + fp_digit *_c, *tmpm, mu, cy; int oldused, x, y, pa; -#if defined(USE_MEMSET) - /* now zero the buff */ - memset(c, 0, sizeof c); +#ifdef WOLFSSL_SMALL_STACK + /* only allocate space for what's needed for window plus res */ + c = (fp_digit*)XMALLOC(sizeof(fp_digit)*FP_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (c == NULL) { + return FP_MEM; + } #endif + + /* now zero the buff */ + XMEMSET(c, 0, sizeof(fp_digit)*(FP_SIZE)); + pa = m->used; /* copy the input */ @@ -38,11 +51,7 @@ void fp_montgomery_reduce_small(fp_int *a, fp_int *m, fp_digit mp) for (x = 0; x < oldused; x++) { c[x] = a->dp[x]; } -#if !defined(USE_MEMSET) - for (; x < 2*pa+3; x++) { - c[x] = 0; - } -#endif + MONT_START; switch (pa) { @@ -3855,6 +3864,11 @@ void fp_montgomery_reduce_small(fp_int *a, fp_int *m, fp_digit mp) if (fp_cmp_mag (a, m) != FP_LT) { s_fp_sub (a, m, a); } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(c, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_12.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_12.i index b25ce5c4a..0f0683d74 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_12.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_12.i @@ -1,8 +1,8 @@ /* fp_mul_comba_12.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifdef TFM_MUL12 -void fp_mul_comba12(fp_int *A, fp_int *B, fp_int *C) -{ - fp_digit c0, c1, c2, at[24]; - memcpy(at, A->dp, 12 * sizeof(fp_digit)); - memcpy(at+12, B->dp, 12 * sizeof(fp_digit)); +#ifdef TFM_MUL12 +int fp_mul_comba12(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[24]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 24, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 12 * sizeof(fp_digit)); + XMEMCPY(at+12, B->dp, 12 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -126,5 +138,10 @@ void fp_mul_comba12(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_17.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_17.i index fe12f0602..fb3205515 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_17.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_17.i @@ -1,8 +1,8 @@ /* fp_mul_comba_17.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifdef TFM_MUL17 -void fp_mul_comba17(fp_int *A, fp_int *B, fp_int *C) -{ - fp_digit c0, c1, c2, at[34]; - memcpy(at, A->dp, 17 * sizeof(fp_digit)); - memcpy(at+17, B->dp, 17 * sizeof(fp_digit)); +#ifdef TFM_MUL17 +int fp_mul_comba17(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[34]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 34, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 17 * sizeof(fp_digit)); + XMEMCPY(at+17, B->dp, 17 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -166,5 +178,10 @@ void fp_mul_comba17(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_20.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_20.i index cd07e5dfd..372f51f41 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_20.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_20.i @@ -1,8 +1,8 @@ /* fp_mul_comba_20.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,16 +16,28 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_MUL20 -void fp_mul_comba20(fp_int *A, fp_int *B, fp_int *C) +int fp_mul_comba20(fp_int *A, fp_int *B, fp_int *C) { - fp_digit c0, c1, c2, at[40]; - - memcpy(at, A->dp, 20 * sizeof(fp_digit)); - memcpy(at+20, B->dp, 20 * sizeof(fp_digit)); + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[40]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 40, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 20 * sizeof(fp_digit)); + XMEMCPY(at+20, B->dp, 20 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -189,5 +201,10 @@ void fp_mul_comba20(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_24.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_24.i index 2576d27aa..17705f7df 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_24.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_24.i @@ -1,8 +1,8 @@ /* fp_mul_comba_24.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifdef TFM_MUL24 -void fp_mul_comba24(fp_int *A, fp_int *B, fp_int *C) -{ - fp_digit c0, c1, c2, at[48]; - memcpy(at, A->dp, 24 * sizeof(fp_digit)); - memcpy(at+24, B->dp, 24 * sizeof(fp_digit)); +#ifdef TFM_MUL24 +int fp_mul_comba24(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[48]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 48, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 24 * sizeof(fp_digit)); + XMEMCPY(at+24, B->dp, 24 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -222,5 +234,10 @@ void fp_mul_comba24(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_28.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_28.i index 822dd14c7..594db74ef 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_28.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_28.i @@ -1,8 +1,8 @@ /* fp_mul_comba_28.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifdef TFM_MUL28 -void fp_mul_comba28(fp_int *A, fp_int *B, fp_int *C) -{ - fp_digit c0, c1, c2, at[56]; - memcpy(at, A->dp, 28 * sizeof(fp_digit)); - memcpy(at+28, B->dp, 28 * sizeof(fp_digit)); +#ifdef TFM_MUL28 +int fp_mul_comba28(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[56]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 56, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 28 * sizeof(fp_digit)); + XMEMCPY(at+28, B->dp, 28 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -254,5 +266,10 @@ void fp_mul_comba28(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_3.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_3.i index 440291e38..0befff860 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_3.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_3.i @@ -1,8 +1,8 @@ /* fp_mul_comba_3.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,18 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_MUL3 -void fp_mul_comba3(fp_int *A, fp_int *B, fp_int *C) +int fp_mul_comba3(fp_int *A, fp_int *B, fp_int *C) { fp_digit c0, c1, c2, at[6]; - memcpy(at, A->dp, 3 * sizeof(fp_digit)); - memcpy(at+3, B->dp, 3 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 3 * sizeof(fp_digit)); + XMEMCPY(at+3, B->dp, 3 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -54,5 +55,7 @@ void fp_mul_comba3(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_32.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_32.i index 905028d17..97dc076be 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_32.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_32.i @@ -1,8 +1,8 @@ /* fp_mul_comba_32.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,19 +16,31 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_MUL32 -void fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C) +int fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C) { - fp_digit c0, c1, c2, at[64]; int out_size; + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[64]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif out_size = A->used + B->used; - memcpy(at, A->dp, 32 * sizeof(fp_digit)); - memcpy(at+32, B->dp, 32 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 32 * sizeof(fp_digit)); + XMEMCPY(at+32, B->dp, 32 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -189,7 +201,7 @@ void fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C) COMBA_STORE(C->dp[38]); /* early out at 40 digits, 40*32==1280, or two 640 bit operands */ - if (out_size <= 40) { COMBA_STORE2(C->dp[39]); C->used = 40; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; } + if (out_size <= 40) { COMBA_STORE2(C->dp[39]); C->used = 40; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return FP_OKAY; } /* 39 */ COMBA_FORWARD; @@ -225,7 +237,7 @@ void fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C) COMBA_STORE(C->dp[46]); /* early out at 48 digits, 48*32==1536, or two 768 bit operands */ - if (out_size <= 48) { COMBA_STORE2(C->dp[47]); C->used = 48; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; } + if (out_size <= 48) { COMBA_STORE2(C->dp[47]); C->used = 48; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return FP_OKAY; } /* 47 */ COMBA_FORWARD; @@ -261,7 +273,7 @@ void fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C) COMBA_STORE(C->dp[54]); /* early out at 56 digits, 56*32==1792, or two 896 bit operands */ - if (out_size <= 56) { COMBA_STORE2(C->dp[55]); C->used = 56; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; } + if (out_size <= 56) { COMBA_STORE2(C->dp[55]); C->used = 56; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return FP_OKAY; } /* 55 */ COMBA_FORWARD; @@ -300,5 +312,10 @@ void fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_4.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_4.i index e981eb1f0..803c6151a 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_4.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_4.i @@ -1,8 +1,8 @@ /* fp_mul_comba_4.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifdef TFM_MUL4 -void fp_mul_comba4(fp_int *A, fp_int *B, fp_int *C) -{ - fp_digit c0, c1, c2, at[8]; - memcpy(at, A->dp, 4 * sizeof(fp_digit)); - memcpy(at+4, B->dp, 4 * sizeof(fp_digit)); +#ifdef TFM_MUL4 +int fp_mul_comba4(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[8]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 8, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 4 * sizeof(fp_digit)); + XMEMCPY(at+4, B->dp, 4 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -62,5 +74,10 @@ void fp_mul_comba4(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_48.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_48.i index 79e43b8d0..0d1533458 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_48.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_48.i @@ -1,8 +1,8 @@ /* fp_mul_comba_48.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifdef TFM_MUL48 -void fp_mul_comba48(fp_int *A, fp_int *B, fp_int *C) -{ - fp_digit c0, c1, c2, at[96]; - memcpy(at, A->dp, 48 * sizeof(fp_digit)); - memcpy(at+48, B->dp, 48 * sizeof(fp_digit)); +#ifdef TFM_MUL48 +int fp_mul_comba48(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[96]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 96, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 48 * sizeof(fp_digit)); + XMEMCPY(at+48, B->dp, 48 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -414,5 +426,10 @@ void fp_mul_comba48(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_6.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_6.i index 165c270b7..815badcb8 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_6.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_6.i @@ -1,8 +1,8 @@ /* fp_mul_comba_6.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifdef TFM_MUL6 -void fp_mul_comba6(fp_int *A, fp_int *B, fp_int *C) -{ - fp_digit c0, c1, c2, at[12]; - memcpy(at, A->dp, 6 * sizeof(fp_digit)); - memcpy(at+6, B->dp, 6 * sizeof(fp_digit)); +#ifdef TFM_MUL6 +int fp_mul_comba6(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[12]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 12, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 6 * sizeof(fp_digit)); + XMEMCPY(at+6, B->dp, 6 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -78,5 +90,10 @@ void fp_mul_comba6(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_64.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_64.i index 76d7c2114..7080fa2a3 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_64.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_64.i @@ -1,8 +1,8 @@ /* fp_mul_comba_64.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifdef TFM_MUL64 -void fp_mul_comba64(fp_int *A, fp_int *B, fp_int *C) -{ - fp_digit c0, c1, c2, at[128]; - memcpy(at, A->dp, 64 * sizeof(fp_digit)); - memcpy(at+64, B->dp, 64 * sizeof(fp_digit)); +#ifdef TFM_MUL64 +int fp_mul_comba64(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[128]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 64 * sizeof(fp_digit)); + XMEMCPY(at+64, B->dp, 64 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -542,5 +554,10 @@ void fp_mul_comba64(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_7.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_7.i index eed886315..b969a9a3b 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_7.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_7.i @@ -1,8 +1,8 @@ /* fp_mul_comba_7.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifdef TFM_MUL7 -void fp_mul_comba7(fp_int *A, fp_int *B, fp_int *C) -{ - fp_digit c0, c1, c2, at[14]; - memcpy(at, A->dp, 7 * sizeof(fp_digit)); - memcpy(at+7, B->dp, 7 * sizeof(fp_digit)); +#ifdef TFM_MUL7 +int fp_mul_comba7(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[14]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 14, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 7 * sizeof(fp_digit)); + XMEMCPY(at+7, B->dp, 7 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -86,5 +98,10 @@ void fp_mul_comba7(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_8.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_8.i index fa578a839..1d61a7781 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_8.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_8.i @@ -1,8 +1,8 @@ /* fp_mul_comba_8.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifdef TFM_MUL8 -void fp_mul_comba8(fp_int *A, fp_int *B, fp_int *C) -{ - fp_digit c0, c1, c2, at[16]; - memcpy(at, A->dp, 8 * sizeof(fp_digit)); - memcpy(at+8, B->dp, 8 * sizeof(fp_digit)); +#ifdef TFM_MUL8 +int fp_mul_comba8(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[16]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 8 * sizeof(fp_digit)); + XMEMCPY(at+8, B->dp, 8 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -94,5 +106,10 @@ void fp_mul_comba8(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_9.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_9.i index 755067f86..0eedd7597 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_9.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_9.i @@ -1,8 +1,8 @@ /* fp_mul_comba_9.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifdef TFM_MUL9 -void fp_mul_comba9(fp_int *A, fp_int *B, fp_int *C) -{ - fp_digit c0, c1, c2, at[18]; - memcpy(at, A->dp, 9 * sizeof(fp_digit)); - memcpy(at+9, B->dp, 9 * sizeof(fp_digit)); +#ifdef TFM_MUL9 +int fp_mul_comba9(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[18]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 18, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 9 * sizeof(fp_digit)); + XMEMCPY(at+9, B->dp, 9 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -102,5 +114,10 @@ void fp_mul_comba9(fp_int *A, fp_int *B, fp_int *C) C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_small_set.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_small_set.i index deea5932c..62ab909cf 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_small_set.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_mul_comba_small_set.i @@ -1,8 +1,8 @@ /* fp_mul_comba_small_set.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,19 +16,32 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #if defined(TFM_SMALL_SET) -void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) +int fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) { - fp_digit c0, c1, c2, at[32]; + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[32]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 32, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + switch (MAX(A->used, B->used)) { case 1: - memcpy(at, A->dp, 1 * sizeof(fp_digit)); - memcpy(at+1, B->dp, 1 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 1 * sizeof(fp_digit)); + XMEMCPY(at+1, B->dp, 1 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -43,8 +56,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 2: - memcpy(at, A->dp, 2 * sizeof(fp_digit)); - memcpy(at+2, B->dp, 2 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 2 * sizeof(fp_digit)); + XMEMCPY(at+2, B->dp, 2 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -67,8 +80,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 3: - memcpy(at, A->dp, 3 * sizeof(fp_digit)); - memcpy(at+3, B->dp, 3 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 3 * sizeof(fp_digit)); + XMEMCPY(at+3, B->dp, 3 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -99,8 +112,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 4: - memcpy(at, A->dp, 4 * sizeof(fp_digit)); - memcpy(at+4, B->dp, 4 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 4 * sizeof(fp_digit)); + XMEMCPY(at+4, B->dp, 4 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -139,8 +152,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 5: - memcpy(at, A->dp, 5 * sizeof(fp_digit)); - memcpy(at+5, B->dp, 5 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 5 * sizeof(fp_digit)); + XMEMCPY(at+5, B->dp, 5 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -187,8 +200,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 6: - memcpy(at, A->dp, 6 * sizeof(fp_digit)); - memcpy(at+6, B->dp, 6 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 6 * sizeof(fp_digit)); + XMEMCPY(at+6, B->dp, 6 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -243,8 +256,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 7: - memcpy(at, A->dp, 7 * sizeof(fp_digit)); - memcpy(at+7, B->dp, 7 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 7 * sizeof(fp_digit)); + XMEMCPY(at+7, B->dp, 7 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -307,8 +320,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 8: - memcpy(at, A->dp, 8 * sizeof(fp_digit)); - memcpy(at+8, B->dp, 8 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 8 * sizeof(fp_digit)); + XMEMCPY(at+8, B->dp, 8 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -379,8 +392,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 9: - memcpy(at, A->dp, 9 * sizeof(fp_digit)); - memcpy(at+9, B->dp, 9 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 9 * sizeof(fp_digit)); + XMEMCPY(at+9, B->dp, 9 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -459,8 +472,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 10: - memcpy(at, A->dp, 10 * sizeof(fp_digit)); - memcpy(at+10, B->dp, 10 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 10 * sizeof(fp_digit)); + XMEMCPY(at+10, B->dp, 10 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -547,8 +560,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 11: - memcpy(at, A->dp, 11 * sizeof(fp_digit)); - memcpy(at+11, B->dp, 11 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 11 * sizeof(fp_digit)); + XMEMCPY(at+11, B->dp, 11 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -643,8 +656,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 12: - memcpy(at, A->dp, 12 * sizeof(fp_digit)); - memcpy(at+12, B->dp, 12 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 12 * sizeof(fp_digit)); + XMEMCPY(at+12, B->dp, 12 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -747,8 +760,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 13: - memcpy(at, A->dp, 13 * sizeof(fp_digit)); - memcpy(at+13, B->dp, 13 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 13 * sizeof(fp_digit)); + XMEMCPY(at+13, B->dp, 13 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -859,8 +872,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 14: - memcpy(at, A->dp, 14 * sizeof(fp_digit)); - memcpy(at+14, B->dp, 14 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 14 * sizeof(fp_digit)); + XMEMCPY(at+14, B->dp, 14 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -979,8 +992,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 15: - memcpy(at, A->dp, 15 * sizeof(fp_digit)); - memcpy(at+15, B->dp, 15 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 15 * sizeof(fp_digit)); + XMEMCPY(at+15, B->dp, 15 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -1107,8 +1120,8 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) break; case 16: - memcpy(at, A->dp, 16 * sizeof(fp_digit)); - memcpy(at+16, B->dp, 16 * sizeof(fp_digit)); + XMEMCPY(at, A->dp, 16 * sizeof(fp_digit)); + XMEMCPY(at+16, B->dp, 16 * sizeof(fp_digit)); COMBA_START; COMBA_CLEAR; @@ -1245,6 +1258,11 @@ void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) default: break; } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_12.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_12.i index 078b8986d..cded4b123 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_12.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_12.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_12.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,30 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR12 -void fp_sqr_comba12(fp_int *A, fp_int *B) +int fp_sqr_comba12(fp_int *A, fp_int *B) { - fp_digit *a, b[24], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[24]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 24, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + a = A->dp; COMBA_START; @@ -151,8 +164,13 @@ void fp_sqr_comba12(fp_int *A, fp_int *B) B->used = 24; B->sign = FP_ZPOS; - memcpy(B->dp, b, 24 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 24 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_17.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_17.i index d5f4674fb..d2418d931 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_17.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_17.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_17.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR17 -void fp_sqr_comba17(fp_int *A, fp_int *B) +int fp_sqr_comba17(fp_int *A, fp_int *B) { - fp_digit *a, b[34], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[34]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 34, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif a = A->dp; COMBA_START; @@ -202,8 +214,13 @@ void fp_sqr_comba17(fp_int *A, fp_int *B) B->used = 34; B->sign = FP_ZPOS; - memcpy(B->dp, b, 34 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 34 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_20.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_20.i index dcd9f318f..78fd3fd96 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_20.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_20.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_20.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR20 -void fp_sqr_comba20(fp_int *A, fp_int *B) +int fp_sqr_comba20(fp_int *A, fp_int *B) { - fp_digit *a, b[40], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO - fp_word tt; -#endif + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[40]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 40, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif a = A->dp; COMBA_START; @@ -232,8 +244,13 @@ void fp_sqr_comba20(fp_int *A, fp_int *B) B->used = 40; B->sign = FP_ZPOS; - memcpy(B->dp, b, 40 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 40 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_24.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_24.i index cf512e3c3..602b36c09 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_24.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_24.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_24.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR24 -void fp_sqr_comba24(fp_int *A, fp_int *B) +int fp_sqr_comba24(fp_int *A, fp_int *B) { - fp_digit *a, b[48], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO - fp_word tt; -#endif + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[48]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 48, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif a = A->dp; COMBA_START; @@ -272,8 +284,13 @@ void fp_sqr_comba24(fp_int *A, fp_int *B) B->used = 48; B->sign = FP_ZPOS; - memcpy(B->dp, b, 48 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 48 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_28.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_28.i index 08e9bc4d5..57c1acc30 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_28.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_28.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_28.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR28 -void fp_sqr_comba28(fp_int *A, fp_int *B) +int fp_sqr_comba28(fp_int *A, fp_int *B) { - fp_digit *a, b[56], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO - fp_word tt; -#endif + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[56]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 56, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif a = A->dp; COMBA_START; @@ -312,8 +324,13 @@ void fp_sqr_comba28(fp_int *A, fp_int *B) B->used = 56; B->sign = FP_ZPOS; - memcpy(B->dp, b, 56 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 56 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_3.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_3.i index b4754093d..51c3d7422 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_3.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_3.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_3.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,12 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR3 -void fp_sqr_comba3(fp_int *A, fp_int *B) +int fp_sqr_comba3(fp_int *A, fp_int *B) { fp_digit *a, b[6], c0, c1, c2; #ifdef TFM_ISO @@ -62,8 +63,10 @@ void fp_sqr_comba3(fp_int *A, fp_int *B) B->used = 6; B->sign = FP_ZPOS; - memcpy(B->dp, b, 6 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 6 * sizeof(fp_digit)); fp_clamp(B); + + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_32.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_32.i index 4a35d7477..4fcf3497b 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_32.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_32.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_32.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR32 -void fp_sqr_comba32(fp_int *A, fp_int *B) +int fp_sqr_comba32(fp_int *A, fp_int *B) { - fp_digit *a, b[64], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO - fp_word tt; -#endif + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[64]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif a = A->dp; COMBA_START; @@ -352,8 +364,13 @@ void fp_sqr_comba32(fp_int *A, fp_int *B) B->used = 64; B->sign = FP_ZPOS; - memcpy(B->dp, b, 64 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 64 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_4.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_4.i index bb09dc891..b7f257288 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_4.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_4.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_4.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR4 -void fp_sqr_comba4(fp_int *A, fp_int *B) +int fp_sqr_comba4(fp_int *A, fp_int *B) { - fp_digit *a, b[8], c0, c1, c2; + fp_digit *a, c0, c1, c2; #ifdef TFM_ISO fp_word tt; #endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[8]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 8, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif a = A->dp; COMBA_START; @@ -72,8 +84,13 @@ void fp_sqr_comba4(fp_int *A, fp_int *B) B->used = 8; B->sign = FP_ZPOS; - memcpy(B->dp, b, 8 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 8 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_48.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_48.i index cbaac02cc..0f24532b1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_48.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_48.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_48.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR48 -void fp_sqr_comba48(fp_int *A, fp_int *B) +int fp_sqr_comba48(fp_int *A, fp_int *B) { - fp_digit *a, b[96], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO - fp_word tt; -#endif + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[96]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 96, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif a = A->dp; COMBA_START; @@ -512,8 +524,13 @@ void fp_sqr_comba48(fp_int *A, fp_int *B) B->used = 96; B->sign = FP_ZPOS; - memcpy(B->dp, b, 96 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 96 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_6.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_6.i index bb2fd743e..b36416844 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_6.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_6.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_6.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR6 -void fp_sqr_comba6(fp_int *A, fp_int *B) +int fp_sqr_comba6(fp_int *A, fp_int *B) { - fp_digit *a, b[12], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[12]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 12, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif a = A->dp; COMBA_START; @@ -92,8 +104,13 @@ void fp_sqr_comba6(fp_int *A, fp_int *B) B->used = 12; B->sign = FP_ZPOS; - memcpy(B->dp, b, 12 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 12 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_64.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_64.i index b74367a7c..b9b2c8ab7 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_64.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_64.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_64.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR64 -void fp_sqr_comba64(fp_int *A, fp_int *B) +int fp_sqr_comba64(fp_int *A, fp_int *B) { - fp_digit *a, b[128], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO - fp_word tt; -#endif + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[128]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif a = A->dp; COMBA_START; @@ -672,8 +684,13 @@ void fp_sqr_comba64(fp_int *A, fp_int *B) B->used = 128; B->sign = FP_ZPOS; - memcpy(B->dp, b, 128 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 128 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_7.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_7.i index 8ddef1a9b..09bf9954a 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_7.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_7.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_7.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR7 -void fp_sqr_comba7(fp_int *A, fp_int *B) +int fp_sqr_comba7(fp_int *A, fp_int *B) { - fp_digit *a, b[14], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[14]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 14, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif a = A->dp; COMBA_START; @@ -102,8 +114,13 @@ void fp_sqr_comba7(fp_int *A, fp_int *B) B->used = 14; B->sign = FP_ZPOS; - memcpy(B->dp, b, 14 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 14 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_8.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_8.i index f9a72bcf6..23fd8e41d 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_8.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_8.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_8.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR8 -void fp_sqr_comba8(fp_int *A, fp_int *B) +int fp_sqr_comba8(fp_int *A, fp_int *B) { - fp_digit *a, b[16], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO - fp_word tt; -#endif + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[16]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif a = A->dp; COMBA_START; @@ -112,8 +124,13 @@ void fp_sqr_comba8(fp_int *A, fp_int *B) B->used = 16; B->sign = FP_ZPOS; - memcpy(B->dp, b, 16 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 16 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_9.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_9.i index 94a5d2e92..ed6451a77 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_9.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_9.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_9.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef TFM_SQR9 -void fp_sqr_comba9(fp_int *A, fp_int *B) +int fp_sqr_comba9(fp_int *A, fp_int *B) { - fp_digit *a, b[18], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO fp_word tt; #endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[18]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 18, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif a = A->dp; COMBA_START; @@ -122,8 +134,13 @@ void fp_sqr_comba9(fp_int *A, fp_int *B) B->used = 18; B->sign = FP_ZPOS; - memcpy(B->dp, b, 18 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 18 * sizeof(fp_digit)); fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_small_set.i b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_small_set.i index 9918b2ee8..a81ee10e2 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_small_set.i +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/fp_sqr_comba_small_set.i @@ -1,8 +1,8 @@ /* fp_sqr_comba_small_set.i * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,30 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #if defined(TFM_SMALL_SET) -void fp_sqr_comba_small(fp_int *A, fp_int *B) +int fp_sqr_comba_small(fp_int *A, fp_int *B) { - fp_digit *a, b[32], c0, c1, c2, sc0, sc1, sc2; + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; #ifdef TFM_ISO - fp_word tt; -#endif + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[32]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 32, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + switch (A->used) { case 1: a = A->dp; @@ -43,7 +56,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 2; B->sign = FP_ZPOS; - memcpy(B->dp, b, 2 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 2 * sizeof(fp_digit)); fp_clamp(B); break; @@ -72,7 +85,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 4; B->sign = FP_ZPOS; - memcpy(B->dp, b, 4 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 4 * sizeof(fp_digit)); fp_clamp(B); break; @@ -111,7 +124,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 6; B->sign = FP_ZPOS; - memcpy(B->dp, b, 6 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 6 * sizeof(fp_digit)); fp_clamp(B); break; @@ -160,7 +173,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 8; B->sign = FP_ZPOS; - memcpy(B->dp, b, 8 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 8 * sizeof(fp_digit)); fp_clamp(B); break; @@ -219,7 +232,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 10; B->sign = FP_ZPOS; - memcpy(B->dp, b, 10 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 10 * sizeof(fp_digit)); fp_clamp(B); break; @@ -288,7 +301,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 12; B->sign = FP_ZPOS; - memcpy(B->dp, b, 12 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 12 * sizeof(fp_digit)); fp_clamp(B); break; @@ -367,7 +380,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 14; B->sign = FP_ZPOS; - memcpy(B->dp, b, 14 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 14 * sizeof(fp_digit)); fp_clamp(B); break; @@ -456,7 +469,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 16; B->sign = FP_ZPOS; - memcpy(B->dp, b, 16 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 16 * sizeof(fp_digit)); fp_clamp(B); break; @@ -555,7 +568,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 18; B->sign = FP_ZPOS; - memcpy(B->dp, b, 18 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 18 * sizeof(fp_digit)); fp_clamp(B); break; @@ -664,7 +677,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 20; B->sign = FP_ZPOS; - memcpy(B->dp, b, 20 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 20 * sizeof(fp_digit)); fp_clamp(B); break; @@ -783,7 +796,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 22; B->sign = FP_ZPOS; - memcpy(B->dp, b, 22 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 22 * sizeof(fp_digit)); fp_clamp(B); break; @@ -912,7 +925,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 24; B->sign = FP_ZPOS; - memcpy(B->dp, b, 24 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 24 * sizeof(fp_digit)); fp_clamp(B); break; @@ -1051,7 +1064,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 26; B->sign = FP_ZPOS; - memcpy(B->dp, b, 26 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 26 * sizeof(fp_digit)); fp_clamp(B); break; @@ -1200,7 +1213,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 28; B->sign = FP_ZPOS; - memcpy(B->dp, b, 28 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 28 * sizeof(fp_digit)); fp_clamp(B); break; @@ -1359,7 +1372,7 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 30; B->sign = FP_ZPOS; - memcpy(B->dp, b, 30 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 30 * sizeof(fp_digit)); fp_clamp(B); break; @@ -1528,13 +1541,18 @@ void fp_sqr_comba_small(fp_int *A, fp_int *B) B->used = 32; B->sign = FP_ZPOS; - memcpy(B->dp, b, 32 * sizeof(fp_digit)); + XMEMCPY(B->dp, b, 32 * sizeof(fp_digit)); fp_clamp(B); break; default: break; -} + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; } #endif /* TFM_SMALL_SET */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ge_448.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ge_448.c new file mode 100644 index 000000000..7795a962d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ge_448.c @@ -0,0 +1,10780 @@ +/* ge_448.c + * + * Copyright (C) 2006-2020 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 + */ + +/* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. + * Small implementation based on Daniel Beer's ed25519 public domain work. + * Reworked for ed448 by Sean Parkinson. + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_ED448 + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* +sc means scalar. +ge means group element. + +Here the group is the set of pairs (x,y) of field elements (see ge_448.h) +satisfying -x^2 + y^2 = 1 + d x^2y^2 +where d = -39081 + +Representations: + ge448_p2 (projective) : (X:Y:Z) satisfying x=X/Z, y=Y/Z + ge448_precomp (affine): (X:Y) +*/ + + +#ifdef ED448_SMALL + +/* Base point of ed448 */ +static const ge448_p2 ed448_base = { + { 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b, + 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12, + 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47, + 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22, + 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f }, + { 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e, + 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a, + 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c, + 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88, + 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69 }, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +/* Part of order of ed448 that needs tp be multiplied when reducing */ +static const uint8_t ed448_order_mul[56] = { + 0x0d, 0xbb, 0xa7, 0x54, 0x6d, 0x3d, 0x87, 0xdc, 0xaa, 0x70, 0x3a, 0x72, + 0x8d, 0x3d, 0x93, 0xde, 0x6f, 0xc9, 0x29, 0x51, 0xb6, 0x24, 0xb1, 0x3b, + 0x16, 0xdc, 0x35, 0x83, +}; + +/* Reduce scalar mod the order of the curve. + * Scalar Will be 114 bytes. + * + * b [in] Scalar to reduce. + */ +void sc448_reduce(uint8_t* b) +{ + int i, j; + uint32_t t[114]; + uint8_t o; + + for (i = 0; i < 86; i++) { + t[i] = b[i]; + } + for (i = 0; i < 58; i++) { + for (j = 0; j < 28; j++) + t[i+j] += b[i+56] * ((uint32_t)ed448_order_mul[j] << 2); + t[i+56] = 0; + } + for (i = 54; i < 87; i++) { + t[i+1] += t[i] >> 8; + t[i] &= 0xff; + } + for (i = 0; i < 31; i++) { + for (j = 0; j < 28; j++) + t[i+j] += t[i+56] * ((uint32_t)ed448_order_mul[j] << 2); + t[i+56] = 0; + } + for (i = 54; i < 60; i++) { + t[i+1] += t[i] >> 8; + t[i] &= 0xff; + } + for (i = 0; i < 4; i++) { + for (j = 0; j < 28; j++) + t[i+j] += t[i+56] * ((uint32_t)ed448_order_mul[j] << 2); + t[i+56] = 0; + } + for (i = 0; i < 55; i++) { + t[i+1] += t[i] >> 8; + t[i] &= 0xff; + } + o = t[55] >> 6; + t[55] &= 0x3f; + for (j = 0; j < 28; j++) + t[j] += o * (uint32_t)ed448_order_mul[j]; + for (i = 0; i < 55; i++) { + t[i+1] += t[i] >> 8; + b[i] = t[i] & 0xff; + } + b[i] = t[i] & 0xff; + b[i+1] = 0; +} + +/* Multiply a by b and add d. r = (a * b + d) mod order + * + * r [in] Scalar to hold result. + * a [in] Scalar to multiply. + * b [in] Scalar to multiply. + * d [in] Scalar to add to multiplicative result. + */ +void sc448_muladd(uint8_t* r, const uint8_t* a, const uint8_t* b, + const uint8_t* d) +{ + int i, j; + uint32_t t[112]; + uint8_t o; + + /* a * b + d */ + for (i = 0; i < 56; i++) + t[i] = d[i]; + for (i = 0; i < 56; i++) { + for (j = 0; j < 56; j++) + t[i+j] += (int16_t)a[i] * b[j]; + t[i+56] = 0; + } + + for (i = 0; i < 111; i++) { + t[i+1] += t[i] >> 8; + t[i] &= 0xff; + } + for (i = 0; i < 56; i++) { + for (j = 0; j < 28; j++) + t[i+j] += t[i+56] * ((uint32_t)ed448_order_mul[j] << 2); + t[i+56] = 0; + } + for (i = 54; i < 85; i++) { + t[i+1] += t[i] >> 8; + t[i] &= 0xff; + } + for (i = 0; i < 29; i++) { + for (j = 0; j < 28; j++) + t[i+j] += t[i+56] * ((uint32_t)ed448_order_mul[j] << 2); + t[i+56] = 0; + } + for (i = 54; i < 58; i++) { + t[i+1] += t[i] >> 8; + t[i] &= 0xff; + } + for (i = 0; i < 2; i++) { + for (j = 0; j < 28; j++) + t[i+j] += t[i+56] * ((uint32_t)ed448_order_mul[j] << 2); + t[i+56] = 0; + } + for (i = 0; i < 55; i++) { + t[i+1] += t[i] >> 8; + t[i] &= 0xff; + } + o = t[55] >> 6; + t[55] &= 0x3f; + for (j = 0; j < 28; j++) + t[j] += o * (uint32_t)ed448_order_mul[j]; + for (i = 0; i < 55; i++) { + t[i+1] += t[i] >> 8; + r[i] = t[i] & 0xff; + } + r[i] = t[i] & 0xff; + r[i+1] = 0; +} + +/* Double the point on the Twisted Edwards curve. r = 2.p + * + * r [in] Point to hold result. + * p [in] Point to double. + */ +static WC_INLINE void ge448_dbl(ge448_p2 *r,const ge448_p2 *p) +{ + ge448 t0[GE448_WORDS]; + ge448 t1[GE448_WORDS]; + + fe448_add(t0, p->X, p->Y); /* t0 = B1 = X1+Y1 */ + fe448_reduce(t0); + fe448_sqr(t0, t0); /* t0 = B = (X1+Y1)^2 */ + fe448_sqr(r->X, p->X); /* r->X = C = X1^2 */ + fe448_sqr(r->Y, p->Y); /* r->Y = D = Y1^2 */ + fe448_add(t1, r->X, r->Y); /* t1 = E = C+D */ + fe448_reduce(t1); + fe448_sub(r->Y, r->X, r->Y); /* r->Y = Y31 = C-D */ + fe448_sqr(r->Z, p->Z); /* r->Z = H = Z1^2 */ + fe448_add(r->Z, r->Z, r->Z); /* r->Z = J1 = 2*H */ + fe448_sub(r->Z, t1, r->Z); /* r->Z = J = E-2*H */ + fe448_reduce(r->Z); + fe448_sub(r->X, t0, t1); /* r->X = X31 = B-E */ + fe448_mul(r->X, r->X, r->Z); /* r->X = X3 = (B-E)*J */ + fe448_mul(r->Y, r->Y, t1); /* r->Y = Y3 = E*(C-D) */ + fe448_mul(r->Z, t1, r->Z); /* r->Z = Z3 = E*J */ +} + +/* Add two point on the Twisted Edwards curve. r = p + q + * + * r [in] Point to hold result. + * p [in] Point to add. + * q [in] Point to add. + */ +static WC_INLINE void ge448_add(ge448_p2* r, const ge448_p2* p, + const ge448_p2* q) +{ + ge448 t0[GE448_WORDS]; + ge448 t1[GE448_WORDS]; + ge448 t2[GE448_WORDS]; + ge448 t3[GE448_WORDS]; + ge448 t4[GE448_WORDS]; + + fe448_mul(t1, p->X, q->X); /* t1 = C = X1*X2 */ + fe448_mul(t2, p->Y, q->Y); /* t2 = D = Y1*Y2 */ + fe448_mul(t3, t1, t2); /* t3 = E1 = C*D */ + fe448_mul39081(t3, t3); /* t3 = E = d*C*D */ + fe448_mul(r->Z, p->Z, q->Z); /* r->Z = A = Z1*Z2 */ + fe448_sqr(t0, r->Z); /* t0 = B = A^2 */ + fe448_add(t4, t0, t3); /* t4 = F = B-(-E) */ + fe448_sub(t0, t0, t3); /* t0 = G = B+(-E) */ + fe448_reduce(t0); + fe448_add(r->X, p->X, p->Y); /* r->X = H1 = X1+Y1 */ + fe448_reduce(r->X); + fe448_add(r->Y, q->X, q->Y); /* r->Y = H2 = X2+Y2 */ + fe448_reduce(r->Y); + fe448_mul(r->X, r->X, r->Y); /* r->X = H = (X1+Y1)*(X2+Y2) */ + fe448_sub(r->X, r->X, t1); /* r->X = X31 = H-C */ + fe448_sub(r->X, r->X, t2); /* r->X = X32 = H-C-D */ + fe448_reduce(r->X); + fe448_mul(r->X, r->X, t4); /* r->X = X33 = F*(H-C-D) */ + fe448_mul(r->X, r->X, r->Z); /* r->X = X3 = A*F*(H-C-D) */ + fe448_sub(r->Y, t2, t1); /* r->Y = Y31 = D-C */ + fe448_reduce(r->Y); + fe448_mul(r->Y, r->Y, t0); /* r->Y = Y32 = G*(D-C) */ + fe448_mul(r->Y, r->Y, r->Z); /* r->Y = Y3 = A*F*(D-C) */ + fe448_mul(r->Z, t4, t0); /* r->Z = Z3 = F*G */ +} + +/* Convert point to byte array assuming projective ordinates. + * + * b [in] Array of bytes to hold compressed point. + * p [in] Point to convert. + */ +void ge448_to_bytes(uint8_t *s, const ge448_p2 *h) +{ + ge448 recip[56]; + ge448 x[56]; + + fe448_invert(recip, h->Z); + fe448_mul(x, h->X, recip); + fe448_mul(s, h->Y, recip); + fe448_norm(x); + fe448_norm(s); + s[56] = (x[0] & 1) << 7; +} + +/* Compress the point to y-ordinate and negative bit. + * + * out [in] Array of bytes to hold compressed key. + * xIn [in] The x-ordinate. + * yIn [in] The y-ordinate. + */ +int ge448_compress_key(uint8_t* out, const uint8_t* xIn, const uint8_t* yIn) +{ + ge448 x[56]; + + fe448_copy(x, xIn); + fe448_copy(out, yIn); + fe448_norm(x); + fe448_norm(out); + out[56] = (x[0] & 1) << 7; + + return 0; +} + +/* Perform a scalar multiplication of the a point. r = p * base + * + * r [in] Point to hold result. + * a [in] Scalar to multiply by. + */ +static void ge448_scalarmult(ge448_p2* h, const ge448_p2* p, const uint8_t* a) +{ + ge448_p2 r; + ge448_p2 s; + int i; + + XMEMSET(&r, 0, sizeof(r)); + r.Y[0] = 1; + r.Z[0] = 1; + + for (i = 447; i >= 0; i--) { + const byte bit = (a[i >> 3] >> (i & 7)) & 1; + + ge448_dbl(&r, &r); + ge448_add(&s, &r, p); + + fe448_cmov(r.X, s.X, bit); + fe448_cmov(r.Y, s.Y, bit); + fe448_cmov(r.Z, s.Z, bit); + } + + XMEMCPY(h, &r, sizeof(r)); +} + +/* Perform a scalar multiplication of the base point. r = a * base + * + * r [in] Point to hold result. + * a [in] Scalar to multiply by. + */ +void ge448_scalarmult_base(ge448_p2* h, const uint8_t* a) +{ + ge448_scalarmult(h, &ed448_base, a); +} + +/* Perform a scalar multplication of the base point and public point. + * r = a * p + b * base + * Uses a sliding window of 5 bits. + * Not constant time. + * + * r [in] Point to hold result. + * a [in] Scalar to multiply by. + */ +int ge448_double_scalarmult_vartime(ge448_p2 *r, const uint8_t *a, + const ge448_p2 *A, const uint8_t *b) +{ + ge448_p2 t; + + ge448_scalarmult(&t, &ed448_base, b); + ge448_scalarmult(r, A, a); + ge448_add(r, r, &t); + + return 0; +} + +/* Convert compressed point to negative of affine point. + * Calculates x from the y and the negative bit. + * Not constant time. + * + * r [in] Uncompressed point. + * b [in] Array of bytes representing point. + * returns 0 on success and -1 on failure. + */ +int ge448_from_bytes_negate_vartime(ge448_p2 *r, const uint8_t *b) +{ + int ret = 0; + ge448 u[GE448_WORDS]; + ge448 v[GE448_WORDS]; + ge448 u3[GE448_WORDS]; + ge448 vxx[GE448_WORDS]; + ge448 check[GE448_WORDS]; + + fe448_copy(r->Y, b); + XMEMSET(r->Z, 0, sizeof(r->Z)); + r->Z[0] = 1; + fe448_sqr(u, r->Y); /* u = y^2 */ + fe448_mul39081(v, u); /* v = 39081.y^2 */ + fe448_sub(u, u, r->Z); /* u = y^2-1 */ + fe448_add(v, v, r->Z); /* v = 39081.y^2-1 */ + fe448_neg(v, v); /* v = -39081.y^2-1 = d.y^2-1 */ + + fe448_sqr(r->X, v); /* x = v^2 */ + fe448_mul(r->X, r->X, v); /* x = v^3 */ + fe448_sqr(u3, u); /* x = u^2.v^3 */ + fe448_mul(r->X, r->X, u3); /* x = u^2.v^3 */ + fe448_mul(u3, u3, u); /* u3 = u^3 */ + fe448_mul(r->X, r->X, u3); /* x = u^5.v^3 */ + + fe448_pow_2_446_222_1(r->X, r->X); /* x = (u^5.v^3)^((q-3)/4) */ + fe448_mul(r->X, r->X, u3); /* x = u^3(u^5.v^3)^((q-3)/4) */ + fe448_mul(r->X, r->X, v); /* x = u^3.v(u^5.v^3)^((q-3)/4) */ + + fe448_sqr(vxx, r->X); + fe448_mul(vxx, vxx, v); + fe448_sub(check, vxx, u); /* check = v.x^2-u */ + fe448_norm(check); + fe448_norm(r->X); + fe448_norm(r->Y); + /* Note; vx^2+u is NOT correct. */ + if (fe448_isnonzero(check)) { + ret = -1; + } + + /* Calculating negative of point in bytes - negate only if X is correct. */ + if ((r->X[0] & 1) == (b[56] >> 7)) { + fe448_neg(r->X, r->X); + } + + return ret; +} + +#else /* !ED448_SMALL */ + +#if defined(CURVED448_128BIT) + +/* Reduce scalar mod the order of the curve. + * Scalar Will be 114 bytes. + * + * b [in] Scalar to reduce. + */ +void sc448_reduce(uint8_t* b) +{ + uint64_t d[8]; + uint128_t t[17]; + uint128_t c; + uint64_t o; + + /* Load from bytes */ + t[ 0] = ((int64_t) (b[ 0]) << 0) + | ((int64_t) (b[ 1]) << 8) + | ((int64_t) (b[ 2]) << 16) + | ((int64_t) (b[ 3]) << 24) + | ((int64_t) (b[ 4]) << 32) + | ((int64_t) (b[ 5]) << 40) + | ((int64_t) (b[ 6]) << 48); + t[ 1] = ((int64_t) (b[ 7]) << 0) + | ((int64_t) (b[ 8]) << 8) + | ((int64_t) (b[ 9]) << 16) + | ((int64_t) (b[10]) << 24) + | ((int64_t) (b[11]) << 32) + | ((int64_t) (b[12]) << 40) + | ((int64_t) (b[13]) << 48); + t[ 2] = ((int64_t) (b[14]) << 0) + | ((int64_t) (b[15]) << 8) + | ((int64_t) (b[16]) << 16) + | ((int64_t) (b[17]) << 24) + | ((int64_t) (b[18]) << 32) + | ((int64_t) (b[19]) << 40) + | ((int64_t) (b[20]) << 48); + t[ 3] = ((int64_t) (b[21]) << 0) + | ((int64_t) (b[22]) << 8) + | ((int64_t) (b[23]) << 16) + | ((int64_t) (b[24]) << 24) + | ((int64_t) (b[25]) << 32) + | ((int64_t) (b[26]) << 40) + | ((int64_t) (b[27]) << 48); + t[ 4] = ((int64_t) (b[28]) << 0) + | ((int64_t) (b[29]) << 8) + | ((int64_t) (b[30]) << 16) + | ((int64_t) (b[31]) << 24) + | ((int64_t) (b[32]) << 32) + | ((int64_t) (b[33]) << 40) + | ((int64_t) (b[34]) << 48); + t[ 5] = ((int64_t) (b[35]) << 0) + | ((int64_t) (b[36]) << 8) + | ((int64_t) (b[37]) << 16) + | ((int64_t) (b[38]) << 24) + | ((int64_t) (b[39]) << 32) + | ((int64_t) (b[40]) << 40) + | ((int64_t) (b[41]) << 48); + t[ 6] = ((int64_t) (b[42]) << 0) + | ((int64_t) (b[43]) << 8) + | ((int64_t) (b[44]) << 16) + | ((int64_t) (b[45]) << 24) + | ((int64_t) (b[46]) << 32) + | ((int64_t) (b[47]) << 40) + | ((int64_t) (b[48]) << 48); + t[ 7] = ((int64_t) (b[49]) << 0) + | ((int64_t) (b[50]) << 8) + | ((int64_t) (b[51]) << 16) + | ((int64_t) (b[52]) << 24) + | ((int64_t) (b[53]) << 32) + | ((int64_t) (b[54]) << 40) + | ((int64_t) (b[55]) << 48); + t[ 8] = ((int64_t) (b[56]) << 0) + | ((int64_t) (b[57]) << 8) + | ((int64_t) (b[58]) << 16) + | ((int64_t) (b[59]) << 24) + | ((int64_t) (b[60]) << 32) + | ((int64_t) (b[61]) << 40) + | ((int64_t) (b[62]) << 48); + t[ 9] = ((int64_t) (b[63]) << 0) + | ((int64_t) (b[64]) << 8) + | ((int64_t) (b[65]) << 16) + | ((int64_t) (b[66]) << 24) + | ((int64_t) (b[67]) << 32) + | ((int64_t) (b[68]) << 40) + | ((int64_t) (b[69]) << 48); + t[10] = ((int64_t) (b[70]) << 0) + | ((int64_t) (b[71]) << 8) + | ((int64_t) (b[72]) << 16) + | ((int64_t) (b[73]) << 24) + | ((int64_t) (b[74]) << 32) + | ((int64_t) (b[75]) << 40) + | ((int64_t) (b[76]) << 48); + t[11] = ((int64_t) (b[77]) << 0) + | ((int64_t) (b[78]) << 8) + | ((int64_t) (b[79]) << 16) + | ((int64_t) (b[80]) << 24) + | ((int64_t) (b[81]) << 32) + | ((int64_t) (b[82]) << 40) + | ((int64_t) (b[83]) << 48); + t[12] = ((int64_t) (b[84]) << 0) + | ((int64_t) (b[85]) << 8) + | ((int64_t) (b[86]) << 16) + | ((int64_t) (b[87]) << 24) + | ((int64_t) (b[88]) << 32) + | ((int64_t) (b[89]) << 40) + | ((int64_t) (b[90]) << 48); + t[13] = ((int64_t) (b[91]) << 0) + | ((int64_t) (b[92]) << 8) + | ((int64_t) (b[93]) << 16) + | ((int64_t) (b[94]) << 24) + | ((int64_t) (b[95]) << 32) + | ((int64_t) (b[96]) << 40) + | ((int64_t) (b[97]) << 48); + t[14] = ((int64_t) (b[98]) << 0) + | ((int64_t) (b[99]) << 8) + | ((int64_t) (b[100]) << 16) + | ((int64_t) (b[101]) << 24) + | ((int64_t) (b[102]) << 32) + | ((int64_t) (b[103]) << 40) + | ((int64_t) (b[104]) << 48); + t[15] = ((int64_t) (b[105]) << 0) + | ((int64_t) (b[106]) << 8) + | ((int64_t) (b[107]) << 16) + | ((int64_t) (b[108]) << 24) + | ((int64_t) (b[109]) << 32) + | ((int64_t) (b[110]) << 40) + | ((int64_t) (b[111]) << 48); + t[16] = ((int64_t) (b[112]) << 0) + | ((int64_t) (b[113]) << 8); + + /* Mod curve order */ + /* 2^446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d */ + /* Mod top half of extra words */ + t[ 4] += (int128_t)0x21cf5b5529eec34L * t[12]; + t[ 5] += (int128_t)0x0f635c8e9c2ab70L * t[12]; + t[ 6] += (int128_t)0x2d944a725bf7a4cL * t[12]; + t[ 7] += (int128_t)0x20cd77058eec490L * t[12]; + t[ 5] += (int128_t)0x21cf5b5529eec34L * t[13]; + t[ 6] += (int128_t)0x0f635c8e9c2ab70L * t[13]; + t[ 7] += (int128_t)0x2d944a725bf7a4cL * t[13]; + t[ 8] += (int128_t)0x20cd77058eec490L * t[13]; + t[ 6] += (int128_t)0x21cf5b5529eec34L * t[14]; + t[ 7] += (int128_t)0x0f635c8e9c2ab70L * t[14]; + t[ 8] += (int128_t)0x2d944a725bf7a4cL * t[14]; + t[ 9] += (int128_t)0x20cd77058eec490L * t[14]; + t[ 7] += (int128_t)0x21cf5b5529eec34L * t[15]; + t[ 8] += (int128_t)0x0f635c8e9c2ab70L * t[15]; + t[ 9] += (int128_t)0x2d944a725bf7a4cL * t[15]; + t[10] += (int128_t)0x20cd77058eec490L * t[15]; + t[ 8] += (int128_t)0x21cf5b5529eec34L * t[16]; + t[ 9] += (int128_t)0x0f635c8e9c2ab70L * t[16]; + t[10] += (int128_t)0x2d944a725bf7a4cL * t[16]; + t[11] += (int128_t)0x20cd77058eec490L * t[16]; + t[12] = 0; + /* Propagate carries */ + c = t[ 4] >> 56; t[ 5] += c; t[ 4] = t[ 4] & 0xffffffffffffff; + c = t[ 5] >> 56; t[ 6] += c; t[ 5] = t[ 5] & 0xffffffffffffff; + c = t[ 6] >> 56; t[ 7] += c; t[ 6] = t[ 6] & 0xffffffffffffff; + c = t[ 7] >> 56; t[ 8] += c; t[ 7] = t[ 7] & 0xffffffffffffff; + c = t[ 8] >> 56; t[ 9] += c; t[ 8] = t[ 8] & 0xffffffffffffff; + c = t[ 9] >> 56; t[10] += c; t[ 9] = t[ 9] & 0xffffffffffffff; + c = t[10] >> 56; t[11] += c; t[10] = t[10] & 0xffffffffffffff; + c = t[11] >> 56; t[12] += c; t[11] = t[11] & 0xffffffffffffff; + /* Mod bottom half of extra words */ + t[ 0] += (int128_t)0x21cf5b5529eec34L * t[ 8]; + t[ 1] += (int128_t)0x0f635c8e9c2ab70L * t[ 8]; + t[ 2] += (int128_t)0x2d944a725bf7a4cL * t[ 8]; + t[ 3] += (int128_t)0x20cd77058eec490L * t[ 8]; + t[ 1] += (int128_t)0x21cf5b5529eec34L * t[ 9]; + t[ 2] += (int128_t)0x0f635c8e9c2ab70L * t[ 9]; + t[ 3] += (int128_t)0x2d944a725bf7a4cL * t[ 9]; + t[ 4] += (int128_t)0x20cd77058eec490L * t[ 9]; + t[ 2] += (int128_t)0x21cf5b5529eec34L * t[10]; + t[ 3] += (int128_t)0x0f635c8e9c2ab70L * t[10]; + t[ 4] += (int128_t)0x2d944a725bf7a4cL * t[10]; + t[ 5] += (int128_t)0x20cd77058eec490L * t[10]; + t[ 3] += (int128_t)0x21cf5b5529eec34L * t[11]; + t[ 4] += (int128_t)0x0f635c8e9c2ab70L * t[11]; + t[ 5] += (int128_t)0x2d944a725bf7a4cL * t[11]; + t[ 6] += (int128_t)0x20cd77058eec490L * t[11]; + t[ 4] += (int128_t)0x21cf5b5529eec34L * t[12]; + t[ 5] += (int128_t)0x0f635c8e9c2ab70L * t[12]; + t[ 6] += (int128_t)0x2d944a725bf7a4cL * t[12]; + t[ 7] += (int128_t)0x20cd77058eec490L * t[12]; + t[ 8] = 0; + /* Propagate carries */ + c = t[ 0] >> 56; t[ 1] += c; t[ 0] = t[ 0] & 0xffffffffffffff; + c = t[ 1] >> 56; t[ 2] += c; t[ 1] = t[ 1] & 0xffffffffffffff; + c = t[ 2] >> 56; t[ 3] += c; t[ 2] = t[ 2] & 0xffffffffffffff; + c = t[ 3] >> 56; t[ 4] += c; t[ 3] = t[ 3] & 0xffffffffffffff; + c = t[ 4] >> 56; t[ 5] += c; t[ 4] = t[ 4] & 0xffffffffffffff; + c = t[ 5] >> 56; t[ 6] += c; t[ 5] = t[ 5] & 0xffffffffffffff; + c = t[ 6] >> 56; t[ 7] += c; t[ 6] = t[ 6] & 0xffffffffffffff; + c = t[ 7] >> 56; t[ 8] += c; t[ 7] = t[ 7] & 0xffffffffffffff; + t[ 0] += (int128_t)0x21cf5b5529eec34L * t[ 8]; + t[ 1] += (int128_t)0x0f635c8e9c2ab70L * t[ 8]; + t[ 2] += (int128_t)0x2d944a725bf7a4cL * t[ 8]; + t[ 3] += (int128_t)0x20cd77058eec490L * t[ 8]; + /* Propagate carries */ + c = t[ 0] >> 56; t[ 1] += c; d[ 0] = (int64_t)(t[ 0] & 0xffffffffffffff); + c = t[ 1] >> 56; t[ 2] += c; d[ 1] = (int64_t)(t[ 1] & 0xffffffffffffff); + c = t[ 2] >> 56; t[ 3] += c; d[ 2] = (int64_t)(t[ 2] & 0xffffffffffffff); + c = t[ 3] >> 56; t[ 4] += c; d[ 3] = (int64_t)(t[ 3] & 0xffffffffffffff); + c = t[ 4] >> 56; t[ 5] += c; d[ 4] = (int64_t)(t[ 4] & 0xffffffffffffff); + c = t[ 5] >> 56; t[ 6] += c; d[ 5] = (int64_t)(t[ 5] & 0xffffffffffffff); + c = t[ 6] >> 56; t[ 7] += c; d[ 6] = (int64_t)(t[ 6] & 0xffffffffffffff); + d[ 7] = t[7]; + /* Mod bits over 56 in last word */ + o = d[7] >> 54; d[ 7] &= 0x3fffffffffffff; + d[ 0] += 0x873d6d54a7bb0dL * o; + d[ 1] += 0x3d8d723a70aadcL * o; + d[ 2] += 0xb65129c96fde93L * o; + d[ 3] += 0x8335dc163bb124L * o; + /* Propagate carries */ + o = d[ 0] >> 56; d[ 1] += o; d[ 0] = d[ 0] & 0xffffffffffffff; + o = d[ 1] >> 56; d[ 2] += o; d[ 1] = d[ 1] & 0xffffffffffffff; + o = d[ 2] >> 56; d[ 3] += o; d[ 2] = d[ 2] & 0xffffffffffffff; + o = d[ 3] >> 56; d[ 4] += o; d[ 3] = d[ 3] & 0xffffffffffffff; + o = d[ 4] >> 56; d[ 5] += o; d[ 4] = d[ 4] & 0xffffffffffffff; + o = d[ 5] >> 56; d[ 6] += o; d[ 5] = d[ 5] & 0xffffffffffffff; + o = d[ 6] >> 56; d[ 7] += o; d[ 6] = d[ 6] & 0xffffffffffffff; + + /* Convert to bytes */ + b[ 0] = (d[0 ] >> 0); + b[ 1] = (d[0 ] >> 8); + b[ 2] = (d[0 ] >> 16); + b[ 3] = (d[0 ] >> 24); + b[ 4] = (d[0 ] >> 32); + b[ 5] = (d[0 ] >> 40); + b[ 6] = (d[0 ] >> 48); + b[ 7] = (d[1 ] >> 0); + b[ 8] = (d[1 ] >> 8); + b[ 9] = (d[1 ] >> 16); + b[10] = (d[1 ] >> 24); + b[11] = (d[1 ] >> 32); + b[12] = (d[1 ] >> 40); + b[13] = (d[1 ] >> 48); + b[14] = (d[2 ] >> 0); + b[15] = (d[2 ] >> 8); + b[16] = (d[2 ] >> 16); + b[17] = (d[2 ] >> 24); + b[18] = (d[2 ] >> 32); + b[19] = (d[2 ] >> 40); + b[20] = (d[2 ] >> 48); + b[21] = (d[3 ] >> 0); + b[22] = (d[3 ] >> 8); + b[23] = (d[3 ] >> 16); + b[24] = (d[3 ] >> 24); + b[25] = (d[3 ] >> 32); + b[26] = (d[3 ] >> 40); + b[27] = (d[3 ] >> 48); + b[28] = (d[4 ] >> 0); + b[29] = (d[4 ] >> 8); + b[30] = (d[4 ] >> 16); + b[31] = (d[4 ] >> 24); + b[32] = (d[4 ] >> 32); + b[33] = (d[4 ] >> 40); + b[34] = (d[4 ] >> 48); + b[35] = (d[5 ] >> 0); + b[36] = (d[5 ] >> 8); + b[37] = (d[5 ] >> 16); + b[38] = (d[5 ] >> 24); + b[39] = (d[5 ] >> 32); + b[40] = (d[5 ] >> 40); + b[41] = (d[5 ] >> 48); + b[42] = (d[6 ] >> 0); + b[43] = (d[6 ] >> 8); + b[44] = (d[6 ] >> 16); + b[45] = (d[6 ] >> 24); + b[46] = (d[6 ] >> 32); + b[47] = (d[6 ] >> 40); + b[48] = (d[6 ] >> 48); + b[49] = (d[7 ] >> 0); + b[50] = (d[7 ] >> 8); + b[51] = (d[7 ] >> 16); + b[52] = (d[7 ] >> 24); + b[53] = (d[7 ] >> 32); + b[54] = (d[7 ] >> 40); + b[55] = (d[7 ] >> 48); + b[56] = 0; +} + +/* Multiply a by b and add d. r = (a * b + d) mod order + * + * r [in] Scalar to hold result. + * a [in] Scalar to multiply. + * b [in] Scalar to multiply. + * d [in] Scalar to add to multiplicative result. + */ +void sc448_muladd(uint8_t* r, const uint8_t* a, const uint8_t* b, + const uint8_t* d) +{ + uint64_t ad[8], bd[8], dd[8], rd[8]; + uint128_t t[16]; + uint128_t c; + uint64_t o; + + /* Load from bytes */ + ad[ 0] = ((int64_t) (a[ 0]) << 0) + | ((int64_t) (a[ 1]) << 8) + | ((int64_t) (a[ 2]) << 16) + | ((int64_t) (a[ 3]) << 24) + | ((int64_t) (a[ 4]) << 32) + | ((int64_t) (a[ 5]) << 40) + | ((int64_t) (a[ 6]) << 48); + ad[ 1] = ((int64_t) (a[ 7]) << 0) + | ((int64_t) (a[ 8]) << 8) + | ((int64_t) (a[ 9]) << 16) + | ((int64_t) (a[10]) << 24) + | ((int64_t) (a[11]) << 32) + | ((int64_t) (a[12]) << 40) + | ((int64_t) (a[13]) << 48); + ad[ 2] = ((int64_t) (a[14]) << 0) + | ((int64_t) (a[15]) << 8) + | ((int64_t) (a[16]) << 16) + | ((int64_t) (a[17]) << 24) + | ((int64_t) (a[18]) << 32) + | ((int64_t) (a[19]) << 40) + | ((int64_t) (a[20]) << 48); + ad[ 3] = ((int64_t) (a[21]) << 0) + | ((int64_t) (a[22]) << 8) + | ((int64_t) (a[23]) << 16) + | ((int64_t) (a[24]) << 24) + | ((int64_t) (a[25]) << 32) + | ((int64_t) (a[26]) << 40) + | ((int64_t) (a[27]) << 48); + ad[ 4] = ((int64_t) (a[28]) << 0) + | ((int64_t) (a[29]) << 8) + | ((int64_t) (a[30]) << 16) + | ((int64_t) (a[31]) << 24) + | ((int64_t) (a[32]) << 32) + | ((int64_t) (a[33]) << 40) + | ((int64_t) (a[34]) << 48); + ad[ 5] = ((int64_t) (a[35]) << 0) + | ((int64_t) (a[36]) << 8) + | ((int64_t) (a[37]) << 16) + | ((int64_t) (a[38]) << 24) + | ((int64_t) (a[39]) << 32) + | ((int64_t) (a[40]) << 40) + | ((int64_t) (a[41]) << 48); + ad[ 6] = ((int64_t) (a[42]) << 0) + | ((int64_t) (a[43]) << 8) + | ((int64_t) (a[44]) << 16) + | ((int64_t) (a[45]) << 24) + | ((int64_t) (a[46]) << 32) + | ((int64_t) (a[47]) << 40) + | ((int64_t) (a[48]) << 48); + ad[ 7] = ((int64_t) (a[49]) << 0) + | ((int64_t) (a[50]) << 8) + | ((int64_t) (a[51]) << 16) + | ((int64_t) (a[52]) << 24) + | ((int64_t) (a[53]) << 32) + | ((int64_t) (a[54]) << 40) + | ((int64_t) (a[55]) << 48); + /* Load from bytes */ + bd[ 0] = ((int64_t) (b[ 0]) << 0) + | ((int64_t) (b[ 1]) << 8) + | ((int64_t) (b[ 2]) << 16) + | ((int64_t) (b[ 3]) << 24) + | ((int64_t) (b[ 4]) << 32) + | ((int64_t) (b[ 5]) << 40) + | ((int64_t) (b[ 6]) << 48); + bd[ 1] = ((int64_t) (b[ 7]) << 0) + | ((int64_t) (b[ 8]) << 8) + | ((int64_t) (b[ 9]) << 16) + | ((int64_t) (b[10]) << 24) + | ((int64_t) (b[11]) << 32) + | ((int64_t) (b[12]) << 40) + | ((int64_t) (b[13]) << 48); + bd[ 2] = ((int64_t) (b[14]) << 0) + | ((int64_t) (b[15]) << 8) + | ((int64_t) (b[16]) << 16) + | ((int64_t) (b[17]) << 24) + | ((int64_t) (b[18]) << 32) + | ((int64_t) (b[19]) << 40) + | ((int64_t) (b[20]) << 48); + bd[ 3] = ((int64_t) (b[21]) << 0) + | ((int64_t) (b[22]) << 8) + | ((int64_t) (b[23]) << 16) + | ((int64_t) (b[24]) << 24) + | ((int64_t) (b[25]) << 32) + | ((int64_t) (b[26]) << 40) + | ((int64_t) (b[27]) << 48); + bd[ 4] = ((int64_t) (b[28]) << 0) + | ((int64_t) (b[29]) << 8) + | ((int64_t) (b[30]) << 16) + | ((int64_t) (b[31]) << 24) + | ((int64_t) (b[32]) << 32) + | ((int64_t) (b[33]) << 40) + | ((int64_t) (b[34]) << 48); + bd[ 5] = ((int64_t) (b[35]) << 0) + | ((int64_t) (b[36]) << 8) + | ((int64_t) (b[37]) << 16) + | ((int64_t) (b[38]) << 24) + | ((int64_t) (b[39]) << 32) + | ((int64_t) (b[40]) << 40) + | ((int64_t) (b[41]) << 48); + bd[ 6] = ((int64_t) (b[42]) << 0) + | ((int64_t) (b[43]) << 8) + | ((int64_t) (b[44]) << 16) + | ((int64_t) (b[45]) << 24) + | ((int64_t) (b[46]) << 32) + | ((int64_t) (b[47]) << 40) + | ((int64_t) (b[48]) << 48); + bd[ 7] = ((int64_t) (b[49]) << 0) + | ((int64_t) (b[50]) << 8) + | ((int64_t) (b[51]) << 16) + | ((int64_t) (b[52]) << 24) + | ((int64_t) (b[53]) << 32) + | ((int64_t) (b[54]) << 40) + | ((int64_t) (b[55]) << 48); + /* Load from bytes */ + dd[ 0] = ((int64_t) (d[ 0]) << 0) + | ((int64_t) (d[ 1]) << 8) + | ((int64_t) (d[ 2]) << 16) + | ((int64_t) (d[ 3]) << 24) + | ((int64_t) (d[ 4]) << 32) + | ((int64_t) (d[ 5]) << 40) + | ((int64_t) (d[ 6]) << 48); + dd[ 1] = ((int64_t) (d[ 7]) << 0) + | ((int64_t) (d[ 8]) << 8) + | ((int64_t) (d[ 9]) << 16) + | ((int64_t) (d[10]) << 24) + | ((int64_t) (d[11]) << 32) + | ((int64_t) (d[12]) << 40) + | ((int64_t) (d[13]) << 48); + dd[ 2] = ((int64_t) (d[14]) << 0) + | ((int64_t) (d[15]) << 8) + | ((int64_t) (d[16]) << 16) + | ((int64_t) (d[17]) << 24) + | ((int64_t) (d[18]) << 32) + | ((int64_t) (d[19]) << 40) + | ((int64_t) (d[20]) << 48); + dd[ 3] = ((int64_t) (d[21]) << 0) + | ((int64_t) (d[22]) << 8) + | ((int64_t) (d[23]) << 16) + | ((int64_t) (d[24]) << 24) + | ((int64_t) (d[25]) << 32) + | ((int64_t) (d[26]) << 40) + | ((int64_t) (d[27]) << 48); + dd[ 4] = ((int64_t) (d[28]) << 0) + | ((int64_t) (d[29]) << 8) + | ((int64_t) (d[30]) << 16) + | ((int64_t) (d[31]) << 24) + | ((int64_t) (d[32]) << 32) + | ((int64_t) (d[33]) << 40) + | ((int64_t) (d[34]) << 48); + dd[ 5] = ((int64_t) (d[35]) << 0) + | ((int64_t) (d[36]) << 8) + | ((int64_t) (d[37]) << 16) + | ((int64_t) (d[38]) << 24) + | ((int64_t) (d[39]) << 32) + | ((int64_t) (d[40]) << 40) + | ((int64_t) (d[41]) << 48); + dd[ 6] = ((int64_t) (d[42]) << 0) + | ((int64_t) (d[43]) << 8) + | ((int64_t) (d[44]) << 16) + | ((int64_t) (d[45]) << 24) + | ((int64_t) (d[46]) << 32) + | ((int64_t) (d[47]) << 40) + | ((int64_t) (d[48]) << 48); + dd[ 7] = ((int64_t) (d[49]) << 0) + | ((int64_t) (d[50]) << 8) + | ((int64_t) (d[51]) << 16) + | ((int64_t) (d[52]) << 24) + | ((int64_t) (d[53]) << 32) + | ((int64_t) (d[54]) << 40) + | ((int64_t) (d[55]) << 48); + + /* a * b + d */ + t[ 0] = dd[ 0] + (int128_t)ad[ 0] * bd[ 0]; + t[ 1] = dd[ 1] + (int128_t)ad[ 0] * bd[ 1] + + (int128_t)ad[ 1] * bd[ 0]; + t[ 2] = dd[ 2] + (int128_t)ad[ 0] * bd[ 2] + + (int128_t)ad[ 1] * bd[ 1] + + (int128_t)ad[ 2] * bd[ 0]; + t[ 3] = dd[ 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] = dd[ 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] = dd[ 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] = dd[ 6] + (int128_t)ad[ 0] * bd[ 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] + + (int128_t)ad[ 6] * bd[ 0]; + t[ 7] = dd[ 7] + (int128_t)ad[ 0] * bd[ 7] + + (int128_t)ad[ 1] * bd[ 6] + + (int128_t)ad[ 2] * bd[ 5] + + (int128_t)ad[ 3] * bd[ 4] + + (int128_t)ad[ 4] * bd[ 3] + + (int128_t)ad[ 5] * bd[ 2] + + (int128_t)ad[ 6] * bd[ 1] + + (int128_t)ad[ 7] * bd[ 0]; + t[ 8] = (int128_t)ad[ 1] * bd[ 7] + + (int128_t)ad[ 2] * bd[ 6] + + (int128_t)ad[ 3] * bd[ 5] + + (int128_t)ad[ 4] * bd[ 4] + + (int128_t)ad[ 5] * bd[ 3] + + (int128_t)ad[ 6] * bd[ 2] + + (int128_t)ad[ 7] * bd[ 1]; + t[ 9] = (int128_t)ad[ 2] * bd[ 7] + + (int128_t)ad[ 3] * bd[ 6] + + (int128_t)ad[ 4] * bd[ 5] + + (int128_t)ad[ 5] * bd[ 4] + + (int128_t)ad[ 6] * bd[ 3] + + (int128_t)ad[ 7] * bd[ 2]; + t[10] = (int128_t)ad[ 3] * bd[ 7] + + (int128_t)ad[ 4] * bd[ 6] + + (int128_t)ad[ 5] * bd[ 5] + + (int128_t)ad[ 6] * bd[ 4] + + (int128_t)ad[ 7] * bd[ 3]; + t[11] = (int128_t)ad[ 4] * bd[ 7] + + (int128_t)ad[ 5] * bd[ 6] + + (int128_t)ad[ 6] * bd[ 5] + + (int128_t)ad[ 7] * bd[ 4]; + t[12] = (int128_t)ad[ 5] * bd[ 7] + + (int128_t)ad[ 6] * bd[ 6] + + (int128_t)ad[ 7] * bd[ 5]; + t[13] = (int128_t)ad[ 6] * bd[ 7] + + (int128_t)ad[ 7] * bd[ 6]; + t[14] = (int128_t)ad[ 7] * bd[ 7]; + t[15] = 0; + + /* Mod curve order */ + /* 2^446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d */ + /* Propagate carries */ + c = t[ 0] >> 56; t[ 1] += c; t[ 0] = t[ 0] & 0xffffffffffffff; + c = t[ 1] >> 56; t[ 2] += c; t[ 1] = t[ 1] & 0xffffffffffffff; + c = t[ 2] >> 56; t[ 3] += c; t[ 2] = t[ 2] & 0xffffffffffffff; + c = t[ 3] >> 56; t[ 4] += c; t[ 3] = t[ 3] & 0xffffffffffffff; + c = t[ 4] >> 56; t[ 5] += c; t[ 4] = t[ 4] & 0xffffffffffffff; + c = t[ 5] >> 56; t[ 6] += c; t[ 5] = t[ 5] & 0xffffffffffffff; + c = t[ 6] >> 56; t[ 7] += c; t[ 6] = t[ 6] & 0xffffffffffffff; + c = t[ 7] >> 56; t[ 8] += c; t[ 7] = t[ 7] & 0xffffffffffffff; + c = t[ 8] >> 56; t[ 9] += c; t[ 8] = t[ 8] & 0xffffffffffffff; + c = t[ 9] >> 56; t[10] += c; t[ 9] = t[ 9] & 0xffffffffffffff; + c = t[10] >> 56; t[11] += c; t[10] = t[10] & 0xffffffffffffff; + c = t[11] >> 56; t[12] += c; t[11] = t[11] & 0xffffffffffffff; + c = t[12] >> 56; t[13] += c; t[12] = t[12] & 0xffffffffffffff; + c = t[13] >> 56; t[14] += c; t[13] = t[13] & 0xffffffffffffff; + c = t[14] >> 56; t[15] += c; t[14] = t[14] & 0xffffffffffffff; + /* Mod top half of extra words */ + t[ 4] += (int128_t)0x21cf5b5529eec34L * t[12]; + t[ 5] += (int128_t)0x0f635c8e9c2ab70L * t[12]; + t[ 6] += (int128_t)0x2d944a725bf7a4cL * t[12]; + t[ 7] += (int128_t)0x20cd77058eec490L * t[12]; + t[ 5] += (int128_t)0x21cf5b5529eec34L * t[13]; + t[ 6] += (int128_t)0x0f635c8e9c2ab70L * t[13]; + t[ 7] += (int128_t)0x2d944a725bf7a4cL * t[13]; + t[ 8] += (int128_t)0x20cd77058eec490L * t[13]; + t[ 6] += (int128_t)0x21cf5b5529eec34L * t[14]; + t[ 7] += (int128_t)0x0f635c8e9c2ab70L * t[14]; + t[ 8] += (int128_t)0x2d944a725bf7a4cL * t[14]; + t[ 9] += (int128_t)0x20cd77058eec490L * t[14]; + t[ 7] += (int128_t)0x21cf5b5529eec34L * t[15]; + t[ 8] += (int128_t)0x0f635c8e9c2ab70L * t[15]; + t[ 9] += (int128_t)0x2d944a725bf7a4cL * t[15]; + t[10] += (int128_t)0x20cd77058eec490L * t[15]; + /* Propagate carries */ + c = t[ 4] >> 56; t[ 5] += c; t[ 4] = t[ 4] & 0xffffffffffffff; + c = t[ 5] >> 56; t[ 6] += c; t[ 5] = t[ 5] & 0xffffffffffffff; + c = t[ 6] >> 56; t[ 7] += c; t[ 6] = t[ 6] & 0xffffffffffffff; + c = t[ 7] >> 56; t[ 8] += c; t[ 7] = t[ 7] & 0xffffffffffffff; + c = t[ 8] >> 56; t[ 9] += c; t[ 8] = t[ 8] & 0xffffffffffffff; + c = t[ 9] >> 56; t[10] += c; t[ 9] = t[ 9] & 0xffffffffffffff; + c = t[10] >> 56; t[11] += c; t[10] = t[10] & 0xffffffffffffff; + /* Mod bottom half of extra words */ + t[ 0] += (int128_t)0x21cf5b5529eec34L * t[ 8]; + t[ 1] += (int128_t)0x0f635c8e9c2ab70L * t[ 8]; + t[ 2] += (int128_t)0x2d944a725bf7a4cL * t[ 8]; + t[ 3] += (int128_t)0x20cd77058eec490L * t[ 8]; + t[ 1] += (int128_t)0x21cf5b5529eec34L * t[ 9]; + t[ 2] += (int128_t)0x0f635c8e9c2ab70L * t[ 9]; + t[ 3] += (int128_t)0x2d944a725bf7a4cL * t[ 9]; + t[ 4] += (int128_t)0x20cd77058eec490L * t[ 9]; + t[ 2] += (int128_t)0x21cf5b5529eec34L * t[10]; + t[ 3] += (int128_t)0x0f635c8e9c2ab70L * t[10]; + t[ 4] += (int128_t)0x2d944a725bf7a4cL * t[10]; + t[ 5] += (int128_t)0x20cd77058eec490L * t[10]; + t[ 3] += (int128_t)0x21cf5b5529eec34L * t[11]; + t[ 4] += (int128_t)0x0f635c8e9c2ab70L * t[11]; + t[ 5] += (int128_t)0x2d944a725bf7a4cL * t[11]; + t[ 6] += (int128_t)0x20cd77058eec490L * t[11]; + /* Propagate carries */ + c = t[ 0] >> 56; t[ 1] += c; rd[ 0] = (int64_t)(t[ 0] & 0xffffffffffffff); + c = t[ 1] >> 56; t[ 2] += c; rd[ 1] = (int64_t)(t[ 1] & 0xffffffffffffff); + c = t[ 2] >> 56; t[ 3] += c; rd[ 2] = (int64_t)(t[ 2] & 0xffffffffffffff); + c = t[ 3] >> 56; t[ 4] += c; rd[ 3] = (int64_t)(t[ 3] & 0xffffffffffffff); + c = t[ 4] >> 56; t[ 5] += c; rd[ 4] = (int64_t)(t[ 4] & 0xffffffffffffff); + c = t[ 5] >> 56; t[ 6] += c; rd[ 5] = (int64_t)(t[ 5] & 0xffffffffffffff); + c = t[ 6] >> 56; t[ 7] += c; rd[ 6] = (int64_t)(t[ 6] & 0xffffffffffffff); + rd[ 7] = t[7]; + /* Mod bits over 56 in last word */ + o = rd[7] >> 54; rd[ 7] &= 0x3fffffffffffff; + rd[ 0] += 0x873d6d54a7bb0dL * o; + rd[ 1] += 0x3d8d723a70aadcL * o; + rd[ 2] += 0xb65129c96fde93L * o; + rd[ 3] += 0x8335dc163bb124L * o; + /* Propagate carries */ + o = rd[ 0] >> 56; rd[ 1] += o; rd[ 0] = rd[ 0] & 0xffffffffffffff; + o = rd[ 1] >> 56; rd[ 2] += o; rd[ 1] = rd[ 1] & 0xffffffffffffff; + o = rd[ 2] >> 56; rd[ 3] += o; rd[ 2] = rd[ 2] & 0xffffffffffffff; + o = rd[ 3] >> 56; rd[ 4] += o; rd[ 3] = rd[ 3] & 0xffffffffffffff; + o = rd[ 4] >> 56; rd[ 5] += o; rd[ 4] = rd[ 4] & 0xffffffffffffff; + o = rd[ 5] >> 56; rd[ 6] += o; rd[ 5] = rd[ 5] & 0xffffffffffffff; + o = rd[ 6] >> 56; rd[ 7] += o; rd[ 6] = rd[ 6] & 0xffffffffffffff; + + /* Convert to bytes */ + r[ 0] = (rd[0 ] >> 0); + r[ 1] = (rd[0 ] >> 8); + r[ 2] = (rd[0 ] >> 16); + r[ 3] = (rd[0 ] >> 24); + r[ 4] = (rd[0 ] >> 32); + r[ 5] = (rd[0 ] >> 40); + r[ 6] = (rd[0 ] >> 48); + r[ 7] = (rd[1 ] >> 0); + r[ 8] = (rd[1 ] >> 8); + r[ 9] = (rd[1 ] >> 16); + r[10] = (rd[1 ] >> 24); + r[11] = (rd[1 ] >> 32); + r[12] = (rd[1 ] >> 40); + r[13] = (rd[1 ] >> 48); + r[14] = (rd[2 ] >> 0); + r[15] = (rd[2 ] >> 8); + r[16] = (rd[2 ] >> 16); + r[17] = (rd[2 ] >> 24); + r[18] = (rd[2 ] >> 32); + r[19] = (rd[2 ] >> 40); + r[20] = (rd[2 ] >> 48); + r[21] = (rd[3 ] >> 0); + r[22] = (rd[3 ] >> 8); + r[23] = (rd[3 ] >> 16); + r[24] = (rd[3 ] >> 24); + r[25] = (rd[3 ] >> 32); + r[26] = (rd[3 ] >> 40); + r[27] = (rd[3 ] >> 48); + r[28] = (rd[4 ] >> 0); + r[29] = (rd[4 ] >> 8); + r[30] = (rd[4 ] >> 16); + r[31] = (rd[4 ] >> 24); + r[32] = (rd[4 ] >> 32); + r[33] = (rd[4 ] >> 40); + r[34] = (rd[4 ] >> 48); + r[35] = (rd[5 ] >> 0); + r[36] = (rd[5 ] >> 8); + r[37] = (rd[5 ] >> 16); + r[38] = (rd[5 ] >> 24); + r[39] = (rd[5 ] >> 32); + r[40] = (rd[5 ] >> 40); + r[41] = (rd[5 ] >> 48); + r[42] = (rd[6 ] >> 0); + r[43] = (rd[6 ] >> 8); + r[44] = (rd[6 ] >> 16); + r[45] = (rd[6 ] >> 24); + r[46] = (rd[6 ] >> 32); + r[47] = (rd[6 ] >> 40); + r[48] = (rd[6 ] >> 48); + r[49] = (rd[7 ] >> 0); + r[50] = (rd[7 ] >> 8); + r[51] = (rd[7 ] >> 16); + r[52] = (rd[7 ] >> 24); + r[53] = (rd[7 ] >> 32); + r[54] = (rd[7 ] >> 40); + r[55] = (rd[7 ] >> 48); + r[56] = 0; +} + +/* Precomputed multiples of the base point. */ +static const ge448_precomp base[58][8] = { +{ + { + { 0x26a82bc70cc05eL, 0x80e18b00938e26L, 0xf72ab66511433bL, + 0xa3d3a46412ae1aL, 0x0f1767ea6de324L, 0x36da9e14657047L, + 0xed221d15a622bfL, 0x4f1970c66bed0dL }, + { 0x08795bf230fa14L, 0x132c4ed7c8ad98L, 0x1ce67c39c4fdbdL, + 0x05a0c2d73ad3ffL, 0xa3984087789c1eL, 0xc7624bea73736cL, + 0x248876203756c9L, 0x693f46716eb6bcL } + }, + { + { 0x55555555555555L, 0x55555555555555L, 0x55555555555555L, + 0x55555555555555L, 0xaaaaaaaaaaaaa9L, 0xaaaaaaaaaaaaaaL, + 0xaaaaaaaaaaaaaaL, 0xaaaaaaaaaaaaaaL }, + { 0xeafbcdea9386edL, 0xb2bed1cda06bdaL, 0x833a2a3098bbbcL, + 0x8ad8c4b80d6565L, 0x884dd7b7e36d72L, 0xc2b0036ed7a035L, + 0x8db359d6205086L, 0xae05e9634ad704L } + }, + { + { 0x28173286ff2f8fL, 0xb769465da85757L, 0xf7f6271fd6e862L, + 0x4a3fcfe8daa9cbL, 0xda82c7e2ba077aL, 0x943332241b8b8cL, + 0x6455bd64316cb6L, 0x0865886b9108afL }, + { 0x22ac13588ed6fcL, 0x9a68fed02dafb8L, 0x1bdb6767f0bffaL, + 0xec4e1d58bb3a33L, 0x56c3b9fce43c82L, 0xa6449a4a8d9523L, + 0xf706cbda7ad43aL, 0xe005a8dbd5125cL } + }, + { + { 0xce42ac48ba7f30L, 0xe1798949e120e2L, 0xf1515dd8ba21aeL, + 0x70c74cc301b7bdL, 0x0891c693fda4beL, 0x29ea255a09cf4eL, + 0x2c1419a17226f9L, 0x49dcbc5c6c0cceL }, + { 0xe236f86de51839L, 0x44285d0d4f5b32L, 0x7ea1ca9472b5d4L, + 0x7b8a5bc1c0d8f9L, 0x57d845c90dc322L, 0x1b979cb7c02f04L, + 0x27164b33a5de02L, 0xd49077e4accde5L } + }, + { + { 0xa99d1092030034L, 0x2d8cefc6f950d0L, 0x7a920c3c96f07bL, + 0x958812808bc0d5L, 0x62ada756d761e8L, 0x0def80cbcf7285L, + 0x0e2ba7601eedb5L, 0x7a9f9335a48dcbL }, + { 0xb4731472f435ebL, 0x5512881f225443L, 0xee59d2b33c5840L, + 0xb698017127d7a4L, 0xb18fced86551f7L, 0x0ade260ca1823aL, + 0xd3b9109ce4fd58L, 0xadfd751a2517edL } + }, + { + { 0x7fd7652abef79cL, 0x6c20a07443a878L, 0x5c1840d12a7109L, + 0x4a06e4a876451cL, 0x3bed0b4ad95f65L, 0x25d2e673fb0260L, + 0x2e00349aebd971L, 0x54523e04498b72L }, + { 0xea5d1da07c7bccL, 0xcce776938ea98cL, 0x80284e861d2b3eL, + 0x48de76b6e1ff1bL, 0x7b121869c58522L, 0xbfd053a2765a1aL, + 0x2d743ec056c667L, 0x3f99b9cd8ab61cL } + }, + { + { 0xdf9567ceb5eaf7L, 0x110a6b478ac7d7L, 0x2d335014706e0bL, + 0x0df9c7b0b5a209L, 0xba4223d568e684L, 0xd78af2d8c3719bL, + 0x77467b9a5291b6L, 0x079748e5c89befL }, + { 0xe20d3fadac377fL, 0x34e866972b5c09L, 0xd8687a3c40bbb7L, + 0x7b3946fd2f84c9L, 0xd00e40ca78f50eL, 0xb87594417e7179L, + 0x9c7373bcb23583L, 0x7ddeda3c90fd69L } + }, + { + { 0x2538a67153bde0L, 0x223aca9406b696L, 0xf9080dc1ad713eL, + 0x6c4cb47d816a64L, 0xbc285685dc8b97L, 0xd97b037c08e2d7L, + 0x5b63fb45d0e66bL, 0xd1f1bc5520e8a3L }, + { 0x4eb873ce69e09bL, 0x1663164bc8ee45L, 0x08f7003ba8d89fL, + 0x4b98ead386ad82L, 0xa4b93b7bd94c7bL, 0x46ba408c6b38b3L, + 0xdae87d1f3574ffL, 0xc7564f4e9bea9bL } + }, +}, +{ + { + { 0x2e4fdb25bfac1cL, 0xf0d79aaf5f3bcaL, 0xe756b0d20fb7ccL, + 0xe3696beb39609aL, 0xa019fc35a5ab58L, 0xa2b24853b281ddL, + 0xe3e2be761ac0a2L, 0xf19c34feb56730L }, + { 0x2d25ce8a30241eL, 0xf5661eab73d7a1L, 0x4611ed0daac9f4L, + 0xd5442344ced72cL, 0xce78f52e92e985L, 0x6fe5dd44da4aadL, + 0xfcaddc61d363ceL, 0x3beb69cc9111bfL } + }, + { + { 0xd2e7660940ebc9L, 0xe032018b17bbe0L, 0xad4939175c0575L, + 0xdd0b14721c7f34L, 0x52c2ba43e147e0L, 0x7dd03c60ee8973L, + 0x5472e8decf2754L, 0x17a1cd1d6482bbL }, + { 0xdd43b848128b3fL, 0xf0cae34ea7dd25L, 0x81ca99fff07df2L, + 0x1c8959792ebbdcL, 0x45c7a6872155e6L, 0x907a50e39ddd08L, + 0xbe398c2bb2d89bL, 0x38063f91b3b536L } + }, + { + { 0x149fafbf843b23L, 0x00ab582ac7f22aL, 0xa3b981bf2f4d4cL, + 0x2ce1a654341a22L, 0x68a40747c03b63L, 0x63206a212f2cf8L, + 0xc9961d35149741L, 0xfb85430bc7099eL }, + { 0x9c9107290a9e59L, 0x734e94a06de367L, 0x5cf3cbedb99214L, + 0xc6bce3245b1fb9L, 0x1a82abedd7be0dL, 0xf74976aede7d1cL, + 0x7025b7c21503bdL, 0xf7894910d096abL } + }, + { + { 0x6bd48bb555a41bL, 0xfbdd0d067de206L, 0x98bc477dd6dfd1L, + 0x1d0693b3e40b8aL, 0x6e15563da32ae4L, 0x0194a20fcebaa2L, + 0xda116150980a93L, 0x8e119200109cecL }, + { 0x8ea0552ffb9726L, 0xeba50a4047e44bL, 0xc050d2460ddf76L, + 0xe009204ac690e0L, 0x47b86399b18edcL, 0x2f5b76ac77f23fL, + 0x4296c240792905L, 0x73f6b4a06f6dc7L } + }, + { + { 0xb6ef9ea3b10cadL, 0x312843df7c8fceL, 0x5bdcd528bedf86L, + 0x2889059f6dd823L, 0x04578e908bfde0L, 0x3245df3123e2e5L, + 0xbf461d57ee9e3aL, 0xddec2d46f94cebL }, + { 0x21b43b9145768fL, 0xe79a8f9dae962aL, 0xff1972bcbb043fL, + 0xe3dcf6d239649bL, 0xed592bdc533b85L, 0x14ff94fdbe22d0L, + 0x6c4eb87f1d8e22L, 0xd8d4c71d18cf6dL } + }, + { + { 0xcda666c8d96345L, 0x9ecaa25836cd21L, 0x6e885bd984606eL, + 0x1dd5fef804f054L, 0x9dfff6b6959ae4L, 0x99b9cf8c9b55ccL, + 0xb4716b062b9b80L, 0x13ec87c554b128L }, + { 0xe696d1f75aacc2L, 0xf78c99387fc5ffL, 0x76c09473809d42L, + 0x99ce62db618fa8L, 0x35e3e022f53341L, 0x62fc1ac0db6c5eL, + 0xa1fb8e600d8b47L, 0x0bc107058f0d1eL } + }, + { + { 0x1f4526916da513L, 0x1f2fc04f5cf341L, 0xae9208664d23e0L, + 0x4e33082da8a113L, 0x2688ec61cfc085L, 0x6f2e8de6e5327fL, + 0x2070db3b4e48a8L, 0xd6626973240adeL }, + { 0xa6b317ffbd997bL, 0x9fa1b5649e26bdL, 0xcbf0d258cba0f3L, + 0x4a7791b17b4745L, 0x25f555b5c9e190L, 0x7cd3940923ec4cL, + 0x16f4c6ae98f1b6L, 0x7962116bcd4e0fL } + }, + { + { 0x8d58fa302491e3L, 0x7cf76c67ab3898L, 0xbc2f657647ebc7L, + 0x5f4bfe0d25f5a3L, 0x503f478d69505dL, 0x4a889fc3fb6645L, + 0x33e1bc1fa86b18L, 0xabb234f5508dd8L }, + { 0x5348e1b9a05b48L, 0x57ac5f164dc858L, 0x21f4d38ec8a2d3L, + 0x5ec6d3ca3a3e9dL, 0xcd4062e560a0b8L, 0x49b74f73433f59L, + 0xefd9d87cab14e3L, 0x858ce7feb964f5L } + }, +}, +{ + { + { 0x7577254eb731b4L, 0x9fff1fb4e2397eL, 0x749b145c821715L, + 0x40619fe2e65e67L, 0x57b82812e618d8L, 0x063186c707b83eL, + 0xcfc80cb31b24a2L, 0xcca6185ac75169L }, + { 0x6539f44b255818L, 0x5895da00368bceL, 0x841a30917c7482L, + 0x85469e1b1a9c9eL, 0x05664c0e4f7d9dL, 0x8a063187b35cc0L, + 0x214763aa0e9b0aL, 0x1bd872c4b26ac2L } + }, + { + { 0x3578f97a93762bL, 0x434f69a72d52bcL, 0xddcca4022cb565L, + 0xa7d1e41ff20544L, 0x823475d8a66588L, 0x9fc97c799d7bafL, + 0x15542f1660e421L, 0xa7d1f60843faf6L }, + { 0xbbfaab54063cccL, 0x3ad9bada49855aL, 0xffd5f1c5bddbfeL, + 0x0e419c2ae87e59L, 0xdce6ed6f89956bL, 0xf047c21ccd8951L, + 0x6ed4a1ba83c991L, 0x85af86e2d28e0aL } + }, + { + { 0x04433c49ed48a8L, 0xeffa8580bc375dL, 0xfb0e1b2fa6e3b5L, + 0x51483a2a1aaddaL, 0x733448df8b2ea8L, 0xaa0513cf639f0cL, + 0x6bc61a3a23bf84L, 0x3e64f68dc2430dL }, + { 0x51bf502c5876b1L, 0x6b833751c0dd2aL, 0xe597be1342914fL, + 0x43d5ab0f8e632cL, 0x2696715d62587bL, 0xe87d20aed34f24L, + 0x25b7e14e18baf7L, 0xf5eb753e22e084L } + }, + { + { 0x51da71724d8295L, 0xd478e4318d1340L, 0xacf94f42cf7f66L, + 0x230d7d13760711L, 0x078a66a5abc626L, 0xd78b0bd6b5f6daL, + 0x23a971396d1d0bL, 0x87623d64bd960fL }, + { 0x0841a9977db53fL, 0x23c1a53f4d03eeL, 0x2f62c2e1f95df1L, + 0xd1e2ec1116f4e7L, 0x896d2fe34811a9L, 0xad65e2bec8096eL, + 0x09d36f9b1744a6L, 0x564bac7ff5ddf7L } + }, + { + { 0x48b41e2c3f77cbL, 0x52276730968938L, 0xff1b899fd9b452L, + 0x67cf3bf2e03908L, 0x3731d90248a6fbL, 0xd800a05256598fL, + 0x347d2f2bdc8530L, 0xc72a3007ad08a1L }, + { 0x5e5be741d65f73L, 0x183d4ae4206eadL, 0xcb50c1cade4013L, + 0x39db43d3102483L, 0x0eb49fa70d6325L, 0xa18f6a2c1f02b9L, + 0x3e6fe30dbf5e66L, 0xac4eeb93a82aa5L } + }, + { + { 0x295affd3613d47L, 0x7b7e68ab56f343L, 0x980629692b173bL, + 0x937061ebad35fbL, 0x25019785c21eeaL, 0xe92721b787a746L, + 0x463c46c3651631L, 0x6da4b5dc6f2d5aL }, + { 0xcb67cc16e6d18cL, 0x1b30d520010588L, 0x1bb6ea6db1d1e8L, + 0x9c6308aad11474L, 0xc3167413d19b1cL, 0xf2e84d7be4fb79L, + 0xeccb873e050f77L, 0xf7c8d80cc2bf86L } + }, + { + { 0x16fe2e17ab20e5L, 0x274deadecf3a92L, 0x9f434870972f67L, + 0x9a65a454605751L, 0x9351f07b8980b2L, 0x412962b0eb08a5L, + 0xb8c9bfd733f440L, 0xac2cd641ca250fL }, + { 0x68cdd0f2ba7d26L, 0xd3d2a4a4e0beeaL, 0x50135c19f4a258L, + 0xb475e53f0d02e4L, 0x432d8c6589283aL, 0x29141bfa0a2b6cL, + 0xd7379ec13704bcL, 0x831562c52459bfL } + }, + { + { 0x676b366eeec506L, 0xdd6cad545da557L, 0x9de39cb77057d2L, + 0x388c5fedf05bf1L, 0x6e55650dfb1f03L, 0xdbceffa52126c9L, + 0xe4d187b3a4a220L, 0xac914f9eb27020L }, + { 0x3f4ab98d2e5f30L, 0x6ae97dadd94451L, 0x64af6950d80981L, + 0x36b4b90f2aa2ceL, 0x6adcd7a18fcf59L, 0x3ddfe6dc116c81L, + 0x661072b549b9e3L, 0xd9e3134ec4584dL } + }, +}, +{ + { + { 0x6e46707a1e400cL, 0xcdc990b551e806L, 0xfa512513a07724L, + 0x500553f1b3e4f5L, 0x67e8b58ef4dac3L, 0x958349f2cb4cc7L, + 0x948b4ed7f9143cL, 0xe646d092b7822bL }, + { 0xd185dd52bc3c26L, 0x34ba16ec837fc9L, 0x516d4ba5a788b7L, + 0x72f2de756142b0L, 0x5846f61f445b3dL, 0xdaec5c9f4631a1L, + 0xa10b18d169ea9bL, 0x85d2998af6751bL } + }, + { + { 0xda0cac443ddf31L, 0x0966e171860911L, 0x9c3a7173cba600L, + 0x5781880571f895L, 0x5e2a927737ac21L, 0x8a461486c253fbL, + 0xe801cf595ee626L, 0x271166a5f84fc0L }, + { 0x306937fba856bdL, 0x80cb179be80a43L, 0x70393b2ffb5980L, + 0xa8e4a1c660fc64L, 0x5078abfc0d5c98L, 0x62ba530fbd31ffL, + 0xda608449e51b88L, 0xdb6ecb0355ae15L } + }, + { + { 0xbcbb6ea23c5d49L, 0x08906ba87959bcL, 0x61cc0880991665L, + 0x21d6b41d90d13cL, 0x0c27ac1d03afe9L, 0x159995f5cfea52L, + 0x4057e20bdfe220L, 0xdd1b349cbdf058L }, + { 0x0cd66262e37159L, 0x8cea8e43eb0d17L, 0x553af085bce7f0L, + 0xb94cb5f5b6511dL, 0x7b8d3a550e0330L, 0x415911057ab7e7L, + 0x320820e6aa886fL, 0x130d4d6c5b6b81L } + }, + { + { 0x2f98059c7bb2edL, 0x33ebf4ca49bdfbL, 0x04c72a1b0a675bL, + 0x94f9ea4adb6c14L, 0x03376d8cf728c0L, 0x5c059d34c6eb6aL, + 0x0178408eb8da48L, 0x8bf607b2956817L }, + { 0x7ad2822ceb3d28L, 0xd07a40337ae653L, 0xbc68739c1e46b2L, + 0x15d7cca9154ba9L, 0x6b97103a26617dL, 0xa610314b2e0d28L, + 0x52a08bafd4d363L, 0x80c2638c7dc2afL } + }, + { + { 0x0cde7ef3187140L, 0x93b92ca4b70acdL, 0x5696e507a79cdcL, + 0x73cc9728eaab66L, 0x6b8c5b68f1b0c7L, 0xb39a3184f7e0b1L, + 0x72cfb0d376108aL, 0x0c53efc98536a7L }, + { 0x03b52a824c2f1eL, 0x717132e6399b78L, 0x31ebd25349a85dL, + 0x265ee811a200d4L, 0x0b1aad2407d7adL, 0x9a9ebc894d2962L, + 0x994e6cd41171d9L, 0x09178d86c8fa83L } + }, + { + { 0x7d1d238a2593a1L, 0x863e93ab38fb19L, 0xd23a4cce7712a9L, + 0x7477b1327efcd5L, 0x3ba69ff1392f6cL, 0x63e0c32f7bb5a5L, + 0x20412c0026effdL, 0xd3ee8e4ef424abL }, + { 0x14c0b2d64e5174L, 0x2a611f2e58c47bL, 0xaa58a06c1e8635L, + 0x1870c3ecf17034L, 0xb0d5e3483f1bf3L, 0xb19905c16c7eb3L, + 0xbf85d626efa4caL, 0xfd16b2f180f92bL } + }, + { + { 0xc0431af3adcb48L, 0xc9a7a8dba90496L, 0xd765a163895294L, + 0xb02a41a551de70L, 0xb71b261749b8a1L, 0x0dfa89ec6f3e47L, + 0x392c0d80f5d9ceL, 0x43c59d831aee3cL }, + { 0x94bfb6d4d76f49L, 0xe8f5b8227d68a5L, 0x78ae1d9630fd08L, + 0x1379029ce1bdaeL, 0x9689da066715dcL, 0x5d4cb24d3278c7L, + 0x77c98339e84fbcL, 0xc8478dcea1048cL } + }, + { + { 0xe4b8f31770d2baL, 0x744f65242ea095L, 0xd06e090036f138L, + 0xd3a3d5b3b078caL, 0xc7ae54178b8417L, 0xad6c5d4c738fd7L, + 0x61789844676454L, 0xfbf34235d9a392L }, + { 0x8e451a7fff772fL, 0x8605bb75ffbeadL, 0x6f75cc1930d59fL, + 0xd4f47558f3f460L, 0xefd2d796700c8aL, 0xceb462a2406421L, + 0x8ed0f979dfe8f1L, 0x0280bf1d1d7600L } + }, +}, +{ + { + { 0x761c219dd9a54dL, 0x1127fcb86a39c0L, 0x7d0e4f04c9beddL, + 0x27c017a4d976b6L, 0x800c973da042cfL, 0xe7419af2593f11L, + 0xbd49448ae67960L, 0xd3b60b7744fd85L }, + { 0x5e74ed961676feL, 0x7383ef339af627L, 0x34407e05e62df7L, + 0xb0534618bf3196L, 0xd6b7184583b407L, 0xe3d068555011beL, + 0x94083d02124b52L, 0xa908324f780aafL } + }, + { + { 0xb27af1a73ec9c3L, 0xb66ad9f70fa725L, 0x07724f58cf73e4L, + 0xc3fcd579949358L, 0x06efb79da0cc01L, 0x1e977d210597c9L, + 0xcd732be703e8d6L, 0x6fd29bf6d0b69eL }, + { 0xca658ac667128eL, 0xca0036ac7872b3L, 0xc9698585355837L, + 0x59f3be8075cf1cL, 0x9f1b9b03809a11L, 0x6881ced9733871L, + 0x8cda0fbe902a5fL, 0x4d8c69b4e3871eL } + }, + { + { 0x5c3bd07ddee82fL, 0xe52dd312f9723bL, 0xcf8761174f1be8L, + 0xd9ecbd835f8657L, 0x4f77393fbfea17L, 0xec9579fd78fe2cL, + 0x320de920fb0450L, 0xbfc9b8d95d9c47L }, + { 0x818bd425e1b4c3L, 0x0e0c41c40e2c78L, 0x0f7ce9abccb0d0L, + 0xc7e9fa45ef81fbL, 0x2561d6f73574adL, 0xa2d8d99d2efb0bL, + 0xcf8f316e96cd0aL, 0x088f0f14964807L } + }, + { + { 0x0a8498945d5a19L, 0x47ab39c6c2131fL, 0x5c02824f3fc35dL, + 0x3be77c89ee8127L, 0xa8491b7c90b80aL, 0x5397631a28aa93L, + 0x54d6e816c0b344L, 0x22878be876d0e4L }, + { 0xeecb8a46db3bf6L, 0x340f29554577a3L, 0xa7798689a00f85L, + 0x98465d74bb9147L, 0x9532d7dda3c736L, 0x6d574f17504b20L, + 0x6e356f4d86e435L, 0x70c2e8d4533887L } + }, + { + { 0xdce5a0ad293980L, 0x32d7210069010eL, 0x64af59f06deaaaL, + 0xd6b43c459239e4L, 0x74bf2559199c29L, 0x3efff4111e1e2bL, + 0x1aa7b5ecb0f8d8L, 0x9baa22b989e395L }, + { 0xf78db807b33ac1L, 0x05a3b4354ce80aL, 0x371defc7bc8e12L, + 0x63305a01224610L, 0x028b1ae6d697efL, 0x7aba39c1cd8051L, + 0x76ed7a928ee4b4L, 0x31bd02a7f99901L } + }, + { + { 0xf9dab7af075566L, 0x84e29a5f56f18bL, 0x3a4c45af64e56dL, + 0xcf3644a6a7302dL, 0xfb40808156b658L, 0xf33ef9cf96be52L, + 0xfe92038caa2f08L, 0xcfaf2e3b261894L }, + { 0xf2a0dbc224ce3fL, 0xed05009592eb27L, 0x501743f95889d0L, + 0xa88a47877c95c2L, 0x86755fbdd63da9L, 0x9024acfc7ee828L, + 0x634b020f38113bL, 0x3c5aacc6056e64L } + }, + { + { 0xe03ff3aa2ef760L, 0x3b95767b1c3bacL, 0x51ce6aa940d754L, + 0x7cbac3f47a9a3dL, 0xa864ac434f8d1aL, 0x1eff3f280dbd47L, + 0xd8ab6607ebd5caL, 0xc4df5c405b07edL }, + { 0x3dc92dfa4f095bL, 0x5ae36a57cdbd9aL, 0x7ff29737891e04L, + 0x37c03130a5fe7bL, 0x210d7b0aa6e35eL, 0x6edfb53bf200d8L, + 0x787b68d84afb85L, 0x9b5c49b72c6de3L } + }, + { + { 0x51857164010f4eL, 0xe0b144b0536ebeL, 0xacabb14887d663L, + 0xac1caededf584fL, 0xb43fb8faf175a3L, 0x310b6d5f992a3cL, + 0xf2c4aa285178a4L, 0x69c99698bd56bfL }, + { 0x73d6372a4d972eL, 0x3d5bb2e9583803L, 0x7bf7d18d891581L, + 0xa5ce5d7568a34aL, 0x670b4331f45c81L, 0x97265a71f96910L, + 0xdb14eb3b07c1eaL, 0xdf008eafed447cL } + }, +}, +{ + { + { 0x0379f5a00c2f10L, 0xb320b4fd350285L, 0x74e560e8efdd7dL, + 0xf2f017ef46a140L, 0x2ced1a60f34624L, 0x7c4b4e3ca08ec9L, + 0xdffc2a15d8bc6bL, 0xcc8f3f3527b007L }, + { 0x59f8ac4861fe83L, 0x8d48d2cd03144cL, 0xa8457d2bfa6dceL, + 0xd7ed333677c136L, 0xcb8e219c228e18L, 0x5f70bc916ab1e4L, + 0x2ae3a3d3780370L, 0x9f3365488f17adL } + }, + { + { 0xeab0710960e4bbL, 0xc668a78ab9cfd3L, 0x2e85553b0ef946L, + 0xa43c4b98df5df3L, 0x0ecd5593cb3646L, 0x6f543c418dbe71L, + 0xee7edaaf59818bL, 0xc44e8d290911c1L }, + { 0xafb38b1269b509L, 0x9e2737c52afe2cL, 0x5b2ef02ccfa664L, + 0x1e0aeace1cc58bL, 0x37a57e95ea134eL, 0xc9c465a83b9fc2L, + 0x4b9e8c76e3eccaL, 0xca07dbe9bdbab5L } + }, + { + { 0xd297f3cb0d7807L, 0xee441a5f59ce61L, 0x728553bb2db844L, + 0x90f87e5640e9e0L, 0xaa72cbfcb76dffL, 0x065c6864012d57L, + 0xd5ee88f9678b44L, 0x3d74b852177603L }, + { 0x3f9c947748b68eL, 0x03856d98f44d44L, 0xde34b84462426cL, + 0xc16d1bb845ab29L, 0x9df6217d2e18deL, 0xec6d219b154643L, + 0x22a8ec32ee0f8fL, 0x632ad3891c5175L } + }, + { + { 0x19d9d236869267L, 0x628df94fe5532aL, 0x458d76c6dc9a01L, + 0x405fe6c2cc39c8L, 0x7dddc67f3a04baL, 0xfee630312500c7L, + 0x580b6f0a50e9deL, 0xfb5918a6090604L }, + { 0xd7159253af6b2dL, 0x83d62d61c7d1ecL, 0x94398c185858c4L, + 0x94643dc14bfb64L, 0x758fa38af7db80L, 0xe2d7d93a8a1557L, + 0xa569e853562af1L, 0xd226bdd84346aaL } + }, + { + { 0xc2d0a5ed0ccd20L, 0xeb9adb85dbc0cfL, 0xe0a29ee26d7e88L, + 0x8bb39f884a8e98L, 0x511f1c137396eaL, 0xbc9ec5ac8b2fb3L, + 0x299d81c090e5bcL, 0xe1dfe344cdd587L }, + { 0x80f61f45e465b7L, 0x5699c531bad59eL, 0x85e92e4b79ff92L, + 0x1e64fce9db244cL, 0x3748574a22097dL, 0xe2aa6b9efff24eL, + 0xb951be70a10bc6L, 0x66853269067a1cL } + }, + { + { 0xf716ddfa6114d3L, 0x9e515f5037ec1fL, 0x773454144944a6L, + 0x1540c4caba97ccL, 0xe41e5488b54bb7L, 0x4363156cae37bcL, + 0xc384eaff3d2ce8L, 0x72a4f454c58ba4L }, + { 0x0ceb530dcaf3fcL, 0x72d536578dcdbbL, 0x9b44084c6320faL, + 0x6262d34eb74c70L, 0x8abac85608e6dcL, 0x82a526410dd38dL, + 0xbc39911a819b8dL, 0xbda15fe03ad0d9L } + }, + { + { 0xadbf587f9dc60bL, 0xf9d814f7d846d2L, 0xccdd241b77bde0L, + 0x89cb6d72242f50L, 0x95c0e3ee6360a8L, 0x7c7dd5adf49713L, + 0x68e0e4957d5814L, 0x3aa097d0c16571L }, + { 0xb56b672267d03aL, 0x4f557088c44af4L, 0x67c49e7f3252a5L, + 0x871d6cfc94a469L, 0x57ae99801fbfaaL, 0x5c0e48f48a5d8eL, + 0xe9bf9c85e240b9L, 0xa41018999d41caL } + }, + { + { 0x6beb0c7b2889b4L, 0x78b7f899455370L, 0xd43421447ca364L, + 0xdd9d2da9f21e5bL, 0xa0c7c180a7e4aaL, 0x022c0d4da1660cL, + 0xe1f5c165a57002L, 0x51c7c9e518f68fL }, + { 0x6d521b62586502L, 0xa0f2cb3183ec1bL, 0x578b4e0caa5e16L, + 0x7bd4fbd764997fL, 0x7ec56c364b1804L, 0xb75a2540ee08e4L, + 0x6bf74a6dc19080L, 0x6ec793d97d6e59L } + }, +}, +{ + { + { 0x16789d60a4beb9L, 0x512b2cd9b9c801L, 0xf8b6d108c7bb9cL, + 0xd85651e9ebdc8cL, 0xc9450829ba971aL, 0x852d9ea7e1cf78L, + 0x6a45e350af01e2L, 0xe6cdadf6151dcfL }, + { 0xc454bb42b8c01bL, 0x59e0c493d54cd2L, 0x8e1e686454d608L, + 0x0dbae4bd8c6103L, 0xa5603a16c18b18L, 0x227a6b23369093L, + 0xf1e89295f3de1cL, 0x42f0b588ab63c5L } + }, + { + { 0xf1974cc5b596d8L, 0xee8093f44719f0L, 0x40ba933f6f5b54L, + 0xd6e53652f3d654L, 0x9aeb83526d73b8L, 0x50ed5350776382L, + 0x3be47d6ad43875L, 0x21d56dfc786e48L }, + { 0x8a75e18b73bb39L, 0x9eba84cf265a78L, 0x7c02a4d2e772e7L, + 0xf7df6d44c1ecd2L, 0xa8d9ea06cef71bL, 0x86e8f91cae3b68L, + 0x2fd141199efefaL, 0x0b36ab2214e6f6L } + }, + { + { 0xd79065cbdce61cL, 0xcb562ffdecb229L, 0xef5d3d14600849L, + 0x348b31b1d23ac8L, 0xb2ea69915c36b8L, 0x268683d4822836L, + 0x083edbec6f0b7dL, 0xaf4f39d1a7821cL }, + { 0x23be6e84e64841L, 0xe9e246365bf791L, 0xa3208ac02bfd7cL, + 0x231989cd01357dL, 0x79b8aad6422ab4L, 0x57d2b7e91b8564L, + 0x28ebbcc8c04421L, 0xdc787d87d09c05L } + }, + { + { 0xeb99f626c7bed5L, 0x326b15f39cd0e8L, 0xd9d53dcd860615L, + 0xdf636e71bf4205L, 0x1eaa0bf0752209L, 0x17ce69a4744abbL, + 0x474572df3ea2fbL, 0xc4f6f73224a7f3L }, + { 0x7ed86ad63081b4L, 0xcd4cdc74a20afbL, 0x7563831b301b2eL, + 0x5b4d2b1e038699L, 0xa15d1fa802a15fL, 0x6687aaf13e9172L, + 0x3eccd36ba6da90L, 0x34e829d7474e83L } + }, + { + { 0x4cea19b19c9b27L, 0xa14c37a5f52523L, 0x248b16d726625cL, + 0x8c40f9f6cabc21L, 0x918470c32a5c65L, 0x314056b2a98d5bL, + 0x6c974cf34a0714L, 0x0c8f8a94f6314aL }, + { 0x484455770bccfdL, 0xf5835db740c9fdL, 0x12e59b5a21407cL, + 0xbe338e0db1689dL, 0x5a50ce9dd5e915L, 0xb1780e9ef99f39L, + 0x1262b55ee4d833L, 0x4be3f2289c5340L } + }, + { + { 0xbb99b906c4b858L, 0xa7724d1550ca53L, 0x7d31f5a826962eL, + 0xf239322a5804daL, 0x3e113200275048L, 0xcbb1bb83ee4cb6L, + 0xdb865251331191L, 0xb7caf9e7d1d903L }, + { 0x06e3b0577d7a9dL, 0x7a132b0b3bbbf5L, 0xd61fbc57c50575L, + 0x393f712af4b646L, 0xef77972cb7efe9L, 0x20e6d5d5ea4995L, + 0x0ac23d4fbbe4c6L, 0x8456617c807f2aL } + }, + { + { 0x4995fb35396143L, 0xa8b4bd1b99dc46L, 0x2293e8e4150064L, + 0x2f77d4922a3545L, 0xe866b03b2192c4L, 0x58b01f05e0aa38L, + 0xe406b232ed246bL, 0x447edb3ed60974L }, + { 0xf541b338869703L, 0x6959fe0383420aL, 0xd6b39db4be4e48L, + 0x048f3b4b5714efL, 0x68b49685d9e4b8L, 0xbda8e6c2177963L, + 0x5094e35c4211feL, 0xea591c32d46d1aL } + }, + { + { 0x3a768ff2fef780L, 0x4218d2832970c6L, 0xce598e4ec6da17L, + 0xf675645fbb126aL, 0xb04c23f0427617L, 0xc9f93fbe4fce74L, + 0x44a414b3c91b00L, 0x4d982f31d3b3ccL }, + { 0xb1d40e8b24cce0L, 0x5a21c07133e73dL, 0x6e9358e0bb589dL, + 0x39cfb172399844L, 0x83f7647166080eL, 0xcfe7bf8450b468L, + 0x2a288f71e8434fL, 0xd39f1e521a81e3L } + }, +}, +{ + { + { 0x78c6f13528af6fL, 0x0001fe294b74d9L, 0xae7742501aab44L, + 0x7cbe937ef0039cL, 0xaf3e4f00fa2a67L, 0xe28175fda1378eL, + 0x72adeed8ccd90eL, 0x16a8ce100af22fL }, + { 0x69fae17cbf63ddL, 0x67861729e39e26L, 0xe92b3d5f827a18L, + 0x4d75e418403682L, 0x01a4fd99056a79L, 0x89efb2d20008f5L, + 0xa2f6918b78ff15L, 0xf41c870a3437f5L } + }, + { + { 0xc840ae57be353cL, 0x465a5eb3fb2691L, 0x34a89f07eba833L, + 0xf620896013346eL, 0x563b5f0e875df2L, 0x5f7fc8bfbc44ceL, + 0x22fcb5acfedf9dL, 0x7cf68d47dc691bL }, + { 0x37f7c2d76a103fL, 0x728a128fd87b7dL, 0x7db2ad8ccf2132L, + 0xa4c13feb100e63L, 0xcd28a517b511d5L, 0xb910280721ca5cL, + 0xec1305fd84bd52L, 0xb9646422729791L } + }, + { + { 0x83fccdf5bc7462L, 0x01f3ddad6f012fL, 0x57f11713a6a87cL, + 0xedb47ceff403acL, 0x6c184e5baab073L, 0x5b17c7d6f0d6a1L, + 0x45a4c4f3ef2c91L, 0x26c3f7e86a8f41L }, + { 0x81a6db0b646514L, 0xf84059fca8b9aeL, 0xd73dab69f02305L, + 0x0de3faec4b7c6cL, 0x18abb88696df2fL, 0x45dd1b975d7740L, + 0x3aeccc69ee35bcL, 0x478252eb029f88L } + }, + { + { 0x66bf85b8b2ce15L, 0x1175425335709dL, 0x00169ef8123874L, + 0xfd3c18c9b89868L, 0xb3612f9775204eL, 0x4b8d09dc2cd510L, + 0xafa12e614559adL, 0x1ddaa889657493L }, + { 0x87d700b1e77a08L, 0xaf4cf2f14d2e71L, 0xe00835dbf90c94L, + 0xb16a6ec6dc8429L, 0x02a7210f8a4d92L, 0x5a5ab403d0c48dL, + 0x0052b3ab5b9beaL, 0x6242739e138f89L } + }, + { + { 0x7c215d316b2819L, 0xdacb65efeb9d7aL, 0xc3c569ed833423L, + 0xbc08435886a058L, 0x132c4db7e5cb61L, 0x6373a279422affL, + 0x43b9d7efca9fc4L, 0xe3319a5dbe465fL }, + { 0x51d36870b39da7L, 0xcb6d7984b75492L, 0x77eb272eadd87aL, + 0xf2fb47de0d3f6cL, 0x807fd86f9f791cL, 0xf01086b975e885L, + 0xf9314b5b6a3604L, 0x8cd453867be852L } + }, + { + { 0x7c1e6b3858f79bL, 0xf0477c4938caf9L, 0xb311bbf3e88c44L, + 0x9234c091e3a3c1L, 0x531af2b95a1d4dL, 0xf3cc969b8d1c64L, + 0x6f3c328b51e78dL, 0x5a1bd6c34e8881L }, + { 0x2e312393a9336fL, 0x020f0cc5ced897L, 0x4b45d7b5fab121L, + 0x8068b1c1841210L, 0x1bd85fc8349170L, 0xfe816d80f97fe5L, + 0x108981814b84fcL, 0x1d4fabbb93cd48L } + }, + { + { 0x1f11d45aef599eL, 0x8d91243b09c58aL, 0xd2eec7bd08c3c3L, + 0x5a6039b3b02793L, 0xb27fed58fb2c00L, 0xb5de44de8acf5eL, + 0x2c3e0cd6e6c698L, 0x2f96ed4777180dL }, + { 0x67de8bf96d0e36L, 0xd36a2b6c9b6d65L, 0x8df5d37637d59cL, + 0x951899fc8d9878L, 0x0fa090db13fcf8L, 0xa5270811f5c7b4L, + 0x56a6560513a37aL, 0xc6f553014dc1feL } + }, + { + { 0x7f6def794945d6L, 0x2f52fe38cc8832L, 0x0228ad9a812ff5L, + 0xcd282e5bb8478aL, 0xa0bc9afbe91b07L, 0x0360cdc11165e2L, + 0xb5240fd7b857e4L, 0x67f1665fa36b08L }, + { 0x84ce588ad2c93fL, 0x94db722e8ff4c0L, 0xad2edbb489c8a3L, + 0x6b2d5b87e5f278L, 0x0265e58d1d0798L, 0xd2c9f264c5589eL, + 0xde81f094e4074dL, 0xc539595303089fL } + }, +}, +{ + { + { 0x183492f83e882cL, 0x4d58203b5e6c12L, 0x1ac96c3efec20bL, + 0xabd5a5be1cd15eL, 0x7e1e242cbbb14bL, 0x9f03f45d0543b3L, + 0xc94bc47d678158L, 0x7917be0a446cadL }, + { 0x53f2be29b37394L, 0x0cb0a6c064cc76L, 0x3a857bcfba3da3L, + 0xac86bc580fcb49L, 0x9d5336e30ab146L, 0xafb093d5bc1270L, + 0x996689de5c3b6eL, 0x55189faea076baL } + }, + { + { 0x99ef986646ce03L, 0xa155f8130e6100L, 0x75bef1729b6b07L, + 0xc46f08e1de077bL, 0xf52fdc57ed0526L, 0xe09d98961a299aL, + 0x95273297b8e93aL, 0x11255b50acd185L }, + { 0x57919db4a6acddL, 0x708a5784451d74L, 0x5b0bd01283f7b3L, + 0xe82f40cc3d9260L, 0x2ab96ec82bbdc2L, 0x921f680c164d87L, + 0xf0f7883c17a6a9L, 0xc366478382a001L } + }, + { + { 0x5c9aa072e40791L, 0xf0b72d6a0776bfL, 0x445f9b2eaa50dcL, + 0xa929fa96bda47fL, 0x539dc713bbfc49L, 0x4f16dd0006a78bL, + 0x331ba3deef39c7L, 0xbfa0a24c34157cL }, + { 0x0220beb6a3b482L, 0x3164d4d6c43885L, 0xa03bb5dacdea23L, + 0xd6b8b5a9d8f450L, 0xd218e65bd208feL, 0x43948ed35c476fL, + 0x29a0dd80a2ed2bL, 0xa6ccf3325295b7L } + }, + { + { 0xf68f15fac38939L, 0xb3dd5a2f8010c1L, 0xf7ac290a35f141L, + 0xdc8f3b27388574L, 0x7ec3de1e95fed2L, 0xc625451257ac7dL, + 0x66fc33e664e55aL, 0xd3968d34832ba5L }, + { 0x980291bc026448L, 0xfcb212524da4a5L, 0xbca7df4827a360L, + 0xfcc395c85ca63bL, 0xcf566ec8e9f733L, 0x835ee9bd465f70L, + 0xe66d111372f916L, 0xc066cf904d9211L } + }, + { + { 0xb9763a38b48818L, 0xa6d23cc4288f96L, 0xe27fcf5ed3a229L, + 0x6aebf9cabaff00L, 0xf3375038131cd1L, 0x13ad41dffabd58L, + 0x1bee6af861c83bL, 0x274fe969c142e7L }, + { 0x70ebcc99b84b5bL, 0xe1a57d78191cfcL, 0x46ccd06cbf00b8L, + 0xc233e8eefe402dL, 0xb4ab215beebeb3L, 0xb7424eabd14e7bL, + 0x351259aa679578L, 0x6d6d01e471d684L } + }, + { + { 0x755c465815ae38L, 0xadc3e85611db56L, 0x633999b188dd50L, + 0xfdf7509c12d907L, 0x25bcfde238b6afL, 0x50d705d397f5e7L, + 0xb65f60b944c974L, 0x8867fc327ac325L }, + { 0x2edc4413763effL, 0x892c0b3341fb63L, 0xb34b83ab3a7f28L, + 0x9aa106d15c2f18L, 0x720bbc61bb2277L, 0x637f72a5cfaefdL, + 0xf57db6ef43e565L, 0xceb7c67b58e772L } + }, + { + { 0x2793da56ecc1deL, 0x4e1097438f31b2L, 0x4229b4f8781267L, + 0xe5d2272dec04a1L, 0x6abb463ec17cffL, 0x28aaa7e0cbb048L, + 0x41dc081d22ef85L, 0xcbc361e5e63d0fL }, + { 0xb78aafcad5dbaaL, 0x0111505fc1edc3L, 0x63ed66d92c7bfaL, + 0x2982284e468919L, 0x30f1f21b8c0d8cL, 0xf0567472685093L, + 0x0e085b6f03dd0fL, 0xa8c8db85581e66L } + }, + { + { 0x42009a6264ad0cL, 0x13bf2b8593bef4L, 0x1d111905d4e8b1L, + 0xfe3e940ef7bddcL, 0xa012275624e62cL, 0xcb659241d6d3ccL, + 0xc7bcc70edb7ab6L, 0xff9fafbb750b1cL }, + { 0xf65df297fea84bL, 0x17c84a890b0e02L, 0xa92a859301e821L, + 0xbee8cb2fb480d1L, 0x7010b8c59c604eL, 0x47bf3f4e803c43L, + 0xd64514247b3fffL, 0xc4c5dcb9f0da13L } + }, +}, +{ + { + { 0x8af700cb5253b3L, 0x31ca605206957aL, 0x25744393eafdcdL, + 0x2ba5ae1d3ae15eL, 0x710b7385b82579L, 0x145ab57112b95aL, + 0x4b133a038c55c5L, 0xf7559c92a16fefL }, + { 0x70c3e68d9ba896L, 0x475dd32c33d07aL, 0xe084e473a41e40L, + 0xddc9382fd2e706L, 0x34b727579510bdL, 0x5e78a69a5f901eL, + 0x429dfd7dcfb823L, 0x1d9dc18014f0a3L } + }, + { + { 0x364fcdfaf403d7L, 0xd9ea4ffb7d7b34L, 0x21a3426cbb1dacL, + 0xfa51052143b4f5L, 0x2bca0736df2409L, 0x7e6985a8ad7285L, + 0x3a1a9d04aaa27fL, 0x1a815e19fc0c6cL }, + { 0xfab6147bb65bb3L, 0xa36dc0d33ced0bL, 0x26a88592062d78L, + 0x343861728a5fb7L, 0xe82da254ebb1adL, 0x70f5071d05aa11L, + 0x0b7f847adaac48L, 0xeb812bc93cb269L } + }, + { + { 0xcb317ccf7cacccL, 0xd3410d9cf85098L, 0xca68c8d7f078d7L, + 0xfe9e812b782efcL, 0x32e7c0f5f544b5L, 0x44fe95a3a7b7f2L, + 0xf4f1543e91327bL, 0x27d118d76645edL }, + { 0x690547cd7abc2cL, 0xf64680fb53c8afL, 0xbe0cbe079ea989L, + 0x6cf0ccea91af28L, 0xa3b85a29daa2f9L, 0xd4b663c91faed0L, + 0x782c7b7a8b20baL, 0xf494fafb8d98ceL } + }, + { + { 0x080c0d7002f55aL, 0xf4f8f142d6d9ddL, 0xb326229382f025L, + 0x58fd0b5ad28c20L, 0x704b9928d06a15L, 0xf4545d97fbd8e4L, + 0xc32fa63ed55581L, 0x3ab793601ac0fdL }, + { 0x13ece526099fd1L, 0x776dba89c79178L, 0x8d28212ce26c45L, + 0x09fddaf60d739cL, 0xf9931eda84826eL, 0x6e73d90b29439eL, + 0x94cfefc9095e61L, 0x3050d16802f474L } + }, + { + { 0x0898f8f9f6394bL, 0x48b8cea88b0e91L, 0x4bc99254c1b362L, + 0xe3fccb4827d9ecL, 0x5d4cf9ad950d6aL, 0xa16f1ef39b5b38L, + 0x3c76d1d620f288L, 0x9fdd059e119390L }, + { 0x7b5de9efb5edf8L, 0x3e290b9769d14eL, 0x4df3a916bd10b5L, + 0xae99bca82f8f7bL, 0x5481d5dc9524afL, 0xf112e4f69504f1L, + 0xb048f0951931ecL, 0xbff876a18f51b1L } + }, + { + { 0x932e2a746c1c37L, 0x903ad529aea4c1L, 0x717ac918f161f2L, + 0xa57d197f425e2aL, 0xae89dac7f39e0eL, 0x91655c0baa2a58L, + 0xe3dc28654836ddL, 0xb5f0baaa9ec9e6L }, + { 0xf7c4662bdbda04L, 0xbe5393b51059c0L, 0xb16d552dd95b0fL, + 0xde495b31b3bd96L, 0xb2a6e02c0206c5L, 0x045cc09014d3a9L, + 0xf66a3152a2f490L, 0x208c108c5dea05L } + }, + { + { 0x6e38b6865237eaL, 0x93a13039f27fc6L, 0x9a6d510a95068aL, + 0x6fbf216e7c9e54L, 0x7824290571ac1dL, 0x8cb23ba91c2a0cL, + 0x611202ec7e434dL, 0x8f901bf76058b4L }, + { 0xef0ac050849588L, 0xe0d2ddedd31804L, 0xaf5417ceb2ca81L, + 0x420ac065d1a509L, 0x46e345e9683bb6L, 0x6daf635f613f7fL, + 0xc9e829148a9576L, 0x5f9f1d1176d147L } + }, + { + { 0xd24ae1d77e9709L, 0x77751dc0047b8aL, 0xe325334c6a1593L, + 0x9baf962671f86aL, 0x425af6ac29a15eL, 0x31086002796e33L, + 0xb6ea78cfc253a5L, 0x4c733e0afae0eaL }, + { 0x4b7443a97c99b9L, 0xc14e9e450203a6L, 0xd1bb51552680baL, + 0xa56a3efd55533aL, 0xa66e38c169e1a0L, 0xb3e4df9eed7da0L, + 0x022c937ddce3d9L, 0x8552089f6e36b4L } + }, +}, +{ + { + { 0x8e4bf95f5cc82eL, 0x2ad80c3c3ed6c9L, 0xf2e5b2cc9045e1L, + 0x42c906559b06d4L, 0xc1f73797b43b84L, 0x1710dbf72d7992L, + 0xe98cf47767b41cL, 0xe713fce7bfb9e9L }, + { 0x9f54ae99fa5134L, 0x3002fd8de40d0eL, 0xdc282b79311334L, + 0x5519810bfeb360L, 0x31539c70f96ffeL, 0x04eacc0d27777bL, + 0x59824108ff5053L, 0x598236632b67adL } + }, + { + { 0x6eb45546bea5c2L, 0x82cfae0d509a33L, 0x6a69bd8394bb59L, + 0x1880d8d5770ee1L, 0x63518447dacf9eL, 0x5b1ecc5f02b891L, + 0xeb7d900b6c9a5aL, 0xdab8a768897da8L }, + { 0x28c7be598851a6L, 0x0101d4f4d73c3bL, 0x3c2569c5084996L, + 0xb9bc911280bde0L, 0x513a22acd0d4f9L, 0xdf2986d2a15f3bL, + 0x231c28f2aa4943L, 0x29623ad0333870L } + }, + { + { 0x2ceb1784084416L, 0x924cf1c49516cdL, 0x76536c04be856fL, + 0x11b59cd47a265bL, 0x720dc844999494L, 0x910f794007b795L, + 0x8434e142d3df83L, 0x8f53878bd478d3L }, + { 0xd9b072eaeb9c2fL, 0x16f87eafd8a29fL, 0x8c42f9b2fd0de1L, + 0x916721e0e816efL, 0x2ecb47018bde37L, 0xcde3b7a2375da2L, + 0x30d0657ef94281L, 0x51054565cd7af8L } + }, + { + { 0x7230b334bdced3L, 0x0c6a3e10838569L, 0xf19c9ece3493b8L, + 0xf2759270d97c57L, 0xf14181e0c862ebL, 0xfd3bac132c72bcL, + 0x620563ff3be362L, 0x672ccaf47283b7L }, + { 0x191e3fa2b7bf16L, 0xf838633520dad7L, 0xd3dde553629d87L, + 0x14d8836af86ebeL, 0x3db7dfb221b2ceL, 0x3872abb0aed72aL, + 0xb60de528c665b7L, 0x89c259644982cbL } + }, + { + { 0x799a2de4dbba25L, 0xd818aaea42715eL, 0xbc88f4df55c362L, + 0x142a163713c9aeL, 0x411e8eefbfb33fL, 0x34b46296bb684aL, + 0x4344becdc81817L, 0xcc9573d17f9d46L }, + { 0xf85f8bcff38a7dL, 0xa14bf730caf117L, 0x126874f4ba6429L, + 0xcc9bf22aa5db97L, 0x62b56df6aba827L, 0xfee1cb89c9772aL, + 0xe36838f177e541L, 0x698815dadd438fL } + }, + { + { 0xc9fd89438ed1adL, 0x73cd79d7b6a601L, 0x2210e6205e8d20L, + 0x72384ac3592af5L, 0x5ccc079763d07eL, 0x2f31a4aa5f79ebL, + 0x693f4ed2945a95L, 0xc7120178056fdcL }, + { 0x361ecd2df4b09aL, 0xa5644eab7d929aL, 0x34abc0b3fabe9aL, + 0x1a2473ce942a8cL, 0xe00c9246454bc3L, 0xab324bcdff7366L, + 0xe1412f121b8f99L, 0x970b572e33551eL } + }, + { + { 0x6ca4cacbd0a6b5L, 0x5584787921d654L, 0x18e5253c809bdaL, + 0x01b32c3f0cbe5eL, 0xb9aa7540f987ddL, 0x628f4bb6dfa4dbL, + 0x0255f0b891890bL, 0x25b7df4874e590L }, + { 0xbded3188ed5f95L, 0x9dc428dca93023L, 0xc68f25abccf520L, + 0xc4f3764e616e6cL, 0xd9a57f1a1d9993L, 0xd1964a5533431bL, + 0x06cd77f02ab6d0L, 0xa66079103e52e0L } + }, + { + { 0xab088645f72700L, 0xf77b2ff0a1a44eL, 0x43ebdd8c2a24b5L, + 0xa6d67114f564d7L, 0x495df63f414160L, 0xf5bacd776f6de6L, + 0x3011aff7c2b43dL, 0xbb1e64c3241928L }, + { 0xf70c5725034073L, 0x891c62a68f1e97L, 0xed8eb2eb22e374L, + 0xd3a53e97dbcc2fL, 0x1d06281dc8f220L, 0x9eef48face4393L, + 0x96014f5d2abecdL, 0x1da7e092653cebL } + }, +}, +{ + { + { 0x7593318d00bc94L, 0x586f3c6c7262a2L, 0xea68f52958ad31L, + 0x6707fccd4e8bedL, 0xb7e35d6cb3f9ceL, 0x2cbb6f7f4b1be8L, + 0xa5352687b41aeeL, 0x1d77845f7b39b8L }, + { 0xb1f3995eaf9554L, 0x3250f70fe9e7d4L, 0x62e5d1ba00c23cL, + 0x5e422f5c10e3bfL, 0x7a18039c25cec4L, 0xb4e66a17cc4d5bL, + 0xad7c5f636d0e0cL, 0x9f40b12a4cf347L } + }, + { + { 0x697f88251e3696L, 0xc89bc40ab0a648L, 0x8f261a59785804L, + 0x4c7f900b51a2bdL, 0xd00e7af8a2dfcfL, 0xf9c534db642aebL, + 0xea2a79fb63df0eL, 0x392a69af2f64a4L }, + { 0x0c0f01cc331b6cL, 0x414bf2e6a5edb5L, 0xfe5ed815068391L, + 0x0a8078d62fbc34L, 0x78a438254bca98L, 0xf7a49ae3d727c7L, + 0x96c1de1ab4dffeL, 0x45901f73b9440aL } + }, + { + { 0x3f1189facfe46eL, 0xdca6f464467443L, 0xac385422eb5bcfL, + 0xb02dce9906bf72L, 0xdd8cdacfe1d454L, 0xc26f04c65f7218L, + 0xb4748596ea145dL, 0xc53dc6b5bdb315L }, + { 0xbe5be749ad7197L, 0x627e91918b5eccL, 0x57c889c9ea405dL, + 0x2e5650c1a5360bL, 0x42290df1b30b27L, 0x4a071575242687L, + 0x553ed1fd379133L, 0xb9d7a0701db019L } + }, + { + { 0xcfe551c56597dcL, 0x81af92a925ebd6L, 0x83efe16f4e8d57L, + 0x61bb4311f640d3L, 0xf80440f78b414aL, 0x72f3c636c9e3b4L, + 0xb55f43a6a03c66L, 0x47a9dede417037L }, + { 0x1a7e287dbb612bL, 0x895c3c7dbb9220L, 0xd50c86e6c04764L, + 0xed5269853cf7caL, 0xc78d799f74af55L, 0xb2ba0f2b969ff2L, + 0x06d48151c6530bL, 0x764a1fe165a575L } + }, + { + { 0x4383a3bc1b5eceL, 0x0563c8854ff148L, 0x9a452795af796eL, + 0xffba7c088e9953L, 0xfe9fb5eb6a3001L, 0x795098825b6b19L, + 0x67c899ad81be5eL, 0xc89ac8d2f9d29bL }, + { 0x7c76ba329ab8f7L, 0xb2a18c96e40f74L, 0x1b5056e3864d9bL, + 0xdfa503d9b582b8L, 0xfb035197c9c68eL, 0xdc501316b3c22bL, + 0x38ab231a6c96ffL, 0x4ea527c8cb1c10L } + }, + { + { 0xd632f20c05b4edL, 0xe0199fab2a032dL, 0x373295626812d7L, + 0x2aed855013df13L, 0x92ca24b39f96acL, 0x620273dbb9751aL, + 0x5d0d21ef7437a1L, 0x9de2a43077de56L }, + { 0x0569b1211a4674L, 0xfc3923e89c3989L, 0x3d127042c5c770L, + 0x0072b9084e8c37L, 0x7178d4dac39f9aL, 0x5f8292f778d345L, + 0x9e5bf0f77c7307L, 0x7691610c3a20f5L } + }, + { + { 0x7c4ead5705fe96L, 0x377ec35c8e464cL, 0x3e5b9907689954L, + 0xc0f6949a2d31eaL, 0x839d395c580671L, 0x2f347a6b215b09L, + 0xfdcfa33683df83L, 0x6e12cc26af39a8L }, + { 0xae46ec813a3bd2L, 0x03a7d3b59366f8L, 0xe2029d5b87aed4L, + 0xbdc4e43fe1b83dL, 0x768437cdb8a1a8L, 0xe47acc3ea0dd7fL, + 0x550e0cc62a0af4L, 0xcaf2cbc1a20962L } + }, + { + { 0x5a784f7f28a78fL, 0x952a9b507e9724L, 0x8ac5e411bab7a3L, + 0x1251e3fb7bc1e1L, 0xe360f82dc15e22L, 0x3ac72da95213f5L, + 0x65ee9ba4dcd47bL, 0xdfeab7b3af5952L }, + { 0x34c5c8026fd3c6L, 0xd977b08f3ac7eeL, 0x003bd017dba2f6L, + 0xcfc5cf8ac98c8dL, 0x05eb6040e46922L, 0xc248b17faa9352L, + 0xfa41c0f395c7a7L, 0x29931d4b71ee44L } + }, +}, +{ + { + { 0xac087bb07861c5L, 0x3bd37db5ae8240L, 0x94c68ecf94518fL, + 0xd32a378ff88a5bL, 0x42c8aaf9b441d1L, 0x089db70fc07f12L, + 0x211c386d3d4455L, 0x1db9af7546b158L }, + { 0xdfd1b6551bc927L, 0x69c04930733df4L, 0xdc72cd42aeb586L, + 0xeebdace823aa13L, 0x51b3b3c56ad643L, 0xb983a99d4e0426L, + 0xa1e5b6c69c4eccL, 0x37cd38245e6668L } + }, + { + { 0x158ce6d9f73aeaL, 0x36a774914ff475L, 0x0d4e424dc0b018L, + 0xc2c44483946f09L, 0x7a7de3ffacda62L, 0x49a19e6b486709L, + 0x65094d8db61da7L, 0x09edfd98f5ee87L }, + { 0xe460fcfb37226dL, 0x3b9d03969bf470L, 0x3d4d511247ca22L, + 0xc7248d6c782cb1L, 0x91189a000ad293L, 0x1244942e8abe75L, + 0x9f88d12bf52cdbL, 0x368463ebbbcadfL } + }, + { + { 0x419e4b38074f45L, 0xd3f8e2e0771c83L, 0xd2743b42e68d34L, + 0xc68b7dbb116a00L, 0xfad2cf7d84cc37L, 0xcfd27c0b7a0f4dL, + 0x3b9e23f190e587L, 0x7bab499751ca9eL }, + { 0x3270861a8f12eeL, 0xee1f38d31b36d5L, 0x748bb31e4c0eedL, + 0x9be5c9b110ebadL, 0x728660bc8b6cb6L, 0x7bc9df793d914aL, + 0x73a4f2cc88c859L, 0xbe4a2fdb4e7f0eL } + }, + { + { 0xe566ff8a450e77L, 0xb0b40066a13abaL, 0x483a510cd7dc90L, + 0xb1a20135fa9cccL, 0xeb0b631a80e67cL, 0x7c34e1f020801aL, + 0x0257dc8f4e447cL, 0x7abe7d174c6f0fL }, + { 0xf115a3ab19a576L, 0x8f0474a064ca0eL, 0x999bb6b351f99bL, + 0x855254b773edc3L, 0x49f6c2f427d717L, 0x9f682532e0cef2L, + 0x1fe126c2ee34f5L, 0x1ec2cae80150f7L } + }, + { + { 0x862c5afc005b7aL, 0x61adea7ec4ef17L, 0xf885fd3007b446L, + 0x25c129d9b0e30eL, 0xbc10f25feec7e0L, 0x3901ac4df79ee1L, + 0xad49db7fe9e19fL, 0xc8624d9360d050L }, + { 0xc74a576bf3260bL, 0xbde80248c010c2L, 0xf15532909b6977L, + 0x6a5a82ed52dcf8L, 0x4fbf59d29b9dfcL, 0x337d049c7b730cL, + 0xb3deac63a89cd4L, 0x1e07595ad2f2ebL } + }, + { + { 0xa0b0a4d3b7c84eL, 0xf132c378cf2b00L, 0x192814beaaa8ecL, + 0xe7929f97b4b5dfL, 0xf08a68e42d0ab7L, 0x814afb17b60cddL, + 0x78c348c7d9c160L, 0xf8a948844db217L }, + { 0xcdefd88eaa2578L, 0xf717f56bd0e260L, 0x7754e131694d02L, + 0x1254c14181dbd8L, 0x0dacdd26e5f312L, 0xb8abdfbcef87bfL, + 0xb985972e74e2eaL, 0x1717621002b424L } + }, + { + { 0x92cc75e162df70L, 0x1e20c0618ee849L, 0xc036b4626aa590L, + 0x31be67e4da5155L, 0x04911b5f7213b0L, 0x39261d7bb2e72eL, + 0x9e844665c015a3L, 0x2f59fc0298ae67L }, + { 0xa3ea7ba1701fccL, 0x87a5fa90ebd651L, 0xa607ed4301d7b1L, + 0xbd4ec5f3b2e271L, 0x732a1a2dc4180fL, 0xbe15d82feaa8c1L, + 0x103670266f2f3fL, 0xccfd3979e79ce8L } + }, + { + { 0x82ab83570a54adL, 0x5c1dee8e3bec75L, 0xf583ff454b556bL, + 0x9220199f461e60L, 0xdf61ca887fc4e7L, 0x6641fd20776dadL, + 0x00c6edd8edd061L, 0xaf9b14255f7e87L }, + { 0x73f15e49bbe3ecL, 0xdd3b788f8bc1faL, 0xb24cc071b8ff86L, + 0x6c260d241be58bL, 0xec1c4e36b10adaL, 0xf6b42097fdb985L, + 0x0d0ac85d47c212L, 0x967191c07d78d1L } + }, +}, +{ + { + { 0x3b11638843d0f3L, 0x4b89297f27f10eL, 0x477236e863ba2aL, + 0x1949622add280cL, 0x7cd523504da757L, 0xe0e99d279e4ff7L, + 0xb4ef894537da41L, 0xc55dde45a24ff1L }, + { 0x18d8e21b587521L, 0x8010b5d3777833L, 0x4af522dd3a54c8L, + 0x7cd476b4c0ac13L, 0x4587e614099f67L, 0x494d0ed605ee64L, + 0x3218ba2cc80903L, 0x5ff56aa0b2e169L } + }, + { + { 0x51ec94e3a06c69L, 0xa26d7be5e65c52L, 0x156f113d44ee96L, + 0x70f0968bf5b9b4L, 0x9b7e4695f5332dL, 0x36c295f6703829L, + 0x1522690d04f492L, 0xcf35ca4728043bL }, + { 0xf9ca3e1190a7c3L, 0x53d2413f971b07L, 0xae596529c48b49L, + 0x74672b8fefff5cL, 0x0a3018ba7643b0L, 0x51919e83e9b0a8L, + 0x89ad33dc932fb5L, 0x52a4419643e687L } + }, + { + { 0x7778990d2d0acdL, 0x3bdbcce487fdf1L, 0xdc413ca2b03dd2L, + 0x278755b9a2b7d0L, 0x4ebb8b535ddd7fL, 0x0465152bcbdb92L, + 0x34f22d6671d051L, 0x1ba04c787192b9L }, + { 0xb1693f483560c1L, 0xe08a5937d174e9L, 0x47ffdc464dc9afL, + 0x1123596ce8126cL, 0x632d95f1124628L, 0x66287abfee7c76L, + 0xb40fe60c552332L, 0x3f11729e304e1eL } + }, + { + { 0x97a6ea05030a8cL, 0x692419809c27b2L, 0x3308501ac9dd5dL, + 0x9fed7fabe73fdcL, 0xea555440535286L, 0xc7c07ab6c9b832L, + 0x178c882c51b967L, 0x6fa0c6986ee075L }, + { 0xbaa4a15b8b5c4aL, 0xf83c0ea3130c0aL, 0xcf8624b2800331L, + 0xade85cd7ccbcb8L, 0x971d7f6f08445dL, 0xfd480b76a546dcL, + 0xdc15a38c93761cL, 0xc4c495c9d04631L } + }, + { + { 0x5f4cee89470efeL, 0x9fe896188d93adL, 0x24783b3f4e49ceL, + 0x1bc7ed752ffb3eL, 0xa3abe6a6d81e17L, 0xd6bb8b47a333c3L, + 0x3485c0b10a3527L, 0x7cddc9c31a9d10L }, + { 0x0c78112c38ca37L, 0x10e249ddd2f8d8L, 0x72c88ccc511911L, + 0x4d75b5a29a6c84L, 0xc74b267a227b1eL, 0x698390cf8e35adL, + 0x8f27edfe98d230L, 0xec922f26bdc7f4L } + }, + { + { 0xac34023fc32e11L, 0xe0ae2f547200d1L, 0xa7c7492bd98c82L, + 0x3910b687b02154L, 0x6fdd06ce28ab6dL, 0xd3a7e49d98b012L, + 0x4c1c82b9f54207L, 0xef5bbe645c176fL }, + { 0x3d17960d3e71ebL, 0x90d7e84080e70cL, 0x83e6438bff5d9eL, + 0x1877e1f535d85cL, 0x931ed6efbb69ccL, 0xcf962651247848L, + 0x76d618b750da4eL, 0xc076708717fbf6L } + }, + { + { 0x80a5ac5eec5126L, 0x6d05dd13379c80L, 0x514b0892336d32L, + 0x586c0066725137L, 0xab2365a574f954L, 0x3c89ea0ac7d356L, + 0xf1f2edd27460baL, 0xf200ddbab9870fL }, + { 0xc8f1b2ca35e885L, 0x5d22f86e6e7550L, 0x24b9a409554615L, + 0xcb41107616314fL, 0xca752f0c976a11L, 0x3e2f839a08291aL, + 0x0cff22ff2c420eL, 0xafd603e82b9747L } + }, + { + { 0xaddeddc810a3daL, 0x78b6c2dd3a87bfL, 0xbc7020bde3a04cL, + 0x47ab9739b6d045L, 0x3b046d60959358L, 0x0f953e7509ee3eL, + 0x803dc8669fc61bL, 0xcceaec0893c8d4L }, + { 0x21f8c40b048a45L, 0xb535073fcaea8aL, 0xe712c3590e360bL, + 0x5d0f3f48403338L, 0xe0ea26c7207f2dL, 0x20f6b57ffd9e05L, + 0xb97d68e4788b00L, 0xb1215541889cceL } + }, +}, +{ + { + { 0x0079817464238eL, 0x21103020d381caL, 0x1cc4c6ed9f01b5L, + 0x5e35dc55a131b1L, 0xb61848d06944ebL, 0x83792a029631a3L, + 0xbe1017fafca0ddL, 0x70aaa01782fcbbL }, + { 0xc63b7a099945e7L, 0xe9164ecc4486c1L, 0xb133e35885f2c1L, + 0x186f0d3c99ae02L, 0x2fca4922bf53e6L, 0xf922aa248a02bcL, + 0x4fe64900dd3dcaL, 0xe8c313ff6a8207L } + }, + { + { 0xc5b358397caf1eL, 0xa001922922a4b6L, 0x67e36bedf07c95L, + 0xabaa0aeb2f4f34L, 0x66dc926dedc333L, 0x82021c438ec5b3L, + 0x82b4f2600ab176L, 0x1b7c22e69c45afL }, + { 0x07b0dbe0924ad9L, 0xe030936a407ddeL, 0x66e1ce926ccd06L, + 0xb50c108e3505a9L, 0x8b921e1da98f51L, 0x449ca1a20cf7c7L, + 0xadb80c7e67d079L, 0x205aa54834372dL } + }, + { + { 0x1482b4819bf847L, 0xd6c16ab5906f0fL, 0x323fb1723ad060L, + 0x0346389c832be7L, 0xe71b2d82ee45bfL, 0x761c37dfb22276L, + 0xa9b33345d70be2L, 0x81a06565a0627aL }, + { 0x337750399a6282L, 0xafc8d2ed0436f0L, 0x22f71d3c53342fL, + 0x66ca56d8939ad3L, 0x15a919230e09baL, 0x261091ea6de890L, + 0x609d700e78f2d5L, 0x8aa52ee8eaaf78L } + }, + { + { 0xa398788ce76258L, 0x3031d07494b975L, 0x4a6d652043dfe2L, + 0xdb1a849b4401ecL, 0xf81ebbbce8bbccL, 0x937dd4716efe9eL, + 0x9c19350ef85eccL, 0x260d932214273bL }, + { 0x1d7e21e77bf1a3L, 0x199d689a544eb7L, 0x9da594194ced50L, + 0x71a60be8a0aeaaL, 0x183a0ae26d3b51L, 0x49f176a8df9728L, + 0x744376e3230674L, 0xb2cb21ae25541cL } + }, + { + { 0x7a721589a0071fL, 0xe19dd29e7d2a6bL, 0x3deb34e55113f0L, + 0xef1f8ebede573bL, 0xa8f7ff95665e37L, 0xa2c21eaf2d7777L, + 0x1387afa91e2e39L, 0x04057b97db68f6L }, + { 0x8b9d5ae1c241f7L, 0x689588a8e75993L, 0x79585b45c0e2d4L, + 0xba1ef167b64974L, 0x72685bc1c08a75L, 0xf0a5814d572eddL, + 0x71464a35ab0e70L, 0xc93c92b339aea7L } + }, + { + { 0x1917e2a5b8a87dL, 0xea5db763a82756L, 0x5bba2fb6420e2bL, + 0x5cc0501019372aL, 0xb1ef8beccc5efdL, 0xaf06393f49c57dL, + 0x3ab1adf87a0bc4L, 0x2ee4cca34fe6b6L }, + { 0xd1606686b8ba9bL, 0xef137d97efec13L, 0x7b6046550abb76L, + 0xb40ec2bf753a00L, 0x696ed22eaf8f1dL, 0x398c91fd8ba3d8L, + 0x11f203437db313L, 0xe1ec33bfe5079eL } + }, + { + { 0x8a10c00bdc81f0L, 0x5f392566fe8e05L, 0xa595dab14a368eL, + 0x32b318138cec6bL, 0xd77afde1b00d00L, 0x3c979284d9923dL, + 0x78f0e7a76e13ddL, 0x5ee8e59bf75675L }, + { 0x49ec89391b130cL, 0x9416182a47a441L, 0x54555b576e2ce8L, + 0xcbdd2fd349c40bL, 0x10ae7379392bbeL, 0x270b1112e2dab0L, + 0x5cb7712af293f4L, 0xfc22a33d6095c6L } + }, + { + { 0xdcb5bbd0f15878L, 0xbcf27adb6bba48L, 0x979913e7b70ebaL, + 0x4c0f34b158578aL, 0x53f59a76ed6088L, 0x19b3b2c75b0fc2L, + 0xad628dc0153f3cL, 0x5195a2bcec1607L }, + { 0x95f8b84dfe0f7aL, 0x935c6b0152920bL, 0x25f9e314da1056L, + 0x4910a94b28c229L, 0x54b03b48ee4d6eL, 0xc991fc3694e3edL, + 0x68c4c26dbe5709L, 0xc9cfce463d7657L } + }, +}, +{ + { + { 0x21c9227f52a44eL, 0x7f105a2e85bfbdL, 0x887781f6268fc2L, + 0x56ee808a2d7e35L, 0x14f9de52d3930fL, 0x4a4e356dcb561aL, + 0x87362267f95598L, 0x211c3425f34151L }, + { 0x8fcb75b0eaf9cbL, 0xcc9edf93d60ce2L, 0x54412c9a5fe627L, + 0x6036a72842dd09L, 0x71ce668a6c6099L, 0x02b30d75386764L, + 0xb69bed36f18e23L, 0x124c9b1d1de9f4L } + }, + { + { 0xe8f8d95e69b531L, 0xe1e115eaff1049L, 0x9087cd1eddea0cL, + 0x8ed55a57449916L, 0x8009f547808404L, 0x990f21617fea55L, + 0x68ba624fe8ecf9L, 0x8ac295056d1f47L }, + { 0x3257887529dfb0L, 0xc4a613f244c080L, 0xabb1ac028672faL, + 0xb2915c531eb291L, 0x6e368ca8fababaL, 0x6b8c2591fde498L, + 0x67724a1f2a548cL, 0x6b3b7e8f90409bL } + }, + { + { 0x5415003fae20aaL, 0x95858a985df5ceL, 0x42bc9870ac6beeL, + 0x8d843c539ea1a9L, 0x5de200cb571043L, 0x084fcd51741a33L, + 0xe1ca20c0009d1cL, 0x0271d28e957e6dL }, + { 0x84cbf809e3be55L, 0xc804dda1c578c6L, 0xea85489409a93aL, + 0x64a450a972021dL, 0xc6a2161e681312L, 0x280bff965bc111L, + 0xd358a4b0f8526fL, 0xd967be8953a3abL } + }, + { + { 0x4c5e6157dd066cL, 0x37afd33634c8d4L, 0xa3ac88a42d8b87L, + 0x9681e9b938b607L, 0x7a286ab37fe4c8L, 0xdeee5742494245L, + 0x184b9d36af75a8L, 0x20f696a3670c04L }, + { 0x1340adfa39e8b9L, 0x03c19290850b2eL, 0x435ebd42c0e1efL, + 0x49de18b142ee9bL, 0xb440b273f116f2L, 0xd94e9fa2214463L, + 0x1b0ddd36311543L, 0x1ae042a991ba3cL } + }, + { + { 0xbc322f85bb47aaL, 0x9e2562554a5845L, 0x96b65ae21115f3L, + 0x46fbed4bb5757bL, 0x18aec4f4c42dceL, 0xc59caf68d801f0L, + 0x91894631205521L, 0x66bd8e089feb7aL }, + { 0x39ebe95c529ee7L, 0x28d89928eadb99L, 0x6058c786927544L, + 0x877e7a5d3808ecL, 0x8f651111c52eafL, 0xfb59812ae221cdL, + 0x22289c6f890391L, 0xa97695b4966e92L } + }, + { + { 0xf0a91226ff10f0L, 0x49a931ba2a65c8L, 0x3fcebbcb1d3cb0L, + 0x70eb79bca9685fL, 0x82520b5ab38cb6L, 0xccf991b76304c3L, + 0x575aab1af8b07cL, 0xec8166a5ed5efbL }, + { 0xddc5698c8689b1L, 0x227c949b2e78d7L, 0x61323218e07d91L, + 0x658a11d22cfd62L, 0x908fb44004dd5fL, 0xe3d14f090d21b1L, + 0x6f3db9da6a1639L, 0x09d86c0333a525L } + }, + { + { 0xd83eaf06f043f7L, 0x88ab648b52d5f6L, 0x67c664d57144d7L, + 0x55d7644eafc8b5L, 0x1c89f20cceb291L, 0x51aec7b831ac47L, + 0x51172fa6148854L, 0x8fabf7ef6d7bfeL }, + { 0x5910316477ee27L, 0x5f299dd20fe61eL, 0x48079a842826abL, + 0xf4a83ba22591faL, 0x8fac66055482ecL, 0x48fd5f16b65b3bL, + 0x4288a7c9fd9e19L, 0x27db8199377894L } + }, + { + { 0x2936ee47fd9dd6L, 0xcce5f0e9ec87c6L, 0x15a50e3db6e3b4L, + 0x61df105ad701c8L, 0x3601add1dff1f7L, 0xb761e06e8a16e1L, + 0x4341e021af3f91L, 0x9156a4a933fa3fL }, + { 0x9dc46ae54bc01dL, 0x605577a64eb910L, 0x22b99f85a59a99L, + 0xab2dbaf0a229d8L, 0xa8bfb656599364L, 0x39ed4a5e94ebf0L, + 0x7b46a1e0dbb23eL, 0x117b1958751422L } + }, +}, +{ + { + { 0xd19e8fd423bddfL, 0x9d77042387ef59L, 0x315cbdd849590aL, + 0xfdc637c7866c1eL, 0x72be83d03515a6L, 0xd44a4a00376780L, + 0x3b9613119e0c2bL, 0x023aca37b1a689L }, + { 0xf5f368782282eaL, 0x44710898a8b5c7L, 0xcd2f00a17a3066L, + 0x754e11281ed681L, 0x9c6c70c0bfcefdL, 0xd6aced03b6f29bL, + 0xe443d562817a2aL, 0xe590ef4e7c0012L } + }, + { + { 0xc2f96763e62e2aL, 0x661816eb2daa26L, 0x3515fd2dd5f512L, + 0xdc36e2756b6e75L, 0x0bdde4674cc658L, 0x102908600e7644L, + 0xfdf00451694a09L, 0x454bcb6ceac169L }, + { 0xf4c92ab6481eb6L, 0x8b77afa09750e7L, 0xe6f42316362d6dL, + 0x0d45deef53a3aeL, 0xdac7aacd7dcf98L, 0x628cb7f125ec4aL, + 0x41e8a20aec0320L, 0x7418c7eea2e35bL } + }, + { + { 0x4d649abdf40519L, 0x8cb22d43525833L, 0x15f6d137a5333fL, + 0x8c3991b72c23eeL, 0x248b9a50cd44a3L, 0x6b4c4e0ccc1a75L, + 0x3221efb15c99a9L, 0x236d5040a9c504L }, + { 0x401c7fbd559100L, 0xcf0e07507c524dL, 0x39647c034a9275L, + 0x2355422f7e8683L, 0x3e0a16eb3ae670L, 0x1c83bcbad61b7fL, + 0x491bcb19ca6cbeL, 0xe668dc45e29458L } + }, + { + { 0xe44c65b219379eL, 0x211381bbb607eeL, 0xd4c7428b7bc6dbL, + 0xba62a03b76a2e8L, 0xe1729c98bb0b31L, 0x3caeb50c6bbc10L, + 0x6c66727b0187aaL, 0xbf9d2f0fb90dcfL }, + { 0xec693501184dc6L, 0xd58d2a32698eb5L, 0xb366d8da316b07L, + 0xe1e39bb251c017L, 0xbe44ba9adb157fL, 0xbaa9a9a8a8b06cL, + 0xd0f46356e473e1L, 0xd25a8f61d681c6L } + }, + { + { 0xba39d5fcb102c7L, 0x66eba21d8aa1ebL, 0xcc2591a697fbf4L, + 0x5adb5792317f54L, 0xa01ae71f76c6f9L, 0x2c525de5042705L, + 0xc8f42724f4479fL, 0x26ab54ae6d7a5bL }, + { 0xda217b5dc28106L, 0xc7cadeaeb2ae6aL, 0x0b1609453ea3b2L, + 0xcddcc1ccc6111bL, 0x5c47affa7a7bebL, 0xf9931bd0e52dabL, + 0x5231835c6dcf96L, 0x7095bdef27ea4eL } + }, + { + { 0xee8adaec33b4e2L, 0x300665163ceb44L, 0xf1476fb880b086L, + 0x07033289569ce8L, 0x2cabf9a238b595L, 0x85017bc26c8158L, + 0x420b5b568d5144L, 0xa9f5f1ef9c696fL }, + { 0x1409c3ac8fec5aL, 0x541516f28e9579L, 0x06573f70e1f446L, + 0x3e3c7062311b96L, 0x0033f1a3c2ffd8L, 0x8e808fcca6711cL, + 0x716752d07aef98L, 0x5e53e9a92525b3L } + }, + { + { 0xce98a425a1c29fL, 0xaa703483ca6dc9L, 0xe77d822edfa48bL, + 0xd2e3455068abcaL, 0xb456e81482cfcaL, 0xc5aa9817fbfb08L, + 0x8979f258243194L, 0x727f2172cd043dL }, + { 0x7cca616aa53923L, 0x387c5aee9bcb72L, 0x0173fd437580bbL, + 0xdd7795b75fc0d9L, 0x47d1c37345deaeL, 0x2eb5d7fb0d1c03L, + 0xf7a1b92958f002L, 0x7365cf48f61b67L } + }, + { + { 0x4b22c3b562a5edL, 0x711216f5c7cd07L, 0x51f72c49ba0648L, + 0xc10d0930de9e6fL, 0xaca479bfda63baL, 0x4722a55af532b0L, + 0x8d59eb77236f39L, 0x5cad8744465c34L }, + { 0xa2119e5722b0c1L, 0xb670264f343ea4L, 0x6910f02c19f387L, + 0xcfec5bc0381fbaL, 0x5f5de0d52c0a1dL, 0x4e474d56378cb6L, + 0x2fc802727e2ba3L, 0xa215da3159b541L } + }, +}, +{ + { + { 0xed535858499895L, 0xa0aefd565c998dL, 0x210d8502d5a561L, + 0xc2cc23ca2cd9d6L, 0x2371d46c4d297eL, 0x88b2143d18d441L, + 0xbebdad9043993dL, 0x6ba91e7ad5f28dL }, + { 0xc2bb3f13a731f4L, 0xd35cfac5d0d5c3L, 0x995099835ac427L, + 0x8938bb55458adbL, 0x0bd738cab26f3bL, 0x56db3d5a28cd8dL, + 0x87eb95fa1d8b4bL, 0xd6700efe7f3b4bL } + }, + { + { 0x962c920ea1e57bL, 0xd3be37e6dded6dL, 0xf499b622c96a73L, + 0x3eaf7b46c99752L, 0xa310c89025590bL, 0x535aa4a721db23L, + 0x56ab57819714a0L, 0xeecb4fad4048c1L }, + { 0x7b79ec4470c466L, 0xc4e8f2e1383ceeL, 0x0f5d7765750c45L, + 0xa3b3bc3725527dL, 0x2f5deb66d00cceL, 0x5d5a0f495a8d81L, + 0x50a442ee02b824L, 0xafb04462a11628L } + }, + { + { 0x72b67bc0c613deL, 0x0150d4be6f0b24L, 0x847854e8ed289dL, + 0xe08292fa320f88L, 0xd5b6da329c6160L, 0x2a48e2d4fb9d06L, + 0x55d9e412de087cL, 0x65683b54f02100L }, + { 0x4dc8c2ea8886c6L, 0xe966dd220d6114L, 0x99745eba57af97L, + 0x23a9a71b854725L, 0x8effe05621a047L, 0xf16d284049a4beL, + 0x95828c25b0660fL, 0xd5b69ba56e96b0L } + }, + { + { 0x0b5b4244ffa0b8L, 0x0585b45096cc5eL, 0x413e1aef505d37L, + 0xe5652a30c7ab8dL, 0xab32fb72990120L, 0x6b8b16e3f09368L, + 0xbf9fadbefe128eL, 0x85f366b14b7671L }, + { 0xcb2f294090608dL, 0x25e2769ac3045fL, 0x069c4f06131904L, + 0x1c57cf1329a779L, 0x72fe0d5b7cace7L, 0x04d9f430897a45L, + 0xbaf32f6359a645L, 0x0fa854ffa7485aL } + }, + { + { 0xae3533c5f56f60L, 0x9773bbb0ad9360L, 0x769b34a38fbe6bL, + 0xb5ba8e9ffb0c00L, 0xa93931875472e4L, 0x12cac92ce5f30fL, + 0x514fc06a9e7dbcL, 0xd7ca86558b4734L }, + { 0xd101ff365a730bL, 0x92da451abe70e9L, 0xfb5f94aef7bf4bL, + 0x8c3ef4c1d56c7bL, 0xb0857668435c10L, 0x7fbbbdae7ed4ccL, + 0x1da6eaf24f372fL, 0x0ab2c1f59b8ae3L } + }, + { + { 0x63a1a78f10a4b9L, 0xbb5278d0c7e510L, 0x97b224ef874142L, + 0x0a9ff52b2517b1L, 0x1b5a485c5cd920L, 0x1a8e2eba1823b9L, + 0x2b088c00e914a8L, 0xe5ec3adcf13432L }, + { 0x0d6ab3e6e7e253L, 0x9f0f5cd6f18458L, 0x839a744f459a6dL, + 0xb4b4f941eb15f7L, 0xe0313acc72cb14L, 0x58ee933b20472dL, + 0x5f73d7a872543eL, 0xb1700c5501f067L } + }, + { + { 0xb70428e085f67fL, 0x5441d5143cabe5L, 0x4d0e8c2e0a6055L, + 0x8d39a080882e4fL, 0x615bb32c1cb39dL, 0x113f18df7a1642L, + 0xbab8cf5250681fL, 0x3017ba2677b72aL }, + { 0xcd2b6e95a3a876L, 0x04765012035a69L, 0x31d6440efa2ea0L, + 0xde8f8d156874d5L, 0xcbc71cd0199d4aL, 0xc546b61e7f2170L, + 0x4e57e4e112c4c3L, 0x58955a8d1622baL } + }, + { + { 0x0064cd704e2f6fL, 0xe9d458de0edd38L, 0xeb1a5977e0a5c8L, + 0xe322ece01fc0a8L, 0x8b9d1661032a19L, 0x3e7b539a89de94L, + 0xfa30262001c754L, 0xe33de4ddb588f6L }, + { 0x4dafbdb954eb94L, 0xbb436480584c1bL, 0x622c93e5dbe29bL, + 0x968f9e3f57b931L, 0x98f03be0f6453bL, 0xb0ecc7f08f696cL, + 0x5af55f4a505335L, 0x028533efb3fa9bL } + }, +}, +{ + { + { 0x3bc8e6827e8d86L, 0x4e43b3063f105aL, 0x5301b7d4981250L, + 0x8b0a75e9f72fa8L, 0x88f59db357348cL, 0x5f0ebb1ec4208eL, + 0x4712561c043d3bL, 0x9e5ded0c806b97L }, + { 0xf9bd0a62121d09L, 0x1759ecbe337cd1L, 0xd1acc0ee945542L, + 0x3683febbd2f63aL, 0x44f1bccda5dfe9L, 0xa3606c9707f22fL, + 0x45ef0642d96ca5L, 0xfc3107d9022df9L } + }, + { + { 0xe81320b44be755L, 0xdf213d55c7c761L, 0xf43d2d5b4e5db9L, + 0x3bcfd828dedcd2L, 0xdf368a6d37a9ecL, 0xfef20aef475a77L, + 0x22f5894162c064L, 0x956bc660142a7dL }, + { 0xaaa10e27daec78L, 0x3cb9b72b6e9a78L, 0xa740bade383f72L, + 0xc31b4017759007L, 0xdada964a7afc50L, 0x6bf062cfd3d11fL, + 0x9470d535db3679L, 0x339447303abf13L } + }, + { + { 0x533f44046e5d7fL, 0xd1793e349048c8L, 0x59e11501929b94L, + 0xcddbbcb8364134L, 0x795c794582774fL, 0x114dfc4e03081aL, + 0x541ef68ef54042L, 0x159295b23f18cdL }, + { 0xfb7e2ba48a2c8cL, 0xe2d4572bb6d116L, 0x7bb0b22d750b53L, + 0xc58888cd142ee8L, 0xd11537a90c9e2dL, 0x77d5858d02eb9eL, + 0x1fa4c75d444a79L, 0xf19b2d3d58a68dL } + }, + { + { 0x37e5b73eb8b90fL, 0x3737f7a3f2a963L, 0x87913fa9de35e0L, + 0xec7f9928731eddL, 0x6e6259e219491eL, 0xb2148a04de236cL, + 0x89700e8fdd309bL, 0x9ce51e49f0bf80L }, + { 0xe7ec421301f17bL, 0xa4b570a3bc5f4fL, 0xc2b1b2a1285ee2L, + 0x5e86bc8c53db73L, 0xb65fceaf24fa90L, 0x9e74c5608ab024L, + 0x5c8003df9ed877L, 0xa632e9e4a2cbbcL } + }, + { + { 0x32a4546c91c8b5L, 0xc122b5ac969363L, 0xbbbec5e3648b3aL, + 0xd5a365e25143b0L, 0xcf3e46454157ceL, 0x9712f04f9bab64L, + 0xc12d43a04b4008L, 0x51932d72edf1c7L }, + { 0xaef1655b2f8470L, 0xaa8e3f36c24aceL, 0x7da75da6b4e761L, + 0xd371827b90bca2L, 0x84db4500afb45cL, 0xae12045ef46b5dL, + 0x91639a5d962f98L, 0x669cbe672f2ac0L } + }, + { + { 0x851bb3183a4356L, 0x7d436bf9a1bf15L, 0x46a3f0e120b378L, + 0x9302abc3f5b357L, 0x1e0672693fef53L, 0xb12f4a95fd2ee9L, + 0x94a884c7de9433L, 0x2645234a6f2874L }, + { 0x6fb56f5cdb8dfaL, 0x4a17dfc9e0ee4eL, 0xe269d8383ab01eL, + 0xda932dab77c10fL, 0x463af0c0321243L, 0xbe1d68216fc8a3L, + 0x2eae3ea48b39e3L, 0x94230213b03e7bL } + }, + { + { 0xaeb507cb22f28aL, 0xa77458b49a6b44L, 0x232ed5ac03dc17L, + 0x79dfc169c61ac6L, 0x7c48be9cd71b93L, 0x983d68ac429cd9L, + 0x7709c4798ae2c8L, 0xe4765c0a5df075L }, + { 0x23c4deb3367f33L, 0xbdf2b7e37d72a7L, 0xbaab5c70af2d26L, + 0xd609f7ffd026abL, 0x23b72b2541b039L, 0x8d06bac83be852L, + 0x911d4a9cb23d1cL, 0xeae815cfb0dbd7L } + }, + { + { 0x487c35c2c33481L, 0xffab636b6136dbL, 0xccd4daea3d3aa4L, + 0x87149bbc3704e0L, 0x9de8119c0e8396L, 0xd49357a58e7ca6L, + 0x68789181562d75L, 0xc7453815ab1fadL }, + { 0x0f1579802c9b91L, 0x7ffc3f0b1ddde5L, 0xa01d5e06aae50dL, + 0x6a97e65e279873L, 0x4bcf42fb5b1b41L, 0x1c6410f32f5982L, + 0xd4f760050701c8L, 0xff02663873b90dL } + }, +}, +{ + { + { 0xdc53ea2e5b2de2L, 0x94b352d38acecbL, 0x37d960b0d9d5e5L, + 0xabd868f90bd997L, 0x781668f35a7376L, 0x043d59710118bfL, + 0xd4da719f57928aL, 0x01942f6983e46cL }, + { 0xab97fc8728bd76L, 0x825956b4b5c1c5L, 0x202809fc82a104L, + 0xdb63e9cc8e3132L, 0xa41c701c2181afL, 0xd28018043e066aL, + 0xc734e4124044ceL, 0x4d9ab23505193cL } + }, + { + { 0x0bcd42af9f0c3fL, 0xda21a46b94a218L, 0xe55243c0ffc788L, + 0x318aae647a5551L, 0x8c2938b79af9cbL, 0x5d15232ec1dce5L, + 0x3d310ba8ad2e5cL, 0xd3d972494f792aL }, + { 0xdeb4ca112a9553L, 0x2f1ed04eb54d9dL, 0xaa9c9cf69fb7a1L, + 0xeb73c3a54dcd3aL, 0xee3eddcf5f201fL, 0x35f9e1cba7d234L, + 0x1d1d04cd2e242fL, 0x48df9d80df7515L } + }, + { + { 0x4ecc77da81dd9aL, 0xa6ac4bb03aa015L, 0x7645842bbc4fedL, + 0x9ae34cd9d6cf52L, 0xf8ff0335917e0bL, 0x7c9da37c2cc175L, + 0x1e74dccaaacfbeL, 0xa8f2df07999af8L }, + { 0xd06c4ea102a466L, 0x2156e87ae190ddL, 0xc95db8aec4a863L, + 0x49edffd244a6feL, 0x110fae6904f81eL, 0xbaa3e50a1cd104L, + 0x5bd38a20478b65L, 0x2b57d05daefbccL } + }, + { + { 0x1ce92ba86f4534L, 0xb2a8592414f5e3L, 0xdd7a4c69979436L, + 0x7599aff3f0add7L, 0xe0ce4d3e2d4f64L, 0x74475cc401a29fL, + 0xaef6541a2377d9L, 0x54048f53f917b6L }, + { 0x1b86b2205312ecL, 0x779ba2231493cbL, 0xc718369aac9320L, + 0xeab01a8617fce4L, 0x17b1f10f7187faL, 0xe68eda0a1aca46L, + 0x61033fe2586342L, 0xfc14e790b6ca43L } + }, + { + { 0x9f2231913d2491L, 0x66bdb537997202L, 0x0bafb0c4617f34L, + 0x5917831f3bb7b3L, 0x6feb2a6b45bddbL, 0x08662b30202c19L, + 0x0bc2b5705852f6L, 0x2c00fd491818c2L }, + { 0xca7672cda37dacL, 0xfe4c04c5a30865L, 0x5f1399f322e92aL, + 0xe7d67ea25b1bebL, 0xe08b014dce7f68L, 0x24df52af2f2b3cL, + 0x2028b23750ecd1L, 0x9b25d4bc810a45L } + }, + { + { 0xa35b7157a9d799L, 0x6da1eb301f9c99L, 0x33ef91ce363ba8L, + 0x21c0e2ece140daL, 0xb0b11bf158cd84L, 0x6a8744293da438L, + 0x924f10d3db585bL, 0xf5ddd7310c6159L }, + { 0xb72dcb86a74c21L, 0x6d14198cc8f79fL, 0x99f4b6c9c5a8d6L, + 0x063968890e135cL, 0x330edb883f6385L, 0xe1a5a6b9079675L, + 0x6e37fa8b8f5fe0L, 0x60e2fd961dca1eL } + }, + { + { 0xc6cb40366c395eL, 0x03b21a7b51d0f1L, 0xbc478a5e693181L, + 0x0017c2fc6cff33L, 0x740a5b839d8d1eL, 0x3968d664d9ec6dL, + 0xfd53738b0ef1b0L, 0x73ca8fd1ed0a04L }, + { 0x4ace93875ab371L, 0xd602936ddad7e9L, 0x1f5424a750bcc2L, + 0xfe09b3668c7a17L, 0x165f7de58341ecL, 0x95b825a6ce61e5L, + 0x9d31e1966c83c4L, 0x65b3e08cc5887bL } + }, + { + { 0xd37e93221482d1L, 0x9af659708b6380L, 0x279426a7d61e4bL, + 0x80dd0ec80997adL, 0x7239b0dd5b76d4L, 0x92e6c73e76c098L, + 0xeeb2321eab3e1dL, 0xa69c4a7eb1a910L }, + { 0x46d6aa7833d9aeL, 0x3ee6957572b0feL, 0x44ccbedcdb3d97L, + 0x342f29dcbea01bL, 0x0d518c58926876L, 0xaaabae75585d2cL, + 0xc548c77e008f58L, 0x819e2fa21fab2cL } + }, +}, +{ + { + { 0x468e149c16e981L, 0x286c7909ddbb7cL, 0x2a92d47db7a38aL, + 0xde614e68a27cb2L, 0x8dc8822e5b0ab6L, 0x38441aecf48565L, + 0x11ed5c9089435bL, 0x238928682d0d31L }, + { 0xc6698d472f2f31L, 0x295242c56d76afL, 0x4099205eba563bL, + 0xae7de5a3ab7384L, 0xccdf127d0ed86cL, 0xb9b6d5b965c3c3L, + 0xe351a8f2c31ad7L, 0xa761dd8ac12f13L } + }, + { + { 0xda115ddf171ab7L, 0x2de17b1401f93dL, 0x95019ca40964b4L, + 0x169d1f465ba3c3L, 0x534a0070090d08L, 0x805c5e282bf410L, + 0x15dfe1165f8d90L, 0x827a416ca72456L }, + { 0x5af888433a36c4L, 0x8bfa54cd8ee604L, 0x08fd1419ce290fL, + 0x2db5e8c287b3a6L, 0xe5be98103cdad2L, 0x155b874bf810b9L, + 0x2ae42de670f473L, 0x22185847f74657L } + }, + { + { 0x54b2a5023ffa43L, 0xcf87b16a24d919L, 0x1ff540263524e8L, + 0x73c94e056d1e54L, 0x76515523899fb5L, 0x13a721418723bfL, + 0x39afbdd3561517L, 0x49b790a9f2862eL }, + { 0xc8c1f4f527d2ceL, 0x1997aec7609bb7L, 0x583ad8002a3400L, + 0xac2374e4f79706L, 0xbf1f9a821b7183L, 0x06158ab6600fe0L, + 0xfcc9b2ebd56751L, 0xe1de5acddaaec7L } + }, + { + { 0x230baa1788fdabL, 0xf30860a7d04597L, 0xa2c7ece99f4caaL, + 0xbd39f106ad065eL, 0xfd92f5d3bef7bdL, 0x6069fad96d2203L, + 0xbff38cac4d9e0dL, 0x419a0171fda313L }, + { 0x5d77fd8572f035L, 0x5af99f2b282b40L, 0x7257d3b23facffL, + 0xf2ee22358c90afL, 0xcc2687d9b6a52aL, 0x140892c302430eL, + 0xa934d5e3ec4f38L, 0xc087d7c3bd18beL } + }, + { + { 0x7e94138a2c5ed7L, 0xbc8ceef53610bfL, 0xe89356bd86f803L, + 0x9a3a3805a55330L, 0xe894aba11ad648L, 0x2e68fbaba95918L, + 0x643e2bafcad344L, 0x0dd025661640aaL }, + { 0xc02e479e25cbddL, 0xd78c4d813a1b3fL, 0xa6dae8fcca9692L, + 0x3dd91e9e5de8a0L, 0x78ae0ce764ea36L, 0xb4ad99985dbc5eL, + 0x967ff23e82a169L, 0xaeb26ecbaee1fcL } + }, + { + { 0x8c502559a6f90cL, 0x56e7abe0ea374aL, 0x675c72256413b2L, + 0xd3fc17e946753fL, 0x28c4e1fe235f7cL, 0xe209bcdb028eb0L, + 0x7d0f93a489fe88L, 0xb966a2e063706aL }, + { 0xb6c228c4a30319L, 0x6868efeca6d674L, 0x0610a70057311aL, + 0x0808112bad7f89L, 0x2a2462c1dd6181L, 0x52ed9feb58e88aL, + 0xbbff16f33821a2L, 0xda53e9617f882aL } + }, + { + { 0xb6ffca38c30e5dL, 0xa90f9915c905f5L, 0x72fb200d753e88L, + 0xe509d4c7256c6aL, 0x369e552d866500L, 0xee4b7e033cf8aeL, + 0x280d954efcf6ebL, 0x5b275d3d557f0eL }, + { 0xeb17211b5cecf8L, 0xd6ad50fbdb2f8dL, 0x2478c7b35e04b7L, + 0x97e7143ac73bd3L, 0x09d6ede4817e24L, 0x68fea712c405e1L, + 0x34adbc905f67a1L, 0xd20ab7073edf99L } + }, + { + { 0xe116a96569f191L, 0xb3f0bce4d6e29aL, 0x30b9e1af51dbabL, + 0x1dd36f3346d276L, 0x83151030749a27L, 0x242f148ab47f70L, + 0xe8a5bcf5585681L, 0x8b801845ed79baL }, + { 0xa4042fd3894ad1L, 0x82f781d2b88bc6L, 0x2d34cacbe4c397L, + 0x8731aeadd99c9fL, 0x0f95498ef1d382L, 0xcaba2e1dd0bbc9L, + 0x78889e954064e8L, 0x8cd9c9761a8ab9L } + }, +}, +{ + { + { 0xf31f53ffa0459eL, 0xf8742a1315cd6bL, 0xabe2f50ae64e97L, + 0xbd787419b9da48L, 0x4521a3351e526eL, 0xfa05935e10ba45L, + 0x5c947e1e8f903cL, 0x0aa47d15a754eeL }, + { 0xb2849efd814825L, 0x9c2a5d25c9968dL, 0x24dbb2604e634cL, + 0x33f3a4cdb38194L, 0xe04f609c8a2b6bL, 0xcaefd8eabbbfdbL, + 0x683119a404498bL, 0x24ab7a98b21cbdL } + }, + { + { 0x6f1326921fa2ddL, 0xd79e61cc10a4bcL, 0xac4b3ce4bd6d46L, + 0x52459b6bd3f37bL, 0xce0f0a3a396966L, 0x050d1d5a1ed488L, + 0x1b9c403e0b17faL, 0xee1abd004a2e66L }, + { 0x97065c35cf3e3bL, 0x6513d5fbe33441L, 0xcd3463479047aeL, + 0x45cbb1cfd22df1L, 0x7a173ae967b17cL, 0x75f5ba72223cdaL, + 0xe3d12dbefe0a73L, 0x3b7f94dfd7adcfL } + }, + { + { 0xd596a13f1e9b7dL, 0x04f5bdd6734e0cL, 0x18b694f8be163aL, + 0x15620c7d959fa3L, 0x65fc2c553d2a3bL, 0xd44a364c4d36f2L, + 0xc8b421f268ceabL, 0x564139abfe2bd4L }, + { 0xb52461019d4633L, 0x5ab3f886346934L, 0x96691fe9819422L, + 0xdfdec898b39b82L, 0x84b1c7997cfb27L, 0xe59a98d4d6d004L, + 0x5e5d0c612c350fL, 0xb431220d415774L } + }, + { + { 0x3d0ca736aae0a2L, 0x7b1991f48c2d8cL, 0x00ae8565cdae72L, + 0xdbb6ca0bd55128L, 0x3c2ab2a45c82bfL, 0xea5a55979545caL, + 0xeba9a26d5927d0L, 0xb52e40183257fcL }, + { 0x55ed517ca9650aL, 0xbdaa081e3ebff2L, 0x8cf7ce49f8831bL, + 0x1d0b5bd6e3b8d3L, 0xa314a9fd8fc869L, 0x07f2079b892babL, + 0xb700dbfa0cc9d9L, 0x7105a086dc0a39L } + }, + { + { 0x0c7e05d8c7d901L, 0xa7ff681af3182bL, 0xb88e3caf9a0d06L, + 0xfe20a12c343b7fL, 0x9f0257703251f9L, 0xf225dedc40c5ebL, + 0x50e0cecb208ea7L, 0x5b250f0e6eeb65L }, + { 0x807a1534806b6eL, 0xded120afa94139L, 0x237ddc749366fbL, + 0xdd3674e5a34bcbL, 0xef6cdff9c4a61dL, 0x036194bb2fb896L, + 0x38659539528cd9L, 0x0723c596936a52L } + }, + { + { 0x1f84cd5e17719dL, 0x545939bc73b394L, 0xefbf3c583e84e7L, + 0x6cc46f1f77fd66L, 0xa629f591383ab8L, 0x9177ffacd35cd2L, + 0x039187f9dd411bL, 0xa9cf1cf7b7eea8L }, + { 0xa3b105aac47e5dL, 0xa755bead0a9da4L, 0x50cfbae73da15eL, + 0x9456cbc60b628cL, 0x7ffc3629b7a910L, 0x30b5924cd6d6a4L, + 0x198629f0b04ab6L, 0xc74609c624dea9L } + }, + { + { 0x27d4d77af12fa6L, 0xdd8a216690aeb2L, 0xe48fc02fe24417L, + 0x1970403720e17eL, 0x95013fdce37b42L, 0x06817d2de4bd9bL, + 0xc5863e763d0ba2L, 0xa1bafc0a556f5dL }, + { 0xf28ec7b410a78aL, 0x0dcac420a01a63L, 0xfcd3fa4b5bce11L, + 0x054d7e5d278b89L, 0x5195db85ce49e3L, 0x4c0b1672c73d96L, + 0xd94307720a1bdbL, 0x66fa8b359c77a7L } + }, + { + { 0xb9e93aed7462feL, 0xbfe54b218dde4fL, 0xaabb5283dbb08eL, + 0x8c367020e5fc45L, 0x35028888e69be3L, 0x6d2efc1c12a11dL, + 0xfce5cebf265e30L, 0x58c8bb35742c7eL }, + { 0x32e89dcccf7fa0L, 0xa811f33dd020a4L, 0xa10d6205129fe5L, + 0x3841c88e4ed29bL, 0xf3303a9d8b1ea6L, 0xa9a0cad1781f58L, + 0x4502b388f3ef0bL, 0x2b7587e74c6d35L } + }, +}, +{ + { + { 0xc6eaea123ae7cdL, 0xa1884d473c0caaL, 0x901e76fef1ea88L, + 0xdb9935ca14269dL, 0xe8b2486947f1deL, 0x4ad56f4a657588L, + 0xe7680542913fb1L, 0x2abff5d37600daL }, + { 0xa814813a81a797L, 0x63e76a446acb69L, 0xb1038394ab8277L, + 0x587de349d8e759L, 0xdfaeb8dddf62dfL, 0x24fe1cf9239d49L, + 0x7de7409e130d1cL, 0x3ecfef9581d070L } + }, + { + { 0x8d177a0f87c72dL, 0xae7e5818c6d1deL, 0x0077b5f8cece85L, + 0x382483832d2187L, 0x49d8b156db2bd2L, 0xe9e5513c8d85b9L, + 0x63c410ce05c53fL, 0xceaf2fbd86f752L }, + { 0x0b432fe93806c5L, 0x18eb15d3d06c75L, 0xcaad82612cfc02L, + 0x581e0401e2d045L, 0xd573cb595edcfdL, 0xce71948dbc66e3L, + 0xcf68721acc14eaL, 0xf68bea26cac4dcL } + }, + { + { 0xd8576afcb74da2L, 0x8771c29c433f46L, 0x7315af6e2f5b8eL, + 0xc195481ba33928L, 0xb77dcc22fb1f94L, 0xcb3e57ca610f75L, + 0xeb2a92753907dfL, 0x916f14923eff95L }, + { 0xbb378e4b6cd291L, 0xa2a5e2b2f13ce1L, 0xa8a0e60bcd00b0L, + 0x5902741682b75aL, 0xa0882c93f65a77L, 0x2069f75c93cfffL, + 0x1ede40570c0cb9L, 0x13840c90d526c4L } + }, + { + { 0xdc2caaa03ced48L, 0x2079219a0315beL, 0xca493563b1f642L, + 0x0202dc7b0665f2L, 0xe5d6bbdb7a5238L, 0x36fbd5e26eab32L, + 0xb3988f1f5819b4L, 0x5b15dc84aa4d69L }, + { 0xa52feed54e5c24L, 0x927471be91a797L, 0xd119bfdd57f677L, + 0xde38f7b78e4c4fL, 0xa7af516b150bc3L, 0x403b21e26b76c2L, + 0x589067d92300dcL, 0x04e406a066802aL } + }, + { + { 0x28e7d09a9ca9bbL, 0xaa84fd5fccf4a0L, 0xdbe9fb8635b7edL, + 0x9ede3f5d56fc7cL, 0xa4b5031b01cb29L, 0x584299d7f93703L, + 0xbd28868b6fe825L, 0x1d385d48b9c2d9L }, + { 0x6606f4a822be80L, 0xb5a0165626d0fdL, 0x9920a2014568adL, + 0x7d430f41c6d174L, 0xc243e16e02e9e9L, 0x367f1d2a6bd649L, + 0x693910071b8c36L, 0x2ede1314de2984L } + }, + { + { 0xdc781875beec32L, 0x1fff0cca525ff4L, 0x6e86425676df34L, + 0x2b4e8a63f638e1L, 0xc4991d29b1e59fL, 0x399d0011589717L, + 0x406464ebe041cdL, 0x901cb3d9e65bb0L }, + { 0xf5f4572fb42307L, 0xf81b3b0f1b7307L, 0x8fb695cf2094d1L, + 0x7db4792db56f7bL, 0x36836d55a794e0L, 0x2da477b09bc879L, + 0x1cdfadb1887c40L, 0x65dc6c2f2699b6L } + }, + { + { 0x36f9f214737972L, 0x48f0c8b7a387b0L, 0xa156ed339a1d24L, + 0x375293a0fed268L, 0xf679f487ff75cbL, 0xd15a00f1cc9e62L, + 0x92a7dc722c3877L, 0xe9870636fb0ed4L }, + { 0xfd8e59c16f5f3cL, 0x375732eaeeb48eL, 0x2dd9213ca1ab42L, + 0xcb062099ffcceaL, 0xfc611f6b23edfdL, 0x271634999b060eL, + 0xb938b5d820de8aL, 0x138f6e7eb49a32L } + }, + { + { 0x7feda63e485f70L, 0x646380aeb27b2cL, 0xcf8fe32c4511c7L, + 0x2c68e1eff9406aL, 0xa9f2fd920b6020L, 0x1c98fc63b3e465L, + 0xb8dac3593e53aaL, 0x2fb47b6a750e96L }, + { 0xea373ef1950bb3L, 0x81566944ac7aecL, 0x8d6b3c2b55b931L, + 0x5d13f2db62ef7dL, 0x4647f2aab9182bL, 0x8f56c5a33bf07cL, + 0xc5ab284b35a221L, 0x0747ab75a46a6bL } + }, +}, +{ + { + { 0x5b9236c86b85c5L, 0x5967a0dc482448L, 0x397c9557df6ae0L, + 0xf83ee1c5378f2bL, 0xf82df656e05dd1L, 0x4c424f619d7c8bL, + 0xa612550a6d5f2aL, 0xfe8482a63c3ebfL }, + { 0xcb8d4030142c82L, 0x08b06623679e6cL, 0x3ea51463eca5eeL, + 0x089eb3b1370500L, 0xcbfb19c5a0d306L, 0x2f6858842a65bbL, + 0xe3e1db5e51e119L, 0x2c150e7110895eL } + }, + { + { 0xf323488f6d4c4cL, 0x5fc931f63b87e2L, 0x8867da035c759fL, + 0xb6f1eff9746d4cL, 0x8a8172d990be0aL, 0x1113eee5c407b4L, + 0xd80dacf378ed8aL, 0x99b57cf3fa7fd1L }, + { 0xf5bb6d95176405L, 0x6b8963a92e83b5L, 0xac55b6b8a7ef8dL, + 0xe73fa126c1fbf0L, 0xdb3756060148dfL, 0x72f1a98f3f1fbaL, + 0x1f71d0aea550f2L, 0xc3ea4f09544a87L } + }, + { + { 0x5b09da24322bf3L, 0x2a573d561264e1L, 0x93cb2e1803acc4L, + 0x397b4fbe502fc6L, 0xddfb21239e0ebcL, 0xeccd8f5bbcbc57L, + 0x49d3bed4663788L, 0x37192aa1218df9L }, + { 0x8a05bc92ffa3c6L, 0xc38c28123ebf4dL, 0xc80d547fe343a8L, + 0xa8d5a5b6c63516L, 0xc5d8ce18d8fa6bL, 0xeb5e87224a87c0L, + 0x9806e9e75bfa23L, 0x11f0889689469aL } + }, + { + { 0x81005f68e75666L, 0xb84d861d349505L, 0xe0832829f321eaL, + 0xb751d7acfa33a1L, 0x793cf6f067c550L, 0x073a6b21027e56L, + 0x53f40ee66a6012L, 0x70bfaa8c210fa9L }, + { 0x1518e39e4b5998L, 0x8f0b53024b8d9cL, 0xd91c281afdf923L, + 0xc5cfb2824e3f69L, 0x63a529a870871fL, 0x3d3e8872128dadL, + 0xed658dccb30cceL, 0xf9373b9afb7baeL } + }, + { + { 0x22d4dbede58ed2L, 0x4fefc1d03f8789L, 0x6b0a1fe344817fL, + 0x96bef40a56b0b2L, 0x32684eeda249faL, 0x8298864524a91bL, + 0xa958baf0c736a1L, 0xd033a7def2f3e5L }, + { 0x5be3edc43f4d6aL, 0x326a39d9c89abbL, 0x90c44f755d997aL, + 0x20581066e966c2L, 0xdbae4906548038L, 0xac7bc97d473fc1L, + 0xb34488b4b2603aL, 0x27aea275e9bb98L } + }, + { + { 0xa59e7281b88773L, 0xe2f05d40c241f6L, 0xa56229e4e75749L, + 0x8f00c0b1b10705L, 0x855994619394d3L, 0x0d7e352aaf5e32L, + 0x526c462787b8eaL, 0x89297d9a179d48L }, + { 0xeff17e6ef43892L, 0x17091eb221f841L, 0x82f5eb34a4b848L, + 0x6bea4778eb7b76L, 0x21f227176c536cL, 0xd9ef2c896c81bbL, + 0x7c2754654bf4d3L, 0x9dd4662d7c28c8L } + }, + { + { 0xe7fff0020e1a6bL, 0x26a35c6a08d467L, 0xb3c773d3248c91L, + 0xa646615ba7d935L, 0xa91f453b0d26faL, 0xdcf9c3460c6d32L, + 0x63668619e3e3dcL, 0x3012813f30f3e2L }, + { 0xac6623dc2fc61aL, 0x108dc252bfd2ffL, 0xd7f5c0d231d6eaL, + 0xa904f9aad1107eL, 0x46941c20d1e9c8L, 0xe5b6451c810cf2L, + 0xaba8e674f511d1L, 0x5b4b94f08373feL } + }, + { + { 0x002d4e2849c230L, 0x9bed0efd8ba391L, 0x745e0c0828e319L, + 0xcd40907ca58de2L, 0x2c87ab11abaa4aL, 0x3c17a97db64391L, + 0x36b184e86c72d2L, 0xb03d202485f7aaL }, + { 0x2b6b79bde24abaL, 0xdcb78542325fb2L, 0xf5d1db966ebae2L, + 0x35a4d5b903840aL, 0x7afeb09190e9daL, 0x1818f6a35c1792L, + 0x90091fa3faa269L, 0xc4ccff62570235L } + }, +}, +{ + { + { 0xa177619ec85940L, 0xfca24db7ef7eeeL, 0xb2450f37a90c11L, + 0x29d256ddbf4f85L, 0x920c8d051316c3L, 0x2f7f7ba04474daL, + 0x308117f2ec9a0bL, 0xd0a231ad0d2085L }, + { 0xf3288fc7ab641dL, 0xc68bade9f4fa32L, 0x768f014bbf8253L, + 0x5eff260c0a33f0L, 0xc71b4536bb93ceL, 0xa71d045680697fL, + 0xb62444cce72bc3L, 0x11f03e8d1379f3L } + }, + { + { 0x1f54789c16df92L, 0x874c642e3ed142L, 0x6699f60fa2a9f1L, + 0xbd1b8d33fecfc1L, 0x59682d58a3d953L, 0xf17c0214a36b81L, + 0xeb9621d181a666L, 0x7c2c3ab3cf1ad8L }, + { 0xe6888c3e529f7cL, 0x197b66ab355315L, 0x63b558a83e31acL, + 0x4aa7bc5891c68eL, 0xc17d989592e360L, 0xc750a291363666L, + 0x0d534704909ac0L, 0xd6d02724594a10L } + }, + { + { 0x35c541b3fbb635L, 0x50016d05982afaL, 0x58ebce496b0ca0L, + 0xb940027577ea56L, 0xf29d305e38480fL, 0x43705b0ebd6a2cL, + 0x0e4acdae90c639L, 0xbe94a29f56e05eL }, + { 0xc61f4a030659adL, 0x39074adc402211L, 0xfe0d8d551b621dL, + 0x2d02e8dd1d5222L, 0x05ece3c46c2683L, 0xf70705ac689d41L, + 0xe3caf444d837bfL, 0xfda058475ba6d0L } + }, + { + { 0x1098163cb7d458L, 0x12b645ff5ba834L, 0x70a318128af72cL, + 0x5f4727ef32e5ddL, 0x7cbae1510a21b4L, 0xa80bf806785389L, + 0x9827402b8f93b7L, 0xe385f8208349daL }, + { 0x2d054619589f6eL, 0x6aa5b26e7c0191L, 0xe79ae12bd5574dL, + 0x5d13f914148e61L, 0x7b2be0f13716ffL, 0x82b0fe680bb81fL, + 0x697633c3e2569cL, 0x6c1f083873f8b3L } + }, + { + { 0x6e26d850be1674L, 0xe4e47f6ab8044fL, 0xfdf46e882fc434L, + 0x639ae2cc89cadcL, 0x2244a524b85bdcL, 0xb1e4790b7cf4eaL, + 0x51dce037e0bb8fL, 0xdd143352716ceeL }, + { 0x1c049b48e8841dL, 0x6bf26dcb97c621L, 0x21d6255ba01178L, + 0x477258a8e4f0e4L, 0xf5e437e68f8ef1L, 0xd118fbc8b03e1eL, + 0x3d6bc51e1c91b3L, 0xa259486d5b6907L } + }, + { + { 0x4159cfc7b6f5dcL, 0x05a52b3493694aL, 0xeeb511c83b8883L, + 0x19d79e42b06400L, 0x8e503a2738f37eL, 0xa30e5795a94ad9L, + 0x3981c75262618dL, 0x06b6c692dcba19L }, + { 0xd7242ee4d1b051L, 0x6274ccb3b350c4L, 0x66df0bbf540019L, + 0x4d66be65ae12d5L, 0xcea29601049cbaL, 0x40473398df84b3L, + 0x7d6c96b75a31c8L, 0xbb80159874174cL } + }, + { + { 0xf0f7be059f1aa4L, 0x798f39adcff451L, 0x96763ff8014e1eL, + 0x03987a809cc5ecL, 0x4919656893650aL, 0x92e8eef75e24dfL, + 0x54e97cde89d639L, 0x8081d067682cc0L }, + { 0xb9ef41aa8ceb71L, 0xb8173a4a4d7aaaL, 0x93d81b1c54ee10L, + 0xabe180570a445aL, 0xac0ff9764d569dL, 0x86946b23e570beL, + 0x8e11dd24180641L, 0x3d0b33c99f67dcL } + }, + { + { 0x2c9637e48bf5a4L, 0x9fdec19ccaf112L, 0xe5cde9d5c42023L, + 0x9869620878f0ccL, 0xcf970a21fe6ebaL, 0x1df5ec854e678bL, + 0x4667f0128d00ddL, 0xfa7260db0b3fa8L }, + { 0x6bd2895b34239bL, 0x04c8bc52d2a50dL, 0x14e55ef6cb23e2L, + 0x6440c273a278d5L, 0xf4b12e32193046L, 0x46adf645dd4c08L, + 0x70e29984656e8cL, 0xe7b36eae4acd44L } + }, +}, +{ + { + { 0xea64a5716cf664L, 0x8497ee426fd357L, 0x44d94b4814e851L, + 0xf4aac225a6a2cfL, 0x947b30980c301fL, 0xf390ba17865383L, + 0x16c4fc6d1773d3L, 0x61b98146227220L }, + { 0x07dd03a1dd0270L, 0x290ca820f160dfL, 0x8f2205444ba955L, + 0x4e85e450b6f1b3L, 0xfd73ce9ad78089L, 0x67c12702f2cb0eL, + 0xa7de0d7ee33a61L, 0x6a811cc6553261L } + }, + { + { 0x5ef05742d0a427L, 0xe8d2e95220a341L, 0xdd28cbf8044886L, + 0xdad7b4ba1aa58bL, 0xb28f3738ec901bL, 0x1841a935bbe3dbL, + 0x8fd7cd1a075feeL, 0x93b603fc0d3cddL }, + { 0xca54fd55edd859L, 0xa4cb05f64ed687L, 0x3138668ed1a3d7L, + 0x1224fdaee32be5L, 0xf1f532bc80aeb3L, 0xa4f65d0e8d4d69L, + 0xc697a015905fe5L, 0x514da7a6690ce4L } + }, + { + { 0xc7b9af83de4a55L, 0xc79bad7b318d93L, 0x1808071f5b1c83L, + 0x92112efb965b16L, 0x655ab387bb740aL, 0x53dbc8b384ff87L, + 0xd153c2872dc6f2L, 0x2ec20e199c7819L }, + { 0x65e46ea3b854b5L, 0x272d5aec711db5L, 0xfd1bb5326e19e8L, + 0x33280b83dc0665L, 0x95b986eb8f1c4aL, 0xa671fc4a685c4aL, + 0xa03cbd583bdbbfL, 0xd329402ab77544L } + }, + { + { 0x40fa6518e62b35L, 0x3913b11f9e55a6L, 0x4e8089b5270a41L, + 0x565f52a80d1886L, 0x93b5f05512749bL, 0x35c869c141c547L, + 0x9a44a1af86717fL, 0x2b9984b9c2b2cbL }, + { 0x61fb6074952322L, 0x2d4072f7af1464L, 0x9b2fa8c600eb30L, + 0x6071fb7f10668eL, 0x27cc24d90634caL, 0x3875bc2471d32bL, + 0x678590ba11210cL, 0x352b447fcc5a9aL } + }, + { + { 0x795d5415fa3200L, 0xadaa557a92949fL, 0x42fff063cc88c4L, + 0x26d683171b68a5L, 0x3286549e67ad8cL, 0x5bf636386396b2L, + 0x41229b6e12c8eaL, 0x05320c9748952eL }, + { 0xae36b63900b460L, 0x9354ff2f2b6affL, 0x10b810b065ee0cL, + 0x4d6925fcc8bb38L, 0x31c03fd7a22f14L, 0x76b7f4457544e8L, + 0x3a9123cc0eed26L, 0x77acd67e0cd1ccL } + }, + { + { 0x2e9053007ec527L, 0x32388ef62937cfL, 0xa445389e229188L, + 0xa44b68e33bcebeL, 0x5a8722e4c4e701L, 0xfd066e8cf07e41L, + 0xa3c1a4f95fab62L, 0xb4d6a1be542f24L }, + { 0xe6a92e4af6c9b5L, 0x9452484c83d61dL, 0x422b55b0062276L, + 0x261973a5279688L, 0xde8be263999fb2L, 0x64e96287b029caL, + 0xd8edfaa06897d4L, 0x408319c6955511L } + }, + { + { 0xff6baed50a5632L, 0x922b7d05c5885aL, 0xdf0f3b31b45864L, + 0x27e49c0c04340eL, 0x618c566122c447L, 0x7863a38eafee7eL, + 0x7143affb828cb0L, 0x51fcf4cf9d054eL }, + { 0xc4a4b3127f5e09L, 0x021f47a90be2bdL, 0x1a060197ab956dL, + 0xe77fa1586ea86bL, 0x9ccde87d550ef3L, 0x7dee53a6532654L, + 0x8b4f060e826387L, 0xda38637ad077b5L } + }, + { + { 0xbc901b30e9fac8L, 0xfa082046fb2a2aL, 0x92f68ab5e04efcL, + 0x184a30a9ac12d0L, 0x1aa11aab25d479L, 0x8bc5f4c0f03161L, + 0x7e3a083cfc8817L, 0x84d9355597f93fL }, + { 0xc014478239abc6L, 0xb226b098d37b04L, 0xb056942f575789L, + 0x816b95aba745ebL, 0x2a49d39b98ddb6L, 0xc41ca26291af81L, + 0xb3afe99ab26347L, 0x59c31bc604b638L } + }, +}, +{ + { + { 0xa16a8b9c42befdL, 0x731c9c92052f00L, 0x1ad49b41f5dfa0L, + 0x7a289e3bffce36L, 0x868fac00c79cf1L, 0x6d6d28486721abL, + 0x590f928e726c94L, 0x0e802cb51f3841L }, + { 0x6a6a57a0b694bcL, 0xb9bb0cd8120fb8L, 0xad96ac79c05826L, + 0x294da8c7768df0L, 0xfe32311b56c6c6L, 0x291c2c6ae8d050L, + 0x1c765e7e7db4c9L, 0xe058298d65f9f7L } + }, + { + { 0x4bfa85b7e8d345L, 0xa04ef95de1dfc8L, 0xb5f7f21324ace3L, + 0x4b350a1574b14aL, 0x11436bff8e5c8dL, 0x1c789f97642369L, + 0xeb5e335fb623ceL, 0x9deacd2442d562L }, + { 0x4ff989f531ee71L, 0x43e2c49aacb52aL, 0xa76319885bfadcL, + 0x08b6d5cd0161a0L, 0x010e3fa541f197L, 0x83a589e3279a16L, + 0xf0991376309f9bL, 0x07c093bf1cea10L } + }, + { + { 0x1ce3f0f33d2192L, 0x07b559ac37ce73L, 0xaa2ad38207be27L, + 0x84f053b7ed93deL, 0xbc5c7973b98a4bL, 0xc92346163aa9b9L, + 0x807cc16231a10cL, 0x8ffdf57a061209L }, + { 0xa9ca741497070fL, 0xf608ec9d113b3aL, 0x51327268d0384dL, + 0x96686acf5ec307L, 0x437bbbd71c4665L, 0xdef09d57c379caL, + 0xf8be033621747cL, 0x2775b378ae8047L } + }, + { + { 0x4009798b2c4fc2L, 0x148d7d1203772eL, 0x9d9392df8423fbL, + 0xa5bd72eaf8cef4L, 0x579d58d4380b53L, 0x2ff88f18c39d24L, + 0x9ca2fbc5706466L, 0xb42987d1e56af2L }, + { 0xcc2556e5d94ea8L, 0x4e5c2b35369d76L, 0x5de35742a94f9cL, + 0x8d068c95cb4145L, 0x4d553ff51bfcbfL, 0x3ab71648a23fceL, + 0xc9cb3a9d0fa7f3L, 0xf81209bed9ced1L } + }, + { + { 0xde7356ee5b66f5L, 0x7b2bf1ae8a25e0L, 0x09a444a2c9b725L, + 0xfd8a2f44906c55L, 0x409cc8082514f3L, 0x47e009928999a9L, + 0x0a582a66a312f4L, 0xf7946f8f6723deL }, + { 0xa55f6ba92d8affL, 0xb62c3c8a544b1cL, 0xa1d14115c16a94L, + 0xc3783192ad5e71L, 0x13d784706b1dd6L, 0x99005f8ee7ff55L, + 0xfb5ea3f8a1e7d8L, 0xdc7f53cb4cac39L } + }, + { + { 0x482abaf36e3794L, 0xc23e9e5c74684fL, 0x4544cf6f1629beL, + 0xd8a8ee52f40374L, 0x2eea87ff433bdbL, 0x489a99cae9990eL, + 0xefc131e54b23b6L, 0x25fe6998600270L }, + { 0x03d2d9ec059a7eL, 0xa6445b56979c3cL, 0x491a10c9bfbceaL, + 0x15b5974e937af1L, 0x4be8002797c7fcL, 0xbed8a49fedcfeeL, + 0x35751cea9e0691L, 0xe9a9fa39ef5982L } + }, + { + { 0xeffeaca3065de7L, 0x841d544ac4d4e2L, 0x8144679caf199fL, + 0x98cf4f9443967aL, 0x8cd57f4f33183cL, 0x390832ac1b15ebL, + 0xc4b1feaa53b500L, 0xd762a10dff24b5L }, + { 0xccd3eedb0ee2a9L, 0xa6dd4a9362d485L, 0xeb4ff26f1d047aL, + 0xc0771fd23860fcL, 0xdbb4e394b64114L, 0x2ff3f244d29b29L, + 0x9cac005387b365L, 0x05b7aa6de5994aL } + }, + { + { 0x5e71752c03dd63L, 0xad10fe9bc74687L, 0x51a5b0c54c76abL, + 0x763fd501f586d4L, 0xc7bd5ce816048bL, 0x8fc83d23f744dcL, + 0x0561802109df9aL, 0x18fb01fccf0e43L }, + { 0xe4606fc038ab23L, 0x5878f1fa664c98L, 0x3aedbbd5da7356L, + 0x3c578f5516746aL, 0x259477f1a17210L, 0xc7a869d028248fL, + 0x6517a6148cbf95L, 0xbc5f91d3d04d47L } + }, +}, +{ + { + { 0x15fd9a9083ca53L, 0x1161da02697ca6L, 0xf516af356b676cL, + 0x8a420d575eec13L, 0x72d67421a9526bL, 0x8d8c29e76b463fL, + 0x38a4f588815627L, 0xf7e528be0650f9L }, + { 0x2cfa78e382edcaL, 0x638d183c4ad83cL, 0x96d3b9de4a0119L, + 0x5769ccba7c1101L, 0xc3b3b792b8d04aL, 0x96212f64951bdeL, + 0xad7905a481161eL, 0x8fd676241c5edfL } + }, + { + { 0xf7b063539d6cdeL, 0x69d0549115a84aL, 0x4a976c6cbd9fe4L, + 0xc92953f950ff96L, 0x1d7f0fe654d127L, 0x7293870da0f75dL, + 0x7bb3652cf2277fL, 0x64798c9834484fL }, + { 0xb94d8bfac3a76cL, 0xf5721a97ff776bL, 0x23a6e9f2722e31L, + 0xe9da9969a5c034L, 0xb9bbf83456ebc3L, 0x239f58a96956a4L, + 0x8b75beb18b7f00L, 0x6c2b5b8a51cb97L } + }, + { + { 0x78b1c627eb41f3L, 0x0638fcf17c4352L, 0x939edd80c5709cL, + 0x0a8dfc3edc906cL, 0x3942f47efb01edL, 0x4c8275749986feL, + 0x792545c4dffa57L, 0xeee68836c3ff26L }, + { 0x824d08e12b1218L, 0x515a478902457fL, 0xc70cc9cbae55b3L, + 0x1240737bcef9d4L, 0xf22e6162f9db7fL, 0x98c4f0291f8da2L, + 0xa89219cafaaa67L, 0xf35fd87e7d27e2L } + }, + { + { 0x19b0cd701b80d0L, 0x3d7e29df9aebd1L, 0xd39c9ca0477cbcL, + 0xac0f6155ff0d3dL, 0x8a51993520fd01L, 0x508ff54b22d6fbL, + 0x8786c47318d3abL, 0x4312c464a683f8L }, + { 0x73b1d3995359f6L, 0x0d94fa5963011eL, 0x5723af29bfe83eL, + 0xafa90016841df3L, 0x791e92ab7c498aL, 0xbc931ad7ea4253L, + 0x438e016b783c06L, 0x1347db22ca662bL } + }, + { + { 0x41df37dfbaa861L, 0x98ecb23329e4deL, 0xdaf1560507e018L, + 0xa902269b088e32L, 0xad898a5e4cab2fL, 0xd84e9ed02c1e1bL, + 0xc20a5d58488af3L, 0xc7165af6cc77c6L }, + { 0x8526f3adeb7461L, 0x03577b14a2d332L, 0x28e469de4760b5L, + 0x442c7f9b276266L, 0x90d5c77f9c90faL, 0x7aa87163e211bdL, + 0x56d8ff05decfd6L, 0xa204b56ee23e6eL } + }, + { + { 0x2e4374e4aceafcL, 0x978743b6fcd5e5L, 0xa0f6345c4855caL, + 0x9bc7e4fe98074bL, 0x3835d57c33d08aL, 0xeec7c8b6f00566L, + 0x71628a21acf55cL, 0x5da375097fb19eL }, + { 0x6904a8e01a7125L, 0xad33c85e6e3780L, 0x1702928c19f94aL, + 0xb424ff27c04b3dL, 0xb212e3919e2ba3L, 0x4cca8e8c9af4c9L, + 0x98ab7aefd9bf0eL, 0x21d245d9799db5L } + }, + { + { 0x6b034dcec08806L, 0xfd763f2b40f2d9L, 0x5e16de029cb906L, + 0x02b70148a0e16aL, 0x463c8eee071e12L, 0x644728125ad509L, + 0x9ee6f2ddc0e07aL, 0x188895c68d4d97L }, + { 0x092fff3b27f971L, 0xb3c159fc9b7722L, 0xe27d8ff3cae42dL, + 0xf8a5ed6e87071dL, 0x318388f607ebd2L, 0x924967b53486f1L, + 0x77304947c46e1fL, 0xf279c60f21d196L } + }, + { + { 0xef2bc0384f3201L, 0xf8750c71f94c51L, 0xbaa4f5a986ec65L, + 0x6f8a5de2732a33L, 0x0f13d80299e365L, 0x2709530e85261fL, + 0x097d922f527d56L, 0x4969687be1f3f8L }, + { 0x9f3f5043e1708dL, 0xac67b874aa4be4L, 0x75fb042320a87eL, + 0xa361ad36e2cad6L, 0xcb01470203e9f6L, 0xe3807b7c9b76c6L, + 0xf086833b907c09L, 0xe9bed3c7e85a01L } + }, +}, +{ + { + { 0xa7ea98991780c7L, 0x04e4eccd2476b6L, 0x0af9f58c494b68L, + 0xe0f269fdee64fdL, 0x85a61f6021bd26L, 0xc265c35b5d284bL, + 0x58755ea3775afdL, 0x617f1742ecf2c6L }, + { 0x50109e25ec556aL, 0x235366bfd57e39L, 0x7b3c97644b6b2eL, + 0xf7f9e82b2b7b9cL, 0xb6196ab0ec6409L, 0x88f1d160a20d9eL, + 0xe3be3b4586f761L, 0x9983c26e26395dL } + }, + { + { 0x1d7605c6909ee2L, 0xfc4d970995ec8aL, 0x2d82e9dcf2b361L, + 0x07f0ef61225f55L, 0xa240c13aee9c55L, 0xd449d1e5627b54L, + 0x07164a73a44575L, 0x61a15fdbd4bd71L }, + { 0x30696b9d3a9fe4L, 0x68308c77e7e326L, 0x3ac222bce0b8c8L, + 0x83ee319304db8eL, 0xeca503b5e5db0bL, 0x78a8dceb1c6539L, + 0x4a8b05e2d256bcL, 0xa1c3cb8bd9fd57L } + }, + { + { 0x5685531d95aa96L, 0xc6f11746bd51ffL, 0xb38308ac9c2343L, + 0x52ee64a2921841L, 0x60809c478f3b01L, 0xe297a99ae403acL, + 0x7edc18fcb09a5bL, 0x4808bcb81ac92aL }, + { 0x3ec1bb234dc89aL, 0x1e8b42e4e39da5L, 0xde67d5ee526486L, + 0x237654876f0684L, 0x0a583bd285a3ddL, 0x3d8b87dfe9b009L, + 0x45bd7360413979L, 0xb5d5f9038a727fL } + }, + { + { 0x7b8820f4bde3eeL, 0xea712ef24d5170L, 0x517f88cdf6ec7bL, + 0xb15cecf983ea9aL, 0x9eeee4431a4592L, 0x786c784ebb013eL, + 0x2f06cb31f4e15dL, 0x5603fd84f4fda1L }, + { 0xf6790e99e1321fL, 0x274c66a74a4c09L, 0xa4b70b49a41a4eL, + 0x7700bddada5157L, 0xe54a60d51be8dcL, 0xfaf92761a477e0L, + 0x6661c72b027eacL, 0x50e2340280b917L } + }, + { + { 0x635f40f96ec123L, 0x4a331337a766a4L, 0x9ce4416b935587L, + 0xbb6e1f595d97e4L, 0x26147239d4197dL, 0xabd4478490e896L, + 0xf6a1b2a8bba895L, 0x401fa405e27a45L }, + { 0x7354ba50620900L, 0xc443a29385678bL, 0x48aba1053cf5faL, + 0xd67e723bbe152dL, 0x4b858e02a63d68L, 0x174e1ee72be4eeL, + 0xad0fbb39ab8d46L, 0xa0fdffbce17dd7L } + }, + { + { 0xa1ea3259c46fd8L, 0xeca122e9fb96efL, 0xf9074a26767acdL, + 0x9b004a22787082L, 0x389f8077f3ba8eL, 0x6463de90d5aabeL, + 0xf30ceaab090585L, 0x71b31e85634ab8L }, + { 0x0dee65caf02aedL, 0x506886e20ac252L, 0x0665f7886b8a59L, + 0xb9b784df2bb328L, 0x46e443adc6b089L, 0x3d5de1966c27fdL, + 0x0419265f0fde70L, 0xed946122b5c034L } + }, + { + { 0x5a52ad213b0056L, 0x9fbeb92b909ee3L, 0xb42ba18bdaab08L, + 0xec127c4ffc8a77L, 0xc6d2985fda906aL, 0x5355547994bbe7L, + 0xa7470c09cdfd62L, 0x31a3971d2e675aL }, + { 0x8d8311ccc8b356L, 0xabb0bf801b4372L, 0x33c1cad0294566L, + 0xe2e649ce07b672L, 0x9084d882ae3284L, 0x7a90d4c1835ce2L, + 0xb4d1cd5809d44cL, 0x78227149f0528fL } + }, + { + { 0xca884cfbf5844bL, 0x9dd05c48524cf9L, 0xdbffa1936ba889L, + 0xef94fdd29e7666L, 0x358f81b3eaf48fL, 0x96734d51530d56L, + 0x378b2d14adf9e5L, 0x2f850464731f61L }, + { 0xd6ae90599dcb83L, 0xa4f89e06199239L, 0x64052498f0f958L, + 0x2866d99cc27707L, 0x64681a2f551c0fL, 0x2c7b0d04c37080L, + 0x218925b00ac301L, 0x8d57fb354df895L } + }, +}, +{ + { + { 0xdaebde0809c8d7L, 0x58c761c0e95ea1L, 0xbd9965000ae5e2L, + 0x6117a85cd51acdL, 0xc4424d87c55d56L, 0xe9b1ddedfbeeafL, + 0xda98bb50db4791L, 0xff3a5a63fca108L }, + { 0x172fb8e5ccbea1L, 0x9fe12a7a9f6cc9L, 0x1de4b0b8967ce2L, + 0xc1ab60f671dbc6L, 0x338385a5dedcdaL, 0x647a4203a043feL, + 0xe9abc6428ebc89L, 0xc357ff003ba3c8L } + }, + { + { 0x37061e7de39ebdL, 0xebb91352be567aL, 0xa9a6f6bd6bb80aL, + 0x039345d99f0ba2L, 0x215494e98bbf47L, 0xf2cb7a4a2a1ccbL, + 0xf51aa1037f67c9L, 0xd29c85c17fff71L }, + { 0x8d4e4f24d30b87L, 0x20fdf5593a8309L, 0x9b9f9cf757075cL, + 0x09142adcd70101L, 0x901d0ee766ca55L, 0x6a5d86a32e418bL, + 0x550ad92d7fcaecL, 0x64e8818d91b26eL } + }, + { + { 0x5cea0f747e5ee5L, 0x8ca1d31be99699L, 0x52db8465c136c7L, + 0x8cecb3890e0d74L, 0xb8efe9dede2ad8L, 0x18d6ff8f17ade8L, + 0xd2227352d66c20L, 0xc46593ef2005fdL }, + { 0xe5ebe6ff7141e1L, 0xc968315e0126f2L, 0x95adc731cb91b6L, + 0x753b54c38a6003L, 0xa6141254230a61L, 0x23ac6eb559feceL, + 0x9816b603865c23L, 0x567014e543a570L } + }, + { + { 0xd46091ddd2b71fL, 0x3999a5d97d24ffL, 0xce2a4f11ecff3cL, + 0xab2687c581c6f0L, 0xa9fb2ebcba70b4L, 0x6fde35642093e1L, + 0x00253ecaee724aL, 0xa08ce3c2b81bddL }, + { 0xa251238935a2b3L, 0x8cae1d4584f750L, 0x011469e988a219L, + 0x61f7ed35a6a50eL, 0xe13ebaa01fcebdL, 0x794b97631d8867L, + 0xf25755ccda32e7L, 0x368a97b4564cd1L } + }, + { + { 0x0d22224aa3397bL, 0x1dbb3e638066dbL, 0xfe0b5ee0ce8e32L, + 0x09c17c87bab4dcL, 0x5cc65ddf188b64L, 0x74c4abf211b5faL, + 0xdcc17b7ab0ba86L, 0xfbdf46fa535501L }, + { 0x4775087aca569eL, 0x6575f9006a1718L, 0xb5c45a9b94de93L, + 0x0fc80068497171L, 0x775d965489f7abL, 0x8775b58f5c0c89L, + 0x05d4e201a06254L, 0x8cab349b6d73a5L } + }, + { + { 0xca7816339465b0L, 0x3ef914814498fdL, 0x9ca1f346255c11L, + 0x389fd15b7f38f1L, 0xdac2089354b8f3L, 0x82d07fca840a70L, + 0xf53fd731dd483aL, 0xa6e4eae1590578L }, + { 0x7bf65af3c01b77L, 0x27542f3a75c982L, 0xc5bd947716cfceL, + 0xba5fe76884b9e7L, 0x39bae14d55725dL, 0x982f64efae0eabL, + 0xcfae6627a5293aL, 0x22a25a1d60f464L } + }, + { + { 0x74caecc7dd5e16L, 0x23678a2ce7bca3L, 0x467393257f1ba1L, + 0x4eb9948a4c1697L, 0x5d400e8eaba18dL, 0x128d1c89807871L, + 0x78f9627bff38a6L, 0xf80b813a39d4ccL }, + { 0x8aeefa031d3aadL, 0x504219927db664L, 0x244fc694cb6383L, + 0x319047772192a3L, 0xcc86075bbfb57bL, 0xbae3a134451511L, + 0x16cf416f6174f0L, 0xb343cc0d376813L } + }, + { + { 0x31ac9b9d1824b7L, 0x6282260ec8f61aL, 0xbbeb9f8c781765L, + 0x06ab5c02d110daL, 0xd583e2247146b8L, 0x79a16084100d05L, + 0x16dbbb4f0a5c95L, 0xfe2af1de331667L }, + { 0x26f0364af8710eL, 0x1cb8c91eec08feL, 0x436bce61d95e9fL, + 0xfe9050c57944a0L, 0x5f45acf07b626bL, 0x48dc93f9cf1276L, + 0x4491371a05bfb7L, 0x51063044bcf785L } + }, +}, +{ + { + { 0xac2e294ed0b3b6L, 0x5c5ade6671637bL, 0x2f289ce1140677L, + 0xaf446e2754eb53L, 0x70911b720421adL, 0x4b73836e0b7556L, + 0xcadf1042a97827L, 0x4824e498005bc6L }, + { 0xb0eeccd937c28aL, 0x1ce061d0c3ee97L, 0xcb076319f33faaL, + 0x9980bf4aea66dcL, 0x2bd0755d111d98L, 0x43feaf67fe4de0L, + 0xe76fb80b077b2fL, 0x227dc9f5793b04L } + }, + { + { 0xea24ae514f49baL, 0xbc39ea611436e7L, 0x9d7fed278485d8L, + 0xb6ef00cdf8b131L, 0x0237b4bfdbc7afL, 0x08745b564ccd27L, + 0xaf8595dafc5a76L, 0x43657af29f5500L }, + { 0x300718348470f8L, 0x51f91fd640fd53L, 0x859c807be15512L, + 0x7d1a474ab3e9c5L, 0x5d714d981553e5L, 0x07573436f62310L, + 0xedc5be06b02a62L, 0x5a4b9b7ea47832L } + }, + { + { 0x03e0a24e93dbb3L, 0x25841dccadc884L, 0xabc1a818d10ad5L, + 0x207e38a2042dddL, 0x7fffbdbfeba8d8L, 0x74efebba3ec9b5L, + 0x0bc39ca0b40a9fL, 0x69ee9c90267febL }, + { 0xd402facbc62919L, 0xe9f8fc11cf53c6L, 0xe76fa5a7cc7d81L, + 0x4f2d87696bb19dL, 0xd4fb7f9adc67c7L, 0x40621d596702dcL, + 0x5b6a98e438f6c5L, 0xa7c64def1a1036L } + }, + { + { 0x84c5e809a092c7L, 0x9e40e0a11c22b7L, 0x820a091d06c99bL, + 0x45fdc77eecca8fL, 0xfe1b8a35794f16L, 0x31f7e5b4ce3d6dL, + 0xfd5e01082c74c8L, 0xfdabf30c1f6f7dL }, + { 0xbfa6017b9248a0L, 0xe898d30546b941L, 0x878c492207ff65L, + 0xbf22e8db874e64L, 0x43fdb1b53a547eL, 0xb66deda5fbd464L, + 0x59127a6c7ae1b5L, 0xa4636466a7515aL } + }, + { + { 0x22c4e66de9ab2eL, 0xfaf60c20203c58L, 0xed2d7bf0d5c5edL, + 0xdbc16fe4ca0f19L, 0x54e8ef6465b979L, 0xe2d64b1a310ef9L, + 0xa0f2c953778636L, 0xf3b4aa4281883bL }, + { 0x4ac9af09be6629L, 0xba455e11ca90c5L, 0x0147538856f492L, + 0xc80db7eabd7840L, 0xb3526d96beb9cdL, 0x37657fb9d81503L, + 0x8729a16193cec3L, 0xd9a93fbd69952aL } + }, + { + { 0xfce017594f47c6L, 0x228da21e366d05L, 0x27ce0b2dc8baf3L, + 0x8cc660b6b4a951L, 0xf678947384bb01L, 0xc629d7d44d980cL, + 0x47980e4e85e81fL, 0xa2e636a1cd723eL }, + { 0x6b6ebae77fb207L, 0x70179614c92891L, 0x5569541b4d279cL, + 0xbb6b36a41758cbL, 0xecaa22227a8e30L, 0x8b6746ab470ad9L, + 0x4c4601763e2d3dL, 0xe19c4edd3edaecL } + }, + { + { 0x0b43fec34718c8L, 0x553c407f33499fL, 0x8272efb970d1dbL, + 0x008c62ca8e8d1cL, 0xe4b79d763eec45L, 0x1fd4230f2d71a3L, + 0x090fdafa368c36L, 0xf62c101fca7baaL }, + { 0x1c9e6c8d2395b3L, 0x671ed6304c5513L, 0x577d933299a465L, + 0x286890e63f9986L, 0xd92a95dbfc979cL, 0xcebd79d2b51019L, + 0xe74d88b3d07251L, 0x8b6db73906f9adL } + }, + { + { 0xc0c43db7b3d90cL, 0x85d154e4304a06L, 0xe8aceefaf2f38eL, + 0x5e0429383d9459L, 0x65e5e32431afd1L, 0x9e5f050a900a65L, + 0xcbaa1718a26671L, 0x33d0b249c93de7L }, + { 0x3dcbf92d5b6680L, 0xc47e5ec20006f9L, 0xc9711299a51924L, + 0x665d9b8cd0ed46L, 0xed2d63fa5fcab6L, 0xa817eb6cfbfc5aL, + 0xb38169fb76eb76L, 0x8b93544f11160bL } + }, +}, +{ + { + { 0x02eca52693bdcdL, 0xbbf09232ae01d6L, 0x0b0a2de8b44b3eL, + 0xdb82449b250dffL, 0x0c42b866e1c530L, 0xcd226dca64c2c4L, + 0xcfb2bb1f046b5fL, 0x97e2fae3fccb0dL }, + { 0xdf9290745ed156L, 0x224dcb9f641229L, 0x2126abc5f1f67eL, + 0xa7eed5ae9c8a6bL, 0x40abedc9857d9bL, 0x3f9c7f6de941c6L, + 0x2158d42d725ddfL, 0xbdd10158c69543L } + }, + { + { 0xa7dd24e8df2fbcL, 0x3adbcfd13d1aeeL, 0xf6a32d113b2177L, + 0x89a72327a9a14cL, 0xe3aef43dc65df9L, 0xeaec3e3a64d74cL, + 0x4d387d84fec33bL, 0xaba2a0521a2128L }, + { 0x2382c226b85e30L, 0x4352d85cd2aad3L, 0xb0c6001d9772c4L, + 0x7ed82635f3653fL, 0x3626a6f0300f47L, 0x23909de6ca7e4eL, + 0xb43dd81c154141L, 0x9a49fad7e4bc68L } + }, + { + { 0xa3661df2428f88L, 0xbe48b0256e0db2L, 0x3cd1871ce79aa9L, + 0x90ab87123dddacL, 0x9c58fb971871a6L, 0xf031f7fa34910eL, + 0xb501eea81060e4L, 0xdb668ba791224eL }, + { 0x240bbcb6a705bcL, 0x7e76fbd2d1865eL, 0x6e2cd022513641L, + 0xe6c522546365c9L, 0xe46a8b8a5a01fbL, 0x696fa7bb67618bL, + 0x418b3b90db6792L, 0x7204acd7108b9cL } + }, + { + { 0xb5a143b8456b45L, 0x8a3ab25f53b4d9L, 0xb112a58e13a570L, + 0x613ca3281487d2L, 0x837d8233b1e7c9L, 0x592baded41e9d5L, + 0xdc1893a5cd02f2L, 0x08795028972e23L }, + { 0x7003c08cb76261L, 0x14bde9e332a5e0L, 0x14b2872cbbd78eL, + 0x5594061de238e8L, 0xad12645067466cL, 0xa8d0e64f5e4952L, + 0x5b44b82c7f8d06L, 0xb51bea8fb1b828L } + }, + { + { 0xebad6853f0daccL, 0x5c31b8b1cbebbcL, 0x6746975fa5a2dcL, + 0x2d9596531d9faaL, 0x343797d00fc0e4L, 0x38d821c55fe01bL, + 0x0bfdb247323aa0L, 0x42613c4f962a8eL }, + { 0x599a211e134bc0L, 0x75fa4a147a7084L, 0x6e719487f734b5L, + 0xd5ced2d6dfca2bL, 0x9fa0fdc8aeabd2L, 0x5e6b03f12361daL, + 0xad23d315859fcfL, 0x3120ef125a5fc8L } + }, + { + { 0x990ef628e9f638L, 0xfdaa240626a60cL, 0x4a3de202abddabL, + 0xd5d10b7d8872b2L, 0xa01b7301ea5880L, 0x481697fa81b9d8L, + 0x29841533471ed8L, 0xefd73f8292d37cL }, + { 0xdda76269994bebL, 0xa0377036a4f865L, 0xda992ece5b47d5L, + 0x912a427e53edbaL, 0x64675989264e45L, 0xd3b68c3af71222L, + 0x9d3436c6dedc5fL, 0x1e027af076b2adL } + }, + { + { 0xd56fca14382f4aL, 0x83712a48966b7bL, 0xd6b2cf5a4c9ddbL, + 0xa66be29f602875L, 0x70e4266894f3d0L, 0x007d220b3195caL, + 0xba38d8f82c74d4L, 0xdccc5fcd975cbdL }, + { 0x03e1610c88b38bL, 0xeb9f9a152e0d8dL, 0x6a57ecab646eb7L, + 0x161641fc76b6c1L, 0xf9025adbd2e12bL, 0x87c74db5c0e26dL, + 0xed5cb51bfeca74L, 0x603dfb6e34a08cL } + }, + { + { 0xc4be728cb03307L, 0xde34c0ec2741ccL, 0xe01db05a74eb17L, + 0x1bfce0c8905e4bL, 0xb18830ad1b1826L, 0xcacbb41e87bbfbL, + 0x8696842d2f1a79L, 0xa80e5fb08c83eaL }, + { 0xe48f1633f1439cL, 0xc1d4108cd6987bL, 0x05705c4b751814L, + 0xa9bffd0c1c622dL, 0x23de4af46cd053L, 0xf782f5e39457c3L, + 0x815276b5e5d243L, 0x31320416161ae3L } + }, +}, +{ + { + { 0x245966177f2542L, 0x203be7e8372b25L, 0xc7c9426ee2007bL, + 0xc5641380621799L, 0xda56589c28c3ceL, 0x13e8a7c7afc1e3L, + 0xdba81e9e352082L, 0xf43054904435c7L }, + { 0x4d26533691de4aL, 0x364408cfb777abL, 0xccdfb43eae7f88L, + 0xbc40f44a525b11L, 0x8e112a53c60627L, 0x7f7c581e17e696L, + 0x0fd78781ea774aL, 0xd09e6320b1f582L } + }, + { + { 0x44390bd70aab15L, 0x41112bc889c3f2L, 0x6b02894d685349L, + 0x71030015584dfeL, 0x373cb1b1ba7887L, 0x53d286c2a017c7L, + 0x2ed03883c81fdcL, 0x3bfc5e3fbcc6fcL }, + { 0xd38ac6ffd6418dL, 0xc667e96bfad89eL, 0x46f4f77eab4d66L, + 0x194c04f0911293L, 0x0fd09cf68c48d5L, 0x6f5b05563cf7f4L, + 0x0c0a8c4acd562fL, 0x94c1d8336d965dL } + }, + { + { 0x94fc8f0caa127aL, 0xc762d5dd803690L, 0x8bfdfd11ebf0d3L, + 0xa98cdf248eac50L, 0x3d7365d8b5ff10L, 0x20dc29bc65b4deL, + 0x62ac28e8ec7c68L, 0x7f5a13290372d2L }, + { 0xf3d8a253246658L, 0xa4bebd39ac202aL, 0x078ede75cc1697L, + 0x5525800c8fc022L, 0x302a8025fae77bL, 0x018013957917b6L, + 0x7c8806d864bf55L, 0x4e2d87812f06f1L } + }, + { + { 0x8d351183d66e88L, 0xfb861a1a91d02aL, 0x8c27c2a7850e5fL, + 0x9fd6399a5496f6L, 0x52152ae8080049L, 0x600e2fffd1c2dcL, + 0xc75902affe8b2eL, 0x5c4d2cce03b175L }, + { 0x8ad7c424f57e78L, 0x77cf6061736f87L, 0x2876012f85038aL, + 0xff328451b97b95L, 0x3cc6dd5392dfc8L, 0x72f1363a6f5075L, + 0x028ec4471de894L, 0x7030f2f6f45a86L } + }, + { + { 0x66400f59695817L, 0xeda0a7df20ea36L, 0x855be51d394992L, + 0x2d082c18336f62L, 0x30944ddf28c868L, 0xfb5f8530dc86d0L, + 0x9562ae5564a0bdL, 0x1f7ea12b6b9b51L }, + { 0x5bd74e0d0a7148L, 0x6c8247fb91e572L, 0x699aba547da498L, + 0xed825811f7c814L, 0x434674b62057b9L, 0x8b4df5e15c15b4L, + 0x2a97da1b110081L, 0x2a96b0c4c417feL } + }, + { + { 0x4f75dfc237639dL, 0xe5ad6bc1db7029L, 0xd43e06eb3d28f7L, + 0x89f3bb5e447989L, 0xc426a2c01a1a6eL, 0x33ea71c315878fL, + 0x8a7784ab1b5705L, 0xa59e86e77ca811L }, + { 0xddb133c36ae155L, 0x49f1d4c0d51b42L, 0x55080829d05519L, + 0x20e23be5291816L, 0x35047ec67181ecL, 0x6237dc47aad091L, + 0xa1d3ce1e2e25a2L, 0x1de05220d3db4cL } + }, + { + { 0xe9a5e19d9fd423L, 0x0c2c3d09801e43L, 0x043c2dd28df2daL, + 0x4eecab4e1ad12aL, 0x97e17979615aa5L, 0xe57b879ca7bb5eL, + 0xa2a903ccc92619L, 0x5cef370aa56e93L }, + { 0xbef29fa7f3232cL, 0x1cf35ed2b7ad5cL, 0x35c48933b6077aL, + 0xe0651487a1d47dL, 0xedb4673ce14572L, 0xdc9e98c0b17629L, + 0xef98ebe9a02a5cL, 0x1f772e311d03c0L } + }, + { + { 0xcbdbdcd4608f72L, 0xb4352235a13c6fL, 0xa6497f64bb3c21L, + 0x3af238312c15c9L, 0xfbbf4b36322d11L, 0x520a5c6c641775L, + 0x18cd967e81e0e1L, 0x980b2c63de3871L }, + { 0xfa9db619ae44a2L, 0x0281dd2176bc56L, 0xfd037118a7f817L, + 0x9c485454129b30L, 0xb439648039626dL, 0x355050ee4ada6bL, + 0xc9c16d67f5d98cL, 0xf53ccc318c4d5eL } + }, +}, +{ + { + { 0x50ae9423ffb20bL, 0xa6c0b426865eb4L, 0x4677f7d09930f1L, + 0x742e0b64a16427L, 0x521d18ef976f9aL, 0x43ac9cfa454749L, + 0xda3a91dc51f50dL, 0xf657029ad6f954L }, + { 0xfe5f0646b4f99aL, 0xd92a5d963ad4ceL, 0xfcb55092e0e081L, + 0xadc85ab8d8a858L, 0x8e9b9660632f0fL, 0xe7a4f168d7216dL, + 0x00a4cc559c3b99L, 0xed6d0bdba09dc1L } + }, + { + { 0x7236d141621bebL, 0x1751fd4bc7ca95L, 0xaa619d12f5319cL, + 0xfc2b15b4e9316fL, 0x2d1a9069fd4d33L, 0x28c3bac8ced829L, + 0xf2efab51dd998fL, 0x2c133303b149edL }, + { 0x65237c9f601ac6L, 0xb54dd6507d6a45L, 0xa1ce391fb1a4cfL, + 0x2957533115f67eL, 0x6456da8465279bL, 0x02890aaa993e02L, + 0x6891853b7175e4L, 0x3fda2030f3e59bL } + }, + { + { 0xe99fe12d8c6e0bL, 0x7cb07ff5341c56L, 0xc292c7bdf77b24L, + 0xf52dfd0ca29906L, 0x4a6aa26772f02cL, 0x26f7684e1bbd09L, + 0xec56b2bee7c2a8L, 0x67709e6ad4a312L }, + { 0x99c57b2c570263L, 0xeb0100b2faafaeL, 0x980d5d1ff25ecaL, + 0xace35e682cf936L, 0x5a82ce544679edL, 0x5c76a41074b81eL, + 0xf36fa43a00abb1L, 0x064281904ffb2dL } + }, + { + { 0x68f6bc804bdd28L, 0xc311d96b5dc7adL, 0xff0d646ed32e45L, + 0xaf3cdc6e0f712dL, 0xd4508e9d483861L, 0xb624be50e1c277L, + 0xc510275c5dd841L, 0x451c5c3298dc02L }, + { 0xf87d479dd34d6bL, 0xda7f293dd06a38L, 0x575e129b699e9fL, + 0x79e5fb2215b2ccL, 0xd280028657e690L, 0x7fecd09e702a71L, + 0x85160abfa13677L, 0x5de3427ce65f64L } + }, + { + { 0x84e4bf6e8fff38L, 0x16f3725b358b1cL, 0x360371c3b472a5L, + 0xe64c06152f217aL, 0x8e673790501241L, 0x88e81d6ab2dd96L, + 0xf3e218a1385604L, 0x9736cafe84184dL }, + { 0xb55a043dbb93a3L, 0x335088f9301088L, 0xcea7a2db2a4959L, + 0x48e5d4ab882c33L, 0x114f09bad46179L, 0x4416467b446576L, + 0x01cb23e34c6c2fL, 0xddebf04a02db8aL } + }, + { + { 0x36d60cc9bde8a1L, 0x20fd2f2676e4adL, 0xebdcfb78936581L, + 0x245d0d5dbfc2c3L, 0x104c62ca9f82e5L, 0x7387457d654d9bL, + 0xe966777ae7f10eL, 0xefeb16f1d8e582L }, + { 0x4faf4f170364b5L, 0x0e1ab58d612472L, 0x11bbfe7fed6085L, + 0xb360a14a59a09aL, 0x61d96e9722fdb6L, 0x16a12f194068bdL, + 0x225bf07f73c2beL, 0x1e64665c8bd24eL } + }, + { + { 0x27a478a3698c75L, 0x778ccd36202aa2L, 0x0149c638d87f1fL, + 0xa660e5f784edaeL, 0xe0d4d2f82adfa8L, 0xf512dd61ba1f9dL, + 0x90cfed96245c58L, 0x6c3a54818b53ddL }, + { 0x833f70cbdc094fL, 0xa5f26f5b1514e7L, 0x93e7cf51c8cf13L, + 0x1436601186ec43L, 0x81924ace78170aL, 0xcc880a08694368L, + 0x2dfa9550b62cbbL, 0x0bc6aa496b4a2cL } + }, + { + { 0x5157a7e3561aa2L, 0x525c5008645c1eL, 0x22feb4ece7cbb3L, + 0x36d0d25c89a58bL, 0x43131f7c9bde9cL, 0x74afdda881f731L, + 0x99ab87c7c8e36aL, 0xf07a476c1d4fb2L }, + { 0x1b82056bebc606L, 0x95a1e5afcf089fL, 0xc5bccfa2b55d5cL, + 0x8fbc18e00eb0b1L, 0x93a06fe9efb483L, 0xcafd7252d74c57L, + 0xc7518f03de4350L, 0x9a719bfc6fd762L } + }, +}, +{ + { + { 0x5ee0d832362087L, 0x7f2c0d70b167e8L, 0xb7327895e0e865L, + 0xef5b2e898c4e65L, 0x222797d8fe9cc1L, 0xfe6d73e82d1e15L, + 0xc7c0e9cf62dc4bL, 0x962acfe937cedaL }, + { 0xd763711c1e85c7L, 0x8f2dbbc2836978L, 0xbadc0558c44e98L, + 0xed63eaba3e93f8L, 0x807e85741b55c7L, 0xd51ae5e6d1207bL, + 0xa0ef9a639d541bL, 0x58855f9a0c56a5L } + }, + { + { 0x7d88eaa213091dL, 0xcbdfee745b6a0dL, 0x826a0124f5e077L, + 0xb04fc1390f1e4cL, 0x1961ac3aea69aaL, 0x3afb719d5bb63eL, + 0x2a378374ac7e5cL, 0x78efcc1c50ca45L }, + { 0x346e8f0b8abdefL, 0x27e3dbd88095d0L, 0x56d3379ffc6c22L, + 0x67d416cfa4b291L, 0xc3baaf63b1b373L, 0x0184e1fdf73baeL, + 0x38ae8f79167528L, 0x7329d4c35d6297L } + }, + { + { 0x45d2ac9f568c52L, 0x51348149808593L, 0x0c92d8331b7ed8L, + 0x921327a0876ecdL, 0xf752d75052736aL, 0x7b56487bc6b837L, + 0x6b1a320a23b4ccL, 0x1983937ec0d665L }, + { 0x2c3017c08554abL, 0x40ad955366e87fL, 0x88c4edf8ed7f02L, + 0x64a7db13cc5e6dL, 0x5ac91fa2dc978bL, 0x016a20d925d2a2L, + 0x3604dfeabb57b4L, 0xc3683ecd7e2e85L } + }, + { + { 0xc47150a4c0c6d0L, 0x30af45ee22adcfL, 0x39b5acb022ea4bL, + 0xfbe318577203b5L, 0xe5aaa346fd9b59L, 0x0062c90dd1c8dcL, + 0xcf113f354049acL, 0xd8fba4d63a31b5L }, + { 0x73b54881056a69L, 0x3be6cbcd780bdaL, 0x5776ec230ba2b9L, + 0xbe883cf8e8d6f7L, 0x64efe945c2be6fL, 0x064f704f1ade8dL, + 0x41cfd17743110eL, 0xaac94114c20abeL } + }, + { + { 0x91f9192f1c1468L, 0x8176e744563e13L, 0xa48b5f90bda15dL, + 0x2a085aeda42af6L, 0xfd38ab2425c018L, 0x2884ba408abafbL, + 0x356f318cbd091dL, 0x454e450817871bL }, + { 0xe080e818ada531L, 0xa40f1eb3152ba8L, 0x051049f0c38eb1L, + 0x37e4bb3bd45003L, 0x6d0980454a01e5L, 0x6de932feeb824aL, + 0xccdef37dc93481L, 0x8633e0793a05e8L } + }, + { + { 0xbe94256034675cL, 0x376c01d08db789L, 0x8707ee79af1b6bL, + 0x633b3ef11bfbacL, 0x694f33fd06db60L, 0x2a68bfcbb13407L, + 0x1c860c9da27c3aL, 0xbca16ded701ac3L }, + { 0x2b76cfac59ffd0L, 0xf9a116554d718dL, 0xf86a1db67f0878L, + 0xe313e05af34e85L, 0xa1888113343159L, 0xdbe4c3f0bb7ed1L, + 0x73b67e80c732bcL, 0xa4e1c87e74110eL } + }, + { + { 0xce1106b5c6770cL, 0x422c70b5c0bcb7L, 0x32a39908195e7fL, + 0xa24968d1ccd4aaL, 0x8f08ecf720e557L, 0x5da10a454bcc81L, + 0x9d3c73b6cd846eL, 0xaeb12c7368d065L }, + { 0x2110859cf9fd1bL, 0xd2a4801ee2bd6dL, 0x376e556e9466acL, + 0x767803b3b5aa35L, 0x343f842b8a89baL, 0x3263cc16726bbfL, + 0x26caf1725871b0L, 0xef66ad641b8578L } + }, + { + { 0xc9f2249638068cL, 0x96d282c1ccf9afL, 0x71df30c69b435aL, + 0x88c943acb9d5c9L, 0xbf98ef12a8f378L, 0xffc1824114c6ffL, + 0xda3ad2cd52e8c7L, 0xf1222bc1afcb59L }, + { 0x459e94b0ee334aL, 0xd4477b8421933aL, 0x60fb7b0a1e401eL, + 0xfde6e820d1e330L, 0xcecfe9b3233fdeL, 0x09ec4662e93523L, + 0xa5ba64930775b9L, 0xcc397e5adf80f2L } + }, +}, +{ + { + { 0x2fe182d4ddc8a8L, 0x88d6e79ac056bfL, 0xc3ff2d10e41e4eL, + 0x32ec7f92c3679fL, 0x3561f094e61051L, 0x4553f5a6c6250aL, + 0x2b765efdd25c5bL, 0xe3a40a26a1cd7fL }, + { 0xb27309b5d821ddL, 0x950fb8dc2c17caL, 0xfeed0158fb0d4cL, + 0x762c479f550179L, 0x306cf44e095840L, 0x84b413ad379e66L, + 0xd6e5d5abb2e4f1L, 0x8bc12b794b085dL } + }, + { + { 0xc0d4cb804b5532L, 0x7a31525b9940a6L, 0x010e7dd68c69d1L, + 0xd81f29d2a18c35L, 0x08ae7703f11e73L, 0x5358f876e55106L, + 0x299e8cac960ef5L, 0x89a6fb4acfc8dcL }, + { 0x5996a406dc7d4aL, 0x21e5112e51b96eL, 0x95b8c3d09a202bL, + 0x306ab0fd441f1fL, 0x2834fed98d4245L, 0xc29c387d0abbdeL, + 0xf6a9bf1b805c15L, 0x602f4f8c4e458dL } + }, + { + { 0xf041486e5a893aL, 0x53b891d8934327L, 0x11e000d4000758L, + 0xa4ccde8662bad9L, 0xe34d3edb9a1b64L, 0x72d967584e7a6dL, + 0x773da2f6627be4L, 0xa11c946e835ae3L }, + { 0x02e8203650bc15L, 0x2d35936e58b78dL, 0xe9cfbe8f21a3ccL, + 0x55ad8311049222L, 0xbf99de438fff47L, 0xebbfd803831db5L, + 0xe990636af2af42L, 0xc26ae52b7f5a0eL } + }, + { + { 0xb5d85b1fa8f846L, 0x4166489b3b1455L, 0x768260dd36a305L, + 0xc6a82354ff5645L, 0xd241cd8d6e93e5L, 0xeed9aa1a406e74L, + 0x9e96ab05f600d9L, 0xa26b8b56eca2a1L }, + { 0x78321cfd705aefL, 0xc4fb6b3c0161ecL, 0xdc324415199cf1L, + 0x33627d0d0a5067L, 0x13490cb15143eeL, 0x77e0ede85b4f44L, + 0x904f12e394b165L, 0x90f50f5efab32dL } + }, + { + { 0x4aa0a16bc2de96L, 0x172596aaa9c12bL, 0xd512e1e60e8a29L, + 0x77d35c1f637e83L, 0xbb0d141d2aae0bL, 0x8a878a58c03738L, + 0x6d24c01ab0e525L, 0xb7d3136f760887L }, + { 0xdbc3f8f3f91b7cL, 0xe7b4bcaa8722c0L, 0x3286a91da0ae65L, + 0x8372274225b084L, 0x5884cd5ae1886cL, 0xb4e63ef3a23cf7L, + 0xfe5f202f2dd0daL, 0x951fac9653916cL } + }, + { + { 0x05e2e8f854fa4eL, 0xf411f941edaf10L, 0x26cc562a0a928dL, + 0x78fd34e4abce65L, 0x1d8760998a32e2L, 0x85dc76f4c37518L, + 0xdcaeef500e8021L, 0x7fcb2f84e9b2a5L }, + { 0x9eba91ef382c06L, 0x2052e8524cae53L, 0x617336ef5c1519L, + 0xf1546d5b4e632bL, 0xa9edc81d7b8ffdL, 0xdb2914f29ab68cL, + 0xe805070debbabaL, 0x775e53bc3b719eL } + }, + { + { 0xa40e294065256aL, 0x9f113868fb031aL, 0xac03af8059667cL, + 0x432eb3a0475f58L, 0x22332bf01faad0L, 0xc8132e9bc57a11L, + 0x27d5a173bc3f8bL, 0x5471fc6930bf3eL }, + { 0xba28bc0e6bff40L, 0x198d57e555e564L, 0x13ce8319c65b8fL, + 0xb0a5c9d5681b51L, 0x467588bdeb9e11L, 0xf1891a7bb4250bL, + 0x10b938bd12b433L, 0x0b8c80224dcda4L } + }, + { + { 0xc428703cf332d3L, 0x9d0053cf2a5b98L, 0x4e4c6207838a15L, + 0x2e92919fbf8a43L, 0x39ad52421cd9a5L, 0x584ed6c1561588L, + 0x20af30517a95c8L, 0xa223077b70e1c8L }, + { 0x679cfea2fa4871L, 0x54f2a46ac633c7L, 0x60306514cdc5f1L, + 0xc4facda75a1dc7L, 0x710a2882d07d19L, 0xd55864e6b44992L, + 0x44d4b6c454c5b2L, 0x2855d2872f9981L } + }, +}, +{ + { + { 0x4071b3ec7b0674L, 0x800eb14f8794d5L, 0x70573afbe6783eL, + 0xafaa4407785901L, 0x112d2a1405f32cL, 0x3761a52169b3e2L, + 0xe168b31842a366L, 0x5bc322f9bf4734L }, + { 0x36ef240976c4a0L, 0x066f3d6fea4e64L, 0x0e954bda989e57L, + 0xe36ef5ef9466e4L, 0x6bb615abeb9226L, 0x5571e5f3d5a2caL, + 0xa86efe24897a86L, 0xed7e9cf28a9f77L } + }, + { + { 0xdf10c971f82c68L, 0x796ba1e3b597e6L, 0x1ac77ece718cbfL, + 0xc8175bb410eac8L, 0x0cdf9a1bc555efL, 0x6b889f17524e05L, + 0x6bf1e61ae26d82L, 0xb3f6ad5d2e97d9L }, + { 0x94dcff9f226487L, 0x60e6356be03ddeL, 0xda1f93b6a3dd7dL, + 0xf1be72179ca90cL, 0x05ed3131e6bce5L, 0xcf50908d48af3eL, + 0x3b0e85c61e554fL, 0xfe7e35ba2778d3L } + }, + { + { 0x42c503275ac5a9L, 0xa66a66dda062c2L, 0xa4f4f82caa7023L, + 0x489d47664b4f86L, 0x10b108897311adL, 0x55dd637177b2ecL, + 0xa5ccff09a267b1L, 0xf07690bff327b0L }, + { 0x39162ed2250cd2L, 0x1426de08b255f1L, 0xf227afd1bdd731L, + 0x78f8a36fa4c844L, 0x267a211157379cL, 0x3f05f92cc04acbL, + 0x374496cfc69caeL, 0xbf2c5d016ebfecL } + }, + { + { 0x605418bd0518d1L, 0x3237f809e1cbc6L, 0x37a7005286c019L, + 0xf1fb0e0b15af0bL, 0xfc3b97caa853c0L, 0x1f48bd0e6beba2L, + 0x8e5d7c5e6a72f1L, 0x575e66d26ebf0cL }, + { 0x099477662eae3dL, 0x53f074f96c9c65L, 0x6cfbfdbb81badeL, + 0x98b4efe3fed7d1L, 0xdaa112338c3382L, 0xdf88b7347b8ec6L, + 0x9b0fe4b9504a4fL, 0x2e7df4cf30c1c3L } + }, + { + { 0x25380cb2fc1833L, 0xb8e248c18d62deL, 0x91c8f59d82f9dbL, + 0x5ec2b202444750L, 0x3f3a1f766b6f74L, 0x0180aa9dd7d14dL, + 0xd0a342d2956b9cL, 0x26e910e7139873L }, + { 0x2261dc4139e23dL, 0x7edb181b8343ddL, 0xfcf1073b4038ddL, + 0x88870efa3bfea3L, 0x4e98ba964a263eL, 0x3c6e5dc70811f5L, + 0x17d28f5f86055dL, 0xca9c27666e4199L } + }, + { + { 0x0b2d8bd964ef8cL, 0x5a99b8588e2ba6L, 0x9e927b204498ceL, + 0x9ff20c5756eb25L, 0x97cc27b3f27736L, 0xf32dd6d4729583L, + 0xbdc26580381a94L, 0x70fef15ef2c06fL }, + { 0x50a619149252ccL, 0x9eb4a14236b4b9L, 0x9b1b2158e00f78L, + 0x27add366ea9c23L, 0xef61763c3a8e79L, 0xed4542fd82ce56L, + 0xa8737e70caed75L, 0xeca0ac2d452d76L } + }, + { + { 0x20c07793d082d0L, 0x6e3ce64c9e9f3bL, 0xb3a4dce75a195fL, + 0x3a3c305bdd9f24L, 0xe2545c88688942L, 0xa463c82080f32bL, + 0x442974842686b8L, 0xf50e20d7213866L }, + { 0x265ac523826e74L, 0x26fba57228e8ecL, 0x8a1e1dbe6b3ed8L, + 0x7c7b278f0fe65aL, 0x9a6df23c395234L, 0x99562060b0f114L, + 0x440c8c4ef90837L, 0x21ad22a3645f65L } + }, + { + { 0x1e023a6edd31b2L, 0xf76d1459ff8668L, 0x970705617b45c8L, + 0x06120781e88e37L, 0x85c51c8922faacL, 0x4df392e22756d9L, + 0x8907fd0a03c98eL, 0x626f46a52ea51cL }, + { 0xf8f766a486c8a2L, 0x8c499a288ed18cL, 0x44d2dc63c4f0deL, + 0x47dde686f2a0b6L, 0x9a655f84a973fdL, 0x3e7124e786ac80L, + 0x699e61ce8a0574L, 0xdf0ba9a31cdd0dL } + }, +}, +{ + { + { 0x76270add73e69bL, 0x991120fc67d38aL, 0x7be58309469f0cL, + 0x93aba597db40acL, 0x2b707bc822fc08L, 0x4199fc069551cdL, + 0x38deed4f367324L, 0xca518e12228787L }, + { 0x72f1befd9a9277L, 0x57d4aabe49ae90L, 0x13810d5db23478L, + 0x2a8b7809b4b77fL, 0xb542f4e1b4e004L, 0x4080fd03ec77f0L, + 0xb49e9fecec6596L, 0x20338d33f16037L } + }, + { + { 0x4adcdae53554b0L, 0xfea4906e04c4dbL, 0x0808bec7748233L, + 0xde7477c47148d7L, 0xdd9124c03da38cL, 0x6b2503125ee8e9L, + 0xae67399b0d6161L, 0x70c4acd82203b6L }, + { 0x9683916d31dae8L, 0x34775031ac7f69L, 0x9553153988e4adL, + 0xb58f41153a15e1L, 0xb65a2d492ba2ddL, 0x7c3efb1a90169cL, + 0x210f45e6b1747dL, 0x16e8d1bcff488dL } + }, + { + { 0x252adf89d703dbL, 0x259ac1dfdfeb39L, 0x7faf6af115e806L, + 0x7aaefd6c1aff21L, 0x80542107c0113dL, 0x481f1a5e19b4b1L, + 0x7c17d43fcc8c61L, 0x8b04452bb0bbbeL }, + { 0xe51e5f54cebae1L, 0x05341ba56a414cL, 0x0083a2c7fb8a30L, + 0xb4663f277f4952L, 0xce72eec4bb0074L, 0x74fdd66a3584d1L, + 0x6b9e58eb02e076L, 0x5be45d53b961f4L } + }, + { + { 0xc7474f31ab2e0bL, 0x2838ccbf4bf454L, 0x634392ef3c3eacL, + 0x440e40a137602bL, 0xeea67e9d1ae8e3L, 0xafdf93a77e221eL, + 0x3c9f3da2719a10L, 0x466ecef32c8256L }, + { 0x1061c19f9c432fL, 0xa1332d9b1c7d98L, 0xbc735f2a425c2cL, + 0x1429cdf4b1bccbL, 0x77b42a16bbb5f9L, 0x30078e35955ae4L, + 0x8acd77721cc315L, 0xaa90d5fe86fa99L } + }, + { + { 0xfcfd460721115aL, 0x6a7de3e08269b8L, 0xe5964a696dd47eL, + 0x6717cd58dca975L, 0x7ea4ebe98b149eL, 0x6f894d5b7b8057L, + 0xbd6f9607f30e31L, 0x61ca45323df092L }, + { 0x32241f99d782f3L, 0x55173b02abfae2L, 0x0abe0edd15bbbdL, + 0xb6d3c0ab438abbL, 0x62fb4679ffa20bL, 0x30926b5d31560aL, + 0x44bf27c2a0aa6dL, 0xf7473131a4cb97L } + }, + { + { 0xa2f6c0db0535deL, 0xcb02ae1c855166L, 0xc699e6bb3422f0L, + 0x774febe281ba8aL, 0x1d9d24fffabcc7L, 0x0b31ba1fe12ba5L, + 0x4c8680313d0af7L, 0x90640d32f47160L }, + { 0xa0c4bf45876603L, 0x717f6fa950ab08L, 0xf12bb53a710de8L, + 0xc500c616a88f50L, 0x0070f992645351L, 0x57aab5d2446893L, + 0xd553fa8b68f657L, 0xe8537c1693c55dL } + }, + { + { 0x58e86eb7fc7684L, 0xdf330f7bfc73a9L, 0x41e337dcc11936L, + 0x36d92006e35759L, 0x01327033500d8bL, 0xfa684059483354L, + 0xc8f2980667851bL, 0x538ec8918296b0L }, + { 0xa2a2c4fcff55f9L, 0xb260d4d60d20bdL, 0x3ed576fd9cc59fL, + 0x4ed8c64d514fccL, 0x37ebfb2c22b315L, 0xca67a3694c212cL, + 0x4f8e08c3a1795eL, 0x498f9264e7261fL } + }, + { + { 0xfea7382c59b3d4L, 0xb9942ed3f2925fL, 0xe4b00dc8ea77e8L, + 0x74a18ec3cab02eL, 0xbbbb752ef16d0bL, 0x639da4fffab032L, + 0xc371a4a3aa30f0L, 0x8e26b22caa175bL }, + { 0x94e41567e2b62eL, 0x7cceea625a794cL, 0x931d2f4479f015L, + 0x946183d90b25b2L, 0x1504e9768a2807L, 0xa7577d3fa49dddL, + 0x24fc87edd48699L, 0x9edefd63d7d99cL } + }, +}, +{ + { + { 0x0508b340f0b450L, 0xe0069a5c36f7f4L, 0x26556642a5a761L, + 0x0193fd8848e04dL, 0xc108cf573fe2e7L, 0x05eb0ecfd787d4L, + 0x1555ccbff28985L, 0xb5af09f651b995L }, + { 0x167d72ce1134beL, 0xd6d98bf57c669aL, 0x40fb7166dd76faL, + 0xeabbf202a41b31L, 0x300ff0e09b75b0L, 0x32b6fadd9a0c1eL, + 0x805188365a80e0L, 0x8bef69332110feL } + }, + { + { 0x637802fbef47d4L, 0xfac114b2d16eaaL, 0x7b3f3ab0415644L, + 0x17ab8d12dd895bL, 0x271b7fe87195f3L, 0xa3f867ea71f65fL, + 0x39ba40cc80583aL, 0x6db067256e1fccL }, + { 0x4feab4e06662a8L, 0xc857415c74bd46L, 0x18032ed732b126L, + 0x87c8aea7a099eaL, 0xb4a753536fe0a8L, 0x33a98da27673f6L, + 0x3e40c022b8e549L, 0x2def1af9a4c587L } + }, + { + { 0x9618b68a8c9ad9L, 0xd70b4aa49defdaL, 0xae8b1385f788efL, + 0x87c3542dd523f4L, 0xe42c7055c5b004L, 0x6303360fa7df57L, + 0x33e27a75f6d068L, 0x9b3268e8ff331aL }, + { 0x845cc9623ee0c3L, 0x003af70ac80084L, 0x6a9f931530c41dL, + 0xa1d7051bb127f0L, 0x642ce05ca36245L, 0xc34205b0323ee9L, + 0x7cc8912b7b3513L, 0x6252cc8076cbdbL } + }, + { + { 0x10e68a07089522L, 0x36c136158fc658L, 0x490397d74723a4L, + 0x42692c0519d56cL, 0x69d251bf1ff235L, 0xe689d03c2cbf37L, + 0xf04ceba825b7f4L, 0xd6b9bee2281c2eL }, + { 0xc52ef3fe0043abL, 0x351bf28d1d1be8L, 0x277615f0f18a5aL, + 0x31f717f5d6800fL, 0xf5fb82dab922e2L, 0x99aee2f2d6ae43L, + 0x42477fec63b982L, 0x904aeb1a594a01L } + }, + { + { 0xaa82174eb39974L, 0xbc38e6195e6aa0L, 0x6a3df8a25c0675L, + 0xf324203ffbe739L, 0xfa5a0b4a3f0649L, 0x79c87327a7a6b8L, + 0xeb65ecd40ad3f5L, 0x718d416e4e45c5L }, + { 0x029dbf4e2326fdL, 0x0c63416e7942f0L, 0x6d0c7286f4e678L, + 0x59f0b10a138601L, 0x8a1d9788d92ea9L, 0x9f8d712c22eca5L, + 0x73970447b6b96bL, 0xa2d49eee6fb955L } + }, + { + { 0x249f900bf14a19L, 0xd3522da63a8cd2L, 0x28a32f386964d2L, + 0xacf712bc1fa743L, 0x98a9bfc0bb94d3L, 0x318ece1bc06824L, + 0xfc476754fce7f0L, 0x19caec9e4135b7L }, + { 0x6de68a8c6817bbL, 0x7121960f3b6d89L, 0xa7d4261f5a818eL, + 0x0c0ba519157455L, 0x78b6acf450d5ffL, 0x198b4934e8649aL, + 0x0941a3cfd05da3L, 0x264ea4adb55951L } + }, + { + { 0xcfee91c46e5a31L, 0x47b6806fff7366L, 0xdb14be45df849dL, + 0x3c5e22bac66cc7L, 0x7f3f284a5f4769L, 0x4e00815383be36L, + 0x39a9f0b8072b0bL, 0x9887cd5c7eadd6L }, + { 0x7dd8f05b659511L, 0x15c796dd2e1cb9L, 0xe5edb0c0d31345L, + 0x2025df06939c60L, 0x6314c08bf15de1L, 0x03c154804c7fb5L, + 0x413337fbb5d3edL, 0xfc20b40477e983L } + }, + { + { 0x7f968805db0ef9L, 0x05562dee9c2a70L, 0x071e5bc7dae133L, + 0xa8cdd12237fc4aL, 0x6d565e74ea492bL, 0xa17cf94381ee52L, + 0x6ab8a4e9f5c546L, 0xbb642f340288efL }, + { 0x64e59215df5c2dL, 0x43696e3bb906f4L, 0x73a841a74ae46cL, + 0xe264883c506b8aL, 0x9542e1aa1be548L, 0x89385395e81b4aL, + 0x5642cfaeaca6ceL, 0xed8077b806e0f9L } + }, +}, +{ + { + { 0x1c776c47e13597L, 0x0ec8b289e584fdL, 0x0bb6043b8b61e8L, + 0xdcc17489cd835bL, 0x493e6ac39fef9aL, 0xb44eb34d133e17L, + 0xfebcd0071cb6f9L, 0xe6cf543d20eff2L }, + { 0xf265cad0a004c7L, 0x9b06c9dd35cc12L, 0x769f985cb4ea53L, + 0x29160a20993434L, 0xdf8dd108d939c4L, 0xefa177c6711e2fL, + 0x1695790cd7a2cdL, 0x38da3d777f6642L } + }, + { + { 0x9bfcfd96307b74L, 0xc26a36dbfdabc3L, 0x9341be04abe28eL, + 0xdb20b5273d1387L, 0xf8d229c3d1949cL, 0xf1e0afeb8b3a41L, + 0x29c60dfed565d0L, 0x6930bb58b43b2cL }, + { 0x1d76527fc0718fL, 0xdb981431f67189L, 0x0c62f6451f32ccL, + 0x70a66268bd35e5L, 0x1725641c1cece7L, 0x7f130a8f96f4a4L, + 0x72319e9f06ee98L, 0x215b73867bf9b2L } + }, + { + { 0x8d1bec20aaddd7L, 0xfb8b95bb8be4f9L, 0xeac193efde1026L, + 0xa5edea79d5860cL, 0x4adbaea44280d3L, 0xce8b67038f4798L, + 0x914c107ec30deaL, 0xbdc5cf7000776bL }, + { 0xb6fd7d1a206a13L, 0x9941ebadae986eL, 0x76c27a81f1caaaL, + 0x6967c123f108b4L, 0x6f115284aea2d0L, 0x9bb4319144ddacL, + 0x1a4d3eac8ec6fcL, 0xfe4b0b8bf37420L } + }, + { + { 0x5d9a4a1ec0ac6fL, 0x84b79f2fc7c80dL, 0x64222f7c14fac3L, + 0xdd9e039c23b3f2L, 0x4a84abdea956bbL, 0x370dcbaebe09dcL, + 0x79a9ea8e0eaf82L, 0x4cfb60aaee375fL }, + { 0x6a10dbf9106827L, 0xa3ba5cf43f305bL, 0x481b885c1bb083L, + 0x2f52380b3117b1L, 0x0066122ddd6791L, 0x4f8923e63bace3L, + 0x5c5f499ecb88d4L, 0xfdc780a3bac146L } + }, + { + { 0x34b70ae7ba1f71L, 0x909182945bd184L, 0x3b39778e707313L, + 0xdeefc5e6164e91L, 0xbb55bed4971f39L, 0x7d523398dafc8bL, + 0x82391bfa6adf0fL, 0xfd6f90ae319522L }, + { 0x60fdf77f29bbc9L, 0xeff9ed8aaa4030L, 0x978e045f8c0d3fL, + 0xe0502c3eed65cdL, 0x3104d8f3cfd4c8L, 0xab1be44a639005L, + 0xe83f4319eeab3fL, 0x01970e8451d797L } + }, + { + { 0xbc972f83180f4bL, 0xac053c0617779dL, 0x89392c57fa149fL, + 0xdc4699bbcb6263L, 0x0ae8b28ce12882L, 0xdca19a7af1a4dcL, + 0xd3d719f64e1a74L, 0xbb50201affdd5dL }, + { 0x56f73107ac30e9L, 0x65cc9c71878900L, 0x83f586627338a3L, + 0x122adefac5bb13L, 0x97de2001bcd4d5L, 0x6ed3985b8aa3a0L, + 0x8680f1d6821f9bL, 0xcb42028dda9f98L } + }, + { + { 0xcdb07080ec2db3L, 0xe28c8333dad1a1L, 0x2093e32de2da07L, + 0x731707383b8987L, 0xad17871f552b8dL, 0x846da9851cf70aL, + 0xf94a16e5c4f5e1L, 0x84299960f8348aL }, + { 0x4bf3f6898db78aL, 0xad77fa83d19b52L, 0x69767728b972dcL, + 0x7dfa35a5321be0L, 0x9881846dd344a6L, 0xe550292ad4e2a8L, + 0x8075217bc68bf1L, 0xdd837c4893be15L } + }, + { + { 0x09c931ed4fab5bL, 0xb2dcf08b77a0f1L, 0x7dac5c0e0d38a6L, + 0xa5570b00ae73afL, 0xc7c19d3f5aed28L, 0x575fa6f5251e92L, + 0xb843cd6cdf7275L, 0xd9d3d8e9a01287L }, + { 0xf94e356b3c370bL, 0xc62b99ffe464b0L, 0x7792650a986057L, + 0xeaa67d5c4b1874L, 0xba1ba4d0b07078L, 0xdbf636d7a03699L, + 0x1a16c34edd32a3L, 0x6ce2495a45cb5dL } + }, +}, +{ + { + { 0xd7c4d9aa684441L, 0xce62af630cd42aL, 0xcd2669b43014c4L, + 0xce7e7116f65b24L, 0x1847ce9576fa19L, 0x82585ac9dd8ca6L, + 0x3009096b42e1dbL, 0x2b2c83e384ab8bL }, + { 0xe171ffcb4e9a6eL, 0x9de42187374b40L, 0x5701f9fdb1d616L, + 0x211e122a3e8cbcL, 0x04e8c1a1e400bfL, 0x02974700f37159L, + 0x41775d13df8c28L, 0xcfaad4a61ac2dbL } + }, + { + { 0x6341b4d7dc0f49L, 0xaff6c2df471a53L, 0x20ec795fb8e91eL, + 0x4c7a4dfc3b7b62L, 0x9f33ff2d374938L, 0x38f8c653a60f2eL, + 0xc1168ac2efef73L, 0x046146fce408eeL }, + { 0x9b39ac0308b0c3L, 0xe032d6136b8570L, 0xee07d8dfc4aacfL, + 0x0a82acbd5a41ddL, 0xbe0ded27c3d726L, 0xce51d60b926ce9L, + 0xfa2f7f45806c1eL, 0xe367c6d1dec59cL } + }, + { + { 0x64511b6da2547bL, 0x76a349c0761405L, 0x37d662601223abL, + 0x0e243c1f4d7c48L, 0xdc9c8b4da756a0L, 0xc7430dfd72e7e9L, + 0x0eb130827b4210L, 0x7a9c044cf11cbdL }, + { 0x2c08ff6e8dd150L, 0x18b738c2932fc6L, 0x07d565104513e8L, + 0x0ca5cffaa40a17L, 0xd48634101baa8fL, 0xfb20fafb72b79eL, + 0x1a051e5654020fL, 0xe3b33174e17f23L } + }, + { + { 0x05910484de9428L, 0x620542a5abdf97L, 0xaa0ededa16a4d1L, + 0xa93f71c6d65bb9L, 0x88be135b8dfaf9L, 0x1d9f4e557ca8eeL, + 0x4c896aa26781adL, 0xd3fbe316c6c49fL }, + { 0x088d8522c34c3dL, 0xbb6d645badff1eL, 0xe3080b8385450dL, + 0x5ccc54c50ab1f3L, 0x4e07e6eac0657dL, 0xa7ba596b7ef2c0L, + 0xcceca8a73a81e9L, 0xa0b804c8284c35L } + }, + { + { 0x7c55956f17a6a2L, 0xb451d81789cfa8L, 0xdf414e82506eaaL, + 0x6ef40fbae96562L, 0x63ea2830e0297eL, 0xf5df26e73c46faL, + 0xe00641caac8bceL, 0xc89ed8f64371f3L }, + { 0xd22b08e793202eL, 0x39a9033875cb50L, 0xe64eec0f85ddb4L, + 0xdce45a77acf7b5L, 0x39d1e71b9b802dL, 0xafdfe7cbd559acL, + 0x17ec1f8809eeb5L, 0x8c0e38a4889b8cL } + }, + { + { 0x47eabfe17089daL, 0x2d18466ec90c50L, 0xa511aa45861531L, + 0xebb3d348c39b39L, 0xa0ac4daf1b5282L, 0xea26be7a9dadbaL, + 0x8992ba8554d86eL, 0x7fcbdb6d5f2ef5L }, + { 0x320e79b56863e7L, 0xeb9d0c0a7dce2dL, 0xb9f4031784cbc6L, + 0x68823ee7ac1f81L, 0xa6b6f4f9d87497L, 0x83c67b657f9b6eL, + 0x37357470fef2a7L, 0xf38028f59596e2L } + }, + { + { 0x9ea57ab7e82886L, 0x18221c548c44d5L, 0xbf8e6cf314a24fL, + 0x70ff18efd025e5L, 0x08d03de5334468L, 0x2b206d57404fb7L, + 0xb92327155e36b0L, 0xcc7604ab88ddd9L }, + { 0x3df51524a746f0L, 0x8fdebd8168e3fcL, 0xffc550c7f8c32cL, + 0x1dbbc17148743eL, 0xd48af29b88e18bL, 0x8dca11c750027cL, + 0x717f9db1832be3L, 0x22923e02b06019L } + }, + { + { 0xd4e06f5c1cc4d3L, 0x0fa32e32b4f03aL, 0x956b9afc4628d0L, + 0x95c39ce939dad1L, 0x39d41e08a00416L, 0xfd7ff266fb01aaL, + 0xc6033d545af340L, 0x2f655428e36584L }, + { 0x14cfb1f8dff960L, 0x7236ffcda81474L, 0xc6a6788d452d0fL, + 0x2ad4a5277f6094L, 0x369d65a07eea74L, 0x27c6c38d6229aaL, + 0xe590e098863976L, 0x361ca6eb38b142L } + }, +}, +{ + { + { 0x6803413dfeb7efL, 0xb669d71d3f4fadL, 0x5df402ac941606L, + 0xe5d17768e6c5b7L, 0x131bcb392ab236L, 0x7f1fb31ce2e0e0L, + 0xa2c020d9e98c35L, 0x33b23c0f28657bL }, + { 0xed14e739cf7879L, 0x10d4867b4357b3L, 0x127cea331e4e04L, + 0xc60d25faa5f8a7L, 0xfef840a025b987L, 0x78081d666f2a0aL, + 0x0fa0b97ac36198L, 0xe0bb919134dc9fL } + }, + { + { 0xc1d2461cc32eaeL, 0x0fdbfdf0f79a37L, 0x70f2bc21c95f02L, + 0x7d68bec372cddfL, 0x44f78178439342L, 0xa3d56784843a6cL, + 0xbadf77a07f8959L, 0xf45819873db4caL }, + { 0xe8eaaf3d54f805L, 0x2f529d1b84c1e7L, 0x404e32e21e535cL, + 0xabac85c159b5f5L, 0x4e8e594b00466fL, 0x40fcaabc941873L, + 0x3b4e370be407c6L, 0xccd57885b2e58dL } + }, + { + { 0x3ee615e88b74a8L, 0xd7d6608eab4e69L, 0x27cf9f1e4ace36L, + 0x282359e7aebabbL, 0x96e509bf6d162fL, 0xad906f3f1a290aL, + 0xe7d6c4f1314a58L, 0xeecffe4218431dL }, + { 0xa66e0e9e2cfed9L, 0xb0887ec71f0544L, 0xd34e36ba04c5d7L, + 0x094daa5ed4392dL, 0xcda83adc8aa925L, 0x1adef91b979786L, + 0x3124dcbfddc5d6L, 0x5cc27ed0b70c14L } + }, + { + { 0x386dbc00eac2d8L, 0xa716ecbc50ca30L, 0x9e3fc0580d9f04L, + 0x37dde44cfeacebL, 0xd88d74da3522d5L, 0x6bb9e9f2cf239aL, + 0x9e7fb49a7cbfecL, 0xe1a75f00a5c0efL }, + { 0x6e434e7fb9229dL, 0x0ec6df5c8a79b3L, 0x7046380d3fb311L, + 0xe957ef052e20faL, 0x0f4fe9a9ef4614L, 0x1b37d9c54d8f2bL, + 0x23b2dc139d84a2L, 0xf62c4f6724e713L } + }, + { + { 0xbd6922c747e219L, 0x34d14383869b7bL, 0x8c875a596f2272L, + 0xd9602c03fe361eL, 0x081348f744839fL, 0x61bd16c61ac1f1L, + 0x993b727d8da4e1L, 0xbb40ba87741271L }, + { 0xe6dcc9881dcfffL, 0x9f513f593ce616L, 0xdc09683618cd8fL, + 0xc3b1d1026639beL, 0xe8f149fc762ee2L, 0x59f26efb244aaeL, + 0x3f2de27693dd96L, 0xd8b68f79c3a7deL } + }, + { + { 0x6fa20b9970bd5bL, 0x87242d775f6179L, 0xa95a6c672d9308L, + 0x6eb251837a8a58L, 0xfdea12ac59562cL, 0x4419c1e20f1fc3L, + 0x0c1bd999d66788L, 0x4b7428832c0547L }, + { 0x4f38accdf479abL, 0x01f6271c52a942L, 0xe3298f402ca9a7L, + 0x533dacab718fc8L, 0x133602ab093ca8L, 0xc04da808f98104L, + 0xd0f2e23af08620L, 0x882c817178b164L } + }, + { + { 0x28e6678ec30a71L, 0xe646879f78aca1L, 0x868a64b88fa078L, + 0x671030afee3433L, 0xb2a06bb87c0211L, 0x202eca946c406aL, + 0x64d6284e4f0f59L, 0x56ae4a23c9f907L }, + { 0x5abbb561dcc100L, 0x6fef6cf07c7784L, 0xb6e25cddb7302dL, + 0xa26785b42980e8L, 0xe7d4043fb96801L, 0x46df55d8e4282bL, + 0x9c0a5f5c602d6eL, 0xf06560475dfe29L } + }, + { + { 0x0e82a1a3dcbc90L, 0xb1ee285656feacL, 0xfa4353b0d3d3b2L, + 0xc2e7a6edd5c5dfL, 0x13707e1416ce53L, 0xc84ce0787ebc07L, + 0xdd273ce8a9a834L, 0x432a6175e8e1e7L }, + { 0xa359670bd0064aL, 0xc899dd56534516L, 0x666560edb27169L, + 0x1537b22a19a068L, 0x3420507eac7527L, 0x479f25e6fc13a7L, + 0xc847acc1bc19b3L, 0xecdecf00b20d45L } + }, +}, +{ + { + { 0x6f241004acea57L, 0xdace1c6da68597L, 0xea7dd4150ce77fL, + 0x1aecb841585884L, 0x92ff208ea4a85cL, 0xde9433c88eebd2L, + 0x53cd3183f4d289L, 0x397085826539afL }, + { 0x4b57599b827d87L, 0xdc82ac03d77638L, 0x694336652f6e61L, + 0xb8fc4b0ad5e8a6L, 0x1b6f7dcf388642L, 0x6f24533a74dd57L, + 0xc66937841750cfL, 0x06757eb28a37afL } + }, + { + { 0x0e70d53c133995L, 0x88a5e0c7c8c97dL, 0x4e59dbf85f3be3L, + 0x0f364ac0e92698L, 0x3a1e79bef6940fL, 0xc8a3941d85d23aL, + 0x143bb999a00e58L, 0x61cf7d6c6f2f10L }, + { 0x979c99485150feL, 0xcfd0df259d773fL, 0xce97b9daab7bcdL, + 0xc9fff8e6afd8fcL, 0x246befd89a4628L, 0xf6302821567090L, + 0x15393426749c58L, 0xff47d0ea0f3fd3L } + }, + { + { 0x09b0bfd35f6706L, 0x74645812c82e69L, 0xb60729f50d5fe9L, + 0xf13324595c74f1L, 0x33647e3bb76c89L, 0x01264045a9afccL, + 0x46d57ee0f154abL, 0x2efa55525680a4L }, + { 0x12ebfc65329d90L, 0xcb37ae579800afL, 0x5bb53496f8e310L, + 0x9b59c63f1bb936L, 0x5b49baaf4610e9L, 0x2bbeeef4f2d6acL, + 0x87ee21e0badc67L, 0x12e2aadf1ddfa0L } + }, + { + { 0x5b4668fa9109eeL, 0xfa951338a6cea2L, 0xe45e6fc4068e16L, + 0x8ae9a0c0205ed8L, 0x2993b96679b79bL, 0xc6b878fed604d3L, + 0x01d020832c77f3L, 0xd45d890495a1abL }, + { 0x99348fa29d2030L, 0x961f9a661f8f7aL, 0xfd53212674f74bL, + 0x45cee23b3e72bcL, 0x3fccb86b77e2d5L, 0xdff03104219cb7L, + 0x233771dc056871L, 0x1214e327d2c521L } + }, + { + { 0x9f51e15ff2a8e1L, 0x86571c5138bc70L, 0xbfc4caf0c09d46L, + 0x65e33fec2a0c18L, 0x8214392426867dL, 0x51ce6c080ae4edL, + 0x6cbe8d7b110de6L, 0x7f6e947fd22ea4L }, + { 0x7373a75cadefc4L, 0x6fca1d2b0c682fL, 0xcd2140df3c7c1eL, + 0x8653a37558b7a5L, 0x653e74e55eb321L, 0xbe0c6b3c31af73L, + 0x3376379f4fc365L, 0x3570b3771add4dL } + }, + { + { 0x9061ec183c3494L, 0xaf2f28d677bc95L, 0x6fe72793bf8768L, + 0xc5f50e30fa86d8L, 0x6c03060a3293ceL, 0x4d53357e2355a6L, + 0x43a59eae4df931L, 0x6f48f5d13b79c6L }, + { 0xa4d073dddc5192L, 0x6d0e318a65773fL, 0x1008792765de9eL, + 0xa724ed239a0375L, 0x510ff1497d7c9eL, 0x251f6225baa863L, + 0x86464fe648a351L, 0xf85e98fd50fd91L } + }, + { + { 0x29c963486ee987L, 0x93e8e5210dcc9fL, 0xa1fc4d1c910b1fL, + 0x015acacfeb603eL, 0xc9f25f80844a5fL, 0x50de93c73f4dacL, + 0x1758783310a4aaL, 0x544d570358f106L }, + { 0x4eeec7b1dc68caL, 0x6238e6fe00fbcbL, 0x34d394cb4e83c9L, + 0x764ffa22292656L, 0x5614cd1f641f2eL, 0x4252eb69e07234L, + 0xcbaef4568d2ba4L, 0x8c9c5508a98b17L } + }, + { + { 0xf235d9d4106140L, 0x1bf2fc39eb601eL, 0x6fb6ca9375e0c3L, + 0x4bf5492c0024d2L, 0x3d97093eb54cc6L, 0xc60931f5c90cb5L, + 0xfa88808fbe0f1aL, 0xc22b83dd33e7d4L }, + { 0x9cfec53c0abbf5L, 0x52c3f0a93723dfL, 0x0622b7e39b96b6L, + 0x300de281667270L, 0x50b66c79ef426aL, 0x8849189c6eb295L, + 0xeaec3a98914a7eL, 0x7ed56b0c4c99e0L } + }, +}, +{ + { + { 0x7926403687e557L, 0xa3498165310017L, 0x1b06e91d43a8fdL, + 0xf201db46ac23cbL, 0x6f172ad4f48750L, 0x5ed8c8ce74bd3eL, + 0x492a654daba648L, 0x123010ba9b64ffL }, + { 0xa83125b6e89f93L, 0x3a3b0b0398378aL, 0x9622e0b0aebe7cL, + 0xb9cbfdc49512a4L, 0x13edffd6aaf12aL, 0x555dff59f5eafdL, + 0x3cba6fe1212efaL, 0xd07b744d9bb0f8L } + }, + { + { 0x45732b09a48920L, 0xf3080fc13ff36dL, 0x9347395de8f950L, + 0x14d025a382b897L, 0x60c5a7404d72adL, 0x30be7e511a9c71L, + 0x43ffabd31ac33aL, 0x97b06f335cbb14L }, + { 0xe4ff5c57740de9L, 0x5fed090aacf81eL, 0x97196eee8b7c9dL, + 0x316dcd1045910bL, 0x7a2b2f55ad8c63L, 0x674fffdc5b03bbL, + 0xc1cd133e65953cL, 0x3c060520a83556L } + }, + { + { 0x797c3f6091c23dL, 0x2ea2de339c9c05L, 0x5d958b4a31f67cL, + 0xf97afe5d5f088cL, 0xbcfbd2a0b37243L, 0xc43ad3eeca630cL, + 0xb92a33742845e0L, 0x970bff7a9a0f16L }, + { 0x86355115970a79L, 0xcee332ef205928L, 0x2c58d70c04c208L, + 0xdbfe19a3f5e5bfL, 0x8f8f2c88e51c56L, 0xb61f58e8e2da75L, + 0x4046a19624d93fL, 0x7de64dbe1f9538L } + }, + { + { 0xd018e1cc2d850eL, 0x8cdb64363a723cL, 0x9a65abe90a42afL, + 0xfeece9616f20ccL, 0xc906800d5cff56L, 0x0acf23a3f0deedL, + 0x2143061728dd3aL, 0x66276e2b8ce34cL }, + { 0x23700dc73cc9c7L, 0xdb448515b1778bL, 0x330f41e4aab669L, + 0x2f5aabcf5282a4L, 0xff837a930f9e01L, 0x1a1eb2f901cc98L, + 0xd3f4ed9e69bd7fL, 0xa6b11418a72a7dL } + }, + { + { 0x34bde809ea3b43L, 0x5ddcb705ced6aeL, 0x8257f5b95a6cb8L, + 0xaac205dc77dcb8L, 0x77d740d035b397L, 0xca7847fcf7e0a6L, + 0x9404dd6085601bL, 0x0a5046c457e4f9L }, + { 0xcaee868bc11470L, 0xb118796005c5f6L, 0xcc04976ec79173L, + 0x7f51ba721f6827L, 0xa8e3f0c486ff7eL, 0x327163af87838cL, + 0xcf2883e6d039fdL, 0x6fb7ab6db8b0e2L } + }, + { + { 0x8ca5bac620d669L, 0xff707c8ed7caa9L, 0xdaefa2b927909bL, + 0x1d2f9557029da3L, 0x52a3ba46d131a0L, 0xe5a94fd3ab1041L, + 0x508917799bc0aeL, 0xf750354fa1bd16L }, + { 0xdd4e83a6cd31fdL, 0xd33505392fac84L, 0xf914cbc1691382L, + 0x669683fda6ade6L, 0x69446438878513L, 0x429d3cc4b1a72dL, + 0x655c46a61eec36L, 0x881eded4bc4970L } + }, + { + { 0x5b39d377ca647fL, 0x41533c1e917b34L, 0xea2aeb57daf734L, + 0xf1ef1eb1286560L, 0x582f2e008e0473L, 0x5913d7d5edc74aL, + 0x588c7ec3c1e754L, 0xbd6db057146fe1L }, + { 0x3b0d49e7634907L, 0x4c65ce4e43b9ccL, 0xb87e9582d92d5bL, + 0x05135727ab1519L, 0x03ec0848c3aed0L, 0x4d7aa21561a641L, + 0xe5f821199e92adL, 0x379b55f48a457cL } + }, + { + { 0x8317c34d6a8442L, 0xb0ab4a5ae499daL, 0xebcb16e720e8ebL, + 0xfd5c5639a96908L, 0xcab4d67ad23acfL, 0xa600a79bcdf748L, + 0x18a6340a2a6a51L, 0xf2f415c3aabd69L }, + { 0xdb38a4f747258aL, 0xb6ea5602e24415L, 0xfad1ea9f1f7655L, + 0x4e27eb5c957684L, 0xf8283e1b2e1cfcL, 0x8f83bd6aa6291cL, + 0x28d23b55619e84L, 0xb9f34e893770a4L } + }, +}, +{ + { + { 0x1bb84377515fb1L, 0xac73f2a7b860a6L, 0x78afdfa22b390fL, + 0x815502b66048aaL, 0xf513b9785bf620L, 0x2524e653fc5d7cL, + 0xa10adc0178c969L, 0xa1d53965391c8dL }, + { 0x09fccc5a8bcc45L, 0xa1f97d67710e1eL, 0xd694442897d0a1L, + 0x7030beb5f42400L, 0xdebe08c7127908L, 0x96b715c2187637L, + 0xc598250b528129L, 0x0f62f45a1ccb07L } + }, + { + { 0x8404941b765479L, 0xfdecff45837dc4L, 0x1796372adbd465L, + 0x5f84c793159806L, 0x6d2e46b6aaad34L, 0xd303b4a384b375L, + 0x440acd5b392002L, 0x4f2a4a7c475e87L }, + { 0x038e1da5606fc2L, 0x2d821c29c2f050L, 0xc074cb3f139db4L, + 0xde2fee74ec59beL, 0x5a819eea84ed59L, 0xd65c62c3e98711L, + 0x72eb440b9723c1L, 0xb92775401be611L } + }, + { + { 0x929fe64ab9e9fcL, 0x04379fd0bf1e85L, 0xb322093bc28ee3L, + 0x78ac4e2e4555e1L, 0xdb42b58abc5588L, 0x1c1b5e177c8b12L, + 0xf6d78dd40366c4L, 0xc21ff75bdae22eL }, + { 0x1e3d28ea211df2L, 0xc5a65a13617c0aL, 0x3fa02c058140d5L, + 0x155c346b62d10cL, 0xc9cf142e48268fL, 0xdc140831993bc3L, + 0x07c44d40ee69dcL, 0x61699505e2ac46L } + }, + { + { 0x44e4a51d0fb585L, 0x00846bef1f3ce8L, 0xedef39a8e2de1eL, + 0x430afe333b3934L, 0xac78b054337188L, 0x0f39de4c9a3f24L, + 0x039edddc9ae6a4L, 0xf4701578eacd51L }, + { 0x1e396949a2f31aL, 0xc8a40f4b19a8b1L, 0xdddd10c9d239d8L, + 0xf974245887e066L, 0xfdb51113ea28c6L, 0xb5af0fbe1122a9L, + 0xd30c89f36e0267L, 0x7b1c0f774f024cL } + }, + { + { 0x1ec995607a39bfL, 0x1c3ecf23a68d15L, 0xd8a5c4e4f59fe9L, + 0xacb2032271abc3L, 0xbc6bdf071ef239L, 0x660d7abb39b391L, + 0x2e73bb2b627a0eL, 0x3464d7e248fc7eL }, + { 0xaa492491666760L, 0xa257b6a8582659L, 0xf572cef5593089L, + 0x2f51bde73ca6bfL, 0x234b63f764cff5L, 0x29f48ead411a35L, + 0xd837840afe1db1L, 0x58ec0b1d9f4c4bL } + }, + { + { 0x8e1deba5e6f3dcL, 0xc636cf406a5ff7L, 0xe172b06c80ca0fL, + 0x56dc0985ffb90aL, 0x895c2189a05e83L, 0x6ddfaec7561ac2L, + 0xaa3574996283a0L, 0x6dfb2627e7cd43L }, + { 0x6576de52c8ca27L, 0x6a4a87249018ebL, 0x00c275c5c34342L, + 0xe34805ad2d90c4L, 0x651b161d8743c4L, 0xb3b9d9b7312bf3L, + 0x5d4b8e20bf7e00L, 0x8899bdf78d3d7eL } + }, + { + { 0x9644ad8faa9cd1L, 0x34c98bf6e0e58eL, 0x6022aad404c637L, + 0x2a11a737ac013bL, 0x5bdd1035540899L, 0x2e675721e022a4L, + 0xe32045db834c33L, 0x74a260c2f2d01cL }, + { 0x20d59e9c48841cL, 0x05045dde560359L, 0xeba779cac998acL, + 0x5bed10c00a6218L, 0x25d4f8e5327ef4L, 0xa2784744597794L, + 0xefd68ca831d11eL, 0x9ad370d934446aL } + }, + { + { 0x3089b3e73c92acL, 0x0ff3f27957a75cL, 0x843d3d9d676f50L, + 0xe547a19d496d43L, 0x68911c98e924a4L, 0xfab38f885b5522L, + 0x104881183e0ac5L, 0xcaccea9dc788c4L }, + { 0xfbe2e95e3c6aadL, 0xa7b3992b3a6cf1L, 0x5302ec587d78b1L, + 0xf589a0e1826100L, 0x2acdb978610632L, 0x1e4ea8f9232b26L, + 0xb21194e9c09a15L, 0xab13645849b909L } + }, +}, +{ + { + { 0x92e5d6df3a71c1L, 0x349ed29297d661L, 0xe58bd521713fc9L, + 0xad999a7b9ddfb5L, 0x271c30f3c28ce0L, 0xf6cd7dc2a9d460L, + 0xaf728e9207dec7L, 0x9c2a532fcb8bf0L }, + { 0xd70218468bf486L, 0x73b45be7ab8ea8L, 0xddfc6581795c93L, + 0x79416606bb8da2L, 0x658f19788e07a2L, 0xa9d5b0826d3d12L, + 0x4d7c95f9535b52L, 0xad55e25268ef8aL } + }, + { + { 0x94a9b0ba2bc326L, 0x485ecc5167e5f3L, 0x8340bc7c97fc74L, + 0x06f882b07aaa5cL, 0x4b57455849698aL, 0xd9281ebb36a0baL, + 0x8918c6c8b8108fL, 0xedd1eea5b50d1dL }, + { 0x94d737d2a25f50L, 0x0e5a8232446ad0L, 0x02a54357ced3e2L, + 0xb09a92a4af8cedL, 0x85fc498eeecef2L, 0x06a02b9e71e3d4L, + 0x00ad30784bb49aL, 0xf61585e64a5b4aL } + }, + { + { 0x915f6d8b86a4c9L, 0x944bc6ba861e1fL, 0x3091ca754465efL, + 0x11df859eb53a38L, 0xd44dde50144679L, 0x6c8da9a0994eddL, + 0xeebcebf91241efL, 0xc419354c2f6859L }, + { 0x1f4969349581b6L, 0x5712b10bb26cb4L, 0x8fcaa41b09fd59L, + 0xbd39aad72e22e3L, 0xf70e794b1199b0L, 0xdf63c0cc6f863dL, + 0xd58166fee9df4fL, 0xb9224eac45e70bL } + }, + { + { 0x80072face525f4L, 0x8597bd666a5502L, 0xf65e203dbc9725L, + 0xeccfbe3f2222a4L, 0x490aa422339834L, 0x134889162489e8L, + 0xaff3f80a735084L, 0x69d53d2f3f1bd6L }, + { 0xb123ffc813341aL, 0x359084c1173848L, 0x751425ed29b08dL, + 0x1edda523890ad4L, 0xb64974c607cf20L, 0xa8c8cb8b42ac7cL, + 0xd5cb305edd42e5L, 0xf3034dc44c090aL } + }, + { + { 0x428921dbb18e19L, 0x4cfd680fed2127L, 0x671144d92ac8c3L, + 0x2121901132c894L, 0x25d0e567604cd9L, 0xa372223afbc2a0L, + 0xcf98a5256c16f7L, 0x71f129ab5459e1L }, + { 0xf4afdc5b668b2eL, 0xc5d937a0c2d410L, 0xe2cc4af285d54aL, + 0x1c827778c53e18L, 0x270f2c369a92f6L, 0x799f9ac616327aL, + 0xce658d9d4246f2L, 0x0fb681ffb12e36L } + }, + { + { 0xc5ab11ee0690feL, 0x80261e33f74249L, 0x8eb4b4758c1cf2L, + 0x4895a80184ae9bL, 0x4a4bdb6d3e27ebL, 0xa7a1638bfd251cL, + 0x29ec144417a7e3L, 0xd0736093f1b960L }, + { 0xcb1ed8349c73d1L, 0x33fc84a8d1945aL, 0x9f668dbe965118L, + 0x3331743a82811fL, 0xf394dec28ba540L, 0x44ce601654a454L, + 0x240dbb63623645L, 0xf07e7f22e61048L } + }, + { + { 0x7c9f1763d45213L, 0x3eefa709c1f77fL, 0xde3c3c51b48350L, + 0x4a2bc649d481a7L, 0xfd4a58a7874f3dL, 0x96655d4037b302L, + 0x945252868bf5abL, 0x1b6d46a75177f6L }, + { 0x7de6763efb8d00L, 0xb2c1ba7a741b7bL, 0xcca6af47bae6edL, + 0xe4378ca5b68b3fL, 0xfb757deaf71948L, 0x7f07b5ebc6ac99L, + 0x752a56827d636dL, 0xc8b7d1d4b8a34fL } + }, + { + { 0x76cb78e325331bL, 0x41f41c9add2eedL, 0x03db2385c5f623L, + 0xbbc1d177102fa2L, 0x80f137a60182ecL, 0xfdd856955adf15L, + 0x4f53f5ee3373dcL, 0xec6faf021b669bL }, + { 0x7d4e9830b86081L, 0x10d3cd9f2d979cL, 0x0f48f5824a22c8L, + 0x86c540c02f99eeL, 0xf4c66545e6c5fcL, 0xaf0c588bc404c8L, + 0x2e6edbd423118aL, 0x86e32e90690eabL } + }, +}, +{ + { + { 0x1d12656dfbfa6fL, 0xa4980957646018L, 0x2f1071bc3597d0L, + 0x3df83f91dda80aL, 0x5853e28f3ae449L, 0xb853d319e19aadL, + 0x863f01ba0d8a46L, 0xa84fca62fef108L }, + { 0xbe4c0b7fb84de9L, 0x40a03dcc0727bfL, 0x781f841b18575cL, + 0x6a63045466cddbL, 0x6be758205dc7a2L, 0x420f87f07ae811L, + 0x28082423bf96c8L, 0x723998c51c6821L } + }, + { + { 0x38ab64181f5863L, 0xd82ecbd05ff9e1L, 0x339c94ea065856L, + 0x143054aa45156dL, 0xe6d64bf065628cL, 0xe530086a938589L, + 0x22d3a49385d79bL, 0x0b107900ab8245L }, + { 0xb0d80fbca387b5L, 0x698206e35551d7L, 0x199685da10bb73L, + 0xa8e5fa89107378L, 0x36e5724d99dbbfL, 0xd67f476d581b03L, + 0x7a15be788dd1e6L, 0x8dac8e4e5baa31L } + }, + { + { 0x4d5d88fe170ef8L, 0xb6ba5de1e9e600L, 0x4a89d41edeabc5L, + 0x737c66b8fac936L, 0x8d05b2365c3125L, 0x85a5cbcb61b68eL, + 0x8fea62620a6af9L, 0x85115ded8b50ecL }, + { 0x5430c8d6a6f30bL, 0x8bef9cf8474295L, 0x0648f5bbe77f38L, + 0xfe2b72f9e47bd7L, 0xad6c5da93106e2L, 0x4fa6f3dfa7a6c3L, + 0xdcd2ed8b396650L, 0x7de1cce1157ef9L } + }, + { + { 0x70a5f6c1f241d1L, 0x6c354d8798cd5cL, 0x23c78381a729fbL, + 0xcff8f15523cbdaL, 0x5683ff43493697L, 0xef7dbab7534f53L, + 0xd7bd08e2243d53L, 0x6f644cbf8072a9L }, + { 0xac960f9b22db63L, 0xa97f41723af04dL, 0x692b652d9798afL, + 0x0e35967fedb156L, 0x14b5e50dfe6ee8L, 0x7597edeb411070L, + 0x116f3ce442b3f9L, 0xe9b5ae81b2b6dbL } + }, + { + { 0xf4385ee2315930L, 0xc8d029827a8740L, 0x7907a8dd934a43L, + 0x20bc946c582191L, 0xa4acb3e6a405e7L, 0x8c1d6c843df2f5L, + 0x9df1593991f0b5L, 0xbb9df984d9be9dL }, + { 0x63620088e4b190L, 0xee1421eada3a88L, 0xb84f0ccf93b027L, + 0x7a5d6678e95091L, 0x3974462f3e3704L, 0xfa6fb5ec593e98L, + 0x44b6cf7a6477d2L, 0xe885b57b09a562L } + }, + { + { 0x6e339e909a0c02L, 0x57afff00e75f29L, 0x797d8d6fb7db03L, + 0xc6e11a3d25a236L, 0x643ce1c0107260L, 0xe644ec462eae1cL, + 0x821d5b83f5a3f5L, 0xa8ad453c0579d6L }, + { 0x6518ed417d43a4L, 0x46e76a53f87ccdL, 0xd6cbaabf9bef95L, + 0x25688324f7cbcfL, 0x367159a08476b4L, 0x1d1b401be6d324L, + 0x348cb98a605026L, 0x144f3fe43b6b1eL } + }, + { + { 0xbabbd787b1822cL, 0xd34ba7e2aa51f8L, 0x086f1cc41fbea4L, + 0x96f7eac746f3d9L, 0xad97f26281ecafL, 0x751a905a14ee2cL, + 0xb4e7fe90d7335fL, 0x0d97b8f4892ff0L }, + { 0xdb8a3155a5c40eL, 0x64e5de77ba567bL, 0x4f155f71eefe88L, + 0xe2297e9fb6fbf4L, 0xfe24bf96c16be5L, 0x2251847cdd83e2L, + 0x13ac2c85eda444L, 0x49d1b85283275fL } + }, + { + { 0xca08731423e08fL, 0x7046bb087d2f14L, 0x876f10c3bc846cL, + 0x2202b76358fbe3L, 0x0d4fc1c0e26ac6L, 0x1fc748bb986881L, + 0x609e61c8384a18L, 0x28a72d60d88e00L }, + { 0x1332a3178c6e2fL, 0x0367919b3526a4L, 0x53989e4698fe3eL, + 0x14b1145b16a99bL, 0xef9ec80ddbb75fL, 0x76256240e53955L, + 0x54e087a8744ae1L, 0xce50e8a672b875L } + }, +}, +{ + { + { 0x4c88b2ba29629cL, 0x946559c7b2642fL, 0x933d432f7ebe4cL, + 0x97109b663632c9L, 0x799b3fbe53184dL, 0xd4628710f069a6L, + 0x0c182a13a68351L, 0x974a8399a2437aL }, + { 0x29f19972a70278L, 0x01b98b6d9c424bL, 0xd85a60b08f4c37L, + 0xcc3523f2b1da15L, 0xf922115ddffb0fL, 0xee0fe4dde84ae2L, + 0x810440c55365beL, 0xd2f66391a457e8L } + }, + { + { 0x5e6879fe2ddd05L, 0x92a7545abdfc61L, 0x7dedd63a5cede8L, + 0x8a03b3f70df4bdL, 0xa5d1f6591f6cbbL, 0x372fde610f3fb2L, + 0x4537f9ea9dee05L, 0x7eb85bbdf7aa50L }, + { 0x963edf8e8c504dL, 0x53c8dcae7bdb6bL, 0xa246e4c6fedf2dL, + 0x75533400c55bdeL, 0x2aa748d0270a54L, 0xadb6cf005860ddL, + 0x8d314509b84763L, 0x626720deb405efL } + }, + { + { 0xa3709ae6601328L, 0x68e94fd2ac2478L, 0x38793439d5d247L, + 0xfa467af392c198L, 0x49e7b0d15df607L, 0x8c5812261792a8L, + 0x79f76581d3762fL, 0xaa38895244a39dL }, + { 0xef60af9c5cd0bcL, 0x2b0db53a33b3bbL, 0xe3e0b1f251015dL, + 0xc608afce64489eL, 0xe52b05703651aaL, 0x1dda8b91c6f7b9L, + 0x833f022ff41893L, 0x58eb0a0192818cL } + }, + { + { 0x6c1300cfc7b5a7L, 0x6d2ffe1a83ab33L, 0x7b3cd019c02eefL, + 0x6c64559ba60d55L, 0x2e9c16c19e2f73L, 0x11b24aedbe47b1L, + 0xc10a2ee1b8153bL, 0x35c0e081e02e1aL }, + { 0xa9f470c1dd6f16L, 0x4ea93b6f41a290L, 0xac240f825ee03fL, + 0x6cd88adb85aabdL, 0x378a64a1be2f8fL, 0xbf254da417bac1L, + 0x7e4e5a59231142L, 0x057aadc3b8c057L } + }, + { + { 0x607c77a80af479L, 0xd3e01ff5ccdf74L, 0x9680aaf101b4c7L, + 0xd2a7be12fc50a6L, 0x92a788db72d782L, 0x35daf2e4640b52L, + 0xc170d6939e601cL, 0x16e05f57b25c2fL }, + { 0x47a42a66fe37f8L, 0xeb74271beca298L, 0x401e11e179da16L, + 0xfb8da82aa53873L, 0xd657d635bb4783L, 0x6847758fcea0b1L, + 0x2f261fb0993154L, 0x868abe3592853aL } + }, + { + { 0x1a4c54335766abL, 0xa1c84d66f4e4eaL, 0x5d737a660ba199L, + 0x4a7b1e298b15a2L, 0x207877ffd967d3L, 0xcaec82dc262b4dL, + 0x0b278494f2a37dL, 0x34781416ac1711L }, + { 0x28e3df18fc6856L, 0xbec03f816d003fL, 0x2bd705bff39ebdL, + 0x1dcb53b2d776d3L, 0xabafa7d5c0e7ceL, 0x5b9c8c24a53332L, + 0xe9f90d99d90214L, 0x789747ec129690L } + }, + { + { 0x94d3c3954e2dfaL, 0x919f406afb2a8fL, 0x159ef0534e3927L, + 0xcdb4d14a165c37L, 0xa23e5e8288f337L, 0x95867c00f90242L, + 0x2528150e34e781L, 0x104e5016657b95L }, + { 0x695a6c9bcdda24L, 0x609b99523eb5faL, 0xcbce4f516a60f8L, + 0xec63f7df084a29L, 0x3075ada20c811fL, 0x129a1928c716a1L, + 0xd65f4d4cd4cd4aL, 0xe18fa9c62188beL } + }, + { + { 0x1672757bac60e3L, 0x525b3b9577144bL, 0x38fc997887055bL, + 0x7a7712631e4408L, 0x884f173cba2fcfL, 0x783cbdc5962ac0L, + 0x4f3ed0a22287dcL, 0x8a73e3450e20e6L }, + { 0xe7a1cd0d764583L, 0x8997d8d0d58ee6L, 0x0ea08e9aa13ed6L, + 0xed478d0cf363cbL, 0x068523d5b37bf4L, 0x8b5a9e8783f13cL, + 0xde47bbd87528a9L, 0xd6499cccaec313L } + }, +}, +{ + { + { 0x54781bbe09859dL, 0x89b6e067f5e648L, 0xb006dfe7075824L, + 0x17316600717f68L, 0x9c865540b4efe2L, 0xdbdb2575e30d8eL, + 0xa6a5db13b4d50fL, 0x3b5662cfa47bebL }, + { 0x9d4091f89d4a59L, 0x790517b550a7dcL, 0x19eae96c52965eL, + 0x1a7b3c5b5ed7a4L, 0x19e9ac6eb16541L, 0x5f6262fef66852L, + 0x1b83091c4cda27L, 0xa4adf6f3bf742bL } + }, + { + { 0x8cc2365a5100e7L, 0x3026f508592422L, 0xa4de79a3d714d0L, + 0xefa0d3f90fcb30L, 0x126d559474ada0L, 0xd68fa77c94350aL, + 0xfa80e570c7cb45L, 0xe042bb83985fbfL }, + { 0x51c80f1fe13dbaL, 0xeace234cf055d7L, 0x6b8197b73f95f7L, + 0x9ca5a89dcdbe89L, 0x2124d5fdfd9896L, 0x7c695569e7ca37L, + 0x58e806a8babb37L, 0x91b4cc7baf99ceL } + }, + { + { 0x874e253197e968L, 0x36277f53160668L, 0x0b65dda8b95dbeL, + 0x477a792f0872a1L, 0x03a7e3a314268dL, 0xa96c8420c805c7L, + 0xb941968b7bc4a8L, 0x79dce3075db390L }, + { 0x577d4ef6f4cc14L, 0x5b0d205b5d1107L, 0x64ff20f9f93624L, + 0x0b15e315034a2fL, 0x3a0f6bb8b6f35cL, 0x0399a84e0d0ec5L, + 0xd0e58230d5d521L, 0xdeb3da1cb1dd54L } + }, + { + { 0x24684ae182401aL, 0x0b79c1c21a706fL, 0xe1d81f8d8998afL, + 0xadf870f4bb069fL, 0xd57f85cf3dd7aaL, 0x62d8e06e4a40f8L, + 0x0c5228c8b55aa1L, 0xc34244aa9c0a1aL }, + { 0xb5c6cf968f544eL, 0xa560533de23ab7L, 0xaa5512047c690cL, + 0x20eda5b12aaaa6L, 0xea0a49a751a6a0L, 0x6d6cfff2baa272L, + 0x95b756ebf4c28aL, 0xd747074e6178a4L } + }, + { + { 0xa27b453221a94bL, 0xd56ad13e635f20L, 0x03574b08c95117L, + 0xf0ee953ed30b70L, 0xb48d733957796fL, 0xf5d958358c336bL, + 0x6170cd882db529L, 0xcd3ef00ec9d1eaL }, + { 0xd1bea0de4d105fL, 0xd2d670fad6a559L, 0x652d01252f9690L, + 0x5f51fb2c2529b0L, 0x5e88bf0e89df2aL, 0x9a90684cd686e4L, + 0xf519ccd882c7a1L, 0x933a0dfc2f4d37L } + }, + { + { 0x0720a9f3f66938L, 0x99356b6d8149dfL, 0xb89c419a3d7f61L, + 0xe6581344ba6e31L, 0xd130561ab936c8L, 0x0625f6c40dbef1L, + 0x7b2d6a2b6bb847L, 0x3ca8b2984d506bL }, + { 0x6bf729afb011b0L, 0x01c307833448c9L, 0x6ae95080837420L, + 0xf781a8da207fb8L, 0xcc54d5857562a9L, 0xc9b7364858c5abL, + 0xdfb5035359908fL, 0x8bf77fd9631138L } + }, + { + { 0xf523365c13fbb1L, 0x88532ea9993ed5L, 0x5318b025a73492L, + 0x94bff5ce5a8f3cL, 0x73f9e61306c2a0L, 0x00abbacf2668a3L, + 0x23ce332076237dL, 0xc867f1734c0f9bL }, + { 0x1e50995cfd2136L, 0x0026a6eb2b70f8L, 0x66cb1845077a7dL, + 0xc31b2b8a3b498eL, 0xc12035b260ec86L, 0x1cbee81e1b3df0L, + 0xfd7b8048d55a42L, 0x912a41cf47a8c8L } + }, + { + { 0xab9ffe79e157e3L, 0x9cfe46d44dc158L, 0x435551c8a4a3efL, + 0x638acc03b7e3a8L, 0x08a4ebd49954a7L, 0x295390c13194f7L, + 0x3a2b68b253892aL, 0xc1662c225d5b11L }, + { 0xcfba0723a5d2bbL, 0xffaf6d3cc327c9L, 0x6c6314bc67e254L, + 0x66616312f32208L, 0xf780f97bea72e1L, 0x495af40002122fL, + 0x3562f247578a99L, 0x5f479a377ce51eL } + }, +}, +{ + { + { 0x91a58841a82a12L, 0xa75417580f3a62L, 0x399009ff73417aL, + 0x2db1fb90a8c5cdL, 0x82c8912c046d51L, 0x0a3f5778f18274L, + 0x2ad0ede26ccae2L, 0x7d6bd8b8a4e9c2L }, + { 0xaa0d7974b3de44L, 0xf8658b996ac9bbL, 0x31e7be25f6c334L, + 0x23836ce4df12c9L, 0x029027b59eb5c9L, 0x2f225315b8649dL, + 0xa0fdf03d907162L, 0x101d9df9e80226L } + }, + { + { 0xf12037a9a90835L, 0xd2d0882f0222a7L, 0xeaf8d40c3814e2L, + 0xa986dc68b8146bL, 0x147a3318504653L, 0x734e0032feaf67L, + 0x6f27bbf602bec5L, 0xa1e21f16a688f3L }, + { 0x5a8eeab73c4ae5L, 0x4dbaddbe70b412L, 0x871cebacfd2af1L, + 0x18603827d7a286L, 0x024059db5bb401L, 0x2557c093c39b73L, + 0xfc5a7116681697L, 0xf881c0f891b57cL } + }, + { + { 0x3c443f18ea191aL, 0x76faa58d700ad0L, 0x6fe6cfabe7fcbfL, + 0xaefc5288990ef7L, 0x44e30fa80004ccL, 0xc744adc6d8ef85L, + 0xafcd931912df70L, 0xf62a9d1572a6d8L }, + { 0x47158a03219f27L, 0x76fb27ead73136L, 0x41bb2adcc2d614L, + 0x8858cb9de1ec21L, 0xab402c45f15866L, 0x6675d5bbc82bbfL, + 0x4ee9dd6f1b28d3L, 0x875884fe373c17L } + }, + { + { 0x17806dd2a67d36L, 0xaa23a8632c9ec1L, 0xd914126fc1ee55L, + 0xbf8f7bd653701bL, 0x9b0111aea71367L, 0x61fd4aba98e417L, + 0xeb45298561c5a5L, 0x2187b0ae7af394L }, + { 0x71f12db1616ddeL, 0x061760907da7b4L, 0x414d37602ddb04L, + 0x1100be7286fb58L, 0xd7cf88d6f0d95bL, 0x8539d23746d703L, + 0xdccc9d64e23d73L, 0xaeef1d2ec89680L } + }, + { + { 0x82ccf1a336508dL, 0xa128c1f5bad150L, 0x551d8c029a188dL, + 0xef13dd4771404fL, 0xdd67696c37b993L, 0x428c0e20dddad2L, + 0x222278d038c94cL, 0x1a24a51078e3f2L }, + { 0xd297fe6edb0db9L, 0x00988d28251a87L, 0xbb946f8bfaa0d7L, + 0x380f7b9df45ea0L, 0x8526415afccf5eL, 0x909bfbfe9ec7bcL, + 0x2ed7093124755cL, 0x436802889404e2L } + }, + { + { 0x21b9fa036d9ef1L, 0xfd64b7ce433526L, 0xd9d7eb76544849L, + 0x201620cd5b54b3L, 0x25fab3dbb61159L, 0x90d4eb0c53e0d3L, + 0xba098319e74772L, 0x8749658ec1681cL }, + { 0xa354349fec316bL, 0x639a9b1a743ea2L, 0x2e514ca37c50e6L, + 0x9f4a4fddbaf6c5L, 0x0df87ef6f511c9L, 0xadd4cef0c00d95L, + 0x401c0ebaa1433fL, 0x3c3a59ebb38af9L } + }, + { + { 0x8706245f0e7dcaL, 0xad238cd3fb29caL, 0x03304439b7d8f0L, + 0xfdcd6e6154f495L, 0xc67e24a7d4ad09L, 0x1b209e85438390L, + 0xf893b81b0c211eL, 0x1aa86f07e11e36L }, + { 0x2cca3ffedea8b1L, 0x7eedd073b306cdL, 0x78e37bc12ee222L, + 0x257870bbc42a1dL, 0x5fb2bb91fbd397L, 0x470247009d6c60L, + 0x11748a320bdc36L, 0x3ff24dc04280e8L } + }, + { + { 0x0eb1c679839b52L, 0x5bcca27acfbd32L, 0xb506c1674898e3L, + 0x37d662e2489e5eL, 0x8dc0731f694887L, 0x571149ef43f1dcL, + 0x6430a3766d63dcL, 0x0d2640eb50dd70L }, + { 0x2b561493b2675bL, 0x1b4806588c604fL, 0x55c86a8aafbabcL, + 0xa7b9447608aabaL, 0xa42f63504cad8cL, 0x0f72b1dcee7788L, + 0x1d68374755d99aL, 0xd7cdd8f5be2531L } + }, +}, +{ + { + { 0x67873bdbcdfee1L, 0xa5a0c0afcd0a3fL, 0x59389f93cfa3d4L, + 0x14e945ce1c865cL, 0x62d2f8e1d588ccL, 0xfd02f8a8e228b4L, + 0x208f791b42b649L, 0x0e0dff1ab397adL }, + { 0x30ac3d90bc6eb1L, 0xf14f16a5f313bbL, 0x70fa447e2a0ad2L, + 0x6e406855a0db84L, 0xd52282be32e1e7L, 0x315a02a15ca330L, + 0x9a57a70867c2feL, 0x55f07650054923L } + }, + { + { 0x2d729f6c0cf08fL, 0x6b80138ebaf57fL, 0x6285bcc0200c25L, + 0xee845192cd2ac7L, 0x28fce4d922778aL, 0x761325ccd1011cL, + 0xd01f2475100e47L, 0xc7a1665c60d8e1L }, + { 0x950966d7ceb064L, 0x0a88e8578420dbL, 0x44f2cfce096f29L, + 0x9d9325f640f1d2L, 0x6a4a81fd2426f1L, 0x3ed6b189c905acL, + 0xba3c0e2008854dL, 0x1df0bd6a0d321bL } + }, + { + { 0x0117ad63feb1e7L, 0xa058ba2f1ae02fL, 0x5eee5aa31b3f06L, + 0x540d9d4afacd4dL, 0x38992f41571d91L, 0xef2738ebf2c7deL, + 0x28bfcab92a798dL, 0x37c7c5d2286733L }, + { 0xb99936e6470df0L, 0x3d762d58af6a42L, 0xa8c357ac74eec5L, + 0x9917bebf13afbcL, 0x28f0941f2dc073L, 0x306abf36ce7df7L, + 0xa3c5f6fd6973c8L, 0x640209b3677632L } + }, + { + { 0xee872a2e23aef7L, 0xb497b6feb9b08eL, 0xfb94d973f33c63L, + 0x9ea1ff42b32315L, 0x537b49249a4166L, 0x89c7fe6ab4f8beL, + 0xf68007fdad8f0fL, 0xe56ef0b71b8474L }, + { 0x478b2e83f333f9L, 0x144e718b2607f5L, 0x13aa605a4c7ab5L, + 0xfc1fc991d0730dL, 0xe7a04375ab3ea1L, 0xc59986a306d8d3L, + 0x24f6111702a8b1L, 0x7741394e040ad2L } + }, + { + { 0x34c6a2560723a7L, 0x8aabd0df4ea691L, 0x9d676a55d7497fL, + 0x12c09577d91fa4L, 0x581c7a86479284L, 0xa54f3daf4fd449L, + 0x2f89f3c4ef44cfL, 0xfc266b5c9ec97cL }, + { 0xfcd3fbe88b142aL, 0x9f3109f4bd69c1L, 0x08839c0b5f5a6aL, + 0x63ca8502e68303L, 0x2f0628dbba0a74L, 0x743cccf5d56b54L, + 0xbd4b06613e09fdL, 0x7a8415bde2ba3eL } + }, + { + { 0x2234a3bc076ab2L, 0xd6953e54977a98L, 0xc12215831ebe2eL, + 0x632145fbad78e2L, 0xd7ba78aa5c4b08L, 0x6f4ea71998e32aL, + 0x25900d23485a63L, 0x97ac6286a5176fL }, + { 0x5df91181093f7bL, 0x2bf9829c844563L, 0x525d99d6272449L, + 0x4281cb5b5c8a18L, 0x35df2780544a08L, 0xf4c3d2dbaeb8f4L, + 0xc7ff3175230447L, 0x6b4d7645d2fbffL } + }, + { + { 0x4837f802b0c9cbL, 0xb65f8168ce8418L, 0xdf66ea99fc1428L, + 0x9788ee804ea7e8L, 0x9eae9008334e3cL, 0xbc91058d6ba1b6L, + 0x634aba1d7064b6L, 0x12d9bb3397b368L }, + { 0x0645c85c413aa8L, 0xb09dea6ac6b5e3L, 0x29a620d289a50bL, + 0x104db3bbbcceb1L, 0x42e479287b3309L, 0xdfc373eec97f01L, + 0xe953f94b93f84eL, 0x3274b7f052dfbfL } + }, + { + { 0x9d5670a1bd6fa9L, 0xec42fc9db6c4d4L, 0xaecd4ed1b42845L, + 0x4eed90e1b03549L, 0xeb3225cbbab1faL, 0x5345e1d28a2816L, + 0x3741cfa0b77d2aL, 0x712b19f7ea8caaL }, + { 0x42e6844661853eL, 0x4cf4126e4a6e5dL, 0x196a9cfc3649f6L, + 0x06621bcf21b6b1L, 0x887021c32e29eaL, 0x5703aeb8c5680fL, + 0x974be24660f6d7L, 0xaf09badc71864eL } + }, +}, +{ + { + { 0x3483535a81b6d3L, 0x19e7301ca037dcL, 0x748cab763ddfebL, + 0xe5d87f66f01a38L, 0xbba4a5c2795cd6L, 0x411c5d4615c36cL, + 0xff48efc706f412L, 0x205bafc4b519dfL }, + { 0xfcaa5be5227110L, 0x7832f463ad0af0L, 0x34ef2c42642b1bL, + 0x7bbef7b072f822L, 0x93cb0a8923a616L, 0x5df02366d91ba7L, + 0x5da94f142f7d21L, 0x3478298a14e891L } + }, + { + { 0xad79a0fc831d39L, 0x24d19484803c44L, 0x4f8a86486aeeb2L, + 0x0ca284b926f6b9L, 0x501829c1acd7cdL, 0x9f6038b3d12c52L, + 0x77223abf371ef5L, 0x2e0351613bf4deL }, + { 0x7a5a4f2b4468ccL, 0xdcea921470ae46L, 0xf23b7e811be696L, + 0xe59ad0d720d6fbL, 0x9eacac22983469L, 0x4dd4110c4397eeL, + 0x4ef85bdcbe2675L, 0xe4999f7aa7c74bL } + }, + { + { 0x031838c8ea1e98L, 0x539b38304d96a2L, 0x5fbdef0163956eL, + 0x6bd4d35ce3f52aL, 0xe538c2355e897fL, 0x6078d3a472dd3fL, + 0x590241eca9f452L, 0x2bc8495fd7fc07L }, + { 0x23d0c89ead4c8cL, 0x1ea55a9601c66eL, 0x41493c94f5b833L, + 0xc49a300aa5a978L, 0xc98bdc90c69594L, 0x4e44cedccbdc8cL, + 0xb0d4e916adccbfL, 0xd56e36b32c37aeL } + }, + { + { 0x052bd405b93152L, 0x688b1d44f1dbfaL, 0xe77ba1abe5cc5fL, + 0x11f8a38a6ac543L, 0x3355fd6e4bb988L, 0xdf29c5af8dffb4L, + 0x751f58981f20eeL, 0x22a0f74da9b7fbL }, + { 0xec8f2bc6397b49L, 0xff59fc93639201L, 0xb7f130aa048264L, + 0xe156a63afdc4ccL, 0x0fd7c34b13acafL, 0x87698d40cb4999L, + 0x6d6ecae7f26f24L, 0xae51fad0f296e2L } + }, + { + { 0xd0ad5ebdd0f58dL, 0x6ec6a2c5c67880L, 0xe1ce0349af1e0fL, + 0x08014853996d32L, 0x59af51e5e69d20L, 0x0ef743aaa48ecfL, + 0x8d3d2ea7dafcb0L, 0x4ac4fad89189b6L }, + { 0x92d91c2eae97f1L, 0xef5eca262b4662L, 0x440b213b38b10aL, + 0xec90187fc661daL, 0x85f3f25f64cf8dL, 0xcee53ca457ad1bL, + 0x8deed4bf517672L, 0x7706fb34761828L } + }, + { + { 0x1577d9117494feL, 0x52d29be2fd7239L, 0x9a0eef00186d37L, + 0x241d0f527fe108L, 0x42824bae6fb59fL, 0xb8d33df0d48c25L, + 0xfffdb0a47af4b0L, 0x534c601073b0b6L }, + { 0xe6df35951c033bL, 0x3e1002b86c0f94L, 0xa7cb55548fb9b6L, + 0x999818ba7bbff8L, 0xe4ba3d684d8bf2L, 0x53dbb326358f0aL, + 0xeebc1e2f2568e8L, 0xc6917ebb3e0f68L } + }, + { + { 0xbe1bbfc19f8d13L, 0xc3951b62d4795cL, 0x9371c49ed535a9L, + 0x77c389f68cebeaL, 0xfc1a947a141d0eL, 0x4b48d7ade44f8bL, + 0x3db1f058580a26L, 0xeed1466258b5fcL }, + { 0x5daa4a19854b21L, 0x5bfa46f1ab1eadL, 0xc152e3559957ebL, + 0xdc84277ea48adaL, 0x68709cffc169b5L, 0xde50ce3720e617L, + 0xe42f262dd9a832L, 0xddffd4d2d6ce29L } + }, + { + { 0xd5ba5578fa0a56L, 0x0d7d0f1fafaf4cL, 0x7666e4138b63edL, + 0x04e65135d87f02L, 0xdca8866c958f32L, 0xaa8486d3ce2686L, + 0xe3785caf1cbcd3L, 0x8a9b11403c8335L }, + { 0x5c1dca22e0ef60L, 0x775af5b7d3fb20L, 0xe690ffc2b373a8L, + 0x30fe15d28330e6L, 0x8a1022bdd0f393L, 0x6bd7364966a828L, + 0x8d4b154949208aL, 0xfb38c6bb9d9828L } + }, +}, +{ + { + { 0x6d197640340ac2L, 0x969f473ecab5ffL, 0xead46f7c458e42L, + 0x168646a1d00eedL, 0xf70c878e0ce0cfL, 0xa7291d38d8d15aL, + 0x92cf916fdd10ccL, 0x6d3613424f86d5L }, + { 0xba50d172d5c4b4L, 0xe0af5024626f15L, 0x76f3809d76098aL, + 0x433dc27d6caaa8L, 0x72dc67a70d97a7L, 0x935b360f5c7355L, + 0xdbaac93179bb31L, 0x76738487ed1a33L } + }, + { + { 0x8d1ca668f9fa0dL, 0x4ed95d8a02f2bfL, 0xd19fc79f630d7bL, + 0x0448ec4f46fa51L, 0xb371dd8623bf3fL, 0xe94fabcd650e94L, + 0x3af3fcacd90a70L, 0x0f720c403ce3b7L }, + { 0x590814cd636c3bL, 0xcf6928d4469945L, 0x5843aaf484a4c6L, + 0xb5a4c1af9b4722L, 0x25116b36cfb2f9L, 0xf248cf032c2640L, + 0x8cd059e27412a1L, 0x866d536862fc5dL } + }, + { + { 0x156e62f6de4a2eL, 0x0365af7aafcc78L, 0x65c861819e925eL, + 0x4db5c01f8b2191L, 0x1fd26d1ad564faL, 0x16bbc5319c8610L, + 0x0718eef815f262L, 0x8684f4727f83d1L }, + { 0xa30fd28b0f48dbL, 0x6fef5066ab8278L, 0xd164e771a652dfL, + 0x5a486f3c6ebc8cL, 0xb68b498dc3132bL, 0x264b6efd73323fL, + 0xc261eb669b2262L, 0xd17015f2a35748L } + }, + { + { 0x4241f657c4bb1dL, 0x5671702f5187c4L, 0x8a9449f3973753L, + 0x272f772cc0c0cdL, 0x1b7efee58e280cL, 0x7b323494b5ee9cL, + 0xf23af4731142a5L, 0x80c0e1dd62cc9eL }, + { 0xcbc05bf675ffe3L, 0x66215cf258ce3cL, 0xc5d223928c9110L, + 0x30e12a32a69bc2L, 0x5ef5e8076a9f48L, 0x77964ed2329d5fL, + 0xdf81ba58a72cf2L, 0x38ea70d6e1b365L } + }, + { + { 0x1b186802f75c80L, 0x0c153a0698665aL, 0x6f5a7fe522e8ddL, + 0x96738668ddfc27L, 0x7e421d50d3bdceL, 0x2d737cf25001b2L, + 0x568840f0e8490cL, 0xea2610be30c8daL }, + { 0xe7b1bc09561fd4L, 0xeda786c26decb0L, 0x22369906a76160L, + 0x371c71478a3da3L, 0x1db8fce2a2d9bfL, 0x59d7b843292f92L, + 0x8097af95a665f9L, 0x7cb4662542b7a9L } + }, + { + { 0xa5c53aec6b0c2fL, 0xc4b87327312d84L, 0xfc374cbc732736L, + 0xa8d78fe9310cc0L, 0xd980e8665d1752L, 0xa62692d6004727L, + 0x5d079280146220L, 0xbd1fedb860fea5L }, + { 0xcbc4f8ab35d111L, 0x5ba8cdf3e32f77L, 0xd5b71adb614b93L, + 0x7b3a2df2f8808dL, 0x09b89c26ef2721L, 0x55a505447c3030L, + 0x21044312986ae6L, 0x427a0112367d4cL } + }, + { + { 0xe9fe256c1942d8L, 0x9e7377d96e3546L, 0x43e734cb0c1744L, + 0x5f46821211fbcaL, 0x44f83dc32b6203L, 0x84513086ad1d96L, + 0x54dd5192fbb455L, 0xc2a18222f10089L }, + { 0x01055a21855bfaL, 0x9e6d7b477078b4L, 0x3f8df6d30cea0eL, + 0x81c215032973f7L, 0x17dd761c0b3d40L, 0x040424c50d0abeL, + 0x5599413783deabL, 0xde9271e8f3146fL } + }, + { + { 0x5edfd25af4a11dL, 0x3a3c5307846783L, 0xb20086873edd31L, + 0x74e00ecfe0eef8L, 0xba65d2f3dd78c7L, 0xab1364371999f1L, + 0xfa9be5dde9a7e8L, 0xeb146ce87a8609L }, + { 0x76afd6565353e9L, 0xfa7023dd51ba1cL, 0x7a09f2237ede4fL, + 0xca085760ba7a1bL, 0xd973882b99950aL, 0xe894266ea5057aL, + 0xd01c4217f55e49L, 0x69cfb9c5555679L } + }, +}, +{ + { + { 0x67867e7c5d631aL, 0x1de88c55bcf47bL, 0x8366d06afd1352L, + 0xd7dbdef6e20337L, 0xb0f9e2f1253ec7L, 0x1be984510ad240L, + 0x63ec533f4a6118L, 0xd5e4c5b96ce633L }, + { 0x1d0b6c34df4a25L, 0xef9486a5a1b554L, 0x2f0e59e47b6ef3L, + 0x4d8042f2ff84d7L, 0x3e74aa3da359c9L, 0x1baa16fd21c160L, + 0xb4cff210191cbaL, 0x50032d8ebc6472L } + }, + { + { 0xb6833e01fc1b13L, 0x8a8b7ba1a5ad8fL, 0xc0cafa2622b820L, + 0xc6663af738ed20L, 0xd8944868b18f97L, 0xcf0c1f9774fbe4L, + 0xeedd4355be814fL, 0xd81c02db57e543L }, + { 0x5e32afc310bad8L, 0x065bc819b813d1L, 0x8efc5fc3142795L, + 0x5006514732d59cL, 0x91e39df2b5a3ceL, 0x2ad4477faf4204L, + 0x1a96b184d9bd4fL, 0xc3fee95a4d9c07L } + }, + { + { 0xfac7df06b4ba61L, 0xa6ed551061aaefL, 0x35aa2d6133f609L, + 0x420cfba20ed13dL, 0x861c63eea03d0cL, 0x75f0c56f936d6eL, + 0xa25f68f3d9a3d5L, 0xba0b7fecd9f66eL }, + { 0x292e1354680772L, 0x6f6a2dba73f405L, 0xca6add924ea9e4L, + 0x81cfd61268daaaL, 0x7a4cb6ce6f147aL, 0x8ec3454bded8f5L, + 0xc8a893b11d61cbL, 0x2256ffc7656022L } + }, + { + { 0x6b33271575cb78L, 0x560d305adcd23eL, 0xeedbd3ad6d834bL, + 0x614a64a5a31e27L, 0xe40b47647ee0c8L, 0x8ef4ff68bd7c2cL, + 0xa5297fc0b77727L, 0x8759208baf88adL }, + { 0x86cfe64918df68L, 0x9d60a73cdd882eL, 0x546b642b953014L, + 0xbaceae38bbef55L, 0xdf58e43f1c3467L, 0x99a83fee9f9babL, + 0xcd52cbf57a4a8bL, 0xf744e968ae36ecL } + }, + { + { 0xb945869a607124L, 0x810dbe9440e6f6L, 0x9911e60738e381L, + 0x51df68c343b80bL, 0xe424336f7a3f39L, 0x2d32acb989015cL, + 0xa69b14931019e8L, 0x8a31a38ec12f93L }, + { 0x0d0d36997c916aL, 0xdc95f3b8885372L, 0xcf1a2613549040L, + 0x60f6f5eabe95a2L, 0xa909e9fe141325L, 0x7d598f2355c865L, + 0x70c6442931a9c9L, 0x2354a85b423850L } + }, + { + { 0x4cdd22497f9619L, 0x4776fffc22162eL, 0xee5ec330cd31c2L, + 0x7c04c10f209bb8L, 0x35bbfde579e211L, 0x0e3832515cdfc2L, + 0x657e6d3e26ffa7L, 0xc66a7c3c65c604L }, + { 0x322acd7b45e567L, 0x1589cf0296db9bL, 0x1fd0bd3ba1db73L, + 0xe8826109337a40L, 0xf505a50b3035c7L, 0x4d5af066ed08d7L, + 0xb3c376b5eda400L, 0x9c7b7001944748L } + }, + { + { 0xd76832570c3716L, 0xda62af0dd540e0L, 0x76b155d6580feaL, + 0x4f42acc32b5464L, 0x881bb603f5b72bL, 0x09c130ee68b9baL, + 0x37ede3b5c50342L, 0xce61a9cfd15e7dL }, + { 0xfff1d8572605d0L, 0x62ac2d3062abc2L, 0xa85e02efbe43ddL, + 0x859d2baa947020L, 0x2ebc8a9111c20bL, 0x7f590a7a656f66L, + 0x0e1384316b21a6L, 0x29b30c500c7db6L } + }, + { + { 0x61e55e2906b8deL, 0x6a97e96949974dL, 0x24b52b526eef67L, + 0x512f5361aa595aL, 0x81cc7b83c48fcbL, 0xa64af2328115adL, + 0x9edf6f93d44b8eL, 0x68d7f7c1fe22e3L }, + { 0x2b2116a520d151L, 0x66a0b7d6aa3efbL, 0x48ae70a9b0f791L, + 0xcf12174037db88L, 0x36868cd317d9f3L, 0xb57305922fc344L, + 0xbaa852646a5d23L, 0xad6569137fc10dL } + }, +}, +{ + { + { 0xcf8e5f512c78d5L, 0xeb94d98805cdbdL, 0xad1dcdf2ab50b5L, + 0xf33c136f33cd31L, 0x0d6226b10aeff5L, 0xf7ff493f2f8fc5L, + 0x7e520d4df57165L, 0x41fbae505271a7L }, + { 0x72c898776480baL, 0x260835925f4523L, 0xed36b8d49f5f01L, + 0x3bc1dcef3d49ebL, 0x30c1c1a4940322L, 0x78c1cda7e0f731L, + 0x51f2dc86d05a31L, 0x57b0aa807f3522L } + }, + { + { 0x7ab628e71f88bcL, 0xcf585f38018f21L, 0xdbbe3a413d64f6L, + 0x0f86df1ec493a5L, 0x8355e6c7725de9L, 0x3954ffee00fe1eL, + 0xbb8978f9924e32L, 0x1c192987812714L }, + { 0x7c4ce3eaabca8bL, 0xf861eb59bf7019L, 0x31a84fc682e541L, + 0x2307ca9acd1b92L, 0x6f8b6ce4bf2842L, 0xde252accb9f9a9L, + 0x7f0611d93c46d1L, 0x8e2bd80751dc98L } + }, + { + { 0xf2fd8fbe27d54bL, 0x2a1e37ec248071L, 0x2fcc888ab8f49aL, + 0x42c62a3c18a9e5L, 0xe30290870b2446L, 0x90277fac5ac55dL, + 0x8d97d56d6dde41L, 0xf4cf8a95db04feL }, + { 0x3e280f5d30d077L, 0x2c903073cb3293L, 0xe0be2ac24eb0ddL, + 0xa2d1a498bcb4f0L, 0x16db466cd0cd45L, 0x3b28aa79a80232L, + 0xdd7e52f17b008eL, 0x20685f2868e4daL } + }, + { + { 0x0a68c147c7a486L, 0xd8ef234c429633L, 0x470667bffe7506L, + 0x55a13c88828d51L, 0x5f327412e44befL, 0x537d92a5929f92L, + 0x0a01d5b31c5cd5L, 0xb77aa7867eb3d7L }, + { 0x36ec45f8b82e4dL, 0x6821da0b37b199L, 0x8af37aad7fa94eL, + 0xf0206421085010L, 0x9b886787e56851L, 0x35f394452948ceL, + 0x125c2baafc1361L, 0x8a57d0e453e332L } + }, + { + { 0xefe99488043664L, 0xb8b8509db1aa55L, 0x1a2e5a9332523fL, + 0x5e255dd1045c0fL, 0xe68dd8a7ae7180L, 0x55f1cf345bf532L, + 0xe00722ee63a716L, 0xd1c21386116bacL }, + { 0x626221f1c6d1f4L, 0x240b8303773278L, 0xe393a0d88def16L, + 0x229266eca0495cL, 0x7b5c6c9d3e4608L, 0xdc559cb7927190L, + 0x06afe42c7b3c57L, 0x8a2ad0bb439c9bL } + }, + { + { 0xd7360fbffc3e2fL, 0xf721317fbd2e95L, 0x8cacbab5748e69L, + 0x7c89f279054bb9L, 0xcbe50faaa86881L, 0x7aa05d375206e4L, + 0x1ea01bcc752c66L, 0x5968cde1f2c2bcL }, + { 0x487c55f09a853eL, 0x82cbef1e09204bL, 0xad5c492abd8670L, + 0x7175963f12dcb3L, 0x7a85762bf6aa06L, 0x02e5697f8d5237L, + 0xccf7d1937c6157L, 0x3b14ca6c2fd59cL } + }, + { + { 0x5e610d81b9f77fL, 0x85876d0051b02fL, 0x5d81c63b8020ddL, + 0xd0b4116d6ce614L, 0x91810e5aa8bf0cL, 0xf27f91fcbf8c66L, + 0x2e5dc5f38480aeL, 0x0a13ffebec7633L }, + { 0x61ff6492bf6af8L, 0xe6aef2d641f827L, 0xad5708a5de5f04L, + 0xe5c3a80cdfee20L, 0x88466e268fcfa2L, 0x8e5bb3ad6e1d7bL, + 0xa514f06ed236b8L, 0x51c9c7ba5f5274L } + }, + { + { 0xa19d228f9bc3d8L, 0xf89c3f03381069L, 0xfee890e5c3f379L, + 0x3d3ef3d32fb857L, 0x39988495b418ddL, 0x6786f73c46e89aL, + 0x79691a59e0f12fL, 0x76916bf3bc022bL }, + { 0xea073b62cd8a0aL, 0x1fbedd4102fdbcL, 0x1888b14cb9d015L, + 0x98f2cfd76655f7L, 0xb9b591059f0494L, 0xa3dbbe1e6986a3L, + 0xef016a5eaf2b04L, 0xf671ba7cd2d876L } + }, +}, +{ + { + { 0x1dae3bf1ae05e9L, 0x6a029961f21fefL, 0x95df2b97aec3c6L, + 0x9abbc5ad83189bL, 0xaf994af2d13140L, 0xc3f884686aa406L, + 0xcd77e5075284c5L, 0x1c1e13d2a9a4d7L }, + { 0x7f8815d744b89dL, 0xb1891332ba673eL, 0x55ea93cd594570L, + 0x19c8a18d61b041L, 0x938ebaa8d2c580L, 0x9b4344d05ba078L, + 0x622da438eaf9b7L, 0x809b8079fea368L } + }, + { + { 0x3780e51c33b7a2L, 0xd7a205c387b1c8L, 0x79515f84be60e4L, + 0xde02a8b1e18277L, 0x4645c96f0d9150L, 0x45f8acbe0b3fd1L, + 0x5d532ba9b53ac3L, 0x7984dcdb0557c9L }, + { 0x5ae5ca68a92f01L, 0xd2fbb3c9d569caL, 0x668cc570c297c1L, + 0xa4829436295e89L, 0xf646bc1a33ad40L, 0x066aaa4c3f425dL, + 0x23434cdd005de2L, 0x5aca9e9db35af4L } + }, + { + { 0x2bca35c6877c56L, 0xab864b4f0ddd7dL, 0x5f6aa74404f46cL, + 0x72be164539c279L, 0x1b1d73ee0283cfL, 0xe550f46ad583d9L, + 0x4ac6518e739ad1L, 0x6b6def78d42100L }, + { 0x4d36b8cfa8468dL, 0x2cb37735a3d7b8L, 0x577f86f5016281L, + 0xdb6fe5f9124733L, 0xacb6d2ae29e039L, 0x2ab8330580b8a1L, + 0x130a4ac643b2d0L, 0xa7996e35e6884eL } + }, + { + { 0x6fb627760a0aa8L, 0xe046843cbe04f0L, 0xc01d120e6ad443L, + 0xa42a05cabef2fcL, 0x6b793f112ff09cL, 0x5734ea8a3e5854L, + 0xe482b36775f0adL, 0x2f4f60df864a34L }, + { 0xf521c5884f2449L, 0x58734a99186a71L, 0x157f5d5ac5eaccL, + 0x858d9a4248ee61L, 0x0727e6d48149c3L, 0xd5c3eaaac9ec50L, + 0xa63a64a20ee9b5L, 0x3f0dfc487be9deL } + }, + { + { 0x836349db13e3f4L, 0xebdd0263e9316dL, 0x3fd61e8324fd6cL, + 0x85dddfa0964f41L, 0x06e72de52add1bL, 0xb752cff8c4a9e2L, + 0x53b0894fdf09f7L, 0xd5220ab0bc24fdL }, + { 0x8442b35fb1981aL, 0xa733a373edd701L, 0x42b60c3d0ef089L, + 0xa1b16ec46e7bcaL, 0xc0df179a09aaf4L, 0xcd4f187638f3a1L, + 0x9af64f79eab1c2L, 0x86fed79d1d78e3L } + }, + { + { 0x42c8d86fe29980L, 0x6657b816575660L, 0x82d52c680f92caL, + 0x8587af102d42beL, 0xb5151316e8bdf0L, 0x706e2d9c333495L, + 0xd53601a9673064L, 0x27b1fbb8219099L }, + { 0x3f0929d705f7c8L, 0xff40b10f3d6e6fL, 0x673c703026af5cL, + 0x2c1dce4e25a422L, 0x5348bd73dad8b6L, 0xc39b6b6be2c329L, + 0x47854ffb921084L, 0xb347b8bb391f20L } + }, + { + { 0x79fc841eb9b774L, 0xf32da25b4b6c1dL, 0xcbba76bfe492cbL, + 0x76c51fcd623903L, 0x114cf6fcf0705aL, 0x6b720497815dafL, + 0x630b362473382eL, 0xbf40c3a9704db5L }, + { 0xa8a9ddcc5456ebL, 0x2b4472a72f2dc1L, 0x9874444d6d6ef3L, + 0x27e8d85a0ba5edL, 0x5d225b4194849fL, 0xe852cd6ebaa40dL, + 0xb669c248d4bf3fL, 0xa8601eb2343991L } + }, + { + { 0x8a0485459502d3L, 0xcab27eee269a7bL, 0x41793074875adaL, + 0x179e685e2405f9L, 0x0d7b6987b28963L, 0x80c9db8422a43eL, + 0xf5ff318a0f43eeL, 0x7a928054ba7aa7L }, + { 0xa5c79fe0c0834eL, 0x837ca0d1f849ecL, 0xfe0d7fa628ab7bL, + 0x94bcb956edd19aL, 0xa18bc932226fbfL, 0x2795379aad54a3L, + 0xceeacf8371129eL, 0x65ca57fa588be5L } + }, +}, +{ + { + { 0x7a578b52caa330L, 0x7c21944d8ca34aL, 0x6c0fbbb6447282L, + 0xa8a9957f90b2e5L, 0xbbe10666586b71L, 0x716a90249138a2L, + 0x2fa6034e7ed66dL, 0x56f77ed2b9916aL }, + { 0x69f1e26bddefb3L, 0xa4978098c08420L, 0xc3377eb09bc184L, + 0x796ce0cbe6dadeL, 0x3be0625d103bbbL, 0x01be27c992685cL, + 0xc0e25597755f9fL, 0x165c40d1c0dbfaL } + }, + { + { 0xc63a397659c761L, 0x10a0e5b630fbadL, 0xf21e8a6655ac56L, + 0xe8580fac1181e2L, 0xbfc2d9c0a84b5cL, 0x2cdbaff7afd5d1L, + 0x95f1182f61e85aL, 0x1173e96719eaf4L }, + { 0xc06d55ec6de8b9L, 0x1b4c8ebafcbcaaL, 0x52af5cbbc2bbcdL, + 0x564fab877bcd10L, 0xfd53a18ae85a6eL, 0x225785994c712fL, + 0x29b11d71352121L, 0xab1cb76c40491aL } + }, + { + { 0xb4e8ca8ce32eb4L, 0x7e484acb250b49L, 0x062c6f7a3e31a2L, + 0x497fd83625d1fcL, 0x98f821c362dda7L, 0xcae1f8f6be3111L, + 0x9077e955d4fa42L, 0xa589971a65855aL }, + { 0xda6321d28832a9L, 0xf9ef5dc3936e9eL, 0xa37f117c9797efL, + 0x0eb3c80db581beL, 0x207c5c4baa0002L, 0xc0401b5f38faa0L, + 0xceee523d0f1e6eL, 0x8d27a5fd1f0045L } + }, + { + { 0x9411063cf0af29L, 0x304385789a6693L, 0x9a9fb8f640145eL, + 0x7d82fe954832ebL, 0xf2789e1898c520L, 0x448b402f948dc0L, + 0xeca8fdf68996ddL, 0x22227e9a149b2fL }, + { 0x63509ff8e62d6aL, 0xe98d81c8c9c57fL, 0xd3874071fe3bedL, + 0xf1db013539538fL, 0xb04092e48418ceL, 0xbbf8e76d6d9d4dL, + 0x2ea9cda2cec5aeL, 0x8414b3e5078fa9L } + }, + { + { 0x5ad1cdbd68a073L, 0xd4cedafc18b591L, 0x78267078e4c1c9L, + 0x9b8d9209ca302aL, 0x3101bd2326115bL, 0x6f154b54c2717aL, + 0x618c31b263e84bL, 0x12c4138bbd6942L }, + { 0xf9ead2580da426L, 0xe748e9947d9680L, 0x9b396a38a4210eL, + 0xfaf03ddf4b8f72L, 0xbd94a5266159e7L, 0x5e730491d4c7cbL, + 0x31d1f9a7910f38L, 0x4fd10ca08d6dd1L } + }, + { + { 0x4f510ac9f2331eL, 0xee872dc7e3dcc2L, 0x4a11a32a0a0c73L, + 0x27e5803aa5a630L, 0xe5ae5037af4a8aL, 0x2dcdeba9fffeb0L, + 0x8c27748719d91fL, 0xd3b5b62b9cc61cL }, + { 0x998ac90cca7939L, 0xc22b59864514e5L, 0x950aaa1b35738aL, + 0x4b208bbdab0264L, 0x6677931a557d2eL, 0x2c696d8f7c17d3L, + 0x1672d4a3e15c51L, 0x95fab663db0e82L } + }, + { + { 0x3d427346ff205eL, 0x7f187d90ea9fbeL, 0xbd9367f466b2afL, + 0x188e53203daf2fL, 0xefe132927b54d8L, 0x14faf85ef70435L, + 0xa5061281ec95c4L, 0xad01705c22cba7L }, + { 0x7d2dfa66197333L, 0xedd7f078b4f6edL, 0xe0cb68575df105L, + 0x47c9ddb80f76bcL, 0x49ab5319073c54L, 0x845255ae607f44L, + 0x0b4ed9fcc74b7cL, 0xcfb52d50f5c3a6L } + }, + { + { 0x545c7c6c278776L, 0x92a39ae98c30f0L, 0x8aa8c01d2f4680L, + 0xa5409ed6b7f840L, 0x0c450acdcb24e7L, 0x5da6fb2c5770d9L, + 0x5b8e8be8658333L, 0xb26bf4a67ea4adL }, + { 0x2e30c81c7d91faL, 0x6e50a490eeb69fL, 0x9458c2bee4bc26L, + 0x419acf233be250L, 0x79d6f8187881abL, 0x694565d403b1beL, + 0x34b3990234fe1dL, 0x60997d72132b38L } + }, +}, +{ + { + { 0x00a974126975dcL, 0x42161c46cf94e7L, 0xcc9fe4bc64ed99L, + 0x020019a4680570L, 0x885595a698da0dL, 0x008444b77dd962L, + 0xbf3c22da4fea0eL, 0xc4630482c81245L }, + { 0xcb248c5793ab18L, 0x4dc7a20eb4320bL, 0x9a0906f1572b7dL, + 0xd5b3019f9ac20fL, 0x79b1bf534520a3L, 0x788dfe869b5322L, + 0x9a05298455b7e2L, 0x2f4aecb016bca9L } + }, + { + { 0x414d3798745618L, 0x64ba22eb7c983cL, 0x9a5d19f9f9d532L, + 0x81a00d844a80c8L, 0xb9e24f5cae98d6L, 0x6c3769caca965aL, + 0x50d6081f6e4e6dL, 0x0d9698054422a6L }, + { 0xbd7e7925cdd790L, 0xcff65da6a35219L, 0x40dc3638b60ebeL, + 0x84bee7492a50dcL, 0x57d4be415ad65eL, 0xc54256b1a6d1d3L, + 0x141c64945717ccL, 0x05eb609cd1c736L } + }, + { + { 0xfd52eab1e3c7ecL, 0xa4a5eca9f24895L, 0xaaa2a8d79fdb83L, + 0xd105e6072bdfdaL, 0x59e6ae2681d97eL, 0xfedf8e08e8077fL, + 0xb06d0ad629e462L, 0x8c7c2d096fa863L }, + { 0x5eecc4cee8fc91L, 0x5e83ab29e61174L, 0x1fd8925b28c02dL, + 0x93be5382072864L, 0xda0c88624c984eL, 0xdcf9f0ca008286L, + 0x1ecb5a6a58ba75L, 0x1d9b890c2e3c83L } + }, + { + { 0x19e866eeeee062L, 0x31c1c7f4f7b387L, 0x9be60181c06652L, + 0xc00a93a2b68bbbL, 0x54c65d69d52b2bL, 0x4591416e8b744aL, + 0x641bcca9a64ab6L, 0xf22bcb1ab08098L }, + { 0x3c0db8ff1f726cL, 0x4f5739e9d2e6a6L, 0x5cb669b45c9530L, + 0x861b04e7b472d0L, 0x3e30515894da77L, 0x3344685c9ac39bL, + 0x9e1730573bdd29L, 0x9cac12c808dc85L } + }, + { + { 0xf152b865e27087L, 0x267bd8590a580eL, 0xba79cec8baafc1L, + 0x6140ab19442686L, 0xa67090c5b31693L, 0x50a103a28b4117L, + 0x7722e610ddc08fL, 0x5d19d43e6569b2L }, + { 0x70e0c525962bf6L, 0x808e316fb5fb02L, 0x3fb80da5b667beL, + 0x8aa366efcfacecL, 0xcb0b3e7134280eL, 0x0bf1de4cd7d944L, + 0x0cd23bed092df5L, 0xc9a6a79a153a0cL } + }, + { + { 0x1c69ad02d5a4b7L, 0x4bb28d0d9e6f4aL, 0x815308ca984fc6L, + 0x40929c79037ca5L, 0x0ea2b491bd0357L, 0xec17e5b42aad4eL, + 0x1f32ade18e7235L, 0xbc60b05a96a9d3L }, + { 0x3b0229ae20f707L, 0xd63505056bdfadL, 0xac2d922d8b2e1eL, + 0x92b2998235c748L, 0x6002c3ad766f97L, 0x99198001a2a862L, + 0x2af7567b58b684L, 0xd8fe707aaafce5L } + }, + { + { 0x54487ab5df7a4bL, 0x51cccdec57ccc2L, 0x23943277510b53L, + 0x3a09f02f555de3L, 0xa696aec1be484dL, 0x56f459f37817a2L, + 0x8d8f61c623dcb4L, 0xc52223c5335656L }, + { 0xf634111b49914aL, 0xbf8e1ab8e4f9bbL, 0x2f59578f4dba02L, + 0x2a94199e004319L, 0x87931f0654d005L, 0x7df57d96fa0814L, + 0xc8da316a154031L, 0x2a44ac041f658bL } + }, + { + { 0xfb5f4f89e34ac6L, 0x0a1b10b97790f2L, 0x58fe4e74b8a06cL, + 0x10c1710955f27cL, 0x77b798ad5ebe19L, 0xaf1c35b1f1c2dcL, + 0xc25b8e6a1f8d69L, 0x49cf751f76bf23L }, + { 0x15cb2db436f7b7L, 0x186d7c27e74d1aL, 0x60731dec00a415L, + 0xea1e15615f0772L, 0xf02d591714463fL, 0x26a0c6451adeb1L, + 0x20174cdcc5229eL, 0xb817e50efd512aL } + }, +}, +}; + +static const ge448_precomp base_i[16] = { + { + { 0x26a82bc70cc05eL, 0x80e18b00938e26L, 0xf72ab66511433bL, + 0xa3d3a46412ae1aL, 0x0f1767ea6de324L, 0x36da9e14657047L, + 0xed221d15a622bfL, 0x4f1970c66bed0dL }, + { 0x08795bf230fa14L, 0x132c4ed7c8ad98L, 0x1ce67c39c4fdbdL, + 0x05a0c2d73ad3ffL, 0xa3984087789c1eL, 0xc7624bea73736cL, + 0x248876203756c9L, 0x693f46716eb6bcL } + }, + { + { 0x28173286ff2f8fL, 0xb769465da85757L, 0xf7f6271fd6e862L, + 0x4a3fcfe8daa9cbL, 0xda82c7e2ba077aL, 0x943332241b8b8cL, + 0x6455bd64316cb6L, 0x0865886b9108afL }, + { 0x22ac13588ed6fcL, 0x9a68fed02dafb8L, 0x1bdb6767f0bffaL, + 0xec4e1d58bb3a33L, 0x56c3b9fce43c82L, 0xa6449a4a8d9523L, + 0xf706cbda7ad43aL, 0xe005a8dbd5125cL } + }, + { + { 0xa99d1092030034L, 0x2d8cefc6f950d0L, 0x7a920c3c96f07bL, + 0x958812808bc0d5L, 0x62ada756d761e8L, 0x0def80cbcf7285L, + 0x0e2ba7601eedb5L, 0x7a9f9335a48dcbL }, + { 0xb4731472f435ebL, 0x5512881f225443L, 0xee59d2b33c5840L, + 0xb698017127d7a4L, 0xb18fced86551f7L, 0x0ade260ca1823aL, + 0xd3b9109ce4fd58L, 0xadfd751a2517edL } + }, + { + { 0xdf9567ceb5eaf7L, 0x110a6b478ac7d7L, 0x2d335014706e0bL, + 0x0df9c7b0b5a209L, 0xba4223d568e684L, 0xd78af2d8c3719bL, + 0x77467b9a5291b6L, 0x079748e5c89befL }, + { 0xe20d3fadac377fL, 0x34e866972b5c09L, 0xd8687a3c40bbb7L, + 0x7b3946fd2f84c9L, 0xd00e40ca78f50eL, 0xb87594417e7179L, + 0x9c7373bcb23583L, 0x7ddeda3c90fd69L } + }, + { + { 0x3d0def76ab686bL, 0x1a467ec49f7c79L, 0x3e53f4fc8989edL, + 0x101e344430a0d9L, 0xa3ae7318ad44eeL, 0xaefa6cdae1d134L, + 0xaa8cd7d824ad4dL, 0xef1650ced584fcL }, + { 0xa74df674f4754fL, 0xf52cea8ef3fb8bL, 0x47c32d42971140L, + 0x391c15da256fbbL, 0xc165faba605671L, 0xf2518c687993b9L, + 0x2daf7acbd5a84dL, 0x1560b6298f12aeL } + }, + { + { 0xef4da0254dc10aL, 0x63118655940db8L, 0xe20b14982f2948L, + 0x67b93775581dbaL, 0x422ee7104f5029L, 0x5d440db5122d34L, + 0xb1e56d71a4c640L, 0xbf12abbc2408eeL }, + { 0x0cc9f86016af01L, 0x88366abf3d8cabL, 0x85dda13a2efe12L, + 0x390df605d00674L, 0xf18f5806d187f7L, 0x28c900ff0c5d20L, + 0xad308123e01733L, 0x42d35b554bf2fdL } + }, + { + { 0x009135f2ffb1f1L, 0x099fc7e8f9c605L, 0xcc67da626bfa5aL, + 0xc186d12344552bL, 0xb5232501b339e1L, 0x70a544fc9708c5L, + 0x06baaec1e928e7L, 0x0baedd2ef0f50fL }, + { 0x535d6d8bf479e5L, 0x156e536e4ec3e9L, 0x3165741ddb9be2L, + 0x988af7159fd736L, 0x13d8a782e33dddL, 0x54604214e69002L, + 0x34d56e0804a268L, 0xc59b84f0e52a4cL } + }, + { + { 0x525d45f24729d9L, 0x5768aba8712327L, 0xa25e43b43035dbL, + 0x15a1ee8927ef21L, 0xa785d216056112L, 0x45e2fbfd508af9L, + 0xb6f721a37ba969L, 0x30d6d8c216d8d3L }, + { 0x3065e0852074c3L, 0xfa40b4a2a0684eL, 0x851325a763f955L, + 0xd4ef19c9f25900L, 0x799c869f665756L, 0x7b052223312990L, + 0xc986c2b28db802L, 0xf48fb8f28ade0aL } + }, + { + { 0x1e461731649b68L, 0xa96e5d65beb9dcL, 0x765ddff481935dL, + 0x6cf132c9f3bf2aL, 0x9f6c5c97c35658L, 0x99cd1394696e60L, + 0x99fa9249c0d5e4L, 0x1acd0638845a95L }, + { 0x0b065413636087L, 0xea20e78ea17b7fL, 0x20afc5f6161967L, + 0xfd6c8a2dc81028L, 0x4ef1357e32c8fdL, 0x8aa400400e4a88L, + 0xd6fcaef48cb82fL, 0x7ba7c6db3cd4faL } + }, + { + { 0xf843473d19c7abL, 0x968e76dc655c4dL, 0x52c87d9c4b9c2fL, + 0x65f641ae4aa082L, 0x491a39733c3603L, 0xa606ffe5810098L, + 0x09920e68bf8ad4L, 0x691a0c86db7882L }, + { 0x5205883a4d3ef5L, 0xee839b7acf2efeL, 0x4b78e2ac00ca66L, + 0xbe3f071f9fcb91L, 0x61e66c9bf6943aL, 0xe9b4e57061b79dL, + 0x8d1b01b56c06bdL, 0x0dfa315df76ae5L } + }, + { + { 0x803df65f1fd093L, 0x1cd6523489b77eL, 0x2cd2e15c20e295L, + 0xcd490be9b912d1L, 0xdd9a2ff2e886d2L, 0xa3c836dfe9d72aL, + 0xfcad5f2298e0c1L, 0xed126e24bcf067L }, + { 0x1e339533dc81bcL, 0xbea4d76ece6a08L, 0x1d15de3991b252L, + 0x74cc5cfe6daf97L, 0x5ad343f0826493L, 0x2d38a471064049L, + 0xf7f47b9ffcfa4dL, 0xef14490418066cL } + }, + { + { 0x4e7f86b9bb55abL, 0x310d7853f496a3L, 0xbd682fc0dec42cL, + 0xbde047a411d32aL, 0xea639b4c5a5ea2L, 0x5052078ba08fa1L, + 0xc968b2307729f2L, 0x567b5a623d3e28L }, + { 0x171e825977fbf7L, 0x0319c70be990aaL, 0x8f65023e12cd69L, + 0x1fb9b19f5015e6L, 0x0083f603568a7cL, 0xba3d30b1f3c5acL, + 0xe7b509d3d7a988L, 0x2318b99cd0f6b6L } + }, + { + { 0x54d3b8793ab2cfL, 0x366abead2d8306L, 0x66e8eb6d7a4977L, + 0xa61888cae0072eL, 0x9eeeef5dbc3315L, 0x93f09db163e7f5L, + 0xee9095959ade9aL, 0xaf7f578ce59be0L }, + { 0x24bfd8d5ece59eL, 0x8aa698b3689523L, 0xa9a65de2de92cfL, + 0xec11dbca6ad300L, 0x217f3fa09f88caL, 0xf6c33e3b4d6af7L, + 0xcd3bfa21d86d2dL, 0x1497f835f13f25L } + }, + { + { 0xa579568cd03d1dL, 0xd717cdae158af6L, 0x59eda97389a19fL, + 0xb32c370099e99cL, 0xa2dba91dabb591L, 0x6d697d577c2c97L, + 0x5423fc2d43fa6dL, 0x56ea8a50b382bfL }, + { 0x4a987bad80c11aL, 0xe4cde217d590a5L, 0x3dd8860f97e559L, + 0xff45e2543b593cL, 0x00eb4535343cb5L, 0x06b9b997bbfbddL, + 0x4da36b716aea24L, 0x247651757a624eL } + }, + { + { 0x32207d03474e0dL, 0x3ffbf04b41cc73L, 0x5c4dc45319eb39L, + 0xfee29be758b463L, 0xcc8a381c30c7a7L, 0x147f4e49fe0e53L, + 0x05b2e26e35a2deL, 0x4362f0292f3666L }, + { 0x0476d0c8474b85L, 0x9d8c65fccaf108L, 0xf58d4041d54b6aL, + 0x3ee6862f38e4b0L, 0x7c7c9d53b44f54L, 0x36a3fd80fb0db5L, + 0xfcd94ba18a8ac8L, 0xc1b1d568f35c05L } + }, + { + { 0x16539fc1bdd30dL, 0x1356e538df4afbL, 0xc0545d85a1aedbL, + 0xeb2037a489396bL, 0x897fcbd5660894L, 0x02a58a9b7d104aL, + 0x57fa24cc96b980L, 0xf6448e35bd8946L }, + { 0xee727418805c83L, 0x10fa274992cfc6L, 0x95141939e66b21L, + 0xe0ffa44bd08009L, 0x174332220da22bL, 0x4891ff359e6831L, + 0x407ed73a7d687bL, 0x2fb4e0751d99cfL } + }, +}; +#else + +/* Reduce scalar mod the order of the curve. + * Scalar Will be 114 bytes. + * + * b [in] Scalar to reduce. + */ +void sc448_reduce(uint8_t* b) +{ + uint32_t d[16]; + uint64_t t[33]; + uint64_t c; + uint32_t o; + + /* Load from bytes */ + t[ 0] = (((int32_t)((b[ 0] ) >> 0)) << 0) + | (((int32_t)((b[ 1] ) >> 0)) << 8) + | (((int32_t)((b[ 2] ) >> 0)) << 16) + | ((((int32_t)((b[ 3] & 0xf )) >> 0)) << 24); + t[ 1] = (((int32_t)((b[ 3] ) >> 4)) << 0) + | (((int32_t)((b[ 4] ) >> 0)) << 4) + | (((int32_t)((b[ 5] ) >> 0)) << 12) + | (((int32_t)((b[ 6] ) >> 0)) << 20); + t[ 2] = (((int32_t)((b[ 7] ) >> 0)) << 0) + | (((int32_t)((b[ 8] ) >> 0)) << 8) + | (((int32_t)((b[ 9] ) >> 0)) << 16) + | ((((int32_t)((b[10] & 0xf )) >> 0)) << 24); + t[ 3] = (((int32_t)((b[10] ) >> 4)) << 0) + | (((int32_t)((b[11] ) >> 0)) << 4) + | (((int32_t)((b[12] ) >> 0)) << 12) + | (((int32_t)((b[13] ) >> 0)) << 20); + t[ 4] = (((int32_t)((b[14] ) >> 0)) << 0) + | (((int32_t)((b[15] ) >> 0)) << 8) + | (((int32_t)((b[16] ) >> 0)) << 16) + | ((((int32_t)((b[17] & 0xf )) >> 0)) << 24); + t[ 5] = (((int32_t)((b[17] ) >> 4)) << 0) + | (((int32_t)((b[18] ) >> 0)) << 4) + | (((int32_t)((b[19] ) >> 0)) << 12) + | (((int32_t)((b[20] ) >> 0)) << 20); + t[ 6] = (((int32_t)((b[21] ) >> 0)) << 0) + | (((int32_t)((b[22] ) >> 0)) << 8) + | (((int32_t)((b[23] ) >> 0)) << 16) + | ((((int32_t)((b[24] & 0xf )) >> 0)) << 24); + t[ 7] = (((int32_t)((b[24] ) >> 4)) << 0) + | (((int32_t)((b[25] ) >> 0)) << 4) + | (((int32_t)((b[26] ) >> 0)) << 12) + | (((int32_t)((b[27] ) >> 0)) << 20); + t[ 8] = (((int32_t)((b[28] ) >> 0)) << 0) + | (((int32_t)((b[29] ) >> 0)) << 8) + | (((int32_t)((b[30] ) >> 0)) << 16) + | ((((int32_t)((b[31] & 0xf )) >> 0)) << 24); + t[ 9] = (((int32_t)((b[31] ) >> 4)) << 0) + | (((int32_t)((b[32] ) >> 0)) << 4) + | (((int32_t)((b[33] ) >> 0)) << 12) + | (((int32_t)((b[34] ) >> 0)) << 20); + t[10] = (((int32_t)((b[35] ) >> 0)) << 0) + | (((int32_t)((b[36] ) >> 0)) << 8) + | (((int32_t)((b[37] ) >> 0)) << 16) + | ((((int32_t)((b[38] & 0xf )) >> 0)) << 24); + t[11] = (((int32_t)((b[38] ) >> 4)) << 0) + | (((int32_t)((b[39] ) >> 0)) << 4) + | (((int32_t)((b[40] ) >> 0)) << 12) + | (((int32_t)((b[41] ) >> 0)) << 20); + t[12] = (((int32_t)((b[42] ) >> 0)) << 0) + | (((int32_t)((b[43] ) >> 0)) << 8) + | (((int32_t)((b[44] ) >> 0)) << 16) + | ((((int32_t)((b[45] & 0xf )) >> 0)) << 24); + t[13] = (((int32_t)((b[45] ) >> 4)) << 0) + | (((int32_t)((b[46] ) >> 0)) << 4) + | (((int32_t)((b[47] ) >> 0)) << 12) + | (((int32_t)((b[48] ) >> 0)) << 20); + t[14] = (((int32_t)((b[49] ) >> 0)) << 0) + | (((int32_t)((b[50] ) >> 0)) << 8) + | (((int32_t)((b[51] ) >> 0)) << 16) + | ((((int32_t)((b[52] & 0xf )) >> 0)) << 24); + t[15] = (((int32_t)((b[52] ) >> 4)) << 0) + | (((int32_t)((b[53] ) >> 0)) << 4) + | (((int32_t)((b[54] ) >> 0)) << 12) + | (((int32_t)((b[55] ) >> 0)) << 20); + t[16] = (((int32_t)((b[56] ) >> 0)) << 0) + | (((int32_t)((b[57] ) >> 0)) << 8) + | (((int32_t)((b[58] ) >> 0)) << 16) + | ((((int32_t)((b[59] & 0xf )) >> 0)) << 24); + t[17] = (((int32_t)((b[59] ) >> 4)) << 0) + | (((int32_t)((b[60] ) >> 0)) << 4) + | (((int32_t)((b[61] ) >> 0)) << 12) + | (((int32_t)((b[62] ) >> 0)) << 20); + t[18] = (((int32_t)((b[63] ) >> 0)) << 0) + | (((int32_t)((b[64] ) >> 0)) << 8) + | (((int32_t)((b[65] ) >> 0)) << 16) + | ((((int32_t)((b[66] & 0xf )) >> 0)) << 24); + t[19] = (((int32_t)((b[66] ) >> 4)) << 0) + | (((int32_t)((b[67] ) >> 0)) << 4) + | (((int32_t)((b[68] ) >> 0)) << 12) + | (((int32_t)((b[69] ) >> 0)) << 20); + t[20] = (((int32_t)((b[70] ) >> 0)) << 0) + | (((int32_t)((b[71] ) >> 0)) << 8) + | (((int32_t)((b[72] ) >> 0)) << 16) + | ((((int32_t)((b[73] & 0xf )) >> 0)) << 24); + t[21] = (((int32_t)((b[73] ) >> 4)) << 0) + | (((int32_t)((b[74] ) >> 0)) << 4) + | (((int32_t)((b[75] ) >> 0)) << 12) + | (((int32_t)((b[76] ) >> 0)) << 20); + t[22] = (((int32_t)((b[77] ) >> 0)) << 0) + | (((int32_t)((b[78] ) >> 0)) << 8) + | (((int32_t)((b[79] ) >> 0)) << 16) + | ((((int32_t)((b[80] & 0xf )) >> 0)) << 24); + t[23] = (((int32_t)((b[80] ) >> 4)) << 0) + | (((int32_t)((b[81] ) >> 0)) << 4) + | (((int32_t)((b[82] ) >> 0)) << 12) + | (((int32_t)((b[83] ) >> 0)) << 20); + t[24] = (((int32_t)((b[84] ) >> 0)) << 0) + | (((int32_t)((b[85] ) >> 0)) << 8) + | (((int32_t)((b[86] ) >> 0)) << 16) + | ((((int32_t)((b[87] & 0xf )) >> 0)) << 24); + t[25] = (((int32_t)((b[87] ) >> 4)) << 0) + | (((int32_t)((b[88] ) >> 0)) << 4) + | (((int32_t)((b[89] ) >> 0)) << 12) + | (((int32_t)((b[90] ) >> 0)) << 20); + t[26] = (((int32_t)((b[91] ) >> 0)) << 0) + | (((int32_t)((b[92] ) >> 0)) << 8) + | (((int32_t)((b[93] ) >> 0)) << 16) + | ((((int32_t)((b[94] & 0xf )) >> 0)) << 24); + t[27] = (((int32_t)((b[94] ) >> 4)) << 0) + | (((int32_t)((b[95] ) >> 0)) << 4) + | (((int32_t)((b[96] ) >> 0)) << 12) + | (((int32_t)((b[97] ) >> 0)) << 20); + t[28] = (((int32_t)((b[98] ) >> 0)) << 0) + | (((int32_t)((b[99] ) >> 0)) << 8) + | (((int32_t)((b[100] ) >> 0)) << 16) + | ((((int32_t)((b[101] & 0xf )) >> 0)) << 24); + t[29] = (((int32_t)((b[101] ) >> 4)) << 0) + | (((int32_t)((b[102] ) >> 0)) << 4) + | (((int32_t)((b[103] ) >> 0)) << 12) + | (((int32_t)((b[104] ) >> 0)) << 20); + t[30] = (((int32_t)((b[105] ) >> 0)) << 0) + | (((int32_t)((b[106] ) >> 0)) << 8) + | (((int32_t)((b[107] ) >> 0)) << 16) + | ((((int32_t)((b[108] & 0xf )) >> 0)) << 24); + t[31] = (((int32_t)((b[108] ) >> 4)) << 0) + | (((int32_t)((b[109] ) >> 0)) << 4) + | (((int32_t)((b[110] ) >> 0)) << 12) + | (((int32_t)((b[111] ) >> 0)) << 20); + t[32] = (((int32_t)((b[112] ) >> 0)) << 0) + | (((int32_t)((b[113] ) >> 0)) << 8); + + /* Mod curve order */ + /* 2^446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d */ + /* Mod top half of extra words */ + t[ 8] += (int64_t)0x129eec34 * t[24]; + t[ 9] += (int64_t)0x21cf5b54 * t[24]; + t[10] += (int64_t)0x29c2ab70 * t[24]; + t[11] += (int64_t)0x0f635c8c * t[24]; + t[12] += (int64_t)0x25bf7a4c * t[24]; + t[13] += (int64_t)0x2d944a70 * t[24]; + t[14] += (int64_t)0x18eec490 * t[24]; + t[15] += (int64_t)0x20cd7704 * t[24]; + t[ 9] += (int64_t)0x129eec34 * t[25]; + t[10] += (int64_t)0x21cf5b54 * t[25]; + t[11] += (int64_t)0x29c2ab70 * t[25]; + t[12] += (int64_t)0x0f635c8c * t[25]; + t[13] += (int64_t)0x25bf7a4c * t[25]; + t[14] += (int64_t)0x2d944a70 * t[25]; + t[15] += (int64_t)0x18eec490 * t[25]; + t[16] += (int64_t)0x20cd7704 * t[25]; + t[10] += (int64_t)0x129eec34 * t[26]; + t[11] += (int64_t)0x21cf5b54 * t[26]; + t[12] += (int64_t)0x29c2ab70 * t[26]; + t[13] += (int64_t)0x0f635c8c * t[26]; + t[14] += (int64_t)0x25bf7a4c * t[26]; + t[15] += (int64_t)0x2d944a70 * t[26]; + t[16] += (int64_t)0x18eec490 * t[26]; + t[17] += (int64_t)0x20cd7704 * t[26]; + t[11] += (int64_t)0x129eec34 * t[27]; + t[12] += (int64_t)0x21cf5b54 * t[27]; + t[13] += (int64_t)0x29c2ab70 * t[27]; + t[14] += (int64_t)0x0f635c8c * t[27]; + t[15] += (int64_t)0x25bf7a4c * t[27]; + t[16] += (int64_t)0x2d944a70 * t[27]; + t[17] += (int64_t)0x18eec490 * t[27]; + t[18] += (int64_t)0x20cd7704 * t[27]; + t[12] += (int64_t)0x129eec34 * t[28]; + t[13] += (int64_t)0x21cf5b54 * t[28]; + t[14] += (int64_t)0x29c2ab70 * t[28]; + t[15] += (int64_t)0x0f635c8c * t[28]; + t[16] += (int64_t)0x25bf7a4c * t[28]; + t[17] += (int64_t)0x2d944a70 * t[28]; + t[18] += (int64_t)0x18eec490 * t[28]; + t[19] += (int64_t)0x20cd7704 * t[28]; + t[13] += (int64_t)0x129eec34 * t[29]; + t[14] += (int64_t)0x21cf5b54 * t[29]; + t[15] += (int64_t)0x29c2ab70 * t[29]; + t[16] += (int64_t)0x0f635c8c * t[29]; + t[17] += (int64_t)0x25bf7a4c * t[29]; + t[18] += (int64_t)0x2d944a70 * t[29]; + t[19] += (int64_t)0x18eec490 * t[29]; + t[20] += (int64_t)0x20cd7704 * t[29]; + t[14] += (int64_t)0x129eec34 * t[30]; + t[15] += (int64_t)0x21cf5b54 * t[30]; + t[16] += (int64_t)0x29c2ab70 * t[30]; + t[17] += (int64_t)0x0f635c8c * t[30]; + t[18] += (int64_t)0x25bf7a4c * t[30]; + t[19] += (int64_t)0x2d944a70 * t[30]; + t[20] += (int64_t)0x18eec490 * t[30]; + t[21] += (int64_t)0x20cd7704 * t[30]; + t[15] += (int64_t)0x129eec34 * t[31]; + t[16] += (int64_t)0x21cf5b54 * t[31]; + t[17] += (int64_t)0x29c2ab70 * t[31]; + t[18] += (int64_t)0x0f635c8c * t[31]; + t[19] += (int64_t)0x25bf7a4c * t[31]; + t[20] += (int64_t)0x2d944a70 * t[31]; + t[21] += (int64_t)0x18eec490 * t[31]; + t[22] += (int64_t)0x20cd7704 * t[31]; + t[16] += (int64_t)0x129eec34 * t[32]; + t[17] += (int64_t)0x21cf5b54 * t[32]; + t[18] += (int64_t)0x29c2ab70 * t[32]; + t[19] += (int64_t)0x0f635c8c * t[32]; + t[20] += (int64_t)0x25bf7a4c * t[32]; + t[21] += (int64_t)0x2d944a70 * t[32]; + t[22] += (int64_t)0x18eec490 * t[32]; + t[23] += (int64_t)0x20cd7704 * t[32]; + t[24] = 0; + /* Propagate carries */ + c = t[ 8] >> 28; t[ 9] += c; t[ 8] = t[ 8] & 0xfffffff; + c = t[ 9] >> 28; t[10] += c; t[ 9] = t[ 9] & 0xfffffff; + c = t[10] >> 28; t[11] += c; t[10] = t[10] & 0xfffffff; + c = t[11] >> 28; t[12] += c; t[11] = t[11] & 0xfffffff; + c = t[12] >> 28; t[13] += c; t[12] = t[12] & 0xfffffff; + c = t[13] >> 28; t[14] += c; t[13] = t[13] & 0xfffffff; + c = t[14] >> 28; t[15] += c; t[14] = t[14] & 0xfffffff; + c = t[15] >> 28; t[16] += c; t[15] = t[15] & 0xfffffff; + c = t[16] >> 28; t[17] += c; t[16] = t[16] & 0xfffffff; + c = t[17] >> 28; t[18] += c; t[17] = t[17] & 0xfffffff; + c = t[18] >> 28; t[19] += c; t[18] = t[18] & 0xfffffff; + c = t[19] >> 28; t[20] += c; t[19] = t[19] & 0xfffffff; + c = t[20] >> 28; t[21] += c; t[20] = t[20] & 0xfffffff; + c = t[21] >> 28; t[22] += c; t[21] = t[21] & 0xfffffff; + c = t[22] >> 28; t[23] += c; t[22] = t[22] & 0xfffffff; + c = t[23] >> 28; t[24] += c; t[23] = t[23] & 0xfffffff; + /* Mod bottom half of extra words */ + t[ 0] += (int64_t)0x129eec34 * t[16]; + t[ 1] += (int64_t)0x21cf5b54 * t[16]; + t[ 2] += (int64_t)0x29c2ab70 * t[16]; + t[ 3] += (int64_t)0x0f635c8c * t[16]; + t[ 4] += (int64_t)0x25bf7a4c * t[16]; + t[ 5] += (int64_t)0x2d944a70 * t[16]; + t[ 6] += (int64_t)0x18eec490 * t[16]; + t[ 7] += (int64_t)0x20cd7704 * t[16]; + t[ 1] += (int64_t)0x129eec34 * t[17]; + t[ 2] += (int64_t)0x21cf5b54 * t[17]; + t[ 3] += (int64_t)0x29c2ab70 * t[17]; + t[ 4] += (int64_t)0x0f635c8c * t[17]; + t[ 5] += (int64_t)0x25bf7a4c * t[17]; + t[ 6] += (int64_t)0x2d944a70 * t[17]; + t[ 7] += (int64_t)0x18eec490 * t[17]; + t[ 8] += (int64_t)0x20cd7704 * t[17]; + t[ 2] += (int64_t)0x129eec34 * t[18]; + t[ 3] += (int64_t)0x21cf5b54 * t[18]; + t[ 4] += (int64_t)0x29c2ab70 * t[18]; + t[ 5] += (int64_t)0x0f635c8c * t[18]; + t[ 6] += (int64_t)0x25bf7a4c * t[18]; + t[ 7] += (int64_t)0x2d944a70 * t[18]; + t[ 8] += (int64_t)0x18eec490 * t[18]; + t[ 9] += (int64_t)0x20cd7704 * t[18]; + t[ 3] += (int64_t)0x129eec34 * t[19]; + t[ 4] += (int64_t)0x21cf5b54 * t[19]; + t[ 5] += (int64_t)0x29c2ab70 * t[19]; + t[ 6] += (int64_t)0x0f635c8c * t[19]; + t[ 7] += (int64_t)0x25bf7a4c * t[19]; + t[ 8] += (int64_t)0x2d944a70 * t[19]; + t[ 9] += (int64_t)0x18eec490 * t[19]; + t[10] += (int64_t)0x20cd7704 * t[19]; + t[ 4] += (int64_t)0x129eec34 * t[20]; + t[ 5] += (int64_t)0x21cf5b54 * t[20]; + t[ 6] += (int64_t)0x29c2ab70 * t[20]; + t[ 7] += (int64_t)0x0f635c8c * t[20]; + t[ 8] += (int64_t)0x25bf7a4c * t[20]; + t[ 9] += (int64_t)0x2d944a70 * t[20]; + t[10] += (int64_t)0x18eec490 * t[20]; + t[11] += (int64_t)0x20cd7704 * t[20]; + t[ 5] += (int64_t)0x129eec34 * t[21]; + t[ 6] += (int64_t)0x21cf5b54 * t[21]; + t[ 7] += (int64_t)0x29c2ab70 * t[21]; + t[ 8] += (int64_t)0x0f635c8c * t[21]; + t[ 9] += (int64_t)0x25bf7a4c * t[21]; + t[10] += (int64_t)0x2d944a70 * t[21]; + t[11] += (int64_t)0x18eec490 * t[21]; + t[12] += (int64_t)0x20cd7704 * t[21]; + t[ 6] += (int64_t)0x129eec34 * t[22]; + t[ 7] += (int64_t)0x21cf5b54 * t[22]; + t[ 8] += (int64_t)0x29c2ab70 * t[22]; + t[ 9] += (int64_t)0x0f635c8c * t[22]; + t[10] += (int64_t)0x25bf7a4c * t[22]; + t[11] += (int64_t)0x2d944a70 * t[22]; + t[12] += (int64_t)0x18eec490 * t[22]; + t[13] += (int64_t)0x20cd7704 * t[22]; + t[ 7] += (int64_t)0x129eec34 * t[23]; + t[ 8] += (int64_t)0x21cf5b54 * t[23]; + t[ 9] += (int64_t)0x29c2ab70 * t[23]; + t[10] += (int64_t)0x0f635c8c * t[23]; + t[11] += (int64_t)0x25bf7a4c * t[23]; + t[12] += (int64_t)0x2d944a70 * t[23]; + t[13] += (int64_t)0x18eec490 * t[23]; + t[14] += (int64_t)0x20cd7704 * t[23]; + t[ 8] += (int64_t)0x129eec34 * t[24]; + t[ 9] += (int64_t)0x21cf5b54 * t[24]; + t[10] += (int64_t)0x29c2ab70 * t[24]; + t[11] += (int64_t)0x0f635c8c * t[24]; + t[12] += (int64_t)0x25bf7a4c * t[24]; + t[13] += (int64_t)0x2d944a70 * t[24]; + t[14] += (int64_t)0x18eec490 * t[24]; + t[15] += (int64_t)0x20cd7704 * t[24]; + t[16] = 0; + /* Propagate carries */ + c = t[ 0] >> 28; t[ 1] += c; t[ 0] = t[ 0] & 0xfffffff; + c = t[ 1] >> 28; t[ 2] += c; t[ 1] = t[ 1] & 0xfffffff; + c = t[ 2] >> 28; t[ 3] += c; t[ 2] = t[ 2] & 0xfffffff; + c = t[ 3] >> 28; t[ 4] += c; t[ 3] = t[ 3] & 0xfffffff; + c = t[ 4] >> 28; t[ 5] += c; t[ 4] = t[ 4] & 0xfffffff; + c = t[ 5] >> 28; t[ 6] += c; t[ 5] = t[ 5] & 0xfffffff; + c = t[ 6] >> 28; t[ 7] += c; t[ 6] = t[ 6] & 0xfffffff; + c = t[ 7] >> 28; t[ 8] += c; t[ 7] = t[ 7] & 0xfffffff; + c = t[ 8] >> 28; t[ 9] += c; t[ 8] = t[ 8] & 0xfffffff; + c = t[ 9] >> 28; t[10] += c; t[ 9] = t[ 9] & 0xfffffff; + c = t[10] >> 28; t[11] += c; t[10] = t[10] & 0xfffffff; + c = t[11] >> 28; t[12] += c; t[11] = t[11] & 0xfffffff; + c = t[12] >> 28; t[13] += c; t[12] = t[12] & 0xfffffff; + c = t[13] >> 28; t[14] += c; t[13] = t[13] & 0xfffffff; + c = t[14] >> 28; t[15] += c; t[14] = t[14] & 0xfffffff; + c = t[15] >> 28; t[16] += c; t[15] = t[15] & 0xfffffff; + t[ 0] += (int64_t)0x129eec34 * t[16]; + t[ 1] += (int64_t)0x21cf5b54 * t[16]; + t[ 2] += (int64_t)0x29c2ab70 * t[16]; + t[ 3] += (int64_t)0x0f635c8c * t[16]; + t[ 4] += (int64_t)0x25bf7a4c * t[16]; + t[ 5] += (int64_t)0x2d944a70 * t[16]; + t[ 6] += (int64_t)0x18eec490 * t[16]; + t[ 7] += (int64_t)0x20cd7704 * t[16]; + /* Propagate carries */ + c = t[ 0] >> 28; t[ 1] += c; d[ 0] = (int32_t)(t[ 0] & 0xfffffff); + c = t[ 1] >> 28; t[ 2] += c; d[ 1] = (int32_t)(t[ 1] & 0xfffffff); + c = t[ 2] >> 28; t[ 3] += c; d[ 2] = (int32_t)(t[ 2] & 0xfffffff); + c = t[ 3] >> 28; t[ 4] += c; d[ 3] = (int32_t)(t[ 3] & 0xfffffff); + c = t[ 4] >> 28; t[ 5] += c; d[ 4] = (int32_t)(t[ 4] & 0xfffffff); + c = t[ 5] >> 28; t[ 6] += c; d[ 5] = (int32_t)(t[ 5] & 0xfffffff); + c = t[ 6] >> 28; t[ 7] += c; d[ 6] = (int32_t)(t[ 6] & 0xfffffff); + c = t[ 7] >> 28; t[ 8] += c; d[ 7] = (int32_t)(t[ 7] & 0xfffffff); + c = t[ 8] >> 28; t[ 9] += c; d[ 8] = (int32_t)(t[ 8] & 0xfffffff); + c = t[ 9] >> 28; t[10] += c; d[ 9] = (int32_t)(t[ 9] & 0xfffffff); + c = t[10] >> 28; t[11] += c; d[10] = (int32_t)(t[10] & 0xfffffff); + c = t[11] >> 28; t[12] += c; d[11] = (int32_t)(t[11] & 0xfffffff); + c = t[12] >> 28; t[13] += c; d[12] = (int32_t)(t[12] & 0xfffffff); + c = t[13] >> 28; t[14] += c; d[13] = (int32_t)(t[13] & 0xfffffff); + c = t[14] >> 28; t[15] += c; d[14] = (int32_t)(t[14] & 0xfffffff); + d[15] = t[15]; + /* Mod bits over 28 in last word */ + o = d[15] >> 26; d[15] &= 0x3ffffff; + d[ 0] += 0x4a7bb0d * o; + d[ 1] += 0x873d6d5 * o; + d[ 2] += 0xa70aadc * o; + d[ 3] += 0x3d8d723 * o; + d[ 4] += 0x96fde93 * o; + d[ 5] += 0xb65129c * o; + d[ 6] += 0x63bb124 * o; + d[ 7] += 0x8335dc1 * o; + /* Propagate carries */ + o = d[ 0] >> 28; d[ 1] += o; d[ 0] = d[ 0] & 0xfffffff; + o = d[ 1] >> 28; d[ 2] += o; d[ 1] = d[ 1] & 0xfffffff; + o = d[ 2] >> 28; d[ 3] += o; d[ 2] = d[ 2] & 0xfffffff; + o = d[ 3] >> 28; d[ 4] += o; d[ 3] = d[ 3] & 0xfffffff; + o = d[ 4] >> 28; d[ 5] += o; d[ 4] = d[ 4] & 0xfffffff; + o = d[ 5] >> 28; d[ 6] += o; d[ 5] = d[ 5] & 0xfffffff; + o = d[ 6] >> 28; d[ 7] += o; d[ 6] = d[ 6] & 0xfffffff; + o = d[ 7] >> 28; d[ 8] += o; d[ 7] = d[ 7] & 0xfffffff; + o = d[ 8] >> 28; d[ 9] += o; d[ 8] = d[ 8] & 0xfffffff; + o = d[ 9] >> 28; d[10] += o; d[ 9] = d[ 9] & 0xfffffff; + o = d[10] >> 28; d[11] += o; d[10] = d[10] & 0xfffffff; + o = d[11] >> 28; d[12] += o; d[11] = d[11] & 0xfffffff; + o = d[12] >> 28; d[13] += o; d[12] = d[12] & 0xfffffff; + o = d[13] >> 28; d[14] += o; d[13] = d[13] & 0xfffffff; + o = d[14] >> 28; d[15] += o; d[14] = d[14] & 0xfffffff; + + /* Convert to bytes */ + b[ 0] = (d[0 ] >> 0); + b[ 1] = (d[0 ] >> 8); + b[ 2] = (d[0 ] >> 16); + b[ 3] = (d[0 ] >> 24) + ((d[1 ] >> 0) << 4); + b[ 4] = (d[1 ] >> 4); + b[ 5] = (d[1 ] >> 12); + b[ 6] = (d[1 ] >> 20); + b[ 7] = (d[2 ] >> 0); + b[ 8] = (d[2 ] >> 8); + b[ 9] = (d[2 ] >> 16); + b[10] = (d[2 ] >> 24) + ((d[3 ] >> 0) << 4); + b[11] = (d[3 ] >> 4); + b[12] = (d[3 ] >> 12); + b[13] = (d[3 ] >> 20); + b[14] = (d[4 ] >> 0); + b[15] = (d[4 ] >> 8); + b[16] = (d[4 ] >> 16); + b[17] = (d[4 ] >> 24) + ((d[5 ] >> 0) << 4); + b[18] = (d[5 ] >> 4); + b[19] = (d[5 ] >> 12); + b[20] = (d[5 ] >> 20); + b[21] = (d[6 ] >> 0); + b[22] = (d[6 ] >> 8); + b[23] = (d[6 ] >> 16); + b[24] = (d[6 ] >> 24) + ((d[7 ] >> 0) << 4); + b[25] = (d[7 ] >> 4); + b[26] = (d[7 ] >> 12); + b[27] = (d[7 ] >> 20); + b[28] = (d[8 ] >> 0); + b[29] = (d[8 ] >> 8); + b[30] = (d[8 ] >> 16); + b[31] = (d[8 ] >> 24) + ((d[9 ] >> 0) << 4); + b[32] = (d[9 ] >> 4); + b[33] = (d[9 ] >> 12); + b[34] = (d[9 ] >> 20); + b[35] = (d[10] >> 0); + b[36] = (d[10] >> 8); + b[37] = (d[10] >> 16); + b[38] = (d[10] >> 24) + ((d[11] >> 0) << 4); + b[39] = (d[11] >> 4); + b[40] = (d[11] >> 12); + b[41] = (d[11] >> 20); + b[42] = (d[12] >> 0); + b[43] = (d[12] >> 8); + b[44] = (d[12] >> 16); + b[45] = (d[12] >> 24) + ((d[13] >> 0) << 4); + b[46] = (d[13] >> 4); + b[47] = (d[13] >> 12); + b[48] = (d[13] >> 20); + b[49] = (d[14] >> 0); + b[50] = (d[14] >> 8); + b[51] = (d[14] >> 16); + b[52] = (d[14] >> 24) + ((d[15] >> 0) << 4); + b[53] = (d[15] >> 4); + b[54] = (d[15] >> 12); + b[55] = (d[15] >> 20); + b[56] = 0; +} + +/* Multiply a by b and add d. r = (a * b + d) mod order + * + * r [in] Scalar to hold result. + * a [in] Scalar to multiply. + * b [in] Scalar to multiply. + * d [in] Scalar to add to multiplicative result. + */ +void sc448_muladd(uint8_t* r, const uint8_t* a, const uint8_t* b, + const uint8_t* d) +{ + uint32_t ad[16], bd[16], dd[16], rd[16]; + uint64_t t[32]; + uint64_t c; + uint32_t o; + + /* Load from bytes */ + ad[ 0] = (((int32_t)((a[ 0] ) >> 0)) << 0) + | (((int32_t)((a[ 1] ) >> 0)) << 8) + | (((int32_t)((a[ 2] ) >> 0)) << 16) + | ((((int32_t)((a[ 3] & 0xf )) >> 0)) << 24); + ad[ 1] = (((int32_t)((a[ 3] ) >> 4)) << 0) + | (((int32_t)((a[ 4] ) >> 0)) << 4) + | (((int32_t)((a[ 5] ) >> 0)) << 12) + | (((int32_t)((a[ 6] ) >> 0)) << 20); + ad[ 2] = (((int32_t)((a[ 7] ) >> 0)) << 0) + | (((int32_t)((a[ 8] ) >> 0)) << 8) + | (((int32_t)((a[ 9] ) >> 0)) << 16) + | ((((int32_t)((a[10] & 0xf )) >> 0)) << 24); + ad[ 3] = (((int32_t)((a[10] ) >> 4)) << 0) + | (((int32_t)((a[11] ) >> 0)) << 4) + | (((int32_t)((a[12] ) >> 0)) << 12) + | (((int32_t)((a[13] ) >> 0)) << 20); + ad[ 4] = (((int32_t)((a[14] ) >> 0)) << 0) + | (((int32_t)((a[15] ) >> 0)) << 8) + | (((int32_t)((a[16] ) >> 0)) << 16) + | ((((int32_t)((a[17] & 0xf )) >> 0)) << 24); + ad[ 5] = (((int32_t)((a[17] ) >> 4)) << 0) + | (((int32_t)((a[18] ) >> 0)) << 4) + | (((int32_t)((a[19] ) >> 0)) << 12) + | (((int32_t)((a[20] ) >> 0)) << 20); + ad[ 6] = (((int32_t)((a[21] ) >> 0)) << 0) + | (((int32_t)((a[22] ) >> 0)) << 8) + | (((int32_t)((a[23] ) >> 0)) << 16) + | ((((int32_t)((a[24] & 0xf )) >> 0)) << 24); + ad[ 7] = (((int32_t)((a[24] ) >> 4)) << 0) + | (((int32_t)((a[25] ) >> 0)) << 4) + | (((int32_t)((a[26] ) >> 0)) << 12) + | (((int32_t)((a[27] ) >> 0)) << 20); + ad[ 8] = (((int32_t)((a[28] ) >> 0)) << 0) + | (((int32_t)((a[29] ) >> 0)) << 8) + | (((int32_t)((a[30] ) >> 0)) << 16) + | ((((int32_t)((a[31] & 0xf )) >> 0)) << 24); + ad[ 9] = (((int32_t)((a[31] ) >> 4)) << 0) + | (((int32_t)((a[32] ) >> 0)) << 4) + | (((int32_t)((a[33] ) >> 0)) << 12) + | (((int32_t)((a[34] ) >> 0)) << 20); + ad[10] = (((int32_t)((a[35] ) >> 0)) << 0) + | (((int32_t)((a[36] ) >> 0)) << 8) + | (((int32_t)((a[37] ) >> 0)) << 16) + | ((((int32_t)((a[38] & 0xf )) >> 0)) << 24); + ad[11] = (((int32_t)((a[38] ) >> 4)) << 0) + | (((int32_t)((a[39] ) >> 0)) << 4) + | (((int32_t)((a[40] ) >> 0)) << 12) + | (((int32_t)((a[41] ) >> 0)) << 20); + ad[12] = (((int32_t)((a[42] ) >> 0)) << 0) + | (((int32_t)((a[43] ) >> 0)) << 8) + | (((int32_t)((a[44] ) >> 0)) << 16) + | ((((int32_t)((a[45] & 0xf )) >> 0)) << 24); + ad[13] = (((int32_t)((a[45] ) >> 4)) << 0) + | (((int32_t)((a[46] ) >> 0)) << 4) + | (((int32_t)((a[47] ) >> 0)) << 12) + | (((int32_t)((a[48] ) >> 0)) << 20); + ad[14] = (((int32_t)((a[49] ) >> 0)) << 0) + | (((int32_t)((a[50] ) >> 0)) << 8) + | (((int32_t)((a[51] ) >> 0)) << 16) + | ((((int32_t)((a[52] & 0xf )) >> 0)) << 24); + ad[15] = (((int32_t)((a[52] ) >> 4)) << 0) + | (((int32_t)((a[53] ) >> 0)) << 4) + | (((int32_t)((a[54] ) >> 0)) << 12) + | (((int32_t)((a[55] ) >> 0)) << 20); + /* Load from bytes */ + bd[ 0] = (((int32_t)((b[ 0] ) >> 0)) << 0) + | (((int32_t)((b[ 1] ) >> 0)) << 8) + | (((int32_t)((b[ 2] ) >> 0)) << 16) + | ((((int32_t)((b[ 3] & 0xf )) >> 0)) << 24); + bd[ 1] = (((int32_t)((b[ 3] ) >> 4)) << 0) + | (((int32_t)((b[ 4] ) >> 0)) << 4) + | (((int32_t)((b[ 5] ) >> 0)) << 12) + | (((int32_t)((b[ 6] ) >> 0)) << 20); + bd[ 2] = (((int32_t)((b[ 7] ) >> 0)) << 0) + | (((int32_t)((b[ 8] ) >> 0)) << 8) + | (((int32_t)((b[ 9] ) >> 0)) << 16) + | ((((int32_t)((b[10] & 0xf )) >> 0)) << 24); + bd[ 3] = (((int32_t)((b[10] ) >> 4)) << 0) + | (((int32_t)((b[11] ) >> 0)) << 4) + | (((int32_t)((b[12] ) >> 0)) << 12) + | (((int32_t)((b[13] ) >> 0)) << 20); + bd[ 4] = (((int32_t)((b[14] ) >> 0)) << 0) + | (((int32_t)((b[15] ) >> 0)) << 8) + | (((int32_t)((b[16] ) >> 0)) << 16) + | ((((int32_t)((b[17] & 0xf )) >> 0)) << 24); + bd[ 5] = (((int32_t)((b[17] ) >> 4)) << 0) + | (((int32_t)((b[18] ) >> 0)) << 4) + | (((int32_t)((b[19] ) >> 0)) << 12) + | (((int32_t)((b[20] ) >> 0)) << 20); + bd[ 6] = (((int32_t)((b[21] ) >> 0)) << 0) + | (((int32_t)((b[22] ) >> 0)) << 8) + | (((int32_t)((b[23] ) >> 0)) << 16) + | ((((int32_t)((b[24] & 0xf )) >> 0)) << 24); + bd[ 7] = (((int32_t)((b[24] ) >> 4)) << 0) + | (((int32_t)((b[25] ) >> 0)) << 4) + | (((int32_t)((b[26] ) >> 0)) << 12) + | (((int32_t)((b[27] ) >> 0)) << 20); + bd[ 8] = (((int32_t)((b[28] ) >> 0)) << 0) + | (((int32_t)((b[29] ) >> 0)) << 8) + | (((int32_t)((b[30] ) >> 0)) << 16) + | ((((int32_t)((b[31] & 0xf )) >> 0)) << 24); + bd[ 9] = (((int32_t)((b[31] ) >> 4)) << 0) + | (((int32_t)((b[32] ) >> 0)) << 4) + | (((int32_t)((b[33] ) >> 0)) << 12) + | (((int32_t)((b[34] ) >> 0)) << 20); + bd[10] = (((int32_t)((b[35] ) >> 0)) << 0) + | (((int32_t)((b[36] ) >> 0)) << 8) + | (((int32_t)((b[37] ) >> 0)) << 16) + | ((((int32_t)((b[38] & 0xf )) >> 0)) << 24); + bd[11] = (((int32_t)((b[38] ) >> 4)) << 0) + | (((int32_t)((b[39] ) >> 0)) << 4) + | (((int32_t)((b[40] ) >> 0)) << 12) + | (((int32_t)((b[41] ) >> 0)) << 20); + bd[12] = (((int32_t)((b[42] ) >> 0)) << 0) + | (((int32_t)((b[43] ) >> 0)) << 8) + | (((int32_t)((b[44] ) >> 0)) << 16) + | ((((int32_t)((b[45] & 0xf )) >> 0)) << 24); + bd[13] = (((int32_t)((b[45] ) >> 4)) << 0) + | (((int32_t)((b[46] ) >> 0)) << 4) + | (((int32_t)((b[47] ) >> 0)) << 12) + | (((int32_t)((b[48] ) >> 0)) << 20); + bd[14] = (((int32_t)((b[49] ) >> 0)) << 0) + | (((int32_t)((b[50] ) >> 0)) << 8) + | (((int32_t)((b[51] ) >> 0)) << 16) + | ((((int32_t)((b[52] & 0xf )) >> 0)) << 24); + bd[15] = (((int32_t)((b[52] ) >> 4)) << 0) + | (((int32_t)((b[53] ) >> 0)) << 4) + | (((int32_t)((b[54] ) >> 0)) << 12) + | (((int32_t)((b[55] ) >> 0)) << 20); + /* Load from bytes */ + dd[ 0] = (((int32_t)((d[ 0] ) >> 0)) << 0) + | (((int32_t)((d[ 1] ) >> 0)) << 8) + | (((int32_t)((d[ 2] ) >> 0)) << 16) + | ((((int32_t)((d[ 3] & 0xf )) >> 0)) << 24); + dd[ 1] = (((int32_t)((d[ 3] ) >> 4)) << 0) + | (((int32_t)((d[ 4] ) >> 0)) << 4) + | (((int32_t)((d[ 5] ) >> 0)) << 12) + | (((int32_t)((d[ 6] ) >> 0)) << 20); + dd[ 2] = (((int32_t)((d[ 7] ) >> 0)) << 0) + | (((int32_t)((d[ 8] ) >> 0)) << 8) + | (((int32_t)((d[ 9] ) >> 0)) << 16) + | ((((int32_t)((d[10] & 0xf )) >> 0)) << 24); + dd[ 3] = (((int32_t)((d[10] ) >> 4)) << 0) + | (((int32_t)((d[11] ) >> 0)) << 4) + | (((int32_t)((d[12] ) >> 0)) << 12) + | (((int32_t)((d[13] ) >> 0)) << 20); + dd[ 4] = (((int32_t)((d[14] ) >> 0)) << 0) + | (((int32_t)((d[15] ) >> 0)) << 8) + | (((int32_t)((d[16] ) >> 0)) << 16) + | ((((int32_t)((d[17] & 0xf )) >> 0)) << 24); + dd[ 5] = (((int32_t)((d[17] ) >> 4)) << 0) + | (((int32_t)((d[18] ) >> 0)) << 4) + | (((int32_t)((d[19] ) >> 0)) << 12) + | (((int32_t)((d[20] ) >> 0)) << 20); + dd[ 6] = (((int32_t)((d[21] ) >> 0)) << 0) + | (((int32_t)((d[22] ) >> 0)) << 8) + | (((int32_t)((d[23] ) >> 0)) << 16) + | ((((int32_t)((d[24] & 0xf )) >> 0)) << 24); + dd[ 7] = (((int32_t)((d[24] ) >> 4)) << 0) + | (((int32_t)((d[25] ) >> 0)) << 4) + | (((int32_t)((d[26] ) >> 0)) << 12) + | (((int32_t)((d[27] ) >> 0)) << 20); + dd[ 8] = (((int32_t)((d[28] ) >> 0)) << 0) + | (((int32_t)((d[29] ) >> 0)) << 8) + | (((int32_t)((d[30] ) >> 0)) << 16) + | ((((int32_t)((d[31] & 0xf )) >> 0)) << 24); + dd[ 9] = (((int32_t)((d[31] ) >> 4)) << 0) + | (((int32_t)((d[32] ) >> 0)) << 4) + | (((int32_t)((d[33] ) >> 0)) << 12) + | (((int32_t)((d[34] ) >> 0)) << 20); + dd[10] = (((int32_t)((d[35] ) >> 0)) << 0) + | (((int32_t)((d[36] ) >> 0)) << 8) + | (((int32_t)((d[37] ) >> 0)) << 16) + | ((((int32_t)((d[38] & 0xf )) >> 0)) << 24); + dd[11] = (((int32_t)((d[38] ) >> 4)) << 0) + | (((int32_t)((d[39] ) >> 0)) << 4) + | (((int32_t)((d[40] ) >> 0)) << 12) + | (((int32_t)((d[41] ) >> 0)) << 20); + dd[12] = (((int32_t)((d[42] ) >> 0)) << 0) + | (((int32_t)((d[43] ) >> 0)) << 8) + | (((int32_t)((d[44] ) >> 0)) << 16) + | ((((int32_t)((d[45] & 0xf )) >> 0)) << 24); + dd[13] = (((int32_t)((d[45] ) >> 4)) << 0) + | (((int32_t)((d[46] ) >> 0)) << 4) + | (((int32_t)((d[47] ) >> 0)) << 12) + | (((int32_t)((d[48] ) >> 0)) << 20); + dd[14] = (((int32_t)((d[49] ) >> 0)) << 0) + | (((int32_t)((d[50] ) >> 0)) << 8) + | (((int32_t)((d[51] ) >> 0)) << 16) + | ((((int32_t)((d[52] & 0xf )) >> 0)) << 24); + dd[15] = (((int32_t)((d[52] ) >> 4)) << 0) + | (((int32_t)((d[53] ) >> 0)) << 4) + | (((int32_t)((d[54] ) >> 0)) << 12) + | (((int32_t)((d[55] ) >> 0)) << 20); + + /* a * b + d */ + t[ 0] = dd[ 0] + (int64_t)ad[ 0] * bd[ 0]; + t[ 1] = dd[ 1] + (int64_t)ad[ 0] * bd[ 1] + + (int64_t)ad[ 1] * bd[ 0]; + t[ 2] = dd[ 2] + (int64_t)ad[ 0] * bd[ 2] + + (int64_t)ad[ 1] * bd[ 1] + + (int64_t)ad[ 2] * bd[ 0]; + t[ 3] = dd[ 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] = dd[ 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] = dd[ 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] = dd[ 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] = dd[ 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] = dd[ 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] = dd[ 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] = dd[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] = dd[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] = dd[12] + (int64_t)ad[ 0] * bd[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] + + (int64_t)ad[12] * bd[ 0]; + t[13] = dd[13] + (int64_t)ad[ 0] * bd[13] + + (int64_t)ad[ 1] * bd[12] + + (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] + + (int64_t)ad[12] * bd[ 1] + + (int64_t)ad[13] * bd[ 0]; + t[14] = dd[14] + (int64_t)ad[ 0] * bd[14] + + (int64_t)ad[ 1] * bd[13] + + (int64_t)ad[ 2] * bd[12] + + (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] + + (int64_t)ad[12] * bd[ 2] + + (int64_t)ad[13] * bd[ 1] + + (int64_t)ad[14] * bd[ 0]; + t[15] = dd[15] + (int64_t)ad[ 0] * bd[15] + + (int64_t)ad[ 1] * bd[14] + + (int64_t)ad[ 2] * bd[13] + + (int64_t)ad[ 3] * bd[12] + + (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] + + (int64_t)ad[12] * bd[ 3] + + (int64_t)ad[13] * bd[ 2] + + (int64_t)ad[14] * bd[ 1] + + (int64_t)ad[15] * bd[ 0]; + t[16] = (int64_t)ad[ 1] * bd[15] + + (int64_t)ad[ 2] * bd[14] + + (int64_t)ad[ 3] * bd[13] + + (int64_t)ad[ 4] * bd[12] + + (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] + + (int64_t)ad[12] * bd[ 4] + + (int64_t)ad[13] * bd[ 3] + + (int64_t)ad[14] * bd[ 2] + + (int64_t)ad[15] * bd[ 1]; + t[17] = (int64_t)ad[ 2] * bd[15] + + (int64_t)ad[ 3] * bd[14] + + (int64_t)ad[ 4] * bd[13] + + (int64_t)ad[ 5] * bd[12] + + (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] + + (int64_t)ad[12] * bd[ 5] + + (int64_t)ad[13] * bd[ 4] + + (int64_t)ad[14] * bd[ 3] + + (int64_t)ad[15] * bd[ 2]; + t[18] = (int64_t)ad[ 3] * bd[15] + + (int64_t)ad[ 4] * bd[14] + + (int64_t)ad[ 5] * bd[13] + + (int64_t)ad[ 6] * bd[12] + + (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] + + (int64_t)ad[12] * bd[ 6] + + (int64_t)ad[13] * bd[ 5] + + (int64_t)ad[14] * bd[ 4] + + (int64_t)ad[15] * bd[ 3]; + t[19] = (int64_t)ad[ 4] * bd[15] + + (int64_t)ad[ 5] * bd[14] + + (int64_t)ad[ 6] * bd[13] + + (int64_t)ad[ 7] * bd[12] + + (int64_t)ad[ 8] * bd[11] + + (int64_t)ad[ 9] * bd[10] + + (int64_t)ad[10] * bd[ 9] + + (int64_t)ad[11] * bd[ 8] + + (int64_t)ad[12] * bd[ 7] + + (int64_t)ad[13] * bd[ 6] + + (int64_t)ad[14] * bd[ 5] + + (int64_t)ad[15] * bd[ 4]; + t[20] = (int64_t)ad[ 5] * bd[15] + + (int64_t)ad[ 6] * bd[14] + + (int64_t)ad[ 7] * bd[13] + + (int64_t)ad[ 8] * bd[12] + + (int64_t)ad[ 9] * bd[11] + + (int64_t)ad[10] * bd[10] + + (int64_t)ad[11] * bd[ 9] + + (int64_t)ad[12] * bd[ 8] + + (int64_t)ad[13] * bd[ 7] + + (int64_t)ad[14] * bd[ 6] + + (int64_t)ad[15] * bd[ 5]; + t[21] = (int64_t)ad[ 6] * bd[15] + + (int64_t)ad[ 7] * bd[14] + + (int64_t)ad[ 8] * bd[13] + + (int64_t)ad[ 9] * bd[12] + + (int64_t)ad[10] * bd[11] + + (int64_t)ad[11] * bd[10] + + (int64_t)ad[12] * bd[ 9] + + (int64_t)ad[13] * bd[ 8] + + (int64_t)ad[14] * bd[ 7] + + (int64_t)ad[15] * bd[ 6]; + t[22] = (int64_t)ad[ 7] * bd[15] + + (int64_t)ad[ 8] * bd[14] + + (int64_t)ad[ 9] * bd[13] + + (int64_t)ad[10] * bd[12] + + (int64_t)ad[11] * bd[11] + + (int64_t)ad[12] * bd[10] + + (int64_t)ad[13] * bd[ 9] + + (int64_t)ad[14] * bd[ 8] + + (int64_t)ad[15] * bd[ 7]; + t[23] = (int64_t)ad[ 8] * bd[15] + + (int64_t)ad[ 9] * bd[14] + + (int64_t)ad[10] * bd[13] + + (int64_t)ad[11] * bd[12] + + (int64_t)ad[12] * bd[11] + + (int64_t)ad[13] * bd[10] + + (int64_t)ad[14] * bd[ 9] + + (int64_t)ad[15] * bd[ 8]; + t[24] = (int64_t)ad[ 9] * bd[15] + + (int64_t)ad[10] * bd[14] + + (int64_t)ad[11] * bd[13] + + (int64_t)ad[12] * bd[12] + + (int64_t)ad[13] * bd[11] + + (int64_t)ad[14] * bd[10] + + (int64_t)ad[15] * bd[ 9]; + t[25] = (int64_t)ad[10] * bd[15] + + (int64_t)ad[11] * bd[14] + + (int64_t)ad[12] * bd[13] + + (int64_t)ad[13] * bd[12] + + (int64_t)ad[14] * bd[11] + + (int64_t)ad[15] * bd[10]; + t[26] = (int64_t)ad[11] * bd[15] + + (int64_t)ad[12] * bd[14] + + (int64_t)ad[13] * bd[13] + + (int64_t)ad[14] * bd[12] + + (int64_t)ad[15] * bd[11]; + t[27] = (int64_t)ad[12] * bd[15] + + (int64_t)ad[13] * bd[14] + + (int64_t)ad[14] * bd[13] + + (int64_t)ad[15] * bd[12]; + t[28] = (int64_t)ad[13] * bd[15] + + (int64_t)ad[14] * bd[14] + + (int64_t)ad[15] * bd[13]; + t[29] = (int64_t)ad[14] * bd[15] + + (int64_t)ad[15] * bd[14]; + t[30] = (int64_t)ad[15] * bd[15]; + t[31] = 0; + + /* Mod curve order */ + /* 2^446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d */ + /* Propagate carries */ + c = t[ 0] >> 28; t[ 1] += c; t[ 0] = t[ 0] & 0xfffffff; + c = t[ 1] >> 28; t[ 2] += c; t[ 1] = t[ 1] & 0xfffffff; + c = t[ 2] >> 28; t[ 3] += c; t[ 2] = t[ 2] & 0xfffffff; + c = t[ 3] >> 28; t[ 4] += c; t[ 3] = t[ 3] & 0xfffffff; + c = t[ 4] >> 28; t[ 5] += c; t[ 4] = t[ 4] & 0xfffffff; + c = t[ 5] >> 28; t[ 6] += c; t[ 5] = t[ 5] & 0xfffffff; + c = t[ 6] >> 28; t[ 7] += c; t[ 6] = t[ 6] & 0xfffffff; + c = t[ 7] >> 28; t[ 8] += c; t[ 7] = t[ 7] & 0xfffffff; + c = t[ 8] >> 28; t[ 9] += c; t[ 8] = t[ 8] & 0xfffffff; + c = t[ 9] >> 28; t[10] += c; t[ 9] = t[ 9] & 0xfffffff; + c = t[10] >> 28; t[11] += c; t[10] = t[10] & 0xfffffff; + c = t[11] >> 28; t[12] += c; t[11] = t[11] & 0xfffffff; + c = t[12] >> 28; t[13] += c; t[12] = t[12] & 0xfffffff; + c = t[13] >> 28; t[14] += c; t[13] = t[13] & 0xfffffff; + c = t[14] >> 28; t[15] += c; t[14] = t[14] & 0xfffffff; + c = t[15] >> 28; t[16] += c; t[15] = t[15] & 0xfffffff; + c = t[16] >> 28; t[17] += c; t[16] = t[16] & 0xfffffff; + c = t[17] >> 28; t[18] += c; t[17] = t[17] & 0xfffffff; + c = t[18] >> 28; t[19] += c; t[18] = t[18] & 0xfffffff; + c = t[19] >> 28; t[20] += c; t[19] = t[19] & 0xfffffff; + c = t[20] >> 28; t[21] += c; t[20] = t[20] & 0xfffffff; + c = t[21] >> 28; t[22] += c; t[21] = t[21] & 0xfffffff; + c = t[22] >> 28; t[23] += c; t[22] = t[22] & 0xfffffff; + c = t[23] >> 28; t[24] += c; t[23] = t[23] & 0xfffffff; + c = t[24] >> 28; t[25] += c; t[24] = t[24] & 0xfffffff; + c = t[25] >> 28; t[26] += c; t[25] = t[25] & 0xfffffff; + c = t[26] >> 28; t[27] += c; t[26] = t[26] & 0xfffffff; + c = t[27] >> 28; t[28] += c; t[27] = t[27] & 0xfffffff; + c = t[28] >> 28; t[29] += c; t[28] = t[28] & 0xfffffff; + c = t[29] >> 28; t[30] += c; t[29] = t[29] & 0xfffffff; + c = t[30] >> 28; t[31] += c; t[30] = t[30] & 0xfffffff; + /* Mod top half of extra words */ + t[ 8] += (int64_t)0x129eec34 * t[24]; + t[ 9] += (int64_t)0x21cf5b54 * t[24]; + t[10] += (int64_t)0x29c2ab70 * t[24]; + t[11] += (int64_t)0x0f635c8c * t[24]; + t[12] += (int64_t)0x25bf7a4c * t[24]; + t[13] += (int64_t)0x2d944a70 * t[24]; + t[14] += (int64_t)0x18eec490 * t[24]; + t[15] += (int64_t)0x20cd7704 * t[24]; + t[ 9] += (int64_t)0x129eec34 * t[25]; + t[10] += (int64_t)0x21cf5b54 * t[25]; + t[11] += (int64_t)0x29c2ab70 * t[25]; + t[12] += (int64_t)0x0f635c8c * t[25]; + t[13] += (int64_t)0x25bf7a4c * t[25]; + t[14] += (int64_t)0x2d944a70 * t[25]; + t[15] += (int64_t)0x18eec490 * t[25]; + t[16] += (int64_t)0x20cd7704 * t[25]; + t[10] += (int64_t)0x129eec34 * t[26]; + t[11] += (int64_t)0x21cf5b54 * t[26]; + t[12] += (int64_t)0x29c2ab70 * t[26]; + t[13] += (int64_t)0x0f635c8c * t[26]; + t[14] += (int64_t)0x25bf7a4c * t[26]; + t[15] += (int64_t)0x2d944a70 * t[26]; + t[16] += (int64_t)0x18eec490 * t[26]; + t[17] += (int64_t)0x20cd7704 * t[26]; + t[11] += (int64_t)0x129eec34 * t[27]; + t[12] += (int64_t)0x21cf5b54 * t[27]; + t[13] += (int64_t)0x29c2ab70 * t[27]; + t[14] += (int64_t)0x0f635c8c * t[27]; + t[15] += (int64_t)0x25bf7a4c * t[27]; + t[16] += (int64_t)0x2d944a70 * t[27]; + t[17] += (int64_t)0x18eec490 * t[27]; + t[18] += (int64_t)0x20cd7704 * t[27]; + t[12] += (int64_t)0x129eec34 * t[28]; + t[13] += (int64_t)0x21cf5b54 * t[28]; + t[14] += (int64_t)0x29c2ab70 * t[28]; + t[15] += (int64_t)0x0f635c8c * t[28]; + t[16] += (int64_t)0x25bf7a4c * t[28]; + t[17] += (int64_t)0x2d944a70 * t[28]; + t[18] += (int64_t)0x18eec490 * t[28]; + t[19] += (int64_t)0x20cd7704 * t[28]; + t[13] += (int64_t)0x129eec34 * t[29]; + t[14] += (int64_t)0x21cf5b54 * t[29]; + t[15] += (int64_t)0x29c2ab70 * t[29]; + t[16] += (int64_t)0x0f635c8c * t[29]; + t[17] += (int64_t)0x25bf7a4c * t[29]; + t[18] += (int64_t)0x2d944a70 * t[29]; + t[19] += (int64_t)0x18eec490 * t[29]; + t[20] += (int64_t)0x20cd7704 * t[29]; + t[14] += (int64_t)0x129eec34 * t[30]; + t[15] += (int64_t)0x21cf5b54 * t[30]; + t[16] += (int64_t)0x29c2ab70 * t[30]; + t[17] += (int64_t)0x0f635c8c * t[30]; + t[18] += (int64_t)0x25bf7a4c * t[30]; + t[19] += (int64_t)0x2d944a70 * t[30]; + t[20] += (int64_t)0x18eec490 * t[30]; + t[21] += (int64_t)0x20cd7704 * t[30]; + t[15] += (int64_t)0x129eec34 * t[31]; + t[16] += (int64_t)0x21cf5b54 * t[31]; + t[17] += (int64_t)0x29c2ab70 * t[31]; + t[18] += (int64_t)0x0f635c8c * t[31]; + t[19] += (int64_t)0x25bf7a4c * t[31]; + t[20] += (int64_t)0x2d944a70 * t[31]; + t[21] += (int64_t)0x18eec490 * t[31]; + t[22] += (int64_t)0x20cd7704 * t[31]; + /* Propagate carries */ + c = t[ 8] >> 28; t[ 9] += c; t[ 8] = t[ 8] & 0xfffffff; + c = t[ 9] >> 28; t[10] += c; t[ 9] = t[ 9] & 0xfffffff; + c = t[10] >> 28; t[11] += c; t[10] = t[10] & 0xfffffff; + c = t[11] >> 28; t[12] += c; t[11] = t[11] & 0xfffffff; + c = t[12] >> 28; t[13] += c; t[12] = t[12] & 0xfffffff; + c = t[13] >> 28; t[14] += c; t[13] = t[13] & 0xfffffff; + c = t[14] >> 28; t[15] += c; t[14] = t[14] & 0xfffffff; + c = t[15] >> 28; t[16] += c; t[15] = t[15] & 0xfffffff; + c = t[16] >> 28; t[17] += c; t[16] = t[16] & 0xfffffff; + c = t[17] >> 28; t[18] += c; t[17] = t[17] & 0xfffffff; + c = t[18] >> 28; t[19] += c; t[18] = t[18] & 0xfffffff; + c = t[19] >> 28; t[20] += c; t[19] = t[19] & 0xfffffff; + c = t[20] >> 28; t[21] += c; t[20] = t[20] & 0xfffffff; + c = t[21] >> 28; t[22] += c; t[21] = t[21] & 0xfffffff; + c = t[22] >> 28; t[23] += c; t[22] = t[22] & 0xfffffff; + /* Mod bottom half of extra words */ + t[ 0] += (int64_t)0x129eec34 * t[16]; + t[ 1] += (int64_t)0x21cf5b54 * t[16]; + t[ 2] += (int64_t)0x29c2ab70 * t[16]; + t[ 3] += (int64_t)0x0f635c8c * t[16]; + t[ 4] += (int64_t)0x25bf7a4c * t[16]; + t[ 5] += (int64_t)0x2d944a70 * t[16]; + t[ 6] += (int64_t)0x18eec490 * t[16]; + t[ 7] += (int64_t)0x20cd7704 * t[16]; + t[ 1] += (int64_t)0x129eec34 * t[17]; + t[ 2] += (int64_t)0x21cf5b54 * t[17]; + t[ 3] += (int64_t)0x29c2ab70 * t[17]; + t[ 4] += (int64_t)0x0f635c8c * t[17]; + t[ 5] += (int64_t)0x25bf7a4c * t[17]; + t[ 6] += (int64_t)0x2d944a70 * t[17]; + t[ 7] += (int64_t)0x18eec490 * t[17]; + t[ 8] += (int64_t)0x20cd7704 * t[17]; + t[ 2] += (int64_t)0x129eec34 * t[18]; + t[ 3] += (int64_t)0x21cf5b54 * t[18]; + t[ 4] += (int64_t)0x29c2ab70 * t[18]; + t[ 5] += (int64_t)0x0f635c8c * t[18]; + t[ 6] += (int64_t)0x25bf7a4c * t[18]; + t[ 7] += (int64_t)0x2d944a70 * t[18]; + t[ 8] += (int64_t)0x18eec490 * t[18]; + t[ 9] += (int64_t)0x20cd7704 * t[18]; + t[ 3] += (int64_t)0x129eec34 * t[19]; + t[ 4] += (int64_t)0x21cf5b54 * t[19]; + t[ 5] += (int64_t)0x29c2ab70 * t[19]; + t[ 6] += (int64_t)0x0f635c8c * t[19]; + t[ 7] += (int64_t)0x25bf7a4c * t[19]; + t[ 8] += (int64_t)0x2d944a70 * t[19]; + t[ 9] += (int64_t)0x18eec490 * t[19]; + t[10] += (int64_t)0x20cd7704 * t[19]; + t[ 4] += (int64_t)0x129eec34 * t[20]; + t[ 5] += (int64_t)0x21cf5b54 * t[20]; + t[ 6] += (int64_t)0x29c2ab70 * t[20]; + t[ 7] += (int64_t)0x0f635c8c * t[20]; + t[ 8] += (int64_t)0x25bf7a4c * t[20]; + t[ 9] += (int64_t)0x2d944a70 * t[20]; + t[10] += (int64_t)0x18eec490 * t[20]; + t[11] += (int64_t)0x20cd7704 * t[20]; + t[ 5] += (int64_t)0x129eec34 * t[21]; + t[ 6] += (int64_t)0x21cf5b54 * t[21]; + t[ 7] += (int64_t)0x29c2ab70 * t[21]; + t[ 8] += (int64_t)0x0f635c8c * t[21]; + t[ 9] += (int64_t)0x25bf7a4c * t[21]; + t[10] += (int64_t)0x2d944a70 * t[21]; + t[11] += (int64_t)0x18eec490 * t[21]; + t[12] += (int64_t)0x20cd7704 * t[21]; + t[ 6] += (int64_t)0x129eec34 * t[22]; + t[ 7] += (int64_t)0x21cf5b54 * t[22]; + t[ 8] += (int64_t)0x29c2ab70 * t[22]; + t[ 9] += (int64_t)0x0f635c8c * t[22]; + t[10] += (int64_t)0x25bf7a4c * t[22]; + t[11] += (int64_t)0x2d944a70 * t[22]; + t[12] += (int64_t)0x18eec490 * t[22]; + t[13] += (int64_t)0x20cd7704 * t[22]; + t[ 7] += (int64_t)0x129eec34 * t[23]; + t[ 8] += (int64_t)0x21cf5b54 * t[23]; + t[ 9] += (int64_t)0x29c2ab70 * t[23]; + t[10] += (int64_t)0x0f635c8c * t[23]; + t[11] += (int64_t)0x25bf7a4c * t[23]; + t[12] += (int64_t)0x2d944a70 * t[23]; + t[13] += (int64_t)0x18eec490 * t[23]; + t[14] += (int64_t)0x20cd7704 * t[23]; + /* Propagate carries */ + c = t[ 0] >> 28; t[ 1] += c; rd[ 0] = (int32_t)(t[ 0] & 0xfffffff); + c = t[ 1] >> 28; t[ 2] += c; rd[ 1] = (int32_t)(t[ 1] & 0xfffffff); + c = t[ 2] >> 28; t[ 3] += c; rd[ 2] = (int32_t)(t[ 2] & 0xfffffff); + c = t[ 3] >> 28; t[ 4] += c; rd[ 3] = (int32_t)(t[ 3] & 0xfffffff); + c = t[ 4] >> 28; t[ 5] += c; rd[ 4] = (int32_t)(t[ 4] & 0xfffffff); + c = t[ 5] >> 28; t[ 6] += c; rd[ 5] = (int32_t)(t[ 5] & 0xfffffff); + c = t[ 6] >> 28; t[ 7] += c; rd[ 6] = (int32_t)(t[ 6] & 0xfffffff); + c = t[ 7] >> 28; t[ 8] += c; rd[ 7] = (int32_t)(t[ 7] & 0xfffffff); + c = t[ 8] >> 28; t[ 9] += c; rd[ 8] = (int32_t)(t[ 8] & 0xfffffff); + c = t[ 9] >> 28; t[10] += c; rd[ 9] = (int32_t)(t[ 9] & 0xfffffff); + c = t[10] >> 28; t[11] += c; rd[10] = (int32_t)(t[10] & 0xfffffff); + c = t[11] >> 28; t[12] += c; rd[11] = (int32_t)(t[11] & 0xfffffff); + c = t[12] >> 28; t[13] += c; rd[12] = (int32_t)(t[12] & 0xfffffff); + c = t[13] >> 28; t[14] += c; rd[13] = (int32_t)(t[13] & 0xfffffff); + c = t[14] >> 28; t[15] += c; rd[14] = (int32_t)(t[14] & 0xfffffff); + rd[15] = t[15]; + /* Mod bits over 28 in last word */ + o = rd[15] >> 26; rd[15] &= 0x3ffffff; + rd[ 0] += 0x4a7bb0d * o; + rd[ 1] += 0x873d6d5 * o; + rd[ 2] += 0xa70aadc * o; + rd[ 3] += 0x3d8d723 * o; + rd[ 4] += 0x96fde93 * o; + rd[ 5] += 0xb65129c * o; + rd[ 6] += 0x63bb124 * o; + rd[ 7] += 0x8335dc1 * o; + /* Propagate carries */ + o = rd[ 0] >> 28; rd[ 1] += o; rd[ 0] = rd[ 0] & 0xfffffff; + o = rd[ 1] >> 28; rd[ 2] += o; rd[ 1] = rd[ 1] & 0xfffffff; + o = rd[ 2] >> 28; rd[ 3] += o; rd[ 2] = rd[ 2] & 0xfffffff; + o = rd[ 3] >> 28; rd[ 4] += o; rd[ 3] = rd[ 3] & 0xfffffff; + o = rd[ 4] >> 28; rd[ 5] += o; rd[ 4] = rd[ 4] & 0xfffffff; + o = rd[ 5] >> 28; rd[ 6] += o; rd[ 5] = rd[ 5] & 0xfffffff; + o = rd[ 6] >> 28; rd[ 7] += o; rd[ 6] = rd[ 6] & 0xfffffff; + o = rd[ 7] >> 28; rd[ 8] += o; rd[ 7] = rd[ 7] & 0xfffffff; + o = rd[ 8] >> 28; rd[ 9] += o; rd[ 8] = rd[ 8] & 0xfffffff; + o = rd[ 9] >> 28; rd[10] += o; rd[ 9] = rd[ 9] & 0xfffffff; + o = rd[10] >> 28; rd[11] += o; rd[10] = rd[10] & 0xfffffff; + o = rd[11] >> 28; rd[12] += o; rd[11] = rd[11] & 0xfffffff; + o = rd[12] >> 28; rd[13] += o; rd[12] = rd[12] & 0xfffffff; + o = rd[13] >> 28; rd[14] += o; rd[13] = rd[13] & 0xfffffff; + o = rd[14] >> 28; rd[15] += o; rd[14] = rd[14] & 0xfffffff; + + /* Convert to bytes */ + r[ 0] = (rd[0 ] >> 0); + r[ 1] = (rd[0 ] >> 8); + r[ 2] = (rd[0 ] >> 16); + r[ 3] = (rd[0 ] >> 24) + ((rd[1 ] >> 0) << 4); + r[ 4] = (rd[1 ] >> 4); + r[ 5] = (rd[1 ] >> 12); + r[ 6] = (rd[1 ] >> 20); + r[ 7] = (rd[2 ] >> 0); + r[ 8] = (rd[2 ] >> 8); + r[ 9] = (rd[2 ] >> 16); + r[10] = (rd[2 ] >> 24) + ((rd[3 ] >> 0) << 4); + r[11] = (rd[3 ] >> 4); + r[12] = (rd[3 ] >> 12); + r[13] = (rd[3 ] >> 20); + r[14] = (rd[4 ] >> 0); + r[15] = (rd[4 ] >> 8); + r[16] = (rd[4 ] >> 16); + r[17] = (rd[4 ] >> 24) + ((rd[5 ] >> 0) << 4); + r[18] = (rd[5 ] >> 4); + r[19] = (rd[5 ] >> 12); + r[20] = (rd[5 ] >> 20); + r[21] = (rd[6 ] >> 0); + r[22] = (rd[6 ] >> 8); + r[23] = (rd[6 ] >> 16); + r[24] = (rd[6 ] >> 24) + ((rd[7 ] >> 0) << 4); + r[25] = (rd[7 ] >> 4); + r[26] = (rd[7 ] >> 12); + r[27] = (rd[7 ] >> 20); + r[28] = (rd[8 ] >> 0); + r[29] = (rd[8 ] >> 8); + r[30] = (rd[8 ] >> 16); + r[31] = (rd[8 ] >> 24) + ((rd[9 ] >> 0) << 4); + r[32] = (rd[9 ] >> 4); + r[33] = (rd[9 ] >> 12); + r[34] = (rd[9 ] >> 20); + r[35] = (rd[10] >> 0); + r[36] = (rd[10] >> 8); + r[37] = (rd[10] >> 16); + r[38] = (rd[10] >> 24) + ((rd[11] >> 0) << 4); + r[39] = (rd[11] >> 4); + r[40] = (rd[11] >> 12); + r[41] = (rd[11] >> 20); + r[42] = (rd[12] >> 0); + r[43] = (rd[12] >> 8); + r[44] = (rd[12] >> 16); + r[45] = (rd[12] >> 24) + ((rd[13] >> 0) << 4); + r[46] = (rd[13] >> 4); + r[47] = (rd[13] >> 12); + r[48] = (rd[13] >> 20); + r[49] = (rd[14] >> 0); + r[50] = (rd[14] >> 8); + r[51] = (rd[14] >> 16); + r[52] = (rd[14] >> 24) + ((rd[15] >> 0) << 4); + r[53] = (rd[15] >> 4); + r[54] = (rd[15] >> 12); + r[55] = (rd[15] >> 20); + r[56] = 0; +} + +/* Precomputed multiples of the base point. */ +static const ge448_precomp base[58][8] = { +{ + { + { 0x70cc05e, 0x26a82bc, 0x0938e26, 0x80e18b0, 0x511433b, 0xf72ab66, + 0x412ae1a, 0xa3d3a46, 0xa6de324, 0x0f1767e, 0x4657047, 0x36da9e1, + 0x5a622bf, 0xed221d1, 0x66bed0d, 0x4f1970c }, + { 0x230fa14, 0x08795bf, 0x7c8ad98, 0x132c4ed, 0x9c4fdbd, 0x1ce67c3, + 0x73ad3ff, 0x05a0c2d, 0x7789c1e, 0xa398408, 0xa73736c, 0xc7624be, + 0x03756c9, 0x2488762, 0x16eb6bc, 0x693f467 } + }, + { + { 0x5555555, 0x5555555, 0x5555555, 0x5555555, 0x5555555, 0x5555555, + 0x5555555, 0x5555555, 0xaaaaaa9, 0xaaaaaaa, 0xaaaaaaa, 0xaaaaaaa, + 0xaaaaaaa, 0xaaaaaaa, 0xaaaaaaa, 0xaaaaaaa }, + { 0xa9386ed, 0xeafbcde, 0xda06bda, 0xb2bed1c, 0x098bbbc, 0x833a2a3, + 0x80d6565, 0x8ad8c4b, 0x7e36d72, 0x884dd7b, 0xed7a035, 0xc2b0036, + 0x6205086, 0x8db359d, 0x34ad704, 0xae05e96 } + }, + { + { 0x6ff2f8f, 0x2817328, 0xda85757, 0xb769465, 0xfd6e862, 0xf7f6271, + 0x8daa9cb, 0x4a3fcfe, 0x2ba077a, 0xda82c7e, 0x41b8b8c, 0x9433322, + 0x4316cb6, 0x6455bd6, 0xb9108af, 0x0865886 }, + { 0x88ed6fc, 0x22ac135, 0x02dafb8, 0x9a68fed, 0x7f0bffa, 0x1bdb676, + 0x8bb3a33, 0xec4e1d5, 0xce43c82, 0x56c3b9f, 0xa8d9523, 0xa6449a4, + 0xa7ad43a, 0xf706cbd, 0xbd5125c, 0xe005a8d } + }, + { + { 0x8ba7f30, 0xce42ac4, 0x9e120e2, 0xe179894, 0x8ba21ae, 0xf1515dd, + 0x301b7bd, 0x70c74cc, 0x3fda4be, 0x0891c69, 0xa09cf4e, 0x29ea255, + 0x17226f9, 0x2c1419a, 0xc6c0cce, 0x49dcbc5 }, + { 0xde51839, 0xe236f86, 0xd4f5b32, 0x44285d0, 0x472b5d4, 0x7ea1ca9, + 0x1c0d8f9, 0x7b8a5bc, 0x90dc322, 0x57d845c, 0x7c02f04, 0x1b979cb, + 0x3a5de02, 0x27164b3, 0x4accde5, 0xd49077e } + }, + { + { 0x2030034, 0xa99d109, 0x6f950d0, 0x2d8cefc, 0xc96f07b, 0x7a920c3, + 0x08bc0d5, 0x9588128, 0x6d761e8, 0x62ada75, 0xbcf7285, 0x0def80c, + 0x01eedb5, 0x0e2ba76, 0x5a48dcb, 0x7a9f933 }, + { 0x2f435eb, 0xb473147, 0xf225443, 0x5512881, 0x33c5840, 0xee59d2b, + 0x127d7a4, 0xb698017, 0x86551f7, 0xb18fced, 0xca1823a, 0x0ade260, + 0xce4fd58, 0xd3b9109, 0xa2517ed, 0xadfd751 } + }, + { + { 0xabef79c, 0x7fd7652, 0x443a878, 0x6c20a07, 0x12a7109, 0x5c1840d, + 0x876451c, 0x4a06e4a, 0xad95f65, 0x3bed0b4, 0x3fb0260, 0x25d2e67, + 0xaebd971, 0x2e00349, 0x4498b72, 0x54523e0 }, + { 0x07c7bcc, 0xea5d1da, 0x38ea98c, 0xcce7769, 0x61d2b3e, 0x80284e8, + 0x6e1ff1b, 0x48de76b, 0x9c58522, 0x7b12186, 0x2765a1a, 0xbfd053a, + 0x056c667, 0x2d743ec, 0xd8ab61c, 0x3f99b9c } + }, + { + { 0xeb5eaf7, 0xdf9567c, 0x78ac7d7, 0x110a6b4, 0x4706e0b, 0x2d33501, + 0x0b5a209, 0x0df9c7b, 0x568e684, 0xba4223d, 0x8c3719b, 0xd78af2d, + 0xa5291b6, 0x77467b9, 0x5c89bef, 0x079748e }, + { 0xdac377f, 0xe20d3fa, 0x72b5c09, 0x34e8669, 0xc40bbb7, 0xd8687a3, + 0xd2f84c9, 0x7b3946f, 0xa78f50e, 0xd00e40c, 0x17e7179, 0xb875944, + 0xcb23583, 0x9c7373b, 0xc90fd69, 0x7ddeda3 } + }, + { + { 0x153bde0, 0x2538a67, 0x406b696, 0x223aca9, 0x1ad713e, 0xf9080dc, + 0xd816a64, 0x6c4cb47, 0x5dc8b97, 0xbc28568, 0xc08e2d7, 0xd97b037, + 0x5d0e66b, 0x5b63fb4, 0x520e8a3, 0xd1f1bc5 }, + { 0xe69e09b, 0x4eb873c, 0xbc8ee45, 0x1663164, 0xba8d89f, 0x08f7003, + 0x386ad82, 0x4b98ead, 0xbd94c7b, 0xa4b93b7, 0xc6b38b3, 0x46ba408, + 0xf3574ff, 0xdae87d1, 0xe9bea9b, 0xc7564f4 } + }, +}, +{ + { + { 0x5bfac1c, 0x2e4fdb2, 0xf5f3bca, 0xf0d79aa, 0x20fb7cc, 0xe756b0d, + 0xb39609a, 0xe3696be, 0x5a5ab58, 0xa019fc3, 0x3b281dd, 0xa2b2485, + 0x61ac0a2, 0xe3e2be7, 0xeb56730, 0xf19c34f }, + { 0xa30241e, 0x2d25ce8, 0xb73d7a1, 0xf5661ea, 0xdaac9f4, 0x4611ed0, + 0x4ced72c, 0xd544234, 0xe92e985, 0xce78f52, 0x4da4aad, 0x6fe5dd4, + 0x1d363ce, 0xfcaddc6, 0xc9111bf, 0x3beb69c } + }, + { + { 0x940ebc9, 0xd2e7660, 0xb17bbe0, 0xe032018, 0x75c0575, 0xad49391, + 0x21c7f34, 0xdd0b147, 0x3e147e0, 0x52c2ba4, 0x0ee8973, 0x7dd03c6, + 0xecf2754, 0x5472e8d, 0xd6482bb, 0x17a1cd1 }, + { 0x8128b3f, 0xdd43b84, 0xea7dd25, 0xf0cae34, 0xff07df2, 0x81ca99f, + 0x92ebbdc, 0x1c89597, 0x72155e6, 0x45c7a68, 0x39ddd08, 0x907a50e, + 0xbb2d89b, 0xbe398c2, 0x1b3b536, 0x38063f9 } + }, + { + { 0xf843b23, 0x149fafb, 0xac7f22a, 0x00ab582, 0xf2f4d4c, 0xa3b981b, + 0x4341a22, 0x2ce1a65, 0x7c03b63, 0x68a4074, 0x12f2cf8, 0x63206a2, + 0x5149741, 0xc9961d3, 0xbc7099e, 0xfb85430 }, + { 0x90a9e59, 0x9c91072, 0x06de367, 0x734e94a, 0xdb99214, 0x5cf3cbe, + 0x45b1fb9, 0xc6bce32, 0xdd7be0d, 0x1a82abe, 0xede7d1c, 0xf74976a, + 0x21503bd, 0x7025b7c, 0x0d096ab, 0xf789491 } + }, + { + { 0x555a41b, 0x6bd48bb, 0x67de206, 0xfbdd0d0, 0xdd6dfd1, 0x98bc477, + 0x3e40b8a, 0x1d0693b, 0xda32ae4, 0x6e15563, 0xfcebaa2, 0x0194a20, + 0x0980a93, 0xda11615, 0x0109cec, 0x8e11920 }, + { 0xffb9726, 0x8ea0552, 0x047e44b, 0xeba50a4, 0x60ddf76, 0xc050d24, + 0xac690e0, 0xe009204, 0x9b18edc, 0x47b8639, 0xc77f23f, 0x2f5b76a, + 0x0792905, 0x4296c24, 0x06f6dc7, 0x73f6b4a } + }, + { + { 0x3b10cad, 0xb6ef9ea, 0xf7c8fce, 0x312843d, 0x8bedf86, 0x5bdcd52, + 0xf6dd823, 0x2889059, 0x08bfde0, 0x04578e9, 0x123e2e5, 0x3245df3, + 0x7ee9e3a, 0xbf461d5, 0x6f94ceb, 0xddec2d4 }, + { 0x145768f, 0x21b43b9, 0xdae962a, 0xe79a8f9, 0xcbb043f, 0xff1972b, + 0x239649b, 0xe3dcf6d, 0xc533b85, 0xed592bd, 0xdbe22d0, 0x14ff94f, + 0xf1d8e22, 0x6c4eb87, 0xd18cf6d, 0xd8d4c71 } + }, + { + { 0x8d96345, 0xcda666c, 0x836cd21, 0x9ecaa25, 0x984606e, 0x6e885bd, + 0x804f054, 0x1dd5fef, 0x6959ae4, 0x9dfff6b, 0xc9b55cc, 0x99b9cf8, + 0x62b9b80, 0xb4716b0, 0x554b128, 0x13ec87c }, + { 0x75aacc2, 0xe696d1f, 0x87fc5ff, 0xf78c993, 0x3809d42, 0x76c0947, + 0xb618fa8, 0x99ce62d, 0x2f53341, 0x35e3e02, 0x0db6c5e, 0x62fc1ac, + 0x00d8b47, 0xa1fb8e6, 0x58f0d1e, 0x0bc1070 } + }, + { + { 0x16da513, 0x1f45269, 0xf5cf341, 0x1f2fc04, 0x64d23e0, 0xae92086, + 0xda8a113, 0x4e33082, 0x1cfc085, 0x2688ec6, 0x6e5327f, 0x6f2e8de, + 0xb4e48a8, 0x2070db3, 0x3240ade, 0xd662697 }, + { 0xfbd997b, 0xa6b317f, 0x49e26bd, 0x9fa1b56, 0x8cba0f3, 0xcbf0d25, + 0x17b4745, 0x4a7791b, 0x5c9e190, 0x25f555b, 0x923ec4c, 0x7cd3940, + 0xe98f1b6, 0x16f4c6a, 0xbcd4e0f, 0x7962116 } + }, + { + { 0x02491e3, 0x8d58fa3, 0x7ab3898, 0x7cf76c6, 0x647ebc7, 0xbc2f657, + 0xd25f5a3, 0x5f4bfe0, 0xd69505d, 0x503f478, 0x3fb6645, 0x4a889fc, + 0xfa86b18, 0x33e1bc1, 0x5508dd8, 0xabb234f }, + { 0x9a05b48, 0x5348e1b, 0x64dc858, 0x57ac5f1, 0xec8a2d3, 0x21f4d38, + 0xa3a3e9d, 0x5ec6d3c, 0x560a0b8, 0xcd4062e, 0x3433f59, 0x49b74f7, + 0xcab14e3, 0xefd9d87, 0xeb964f5, 0x858ce7f } + }, +}, +{ + { + { 0xeb731b4, 0x7577254, 0x4e2397e, 0x9fff1fb, 0xc821715, 0x749b145, + 0x2e65e67, 0x40619fe, 0x2e618d8, 0x57b8281, 0x707b83e, 0x063186c, + 0x31b24a2, 0xcfc80cb, 0xac75169, 0xcca6185 }, + { 0xb255818, 0x6539f44, 0x0368bce, 0x5895da0, 0x17c7482, 0x841a309, + 0xb1a9c9e, 0x85469e1, 0xe4f7d9d, 0x05664c0, 0x7b35cc0, 0x8a06318, + 0xa0e9b0a, 0x214763a, 0x4b26ac2, 0x1bd872c } + }, + { + { 0xa93762b, 0x3578f97, 0x72d52bc, 0x434f69a, 0x22cb565, 0xddcca40, + 0xff20544, 0xa7d1e41, 0x8a66588, 0x823475d, 0x99d7baf, 0x9fc97c7, + 0x660e421, 0x15542f1, 0x843faf6, 0xa7d1f60 }, + { 0x4063ccc, 0xbbfaab5, 0xa49855a, 0x3ad9bad, 0x5bddbfe, 0xffd5f1c, + 0xae87e59, 0x0e419c2, 0xf89956b, 0xdce6ed6, 0xccd8951, 0xf047c21, + 0xa83c991, 0x6ed4a1b, 0x2d28e0a, 0x85af86e } + }, + { + { 0x9ed48a8, 0x04433c4, 0x0bc375d, 0xeffa858, 0xfa6e3b5, 0xfb0e1b2, + 0xa1aadda, 0x51483a2, 0xf8b2ea8, 0x733448d, 0xf639f0c, 0xaa0513c, + 0xa23bf84, 0x6bc61a3, 0xdc2430d, 0x3e64f68 }, + { 0xc5876b1, 0x51bf502, 0x1c0dd2a, 0x6b83375, 0x342914f, 0xe597be1, + 0xf8e632c, 0x43d5ab0, 0xd62587b, 0x2696715, 0xed34f24, 0xe87d20a, + 0xe18baf7, 0x25b7e14, 0xe22e084, 0xf5eb753 } + }, + { + { 0x24d8295, 0x51da717, 0x18d1340, 0xd478e43, 0x2cf7f66, 0xacf94f4, + 0x3760711, 0x230d7d1, 0x5abc626, 0x078a66a, 0x6b5f6da, 0xd78b0bd, + 0x96d1d0b, 0x23a9713, 0x4bd960f, 0x87623d6 }, + { 0x77db53f, 0x0841a99, 0xf4d03ee, 0x23c1a53, 0x1f95df1, 0x2f62c2e, + 0x116f4e7, 0xd1e2ec1, 0x34811a9, 0x896d2fe, 0xec8096e, 0xad65e2b, + 0xb1744a6, 0x09d36f9, 0xff5ddf7, 0x564bac7 } + }, + { + { 0xc3f77cb, 0x48b41e2, 0x0968938, 0x5227673, 0xfd9b452, 0xff1b899, + 0x2e03908, 0x67cf3bf, 0x248a6fb, 0x3731d90, 0x256598f, 0xd800a05, + 0xbdc8530, 0x347d2f2, 0x7ad08a1, 0xc72a300 }, + { 0x1d65f73, 0x5e5be74, 0x4206ead, 0x183d4ae, 0xade4013, 0xcb50c1c, + 0x3102483, 0x39db43d, 0x70d6325, 0x0eb49fa, 0xc1f02b9, 0xa18f6a2, + 0xdbf5e66, 0x3e6fe30, 0x3a82aa5, 0xac4eeb9 } + }, + { + { 0x3613d47, 0x295affd, 0xb56f343, 0x7b7e68a, 0x92b173b, 0x9806296, + 0xbad35fb, 0x937061e, 0x5c21eea, 0x2501978, 0x787a746, 0xe92721b, + 0x3651631, 0x463c46c, 0xc6f2d5a, 0x6da4b5d }, + { 0x6e6d18c, 0xcb67cc1, 0x0010588, 0x1b30d52, 0xdb1d1e8, 0x1bb6ea6, + 0xad11474, 0x9c6308a, 0x3d19b1c, 0xc316741, 0xbe4fb79, 0xf2e84d7, + 0xe050f77, 0xeccb873, 0xcc2bf86, 0xf7c8d80 } + }, + { + { 0x7ab20e5, 0x16fe2e1, 0xecf3a92, 0x274dead, 0x0972f67, 0x9f43487, + 0x4605751, 0x9a65a45, 0xb8980b2, 0x9351f07, 0x0eb08a5, 0x412962b, + 0x733f440, 0xb8c9bfd, 0x1ca250f, 0xac2cd64 }, + { 0x2ba7d26, 0x68cdd0f, 0x4e0beea, 0xd3d2a4a, 0x9f4a258, 0x50135c1, + 0xf0d02e4, 0xb475e53, 0x589283a, 0x432d8c6, 0xa0a2b6c, 0x29141bf, + 0x13704bc, 0xd7379ec, 0x52459bf, 0x831562c } + }, + { + { 0xeeec506, 0x676b366, 0x45da557, 0xdd6cad5, 0x77057d2, 0x9de39cb, + 0xdf05bf1, 0x388c5fe, 0xdfb1f03, 0x6e55650, 0x52126c9, 0xdbceffa, + 0x3a4a220, 0xe4d187b, 0xeb27020, 0xac914f9 }, + { 0xd2e5f30, 0x3f4ab98, 0xdd94451, 0x6ae97da, 0x0d80981, 0x64af695, + 0xf2aa2ce, 0x36b4b90, 0x18fcf59, 0x6adcd7a, 0xc116c81, 0x3ddfe6d, + 0x549b9e3, 0x661072b, 0xec4584d, 0xd9e3134 } + }, +}, +{ + { + { 0xa1e400c, 0x6e46707, 0x551e806, 0xcdc990b, 0x3a07724, 0xfa51251, + 0x1b3e4f5, 0x500553f, 0xef4dac3, 0x67e8b58, 0x2cb4cc7, 0x958349f, + 0x7f9143c, 0x948b4ed, 0x2b7822b, 0xe646d09 }, + { 0x2bc3c26, 0xd185dd5, 0xc837fc9, 0x34ba16e, 0x5a788b7, 0x516d4ba, + 0x56142b0, 0x72f2de7, 0xf445b3d, 0x5846f61, 0xf4631a1, 0xdaec5c9, + 0x169ea9b, 0xa10b18d, 0xaf6751b, 0x85d2998 } + }, + { + { 0x43ddf31, 0xda0cac4, 0x1860911, 0x0966e17, 0x3cba600, 0x9c3a717, + 0x571f895, 0x5781880, 0x737ac21, 0x5e2a927, 0x6c253fb, 0x8a46148, + 0x95ee626, 0xe801cf5, 0x5f84fc0, 0x271166a }, + { 0xba856bd, 0x306937f, 0xbe80a43, 0x80cb179, 0xffb5980, 0x70393b2, + 0x660fc64, 0xa8e4a1c, 0xc0d5c98, 0x5078abf, 0xfbd31ff, 0x62ba530, + 0x9e51b88, 0xda60844, 0x355ae15, 0xdb6ecb0 } + }, + { + { 0x23c5d49, 0xbcbb6ea, 0x87959bc, 0x08906ba, 0x0991665, 0x61cc088, + 0xd90d13c, 0x21d6b41, 0xd03afe9, 0x0c27ac1, 0x5cfea52, 0x159995f, + 0xbdfe220, 0x4057e20, 0xcbdf058, 0xdd1b349 }, + { 0x2e37159, 0x0cd6626, 0x3eb0d17, 0x8cea8e4, 0x5bce7f0, 0x553af08, + 0x5b6511d, 0xb94cb5f, 0x50e0330, 0x7b8d3a5, 0x57ab7e7, 0x4159110, + 0x6aa886f, 0x320820e, 0xc5b6b81, 0x130d4d6 } + }, + { + { 0xc7bb2ed, 0x2f98059, 0xa49bdfb, 0x33ebf4c, 0xb0a675b, 0x04c72a1, + 0xadb6c14, 0x94f9ea4, 0xcf728c0, 0x03376d8, 0x4c6eb6a, 0x5c059d3, + 0xeb8da48, 0x0178408, 0x2956817, 0x8bf607b }, + { 0xceb3d28, 0x7ad2822, 0x37ae653, 0xd07a403, 0xc1e46b2, 0xbc68739, + 0x9154ba9, 0x15d7cca, 0xa26617d, 0x6b97103, 0xb2e0d28, 0xa610314, + 0xfd4d363, 0x52a08ba, 0xc7dc2af, 0x80c2638 } + }, + { + { 0x3187140, 0x0cde7ef, 0x4b70acd, 0x93b92ca, 0x7a79cdc, 0x5696e50, + 0x8eaab66, 0x73cc972, 0x8f1b0c7, 0x6b8c5b6, 0x4f7e0b1, 0xb39a318, + 0x376108a, 0x72cfb0d, 0x98536a7, 0x0c53efc }, + { 0x24c2f1e, 0x03b52a8, 0x6399b78, 0x717132e, 0x349a85d, 0x31ebd25, + 0x1a200d4, 0x265ee81, 0x407d7ad, 0x0b1aad2, 0x94d2962, 0x9a9ebc8, + 0x41171d9, 0x994e6cd, 0x6c8fa83, 0x09178d8 } + }, + { + { 0xa2593a1, 0x7d1d238, 0xb38fb19, 0x863e93a, 0xe7712a9, 0xd23a4cc, + 0x27efcd5, 0x7477b13, 0x1392f6c, 0x3ba69ff, 0xf7bb5a5, 0x63e0c32, + 0x026effd, 0x20412c0, 0xef424ab, 0xd3ee8e4 }, + { 0x64e5174, 0x14c0b2d, 0xe58c47b, 0x2a611f2, 0xc1e8635, 0xaa58a06, + 0xcf17034, 0x1870c3e, 0x83f1bf3, 0xb0d5e34, 0x16c7eb3, 0xb19905c, + 0x6efa4ca, 0xbf85d62, 0x180f92b, 0xfd16b2f } + }, + { + { 0x3adcb48, 0xc0431af, 0xba90496, 0xc9a7a8d, 0x3895294, 0xd765a16, + 0x551de70, 0xb02a41a, 0x749b8a1, 0xb71b261, 0xc6f3e47, 0x0dfa89e, + 0x0f5d9ce, 0x392c0d8, 0x31aee3c, 0x43c59d8 }, + { 0x4d76f49, 0x94bfb6d, 0x27d68a5, 0xe8f5b82, 0x630fd08, 0x78ae1d9, + 0xce1bdae, 0x1379029, 0x66715dc, 0x9689da0, 0xd3278c7, 0x5d4cb24, + 0x9e84fbc, 0x77c9833, 0xea1048c, 0xc8478dc } + }, + { + { 0x770d2ba, 0xe4b8f31, 0x42ea095, 0x744f652, 0x036f138, 0xd06e090, + 0x3b078ca, 0xd3a3d5b, 0x78b8417, 0xc7ae541, 0xc738fd7, 0xad6c5d4, + 0x4676454, 0x6178984, 0x5d9a392, 0xfbf3423 }, + { 0xfff772f, 0x8e451a7, 0x5ffbead, 0x8605bb7, 0x930d59f, 0x6f75cc1, + 0x8f3f460, 0xd4f4755, 0x6700c8a, 0xefd2d79, 0x2406421, 0xceb462a, + 0x9dfe8f1, 0x8ed0f97, 0xd1d7600, 0x0280bf1 } + }, +}, +{ + { + { 0xdd9a54d, 0x761c219, 0x86a39c0, 0x1127fcb, 0x4c9bedd, 0x7d0e4f0, + 0x4d976b6, 0x27c017a, 0xda042cf, 0x800c973, 0x2593f11, 0xe7419af, + 0xae67960, 0xbd49448, 0x744fd85, 0xd3b60b7 }, + { 0x61676fe, 0x5e74ed9, 0x39af627, 0x7383ef3, 0x5e62df7, 0x34407e0, + 0x8bf3196, 0xb053461, 0x583b407, 0xd6b7184, 0x55011be, 0xe3d0685, + 0x2124b52, 0x94083d0, 0xf780aaf, 0xa908324 } + }, + { + { 0x73ec9c3, 0xb27af1a, 0x70fa725, 0xb66ad9f, 0x8cf73e4, 0x07724f5, + 0x9949358, 0xc3fcd57, 0xda0cc01, 0x06efb79, 0x10597c9, 0x1e977d2, + 0x703e8d6, 0xcd732be, 0x6d0b69e, 0x6fd29bf }, + { 0x667128e, 0xca658ac, 0xc7872b3, 0xca0036a, 0x5355837, 0xc969858, + 0x075cf1c, 0x59f3be8, 0x3809a11, 0x9f1b9b0, 0x9733871, 0x6881ced, + 0xe902a5f, 0x8cda0fb, 0x4e3871e, 0x4d8c69b } + }, + { + { 0xddee82f, 0x5c3bd07, 0x2f9723b, 0xe52dd31, 0x74f1be8, 0xcf87611, + 0x35f8657, 0xd9ecbd8, 0xfbfea17, 0x4f77393, 0xd78fe2c, 0xec9579f, + 0x0fb0450, 0x320de92, 0x95d9c47, 0xbfc9b8d }, + { 0x5e1b4c3, 0x818bd42, 0x40e2c78, 0x0e0c41c, 0xbccb0d0, 0x0f7ce9a, + 0x5ef81fb, 0xc7e9fa4, 0x73574ad, 0x2561d6f, 0xd2efb0b, 0xa2d8d99, + 0xe96cd0a, 0xcf8f316, 0x4964807, 0x088f0f1 } + }, + { + { 0x45d5a19, 0x0a84989, 0x6c2131f, 0x47ab39c, 0xf3fc35d, 0x5c02824, + 0x9ee8127, 0x3be77c8, 0xc90b80a, 0xa8491b7, 0xa28aa93, 0x5397631, + 0x6c0b344, 0x54d6e81, 0x876d0e4, 0x22878be }, + { 0x6db3bf6, 0xeecb8a4, 0x54577a3, 0x340f295, 0x9a00f85, 0xa779868, + 0x4bb9147, 0x98465d7, 0xda3c736, 0x9532d7d, 0x7504b20, 0x6d574f1, + 0xd86e435, 0x6e356f4, 0x4533887, 0x70c2e8d } + }, + { + { 0xd293980, 0xdce5a0a, 0x069010e, 0x32d7210, 0x06deaaa, 0x64af59f, + 0x59239e4, 0xd6b43c4, 0x9199c29, 0x74bf255, 0x11e1e2b, 0x3efff41, + 0xcb0f8d8, 0x1aa7b5e, 0x989e395, 0x9baa22b }, + { 0x7b33ac1, 0xf78db80, 0x54ce80a, 0x05a3b43, 0x7bc8e12, 0x371defc, + 0x1224610, 0x63305a0, 0x6d697ef, 0x028b1ae, 0x1cd8051, 0x7aba39c, + 0x28ee4b4, 0x76ed7a9, 0x7f99901, 0x31bd02a } + }, + { + { 0xf075566, 0xf9dab7a, 0xf56f18b, 0x84e29a5, 0xf64e56d, 0x3a4c45a, + 0x6a7302d, 0xcf3644a, 0x156b658, 0xfb40808, 0xf96be52, 0xf33ef9c, + 0xcaa2f08, 0xfe92038, 0xb261894, 0xcfaf2e3 }, + { 0x224ce3f, 0xf2a0dbc, 0x592eb27, 0xed05009, 0x95889d0, 0x501743f, + 0x77c95c2, 0xa88a478, 0xdd63da9, 0x86755fb, 0xc7ee828, 0x9024acf, + 0xf38113b, 0x634b020, 0x6056e64, 0x3c5aacc } + }, + { + { 0xa2ef760, 0xe03ff3a, 0xb1c3bac, 0x3b95767, 0x940d754, 0x51ce6aa, + 0x47a9a3d, 0x7cbac3f, 0x34f8d1a, 0xa864ac4, 0x80dbd47, 0x1eff3f2, + 0x7ebd5ca, 0xd8ab660, 0x05b07ed, 0xc4df5c4 }, + { 0xa4f095b, 0x3dc92df, 0x7cdbd9a, 0x5ae36a5, 0x7891e04, 0x7ff2973, + 0x0a5fe7b, 0x37c0313, 0xaa6e35e, 0x210d7b0, 0xbf200d8, 0x6edfb53, + 0x84afb85, 0x787b68d, 0x72c6de3, 0x9b5c49b } + }, + { + { 0x4010f4e, 0x5185716, 0x0536ebe, 0xe0b144b, 0x887d663, 0xacabb14, + 0xedf584f, 0xac1caed, 0xaf175a3, 0xb43fb8f, 0xf992a3c, 0x310b6d5, + 0x85178a4, 0xf2c4aa2, 0x8bd56bf, 0x69c9969 }, + { 0xa4d972e, 0x73d6372, 0x9583803, 0x3d5bb2e, 0xd891581, 0x7bf7d18, + 0x568a34a, 0xa5ce5d7, 0x1f45c81, 0x670b433, 0x1f96910, 0x97265a7, + 0xb07c1ea, 0xdb14eb3, 0xfed447c, 0xdf008ea } + }, +}, +{ + { + { 0x00c2f10, 0x0379f5a, 0xd350285, 0xb320b4f, 0x8efdd7d, 0x74e560e, + 0xf46a140, 0xf2f017e, 0x0f34624, 0x2ced1a6, 0xca08ec9, 0x7c4b4e3, + 0x5d8bc6b, 0xdffc2a1, 0x527b007, 0xcc8f3f3 }, + { 0x861fe83, 0x59f8ac4, 0xd03144c, 0x8d48d2c, 0xbfa6dce, 0xa8457d2, + 0x677c136, 0xd7ed333, 0xc228e18, 0xcb8e219, 0x16ab1e4, 0x5f70bc9, + 0x3780370, 0x2ae3a3d, 0x88f17ad, 0x9f33654 } + }, + { + { 0x960e4bb, 0xeab0710, 0xab9cfd3, 0xc668a78, 0xb0ef946, 0x2e85553, + 0x8df5df3, 0xa43c4b9, 0x3cb3646, 0x0ecd559, 0x18dbe71, 0x6f543c4, + 0xf59818b, 0xee7edaa, 0x90911c1, 0xc44e8d2 }, + { 0x269b509, 0xafb38b1, 0x52afe2c, 0x9e2737c, 0xccfa664, 0x5b2ef02, + 0xe1cc58b, 0x1e0aeac, 0x5ea134e, 0x37a57e9, 0x83b9fc2, 0xc9c465a, + 0x6e3ecca, 0x4b9e8c7, 0x9bdbab5, 0xca07dbe } + }, + { + { 0xb0d7807, 0xd297f3c, 0xf59ce61, 0xee441a5, 0xb2db844, 0x728553b, + 0x640e9e0, 0x90f87e5, 0xcb76dff, 0xaa72cbf, 0x4012d57, 0x065c686, + 0x9678b44, 0xd5ee88f, 0x2177603, 0x3d74b85 }, + { 0x748b68e, 0x3f9c947, 0x8f44d44, 0x03856d9, 0x462426c, 0xde34b84, + 0x845ab29, 0xc16d1bb, 0xd2e18de, 0x9df6217, 0xb154643, 0xec6d219, + 0x2ee0f8f, 0x22a8ec3, 0x91c5175, 0x632ad38 } + }, + { + { 0x6869267, 0x19d9d23, 0xfe5532a, 0x628df94, 0x6dc9a01, 0x458d76c, + 0x2cc39c8, 0x405fe6c, 0xf3a04ba, 0x7dddc67, 0x12500c7, 0xfee6303, + 0xa50e9de, 0x580b6f0, 0x6090604, 0xfb5918a }, + { 0x3af6b2d, 0xd715925, 0x1c7d1ec, 0x83d62d6, 0x85858c4, 0x94398c1, + 0x14bfb64, 0x94643dc, 0xaf7db80, 0x758fa38, 0xa8a1557, 0xe2d7d93, + 0x3562af1, 0xa569e85, 0x84346aa, 0xd226bdd } + }, + { + { 0xd0ccd20, 0xc2d0a5e, 0x5dbc0cf, 0xeb9adb8, 0x26d7e88, 0xe0a29ee, + 0x84a8e98, 0x8bb39f8, 0x37396ea, 0x511f1c1, 0xc8b2fb3, 0xbc9ec5a, + 0x090e5bc, 0x299d81c, 0x4cdd587, 0xe1dfe34 }, + { 0x5e465b7, 0x80f61f4, 0x1bad59e, 0x5699c53, 0xb79ff92, 0x85e92e4, + 0x9db244c, 0x1e64fce, 0xa22097d, 0x3748574, 0xefff24e, 0xe2aa6b9, + 0x0a10bc6, 0xb951be7, 0x9067a1c, 0x6685326 } + }, + { + { 0xa6114d3, 0xf716ddf, 0x037ec1f, 0x9e515f5, 0x44944a6, 0x7734541, + 0xaba97cc, 0x1540c4c, 0x8b54bb7, 0xe41e548, 0xcae37bc, 0x4363156, + 0xf3d2ce8, 0xc384eaf, 0x4c58ba4, 0x72a4f45 }, + { 0xdcaf3fc, 0x0ceb530, 0x78dcdbb, 0x72d5365, 0xc6320fa, 0x9b44084, + 0xeb74c70, 0x6262d34, 0x608e6dc, 0x8abac85, 0x10dd38d, 0x82a5264, + 0xa819b8d, 0xbc39911, 0x03ad0d9, 0xbda15fe } + }, + { + { 0xf9dc60b, 0xadbf587, 0x7d846d2, 0xf9d814f, 0xb77bde0, 0xccdd241, + 0x2242f50, 0x89cb6d7, 0xe6360a8, 0x95c0e3e, 0xdf49713, 0x7c7dd5a, + 0x57d5814, 0x68e0e49, 0x0c16571, 0x3aa097d }, + { 0x267d03a, 0xb56b672, 0x8c44af4, 0x4f55708, 0xf3252a5, 0x67c49e7, + 0xc94a469, 0x871d6cf, 0x01fbfaa, 0x57ae998, 0x48a5d8e, 0x5c0e48f, + 0x5e240b9, 0xe9bf9c8, 0x99d41ca, 0xa410189 } + }, + { + { 0xb2889b4, 0x6beb0c7, 0x9455370, 0x78b7f89, 0x47ca364, 0xd434214, + 0x9f21e5b, 0xdd9d2da, 0x0a7e4aa, 0xa0c7c18, 0xda1660c, 0x022c0d4, + 0x5a57002, 0xe1f5c16, 0x518f68f, 0x51c7c9e }, + { 0x2586502, 0x6d521b6, 0x183ec1b, 0xa0f2cb3, 0xcaa5e16, 0x578b4e0, + 0x764997f, 0x7bd4fbd, 0x64b1804, 0x7ec56c3, 0x0ee08e4, 0xb75a254, + 0xdc19080, 0x6bf74a6, 0x97d6e59, 0x6ec793d } + }, +}, +{ + { + { 0x0a4beb9, 0x16789d6, 0x9b9c801, 0x512b2cd, 0x8c7bb9c, 0xf8b6d10, + 0x9ebdc8c, 0xd85651e, 0x9ba971a, 0xc945082, 0x7e1cf78, 0x852d9ea, + 0x0af01e2, 0x6a45e35, 0x6151dcf, 0xe6cdadf }, + { 0x2b8c01b, 0xc454bb4, 0x3d54cd2, 0x59e0c49, 0x454d608, 0x8e1e686, + 0xd8c6103, 0x0dbae4b, 0x6c18b18, 0xa5603a1, 0x3369093, 0x227a6b2, + 0x5f3de1c, 0xf1e8929, 0x8ab63c5, 0x42f0b58 } + }, + { + { 0x5b596d8, 0xf1974cc, 0x44719f0, 0xee8093f, 0xf6f5b54, 0x40ba933, + 0x2f3d654, 0xd6e5365, 0x26d73b8, 0x9aeb835, 0x0776382, 0x50ed535, + 0xad43875, 0x3be47d6, 0xc786e48, 0x21d56df }, + { 0xb73bb39, 0x8a75e18, 0xf265a78, 0x9eba84c, 0x2e772e7, 0x7c02a4d, + 0x4c1ecd2, 0xf7df6d4, 0x6cef71b, 0xa8d9ea0, 0xcae3b68, 0x86e8f91, + 0x99efefa, 0x2fd1411, 0x214e6f6, 0x0b36ab2 } + }, + { + { 0xbdce61c, 0xd79065c, 0xdecb229, 0xcb562ff, 0x4600849, 0xef5d3d1, + 0x1d23ac8, 0x348b31b, 0x15c36b8, 0xb2ea699, 0x4822836, 0x268683d, + 0xc6f0b7d, 0x083edbe, 0x1a7821c, 0xaf4f39d }, + { 0x4e64841, 0x23be6e8, 0x65bf791, 0xe9e2463, 0x02bfd7c, 0xa3208ac, + 0xd01357d, 0x231989c, 0x6422ab4, 0x79b8aad, 0x91b8564, 0x57d2b7e, + 0x8c04421, 0x28ebbcc, 0x7d09c05, 0xdc787d8 } + }, + { + { 0x6c7bed5, 0xeb99f62, 0x39cd0e8, 0x326b15f, 0xd860615, 0xd9d53dc, + 0x1bf4205, 0xdf636e7, 0x0752209, 0x1eaa0bf, 0x4744abb, 0x17ce69a, + 0xf3ea2fb, 0x474572d, 0x224a7f3, 0xc4f6f73 }, + { 0x63081b4, 0x7ed86ad, 0x4a20afb, 0xcd4cdc7, 0xb301b2e, 0x7563831, + 0xe038699, 0x5b4d2b1, 0x802a15f, 0xa15d1fa, 0x13e9172, 0x6687aaf, + 0xba6da90, 0x3eccd36, 0x7474e83, 0x34e829d } + }, + { + { 0x19c9b27, 0x4cea19b, 0x5f52523, 0xa14c37a, 0x726625c, 0x248b16d, + 0x6cabc21, 0x8c40f9f, 0x32a5c65, 0x918470c, 0x2a98d5b, 0x314056b, + 0x34a0714, 0x6c974cf, 0x4f6314a, 0x0c8f8a9 }, + { 0x70bccfd, 0x4844557, 0x740c9fd, 0xf5835db, 0xa21407c, 0x12e59b5, + 0xdb1689d, 0xbe338e0, 0xdd5e915, 0x5a50ce9, 0xef99f39, 0xb1780e9, + 0xee4d833, 0x1262b55, 0x89c5340, 0x4be3f22 } + }, + { + { 0x6c4b858, 0xbb99b90, 0x550ca53, 0xa7724d1, 0x826962e, 0x7d31f5a, + 0xa5804da, 0xf239322, 0x0275048, 0x3e11320, 0x3ee4cb6, 0xcbb1bb8, + 0x1331191, 0xdb86525, 0x7d1d903, 0xb7caf9e }, + { 0x77d7a9d, 0x06e3b05, 0xb3bbbf5, 0x7a132b0, 0x7c50575, 0xd61fbc5, + 0xaf4b646, 0x393f712, 0xcb7efe9, 0xef77972, 0x5ea4995, 0x20e6d5d, + 0xfbbe4c6, 0x0ac23d4, 0xc807f2a, 0x8456617 } + }, + { + { 0x5396143, 0x4995fb3, 0xb99dc46, 0xa8b4bd1, 0x4150064, 0x2293e8e, + 0x22a3545, 0x2f77d49, 0xb2192c4, 0xe866b03, 0x5e0aa38, 0x58b01f0, + 0x2ed246b, 0xe406b23, 0xed60974, 0x447edb3 }, + { 0x8869703, 0xf541b33, 0x383420a, 0x6959fe0, 0x4be4e48, 0xd6b39db, + 0xb5714ef, 0x048f3b4, 0x5d9e4b8, 0x68b4968, 0x2177963, 0xbda8e6c, + 0xc4211fe, 0x5094e35, 0x2d46d1a, 0xea591c3 } + }, + { + { 0x2fef780, 0x3a768ff, 0x32970c6, 0x4218d28, 0xec6da17, 0xce598e4, + 0xfbb126a, 0xf675645, 0x0427617, 0xb04c23f, 0xe4fce74, 0xc9f93fb, + 0x3c91b00, 0x44a414b, 0x1d3b3cc, 0x4d982f3 }, + { 0xb24cce0, 0xb1d40e8, 0x133e73d, 0x5a21c07, 0x0bb589d, 0x6e9358e, + 0x2399844, 0x39cfb17, 0x166080e, 0x83f7647, 0x450b468, 0xcfe7bf8, + 0x1e8434f, 0x2a288f7, 0x21a81e3, 0xd39f1e5 } + }, +}, +{ + { + { 0x528af6f, 0x78c6f13, 0x94b74d9, 0x0001fe2, 0x01aab44, 0xae77425, + 0xef0039c, 0x7cbe937, 0x0fa2a67, 0xaf3e4f0, 0xda1378e, 0xe28175f, + 0x8ccd90e, 0x72adeed, 0x00af22f, 0x16a8ce1 }, + { 0xcbf63dd, 0x69fae17, 0x9e39e26, 0x6786172, 0xf827a18, 0xe92b3d5, + 0x8403682, 0x4d75e41, 0x9056a79, 0x01a4fd9, 0x20008f5, 0x89efb2d, + 0xb78ff15, 0xa2f6918, 0xa3437f5, 0xf41c870 } + }, + { + { 0x7be353c, 0xc840ae5, 0x3fb2691, 0x465a5eb, 0x7eba833, 0x34a89f0, + 0x013346e, 0xf620896, 0xe875df2, 0x563b5f0, 0xfbc44ce, 0x5f7fc8b, + 0xcfedf9d, 0x22fcb5a, 0x7dc691b, 0x7cf68d4 }, + { 0x76a103f, 0x37f7c2d, 0xfd87b7d, 0x728a128, 0xccf2132, 0x7db2ad8, + 0xb100e63, 0xa4c13fe, 0x7b511d5, 0xcd28a51, 0x721ca5c, 0xb910280, + 0xd84bd52, 0xec1305f, 0x2729791, 0xb964642 } + }, + { + { 0x5bc7462, 0x83fccdf, 0xd6f012f, 0x01f3dda, 0x3a6a87c, 0x57f1171, + 0xff403ac, 0xedb47ce, 0xbaab073, 0x6c184e5, 0x6f0d6a1, 0x5b17c7d, + 0x3ef2c91, 0x45a4c4f, 0x86a8f41, 0x26c3f7e }, + { 0xb646514, 0x81a6db0, 0xca8b9ae, 0xf84059f, 0x9f02305, 0xd73dab6, + 0xc4b7c6c, 0x0de3fae, 0x696df2f, 0x18abb88, 0x75d7740, 0x45dd1b9, + 0x9ee35bc, 0x3aeccc6, 0xb029f88, 0x478252e } + }, + { + { 0x8b2ce15, 0x66bf85b, 0x335709d, 0x1175425, 0x8123874, 0x00169ef, + 0x9b89868, 0xfd3c18c, 0x775204e, 0xb3612f9, 0xc2cd510, 0x4b8d09d, + 0x14559ad, 0xafa12e6, 0x9657493, 0x1ddaa88 }, + { 0x1e77a08, 0x87d700b, 0x14d2e71, 0xaf4cf2f, 0xbf90c94, 0xe00835d, + 0x6dc8429, 0xb16a6ec, 0xf8a4d92, 0x02a7210, 0x3d0c48d, 0x5a5ab40, + 0xb5b9bea, 0x0052b3a, 0xe138f89, 0x6242739 } + }, + { + { 0x16b2819, 0x7c215d3, 0xfeb9d7a, 0xdacb65e, 0xd833423, 0xc3c569e, + 0x886a058, 0xbc08435, 0x7e5cb61, 0x132c4db, 0x9422aff, 0x6373a27, + 0xfca9fc4, 0x43b9d7e, 0xdbe465f, 0xe3319a5 }, + { 0x0b39da7, 0x51d3687, 0x4b75492, 0xcb6d798, 0xeadd87a, 0x77eb272, + 0xe0d3f6c, 0xf2fb47d, 0xf9f791c, 0x807fd86, 0x975e885, 0xf01086b, + 0xb6a3604, 0xf9314b5, 0x67be852, 0x8cd4538 } + }, + { + { 0x858f79b, 0x7c1e6b3, 0x938caf9, 0xf0477c4, 0x3e88c44, 0xb311bbf, + 0x1e3a3c1, 0x9234c09, 0x95a1d4d, 0x531af2b, 0xb8d1c64, 0xf3cc969, + 0xb51e78d, 0x6f3c328, 0x34e8881, 0x5a1bd6c }, + { 0x3a9336f, 0x2e31239, 0x5ced897, 0x020f0cc, 0x5fab121, 0x4b45d7b, + 0x1841210, 0x8068b1c, 0x8349170, 0x1bd85fc, 0x0f97fe5, 0xfe816d8, + 0x14b84fc, 0x1089818, 0xb93cd48, 0x1d4fabb } + }, + { + { 0xaef599e, 0x1f11d45, 0xb09c58a, 0x8d91243, 0xd08c3c3, 0xd2eec7b, + 0x3b02793, 0x5a6039b, 0x8fb2c00, 0xb27fed5, 0xe8acf5e, 0xb5de44d, + 0x6e6c698, 0x2c3e0cd, 0x777180d, 0x2f96ed4 }, + { 0x96d0e36, 0x67de8bf, 0xc9b6d65, 0xd36a2b6, 0x637d59c, 0x8df5d37, + 0xc8d9878, 0x951899f, 0xb13fcf8, 0x0fa090d, 0x1f5c7b4, 0xa527081, + 0x513a37a, 0x56a6560, 0x14dc1fe, 0xc6f5530 } + }, + { + { 0x94945d6, 0x7f6def7, 0x8cc8832, 0x2f52fe3, 0xa812ff5, 0x0228ad9, + 0xbb8478a, 0xcd282e5, 0xbe91b07, 0xa0bc9af, 0x11165e2, 0x0360cdc, + 0x7b857e4, 0xb5240fd, 0xfa36b08, 0x67f1665 }, + { 0xad2c93f, 0x84ce588, 0xe8ff4c0, 0x94db722, 0x489c8a3, 0xad2edbb, + 0x7e5f278, 0x6b2d5b8, 0xd1d0798, 0x0265e58, 0x4c5589e, 0xd2c9f26, + 0x4e4074d, 0xde81f09, 0x303089f, 0xc539595 } + }, +}, +{ + { + { 0x83e882c, 0x183492f, 0xb5e6c12, 0x4d58203, 0xefec20b, 0x1ac96c3, + 0xe1cd15e, 0xabd5a5b, 0xcbbb14b, 0x7e1e242, 0xd0543b3, 0x9f03f45, + 0xd678158, 0xc94bc47, 0xa446cad, 0x7917be0 }, + { 0x9b37394, 0x53f2be2, 0x064cc76, 0x0cb0a6c, 0xfba3da3, 0x3a857bc, + 0x80fcb49, 0xac86bc5, 0x30ab146, 0x9d5336e, 0x5bc1270, 0xafb093d, + 0xe5c3b6e, 0x996689d, 0xea076ba, 0x55189fa } + }, + { + { 0x646ce03, 0x99ef986, 0x30e6100, 0xa155f81, 0x29b6b07, 0x75bef17, + 0x1de077b, 0xc46f08e, 0x7ed0526, 0xf52fdc5, 0x61a299a, 0xe09d989, + 0x7b8e93a, 0x9527329, 0x0acd185, 0x11255b5 }, + { 0x4a6acdd, 0x57919db, 0x4451d74, 0x708a578, 0x283f7b3, 0x5b0bd01, + 0xc3d9260, 0xe82f40c, 0x82bbdc2, 0x2ab96ec, 0xc164d87, 0x921f680, + 0xc17a6a9, 0xf0f7883, 0x382a001, 0xc366478 } + }, + { + { 0x2e40791, 0x5c9aa07, 0xa0776bf, 0xf0b72d6, 0xeaa50dc, 0x445f9b2, + 0x6bda47f, 0xa929fa9, 0x3bbfc49, 0x539dc71, 0x006a78b, 0x4f16dd0, + 0xeef39c7, 0x331ba3d, 0xc34157c, 0xbfa0a24 }, + { 0x6a3b482, 0x0220beb, 0x6c43885, 0x3164d4d, 0xacdea23, 0xa03bb5d, + 0x9d8f450, 0xd6b8b5a, 0xbd208fe, 0xd218e65, 0x35c476f, 0x43948ed, + 0x0a2ed2b, 0x29a0dd8, 0x25295b7, 0xa6ccf33 } + }, + { + { 0xac38939, 0xf68f15f, 0xf8010c1, 0xb3dd5a2, 0xa35f141, 0xf7ac290, + 0x7388574, 0xdc8f3b2, 0xe95fed2, 0x7ec3de1, 0x257ac7d, 0xc625451, + 0x664e55a, 0x66fc33e, 0x4832ba5, 0xd3968d3 }, + { 0xc026448, 0x980291b, 0x24da4a5, 0xfcb2125, 0x827a360, 0xbca7df4, + 0x85ca63b, 0xfcc395c, 0x8e9f733, 0xcf566ec, 0xd465f70, 0x835ee9b, + 0x372f916, 0xe66d111, 0x04d9211, 0xc066cf9 } + }, + { + { 0x8b48818, 0xb9763a3, 0x4288f96, 0xa6d23cc, 0xed3a229, 0xe27fcf5, + 0xabaff00, 0x6aebf9c, 0x8131cd1, 0xf337503, 0xffabd58, 0x13ad41d, + 0x861c83b, 0x1bee6af, 0x9c142e7, 0x274fe96 }, + { 0x9b84b5b, 0x70ebcc9, 0x8191cfc, 0xe1a57d7, 0xcbf00b8, 0x46ccd06, + 0xefe402d, 0xc233e8e, 0xbeebeb3, 0xb4ab215, 0xbd14e7b, 0xb7424ea, + 0xa679578, 0x351259a, 0x471d684, 0x6d6d01e } + }, + { + { 0x815ae38, 0x755c465, 0x611db56, 0xadc3e85, 0x188dd50, 0x633999b, + 0xc12d907, 0xfdf7509, 0x238b6af, 0x25bcfde, 0x397f5e7, 0x50d705d, + 0x944c974, 0xb65f60b, 0x27ac325, 0x8867fc3 }, + { 0x3763eff, 0x2edc441, 0x341fb63, 0x892c0b3, 0xb3a7f28, 0xb34b83a, + 0x15c2f18, 0x9aa106d, 0x1bb2277, 0x720bbc6, 0x5cfaefd, 0x637f72a, + 0xf43e565, 0xf57db6e, 0xb58e772, 0xceb7c67 } + }, + { + { 0x6ecc1de, 0x2793da5, 0x38f31b2, 0x4e10974, 0x8781267, 0x4229b4f, + 0xdec04a1, 0xe5d2272, 0xec17cff, 0x6abb463, 0x0cbb048, 0x28aaa7e, + 0xd22ef85, 0x41dc081, 0x5e63d0f, 0xcbc361e }, + { 0xad5dbaa, 0xb78aafc, 0xfc1edc3, 0x0111505, 0x92c7bfa, 0x63ed66d, + 0xe468919, 0x2982284, 0xb8c0d8c, 0x30f1f21, 0x2685093, 0xf056747, + 0xf03dd0f, 0x0e085b6, 0x5581e66, 0xa8c8db8 } + }, + { + { 0x264ad0c, 0x42009a6, 0x593bef4, 0x13bf2b8, 0x5d4e8b1, 0x1d11190, + 0xef7bddc, 0xfe3e940, 0x624e62c, 0xa012275, 0x1d6d3cc, 0xcb65924, + 0xedb7ab6, 0xc7bcc70, 0xb750b1c, 0xff9fafb }, + { 0x7fea84b, 0xf65df29, 0x90b0e02, 0x17c84a8, 0x301e821, 0xa92a859, + 0xfb480d1, 0xbee8cb2, 0x59c604e, 0x7010b8c, 0xe803c43, 0x47bf3f4, + 0x47b3fff, 0xd645142, 0x9f0da13, 0xc4c5dcb } + }, +}, +{ + { + { 0xb5253b3, 0x8af700c, 0x206957a, 0x31ca605, 0x3eafdcd, 0x2574439, + 0xd3ae15e, 0x2ba5ae1, 0x5b82579, 0x710b738, 0x112b95a, 0x145ab57, + 0x38c55c5, 0x4b133a0, 0x2a16fef, 0xf7559c9 }, + { 0xd9ba896, 0x70c3e68, 0xc33d07a, 0x475dd32, 0x3a41e40, 0xe084e47, + 0xfd2e706, 0xddc9382, 0x79510bd, 0x34b7275, 0xa5f901e, 0x5e78a69, + 0xdcfb823, 0x429dfd7, 0x014f0a3, 0x1d9dc18 } + }, + { + { 0xaf403d7, 0x364fcdf, 0xb7d7b34, 0xd9ea4ff, 0xcbb1dac, 0x21a3426, + 0x143b4f5, 0xfa51052, 0x6df2409, 0x2bca073, 0x8ad7285, 0x7e6985a, + 0x4aaa27f, 0x3a1a9d0, 0x9fc0c6c, 0x1a815e1 }, + { 0xbb65bb3, 0xfab6147, 0x33ced0b, 0xa36dc0d, 0x2062d78, 0x26a8859, + 0x28a5fb7, 0x3438617, 0x4ebb1ad, 0xe82da25, 0xd05aa11, 0x70f5071, + 0xadaac48, 0x0b7f847, 0x93cb269, 0xeb812bc } + }, + { + { 0xf7caccc, 0xcb317cc, 0xcf85098, 0xd3410d9, 0x7f078d7, 0xca68c8d, + 0xb782efc, 0xfe9e812, 0x5f544b5, 0x32e7c0f, 0x3a7b7f2, 0x44fe95a, + 0xe91327b, 0xf4f1543, 0x76645ed, 0x27d118d }, + { 0xd7abc2c, 0x690547c, 0xb53c8af, 0xf64680f, 0x79ea989, 0xbe0cbe0, + 0xa91af28, 0x6cf0cce, 0x9daa2f9, 0xa3b85a2, 0x91faed0, 0xd4b663c, + 0xa8b20ba, 0x782c7b7, 0xb8d98ce, 0xf494faf } + }, + { + { 0x002f55a, 0x080c0d7, 0x2d6d9dd, 0xf4f8f14, 0x382f025, 0xb326229, + 0xad28c20, 0x58fd0b5, 0x8d06a15, 0x704b992, 0x7fbd8e4, 0xf4545d9, + 0xed55581, 0xc32fa63, 0x01ac0fd, 0x3ab7936 }, + { 0x6099fd1, 0x13ece52, 0x9c79178, 0x776dba8, 0xce26c45, 0x8d28212, + 0x60d739c, 0x09fddaf, 0xa84826e, 0xf9931ed, 0xb29439e, 0x6e73d90, + 0x9095e61, 0x94cfefc, 0x802f474, 0x3050d16 } + }, + { + { 0x9f6394b, 0x0898f8f, 0x88b0e91, 0x48b8cea, 0x4c1b362, 0x4bc9925, + 0x827d9ec, 0xe3fccb4, 0xd950d6a, 0x5d4cf9a, 0x39b5b38, 0xa16f1ef, + 0x620f288, 0x3c76d1d, 0xe119390, 0x9fdd059 }, + { 0xfb5edf8, 0x7b5de9e, 0x769d14e, 0x3e290b9, 0x6bd10b5, 0x4df3a91, + 0x82f8f7b, 0xae99bca, 0xc9524af, 0x5481d5d, 0x69504f1, 0xf112e4f, + 0x51931ec, 0xb048f09, 0x18f51b1, 0xbff876a } + }, + { + { 0x46c1c37, 0x932e2a7, 0x9aea4c1, 0x903ad52, 0x8f161f2, 0x717ac91, + 0xf425e2a, 0xa57d197, 0x7f39e0e, 0xae89dac, 0xbaa2a58, 0x91655c0, + 0x54836dd, 0xe3dc286, 0xa9ec9e6, 0xb5f0baa }, + { 0xbdbda04, 0xf7c4662, 0x51059c0, 0xbe5393b, 0xdd95b0f, 0xb16d552, + 0x1b3bd96, 0xde495b3, 0xc0206c5, 0xb2a6e02, 0x014d3a9, 0x045cc09, + 0x2a2f490, 0xf66a315, 0xc5dea05, 0x208c108 } + }, + { + { 0x65237ea, 0x6e38b68, 0x9f27fc6, 0x93a1303, 0xa95068a, 0x9a6d510, + 0xe7c9e54, 0x6fbf216, 0x571ac1d, 0x7824290, 0x91c2a0c, 0x8cb23ba, + 0xc7e434d, 0x611202e, 0x76058b4, 0x8f901bf }, + { 0x0849588, 0xef0ac05, 0xdd31804, 0xe0d2dde, 0xeb2ca81, 0xaf5417c, + 0x5d1a509, 0x420ac06, 0x9683bb6, 0x46e345e, 0xf613f7f, 0x6daf635, + 0x48a9576, 0xc9e8291, 0x176d147, 0x5f9f1d1 } + }, + { + { 0x77e9709, 0xd24ae1d, 0x0047b8a, 0x77751dc, 0xc6a1593, 0xe325334, + 0x671f86a, 0x9baf962, 0xc29a15e, 0x425af6a, 0x2796e33, 0x3108600, + 0xfc253a5, 0xb6ea78c, 0xafae0ea, 0x4c733e0 }, + { 0x97c99b9, 0x4b7443a, 0x50203a6, 0xc14e9e4, 0x52680ba, 0xd1bb515, + 0xd55533a, 0xa56a3ef, 0x169e1a0, 0xa66e38c, 0xeed7da0, 0xb3e4df9, + 0xddce3d9, 0x022c937, 0xf6e36b4, 0x8552089 } + }, +}, +{ + { + { 0xf5cc82e, 0x8e4bf95, 0xc3ed6c9, 0x2ad80c3, 0xc9045e1, 0xf2e5b2c, + 0x59b06d4, 0x42c9065, 0x7b43b84, 0xc1f7379, 0x72d7992, 0x1710dbf, + 0x767b41c, 0xe98cf47, 0x7bfb9e9, 0xe713fce }, + { 0x9fa5134, 0x9f54ae9, 0xde40d0e, 0x3002fd8, 0x9311334, 0xdc282b7, + 0xbfeb360, 0x5519810, 0x0f96ffe, 0x31539c7, 0xd27777b, 0x04eacc0, + 0x8ff5053, 0x5982410, 0x32b67ad, 0x5982366 } + }, + { + { 0x6bea5c2, 0x6eb4554, 0xd509a33, 0x82cfae0, 0x394bb59, 0x6a69bd8, + 0x5770ee1, 0x1880d8d, 0x7dacf9e, 0x6351844, 0xf02b891, 0x5b1ecc5, + 0xb6c9a5a, 0xeb7d900, 0x8897da8, 0xdab8a76 }, + { 0x98851a6, 0x28c7be5, 0x4d73c3b, 0x0101d4f, 0x5084996, 0x3c2569c, + 0x280bde0, 0xb9bc911, 0xcd0d4f9, 0x513a22a, 0x2a15f3b, 0xdf2986d, + 0x2aa4943, 0x231c28f, 0x0333870, 0x29623ad } + }, + { + { 0x4084416, 0x2ceb178, 0x49516cd, 0x924cf1c, 0x4be856f, 0x76536c0, + 0x47a265b, 0x11b59cd, 0x4999494, 0x720dc84, 0x007b795, 0x910f794, + 0x2d3df83, 0x8434e14, 0xbd478d3, 0x8f53878 }, + { 0xaeb9c2f, 0xd9b072e, 0xfd8a29f, 0x16f87ea, 0x2fd0de1, 0x8c42f9b, + 0x0e816ef, 0x916721e, 0x18bde37, 0x2ecb470, 0x2375da2, 0xcde3b7a, + 0xef94281, 0x30d0657, 0x5cd7af8, 0x5105456 } + }, + { + { 0x4bdced3, 0x7230b33, 0x0838569, 0x0c6a3e1, 0xe3493b8, 0xf19c9ec, + 0x0d97c57, 0xf275927, 0x0c862eb, 0xf14181e, 0x32c72bc, 0xfd3bac1, + 0xf3be362, 0x620563f, 0x47283b7, 0x672ccaf }, + { 0x2b7bf16, 0x191e3fa, 0x520dad7, 0xf838633, 0x3629d87, 0xd3dde55, + 0xaf86ebe, 0x14d8836, 0x221b2ce, 0x3db7dfb, 0x0aed72a, 0x3872abb, + 0x8c665b7, 0xb60de52, 0x44982cb, 0x89c2596 } + }, + { + { 0x4dbba25, 0x799a2de, 0xa42715e, 0xd818aae, 0xf55c362, 0xbc88f4d, + 0x713c9ae, 0x142a163, 0xfbfb33f, 0x411e8ee, 0x6bb684a, 0x34b4629, + 0xdc81817, 0x4344bec, 0x17f9d46, 0xcc9573d }, + { 0xff38a7d, 0xf85f8bc, 0x0caf117, 0xa14bf73, 0x4ba6429, 0x126874f, + 0xaa5db97, 0xcc9bf22, 0x6aba827, 0x62b56df, 0x9c9772a, 0xfee1cb8, + 0x177e541, 0xe36838f, 0xadd438f, 0x698815d } + }, + { + { 0x38ed1ad, 0xc9fd894, 0x7b6a601, 0x73cd79d, 0x05e8d20, 0x2210e62, + 0x3592af5, 0x72384ac, 0x763d07e, 0x5ccc079, 0xa5f79eb, 0x2f31a4a, + 0x2945a95, 0x693f4ed, 0x8056fdc, 0xc712017 }, + { 0xdf4b09a, 0x361ecd2, 0xb7d929a, 0xa5644ea, 0x3fabe9a, 0x34abc0b, + 0xe942a8c, 0x1a2473c, 0x6454bc3, 0xe00c924, 0xdff7366, 0xab324bc, + 0x21b8f99, 0xe1412f1, 0xe33551e, 0x970b572 } + }, + { + { 0xbd0a6b5, 0x6ca4cac, 0x921d654, 0x5584787, 0xc809bda, 0x18e5253, + 0xf0cbe5e, 0x01b32c3, 0x0f987dd, 0xb9aa754, 0x6dfa4db, 0x628f4bb, + 0x891890b, 0x0255f0b, 0x874e590, 0x25b7df4 }, + { 0x8ed5f95, 0xbded318, 0xca93023, 0x9dc428d, 0xbccf520, 0xc68f25a, + 0xe616e6c, 0xc4f3764, 0xa1d9993, 0xd9a57f1, 0x533431b, 0xd1964a5, + 0x02ab6d0, 0x06cd77f, 0x03e52e0, 0xa660791 } + }, + { + { 0x5f72700, 0xab08864, 0x0a1a44e, 0xf77b2ff, 0xc2a24b5, 0x43ebdd8, + 0x4f564d7, 0xa6d6711, 0xf414160, 0x495df63, 0x76f6de6, 0xf5bacd7, + 0x7c2b43d, 0x3011aff, 0x3241928, 0xbb1e64c }, + { 0x5034073, 0xf70c572, 0x68f1e97, 0x891c62a, 0xb22e374, 0xed8eb2e, + 0x7dbcc2f, 0xd3a53e9, 0xdc8f220, 0x1d06281, 0xace4393, 0x9eef48f, + 0xd2abecd, 0x96014f5, 0x2653ceb, 0x1da7e09 } + }, +}, +{ + { + { 0xd00bc94, 0x7593318, 0xc7262a2, 0x586f3c6, 0x958ad31, 0xea68f52, + 0xd4e8bed, 0x6707fcc, 0xcb3f9ce, 0xb7e35d6, 0xf4b1be8, 0x2cbb6f7, + 0x7b41aee, 0xa535268, 0xf7b39b8, 0x1d77845 }, + { 0xeaf9554, 0xb1f3995, 0xfe9e7d4, 0x3250f70, 0xa00c23c, 0x62e5d1b, + 0xc10e3bf, 0x5e422f5, 0xc25cec4, 0x7a18039, 0x7cc4d5b, 0xb4e66a1, + 0x36d0e0c, 0xad7c5f6, 0xa4cf347, 0x9f40b12 } + }, + { + { 0x51e3696, 0x697f882, 0xab0a648, 0xc89bc40, 0x9785804, 0x8f261a5, + 0xb51a2bd, 0x4c7f900, 0x8a2dfcf, 0xd00e7af, 0xb642aeb, 0xf9c534d, + 0xb63df0e, 0xea2a79f, 0xf2f64a4, 0x392a69a }, + { 0xc331b6c, 0x0c0f01c, 0x6a5edb5, 0x414bf2e, 0x5068391, 0xfe5ed81, + 0x62fbc34, 0x0a8078d, 0x54bca98, 0x78a4382, 0x3d727c7, 0xf7a49ae, + 0xab4dffe, 0x96c1de1, 0x3b9440a, 0x45901f7 } + }, + { + { 0xacfe46e, 0x3f1189f, 0x4467443, 0xdca6f46, 0x2eb5bcf, 0xac38542, + 0x906bf72, 0xb02dce9, 0xfe1d454, 0xdd8cdac, 0x65f7218, 0xc26f04c, + 0x6ea145d, 0xb474859, 0x5bdb315, 0xc53dc6b }, + { 0x9ad7197, 0xbe5be74, 0x18b5ecc, 0x627e919, 0x9ea405d, 0x57c889c, + 0x1a5360b, 0x2e5650c, 0x1b30b27, 0x42290df, 0x5242687, 0x4a07157, + 0xd379133, 0x553ed1f, 0x01db019, 0xb9d7a07 } + }, + { + { 0x56597dc, 0xcfe551c, 0x925ebd6, 0x81af92a, 0xf4e8d57, 0x83efe16, + 0x1f640d3, 0x61bb431, 0x78b414a, 0xf80440f, 0x6c9e3b4, 0x72f3c63, + 0x6a03c66, 0xb55f43a, 0xe417037, 0x47a9ded }, + { 0xdbb612b, 0x1a7e287, 0xdbb9220, 0x895c3c7, 0x6c04764, 0xd50c86e, + 0x53cf7ca, 0xed52698, 0xf74af55, 0xc78d799, 0xb969ff2, 0xb2ba0f2, + 0x1c6530b, 0x06d4815, 0x165a575, 0x764a1fe } + }, + { + { 0xc1b5ece, 0x4383a3b, 0x54ff148, 0x0563c88, 0x5af796e, 0x9a45279, + 0x88e9953, 0xffba7c0, 0xb6a3001, 0xfe9fb5e, 0x25b6b19, 0x7950988, + 0xd81be5e, 0x67c899a, 0x2f9d29b, 0xc89ac8d }, + { 0x29ab8f7, 0x7c76ba3, 0x6e40f74, 0xb2a18c9, 0x3864d9b, 0x1b5056e, + 0x9b582b8, 0xdfa503d, 0x7c9c68e, 0xfb03519, 0x6b3c22b, 0xdc50131, + 0xa6c96ff, 0x38ab231, 0x8cb1c10, 0x4ea527c } + }, + { + { 0xc05b4ed, 0xd632f20, 0xb2a032d, 0xe0199fa, 0x26812d7, 0x3732956, + 0x013df13, 0x2aed855, 0x39f96ac, 0x92ca24b, 0xbb9751a, 0x620273d, + 0xf7437a1, 0x5d0d21e, 0x077de56, 0x9de2a43 }, + { 0x11a4674, 0x0569b12, 0x89c3989, 0xfc3923e, 0x2c5c770, 0x3d12704, + 0x84e8c37, 0x0072b90, 0xac39f9a, 0x7178d4d, 0x778d345, 0x5f8292f, + 0x77c7307, 0x9e5bf0f, 0xc3a20f5, 0x7691610 } + }, + { + { 0x705fe96, 0x7c4ead5, 0xc8e464c, 0x377ec35, 0x7689954, 0x3e5b990, + 0xa2d31ea, 0xc0f6949, 0xc580671, 0x839d395, 0xb215b09, 0x2f347a6, + 0x683df83, 0xfdcfa33, 0x6af39a8, 0x6e12cc2 }, + { 0x13a3bd2, 0xae46ec8, 0x59366f8, 0x03a7d3b, 0xb87aed4, 0xe2029d5, + 0xfe1b83d, 0xbdc4e43, 0xdb8a1a8, 0x768437c, 0xea0dd7f, 0xe47acc3, + 0x62a0af4, 0x550e0cc, 0x1a20962, 0xcaf2cbc } + }, + { + { 0xf28a78f, 0x5a784f7, 0x07e9724, 0x952a9b5, 0x1bab7a3, 0x8ac5e41, + 0xb7bc1e1, 0x1251e3f, 0xdc15e22, 0xe360f82, 0x95213f5, 0x3ac72da, + 0x4dcd47b, 0x65ee9ba, 0x3af5952, 0xdfeab7b }, + { 0x26fd3c6, 0x34c5c80, 0xf3ac7ee, 0xd977b08, 0x7dba2f6, 0x003bd01, + 0xac98c8d, 0xcfc5cf8, 0x0e46922, 0x05eb604, 0xfaa9352, 0xc248b17, + 0x395c7a7, 0xfa41c0f, 0xb71ee44, 0x29931d4 } + }, +}, +{ + { + { 0x07861c5, 0xac087bb, 0x5ae8240, 0x3bd37db, 0xf94518f, 0x94c68ec, + 0xff88a5b, 0xd32a378, 0x9b441d1, 0x42c8aaf, 0xfc07f12, 0x089db70, + 0xd3d4455, 0x211c386, 0x546b158, 0x1db9af7 }, + { 0x51bc927, 0xdfd1b65, 0x0733df4, 0x69c0493, 0x2aeb586, 0xdc72cd4, + 0x823aa13, 0xeebdace, 0x56ad643, 0x51b3b3c, 0xd4e0426, 0xb983a99, + 0x69c4ecc, 0xa1e5b6c, 0x45e6668, 0x37cd382 } + }, + { + { 0x9f73aea, 0x158ce6d, 0x14ff475, 0x36a7749, 0xdc0b018, 0x0d4e424, + 0x3946f09, 0xc2c4448, 0xfacda62, 0x7a7de3f, 0xb486709, 0x49a19e6, + 0xdb61da7, 0x65094d8, 0x8f5ee87, 0x09edfd9 }, + { 0xb37226d, 0xe460fcf, 0x69bf470, 0x3b9d039, 0x247ca22, 0x3d4d511, + 0xc782cb1, 0xc7248d6, 0x00ad293, 0x91189a0, 0xe8abe75, 0x1244942, + 0xbf52cdb, 0x9f88d12, 0xbbbcadf, 0x368463e } + }, + { + { 0x8074f45, 0x419e4b3, 0x0771c83, 0xd3f8e2e, 0x2e68d34, 0xd2743b4, + 0xb116a00, 0xc68b7db, 0xd84cc37, 0xfad2cf7, 0xb7a0f4d, 0xcfd27c0, + 0x190e587, 0x3b9e23f, 0x751ca9e, 0x7bab499 }, + { 0xa8f12ee, 0x3270861, 0x31b36d5, 0xee1f38d, 0xe4c0eed, 0x748bb31, + 0x110ebad, 0x9be5c9b, 0xc8b6cb6, 0x728660b, 0x93d914a, 0x7bc9df7, + 0xc88c859, 0x73a4f2c, 0xb4e7f0e, 0xbe4a2fd } + }, + { + { 0xa450e77, 0xe566ff8, 0x6a13aba, 0xb0b4006, 0xcd7dc90, 0x483a510, + 0x5fa9ccc, 0xb1a2013, 0xa80e67c, 0xeb0b631, 0x020801a, 0x7c34e1f, + 0xf4e447c, 0x0257dc8, 0x74c6f0f, 0x7abe7d1 }, + { 0xb19a576, 0xf115a3a, 0x064ca0e, 0x8f0474a, 0x351f99b, 0x999bb6b, + 0x773edc3, 0x855254b, 0x427d717, 0x49f6c2f, 0x2e0cef2, 0x9f68253, + 0x2ee34f5, 0x1fe126c, 0x80150f7, 0x1ec2cae } + }, + { + { 0xc005b7a, 0x862c5af, 0xec4ef17, 0x61adea7, 0x007b446, 0xf885fd3, + 0x9b0e30e, 0x25c129d, 0xfeec7e0, 0xbc10f25, 0xdf79ee1, 0x3901ac4, + 0xfe9e19f, 0xad49db7, 0x360d050, 0xc8624d9 }, + { 0xbf3260b, 0xc74a576, 0x8c010c2, 0xbde8024, 0x09b6977, 0xf155329, + 0xd52dcf8, 0x6a5a82e, 0x29b9dfc, 0x4fbf59d, 0xc7b730c, 0x337d049, + 0x3a89cd4, 0xb3deac6, 0xad2f2eb, 0x1e07595 } + }, + { + { 0x3b7c84e, 0xa0b0a4d, 0x8cf2b00, 0xf132c37, 0xeaaa8ec, 0x192814b, + 0x7b4b5df, 0xe7929f9, 0x42d0ab7, 0xf08a68e, 0x7b60cdd, 0x814afb1, + 0x7d9c160, 0x78c348c, 0x44db217, 0xf8a9488 }, + { 0xeaa2578, 0xcdefd88, 0xbd0e260, 0xf717f56, 0x1694d02, 0x7754e13, + 0x181dbd8, 0x1254c14, 0x6e5f312, 0x0dacdd2, 0xcef87bf, 0xb8abdfb, + 0xe74e2ea, 0xb985972, 0x002b424, 0x1717621 } + }, + { + { 0x162df70, 0x92cc75e, 0x18ee849, 0x1e20c06, 0x26aa590, 0xc036b46, + 0x4da5155, 0x31be67e, 0xf7213b0, 0x04911b5, 0xbb2e72e, 0x39261d7, + 0x5c015a3, 0x9e84466, 0x298ae67, 0x2f59fc0 }, + { 0x1701fcc, 0xa3ea7ba, 0x0ebd651, 0x87a5fa9, 0x301d7b1, 0xa607ed4, + 0x3b2e271, 0xbd4ec5f, 0xdc4180f, 0x732a1a2, 0xfeaa8c1, 0xbe15d82, + 0x66f2f3f, 0x1036702, 0x9e79ce8, 0xccfd397 } + }, + { + { 0x70a54ad, 0x82ab835, 0xe3bec75, 0x5c1dee8, 0x54b556b, 0xf583ff4, + 0xf461e60, 0x9220199, 0x87fc4e7, 0xdf61ca8, 0x0776dad, 0x6641fd2, + 0x8edd061, 0x00c6edd, 0x55f7e87, 0xaf9b142 }, + { 0x9bbe3ec, 0x73f15e4, 0xf8bc1fa, 0xdd3b788, 0x1b8ff86, 0xb24cc07, + 0x41be58b, 0x6c260d2, 0x6b10ada, 0xec1c4e3, 0x7fdb985, 0xf6b4209, + 0xd47c212, 0x0d0ac85, 0x07d78d1, 0x967191c } + }, +}, +{ + { + { 0x843d0f3, 0x3b11638, 0xf27f10e, 0x4b89297, 0x863ba2a, 0x477236e, + 0xadd280c, 0x1949622, 0x04da757, 0x7cd5235, 0x79e4ff7, 0xe0e99d2, + 0x537da41, 0xb4ef894, 0x5a24ff1, 0xc55dde4 }, + { 0xb587521, 0x18d8e21, 0x3777833, 0x8010b5d, 0xd3a54c8, 0x4af522d, + 0x4c0ac13, 0x7cd476b, 0x4099f67, 0x4587e61, 0x605ee64, 0x494d0ed, + 0xcc80903, 0x3218ba2, 0x0b2e169, 0x5ff56aa } + }, + { + { 0x3a06c69, 0x51ec94e, 0x5e65c52, 0xa26d7be, 0xd44ee96, 0x156f113, + 0xbf5b9b4, 0x70f0968, 0x5f5332d, 0x9b7e469, 0x6703829, 0x36c295f, + 0xd04f492, 0x1522690, 0x728043b, 0xcf35ca4 }, + { 0x190a7c3, 0xf9ca3e1, 0xf971b07, 0x53d2413, 0x9c48b49, 0xae59652, + 0xfefff5c, 0x74672b8, 0xa7643b0, 0x0a3018b, 0x3e9b0a8, 0x51919e8, + 0xc932fb5, 0x89ad33d, 0x643e687, 0x52a4419 } + }, + { + { 0xd2d0acd, 0x7778990, 0x487fdf1, 0x3bdbcce, 0x2b03dd2, 0xdc413ca, + 0x9a2b7d0, 0x278755b, 0x35ddd7f, 0x4ebb8b5, 0xbcbdb92, 0x0465152, + 0x671d051, 0x34f22d6, 0x87192b9, 0x1ba04c7 }, + { 0x83560c1, 0xb1693f4, 0x7d174e9, 0xe08a593, 0x64dc9af, 0x47ffdc4, + 0xce8126c, 0x1123596, 0x1124628, 0x632d95f, 0xfee7c76, 0x66287ab, + 0xc552332, 0xb40fe60, 0xe304e1e, 0x3f11729 } + }, + { + { 0x5030a8c, 0x97a6ea0, 0x09c27b2, 0x6924198, 0xac9dd5d, 0x3308501, + 0xbe73fdc, 0x9fed7fa, 0x0535286, 0xea55544, 0x6c9b832, 0xc7c07ab, + 0xc51b967, 0x178c882, 0x86ee075, 0x6fa0c69 }, + { 0xb8b5c4a, 0xbaa4a15, 0x3130c0a, 0xf83c0ea, 0x2800331, 0xcf8624b, + 0x7ccbcb8, 0xade85cd, 0xf08445d, 0x971d7f6, 0x6a546dc, 0xfd480b7, + 0xc93761c, 0xdc15a38, 0x9d04631, 0xc4c495c } + }, + { + { 0x9470efe, 0x5f4cee8, 0x88d93ad, 0x9fe8961, 0xf4e49ce, 0x24783b3, + 0x52ffb3e, 0x1bc7ed7, 0x6d81e17, 0xa3abe6a, 0x7a333c3, 0xd6bb8b4, + 0x10a3527, 0x3485c0b, 0x31a9d10, 0x7cddc9c }, + { 0xc38ca37, 0x0c78112, 0xdd2f8d8, 0x10e249d, 0xc511911, 0x72c88cc, + 0x29a6c84, 0x4d75b5a, 0xa227b1e, 0xc74b267, 0xf8e35ad, 0x698390c, + 0xe98d230, 0x8f27edf, 0x6bdc7f4, 0xec922f2 } + }, + { + { 0xfc32e11, 0xac34023, 0x47200d1, 0xe0ae2f5, 0xbd98c82, 0xa7c7492, + 0x7b02154, 0x3910b68, 0xe28ab6d, 0x6fdd06c, 0xd98b012, 0xd3a7e49, + 0x9f54207, 0x4c1c82b, 0x45c176f, 0xef5bbe6 }, + { 0xd3e71eb, 0x3d17960, 0x080e70c, 0x90d7e84, 0xbff5d9e, 0x83e6438, + 0x535d85c, 0x1877e1f, 0xfbb69cc, 0x931ed6e, 0x1247848, 0xcf96265, + 0x750da4e, 0x76d618b, 0x717fbf6, 0xc076708 } + }, + { + { 0xeec5126, 0x80a5ac5, 0x3379c80, 0x6d05dd1, 0x2336d32, 0x514b089, + 0x6725137, 0x586c006, 0x574f954, 0xab2365a, 0xac7d356, 0x3c89ea0, + 0x27460ba, 0xf1f2edd, 0xab9870f, 0xf200ddb }, + { 0xa35e885, 0xc8f1b2c, 0xe6e7550, 0x5d22f86, 0x9554615, 0x24b9a40, + 0x616314f, 0xcb41107, 0xc976a11, 0xca752f0, 0xa08291a, 0x3e2f839, + 0xf2c420e, 0x0cff22f, 0x82b9747, 0xafd603e } + }, + { + { 0x810a3da, 0xaddeddc, 0xd3a87bf, 0x78b6c2d, 0xde3a04c, 0xbc7020b, + 0x9b6d045, 0x47ab973, 0x0959358, 0x3b046d6, 0x509ee3e, 0x0f953e7, + 0x69fc61b, 0x803dc86, 0x893c8d4, 0xcceaec0 }, + { 0xb048a45, 0x21f8c40, 0xfcaea8a, 0xb535073, 0x90e360b, 0xe712c35, + 0x8403338, 0x5d0f3f4, 0x7207f2d, 0xe0ea26c, 0xffd9e05, 0x20f6b57, + 0x4788b00, 0xb97d68e, 0x1889cce, 0xb121554 } + }, +}, +{ + { + { 0x464238e, 0x0079817, 0x0d381ca, 0x2110302, 0xd9f01b5, 0x1cc4c6e, + 0x5a131b1, 0x5e35dc5, 0x06944eb, 0xb61848d, 0x29631a3, 0x83792a0, + 0xafca0dd, 0xbe1017f, 0x782fcbb, 0x70aaa01 }, + { 0x99945e7, 0xc63b7a0, 0xc4486c1, 0xe9164ec, 0x885f2c1, 0xb133e35, + 0xc99ae02, 0x186f0d3, 0x2bf53e6, 0x2fca492, 0x48a02bc, 0xf922aa2, + 0x0dd3dca, 0x4fe6490, 0xf6a8207, 0xe8c313f } + }, + { + { 0x97caf1e, 0xc5b3583, 0x922a4b6, 0xa001922, 0xdf07c95, 0x67e36be, + 0xb2f4f34, 0xabaa0ae, 0xdedc333, 0x66dc926, 0x38ec5b3, 0x82021c4, + 0x00ab176, 0x82b4f26, 0x69c45af, 0x1b7c22e }, + { 0x0924ad9, 0x07b0dbe, 0xa407dde, 0xe030936, 0x26ccd06, 0x66e1ce9, + 0xe3505a9, 0xb50c108, 0xda98f51, 0x8b921e1, 0x20cf7c7, 0x449ca1a, + 0xe67d079, 0xadb80c7, 0x834372d, 0x205aa54 } + }, + { + { 0x19bf847, 0x1482b48, 0x5906f0f, 0xd6c16ab, 0x23ad060, 0x323fb17, + 0xc832be7, 0x0346389, 0x2ee45bf, 0xe71b2d8, 0xfb22276, 0x761c37d, + 0x5d70be2, 0xa9b3334, 0x5a0627a, 0x81a0656 }, + { 0x99a6282, 0x3377503, 0xd0436f0, 0xafc8d2e, 0xc53342f, 0x22f71d3, + 0x8939ad3, 0x66ca56d, 0x30e09ba, 0x15a9192, 0xa6de890, 0x261091e, + 0xe78f2d5, 0x609d700, 0x8eaaf78, 0x8aa52ee } + }, + { + { 0xce76258, 0xa398788, 0x494b975, 0x3031d07, 0x043dfe2, 0x4a6d652, + 0xb4401ec, 0xdb1a849, 0xce8bbcc, 0xf81ebbb, 0x16efe9e, 0x937dd47, + 0xef85ecc, 0x9c19350, 0x214273b, 0x260d932 }, + { 0x77bf1a3, 0x1d7e21e, 0xa544eb7, 0x199d689, 0x94ced50, 0x9da5941, + 0x8a0aeaa, 0x71a60be, 0x26d3b51, 0x183a0ae, 0x8df9728, 0x49f176a, + 0x3230674, 0x744376e, 0xe25541c, 0xb2cb21a } + }, + { + { 0x9a0071f, 0x7a72158, 0xe7d2a6b, 0xe19dd29, 0x55113f0, 0x3deb34e, + 0xede573b, 0xef1f8eb, 0x5665e37, 0xa8f7ff9, 0xf2d7777, 0xa2c21ea, + 0x91e2e39, 0x1387afa, 0x7db68f6, 0x04057b9 }, + { 0x1c241f7, 0x8b9d5ae, 0x8e75993, 0x689588a, 0x5c0e2d4, 0x79585b4, + 0x7b64974, 0xba1ef16, 0x1c08a75, 0x72685bc, 0xd572edd, 0xf0a5814, + 0x5ab0e70, 0x71464a3, 0x339aea7, 0xc93c92b } + }, + { + { 0x5b8a87d, 0x1917e2a, 0x3a82756, 0xea5db76, 0x6420e2b, 0x5bba2fb, + 0x019372a, 0x5cc0501, 0xccc5efd, 0xb1ef8be, 0xf49c57d, 0xaf06393, + 0x87a0bc4, 0x3ab1adf, 0x34fe6b6, 0x2ee4cca }, + { 0x6b8ba9b, 0xd160668, 0x7efec13, 0xef137d9, 0x50abb76, 0x7b60465, + 0xf753a00, 0xb40ec2b, 0xeaf8f1d, 0x696ed22, 0xd8ba3d8, 0x398c91f, + 0x37db313, 0x11f2034, 0xfe5079e, 0xe1ec33b } + }, + { + { 0xbdc81f0, 0x8a10c00, 0x6fe8e05, 0x5f39256, 0x14a368e, 0xa595dab, + 0x38cec6b, 0x32b3181, 0x1b00d00, 0xd77afde, 0x4d9923d, 0x3c97928, + 0x76e13dd, 0x78f0e7a, 0xbf75675, 0x5ee8e59 }, + { 0x91b130c, 0x49ec893, 0xa47a441, 0x9416182, 0x76e2ce8, 0x54555b5, + 0x349c40b, 0xcbdd2fd, 0x9392bbe, 0x10ae737, 0x2e2dab0, 0x270b111, + 0xaf293f4, 0x5cb7712, 0xd6095c6, 0xfc22a33 } + }, + { + { 0x0f15878, 0xdcb5bbd, 0xb6bba48, 0xbcf27ad, 0x7b70eba, 0x979913e, + 0x158578a, 0x4c0f34b, 0x6ed6088, 0x53f59a7, 0x75b0fc2, 0x19b3b2c, + 0x0153f3c, 0xad628dc, 0xcec1607, 0x5195a2b }, + { 0xdfe0f7a, 0x95f8b84, 0x152920b, 0x935c6b0, 0x4da1056, 0x25f9e31, + 0xb28c229, 0x4910a94, 0x8ee4d6e, 0x54b03b4, 0x694e3ed, 0xc991fc3, + 0xdbe5709, 0x68c4c26, 0x63d7657, 0xc9cfce4 } + }, +}, +{ + { + { 0xf52a44e, 0x21c9227, 0xe85bfbd, 0x7f105a2, 0x6268fc2, 0x887781f, + 0xa2d7e35, 0x56ee808, 0x2d3930f, 0x14f9de5, 0xdcb561a, 0x4a4e356, + 0x7f95598, 0x8736226, 0x5f34151, 0x211c342 }, + { 0x0eaf9cb, 0x8fcb75b, 0x3d60ce2, 0xcc9edf9, 0xa5fe627, 0x54412c9, + 0x842dd09, 0x6036a72, 0xa6c6099, 0x71ce668, 0x5386764, 0x02b30d7, + 0x6f18e23, 0xb69bed3, 0xd1de9f4, 0x124c9b1 } + }, + { + { 0xe69b531, 0xe8f8d95, 0xaff1049, 0xe1e115e, 0xeddea0c, 0x9087cd1, + 0x7449916, 0x8ed55a5, 0x7808404, 0x8009f54, 0x17fea55, 0x990f216, + 0xfe8ecf9, 0x68ba624, 0x56d1f47, 0x8ac2950 }, + { 0x529dfb0, 0x3257887, 0x244c080, 0xc4a613f, 0x28672fa, 0xabb1ac0, + 0x31eb291, 0xb2915c5, 0x8fababa, 0x6e368ca, 0x1fde498, 0x6b8c259, + 0xf2a548c, 0x67724a1, 0xf90409b, 0x6b3b7e8 } + }, + { + { 0xfae20aa, 0x5415003, 0x85df5ce, 0x95858a9, 0x0ac6bee, 0x42bc987, + 0x39ea1a9, 0x8d843c5, 0xb571043, 0x5de200c, 0x1741a33, 0x084fcd5, + 0x0009d1c, 0xe1ca20c, 0xe957e6d, 0x0271d28 }, + { 0x9e3be55, 0x84cbf80, 0x1c578c6, 0xc804dda, 0x409a93a, 0xea85489, + 0x972021d, 0x64a450a, 0xe681312, 0xc6a2161, 0x65bc111, 0x280bff9, + 0x0f8526f, 0xd358a4b, 0x953a3ab, 0xd967be8 } + }, + { + { 0x7dd066c, 0x4c5e615, 0x634c8d4, 0x37afd33, 0x42d8b87, 0xa3ac88a, + 0x938b607, 0x9681e9b, 0x37fe4c8, 0x7a286ab, 0x2494245, 0xdeee574, + 0x6af75a8, 0x184b9d3, 0x3670c04, 0x20f696a }, + { 0xa39e8b9, 0x1340adf, 0x0850b2e, 0x03c1929, 0x2c0e1ef, 0x435ebd4, + 0x142ee9b, 0x49de18b, 0x3f116f2, 0xb440b27, 0x2214463, 0xd94e9fa, + 0x6311543, 0x1b0ddd3, 0x991ba3c, 0x1ae042a } + }, + { + { 0x5bb47aa, 0xbc322f8, 0x54a5845, 0x9e25625, 0x21115f3, 0x96b65ae, + 0xbb5757b, 0x46fbed4, 0x4c42dce, 0x18aec4f, 0x8d801f0, 0xc59caf6, + 0x1205521, 0x9189463, 0x89feb7a, 0x66bd8e0 }, + { 0xc529ee7, 0x39ebe95, 0x8eadb99, 0x28d8992, 0x6927544, 0x6058c78, + 0xd3808ec, 0x877e7a5, 0x1c52eaf, 0x8f65111, 0xae221cd, 0xfb59812, + 0xf890391, 0x22289c6, 0x4966e92, 0xa97695b } + }, + { + { 0x6ff10f0, 0xf0a9122, 0xa2a65c8, 0x49a931b, 0xb1d3cb0, 0x3fcebbc, + 0xca9685f, 0x70eb79b, 0xab38cb6, 0x82520b5, 0x76304c3, 0xccf991b, + 0xaf8b07c, 0x575aab1, 0x5ed5efb, 0xec8166a }, + { 0xc8689b1, 0xddc5698, 0xb2e78d7, 0x227c949, 0x8e07d91, 0x6132321, + 0x22cfd62, 0x658a11d, 0x004dd5f, 0x908fb44, 0x90d21b1, 0xe3d14f0, + 0xa6a1639, 0x6f3db9d, 0x333a525, 0x09d86c0 } + }, + { + { 0x6f043f7, 0xd83eaf0, 0xb52d5f6, 0x88ab648, 0x57144d7, 0x67c664d, + 0xeafc8b5, 0x55d7644, 0xcceb291, 0x1c89f20, 0x831ac47, 0x51aec7b, + 0x6148854, 0x51172fa, 0xf6d7bfe, 0x8fabf7e }, + { 0x477ee27, 0x5910316, 0x20fe61e, 0x5f299dd, 0x42826ab, 0x48079a8, + 0x22591fa, 0xf4a83ba, 0x55482ec, 0x8fac660, 0x6b65b3b, 0x48fd5f1, + 0x9fd9e19, 0x4288a7c, 0x9377894, 0x27db819 } + }, + { + { 0x7fd9dd6, 0x2936ee4, 0x9ec87c6, 0xcce5f0e, 0xdb6e3b4, 0x15a50e3, + 0xad701c8, 0x61df105, 0x1dff1f7, 0x3601add, 0xe8a16e1, 0xb761e06, + 0x1af3f91, 0x4341e02, 0x933fa3f, 0x9156a4a }, + { 0x54bc01d, 0x9dc46ae, 0x64eb910, 0x605577a, 0x5a59a99, 0x22b99f8, + 0x0a229d8, 0xab2dbaf, 0x6599364, 0xa8bfb65, 0xe94ebf0, 0x39ed4a5, + 0x0dbb23e, 0x7b46a1e, 0x8751422, 0x117b195 } + }, +}, +{ + { + { 0x423bddf, 0xd19e8fd, 0x387ef59, 0x9d77042, 0x849590a, 0x315cbdd, + 0x7866c1e, 0xfdc637c, 0x03515a6, 0x72be83d, 0x0376780, 0xd44a4a0, + 0x19e0c2b, 0x3b96131, 0x7b1a689, 0x023aca3 }, + { 0x82282ea, 0xf5f3687, 0x8a8b5c7, 0x4471089, 0x17a3066, 0xcd2f00a, + 0x81ed681, 0x754e112, 0x0bfcefd, 0x9c6c70c, 0x3b6f29b, 0xd6aced0, + 0x2817a2a, 0xe443d56, 0xe7c0012, 0xe590ef4 } + }, + { + { 0x3e62e2a, 0xc2f9676, 0xb2daa26, 0x661816e, 0xdd5f512, 0x3515fd2, + 0x56b6e75, 0xdc36e27, 0x74cc658, 0x0bdde46, 0x00e7644, 0x1029086, + 0x1694a09, 0xfdf0045, 0xceac169, 0x454bcb6 }, + { 0x6481eb6, 0xf4c92ab, 0x09750e7, 0x8b77afa, 0x6362d6d, 0xe6f4231, + 0xf53a3ae, 0x0d45dee, 0xd7dcf98, 0xdac7aac, 0x125ec4a, 0x628cb7f, + 0xaec0320, 0x41e8a20, 0xea2e35b, 0x7418c7e } + }, + { + { 0xdf40519, 0x4d649ab, 0x3525833, 0x8cb22d4, 0x7a5333f, 0x15f6d13, + 0x72c23ee, 0x8c3991b, 0x0cd44a3, 0x248b9a5, 0xccc1a75, 0x6b4c4e0, + 0x15c99a9, 0x3221efb, 0x0a9c504, 0x236d504 }, + { 0xd559100, 0x401c7fb, 0x07c524d, 0xcf0e075, 0x34a9275, 0x39647c0, + 0xf7e8683, 0x2355422, 0xb3ae670, 0x3e0a16e, 0xad61b7f, 0x1c83bcb, + 0x9ca6cbe, 0x491bcb1, 0x5e29458, 0xe668dc4 } + }, + { + { 0x219379e, 0xe44c65b, 0xbb607ee, 0x211381b, 0xb7bc6db, 0xd4c7428, + 0xb76a2e8, 0xba62a03, 0x8bb0b31, 0xe1729c9, 0xc6bbc10, 0x3caeb50, + 0xb0187aa, 0x6c66727, 0xfb90dcf, 0xbf9d2f0 }, + { 0x1184dc6, 0xec69350, 0x2698eb5, 0xd58d2a3, 0xa316b07, 0xb366d8d, + 0x251c017, 0xe1e39bb, 0xadb157f, 0xbe44ba9, 0x8a8b06c, 0xbaa9a9a, + 0x6e473e1, 0xd0f4635, 0x1d681c6, 0xd25a8f6 } + }, + { + { 0xcb102c7, 0xba39d5f, 0xd8aa1eb, 0x66eba21, 0x697fbf4, 0xcc2591a, + 0x2317f54, 0x5adb579, 0xf76c6f9, 0xa01ae71, 0x5042705, 0x2c525de, + 0x4f4479f, 0xc8f4272, 0xe6d7a5b, 0x26ab54a }, + { 0xdc28106, 0xda217b5, 0xeb2ae6a, 0xc7cadea, 0x53ea3b2, 0x0b16094, + 0xcc6111b, 0xcddcc1c, 0xa7a7beb, 0x5c47aff, 0x0e52dab, 0xf9931bd, + 0xc6dcf96, 0x5231835, 0xf27ea4e, 0x7095bde } + }, + { + { 0xc33b4e2, 0xee8adae, 0x63ceb44, 0x3006651, 0x880b086, 0xf1476fb, + 0x9569ce8, 0x0703328, 0x238b595, 0x2cabf9a, 0x26c8158, 0x85017bc, + 0x68d5144, 0x420b5b5, 0xf9c696f, 0xa9f5f1e }, + { 0xc8fec5a, 0x1409c3a, 0x28e9579, 0x541516f, 0x0e1f446, 0x06573f7, + 0x2311b96, 0x3e3c706, 0x3c2ffd8, 0x0033f1a, 0xca6711c, 0x8e808fc, + 0x07aef98, 0x716752d, 0x92525b3, 0x5e53e9a } + }, + { + { 0x5a1c29f, 0xce98a42, 0x3ca6dc9, 0xaa70348, 0xedfa48b, 0xe77d822, + 0x068abca, 0xd2e3455, 0x482cfca, 0xb456e81, 0x7fbfb08, 0xc5aa981, + 0x8243194, 0x8979f25, 0x2cd043d, 0x727f217 }, + { 0xaa53923, 0x7cca616, 0xe9bcb72, 0x387c5ae, 0x37580bb, 0x0173fd4, + 0x75fc0d9, 0xdd7795b, 0x345deae, 0x47d1c37, 0xb0d1c03, 0x2eb5d7f, + 0x958f002, 0xf7a1b92, 0x8f61b67, 0x7365cf4 } + }, + { + { 0x562a5ed, 0x4b22c3b, 0x5c7cd07, 0x711216f, 0x9ba0648, 0x51f72c4, + 0x0de9e6f, 0xc10d093, 0xfda63ba, 0xaca479b, 0xaf532b0, 0x4722a55, + 0x7236f39, 0x8d59eb7, 0x4465c34, 0x5cad874 }, + { 0x722b0c1, 0xa2119e5, 0xf343ea4, 0xb670264, 0xc19f387, 0x6910f02, + 0x0381fba, 0xcfec5bc, 0x52c0a1d, 0x5f5de0d, 0x6378cb6, 0x4e474d5, + 0x27e2ba3, 0x2fc8027, 0x159b541, 0xa215da3 } + }, +}, +{ + { + { 0x8499895, 0xed53585, 0x65c998d, 0xa0aefd5, 0x2d5a561, 0x210d850, + 0xa2cd9d6, 0xc2cc23c, 0xc4d297e, 0x2371d46, 0xd18d441, 0x88b2143, + 0x043993d, 0xbebdad9, 0xad5f28d, 0x6ba91e7 }, + { 0x3a731f4, 0xc2bb3f1, 0x5d0d5c3, 0xd35cfac, 0x35ac427, 0x9950998, + 0x5458adb, 0x8938bb5, 0xab26f3b, 0x0bd738c, 0xa28cd8d, 0x56db3d5, + 0xa1d8b4b, 0x87eb95f, 0xe7f3b4b, 0xd6700ef } + }, + { + { 0xea1e57b, 0x962c920, 0x6dded6d, 0xd3be37e, 0x2c96a73, 0xf499b62, + 0x6c99752, 0x3eaf7b4, 0x025590b, 0xa310c89, 0x721db23, 0x535aa4a, + 0x19714a0, 0x56ab578, 0xd4048c1, 0xeecb4fa }, + { 0x470c466, 0x7b79ec4, 0x1383cee, 0xc4e8f2e, 0x5750c45, 0x0f5d776, + 0x725527d, 0xa3b3bc3, 0x6d00cce, 0x2f5deb6, 0x95a8d81, 0x5d5a0f4, + 0xe02b824, 0x50a442e, 0x2a11628, 0xafb0446 } + }, + { + { 0x0c613de, 0x72b67bc, 0xe6f0b24, 0x0150d4b, 0x8ed289d, 0x847854e, + 0xa320f88, 0xe08292f, 0x29c6160, 0xd5b6da3, 0x4fb9d06, 0x2a48e2d, + 0x2de087c, 0x55d9e41, 0x4f02100, 0x65683b5 }, + { 0xa8886c6, 0x4dc8c2e, 0x20d6114, 0xe966dd2, 0xa57af97, 0x99745eb, + 0xb854725, 0x23a9a71, 0x621a047, 0x8effe05, 0x049a4be, 0xf16d284, + 0x5b0660f, 0x95828c2, 0x56e96b0, 0xd5b69ba } + }, + { + { 0x4ffa0b8, 0x0b5b424, 0x096cc5e, 0x0585b45, 0xf505d37, 0x413e1ae, + 0x0c7ab8d, 0xe5652a3, 0x2990120, 0xab32fb7, 0x3f09368, 0x6b8b16e, + 0xefe128e, 0xbf9fadb, 0x14b7671, 0x85f366b }, + { 0x090608d, 0xcb2f294, 0xac3045f, 0x25e2769, 0x6131904, 0x069c4f0, + 0x329a779, 0x1c57cf1, 0xb7cace7, 0x72fe0d5, 0x0897a45, 0x04d9f43, + 0x359a645, 0xbaf32f6, 0xfa7485a, 0x0fa854f } + }, + { + { 0x5f56f60, 0xae3533c, 0x0ad9360, 0x9773bbb, 0x38fbe6b, 0x769b34a, + 0xffb0c00, 0xb5ba8e9, 0x75472e4, 0xa939318, 0xce5f30f, 0x12cac92, + 0xa9e7dbc, 0x514fc06, 0x58b4734, 0xd7ca865 }, + { 0x65a730b, 0xd101ff3, 0xabe70e9, 0x92da451, 0xef7bf4b, 0xfb5f94a, + 0x1d56c7b, 0x8c3ef4c, 0x8435c10, 0xb085766, 0xe7ed4cc, 0x7fbbbda, + 0x24f372f, 0x1da6eaf, 0x59b8ae3, 0x0ab2c1f } + }, + { + { 0xf10a4b9, 0x63a1a78, 0x0c7e510, 0xbb5278d, 0xf874142, 0x97b224e, + 0xb2517b1, 0x0a9ff52, 0xc5cd920, 0x1b5a485, 0xa1823b9, 0x1a8e2eb, + 0x0e914a8, 0x2b088c0, 0xcf13432, 0xe5ec3ad }, + { 0x6e7e253, 0x0d6ab3e, 0x6f18458, 0x9f0f5cd, 0xf459a6d, 0x839a744, + 0x1eb15f7, 0xb4b4f94, 0xc72cb14, 0xe0313ac, 0xb20472d, 0x58ee933, + 0x872543e, 0x5f73d7a, 0x501f067, 0xb1700c5 } + }, + { + { 0x085f67f, 0xb70428e, 0x43cabe5, 0x5441d51, 0xe0a6055, 0x4d0e8c2, + 0x0882e4f, 0x8d39a08, 0xc1cb39d, 0x615bb32, 0xf7a1642, 0x113f18d, + 0x250681f, 0xbab8cf5, 0x677b72a, 0x3017ba2 }, + { 0x5a3a876, 0xcd2b6e9, 0x2035a69, 0x0476501, 0xefa2ea0, 0x31d6440, + 0x56874d5, 0xde8f8d1, 0x0199d4a, 0xcbc71cd, 0xe7f2170, 0xc546b61, + 0x112c4c3, 0x4e57e4e, 0xd1622ba, 0x58955a8 } + }, + { + { 0x04e2f6f, 0x0064cd7, 0xe0edd38, 0xe9d458d, 0x7e0a5c8, 0xeb1a597, + 0x01fc0a8, 0xe322ece, 0x1032a19, 0x8b9d166, 0xa89de94, 0x3e7b539, + 0x001c754, 0xfa30262, 0xdb588f6, 0xe33de4d }, + { 0x954eb94, 0x4dafbdb, 0x0584c1b, 0xbb43648, 0x5dbe29b, 0x622c93e, + 0xf57b931, 0x968f9e3, 0x0f6453b, 0x98f03be, 0x08f696c, 0xb0ecc7f, + 0xa505335, 0x5af55f4, 0xfb3fa9b, 0x028533e } + }, +}, +{ + { + { 0x27e8d86, 0x3bc8e68, 0x63f105a, 0x4e43b30, 0x4981250, 0x5301b7d, + 0x9f72fa8, 0x8b0a75e, 0x357348c, 0x88f59db, 0xec4208e, 0x5f0ebb1, + 0xc043d3b, 0x4712561, 0xc806b97, 0x9e5ded0 }, + { 0x2121d09, 0xf9bd0a6, 0xe337cd1, 0x1759ecb, 0xe945542, 0xd1acc0e, + 0xbd2f63a, 0x3683feb, 0xda5dfe9, 0x44f1bcc, 0x707f22f, 0xa3606c9, + 0x2d96ca5, 0x45ef064, 0x9022df9, 0xfc3107d } + }, + { + { 0x44be755, 0xe81320b, 0x5c7c761, 0xdf213d5, 0xb4e5db9, 0xf43d2d5, + 0x8dedcd2, 0x3bcfd82, 0xd37a9ec, 0xdf368a6, 0xf475a77, 0xfef20ae, + 0x162c064, 0x22f5894, 0x0142a7d, 0x956bc66 }, + { 0x7daec78, 0xaaa10e2, 0xb6e9a78, 0x3cb9b72, 0xe383f72, 0xa740bad, + 0x7759007, 0xc31b401, 0xa7afc50, 0xdada964, 0xfd3d11f, 0x6bf062c, + 0x5db3679, 0x9470d53, 0x03abf13, 0x3394473 } + }, + { + { 0x46e5d7f, 0x533f440, 0x49048c8, 0xd1793e3, 0x1929b94, 0x59e1150, + 0x8364134, 0xcddbbcb, 0x582774f, 0x795c794, 0xe03081a, 0x114dfc4, + 0xef54042, 0x541ef68, 0x23f18cd, 0x159295b }, + { 0x48a2c8c, 0xfb7e2ba, 0xbb6d116, 0xe2d4572, 0xd750b53, 0x7bb0b22, + 0xd142ee8, 0xc58888c, 0x90c9e2d, 0xd11537a, 0xd02eb9e, 0x77d5858, + 0xd444a79, 0x1fa4c75, 0xd58a68d, 0xf19b2d3 } + }, + { + { 0xeb8b90f, 0x37e5b73, 0x3f2a963, 0x3737f7a, 0x9de35e0, 0x87913fa, + 0x8731edd, 0xec7f992, 0x219491e, 0x6e6259e, 0x4de236c, 0xb2148a0, + 0xfdd309b, 0x89700e8, 0x9f0bf80, 0x9ce51e4 }, + { 0x301f17b, 0xe7ec421, 0x3bc5f4f, 0xa4b570a, 0x1285ee2, 0xc2b1b2a, + 0xc53db73, 0x5e86bc8, 0xf24fa90, 0xb65fcea, 0x08ab024, 0x9e74c56, + 0xf9ed877, 0x5c8003d, 0x4a2cbbc, 0xa632e9e } + }, + { + { 0xc91c8b5, 0x32a4546, 0xc969363, 0xc122b5a, 0x3648b3a, 0xbbbec5e, + 0x25143b0, 0xd5a365e, 0x54157ce, 0xcf3e464, 0xf9bab64, 0x9712f04, + 0x04b4008, 0xc12d43a, 0x2edf1c7, 0x51932d7 }, + { 0xb2f8470, 0xaef1655, 0x6c24ace, 0xaa8e3f3, 0x6b4e761, 0x7da75da, + 0xb90bca2, 0xd371827, 0x0afb45c, 0x84db450, 0xef46b5d, 0xae12045, + 0xd962f98, 0x91639a5, 0x72f2ac0, 0x669cbe6 } + }, + { + { 0x83a4356, 0x851bb31, 0x9a1bf15, 0x7d436bf, 0x120b378, 0x46a3f0e, + 0x3f5b357, 0x9302abc, 0x93fef53, 0x1e06726, 0x5fd2ee9, 0xb12f4a9, + 0x7de9433, 0x94a884c, 0xa6f2874, 0x2645234 }, + { 0xcdb8dfa, 0x6fb56f5, 0x9e0ee4e, 0x4a17dfc, 0x83ab01e, 0xe269d83, + 0xb77c10f, 0xda932da, 0x0321243, 0x463af0c, 0x16fc8a3, 0xbe1d682, + 0x48b39e3, 0x2eae3ea, 0x3b03e7b, 0x9423021 } + }, + { + { 0xb22f28a, 0xaeb507c, 0x49a6b44, 0xa77458b, 0xc03dc17, 0x232ed5a, + 0x9c61ac6, 0x79dfc16, 0xcd71b93, 0x7c48be9, 0xc429cd9, 0x983d68a, + 0x98ae2c8, 0x7709c47, 0xa5df075, 0xe4765c0 }, + { 0x3367f33, 0x23c4deb, 0x37d72a7, 0xbdf2b7e, 0x0af2d26, 0xbaab5c7, + 0xfd026ab, 0xd609f7f, 0x541b039, 0x23b72b2, 0x83be852, 0x8d06bac, + 0xcb23d1c, 0x911d4a9, 0xfb0dbd7, 0xeae815c } + }, + { + { 0x2c33481, 0x487c35c, 0xb6136db, 0xffab636, 0xa3d3aa4, 0xccd4dae, + 0xc3704e0, 0x87149bb, 0xc0e8396, 0x9de8119, 0x58e7ca6, 0xd49357a, + 0x1562d75, 0x6878918, 0x5ab1fad, 0xc745381 }, + { 0x02c9b91, 0x0f15798, 0xb1ddde5, 0x7ffc3f0, 0x6aae50d, 0xa01d5e0, + 0xe279873, 0x6a97e65, 0xb5b1b41, 0x4bcf42f, 0x32f5982, 0x1c6410f, + 0x50701c8, 0xd4f7600, 0x873b90d, 0xff02663 } + }, +}, +{ + { + { 0xe5b2de2, 0xdc53ea2, 0x38acecb, 0x94b352d, 0x0d9d5e5, 0x37d960b, + 0x90bd997, 0xabd868f, 0x35a7376, 0x781668f, 0x10118bf, 0x043d597, + 0xf57928a, 0xd4da719, 0x983e46c, 0x01942f6 }, + { 0x728bd76, 0xab97fc8, 0x4b5c1c5, 0x825956b, 0xc82a104, 0x202809f, + 0xc8e3132, 0xdb63e9c, 0xc2181af, 0xa41c701, 0x43e066a, 0xd280180, + 0x24044ce, 0xc734e41, 0x505193c, 0x4d9ab23 } + }, + { + { 0xf9f0c3f, 0x0bcd42a, 0xb94a218, 0xda21a46, 0x0ffc788, 0xe55243c, + 0x47a5551, 0x318aae6, 0x79af9cb, 0x8c2938b, 0xec1dce5, 0x5d15232, + 0x8ad2e5c, 0x3d310ba, 0x94f792a, 0xd3d9724 }, + { 0x12a9553, 0xdeb4ca1, 0xeb54d9d, 0x2f1ed04, 0x69fb7a1, 0xaa9c9cf, + 0x54dcd3a, 0xeb73c3a, 0xf5f201f, 0xee3eddc, 0xba7d234, 0x35f9e1c, + 0xd2e242f, 0x1d1d04c, 0x0df7515, 0x48df9d8 } + }, + { + { 0xa81dd9a, 0x4ecc77d, 0x03aa015, 0xa6ac4bb, 0xbbc4fed, 0x7645842, + 0x9d6cf52, 0x9ae34cd, 0x5917e0b, 0xf8ff033, 0xc2cc175, 0x7c9da37, + 0xaaacfbe, 0x1e74dcc, 0x7999af8, 0xa8f2df0 }, + { 0x102a466, 0xd06c4ea, 0xae190dd, 0x2156e87, 0xec4a863, 0xc95db8a, + 0x244a6fe, 0x49edffd, 0x904f81e, 0x110fae6, 0xa1cd104, 0xbaa3e50, + 0x0478b65, 0x5bd38a2, 0xdaefbcc, 0x2b57d05 } + }, + { + { 0x86f4534, 0x1ce92ba, 0x414f5e3, 0xb2a8592, 0x9979436, 0xdd7a4c6, + 0x3f0add7, 0x7599aff, 0xe2d4f64, 0xe0ce4d3, 0x401a29f, 0x74475cc, + 0xa2377d9, 0xaef6541, 0x3f917b6, 0x54048f5 }, + { 0x05312ec, 0x1b86b22, 0x31493cb, 0x779ba22, 0xaac9320, 0xc718369, + 0x617fce4, 0xeab01a8, 0xf7187fa, 0x17b1f10, 0xa1aca46, 0xe68eda0, + 0x2586342, 0x61033fe, 0x0b6ca43, 0xfc14e79 } + }, + { + { 0x13d2491, 0x9f22319, 0x7997202, 0x66bdb53, 0x4617f34, 0x0bafb0c, + 0xf3bb7b3, 0x5917831, 0xb45bddb, 0x6feb2a6, 0x0202c19, 0x08662b3, + 0x05852f6, 0x0bc2b57, 0x91818c2, 0x2c00fd4 }, + { 0xda37dac, 0xca7672c, 0x5a30865, 0xfe4c04c, 0x322e92a, 0x5f1399f, + 0x25b1beb, 0xe7d67ea, 0xdce7f68, 0xe08b014, 0xf2f2b3c, 0x24df52a, + 0x750ecd1, 0x2028b23, 0xc810a45, 0x9b25d4b } + }, + { + { 0x7a9d799, 0xa35b715, 0x01f9c99, 0x6da1eb3, 0xe363ba8, 0x33ef91c, + 0xce140da, 0x21c0e2e, 0x158cd84, 0xb0b11bf, 0x93da438, 0x6a87442, + 0x3db585b, 0x924f10d, 0x10c6159, 0xf5ddd73 }, + { 0x6a74c21, 0xb72dcb8, 0xcc8f79f, 0x6d14198, 0x9c5a8d6, 0x99f4b6c, + 0x90e135c, 0x0639688, 0x83f6385, 0x330edb8, 0x9079675, 0xe1a5a6b, + 0xb8f5fe0, 0x6e37fa8, 0x61dca1e, 0x60e2fd9 } + }, + { + { 0x66c395e, 0xc6cb403, 0xb51d0f1, 0x03b21a7, 0xe693181, 0xbc478a5, + 0xc6cff33, 0x0017c2f, 0x39d8d1e, 0x740a5b8, 0x4d9ec6d, 0x3968d66, + 0xb0ef1b0, 0xfd53738, 0x1ed0a04, 0x73ca8fd }, + { 0x75ab371, 0x4ace938, 0xddad7e9, 0xd602936, 0x750bcc2, 0x1f5424a, + 0x68c7a17, 0xfe09b36, 0x58341ec, 0x165f7de, 0x6ce61e5, 0x95b825a, + 0x66c83c4, 0x9d31e19, 0xcc5887b, 0x65b3e08 } + }, + { + { 0x21482d1, 0xd37e932, 0x08b6380, 0x9af6597, 0x7d61e4b, 0x279426a, + 0x80997ad, 0x80dd0ec, 0xd5b76d4, 0x7239b0d, 0xe76c098, 0x92e6c73, + 0xeab3e1d, 0xeeb2321, 0xeb1a910, 0xa69c4a7 }, + { 0x833d9ae, 0x46d6aa7, 0x572b0fe, 0x3ee6957, 0xcdb3d97, 0x44ccbed, + 0xcbea01b, 0x342f29d, 0x8926876, 0x0d518c5, 0x5585d2c, 0xaaabae7, + 0xe008f58, 0xc548c77, 0x21fab2c, 0x819e2fa } + }, +}, +{ + { + { 0xc16e981, 0x468e149, 0x9ddbb7c, 0x286c790, 0xdb7a38a, 0x2a92d47, + 0x8a27cb2, 0xde614e6, 0xe5b0ab6, 0x8dc8822, 0xcf48565, 0x38441ae, + 0x089435b, 0x11ed5c9, 0x82d0d31, 0x2389286 }, + { 0x72f2f31, 0xc6698d4, 0x56d76af, 0x295242c, 0xeba563b, 0x4099205, + 0x3ab7384, 0xae7de5a, 0xd0ed86c, 0xccdf127, 0x965c3c3, 0xb9b6d5b, + 0x2c31ad7, 0xe351a8f, 0xac12f13, 0xa761dd8 } + }, + { + { 0xf171ab7, 0xda115dd, 0x401f93d, 0x2de17b1, 0x40964b4, 0x95019ca, + 0x65ba3c3, 0x169d1f4, 0x0090d08, 0x534a007, 0x82bf410, 0x805c5e2, + 0x65f8d90, 0x15dfe11, 0xca72456, 0x827a416 }, + { 0x33a36c4, 0x5af8884, 0xd8ee604, 0x8bfa54c, 0x9ce290f, 0x08fd141, + 0x287b3a6, 0x2db5e8c, 0x03cdad2, 0xe5be981, 0xbf810b9, 0x155b874, + 0x670f473, 0x2ae42de, 0x7f74657, 0x2218584 } + }, + { + { 0x23ffa43, 0x54b2a50, 0xa24d919, 0xcf87b16, 0x63524e8, 0x1ff5402, + 0x56d1e54, 0x73c94e0, 0x3899fb5, 0x7651552, 0x18723bf, 0x13a7214, + 0x3561517, 0x39afbdd, 0x9f2862e, 0x49b790a }, + { 0x527d2ce, 0xc8c1f4f, 0x7609bb7, 0x1997aec, 0x02a3400, 0x583ad80, + 0x4f79706, 0xac2374e, 0x21b7183, 0xbf1f9a8, 0x6600fe0, 0x06158ab, + 0xbd56751, 0xfcc9b2e, 0xddaaec7, 0xe1de5ac } + }, + { + { 0x788fdab, 0x230baa1, 0x7d04597, 0xf30860a, 0x99f4caa, 0xa2c7ece, + 0x6ad065e, 0xbd39f10, 0x3bef7bd, 0xfd92f5d, 0x96d2203, 0x6069fad, + 0xc4d9e0d, 0xbff38ca, 0x1fda313, 0x419a017 }, + { 0x572f035, 0x5d77fd8, 0xb282b40, 0x5af99f2, 0x23facff, 0x7257d3b, + 0x58c90af, 0xf2ee223, 0x9b6a52a, 0xcc2687d, 0x302430e, 0x140892c, + 0x3ec4f38, 0xa934d5e, 0x3bd18be, 0xc087d7c } + }, + { + { 0xa2c5ed7, 0x7e94138, 0x53610bf, 0xbc8ceef, 0xd86f803, 0xe89356b, + 0x5a55330, 0x9a3a380, 0x11ad648, 0xe894aba, 0xba95918, 0x2e68fba, + 0xfcad344, 0x643e2ba, 0x61640aa, 0x0dd0256 }, + { 0xe25cbdd, 0xc02e479, 0x13a1b3f, 0xd78c4d8, 0xcca9692, 0xa6dae8f, + 0xe5de8a0, 0x3dd91e9, 0x764ea36, 0x78ae0ce, 0x85dbc5e, 0xb4ad999, + 0xe82a169, 0x967ff23, 0xbaee1fc, 0xaeb26ec } + }, + { + { 0x9a6f90c, 0x8c50255, 0x0ea374a, 0x56e7abe, 0x56413b2, 0x675c722, + 0x946753f, 0xd3fc17e, 0xe235f7c, 0x28c4e1f, 0xb028eb0, 0xe209bcd, + 0x489fe88, 0x7d0f93a, 0x063706a, 0xb966a2e }, + { 0x4a30319, 0xb6c228c, 0xca6d674, 0x6868efe, 0x057311a, 0x0610a70, + 0xbad7f89, 0x0808112, 0x1dd6181, 0x2a2462c, 0xb58e88a, 0x52ed9fe, + 0x33821a2, 0xbbff16f, 0x17f882a, 0xda53e96 } + }, + { + { 0x8c30e5d, 0xb6ffca3, 0x5c905f5, 0xa90f991, 0xd753e88, 0x72fb200, + 0x7256c6a, 0xe509d4c, 0xd866500, 0x369e552, 0x33cf8ae, 0xee4b7e0, + 0xefcf6eb, 0x280d954, 0xd557f0e, 0x5b275d3 }, + { 0xb5cecf8, 0xeb17211, 0xbdb2f8d, 0xd6ad50f, 0x35e04b7, 0x2478c7b, + 0xac73bd3, 0x97e7143, 0x4817e24, 0x09d6ede, 0x2c405e1, 0x68fea71, + 0x05f67a1, 0x34adbc9, 0x73edf99, 0xd20ab70 } + }, + { + { 0x569f191, 0xe116a96, 0x4d6e29a, 0xb3f0bce, 0xf51dbab, 0x30b9e1a, + 0x346d276, 0x1dd36f3, 0x0749a27, 0x8315103, 0xab47f70, 0x242f148, + 0x5585681, 0xe8a5bcf, 0x5ed79ba, 0x8b80184 }, + { 0x3894ad1, 0xa4042fd, 0x2b88bc6, 0x82f781d, 0xbe4c397, 0x2d34cac, + 0xdd99c9f, 0x8731aea, 0xef1d382, 0x0f95498, 0xdd0bbc9, 0xcaba2e1, + 0x54064e8, 0x78889e9, 0x61a8ab9, 0x8cd9c97 } + }, +}, +{ + { + { 0xfa0459e, 0xf31f53f, 0x315cd6b, 0xf8742a1, 0xae64e97, 0xabe2f50, + 0x9b9da48, 0xbd78741, 0x51e526e, 0x4521a33, 0xe10ba45, 0xfa05935, + 0xe8f903c, 0x5c947e1, 0x5a754ee, 0x0aa47d1 }, + { 0xd814825, 0xb2849ef, 0x5c9968d, 0x9c2a5d2, 0x04e634c, 0x24dbb26, + 0xdb38194, 0x33f3a4c, 0xc8a2b6b, 0xe04f609, 0xabbbfdb, 0xcaefd8e, + 0x404498b, 0x683119a, 0x8b21cbd, 0x24ab7a9 } + }, + { + { 0x21fa2dd, 0x6f13269, 0xc10a4bc, 0xd79e61c, 0x4bd6d46, 0xac4b3ce, + 0xbd3f37b, 0x52459b6, 0xa396966, 0xce0f0a3, 0xa1ed488, 0x050d1d5, + 0xe0b17fa, 0x1b9c403, 0x04a2e66, 0xee1abd0 }, + { 0x5cf3e3b, 0x97065c3, 0xbe33441, 0x6513d5f, 0x79047ae, 0xcd34634, + 0xfd22df1, 0x45cbb1c, 0x967b17c, 0x7a173ae, 0x2223cda, 0x75f5ba7, + 0xefe0a73, 0xe3d12db, 0xfd7adcf, 0x3b7f94d } + }, + { + { 0xf1e9b7d, 0xd596a13, 0x6734e0c, 0x04f5bdd, 0x8be163a, 0x18b694f, + 0xd959fa3, 0x15620c7, 0x53d2a3b, 0x65fc2c5, 0xc4d36f2, 0xd44a364, + 0x268ceab, 0xc8b421f, 0xbfe2bd4, 0x564139a }, + { 0x19d4633, 0xb524610, 0x6346934, 0x5ab3f88, 0x9819422, 0x96691fe, + 0x8b39b82, 0xdfdec89, 0x97cfb27, 0x84b1c79, 0x4d6d004, 0xe59a98d, + 0x12c350f, 0x5e5d0c6, 0xd415774, 0xb431220 } + }, + { + { 0x6aae0a2, 0x3d0ca73, 0x48c2d8c, 0x7b1991f, 0x5cdae72, 0x00ae856, + 0xbd55128, 0xdbb6ca0, 0x45c82bf, 0x3c2ab2a, 0x79545ca, 0xea5a559, + 0xd5927d0, 0xeba9a26, 0x83257fc, 0xb52e401 }, + { 0xca9650a, 0x55ed517, 0xe3ebff2, 0xbdaa081, 0x9f8831b, 0x8cf7ce4, + 0x6e3b8d3, 0x1d0b5bd, 0xd8fc869, 0xa314a9f, 0xb892bab, 0x07f2079, + 0xa0cc9d9, 0xb700dbf, 0x6dc0a39, 0x7105a08 } + }, + { + { 0x8c7d901, 0x0c7e05d, 0xaf3182b, 0xa7ff681, 0xf9a0d06, 0xb88e3ca, + 0xc343b7f, 0xfe20a12, 0x03251f9, 0x9f02577, 0xc40c5eb, 0xf225ded, + 0xb208ea7, 0x50e0cec, 0xe6eeb65, 0x5b250f0 }, + { 0x4806b6e, 0x807a153, 0xfa94139, 0xded120a, 0x49366fb, 0x237ddc7, + 0x5a34bcb, 0xdd3674e, 0x9c4a61d, 0xef6cdff, 0xb2fb896, 0x036194b, + 0x9528cd9, 0x3865953, 0x6936a52, 0x0723c59 } + }, + { + { 0xe17719d, 0x1f84cd5, 0xc73b394, 0x545939b, 0x83e84e7, 0xefbf3c5, + 0xf77fd66, 0x6cc46f1, 0x1383ab8, 0xa629f59, 0xcd35cd2, 0x9177ffa, + 0x9dd411b, 0x039187f, 0x7b7eea8, 0xa9cf1cf }, + { 0xac47e5d, 0xa3b105a, 0xd0a9da4, 0xa755bea, 0x73da15e, 0x50cfbae, + 0x60b628c, 0x9456cbc, 0x9b7a910, 0x7ffc362, 0xcd6d6a4, 0x30b5924, + 0x0b04ab6, 0x198629f, 0x624dea9, 0xc74609c } + }, + { + { 0xaf12fa6, 0x27d4d77, 0x690aeb2, 0xdd8a216, 0xfe24417, 0xe48fc02, + 0x720e17e, 0x1970403, 0xce37b42, 0x95013fd, 0xde4bd9b, 0x06817d2, + 0x63d0ba2, 0xc5863e7, 0xa556f5d, 0xa1bafc0 }, + { 0x410a78a, 0xf28ec7b, 0x0a01a63, 0x0dcac42, 0xb5bce11, 0xfcd3fa4, + 0xd278b89, 0x054d7e5, 0x5ce49e3, 0x5195db8, 0x2c73d96, 0x4c0b167, + 0x20a1bdb, 0xd943077, 0x59c77a7, 0x66fa8b3 } + }, + { + { 0xd7462fe, 0xb9e93ae, 0x18dde4f, 0xbfe54b2, 0x3dbb08e, 0xaabb528, + 0x0e5fc45, 0x8c36702, 0x8e69be3, 0x3502888, 0xc12a11d, 0x6d2efc1, + 0xf265e30, 0xfce5ceb, 0x5742c7e, 0x58c8bb3 }, + { 0xccf7fa0, 0x32e89dc, 0xdd020a4, 0xa811f33, 0x5129fe5, 0xa10d620, + 0xe4ed29b, 0x3841c88, 0xd8b1ea6, 0xf3303a9, 0x1781f58, 0xa9a0cad, + 0x8f3ef0b, 0x4502b38, 0x74c6d35, 0x2b7587e } + }, +}, +{ + { + { 0x23ae7cd, 0xc6eaea1, 0x73c0caa, 0xa1884d4, 0xef1ea88, 0x901e76f, + 0xa14269d, 0xdb9935c, 0x947f1de, 0xe8b2486, 0xa657588, 0x4ad56f4, + 0x2913fb1, 0xe768054, 0x37600da, 0x2abff5d }, + { 0xa81a797, 0xa814813, 0x46acb69, 0x63e76a4, 0x4ab8277, 0xb103839, + 0x9d8e759, 0x587de34, 0xddf62df, 0xdfaeb8d, 0x9239d49, 0x24fe1cf, + 0xe130d1c, 0x7de7409, 0x581d070, 0x3ecfef9 } + }, + { + { 0xf87c72d, 0x8d177a0, 0x8c6d1de, 0xae7e581, 0x8cece85, 0x0077b5f, + 0x32d2187, 0x3824838, 0x6db2bd2, 0x49d8b15, 0xc8d85b9, 0xe9e5513, + 0xe05c53f, 0x63c410c, 0xd86f752, 0xceaf2fb }, + { 0x93806c5, 0x0b432fe, 0x3d06c75, 0x18eb15d, 0x12cfc02, 0xcaad826, + 0x1e2d045, 0x581e040, 0x95edcfd, 0xd573cb5, 0xdbc66e3, 0xce71948, + 0xacc14ea, 0xcf68721, 0x6cac4dc, 0xf68bea2 } + }, + { + { 0xcb74da2, 0xd8576af, 0xc433f46, 0x8771c29, 0xe2f5b8e, 0x7315af6, + 0xba33928, 0xc195481, 0x2fb1f94, 0xb77dcc2, 0xa610f75, 0xcb3e57c, + 0x53907df, 0xeb2a927, 0x23eff95, 0x916f149 }, + { 0xb6cd291, 0xbb378e4, 0x2f13ce1, 0xa2a5e2b, 0xbcd00b0, 0xa8a0e60, + 0x682b75a, 0x5902741, 0x3f65a77, 0xa0882c9, 0xc93cfff, 0x2069f75, + 0x70c0cb9, 0x1ede405, 0x0d526c4, 0x13840c9 } + }, + { + { 0x03ced48, 0xdc2caaa, 0xa0315be, 0x2079219, 0x3b1f642, 0xca49356, + 0xb0665f2, 0x0202dc7, 0xb7a5238, 0xe5d6bbd, 0x26eab32, 0x36fbd5e, + 0xf5819b4, 0xb3988f1, 0x4aa4d69, 0x5b15dc8 }, + { 0x54e5c24, 0xa52feed, 0xe91a797, 0x927471b, 0xd57f677, 0xd119bfd, + 0x78e4c4f, 0xde38f7b, 0xb150bc3, 0xa7af516, 0x26b76c2, 0x403b21e, + 0x92300dc, 0x589067d, 0x066802a, 0x04e406a } + }, + { + { 0xa9ca9bb, 0x28e7d09, 0xfccf4a0, 0xaa84fd5, 0x635b7ed, 0xdbe9fb8, + 0xd56fc7c, 0x9ede3f5, 0xb01cb29, 0xa4b5031, 0x7f93703, 0x584299d, + 0xb6fe825, 0xbd28868, 0x8b9c2d9, 0x1d385d4 }, + { 0x822be80, 0x6606f4a, 0x626d0fd, 0xb5a0165, 0x14568ad, 0x9920a20, + 0x1c6d174, 0x7d430f4, 0xe02e9e9, 0xc243e16, 0xa6bd649, 0x367f1d2, + 0x71b8c36, 0x6939100, 0x4de2984, 0x2ede131 } + }, + { + { 0x5beec32, 0xdc78187, 0xa525ff4, 0x1fff0cc, 0x676df34, 0x6e86425, + 0x3f638e1, 0x2b4e8a6, 0x9b1e59f, 0xc4991d2, 0x1589717, 0x399d001, + 0xbe041cd, 0x406464e, 0x9e65bb0, 0x901cb3d }, + { 0xfb42307, 0xf5f4572, 0xf1b7307, 0xf81b3b0, 0xf2094d1, 0x8fb695c, + 0xdb56f7b, 0x7db4792, 0x5a794e0, 0x36836d5, 0x09bc879, 0x2da477b, + 0x1887c40, 0x1cdfadb, 0xf2699b6, 0x65dc6c2 } + }, + { + { 0x4737972, 0x36f9f21, 0x7a387b0, 0x48f0c8b, 0x39a1d24, 0xa156ed3, + 0x0fed268, 0x375293a, 0x7ff75cb, 0xf679f48, 0x1cc9e62, 0xd15a00f, + 0x22c3877, 0x92a7dc7, 0x6fb0ed4, 0xe987063 }, + { 0x16f5f3c, 0xfd8e59c, 0xaeeb48e, 0x375732e, 0xca1ab42, 0x2dd9213, + 0x9ffccea, 0xcb06209, 0xb23edfd, 0xfc611f6, 0x99b060e, 0x2716349, + 0x820de8a, 0xb938b5d, 0xeb49a32, 0x138f6e7 } + }, + { + { 0xe485f70, 0x7feda63, 0xeb27b2c, 0x646380a, 0xc4511c7, 0xcf8fe32, + 0xff9406a, 0x2c68e1e, 0x20b6020, 0xa9f2fd9, 0x3b3e465, 0x1c98fc6, + 0x93e53aa, 0xb8dac35, 0xa750e96, 0x2fb47b6 }, + { 0x1950bb3, 0xea373ef, 0x4ac7aec, 0x8156694, 0xb55b931, 0x8d6b3c2, + 0xb62ef7d, 0x5d13f2d, 0xab9182b, 0x4647f2a, 0x33bf07c, 0x8f56c5a, + 0xb35a221, 0xc5ab284, 0x5a46a6b, 0x0747ab7 } + }, +}, +{ + { + { 0x86b85c5, 0x5b9236c, 0xc482448, 0x5967a0d, 0x7df6ae0, 0x397c955, + 0x5378f2b, 0xf83ee1c, 0x6e05dd1, 0xf82df65, 0x19d7c8b, 0x4c424f6, + 0xa6d5f2a, 0xa612550, 0x63c3ebf, 0xfe8482a }, + { 0x0142c82, 0xcb8d403, 0x3679e6c, 0x08b0662, 0x3eca5ee, 0x3ea5146, + 0x1370500, 0x089eb3b, 0x5a0d306, 0xcbfb19c, 0x42a65bb, 0x2f68588, + 0xe51e119, 0xe3e1db5, 0x110895e, 0x2c150e7 } + }, + { + { 0xf6d4c4c, 0xf323488, 0x63b87e2, 0x5fc931f, 0x35c759f, 0x8867da0, + 0x9746d4c, 0xb6f1eff, 0x990be0a, 0x8a8172d, 0x5c407b4, 0x1113eee, + 0x378ed8a, 0xd80dacf, 0x3fa7fd1, 0x99b57cf }, + { 0x5176405, 0xf5bb6d9, 0x92e83b5, 0x6b8963a, 0x8a7ef8d, 0xac55b6b, + 0x6c1fbf0, 0xe73fa12, 0x60148df, 0xdb37560, 0xf3f1fba, 0x72f1a98, + 0xea550f2, 0x1f71d0a, 0x9544a87, 0xc3ea4f0 } + }, + { + { 0x4322bf3, 0x5b09da2, 0x61264e1, 0x2a573d5, 0x803acc4, 0x93cb2e1, + 0xe502fc6, 0x397b4fb, 0x39e0ebc, 0xddfb212, 0xbbcbc57, 0xeccd8f5, + 0x4663788, 0x49d3bed, 0x1218df9, 0x37192aa }, + { 0x2ffa3c6, 0x8a05bc9, 0x23ebf4d, 0xc38c281, 0xfe343a8, 0xc80d547, + 0x6c63516, 0xa8d5a5b, 0x8d8fa6b, 0xc5d8ce1, 0x24a87c0, 0xeb5e872, + 0x75bfa23, 0x9806e9e, 0x689469a, 0x11f0889 } + }, + { + { 0x8e75666, 0x81005f6, 0xd349505, 0xb84d861, 0x9f321ea, 0xe083282, + 0xcfa33a1, 0xb751d7a, 0x067c550, 0x793cf6f, 0x1027e56, 0x073a6b2, + 0x66a6012, 0x53f40ee, 0xc210fa9, 0x70bfaa8 }, + { 0xe4b5998, 0x1518e39, 0x24b8d9c, 0x8f0b530, 0xafdf923, 0xd91c281, + 0x24e3f69, 0xc5cfb28, 0x870871f, 0x63a529a, 0x2128dad, 0x3d3e887, + 0xcb30cce, 0xed658dc, 0xafb7bae, 0xf9373b9 } + }, + { + { 0xde58ed2, 0x22d4dbe, 0x03f8789, 0x4fefc1d, 0x344817f, 0x6b0a1fe, + 0xa56b0b2, 0x96bef40, 0xda249fa, 0x32684ee, 0x524a91b, 0x8298864, + 0x0c736a1, 0xa958baf, 0xef2f3e5, 0xd033a7d }, + { 0x43f4d6a, 0x5be3edc, 0x9c89abb, 0x326a39d, 0x55d997a, 0x90c44f7, + 0x6e966c2, 0x2058106, 0x6548038, 0xdbae490, 0xd473fc1, 0xac7bc97, + 0x4b2603a, 0xb34488b, 0x5e9bb98, 0x27aea27 } + }, + { + { 0x1b88773, 0xa59e728, 0x0c241f6, 0xe2f05d4, 0x4e75749, 0xa56229e, + 0x1b10705, 0x8f00c0b, 0x19394d3, 0x8559946, 0xaaf5e32, 0x0d7e352, + 0x787b8ea, 0x526c462, 0xa179d48, 0x89297d9 }, + { 0xef43892, 0xeff17e6, 0x221f841, 0x17091eb, 0x4a4b848, 0x82f5eb3, + 0x8eb7b76, 0x6bea477, 0x76c536c, 0x21f2271, 0x96c81bb, 0xd9ef2c8, + 0x54bf4d3, 0x7c27546, 0xd7c28c8, 0x9dd4662 } + }, + { + { 0x20e1a6b, 0xe7fff00, 0xa08d467, 0x26a35c6, 0x3248c91, 0xb3c773d, + 0xba7d935, 0xa646615, 0xb0d26fa, 0xa91f453, 0x60c6d32, 0xdcf9c34, + 0x9e3e3dc, 0x6366861, 0xf30f3e2, 0x3012813 }, + { 0xc2fc61a, 0xac6623d, 0x2bfd2ff, 0x108dc25, 0x231d6ea, 0xd7f5c0d, + 0xad1107e, 0xa904f9a, 0x0d1e9c8, 0x46941c2, 0xc810cf2, 0xe5b6451, + 0x4f511d1, 0xaba8e67, 0x08373fe, 0x5b4b94f } + }, + { + { 0x849c230, 0x002d4e2, 0xd8ba391, 0x9bed0ef, 0x828e319, 0x745e0c0, + 0xca58de2, 0xcd40907, 0x1abaa4a, 0x2c87ab1, 0xdb64391, 0x3c17a97, + 0x86c72d2, 0x36b184e, 0x485f7aa, 0xb03d202 }, + { 0xde24aba, 0x2b6b79b, 0x2325fb2, 0xdcb7854, 0x66ebae2, 0xf5d1db9, + 0x903840a, 0x35a4d5b, 0x190e9da, 0x7afeb09, 0x35c1792, 0x1818f6a, + 0x3faa269, 0x90091fa, 0x2570235, 0xc4ccff6 } + }, +}, +{ + { + { 0xec85940, 0xa177619, 0x7ef7eee, 0xfca24db, 0x7a90c11, 0xb2450f3, + 0xdbf4f85, 0x29d256d, 0x51316c3, 0x920c8d0, 0x04474da, 0x2f7f7ba, + 0x2ec9a0b, 0x308117f, 0xd0d2085, 0xd0a231a }, + { 0x7ab641d, 0xf3288fc, 0x9f4fa32, 0xc68bade, 0xbbf8253, 0x768f014, + 0xc0a33f0, 0x5eff260, 0x6bb93ce, 0xc71b453, 0x680697f, 0xa71d045, + 0xce72bc3, 0xb62444c, 0xd1379f3, 0x11f03e8 } + }, + { + { 0xc16df92, 0x1f54789, 0xe3ed142, 0x874c642, 0xfa2a9f1, 0x6699f60, + 0x3fecfc1, 0xbd1b8d3, 0x8a3d953, 0x59682d5, 0x4a36b81, 0xf17c021, + 0x181a666, 0xeb9621d, 0x3cf1ad8, 0x7c2c3ab }, + { 0xe529f7c, 0xe6888c3, 0xb355315, 0x197b66a, 0x83e31ac, 0x63b558a, + 0x891c68e, 0x4aa7bc5, 0x592e360, 0xc17d989, 0x1363666, 0xc750a29, + 0x4909ac0, 0x0d53470, 0x4594a10, 0xd6d0272 } + }, + { + { 0x3fbb635, 0x35c541b, 0x5982afa, 0x50016d0, 0x96b0ca0, 0x58ebce4, + 0x577ea56, 0xb940027, 0xe38480f, 0xf29d305, 0xebd6a2c, 0x43705b0, + 0xe90c639, 0x0e4acda, 0xf56e05e, 0xbe94a29 }, + { 0x30659ad, 0xc61f4a0, 0xc402211, 0x39074ad, 0x51b621d, 0xfe0d8d5, + 0xd1d5222, 0x2d02e8d, 0x46c2683, 0x05ece3c, 0xc689d41, 0xf70705a, + 0x4d837bf, 0xe3caf44, 0x75ba6d0, 0xfda0584 } + }, + { + { 0xcb7d458, 0x1098163, 0xf5ba834, 0x12b645f, 0x28af72c, 0x70a3181, + 0xf32e5dd, 0x5f4727e, 0x10a21b4, 0x7cbae15, 0x6785389, 0xa80bf80, + 0xb8f93b7, 0x9827402, 0x08349da, 0xe385f82 }, + { 0x9589f6e, 0x2d05461, 0xe7c0191, 0x6aa5b26, 0xbd5574d, 0xe79ae12, + 0x4148e61, 0x5d13f91, 0x13716ff, 0x7b2be0f, 0x80bb81f, 0x82b0fe6, + 0x3e2569c, 0x697633c, 0x873f8b3, 0x6c1f083 } + }, + { + { 0x0be1674, 0x6e26d85, 0xab8044f, 0xe4e47f6, 0x82fc434, 0xfdf46e8, + 0xc89cadc, 0x639ae2c, 0x4b85bdc, 0x2244a52, 0xb7cf4ea, 0xb1e4790, + 0x7e0bb8f, 0x51dce03, 0x2716cee, 0xdd14335 }, + { 0x8e8841d, 0x1c049b4, 0xb97c621, 0x6bf26dc, 0xba01178, 0x21d6255, + 0x8e4f0e4, 0x477258a, 0x68f8ef1, 0xf5e437e, 0x8b03e1e, 0xd118fbc, + 0xe1c91b3, 0x3d6bc51, 0xd5b6907, 0xa259486 } + }, + { + { 0x7b6f5dc, 0x4159cfc, 0x493694a, 0x05a52b3, 0x83b8883, 0xeeb511c, + 0x2b06400, 0x19d79e4, 0x738f37e, 0x8e503a2, 0x5a94ad9, 0xa30e579, + 0x262618d, 0x3981c75, 0x2dcba19, 0x06b6c69 }, + { 0x4d1b051, 0xd7242ee, 0x3b350c4, 0x6274ccb, 0xf540019, 0x66df0bb, + 0x5ae12d5, 0x4d66be6, 0x1049cba, 0xcea2960, 0x8df84b3, 0x4047339, + 0x75a31c8, 0x7d6c96b, 0x874174c, 0xbb80159 } + }, + { + { 0x59f1aa4, 0xf0f7be0, 0xdcff451, 0x798f39a, 0x8014e1e, 0x96763ff, + 0x09cc5ec, 0x03987a8, 0x893650a, 0x4919656, 0x75e24df, 0x92e8eef, + 0xe89d639, 0x54e97cd, 0x7682cc0, 0x8081d06 }, + { 0xa8ceb71, 0xb9ef41a, 0xa4d7aaa, 0xb8173a4, 0xc54ee10, 0x93d81b1, + 0x70a445a, 0xabe1805, 0x64d569d, 0xac0ff97, 0x3e570be, 0x86946b2, + 0x4180641, 0x8e11dd2, 0x99f67dc, 0x3d0b33c } + }, + { + { 0x48bf5a4, 0x2c9637e, 0xccaf112, 0x9fdec19, 0x5c42023, 0xe5cde9d, + 0x878f0cc, 0x9869620, 0x1fe6eba, 0xcf970a2, 0x54e678b, 0x1df5ec8, + 0x28d00dd, 0x4667f01, 0xb0b3fa8, 0xfa7260d }, + { 0xb34239b, 0x6bd2895, 0x2d2a50d, 0x04c8bc5, 0x6cb23e2, 0x14e55ef, + 0x3a278d5, 0x6440c27, 0x2193046, 0xf4b12e3, 0x5dd4c08, 0x46adf64, + 0x4656e8c, 0x70e2998, 0xe4acd44, 0xe7b36ea } + }, +}, +{ + { + { 0x16cf664, 0xea64a57, 0x26fd357, 0x8497ee4, 0x814e851, 0x44d94b4, + 0x5a6a2cf, 0xf4aac22, 0x80c301f, 0x947b309, 0x7865383, 0xf390ba1, + 0xd1773d3, 0x16c4fc6, 0x6227220, 0x61b9814 }, + { 0x1dd0270, 0x07dd03a, 0x0f160df, 0x290ca82, 0x44ba955, 0x8f22054, + 0x0b6f1b3, 0x4e85e45, 0xad78089, 0xfd73ce9, 0x2f2cb0e, 0x67c1270, + 0xee33a61, 0xa7de0d7, 0x6553261, 0x6a811cc } + }, + { + { 0x2d0a427, 0x5ef0574, 0x220a341, 0xe8d2e95, 0x8044886, 0xdd28cbf, + 0xa1aa58b, 0xdad7b4b, 0x8ec901b, 0xb28f373, 0x5bbe3db, 0x1841a93, + 0xa075fee, 0x8fd7cd1, 0xc0d3cdd, 0x93b603f }, + { 0x5edd859, 0xca54fd5, 0x64ed687, 0xa4cb05f, 0xed1a3d7, 0x3138668, + 0xee32be5, 0x1224fda, 0xc80aeb3, 0xf1f532b, 0xe8d4d69, 0xa4f65d0, + 0x5905fe5, 0xc697a01, 0x6690ce4, 0x514da7a } + }, + { + { 0x3de4a55, 0xc7b9af8, 0xb318d93, 0xc79bad7, 0xf5b1c83, 0x1808071, + 0xb965b16, 0x92112ef, 0x7bb740a, 0x655ab38, 0x384ff87, 0x53dbc8b, + 0x72dc6f2, 0xd153c28, 0x99c7819, 0x2ec20e1 }, + { 0x3b854b5, 0x65e46ea, 0xc711db5, 0x272d5ae, 0x26e19e8, 0xfd1bb53, + 0x3dc0665, 0x33280b8, 0xb8f1c4a, 0x95b986e, 0xa685c4a, 0xa671fc4, + 0x83bdbbf, 0xa03cbd5, 0xab77544, 0xd329402 } + }, + { + { 0x8e62b35, 0x40fa651, 0xf9e55a6, 0x3913b11, 0x5270a41, 0x4e8089b, + 0x80d1886, 0x565f52a, 0x512749b, 0x93b5f05, 0x141c547, 0x35c869c, + 0xf86717f, 0x9a44a1a, 0x9c2b2cb, 0x2b9984b }, + { 0x4952322, 0x61fb607, 0x7af1464, 0x2d4072f, 0x600eb30, 0x9b2fa8c, + 0xf10668e, 0x6071fb7, 0x90634ca, 0x27cc24d, 0x471d32b, 0x3875bc2, + 0xa11210c, 0x678590b, 0xfcc5a9a, 0x352b447 } + }, + { + { 0x5fa3200, 0x795d541, 0xa92949f, 0xadaa557, 0x3cc88c4, 0x42fff06, + 0x71b68a5, 0x26d6831, 0xe67ad8c, 0x3286549, 0x86396b2, 0x5bf6363, + 0xe12c8ea, 0x41229b6, 0x748952e, 0x05320c9 }, + { 0x900b460, 0xae36b63, 0xf2b6aff, 0x9354ff2, 0x065ee0c, 0x10b810b, + 0xcc8bb38, 0x4d6925f, 0x7a22f14, 0x31c03fd, 0x57544e8, 0x76b7f44, + 0xc0eed26, 0x3a9123c, 0xe0cd1cc, 0x77acd67 } + }, + { + { 0x07ec527, 0x2e90530, 0x62937cf, 0x32388ef, 0xe229188, 0xa445389, + 0x33bcebe, 0xa44b68e, 0x4c4e701, 0x5a8722e, 0xcf07e41, 0xfd066e8, + 0x95fab62, 0xa3c1a4f, 0xe542f24, 0xb4d6a1b }, + { 0xaf6c9b5, 0xe6a92e4, 0xc83d61d, 0x9452484, 0x0062276, 0x422b55b, + 0x5279688, 0x261973a, 0x3999fb2, 0xde8be26, 0x7b029ca, 0x64e9628, + 0x06897d4, 0xd8edfaa, 0x6955511, 0x408319c } + }, + { + { 0x50a5632, 0xff6baed, 0x5c5885a, 0x922b7d0, 0x1b45864, 0xdf0f3b3, + 0xc04340e, 0x27e49c0, 0x122c447, 0x618c566, 0xeafee7e, 0x7863a38, + 0xb828cb0, 0x7143aff, 0xf9d054e, 0x51fcf4c }, + { 0x27f5e09, 0xc4a4b31, 0x90be2bd, 0x021f47a, 0x7ab956d, 0x1a06019, + 0x86ea86b, 0xe77fa15, 0xd550ef3, 0x9ccde87, 0x6532654, 0x7dee53a, + 0xe826387, 0x8b4f060, 0xad077b5, 0xda38637 } + }, + { + { 0x0e9fac8, 0xbc901b3, 0x6fb2a2a, 0xfa08204, 0x5e04efc, 0x92f68ab, + 0x9ac12d0, 0x184a30a, 0xb25d479, 0x1aa11aa, 0x0f03161, 0x8bc5f4c, + 0xcfc8817, 0x7e3a083, 0x597f93f, 0x84d9355 }, + { 0x239abc6, 0xc014478, 0x8d37b04, 0xb226b09, 0xf575789, 0xb056942, + 0xba745eb, 0x816b95a, 0xb98ddb6, 0x2a49d39, 0x291af81, 0xc41ca26, + 0xab26347, 0xb3afe99, 0x604b638, 0x59c31bc } + }, +}, +{ + { + { 0xc42befd, 0xa16a8b9, 0x2052f00, 0x731c9c9, 0x1f5dfa0, 0x1ad49b4, + 0xbffce36, 0x7a289e3, 0x0c79cf1, 0x868fac0, 0x86721ab, 0x6d6d284, + 0xe726c94, 0x590f928, 0x51f3841, 0x0e802cb }, + { 0x0b694bc, 0x6a6a57a, 0x8120fb8, 0xb9bb0cd, 0x9c05826, 0xad96ac7, + 0x7768df0, 0x294da8c, 0xb56c6c6, 0xfe32311, 0xae8d050, 0x291c2c6, + 0xe7db4c9, 0x1c765e7, 0xd65f9f7, 0xe058298 } + }, + { + { 0x7e8d345, 0x4bfa85b, 0xde1dfc8, 0xa04ef95, 0x324ace3, 0xb5f7f21, + 0x574b14a, 0x4b350a1, 0xf8e5c8d, 0x11436bf, 0x7642369, 0x1c789f9, + 0xfb623ce, 0xeb5e335, 0x442d562, 0x9deacd2 }, + { 0x531ee71, 0x4ff989f, 0xaacb52a, 0x43e2c49, 0x85bfadc, 0xa763198, + 0xd0161a0, 0x08b6d5c, 0x541f197, 0x010e3fa, 0x3279a16, 0x83a589e, + 0x6309f9b, 0xf099137, 0xf1cea10, 0x07c093b } + }, + { + { 0x33d2192, 0x1ce3f0f, 0xc37ce73, 0x07b559a, 0x207be27, 0xaa2ad38, + 0x7ed93de, 0x84f053b, 0x3b98a4b, 0xbc5c797, 0x63aa9b9, 0xc923461, + 0x231a10c, 0x807cc16, 0xa061209, 0x8ffdf57 }, + { 0x497070f, 0xa9ca741, 0xd113b3a, 0xf608ec9, 0x8d0384d, 0x5132726, + 0xf5ec307, 0x96686ac, 0x71c4665, 0x437bbbd, 0x7c379ca, 0xdef09d5, + 0x621747c, 0xf8be033, 0x8ae8047, 0x2775b37 } + }, + { + { 0xb2c4fc2, 0x4009798, 0x203772e, 0x148d7d1, 0xf8423fb, 0x9d9392d, + 0xaf8cef4, 0xa5bd72e, 0x4380b53, 0x579d58d, 0x8c39d24, 0x2ff88f1, + 0x5706466, 0x9ca2fbc, 0x1e56af2, 0xb42987d }, + { 0x5d94ea8, 0xcc2556e, 0x5369d76, 0x4e5c2b3, 0x2a94f9c, 0x5de3574, + 0x5cb4145, 0x8d068c9, 0x51bfcbf, 0x4d553ff, 0x8a23fce, 0x3ab7164, + 0xd0fa7f3, 0xc9cb3a9, 0xed9ced1, 0xf81209b } + }, + { + { 0xe5b66f5, 0xde7356e, 0xe8a25e0, 0x7b2bf1a, 0x2c9b725, 0x09a444a, + 0x4906c55, 0xfd8a2f4, 0x82514f3, 0x409cc80, 0x28999a9, 0x47e0099, + 0x6a312f4, 0x0a582a6, 0xf6723de, 0xf7946f8 }, + { 0x92d8aff, 0xa55f6ba, 0xa544b1c, 0xb62c3c8, 0x5c16a94, 0xa1d1411, + 0x2ad5e71, 0xc378319, 0x06b1dd6, 0x13d7847, 0xee7ff55, 0x99005f8, + 0x8a1e7d8, 0xfb5ea3f, 0xb4cac39, 0xdc7f53c } + }, + { + { 0x36e3794, 0x482abaf, 0xc74684f, 0xc23e9e5, 0xf1629be, 0x4544cf6, + 0x2f40374, 0xd8a8ee5, 0xf433bdb, 0x2eea87f, 0xae9990e, 0x489a99c, + 0x54b23b6, 0xefc131e, 0x8600270, 0x25fe699 }, + { 0xc059a7e, 0x03d2d9e, 0x6979c3c, 0xa6445b5, 0x9bfbcea, 0x491a10c, + 0xe937af1, 0x15b5974, 0x797c7fc, 0x4be8002, 0xfedcfee, 0xbed8a49, + 0xa9e0691, 0x35751ce, 0x9ef5982, 0xe9a9fa3 } + }, + { + { 0x3065de7, 0xeffeaca, 0xac4d4e2, 0x841d544, 0xcaf199f, 0x8144679, + 0x443967a, 0x98cf4f9, 0xf33183c, 0x8cd57f4, 0xc1b15eb, 0x390832a, + 0xa53b500, 0xc4b1fea, 0xdff24b5, 0xd762a10 }, + { 0xb0ee2a9, 0xccd3eed, 0x362d485, 0xa6dd4a9, 0xf1d047a, 0xeb4ff26, + 0x23860fc, 0xc0771fd, 0x4b64114, 0xdbb4e39, 0x4d29b29, 0x2ff3f24, + 0x387b365, 0x9cac005, 0xde5994a, 0x05b7aa6 } + }, + { + { 0xc03dd63, 0x5e71752, 0xbc74687, 0xad10fe9, 0x54c76ab, 0x51a5b0c, + 0x1f586d4, 0x763fd50, 0x816048b, 0xc7bd5ce, 0x3f744dc, 0x8fc83d2, + 0x109df9a, 0x0561802, 0xccf0e43, 0x18fb01f }, + { 0x038ab23, 0xe4606fc, 0xa664c98, 0x5878f1f, 0x5da7356, 0x3aedbbd, + 0x516746a, 0x3c578f5, 0x1a17210, 0x259477f, 0x028248f, 0xc7a869d, + 0x48cbf95, 0x6517a61, 0x3d04d47, 0xbc5f91d } + }, +}, +{ + { + { 0x083ca53, 0x15fd9a9, 0x2697ca6, 0x1161da0, 0x56b676c, 0xf516af3, + 0x75eec13, 0x8a420d5, 0x1a9526b, 0x72d6742, 0x76b463f, 0x8d8c29e, + 0x8815627, 0x38a4f58, 0xe0650f9, 0xf7e528b }, + { 0x382edca, 0x2cfa78e, 0xc4ad83c, 0x638d183, 0xe4a0119, 0x96d3b9d, + 0xa7c1101, 0x5769ccb, 0x2b8d04a, 0xc3b3b79, 0x4951bde, 0x96212f6, + 0x481161e, 0xad7905a, 0x41c5edf, 0x8fd6762 } + }, + { + { 0x39d6cde, 0xf7b0635, 0x115a84a, 0x69d0549, 0xcbd9fe4, 0x4a976c6, + 0x950ff96, 0xc92953f, 0x654d127, 0x1d7f0fe, 0xda0f75d, 0x7293870, + 0xcf2277f, 0x7bb3652, 0x834484f, 0x64798c9 }, + { 0xac3a76c, 0xb94d8bf, 0x7ff776b, 0xf5721a9, 0x2722e31, 0x23a6e9f, + 0x9a5c034, 0xe9da996, 0x456ebc3, 0xb9bbf83, 0x96956a4, 0x239f58a, + 0x18b7f00, 0x8b75beb, 0xa51cb97, 0x6c2b5b8 } + }, + { + { 0x7eb41f3, 0x78b1c62, 0x17c4352, 0x0638fcf, 0x0c5709c, 0x939edd8, + 0xedc906c, 0x0a8dfc3, 0xefb01ed, 0x3942f47, 0x49986fe, 0x4c82757, + 0x4dffa57, 0x792545c, 0x6c3ff26, 0xeee6883 }, + { 0x12b1218, 0x824d08e, 0x902457f, 0x515a478, 0xbae55b3, 0xc70cc9c, + 0xbcef9d4, 0x1240737, 0x2f9db7f, 0xf22e616, 0x91f8da2, 0x98c4f02, + 0xafaaa67, 0xa89219c, 0xe7d27e2, 0xf35fd87 } + }, + { + { 0x01b80d0, 0x19b0cd7, 0xf9aebd1, 0x3d7e29d, 0x0477cbc, 0xd39c9ca, + 0x5ff0d3d, 0xac0f615, 0x520fd01, 0x8a51993, 0xb22d6fb, 0x508ff54, + 0x318d3ab, 0x8786c47, 0x4a683f8, 0x4312c46 }, + { 0x95359f6, 0x73b1d39, 0x963011e, 0x0d94fa5, 0x9bfe83e, 0x5723af2, + 0x6841df3, 0xafa9001, 0xb7c498a, 0x791e92a, 0x7ea4253, 0xbc931ad, + 0xb783c06, 0x438e016, 0x2ca662b, 0x1347db2 } + }, + { + { 0xfbaa861, 0x41df37d, 0x329e4de, 0x98ecb23, 0x507e018, 0xdaf1560, + 0xb088e32, 0xa902269, 0xe4cab2f, 0xad898a5, 0x02c1e1b, 0xd84e9ed, + 0x8488af3, 0xc20a5d5, 0x6cc77c6, 0xc7165af }, + { 0xdeb7461, 0x8526f3a, 0x4a2d332, 0x03577b1, 0xe4760b5, 0x28e469d, + 0xb276266, 0x442c7f9, 0xf9c90fa, 0x90d5c77, 0x3e211bd, 0x7aa8716, + 0x5decfd6, 0x56d8ff0, 0xee23e6e, 0xa204b56 } + }, + { + { 0x4aceafc, 0x2e4374e, 0x6fcd5e5, 0x978743b, 0xc4855ca, 0xa0f6345, + 0xe98074b, 0x9bc7e4f, 0xc33d08a, 0x3835d57, 0x6f00566, 0xeec7c8b, + 0x1acf55c, 0x71628a2, 0x97fb19e, 0x5da3750 }, + { 0x01a7125, 0x6904a8e, 0xe6e3780, 0xad33c85, 0xc19f94a, 0x1702928, + 0x7c04b3d, 0xb424ff2, 0x19e2ba3, 0xb212e39, 0xc9af4c9, 0x4cca8e8, + 0xfd9bf0e, 0x98ab7ae, 0x9799db5, 0x21d245d } + }, + { + { 0xec08806, 0x6b034dc, 0xb40f2d9, 0xfd763f2, 0x29cb906, 0x5e16de0, + 0x8a0e16a, 0x02b7014, 0xe071e12, 0x463c8ee, 0x25ad509, 0x6447281, + 0xdc0e07a, 0x9ee6f2d, 0x68d4d97, 0x188895c }, + { 0xb27f971, 0x092fff3, 0xc9b7722, 0xb3c159f, 0x3cae42d, 0xe27d8ff, + 0xe87071d, 0xf8a5ed6, 0x607ebd2, 0x318388f, 0x53486f1, 0x924967b, + 0x7c46e1f, 0x7730494, 0xf21d196, 0xf279c60 } + }, + { + { 0x84f3201, 0xef2bc03, 0x1f94c51, 0xf8750c7, 0x986ec65, 0xbaa4f5a, + 0x2732a33, 0x6f8a5de, 0x299e365, 0x0f13d80, 0xe85261f, 0x2709530, + 0xf527d56, 0x097d922, 0xbe1f3f8, 0x4969687 }, + { 0x3e1708d, 0x9f3f504, 0x4aa4be4, 0xac67b87, 0x320a87e, 0x75fb042, + 0x6e2cad6, 0xa361ad3, 0x203e9f6, 0xcb01470, 0xc9b76c6, 0xe3807b7, + 0xb907c09, 0xf086833, 0x7e85a01, 0xe9bed3c } + }, +}, +{ + { + { 0x91780c7, 0xa7ea989, 0xd2476b6, 0x04e4ecc, 0xc494b68, 0x0af9f58, + 0xdee64fd, 0xe0f269f, 0x021bd26, 0x85a61f6, 0xb5d284b, 0xc265c35, + 0x3775afd, 0x58755ea, 0x2ecf2c6, 0x617f174 }, + { 0x5ec556a, 0x50109e2, 0xfd57e39, 0x235366b, 0x44b6b2e, 0x7b3c976, + 0xb2b7b9c, 0xf7f9e82, 0x0ec6409, 0xb6196ab, 0x0a20d9e, 0x88f1d16, + 0x586f761, 0xe3be3b4, 0xe26395d, 0x9983c26 } + }, + { + { 0x6909ee2, 0x1d7605c, 0x995ec8a, 0xfc4d970, 0xcf2b361, 0x2d82e9d, + 0x1225f55, 0x07f0ef6, 0xaee9c55, 0xa240c13, 0x5627b54, 0xd449d1e, + 0x3a44575, 0x07164a7, 0xbd4bd71, 0x61a15fd }, + { 0xd3a9fe4, 0x30696b9, 0x7e7e326, 0x68308c7, 0xce0b8c8, 0x3ac222b, + 0x304db8e, 0x83ee319, 0x5e5db0b, 0xeca503b, 0xb1c6539, 0x78a8dce, + 0x2d256bc, 0x4a8b05e, 0xbd9fd57, 0xa1c3cb8 } + }, + { + { 0xd95aa96, 0x5685531, 0x6bd51ff, 0xc6f1174, 0xc9c2343, 0xb38308a, + 0x2921841, 0x52ee64a, 0x78f3b01, 0x60809c4, 0xae403ac, 0xe297a99, + 0xcb09a5b, 0x7edc18f, 0x81ac92a, 0x4808bcb }, + { 0x34dc89a, 0x3ec1bb2, 0x4e39da5, 0x1e8b42e, 0xe526486, 0xde67d5e, + 0x76f0684, 0x2376548, 0x285a3dd, 0x0a583bd, 0xfe9b009, 0x3d8b87d, + 0x0413979, 0x45bd736, 0x38a727f, 0xb5d5f90 } + }, + { + { 0x4bde3ee, 0x7b8820f, 0x24d5170, 0xea712ef, 0xdf6ec7b, 0x517f88c, + 0x983ea9a, 0xb15cecf, 0x31a4592, 0x9eeee44, 0xebb013e, 0x786c784, + 0x1f4e15d, 0x2f06cb3, 0x4f4fda1, 0x5603fd8 }, + { 0x9e1321f, 0xf6790e9, 0x74a4c09, 0x274c66a, 0x9a41a4e, 0xa4b70b4, + 0xada5157, 0x7700bdd, 0x51be8dc, 0xe54a60d, 0x1a477e0, 0xfaf9276, + 0xb027eac, 0x6661c72, 0x280b917, 0x50e2340 } + }, + { + { 0x96ec123, 0x635f40f, 0x7a766a4, 0x4a33133, 0xb935587, 0x9ce4416, + 0x95d97e4, 0xbb6e1f5, 0x9d4197d, 0x2614723, 0x490e896, 0xabd4478, + 0x8bba895, 0xf6a1b2a, 0x5e27a45, 0x401fa40 }, + { 0x0620900, 0x7354ba5, 0x385678b, 0xc443a29, 0x53cf5fa, 0x48aba10, + 0xbbe152d, 0xd67e723, 0x2a63d68, 0x4b858e0, 0x72be4ee, 0x174e1ee, + 0x9ab8d46, 0xad0fbb3, 0xce17dd7, 0xa0fdffb } + }, + { + { 0x9c46fd8, 0xa1ea325, 0x9fb96ef, 0xeca122e, 0x6767acd, 0xf9074a2, + 0x2787082, 0x9b004a2, 0x7f3ba8e, 0x389f807, 0x0d5aabe, 0x6463de9, + 0xb090585, 0xf30ceaa, 0x5634ab8, 0x71b31e8 }, + { 0xaf02aed, 0x0dee65c, 0x20ac252, 0x506886e, 0x86b8a59, 0x0665f78, + 0xf2bb328, 0xb9b784d, 0xdc6b089, 0x46e443a, 0x66c27fd, 0x3d5de19, + 0xf0fde70, 0x0419265, 0x2b5c034, 0xed94612 } + }, + { + { 0x13b0056, 0x5a52ad2, 0xb909ee3, 0x9fbeb92, 0xbdaab08, 0xb42ba18, + 0xffc8a77, 0xec127c4, 0xfda906a, 0xc6d2985, 0x994bbe7, 0x5355547, + 0x9cdfd62, 0xa7470c0, 0xd2e675a, 0x31a3971 }, + { 0xcc8b356, 0x8d8311c, 0x01b4372, 0xabb0bf8, 0x0294566, 0x33c1cad, + 0xe07b672, 0xe2e649c, 0x2ae3284, 0x9084d88, 0x1835ce2, 0x7a90d4c, + 0x809d44c, 0xb4d1cd5, 0x9f0528f, 0x7822714 } + }, + { + { 0xbf5844b, 0xca884cf, 0x8524cf9, 0x9dd05c4, 0x36ba889, 0xdbffa19, + 0x29e7666, 0xef94fdd, 0x3eaf48f, 0x358f81b, 0x1530d56, 0x96734d5, + 0x4adf9e5, 0x378b2d1, 0x4731f61, 0x2f85046 }, + { 0x99dcb83, 0xd6ae905, 0x6199239, 0xa4f89e0, 0x8f0f958, 0x6405249, + 0xcc27707, 0x2866d99, 0xf551c0f, 0x64681a2, 0x4c37080, 0x2c7b0d0, + 0x00ac301, 0x218925b, 0x54df895, 0x8d57fb3 } + }, +}, +{ + { + { 0x809c8d7, 0xdaebde0, 0x0e95ea1, 0x58c761c, 0x00ae5e2, 0xbd99650, + 0xcd51acd, 0x6117a85, 0x7c55d56, 0xc4424d8, 0xdfbeeaf, 0xe9b1dde, + 0x0db4791, 0xda98bb5, 0x3fca108, 0xff3a5a6 }, + { 0x5ccbea1, 0x172fb8e, 0xa9f6cc9, 0x9fe12a7, 0x8967ce2, 0x1de4b0b, + 0x671dbc6, 0xc1ab60f, 0x5dedcda, 0x338385a, 0x3a043fe, 0x647a420, + 0x28ebc89, 0xe9abc64, 0x03ba3c8, 0xc357ff0 } + }, + { + { 0xde39ebd, 0x37061e7, 0x2be567a, 0xebb9135, 0xd6bb80a, 0xa9a6f6b, + 0x99f0ba2, 0x039345d, 0x98bbf47, 0x215494e, 0xa2a1ccb, 0xf2cb7a4, + 0x37f67c9, 0xf51aa10, 0x17fff71, 0xd29c85c }, + { 0x4d30b87, 0x8d4e4f2, 0x93a8309, 0x20fdf55, 0x757075c, 0x9b9f9cf, + 0xcd70101, 0x09142ad, 0x766ca55, 0x901d0ee, 0x32e418b, 0x6a5d86a, + 0xd7fcaec, 0x550ad92, 0xd91b26e, 0x64e8818 } + }, + { + { 0x47e5ee5, 0x5cea0f7, 0xbe99699, 0x8ca1d31, 0x5c136c7, 0x52db846, + 0x90e0d74, 0x8cecb38, 0xede2ad8, 0xb8efe9d, 0xf17ade8, 0x18d6ff8, + 0x2d66c20, 0xd222735, 0xf2005fd, 0xc46593e }, + { 0xf7141e1, 0xe5ebe6f, 0xe0126f2, 0xc968315, 0x1cb91b6, 0x95adc73, + 0x38a6003, 0x753b54c, 0x4230a61, 0xa614125, 0x559fece, 0x23ac6eb, + 0x3865c23, 0x9816b60, 0x543a570, 0x567014e } + }, + { + { 0xdd2b71f, 0xd46091d, 0x97d24ff, 0x3999a5d, 0x1ecff3c, 0xce2a4f1, + 0x581c6f0, 0xab2687c, 0xcba70b4, 0xa9fb2eb, 0x42093e1, 0x6fde356, + 0xaee724a, 0x00253ec, 0x2b81bdd, 0xa08ce3c }, + { 0x935a2b3, 0xa251238, 0x584f750, 0x8cae1d4, 0x988a219, 0x011469e, + 0x5a6a50e, 0x61f7ed3, 0x01fcebd, 0xe13ebaa, 0x31d8867, 0x794b976, + 0xcda32e7, 0xf25755c, 0x4564cd1, 0x368a97b } + }, + { + { 0xaa3397b, 0x0d22224, 0x38066db, 0x1dbb3e6, 0x0ce8e32, 0xfe0b5ee, + 0x7bab4dc, 0x09c17c8, 0xf188b64, 0x5cc65dd, 0x211b5fa, 0x74c4abf, + 0xab0ba86, 0xdcc17b7, 0xa535501, 0xfbdf46f }, + { 0xaca569e, 0x4775087, 0x06a1718, 0x6575f90, 0xb94de93, 0xb5c45a9, + 0x8497171, 0x0fc8006, 0x489f7ab, 0x775d965, 0xf5c0c89, 0x8775b58, + 0x1a06254, 0x05d4e20, 0xb6d73a5, 0x8cab349 } + }, + { + { 0x39465b0, 0xca78163, 0x14498fd, 0x3ef9148, 0x6255c11, 0x9ca1f34, + 0xb7f38f1, 0x389fd15, 0x354b8f3, 0xdac2089, 0xa840a70, 0x82d07fc, + 0x1dd483a, 0xf53fd73, 0x1590578, 0xa6e4eae }, + { 0x3c01b77, 0x7bf65af, 0xa75c982, 0x27542f3, 0x716cfce, 0xc5bd947, + 0x884b9e7, 0xba5fe76, 0xd55725d, 0x39bae14, 0xfae0eab, 0x982f64e, + 0x7a5293a, 0xcfae662, 0xd60f464, 0x22a25a1 } + }, + { + { 0x7dd5e16, 0x74caecc, 0xce7bca3, 0x23678a2, 0x57f1ba1, 0x4673932, + 0xa4c1697, 0x4eb9948, 0xeaba18d, 0x5d400e8, 0x9807871, 0x128d1c8, + 0xbff38a6, 0x78f9627, 0xa39d4cc, 0xf80b813 }, + { 0x31d3aad, 0x8aeefa0, 0x27db664, 0x5042199, 0x4cb6383, 0x244fc69, + 0x72192a3, 0x3190477, 0xbbfb57b, 0xcc86075, 0x4451511, 0xbae3a13, + 0xf6174f0, 0x16cf416, 0xd376813, 0xb343cc0 } + }, + { + { 0xd1824b7, 0x31ac9b9, 0xec8f61a, 0x6282260, 0xc781765, 0xbbeb9f8, + 0x2d110da, 0x06ab5c0, 0x47146b8, 0xd583e22, 0x4100d05, 0x79a1608, + 0xf0a5c95, 0x16dbbb4, 0xe331667, 0xfe2af1d }, + { 0xaf8710e, 0x26f0364, 0xeec08fe, 0x1cb8c91, 0x1d95e9f, 0x436bce6, + 0x57944a0, 0xfe9050c, 0x07b626b, 0x5f45acf, 0x9cf1276, 0x48dc93f, + 0xa05bfb7, 0x4491371, 0x4bcf785, 0x5106304 } + }, +}, +{ + { + { 0xed0b3b6, 0xac2e294, 0x671637b, 0x5c5ade6, 0x1140677, 0x2f289ce, + 0x754eb53, 0xaf446e2, 0x20421ad, 0x70911b7, 0xe0b7556, 0x4b73836, + 0x2a97827, 0xcadf104, 0x8005bc6, 0x4824e49 }, + { 0x937c28a, 0xb0eeccd, 0x0c3ee97, 0x1ce061d, 0x9f33faa, 0xcb07631, + 0xaea66dc, 0x9980bf4, 0xd111d98, 0x2bd0755, 0x7fe4de0, 0x43feaf6, + 0xb077b2f, 0xe76fb80, 0x5793b04, 0x227dc9f } + }, + { + { 0x14f49ba, 0xea24ae5, 0x11436e7, 0xbc39ea6, 0x78485d8, 0x9d7fed2, + 0xdf8b131, 0xb6ef00c, 0xfdbc7af, 0x0237b4b, 0x64ccd27, 0x08745b5, + 0xafc5a76, 0xaf8595d, 0x29f5500, 0x43657af }, + { 0x48470f8, 0x3007183, 0x640fd53, 0x51f91fd, 0xbe15512, 0x859c807, + 0xab3e9c5, 0x7d1a474, 0x81553e5, 0x5d714d9, 0x6f62310, 0x0757343, + 0x6b02a62, 0xedc5be0, 0xea47832, 0x5a4b9b7 } + }, + { + { 0xe93dbb3, 0x03e0a24, 0xcadc884, 0x25841dc, 0x8d10ad5, 0xabc1a81, + 0x2042ddd, 0x207e38a, 0xfeba8d8, 0x7fffbdb, 0xa3ec9b5, 0x74efebb, + 0x0b40a9f, 0x0bc39ca, 0x0267feb, 0x69ee9c9 }, + { 0xbc62919, 0xd402fac, 0x1cf53c6, 0xe9f8fc1, 0x7cc7d81, 0xe76fa5a, + 0x96bb19d, 0x4f2d876, 0xadc67c7, 0xd4fb7f9, 0x96702dc, 0x40621d5, + 0x438f6c5, 0x5b6a98e, 0xf1a1036, 0xa7c64de } + }, + { + { 0x9a092c7, 0x84c5e80, 0x11c22b7, 0x9e40e0a, 0xd06c99b, 0x820a091, + 0xeecca8f, 0x45fdc77, 0x5794f16, 0xfe1b8a3, 0x4ce3d6d, 0x31f7e5b, + 0x82c74c8, 0xfd5e010, 0xc1f6f7d, 0xfdabf30 }, + { 0xb9248a0, 0xbfa6017, 0x546b941, 0xe898d30, 0x207ff65, 0x878c492, + 0xb874e64, 0xbf22e8d, 0x53a547e, 0x43fdb1b, 0x5fbd464, 0xb66deda, + 0xc7ae1b5, 0x59127a6, 0x6a7515a, 0xa463646 } + }, + { + { 0xde9ab2e, 0x22c4e66, 0x0203c58, 0xfaf60c2, 0x0d5c5ed, 0xed2d7bf, + 0x4ca0f19, 0xdbc16fe, 0x465b979, 0x54e8ef6, 0xa310ef9, 0xe2d64b1, + 0x3778636, 0xa0f2c95, 0x281883b, 0xf3b4aa4 }, + { 0x9be6629, 0x4ac9af0, 0x1ca90c5, 0xba455e1, 0x856f492, 0x0147538, + 0xabd7840, 0xc80db7e, 0x6beb9cd, 0xb3526d9, 0x9d81503, 0x37657fb, + 0x193cec3, 0x8729a16, 0xd69952a, 0xd9a93fb } + }, + { + { 0x94f47c6, 0xfce0175, 0xe366d05, 0x228da21, 0xdc8baf3, 0x27ce0b2, + 0x6b4a951, 0x8cc660b, 0x384bb01, 0xf678947, 0x44d980c, 0xc629d7d, + 0xe85e81f, 0x47980e4, 0x1cd723e, 0xa2e636a }, + { 0x77fb207, 0x6b6ebae, 0x4c92891, 0x7017961, 0xb4d279c, 0x5569541, + 0x41758cb, 0xbb6b36a, 0x27a8e30, 0xecaa222, 0xb470ad9, 0x8b6746a, + 0x63e2d3d, 0x4c46017, 0xd3edaec, 0xe19c4ed } + }, + { + { 0x34718c8, 0x0b43fec, 0xf33499f, 0x553c407, 0x970d1db, 0x8272efb, + 0xa8e8d1c, 0x008c62c, 0x63eec45, 0xe4b79d7, 0xf2d71a3, 0x1fd4230, + 0xa368c36, 0x090fdaf, 0xfca7baa, 0xf62c101 }, + { 0xd2395b3, 0x1c9e6c8, 0x04c5513, 0x671ed63, 0x299a465, 0x577d933, + 0x63f9986, 0x286890e, 0xbfc979c, 0xd92a95d, 0x2b51019, 0xcebd79d, + 0x3d07251, 0xe74d88b, 0x906f9ad, 0x8b6db73 } + }, + { + { 0x7b3d90c, 0xc0c43db, 0x4304a06, 0x85d154e, 0xaf2f38e, 0xe8aceef, + 0x83d9459, 0x5e04293, 0x431afd1, 0x65e5e32, 0xa900a65, 0x9e5f050, + 0x8a26671, 0xcbaa171, 0x9c93de7, 0x33d0b24 }, + { 0xd5b6680, 0x3dcbf92, 0x20006f9, 0xc47e5ec, 0x9a51924, 0xc971129, + 0xcd0ed46, 0x665d9b8, 0xa5fcab6, 0xed2d63f, 0xcfbfc5a, 0xa817eb6, + 0xb76eb76, 0xb38169f, 0xf11160b, 0x8b93544 } + }, +}, +{ + { + { 0x693bdcd, 0x02eca52, 0x2ae01d6, 0xbbf0923, 0x8b44b3e, 0x0b0a2de, + 0xb250dff, 0xdb82449, 0x6e1c530, 0x0c42b86, 0xa64c2c4, 0xcd226dc, + 0xf046b5f, 0xcfb2bb1, 0x3fccb0d, 0x97e2fae }, + { 0x45ed156, 0xdf92907, 0xf641229, 0x224dcb9, 0x5f1f67e, 0x2126abc, + 0xe9c8a6b, 0xa7eed5a, 0x9857d9b, 0x40abedc, 0xde941c6, 0x3f9c7f6, + 0xd725ddf, 0x2158d42, 0x8c69543, 0xbdd1015 } + }, + { + { 0x8df2fbc, 0xa7dd24e, 0x13d1aee, 0x3adbcfd, 0x13b2177, 0xf6a32d1, + 0x7a9a14c, 0x89a7232, 0xdc65df9, 0xe3aef43, 0xa64d74c, 0xeaec3e3, + 0x4fec33b, 0x4d387d8, 0x21a2128, 0xaba2a05 }, + { 0x6b85e30, 0x2382c22, 0xcd2aad3, 0x4352d85, 0xd9772c4, 0xb0c6001, + 0x5f3653f, 0x7ed8263, 0x0300f47, 0x3626a6f, 0x6ca7e4e, 0x23909de, + 0xc154141, 0xb43dd81, 0x7e4bc68, 0x9a49fad } + }, + { + { 0x2428f88, 0xa3661df, 0x56e0db2, 0xbe48b02, 0xce79aa9, 0x3cd1871, + 0x23dddac, 0x90ab871, 0x71871a6, 0x9c58fb9, 0xa34910e, 0xf031f7f, + 0x81060e4, 0xb501eea, 0x791224e, 0xdb668ba }, + { 0x6a705bc, 0x240bbcb, 0x2d1865e, 0x7e76fbd, 0x2513641, 0x6e2cd02, + 0x46365c9, 0xe6c5225, 0xa5a01fb, 0xe46a8b8, 0xb67618b, 0x696fa7b, + 0x0db6792, 0x418b3b9, 0x7108b9c, 0x7204acd } + }, + { + { 0x8456b45, 0xb5a143b, 0xf53b4d9, 0x8a3ab25, 0xe13a570, 0xb112a58, + 0x81487d2, 0x613ca32, 0x3b1e7c9, 0x837d823, 0xd41e9d5, 0x592bade, + 0x5cd02f2, 0xdc1893a, 0x8972e23, 0x0879502 }, + { 0xcb76261, 0x7003c08, 0x332a5e0, 0x14bde9e, 0xcbbd78e, 0x14b2872, + 0xde238e8, 0x5594061, 0x067466c, 0xad12645, 0xf5e4952, 0xa8d0e64, + 0xc7f8d06, 0x5b44b82, 0xfb1b828, 0xb51bea8 } + }, + { + { 0x3f0dacc, 0xebad685, 0x1cbebbc, 0x5c31b8b, 0xfa5a2dc, 0x6746975, + 0x31d9faa, 0x2d95965, 0x00fc0e4, 0x343797d, 0x55fe01b, 0x38d821c, + 0x7323aa0, 0x0bfdb24, 0xf962a8e, 0x42613c4 }, + { 0xe134bc0, 0x599a211, 0x47a7084, 0x75fa4a1, 0x7f734b5, 0x6e71948, + 0x6dfca2b, 0xd5ced2d, 0x8aeabd2, 0x9fa0fdc, 0x12361da, 0x5e6b03f, + 0x5859fcf, 0xad23d31, 0x25a5fc8, 0x3120ef1 } + }, + { + { 0x8e9f638, 0x990ef62, 0x626a60c, 0xfdaa240, 0x2abddab, 0x4a3de20, + 0xd8872b2, 0xd5d10b7, 0x1ea5880, 0xa01b730, 0xa81b9d8, 0x481697f, + 0x3471ed8, 0x2984153, 0x292d37c, 0xefd73f8 }, + { 0x9994beb, 0xdda7626, 0x6a4f865, 0xa037703, 0xe5b47d5, 0xda992ec, + 0xe53edba, 0x912a427, 0x9264e45, 0x6467598, 0xaf71222, 0xd3b68c3, + 0x6dedc5f, 0x9d3436c, 0x076b2ad, 0x1e027af } + }, + { + { 0x4382f4a, 0xd56fca1, 0x8966b7b, 0x83712a4, 0xa4c9ddb, 0xd6b2cf5, + 0xf602875, 0xa66be29, 0x894f3d0, 0x70e4266, 0xb3195ca, 0x007d220, + 0x82c74d4, 0xba38d8f, 0xd975cbd, 0xdccc5fc }, + { 0xc88b38b, 0x03e1610, 0x52e0d8d, 0xeb9f9a1, 0xb646eb7, 0x6a57eca, + 0xc76b6c1, 0x161641f, 0xbd2e12b, 0xf9025ad, 0x5c0e26d, 0x87c74db, + 0xbfeca74, 0xed5cb51, 0xe34a08c, 0x603dfb6 } + }, + { + { 0xcb03307, 0xc4be728, 0xc2741cc, 0xde34c0e, 0xa74eb17, 0xe01db05, + 0x8905e4b, 0x1bfce0c, 0xd1b1826, 0xb18830a, 0xe87bbfb, 0xcacbb41, + 0xd2f1a79, 0x8696842, 0x08c83ea, 0xa80e5fb }, + { 0x3f1439c, 0xe48f163, 0xcd6987b, 0xc1d4108, 0xb751814, 0x05705c4, + 0xc1c622d, 0xa9bffd0, 0x46cd053, 0x23de4af, 0x39457c3, 0xf782f5e, + 0x5e5d243, 0x815276b, 0x6161ae3, 0x3132041 } + }, +}, +{ + { + { 0x77f2542, 0x2459661, 0x8372b25, 0x203be7e, 0xee2007b, 0xc7c9426, + 0x0621799, 0xc564138, 0xc28c3ce, 0xda56589, 0x7afc1e3, 0x13e8a7c, + 0xe352082, 0xdba81e9, 0x04435c7, 0xf430549 }, + { 0x691de4a, 0x4d26533, 0xfb777ab, 0x364408c, 0xeae7f88, 0xccdfb43, + 0xa525b11, 0xbc40f44, 0x3c60627, 0x8e112a5, 0xe17e696, 0x7f7c581, + 0x1ea774a, 0x0fd7878, 0x0b1f582, 0xd09e632 } + }, + { + { 0x70aab15, 0x44390bd, 0x889c3f2, 0x41112bc, 0xd685349, 0x6b02894, + 0x5584dfe, 0x7103001, 0x1ba7887, 0x373cb1b, 0x2a017c7, 0x53d286c, + 0x3c81fdc, 0x2ed0388, 0xfbcc6fc, 0x3bfc5e3 }, + { 0xfd6418d, 0xd38ac6f, 0xbfad89e, 0xc667e96, 0xeab4d66, 0x46f4f77, + 0x0911293, 0x194c04f, 0x68c48d5, 0x0fd09cf, 0x63cf7f4, 0x6f5b055, + 0xacd562f, 0x0c0a8c4, 0x36d965d, 0x94c1d83 } + }, + { + { 0xcaa127a, 0x94fc8f0, 0xd803690, 0xc762d5d, 0x1ebf0d3, 0x8bfdfd1, + 0x48eac50, 0xa98cdf2, 0x8b5ff10, 0x3d7365d, 0xc65b4de, 0x20dc29b, + 0x8ec7c68, 0x62ac28e, 0x90372d2, 0x7f5a132 }, + { 0x3246658, 0xf3d8a25, 0x9ac202a, 0xa4bebd3, 0x5cc1697, 0x078ede7, + 0xc8fc022, 0x5525800, 0x5fae77b, 0x302a802, 0x57917b6, 0x0180139, + 0x864bf55, 0x7c8806d, 0x12f06f1, 0x4e2d878 } + }, + { + { 0x3d66e88, 0x8d35118, 0xa91d02a, 0xfb861a1, 0x7850e5f, 0x8c27c2a, + 0xa5496f6, 0x9fd6399, 0x8080049, 0x52152ae, 0xfd1c2dc, 0x600e2ff, + 0xffe8b2e, 0xc75902a, 0xe03b175, 0x5c4d2cc }, + { 0x4f57e78, 0x8ad7c42, 0x1736f87, 0x77cf606, 0xf85038a, 0x2876012, + 0x1b97b95, 0xff32845, 0x392dfc8, 0x3cc6dd5, 0xa6f5075, 0x72f1363, + 0x71de894, 0x028ec44, 0x6f45a86, 0x7030f2f } + }, + { + { 0x9695817, 0x66400f5, 0xf20ea36, 0xeda0a7d, 0xd394992, 0x855be51, + 0x8336f62, 0x2d082c1, 0xf28c868, 0x30944dd, 0x0dc86d0, 0xfb5f853, + 0x564a0bd, 0x9562ae5, 0xb6b9b51, 0x1f7ea12 }, + { 0xd0a7148, 0x5bd74e0, 0xb91e572, 0x6c8247f, 0x47da498, 0x699aba5, + 0x1f7c814, 0xed82581, 0x62057b9, 0x434674b, 0x15c15b4, 0x8b4df5e, + 0xb110081, 0x2a97da1, 0x4c417fe, 0x2a96b0c } + }, + { + { 0x237639d, 0x4f75dfc, 0x1db7029, 0xe5ad6bc, 0xb3d28f7, 0xd43e06e, + 0xe447989, 0x89f3bb5, 0x01a1a6e, 0xc426a2c, 0x315878f, 0x33ea71c, + 0xb1b5705, 0x8a7784a, 0x77ca811, 0xa59e86e }, + { 0x36ae155, 0xddb133c, 0x0d51b42, 0x49f1d4c, 0x9d05519, 0x5508082, + 0x5291816, 0x20e23be, 0x67181ec, 0x35047ec, 0x7aad091, 0x6237dc4, + 0xe2e25a2, 0xa1d3ce1, 0x0d3db4c, 0x1de0522 } + }, + { + { 0xd9fd423, 0xe9a5e19, 0x9801e43, 0x0c2c3d0, 0x28df2da, 0x043c2dd, + 0xe1ad12a, 0x4eecab4, 0x9615aa5, 0x97e1797, 0xca7bb5e, 0xe57b879, + 0xcc92619, 0xa2a903c, 0xaa56e93, 0x5cef370 }, + { 0x7f3232c, 0xbef29fa, 0x2b7ad5c, 0x1cf35ed, 0x3b6077a, 0x35c4893, + 0x7a1d47d, 0xe065148, 0xce14572, 0xedb4673, 0x0b17629, 0xdc9e98c, + 0x9a02a5c, 0xef98ebe, 0x11d03c0, 0x1f772e3 } + }, + { + { 0x4608f72, 0xcbdbdcd, 0x5a13c6f, 0xb435223, 0x4bb3c21, 0xa6497f6, + 0x12c15c9, 0x3af2383, 0x6322d11, 0xfbbf4b3, 0xc641775, 0x520a5c6, + 0xe81e0e1, 0x18cd967, 0x3de3871, 0x980b2c6 }, + { 0x9ae44a2, 0xfa9db61, 0x176bc56, 0x0281dd2, 0x8a7f817, 0xfd03711, + 0x4129b30, 0x9c48545, 0x039626d, 0xb439648, 0xe4ada6b, 0x355050e, + 0x7f5d98c, 0xc9c16d6, 0x18c4d5e, 0xf53ccc3 } + }, +}, +{ + { + { 0x3ffb20b, 0x50ae942, 0x6865eb4, 0xa6c0b42, 0x09930f1, 0x4677f7d, + 0x4a16427, 0x742e0b6, 0xf976f9a, 0x521d18e, 0xa454749, 0x43ac9cf, + 0xc51f50d, 0xda3a91d, 0xad6f954, 0xf657029 }, + { 0x6b4f99a, 0xfe5f064, 0x63ad4ce, 0xd92a5d9, 0x2e0e081, 0xfcb5509, + 0x8d8a858, 0xadc85ab, 0x0632f0f, 0x8e9b966, 0x8d7216d, 0xe7a4f16, + 0x59c3b99, 0x00a4cc5, 0xba09dc1, 0xed6d0bd } + }, + { + { 0x1621beb, 0x7236d14, 0xbc7ca95, 0x1751fd4, 0x2f5319c, 0xaa619d1, + 0x4e9316f, 0xfc2b15b, 0x9fd4d33, 0x2d1a906, 0x8ced829, 0x28c3bac, + 0x1dd998f, 0xf2efab5, 0x3b149ed, 0x2c13330 }, + { 0xf601ac6, 0x65237c9, 0x07d6a45, 0xb54dd65, 0xfb1a4cf, 0xa1ce391, + 0x115f67e, 0x2957533, 0x465279b, 0x6456da8, 0xa993e02, 0x02890aa, + 0xb7175e4, 0x6891853, 0x0f3e59b, 0x3fda203 } + }, + { + { 0xd8c6e0b, 0xe99fe12, 0x5341c56, 0x7cb07ff, 0xdf77b24, 0xc292c7b, + 0xca29906, 0xf52dfd0, 0x772f02c, 0x4a6aa26, 0xe1bbd09, 0x26f7684, + 0xee7c2a8, 0xec56b2b, 0xad4a312, 0x67709e6 }, + { 0xc570263, 0x99c57b2, 0x2faafae, 0xeb0100b, 0xff25eca, 0x980d5d1, + 0x82cf936, 0xace35e6, 0x44679ed, 0x5a82ce5, 0x074b81e, 0x5c76a41, + 0xa00abb1, 0xf36fa43, 0x04ffb2d, 0x0642819 } + }, + { + { 0x04bdd28, 0x68f6bc8, 0xb5dc7ad, 0xc311d96, 0xed32e45, 0xff0d646, + 0xe0f712d, 0xaf3cdc6, 0xd483861, 0xd4508e9, 0x0e1c277, 0xb624be5, + 0xc5dd841, 0xc510275, 0x298dc02, 0x451c5c3 }, + { 0xdd34d6b, 0xf87d479, 0xdd06a38, 0xda7f293, 0xb699e9f, 0x575e129, + 0x215b2cc, 0x79e5fb2, 0x657e690, 0xd280028, 0xe702a71, 0x7fecd09, + 0xfa13677, 0x85160ab, 0xce65f64, 0x5de3427 } + }, + { + { 0xe8fff38, 0x84e4bf6, 0xb358b1c, 0x16f3725, 0x3b472a5, 0x360371c, + 0x52f217a, 0xe64c061, 0x0501241, 0x8e67379, 0xab2dd96, 0x88e81d6, + 0x1385604, 0xf3e218a, 0xe84184d, 0x9736caf }, + { 0xdbb93a3, 0xb55a043, 0x9301088, 0x335088f, 0xb2a4959, 0xcea7a2d, + 0xb882c33, 0x48e5d4a, 0xad46179, 0x114f09b, 0xb446576, 0x4416467, + 0x34c6c2f, 0x01cb23e, 0xa02db8a, 0xddebf04 } + }, + { + { 0x9bde8a1, 0x36d60cc, 0x676e4ad, 0x20fd2f2, 0x8936581, 0xebdcfb7, + 0xdbfc2c3, 0x245d0d5, 0xa9f82e5, 0x104c62c, 0xd654d9b, 0x7387457, + 0xae7f10e, 0xe966777, 0x1d8e582, 0xefeb16f }, + { 0x70364b5, 0x4faf4f1, 0xd612472, 0x0e1ab58, 0xfed6085, 0x11bbfe7, + 0xa59a09a, 0xb360a14, 0x722fdb6, 0x61d96e9, 0x94068bd, 0x16a12f1, + 0xf73c2be, 0x225bf07, 0xc8bd24e, 0x1e64665 } + }, + { + { 0x3698c75, 0x27a478a, 0x6202aa2, 0x778ccd3, 0x8d87f1f, 0x0149c63, + 0x784edae, 0xa660e5f, 0x82adfa8, 0xe0d4d2f, 0x1ba1f9d, 0xf512dd6, + 0x6245c58, 0x90cfed9, 0x18b53dd, 0x6c3a548 }, + { 0xbdc094f, 0x833f70c, 0xb1514e7, 0xa5f26f5, 0x1c8cf13, 0x93e7cf5, + 0x186ec43, 0x1436601, 0xe78170a, 0x81924ac, 0x8694368, 0xcc880a0, + 0x0b62cbb, 0x2dfa955, 0x96b4a2c, 0x0bc6aa4 } + }, + { + { 0x3561aa2, 0x5157a7e, 0x8645c1e, 0x525c500, 0xce7cbb3, 0x22feb4e, + 0xc89a58b, 0x36d0d25, 0xc9bde9c, 0x43131f7, 0x881f731, 0x74afdda, + 0x7c8e36a, 0x99ab87c, 0xc1d4fb2, 0xf07a476 }, + { 0xbebc606, 0x1b82056, 0xfcf089f, 0x95a1e5a, 0x2b55d5c, 0xc5bccfa, + 0x00eb0b1, 0x8fbc18e, 0x9efb483, 0x93a06fe, 0x2d74c57, 0xcafd725, + 0x3de4350, 0xc7518f0, 0xc6fd762, 0x9a719bf } + }, +}, +{ + { + { 0x2362087, 0x5ee0d83, 0x0b167e8, 0x7f2c0d7, 0x5e0e865, 0xb732789, + 0x98c4e65, 0xef5b2e8, 0x8fe9cc1, 0x222797d, 0x82d1e15, 0xfe6d73e, + 0xf62dc4b, 0xc7c0e9c, 0x937ceda, 0x962acfe }, + { 0xc1e85c7, 0xd763711, 0x2836978, 0x8f2dbbc, 0x8c44e98, 0xbadc055, + 0xa3e93f8, 0xed63eab, 0x41b55c7, 0x807e857, 0x6d1207b, 0xd51ae5e, + 0x39d541b, 0xa0ef9a6, 0xa0c56a5, 0x58855f9 } + }, + { + { 0x213091d, 0x7d88eaa, 0x45b6a0d, 0xcbdfee7, 0x4f5e077, 0x826a012, + 0x90f1e4c, 0xb04fc13, 0xaea69aa, 0x1961ac3, 0xd5bb63e, 0x3afb719, + 0x4ac7e5c, 0x2a37837, 0xc50ca45, 0x78efcc1 }, + { 0xb8abdef, 0x346e8f0, 0x88095d0, 0x27e3dbd, 0xffc6c22, 0x56d3379, + 0xfa4b291, 0x67d416c, 0x3b1b373, 0xc3baaf6, 0xdf73bae, 0x0184e1f, + 0x9167528, 0x38ae8f7, 0x35d6297, 0x7329d4c } + }, + { + { 0xf568c52, 0x45d2ac9, 0x9808593, 0x5134814, 0x31b7ed8, 0x0c92d83, + 0x0876ecd, 0x921327a, 0x052736a, 0xf752d75, 0xbc6b837, 0x7b56487, + 0xa23b4cc, 0x6b1a320, 0xec0d665, 0x1983937 }, + { 0x08554ab, 0x2c3017c, 0x366e87f, 0x40ad955, 0x8ed7f02, 0x88c4edf, + 0x3cc5e6d, 0x64a7db1, 0x2dc978b, 0x5ac91fa, 0x925d2a2, 0x016a20d, + 0xabb57b4, 0x3604dfe, 0xd7e2e85, 0xc3683ec } + }, + { + { 0x4c0c6d0, 0xc47150a, 0xe22adcf, 0x30af45e, 0x022ea4b, 0x39b5acb, + 0x77203b5, 0xfbe3185, 0x6fd9b59, 0xe5aaa34, 0xdd1c8dc, 0x0062c90, + 0x54049ac, 0xcf113f3, 0x63a31b5, 0xd8fba4d }, + { 0x1056a69, 0x73b5488, 0xd780bda, 0x3be6cbc, 0x30ba2b9, 0x5776ec2, + 0x8e8d6f7, 0xbe883cf, 0x5c2be6f, 0x64efe94, 0xf1ade8d, 0x064f704, + 0x743110e, 0x41cfd17, 0x4c20abe, 0xaac9411 } + }, + { + { 0xf1c1468, 0x91f9192, 0x4563e13, 0x8176e74, 0x0bda15d, 0xa48b5f9, + 0xda42af6, 0x2a085ae, 0x425c018, 0xfd38ab2, 0x08abafb, 0x2884ba4, + 0xcbd091d, 0x356f318, 0x817871b, 0x454e450 }, + { 0x8ada531, 0xe080e81, 0x3152ba8, 0xa40f1eb, 0x0c38eb1, 0x051049f, + 0xbd45003, 0x37e4bb3, 0x54a01e5, 0x6d09804, 0xeeb824a, 0x6de932f, + 0xdc93481, 0xccdef37, 0x93a05e8, 0x8633e07 } + }, + { + { 0x034675c, 0xbe94256, 0x08db789, 0x376c01d, 0x9af1b6b, 0x8707ee7, + 0x11bfbac, 0x633b3ef, 0xd06db60, 0x694f33f, 0xbb13407, 0x2a68bfc, + 0xda27c3a, 0x1c860c9, 0xd701ac3, 0xbca16de }, + { 0xc59ffd0, 0x2b76cfa, 0x54d718d, 0xf9a1165, 0x67f0878, 0xf86a1db, + 0xaf34e85, 0xe313e05, 0x3343159, 0xa188811, 0x0bb7ed1, 0xdbe4c3f, + 0x0c732bc, 0x73b67e8, 0xe74110e, 0xa4e1c87 } + }, + { + { 0x5c6770c, 0xce1106b, 0x5c0bcb7, 0x422c70b, 0x8195e7f, 0x32a3990, + 0x1ccd4aa, 0xa24968d, 0x720e557, 0x8f08ecf, 0x54bcc81, 0x5da10a4, + 0x6cd846e, 0x9d3c73b, 0x368d065, 0xaeb12c7 }, + { 0xcf9fd1b, 0x2110859, 0xee2bd6d, 0xd2a4801, 0xe9466ac, 0x376e556, + 0x3b5aa35, 0x767803b, 0xb8a89ba, 0x343f842, 0x6726bbf, 0x3263cc1, + 0x25871b0, 0x26caf17, 0x41b8578, 0xef66ad6 } + }, + { + { 0x638068c, 0xc9f2249, 0x1ccf9af, 0x96d282c, 0x69b435a, 0x71df30c, + 0xcb9d5c9, 0x88c943a, 0x2a8f378, 0xbf98ef1, 0x114c6ff, 0xffc1824, + 0xd52e8c7, 0xda3ad2c, 0x1afcb59, 0xf1222bc }, + { 0x0ee334a, 0x459e94b, 0x421933a, 0xd4477b8, 0xa1e401e, 0x60fb7b0, + 0x0d1e330, 0xfde6e82, 0x3233fde, 0xcecfe9b, 0x2e93523, 0x09ec466, + 0x30775b9, 0xa5ba649, 0xadf80f2, 0xcc397e5 } + }, +}, +{ + { + { 0x4ddc8a8, 0x2fe182d, 0xac056bf, 0x88d6e79, 0x0e41e4e, 0xc3ff2d1, + 0x2c3679f, 0x32ec7f9, 0x4e61051, 0x3561f09, 0x6c6250a, 0x4553f5a, + 0xdd25c5b, 0x2b765ef, 0x6a1cd7f, 0xe3a40a2 }, + { 0x5d821dd, 0xb27309b, 0xc2c17ca, 0x950fb8d, 0x8fb0d4c, 0xfeed015, + 0xf550179, 0x762c479, 0xe095840, 0x306cf44, 0xd379e66, 0x84b413a, + 0xbb2e4f1, 0xd6e5d5a, 0x94b085d, 0x8bc12b7 } + }, + { + { 0x04b5532, 0xc0d4cb8, 0xb9940a6, 0x7a31525, 0x68c69d1, 0x010e7dd, + 0x2a18c35, 0xd81f29d, 0x3f11e73, 0x08ae770, 0x6e55106, 0x5358f87, + 0xc960ef5, 0x299e8ca, 0xacfc8dc, 0x89a6fb4 }, + { 0x6dc7d4a, 0x5996a40, 0xe51b96e, 0x21e5112, 0x09a202b, 0x95b8c3d, + 0xd441f1f, 0x306ab0f, 0x98d4245, 0x2834fed, 0xd0abbde, 0xc29c387, + 0xb805c15, 0xf6a9bf1, 0xc4e458d, 0x602f4f8 } + }, + { + { 0xe5a893a, 0xf041486, 0x8934327, 0x53b891d, 0x4000758, 0x11e000d, + 0x662bad9, 0xa4ccde8, 0xb9a1b64, 0xe34d3ed, 0x84e7a6d, 0x72d9675, + 0x6627be4, 0x773da2f, 0xe835ae3, 0xa11c946 }, + { 0x650bc15, 0x02e8203, 0xe58b78d, 0x2d35936, 0xf21a3cc, 0xe9cfbe8, + 0x1049222, 0x55ad831, 0x38fff47, 0xbf99de4, 0x3831db5, 0xebbfd80, + 0xaf2af42, 0xe990636, 0xb7f5a0e, 0xc26ae52 } + }, + { + { 0xfa8f846, 0xb5d85b1, 0xb3b1455, 0x4166489, 0xd36a305, 0x768260d, + 0x4ff5645, 0xc6a8235, 0xd6e93e5, 0xd241cd8, 0xa406e74, 0xeed9aa1, + 0x5f600d9, 0x9e96ab0, 0x6eca2a1, 0xa26b8b5 }, + { 0xd705aef, 0x78321cf, 0xc0161ec, 0xc4fb6b3, 0x5199cf1, 0xdc32441, + 0xd0a5067, 0x33627d0, 0x15143ee, 0x13490cb, 0x85b4f44, 0x77e0ede, + 0x394b165, 0x904f12e, 0xefab32d, 0x90f50f5 } + }, + { + { 0xbc2de96, 0x4aa0a16, 0xaa9c12b, 0x172596a, 0x60e8a29, 0xd512e1e, + 0xf637e83, 0x77d35c1, 0xd2aae0b, 0xbb0d141, 0x8c03738, 0x8a878a5, + 0xab0e525, 0x6d24c01, 0xf760887, 0xb7d3136 }, + { 0x3f91b7c, 0xdbc3f8f, 0xa8722c0, 0xe7b4bca, 0xda0ae65, 0x3286a91, + 0x225b084, 0x8372274, 0xae1886c, 0x5884cd5, 0x3a23cf7, 0xb4e63ef, + 0xf2dd0da, 0xfe5f202, 0x653916c, 0x951fac9 } + }, + { + { 0x854fa4e, 0x05e2e8f, 0x1edaf10, 0xf411f94, 0xa0a928d, 0x26cc562, + 0x4abce65, 0x78fd34e, 0x98a32e2, 0x1d87609, 0x4c37518, 0x85dc76f, + 0x00e8021, 0xdcaeef5, 0x4e9b2a5, 0x7fcb2f8 }, + { 0xf382c06, 0x9eba91e, 0x24cae53, 0x2052e85, 0xf5c1519, 0x617336e, + 0xb4e632b, 0xf1546d5, 0xd7b8ffd, 0xa9edc81, 0x29ab68c, 0xdb2914f, + 0xdebbaba, 0xe805070, 0xc3b719e, 0x775e53b } + }, + { + { 0x065256a, 0xa40e294, 0x8fb031a, 0x9f11386, 0x059667c, 0xac03af8, + 0x0475f58, 0x432eb3a, 0x01faad0, 0x22332bf, 0xbc57a11, 0xc8132e9, + 0x3bc3f8b, 0x27d5a17, 0x930bf3e, 0x5471fc6 }, + { 0xe6bff40, 0xba28bc0, 0x555e564, 0x198d57e, 0x9c65b8f, 0x13ce831, + 0x5681b51, 0xb0a5c9d, 0xdeb9e11, 0x467588b, 0xbb4250b, 0xf1891a7, + 0xd12b433, 0x10b938b, 0x24dcda4, 0x0b8c802 } + }, + { + { 0xcf332d3, 0xc428703, 0xf2a5b98, 0x9d0053c, 0x7838a15, 0x4e4c620, + 0xfbf8a43, 0x2e92919, 0x21cd9a5, 0x39ad524, 0x1561588, 0x584ed6c, + 0x17a95c8, 0x20af305, 0xb70e1c8, 0xa223077 }, + { 0x2fa4871, 0x679cfea, 0xac633c7, 0x54f2a46, 0x4cdc5f1, 0x6030651, + 0x75a1dc7, 0xc4facda, 0x2d07d19, 0x710a288, 0x6b44992, 0xd55864e, + 0x454c5b2, 0x44d4b6c, 0x72f9981, 0x2855d28 } + }, +}, +{ + { + { 0xc7b0674, 0x4071b3e, 0xf8794d5, 0x800eb14, 0xbe6783e, 0x70573af, + 0x7785901, 0xafaa440, 0x405f32c, 0x112d2a1, 0x169b3e2, 0x3761a52, + 0x842a366, 0xe168b31, 0x9bf4734, 0x5bc322f }, + { 0x976c4a0, 0x36ef240, 0xfea4e64, 0x066f3d6, 0xa989e57, 0x0e954bd, + 0xf9466e4, 0xe36ef5e, 0xbeb9226, 0x6bb615a, 0x3d5a2ca, 0x5571e5f, + 0x4897a86, 0xa86efe2, 0x28a9f77, 0xed7e9cf } + }, + { + { 0x1f82c68, 0xdf10c97, 0x3b597e6, 0x796ba1e, 0xe718cbf, 0x1ac77ec, + 0x410eac8, 0xc8175bb, 0xbc555ef, 0x0cdf9a1, 0x7524e05, 0x6b889f1, + 0xae26d82, 0x6bf1e61, 0xd2e97d9, 0xb3f6ad5 }, + { 0xf226487, 0x94dcff9, 0xbe03dde, 0x60e6356, 0x6a3dd7d, 0xda1f93b, + 0x79ca90c, 0xf1be721, 0x1e6bce5, 0x05ed313, 0xd48af3e, 0xcf50908, + 0x61e554f, 0x3b0e85c, 0xa2778d3, 0xfe7e35b } + }, + { + { 0x75ac5a9, 0x42c5032, 0xda062c2, 0xa66a66d, 0xcaa7023, 0xa4f4f82, + 0x64b4f86, 0x489d476, 0x97311ad, 0x10b1088, 0x177b2ec, 0x55dd637, + 0x9a267b1, 0xa5ccff0, 0xff327b0, 0xf07690b }, + { 0x2250cd2, 0x39162ed, 0x8b255f1, 0x1426de0, 0x1bdd731, 0xf227afd, + 0xfa4c844, 0x78f8a36, 0x157379c, 0x267a211, 0xcc04acb, 0x3f05f92, + 0xfc69cae, 0x374496c, 0x16ebfec, 0xbf2c5d0 } + }, + { + { 0xd0518d1, 0x605418b, 0x9e1cbc6, 0x3237f80, 0x286c019, 0x37a7005, + 0xb15af0b, 0xf1fb0e0, 0xaa853c0, 0xfc3b97c, 0xe6beba2, 0x1f48bd0, + 0xe6a72f1, 0x8e5d7c5, 0x26ebf0c, 0x575e66d }, + { 0x62eae3d, 0x0994776, 0x96c9c65, 0x53f074f, 0xb81bade, 0x6cfbfdb, + 0x3fed7d1, 0x98b4efe, 0x38c3382, 0xdaa1123, 0x47b8ec6, 0xdf88b73, + 0x9504a4f, 0x9b0fe4b, 0xf30c1c3, 0x2e7df4c } + }, + { + { 0x2fc1833, 0x25380cb, 0x18d62de, 0xb8e248c, 0xd82f9db, 0x91c8f59, + 0x2444750, 0x5ec2b20, 0x66b6f74, 0x3f3a1f7, 0xdd7d14d, 0x0180aa9, + 0x2956b9c, 0xd0a342d, 0x7139873, 0x26e910e }, + { 0x139e23d, 0x2261dc4, 0xb8343dd, 0x7edb181, 0xb4038dd, 0xfcf1073, + 0xa3bfea3, 0x88870ef, 0x64a263e, 0x4e98ba9, 0x70811f5, 0x3c6e5dc, + 0xf86055d, 0x17d28f5, 0x66e4199, 0xca9c276 } + }, + { + { 0x964ef8c, 0x0b2d8bd, 0x88e2ba6, 0x5a99b85, 0x04498ce, 0x9e927b2, + 0x756eb25, 0x9ff20c5, 0x3f27736, 0x97cc27b, 0x4729583, 0xf32dd6d, + 0x0381a94, 0xbdc2658, 0xef2c06f, 0x70fef15 }, + { 0x49252cc, 0x50a6191, 0x236b4b9, 0x9eb4a14, 0x8e00f78, 0x9b1b215, + 0x6ea9c23, 0x27add36, 0xc3a8e79, 0xef61763, 0xd82ce56, 0xed4542f, + 0x0caed75, 0xa8737e7, 0xd452d76, 0xeca0ac2 } + }, + { + { 0x3d082d0, 0x20c0779, 0xc9e9f3b, 0x6e3ce64, 0x75a195f, 0xb3a4dce, + 0xbdd9f24, 0x3a3c305, 0x8688942, 0xe2545c8, 0x080f32b, 0xa463c82, + 0x42686b8, 0x4429748, 0x7213866, 0xf50e20d }, + { 0x3826e74, 0x265ac52, 0x228e8ec, 0x26fba57, 0xe6b3ed8, 0x8a1e1db, + 0xf0fe65a, 0x7c7b278, 0xc395234, 0x9a6df23, 0x0b0f114, 0x9956206, + 0xef90837, 0x440c8c4, 0x3645f65, 0x21ad22a } + }, + { + { 0xedd31b2, 0x1e023a6, 0x9ff8668, 0xf76d145, 0x17b45c8, 0x9707056, + 0x1e88e37, 0x0612078, 0x922faac, 0x85c51c8, 0x22756d9, 0x4df392e, + 0xa03c98e, 0x8907fd0, 0x52ea51c, 0x626f46a }, + { 0x486c8a2, 0xf8f766a, 0x88ed18c, 0x8c499a2, 0x3c4f0de, 0x44d2dc6, + 0x6f2a0b6, 0x47dde68, 0x4a973fd, 0x9a655f8, 0x786ac80, 0x3e7124e, + 0xe8a0574, 0x699e61c, 0x31cdd0d, 0xdf0ba9a } + }, +}, +{ + { + { 0xd73e69b, 0x76270ad, 0xc67d38a, 0x991120f, 0x9469f0c, 0x7be5830, + 0x7db40ac, 0x93aba59, 0x822fc08, 0x2b707bc, 0x69551cd, 0x4199fc0, + 0xf367324, 0x38deed4, 0x2228787, 0xca518e1 }, + { 0xd9a9277, 0x72f1bef, 0xe49ae90, 0x57d4aab, 0xdb23478, 0x13810d5, + 0x9b4b77f, 0x2a8b780, 0x1b4e004, 0xb542f4e, 0x3ec77f0, 0x4080fd0, + 0xcec6596, 0xb49e9fe, 0x3f16037, 0x20338d3 } + }, + { + { 0x53554b0, 0x4adcdae, 0xe04c4db, 0xfea4906, 0x7748233, 0x0808bec, + 0x47148d7, 0xde7477c, 0x03da38c, 0xdd9124c, 0x25ee8e9, 0x6b25031, + 0xb0d6161, 0xae67399, 0x82203b6, 0x70c4acd }, + { 0xd31dae8, 0x9683916, 0x1ac7f69, 0x3477503, 0x988e4ad, 0x9553153, + 0x53a15e1, 0xb58f411, 0x92ba2dd, 0xb65a2d4, 0xa90169c, 0x7c3efb1, + 0x6b1747d, 0x210f45e, 0xcff488d, 0x16e8d1b } + }, + { + { 0x9d703db, 0x252adf8, 0xfdfeb39, 0x259ac1d, 0x115e806, 0x7faf6af, + 0xc1aff21, 0x7aaefd6, 0x7c0113d, 0x8054210, 0xe19b4b1, 0x481f1a5, + 0xfcc8c61, 0x7c17d43, 0xbb0bbbe, 0x8b04452 }, + { 0x4cebae1, 0xe51e5f5, 0x56a414c, 0x05341ba, 0x7fb8a30, 0x0083a2c, + 0x77f4952, 0xb4663f2, 0x4bb0074, 0xce72eec, 0xa3584d1, 0x74fdd66, + 0xb02e076, 0x6b9e58e, 0x3b961f4, 0x5be45d5 } + }, + { + { 0x1ab2e0b, 0xc7474f3, 0xf4bf454, 0x2838ccb, 0xf3c3eac, 0x634392e, + 0x137602b, 0x440e40a, 0xd1ae8e3, 0xeea67e9, 0x77e221e, 0xafdf93a, + 0x2719a10, 0x3c9f3da, 0x32c8256, 0x466ecef }, + { 0xf9c432f, 0x1061c19, 0xb1c7d98, 0xa1332d9, 0xa425c2c, 0xbc735f2, + 0x4b1bccb, 0x1429cdf, 0x6bbb5f9, 0x77b42a1, 0x5955ae4, 0x30078e3, + 0x21cc315, 0x8acd777, 0xe86fa99, 0xaa90d5f } + }, + { + { 0x721115a, 0xfcfd460, 0x08269b8, 0x6a7de3e, 0x96dd47e, 0xe5964a6, + 0x8dca975, 0x6717cd5, 0x98b149e, 0x7ea4ebe, 0xb7b8057, 0x6f894d5, + 0x7f30e31, 0xbd6f960, 0x23df092, 0x61ca453 }, + { 0x9d782f3, 0x32241f9, 0x2abfae2, 0x55173b0, 0xd15bbbd, 0x0abe0ed, + 0xb438abb, 0xb6d3c0a, 0x9ffa20b, 0x62fb467, 0xd31560a, 0x30926b5, + 0x2a0aa6d, 0x44bf27c, 0x1a4cb97, 0xf747313 } + }, + { + { 0xb0535de, 0xa2f6c0d, 0xc855166, 0xcb02ae1, 0xb3422f0, 0xc699e6b, + 0x281ba8a, 0x774febe, 0xffabcc7, 0x1d9d24f, 0xfe12ba5, 0x0b31ba1, + 0x13d0af7, 0x4c86803, 0x2f47160, 0x90640d3 }, + { 0x5876603, 0xa0c4bf4, 0x950ab08, 0x717f6fa, 0xa710de8, 0xf12bb53, + 0x6a88f50, 0xc500c61, 0x2645351, 0x0070f99, 0x2446893, 0x57aab5d, + 0xb68f657, 0xd553fa8, 0x693c55d, 0xe8537c1 } + }, + { + { 0x7fc7684, 0x58e86eb, 0xbfc73a9, 0xdf330f7, 0xcc11936, 0x41e337d, + 0x6e35759, 0x36d9200, 0x3500d8b, 0x0132703, 0x9483354, 0xfa68405, + 0x667851b, 0xc8f2980, 0x18296b0, 0x538ec89 }, + { 0xcff55f9, 0xa2a2c4f, 0x60d20bd, 0xb260d4d, 0xd9cc59f, 0x3ed576f, + 0xd514fcc, 0x4ed8c64, 0xc22b315, 0x37ebfb2, 0x94c212c, 0xca67a36, + 0x3a1795e, 0x4f8e08c, 0x4e7261f, 0x498f926 } + }, + { + { 0xc59b3d4, 0xfea7382, 0x3f2925f, 0xb9942ed, 0x8ea77e8, 0xe4b00dc, + 0x3cab02e, 0x74a18ec, 0xef16d0b, 0xbbbb752, 0xffab032, 0x639da4f, + 0x3aa30f0, 0xc371a4a, 0xcaa175b, 0x8e26b22 }, + { 0x7e2b62e, 0x94e4156, 0x25a794c, 0x7cceea6, 0x479f015, 0x931d2f4, + 0x90b25b2, 0x946183d, 0x68a2807, 0x1504e97, 0xfa49ddd, 0xa7577d3, + 0xdd48699, 0x24fc87e, 0x3d7d99c, 0x9edefd6 } + }, +}, +{ + { + { 0x0f0b450, 0x0508b34, 0xc36f7f4, 0xe0069a5, 0x2a5a761, 0x2655664, + 0x848e04d, 0x0193fd8, 0x73fe2e7, 0xc108cf5, 0xfd787d4, 0x05eb0ec, + 0xff28985, 0x1555ccb, 0x651b995, 0xb5af09f }, + { 0xe1134be, 0x167d72c, 0x57c669a, 0xd6d98bf, 0x6dd76fa, 0x40fb716, + 0x2a41b31, 0xeabbf20, 0x09b75b0, 0x300ff0e, 0xd9a0c1e, 0x32b6fad, + 0x65a80e0, 0x8051883, 0x32110fe, 0x8bef693 } + }, + { + { 0xbef47d4, 0x637802f, 0x2d16eaa, 0xfac114b, 0x0415644, 0x7b3f3ab, + 0x2dd895b, 0x17ab8d1, 0x87195f3, 0x271b7fe, 0xa71f65f, 0xa3f867e, + 0xc80583a, 0x39ba40c, 0x56e1fcc, 0x6db0672 }, + { 0x06662a8, 0x4feab4e, 0xc74bd46, 0xc857415, 0x732b126, 0x18032ed, + 0x7a099ea, 0x87c8aea, 0x36fe0a8, 0xb4a7535, 0x27673f6, 0x33a98da, + 0x2b8e549, 0x3e40c02, 0x9a4c587, 0x2def1af } + }, + { + { 0xa8c9ad9, 0x9618b68, 0x49defda, 0xd70b4aa, 0x5f788ef, 0xae8b138, + 0xdd523f4, 0x87c3542, 0x5c5b004, 0xe42c705, 0xfa7df57, 0x6303360, + 0x5f6d068, 0x33e27a7, 0x8ff331a, 0x9b3268e }, + { 0x23ee0c3, 0x845cc96, 0xac80084, 0x003af70, 0x530c41d, 0x6a9f931, + 0xbb127f0, 0xa1d7051, 0xca36245, 0x642ce05, 0x0323ee9, 0xc34205b, + 0xb7b3513, 0x7cc8912, 0x076cbdb, 0x6252cc8 } + }, + { + { 0x7089522, 0x10e68a0, 0x58fc658, 0x36c1361, 0x74723a4, 0x490397d, + 0x519d56c, 0x42692c0, 0xf1ff235, 0x69d251b, 0xc2cbf37, 0xe689d03, + 0x825b7f4, 0xf04ceba, 0x2281c2e, 0xd6b9bee }, + { 0xe0043ab, 0xc52ef3f, 0xd1d1be8, 0x351bf28, 0x0f18a5a, 0x277615f, + 0x5d6800f, 0x31f717f, 0xab922e2, 0xf5fb82d, 0x2d6ae43, 0x99aee2f, + 0xc63b982, 0x42477fe, 0xa594a01, 0x904aeb1 } + }, + { + { 0xeb39974, 0xaa82174, 0x95e6aa0, 0xbc38e61, 0x25c0675, 0x6a3df8a, + 0xffbe739, 0xf324203, 0xa3f0649, 0xfa5a0b4, 0x7a7a6b8, 0x79c8732, + 0x40ad3f5, 0xeb65ecd, 0xe4e45c5, 0x718d416 }, + { 0xe2326fd, 0x029dbf4, 0xe7942f0, 0x0c63416, 0x6f4e678, 0x6d0c728, + 0xa138601, 0x59f0b10, 0x8d92ea9, 0x8a1d978, 0xc22eca5, 0x9f8d712, + 0x7b6b96b, 0x7397044, 0xe6fb955, 0xa2d49ee } + }, + { + { 0xbf14a19, 0x249f900, 0x63a8cd2, 0xd3522da, 0x86964d2, 0x28a32f3, + 0xc1fa743, 0xacf712b, 0x0bb94d3, 0x98a9bfc, 0xbc06824, 0x318ece1, + 0x4fce7f0, 0xfc47675, 0xe4135b7, 0x19caec9 }, + { 0xc6817bb, 0x6de68a8, 0xf3b6d89, 0x7121960, 0xf5a818e, 0xa7d4261, + 0x9157455, 0x0c0ba51, 0x450d5ff, 0x78b6acf, 0x4e8649a, 0x198b493, + 0xfd05da3, 0x0941a3c, 0xdb55951, 0x264ea4a } + }, + { + { 0x46e5a31, 0xcfee91c, 0xfff7366, 0x47b6806, 0x5df849d, 0xdb14be4, + 0xac66cc7, 0x3c5e22b, 0xa5f4769, 0x7f3f284, 0x383be36, 0x4e00815, + 0x8072b0b, 0x39a9f0b, 0xc7eadd6, 0x9887cd5 }, + { 0xb659511, 0x7dd8f05, 0xd2e1cb9, 0x15c796d, 0x0d31345, 0xe5edb0c, + 0x6939c60, 0x2025df0, 0xbf15de1, 0x6314c08, 0x04c7fb5, 0x03c1548, + 0xbb5d3ed, 0x413337f, 0x477e983, 0xfc20b40 } + }, + { + { 0x5db0ef9, 0x7f96880, 0xe9c2a70, 0x05562de, 0x7dae133, 0x071e5bc, + 0x237fc4a, 0xa8cdd12, 0x4ea492b, 0x6d565e7, 0x381ee52, 0xa17cf94, + 0x9f5c546, 0x6ab8a4e, 0x40288ef, 0xbb642f3 }, + { 0x5df5c2d, 0x64e5921, 0xbb906f4, 0x43696e3, 0x74ae46c, 0x73a841a, + 0xc506b8a, 0xe264883, 0xa1be548, 0x9542e1a, 0x5e81b4a, 0x8938539, + 0xeaca6ce, 0x5642cfa, 0x806e0f9, 0xed8077b } + }, +}, +{ + { + { 0x7e13597, 0x1c776c4, 0x9e584fd, 0x0ec8b28, 0xb8b61e8, 0x0bb6043, + 0x9cd835b, 0xdcc1748, 0x39fef9a, 0x493e6ac, 0xd133e17, 0xb44eb34, + 0x71cb6f9, 0xfebcd00, 0xd20eff2, 0xe6cf543 }, + { 0x0a004c7, 0xf265cad, 0xd35cc12, 0x9b06c9d, 0xcb4ea53, 0x769f985, + 0x0993434, 0x29160a2, 0x8d939c4, 0xdf8dd10, 0x6711e2f, 0xefa177c, + 0xcd7a2cd, 0x1695790, 0x77f6642, 0x38da3d7 } + }, + { + { 0x6307b74, 0x9bfcfd9, 0xbfdabc3, 0xc26a36d, 0x4abe28e, 0x9341be0, + 0x73d1387, 0xdb20b52, 0x3d1949c, 0xf8d229c, 0xb8b3a41, 0xf1e0afe, + 0xed565d0, 0x29c60df, 0x8b43b2c, 0x6930bb5 }, + { 0xfc0718f, 0x1d76527, 0x1f67189, 0xdb98143, 0x51f32cc, 0x0c62f64, + 0x8bd35e5, 0x70a6626, 0xc1cece7, 0x1725641, 0xf96f4a4, 0x7f130a8, + 0xf06ee98, 0x72319e9, 0x67bf9b2, 0x215b738 } + }, + { + { 0x0aaddd7, 0x8d1bec2, 0xb8be4f9, 0xfb8b95b, 0xfde1026, 0xeac193e, + 0x9d5860c, 0xa5edea7, 0x44280d3, 0x4adbaea, 0x38f4798, 0xce8b670, + 0xec30dea, 0x914c107, 0x000776b, 0xbdc5cf7 }, + { 0xa206a13, 0xb6fd7d1, 0xdae986e, 0x9941eba, 0x1f1caaa, 0x76c27a8, + 0x3f108b4, 0x6967c12, 0x4aea2d0, 0x6f11528, 0x144ddac, 0x9bb4319, + 0xc8ec6fc, 0x1a4d3ea, 0xbf37420, 0xfe4b0b8 } + }, + { + { 0xec0ac6f, 0x5d9a4a1, 0xfc7c80d, 0x84b79f2, 0xc14fac3, 0x64222f7, + 0xc23b3f2, 0xdd9e039, 0xea956bb, 0x4a84abd, 0xebe09dc, 0x370dcba, + 0xe0eaf82, 0x79a9ea8, 0xaee375f, 0x4cfb60a }, + { 0x9106827, 0x6a10dbf, 0x43f305b, 0xa3ba5cf, 0xc1bb083, 0x481b885, + 0xb3117b1, 0x2f52380, 0xddd6791, 0x0066122, 0x63bace3, 0x4f8923e, + 0xecb88d4, 0x5c5f499, 0x3bac146, 0xfdc780a } + }, + { + { 0x7ba1f71, 0x34b70ae, 0x45bd184, 0x9091829, 0xe707313, 0x3b39778, + 0x6164e91, 0xdeefc5e, 0x4971f39, 0xbb55bed, 0x8dafc8b, 0x7d52339, + 0xa6adf0f, 0x82391bf, 0xe319522, 0xfd6f90a }, + { 0xf29bbc9, 0x60fdf77, 0xaaa4030, 0xeff9ed8, 0xf8c0d3f, 0x978e045, + 0xeed65cd, 0xe0502c3, 0x3cfd4c8, 0x3104d8f, 0xa639005, 0xab1be44, + 0x9eeab3f, 0xe83f431, 0x451d797, 0x01970e8 } + }, + { + { 0x3180f4b, 0xbc972f8, 0x617779d, 0xac053c0, 0x7fa149f, 0x89392c5, + 0xbcb6263, 0xdc4699b, 0xce12882, 0x0ae8b28, 0xaf1a4dc, 0xdca19a7, + 0x64e1a74, 0xd3d719f, 0xaffdd5d, 0xbb50201 }, + { 0x7ac30e9, 0x56f7310, 0x1878900, 0x65cc9c7, 0x27338a3, 0x83f5866, + 0xac5bb13, 0x122adef, 0x1bcd4d5, 0x97de200, 0xb8aa3a0, 0x6ed3985, + 0x6821f9b, 0x8680f1d, 0xdda9f98, 0xcb42028 } + }, + { + { 0x0ec2db3, 0xcdb0708, 0x3dad1a1, 0xe28c833, 0xde2da07, 0x2093e32, + 0x83b8987, 0x7317073, 0xf552b8d, 0xad17871, 0x51cf70a, 0x846da98, + 0x5c4f5e1, 0xf94a16e, 0x0f8348a, 0x8429996 }, + { 0x98db78a, 0x4bf3f68, 0x3d19b52, 0xad77fa8, 0x8b972dc, 0x6976772, + 0x5321be0, 0x7dfa35a, 0xdd344a6, 0x9881846, 0xad4e2a8, 0xe550292, + 0xbc68bf1, 0x8075217, 0x893be15, 0xdd837c4 } + }, + { + { 0xd4fab5b, 0x09c931e, 0xb77a0f1, 0xb2dcf08, 0xe0d38a6, 0x7dac5c0, + 0x0ae73af, 0xa5570b0, 0xf5aed28, 0xc7c19d3, 0x5251e92, 0x575fa6f, + 0xcdf7275, 0xb843cd6, 0x9a01287, 0xd9d3d8e }, + { 0xb3c370b, 0xf94e356, 0xfe464b0, 0xc62b99f, 0xa986057, 0x7792650, + 0xc4b1874, 0xeaa67d5, 0x0b07078, 0xba1ba4d, 0x7a03699, 0xdbf636d, + 0xedd32a3, 0x1a16c34, 0xa45cb5d, 0x6ce2495 } + }, +}, +{ + { + { 0xa684441, 0xd7c4d9a, 0x30cd42a, 0xce62af6, 0x43014c4, 0xcd2669b, + 0x6f65b24, 0xce7e711, 0x576fa19, 0x1847ce9, 0x9dd8ca6, 0x82585ac, + 0xb42e1db, 0x3009096, 0x384ab8b, 0x2b2c83e }, + { 0xb4e9a6e, 0xe171ffc, 0x7374b40, 0x9de4218, 0xdb1d616, 0x5701f9f, + 0xa3e8cbc, 0x211e122, 0x1e400bf, 0x04e8c1a, 0x0f37159, 0x0297470, + 0x3df8c28, 0x41775d1, 0x61ac2db, 0xcfaad4a } + }, + { + { 0x7dc0f49, 0x6341b4d, 0xf471a53, 0xaff6c2d, 0xfb8e91e, 0x20ec795, + 0xc3b7b62, 0x4c7a4df, 0xd374938, 0x9f33ff2, 0x3a60f2e, 0x38f8c65, + 0x2efef73, 0xc1168ac, 0xce408ee, 0x046146f }, + { 0x308b0c3, 0x9b39ac0, 0x36b8570, 0xe032d61, 0xfc4aacf, 0xee07d8d, + 0xd5a41dd, 0x0a82acb, 0x7c3d726, 0xbe0ded2, 0xb926ce9, 0xce51d60, + 0x5806c1e, 0xfa2f7f4, 0x1dec59c, 0xe367c6d } + }, + { + { 0xda2547b, 0x64511b6, 0x0761405, 0x76a349c, 0x01223ab, 0x37d6626, + 0xf4d7c48, 0x0e243c1, 0xda756a0, 0xdc9c8b4, 0xd72e7e9, 0xc7430df, + 0x27b4210, 0x0eb1308, 0xcf11cbd, 0x7a9c044 }, + { 0xe8dd150, 0x2c08ff6, 0x2932fc6, 0x18b738c, 0x04513e8, 0x07d5651, + 0xaa40a17, 0x0ca5cff, 0x01baa8f, 0xd486341, 0xb72b79e, 0xfb20faf, + 0x654020f, 0x1a051e5, 0x4e17f23, 0xe3b3317 } + }, + { + { 0x4de9428, 0x0591048, 0x5abdf97, 0x620542a, 0xa16a4d1, 0xaa0eded, + 0x6d65bb9, 0xa93f71c, 0xb8dfaf9, 0x88be135, 0x57ca8ee, 0x1d9f4e5, + 0x26781ad, 0x4c896aa, 0x6c6c49f, 0xd3fbe31 }, + { 0x2c34c3d, 0x088d852, 0xbadff1e, 0xbb6d645, 0x385450d, 0xe3080b8, + 0x50ab1f3, 0x5ccc54c, 0xac0657d, 0x4e07e6e, 0xb7ef2c0, 0xa7ba596, + 0x73a81e9, 0xcceca8a, 0x8284c35, 0xa0b804c } + }, + { + { 0xf17a6a2, 0x7c55956, 0x789cfa8, 0xb451d81, 0x2506eaa, 0xdf414e8, + 0xae96562, 0x6ef40fb, 0x0e0297e, 0x63ea283, 0x73c46fa, 0xf5df26e, + 0xaac8bce, 0xe00641c, 0x64371f3, 0xc89ed8f }, + { 0x793202e, 0xd22b08e, 0x875cb50, 0x39a9033, 0xf85ddb4, 0xe64eec0, + 0x7acf7b5, 0xdce45a7, 0xb9b802d, 0x39d1e71, 0xbd559ac, 0xafdfe7c, + 0x809eeb5, 0x17ec1f8, 0x4889b8c, 0x8c0e38a } + }, + { + { 0x17089da, 0x47eabfe, 0xec90c50, 0x2d18466, 0x5861531, 0xa511aa4, + 0x8c39b39, 0xebb3d34, 0xf1b5282, 0xa0ac4da, 0xa9dadba, 0xea26be7, + 0x554d86e, 0x8992ba8, 0xd5f2ef5, 0x7fcbdb6 }, + { 0x56863e7, 0x320e79b, 0xa7dce2d, 0xeb9d0c0, 0x784cbc6, 0xb9f4031, + 0x7ac1f81, 0x68823ee, 0x9d87497, 0xa6b6f4f, 0x57f9b6e, 0x83c67b6, + 0x0fef2a7, 0x3735747, 0x59596e2, 0xf38028f } + }, + { + { 0x7e82886, 0x9ea57ab, 0x48c44d5, 0x18221c5, 0x314a24f, 0xbf8e6cf, + 0xfd025e5, 0x70ff18e, 0x5334468, 0x08d03de, 0x7404fb7, 0x2b206d5, + 0x55e36b0, 0xb923271, 0xb88ddd9, 0xcc7604a }, + { 0x4a746f0, 0x3df5152, 0x168e3fc, 0x8fdebd8, 0x7f8c32c, 0xffc550c, + 0x148743e, 0x1dbbc17, 0xb88e18b, 0xd48af29, 0x750027c, 0x8dca11c, + 0x1832be3, 0x717f9db, 0x2b06019, 0x22923e0 } + }, + { + { 0xc1cc4d3, 0xd4e06f5, 0x2b4f03a, 0x0fa32e3, 0xc4628d0, 0x956b9af, + 0x939dad1, 0x95c39ce, 0x8a00416, 0x39d41e0, 0x6fb01aa, 0xfd7ff26, + 0x45af340, 0xc6033d5, 0x8e36584, 0x2f65542 }, + { 0x8dff960, 0x14cfb1f, 0xda81474, 0x7236ffc, 0xd452d0f, 0xc6a6788, + 0x77f6094, 0x2ad4a52, 0x07eea74, 0x369d65a, 0xd6229aa, 0x27c6c38, + 0x8863976, 0xe590e09, 0xb38b142, 0x361ca6e } + }, +}, +{ + { + { 0xdfeb7ef, 0x6803413, 0xd3f4fad, 0xb669d71, 0xc941606, 0x5df402a, + 0x8e6c5b7, 0xe5d1776, 0x92ab236, 0x131bcb3, 0xce2e0e0, 0x7f1fb31, + 0x9e98c35, 0xa2c020d, 0xf28657b, 0x33b23c0 }, + { 0x9cf7879, 0xed14e73, 0xb4357b3, 0x10d4867, 0x31e4e04, 0x127cea3, + 0xaa5f8a7, 0xc60d25f, 0x025b987, 0xfef840a, 0x66f2a0a, 0x78081d6, + 0xac36198, 0x0fa0b97, 0x134dc9f, 0xe0bb919 } + }, + { + { 0xcc32eae, 0xc1d2461, 0x0f79a37, 0x0fdbfdf, 0x1c95f02, 0x70f2bc2, + 0x372cddf, 0x7d68bec, 0x8439342, 0x44f7817, 0x4843a6c, 0xa3d5678, + 0x07f8959, 0xbadf77a, 0x73db4ca, 0xf458198 }, + { 0xd54f805, 0xe8eaaf3, 0xb84c1e7, 0x2f529d1, 0x21e535c, 0x404e32e, + 0x159b5f5, 0xabac85c, 0xb00466f, 0x4e8e594, 0xc941873, 0x40fcaab, + 0xbe407c6, 0x3b4e370, 0x5b2e58d, 0xccd5788 } + }, + { + { 0x88b74a8, 0x3ee615e, 0xeab4e69, 0xd7d6608, 0xe4ace36, 0x27cf9f1, + 0x7aebabb, 0x282359e, 0xf6d162f, 0x96e509b, 0xf1a290a, 0xad906f3, + 0x1314a58, 0xe7d6c4f, 0x218431d, 0xeecffe4 }, + { 0xe2cfed9, 0xa66e0e9, 0x71f0544, 0xb0887ec, 0xa04c5d7, 0xd34e36b, + 0xed4392d, 0x094daa5, 0xc8aa925, 0xcda83ad, 0xb979786, 0x1adef91, + 0xfddc5d6, 0x3124dcb, 0x0b70c14, 0x5cc27ed } + }, + { + { 0x0eac2d8, 0x386dbc0, 0xc50ca30, 0xa716ecb, 0x80d9f04, 0x9e3fc05, + 0xcfeaceb, 0x37dde44, 0xa3522d5, 0xd88d74d, 0x2cf239a, 0x6bb9e9f, + 0xa7cbfec, 0x9e7fb49, 0x0a5c0ef, 0xe1a75f0 }, + { 0xfb9229d, 0x6e434e7, 0xc8a79b3, 0x0ec6df5, 0xd3fb311, 0x7046380, + 0x52e20fa, 0xe957ef0, 0x9ef4614, 0x0f4fe9a, 0x54d8f2b, 0x1b37d9c, + 0x39d84a2, 0x23b2dc1, 0x724e713, 0xf62c4f6 } + }, + { + { 0x747e219, 0xbd6922c, 0x3869b7b, 0x34d1438, 0x96f2272, 0x8c875a5, + 0x3fe361e, 0xd9602c0, 0x744839f, 0x081348f, 0x61ac1f1, 0x61bd16c, + 0xd8da4e1, 0x993b727, 0x7741271, 0xbb40ba8 }, + { 0x81dcfff, 0xe6dcc98, 0x93ce616, 0x9f513f5, 0x618cd8f, 0xdc09683, + 0x26639be, 0xc3b1d10, 0xc762ee2, 0xe8f149f, 0xb244aae, 0x59f26ef, + 0x693dd96, 0x3f2de27, 0x9c3a7de, 0xd8b68f7 } + }, + { + { 0x970bd5b, 0x6fa20b9, 0x75f6179, 0x87242d7, 0x72d9308, 0xa95a6c6, + 0x37a8a58, 0x6eb2518, 0xc59562c, 0xfdea12a, 0x20f1fc3, 0x4419c1e, + 0x9d66788, 0x0c1bd99, 0x32c0547, 0x4b74288 }, + { 0xdf479ab, 0x4f38acc, 0xc52a942, 0x01f6271, 0x02ca9a7, 0xe3298f4, + 0xb718fc8, 0x533daca, 0xb093ca8, 0x133602a, 0x8f98104, 0xc04da80, + 0xaf08620, 0xd0f2e23, 0x178b164, 0x882c817 } + }, + { + { 0xec30a71, 0x28e6678, 0xf78aca1, 0xe646879, 0x88fa078, 0x868a64b, + 0xfee3433, 0x671030a, 0x87c0211, 0xb2a06bb, 0x46c406a, 0x202eca9, + 0xe4f0f59, 0x64d6284, 0x3c9f907, 0x56ae4a2 }, + { 0x1dcc100, 0x5abbb56, 0x07c7784, 0x6fef6cf, 0xdb7302d, 0xb6e25cd, + 0x42980e8, 0xa26785b, 0xfb96801, 0xe7d4043, 0x8e4282b, 0x46df55d, + 0xc602d6e, 0x9c0a5f5, 0x75dfe29, 0xf065604 } + }, + { + { 0x3dcbc90, 0x0e82a1a, 0x656feac, 0xb1ee285, 0x0d3d3b2, 0xfa4353b, + 0xdd5c5df, 0xc2e7a6e, 0x416ce53, 0x13707e1, 0x87ebc07, 0xc84ce07, + 0x8a9a834, 0xdd273ce, 0x5e8e1e7, 0x432a617 }, + { 0xbd0064a, 0xa359670, 0x6534516, 0xc899dd5, 0xdb27169, 0x666560e, + 0xa19a068, 0x1537b22, 0xeac7527, 0x3420507, 0x6fc13a7, 0x479f25e, + 0x1bc19b3, 0xc847acc, 0x0b20d45, 0xecdecf0 } + }, +}, +{ + { + { 0x4acea57, 0x6f24100, 0xda68597, 0xdace1c6, 0x50ce77f, 0xea7dd41, + 0x1585884, 0x1aecb84, 0xea4a85c, 0x92ff208, 0x88eebd2, 0xde9433c, + 0x3f4d289, 0x53cd318, 0x26539af, 0x3970858 }, + { 0xb827d87, 0x4b57599, 0x3d77638, 0xdc82ac0, 0x52f6e61, 0x6943366, + 0xad5e8a6, 0xb8fc4b0, 0xf388642, 0x1b6f7dc, 0xa74dd57, 0x6f24533, + 0x41750cf, 0xc669378, 0x28a37af, 0x06757eb } + }, + { + { 0xc133995, 0x0e70d53, 0x7c8c97d, 0x88a5e0c, 0x85f3be3, 0x4e59dbf, + 0x0e92698, 0x0f364ac, 0xef6940f, 0x3a1e79b, 0xd85d23a, 0xc8a3941, + 0x9a00e58, 0x143bb99, 0xc6f2f10, 0x61cf7d6 }, + { 0x85150fe, 0x979c994, 0x59d773f, 0xcfd0df2, 0xaab7bcd, 0xce97b9d, + 0x6afd8fc, 0xc9fff8e, 0x89a4628, 0x246befd, 0x1567090, 0xf630282, + 0x6749c58, 0x1539342, 0xa0f3fd3, 0xff47d0e } + }, + { + { 0x35f6706, 0x09b0bfd, 0x2c82e69, 0x7464581, 0x50d5fe9, 0xb60729f, + 0x95c74f1, 0xf133245, 0xbb76c89, 0x33647e3, 0x5a9afcc, 0x0126404, + 0x0f154ab, 0x46d57ee, 0x25680a4, 0x2efa555 }, + { 0x5329d90, 0x12ebfc6, 0x79800af, 0xcb37ae5, 0x6f8e310, 0x5bb5349, + 0xf1bb936, 0x9b59c63, 0xf4610e9, 0x5b49baa, 0x4f2d6ac, 0x2bbeeef, + 0x0badc67, 0x87ee21e, 0xf1ddfa0, 0x12e2aad } + }, + { + { 0xa9109ee, 0x5b4668f, 0x8a6cea2, 0xfa95133, 0x4068e16, 0xe45e6fc, + 0x0205ed8, 0x8ae9a0c, 0x679b79b, 0x2993b96, 0xed604d3, 0xc6b878f, + 0x32c77f3, 0x01d0208, 0x495a1ab, 0xd45d890 }, + { 0x29d2030, 0x99348fa, 0x61f8f7a, 0x961f9a6, 0x674f74b, 0xfd53212, + 0xb3e72bc, 0x45cee23, 0xb77e2d5, 0x3fccb86, 0x4219cb7, 0xdff0310, + 0xc056871, 0x233771d, 0x7d2c521, 0x1214e32 } + }, + { + { 0xff2a8e1, 0x9f51e15, 0x138bc70, 0x86571c5, 0x0c09d46, 0xbfc4caf, + 0xc2a0c18, 0x65e33fe, 0x426867d, 0x8214392, 0x80ae4ed, 0x51ce6c0, + 0xb110de6, 0x6cbe8d7, 0xfd22ea4, 0x7f6e947 }, + { 0xcadefc4, 0x7373a75, 0xb0c682f, 0x6fca1d2, 0xf3c7c1e, 0xcd2140d, + 0x558b7a5, 0x8653a37, 0x55eb321, 0x653e74e, 0xc31af73, 0xbe0c6b3, + 0xf4fc365, 0x3376379, 0x71add4d, 0x3570b37 } + }, + { + { 0x83c3494, 0x9061ec1, 0x677bc95, 0xaf2f28d, 0x3bf8768, 0x6fe7279, + 0x0fa86d8, 0xc5f50e3, 0xa3293ce, 0x6c03060, 0xe2355a6, 0x4d53357, + 0xe4df931, 0x43a59ea, 0x13b79c6, 0x6f48f5d }, + { 0xddc5192, 0xa4d073d, 0xa65773f, 0x6d0e318, 0x765de9e, 0x1008792, + 0x39a0375, 0xa724ed2, 0x97d7c9e, 0x510ff14, 0x5baa863, 0x251f622, + 0x648a351, 0x86464fe, 0xd50fd91, 0xf85e98f } + }, + { + { 0x86ee987, 0x29c9634, 0x10dcc9f, 0x93e8e52, 0xc910b1f, 0xa1fc4d1, + 0xfeb603e, 0x015acac, 0x0844a5f, 0xc9f25f8, 0x73f4dac, 0x50de93c, + 0x310a4aa, 0x1758783, 0x358f106, 0x544d570 }, + { 0x1dc68ca, 0x4eeec7b, 0xe00fbcb, 0x6238e6f, 0xb4e83c9, 0x34d394c, + 0x2292656, 0x764ffa2, 0xf641f2e, 0x5614cd1, 0x9e07234, 0x4252eb6, + 0x68d2ba4, 0xcbaef45, 0x8a98b17, 0x8c9c550 } + }, + { + { 0x4106140, 0xf235d9d, 0x9eb601e, 0x1bf2fc3, 0x375e0c3, 0x6fb6ca9, + 0xc0024d2, 0x4bf5492, 0xeb54cc6, 0x3d97093, 0x5c90cb5, 0xc60931f, + 0xfbe0f1a, 0xfa88808, 0xd33e7d4, 0xc22b83d }, + { 0xc0abbf5, 0x9cfec53, 0x93723df, 0x52c3f0a, 0x39b96b6, 0x0622b7e, + 0x1667270, 0x300de28, 0x9ef426a, 0x50b66c7, 0xc6eb295, 0x8849189, + 0x8914a7e, 0xeaec3a9, 0xc4c99e0, 0x7ed56b0 } + }, +}, +{ + { + { 0x687e557, 0x7926403, 0x5310017, 0xa349816, 0xd43a8fd, 0x1b06e91, + 0x6ac23cb, 0xf201db4, 0x4f48750, 0x6f172ad, 0xe74bd3e, 0x5ed8c8c, + 0xdaba648, 0x492a654, 0xa9b64ff, 0x123010b }, + { 0x6e89f93, 0xa83125b, 0x398378a, 0x3a3b0b0, 0x0aebe7c, 0x9622e0b, + 0x49512a4, 0xb9cbfdc, 0x6aaf12a, 0x13edffd, 0x9f5eafd, 0x555dff5, + 0x1212efa, 0x3cba6fe, 0xd9bb0f8, 0xd07b744 } + }, + { + { 0x9a48920, 0x45732b0, 0x13ff36d, 0xf3080fc, 0xde8f950, 0x9347395, + 0x382b897, 0x14d025a, 0x04d72ad, 0x60c5a74, 0x11a9c71, 0x30be7e5, + 0x31ac33a, 0x43ffabd, 0x35cbb14, 0x97b06f3 }, + { 0x7740de9, 0xe4ff5c5, 0xaacf81e, 0x5fed090, 0xe8b7c9d, 0x97196ee, + 0x045910b, 0x316dcd1, 0x5ad8c63, 0x7a2b2f5, 0xc5b03bb, 0x674fffd, + 0xe65953c, 0xc1cd133, 0x0a83556, 0x3c06052 } + }, + { + { 0x091c23d, 0x797c3f6, 0x39c9c05, 0x2ea2de3, 0xa31f67c, 0x5d958b4, + 0xd5f088c, 0xf97afe5, 0x0b37243, 0xbcfbd2a, 0xeca630c, 0xc43ad3e, + 0x42845e0, 0xb92a337, 0xa9a0f16, 0x970bff7 }, + { 0x5970a79, 0x8635511, 0xf205928, 0xcee332e, 0xc04c208, 0x2c58d70, + 0x3f5e5bf, 0xdbfe19a, 0x8e51c56, 0x8f8f2c8, 0x8e2da75, 0xb61f58e, + 0x624d93f, 0x4046a19, 0xe1f9538, 0x7de64db } + }, + { + { 0xc2d850e, 0xd018e1c, 0x63a723c, 0x8cdb643, 0x90a42af, 0x9a65abe, + 0x16f20cc, 0xfeece96, 0xd5cff56, 0xc906800, 0x3f0deed, 0x0acf23a, + 0x728dd3a, 0x2143061, 0xb8ce34c, 0x66276e2 }, + { 0x73cc9c7, 0x23700dc, 0x5b1778b, 0xdb44851, 0x4aab669, 0x330f41e, + 0xf5282a4, 0x2f5aabc, 0x30f9e01, 0xff837a9, 0x901cc98, 0x1a1eb2f, + 0xe69bd7f, 0xd3f4ed9, 0x8a72a7d, 0xa6b1141 } + }, + { + { 0x9ea3b43, 0x34bde80, 0x5ced6ae, 0x5ddcb70, 0x95a6cb8, 0x8257f5b, + 0xc77dcb8, 0xaac205d, 0x035b397, 0x77d740d, 0xcf7e0a6, 0xca7847f, + 0x085601b, 0x9404dd6, 0x457e4f9, 0x0a5046c }, + { 0xbc11470, 0xcaee868, 0x005c5f6, 0xb118796, 0xec79173, 0xcc04976, + 0x21f6827, 0x7f51ba7, 0x486ff7e, 0xa8e3f0c, 0xf87838c, 0x327163a, + 0x6d039fd, 0xcf2883e, 0xdb8b0e2, 0x6fb7ab6 } + }, + { + { 0x620d669, 0x8ca5bac, 0xed7caa9, 0xff707c8, 0x927909b, 0xdaefa2b, + 0x7029da3, 0x1d2f955, 0x6d131a0, 0x52a3ba4, 0x3ab1041, 0xe5a94fd, + 0x99bc0ae, 0x5089177, 0xfa1bd16, 0xf750354 }, + { 0x6cd31fd, 0xdd4e83a, 0x92fac84, 0xd335053, 0x1691382, 0xf914cbc, + 0xda6ade6, 0x669683f, 0x8878513, 0x6944643, 0x4b1a72d, 0x429d3cc, + 0x61eec36, 0x655c46a, 0x4bc4970, 0x881eded } + }, + { + { 0x7ca647f, 0x5b39d37, 0xe917b34, 0x41533c1, 0x7daf734, 0xea2aeb5, + 0x1286560, 0xf1ef1eb, 0x08e0473, 0x582f2e0, 0x5edc74a, 0x5913d7d, + 0x3c1e754, 0x588c7ec, 0x7146fe1, 0xbd6db05 }, + { 0x7634907, 0x3b0d49e, 0xe43b9cc, 0x4c65ce4, 0x2d92d5b, 0xb87e958, + 0x7ab1519, 0x0513572, 0x8c3aed0, 0x03ec084, 0x561a641, 0x4d7aa21, + 0x99e92ad, 0xe5f8211, 0x48a457c, 0x379b55f } + }, + { + { 0xd6a8442, 0x8317c34, 0xae499da, 0xb0ab4a5, 0x720e8eb, 0xebcb16e, + 0x9a96908, 0xfd5c563, 0xad23acf, 0xcab4d67, 0xbcdf748, 0xa600a79, + 0xa2a6a51, 0x18a6340, 0x3aabd69, 0xf2f415c }, + { 0x747258a, 0xdb38a4f, 0x2e24415, 0xb6ea560, 0xf1f7655, 0xfad1ea9, + 0xc957684, 0x4e27eb5, 0xb2e1cfc, 0xf8283e1, 0xaa6291c, 0x8f83bd6, + 0x5619e84, 0x28d23b5, 0x93770a4, 0xb9f34e8 } + }, +}, +{ + { + { 0x7515fb1, 0x1bb8437, 0x7b860a6, 0xac73f2a, 0x22b390f, 0x78afdfa, + 0x66048aa, 0x815502b, 0x85bf620, 0xf513b97, 0x3fc5d7c, 0x2524e65, + 0x178c969, 0xa10adc0, 0x5391c8d, 0xa1d5396 }, + { 0xa8bcc45, 0x09fccc5, 0x7710e1e, 0xa1f97d6, 0x897d0a1, 0xd694442, + 0x5f42400, 0x7030beb, 0x7127908, 0xdebe08c, 0x2187637, 0x96b715c, + 0xb528129, 0xc598250, 0xa1ccb07, 0x0f62f45 } + }, + { + { 0xb765479, 0x8404941, 0x5837dc4, 0xfdecff4, 0xadbd465, 0x1796372, + 0x3159806, 0x5f84c79, 0x6aaad34, 0x6d2e46b, 0x384b375, 0xd303b4a, + 0xb392002, 0x440acd5, 0xc475e87, 0x4f2a4a7 }, + { 0x5606fc2, 0x038e1da, 0x9c2f050, 0x2d821c2, 0xf139db4, 0xc074cb3, + 0x4ec59be, 0xde2fee7, 0xa84ed59, 0x5a819ee, 0x3e98711, 0xd65c62c, + 0xb9723c1, 0x72eb440, 0x01be611, 0xb927754 } + }, + { + { 0xab9e9fc, 0x929fe64, 0x0bf1e85, 0x04379fd, 0xbc28ee3, 0xb322093, + 0xe4555e1, 0x78ac4e2, 0xabc5588, 0xdb42b58, 0x77c8b12, 0x1c1b5e1, + 0x40366c4, 0xf6d78dd, 0xbdae22e, 0xc21ff75 }, + { 0xa211df2, 0x1e3d28e, 0x3617c0a, 0xc5a65a1, 0x58140d5, 0x3fa02c0, + 0xb62d10c, 0x155c346, 0xe48268f, 0xc9cf142, 0x1993bc3, 0xdc14083, + 0x0ee69dc, 0x07c44d4, 0x5e2ac46, 0x6169950 } + }, + { + { 0xd0fb585, 0x44e4a51, 0xf1f3ce8, 0x00846be, 0x8e2de1e, 0xedef39a, + 0x33b3934, 0x430afe3, 0x4337188, 0xac78b05, 0xc9a3f24, 0x0f39de4, + 0xc9ae6a4, 0x039eddd, 0x8eacd51, 0xf470157 }, + { 0x9a2f31a, 0x1e39694, 0xb19a8b1, 0xc8a40f4, 0x9d239d8, 0xdddd10c, + 0x887e066, 0xf974245, 0x3ea28c6, 0xfdb5111, 0xe1122a9, 0xb5af0fb, + 0x36e0267, 0xd30c89f, 0x74f024c, 0x7b1c0f7 } + }, + { + { 0x07a39bf, 0x1ec9956, 0x3a68d15, 0x1c3ecf2, 0x4f59fe9, 0xd8a5c4e, + 0x271abc3, 0xacb2032, 0x71ef239, 0xbc6bdf0, 0xb39b391, 0x660d7ab, + 0xb627a0e, 0x2e73bb2, 0x248fc7e, 0x3464d7e }, + { 0x1666760, 0xaa49249, 0x8582659, 0xa257b6a, 0x5593089, 0xf572cef, + 0x73ca6bf, 0x2f51bde, 0x764cff5, 0x234b63f, 0xd411a35, 0x29f48ea, + 0xafe1db1, 0xd837840, 0xd9f4c4b, 0x58ec0b1 } + }, + { + { 0x5e6f3dc, 0x8e1deba, 0x06a5ff7, 0xc636cf4, 0xc80ca0f, 0xe172b06, + 0x5ffb90a, 0x56dc098, 0x9a05e83, 0x895c218, 0x7561ac2, 0x6ddfaec, + 0x96283a0, 0xaa35749, 0x7e7cd43, 0x6dfb262 }, + { 0x2c8ca27, 0x6576de5, 0x49018eb, 0x6a4a872, 0x5c34342, 0x00c275c, + 0xd2d90c4, 0xe34805a, 0xd8743c4, 0x651b161, 0x7312bf3, 0xb3b9d9b, + 0x0bf7e00, 0x5d4b8e2, 0x78d3d7e, 0x8899bdf } + }, + { + { 0xfaa9cd1, 0x9644ad8, 0x6e0e58e, 0x34c98bf, 0x404c637, 0x6022aad, + 0x7ac013b, 0x2a11a73, 0x5540899, 0x5bdd103, 0x1e022a4, 0x2e67572, + 0xb834c33, 0xe32045d, 0x2f2d01c, 0x74a260c }, + { 0xc48841c, 0x20d59e9, 0xe560359, 0x05045dd, 0xac998ac, 0xeba779c, + 0x00a6218, 0x5bed10c, 0x5327ef4, 0x25d4f8e, 0x4597794, 0xa278474, + 0x831d11e, 0xefd68ca, 0x934446a, 0x9ad370d } + }, + { + { 0x73c92ac, 0x3089b3e, 0x957a75c, 0x0ff3f27, 0xd676f50, 0x843d3d9, + 0xd496d43, 0xe547a19, 0x8e924a4, 0x68911c9, 0x85b5522, 0xfab38f8, + 0x83e0ac5, 0x1048811, 0xdc788c4, 0xcaccea9 }, + { 0xe3c6aad, 0xfbe2e95, 0xb3a6cf1, 0xa7b3992, 0x87d78b1, 0x5302ec5, + 0x1826100, 0xf589a0e, 0x8610632, 0x2acdb97, 0x9232b26, 0x1e4ea8f, + 0x9c09a15, 0xb21194e, 0x849b909, 0xab13645 } + }, +}, +{ + { + { 0xf3a71c1, 0x92e5d6d, 0x297d661, 0x349ed29, 0x1713fc9, 0xe58bd52, + 0xb9ddfb5, 0xad999a7, 0x3c28ce0, 0x271c30f, 0x2a9d460, 0xf6cd7dc, + 0x207dec7, 0xaf728e9, 0xfcb8bf0, 0x9c2a532 }, + { 0x68bf486, 0xd702184, 0x7ab8ea8, 0x73b45be, 0x1795c93, 0xddfc658, + 0x6bb8da2, 0x7941660, 0x88e07a2, 0x658f197, 0x26d3d12, 0xa9d5b08, + 0x9535b52, 0x4d7c95f, 0x268ef8a, 0xad55e25 } + }, + { + { 0xa2bc326, 0x94a9b0b, 0x167e5f3, 0x485ecc5, 0xc97fc74, 0x8340bc7, + 0x07aaa5c, 0x06f882b, 0x849698a, 0x4b57455, 0xb36a0ba, 0xd9281eb, + 0x8b8108f, 0x8918c6c, 0x5b50d1d, 0xedd1eea }, + { 0x2a25f50, 0x94d737d, 0x2446ad0, 0x0e5a823, 0x7ced3e2, 0x02a5435, + 0x4af8ced, 0xb09a92a, 0xeeecef2, 0x85fc498, 0xe71e3d4, 0x06a02b9, + 0x84bb49a, 0x00ad307, 0x64a5b4a, 0xf61585e } + }, + { + { 0xb86a4c9, 0x915f6d8, 0xa861e1f, 0x944bc6b, 0x54465ef, 0x3091ca7, + 0xeb53a38, 0x11df859, 0x0144679, 0xd44dde5, 0x0994edd, 0x6c8da9a, + 0x91241ef, 0xeebcebf, 0xc2f6859, 0xc419354 }, + { 0x49581b6, 0x1f49693, 0xbb26cb4, 0x5712b10, 0xb09fd59, 0x8fcaa41, + 0x72e22e3, 0xbd39aad, 0xb1199b0, 0xf70e794, 0xc6f863d, 0xdf63c0c, + 0xee9df4f, 0xd58166f, 0xc45e70b, 0xb9224ea } + }, + { + { 0xce525f4, 0x80072fa, 0x66a5502, 0x8597bd6, 0xdbc9725, 0xf65e203, + 0xf2222a4, 0xeccfbe3, 0x2339834, 0x490aa42, 0x62489e8, 0x1348891, + 0xa735084, 0xaff3f80, 0xf3f1bd6, 0x69d53d2 }, + { 0x813341a, 0xb123ffc, 0x1173848, 0x359084c, 0xd29b08d, 0x751425e, + 0x3890ad4, 0x1edda52, 0x607cf20, 0xb64974c, 0xb42ac7c, 0xa8c8cb8, + 0xedd42e5, 0xd5cb305, 0x44c090a, 0xf3034dc } + }, + { + { 0xbb18e19, 0x428921d, 0xfed2127, 0x4cfd680, 0x92ac8c3, 0x671144d, + 0x132c894, 0x2121901, 0x7604cd9, 0x25d0e56, 0xafbc2a0, 0xa372223, + 0x56c16f7, 0xcf98a52, 0xb5459e1, 0x71f129a }, + { 0xb668b2e, 0xf4afdc5, 0x0c2d410, 0xc5d937a, 0x285d54a, 0xe2cc4af, + 0x8c53e18, 0x1c82777, 0x69a92f6, 0x270f2c3, 0x616327a, 0x799f9ac, + 0xd4246f2, 0xce658d9, 0xfb12e36, 0x0fb681f } + }, + { + { 0xe0690fe, 0xc5ab11e, 0x3f74249, 0x80261e3, 0x58c1cf2, 0x8eb4b47, + 0x184ae9b, 0x4895a80, 0xd3e27eb, 0x4a4bdb6, 0xbfd251c, 0xa7a1638, + 0x417a7e3, 0x29ec144, 0x3f1b960, 0xd073609 }, + { 0x49c73d1, 0xcb1ed83, 0x8d1945a, 0x33fc84a, 0xe965118, 0x9f668db, + 0xa82811f, 0x3331743, 0x28ba540, 0xf394dec, 0x654a454, 0x44ce601, + 0x3623645, 0x240dbb6, 0x2e61048, 0xf07e7f2 } + }, + { + { 0x3d45213, 0x7c9f176, 0x9c1f77f, 0x3eefa70, 0x1b48350, 0xde3c3c5, + 0x9d481a7, 0x4a2bc64, 0x7874f3d, 0xfd4a58a, 0x037b302, 0x96655d4, + 0x68bf5ab, 0x9452528, 0x75177f6, 0x1b6d46a }, + { 0xefb8d00, 0x7de6763, 0xa741b7b, 0xb2c1ba7, 0x7bae6ed, 0xcca6af4, + 0x5b68b3f, 0xe4378ca, 0xaf71948, 0xfb757de, 0xbc6ac99, 0x7f07b5e, + 0x27d636d, 0x752a568, 0x4b8a34f, 0xc8b7d1d } + }, + { + { 0x325331b, 0x76cb78e, 0xadd2eed, 0x41f41c9, 0x5c5f623, 0x03db238, + 0x7102fa2, 0xbbc1d17, 0x60182ec, 0x80f137a, 0x55adf15, 0xfdd8569, + 0xe3373dc, 0x4f53f5e, 0x21b669b, 0xec6faf0 }, + { 0x0b86081, 0x7d4e983, 0xf2d979c, 0x10d3cd9, 0x24a22c8, 0x0f48f58, + 0x02f99ee, 0x86c540c, 0x5e6c5fc, 0xf4c6654, 0xbc404c8, 0xaf0c588, + 0x423118a, 0x2e6edbd, 0x0690eab, 0x86e32e9 } + }, +}, +{ + { + { 0xdfbfa6f, 0x1d12656, 0x7646018, 0xa498095, 0xc3597d0, 0x2f1071b, + 0x1dda80a, 0x3df83f9, 0xf3ae449, 0x5853e28, 0x9e19aad, 0xb853d31, + 0xa0d8a46, 0x863f01b, 0x2fef108, 0xa84fca6 }, + { 0xfb84de9, 0xbe4c0b7, 0xc0727bf, 0x40a03dc, 0xb18575c, 0x781f841, + 0x466cddb, 0x6a63045, 0x05dc7a2, 0x6be7582, 0x07ae811, 0x420f87f, + 0x3bf96c8, 0x2808242, 0x51c6821, 0x723998c } + }, + { + { 0x81f5863, 0x38ab641, 0x05ff9e1, 0xd82ecbd, 0xa065856, 0x339c94e, + 0xa45156d, 0x143054a, 0x065628c, 0xe6d64bf, 0xa938589, 0xe530086, + 0x385d79b, 0x22d3a49, 0x0ab8245, 0x0b10790 }, + { 0xca387b5, 0xb0d80fb, 0x35551d7, 0x698206e, 0xa10bb73, 0x199685d, + 0x9107378, 0xa8e5fa8, 0xd99dbbf, 0x36e5724, 0xd581b03, 0xd67f476, + 0x88dd1e6, 0x7a15be7, 0xe5baa31, 0x8dac8e4 } + }, + { + { 0xe170ef8, 0x4d5d88f, 0x1e9e600, 0xb6ba5de, 0xedeabc5, 0x4a89d41, + 0x8fac936, 0x737c66b, 0x65c3125, 0x8d05b23, 0xb61b68e, 0x85a5cbc, + 0x20a6af9, 0x8fea626, 0xd8b50ec, 0x85115de }, + { 0x6a6f30b, 0x5430c8d, 0x8474295, 0x8bef9cf, 0xbe77f38, 0x0648f5b, + 0x9e47bd7, 0xfe2b72f, 0x93106e2, 0xad6c5da, 0xfa7a6c3, 0x4fa6f3d, + 0xb396650, 0xdcd2ed8, 0x1157ef9, 0x7de1cce } + }, + { + { 0x1f241d1, 0x70a5f6c, 0x798cd5c, 0x6c354d8, 0x1a729fb, 0x23c7838, + 0x523cbda, 0xcff8f15, 0x3493697, 0x5683ff4, 0x7534f53, 0xef7dbab, + 0x2243d53, 0xd7bd08e, 0xf8072a9, 0x6f644cb }, + { 0xb22db63, 0xac960f9, 0x23af04d, 0xa97f417, 0xd9798af, 0x692b652, + 0xfedb156, 0x0e35967, 0xdfe6ee8, 0x14b5e50, 0xb411070, 0x7597ede, + 0x442b3f9, 0x116f3ce, 0x1b2b6db, 0xe9b5ae8 } + }, + { + { 0x2315930, 0xf4385ee, 0x27a8740, 0xc8d0298, 0xd934a43, 0x7907a8d, + 0xc582191, 0x20bc946, 0x6a405e7, 0xa4acb3e, 0x43df2f5, 0x8c1d6c8, + 0x991f0b5, 0x9df1593, 0x4d9be9d, 0xbb9df98 }, + { 0x8e4b190, 0x6362008, 0xada3a88, 0xee1421e, 0xf93b027, 0xb84f0cc, + 0x8e95091, 0x7a5d667, 0xf3e3704, 0x3974462, 0xc593e98, 0xfa6fb5e, + 0xa6477d2, 0x44b6cf7, 0xb09a562, 0xe885b57 } + }, + { + { 0x09a0c02, 0x6e339e9, 0x0e75f29, 0x57afff0, 0xfb7db03, 0x797d8d6, + 0xd25a236, 0xc6e11a3, 0x0107260, 0x643ce1c, 0x62eae1c, 0xe644ec4, + 0x3f5a3f5, 0x821d5b8, 0xc0579d6, 0xa8ad453 }, + { 0x17d43a4, 0x6518ed4, 0x3f87ccd, 0x46e76a5, 0xf9bef95, 0xd6cbaab, + 0x4f7cbcf, 0x2568832, 0x08476b4, 0x367159a, 0xbe6d324, 0x1d1b401, + 0xa605026, 0x348cb98, 0x43b6b1e, 0x144f3fe } + }, + { + { 0x7b1822c, 0xbabbd78, 0x2aa51f8, 0xd34ba7e, 0x41fbea4, 0x086f1cc, + 0x746f3d9, 0x96f7eac, 0x281ecaf, 0xad97f26, 0xa14ee2c, 0x751a905, + 0x0d7335f, 0xb4e7fe9, 0x4892ff0, 0x0d97b8f }, + { 0x5a5c40e, 0xdb8a315, 0x7ba567b, 0x64e5de7, 0x1eefe88, 0x4f155f7, + 0xfb6fbf4, 0xe2297e9, 0x6c16be5, 0xfe24bf9, 0xcdd83e2, 0x2251847, + 0x5eda444, 0x13ac2c8, 0x283275f, 0x49d1b85 } + }, + { + { 0x423e08f, 0xca08731, 0x87d2f14, 0x7046bb0, 0x3bc846c, 0x876f10c, + 0x358fbe3, 0x2202b76, 0x0e26ac6, 0x0d4fc1c, 0xb986881, 0x1fc748b, + 0x8384a18, 0x609e61c, 0x0d88e00, 0x28a72d6 }, + { 0x78c6e2f, 0x1332a31, 0xb3526a4, 0x0367919, 0x698fe3e, 0x53989e4, + 0xb16a99b, 0x14b1145, 0xddbb75f, 0xef9ec80, 0x0e53955, 0x7625624, + 0x8744ae1, 0x54e087a, 0x672b875, 0xce50e8a } + }, +}, +{ + { + { 0xa29629c, 0x4c88b2b, 0x7b2642f, 0x946559c, 0xf7ebe4c, 0x933d432, + 0x63632c9, 0x97109b6, 0xe53184d, 0x799b3fb, 0x0f069a6, 0xd462871, + 0x3a68351, 0x0c182a1, 0x9a2437a, 0x974a839 }, + { 0x2a70278, 0x29f1997, 0xd9c424b, 0x01b98b6, 0x08f4c37, 0xd85a60b, + 0x2b1da15, 0xcc3523f, 0xddffb0f, 0xf922115, 0xde84ae2, 0xee0fe4d, + 0x55365be, 0x810440c, 0x1a457e8, 0xd2f6639 } + }, + { + { 0xe2ddd05, 0x5e6879f, 0xabdfc61, 0x92a7545, 0xa5cede8, 0x7dedd63, + 0x70df4bd, 0x8a03b3f, 0x91f6cbb, 0xa5d1f65, 0x10f3fb2, 0x372fde6, + 0xa9dee05, 0x4537f9e, 0xdf7aa50, 0x7eb85bb }, + { 0xe8c504d, 0x963edf8, 0xe7bdb6b, 0x53c8dca, 0x6fedf2d, 0xa246e4c, + 0x0c55bde, 0x7553340, 0x0270a54, 0x2aa748d, 0x05860dd, 0xadb6cf0, + 0x9b84763, 0x8d31450, 0xeb405ef, 0x626720d } + }, + { + { 0x6601328, 0xa3709ae, 0x2ac2478, 0x68e94fd, 0x9d5d247, 0x3879343, + 0x392c198, 0xfa467af, 0x15df607, 0x49e7b0d, 0x61792a8, 0x8c58122, + 0x1d3762f, 0x79f7658, 0x244a39d, 0xaa38895 }, + { 0xc5cd0bc, 0xef60af9, 0xa33b3bb, 0x2b0db53, 0x251015d, 0xe3e0b1f, + 0xe64489e, 0xc608afc, 0x03651aa, 0xe52b057, 0x1c6f7b9, 0x1dda8b9, + 0xff41893, 0x833f022, 0x192818c, 0x58eb0a0 } + }, + { + { 0xfc7b5a7, 0x6c1300c, 0xa83ab33, 0x6d2ffe1, 0x9c02eef, 0x7b3cd01, + 0xba60d55, 0x6c64559, 0x19e2f73, 0x2e9c16c, 0xdbe47b1, 0x11b24ae, + 0x1b8153b, 0xc10a2ee, 0x1e02e1a, 0x35c0e08 }, + { 0x1dd6f16, 0xa9f470c, 0xf41a290, 0x4ea93b6, 0x25ee03f, 0xac240f8, + 0xb85aabd, 0x6cd88ad, 0x1be2f8f, 0x378a64a, 0x417bac1, 0xbf254da, + 0x9231142, 0x7e4e5a5, 0x3b8c057, 0x057aadc } + }, + { + { 0x80af479, 0x607c77a, 0x5ccdf74, 0xd3e01ff, 0x101b4c7, 0x9680aaf, + 0x2fc50a6, 0xd2a7be1, 0xb72d782, 0x92a788d, 0x4640b52, 0x35daf2e, + 0x39e601c, 0xc170d69, 0x7b25c2f, 0x16e05f5 }, + { 0x6fe37f8, 0x47a42a6, 0xbeca298, 0xeb74271, 0x179da16, 0x401e11e, + 0xaa53873, 0xfb8da82, 0x5bb4783, 0xd657d63, 0xfcea0b1, 0x6847758, + 0x0993154, 0x2f261fb, 0x592853a, 0x868abe3 } + }, + { + { 0x35766ab, 0x1a4c543, 0x6f4e4ea, 0xa1c84d6, 0x60ba199, 0x5d737a6, + 0x98b15a2, 0x4a7b1e2, 0xfd967d3, 0x207877f, 0xc262b4d, 0xcaec82d, + 0x4f2a37d, 0x0b27849, 0x6ac1711, 0x3478141 }, + { 0x8fc6856, 0x28e3df1, 0x16d003f, 0xbec03f8, 0xff39ebd, 0x2bd705b, + 0x2d776d3, 0x1dcb53b, 0x5c0e7ce, 0xabafa7d, 0x4a53332, 0x5b9c8c2, + 0x9d90214, 0xe9f90d9, 0xc129690, 0x789747e } + }, + { + { 0x54e2dfa, 0x94d3c39, 0xafb2a8f, 0x919f406, 0x34e3927, 0x159ef05, + 0xa165c37, 0xcdb4d14, 0x288f337, 0xa23e5e8, 0x0f90242, 0x95867c0, + 0xe34e781, 0x2528150, 0x6657b95, 0x104e501 }, + { 0xbcdda24, 0x695a6c9, 0x23eb5fa, 0x609b995, 0x16a60f8, 0xcbce4f5, + 0xf084a29, 0xec63f7d, 0x20c811f, 0x3075ada, 0x8c716a1, 0x129a192, + 0xcd4cd4a, 0xd65f4d4, 0x62188be, 0xe18fa9c } + }, + { + { 0xbac60e3, 0x1672757, 0x577144b, 0x525b3b9, 0x887055b, 0x38fc997, + 0x31e4408, 0x7a77126, 0xcba2fcf, 0x884f173, 0x5962ac0, 0x783cbdc, + 0x22287dc, 0x4f3ed0a, 0x50e20e6, 0x8a73e34 }, + { 0xd764583, 0xe7a1cd0, 0x0d58ee6, 0x8997d8d, 0xaa13ed6, 0x0ea08e9, + 0xcf363cb, 0xed478d0, 0x5b37bf4, 0x068523d, 0x783f13c, 0x8b5a9e8, + 0x87528a9, 0xde47bbd, 0xcaec313, 0xd6499cc } + }, +}, +{ + { + { 0xe09859d, 0x54781bb, 0x7f5e648, 0x89b6e06, 0x7075824, 0xb006dfe, + 0x0717f68, 0x1731660, 0x0b4efe2, 0x9c86554, 0x5e30d8e, 0xdbdb257, + 0x3b4d50f, 0xa6a5db1, 0xfa47beb, 0x3b5662c }, + { 0x89d4a59, 0x9d4091f, 0x550a7dc, 0x790517b, 0xc52965e, 0x19eae96, + 0xb5ed7a4, 0x1a7b3c5, 0xeb16541, 0x19e9ac6, 0xef66852, 0x5f6262f, + 0xc4cda27, 0x1b83091, 0x3bf742b, 0xa4adf6f } + }, + { + { 0xa5100e7, 0x8cc2365, 0x8592422, 0x3026f50, 0x3d714d0, 0xa4de79a, + 0x90fcb30, 0xefa0d3f, 0x474ada0, 0x126d559, 0xc94350a, 0xd68fa77, + 0x0c7cb45, 0xfa80e57, 0x3985fbf, 0xe042bb8 }, + { 0xfe13dba, 0x51c80f1, 0xcf055d7, 0xeace234, 0x73f95f7, 0x6b8197b, + 0xdcdbe89, 0x9ca5a89, 0xdfd9896, 0x2124d5f, 0x9e7ca37, 0x7c69556, + 0x8babb37, 0x58e806a, 0xbaf99ce, 0x91b4cc7 } + }, + { + { 0x197e968, 0x874e253, 0x3160668, 0x36277f5, 0x8b95dbe, 0x0b65dda, + 0xf0872a1, 0x477a792, 0x314268d, 0x03a7e3a, 0x0c805c7, 0xa96c842, + 0xb7bc4a8, 0xb941968, 0x75db390, 0x79dce30 }, + { 0x6f4cc14, 0x577d4ef, 0xb5d1107, 0x5b0d205, 0x9f93624, 0x64ff20f, + 0x5034a2f, 0x0b15e31, 0x8b6f35c, 0x3a0f6bb, 0xe0d0ec5, 0x0399a84, + 0x0d5d521, 0xd0e5823, 0xcb1dd54, 0xdeb3da1 } + }, + { + { 0x182401a, 0x24684ae, 0x21a706f, 0x0b79c1c, 0xd8998af, 0xe1d81f8, + 0x4bb069f, 0xadf870f, 0xf3dd7aa, 0xd57f85c, 0xe4a40f8, 0x62d8e06, + 0x8b55aa1, 0x0c5228c, 0xa9c0a1a, 0xc34244a }, + { 0x68f544e, 0xb5c6cf9, 0xde23ab7, 0xa560533, 0x47c690c, 0xaa55120, + 0x12aaaa6, 0x20eda5b, 0x751a6a0, 0xea0a49a, 0x2baa272, 0x6d6cfff, + 0xbf4c28a, 0x95b756e, 0xe6178a4, 0xd747074 } + }, + { + { 0x221a94b, 0xa27b453, 0xe635f20, 0xd56ad13, 0x8c95117, 0x03574b0, + 0xed30b70, 0xf0ee953, 0x957796f, 0xb48d733, 0x58c336b, 0xf5d9583, + 0x82db529, 0x6170cd8, 0xec9d1ea, 0xcd3ef00 }, + { 0xe4d105f, 0xd1bea0d, 0xad6a559, 0xd2d670f, 0x52f9690, 0x652d012, + 0xc2529b0, 0x5f51fb2, 0xe89df2a, 0x5e88bf0, 0xcd686e4, 0x9a90684, + 0x882c7a1, 0xf519ccd, 0xc2f4d37, 0x933a0df } + }, + { + { 0x3f66938, 0x0720a9f, 0xd8149df, 0x99356b6, 0xa3d7f61, 0xb89c419, + 0x4ba6e31, 0xe658134, 0xab936c8, 0xd130561, 0x40dbef1, 0x0625f6c, + 0xb6bb847, 0x7b2d6a2, 0x84d506b, 0x3ca8b29 }, + { 0xfb011b0, 0x6bf729a, 0x33448c9, 0x01c3078, 0x0837420, 0x6ae9508, + 0xa207fb8, 0xf781a8d, 0x57562a9, 0xcc54d58, 0x858c5ab, 0xc9b7364, + 0x359908f, 0xdfb5035, 0x9631138, 0x8bf77fd } + }, + { + { 0xc13fbb1, 0xf523365, 0x9993ed5, 0x88532ea, 0x5a73492, 0x5318b02, + 0xe5a8f3c, 0x94bff5c, 0x306c2a0, 0x73f9e61, 0xf2668a3, 0x00abbac, + 0x076237d, 0x23ce332, 0x34c0f9b, 0xc867f17 }, + { 0xcfd2136, 0x1e50995, 0xb2b70f8, 0x0026a6e, 0x5077a7d, 0x66cb184, + 0xa3b498e, 0xc31b2b8, 0x260ec86, 0xc12035b, 0xe1b3df0, 0x1cbee81, + 0x8d55a42, 0xfd7b804, 0xf47a8c8, 0x912a41c } + }, + { + { 0x9e157e3, 0xab9ffe7, 0x44dc158, 0x9cfe46d, 0x8a4a3ef, 0x435551c, + 0x3b7e3a8, 0x638acc0, 0x49954a7, 0x08a4ebd, 0x13194f7, 0x295390c, + 0x253892a, 0x3a2b68b, 0x25d5b11, 0xc1662c2 }, + { 0x3a5d2bb, 0xcfba072, 0xcc327c9, 0xffaf6d3, 0xc67e254, 0x6c6314b, + 0x2f32208, 0x6661631, 0xbea72e1, 0xf780f97, 0x002122f, 0x495af40, + 0x7578a99, 0x3562f24, 0x77ce51e, 0x5f479a3 } + }, +}, +{ + { + { 0x1a82a12, 0x91a5884, 0x80f3a62, 0xa754175, 0xf73417a, 0x399009f, + 0x0a8c5cd, 0x2db1fb9, 0xc046d51, 0x82c8912, 0x8f18274, 0x0a3f577, + 0x26ccae2, 0x2ad0ede, 0x8a4e9c2, 0x7d6bd8b }, + { 0x4b3de44, 0xaa0d797, 0x96ac9bb, 0xf8658b9, 0x5f6c334, 0x31e7be2, + 0x4df12c9, 0x23836ce, 0x59eb5c9, 0x029027b, 0x5b8649d, 0x2f22531, + 0xd907162, 0xa0fdf03, 0x9e80226, 0x101d9df } + }, + { + { 0x9a90835, 0xf12037a, 0xf0222a7, 0xd2d0882, 0xc3814e2, 0xeaf8d40, + 0x8b8146b, 0xa986dc6, 0x8504653, 0x147a331, 0x2feaf67, 0x734e003, + 0x602bec5, 0x6f27bbf, 0x6a688f3, 0xa1e21f1 }, + { 0x73c4ae5, 0x5a8eeab, 0xe70b412, 0x4dbaddb, 0xcfd2af1, 0x871ceba, + 0x7d7a286, 0x1860382, 0xb5bb401, 0x024059d, 0x3c39b73, 0x2557c09, + 0x6681697, 0xfc5a711, 0x891b57c, 0xf881c0f } + }, + { + { 0x8ea191a, 0x3c443f1, 0xd700ad0, 0x76faa58, 0xbe7fcbf, 0x6fe6cfa, + 0x8990ef7, 0xaefc528, 0x80004cc, 0x44e30fa, 0x6d8ef85, 0xc744adc, + 0x912df70, 0xafcd931, 0x572a6d8, 0xf62a9d1 }, + { 0x3219f27, 0x47158a0, 0xad73136, 0x76fb27e, 0xcc2d614, 0x41bb2ad, + 0xde1ec21, 0x8858cb9, 0x5f15866, 0xab402c4, 0xbc82bbf, 0x6675d5b, + 0xf1b28d3, 0x4ee9dd6, 0xe373c17, 0x875884f } + }, + { + { 0x2a67d36, 0x17806dd, 0x32c9ec1, 0xaa23a86, 0xfc1ee55, 0xd914126, + 0x653701b, 0xbf8f7bd, 0xea71367, 0x9b0111a, 0xa98e417, 0x61fd4ab, + 0x561c5a5, 0xeb45298, 0xe7af394, 0x2187b0a }, + { 0x1616dde, 0x71f12db, 0x07da7b4, 0x0617609, 0x02ddb04, 0x414d376, + 0x286fb58, 0x1100be7, 0x6f0d95b, 0xd7cf88d, 0x746d703, 0x8539d23, + 0x4e23d73, 0xdccc9d6, 0xec89680, 0xaeef1d2 } + }, + { + { 0x336508d, 0x82ccf1a, 0x5bad150, 0xa128c1f, 0x29a188d, 0x551d8c0, + 0x771404f, 0xef13dd4, 0xc37b993, 0xdd67696, 0x0dddad2, 0x428c0e2, + 0x038c94c, 0x222278d, 0x078e3f2, 0x1a24a51 }, + { 0xedb0db9, 0xd297fe6, 0x8251a87, 0x00988d2, 0xbfaa0d7, 0xbb946f8, + 0xdf45ea0, 0x380f7b9, 0xafccf5e, 0x8526415, 0xe9ec7bc, 0x909bfbf, + 0x124755c, 0x2ed7093, 0x89404e2, 0x4368028 } + }, + { + { 0x36d9ef1, 0x21b9fa0, 0xe433526, 0xfd64b7c, 0x6544849, 0xd9d7eb7, + 0xd5b54b3, 0x201620c, 0xbb61159, 0x25fab3d, 0xc53e0d3, 0x90d4eb0, + 0x9e74772, 0xba09831, 0xec1681c, 0x8749658 }, + { 0xfec316b, 0xa354349, 0xa743ea2, 0x639a9b1, 0x37c50e6, 0x2e514ca, + 0xdbaf6c5, 0x9f4a4fd, 0x6f511c9, 0x0df87ef, 0x0c00d95, 0xadd4cef, + 0xaa1433f, 0x401c0eb, 0xbb38af9, 0x3c3a59e } + }, + { + { 0xf0e7dca, 0x8706245, 0x3fb29ca, 0xad238cd, 0x9b7d8f0, 0x0330443, + 0x154f495, 0xfdcd6e6, 0x7d4ad09, 0xc67e24a, 0x5438390, 0x1b209e8, + 0xb0c211e, 0xf893b81, 0x7e11e36, 0x1aa86f0 }, + { 0xedea8b1, 0x2cca3ff, 0x3b306cd, 0x7eedd07, 0x12ee222, 0x78e37bc, + 0xbc42a1d, 0x257870b, 0x1fbd397, 0x5fb2bb9, 0x09d6c60, 0x4702470, + 0x20bdc36, 0x11748a3, 0x04280e8, 0x3ff24dc } + }, + { + { 0x9839b52, 0x0eb1c67, 0xacfbd32, 0x5bcca27, 0x74898e3, 0xb506c16, + 0x2489e5e, 0x37d662e, 0xf694887, 0x8dc0731, 0xf43f1dc, 0x571149e, + 0x66d63dc, 0x6430a37, 0xb50dd70, 0x0d2640e }, + { 0x3b2675b, 0x2b56149, 0x88c604f, 0x1b48065, 0xaafbabc, 0x55c86a8, + 0x608aaba, 0xa7b9447, 0x04cad8c, 0xa42f635, 0xcee7788, 0x0f72b1d, + 0x755d99a, 0x1d68374, 0x5be2531, 0xd7cdd8f } + }, +}, +{ + { + { 0xbcdfee1, 0x67873bd, 0xfcd0a3f, 0xa5a0c0a, 0x3cfa3d4, 0x59389f9, + 0xe1c865c, 0x14e945c, 0x1d588cc, 0x62d2f8e, 0x8e228b4, 0xfd02f8a, + 0xb42b649, 0x208f791, 0xab397ad, 0x0e0dff1 }, + { 0x0bc6eb1, 0x30ac3d9, 0x5f313bb, 0xf14f16a, 0xe2a0ad2, 0x70fa447, + 0x5a0db84, 0x6e40685, 0xe32e1e7, 0xd52282b, 0x15ca330, 0x315a02a, + 0x867c2fe, 0x9a57a70, 0x0054923, 0x55f0765 } + }, + { + { 0xc0cf08f, 0x2d729f6, 0xebaf57f, 0x6b80138, 0x0200c25, 0x6285bcc, + 0x2cd2ac7, 0xee84519, 0x922778a, 0x28fce4d, 0xcd1011c, 0x761325c, + 0x5100e47, 0xd01f247, 0xc60d8e1, 0xc7a1665 }, + { 0x7ceb064, 0x950966d, 0x78420db, 0x0a88e85, 0xe096f29, 0x44f2cfc, + 0x640f1d2, 0x9d9325f, 0xd2426f1, 0x6a4a81f, 0x9c905ac, 0x3ed6b18, + 0x008854d, 0xba3c0e2, 0xa0d321b, 0x1df0bd6 } + }, + { + { 0x3feb1e7, 0x0117ad6, 0xf1ae02f, 0xa058ba2, 0x31b3f06, 0x5eee5aa, + 0xafacd4d, 0x540d9d4, 0x1571d91, 0x38992f4, 0xbf2c7de, 0xef2738e, + 0x92a798d, 0x28bfcab, 0x2286733, 0x37c7c5d }, + { 0x6470df0, 0xb99936e, 0x8af6a42, 0x3d762d5, 0xc74eec5, 0xa8c357a, + 0xf13afbc, 0x9917beb, 0xf2dc073, 0x28f0941, 0x6ce7df7, 0x306abf3, + 0xd6973c8, 0xa3c5f6f, 0x3677632, 0x640209b } + }, + { + { 0xe23aef7, 0xee872a2, 0xeb9b08e, 0xb497b6f, 0x3f33c63, 0xfb94d97, + 0x2b32315, 0x9ea1ff4, 0x49a4166, 0x537b492, 0xab4f8be, 0x89c7fe6, + 0xdad8f0f, 0xf68007f, 0x71b8474, 0xe56ef0b }, + { 0x3f333f9, 0x478b2e8, 0xb2607f5, 0x144e718, 0xa4c7ab5, 0x13aa605, + 0x1d0730d, 0xfc1fc99, 0x5ab3ea1, 0xe7a0437, 0x306d8d3, 0xc59986a, + 0x702a8b1, 0x24f6111, 0xe040ad2, 0x7741394 } + }, + { + { 0x60723a7, 0x34c6a25, 0xf4ea691, 0x8aabd0d, 0x5d7497f, 0x9d676a5, + 0x7d91fa4, 0x12c0957, 0x6479284, 0x581c7a8, 0xf4fd449, 0xa54f3da, + 0x4ef44cf, 0x2f89f3c, 0xc9ec97c, 0xfc266b5 }, + { 0x88b142a, 0xfcd3fbe, 0x4bd69c1, 0x9f3109f, 0xb5f5a6a, 0x08839c0, + 0x2e68303, 0x63ca850, 0xbba0a74, 0x2f0628d, 0x5d56b54, 0x743cccf, + 0x13e09fd, 0xbd4b066, 0xde2ba3e, 0x7a8415b } + }, + { + { 0xc076ab2, 0x2234a3b, 0x4977a98, 0xd6953e5, 0x31ebe2e, 0xc122158, + 0xbad78e2, 0x632145f, 0xa5c4b08, 0xd7ba78a, 0x998e32a, 0x6f4ea71, + 0x3485a63, 0x25900d2, 0x6a5176f, 0x97ac628 }, + { 0x1093f7b, 0x5df9118, 0xc844563, 0x2bf9829, 0x6272449, 0x525d99d, + 0xb5c8a18, 0x4281cb5, 0x0544a08, 0x35df278, 0xbaeb8f4, 0xf4c3d2d, + 0x5230447, 0xc7ff317, 0x5d2fbff, 0x6b4d764 } + }, + { + { 0x2b0c9cb, 0x4837f80, 0x8ce8418, 0xb65f816, 0x9fc1428, 0xdf66ea9, + 0x04ea7e8, 0x9788ee8, 0x8334e3c, 0x9eae900, 0xd6ba1b6, 0xbc91058, + 0xd7064b6, 0x634aba1, 0x397b368, 0x12d9bb3 }, + { 0xc413aa8, 0x0645c85, 0xac6b5e3, 0xb09dea6, 0x289a50b, 0x29a620d, + 0xbbcceb1, 0x104db3b, 0x87b3309, 0x42e4792, 0xec97f01, 0xdfc373e, + 0xb93f84e, 0xe953f94, 0x052dfbf, 0x3274b7f } + }, + { + { 0x1bd6fa9, 0x9d5670a, 0xdb6c4d4, 0xec42fc9, 0x1b42845, 0xaecd4ed, + 0x1b03549, 0x4eed90e, 0xbbab1fa, 0xeb3225c, 0x28a2816, 0x5345e1d, + 0x0b77d2a, 0x3741cfa, 0x7ea8caa, 0x712b19f }, + { 0x661853e, 0x42e6844, 0xe4a6e5d, 0x4cf4126, 0xc3649f6, 0x196a9cf, + 0xf21b6b1, 0x06621bc, 0x32e29ea, 0x887021c, 0x8c5680f, 0x5703aeb, + 0x660f6d7, 0x974be24, 0xc71864e, 0xaf09bad } + }, +}, +{ + { + { 0xa81b6d3, 0x3483535, 0xca037dc, 0x19e7301, 0x63ddfeb, 0x748cab7, + 0x6f01a38, 0xe5d87f6, 0x2795cd6, 0xbba4a5c, 0x615c36c, 0x411c5d4, + 0x706f412, 0xff48efc, 0x4b519df, 0x205bafc }, + { 0x5227110, 0xfcaa5be, 0x3ad0af0, 0x7832f46, 0x2642b1b, 0x34ef2c4, + 0x072f822, 0x7bbef7b, 0x923a616, 0x93cb0a8, 0x6d91ba7, 0x5df0236, + 0x42f7d21, 0x5da94f1, 0xa14e891, 0x3478298 } + }, + { + { 0xc831d39, 0xad79a0f, 0x4803c44, 0x24d1948, 0x86aeeb2, 0x4f8a864, + 0x926f6b9, 0x0ca284b, 0x1acd7cd, 0x501829c, 0x3d12c52, 0x9f6038b, + 0xf371ef5, 0x77223ab, 0x13bf4de, 0x2e03516 }, + { 0xb4468cc, 0x7a5a4f2, 0x470ae46, 0xdcea921, 0x11be696, 0xf23b7e8, + 0x720d6fb, 0xe59ad0d, 0x2983469, 0x9eacac2, 0xc4397ee, 0x4dd4110, + 0xcbe2675, 0x4ef85bd, 0xaa7c74b, 0xe4999f7 } + }, + { + { 0x8ea1e98, 0x031838c, 0x04d96a2, 0x539b383, 0x163956e, 0x5fbdef0, + 0xce3f52a, 0x6bd4d35, 0x55e897f, 0xe538c23, 0x472dd3f, 0x6078d3a, + 0xca9f452, 0x590241e, 0xfd7fc07, 0x2bc8495 }, + { 0xead4c8c, 0x23d0c89, 0x601c66e, 0x1ea55a9, 0x4f5b833, 0x41493c9, + 0xaa5a978, 0xc49a300, 0x0c69594, 0xc98bdc9, 0xccbdc8c, 0x4e44ced, + 0x6adccbf, 0xb0d4e91, 0x32c37ae, 0xd56e36b } + }, + { + { 0x5b93152, 0x052bd40, 0x4f1dbfa, 0x688b1d4, 0xbe5cc5f, 0xe77ba1a, + 0xa6ac543, 0x11f8a38, 0xe4bb988, 0x3355fd6, 0xf8dffb4, 0xdf29c5a, + 0x81f20ee, 0x751f589, 0xda9b7fb, 0x22a0f74 }, + { 0x6397b49, 0xec8f2bc, 0x3639201, 0xff59fc9, 0xa048264, 0xb7f130a, + 0xafdc4cc, 0xe156a63, 0xb13acaf, 0x0fd7c34, 0x0cb4999, 0x87698d4, + 0x7f26f24, 0x6d6ecae, 0x0f296e2, 0xae51fad } + }, + { + { 0xdd0f58d, 0xd0ad5eb, 0x5c67880, 0x6ec6a2c, 0x9af1e0f, 0xe1ce034, + 0x3996d32, 0x0801485, 0x5e69d20, 0x59af51e, 0xaa48ecf, 0x0ef743a, + 0x7dafcb0, 0x8d3d2ea, 0x89189b6, 0x4ac4fad }, + { 0xeae97f1, 0x92d91c2, 0x62b4662, 0xef5eca2, 0xb38b10a, 0x440b213, + 0xfc661da, 0xec90187, 0xf64cf8d, 0x85f3f25, 0x457ad1b, 0xcee53ca, + 0xf517672, 0x8deed4b, 0x4761828, 0x7706fb3 } + }, + { + { 0x17494fe, 0x1577d91, 0x2fd7239, 0x52d29be, 0x0186d37, 0x9a0eef0, + 0x27fe108, 0x241d0f5, 0xe6fb59f, 0x42824ba, 0x0d48c25, 0xb8d33df, + 0x47af4b0, 0xfffdb0a, 0x073b0b6, 0x534c601 }, + { 0x51c033b, 0xe6df359, 0x86c0f94, 0x3e1002b, 0x48fb9b6, 0xa7cb555, + 0xa7bbff8, 0x999818b, 0x84d8bf2, 0xe4ba3d6, 0x6358f0a, 0x53dbb32, + 0xf2568e8, 0xeebc1e2, 0xb3e0f68, 0xc6917eb } + }, + { + { 0x19f8d13, 0xbe1bbfc, 0x2d4795c, 0xc3951b6, 0xed535a9, 0x9371c49, + 0x68cebea, 0x77c389f, 0xa141d0e, 0xfc1a947, 0xde44f8b, 0x4b48d7a, + 0x8580a26, 0x3db1f05, 0x258b5fc, 0xeed1466 }, + { 0x9854b21, 0x5daa4a1, 0x1ab1ead, 0x5bfa46f, 0x59957eb, 0xc152e35, + 0xea48ada, 0xdc84277, 0xfc169b5, 0x68709cf, 0x720e617, 0xde50ce3, + 0xdd9a832, 0xe42f262, 0x2d6ce29, 0xddffd4d } + }, + { + { 0x8fa0a56, 0xd5ba557, 0xfafaf4c, 0x0d7d0f1, 0x38b63ed, 0x7666e41, + 0x5d87f02, 0x04e6513, 0xc958f32, 0xdca8866, 0x3ce2686, 0xaa8486d, + 0xf1cbcd3, 0xe3785ca, 0x03c8335, 0x8a9b114 }, + { 0x2e0ef60, 0x5c1dca2, 0x7d3fb20, 0x775af5b, 0x2b373a8, 0xe690ffc, + 0x28330e6, 0x30fe15d, 0xdd0f393, 0x8a1022b, 0x966a828, 0x6bd7364, + 0x949208a, 0x8d4b154, 0xb9d9828, 0xfb38c6b } + }, +}, +{ + { + { 0x0340ac2, 0x6d19764, 0xecab5ff, 0x969f473, 0xc458e42, 0xead46f7, + 0x1d00eed, 0x168646a, 0xe0ce0cf, 0xf70c878, 0x8d8d15a, 0xa7291d3, + 0xfdd10cc, 0x92cf916, 0x24f86d5, 0x6d36134 }, + { 0x2d5c4b4, 0xba50d17, 0x4626f15, 0xe0af502, 0xd76098a, 0x76f3809, + 0xd6caaa8, 0x433dc27, 0x70d97a7, 0x72dc67a, 0xf5c7355, 0x935b360, + 0x179bb31, 0xdbaac93, 0x7ed1a33, 0x7673848 } + }, + { + { 0x8f9fa0d, 0x8d1ca66, 0xa02f2bf, 0x4ed95d8, 0xf630d7b, 0xd19fc79, + 0xf46fa51, 0x0448ec4, 0x623bf3f, 0xb371dd8, 0xd650e94, 0xe94fabc, + 0xcd90a70, 0x3af3fca, 0x03ce3b7, 0x0f720c4 }, + { 0xd636c3b, 0x590814c, 0x4469945, 0xcf6928d, 0x484a4c6, 0x5843aaf, + 0xf9b4722, 0xb5a4c1a, 0x6cfb2f9, 0x25116b3, 0x32c2640, 0xf248cf0, + 0x27412a1, 0x8cd059e, 0x862fc5d, 0x866d536 } + }, + { + { 0x6de4a2e, 0x156e62f, 0xaafcc78, 0x0365af7, 0x19e925e, 0x65c8618, + 0xf8b2191, 0x4db5c01, 0xad564fa, 0x1fd26d1, 0x19c8610, 0x16bbc53, + 0x815f262, 0x0718eef, 0x27f83d1, 0x8684f47 }, + { 0xb0f48db, 0xa30fd28, 0x6ab8278, 0x6fef506, 0x1a652df, 0xd164e77, + 0xc6ebc8c, 0x5a486f3, 0xdc3132b, 0xb68b498, 0xd73323f, 0x264b6ef, + 0x69b2262, 0xc261eb6, 0x2a35748, 0xd17015f } + }, + { + { 0x7c4bb1d, 0x4241f65, 0xf5187c4, 0x5671702, 0x3973753, 0x8a9449f, + 0xcc0c0cd, 0x272f772, 0x58e280c, 0x1b7efee, 0x4b5ee9c, 0x7b32349, + 0x31142a5, 0xf23af47, 0xd62cc9e, 0x80c0e1d }, + { 0x675ffe3, 0xcbc05bf, 0x258ce3c, 0x66215cf, 0x28c9110, 0xc5d2239, + 0x2a69bc2, 0x30e12a3, 0x76a9f48, 0x5ef5e80, 0x2329d5f, 0x77964ed, + 0x8a72cf2, 0xdf81ba5, 0x6e1b365, 0x38ea70d } + }, + { + { 0x2f75c80, 0x1b18680, 0x698665a, 0x0c153a0, 0x522e8dd, 0x6f5a7fe, + 0x8ddfc27, 0x9673866, 0x0d3bdce, 0x7e421d5, 0x25001b2, 0x2d737cf, + 0x0e8490c, 0x568840f, 0xe30c8da, 0xea2610b }, + { 0x9561fd4, 0xe7b1bc0, 0x26decb0, 0xeda786c, 0x6a76160, 0x2236990, + 0x78a3da3, 0x371c714, 0x2a2d9bf, 0x1db8fce, 0x3292f92, 0x59d7b84, + 0x5a665f9, 0x8097af9, 0x542b7a9, 0x7cb4662 } + }, + { + { 0xc6b0c2f, 0xa5c53ae, 0x7312d84, 0xc4b8732, 0xc732736, 0xfc374cb, + 0x9310cc0, 0xa8d78fe, 0x65d1752, 0xd980e86, 0x6004727, 0xa62692d, + 0x0146220, 0x5d07928, 0x860fea5, 0xbd1fedb }, + { 0xb35d111, 0xcbc4f8a, 0x3e32f77, 0x5ba8cdf, 0xb614b93, 0xd5b71ad, + 0x2f8808d, 0x7b3a2df, 0x6ef2721, 0x09b89c2, 0x47c3030, 0x55a5054, + 0x2986ae6, 0x2104431, 0x2367d4c, 0x427a011 } + }, + { + { 0xc1942d8, 0xe9fe256, 0x96e3546, 0x9e7377d, 0xb0c1744, 0x43e734c, + 0x211fbca, 0x5f46821, 0x32b6203, 0x44f83dc, 0x6ad1d96, 0x8451308, + 0x2fbb455, 0x54dd519, 0x2f10089, 0xc2a1822 }, + { 0x1855bfa, 0x01055a2, 0x77078b4, 0x9e6d7b4, 0x30cea0e, 0x3f8df6d, + 0x32973f7, 0x81c2150, 0xc0b3d40, 0x17dd761, 0x50d0abe, 0x040424c, + 0x783deab, 0x5599413, 0x8f3146f, 0xde9271e } + }, + { + { 0xaf4a11d, 0x5edfd25, 0x7846783, 0x3a3c530, 0x73edd31, 0xb200868, + 0xfe0eef8, 0x74e00ec, 0x3dd78c7, 0xba65d2f, 0x71999f1, 0xab13643, + 0xde9a7e8, 0xfa9be5d, 0x87a8609, 0xeb146ce }, + { 0x65353e9, 0x76afd65, 0xd51ba1c, 0xfa7023d, 0x37ede4f, 0x7a09f22, + 0x0ba7a1b, 0xca08576, 0xb99950a, 0xd973882, 0xea5057a, 0xe894266, + 0x7f55e49, 0xd01c421, 0x5555679, 0x69cfb9c } + }, +}, +{ + { + { 0xc5d631a, 0x67867e7, 0x5bcf47b, 0x1de88c5, 0xafd1352, 0x8366d06, + 0x6e20337, 0xd7dbdef, 0x1253ec7, 0xb0f9e2f, 0x10ad240, 0x1be9845, + 0xf4a6118, 0x63ec533, 0x96ce633, 0xd5e4c5b }, + { 0x4df4a25, 0x1d0b6c3, 0x5a1b554, 0xef9486a, 0x47b6ef3, 0x2f0e59e, + 0x2ff84d7, 0x4d8042f, 0xda359c9, 0x3e74aa3, 0xd21c160, 0x1baa16f, + 0x0191cba, 0xb4cff21, 0xebc6472, 0x50032d8 } + }, + { + { 0x1fc1b13, 0xb6833e0, 0x1a5ad8f, 0x8a8b7ba, 0x622b820, 0xc0cafa2, + 0x738ed20, 0xc6663af, 0x8b18f97, 0xd894486, 0x774fbe4, 0xcf0c1f9, + 0x5be814f, 0xeedd435, 0xb57e543, 0xd81c02d }, + { 0x310bad8, 0x5e32afc, 0x9b813d1, 0x065bc81, 0x3142795, 0x8efc5fc, + 0x732d59c, 0x5006514, 0x2b5a3ce, 0x91e39df, 0xfaf4204, 0x2ad4477, + 0x4d9bd4f, 0x1a96b18, 0xa4d9c07, 0xc3fee95 } + }, + { + { 0x6b4ba61, 0xfac7df0, 0x061aaef, 0xa6ed551, 0x133f609, 0x35aa2d6, + 0x20ed13d, 0x420cfba, 0xea03d0c, 0x861c63e, 0xf936d6e, 0x75f0c56, + 0x3d9a3d5, 0xa25f68f, 0xcd9f66e, 0xba0b7fe }, + { 0x4680772, 0x292e135, 0xa73f405, 0x6f6a2db, 0x24ea9e4, 0xca6add9, + 0x268daaa, 0x81cfd61, 0xe6f147a, 0x7a4cb6c, 0xbded8f5, 0x8ec3454, + 0x11d61cb, 0xc8a893b, 0x7656022, 0x2256ffc } + }, + { + { 0x575cb78, 0x6b33271, 0xadcd23e, 0x560d305, 0xd6d834b, 0xeedbd3a, + 0x5a31e27, 0x614a64a, 0x47ee0c8, 0xe40b476, 0x8bd7c2c, 0x8ef4ff6, + 0x0b77727, 0xa5297fc, 0xbaf88ad, 0x8759208 }, + { 0x918df68, 0x86cfe64, 0xcdd882e, 0x9d60a73, 0xb953014, 0x546b642, + 0x8bbef55, 0xbaceae3, 0xf1c3467, 0xdf58e43, 0xe9f9bab, 0x99a83fe, + 0x57a4a8b, 0xcd52cbf, 0x8ae36ec, 0xf744e96 } + }, + { + { 0xa607124, 0xb945869, 0x440e6f6, 0x810dbe9, 0x738e381, 0x9911e60, + 0x343b80b, 0x51df68c, 0xf7a3f39, 0xe424336, 0x989015c, 0x2d32acb, + 0x31019e8, 0xa69b149, 0xec12f93, 0x8a31a38 }, + { 0x97c916a, 0x0d0d369, 0x8885372, 0xdc95f3b, 0x3549040, 0xcf1a261, + 0xabe95a2, 0x60f6f5e, 0xe141325, 0xa909e9f, 0x355c865, 0x7d598f2, + 0x931a9c9, 0x70c6442, 0xb423850, 0x2354a85 } + }, + { + { 0x97f9619, 0x4cdd224, 0xc22162e, 0x4776fff, 0x0cd31c2, 0xee5ec33, + 0xf209bb8, 0x7c04c10, 0x579e211, 0x35bbfde, 0x15cdfc2, 0x0e38325, + 0xe26ffa7, 0x657e6d3, 0xc65c604, 0xc66a7c3 }, + { 0xb45e567, 0x322acd7, 0x296db9b, 0x1589cf0, 0xba1db73, 0x1fd0bd3, + 0x9337a40, 0xe882610, 0xb3035c7, 0xf505a50, 0x6ed08d7, 0x4d5af06, + 0x5eda400, 0xb3c376b, 0x1944748, 0x9c7b700 } + }, + { + { 0x70c3716, 0xd768325, 0xdd540e0, 0xda62af0, 0x6580fea, 0x76b155d, + 0x32b5464, 0x4f42acc, 0x3f5b72b, 0x881bb60, 0xe68b9ba, 0x09c130e, + 0x5c50342, 0x37ede3b, 0xfd15e7d, 0xce61a9c }, + { 0x72605d0, 0xfff1d85, 0x062abc2, 0x62ac2d3, 0xfbe43dd, 0xa85e02e, + 0xa947020, 0x859d2ba, 0x111c20b, 0x2ebc8a9, 0xa656f66, 0x7f590a7, + 0x16b21a6, 0x0e13843, 0x00c7db6, 0x29b30c5 } + }, + { + { 0x906b8de, 0x61e55e2, 0x949974d, 0x6a97e96, 0x26eef67, 0x24b52b5, + 0x1aa595a, 0x512f536, 0x3c48fcb, 0x81cc7b8, 0x28115ad, 0xa64af23, + 0x3d44b8e, 0x9edf6f9, 0x1fe22e3, 0x68d7f7c }, + { 0x520d151, 0x2b2116a, 0x6aa3efb, 0x66a0b7d, 0x9b0f791, 0x48ae70a, + 0x037db88, 0xcf12174, 0x317d9f3, 0x36868cd, 0x22fc344, 0xb573059, + 0x46a5d23, 0xbaa8526, 0x37fc10d, 0xad65691 } + }, +}, +{ + { + { 0x12c78d5, 0xcf8e5f5, 0x805cdbd, 0xeb94d98, 0x2ab50b5, 0xad1dcdf, + 0xf33cd31, 0xf33c136, 0x10aeff5, 0x0d6226b, 0xf2f8fc5, 0xf7ff493, + 0xdf57165, 0x7e520d4, 0x05271a7, 0x41fbae5 }, + { 0x76480ba, 0x72c8987, 0x25f4523, 0x2608359, 0x49f5f01, 0xed36b8d, + 0xf3d49eb, 0x3bc1dce, 0x4940322, 0x30c1c1a, 0x7e0f731, 0x78c1cda, + 0x6d05a31, 0x51f2dc8, 0x07f3522, 0x57b0aa8 } + }, + { + { 0x71f88bc, 0x7ab628e, 0x8018f21, 0xcf585f3, 0x13d64f6, 0xdbbe3a4, + 0xec493a5, 0x0f86df1, 0x7725de9, 0x8355e6c, 0xe00fe1e, 0x3954ffe, + 0x9924e32, 0xbb8978f, 0x7812714, 0x1c19298 }, + { 0xaabca8b, 0x7c4ce3e, 0x9bf7019, 0xf861eb5, 0x682e541, 0x31a84fc, + 0xacd1b92, 0x2307ca9, 0x4bf2842, 0x6f8b6ce, 0xcb9f9a9, 0xde252ac, + 0x93c46d1, 0x7f0611d, 0x751dc98, 0x8e2bd80 } + }, + { + { 0xe27d54b, 0xf2fd8fb, 0xc248071, 0x2a1e37e, 0xab8f49a, 0x2fcc888, + 0xc18a9e5, 0x42c62a3, 0x70b2446, 0xe302908, 0xc5ac55d, 0x90277fa, + 0xd6dde41, 0x8d97d56, 0x5db04fe, 0xf4cf8a9 }, + { 0xd30d077, 0x3e280f5, 0x3cb3293, 0x2c90307, 0x24eb0dd, 0xe0be2ac, + 0x8bcb4f0, 0xa2d1a49, 0xcd0cd45, 0x16db466, 0x9a80232, 0x3b28aa7, + 0x17b008e, 0xdd7e52f, 0x868e4da, 0x20685f2 } + }, + { + { 0x7c7a486, 0x0a68c14, 0xc429633, 0xd8ef234, 0xffe7506, 0x470667b, + 0x8828d51, 0x55a13c8, 0x2e44bef, 0x5f32741, 0x5929f92, 0x537d92a, + 0x31c5cd5, 0x0a01d5b, 0x67eb3d7, 0xb77aa78 }, + { 0x8b82e4d, 0x36ec45f, 0xb37b199, 0x6821da0, 0xd7fa94e, 0x8af37aa, + 0x1085010, 0xf020642, 0x7e56851, 0x9b88678, 0x52948ce, 0x35f3944, + 0xafc1361, 0x125c2ba, 0x453e332, 0x8a57d0e } + }, + { + { 0x8043664, 0xefe9948, 0xdb1aa55, 0xb8b8509, 0x332523f, 0x1a2e5a9, + 0x1045c0f, 0x5e255dd, 0x7ae7180, 0xe68dd8a, 0x45bf532, 0x55f1cf3, + 0xe63a716, 0xe00722e, 0x6116bac, 0xd1c2138 }, + { 0x1c6d1f4, 0x626221f, 0x3773278, 0x240b830, 0x88def16, 0xe393a0d, + 0xca0495c, 0x229266e, 0xd3e4608, 0x7b5c6c9, 0x7927190, 0xdc559cb, + 0xc7b3c57, 0x06afe42, 0xb439c9b, 0x8a2ad0b } + }, + { + { 0xffc3e2f, 0xd7360fb, 0xfbd2e95, 0xf721317, 0x5748e69, 0x8cacbab, + 0x9054bb9, 0x7c89f27, 0xaa86881, 0xcbe50fa, 0x75206e4, 0x7aa05d3, + 0xc752c66, 0x1ea01bc, 0x1f2c2bc, 0x5968cde }, + { 0x09a853e, 0x487c55f, 0xe09204b, 0x82cbef1, 0xabd8670, 0xad5c492, + 0xf12dcb3, 0x7175963, 0xbf6aa06, 0x7a85762, 0xf8d5237, 0x02e5697, + 0x37c6157, 0xccf7d19, 0xc2fd59c, 0x3b14ca6 } + }, + { + { 0x1b9f77f, 0x5e610d8, 0x051b02f, 0x85876d0, 0xb8020dd, 0x5d81c63, + 0xd6ce614, 0xd0b4116, 0xaa8bf0c, 0x91810e5, 0xcbf8c66, 0xf27f91f, + 0x38480ae, 0x2e5dc5f, 0xbec7633, 0x0a13ffe }, + { 0x2bf6af8, 0x61ff649, 0x641f827, 0xe6aef2d, 0x5de5f04, 0xad5708a, + 0xcdfee20, 0xe5c3a80, 0x68fcfa2, 0x88466e2, 0xd6e1d7b, 0x8e5bb3a, + 0xed236b8, 0xa514f06, 0xa5f5274, 0x51c9c7b } + }, + { + { 0xf9bc3d8, 0xa19d228, 0x3381069, 0xf89c3f0, 0x5c3f379, 0xfee890e, + 0x32fb857, 0x3d3ef3d, 0x5b418dd, 0x3998849, 0xc46e89a, 0x6786f73, + 0x9e0f12f, 0x79691a5, 0x3bc022b, 0x76916bf }, + { 0x2cd8a0a, 0xea073b6, 0x102fdbc, 0x1fbedd4, 0xcb9d015, 0x1888b14, + 0x76655f7, 0x98f2cfd, 0x59f0494, 0xb9b5910, 0xe6986a3, 0xa3dbbe1, + 0xeaf2b04, 0xef016a5, 0xcd2d876, 0xf671ba7 } + }, +}, +{ + { + { 0x1ae05e9, 0x1dae3bf, 0x1f21fef, 0x6a02996, 0x7aec3c6, 0x95df2b9, + 0xd83189b, 0x9abbc5a, 0x2d13140, 0xaf994af, 0x86aa406, 0xc3f8846, + 0x75284c5, 0xcd77e50, 0x2a9a4d7, 0x1c1e13d }, + { 0x744b89d, 0x7f8815d, 0x2ba673e, 0xb189133, 0xd594570, 0x55ea93c, + 0xd61b041, 0x19c8a18, 0x8d2c580, 0x938ebaa, 0x05ba078, 0x9b4344d, + 0x8eaf9b7, 0x622da43, 0x9fea368, 0x809b807 } + }, + { + { 0xc33b7a2, 0x3780e51, 0x387b1c8, 0xd7a205c, 0x4be60e4, 0x79515f8, + 0x1e18277, 0xde02a8b, 0xf0d9150, 0x4645c96, 0xe0b3fd1, 0x45f8acb, + 0x9b53ac3, 0x5d532ba, 0xb0557c9, 0x7984dcd }, + { 0x8a92f01, 0x5ae5ca6, 0x9d569ca, 0xd2fbb3c, 0x0c297c1, 0x668cc57, + 0x6295e89, 0xa482943, 0xa33ad40, 0xf646bc1, 0xc3f425d, 0x066aaa4, + 0xd005de2, 0x23434cd, 0xdb35af4, 0x5aca9e9 } + }, + { + { 0x6877c56, 0x2bca35c, 0xf0ddd7d, 0xab864b4, 0x404f46c, 0x5f6aa74, + 0x539c279, 0x72be164, 0xe0283cf, 0x1b1d73e, 0xad583d9, 0xe550f46, + 0xe739ad1, 0x4ac6518, 0x8d42100, 0x6b6def7 }, + { 0xfa8468d, 0x4d36b8c, 0x5a3d7b8, 0x2cb3773, 0x5016281, 0x577f86f, + 0x9124733, 0xdb6fe5f, 0xe29e039, 0xacb6d2a, 0x580b8a1, 0x2ab8330, + 0x643b2d0, 0x130a4ac, 0x5e6884e, 0xa7996e3 } + }, + { + { 0x60a0aa8, 0x6fb6277, 0xcbe04f0, 0xe046843, 0xe6ad443, 0xc01d120, + 0xabef2fc, 0xa42a05c, 0x12ff09c, 0x6b793f1, 0xa3e5854, 0x5734ea8, + 0x775f0ad, 0xe482b36, 0xf864a34, 0x2f4f60d }, + { 0x84f2449, 0xf521c58, 0x9186a71, 0x58734a9, 0xac5eacc, 0x157f5d5, + 0x248ee61, 0x858d9a4, 0x48149c3, 0x0727e6d, 0xac9ec50, 0xd5c3eaa, + 0x20ee9b5, 0xa63a64a, 0x87be9de, 0x3f0dfc4 } + }, + { + { 0xb13e3f4, 0x836349d, 0x3e9316d, 0xebdd026, 0x324fd6c, 0x3fd61e8, + 0x0964f41, 0x85dddfa, 0x52add1b, 0x06e72de, 0x8c4a9e2, 0xb752cff, + 0xfdf09f7, 0x53b0894, 0x0bc24fd, 0xd5220ab }, + { 0xfb1981a, 0x8442b35, 0x3edd701, 0xa733a37, 0xd0ef089, 0x42b60c3, + 0x46e7bca, 0xa1b16ec, 0xa09aaf4, 0xc0df179, 0x638f3a1, 0xcd4f187, + 0x9eab1c2, 0x9af64f7, 0xd1d78e3, 0x86fed79 } + }, + { + { 0xfe29980, 0x42c8d86, 0x6575660, 0x6657b81, 0x80f92ca, 0x82d52c6, + 0x02d42be, 0x8587af1, 0x6e8bdf0, 0xb515131, 0xc333495, 0x706e2d9, + 0x9673064, 0xd53601a, 0x8219099, 0x27b1fbb }, + { 0x705f7c8, 0x3f0929d, 0xf3d6e6f, 0xff40b10, 0x026af5c, 0x673c703, + 0xe25a422, 0x2c1dce4, 0x3dad8b6, 0x5348bd7, 0xbe2c329, 0xc39b6b6, + 0xb921084, 0x47854ff, 0xb391f20, 0xb347b8b } + }, + { + { 0xeb9b774, 0x79fc841, 0xb4b6c1d, 0xf32da25, 0xfe492cb, 0xcbba76b, + 0xd623903, 0x76c51fc, 0xcf0705a, 0x114cf6f, 0x7815daf, 0x6b72049, + 0x473382e, 0x630b362, 0x9704db5, 0xbf40c3a }, + { 0xc5456eb, 0xa8a9ddc, 0x72f2dc1, 0x2b4472a, 0xd6d6ef3, 0x9874444, + 0xa0ba5ed, 0x27e8d85, 0x194849f, 0x5d225b4, 0xebaa40d, 0xe852cd6, + 0x8d4bf3f, 0xb669c24, 0x2343991, 0xa8601eb } + }, + { + { 0x59502d3, 0x8a04854, 0xe269a7b, 0xcab27ee, 0x4875ada, 0x4179307, + 0xe2405f9, 0x179e685, 0x7b28963, 0x0d7b698, 0x422a43e, 0x80c9db8, + 0xa0f43ee, 0xf5ff318, 0x4ba7aa7, 0x7a92805 }, + { 0x0c0834e, 0xa5c79fe, 0x1f849ec, 0x837ca0d, 0x628ab7b, 0xfe0d7fa, + 0x6edd19a, 0x94bcb95, 0x2226fbf, 0xa18bc93, 0xaad54a3, 0x2795379, + 0x371129e, 0xceeacf8, 0xa588be5, 0x65ca57f } + }, +}, +{ + { + { 0x2caa330, 0x7a578b5, 0xd8ca34a, 0x7c21944, 0x6447282, 0x6c0fbbb, + 0xf90b2e5, 0xa8a9957, 0x6586b71, 0xbbe1066, 0x49138a2, 0x716a902, + 0xe7ed66d, 0x2fa6034, 0x2b9916a, 0x56f77ed }, + { 0xbddefb3, 0x69f1e26, 0x8c08420, 0xa497809, 0x09bc184, 0xc3377eb, + 0xbe6dade, 0x796ce0c, 0xd103bbb, 0x3be0625, 0x992685c, 0x01be27c, + 0x7755f9f, 0xc0e2559, 0x1c0dbfa, 0x165c40d } + }, + { + { 0x659c761, 0xc63a397, 0x630fbad, 0x10a0e5b, 0x655ac56, 0xf21e8a6, + 0xc1181e2, 0xe8580fa, 0x0a84b5c, 0xbfc2d9c, 0x7afd5d1, 0x2cdbaff, + 0xf61e85a, 0x95f1182, 0x719eaf4, 0x1173e96 }, + { 0xc6de8b9, 0xc06d55e, 0xafcbcaa, 0x1b4c8eb, 0xbc2bbcd, 0x52af5cb, + 0x77bcd10, 0x564fab8, 0xae85a6e, 0xfd53a18, 0x94c712f, 0x2257859, + 0x1352121, 0x29b11d7, 0xc40491a, 0xab1cb76 } + }, + { + { 0xce32eb4, 0xb4e8ca8, 0xb250b49, 0x7e484ac, 0xa3e31a2, 0x062c6f7, + 0x625d1fc, 0x497fd83, 0x362dda7, 0x98f821c, 0x6be3111, 0xcae1f8f, + 0x5d4fa42, 0x9077e95, 0xa65855a, 0xa589971 }, + { 0x28832a9, 0xda6321d, 0x3936e9e, 0xf9ef5dc, 0xc9797ef, 0xa37f117, + 0xdb581be, 0x0eb3c80, 0xbaa0002, 0x207c5c4, 0xf38faa0, 0xc0401b5, + 0xd0f1e6e, 0xceee523, 0xd1f0045, 0x8d27a5f } + }, + { + { 0xcf0af29, 0x9411063, 0x89a6693, 0x3043857, 0x640145e, 0x9a9fb8f, + 0x54832eb, 0x7d82fe9, 0x898c520, 0xf2789e1, 0xf948dc0, 0x448b402, + 0x68996dd, 0xeca8fdf, 0xa149b2f, 0x22227e9 }, + { 0x8e62d6a, 0x63509ff, 0x8c9c57f, 0xe98d81c, 0x1fe3bed, 0xd387407, + 0x539538f, 0xf1db013, 0x48418ce, 0xb04092e, 0xd6d9d4d, 0xbbf8e76, + 0x2cec5ae, 0x2ea9cda, 0x5078fa9, 0x8414b3e } + }, + { + { 0xd68a073, 0x5ad1cdb, 0xc18b591, 0xd4cedaf, 0x8e4c1c9, 0x7826707, + 0x9ca302a, 0x9b8d920, 0x326115b, 0x3101bd2, 0x4c2717a, 0x6f154b5, + 0x263e84b, 0x618c31b, 0xbbd6942, 0x12c4138 }, + { 0x80da426, 0xf9ead25, 0x47d9680, 0xe748e99, 0x8a4210e, 0x9b396a3, + 0xf4b8f72, 0xfaf03dd, 0x66159e7, 0xbd94a52, 0x1d4c7cb, 0x5e73049, + 0x7910f38, 0x31d1f9a, 0x08d6dd1, 0x4fd10ca } + }, + { + { 0x9f2331e, 0x4f510ac, 0x7e3dcc2, 0xee872dc, 0xa0a0c73, 0x4a11a32, + 0xaa5a630, 0x27e5803, 0x7af4a8a, 0xe5ae503, 0x9fffeb0, 0x2dcdeba, + 0x719d91f, 0x8c27748, 0xb9cc61c, 0xd3b5b62 }, + { 0xcca7939, 0x998ac90, 0x64514e5, 0xc22b598, 0xb35738a, 0x950aaa1, + 0xdab0264, 0x4b208bb, 0xa557d2e, 0x6677931, 0xf7c17d3, 0x2c696d8, + 0x3e15c51, 0x1672d4a, 0x3db0e82, 0x95fab66 } + }, + { + { 0x6ff205e, 0x3d42734, 0x0ea9fbe, 0x7f187d9, 0x466b2af, 0xbd9367f, + 0x03daf2f, 0x188e532, 0x27b54d8, 0xefe1329, 0xef70435, 0x14faf85, + 0x1ec95c4, 0xa506128, 0xc22cba7, 0xad01705 }, + { 0x6197333, 0x7d2dfa6, 0x8b4f6ed, 0xedd7f07, 0x75df105, 0xe0cb685, + 0x80f76bc, 0x47c9ddb, 0x9073c54, 0x49ab531, 0xe607f44, 0x845255a, + 0xcc74b7c, 0x0b4ed9f, 0x0f5c3a6, 0xcfb52d5 } + }, + { + { 0xc278776, 0x545c7c6, 0x98c30f0, 0x92a39ae, 0xd2f4680, 0x8aa8c01, + 0x6b7f840, 0xa5409ed, 0xdcb24e7, 0x0c450ac, 0xc5770d9, 0x5da6fb2, + 0x8658333, 0x5b8e8be, 0x67ea4ad, 0xb26bf4a }, + { 0xc7d91fa, 0x2e30c81, 0x0eeb69f, 0x6e50a49, 0xee4bc26, 0x9458c2b, + 0x33be250, 0x419acf2, 0x87881ab, 0x79d6f81, 0x403b1be, 0x694565d, + 0x234fe1d, 0x34b3990, 0x2132b38, 0x60997d7 } + }, +}, +{ + { + { 0x26975dc, 0x00a9741, 0x6cf94e7, 0x42161c4, 0xc64ed99, 0xcc9fe4b, + 0x4680570, 0x020019a, 0x698da0d, 0x885595a, 0x77dd962, 0x008444b, + 0xa4fea0e, 0xbf3c22d, 0x2c81245, 0xc463048 }, + { 0x793ab18, 0xcb248c5, 0xeb4320b, 0x4dc7a20, 0x1572b7d, 0x9a0906f, + 0xf9ac20f, 0xd5b3019, 0x34520a3, 0x79b1bf5, 0x69b5322, 0x788dfe8, + 0x455b7e2, 0x9a05298, 0x016bca9, 0x2f4aecb } + }, + { + { 0x8745618, 0x414d379, 0xb7c983c, 0x64ba22e, 0x9f9d532, 0x9a5d19f, + 0x44a80c8, 0x81a00d8, 0xcae98d6, 0xb9e24f5, 0xaca965a, 0x6c3769c, + 0xf6e4e6d, 0x50d6081, 0x54422a6, 0x0d96980 }, + { 0x5cdd790, 0xbd7e792, 0x6a35219, 0xcff65da, 0x8b60ebe, 0x40dc363, + 0x92a50dc, 0x84bee74, 0x15ad65e, 0x57d4be4, 0x1a6d1d3, 0xc54256b, + 0x45717cc, 0x141c649, 0xcd1c736, 0x05eb609 } + }, + { + { 0x1e3c7ec, 0xfd52eab, 0x9f24895, 0xa4a5eca, 0x79fdb83, 0xaaa2a8d, + 0x72bdfda, 0xd105e60, 0x681d97e, 0x59e6ae2, 0x8e8077f, 0xfedf8e0, + 0x629e462, 0xb06d0ad, 0x96fa863, 0x8c7c2d0 }, + { 0xee8fc91, 0x5eecc4c, 0x9e61174, 0x5e83ab2, 0xb28c02d, 0x1fd8925, + 0x2072864, 0x93be538, 0x24c984e, 0xda0c886, 0xa008286, 0xdcf9f0c, + 0xa58ba75, 0x1ecb5a6, 0xc2e3c83, 0x1d9b890 } + }, + { + { 0xeeee062, 0x19e866e, 0x4f7b387, 0x31c1c7f, 0x1c06652, 0x9be6018, + 0x2b68bbb, 0xc00a93a, 0x9d52b2b, 0x54c65d6, 0xe8b744a, 0x4591416, + 0x9a64ab6, 0x641bcca, 0xab08098, 0xf22bcb1 }, + { 0xf1f726c, 0x3c0db8f, 0x9d2e6a6, 0x4f5739e, 0x45c9530, 0x5cb669b, + 0x7b472d0, 0x861b04e, 0x894da77, 0x3e30515, 0xc9ac39b, 0x3344685, + 0x73bdd29, 0x9e17305, 0x808dc85, 0x9cac12c } + }, + { + { 0x5e27087, 0xf152b86, 0x90a580e, 0x267bd85, 0x8baafc1, 0xba79cec, + 0x9442686, 0x6140ab1, 0x5b31693, 0xa67090c, 0x28b4117, 0x50a103a, + 0x0ddc08f, 0x7722e61, 0xe6569b2, 0x5d19d43 }, + { 0x5962bf6, 0x70e0c52, 0xfb5fb02, 0x808e316, 0x5b667be, 0x3fb80da, + 0xfcfacec, 0x8aa366e, 0x134280e, 0xcb0b3e7, 0xcd7d944, 0x0bf1de4, + 0xd092df5, 0x0cd23be, 0xa153a0c, 0xc9a6a79 } + }, + { + { 0x2d5a4b7, 0x1c69ad0, 0xd9e6f4a, 0x4bb28d0, 0xa984fc6, 0x815308c, + 0x9037ca5, 0x40929c7, 0x1bd0357, 0x0ea2b49, 0x42aad4e, 0xec17e5b, + 0x18e7235, 0x1f32ade, 0xa96a9d3, 0xbc60b05 }, + { 0xe20f707, 0x3b0229a, 0x56bdfad, 0xd635050, 0xd8b2e1e, 0xac2d922, + 0x235c748, 0x92b2998, 0xd766f97, 0x6002c3a, 0x1a2a862, 0x9919800, + 0xb58b684, 0x2af7567, 0xaaafce5, 0xd8fe707 } + }, + { + { 0x5df7a4b, 0x54487ab, 0xc57ccc2, 0x51cccde, 0x7510b53, 0x2394327, + 0xf555de3, 0x3a09f02, 0x1be484d, 0xa696aec, 0x37817a2, 0x56f459f, + 0x623dcb4, 0x8d8f61c, 0x5335656, 0xc52223c }, + { 0xb49914a, 0xf634111, 0x8e4f9bb, 0xbf8e1ab, 0xf4dba02, 0x2f59578, + 0xe004319, 0x2a94199, 0x654d005, 0x87931f0, 0x6fa0814, 0x7df57d9, + 0xa154031, 0xc8da316, 0x41f658b, 0x2a44ac0 } + }, + { + { 0x9e34ac6, 0xfb5f4f8, 0x97790f2, 0x0a1b10b, 0x4b8a06c, 0x58fe4e7, + 0x955f27c, 0x10c1710, 0xd5ebe19, 0x77b798a, 0x1f1c2dc, 0xaf1c35b, + 0xa1f8d69, 0xc25b8e6, 0xf76bf23, 0x49cf751 }, + { 0x436f7b7, 0x15cb2db, 0x7e74d1a, 0x186d7c2, 0xc00a415, 0x60731de, + 0x15f0772, 0xea1e156, 0x714463f, 0xf02d591, 0x51adeb1, 0x26a0c64, + 0xcc5229e, 0x20174cd, 0xefd512a, 0xb817e50 } + }, +}, +}; + +static const ge448_precomp base_i[16] = { + { + { 0x70cc05e, 0x26a82bc, 0x0938e26, 0x80e18b0, 0x511433b, 0xf72ab66, + 0x412ae1a, 0xa3d3a46, 0xa6de324, 0x0f1767e, 0x4657047, 0x36da9e1, + 0x5a622bf, 0xed221d1, 0x66bed0d, 0x4f1970c }, + { 0x230fa14, 0x08795bf, 0x7c8ad98, 0x132c4ed, 0x9c4fdbd, 0x1ce67c3, + 0x73ad3ff, 0x05a0c2d, 0x7789c1e, 0xa398408, 0xa73736c, 0xc7624be, + 0x03756c9, 0x2488762, 0x16eb6bc, 0x693f467 } + }, + { + { 0x6ff2f8f, 0x2817328, 0xda85757, 0xb769465, 0xfd6e862, 0xf7f6271, + 0x8daa9cb, 0x4a3fcfe, 0x2ba077a, 0xda82c7e, 0x41b8b8c, 0x9433322, + 0x4316cb6, 0x6455bd6, 0xb9108af, 0x0865886 }, + { 0x88ed6fc, 0x22ac135, 0x02dafb8, 0x9a68fed, 0x7f0bffa, 0x1bdb676, + 0x8bb3a33, 0xec4e1d5, 0xce43c82, 0x56c3b9f, 0xa8d9523, 0xa6449a4, + 0xa7ad43a, 0xf706cbd, 0xbd5125c, 0xe005a8d } + }, + { + { 0x2030034, 0xa99d109, 0x6f950d0, 0x2d8cefc, 0xc96f07b, 0x7a920c3, + 0x08bc0d5, 0x9588128, 0x6d761e8, 0x62ada75, 0xbcf7285, 0x0def80c, + 0x01eedb5, 0x0e2ba76, 0x5a48dcb, 0x7a9f933 }, + { 0x2f435eb, 0xb473147, 0xf225443, 0x5512881, 0x33c5840, 0xee59d2b, + 0x127d7a4, 0xb698017, 0x86551f7, 0xb18fced, 0xca1823a, 0x0ade260, + 0xce4fd58, 0xd3b9109, 0xa2517ed, 0xadfd751 } + }, + { + { 0xeb5eaf7, 0xdf9567c, 0x78ac7d7, 0x110a6b4, 0x4706e0b, 0x2d33501, + 0x0b5a209, 0x0df9c7b, 0x568e684, 0xba4223d, 0x8c3719b, 0xd78af2d, + 0xa5291b6, 0x77467b9, 0x5c89bef, 0x079748e }, + { 0xdac377f, 0xe20d3fa, 0x72b5c09, 0x34e8669, 0xc40bbb7, 0xd8687a3, + 0xd2f84c9, 0x7b3946f, 0xa78f50e, 0xd00e40c, 0x17e7179, 0xb875944, + 0xcb23583, 0x9c7373b, 0xc90fd69, 0x7ddeda3 } + }, + { + { 0x6ab686b, 0x3d0def7, 0x49f7c79, 0x1a467ec, 0xc8989ed, 0x3e53f4f, + 0x430a0d9, 0x101e344, 0x8ad44ee, 0xa3ae731, 0xae1d134, 0xaefa6cd, + 0x824ad4d, 0xaa8cd7d, 0xed584fc, 0xef1650c }, + { 0x4f4754f, 0xa74df67, 0xef3fb8b, 0xf52cea8, 0x2971140, 0x47c32d4, + 0xa256fbb, 0x391c15d, 0xa605671, 0xc165fab, 0x87993b9, 0xf2518c6, + 0xbd5a84d, 0x2daf7ac, 0x98f12ae, 0x1560b62 } + }, + { + { 0x54dc10a, 0xef4da02, 0x5940db8, 0x6311865, 0x82f2948, 0xe20b149, + 0x5581dba, 0x67b9377, 0x04f5029, 0x422ee71, 0x5122d34, 0x5d440db, + 0x1a4c640, 0xb1e56d7, 0xc2408ee, 0xbf12abb }, + { 0x016af01, 0x0cc9f86, 0xf3d8cab, 0x88366ab, 0xa2efe12, 0x85dda13, + 0x5d00674, 0x390df60, 0x6d187f7, 0xf18f580, 0xf0c5d20, 0x28c900f, + 0x3e01733, 0xad30812, 0x54bf2fd, 0x42d35b5 } + }, + { + { 0x2ffb1f1, 0x009135f, 0x8f9c605, 0x099fc7e, 0x26bfa5a, 0xcc67da6, + 0x344552b, 0xc186d12, 0x1b339e1, 0xb523250, 0xc9708c5, 0x70a544f, + 0x1e928e7, 0x06baaec, 0xef0f50f, 0x0baedd2 }, + { 0xbf479e5, 0x535d6d8, 0xe4ec3e9, 0x156e536, 0xddb9be2, 0x3165741, + 0x59fd736, 0x988af71, 0x2e33ddd, 0x13d8a78, 0x4e69002, 0x5460421, + 0x804a268, 0x34d56e0, 0x0e52a4c, 0xc59b84f } + }, + { + { 0x24729d9, 0x525d45f, 0x8712327, 0x5768aba, 0x43035db, 0xa25e43b, + 0x927ef21, 0x15a1ee8, 0x6056112, 0xa785d21, 0xd508af9, 0x45e2fbf, + 0x37ba969, 0xb6f721a, 0x216d8d3, 0x30d6d8c }, + { 0x52074c3, 0x3065e08, 0x2a0684e, 0xfa40b4a, 0x763f955, 0x851325a, + 0x9f25900, 0xd4ef19c, 0xf665756, 0x799c869, 0x3312990, 0x7b05222, + 0x28db802, 0xc986c2b, 0x28ade0a, 0xf48fb8f } + }, + { + { 0x1649b68, 0x1e46173, 0x5beb9dc, 0xa96e5d6, 0x481935d, 0x765ddff, + 0x9f3bf2a, 0x6cf132c, 0x7c35658, 0x9f6c5c9, 0x4696e60, 0x99cd139, + 0x9c0d5e4, 0x99fa924, 0x8845a95, 0x1acd063 }, + { 0x3636087, 0x0b06541, 0xea17b7f, 0xea20e78, 0x6161967, 0x20afc5f, + 0xdc81028, 0xfd6c8a2, 0xe32c8fd, 0x4ef1357, 0x00e4a88, 0x8aa4004, + 0x48cb82f, 0xd6fcaef, 0xb3cd4fa, 0x7ba7c6d } + }, + { + { 0xd19c7ab, 0xf843473, 0xc655c4d, 0x968e76d, 0xc4b9c2f, 0x52c87d9, + 0xe4aa082, 0x65f641a, 0x33c3603, 0x491a397, 0x5810098, 0xa606ffe, + 0x8bf8ad4, 0x09920e6, 0x6db7882, 0x691a0c8 }, + { 0xa4d3ef5, 0x5205883, 0xacf2efe, 0xee839b7, 0xc00ca66, 0x4b78e2a, + 0xf9fcb91, 0xbe3f071, 0xbf6943a, 0x61e66c9, 0x061b79d, 0xe9b4e57, + 0x56c06bd, 0x8d1b01b, 0xdf76ae5, 0x0dfa315 } + }, + { + { 0xf1fd093, 0x803df65, 0x489b77e, 0x1cd6523, 0xc20e295, 0x2cd2e15, + 0x9b912d1, 0xcd490be, 0x2e886d2, 0xdd9a2ff, 0xfe9d72a, 0xa3c836d, + 0x298e0c1, 0xfcad5f2, 0x4bcf067, 0xed126e2 }, + { 0x3dc81bc, 0x1e33953, 0xece6a08, 0xbea4d76, 0x991b252, 0x1d15de3, + 0xe6daf97, 0x74cc5cf, 0x0826493, 0x5ad343f, 0x1064049, 0x2d38a47, + 0xffcfa4d, 0xf7f47b9, 0x418066c, 0xef14490 } + }, + { + { 0x9bb55ab, 0x4e7f86b, 0x3f496a3, 0x310d785, 0x0dec42c, 0xbd682fc, + 0x411d32a, 0xbde047a, 0xc5a5ea2, 0xea639b4, 0xba08fa1, 0x5052078, + 0x07729f2, 0xc968b23, 0x23d3e28, 0x567b5a6 }, + { 0x977fbf7, 0x171e825, 0xbe990aa, 0x0319c70, 0xe12cd69, 0x8f65023, + 0xf5015e6, 0x1fb9b19, 0x3568a7c, 0x0083f60, 0x1f3c5ac, 0xba3d30b, + 0x3d7a988, 0xe7b509d, 0xcd0f6b6, 0x2318b99 } + }, + { + { 0x93ab2cf, 0x54d3b87, 0xd2d8306, 0x366abea, 0xd7a4977, 0x66e8eb6, + 0xae0072e, 0xa61888c, 0xdbc3315, 0x9eeeef5, 0x163e7f5, 0x93f09db, + 0x59ade9a, 0xee90959, 0xce59be0, 0xaf7f578 }, + { 0x5ece59e, 0x24bfd8d, 0x3689523, 0x8aa698b, 0x2de92cf, 0xa9a65de, + 0xa6ad300, 0xec11dbc, 0x09f88ca, 0x217f3fa, 0xb4d6af7, 0xf6c33e3, + 0x1d86d2d, 0xcd3bfa2, 0x5f13f25, 0x1497f83 } + }, + { + { 0xcd03d1d, 0xa579568, 0xe158af6, 0xd717cda, 0x389a19f, 0x59eda97, + 0x099e99c, 0xb32c370, 0xdabb591, 0xa2dba91, 0x77c2c97, 0x6d697d5, + 0xd43fa6d, 0x5423fc2, 0x0b382bf, 0x56ea8a5 }, + { 0xd80c11a, 0x4a987ba, 0x7d590a5, 0xe4cde21, 0xf97e559, 0x3dd8860, + 0x43b593c, 0xff45e25, 0x5343cb5, 0x00eb453, 0x7bbfbdd, 0x06b9b99, + 0x16aea24, 0x4da36b7, 0x57a624e, 0x2476517 } + }, + { + { 0x3474e0d, 0x32207d0, 0xb41cc73, 0x3ffbf04, 0x319eb39, 0x5c4dc45, + 0x758b463, 0xfee29be, 0xc30c7a7, 0xcc8a381, 0x9fe0e53, 0x147f4e4, + 0xe35a2de, 0x05b2e26, 0x92f3666, 0x4362f02 }, + { 0x8474b85, 0x0476d0c, 0xccaf108, 0x9d8c65f, 0x1d54b6a, 0xf58d404, + 0xf38e4b0, 0x3ee6862, 0x3b44f54, 0x7c7c9d5, 0x0fb0db5, 0x36a3fd8, + 0x18a8ac8, 0xfcd94ba, 0x8f35c05, 0xc1b1d56 } + }, + { + { 0x1bdd30d, 0x16539fc, 0x8df4afb, 0x1356e53, 0x5a1aedb, 0xc0545d8, + 0x489396b, 0xeb2037a, 0x5660894, 0x897fcbd, 0xb7d104a, 0x02a58a9, + 0xc96b980, 0x57fa24c, 0x5bd8946, 0xf6448e3 }, + { 0x8805c83, 0xee72741, 0x992cfc6, 0x10fa274, 0x9e66b21, 0x9514193, + 0xbd08009, 0xe0ffa44, 0x20da22b, 0x1743322, 0x59e6831, 0x4891ff3, + 0xa7d687b, 0x407ed73, 0x51d99cf, 0x2fb4e07 } + }, +}; +#endif + +/* Set the 0 point. + * + * p [in] Point to set to 0. + */ +static WC_INLINE void ge448_0(ge448_p2 *p) +{ + fe448_0(p->X); + fe448_1(p->Y); + fe448_1(p->Z); +} + +/* Set the precompute point to 0. + * + * p [in] Precompute point to set. + */ +static void ge448_precomp_0(ge448_precomp *p) +{ + fe448_0(p->x); + fe448_1(p->y); +} + +/* Double the point on the Twisted Edwards curve. r = 2.p + * + * r [in] Point to hold result. + * p [in] Point to double. + */ +static WC_INLINE void ge448_dbl(ge448_p2 *r,const ge448_p2 *p) +{ + ge448 t0[GE448_WORDS]; + ge448 t1[GE448_WORDS]; + + fe448_add(t0, p->X, p->Y); /* t0 = B1 = X1+Y1 */ + fe448_reduce(t0); + fe448_sqr(t0, t0); /* t0 = B = (X1+Y1)^2 */ + fe448_sqr(r->X, p->X); /* r->X = C = X1^2 */ + fe448_sqr(r->Y, p->Y); /* r->Y = D = Y1^2 */ + fe448_add(t1, r->X, r->Y); /* t1 = E = C+D */ + fe448_reduce(t1); + fe448_sub(r->Y, r->X, r->Y); /* r->Y = Y31 = C-D */ + fe448_sqr(r->Z, p->Z); /* r->Z = H = Z1^2 */ + fe448_add(r->Z, r->Z, r->Z); /* r->Z = J1 = 2*H */ + fe448_sub(r->Z, t1, r->Z); /* r->Z = J = E-2*H */ + fe448_reduce(r->Z); + fe448_sub(r->X, t0, t1); /* r->X = X31 = B-E */ + fe448_mul(r->X, r->X, r->Z); /* r->X = X3 = (B-E)*J */ + fe448_mul(r->Y, r->Y, t1); /* r->Y = Y3 = E*(C-D) */ + fe448_mul(r->Z, t1, r->Z); /* r->Z = Z3 = E*J */ +} + +/* Add two point on the Twisted Edwards curve. r = p + q + * Second point has z-ordinate of 1. + * + * r [in] Point to hold result. + * p [in] Point to add. + * q [in] Point to add. + */ +static WC_INLINE void ge448_madd(ge448_p2 *r, const ge448_p2 *p, + const ge448_precomp *q) +{ + ge448 t0[GE448_WORDS]; + ge448 t1[GE448_WORDS]; + ge448 t2[GE448_WORDS]; + ge448 t3[GE448_WORDS]; + ge448 t4[GE448_WORDS]; + + /* p->Z = A */ + fe448_mul(t1, p->X, q->x); /* t1 = C = X1*X2 */ + fe448_mul(t2, p->Y, q->y); /* t2 = D = Y1*Y2 */ + fe448_mul(t3, t1, t2); /* t3 = E1 = C*D */ + fe448_mul39081(t3, t3); /* t3 = E = d*C*D */ + fe448_sqr(t0, p->Z); /* t0 = B = A^2 */ + fe448_add(t4, t0, t3); /* t4 = F = B-(-E) */ + fe448_sub(t0, t0, t3); /* t0 = G = B+(-E) */ + fe448_reduce(t0); + fe448_add(r->X, p->X, p->Y); /* r->X = H1 = X1+Y1 */ + fe448_reduce(r->X); + fe448_add(r->Y, q->x, q->y); /* r->Y = H2 = X2+Y2 */ + fe448_reduce(r->Y); + fe448_mul(r->X, r->X, r->Y); /* r->X = H = (X1+Y1)*(X2+Y2) */ + fe448_sub(r->X, r->X, t1); /* r->X = X31 = H-C */ + fe448_sub(r->X, r->X, t2); /* r->X = X32 = H-C-D */ + fe448_reduce(r->X); + fe448_mul(r->X, r->X, t4); /* r->X = X33 = F*(H-C-D) */ + fe448_mul(r->X, r->X, p->Z); /* r->X = X3 = A*F*(H-C-D) */ + fe448_sub(r->Y, t2, t1); /* r->Y = Y31 = D-C */ + fe448_reduce(r->Y); + fe448_mul(r->Y, r->Y, t0); /* r->Y = Y32 = G*(D-C) */ + fe448_mul(r->Y, r->Y, p->Z); /* r->Y = Y3 = A*F*(D-C) */ + fe448_mul(r->Z, t4, t0); /* r->Z = Z3 = F*G */ +} + +/* Subtract one point from another on the Twisted Edwards curve. r = p - q + * Second point has z-ordinate of 1. + * + * r [in] Point to hold result. + * p [in] Point to subtract from. + * q [in] Point to subtract. + */ +static WC_INLINE void ge448_msub(ge448_p2 *r, const ge448_p2 *p, + const ge448_precomp *q) +{ + ge448 t0[GE448_WORDS]; + ge448 t1[GE448_WORDS]; + ge448 t2[GE448_WORDS]; + ge448 t3[GE448_WORDS]; + ge448 t4[GE448_WORDS]; + + /* p->Z = A */ + fe448_sqr(t0, p->Z); /* t0 = B = A^2 */ + fe448_mul(t1, p->X, q->x); /* t1 = C = X1*X2 */ + fe448_mul(t2, p->Y, q->y); /* t2 = D = Y1*Y2 */ + fe448_mul(t3, t1, t2); /* t3 = E1 = C*D */ + fe448_mul39081(t3, t3); /* t3 = E = d*C*D */ + fe448_sub(t4, t0, t3); /* t4 = F = B-(--E) */ + fe448_add(t0, t0, t3); /* t0 = G = B+(--E) */ + fe448_reduce(t0); + fe448_add(r->X, p->X, p->Y); /* r->X = H1 = X1+Y1 */ + fe448_reduce(r->X); + fe448_sub(r->Y, q->y, q->x); /* r->Y = H2 = Y2+(-X2) */ + fe448_reduce(r->Y); + fe448_mul(r->X, r->X, r->Y); /* r->X = H = (X1+Y1)*(X2+Y2) */ + fe448_add(r->X, r->X, t1); /* r->X = X31 = H-(-C) */ + fe448_sub(r->X, r->X, t2); /* r->X = X32 = H-(-C)-D */ + fe448_reduce(r->X); + fe448_mul(r->X, r->X, t4); /* r->X = X33 = F*(H-C-D) */ + fe448_mul(r->X, r->X, p->Z); /* r->X = X3 = A*F*(H-C-D) */ + fe448_add(r->Y, t2, t1); /* r->Y = Y31 = D-C */ + fe448_reduce(r->Y); + fe448_mul(r->Y, r->Y, t0); /* r->Y = Y32 = G*(D-C) */ + fe448_mul(r->Y, r->Y, p->Z); /* r->Y = Y3 = A*F*(D-C) */ + fe448_mul(r->Z, t4, t0); /* r->Z = Z3 = F*G */ +} + +/* Add two point on the Twisted Edwards curve. r = p + q + * + * r [in] Point to hold result. + * p [in] Point to add. + * q [in] Point to add. + */ +static WC_INLINE void ge448_add(ge448_p2* r, const ge448_p2* p, + const ge448_p2* q) +{ + ge448 t0[GE448_WORDS]; + ge448 t1[GE448_WORDS]; + ge448 t2[GE448_WORDS]; + ge448 t3[GE448_WORDS]; + ge448 t4[GE448_WORDS]; + + fe448_mul(t1, p->X, q->X); /* t1 = C = X1*X2 */ + fe448_mul(t2, p->Y, q->Y); /* t2 = D = Y1*Y2 */ + fe448_mul(t3, t1, t2); /* t3 = E1 = C*D */ + fe448_mul39081(t3, t3); /* t3 = E = d*C*D */ + fe448_mul(r->Z, p->Z, q->Z); /* r->Z = A = Z1*Z2 */ + fe448_sqr(t0, r->Z); /* t0 = B = A^2 */ + fe448_add(t4, t0, t3); /* t4 = F = B-(-E) */ + fe448_sub(t0, t0, t3); /* t0 = G = B+(-E) */ + fe448_reduce(t0); + fe448_add(r->X, p->X, p->Y); /* r->X = H1 = X1+Y1 */ + fe448_reduce(r->X); + fe448_add(r->Y, q->X, q->Y); /* r->Y = H2 = X2+Y2 */ + fe448_reduce(r->Y); + fe448_mul(r->X, r->X, r->Y); /* r->X = H = (X1+Y1)*(X2+Y2) */ + fe448_sub(r->X, r->X, t1); /* r->X = X31 = H-C */ + fe448_sub(r->X, r->X, t2); /* r->X = X32 = H-C-D */ + fe448_reduce(r->X); + fe448_mul(r->X, r->X, t4); /* r->X = X33 = F*(H-C-D) */ + fe448_mul(r->X, r->X, r->Z); /* r->X = X3 = A*F*(H-C-D) */ + fe448_sub(r->Y, t2, t1); /* r->Y = Y31 = D-C */ + fe448_reduce(r->Y); + fe448_mul(r->Y, r->Y, t0); /* r->Y = Y32 = G*(D-C) */ + fe448_mul(r->Y, r->Y, r->Z); /* r->Y = Y3 = A*F*(D-C) */ + fe448_mul(r->Z, t4, t0); /* r->Z = Z3 = F*G */ +} + +/* Subtract one point from another on the Twisted Edwards curve. r = p - q + * + * r [in] Point to hold result. + * p [in] Point to subtract from. + * q [in] Point to subtract. + */ +static WC_INLINE void ge448_sub(ge448_p2 *r, const ge448_p2 *p, + const ge448_p2 *q) +{ + ge448 t0[GE448_WORDS]; + ge448 t1[GE448_WORDS]; + ge448 t2[GE448_WORDS]; + ge448 t3[GE448_WORDS]; + ge448 t4[GE448_WORDS]; + + fe448_mul(t1, p->X, q->X); /* t1 = C = X1*X2 */ + fe448_mul(t2, p->Y, q->Y); /* t2 = D = Y1*Y2 */ + fe448_mul(t3, t1, t2); /* t3 = E1 = C*D */ + fe448_mul39081(t3, t3); /* t3 = E = d*C*D */ + fe448_mul(r->Z, p->Z, q->Z); /* r->Z = A = Z1*Z2 */ + fe448_sqr(t0, p->Z); /* t0 = B = A^2 */ + fe448_sub(t4, t0, t3); /* t4 = F = B-(--E) */ + fe448_add(t0, t0, t3); /* t0 = G = B+(--E) */ + fe448_reduce(t0); + fe448_add(r->X, p->X, p->Y); /* r->X = H1 = X1+Y1 */ + fe448_reduce(r->X); + fe448_sub(r->Y, q->Y, q->X); /* r->Y = H2 = Y2+(-X2) */ + fe448_reduce(r->Y); + fe448_mul(r->X, r->X, r->Y); /* r->X = H = (X1+Y1)*(X2+Y2) */ + fe448_add(r->X, r->X, t1); /* r->X = X31 = H-(-C) */ + fe448_sub(r->X, r->X, t2); /* r->X = X32 = H-(-C)-D */ + fe448_reduce(r->X); + fe448_mul(r->X, r->X, t4); /* r->X = X33 = F*(H-C-D) */ + fe448_mul(r->X, r->X, r->Z); /* r->X = X3 = A*F*(H-C-D) */ + fe448_add(r->Y, t2, t1); /* r->Y = Y31 = D-C */ + fe448_reduce(r->Y); + fe448_mul(r->Y, r->Y, t0); /* r->Y = Y32 = G*(D-C) */ + fe448_mul(r->Y, r->Y, r->Z); /* r->Y = Y3 = A*F*(D-C) */ + fe448_mul(r->Z, t4, t0); /* r->Z = Z3 = F*G */ +} + +/* Convert point to byte array assuming projective ordinates. + * + * b [in] Array of bytes to hold compressed point. + * p [in] Point to convert. + */ +void ge448_to_bytes(uint8_t *b, const ge448_p2 *p) +{ + ge448 recip[GE448_WORDS]; + ge448 x[GE448_WORDS]; + ge448 y[GE448_WORDS]; + + fe448_invert(recip, p->Z); + fe448_mul(x, p->X, recip); + fe448_mul(y, p->Y, recip); + fe448_to_bytes(b, y); + b[56] = fe448_isnegative(x) << 7; +} + +/* Convert point to byte array assuming z is 1. + * + * b [in] Array of bytes to hold compressed point. + * p [in] Point to convert. + */ +static void ge448_p2z1_to_bytes(uint8_t *b, const ge448_p2 *p) +{ + fe448_to_bytes(b, p->Y); + b[56] = fe448_isnegative(p->X) << 7; +} + +/* Compress the point to y-ordinate and negative bit. + * + * out [in] Array of bytes to hold compressed key. + * xIn [in] The x-ordinate. + * yIn [in] The y-ordinate. + */ +int ge448_compress_key(uint8_t* out, const uint8_t* xIn, const uint8_t* yIn) +{ + ge448_p2 g; + uint8_t bArray[ED448_KEY_SIZE]; + uint32_t i; + + fe448_from_bytes(g.X, xIn); + fe448_from_bytes(g.Y, yIn); + fe448_1(g.Z); + + ge448_p2z1_to_bytes(bArray, &g); + + for (i = 0; i < 57; i++) { + out[57 - 1 - i] = bArray[i]; + } + + return 0; +} + +/* Determine whether the value is negative. + * + * b [in] An 8-bit signed value. + * returns 1 when negative and 0 otherwise. + */ +static uint8_t negative(int8_t b) +{ + return ((uint8_t)b) >> 7; +} + +/* Determine whether two values are equal. a == b + * Constant time implementation. + * + * a [in] An 8-bit unsigned value. + * b [in] An 8-bit unsigned value. + * returns 1 when equal and 0 otherwise. + */ +static uint8_t equal(uint8_t a, uint8_t b) +{ + return (uint8_t)(((uint32_t)(a ^ b) - 1) >> 31); +} + +/* Conditional move the point into result point if two values are equal. + * Constant time implementation. + * + * f [in] Point to conditionally overwrite. + * p [in] Point to conditionally copy. + * b [in] An 8-bit unsigned value. + * n [in] An 8-bit unsigned value. + */ +static WC_INLINE void cmov(ge448_precomp* r, const ge448_precomp* p, uint8_t b, + uint8_t n) +{ + b = equal(b, n); + fe448_cmov(r->x, p->x, b); + fe448_cmov(r->y, p->y, b); +} + +/* Select one of the entries from the precomputed table and negate if required. + * Constant time implementation. + * + * r [in] Point to hold chosen point. + * pos [in] Position of array of entries to choose from. + * b [in] Index of point to select. -ve value means negate the point. + */ +static void ge448_select(ge448_precomp* r, int pos, int8_t b) +{ + ge448 minusx[16]; + uint8_t bnegative = negative(b); + uint8_t babs = b - (((-bnegative) & b) << 1); + + ge448_precomp_0(r); + cmov(r, &base[pos][0], babs, 1); + cmov(r, &base[pos][1], babs, 2); + cmov(r, &base[pos][2], babs, 3); + cmov(r, &base[pos][3], babs, 4); + cmov(r, &base[pos][4], babs, 5); + cmov(r, &base[pos][5], babs, 6); + cmov(r, &base[pos][6], babs, 7); + cmov(r, &base[pos][7], babs, 8); + fe448_neg(minusx, r->x); + fe448_cmov(r->x, minusx, bnegative); +} + +/* Perform a scalar multiplication of the base point. r = a * base + * + * r [in] Point to hold result. + * a [in] Scalar to multiply by. + */ +void ge448_scalarmult_base(ge448_p2* r, const uint8_t* a) +{ + int8_t carry; + ge448_precomp t; + int i; + int8_t e[113]; + + carry = 0; + for (i = 0; i < 56; ++i) { + e[2 * i + 0] = ((a[i] >> 0) & 0xf) + carry; + carry = e[2 * i + 0] + 8; + carry >>= 4; + e[2 * i + 0] -= carry << 4; + + e[2 * i + 1] = ((a[i] >> 4) & 0xf) + carry; + carry = e[2 * i + 1] + 8; + carry >>= 4; + e[2 * i + 1] -= carry << 4; + } + e[112] = carry; + /* each e[i] is between -8 and 8 */ + + /* Odd indeces first - sum based on even index so multiply by 16 */ + ge448_select(&t, 0, e[1]); + fe448_copy(r->X, t.x); + fe448_copy(r->Y, t.y); + fe448_1(r->Z); + for (i = 3; i < 112; i += 2) { + ge448_select(&t, i / 2, e[i]); + ge448_madd(r, r, &t); + } + + ge448_dbl(r, r); + ge448_dbl(r, r); + ge448_dbl(r, r); + ge448_dbl(r, r); + + /* Add even indeces */ + for (i = 0; i <= 112; i += 2) { + ge448_select(&t, i / 2, e[i]); + ge448_madd(r, r, &t); + } +} + +/* Create to a sliding window for the scalar multiplicaton. + * + * r [in] Array of indeces. + * a [in] Scalar to break up. + */ +static void slide(int8_t *r, const uint8_t *a) +{ + int i; + int b; + int k; + + for (i = 0; i < 448; ++i) { + r[i] = (a[i >> 3] >> (i & 7)) & 1; + } + + for (i = 0; i < 448; ++i) { + if (r[i] == 0) { + continue; + } + + for (b = 1; b <= 7 && i + b < 448; ++b) { + if (r[i + b] == 0) { + continue; + } + + if (r[i] + (r[i + b] << b) <= 31) { + r[i] += r[i + b] << b; r[i + b] = 0; + } + else if (r[i] - (r[i + b] << b) >= -31) { + r[i] -= r[i + b] << b; + for (k = i + b; k < 448; ++k) { + if (!r[k]) { + r[k] = 1; + break; + } + r[k] = 0; + } + } + else { + break; + } + } + } +} + +/* Perform a scalar multplication of the base point and public point. + * r = a * p + b * base + * Uses a sliding window of 5 bits. + * Not constant time. + * + * r [in] Point to hold result. + * a [in] Scalar to multiply by. + */ +int ge448_double_scalarmult_vartime(ge448_p2 *r, const uint8_t *a, + const ge448_p2 *p, const uint8_t *b) +{ + int8_t aslide[448]; + int8_t bslide[448]; + ge448_p2 pi[16]; /* p,3p,..,31p */ + ge448_p2 p2; + int i; + + slide(aslide, a); + slide(bslide, b); + + fe448_copy(pi[0].X, p->X); + fe448_copy(pi[0].Y, p->Y); + fe448_copy(pi[0].Z, p->Z); + ge448_dbl(&p2, p); + ge448_add(&pi[1], &p2, &pi[0]); + ge448_add(&pi[2], &p2, &pi[1]); + ge448_add(&pi[3], &p2, &pi[2]); + ge448_add(&pi[4], &p2, &pi[3]); + ge448_add(&pi[5], &p2, &pi[4]); + ge448_add(&pi[6], &p2, &pi[5]); + ge448_add(&pi[7], &p2, &pi[6]); + ge448_add(&pi[8], &p2, &pi[7]); + ge448_add(&pi[9], &p2, &pi[8]); + ge448_add(&pi[10], &p2, &pi[9]); + ge448_add(&pi[11], &p2, &pi[10]); + ge448_add(&pi[12], &p2, &pi[11]); + ge448_add(&pi[13], &p2, &pi[12]); + ge448_add(&pi[14], &p2, &pi[13]); + ge448_add(&pi[15], &p2, &pi[14]); + + ge448_0(r); + + /* Find first index that is not 0. */ + for (i = 447; i >= 0; --i) { + if (aslide[i] || bslide[i]) { + break; + } + } + + for (; i >= 0; --i) { + ge448_dbl(r, r); + + if (aslide[i] > 0) + ge448_add(r, r, &pi[aslide[i]/2]); + else if (aslide[i] < 0) + ge448_sub(r, r ,&pi[(-aslide[i])/2]); + + if (bslide[i] > 0) + ge448_madd(r, r, &base_i[bslide[i]/2]); + else if (bslide[i] < 0) + ge448_msub(r, r, &base_i[(-bslide[i])/2]); + } + + return 0; +} + +/* Convert compressed point to negative of affine point. + * Calculates x from the y and the negative bit. + * Not constant time. + * + * r [in] Uncompressed point. + * b [in] Array of bytes representing point. + * returns 0 on success and -1 on failure. + */ +int ge448_from_bytes_negate_vartime(ge448_p2 *r, const uint8_t *b) +{ + int ret = 0; + ge448 u[GE448_WORDS]; + ge448 v[GE448_WORDS]; + ge448 u3[GE448_WORDS]; + ge448 vxx[GE448_WORDS]; + ge448 check[GE448_WORDS]; + + fe448_from_bytes(r->Y, b); + fe448_1(r->Z); + fe448_sqr(u, r->Y); /* u = y^2 */ + fe448_mul39081(v, u); /* v = 39081.y^2 */ + fe448_sub(u, u, r->Z); /* u = y^2-1 */ + fe448_reduce(u); + fe448_add(v, v, r->Z); /* v = 39081.y^2-1 */ + fe448_reduce(v); + fe448_neg(v, v); /* v = -39081.y^2-1 = d.y^2-1 */ + + fe448_sqr(r->X, v); /* x = v^2 */ + fe448_mul(r->X, r->X, v); /* x = v^3 */ + fe448_sqr(u3, u); /* x = u^2.v^3 */ + fe448_mul(r->X, r->X, u3); /* x = u^2.v^3 */ + fe448_mul(u3, u3, u); /* u3 = u^3 */ + fe448_mul(r->X, r->X, u3); /* x = u^5.v^3 */ + + fe448_pow_2_446_222_1(r->X, r->X); /* x = (u^5.v^3)^((q-3)/4) */ + fe448_mul(r->X, r->X, u3); /* x = u^3(u^5.v^3)^((q-3)/4) */ + fe448_mul(r->X, r->X, v); /* x = u^3.v(u^5.v^3)^((q-3)/4) */ + + fe448_sqr(vxx, r->X); + fe448_mul(vxx, vxx, v); + fe448_sub(check, vxx, u); /* check = v.x^2-u */ + fe448_reduce(check); + /* Note; vx^2+u is NOT correct. */ + if (fe448_isnonzero(check)) { + ret = -1; + } + + /* Calculating negative of point in bytes - negate only if X is correct. */ + if (fe448_isnegative(r->X) == (b[56] >> 7)) { + fe448_neg(r->X, r->X); + } + + return ret; +} + +#endif /* ED448_SMALL */ +#endif /* HAVE_CURVE448 || HAVE_ED448 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ge_low_mem.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ge_low_mem.c index 43c533c69..3b72b96cc 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ge_low_mem.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ge_low_mem.c @@ -1,8 +1,8 @@ /* ge_low_mem.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Based from Daniel Beer's public domain work. */ #ifdef HAVE_CONFIG_H @@ -28,12 +29,14 @@ #include #ifdef HAVE_ED25519 +#ifdef ED25519_SMALL /* use slower code that takes less memory */ #include #include #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif @@ -43,10 +46,10 @@ void ed25519_double(ge_p3 *r, const ge_p3 *a); static const byte ed25519_order[F25519_SIZE] = { - 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, - 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, + 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }; /*Arithmetic modulo the group order m = 2^252 + @@ -69,16 +72,16 @@ static const word32 mu[33] = { int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, word32 keySz) { - byte tmp[F25519_SIZE]; - byte parity; + byte tmp[F25519_SIZE]; + byte parity; + byte pt[32]; int i; - fe_copy(tmp, xIn); - parity = (tmp[0] & 1) << 7; + lm_copy(tmp, xIn); + parity = (tmp[0] & 1) << 7; - byte pt[32]; - fe_copy(pt, yIn); - pt[31] |= parity; + lm_copy(pt, yIn); + pt[31] |= parity; for(i = 0; i < 32; i++) { out[32-i-1] = pt[i]; @@ -90,7 +93,7 @@ int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, static word32 lt(word32 a,word32 b) /* 16-bit inputs */ { - unsigned int x = a; + word32 x = a; x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */ x >>= 31; /* 0: no; 1: yes */ return x; @@ -187,20 +190,20 @@ void sc_reduce(unsigned char x[64]) void sc_muladd(byte* out, const byte* a, const byte* b, const byte* c) { - byte s[32]; + byte s[32]; byte e[64]; XMEMSET(e, 0, sizeof(e)); XMEMCPY(e, b, 32); - /* Obtain e */ - sc_reduce(e); + /* Obtain e */ + sc_reduce(e); - /* Compute s = ze + k */ - fprime_mul(s, a, e, ed25519_order); - fprime_add(s, c, ed25519_order); + /* Compute s = ze + k */ + fprime_mul(s, a, e, ed25519_order); + fprime_add(s, c, ed25519_order); - XMEMCPY(out, s, 32); + XMEMCPY(out, s, 32); } @@ -216,315 +219,317 @@ void sc_muladd(byte* out, const byte* a, const byte* b, const byte* c) * t is x*y. */ const ge_p3 ed25519_base = { - .X = { - 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, - 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, - 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, - 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21 - }, - .Y = { - 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66 - }, - .T = { - 0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d, - 0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20, - 0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66, - 0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67 - }, - .Z = {1, 0} + { + 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, + 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, + 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, + 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21 + }, + { + 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66 + }, + {1, 0}, + { + 0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d, + 0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20, + 0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66, + 0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67 + }, + }; const ge_p3 ed25519_neutral = { - .X = {0}, - .Y = {1, 0}, - .T = {0}, - .Z = {1, 0} + {0}, + {1, 0}, + {1, 0}, + {0}, + }; static const byte ed25519_d[F25519_SIZE] = { - 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, - 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, - 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, - 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52 + 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, + 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, + 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, + 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52 }; /* k = 2d */ static const byte ed25519_k[F25519_SIZE] = { - 0x59, 0xf1, 0xb2, 0x26, 0x94, 0x9b, 0xd6, 0xeb, - 0x56, 0xb1, 0x83, 0x82, 0x9a, 0x14, 0xe0, 0x00, - 0x30, 0xd1, 0xf3, 0xee, 0xf2, 0x80, 0x8e, 0x19, - 0xe7, 0xfc, 0xdf, 0x56, 0xdc, 0xd9, 0x06, 0x24 + 0x59, 0xf1, 0xb2, 0x26, 0x94, 0x9b, 0xd6, 0xeb, + 0x56, 0xb1, 0x83, 0x82, 0x9a, 0x14, 0xe0, 0x00, + 0x30, 0xd1, 0xf3, 0xee, 0xf2, 0x80, 0x8e, 0x19, + 0xe7, 0xfc, 0xdf, 0x56, 0xdc, 0xd9, 0x06, 0x24 }; void ed25519_add(ge_p3 *r, - const ge_p3 *p1, const ge_p3 *p2) + const ge_p3 *p1, const ge_p3 *p2) { - /* Explicit formulas database: add-2008-hwcd-3 - * - * source 2008 Hisil--Wong--Carter--Dawson, - * http://eprint.iacr.org/2008/522, Section 3.1 - * appliesto extended-1 - * parameter k - * assume k = 2 d - * compute A = (Y1-X1)(Y2-X2) - * compute B = (Y1+X1)(Y2+X2) - * compute C = T1 k T2 - * compute D = Z1 2 Z2 - * compute E = B - A - * compute F = D - C - * compute G = D + C - * compute H = B + A - * compute X3 = E F - * compute Y3 = G H - * compute T3 = E H - * compute Z3 = F G - */ - byte a[F25519_SIZE]; - byte b[F25519_SIZE]; - byte c[F25519_SIZE]; - byte d[F25519_SIZE]; - byte e[F25519_SIZE]; - byte f[F25519_SIZE]; - byte g[F25519_SIZE]; - byte h[F25519_SIZE]; + /* Explicit formulas database: add-2008-hwcd-3 + * + * source 2008 Hisil--Wong--Carter--Dawson, + * http://eprint.iacr.org/2008/522, Section 3.1 + * appliesto extended-1 + * parameter k + * assume k = 2 d + * compute A = (Y1-X1)(Y2-X2) + * compute B = (Y1+X1)(Y2+X2) + * compute C = T1 k T2 + * compute D = Z1 2 Z2 + * compute E = B - A + * compute F = D - C + * compute G = D + C + * compute H = B + A + * compute X3 = E F + * compute Y3 = G H + * compute T3 = E H + * compute Z3 = F G + */ + byte a[F25519_SIZE]; + byte b[F25519_SIZE]; + byte c[F25519_SIZE]; + byte d[F25519_SIZE]; + byte e[F25519_SIZE]; + byte f[F25519_SIZE]; + byte g[F25519_SIZE]; + byte h[F25519_SIZE]; - /* A = (Y1-X1)(Y2-X2) */ - fe_sub(c, p1->Y, p1->X); - fe_sub(d, p2->Y, p2->X); - fe_mul__distinct(a, c, d); + /* A = (Y1-X1)(Y2-X2) */ + 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); - fe_mul__distinct(b, c, d); + /* B = (Y1+X1)(Y2+X2) */ + lm_add(c, p1->Y, p1->X); + lm_add(d, p2->Y, p2->X); + fe_mul__distinct(b, c, d); - /* C = T1 k T2 */ - fe_mul__distinct(d, p1->T, p2->T); - fe_mul__distinct(c, d, ed25519_k); + /* C = T1 k T2 */ + fe_mul__distinct(d, p1->T, p2->T); + fe_mul__distinct(c, d, ed25519_k); - /* D = Z1 2 Z2 */ - fe_mul__distinct(d, p1->Z, p2->Z); - fe_add(d, d, d); + /* D = Z1 2 Z2 */ + fe_mul__distinct(d, p1->Z, p2->Z); + lm_add(d, d, d); - /* E = B - A */ - fe_sub(e, b, a); + /* E = B - A */ + lm_sub(e, b, a); - /* F = D - C */ - fe_sub(f, d, c); + /* F = D - C */ + lm_sub(f, d, c); - /* G = D + C */ - fe_add(g, d, c); + /* G = D + C */ + lm_add(g, d, c); - /* H = B + A */ - fe_add(h, b, a); + /* H = B + A */ + lm_add(h, b, a); - /* X3 = E F */ - fe_mul__distinct(r->X, e, f); + /* X3 = E F */ + fe_mul__distinct(r->X, e, f); - /* Y3 = G H */ - fe_mul__distinct(r->Y, g, h); + /* Y3 = G H */ + fe_mul__distinct(r->Y, g, h); - /* T3 = E H */ - fe_mul__distinct(r->T, e, h); + /* T3 = E H */ + fe_mul__distinct(r->T, e, h); - /* Z3 = F G */ - fe_mul__distinct(r->Z, f, g); + /* Z3 = F G */ + fe_mul__distinct(r->Z, f, g); } void ed25519_double(ge_p3 *r, const ge_p3 *p) { - /* Explicit formulas database: dbl-2008-hwcd - * - * source 2008 Hisil--Wong--Carter--Dawson, - * http://eprint.iacr.org/2008/522, Section 3.3 - * compute A = X1^2 - * compute B = Y1^2 - * compute C = 2 Z1^2 - * compute D = a A - * compute E = (X1+Y1)^2-A-B - * compute G = D + B - * compute F = G - C - * compute H = D - B - * compute X3 = E F - * compute Y3 = G H - * compute T3 = E H - * compute Z3 = F G - */ - byte a[F25519_SIZE]; - byte b[F25519_SIZE]; - byte c[F25519_SIZE]; - byte e[F25519_SIZE]; - byte f[F25519_SIZE]; - byte g[F25519_SIZE]; - byte h[F25519_SIZE]; + /* Explicit formulas database: dbl-2008-hwcd + * + * source 2008 Hisil--Wong--Carter--Dawson, + * http://eprint.iacr.org/2008/522, Section 3.3 + * compute A = X1^2 + * compute B = Y1^2 + * compute C = 2 Z1^2 + * compute D = a A + * compute E = (X1+Y1)^2-A-B + * compute G = D + B + * compute F = G - C + * compute H = D - B + * compute X3 = E F + * compute Y3 = G H + * compute T3 = E H + * compute Z3 = F G + */ + byte a[F25519_SIZE]; + byte b[F25519_SIZE]; + byte c[F25519_SIZE]; + byte e[F25519_SIZE]; + byte f[F25519_SIZE]; + byte g[F25519_SIZE]; + byte h[F25519_SIZE]; - /* A = X1^2 */ - fe_mul__distinct(a, p->X, p->X); + /* A = X1^2 */ + fe_mul__distinct(a, p->X, p->X); - /* B = Y1^2 */ - fe_mul__distinct(b, p->Y, p->Y); + /* B = Y1^2 */ + fe_mul__distinct(b, p->Y, p->Y); - /* C = 2 Z1^2 */ - fe_mul__distinct(c, p->Z, p->Z); - fe_add(c, c, c); + /* C = 2 Z1^2 */ + fe_mul__distinct(c, p->Z, p->Z); + lm_add(c, c, c); - /* D = a A (alter sign) */ - /* E = (X1+Y1)^2-A-B */ - fe_add(f, p->X, p->Y); - fe_mul__distinct(e, f, f); - fe_sub(e, e, a); - fe_sub(e, e, b); + /* D = a A (alter sign) */ + /* E = (X1+Y1)^2-A-B */ + lm_add(f, p->X, p->Y); + fe_mul__distinct(e, f, f); + lm_sub(e, e, a); + lm_sub(e, e, b); - /* G = D + B */ - fe_sub(g, b, a); + /* G = D + B */ + lm_sub(g, b, a); - /* F = G - C */ - fe_sub(f, g, c); + /* F = G - C */ + lm_sub(f, g, c); - /* H = D - B */ - fe_neg(h, b); - fe_sub(h, h, a); + /* H = D - B */ + lm_neg(h, b); + lm_sub(h, h, a); - /* X3 = E F */ - fe_mul__distinct(r->X, e, f); + /* X3 = E F */ + fe_mul__distinct(r->X, e, f); - /* Y3 = G H */ - fe_mul__distinct(r->Y, g, h); + /* Y3 = G H */ + fe_mul__distinct(r->Y, g, h); - /* T3 = E H */ - fe_mul__distinct(r->T, e, h); + /* T3 = E H */ + fe_mul__distinct(r->T, e, h); - /* Z3 = F G */ - fe_mul__distinct(r->Z, f, g); + /* Z3 = F G */ + fe_mul__distinct(r->Z, f, g); } void ed25519_smult(ge_p3 *r_out, const ge_p3 *p, const byte *e) { - ge_p3 r; - int i; + ge_p3 r; + int i; XMEMCPY(&r, &ed25519_neutral, sizeof(r)); - for (i = 255; i >= 0; i--) { - const byte bit = (e[i >> 3] >> (i & 7)) & 1; - ge_p3 s; + for (i = 255; i >= 0; i--) { + const byte bit = (e[i >> 3] >> (i & 7)) & 1; + ge_p3 s; - ed25519_double(&r, &r); - ed25519_add(&s, &r, p); + ed25519_double(&r, &r); + ed25519_add(&s, &r, p); - fe_select(r.X, r.X, s.X, bit); - fe_select(r.Y, r.Y, s.Y, bit); - fe_select(r.Z, r.Z, s.Z, bit); - fe_select(r.T, r.T, s.T, bit); - } + fe_select(r.X, r.X, s.X, bit); + fe_select(r.Y, r.Y, s.Y, bit); + fe_select(r.Z, r.Z, s.Z, bit); + fe_select(r.T, r.T, s.T, bit); + } XMEMCPY(r_out, &r, sizeof(r)); } void ge_scalarmult_base(ge_p3 *R,const unsigned char *nonce) { - ed25519_smult(R, &ed25519_base, nonce); + ed25519_smult(R, &ed25519_base, nonce); } /* pack the point h into array s */ void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) { - byte x[F25519_SIZE]; - byte y[F25519_SIZE]; - byte z1[F25519_SIZE]; - byte parity; + byte x[F25519_SIZE]; + byte y[F25519_SIZE]; + byte z1[F25519_SIZE]; + byte parity; - fe_inv__distinct(z1, h->Z); - fe_mul__distinct(x, h->X, z1); - fe_mul__distinct(y, h->Y, z1); + fe_inv__distinct(z1, h->Z); + fe_mul__distinct(x, h->X, z1); + fe_mul__distinct(y, h->Y, z1); - fe_normalize(x); - fe_normalize(y); + fe_normalize(x); + fe_normalize(y); - parity = (x[0] & 1) << 7; - fe_copy(s, y); - fe_normalize(s); - s[31] |= parity; + parity = (x[0] & 1) << 7; + lm_copy(s, y); + fe_normalize(s); + s[31] |= parity; } /* pack the point h into array s */ void ge_tobytes(unsigned char *s,const ge_p2 *h) { - byte x[F25519_SIZE]; - byte y[F25519_SIZE]; - byte z1[F25519_SIZE]; - byte parity; + byte x[F25519_SIZE]; + byte y[F25519_SIZE]; + byte z1[F25519_SIZE]; + byte parity; - fe_inv__distinct(z1, h->Z); - fe_mul__distinct(x, h->X, z1); - fe_mul__distinct(y, h->Y, z1); + fe_inv__distinct(z1, h->Z); + fe_mul__distinct(x, h->X, z1); + fe_mul__distinct(y, h->Y, z1); - fe_normalize(x); - fe_normalize(y); + fe_normalize(x); + fe_normalize(y); - parity = (x[0] & 1) << 7; - fe_copy(s, y); - fe_normalize(s); - s[31] |= parity; + parity = (x[0] & 1) << 7; + lm_copy(s, y); + fe_normalize(s); + s[31] |= parity; } /* - Test if the public key can be uncommpressed and negate it (-X,Y,Z,-T) + Test if the public key can be uncompressed and negate it (-X,Y,Z,-T) return 0 on success */ int ge_frombytes_negate_vartime(ge_p3 *p,const unsigned char *s) { - byte parity; + byte parity; byte x[F25519_SIZE]; - byte y[F25519_SIZE]; - byte a[F25519_SIZE]; - byte b[F25519_SIZE]; - byte c[F25519_SIZE]; + byte y[F25519_SIZE]; + byte a[F25519_SIZE]; + byte b[F25519_SIZE]; + byte c[F25519_SIZE]; int ret = 0; /* unpack the key s */ parity = s[31] >> 7; - fe_copy(y, s); - y[31] &= 127; + lm_copy(y, s); + y[31] &= 127; - fe_mul__distinct(c, y, y); + fe_mul__distinct(c, y, y); fe_mul__distinct(b, c, ed25519_d); - fe_add(a, b, f25519_one); - fe_inv__distinct(b, a); - fe_sub(a, c, f25519_one); - fe_mul__distinct(c, a, b); - fe_sqrt(a, c); - fe_neg(b, a); - fe_select(x, a, b, (a[0] ^ parity) & 1); + lm_add(a, b, f25519_one); + fe_inv__distinct(b, a); + lm_sub(a, c, f25519_one); + fe_mul__distinct(c, a, b); + fe_sqrt(a, c); + lm_neg(b, a); + fe_select(x, a, b, (a[0] ^ parity) & 1); /* test that x^2 is equal to c */ fe_mul__distinct(a, x, x); - fe_normalize(a); - fe_normalize(c); - ret |= ConstantCompare(a, c, F25519_SIZE); + fe_normalize(a); + fe_normalize(c); + ret |= ConstantCompare(a, c, F25519_SIZE); /* project the key s onto p */ - fe_copy(p->X, x); - fe_copy(p->Y, y); - fe_load(p->Z, 1); - fe_mul__distinct(p->T, x, 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; } @@ -542,17 +547,17 @@ int ge_double_scalarmult_vartime(ge_p2* R, const unsigned char *h, ed25519_smult(&p, &ed25519_base, sig); /* find H(R,A,M) * -A */ - ed25519_smult(&A, &A, h); + ed25519_smult(&A, &A, h); /* SB + -H(R,A,M)A */ - ed25519_add(&A, &p, &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 */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ge_operations.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ge_operations.c index 665cfe89b..73fa06e35 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ge_operations.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ge_operations.c @@ -1,8 +1,8 @@ /* ge_operations.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. */ @@ -29,19 +30,52 @@ #include #ifdef HAVE_ED25519 +#ifndef ED25519_SMALL /* run when not defined to use small memory math */ #include +#include #include #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif +#if defined(CURVED25519_X64) + #define CURVED25519_ASM_64BIT + #define CURVED25519_ASM +#endif +#if defined(WOLFSSL_ARMASM) + #if defined(__aarch64__) + #define CURVED25519_ASM_64BIT + #else + #define CURVED25519_ASM_32BIT + #endif + #define CURVED25519_ASM +#endif + + +static void ge_p2_0(ge_p2 *); +#ifndef CURVED25519_ASM +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. @@ -52,6 +86,36 @@ 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 + +#ifdef CURVED25519_ASM_32BIT +uint64_t load_3(const unsigned char *in) +{ + uint64_t result; + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + return result; +} + + +uint64_t load_4(const unsigned char *in) +{ + uint64_t result; + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + result |= ((uint64_t) in[3]) << 24; + return result; +} +#endif /* Input: @@ -64,261 +128,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 @@ -331,365 +331,611 @@ 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[keySz]; + byte bArray[ED25519_KEY_SIZE]; word32 i; fe_0(x); @@ -715,23 +961,29 @@ 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 WC_INLINE void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) { - fe t0; - fe_add(r->X,p->Y,p->X); - fe_sub(r->Y,p->Y,p->X); - fe_mul(r->Z,r->X,q->YplusX); - fe_mul(r->Y,r->Y,q->YminusX); - fe_mul(r->T,q->T2d,p->T); - fe_mul(r->X,p->Z,q->Z); - fe_add(t0,r->X,r->X); - fe_sub(r->X,r->Z,r->Y); - fe_add(r->Y,r->Z,r->Y); - fe_add(r->Z,t0,r->T); - fe_sub(r->T,t0,r->T); +#ifndef CURVED25519_ASM + 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); + fe_mul(r->Y,r->Y,q->YminusX); + fe_mul(r->T,q->T2d,p->T); + fe_mul(r->X,p->Z,q->Z); + fe_add(t0,r->X,r->X); + fe_sub(r->X,r->Z,r->Y); + fe_add(r->Y,r->Z,r->Y); + fe_add(r->Z,t0,r->T); + fe_sub(r->T,t0,r->T); +#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_ASM /* ge_scalar mult base */ static unsigned char equal(signed char b,signed char c) { @@ -741,29 +993,6758 @@ 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,ge_precomp *u,unsigned char b) +static WC_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_ASM_64BIT +static const ge_precomp base[64][8] = { +{ + { + { 0x2fbc93c6f58c3b85, -0x306cd2390473f1e7, 0x270b4898643d42c2, 0x07cf9d3a33d4ba65 }, + { -0x62efc6fa28bf6ec2, -0x02c660fa2ebf414d, -0x5a3e7bcb977075f7, 0x44fd2f9298f81267 }, + { -0x2442ea98b49044a7, 0x41e13f00eea2a5ea, -0x322b62e336a83906, 0x4f0ebe1faf16ecca } + }, + { + { -0x6ddb18036cc38e29, -0x60b9626985f00a4b, 0x5aa69a65e1d60702, 0x590c063fa87d2e2e }, + { -0x75665a9fbd4b2a58, -0x70d47ef3b19f530a, -0x1f61dc944e91c856, 0x6bb595a669c92555 }, + { 0x6e347eaadad36802, -0x450ca66c7c11b7fb, 0x3bcabe10e6076826, 0x49314f0a165ed1b8 } + }, + { + { -0x50da4f57b31168d0, 0x025a8430e8864b8a, -0x3ee4affd60fe98ce, 0x7a164e1b9a80f8f4 }, + { 0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, -0x7ece0ce5deb42943, 0x2ab91587555bda62 }, + { -0x640dee0b0e98b7cc, -0x47b194e809d2076b, -0x282190f8a48dd5b2, 0x549a04b963bb2a21 } + }, + { + { 0x287351b98efc099f, 0x6765c6f47dfd2538, -0x35cb72c204f56d9b, 0x680e910321e58727 }, + { -0x6a01faf5fa97e741, 0x327e89715660faa9, -0x3c171c32f95faf8d, 0x27933f4c7445a49a }, + { -0x40e1ba131aebd950, -0x1cd439c29245f06c, -0x1bd68b2a7307ad40, 0x44f079b1b0e64c18 } + }, + { + { -0x5ded43bbf75a44cd, -0x72afb73c38a112fe, -0x22e414f3a54013bc, 0x2945ccf146e206eb }, + { 0x7f9182c3a447d6ba, -0x2affeb2eb4d8d649, -0x1cc30ee3479b5f79, 0x154a7e73eb1b55f3 }, + { -0x37cd5e86182ffc4d, 0x5f729d0a00124d7e, 0x62c1d4a10e6d8ff3, 0x68b8ac5938b27a98 } + }, + { + { 0x3a0ceeeb77157131, -0x64d8ea76ff375078, -0x7f9a499725a658ca, 0x51e57bb6a2cc38bd }, + { 0x499806b67b7d8ca4, 0x575be28427d22739, -0x44f7a318dfbaac47, 0x38b64c41ae417884 }, + { -0x7062526e97621c5c, 0x175f2428f8fb9137, 0x050ab5329fcfb988, 0x7865dfa21354c09f } + }, + { + { 0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e }, + { -0x4590d36555cdde4f, 0x6ca021533bba23a7, -0x621589b06de6d3c6, 0x1d6edd5d2e5317e0 }, + { 0x217a8aacab0fda36, -0x5ad739abc2cab638, 0x37d05b8b13ab7568, 0x233cef623a2cbc37 } + }, + { + { 0x59b7596604dd3e8f, 0x6cb30377e288702c, -0x4ecc6399a1263cdd, 0x0915e76061bce52f }, + { -0x1d58a2120c6dcb27, -0x69c2897f1e4aa707, 0x2c2741ac6e3c23fb, 0x3a9024a1320e01c3 }, + { -0x208217ca57cb5c82, -0x741e63259767a816, 0x2c1185367167b326, 0x589eb3d9dbefd5c2 } + }, +}, +{ + { + { 0x322d04a52d9021f6, -0x463e60cc8a394064, 0x587a3a4342d20b09, 0x143b1cf8aa64fe61 }, + { 0x7ec851ca553e2df3, -0x58ed7b3459b7874d, -0x194a1be6cd772e19, 0x4cf210ec5a9a8883 }, + { -0x6079838269753555, 0x5f54258e27092729, -0x2f582cb415e7f68b, 0x21b546a3374126e1 } + }, + { + { 0x490a7a45d185218f, -0x65eac887b9fb6ccb, 0x0060ea09cc31e1f6, 0x7e041577f86ee965 }, + { -0x56b007a75d777cbd, -0x31f12ba9acec12c4, -0x0aa3c2304a40cb06, 0x0a653ca5c9eab371 }, + { 0x66b2a496ce5b67f3, -0x00ab6d2742a9686a, 0x503cec294a592cd0, 0x566943650813acb2 } + }, + { + { 0x5672f9eb1dabb69d, -0x458f4aca5017ac04, 0x47ac0f752796d66d, 0x32a5351794117275 }, + { -0x47e724f3d99df868, 0x5d5c31d9606e354a, 0x0982fa4f00a8cdc7, 0x17e12bcd4653e2d4 }, + { -0x2c59bb59209b7bc9, 0x703b6559880fbfdd, -0x347adabf52c5e55b, 0x0900b3f78e4c6468 } + }, + { + { -0x12d7f04137e952cf, 0x52d9595bd8e6efe3, 0x0fe71772f6c623f5, 0x4314030b051e293c }, + { 0x0a851b9f679d651b, -0x1ef7349efcccbd0e, -0x29fe0a801774cf5d, 0x371f3acaed2dd714 }, + { -0x2a9fffa1040f4353, -0x7148f0d12e78f3a2, 0x201f9033d084e6a0, 0x4c3a5ae1ce7b6670 } + }, + { + { -0x45078a1b36c25f23, -0x46cd7d588e46d6b3, -0x7f29c0480b393ba0, 0x6de9c73dea66c181 }, + { 0x4138a434dcb8fa95, -0x78f3098293697bf5, -0x21c77a8bd68417d4, 0x7c814db27262a55a }, + { 0x478904d5a04df8f2, -0x050451b54efebd2d, -0x0937539caaa2f668, 0x5aac4a412f90b104 } + }, + { + { 0x603a0d0abd7f5134, -0x7f7636cd1e2c51ba, -0x20da6ec67867429d, 0x1c145cd274ba0235 }, + { -0x39b0cd94c536d6f8, 0x5551b282e663e1e0, 0x476b35f54a1a4b83, 0x1b9da3fe189f68c2 }, + { 0x32e8386475f3d743, 0x365b8baf6ae5d9ef, -0x7dadc749c7a497e2, 0x234929c1167d65e1 } + }, + { + { 0x48145cc21d099fcf, 0x4535c192cc28d7e5, -0x7f183e1ab7db81ff, 0x4a5f28743b2973ee }, + { -0x67b213545f885218, 0x383f77ad19eb389d, -0x38139481d6ab286c, 0x59c77b3aeb7c3a7a }, + { -0x2c5228dadda3309e, -0x6ee5cc7e4dead3a3, -0x274c6052a4f70783, 0x6f05606b4799fe3b } + }, + { + { 0x5b433149f91b6483, -0x524a239aa5d3409e, -0x78057bed9cd7d84d, 0x60895e91ab49f8d8 }, + { -0x6001616de884569e, -0x675118e2f21a351f, 0x3ff4ae942d831044, 0x714de12e58533ac8 }, + { -0x16130d12f30793e8, -0x4b92f9edf8ca202c, -0x43625f67fb469419, 0x73e2e62fd96dc26b } + }, +}, +{ + { + { 0x2eccdd0e632f9c1d, 0x51d0b69676893115, 0x52dfb76ba8637a58, 0x6dd37d49a00eef39 }, + { -0x12a49cabb655aea2, -0x579a3b60f4397dc6, -0x7af3e016a4bd2e3c, 0x30d76d6f03d315b9 }, + { 0x6c4444172106e4c7, -0x04ac297f6d728097, -0x4b8c615b96b2c0da, 0x10c697112e864bb0 } + }, + { + { 0x0ca62aa08358c805, 0x6a3d4ae37a204247, 0x7464d3a63b11eddc, 0x03bf9baf550806ef }, + { 0x6493c4277dbe5fde, 0x265d4fad19ad7ea2, 0x0e00dfc846304590, 0x25e61cabed66fe09 }, + { 0x3f13e128cc586604, 0x6f5873ecb459747e, -0x5f49c21233ed970b, 0x566d78634586e22c } + }, + { + { -0x5efabd7a39a5d030, 0x6c64112af31667c3, 0x680ae240731aee58, 0x14fba5f34793b22a }, + { 0x1637a49f9cc10834, -0x4371a92a57643baf, 0x1cb5ec0f7f7fd2db, 0x33975bca5ecc35d9 }, + { 0x3cd746166985f7d4, 0x593e5e84c9c80057, 0x2fc3f2b67b61131e, 0x14829cea83fc526c } + }, + { + { 0x21e70b2f4e71ecb8, -0x19a92246bf5b881d, -0x409aa93131e2b080, 0x05fc3bc4535d7b7e }, + { -0x00bc847b68226a3e, 0x6c744e30aa4eb5a7, -0x61f3a29ec37a1775, 0x2fd9c71e5f758173 }, + { 0x24b8b3ae52afdedd, 0x3495638ced3b30cf, 0x33a4bc83a9be8195, 0x373767475c651f04 } + }, + { + { 0x634095cb14246590, -0x10edebbfe93eaacb, -0x61c7ebf376ef43a0, 0x6bf5905730907c8c }, + { 0x2fba99fd40d1add9, -0x4cf8e990690b2fd9, 0x4363f05215f03bae, 0x1fbea56c3b18f999 }, + { 0x0fa778f1e1415b8a, 0x06409ff7bac3a77e, 0x6f52d7b89aa29a50, 0x02521cf67a635a56 } + }, + { + { -0x4eeb98df88d0a11c, -0x17076b4e69f86532, 0x4af8224d00ac824a, 0x001753d9f7cd6cc4 }, + { 0x513fee0b0a9d5294, -0x706718a3f020a59a, -0x2b9e7977401ef832, 0x3fa00a7e71382ced }, + { 0x3c69232d963ddb34, 0x1dde87dab4973858, -0x55282e065f6e0d7b, 0x12b5fe2fa048edb6 } + }, + { + { -0x20d483d95290e16e, 0x4b66d323504b8913, -0x73bf623f8ae3743d, 0x6f7e93c20796c7b8 }, + { 0x71f0fbc496fce34d, 0x73b9826badf35bed, -0x2dfb8d9e00d73a9f, 0x749b76f96fb1206f }, + { 0x1f5af604aea6ae05, -0x3edcae0e411b6367, 0x61a808b5eeff6b66, 0x0fcec10f01e02151 } + }, + { + { 0x3df2d29dc4244e45, 0x2b020e7493d8de0a, 0x6cc8067e820c214d, 0x413779166feab90a }, + { 0x644d58a649fe1e44, 0x21fcaea231ad777e, 0x02441c5a887fd0d2, 0x4901aa7183c511f3 }, + { 0x08b1b7548c1af8f0, -0x31f08583db9d664c, -0x089f4f06e1f926c7, 0x41bb887b726d1213 } + }, +}, +{ + { + { -0x68267f1f55c6082e, 0x35d0384252c6b51c, 0x7d43f49307cd55aa, 0x56bd36cfb78ac362 }, + { -0x6d987f93a983b628, 0x066d04ccca791e6a, -0x5960a9ba1c33c6b5, 0x5c95b686a0788cd2 }, + { 0x2ac519c10d14a954, -0x150b8b4b6b4a0570, -0x19507c7d560785a6, 0x0dea6db1879be094 } + }, + { + { 0x15baeb74d6a8797a, 0x7ef55cf1fac41732, 0x29001f5a3c8b05c5, 0x0ad7cc8752eaccfb }, + { -0x559940ab8cbb1a55, -0x25eda77770e4bcf7, 0x5e87d2b3fd564b2f, 0x5b2c78885483b1dd }, + { 0x52151362793408cf, -0x14f0e8fce669c26c, -0x57cc4d0577c26b9a, 0x093a7fa775003c78 } + }, + { + { -0x47169fbb9f56ed7a, 0x7f3fd8047778d3de, 0x67d01e31bf8a5e2d, 0x7b038a06c27b653e }, + { -0x1aef8219c5e92842, -0x5c880023650ccd31, 0x70d5bf18440b677f, 0x6a252b19a4a31403 }, + { -0x6126e62a2c966f0d, 0x5213aebbdb4eb9f2, -0x38f715fab3466ecb, 0x58ded57f72260e56 } + }, + { + { -0x2592acd9a4f02b75, -0x769f7dce6c405678, -0x287536cd9e2a81d8, 0x79f2942d3a5c8143 }, + { 0x78e79dade9413d77, -0x0da8062a68d61983, 0x59db910ee37aa7e6, 0x6aa11b5bbb9e039c }, + { -0x6825d0da49377217, 0x251ba7eaacf20169, 0x09b44f87ef4eb4e4, 0x7d90ab1bbc6a7da5 } + }, + { + { 0x1a07a3f496b3c397, 0x11ceaa188f4e2532, 0x7d9498d5a7751bf0, 0x19ed161f508dd8a0 }, + { -0x6533597c58fe9402, -0x6fafa0b20d3af493, 0x6b610d5fcce435aa, 0x19a10d446198ff96 }, + { 0x560a2cd687dce6ca, 0x7f3568c48664cf4d, -0x78be16addd7fc5c8, 0x483bdab1595653fc } + }, + { + { -0x2930b2f54b257f0a, -0x7db7c1ba07cf8020, 0x05005269ae6f9da4, 0x1c7052909cf7877a }, + { -0x0587f0eb78cb05b7, 0x106f0b70360534e0, 0x2210776fe3e307bd, 0x3286c109dde6a0fe }, + { 0x32ee7de2874e98d4, 0x14c362e9b97e0c60, 0x5781dcde6a60a38a, 0x217dd5eaaa7aa840 } + }, + { + { -0x7420e0464173f138, 0x00bae7f8e30a0282, 0x4963991dad6c4f6c, 0x07058a6e5df6f60a }, + { -0x62483b2fdb71e150, -0x1f89681eb28b40ae, 0x1e6a9b173c562354, 0x7fa7c21f795a4965 }, + { -0x1614fd3b24ce0981, -0x12da0276ef4304d5, 0x46c8131f5c5cddb4, 0x33b21c13a0cb9bce } + }, + { + { -0x6550464fa11c73a5, -0x4062d2b1f8e5ec39, -0x7111919216ccd6f6, 0x1c3bab17ae109717 }, + { 0x360692f8087d8e31, -0x0b2339c82d8e9c09, 0x25a4e62065ea5963, 0x659bf72e5ac160d9 }, + { 0x1c9ab216c7cab7b0, 0x7d65d37407bbc3cc, 0x52744750504a58d5, 0x09f2606b131a2990 } + }, +}, +{ + { + { 0x7e234c597c6691ae, 0x64889d3d0a85b4c8, -0x251d36f3cab50519, 0x0a871e070c6a9e1d }, + { 0x40e87d44744346be, 0x1d48dad415b52b25, 0x7c3a8a18a13b603e, 0x4eb728c12fcdbdf7 }, + { 0x3301b5994bbc8989, 0x736bae3a5bdd4260, 0x0d61ade219d59e3c, 0x3ee7300f2685d464 } + }, + { + { 0x43fa7947841e7518, -0x1a3905a69c63b929, -0x5ef9a1e21cfad48c, 0x7d47c6a2cfb89030 }, + { -0x0a2daa1b61822949, -0x7fe9eea39ef4e154, 0x3c99975d92e187ca, 0x13815762979125c2 }, + { 0x3fdad0148ef0d6e0, -0x62c18b656eab90c4, 0x71ec621026bb8157, 0x148cf58d34c9ec80 } + }, + { + { -0x1da8d082651b8a93, 0x56c345bb88f3487f, -0x602ef492969f5773, 0x278febad4eaea1b9 }, + { 0x46a492f67934f027, 0x469984bef6840aa9, 0x5ca1bc2a89611854, 0x3ff2fa1ebd5dbbd4 }, + { -0x4e5597e0736cc69a, -0x73de6b63dfd6f368, 0x39115291219d3c52, 0x4104dd02fe9c677b } + }, + { + { -0x7edeb1f924f69548, 0x21a8b6c90ce44f35, 0x6524c12a409e2af5, 0x0165b5a48efca481 }, + { 0x72b2bf5e1124422a, -0x5e05f3cc675cc54b, -0x6b349efe05ad499a, 0x2c863b00afaf53d5 }, + { -0x0e6f5b8b5f7b958a, 0x12eff984cd2f7cc0, 0x695e290658aa2b8f, 0x591b67d9bffec8b8 } + }, + { + { -0x66464c8e60e74aa3, -0x1b9a1a055e739be2, 0x61081136c29f05ed, 0x489b4f867030128b }, + { 0x312f0d1c80b49bfa, 0x5979515eabf3ec8a, 0x727033c09ef01c88, 0x3de02ec7ca8f7bcb }, + { -0x2dcdefd2c5146d11, -0x1e9dac4b9ee9579f, 0x3d7eabe7190baa24, 0x49f5fbba496cbebf } + }, + { + { 0x155d628c1e9c572e, -0x75b279533a77b8bf, -0x6e5cad09aea89c15, 0x06a1a6c28867515b }, + { 0x30949a108a5bcfd4, -0x23bf228f439b8c15, -0x6d3d6b3ecf83f2e4, 0x5604a86dcbfa6e74 }, + { 0x7288d1d47c1764b6, 0x72541140e0418b51, -0x60fce59fe753092f, 0x20989e89fe2742c6 } + }, + { + { 0x1674278b85eaec2e, 0x5621dc077acb2bdf, 0x640a4c1661cbf45a, 0x730b9950f70595d3 }, + { 0x499777fd3a2dcc7f, 0x32857c2ca54fd892, -0x5d86279b2df81c60, 0x0403ed1d0ca67e29 }, + { -0x36b4d2ca78b13aae, -0x3a19373067db9073, -0x0834b905e93fca32, 0x5bd7454308303dcc } + }, + { + { -0x7a3b6cdeea1886d6, -0x39b3765d42322237, -0x62e1c257525c289e, 0x5bb7db123067f82c }, + { 0x7f9ad19528b24cc2, 0x7f6b54656335c181, 0x66b8b66e4fc07236, 0x133a78007380ad83 }, + { 0x0961f467c6ca62be, 0x04ec21d6211952ee, 0x182360779bd54770, 0x740dca6d58f0e0d2 } + }, +}, +{ + { + { 0x3906c72aed261ae5, -0x65497026771eff09, -0x0a16fa650cc9fe69, 0x0e53dc78bf2b6d47 }, + { 0x50b70bf5d3f0af0b, 0x4feaf48ae32e71f7, 0x60e84ed3a55bbd34, 0x00ed489b3f50d1ed }, + { -0x46f7d640868e7886, 0x5e4444636d17e631, 0x4d05c52e18276893, 0x27632d9a5a4a4af5 } + }, + { + { -0x567d7a2e78150025, -0x5a4b0444272f579c, -0x49a70d80fdd99c09, 0x3bbc2b22d99ce282 }, + { -0x2ee00faeab4d9f32, -0x27923c718d06ad90, 0x601fcd0d267cc138, 0x2b67916429e90ccd }, + { -0x46e836ada7c3f5a8, 0x653ff9b80fe4c6f3, -0x64f258284320c3f4, 0x43a0eeb6ab54d60e } + }, + { + { 0x3ac6322357875fe8, -0x262b0b130a043471, -0x72117b6cc7d449e0, 0x50c5eaa14c799fdc }, + { 0x396966a46d4a5487, -0x07ee5e7553d44c46, 0x66e4685b5628b26b, 0x70a477029d929b92 }, + { -0x22f12374290d04c4, 0x54c63aa79cc7b7a0, -0x51f4fcd4d37260e6, 0x6f9ce107602967fb } + }, + { + { 0x139693063520e0b5, 0x437fcf7c88ea03fe, -0x082b3bf42c36a644, 0x699154d1f893ded9 }, + { -0x52efab4e321e3dd6, -0x3b5716fdb714cd21, 0x5f3e7b33accdc0ea, 0x72364713fc79963e }, + { 0x315d5c75b4b27526, -0x33347bd2fdc9255b, 0x22f0c8a3345fee8e, 0x73975a617d39dbed } + }, + { + { 0x6f37f392f4433e46, 0x0e19b9a11f566b18, 0x220fb78a1fd1d662, 0x362a4258a381c94d }, + { -0x1bfdb2069c8a25f0, 0x78d3251a1830c870, -0x6fd4e6b79a7326e4, 0x7e18b10b29b7438a }, + { -0x6f8e26ecd49414d1, 0x0f26e9ad28418247, -0x1546e13642136da3, 0x4be65bc8f48af2de } + }, + { + { 0x1d50fba257c26234, 0x7bd4823adeb0678b, -0x3d4f239159ac750b, 0x5665eec6351da73e }, + { 0x78487feba36e7028, 0x5f3f13001dd8ce34, -0x6cb04ed2b4cf3b77, 0x056c244d397f0a2b }, + { -0x24c11ff6bc404df0, 0x4972018720800ac2, 0x26ab5d6173bd8667, 0x20b209c2ab204938 } + }, + { + { 0x1fcca94516bd3289, 0x448d65aa41420428, 0x59c3b7b216a55d62, 0x49992cc64e612cd8 }, + { 0x549e342ac07fb34b, 0x02d8220821373d93, -0x43d9d28f532e0a99, 0x7a92c9fdfbcac784 }, + { 0x65bd1bea70f801de, 0x1befb7c0fe49e28a, -0x579cf9324e4d51b6, 0x3b7ac0cd265c2a09 } + }, + { + { -0x0f2ab1b0dd12c659, -0x5d5516e1a9f7eaf6, -0x0bde4d161225178b, 0x31bc531d6b7de992 }, + { -0x7dd411bc73fe4314, 0x530cb525c0fbc73b, 0x48519034c1953fe9, 0x265cc261e09a0f5b }, + { -0x20c2ecb2567f068f, 0x7a4fb8d1221a22a7, 0x3df7d42035aad6d8, 0x2a14edcc6a1a125e } + }, +}, +{ + { + { 0x231a8c570478433c, -0x484ad8f13d7ebc63, -0x245566151c26f861, 0x2c03f5256c2b03d9 }, + { -0x20b711f8ad3031b2, -0x3c00050cf913f749, 0x05710b2ab95459c4, 0x161d25fa963ea38d }, + { 0x790f18757b53a47d, 0x307b0130cf0c5879, 0x31903d77257ef7f9, 0x699468bdbd96bbaf } + }, + { + { -0x2722c2199556e6b8, 0x485064c22fc0d2cc, -0x64b7db99cb0215d1, 0x293e1c4e6c4a2e3a }, + { -0x42e0d0b90b250131, 0x7cef0114a47fd6f7, -0x2ce00225b5b84c81, 0x525219a473905785 }, + { 0x376e134b925112e1, 0x703778b5dca15da0, -0x4fba7650b9e3ceef, 0x5b605c447f032823 } + }, + { + { 0x3be9fec6f0e7f04c, -0x7995a8618a1cb69e, 0x5542ef161e1de61a, 0x2f12fef4cc5abdd5 }, + { -0x469a7fa6df3b8377, -0x180feff36dc47034, 0x0001256502e2ef77, 0x24a76dcea8aeb3ee }, + { 0x0a4522b2dfc0c740, 0x10d06e7f40c9a407, -0x3930ebbe87300998, 0x5e607b2518a43790 } + }, + { + { -0x5fd3bce35a6930ec, -0x1c3bd2bf512c1c00, -0x2dbad97fd1f0d925, 0x201f33139e457068 }, + { 0x58b31d8f6cdf1818, 0x35cfa74fc36258a2, -0x1e4c00b09919e292, 0x5067acab6ccdd5f7 }, + { -0x02ad8094f7fc62af, 0x18b14964017c0006, -0x2addf14fd1da5b58, 0x397cba8862460375 } + }, + { + { 0x7815c3fbc81379e7, -0x599e6bdf221ed50f, -0x00563f077a57022b, 0x771b4022c1e1c252 }, + { 0x30c13093f05959b2, -0x1dc55e721656868a, 0x222fd491721d5e26, 0x2339d320766e6c3a }, + { -0x27822679aec5d059, -0x0a53648e062b30f8, -0x2f943ce4e15d7c4d, 0x331a189219971a76 } + }, + { + { 0x26512f3a9d7572af, 0x5bcbe28868074a9e, -0x7b123e3eee7f083c, 0x1ac9619ff649a67b }, + { -0x0ae990ba04b07f3a, -0x63c938219e388a31, -0x1c2b17e46fbe26e4, 0x31167c6b83bdfe21 }, + { -0x0dd4c7bdadb4ef98, 0x5068343bee9ce987, -0x03628e7bb59daf38, 0x612436341f08b111 } + }, + { + { -0x749cb61ce5d2d9c8, -0x622048ff642c02cb, 0x7f8bf1b8a3a06ba4, 0x1522aa3178d90445 }, + { -0x2662be2478b17673, 0x09fea5f16c07dc20, 0x793d2c67d00f9bbc, 0x46ebe2309e5eff40 }, + { 0x2c382f5369614938, -0x2501bf6548d292f0, -0x1737cc6e49b90dd9, 0x45fe70f50524306c } + }, + { + { 0x62f24920c8951491, 0x05f007c83f630ca2, 0x6fbb45d2f5c9d4b8, 0x16619f6db57a2245 }, + { -0x25b78a5969f3f474, 0x5b68d076ef0e2f20, 0x07fb51cf3d0b8fd4, 0x428d1623a0e392d4 }, + { 0x084f4a4401a308fd, -0x57dde63c895a3554, -0x214721b9bc2e4383, 0x1d81592d60bd38c6 } + }, +}, +{ + { + { 0x3a4a369a2f89c8a1, 0x63137a1d7c8de80d, -0x4353ff7587125feb, 0x2cb8b3a5b483b03f }, + { -0x27cc284113d5b3c8, 0x2c9162830acc20ed, -0x16c5b8556d208a7f, 0x702d67a3333c4a81 }, + { 0x36e417cbcb1b90a1, 0x33b3ddaa7f11794e, 0x3f510808885bc607, 0x24141dc0e6a8020d } + }, + { + { -0x6e6da233427cea83, 0x3ca1205322cc8094, 0x28e57f183f90d6e4, 0x1a4714cede2e767b }, + { 0x59f73c773fefee9d, -0x4c0e10763e306763, -0x1ca204bd1fd1aba1, 0x5766120b47a1b47c }, + { -0x24df45f047494801, -0x48cd3c4988aee05f, -0x56d4ae3f660fd277, 0x4f3875ad489ca5f1 } + }, + { + { 0x79ed13f6ee73eec0, -0x5a39ad9296eef44f, -0x1b76d73c79fc79f4, 0x722a1446fd7059f5 }, + { -0x380389d0b6cd54de, 0x7ac0edf72f4c3c1b, 0x5f6b55aa9aa895e8, 0x3680274dad0a0081 }, + { -0x2f6a6016573077e7, -0x2f566aaf7b8a5664, 0x6eac173320b09cc5, 0x628ecf04331b1095 } + }, + { + { -0x64be5307a38b330f, -0x498cce7ef7d9adaf, -0x6636d512ee524eb9, 0x7a47d70d34ecb40f }, + { -0x67434ee7562f2244, -0x11bb61cbf74b7fd5, -0x78f76dd947594efc, 0x685f349a45c7915d }, + { 0x60a0c4cbcc43a4f5, 0x775c66ca3677bea9, -0x5e855e8ad0070a13, 0x11ded9020e01fdc0 } + }, + { + { 0x471f95b03bea93b7, 0x0552d7d43313abd3, -0x426c8f1d1e81c085, 0x7b120f1db20e5bec }, + { -0x76f187f6351018fc, -0x78d7d6921cf17394, 0x4c5cd2a392aeb1c9, 0x194263d15771531f }, + { 0x17d2fb3d86502d7a, -0x4a9b27bbaf596cae, 0x7da962c8a60ed75d, 0x00d0f85b318736aa } + }, + { + { -0x598ac3e10289de3f, 0x69c0b4a7445671f5, -0x68e0ad8bfa4dc3ef, 0x387bc74851a8c7cd }, + { -0x6874ebd188837b03, -0x0bfd9bb8fa573f9e, -0x59852ae41819ed39, 0x2f7b459698dd6a33 }, + { -0x7e76b4b2b5ad5658, -0x5226c1ed09477cd1, 0x184d8548b61bd638, 0x3f1c62dbd6c9f6cd } + }, + { + { 0x3fad3e40148f693d, 0x052656e194eb9a72, 0x2f4dcbfd184f4e2f, 0x406f8db1c482e18b }, + { 0x2e8f1f0091910c1f, -0x5b20b01f400d1ed4, 0x60c6560aee927438, 0x6338283facefc8fa }, + { -0x619cf2d380e6e11c, 0x4fbf8301bc3ff670, 0x787d8e4e7afb73c4, 0x50d83d5be8f58fa5 } + }, + { + { -0x3f53306f4b2c4993, -0x58fa621a9e8cd1a0, 0x033d1f7870c6b0ba, 0x584161cd26d946e4 }, + { -0x7a97c6e93ee5e769, 0x2d69a4efe506d008, 0x39af1378f664bd01, 0x65942131361517c6 }, + { -0x440d4e5f8d2d835e, -0x40c6c3a6042138fc, -0x167244311d9d47e2, 0x02eebd0b3029b589 } + }, +}, +{ + { + { -0x789a4960847a3a18, 0x6ff0678bd168bab2, 0x3a70e77c1d330f9b, 0x3a5f6d51b0af8e7c }, + { 0x61368756a60dac5f, 0x17e02f6aebabdc57, 0x7f193f2d4cce0f7d, 0x20234a7789ecdcf0 }, + { 0x76d20db67178b252, 0x071c34f9d51ed160, -0x09d5b5df4c1bee90, 0x7cd682353cffe366 } + }, + { + { -0x599a329f97530b0d, 0x42d92d183cd7e3d3, 0x5759389d336025d9, 0x3ef0253b2b2cd8ff }, + { 0x0be1a45bd887fab6, 0x2a846a32ba403b6e, -0x266defed1691a000, 0x2838c8863bdc0943 }, + { -0x2e944f30b5b9afd0, -0x05b694beea3a8855, -0x7d3051750b54be63, 0x21dcb8a606a82812 } + }, + { + { -0x6572ff054188ce46, -0x7dfc9f819d61e777, -0x4d33fdc8bc0c2681, 0x5d840dbf6c6f678b }, + { 0x5c6004468c9d9fc8, 0x2540096ed42aa3cb, 0x125b4d4c12ee2f9c, 0x0bc3d08194a31dab }, + { 0x706e380d309fe18b, 0x6eb02da6b9e165c7, 0x57bbba997dae20ab, 0x3a4276232ac196dd } + }, + { + { 0x3bf8c172db447ecb, 0x5fcfc41fc6282dbd, -0x7f53003f8a55ea02, 0x0770c9e824e1a9f9 }, + { 0x4b42432c8a7084fa, -0x7675e61c20461abb, -0x4160ffde63a71ba3, 0x1ff177cea16debd1 }, + { -0x309e2665ba4a4a03, -0x79f67b16e4c586dc, -0x18cff6e6cfc1c177, 0x39f264fd41500b1e } + }, + { + { -0x2e64b55401f6841f, -0x5b92031e201fe6d7, -0x3c36f76bd3590e01, 0x65c621272c35f14e }, + { -0x5852cbe824181d64, -0x426bc895d463ec64, -0x5f16e4716ca68457, 0x1712d73468889840 }, + { -0x18d4760731ce6c23, 0x4d103356a125c0bb, 0x0419a93d2e1cfe83, 0x22f9800ab19ce272 } + }, + { + { 0x42029fdd9a6efdac, -0x46ed3141cb5ab6bf, 0x640f64b987bdf37b, 0x4171a4d38598cab4 }, + { 0x605a368a3e9ef8cb, -0x1c163fdd5aafb8eb, 0x553d48b05f24248f, 0x13f416cd647626e5 }, + { -0x05d8a7556636b374, 0x23006f6fb000b807, -0x042d6e225225ac6e, 0x508214fa574bd1ab } + }, + { + { 0x461a15bb53d003d6, -0x4defd777430c369b, 0x27c576756c683a5a, 0x3a7758a4c86cb447 }, + { -0x3dfd96eac12901b5, -0x59a598c6aee2883c, -0x3421d9b9d3eb506c, 0x22f960ec6faba74b }, + { 0x548111f693ae5076, 0x1dae21df1dfd54a6, 0x12248c90f3115e65, 0x5d9fd15f8de7f494 } + }, + { + { 0x3f244d2aeed7521e, -0x71c56fd7bcd169eb, -0x1e9b4588d163e92c, 0x3bc187fa47eb98d8 }, + { 0x031408d36d63727f, 0x6a379aefd7c7b533, -0x561e703a33511db5, 0x332f35914f8fbed3 }, + { 0x6d470115ea86c20c, -0x6675483493b92edb, -0x2887cd4ac599fe78, 0x450d81ce906fba03 } + }, +}, +{ + { + { 0x23264d66b2cae0b5, 0x7dbaed33ebca6576, 0x030ebed6f0d24ac8, 0x2a887f78f7635510 }, + { -0x0751b2d527bac6fe, 0x7018058ee8db2d1d, -0x554c66a0382d3ee2, 0x53b16d2324ccca79 }, + { 0x2a23b9e75c012d4f, 0x0c974651cae1f2ea, 0x2fb63273675d70ca, 0x0ba7250b864403f5 } + }, + { + { -0x229ca76c79079264, 0x61699176e13a85a4, 0x2e5111954eaa7d57, 0x32c21b57fb60bdfb }, + { -0x44f2e702fd639bdf, -0x43d2ebde76d670fe, -0x7cb8071974daf16a, 0x7b9f2fe8032d71c9 }, + { -0x2787dc32ce61f880, -0x103b303e76888a3b, 0x4854fb129a0ab3f7, 0x12c49d417238c371 } + }, + { + { 0x09b3a01783799542, 0x626dd08faad5ee3f, -0x45ff4311148feb61, 0x1421b246a0a444c9 }, + { 0x0950b533ffe83769, 0x21861c1d8e1d6bd1, -0x0fdd27c7ecfd1af0, 0x2509200c6391cab4 }, + { 0x4aa43a8e8c24a7c7, 0x04c1f540d8f05ef5, -0x5245a1f3f4c14624, 0x2ab5504448a49ce3 } + }, + { + { -0x23f8539ce3a2c506, 0x58615171f9df8c6c, 0x72a079d89d73e2b0, 0x7301f4ceb4eae15d }, + { 0x2ed227266f0f5dec, -0x67db11bea12af7dc, -0x7f8413836b972beb, 0x7093bae1b521e23f }, + { 0x6409e759d6722c41, -0x598b1e308d408d65, -0x43f5db14c3de1a97, 0x390167d24ebacb23 } + }, + { + { -0x2844fab45d0dedf5, -0x1d4631514efa7649, 0x3fe8bac8f3c0edbe, 0x4cbd40767112cb69 }, + { 0x27f58e3bba353f1c, 0x4c47764dbf6a4361, -0x50443b1a91a9d9b0, 0x07db2ee6aae1a45d }, + { 0x0b603cc029c58176, 0x5988e3825cb15d61, 0x2bb61413dcf0ad8d, 0x7b8eec6c74183287 } + }, + { + { 0x32fee570fc386b73, -0x2574febe25c57339, -0x68a002f537697ca7, 0x6ee809a1b132a855 }, + { -0x1b35bf87d32d8350, -0x25063cdc04169843, -0x4d642cb5752be162, 0x72810497626ede4d }, + { -0x6bbb44ce030279c6, 0x2fe3690a3e4e48c5, -0x23d637982f7705db, 0x13bd1e38d173292e } + }, + { + { 0x223fb5cf1dfac521, 0x325c25316f554450, 0x030b98d7659177ac, 0x1ed018b64f88a4bd }, + { -0x2cd4b327969eb64b, -0x1aa6c8287e275549, 0x0bcb2127ae122b94, 0x41e86fcfb14099b0 }, + { 0x3630dfa1b802a6b0, -0x77f078b8bd52c42b, 0x0af90d6ceec5a4d4, 0x746a247a37cdc5d9 } + }, + { + { 0x6eccd85278d941ed, 0x2254ae83d22f7843, -0x3add2fd184403249, 0x681e3351bff0e4e2 }, + { -0x2ace4742d484650a, 0x5005093537fc5b51, 0x232fcf25c593546d, 0x20a365142bb40f49 }, + { -0x749b4a627cfcb0bb, 0x2f8b71f21fa20efb, 0x69249495ba6550e4, 0x539ef98e45d5472b } + }, +}, +{ + { + { -0x2f8b2769e3518bc1, -0x0792e70a11e39c13, -0x68423aa4180b12d7, 0x4cbad279663ab108 }, + { 0x6e7bb6a1a6205275, -0x55b0de28bec3717d, 0x6f56d155e88f5cb2, 0x2de25d4ba6345be1 }, + { -0x7f2e6fdb5f28e033, -0x3ada3df504d77508, -0x4e5c68b4a0c59be7, 0x7d7fbcefe2007233 } + }, + { + { -0x3283a23a0c3d6f6c, -0x387e5d65d56efa55, -0x7f39e2c9bde3cfa8, 0x4f9cd196dcd8d4d7 }, + { -0x0510e195d994d7ff, -0x7993973b2a8c60ea, -0x0975d043e4fc89d4, 0x5975435e87b75a8d }, + { 0x199297d86a7b3768, -0x2f2fa7dbe52e859d, -0x45fd6352a3e3f3e9, 0x7ccdd084387a0307 } + }, + { + { -0x64f37be7989f336d, -0x3251ff85e54cd567, -0x577213799df425e8, 0x3593ca848190ca44 }, + { -0x2359bdd392d9fbe9, -0x51eac2af6b7dbf43, -0x563f3e4b04973989, 0x428bd0ed61d0cf53 }, + { -0x6dece765a17b6559, -0x2b273cca9a270533, -0x73adaba4ac02442f, 0x27398308da2d63e6 } + }, + { + { -0x465ef1b3f58fdbad, 0x0fa25866d57d1bde, -0x0046264a32d82509, 0x572c2945492c33fd }, + { 0x42c38d28435ed413, -0x42af0c9fcd873337, -0x44f854e58625fc11, 0x269597aebe8c3355 }, + { -0x388038ba2932cf42, -0x1b20172c1c455105, -0x5dd377cf55a225f4, 0x7f985498c05bca80 } + }, + { + { -0x2ca9eaadf0409c9d, 0x08045a45cf4dfba6, -0x113db04378c05f3e, 0x30f2653cd69b12e7 }, + { 0x3849ce889f0be117, -0x7ffa52e484ab5d78, 0x3da3c39f23fc921c, 0x76c2ec470a31f304 }, + { -0x75f736c7553ef37b, 0x46179b60db276bcb, -0x56df3fe1f1905390, 0x2f1273f1596473da } + }, + { + { 0x30488bd755a70bc0, 0x06d6b5a4f1d442e7, -0x152e596143a69e9e, 0x38ac1997edc5f784 }, + { 0x4739fc7c8ae01e11, -0x02ad8b6fb5955461, 0x41d98a8287728f2e, 0x5d9e572ad85b69f2 }, + { 0x0666b517a751b13b, 0x747d06867e9b858c, -0x53533feebab221b7, 0x22dfcd9cbfe9e69c } + }, + { + { 0x56ec59b4103be0a1, 0x2ee3baecd259f969, 0x797cb29413f5cd32, 0x0fe9877824cde472 }, + { -0x72242d1f3cf2f327, -0x527199a05344bccd, -0x7094da73cdd569e1, 0x6b2916c05448c1c7 }, + { 0x7edb34d10aba913b, 0x4ea3cd822e6dac0e, 0x66083dff6578f815, 0x4c303f307ff00a17 } + }, + { + { 0x29fc03580dd94500, -0x132d855b9044136d, 0x130a155fc2e2a7f8, 0x416b151ab706a1d5 }, + { -0x2cf5c429e84d737b, -0x3a2c8848c688c416, -0x39391873e195a341, 0x0d61b8f78b2ab7c4 }, + { 0x56a8d7efe9c136b0, -0x42f81a32a71bb4e0, -0x5019d025e4a81f55, 0x191a2af74277e8d2 } + }, +}, +{ + { + { 0x09d4b60b2fe09a14, -0x3c7b0f50244e8b82, 0x58e2ea8978b5fd6e, 0x519ef577b5e09b0a }, + { -0x2aaff6a45490b67b, 0x04f4cd5b4fbfaf1a, -0x6271d12ed5f38ac0, 0x2bc24e04b2212286 }, + { 0x1863d7d91124cca9, 0x7ac08145b88a708e, 0x2bcd7309857031f5, 0x62337a6e8ab8fae5 } + }, + { + { -0x2e54cdb1e4c5ed8d, 0x18947cf181055340, 0x3b5d9567a98c196e, 0x7fa00425802e1e68 }, + { 0x4bcef17f06ffca16, -0x21f91e2496d51e96, 0x0753702d614f42b0, 0x5f6041b45b9212d0 }, + { 0x7d531574028c2705, -0x7fce829624f28a02, 0x30fface8ef8c8ddd, 0x7e9de97bb6c3e998 } + }, + { + { -0x0ffb419d5db2bf23, -0x45f9a66efbad2be1, -0x7e3ba11e9d5bbdcc, 0x4cb829d8a22266ef }, + { 0x1558967b9e6585a3, -0x6836631f6716746e, 0x10af149b6eb3adad, 0x42181fe8f4d38cfa }, + { 0x1dbcaa8407b86681, 0x081f001e8b26753b, 0x3cd7ce6a84048e81, 0x78af11633f25f22c } + }, + { + { 0x3241c00e7d65318c, -0x19411a232f179219, 0x118b2dc2fbc08c26, 0x680d04a7fc603dc3 }, + { -0x7be9142bf4af4544, 0x1508722628208bee, -0x5ceb7050463e3c93, 0x0d07daacd32d7d5d }, + { -0x063dbeb596a55c15, -0x255bd3b3fa5970df, 0x7c6c23987f93963e, 0x210e8cd30c3954e3 } + }, + { + { 0x2b50f16137fe6c26, -0x1efd4327a91bfb28, 0x12b0f1414c561f6b, 0x51b17bc8d028ec91 }, + { -0x53bdfe0def58e3fa, 0x6a65e0aef3bfb021, -0x43bd3ca3c6c9cd09, 0x56ea8db1865f0742 }, + { -0x000a04b430acaee7, -0x0b67628620eef760, -0x4203159a65c45cdb, 0x18a11f1174d1a6f2 } + }, + { + { -0x0429c3252d85a0d4, -0x0ff03b43755ef929, 0x53fb5c1a8e64a430, 0x04eaabe50c1a2e85 }, + { 0x407375ab3f6bba29, -0x613c492766e1b7d2, -0x6637f17d1aa06d17, 0x307c13b6fb0c0ae1 }, + { 0x24751021cb8ab5e7, -0x03dcbbb6a3afef15, 0x5f1e717b4e5610a1, 0x44da5f18c2710cd5 } + }, + { + { -0x6ea9019476271534, -0x19486bae1dced95f, -0x428b9c26c6bb14b2, 0x726373f6767203ae }, + { 0x033cc55ff1b82eb5, -0x4ea51c92bee351ae, -0x45bf49e67004532d, 0x768edce1532e861f }, + { -0x1cfa358d14810976, 0x662cf31f70eadb23, 0x18f026fdb4c45b68, 0x513b5384b5d2ecbd } + }, + { + { 0x5e2702878af34ceb, -0x6ff4fbf646b92952, 0x6512ebf7dabd8512, 0x61d9b76988258f81 }, + { 0x46d46280c729989e, 0x4b93fbd05368a5dd, 0x63df3f81d1765a89, 0x34cebd64b9a0a223 }, + { -0x593a58ecb64826b5, -0x5c0c2ea7dc146bba, 0x0416fbd277484834, 0x69d45e6f2c70812f } + }, +}, +{ + { + { -0x6019d4bcb0b9f105, -0x212cfc2b59c9f82a, -0x0faddef1485f25dc, 0x237e7dbe00545b93 }, + { -0x31e908b43ac3ebcf, 0x2b9725ce2072edde, -0x47463c904a4dc119, 0x7e2e0e450b5cc908 }, + { 0x013575ed6701b430, 0x231094e69f0bfd10, 0x75320f1583e47f22, 0x71afa699b11155e3 } + }, + { + { -0x15bdc3e3b8c4af2a, 0x51e87a1f3b38ef10, -0x647b40a04d36416b, 0x00731fbc78f89a1c }, + { 0x65ce6f9b3953b61d, -0x39a7c615505ebe1a, 0x0f435ffda9f759fe, 0x021142e9c2b1c28e }, + { -0x1bcf38e7b707e780, -0x4069f3dda1313ee7, -0x49251f7c9445ea1d, 0x4c4d6f3347e15808 } + }, + { + { 0x2f0cddfc988f1970, 0x6b916227b0b9f51b, 0x6ec7b6c4779176be, 0x38bf9500a88f9fa8 }, + { 0x18f7eccfc17d1fc9, 0x6c75f5a651403c14, -0x24218ed40811f321, 0x193fddaaa7e47a22 }, + { 0x1fd2c93c37e8876f, -0x5d09e1a5e72eb9d4, 0x5080f58239241276, 0x6a6fb99ebf0d4969 } + }, + { + { -0x114edd4a491bdc3a, -0x6c628fef0d790072, -0x6f56d57ce230a274, 0x136fda9f42c5eb10 }, + { 0x6a46c1bb560855eb, 0x2416bb38f893f09d, -0x28e2eec8708e533f, 0x75f76914a31896ea }, + { -0x06b3204e5cfa422f, 0x0f364b9d9ff82c08, 0x2a87d8a5c3bb588a, 0x022183510be8dcba } + }, + { + { -0x62a58efebccf8581, -0x4f9c21613b825ba1, 0x22bbfe52be927ad3, 0x1387c441fd40426c }, + { 0x4af766385ead2d14, -0x5f71277f3583a7d0, 0x0d13a6e610211e3d, 0x6a071ce17b806c03 }, + { -0x4a2c3c2e78687508, 0x722b5a3d7f0e4413, 0x0d7b4848bb477ca0, 0x3171b26aaf1edc92 } + }, + { + { -0x59f248274d75b82f, -0x5940eb29e88f5b0f, -0x2b5e076cac2242a8, 0x6c514a63344243e9 }, + { -0x56d0ce6f68a9b358, -0x008447b3dd8a1ee7, 0x4f55fe37a4875150, 0x221fd4873cf0835a }, + { 0x2322204f3a156341, -0x048c1f1645f5fcd3, -0x031f22b3bef0fcf2, 0x48daa596fb924aaa } + }, + { + { 0x14f61d5dc84c9793, -0x66be061c10be7dfa, -0x320a4770cb9d8854, 0x58c837fa0e8a79a9 }, + { 0x6eca8e665ca59cc7, -0x57b8dab4d1c75360, 0x31afc708d21e17ce, 0x676dd6fccad84af7 }, + { 0x0cf9688596fc9058, 0x1ddcbbf37b56a01b, -0x233d1882b6ca2996, 0x1c4f73f2c6a57f0a } + }, + { + { -0x4c918f910383cb7c, 0x73dfc9b4c3c1cf61, -0x14e2863687e3381b, 0x70459adb7daf675c }, + { 0x0e7a4fbd305fa0bb, -0x7d62b31fab399c53, -0x0bde3c7cd01cc7b8, 0x795ac80d1bf64c42 }, + { 0x1b91db4991b42bb3, 0x572696234b02dcca, -0x6020611ae0738724, 0x5fe162848ce21fd3 } + }, +}, +{ + { + { 0x315c29c795115389, -0x281f1af879d08b32, 0x0c4a762185927432, 0x72de6c984a25a1e4 }, + { -0x1d86f551b2f883bf, -0x746c7d8f248b965d, 0x6eb632dc8abd16a2, 0x720814ecaa064b72 }, + { -0x51654aac40955cf0, 0x050a50a9806d6e1b, -0x6d448bfc5200aec7, 0x0394d27645be618b } + }, + { + { -0x0ac69bda4dcaba5c, 0x15a7a27e98fbb296, -0x5493ad439c90227a, 0x79d995a8419334ee }, + { 0x4d572251857eedf4, -0x1c8db1221e616c3b, -0x758ebdf1f4868fcb, 0x3b3c833687abe743 }, + { -0x32757159ee6a228b, -0x5afb2757e22657d1, 0x540dca81a35879b6, 0x60dd16a379c86a8a } + }, + { + { 0x3501d6f8153e47b8, -0x485698abeb5d09f4, 0x112ee8b6455d9523, 0x4e62a3c18112ea8a }, + { 0x35a2c8487381e559, 0x596ffea6d78082cb, -0x34688e14245849ad, 0x5a08b5019b4da685 }, + { -0x372b53fbae95487a, 0x595af3215295b23d, -0x29122dcb24fdcf3f, 0x0929efe8825b41cc } + }, + { + { -0x74ce8d4852a99ae3, 0x01581b7a3fabd717, 0x2dc94df6424df6e4, 0x30376e5d2c29284f }, + { 0x5f0601d1cbd0f2d3, 0x736e412f6132bb7f, -0x7c9fbbcddc722179, 0x1e3a5272f5c0753c }, + { -0x2d6e72587ea65a64, 0x6bdc1cd93f0713f3, 0x565f7a934acd6590, 0x53daacec4cb4c128 } + }, + { + { -0x667ad43c7ad30250, 0x2cc12e9559d6ed0b, 0x70f9e2bf9b5ac27b, 0x4f3b8c117959ae99 }, + { 0x4ca73bd79cc8a7d6, 0x4d4a738f47e9a9b2, -0x0b340ed6bd0a0200, 0x01a13ff9bdbf0752 }, + { 0x55b6c9c82ff26412, 0x1ac4a8c91fb667a8, -0x2ad840301488740e, 0x303337da7012a3be } + }, + { + { -0x6892c334052d022f, -0x34777c68c859bf58, 0x2ff00c1d6734cb25, 0x269ff4dc789c2d2b }, + { -0x6aabdddd73e36284, 0x01fac1371a9b340f, 0x7e8d9177925b48d7, 0x53f8ad5661b3e31b }, + { 0x0c003fbdc08d678d, 0x4d982fa37ead2b17, -0x3f8194324d1a7d0f, 0x296c7291df412a44 } + }, + { + { -0x204dcdfa25474a62, 0x465aeaa0c8092250, -0x2ecc3ee7658da2e8, 0x2327370261f117d1 }, + { 0x7903de2b33daf397, -0x2f00f9e63659db4d, -0x75e2dad4aaa4c1e8, 0x2b6d581c52e0b7c0 }, + { 0x3d0543d3623e7986, 0x679414c2c278a354, -0x51bc0f338d9e690a, 0x7836c41f8245eaba } + }, + { + { -0x359ae17b7fee6c84, -0x394f3b91910be5d8, -0x48fde458a0c072ae, 0x119dff99ead7b9fd }, + { -0x185dab24b616a57f, 0x5192d5d008b0ad73, 0x4d20e5b1d00afc07, 0x5d55f8012cf25f38 }, + { 0x43eadfcbf4b31d4d, -0x39afc08beeeb776e, -0x0111973af9f2c4e9, 0x329293b3dd4a0ac8 } + }, +}, +{ + { + { 0x2879852d5d7cb208, -0x4721228f97820d19, -0x23f40054de97876f, 0x2b44c043677daa35 }, + { 0x4e59214fe194961a, 0x49be7dc70d71cd4f, -0x6cff302dc4af0dd3, 0x4789d446fc917232 }, + { 0x1a1c87ab074eb78e, -0x05392e7166250b99, 0x3eacbbcd484f9067, 0x60c52eef2bb9a4e4 } + }, + { + { 0x702bc5c27cae6d11, 0x44c7699b54a48cab, -0x1043bfa945b6d14e, 0x70d77248d9b6676d }, + { 0x0b5d89bc3bfd8bf1, -0x4f946dc8360caae6, 0x0e4c16b0d53028f5, 0x10bc9c312ccfcaab }, + { -0x557517b4c13d5fa5, -0x6796610b12e87e20, 0x794513e4708e85d1, 0x63755bd3a976f413 } + }, + { + { 0x3dc7101897f1acb7, 0x5dda7d5ec165bbd8, 0x508e5b9c0fa1020f, 0x2763751737c52a56 }, + { -0x4aa05fc1d52ef7ad, 0x356f75909ee63569, -0x60060e0241964770, 0x0d8cc1c48bc16f84 }, + { 0x029402d36eb419a9, -0x0f4bb181884b9f5b, -0x30579dcf2bc3b6aa, 0x70c2dd8a7ad166e7 } + }, + { + { -0x6e2b6982471281ed, 0x74252f0ad776817a, -0x1bf67d1ff27ada9c, 0x32b8613816a53ce5 }, + { 0x656194509f6fec0e, -0x11d18156b939ae73, -0x68cc3e0c981f64a4, 0x2e0fac6363948495 }, + { 0x79e7f7bee448cd64, 0x6ac83a67087886d0, -0x07602b265f1b24d2, 0x4179215c735a4f41 } + }, + { + { -0x1b51cc46d79432cc, -0x48108149aa622924, 0x278b141fb3d38e1f, 0x31fa85662241c286 }, + { -0x738f6b18282312d6, -0x6804753cb82c6390, -0x1ec41fcc56f926fe, 0x700344a30cd99d76 }, + { -0x507d93bdd1c9dd0c, -0x3edfd67867ccafd3, -0x643e481ed4c76edd, 0x24bb2312a9952489 } + }, + { + { 0x41f80c2af5f85c6b, 0x687284c304fa6794, -0x76ba20665c45e453, 0x0d1d2af9ffeb5d16 }, + { -0x4e5712e8cd21983d, 0x3cb49418461b4948, -0x7142bcbc8930432e, 0x0fee3e871e188008 }, + { -0x5625755ecd9de121, 0x30b822a159226579, 0x4004197ba79ac193, 0x16acd79718531d76 } + }, + { + { -0x36a6393a87784953, -0x6b1e6152a06f0146, 0x16e24e62a342f504, 0x164ed34b18161700 }, + { 0x72df72af2d9b1d3d, 0x63462a36a432245a, 0x3ecea07916b39637, 0x123e0ef6b9302309 }, + { 0x487ed94c192fe69a, 0x61ae2cea3a911513, -0x7884092c465b21d9, 0x78da0fc61073f3eb } + }, + { + { -0x5d607f0e97f3c56c, 0x71f77e151ae9e7e6, 0x1100f15848017973, 0x054aa4b316b38ddd }, + { 0x5bf15d28e52bc66a, 0x2c47e31870f01a8e, 0x2419afbc06c28bdd, 0x2d25deeb256b173a }, + { -0x2037b972e6d98348, 0x0b28789c66e54daf, 0x2aeb1d2a666eec17, 0x134610a6ab7da760 } + }, +}, +{ + { + { -0x26ebcf1f23fd73c4, 0x0eb955a85217c771, 0x4b09e1ed2c99a1fa, 0x42881af2bd6a743c }, + { -0x350aa13d83a64dc1, -0x665112c1eab2fb0e, 0x68441d72e14141f4, 0x140345133932a0a2 }, + { 0x7bfec69aab5cad3d, -0x3dc1732cb34d3053, 0x685dd14bfb37d6a2, 0x0ad6d64415677a18 } + }, + { + { 0x7914892847927e9f, 0x33dad6ef370aa877, 0x1f8f24fa11122703, 0x5265ac2f2adf9592 }, + { 0x781a439e417becb5, 0x4ac5938cd10e0266, 0x5da385110692ac24, 0x11b065a2ade31233 }, + { 0x405fdd309afcb346, -0x268dc2bbd719c0ac, -0x6b3fe20fa09a5552, 0x43e4dc3ae14c0809 } + }, + { + { -0x1590853c523d395d, -0x2f16d709168e836c, -0x1d2c861529ba150b, 0x46dd8785c51ffbbe }, + { -0x43ed380e56c75ae9, 0x473028ab3180b2e1, 0x3f78571efbcd254a, 0x74e534426ff6f90f }, + { 0x709801be375c8898, 0x4b06dab5e3fd8348, 0x75880ced27230714, 0x2b09468fdd2f4c42 } + }, + { + { 0x5b97946582ffa02a, -0x25f695ae01570ab7, -0x5f9caec8a0885065, 0x1bcfde61201d1e76 }, + { -0x6838b61148fe346a, -0x7c0bc72b495c963d, 0x62962b8b9a402cd9, 0x6976c7509888df7b }, + { 0x4a4a5490246a59a2, -0x29c1422117802270, -0x26bc8398f2dc8e06, 0x69e87308d30f8ed6 } + }, + { + { 0x0f80bf028bc80303, 0x6aae16b37a18cefb, -0x22b815b828d3295d, 0x61943588f4ed39aa }, + { 0x435a8bb15656beb0, -0x07053645b0b2a436, -0x464d873beab73f8b, 0x3eb0ef76e892b622 }, + { -0x2d91a3c16efc607b, -0x3f161882090cc557, -0x176973aa8ff9956d, 0x3c34d1881faaaddd } + }, + { + { -0x42a4f470d0001f27, 0x6aa254103ed24fb9, 0x2ac7d7bcb26821c4, 0x605b394b60dca36a }, + { 0x3f9d2b5ea09f9ec0, 0x1dab3b6fb623a890, -0x5f645c158d26d93c, 0x374193513fd8b36d }, + { -0x4b17a91ba562e12e, -0x1017b7899368565e, -0x4efb309be1a11183, 0x2f50b81c88a71c8f } + }, + { + { 0x2b552ca0a7da522a, 0x3230b336449b0250, -0x0d3b3a435b466047, 0x7b2c674958074a22 }, + { 0x31723c61fc6811bb, -0x634bafb79dee7ff1, 0x768933d347995753, 0x3491a53502752fcd }, + { -0x2aae9a77c12d7321, 0x12d84fd2d362de39, 0x0a874ad3e3378e4f, 0x000d2b1f7c763e74 } + }, + { + { -0x69db8873c16b5755, 0x0ad6f3cee9a78bec, -0x6b75387ef28bc3b1, 0x76627935aaecfccc }, + { 0x3d420811d06d4a67, -0x4103fb7a6f1f001d, -0x078f394842b78422, 0x6e2a7316319afa28 }, + { 0x56a8ac24d6d59a9f, -0x37248ac1cf690ffa, 0x477f41e68f4c5299, 0x588d851cf6c86114 } + }, +}, +{ + { + { -0x32d59a18882e0aeb, 0x548991878faa60f1, -0x4e48c4432543f91b, 0x654878cba97cc9fb }, + { 0x51138ec78df6b0fe, 0x5397da89e575f51b, 0x09207a1d717af1b9, 0x2102fdba2b20d650 }, + { -0x69611bfafaa3195f, 0x36bca7681251ad29, 0x3a1af517aa7da415, 0x0ad725db29ecb2ba } + }, + { + { -0x013843f364fa907b, 0x537d5268e7f5ffd7, 0x77afc6624312aefa, 0x4f675f5302399fd9 }, + { -0x23bd984e7cb1dba9, -0x498abb4a8f31e43b, 0x1af07a0bf7d15ed7, 0x4aefcffb71a03650 }, + { -0x3cd2c9c9fbeae8e2, -0x32d410ee7667b7c5, -0x78f591522f6baef0, 0x0bccbb72a2a86561 } + }, + { + { 0x186d5e4c50fe1296, -0x1fc6847d01176082, 0x3bc7f6c5507031b0, 0x6678fd69108f37c2 }, + { 0x185e962feab1a9c8, -0x791819ca9aeb8233, -0x4f6d1fce44a4920e, 0x4024f0ab59d6b73e }, + { 0x1586fa31636863c2, 0x07f68c48572d33f2, 0x4f73cc9f789eaefc, 0x2d42e2108ead4701 } + }, + { + { 0x21717b0d0f537593, -0x6eb196f4ece1f9b4, 0x1bb687ae752ae09f, 0x420bf3a79b423c6e }, + { -0x680aecea6b202d65, 0x6155985d313f4c6a, -0x145ec0f8f7baaff0, 0x676b2608b8d2d322 }, + { -0x7ec7459ae3a4d4b9, -0x798e4913cee4e480, 0x7bff0cb1bc3135b0, 0x745d2ffa9c0cf1e0 } + }, + { + { 0x6036df5721d34e6a, -0x4e2477d866844c30, -0x2c3df63c378a9506, 0x06e15be54c1dc839 }, + { -0x40ada5e1d4363743, -0x15a4d9f7d9b8627f, -0x2aee38f120feaa25, 0x1ae23ceb960cf5d0 }, + { 0x5b725d871932994a, 0x32351cb5ceb1dab0, 0x7dc41549dab7ca05, 0x58ded861278ec1f7 } + }, + { + { 0x2dfb5ba8b6c2c9a8, 0x48eeef8ef52c598c, 0x33809107f12d1573, 0x08ba696b531d5bd8 }, + { -0x27e8c86c0d993aa4, -0x3736893a33bab1b7, 0x5ce382f8bc26c3a8, 0x2ff39de85485f6f9 }, + { 0x77ed3eeec3efc57a, 0x04e05517d4ff4811, -0x15c285c00e598e35, 0x120633b4947cfe54 } + }, + { + { -0x7d42ceb8b6edeff6, -0x21dc8492819041fa, -0x1ee189e6ee15863a, 0x07433be3cb393bde }, + { 0x0b94987891610042, 0x4ee7b13cecebfae8, 0x70be739594f0a4c0, 0x35d30a99b4d59185 }, + { -0x0086bb3fa316680c, 0x575d3de4b05c51a3, 0x583381fd5a76847c, 0x2d873ede7af6da9f } + }, + { + { -0x559dfd1eb1a2067f, -0x5df2a6e8afea1e0b, 0x18a275d3bae21d6c, 0x0543618a01600253 }, + { 0x157a316443373409, -0x054748110b557e27, -0x4f6c01190a59b7fa, 0x2e773654707fa7b6 }, + { 0x0deabdf4974c23c1, -0x5590f5da6231b96d, 0x04202cb8a29aba2c, 0x4b1443362d07960d } + }, +}, +{ + { + { 0x299b1c3f57c5715e, -0x69346d6194979270, 0x3004806447235ab3, 0x2c435c24a44d9fe1 }, + { 0x47b837f753242cec, 0x256dc48cc04212f2, -0x1ddd04041e26d73b, 0x48ea295bad8a2c07 }, + { 0x0607c97c80f8833f, 0x0e851578ca25ec5b, 0x54f7450b161ebb6f, 0x7bcb4792a0def80e } + }, + { + { 0x1cecd0a0045224c2, 0x757f1b1b69e53952, 0x775b7a925289f681, 0x1b6cc62016736148 }, + { -0x7b781c2fd438c9a7, 0x4baf8445059979df, -0x2e8368a523529041, 0x57369f0bdefc96b6 }, + { -0x0e5666fe8a9c7968, 0x353dd1beeeaa60d3, -0x7b6b8eccb3645b78, 0x63fa6e6843ade311 } + }, + { + { 0x2195becdd24b5eb7, 0x5e41f18cc0cd44f9, -0x20d7f8bbbe356122, 0x07073b98f35b7d67 }, + { -0x2ea3dfac9a683e98, -0x608c8bff672d7877, 0x18aee7f13257ba1f, 0x3418bfda07346f14 }, + { -0x2fc39893b31acf2c, 0x0b64c0473b5df9f4, 0x065cef8b19b3a31e, 0x3084d661533102c9 } + }, + { + { -0x6593178989fcde03, 0x7fe2b5109eb63ad8, 0x00e7d4ae8ac80592, 0x73d86b7abb6f723a }, + { -0x1e094861407b9653, 0x15801004e2663135, -0x65b67ccf508be7e5, 0x3ba2504f049b673c }, + { 0x0b52b5606dba5ab6, -0x56ecb0f0444e1255, 0x30a9520d9b04a635, 0x6813b8f37973e5db } + }, + { + { -0x0e6b35a90cea81d7, 0x136d35705ef528a5, -0x22b3108874fa6644, 0x7d5472af24f833ed }, + { -0x67ab4fabccbed83f, 0x105d047882fbff25, -0x24b60806bbe790b1, 0x1768e838bed0b900 }, + { -0x2f1078b250cc25b9, 0x00d3be5db6e339f9, 0x3f2a8a2f9c9ceece, 0x5d1aeb792352435a } + }, + { + { 0x12c7bfaeb61ba775, -0x47b19de01d9c4003, 0x0b47a5c35c840dcf, 0x7e83be0bccaf8634 }, + { -0x0a61944ce6329c36, 0x670c159221d06839, -0x4f92a9a4deaf354a, 0x20fb199d104f12a3 }, + { 0x61943dee6d99c120, -0x79efe0d1b9f46020, 0x6bb2f1518ee8598d, 0x76b76289fcc475cc } + }, + { + { 0x4245f1a1522ec0b3, 0x558785b22a75656d, 0x1d485a2548a1b3c0, 0x60959eccd58fe09f }, + { 0x791b4cc1756286fa, -0x24312ce828b5ea84, 0x7e732421ea72bde6, 0x01fe18491131c8e9 }, + { 0x3ebfeb7ba8ed7a09, 0x49fdc2bbe502789c, 0x44ebce5d3c119428, 0x35e1eb55be947f4a } + }, + { + { 0x14fd6dfa726ccc74, 0x3b084cfe2f53b965, -0x0cc51b0aad5d374c, 0x59aab07a0d40166a }, + { -0x242518fe3a8c722d, -0x063909ca4d90e412, 0x61e96a8042f15ef4, 0x3aa1d11faf60a4d8 }, + { 0x77bcec4c925eac25, 0x1848718460137738, 0x5b374337fea9f451, 0x1865e78ec8e6aa46 } + }, +}, +{ + { + { -0x6983ab16e3ad6335, 0x30f6269264c635fb, 0x2747aff478121965, 0x17038418eaf66f5c }, + { -0x333b48384991e086, 0x44157e25f50c2f7e, 0x3ef06dfc713eaf1c, 0x582f446752da63f7 }, + { -0x39ce842cdfcdb31c, -0x57efbd175bb7743c, -0x4de10e74b1a5ec9c, 0x0c2a1c4bcda28dc9 } + }, + { + { -0x123b7eb7964296bb, 0x0d6d907dbe1c8d22, -0x39c42ded2aa33a55, 0x5a6a9b30a314dc83 }, + { -0x2db2382f90e0fbb9, -0x4dd961c124783fa7, -0x2ea4fd8d044d2d71, 0x7c558bd1c6f64877 }, + { -0x2f13eadb2c69b9c3, 0x12bb628ac35a24f0, -0x5af3c586e343a05c, 0x0404a5ca0afbafc3 } + }, + { + { 0x62bc9e1b2a416fd1, -0x4a3908d71cafa675, 0x04343fd83d5d6967, 0x39527516e7f8ee98 }, + { -0x73e0bff8f558bc2a, -0x33452f34a4d9a118, 0x574b046b668fd2de, 0x46395bfdcadd9633 }, + { 0x117fdb2d1a5d9a9c, -0x6388ba432effa3d6, -0x102b410eab2a9016, 0x76579a29e822d016 } + }, + { + { 0x333cb51352b434f2, -0x27cdd7b66c217f1f, -0x4aaed7788af2ca32, 0x02c514bb2a2777c1 }, + { 0x45b68e7e49c02a17, 0x23cd51a2bca9a37f, 0x3ed65f11ec224c1b, 0x43a384dc9e05bdb1 }, + { 0x684bd5da8bf1b645, -0x04742c81094ab4ad, 0x313916d7a9b0d253, 0x1160920961548059 } + }, + { + { 0x7a385616369b4dcd, 0x75c02ca7655c3563, 0x7dc21bf9d4f18021, 0x2f637d7491e6e042 }, + { -0x4bb2e996d6253056, -0x25ad60b37beca671, -0x16109c35bac2aaa7, 0x351e125bc5698e0b }, + { -0x2b4b64b9e5098442, -0x29fcfc853754769f, 0x71dee19ff9a699fb, 0x7f182d06e7ce2a9a } + }, + { + { 0x09454b728e217522, -0x55a7170b2b7b4728, -0x2ca7dab280b96fc4, 0x44acc043241c5217 }, + { 0x7a7c8e64ab0168ec, -0x34a5b5aaea123abd, 0x095519d347cd0eda, 0x67d4ac8c343e93b0 }, + { 0x1c7d6bbb4f7a5777, -0x74ca012b6e7cec1f, 0x4adca1c6c96b4684, 0x556d1c8312ad71bd } + }, + { + { -0x7e0f98a94ee417df, 0x0faff82310a3f3dd, -0x074d2faa9566b9a3, 0x097abe38cc8c7f05 }, + { 0x17ef40e30c8d3982, 0x31f7073e15a3fa34, 0x4f21f3cb0773646e, 0x746c6c6d1d824eff }, + { 0x0c49c9877ea52da4, 0x4c4369559bdc1d43, 0x022c3809f7ccebd2, 0x577e14a34bee84bd } + }, + { + { -0x6b01314142b228d5, -0x0b95b025f9f0ddef, 0x124a5977c0c8d1ff, 0x705304b8fb009295 }, + { -0x0f1d97539e58c4f6, -0x0d0505efc86e5a0b, -0x3e1ec17d9492ff17, 0x60fa7ee96fd78f42 }, + { -0x49c2e2cab2d6913a, -0x0c3cfac1a052ce28, 0x670b958cb4bd42ec, 0x21398e0ca16353fd } + }, +}, +{ + { + { -0x793a03e979e48166, -0x095ccfb895d83baf, 0x01667267a1e93597, 0x05ffb9cd6082dfeb }, + { 0x216ab2ca8da7d2ef, 0x366ad9dd99f42827, -0x519b46ffb022c38b, 0x403a395b53909e62 }, + { -0x59e805600ac09ec7, 0x60f2b5e513e66cb6, -0x285741104cbb755c, 0x7a2932856f5ea192 } + }, + { + { -0x4763bbb7869c6cfe, 0x4ae4f19350c67f2c, -0x0f4ca25737e5063a, 0x39d0003546871017 }, + { 0x0b39d761b02de888, 0x5f550e7ed2414e1f, -0x59405ba7dd1e56c0, 0x050a2f7dfd447b99 }, + { 0x437c3b33a650db77, 0x6bafe81dbac52bb2, -0x0166bfd2d2482ce8, 0x2b5b7eec372ba6ce } + }, + { + { -0x596bbfb29ec5370c, 0x500c3c2bfa97e72c, -0x78befb2de0313df0, 0x1b205fb38604a8ee }, + { -0x4c43b4427c0af111, 0x508f0c998c927866, 0x43e76587c8b7e66e, 0x0f7655a3a47f98d9 }, + { 0x55ecad37d24b133c, 0x441e147d6038c90b, 0x656683a1d62c6fee, 0x0157d5dc87e0ecae } + }, + { + { -0x6ad9aaeb28e14adc, -0x19fc277ea20eba6d, 0x147cdf410d4de6b7, 0x5293b1730437c850 }, + { -0x0d5850aefcab3ec3, -0x285f4eba55c8d4a0, 0x2869b96a05a3d470, 0x6528e42d82460173 }, + { 0x23d0e0814bccf226, -0x6d38ba327e69046d, -0x749e8693a6abe1a5, 0x40a44df0c021f978 } + }, + { + { -0x793691aeb43a2f6b, -0x0df2bf6703597fb6, 0x27363d89c826ea5d, 0x39ca36565719cacf }, + { -0x25579676b0df1596, -0x15eb5c2eb39df9e8, 0x6001fccb090bf8be, 0x35f4e822947e9cf0 }, + { -0x68af90d0907848a4, -0x39db515ffcb51f90, 0x1ec856e3aad34dd6, 0x055b0be0e440e58f } + }, + { + { 0x4d12a04b6ea33da2, 0x57cf4c15e36126dd, -0x6f13698a11bb2699, 0x64ca348d2a985aac }, + { 0x6469a17d89735d12, -0x2490d82a199d460f, -0x60345cd795c6a97f, 0x363b8004d269af25 }, + { -0x66a771e61b3b6ed3, -0x1033c4b1e35a3195, 0x4522ea60fa5b98d5, 0x7064bbab1de4a819 } + }, + { + { -0x5d6f3f9ebdabded7, -0x0d1d3d514172a470, -0x30dba724895401e5, 0x02157ade83d626bf }, + { -0x46e61eaea588f9bf, -0x565d1d38b1807fc7, 0x7527250b3df23109, 0x756a7330ac27b78b }, + { 0x3e46972a1b9a038b, 0x2e4ee66a7ee03fb4, -0x7e5db78891244b36, 0x1a944ee88ecd0563 } + }, + { + { -0x44bf57a6e7dc9d2a, -0x4660aa8875b2e545, -0x72e74bd88a7aa60a, 0x26c20fe74d26235a }, + { -0x2a56e2eeaefc6c8e, 0x2ed377b799ca26de, -0x5e8dfd5302c99495, 0x0730291bd6901995 }, + { 0x648d1d9fe9cc22f5, 0x66bc561928dd577c, 0x47d3ed21652439d1, 0x49d271acedaf8b49 } + }, +}, +{ + { + { 0x2798aaf9b4b75601, 0x5eac72135c8dad72, -0x2d31559e9e485fdd, 0x1bbfb284e98f7d4e }, + { -0x760afa75c7d4cc0d, 0x5ae2ba0bad48c0b4, -0x706c4afc5ac24c92, 0x5aa3ed9d95a232e6 }, + { 0x656777e9c7d96561, -0x34d4edab8d387fca, 0x65053299d9506eee, 0x4a07e14e5e8957cc } + }, + { + { 0x240b58cdc477a49b, -0x02c725219bb80fe9, 0x19928d32a7c86aad, 0x50af7aed84afa081 }, + { 0x4ee412cb980df999, -0x5cea2890c391388f, -0x445a12216da38803, 0x3f0bac391d313402 }, + { 0x6e4fde0115f65be5, 0x29982621216109b2, 0x780205810badd6d9, 0x1921a316baebd006 } + }, + { + { -0x28a55265260c3e75, 0x566a0eef60b1c19c, 0x3e9a0bac255c0ed9, 0x7b049deca062c7f5 }, + { -0x76bdd08120478f04, 0x2c296beb4f76b3bd, 0x0738f1d436c24df7, 0x6458df41e273aeb0 }, + { -0x23341c85cabbbb7d, 0x758879330fedbe93, 0x786004c312c5dd87, 0x6093dccbc2950e64 } + }, + { + { 0x6bdeeebe6084034b, 0x3199c2b6780fb854, -0x68cc895449d2f96b, 0x6e3180c98b647d90 }, + { 0x1ff39a8585e0706d, 0x36d0a5d8b3e73933, 0x43b9f2e1718f453b, 0x57d1ea084827a97c }, + { -0x118549185ed74f8f, -0x5b3ea6926c577456, -0x084b217d4dde9ed0, 0x363e999ddd97bd18 } + }, + { + { 0x2f1848dce24baec6, 0x769b7255babcaf60, -0x6f34c391c31016cf, 0x231f979bc6f9b355 }, + { -0x6957bc3eca11e03c, -0x68914caaf71b3731, -0x4bd097fe4a732cd0, 0x48ee9b78693a052b }, + { 0x5c31de4bcc2af3c6, -0x4fb44fcf01df72e1, -0x48728ff63eb04b9a, 0x079bfa9b08792413 } + }, + { + { -0x0c36127f5d2abdbb, 0x0aa08b7877f63952, -0x2892539c2ef7ab8b, 0x1ef4fb159470636b }, + { -0x1c6fc5ae25cff20c, -0x7bc69bdcc256a550, -0x12c30ed2f4ca9b80, 0x038c77f684817194 }, + { -0x7ab1a119a4e98414, 0x59590a4296d0cdc2, 0x72b2df3498102199, 0x575ee92a4a0bff56 } + }, + { + { 0x5d46bc450aa4d801, -0x3c50edd85acc4628, 0x389e3b262b8906c2, 0x200a1e7e382f581b }, + { -0x2b3f7f6f75e7d031, 0x30e170c299489dbd, 0x05babd5752f733de, 0x43d4e7112cd3fd00 }, + { 0x518db967eaf93ac5, 0x71bc989b056652c0, -0x01d47a26a98e680b, 0x050eca52651e4e38 } + }, + { + { -0x6853c6899f199716, -0x64e64401eac54b69, 0x4cb179b534eca79f, 0x6151c09fa131ae57 }, + { -0x3cbce521bac0f364, -0x160afba1008fc465, -0x03268536127b84c3, 0x4b0ee6c21c58f4c6 }, + { 0x3af55c0dfdf05d96, -0x22d9d11fd54b1186, 0x11b2bb8712171709, 0x1fef24fa800f030b } + }, +}, +{ + { + { -0x006e59956fe99de0, -0x0ddaad51a40e1ff7, 0x7dff85d87f90df7c, 0x4f620ffe0c736fb9 }, + { -0x4b69edc5949399f7, -0x58af017a7f54a6c8, -0x0b8e40c6483d85a1, 0x507903ce77ac193c }, + { 0x62f90d65dfde3e34, -0x30d73a6d4605a053, -0x6637910639e9baf0, 0x25d448044a256c84 } + }, + { + { 0x2c7c4415c9022b55, 0x56a0d241812eb1fe, -0x0fd15e362849a1f3, 0x4180512fd5323b26 }, + { -0x4297dcf138164e91, 0x0eb1b9c1c1c5795d, 0x7943c8c495b6b1ff, 0x2f9faf620bbacf5e }, + { -0x5b00c19675b75a25, -0x4595c7f9426abfc5, -0x60831e50b82a49a3, 0x15e087e55939d2fb } + }, + { + { -0x776be7910469c0c8, 0x48a00e80dc639bd5, -0x5b17f6d41693e367, 0x5a097d54ca573661 }, + { 0x12207543745c1496, -0x2500c30225c79ef4, -0x1b1868d8d38e3cb1, 0x39c07b1934bdede9 }, + { 0x2d45892b17c9e755, -0x2fcc028d76cf7208, 0x6c2fe9d9525b8bd9, 0x2edbecf1c11cc079 } + }, + { + { -0x11f0f0222f785da1, -0x638aceaaa3c1cb12, 0x660c572e8fab3ab5, 0x0854fc44544cd3b2 }, + { 0x1616a4e3c715a0d2, 0x53623cb0f8341d4d, -0x6910acd638176635, 0x3d4e8dbba668baa6 }, + { 0x61eba0c555edad19, 0x24b533fef0a83de6, 0x3b77042883baa5f8, 0x678f82b898a47e8d } + }, + { + { 0x1e09d94057775696, -0x112ed9a3c326ae25, -0x056253d4df431e91, 0x0f7f76e0e8d089f4 }, + { -0x4eb6e2f4296ff3ac, 0x3539722c9d132636, 0x4db928920b362bc9, 0x4d7cd1fea68b69df }, + { 0x36d9ebc5d485b00c, -0x5da69b6d1b524c9b, -0x3e9a6b7f3dee6333, 0x45306349186e0d5f } + }, + { + { -0x695beb13d4f8db6f, 0x1bb2218127a7b65b, 0x6d2849596e8a4af0, 0x65f3b08ccd27765f }, + { -0x6b222f3e593200e3, 0x55f6f115e84213ae, 0x6c935f85992fcf6a, 0x067ee0f54a37f16f }, + { -0x134d6000e667fe09, -0x62c9e2e05d5f08d1, 0x25f11d2375fd2f49, 0x124cefe80fe10fe2 } + }, + { + { 0x1518e85b31b16489, -0x70552348248ef405, 0x39b0bdf4a14ae239, 0x05f4cbea503d20c1 }, + { 0x4c126cf9d18df255, -0x3e2b8e16eb859c4a, 0x2c6d3c73f3c93b5f, 0x6be3a6a2e3ff86a2 }, + { -0x31fbf1613fbeba44, -0x38e00b1df7097cb4, -0x42ab91725477b85d, 0x64666aa0a4d2aba5 } + }, + { + { -0x4f3ac408ccc816b4, 0x7cb5697e11e14f15, 0x4b84abac1930c750, 0x28dd4abfe0640468 }, + { 0x6841435a7c06d912, -0x35edc3de44c07cf5, -0x2b4c84d84e341d88, 0x1d753b84c76f5046 }, + { 0x7dc0b64c44cb9f44, 0x18a3e1ace3925dbf, 0x7a3034862d0457c4, 0x4c498bf78a0c892e } + }, +}, +{ + { + { 0x22d2aff530976b86, -0x726f47f93d2db9fc, -0x235e7693b21a451b, 0x28005fe6c8340c17 }, + { 0x37d653fb1aa73196, 0x0f9495303fd76418, -0x52dff4f604c5e84e, 0x544d49292fc8613e }, + { 0x6aefba9f34528688, 0x5c1bff9425107da1, -0x08a444329926b4ca, 0x72e472930f316dfa } + }, + { + { 0x07f3f635d32a7627, 0x7aaa4d865f6566f0, 0x3c85e79728d04450, 0x1fee7f000fe06438 }, + { 0x2695208c9781084f, -0x4eafd5f4dcbaf11f, -0x02625159fc1021fe, 0x5a9d2e8c2733a34c }, + { 0x765305da03dbf7e5, -0x5b250db6ebcb3243, 0x7b4ad5cdd24a88ec, 0x00f94051ee040543 } + }, + { + { -0x28106c44f85068ad, 0x583ed0cf3db766a7, -0x3196674091f4e13b, 0x47b7ffd25dd40452 }, + { -0x72ca94dc3c2ccf4e, -0x0de374644fb8e4fa, -0x4c93ce9391bd47c4, 0x07d79c7e8beab10d }, + { -0x7804046343f722ee, -0x75f994c51e113d65, 0x0d57242bdb1fc1bf, 0x1c3520a35ea64bb6 } + }, + { + { -0x325790bfde943fa7, 0x1fbb231d12bcd87e, -0x4b6a9561e838f670, 0x38750c3b66d12e55 }, + { -0x7f2dac5943345cb6, 0x3e61c3a13838219b, -0x6f3c49fe677d1c6a, 0x1c3d05775d0ee66f }, + { 0x692ef1409422e51a, -0x343f38c3d4a2098f, 0x21014fe7744ce029, 0x0621e2c7d330487c } + }, + { + { -0x4851e8694f240f0d, 0x54dfafb9e17ce196, 0x25923071e9aaa3b4, 0x5d8e589ca1002e9d }, + { -0x50679f337da67c73, -0x6f15b73e39606524, 0x6526483765581e30, 0x0007d6097bd3a5bc }, + { -0x3f40e26af7bd56b5, -0x4d2c3c9ca770d1c2, 0x0a961438bb51e2ef, 0x1583d7783c1cbf86 } + }, + { + { -0x6ffcb8fb3362d739, 0x1d1b679ef72cc58f, 0x16e12b5fbe5b8726, 0x4958064e83c5580a }, + { -0x13115d10a25d851f, 0x597c3a1455670174, -0x3659d5ed99f6e986, 0x252a5f2e81ed8f70 }, + { 0x0d2894265066e80d, -0x033c087acf837395, 0x1b53da780c1112fd, 0x079c170bd843b388 } + }, + { + { -0x322932af3f2a2faa, -0x6508979244fca8c5, 0x3ca6723ff3c3ef48, 0x6768c0d7317b8acc }, + { 0x0506ece464fa6fff, -0x411cbce19dfa1add, 0x3579422451b8ea42, 0x6dec05e34ac9fb00 }, + { -0x6b49da1a0eaa3e4d, 0x417bf3a7997b7b91, -0x3dd342239294da00, 0x51445e14ddcd52f4 } + }, + { + { -0x76ceb854d4415bab, -0x73ac5db06df86ed7, 0x4b49f948be30f7a7, 0x12e990086e4fd43d }, + { 0x57502b4b3b144951, -0x71980094bbb4434d, -0x474296d8e99c7a25, 0x13186f31e39295c8 }, + { -0x0ef3694c802044d2, -0x60656ca1ede31507, -0x20eec93bc5a467c1, 0x77b2e3f05d3e99af } + }, +}, +{ + { + { -0x6acd0b7033a32d65, 0x2ba851bea3ce3671, 0x32dacaa051122941, 0x478d99d9350004f2 }, + { -0x02f28a78630ed9a9, -0x17d0106b1ac5f1d7, -0x33cb580fa444b419, 0x0b251172a50c38a2 }, + { 0x1d5ad94890bb02c0, 0x50e208b10ec25115, -0x5d95dd76b10de8fe, 0x4dc923343b524805 } + }, + { + { 0x3ad3e3ebf36c4975, -0x28a2da5ac879dedb, -0x178c6bc25fda5aea, 0x6bbc7cb4c411c847 }, + { -0x1c7d73bff07f794a, 0x3f77e6f7979f0dc8, 0x7ef6de304df42cb4, 0x5265797cb6abd784 }, + { 0x3c6f9cd1d4a50d56, -0x49dbbf8839015482, 0x6ff9bf483580972e, 0x00375883b332acfb } + }, + { + { -0x3674137a938a3664, -0x1bbe7b3fff1cc30c, 0x0a676b9bba907634, 0x669e2cb571f379d7 }, + { 0x0001b2cd28cb0940, 0x63fb51a06f1c24c9, -0x4a52796e232a35cf, 0x67238dbd8c450660 }, + { -0x34ee948c5b642cf8, 0x025aad6b2392729e, -0x4b86c105c0aa264f, 0x72a1056140678bb9 } + }, + { + { 0x0d8d2909e2e505b6, -0x673587543fd6edd0, 0x77ef5569a9b12327, 0x7c77897b81439b47 }, + { -0x5d497ed4e336db63, 0x62866eee21211f58, 0x2cb5c5b85df10ece, 0x03a6b259e263ae00 }, + { -0x0e3e4a1d21cce34b, 0x5a9f5d8e15fca420, -0x605bc70e8426cd4f, 0x2a381bf01c6146e7 } + }, + { + { -0x083f41cd4acbe991, 0x27e6ca6419cf70d4, -0x6cb2082856a858a7, 0x5701461dabdec2aa }, + { -0x536467863037ee3f, -0x7482d67ec8a91a99, 0x50da4e607c70edfc, 0x5dbca62f884400b6 }, + { 0x2c6747402c915c25, 0x1bdcd1a80b0d340a, 0x5e5601bd07b43f5f, 0x2555b4e05539a242 } + }, + { + { 0x78409b1d87e463d4, -0x52b256a532049c63, -0x13d788c8aada6464, 0x69c806e9c31230ab }, + { 0x6fc09f5266ddd216, -0x231a9f58371c8fb8, -0x139a6c625d209d03, 0x7a869ae7e52ed192 }, + { 0x7b48f57414bb3f22, 0x68c7cee4aedccc88, -0x12d06c9e86127f42, 0x25d70b885f77bc4b } + }, + { + { -0x67ba62d644e51b2c, 0x56b9c4c739f954ec, -0x7cd8bc093d64b4c2, 0x21ea8e2798b6878a }, + { 0x4151c3d9762bf4de, 0x083f435f2745d82b, 0x29775a2e0d23ddd5, 0x138e3a6269a5db24 }, + { -0x78410b4b95a58464, -0x2dd662e4a03e2f9e, -0x7dbf67e722cde9b8, 0x5c5abeb1e5a2e03d } + }, + { + { 0x02cde6de1306a233, 0x7b5a52a2116f8ec7, -0x1e397e0b3ee9c4a5, 0x241d350660d32643 }, + { 0x14722af4b73c2ddb, -0x43b8f3a0a5faf9f3, 0x00943eac2581b02e, 0x0e434b3b1f499c8f }, + { 0x6be4404d0ebc52c7, -0x51b9dcc44e586e0b, 0x2aec170ed25db42b, 0x1d8dfd966645d694 } + }, +}, +{ + { + { -0x2a679c63ed224f5c, -0x5a2e60cf3fdb7995, -0x2e83d0fca7031ba0, 0x07a195152e095e8a }, + { 0x296fa9c59c2ec4de, -0x43749e40b07b0c35, 0x1c7706d917a8f908, 0x63b795fc7ad3255d }, + { -0x57c970fdc761a038, -0x6fbcc4fd30721bc5, -0x505e02a23abed9bd, 0x3e8fe83d032f0137 } + }, + { + { 0x08704c8de8efd13c, -0x203ae571cc1fc8cf, -0x5a62a25aed9f321d, 0x22d60899a6258c86 }, + { 0x2f8b15b90570a294, -0x6b0dbd8f98f7bab7, -0x21e3a51e9e44027c, 0x75ba3b797fac4007 }, + { 0x6239dbc070cdd196, 0x60fe8a8b6c7d8a9a, -0x4c77b84314bfeda0, 0x0904d07b87779e5e } + }, + { + { -0x0bcdd299b706bf47, 0x06952f0cbd2d0c39, 0x167697ada081f931, 0x6240aacebaf72a6c }, + { -0x4b31e02b22456e64, -0x30ce24c138b37256, 0x2c63cc63ad86cc51, 0x43e2143fbc1dde07 }, + { -0x07cb8b63a45d6a60, -0x296b83a435c82da6, 0x66f13ba7e7c9316a, 0x56bdaf238db40cac } + }, + { + { 0x1310d36cc19d3bb2, 0x062a6bb7622386b9, 0x7c9b8591d7a14f5c, 0x03aa31507e1e5754 }, + { 0x362ab9e3f53533eb, 0x338568d56eb93d40, -0x61f1ebade2a5aa8e, 0x1d24a86d83741318 }, + { -0x0b1389b7002b31e1, -0x1fba150fab5373e4, -0x772dda7de2f6ca84, 0x43b261dc9aeb4859 } + }, + { + { 0x19513d8b6c951364, -0x6b018ed9fff40b85, 0x028d10ddd54f9567, 0x02b4d5e242940964 }, + { -0x1aa4e1e677448645, -0x5f612f823e85ca63, -0x4fd3d11d9fc215cd, 0x326055cf5b276bc2 }, + { -0x4b5eaa34d72e720e, -0x1533b9b9e7931af8, -0x3b630b6c937dbc77, 0x27a6c809ae5d3410 } + }, + { + { -0x32d3d8f53bc296ac, -0x22b5c1a89599354e, 0x79fa592469d7036c, 0x221503603d8c2599 }, + { -0x74591432e0f24e78, 0x37d3d73a675a5be8, -0x0dd1205cea0aa7a6, 0x2cb67174ff60a17e }, + { 0x59eecdf9390be1d0, -0x56bddfbb8d731c0f, -0x7d76e399856b0f0c, 0x7b1df4b73890f436 } + }, + { + { 0x5f2e221807f8f58c, -0x1caaa3602b6bf62c, -0x4d555772e04959d0, 0x68698245d352e03d }, + { -0x1b6d0d1f4c4d5ddc, 0x7c6c9e062b551160, 0x15eb8fe20d7f7b0e, 0x61fcef2658fc5992 }, + { -0x244ea27ad5e7e786, -0x0c1b552c79225329, 0x44bae2810ff6c482, 0x46cf4c473daf01cf } + }, + { + { 0x213c6ea7f1498140, 0x7c1e7ef8392b4854, 0x2488c38c5629ceba, 0x1065aae50d8cc5bb }, + { 0x426525ed9ec4e5f9, 0x0e5eda0116903303, 0x72b1a7f2cbe5cadc, 0x29387bcd14eb5f40 }, + { 0x1c2c4525df200d57, 0x5c3b2dd6bfca674a, 0x0a07e7b1e1834030, 0x69a198e64f1ce716 } + }, +}, +{ + { + { 0x7b26e56b9e2d4734, -0x3b38ecd47e39e98b, -0x10a36ada13632181, 0x39c80b16e71743ad }, + { 0x7afcd613efa9d697, 0x0cc45aa41c067959, -0x5a901efb3e05256a, 0x3a73b70472e40365 }, + { 0x0f196e0d1b826c68, -0x08e00f1db69f1c25, 0x6113167023b7436c, 0x0cf0ea5877da7282 } + }, + { + { -0x1ccd312bc4596ba6, -0x21f4ec9e177e3fa3, 0x1ad40f095e67ed3b, 0x5da8acdab8c63d5d }, + { 0x196c80a4ddd4ccbd, 0x22e6f55d95f2dd9d, -0x38a1cc38bf2938e5, 0x7bb51279cb3c042f }, + { -0x3b4999b5c58fea61, 0x76194f0f0a904e14, -0x5a9eb3c65bf693ed, 0x6cd0ff50979feced } + }, + { + { 0x7fecfabdb04ba18e, -0x2f038403c4224309, -0x5be2b791fa85ece4, 0x641a4391f2223a61 }, + { -0x3f1f981870bbd754, 0x14835ab0a61135e3, -0x0de2eb0cc7f9d6cb, 0x6390a4c8df04849c }, + { -0x3a3946a559f95725, -0x6eb480614f97da0f, 0x2a731f6b44fc9eff, 0x30ddf38562705cfc } + }, + { + { 0x33bef2bd68bcd52c, -0x39b6244f96b7d10e, -0x4a4911f3be34e512, 0x5c294d270212a7e5 }, + { 0x4e3dcbdad1bff7f9, -0x36ee717ddf9ba8e9, -0x45333143f0e762aa, 0x1b4822e9d4467668 }, + { -0x54c9f580daa9c87f, 0x2512228a480f7958, -0x38a2fad89eeb4b1d, 0x222d9625d976fe2a } + }, + { + { 0x0f94be7e0a344f85, -0x14d05573780dd3c8, -0x631e18a1b11e90f1, 0x43e64e5418a08dea }, + { 0x1c717f85b372ace1, -0x7e6cf196b9c740e8, 0x239cad056bc08b58, 0x0b34271c87f8fff4 }, + { -0x7eaa1dade5ca319d, -0x41eff2b206edfd72, -0x4007f4075a822314, 0x57342dc96d6bc6e4 } + }, + { + { -0x0c3c4348e18f840a, 0x351d9b8c7291a762, 0x00502e6edad69a33, 0x522f521f1ec8807f }, + { -0x10110f9a3731a668, -0x40fd6aef4a34155e, -0x739b5ef9df483ba8, 0x35134fb231c24855 }, + { 0x272c1f46f9a3902b, -0x36e45c48669a8434, -0x519eb4cfb075e3f2, 0x7afcaad70b99017b } + }, + { + { -0x577ebe13107bd495, 0x55e7b14797abe6c5, -0x738b7068fc87b002, 0x5b50a1f7afcd00b7 }, + { -0x3da212ab5b4741bf, -0x6fd2ec1ee44f1d23, 0x41f43233cde82ab2, 0x1085faa5c3aae7cb }, + { -0x647bf0990ec9eceb, 0x18462242701003e9, 0x65ed45fae4a25080, 0x0a2862393fda7320 } + }, + { + { -0x69f18c84913462e9, -0x050db6b72983151f, 0x37e7a9b4d55e1b89, 0x5cb7173cb46c59eb }, + { 0x46ab13c8347cbc9d, 0x3849e8d499c12383, 0x4cea314087d64ac9, 0x1f354134b1a29ee7 }, + { 0x4a89e68b82b7abf0, -0x0be326d864594847, 0x16e6c210e18d876f, 0x7cacdb0f7f1b09c6 } + }, +}, +{ + { + { -0x1efebbcb233a3513, 0x47ed5d963c84fb33, 0x70019576ed86a0e7, 0x25b2697bd267f9e4 }, + { -0x6f9d4d1f26e58744, 0x47c9889cc8509667, -0x620ab599bfaf8f48, 0x7369e6a92493a1bf }, + { -0x6298c004ec67979c, 0x3ca5fbd9415dc7b8, -0x1fb133c420d8c4a2, 0x1420683db54e4cd2 } + }, + { + { 0x34eebb6fc1cc5ad0, 0x6a1b0ce99646ac8b, -0x2c4f25b6599421ad, 0x31e83b4161d081c1 }, + { -0x4b8742e1db622e69, 0x620c35005e58c102, -0x04fd2cd0334553a4, 0x60b63bebf508a72d }, + { -0x681738ed61f9d4b1, 0x49e48f4f29320ad8, 0x5bece14b6f18683f, 0x55cf1eb62d550317 } + }, + { + { 0x3076b5e37df58c52, -0x28c54622186633ca, -0x427ce31cb6ec11e0, 0x1a56fbaa62ba0133 }, + { 0x5879101065c23d58, -0x7462f792af6b7e64, -0x1dbfd056ed3aa059, 0x669a6564570891d4 }, + { -0x6bc194afa3623614, 0x302557bba77c371a, -0x678c51a9becb89af, 0x13c4836799c58a5c } + }, + { + { -0x3b230495a2742f80, -0x21143b13a8e5b7be, -0x2b4d177c471aac9b, 0x50bdc87dc8e5b827 }, + { 0x423a5d465ab3e1b9, -0x03ec3e78380ec09f, 0x19f83664ecb5b9b6, 0x66f80c93a637b607 }, + { 0x606d37836edfe111, 0x32353e15f011abd9, 0x64b03ac325b73b96, 0x1dd56444725fd5ae } + }, + { + { -0x3d6819fff7453766, 0x7d4cea11eae1c3e0, -0x0c1c741e60186884, 0x3a3a450f63a305cd }, + { -0x705b8007cc9ded83, -0x4360953b8e3283eb, 0x6e71454349220c8b, 0x0e645912219f732e }, + { 0x078f2f31d8394627, 0x389d3183de94a510, -0x2e1c9392e8669080, 0x318c8d9393a9a87b } + }, + { + { 0x5d669e29ab1dd398, -0x036de9a7cbd261c5, 0x55851dfdf35973cd, 0x509a41c325950af6 }, + { -0x0d8ba2fcd50001e7, 0x0c9f3c497f24db66, -0x43672c1c457a6711, 0x224c7c679a1d5314 }, + { -0x423f91235906da17, 0x793ef3f4641b1f33, -0x7d13ed7f627cc177, 0x05bff02328a11389 } + }, + { + { 0x6881a0dd0dc512e4, 0x4fe70dc844a5fafe, 0x1f748e6b8f4a5240, 0x576277cdee01a3ea }, + { 0x3632137023cae00b, 0x544acf0ad1accf59, -0x698befb62de5e378, 0x780b8cc3fa2a44a7 }, + { 0x1ef38abc234f305f, -0x65a88042ebfa21f8, 0x5e82a51434e62a0d, 0x5ff418726271b7a1 } + }, + { + { -0x1a24b817ec496ac0, -0x0ca2d5c4bcd9ef1f, -0x53e0d916c787ed8a, 0x29d4db8ca0a0cb69 }, + { 0x398e080c1789db9d, -0x589fdfda0c18870b, -0x056776b3f942fca3, 0x106a03dc25a966be }, + { -0x2652f550ccccac30, 0x38669da5acd309e5, 0x3c57658ac888f7f0, 0x4ab38a51052cbefa } + }, +}, +{ + { + { -0x09701d177f621fac, -0x1c43f695637d452f, 0x076353d40aadbf45, 0x7b9b1fb5dea1959e }, + { -0x20253411bcdb3f17, 0x054442883f955bb7, -0x2108555715ce9f61, 0x68aee70642287cff }, + { -0x0fe3370e8b8e33f4, -0x6adbd1c8a86f7d45, 0x27776093d3e46b5f, 0x2d13d55a28bd85fb } + }, + { + { -0x40fe6331851185ae, -0x57212d491bab152d, 0x3c619f0b87a8bb19, 0x3619b5d7560916d8 }, + { -0x053a2df9a4ca4726, -0x572575657a9db449, -0x332d356ec2de32f1, 0x6b8341ee8bf90d58 }, + { 0x3579f26b0282c4b2, 0x64d592f24fafefae, -0x48321284d7373840, 0x6a927b6b7173a8d7 } + }, + { + { -0x728fbf79c1317715, -0x0f1cf8567f113f74, -0x53ddaf9ef2877026, 0x056d92a43a0d478d }, + { 0x1f6db24f986e4656, 0x1021c02ed1e9105b, -0x0700c000d33f5c8b, 0x1d2a6bf8c6c82592 }, + { 0x1b05a196fc3da5a1, 0x77d7a8c243b59ed0, 0x06da3d6297d17918, 0x66fbb494f12353f7 } + }, + { + { -0x2928f6690edcf62a, -0x2404dc7a163c2ac7, 0x46d602b0f7552411, 0x270a0b0557843e0c }, + { 0x751a50b9d85c0fb8, -0x2e5023da7430f685, 0x2f16a6a38309a969, 0x14ddff9ee5b00659 }, + { 0x61ff0640a7862bcc, -0x7e353f65a0ee5402, -0x6fb87cfbaa2ed545, 0x19a4bde1945ae873 } + }, + { + { 0x40c709dec076c49f, 0x657bfaf27f3e53f6, 0x40662331eca042c4, 0x14b375487eb4df04 }, + { -0x6460d90adf59dff6, 0x64804443cf13eaf8, -0x759c98c079ce122d, 0x72bbbce11ed39dc1 }, + { -0x517ac36b549923b9, -0x149dcbc12089d292, -0x0f71f1e7904d082f, 0x4f0b1c02700ab37a } + }, + { + { 0x79fd21ccc1b2e23f, 0x4ae7c281453df52a, -0x37e8d1362eaeb795, 0x68abe9443e0a7534 }, + { -0x1e8f987827e6ae06, -0x5ef5d3714d6f3885, -0x18c7d05fc129988d, 0x0a4d84710bcc4b54 }, + { -0x25ed393bf87ce235, 0x0da230d74d5c510d, 0x4ab1531e6bd404e1, 0x4106b166bcf440ef } + }, + { + { -0x5b7a332ac61b130e, 0x5aa3f3ad0555bab5, 0x145e3439937df82d, 0x1238b51e1214283f }, + { 0x02e57a421cd23668, 0x4ad9fb5d0eaef6fd, -0x6ab198d84edbbb80, 0x7f792f9d2699f331 }, + { 0x0b886b925fd4d924, 0x60906f7a3626a80d, -0x132c984b467542ee, 0x2876beb1def344cf } + }, + { + { -0x2a6b4cccc5757a08, 0x4ea37689e78d7d58, 0x73bf9f455e8e351f, 0x5507d7d2bc41ebb4 }, + { -0x237b16ca9cebb96f, 0x632fe8a0d61f23f4, 0x4caa800612a9a8d5, 0x48f9dbfa0e9918d3 }, + { 0x1ceb2903299572fc, 0x7c8ccaa29502d0ee, -0x6e405bcbee331985, 0x5784481964a831e7 } + }, +}, +{ + { + { -0x29302e10a0223f64, -0x17d4c10208a8a232, 0x25d56b5d201634c2, 0x3041c6bb04ed2b9b }, + { -0x2583d4da98972a6d, -0x673e3fa8bbdd35ed, -0x0e57f42a35f531e3, 0x29cdd1adc088a690 }, + { 0x0ff2f2f9d956e148, -0x5218688a60ca94d2, 0x1a4698bb5f6c025c, 0x104bbd6814049a7b } + }, + { + { -0x56a265a029800e9d, -0x16d41962b338a97f, -0x4807fdb321df0da9, 0x204f2a20fb072df5 }, + { 0x51f0fd3168f1ed67, 0x2c811dcdd86f3bc2, 0x44dc5c4304d2f2de, 0x5be8cc57092a7149 }, + { -0x37ebc4c2cf144f87, 0x7589155abd652e30, 0x653c3c318f6d5c31, 0x2570fb17c279161f } + }, + { + { 0x192ea9550bb8245a, -0x37190457706faf2f, 0x7986ea2d88a4c935, 0x241c5f91de018668 }, + { 0x3efa367f2cb61575, -0x0a069089e329fd94, -0x1738ebd59a4ada9e, 0x3dcb65ea53030acd }, + { 0x28d8172940de6caa, -0x7040d30fdd268cc6, 0x16d7fcdd235b01d1, 0x08420edd5fcdf0e5 } + }, + { + { 0x0358c34e04f410ce, -0x49eca4a5d891f97b, 0x5d9670c7ebb91521, 0x04d654f321db889c }, + { -0x3200df547c9d05b6, 0x57e118d4e21a3e6e, -0x1ce869e803c619d5, 0x0d9a53efbc1769fd }, + { 0x5e7dc116ddbdb5d5, 0x2954deb68da5dd2d, 0x1cb608173334a292, 0x4a7a4f2618991ad7 } + }, + { + { 0x24c3b291af372a4b, -0x6c257d8f8e7eb80e, -0x227b7a9b7976610e, 0x4a96314223e0ee33 }, + { -0x0b58e7fda04ea06b, 0x3df65f346b5c1b8f, -0x32030f7aff1feeee, 0x11b50c4cddd31848 }, + { -0x5917d8bbf75b002a, 0x738e177e9c1576d9, 0x773348b63d02b3f2, 0x4f4bce4dce6bcc51 } + }, + { + { 0x30e2616ec49d0b6f, -0x1ba98e703513dce9, 0x48eb409bf26b4fa6, 0x3042cee561595f37 }, + { -0x58e031a51ddbda7c, 0x26ea725692f58a9e, -0x2de5f628e315c30c, 0x73fcdd14b71c01e6 }, + { 0x427e7079449bac41, -0x7aa51c92431dcef6, 0x4cae76215f841a7c, 0x389e740c9a9ce1d6 } + }, + { + { -0x36428709a8f153d8, -0x1aa4f4cdd86e631f, 0x65fc3eaba19b91ed, 0x25c425e5d6263690 }, + { 0x64fcb3ae34dcb9ce, -0x68affcdc1cb72f53, 0x45b3f07d62c6381b, 0x61545379465a6788 }, + { 0x3f3e06a6f1d7de6e, 0x3ef976278e062308, -0x73eb09d9b1759389, 0x6539a08915484759 } + }, + { + { -0x223b242beb44b5e7, 0x19b2bc3c98424f8e, 0x48a89fd736ca7169, 0x0f65320ef019bd90 }, + { -0x162de08b3c2d088d, -0x3eafabbeda3b97bb, 0x624e5ce8f9b99e33, 0x11c5e4aac5cd186c }, + { -0x2b792e4e35021f3a, 0x4f3fe6e3163b5181, 0x59a8af0dfaf2939a, 0x4cabc7bdec33072a } + }, +}, +{ + { + { -0x083f5e63e5ab5fbc, 0x4a1c5e2477bd9fbb, -0x591c35eea50dd68e, 0x1819bb953f2e9e0d }, + { 0x16faa8fb532f7428, -0x242bd15fb95b1d8e, 0x5337653b8b9ea480, 0x4065947223973f03 }, + { 0x498fbb795e042e84, 0x7d0dd89a7698b714, -0x7404f45bd8019d6b, 0x36ba82e721200524 } + }, + { + { -0x372962f5a8d8b12b, 0x45ba803260804b17, -0x20c325efddaa2054, 0x77d221232709b339 }, + { -0x29f13448bdba13bf, -0x02641761cbcb78ea, -0x36dbf5011bdd7b22, 0x4472f648d0531db4 }, + { 0x498a6d7064ad94d8, -0x5a4a37026509dd9d, -0x735712faba3ebe0c, 0x2c63bec3662d358c } + }, + { + { -0x65ae74c57a790741, -0x6118e509344e6910, -0x55f9da195dc7a30e, 0x1deb2176ddd7c8d1 }, + { 0x7fe60d8bea787955, -0x4623ee814a0bfe49, -0x6e383f65e6caa332, 0x22692ef59442bedf }, + { -0x7a9c2e65df993094, 0x401bfd8c4dcc7cd7, -0x2689594132f2709e, 0x67cfd773a278b05e } + }, + { + { 0x2d5fa9855a4e586a, 0x65f8f7a449beab7e, -0x55f8b2220de2cc2d, 0x185cba721bcb9dee }, + { -0x7213ce0510c11b8b, -0x6624007561dd026e, 0x512d11594e26cab1, 0x0cde561eec4310b9 }, + { -0x6c79625c0b1c34bf, -0x40fc6d0abf086882, 0x026204fcd0463b83, 0x3ec91a769eec6eed } + }, + { + { 0x0fad2fb7b0a3402f, 0x46615ecbfb69f4a8, -0x08ba43373a07155a, 0x7a5fa8794a94e896 }, + { 0x1e9df75bf78166ad, 0x4dfda838eb0cd7af, -0x45ffd1273e150678, 0x13fedb3e11f33cfc }, + { 0x52958faa13cd67a1, -0x69a11f7e74244ae9, 0x16e58daa2e8845b3, 0x357d397d5499da8f } + }, + { + { 0x481dacb4194bfbf8, 0x4d77e3f1bae58299, 0x1ef4612e7d1372a0, 0x3a8d867e70ff69e1 }, + { 0x1ebfa05fb0bace6c, -0x36cb9df3e35065e2, -0x3388e33be27d49e6, 0x2d94a16aa5f74fec }, + { 0x6f58cd5d55aff958, -0x45c155a38aa988df, 0x75c123999165227d, 0x69be1343c2f2b35e } + }, + { + { -0x7d44425397b4721d, -0x5d0b382fc035f8e8, 0x337f92fbe096aaa8, 0x200d4d8c63587376 }, + { 0x0e091d5ee197c92a, 0x4f51019f2945119f, 0x143679b9f034e99c, 0x7d88112e4d24c696 }, + { 0x208aed4b4893b32b, 0x3efbf23ebe59b964, -0x289d214f245a1af9, 0x69607bd681bd9d94 } + }, + { + { 0x3b7f3bd49323a902, 0x7c21b5566b2c6e53, -0x1a45700ac587ad59, 0x28bc77a5838ece00 }, + { -0x0941fdef9721e31f, -0x172ae718f12343e1, -0x1c10022fe4aafa5b, 0x35f63353d3ec3fd0 }, + { 0x63ba78a8e25d8036, 0x63651e0094333490, 0x48d82f20288ce532, 0x3a31abfa36b57524 } + }, +}, +{ + { + { -0x3f708770c0872d77, -0x01cf58d35ebfb261, -0x0d887403309a3363, 0x7ee498165acb2021 }, + { 0x239e9624089c0a2e, -0x38b73b3fc501b8c8, 0x17dbed2a764fa12a, 0x639b93f0321c8582 }, + { 0x7bd508e39111a1c3, 0x2b2b90d480907489, -0x182d513d518d02e7, 0x0edf493c85b602a6 } + }, + { + { 0x6767c4d284764113, -0x5f6fbfc0080a07cb, 0x1c8fcffacae6bede, 0x04c00c54d1dfa369 }, + { -0x51337ea7a664a598, -0x15a8b0f014521df2, 0x4fe41d7422b67f07, 0x403b92e3019d4fb4 }, + { 0x4dc22f818b465cf8, 0x71a0f35a1480eff8, -0x51174052fb3829a9, 0x355bb12ab26176f4 } + }, + { + { -0x5cfe2538a5738ce8, -0x126ffc624c3155ef, 0x6f077cbf3bae3f2d, 0x7518eaf8e052ad8e }, + { -0x58e19b338b6c440c, -0x1a427b26135c4f3d, 0x0a6bc50cfa05e785, 0x0f9b8132182ec312 }, + { -0x5b77a63be48093ce, 0x0f2d60bcf4383298, 0x1815a929c9b1d1d9, 0x47c3871bbb1755c4 } + }, + { + { -0x0419a2af37af9950, 0x62ecc4b0b3a299b0, -0x1ac8ab15bbe51720, 0x08fea02ce8d48d5f }, + { 0x5144539771ec4f48, -0x07fa4e823673a292, -0x089d3ee5b83c3995, 0x00b89b85764699dc }, + { -0x7db2228997211530, -0x379bbadfb497a2dd, -0x4aeb3032a276299b, 0x473829a74f75d537 } + }, + { + { 0x23d9533aad3902c9, 0x64c2ddceef03588f, 0x15257390cfe12fb4, 0x6c668b4d44e4d390 }, + { -0x7d2d258ab9863be8, -0x19c428274d9e7210, 0x355eef24ac47eb0a, 0x2078684c4833c6b4 }, + { 0x3b48cf217a78820c, -0x0895f54d7ed8c169, -0x56939a5873711285, 0x7411a6054f8a433f } + }, + { + { 0x579ae53d18b175b4, 0x68713159f392a102, -0x7baa1345e110ca0b, 0x1ec9a872458c398f }, + { 0x4d659d32b99dc86d, 0x044cdc75603af115, -0x4cb38ed3233d1b78, 0x7c136574fb8134ff }, + { -0x47195b2bff5daf65, -0x647e28fdf4377d4c, 0x57e7cc9bf1957561, 0x3add88a5c7cd6460 } + }, + { + { -0x7a3d672ba6c6cfba, -0x7081ca67a009a614, 0x1d2ca22af2f66e3a, 0x61ba1131a406a720 }, + { -0x5476a88f49ca230e, 0x02dfef6cf66c1fbc, -0x7aacfd9741492e79, 0x249929fccc879e74 }, + { -0x5c2f5f0ee96a6fd7, 0x023b6b6cba7ebd89, 0x7bf15a3e26783307, 0x5620310cbbd8ece7 } + }, + { + { 0x6646b5f477e285d6, 0x40e8ff676c8f6193, -0x59138cee544a6b23, 0x7ec846f3658cec4d }, + { 0x528993434934d643, -0x462407f95aeddd0b, -0x709278703c0be3de, 0x37676a2a4d9d9730 }, + { -0x64a170c0e25dd139, 0x130f1d776c01cd13, 0x214c8fcfa2989fb8, 0x6daaf723399b9dd5 } + }, +}, +{ + { + { -0x7e514422d32ecf90, -0x69d1bcda07a5f162, -0x216c6e5535200135, 0x53177fda52c230e6 }, + { 0x591e4a5610628564, 0x2a4bb87ca8b4df34, -0x21d5da8d185c71bd, 0x3cbdabd9fee5046e }, + { -0x584368f9af462187, 0x3d12a7fbc301b59b, 0x02652e68d36ae38c, 0x79d739835a6199dc } + }, + { + { 0x21c9d9920d591737, -0x6415be2d164b932a, -0x1df17bdff2764036, 0x79d99f946eae5ff8 }, + { -0x26cab209bece3e43, 0x758094a186ec5822, 0x4464ee12e459f3c2, 0x6c11fce4cb133282 }, + { -0x0e84b7ca9798cdfb, 0x387deae83caad96c, 0x61b471fd56ffe386, 0x31741195b745a599 } + }, + { + { 0x17f8ba683b02a047, 0x50212096feefb6c8, 0x70139be21556cbe2, 0x203e44a11d98915b }, + { -0x172efe6f4885c9f5, -0x66467cdf666a18fe, -0x42b0200705fdb856, 0x2772e344e0d36a87 }, + { -0x2979c145c8461c61, 0x105bc169723b5a23, 0x104f6459a65c0762, 0x567951295b4d38d4 } + }, + { + { 0x07242eb30d4b497f, 0x1ef96306b9bccc87, 0x37950934d8116f45, 0x05468d6201405b04 }, + { 0x535fd60613037524, -0x1def52094f043d96, -0x5372f564dc166f52, 0x47204d08d72fdbf9 }, + { 0x00f565a9f93267de, -0x313028723f2a7176, -0x5dea1d230ce71d72, 0x4599ee919b633352 } + }, + { + { -0x538b929479e51a87, 0x31ab0650f6aea9dc, 0x241d661140256d4c, 0x2f485e853d21a5de }, + { -0x2c3ddf358f1f1895, -0x4ed415a71560cf6c, 0x294ddec8c3271282, 0x0c3539e1a1d1d028 }, + { 0x329744839c0833f3, 0x6fe6257fd2abc484, 0x5327d1814b358817, 0x65712585893fe9bc } + }, + { + { -0x7e3d60e428f711c1, -0x2234a5fa519bf830, -0x68513e282d5c1459, 0x1590521a91d50831 }, + { -0x63efd048cd59ee9f, -0x1b71ef22cb2adf58, 0x365c63546f9a9176, 0x32f6fe4c046f6006 }, + { 0x40a3a11ec7910acc, -0x6fec20070e92d852, 0x1a9720d8abb195d4, 0x1bb9fe452ea98463 } + }, + { + { -0x30a1936a33c98b84, 0x294201536b0bc30d, 0x453ac67cee797af0, 0x5eae6ab32a8bb3c9 }, + { -0x162e26af4c2ab062, 0x2d5f9cbee00d33c1, 0x51c2c656a04fc6ac, 0x65c091ee3c1cbcc9 }, + { 0x7083661114f118ea, 0x2b37b87b94349cad, 0x7273f51cb4e99f40, 0x78a2a95823d75698 } + }, + { + { -0x4b0dc3bda107cdf9, -0x54076b2c3656cb4b, -0x2f8f73ecc6027809, 0x1876789117166130 }, + { -0x5d4f8d16a373d532, 0x69cffc96651e9c4b, 0x44328ef842e7b42b, 0x5dd996c122aadeb3 }, + { -0x6da4a10f98f3af84, -0x7e6437bd46c3cc41, 0x10792e9a70dd003f, 0x59ad4b7a6e28dc74 } + }, +}, +{ + { + { 0x583b04bfacad8ea2, 0x29b743e8148be884, 0x2b1e583b0810c5db, 0x2b5449e58eb3bbaa }, + { 0x5f3a7562eb3dbe47, -0x0815c7ab71425f48, 0x00c3e53145747299, 0x1304e9e71627d551 }, + { 0x789814d26adc9cfe, 0x3c1bab3f8b48dd0b, -0x25f01e00068639f6, 0x4468de2d7c2dd693 } + }, + { + { 0x4b9ad8c6f86307ce, 0x21113531435d0c28, -0x2b57993a9a8588d4, 0x5da6427e63247352 }, + { 0x51bb355e9419469e, 0x33e6dc4c23ddc754, -0x6c5a4929bb80669e, 0x6cce7c6ffb44bd63 }, + { 0x1a94c688deac22ca, -0x46f991084451e008, -0x775273c772a6a7f1, 0x58f29abfe79f2ca8 } + }, + { + { 0x4b5a64bf710ecdf6, -0x4eb31ac7b9d3d6c4, 0x3643d056d50b3ab9, 0x6af93724185b4870 }, + { -0x16f130547218c198, 0x54036f9f377e76a5, -0x0fb6a4f441fea67e, 0x577629c4a7f41e36 }, + { 0x3220024509c6a888, -0x2d1fc9ecb4aa768d, -0x7c1dc9dcc3ccd761, 0x701f25bb0caec18f } + }, + { + { -0x62e7092683413eed, -0x7bb5f9198b40241c, 0x20f5b522ac4e60d6, 0x720a5bc050955e51 }, + { -0x3c574f071b9e9313, -0x08ff99f161da5783, 0x61e3061ff4bca59c, 0x2e0c92bfbdc40be9 }, + { 0x0c3f09439b805a35, -0x17b174c89dbd5404, 0x691417f35c229346, 0x0e9b9cbb144ef0ec } + }, + { + { -0x7211642aa24e4112, -0x363c54c8f58dc047, 0x44a8f1bf1c68d791, 0x366d44191cfd3cde }, + { -0x04452b7004a8df53, -0x117e6e942406f2f2, -0x2b7ecead9caabc41, 0x221104eb3f337bd8 }, + { -0x61c3e8bc0d4373ec, 0x2eda26fcb5856c3b, -0x3347d0f197580469, 0x4167a4e6bc593244 } + }, + { + { -0x3d41d99a07317012, -0x169800eb177f29d4, -0x0ed19181d0c9b112, 0x34b33370cb7ed2f6 }, + { 0x643b9d2876f62700, 0x5d1d9d400e7668eb, 0x1b4b430321fc0684, 0x7938bb7e2255246a }, + { -0x323a6e11797e2934, -0x31fdef63127a58ad, -0x128b7a3ea77f777d, 0x1176fc6e2dfe65e4 } + }, + { + { -0x246f1d76b688f148, -0x670433d5530bbf5d, 0x21354ffeded7879b, 0x1f6a3e54f26906b6 }, + { -0x4b50932fa4639e65, 0x2ddfc9f4b2a58480, 0x3d4fa502ebe94dc4, 0x08fc3a4c677d5f34 }, + { 0x60a4c199d30734ea, 0x40c085b631165cd6, -0x1dccc1dc08a67d6b, 0x4f2fad0116b900d1 } + }, + { + { -0x69d326e248c449c8, -0x19fa885503ed63f8, 0x6f619b39f3b61689, 0x3451995f2944ee81 }, + { 0x44beb24194ae4e54, 0x5f541c511857ef6c, -0x59e194d2c972fb68, 0x445484a4972ef7ab }, + { -0x6ead032f60158284, 0x4a816c94b0935cf6, 0x258e9aaa47285c40, 0x10b89ca6042893b7 } + }, +}, +{ + { + { -0x29832129862cb560, -0x33f4613f33b24c61, -0x5aca5ba91ca2e6f1, 0x2e05d9eaf61f6fef }, + { -0x64d5bd91c49b9fdb, 0x32127190385ce4cf, -0x5da3003d229215bb, 0x06409010bea8de75 }, + { -0x3bb86fe529e414a7, 0x661f19bce5dc880a, 0x24685482b7ca6827, 0x293c778cefe07f26 } + }, + { + { 0x16c795d6a11ff200, -0x348f2f1d4ea7ea37, -0x760d6cdf64ac6a4b, 0x50b8c2d031e47b4f }, + { -0x797f618ff8f96f6a, -0x5528a4ea1b1afe77, 0x07f35715a21a0147, 0x0487f3f112815d5e }, + { 0x48350c08068a4962, 0x6ffdd05351092c9a, 0x17af4f4aaf6fc8dd, 0x4b0553b53cdba58b } + }, + { + { -0x40fadee4d83ead2c, 0x5ec26849bd1af639, 0x5e0b2caa8e6fab98, 0x054c8bdd50bd0840 }, + { -0x639a0341e4cd0087, -0x148a1560fc4af065, -0x0312d59393f819fa, 0x35106cd551717908 }, + { 0x38a0b12f1dcf073d, 0x4b60a8a3b7f6a276, -0x012a53da2cbfb066, 0x72e82d5e5505c229 } + }, + { + { 0x00d9cdfd69771d02, 0x410276cd6cfbf17e, 0x4c45306c1cb12ec7, 0x2857bf1627500861 }, + { 0x6b0b697ff0d844c8, -0x44ed07a3268634b7, -0x2d5abe393e25f0e1, 0x7b7c242958ce7211 }, + { -0x60de6fc0fefe9762, -0x2886202c4079effb, -0x5edd11a0c214f0e5, 0x510df84b485a00d4 } + }, + { + { 0x24b3c887c70ac15e, -0x4f0c5aa8047e48ce, -0x64d321d01a8733e5, 0x4cf7ed0703b54f8e }, + { -0x5abecc446d885e06, 0x74ec3b6263991237, 0x1a3c54dc35d2f15a, 0x2d347144e482ba3a }, + { 0x6bd47c6598fbee0f, -0x61b8cc1d54aa41d3, 0x1093f624127610c5, 0x4e05e26ad0a1eaa4 } + }, + { + { 0x1833c773e18fe6c0, -0x1c3b8ee52c378d9b, 0x3bfd3c4f0116b283, 0x1955875eb4cd4db8 }, + { -0x2564949db4ace0e0, 0x429a760e77509abb, -0x24160add17dc3480, 0x618f1856880c8f82 }, + { 0x6da6de8f0e399799, 0x7ad61aa440fda178, -0x4cd327efa1ca9c23, 0x15f6beae2ae340ae } + }, + { + { -0x4565f0846dba1deb, -0x0c979ed22673f245, 0x2e84e4cbf220b020, 0x6ba92fe962d90eda }, + { -0x79d434f3ce13c59e, -0x7ef1d4baeec70c3e, 0x788ec4b839dac2a4, 0x28f76867ae2a9281 }, + { 0x3e4df9655884e2aa, -0x429d0424242b9a5b, -0x28a69355f2161adc, 0x6e8042ccb2b1b3d7 } + }, + { + { 0x1530653616521f7e, 0x660d06b896203dba, 0x2d3989bc545f0879, 0x4b5303af78ebd7b0 }, + { -0x0ef2c3d631d73592, -0x452cbabf0349f6c3, -0x18bd91285d15d2c1, 0x08af9d4e4ff298b9 }, + { 0x72f8a6c3bebcbde8, 0x4f0fca4adc3a8e89, 0x6fa9d4e8c7bfdf7a, 0x0dcf2d679b624eb7 } + }, +}, +{ + { + { 0x753941be5a45f06e, -0x2f8351129263a09b, 0x11776b9c72ff51b6, 0x17d2d1d9ef0d4da9 }, + { 0x3d5947499718289c, 0x12ebf8c524533f26, 0x0262bfcb14c3ef15, 0x20b878d577b7518e }, + { 0x27f2af18073f3e6a, -0x02c01ae628adef97, 0x22e3b72c3ca60022, 0x72214f63cc65c6a7 } + }, + { + { 0x1d9db7b9f43b29c9, -0x29fa7db5b0ae708b, -0x0d3f8d42ced0623c, 0x1f24ac855a1545b0 }, + { -0x4b1c80bfacf8596d, -0x5458eb28d0cc986b, -0x29042f588c89ef67, 0x5fdf48c58171cbc9 }, + { 0x24d608328e9505aa, 0x4748c1d10c1420ee, -0x38001ba3f904da5e, 0x00ba739e2ae395e6 } + }, + { + { -0x51bbd90a157744da, 0x360679d984973bfb, 0x5c9f030c26694e50, 0x72297de7d518d226 }, + { 0x592e98de5c8790d6, -0x1a40482cba3d5d21, 0x115a3b60f9b49922, 0x03283a3e67ad78f3 }, + { 0x48241dc7be0cb939, 0x32f19b4d8b633080, -0x2c2036f2fdd76cf8, 0x05e1296846271945 } + }, + { + { -0x52404437dbd3bab0, -0x4337f3132fcf7e27, -0x7bca99590a37206e, 0x78cf25d38258ce4c }, + { -0x457d114cd263b6a6, -0x311037030ed44684, -0x4fd254516c4a2e20, 0x39c00c9c13698d9b }, + { 0x15ae6b8e31489d68, -0x557ae35463d40f79, -0x3658a5680fb105fb, 0x006b52076b3ff832 } + }, + { + { -0x0a3481e94631f7d3, 0x3407f14c417abc29, -0x2b4c9431d40b5855, 0x7de2e9561a9f75ce }, + { 0x29e0cfe19d95781c, -0x497e20e7699cef1e, 0x57df39d370516b39, 0x4d57e3443bc76122 }, + { -0x218f2b0b495aa135, 0x4801527f5d85db99, -0x24363bbf2c11657f, 0x6b2a90af1a6029ed } + }, + { + { 0x77ebf3245bb2d80a, -0x27cfe4b8d046f865, -0x39b8190db3118ccd, 0x465812c8276c2109 }, + { 0x6923f4fc9ae61e97, 0x5735281de03f5fd1, -0x589b51bc19122ed3, 0x5fd8f4e9d12d3e4a }, + { 0x4d43beb22a1062d9, 0x7065fb753831dc16, 0x180d4a7bde2968d7, 0x05b32c2b1cb16790 } + }, + { + { -0x08035bd3852a7e6b, 0x3214286e4333f3cc, -0x493d62f2cbf46863, 0x31771a48567307e1 }, + { -0x373fa1332db25703, -0x5e30e553fa20107d, -0x2441100d8206329f, 0x3b5556a37b471e99 }, + { 0x32b0c524e14dd482, -0x124caeabe5d45b4a, -0x5c2e9fb7d7d4a50d, 0x4fc079d27a7336eb } + }, + { + { -0x23cb74bbf3793af3, 0x1337cbc9cc94e651, 0x6422f74d643e3cb9, 0x241170c2bae3cd08 }, + { 0x51c938b089bf2f7f, 0x2497bd6502dfe9a7, -0x00003f63877f1bad, 0x124567cecaf98e92 }, + { 0x3ff9ab860ac473b4, -0x0f6ee211feec1bcb, 0x4ae75060ebc6c4af, 0x3f8612966c87000d } + }, +}, +{ + { + { 0x529fdffe638c7bf3, -0x20d4619fc774b66b, -0x1fd84cb0e452fdb7, 0x7bc92fc9b9fa74ed }, + { 0x0c9c5303f7957be4, -0x5c3ce5df1f7a3ebb, -0x4f8de28e2f7affb0, 0x0aba390eab0bf2da }, + { -0x606810d17fe52607, -0x7c9682ab865025c6, -0x16f94c0042a694b0, 0x02672b37dd3fb8e0 } + }, + { + { -0x116458d6c673580b, -0x146359da85b7b625, 0x29eb29ce7ec544e1, 0x232ca21ef736e2c8 }, + { 0x48b2ca8b260885e4, -0x5bd794137d4cb3e4, -0x6c81e5d9e80a708c, 0x741d1fcbab2ca2a5 }, + { -0x409ebdc2dac034e9, 0x08803ceafa39eb14, -0x0e79fd2067ae3851, 0x0400f3a049e3414b } + }, + { + { 0x2efba412a06e7b06, 0x146785452c8d2560, -0x2068ec1429856e39, 0x32830ac7157eadf3 }, + { -0x5431fb89459e3aa5, 0x36a3d6d7c4d39716, 0x6eb259d5e8d82d09, 0x0c9176e984d756fb }, + { 0x0e782a7ab73769e8, 0x04a05d7875b18e2c, 0x29525226ebcceae1, 0x0d794f8383eba820 } + }, + { + { 0x7be44ce7a7a2e1ac, 0x411fd93efad1b8b7, 0x1734a1d70d5f7c9b, 0x0d6592233127db16 }, + { -0x00ca0a3461eae90c, -0x117fa4309b7551bb, -0x0f28c3d446c5610d, 0x097b0bf22092a6c2 }, + { -0x3b7454eade5628cd, -0x593d151529e544db, 0x625c6c1cc6cb4305, 0x7fc90fea93eb3a67 } + }, + { + { -0x3ad8214a63834dc3, -0x6aac6e96acd7bfb2, -0x29bc6d7e8330d386, 0x6ce97dabf7d8fa11 }, + { 0x0408f1fe1f5c5926, 0x1a8f2f5e3b258bf4, 0x40a951a2fdc71669, 0x6598ee93c98b577e }, + { 0x25b5a8e50ef7c48f, -0x149fcbee90d31ace, -0x3a18ae8c1ac21ac9, 0x73119fa08c12bb03 } + }, + { + { 0x7845b94d21f4774d, -0x409d0e93876848d9, 0x671857c03c56522b, 0x3cd6a85295621212 }, + { -0x12cfed6bac0e5b35, -0x4319de36370ac879, -0x0534d4ecc7411847, 0x3025798a9ea8428c }, + { 0x3fecde923aeca999, -0x4255a4ff9d173ed1, 0x67b99dfc96988ade, 0x3f52c02852661036 } + }, + { + { -0x6da74066113be93a, -0x5375afe8562d098f, 0x629549ab16dea4ab, 0x05d0e85c99091569 }, + { -0x00155b71d5ecae3a, 0x28624754fa7f53d7, 0x0b5ba9e57582ddf1, 0x60c0104ba696ac59 }, + { 0x051de020de9cbe97, -0x05f803a94af4308c, 0x378cec9f0f11df65, 0x36853c69ab96de4d } + }, + { + { 0x4433c0b0fac5e7be, 0x724bae854c08dcbe, -0x0e0db33bb9687065, 0x4a0aff6d62825fc8 }, + { 0x36d9b8de78f39b2d, 0x7f42ed71a847b9ec, 0x241cd1d679bd3fde, 0x6a704fec92fbce6b }, + { -0x16e804619ef6acff, -0x3efd206bfd5f6d08, -0x40f61d0a0599e6f5, 0x681109bee0dcfe37 } + }, +}, +{ + { + { -0x63e70305c9fb72ed, 0x29159db373899ddd, -0x2360caf4606d2f56, 0x26f57eee878a19d4 }, + { 0x559a0cc9782a0dde, 0x551dcdb2ea718385, 0x7f62865b31ef238c, 0x504aa7767973613d }, + { 0x0cab2cd55687efb1, 0x5180d162247af17b, -0x7a3ea5cbb0a5db99, 0x4041943d9dba3069 } + }, + { + { 0x4b217743a26caadd, 0x47a6b424648ab7ce, -0x34e2b085fc04361d, 0x12d931429800d019 }, + { -0x3c3f1145bc14336a, -0x728b6363d9156351, -0x26056a11e388333a, 0x1420a1d97684340f }, + { 0x00c67799d337594f, 0x5e3c5140b23aa47b, 0x44182854e35ff395, 0x1b4f92314359a012 } + }, + { + { 0x33cf3030a49866b1, 0x251f73d2215f4859, -0x547d55bfae210b0a, 0x5ff191d56f9a23f6 }, + { 0x3e5c109d89150951, 0x39cefa912de9696a, 0x20eae43f975f3020, 0x239b572a7f132dae }, + { -0x7e612bcc53d26f98, 0x2883ab795fc98523, -0x10ba8d7faa6c14c3, 0x020c526a758f36cb } + }, + { + { -0x16ce10a60fbd3377, 0x2c589c9d8e124bb6, -0x52371e755138a669, 0x452cfe0a5602c50c }, + { 0x779834f89ed8dbbc, -0x370d550623835b94, -0x56adb3235c1e4f8c, 0x02aacc4615313877 }, + { -0x795f085f9b878821, -0x443b9bd8f19f8361, -0x54e815da0e04ee37, 0x4cfb7d7b304b877b } + }, + { + { -0x1d79663d687610ee, 0x2b6ecd71df57190d, -0x3cbc37a813368f30, 0x5b1d4cbc434d3ac5 }, + { 0x72b43d6cb89b75fe, 0x54c694d99c6adc80, -0x473c55c8c11cb361, 0x14b4622b39075364 }, + { -0x4904d9ea33f560da, 0x3a4f0e2bb88dcce5, 0x1301498b3369a705, 0x2f98f71258592dd1 } + }, + { + { 0x2e12ae444f54a701, -0x0301c10f56342822, -0x314076f28a7ca220, 0x1d8062e9e7614554 }, + { 0x0c94a74cb50f9e56, 0x5b1ff4a98e8e1320, -0x65d533de7dcff099, 0x3a6ae249d806aaf9 }, + { 0x657ada85a9907c5a, 0x1a0ea8b591b90f62, -0x72f1e20420cb4b17, 0x298b8ce8aef25ff3 } + }, + { + { -0x7c858d15f5de9a22, 0x3fab07b40bcf79f6, 0x521636c77738ae70, 0x6ba6271803a7d7dc }, + { 0x2a927953eff70cb2, 0x4b89c92a79157076, -0x6be7ba85cf583096, 0x34b8a8404d5ce485 }, + { -0x3d91134a7c96cccb, -0x2a57ec209c4a0103, -0x5d6c55655b4dda8d, 0x71d62bdd465e1c6a } + }, + { + { -0x32d24a254e08a10b, -0x28806a30e94f9a0b, 0x14571fea3f49f085, 0x1c333621262b2b3d }, + { 0x6533cc28d378df80, -0x0924bc86f5f05b4c, -0x1c9ba00608fe25a6, 0x74d5f317f3172ba4 }, + { -0x57901aab9826357f, 0x398b7c752b298c37, -0x2592f76d1c539dc5, 0x4aebcc4547e9d98c } + }, +}, +{ + { + { 0x0de9b204a059a445, -0x1ea34b55b4e852f1, -0x1e4413ade0863aa9, 0x2633f1b9d071081b }, + { 0x53175a7205d21a77, -0x4f3fbbdd2c46cb2c, -0x52260db422a21524, 0x074f46e69f10ff8c }, + { -0x3e04be88fe7466f0, -0x5915df2393f01ec0, -0x299e0c18bcab3901, 0x5ecb72e6f1a3407a } + }, + { + { -0x01151ef917179669, -0x679ccc80672f6c7d, -0x6b8fb7f155f91411, 0x038b6898d4c5c2d0 }, + { -0x5aea5ce4dda604b2, 0x0960f3972bcac52f, -0x124ad01372cbab35, 0x382e2720c476c019 }, + { -0x0c6e3ae27531af5a, 0x3142d0b9ae2d2948, -0x24b2a5e580db3580, 0x21aeba8b59250ea8 } + }, + { + { 0x53853600f0087f23, 0x4c461879da7d5784, 0x6af303deb41f6860, 0x0a3c16c5c27c18ed }, + { 0x24f13b34cf405530, 0x3c44ea4a43088af7, 0x5dd5c5170006a482, 0x118eb8f8890b086d }, + { 0x17e49c17cc947f3d, -0x33391259553e2d85, -0x209f6d314f0f71aa, 0x4909b3e22c67c36b } + }, + { + { 0x59a16676706ff64e, 0x10b953dd0d86a53d, 0x5848e1e6ce5c0b96, 0x2d8b78e712780c68 }, + { -0x63637a159c01d177, -0x41e4506ef16bed14, -0x7084557579040185, 0x0fb17f9fef968b6c }, + { 0x79d5c62eafc3902b, 0x773a215289e80728, -0x3c7519bf1efedf47, 0x09ae23717b2b1a6d } + }, + { + { 0x10ab8fa1ad32b1d0, -0x165312e41d8874dc, -0x577a943fc8c216f1, 0x66f35ddddda53996 }, + { -0x4495e6d5b1b2f7c4, 0x34ace0630029e192, -0x67dba5a655054515, 0x6d9c8a9ada97faac }, + { -0x2d826504db668cdd, 0x1bb7e07ef6f01d2e, 0x2ba7472df52ecc7f, 0x03019b4f646f9dc8 } + }, + { + { -0x50f64deb194c2395, 0x3f7573b5ad7d2f65, -0x2fe62677eff5dc50, 0x392b63a58b5c35f7 }, + { 0x04a186b5565345cd, -0x111899ef433bee96, 0x689c73b478fb2a45, 0x387dcbff65697512 }, + { 0x4093addc9c07c205, -0x3a9a41ea0acd3c82, 0x63dbecfd1583402a, 0x61722b4aef2e032e } + }, + { + { -0x294f85aa7e34f1c4, 0x290ff006d9444969, 0x08680b6a16dcda1f, 0x5568d2b75a06de59 }, + { 0x0012aafeecbd47af, 0x55a266fb1cd46309, -0x0dfc1497f69838d4, 0x39633944ca3c1429 }, + { -0x72f34773e4c8301f, 0x05b6a5a3053818f3, -0x0d1643fb487826a7, 0x6beba1249add7f64 } + }, + { + { 0x5c3cecb943f5a53b, -0x633659e2f93f720e, -0x30459c657a76abb9, 0x5a845ae80df09fd5 }, + { 0x1d06005ca5b1b143, 0x6d4c6bb87fd1cda2, 0x6ef5967653fcffe7, 0x097c29e8c1ce1ea5 }, + { 0x4ce97dbe5deb94ca, 0x38d0a4388c709c48, -0x3bc1312b5e962f69, 0x0a1249fff7e587c3 } + }, +}, +{ + { + { 0x0b408d9e7354b610, -0x7f94cdaca457a492, -0x2419c5fcb5a75df9, 0x173bd9ddc9a1df2c }, + { 0x12f0071b276d01c9, -0x1847453a793b7390, 0x5308129b71d6fba9, 0x5d88fbf95a3db792 }, + { 0x2b500f1efe5872df, 0x58d6582ed43918c1, -0x1912d8713698c520, 0x06e1cd13b19ea319 } + }, + { + { 0x472baf629e5b0353, 0x3baa0b90278d0447, 0x0c785f469643bf27, 0x7f3a6a1a8d837b13 }, + { 0x40d0ad516f166f23, 0x118e32931fab6abe, 0x3fe35e14a04d088e, 0x3080603526e16266 }, + { -0x0819bbc6a2c27ff5, -0x6a572aaa36fe120a, 0x68cd7830592c6339, 0x30d0fded2e51307e } + }, + { + { -0x634b68e19747b8b0, -0x5f6a8dd6999b4431, 0x5c8de72672fa412b, 0x4615084351c589d9 }, + { -0x1fa6b2e50dedcc4d, 0x1bdbe78ef0cc4d9c, 0x6965187f8f499a77, 0x0a9214202c099868 }, + { -0x436fe63f51465fd2, 0x55c7110d16034cae, 0x0e6df501659932ec, 0x3bca0d2895ca5dfe } + }, + { + { -0x639771496133fe41, -0x0f437c5259bb7691, -0x35d26aa0a085601e, 0x4ea8b4038df28241 }, + { 0x40f031bc3c5d62a4, 0x19fc8b3ecff07a60, -0x67e7c25decf04abb, 0x5631deddae8f13cd }, + { 0x2aed460af1cad202, 0x46305305a48cee83, -0x6ede88bab60ee5a1, 0x24ce0930542ca463 } + }, + { + { 0x3fcfa155fdf30b85, -0x2d08e971c9c8d15c, -0x4d1f9b219b6d07bc, 0x549928a7324f4280 }, + { 0x1fe890f5fd06c106, -0x4a3b97caa277ef0e, -0x7d87f701917350c2, 0x41d4e3c28a06d74b }, + { -0x0d91cd589c11e5d2, -0x516e1b482da00216, -0x43c42cc42e80b297, 0x491b66dec0dcff6a } + }, + { + { 0x75f04a8ed0da64a1, -0x12ddd350981dd7b5, -0x7dcb5c86e084845c, 0x4cf6b8b0b7018b67 }, + { -0x670a4ec23815cd59, -0x1c2a073381e92468, -0x53f540ad340726b9, 0x08f338d0c85ee4ac }, + { -0x3c7c57de66e58c43, -0x54d843fe20cdf386, -0x3ec2cce47b888f9d, 0x530d4a82eb078a99 } + }, + { + { 0x6d6973456c9abf9e, 0x257fb2fc4900a880, 0x2bacf412c8cfb850, 0x0db3e7e00cbfbd5b }, + { 0x004c3630e1f94825, 0x7e2d78268cab535a, -0x38b7dcdc337b0075, 0x65ea753f101770b9 }, + { 0x3d66fc3ee2096363, -0x7e29d3809e4a3495, 0x0fbe044213443b1a, 0x02a4ec1921e1a1db } + }, + { + { -0x0a379e9d0e3086a1, 0x118c861926ee57f2, 0x172124851c063578, 0x36d12b5dec067fcf }, + { 0x5ce6259a3b24b8a2, -0x47a88533ba505f48, -0x33341917745f8fc9, 0x3d143c51127809bf }, + { 0x126d279179154557, -0x2a1b70a30387c5f6, 0x36bdb6e8df179bac, 0x2ef517885ba82859 } + }, +}, +{ + { + { 0x1ea436837c6da1e9, -0x063e7650e0464242, 0x303001fcce5dd155, 0x28a7c99ebc57be52 }, + { -0x7742bc732ee1f2b6, 0x30cb610d43ccf308, -0x1f65f1c86e6c8434, 0x4559135b25b1720c }, + { -0x47026c66172e6163, -0x6f7e6e3469dbdc01, -0x4d46b728b838bd5d, 0x37f33226d7fb44c4 } + }, + { + { 0x33912553c821b11d, 0x66ed42c241e301df, 0x066fcc11104222fd, 0x307a3b41c192168f }, + { 0x0dae8767b55f6e08, 0x4a43b3b35b203a02, -0x1c8da5917f507387, 0x0f7a7fd1705fa7a3 }, + { -0x7114a2f8914aa320, 0x2fc536bfaa0d925a, -0x417e7cf023493918, 0x556c7045827baf52 } + }, + { + { -0x46b46ffdd40bbbfa, -0x542bdc81006f4acc, 0x7600a960faf86d3a, 0x2f45abdac2322ee3 }, + { -0x71d4ae8cfd162749, -0x1c1add96db78eb18, -0x42b04288b3569f4b, 0x6f4b4199c5ecada9 }, + { 0x61af4912c8ef8a6a, -0x1a705b01bc0491a2, -0x4a5033a2902bd831, 0x6a5393281e1e11eb } + }, + { + { 0x0fff04fe149443cf, 0x53cac6d9865cddd7, 0x31385b03531ed1b7, 0x5846a27cacd1039d }, + { -0x0c25aec65a2e1177, -0x7ebaba83006c9678, 0x3f622fed00e188c4, 0x0f513815db8b5a3d }, + { 0x4ff5cdac1eb08717, 0x67e8b29590f2e9bc, 0x44093b5e237afa99, 0x0d414bed8708b8b2 } + }, + { + { -0x7e77956dd6b53618, 0x23162b45d55547be, -0x6b3043bbfc8ea67d, 0x50eb8fdb134bc401 }, + { -0x30497d9a02f18a0a, -0x1ba4c1d7446f18f9, 0x7242a8de9ff92c7a, 0x685b3201933202dd }, + { -0x3f48c139294ccf33, -0x7b1bb7f8ecd0500f, 0x732b7352c4a5dee1, 0x5d7c7cf1aa7cd2d2 } + }, + { + { 0x33d1013e9b73a562, -0x6da310a8b713d91f, -0x580319eb22b97fa8, 0x78b0fad41e9aa438 }, + { -0x50c4b94085b5505e, -0x4878fa13b2bf2bef, 0x114f0c6aca7c15e3, 0x3f364faaa9489d4d }, + { -0x40a95bce12fa4b78, -0x5acc199363b6a382, -0x179ad450780c9ae6, 0x0241800059d66c33 } + }, + { + { 0x28350c7dcf38ea01, 0x7c6cdbc0b2917ab6, -0x531830417a8f7d09, 0x4d2845aba2d9a1e0 }, + { -0x314f88015c85a41c, -0x249bd0fd1a5a1149, -0x3d192f3ab8ed8f48, 0x4771b65538e4529c }, + { -0x44ac801fbb8f8f22, -0x3458bbbc922aa821, -0x2c4a5cb8c9ff2435, 0x4aeabbe6f9ffd7f8 } + }, + { + { 0x6a2134bcc4a9c8f2, -0x040702e37531d1c9, 0x000ae3049911a0ba, 0x046e3a616bc89b9e }, + { 0x4630119e40d8f78c, -0x5fe5643ac38ef1ef, 0x486d2b258910dd79, 0x1e6c47b3db0324e5 }, + { 0x14e65442f03906be, 0x4a019d54e362be2a, 0x68ccdfec8dc230c7, 0x7cfb7e3faf6b861c } + }, +}, +{ + { + { -0x69114004cfa4d0af, -0x2c06c752776a6948, -0x0f0ad238b92a22db, 0x57968290bb3a0095 }, + { 0x4637974e8c58aedc, -0x4610dd04540fbe5c, -0x1e7a26a9167f8e76, 0x2f1b78fab143a8a6 }, + { -0x08e547bcf5df1eff, -0x0c6c9a72db0f13b9, -0x308af657911d112f, 0x7dc43e35dc2aa3e1 } + }, + { + { 0x5a782a5c273e9718, 0x3576c6995e4efd94, 0x0f2ed8051f237d3e, 0x044fb81d82d50a99 }, + { -0x7a69999a7782263d, -0x36f064ceb44facab, -0x391f720710df864f, 0x7ef72016758cc12f }, + { -0x3e20e73a56f81c27, 0x57b3371dce4c6359, -0x358fbacb4dfe44b7, 0x7f79823f9c30dd2e } + }, + { + { 0x6a9c1ff068f587ba, 0x0827894e0050c8de, 0x3cbf99557ded5be7, 0x64a9b0431c06d6f0 }, + { -0x7ccb2dc65c4aec18, -0x3ec98f2b46e05728, 0x12b54136f590bd33, 0x0a4e0373d784d9b4 }, + { 0x2eb3d6a15b7d2919, -0x4f4b095f2ac57dcb, 0x7156ce4389a45d47, 0x071a7d0ace18346c } + }, + { + { -0x33f3caaddf1ebbcf, 0x0d65950709b15141, -0x650a9de4df62a0ca, 0x7c69bcf7617755d3 }, + { -0x2cf8d255377845f5, 0x01262905bfa562ee, -0x30abcffd3f108975, 0x2c3bcc7146ea7e9c }, + { 0x07f0d7eb04e8295f, 0x10db18252f50f37d, -0x16ae565ce8e86729, 0x6f5a9a7322aca51d } + }, + { + { -0x18d62b145c26bb42, -0x7261f6bf7f875062, 0x4525567a47869c03, 0x02ab9680ee8d3b24 }, + { -0x745efff3d0be393b, -0x3b60863ef3010465, 0x4efa47703cc51c9f, 0x494e21a2e147afca }, + { -0x105b757a221af266, 0x219a224e0fb9a249, -0x05f6e0e226e10927, 0x6b5d76cbea46bb34 } + }, + { + { -0x1f06bee8e187dade, -0x0e19518bfc96c92d, 0x408b3ea2d0fcc746, 0x16fb869c03dd313e }, + { -0x77a8aa9313f3266c, 0x6472dc6f5cd01dba, -0x50fe96eb70bd4b89, 0x0ae333f685277354 }, + { 0x288e199733b60962, 0x24fc72b4d8abe133, 0x4811f7ed0991d03e, 0x3f81e38b8f70d075 } + }, + { + { 0x0adb7f355f17c824, 0x74b923c3d74299a4, -0x2a83c17434071509, 0x0ad3e2d34cdedc3d }, + { 0x7f910fcc7ed9affe, 0x545cb8a12465874b, -0x57c6812db4f3b8fc, 0x50510fc104f50993 }, + { 0x6f0c0fc5336e249d, 0x745ede19c331cfd9, -0x0d2902fff61101e4, 0x127c158bf0fa1ebe } + }, + { + { -0x215d703b51ae468c, 0x1d9973d3744dfe96, 0x6240680b873848a8, 0x4ed82479d167df95 }, + { -0x09e683bdd167865e, -0x5bb5222bad35c9b9, -0x64bec03eb4b15335, 0x354ef87d07ef4f68 }, + { -0x011c4add9f3a268b, 0x50352efceb41b0b8, -0x77f753cf56099ac4, 0x302d92d20539236d } + }, +}, +{ + { + { -0x6a847474f20ac3d0, 0x2a1c770a8e60f098, -0x4438598fcba86922, 0x22a48f9a90c99bc9 }, + { 0x4c59023fcb3efb7c, 0x6c2fcb99c63c2a94, -0x45be6f1d3c381f7c, 0x0e545daea51874d9 }, + { 0x6b7dc0dc8d3fac58, 0x5497cd6ce6e42bfd, 0x542f7d1bf400d305, 0x4159f47f048d9136 } + }, + { + { 0x748515a8bbd24839, 0x77128347afb02b55, 0x50ba2ac649a2a17f, 0x060525513ad730f1 }, + { 0x20ad660839e31e32, -0x07e1e42a7bfa41b0, -0x07f9bfa90b254397, 0x14d23dd4ce71b975 }, + { -0x0dc671f6755d807e, 0x6d7982bb89a1b024, -0x0596bf7bdeb22db4, 0x71ab966fa32301c3 } + }, + { + { -0x4ef775f8fd7f66ab, 0x43b273ea0b43c391, -0x3564985101f97913, 0x605eecbf8335f4ed }, + { 0x2dcbd8e34ded02fc, 0x1151f3ec596f22aa, -0x435daabcb1fcd726, 0x35768fbe92411b22 }, + { -0x7cdff59a93cbfbcf, -0x60328e98711a63d1, 0x75d4613f71300f8a, 0x7a912faf60f542f9 } + }, + { + { 0x253f4f8dfa2d5597, 0x25e49c405477130c, 0x00c052e5996b1102, 0x33cb966e33bb6c4a }, + { -0x4dfba7a1a123e5bd, -0x60f1e911a76838c4, 0x5b82c0ae4e70483c, 0x624a170e2bddf9be }, + { 0x597028047f116909, -0x7d753be3e1a9bb99, 0x70417dbde6217387, 0x721627aefbac4384 } + }, + { + { -0x02cf6843bef4d0de, -0x0e5fa2584a3057bc, 0x61289a1def57ca74, 0x245ea199bb821902 }, + { -0x682fc43c78c9522b, 0x2f1422afc532b130, 0x3aa68a057101bbc4, 0x4c946cf7e74f9fa7 }, + { -0x51235996872b8808, 0x1898ba3c29117fe1, -0x308c067c8df342a8, 0x67da12e6b8b56351 } + }, + { + { 0x2b7ef3d38ec8308c, -0x7d7028138e146b55, -0x7f83c4c93af9d543, 0x0cb64cb831a94141 }, + { 0x7067e187b4bd6e07, 0x6e8f0203c7d1fe74, -0x6c3955d0c737a5d0, 0x76297d1f3d75a78a }, + { 0x3030fc33534c6378, -0x469ca3a31abe179f, 0x15d9a9bed9b2c728, 0x49233ea3f3775dcb } + }, + { + { 0x7b3985fe1c9f249b, 0x4fd6b2d5a1233293, -0x314cba6be520b29e, 0x6987ff6f542de50c }, + { 0x629398fa8dbffc3a, -0x1ed01ad22ab24bab, -0x0c41ee20250dad6b, 0x628b140dce5e7b51 }, + { 0x47e241428f83753c, 0x6317bebc866af997, -0x2544a4bcc2e567d7, 0x074d8d245287fb2d } + }, + { + { 0x481875c6c0e31488, 0x219429b2e22034b4, 0x7223c98a31283b65, 0x3420d60b342277f9 }, + { -0x7cc82632bbf403cf, 0x729d2ca1af318fd7, -0x5fbf5b5b88d3df90, 0x46002ef03a7349be }, + { -0x055dc52150019a09, 0x78261ed45be0764c, 0x441c0a1e2f164403, 0x5aea8e567a87d395 } + }, +}, +{ + { + { 0x2dbc6fb6e4e0f177, 0x04e1bf29a4bd6a93, 0x5e1966d4787af6e8, 0x0edc5f5eb426d060 }, + { 0x7813c1a2bca4283d, -0x129d0f6e5e79c227, -0x513843473d97057a, 0x10e5d3b76f1cae4c }, + { 0x5453bfd653da8e67, -0x1623e113db5609bf, -0x4078d9c4fca875dd, 0x45b46c51361cba72 } + }, + { + { -0x3162b22275801c1c, -0x54ec9ba9899df1d0, 0x4b594f7bb30e9958, 0x5c1c0aef321229df }, + { -0x56bfd540ceb0805f, -0x1da80e2371730bb0, 0x1dbbd54b23a8be84, 0x2177bfa36dcb713b }, + { 0x37081bbcfa79db8f, 0x6048811ec25f59b3, 0x087a76659c832487, 0x4ae619387d8ab5bb } + }, + { + { 0x61117e44985bfb83, -0x031fb9d58e69ceca, -0x7c53cbb72bda6fb5, 0x75685abe5ba43d64 }, + { -0x72240955acbb5cd2, 0x7d88eab4b41b4078, 0x5eb0eb974a130d60, 0x1a00d91b17bf3e03 }, + { 0x6e960933eb61f2b2, 0x543d0fa8c9ff4952, -0x208d8aef85099a97, 0x135529b623b0e6aa } + }, + { + { -0x0a38e9431dd17c02, -0x4bd414e617f67a3f, -0x136259c8ebdab552, 0x5972ea051590a613 }, + { 0x18f0dbd7add1d518, -0x68608777303ee0ef, -0x78cd1e0f8eeb8a65, 0x79b5b81a65ca3a01 }, + { 0x0fd4ac20dc8f7811, -0x65652d6b53b2b058, -0x3fe4d29b4cc9fbcc, 0x4f7e9c95905f3bdb } + }, + { + { 0x71c8443d355299fe, -0x7432c4e324141529, -0x7f6db6610e5b6b9a, 0x1942eec4a144adc8 }, + { 0x62674bbc5781302e, -0x27adf0c6765223f1, -0x73d66651ac04263a, 0x31993ad92e638e4c }, + { 0x7dac5319ae234992, 0x2c1b3d910cea3e92, 0x553ce494253c1122, 0x2a0a65314ef9ca75 } + }, + { + { -0x30c9e532c3e386c6, 0x2f9ebcac5a35bc3b, 0x60e860e9a8cda6ab, 0x055dc39b6dea1a13 }, + { 0x2db7937ff7f927c2, -0x248be0f9e82f59cb, 0x5982f3a21155af76, 0x4cf6e218647c2ded }, + { -0x4ee6dd833d72a44a, 0x07e24ebc774dffab, -0x57c387311b5cd377, 0x121a307710aa24b6 } + }, + { + { -0x29a68ec1388b7c37, -0x77401f8847d46951, 0x289e28231097bcd3, 0x527bb94a6ced3a9b }, + { -0x1b24a2a160fcb569, -0x1eac03f6cfcb43d3, 0x460546919551d3b1, 0x333fc76c7a40e52d }, + { 0x563d992a995b482e, 0x3405d07c6e383801, 0x485035de2f64d8e5, 0x6b89069b20a7a9f7 } + }, + { + { 0x4082fa8cb5c7db77, 0x068686f8c734c155, 0x29e6c8d9f6e7a57e, 0x0473d308a7639bcf }, + { -0x7ed55fbe9d8fddf3, -0x66a5760506dba4b2, -0x00523b31af8d10fb, 0x23bc2103aa73eb73 }, + { -0x351186d9fca761fb, 0x2b4b421246dcc492, 0x02a1ef74e601a94f, 0x102f73bfde04341a } + }, +}, +{ + { + { 0x358ecba293a36247, -0x5070679d4d97029b, 0x412f7e9968a01c89, 0x5786f312cd754524 }, + { -0x4a5d2af3813df2c2, -0x39b422915f368d9d, 0x56e89052c1ff734d, 0x4929c6f72b2ffaba }, + { 0x337788ffca14032c, -0x0c6defd7bb80e11d, -0x74ebf8e0dce43353, 0x4c817b4bf2344783 } + }, + { + { 0x413ba057a40b4484, -0x45b3d1e5b0a095bd, 0x614ba0a5aee1d61c, 0x78a1531a8b05dc53 }, + { 0x0ff853852871b96e, -0x1ec160549f3c0e45, -0x1102a6acdacbbbfe, 0x0a37c37075b7744b }, + { 0x6cbdf1703ad0562b, -0x7130b7cf36dade5d, -0x25142cfc027bdb19, 0x72ad82a42e5ec56f } + }, + { + { -0x3c976c6e98fdb43d, -0x71962e92b6afd026, -0x030d13c31ba0b4d7, 0x065f669ea3b4cbc4 }, + { 0x3f9e8e35bafb65f6, 0x39d69ec8f27293a1, 0x6cb8cd958cf6a3d0, 0x1734778173adae6d }, + { -0x75ff5138aacd24b3, -0x47965b1bbc1ce44f, 0x4a0f8552d3a7f515, 0x19adeb7c303d7c08 } + }, + { + { -0x62fa4582bc3ce86c, 0x2470c8ff93322526, -0x7cdc2137e9e68bc8, 0x2852709881569b53 }, + { -0x38df349eac15265d, 0x55b2c97f512b636e, -0x4e1ca4a02bfd6f4f, 0x2fd9ccf13b530ee2 }, + { 0x07bd475b47f796b8, -0x2d384fecabd370ac, 0x2dbd23f43b24f87e, 0x6551afd77b0901d6 } + }, + { + { 0x68a24ce3a1d5c9ac, -0x44885cc2ef009b9f, 0x0f86ce4425d3166e, 0x56507c0950b9623b }, + { 0x4546baaf54aac27f, -0x090990134d5ba5d8, 0x582d1b5b562bcfe8, 0x44b123f3920f785f }, + { 0x1206f0b7d1713e63, 0x353fe3d915bafc74, 0x194ceb970ad9d94d, 0x62fadd7cf9d03ad3 } + }, + { + { 0x3cd7bc61e7ce4594, -0x3294ca564822d982, -0x5f7f5437bc9910d9, 0x6ec7c46f59c79711 }, + { -0x394a6984aa675f8c, 0x5efe91ce8e493e25, -0x2b48d3bab6d7f778, 0x20ef1149a26740c2 }, + { 0x2f07ad636f09a8a2, -0x79681931dbdfa183, -0x3f5103fa11ca5ec7, 0x15e80958b5f9d897 } + }, + { + { 0x4dd1ed355bb061c4, 0x42dc0cef941c0700, 0x61305dc1fd86340e, 0x56b2cc930e55a443 }, + { 0x25a5ef7d0c3e235b, 0x6c39c17fbe134ee7, -0x388b1ecbd23a3cd9, 0x021354b892021f39 }, + { 0x1df79da6a6bfc5a2, 0x02f3a2749fde4369, -0x4cdc260d325c6f59, 0x7be0847b8774d363 } + }, + { + { 0x1466f5af5307fa11, -0x7e8033821293f50e, 0x0a6de44ec3a4a3fb, 0x74071475bc927d0b }, + { -0x736633a574c0aa3d, 0x0611d7253fded2a0, -0x12d66a00c948f5ca, 0x1f699a54d78a2619 }, + { -0x188d6d0c8c181576, 0x296537d2cb045a31, 0x1bd0653ed3274fde, 0x2f9a2c4476bd2966 } + }, +}, +{ + { + { -0x5d4b251f4aaee366, 0x7ac860292bffff06, -0x67e0c8a20aafbdcc, 0x3f6bd725da4ea12d }, + { -0x14e7465480a8ba3a, 0x023a8aee5787c690, -0x48d8ed25d2085057, 0x36597d25ea5c013d }, + { 0x734d8d7b106058ac, -0x26bfa86190396fa1, 0x6466f8f99202932d, 0x7b7ecc19da60d6d0 } + }, + { + { 0x6dae4a51a77cfa9b, -0x7dd9c9ab185c79b0, 0x09bbffcd8f2d82db, 0x03bedc661bf5caba }, + { 0x78c2373c695c690d, -0x22dad199f9bd6f92, -0x6ae2bbbbb51ed42e, 0x4235ad7601743956 }, + { 0x6258cb0d078975f5, 0x492942549189f298, -0x5f354bdc1d1c911c, 0x0e7ce2b0cdf066a1 } + }, + { + { -0x0159012026b48f07, -0x0ecf3fae3e0345d3, 0x4882d47e7f2fab89, 0x615256138aeceeb5 }, + { -0x3b6b9bc53b737a5d, -0x02c9e20bc39ec653, 0x09db17dd3ae94d48, 0x666e0a5d8fb4674a }, + { 0x2abbf64e4870cb0d, -0x329a430f55ba7495, -0x6541b1458a1767a3, 0x7f0bc810d514dee4 } + }, + { + { -0x7c5362528c8dec60, -0x60090745d108d168, 0x311e2edd43ec6957, 0x1d3a907ddec5ab75 }, + { -0x46ff945bd90bec91, -0x7298c961a81fcfcb, -0x34372026b0b9c3d8, 0x0d1f8dbcf8eedbf5 }, + { -0x45e96ccec12f7e24, 0x29329fad851b3480, 0x0128013c030321cb, 0x00011b44a31bfde3 } + }, + { + { 0x16561f696a0aa75c, -0x3e408da3a7ad4296, 0x11a8dd7f9a7966ad, 0x63d988a2d2851026 }, + { 0x3fdfa06c3fc66c0c, 0x5d40e38e4dd60dd2, 0x7ae38b38268e4d71, 0x3ac48d916e8357e1 }, + { 0x00120753afbd232e, -0x16d431470227097d, -0x07e9964c7b18d46f, 0x33fad52b2368a066 } + }, + { + { -0x72d3372f3bdd3018, 0x072b4f7b05a13acb, -0x5c01491913095a91, 0x3cc355ccb90a71e2 }, + { 0x540649c6c5e41e16, 0x0af86430333f7735, -0x4d53032d0cfa18ba, 0x16c0f429a256dca7 }, + { -0x16496bbc6fc16ecf, -0x475b6b3485a9c832, -0x37832e5b45456dbc, 0x631eaf426bae7568 } + }, + { + { 0x47d975b9a3700de8, 0x7280c5fbe2f80552, 0x53658f2732e45de1, 0x431f2c7f665f80b5 }, + { -0x4c16fbef25990161, -0x7a22b4ad93e91a5a, -0x43c2689ee106407d, 0x5599648b1ea919b5 }, + { -0x29fd9cbb7a7084e7, 0x14ab352fa1ea514a, -0x76ffbbe5df6f5629, 0x7b04715f91253b26 } + }, + { + { -0x4c893d7f3b19453a, -0x68f12c2292e264f5, -0x4f656aa7baf406bc, 0x48d0acfa57cde223 }, + { -0x7c1242d7530951bd, -0x79ca837482a3854c, -0x3fbfb8964814d3bc, 0x59b37bf5c2f6583f }, + { -0x49f0d91b8254198f, -0x0e2e5e689dd0c5c9, 0x4208ce7ee9960394, 0x16234191336d3bdb } + }, +}, +{ + { + { -0x7ad22e02c2a87442, 0x2b65ce72c3286108, 0x658c07f4eace2273, 0x0933f804ec38ab40 }, + { -0x0e651538cc59c511, 0x2c7fba5d4442454e, 0x5da87aa04795e441, 0x413051e1a4e0b0f5 }, + { -0x5854968672b69b8a, -0x7ede5521034a5438, -0x5a23ed1084ac6b8e, 0x07fd47065e45351a } + }, + { + { 0x304211559ae8e7c3, -0x0d7e4dd66bb77d5b, -0x75ec53d1c87daf1c, 0x014afa0954ba48f4 }, + { -0x37a7c3c2da72d433, 0x17029a4daf60b73f, -0x05f03629be95c87f, 0x1c1e5fba38b3fb23 }, + { -0x34ce68ffe44c9994, 0x330060524bffecb9, 0x293711991a88233c, 0x291884363d4ed364 } + }, + { + { -0x0462c83c43e54915, 0x02be14534d57a240, -0x0b28cbea075a1e0a, 0x5964f4300ccc8188 }, + { 0x033c6805dc4babfa, 0x2c15bf5e5596ecc1, 0x1bc70624b59b1d3b, 0x3ede9850a19f0ec5 }, + { -0x1bb5dcead2f69800, 0x5c08c55970866996, -0x20d249f5b9500492, 0x579155c1f856fd89 } + }, + { + { -0x4a0e949cf7e8185a, -0x7f7396dcc3caefda, 0x324a983b54cef201, 0x53c092084a485345 }, + { -0x69cdb122ed1f3611, 0x468b878df2420297, 0x199a3776a4f573be, 0x1e7fbcf18e91e92a }, + { -0x2d2beb7e0e345041, 0x231d2db6716174e5, 0x0b7d7656e2a55c98, 0x3e955cd82aa495f6 } + }, + { + { -0x54c60c109e44c5c1, -0x714bff9ad146e6c2, -0x4a219133c73ee08c, 0x654d7e9626f3c49f }, + { -0x1b70aca1c12eabcd, -0x2f8a96d5f28d8f5d, 0x40fbd21daade6387, 0x14264887cf4495f5 }, + { -0x1a9b3022a382d315, -0x7d11502128c83347, 0x6107db62d1f9b0ab, 0x0b6baac3b4358dbb } + }, + { + { 0x204abad63700a93b, -0x41ffdc2c25886c8d, -0x27a0fcb99cc548f7, 0x00496dc490820412 }, + { 0x7ae62bcb8622fe98, 0x47762256ceb891af, 0x1a5a92bcf2e406b4, 0x7d29401784e41501 }, + { 0x1c74b88dc27e6360, 0x074854268d14850c, -0x5eba0484c1f234d0, 0x10843f1b43803b23 } + }, + { + { -0x2a9098d21cdb9765, -0x2e2575124c6b567f, -0x2284a7016e973013, 0x7ce246cd4d56c1e8 }, + { -0x3a06fbaac89d8923, -0x31a6ea72289ba327, -0x6d09a2aee2c994c7, 0x11574b6e526996c4 }, + { -0x470bcf71807f41ad, 0x5f3cb8cb34a9d397, 0x18a961bd33cc2b2c, 0x710045fb3a9af671 } + }, + { + { -0x5fc0379dfa629662, 0x2370cfa19a619e69, -0x3b01c4edd07dc215, 0x1d1b056fa7f0844e }, + { 0x73f93d36101b95eb, -0x0510cc86b090bb7a, 0x5651735f8f15e562, 0x7fa3f19058b40da1 }, + { 0x1bc64631e56bf61f, -0x2c8654ef91ac7d5d, 0x4d58c57e0540168d, 0x566256628442d8e4 } + }, +}, +{ + { + { -0x22b66329e00c79c0, 0x29cd9bc3063625a0, 0x51e2d8023dd73dc3, 0x4a25707a203b9231 }, + { -0x461b662109d9800a, 0x7772ca7b742c0843, 0x23a0153fe9a4f2b1, 0x2cdfdfecd5d05006 }, + { 0x2ab7668a53f6ed6a, 0x304242581dd170a1, 0x4000144c3ae20161, 0x5721896d248e49fc } + }, + { + { 0x285d5091a1d0da4e, 0x4baa6fa7b5fe3e08, 0x63e5177ce19393b3, 0x03c935afc4b030fd }, + { 0x0b6e5517fd181bae, -0x6fdd9d60d4469c4c, 0x5509bce932064625, 0x578edd74f63c13da }, + { -0x668d8939b6d4f3c3, 0x47ccc2c4dfe205fc, -0x232d647b229dc5c4, 0x3ec2ab590288c7a2 } + }, + { + { -0x58dec5f651cd2e35, 0x0f2b87df40f5c2d5, 0x0baea4c6e81eab29, 0x0e1bf66c6adbac5e }, + { -0x5e5f2d841b278447, -0x5674b2149ec6e513, -0x665f222f8c34647d, 0x2dd5c25a200fcace }, + { -0x1d542a1686d37782, 0x1a020018cb926d5d, -0x404596324551a0e2, 0x730548b35ae88f5f } + }, + { + { -0x7fa4f6b45e291ccc, -0x40c10e88f6cac0e7, 0x423f06cb0622702b, 0x585a2277d87845dd }, + { -0x3bcaae5c34574712, 0x65a26f1db2115f16, 0x760f4f52ab8c3850, 0x3043443b411db8ca }, + { -0x5e75a07dcc2b769e, 0x6698c4b5ec78257f, -0x5871905ac8c1be01, 0x7656278950ef981f } + }, + { + { -0x1e8f8c5c15793063, 0x3a8cfbb707155fdc, 0x4853e7fc31838a8e, 0x28bbf484b613f616 }, + { 0x38c3cf59d51fc8c0, -0x64122d02faf9490e, 0x26bf109fab570e8f, 0x3f4160a8c1b846a6 }, + { -0x0d9ed0a390ec9384, -0x50152ef80922ee42, 0x527e9ad213de6f33, 0x1e79cb358188f75d } + }, + { + { 0x77e953d8f5e08181, -0x7b5af3bbd6622127, -0x2393d2f379bada1b, 0x478ab52d39d1f2f4 }, + { 0x013436c3eef7e3f1, -0x7d7495800161ef08, 0x7ff908e5bcf9defc, 0x65d7951b3a3b3831 }, + { 0x66a6a4d39252d159, -0x1a221e4378e537f9, -0x47d394bf593e3691, 0x16d87a411a212214 } + }, + { + { -0x045b2a1d2ab1fa7d, -0x1de05028d1426606, 0x497ac2736ee9778f, 0x1f990b577a5a6dde }, + { -0x4c4281a5bdf99deb, -0x78641c32f3a5db3f, 0x57c05db1d6f994b7, 0x28f87c8165f38ca6 }, + { -0x5ccbb152e417082a, 0x7d1e50ebacea798f, 0x77c6569e520de052, 0x45882fe1534d6d3e } + }, + { + { -0x275366d66bc3901c, -0x4a060e9e5c7c6d5e, 0x2699db13bec89af3, 0x7dcf843ce405f074 }, + { 0x6669345d757983d6, 0x62b6ed1117aa11a6, 0x7ddd1857985e128f, 0x688fe5b8f626f6dd }, + { 0x6c90d6484a4732c0, -0x2adebc0235a9cd67, -0x4c41d73c6ea2391f, 0x6739687e7327191b } + }, +}, +{ + { + { -0x731a552f363468e1, 0x1156aaa99fd54a29, 0x41f7247015af9b78, 0x1fe8cca8420f49aa }, + { -0x609a3a15dff7eb31, -0x7bfac91e965ce8c0, -0x74f12ec6da374b53, 0x0080dbafe936361d }, + { 0x72a1848f3c0cc82a, 0x38c560c2877c9e54, 0x5004e228ce554140, 0x042418a103429d71 } + }, + { + { 0x58e84c6f20816247, -0x724d4d491c90286d, -0x688e7da9e2b7b27b, 0x0822024f8632abd7 }, + { -0x766215ae540c00a1, -0x646c5798d03d2746, 0x2c38cb97be6ebd5c, 0x114d578497263b5d }, + { -0x4cfe448394e4135d, 0x55393f6dc6eb1375, -0x6ef2d7ef68491b15, 0x1ad4548d9d479ea3 } + }, + { + { -0x5f901992f016012d, -0x578cc5bfe3a786f7, 0x30d14d800df98953, 0x41ce5876c7b30258 }, + { -0x32a5825fc765b703, -0x4c705b556587c8e2, -0x392689e4d3247194, 0x35cf51dbc97e1443 }, + { 0x59ac3bc5d670c022, -0x151983ef64ee6bfa, -0x6867420f4c87d026, 0x651e3201fd074092 } + }, + { + { -0x5a845b5fe1035162, 0x769f4beedc308a94, -0x2e0ef114c9fc34d2, 0x4099ce5e7e441278 }, + { -0x29c27b7c10cf3a31, 0x4cd4b4962361cc0c, -0x116f1aff5b7bd954, 0x0af51d7d18c14eeb }, + { 0x1ac98e4f8a5121e9, 0x7dae9544dbfa2fe0, -0x7cdf55f229bcf207, 0x667282652c4a2fb5 } + }, + { + { -0x5257491fd6b924dd, 0x1c0ce51a7b253ab7, -0x7bb737a59922b7a5, 0x7f1fc025d0675adf }, + { -0x78b9de0b27943655, -0x4ab38441a9019016, 0x077a24257fadc22c, 0x1ab53be419b90d39 }, + { -0x2711e4e7ce615956, 0x004d88083a21f0da, 0x3bd6aa1d883a4f4b, 0x4db9a3a6dfd9fd14 } + }, + { + { -0x26a4ff4434488398, -0x22437b956e0e87b7, 0x7cf700aebe28d9b3, 0x5ce1285c85d31f3e }, + { -0x73184dc44663f8ab, 0x35c5d6edc4f50f7a, 0x7e1e2ed2ed9b50c3, 0x36305f16e8934da1 }, + { 0x31b6972d98b0bde8, 0x7d920706aca6de5b, -0x198cef076f759a61, 0x50fac2a6efdf0235 } + }, + { + { 0x295b1c86f6f449bc, 0x51b2e84a1f0ab4dd, -0x3ffe34cf5571aae3, 0x6a28d35944f43662 }, + { -0x0c2c560ca477f0a6, -0x1213faf324fc183e, -0x576967e0060f4e5e, 0x49a4ae2bac5e34a4 }, + { 0x28bb12ee04a740e0, 0x14313bbd9bce8174, 0x72f5b5e4e8c10c40, 0x7cbfb19936adcd5b } + }, + { + { -0x7186c58533c91920, -0x0605485c82a79113, 0x3a4f9692bae1f4e4, 0x1c14b03eff5f447e }, + { -0x5cee223d947686d3, 0x1b30b4c6da512664, 0x0ca77b4ccf150859, 0x1de443df1b009408 }, + { 0x19647bd114a85291, 0x57b76cb21034d3af, 0x6329db440f9d6dfa, 0x5ef43e586a571493 } + }, +}, +{ + { + { -0x5992336237f3e540, -0x685fa30be4c75bca, -0x58140c416a24283a, 0x7da0b8f68d7e7dab }, + { -0x1087dfebc7a98a5a, -0x5d9b60cf55025618, 0x4cd1eb505cdfa8cb, 0x46115aba1d4dc0b3 }, + { -0x2bf0e6ac3c4a258a, 0x1dac6f7321119e9b, 0x03cc6021feb25960, 0x5a5f887e83674b4b } + }, + { + { -0x6169d72c5f59bc47, -0x4a3c34ff193cdf9c, -0x64acfd7683d213ce, 0x43e37ae2d5d1c70c }, + { -0x709cfe308f5ec2ef, -0x303147eacaf22f3c, -0x08fd682b5b435b82, 0x3669b656e44d1434 }, + { 0x387e3f06eda6e133, 0x67301d5199a13ac0, -0x42a52707c9d9c7ef, 0x6a21e6cd4fd5e9be } + }, + { + { -0x10bed6ed99664d1d, 0x71d30847708d1301, 0x325432d01182b0bd, 0x45371b07001e8b36 }, + { -0x0e39e8f5cfb919a1, 0x58712a2a00d23524, 0x69dbbd3c8c82b755, 0x586bf9f1a195ff57 }, + { -0x5924f772a10786f5, 0x5278f0dc610937e5, -0x53fcb62d9e5e9148, 0x0eafb03790e52179 } + }, + { + { 0x5140805e0f75ae1d, -0x13fd041cd99d33d0, 0x2cebdf1eea92396d, 0x44ae3344c5435bb3 }, + { -0x69faaa3ec8b7fbd1, 0x219a41e6820baa11, 0x1c81f73873486d0c, 0x309acc675a02c661 }, + { -0x630d7646445abc12, -0x0c89f162a5368ebe, 0x1d82e5c64f9360aa, 0x62d5221b7f94678f } + }, + { + { 0x7585d4263af77a3c, -0x205184ee0116ebb3, -0x5af98f7fa608e6c3, 0x14f29a5383922037 }, + { 0x524c299c18d0936d, -0x37944a9375f3e5f4, -0x5c8afad124b579cf, 0x5c0efde4bc754562 }, + { -0x208e8123da4d280b, 0x21f970db99b53040, -0x256dcb483c12b39e, 0x5e72365c7bee093e } + }, + { + { 0x7d9339062f08b33e, 0x5b9659e5df9f32be, -0x5300c252e0614203, 0x70b20555cb7349b7 }, + { 0x575bfc074571217f, 0x3779675d0694d95b, -0x65f5c8440be6e1cd, 0x77f1104c47b4eabc }, + { -0x41aeec3aaaeed3b4, 0x6688423a9a881fcd, 0x446677855e503b47, 0x0e34398f4a06404a } + }, + { + { 0x18930b093e4b1928, 0x7de3e10e73f3f640, -0x0bcde8258cc6a291, 0x6f8aded6ca379c3e }, + { -0x4982dd26c1314218, 0x09b3e84127822f07, 0x743fa61fb05b6d8d, 0x5e5405368a362372 }, + { -0x1cbfedc202484d66, 0x487b97e1a21ab291, -0x066982fd02196b62, 0x780de72ec8d3de97 } + }, + { + { 0x671feaf300f42772, -0x708d14d5d573be56, 0x29a17fd797373292, 0x1defc6ad32b587a6 }, + { 0x0ae28545089ae7bc, 0x388ddecf1c7f4d06, 0x38ac15510a4811b8, 0x0eb28bf671928ce4 }, + { -0x50a441e510ae6a59, 0x148c1277917b15ed, 0x2991f7fb7ae5da2e, 0x467d201bf8dd2867 } + }, +}, +{ + { + { 0x745f9d56296bc318, -0x66ca7f2b27ead19b, -0x4f1a4ec0a7c61632, 0x51fc2b28d43921c0 }, + { 0x7906ee72f7bd2e6b, 0x05d270d6109abf4e, -0x72a301ba46be575c, 0x44c218671c974287 }, + { 0x1b8fd11795e2a98c, 0x1c4e5ee12b6b6291, 0x5b30e7107424b572, 0x6e6b9de84c4f4ac6 } + }, + { + { 0x6b7c5f10f80cb088, 0x736b54dc56e42151, -0x3d49df5a3910663c, 0x5f4c802cc3a06f42 }, + { -0x200da031b4e21eaf, -0x27be3f381ee3bfdb, 0x2554b3c854749c87, 0x2d292459908e0df9 }, + { -0x649a370e82f8ad26, -0x77e31cc738811800, -0x3c4aeb0fa49d061d, 0x66ed5dd5bec10d48 } + }, + { + { -0x0f520c363435fb83, -0x7e3c4d340baad095, -0x3025eed2bb8ca06d, 0x1f23a0c77e20048c }, + { 0x7d38a1c20bb2089d, -0x7f7ccb1e69332bee, -0x3b58f47393682ced, 0x2eacf8bc03007f20 }, + { -0x0dcab9841a43ea90, 0x03d2d9020dbab38c, 0x27529aa2fcf9e09e, 0x0840bef29d34bc50 } + }, + { + { -0x32ab1f9480c81b15, -0x733ea0780a169336, -0x47db744f2ca68232, 0x246affa06074400c }, + { 0x796dfb35dc10b287, 0x27176bcd5c7ff29d, 0x7f3d43e8c7b24905, 0x0304f5a191c54276 }, + { 0x37d88e68fbe45321, -0x79f68ab73f28afce, 0x4e9b13ef894a0d35, 0x25a83cac5753d325 } + }, + { + { -0x60f099d6c6ad491e, 0x33db5e0e0934267b, -0x00badad429f60124, 0x06be10f5c506e0c9 }, + { 0x10222f48eed8165e, 0x623fc1234b8bcf3a, 0x1e145c09c221e8f0, 0x7ccfa59fca782630 }, + { 0x1a9615a9b62a345f, 0x22050c564a52fecc, -0x585d877ad743f202, 0x5e82770a1a1ee71d } + }, + { + { -0x17fd17f5bdcc638c, 0x34175166a7fffae5, 0x34865d1f1c408cae, 0x2cca982c605bc5ee }, + { 0x35425183ad896a5c, -0x1798c5041872ad0a, 0x2c66f25f92a35f64, 0x09d04f3b3b86b102 }, + { -0x02d2a2cae6824192, 0x207c2eea8be4ffa3, 0x2613d8db325ae918, 0x7a325d1727741d3e } + }, + { + { -0x132d82fe81d5f896, -0x28779760e9c9b6a2, 0x52a61af0919233e5, 0x2a479df17bb1ae64 }, + { -0x2fc946442e92021e, -0x5dfaa8a83b6857d7, -0x71933699580ed999, 0x4d3b1a791239c180 }, + { -0x61a11171cc24d8f0, 0x189854ded6c43ca5, -0x5be3dd3a6d8e7ec8, 0x27ad5538a43a5e9b } + }, + { + { -0x34a5829c71b8f884, -0x7248ac9edf5e3fa7, 0x549e1e4d8bedfdcc, 0x080153b7503b179d }, + { 0x2746dd4b15350d61, -0x2fc03437116ade49, -0x1791c9a5ec798d36, 0x510e987f7e7d89e2 }, + { -0x2259626cf5c12c1d, 0x3d386ef1cd60a722, -0x37e852a74255b11a, 0x23be8d554fe7372a } + }, +}, +{ + { + { -0x43e10b42a9851857, 0x3f624cb2d64498bd, -0x1bef9b2dd3e0b138, 0x2ef9c5a5ba384001 }, + { -0x6a016e658b10b053, 0x3a827becf6a308a2, -0x69b1fe2cf65b84ff, 0x71c43c4f5ba3c797 }, + { -0x4902920905618b33, -0x0e7d87431b50d986, -0x7daa4c2f0e1066f2, 0x5a758ca390c5f293 } + }, + { + { -0x731f6e74e29e236c, -0x7212c9b9657ecf9a, -0x2b1957d65017552d, 0x0a738027f639d43f }, + { -0x5d48d8ef26b9db6b, 0x3aa8c6d2d57d5003, -0x1c2bff405f4b7836, 0x2dbae244b3eb72ec }, + { -0x67f0b5d0a8001e34, 0x00670d0de1839843, 0x105c3f4a49fb15fd, 0x2698ca635126a69c } + }, + { + { 0x2e3d702f5e3dd90e, -0x61c0f6e71b2dac7a, 0x5e773ef6024da96a, 0x3c004b0c4afa3332 }, + { -0x189ace77cd4f4588, 0x381831f7925cff8b, 0x08a81b91a0291fcc, 0x1fb43dcc49caeb07 }, + { -0x6556b953f90b47d5, 0x1ca284a5a806c4f3, 0x3ed3265fc6cd4787, 0x6b43fd01cd1fd217 } + }, + { + { -0x4a38bda7c189f10d, 0x75dc52b9ee0ab990, -0x40ebd83df8d46dc1, 0x73420b2d6ff0d9f0 }, + { -0x3858a2b4b9683abc, 0x15fdf848df0fffbf, 0x2868b9ebaa46785a, 0x5a68d7105b52f714 }, + { -0x50d30934617ae1fa, -0x70a6c6ec39ddc73c, -0x2575476966040c8d, 0x3db5632fea34bc9e } + }, + { + { 0x2e4990b1829825d5, -0x12151478c165766f, -0x110fc2c6b38fb508, 0x59197ea495df2b0e }, + { -0x0b9111d408a22628, 0x0d17b1f6396759a5, 0x1bf2d131499e7273, 0x04321adf49d75f13 }, + { 0x04e16019e4e55aae, -0x1884bc8581d06d17, -0x3831d23e90ea655c, 0x45eafdc1f4d70cc0 } + }, + { + { -0x49f1b9db30334e13, 0x59dbc292bd5c0395, 0x31a09d1ddc0481c9, 0x3f73ceea5d56d940 }, + { 0x698401858045d72b, 0x4c22faa2cf2f0651, -0x6be5c99a94ddd23a, 0x5a5eebc80362dade }, + { -0x4858402ef5b1723a, -0x41a8ff81bb364cc7, 0x60c1207f1557aefa, 0x26058891266218db } + }, + { + { 0x4c818e3cc676e542, 0x5e422c9303ceccad, -0x13f833354bed60f8, 0x0dedfa10b24443b8 }, + { 0x59f704a68360ff04, -0x3c26c021899e190c, -0x7ce4d58ced78caaf, 0x54ad0c2e4e615d57 }, + { -0x11c4982a47d4add6, 0x36f163469fa5c1eb, -0x5a4b2d0d913e602d, 0x62ecb2baa77a9408 } + }, + { + { -0x6df8d7c95049d78c, 0x5fcd5e8579e104a5, 0x5aad01adc630a14a, 0x61913d5075663f98 }, + { -0x1a1286ad9eead4c3, 0x4962357d0eddd7d1, 0x7482c8d0b96b4c71, 0x2e59f919a966d8be }, + { 0x0dc62d361a3231da, -0x05b8a7cd6bdffd90, 0x02d801513f9594ce, 0x3ddbc2a131c05d5c } + }, +}, +{ + { + { -0x048ca53dffb5ca2f, 0x31de0f433a6607c3, 0x7b8591bfc528d599, 0x55be9a25f5bb050c }, + { 0x3f50a50a4ffb81ef, -0x4e1fcaf6c40bdf41, -0x645571e33955d330, 0x32239861fa237a40 }, + { 0x0d005acd33db3dbf, 0x0111b37c80ac35e2, 0x4892d66c6f88ebeb, 0x770eadb16508fbcd } + }, + { + { -0x0e2c497e5faf8e47, 0x2207659a3592ff3a, 0x5f0169297881e40e, 0x16bedd0e86ba374e }, + { -0x7bae061fa1b17623, -0x3f9cfd004386c6c9, 0x5d22749556a6495c, 0x09a6755ca05603fb }, + { 0x5ecccc4f2c2737b5, 0x43b79e0c2dccb703, 0x33e008bc4ec43df3, 0x06c1b840f07566c0 } + }, + { + { 0x69ee9e7f9b02805c, -0x34007d75ab82e9c0, 0x3d93a869b2430968, 0x46b7b8cd3fe26972 }, + { 0x7688a5c6a388f877, 0x02a96c14deb2b6ac, 0x64c9f3431b8c2af8, 0x3628435554a1eed6 }, + { -0x167edf7901811420, 0x4cba6be72f515437, 0x1d04168b516efae9, 0x5ea1391043982cb9 } + }, + { + { 0x6f2b3be4d5d3b002, -0x5013cc2695f63780, 0x035f73a4a8bcc4cc, 0x22c5b9284662198b }, + { 0x49125c9cf4702ee1, 0x4520b71f8b25b32d, 0x33193026501fef7e, 0x656d8997c8d2eb2b }, + { -0x34a73701bcc276c7, -0x765f34d1957281b0, 0x79ca955309fbbe5a, 0x0c626616cd7fc106 } + }, + { + { -0x70203c86040bab4f, 0x45a5a970f1a4b771, -0x536de108452ca6eb, 0x42d088dca81c2192 }, + { 0x1ffeb80a4879b61f, 0x6396726e4ada21ed, 0x33c7b093368025ba, 0x471aa0c6f3c31788 }, + { -0x7025f0c85fe9ae67, 0x0adadb77c8a0e343, 0x20fbfdfcc875e820, 0x1cf2bea80c2206e7 } + }, + { + { -0x67d291e5fd3fbed1, -0x6f05b37c24a71702, 0x01c2f5bcdcb18bc0, 0x686e0c90216abc66 }, + { -0x3d220e214c9dfd54, -0x6d5a01f62d1d855b, 0x7d1648f6fc09f1d3, 0x74c2cc0513bc4959 }, + { 0x1fadbadba54395a7, -0x4be5fd5f51f25996, -0x40e60a67445c83f9, 0x6a12b8acde48430d } + }, + { + { 0x793bdd801aaeeb5f, 0x00a2a0aac1518871, -0x175c8c5ce0dec94c, 0x48aab888fc91ef19 }, + { -0x072515e0c62b6a27, 0x592c190e525f1dfc, -0x247342fb3666e2e5, 0x11f7fda3d88f0cb7 }, + { 0x041f7e925830f40e, 0x002d6ca979661c06, -0x79236006d4fb95d2, 0x760360928b0493d1 } + }, + { + { -0x4bcef71a96a5f4fb, 0x6cb00ee8ad37a38b, 0x5edad6eea3537381, 0x3f2602d4b6dc3224 }, + { 0x21bb41c6120cf9c6, -0x154d55ed21325a65, -0x3e58d2fdf55b74cc, 0x215d4d27e87d3b68 }, + { -0x374db849a4350e64, 0x49779dc3b1b2c652, -0x765e7f442a131d1e, 0x13f098a3cec8e039 } + }, +}, +{ + { + { -0x0c55a85dd86944ec, -0x77c5454864f825df, -0x1ab41de7ce5fc6e4, 0x5ee7fb38d83205f9 }, + { -0x6523f00631a13ab5, 0x039c2a6b8c2f130d, 0x028007c7f0f89515, 0x78968314ac04b36b }, + { 0x538dfdcb41446a8e, -0x5a530256bcb6c807, 0x46af908d263c8c78, 0x61d0633c9bca0d09 } + }, + { + { -0x525cd74307038c21, -0x117b96a2590fc804, 0x637fb4db38c2a909, 0x5b23ac2df8067bdc }, + { 0x63744935ffdb2566, -0x3a42947687f49745, 0x6f1b3280553eec03, 0x6e965fd847aed7f5 }, + { -0x652d46ac117fad85, -0x1770e65505219273, 0x0e711704150e82cf, 0x79b9bbb9dd95dedc } + }, + { + { -0x2e66825171608c8c, -0x5fcd5d073044f7ea, -0x329345ed92bba0f6, 0x1ba811460accb834 }, + { -0x144caabf95ced93e, -0x2d9c7c5797373c6d, 0x6c0c6429e5b97a82, 0x5065f158c9fd2147 }, + { 0x708169fb0c429954, -0x1eb9ff5328913099, 0x2eaab98a70e645ba, 0x3981f39e58a4faf2 } + }, + { + { -0x37ba205a92199022, -0x1ead5affd3bfb7c6, -0x162d1e9c384b09ce, 0x30f4452edcbc1b65 }, + { 0x18fb8a7559230a93, 0x1d168f6960e6f45d, 0x3a85a94514a93cb5, 0x38dc083705acd0fd }, + { -0x7a92d87d3a8a68c0, -0x05ecba9606634134, -0x77bb038c3f15b18f, 0x632d9a1a593f2469 } + }, + { + { -0x40f602ee12f37b59, 0x63f071810d9f693a, 0x21908c2d57cf8779, 0x3a5a7df28af64ba2 }, + { -0x094494ea47f8345a, 0x1823c7dfbc54f0d7, -0x44e268fc91d698f5, 0x0b24f48847ed4a57 }, + { -0x23252b41aee41539, -0x5bac7f8a12d9330e, -0x1e630060ffa0659b, 0x34fcf74475481f63 } + }, + { + { -0x5a44e25487305568, 0x5ceda267190b72f2, -0x6cf636eef56d9f72, 0x0119a3042fb374b0 }, + { -0x3e681fb387689836, -0x478eb234c726b983, 0x55de888283f95fa8, 0x3d3bdc164dfa63f7 }, + { 0x67a2d89ce8c2177d, 0x669da5f66895d0c1, -0x0a9a671a4d7d5d50, 0x56c088f1ede20a73 } + }, + { + { 0x581b5fac24f38f02, -0x56f41601451cf343, -0x65de96fd75306d10, 0x038b7ea48359038f }, + { 0x336d3d1110a86e17, -0x280c77cdf48a4d06, -0x06eacc89daf8d678, 0x09674c6b99108b87 }, + { -0x60b107de66ce9008, 0x2f49d282eaa78d4f, 0x0971a5ab5aef3174, 0x6e5e31025969eb65 } + }, + { + { 0x3304fb0e63066222, -0x04caf976785345c1, -0x42e6db8873ef9e5d, 0x3058ad43d1838620 }, + { -0x4e939d0a781a6c05, 0x4999eddeca5d3e71, -0x4b6e3e1feb33c193, 0x08f5114789a8dba8 }, + { 0x323c0ffde57663d0, 0x05c3df38a22ea610, -0x423875425366b066, 0x26549fa4efe3dc99 } + }, +}, +{ + { + { 0x04dbbc17f75396b9, 0x69e6a2d7d2f86746, -0x39bf62660ac1543a, 0x606175f6332e25d2 }, + { 0x738b38d787ce8f89, -0x49d9a71dbe865773, 0x30738c9cf151316d, 0x49128c7f727275c9 }, + { 0x4021370ef540e7dd, 0x0910d6f5a1f1d0a5, 0x4634aacd5b06b807, 0x6a39e6356944f235 } + }, + { + { 0x1da1965774049e9d, -0x0432915e6701cad5, -0x4e3432af33adc95a, 0x1f5ec83d3f9846e2 }, + { -0x6932a9bf206f0c19, 0x6c3a760edbfa25ea, 0x24f3ef0959e33cc4, 0x42889e7e530d2e58 }, + { -0x7104dc3ccd73348b, -0x50bd5df822789117, 0x20fbdadc5dfae796, 0x241e246b06bf9f51 } + }, + { + { 0x7eaafc9a6280bbb8, 0x22a70f12f403d809, 0x31ce40bb1bfc8d20, 0x2bc65635e8bd53ee }, + { 0x29e68e57ad6e98f6, 0x4c9260c80b462065, 0x3f00862ea51ebb4b, 0x5bc2c77fb38d9097 }, + { -0x172a23605694526d, -0x1a704e8221e6b824, 0x681532ea65185fa3, 0x1fdd6c3b034a7830 } + }, + { + { -0x63ec595ad2270857, 0x2dbb1f8c3efdcabf, -0x69e1cdbfa1f7084b, 0x48c8a121bbe6c9e5 }, + { 0x0a64e28c55dc18fe, -0x1c206166cc661423, 0x79ac432370e2e652, 0x35ff7fc33ae4cc0e }, + { -0x03bea583a69b9bbb, -0x2ddb4d283ed749eb, 0x6035c9c905fbb912, 0x42d7a91274429fab } + }, + { + { -0x565b76b86cc25a44, 0x4a58920ec2e979ec, -0x69277fffec1a53b4, 0x453692d74b48b147 }, + { 0x4e6213e3eaf72ed3, 0x6794981a43acd4e7, -0x00ab8321914af735, 0x6fed19dd10fcb532 }, + { -0x2288a26657aa6391, -0x0bd5debf20ffc1dc, 0x5223e229da928a66, 0x063f46ba6d38f22c } + }, + { + { 0x39843cb737346921, -0x58b804f8c7376bb9, -0x34727fce5dbacf82, 0x67810f8e6d82f068 }, + { -0x2d2dbd76a0ac996c, -0x35cc5d3abd6c64d4, -0x67905259382246a4, 0x5a152c042f712d5d }, + { 0x3eeb8fbcd2287db4, 0x72c7d3a301a03e93, 0x5473e88cbd98265a, 0x7324aa515921b403 } + }, + { + { -0x52dc092517dcab35, 0x6962502ab6571a6d, -0x649ae9c91c71c82f, 0x5cac5005d1a3312f }, + { -0x7a86bd0b93c34172, -0x5e2c9b4eb8cf3fba, 0x1c8ed914d23c41bf, 0x0838e161eef6d5d2 }, + { -0x733eab33161c66fc, 0x5b3a040b84de6846, -0x3b2759e34e41a292, 0x40fb897bd8861f02 } + }, + { + { -0x1a8127b8a54ef89f, 0x71435e206fd13746, 0x342f824ecd025632, 0x4b16281ea8791e7b }, + { -0x7b3a556f9d21c85f, 0x421da5000d1d96e1, 0x788286306a9242d9, 0x3c5e464a690d10da }, + { -0x2e3efe2af47ecc7f, -0x2119f0ee891197d8, 0x0cb68893383f6409, 0x6183c565f6ff484a } + }, +}, +{ + { + { -0x24b97ab650c09992, -0x288030fb0eb5f15b, 0x3df23ff7a4ba0c47, 0x3a10dfe132ce3c85 }, + { 0x741d5a461e6bf9d6, 0x2305b3fc7777a581, -0x2baa8b5d9b8b2c27, 0x1926e1dc6401e0ff }, + { -0x1f80b17515e83160, 0x2fd515463a1fc1fd, 0x175322fd31f2c0f1, 0x1fa1d01d861e5d15 } + }, + { + { 0x38dcac00d1df94ab, 0x2e712bddd1080de9, 0x7f13e93efdd5e262, 0x73fced18ee9a01e5 }, + { -0x337faa6b82a667ce, 0x1e4656da37f15520, -0x6609088bb1fa6ce0, 0x773563bc6a75cf33 }, + { 0x06b1e90863139cb3, -0x5b6c25983a5fc133, -0x72883137529c76ce, 0x1f426b701b864f44 } + }, + { + { -0x0e81ca376e5edaae, -0x48947eaca8a1638a, -0x057cbf90f2648dc2, 0x0b76bb1b3fa7e438 }, + { -0x1036d9b3be6ee3ff, -0x0e5c4847e85dd3db, 0x5875da6bf30f1447, 0x4e1af5271d31b090 }, + { 0x08b8c1f97f92939b, -0x41988e342bbb5492, 0x22e5646399bb8017, 0x7b6dd61eb772a955 } + }, + { + { 0x5730abf9ab01d2c7, 0x16fb76dc40143b18, -0x7993419a5f344d7f, 0x53fa9b659bff6afe }, + { -0x48523e17af0cc26e, 0x7998fa4f608cd5cf, -0x5269d2427203a425, 0x703e9bceaf1d2f4f }, + { 0x6c14c8e994885455, -0x7bc5a2999a512b1b, 0x181bb73ebcd65af1, 0x398d93e5c4c61f50 } + }, + { + { -0x3c78839f2d181c0e, 0x3b34aaa030828bb1, 0x283e26e7739ef138, 0x699c9c9002c30577 }, + { 0x1c4bd16733e248f3, -0x4261ed78ea40f5a1, -0x2bc0730f5ef4fc8a, 0x53b09b5ddf191b13 }, + { -0x0cf958dca6b90e34, -0x6de8e74a331a2683, 0x28cdd24781b4e975, 0x51caf30c6fcdd907 } + }, + { + { 0x737af99a18ac54c7, -0x6fcc87233ae34cf1, 0x2b89bc334ce10cc7, 0x12ae29c189f8e99a }, + { -0x59f458bd898b1ff6, 0x630e8570a17a7bf3, 0x3758563dcf3324cc, 0x5504aa292383fdaa }, + { -0x56613f34e0f2fe31, 0x0dd1efcc3a34f7ae, 0x55ca7521d09c4e22, 0x5fd14fe958eba5ea } + }, + { + { 0x3c42fe5ebf93cb8e, -0x412057aec92ba9a1, -0x1f0f7a6177bddf18, 0x7dd73f960725d128 }, + { -0x4a23d220d7ba54d4, 0x069491b10a7fe993, 0x4daaf3d64002e346, 0x093ff26e586474d1 }, + { -0x4ef2db0197fa67d7, 0x75730672dbaf23e5, 0x1367253ab457ac29, 0x2f59bcbc86b470a4 } + }, + { + { 0x7041d560b691c301, -0x7adfe4c0522818e2, 0x16c2e16311335585, 0x2aa55e3d010828b1 }, + { -0x7c7b82bd66e8eca1, -0x52e46ee0a982fc29, 0x7e7748d9be77aad1, 0x5458b42e2e51af4a }, + { -0x12ae6d19f3f8bbb1, 0x42c54e2d74421d10, 0x352b4c82fdb5c864, 0x13e9004a8a768664 } + }, +}, +{ + { + { 0x1e6284c5806b467c, -0x3a09668418a29f85, -0x749826a74c872d9e, 0x3d88d66a81cd8b70 }, + { -0x344a4aaa93fcd401, -0x208e6e48d6d685c6, -0x3e008cd952127e45, 0x71ade8bb68be03f5 }, + { -0x7489856cdfb12877, 0x762fcacb9fa0ae2a, 0x771febcc6dce4887, 0x343062158ff05fb3 } + }, + { + { -0x031de6f8d584ce4c, 0x4d7adc75aa578016, 0x0ec276a687479324, 0x6d6d9d5d1fda4beb }, + { -0x1fa25e581e0a40b7, 0x26457d6dd4736092, 0x77dcb07773cc32f6, 0x0a5d94969cdd5fcd }, + { 0x22b1a58ae9b08183, -0x026a2f8e3ea3c775, -0x567edc897af5fae9, 0x33384cbabb7f335e } + }, + { + { 0x33bc627a26218b8d, -0x157f4de03857f39f, -0x6ba74ed4e8c1611a, 0x076247be0e2f3059 }, + { 0x3c6fa2680ca2c7b5, 0x1b5082046fb64fda, -0x14accb63abce2922, 0x5278b38f6b879c89 }, + { 0x52e105f61416375a, -0x136850c97a54145c, 0x26e6b50623a67c36, 0x5cf0e856f3d4fb01 } + }, + { + { -0x415131cec24cbd58, -0x345c9ca47bd24812, -0x177399df7e80ec11, 0x1b9438aa4e76d5c6 }, + { -0x0936978ce517354c, 0x5e20741ecb4f92c5, 0x2da53be58ccdbc3e, 0x2dddfea269970df7 }, + { -0x75af8881e990fce6, 0x067b39f10fb7a328, 0x1925c9a6010fbd76, 0x6df9b575cc740905 } + }, + { + { -0x13203ca4b73521bf, 0x6a88471fb2328270, 0x740a4a2440a01b6a, 0x471e5796003b5f29 }, + { 0x42c1192927f6bdcf, -0x706e6e85bfc29e36, -0x23e3a5997461e09f, 0x1596047804ec0f8d }, + { -0x2569444c5312c854, 0x7a2423b5e9208cea, 0x24cc5c3038aebae2, 0x50c356afdc5dae2f } + }, + { + { -0x30126320e4ce469c, -0x0b79567a735ae50d, 0x14897265ea8c1f84, 0x784a53dd932acc00 }, + { 0x09dcbf4341c30318, -0x1145f9ee7ce7e232, -0x3e863f3123e1d65f, 0x1dbf7b89073f35b0 }, + { 0x2d99f9df14fc4920, 0x76ccb60cc4499fe5, -0x5becd3441a30fffd, 0x3f93d82354f000ea } + }, + { + { -0x1553ed2e861eb688, -0x006dc00c441400a2, 0x4af663e40663ce27, 0x0fd381a811a5f5ff }, + { -0x7e7c189761fb317b, 0x678fb71e04465341, -0x526dfa7099771254, 0x5da350d3532b099a }, + { -0x0da953135bc920ac, 0x108b6168ae69d6e8, 0x20d986cb6b5d036c, 0x655957b9fee2af50 } + }, + { + { -0x423ebf642ffd2f54, 0x66660245b5ccd9a6, -0x7dce823b05217a14, 0x02fe934b6ad7df0d }, + { -0x51574f8056fdfcf1, -0x077389950b9c2ebd, 0x15b083663c787a60, 0x08eab1148267a4a8 }, + { -0x10a30eff3048158c, 0x22897633a1cb42ac, -0x2b31f3ab310d7a1e, 0x30408c048a146a55 } + }, +}, +{ + { + { -0x44d1ff36e6c47881, -0x131c576f1f23af95, -0x130c483fc9219b61, 0x5f46040898de9e1a }, + { 0x739d8845832fcedb, -0x05c729365194079d, 0x32bc0dcab74ffef7, 0x73937e8814bce45e }, + { -0x46fc8ee9d6840b73, -0x562ec4dd2b0f97cc, -0x1e68eaa8b969423a, 0x2cf8a4e891d5e835 } + }, + { + { 0x2cb5487e17d06ba2, 0x24d2381c3950196b, -0x289a637e7a6875d0, 0x7a6f7f2891d6a4f6 }, + { 0x6d93fd8707110f67, -0x22b3f62c83c74ab7, 0x7cb16a4cc2736a86, 0x2049bd6e58252a09 }, + { 0x7d09fd8d6a9aef49, -0x0f119f41a4c246f5, 0x4c21b52c519ebfd4, 0x6011aadfc545941d } + }, + { + { 0x63ded0c802cbf890, -0x042f6735f2009556, 0x624d0afdb9b6ed99, 0x69ce18b779340b1e }, + { 0x5f67926dcf95f83c, 0x7c7e856171289071, -0x295e180c667085a5, 0x6fc5cc1b0b62f9e0 }, + { -0x2e10aad74d678635, -0x22e551c32b816f6e, 0x127e0442189f2352, 0x15596b3ae57101f1 } + }, + { + { 0x09ff31167e5124ca, 0x0be4158bd9c745df, 0x292b7d227ef556e5, 0x3aa4e241afb6d138 }, + { 0x462739d23f9179a2, -0x007cedce68292231, 0x1307deb553f2148a, 0x0d2237687b5f4dda }, + { 0x2cc138bf2a3305f5, 0x48583f8fa2e926c3, 0x083ab1a25549d2eb, 0x32fcaa6e4687a36c } + }, + { + { 0x3207a4732787ccdf, 0x17e31908f213e3f8, -0x2a4d132809f269b2, 0x746f6336c2600be9 }, + { 0x7bc56e8dc57d9af5, 0x3e0bd2ed9df0bdf2, -0x553feb21dd101b5d, 0x4627e9cefebd6a5c }, + { 0x3f4af345ab6c971c, -0x1d77148d66bc8ce1, 0x33596a8a0344186d, 0x7b4917007ed66293 } + }, + { + { 0x54341b28dd53a2dd, -0x55e86fa420bd03c1, 0x0ff592d94dd2f8f4, 0x1d03620fe08cd37d }, + { 0x2d85fb5cab84b064, 0x497810d289f3bc14, 0x476adc447b15ce0c, 0x122ba376f844fd7b }, + { -0x3dfdcd325d4b1aac, -0x612f02bdeea2e781, 0x2eabb4be7dd479d9, 0x02c70bf52b68ec4c } + }, + { + { -0x531acd40ba728d1f, 0x5be768e07cb73cb5, 0x56cf7d94ee8bbde7, 0x6b0697e3feb43a03 }, + { -0x5d7813b4a2f4d045, 0x415c5790074882ca, -0x1fbb59e13e2f7ea4, 0x26334f0a409ef5e0 }, + { -0x49370fb5209d5c40, 0x3ef000ef076da45d, -0x636346a7b60f2d57, 0x1cc37f43441b2fae } + }, + { + { -0x2899a90e36315147, 0x1c5b15f818e5656a, 0x26e72832844c2334, 0x3a346f772f196838 }, + { 0x508f565a5cc7324f, -0x2f9e3b3f1af956de, -0x04e75424a3ba53e7, 0x6c6809c10380314a }, + { -0x2d2aaeed1d259538, -0x1642fcce4e17ae13, -0x69f8b92271398d9e, 0x05911b9f6ef7c5d0 } + }, +}, +{ + { + { 0x01c18980c5fe9f94, -0x329a98968e902a38, -0x7e9fba3c2e6a5f7a, 0x6e2b7f3266cc7982 }, + { -0x162328a949c800d3, -0x13b3cb7036780f3c, -0x312a6d7a0c043849, 0x3305354793e1ea87 }, + { -0x337fdb97083ca971, -0x6216457de668b34d, -0x5448dd634a47eca0, 0x44e2017a6fbeba62 } + }, + { + { -0x7807d30c49359133, 0x580f893e18f4a0c2, 0x058930072604e557, 0x6cab6ac256d19c1d }, + { -0x3b3d58bcab25488c, -0x71a2b3c3b150fce6, -0x4893dc2dbd7c70e9, 0x749a098f68dce4ea }, + { -0x23201f5fd33e21a0, 0x032665ff51c5575b, 0x2c0c32f1073abeeb, 0x6a882014cd7b8606 } + }, + { + { -0x2eee2e8350b01492, 0x050bba42b33aa4a3, 0x17514c3ceeb46c30, 0x54bedb8b1bc27d75 }, + { -0x5ad56d015b8b804b, -0x23ed5bb6e05a5477, -0x27d256b447b85b32, 0x4d77edce9512cc4e }, + { 0x77c8e14577e2189c, -0x5c1b909500663bbb, 0x3144dfc86d335343, 0x3a96559e7c4216a9 } + }, + { + { 0x4493896880baaa52, 0x4c98afc4f285940e, -0x10b558645babb74a, 0x5278c510a57aae7f }, + { 0x12550d37f42ad2ee, -0x74871ffb675e040b, 0x5d53078233894cb2, 0x02c84e4e3e498d0c }, + { -0x5ab22f8bd6b3f46c, -0x0aa2b94720e7004a, -0x0f90133a72517c9a, 0x588657668190d165 } + }, + { + { -0x40a7cb0fc21da33d, -0x47783751297eab6a, 0x5105221a9481e892, 0x6760ed19f7723f93 }, + { -0x2b88edcee5108ee9, 0x50343101229e92c7, 0x7a95e1849d159b97, 0x2449959b8b5d29c9 }, + { 0x669ba3b7ac35e160, 0x2eccf73fba842056, 0x1aec1f17c0804f07, 0x0d96bc031856f4e7 } + }, + { + { -0x4e2acb4f338afa1f, 0x32cd003416c35288, -0x34c95a7ff89d3d63, 0x5bfe69b9237a0bf8 }, + { 0x3318be7775c52d82, 0x4cb764b554d0aab9, -0x5430c2d83388c26f, 0x3bf4d1848123288a }, + { 0x183eab7e78a151ab, -0x44166f3666f6c89d, -0x008e8291b5381ccb, 0x4c5cddb325f39f88 } + }, + { + { 0x57750967e7a9f902, 0x2c37fdfc4f5b467e, -0x4d9e99c5ce8845ba, 0x3a375e78dc2d532b }, + { -0x3f0948b29e6f5915, 0x20ea81a42db8f4e4, -0x5742908268cea8a0, 0x33b1d60262ac7c21 }, + { -0x7ebe18d0d2b22216, -0x191501679d39f838, 0x23c28458573cafd0, 0x46b9476f4ff97346 } + }, + { + { 0x1215505c0d58359f, 0x2a2013c7fc28c46b, 0x24a0a1af89ea664e, 0x4400b638a1130e1f }, + { 0x0c1ffea44f901e5c, 0x2b0b6fb72184b782, -0x1a78006efeeb2478, 0x37130f364785a142 }, + { 0x3a01b76496ed19c3, 0x31e00ab0ed327230, 0x520a885783ca15b1, 0x06aab9875accbec7 } + }, +}, +{ + { + { 0x5349acf3512eeaef, 0x20c141d31cc1cb49, 0x24180c07a99a688d, 0x555ef9d1c64b2d17 }, + { -0x3ecc667c0a20f145, -0x3f0c8a70aed3b354, 0x2cf1130a0bb398e1, 0x6b3cecf9aa270c62 }, + { 0x36a770ba3b73bd08, 0x624aef08a3afbf0c, 0x5737ff98b40946f2, 0x675f4de13381749d } + }, + { + { -0x5ed00926c4254ce3, 0x0725d80f9d652dfe, 0x019c4ff39abe9487, 0x60f450b882cd3c43 }, + { 0x0e2c52036b1782fc, 0x64816c816cad83b4, -0x2f234226969bf8c2, 0x13d99df70164c520 }, + { 0x014b5ec321e5c0ca, 0x4fcb69c9d719bfa2, 0x4e5f1c18750023a0, 0x1c06de9e55edac80 } + }, + { + { -0x002ad4bf00929656, 0x34530b18dc4049bb, 0x5e4a5c2fa34d9897, 0x78096f8e7d32ba2d }, + { -0x66f085295cc13b1e, 0x6608f938be2ee08e, -0x635ebc3a9cd7baeb, 0x4cf38a1fec2db60d }, + { -0x5f55559af205a319, -0x063b61d5b74ab874, 0x4f09cc7d7003725b, 0x373cad3a26091abe } + }, + { + { -0x0e41570476224453, 0x3bcb2cbc61aeaecb, -0x70a75844e0647263, 0x21547eda5112a686 }, + { -0x4d6b9cb27d360a84, 0x1fcbfde124934536, -0x6163b24cbe7324a6, 0x0040f3d9454419fc }, + { -0x210216c602a6792d, -0x0bd8d376aef5c7f4, -0x48d45bf844cee647, 0x63550a334a254df4 } + }, + { + { -0x6445a7ba8dab84b7, -0x0cfa39051d3bf720, 0x60e8fa69c734f18d, 0x39a92bafaa7d767a }, + { 0x6507d6edb569cf37, 0x178429b00ca52ee1, -0x1583ff6f149429a3, 0x3eea62c7daf78f51 }, + { -0x62db38ec196cd8b2, 0x5f63857768dbd375, 0x70525560eb8ab39a, 0x68436a0665c9c4cd } + }, + { + { 0x1e56d317e820107c, -0x3ad997bb7bf5169b, -0x3e1f5e39cdf00386, 0x5373669c91611472 }, + { -0x43fdca17dfd0c0d9, -0x38a3ff1d9b068a50, -0x6e5b162a5c73dbea, 0x17b6e7f68ab789f9 }, + { 0x5d2814ab9a0e5257, -0x6f70df7b36354c04, -0x50350a77a4d2e136, 0x1cb4b5a678f87d11 } + }, + { + { 0x6b74aa62a2a007e7, -0x0cee1f4f0f8e384f, 0x5707e438000be223, 0x2dc0fd2d82ef6eac }, + { -0x499b3f94c6b50394, 0x0c88de2498da5fb1, 0x4f8d03164bcad834, 0x330bca78de7434a2 }, + { -0x67d1007beee68bb2, -0x0696a169d4f8b8dc, -0x3a753eb04036ac05, 0x3c31be1b369f1cf5 } + }, + { + { -0x3e97436c0634bd8e, -0x51478ee038312468, 0x7f0e52aa34ac8d7a, 0x41cec1097e7d55bb }, + { -0x4f0b79b2f76b7512, 0x07dc19ee91ba1c6f, 0x7975cdaea6aca158, 0x330b61134262d4bb }, + { -0x0869e6285d927f76, -0x44e02b61e261ea93, 0x73d7c36cdba1df27, 0x26b44cd91f28777d } + }, +}, +{ + { + { -0x50bb7bd24fd7a0c9, -0x78ace76fb8103721, -0x6a8b1f6e07df6866, 0x0e378d6069615579 }, + { 0x300a9035393aa6d8, 0x2b501131a12bb1cd, 0x7b1ff677f093c222, 0x4309c1f8cab82bad }, + { -0x26056e8e7cf8a5ab, 0x4bdb5ad26b009fdc, 0x7829ad2cd63def0e, 0x078fc54975fd3877 } + }, + { + { -0x1dffb4a447cc5676, 0x44775dec2d4c3330, 0x3aa244067eace913, 0x272630e3d58e00a9 }, + { -0x782042ebd77870d3, 0x134636dd1e9421a1, 0x4f17c951257341a3, 0x5df98d4bad296cb8 }, + { -0x0c98702f1336f4ac, -0x0ffeba64edfbca67, 0x26725fbc3758b89b, 0x4325e4aa73a719ae } + }, + { + { -0x12db9d6530960a63, 0x2a4a1ccedd5abbf4, 0x3535ca1f56b2d67b, 0x5d8c68d043b1b42d }, + { 0x657dc6ef433c3493, 0x65375e9f80dbf8c3, 0x47fd2d465b372dae, 0x4966ab79796e7947 }, + { -0x11ccd2b21c4bd4f6, -0x27b1a5d4e95b9fe4, 0x78243877078ba3e4, 0x77ed1eb4184ee437 } + }, + { + { 0x185d43f89e92ed1a, -0x4fb5e11501b8e63a, 0x499fbe88a6f03f4f, 0x5d8b0d2f3c859bdd }, + { -0x402b1ec0dfe7c660, -0x5110001dc1c20e9f, -0x49a4fb0f94a2e01d, 0x52e085fb2b62fbc0 }, + { 0x124079eaa54cf2ba, -0x28db9a14ffe4d919, 0x6843bcfdc97af7fd, 0x0524b42b55eacd02 } + }, + { + { -0x43e72352647d6154, 0x23ae7d28b5f579d0, -0x3cb9edd596c7bdcd, 0x1a6110b2e7d4ac89 }, + { -0x02f2a2411babb850, 0x6cec351a092005ee, -0x665b87bba98a8635, 0x59d242a216e7fa45 }, + { 0x4f833f6ae66997ac, 0x6849762a361839a4, 0x6985dec1970ab525, 0x53045e89dcb1f546 } + }, + { + { -0x7b25c32172ba01ee, -0x42bd3de71bbb1d2e, -0x57ae6987e081ca68, 0x7642c93f5616e2b2 }, + { -0x34744cb928acac25, -0x03034db451aee1de, -0x345b72bf2af51911, 0x26e3bae5f4f7cb5d }, + { 0x2323daa74595f8e4, -0x219773747a85414c, 0x3fc48e961c59326e, 0x0b2e73ca15c9b8ba } + }, + { + { 0x0e3fbfaf79c03a55, 0x3077af054cbb5acf, -0x2a3aadba24c21c61, 0x015e68c1476a4af7 }, + { -0x2944bbd73e80afda, -0x614d8ddc04a56359, -0x1c845afce6e639bc, 0x21ce380db59a6602 }, + { -0x3e2ad7addff995c8, -0x6a9fc1adca8f510d, -0x7cd9a658dd9475b3, 0x5dd689091f8eedc9 } + }, + { + { 0x1d022591a5313084, -0x35d2b55129d8f78e, -0x795ed47ad0f402e0, 0x56e6c439ad7da748 }, + { -0x34537b21402c37aa, 0x1624c348b35ff244, -0x48077235a26352f9, 0x3b0e574da2c2ebe8 }, + { -0x38fb00b6bd42451a, 0x5e21ade2b2de1f79, -0x16a24c0ca9ad0528, 0x0822b5378f08ebc1 } + }, +}, +{ + { + { -0x1e480d6c9d8cfc7d, 0x4b5279ffebca8a2c, -0x25038875402becec, 0x7deb10149c72610f }, + { 0x51f048478f387475, -0x4da2430b634134c4, -0x6554edbb2660dfab, 0x2c709e6c1c10a5d6 }, + { -0x349d509578991186, 0x66cbec045553cd0e, 0x588001380f0be4b5, 0x08e68e9ff62ce2ea } + }, + { + { 0x2f2d09d50ab8f2f9, -0x5346de723aa6dc21, 0x4a8f342673766cb9, 0x4cb13bd738f719f5 }, + { 0x34ad500a4bc130ad, -0x72c724b6c2f42b64, -0x5da3c267aff57642, 0x2f1f3f87eeba3b09 }, + { -0x087b738a1aea49b6, -0x5a6afe4524b56fc8, -0x3df2cec0c08ae4b0, 0x19a1e353c0ae2ee8 } + }, + { + { -0x4bde8d322a694243, -0x6c1fbabc671103c0, -0x604eacb84bbef64b, 0x736bd3990266ae34 }, + { 0x7d1c7560bafa05c3, -0x4c1e5f5f391aa19f, -0x1cad68e73f299b8d, 0x41546b11c20c3486 }, + { -0x7aacd2af6ccb4c4c, 0x46fd114b60816573, -0x33a0a0cfbda37c8b, 0x412295a2b87fab5c } + }, + { + { 0x2e655261e293eac6, -0x7ba56dfcdecc5325, 0x460975cb7900996b, 0x0760bb8d195add80 }, + { 0x19c99b88f57ed6e9, 0x5393cb266df8c825, 0x5cee3213b30ad273, 0x14e153ebb52d2e34 }, + { 0x413e1a17cde6818a, 0x57156da9ed69a084, 0x2cbf268f46caccb1, 0x6b34be9bc33ac5f2 } + }, + { + { 0x11fc69656571f2d3, -0x393617baacf18c86, -0x1cc5185d2b01afcb, 0x01b9c7b62e6dd30b }, + { -0x0c20d09bc5873f4e, 0x4c3e971ef22e027c, -0x1382e3a1b63e4a5d, 0x2012c18f0922dd2d }, + { -0x77f4aa1aa53762d7, 0x1483241f45a0a763, 0x3d36efdfc2e76c1f, 0x08af5b784e4bade8 } + }, + { + { -0x1d8ceb2d7633d3b5, 0x4be4bd11a287178d, 0x18d528d6fa3364ce, 0x6423c1d5afd9826e }, + { 0x283499dc881f2533, -0x62fada25886cdc4a, -0x7685220498cbbe0c, 0x32b79d71163a168d }, + { -0x337a072612034c96, 0x22bcc28f3746e5f9, -0x1b621cc7061a2c33, 0x480a5efbc13e2dcc } + }, + { + { -0x499eb31bbd31dde1, 0x6e199dcc4c053928, 0x663fb4a4dc1cbe03, 0x24b31d47691c8e06 }, + { 0x0b51e70b01622071, 0x06b505cf8b1dafc5, 0x2c6bb061ef5aabcd, 0x47aa27600cb7bf31 }, + { 0x2a541eedc015f8c3, 0x11a4fe7e7c693f7c, -0x0f5099ecb15d872a, 0x545b585d14dda094 } + }, + { + { 0x6204e4d0e3b321e1, 0x3baa637a28ff1e95, 0x0b0ccffd5b99bd9e, 0x4d22dc3e64c8d071 }, + { 0x67bf275ea0d43a0f, -0x521971cbf7641142, 0x4289134cd479e72e, 0x0f62f9c332ba5454 }, + { -0x034b9a7629c4a0c7, 0x5cae6a3f57cbcf61, -0x01453d2d6ac505fb, 0x1c0fa01a36371436 } + }, +}, +{ + { + { -0x3ee11a17ab3ac052, 0x6a0b06c12b4f3ff4, 0x33540f80e0b67a72, 0x15f18fc3cd07e3ef }, + { -0x18ab8bb64383296e, 0x0f9abeaae6f73ddf, 0x4af01ca700837e29, 0x63ab1b5d3f1bc183 }, + { 0x32750763b028f48c, 0x06020740556a065f, -0x2ac427ed3cb6a4a8, 0x08706c9b865f508d } + }, + { + { -0x3366e4bec74bedba, 0x243b9c526f9ac26b, -0x4610b6b248345443, 0x5fba433dd082ed00 }, + { -0x0c835d54c2cbc201, 0x1a8c6a2d80abc617, -0x71b61fca2b330036, 0x48b46beebaa1d1b9 }, + { -0x63b61caa366be530, -0x468cb5218bb6707c, 0x41c3fed066663e5c, 0x0ecfedf8e8e710b3 } + }, + { + { 0x744f7463e9403762, -0x0865721172033637, 0x163a649655e4cde3, 0x3b61788db284f435 }, + { 0x76430f9f9cd470d9, -0x49d533645bd09ff8, 0x1898297c59adad5e, 0x7789dd2db78c5080 }, + { -0x4dddd7e6f291094e, -0x56b5994db931b406, 0x46c1a77a4f0b6cc7, 0x4236ccffeb7338cf } + }, + { + { 0x3bd82dbfda777df6, 0x71b177cc0b98369e, 0x1d0e8463850c3699, 0x5a71945b48e2d1f1 }, + { -0x7b68bfb2f2aa1d8c, 0x6c6663d9c4ad2b53, -0x13d04f265256a8cc, 0x2617e120cdb8f73c }, + { 0x6f203dd5405b4b42, 0x327ec60410b24509, -0x63cb8dcf53d577ba, 0x77de29fc11ffeb6a } + }, + { + { -0x7ca1ec7013312d36, -0x736150ec1569c466, -0x36a0403f4de9f15a, 0x575e66f3ad877892 }, + { -0x4f53a8367c488758, 0x53cdcca9d7fe912c, 0x61c2b854ff1f59dc, 0x3a1a2cf0f0de7dac }, + { -0x667fc5d8377034c6, 0x345a6789275ec0b0, 0x459789d0ff6c2be5, 0x62f882651e70a8b2 } + }, + { + { 0x6d822986698a19e0, -0x2367de1e8b28758f, 0x41a85f31f6cb1f47, 0x352721c2bcda9c51 }, + { 0x085ae2c759ff1be4, 0x149145c93b0e40b7, -0x3b981805800d8c87, 0x4eeecf0ad5c73a95 }, + { 0x48329952213fc985, 0x1087cf0d368a1746, -0x71ad9e4e993ea55b, 0x2d5b2d842ed24c21 } + }, + { + { 0x5eb7d13d196ac533, 0x377234ecdb80be2b, -0x1ebb3003830a51dc, 0x5226bcf9c441acec }, + { 0x02cfebd9ebd3ded1, -0x2ba4de88c6fde68c, 0x7576f813fe30a1b7, 0x5691b6f9a34ef6c2 }, + { 0x79ee6c7223e5b547, 0x6f5f50768330d679, -0x128c1e1692752317, 0x27c3da1e1d8ccc03 } + }, + { + { 0x28302e71630ef9f6, -0x3d2b5dfcd49b3120, 0x090820304b6292be, 0x5fca747aa82adf18 }, + { 0x7eb9efb23fe24c74, 0x3e50f49f1651be01, 0x3ea732dc21858dea, 0x17377bd75bb810f9 }, + { 0x232a03c35c258ea5, -0x790dc5d39434f30f, 0x3dad8d0d2e442166, 0x04a8933cab76862b } + }, +}, +{ + { + { 0x69082b0e8c936a50, -0x06365fca3e253a4a, 0x6fb73e54c4dfb634, 0x4005419b1d2bc140 }, + { -0x2d39fb49dd6bc201, -0x43734131bb304c60, 0x5d254ff397808678, 0x0fa3614f3b1ca6bf }, + { -0x5ffc014246417d10, 0x2089c1af3a44ac90, -0x07b6606ee6ab0572, 0x1fba218aef40ab42 } + }, + { + { 0x4f3e57043e7b0194, -0x57e2c111f7255081, -0x37c639546623210f, 0x6c535d13ff7761d5 }, + { -0x54ab6bb705370ac2, -0x7e0917658459c8bf, 0x74fd6c7d6c2b5e01, 0x392e3acaa8c86e42 }, + { 0x4cbd34e93e8a35af, 0x2e0781445887e816, 0x19319c76f29ab0ab, 0x25e17fe4d50ac13b } + }, + { + { -0x6ea0800a890ede59, -0x3cb5cdd8d032781d, -0x3345d021b2e41ada, 0x6bba828f8969899b }, + { 0x0a289bd71e04f676, 0x208e1c52d6420f95, 0x5186d8b034691fab, 0x255751442a9fb351 }, + { -0x1d2e43996f01c6ff, 0x4cb54a18a0997ad5, -0x68e296eb507b9f2c, 0x559d504f7f6b7be4 } + }, + { + { -0x63b76e18092d9903, 0x0744a19b0307781b, -0x77c770e29f9e1dc5, 0x123ea6a3354bd50e }, + { -0x588c7c874c14ab2b, 0x1d69d366a5553c7c, 0x0a26cf62f92800ba, 0x01ab12d5807e3217 }, + { 0x118d189041e32d96, -0x46121c3d27cea7b8, 0x1eab4271d83245d9, 0x4a3961e2c918a154 } + }, + { + { 0x0327d644f3233f1e, 0x499a260e34fcf016, -0x7c4a58e90d254687, 0x68aceead9bd4111f }, + { 0x71dc3be0f8e6bba0, -0x293107cb81001cf6, -0x566dbda01ec5b896, 0x2cd6bce3fb1db763 }, + { 0x38b4c90ef3d7c210, 0x308e6e24b7ad040c, 0x3860d9f1b7e73e23, 0x595760d5b508f597 } + }, + { + { -0x77d5341402fdd870, -0x7650ccfa3beea8a0, 0x65f492e37d3473f4, 0x2cb2c5df54515a2b }, + { 0x6129bfe104aa6397, -0x7069fff75b580335, 0x3f8bc0897d909458, 0x709fa43edcb291a9 }, + { -0x14f5a2739c02d536, -0x2dd43e99d196b101, 0x2723f36ef8cbb03a, 0x70f029ecf0c8131f } + }, + { + { 0x2a6aafaa5e10b0b9, 0x78f0a370ef041aa9, 0x773efb77aa3ad61f, 0x44eca5a2a74bd9e1 }, + { 0x461307b32eed3e33, -0x51fbd0cc5baa7e19, -0x36bbb62ce6a0fc9a, 0x0b7d5d8a6c314858 }, + { 0x25d448327b95d543, 0x70d38300a3340f1d, -0x21e3ace39f1e3ad5, 0x272224512c7de9e4 } + }, + { + { -0x40844475bd568a04, -0x73a3c68869525ca8, -0x1d803890321255b8, 0x19735fd7f6bc20a6 }, + { 0x1abc92af49c5342e, -0x001127ee4d190530, -0x105d73720337b1d7, 0x11b5df18a44cc543 }, + { -0x1c546f2fbd37bd9a, -0x147b71f080e6ab82, 0x2503a1d065a497b9, 0x0fef911191df895f } + }, +}, +{ + { + { 0x6ab5dcb85b1c16b7, -0x6b3f0317c384d85b, -0x5b4ee3e58caae842, 0x499238d0ba0eafaa }, + { -0x4eaf835e54e39147, -0x42bb70c1e949784d, 0x3455fb7f2c7a91ab, 0x7579229e2f2adec1 }, + { -0x130b91ad854574a9, 0x15a08c478bd1647b, 0x7af1c6a65f706fef, 0x6345fa78f03a30d5 } + }, + { + { -0x6c2c341642270f5c, -0x24ead3e402e88cfe, 0x7dbddc6d7f17a875, 0x3e1a71cc8f426efe }, + { -0x20fd06a0efea185f, 0x790ec41da9b40263, 0x4d3a0ea133ea1107, 0x54f70be7e33af8c9 }, + { -0x37c35c1c6f45429e, -0x7f121c98fd6e37cd, -0x377fc7332c86ff3c, 0x2c5fc0231ec31fa1 } + }, + { + { -0x3bdd1b2efdba919b, -0x78beb53e352b846f, 0x1592e2bba2b6ffdd, 0x75d9d2bff5c2100f }, + { -0x01456ee8e8fc74b1, -0x1aedc8de3621107f, 0x1c97e4e75d0d8834, 0x68afae7a23dc3bc6 }, + { 0x5bd9b4763626e81c, -0x766996c9435fd123, 0x0a41193d61f077b3, 0x3097a24200ce5471 } + }, + { + { -0x5e9d18db996a3b7a, 0x131d633435a89607, 0x30521561a0d12a37, 0x56704bada6afb363 }, + { 0x57427734c7f8b84c, -0x0ebe5ec1fe4d8f17, 0x02d1adfeb4e564a6, 0x4bb23d92ce83bd48 }, + { -0x5093b558ad06ed47, 0x5e665f6cd86770c8, 0x4c35ac83a3c8cd58, 0x2b7a29c010a58a7e } + }, + { + { 0x33810a23bf00086e, -0x50316da118c90084, 0x3d60e670e24922d4, 0x11ce9e714f96061b }, + { -0x3bff80882f3e313d, -0x72efdf49453b6d08, 0x32ec29d57e69daaf, 0x599408759d95fce0 }, + { 0x219ef713d815bac1, -0x0ebeb9a2b7a41da4, 0x6d5447cc4e513c51, 0x174926be5ef44393 } + }, + { + { 0x3ef5d41593ea022e, 0x5cbcc1a20ed0eed6, -0x702db130f8c7d374, 0x6fa42ead06d8e1ad }, + { -0x4a214d0603a42a45, -0x6d2558d51e27ef1f, -0x503b302348d5e3a7, 0x497d78813fc22a24 }, + { -0x1d897db5e08cc8e1, 0x7f7cf01c4f5b6736, 0x7e201fe304fa46e7, 0x785a36a357808c96 } + }, + { + { 0x070442985d517bc3, 0x6acd56c7ae653678, 0x00a27983985a7763, 0x5167effae512662b }, + { -0x7da042029cfeb2d5, -0x37adc9639358a875, 0x5b2fcd285c0b5df0, 0x12ab214c58048c8f }, + { -0x42b1561ef0ac3b4a, 0x1673dc5f8ac91a14, -0x5707e5b1d533e546, 0x33a92a7924332a25 } + }, + { + { 0x7ba95ba0218f2ada, -0x300bdd78ccf04636, -0x2525b692a93926f9, 0x5380c296f4beee54 }, + { -0x622e0b66d86693fe, 0x0cb3b058e04d1752, 0x1f7e88967fd02c3e, 0x2f964268cb8b3eb1 }, + { -0x62b0d8fb997672f6, 0x3d0987990aff3f7a, -0x2f610c9d982545bb, 0x7761455e7b1c669c } + }, +}, +}; +#elif defined(CURVED25519_ASM_32BIT) +static const ge_precomp base[64][8] = { +{ + { + { -0x0a73c47b, 0x2fbc93c6, -0x0473f1e7, -0x306cd23a, 0x643d42c2, 0x270b4898, 0x33d4ba65, 0x07cf9d3a }, + { -0x28bf6ec2, -0x62efc6fb, -0x2ebf414d, -0x02c660fb, 0x688f8a09, -0x5a3e7bcc, -0x6707ed99, 0x44fd2f92 }, + { 0x4b6fbb59, -0x2442ea99, -0x115d5a16, 0x41e13f00, -0x36a83906, -0x322b62e4, -0x50e91336, 0x4f0ebe1f } + }, + { + { -0x6cc38e29, -0x6ddb1804, 0x7a0ff5b5, -0x60b9626a, -0x1e29f8fe, 0x5aa69a65, -0x5782d1d2, 0x590c063f }, + { 0x42b4d5a8, -0x75665aa0, 0x4e60acf6, -0x70d47ef4, -0x4e91c856, -0x1f61dc95, 0x69c92555, 0x6bb595a6 }, + { -0x252c97fe, 0x6e347eaa, -0x7c11b7fb, -0x450ca66d, -0x19f897da, 0x3bcabe10, 0x165ed1b8, 0x49314f0a } + }, + { + { 0x4cee9730, -0x50da4f58, -0x1779b476, 0x025a8430, -0x60fe98ce, -0x3ee4affe, -0x657f070c, 0x7a164e1b }, + { -0x5b032d9b, 0x56611fe8, -0x1a3e4583, 0x3bd353fd, 0x214bd6bd, -0x7ece0ce6, 0x555bda62, 0x2ab91587 }, + { -0x0e98b7cc, -0x640dee0c, -0x09d2076b, -0x47b194e9, 0x5b722a4e, -0x282190f9, 0x63bb2a21, 0x549a04b9 } + }, + { + { -0x7103f661, 0x287351b9, 0x7dfd2538, 0x6765c6f4, -0x04f56d9b, -0x35cb72c3, 0x21e58727, 0x680e9103 }, + { 0x056818bf, -0x6a01faf6, 0x5660faa9, 0x327e8971, 0x06a05073, -0x3c171c33, 0x7445a49a, 0x27933f4c }, + { -0x1aebd950, -0x40e1ba14, 0x6dba0f94, -0x1cd439c3, -0x7307ad40, -0x1bd68b2b, -0x4f19b3e8, 0x44f079b1 } + }, + { + { 0x08a5bb33, -0x5ded43bc, -0x38a112fe, -0x72afb73d, 0x5abfec44, -0x22e414f4, 0x46e206eb, 0x2945ccf1 }, + { -0x5bb82946, 0x7f9182c3, 0x4b2729b7, -0x2affeb2f, -0x479b5f79, -0x1cc30ee4, -0x14e4aa0d, 0x154a7e73 }, + { -0x182ffc4d, -0x37cd5e87, 0x00124d7e, 0x5f729d0a, 0x0e6d8ff3, 0x62c1d4a1, 0x38b27a98, 0x68b8ac59 } + }, + { + { 0x77157131, 0x3a0ceeeb, 0x00c8af88, -0x64d8ea77, -0x25a658ca, -0x7f9a4998, -0x5d33c743, 0x51e57bb6 }, + { 0x7b7d8ca4, 0x499806b6, 0x27d22739, 0x575be284, 0x204553b9, -0x44f7a319, -0x51be877c, 0x38b64c41 }, + { 0x689de3a4, -0x7062526f, -0x07046ec9, 0x175f2428, -0x60304678, 0x050ab532, 0x1354c09f, 0x7865dfa2 } + }, + { + { -0x6bb15c41, 0x6b1a5cd0, -0x4c623f2e, 0x7470353a, 0x28542e49, 0x71b25282, 0x283c927e, 0x461bea69 }, + { -0x55cdde4f, -0x4590d366, 0x3bba23a7, 0x6ca02153, -0x6de6d3c6, -0x621589b1, 0x2e5317e0, 0x1d6edd5d }, + { -0x54f025ca, 0x217a8aac, 0x3d3549c8, -0x5ad739ac, 0x13ab7568, 0x37d05b8b, 0x3a2cbc37, 0x233cef62 } + }, + { + { 0x04dd3e8f, 0x59b75966, -0x1d778fd4, 0x6cb30377, 0x5ed9c323, -0x4ecc639a, 0x61bce52f, 0x0915e760 }, + { -0x0c6dcb27, -0x1d58a213, -0x1e4aa707, -0x69c28980, 0x6e3c23fb, 0x2c2741ac, 0x320e01c3, 0x3a9024a1 }, + { -0x57cb5c82, -0x208217cb, 0x689857ea, -0x741e6326, 0x7167b326, 0x2c118536, -0x24102a3e, 0x589eb3d9 } + }, +}, +{ + { + { 0x2d9021f6, 0x322d04a5, 0x75c6bf9c, -0x463e60cd, 0x42d20b09, 0x587a3a43, -0x559b019f, 0x143b1cf8 }, + { 0x553e2df3, 0x7ec851ca, -0x59b7874d, -0x58ed7b35, 0x3288d1e7, -0x194a1be7, 0x5a9a8883, 0x4cf210ec }, + { -0x69753555, -0x60798383, 0x27092729, 0x5f54258e, -0x15e7f68b, -0x2f582cb5, 0x374126e1, 0x21b546a3 } + }, + { + { -0x2e7ade71, 0x490a7a45, 0x46049335, -0x65eac888, -0x33ce1e0a, 0x0060ea09, -0x0791169b, 0x7e041577 }, + { -0x5d777cbd, -0x56b007a8, 0x5313ed3c, -0x31f12baa, -0x4a40cb06, -0x0aa3c231, -0x36154c8f, 0x0a653ca5 }, + { -0x31a4980d, 0x66b2a496, -0x42a9686a, -0x00ab6d28, 0x4a592cd0, 0x503cec29, 0x0813acb2, 0x56694365 } + }, + { + { 0x1dabb69d, 0x5672f9eb, -0x5017ac04, -0x458f4acb, 0x2796d66d, 0x47ac0f75, -0x6bee8d8b, 0x32a53517 }, + { 0x26620798, -0x47e724f4, 0x606e354a, 0x5d5c31d9, 0x00a8cdc7, 0x0982fa4f, 0x4653e2d4, 0x17e12bcd }, + { -0x209b7bc9, -0x2c59bb5a, -0x77f04023, 0x703b6559, -0x52c5e55b, -0x347adac0, -0x71b39b98, 0x0900b3f7 } + }, + { + { -0x37e952cf, -0x12d7f042, -0x2719101d, 0x52d9595b, -0x0939dc0b, 0x0fe71772, 0x051e293c, 0x4314030b }, + { 0x679d651b, 0x0a851b9f, 0x033342f2, -0x1ef7349f, -0x1774cf5d, -0x29fe0a81, -0x12d228ec, 0x371f3aca }, + { -0x040f4353, -0x2a9fffa2, -0x2e78f3a2, -0x7148f0d2, -0x2f7b1960, 0x201f9033, -0x31849990, 0x4c3a5ae1 } + }, + { + { -0x36c25f23, -0x45078a1c, 0x71b9294d, -0x46cd7d59, -0x0b393ba0, -0x7f29c049, -0x15993e7f, 0x6de9c73d }, + { -0x2347056b, 0x4138a434, 0x6c96840b, -0x78f30983, 0x297be82c, -0x21c77a8c, 0x7262a55a, 0x7c814db2 }, + { -0x5fb2070e, 0x478904d5, -0x4efebd2d, -0x050451b6, 0x555d0998, -0x0937539d, 0x2f90b104, 0x5aac4a41 } + }, + { + { -0x4280aecc, 0x603a0d0a, -0x1e2c51ba, -0x7f7636ce, -0x7867429d, -0x20da6ec7, 0x74ba0235, 0x1c145cd2 }, + { 0x3ac92908, -0x39b0cd95, -0x199c1e20, 0x5551b282, 0x4a1a4b83, 0x476b35f5, 0x189f68c2, 0x1b9da3fe }, + { 0x75f3d743, 0x32e83864, 0x6ae5d9ef, 0x365b8baf, 0x385b681e, -0x7dadc74a, 0x167d65e1, 0x234929c1 } + }, + { + { 0x1d099fcf, 0x48145cc2, -0x33d7281b, 0x4535c192, 0x48247e01, -0x7f183e1b, 0x3b2973ee, 0x4a5f2874 }, + { -0x5f885218, -0x67b21355, 0x19eb389d, 0x383f77ad, 0x2954d794, -0x38139482, -0x1483c586, 0x59c77b3a }, + { 0x225ccf62, -0x2c5228db, -0x4dead3a3, -0x6ee5cc7f, 0x5b08f87d, -0x274c6053, 0x4799fe3b, 0x6f05606b } + }, + { + { -0x06e49b7d, 0x5b433149, 0x5a2cbf62, -0x524a239b, 0x632827b3, -0x78057bee, -0x54b60728, 0x60895e91 }, + { 0x177ba962, -0x6001616e, 0x0de5cae1, -0x675118e3, 0x2d831044, 0x3ff4ae94, 0x58533ac8, 0x714de12e }, + { 0x0cf86c18, -0x16130d13, 0x0735dfd4, -0x4b92f9ee, 0x04b96be7, -0x43625f68, -0x26923d95, 0x73e2e62f } + }, +}, +{ + { + { 0x632f9c1d, 0x2eccdd0e, 0x76893115, 0x51d0b696, -0x579c85a8, 0x52dfb76b, -0x5ff110c7, 0x6dd37d49 }, + { 0x49aa515e, -0x12a49cac, 0x0bc6823a, -0x579a3b61, 0x5b42d1c4, -0x7af3e017, 0x03d315b9, 0x30d76d6f }, + { 0x2106e4c7, 0x6c444417, -0x6d728097, -0x04ac2980, 0x694d3f26, -0x4b8c615c, 0x2e864bb0, 0x10c69711 } + }, + { + { -0x7ca737fb, 0x0ca62aa0, 0x7a204247, 0x6a3d4ae3, 0x3b11eddc, 0x7464d3a6, 0x550806ef, 0x03bf9baf }, + { 0x7dbe5fde, 0x6493c427, 0x19ad7ea2, 0x265d4fad, 0x46304590, 0x0e00dfc8, -0x129901f7, 0x25e61cab }, + { -0x33a799fc, 0x3f13e128, -0x4ba68b82, 0x6f5873ec, -0x33ed970b, -0x5f49c213, 0x4586e22c, 0x566d7863 } + }, + { + { -0x39a5d030, -0x5efabd7b, -0x0ce9983d, 0x6c64112a, 0x731aee58, 0x680ae240, 0x4793b22a, 0x14fba5f3 }, + { -0x633ef7cc, 0x1637a49f, -0x57643baf, -0x4371a92b, 0x7f7fd2db, 0x1cb5ec0f, 0x5ecc35d9, 0x33975bca }, + { 0x6985f7d4, 0x3cd74616, -0x3637ffa9, 0x593e5e84, 0x7b61131e, 0x2fc3f2b6, -0x7c03ad94, 0x14829cea } + }, + { + { 0x4e71ecb8, 0x21e70b2f, 0x40a477e3, -0x19a92247, -0x31e2b080, -0x409aa932, 0x535d7b7e, 0x05fc3bc4 }, + { -0x68226a3e, -0x00bc847c, -0x55b14a59, 0x6c744e30, 0x3c85e88b, -0x61f3a29f, 0x5f758173, 0x2fd9c71e }, + { 0x52afdedd, 0x24b8b3ae, -0x12c4cf31, 0x3495638c, -0x56417e6b, 0x33a4bc83, 0x5c651f04, 0x37376747 } + }, + { + { 0x14246590, 0x634095cb, 0x16c15535, -0x10edebc0, -0x76ef43a0, -0x61c7ebf4, 0x30907c8c, 0x6bf59057 }, + { 0x40d1add9, 0x2fba99fd, -0x690b2fd9, -0x4cf8e991, 0x15f03bae, 0x4363f052, 0x3b18f999, 0x1fbea56c }, + { -0x1ebea476, 0x0fa778f1, -0x453c5882, 0x06409ff7, -0x655d65b0, 0x6f52d7b8, 0x7a635a56, 0x02521cf6 } + }, + { + { 0x772f5ee4, -0x4eeb98e0, -0x69f86532, -0x17076b4f, 0x00ac824a, 0x4af8224d, -0x0832933c, 0x001753d9 }, + { 0x0a9d5294, 0x513fee0b, 0x0fdf5a66, -0x706718a4, -0x401ef832, -0x2b9e7978, 0x71382ced, 0x3fa00a7e }, + { -0x69c224cc, 0x3c69232d, -0x4b68c7a8, 0x1dde87da, -0x5f6e0d7b, -0x55282e07, -0x5fb7124a, 0x12b5fe2f } + }, + { + { -0x5290e16e, -0x20d483da, 0x504b8913, 0x4b66d323, 0x751c8bc3, -0x73bf6240, 0x0796c7b8, 0x6f7e93c2 }, + { -0x69031cb3, 0x71f0fbc4, -0x520ca413, 0x73b9826b, -0x00d73a9f, -0x2dfb8d9f, 0x6fb1206f, 0x749b76f9 }, + { -0x515951fb, 0x1f5af604, -0x411b6367, -0x3edcae0f, -0x1100949a, 0x61a808b5, 0x01e02151, 0x0fcec10f } + }, + { + { -0x3bdbb1bb, 0x3df2d29d, -0x6c2721f6, 0x2b020e74, -0x7df3deb3, 0x6cc8067e, 0x6feab90a, 0x41377916 }, + { 0x49fe1e44, 0x644d58a6, 0x31ad777e, 0x21fcaea2, -0x77802f2e, 0x02441c5a, -0x7c3aee0d, 0x4901aa71 }, + { -0x73e50710, 0x08b1b754, 0x246299b4, -0x31f08584, 0x1e06d939, -0x089f4f07, 0x726d1213, 0x41bb887b } + }, +}, +{ + { + { -0x55c6082e, -0x68267f20, 0x52c6b51c, 0x35d03842, 0x07cd55aa, 0x7d43f493, -0x48753c9e, 0x56bd36cf }, + { 0x567c49d8, -0x6d987f94, -0x3586e196, 0x066d04cc, -0x1c33c6b5, -0x5960a9bb, -0x5f87732e, 0x5c95b686 }, + { 0x0d14a954, 0x2ac519c1, -0x6b4a0570, -0x150b8b4c, -0x560785a6, -0x19507c7e, -0x78641f6c, 0x0dea6db1 } + }, + { + { -0x29578686, 0x15baeb74, -0x053be8ce, 0x7ef55cf1, 0x3c8b05c5, 0x29001f5a, 0x52eaccfb, 0x0ad7cc87 }, + { 0x7344e5ab, -0x559940ac, -0x70e4bcf7, -0x25eda778, -0x02a9b4d1, 0x5e87d2b3, 0x5483b1dd, 0x5b2c7888 }, + { 0x793408cf, 0x52151362, 0x19963d94, -0x14f0e8fd, -0x77c26b9a, -0x57cc4d06, 0x75003c78, 0x093a7fa7 } + }, + { + { 0x60a91286, -0x47169fbc, 0x7778d3de, 0x7f3fd804, -0x4075a1d3, 0x67d01e31, -0x3d849ac2, 0x7b038a06 }, + { 0x3a16d7be, -0x1aef821a, -0x650ccd31, -0x5c880024, 0x440b677f, 0x70d5bf18, -0x5b5cebfd, 0x6a252b19 }, + { -0x2c966f0d, -0x6126e62b, -0x24b1460e, 0x5213aebb, 0x4cb99135, -0x38f715fb, 0x72260e56, 0x58ded57f } + }, + { + { 0x5b0fd48b, -0x2592acda, -0x6c405678, -0x769f7dcf, 0x61d57e28, -0x287536ce, 0x3a5c8143, 0x79f2942d }, + { -0x16bec289, 0x78e79dad, -0x68d61983, -0x0da8062b, -0x1c85581a, 0x59db910e, -0x4461fc64, 0x6aa11b5b }, + { -0x49377217, -0x6825d0db, -0x530dfe97, 0x251ba7ea, -0x10b14b1c, 0x09b44f87, -0x4395825b, 0x7d90ab1b } + }, + { + { -0x694c3c69, 0x1a07a3f4, -0x70b1dace, 0x11ceaa18, -0x588ae410, 0x7d9498d5, 0x508dd8a0, 0x19ed161f }, + { -0x58fe9402, -0x6533597d, -0x0d3af493, -0x6fafa0b3, -0x331bca56, 0x6b610d5f, 0x6198ff96, 0x19a10d44 }, + { -0x78231936, 0x560a2cd6, -0x799b30b3, 0x7f3568c4, 0x22803a38, -0x78be16ae, 0x595653fc, 0x483bdab1 } + }, + { + { -0x4b257f0a, -0x2930b2f6, -0x07cf8020, -0x7db7c1bb, -0x5190625c, 0x05005269, -0x63087886, 0x1c705290 }, + { -0x78cb05b7, -0x0587f0ec, 0x360534e0, 0x106f0b70, -0x1c1cf843, 0x2210776f, -0x22195f02, 0x3286c109 }, + { -0x78b1672c, 0x32ee7de2, -0x4681f3a0, 0x14c362e9, 0x6a60a38a, 0x5781dcde, -0x558557c0, 0x217dd5ea } + }, + { + { -0x4173f138, -0x7420e047, -0x1cf5fd7e, 0x00bae7f8, -0x5293b094, 0x4963991d, 0x5df6f60a, 0x07058a6e }, + { 0x248e1eb0, -0x62483b30, 0x4d74bf52, -0x1f89681f, 0x3c562354, 0x1e6a9b17, 0x795a4965, 0x7fa7c21f }, + { -0x24ce0981, -0x1614fd3c, 0x10bcfb2b, -0x12da0277, 0x5c5cddb4, 0x46c8131f, -0x5f346432, 0x33b21c13 } + }, + { + { 0x5ee38c5b, -0x65504650, 0x071a13c7, -0x4062d2b2, -0x16ccd6f6, -0x71119193, -0x51ef68e9, 0x1c3bab17 }, + { 0x087d8e31, 0x360692f8, -0x2d8e9c09, -0x0b2339c9, 0x65ea5963, 0x25a4e620, 0x5ac160d9, 0x659bf72e }, + { -0x38354850, 0x1c9ab216, 0x07bbc3cc, 0x7d65d374, 0x504a58d5, 0x52744750, 0x131a2990, 0x09f2606b } + }, +}, +{ + { + { 0x7c6691ae, 0x7e234c59, 0x0a85b4c8, 0x64889d3d, 0x354afae7, -0x251d36f4, 0x0c6a9e1d, 0x0a871e07 }, + { 0x744346be, 0x40e87d44, 0x15b52b25, 0x1d48dad4, -0x5ec49fc2, 0x7c3a8a18, 0x2fcdbdf7, 0x4eb728c1 }, + { 0x4bbc8989, 0x3301b599, 0x5bdd4260, 0x736bae3a, 0x19d59e3c, 0x0d61ade2, 0x2685d464, 0x3ee7300f } + }, + { + { -0x7be18ae8, 0x43fa7947, 0x639c46d7, -0x1a3905a7, -0x1cfad48c, -0x5ef9a1e3, -0x30476fd0, 0x7d47c6a2 }, + { -0x61822949, -0x0a2daa1c, 0x610b1eac, -0x7fe9eea4, -0x6d1e7836, 0x3c99975d, -0x686eda3e, 0x13815762 }, + { -0x710f2920, 0x3fdad014, -0x6eab90c4, -0x62c18b66, 0x26bb8157, 0x71ec6210, 0x34c9ec80, 0x148cf58d } + }, + { + { -0x651b8a93, -0x1da8d083, -0x770cb781, 0x56c345bb, 0x6960a88d, -0x602ef493, 0x4eaea1b9, 0x278febad }, + { 0x7934f027, 0x46a492f6, -0x097bf557, 0x469984be, -0x769ee7ac, 0x5ca1bc2a, -0x42a2442c, 0x3ff2fa1e }, + { -0x736cc69a, -0x4e5597e1, 0x20290c98, -0x73de6b64, 0x219d3c52, 0x39115291, -0x01639885, 0x4104dd02 } + }, + { + { -0x24f69548, -0x7edeb1fa, 0x0ce44f35, 0x21a8b6c9, 0x409e2af5, 0x6524c12a, -0x71035b7f, 0x0165b5a4 }, + { 0x1124422a, 0x72b2bf5e, -0x675cc54b, -0x5e05f3cd, -0x05ad499a, -0x6b349eff, -0x5050ac2b, 0x2c863b00 }, + { -0x5f7b958a, -0x0e6f5b8c, -0x32d08340, 0x12eff984, 0x58aa2b8f, 0x695e2906, -0x40013748, 0x591b67d9 } + }, + { + { -0x60e74aa3, -0x66464c8f, -0x5e739be2, -0x1b9a1a06, -0x3d60fa13, 0x61081136, 0x7030128b, 0x489b4f86 }, + { -0x7f4b6406, 0x312f0d1c, -0x540c1376, 0x5979515e, -0x610fe378, 0x727033c0, -0x35708435, 0x3de02ec7 }, + { 0x3aeb92ef, -0x2dcdefd3, 0x6116a861, -0x1e9dac4c, 0x190baa24, 0x3d7eabe7, 0x496cbebf, 0x49f5fbba } + }, + { + { 0x1e9c572e, 0x155d628c, -0x3a77b8bf, -0x75b27954, 0x515763eb, -0x6e5cad0a, -0x7798aea5, 0x06a1a6c2 }, + { -0x75a4302c, 0x30949a10, -0x439b8c15, -0x23bf2290, 0x307c0d1c, -0x6d3d6b3f, -0x3405918c, 0x5604a86d }, + { 0x7c1764b6, 0x7288d1d4, -0x1fbe74af, 0x72541140, 0x18acf6d1, -0x60fce5a0, -0x01d8bd3a, 0x20989e89 } + }, + { + { -0x7a1513d2, 0x1674278b, 0x7acb2bdf, 0x5621dc07, 0x61cbf45a, 0x640a4c16, -0x08fa6a2d, 0x730b9950 }, + { 0x3a2dcc7f, 0x499777fd, -0x5ab0276e, 0x32857c2c, -0x2df81c60, -0x5d86279c, 0x0ca67e29, 0x0403ed1d }, + { -0x78b13aae, -0x36b4d2cb, -0x67db9073, -0x3a193731, 0x16c035ce, -0x0834b906, 0x08303dcc, 0x5bd74543 } + }, + { + { 0x15e7792a, -0x7a3b6cdf, -0x42322237, -0x39b3765e, -0x525c289e, -0x62e1c258, 0x3067f82c, 0x5bb7db12 }, + { 0x28b24cc2, 0x7f9ad195, 0x6335c181, 0x7f6b5465, 0x4fc07236, 0x66b8b66e, 0x7380ad83, 0x133a7800 }, + { -0x39359d42, 0x0961f467, 0x211952ee, 0x04ec21d6, -0x642ab890, 0x18236077, 0x58f0e0d2, 0x740dca6d } + }, +}, +{ + { + { -0x12d9e51b, 0x3906c72a, -0x771eff09, -0x65497027, -0x0cc9fe69, -0x0a16fa66, -0x40d492b9, 0x0e53dc78 }, + { -0x2c0f50f5, 0x50b70bf5, -0x1cd18e09, 0x4feaf48a, -0x5aa442cc, 0x60e84ed3, 0x3f50d1ed, 0x00ed489b }, + { 0x7971877a, -0x46f7d641, 0x6d17e631, 0x5e444463, 0x18276893, 0x4d05c52e, 0x5a4a4af5, 0x27632d9a } + }, + { + { -0x78150025, -0x567d7a2f, -0x272f579c, -0x5a4b0445, 0x022663f7, -0x49a70d81, -0x26631d7e, 0x3bbc2b22 }, + { 0x54b260ce, -0x2ee00faf, 0x72f95270, -0x27923c72, 0x267cc138, 0x601fcd0d, 0x29e90ccd, 0x2b679164 }, + { 0x583c0a58, -0x46e836ae, 0x0fe4c6f3, 0x653ff9b8, -0x4320c3f4, -0x64f25829, -0x54ab29f2, 0x43a0eeb6 } + }, + { + { 0x57875fe8, 0x3ac63223, -0x0a043471, -0x262b0b14, 0x382bb620, -0x72117b6d, 0x4c799fdc, 0x50c5eaa1 }, + { 0x6d4a5487, 0x396966a4, -0x53d44c46, -0x07ee5e76, 0x5628b26b, 0x66e4685b, -0x626d646e, 0x70a47702 }, + { -0x290d04c4, -0x22f12375, -0x63384860, 0x54c63aa7, 0x2c8d9f1a, -0x51f4fcd5, 0x602967fb, 0x6f9ce107 } + }, + { + { 0x3520e0b5, 0x13969306, -0x7715fc02, 0x437fcf7c, -0x2c36a644, -0x082b3bf5, -0x076c2127, 0x699154d1 }, + { -0x321e3dd6, -0x52efab4f, 0x48eb32df, -0x3b5716fe, -0x53323f16, 0x5f3e7b33, -0x038669c2, 0x72364713 }, + { -0x4b4d8ada, 0x315d5c75, 0x0236daa5, -0x33347bd3, 0x345fee8e, 0x22f0c8a3, 0x7d39dbed, 0x73975a61 } + }, + { + { -0x0bbcc1ba, 0x6f37f392, 0x1f566b18, 0x0e19b9a1, 0x1fd1d662, 0x220fb78a, -0x5c7e36b3, 0x362a4258 }, + { 0x6375da10, -0x1bfdb207, 0x1830c870, 0x78d3251a, 0x658cd91c, -0x6fd4e6b8, 0x29b7438a, 0x7e18b10b }, + { 0x2b6beb2f, -0x6f8e26ed, 0x28418247, 0x0f26e9ad, -0x42136da3, -0x1546e137, -0x0b750d22, 0x4be65bc8 } + }, + { + { 0x57c26234, 0x1d50fba2, -0x214f9875, 0x7bd4823a, -0x59ac750b, -0x3d4f2392, 0x351da73e, 0x5665eec6 }, + { -0x5c918fd8, 0x78487feb, 0x1dd8ce34, 0x5f3f1300, 0x4b30c489, -0x6cb04ed3, 0x397f0a2b, 0x056c244d }, + { 0x43bfb210, -0x24c11ff7, 0x20800ac2, 0x49720187, 0x73bd8667, 0x26ab5d61, -0x54dfb6c8, 0x20b209c2 } + }, + { + { 0x16bd3289, 0x1fcca945, 0x41420428, 0x448d65aa, 0x16a55d62, 0x59c3b7b2, 0x4e612cd8, 0x49992cc6 }, + { -0x3f804cb5, 0x549e342a, 0x21373d93, 0x02d82208, -0x532e0a99, -0x43d9d290, -0x0435387c, 0x7a92c9fd }, + { 0x70f801de, 0x65bd1bea, -0x01b61d76, 0x1befb7c0, -0x4e4d51b6, -0x579cf933, 0x265c2a09, 0x3b7ac0cd } + }, + { + { 0x22ed39a7, -0x0f2ab1b1, 0x5608150a, -0x5d5516e2, -0x1225178b, -0x0bde4d17, 0x6b7de992, 0x31bc531d }, + { -0x73fe4314, -0x7dd411bd, -0x3f0438c5, 0x530cb525, -0x3e6ac017, 0x48519034, -0x1f65f0a5, 0x265cc261 }, + { -0x567f068f, -0x20c2ecb3, 0x221a22a7, 0x7a4fb8d1, 0x35aad6d8, 0x3df7d420, 0x6a1a125e, 0x2a14edcc } + }, +}, +{ + { + { 0x0478433c, 0x231a8c57, -0x3d7ebc63, -0x484ad8f2, -0x1c26f861, -0x24556616, 0x6c2b03d9, 0x2c03f525 }, + { 0x52cfce4e, -0x20b711f9, 0x06ec08b7, -0x3c00050d, -0x46aba63c, 0x05710b2a, -0x69c15c73, 0x161d25fa }, + { 0x7b53a47d, 0x790f1875, -0x30f3a787, 0x307b0130, 0x257ef7f9, 0x31903d77, -0x42694451, 0x699468bd } + }, + { + { 0x6aa91948, -0x2722c21a, 0x2fc0d2cc, 0x485064c2, 0x34fdea2f, -0x64b7db9a, 0x6c4a2e3a, 0x293e1c4e }, + { -0x0b250131, -0x42e0d0ba, -0x5b802909, 0x7cef0114, 0x4a47b37f, -0x2ce00226, 0x73905785, 0x525219a4 }, + { -0x6daeed1f, 0x376e134b, -0x235ea260, 0x703778b5, 0x461c3111, -0x4fba7651, 0x7f032823, 0x5b605c44 } + }, + { + { -0x0f180fb4, 0x3be9fec6, 0x75e34962, -0x7995a862, 0x1e1de61a, 0x5542ef16, -0x33a5422b, 0x2f12fef4 }, + { 0x20c47c89, -0x469a7fa7, -0x6dc47034, -0x180feff4, 0x02e2ef77, 0x00012565, -0x57514c12, 0x24a76dce }, + { -0x203f38c0, 0x0a4522b2, 0x40c9a407, 0x10d06e7f, 0x78cff668, -0x3930ebbf, 0x18a43790, 0x5e607b25 } + }, + { + { -0x5a6930ec, -0x5fd3bce4, -0x512c1c00, -0x1c3bd2c0, 0x2e0f26db, -0x2dbad980, -0x61ba8f98, 0x201f3313 }, + { 0x6cdf1818, 0x58b31d8f, -0x3c9da75e, 0x35cfa74f, 0x66e61d6e, -0x1e4c00b1, 0x6ccdd5f7, 0x5067acab }, + { 0x08039d51, -0x02ad8095, 0x017c0006, 0x18b14964, 0x2e25a4a8, -0x2addf150, 0x62460375, 0x397cba88 } + }, + { + { -0x37ec8619, 0x7815c3fb, -0x221ed50f, -0x599e6be0, -0x7a57022b, -0x00563f08, -0x3e1e3dae, 0x771b4022 }, + { -0x0fa6a64e, 0x30c13093, -0x1656868a, -0x1dc55e73, 0x721d5e26, 0x222fd491, 0x766e6c3a, 0x2339d320 }, + { 0x513a2fa7, -0x2782267a, -0x062b30f8, -0x0a53648f, 0x1ea283b3, -0x2f943ce5, 0x19971a76, 0x331a1892 } + }, + { + { -0x628a8d51, 0x26512f3a, 0x68074a9e, 0x5bcbe288, 0x1180f7c4, -0x7b123e3f, -0x09b65985, 0x1ac9619f }, + { -0x04b07f3a, -0x0ae990bb, 0x61c775cf, -0x63c93822, -0x6fbe26e4, -0x1c2b17e5, -0x7c4201df, 0x31167c6b }, + { 0x524b1068, -0x0dd4c7be, -0x11631679, 0x5068343b, 0x4a6250c8, -0x03628e7c, 0x1f08b111, 0x61243634 } + }, + { + { 0x1a2d2638, -0x749cb61d, -0x642c02cb, -0x62204900, -0x5c5f945c, 0x7f8bf1b8, 0x78d90445, 0x1522aa31 }, + { -0x78b17673, -0x2662be25, 0x6c07dc20, 0x09fea5f1, -0x2ff06444, 0x793d2c67, -0x61a100c0, 0x46ebe230 }, + { 0x69614938, 0x2c382f53, -0x48d292f0, -0x2501bf66, -0x49b90dd9, -0x1737cc6f, 0x0524306c, 0x45fe70f5 } + }, + { + { -0x376aeb6f, 0x62f24920, 0x3f630ca2, 0x05f007c8, -0x0a362b48, 0x6fbb45d2, -0x4a85ddbb, 0x16619f6d }, + { -0x69f3f474, -0x25b78a5a, -0x10f1d0e0, 0x5b68d076, 0x3d0b8fd4, 0x07fb51cf, -0x5f1c6d2c, 0x428d1623 }, + { 0x01a308fd, 0x084f4a44, 0x76a5caac, -0x57dde63d, 0x43d1bc7d, -0x214721ba, 0x60bd38c6, 0x1d81592d } + }, +}, +{ + { + { 0x2f89c8a1, 0x3a4a369a, 0x7c8de80d, 0x63137a1d, 0x78eda015, -0x4353ff76, -0x4b7c4fc1, 0x2cb8b3a5 }, + { -0x13d5b3c8, -0x27cc2842, 0x0acc20ed, 0x2c916283, -0x6d208a7f, -0x16c5b856, 0x333c4a81, 0x702d67a3 }, + { -0x34e46f5f, 0x36e417cb, 0x7f11794e, 0x33b3ddaa, -0x77a439f9, 0x3f510808, -0x1957fdf3, 0x24141dc0 } + }, + { + { -0x427cea83, -0x6e6da234, 0x22cc8094, 0x3ca12053, 0x3f90d6e4, 0x28e57f18, -0x21d18985, 0x1a4714ce }, + { 0x3fefee9d, 0x59f73c77, -0x3e306763, -0x4c0e1077, -0x1fd1aba1, -0x1ca204be, 0x47a1b47c, 0x5766120b }, + { -0x47494801, -0x24df45f1, 0x77511fa1, -0x48cd3c4a, -0x660fd277, -0x56d4ae40, 0x489ca5f1, 0x4f3875ad } + }, + { + { -0x118c1140, 0x79ed13f6, 0x69110bb1, -0x5a39ad93, -0x79fc79f4, -0x1b76d73d, -0x028fa60b, 0x722a1446 }, + { 0x4932ab22, -0x380389d1, 0x2f4c3c1b, 0x7ac0edf7, -0x65576a18, 0x5f6b55aa, -0x52f5ff7f, 0x3680274d }, + { -0x573077e7, -0x2f6a6017, -0x7b8a5664, -0x2f566ab0, 0x20b09cc5, 0x6eac1733, 0x331b1095, 0x628ecf04 } + }, + { + { 0x5c74ccf1, -0x64be5308, 0x08265251, -0x498cce7f, 0x11adb147, -0x6636d513, 0x34ecb40f, 0x7a47d70d }, + { -0x562f2244, -0x67434ee8, 0x08b4802b, -0x11bb61cc, -0x47594efc, -0x78f76dda, 0x45c7915d, 0x685f349a }, + { -0x33bc5b0b, 0x60a0c4cb, 0x3677bea9, 0x775c66ca, 0x2ff8f5ed, -0x5e855e8b, 0x0e01fdc0, 0x11ded902 } + }, + { + { 0x3bea93b7, 0x471f95b0, 0x3313abd3, 0x0552d7d4, -0x1e81c085, -0x426c8f1e, -0x4df1a414, 0x7b120f1d }, + { -0x351018fc, -0x76f187f7, -0x1cf17394, -0x78d7d693, -0x6d514e37, 0x4c5cd2a3, 0x5771531f, 0x194263d1 }, + { -0x79afd286, 0x17d2fb3d, 0x50a69352, -0x4a9b27bc, -0x59f128a3, 0x7da962c8, 0x318736aa, 0x00d0f85b } + }, + { + { -0x0289de3f, -0x598ac3e2, 0x445671f5, 0x69c0b4a7, 0x05b23c11, -0x68e0ad8c, 0x51a8c7cd, 0x387bc748 }, + { 0x777c84fd, -0x6874ebd2, 0x05a8c062, -0x0bfd9bb9, -0x1819ed39, -0x59852ae5, -0x672295cd, 0x2f7b4596 }, + { 0x4a52a9a8, -0x7e76b4b3, -0x09477cd1, -0x5226c1ee, -0x49e429c8, 0x184d8548, -0x29360933, 0x3f1c62db } + }, + { + { 0x148f693d, 0x3fad3e40, -0x6b14658e, 0x052656e1, 0x184f4e2f, 0x2f4dcbfd, -0x3b7d1e75, 0x406f8db1 }, + { -0x6e6ef3e1, 0x2e8f1f00, -0x400d1ed4, -0x5b20b020, -0x116d8bc8, 0x60c6560a, -0x53103706, 0x6338283f }, + { 0x7f191ee4, -0x619cf2d4, -0x43c00990, 0x4fbf8301, 0x7afb73c4, 0x787d8e4e, -0x170a705b, 0x50d83d5b } + }, + { + { -0x4b2c4993, -0x3f533070, 0x61732e60, -0x58fa621b, 0x70c6b0ba, 0x033d1f78, 0x26d946e4, 0x584161cd }, + { -0x3ee5e769, -0x7a97c6ea, -0x1af92ff8, 0x2d69a4ef, -0x099b42ff, 0x39af1378, 0x361517c6, 0x65942131 }, + { 0x72d27ca2, -0x440d4e60, -0x042138fc, -0x40c6c3a7, -0x1d9d47e2, -0x16724432, 0x3029b589, 0x02eebd0b } + }, +}, +{ + { + { 0x7b85c5e8, -0x789a4961, -0x2e97454e, 0x6ff0678b, 0x1d330f9b, 0x3a70e77c, -0x4f507184, 0x3a5f6d51 }, + { -0x59f253a1, 0x61368756, -0x145423a9, 0x17e02f6a, 0x4cce0f7d, 0x7f193f2d, -0x76132310, 0x20234a77 }, + { 0x7178b252, 0x76d20db6, -0x2ae12ea0, 0x071c34f9, -0x4c1bee90, -0x09d5b5e0, 0x3cffe366, 0x7cd68235 } + }, + { + { 0x68acf4f3, -0x599a32a0, 0x3cd7e3d3, 0x42d92d18, 0x336025d9, 0x5759389d, 0x2b2cd8ff, 0x3ef0253b }, + { -0x2778054a, 0x0be1a45b, -0x45bfc492, 0x2a846a32, -0x1691a000, -0x266defee, 0x3bdc0943, 0x2838c886 }, + { 0x4a465030, -0x2e944f31, 0x15c577ab, -0x05b694bf, -0x0b54be63, -0x7d305176, 0x06a82812, 0x21dcb8a6 } + }, + { + { -0x4188ce46, -0x6572ff06, 0x629e1889, -0x7dfc9f82, 0x43f3d97f, -0x4d33fdc9, 0x6c6f678b, 0x5d840dbf }, + { -0x73626038, 0x5c600446, -0x2bd55c35, 0x2540096e, 0x12ee2f9c, 0x125b4d4c, -0x6b5ce255, 0x0bc3d081 }, + { 0x309fe18b, 0x706e380d, -0x461e9a39, 0x6eb02da6, 0x7dae20ab, 0x57bbba99, 0x2ac196dd, 0x3a427623 } + }, + { + { -0x24bb8135, 0x3bf8c172, -0x39d7d243, 0x5fcfc41f, 0x75aa15fe, -0x7f530040, 0x24e1a9f9, 0x0770c9e8 }, + { -0x758f7b06, 0x4b42432c, -0x20461abb, -0x7675e61d, -0x63a71ba3, -0x4160ffdf, -0x5e92142f, 0x1ff177ce }, + { 0x45b5b5fd, -0x309e2666, 0x1b3a7924, -0x79f67b17, 0x303e3e89, -0x18cff6e7, 0x41500b1e, 0x39f264fd } + }, + { + { -0x01f6841f, -0x2e64b555, -0x201fe6d7, -0x5b92031f, 0x2ca6f1ff, -0x3c36f76c, 0x2c35f14e, 0x65c62127 }, + { -0x24181d64, -0x5852cbe9, 0x2b9c139c, -0x426bc896, -0x6ca68457, -0x5f16e472, 0x68889840, 0x1712d734 }, + { -0x31ce6c23, -0x18d47608, -0x5eda3f45, 0x4d103356, 0x2e1cfe83, 0x0419a93d, -0x4e631d8e, 0x22f9800a } + }, + { + { -0x65910254, 0x42029fdd, 0x34a54941, -0x46ed3142, -0x78420c85, 0x640f64b9, -0x7a67354c, 0x4171a4d3 }, + { 0x3e9ef8cb, 0x605a368a, -0x5aafb8eb, -0x1c163fde, 0x5f24248f, 0x553d48b0, 0x647626e5, 0x13f416cd }, + { -0x6636b374, -0x05d8a756, -0x4fff47f9, 0x23006f6f, -0x5225ac6e, -0x042d6e23, 0x574bd1ab, 0x508214fa } + }, + { + { 0x53d003d6, 0x461a15bb, -0x430c369b, -0x4defd778, 0x6c683a5a, 0x27c57675, -0x37934bb9, 0x3a7758a4 }, + { 0x3ed6fe4b, -0x3dfd96eb, 0x511d77c4, -0x59a598c7, 0x2c14af94, -0x3421d9ba, 0x6faba74b, 0x22f960ec }, + { -0x6c51af8a, 0x548111f6, 0x1dfd54a6, 0x1dae21df, -0x0ceea19b, 0x12248c90, -0x72180b6c, 0x5d9fd15f } + }, + { + { -0x1128ade2, 0x3f244d2a, 0x432e9615, -0x71c56fd8, 0x2e9c16d4, -0x1e9b4589, 0x47eb98d8, 0x3bc187fa }, + { 0x6d63727f, 0x031408d3, -0x28384acd, 0x6a379aef, -0x33511db5, -0x561e703b, 0x4f8fbed3, 0x332f3591 }, + { -0x15793df4, 0x6d470115, 0x6c46d125, -0x66754835, 0x3a660188, -0x2887cd4b, -0x6f9045fd, 0x450d81ce } + }, +}, +{ + { + { -0x4d351f4b, 0x23264d66, -0x14359a8a, 0x7dbaed33, -0x0f2db538, 0x030ebed6, -0x089caaf0, 0x2a887f78 }, + { -0x27bac6fe, -0x0751b2d6, -0x1724d2e3, 0x7018058e, -0x382d3ee2, -0x554c66a1, 0x24ccca79, 0x53b16d23 }, + { 0x5c012d4f, 0x2a23b9e7, -0x351e0d16, 0x0c974651, 0x675d70ca, 0x2fb63273, -0x79bbfc0b, 0x0ba7250b } + }, + { + { -0x79079264, -0x229ca76d, -0x1ec57a5c, 0x61699176, 0x4eaa7d57, 0x2e511195, -0x049f4205, 0x32c21b57 }, + { 0x029c6421, -0x44f2e703, -0x76d670fe, -0x43d2ebdf, -0x74daf16a, -0x7cb8071a, 0x032d71c9, 0x7b9f2fe8 }, + { 0x319e0780, -0x2787dc33, -0x76888a3b, -0x103b303f, -0x65f54c09, 0x4854fb12, 0x7238c371, 0x12c49d41 } + }, + { + { -0x7c866abe, 0x09b3a017, -0x552a11c1, 0x626dd08f, -0x148feb61, -0x45ff4312, -0x5f5bbb37, 0x1421b246 }, + { -0x0017c897, 0x0950b533, -0x71e2942f, 0x21861c1d, 0x1302e510, -0x0fdd27c8, 0x6391cab4, 0x2509200c }, + { -0x73db5839, 0x4aa43a8e, -0x270fa10b, 0x04c1f540, 0x0b3eb9dc, -0x5245a1f4, 0x48a49ce3, 0x2ab55044 } + }, + { + { 0x1c5d3afa, -0x23f8539d, -0x06207394, 0x58615171, -0x628c1d50, 0x72a079d8, -0x4b151ea3, 0x7301f4ce }, + { 0x6f0f5dec, 0x2ed22726, 0x5ed50824, -0x67db11bf, -0x6b972beb, -0x7f841384, -0x4ade1dc1, 0x7093bae1 }, + { -0x298dd3bf, 0x6409e759, 0x72bf729b, -0x598b1e31, 0x3c21e569, -0x43f5db15, 0x4ebacb23, 0x390167d2 } + }, + { + { -0x5d0dedf5, -0x2844fab5, -0x4efa7649, -0x1d463152, -0x0c3f1242, 0x3fe8bac8, 0x7112cb69, 0x4cbd4076 }, + { -0x45cac0e4, 0x27f58e3b, -0x4095bc9f, 0x4c47764d, 0x6e562650, -0x50443b1b, -0x551e5ba3, 0x07db2ee6 }, + { 0x29c58176, 0x0b603cc0, 0x5cb15d61, 0x5988e382, -0x230f5273, 0x2bb61413, 0x74183287, 0x7b8eec6c } + }, + { + { -0x03c7948d, 0x32fee570, -0x25c57339, -0x2574febf, -0x37697ca7, -0x68a002f6, -0x4ecd57ab, 0x6ee809a1 }, + { 0x2cd27cb0, -0x1b35bf88, -0x04169843, -0x25063cdd, -0x752be162, -0x4d642cb6, 0x626ede4d, 0x72810497 }, + { -0x030279c6, -0x6bbb44cf, 0x3e4e48c5, 0x2fe3690a, -0x2f7705db, -0x23d63799, -0x2e8cd6d2, 0x13bd1e38 } + }, + { + { 0x1dfac521, 0x223fb5cf, 0x6f554450, 0x325c2531, 0x659177ac, 0x030b98d7, 0x4f88a4bd, 0x1ed018b6 }, + { 0x696149b5, -0x2cd4b328, -0x7e275549, -0x1aa6c829, -0x51edd46c, 0x0bcb2127, -0x4ebf6650, 0x41e86fcf }, + { -0x47fd5950, 0x3630dfa1, 0x42ad3bd5, -0x77f078b9, -0x113a5b2c, 0x0af90d6c, 0x37cdc5d9, 0x746a247a } + }, + { + { 0x78d941ed, 0x6eccd852, -0x2dd087bd, 0x2254ae83, 0x7bbfcdb7, -0x3add2fd2, -0x400f1b1e, 0x681e3351 }, + { 0x2b7b9af6, -0x2ace4743, 0x37fc5b51, 0x50050935, -0x3a6cab93, 0x232fcf25, 0x2bb40f49, 0x20a36514 }, + { -0x7cfcb0bb, -0x749b4a63, 0x1fa20efb, 0x2f8b71f2, -0x459aaf1c, 0x69249495, 0x45d5472b, 0x539ef98e } + }, +}, +{ + { + { 0x1cae743f, -0x2f8b276a, -0x11e39c13, -0x0792e70b, -0x180b12d7, -0x68423aa5, 0x663ab108, 0x4cbad279 }, + { -0x59dfad8b, 0x6e7bb6a1, 0x413c8e83, -0x55b0de29, -0x1770a34e, 0x6f56d155, -0x59cba41f, 0x2de25d4b }, + { -0x5f28e033, -0x7f2e6fdc, -0x04d77508, -0x3ada3df6, 0x5f3a6419, -0x4e5c68b5, -0x1dff8dcd, 0x7d7fbcef } + }, + { + { -0x0c3d6f6c, -0x3283a23b, 0x2a9105ab, -0x387e5d66, 0x421c3058, -0x7f39e2ca, -0x23272b29, 0x4f9cd196 }, + { 0x266b2801, -0x0510e196, -0x2a8c60ea, -0x7993973c, 0x1b03762c, -0x0975d044, -0x7848a573, 0x5975435e }, + { 0x6a7b3768, 0x199297d8, 0x1ad17a63, -0x2f2fa7dc, 0x5c1c0c17, -0x45fd6353, 0x387a0307, 0x7ccdd084 } + }, + { + { 0x6760cc93, -0x64f37be8, 0x1ab32a99, -0x3251ff86, 0x620bda18, -0x5772137a, -0x7e6f35bc, 0x3593ca84 }, + { 0x6d260417, -0x2359bdd4, -0x6b7dbf43, -0x51eac2b0, -0x04973989, -0x563f3e4c, 0x61d0cf53, 0x428bd0ed }, + { 0x5e849aa7, -0x6dece766, 0x65d8facd, -0x2b273ccb, 0x53fdbbd1, -0x73adaba5, -0x25d29c1a, 0x27398308 } + }, + { + { 0x0a702453, -0x465ef1b4, -0x2a82e422, 0x0fa25866, -0x32d82509, -0x0046264b, 0x492c33fd, 0x572c2945 }, + { 0x435ed413, 0x42c38d28, 0x3278ccc9, -0x42af0ca0, 0x79da03ef, -0x44f854e6, -0x4173ccab, 0x269597ae }, + { -0x2932cf42, -0x388038bb, -0x1c455105, -0x1b20172d, -0x55a225f4, -0x5dd377d0, -0x3fa43580, 0x7f985498 } + }, + { + { 0x0fbf6363, -0x2ca9eaae, -0x30b2045a, 0x08045a45, -0x78c05f3e, -0x113db044, -0x2964ed19, 0x30f2653c }, + { -0x60f41ee9, 0x3849ce88, 0x7b54a288, -0x7ffa52e5, 0x23fc921c, 0x3da3c39f, 0x0a31f304, 0x76c2ec47 }, + { -0x553ef37b, -0x75f736c8, -0x24d89435, 0x46179b60, 0x0e6fac70, -0x56df3fe2, 0x596473da, 0x2f1273f1 } + }, + { + { 0x55a70bc0, 0x30488bd7, -0x0e2bbd19, 0x06d6b5a4, -0x43a69e9e, -0x152e5962, -0x123a087c, 0x38ac1997 }, + { -0x751fe1ef, 0x4739fc7c, 0x4a6aab9f, -0x02ad8b70, -0x788d70d2, 0x41d98a82, -0x27a4960e, 0x5d9e572a }, + { -0x58ae4ec5, 0x0666b517, 0x7e9b858c, 0x747d0686, 0x454dde49, -0x53533fef, -0x40161964, 0x22dfcd9c } + }, + { + { 0x103be0a1, 0x56ec59b4, -0x2da60697, 0x2ee3baec, 0x13f5cd32, 0x797cb294, 0x24cde472, 0x0fe98778 }, + { -0x3cf2f327, -0x72242d20, -0x5344bccd, -0x527199a1, 0x322a961f, -0x7094da74, 0x5448c1c7, 0x6b2916c0 }, + { 0x0aba913b, 0x7edb34d1, 0x2e6dac0e, 0x4ea3cd82, 0x6578f815, 0x66083dff, 0x7ff00a17, 0x4c303f30 } + }, + { + { 0x0dd94500, 0x29fc0358, 0x6fbbec93, -0x132d855c, -0x3d1d5808, 0x130a155f, -0x48f95e2b, 0x416b151a }, + { 0x17b28c85, -0x2cf5c42a, 0x39773bea, -0x3a2c8849, 0x1e6a5cbf, -0x39391874, -0x74d5483c, 0x0d61b8f7 }, + { -0x163ec950, 0x56a8d7ef, 0x58e44b20, -0x42f81a33, 0x1b57e0ab, -0x5019d026, 0x4277e8d2, 0x191a2af7 } + }, +}, +{ + { + { 0x2fe09a14, 0x09d4b60b, -0x244e8b82, -0x3c7b0f51, 0x78b5fd6e, 0x58e2ea89, -0x4a1f64f6, 0x519ef577 }, + { -0x5490b67b, -0x2aaff6a5, 0x4fbfaf1a, 0x04f4cd5b, 0x2a0c7540, -0x6271d12f, -0x4ddedd7a, 0x2bc24e04 }, + { 0x1124cca9, 0x1863d7d9, -0x47758f72, 0x7ac08145, -0x7a8fce0b, 0x2bcd7309, -0x7547051b, 0x62337a6e } + }, + { + { 0x1b3a1273, -0x2e54cdb2, -0x7efaacc0, 0x18947cf1, -0x5673e692, 0x3b5d9567, -0x7fd1e198, 0x7fa00425 }, + { 0x06ffca16, 0x4bcef17f, 0x692ae16a, -0x21f91e25, 0x614f42b0, 0x0753702d, 0x5b9212d0, 0x5f6041b4 }, + { 0x028c2705, 0x7d531574, -0x24f28a02, -0x7fce8297, -0x10737223, 0x30fface8, -0x493c1668, 0x7e9de97b } + }, + { + { -0x5db2bf23, -0x0ffb419e, 0x0452d41f, -0x45f9a66f, 0x62a44234, -0x7e3ba11f, -0x5ddd9911, 0x4cb829d8 }, + { -0x619a7a5d, 0x1558967b, -0x6716746e, -0x68366320, 0x6eb3adad, 0x10af149b, -0x0b2c7306, 0x42181fe8 }, + { 0x07b86681, 0x1dbcaa84, -0x74d98ac5, 0x081f001e, -0x7bfb717f, 0x3cd7ce6a, 0x3f25f22c, 0x78af1163 } + }, + { + { 0x7d65318c, 0x3241c00e, -0x2f179219, -0x19411a24, -0x043f73da, 0x118b2dc2, -0x039fc23d, 0x680d04a7 }, + { 0x0b50babc, -0x7be9142c, 0x28208bee, 0x15087226, -0x463e3c93, -0x5ceb7051, -0x2cd282a3, 0x0d07daac }, + { 0x695aa3eb, -0x063dbeb6, 0x05a68f21, -0x255bd3b4, 0x7f93963e, 0x7c6c2398, 0x0c3954e3, 0x210e8cd3 } + }, + { + { 0x37fe6c26, 0x2b50f161, 0x56e404d8, -0x1efd4328, 0x4c561f6b, 0x12b0f141, -0x2fd7136f, 0x51b17bc8 }, + { 0x10a71c06, -0x53bdfe0e, -0x0c404fdf, 0x6a65e0ae, 0x393632f7, -0x43bd3ca4, -0x79a0f8be, 0x56ea8db1 }, + { -0x30acaee7, -0x000a04b5, -0x20eef760, -0x0b676287, -0x65c45cdb, -0x4203159b, 0x74d1a6f2, 0x18a11f11 } + }, + { + { -0x2d85a0d4, -0x0429c326, -0x755ef929, -0x0ff03b44, -0x719b5bd0, 0x53fb5c1a, 0x0c1a2e85, 0x04eaabe5 }, + { 0x3f6bba29, 0x407375ab, -0x66e1b7d2, -0x613c4928, -0x1aa06d17, -0x6637f17e, -0x04f3f51f, 0x307c13b6 }, + { -0x34754a19, 0x24751021, 0x5c5010eb, -0x03dcbbb7, 0x4e5610a1, 0x5f1e717b, -0x3d8ef32b, 0x44da5f18 } + }, + { + { -0x76271534, -0x6ea90195, -0x1dced95f, -0x19486baf, 0x3944eb4e, -0x428b9c27, 0x767203ae, 0x726373f6 }, + { -0x0e47d14b, 0x033cc55f, 0x411cae52, -0x4ea51c93, -0x7004532d, -0x45bf49e7, 0x532e861f, 0x768edce1 }, + { -0x14810976, -0x1cfa358e, 0x70eadb23, 0x662cf31f, -0x4b3ba498, 0x18f026fd, -0x4a2d1343, 0x513b5384 } + }, + { + { -0x750cb315, 0x5e270287, -0x46b92952, -0x6ff4fbf7, -0x25427aee, 0x6512ebf7, -0x77da707f, 0x61d9b769 }, + { -0x38d66762, 0x46d46280, 0x5368a5dd, 0x4b93fbd0, -0x2e89a577, 0x63df3f81, -0x465f5ddd, 0x34cebd64 }, + { 0x49b7d94b, -0x593a58ed, 0x23eb9446, -0x5c0c2ea8, 0x77484834, 0x0416fbd2, 0x2c70812f, 0x69d45e6f } + }, +}, +{ + { + { 0x4f460efb, -0x6019d4bd, -0x59c9f82a, -0x212cfc2c, -0x485f25dc, -0x0faddef2, 0x00545b93, 0x237e7dbe }, + { -0x3ac3ebcf, -0x31e908b5, 0x2072edde, 0x2b9725ce, -0x4a4dc119, -0x47463c91, 0x0b5cc908, 0x7e2e0e45 }, + { 0x6701b430, 0x013575ed, -0x60f402f0, 0x231094e6, -0x7c1b80de, 0x75320f15, -0x4eeeaa1d, 0x71afa699 } + }, + { + { 0x473b50d6, -0x15bdc3e4, 0x3b38ef10, 0x51e87a1f, -0x4d36416b, -0x647b40a1, 0x78f89a1c, 0x00731fbc }, + { 0x3953b61d, 0x65ce6f9b, -0x505ebe1a, -0x39a7c616, -0x5608a602, 0x0f435ffd, -0x3d4e3d72, 0x021142e9 }, + { 0x48f81880, -0x1bcf38e8, 0x5ecec119, -0x4069f3de, 0x6bba15e3, -0x49251f7d, 0x47e15808, 0x4c4d6f33 } + }, + { + { -0x6770e690, 0x2f0cddfc, -0x4f460ae5, 0x6b916227, 0x779176be, 0x6ec7b6c4, -0x57706058, 0x38bf9500 }, + { -0x3e82e037, 0x18f7eccf, 0x51403c14, 0x6c75f5a6, -0x0811f321, -0x24218ed5, -0x581b85de, 0x193fddaa }, + { 0x37e8876f, 0x1fd2c93c, 0x18d1462c, -0x5d09e1a6, 0x39241276, 0x5080f582, -0x40f2b697, 0x6a6fb99e } + }, + { + { -0x491bdc3a, -0x114edd4b, -0x0d790072, -0x6c628ff0, 0x1dcf5d8c, -0x6f56d57d, 0x42c5eb10, 0x136fda9f }, + { 0x560855eb, 0x6a46c1bb, -0x076c0f63, 0x2416bb38, -0x708e533f, -0x28e2eec9, -0x5ce76916, 0x75f76914 }, + { -0x5cfa422f, -0x06b3204f, -0x6007d3f8, 0x0f364b9d, -0x3c44a776, 0x2a87d8a5, 0x0be8dcba, 0x02218351 } + }, + { + { 0x43307a7f, -0x62a58eff, -0x3b825ba1, -0x4f9c2162, -0x416d852d, 0x22bbfe52, -0x02bfbd94, 0x1387c441 }, + { 0x5ead2d14, 0x4af76638, -0x3583a7d0, -0x5f712780, 0x10211e3d, 0x0d13a6e6, 0x7b806c03, 0x6a071ce1 }, + { -0x78687508, -0x4a2c3c2f, 0x7f0e4413, 0x722b5a3d, -0x44b88360, 0x0d7b4848, -0x50e1236e, 0x3171b26a } + }, + { + { -0x4d75b82f, -0x59f24828, 0x1770a4f1, -0x5940eb2a, 0x53ddbd58, -0x2b5e076d, 0x344243e9, 0x6c514a63 }, + { -0x68a9b358, -0x56d0ce70, 0x2275e119, -0x008447b4, -0x5b78aeb0, 0x4f55fe37, 0x3cf0835a, 0x221fd487 }, + { 0x3a156341, 0x2322204f, -0x45f5fcd3, -0x048c1f17, 0x410f030e, -0x031f22b4, -0x046db556, 0x48daa596 } + }, + { + { -0x37b3686d, 0x14f61d5d, -0x10be7dfa, -0x66be061d, 0x346277ac, -0x320a4771, 0x0e8a79a9, 0x58c837fa }, + { 0x5ca59cc7, 0x6eca8e66, 0x2e38aca0, -0x57b8dab5, -0x2de1e832, 0x31afc708, -0x3527b509, 0x676dd6fc }, + { -0x69036fa8, 0x0cf96885, 0x7b56a01b, 0x1ddcbbf3, 0x4935d66a, -0x233d1883, -0x395a80f6, 0x1c4f73f2 } + }, + { + { -0x0383cb7c, -0x4c918f92, -0x3c3e309f, 0x73dfc9b4, 0x781cc7e5, -0x14e28637, 0x7daf675c, 0x70459adb }, + { 0x305fa0bb, 0x0e7a4fbd, 0x54c663ad, -0x7d62b320, 0x2fe33848, -0x0bde3c7d, 0x1bf64c42, 0x795ac80d }, + { -0x6e4bd44d, 0x1b91db49, 0x4b02dcca, 0x57269623, 0x1f8c78dc, -0x6020611b, -0x731de02d, 0x5fe16284 } + }, +}, +{ + { + { -0x6aeeac77, 0x315c29c7, -0x79d08b32, -0x281f1af9, -0x7a6d8bce, 0x0c4a7621, 0x4a25a1e4, 0x72de6c98 }, + { 0x4d077c41, -0x1d86f552, -0x248b965d, -0x746c7d90, -0x7542e95e, 0x6eb632dc, -0x55f9b48e, 0x720814ec }, + { -0x40955cf0, -0x51654aad, -0x7f9291e5, 0x050a50a9, -0x5200aec7, -0x6d448bfd, 0x45be618b, 0x0394d276 } + }, + { + { -0x4dcaba5c, -0x0ac69bdb, -0x67044d6a, 0x15a7a27e, 0x636fdd86, -0x5493ad44, 0x419334ee, 0x79d995a8 }, + { -0x7a81120c, 0x4d572251, -0x1e616c3b, -0x1c8db123, 0x0b797035, -0x758ebdf2, -0x785418bd, 0x3b3c8336 }, + { 0x1195dd75, -0x3275715a, 0x1dd9a82f, -0x5afb2758, -0x5ca7864a, 0x540dca81, 0x79c86a8a, 0x60dd16a3 } + }, + { + { 0x153e47b8, 0x3501d6f8, 0x14a2f60c, -0x485698ac, 0x455d9523, 0x112ee8b6, -0x7eed1576, 0x4e62a3c1 }, + { 0x7381e559, 0x35a2c848, -0x287f7d35, 0x596ffea6, -0x245849ad, -0x34688e15, -0x64b2597b, 0x5a08b501 }, + { 0x516ab786, -0x372b53fc, 0x5295b23d, 0x595af321, -0x24fdcf3f, -0x29122dcc, -0x7da4be34, 0x0929efe8 } + }, + { + { -0x52a99ae3, -0x74ce8d49, 0x3fabd717, 0x01581b7a, 0x424df6e4, 0x2dc94df6, 0x2c29284f, 0x30376e5d }, + { -0x342f0d2d, 0x5f0601d1, 0x6132bb7f, 0x736e412f, 0x238dde87, -0x7c9fbbce, -0x0a3f8ac4, 0x1e3a5272 }, + { -0x7ea65a64, -0x2d6e7259, 0x3f0713f3, 0x6bdc1cd9, 0x4acd6590, 0x565f7a93, 0x4cb4c128, 0x53daacec } + }, + { + { -0x7ad30250, -0x667ad43d, 0x59d6ed0b, 0x2cc12e95, -0x64a53d85, 0x70f9e2bf, 0x7959ae99, 0x4f3b8c11 }, + { -0x6337582a, 0x4ca73bd7, 0x47e9a9b2, 0x4d4a738f, 0x42f5fe00, -0x0b340ed7, -0x4240f8ae, 0x01a13ff9 }, + { 0x2ff26412, 0x55b6c9c8, 0x1fb667a8, 0x1ac4a8c9, -0x1488740e, -0x2ad84031, 0x7012a3be, 0x303337da } + }, + { + { -0x052d022f, -0x6892c335, 0x37a640a8, -0x34777c69, 0x6734cb25, 0x2ff00c1d, 0x789c2d2b, 0x269ff4dc }, + { -0x73e36284, -0x6aabddde, 0x1a9b340f, 0x01fac137, -0x6da4b729, 0x7e8d9177, 0x61b3e31b, 0x53f8ad56 }, + { -0x3f729873, 0x0c003fbd, 0x7ead2b17, 0x4d982fa3, -0x4d1a7d0f, -0x3f819433, -0x20bed5bc, 0x296c7291 } + }, + { + { -0x25474a62, -0x204dcdfb, -0x37f6ddb0, 0x465aeaa0, -0x658da2e8, -0x2ecc3ee8, 0x61f117d1, 0x23273702 }, + { 0x33daf397, 0x7903de2b, -0x3659db4d, -0x2f00f9e7, 0x555b3e18, -0x75e2dad5, 0x52e0b7c0, 0x2b6d581c }, + { 0x623e7986, 0x3d0543d3, -0x3d875cac, 0x679414c2, 0x726196f6, -0x51bc0f34, -0x7dba1546, 0x7836c41f } + }, + { + { -0x7fee6c84, -0x359ae17c, 0x6ef41a28, -0x394f3b92, 0x5f3f8d52, -0x48fde459, -0x15284603, 0x119dff99 }, + { 0x49e95a81, -0x185dab25, 0x08b0ad73, 0x5192d5d0, -0x2ff503f9, 0x4d20e5b1, 0x2cf25f38, 0x5d55f801 }, + { -0x0b4ce2b3, 0x43eadfcb, 0x11148892, -0x39afc08c, 0x060d3b17, -0x0111973b, -0x22b5f538, 0x329293b3 } + }, +}, +{ + { + { 0x5d7cb208, 0x2879852d, 0x687df2e7, -0x47212290, 0x21687891, -0x23f40055, 0x677daa35, 0x2b44c043 }, + { -0x1e6b69e6, 0x4e59214f, 0x0d71cd4f, 0x49be7dc7, 0x3b50f22d, -0x6cff302e, -0x036e8dce, 0x4789d446 }, + { 0x074eb78e, 0x1a1c87ab, -0x66250b99, -0x05392e72, 0x484f9067, 0x3eacbbcd, 0x2bb9a4e4, 0x60c52eef } + }, + { + { 0x7cae6d11, 0x702bc5c2, 0x54a48cab, 0x44c7699b, -0x45b6d14e, -0x1043bfaa, -0x26499893, 0x70d77248 }, + { 0x3bfd8bf1, 0x0b5d89bc, -0x360caae6, -0x4f946dc9, -0x2acfd70b, 0x0e4c16b0, 0x2ccfcaab, 0x10bc9c31 }, + { 0x3ec2a05b, -0x557517b5, -0x12e87e20, -0x6796610c, 0x708e85d1, 0x794513e4, -0x56890bed, 0x63755bd3 } + }, + { + { -0x680e5349, 0x3dc71018, -0x3e9a4428, 0x5dda7d5e, 0x0fa1020f, 0x508e5b9c, 0x37c52a56, 0x27637517 }, + { 0x2ad10853, -0x4aa05fc2, -0x6119ca97, 0x356f7590, -0x41964770, -0x60060e03, -0x743e907c, 0x0d8cc1c4 }, + { 0x6eb419a9, 0x029402d3, 0x77b460a5, -0x0f4bb182, -0x2bc3b6aa, -0x30579dd0, 0x7ad166e7, 0x70c2dd8a } + }, + { + { -0x471281ed, -0x6e2b6983, -0x28897e86, 0x74252f0a, 0x0d852564, -0x1bf67d20, 0x16a53ce5, 0x32b86138 }, + { -0x609013f2, 0x65619450, 0x46c6518d, -0x11d18157, 0x67e09b5c, -0x68cc3e0d, 0x63948495, 0x2e0fac63 }, + { -0x1bb7329c, 0x79e7f7be, 0x087886d0, 0x6ac83a67, -0x5f1b24d2, -0x07602b27, 0x735a4f41, 0x4179215c } + }, + { + { 0x286bcd34, -0x1b51cc47, 0x559dd6dc, -0x4810814a, -0x4c2c71e1, 0x278b141f, 0x2241c286, 0x31fa8566 }, + { -0x282312d6, -0x738f6b19, 0x47d39c70, -0x6804753d, -0x56f926fe, -0x1ec41fcd, 0x0cd99d76, 0x700344a3 }, + { 0x2e3622f4, -0x507d93be, -0x67ccafd3, -0x3edfd679, 0x2b389123, -0x643e481f, -0x566adb77, 0x24bb2312 } + }, + { + { -0x0a07a395, 0x41f80c2a, 0x04fa6794, 0x687284c3, -0x5c45e453, -0x76ba2067, -0x0014a2ea, 0x0d1d2af9 }, + { 0x32de67c3, -0x4e5712e9, 0x461b4948, 0x3cb49418, 0x76cfbcd2, -0x7142bcbd, 0x1e188008, 0x0fee3e87 }, + { 0x32621edf, -0x5625755f, 0x59226579, 0x30b822a1, -0x58653e6d, 0x4004197b, 0x18531d76, 0x16acd797 } + }, + { + { 0x7887b6ad, -0x36a6393b, 0x5f90feba, -0x6b1e6153, -0x5cbd0afc, 0x16e24e62, 0x18161700, 0x164ed34b }, + { 0x2d9b1d3d, 0x72df72af, -0x5bcddba6, 0x63462a36, 0x16b39637, 0x3ecea079, -0x46cfdcf7, 0x123e0ef6 }, + { 0x192fe69a, 0x487ed94c, 0x3a911513, 0x61ae2cea, -0x465b21d9, -0x7884092d, 0x1073f3eb, 0x78da0fc6 } + }, + { + { 0x680c3a94, -0x5d607f0f, 0x1ae9e7e6, 0x71f77e15, 0x48017973, 0x1100f158, 0x16b38ddd, 0x054aa4b3 }, + { -0x1ad43996, 0x5bf15d28, 0x70f01a8e, 0x2c47e318, 0x06c28bdd, 0x2419afbc, 0x256b173a, 0x2d25deeb }, + { 0x19267cb8, -0x2037b973, 0x66e54daf, 0x0b28789c, 0x666eec17, 0x2aeb1d2a, -0x548258a0, 0x134610a6 } + }, +}, +{ + { + { -0x23fd73c4, -0x26ebcf20, 0x5217c771, 0x0eb955a8, 0x2c99a1fa, 0x4b09e1ed, -0x42958bc4, 0x42881af2 }, + { 0x7c59b23f, -0x350aa13e, 0x154d04f2, -0x665112c2, -0x1ebebe0c, 0x68441d72, 0x3932a0a2, 0x14034513 }, + { -0x54a352c3, 0x7bfec69a, 0x4cb2cfad, -0x3dc1732d, -0x04c8295e, 0x685dd14b, 0x15677a18, 0x0ad6d644 } + }, + { + { 0x47927e9f, 0x79148928, 0x370aa877, 0x33dad6ef, 0x11122703, 0x1f8f24fa, 0x2adf9592, 0x5265ac2f }, + { 0x417becb5, 0x781a439e, -0x2ef1fd9a, 0x4ac5938c, 0x0692ac24, 0x5da38511, -0x521cedcd, 0x11b065a2 }, + { -0x65034cba, 0x405fdd30, 0x28e63f54, -0x268dc2bc, 0x5f65aaae, -0x6b3fe210, -0x1eb3f7f7, 0x43e4dc3a } + }, + { + { -0x523d395d, -0x1590853d, -0x168e836c, -0x2f16d70a, -0x29ba150b, -0x1d2c8616, -0x3ae00442, 0x46dd8785 }, + { -0x56c75ae9, -0x43ed380f, 0x3180b2e1, 0x473028ab, -0x0432dab6, 0x3f78571e, 0x6ff6f90f, 0x74e53442 }, + { 0x375c8898, 0x709801be, -0x1c027cb8, 0x4b06dab5, 0x27230714, 0x75880ced, -0x22d0b3be, 0x2b09468f } + }, + { + { -0x7d005fd6, 0x5b979465, -0x01570ab7, -0x25f695af, 0x5f77af9b, -0x5f9caec9, 0x201d1e76, 0x1bcfde61 }, + { -0x48fe346a, -0x6838b612, -0x495c963d, -0x7c0bc72c, -0x65bfd327, 0x62962b8b, -0x67772085, 0x6976c750 }, + { 0x246a59a2, 0x4a4a5490, -0x17802270, -0x29c14222, 0x0d2371fa, -0x26bc8399, -0x2cf0712a, 0x69e87308 } + }, + { + { -0x7437fcfd, 0x0f80bf02, 0x7a18cefb, 0x6aae16b3, -0x28d3295d, -0x22b815b9, -0x0b12c656, 0x61943588 }, + { 0x5656beb0, 0x435a8bb1, 0x4f4d5bca, -0x07053646, 0x1548c075, -0x464d873c, -0x176d49de, 0x3eb0ef76 }, + { -0x6efc607b, -0x2d91a3c2, -0x090cc557, -0x3f161883, 0x70066a93, -0x176973ab, 0x1faaaddd, 0x3c34d188 } + }, + { + { 0x2fffe0d9, -0x42a4f471, 0x3ed24fb9, 0x6aa25410, -0x4d97de3c, 0x2ac7d7bc, 0x60dca36a, 0x605b394b }, + { -0x5f606140, 0x3f9d2b5e, -0x49dc5770, 0x1dab3b6f, 0x72d926c4, -0x5f645c16, 0x3fd8b36d, 0x37419351 }, + { 0x5a9d1ed2, -0x4b17a91c, 0x6c97a9a2, -0x1017b78a, 0x1e5eee7d, -0x4efb309c, -0x7758e371, 0x2f50b81c } + }, + { + { -0x5825add6, 0x2b552ca0, 0x449b0250, 0x3230b336, -0x5b466047, -0x0d3b3a44, 0x58074a22, 0x7b2c6749 }, + { -0x0397ee45, 0x31723c61, 0x6211800f, -0x634bafb8, 0x47995753, 0x768933d3, 0x02752fcd, 0x3491a535 }, + { 0x3ed28cdf, -0x2aae9a78, -0x2c9d21c7, 0x12d84fd2, -0x1cc871b1, 0x0a874ad3, 0x7c763e74, 0x000d2b1f } + }, + { + { 0x3e94a8ab, -0x69db8874, -0x16587414, 0x0ad6f3ce, 0x0d743c4f, -0x6b75387f, -0x55130334, 0x76627935 }, + { -0x2f92b599, 0x3d420811, -0x6f1f001d, -0x4103fb7b, -0x42b78422, -0x078f3949, 0x319afa28, 0x6e2a7316 }, + { -0x292a6561, 0x56a8ac24, 0x3096f006, -0x37248ac2, -0x70b3ad67, 0x477f41e6, -0x09379eec, 0x588d851c } + }, +}, +{ + { + { 0x77d1f515, -0x32d59a19, -0x70559f0f, 0x54899187, -0x2543f91b, -0x4e48c444, -0x56833605, 0x654878cb }, + { -0x72094f02, 0x51138ec7, -0x1a8a0ae5, 0x5397da89, 0x717af1b9, 0x09207a1d, 0x2b20d650, 0x2102fdba }, + { 0x055ce6a1, -0x69611bfb, 0x1251ad29, 0x36bca768, -0x55825beb, 0x3a1af517, 0x29ecb2ba, 0x0ad725db } + }, + { + { -0x64fa907b, -0x013843f4, -0x180a0029, 0x537d5268, 0x4312aefa, 0x77afc662, 0x02399fd9, 0x4f675f53 }, + { -0x7cb1dba9, -0x23bd984f, 0x70ce1bc5, -0x498abb4b, -0x082ea129, 0x1af07a0b, 0x71a03650, 0x4aefcffb }, + { 0x0415171e, -0x3cd2c9ca, -0x7667b7c5, -0x32d410ef, -0x2f6baef0, -0x78f59153, -0x5d579a9f, 0x0bccbb72 } + }, + { + { 0x50fe1296, 0x186d5e4c, -0x01176082, -0x1fc6847e, 0x507031b0, 0x3bc7f6c5, 0x108f37c2, 0x6678fd69 }, + { -0x154e5638, 0x185e962f, 0x65147dcd, -0x791819cb, -0x44a4920e, -0x4f6d1fcf, 0x59d6b73e, 0x4024f0ab }, + { 0x636863c2, 0x1586fa31, 0x572d33f2, 0x07f68c48, 0x789eaefc, 0x4f73cc9f, -0x7152b8ff, 0x2d42e210 } + }, + { + { 0x0f537593, 0x21717b0d, 0x131e064c, -0x6eb196f5, 0x752ae09f, 0x1bb687ae, -0x64bdc392, 0x420bf3a7 }, + { -0x6b202d65, -0x680aeceb, 0x313f4c6a, 0x6155985d, 0x08455010, -0x145ec0f9, -0x472d2cde, 0x676b2608 }, + { 0x1c5b2b47, -0x7ec7459b, 0x311b1b80, -0x798e4914, -0x43ceca50, 0x7bff0cb1, -0x63f30e20, 0x745d2ffa } + }, + { + { 0x21d34e6a, 0x6036df57, -0x66844c30, -0x4e2477d9, -0x378a9506, -0x2c3df63d, 0x4c1dc839, 0x06e15be5 }, + { 0x2bc9c8bd, -0x40ada5e2, 0x26479d81, -0x15a4d9f8, -0x20feaa25, -0x2aee38f2, -0x69f30a30, 0x1ae23ceb }, + { 0x1932994a, 0x5b725d87, -0x314e2550, 0x32351cb5, -0x254835fb, 0x7dc41549, 0x278ec1f7, 0x58ded861 } + }, + { + { -0x493d3658, 0x2dfb5ba8, -0x0ad3a674, 0x48eeef8e, -0x0ed2ea8d, 0x33809107, 0x531d5bd8, 0x08ba696b }, + { -0x0d993aa4, -0x27e8c86d, -0x33bab1b7, -0x3736893b, -0x43d93c58, 0x5ce382f8, 0x5485f6f9, 0x2ff39de8 }, + { -0x3c103a86, 0x77ed3eee, -0x2b00b7ef, 0x04e05517, -0x0e598e35, -0x15c285c1, -0x6b8301ac, 0x120633b4 } + }, + { + { 0x4912100a, -0x7d42ceb9, 0x7e6fbe06, -0x21dc8493, 0x11ea79c6, -0x1ee189e7, -0x34c6c422, 0x07433be3 }, + { -0x6e9effbe, 0x0b949878, -0x13140518, 0x4ee7b13c, -0x6b0f5b40, 0x70be7395, -0x4b2a6e7b, 0x35d30a99 }, + { 0x5ce997f4, -0x0086bb40, -0x4fa3ae5d, 0x575d3de4, 0x5a76847c, 0x583381fd, 0x7af6da9f, 0x2d873ede } + }, + { + { 0x4e5df981, -0x559dfd1f, 0x5015e1f5, -0x5df2a6e9, -0x451de294, 0x18a275d3, 0x01600253, 0x0543618a }, + { 0x43373409, 0x157a3164, -0x0b557e27, -0x05474812, -0x0a59b7fa, -0x4f6c011a, 0x707fa7b6, 0x2e773654 }, + { -0x68b3dc3f, 0x0deabdf4, -0x6231b96d, -0x5590f5db, -0x5d6545d4, 0x04202cb8, 0x2d07960d, 0x4b144336 } + }, +}, +{ + { + { 0x57c5715e, 0x299b1c3f, 0x6b686d90, -0x69346d62, 0x47235ab3, 0x30048064, -0x5bb2601f, 0x2c435c24 }, + { 0x53242cec, 0x47b837f7, -0x3fbded0e, 0x256dc48c, -0x1e26d73b, -0x1ddd0405, -0x5275d3f9, 0x48ea295b }, + { -0x7f077cc1, 0x0607c97c, -0x35da13a5, 0x0e851578, 0x161ebb6f, 0x54f7450b, -0x5f2107f2, 0x7bcb4792 } + }, + { + { 0x045224c2, 0x1cecd0a0, 0x69e53952, 0x757f1b1b, 0x5289f681, 0x775b7a92, 0x16736148, 0x1b6cc620 }, + { 0x2bc73659, -0x7b781c30, 0x059979df, 0x4baf8445, -0x23529041, -0x2e8368a6, -0x2103694a, 0x57369f0b }, + { 0x75638698, -0x0e5666ff, -0x11559f2d, 0x353dd1be, 0x4c9ba488, -0x7b6b8ecd, 0x43ade311, 0x63fa6e68 } + }, + { + { -0x2db4a149, 0x2195becd, -0x3f32bb07, 0x5e41f18c, 0x41ca9ede, -0x20d7f8bc, -0x0ca48299, 0x07073b98 }, + { 0x6597c168, -0x2ea3dfad, -0x672d7877, -0x608c8c00, 0x3257ba1f, 0x18aee7f1, 0x07346f14, 0x3418bfda }, + { 0x4ce530d4, -0x2fc39894, 0x3b5df9f4, 0x0b64c047, 0x19b3a31e, 0x065cef8b, 0x533102c9, 0x3084d661 } + }, + { + { 0x760321fd, -0x6593178a, -0x6149c528, 0x7fe2b510, -0x7537fa6e, 0x00e7d4ae, -0x44908dc6, 0x73d86b7a }, + { -0x407b9653, -0x1e094862, -0x1d99cecb, 0x15801004, -0x508be7e5, -0x65b67cd0, 0x049b673c, 0x3ba2504f }, + { 0x6dba5ab6, 0x0b52b560, -0x444e1255, -0x56ecb0f1, -0x64fb59cb, 0x30a9520d, 0x7973e5db, 0x6813b8f3 } + }, + { + { -0x0cea81d7, -0x0e6b35aa, 0x5ef528a5, 0x136d3570, -0x74fa6644, -0x22b31089, 0x24f833ed, 0x7d5472af }, + { 0x334127c1, -0x67ab4fac, -0x7d0400db, 0x105d0478, 0x44186f4f, -0x24b60807, -0x412f4700, 0x1768e838 }, + { -0x50cc25b9, -0x2f1078b3, -0x491cc607, 0x00d3be5d, -0x63631132, 0x3f2a8a2f, 0x2352435a, 0x5d1aeb79 } + }, + { + { -0x49e4588b, 0x12c7bfae, -0x1d9c4003, -0x47b19de1, 0x5c840dcf, 0x0b47a5c3, -0x335079cc, 0x7e83be0b }, + { 0x19cd63ca, -0x0a61944d, 0x21d06839, 0x670c1592, 0x2150cab6, -0x4f92a9a5, 0x104f12a3, 0x20fb199d }, + { 0x6d99c120, 0x61943dee, 0x460b9fe0, -0x79efe0d2, -0x7117a673, 0x6bb2f151, -0x033b8a34, 0x76b76289 } + }, + { + { 0x522ec0b3, 0x4245f1a1, 0x2a75656d, 0x558785b2, 0x48a1b3c0, 0x1d485a25, -0x2a701f61, 0x60959ecc }, + { 0x756286fa, 0x791b4cc1, -0x28b5ea84, -0x24312ce9, -0x158d421a, 0x7e732421, 0x1131c8e9, 0x01fe1849 }, + { -0x571285f7, 0x3ebfeb7b, -0x1afd8764, 0x49fdc2bb, 0x3c119428, 0x44ebce5d, -0x416b80b6, 0x35e1eb55 } + }, + { + { 0x726ccc74, 0x14fd6dfa, 0x2f53b965, 0x3b084cfe, 0x52a2c8b4, -0x0cc51b0b, 0x0d40166a, 0x59aab07a }, + { -0x3a8c722d, -0x242518ff, -0x4d90e412, -0x063909cb, 0x42f15ef4, 0x61e96a80, -0x509f5b28, 0x3aa1d11f }, + { -0x6da153db, 0x77bcec4c, 0x60137738, 0x18487184, -0x01560baf, 0x5b374337, -0x371955ba, 0x1865e78e } + }, +}, +{ + { + { 0x1c529ccb, -0x6983ab17, 0x64c635fb, 0x30f62692, 0x78121965, 0x2747aff4, -0x150990a4, 0x17038418 }, + { -0x4991e086, -0x333b4839, -0x0af3d082, 0x44157e25, 0x713eaf1c, 0x3ef06dfc, 0x52da63f7, 0x582f4467 }, + { 0x20324ce4, -0x39ce842d, -0x5bb7743c, -0x57efbd18, 0x4e5a1364, -0x4de10e75, -0x325d7237, 0x0c2a1c4b } + }, + { + { 0x69bd6945, -0x123b7eb8, -0x41e372de, 0x0d6d907d, -0x2aa33a55, -0x39c42dee, -0x5ceb237d, 0x5a6a9b30 }, + { 0x6f1f0447, -0x2db23830, -0x24783fa7, -0x4dd961c2, -0x044d2d71, -0x2ea4fd8e, -0x3909b789, 0x7c558bd1 }, + { -0x2c69b9c3, -0x2f13eadc, -0x3ca5db10, 0x12bb628a, 0x1cbc5fa4, -0x5af3c587, 0x0afbafc3, 0x0404a5ca } + }, + { + { 0x2a416fd1, 0x62bc9e1b, -0x1cafa675, -0x4a3908d8, 0x3d5d6967, 0x04343fd8, -0x18071168, 0x39527516 }, + { 0x0aa743d6, -0x73e0bff9, 0x5b265ee8, -0x33452f35, 0x668fd2de, 0x574b046b, -0x352269cd, 0x46395bfd }, + { 0x1a5d9a9c, 0x117fdb2d, -0x2effa3d6, -0x6388ba44, 0x54d56fea, -0x102b410f, -0x17dd2fea, 0x76579a29 } + }, + { + { 0x52b434f2, 0x333cb513, -0x6c217f1f, -0x27cdd7b7, 0x750d35ce, -0x4aaed779, 0x2a2777c1, 0x02c514bb }, + { 0x49c02a17, 0x45b68e7e, -0x43565c81, 0x23cd51a2, -0x13ddb3e5, 0x3ed65f11, -0x61fa424f, 0x43a384dc }, + { -0x740e49bb, 0x684bd5da, -0x094ab4ad, -0x04742c82, -0x564f2dad, 0x313916d7, 0x61548059, 0x11609209 } + }, + { + { 0x369b4dcd, 0x7a385616, 0x655c3563, 0x75c02ca7, -0x2b0e7fdf, 0x7dc21bf9, -0x6e191fbe, 0x2f637d74 }, + { 0x29dacfaa, -0x4bb2e997, -0x7beca671, -0x25ad60b4, 0x453d5559, -0x16109c36, -0x3a9671f5, 0x351e125b }, + { 0x1af67bbe, -0x2b4b64ba, -0x3754769f, -0x29fcfc86, -0x06596605, 0x71dee19f, -0x1831d566, 0x7f182d06 } + }, + { + { -0x71de8ade, 0x09454b72, -0x2b7b4728, -0x55a7170c, 0x7f46903c, -0x2ca7dab3, 0x241c5217, 0x44acc043 }, + { -0x54fe9714, 0x7a7c8e64, 0x15edc543, -0x34a5b5ab, 0x47cd0eda, 0x095519d3, 0x343e93b0, 0x67d4ac8c }, + { 0x4f7a5777, 0x1c7d6bbb, -0x6e7cec1f, -0x74ca012c, -0x3694b97c, 0x4adca1c6, 0x12ad71bd, 0x556d1c83 } + }, + { + { -0x4ee417df, -0x7e0f98aa, 0x10a3f3dd, 0x0faff823, 0x6a99465d, -0x074d2fab, -0x337380fb, 0x097abe38 }, + { 0x0c8d3982, 0x17ef40e3, 0x15a3fa34, 0x31f7073e, 0x0773646e, 0x4f21f3cb, 0x1d824eff, 0x746c6c6d }, + { 0x7ea52da4, 0x0c49c987, -0x6423e2bd, 0x4c436955, -0x0833142e, 0x022c3809, 0x4bee84bd, 0x577e14a3 } + }, + { + { -0x42b228d5, -0x6b013142, 0x060f2211, -0x0b95b026, -0x3f372e01, 0x124a5977, -0x04ff6d6b, 0x705304b8 }, + { 0x61a73b0a, -0x0f1d9754, 0x3791a5f5, -0x0d0505f0, 0x6b6d00e9, -0x3e1ec17e, 0x6fd78f42, 0x60fa7ee9 }, + { 0x4d296ec6, -0x49c2e2cb, 0x5fad31d8, -0x0c3cfac2, -0x4b42bd14, 0x670b958c, -0x5e9cac03, 0x21398e0c } + }, +}, +{ + { + { -0x79e48166, -0x793a03ea, 0x6a27c451, -0x095ccfb9, -0x5e16ca69, 0x01667267, 0x6082dfeb, 0x05ffb9cd }, + { -0x72582d11, 0x216ab2ca, -0x660bd7d9, 0x366ad9dd, 0x4fdd3c75, -0x519b4700, 0x53909e62, 0x403a395b }, + { -0x0ac09ec7, -0x59e80561, 0x13e66cb6, 0x60f2b5e5, -0x4cbb755c, -0x28574111, 0x6f5ea192, 0x7a293285 } + }, + { + { 0x79639302, -0x4763bbb8, 0x50c67f2c, 0x4ae4f193, -0x37e5063a, -0x0f4ca258, 0x46871017, 0x39d00035 }, + { -0x4fd21778, 0x0b39d761, -0x2dbeb1e1, 0x5f550e7e, 0x22e1a940, -0x59405ba8, -0x02bb8467, 0x050a2f7d }, + { -0x59af2489, 0x437c3b33, -0x453ad44e, 0x6bafe81d, 0x2db7d318, -0x0166bfd3, 0x372ba6ce, 0x2b5b7eec } + }, + { + { 0x613ac8f4, -0x596bbfb3, -0x056818d4, 0x500c3c2b, 0x1fcec210, -0x78befb2e, -0x79fb5712, 0x1b205fb3 }, + { -0x7c0af111, -0x4c43b443, -0x736d879a, 0x508f0c99, -0x37481992, 0x43e76587, -0x5b806727, 0x0f7655a3 }, + { -0x2db4ecc4, 0x55ecad37, 0x6038c90b, 0x441e147d, -0x29d39012, 0x656683a1, -0x781f1352, 0x0157d5dc } + }, + { + { -0x28e14adc, -0x6ad9aaec, 0x5df14593, -0x19fc277f, 0x0d4de6b7, 0x147cdf41, 0x0437c850, 0x5293b173 }, + { 0x0354c13d, -0x0d5850af, -0x55c8d4a0, -0x285f4ebb, 0x05a3d470, 0x2869b96a, -0x7db9fe8d, 0x6528e42d }, + { 0x4bccf226, 0x23d0e081, -0x7e69046d, -0x6d38ba33, 0x59541e5b, -0x749e8694, -0x3fde0688, 0x40a44df0 } + }, + { + { 0x4bc5d095, -0x793691af, -0x03597fb6, -0x0df2bf68, -0x37d915a3, 0x27363d89, 0x5719cacf, 0x39ca3656 }, + { 0x4f20ea6a, -0x25579677, 0x4c620618, -0x15eb5c2f, 0x090bf8be, 0x6001fccb, -0x6b816310, 0x35f4e822 }, + { 0x6f87b75c, -0x68af90d1, 0x034ae070, -0x39db5160, -0x552cb22a, 0x1ec856e3, -0x1bbf1a71, 0x055b0be0 } + }, + { + { 0x6ea33da2, 0x4d12a04b, -0x1c9ed923, 0x57cf4c15, -0x11bb2699, -0x6f13698b, 0x2a985aac, 0x64ca348d }, + { -0x768ca2ee, 0x6469a17d, -0x199d460f, -0x2490d82b, 0x6a395681, -0x60345cd8, -0x2d9650db, 0x363b8004 }, + { -0x1b3b6ed3, -0x66a771e7, 0x1ca5ce6b, -0x1033c4b2, -0x05a4672b, 0x4522ea60, 0x1de4a819, 0x7064bbab } + }, + { + { 0x42542129, -0x5d6f3f9f, -0x4172a470, -0x0d1d3d52, 0x76abfe1b, -0x30dba725, -0x7c29d941, 0x02157ade }, + { 0x5a770641, -0x46e61eaf, 0x4e7f8039, -0x565d1d39, 0x3df23109, 0x7527250b, -0x53d84875, 0x756a7330 }, + { 0x1b9a038b, 0x3e46972a, 0x7ee03fb4, 0x2e4ee66a, 0x6edbb4ca, -0x7e5db789, -0x7132fa9d, 0x1a944ee8 } + }, + { + { 0x182362d6, -0x44bf57a7, -0x75b2e545, -0x4660aa89, 0x758559f6, -0x72e74bd9, 0x4d26235a, 0x26c20fe7 }, + { 0x51039372, -0x2a56e2ef, -0x6635d922, 0x2ed377b7, -0x02c99495, -0x5e8dfd54, -0x296fe66b, 0x0730291b }, + { -0x1633dd0b, 0x648d1d9f, 0x28dd577c, 0x66bc5619, 0x652439d1, 0x47d3ed21, -0x125074b7, 0x49d271ac } + }, +}, +{ + { + { -0x4b48a9ff, 0x2798aaf9, 0x5c8dad72, 0x5eac7213, 0x61b7a023, -0x2d31559f, -0x167082b2, 0x1bbfb284 }, + { 0x382b33f3, -0x760afa76, -0x52b73f4c, 0x5ae2ba0b, -0x5ac24c92, -0x706c4afd, -0x6a5dcd1a, 0x5aa3ed9d }, + { -0x38269a9f, 0x656777e9, 0x72c78036, -0x34d4edac, -0x26af9112, 0x65053299, 0x5e8957cc, 0x4a07e14e } + }, + { + { -0x3b885b65, 0x240b58cd, 0x6447f017, -0x02c72522, -0x58379553, 0x19928d32, -0x7b505f7f, 0x50af7aed }, + { -0x67f20667, 0x4ee412cb, 0x3c6ec771, -0x5cea2891, -0x6da38803, -0x445a1222, 0x1d313402, 0x3f0bac39 }, + { 0x15f65be5, 0x6e4fde01, 0x216109b2, 0x29982621, 0x0badd6d9, 0x78020581, -0x45142ffa, 0x1921a316 } + }, + { + { -0x260c3e75, -0x28a55266, 0x60b1c19c, 0x566a0eef, 0x255c0ed9, 0x3e9a0bac, -0x5f9d380b, 0x7b049dec }, + { -0x20478f04, -0x76bdd082, 0x4f76b3bd, 0x2c296beb, 0x36c24df7, 0x0738f1d4, -0x1d8c5150, 0x6458df41 }, + { 0x35444483, -0x23341c86, 0x0fedbe93, 0x75887933, 0x12c5dd87, 0x786004c3, -0x3d6af19c, 0x6093dccb } + }, + { + { 0x6084034b, 0x6bdeeebe, 0x780fb854, 0x3199c2b6, -0x49d2f96b, -0x68cc8955, -0x749b8270, 0x6e3180c9 }, + { -0x7a1f8f93, 0x1ff39a85, -0x4c18c6cd, 0x36d0a5d8, 0x718f453b, 0x43b9f2e1, 0x4827a97c, 0x57d1ea08 }, + { -0x5ed74f8f, -0x11854919, -0x6c577456, -0x5b3ea693, -0x4dde9ed0, -0x084b217e, -0x226842e8, 0x363e999d } + }, + { + { -0x1db4513a, 0x2f1848dc, -0x454350a0, 0x769b7255, 0x3cefe931, -0x6f34c392, -0x39064cab, 0x231f979b }, + { 0x35ee1fc4, -0x6957bc3f, 0x08e4c8cf, -0x68914cab, -0x4a732cd0, -0x4bd097ff, 0x693a052b, 0x48ee9b78 }, + { -0x33d50c3a, 0x5c31de4b, -0x01df72e1, -0x4fb44fd0, -0x3eb04b9a, -0x48728ff7, 0x08792413, 0x079bfa9b } + }, + { + { -0x5d2abdbb, -0x0c361280, 0x77f63952, 0x0aa08b78, -0x2ef7ab8b, -0x2892539d, -0x6b8f9c95, 0x1ef4fb15 }, + { -0x25cff20c, -0x1c6fc5af, 0x3da95ab0, -0x7bc69bdd, 0x0b356480, -0x12c30ed3, -0x7b7e8e6c, 0x038c77f6 }, + { 0x5b167bec, -0x7ab1a11a, -0x692f323e, 0x59590a42, -0x67efde67, 0x72b2df34, 0x4a0bff56, 0x575ee92a } + }, + { + { 0x0aa4d801, 0x5d46bc45, -0x5acc4628, -0x3c50edd9, 0x2b8906c2, 0x389e3b26, 0x382f581b, 0x200a1e7e }, + { -0x75e7d031, -0x2b3f7f70, -0x66b76243, 0x30e170c2, 0x52f733de, 0x05babd57, 0x2cd3fd00, 0x43d4e711 }, + { -0x1506c53b, 0x518db967, 0x056652c0, 0x71bc989b, 0x567197f5, -0x01d47a27, 0x651e4e38, 0x050eca52 } + }, + { + { 0x60e668ea, -0x6853c68a, 0x153ab497, -0x64e64402, 0x34eca79f, 0x4cb179b5, -0x5ece51a9, 0x6151c09f }, + { 0x453f0c9c, -0x3cbce522, -0x008fc465, -0x160afba2, -0x127b84c3, -0x03268537, 0x1c58f4c6, 0x4b0ee6c2 }, + { -0x020fa26a, 0x3af55c0d, 0x2ab4ee7a, -0x22d9d120, 0x12171709, 0x11b2bb87, -0x7ff0fcf5, 0x1fef24fa } + }, +}, +{ + { + { -0x6fe99de0, -0x006e5996, 0x5bf1e009, -0x0ddaad52, 0x7f90df7c, 0x7dff85d8, 0x0c736fb9, 0x4f620ffe }, + { 0x6b6c6609, -0x4b69edc6, -0x7f54a6c8, -0x58af017b, -0x483d85a1, -0x0b8e40c7, 0x77ac193c, 0x507903ce }, + { -0x2021c1cc, 0x62f90d65, -0x4605a053, -0x30d73a6e, -0x39e9baf0, -0x66379107, 0x4a256c84, 0x25d44804 } + }, + { + { -0x36fdd4ab, 0x2c7c4415, -0x7ed14e02, 0x56a0d241, -0x2849a1f3, -0x0fd15e37, -0x2acdc4da, 0x4180512f }, + { -0x38164e91, -0x4297dcf2, -0x3e3a86a3, 0x0eb1b9c1, -0x6a494e01, 0x7943c8c4, 0x0bbacf5e, 0x2f9faf62 }, + { -0x75b75a25, -0x5b00c197, -0x426abfc5, -0x4595c7fa, 0x47d5b65d, -0x60831e51, 0x5939d2fb, 0x15e087e5 } + }, + { + { -0x0469c0c8, -0x776be792, -0x239c642b, 0x48a00e80, -0x1693e367, -0x5b17f6d5, -0x35a8c99f, 0x5a097d54 }, + { 0x745c1496, 0x12207543, -0x25c79ef4, -0x2500c303, 0x2c71c34f, -0x1b1868d9, 0x34bdede9, 0x39c07b19 }, + { 0x17c9e755, 0x2d45892b, -0x76cf7208, -0x2fcc028e, 0x525b8bd9, 0x6c2fe9d9, -0x3ee33f87, 0x2edbecf1 } + }, + { + { -0x2f785da1, -0x11f0f023, 0x5c3e34ee, -0x638aceab, -0x7054c54b, 0x660c572e, 0x544cd3b2, 0x0854fc44 }, + { -0x38ea5f2e, 0x1616a4e3, -0x07cbe2b3, 0x53623cb0, -0x38176635, -0x6910acd7, -0x5997455a, 0x3d4e8dbb }, + { 0x55edad19, 0x61eba0c5, -0x0f57c21a, 0x24b533fe, -0x7c455a08, 0x3b770428, -0x675b8173, 0x678f82b8 } + }, + { + { 0x57775696, 0x1e09d940, 0x3cd951db, -0x112ed9a4, 0x20bce16f, -0x056253d5, -0x172f760c, 0x0f7f76e0 }, + { -0x296ff3ac, -0x4eb6e2f5, -0x62ecd9ca, 0x3539722c, 0x0b362bc9, 0x4db92892, -0x59749621, 0x4d7cd1fe }, + { -0x2b7a4ff4, 0x36d9ebc5, -0x1b524c9b, -0x5da69b6e, -0x3dee6333, -0x3e9a6b80, 0x186e0d5f, 0x45306349 } + }, + { + { 0x2b072491, -0x695beb14, 0x27a7b65b, 0x1bb22181, 0x6e8a4af0, 0x6d284959, -0x32d889a1, 0x65f3b08c }, + { -0x593200e3, -0x6b222f3f, -0x17bdec52, 0x55f6f115, -0x66d03096, 0x6c935f85, 0x4a37f16f, 0x067ee0f5 }, + { 0x199801f7, -0x134d6001, -0x5d5f08d1, -0x62c9e2e1, 0x75fd2f49, 0x25f11d23, 0x0fe10fe2, 0x124cefe8 } + }, + { + { 0x31b16489, 0x1518e85b, -0x248ef405, -0x70552349, -0x5eb51dc7, 0x39b0bdf4, 0x503d20c1, 0x05f4cbea }, + { -0x2e720dab, 0x4c126cf9, 0x147a63b6, -0x3e2b8e17, -0x0c36c4a1, 0x2c6d3c73, -0x1c00795e, 0x6be3a6a2 }, + { -0x3fbeba44, -0x31fbf162, 0x08f6834c, -0x38e00b1e, -0x5477b85d, -0x42ab9173, -0x5b2d545b, 0x64666aa0 } + }, + { + { 0x3337e94c, -0x4f3ac409, 0x11e14f15, 0x7cb5697e, 0x1930c750, 0x4b84abac, -0x1f9bfb98, 0x28dd4abf }, + { 0x7c06d912, 0x6841435a, -0x44c07cf5, -0x35edc3df, -0x4e341d88, -0x2b4c84d9, -0x3890afba, 0x1d753b84 }, + { 0x44cb9f44, 0x7dc0b64c, -0x1c6da241, 0x18a3e1ac, 0x2d0457c4, 0x7a303486, -0x75f376d2, 0x4c498bf7 } + }, +}, +{ + { + { 0x30976b86, 0x22d2aff5, -0x3d2db9fc, -0x726f47fa, 0x4de5bae5, -0x235e7694, -0x37cbf3e9, 0x28005fe6 }, + { 0x1aa73196, 0x37d653fb, 0x3fd76418, 0x0f949530, -0x04c5e84e, -0x52dff4f7, 0x2fc8613e, 0x544d4929 }, + { 0x34528688, 0x6aefba9f, 0x25107da1, 0x5c1bff94, 0x66d94b36, -0x08a44433, 0x0f316dfa, 0x72e47293 } + }, + { + { -0x2cd589d9, 0x07f3f635, 0x5f6566f0, 0x7aaa4d86, 0x28d04450, 0x3c85e797, 0x0fe06438, 0x1fee7f00 }, + { -0x687ef7b1, 0x2695208c, 0x23450ee1, -0x4eafd5f5, 0x03efde02, -0x0262515a, 0x2733a34c, 0x5a9d2e8c }, + { 0x03dbf7e5, 0x765305da, 0x1434cdbd, -0x5b250db7, -0x2db57714, 0x7b4ad5cd, -0x11fbfabd, 0x00f94051 } + }, + { + { 0x07af9753, -0x28106c45, 0x3db766a7, 0x583ed0cf, 0x6e0b1ec5, -0x31966741, 0x5dd40452, 0x47b7ffd2 }, + { -0x3c2ccf4e, -0x72ca94dd, -0x4fb8e4fa, -0x0de37465, 0x6e42b83c, -0x4c93ce94, -0x74154ef3, 0x07d79c7e }, + { -0x43f722ee, -0x78040464, -0x1e113d65, -0x75f994c6, -0x24e03e41, 0x0d57242b, 0x5ea64bb6, 0x1c3520a3 } + }, + { + { 0x216bc059, -0x325790c0, 0x12bcd87e, 0x1fbb231d, 0x17c70990, -0x4b6a9562, 0x66d12e55, 0x38750c3b }, + { -0x43345cb6, -0x7f2dac5a, 0x3838219b, 0x3e61c3a1, -0x677d1c6a, -0x6f3c49ff, 0x5d0ee66f, 0x1c3d0577 }, + { -0x6bdd1ae6, 0x692ef140, 0x2b5df671, -0x343f38c4, 0x744ce029, 0x21014fe7, -0x2ccfb784, 0x0621e2c7 } + }, + { + { -0x4f240f0d, -0x4851e86a, -0x1e831e6a, 0x54dfafb9, -0x16555c4c, 0x25923071, -0x5effd163, 0x5d8e589c }, + { -0x7da67c73, -0x50679f34, -0x39606524, -0x6f15b73f, 0x65581e30, 0x65264837, 0x7bd3a5bc, 0x0007d609 }, + { 0x0842a94b, -0x3f40e26b, 0x588f2e3e, -0x4d2c3c9d, -0x44ae1d11, 0x0a961438, 0x3c1cbf86, 0x1583d778 } + }, + { + { -0x3362d739, -0x6ffcb8fc, -0x08d33a71, 0x1d1b679e, -0x41a478da, 0x16e12b5f, -0x7c3aa7f6, 0x4958064e }, + { 0x5da27ae1, -0x13115d11, 0x55670174, 0x597c3a14, 0x6609167a, -0x3659d5ee, -0x7e127090, 0x252a5f2e }, + { 0x5066e80d, 0x0d289426, 0x307c8c6b, -0x033c087b, 0x0c1112fd, 0x1b53da78, -0x27bc4c78, 0x079c170b } + }, + { + { -0x3f2a2faa, -0x322932b0, -0x44fca8c5, -0x65089793, -0x0c3c10b8, 0x3ca6723f, 0x317b8acc, 0x6768c0d7 }, + { 0x64fa6fff, 0x0506ece4, 0x6205e523, -0x411cbce2, 0x51b8ea42, 0x35794224, 0x4ac9fb00, 0x6dec05e3 }, + { -0x0eaa3e4d, -0x6b49da1b, -0x6684846f, 0x417bf3a7, 0x6d6b2600, -0x3dd34224, -0x2232ad0c, 0x51445e14 } + }, + { + { 0x2bbea455, -0x76ceb855, -0x6df86ed7, -0x73ac5db1, -0x41cf0859, 0x4b49f948, 0x6e4fd43d, 0x12e99008 }, + { 0x3b144951, 0x57502b4b, 0x444bbcb3, -0x71980095, 0x166385db, -0x474296d9, -0x1c6d6a38, 0x13186f31 }, + { 0x7fdfbb2e, -0x0ef3694d, 0x121ceaf9, -0x60656ca2, 0x3a5b983f, -0x20eec93c, 0x5d3e99af, 0x77b2e3f0 } + }, +}, +{ + { + { -0x33a32d65, -0x6acd0b71, -0x5c31c98f, 0x2ba851be, 0x51122941, 0x32dacaa0, 0x350004f2, 0x478d99d9 }, + { -0x630ed9a9, -0x02f28a79, -0x1ac5f1d7, -0x17d0106c, 0x5bbb4be7, -0x33cb5810, -0x5af3c75e, 0x0b251172 }, + { -0x6f44fd40, 0x1d5ad948, 0x0ec25115, 0x50e208b1, 0x4ef21702, -0x5d95dd77, 0x3b524805, 0x4dc92334 } + }, + { + { -0x0c93b68b, 0x3ad3e3eb, 0x37862125, -0x28a2da5b, -0x5fda5aea, -0x178c6bc3, -0x3bee37b9, 0x6bbc7cb4 }, + { 0x0f8086b6, -0x1c7d73c0, -0x6860f238, 0x3f77e6f7, 0x4df42cb4, 0x7ef6de30, -0x4954287c, 0x5265797c }, + { -0x2b5af2aa, 0x3c6f9cd1, -0x39015482, -0x49dbbf89, 0x3580972e, 0x6ff9bf48, -0x4ccd5305, 0x00375883 } + }, + { + { 0x6c75c99c, -0x3674137b, 0x00e33cf4, -0x1bbe7b40, -0x456f89cc, 0x0a676b9b, 0x71f379d7, 0x669e2cb5 }, + { 0x28cb0940, 0x0001b2cd, 0x6f1c24c9, 0x63fb51a0, -0x232a35cf, -0x4a52796f, -0x73baf9a0, 0x67238dbd }, + { -0x5b642cf8, -0x34ee948d, 0x2392729e, 0x025aad6b, 0x3f55d9b1, -0x4b86c106, 0x40678bb9, 0x72a10561 } + }, + { + { -0x1d1afa4a, 0x0d8d2909, -0x3fd6edd0, -0x67358755, -0x564edcd9, 0x77ef5569, -0x7ebc64b9, 0x7c77897b }, + { 0x1cc9249d, -0x5d497ed5, 0x21211f58, 0x62866eee, 0x5df10ece, 0x2cb5c5b8, -0x1d9c5200, 0x03a6b259 }, + { -0x21cce34b, -0x0e3e4a1e, 0x15fca420, 0x5a9f5d8e, 0x7bd932b1, -0x605bc70f, 0x1c6146e7, 0x2a381bf0 } + }, + { + { -0x4acbe991, -0x083f41ce, 0x19cf70d4, 0x27e6ca64, -0x56a858a7, -0x6cb20829, -0x54213d56, 0x5701461d }, + { -0x3037ee3f, -0x53646787, 0x3756e567, -0x7482d67f, 0x7c70edfc, 0x50da4e60, -0x77bbff4a, 0x5dbca62f }, + { 0x2c915c25, 0x2c674740, 0x0b0d340a, 0x1bdcd1a8, 0x07b43f5f, 0x5e5601bd, 0x5539a242, 0x2555b4e0 } + }, + { + { -0x781b9c2c, 0x78409b1d, -0x32049c63, -0x52b256a6, 0x55259b9c, -0x13d788c9, -0x3cedcf55, 0x69c806e9 }, + { 0x66ddd216, 0x6fc09f52, -0x371c8fb8, -0x231a9f59, -0x5d209d03, -0x139a6c63, -0x1ad12e6e, 0x7a869ae7 }, + { 0x14bb3f22, 0x7b48f574, -0x51233378, 0x68c7cee4, 0x79ed80be, -0x12d06c9f, 0x5f77bc4b, 0x25d70b88 } + }, + { + { -0x44e51b2c, -0x67ba62d7, 0x39f954ec, 0x56b9c4c7, -0x3d64b4c2, -0x7cd8bc0a, -0x67497876, 0x21ea8e27 }, + { 0x762bf4de, 0x4151c3d9, 0x2745d82b, 0x083f435f, 0x0d23ddd5, 0x29775a2e, 0x69a5db24, 0x138e3a62 }, + { 0x6a5a7b9c, -0x78410b4c, 0x5fc1d062, -0x2dd662e5, -0x22cde9b8, -0x7dbf67e8, -0x1a5d1fc3, 0x5c5abeb1 } + }, + { + { 0x1306a233, 0x02cde6de, 0x116f8ec7, 0x7b5a52a2, -0x3ee9c4a5, -0x1e397e0c, 0x60d32643, 0x241d3506 }, + { -0x48c3d225, 0x14722af4, 0x5a05060d, -0x43b8f3a1, 0x2581b02e, 0x00943eac, 0x1f499c8f, 0x0e434b3b }, + { 0x0ebc52c7, 0x6be4404d, -0x4e586e0b, -0x51b9dcc5, -0x2da24bd5, 0x2aec170e, 0x6645d694, 0x1d8dfd96 } + }, +}, +{ + { + { 0x12ddb0a4, -0x2a679c64, -0x3fdb7995, -0x5a2e60d0, 0x58fce460, -0x2e83d0fd, 0x2e095e8a, 0x07a19515 }, + { -0x63d13b22, 0x296fa9c5, 0x4f84f3cb, -0x43749e41, 0x17a8f908, 0x1c7706d9, 0x7ad3255d, 0x63b795fc }, + { 0x389e5fc8, -0x57c970fe, -0x30721bc5, -0x6fbcc4fe, -0x3abed9bd, -0x505e02a3, 0x032f0137, 0x3e8fe83d } + }, + { + { -0x17102ec4, 0x08704c8d, 0x33e03731, -0x203ae572, 0x1260cde3, -0x5a62a25b, -0x59da737a, 0x22d60899 }, + { 0x0570a294, 0x2f8b15b9, 0x67084549, -0x6b0dbd90, 0x61bbfd84, -0x21e3a51f, 0x7fac4007, 0x75ba3b79 }, + { 0x70cdd196, 0x6239dbc0, 0x6c7d8a9a, 0x60fe8a8b, -0x14bfeda0, -0x4c77b844, -0x788861a2, 0x0904d07b } + }, + { + { 0x48f940b9, -0x0bcdd29a, -0x42d2f3c7, 0x06952f0c, -0x5f7e06cf, 0x167697ad, -0x4508d594, 0x6240aace }, + { -0x22456e64, -0x4b31e02c, -0x38b37256, -0x30ce24c2, -0x527933af, 0x2c63cc63, -0x43e221f9, 0x43e2143f }, + { 0x5ba295a0, -0x07cb8b64, -0x35c82da6, -0x296b83a5, -0x1836ce96, 0x66f13ba7, -0x724bf354, 0x56bdaf23 } + }, + { + { -0x3e62c44e, 0x1310d36c, 0x622386b9, 0x062a6bb7, -0x285eb0a4, 0x7c9b8591, 0x7e1e5754, 0x03aa3150 }, + { -0x0acacc15, 0x362ab9e3, 0x6eb93d40, 0x338568d5, 0x1d5a5572, -0x61f1ebae, -0x7c8bece8, 0x1d24a86d }, + { -0x002b31e1, -0x0b1389b8, 0x54ac8c1c, -0x1fba1510, 0x1d09357c, -0x772dda7e, -0x6514b7a7, 0x43b261dc } + }, + { + { 0x6c951364, 0x19513d8b, 0x000bf47b, -0x6b018eda, -0x2ab06a99, 0x028d10dd, 0x42940964, 0x02b4d5e2 }, + { -0x77448645, -0x1aa4e1e7, -0x3e85ca63, -0x5f612f83, 0x603dea33, -0x4fd3d11e, 0x5b276bc2, 0x326055cf }, + { 0x28d18df2, -0x4b5eaa35, 0x186ce508, -0x1533b9ba, 0x6c824389, -0x3b630b6d, -0x51a2cbf0, 0x27a6c809 } + }, + { + { -0x3bc296ac, -0x32d3d8f6, 0x6a66cab2, -0x22b5c1a9, 0x69d7036c, 0x79fa5924, 0x3d8c2599, 0x22150360 }, + { 0x1f0db188, -0x74591433, 0x675a5be8, 0x37d3d73a, 0x15f5585a, -0x0dd1205d, -0x009f5e82, 0x2cb67174 }, + { 0x390be1d0, 0x59eecdf9, 0x728ce3f1, -0x56bddfbc, 0x7a94f0f4, -0x7d76e39a, 0x3890f436, 0x7b1df4b7 } + }, + { + { 0x07f8f58c, 0x5f2e2218, -0x2b6bf62c, -0x1caaa361, 0x1fb6a630, -0x4d555773, -0x2cad1fc3, 0x68698245 }, + { -0x4c4d5ddc, -0x1b6d0d20, 0x2b551160, 0x7c6c9e06, 0x0d7f7b0e, 0x15eb8fe2, 0x58fc5992, 0x61fcef26 }, + { 0x2a18187a, -0x244ea27b, -0x79225329, -0x0c1b552d, 0x0ff6c482, 0x44bae281, 0x3daf01cf, 0x46cf4c47 } + }, + { + { -0x0eb67ec0, 0x213c6ea7, 0x392b4854, 0x7c1e7ef8, 0x5629ceba, 0x2488c38c, 0x0d8cc5bb, 0x1065aae5 }, + { -0x613b1a07, 0x426525ed, 0x16903303, 0x0e5eda01, -0x341a3524, 0x72b1a7f2, 0x14eb5f40, 0x29387bcd }, + { -0x20dff2a9, 0x1c2c4525, -0x403598b6, 0x5c3b2dd6, -0x1e7cbfd0, 0x0a07e7b1, 0x4f1ce716, 0x69a198e6 } + }, +}, +{ + { + { -0x61d2b8cc, 0x7b26e56b, -0x7e39e98b, -0x3b38ecd5, -0x13632181, -0x10a36adb, -0x18e8bc53, 0x39c80b16 }, + { -0x10562969, 0x7afcd613, 0x1c067959, 0x0cc45aa4, -0x3e05256a, -0x5a901efc, 0x72e40365, 0x3a73b704 }, + { 0x1b826c68, 0x0f196e0d, 0x4960e3db, -0x08e00f1e, 0x23b7436c, 0x61131670, 0x77da7282, 0x0cf0ea58 } + }, + { + { 0x3ba6945a, -0x1ccd312c, -0x177e3fa3, -0x21f4ec9f, 0x5e67ed3b, 0x1ad40f09, -0x4739c2a3, 0x5da8acda }, + { -0x222b3343, 0x196c80a4, -0x6a0d2263, 0x22e6f55d, 0x40d6c71b, -0x38a1cc39, -0x34c3fbd1, 0x7bb51279 }, + { 0x3a70159f, -0x3b4999b6, 0x0a904e14, 0x76194f0f, -0x5bf693ed, -0x5a9eb3c7, -0x68601313, 0x6cd0ff50 } + }, + { + { -0x4fb45e72, 0x7fecfabd, 0x3bddbcf7, -0x2f038404, 0x057a131c, -0x5be2b792, -0x0dddc59f, 0x641a4391 }, + { -0x70bbd754, -0x3f1f9819, -0x59eeca1d, 0x14835ab0, 0x38062935, -0x0de2eb0d, -0x20fb7b64, 0x6390a4c8 }, + { -0x59f95725, -0x3a3946a6, -0x4f97da0f, -0x6eb48062, 0x44fc9eff, 0x2a731f6b, 0x62705cfc, 0x30ddf385 } + }, + { + { 0x68bcd52c, 0x33bef2bd, 0x69482ef2, -0x39b62450, 0x41cb1aee, -0x4a4911f4, 0x0212a7e5, 0x5c294d27 }, + { -0x2e400807, 0x4e3dcbda, 0x20645717, -0x36ee717e, 0x0f189d56, -0x45333144, -0x2bb98998, 0x1b4822e9 }, + { 0x25563781, -0x54c9f581, 0x480f7958, 0x2512228a, 0x6114b4e3, -0x38a2fad9, -0x268901d6, 0x222d9625 } + }, + { + { 0x0a344f85, 0x0f94be7e, -0x780dd3c8, -0x14d05574, 0x4ee16f0f, -0x631e18a2, 0x18a08dea, 0x43e64e54 }, + { -0x4c8d531f, 0x1c717f85, 0x4638bf18, -0x7e6cf197, 0x6bc08b58, 0x239cad05, -0x7807000c, 0x0b34271c }, + { 0x1a35ce63, -0x7eaa1dae, -0x06edfd72, -0x41eff2b3, -0x5a822314, -0x4007f408, 0x6d6bc6e4, 0x57342dc9 } + }, + { + { 0x1e707bf6, -0x0c3c4349, 0x7291a762, 0x351d9b8c, -0x252965cd, 0x00502e6e, 0x1ec8807f, 0x522f521f }, + { -0x3731a668, -0x10110f9b, -0x4a34155e, -0x40fd6af0, 0x20b7c458, -0x739b5efa, 0x31c24855, 0x35134fb2 }, + { -0x065c6fd5, 0x272c1f46, -0x669a8434, -0x36e45c49, 0x4f8a1c0e, -0x519eb4d0, 0x0b99017b, 0x7afcaad7 } + }, + { + { -0x107bd495, -0x577ebe14, -0x6854193b, 0x55e7b147, 0x03784ffe, -0x738b7069, -0x5032ff49, 0x5b50a1f7 }, + { -0x5b4741bf, -0x3da212ac, 0x1bb0e2dd, -0x6fd2ec1f, -0x3217d54e, 0x41f43233, -0x3c551835, 0x1085faa5 }, + { -0x0ec9eceb, -0x647bf09a, 0x701003e9, 0x18462242, -0x1b5daf80, 0x65ed45fa, 0x3fda7320, 0x0a286239 } + }, + { + { 0x6ecb9d17, -0x69f18c85, -0x2983151f, -0x050db6b8, -0x2aa1e477, 0x37e7a9b4, -0x4b93a615, 0x5cb7173c }, + { 0x347cbc9d, 0x46ab13c8, -0x663edc7d, 0x3849e8d4, -0x7829b537, 0x4cea3140, -0x4e5d6119, 0x1f354134 }, + { -0x7d485410, 0x4a89e68b, -0x64594847, -0x0be326d9, -0x1e727891, 0x16e6c210, 0x7f1b09c6, 0x7cacdb0f } + }, +}, +{ + { + { -0x233a3513, -0x1efebbcc, 0x3c84fb33, 0x47ed5d96, -0x12795f19, 0x70019576, -0x2d98061c, 0x25b2697b }, + { -0x26e58744, -0x6f9d4d20, -0x37af6999, 0x47c9889c, 0x405070b8, -0x620ab59a, 0x2493a1bf, 0x7369e6a9 }, + { 0x13986864, -0x6298c005, 0x415dc7b8, 0x3ca5fbd9, -0x20d8c4a2, -0x1fb133c5, -0x4ab1b32e, 0x1420683d } + }, + { + { -0x3e33a530, 0x34eebb6f, -0x69b95375, 0x6a1b0ce9, -0x599421ad, -0x2c4f25b7, 0x61d081c1, 0x31e83b41 }, + { 0x249dd197, -0x4b8742e2, 0x5e58c102, 0x620c3500, -0x334553a4, -0x04fd2cd1, -0x0af758d3, 0x60b63beb }, + { -0x61f9d4b1, -0x681738ee, 0x29320ad8, 0x49e48f4f, 0x6f18683f, 0x5bece14b, 0x2d550317, 0x55cf1eb6 } + }, + { + { 0x7df58c52, 0x3076b5e3, -0x186633ca, -0x28c54623, 0x4913ee20, -0x427ce31d, 0x62ba0133, 0x1a56fbaa }, + { 0x65c23d58, 0x58791010, 0x5094819c, -0x7462f793, 0x12c55fa7, -0x1dbfd057, 0x570891d4, 0x669a6564 }, + { 0x5c9dc9ec, -0x6bc194b0, -0x5883c8e6, 0x302557bb, 0x41347651, -0x678c51aa, -0x663a75a4, 0x13c48367 } + }, + { + { 0x5d8bd080, -0x3b230496, 0x571a4842, -0x21143b14, -0x471aac9b, -0x2b4d177d, -0x371a47d9, 0x50bdc87d }, + { 0x5ab3e1b9, 0x423a5d46, -0x380ec09f, -0x03ec3e79, -0x134a464a, 0x19f83664, -0x59c849f9, 0x66f80c93 }, + { 0x6edfe111, 0x606d3783, -0x0fee5427, 0x32353e15, 0x25b73b96, 0x64b03ac3, 0x725fd5ae, 0x1dd56444 } + }, + { + { 0x08bac89a, -0x3d681a00, -0x151e3c20, 0x7d4cea11, -0x60186884, -0x0c1c741f, 0x63a305cd, 0x3a3a450f }, + { 0x3362127d, -0x705b8008, 0x71cd7c15, -0x4360953c, 0x49220c8b, 0x6e714543, 0x219f732e, 0x0e645912 }, + { -0x27c6b9d9, 0x078f2f31, -0x216b5af0, 0x389d3183, 0x17996f80, -0x2e1c9393, -0x6c565785, 0x318c8d93 } + }, + { + { -0x54e22c68, 0x5d669e29, 0x342d9e3b, -0x036de9a8, -0x0ca68c33, 0x55851dfd, 0x25950af6, 0x509a41c3 }, + { 0x2afffe19, -0x0d8ba2fd, 0x7f24db66, 0x0c9f3c49, -0x457a6711, -0x43672c1d, -0x65e2acec, 0x224c7c67 }, + { -0x5906da17, -0x423f9124, 0x641b1f33, 0x793ef3f4, -0x627cc177, -0x7d13ed80, 0x28a11389, 0x05bff023 } + }, + { + { 0x0dc512e4, 0x6881a0dd, 0x44a5fafe, 0x4fe70dc8, -0x70b5adc0, 0x1f748e6b, -0x11fe5c16, 0x576277cd }, + { 0x23cae00b, 0x36321370, -0x2e5330a7, 0x544acf0a, -0x2de5e378, -0x698befb7, -0x05d5bb59, 0x780b8cc3 }, + { 0x234f305f, 0x1ef38abc, 0x1405de08, -0x65a88043, 0x34e62a0d, 0x5e82a514, 0x6271b7a1, 0x5ff41872 } + }, + { + { 0x13b69540, -0x1a24b818, 0x432610e1, -0x0ca2d5c5, 0x38781276, -0x53e0d917, -0x5f5f3497, 0x29d4db8c }, + { 0x1789db9d, 0x398e080c, -0x0c18870b, -0x589fdfdb, 0x06bd035d, -0x056776b4, 0x25a966be, 0x106a03dc }, + { 0x333353d0, -0x2652f551, -0x532cf61b, 0x38669da5, -0x37770810, 0x3c57658a, 0x052cbefa, 0x4ab38a51 } + }, +}, +{ + { + { -0x7f621fac, -0x09701d18, -0x637d452f, -0x1c43f696, 0x0aadbf45, 0x076353d4, -0x215e6a62, 0x7b9b1fb5 }, + { 0x4324c0e9, -0x20253412, 0x3f955bb7, 0x05444288, -0x15ce9f61, -0x21085558, 0x42287cff, 0x68aee706 }, + { 0x7471cc0c, -0x0fe3370f, 0x579082bb, -0x6adbd1c9, -0x2c1b94a1, 0x27776093, 0x28bd85fb, 0x2d13d55a } + }, + { + { 0x7aee7a52, -0x40fe6332, -0x1bab152d, -0x57212d4a, -0x785744e7, 0x3c619f0b, 0x560916d8, 0x3619b5d7 }, + { 0x5b35b8da, -0x053a2dfa, -0x7a9db449, -0x57257566, 0x3d21cd0f, -0x332d356f, -0x7406f2a8, 0x6b8341ee }, + { 0x0282c4b2, 0x3579f26b, 0x4fafefae, 0x64d592f2, 0x28c8c7c0, -0x48321285, 0x7173a8d7, 0x6a927b6b } + }, + { + { 0x3ece88eb, -0x728fbf7a, -0x7f113f74, -0x0f1cf857, 0x0d788fda, -0x53ddaf9f, 0x3a0d478d, 0x056d92a4 }, + { -0x6791b9aa, 0x1f6db24f, -0x2e16efa5, 0x1021c02e, 0x2cc0a375, -0x0700c001, -0x3937da6e, 0x1d2a6bf8 }, + { -0x03c25a5f, 0x1b05a196, 0x43b59ed0, 0x77d7a8c2, -0x682e86e8, 0x06da3d62, -0x0edcac09, 0x66fbb494 } + }, + { + { -0x0edcf62a, -0x2928f66a, -0x163c2ac7, -0x2404dc7b, -0x08aadbef, 0x46d602b0, 0x57843e0c, 0x270a0b05 }, + { -0x27a3f048, 0x751a50b9, -0x7430f685, -0x2e5023db, -0x7cf65697, 0x2f16a6a3, -0x1a4ff9a7, 0x14ddff9e }, + { -0x5879d434, 0x61ff0640, 0x5f11abfe, -0x7e353f66, 0x55d12abb, -0x6fb87cfc, -0x6ba5178d, 0x19a4bde1 } + }, + { + { -0x3f893b61, 0x40c709de, 0x7f3e53f6, 0x657bfaf2, -0x135fbd3c, 0x40662331, 0x7eb4df04, 0x14b37548 }, + { 0x20a6200a, -0x6460d90b, -0x30ec1508, 0x64804443, -0x79ce122d, -0x759c98c1, 0x1ed39dc1, 0x72bbbce1 }, + { -0x549923b9, -0x517ac36c, -0x2089d292, -0x149dcbc2, 0x6fb2f7d1, -0x0f71f1e8, 0x700ab37a, 0x4f0b1c02 } + }, + { + { -0x3e4d1dc1, 0x79fd21cc, 0x453df52a, 0x4ae7c281, -0x2eaeb795, -0x37e8d137, 0x3e0a7534, 0x68abe944 }, + { -0x27e6ae06, -0x1e8f9879, -0x4d6f3885, -0x5ef5d372, 0x3ed66773, -0x18c7d060, 0x0bcc4b54, 0x0a4d8471 }, + { 0x07831dcb, -0x25ed393c, 0x4d5c510d, 0x0da230d7, 0x6bd404e1, 0x4ab1531e, -0x430bbf11, 0x4106b166 } + }, + { + { 0x39e4ecf2, -0x5b7a332b, 0x0555bab5, 0x5aa3f3ad, -0x6c8207d3, 0x145e3439, 0x1214283f, 0x1238b51e }, + { 0x1cd23668, 0x02e57a42, 0x0eaef6fd, 0x4ad9fb5d, -0x4edbbb80, -0x6ab198d9, 0x2699f331, 0x7f792f9d }, + { 0x5fd4d924, 0x0b886b92, 0x3626a80d, 0x60906f7a, -0x467542ee, -0x132c984c, -0x210cbb31, 0x2876beb1 } + }, + { + { 0x3a8a85f8, -0x2a6b4ccd, -0x187282a8, 0x4ea37689, 0x5e8e351f, 0x73bf9f45, -0x43be144c, 0x5507d7d2 }, + { 0x63144691, -0x237b16cb, -0x29e0dc0c, 0x632fe8a0, 0x12a9a8d5, 0x4caa8006, 0x0e9918d3, 0x48f9dbfa }, + { 0x299572fc, 0x1ceb2903, -0x6afd2f12, 0x7c8ccaa2, 0x11cce67b, -0x6e405bcc, 0x64a831e7, 0x57844819 } + }, +}, +{ + { + { 0x5fddc09c, -0x29302e11, -0x08a8a232, -0x17d4c103, 0x201634c2, 0x25d56b5d, 0x04ed2b9b, 0x3041c6bb }, + { 0x6768d593, -0x2583d4db, 0x4422ca13, -0x673e3fa9, -0x35f531e3, -0x0e57f42b, -0x3f775970, 0x29cdd1ad }, + { -0x26a91eb8, 0x0ff2f2f9, -0x60ca94d2, -0x5218688b, 0x5f6c025c, 0x1a4698bb, 0x14049a7b, 0x104bbd68 } + }, + { + { -0x29800e9d, -0x56a265a1, 0x4cc75681, -0x16d41963, -0x21df0da9, -0x4807fdb4, -0x04f8d20b, 0x204f2a20 }, + { 0x68f1ed67, 0x51f0fd31, -0x2790c43e, 0x2c811dcd, 0x04d2f2de, 0x44dc5c43, 0x092a7149, 0x5be8cc57 }, + { 0x30ebb079, -0x37ebc4c3, -0x429ad1d0, 0x7589155a, -0x7092a3cf, 0x653c3c31, -0x3d86e9e1, 0x2570fb17 } + }, + { + { 0x0bb8245a, 0x192ea955, -0x706faf2f, -0x37190458, -0x775b36cb, 0x7986ea2d, -0x21fe7998, 0x241c5f91 }, + { 0x2cb61575, 0x3efa367f, 0x1cd6026c, -0x0a06908a, 0x65b52562, -0x1738ebd6, 0x53030acd, 0x3dcb65ea }, + { 0x40de6caa, 0x28d81729, 0x22d9733a, -0x7040d310, 0x235b01d1, 0x16d7fcdd, 0x5fcdf0e5, 0x08420edd } + }, + { + { 0x04f410ce, 0x0358c34e, 0x276e0685, -0x49eca4a6, -0x1446eadf, 0x5d9670c7, 0x21db889c, 0x04d654f3 }, + { -0x7c9d05b6, -0x3200df55, -0x1de5c192, 0x57e118d4, -0x03c619d5, -0x1ce869e9, -0x43e89603, 0x0d9a53ef }, + { -0x22424a2b, 0x5e7dc116, -0x725a22d3, 0x2954deb6, 0x3334a292, 0x1cb60817, 0x18991ad7, 0x4a7a4f26 } + }, + { + { -0x50c8d5b5, 0x24c3b291, 0x718147f2, -0x6c257d90, -0x7976610e, -0x227b7a9c, 0x23e0ee33, 0x4a963142 }, + { 0x5fb15f95, -0x0b58e7fe, 0x6b5c1b8f, 0x3df65f34, 0x00e01112, -0x32030f7b, -0x222ce7b8, 0x11b50c4c }, + { 0x08a4ffd6, -0x5917d8bc, -0x63ea8927, 0x738e177e, 0x3d02b3f2, 0x773348b6, -0x319433af, 0x4f4bce4d } + }, + { + { -0x3b62f491, 0x30e2616e, -0x3513dce9, -0x1ba98e71, -0x0d94b05a, 0x48eb409b, 0x61595f37, 0x3042cee5 }, + { -0x1ddbda7c, -0x58e031a6, -0x6d0a7562, 0x26ea7256, 0x1cea3cf4, -0x2de5f629, -0x48e3fe1a, 0x73fcdd14 }, + { 0x449bac41, 0x427e7079, -0x431dcef6, -0x7aa51c93, 0x5f841a7c, 0x4cae7621, -0x65631e2a, 0x389e740c } + }, + { + { 0x570eac28, -0x3642870a, 0x27919ce1, -0x1aa4f4ce, -0x5e646e13, 0x65fc3eab, -0x29d9c970, 0x25c425e5 }, + { 0x34dcb9ce, 0x64fcb3ae, -0x1cb72f53, -0x68affcdd, 0x62c6381b, 0x45b3f07d, 0x465a6788, 0x61545379 }, + { -0x0e282192, 0x3f3e06a6, -0x71f9dcf8, 0x3ef97627, 0x4e8a6c77, -0x73eb09da, 0x15484759, 0x6539a089 } + }, + { + { 0x14bb4a19, -0x223b242c, -0x67bdb072, 0x19b2bc3c, 0x36ca7169, 0x48a89fd7, -0x0fe64270, 0x0f65320e }, + { -0x3c2d088d, -0x162de08c, 0x25c46845, -0x3eafabbf, -0x064661cd, 0x624e5ce8, -0x3a32e794, 0x11c5e4aa }, + { -0x35021f3a, -0x2b792e4f, 0x163b5181, 0x4f3fe6e3, -0x050d6c66, 0x59a8af0d, -0x13ccf8d6, 0x4cabc7bd } + }, +}, +{ + { + { 0x1a54a044, -0x083f5e64, 0x77bd9fbb, 0x4a1c5e24, 0x5af22972, -0x591c35ef, 0x3f2e9e0d, 0x1819bb95 }, + { 0x532f7428, 0x16faa8fb, 0x46a4e272, -0x242bd160, -0x74615b80, 0x5337653b, 0x23973f03, 0x40659472 }, + { 0x5e042e84, 0x498fbb79, 0x7698b714, 0x7d0dd89a, 0x27fe6295, -0x7404f45c, 0x21200524, 0x36ba82e7 } + }, + { + { 0x57274ed5, -0x372962f6, 0x60804b17, 0x45ba8032, 0x2255dfac, -0x20c325f0, 0x2709b339, 0x77d22123 }, + { 0x4245ec41, -0x29f13449, 0x34348716, -0x02641762, -0x1bdd7b22, -0x36dbf502, -0x2face24c, 0x4472f648 }, + { 0x64ad94d8, 0x498a6d70, -0x6509dd9d, -0x5a4a3703, 0x45c141f4, -0x735712fb, 0x662d358c, 0x2c63bec3 } + }, + { + { -0x7a790741, -0x65ae74c6, -0x344e6910, -0x6118e50a, -0x5dc7a30e, -0x55f9da1a, -0x2228372f, 0x1deb2176 }, + { -0x158786ab, 0x7fe60d8b, -0x4a0bfe49, -0x4623ee82, 0x19355cce, -0x6e383f66, -0x6bbd4121, 0x22692ef5 }, + { 0x2066cf6c, -0x7a9c2e66, 0x4dcc7cd7, 0x401bfd8c, -0x32f2709e, -0x26895942, -0x5d874fa2, 0x67cfd773 } + }, + { + { 0x5a4e586a, 0x2d5fa985, 0x49beab7e, 0x65f8f7a4, -0x0de2cc2d, -0x55f8b223, 0x1bcb9dee, 0x185cba72 }, + { -0x10c11b8b, -0x7213ce06, -0x61dd026e, -0x66240076, 0x4e26cab1, 0x512d1159, -0x13bcef47, 0x0cde561e }, + { -0x0b1c34bf, -0x6c79625d, 0x40f7977e, -0x40fc6d0b, -0x2fb9c47d, 0x026204fc, -0x61139113, 0x3ec91a76 } + }, + { + { -0x4f5cbfd1, 0x0fad2fb7, -0x04960b58, 0x46615ecb, -0x3a07155a, -0x08ba4338, 0x4a94e896, 0x7a5fa879 }, + { -0x087e9953, 0x1e9df75b, -0x14f32851, 0x4dfda838, -0x3e150678, -0x45ffd128, 0x11f33cfc, 0x13fedb3e }, + { 0x13cd67a1, 0x52958faa, -0x74244ae9, -0x69a11f7f, 0x2e8845b3, 0x16e58daa, 0x5499da8f, 0x357d397d } + }, + { + { 0x194bfbf8, 0x481dacb4, -0x451a7d67, 0x4d77e3f1, 0x7d1372a0, 0x1ef4612e, 0x70ff69e1, 0x3a8d867e }, + { -0x4f453194, 0x1ebfa05f, 0x1caf9a1e, -0x36cb9df4, 0x1d82b61a, -0x3388e33c, -0x5a08b014, 0x2d94a16a }, + { 0x55aff958, 0x6f58cd5d, 0x75567721, -0x45c155a4, -0x6e9add83, 0x75c12399, -0x3d0d4ca2, 0x69be1343 } + }, + { + { 0x684b8de3, -0x7d444254, 0x3fca0718, -0x5d0b3830, -0x1f695558, 0x337f92fb, 0x63587376, 0x200d4d8c }, + { -0x1e6836d6, 0x0e091d5e, 0x2945119f, 0x4f51019f, -0x0fcb1664, 0x143679b9, 0x4d24c696, 0x7d88112e }, + { 0x4893b32b, 0x208aed4b, -0x41a6469c, 0x3efbf23e, -0x245a1af9, -0x289d2150, -0x7e42626c, 0x69607bd6 } + }, + { + { -0x6cdc56fe, 0x3b7f3bd4, 0x6b2c6e53, 0x7c21b556, 0x3a7852a7, -0x1a45700b, -0x7c713200, 0x28bc77a5 }, + { 0x68de1ce1, -0x0941fdf0, 0x0edcbc1f, -0x172ae719, 0x1b5505a5, -0x1c100230, -0x2c13c030, 0x35f63353 }, + { -0x1da27fca, 0x63ba78a8, -0x6bcccb70, 0x63651e00, 0x288ce532, 0x48d82f20, 0x36b57524, 0x3a31abfa } + }, +}, +{ + { + { 0x3f78d289, -0x3f708771, -0x5ebfb261, -0x01cf58d4, -0x309a3363, -0x0d887404, 0x5acb2021, 0x7ee49816 }, + { 0x089c0a2e, 0x239e9624, 0x3afe4738, -0x38b73b40, 0x764fa12a, 0x17dbed2a, 0x321c8582, 0x639b93f0 }, + { -0x6eee5e3d, 0x7bd508e3, -0x7f6f8b77, 0x2b2b90d4, -0x518d02e7, -0x182d513e, -0x7a49fd5a, 0x0edf493c } + }, + { + { -0x7b89beed, 0x6767c4d2, -0x080a07cb, -0x5f6fbfc1, -0x35194122, 0x1c8fcffa, -0x2e205c97, 0x04c00c54 }, + { 0x599b5a68, -0x51337ea8, -0x14521df2, -0x15a8b0f1, 0x22b67f07, 0x4fe41d74, 0x019d4fb4, 0x403b92e3 }, + { -0x74b9a308, 0x4dc22f81, 0x1480eff8, 0x71a0f35a, 0x04c7d657, -0x51174053, -0x4d9e890c, 0x355bb12a } + }, + { + { 0x5a8c7318, -0x5cfe2539, -0x4c3155ef, -0x126ffc63, 0x3bae3f2d, 0x6f077cbf, -0x1fad5272, 0x7518eaf8 }, + { 0x7493bbf4, -0x58e19b34, -0x135c4f3d, -0x1a427b27, -0x05fa187b, 0x0a6bc50c, 0x182ec312, 0x0f9b8132 }, + { 0x1b7f6c32, -0x5b77a63c, -0x0bc7cd68, 0x0f2d60bc, -0x364e2e27, 0x1815a929, -0x44e8aa3c, 0x47c3871b } + }, + { + { -0x37af9950, -0x0419a2b0, -0x4c5d6650, 0x62ecc4b0, 0x441ae8e0, -0x1ac8ab16, -0x172b72a1, 0x08fea02c }, + { 0x71ec4f48, 0x51445397, -0x3673a292, -0x07fa4e83, 0x47c3c66b, -0x089d3ee6, 0x764699dc, 0x00b89b85 }, + { 0x68deead0, -0x7db2228a, 0x4b685d23, -0x379bbae0, 0x5d89d665, -0x4aeb3033, 0x4f75d537, 0x473829a7 } + }, + { + { -0x52c6fd37, 0x23d9533a, -0x10fca771, 0x64c2ddce, -0x301ed04c, 0x15257390, 0x44e4d390, 0x6c668b4d }, + { 0x4679c418, -0x7d2d258b, -0x4d9e7210, -0x19c42828, -0x53b814f6, 0x355eef24, 0x4833c6b4, 0x2078684c }, + { 0x7a78820c, 0x3b48cf21, -0x7ed8c169, -0x0895f54e, -0x73711285, -0x56939a59, 0x4f8a433f, 0x7411a605 } + }, + { + { 0x18b175b4, 0x579ae53d, -0x0c6d5efe, 0x68713159, 0x1eef35f5, -0x7baa1346, 0x458c398f, 0x1ec9a872 }, + { -0x46623793, 0x4d659d32, 0x603af115, 0x044cdc75, -0x233d1b78, -0x4cb38ed4, -0x047ecb01, 0x7c136574 }, + { 0x00a2509b, -0x47195b2c, 0x0bc882b4, -0x647e28fe, -0x0e6a8a9f, 0x57e7cc9b, -0x38329ba0, 0x3add88a5 } + }, + { + { 0x59393046, -0x7a3d672c, 0x5ff659ec, -0x7081ca68, -0x0d0991c6, 0x1d2ca22a, -0x5bf958e0, 0x61ba1131 }, + { -0x49ca230e, -0x5476a890, -0x0993e044, 0x02dfef6c, -0x41492e79, -0x7aacfd98, -0x3378618c, 0x249929fc }, + { 0x16959029, -0x5c2f5f0f, -0x45814277, 0x023b6b6c, 0x26783307, 0x7bf15a3e, -0x44271319, 0x5620310c } + }, + { + { 0x77e285d6, 0x6646b5f4, 0x6c8f6193, 0x40e8ff67, -0x544a6b23, -0x59138cef, 0x658cec4d, 0x7ec846f3 }, + { 0x4934d643, 0x52899343, -0x5aeddd0b, -0x462407fa, -0x3c0be3de, -0x70927871, 0x4d9d9730, 0x37676a2a }, + { 0x1da22ec7, -0x64a170c1, 0x6c01cd13, 0x130f1d77, -0x5d676048, 0x214c8fcf, 0x399b9dd5, 0x6daaf723 } + }, +}, +{ + { + { 0x2cd13070, -0x7e514423, -0x07a5f162, -0x69d1bcdb, -0x35200135, -0x216c6e56, 0x52c230e6, 0x53177fda }, + { 0x10628564, 0x591e4a56, -0x574b20cc, 0x2a4bb87c, -0x185c71bd, -0x21d5da8e, -0x011afb92, 0x3cbdabd9 }, + { 0x50b9de79, -0x584368fa, -0x3cfe4a65, 0x3d12a7fb, -0x2c951c74, 0x02652e68, 0x5a6199dc, 0x79d73983 } + }, + { + { 0x0d591737, 0x21c9d992, -0x164b932a, -0x6415be2e, 0x0d89bfca, -0x1df17be0, 0x6eae5ff8, 0x79d99f94 }, + { 0x4131c1bd, -0x26cab20a, -0x7913a7de, 0x758094a1, -0x1ba60c3e, 0x4464ee12, -0x34eccd7e, 0x6c11fce4 }, + { 0x68673205, -0x0e84b7cb, 0x3caad96c, 0x387deae8, 0x56ffe386, 0x61b471fd, -0x48ba5a67, 0x31741195 } + }, + { + { 0x3b02a047, 0x17f8ba68, -0x01104938, 0x50212096, 0x1556cbe2, 0x70139be2, 0x1d98915b, 0x203e44a1 }, + { -0x4885c9f5, -0x172efe70, -0x666a18fe, -0x66467ce0, -0x05fdb856, -0x42b02008, -0x1f2c9579, 0x2772e344 }, + { 0x37b9e39f, -0x2979c146, 0x723b5a23, 0x105bc169, -0x59a3f89e, 0x104f6459, 0x5b4d38d4, 0x56795129 } + }, + { + { 0x0d4b497f, 0x07242eb3, -0x46433379, 0x1ef96306, -0x27ee90bb, 0x37950934, 0x01405b04, 0x05468d62 }, + { 0x13037524, 0x535fd606, -0x4f043d96, -0x1def520a, 0x23e990ae, -0x5372f565, -0x28d02407, 0x47204d08 }, + { -0x06cd9822, 0x00f565a9, -0x3f2a7176, -0x31302873, -0x0ce71d72, -0x5dea1d24, -0x649cccae, 0x4599ee91 } + }, + { + { -0x79e51a87, -0x538b9295, -0x09515624, 0x31ab0650, 0x40256d4c, 0x241d6611, 0x3d21a5de, 0x2f485e85 }, + { 0x70e0e76b, -0x2c3ddf36, -0x1560cf6c, -0x4ed415a8, -0x3cd8ed7e, 0x294ddec8, -0x5e2e2fd8, 0x0c3539e1 }, + { -0x63f7cc0d, 0x32974483, -0x2d543b7c, 0x6fe6257f, 0x4b358817, 0x5327d181, -0x76c01644, 0x65712585 } + }, + { + { -0x28f711c1, -0x7e3d60e5, -0x519bf830, -0x2234a5fb, -0x2d5c1459, -0x68513e29, -0x6e2af7cf, 0x1590521a }, + { 0x32a61161, -0x63efd049, 0x34d520a8, -0x1b71ef23, 0x6f9a9176, 0x365c6354, 0x046f6006, 0x32f6fe4c }, + { -0x386ef534, 0x40a3a11e, -0x0e92d852, -0x6fec2008, -0x544e6a2c, 0x1a9720d8, 0x2ea98463, 0x1bb9fe45 } + }, + { + { -0x33c98b84, -0x30a1936b, 0x6b0bc30d, 0x29420153, -0x11868510, 0x453ac67c, 0x2a8bb3c9, 0x5eae6ab3 }, + { -0x4c2ab062, -0x162e26b0, -0x1ff2cc3f, 0x2d5f9cbe, -0x5fb03954, 0x51c2c656, 0x3c1cbcc9, 0x65c091ee }, + { 0x14f118ea, 0x70836611, -0x6bcb6353, 0x2b37b87b, -0x4b1660c0, 0x7273f51c, 0x23d75698, 0x78a2a958 } + }, + { + { 0x5ef83207, -0x4b0dc3be, -0x3656cb4b, -0x54076b2d, 0x39fd87f7, -0x2f8f73ed, 0x17166130, 0x18767891 }, + { 0x5c8c2ace, -0x5d4f8d17, 0x651e9c4b, 0x69cffc96, 0x42e7b42b, 0x44328ef8, 0x22aadeb3, 0x5dd996c1 }, + { 0x670c507c, -0x6da4a110, -0x46c3cc41, -0x7e6437be, 0x70dd003f, 0x10792e9a, 0x6e28dc74, 0x59ad4b7a } + }, +}, +{ + { + { -0x5352715e, 0x583b04bf, 0x148be884, 0x29b743e8, 0x0810c5db, 0x2b1e583b, -0x714c4456, 0x2b5449e5 }, + { -0x14c241b9, 0x5f3a7562, -0x71425f48, -0x0815c7ac, 0x45747299, 0x00c3e531, 0x1627d551, 0x1304e9e7 }, + { 0x6adc9cfe, 0x789814d2, -0x74b722f5, 0x3c1bab3f, -0x068639f6, -0x25f01e01, 0x7c2dd693, 0x4468de2d } + }, + { + { -0x079cf832, 0x4b9ad8c6, 0x435d0c28, 0x21113531, 0x657a772c, -0x2b57993b, 0x63247352, 0x5da6427e }, + { -0x6be6b962, 0x51bb355e, 0x23ddc754, 0x33e6dc4c, 0x447f9962, -0x6c5a492a, -0x04bb429d, 0x6cce7c6f }, + { -0x2153dd36, 0x1a94c688, -0x4451e008, -0x46f99109, -0x72a6a7f1, -0x775273c8, -0x1860d358, 0x58f29abf } + }, + { + { 0x710ecdf6, 0x4b5a64bf, 0x462c293c, -0x4eb31ac8, -0x2af4c547, 0x3643d056, 0x185b4870, 0x6af93724 }, + { -0x7218c198, -0x16f13055, 0x377e76a5, 0x54036f9f, -0x41fea67e, -0x0fb6a4f5, -0x580be1ca, 0x577629c4 }, + { 0x09c6a888, 0x32200245, 0x4b558973, -0x2d1fc9ed, 0x3c33289f, -0x7c1dc9dd, 0x0caec18f, 0x701f25bb } + }, + { + { 0x7cbec113, -0x62e70927, 0x74bfdbe4, -0x7bb5f91a, -0x53b19f2a, 0x20f5b522, 0x50955e51, 0x720a5bc0 }, + { -0x1b9e9313, -0x3c574f08, -0x61da5783, -0x08ff99f2, -0x0b435a64, 0x61e3061f, -0x423bf417, 0x2e0c92bf }, + { -0x647fa5cb, 0x0c3f0943, 0x6242abfc, -0x17b174c9, 0x5c229346, 0x691417f3, 0x144ef0ec, 0x0e9b9cbb } + }, + { + { 0x5db1beee, -0x7211642b, 0x0a723fb9, -0x363c54c9, 0x1c68d791, 0x44a8f1bf, 0x1cfd3cde, 0x366d4419 }, + { -0x04a8df53, -0x04452b71, -0x2406f2f2, -0x117e6e95, 0x635543bf, -0x2b7eceae, 0x3f337bd8, 0x221104eb }, + { -0x0d4373ec, -0x61c3e8bd, -0x4a7a93c5, 0x2eda26fc, 0x68a7fb97, -0x3347d0f2, -0x43a6cdbc, 0x4167a4e6 } + }, + { + { -0x07317012, -0x3d41d99b, -0x177f29d4, -0x169800ec, 0x2f364eee, -0x0ed19182, -0x34812d0a, 0x34b33370 }, + { 0x76f62700, 0x643b9d28, 0x0e7668eb, 0x5d1d9d40, 0x21fc0684, 0x1b4b4303, 0x2255246a, 0x7938bb7e }, + { -0x797e2934, -0x323a6e12, -0x127a58ad, -0x31fdef64, 0x58808883, -0x128b7a3f, 0x2dfe65e4, 0x1176fc6e } + }, + { + { 0x49770eb8, -0x246f1d77, -0x530bbf5d, -0x670433d6, -0x21287865, 0x21354ffe, -0x0d96f94a, 0x1f6a3e54 }, + { 0x5b9c619b, -0x4b509330, -0x4d5a7b80, 0x2ddfc9f4, -0x1416b23c, 0x3d4fa502, 0x677d5f34, 0x08fc3a4c }, + { -0x2cf8cb16, 0x60a4c199, 0x31165cd6, 0x40c085b6, -0x08a67d6b, -0x1dccc1dd, 0x16b900d1, 0x4f2fad01 } + }, + { + { -0x48c449c8, -0x69d326e3, -0x03ed63f8, -0x19fa8856, -0x0c49e977, 0x6f619b39, 0x2944ee81, 0x3451995f }, + { -0x6b51b1ac, 0x44beb241, 0x1857ef6c, 0x5f541c51, 0x368d0498, -0x59e194d3, -0x68d10855, 0x445484a4 }, + { -0x60158284, -0x6ead0330, -0x4f6ca30a, 0x4a816c94, 0x47285c40, 0x258e9aaa, 0x042893b7, 0x10b89ca6 } + }, +}, +{ + { + { 0x79d34aa0, -0x2983212a, -0x33b24c61, -0x33f46140, -0x1ca2e6f1, -0x5aca5baa, -0x09e09011, 0x2e05d9ea }, + { 0x3b646025, -0x64d5bd92, 0x385ce4cf, 0x32127190, -0x229215bb, -0x5da3003e, -0x4157218b, 0x06409010 }, + { -0x29e414a7, -0x3bb86fe6, -0x1a2377f6, 0x661f19bc, -0x483597d9, 0x24685482, -0x101f80da, 0x293c778c } + }, + { + { -0x5ee00e00, 0x16c795d6, -0x4ea7ea37, -0x348f2f1e, -0x64ac6a4b, -0x760d6ce0, 0x31e47b4f, 0x50b8c2d0 }, + { 0x07069096, -0x797f6190, -0x1b1afe77, -0x5528a4eb, -0x5de5feb9, 0x07f35715, 0x12815d5e, 0x0487f3f1 }, + { 0x068a4962, 0x48350c08, 0x51092c9a, 0x6ffdd053, -0x50903723, 0x17af4f4a, 0x3cdba58b, 0x4b0553b5 } + }, + { + { 0x27c152d4, -0x40fadee5, -0x42e509c7, 0x5ec26849, -0x71905468, 0x5e0b2caa, 0x50bd0840, 0x054c8bdd }, + { 0x1b32ff79, -0x639a0342, 0x03b50f9b, -0x148a1561, 0x6c07e606, -0x0312d594, 0x51717908, 0x35106cd5 }, + { 0x1dcf073d, 0x38a0b12f, -0x48095d8a, 0x4b60a8a3, -0x2cbfb066, -0x012a53db, 0x5505c229, 0x72e82d5e } + }, + { + { 0x69771d02, 0x00d9cdfd, 0x6cfbf17e, 0x410276cd, 0x1cb12ec7, 0x4c45306c, 0x27500861, 0x2857bf16 }, + { -0x0f27bb38, 0x6b0b697f, -0x268634b7, -0x44ed07a4, -0x3e25f0e1, -0x2d5abe3a, 0x58ce7211, 0x7b7c2429 }, + { 0x0101689e, -0x60de6fc1, -0x4079effb, -0x2886202d, 0x3deb0f1b, -0x5edd11a1, 0x485a00d4, 0x510df84b } + }, + { + { -0x38f53ea2, 0x24b3c887, -0x047e48ce, -0x4f0c5aa9, -0x1a8733e5, -0x64d321d1, 0x03b54f8e, 0x4cf7ed07 }, + { -0x6d885e06, -0x5abecc45, 0x63991237, 0x74ec3b62, 0x35d2f15a, 0x1a3c54dc, -0x1b7d45c6, 0x2d347144 }, + { -0x670411f1, 0x6bd47c65, -0x54aa41d3, -0x61b8cc1e, 0x127610c5, 0x1093f624, -0x2f5e155c, 0x4e05e26a } + }, + { + { -0x1e701940, 0x1833c773, -0x2c378d9b, -0x1c3b8ee6, 0x0116b283, 0x3bfd3c4f, -0x4b32b248, 0x1955875e }, + { 0x4b531f20, -0x2564949e, 0x77509abb, 0x429a760e, -0x17dc3480, -0x24160ade, -0x77f3707e, 0x618f1856 }, + { 0x0e399799, 0x6da6de8f, 0x40fda178, 0x7ad61aa4, 0x5e3563dd, -0x4cd327f0, 0x2ae340ae, 0x15f6beae } + }, + { + { -0x6dba1deb, -0x4565f085, -0x2673f245, -0x0c979ed3, -0x0ddf4fe0, 0x2e84e4cb, 0x62d90eda, 0x6ba92fe9 }, + { 0x31ec3a62, -0x79d434f4, 0x1138f3c2, -0x7ef1d4bb, 0x39dac2a4, 0x788ec4b8, -0x51d56d7f, 0x28f76867 }, + { 0x5884e2aa, 0x3e4df965, -0x242b9a5b, -0x429d0425, 0x0de9e524, -0x28a69356, -0x4d4e4c29, 0x6e8042cc } + }, + { + { 0x16521f7e, 0x15306536, -0x69dfc246, 0x660d06b8, 0x545f0879, 0x2d3989bc, 0x78ebd7b0, 0x4b5303af }, + { -0x31d73592, -0x0ef2c3d7, -0x0349f6c3, -0x452cbac0, -0x5d15d2c1, -0x18bd9129, 0x4ff298b9, 0x08af9d4e }, + { -0x41434218, 0x72f8a6c3, -0x23c57177, 0x4f0fca4a, -0x38402086, 0x6fa9d4e8, -0x649db149, 0x0dcf2d67 } + }, +}, +{ + { + { 0x5a45f06e, 0x753941be, 0x6d9c5f65, -0x2f835113, 0x72ff51b6, 0x11776b9c, -0x10f2b257, 0x17d2d1d9 }, + { -0x68e7d764, 0x3d594749, 0x24533f26, 0x12ebf8c5, 0x14c3ef15, 0x0262bfcb, 0x77b7518e, 0x20b878d5 }, + { 0x073f3e6a, 0x27f2af18, -0x28adef97, -0x02c01ae7, 0x3ca60022, 0x22e3b72c, -0x339a3959, 0x72214f63 } + }, + { + { -0x0bc4d637, 0x1d9db7b9, 0x4f518f75, -0x29fa7db6, 0x312f9dc4, -0x0d3f8d43, 0x5a1545b0, 0x1f24ac85 }, + { 0x5307a693, -0x4b1c80c0, 0x2f336795, -0x5458eb29, 0x73761099, -0x29042f59, -0x7e8e3437, 0x5fdf48c5 }, + { -0x716afa56, 0x24d60832, 0x0c1420ee, 0x4748c1d1, 0x06fb25a2, -0x38001ba4, 0x2ae395e6, 0x00ba739e } + }, + { + { -0x157744da, -0x51bbd90b, -0x7b68c405, 0x360679d9, 0x26694e50, 0x5c9f030c, -0x2ae72dda, 0x72297de7 }, + { 0x5c8790d6, 0x592e98de, 0x45c2a2df, -0x1a40482d, -0x064b66de, 0x115a3b60, 0x67ad78f3, 0x03283a3e }, + { -0x41f346c7, 0x48241dc7, -0x749ccf80, 0x32f19b4d, 0x02289308, -0x2c2036f3, 0x46271945, 0x05e12968 } + }, + { + { 0x242c4550, -0x52404438, -0x2fcf7e27, -0x4337f314, -0x0a37206e, -0x7bca995a, -0x7da731b4, 0x78cf25d3 }, + { 0x2d9c495a, -0x457d114d, -0x0ed44684, -0x31103704, -0x6c4a2e20, -0x4fd25452, 0x13698d9b, 0x39c00c9c }, + { 0x31489d68, 0x15ae6b8e, -0x63d40f79, -0x557ae355, -0x0fb105fb, -0x3658a569, 0x6b3ff832, 0x006b5207 } + }, + { + { -0x4631f7d3, -0x0a3481ea, 0x417abc29, 0x3407f14c, 0x2bf4a7ab, -0x2b4c9432, 0x1a9f75ce, 0x7de2e956 }, + { -0x626a87e4, 0x29e0cfe1, -0x699cef1e, -0x497e20e8, 0x70516b39, 0x57df39d3, 0x3bc76122, 0x4d57e344 }, + { -0x495aa135, -0x218f2b0c, 0x5d85db99, 0x4801527f, -0x2c11657f, -0x24363bc0, 0x1a6029ed, 0x6b2a90af } + }, + { + { 0x5bb2d80a, 0x77ebf324, 0x2fb9079b, -0x27cfe4b9, 0x4cee7333, -0x39b8190e, 0x276c2109, 0x465812c8 }, + { -0x6519e169, 0x6923f4fc, -0x1fc0a02f, 0x5735281d, -0x19122ed3, -0x589b51bd, -0x2ed2c1b6, 0x5fd8f4e9 }, + { 0x2a1062d9, 0x4d43beb2, 0x3831dc16, 0x7065fb75, -0x21d69729, 0x180d4a7b, 0x1cb16790, 0x05b32c2b } + }, + { + { 0x7ad58195, -0x08035bd4, 0x4333f3cc, 0x3214286e, 0x340b979d, -0x493d62f3, 0x567307e1, 0x31771a48 }, + { -0x2db25703, -0x373fa134, 0x05dfef83, -0x5e30e554, 0x7df9cd61, -0x2441100e, 0x7b471e99, 0x3b5556a3 }, + { -0x1eb22b7e, 0x32b0c524, 0x1a2ba4b6, -0x124caeac, 0x282b5af3, -0x5c2e9fb8, 0x7a7336eb, 0x4fc079d2 } + }, + { + { 0x0c86c50d, -0x23cb74bc, -0x336b19af, 0x1337cbc9, 0x643e3cb9, 0x6422f74d, -0x451c32f8, 0x241170c2 }, + { -0x7640d081, 0x51c938b0, 0x02dfe9a7, 0x2497bd65, 0x7880e453, -0x00003f64, -0x3506716e, 0x124567ce }, + { 0x0ac473b4, 0x3ff9ab86, 0x0113e435, -0x0f6ee212, -0x14393b51, 0x4ae75060, 0x6c87000d, 0x3f861296 } + }, +}, +{ + { + { 0x638c7bf3, 0x529fdffe, 0x388b4995, -0x20d461a0, 0x1bad0249, -0x1fd84cb1, -0x46058b13, 0x7bc92fc9 }, + { -0x086a841c, 0x0c9c5303, -0x1f7a3ebb, -0x5c3ce5e0, -0x2f7affb0, -0x4f8de28f, -0x54f40d26, 0x0aba390e }, + { -0x7fe52607, -0x606810d2, 0x79afda3a, -0x7c9682ac, -0x42a694b0, -0x16f94c01, -0x22c04720, 0x02672b37 } + }, + { + { 0x398ca7f5, -0x116458d7, 0x7a4849db, -0x146359db, 0x7ec544e1, 0x29eb29ce, -0x08c91d38, 0x232ca21e }, + { 0x260885e4, 0x48b2ca8b, -0x7d4cb3e4, -0x5bd79414, 0x17f58f74, -0x6c81e5da, -0x54d35d5b, 0x741d1fcb }, + { 0x253fcb17, -0x409ebdc3, -0x05c614ec, 0x08803cea, -0x67ae3851, -0x0e79fd21, 0x49e3414b, 0x0400f3a0 } + }, + { + { -0x5f9184fa, 0x2efba412, 0x2c8d2560, 0x14678545, -0x29856e39, -0x2068ec15, 0x157eadf3, 0x32830ac7 }, + { -0x459e3aa5, -0x5431fb8a, -0x3b2c68ea, 0x36a3d6d7, -0x1727d2f7, 0x6eb259d5, -0x7b28a905, 0x0c9176e9 }, + { -0x48c89618, 0x0e782a7a, 0x75b18e2c, 0x04a05d78, -0x1433151f, 0x29525226, -0x7c1457e0, 0x0d794f83 } + }, + { + { -0x585d1e54, 0x7be44ce7, -0x052e4749, 0x411fd93e, 0x0d5f7c9b, 0x1734a1d7, 0x3127db16, 0x0d659223 }, + { -0x61eae90c, -0x00ca0a35, 0x648aae45, -0x117fa431, -0x46c5610d, -0x0f28c3d5, 0x2092a6c2, 0x097b0bf2 }, + { 0x21a9d733, -0x3b7454eb, -0x29e544db, -0x593d1516, -0x3934bcfb, 0x625c6c1c, -0x6c14c599, 0x7fc90fea } + }, + { + { -0x63834dc3, -0x3ad8214b, 0x5328404e, -0x6aac6e97, 0x7ccf2c7a, -0x29bc6d7f, -0x082705ef, 0x6ce97dab }, + { 0x1f5c5926, 0x0408f1fe, 0x3b258bf4, 0x1a8f2f5e, -0x0238e997, 0x40a951a2, -0x3674a882, 0x6598ee93 }, + { 0x0ef7c48f, 0x25b5a8e5, 0x6f2ce532, -0x149fcbef, -0x1ac21ac9, -0x3a18ae8d, -0x73ed44fd, 0x73119fa0 } + }, + { + { 0x21f4774d, 0x7845b94d, 0x7897b727, -0x409d0e94, 0x3c56522b, 0x671857c0, -0x6a9dedee, 0x3cd6a852 }, + { 0x53f1a4cb, -0x12cfed6c, -0x370ac879, -0x4319de37, 0x38bee7b9, -0x0534d4ed, -0x6157bd74, 0x3025798a }, + { 0x3aeca999, 0x3fecde92, 0x62e8c12f, -0x4255a500, -0x69677522, 0x67b99dfc, 0x52661036, 0x3f52c028 } + }, + { + { -0x113be93a, -0x6da74067, -0x562d098f, -0x5375afe9, 0x16dea4ab, 0x629549ab, -0x66f6ea97, 0x05d0e85c }, + { 0x2a1351c6, -0x00155b72, -0x0580ac29, 0x28624754, 0x7582ddf1, 0x0b5ba9e5, -0x596953a7, 0x60c0104b }, + { -0x21634169, 0x051de020, -0x4af4308c, -0x05f803aa, 0x0f11df65, 0x378cec9f, -0x546921b3, 0x36853c69 } + }, + { + { -0x053a1842, 0x4433c0b0, 0x4c08dcbe, 0x724bae85, 0x46978f9b, -0x0e0db33c, 0x62825fc8, 0x4a0aff6d }, + { 0x78f39b2d, 0x36d9b8de, -0x57b84614, 0x7f42ed71, 0x79bd3fde, 0x241cd1d6, -0x6d043195, 0x6a704fec }, + { 0x61095301, -0x16e80462, 0x02a092f8, -0x3efd206c, -0x0599e6f5, -0x40f61d0b, -0x1f2301c9, 0x681109be } + }, +}, +{ + { + { 0x36048d13, -0x63e70306, 0x73899ddd, 0x29159db3, -0x606d2f56, -0x2360caf5, -0x7875e62c, 0x26f57eee }, + { 0x782a0dde, 0x559a0cc9, -0x158e7c7b, 0x551dcdb2, 0x31ef238c, 0x7f62865b, 0x7973613d, 0x504aa776 }, + { 0x5687efb1, 0x0cab2cd5, 0x247af17b, 0x5180d162, 0x4f5a2467, -0x7a3ea5cc, -0x6245cf97, 0x4041943d } + }, + { + { -0x5d935523, 0x4b217743, 0x648ab7ce, 0x47a6b424, 0x03fbc9e3, -0x34e2b086, -0x67ff2fe7, 0x12d93142 }, + { 0x43ebcc96, -0x3c3f1146, 0x26ea9caf, -0x728b6364, 0x1c77ccc6, -0x26056a12, 0x7684340f, 0x1420a1d9 }, + { -0x2cc8a6b1, 0x00c67799, -0x4dc55b85, 0x5e3c5140, -0x1ca00c6b, 0x44182854, 0x4359a012, 0x1b4f9231 } + }, + { + { -0x5b67994f, 0x33cf3030, 0x215f4859, 0x251f73d2, 0x51def4f6, -0x547d55c0, 0x6f9a23f6, 0x5ff191d5 }, + { -0x76eaf6af, 0x3e5c109d, 0x2de9696a, 0x39cefa91, -0x68a0cfe0, 0x20eae43f, 0x7f132dae, 0x239b572a }, + { -0x53d26f98, -0x7e612bcd, 0x5fc98523, 0x2883ab79, 0x5593eb3d, -0x10ba8d80, 0x758f36cb, 0x020c526a } + }, + { + { -0x0fbd3377, -0x16ce10a7, -0x71edb44a, 0x2c589c9d, -0x5138a669, -0x52371e76, 0x5602c50c, 0x452cfe0a }, + { -0x61272444, 0x779834f8, -0x23835b94, -0x370d5507, -0x5c1e4f8c, -0x56adb324, 0x15313877, 0x02aacc46 }, + { 0x647877df, -0x795f0860, 0x0e607c9f, -0x443b9bd9, -0x0e04ee37, -0x54e815db, 0x304b877b, 0x4cfb7d7b } + }, + { + { -0x687610ee, -0x1d79663e, -0x20a8e6f3, 0x2b6ecd71, -0x13368f30, -0x3cbc37a9, 0x434d3ac5, 0x5b1d4cbc }, + { -0x47648a02, 0x72b43d6c, -0x63952380, 0x54c694d9, 0x3ee34c9f, -0x473c55c9, 0x39075364, 0x14b4622b }, + { -0x33f560da, -0x4904d9eb, -0x4772331b, 0x3a4f0e2b, 0x3369a705, 0x1301498b, 0x58592dd1, 0x2f98f712 } + }, + { + { 0x4f54a701, 0x2e12ae44, -0x56342822, -0x0301c110, 0x75835de0, -0x314076f3, -0x189ebaac, 0x1d8062e9 }, + { -0x4af061aa, 0x0c94a74c, -0x7171ece0, 0x5b1ff4a9, -0x7dcff099, -0x65d533df, -0x27f95507, 0x3a6ae249 }, + { -0x566f83a6, 0x657ada85, -0x6e46f09e, 0x1a0ea8b5, -0x20cb4b17, -0x72f1e205, -0x510da00d, 0x298b8ce8 } + }, + { + { 0x0a2165de, -0x7c858d16, 0x0bcf79f6, 0x3fab07b4, 0x7738ae70, 0x521636c7, 0x03a7d7dc, 0x6ba62718 }, + { -0x1008f34e, 0x2a927953, 0x79157076, 0x4b89c92a, 0x30a7cf6a, -0x6be7ba86, 0x4d5ce485, 0x34b8a840 }, + { -0x7c96cccb, -0x3d91134b, 0x63b5fefd, -0x2a57ec21, -0x5b4dda8d, -0x5d6c5566, 0x465e1c6a, 0x71d62bdd } + }, + { + { -0x4e08a10b, -0x32d24a26, 0x16b065f5, -0x28806a31, 0x3f49f085, 0x14571fea, 0x262b2b3d, 0x1c333621 }, + { -0x2c872080, 0x6533cc28, 0x0a0fa4b4, -0x0924bc87, -0x08fe25a6, -0x1c9ba007, -0x0ce8d45c, 0x74d5f317 }, + { 0x67d9ca81, -0x57901aac, 0x2b298c37, 0x398b7c75, -0x1c539dc5, -0x2592f76e, 0x47e9d98c, 0x4aebcc45 } + }, +}, +{ + { + { -0x5fa65bbb, 0x0de9b204, 0x4b17ad0f, -0x1ea34b56, 0x1f79c557, -0x1e4413ae, -0x2f8ef7e5, 0x2633f1b9 }, + { 0x05d21a77, 0x53175a72, -0x2c46cb2c, -0x4f3fbbde, -0x22a21524, -0x52260db5, -0x60ef0074, 0x074f46e6 }, + { 0x018b9910, -0x3e04be89, 0x6c0fe140, -0x5915df24, 0x4354c6ff, -0x299e0c19, -0x0e5cbf86, 0x5ecb72e6 } + }, + { + { -0x17179669, -0x01151efa, -0x672f6c7d, -0x679ccc81, -0x55f91411, -0x6b8fb7f2, -0x2b3a3d30, 0x038b6898 }, + { 0x2259fb4e, -0x5aea5ce5, 0x2bcac52f, 0x0960f397, -0x72cbab35, -0x124ad014, -0x3b893fe7, 0x382e2720 }, + { -0x7531af5a, -0x0c6e3ae3, -0x51d2d6b8, 0x3142d0b9, 0x7f24ca80, -0x24b2a5e6, 0x59250ea8, 0x21aeba8b } + }, + { + { -0x0ff780dd, 0x53853600, -0x2582a87c, 0x4c461879, -0x4be097a0, 0x6af303de, -0x3d83e713, 0x0a3c16c5 }, + { -0x30bfaad0, 0x24f13b34, 0x43088af7, 0x3c44ea4a, 0x0006a482, 0x5dd5c517, -0x76f4f793, 0x118eb8f8 }, + { -0x336b80c3, 0x17e49c17, -0x553e2d85, -0x3339125a, -0x4f0f71aa, -0x209f6d32, 0x2c67c36b, 0x4909b3e2 } + }, + { + { 0x706ff64e, 0x59a16676, 0x0d86a53d, 0x10b953dd, -0x31a3f46a, 0x5848e1e6, 0x12780c68, 0x2d8b78e7 }, + { 0x63fe2e89, -0x63637a16, 0x0e9412ec, -0x41e4506f, -0x79040185, -0x70845576, -0x10697494, 0x0fb17f9f }, + { -0x503c6fd5, 0x79d5c62e, -0x7617f8d8, 0x773a2152, -0x1efedf47, -0x3c7519c0, 0x7b2b1a6d, 0x09ae2371 } + }, + { + { -0x52cd4e30, 0x10ab8fa1, -0x1d8874dc, -0x165312e5, 0x373de90f, -0x577a9440, -0x225ac66a, 0x66f35ddd }, + { 0x4e4d083c, -0x4495e6d6, 0x0029e192, 0x34ace063, -0x55054515, -0x67dba5a7, -0x25680554, 0x6d9c8a9a }, + { 0x24997323, -0x2d826505, -0x090fe2d2, 0x1bb7e07e, -0x0ad13381, 0x2ba7472d, 0x646f9dc8, 0x03019b4f } + }, + { + { -0x194c2395, -0x50f64dec, -0x5282d09b, 0x3f7573b5, 0x100a23b0, -0x2fe62678, -0x74a3ca09, 0x392b63a5 }, + { 0x565345cd, 0x04a186b5, -0x433bee96, -0x111899f0, 0x78fb2a45, 0x689c73b4, 0x65697512, 0x387dcbff }, + { -0x63f83dfb, 0x4093addc, -0x0acd3c82, -0x3a9a41eb, 0x1583402a, 0x63dbecfd, -0x10d1fcd2, 0x61722b4a } + }, + { + { -0x7e34f1c4, -0x294f85ab, -0x26bbb697, 0x290ff006, 0x16dcda1f, 0x08680b6a, 0x5a06de59, 0x5568d2b7 }, + { -0x1342b851, 0x0012aafe, 0x1cd46309, 0x55a266fb, 0x0967c72c, -0x0dfc1498, -0x35c3ebd7, 0x39633944 }, + { 0x1b37cfe1, -0x72f34774, 0x053818f3, 0x05b6a5a3, -0x487826a7, -0x0d1643fc, -0x6522809c, 0x6beba124 } + }, + { + { 0x43f5a53b, 0x5c3cecb9, 0x06c08df2, -0x633659e3, -0x7a76abb9, -0x30459c66, 0x0df09fd5, 0x5a845ae8 }, + { -0x5a4e4ebd, 0x1d06005c, 0x7fd1cda2, 0x6d4c6bb8, 0x53fcffe7, 0x6ef59676, -0x3e31e15b, 0x097c29e8 }, + { 0x5deb94ca, 0x4ce97dbe, -0x738f63b8, 0x38d0a438, -0x5e962f69, -0x3bc1312c, -0x081a783d, 0x0a1249ff } + }, +}, +{ + { + { 0x7354b610, 0x0b408d9e, 0x5ba85b6e, -0x7f94cdad, 0x4a58a207, -0x2419c5fd, -0x365e20d4, 0x173bd9dd }, + { 0x276d01c9, 0x12f0071b, -0x793b7390, -0x1847453b, 0x71d6fba9, 0x5308129b, 0x5a3db792, 0x5d88fbf9 }, + { -0x01a78d21, 0x2b500f1e, -0x2bc6e73f, 0x58d6582e, -0x3698c520, -0x1912d872, -0x4e615ce7, 0x06e1cd13 } + }, + { + { -0x61a4fcad, 0x472baf62, 0x278d0447, 0x3baa0b90, -0x69bc40d9, 0x0c785f46, -0x727c84ed, 0x7f3a6a1a }, + { 0x6f166f23, 0x40d0ad51, 0x1fab6abe, 0x118e3293, -0x5fb2f772, 0x3fe35e14, 0x26e16266, 0x30806035 }, + { 0x5d3d800b, -0x0819bbc7, -0x36fe120a, -0x6a572aab, 0x592c6339, 0x68cd7830, 0x2e51307e, 0x30d0fded } + }, + { + { 0x68b84750, -0x634b68e2, 0x6664bbcf, -0x5f6a8dd7, 0x72fa412b, 0x5c8de726, 0x51c589d9, 0x46150843 }, + { -0x0dedcc4d, -0x1fa6b2e6, -0x0f33b264, 0x1bdbe78e, -0x70b66589, 0x6965187f, 0x2c099868, 0x0a921420 }, + { -0x51465fd2, -0x436fe640, 0x16034cae, 0x55c7110d, 0x659932ec, 0x0e6df501, -0x6a35a202, 0x3bca0d28 } + }, + { + { -0x6133fe41, -0x6397714a, -0x59bb7691, -0x0f437c53, 0x5f7a9fe2, -0x35d26aa1, -0x720d7dbf, 0x4ea8b403 }, + { 0x3c5d62a4, 0x40f031bc, -0x300f85a0, 0x19fc8b3e, 0x130fb545, -0x67e7c25e, -0x5170ec33, 0x5631dedd }, + { -0x0e352dfe, 0x2aed460a, -0x5b73117d, 0x46305305, 0x49f11a5f, -0x6ede88bb, 0x542ca463, 0x24ce0930 } + }, + { + { -0x020cf47b, 0x3fcfa155, 0x36372ea4, -0x2d08e972, 0x6492f844, -0x4d1f9b22, 0x324f4280, 0x549928a7 }, + { -0x02f93efa, 0x1fe890f5, 0x5d8810f2, -0x4a3b97cb, 0x6e8caf3e, -0x7d87f702, -0x75f928b5, 0x41d4e3c2 }, + { 0x63ee1a2e, -0x0d91cd59, -0x2da00216, -0x516e1b49, -0x2e80b297, -0x43c42cc5, -0x3f230096, 0x491b66de } + }, + { + { -0x2f259b5f, 0x75f04a8e, 0x67e2284b, -0x12ddd351, 0x1f7b7ba4, -0x7dcb5c87, -0x48fe7499, 0x4cf6b8b0 }, + { -0x3815cd59, -0x670a4ec3, 0x7e16db98, -0x1c2a0734, -0x340726b9, -0x53f540ae, -0x37a11b54, 0x08f338d0 }, + { -0x66e58c43, -0x3c7c57df, -0x20cdf386, -0x54d843ff, -0x7b888f9d, -0x3ec2cce5, -0x14f87567, 0x530d4a82 } + }, + { + { 0x6c9abf9e, 0x6d697345, 0x4900a880, 0x257fb2fc, -0x373047b0, 0x2bacf412, 0x0cbfbd5b, 0x0db3e7e0 }, + { -0x1e06b7db, 0x004c3630, -0x7354aca6, 0x7e2d7826, -0x337b0075, -0x38b7dcdd, 0x101770b9, 0x65ea753f }, + { -0x1df69c9d, 0x3d66fc3e, 0x61b5cb6b, -0x7e29d381, 0x13443b1a, 0x0fbe0442, 0x21e1a1db, 0x02a4ec19 } + }, + { + { -0x0e3086a1, -0x0a379e9e, 0x26ee57f2, 0x118c8619, 0x1c063578, 0x17212485, -0x13f98031, 0x36d12b5d }, + { 0x3b24b8a2, 0x5ce6259a, 0x45afa0b8, -0x47a88534, -0x745f8fc9, -0x33341918, 0x127809bf, 0x3d143c51 }, + { 0x79154557, 0x126d2791, -0x0387c5f6, -0x2a1b70a4, -0x20e86454, 0x36bdb6e8, 0x5ba82859, 0x2ef51788 } + }, +}, +{ + { + { 0x7c6da1e9, 0x1ea43683, 0x1fb9bdbe, -0x063e7651, -0x31a22eab, 0x303001fc, -0x43a841ae, 0x28a7c99e }, + { -0x2ee1f2b6, -0x7742bc74, 0x43ccf308, 0x30cb610d, -0x6e6c8434, -0x1f65f1c9, 0x25b1720c, 0x4559135b }, + { -0x172e6163, -0x47026c67, -0x69dbdc01, -0x6f7e6e35, 0x47c742a3, -0x4d46b729, -0x2804bb3c, 0x37f33226 } + }, + { + { -0x37de4ee3, 0x33912553, 0x41e301df, 0x66ed42c2, 0x104222fd, 0x066fcc11, -0x3e6de971, 0x307a3b41 }, + { -0x4aa091f8, 0x0dae8767, 0x5b203a02, 0x4a43b3b3, -0x7f507387, -0x1c8da592, 0x705fa7a3, 0x0f7a7fd1 }, + { 0x6eb55ce0, -0x7114a2f9, -0x55f26da6, 0x2fc536bf, -0x23493918, -0x417e7cf1, -0x7d8450ae, 0x556c7045 } + }, + { + { 0x2bf44406, -0x46b46ffe, -0x006f4acc, -0x542bdc82, -0x050792c6, 0x7600a960, -0x3dcdd11d, 0x2f45abda }, + { 0x02e9d8b7, -0x71d4ae8d, 0x248714e8, -0x1c1add97, 0x4ca960b5, -0x42b04289, -0x3a135257, 0x6f4b4199 }, + { -0x37107596, 0x61af4912, 0x43fb6e5e, -0x1a705b02, 0x6fd427cf, -0x4a5033a3, 0x1e1e11eb, 0x6a539328 } + }, + { + { 0x149443cf, 0x0fff04fe, -0x79a32229, 0x53cac6d9, 0x531ed1b7, 0x31385b03, -0x532efc63, 0x5846a27c }, + { -0x5a2e1177, -0x0c25aec7, -0x006c9678, -0x7ebaba84, 0x00e188c4, 0x3f622fed, -0x2474a5c3, 0x0f513815 }, + { 0x1eb08717, 0x4ff5cdac, -0x6f0d1644, 0x67e8b295, 0x237afa99, 0x44093b5e, -0x78f7474e, 0x0d414bed } + }, + { + { 0x294ac9e8, -0x7e77956e, -0x2aaab842, 0x23162b45, 0x03715983, -0x6b3043bc, 0x134bc401, 0x50eb8fdb }, + { -0x02f18a0a, -0x30497d9b, -0x446f18f9, -0x1ba4c1d8, -0x6006d386, 0x7242a8de, -0x6ccdfd23, 0x685b3201 }, + { -0x294ccf33, -0x3f48c13a, 0x132faff1, -0x7b1bb7f9, -0x3b5a211f, 0x732b7352, -0x55832d2e, 0x5d7c7cf1 } + }, + { + { -0x648c5a9e, 0x33d1013e, 0x48ec26e1, -0x6da310a9, -0x22b97fa8, -0x580319ec, 0x1e9aa438, 0x78b0fad4 }, + { 0x7a4aafa2, -0x50c4b941, 0x4d40d411, -0x4878fa14, -0x3583ea1d, 0x114f0c6a, -0x56b762b3, 0x3f364faa }, + { -0x12fa4b78, -0x40a95bcf, -0x63b6a382, -0x5acc1994, -0x780c9ae6, -0x179ad451, 0x59d66c33, 0x02418000 } + }, + { + { -0x30c715ff, 0x28350c7d, -0x4d6e854a, 0x7c6cdbc0, -0x7a8f7d09, -0x53183042, -0x5d265e20, 0x4d2845ab }, + { -0x5c85a41c, -0x314f8802, -0x1a5a1149, -0x249bd0fe, 0x471270b8, -0x3d192f3b, 0x38e4529c, 0x4771b655 }, + { 0x447070de, -0x44ac8020, 0x6dd557df, -0x3458bbbd, 0x3600dbcb, -0x2c4a5cb9, -0x06002808, 0x4aeabbe6 } + }, + { + { -0x3b56370e, 0x6a2134bc, -0x7531d1c9, -0x040702e4, -0x66ee5f46, 0x000ae304, 0x6bc89b9e, 0x046e3a61 }, + { 0x40d8f78c, 0x4630119e, 0x3c710e11, -0x5fe5643b, -0x76ef2287, 0x486d2b25, -0x24fcdb1b, 0x1e6c47b3 }, + { -0x0fc6f942, 0x14e65442, -0x1c9d41d6, 0x4a019d54, -0x723dcf39, 0x68ccdfec, -0x509479e4, 0x7cfb7e3f } + }, +}, +{ + { + { 0x305b2f51, -0x69114005, -0x776a6948, -0x2c06c753, 0x46d5dd25, -0x0f0ad239, -0x44c5ff6b, 0x57968290 }, + { -0x73a75124, 0x4637974e, -0x540fbe5c, -0x4610dd05, -0x167f8e76, -0x1e7a26aa, -0x4ebc575a, 0x2f1b78fa }, + { 0x0a20e101, -0x08e547bd, 0x24f0ec47, -0x0c6c9a73, 0x6ee2eed1, -0x308af658, -0x23d55c1f, 0x7dc43e35 } + }, + { + { 0x273e9718, 0x5a782a5c, 0x5e4efd94, 0x3576c699, 0x1f237d3e, 0x0f2ed805, -0x7d2af567, 0x044fb81d }, + { -0x7782263d, -0x7a69999b, 0x4bb05355, -0x36f064cf, -0x10df864f, -0x391f7208, 0x758cc12f, 0x7ef72016 }, + { -0x56f81c27, -0x3e20e73b, -0x31b39ca7, 0x57b3371d, -0x4dfe44b7, -0x358fbacc, -0x63cf22d2, 0x7f79823f } + }, + { + { 0x68f587ba, 0x6a9c1ff0, 0x0050c8de, 0x0827894e, 0x7ded5be7, 0x3cbf9955, 0x1c06d6f0, 0x64a9b043 }, + { -0x5c4aec18, -0x7ccb2dc7, -0x46e05728, -0x3ec98f2c, -0x0a6f42cd, 0x12b54136, -0x287b264c, 0x0a4e0373 }, + { 0x5b7d2919, 0x2eb3d6a1, -0x2ac57dcb, -0x4f4b0960, -0x765ba2b9, 0x7156ce43, -0x31e7cb94, 0x071a7d0a } + }, + { + { 0x20e14431, -0x33f3caae, 0x09b15141, 0x0d659507, 0x209d5f36, -0x650a9de5, 0x617755d3, 0x7c69bcf7 }, + { -0x377845f5, -0x2cf8d256, -0x405a9d12, 0x01262905, -0x3f108975, -0x30abcffe, 0x46ea7e9c, 0x2c3bcc71 }, + { 0x04e8295f, 0x07f0d7eb, 0x2f50f37d, 0x10db1825, 0x171798d7, -0x16ae565d, 0x22aca51d, 0x6f5a9a73 } + }, + { + { -0x5c26bb42, -0x18d62b15, -0x7f875062, -0x7261f6c0, 0x47869c03, 0x4525567a, -0x1172c4dc, 0x02ab9680 }, + { 0x2f41c6c5, -0x745efff4, 0x0cfefb9b, -0x3b60863f, 0x3cc51c9f, 0x4efa4770, -0x1eb85036, 0x494e21a2 }, + { -0x221af266, -0x105b757b, 0x0fb9a249, 0x219a224e, -0x26e10927, -0x05f6e0e3, -0x15b944cc, 0x6b5d76cb } + }, + { + { 0x1e782522, -0x1f06bee9, 0x036936d3, -0x0e19518c, -0x2f0338ba, 0x408b3ea2, 0x03dd313e, 0x16fb869c }, + { -0x13f3266c, -0x77a8aa94, 0x5cd01dba, 0x6472dc6f, -0x70bd4b89, -0x50fe96ec, -0x7ad88cac, 0x0ae333f6 }, + { 0x33b60962, 0x288e1997, -0x27541ecd, 0x24fc72b4, 0x0991d03e, 0x4811f7ed, -0x708f2f8b, 0x3f81e38b } + }, + { + { 0x5f17c824, 0x0adb7f35, -0x28bd665c, 0x74b923c3, -0x34071509, -0x2a83c175, 0x4cdedc3d, 0x0ad3e2d3 }, + { 0x7ed9affe, 0x7f910fcc, 0x2465874b, 0x545cb8a1, 0x4b0c4704, -0x57c6812e, 0x04f50993, 0x50510fc1 }, + { 0x336e249d, 0x6f0c0fc5, -0x3cce3027, 0x745ede19, 0x09eefe1c, -0x0d290300, -0x0f05e142, 0x127c158b } + }, + { + { -0x51ae468c, -0x215d703c, 0x744dfe96, 0x1d9973d3, -0x78c7b758, 0x6240680b, -0x2e98206b, 0x4ed82479 }, + { 0x2e9879a2, -0x09e683be, 0x52ca3647, -0x5bb5222c, 0x4b4eaccb, -0x64bec03f, 0x07ef4f68, 0x354ef87d }, + { 0x60c5d975, -0x011c4ade, -0x14be4f48, 0x50352efc, -0x56099ac4, -0x77f753d0, 0x0539236d, 0x302d92d2 } + }, +}, +{ + { + { 0x0df53c30, -0x6a847475, -0x719f0f68, 0x2a1c770a, 0x345796de, -0x44385990, -0x6f366437, 0x22a48f9a }, + { -0x34c10484, 0x4c59023f, -0x39c3d56c, 0x6c2fcb99, -0x3c381f7c, -0x45be6f1e, -0x5ae78b27, 0x0e545dae }, + { -0x72c053a8, 0x6b7dc0dc, -0x191bd403, 0x5497cd6c, -0x0bff2cfb, 0x542f7d1b, 0x048d9136, 0x4159f47f } + }, + { + { -0x442db7c7, 0x748515a8, -0x504fd4ab, 0x77128347, 0x49a2a17f, 0x50ba2ac6, 0x3ad730f1, 0x06052551 }, + { 0x39e31e32, 0x20ad6608, -0x7bfa41b0, -0x07e1e42b, -0x0b254397, -0x07f9bfaa, -0x318e468b, 0x14d23dd4 }, + { -0x755d807e, -0x0dc671f7, -0x765e4fdc, 0x6d7982bb, 0x214dd24c, -0x0596bf7c, -0x5cdcfe3d, 0x71ab966f } + }, + { + { 0x02809955, -0x4ef775f9, 0x0b43c391, 0x43b273ea, -0x01f97913, -0x35649852, -0x7cca0b13, 0x605eecbf }, + { 0x4ded02fc, 0x2dcbd8e3, 0x596f22aa, 0x1151f3ec, 0x4e0328da, -0x435daabd, -0x6dbee4de, 0x35768fbe }, + { 0x6c340431, -0x7cdff59b, -0x711a63d1, -0x60328e99, 0x71300f8a, 0x75d4613f, 0x60f542f9, 0x7a912faf } + }, + { + { -0x05d2aa69, 0x253f4f8d, 0x5477130c, 0x25e49c40, -0x6694eefe, 0x00c052e5, 0x33bb6c4a, 0x33cb966e }, + { 0x5edc1a43, -0x4dfba7a2, 0x5897c73c, -0x60f1e912, 0x4e70483c, 0x5b82c0ae, 0x2bddf9be, 0x624a170e }, + { 0x7f116909, 0x59702804, 0x1e564467, -0x7d753be4, -0x19de8c79, 0x70417dbd, -0x0453bc7c, 0x721627ae } + }, + { + { 0x410b2f22, -0x02cf6844, -0x4a3057bc, -0x0e5fa259, -0x10a8358c, 0x61289a1d, -0x447de6fe, 0x245ea199 }, + { -0x78c9522b, -0x682fc43d, -0x3acd4ed0, 0x2f1422af, 0x7101bbc4, 0x3aa68a05, -0x18b06059, 0x4c946cf7 }, + { 0x78d477f8, -0x51235997, 0x29117fe1, 0x1898ba3c, 0x720cbd58, -0x308c067d, -0x474a9caf, 0x67da12e6 } + }, + { + { -0x7137cf74, 0x2b7ef3d3, 0x71eb94ab, -0x7d702814, -0x3af9d543, -0x7f83c4ca, 0x31a94141, 0x0cb64cb8 }, + { -0x4b4291f9, 0x7067e187, -0x382e018c, 0x6e8f0203, 0x38c85a30, -0x6c3955d1, 0x3d75a78a, 0x76297d1f }, + { 0x534c6378, 0x3030fc33, -0x1abe179f, -0x469ca3a4, -0x264d38d8, 0x15d9a9be, -0x0c88a235, 0x49233ea3 } + }, + { + { 0x1c9f249b, 0x7b3985fe, -0x5edccd6d, 0x4fd6b2d5, 0x1adf4d62, -0x314cba6c, 0x542de50c, 0x6987ff6f }, + { -0x724003c6, 0x629398fa, -0x2ab24bab, -0x1ed01ad3, -0x250dad6b, -0x0c41ee21, -0x31a184af, 0x628b140d }, + { -0x707c8ac4, 0x47e24142, -0x79950669, 0x6317bebc, 0x3d1a9829, -0x2544a4bd, 0x5287fb2d, 0x074d8d24 } + }, + { + { -0x3f1ceb78, 0x481875c6, -0x1ddfcb4c, 0x219429b2, 0x31283b65, 0x7223c98a, 0x342277f9, 0x3420d60b }, + { 0x440bfc31, -0x7cc82633, -0x50ce7029, 0x729d2ca1, 0x772c2070, -0x5fbf5b5c, 0x3a7349be, 0x46002ef0 }, + { -0x50019a09, -0x055dc522, 0x5be0764c, 0x78261ed4, 0x2f164403, 0x441c0a1e, 0x7a87d395, 0x5aea8e56 } + }, +}, +{ + { + { -0x1b1f0e89, 0x2dbc6fb6, -0x5b42956d, 0x04e1bf29, 0x787af6e8, 0x5e1966d4, -0x4bd92fa0, 0x0edc5f5e }, + { -0x435bd7c3, 0x7813c1a2, -0x5e79c227, -0x129d0f6f, -0x3d97057a, -0x51384348, 0x6f1cae4c, 0x10e5d3b7 }, + { 0x53da8e67, 0x5453bfd6, 0x24a9f641, -0x1623e114, 0x03578a23, -0x4078d9c5, 0x361cba72, 0x45b46c51 } + }, + { + { -0x75801c1c, -0x3162b223, 0x76620e30, -0x54ec9baa, -0x4cf166a8, 0x4b594f7b, 0x321229df, 0x5c1c0aef }, + { 0x314f7fa1, -0x56bfd541, -0x71730bb0, -0x1da80e24, 0x23a8be84, 0x1dbbd54b, 0x6dcb713b, 0x2177bfa3 }, + { -0x05862471, 0x37081bbc, -0x3da0a64d, 0x6048811e, -0x637cdb79, 0x087a7665, 0x7d8ab5bb, 0x4ae61938 } + }, + { + { -0x67a4047d, 0x61117e44, 0x71963136, -0x031fb9d6, -0x2bda6fb5, -0x7c53cbb8, 0x5ba43d64, 0x75685abe }, + { 0x5344a32e, -0x72240956, -0x4be4bf88, 0x7d88eab4, 0x4a130d60, 0x5eb0eb97, 0x17bf3e03, 0x1a00d91b }, + { -0x149e0d4e, 0x6e960933, -0x3600b6ae, 0x543d0fa8, 0x7af66569, -0x208d8af0, 0x23b0e6aa, 0x135529b6 } + }, + { + { -0x1dd17c02, -0x0a38e944, -0x17f67a3f, -0x4bd414e7, 0x14254aae, -0x136259c9, 0x1590a613, 0x5972ea05 }, + { -0x522e2ae8, 0x18f0dbd7, -0x303ee0ef, -0x68608778, 0x7114759b, -0x78cd1e10, 0x65ca3a01, 0x79b5b81a }, + { -0x237087ef, 0x0fd4ac20, -0x53b2b058, -0x65652d6c, -0x4cc9fbcc, -0x3fe4d29c, -0x6fa0c425, 0x4f7e9c95 } + }, + { + { 0x355299fe, 0x71c8443d, -0x24141529, -0x7432c4e4, -0x0e5b6b9a, -0x7f6db662, -0x5ebb5238, 0x1942eec4 }, + { 0x5781302e, 0x62674bbc, -0x765223f1, -0x27adf0c7, 0x53fbd9c6, -0x73d66652, 0x2e638e4c, 0x31993ad9 }, + { -0x51dcb66e, 0x7dac5319, 0x0cea3e92, 0x2c1b3d91, 0x253c1122, 0x553ce494, 0x4ef9ca75, 0x2a0a6531 } + }, + { + { 0x3c1c793a, -0x30c9e533, 0x5a35bc3b, 0x2f9ebcac, -0x57325955, 0x60e860e9, 0x6dea1a13, 0x055dc39b }, + { -0x0806d83e, 0x2db7937f, 0x17d0a635, -0x248be0fa, 0x1155af76, 0x5982f3a2, 0x647c2ded, 0x4cf6e218 }, + { -0x3d72a44a, -0x4ee6dd84, 0x774dffab, 0x07e24ebc, -0x1b5cd377, -0x57c38732, 0x10aa24b6, 0x121a3077 } + }, + { + { -0x388b7c37, -0x29a68ec2, -0x47d46951, -0x77401f89, 0x1097bcd3, 0x289e2823, 0x6ced3a9b, 0x527bb94a }, + { -0x60fcb569, -0x1b24a2a2, 0x3034bc2d, -0x1eac03f7, -0x6aae2c4f, 0x46054691, 0x7a40e52d, 0x333fc76c }, + { -0x66a4b7d2, 0x563d992a, 0x6e383801, 0x3405d07c, 0x2f64d8e5, 0x485035de, 0x20a7a9f7, 0x6b89069b } + }, + { + { -0x4a382489, 0x4082fa8c, -0x38cb3eab, 0x068686f8, -0x09185a82, 0x29e6c8d9, -0x589c6431, 0x0473d308 }, + { 0x6270220d, -0x7ed55fbf, -0x06dba4b2, -0x66a57606, 0x5072ef05, -0x00523b32, -0x558c148d, 0x23bc2103 }, + { 0x03589e05, -0x351186da, 0x46dcc492, 0x2b4b4212, -0x19fe56b1, 0x02a1ef74, -0x21fbcbe6, 0x102f73bf } + }, +}, +{ + { + { -0x6c5c9db9, 0x358ecba2, -0x4d97029b, -0x5070679e, 0x68a01c89, 0x412f7e99, -0x328abadc, 0x5786f312 }, + { 0x7ec20d3e, -0x4a5d2af4, -0x5f368d9d, -0x39b42292, -0x3e008cb3, 0x56e89052, 0x2b2ffaba, 0x4929c6f7 }, + { -0x35ebfcd4, 0x337788ff, 0x447f1ee3, -0x0c6defd8, 0x231bccad, -0x74ebf8e1, -0x0dcbb87d, 0x4c817b4b } + }, + { + { -0x5bf4bb7c, 0x413ba057, 0x4f5f6a43, -0x45b3d1e6, -0x511e29e4, 0x614ba0a5, -0x74fa23ad, 0x78a1531a }, + { 0x2871b96e, 0x0ff85385, 0x60c3f1bb, -0x1ec16055, 0x25344402, -0x1102a6ad, 0x75b7744b, 0x0a37c370 }, + { 0x3ad0562b, 0x6cbdf170, -0x36dade5d, -0x7130b7d0, -0x027bdb19, -0x25142cfd, 0x2e5ec56f, 0x72ad82a4 } + }, + { + { 0x67024bc3, -0x3c976c6f, 0x49502fda, -0x71962e93, -0x1ba0b4d7, -0x030d13c4, -0x5c4b343c, 0x065f669e }, + { -0x45049a0a, 0x3f9e8e35, -0x0d8d6c5f, 0x39d69ec8, -0x73095c30, 0x6cb8cd95, 0x73adae6d, 0x17347781 }, + { 0x5532db4d, -0x75ff5139, 0x43e31bb1, -0x47965b1c, -0x2c580aeb, 0x4a0f8552, 0x303d7c08, 0x19adeb7c } + }, + { + { 0x43c31794, -0x62fa4583, -0x6ccddada, 0x2470c8ff, 0x16197438, -0x7cdc2138, -0x7ea964ad, 0x28527098 }, + { 0x53ead9a3, -0x38df349f, 0x512b636e, 0x55b2c97f, -0x2bfd6f4f, -0x4e1ca4a1, 0x3b530ee2, 0x2fd9ccf1 }, + { 0x47f796b8, 0x07bd475b, 0x542c8f54, -0x2d384fed, 0x3b24f87e, 0x2dbd23f4, 0x7b0901d6, 0x6551afd7 } + }, + { + { -0x5e2a3654, 0x68a24ce3, 0x10ff6461, -0x44885cc3, 0x25d3166e, 0x0f86ce44, 0x50b9623b, 0x56507c09 }, + { 0x54aac27f, 0x4546baaf, -0x4d5ba5d8, -0x09099014, 0x562bcfe8, 0x582d1b5b, -0x6df087a1, 0x44b123f3 }, + { -0x2e8ec19d, 0x1206f0b7, 0x15bafc74, 0x353fe3d9, 0x0ad9d94d, 0x194ceb97, -0x062fc52d, 0x62fadd7c } + }, + { + { -0x1831ba6c, 0x3cd7bc61, -0x4822d982, -0x3294ca57, 0x4366ef27, -0x5f7f5438, 0x59c79711, 0x6ec7c46f }, + { 0x5598a074, -0x394a6985, -0x71b6c1db, 0x5efe91ce, 0x49280888, -0x2b48d3bb, -0x5d98bf3e, 0x20ef1149 }, + { 0x6f09a8a2, 0x2f07ad63, 0x24205e7d, -0x79681932, -0x11ca5ec7, -0x3f5103fb, -0x4a062769, 0x15e80958 } + }, + { + { 0x5bb061c4, 0x4dd1ed35, -0x6be3f900, 0x42dc0cef, -0x0279cbf2, 0x61305dc1, 0x0e55a443, 0x56b2cc93 }, + { 0x0c3e235b, 0x25a5ef7d, -0x41ecb119, 0x6c39c17f, 0x2dc5c327, -0x388b1ecc, -0x6dfde0c7, 0x021354b8 }, + { -0x59403a5e, 0x1df79da6, -0x6021bc97, 0x02f3a274, -0x325c6f59, -0x4cdc260e, -0x788b2c9d, 0x7be0847b } + }, + { + { 0x5307fa11, 0x1466f5af, -0x1293f50e, -0x7e803383, -0x3c5b5c05, 0x0a6de44e, -0x436d82f5, 0x74071475 }, + { -0x74c0aa3d, -0x736633a6, 0x3fded2a0, 0x0611d725, 0x36b70a36, -0x12d66a01, -0x2875d9e7, 0x1f699a54 }, + { 0x73e7ea8a, -0x188d6d0d, -0x34fba5cf, 0x296537d2, -0x2cd8b022, 0x1bd0653e, 0x76bd2966, 0x2f9a2c44 } + }, +}, +{ + { + { -0x4aaee366, -0x5d4b2520, 0x2bffff06, 0x7ac86029, -0x0aafbdcc, -0x67e0c8a3, -0x25b15ed3, 0x3f6bd725 }, + { 0x7f5745c6, -0x14e74655, 0x5787c690, 0x023a8aee, 0x2df7afa9, -0x48d8ed26, -0x15a3fec3, 0x36597d25 }, + { 0x106058ac, 0x734d8d7b, 0x6fc6905f, -0x26bfa862, -0x6dfd6cd3, 0x6466f8f9, -0x259f2930, 0x7b7ecc19 } + }, + { + { -0x58830565, 0x6dae4a51, -0x185c79b0, -0x7dd9c9ac, -0x70d27d25, 0x09bbffcd, 0x1bf5caba, 0x03bedc66 }, + { 0x695c690d, 0x78c2373c, 0x0642906e, -0x22dad19a, 0x4ae12bd2, -0x6ae2bbbc, 0x01743956, 0x4235ad76 }, + { 0x078975f5, 0x6258cb0d, -0x6e760d68, 0x49294254, -0x1d1c911c, -0x5f354bdd, -0x320f995f, 0x0e7ce2b0 } + }, + { + { -0x26b48f07, -0x01590121, -0x3e0345d3, -0x0ecf3faf, 0x7f2fab89, 0x4882d47e, -0x7513114b, 0x61525613 }, + { -0x3b737a5d, -0x3b6b9bc6, 0x3c6139ad, -0x02c9e20c, 0x3ae94d48, 0x09db17dd, -0x704b98b6, 0x666e0a5d }, + { 0x4870cb0d, 0x2abbf64e, -0x55ba7495, -0x329a4310, 0x75e8985d, -0x6541b146, -0x2aeb211c, 0x7f0bc810 } + }, + { + { 0x737213a0, -0x7c536253, 0x2ef72e98, -0x60090746, 0x43ec6957, 0x311e2edd, -0x213a548b, 0x1d3a907d }, + { 0x26f4136f, -0x46ff945c, 0x57e03035, -0x7298c962, 0x4f463c28, -0x34372027, -0x0711240b, 0x0d1f8dbc }, + { 0x3ed081dc, -0x45e96ccf, -0x7ae4cb80, 0x29329fad, 0x030321cb, 0x0128013c, -0x5ce4021d, 0x00011b44 } + }, + { + { 0x6a0aa75c, 0x16561f69, 0x5852bd6a, -0x3e408da4, -0x65869953, 0x11a8dd7f, -0x2d7aefda, 0x63d988a2 }, + { 0x3fc66c0c, 0x3fdfa06c, 0x4dd60dd2, 0x5d40e38e, 0x268e4d71, 0x7ae38b38, 0x6e8357e1, 0x3ac48d91 }, + { -0x5042dcd2, 0x00120753, -0x0227097d, -0x16d43148, -0x7b18d46f, -0x07e9964d, 0x2368a066, 0x33fad52b } + }, + { + { -0x3bdd3018, -0x72d33730, 0x05a13acb, 0x072b4f7b, -0x13095a91, -0x5c01491a, -0x46f58e1e, 0x3cc355cc }, + { -0x3a1be1ea, 0x540649c6, 0x333f7735, 0x0af86430, -0x0cfa18ba, -0x4d53032e, -0x5da92359, 0x16c0f429 }, + { -0x6fc16ecf, -0x16496bbd, 0x7a5637ce, -0x475b6b35, -0x45456dbc, -0x37832e5c, 0x6bae7568, 0x631eaf42 } + }, + { + { -0x5c8ff218, 0x47d975b9, -0x1d07faae, 0x7280c5fb, 0x32e45de1, 0x53658f27, 0x665f80b5, 0x431f2c7f }, + { -0x25990161, -0x4c16fbf0, 0x6c16e5a6, -0x7a22b4ae, 0x1ef9bf83, -0x43c2689f, 0x1ea919b5, 0x5599648b }, + { -0x7a7084e7, -0x29fd9cbc, -0x5e15aeb6, 0x14ab352f, 0x2090a9d7, -0x76ffbbe6, -0x6edac4da, 0x7b04715f } + }, + { + { -0x3b19453a, -0x4c893d80, 0x6d1d9b0b, -0x68f12c23, 0x450bf944, -0x4f656aa8, 0x57cde223, 0x48d0acfa }, + { -0x530951bd, -0x7c1242d8, 0x7d5c7ab4, -0x79ca8375, -0x4814d3bc, -0x3fbfb897, -0x3d09a7c1, 0x59b37bf5 }, + { 0x7dabe671, -0x49f0d91c, 0x622f3a37, -0x0e2e5e69, -0x1669fc6c, 0x4208ce7e, 0x336d3bdb, 0x16234191 } + }, +}, +{ + { + { 0x3d578bbe, -0x7ad22e03, -0x3cd79ef8, 0x2b65ce72, -0x1531dd8d, 0x658c07f4, -0x13c754c0, 0x0933f804 }, + { 0x33a63aef, -0x0e651539, 0x4442454e, 0x2c7fba5d, 0x4795e441, 0x5da87aa0, -0x5b1f4f0b, 0x413051e1 }, + { -0x72b69b8a, -0x58549687, -0x034a5438, -0x7ede5522, 0x7b539472, -0x5a23ed11, 0x5e45351a, 0x07fd4706 } + }, + { + { -0x6517183d, 0x30421155, -0x6bb77d5b, -0x0d7e4dd7, 0x378250e4, -0x75ec53d2, 0x54ba48f4, 0x014afa09 }, + { 0x258d2bcd, -0x37a7c3c3, -0x509f48c1, 0x17029a4d, 0x416a3781, -0x05f0362a, 0x38b3fb23, 0x1c1e5fba }, + { 0x1bb3666c, -0x34ce6900, 0x4bffecb9, 0x33006052, 0x1a88233c, 0x29371199, 0x3d4ed364, 0x29188436 } + }, + { + { -0x43e54915, -0x0462c83d, 0x4d57a240, 0x02be1453, -0x075a1e0a, -0x0b28cbeb, 0x0ccc8188, 0x5964f430 }, + { -0x23b45406, 0x033c6805, 0x5596ecc1, 0x2c15bf5e, -0x4a64e2c5, 0x1bc70624, -0x5e60f13b, 0x3ede9850 }, + { 0x2d096800, -0x1bb5dceb, 0x70866996, 0x5c08c559, 0x46affb6e, -0x20d249f6, -0x07a90277, 0x579155c1 } + }, + { + { 0x0817e7a6, -0x4a0e949d, 0x3c351026, -0x7f7396dd, 0x54cef201, 0x324a983b, 0x4a485345, 0x53c09208 }, + { 0x12e0c9ef, -0x69cdb123, -0x0dbdfd69, 0x468b878d, -0x5b0a8c42, 0x199a3776, -0x716e16d6, 0x1e7fbcf1 }, + { -0x0e345041, -0x2d2beb7f, 0x716174e5, 0x231d2db6, -0x1d5aa368, 0x0b7d7656, 0x2aa495f6, 0x3e955cd8 } + }, + { + { 0x61bb3a3f, -0x54c60c11, 0x2eb9193e, -0x714bff9b, 0x38c11f74, -0x4a219134, 0x26f3c49f, 0x654d7e96 }, + { 0x3ed15433, -0x1b70aca2, 0x0d7270a3, -0x2f8a96d6, -0x55219c79, 0x40fbd21d, -0x30bb6a0b, 0x14264887 }, + { 0x5c7d2ceb, -0x1a9b3023, -0x28c83347, -0x7d115022, -0x2e064f55, 0x6107db62, -0x4bca7245, 0x0b6baac3 } + }, + { + { 0x3700a93b, 0x204abad6, -0x25886c8d, -0x41ffdc2d, 0x633ab709, -0x27a0fcba, -0x6f7dfbee, 0x00496dc4 }, + { -0x79dd0168, 0x7ae62bcb, -0x31476e51, 0x47762256, -0x0d1bf94c, 0x1a5a92bc, -0x7b1beaff, 0x7d294017 }, + { -0x3d819ca0, 0x1c74b88d, -0x72eb7af4, 0x07485426, 0x3e0dcb30, -0x5eba0485, 0x43803b23, 0x10843f1b } + }, + { + { -0x1cdb9765, -0x2a9098d3, -0x4c6b567f, -0x2e257513, -0x6e973013, -0x2284a702, 0x4d56c1e8, 0x7ce246cd }, + { 0x376276dd, -0x3a06fbab, -0x289ba327, -0x31a6ea73, 0x1d366b39, -0x6d09a2af, 0x526996c4, 0x11574b6e }, + { 0x7f80be53, -0x470bcf72, 0x34a9d397, 0x5f3cb8cb, 0x33cc2b2c, 0x18a961bd, 0x3a9af671, 0x710045fb } + }, + { + { 0x059d699e, -0x5fc0379e, -0x659e6197, 0x2370cfa1, 0x2f823deb, -0x3b01c4ee, -0x580f7bb2, 0x1d1b056f }, + { 0x101b95eb, 0x73f93d36, 0x4f6f4486, -0x0510cc87, -0x70ea1a9e, 0x5651735f, 0x58b40da1, 0x7fa3f190 }, + { -0x1a9409e1, 0x1bc64631, 0x6e5382a3, -0x2c8654f0, 0x0540168d, 0x4d58c57e, -0x7bbd271c, 0x56625662 } + }, +}, +{ + { + { 0x1ff38640, -0x22b6632a, 0x063625a0, 0x29cd9bc3, 0x3dd73dc3, 0x51e2d802, 0x203b9231, 0x4a25707a }, + { -0x09d9800a, -0x461b6622, 0x742c0843, 0x7772ca7b, -0x165b0d4f, 0x23a0153f, -0x2a2faffa, 0x2cdfdfec }, + { 0x53f6ed6a, 0x2ab7668a, 0x1dd170a1, 0x30424258, 0x3ae20161, 0x4000144c, 0x248e49fc, 0x5721896d } + }, + { + { -0x5e2f25b2, 0x285d5091, -0x4a01c1f8, 0x4baa6fa7, -0x1e6c6c4d, 0x63e5177c, -0x3b4fcf03, 0x03c935af }, + { -0x02e7e452, 0x0b6e5517, 0x2bb963b4, -0x6fdd9d61, 0x32064625, 0x5509bce9, -0x09c3ec26, 0x578edd74 }, + { 0x492b0c3d, -0x668d893a, -0x201dfa04, 0x47ccc2c4, -0x229dc5c4, -0x232d647c, 0x0288c7a2, 0x3ec2ab59 } + }, + { + { -0x51cd2e35, -0x58dec5f7, 0x40f5c2d5, 0x0f2b87df, -0x17e154d7, 0x0baea4c6, 0x6adbac5e, 0x0e1bf66c }, + { -0x1b278447, -0x5e5f2d85, 0x61391aed, -0x5674b215, 0x73cb9b83, -0x665f2230, 0x200fcace, 0x2dd5c25a }, + { 0x792c887e, -0x1d542a17, -0x346d92a3, 0x1a020018, -0x4551a0e2, -0x40459633, 0x5ae88f5f, 0x730548b3 } + }, + { + { -0x5e291ccc, -0x7fa4f6b5, 0x09353f19, -0x40c10e89, 0x0622702b, 0x423f06cb, -0x2787ba23, 0x585a2277 }, + { -0x34574712, -0x3bcaae5d, -0x4deea0ea, 0x65a26f1d, -0x5473c7b0, 0x760f4f52, 0x411db8ca, 0x3043443b }, + { 0x33d48962, -0x5e75a07e, -0x1387da81, 0x6698c4b5, 0x373e41ff, -0x5871905b, 0x50ef981f, 0x76562789 } + }, + { + { -0x15793063, -0x1e8f8c5d, 0x07155fdc, 0x3a8cfbb7, 0x31838a8e, 0x4853e7fc, -0x49ec09ea, 0x28bbf484 }, + { -0x2ae03740, 0x38c3cf59, 0x0506b6f2, -0x64122d03, -0x54a8f171, 0x26bf109f, -0x3e47b95a, 0x3f4160a8 }, + { 0x6f136c7c, -0x0d9ed0a4, -0x0922ee42, -0x50152ef9, 0x13de6f33, 0x527e9ad2, -0x7e7708a3, 0x1e79cb35 } + }, + { + { -0x0a1f7e7f, 0x77e953d8, 0x299dded9, -0x7b5af3bc, -0x79bada1b, -0x2393d2f4, 0x39d1f2f4, 0x478ab52d }, + { -0x11081c0f, 0x013436c3, -0x0161ef08, -0x7d749581, -0x43062104, 0x7ff908e5, 0x3a3b3831, 0x65d7951b }, + { -0x6dad2ea7, 0x66a6a4d3, -0x78e537f9, -0x1a221e44, -0x593e3691, -0x47d394c0, 0x1a212214, 0x16d87a41 } + }, + { + { -0x2ab1fa7d, -0x045b2a1e, 0x2ebd99fa, -0x1de05029, 0x6ee9778f, 0x497ac273, 0x7a5a6dde, 0x1f990b57 }, + { 0x42066215, -0x4c4281a6, 0x0c5a24c1, -0x78641c33, -0x29066b49, 0x57c05db1, 0x65f38ca6, 0x28f87c81 }, + { 0x1be8f7d6, -0x5ccbb153, -0x53158671, 0x7d1e50eb, 0x520de052, 0x77c6569e, 0x534d6d3e, 0x45882fe1 } + }, + { + { -0x6bc3901c, -0x275366d7, -0x5c7c6d5e, -0x4a060e9f, -0x4137650d, 0x2699db13, -0x1bfa0f8c, 0x7dcf843c }, + { 0x757983d6, 0x6669345d, 0x17aa11a6, 0x62b6ed11, -0x67a1ed71, 0x7ddd1857, -0x09d90923, 0x688fe5b8 }, + { 0x4a4732c0, 0x6c90d648, -0x35a9cd67, -0x2adebc03, -0x6ea2391f, -0x4c41d73d, 0x7327191b, 0x6739687e } + }, +}, +{ + { + { -0x363468e1, -0x731a5530, -0x602ab5d7, 0x1156aaa9, 0x15af9b78, 0x41f72470, 0x420f49aa, 0x1fe8cca8 }, + { 0x200814cf, -0x609a3a16, 0x69a31740, -0x7bfac91f, 0x25c8b4ad, -0x74f12ec7, -0x16c9c9e3, 0x0080dbaf }, + { 0x3c0cc82a, 0x72a1848f, -0x788361ac, 0x38c560c2, -0x31aabec0, 0x5004e228, 0x03429d71, 0x042418a1 } + }, + { + { 0x20816247, 0x58e84c6f, -0x1c90286d, -0x724d4d4a, 0x1d484d85, -0x688e7daa, -0x79cd5429, 0x0822024f }, + { -0x540c00a1, -0x766215af, 0x2fc2d8ba, -0x646c5799, -0x419142a4, 0x2c38cb97, -0x68d9c4a3, 0x114d5784 }, + { 0x6b1beca3, -0x4cfe4484, -0x3914ec8b, 0x55393f6d, -0x68491b15, -0x6ef2d7f0, -0x62b8615d, 0x1ad4548d } + }, + { + { 0x0fe9fed3, -0x5f901993, 0x1c587909, -0x578cc5c0, 0x0df98953, 0x30d14d80, -0x384cfda8, 0x41ce5876 }, + { 0x389a48fd, -0x32a58260, -0x6587c8e2, -0x4c705b56, 0x2cdb8e6c, -0x392689e5, -0x3681ebbd, 0x35cf51db }, + { -0x298f3fde, 0x59ac3bc5, -0x64ee6bfa, -0x151983f0, -0x4c87d026, -0x68674210, -0x02f8bf6e, 0x651e3201 } + }, + { + { 0x1efcae9e, -0x5a845b60, -0x23cf756c, 0x769f4bee, 0x3603cb2e, -0x2e0ef115, 0x7e441278, 0x4099ce5e }, + { -0x10cf3a31, -0x29c27b7d, 0x2361cc0c, 0x4cd4b496, -0x5b7bd954, -0x116f1b00, 0x18c14eeb, 0x0af51d7d }, + { -0x75aede17, 0x1ac98e4f, -0x2405d020, 0x7dae9544, -0x29bcf207, -0x7cdf55f3, 0x2c4a2fb5, 0x66728265 } + }, + { + { 0x2946db23, -0x52574920, 0x7b253ab7, 0x1c0ce51a, 0x66dd485b, -0x7bb737a6, -0x2f98a521, 0x7f1fc025 }, + { -0x27943655, -0x78b9de0c, 0x56fe6fea, -0x4ab38442, 0x7fadc22c, 0x077a2425, 0x19b90d39, 0x1ab53be4 }, + { 0x319ea6aa, -0x2711e4e8, 0x3a21f0da, 0x004d8808, -0x77c5b0b5, 0x3bd6aa1d, -0x202602ec, 0x4db9a3a6 } + }, + { + { -0x34488398, -0x26a4ff45, -0x6e0e87b7, -0x22437b96, -0x41d7264d, 0x7cf700ae, -0x7a2ce0c2, 0x5ce1285c }, + { -0x4663f8ab, -0x73184dc5, -0x3b0af086, 0x35c5d6ed, -0x1264af3d, 0x7e1e2ed2, -0x176cb25f, 0x36305f16 }, + { -0x674f4218, 0x31b6972d, -0x535921a5, 0x7d920706, -0x6f759a61, -0x198cef08, -0x1020fdcb, 0x50fac2a6 } + }, + { + { -0x090bb644, 0x295b1c86, 0x1f0ab4dd, 0x51b2e84a, -0x5571aae3, -0x3ffe34d0, 0x44f43662, 0x6a28d359 }, + { 0x5b880f5a, -0x0c2c560d, -0x24fc183e, -0x1213faf4, -0x060f4e5e, -0x576967e1, -0x53a1cb5c, 0x49a4ae2b }, + { 0x04a740e0, 0x28bb12ee, -0x64317e8c, 0x14313bbd, -0x173ef3c0, 0x72f5b5e4, 0x36adcd5b, 0x7cbfb199 } + }, + { + { -0x33c91920, -0x7186c586, 0x7d586eed, -0x0605485d, -0x451e0b1c, 0x3a4f9692, -0x00a0bb82, 0x1c14b03e }, + { 0x6b89792d, -0x5cee223e, -0x25aed99c, 0x1b30b4c6, -0x30eaf7a7, 0x0ca77b4c, 0x1b009408, 0x1de443df }, + { 0x14a85291, 0x19647bd1, 0x1034d3af, 0x57b76cb2, 0x0f9d6dfa, 0x6329db44, 0x6a571493, 0x5ef43e58 } + }, +}, +{ + { + { -0x37f3e540, -0x59923363, 0x1b38a436, -0x685fa30c, -0x6a24283a, -0x58140c42, -0x72818255, 0x7da0b8f6 }, + { 0x385675a6, -0x1087dfec, -0x55025618, -0x5d9b60d0, 0x5cdfa8cb, 0x4cd1eb50, 0x1d4dc0b3, 0x46115aba }, + { -0x3c4a258a, -0x2bf0e6ad, 0x21119e9b, 0x1dac6f73, -0x014da6a0, 0x03cc6021, -0x7c98b4b5, 0x5a5f887e } + }, + { + { -0x5f59bc47, -0x6169d72d, -0x193cdf9c, -0x4a3c3500, 0x7c2dec32, -0x64acfd77, -0x2a2e38f4, 0x43e37ae2 }, + { 0x70a13d11, -0x709cfe31, 0x350dd0c4, -0x303147eb, -0x5b435b82, -0x08fd682c, -0x1bb2ebcc, 0x3669b656 }, + { -0x12591ecd, 0x387e3f06, -0x665ec540, 0x67301d51, 0x36263811, -0x42a52708, 0x4fd5e9be, 0x6a21e6cd } + }, + { + { 0x6699b2e3, -0x10bed6ee, 0x708d1301, 0x71d30847, 0x1182b0bd, 0x325432d0, 0x001e8b36, 0x45371b07 }, + { 0x3046e65f, -0x0e39e8f6, 0x00d23524, 0x58712a2a, -0x737d48ab, 0x69dbbd3c, -0x5e6a00a9, 0x586bf9f1 }, + { 0x5ef8790b, -0x5924f773, 0x610937e5, 0x5278f0dc, 0x61a16eb8, -0x53fcb62e, -0x6f1ade87, 0x0eafb037 } + }, + { + { 0x0f75ae1d, 0x5140805e, 0x2662cc30, -0x13fd041d, -0x156dc693, 0x2cebdf1e, -0x3abca44d, 0x44ae3344 }, + { 0x3748042f, -0x69faaa3f, -0x7df455ef, 0x219a41e6, 0x73486d0c, 0x1c81f738, 0x5a02c661, 0x309acc67 }, + { -0x445abc12, -0x630d7647, 0x5ac97142, -0x0c89f163, 0x4f9360aa, 0x1d82e5c6, 0x7f94678f, 0x62d5221b } + }, + { + { 0x3af77a3c, 0x7585d426, -0x0116ebb3, -0x205184ef, 0x59f7193d, -0x5af98f80, -0x7c6ddfc9, 0x14f29a53 }, + { 0x18d0936d, 0x524c299c, -0x75f3e5f4, -0x37944a94, -0x24b579cf, -0x5c8afad2, -0x438aba9e, 0x5c0efde4 }, + { 0x25b2d7f5, -0x208e8124, -0x664acfc0, 0x21f970db, -0x3c12b39e, -0x256dcb49, 0x7bee093e, 0x5e72365c } + }, + { + { 0x2f08b33e, 0x7d933906, -0x2060cd42, 0x5b9659e5, 0x1f9ebdfd, -0x5300c253, -0x348cb649, 0x70b20555 }, + { 0x4571217f, 0x575bfc07, 0x0694d95b, 0x3779675d, -0x0be6e1cd, -0x65f5c845, 0x47b4eabc, 0x77f1104c }, + { 0x55112c4c, -0x41aeec3b, -0x6577e033, 0x6688423a, 0x5e503b47, 0x44667785, 0x4a06404a, 0x0e34398f } + }, + { + { 0x3e4b1928, 0x18930b09, 0x73f3f640, 0x7de3e10e, 0x73395d6f, -0x0bcde826, -0x35c863c2, 0x6f8aded6 }, + { 0x3ecebde8, -0x4982dd27, 0x27822f07, 0x09b3e841, -0x4fa49273, 0x743fa61f, -0x75c9dc8e, 0x5e540536 }, + { -0x02484d66, -0x1cbfedc3, -0x5de54d6f, 0x487b97e1, -0x02196b62, -0x066982fe, -0x372c2169, 0x780de72e } + }, + { + { 0x00f42772, 0x671feaf3, 0x2a8c41aa, -0x708d14d6, -0x68c8cd6e, 0x29a17fd7, 0x32b587a6, 0x1defc6ad }, + { 0x089ae7bc, 0x0ae28545, 0x1c7f4d06, 0x388ddecf, 0x0a4811b8, 0x38ac1551, 0x71928ce4, 0x0eb28bf6 }, + { -0x10ae6a59, -0x50a441e6, -0x6e84ea13, 0x148c1277, 0x7ae5da2e, 0x2991f7fb, -0x0722d799, 0x467d201b } + }, +}, +{ + { + { 0x296bc318, 0x745f9d56, -0x27ead19b, -0x66ca7f2c, 0x5839e9ce, -0x4f1a4ec1, -0x2bc6de40, 0x51fc2b28 }, + { -0x0842d195, 0x7906ee72, 0x109abf4e, 0x05d270d6, -0x46be575c, -0x72a301bb, 0x1c974287, 0x44c21867 }, + { -0x6a1d5674, 0x1b8fd117, 0x2b6b6291, 0x1c4e5ee1, 0x7424b572, 0x5b30e710, 0x4c4f4ac6, 0x6e6b9de8 } + }, + { + { -0x07f34f78, 0x6b7c5f10, 0x56e42151, 0x736b54dc, -0x3910663c, -0x3d49df5b, -0x3c5f90be, 0x5f4c802c }, + { 0x4b1de151, -0x200da032, -0x1ee3bfdb, -0x27be3f39, 0x54749c87, 0x2554b3c8, -0x6f71f207, 0x2d292459 }, + { 0x7d0752da, -0x649a370f, -0x38811800, -0x77e31cc8, 0x5b62f9e3, -0x3c4aeb10, -0x413ef2b8, 0x66ed5dd5 } + }, + { + { -0x3435fb83, -0x0f520c37, -0x0baad095, -0x7e3c4d35, 0x44735f93, -0x3025eed3, 0x7e20048c, 0x1f23a0c7 }, + { 0x0bb2089d, 0x7d38a1c2, -0x69332bee, -0x7f7ccb1f, 0x6c97d313, -0x3b58f474, 0x03007f20, 0x2eacf8bc }, + { -0x1a43ea90, -0x0dcab985, 0x0dbab38c, 0x03d2d902, -0x03061f62, 0x27529aa2, -0x62cb43b0, 0x0840bef2 } + }, + { + { 0x7f37e4eb, -0x32ab1f95, -0x0a169336, -0x733ea079, -0x2ca68232, -0x47db7450, 0x6074400c, 0x246affa0 }, + { -0x23ef4d79, 0x796dfb35, 0x5c7ff29d, 0x27176bcd, -0x384db6fb, 0x7f3d43e8, -0x6e3abd8a, 0x0304f5a1 }, + { -0x041bacdf, 0x37d88e68, -0x3f28afce, -0x79f68ab8, -0x76b5f2cb, 0x4e9b13ef, 0x5753d325, 0x25a83cac } + }, + { + { 0x3952b6e2, -0x60f099d7, 0x0934267b, 0x33db5e0e, -0x29f60124, -0x00badad5, -0x3af91f37, 0x06be10f5 }, + { -0x1127e9a2, 0x10222f48, 0x4b8bcf3a, 0x623fc123, -0x3dde1710, 0x1e145c09, -0x3587d9d0, 0x7ccfa59f }, + { -0x49d5cba1, 0x1a9615a9, 0x4a52fecc, 0x22050c56, 0x28bc0dfe, -0x585d877b, 0x1a1ee71d, 0x5e82770a } + }, + { + { 0x42339c74, -0x17fd17f6, -0x5800051b, 0x34175166, 0x1c408cae, 0x34865d1f, 0x605bc5ee, 0x2cca982c }, + { -0x527695a4, 0x35425183, -0x1872ad0a, -0x1798c505, -0x6d5ca09c, 0x2c66f25f, 0x3b86b102, 0x09d04f3b }, + { 0x197dbe6e, -0x02d2a2cb, -0x741b005d, 0x207c2eea, 0x325ae918, 0x2613d8db, 0x27741d3e, 0x7a325d17 } + }, + { + { 0x7e2a076a, -0x132d82ff, 0x1636495e, -0x28779761, -0x6e6dcc1b, 0x52a61af0, 0x7bb1ae64, 0x2a479df1 }, + { -0x2e92021e, -0x2fc94645, -0x3b6857d7, -0x5dfaa8a9, -0x580ed999, -0x7193369a, 0x1239c180, 0x4d3b1a79 }, + { 0x33db2710, -0x61a11172, -0x293bc35b, 0x189854de, -0x6d8e7ec8, -0x5be3dd3b, -0x5bc5a165, 0x27ad5538 } + }, + { + { -0x71b8f884, -0x34a5829d, 0x20a1c059, -0x7248ac9f, -0x74120234, 0x549e1e4d, 0x503b179d, 0x080153b7 }, + { 0x15350d61, 0x2746dd4b, -0x116ade49, -0x2fc03438, 0x138672ca, -0x1791c9a6, 0x7e7d89e2, 0x510e987f }, + { 0x0a3ed3e3, -0x2259626d, -0x329f58de, 0x3d386ef1, -0x4255b11a, -0x37e852a8, 0x4fe7372a, 0x23be8d55 } + }, +}, +{ + { + { 0x567ae7a9, -0x43e10b43, -0x29bb6743, 0x3f624cb2, 0x2c1f4ec8, -0x1bef9b2e, -0x45c7bfff, 0x2ef9c5a5 }, + { 0x74ef4fad, -0x6a016e66, -0x095cf75e, 0x3a827bec, 0x09a47b01, -0x69b1fe2d, 0x5ba3c797, 0x71c43c4f }, + { -0x05618b33, -0x4902920a, -0x1b50d986, -0x0e7d8744, -0x0e1066f2, -0x7daa4c30, -0x6f3a0d6d, 0x5a758ca3 } + }, + { + { 0x1d61dc94, -0x731f6e75, -0x657ecf9a, -0x7212c9ba, -0x5017552d, -0x2b1957d7, -0x09c62bc1, 0x0a738027 }, + { -0x26b9db6b, -0x5d48d8f0, -0x2a82affd, 0x3aa8c6d2, -0x5f4b7836, -0x1c2bff41, -0x4c148d14, 0x2dbae244 }, + { 0x57ffe1cc, -0x67f0b5d1, -0x1e7c67bd, 0x00670d0d, 0x49fb15fd, 0x105c3f4a, 0x5126a69c, 0x2698ca63 } + }, + { + { 0x5e3dd90e, 0x2e3d702f, -0x1b2dac7a, -0x61c0f6e8, 0x024da96a, 0x5e773ef6, 0x4afa3332, 0x3c004b0c }, + { 0x32b0ba78, -0x189ace78, -0x6da30075, 0x381831f7, -0x5fd6e034, 0x08a81b91, 0x49caeb07, 0x1fb43dcc }, + { 0x06f4b82b, -0x6556b954, -0x57f93b0d, 0x1ca284a5, -0x3932b879, 0x3ed3265f, -0x32e02de9, 0x6b43fd01 } + }, + { + { 0x3e760ef3, -0x4a38bda8, -0x11f54670, 0x75dc52b9, 0x072b923f, -0x40ebd83e, 0x6ff0d9f0, 0x73420b2d }, + { 0x4697c544, -0x3858a2b5, -0x20f00041, 0x15fdf848, -0x55b987a6, 0x2868b9eb, 0x5b52f714, 0x5a68d710 }, + { -0x617ae1fa, -0x50d30935, -0x39ddc73c, -0x70a6c6ed, -0x66040c8d, -0x2575476a, -0x15cb4362, 0x3db5632f } + }, + { + { -0x7d67da2b, 0x2e4990b1, 0x3e9a8991, -0x12151479, 0x4c704af8, -0x110fc2c7, -0x6a20d4f2, 0x59197ea4 }, + { -0x08a22628, -0x0b9111d5, 0x396759a5, 0x0d17b1f6, 0x499e7273, 0x1bf2d131, 0x49d75f13, 0x04321adf }, + { -0x1b1aa552, 0x04e16019, 0x7e2f92e9, -0x1884bc86, 0x6f159aa4, -0x3831d23f, -0x0b28f340, 0x45eafdc1 } + }, + { + { -0x30334e13, -0x49f1b9dc, -0x42a3fc6b, 0x59dbc292, -0x23fb7e37, 0x31a09d1d, 0x5d56d940, 0x3f73ceea }, + { -0x7fba28d5, 0x69840185, -0x30d0f9af, 0x4c22faa2, 0x6b222dc6, -0x6be5c99b, 0x0362dade, 0x5a5eebc8 }, + { 0x0a4e8dc6, -0x4858402f, 0x44c9b339, -0x41a8ff82, 0x1557aefa, 0x60c1207f, 0x266218db, 0x26058891 } + }, + { + { -0x39891abe, 0x4c818e3c, 0x03ceccad, 0x5e422c93, -0x4bed60f8, -0x13f83336, -0x4dbbbc48, 0x0dedfa10 }, + { -0x7c9f00fc, 0x59f704a6, 0x7661e6f4, -0x3c26c022, 0x12873551, -0x7ce4d58d, 0x4e615d57, 0x54ad0c2e }, + { -0x47d4add6, -0x11c4982b, -0x605a3e15, 0x36f16346, 0x6ec19fd3, -0x5a4b2d0e, -0x58856bf8, 0x62ecb2ba } + }, + { + { -0x5049d78c, -0x6df8d7ca, 0x79e104a5, 0x5fcd5e85, -0x39cf5eb6, 0x5aad01ad, 0x75663f98, 0x61913d50 }, + { 0x61152b3d, -0x1a1286ae, 0x0eddd7d1, 0x4962357d, -0x4694b38f, 0x7482c8d0, -0x56992742, 0x2e59f919 }, + { 0x1a3231da, 0x0dc62d36, -0x6bdffd90, -0x05b8a7ce, 0x3f9594ce, 0x02d80151, 0x31c05d5c, 0x3ddbc2a1 } + }, +}, +{ + { + { 0x004a35d1, -0x048ca53e, 0x3a6607c3, 0x31de0f43, -0x3ad72a67, 0x7b8591bf, -0x0a44faf4, 0x55be9a25 }, + { 0x4ffb81ef, 0x3f50a50a, 0x3bf420bf, -0x4e1fcaf7, -0x3955d330, -0x645571e4, -0x05dc85c0, 0x32239861 }, + { 0x33db3dbf, 0x0d005acd, -0x7f53ca1e, 0x0111b37c, 0x6f88ebeb, 0x4892d66c, 0x6508fbcd, 0x770eadb1 } + }, + { + { -0x5faf8e47, -0x0e2c497f, 0x3592ff3a, 0x2207659a, 0x7881e40e, 0x5f016929, -0x7945c8b2, 0x16bedd0e }, + { 0x5e4e89dd, -0x7bae0620, -0x4386c6c9, -0x3f9cfd01, 0x56a6495c, 0x5d227495, -0x5fa9fc05, 0x09a6755c }, + { 0x2c2737b5, 0x5ecccc4f, 0x2dccb703, 0x43b79e0c, 0x4ec43df3, 0x33e008bc, -0x0f8a9940, 0x06c1b840 } + }, + { + { -0x64fd7fa4, 0x69ee9e7f, 0x547d1640, -0x34007d76, -0x4dbcf698, 0x3d93a869, 0x3fe26972, 0x46b7b8cd }, + { -0x5c770789, 0x7688a5c6, -0x214d4954, 0x02a96c14, 0x1b8c2af8, 0x64c9f343, 0x54a1eed6, 0x36284355 }, + { -0x01811420, -0x167edf7a, 0x2f515437, 0x4cba6be7, 0x516efae9, 0x1d04168b, 0x43982cb9, 0x5ea13910 } + }, + { + { -0x2a2c4ffe, 0x6f2b3be4, 0x6a09c880, -0x5013cc27, -0x57433b34, 0x035f73a4, 0x4662198b, 0x22c5b928 }, + { -0x0b8fd11f, 0x49125c9c, -0x74da4cd3, 0x4520b71f, 0x501fef7e, 0x33193026, -0x372d14d5, 0x656d8997 }, + { 0x433d8939, -0x34a73702, 0x6a8d7e50, -0x765f34d2, 0x09fbbe5a, 0x79ca9553, -0x32803efa, 0x0c626616 } + }, + { + { -0x040bab4f, -0x70203c87, -0x0e5b488f, 0x45a5a970, -0x452ca6eb, -0x536de109, -0x57e3de6e, 0x42d088dc }, + { 0x4879b61f, 0x1ffeb80a, 0x4ada21ed, 0x6396726e, 0x368025ba, 0x33c7b093, -0x0c3ce878, 0x471aa0c6 }, + { -0x5fe9ae67, -0x7025f0c9, -0x375f1cbd, 0x0adadb77, -0x378a17e0, 0x20fbfdfc, 0x0c2206e7, 0x1cf2bea8 } + }, + { + { 0x02c0412f, -0x67d291e6, -0x24a71702, -0x6f05b37d, -0x234e7440, 0x01c2f5bc, 0x216abc66, 0x686e0c90 }, + { -0x4c9dfd54, -0x3d220e22, -0x2d1d855b, -0x6d5a01f7, -0x03f60e2d, 0x7d1648f6, 0x13bc4959, 0x74c2cc05 }, + { -0x5abc6a59, 0x1fadbadb, -0x51f25996, -0x4be5fd60, -0x445c83f9, -0x40e60a68, -0x21b7bcf3, 0x6a12b8ac } + }, + { + { 0x1aaeeb5f, 0x793bdd80, -0x3eae778f, 0x00a2a0aa, 0x1f2136b4, -0x175c8c5d, -0x036e10e7, 0x48aab888 }, + { 0x39d495d9, -0x072515e1, 0x525f1dfc, 0x592c190e, -0x3666e2e5, -0x247342fc, -0x2770f349, 0x11f7fda3 }, + { 0x5830f40e, 0x041f7e92, 0x79661c06, 0x002d6ca9, 0x2b046a2e, -0x79236007, -0x74fb6c2f, 0x76036092 } + }, + { + { 0x695a0b05, -0x4bcef71b, -0x52c85c75, 0x6cb00ee8, -0x5cac8c7f, 0x5edad6ee, -0x4923cddc, 0x3f2602d4 }, + { 0x120cf9c6, 0x21bb41c6, -0x21325a65, -0x154d55ee, 0x0aa48b34, -0x3e58d2fe, -0x1782c498, 0x215d4d27 }, + { 0x5bcaf19c, -0x374db84a, -0x4e4d39ae, 0x49779dc3, -0x2a131d1e, -0x765e7f45, -0x31371fc7, 0x13f098a3 } + }, +}, +{ + { + { 0x2796bb14, -0x0c55a85e, -0x64f825df, -0x77c54549, 0x31a0391c, -0x1ab41de8, -0x27cdfa07, 0x5ee7fb38 }, + { -0x31a13ab5, -0x6523f007, -0x73d0ecf3, 0x039c2a6b, -0x0f076aeb, 0x028007c7, -0x53fb4c95, 0x78968314 }, + { 0x41446a8e, 0x538dfdcb, 0x434937f9, -0x5a530257, 0x263c8c78, 0x46af908d, -0x6435f2f7, 0x61d0633c } + }, + { + { -0x07038c21, -0x525cd744, -0x590fc804, -0x117b96a3, 0x38c2a909, 0x637fb4db, -0x07f98424, 0x5b23ac2d }, + { -0x0024da9a, 0x63744935, 0x780b68bb, -0x3a429477, 0x553eec03, 0x6f1b3280, 0x47aed7f5, 0x6e965fd8 }, + { -0x117fad85, -0x652d46ad, -0x05219273, -0x1770e656, 0x150e82cf, 0x0e711704, -0x226a2124, 0x79b9bbb9 } + }, + { + { -0x71608c8c, -0x2e668252, -0x3044f7ea, -0x5fcd5d08, 0x6d445f0a, -0x329345ee, 0x0accb834, 0x1ba81146 }, + { 0x6a3126c2, -0x144caac0, 0x68c8c393, -0x2d9c7c58, -0x1a46857e, 0x6c0c6429, -0x3602deb9, 0x5065f158 }, + { 0x0c429954, 0x708169fb, -0x28913099, -0x1eb9ff54, 0x70e645ba, 0x2eaab98a, 0x58a4faf2, 0x3981f39e } + }, + { + { 0x6de66fde, -0x37ba205b, 0x2c40483a, -0x1ead5b00, -0x384b09ce, -0x162d1e9d, -0x2343e49b, 0x30f4452e }, + { 0x59230a93, 0x18fb8a75, 0x60e6f45d, 0x1d168f69, 0x14a93cb5, 0x3a85a945, 0x05acd0fd, 0x38dc0837 }, + { -0x3a8a68c0, -0x7a92d87e, -0x06634134, -0x05ecba97, -0x3f15b18f, -0x77bb038d, 0x593f2469, 0x632d9a1a } + }, + { + { -0x12f37b59, -0x40f602ef, 0x0d9f693a, 0x63f07181, 0x57cf8779, 0x21908c2d, -0x7509b45e, 0x3a5a7df2 }, + { -0x47f8345a, -0x094494eb, -0x43ab0f29, 0x1823c7df, 0x6e29670b, -0x44e268fd, 0x47ed4a57, 0x0b24f488 }, + { 0x511beac7, -0x23252b42, -0x12d9330e, -0x5bac7f8b, 0x005f9a65, -0x1e630061, 0x75481f63, 0x34fcf744 } + }, + { + { 0x78cfaa98, -0x5a44e255, 0x190b72f2, 0x5ceda267, 0x0a92608e, -0x6cf636ef, 0x2fb374b0, 0x0119a304 }, + { 0x789767ca, -0x3e681fb4, 0x38d9467d, -0x478eb235, -0x7c06a058, 0x55de8882, 0x4dfa63f7, 0x3d3bdc16 }, + { -0x173de883, 0x67a2d89c, 0x6895d0c1, 0x669da5f6, -0x4d7d5d50, -0x0a9a671b, -0x121df58d, 0x56c088f1 } + }, + { + { 0x24f38f02, 0x581b5fac, -0x451cf343, -0x56f41602, -0x75306d10, -0x65de96fe, -0x7ca6fc71, 0x038b7ea4 }, + { 0x10a86e17, 0x336d3d11, 0x0b75b2fa, -0x280c77ce, 0x25072988, -0x06eacc8a, -0x66ef7479, 0x09674c6b }, + { -0x66ce9008, -0x60b107df, -0x155872b1, 0x2f49d282, 0x5aef3174, 0x0971a5ab, 0x5969eb65, 0x6e5e3102 } + }, + { + { 0x63066222, 0x3304fb0e, -0x785345c1, -0x04caf977, -0x73ef9e5d, -0x42e6db89, -0x2e7c79e0, 0x3058ad43 }, + { -0x781a6c05, -0x4e939d0b, -0x35a2c18f, 0x4999edde, 0x14cc3e6d, -0x4b6e3e20, -0x76572458, 0x08f51147 }, + { -0x1a899c30, 0x323c0ffd, -0x5dd159f0, 0x05c3df38, -0x5366b066, -0x42387543, -0x101c2367, 0x26549fa4 } + }, +}, +{ + { + { -0x08ac6947, 0x04dbbc17, -0x2d0798ba, 0x69e6a2d7, -0x0ac1543a, -0x39bf6267, 0x332e25d2, 0x606175f6 }, + { -0x78317077, 0x738b38d7, 0x4179a88d, -0x49d9a71e, -0x0eaece93, 0x30738c9c, 0x727275c9, 0x49128c7f }, + { -0x0abf1823, 0x4021370e, -0x5e0e2f5b, 0x0910d6f5, 0x5b06b807, 0x4634aacd, 0x6944f235, 0x6a39e635 } + }, + { + { 0x74049e9d, 0x1da19657, -0x6701cad5, -0x0432915f, -0x33adc95a, -0x4e3432b0, 0x3f9846e2, 0x1f5ec83d }, + { -0x206f0c19, -0x6932a9c0, -0x2405da16, 0x6c3a760e, 0x59e33cc4, 0x24f3ef09, 0x530d2e58, 0x42889e7e }, + { 0x328ccb75, -0x7104dc3d, -0x22789117, -0x50bd5df9, 0x5dfae796, 0x20fbdadc, 0x06bf9f51, 0x241e246b } + }, + { + { 0x6280bbb8, 0x7eaafc9a, -0x0bfc27f7, 0x22a70f12, 0x1bfc8d20, 0x31ce40bb, -0x1742ac12, 0x2bc65635 }, + { -0x5291670a, 0x29e68e57, 0x0b462065, 0x4c9260c8, -0x5ae144b5, 0x3f00862e, -0x4c726f69, 0x5bc2c77f }, + { -0x5694526d, -0x172a2361, -0x21e6b824, -0x1a704e83, 0x65185fa3, 0x681532ea, 0x034a7830, 0x1fdd6c3b } + }, + { + { 0x2dd8f7a9, -0x63ec595b, 0x3efdcabf, 0x2dbb1f8c, 0x5e08f7b5, -0x69e1cdc0, -0x4419361b, 0x48c8a121 }, + { 0x55dc18fe, 0x0a64e28c, 0x3399ebdd, -0x1c206167, 0x70e2e652, 0x79ac4323, 0x3ae4cc0e, 0x35ff7fc3 }, + { 0x59646445, -0x03bea584, -0x3ed749eb, -0x2ddb4d29, 0x05fbb912, 0x6035c9c9, 0x74429fab, 0x42d7a912 } + }, + { + { -0x6cc25a44, -0x565b76b9, -0x3d168614, 0x4a58920e, 0x13e5ac4c, -0x69278000, 0x4b48b147, 0x453692d7 }, + { -0x1508d12d, 0x4e6213e3, 0x43acd4e7, 0x6794981a, 0x6eb508cb, -0x00ab8322, 0x10fcb532, 0x6fed19dd }, + { -0x57aa6391, -0x2288a267, -0x20ffc1dc, -0x0bd5dec0, -0x256d759a, 0x5223e229, 0x6d38f22c, 0x063f46ba } + }, + { + { 0x37346921, 0x39843cb7, 0x38c89447, -0x58b804f9, -0x5dbacf82, -0x34727fcf, 0x6d82f068, 0x67810f8e }, + { 0x5f536694, -0x2d2dbd77, 0x42939b2c, -0x35cc5d3b, -0x382246a4, -0x6790525a, 0x2f712d5d, 0x5a152c04 }, + { -0x2dd7824c, 0x3eeb8fbc, 0x01a03e93, 0x72c7d3a3, -0x4267d9a6, 0x5473e88c, 0x5921b403, 0x7324aa51 } + }, + { + { -0x17dcab35, -0x52dc0926, -0x49a8e593, 0x6962502a, -0x1c71c82f, -0x649ae9ca, -0x2e5cced1, 0x5cac5005 }, + { 0x6c3cbe8e, -0x7a86bd0c, 0x4730c046, -0x5e2c9b4f, -0x2dc3be41, 0x1c8ed914, -0x11092a2e, 0x0838e161 }, + { -0x161c66fc, -0x733eab34, -0x7b2197ba, 0x5b3a040b, -0x4e41a292, -0x3b2759e4, -0x2779e0fe, 0x40fb897b } + }, + { + { 0x5ab10761, -0x1a8127b9, 0x6fd13746, 0x71435e20, -0x32fda9ce, 0x342f824e, -0x5786e185, 0x4b16281e }, + { 0x62de37a1, -0x7b3a5570, 0x0d1d96e1, 0x421da500, 0x6a9242d9, 0x78828630, 0x690d10da, 0x3c5e464a }, + { 0x0b813381, -0x2e3efe2b, 0x76ee6828, -0x2119f0ef, 0x383f6409, 0x0cb68893, -0x0900b7b6, 0x6183c565 } + }, +}, +{ + { + { -0x50c09992, -0x24b97ab7, -0x0eb5f15b, -0x288030fc, -0x5b45f3b9, 0x3df23ff7, 0x32ce3c85, 0x3a10dfe1 }, + { 0x1e6bf9d6, 0x741d5a46, 0x7777a581, 0x2305b3fc, 0x6474d3d9, -0x2baa8b5e, 0x6401e0ff, 0x1926e1dc }, + { -0x15e83160, -0x1f80b176, 0x3a1fc1fd, 0x2fd51546, 0x31f2c0f1, 0x175322fd, -0x79e1a2eb, 0x1fa1d01d } + }, + { + { -0x2e206b55, 0x38dcac00, -0x2ef7f217, 0x2e712bdd, -0x022a1d9e, 0x7f13e93e, -0x1165fe1b, 0x73fced18 }, + { 0x7d599832, -0x337faa6c, 0x37f15520, 0x1e4656da, 0x4e059320, -0x6609088c, 0x6a75cf33, 0x773563bc }, + { 0x63139cb3, 0x06b1e908, -0x3a5fc133, -0x5b6c2599, -0x529c76ce, -0x72883138, 0x1b864f44, 0x1f426b70 } + }, + { + { -0x6e5edaae, -0x0e81ca38, 0x575e9c76, -0x48947ead, 0x0d9b723e, -0x057cbf91, 0x3fa7e438, 0x0b76bb1b }, + { 0x41911c01, -0x1036d9b4, 0x17a22c25, -0x0e5c4848, -0x0cf0ebb9, 0x5875da6b, 0x1d31b090, 0x4e1af527 }, + { 0x7f92939b, 0x08b8c1f9, -0x2bbb5492, -0x41988e35, -0x66447fe9, 0x22e56463, -0x488d56ab, 0x7b6dd61e } + }, + { + { -0x54fe2d39, 0x5730abf9, 0x40143b18, 0x16fb76dc, -0x5f344d7f, -0x7993419b, -0x64009502, 0x53fa9b65 }, + { 0x50f33d92, -0x48523e18, 0x608cd5cf, 0x7998fa4f, -0x7203a425, -0x5269d243, -0x50e2d0b1, 0x703e9bce }, + { -0x6b77abab, 0x6c14c8e9, 0x65aed4e5, -0x7bc5a29a, -0x4329a50f, 0x181bb73e, -0x3b39e0b0, 0x398d93e5 } + }, + { + { -0x2d181c0e, -0x3c7883a0, 0x30828bb1, 0x3b34aaa0, 0x739ef138, 0x283e26e7, 0x02c30577, 0x699c9c90 }, + { 0x33e248f3, 0x1c4bd167, 0x15bf0a5f, -0x4261ed79, -0x5ef4fc8a, -0x2bc07310, -0x20e6e4ed, 0x53b09b5d }, + { 0x5946f1cc, -0x0cf958dd, -0x331a2683, -0x6de8e74b, -0x7e4b168b, 0x28cdd247, 0x6fcdd907, 0x51caf30c } + }, + { + { 0x18ac54c7, 0x737af99a, -0x3ae34cf1, -0x6fcc8724, 0x4ce10cc7, 0x2b89bc33, -0x76071666, 0x12ae29c1 }, + { 0x7674e00a, -0x59f458be, -0x5e85840d, 0x630e8570, -0x30ccdb34, 0x3758563d, 0x2383fdaa, 0x5504aa29 }, + { 0x1f0d01cf, -0x56613f35, 0x3a34f7ae, 0x0dd1efcc, -0x2f63b1de, 0x55ca7521, 0x58eba5ea, 0x5fd14fe9 } + }, + { + { -0x406c3472, 0x3c42fe5e, 0x36d4565f, -0x412057af, -0x77bddf18, -0x1f0f7a62, 0x0725d128, 0x7dd73f96 }, + { 0x2845ab2c, -0x4a23d221, 0x0a7fe993, 0x069491b1, 0x4002e346, 0x4daaf3d6, 0x586474d1, 0x093ff26e }, + { 0x68059829, -0x4ef2db02, -0x2450dc1b, 0x75730672, -0x4ba853d7, 0x1367253a, -0x794b8f5c, 0x2f59bcbc } + }, + { + { -0x496e3cff, 0x7041d560, -0x522818e2, -0x7adfe4c1, 0x11335585, 0x16c2e163, 0x010828b1, 0x2aa55e3d }, + { -0x66e8eca1, -0x7c7b82be, 0x567d03d7, -0x52e46ee1, -0x4188552f, 0x7e7748d9, 0x2e51af4a, 0x5458b42e }, + { 0x0c07444f, -0x12ae6d1a, 0x74421d10, 0x42c54e2d, -0x024a379c, 0x352b4c82, -0x7589799c, 0x13e9004a } + }, +}, +{ + { + { -0x7f94b984, 0x1e6284c5, -0x18a29f85, -0x3a096685, -0x4c872d9e, -0x749826a8, -0x7e327490, 0x3d88d66a }, + { 0x6c032bff, -0x344a4aab, 0x29297a3a, -0x208e6e49, -0x52127e45, -0x3e008cda, 0x68be03f5, 0x71ade8bb }, + { 0x204ed789, -0x7489856d, -0x605f51d6, 0x762fcacb, 0x6dce4887, 0x771febcc, -0x700fa04d, 0x34306215 } + }, + { + { 0x2a7b31b4, -0x031de6f9, -0x55a87fea, 0x4d7adc75, -0x78b86cdc, 0x0ec276a6, 0x1fda4beb, 0x6d6d9d5d }, + { -0x1e0a40b7, -0x1fa25e59, -0x2b8c9f6e, 0x26457d6d, 0x73cc32f6, 0x77dcb077, -0x6322a033, 0x0a5d9496 }, + { -0x164f7e7d, 0x22b1a58a, -0x3ea3c775, -0x026a2f8f, -0x7af5fae9, -0x567edc8a, -0x4480cca2, 0x33384cba } + }, + { + { 0x26218b8d, 0x33bc627a, -0x3857f39f, -0x157f4de1, 0x173e9ee6, -0x6ba74ed5, 0x0e2f3059, 0x076247be }, + { 0x0ca2c7b5, 0x3c6fa268, 0x6fb64fda, 0x1b508204, 0x5431d6de, -0x14accb64, 0x6b879c89, 0x5278b38f }, + { 0x1416375a, 0x52e105f6, -0x7a54145c, -0x136850ca, 0x23a67c36, 0x26e6b506, -0x0c2b04ff, 0x5cf0e856 } + }, + { + { 0x3db342a8, -0x415131cf, -0x7bd24812, -0x345c9ca5, -0x7e80ec11, -0x177399e0, 0x4e76d5c6, 0x1b9438aa }, + { 0x1ae8cab4, -0x0936978d, -0x34b06d3b, 0x5e20741e, -0x733243c2, 0x2da53be5, 0x69970df7, 0x2dddfea2 }, + { 0x166f031a, -0x75af8882, 0x0fb7a328, 0x067b39f1, 0x010fbd76, 0x1925c9a6, -0x338bf6fb, 0x6df9b575 } + }, + { + { 0x48cade41, -0x13203ca5, -0x4dcd7d90, 0x6a88471f, 0x40a01b6a, 0x740a4a24, 0x003b5f29, 0x471e5796 }, + { 0x27f6bdcf, 0x42c11929, 0x403d61ca, -0x706e6e86, -0x7461e09f, -0x23e3a59a, 0x04ec0f8d, 0x15960478 }, + { -0x5312c854, -0x2569444d, -0x16df7316, 0x7a2423b5, 0x38aebae2, 0x24cc5c30, -0x23a251d1, 0x50c356af } + }, + { + { 0x1b31b964, -0x30126321, -0x735ae50d, -0x0b79567b, -0x1573e07c, 0x14897265, -0x6cd53400, 0x784a53dd }, + { 0x41c30318, 0x09dcbf43, -0x7ce7e232, -0x1145f9ef, -0x23e1d65f, -0x3e863f32, 0x073f35b0, 0x1dbf7b89 }, + { 0x14fc4920, 0x2d99f9df, -0x3bb6601b, 0x76ccb60c, -0x1a30fffd, -0x5becd345, 0x54f000ea, 0x3f93d823 } + }, + { + { 0x79e14978, -0x1553ed2f, -0x441400a2, -0x006dc00d, 0x0663ce27, 0x4af663e4, 0x11a5f5ff, 0x0fd381a8 }, + { -0x61fb317b, -0x7e7c1898, 0x04465341, 0x678fb71e, 0x6688edac, -0x526dfa71, 0x532b099a, 0x5da350d3 }, + { -0x5bc920ac, -0x0da95314, -0x51962918, 0x108b6168, 0x6b5d036c, 0x20d986cb, -0x011d50b0, 0x655957b9 } + }, + { + { -0x2ffd2f54, -0x423ebf65, -0x4a33265a, 0x66660245, -0x05217a14, -0x7dce823c, 0x6ad7df0d, 0x02fe934b }, + { -0x56fdfcf1, -0x51574f81, -0x0b9c2ebd, -0x07738996, 0x3c787a60, 0x15b08366, -0x7d985b58, 0x08eab114 }, + { -0x3048158c, -0x10a30f00, -0x5e34bd54, 0x22897633, -0x310d7a1e, -0x2b31f3ac, -0x75eb95ab, 0x30408c04 } + }, +}, +{ + { + { 0x193b877f, -0x44d1ff37, -0x1f23af95, -0x131c5770, 0x36de649f, -0x130c4840, -0x672161e6, 0x5f460408 }, + { -0x7cd03125, 0x739d8845, -0x5194079d, -0x05c72937, -0x48b00109, 0x32bc0dca, 0x14bce45e, 0x73937e88 }, + { 0x297bf48d, -0x46fc8eea, -0x2b0f97cc, -0x562ec4de, 0x4696bdc6, -0x1e68eaa9, -0x6e2a17cb, 0x2cf8a4e8 } + }, + { + { 0x17d06ba2, 0x2cb5487e, 0x3950196b, 0x24d2381c, -0x7a6875d0, -0x289a637f, -0x6e295b0a, 0x7a6f7f28 }, + { 0x07110f67, 0x6d93fd87, 0x7c38b549, -0x22b3f62d, -0x3d8c957a, 0x7cb16a4c, 0x58252a09, 0x2049bd6e }, + { 0x6a9aef49, 0x7d09fd8d, 0x5b3db90b, -0x0f119f42, 0x519ebfd4, 0x4c21b52c, -0x3aba6be3, 0x6011aadf } + }, + { + { 0x02cbf890, 0x63ded0c8, 0x0dff6aaa, -0x042f6736, -0x46491267, 0x624d0afd, 0x79340b1e, 0x69ce18b7 }, + { -0x306a07c4, 0x5f67926d, 0x71289071, 0x7c7e8561, -0x667085a5, -0x295e180d, 0x0b62f9e0, 0x6fc5cc1b }, + { -0x4d678635, -0x2e10aad8, -0x2b816f6e, -0x22e551c4, 0x189f2352, 0x127e0442, -0x1a8efe0f, 0x15596b3a } + }, + { + { 0x7e5124ca, 0x09ff3116, -0x2638ba21, 0x0be4158b, 0x7ef556e5, 0x292b7d22, -0x50492ec8, 0x3aa4e241 }, + { 0x3f9179a2, 0x462739d2, -0x68292231, -0x007cedcf, 0x53f2148a, 0x1307deb5, 0x7b5f4dda, 0x0d223768 }, + { 0x2a3305f5, 0x2cc138bf, -0x5d16d93d, 0x48583f8f, 0x5549d2eb, 0x083ab1a2, 0x4687a36c, 0x32fcaa6e } + }, + { + { 0x2787ccdf, 0x3207a473, -0x0dec1c08, 0x17e31908, -0x09f269b2, -0x2a4d1329, -0x3d9ff417, 0x746f6336 }, + { -0x3a82650b, 0x7bc56e8d, -0x620f420e, 0x3e0bd2ed, 0x22efe4a3, -0x553feb22, -0x014295a4, 0x4627e9ce }, + { -0x549368e4, 0x3f4af345, -0x66bc8ce1, -0x1d77148e, 0x0344186d, 0x33596a8a, 0x7ed66293, 0x7b491700 } + }, + { + { -0x22ac5d23, 0x54341b28, -0x20bd03c1, -0x55e86fa5, 0x4dd2f8f4, 0x0ff592d9, -0x1f732c83, 0x1d03620f }, + { -0x547b4f9c, 0x2d85fb5c, -0x760c43ec, 0x497810d2, 0x7b15ce0c, 0x476adc44, -0x07bb0285, 0x122ba376 }, + { -0x5d4b1aac, -0x3dfdcd33, 0x115d187f, -0x612f02be, 0x7dd479d9, 0x2eabb4be, 0x2b68ec4c, 0x02c70bf5 } + }, + { + { 0x458d72e1, -0x531acd41, 0x7cb73cb5, 0x5be768e0, -0x11744219, 0x56cf7d94, -0x014bc5fd, 0x6b0697e3 }, + { 0x5d0b2fbb, -0x5d7813b5, 0x074882ca, 0x415c5790, -0x3e2f7ea4, -0x1fbb59e2, 0x409ef5e0, 0x26334f0a }, + { -0x209d5c40, -0x49370fb6, 0x076da45d, 0x3ef000ef, 0x49f0d2a9, -0x636346a8, 0x441b2fae, 0x1cc37f43 } + }, + { + { -0x36315147, -0x2899a90f, 0x18e5656a, 0x1c5b15f8, -0x7bb3dccc, 0x26e72832, 0x2f196838, 0x3a346f77 }, + { 0x5cc7324f, 0x508f565a, -0x1af956de, -0x2f9e3b40, 0x5c45ac19, -0x04e75425, 0x0380314a, 0x6c6809c1 }, + { -0x1d259538, -0x2d2aaeee, -0x4e17ae13, -0x1642fccf, -0x71398d9e, -0x69f8b923, 0x6ef7c5d0, 0x05911b9f } + }, +}, +{ + { + { -0x3a01606c, 0x01c18980, 0x716fd5c8, -0x329a9897, -0x2e6a5f7a, -0x7e9fba3d, 0x66cc7982, 0x6e2b7f32 }, + { -0x49c800d3, -0x162328aa, -0x36780f3c, -0x13b3cb71, -0x0c043849, -0x312a6d7b, -0x6c1e1579, 0x33053547 }, + { -0x083ca971, -0x337fdb98, 0x19974cb3, -0x6216457e, -0x4a47eca0, -0x5448dd64, 0x6fbeba62, 0x44e2017a } + }, + { + { -0x49359133, -0x7807d30d, 0x18f4a0c2, 0x580f893e, 0x2604e557, 0x05893007, 0x56d19c1d, 0x6cab6ac2 }, + { 0x54dab774, -0x3b3d58bd, 0x4eaf031a, -0x71a2b3c4, 0x42838f17, -0x4893dc2e, 0x68dce4ea, 0x749a098f }, + { 0x2cc1de60, -0x23201f60, 0x51c5575b, 0x032665ff, 0x073abeeb, 0x2c0c32f1, -0x328479fa, 0x6a882014 } + }, + { + { -0x50b01492, -0x2eee2e84, -0x4cc55b5d, 0x050bba42, -0x114b93d0, 0x17514c3c, 0x1bc27d75, 0x54bedb8b }, + { -0x5b8b804b, -0x5ad56d02, 0x1fa5ab89, -0x23ed5bb7, -0x47b85b32, -0x27d256b5, -0x6aed33b2, 0x4d77edce }, + { 0x77e2189c, 0x77c8e145, -0x00663bbb, -0x5c1b9096, 0x6d335343, 0x3144dfc8, 0x7c4216a9, 0x3a96559e } + }, + { + { -0x7f4555ae, 0x44938968, -0x0d7a6bf2, 0x4c98afc4, -0x5babb74a, -0x10b55865, -0x5a855181, 0x5278c510 }, + { -0x0bd52d12, 0x12550d37, -0x675e040b, -0x74871ffc, 0x33894cb2, 0x5d530782, 0x3e498d0c, 0x02c84e4e }, + { 0x294c0b94, -0x5ab22f8c, -0x20e7004a, -0x0aa2b948, -0x72517c9a, -0x0f90133b, -0x7e6f2e9b, 0x58865766 } + }, + { + { 0x3de25cc3, -0x40a7cb10, -0x297eab6a, -0x47783752, -0x6b7e176e, 0x5105221a, -0x088dc06d, 0x6760ed19 }, + { 0x1aef7117, -0x2b88edcf, 0x229e92c7, 0x50343101, -0x62ea6469, 0x7a95e184, -0x74a2d637, 0x2449959b }, + { -0x53ca1ea0, 0x669ba3b7, -0x457bdfaa, 0x2eccf73f, -0x3f7fb0f9, 0x1aec1f17, 0x1856f4e7, 0x0d96bc03 } + }, + { + { -0x338afa1f, -0x4e2acb50, 0x16c35288, 0x32cd0034, 0x0762c29d, -0x34c95a80, 0x237a0bf8, 0x5bfe69b9 }, + { 0x75c52d82, 0x3318be77, 0x54d0aab9, 0x4cb764b5, -0x3388c26f, -0x5430c2d9, -0x7edcd776, 0x3bf4d184 }, + { 0x78a151ab, 0x183eab7e, -0x66f6c89d, -0x44166f37, 0x4ac7e335, -0x008e8292, 0x25f39f88, 0x4c5cddb3 } + }, + { + { -0x185606fe, 0x57750967, 0x4f5b467e, 0x2c37fdfc, 0x3177ba46, -0x4d9e99c6, -0x23d2acd5, 0x3a375e78 }, + { 0x6190a6eb, -0x3f0948b3, 0x2db8f4e4, 0x20ea81a4, -0x68cea8a0, -0x57429083, 0x62ac7c21, 0x33b1d602 }, + { 0x2d4dddea, -0x7ebe18d1, 0x62c607c8, -0x19150168, 0x573cafd0, 0x23c28458, 0x4ff97346, 0x46b9476f } + }, + { + { 0x0d58359f, 0x1215505c, -0x03d73b95, 0x2a2013c7, -0x761599b2, 0x24a0a1af, -0x5eecf1e1, 0x4400b638 }, + { 0x4f901e5c, 0x0c1ffea4, 0x2184b782, 0x2b0b6fb7, 0x0114db88, -0x1a78006f, 0x4785a142, 0x37130f36 }, + { -0x6912e63d, 0x3a01b764, -0x12cd8dd0, 0x31e00ab0, -0x7c35ea4f, 0x520a8857, 0x5accbec7, 0x06aab987 } + }, +}, +{ + { + { 0x512eeaef, 0x5349acf3, 0x1cc1cb49, 0x20c141d3, -0x56659773, 0x24180c07, -0x39b4d2e9, 0x555ef9d1 }, + { -0x0a20f145, -0x3ecc667d, 0x512c4cac, -0x3f0c8a71, 0x0bb398e1, 0x2cf1130a, -0x55d8f39e, 0x6b3cecf9 }, + { 0x3b73bd08, 0x36a770ba, -0x5c5040f4, 0x624aef08, -0x4bf6b90e, 0x5737ff98, 0x3381749d, 0x675f4de1 } + }, + { + { 0x3bdab31d, -0x5ed00927, -0x629ad202, 0x0725d80f, -0x65416b79, 0x019c4ff3, -0x7d32c3bd, 0x60f450b8 }, + { 0x6b1782fc, 0x0e2c5203, 0x6cad83b4, 0x64816c81, 0x6964073e, -0x2f234227, 0x0164c520, 0x13d99df7 }, + { 0x21e5c0ca, 0x014b5ec3, -0x28e6405e, 0x4fcb69c9, 0x750023a0, 0x4e5f1c18, 0x55edac80, 0x1c06de9e } + }, + { + { -0x00929656, -0x002ad4c0, -0x23bfb645, 0x34530b18, -0x5cb26769, 0x5e4a5c2f, 0x7d32ba2d, 0x78096f8e }, + { -0x5cc13b1e, -0x66f0852a, -0x41d11f72, 0x6608f938, 0x63284515, -0x635ebc3b, -0x13d249f3, 0x4cf38a1f }, + { 0x0dfa5ce7, -0x5f55559b, 0x48b5478c, -0x063b61d6, 0x7003725b, 0x4f09cc7d, 0x26091abe, 0x373cad3a } + }, + { + { -0x76224453, -0x0e415705, 0x61aeaecb, 0x3bcb2cbc, 0x1f9b8d9d, -0x70a75845, 0x5112a686, 0x21547eda }, + { -0x7d360a84, -0x4d6b9cb3, 0x24934536, 0x1fcbfde1, 0x418cdb5a, -0x6163b24d, 0x454419fc, 0x0040f3d9 }, + { -0x02a6792d, -0x210216c7, 0x510a380c, -0x0bd8d377, -0x44cee647, -0x48d45bf9, 0x4a254df4, 0x63550a33 } + }, + { + { 0x72547b49, -0x6445a7bb, -0x1d3bf720, -0x0cfa3906, -0x38cb0e73, 0x60e8fa69, -0x55828986, 0x39a92baf }, + { -0x4a9630c9, 0x6507d6ed, 0x0ca52ee1, 0x178429b0, -0x149429a3, -0x1583ff70, -0x250870af, 0x3eea62c7 }, + { -0x196cd8b2, -0x62db38ed, 0x68dbd375, 0x5f638577, -0x14754c66, 0x70525560, 0x65c9c4cd, 0x68436a06 } + }, + { + { -0x17dfef84, 0x1e56d317, -0x7bf5169b, -0x3ad997bc, 0x320ffc7a, -0x3e1f5e3a, -0x6e9eeb8e, 0x5373669c }, + { 0x202f3f27, -0x43fdca18, 0x64f975b0, -0x38a3ff1e, -0x5c73dbea, -0x6e5b162b, -0x75487607, 0x17b6e7f6 }, + { -0x65f1ada9, 0x5d2814ab, -0x36354c04, -0x6f70df7c, 0x5b2d1eca, -0x50350a78, 0x78f87d11, 0x1cb4b5a6 } + }, + { + { -0x5d5ff819, 0x6b74aa62, -0x0f8e384f, -0x0cee1f50, 0x000be223, 0x5707e438, -0x7d109154, 0x2dc0fd2d }, + { 0x394afc6c, -0x499b3f95, -0x6725a04f, 0x0c88de24, 0x4bcad834, 0x4f8d0316, -0x218bcb5e, 0x330bca78 }, + { 0x1119744e, -0x67d1007c, 0x2b074724, -0x0696a16a, -0x4036ac05, -0x3a753eb1, 0x369f1cf5, 0x3c31be1b } + }, + { + { -0x0634bd8e, -0x3e97436d, -0x38312468, -0x51478ee1, 0x34ac8d7a, 0x7f0e52aa, 0x7e7d55bb, 0x41cec109 }, + { 0x08948aee, -0x4f0b79b3, -0x6e45e391, 0x07dc19ee, -0x59535ea8, 0x7975cdae, 0x4262d4bb, 0x330b6113 }, + { -0x5d927f76, -0x0869e629, 0x1d9e156d, -0x44e02b62, -0x245e20d9, 0x73d7c36c, 0x1f28777d, 0x26b44cd9 } + }, +}, +{ + { + { -0x4fd7a0c9, -0x50bb7bd3, 0x47efc8df, -0x78ace770, -0x07df6866, -0x6a8b1f6f, 0x69615579, 0x0e378d60 }, + { 0x393aa6d8, 0x300a9035, -0x5ed44e33, 0x2b501131, -0x0f6c3dde, 0x7b1ff677, -0x3547d453, 0x4309c1f8 }, + { -0x7cf8a5ab, -0x26056e8f, 0x6b009fdc, 0x4bdb5ad2, -0x29c210f2, 0x7829ad2c, 0x75fd3877, 0x078fc549 } + }, + { + { -0x47cc5676, -0x1dffb4a5, 0x2d4c3330, 0x44775dec, 0x7eace913, 0x3aa24406, -0x2a71ff57, 0x272630e3 }, + { 0x28878f2d, -0x782042ec, 0x1e9421a1, 0x134636dd, 0x257341a3, 0x4f17c951, -0x52d69348, 0x5df98d4b }, + { -0x1336f4ac, -0x0c987030, 0x12043599, -0x0ffeba65, 0x3758b89b, 0x26725fbc, 0x73a719ae, 0x4325e4aa } + }, + { + { -0x30960a63, -0x12db9d66, -0x22a5440c, 0x2a4a1cce, 0x56b2d67b, 0x3535ca1f, 0x43b1b42d, 0x5d8c68d0 }, + { 0x433c3493, 0x657dc6ef, -0x7f24073d, 0x65375e9f, 0x5b372dae, 0x47fd2d46, 0x796e7947, 0x4966ab79 }, + { -0x1c4bd4f6, -0x11ccd2b3, 0x16a4601c, -0x27b1a5d5, 0x078ba3e4, 0x78243877, 0x184ee437, 0x77ed1eb4 } + }, + { + { -0x616d12e6, 0x185d43f8, -0x01b8e63a, -0x4fb5e116, -0x590fc0b1, 0x499fbe88, 0x3c859bdd, 0x5d8b0d2f }, + { 0x201839a0, -0x402b1ec1, 0x3e3df161, -0x5110001e, 0x6b5d1fe3, -0x49a4fb10, 0x2b62fbc0, 0x52e085fb }, + { -0x5ab30d46, 0x124079ea, 0x001b26e7, -0x28db9a15, -0x36850803, 0x6843bcfd, 0x55eacd02, 0x0524b42b } + }, + { + { -0x647d6154, -0x43e72353, -0x4a0a8630, 0x23ae7d28, 0x69384233, -0x3cb9edd6, -0x182b5377, 0x1a6110b2 }, + { -0x1babb850, -0x02f2a242, 0x092005ee, 0x6cec351a, 0x567579cb, -0x665b87bc, 0x16e7fa45, 0x59d242a2 }, + { -0x19966854, 0x4f833f6a, 0x361839a4, 0x6849762a, -0x68f54adb, 0x6985dec1, -0x234e0aba, 0x53045e89 } + }, + { + { -0x72ba01ee, -0x7b25c322, -0x1bbb1d2e, -0x42bd3de8, 0x1f7e3598, -0x57ae6988, 0x5616e2b2, 0x7642c93f }, + { -0x28acac25, -0x34744cba, -0x51aee1de, -0x03034db5, -0x2af51911, -0x345b72c0, -0x0b0834a3, 0x26e3bae5 }, + { 0x4595f8e4, 0x2323daa7, -0x7a85414c, -0x21977375, 0x1c59326e, 0x3fc48e96, 0x15c9b8ba, 0x0b2e73ca } + }, + { + { 0x79c03a55, 0x0e3fbfaf, 0x4cbb5acf, 0x3077af05, -0x24c21c61, -0x2a3aadbb, 0x476a4af7, 0x015e68c1 }, + { -0x3e80afda, -0x2944bbd8, -0x04a56359, -0x614d8ddd, 0x1919c644, -0x1c845afd, -0x4a6599fe, 0x21ce380d }, + { 0x20066a38, -0x3e2ad7ae, 0x3570aef3, -0x6a9fc1ae, 0x226b8a4d, -0x7cd9a659, 0x1f8eedc9, 0x5dd68909 } + }, + { + { -0x5acecf7c, 0x1d022591, -0x29d8f78e, -0x35d2b552, 0x2f0bfd20, -0x795ed47b, -0x528258b8, 0x56e6c439 }, + { -0x402c37aa, -0x34537b22, -0x4ca00dbc, 0x1624c348, 0x5d9cad07, -0x48077236, -0x5d3d1418, 0x3b0e574d }, + { 0x42bdbae6, -0x38fb00b7, -0x4d21e087, 0x5e21ade2, 0x5652fad8, -0x16a24c0d, -0x70f7143f, 0x0822b537 } + }, +}, +{ + { + { 0x62730383, -0x1e480d6d, -0x143575d4, 0x4b5279ff, -0x402becec, -0x25038876, -0x638d9ef1, 0x7deb1014 }, + { -0x70c78b8b, 0x51f04847, -0x634134c4, -0x4da2430c, -0x2660dfab, -0x6554edbc, 0x1c10a5d6, 0x2c709e6c }, + { -0x78991186, -0x349d5096, 0x5553cd0e, 0x66cbec04, 0x0f0be4b5, 0x58800138, -0x09d31d16, 0x08e68e9f } + }, + { + { 0x0ab8f2f9, 0x2f2d09d5, -0x3aa6dc21, -0x5346de73, 0x73766cb9, 0x4a8f3426, 0x38f719f5, 0x4cb13bd7 }, + { 0x4bc130ad, 0x34ad500a, 0x3d0bd49c, -0x72c724b7, 0x500a89be, -0x5da3c268, -0x1145c4f7, 0x2f1f3f87 }, + { -0x1aea49b6, -0x087b738b, -0x24b56fc8, -0x5a6afe46, 0x3f751b50, -0x3df2cec1, -0x3f51d118, 0x19a1e353 } + }, + { + { -0x2a694243, -0x4bde8d33, -0x671103c0, -0x6c1fbabd, -0x4bbef64b, -0x604eacb9, 0x0266ae34, 0x736bd399 }, + { -0x4505fa3d, 0x7d1c7560, -0x391aa19f, -0x4c1e5f60, -0x3f299b8d, -0x1cad68e8, -0x3df3cb7a, 0x41546b11 }, + { -0x6ccb4c4c, -0x7aacd2b0, 0x60816573, 0x46fd114b, 0x425c8375, -0x33a0a0d0, -0x478054a4, 0x412295a2 } + }, + { + { -0x1d6c153a, 0x2e655261, 0x2133acdb, -0x7ba56dfd, 0x7900996b, 0x460975cb, 0x195add80, 0x0760bb8d }, + { -0x0a812917, 0x19c99b88, 0x6df8c825, 0x5393cb26, -0x4cf52d8d, 0x5cee3213, -0x4ad2d1cc, 0x14e153eb }, + { -0x32197e76, 0x413e1a17, -0x12965f7c, 0x57156da9, 0x46caccb1, 0x2cbf268f, -0x3cc53a0e, 0x6b34be9b } + }, + { + { 0x6571f2d3, 0x11fc6965, 0x530e737a, -0x393617bb, -0x2b01afcb, -0x1cc5185e, 0x2e6dd30b, 0x01b9c7b6 }, + { 0x3a78c0b2, -0x0c20d09c, -0x0dd1fd84, 0x4c3e971e, 0x49c1b5a3, -0x1382e3a2, 0x0922dd2d, 0x2012c18f }, + { 0x5ac89d29, -0x77f4aa1b, 0x45a0a763, 0x1483241f, -0x3d1893e1, 0x3d36efdf, 0x4e4bade8, 0x08af5b78 } + }, + { + { -0x7633d3b5, -0x1d8ceb2e, -0x5d78e873, 0x4be4bd11, -0x05cc9b32, 0x18d528d6, -0x50267d92, 0x6423c1d5 }, + { -0x77e0dacd, 0x283499dc, 0x779323b6, -0x62fada26, 0x673441f4, -0x76852205, 0x163a168d, 0x32b79d71 }, + { -0x12034c96, -0x337a0727, 0x3746e5f9, 0x22bcc28f, -0x061a2c33, -0x1b621cc8, -0x3ec1d234, 0x480a5efb } + }, + { + { 0x42ce221f, -0x499eb31c, 0x4c053928, 0x6e199dcc, -0x23e341fd, 0x663fb4a4, 0x691c8e06, 0x24b31d47 }, + { 0x01622071, 0x0b51e70b, -0x74e2503b, 0x06b505cf, -0x10a55433, 0x2c6bb061, 0x0cb7bf31, 0x47aa2760 }, + { -0x3fea073d, 0x2a541eed, 0x7c693f7c, 0x11a4fe7e, 0x4ea278d6, -0x0f5099ed, 0x14dda094, 0x545b585d } + }, + { + { -0x1c4cde1f, 0x6204e4d0, 0x28ff1e95, 0x3baa637a, 0x5b99bd9e, 0x0b0ccffd, 0x64c8d071, 0x4d22dc3e }, + { -0x5f2bc5f1, 0x67bf275e, 0x089beebe, -0x521971cc, -0x2b8618d2, 0x4289134c, 0x32ba5454, 0x0f62f9c3 }, + { -0x29c4a0c7, -0x034b9a77, 0x57cbcf61, 0x5cae6a3f, -0x6ac505fb, -0x01453d2e, 0x36371436, 0x1c0fa01a } + }, +}, +{ + { + { 0x54c53fae, -0x3ee11a18, 0x2b4f3ff4, 0x6a0b06c1, -0x1f49858e, 0x33540f80, -0x32f81c11, 0x15f18fc3 }, + { -0x4383296e, -0x18ab8bb7, -0x1908c221, 0x0f9abeaa, 0x00837e29, 0x4af01ca7, 0x3f1bc183, 0x63ab1b5d }, + { -0x4fd70b74, 0x32750763, 0x556a065f, 0x06020740, -0x3cb6a4a8, -0x2ac427ee, -0x79a0af73, 0x08706c9b } + }, + { + { 0x38b41246, -0x3366e4bf, 0x6f9ac26b, 0x243b9c52, -0x48345443, -0x4610b6b3, -0x2f7d1300, 0x5fba433d }, + { 0x3d343dff, -0x0c835d55, -0x7f5439e9, 0x1a8c6a2d, -0x2b330036, -0x71b61fcb, -0x455e2e47, 0x48b46bee }, + { -0x366be530, -0x63b61cab, 0x74498f84, -0x468cb522, 0x66663e5c, 0x41c3fed0, -0x1718ef4d, 0x0ecfedf8 } + }, + { + { -0x16bfc89e, 0x744f7463, -0x72033637, -0x08657212, 0x55e4cde3, 0x163a6496, -0x4d7b0bcb, 0x3b61788d }, + { -0x632b8f27, 0x76430f9f, -0x5bd09ff8, -0x49d53365, 0x59adad5e, 0x1898297c, -0x4873af80, 0x7789dd2d }, + { 0x0d6ef6b2, -0x4dddd7e7, 0x46ce4bfa, -0x56b5994e, 0x4f0b6cc7, 0x46c1a77a, -0x148cc731, 0x4236ccff } + }, + { + { -0x2588820a, 0x3bd82dbf, 0x0b98369e, 0x71b177cc, -0x7af3c967, 0x1d0e8463, 0x48e2d1f1, 0x5a71945b }, + { 0x0d55e274, -0x7b68bfb3, -0x3b52d4ad, 0x6c6663d9, -0x5256a8cc, -0x13d04f27, -0x324708c4, 0x2617e120 }, + { 0x405b4b42, 0x6f203dd5, 0x10b24509, 0x327ec604, -0x53d577ba, -0x63cb8dd0, 0x11ffeb6a, 0x77de29fc } + }, + { + { -0x13312d36, -0x7ca1ec71, -0x1569c466, -0x736150ed, -0x4de9f15a, -0x36a04040, -0x5278876e, 0x575e66f3 }, + { -0x7c488758, -0x4f53a837, -0x28016ed4, 0x53cdcca9, -0x00e0a624, 0x61c2b854, -0x0f218254, 0x3a1a2cf0 }, + { -0x377034c6, -0x667fc5d9, 0x275ec0b0, 0x345a6789, -0x0093d41b, 0x459789d0, 0x1e70a8b2, 0x62f88265 } + }, + { + { 0x698a19e0, 0x6d822986, 0x74d78a71, -0x2367de1f, -0x0934e0b9, 0x41a85f31, -0x432563af, 0x352721c2 }, + { 0x59ff1be4, 0x085ae2c7, 0x3b0e40b7, 0x149145c9, 0x7ff27379, -0x3b981806, -0x2a38c56b, 0x4eeecf0a }, + { 0x213fc985, 0x48329952, 0x368a1746, 0x1087cf0d, 0x66c15aa5, -0x71ad9e4f, 0x2ed24c21, 0x2d5b2d84 } + }, + { + { 0x196ac533, 0x5eb7d13d, -0x247f41d5, 0x377234ec, 0x7cf5ae24, -0x1ebb3004, -0x3bbe5314, 0x5226bcf9 }, + { -0x142c212f, 0x02cfebd9, 0x39021974, -0x2ba4de89, -0x01cf5e49, 0x7576f813, -0x5cb1093e, 0x5691b6f9 }, + { 0x23e5b547, 0x79ee6c72, -0x7ccf2987, 0x6f5f5076, 0x6d8adce9, -0x128c1e17, 0x1d8ccc03, 0x27c3da1e } + }, + { + { 0x630ef9f6, 0x28302e71, 0x2b64cee0, -0x3d2b5dfd, 0x4b6292be, 0x09082030, -0x57d520e8, 0x5fca747a }, + { 0x3fe24c74, 0x7eb9efb2, 0x1651be01, 0x3e50f49f, 0x21858dea, 0x3ea732dc, 0x5bb810f9, 0x17377bd7 }, + { 0x5c258ea5, 0x232a03c3, 0x6bcb0cf1, -0x790dc5d4, 0x2e442166, 0x3dad8d0d, -0x548979d5, 0x04a8933c } + }, +}, +{ + { + { -0x736c95b0, 0x69082b0e, -0x3e253a4a, -0x06365fcb, -0x3b2049cc, 0x6fb73e54, 0x1d2bc140, 0x4005419b }, + { 0x22943dff, -0x2d39fb4a, 0x44cfb3a0, -0x43734132, -0x687f7988, 0x5d254ff3, 0x3b1ca6bf, 0x0fa3614f }, + { -0x46417d10, -0x5ffc0143, 0x3a44ac90, 0x2089c1af, 0x1954fa8e, -0x07b6606f, -0x10bf54be, 0x1fba218a } + }, + { + { 0x3e7b0194, 0x4f3e5704, 0x08daaf7f, -0x57e2c112, -0x6623210f, -0x37c63955, -0x00889e2b, 0x6c535d13 }, + { -0x05370ac2, -0x54ab6bb8, 0x7ba63741, -0x7e091766, 0x6c2b5e01, 0x74fd6c7d, -0x573791be, 0x392e3aca }, + { 0x3e8a35af, 0x4cbd34e9, 0x5887e816, 0x2e078144, -0x0d654f55, 0x19319c76, -0x2af53ec5, 0x25e17fe4 } + }, + { + { 0x76f121a7, -0x6ea0800b, 0x2fcd87e3, -0x3cb5cdd9, 0x4d1be526, -0x3345d022, -0x76967665, 0x6bba828f }, + { 0x1e04f676, 0x0a289bd7, -0x29bdf06b, 0x208e1c52, 0x34691fab, 0x5186d8b0, 0x2a9fb351, 0x25575144 }, + { -0x6f01c6ff, -0x1d2e439a, -0x5f66852b, 0x4cb54a18, -0x507b9f2c, -0x68e296ec, 0x7f6b7be4, 0x559d504f } + }, + { + { -0x092d9903, -0x63b76e19, 0x0307781b, 0x0744a19b, 0x6061e23b, -0x77c770e3, 0x354bd50e, 0x123ea6a3 }, + { -0x4c14ab2b, -0x588c7c88, -0x5aaac384, 0x1d69d366, -0x06d7ff46, 0x0a26cf62, -0x7f81cde9, 0x01ab12d5 }, + { 0x41e32d96, 0x118d1890, -0x27cea7b8, -0x46121c3e, -0x27cdba27, 0x1eab4271, -0x36e75eac, 0x4a3961e2 } + }, + { + { -0x0cdcc0e2, 0x0327d644, 0x34fcf016, 0x499a260e, -0x0d254687, -0x7c4a58ea, -0x642beee1, 0x68aceead }, + { -0x07194460, 0x71dc3be0, 0x7effe30a, -0x293107cc, -0x1ec5b896, -0x566dbda1, -0x04e2489d, 0x2cd6bce3 }, + { -0x0c283df0, 0x38b4c90e, -0x4852fbf4, 0x308e6e24, -0x4818c1dd, 0x3860d9f1, -0x4af70a69, 0x595760d5 } + }, + { + { -0x02fdd870, -0x77d53415, -0x3beea8a0, -0x7650ccfb, 0x7d3473f4, 0x65f492e3, 0x54515a2b, 0x2cb2c5df }, + { 0x04aa6397, 0x6129bfe1, -0x5b580335, -0x7069fff8, 0x7d909458, 0x3f8bc089, -0x234d6e57, 0x709fa43e }, + { 0x63fd2aca, -0x14f5a274, 0x2e694eff, -0x2dd43e9a, -0x07344fc6, 0x2723f36e, -0x0f37ece1, 0x70f029ec } + }, + { + { 0x5e10b0b9, 0x2a6aafaa, -0x10fbe557, 0x78f0a370, -0x55c529e1, 0x773efb77, -0x58b4261f, 0x44eca5a2 }, + { 0x2eed3e33, 0x461307b3, -0x5baa7e19, -0x51fbd0cd, 0x195f0366, -0x36bbb62d, 0x6c314858, 0x0b7d5d8a }, + { 0x7b95d543, 0x25d44832, -0x5ccbf0e3, 0x70d38300, 0x60e1c52b, -0x21e3ace4, 0x2c7de9e4, 0x27222451 } + }, + { + { 0x42a975fc, -0x40844476, -0x69525ca8, -0x73a3c689, -0x321255b8, -0x1d803891, -0x0943df5a, 0x19735fd7 }, + { 0x49c5342e, 0x1abc92af, -0x4d190530, -0x001127ef, -0x0337b1d7, -0x105d7373, -0x5bb33abd, 0x11b5df18 }, + { 0x42c84266, -0x1c546f30, 0x7f19547e, -0x147b71f1, 0x65a497b9, 0x2503a1d0, -0x6e2076a1, 0x0fef9111 } + }, +}, +{ + { + { 0x5b1c16b7, 0x6ab5dcb8, 0x3c7b27a5, -0x6b3f0318, 0x735517be, -0x5b4ee3e6, -0x45f15056, 0x499238d0 }, + { -0x54e39147, -0x4eaf835f, 0x16b687b3, -0x42bb70c2, 0x2c7a91ab, 0x3455fb7f, 0x2f2adec1, 0x7579229e }, + { 0x7aba8b57, -0x130b91ae, -0x742e9b85, 0x15a08c47, 0x5f706fef, 0x7af1c6a6, -0x0fc5cf2b, 0x6345fa78 } + }, + { + { -0x42270f5c, -0x6c2c3417, -0x02e88cfe, -0x24ead3e5, 0x7f17a875, 0x7dbddc6d, -0x70bd9102, 0x3e1a71cc }, + { 0x1015e7a1, -0x20fd06a1, -0x564bfd9d, 0x790ec41d, 0x33ea1107, 0x4d3a0ea1, -0x1cc50737, 0x54f70be7 }, + { -0x6f45429e, -0x37c35c1d, 0x0291c833, -0x7f121c99, -0x2c86ff3c, -0x377fc734, 0x1ec31fa1, 0x2c5fc023 } + }, + { + { 0x02456e65, -0x3bdd1b2f, -0x352b846f, -0x78beb53f, -0x5d490023, 0x1592e2bb, -0x0a3deff1, 0x75d9d2bf }, + { 0x17038b4f, -0x01456ee9, -0x3621107f, -0x1aedc8df, 0x5d0d8834, 0x1c97e4e7, 0x23dc3bc6, 0x68afae7a }, + { 0x3626e81c, 0x5bd9b476, -0x435fd123, -0x766996ca, 0x61f077b3, 0x0a41193d, 0x00ce5471, 0x3097a242 } + }, + { + { 0x6695c486, -0x5e9d18dc, 0x35a89607, 0x131d6334, -0x5f2ed5c9, 0x30521561, -0x59504c9d, 0x56704bad }, + { -0x380747b4, 0x57427734, 0x01b270e9, -0x0ebe5ec2, -0x4b1a9b5a, 0x02d1adfe, -0x317c42b8, 0x4bb23d92 }, + { 0x52f912b9, -0x5093b559, -0x27988f38, 0x5e665f6c, -0x5c3732a8, 0x4c35ac83, 0x10a58a7e, 0x2b7a29c0 } + }, + { + { -0x40fff792, 0x33810a23, -0x18c90084, -0x50316da2, -0x1db6dd2c, 0x3d60e670, 0x4f96061b, 0x11ce9e71 }, + { -0x2f3e313d, -0x3bff8089, -0x453b6d08, -0x72efdf4a, 0x7e69daaf, 0x32ec29d5, -0x626a0320, 0x59940875 }, + { -0x27ea453f, 0x219ef713, 0x485be25c, -0x0ebeb9a3, 0x4e513c51, 0x6d5447cc, 0x5ef44393, 0x174926be } + }, + { + { -0x6c15fdd2, 0x3ef5d415, 0x0ed0eed6, 0x5cbcc1a2, 0x07382c8c, -0x702db131, 0x06d8e1ad, 0x6fa42ead }, + { -0x03a42a45, -0x4a214d07, -0x1e27ef1f, -0x6d2558d6, -0x48d5e3a7, -0x503b3024, 0x3fc22a24, 0x497d7881 }, + { 0x1f73371f, -0x1d897db6, 0x4f5b6736, 0x7f7cf01c, 0x04fa46e7, 0x7e201fe3, 0x57808c96, 0x785a36a3 } + }, + { + { 0x5d517bc3, 0x07044298, -0x519ac988, 0x6acd56c7, -0x67a5889d, 0x00a27983, -0x1aed99d5, 0x5167effa }, + { 0x63014d2b, -0x7da04203, 0x6ca7578b, -0x37adc964, 0x5c0b5df0, 0x5b2fcd28, 0x58048c8f, 0x12ab214c }, + { 0x0f53c4b6, -0x42b1561f, -0x7536e5ec, 0x1673dc5f, 0x2acc1aba, -0x5707e5b2, 0x24332a25, 0x33a92a79 } + }, + { + { 0x218f2ada, 0x7ba95ba0, 0x330fb9ca, -0x300bdd79, 0x56c6d907, -0x2525b693, -0x0b4111ac, 0x5380c296 }, + { 0x27996c02, -0x622e0b67, -0x1fb2e8ae, 0x0cb3b058, 0x7fd02c3e, 0x1f7e8896, -0x3474c14f, 0x2f964268 }, + { 0x66898d0a, -0x62b0d8fc, 0x0aff3f7a, 0x3d098799, 0x67daba45, -0x2f610c9e, 0x7b1c669c, 0x7761455e } + }, +}, +}; +#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 ge_precomp base[32][8] = { +static const ge_precomp base[32][8] = { { { { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 }, @@ -2109,30 +9090,33 @@ static ge_precomp base[32][8] = { }, }, } ; +#endif static void ge_select(ge_precomp *t,int pos,signed char b) { +#ifndef CURVED25519_ASM 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 } - /* h = a * B where a = a[0]+256*a[1]+...+256^31 a[31] @@ -2146,7 +9130,9 @@ void ge_scalarmult_base(ge_p3 *h,const unsigned char *a) signed char e[64]; signed char carry; ge_p1p1 r; +#ifndef CURVED25519_ASM ge_p2 s; +#endif ge_precomp t; int i; @@ -2167,8 +9153,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_ASM + 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); } @@ -2182,6 +9177,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 } @@ -2217,8 +9224,137 @@ static void slide(signed char *r,const unsigned char *a) } } - -static ge_precomp Bi[8] = { +#ifdef CURVED25519_ASM_64BIT +static const ge_precomp Bi[8] = { + { + { 0x2fbc93c6f58c3b85, -0x306cd2390473f1e7, 0x270b4898643d42c2, 0x07cf9d3a33d4ba65, }, + { -0x62efc6fa28bf6ec2, -0x02c660fa2ebf414d, -0x5a3e7bcb977075f7, 0x44fd2f9298f81267, }, + { -0x5436edfa78855598, 0x26d9e823ccaac49e, 0x5a1b7dcbdd43598c, 0x6f117b689f0c65a8, }, + }, + { + { -0x50da4f57b31168d0, 0x025a8430e8864b8a, -0x3ee4affd60fe98ce, 0x7a164e1b9a80f8f4, }, + { 0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, -0x7ece0ce5deb42943, 0x2ab91587555bda62, }, + { 0x14ae933f0dd0d889, 0x589423221c35da62, -0x2e8f1aba730d24b4, 0x5a2826af12b9b4c6, }, + }, + { + { -0x5ded43bbf75a44cd, -0x72afb73c38a112fe, -0x22e414f3a54013bc, 0x2945ccf146e206eb, }, + { 0x7f9182c3a447d6ba, -0x2affeb2eb4d8d649, -0x1cc30ee3479b5f79, 0x154a7e73eb1b55f3, }, + { -0x4344240e7ed57d7b, 0x270e0807d0bdd1fc, -0x4be498f4e44258d3, 0x43aabe696b3bb69a, }, + }, + { + { 0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e, }, + { -0x4590d36555cdde4f, 0x6ca021533bba23a7, -0x621589b06de6d3c6, 0x1d6edd5d2e5317e0, }, + { -0x0e7c9237fe474c5e, -0x4cfca0b8fac15b66, 0x529c41ba5877adf3, 0x7a9fbb1c6a0f90a7, }, + }, + { + { -0x64d1987559579cd1, -0x59af6190ae43b93b, -0x314dcc3639790a4b, 0x34b9ed338add7f59, }, + { -0x0c91de81fc627f9c, -0x675f7e490adfbe65, -0x693439f718a14fbc, 0x49c05a51fadc9c8f, }, + { 0x06b4e8bf9045af1b, -0x1d007c1758e62dd1, -0x550903d66c2b30ea, 0x73c172021b008b06, }, + }, + { + { 0x2fbf00848a802ade, -0x1a260130fdcfd1d9, 0x113e847117703406, 0x4275aae2546d8faf, }, + { 0x315f5b0249864348, 0x3ed6b36977088381, -0x5c5f8aaa9572146b, 0x18ab598029d5c77f, }, + { -0x27d4d33a029f7617, 0x031eb4a13282e4a4, 0x44311199b51a8622, 0x3dc65522b53df948, }, + }, + { + { -0x408f3ddd5dff8093, -0x407b4c654a432125, 0x537a0e12fb07ba07, 0x234fd7eec346f241, }, + { 0x506f013b327fbf93, -0x5103143664889095, -0x62ed4dcd5552a698, 0x0267882d176024a7, }, + { 0x5360a119732ea378, 0x2437e6b1df8dd471, -0x5d10c8076e581acd, 0x497ba6fdaa097863, }, + }, + { + { 0x24cecc0313cfeaa0, -0x79b73d72e763db93, 0x2dbdbdfac1f2d4d0, 0x61e22917f12de72b, }, + { 0x040bcd86468ccf0b, -0x2c7d645bd566ef2a, 0x7508300807b25192, 0x43b5cd4218d05ebf, }, + { 0x5d9a762f9bd0b516, -0x14c750b1c8c02112, 0x032e5a7d93d64270, 0x511d61210ae4d842, }, + }, +}; +#elif defined(CURVED25519_ASM_32BIT) +static const ge_precomp Bi[8] = { + { + { -0x0a73c47b, 0x2fbc93c6, -0x0473f1e7, -0x306cd23a, 0x643d42c2, 0x270b4898, 0x33d4ba65, 0x07cf9d3a, }, + { -0x28bf6ec2, -0x62efc6fb, -0x2ebf414d, -0x02c660fb, 0x688f8a09, -0x5a3e7bcc, -0x6707ed99, 0x44fd2f92, }, + { -0x78855598, -0x5436edfb, -0x33553b62, 0x26d9e823, -0x22bca674, 0x5a1b7dcb, -0x60f39a58, 0x6f117b68, }, + }, + { + { 0x4cee9730, -0x50da4f58, -0x1779b476, 0x025a8430, -0x60fe98ce, -0x3ee4affe, -0x657f070c, 0x7a164e1b, }, + { -0x5b032d9b, 0x56611fe8, -0x1a3e4583, 0x3bd353fd, 0x214bd6bd, -0x7ece0ce6, 0x555bda62, 0x2ab91587, }, + { 0x0dd0d889, 0x14ae933f, 0x1c35da62, 0x58942322, -0x730d24b4, -0x2e8f1abb, 0x12b9b4c6, 0x5a2826af, }, + }, + { + { 0x08a5bb33, -0x5ded43bc, -0x38a112fe, -0x72afb73d, 0x5abfec44, -0x22e414f4, 0x46e206eb, 0x2945ccf1, }, + { -0x5bb82946, 0x7f9182c3, 0x4b2729b7, -0x2affeb2f, -0x479b5f79, -0x1cc30ee4, -0x14e4aa0d, 0x154a7e73, }, + { -0x7ed57d7b, -0x4344240f, -0x2f422e04, 0x270e0807, 0x1bbda72d, -0x4be498f5, 0x6b3bb69a, 0x43aabe69, }, + }, + { + { -0x6bb15c41, 0x6b1a5cd0, -0x4c623f2e, 0x7470353a, 0x28542e49, 0x71b25282, 0x283c927e, 0x461bea69, }, + { -0x55cdde4f, -0x4590d366, 0x3bba23a7, 0x6ca02153, -0x6de6d3c6, -0x621589b1, 0x2e5317e0, 0x1d6edd5d, }, + { 0x01b8b3a2, -0x0e7c9238, 0x053ea49a, -0x4cfca0b9, 0x5877adf3, 0x529c41ba, 0x6a0f90a7, 0x7a9fbb1c, }, + }, + { + { -0x59579cd1, -0x64d19876, 0x51bc46c5, -0x59af6191, -0x39790a4b, -0x314dcc37, -0x752280a7, 0x34b9ed33, }, + { 0x039d8064, -0x0c91de82, -0x0adfbe65, -0x675f7e4a, -0x18a14fbc, -0x693439f8, -0x05236371, 0x49c05a51, }, + { -0x6fba50e5, 0x06b4e8bf, -0x58e62dd1, -0x1d007c18, -0x6c2b30ea, -0x550903d7, 0x1b008b06, 0x73c17202, }, + }, + { + { -0x757fd522, 0x2fbf0084, 0x02302e27, -0x1a260131, 0x17703406, 0x113e8471, 0x546d8faf, 0x4275aae2, }, + { 0x49864348, 0x315f5b02, 0x77088381, 0x3ed6b369, 0x6a8deb95, -0x5c5f8aab, 0x29d5c77f, 0x18ab5980, }, + { -0x029f7617, -0x27d4d33b, 0x3282e4a4, 0x031eb4a1, -0x4ae579de, 0x44311199, -0x4ac206b8, 0x3dc65522, }, + }, + { + { -0x5dff8093, -0x408f3dde, -0x4a432125, -0x407b4c66, -0x04f845f9, 0x537a0e12, -0x3cb90dbf, 0x234fd7ee, }, + { 0x327fbf93, 0x506f013b, -0x64889095, -0x51031437, -0x5552a698, -0x62ed4dce, 0x176024a7, 0x0267882d, }, + { 0x732ea378, 0x5360a119, -0x20722b8f, 0x2437e6b1, -0x6e581acd, -0x5d10c808, -0x55f6879d, 0x497ba6fd, }, + }, + { + { 0x13cfeaa0, 0x24cecc03, 0x189c246d, -0x79b73d73, -0x3e0d2b30, 0x2dbdbdfa, -0x0ed218d5, 0x61e22917, }, + { 0x468ccf0b, 0x040bcd86, 0x2a9910d6, -0x2c7d645c, 0x07b25192, 0x75083008, 0x18d05ebf, 0x43b5cd42, }, + { -0x642f4aea, 0x5d9a762f, 0x373fdeee, -0x14c750b2, -0x6c29bd90, 0x032e5a7d, 0x0ae4d842, 0x511d6121, }, + }, +}; +#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 }, { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 }, @@ -2260,6 +9396,7 @@ static ge_precomp Bi[8] = { { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 }, }, } ; +#endif /* @@ -2268,7 +9405,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]; @@ -2323,26 +9460,55 @@ int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, return 0; } - -static const fe d = { +#ifdef CURVED25519_ASM_64BIT +static const ge d = { + 0x75eb4dca135978a3, 0x00700a4d4141d8ab, -0x7338bf8688861768, 0x52036cee2b6ffe73, +}; +#elif defined(CURVED25519_ASM_32BIT) +static const ge d = { + 0x135978a3, 0x75eb4dca, 0x4141d8ab, 0x00700a4d, 0x7779e898, -0x7338bf87, 0x2b6ffe73, 0x52036cee, +}; +#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_ASM_64BIT +static const ge sqrtm1 = { + -0x3b11e4d8b5f15f50, 0x2f431806ad2fe478, 0x2b4d00993dfbd7a7, 0x2b8324804fc1df0b, +}; +#elif defined(CURVED25519_ASM_32BIT) +static const ge sqrtm1 = { + 0x4a0ea0b0, -0x3b11e4d9, -0x52d01b88, 0x2f431806, 0x3dfbd7a7, 0x2b4d0099, 0x4fc1df0b, 0x2b832480, +}; +#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); @@ -2384,19 +9550,24 @@ 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 WC_INLINE void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) { - fe t0; - fe_add(r->X,p->Y,p->X); - fe_sub(r->Y,p->Y,p->X); - fe_mul(r->Z,r->X,q->yplusx); - fe_mul(r->Y,r->Y,q->yminusx); - fe_mul(r->T,q->xy2d,p->T); - fe_add(t0,p->Z,p->Z); - fe_sub(r->X,r->Z,r->Y); - fe_add(r->Y,r->Z,r->Y); - fe_add(r->Z,t0,r->T); - fe_sub(r->T,t0,r->T); +#ifndef CURVED25519_ASM + 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); + fe_mul(r->Y,r->Y,q->yminusx); + fe_mul(r->T,q->xy2d,p->T); + fe_add(t0,p->Z,p->Z); + fe_sub(r->X,r->Z,r->Y); + fe_add(r->Y,r->Z,r->Y); + fe_add(r->Z,t0,r->T); + fe_sub(r->T,t0,r->T); +#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 } @@ -2406,19 +9577,24 @@ 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 WC_INLINE void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) { - fe t0; - fe_add(r->X,p->Y,p->X); - fe_sub(r->Y,p->Y,p->X); - fe_mul(r->Z,r->X,q->yminusx); - fe_mul(r->Y,r->Y,q->yplusx); - fe_mul(r->T,q->xy2d,p->T); - fe_add(t0,p->Z,p->Z); - fe_sub(r->X,r->Z,r->Y); - fe_add(r->Y,r->Z,r->Y); - fe_sub(r->Z,t0,r->T); - fe_add(r->T,t0,r->T); +#ifndef CURVED25519_ASM + 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); + fe_mul(r->Y,r->Y,q->yplusx); + fe_mul(r->T,q->xy2d,p->T); + fe_add(t0,p->Z,p->Z); + fe_sub(r->X,r->Z,r->Y); + fe_add(r->Y,r->Z,r->Y); + fe_sub(r->Z,t0,r->T); + fe_add(r->T,t0,r->T); +#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 } @@ -2427,11 +9603,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_ASM 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 } @@ -2441,18 +9621,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 WC_INLINE void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p) { +#ifndef CURVED25519_ASM 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); @@ -2466,29 +9650,22 @@ void ge_p2_0(ge_p2 *h) r = 2 * p */ -void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p) +static WC_INLINE void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p) { - fe t0; - fe_sq(r->X,p->X); - fe_sq(r->Z,p->Y); - fe_sq2(r->T,p->Z); - fe_add(r->Y,p->X,p->Y); - fe_sq(t0,r->Y); - fe_add(r->Y,r->Z,r->X); - fe_sub(r->Z,r->Z,r->X); - fe_sub(r->X,t0,r->Y); - fe_sub(r->T,r->T,r->Z); -} - - -/* 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); +#ifndef CURVED25519_ASM + ge t0; + fe_sq(r->X,p->X); + fe_sq(r->Z,p->Y); + fe_sq2(r->T,p->Z); + fe_add(r->Y,p->X,p->Y); + fe_sq(t0,r->Y); + fe_add(r->Y,r->Z,r->X); + fe_sub(r->Z,r->Z,r->X); + fe_sub(r->X,t0,r->Y); + fe_sub(r->T,r->T,r->Z); +#else + fe_ge_dbl(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z); +#endif } @@ -2498,7 +9675,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); @@ -2512,13 +9689,28 @@ void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) r = p */ -static const fe d2 = { +#ifdef CURVED25519_ASM_64BIT +static const ge d2 = { + -0x1429646bd94d0ea7, 0x00e0149a8283b156, 0x198e80f2eef3d130, 0x2406d9dc56dffce7, +}; +#elif defined(CURVED25519_ASM_32BIT) +static const ge d2 = { + 0x26b2f159, -0x1429646c, -0x7d7c4eaa, 0x00e0149a, -0x110c2ed0, 0x198e80f2, 0x56dffce7, 0x2406d9dc, +}; +#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 WC_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); @@ -2532,7 +9724,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); @@ -2543,9 +9735,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); @@ -2555,13 +9747,15 @@ void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) } +#ifndef CURVED25519_ASM /* 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 */ @@ -2569,29 +9763,34 @@ 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 WC_INLINE void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) { - fe t0; - fe_add(r->X,p->Y,p->X); - fe_sub(r->Y,p->Y,p->X); - fe_mul(r->Z,r->X,q->YminusX); - fe_mul(r->Y,r->Y,q->YplusX); - fe_mul(r->T,q->T2d,p->T); - fe_mul(r->X,p->Z,q->Z); - fe_add(t0,r->X,r->X); - fe_sub(r->X,r->Z,r->Y); - fe_add(r->Y,r->Z,r->Y); - fe_sub(r->Z,t0,r->T); - fe_add(r->T,t0,r->T); +#ifndef CURVED25519_ASM + 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); + fe_mul(r->Y,r->Y,q->YplusX); + fe_mul(r->T,q->T2d,p->T); + fe_mul(r->X,p->Z,q->Z); + fe_add(t0,r->X,r->X); + fe_sub(r->X,r->Z,r->Y); + fe_add(r->Y,r->Z,r->Y); + fe_sub(r->Z,t0,r->T); + fe_add(r->T,t0,r->T); +#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); @@ -2599,5 +9798,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 /* !ED25519_SMALL */ +#endif /* HAVE_ED25519 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/hash.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/hash.c index 55a1f6a1d..c53f5e67a 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/hash.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/hash.c @@ -1,8 +1,8 @@ /* hash.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,61 +16,1662 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include +#include +#include +#ifndef NO_ASN +#include +#endif + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#ifdef NO_ASN +enum Hash_Sum { + MD2h = 646, + MD5h = 649, + SHAh = 88, + SHA224h = 417, + SHA256h = 414, + SHA384h = 415, + SHA512h = 416, + SHA3_224h = 420, + SHA3_256h = 421, + SHA3_384h = 422, + SHA3_512h = 423 +}; +#endif /* !NO_ASN */ + +#if !defined(NO_PWDBASED) || !defined(NO_ASN) +/* function converts int hash type to enum */ +enum wc_HashType wc_HashTypeConvert(int hashType) +{ + /* Default to hash type none as error */ + enum wc_HashType eHashType = WC_HASH_TYPE_NONE; +#if defined(HAVE_FIPS) || defined(HAVE_SELFTEST) + /* original FIPSv1 and CAVP selftest require a mapping for unique hash + type to wc_HashType */ + switch (hashType) { + #ifndef NO_MD5 + case WC_MD5: + eHashType = WC_HASH_TYPE_MD5; + break; + #endif /* !NO_MD5 */ + #ifndef NO_SHA + case WC_SHA: + eHashType = WC_HASH_TYPE_SHA; + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + eHashType = WC_HASH_TYPE_SHA224; + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + eHashType = WC_HASH_TYPE_SHA256; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + eHashType = WC_HASH_TYPE_SHA384; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + eHashType = WC_HASH_TYPE_SHA512; + break; + #endif /* WOLFSSL_SHA512 */ + #ifdef WOLFSSL_SHA3 + case WC_SHA3_224: + eHashType = WC_HASH_TYPE_SHA3_224; + break; + case WC_SHA3_256: + eHashType = WC_HASH_TYPE_SHA3_256; + break; + case WC_SHA3_384: + eHashType = WC_HASH_TYPE_SHA3_384; + break; + case WC_SHA3_512: + eHashType = WC_HASH_TYPE_SHA3_512; + break; + #endif /* WOLFSSL_SHA3 */ + default: + eHashType = WC_HASH_TYPE_NONE; + break; + } +#else + /* current master uses same unique types as wc_HashType */ + if (hashType > 0 && hashType <= WC_HASH_TYPE_MAX) { + eHashType = (enum wc_HashType)hashType; + } +#endif + return eHashType; +} +#endif /* !NO_PWDBASED || !NO_ASN */ + +#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) + +int wc_HashGetOID(enum wc_HashType hash_type) +{ + int oid = HASH_TYPE_E; /* Default to hash type error */ + switch(hash_type) + { + case WC_HASH_TYPE_MD2: + #ifdef WOLFSSL_MD2 + oid = MD2h; + #endif + break; + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD5: + #ifndef NO_MD5 + oid = MD5h; + #endif + break; + case WC_HASH_TYPE_SHA: + #ifndef NO_SHA + oid = SHAh; + #endif + break; + case WC_HASH_TYPE_SHA224: + #ifdef WOLFSSL_SHA224 + oid = SHA224h; + #endif + break; + case WC_HASH_TYPE_SHA256: + #ifndef NO_SHA256 + oid = SHA256h; + #endif + break; + case WC_HASH_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + oid = SHA384h; + #endif + break; + case WC_HASH_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + oid = SHA512h; + #endif + break; + case WC_HASH_TYPE_SHA3_224: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + oid = SHA3_224h; + #endif + break; + case WC_HASH_TYPE_SHA3_256: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + oid = SHA3_256h; + #endif + break; + case WC_HASH_TYPE_SHA3_384: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + oid = SHA3_384h; + #endif + break; + case WC_HASH_TYPE_SHA3_512: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + oid = SHA3_512h; + #endif + break; + + /* Not Supported */ + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + oid = BAD_FUNC_ARG; + break; + } + return oid; +} + +enum wc_HashType wc_OidGetHash(int oid) +{ + enum wc_HashType hash_type = WC_HASH_TYPE_NONE; + switch (oid) + { + #ifdef WOLFSSL_MD2 + case MD2h: + hash_type = WC_HASH_TYPE_MD2; + break; + #endif + case MD5h: + #ifndef NO_MD5 + hash_type = WC_HASH_TYPE_MD5; + #endif + break; + case SHAh: + #ifndef NO_SHA + hash_type = WC_HASH_TYPE_SHA; + #endif + break; + case SHA224h: + #ifdef WOLFSSL_SHA224 + hash_type = WC_HASH_TYPE_SHA224; + #endif + break; + case SHA256h: + #ifndef NO_SHA256 + hash_type = WC_HASH_TYPE_SHA256; + #endif + break; + case SHA384h: + #ifdef WOLFSSL_SHA384 + hash_type = WC_HASH_TYPE_SHA384; + #endif + break; + case SHA512h: + #ifdef WOLFSSL_SHA512 + hash_type = WC_HASH_TYPE_SHA512; + #endif + break; + #ifdef WOLFSSL_SHA3 + case SHA3_224h: + hash_type = WC_HASH_TYPE_SHA3_224; + break; + case SHA3_256h: + hash_type = WC_HASH_TYPE_SHA3_256; + break; + case SHA3_384h: + hash_type = WC_HASH_TYPE_SHA3_384; + break; + case SHA3_512h: + hash_type = WC_HASH_TYPE_SHA3_512; + break; + #endif /* WOLFSSL_SHA3 */ + default: + break; + } + return hash_type; +} +#endif /* !NO_ASN || !NO_DH || HAVE_ECC */ + +#ifndef NO_HASH_WRAPPER + +/* Get Hash digest size */ +int wc_HashGetDigestSize(enum wc_HashType hash_type) +{ + int dig_size = HASH_TYPE_E; /* Default to hash type error */ + switch(hash_type) + { + case WC_HASH_TYPE_MD2: + #ifdef WOLFSSL_MD2 + dig_size = MD2_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_MD4: + #ifndef NO_MD4 + dig_size = MD4_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_MD5: + #ifndef NO_MD5 + dig_size = WC_MD5_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA: + #ifndef NO_SHA + dig_size = WC_SHA_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA224: + #ifdef WOLFSSL_SHA224 + dig_size = WC_SHA224_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA256: + #ifndef NO_SHA256 + dig_size = WC_SHA256_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + dig_size = WC_SHA384_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + dig_size = WC_SHA512_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_MD5_SHA: /* Old TLS Specific */ + #if !defined(NO_MD5) && !defined(NO_SHA) + dig_size = (int)WC_MD5_DIGEST_SIZE + (int)WC_SHA_DIGEST_SIZE; + #endif + break; + + case WC_HASH_TYPE_SHA3_224: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + dig_size = WC_SHA3_224_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA3_256: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + dig_size = WC_SHA3_256_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA3_384: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + dig_size = WC_SHA3_384_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA3_512: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + dig_size = WC_SHA3_512_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + #if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) + dig_size = BLAKE2S_OUTBYTES; + #endif + break; + + /* Not Supported */ + case WC_HASH_TYPE_NONE: + default: + dig_size = BAD_FUNC_ARG; + break; + } + return dig_size; +} + + +/* Get Hash block size */ +int wc_HashGetBlockSize(enum wc_HashType hash_type) +{ + int block_size = HASH_TYPE_E; /* Default to hash type error */ + switch (hash_type) + { + case WC_HASH_TYPE_MD2: + #ifdef WOLFSSL_MD2 + block_size = MD2_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_MD4: + #ifndef NO_MD4 + block_size = MD4_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_MD5: + #ifndef NO_MD5 + block_size = WC_MD5_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA: + #ifndef NO_SHA + block_size = WC_SHA_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA224: + #ifdef WOLFSSL_SHA224 + block_size = WC_SHA224_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA256: + #ifndef NO_SHA256 + block_size = WC_SHA256_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + block_size = WC_SHA384_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + block_size = WC_SHA512_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_MD5_SHA: /* Old TLS Specific */ + #if !defined(NO_MD5) && !defined(NO_SHA) + block_size = (int)WC_MD5_BLOCK_SIZE + (int)WC_SHA_BLOCK_SIZE; + #endif + break; + + case WC_HASH_TYPE_SHA3_224: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + block_size = WC_SHA3_224_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA3_256: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + block_size = WC_SHA3_256_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA3_384: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + block_size = WC_SHA3_384_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA3_512: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + block_size = WC_SHA3_512_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + #if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) + block_size = BLAKE2S_BLOCKBYTES; + #endif + break; + + /* Not Supported */ + case WC_HASH_TYPE_NONE: + default: + block_size = BAD_FUNC_ARG; + break; + } + return block_size; +} + +/* Generic Hashing Wrapper */ +int wc_Hash(enum wc_HashType hash_type, const byte* data, + word32 data_len, byte* hash, word32 hash_len) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + word32 dig_size; + + /* Validate hash buffer size */ + dig_size = wc_HashGetDigestSize(hash_type); + if (hash_len < dig_size) { + return BUFFER_E; + } + + /* Suppress possible unused arg if all hashing is disabled */ + (void)data; + (void)data_len; + (void)hash; + (void)hash_len; + + switch(hash_type) + { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + ret = wc_Md5Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + ret = wc_ShaHash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + ret = wc_Sha224Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + ret = wc_Sha256Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_MD5_SHA: +#if !defined(NO_MD5) && !defined(NO_SHA) + ret = wc_Md5Hash(data, data_len, hash); + if (ret == 0) { + ret = wc_ShaHash(data, data_len, &hash[WC_MD5_DIGEST_SIZE]); + } +#endif + break; + + case WC_HASH_TYPE_SHA3_224: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + ret = wc_Sha3_224Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA3_256: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + ret = wc_Sha3_256Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA3_384: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + ret = wc_Sha3_384Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA3_512: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + ret = wc_Sha3_512Hash(data, data_len, hash); +#endif + break; + + /* Not Supported */ + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + break; + } + return ret; +} + +int wc_HashInit_ex(wc_HashAlg* hash, enum wc_HashType type, void* heap, + int devId) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + + if (hash == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + ret = wc_InitMd5_ex(&hash->md5, heap, devId); +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + ret = wc_InitSha_ex(&hash->sha, heap, devId); +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + ret = wc_InitSha224_ex(&hash->sha224, heap, devId); +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + ret = wc_InitSha256_ex(&hash->sha256, heap, devId); +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + ret = wc_InitSha384_ex(&hash->sha384, heap, devId); +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + ret = wc_InitSha512_ex(&hash->sha512, heap, devId); +#endif + break; + + case WC_HASH_TYPE_SHA3_224: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + ret = wc_InitSha3_224(&hash->sha3, heap, devId); +#endif + break; + case WC_HASH_TYPE_SHA3_256: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + ret = wc_InitSha3_256(&hash->sha3, heap, devId); +#endif + break; + case WC_HASH_TYPE_SHA3_384: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + ret = wc_InitSha3_384(&hash->sha3, heap, devId); +#endif + break; + case WC_HASH_TYPE_SHA3_512: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + ret = wc_InitSha3_512(&hash->sha3, heap, devId); +#endif + break; + + /* not supported */ + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + }; + + return ret; +} + +int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type) +{ + return wc_HashInit_ex(hash, type, NULL, INVALID_DEVID); +} + +int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, + word32 dataSz) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + + if (hash == NULL || data == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + ret = wc_Md5Update(&hash->md5, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + ret = wc_ShaUpdate(&hash->sha, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + ret = wc_Sha224Update(&hash->sha224, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + ret = wc_Sha256Update(&hash->sha256, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384Update(&hash->sha384, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512Update(&hash->sha512, data, dataSz); +#endif + break; + + case WC_HASH_TYPE_SHA3_224: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + ret = wc_Sha3_224_Update(&hash->sha3, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA3_256: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + ret = wc_Sha3_256_Update(&hash->sha3, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA3_384: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + ret = wc_Sha3_384_Update(&hash->sha3, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA3_512: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + ret = wc_Sha3_512_Update(&hash->sha3, data, dataSz); +#endif + break; + + /* not supported */ + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + }; + + return ret; +} + +int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + + if (hash == NULL || out == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + ret = wc_Md5Final(&hash->md5, out); +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + ret = wc_ShaFinal(&hash->sha, out); +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + ret = wc_Sha224Final(&hash->sha224, out); +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + ret = wc_Sha256Final(&hash->sha256, out); +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384Final(&hash->sha384, out); +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512Final(&hash->sha512, out); +#endif + break; + + case WC_HASH_TYPE_SHA3_224: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + ret = wc_Sha3_224_Final(&hash->sha3, out); +#endif + break; + case WC_HASH_TYPE_SHA3_256: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + ret = wc_Sha3_256_Final(&hash->sha3, out); +#endif + break; + case WC_HASH_TYPE_SHA3_384: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + ret = wc_Sha3_384_Final(&hash->sha3, out); +#endif + break; + case WC_HASH_TYPE_SHA3_512: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + ret = wc_Sha3_512_Final(&hash->sha3, out); +#endif + break; + + /* not supported */ + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + }; + + return ret; +} + +int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + + if (hash == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + wc_Md5Free(&hash->md5); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + wc_ShaFree(&hash->sha); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + wc_Sha224Free(&hash->sha224); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + wc_Sha256Free(&hash->sha256); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + wc_Sha384Free(&hash->sha384); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + wc_Sha512Free(&hash->sha512); + ret = 0; +#endif + break; + + case WC_HASH_TYPE_SHA3_224: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + wc_Sha3_224_Free(&hash->sha3); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA3_256: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + wc_Sha3_256_Free(&hash->sha3); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA3_384: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + wc_Sha3_384_Free(&hash->sha3); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA3_512: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + wc_Sha3_512_Free(&hash->sha3); + ret = 0; +#endif + break; + + /* not supported */ + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + }; + + return ret; +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_HashSetFlags(wc_HashAlg* hash, enum wc_HashType type, word32 flags) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + + if (hash == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + ret = wc_Md5SetFlags(&hash->md5, flags); +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + ret = wc_ShaSetFlags(&hash->sha, flags); +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + ret = wc_Sha224SetFlags(&hash->sha224, flags); +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + ret = wc_Sha256SetFlags(&hash->sha256, flags); +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384SetFlags(&hash->sha384, flags); +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512SetFlags(&hash->sha512, flags); +#endif + break; + + case WC_HASH_TYPE_SHA3_224: + case WC_HASH_TYPE_SHA3_256: + case WC_HASH_TYPE_SHA3_384: + case WC_HASH_TYPE_SHA3_512: +#ifdef WOLFSSL_SHA3 + ret = wc_Sha3_SetFlags(&hash->sha3, flags); +#endif + break; + + /* not supported */ + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + }; + + return ret; +} +int wc_HashGetFlags(wc_HashAlg* hash, enum wc_HashType type, word32* flags) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + + if (hash == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + ret = wc_Md5GetFlags(&hash->md5, flags); +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + ret = wc_ShaGetFlags(&hash->sha, flags); +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + ret = wc_Sha224GetFlags(&hash->sha224, flags); +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + ret = wc_Sha256GetFlags(&hash->sha256, flags); +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384GetFlags(&hash->sha384, flags); +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512GetFlags(&hash->sha512, flags); +#endif + break; + + case WC_HASH_TYPE_SHA3_224: + case WC_HASH_TYPE_SHA3_256: + case WC_HASH_TYPE_SHA3_384: + case WC_HASH_TYPE_SHA3_512: +#ifdef WOLFSSL_SHA3 + ret = wc_Sha3_GetFlags(&hash->sha3, flags); +#endif + break; + + /* not supported */ + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + }; + + return ret; +} +#endif + #if !defined(WOLFSSL_TI_HASH) -#include - #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 ; -} -#endif + #ifdef WOLFSSL_SMALL_STACK + md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitMd5(md5)) != 0) { + WOLFSSL_MSG("InitMd5 failed"); + } + else { + if ((ret = wc_Md5Update(md5, data, len)) != 0) { + WOLFSSL_MSG("Md5Update failed"); + } + else if ((ret = wc_Md5Final(md5, hash)) != 0) { + WOLFSSL_MSG("Md5Final failed"); + } + wc_Md5Free(md5); + } + + #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 -WOLFSSL_API 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 + + if ((ret = wc_InitSha(sha)) != 0) { + WOLFSSL_MSG("InitSha failed"); + } + else { + if ((ret = wc_ShaUpdate(sha, data, len)) != 0) { + WOLFSSL_MSG("ShaUpdate failed"); + } + else if ((ret = wc_ShaFinal(sha, hash)) != 0) { + WOLFSSL_MSG("ShaFinal failed"); + } + wc_ShaFree(sha); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !NO_SHA */ + +#if defined(WOLFSSL_SHA224) + int wc_Sha224Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha224* sha224; + #else + wc_Sha224 sha224[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha224 = (wc_Sha224*)XMALLOC(sizeof(wc_Sha224), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha224 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha224(sha224)) != 0) { + WOLFSSL_MSG("InitSha224 failed"); + } + else { + if ((ret = wc_Sha224Update(sha224, data, len)) != 0) { + WOLFSSL_MSG("Sha224Update failed"); + } + else if ((ret = wc_Sha224Final(sha224, hash)) != 0) { + WOLFSSL_MSG("Sha224Final failed"); + } + wc_Sha224Free(sha224); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha224, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; } -#endif +#endif /* WOLFSSL_SHA224 */ #if !defined(NO_SHA256) -int wc_Sha256GetHash(Sha256* sha256, byte* hash) + 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 + + #ifdef WOLFSSL_SMALL_STACK + sha256 = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha256 == NULL) + return MEMORY_E; + #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"); + } + wc_Sha256Free(sha256); + } + + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !NO_SHA256 */ + +#endif /* !defined(WOLFSSL_TI_HASH) */ + + +#if defined(WOLFSSL_SHA512) + 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 + + #ifdef WOLFSSL_SMALL_STACK + sha512 = (wc_Sha512*)XMALLOC(sizeof(wc_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"); + } + wc_Sha512Free(sha512); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* WOLFSSL_SHA512 */ + +#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 + + #ifdef WOLFSSL_SMALL_STACK + sha384 = (wc_Sha384*)XMALLOC(sizeof(wc_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"); + } + wc_Sha384Free(sha384); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* WOLFSSL_SHA384 */ + +#if defined(WOLFSSL_SHA3) +#if !defined(WOLFSSL_NOSHA3_224) + int wc_Sha3_224Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha3* sha3; + #else + wc_Sha3 sha3[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha3 = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha3 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha3_224(sha3, NULL, INVALID_DEVID)) != 0) { + WOLFSSL_MSG("InitSha3_224 failed"); + } + else { + if ((ret = wc_Sha3_224_Update(sha3, data, len)) != 0) { + WOLFSSL_MSG("Sha3_224_Update failed"); + } + else if ((ret = wc_Sha3_224_Final(sha3, hash)) != 0) { + WOLFSSL_MSG("Sha3_224_Final failed"); + } + wc_Sha3_224_Free(sha3); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha3, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !WOLFSSL_NOSHA3_224 */ + +#if !defined(WOLFSSL_NOSHA3_256) + int wc_Sha3_256Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha3* sha3; + #else + wc_Sha3 sha3[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha3 = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha3 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha3_256(sha3, NULL, INVALID_DEVID)) != 0) { + WOLFSSL_MSG("InitSha3_256 failed"); + } + else { + if ((ret = wc_Sha3_256_Update(sha3, data, len)) != 0) { + WOLFSSL_MSG("Sha3_256_Update failed"); + } + else if ((ret = wc_Sha3_256_Final(sha3, hash)) != 0) { + WOLFSSL_MSG("Sha3_256_Final failed"); + } + wc_Sha3_256_Free(sha3); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha3, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !WOLFSSL_NOSHA3_256 */ + +#if !defined(WOLFSSL_NOSHA3_384) + int wc_Sha3_384Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha3* sha3; + #else + wc_Sha3 sha3[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha3 = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha3 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha3_384(sha3, NULL, INVALID_DEVID)) != 0) { + WOLFSSL_MSG("InitSha3_384 failed"); + } + else { + if ((ret = wc_Sha3_384_Update(sha3, data, len)) != 0) { + WOLFSSL_MSG("Sha3_384_Update failed"); + } + else if ((ret = wc_Sha3_384_Final(sha3, hash)) != 0) { + WOLFSSL_MSG("Sha3_384_Final failed"); + } + wc_Sha3_384_Free(sha3); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha3, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !WOLFSSL_NOSHA3_384 */ + +#if !defined(WOLFSSL_NOSHA3_512) + int wc_Sha3_512Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha3* sha3; + #else + wc_Sha3 sha3[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha3 = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha3 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha3_512(sha3, NULL, INVALID_DEVID)) != 0) { + WOLFSSL_MSG("InitSha3_512 failed"); + } + else { + if ((ret = wc_Sha3_512_Update(sha3, data, len)) != 0) { + WOLFSSL_MSG("Sha3_512_Update failed"); + } + else if ((ret = wc_Sha3_512_Final(sha3, hash)) != 0) { + WOLFSSL_MSG("Sha3_512_Final failed"); + } + wc_Sha3_512_Free(sha3); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha3, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !WOLFSSL_NOSHA3_512 */ + +#if defined(WOLFSSL_SHAKE256) && !defined(WOLFSSL_NO_SHAKE256) + int wc_Shake256Hash(const byte* data, word32 len, byte* hash, + word32 hashLen) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Shake* shake; + #else + wc_Shake shake[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + shake = (wc_Shake*)XMALLOC(sizeof(wc_Shake), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (shake == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitShake256(shake, NULL, INVALID_DEVID)) != 0) { + WOLFSSL_MSG("InitShake256 failed"); + } + else { + if ((ret = wc_Shake256_Update(shake, data, len)) != 0) { + WOLFSSL_MSG("Shake256_Update failed"); + } + else if ((ret = wc_Shake256_Final(shake, hash, hashLen)) != 0) { + WOLFSSL_MSG("Shake256_Final failed"); + } + wc_Shake256_Free(shake); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(shake, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* WOLFSSL_SHAKE_256 && !WOLFSSL_NO_SHAKE256 */ +#endif /* WOLFSSL_SHA3 */ + +#endif /* !NO_HASH_WRAPPER */ + +#ifdef WOLFSSL_HAVE_PRF + +#ifdef WOLFSSL_SHA384 + #define P_HASH_MAX_SIZE WC_SHA384_DIGEST_SIZE +#else + #define P_HASH_MAX_SIZE WC_SHA256_DIGEST_SIZE +#endif + +/* Pseudo Random Function for MD5, SHA-1, SHA-256, or SHA-384 */ +int wc_PRF(byte* result, word32 resLen, const byte* secret, + word32 secLen, const byte* seed, word32 seedLen, int hash, + void* heap, int devId) { - int ret ; - Sha256 save = *sha256 ; - ret = wc_Sha256Final(sha256, hash) ; - *sha256 = save ; - return ret ; -} - -WOLFSSL_API void wc_Sha256RestorePos(Sha256* s1, Sha256* s2) { - *s1 = *s2 ; -} + word32 len = P_HASH_MAX_SIZE; + word32 times; + word32 lastLen; + word32 lastTime; + word32 i; + word32 idx = 0; + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* previous; + byte* current; + Hmac* hmac; +#else + byte previous[P_HASH_MAX_SIZE]; /* max size */ + byte current[P_HASH_MAX_SIZE]; /* max size */ + Hmac hmac[1]; #endif +#ifdef WOLFSSL_SMALL_STACK + 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, heap, DYNAMIC_TYPE_DIGEST); + if (current) XFREE(current, heap, DYNAMIC_TYPE_DIGEST); + if (hmac) XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); + + return MEMORY_E; + } #endif + switch (hash) { + #ifndef NO_MD5 + case md5_mac: + hash = WC_MD5; + len = WC_MD5_DIGEST_SIZE; + break; + #endif + + #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 + + #ifndef NO_SHA + case sha_mac: + default: + hash = WC_SHA; + len = WC_SHA_DIGEST_SIZE; + break; + #endif + } + + times = resLen / len; + lastLen = resLen % len; + + if (lastLen) + times += 1; + + lastTime = times - 1; + + 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_HmacFinal(hmac, previous); + if (ret != 0) + break; + } + } + } + wc_HmacFree(hmac); + } + + ForceZero(previous, P_HASH_MAX_SIZE); + ForceZero(current, P_HASH_MAX_SIZE); + ForceZero(hmac, sizeof(Hmac)); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(previous, heap, DYNAMIC_TYPE_DIGEST); + XFREE(current, heap, DYNAMIC_TYPE_DIGEST); + XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); +#endif + + return ret; +} +#undef P_HASH_MAX_SIZE + +/* compute PRF (pseudo random function) using SHA1 and MD5 for TLSv1 */ +int wc_PRF_TLSv1(byte* digest, word32 digLen, const byte* secret, + word32 secLen, const byte* label, word32 labLen, + const byte* seed, word32 seedLen, void* heap, int devId) +{ + int ret = 0; + word32 half = (secLen + 1) / 2; + +#ifdef WOLFSSL_SMALL_STACK + byte* md5_half; + byte* sha_half; + byte* md5_result; + byte* sha_result; +#else + byte md5_half[MAX_PRF_HALF]; /* half is real size */ + byte sha_half[MAX_PRF_HALF]; /* half is real size */ + byte md5_result[MAX_PRF_DIG]; /* digLen is real size */ + byte sha_result[MAX_PRF_DIG]; /* digLen is real size */ +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap); + if (labelSeed == NULL) + return MEMORY_E; +#else + byte labelSeed[MAX_PRF_LABSEED]; +#endif + + if (half > MAX_PRF_HALF || + labLen + seedLen > MAX_PRF_LABSEED || + digLen > MAX_PRF_DIG) + { + #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(labelSeed, heap); + #endif + return BUFFER_E; + } + +#ifdef WOLFSSL_SMALL_STACK + md5_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST); + sha_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST); + 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 || md5_result == NULL || + sha_result == NULL) { + if (md5_half) XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST); + if (sha_half) XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST); + if (md5_result) XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST); + if (sha_result) XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST); + #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(labelSeed, heap); + #endif + + return MEMORY_E; + } +#endif + + XMEMSET(md5_result, 0, digLen); + XMEMSET(sha_result, 0, digLen); + + XMEMCPY(md5_half, secret, half); + XMEMCPY(sha_half, secret + half - secLen % 2, half); + + XMEMCPY(labelSeed, label, labLen); + XMEMCPY(labelSeed + labLen, seed, seedLen); + + if ((ret = wc_PRF(md5_result, digLen, md5_half, half, labelSeed, + labLen + seedLen, md5_mac, heap, devId)) == 0) { + if ((ret = wc_PRF(sha_result, digLen, sha_half, half, labelSeed, + labLen + seedLen, sha_mac, heap, devId)) == 0) { + /* calculate XOR for TLSv1 PRF */ + XMEMCPY(digest, md5_result, digLen); + xorbuf(digest, sha_result, digLen); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST); + XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST); + XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST); + XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST); +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(labelSeed, heap); +#endif + + return ret; +} + +/* Wrapper for TLS 1.2 and TLSv1 cases to calculate PRF */ +/* In TLS 1.2 case call straight thru to wc_PRF */ +int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen, + const byte* label, word32 labLen, const byte* seed, word32 seedLen, + int useAtLeastSha256, int hash_type, void* heap, int devId) +{ + int ret = 0; + + if (useAtLeastSha256) { + #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap); + if (labelSeed == NULL) + return MEMORY_E; + #else + byte labelSeed[MAX_PRF_LABSEED]; + #endif + + if (labLen + seedLen > MAX_PRF_LABSEED) + return BUFFER_E; + + XMEMCPY(labelSeed, label, labLen); + XMEMCPY(labelSeed + labLen, seed, seedLen); + + /* If a cipher suite wants an algorithm better than sha256, it + * should use better. */ + if (hash_type < sha256_mac || hash_type == blake2b_mac) + hash_type = sha256_mac; + /* compute PRF for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1.2 PRF */ + ret = wc_PRF(digest, digLen, secret, secLen, labelSeed, + labLen + seedLen, hash_type, heap, devId); + + #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(labelSeed, heap); + #endif + } +#ifndef NO_OLD_TLS + else { + /* compute TLSv1 PRF (pseudo random function using HMAC) */ + ret = wc_PRF_TLSv1(digest, digLen, secret, secLen, label, labLen, seed, + seedLen, heap, devId); + } +#endif + + return ret; +} +#endif /* WOLFSSL_HAVE_PRF */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/hc128.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/hc128.c index bcfa148e0..96f02d16d 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/hc128.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/hc128.c @@ -1,8 +1,8 @@ /* hc128.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -34,6 +35,7 @@ #include #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif @@ -71,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){ \ @@ -83,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]); @@ -112,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]); @@ -148,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){ \ @@ -159,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*/ @@ -169,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); @@ -187,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); @@ -207,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); + } } @@ -230,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]; @@ -238,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; +static WC_INLINE int DoKey(HC128* ctx, const byte* key, const byte* iv) +{ + 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); @@ -286,10 +288,35 @@ static INLINE int DoKey(HC128* ctx, const byte* key, const byte* iv) } +int wc_Hc128_SetHeap(HC128* ctx, void* heap) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef XSTREAM_ALIGN + ctx->heap = heap; +#endif + + (void)heap; + return 0; +} + /* 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 + ctx->heap = (void*)WOLFSSL_HEAP_TEST; + #else + ctx->heap = NULL; + #endif /* WOLFSSL_HEAP_TEST */ + if ((wolfssl_word)key % 4) { int alignKey[4]; @@ -308,7 +335,7 @@ int wc_Hc128_SetKey(HC128* ctx, const byte* key, const byte* iv) /* The following defines the encryption of data stream */ -static INLINE int DoProcess(HC128* ctx, byte* output, const byte* input, +static WC_INLINE int DoProcess(HC128* ctx, byte* output, const byte* input, word32 msglen) { word32 i, keystream[16]; @@ -345,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 @@ -361,20 +388,24 @@ 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 byte* tmp; WOLFSSL_MSG("Hc128Process unaligned"); - tmp = (byte*)XMALLOC(msglen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmp = (byte*)XMALLOC(msglen, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) return MEMORY_E; XMEMCPY(tmp, input, msglen); DoProcess(ctx, tmp, tmp, msglen); XMEMCPY(output, tmp, msglen); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); return 0; #else diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/hmac.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/hmac.c index 242adfa55..bcebc1ce2 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/hmac.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/hmac.c @@ -1,8 +1,8 @@ -/* hmac.h +/* hmac.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,170 +16,298 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include +#include #ifndef NO_HMAC -#include +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) -#ifdef HAVE_FIPS -/* does init */ -int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz) -{ - return HmacSetKey_fips(hmac, type, key, keySz); -} + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS - -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 HAVE_CAVIUM - int wc_HmacInitCavium(Hmac* hmac, int i) - { - return HmacInitCavium(hmac, i); - } - - - void wc_HmacFreeCavium(Hmac* hmac) - { - HmacFreeCavium(hmac); - } + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$b") + #pragma const_seg(".fipsB$b") + #endif #endif -int wolfSSL_GetHmacMaxSize(void) -{ - return CyaSSL_GetHmacMaxSize(); -} +#include -#ifdef HAVE_HKDF +#ifdef WOLF_CRYPTO_CB + #include +#endif -int wc_HKDF(int type, const byte* inKey, word32 inKeySz, +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +/* fips wrapper calls, user can call direct */ +/* If building for old FIPS. */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + + /* does init */ + int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz) + { + if (hmac == NULL || (key == NULL && keySz != 0) || + !(type == WC_MD5 || type == WC_SHA || type == WC_SHA256 || + type == WC_SHA384 || type == WC_SHA512)) { + 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(); + } + + int wc_HmacInit(Hmac* hmac, void* heap, int devId) + { + (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); */ + } + + #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); + } + #endif /* HAVE_HKDF */ + +#else /* else build without fips, or for new fips */ + + +int wc_HmacSizeByType(int type) { - return HKDF(type, inKey, inKeySz, salt, saltSz, info, infoSz, out, outSz); + int ret; + + if (!(type == WC_MD5 || type == WC_SHA || + type == WC_SHA224 || type == WC_SHA256 || + type == WC_SHA384 || type == WC_SHA512 || + type == WC_SHA3_224 || type == WC_SHA3_256 || + type == WC_SHA3_384 || type == WC_SHA3_512)) { + return BAD_FUNC_ARG; + } + + switch (type) { + #ifndef NO_MD5 + case WC_MD5: + ret = WC_MD5_DIGEST_SIZE; + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + ret = WC_SHA_DIGEST_SIZE; + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + ret = WC_SHA224_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + ret = WC_SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = WC_SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + ret = WC_SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef WOLFSSL_SHA3 + case WC_SHA3_224: + ret = WC_SHA3_224_DIGEST_SIZE; + break; + + case WC_SHA3_256: + ret = WC_SHA3_256_DIGEST_SIZE; + break; + + case WC_SHA3_384: + ret = WC_SHA3_384_DIGEST_SIZE; + break; + + case WC_SHA3_512: + ret = WC_SHA3_512_DIGEST_SIZE; + break; + + #endif + + default: + ret = BAD_FUNC_ARG; + break; + } + + return ret; } - -#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 - - -#ifdef HAVE_CAVIUM - static void HmacCaviumFinal(Hmac* hmac, byte* hash); - static void HmacCaviumUpdate(Hmac* hmac, const byte* msg, word32 length); - static void HmacCaviumSetKey(Hmac* hmac, int type, const byte* key, - word32 length); -#endif - -static int InitHmac(Hmac* hmac, int type) +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)) - 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 - - #ifndef NO_SHA256 - case SHA256: + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + ret = wc_InitSha224(&hmac->hash.sha224); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: ret = wc_InitSha256(&hmac->hash.sha256); - break; - #endif - - #ifdef WOLFSSL_SHA384 - case SHA384: + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: ret = wc_InitSha384(&hmac->hash.sha384); - break; - #endif - - #ifdef WOLFSSL_SHA512 - case SHA512: + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: ret = wc_InitSha512(&hmac->hash.sha512); - break; - #endif - - #ifdef HAVE_BLAKE2 - case BLAKE2B_ID: - ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256); - break; - #endif - + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_SHA3_224: + ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_SHA3_256: + ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case WC_SHA3_384: + ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case WC_SHA3_512: + ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + #endif + #endif + 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; -#ifdef HAVE_CAVIUM - if (hmac->magic == WOLFSSL_HMAC_CAVIUM_MAGIC) - return HmacCaviumSetKey(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 == WC_SHA3_224 || type == WC_SHA3_256 || + type == WC_SHA3_384 || type == WC_SHA3_512)) { + return BAD_FUNC_ARG; + } + +#ifndef HAVE_FIPS + /* if set key has already been run then make sure and free existing */ + /* This is for async and PIC32MZ situations, and just normally OK, + provided the user calls wc_HmacInit() first. That function is not + available in FIPS builds. In current FIPS builds, the hashes are + not allocating resources. */ + if (hmac->macType != WC_HASH_TYPE_NONE) { + wc_HmacFree(hmac); + } #endif - ret = InitHmac(hmac, type); + hmac->innerHashKeyed = 0; + hmac->macType = (byte)type; + + ret = _InitHmac(hmac, type, heap); if (ret != 0) return ret; @@ -188,138 +316,255 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) return HMAC_MIN_KEYLEN_E; #endif +#ifdef WOLF_CRYPTO_CB + hmac->keyRaw = key; /* use buffer directly */ + hmac->keyLen = length; +#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; - #ifndef NO_SHA256 - case SHA256: - { - hmac_block_size = SHA256_BLOCK_SIZE; - if (length <= SHA256_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + length = WC_SHA_DIGEST_SIZE; + } + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + 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) + break; + ret = wc_Sha224Final(&hmac->hash.sha224, ip); + if (ret != 0) + break; + + length = WC_SHA224_DIGEST_SIZE; + } + break; + #endif /* WOLFSSL_SHA224 */ + #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_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 */ + #ifdef WOLFSSL_SHA512 + 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 - case BLAKE2B_ID: - { - hmac_block_size = BLAKE2B_BLOCKBYTES; - if (length <= BLAKE2B_BLOCKBYTES) { - XMEMCPY(ip, key, length); + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_SHA3_224: + hmac_block_size = WC_SHA3_224_BLOCK_SIZE; + if (length <= WC_SHA3_224_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, key, length); + ret = wc_Sha3_224_Update(&hmac->hash.sha3, key, length); if (ret != 0) - return ret; - - ret = wc_Blake2bFinal(&hmac->hash.blake2b, ip, BLAKE2B_256); + break; + ret = wc_Sha3_224_Final(&hmac->hash.sha3, ip); if (ret != 0) - return ret; + break; - length = BLAKE2B_256; + length = WC_SHA3_224_DIGEST_SIZE; } - } - break; - #endif + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_SHA3_256: + hmac_block_size = WC_SHA3_256_BLOCK_SIZE; + if (length <= WC_SHA3_256_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Sha3_256_Update(&hmac->hash.sha3, key, length); + if (ret != 0) + break; + ret = wc_Sha3_256_Final(&hmac->hash.sha3, ip); + if (ret != 0) + break; + + length = WC_SHA3_256_DIGEST_SIZE; + } + break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case WC_SHA3_384: + hmac_block_size = WC_SHA3_384_BLOCK_SIZE; + if (length <= WC_SHA3_384_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Sha3_384_Update(&hmac->hash.sha3, key, length); + if (ret != 0) + break; + ret = wc_Sha3_384_Final(&hmac->hash.sha3, ip); + if (ret != 0) + break; + + length = WC_SHA3_384_DIGEST_SIZE; + } + break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case WC_SHA3_512: + hmac_block_size = WC_SHA3_512_BLOCK_SIZE; + if (length <= WC_SHA3_512_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Sha3_512_Update(&hmac->hash.sha3, key, length); + if (ret != 0) + break; + ret = wc_Sha3_512_Final(&hmac->hash.sha3, ip); + if (ret != 0) + break; + + length = WC_SHA3_512_DIGEST_SIZE; + } + break; + #endif + #endif /* WOLFSSL_SHA3 */ 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) || defined(HAVE_CAVIUM) + #ifdef HAVE_INTEL_QA + if (IntelQaHmacGetType(hmac->macType, NULL) == 0) + #endif + { + 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; } @@ -328,59 +573,79 @@ 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 */ - #ifndef NO_SHA256 - case SHA256: - ret = wc_Sha256Update(&hmac->hash.sha256, - (byte*) hmac->ipad, SHA256_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 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_SHA384 + case WC_SHA384: + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->ipad, + WC_SHA384_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + 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 - case BLAKE2B_ID: - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, - (byte*) hmac->ipad,BLAKE2B_BLOCKBYTES); - if (ret != 0) - return ret; - break; - #endif + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_SHA3_224: + ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->ipad, + WC_SHA3_224_BLOCK_SIZE); + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_SHA3_256: + ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->ipad, + WC_SHA3_256_BLOCK_SIZE); + break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case WC_SHA3_384: + ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->ipad, + WC_SHA3_384_BLOCK_SIZE); + break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case WC_SHA3_512: + ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->ipad, + WC_SHA3_512_BLOCK_SIZE); + break; + #endif + #endif /* WOLFSSL_SHA3 */ default: - break; + break; } - hmac->innerHashKeyed = 1; + if (ret == 0) + hmac->innerHashKeyed = WC_HMAC_INNER_HASH_KEYED_SW; return ret; } @@ -388,12 +653,33 @@ static int HmacKeyInnerHash(Hmac* hmac) int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) { - int ret; + int ret = 0; -#ifdef HAVE_CAVIUM - if (hmac->magic == WOLFSSL_HMAC_CAVIUM_MAGIC) - return HmacCaviumUpdate(hmac, msg, length); + if (hmac == NULL || (msg == NULL && length > 0)) { + return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (hmac->devId != INVALID_DEVID) { + ret = wc_CryptoCb_Hmac(hmac, hmac->macType, msg, length, NULL); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; /* reset error code */ + } #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) + if (IntelQaHmacGetType(hmac->macType, NULL) == 0) { + 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); @@ -402,55 +688,69 @@ 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 */ - #ifndef NO_SHA256 - case SHA256: + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + ret = wc_Sha224Update(&hmac->hash.sha224, msg, length); + break; + #endif /* WOLFSSL_SHA224 */ + + #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_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 */ + #ifdef WOLFSSL_SHA512 + 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 - case BLAKE2B_ID: - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, msg, length); - if (ret != 0) - return ret; - break; - #endif + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_SHA3_224: + ret = wc_Sha3_224_Update(&hmac->hash.sha3, msg, length); + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_SHA3_256: + ret = wc_Sha3_256_Update(&hmac->hash.sha3, msg, length); + break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case WC_SHA3_384: + ret = wc_Sha3_384_Update(&hmac->hash.sha3, msg, length); + break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case WC_SHA3_512: + ret = wc_Sha3_512_Update(&hmac->hash.sha3, msg, length); + break; + #endif + #endif /* WOLFSSL_SHA3 */ default: - break; + break; } - return 0; + return ret; } @@ -458,10 +758,34 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) { int ret; -#ifdef HAVE_CAVIUM - if (hmac->magic == WOLFSSL_HMAC_CAVIUM_MAGIC) - return HmacCaviumFinal(hmac, hash); + if (hmac == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (hmac->devId != INVALID_DEVID) { + ret = wc_CryptoCb_Hmac(hmac, hmac->macType, NULL, 0, hash); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } #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, hash, hashLen); + #elif defined(HAVE_INTEL_QA) + if (IntelQaHmacGetType(hmac->macType, NULL) == 0) { + 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); @@ -470,377 +794,437 @@ 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 - - #ifndef NO_SHA256 - case SHA256: - { - ret = wc_Sha256Final(&hmac->hash.sha256, (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_Sha256Update(&hmac->hash.sha256, - (byte*) hmac->opad, SHA256_BLOCK_SIZE); + break; + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->opad, + WC_MD5_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha256Update(&hmac->hash.sha256, - (byte*) hmac->innerHash, SHA256_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) + break; + break; + #endif /* WOLFSSL_SHA224 */ + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_Sha256Final(&hmac->hash.sha256, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->opad, + WC_SHA256_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->innerHash, + WC_SHA256_DIGEST_SIZE); + if (ret != 0) + 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_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 */ + #ifdef WOLFSSL_SHA512 + 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 - case BLAKE2B_ID: - { - ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*) hmac->innerHash, - BLAKE2B_256); + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_SHA3_224: + ret = wc_Sha3_224_Final(&hmac->hash.sha3, (byte*)hmac->innerHash); if (ret != 0) - return ret; - - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, - (byte*) hmac->opad, BLAKE2B_BLOCKBYTES); + break; + ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->opad, + WC_SHA3_224_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, - (byte*) hmac->innerHash, BLAKE2B_256); + break; + ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->innerHash, + WC_SHA3_224_DIGEST_SIZE); if (ret != 0) - return ret; - - ret = wc_Blake2bFinal(&hmac->hash.blake2b, hash, BLAKE2B_256); + break; + ret = wc_Sha3_224_Final(&hmac->hash.sha3, hash); + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_SHA3_256: + ret = wc_Sha3_256_Final(&hmac->hash.sha3, (byte*)hmac->innerHash); if (ret != 0) - return ret; - } - break; - #endif + break; + ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->opad, + WC_SHA3_256_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->innerHash, + WC_SHA3_256_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_256_Final(&hmac->hash.sha3, hash); + break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case WC_SHA3_384: + ret = wc_Sha3_384_Final(&hmac->hash.sha3, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->opad, + WC_SHA3_384_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->innerHash, + WC_SHA3_384_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_384_Final(&hmac->hash.sha3, hash); + break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case WC_SHA3_512: + ret = wc_Sha3_512_Final(&hmac->hash.sha3, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->opad, + WC_SHA3_512_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->innerHash, + WC_SHA3_512_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_512_Final(&hmac->hash.sha3, hash); + break; + #endif + #endif /* WOLFSSL_SHA3 */ default: - break; + ret = BAD_FUNC_ARG; + break; } - hmac->innerHashKeyed = 0; + if (ret == 0) { + hmac->innerHashKeyed = 0; + } - return 0; + return ret; } -#ifdef HAVE_CAVIUM - -/* Initiliaze Hmac for use with Nitrox device */ -int wc_HmacInitCavium(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; - if (CspAllocContext(CONTEXT_SSL, &hmac->contextHandle, devId) != 0) - return -1; + XMEMSET(hmac, 0, sizeof(Hmac)); + hmac->macType = WC_HASH_TYPE_NONE; + hmac->heap = heap; +#ifdef WOLF_CRYPTO_CB + hmac->devId = devId; + hmac->devCtx = NULL; +#endif - hmac->keyLen = 0; - hmac->dataLen = 0; - hmac->type = 0; - hmac->devId = devId; - hmac->magic = WOLFSSL_HMAC_CAVIUM_MAGIC; - hmac->data = NULL; /* buffered input data */ - - hmac->innerHashKeyed = 0; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + ret = wolfAsync_DevCtxInit(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC, + hmac->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ - return 0; + return ret; } +#ifdef HAVE_PKCS11 +int wc_HmacInit_Id(Hmac* hmac, unsigned char* id, int len, void* heap, + int devId) +{ + int ret = 0; -/* Free Hmac from use with Nitrox device */ -void wc_HmacFreeCavium(Hmac* hmac) + if (hmac == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0 && (len < 0 || len > HMAC_MAX_ID_LEN)) + ret = BUFFER_E; + + if (ret == 0) + ret = wc_HmacInit(hmac, heap, devId); + if (ret == 0) { + XMEMCPY(hmac->id, id, len); + hmac->idLen = len; + } + + return ret; +} +#endif + +/* Free Hmac from use with async device */ +void wc_HmacFree(Hmac* hmac) { if (hmac == NULL) return; - CspFreeContext(CONTEXT_SSL, hmac->contextHandle, hmac->devId); - hmac->magic = 0; - XFREE(hmac->data, NULL, DYNAMIC_TYPE_CAVIUM_TMP); - hmac->data = NULL; +#ifdef WOLF_CRYPTO_CB + /* handle cleanup case where final is not called */ + if (hmac->devId != INVALID_DEVID && hmac->devCtx != NULL) { + int ret; + byte finalHash[WC_HMAC_BLOCK_SIZE]; + ret = wc_CryptoCb_Hmac(hmac, hmac->macType, NULL, 0, finalHash); + (void)ret; /* must ignore return code here */ + (void)finalHash; + } +#endif + + switch (hmac->macType) { + #ifndef NO_MD5 + case WC_MD5: + wc_Md5Free(&hmac->hash.md5); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + wc_ShaFree(&hmac->hash.sha); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + wc_Sha224Free(&hmac->hash.sha224); + break; + #endif /* WOLFSSL_SHA224 */ + #ifndef NO_SHA256 + case WC_SHA256: + wc_Sha256Free(&hmac->hash.sha256); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + wc_Sha384Free(&hmac->hash.sha384); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + wc_Sha512Free(&hmac->hash.sha512); + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_SHA3_224: + wc_Sha3_224_Free(&hmac->hash.sha3); + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_SHA3_256: + wc_Sha3_256_Free(&hmac->hash.sha3); + break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case WC_SHA3_384: + wc_Sha3_384_Free(&hmac->hash.sha3); + break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case WC_SHA3_512: + wc_Sha3_512_Free(&hmac->hash.sha3); + break; + #endif + #endif /* WOLFSSL_SHA3 */ + + default: + break; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + wolfAsync_DevCtxFree(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC); +#endif /* WOLFSSL_ASYNC_CRYPT */ + + switch (hmac->macType) { + #ifndef NO_MD5 + case WC_MD5: + wc_Md5Free(&hmac->hash.md5); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + wc_ShaFree(&hmac->hash.sha); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + wc_Sha224Free(&hmac->hash.sha224); + break; + #endif /* WOLFSSL_SHA224 */ + #ifndef NO_SHA256 + case WC_SHA256: + wc_Sha256Free(&hmac->hash.sha256); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + wc_Sha384Free(&hmac->hash.sha384); + break; + #endif /* WOLFSSL_SHA384 */ + case WC_SHA512: + wc_Sha512Free(&hmac->hash.sha512); + break; + #endif /* WOLFSSL_SHA512 */ + } } - -static void HmacCaviumFinal(Hmac* hmac, byte* hash) -{ - word32 requestId; - - if (CspHmac(CAVIUM_BLOCKING, hmac->type, NULL, hmac->keyLen, - (byte*)hmac->ipad, hmac->dataLen, hmac->data, hash, &requestId, - hmac->devId) != 0) { - WOLFSSL_MSG("Cavium Hmac failed"); - } - hmac->innerHashKeyed = 0; /* tell update to start over if used again */ -} - - -static void HmacCaviumUpdate(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; - } - - 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; - } - - tmp = XMALLOC(hmac->dataLen + add, NULL,DYNAMIC_TYPE_CAVIUM_TMP); - if (tmp == NULL) { - WOLFSSL_MSG("Out of memory for cavium update"); - return; - } - if (hmac->dataLen) - XMEMCPY(tmp, hmac->data, hmac->dataLen); - XMEMCPY(tmp + hmac->dataLen, msg, add); - - hmac->dataLen += add; - XFREE(hmac->data, NULL, DYNAMIC_TYPE_CAVIUM_TMP); - hmac->data = tmp; -} - - -static void HmacCaviumSetKey(Hmac* hmac, int type, const byte* key, - word32 length) -{ - hmac->macType = (byte)type; - if (type == MD5) - hmac->type = MD5_TYPE; - else if (type == SHA) - hmac->type = SHA1_TYPE; - else if (type == SHA256) - hmac->type = SHA256_TYPE; - else { - WOLFSSL_MSG("unsupported cavium hmac type"); - } - - hmac->innerHashKeyed = 0; /* should we key Startup flag */ - - hmac->keyLen = (word16)length; - /* store key in ipad */ - XMEMCPY(hmac->ipad, key, length); -} - -#endif /* HAVE_CAVIUM */ - int wolfSSL_GetHmacMaxSize(void) { - return MAX_DIGEST_SIZE; + return WC_MAX_DIGEST_SIZE; } #ifdef HAVE_HKDF - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) + /* 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) { - return a > b ? b : a; + byte tmp[WC_MAX_DIGEST_SIZE]; /* localSalt helper */ + Hmac myHmac; + int ret; + const byte* localSalt; /* either points to user input or tmp */ + int hashSz; + + ret = wc_HmacSizeByType(type); + if (ret < 0) + return ret; + + hashSz = ret; + localSalt = salt; + if (localSalt == NULL) { + XMEMSET(tmp, 0, hashSz); + localSalt = tmp; + saltSz = hashSz; + } + + 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); + } + + return ret; } -#endif /* WOLFSSL_HAVE_MIN */ + /* 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[WC_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; -static INLINE int GetHashSizeByType(int type) -{ - if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 - || type == SHA512 || type == BLAKE2B_ID)) - return BAD_FUNC_ARG; - - switch (type) { - #ifndef NO_MD5 - case MD5: - return MD5_DIGEST_SIZE; - break; - #endif - - #ifndef NO_SHA - case SHA: - return SHA_DIGEST_SIZE; - break; - #endif - - #ifndef NO_SHA256 - case SHA256: - return SHA256_DIGEST_SIZE; - break; - #endif - - #ifdef WOLFSSL_SHA384 - case SHA384: - return SHA384_DIGEST_SIZE; - break; - #endif - - #ifdef WOLFSSL_SHA512 - case SHA512: - return SHA512_DIGEST_SIZE; - break; - #endif - - #ifdef HAVE_BLAKE2 - case BLAKE2B_ID: - return BLAKE2B_OUTBYTES; - break; - #endif - - default: - return BAD_FUNC_ARG; - break; - } -} - - -/* 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 = GetHashSizeByType(type); - word32 outIdx = 0; - byte n = 0x1; - int ret; - - if (hashSz < 0) - return BAD_FUNC_ARG; - -#ifdef WOLFSSL_SMALL_STACK - tmp = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) - return MEMORY_E; - - 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; - } - - 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); - - 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); @@ -856,24 +1240,51 @@ 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[WC_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 */ #endif /* HAVE_FIPS */ #endif /* NO_HMAC */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/idea.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/idea.c new file mode 100644 index 000000000..600c90654 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/idea.c @@ -0,0 +1,303 @@ +/* idea.c + * + * Copyright (C) 2006-2020 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 HAVE_IDEA + +#include + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* multiplication of x and y modulo 2^16+1 + * IDEA specify a special case when an entry value is 0 ( x or y) + * then it must be replaced by 2^16 + */ +static WC_INLINE word16 idea_mult(word16 x, word16 y) +{ + long mul, res; + + mul = (long)x * (long)y; + if (mul) { + res = (mul & IDEA_MASK) - ((word32)mul >> 16); + if (res <= 0) + res += IDEA_MODULO; + + return (word16) (res & IDEA_MASK); + } + + if (!x) + return ((IDEA_MODULO - y) & IDEA_MASK); + + /* !y */ + return ((IDEA_MODULO - x) & IDEA_MASK); +} + +/* compute 1/a modulo 2^16+1 using Extended euclidean algorithm + * adapted from fp_invmod */ +static WC_INLINE word16 idea_invmod(word16 x) +{ + int u, v, b, d; + + if (x <= 1) + return x; + + u = IDEA_MODULO; + v = x; + d = 1; + b = 0; + + do { + while (!(u & 1)) { + u >>= 1; + if (b & 1) + b -= IDEA_MODULO; + b >>= 1; + } + + while (!(v & 1)) { + v >>= 1; + if (d & 1) { + d -= IDEA_MODULO; + } + d >>= 1; + } + + if (u >= v) { + u -= v; + b -= d; + } else { + v -= u; + d -= b; + } + } while (u != 0); + + /* d is now the inverse, put positive value if required */ + while (d < 0) + d += IDEA_MODULO; + + /* d must be < IDEA_MODULO */ + while (d >= (int)IDEA_MODULO) + d -= IDEA_MODULO; + + return (word16)(d & IDEA_MASK); +} + +/* generate the 52 16-bits key sub-blocks from the 128 key */ +int wc_IdeaSetKey(Idea *idea, const byte* key, word16 keySz, + const byte *iv, int dir) +{ + word16 idx = 0; + word32 t; + short i; + + if (idea == NULL || key == NULL || keySz != IDEA_KEY_SIZE || + (dir != IDEA_ENCRYPTION && dir != IDEA_DECRYPTION)) + return BAD_FUNC_ARG; + + /* initial key schedule for 0 -> 7 */ + for (i = 0; i < IDEA_ROUNDS; i++) { + idea->skey[i] = (word16)key[idx++] << 8; + idea->skey[i] |= (word16)key[idx++]; + } + + /* shift phase key schedule for 8 -> 51 */ + for (i = IDEA_ROUNDS; i < IDEA_SK_NUM; i++) { + t = (word32)idea->skey[((i+1) & 7) ? i-7 : i-15] << 9; + t |= (word32)idea->skey[((i+2) & 7) < 2 ? i-14 : i-6] >> 7; + idea->skey[i] = (word16)(t & IDEA_MASK); + } + + /* compute decryption key from encryption key */ + if (dir == IDEA_DECRYPTION) { + word16 enckey[IDEA_SK_NUM]; + + /* put encryption key in tmp buffer */ + XMEMCPY(enckey, idea->skey, sizeof(idea->skey)); + + idx = 0; + + idea->skey[6*IDEA_ROUNDS] = idea_invmod(enckey[idx++]); + idea->skey[6*IDEA_ROUNDS+1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; + idea->skey[6*IDEA_ROUNDS+2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; + idea->skey[6*IDEA_ROUNDS+3] = idea_invmod(enckey[idx++]); + + for (i = 6*(IDEA_ROUNDS-1); i >= 0; i -= 6) { + idea->skey[i+4] = enckey[idx++]; + idea->skey[i+5] = enckey[idx++]; + + idea->skey[i] = idea_invmod(enckey[idx++]); + if (i) { + idea->skey[i+2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; + idea->skey[i+1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; + } + else { + idea->skey[1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; + idea->skey[2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; + } + + idea->skey[i+3] = idea_invmod(enckey[idx++]); + } + + /* erase temporary buffer */ + ForceZero(enckey, sizeof(enckey)); + } + + /* set the iv */ + return wc_IdeaSetIV(idea, iv); +} + +/* set the IV in the Idea key structure */ +int wc_IdeaSetIV(Idea *idea, const byte* iv) +{ + if (idea == NULL) + return BAD_FUNC_ARG; + + if (iv != NULL) + XMEMCPY(idea->reg, iv, IDEA_BLOCK_SIZE); + else + XMEMSET(idea->reg, 0, IDEA_BLOCK_SIZE); + + return 0; +} + +/* encryption/decryption for a block (64 bits) + */ +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; + x[i] |= (word16)in[idx++]; + } + + for (i = 0; i < IDEA_ROUNDS; i++) { + x[0] = idea_mult(x[0], idea->skey[skey_idx++]); + x[1] = ((word32)x[1] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; + x[2] = ((word32)x[2] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; + x[3] = idea_mult(x[3], idea->skey[skey_idx++]); + + t2 = x[0] ^ x[2]; + t2 = idea_mult((word16)t2, idea->skey[skey_idx++]); + t1 = (t2 + (x[1] ^ x[3])) & IDEA_MASK; + t1 = idea_mult((word16)t1, idea->skey[skey_idx++]); + t2 = (t1 + t2) & IDEA_MASK; + + x[0] ^= t1; + x[3] ^= t2; + + t2 ^= x[1]; + x[1] = x[2] ^ (word16)t1; + x[2] = (word16)t2; + } + + x[0] = idea_mult(x[0], idea->skey[skey_idx++]); + out[0] = (x[0] >> 8) & 0xFF; + out[1] = x[0] & 0xFF; + + x[2] = ((word32)x[2] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; + out[2] = (x[2] >> 8) & 0xFF; + out[3] = x[2] & 0xFF; + + x[1] = ((word32)x[1] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; + out[4] = (x[1] >> 8) & 0xFF; + out[5] = x[1] & 0xFF; + + 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; + + blocks = len / IDEA_BLOCK_SIZE; + while (blocks--) { + xorbuf((byte*)idea->reg, in, IDEA_BLOCK_SIZE); + 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; + in += IDEA_BLOCK_SIZE; + } + + return 0; +} + +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; + + blocks = len / IDEA_BLOCK_SIZE; + while (blocks--) { + XMEMCPY((byte*)idea->tmp, in, IDEA_BLOCK_SIZE); + 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); + + out += IDEA_BLOCK_SIZE; + in += IDEA_BLOCK_SIZE; + } + + return 0; +} + +#endif /* HAVE_IDEA */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/include.am b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/include.am index 299921579..bba761bc1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/include.am @@ -1,9 +1,13 @@ # vim:ft=automake # All paths should be given relative to the root +EXTRA_DIST += src/bio.c EXTRA_DIST += wolfcrypt/src/misc.c +EXTRA_DIST += wolfcrypt/src/evp.c EXTRA_DIST += wolfcrypt/src/asm.c EXTRA_DIST += wolfcrypt/src/aes_asm.asm +EXTRA_DIST += wolfcrypt/src/wc_dsp.c +EXTRA_DIST += wolfcrypt/src/sp_dsp32.c EXTRA_DIST += \ wolfcrypt/src/ecc_fp.c \ @@ -37,12 +41,87 @@ 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 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/arm/armv8-chacha.c \ + wolfcrypt/src/port/arm/armv8-curve25519.c \ + wolfcrypt/src/port/arm/armv8-32-curve25519.c \ + wolfcrypt/src/port/arm/armv8-sha512-asm.c \ + wolfcrypt/src/port/arm/armv8-32-sha512-asm.c \ + wolfcrypt/src/port/nxp/ksdk_port.c \ + wolfcrypt/src/port/atmel/README.md \ + wolfcrypt/src/port/xilinx/xil-sha3.c \ + wolfcrypt/src/port/xilinx/xil-aesgcm.c \ + wolfcrypt/src/port/caam/caam_aes.c \ + wolfcrypt/src/port/caam/caam_driver.c \ + wolfcrypt/src/port/caam/caam_init.c \ + wolfcrypt/src/port/caam/caam_sha.c \ + wolfcrypt/src/port/caam/caam_doc.pdf \ + wolfcrypt/src/port/st/stm32.c \ + wolfcrypt/src/port/st/stsafe.c \ + wolfcrypt/src/port/st/README.md \ + wolfcrypt/src/port/af_alg/afalg_aes.c \ + wolfcrypt/src/port/af_alg/afalg_hash.c \ + wolfcrypt/src/port/devcrypto/devcrypto_hash.c \ + wolfcrypt/src/port/devcrypto/wc_devcrypto.c \ + wolfcrypt/src/port/devcrypto/README.md \ + wolfcrypt/src/port/mynewt/mynewt_port.c \ + wolfcrypt/src/port/Espressif/esp32_aes.c \ + wolfcrypt/src/port/Espressif/esp32_sha.c \ + wolfcrypt/src/port/Espressif/esp32_util.c \ + wolfcrypt/src/port/Espressif/esp32_mp.c \ + wolfcrypt/src/port/Espressif/README.md \ + wolfcrypt/src/port/arm/cryptoCell.c \ + wolfcrypt/src/port/arm/cryptoCellHash.c \ + wolfcrypt/src/port/Renesas/renesas_tsip_aes.c \ + wolfcrypt/src/port/Renesas/renesas_tsip_sha.c \ + wolfcrypt/src/port/Renesas/renesas_tsip_util.c \ + wolfcrypt/src/port/Renesas/README.md +if BUILD_CRYPTOCB +src_libwolfssl_la_SOURCES += wolfcrypt/src/cryptocb.c +endif + +if BUILD_PKCS11 +src_libwolfssl_la_SOURCES += wolfcrypt/src/wc_pkcs11.c +endif + +if BUILD_DEVCRYPTO +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/devcrypto/devcrypto_hash.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/devcrypto/devcrypto_aes.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/devcrypto/wc_devcrypto.c +endif + +if BUILD_CAVIUM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/cavium/cavium_nitrox.c +endif +EXTRA_DIST += wolfcrypt/src/port/cavium/README.md + +if BUILD_OCTEON_SYNC +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/cavium/cavium_octeon_sync.c +endif +EXTRA_DIST += wolfcrypt/src/port/cavium/README_Octeon.md + +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 +endif +EXTRA_DIST += wolfcrypt/src/port/intel/README.md + +if BUILD_INTEL_QA_SYNC +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/intel/quickassist_sync.c +endif + +if BUILD_CRYPTOAUTHLIB +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/atmel/atmel.c +endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/integer.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/integer.c index b3ce4203e..56d684b46 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/integer.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/integer.c @@ -1,8 +1,8 @@ /* integer.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* * Based on public domain LibTomMath 0.38 by Tom St Denis, tomstdenis@iahu.ca, * http://math.libtomcrypt.com @@ -33,19 +34,70 @@ /* in case user set USE_FAST_MATH there */ #include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + #ifndef NO_BIG_INT #ifndef USE_FAST_MATH +#ifndef WOLFSSL_SP_MATH + #include -#ifndef NO_WOLFSSL_SMALL_STACK - #ifndef WOLFSSL_SMALL_STACK - #define WOLFSSL_SMALL_STACK +#if defined(FREESCALE_LTC_TFM) + #include +#endif +#ifdef WOLFSSL_DEBUG_MATH + #include +#endif + +#ifdef SHOW_GEN + #ifndef NO_STDIO_FILESYSTEM + #include #endif #endif -static void bn_reverse (unsigned char *s, int len); +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifdef __cplusplus + extern "C" { +#endif +WOLFSSL_LOCAL int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +#ifdef __cplusplus + } /* extern "C" */ +#endif +#endif + +/* reverse an array, used for radix code */ +static void +bn_reverse (unsigned char *s, int len) +{ + int ix, iy; + unsigned char t; + + ix = 0; + iy = len - 1; + while (ix < iy) { + t = s[ix]; + s[ix] = s[iy]; + s[iy] = t; + ++ix; + --iy; + } +} /* math settings check */ word32 CheckRunTimeSettings(void) @@ -60,6 +112,13 @@ int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, { int res = MP_OKAY; + if (a) XMEMSET(a, 0, sizeof(mp_int)); + if (b) XMEMSET(b, 0, sizeof(mp_int)); + if (c) XMEMSET(c, 0, sizeof(mp_int)); + if (d) XMEMSET(d, 0, sizeof(mp_int)); + if (e) XMEMSET(e, 0, sizeof(mp_int)); + if (f) XMEMSET(f, 0, sizeof(mp_int)); + if (a && ((res = mp_init(a)) != MP_OKAY)) return res; @@ -95,33 +154,28 @@ 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; } /* clear one (frees) */ -void -mp_clear (mp_int * a) +void mp_clear (mp_int * a) { int i; @@ -136,15 +190,52 @@ 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) + return; + + /* only do anything if a hasn't been freed previously */ + 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 */ + mp_free(a); + + /* reset members to make debugging easier */ + a->alloc = a->used = 0; + a->sign = MP_ZPOS; + } + + a->sign = MP_ZPOS; + a->used = 0; +} + /* get the size for an unsigned equivalent */ int mp_unsigned_bin_size (mp_int * a) @@ -155,8 +246,7 @@ int mp_unsigned_bin_size (mp_int * a) /* returns the number of bits in an int */ -int -mp_count_bits (mp_int * a) +int mp_count_bits (mp_int * a) { int r; mp_digit q; @@ -187,11 +277,11 @@ int mp_leading_bit (mp_int * a) if (mp_init_copy(&t, a) != MP_OKAY) return 0; - while (mp_iszero(&t) == 0) { + while (mp_iszero(&t) == MP_NO) { #ifndef MP_8BIT bit = (t.dp[0] & 0x80) != 0; #else - bit = (t.dp[0] | ((t.dp[1] & 0x01) << 7)) & 0x80 != 0; + bit = ((t.dp[0] | ((t.dp[1] & 0x01) << 7)) & 0x80) != 0; #endif if (mp_div_2d (&t, 8, &t, NULL) != MP_OKAY) break; @@ -200,6 +290,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) @@ -211,49 +317,62 @@ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) return res; } - x = 0; - while (mp_iszero (&t) == 0) { -#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; } +int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c) +{ + int i, len; + + len = mp_unsigned_bin_size(a); + + /* pad front w/ zeros to match length */ + for (i = 0; i < c - len; i++) + b[i] = 0x00; + return mp_to_unsigned_bin(a, b + i); +} /* creates "a" then copies b into it */ 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; } /* copy, b = a */ -int -mp_copy (mp_int * a, mp_int * b) +int mp_copy (mp_int * a, mp_int * b) { int res, n; + /* Safeguard against passing in a null pointer */ + if (a == NULL || b == NULL) + return MP_VAL; + /* if dst == src do nothing */ if (a == b) { return MP_OKAY; } /* 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; } @@ -261,7 +380,7 @@ mp_copy (mp_int * a, mp_int * b) /* zero b and copy the parameters over */ { - register mp_digit *tmpa, *tmpb; + mp_digit *tmpa, *tmpb; /* pointer aliases */ @@ -277,7 +396,7 @@ 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; } } @@ -296,7 +415,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); @@ -306,8 +425,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; @@ -327,25 +446,6 @@ int mp_grow (mp_int * a, int size) } -/* reverse an array, used for radix code */ -void -bn_reverse (unsigned char *s, int len) -{ - int ix, iy; - unsigned char t; - - ix = 0; - iy = len - 1; - while (ix < iy) { - t = s[ix]; - s[ix] = s[iy]; - s[iy] = t; - ++ix; - --iy; - } -} - - /* shift right by a certain bit count (store quotient in c, optional remainder in d) */ int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) @@ -406,6 +506,9 @@ void mp_zero (mp_int * a) int n; mp_digit *tmp; + if (a == NULL) + return; + a->sign = MP_ZPOS; a->used = 0; @@ -419,12 +522,11 @@ void mp_zero (mp_int * a) /* trim unused digits * * This is used to ensure that leading zero digits are - * trimed and the leading "used" digit will be non-zero + * trimmed and the leading "used" digit will be non-zero * Typically very fast. Also fixes the sign if there * are no more leading digits */ -void -mp_clamp (mp_int * a) +void mp_clamp (mp_int * a) { /* decrease used while the most significant digit is * zero. @@ -443,8 +545,7 @@ mp_clamp (mp_int * a) /* swap the elements of two integers, for cases where you can't simply swap the * mp_int pointers around */ -void -mp_exch (mp_int * a, mp_int * b) +void mp_exch (mp_int * a, mp_int * b) { mp_int t; @@ -457,10 +558,12 @@ mp_exch (mp_int * a, mp_int * b) /* shift right a certain number of bits */ void mp_rshb (mp_int *c, int x) { - register mp_digit *tmpc, mask, shift; + mp_digit *tmpc, mask, shift; mp_digit r, rr; mp_digit D = x; + if (mp_iszero(c)) return; + /* mask */ mask = (((mp_digit)1) << D) - 1; @@ -483,6 +586,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); } @@ -503,7 +607,7 @@ void mp_rshd (mp_int * a, int b) } { - register mp_digit *bottom, *top; + mp_digit *bottom, *top; /* shift the digits down */ @@ -539,8 +643,7 @@ void mp_rshd (mp_int * a, int b) /* calc a value mod 2**b */ -int -mp_mod_2d (mp_int * a, int b, mp_int * c) +int mp_mod_2d (mp_int * a, int b, mp_int * c) { int x, res; @@ -637,8 +740,8 @@ int mp_mul_2d (mp_int * a, int b, mp_int * c) /* shift any bit count < DIGIT_BIT */ d = (mp_digit) (b % DIGIT_BIT); if (d != 0) { - register mp_digit *tmpc, shift, mask, r, rr; - register int x; + mp_digit *tmpc, shift, mask, r, rr; + int x; /* bitmask for carries */ mask = (((mp_digit)1) << d) - 1; @@ -656,7 +759,7 @@ int mp_mul_2d (mp_int * a, int b, mp_int * c) rr = (*tmpc >> shift) & mask; /* shift the current word and OR in the carry */ - *tmpc = ((*tmpc << d) | r) & MP_MASK; + *tmpc = (mp_digit)(((*tmpc << d) | r) & MP_MASK); ++tmpc; /* set the carry to the carry bits of the current word */ @@ -691,7 +794,7 @@ int mp_lshd (mp_int * a, int b) } { - register mp_digit *top, *bottom; + mp_digit *top, *bottom; /* increment the used by the shift amount then copy upwards */ a->used += b; @@ -703,7 +806,7 @@ int mp_lshd (mp_int * a, int b) bottom = a->dp + a->used - 1 - b; /* much like mp_rshd this is implemented using a sliding window - * except the window goes the otherway around. Copying from + * except the window goes the other way around. Copying from * the bottom to the top. see bn_mp_rshd.c for more info. */ for (x = a->used - 1; x >= b; x--) { @@ -722,17 +825,33 @@ int mp_lshd (mp_int * a, int b) /* this is a shell function that calls either the normal or Montgomery * exptmod functions. Originally the call to the montgomery code was - * embedded in the normal function but that wasted alot of stack space + * 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; /* modulus P must be positive */ - if (P->sign == MP_NEG) { + if (mp_iszero(P) || P->sign == MP_NEG) { return MP_VAL; } + if (mp_isone(P)) { + mp_set(Y, 0); + return MP_OKAY; + } + if (mp_iszero(X)) { + mp_set(Y, 1); + return MP_OKAY; + } + if (mp_iszero(G)) { + mp_set(Y, 0); + return MP_OKAY; + } /* if exponent X is negative we have to recurse */ if (X->sign == MP_NEG) { @@ -771,6 +890,12 @@ int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) #endif } +#ifdef BN_MP_EXPTMOD_BASE_2 + if (G->used == 1 && G->dp[0] == 2) { + return mp_exptmod_base_2(X, P, Y); + } +#endif + /* modified diminished radix reduction */ #if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && \ defined(BN_S_MP_EXPTMOD_C) @@ -787,6 +912,8 @@ int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) dr = 0; #endif + (void)dr; + #ifdef BN_MP_REDUCE_IS_2K_C /* if not, is it a unrestricted DR modulus? */ if (dr == 0) { @@ -796,7 +923,7 @@ int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) /* if the modulus is odd or dr != 0 use the montgomery method */ #ifdef BN_MP_EXPTMOD_FAST_C - if (mp_isodd (P) == 1 || dr != 0) { + if (mp_isodd (P) == MP_YES || dr != 0) { return mp_exptmod_fast (G, X, P, Y, dr); } else { #endif @@ -812,13 +939,17 @@ int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) #endif } +int mp_exptmod_ex (mp_int * G, mp_int * X, int digits, mp_int * P, mp_int * Y) +{ + (void)digits; + return mp_exptmod(G, X, P, Y); +} /* b = |a| * * Simple function copies the input and fixes the sign to positive */ -int -mp_abs (mp_int * a, mp_int * b) +int mp_abs (mp_int * a, mp_int * b) { int res; @@ -837,22 +968,28 @@ 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) == 1) { + /* b cannot be negative or zero, and can not divide by 0 (1/a mod b) */ + if (b->sign == MP_NEG || mp_iszero(b) == MP_YES || mp_iszero(a) == MP_YES) { return MP_VAL; } #ifdef BN_FAST_MP_INVMOD_C /* if the modulus is odd we can use a faster routine instead */ - if (mp_isodd (b) == 1) { + 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 } @@ -869,7 +1006,7 @@ int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) int res, neg, loop_check = 0; /* 2. [modified] b must be odd */ - if (mp_iseven (b) == 1) { + if (mp_iseven (b) == MP_YES) { return MP_VAL; } @@ -895,17 +1032,19 @@ 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 */ - while (mp_iseven (&u) == 1) { + while (mp_iseven (&u) == MP_YES) { /* 4.1 u = u/2 */ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { goto LBL_ERR; } /* 4.2 if B is odd then */ - if (mp_isodd (&B) == 1) { + if (mp_isodd (&B) == MP_YES) { if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { goto LBL_ERR; } @@ -917,13 +1056,13 @@ top: } /* 5. while v is even do */ - while (mp_iseven (&v) == 1) { + while (mp_iseven (&v) == MP_YES) { /* 5.1 v = v/2 */ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { goto LBL_ERR; } /* 5.2 if D is odd then */ - if (mp_isodd (&D) == 1) { + if (mp_isodd (&D) == MP_YES) { /* D = (D-x)/2 */ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { goto LBL_ERR; @@ -957,8 +1096,8 @@ top: } /* if not zero goto step 4 */ - if (mp_iszero (&u) == 0) { - if (++loop_check > 1024) { + if (mp_iszero (&u) == MP_NO) { + if (++loop_check > MAX_INVMOD_SZ) { res = MP_VAL; goto LBL_ERR; } @@ -980,6 +1119,12 @@ top: goto LBL_ERR; } } + /* too big */ + while (mp_cmp_mag(&D, b) != MP_LT) { + if ((res = mp_sub(&D, b, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } mp_exch (&D, c); c->sign = neg; res = MP_OKAY; @@ -1001,31 +1146,42 @@ int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) int res; /* b cannot be negative */ - if (b->sign == MP_NEG || mp_iszero(b) == 1) { + if (b->sign == MP_NEG || mp_iszero(b) == MP_YES) { return MP_VAL; } /* init temps */ if ((res = mp_init_multi(&x, &y, &u, &v, &A, &B)) != MP_OKAY) { - return res; + return res; } /* init rest of tmps temps */ if ((res = mp_init_multi(&C, &D, 0, 0, 0, 0)) != MP_OKAY) { - return res; + mp_clear(&x); + mp_clear(&y); + mp_clear(&u); + mp_clear(&v); + mp_clear(&A); + mp_clear(&B); + return res; } /* x = a, y = b */ if ((res = mp_mod(a, b, &x)) != MP_OKAY) { - goto LBL_ERR; + goto LBL_ERR; + } + if (mp_isone(&x)) { + mp_set(c, 1); + res = MP_OKAY; + goto LBL_ERR; } if ((res = mp_copy (b, &y)) != MP_OKAY) { goto LBL_ERR; } /* 2. [modified] if x,y are both even then return an error! */ - if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { + if (mp_iseven (&x) == MP_YES && mp_iseven (&y) == MP_YES) { res = MP_VAL; goto LBL_ERR; } @@ -1037,24 +1193,28 @@ 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 */ - while (mp_iseven (&u) == 1) { + while (mp_iseven (&u) == MP_YES) { /* 4.1 u = u/2 */ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { goto LBL_ERR; } /* 4.2 if A or B is odd then */ - if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) { + if (mp_isodd (&A) == MP_YES || mp_isodd (&B) == MP_YES) { /* A = (A+y)/2, B = (B-x)/2 */ if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { - goto LBL_ERR; + goto LBL_ERR; } if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { - goto LBL_ERR; + goto LBL_ERR; } } /* A = A/2, B = B/2 */ @@ -1067,19 +1227,19 @@ top: } /* 5. while v is even do */ - while (mp_iseven (&v) == 1) { + while (mp_iseven (&v) == MP_YES) { /* 5.1 v = v/2 */ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { goto LBL_ERR; } /* 5.2 if C or D is odd then */ - if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) { + if (mp_isodd (&C) == MP_YES || mp_isodd (&D) == MP_YES) { /* C = (C+y)/2, D = (D-x)/2 */ if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { - goto LBL_ERR; + goto LBL_ERR; } if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { - goto LBL_ERR; + goto LBL_ERR; } } /* C = C/2, D = D/2 */ @@ -1121,7 +1281,7 @@ top: } /* if not zero goto step 4 */ - if (mp_iszero (&u) == 0) + if (mp_iszero (&u) == MP_NO) goto top; /* now a = C, b = D, gcd == g*v */ @@ -1161,7 +1321,7 @@ LBL_ERR:mp_clear(&x); } -/* compare maginitude of two ints (unsigned) */ +/* compare magnitude of two ints (unsigned) */ int mp_cmp_mag (mp_int * a, mp_int * b) { int n; @@ -1197,8 +1357,7 @@ int mp_cmp_mag (mp_int * a, mp_int * b) /* compare two ints (signed)*/ -int -mp_cmp (mp_int * a, mp_int * b) +int mp_cmp (mp_int * a, mp_int * b) { /* compare based on sign */ if (a->sign != b->sign) { @@ -1222,8 +1381,12 @@ 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; } @@ -1244,22 +1407,38 @@ 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] = 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; } +/* check if a bit is set */ +int mp_is_bit_set (mp_int *a, mp_digit b) +{ + if ((mp_digit)a->used < b/DIGIT_BIT) + return 0; + + return (int)((a->dp[b/DIGIT_BIT] >> b%DIGIT_BIT) & (mp_digit)1); +} /* c = a mod b, 0 <= c < b */ -int -mp_mod (mp_int * a, mp_int * b, mp_int * c) +#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; } @@ -1268,11 +1447,11 @@ 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); @@ -1287,7 +1466,7 @@ int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) int res, n, n2; /* is divisor zero ? */ - if (mp_iszero (b) == 1) { + if (mp_iszero (b) == MP_YES) { return MP_VAL; } @@ -1309,8 +1488,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) || @@ -1367,7 +1547,7 @@ int mp_div_2(mp_int * a, mp_int * b) oldused = b->used; b->used = a->used; { - register mp_digit r, rr, *tmpa, *tmpb; + mp_digit r, rr, *tmpa, *tmpb; /* source alias */ tmpa = a->dp + b->used - 1; @@ -1403,7 +1583,7 @@ int mp_div_2(mp_int * a, mp_int * b) /* high level addition (handles signs) */ int mp_add (mp_int * a, mp_int * b, mp_int * c) { - int sa, sb, res; + int sa, sb, res; /* get sign of both inputs */ sa = a->sign; @@ -1433,39 +1613,38 @@ int mp_add (mp_int * a, mp_int * b, mp_int * c) /* low level addition, based on HAC pp.594, Algorithm 14.7 */ -int -s_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; { - register mp_digit u, *tmpa, *tmpb, *tmpc; - register int i; + mp_digit u, *tmpa, *tmpb, *tmpc; + int i; /* alias for digit pointers */ @@ -1480,7 +1659,7 @@ 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; @@ -1494,8 +1673,8 @@ 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; @@ -1510,7 +1689,7 @@ s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* add carry */ *tmpc++ = u; - /* clear digits above oldused */ + /* clear digits above olduse */ for (i = c->used; i < olduse; i++) { *tmpc++ = 0; } @@ -1522,27 +1701,31 @@ 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 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; { - register mp_digit u, *tmpa, *tmpb, *tmpc; - register int i; + mp_digit u, *tmpa, *tmpb, *tmpc; + int i; /* alias for digit pointers */ tmpa = a->dp; @@ -1551,7 +1734,7 @@ 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; @@ -1567,7 +1750,7 @@ 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; @@ -1590,8 +1773,7 @@ s_mp_sub (mp_int * a, mp_int * b, mp_int * c) /* high level subtraction (handles signs) */ -int -mp_sub (mp_int * a, mp_int * b, mp_int * c) +int mp_sub (mp_int * a, mp_int * b, mp_int * c) { int sa, sb, res; @@ -1725,7 +1907,7 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, mp_digit buf, mp; int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; #ifdef WOLFSSL_SMALL_STACK - mp_int* M = NULL; + mp_int* M; #else mp_int M[TAB_SIZE]; #endif @@ -1733,11 +1915,11 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, * one of many reduction algorithms without modding the guts of * the code with if statements everywhere. */ - int (*redux)(mp_int*,mp_int*,mp_digit); + int (*redux)(mp_int*,mp_int*,mp_digit) = NULL; #ifdef WOLFSSL_SMALL_STACK M = (mp_int*) XMALLOC(sizeof(mp_int) * TAB_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_BIGINT); if (M == NULL) return MP_MEM; #endif @@ -1768,9 +1950,9 @@ 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); + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); #endif return err; @@ -1778,14 +1960,14 @@ 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]); } mp_clear(&M[1]); #ifdef WOLFSSL_SMALL_STACK - XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); #endif return err; @@ -1807,7 +1989,7 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, /* automatically pick the comba one if available (saves quite a few calls/ifs) */ #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C - if (((P->used * 2 + 1) < MP_WARRAY) && + if (((P->used * 2 + 1) < (int)MP_WARRAY) && P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { redux = fast_mp_montgomery_reduce; } else @@ -1816,9 +1998,6 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, #ifdef BN_MP_MONTGOMERY_REDUCE_C /* use slower baseline Montgomery method */ redux = mp_montgomery_reduce; -#else - err = MP_VAL; - goto LBL_M; #endif } } else if (redmode == 1) { @@ -1826,9 +2005,6 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, /* setup DR reduction for moduli of the form B**k - b */ mp_dr_setup(P, &mp); redux = mp_dr_reduce; -#else - err = MP_VAL; - goto LBL_M; #endif } else { #if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C) @@ -1837,14 +2013,16 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, goto LBL_M; } redux = mp_reduce_2k; -#else - err = MP_VAL; - goto LBL_M; #endif } + if (redux == NULL) { + err = MP_VAL; + goto LBL_M; + } + /* setup result */ - if ((err = mp_init (&res)) != MP_OKAY) { + if ((err = mp_init_size (&res, P->alloc)) != MP_OKAY) { goto LBL_M; } @@ -1861,17 +2039,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; } @@ -1883,7 +2063,8 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, } for (x = 0; x < (winsize - 1); x++) { - if ((err = mp_sqr (&M[(mp_digit)(1 << (winsize - 1))], &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) { + if ((err = mp_sqr (&M[(mp_digit)(1 << (winsize - 1))], + &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&M[(mp_digit)(1 << (winsize - 1))], P, mp)) != MP_OKAY) { @@ -2024,16 +2205,179 @@ LBL_M: } #ifdef WOLFSSL_SMALL_STACK - XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); #endif return err; } +#ifdef BN_MP_EXPTMOD_BASE_2 +#if DIGIT_BIT < 16 + #define WINSIZE 3 +#elif DIGIT_BIT < 32 + #define WINSIZE 4 +#elif DIGIT_BIT < 64 + #define WINSIZE 5 +#elif DIGIT_BIT < 128 + #define WINSIZE 6 +#endif +int mp_exptmod_base_2(mp_int * X, mp_int * P, mp_int * Y) +{ + mp_digit buf, mp; + int err = MP_OKAY, bitbuf, bitcpy, bitcnt, digidx, x, y; +#ifdef WOLFSSL_SMALL_STACK + mp_int *res = NULL; +#else + mp_int res[1]; +#endif + int (*redux)(mp_int*,mp_int*,mp_digit) = NULL; + + /* automatically pick the comba one if available (saves quite a few + calls/ifs) */ +#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C + if (((P->used * 2 + 1) < (int)MP_WARRAY) && + P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + redux = fast_mp_montgomery_reduce; + } else +#endif + { +#ifdef BN_MP_MONTGOMERY_REDUCE_C + /* use slower baseline Montgomery method */ + redux = mp_montgomery_reduce; +#else + return MP_VAL; +#endif + } + +#ifdef WOLFSSL_SMALL_STACK + res = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (res == NULL) { + return MP_MEM; + } +#endif + + /* now setup montgomery */ + if ((err = mp_montgomery_setup(P, &mp)) != MP_OKAY) { + goto LBL_M; + } + + /* setup result */ + if ((err = mp_init(res)) != MP_OKAY) { + goto LBL_M; + } + + /* now we need R mod m */ + if ((err = mp_montgomery_calc_normalization(res, P)) != MP_OKAY) { + goto LBL_RES; + } + + /* Get the top bits left over after taking WINSIZE bits starting at the + * least-significant. + */ + digidx = X->used - 1; + bitcpy = (X->used * DIGIT_BIT) % WINSIZE; + if (bitcpy > 0) { + bitcnt = (int)DIGIT_BIT - bitcpy; + buf = X->dp[digidx--]; + bitbuf = (int)(buf >> bitcnt); + /* Multiply montgomery representation of 1 by 2 ^ top */ + err = mp_mul_2d(res, bitbuf, res); + if (err != MP_OKAY) { + goto LBL_RES; + } + err = mp_mod(res, P, res); + if (err != MP_OKAY) { + goto LBL_RES; + } + /* Move out bits used */ + buf <<= bitcpy; + bitcnt++; + } + else { + bitcnt = 1; + buf = 0; + } + + /* empty window and reset */ + bitbuf = 0; + bitcpy = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (int)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= (mp_digit)1; + /* add bit to the window */ + bitbuf |= (y << (WINSIZE - ++bitcpy)); + + if (bitcpy == WINSIZE) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < WINSIZE; x++) { + err = mp_sqr(res, res); + if (err != MP_OKAY) { + goto LBL_RES; + } + err = (*redux)(res, P, mp); + if (err != MP_OKAY) { + goto LBL_RES; + } + } + + /* then multiply by 2^bitbuf */ + err = mp_mul_2d(res, bitbuf, res); + if (err != MP_OKAY) { + goto LBL_RES; + } + err = mp_mod(res, P, res); + if (err != MP_OKAY) { + goto LBL_RES; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + } + } + + /* fixup result if Montgomery reduction is used + * recall that any value in a Montgomery system is + * actually multiplied by R mod n. So we have + * to reduce one more time to cancel out the factor + * of R. + */ + err = (*redux)(res, P, mp); + if (err != MP_OKAY) { + goto LBL_RES; + } + + /* swap res with Y */ + mp_copy(res, Y); + +LBL_RES:mp_clear (res); +LBL_M: +#ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; +} + +#undef WINSIZE +#endif /* BN_MP_EXPTMOD_BASE_2 */ + /* setups the montgomery reduction stuff */ -int -mp_montgomery_setup (mp_int * n, mp_digit * rho) +int mp_montgomery_setup (mp_int * n, mp_digit * rho) { mp_digit x, b; @@ -2065,7 +2409,7 @@ mp_montgomery_setup (mp_int * n, mp_digit * rho) /* rho = -1/m mod b */ /* TAO, switched mp_word casts to mp_digit to shut up compiler */ - *rho = (((mp_digit)1 << ((mp_digit) DIGIT_BIT)) - x) & MP_MASK; + *rho = (mp_digit)((((mp_digit)1 << ((mp_digit) DIGIT_BIT)) - x) & MP_MASK); return MP_OKAY; } @@ -2099,7 +2443,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 @@ -2108,8 +2452,8 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) * an array of double precision words W[...] */ { - register mp_word *_W; - register mp_digit *tmpx; + mp_word *_W; + mp_digit *tmpx; /* alias for the W[] array */ _W = W; @@ -2138,13 +2482,13 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) * by casting the value down to a mp_digit. Note this requires * that W[ix-1] have the carry cleared (see after the inner loop) */ - register mp_digit mu; + mp_digit mu; mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK); /* a = a + mu * m * b**i * * This is computed in place and on the fly. The multiplication - * by b**i is handled by offseting which columns the results + * by b**i is handled by offsetting which columns the results * are added to. * * Note the comba method normally doesn't handle carries in the @@ -2156,9 +2500,9 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) * first m->used words of W[] have the carries fixed */ { - register int iy; - register mp_digit *tmpn; - register mp_word *_W; + int iy; + mp_digit *tmpn; + mp_word *_W; /* alias for the digits of the modulus */ tmpn = n->dp; @@ -2181,8 +2525,8 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) * significant digits we zeroed]. */ { - register mp_digit *tmpx; - register mp_word *_W, *_W1; + mp_digit *tmpx; + mp_word *_W, *_W1; /* nox fix rest of carries */ @@ -2213,7 +2557,7 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK)); } - /* zero oldused digits, if the input a was larger than + /* zero olduse digits, if the input a was larger than * m->used+1 we'll have to clear the digits */ for (; ix < olduse; ix++) { @@ -2226,7 +2570,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 */ @@ -2238,8 +2582,7 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) /* computes xR**-1 == x (mod N) via Montgomery Reduction */ -int -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) { int ix, res, digs; mp_digit mu; @@ -2251,7 +2594,7 @@ mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) * are fixed up in the inner loop. */ digs = n->used * 2 + 1; - if ((digs < MP_WARRAY) && + if ((digs < (int)MP_WARRAY) && n->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { return fast_mp_montgomery_reduce (x, n, rho); @@ -2278,9 +2621,9 @@ mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) /* a = a + mu * m * b**i */ { - register int iy; - register mp_digit *tmpn, *tmpx, u; - register mp_word r; + int iy; + mp_digit *tmpn, *tmpx, u; + mp_word r; /* alias for digits of the modulus */ tmpn = n->dp; @@ -2360,8 +2703,7 @@ void mp_dr_setup(mp_int *a, mp_digit *d) * * Input x must be in the range 0 <= x <= (n-1)**2 */ -int -mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k) +int mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k) { int err, i, m; mp_word r; @@ -2413,7 +2755,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; @@ -2450,7 +2794,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; } @@ -2487,37 +2833,49 @@ int mp_reduce_2k_setup(mp_int *a, mp_digit *d) } -/* computes a = 2**b - * - * Simple algorithm which zeroes the int, grows it then just sets one bit - * as required. - */ -int -mp_2expt (mp_int * a, int b) +/* set the b bit of a */ +int mp_set_bit (mp_int * a, int b) { - int res; + int i = b / DIGIT_BIT, res; - /* zero a as per default */ - mp_zero (a); + /* + * Require: + * bit index b >= 0 + * a->alloc == a->used == 0 if a->dp == NULL + */ + if (b < 0 || (a->dp == NULL && (a->alloc != 0 || a->used != 0))) + return MP_VAL; - /* grow a to accomodate the single bit */ - if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { - return res; - } + if (a->dp == NULL || a->used < (int)(i + 1)) { + /* grow a to accommodate the single bit */ + if ((res = mp_grow (a, i + 1)) != MP_OKAY) { + return res; + } - /* set the used count of where the bit will go */ - a->used = b / DIGIT_BIT + 1; + /* set the used count of where the bit will go */ + a->used = (int)(i + 1); + } - /* put the single bit in its place */ - a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT); + /* put the single bit in its place */ + a->dp[i] |= ((mp_digit)1) << (b % DIGIT_BIT); - return MP_OKAY; + return MP_OKAY; } +/* computes a = 2**b + * + * Simple algorithm which zeros the int, set the required bit + */ +int mp_2expt (mp_int * a, int b) +{ + /* zero a as per default */ + mp_zero (a); + + return mp_set_bit(a, b); +} /* multiply by a digit */ -int -mp_mul_d (mp_int * a, mp_digit b, mp_int * c) +int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) { mp_digit u, *tmpa, *tmpc; mp_word r; @@ -2575,7 +2933,31 @@ 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_size (&t, c->used)) != MP_OKAY) { + return res; + } + + res = mp_mul (a, b, &t); + if (res == MP_OKAY) { + res = mp_mod (&t, c, d); + } + + mp_clear (&t); + return res; +} + + +/* d = a - b (mod c) */ +int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d) { int res; mp_int t; @@ -2584,26 +2966,45 @@ int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) return res; } - if ((res = mp_mul (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; + res = mp_sub (a, b, &t); + if (res == MP_OKAY) { + res = mp_mod (&t, c, d); } - res = mp_mod (&t, c, d); + mp_clear (&t); + return res; } +/* d = a + b (mod c) */ +int mp_addmod(mp_int* a, mp_int* b, mp_int* c, mp_int* d) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + res = mp_add (a, b, &t); + if (res == MP_OKAY) { + res = mp_mod (&t, c, d); + } + + mp_clear (&t); + + return res; +} /* computes b = a*a */ -int -mp_sqr (mp_int * a, mp_int * b) +int mp_sqr (mp_int * a, mp_int * b) { int res; { #ifdef BN_FAST_S_MP_SQR_C /* can we use the fast comba multiplier? */ - if ((a->used * 2 + 1) < MP_WARRAY && + if ((a->used * 2 + 1) < (int)MP_WARRAY && a->used < (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { res = fast_s_mp_sqr (a, b); @@ -2621,12 +3022,17 @@ 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; { +#ifdef BN_FAST_S_MP_MUL_DIGS_C /* can we use the fast multiplier? * * The fast multiplier can be used if the output will @@ -2635,8 +3041,7 @@ int mp_mul (mp_int * a, mp_int * b, mp_int * c) */ int digs = a->used + b->used + 1; -#ifdef BN_FAST_S_MP_MUL_DIGS_C - if ((digs < MP_WARRAY) && + if ((digs < (int)MP_WARRAY) && MIN(a->used, b->used) <= (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { res = fast_s_mp_mul_digs (a, b, c, digs); @@ -2659,7 +3064,7 @@ int mp_mul_2(mp_int * a, mp_int * b) { int x, res, oldused; - /* grow to accomodate result */ + /* grow to accommodate result */ if (b->alloc < a->used + 1) { if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { return res; @@ -2670,7 +3075,7 @@ int mp_mul_2(mp_int * a, mp_int * b) b->used = a->used; { - register mp_digit r, rr, *tmpa, *tmpb; + mp_digit r, rr, *tmpa, *tmpb; /* alias for source */ tmpa = a->dp; @@ -2688,7 +3093,7 @@ int mp_mul_2(mp_int * a, mp_int * b) rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1)); /* now shift up this digit, add in the carry [from the previous] */ - *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK; + *tmpb++ = (mp_digit)(((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK); /* copy the carry that would be from the source * digit into the next iteration @@ -2717,8 +3122,7 @@ int mp_mul_2(mp_int * a, mp_int * b) /* divide by three (based on routine from MPI and the GMP manual) */ -int -mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) +int mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) { mp_int q; mp_word w, t; @@ -2783,7 +3187,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; @@ -2793,6 +3197,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++) { @@ -2832,11 +3239,11 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) } } - if (pa > MP_WARRAY) + if (pa > (int)MP_WARRAY) 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 @@ -2859,7 +3266,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) tmpx = a->dp + tx; tmpy = a->dp + ty; - /* this is the number of times the loop will iterrate, essentially + /* this is the number of times the loop will iterate, essentially while (tx++ < a->used && ty-- >= 0) { ... } */ iy = MIN(a->used-tx, ty+1); @@ -2898,7 +3305,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) mp_digit *tmpb; tmpb = b->dp; for (ix = 0; ix < pa; ix++) { - *tmpb++ = W[ix] & MP_MASK; + *tmpb++ = (mp_digit)(W[ix] & MP_MASK); } /* clear unused digits [that existed in the old copy of c] */ @@ -2909,7 +3316,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; @@ -2940,7 +3347,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) #else mp_digit W[MP_WARRAY]; #endif - register mp_word _W; + mp_word _W; /* grow the destination as required */ if (c->alloc < digs) { @@ -2951,11 +3358,11 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* number of output digits to produce */ pa = MIN(digs, a->used + b->used); - if (pa > MP_WARRAY) + if (pa > (int)MP_WARRAY) 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 @@ -2975,7 +3382,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) tmpx = a->dp + tx; tmpy = b->dp + ty; - /* this is the number of times the loop will iterrate, essentially + /* this is the number of times the loop will iterate, essentially while (tx++ < a->used && ty-- >= 0) { ... } */ iy = MIN(a->used-tx, ty+1); @@ -2987,7 +3394,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) } /* store term */ - W[ix] = ((mp_digit)_W) & MP_MASK; + W[ix] = (mp_digit)(((mp_digit)_W) & MP_MASK); /* make next carry */ _W = _W >> ((mp_word)DIGIT_BIT); @@ -2998,9 +3405,9 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) c->used = pa; { - register mp_digit *tmpc; + 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]; } @@ -3013,7 +3420,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; @@ -3084,7 +3491,7 @@ int s_mp_sqr (mp_int * a, mp_int * b) } -/* multiplies |a| * |b| and only computes upto digs digits of result +/* multiplies |a| * |b| and only computes up to digs digits of result * HAC pp. 595, Algorithm 14.12 Modified so you can control how * many digits of output are created. */ @@ -3097,7 +3504,7 @@ int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) mp_digit tmpx, *tmpt, *tmpy; /* can we use the fast multiplier? */ - if (((digs) < MP_WARRAY) && + if ((digs < (int)MP_WARRAY) && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { return fast_s_mp_mul_digs (a, b, c, digs); @@ -3157,8 +3564,8 @@ int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* * shifts with subtractions when the result is greater than b. * - * The method is slightly modified to shift B unconditionally upto just under - * the leading bit of b. This saves alot of multiple precision shifting. + * The method is slightly modified to shift B unconditionally up to just under + * the leading bit of b. This saves a lot of multiple precision shifting. */ int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) { @@ -3168,15 +3575,17 @@ int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) bits = mp_count_bits (b) % DIGIT_BIT; if (b->used > 1) { - if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { + if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) + != MP_OKAY) { return res; } } else { - mp_set(a, 1); + if ((res = mp_set(a, 1)) != MP_OKAY) { + return res; + } bits = 1; } - /* now compute C = A * B mod b */ for (x = bits - 1; x < (int)DIGIT_BIT; x++) { if ((res = mp_mul_2 (a, a)) != MP_OKAY) { @@ -3312,7 +3721,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; @@ -3427,7 +3838,7 @@ LBL_M: /* pre-calculate the value required for Barrett reduction - * For a given modulus "b" it calulates the value required in "a" + * For a given modulus "b" it calculates the value required in "a" */ int mp_reduce_setup (mp_int * a, mp_int * b) { @@ -3499,7 +3910,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) @@ -3551,7 +3963,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; } @@ -3588,8 +4002,7 @@ ERR: /* multiplies |a| * |b| and does not compute the lower digs digits * [meant to get the higher part of the product] */ -int -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) { mp_int t; int res, pa, pb, ix, iy; @@ -3599,8 +4012,9 @@ s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* can we use the fast multiplier? */ #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C - if (((a->used + b->used + 1) < MP_WARRAY) - && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + if (((a->used + b->used + 1) < (int)MP_WARRAY) + && MIN (a->used, b->used) < + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { return fast_s_mp_mul_high_digs (a, b, c, digs); } #endif @@ -3612,7 +4026,7 @@ 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; @@ -3665,6 +4079,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) { @@ -3673,11 +4091,11 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) } } - if (pa > MP_WARRAY) + if (pa > (int)MP_WARRAY) 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 @@ -3685,7 +4103,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; @@ -3697,7 +4115,7 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) tmpx = a->dp + tx; tmpy = b->dp + ty; - /* this is the number of times the loop will iterrate, essentially its + /* this is the number of times the loop will iterate, essentially its while (tx++ < a->used && ty-- >= 0) { ... } */ iy = MIN(a->used-tx, ty+1); @@ -3708,7 +4126,7 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) } /* store term */ - W[ix] = ((mp_digit)_W) & MP_MASK; + W[ix] = (mp_digit)(((mp_digit)_W) & MP_MASK); /* make next carry */ _W = _W >> ((mp_word)DIGIT_BIT); @@ -3719,10 +4137,10 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) c->used = pa; { - register mp_digit *tmpc; + mp_digit *tmpc; tmpc = c->dp + digs; - for (ix = digs; ix <= pa; ix++) { + for (ix = digs; ix < pa; ix++) { /* TAO, <= could potentially overwrite */ /* now extract the previous digit [below the carry] */ *tmpc++ = W[ix]; } @@ -3735,32 +4153,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; @@ -3770,7 +4196,8 @@ int mp_set_int (mp_int * a, unsigned long b) } -#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_ECC) +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_ECC) || !defined(NO_RSA) || \ + !defined(NO_DSA) | !defined(NO_DH) /* c = a * a (mod b) */ int mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) @@ -3794,7 +4221,10 @@ int mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) #endif -#if defined(HAVE_ECC) || !defined(NO_PWDBASED) || defined(WOLFSSL_SNIFFER) || defined(WOLFSSL_HAVE_WOLFSCEP) || defined(WOLFSSL_KEY_GEN) +#if defined(HAVE_ECC) || !defined(NO_PWDBASED) || defined(WOLFSSL_SNIFFER) || \ + defined(WOLFSSL_HAVE_WOLFSCEP) || defined(WOLFSSL_KEY_GEN) || \ + defined(OPENSSL_EXTRA) || defined(WC_RSA_BLINDING) || \ + (!defined(NO_RSA) && !defined(NO_RSA_BOUNDS_CHECK)) /* single digit addition */ int mp_add_d (mp_int* a, mp_digit b, mp_int* c) @@ -3854,7 +4284,7 @@ int mp_add_d (mp_int* a, mp_digit b, mp_int* c) *tmpc++ &= MP_MASK; } /* set final carry */ - if (mu != 0 && ix < c->alloc) { + if (ix < c->alloc) { ix++; *tmpc++ = mu; } @@ -3961,7 +4391,9 @@ 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) +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(HAVE_ECC) || \ + defined(DEBUG_WOLFSSL) || !defined(NO_RSA) || !defined(NO_DSA) || \ + !defined(NO_DH) static const int lnz[16] = { 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 @@ -3971,16 +4403,17 @@ 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) == 1) { + if (mp_iszero(a) == MP_YES) { return 0; } /* scan lower digits until non-zero */ - for (x = 0; x < a->used && a->dp[x] == 0; x++); - q = a->dp[x]; + for (x = 0; x < a->used && a->dp[x] == 0; x++) {} + if (a->dp) + q = a->dp[x]; x *= DIGIT_BIT; /* now scan this digit until a 1 is found */ @@ -4021,7 +4454,7 @@ static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) mp_int q; mp_word w; mp_digit t; - int res, ix; + int res = MP_OKAY, ix; /* cannot divide by zero */ if (b == 0) { @@ -4029,7 +4462,7 @@ static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) } /* quick outs */ - if (b == 1 || mp_iszero(a) == 1) { + if (b == 1 || mp_iszero(a) == MP_YES) { if (d != NULL) { *d = 0; } @@ -4058,12 +4491,21 @@ static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) #endif /* no easy answer [c'est la vie]. Just division */ - if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { - return res; + if (c != NULL) { + if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { + return res; + } + + q.used = a->used; + q.sign = a->sign; + } + else { + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } } - q.used = a->used; - q.sign = a->sign; + w = 0; for (ix = a->used - 1; ix >= 0; ix--) { w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); @@ -4074,7 +4516,8 @@ static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) } else { t = 0; } - q.dp[ix] = (mp_digit)t; + if (c != NULL) + q.dp[ix] = (mp_digit)t; } if (d != NULL) { @@ -4096,11 +4539,11 @@ 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) */ +#endif /* WOLFSSL_KEY_GEN || HAVE_COMP_KEY || HAVE_ECC || DEBUG_WOLFSSL */ -#ifdef WOLFSSL_KEY_GEN +#if defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) -const mp_digit ltm_prime_tab[] = { +const mp_digit ltm_prime_tab[PRIME_SIZE] = { 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, @@ -4189,9 +4632,30 @@ static int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result) if ((err = mp_init (&y)) != MP_OKAY) { goto LBL_R; } - if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) { - goto LBL_Y; - } +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(a) == 1024) + err = sp_ModExp_1024(b, &r, a, &y); + else if (mp_count_bits(a) == 2048) + err = sp_ModExp_2048(b, &r, a, &y); + else +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(a) == 1536) + err = sp_ModExp_1536(b, &r, a, &y); + else if (mp_count_bits(a) == 3072) + err = sp_ModExp_3072(b, &r, a, &y); + else +#endif +#ifdef WOLFSSL_SP_4096 + if (mp_count_bits(a) == 4096) + err = sp_ModExp_4096(b, &r, a, &y); + else +#endif +#endif + err = mp_exptmod (b, &r, a, &y); + if (err != MP_OKAY) + goto LBL_Y; /* if y != 1 and y != n1 do */ if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) { @@ -4254,7 +4718,6 @@ static int mp_prime_is_divisible (mp_int * a, int *result) return MP_OKAY; } - /* * Sets result to 1 if probably prime, 0 otherwise */ @@ -4271,10 +4734,15 @@ int mp_prime_is_prime (mp_int * a, int t, int *result) return MP_VAL; } + if (mp_isone(a)) { + *result = MP_NO; + return MP_OKAY; + } + /* is the input equal to one of the primes in the table? */ for (ix = 0; ix < PRIME_SIZE; ix++) { if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) { - *result = 1; + *result = MP_YES; return MP_OKAY; } } @@ -4296,7 +4764,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; @@ -4314,6 +4784,177 @@ LBL_B:mp_clear (&b); } +/* + * Sets result to 1 if probably prime, 0 otherwise + */ +int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng) +{ + mp_int b, c; + int ix, err, res; + byte* base = NULL; + word32 baseSz = 0; + + /* default to no */ + *result = MP_NO; + + /* valid value of t? */ + if (t <= 0 || t > PRIME_SIZE) { + return MP_VAL; + } + + if (mp_isone(a)) { + *result = MP_NO; + return MP_OKAY; + } + + /* is the input equal to one of the primes in the table? */ + for (ix = 0; ix < PRIME_SIZE; ix++) { + if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) { + *result = MP_YES; + return MP_OKAY; + } + } + + /* first perform trial division */ + if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) { + return err; + } + + /* return if it was trivially divisible */ + if (res == MP_YES) { + return MP_OKAY; + } + + /* now perform the miller-rabin rounds */ + if ((err = mp_init (&b)) != MP_OKAY) { + return err; + } + if ((err = mp_init (&c)) != MP_OKAY) { + mp_clear(&b); + return err; + } + + baseSz = mp_count_bits(a); + baseSz = (baseSz / 8) + ((baseSz % 8) ? 1 : 0); + + base = (byte*)XMALLOC(baseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (base == NULL) { + err = MP_MEM; + goto LBL_B; + } + + if ((err = mp_sub_d(a, 2, &c)) != MP_OKAY) { + goto LBL_B; + } + + /* now do a miller rabin with up to t random numbers, this should + * give a (1/4)^t chance of a false prime. */ + for (ix = 0; ix < t; ix++) { + /* Set a test candidate. */ + if ((err = wc_RNG_GenerateBlock(rng, base, baseSz)) != 0) { + goto LBL_B; + } + + if ((err = mp_read_unsigned_bin(&b, base, baseSz)) != MP_OKAY) { + goto LBL_B; + } + + if (mp_cmp_d(&b, 2) != MP_GT || mp_cmp(&b, &c) != MP_LT) { + ix--; + continue; + } + + if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + + if (res == MP_NO) { + goto LBL_B; + } + } + + /* passed the test */ + *result = MP_YES; +LBL_B:mp_clear (&b); + mp_clear (&c); + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return err; +} + +#endif /* WOLFSSL_KEY_GEN NO_DH NO_DSA NO_RSA */ + +#ifdef WOLFSSL_KEY_GEN + +static const int USE_BBS = 1; + +int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap) +{ + int err, res, type; + byte* buf; + + if (N == NULL || rng == NULL) + return MP_VAL; + + /* get type */ + if (len < 0) { + type = USE_BBS; + len = -len; + } else { + type = 0; + } + + /* allow sizes between 2 and 512 bytes for a prime size */ + if (len < 2 || len > 512) { + return MP_VAL; + } + + /* allocate buffer to work with */ + buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_RSA); + if (buf == NULL) { + return MP_MEM; + } + XMEMSET(buf, 0, len); + + do { +#ifdef SHOW_GEN + printf("."); + fflush(stdout); +#endif + /* generate value */ + err = wc_RNG_GenerateBlock(rng, buf, len); + if (err != 0) { + XFREE(buf, heap, DYNAMIC_TYPE_RSA); + return err; + } + + /* munge bits */ + buf[0] |= 0x80 | 0x40; + buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); + + /* load value */ + if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) { + XFREE(buf, heap, DYNAMIC_TYPE_RSA); + return err; + } + + /* test */ + /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance + * of a 1024-bit candidate being a false positive, when it is our + * prime candidate. (Note 4.49 of Handbook of Applied Cryptography.) + * Using 8 because we've always used 8. */ + if ((err = mp_prime_is_prime_ex(N, 8, &res, rng)) != MP_OKAY) { + XFREE(buf, heap, DYNAMIC_TYPE_RSA); + return err; + } + } while (res == MP_NO); + + XMEMSET(buf, 0, len); + XFREE(buf, heap, DYNAMIC_TYPE_RSA); + + return MP_OKAY; +} + + /* computes least common multiple as |a*b|/(a, b) */ int mp_lcm (mp_int * a, mp_int * b, mp_int * c) { @@ -4411,7 +5052,7 @@ int mp_gcd (mp_int * a, mp_int * b, mp_int * c) } } - while (mp_iszero(&v) == 0) { + while (mp_iszero(&v) == MP_NO) { /* make sure v is the largest */ if (mp_cmp_mag(&u, &v) == MP_GT) { /* swap u and v to make sure v is >= u */ @@ -4435,21 +5076,24 @@ int mp_gcd (mp_int * a, mp_int * b, mp_int * c) } c->sign = MP_ZPOS; res = MP_OKAY; -LBL_V:mp_clear (&u); -LBL_U:mp_clear (&v); +LBL_V:mp_clear (&v); +LBL_U:mp_clear (&u); return res; } - - #endif /* WOLFSSL_KEY_GEN */ -#ifdef HAVE_ECC +#if !defined(NO_DSA) || defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || \ + defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) || \ + defined(DEBUG_WOLFSSL) || defined(OPENSSL_EXTRA) /* chars used in radix conversions */ -const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz+/"; +#endif +#if !defined(NO_DSA) || defined(HAVE_ECC) /* read a string [ASCII] in a given radix */ int mp_read_radix (mp_int * a, const char *str, int radix) { @@ -4460,7 +5104,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; } @@ -4478,12 +5122,12 @@ int mp_read_radix (mp_int * a, const char *str, int radix) mp_zero (a); /* process each digit of the string */ - while (*str) { - /* if the radix < 36 the conversion is case insensitive + 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] */ - ch = (char) ((radix < 36) ? XTOUPPER((unsigned char)*str) : *str); + ch = (radix <= 36) ? (char)XTOUPPER((unsigned char)*str) : *str; for (y = 0; y < 64; y++) { if (ch == mp_s_rmap[y]) { break; @@ -4507,16 +5151,170 @@ 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) != 1) { + if (mp_iszero(a) != MP_YES) { a->sign = neg; } return MP_OKAY; } +#endif /* !defined(NO_DSA) || defined(HAVE_ECC) */ -#endif /* HAVE_ECC */ +#ifdef WC_MP_TO_RADIX + +/* returns size of ASCII representation */ +int mp_radix_size (mp_int *a, int radix, int *size) +{ + int res, digs; + mp_int t; + mp_digit d; + + *size = 0; + + /* special case for binary */ + 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 < MP_RADIX_BIN || radix > MP_RADIX_MAX) { + return MP_VAL; + } + + if (mp_iszero(a) == MP_YES) { + *size = 2; + return MP_OKAY; + } + + /* digs is the digit count */ + digs = 0; + + /* if it's negative add one for the sign */ + if (a->sign == MP_NEG) { + ++digs; + } + + /* init a copy of the input */ + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + /* force temp to positive */ + t.sign = MP_ZPOS; + + /* fetch out all of the digits */ + while (mp_iszero (&t) == MP_NO) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return res; + } + ++digs; + } + mp_clear (&t); + + /* return digs + 1, the 1 is for the NULL byte that would be required. */ + *size = digs + 1; + return MP_OKAY; +} + +/* stores a bignum as a ASCII string in a given radix (2..64) */ +int mp_toradix (mp_int *a, char *str, int radix) +{ + int res, digs; + mp_int t; + mp_digit d; + char *_s = str; + + /* check range of the radix */ + if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) { + return MP_VAL; + } + + /* quick out if its zero */ + if (mp_iszero(a) == MP_YES) { + *str++ = '0'; + *str = '\0'; + return MP_OKAY; + } + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + /* if it is negative output a - */ + if (t.sign == MP_NEG) { + ++_s; + *str++ = '-'; + t.sign = MP_ZPOS; + } + + digs = 0; + while (mp_iszero (&t) == MP_NO) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return res; + } + *str++ = mp_s_rmap[d]; + ++digs; + } +#ifndef WC_DISABLE_RADIX_ZERO_PAD + /* For hexadecimal output, add zero padding when number of digits is odd */ + if ((digs & 1) && (radix == 16)) { + *str++ = mp_s_rmap[0]; + ++digs; + } +#endif + /* reverse the digits of the string. In this case _s points + * to the first digit [excluding the sign] of the number] + */ + bn_reverse ((unsigned char *)_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + + mp_clear (&t); + return MP_OKAY; +} + +#ifdef WOLFSSL_DEBUG_MATH +void mp_dump(const char* desc, mp_int* a, byte verbose) +{ + char *buffer; + int size = a->alloc; + + buffer = (char*)XMALLOC(size * sizeof(mp_digit) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buffer == NULL) { + return; + } + + 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_tohex(a, buffer); + printf(" %s\n ", buffer); + + if (verbose) { + int i; + for(i=0; ialloc * (int)sizeof(mp_digit); i++) { + printf("%02x ", *(((byte*)a->dp) + i)); + } + printf("\n"); + } + + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +} +#endif /* WOLFSSL_DEBUG_MATH */ + +#endif /* WC_MP_TO_RADIX */ + +#endif /* WOLFSSL_SP_MATH */ #endif /* USE_FAST_MATH */ #endif /* NO_BIG_INT */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/logging.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/logging.c index 321530616..0c818aa71 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/logging.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/logging.c @@ -1,8 +1,8 @@ /* logging.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,62 +16,145 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include -/* submitted by eof */ - #include #include - - -#ifdef __cplusplus - extern "C" { -#endif - WOLFSSL_API int wolfSSL_Debugging_ON(void); - WOLFSSL_API void wolfSSL_Debugging_OFF(void); -#ifdef __cplusplus - } +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) +/* avoid adding WANT_READ and WANT_WRITE to error queue */ +#include #endif +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +static wolfSSL_Mutex debug_mutex; /* mutex for access to debug structure */ + +/* accessing any node from the queue should be wrapped in a lock of + * debug_mutex */ +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; + int line; +}; +volatile struct wc_error_queue* wc_errors; +static struct wc_error_queue* wc_current_node; +static struct wc_error_queue* wc_last_node; +/* pointer to last node in queue to make insertion O(1) */ +#endif + +#ifdef WOLFSSL_FUNC_TIME +/* WARNING: This code is only to be used for debugging performance. + * The code is not thread-safe. + * Do not use WOLFSSL_FUNC_TIME in production code. + */ +static double wc_func_start[WC_FUNC_COUNT]; +static double wc_func_time[WC_FUNC_COUNT] = { 0, }; +static const char* wc_func_name[WC_FUNC_COUNT] = { + "SendHelloRequest", + "DoHelloRequest", + "SendClientHello", + "DoClientHello", + "SendServerHello", + "DoServerHello", + "SendEncryptedExtensions", + "DoEncryptedExtensions", + "SendCertificateRequest", + "DoCertificateRequest", + "SendCertificate", + "DoCertificate", + "SendCertificateVerify", + "DoCertificateVerify", + "SendFinished", + "DoFinished", + "SendKeyUpdate", + "DoKeyUpdate", + "SendEarlyData", + "DoEarlyData", + "SendNewSessionTicket", + "DoNewSessionTicket", + "SendServerHelloDone", + "DoServerHelloDone", + "SendTicket", + "DoTicket", + "SendClientKeyExchange", + "DoClientKeyExchange", + "SendCertificateStatus", + "DoCertificateStatus", + "SendServerKeyExchange", + "DoServerKeyExchange", + "SendEarlyData", + "DoEarlyData", +}; + +#include + +/* WARNING: This function is not portable. */ +static WC_INLINE double current_time(int reset) +{ + struct timeval tv; + gettimeofday(&tv, 0); + (void)reset; + + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; +} +#endif /* WOLFSSL_FUNC_TIME */ #ifdef 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; +#if defined(WOLFSSL_APACHE_MYNEWT) +#include "log/log.h" +static struct log mynewt_log; +#endif /* WOLFSSL_APACHE_MYNEWT */ + #endif /* DEBUG_WOLFSSL */ +/* allow this to be set to NULL, so logs can be redirected to default output */ int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb f) { #ifdef DEBUG_WOLFSSL - int res = 0; - - if (f) - log_function = f; - else - res = BAD_FUNC_ARG; - - return res; + log_function = f; + return 0; #else (void)f; return NOT_COMPILED_IN; #endif } +/* allow this to be set to NULL, so logs can be redirected to default output */ +wolfSSL_Logging_cb wolfSSL_GetLoggingCb(void) +{ +#ifdef DEBUG_WOLFSSL + return log_function; +#else + return NULL; +#endif +} + int wolfSSL_Debugging_ON(void) { #ifdef DEBUG_WOLFSSL loggingEnabled = 1; +#if defined(WOLFSSL_APACHE_MYNEWT) + log_register("wolfcrypt", &mynewt_log, &log_console_handler, NULL, LOG_SYSLEVEL); +#endif /* WOLFSSL_APACHE_MYNEWT */ return 0; #else return NOT_COMPILED_IN; @@ -86,16 +169,72 @@ void wolfSSL_Debugging_OFF(void) #endif } +#ifdef WOLFSSL_FUNC_TIME +/* WARNING: This code is only to be used for debugging performance. + * The code is not thread-safe. + * Do not use WOLFSSL_FUNC_TIME in production code. + */ +void WOLFSSL_START(int funcNum) +{ + double now = current_time(0) * 1000.0; +#ifdef WOLFSSL_FUNC_TIME_LOG + fprintf(stderr, "%17.3f: START - %s\n", now, wc_func_name[funcNum]); +#endif + wc_func_start[funcNum] = now; +} + +void WOLFSSL_END(int funcNum) +{ + double now = current_time(0) * 1000.0; + wc_func_time[funcNum] += now - wc_func_start[funcNum]; +#ifdef WOLFSSL_FUNC_TIME_LOG + fprintf(stderr, "%17.3f: END - %s\n", now, wc_func_name[funcNum]); +#endif +} + +void WOLFSSL_TIME(int count) +{ + int i; + double avg, total = 0; + + for (i = 0; i < WC_FUNC_COUNT; i++) { + if (wc_func_time[i] > 0) { + avg = wc_func_time[i] / count; + fprintf(stderr, "%8.3f ms: %s\n", avg, wc_func_name[i]); + total += avg; + } + } + fprintf(stderr, "%8.3f ms\n", total); +} +#endif #ifdef DEBUG_WOLFSSL -#ifdef FREESCALE_MQX - #include +#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + /* see wc_port.h for fio.h and nio.h includes */ +#elif defined(WOLFSSL_SGX) + /* Declare sprintf for ocall */ + int sprintf(char* buf, const char *fmt, ...); +#elif defined(WOLFSSL_DEOS) +#elif defined(MICRIUM) + #if (BSP_SER_COMM_EN == DEF_ENABLED) + #include + #endif +#elif defined(WOLFSSL_USER_LOG) + /* user includes their own headers */ +#elif defined(WOLFSSL_ESPIDF) + #include "esp_types.h" + #include "esp_log.h" +#elif defined(WOLFSSL_TELIT_M2MB) + #include + #include "m2m_log.h" +#elif defined(WOLFSSL_ANDROID_DEBUG) + #include #else #include /* for default printf stuff */ #endif -#ifdef THREADX +#if defined(THREADX) && !defined(THREADX_NO_DC_PRINTF) int dc_log_printf(char*, ...); #endif @@ -104,37 +243,105 @@ static void wolfssl_log(const int logLevel, const char *const logMessage) if (log_function) log_function(logLevel, logMessage); else { - if (loggingEnabled) { -#ifdef THREADX - dc_log_printf("%s\n", logMessage); +#if defined(WOLFSSL_USER_LOG) + WOLFSSL_USER_LOG(logMessage); +#elif defined(WOLFSSL_LOG_PRINTF) + printf("%s\n", logMessage); + +#elif defined(THREADX) && !defined(THREADX_NO_DC_PRINTF) + dc_log_printf("%s\n", logMessage); +#elif defined(WOLFSSL_DEOS) + printf("%s\r\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); - fflush(stdout) ; + fflush(stdout) ; + printf("%s\n", logMessage); + fflush(stdout) ; +#elif defined(WOLFSSL_UTASKER) + fnDebugMsg((char*)logMessage); + fnDebugMsg("\r\n"); +#elif defined(MQX_USE_IO_OLD) + fprintf(_mqxio_stderr, "%s\n", logMessage); + +#elif defined(WOLFSSL_APACHE_MYNEWT) + LOG_DEBUG(&mynewt_log, LOG_MODULE_DEFAULT, "%s\n", logMessage); +#elif defined(WOLFSSL_ESPIDF) + ESP_LOGI("wolfssl", "%s", logMessage); +#elif defined(WOLFSSL_ZEPHYR) + printk("%s\n", logMessage); +#elif defined(WOLFSSL_TELIT_M2MB) + M2M_LOG_INFO("%s\n", logMessage); +#elif defined(WOLFSSL_ANDROID_DEBUG) + __android_log_print(ANDROID_LOG_VERBOSE, "[wolfSSL]", "%s", logMessage); #else - fprintf(stderr, "%s\n", logMessage); + fprintf(stderr, "%s\n", logMessage); #endif - } } } - +#ifndef WOLFSSL_DEBUG_ERRORS_ONLY void WOLFSSL_MSG(const char* msg) { if (loggingEnabled) wolfssl_log(INFO_LOG , msg); } +#ifndef LINE_LEN +#define LINE_LEN 16 +#endif +void WOLFSSL_BUFFER(const byte* buffer, word32 length) +{ + int i, buflen = (int)length, bufidx; + char line[(LINE_LEN * 4) + 3]; /* \t00..0F | chars...chars\0 */ + + if (!loggingEnabled) { + return; + } + + if (!buffer) { + wolfssl_log(INFO_LOG, "\tNULL"); + return; + } + + while (buflen > 0) { + bufidx = 0; + XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "\t"); + bufidx++; + + for (i = 0; i < LINE_LEN; i++) { + if (i < buflen) { + XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "%02x ", buffer[i]); + } + else { + XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, " "); + } + bufidx += 3; + } + + XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "| "); + bufidx++; + + for (i = 0; i < LINE_LEN; i++) { + if (i < buflen) { + XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, + "%c", 31 < buffer[i] && buffer[i] < 127 ? buffer[i] : '.'); + bufidx++; + } + } + + wolfssl_log(INFO_LOG, line); + buffer += LINE_LEN; + buflen -= LINE_LEN; + } +} + 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); } } @@ -143,20 +350,494 @@ 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); } } - -void WOLFSSL_ERROR(int error) +WOLFSSL_API int WOLFSSL_IS_DEBUG_ON(void) { - if (loggingEnabled) { - char buffer[80]; - sprintf(buffer, "wolfSSL error occured, error = %d", error); - wolfssl_log(ERROR_LOG , buffer); + return loggingEnabled; +} +#endif /* !WOLFSSL_DEBUG_ERRORS_ONLY */ +#endif /* DEBUG_WOLFSSL */ + +/* + * When using OPENSSL_EXTRA or DEBUG_WOLFSSL_VERBOSE macro then WOLFSSL_ERROR is + * mapped to new function WOLFSSL_ERROR_LINE which gets the line # and function + * name where WOLFSSL_ERROR is called at. + */ +#if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(OPENSSL_EXTRA) + +#if (defined(OPENSSL_EXTRA) && !defined(_WIN32) && !defined(NO_ERROR_QUEUE)) \ + || defined(DEBUG_WOLFSSL_VERBOSE) +void WOLFSSL_ERROR_LINE(int error, const char* func, unsigned int line, + const char* file, void* usrCtx) +#else +void WOLFSSL_ERROR(int error) +#endif +{ +#ifdef WOLFSSL_ASYNC_CRYPT + if (error != WC_PENDING_E) +#endif + { + char buffer[WOLFSSL_MAX_ERROR_SZ]; + + #if (defined(OPENSSL_EXTRA) && !defined(_WIN32) && \ + !defined(NO_ERROR_QUEUE)) || 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"); + XSNPRINTF(buffer, sizeof(buffer), + "wolfSSL error occurred, error = %d", error); + } + else { + #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) + /* If running in compatibility mode do not add want read and + want right to error queue */ + if (error != WANT_READ && error != WANT_WRITE) { + #endif + if (error < 0) + error = error - (2 * error); /* get absolute value */ + 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"); + /* with void function there is no return here, continue on + * to unlock mutex and log what buffer was created. */ + } + #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) + } + else { + XSNPRINTF(buffer, sizeof(buffer), + "wolfSSL error occurred, error = %d", error); + + } + #endif + + wc_UnLockMutex(&debug_mutex); + } + #else + XSNPRINTF(buffer, sizeof(buffer), + "wolfSSL error occurred, error = %d", error); + #endif + + #ifdef DEBUG_WOLFSSL + if (loggingEnabled) + wolfssl_log(ERROR_LOG , buffer); + #endif } } -#endif /* DEBUG_WOLFSSL */ +void WOLFSSL_ERROR_MSG(const char* msg) +{ +#ifdef DEBUG_WOLFSSL + if (loggingEnabled) + wolfssl_log(ERROR_LOG , msg); +#else + (void)msg; +#endif +} + +#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +/* Internal function that is called by wolfCrypt_Init() */ +int wc_LoggingInit(void) +{ + if (wc_InitMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex"); + return BAD_MUTEX_E; + } + wc_errors = NULL; + wc_current_node = NULL; + wc_last_node = NULL; + + return 0; +} + + +/* internal function that is called by wolfCrypt_Cleanup */ +int wc_LoggingCleanup(void) +{ + /* clear logging entries */ + wc_ClearErrorNodes(); + + /* free mutex */ + if (wc_FreeMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Bad Mutex free"); + return BAD_MUTEX_E; + } + return 0; +} + + +/* peek at an error node + * + * 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 + * line : line number that error happened at + * + * Returns a negative value in error case, on success returns the nodes error + * value which is positive (absolute value) + */ +int wc_PeekErrorNode(int idx, const char **file, const char **reason, + int *line) +{ + struct wc_error_queue* err; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return BAD_MUTEX_E; + } + + if (idx < 0) { + err = wc_last_node; + } + else { + int i; + + err = (struct wc_error_queue*)wc_errors; + for (i = 0; i < idx; i++) { + if (err == NULL) { + WOLFSSL_MSG("Error node not found. Bad index?"); + wc_UnLockMutex(&debug_mutex); + return BAD_FUNC_ARG; + } + err = err->next; + } + } + + if (err == NULL) { + WOLFSSL_MSG("No Errors in queue"); + wc_UnLockMutex(&debug_mutex); + return BAD_STATE_E; + } + + if (file != NULL) { + *file = err->file; + } + + if (reason != NULL) { + *reason = err->error; + } + + if (line != NULL) { + *line = err->line; + } + + wc_UnLockMutex(&debug_mutex); + + return err->value; +} + + +/* Pulls the current node from error queue and increments current state. + * Note: this does not delete nodes because input arguments are pointing to + * node buffers. + * + * file pointer to file that error was in. Can be NULL to return no file. + * reason error string giving reason for error. Can be NULL to return no reason. + * line return line number of where error happened. + * + * returns the error value on success and BAD_MUTEX_E or BAD_STATE_E on failure + */ +int wc_PullErrorNode(const char **file, const char **reason, int *line) +{ + struct wc_error_queue* err; + int value; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return BAD_MUTEX_E; + } + + err = wc_current_node; + if (err == NULL) { + WOLFSSL_MSG("No Errors in queue"); + wc_UnLockMutex(&debug_mutex); + return BAD_STATE_E; + } + + if (file != NULL) { + *file = err->file; + } + + if (reason != NULL) { + *reason = err->error; + } + + if (line != NULL) { + *line = err->line; + } + + value = err->value; + wc_current_node = err->next; + wc_UnLockMutex(&debug_mutex); + + return value; +} + + +/* create new error node and add it to the queue + * buffers are assumed to be of size WOLFSSL_MAX_ERROR_SZ for this internal + * function. debug_mutex should be locked before a call to this function. */ +int wc_AddErrorNode(int error, int line, char* buf, char* file) +{ +#if defined(NO_ERROR_QUEUE) + (void)error; + (void)line; + (void)buf; + (void)file; + WOLFSSL_MSG("Error queue turned off, can not add nodes"); +#else + struct wc_error_queue* err; + err = (struct wc_error_queue*)XMALLOC( + sizeof(struct wc_error_queue), wc_error_heap, DYNAMIC_TYPE_LOG); + if (err == NULL) { + WOLFSSL_MSG("Unable to create error node for log"); + return MEMORY_E; + } + else { + int sz; + + XMEMSET(err, 0, sizeof(struct wc_error_queue)); + err->heap = wc_error_heap; + sz = (int)XSTRLEN(buf); + if (sz > WOLFSSL_MAX_ERROR_SZ - 1) { + sz = WOLFSSL_MAX_ERROR_SZ - 1; + } + if (sz > 0) { + XMEMCPY(err->error, buf, sz); + } + + sz = (int)XSTRLEN(file); + if (sz > WOLFSSL_MAX_ERROR_SZ - 1) { + sz = WOLFSSL_MAX_ERROR_SZ - 1; + } + if (sz > 0) { + XMEMCPY(err->file, file, sz); + } + + err->value = error; + err->line = line; + + /* make sure is terminated */ + err->error[WOLFSSL_MAX_ERROR_SZ - 1] = '\0'; + err->file[WOLFSSL_MAX_ERROR_SZ - 1] = '\0'; + + + /* since is queue place new node at last of the list */ + if (wc_last_node == NULL) { + /* case of first node added to queue */ + if (wc_errors != NULL) { + /* check for unexpected case before over writing wc_errors */ + WOLFSSL_MSG("ERROR in adding new node to logging queue!!\n"); + /* In the event both wc_last_node and wc_errors are NULL, err + * goes unassigned to external wc_errors, wc_last_node. Free + * err in this instance since wc_ClearErrorNodes will not + */ + XFREE(err, wc_error_heap, DYNAMIC_TYPE_LOG); + } + else { + wc_errors = err; + wc_last_node = err; + wc_current_node = err; + } + } + else { + wc_last_node->next = err; + err->prev = wc_last_node; + wc_last_node = err; + + /* check the case where have read to the end of the queue and the + * current node to read needs updated */ + if (wc_current_node == NULL) { + wc_current_node = err; + } + } + } +#endif + return 0; +} + +/* 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 (current->next != NULL) + current->next->prev = current->prev; + if (wc_last_node == current) + wc_last_node = current->prev; + if (wc_errors == current) + wc_errors = current->next; + if (wc_current_node == current) + wc_current_node = current->next; + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + } + + wc_UnLockMutex(&debug_mutex); +} + + +/* Clears out the list of error nodes. + */ +void wc_ClearErrorNodes(void) +{ +#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX) || \ + defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + + 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_current_node = NULL; + wc_UnLockMutex(&debug_mutex); +#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX */ +} + +int wc_SetLoggingHeap(void* h) +{ + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return BAD_MUTEX_E; + } + wc_error_heap = h; + wc_UnLockMutex(&debug_mutex); + return 0; +} + + +/* frees all nodes in the queue + * + * id this is the thread id + */ +int wc_ERR_remove_state(void) +{ + struct wc_error_queue* current; + struct wc_error_queue* next; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return BAD_MUTEX_E; + } + + /* free all nodes from error queue */ + 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); + + return 0; +} + +#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) +/* empties out the error queue into the file */ +static int wc_ERR_dump_to_file (const char *str, size_t len, void *u) +{ + XFILE fp = (XFILE ) u; + fprintf(fp, "%-*.*s\n", (int)len, (int)len, str); + return 0; +} + +/* This callback allows the application to provide a custom error printing + * function. */ +void wc_ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u), + void *u) +{ + WOLFSSL_ENTER("wc_ERR_print_errors_cb"); + + if (cb == NULL) { + /* Invalid param */ + return; + } + + if (wc_LockMutex(&debug_mutex) != 0) + { + WOLFSSL_MSG("Lock debug mutex failed"); + } + else + { + /* free all nodes from error queue and print them to file */ + struct wc_error_queue *current; + struct wc_error_queue *next; + + current = (struct wc_error_queue *)wc_errors; + while (current != NULL) + { + next = current->next; + cb(current->error, strlen(current->error), u); + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + current = next; + } + + /* set global pointers to match having been freed */ + wc_errors = NULL; + wc_last_node = NULL; + + wc_UnLockMutex(&debug_mutex); + } +} + +void wc_ERR_print_errors_fp(XFILE fp) +{ + WOLFSSL_ENTER("wc_ERR_print_errors_fp"); + + /* Send all errors to the wc_ERR_dump_to_file function */ + wc_ERR_print_errors_cb(wc_ERR_dump_to_file, fp); +} + +#endif /* !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) */ + +#endif /* defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/md2.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/md2.c index ce4e424b7..c2f34203d 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/md2.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/md2.c @@ -1,8 +1,8 @@ /* md2.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -34,6 +35,7 @@ #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif @@ -49,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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/md4.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/md4.c index c428610ef..f6f67454a 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/md4.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/md4.c @@ -1,8 +1,8 @@ /* md4.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -31,21 +32,11 @@ #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - void wc_InitMd4(Md4* md4) { md4->digest[0] = 0x67452301L; @@ -89,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); @@ -110,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); @@ -130,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; @@ -139,7 +130,7 @@ static void Transform(Md4* md4) } -static INLINE void AddLength(Md4* md4, word32 len) +static WC_INLINE void AddLength(Md4* md4, word32 len) { word32 tmp = md4->loLen; if ( (md4->loLen += len) < tmp) @@ -192,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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/md5.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/md5.c index fbf732add..7eb2a5120 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/md5.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/md5.c @@ -1,8 +1,8 @@ /* md5.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,12 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H - #include +#include #endif #include @@ -29,159 +30,270 @@ #if !defined(NO_MD5) #if defined(WOLFSSL_TI_HASH) - /* #include included by wc_port.c */ -#else +/* #include included by wc_port.c */ -#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 +#include #ifdef NO_INLINE - #include +#include #else - #include -#endif - -#ifdef FREESCALE_MMCAU - #include "cau_api.h" - #define XTRANSFORM(S,B) cau_md5_hash_n((B), 1, (unsigned char*)(S)->digest) -#else - #define XTRANSFORM(S,B) Transform((S)) +#define WOLFSSL_MISC_INCLUDED +#include #endif -#ifdef STM32F2_HASH - /* - * STM32F2 hardware MD5 support through the STM32F2 standard peripheral - * library. Documentation located in STM32F2xx Standard Peripheral Library - * document (See note in README). - */ - #include "stm32f2xx.h" +/* Hardware Acceleration */ +#if defined(STM32_HASH) - void wc_InitMd5(Md5* md5) - { - /* STM32F2 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); - - md5->buffLen = 0; - md5->loLen = 0; +/* Supports CubeMX HAL or Standard Peripheral Library */ +#define HAVE_MD5_CUST_API - /* initialize HASH peripheral */ - HASH_DeInit(); - - /* configure algo used, algo mode, datatype */ - 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; - } - - void wc_Md5Update(Md5* md5, const byte* data, word32 len) - { - word32 i = 0; - word32 fill = 0; - word32 diff = 0; - - /* if saved partial block is available */ - if (md5->buffLen > 0) { - fill = 4 - md5->buffLen; - - /* 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); - - data += fill; - len -= fill; - md5->loLen += 4; - 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); - } - - void wc_Md5Final(Md5* md5, byte* hash) - { - __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; - } - - /* calculate number of valid bits in last word of input data */ - nbvalidbitsdata = 8 * (md5->loLen % MD5_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 */ - md5->digest[0] = HASH->HR[0]; - md5->digest[1] = HASH->HR[1]; - md5->digest[2] = HASH->HR[2]; - md5->digest[3] = HASH->HR[3]; - - ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); - - XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); - - wc_InitMd5(md5); /* reset state */ - } - -#else /* CTaoCrypt software implementation */ - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - -void wc_InitMd5(Md5* md5) +int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId) { + if (md5 == NULL) { + return BAD_FUNC_ARG; + } + + (void)devId; + (void)heap; + + wc_Stm32_Hash_Init(&md5->stmCtx); + + return 0; +} + +int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len) +{ + int ret; + + if (md5 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Update(&md5->stmCtx, HASH_AlgoSelection_MD5, + data, len); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; +} + +int wc_Md5Final(wc_Md5* md5, byte* hash) +{ + int ret; + + if (md5 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Final(&md5->stmCtx, HASH_AlgoSelection_MD5, + hash, WC_MD5_DIGEST_SIZE); + wolfSSL_CryptHwMutexUnLock(); + } + + (void)wc_InitMd5(md5); /* reset state */ + + return ret; +} + +#elif defined(FREESCALE_MMCAU_SHA) + +#ifdef FREESCALE_MMCAU_CLASSIC_SHA + #include "cau_api.h" +#else + #include "fsl_mmcau.h" +#endif + +#define XTRANSFORM(S,B) Transform((S), (B)) +#define XTRANSFORM_LEN(S,B,L) Transform_Len((S), (B), (L)) + +#ifndef WC_HASH_DATA_ALIGNMENT + /* these hardware API's require 4 byte (word32) alignment */ + #define WC_HASH_DATA_ALIGNMENT 4 +#endif + +static int Transform(wc_Md5* md5, const byte* data) +{ + int ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { +#ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_md5_hash_n((byte*)data, 1, (unsigned char*)md5->digest); +#else + MMCAU_MD5_HashN((byte*)data, 1, (uint32_t*)md5->digest); +#endif + wolfSSL_CryptHwMutexUnLock(); + } + return ret; +} + +static int Transform_Len(wc_Md5* md5, const byte* data, word32 len) +{ + int ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + #if defined(WC_HASH_DATA_ALIGNMENT) && WC_HASH_DATA_ALIGNMENT > 0 + if ((size_t)data % WC_HASH_DATA_ALIGNMENT) { + /* data pointer is NOT aligned, + * so copy and perform one block at a time */ + byte* local = (byte*)md5->buffer; + while (len >= WC_MD5_BLOCK_SIZE) { + XMEMCPY(local, data, WC_MD5_BLOCK_SIZE); + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_md5_hash_n(local, 1, (unsigned char*)md5->digest); + #else + MMCAU_MD5_HashN(local, 1, (uint32_t*)md5->digest); + #endif + data += WC_MD5_BLOCK_SIZE; + len -= WC_MD5_BLOCK_SIZE; + } + } + else + #endif + { +#ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_md5_hash_n((byte*)data, len / WC_MD5_BLOCK_SIZE, + (unsigned char*)md5->digest); +#else + MMCAU_MD5_HashN((byte*)data, len / WC_MD5_BLOCK_SIZE, + (uint32_t*)md5->digest); +#endif + } + wolfSSL_CryptHwMutexUnLock(); + } + return ret; +} + +#elif defined(WOLFSSL_PIC32MZ_HASH) +#include +#define HAVE_MD5_CUST_API + +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) +/* functions implemented in wolfcrypt/src/port/caam/caam_sha.c */ +#define HAVE_MD5_CUST_API +#else +#define NEED_SOFT_MD5 +#endif /* End Hardware Acceleration */ + +#ifdef NEED_SOFT_MD5 + +#define XTRANSFORM(S,B) Transform((S),(B)) + +#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, const byte* data) +{ + word32* buffer = (word32*)data; + /* 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, buffer[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, buffer[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, buffer[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, buffer[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, buffer[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, buffer[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, buffer[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, buffer[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, buffer[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, buffer[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, buffer[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, buffer[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, buffer[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, buffer[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, buffer[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, buffer[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, buffer[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, buffer[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, buffer[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, buffer[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, buffer[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, buffer[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, buffer[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, buffer[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, buffer[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, buffer[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, buffer[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, buffer[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, buffer[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, buffer[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, buffer[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, buffer[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, buffer[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, buffer[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, buffer[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, buffer[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, buffer[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, buffer[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, buffer[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, buffer[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, buffer[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, buffer[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, buffer[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, buffer[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, buffer[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, buffer[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, buffer[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, buffer[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, buffer[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, buffer[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, buffer[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, buffer[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, buffer[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, buffer[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, buffer[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, buffer[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, buffer[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, buffer[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, buffer[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, buffer[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, buffer[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, buffer[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, buffer[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, 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 */ + +#ifndef HAVE_MD5_CUST_API + +static WC_INLINE void AddLength(wc_Md5* md5, word32 len) +{ + word32 tmp = md5->loLen; + if ((md5->loLen += len) < tmp) { + md5->hiLen++; /* carry low to high */ + } +} + +static int _InitMd5(wc_Md5* md5) +{ + int ret = 0; + md5->digest[0] = 0x67452301L; md5->digest[1] = 0xefcdab89L; md5->digest[2] = 0x98badcfeL; @@ -190,208 +302,271 @@ void wc_InitMd5(Md5* md5) md5->buffLen = 0; md5->loLen = 0; md5->hiLen = 0; +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + md5->flags = 0; +#endif + + return ret; } -#ifndef FREESCALE_MMCAU - -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 /* FREESCALE_MMCAU */ - - -static INLINE void AddLength(Md5* md5, word32 len) +/* do block size increments/updates */ +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; + word32 blocksLen; + byte* local; + if (md5 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } -void wc_Md5Update(Md5* md5, const byte* data, word32 len) -{ - /* do block size increments */ - byte* local = (byte*)md5->buffer; +#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 */ - while (len) { - word32 add = min(len, MD5_BLOCK_SIZE - md5->buffLen); - XMEMCPY(&local[md5->buffLen], data, add); + /* check that internal buffLen is valid */ + if (md5->buffLen >= WC_MD5_BLOCK_SIZE) + return BUFFER_E; - md5->buffLen += add; - data += add; - len -= add; + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + + /* add length for final */ + AddLength(md5, len); + + local = (byte*)md5->buffer; + + /* process any remainder from previous operation */ + if (md5->buffLen > 0) { + blocksLen = min(len, WC_MD5_BLOCK_SIZE - md5->buffLen); + XMEMCPY(&local[md5->buffLen], data, blocksLen); + + md5->buffLen += blocksLen; + data += blocksLen; + len -= blocksLen; + + 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 + + ret = XTRANSFORM(md5, (const byte*)local); + if (ret != 0) + return ret; - if (md5->buffLen == MD5_BLOCK_SIZE) { - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif - XTRANSFORM(md5, local); - AddLength(md5, MD5_BLOCK_SIZE); md5->buffLen = 0; } } + + /* process blocks */ +#ifdef XTRANSFORM_LEN + /* get number of blocks */ + /* 64-1 = 0x3F (~ Inverted = 0xFFFFFFC0) */ + /* len (masked by 0xFFFFFFC0) returns block aligned length */ + blocksLen = len & ~(WC_MD5_BLOCK_SIZE-1); + if (blocksLen > 0) { + /* Byte reversal performed in function if required. */ + XTRANSFORM_LEN(md5, data, blocksLen); + data += blocksLen; + len -= blocksLen; + } +#else + while (len >= WC_MD5_BLOCK_SIZE) { + word32* local32 = md5->buffer; + /* optimization to avoid memcpy if data pointer is properly aligned */ + /* Big Endian requires byte swap, so can't use data directly */ + #if defined(WC_HASH_DATA_ALIGNMENT) && !defined(BIG_ENDIAN_ORDER) + if (((size_t)data % WC_HASH_DATA_ALIGNMENT) == 0) { + local32 = (word32*)data; + } + else + #endif + { + XMEMCPY(local32, data, WC_MD5_BLOCK_SIZE); + } + + data += WC_MD5_BLOCK_SIZE; + len -= WC_MD5_BLOCK_SIZE; + + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(local32, local32, WC_MD5_BLOCK_SIZE); + #endif + + ret = XTRANSFORM(md5, (const byte*)local32); + } +#endif /* XTRANSFORM_LEN */ + + /* save remainder */ + if (len > 0) { + XMEMCPY(local, data, len); + md5->buffLen = len; + } + + return ret; } - -void wc_Md5Final(Md5* md5, byte* hash) +int wc_Md5Final(wc_Md5* md5, byte* hash) { - byte* local = (byte*)md5->buffer; + byte* local; - AddLength(md5, md5->buffLen); /* before adding pads */ + 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; 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) - 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)) + + md5->hiLen = (md5->loLen >> (8 * sizeof(md5->loLen) - 3)) + (md5->hiLen << 3); md5->loLen = md5->loLen << 3; /* store lengths */ - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - 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 /* STM32F2_HASH */ - - -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 */ + +#ifdef WOLFSSL_PIC32MZ_HASH + wc_Md5Pic32Free(md5); +#endif +} + +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 +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; #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 ret; +} +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Md5SetFlags(wc_Md5* md5, word32 flags) +{ + if (md5) { + md5->flags = flags; + } return 0; } +int wc_Md5GetFlags(wc_Md5* md5, word32* flags) +{ + if (md5 && flags) { + *flags = md5->flags; + } + return 0; +} +#endif #endif /* WOLFSSL_TI_HASH */ - #endif /* NO_MD5 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/memory.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/memory.c index dd9281945..3bc8e21cf 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/memory.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/memory.c @@ -1,8 +1,8 @@ /* memory.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -33,81 +34,920 @@ #define WOLFSSL_MALLOC_CHECK #endif + +/* +Possible memory options: + * NO_WOLFSSL_MEMORY: Disables wolf memory callback support. When not defined settings.h defines USE_WOLFSSL_MEMORY. + * WOLFSSL_STATIC_MEMORY: Turns on the use of static memory buffers and functions. + This allows for using static memory instead of dynamic. + * WOLFSSL_STATIC_ALIGN: Define defaults to 16 to indicate static memory alignment. + * HAVE_IO_POOL: Enables use of static thread safe memory pool for input/output buffers. + * XMALLOC_OVERRIDE: Allows override of the XMALLOC, XFREE and XREALLOC macros. + * XMALLOC_USER: Allows custom XMALLOC, XFREE and XREALLOC functions to be defined. + * WOLFSSL_NO_MALLOC: Disables the fall-back case to use STDIO malloc/free when no callbacks are set. + * WOLFSSL_TRACK_MEMORY: Enables memory tracking for total stats and list of allocated memory. + * WOLFSSL_DEBUG_MEMORY: Enables extra function and line number args for memory callbacks. + * WOLFSSL_DEBUG_MEMORY_PRINT: Enables printing of each malloc/free. + * WOLFSSL_MALLOC_CHECK: Reports malloc or alignment failure using WOLFSSL_STATIC_ALIGN + * WOLFSSL_FORCE_MALLOC_FAIL_TEST: Used for internal testing to induce random malloc failures. + * WOLFSSL_HEAP_TEST: Used for internal testing of heap hint + */ + +#ifdef WOLFSSL_ZEPHYR +#undef realloc +void *z_realloc(void *ptr, size_t size) +{ + if (ptr == NULL) + ptr = malloc(size); + else + ptr = realloc(ptr, size); + + return ptr; +} +#define realloc z_realloc +#endif + #ifdef USE_WOLFSSL_MEMORY #include #include +#include -#ifdef WOLFSSL_MALLOC_CHECK +#if defined(WOLFSSL_DEBUG_MEMORY) && defined(WOLFSSL_DEBUG_MEMORY_PRINT) +#include +#endif + +#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST + static int gMemFailCountSeed; + static int gMemFailCount; + void wolfSSL_SetMemFailCount(int memFailCount) + { + if (gMemFailCountSeed == 0) { + gMemFailCountSeed = memFailCount; + gMemFailCount = memFailCount; + } + } +#endif +#if defined(WOLFSSL_MALLOC_CHECK) || defined(WOLFSSL_TRACK_MEMORY_FULL) || \ + defined(WOLFSSL_MEMORY_LOG) #include #endif + /* Set these to default values initially. */ -static wolfSSL_Malloc_cb malloc_function = 0; -static wolfSSL_Free_cb free_function = 0; -static wolfSSL_Realloc_cb realloc_function = 0; +static wolfSSL_Malloc_cb malloc_function = NULL; +static wolfSSL_Free_cb free_function = NULL; +static wolfSSL_Realloc_cb realloc_function = NULL; int wolfSSL_SetAllocators(wolfSSL_Malloc_cb mf, wolfSSL_Free_cb ff, wolfSSL_Realloc_cb rf) { - int res = 0; + malloc_function = mf; + free_function = ff; + realloc_function = rf; + return 0; +} - if (mf) - malloc_function = mf; - else - res = BAD_FUNC_ARG; +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; +} - if (ff) - free_function = ff; - else - res = BAD_FUNC_ARG; +#ifndef WOLFSSL_STATIC_MEMORY +#ifdef WOLFSSL_DEBUG_MEMORY +void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line) +#else +void* wolfSSL_Malloc(size_t size) +#endif +{ + void* res = 0; - if (rf) - realloc_function = rf; - else - res = BAD_FUNC_ARG; + if (malloc_function) { + #ifdef WOLFSSL_DEBUG_MEMORY + res = malloc_function(size, func, line); + #else + res = malloc_function(size); + #endif + } + else { + #ifndef WOLFSSL_NO_MALLOC + res = malloc(size); + #else + WOLFSSL_MSG("No malloc available"); + #endif + } + +#ifdef WOLFSSL_DEBUG_MEMORY +#if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY) + printf("Alloc: %p -> %u at %s:%d\n", res, (word32)size, func, line); +#else + (void)func; + (void)line; +#endif +#endif + +#ifdef WOLFSSL_MALLOC_CHECK + if (res == NULL) + WOLFSSL_MSG("wolfSSL_malloc failed"); +#endif + +#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST + if (res && --gMemFailCount == 0) { + printf("\n---FORCED MEM FAIL TEST---\n"); + if (free_function) { + #ifdef WOLFSSL_DEBUG_MEMORY + free_function(res, func, line); + #else + free_function(res); + #endif + } + else { + free(res); /* clear */ + } + gMemFailCount = gMemFailCountSeed; /* reset */ + return NULL; + } +#endif return res; } +#ifdef WOLFSSL_DEBUG_MEMORY +void wolfSSL_Free(void *ptr, const char* func, unsigned int line) +#else +void wolfSSL_Free(void *ptr) +#endif +{ +#ifdef WOLFSSL_DEBUG_MEMORY +#if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY) + printf("Free: %p at %s:%d\n", ptr, func, line); +#else + (void)func; + (void)line; +#endif +#endif -void* wolfSSL_Malloc(size_t size) + if (free_function) { + #ifdef WOLFSSL_DEBUG_MEMORY + free_function(ptr, func, line); + #else + free_function(ptr); + #endif + } + else { + #ifndef WOLFSSL_NO_MALLOC + free(ptr); + #else + WOLFSSL_MSG("No free available"); + #endif + } +} + +#ifdef WOLFSSL_DEBUG_MEMORY +void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line) +#else +void* wolfSSL_Realloc(void *ptr, size_t size) +#endif { void* res = 0; - if (malloc_function) - res = malloc_function(size); - else - res = malloc(size); + if (realloc_function) { + #ifdef WOLFSSL_DEBUG_MEMORY + res = realloc_function(ptr, size, func, line); + #else + res = realloc_function(ptr, size); + #endif + } + else { + #ifndef WOLFSSL_NO_MALLOC + res = realloc(ptr, size); + #else + WOLFSSL_MSG("No realloc available"); + #endif + } + + return res; +} +#endif /* WOLFSSL_STATIC_MEMORY */ + +#ifdef WOLFSSL_STATIC_MEMORY + +struct wc_Memory { + byte* buffer; + struct wc_Memory* next; + word32 sz; +}; + + +/* returns amount of memory used on success. On error returns negative value + wc_Memory** list is the list that new buckets are prepended to + */ +static int create_memory_buckets(byte* buffer, word32 bufSz, + word32 buckSz, word32 buckNum, wc_Memory** list) { + word32 i; + byte* pt = buffer; + int ret = 0; + word32 memSz = (word32)sizeof(wc_Memory); + word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + + /* if not enough space available for bucket size then do not try */ + if (buckSz + memSz + padSz > bufSz) { + return ret; + } + + for (i = 0; i < buckNum; i++) { + if ((buckSz + memSz + padSz) <= (bufSz - ret)) { + /* create a new struct and set its values */ + wc_Memory* mem = (struct wc_Memory*)(pt); + mem->sz = buckSz; + mem->buffer = (byte*)pt + padSz + memSz; + mem->next = NULL; + + /* add the newly created struct to front of list */ + if (*list == NULL) { + *list = mem; + } else { + mem->next = *list; + *list = mem; + } + + /* advance pointer and keep track of memory used */ + ret += buckSz + padSz + memSz; + pt += buckSz + padSz + memSz; + } + else { + break; /* not enough space left for more buckets of this size */ + } + } + + return ret; +} + +int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap) +{ + word32 wc_MemSz[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; + word32 wc_Dist[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; + + if (heap == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP)); + + XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz)); + XMEMCPY(heap->distList, wc_Dist, sizeof(wc_Dist)); + + if (wc_InitMutex(&(heap->memory_mutex)) != 0) { + WOLFSSL_MSG("Error creating heap memory mutex"); + return BAD_MUTEX_E; + } + + return 0; +} + +int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, + unsigned char* buf, unsigned int sz, int flag, int max) +{ + int ret; + WOLFSSL_HEAP* heap; + WOLFSSL_HEAP_HINT* hint; + word32 idx = 0; + + if (pHint == NULL || buf == NULL) { + return BAD_FUNC_ARG; + } + + if ((sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) > sz - idx) { + return BUFFER_E; /* not enough memory for structures */ + } + + /* check if hint has already been assigned */ + if (*pHint == NULL) { + heap = (WOLFSSL_HEAP*)buf; + idx += sizeof(WOLFSSL_HEAP); + hint = (WOLFSSL_HEAP_HINT*)(buf + idx); + idx += sizeof(WOLFSSL_HEAP_HINT); + + ret = wolfSSL_init_memory_heap(heap); + if (ret != 0) { + return ret; + } + + XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT)); + hint->memory = heap; + } + else { + #ifdef WOLFSSL_HEAP_TEST + /* do not load in memory if test has been set */ + if (heap == (void*)WOLFSSL_HEAP_TEST) { + return 0; + } + #endif + + hint = (WOLFSSL_HEAP_HINT*)(*pHint); + heap = hint->memory; + } + + ret = wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap); + if (ret != 1) { + WOLFSSL_MSG("Error partitioning memory"); + return -1; + } + + /* determine what max applies too */ + if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) { + heap->maxIO = max; + } + else { /* general memory used in handshakes */ + heap->maxHa = max; + } + + heap->flag |= flag; + *pHint = hint; + + (void)max; + + return 0; +} + +int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag, + WOLFSSL_HEAP* heap) +{ + word32 ava = sz; + byte* pt = buffer; + int ret = 0; + word32 memSz = (word32)sizeof(wc_Memory); + word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + + WOLFSSL_ENTER("wolfSSL_load_static_memory"); + + if (buffer == NULL) { + return BAD_FUNC_ARG; + } + + /* align pt */ + while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) { + *pt = 0x00; + pt++; + ava--; + } + +#ifdef WOLFSSL_DEBUG_MEMORY + printf("Allocated %d bytes for static memory @ %p\n", ava, pt); +#endif + + /* divide into chunks of memory and add them to available list */ + while (ava >= (heap->sizeList[0] + padSz + memSz)) { + int i; + /* creating only IO buffers from memory passed in, max TLS is 16k */ + if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { + if ((ret = create_memory_buckets(pt, ava, + WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) { + WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret); + return ret; + } + + /* check if no more room left for creating IO buffers */ + if (ret == 0) { + break; + } + + /* advance pointer in buffer for next buckets and keep track + of how much memory is left available */ + pt += ret; + ava -= ret; + } + else { + /* start at largest and move to smaller buckets */ + for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { + if ((heap->sizeList[i] + padSz + memSz) <= ava) { + if ((ret = create_memory_buckets(pt, ava, heap->sizeList[i], + heap->distList[i], &(heap->ava[i]))) < 0) { + WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret); + return ret; + } + + /* advance pointer in buffer for next buckets and keep track + of how much memory is left available */ + pt += ret; + ava -= ret; + } + } + } + } + + return 1; +} + + +/* returns the size of management memory needed for each bucket. + * This is memory that is used to keep track of and align memory buckets. */ +int wolfSSL_MemoryPaddingSz(void) +{ + word32 memSz = (word32)sizeof(wc_Memory); + word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + return memSz + padSz; +} + + +/* Used to calculate memory size for optimum use with buckets. + returns the suggested size rounded down to the nearest bucket. */ +int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag) +{ + word32 bucketSz[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_BUCKETS}; + word32 distList[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_DIST}; + + word32 ava = sz; + byte* pt = buffer; + word32 memSz = (word32)sizeof(wc_Memory); + word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + + WOLFSSL_ENTER("wolfSSL_static_size"); + + if (buffer == NULL) { + return BAD_FUNC_ARG; + } + + /* align pt */ + while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) { + pt++; + ava--; + } + + /* creating only IO buffers from memory passed in, max TLS is 16k */ + if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { + if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) { + return 0; /* not enough room for even one bucket */ + } + + ava = ava % (memSz + padSz + WOLFMEM_IO_SZ); + } + else { + int i, k; + + if (ava < (bucketSz[0] + padSz + memSz)) { + return 0; /* not enough room for even one bucket */ + } + + while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) { + /* start at largest and move to smaller buckets */ + for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { + for (k = distList[i]; k > 0; k--) { + if ((bucketSz[i] + padSz + memSz) <= ava) { + ava -= bucketSz[i] + padSz + memSz; + } + } + } + } + } + + return sz - ava; /* round down */ +} + + +int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) +{ + WOLFSSL_MSG("Freeing fixed IO buffer"); + + /* check if fixed buffer was set */ + if (*io == NULL) { + return 1; + } + + if (heap == NULL) { + WOLFSSL_MSG("No heap to return fixed IO too"); + } + else { + /* put IO buffer back into IO pool */ + (*io)->next = heap->io; + heap->io = *io; + *io = NULL; + } + + return 1; +} + + +int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) +{ + WOLFSSL_MSG("Setting fixed IO for SSL"); + if (heap == NULL) { + return MEMORY_E; + } + + *io = heap->io; + + if (*io != NULL) { + heap->io = (*io)->next; + (*io)->next = NULL; + } + else { /* failed to grab an IO buffer */ + return 0; + } + + return 1; +} + + +int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats) +{ + word32 i; + wc_Memory* pt; + + XMEMSET(stats, 0, sizeof(WOLFSSL_MEM_STATS)); + + stats->totalAlloc = heap->alloc; + stats->totalFr = heap->frAlc; + stats->curAlloc = stats->totalAlloc - stats->totalFr; + stats->maxHa = heap->maxHa; + stats->maxIO = heap->maxIO; + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + stats->blockSz[i] = heap->sizeList[i]; + for (pt = heap->ava[i]; pt != NULL; pt = pt->next) { + stats->avaBlock[i] += 1; + } + } + + for (pt = heap->io; pt != NULL; pt = pt->next) { + stats->avaIO++; + } + + stats->flag = heap->flag; /* flag used */ + + return 1; +} + + +#ifdef WOLFSSL_DEBUG_MEMORY +void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line) +#else +void* wolfSSL_Malloc(size_t size, void* heap, int type) +#endif +{ + void* res = 0; + wc_Memory* pt = NULL; + int i; + + /* check for testing heap hint was set */ +#ifdef WOLFSSL_HEAP_TEST + if (heap == (void*)WOLFSSL_HEAP_TEST) { + return malloc(size); + } +#endif + + /* if no heap hint then use dynamic memory*/ + if (heap == NULL) { + #ifdef WOLFSSL_HEAP_TEST + /* allow using malloc for creating ctx and method */ + if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD || + type == DYNAMIC_TYPE_CERT_MANAGER) { + WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n"); + res = malloc(size); + } + else { + WOLFSSL_MSG("ERROR null heap hint passed into XMALLOC\n"); + res = NULL; + } + #else + #ifndef WOLFSSL_NO_MALLOC + #ifdef FREERTOS + res = pvPortMalloc(size); + #else + res = malloc(size); + #endif + #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 */ + } + else { + WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; + WOLFSSL_HEAP* mem = hint->memory; + + if (wc_LockMutex(&(mem->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + return NULL; + } + + /* case of using fixed IO buffers */ + 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; + } + if (type == DYNAMIC_TYPE_IN_BUFFER) { + pt = hint->inBuf; + } + } + 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; + } + } + + /* 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; + } + #ifdef WOLFSSL_DEBUG_STATIC_MEMORY + else { + printf("Size: %ld, Empty: %d\n", size, + mem->sizeList[i]); + } + #endif + } + } + } + } + + if (pt != NULL) { + mem->inUse += pt->sz; + mem->alloc += 1; + res = pt->buffer; + + #ifdef WOLFSSL_DEBUG_MEMORY + printf("Alloc: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line); + #endif + + /* keep track of connection statistics if flag is set */ + if (mem->flag & WOLFMEM_TRACK_STATS) { + WOLFSSL_MEM_CONN_STATS* stats = hint->stats; + if (stats != NULL) { + stats->curMem += pt->sz; + if (stats->peakMem < stats->curMem) { + stats->peakMem = stats->curMem; + } + stats->curAlloc++; + if (stats->peakAlloc < stats->curAlloc) { + stats->peakAlloc = stats->curAlloc; + } + stats->totalAlloc++; + } + } + } + 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)); + } #ifdef WOLFSSL_MALLOC_CHECK - if (res == NULL) - puts("wolfSSL_malloc failed"); + if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) { + WOLFSSL_MSG("ERROR memory is not aligned"); + res = NULL; + } #endif - + + + (void)i; + (void)pt; + (void)type; + return res; } -void wolfSSL_Free(void *ptr) + +#ifdef WOLFSSL_DEBUG_MEMORY +void wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line) +#else +void wolfSSL_Free(void *ptr, void* heap, int type) +#endif { - if (free_function) - free_function(ptr); - else - free(ptr); + int i; + wc_Memory* pt; + + if (ptr) { + /* check for testing heap hint was set */ + #ifdef WOLFSSL_HEAP_TEST + if (heap == (void*)WOLFSSL_HEAP_TEST) { + return free(ptr); + } + #endif + + if (heap == NULL) { + #ifdef WOLFSSL_HEAP_TEST + /* allow using malloc for creating ctx and method */ + if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD || + type == DYNAMIC_TYPE_CERT_MANAGER) { + WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n"); + } + else { + WOLFSSL_MSG("ERROR null heap hint passed into XFREE\n"); + } + #endif + #ifndef WOLFSSL_NO_MALLOC + #ifdef FREERTOS + vPortFree(ptr); + #else + free(ptr); + #endif + #else + WOLFSSL_MSG("Error trying to call free when turned off"); + #endif /* WOLFSSL_NO_MALLOC */ + } + else { + WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; + WOLFSSL_HEAP* mem = hint->memory; + word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1); + + /* get memory struct and add it to available list */ + pt = (wc_Memory*)((byte*)ptr - sizeof(wc_Memory) - padSz); + if (wc_LockMutex(&(mem->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + return; + } + + /* case of using fixed IO buffers */ + if (mem->flag & WOLFMEM_IO_POOL_FIXED && + (type == DYNAMIC_TYPE_OUT_BUFFER || + type == DYNAMIC_TYPE_IN_BUFFER)) { + /* 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 && pt->sz == WOLFMEM_IO_SZ && + (type == DYNAMIC_TYPE_OUT_BUFFER || + type == DYNAMIC_TYPE_IN_BUFFER)) { + pt->next = mem->io; + mem->io = pt; + } + else { /* general memory free */ + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + if (pt->sz == mem->sizeList[i]) { + pt->next = mem->ava[i]; + mem->ava[i] = pt; + break; + } + } + } + mem->inUse -= pt->sz; + mem->frAlc += 1; + + #ifdef WOLFSSL_DEBUG_MEMORY + printf("Free: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line); + #endif + + /* keep track of connection statistics if flag is set */ + if (mem->flag & WOLFMEM_TRACK_STATS) { + WOLFSSL_MEM_CONN_STATS* stats = hint->stats; + if (stats != NULL) { + /* avoid under flow */ + if (stats->curMem > pt->sz) { + stats->curMem -= pt->sz; + } + else { + stats->curMem = 0; + } + + if (stats->curAlloc > 0) { + stats->curAlloc--; + } + stats->totalFr++; + } + } + wc_UnLockMutex(&(mem->memory_mutex)); + } + } + + (void)i; + (void)pt; + (void)type; } -void* wolfSSL_Realloc(void *ptr, size_t size) +#ifdef WOLFSSL_DEBUG_MEMORY +void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line) +#else +void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) +#endif { void* res = 0; + wc_Memory* pt = NULL; + word32 prvSz; + int i; - if (realloc_function) - res = realloc_function(ptr, size); - else - res = realloc(ptr, size); + /* check for testing heap hint was set */ +#ifdef WOLFSSL_HEAP_TEST + if (heap == (void*)WOLFSSL_HEAP_TEST) { + return realloc(ptr, size); + } +#endif + + if (heap == NULL) { + #ifdef WOLFSSL_HEAP_TEST + WOLFSSL_MSG("ERROR null heap hint passed in to XREALLOC\n"); + #endif + #ifndef WOLFSSL_NO_MALLOC + res = realloc(ptr, size); + #else + WOLFSSL_MSG("NO heap found to use for realloc"); + #endif /* WOLFSSL_NO_MALLOC */ + } + else { + WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; + WOLFSSL_HEAP* mem = hint->memory; + word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1); + + if (ptr == NULL) { + #ifdef WOLFSSL_DEBUG_MEMORY + return wolfSSL_Malloc(size, heap, type, func, line); + #else + return wolfSSL_Malloc(size, heap, type); + #endif + } + + if (wc_LockMutex(&(mem->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + return NULL; + } + + /* case of using fixed IO buffers or IO pool */ + if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED)) + && (type == DYNAMIC_TYPE_OUT_BUFFER || + type == DYNAMIC_TYPE_IN_BUFFER)) { + /* no realloc, is fixed size */ + pt = (wc_Memory*)((byte*)ptr - padSz - sizeof(wc_Memory)); + if (pt->sz < size) { + WOLFSSL_MSG("Error IO memory was not large enough"); + res = NULL; /* return NULL in error case */ + } + res = pt->buffer; + } + else { + /* general memory */ + 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; + } + } + } + + if (pt != NULL && res == NULL) { + res = pt->buffer; + + /* copy over original information and free ptr */ + prvSz = ((wc_Memory*)((byte*)ptr - padSz - + sizeof(wc_Memory)))->sz; + prvSz = (prvSz > pt->sz)? pt->sz: prvSz; + XMEMCPY(pt->buffer, ptr, prvSz); + mem->inUse += pt->sz; + mem->alloc += 1; + + /* free memory that was previously being used */ + wc_UnLockMutex(&(mem->memory_mutex)); + wolfSSL_Free(ptr, heap, type + #ifdef WOLFSSL_DEBUG_MEMORY + , func, line + #endif + ); + if (wc_LockMutex(&(mem->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + return NULL; + } + } + } + wc_UnLockMutex(&(mem->memory_mutex)); + } + + #ifdef WOLFSSL_MALLOC_CHECK + if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) { + WOLFSSL_MSG("ERROR memory is not aligned"); + res = NULL; + } + #endif + + (void)i; + (void)pt; + (void)type; return res; } +#endif /* WOLFSSL_STATIC_MEMORY */ #endif /* USE_WOLFSSL_MEMORY */ @@ -125,7 +965,7 @@ void* wolfSSL_Realloc(void *ptr, size_t size) /* allow simple per thread in and out pools */ -/* use 17k size sense max record size is 16k plus overhead */ +/* use 17k size since max record size is 16k plus overhead */ static THREAD_LS_T byte pool_in[17*1024]; static THREAD_LS_T byte pool_out[17*1024]; @@ -172,9 +1012,7 @@ void* XREALLOC(void *p, size_t n, void* heap, int type) return realloc(p, n); } - -/* unit api calls, let's make sure visible with WOLFSSL_API */ -WOLFSSL_API void XFREE(void *p, void* heap, int type) +void XFREE(void *p, void* heap, int type) { (void)heap; @@ -189,3 +1027,100 @@ WOLFSSL_API void XFREE(void *p, void* heap, int type) #endif /* HAVE_IO_POOL */ +#ifdef WOLFSSL_MEMORY_LOG +void *xmalloc(size_t n, void* heap, int type, const char* func, + const char* file, unsigned int line) +{ + void* p; + word32* p32; + + if (malloc_function) + p32 = malloc_function(n + sizeof(word32) * 4); + else + p32 = malloc(n + sizeof(word32) * 4); + + p32[0] = (word32)n; + p = (void*)(p32 + 4); + + fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", p, (word32)n, type, + func, file, line); + + (void)heap; + + return p; +} +void *xrealloc(void *p, size_t n, void* heap, int type, const char* func, + const char* file, unsigned int line) +{ + void* newp = NULL; + word32* p32; + word32* oldp32 = NULL; + word32 oldLen; + + if (p != NULL) { + oldp32 = (word32*)p; + oldp32 -= 4; + oldLen = oldp32[0]; + } + + if (realloc_function) + p32 = realloc_function(oldp32, n + sizeof(word32) * 4); + else + p32 = realloc(oldp32, n + sizeof(word32) * 4); + + if (p32 != NULL) { + p32[0] = (word32)n; + newp = (void*)(p32 + 4); + + fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%u\n", newp, (word32)n, + type, func, file, line); + if (p != NULL) { + fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, oldLen, + type, func, file, line); + } + } + + (void)heap; + + return newp; +} +void xfree(void *p, void* heap, int type, const char* func, const char* file, + unsigned int line) +{ + word32* p32 = (word32*)p; + + if (p != NULL) { + p32 -= 4; + + fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, p32[0], type, + func, file, line); + + if (free_function) + free_function(p32); + else + free(p32); + } + + (void)heap; +} +#endif /* WOLFSSL_MEMORY_LOG */ + +#ifdef WOLFSSL_STACK_LOG +/* Note: this code only works with GCC using -finstrument-functions. */ +void __attribute__((no_instrument_function)) + __cyg_profile_func_enter(void *func, void *caller) +{ + register void* sp asm("sp"); + fprintf(stderr, "ENTER: %016lx %p\n", (unsigned long)(size_t)func, sp); + (void)caller; +} + +void __attribute__((no_instrument_function)) + __cyg_profile_func_exit(void *func, void *caller) +{ + register void* sp asm("sp"); + fprintf(stderr, "EXIT: %016lx %p\n", (unsigned long)(size_t)func, sp); + (void)caller; +} +#endif + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/misc.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/misc.c index 8a79a4c29..8f2402c9c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/misc.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/misc.c @@ -1,8 +1,8 @@ /* misc.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -30,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 @@ -38,9 +39,22 @@ */ #ifdef NO_INLINE - #define STATIC + #define WC_STATIC #else - #define STATIC static + #define WC_STATIC static +#endif + +/* Check for if compiling misc.c when not needed. */ +#if !defined(WOLFSSL_MISC_INCLUDED) && !defined(NO_INLINE) + #ifndef WOLFSSL_IGNORE_FILE_WARN + // #warning misc.c does not need to be compiled when using inline (NO_INLINE not defined) + #endif + +#else + + +#if defined(__ICCARM__) + #include #endif @@ -52,25 +66,25 @@ * i.e., _rotl and _rotr */ #pragma intrinsic(_lrotl, _lrotr) - STATIC INLINE word32 rotlFixed(word32 x, word32 y) + WC_STATIC WC_INLINE word32 rotlFixed(word32 x, word32 y) { return y ? _lrotl(x, y) : x; } - STATIC INLINE word32 rotrFixed(word32 x, word32 y) + WC_STATIC WC_INLINE word32 rotrFixed(word32 x, word32 y) { return y ? _lrotr(x, y) : x; } #else /* generic */ - STATIC INLINE word32 rotlFixed(word32 x, word32 y) + WC_STATIC WC_INLINE word32 rotlFixed(word32 x, word32 y) { return (x << y) | (x >> (sizeof(y) * 8 - y)); - } + } - STATIC INLINE word32 rotrFixed(word32 x, word32 y) + WC_STATIC WC_INLINE word32 rotrFixed(word32 x, word32 y) { return (x >> y) | (x << (sizeof(y) * 8 - y)); } @@ -78,13 +92,18 @@ #endif -STATIC INLINE word32 ByteReverseWord32(word32 value) +WC_STATIC WC_INLINE word32 ByteReverseWord32(word32 value) { #ifdef PPC_INTRINSICS /* PPC: load reverse indexed instruction */ return (word32)__lwbrx(&value,0); +#elif defined(__ICCARM__) + return (word32)__REV(value); #elif defined(KEIL_INTRINSICS) return (word32)__rev(value); +#elif defined(WOLF_ALLOW_BUILTIN) && \ + defined(__GNUC_PREREQ) && __GNUC_PREREQ(4, 3) + return (word32)__builtin_bswap32(value); #elif defined(FAST_ROTATE) /* 5 instructions with rotate instruction, 9 without */ return (rotrFixed(value, 8U) & 0xff00ff00) | @@ -97,7 +116,7 @@ STATIC INLINE word32 ByteReverseWord32(word32 value) } -STATIC INLINE void ByteReverseWords(word32* out, const word32* in, +WC_STATIC WC_INLINE void ByteReverseWords(word32* out, const word32* in, word32 byteCount) { word32 count = byteCount/(word32)sizeof(word32), i; @@ -108,26 +127,28 @@ STATIC INLINE void ByteReverseWords(word32* out, const word32* in, } -#ifdef WORD64_AVAILABLE +#if defined(WORD64_AVAILABLE) && !defined(WOLFSSL_NO_WORD64_OPS) -STATIC INLINE word64 rotlFixed64(word64 x, word64 y) +WC_STATIC WC_INLINE word64 rotlFixed64(word64 x, word64 y) { return (x << y) | (x >> (sizeof(y) * 8 - y)); -} +} -STATIC INLINE word64 rotrFixed64(word64 x, word64 y) +WC_STATIC WC_INLINE word64 rotrFixed64(word64 x, word64 y) { return (x >> y) | (x << (sizeof(y) * 8 - y)); } -STATIC INLINE word64 ByteReverseWord64(word64 value) +WC_STATIC WC_INLINE word64 ByteReverseWord64(word64 value) { -#ifdef WOLFCRYPT_SLOW_WORD64 - return (word64)(ByteReverseWord32((word32)value)) << 32 | - ByteReverseWord32((word32)(value>>32)); +#if defined(WOLF_ALLOW_BUILTIN) && defined(__GNUC_PREREQ) && __GNUC_PREREQ(4, 3) + return (word64)__builtin_bswap64(value); +#elif 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); @@ -138,7 +159,7 @@ STATIC INLINE word64 ByteReverseWord64(word64 value) } -STATIC INLINE void ByteReverseWords64(word64* out, const word64* in, +WC_STATIC WC_INLINE void ByteReverseWords64(word64* out, const word64* in, word32 byteCount) { word32 count = byteCount/(word32)sizeof(word64), i; @@ -148,10 +169,10 @@ STATIC INLINE void ByteReverseWords64(word64* out, const word64* in, } -#endif /* WORD64_AVAILABLE */ +#endif /* WORD64_AVAILABLE && !WOLFSSL_NO_WORD64_OPS */ - -STATIC INLINE void XorWords(wolfssl_word* r, const wolfssl_word* a, word32 n) +#ifndef WOLFSSL_NO_XOR_OPS +WC_STATIC WC_INLINE void XorWords(wolfssl_word* r, const wolfssl_word* a, word32 n) { word32 i; @@ -159,7 +180,7 @@ STATIC INLINE void XorWords(wolfssl_word* r, const wolfssl_word* a, word32 n) } -STATIC INLINE void xorbuf(void* buf, const void* mask, word32 count) +WC_STATIC WC_INLINE void xorbuf(void* buf, const void* mask, word32 count) { if (((wolfssl_word)buf | (wolfssl_word)mask | count) % WOLFSSL_WORD_SIZE == 0) XorWords( (wolfssl_word*)buf, @@ -172,19 +193,37 @@ STATIC INLINE void xorbuf(void* buf, const void* mask, word32 count) for (i = 0; i < count; i++) b[i] ^= m[i]; } } +#endif - +#ifndef WOLFSSL_NO_FORCE_ZERO /* Make sure compiler doesn't skip */ -STATIC INLINE void ForceZero(const void* mem, word32 len) +WC_STATIC WC_INLINE void ForceZero(const void* mem, word32 len) { volatile byte* z = (volatile byte*)mem; +#if defined(WOLFSSL_X86_64_BUILD) && defined(WORD64_AVAILABLE) + volatile word64* w; + #ifndef WOLFSSL_UNALIGNED_64BIT_ACCESS + word32 l = (sizeof(word64) - ((size_t)z & (sizeof(word64)-1))) & + (sizeof(word64)-1); + + if (len < l) l = len; + len -= l; + while (l--) *z++ = 0; + #endif + for (w = (volatile word64*)z; len >= sizeof(*w); len -= sizeof(*w)) + *w++ = 0; + z = (volatile byte*)w; +#endif + while (len--) *z++ = 0; } +#endif +#ifndef WOLFSSL_NO_CONST_CMP /* check all length bytes for equality, return 0 on success */ -STATIC INLINE int ConstantCompare(const byte* a, const byte* b, int length) +WC_STATIC WC_INLINE int ConstantCompare(const byte* a, const byte* b, int length) { int i; int compareSum = 0; @@ -195,7 +234,172 @@ STATIC INLINE int ConstantCompare(const byte* a, const byte* b, int length) return compareSum; } +#endif -#undef STATIC + +#ifndef WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MIN + #if defined(HAVE_FIPS) && !defined(min) /* so ifdef check passes */ + #define min min + #endif + WC_STATIC WC_INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } +#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 + WC_STATIC WC_INLINE word32 max(word32 a, word32 b) + { + return a > b ? a : b; + } +#endif /* !WOLFSSL_HAVE_MAX */ + +#ifndef WOLFSSL_NO_INT_ENCODE +/* converts a 32 bit integer to 24 bit */ +WC_STATIC WC_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 */ +WC_STATIC WC_INLINE void c16toa(word16 wc_u16, byte* c) +{ + c[0] = (wc_u16 >> 8) & 0xff; + c[1] = wc_u16 & 0xff; +} + +/* convert 32 bit integer to opaque */ +WC_STATIC WC_INLINE void c32toa(word32 wc_u32, byte* c) +{ + c[0] = (wc_u32 >> 24) & 0xff; + c[1] = (wc_u32 >> 16) & 0xff; + c[2] = (wc_u32 >> 8) & 0xff; + c[3] = wc_u32 & 0xff; +} +#endif + +#ifndef WOLFSSL_NO_INT_DECODE +/* convert a 24 bit integer into a 32 bit one */ +WC_STATIC WC_INLINE void c24to32(const word24 wc_u24, word32* wc_u32) +{ + *wc_u32 = ((word32)wc_u24[0] << 16) | (wc_u24[1] << 8) | wc_u24[2]; +} + + +/* convert opaque to 24 bit integer */ +WC_STATIC WC_INLINE void ato24(const byte* c, word32* wc_u24) +{ + *wc_u24 = ((word32)c[0] << 16) | (c[1] << 8) | c[2]; +} + +/* convert opaque to 16 bit integer */ +WC_STATIC WC_INLINE void ato16(const byte* c, word16* wc_u16) +{ + *wc_u16 = (word16) ((c[0] << 8) | (c[1])); +} + +/* convert opaque to 32 bit integer */ +WC_STATIC WC_INLINE void ato32(const byte* c, word32* wc_u32) +{ + *wc_u32 = ((word32)c[0] << 24) | ((word32)c[1] << 16) | (c[2] << 8) | c[3]; +} + + +WC_STATIC WC_INLINE word32 btoi(byte b) +{ + return (word32)(b - 0x30); +} +#endif + + +#ifndef WOLFSSL_NO_CT_OPS +/* Constant time - mask set when a > b. */ +WC_STATIC WC_INLINE byte ctMaskGT(int a, int b) +{ + return (((word32)a - b - 1) >> 31) - 1; +} + +/* Constant time - mask set when a >= b. */ +WC_STATIC WC_INLINE byte ctMaskGTE(int a, int b) +{ + return (((word32)a - b ) >> 31) - 1; +} + +/* Constant time - mask set when a >= b. */ +WC_STATIC WC_INLINE int ctMaskIntGTE(int a, int b) +{ + return (((word32)a - b ) >> 31) - 1; +} + +/* Constant time - mask set when a < b. */ +WC_STATIC WC_INLINE byte ctMaskLT(int a, int b) +{ + return (((word32)b - a - 1) >> 31) - 1; +} + +/* Constant time - mask set when a <= b. */ +WC_STATIC WC_INLINE byte ctMaskLTE(int a, int b) +{ + return (((word32)b - a ) >> 31) - 1; +} + +/* Constant time - mask set when a == b. */ +WC_STATIC WC_INLINE byte ctMaskEq(int a, int b) +{ + return (~ctMaskGT(a, b)) & (~ctMaskLT(a, b)); +} + +WC_STATIC WC_INLINE word16 ctMask16GT(int a, int b) +{ + return (((word32)a - b - 1) >> 31) - 1; +} + +WC_STATIC WC_INLINE word16 ctMask16LT(int a, int b) +{ + return (((word32)a - b - 1) >> 31) - 1; +} + +WC_STATIC WC_INLINE word16 ctMask16Eq(int a, int b) +{ + return (~ctMask16GT(a, b)) & (~ctMask16LT(a, b)); +} + +/* Constant time - mask set when a != b. */ +WC_STATIC WC_INLINE byte ctMaskNotEq(int a, int b) +{ + return ctMaskGT(a, b) | ctMaskLT(a, b); +} + +/* Constant time - select a when mask is set and b otherwise. */ +WC_STATIC WC_INLINE byte ctMaskSel(byte m, byte a, byte b) +{ + return (b & ((byte)~(word32)m)) | (a & m); +} + +/* Constant time - select integer a when mask is set and integer b otherwise. */ +WC_STATIC WC_INLINE int ctMaskSelInt(byte m, int a, int b) +{ + return (b & (~(signed int)(signed char)m)) | + (a & ( (signed int)(signed char)m)); +} + +/* Constant time - bit set when a <= b. */ +WC_STATIC WC_INLINE byte ctSetLTE(int a, int b) +{ + return ((word32)a - b - 1) >> 31; +} +#endif + + +#undef WC_STATIC + +#endif /* !WOLFSSL_MISC_INCLUDED && !NO_INLINE */ #endif /* WOLF_CRYPT_MISC_C */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/pkcs12.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/pkcs12.c new file mode 100644 index 000000000..8ae500417 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/pkcs12.c @@ -0,0 +1,2403 @@ +/* pkcs12.c + * + * Copyright (C) 2006-2020 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_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12) + +#include +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif +#include +#include +#include + + +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } + +enum { + WC_PKCS12_KeyBag = 667, + WC_PKCS12_ShroudedKeyBag = 668, + WC_PKCS12_CertBag = 669, + WC_PKCS12_CertBag_Type1 = 675, + WC_PKCS12_CrlBag = 670, + WC_PKCS12_SecretBag = 671, + WC_PKCS12_SafeContentsBag = 672, + WC_PKCS12_DATA = 651, + WC_PKCS12_ENCRYPTED_DATA = 656, + + WC_PKCS12_DATA_OBJ_SZ = 11, +}; + +static const byte WC_PKCS12_ENCRYPTED_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06}; +static const byte WC_PKCS12_DATA_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01}; +static const byte WC_PKCS12_CertBag_Type1_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x16, 0x01}; +static const byte WC_PKCS12_CertBag_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x03}; +static const byte WC_PKCS12_KeyBag_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x01}; +static const byte WC_PKCS12_ShroudedKeyBag_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x02}; + + +typedef struct ContentInfo { + byte* data; + struct ContentInfo* next; + word32 encC; /* encryptedContent */ + word32 dataSz; + int type; /* DATA / encrypted / enveloped */ +} ContentInfo; + + +typedef struct AuthenticatedSafe { + ContentInfo* CI; + byte* data; /* T contents.... */ + word32 oid; /* encrypted or not */ + word32 numCI; /* number of Content Info structs */ + word32 dataSz; +} AuthenticatedSafe; + + +typedef struct MacData { + byte* digest; + byte* salt; + word32 oid; + word32 digestSz; + word32 saltSz; + int itt; /* number of iterations when creating HMAC key */ +} MacData; + + +struct WC_PKCS12 { + void* heap; + AuthenticatedSafe* safe; + MacData* signData; + word32 oid; /* DATA / Enveloped DATA ... */ +}; + + +/* for friendlyName, localKeyId .... */ +typedef struct WC_PKCS12_ATTRIBUTE { + byte* data; + word32 oid; + word32 dataSz; +} WC_PKCS12_ATTRIBUTE; + + +WC_PKCS12* wc_PKCS12_new(void) +{ + WC_PKCS12* pkcs12 = (WC_PKCS12*)XMALLOC(sizeof(WC_PKCS12), + NULL, DYNAMIC_TYPE_PKCS); + if (pkcs12 == NULL) { + WOLFSSL_MSG("Memory issue when creating WC_PKCS12 struct"); + return NULL; + } + + XMEMSET(pkcs12, 0, sizeof(WC_PKCS12)); + + return pkcs12; +} + + +static void freeSafe(AuthenticatedSafe* safe, void* heap) +{ + int i; + + if (safe == NULL) { + return; + } + + /* free content info structs */ + for (i = safe->numCI; i > 0; i--) { + ContentInfo* ci = safe->CI; + safe->CI = ci->next; + XFREE(ci, heap, DYNAMIC_TYPE_PKCS); + } + if (safe->data != NULL) { + XFREE(safe->data, heap, DYNAMIC_TYPE_PKCS); + } + XFREE(safe, heap, DYNAMIC_TYPE_PKCS); + + (void)heap; +} + + +void wc_PKCS12_free(WC_PKCS12* pkcs12) +{ + void* heap; + + /* if null pointer is passed in do nothing */ + if (pkcs12 == NULL) { + WOLFSSL_MSG("Trying to free null WC_PKCS12 object"); + return; + } + + heap = pkcs12->heap; + if (pkcs12->safe != NULL) { + freeSafe(pkcs12->safe, heap); + } + + /* free mac data */ + if (pkcs12->signData != NULL) { + if (pkcs12->signData->digest != NULL) { + XFREE(pkcs12->signData->digest, heap, DYNAMIC_TYPE_DIGEST); + pkcs12->signData->digest = NULL; + } + if (pkcs12->signData->salt != NULL) { + 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; +} + + +static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, + word32* idx, int maxIdx) +{ + AuthenticatedSafe* safe; + word32 oid; + word32 localIdx = *idx; + int ret; + int size = 0; + byte tag; + + safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), pkcs12->heap, + DYNAMIC_TYPE_PKCS); + if (safe == NULL) { + return MEMORY_E; + } + XMEMSET(safe, 0, sizeof(AuthenticatedSafe)); + + ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, maxIdx); + if (ret < 0) { + WOLFSSL_LEAVE("Get object id failed", ret); + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + + safe->oid = oid; + /* check tag, length */ + if (GetASNTag(input, &localIdx, &tag, maxIdx) < 0) { + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + WOLFSSL_MSG("Unexpected tag in PKCS12 DER"); + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { + freeSafe(safe, pkcs12->heap); + return ret; + } + + switch (oid) { + case WC_PKCS12_ENCRYPTED_DATA: + WOLFSSL_MSG("Found PKCS12 OBJECT: ENCRYPTED DATA\n"); + break; + + case WC_PKCS12_DATA: + WOLFSSL_MSG("Found PKCS12 OBJECT: DATA"); + /* get octets holding contents */ + if (GetASNTag(input, &localIdx, &tag, maxIdx) < 0) { + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + + if (tag != ASN_OCTET_STRING) { + WOLFSSL_MSG("Wrong tag with content PKCS12 type DATA"); + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { + freeSafe(safe, pkcs12->heap); + return ret; + } + + break; + } + + safe->dataSz = size; + safe->data = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS); + if (safe->data == NULL) { + freeSafe(safe, pkcs12->heap); + return MEMORY_E; + } + XMEMCPY(safe->data, input + localIdx, size); + *idx = localIdx; + + /* an instance of AuthenticatedSafe is created from + * ContentInfo's strung together in a SEQUENCE. Here we iterate + * through the ContentInfo's and add them to our + * AuthenticatedSafe struct */ + localIdx = 0; + input = safe->data; + { + int CISz; + ret = GetSequence(input, &localIdx, &CISz, safe->dataSz); + if (ret < 0) { + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + CISz += localIdx; + while ((int)localIdx < CISz) { + int curSz = 0; + word32 curIdx; + ContentInfo* ci = NULL; + + #ifdef WOLFSSL_DEBUG_PKCS12 + printf("\t\tlooking for Content Info.... "); + #endif + + if ((ret = GetSequence(input, &localIdx, &curSz, safe->dataSz)) + < 0) { + freeSafe(safe, pkcs12->heap); + return ret; + } + + if (curSz > CISz) { + /* subset should not be larger than universe */ + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + + curIdx = localIdx; + if ((ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, + safe->dataSz)) < 0) { + WOLFSSL_LEAVE("Get object id failed", ret); + freeSafe(safe, pkcs12->heap); + return ret; + } + + /* create new content info struct ... possible OID sanity check? */ + ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), pkcs12->heap, + DYNAMIC_TYPE_PKCS); + if (ci == NULL) { + freeSafe(safe, pkcs12->heap); + return MEMORY_E; + } + + ci->type = oid; + ci->dataSz = curSz - (localIdx-curIdx); + ci->data = (byte*)input + localIdx; + localIdx += ci->dataSz; + + #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: + printf("CONTENT INFO: DATA, size = %d\n", ci->dataSz); + break; + default: + printf("CONTENT INFO: UNKNOWN, size = %d\n", ci->dataSz); + } + #endif + + /* insert to head of list */ + ci->next = safe->CI; + safe->CI = ci; + safe->numCI += 1; + } + } + + pkcs12->safe = safe; + *idx += localIdx; + + return ret; +} + + +/* optional mac data */ +static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, + word32 totalSz) +{ + MacData* mac; + word32 curIdx = *idx; + word32 oid = 0; + int size, ret; + byte tag; + + /* Digest Info : Sequence + * DigestAlgorithmIdentifier + * Digest + */ + if ((ret = GetSequence(mem, &curIdx, &size, totalSz)) <= 0) { + WOLFSSL_MSG("Failed to get PKCS12 sequence"); + return ret; + } + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("\t\tSEQUENCE: DigestInfo size = %d\n", size); +#endif + + mac = (MacData*)XMALLOC(sizeof(MacData), pkcs12->heap, DYNAMIC_TYPE_PKCS); + if (mac == NULL) { + return MEMORY_E; + } + XMEMSET(mac, 0, sizeof(MacData)); + + /* DigestAlgorithmIdentifier */ + if ((ret = GetAlgoId(mem, &curIdx, &oid, oidIgnoreType, totalSz)) < 0) { + WOLFSSL_MSG("Failed to get PKCS12 sequence"); + XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); + return ret; + } + mac->oid = oid; + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("\t\tALGO ID = %d\n", oid); +#endif + + /* Digest: should be octet type holding digest */ + if (GetASNTag(mem, &curIdx, &tag, totalSz) < 0) { + XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); + return ASN_PARSE_E; + } + + if (tag != ASN_OCTET_STRING) { + WOLFSSL_MSG("Failed to get digest"); + XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); + return ASN_PARSE_E; + } + + if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) { + XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); + return ret; + } + mac->digestSz = size; + mac->digest = (byte*)XMALLOC(mac->digestSz, pkcs12->heap, + DYNAMIC_TYPE_DIGEST); + if (mac->digest == NULL || mac->digestSz + curIdx > totalSz) { + ERROR_OUT(MEMORY_E, exit_gsd); + } + XMEMCPY(mac->digest, mem + curIdx, mac->digestSz); + +#ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("\t\tDigest = "), p = (byte*)mem+curIdx; + p < (byte*)mem + curIdx + mac->digestSz; + printf("%02X", *p), p++); + printf(" : size = %d\n", mac->digestSz); + } +#endif + + curIdx += mac->digestSz; + + /* get salt, should be octet string */ + if (GetASNTag(mem, &curIdx, &tag, totalSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_gsd); + } + + if (tag != ASN_OCTET_STRING) { + WOLFSSL_MSG("Failed to get salt"); + ERROR_OUT(ASN_PARSE_E, exit_gsd); + } + + if ((ret = GetLength(mem, &curIdx, &size, totalSz)) < 0) { + goto exit_gsd; + } + mac->saltSz = size; + mac->salt = (byte*)XMALLOC(mac->saltSz, pkcs12->heap, DYNAMIC_TYPE_SALT); + if (mac->salt == NULL || mac->saltSz + curIdx > totalSz) { + ERROR_OUT(MEMORY_E, exit_gsd); + } + XMEMCPY(mac->salt, mem + curIdx, mac->saltSz); + +#ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("\t\tSalt = "), p = (byte*)mem + curIdx; + p < (byte*)mem + curIdx + mac->saltSz; + printf("%02X", *p), p++); + printf(" : size = %d\n", mac->saltSz); + } +#endif + + curIdx += mac->saltSz; + + /* check for MAC iterations, default to 1 */ + mac->itt = WC_PKCS12_MAC_DEFAULT; + if (curIdx < totalSz) { + int number = 0; + if ((ret = GetShortInt(mem, &curIdx, &number, totalSz)) >= 0) { + /* found a iteration value */ + mac->itt = number; + } + } + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("\t\tITERATIONS : %d\n", mac->itt); +#endif + + *idx = curIdx; + pkcs12->signData = mac; + ret = 0; /* success */ + +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; +} + + +/* expects PKCS12 signData to be set up with OID + * + * returns the size of mac created on success. A negative value will be returned + * in the case that an error happened. + */ +static int wc_PKCS12_create_mac(WC_PKCS12* pkcs12, byte* data, word32 dataSz, + const byte* psw, word32 pswSz, byte* out, word32 outSz) +{ + Hmac hmac; + MacData* mac; + int ret, kLen; + enum wc_HashType hashT; + int idx = 0; + int id = 3; /* value from RFC 7292 indicating key is used for MAC */ + word32 i; + byte unicodePasswd[MAX_UNICODE_SZ]; + byte key[MAX_KEY_SIZE]; + + if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL || + out == NULL) { + return BAD_FUNC_ARG; + } + + mac = pkcs12->signData; + + /* unicode set up from asn.c */ + if ((pswSz * 2 + 2) > (int)sizeof(unicodePasswd)) { + WOLFSSL_MSG("PKCS12 max unicode size too small"); + return UNICODE_SIZE_E; + } + + for (i = 0; i < pswSz; i++) { + unicodePasswd[idx++] = 0x00; + unicodePasswd[idx++] = (byte)psw[i]; + } + /* add trailing NULL */ + unicodePasswd[idx++] = 0x00; + unicodePasswd[idx++] = 0x00; + + /* get hash type used and resulting size of HMAC key */ + hashT = wc_OidGetHash(mac->oid); + if (hashT == WC_HASH_TYPE_NONE) { + WOLFSSL_MSG("Unsupported hash used"); + return BAD_FUNC_ARG; + } + kLen = wc_HashGetDigestSize(hashT); + + /* check out buffer is large enough */ + if (kLen < 0 || outSz < (word32)kLen) { + return BAD_FUNC_ARG; + } + + /* idx contains size of unicodePasswd */ + if ((ret = wc_PKCS12_PBKDF_ex(key, unicodePasswd, idx, mac->salt, + mac->saltSz, mac->itt, kLen, (int)hashT, id, pkcs12->heap)) < 0) { + return ret; + } + + /* now that key has been created use it to get HMAC hash on data */ + if ((ret = wc_HmacInit(&hmac, pkcs12->heap, INVALID_DEVID)) != 0) { + return ret; + } + ret = wc_HmacSetKey(&hmac, (int)hashT, key, kLen); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, data, dataSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, out); + wc_HmacFree(&hmac); + + if (ret != 0) + return ret; + + return kLen; /* same as digest size */ +} + + +/* check mac on pkcs12, pkcs12->mac has been sanity checked before entering * + * returns the result of comparison, success is 0 */ +static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz, + const byte* psw, word32 pswSz) +{ + MacData* mac; + int ret; + byte digest[WC_MAX_DIGEST_SIZE]; + + if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL) { + return BAD_FUNC_ARG; + } + + mac = pkcs12->signData; + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("Verifying MAC with OID = %d\n", mac->oid); +#endif + + /* check if this builds digest size is too small */ + if (mac->digestSz > WC_MAX_DIGEST_SIZE) { + WOLFSSL_MSG("PKCS12 max digest size too small"); + return BAD_FUNC_ARG; + } + + if ((ret = wc_PKCS12_create_mac(pkcs12, data, dataSz, psw, pswSz, + digest, WC_MAX_DIGEST_SIZE)) < 0) { + return ret; + } + +#ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("\t\tHash = "), p = (byte*)digest; + p < (byte*)digest + mac->digestSz; + printf("%02X", *p), p++); + printf(" : size = %d\n", mac->digestSz); + } +#endif + + return XMEMCMP(digest, mac->digest, mac->digestSz); +} + + +/* Convert DER format stored in der buffer to WC_PKCS12 struct + * Puts the raw contents of Content Info into structure without completely + * parsing or decoding. + * 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) +{ + word32 idx = 0; + word32 totalSz = 0; + int ret; + int size = 0; + int version = 0; + + WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio"); + + if (der == NULL || pkcs12 == NULL) { + return BAD_FUNC_ARG; + } + + totalSz = derSz; + if ((ret = GetSequence(der, &idx, &size, totalSz)) <= 0) { + WOLFSSL_MSG("Failed to get PKCS12 sequence"); + return ret; + } + + /* get version */ + if ((ret = GetMyVersion(der, &idx, &version, totalSz)) < 0) { + return ret; + } + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("\nBEGIN: PKCS12 size = %d\n", totalSz); + printf("version = %d\n", version); +#endif + + if (version != WC_PKCS12_VERSION_DEFAULT) { + WOLFSSL_MSG("PKCS12 unsupported version!"); + return ASN_VERSION_E; + } + + if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) { + return ret; + } + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("\tSEQUENCE: AuthenticatedSafe size = %d\n", size); +#endif + + if ((ret = GetSafeContent(pkcs12, der, &idx, size + idx)) < 0) { + WOLFSSL_MSG("GetSafeContent error"); + return ret; + } + + /* if more buffer left check for MAC data */ + if (idx < totalSz) { + if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) { + WOLFSSL_MSG("Ignoring unknown data at end of PKCS12 DER buffer"); + } + else { + #ifdef WOLFSSL_DEBUG_PKCS12 + printf("\tSEQUENCE: Signature size = %d\n", size); + #endif + + if ((ret = GetSignData(pkcs12, der, &idx, totalSz)) < 0) { + return ASN_PARSE_E; + } + } + } + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("END: PKCS12\n"); +#endif + + return ret; +} + +/* Convert WC_PKCS12 struct to allocated DER buffer. + * pkcs12 : non-null pkcs12 pointer + * der : pointer-pointer to der buffer. If NULL space will be + * allocated for der, which must be freed by application. + * derSz : size of buffer passed in when der is not NULL. NULL arg disables + * sanity checks on buffer read/writes. Max size gets set to derSz when + * the "der" buffer passed in is NULL and LENGTH_ONLY_E is returned. + * return size of DER on success and negative on failure. + */ +int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz) +{ + int ret = 0; + word32 seqSz = 0, verSz = 0, totalSz = 0, idx = 0, sdBufSz = 0; + byte *buf = NULL; + byte ver[MAX_VERSION_SZ]; + byte seq[MAX_SEQ_SZ]; + byte *sdBuf = NULL; + + if ((pkcs12 == NULL) || (pkcs12->safe == NULL) || + (der == NULL && derSz == NULL)) { + return BAD_FUNC_ARG; + } + + /* Create the MAC portion */ + if (pkcs12->signData != NULL) { + MacData *mac = (MacData*)pkcs12->signData; + word32 innerSz = 0; + word32 outerSz = 0; + + /* get exact size */ + { + byte ASNLENGTH[MAX_LENGTH_SZ]; + byte ASNSHORT[MAX_SHORT_SZ]; + byte ASNALGO[MAX_ALGO_SZ]; + word32 tmpIdx = 0; + + /* algo id */ + innerSz += SetAlgoID(mac->oid, ASNALGO, oidHashType, 0); + + /* Octet string holding digest */ + innerSz += ASN_TAG_SZ; + innerSz += SetLength(mac->digestSz, ASNLENGTH); + innerSz += mac->digestSz; + + /* salt */ + outerSz += ASN_TAG_SZ; + outerSz += SetLength(mac->saltSz, ASNLENGTH); + outerSz += mac->saltSz; + + /* MAC iterations */ + outerSz += SetShortInt(ASNSHORT, &tmpIdx, mac->itt, MAX_SHORT_SZ); + + /* sequence of inner data */ + outerSz += SetSequence(innerSz, seq); + outerSz += innerSz; + } + sdBufSz = outerSz + SetSequence(outerSz, seq); + sdBuf = (byte*)XMALLOC(sdBufSz, pkcs12->heap, DYNAMIC_TYPE_PKCS); + if (sdBuf == NULL) { + ret = MEMORY_E; + } + + if (ret == 0) { + idx += SetSequence(outerSz, sdBuf); + idx += SetSequence(innerSz, &sdBuf[idx]); + + /* Set Algorithm Identifier */ + { + word32 algoIdSz; + + algoIdSz = SetAlgoID(mac->oid, &sdBuf[idx], oidHashType, 0); + if (algoIdSz == 0) { + ret = ALGO_ID_E; + } + else { + idx += algoIdSz; + } + } + } + + if (ret == 0) { + + + /* Octet string holding digest */ + idx += SetOctetString(mac->digestSz, &sdBuf[idx]); + XMEMCPY(&sdBuf[idx], mac->digest, mac->digestSz); + idx += mac->digestSz; + + /* Set salt */ + idx += SetOctetString(mac->saltSz, &sdBuf[idx]); + XMEMCPY(&sdBuf[idx], mac->salt, mac->saltSz); + idx += mac->saltSz; + + /* MAC iterations */ + { + int tmpSz; + word32 tmpIdx = 0; + byte ar[MAX_SHORT_SZ]; + tmpSz = SetShortInt(ar, &tmpIdx, mac->itt, MAX_SHORT_SZ); + if (tmpSz < 0) { + ret = tmpSz; + } + else { + XMEMCPY(&sdBuf[idx], ar, tmpSz); + } + } + totalSz += sdBufSz; + } + } + + /* Calculate size of der */ + if (ret == 0) { + totalSz += pkcs12->safe->dataSz; + + totalSz += 4; /* Octet string */ + + totalSz += 4; /* Element */ + + totalSz += 2 + sizeof(WC_PKCS12_DATA_OID); + + totalSz += 4; /* Seq */ + + ret = SetMyVersion(WC_PKCS12_VERSION_DEFAULT, ver, FALSE); + if (ret > 0) { + verSz = (word32)ret; + ret = 0; /* value larger than 0 is success */ + totalSz += verSz; + + seqSz = SetSequence(totalSz, seq); + totalSz += seqSz; + + /* check if getting length only */ + if (der == NULL && derSz != NULL) { + *derSz = totalSz; + XFREE(sdBuf, pkcs12->heap, DYNAMIC_TYPE_PKCS); + return LENGTH_ONLY_E; + } + + if (*der == NULL) { + /* Allocate if requested */ + buf = (byte*)XMALLOC(totalSz, NULL, DYNAMIC_TYPE_PKCS); + } + else { + buf = *der; + + /* sanity check on buffer size if passed in */ + if (derSz != NULL) { + if (*derSz < (int)totalSz) { + WOLFSSL_MSG("Buffer passed in is too small"); + ret = BUFFER_E; + } + } + } + } + } + + if (buf == NULL) { + ret = MEMORY_E; + } + + if (ret == 0) { + idx = 0; + + /* Copy parts to buf */ + XMEMCPY(&buf[idx], seq, seqSz); + idx += seqSz; + + XMEMCPY(&buf[idx], ver, verSz); + idx += verSz; + + seqSz = SetSequence(totalSz - sdBufSz - idx - 4, seq); + XMEMCPY(&buf[idx], seq, seqSz); + idx += seqSz; + + /* OID */ + idx += SetObjectId(sizeof(WC_PKCS12_DATA_OID), &buf[idx]); + XMEMCPY(&buf[idx], WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID)); + idx += sizeof(WC_PKCS12_DATA_OID); + + /* Element */ + buf[idx++] = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC; + idx += SetLength(totalSz - sdBufSz - idx - 3, &buf[idx]); + + /* Octet string */ + idx += SetOctetString(totalSz - sdBufSz - idx - 4, &buf[idx]); + + XMEMCPY(&buf[idx], pkcs12->safe->data, pkcs12->safe->dataSz); + idx += pkcs12->safe->dataSz; + + if (pkcs12->signData != NULL) { + XMEMCPY(&buf[idx], sdBuf, sdBufSz); + } + + if (*der == NULL) { + /* Point to start of data allocated for DER */ + *der = buf; + } + else { + /* Increment pointer to byte past DER */ + *der = &buf[totalSz]; + } + + /* Return size of der */ + ret = totalSz; + } + + XFREE(sdBuf, pkcs12->heap, DYNAMIC_TYPE_PKCS); + /* Allocation of buf was the last time ret could be a failure, + * so no need to free here */ + + return ret; +} + + +/* helper function to free WC_DerCertList */ +void wc_FreeCertList(WC_DerCertList* list, void* heap) +{ + WC_DerCertList* current = list; + WC_DerCertList* next; + + if (list == NULL) { + return; + } + + while (current != NULL) { + next = current->next; + if (current->buffer != NULL) { + XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); + } + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + current = next; + } + + (void)heap; +} + +static void freeDecCertList(WC_DerCertList** list, byte** pkey, word32* pkeySz, + byte** cert, word32* certSz, void* heap) +{ + 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; + } +} + + +/* 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 + * + * NOTE: can parse with USER RSA enabled but may return cert that is not the + * pair for the key when using RSA key pairs. + * + * pkcs12 : non-null WC_PKCS12 struct + * psw : password to use for PKCS12 decode + * pkey : Private key returned + * cert : x509 cert returned + * ca : optional ca returned + */ +int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, + byte** pkey, word32* pkeySz, byte** cert, word32* certSz, + WC_DerCertList** ca) +{ + ContentInfo* ci = NULL; + WC_DerCertList* certList = NULL; + WC_DerCertList* tailList = NULL; + byte* buf = NULL; + word32 i, oid; + int ret, pswSz; + word32 algId; + + WOLFSSL_ENTER("wc_PKCS12_parse"); + + if (pkcs12 == NULL || psw == NULL || cert == NULL || certSz == NULL || + pkey == NULL || pkeySz == NULL) { + return BAD_FUNC_ARG; + } + + pswSz = (int)XSTRLEN(psw); + *cert = NULL; + *pkey = NULL; + if (ca != NULL) + *ca = NULL; + + /* if there is sign data then verify the MAC */ + if (pkcs12->signData != NULL ) { + if ((ret = wc_PKCS12_verify(pkcs12, pkcs12->safe->data, + pkcs12->safe->dataSz, (byte*)psw, pswSz)) != 0) { + WOLFSSL_MSG("PKCS12 Bad MAC on verify"); + WOLFSSL_LEAVE("wc_PKCS12_parse verify ", ret); + return MAC_CMP_FAILED_E; + } + } + + if (pkcs12->safe == NULL) { + WOLFSSL_MSG("No PKCS12 safes to parse"); + return BAD_FUNC_ARG; + } + + /* Decode content infos */ + ci = pkcs12->safe->CI; + for (i = 0; i < pkcs12->safe->numCI; i++) { + byte* data; + word32 idx = 0; + int size, totalSz; + byte tag; + + if (ci->type == WC_PKCS12_ENCRYPTED_DATA) { + int number; + + WOLFSSL_MSG("Decrypting PKCS12 Content Info Container"); + data = ci->data; + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { + goto exit_pk12par; + } + + if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) { + goto exit_pk12par; + } + + if ((ret = GetShortInt(data, &idx, &number, ci->dataSz)) < 0) { + goto exit_pk12par; + } + + if (number != 0) { + WOLFSSL_MSG("Expecting 0 for Integer with Encrypted PKCS12"); + } + + if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) { + 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"); + 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) { + ERROR_OUT(MEMORY_E, exit_pk12par); + } + XMEMCPY(buf, data + idx, size); + + if ((ret = DecryptContent(buf, size, psw, pswSz)) < 0) { + WOLFSSL_MSG("Decryption failed, algorithm not compiled in?"); + goto exit_pk12par; + } + + data = buf; + idx = 0; + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("\tData = "), p = (byte*)buf; + p < (byte*)buf + size; + printf("%02X", *p), p++); + printf("\n"); + } + #endif + } + else { /* type DATA */ + WOLFSSL_MSG("Parsing PKCS12 DATA Content Info Container"); + data = ci->data; + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if (tag != ASN_OCTET_STRING) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { + goto exit_pk12par; + } + + } + + /* parse through bags in ContentInfo */ + if ((ret = GetSequence(data, &idx, &totalSz, ci->dataSz)) < 0) { + goto exit_pk12par; + } + totalSz += idx; + + while ((int)idx < totalSz) { + int bagSz; + if ((ret = GetSequence(data, &idx, &bagSz, ci->dataSz)) < 0) { + goto exit_pk12par; + } + bagSz += idx; + + if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType, + ci->dataSz)) < 0) { + goto exit_pk12par; + } + + switch (oid) { + case WC_PKCS12_KeyBag: /* 667 */ + WOLFSSL_MSG("PKCS12 Key Bag found"); + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { + if (ret == 0) + ret = ASN_PARSE_E; + goto exit_pk12par; + } + if (*pkey == NULL) { + *pkey = (byte*)XMALLOC(size, pkcs12->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (*pkey == NULL) { + ERROR_OUT(MEMORY_E, exit_pk12par); + } + XMEMCPY(*pkey, data + idx, size); + *pkeySz = ToTraditional_ex(*pkey, size, &algId); + } + + #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 (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, + ci->dataSz)) < 0) { + goto exit_pk12par; + } + + k = (byte*)XMALLOC(size, pkcs12->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (k == NULL) { + ERROR_OUT(MEMORY_E, exit_pk12par); + } + XMEMCPY(k, data + idx, size); + + /* overwrites input, be warned */ + if ((ret = ToTraditionalEnc(k, size, psw, pswSz, + &algId)) < 0) { + XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); + goto exit_pk12par; + } + + if (ret < size) { + /* shrink key buffer */ + 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; + + if (*pkey == NULL) { + *pkey = k; + *pkeySz = size; + } + else { /* only expecting one key */ + XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + idx += size; + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("\tKey = "), p = (byte*)k; + p < (byte*)k + ret; + printf("%02X", *p), p++); + printf("\n"); + } + #endif + } + break; + + case WC_PKCS12_CertBag: /* 669 */ + { + WC_DerCertList* node; + WOLFSSL_MSG("PKCS12 Cert Bag found"); + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { + goto exit_pk12par; + } + + /* get cert bag type */ + if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) <0) { + goto exit_pk12par; + } + + if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType, + ci->dataSz)) < 0) { + goto exit_pk12par; + } + + switch (oid) { + case WC_PKCS12_CertBag_Type1: /* 675 */ + /* type 1 */ + WOLFSSL_MSG("PKCS12 cert bag type 1"); + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if (tag != (ASN_CONSTRUCTED | + ASN_CONTEXT_SPECIFIC)) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) + <= 0) { + if (ret == 0) + ret = ASN_PARSE_E; + goto exit_pk12par; + } + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if (tag != ASN_OCTET_STRING) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) + < 0) { + goto exit_pk12par; + } + break; + default: + WOLFSSL_MSG("Unknown PKCS12 cert bag type"); + } + + if (size + idx > (word32)bagSz) { + 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) { + ERROR_OUT(MEMORY_E, exit_pk12par); + } + XMEMSET(node, 0, sizeof(WC_DerCertList)); + + node->buffer = (byte*)XMALLOC(size, pkcs12->heap, + DYNAMIC_TYPE_PKCS); + if (node->buffer == NULL) { + XFREE(node, pkcs12->heap, DYNAMIC_TYPE_PKCS); + ERROR_OUT(MEMORY_E, exit_pk12par); + } + XMEMCPY(node->buffer, data + idx, size); + node->bufferSz = size; + + /* put the new node into the list */ + if (certList != NULL) { + WOLFSSL_MSG("Pushing new cert onto queue"); + tailList->next = node; + tailList = node; + } + else { + certList = node; + tailList = node; + } + + /* on to next */ + idx += size; + } + break; + + case WC_PKCS12_CrlBag: /* 670 */ + WOLFSSL_MSG("PKCS12 CRL BAG not yet supported"); + break; + + case WC_PKCS12_SecretBag: /* 671 */ + WOLFSSL_MSG("PKCS12 Secret BAG not yet supported"); + break; + + case WC_PKCS12_SafeContentsBag: /* 672 */ + WOLFSSL_MSG("PKCS12 Safe Contents BAG not yet supported"); + break; + + default: + WOLFSSL_MSG("Unknown PKCS12 BAG type found"); + } + + /* Attribute, unknown bag or unsupported */ + if ((int)idx < bagSz) { + idx = bagSz; /* skip for now */ + } + } + + /* free temporary buffer */ + if (buf != NULL) { + 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 */ + 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; + } + else { + /* free list, not wanted */ + wc_FreeCertList(certList, pkcs12->heap); + } + (void)tailList; /* not used */ + + 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; + } + + wc_FreeCertList(certList, pkcs12->heap); + } + + return ret; +} + + +/* Helper function to shroud keys. + * + * pkcs12 structure to use with shrouding key + * rng random number generator used + * out buffer to hold results + * outSz size of out buffer + * key key that is going to be shrouded + * keySz size of key buffer + * vAlgo algorithm version + * pass password to use + * passSz size of pass buffer + * itt number of iterations + * + * returns the size of the shrouded key on success + */ +static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng, + byte* out, word32* outSz, byte* key, word32 keySz, int vAlgo, + const char* pass, int passSz, int itt) +{ + void* heap; + word32 tmpIdx = 0; + int vPKCS = 1; /* PKCS#12 default set to 1 */ + word32 sz; + word32 totalSz = 0; + int ret; + + + if (outSz == NULL || pkcs12 == NULL || rng == NULL || key == NULL || + pass == NULL) { + return BAD_FUNC_ARG; + } + + heap = wc_PKCS12_GetHeap(pkcs12); + + /* check if trying to get size */ + if (out != NULL) { + tmpIdx += MAX_LENGTH_SZ + 1; /* save room for length and tag (+1) */ + sz = *outSz - tmpIdx; + } + + /* case of no encryption */ + if (vAlgo < 0) { + const byte* curveOID = NULL; + word32 oidSz = 0; + int algoID; + + WOLFSSL_MSG("creating PKCS12 Key Bag"); + + /* check key type and get OID if ECC */ + if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap)) + < 0) { + return ret; + } + + /* PKCS#8 wrapping around key */ + ret = wc_CreatePKCS8Key(out + tmpIdx, &sz, key, keySz, algoID, + curveOID, oidSz); + } + else { + WOLFSSL_MSG("creating PKCS12 Shrouded Key Bag"); + + if (vAlgo == PBE_SHA1_DES) { + vPKCS = PKCS5; + vAlgo = 10; + } + + ret = UnTraditionalEnc(key, keySz, out + tmpIdx, &sz, pass, passSz, + vPKCS, vAlgo, NULL, 0, itt, rng, heap); + } + if (ret == LENGTH_ONLY_E) { + *outSz = sz + MAX_LENGTH_SZ + 1; + return LENGTH_ONLY_E; + } + if (ret < 0) { + return ret; + } + + totalSz += ret; + + /* out should not be null at this point but check before writing */ + if (out == NULL) { + return BAD_FUNC_ARG; + } + + /* rewind index and set tag and length */ + tmpIdx -= MAX_LENGTH_SZ + 1; + sz = SetExplicit(0, ret, out + tmpIdx); + tmpIdx += sz; totalSz += sz; + XMEMMOVE(out + tmpIdx, out + MAX_LENGTH_SZ + 1, ret); + + return totalSz; +} + + +/* Helper function to create key bag. + * + * pkcs12 structure to use with key bag + * rng random number generator used + * out buffer to hold results + * outSz size of out buffer + * key key that is going into key bag + * keySz size of key buffer + * algo algorithm version + * iter number of iterations + * pass password to use + * passSz size of pass buffer + * + * returns the size of the key bag on success + */ +static int wc_PKCS12_create_key_bag(WC_PKCS12* pkcs12, WC_RNG* rng, + byte* out, word32* outSz, byte* key, word32 keySz, int algo, int iter, + char* pass, int passSz) +{ + void* heap; + byte* tmp; + word32 length = 0; + word32 idx = 0; + word32 totalSz = 0; + word32 sz; + word32 i; + word32 tmpSz; + int ret; + + /* get max size for shrouded key */ + ret = wc_PKCS12_shroud_key(pkcs12, rng, NULL, &length, key, keySz, + algo, pass, passSz, iter); + if (ret != LENGTH_ONLY_E && ret < 0) { + return ret; + } + + if (out == NULL) { + *outSz = MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ + 1 + MAX_LENGTH_SZ + + length; + return LENGTH_ONLY_E; + } + + heap = wc_PKCS12_GetHeap(pkcs12); + + /* leave room for sequence */ + idx += MAX_SEQ_SZ; + + if (algo < 0) { /* not encrypted */ + out[idx++] = ASN_OBJECT_ID; totalSz++; + sz = SetLength(sizeof(WC_PKCS12_KeyBag_OID), out + idx); + idx += sz; totalSz += sz; + for (i = 0; i < sizeof(WC_PKCS12_KeyBag_OID); i++) { + out[idx++] = WC_PKCS12_KeyBag_OID[i]; totalSz++; + } + } + else { /* encrypted */ + out[idx++] = ASN_OBJECT_ID; totalSz++; + sz = SetLength(sizeof(WC_PKCS12_ShroudedKeyBag_OID), out + idx); + idx += sz; totalSz += sz; + for (i = 0; i < sizeof(WC_PKCS12_ShroudedKeyBag_OID); i++) { + out[idx++] = WC_PKCS12_ShroudedKeyBag_OID[i]; totalSz++; + } + } + + /* shroud key */ + tmp = (byte*)XMALLOC(length, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + + ret = wc_PKCS12_shroud_key(pkcs12, rng, tmp, &length, key, keySz, + algo, pass, passSz, iter); + if (ret < 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + length = ret; + XMEMCPY(out + idx, tmp, length); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + totalSz += length; + + /* set beginning sequence */ + tmpSz = SetSequence(totalSz, out); + XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz); + + (void)heap; + return totalSz + tmpSz; +} + + +/* Helper function to create cert bag. + * + * pkcs12 structure to use with cert bag + * out buffer to hold results + * outSz size of out buffer + * cert cert that is going into cert bag + * certSz size of cert buffer + * + * returns the size of the cert bag on success + */ +static int wc_PKCS12_create_cert_bag(WC_PKCS12* pkcs12, + byte* out, word32* outSz, byte* cert, word32 certSz) +{ + word32 length = 0; + word32 idx = 0; + word32 totalSz = 0; + word32 sz; + int WC_CERTBAG_OBJECT_ID = 13; + int WC_CERTBAG1_OBJECT_ID = 12; + word32 i; + word32 tmpSz; + + if (out == NULL) { + *outSz = MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ + + MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 + + MAX_LENGTH_SZ + certSz; + return LENGTH_ONLY_E; + } + + /* check buffer size able to handle max size */ + if (*outSz < (MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ + + MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 + + MAX_LENGTH_SZ + certSz)) { + return BUFFER_E; + } + + /* save room for sequence */ + idx += MAX_SEQ_SZ; + + /* objectId WC_PKCS12_CertBag */ + out[idx++] = ASN_OBJECT_ID; totalSz++; + sz = SetLength(sizeof(WC_PKCS12_CertBag_OID), out + idx); + idx += sz; totalSz += sz; + for (i = 0; i < sizeof(WC_PKCS12_CertBag_OID); i++) { + out[idx++] = WC_PKCS12_CertBag_OID[i]; totalSz++; + } + + /**** Cert Bag type 1 ****/ + out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); totalSz++; + + /* save room for length and sequence */ + idx += MAX_LENGTH_SZ; + idx += MAX_SEQ_SZ; + + /* object id WC_PKCS12_CertBag_Type1 */ + out[idx++] = ASN_OBJECT_ID; length++; + sz = SetLength(sizeof(WC_PKCS12_CertBag_Type1_OID), out + idx); + idx += sz; length += sz; + for (i = 0; i < sizeof(WC_PKCS12_CertBag_Type1_OID); i++) { + out[idx++] = WC_PKCS12_CertBag_Type1_OID[i]; length++; + } + + out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); length++; + sz = 0; + idx += MAX_LENGTH_SZ; /* save room for length */ + + /* place the cert in the buffer */ + out[idx++] = ASN_OCTET_STRING; sz++; + tmpSz = SetLength(certSz, out + idx); + idx += tmpSz; sz += tmpSz; + XMEMCPY(out + idx, cert, certSz); + idx += certSz; sz += certSz; + + /* rewind idx and place length */ + idx -= (sz + MAX_LENGTH_SZ); + tmpSz = SetLength(sz, out + idx); + XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, sz); + idx += tmpSz + sz; length += tmpSz + sz; + + /* rewind idx and set sequence */ + idx -= (length + MAX_SEQ_SZ); + tmpSz = SetSequence(length, out + idx); + XMEMMOVE(out + idx + tmpSz, out + idx + MAX_SEQ_SZ, length); + length += tmpSz; + + /* place final length */ + idx -= MAX_LENGTH_SZ; + tmpSz = SetLength(length, out + idx); + XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length); + length += tmpSz; + + /* place final sequence */ + totalSz += length; + tmpSz = SetSequence(totalSz, out); + XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz); + + (void)pkcs12; + + return totalSz + tmpSz; +} + + +/* Helper function to encrypt content. + * + * pkcs12 structure to use with key bag + * rng random number generator used + * out buffer to hold results + * outSz size of out buffer + * content content to encrypt + * contentSz size of content buffer + * vAlgo algorithm version + * pass password to use + * passSz size of pass buffer + * iter number of iterations + * type content type i.e WC_PKCS12_ENCRYPTED_DATA or WC_PKCS12_DATA + * + * returns the size of result on success + */ +static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, + byte* out, word32* outSz, byte* content, word32 contentSz, int vAlgo, + const char* pass, int passSz, int iter, int type) +{ + void* heap; + int vPKCS = 1; /* PKCS#12 is always set to 1 */ + int ret; + byte* tmp; + word32 idx = 0; + word32 totalSz = 0; + word32 length = 0; + word32 tmpSz; + word32 encSz; + + byte seq[MAX_SEQ_SZ]; + + WOLFSSL_MSG("encrypting PKCS12 content"); + + heap = wc_PKCS12_GetHeap(pkcs12); + + /* ENCRYPTED DATA + * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC + * length + * sequence + * short int + * sequence + * get object id */ + if (type == WC_PKCS12_ENCRYPTED_DATA) { + word32 outerSz = 0; + + encSz = contentSz; + if ((ret = EncryptContent(NULL, contentSz, NULL, &encSz, + pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) { + if (ret != LENGTH_ONLY_E) { + return ret; + } + } + + /* calculate size */ + totalSz = SetObjectId(sizeof(WC_PKCS12_ENCRYPTED_OID), seq); + totalSz += sizeof(WC_PKCS12_ENCRYPTED_OID); + totalSz += ASN_TAG_SZ; + + length = SetMyVersion(0, seq, 0); + tmpSz = SetObjectId(sizeof(WC_PKCS12_DATA_OID), seq); + tmpSz += sizeof(WC_PKCS12_DATA_OID); + tmpSz += encSz; + length += SetSequence(tmpSz, seq) + tmpSz; + outerSz = SetSequence(length, seq) + length; + + totalSz += SetLength(outerSz, seq) + outerSz; + if (out == NULL) { + *outSz = totalSz + SetSequence(totalSz, seq); + return LENGTH_ONLY_E; + } + + if (*outSz < totalSz + SetSequence(totalSz, seq)) { + return BUFFER_E; + } + + idx = 0; + idx += SetSequence(totalSz, out + idx); + idx += SetObjectId(sizeof(WC_PKCS12_ENCRYPTED_OID), out + idx); + if (idx + sizeof(WC_PKCS12_ENCRYPTED_OID) > *outSz){ + return BUFFER_E; + } + XMEMCPY(out + idx, WC_PKCS12_ENCRYPTED_OID, + sizeof(WC_PKCS12_ENCRYPTED_OID)); + idx += sizeof(WC_PKCS12_ENCRYPTED_OID); + + if (idx + 1 > *outSz){ + return BUFFER_E; + } + out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); + idx += SetLength(outerSz, out + idx); + + idx += SetSequence(length, out + idx); + idx += SetMyVersion(0, out + idx, 0); + tmp = (byte*)XMALLOC(encSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + + if ((ret = EncryptContent(content, contentSz, tmp, &encSz, + pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + encSz = ret; + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("(size %u) Encrypted Content = ", encSz), + p = (byte*)tmp; + p < (byte*)tmp + encSz; + printf("%02X", *p), p++); + printf("\n"); + } + #endif + + idx += SetSequence(WC_PKCS12_DATA_OBJ_SZ + encSz, out + idx); + idx += SetObjectId(sizeof(WC_PKCS12_DATA_OID), out + idx); + if (idx + sizeof(WC_PKCS12_DATA_OID) > *outSz){ + WOLFSSL_MSG("Buffer not large enough for DATA OID"); + return BUFFER_E; + } + XMEMCPY(out + idx, WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID)); + idx += sizeof(WC_PKCS12_DATA_OID); + + /* copy over encrypted data */ + if (idx + encSz > *outSz){ + return BUFFER_E; + } + XMEMCPY(out + idx, tmp, encSz); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + idx += encSz; + return idx; + } + + /* DATA + * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC + * length + * ASN_OCTET_STRING + * length + * sequence containing all bags */ + if (type == WC_PKCS12_DATA) { + /* calculate size */ + totalSz = SetObjectId(sizeof(WC_PKCS12_DATA_OID), seq); + totalSz += sizeof(WC_PKCS12_DATA_OID); + totalSz += ASN_TAG_SZ; + + length = SetOctetString(contentSz, seq); + length += contentSz; + totalSz += SetLength(length, seq); + totalSz += length; + + if (out == NULL) { + *outSz = totalSz + SetSequence(totalSz, seq); + return LENGTH_ONLY_E; + } + + if (*outSz < (totalSz + SetSequence(totalSz, seq))) { + return BUFFER_E; + } + + /* place data in output buffer */ + idx = 0; + idx += SetSequence(totalSz, out); + idx += SetObjectId(sizeof(WC_PKCS12_DATA_OID), out + idx); + if (idx + sizeof(WC_PKCS12_DATA_OID) > *outSz){ + WOLFSSL_MSG("Buffer not large enough for DATA OID"); + return BUFFER_E; + } + XMEMCPY(out + idx, WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID)); + idx += sizeof(WC_PKCS12_DATA_OID); + + if (idx + 1 > *outSz){ + return BUFFER_E; + } + out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); + idx += SetLength(length, out + idx); + idx += SetOctetString(contentSz, out + idx); + + if (idx + contentSz > *outSz){ + return BUFFER_E; + } + XMEMCPY(out + idx, content, contentSz); + idx += contentSz; + + return idx; + } + + WOLFSSL_MSG("Unknown/Unsupported content type"); + return BAD_FUNC_ARG; +} + + +/* helper function to create the PKCS12 key content + * keyCiSz is output buffer size + * returns a pointer to be free'd by caller on success and NULL on failure */ +static byte* PKCS12_create_key_content(WC_PKCS12* pkcs12, int nidKey, + word32* keyCiSz, WC_RNG* rng, char* pass, word32 passSz, + byte* key, word32 keySz, int iter) +{ + byte* keyBuf; + word32 keyBufSz = 0; + byte* keyCi = NULL; + word32 tmpSz; + int ret; + int algo; + void* heap; + + heap = wc_PKCS12_GetHeap(pkcs12); + *keyCiSz = 0; + switch (nidKey) { + case PBE_SHA1_RC4_128: + algo = 1; + break; + + case PBE_SHA1_DES: + algo = 2; + break; + + case PBE_SHA1_DES3: + algo = 3; + break; + + /* no encryption */ + case -1: + algo = -1; + break; + + default: + WOLFSSL_MSG("Unknown/Unsupported key encryption"); + return NULL; + } + + /* get max size for key bag */ + ret = wc_PKCS12_create_key_bag(pkcs12, rng, NULL, &keyBufSz, key, keySz, + algo, iter, pass, passSz); + if (ret != LENGTH_ONLY_E && ret < 0) { + WOLFSSL_MSG("Error getting key bag size"); + return NULL; + } + + /* account for sequence around bag */ + keyBufSz += MAX_SEQ_SZ; + keyBuf = (byte*)XMALLOC(keyBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + WOLFSSL_MSG("Memory error creating keyBuf buffer"); + return NULL; + } + + ret = wc_PKCS12_create_key_bag(pkcs12, rng, keyBuf + MAX_SEQ_SZ, &keyBufSz, + key, keySz, algo, iter, pass, passSz); + if (ret < 0) { + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Error creating key bag"); + return NULL; + } + keyBufSz = ret; + + tmpSz = SetSequence(keyBufSz, keyBuf); + XMEMMOVE(keyBuf + tmpSz, keyBuf + MAX_SEQ_SZ, keyBufSz); + keyBufSz += tmpSz; + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + word32 i; + printf("(size %u) Key Bag = ", keyBufSz); + for (i = 0; i < keyBufSz; i++) + printf("%02X", keyBuf[i]); + printf("\n"); + } + #endif + ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, keyCiSz, + NULL, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA); + if (ret != LENGTH_ONLY_E) { + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Error getting key encrypt content size"); + return NULL; + } + keyCi = (byte*)XMALLOC(*keyCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (keyCi == NULL) { + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + ret = wc_PKCS12_encrypt_content(pkcs12, rng, keyCi, keyCiSz, + keyBuf, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA); + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0 ) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Error creating key encrypt content"); + return NULL; + } + *keyCiSz = ret; + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + word32 i; + printf("(size %u) Key Content Info = ", *keyCiSz); + for (i = 0; i < *keyCiSz; i++) + printf("%02X", keyCi[i]); + printf("\n"); + } + #endif + + (void)heap; + return keyCi; +} + + +/* helper function to create the PKCS12 certificate content + * certCiSz is output buffer size + * returns a pointer to be free'd by caller on success and NULL on failure */ +static byte* PKCS12_create_cert_content(WC_PKCS12* pkcs12, int nidCert, + WC_DerCertList* ca, byte* cert, word32 certSz, word32* certCiSz, + WC_RNG* rng, char* pass, word32 passSz, int iter) +{ + int algo; + int ret; + int type; + + byte* certBuf = NULL; + word32 certBufSz; + word32 idx; + word32 sz; + word32 tmpSz; + + byte* certCi; + void* heap; + + heap = wc_PKCS12_GetHeap(pkcs12); + switch (nidCert) { + case PBE_SHA1_RC4_128: + type = WC_PKCS12_ENCRYPTED_DATA; + algo = 1; + break; + + case PBE_SHA1_DES: + type = WC_PKCS12_ENCRYPTED_DATA; + algo = 2; + break; + + case PBE_SHA1_DES3: + type = WC_PKCS12_ENCRYPTED_DATA; + algo = 3; + break; + + case -1: + type = WC_PKCS12_DATA; + algo = -1; + break; + + default: + WOLFSSL_MSG("Unknown/Unsupported certificate encryption"); + return NULL; + } + + /* get max size of buffer needed */ + ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &certBufSz, cert, certSz); + if (ret != LENGTH_ONLY_E) { + return NULL; + } + + if (ca != NULL) { + WC_DerCertList* current = ca; + word32 curBufSz = 0; + + /* get max buffer size */ + while (current != NULL) { + ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &curBufSz, + current->buffer, current->bufferSz); + if (ret != LENGTH_ONLY_E) { + return NULL; + } + certBufSz += curBufSz; + current = current->next; + } + } + + /* account for Sequence that holds all certificate bags */ + certBufSz += MAX_SEQ_SZ; + + /* completed getting max size, now create buffer and start adding bags */ + certBuf = (byte*)XMALLOC(certBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (certBuf == NULL) { + WOLFSSL_MSG("Memory error creating certificate bags"); + return NULL; + } + + idx = 0; + idx += MAX_SEQ_SZ; + + sz = certBufSz - idx; + if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz, + cert, certSz)) < 0) { + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + idx += ret; + + if (ca != NULL) { + WC_DerCertList* current = ca; + + while (current != NULL) { + sz = certBufSz - idx; + if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz, + current->buffer, current->bufferSz)) < 0) { + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + idx += ret; + current = current->next; + } + } + + /* set sequence and create encrypted content with all certificate bags */ + tmpSz = SetSequence(idx - MAX_SEQ_SZ, certBuf); + XMEMMOVE(certBuf + tmpSz, certBuf + MAX_SEQ_SZ, idx - MAX_SEQ_SZ); + certBufSz = tmpSz + (idx - MAX_SEQ_SZ); + + /* get buffer size needed for content info */ + ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, certCiSz, + NULL, certBufSz, algo, pass, passSz, iter, type); + if (ret != LENGTH_ONLY_E) { + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_LEAVE("wc_PKCS12_create()", ret); + return NULL; + } + certCi = (byte*)XMALLOC(*certCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (certCi == NULL) { + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + ret = wc_PKCS12_encrypt_content(pkcs12, rng, certCi, certCiSz, + certBuf, certBufSz, algo, pass, passSz, iter, type); + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0) { + WOLFSSL_LEAVE("wc_PKCS12_create()", ret); + return NULL; + } + *certCiSz = ret; + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + word32 i; + printf("(size %u) Encrypted Certificate Content Info = ", *certCiSz); + for (i = 0; i < *certCiSz; i++) + printf("%02X", certCi[i]); + printf("\n"); + } + #endif + + (void)heap; + return certCi; +} + + +/* helper function to create the PKCS12 safe + * returns 0 on success */ +static int PKCS12_create_safe(WC_PKCS12* pkcs12, byte* certCi, word32 certCiSz, + byte* keyCi, word32 keyCiSz, WC_RNG* rng, char* pass, word32 passSz, + int iter) +{ + int length; + int ret; + byte seq[MAX_SEQ_SZ]; + word32 safeDataSz; + word32 innerDataSz; + byte *innerData = NULL; + byte *safeData = NULL; + word32 idx; + + innerDataSz = certCiSz + keyCiSz+SetSequence(certCiSz + keyCiSz, seq); + + /* add Content Info structs to safe, key first then cert */ + ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, &safeDataSz, + NULL, innerDataSz, 0, NULL, 0, 0, WC_PKCS12_DATA); + if (ret != LENGTH_ONLY_E) { + return ret; + } + + safeData = (byte*)XMALLOC(safeDataSz, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (safeData == NULL) { + WOLFSSL_MSG("Error malloc'ing safe data buffer"); + return MEMORY_E; + } + + /* create sequence of inner data */ + innerData = (byte*)XMALLOC(innerDataSz, pkcs12->heap, DYNAMIC_TYPE_PKCS); + if (innerData == NULL) { + WOLFSSL_MSG("Error malloc'ing inner data buffer"); + XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + idx = 0; + idx += SetSequence(certCiSz + keyCiSz, innerData); + XMEMCPY(innerData + idx, certCi, certCiSz); + XMEMCPY(innerData + idx + certCiSz, keyCi, keyCiSz); + + ret = wc_PKCS12_encrypt_content(pkcs12, rng, safeData, &safeDataSz, + innerData, innerDataSz, 0, pass, passSz, iter, WC_PKCS12_DATA); + XFREE(innerData, pkcs12->heap, DYNAMIC_TYPE_PKCS); + if (ret < 0 ) { + WOLFSSL_MSG("Error setting data type for safe contents"); + XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + idx = 0; + + ret = GetSequence(safeData, &idx, &length, safeDataSz); + if (ret < 0) { + WOLFSSL_MSG("Error getting first sequence of safe"); + XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + ret = GetSafeContent(pkcs12, safeData, &idx, safeDataSz); + XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0) { + WOLFSSL_MSG("Unable to create safe contents"); + return ret; + } + return 0; +} + + +/* + * pass : password to use with encryption + * passSz : size of the password buffer + * name : friendlyName to use + * key : DER format of key + * keySz : size of key buffer + * cert : DER format of certificate + * certSz : size of the certificate buffer + * ca : a list of extra certificates + * nidKey : type of encryption to use on the key (-1 means no encryption) + * nidCert : type of encryption to use on the certificate + * (-1 means no encryption) + * iter : number of iterations with encryption + * macIter : number of iterations when creating MAC + * keyType : flag for signature and/or encryption key + * heap : pointer to allocate from memory + * + * returns a pointer to a new WC_PKCS12 structure on success and NULL if failed + */ +WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name, + byte* key, word32 keySz, byte* cert, word32 certSz, WC_DerCertList* ca, + int nidKey, int nidCert, int iter, int macIter, int keyType, void* heap) +{ + WC_PKCS12* pkcs12; + WC_RNG rng; + int ret; + + byte* certCi = NULL; + byte* keyCi = NULL; + word32 certCiSz; + word32 keyCiSz; + + WOLFSSL_ENTER("wc_PKCS12_create()"); + + if ((ret = wc_InitRng_ex(&rng, heap, INVALID_DEVID)) != 0) { + return NULL; + } + + if ((pkcs12 = wc_PKCS12_new()) == NULL) { + wc_FreeRng(&rng); + WOLFSSL_LEAVE("wc_PKCS12_create", MEMORY_E); + return NULL; + } + + if ((ret = wc_PKCS12_SetHeap(pkcs12, heap)) != 0) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + WOLFSSL_LEAVE("wc_PKCS12_create", ret); + return NULL; + } + + if (iter <= 0) { + iter = WC_PKCS12_ITT_DEFAULT; + } + + /**** add private key bag ****/ + keyCi = PKCS12_create_key_content(pkcs12, nidKey, &keyCiSz, &rng, + pass, passSz, key, keySz, iter); + if (keyCi == NULL) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + + /**** add main certificate bag and extras ****/ + certCi = PKCS12_create_cert_content(pkcs12, nidCert, ca, cert, certSz, + &certCiSz, &rng, pass, passSz, iter); + if (certCi == NULL) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + + /**** create safe and Content Info ****/ + ret = PKCS12_create_safe(pkcs12, certCi, certCiSz, keyCi, keyCiSz, &rng, + pass, passSz, iter); + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret != 0) { + WOLFSSL_MSG("Unable to create PKCS12 safe"); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + + /* create MAC */ + if (macIter > 0) { + MacData* mac; + byte digest[WC_MAX_DIGEST_SIZE]; /* for MAC */ + + mac = (MacData*)XMALLOC(sizeof(MacData), heap, DYNAMIC_TYPE_PKCS); + if (mac == NULL) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + WOLFSSL_MSG("Error malloc'ing mac data buffer"); + return NULL; + } + XMEMSET(mac, 0, sizeof(MacData)); + pkcs12->signData = mac; /* now wc_PKCS12_free will free all mac too */ + + #ifndef NO_SHA256 + mac->oid = SHA256h; + #elif !defined(NO_SHA) + mac->oid = SHA; + #elif defined(WOLFSSL_SHA384) + mac->oid = SHA384; + #elif defined(WOLFSSL_SHA512) + mac->oid = SHA512; + #else + WOLFSSL_MSG("No supported hash algorithm compiled in!"); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + #endif + + /* store number of iterations */ + mac->itt = macIter; + + /* set mac salt */ + mac->saltSz = 8; + mac->salt = (byte*)XMALLOC(mac->saltSz, heap, DYNAMIC_TYPE_PKCS); + if (mac->salt == NULL) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + WOLFSSL_MSG("Error malloc'ing salt data buffer"); + return NULL; + } + + if ((ret = wc_RNG_GenerateBlock(&rng, mac->salt, mac->saltSz)) != 0) { + WOLFSSL_MSG("Error generating random salt"); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + ret = wc_PKCS12_create_mac(pkcs12, pkcs12->safe->data, + pkcs12->safe->dataSz, (const byte*)pass, passSz, digest, + WC_MAX_DIGEST_SIZE); + if (ret < 0) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + WOLFSSL_MSG("Error creating mac"); + WOLFSSL_LEAVE("wc_PKCS12_create", ret); + return NULL; + } + + mac->digestSz = ret; + mac->digest = (byte*)XMALLOC(ret, heap, DYNAMIC_TYPE_PKCS); + if (mac->digest == NULL) { + WOLFSSL_MSG("Error malloc'ing mac digest buffer"); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + XMEMCPY(mac->digest, digest, mac->digestSz); + } + else { + pkcs12->signData = NULL; + } + + wc_FreeRng(&rng); + (void)name; + (void)keyType; + + return pkcs12; +} + + +/* if using a specific memory heap */ +int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap) +{ + if (pkcs12 == NULL) { + return BAD_FUNC_ARG; + } + pkcs12->heap = heap; + + return 0; +} + + +/* getter for heap */ +void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12) +{ + if (pkcs12 == NULL) { + return NULL; + } + + return pkcs12->heap; +} + +#undef ERROR_OUT + +#endif /* !NO_ASN && !NO_PWDBASED && HAVE_PKCS12 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/pkcs7.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/pkcs7.c index 2f66ea216..e420cad37 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/pkcs7.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/pkcs7.c @@ -1,8 +1,8 @@ /* pkcs7.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -30,45 +31,512 @@ #include #include #include +#include +#ifndef NO_RSA + #include +#endif +#ifdef HAVE_ECC + #include +#endif +#ifdef HAVE_LIBZ + #include +#endif +#ifndef NO_PWDBASED + #include +#endif #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN +/* direction for processing, encoding or decoding */ +typedef enum { + WC_PKCS7_ENCODE, + WC_PKCS7_DECODE +} pkcs7Direction; - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; +#define NO_USER_CHECK 0 + +/* holds information about the signers */ +struct PKCS7SignerInfo { + int version; + byte *sid; + word32 sidSz; +}; + + +#ifndef NO_PKCS7_STREAM + +#define MAX_PKCS7_STREAM_BUFFER 256 +struct PKCS7State { + byte* tmpCert; + byte* bufferPt; + byte* key; + byte* nonce; /* stored nonce */ + byte* aad; /* additional data for AEAD algos */ + byte* tag; /* tag data for AEAD algos */ + byte* content; + byte* buffer; /* main internal read buffer */ + + /* stack variables to store for when returning */ + word32 varOne; + int varTwo; + int varThree; + + word32 vers; + word32 idx; /* index read into current input buffer */ + word32 maxLen; /* sanity cap on maximum amount of data to allow + * needed for GetSequence and other calls */ + word32 length; /* amount of data stored */ + word32 bufferSz; /* size of internal buffer */ + word32 expected; /* next amount of data expected, if needed */ + word32 totalRd; /* total amount of bytes read */ + word32 nonceSz; /* size of nonce stored */ + word32 aadSz; /* size of additional AEAD data */ + word32 tagSz; /* size of tag for AEAD */ + word32 contentSz; + byte tmpIv[MAX_CONTENT_IV_SIZE]; /* store IV if needed */ +#ifdef WC_PKCS7_STREAM_DEBUG + word32 peakUsed; /* most bytes used for struct at any one time */ + word32 peakRead; /* most bytes used by read buffer */ +#endif + byte multi:1; /* flag for if content is in multiple parts */ + byte flagOne:1; + byte detached:1; /* flag to indicate detached signature is present */ +}; + + +enum PKCS7_MaxLen { + PKCS7_DEFAULT_PEEK = 0, + PKCS7_SEQ_PEEK +}; + +/* creates a PKCS7State structure and returns 0 on success */ +static int wc_PKCS7_CreateStream(PKCS7* pkcs7) +{ + WOLFSSL_MSG("creating PKCS7 stream structure"); + pkcs7->stream = (PKCS7State*)XMALLOC(sizeof(PKCS7State), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream == NULL) { + return MEMORY_E; + } + XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State)); +#ifdef WC_PKCS7_STREAM_DEBUG + printf("\nCreating new PKCS#7 stream %p\n", pkcs7->stream); +#endif + return 0; +} + + +static void wc_PKCS7_ResetStream(PKCS7* pkcs7) +{ + if (pkcs7 != NULL && pkcs7->stream != NULL) { +#ifdef WC_PKCS7_STREAM_DEBUG + /* collect final data point in case more was read right before reset */ + if (pkcs7->stream->length > pkcs7->stream->peakRead) { + pkcs7->stream->peakRead = pkcs7->stream->length; + } + if (pkcs7->stream->bufferSz + pkcs7->stream->aadSz + + pkcs7->stream->nonceSz + pkcs7->stream->tagSz > + pkcs7->stream->peakUsed) { + pkcs7->stream->peakUsed = pkcs7->stream->bufferSz + + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + + pkcs7->stream->tagSz; + } + + /* print out debugging statistics */ + if (pkcs7->stream->peakUsed > 0 || pkcs7->stream->peakRead > 0) { + printf("PKCS#7 STREAM:\n\tPeak heap used by struct = %d" + "\n\tPeak read buffer bytes = %d" + "\n\tTotal bytes read = %d" + "\n", + pkcs7->stream->peakUsed, pkcs7->stream->peakRead, + pkcs7->stream->totalRd); + } + printf("PKCS#7 stream reset : Address [%p]\n", pkcs7->stream); + #endif + + /* free any buffers that may be allocated */ + XFREE(pkcs7->stream->aad, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->tag, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->nonce, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->key, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->aad = NULL; + pkcs7->stream->tag = NULL; + pkcs7->stream->nonce = NULL; + pkcs7->stream->buffer = NULL; + pkcs7->stream->key = NULL; + + /* reset values, note that content and tmpCert are saved */ + pkcs7->stream->maxLen = 0; + pkcs7->stream->length = 0; + pkcs7->stream->idx = 0; + pkcs7->stream->expected = 0; + pkcs7->stream->totalRd = 0; + pkcs7->stream->bufferSz = 0; + + pkcs7->stream->multi = 0; + pkcs7->stream->flagOne = 0; + pkcs7->stream->detached = 0; + pkcs7->stream->varOne = 0; + pkcs7->stream->varTwo = 0; + pkcs7->stream->varThree = 0; + } +} + + +static void wc_PKCS7_FreeStream(PKCS7* pkcs7) +{ + if (pkcs7 != NULL && pkcs7->stream != NULL) { + wc_PKCS7_ResetStream(pkcs7); + + XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->content = NULL; + pkcs7->stream->tmpCert = NULL; + + XFREE(pkcs7->stream, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream = NULL; + } +} + + +/* used to increase the max size for internal buffer + * returns 0 on success */ +static int wc_PKCS7_GrowStream(PKCS7* pkcs7, word32 newSz) +{ + byte* pt; + + pt = (byte*)XMALLOC(newSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pt == NULL) { + return MEMORY_E; + } + XMEMCPY(pt, pkcs7->stream->buffer, pkcs7->stream->bufferSz); + +#ifdef WC_PKCS7_STREAM_DEBUG + printf("PKCS7 increasing internal stream buffer %d -> %d\n", + pkcs7->stream->bufferSz, newSz); +#endif + pkcs7->stream->bufferSz = newSz; + XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->buffer = pt; + return 0; +} + + +/* pt gets set to the buffer that is holding data in the case that stream struct + * is used. + * + * Sets idx to be the current offset into "pt" buffer + * returns 0 on success + */ +static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, + word32 expected, byte** pt, word32* idx) +{ + word32 rdSz = pkcs7->stream->idx; + + /* If the input size minus current index into input buffer is greater than + * the expected size then use the input buffer. If data is already stored + * in stream buffer or if there is not enough input data available then use + * the stream buffer. */ + if (inSz - rdSz >= expected && pkcs7->stream->length == 0) { + /* storing input buffer is not needed */ + *pt = in; /* reset in case previously used internal buffer */ + *idx = rdSz; + return 0; } -#endif /* WOLFSSL_HAVE_MIN */ + /* is there enough stored in buffer already? */ + if (pkcs7->stream->length >= expected) { + *idx = 0; /* start reading from beginning of stream buffer */ + *pt = pkcs7->stream->buffer; + return 0; + } + + /* check if all data has been read from input */ + if (rdSz >= inSz) { + /* no more input to read, reset input index and request more data */ + pkcs7->stream->idx = 0; + return WC_PKCS7_WANT_READ_E; + } + + /* try to store input data into stream buffer */ + if (inSz - rdSz > 0 && pkcs7->stream->length < expected) { + int len = min(inSz - rdSz, expected - pkcs7->stream->length); + + /* sanity check that the input buffer is not internal buffer */ + if (in == pkcs7->stream->buffer) { + return WC_PKCS7_WANT_READ_E; + } + + /* check if internal buffer size needs to be increased */ + if (len + pkcs7->stream->length > pkcs7->stream->bufferSz) { + int ret = wc_PKCS7_GrowStream(pkcs7, expected); + if (ret < 0) { + return ret; + } + } + XMEMCPY(pkcs7->stream->buffer + pkcs7->stream->length, in + rdSz, len); + pkcs7->stream->length += len; + pkcs7->stream->idx += len; + pkcs7->stream->totalRd += len; + } + +#ifdef WC_PKCS7_STREAM_DEBUG + /* collects memory usage for debugging */ + if (pkcs7->stream->length > pkcs7->stream->peakRead) { + pkcs7->stream->peakRead = pkcs7->stream->length; + } + if (pkcs7->stream->bufferSz + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + + pkcs7->stream->tagSz > pkcs7->stream->peakUsed) { + pkcs7->stream->peakUsed = pkcs7->stream->bufferSz + + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + pkcs7->stream->tagSz; + } +#endif + + /* if not enough data was read in then request more */ + if (pkcs7->stream->length < expected) { + pkcs7->stream->idx = 0; + return WC_PKCS7_WANT_READ_E; + } + + /* adjust pointer to read from stored buffer */ + *idx = 0; + *pt = pkcs7->stream->buffer; + return 0; +} + + +/* Does two things + * 1) Tries to get the length from current buffer and set it as max length + * 2) Retrieves the set max length + * + * if no flag value is set then the stored max length is returned. + * returns length found on success and defSz if no stored data is found + */ +static long wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, byte* in, + word32 defSz) +{ + /* check there is a buffer to read from */ + if (pkcs7) { + int length = 0, ret; + word32 idx = 0, maxIdx; + byte* pt; + + if (flag != PKCS7_DEFAULT_PEEK) { + if (pkcs7->stream->length > 0) { + length = pkcs7->stream->length; + pt = pkcs7->stream->buffer; + } + else { + length = defSz; + pt = in; + } + maxIdx = (word32)length; + + if (length < MAX_SEQ_SZ) { + WOLFSSL_MSG("PKCS7 Error not enough data for SEQ peek\n"); + return 0; + } + if (flag == PKCS7_SEQ_PEEK) { + if ((ret = GetSequence_ex(pt, &idx, &length, maxIdx, + NO_USER_CHECK)) < 0) { + return ret; + } + + #ifdef ASN_BER_TO_DER + if (length == 0 && ret == 0) { + idx = 0; + if ((ret = wc_BerToDer(pt, defSz, NULL, + (word32*)&length)) != LENGTH_ONLY_E) { + return ret; + } + } + #endif /* ASN_BER_TO_DER */ + pkcs7->stream->maxLen = length + idx; + } + } + + if (pkcs7->stream->maxLen == 0) { + pkcs7->stream->maxLen = defSz; + } + + return pkcs7->stream->maxLen; + } + + return defSz; +} + + +/* setter function for stored variables */ +static void wc_PKCS7_StreamStoreVar(PKCS7* pkcs7, word32 var1, int var2, + int var3) +{ + if (pkcs7 != NULL && pkcs7->stream != NULL) { + pkcs7->stream->varOne = var1; + pkcs7->stream->varTwo = var2; + pkcs7->stream->varThree = var3; + } +} + +/* getter function for stored variables */ +static void wc_PKCS7_StreamGetVar(PKCS7* pkcs7, word32* var1, int* var2, + int* var3) +{ + if (pkcs7 != NULL && pkcs7->stream != NULL) { + if (var1 != NULL) *var1 = pkcs7->stream->varOne; + if (var2 != NULL) *var2 = pkcs7->stream->varTwo; + if (var3 != NULL) *var3 = pkcs7->stream->varThree; + } +} + + +/* common update of index and total read after section complete + * returns 0 on success */ +static int wc_PKCS7_StreamEndCase(PKCS7* pkcs7, word32* tmpIdx, word32* idx) +{ + int ret = 0; + + if (pkcs7->stream->length > 0) { + if (pkcs7->stream->length < *idx) { + WOLFSSL_MSG("PKCS7 read too much data from internal buffer"); + ret = BUFFER_E; + } + else { + XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + *idx, + pkcs7->stream->length - *idx); + pkcs7->stream->length -= *idx; + } + } + else { + pkcs7->stream->totalRd += *idx - *tmpIdx; + pkcs7->stream->idx = *idx; /* adjust index into input buffer */ + *tmpIdx = *idx; + } + + return ret; +} +#endif /* NO_PKCS7_STREAM */ + +#ifdef WC_PKCS7_STREAM_DEBUG +/* used to print out human readable state for debugging */ +static const char* wc_PKCS7_GetStateName(int in) +{ + switch (in) { + case WC_PKCS7_START: return "WC_PKCS7_START"; + + case WC_PKCS7_STAGE2: return "WC_PKCS7_STAGE2"; + case WC_PKCS7_STAGE3: return "WC_PKCS7_STAGE3"; + case WC_PKCS7_STAGE4: return "WC_PKCS7_STAGE4"; + case WC_PKCS7_STAGE5: return "WC_PKCS7_STAGE5"; + case WC_PKCS7_STAGE6: return "WC_PKCS7_STAGE6"; + + /* parse info set */ + case WC_PKCS7_INFOSET_START: return "WC_PKCS7_INFOSET_START"; + case WC_PKCS7_INFOSET_BER: return "WC_PKCS7_INFOSET_BER"; + case WC_PKCS7_INFOSET_STAGE1: return "WC_PKCS7_INFOSET_STAGE1"; + case WC_PKCS7_INFOSET_STAGE2: return "WC_PKCS7_INFOSET_STAGE2"; + case WC_PKCS7_INFOSET_END: return "WC_PKCS7_INFOSET_END"; + + /* decode enveloped data */ + case WC_PKCS7_ENV_2: return "WC_PKCS7_ENV_2"; + case WC_PKCS7_ENV_3: return "WC_PKCS7_ENV_3"; + case WC_PKCS7_ENV_4: return "WC_PKCS7_ENV_4"; + case WC_PKCS7_ENV_5: return "WC_PKCS7_ENV_5"; + + /* decode auth enveloped */ + case WC_PKCS7_AUTHENV_2: return "WC_PKCS7_AUTHENV_2"; + case WC_PKCS7_AUTHENV_3: return "WC_PKCS7_AUTHENV_3"; + case WC_PKCS7_AUTHENV_4: return "WC_PKCS7_AUTHENV_4"; + case WC_PKCS7_AUTHENV_5: return "WC_PKCS7_AUTHENV_5"; + case WC_PKCS7_AUTHENV_6: return "WC_PKCS7_AUTHENV_6"; + case WC_PKCS7_AUTHENV_ATRB: return "WC_PKCS7_AUTHENV_ATRB"; + case WC_PKCS7_AUTHENV_ATRBEND: return "WC_PKCS7_AUTHENV_ATRBEND"; + case WC_PKCS7_AUTHENV_7: return "WC_PKCS7_AUTHENV_7"; + + /* decryption state types */ + case WC_PKCS7_DECRYPT_KTRI: return "WC_PKCS7_DECRYPT_KTRI"; + case WC_PKCS7_DECRYPT_KTRI_2: return "WC_PKCS7_DECRYPT_KTRI_2"; + case WC_PKCS7_DECRYPT_KTRI_3: return "WC_PKCS7_DECRYPT_KTRI_3"; + + case WC_PKCS7_DECRYPT_KARI: return "WC_PKCS7_DECRYPT_KARI"; + case WC_PKCS7_DECRYPT_KEKRI: return "WC_PKCS7_DECRYPT_KEKRI"; + case WC_PKCS7_DECRYPT_PWRI: return "WC_PKCS7_DECRYPT_PWRI"; + case WC_PKCS7_DECRYPT_ORI: return "WC_PKCS7_DECRYPT_ORI"; + case WC_PKCS7_DECRYPT_DONE: return "WC_PKCS7_DECRYPT_DONE"; + + case WC_PKCS7_VERIFY_STAGE2: return "WC_PKCS7_VERIFY_STAGE2"; + case WC_PKCS7_VERIFY_STAGE3: return "WC_PKCS7_VERIFY_STAGE3"; + case WC_PKCS7_VERIFY_STAGE4: return "WC_PKCS7_VERIFY_STAGE4"; + case WC_PKCS7_VERIFY_STAGE5: return "WC_PKCS7_VERIFY_STAGE5"; + case WC_PKCS7_VERIFY_STAGE6: return "WC_PKCS7_VERIFY_STAGE6"; + + default: + return "Unknown state"; + } +} +#endif + +/* Used to change the PKCS7 state. Having state change as a function allows + * for easier debugging */ +static void wc_PKCS7_ChangeState(PKCS7* pkcs7, int newState) +{ +#ifdef WC_PKCS7_STREAM_DEBUG + printf("\tChanging from state [%02d] %s to [%02d] %s\n", + pkcs7->state, wc_PKCS7_GetStateName(pkcs7->state), + newState, wc_PKCS7_GetStateName(newState)); +#endif + pkcs7->state = newState; +} + +#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 */ -WOLFSSL_LOCAL int wc_SetContentType(int pkcs7TypeOID, byte* output) +static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) { /* PKCS#7 content types, RFC 2315, section 14 */ - static const byte pkcs7[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + const byte pkcs7[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07 }; - static const byte data[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + const byte data[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 }; - static const byte signedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + const byte signedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02}; - static const byte envelopedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + const byte envelopedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x03 }; - static const byte signedAndEnveloped[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + const byte authEnvelopedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x10, 0x01, 0x17}; + const byte signedAndEnveloped[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x04 }; - static const byte digestedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + const byte digestedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05 }; - static const byte encryptedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, +#ifndef NO_PKCS7_ENCRYPTED_DATA + const byte encryptedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 }; +#endif + /* FirmwarePkgData (1.2.840.113549.1.9.16.1.16), RFC 4108 */ + const byte firmwarePkgData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x01, 0x10 }; +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + /* id-ct-compressedData (1.2.840.113549.1.9.16.1.9), RFC 3274 */ + const byte compressedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x01, 0x09 }; +#endif - int idSz; - int typeSz = 0, idx = 0; +#if !defined(NO_PWDBASED) && !defined(NO_SHA) + const byte pwriKek[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x03, 0x09 }; + const byte pbkdf2[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x05, 0x0C }; +#endif + + int idSz, idx = 0; + word32 typeSz = 0; const byte* typeName = 0; byte ID_Length[MAX_LENGTH_SZ]; @@ -87,12 +555,17 @@ WOLFSSL_LOCAL int wc_SetContentType(int pkcs7TypeOID, byte* output) typeSz = sizeof(signedData); typeName = signedData; break; - + case ENVELOPED_DATA: typeSz = sizeof(envelopedData); typeName = envelopedData; break; + case AUTH_ENVELOPED_DATA: + typeSz = sizeof(authEnvelopedData); + typeName = authEnvelopedData; + break; + case SIGNED_AND_ENVELOPED_DATA: typeSz = sizeof(signedAndEnveloped); typeName = signedAndEnveloped; @@ -103,16 +576,45 @@ WOLFSSL_LOCAL 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 +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + case COMPRESSED_DATA: + typeSz = sizeof(compressedData); + typeName = compressedData; + break; +#endif + case FIRMWARE_PKG_DATA: + typeSz = sizeof(firmwarePkgData); + typeName = firmwarePkgData; + break; + +#if !defined(NO_PWDBASED) && !defined(NO_SHA) + case PWRI_KEK_WRAP: + typeSz = sizeof(pwriKek); + typeName = pwriKek; + break; + + case PBKDF2_OID: + typeSz = sizeof(pbkdf2); + typeName = pbkdf2; + break; +#endif default: WOLFSSL_MSG("Unknown PKCS#7 Type"); return 0; }; + if (outputSz < (MAX_LENGTH_SZ + 1 + typeSz)) { + WOLFSSL_MSG("CMS content type buffer too small"); + return BAD_FUNC_ARG; + } + idSz = SetLength(typeSz, ID_Length); output[idx++] = ASN_OBJECT_ID; XMEMCPY(output + idx, ID_Length, idSz); @@ -121,82 +623,384 @@ WOLFSSL_LOCAL int wc_SetContentType(int pkcs7TypeOID, byte* output) idx += typeSz; return idx; - } /* get ASN.1 contentType OID sum, return 0 on success, <0 on failure */ -int wc_GetContentType(const byte* input, word32* inOutIdx, word32* oid, - word32 maxIdx) +static int wc_GetContentType(const byte* input, word32* inOutIdx, word32* oid, + word32 maxIdx) { - int length; - word32 i = *inOutIdx; - byte b; - *oid = 0; - WOLFSSL_ENTER("wc_GetContentType"); - - b = input[i++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; - - if (GetLength(input, &i, &length, maxIdx) < 0) + if (GetObjectId(input, inOutIdx, oid, oidIgnoreType, maxIdx) < 0) return ASN_PARSE_E; - while(length--) { - *oid += input[i]; - i++; - } - - *inOutIdx = i; - return 0; } -/* init PKCS7 struct with recipient cert, decode into DecodedCert */ -int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) +/* return block size for algorithm represented by oid, or <0 on error */ +static int wc_PKCS7_GetOIDBlockSize(int oid) +{ + int blockSz; + + switch (oid) { +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + case AES128GCMb: + case AES128CCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + case AES192GCMb: + case AES192CCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + case AES256GCMb: + case AES256CCMb: + #endif + blockSz = AES_BLOCK_SIZE; + break; +#endif +#ifndef NO_DES3 + case DESb: + case DES3b: + blockSz = DES_BLOCK_SIZE; + break; +#endif + default: + WOLFSSL_MSG("Unsupported content cipher type"); + return ALGO_ID_E; + }; + + return blockSz; +} + + +/* get key size for algorithm represented by oid, or <0 on error */ +static int wc_PKCS7_GetOIDKeySize(int oid) +{ + int blockKeySz; + + switch (oid) { +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + case AES128GCMb: + case AES128CCMb: + case AES128_WRAP: + blockKeySz = 16; + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + case AES192GCMb: + case AES192CCMb: + case AES192_WRAP: + blockKeySz = 24; + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + case AES256GCMb: + case AES256CCMb: + case AES256_WRAP: + blockKeySz = 32; + break; + #endif +#endif +#ifndef NO_DES3 + case DESb: + blockKeySz = DES_KEYLEN; + break; + + case DES3b: + blockKeySz = DES3_KEYLEN; + break; +#endif + default: + WOLFSSL_MSG("Unsupported content cipher type"); + return ALGO_ID_E; + }; + + return blockKeySz; +} + + +PKCS7* wc_PKCS7_New(void* heap, int devId) +{ + PKCS7* pkcs7 = (PKCS7*)XMALLOC(sizeof(PKCS7), heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7) { + XMEMSET(pkcs7, 0, sizeof(PKCS7)); + if (wc_PKCS7_Init(pkcs7, heap, devId) == 0) { + pkcs7->isDynamic = 1; + } + else { + XFREE(pkcs7, heap, DYNAMIC_TYPE_PKCS7); + pkcs7 = NULL; + } + } + return pkcs7; +} + +/* 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) +{ + word16 isDynamic; + + WOLFSSL_ENTER("wc_PKCS7_Init"); + + if (pkcs7 == NULL) { + return BAD_FUNC_ARG; + } + + isDynamic = pkcs7->isDynamic; + XMEMSET(pkcs7, 0, sizeof(PKCS7)); + pkcs7->isDynamic = isDynamic; +#ifdef WOLFSSL_HEAP_TEST + pkcs7->heap = (void*)WOLFSSL_HEAP_TEST; +#else + pkcs7->heap = heap; +#endif + pkcs7->devId = devId; + + return 0; +} + + +/* Certificate structure holding der pointer, size, and pointer to next + * Pkcs7Cert struct. Used when creating SignedData types with multiple + * certificates. */ +struct Pkcs7Cert { + byte* der; + word32 derSz; + Pkcs7Cert* next; +}; + + +/* Linked list of ASN.1 encoded RecipientInfos */ +struct Pkcs7EncodedRecip { + byte recip[MAX_RECIP_SZ]; + word32 recipSz; + int recipType; + int recipVersion; + Pkcs7EncodedRecip* next; +}; + + +/* free all members of Pkcs7Cert linked list */ +static void wc_PKCS7_FreeCertSet(PKCS7* pkcs7) +{ + Pkcs7Cert* curr = NULL; + Pkcs7Cert* next = NULL; + + if (pkcs7 == NULL) + return; + + curr = pkcs7->certList; + pkcs7->certList = NULL; + + while (curr != NULL) { + next = curr->next; + curr->next = NULL; + XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + curr = next; + } + + return; +} + + +/* Get total size of all recipients in recipient list. + * + * Returns total size of recipients, or negative upon error */ +static int wc_PKCS7_GetRecipientListSize(PKCS7* pkcs7) +{ + int totalSz = 0; + Pkcs7EncodedRecip* tmp = NULL; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + tmp = pkcs7->recipList; + + while (tmp != NULL) { + totalSz += tmp->recipSz; + tmp = tmp->next; + } + + return totalSz; +} + + +/* free all members of Pkcs7EncodedRecip linked list */ +static void wc_PKCS7_FreeEncodedRecipientSet(PKCS7* pkcs7) +{ + Pkcs7EncodedRecip* curr = NULL; + Pkcs7EncodedRecip* next = NULL; + + if (pkcs7 == NULL) + return; + + curr = pkcs7->recipList; + pkcs7->recipList = NULL; + + while (curr != NULL) { + next = curr->next; + curr->next = NULL; + XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + curr = next; + } + + return; +} + + +/* search through RecipientInfo list for specific type. + * return 1 if ANY recipient of type specified is present, otherwise + * return 0 */ +static int wc_PKCS7_RecipientListIncludesType(PKCS7* pkcs7, int type) +{ + Pkcs7EncodedRecip* tmp = NULL; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + tmp = pkcs7->recipList; + + while (tmp != NULL) { + if (tmp->recipType == type) + return 1; + + tmp = tmp->next; + } + + return 0; +} + + +/* searches through RecipientInfo list, returns 1 if all structure + * versions are set to 0, otherwise returns 0 */ +static int wc_PKCS7_RecipientListVersionsAllZero(PKCS7* pkcs7) +{ + Pkcs7EncodedRecip* tmp = NULL; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + tmp = pkcs7->recipList; + + while (tmp != NULL) { + if (tmp->recipVersion != 0) + return 0; + + tmp = tmp->next; + } + + return 1; +} + + +/* Init PKCS7 struct with recipient cert, decode into DecodedCert + * NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */ +int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) { int ret = 0; + void* heap; + int devId; + Pkcs7Cert* cert; + Pkcs7Cert* lastCert; - XMEMSET(pkcs7, 0, sizeof(PKCS7)); - if (cert != NULL && certSz > 0) { + if (pkcs7 == NULL || (derCert == NULL && derCertSz != 0)) { + return BAD_FUNC_ARG; + } + + heap = pkcs7->heap; + devId = pkcs7->devId; + cert = pkcs7->certList; + ret = wc_PKCS7_Init(pkcs7, heap, devId); + if (ret != 0) + return ret; + pkcs7->certList = cert; + + if (derCert != NULL && derCertSz > 0) { #ifdef WOLFSSL_SMALL_STACK DecodedCert* dCert; - dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_DCERT); if (dCert == NULL) return MEMORY_E; #else - DecodedCert stack_dCert; - DecodedCert* dCert = &stack_dCert; + DecodedCert dCert[1]; #endif - pkcs7->singleCert = cert; - pkcs7->singleCertSz = certSz; - InitDecodedCert(dCert, cert, certSz, 0); + pkcs7->singleCert = derCert; + pkcs7->singleCertSz = derCertSz; + pkcs7->cert[0] = derCert; + pkcs7->certSz[0] = derCertSz; + /* create new Pkcs7Cert for recipient, freed during cleanup */ + cert = (Pkcs7Cert*)XMALLOC(sizeof(Pkcs7Cert), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + XMEMSET(cert, 0, sizeof(Pkcs7Cert)); + cert->der = derCert; + cert->derSz = derCertSz; + cert->next = NULL; + + /* free existing cert list if existing */ + wc_PKCS7_FreeCertSet(pkcs7); + + /* add cert to list */ + if (pkcs7->certList == NULL) { + pkcs7->certList = cert; + } else { + lastCert = pkcs7->certList; + while (lastCert->next != NULL) { + lastCert = lastCert->next; + } + lastCert->next = cert; + } + + InitDecodedCert(dCert, derCert, derCertSz, pkcs7->heap); ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { FreeDecodedCert(dCert); #ifdef WOLFSSL_SMALL_STACK - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); #endif return ret; } XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize); pkcs7->publicKeySz = dCert->pubKeySize; + pkcs7->publicKeyOID = dCert->keyOID; XMEMCPY(pkcs7->issuerHash, dCert->issuerHash, KEYID_SIZE); pkcs7->issuer = dCert->issuerRaw; pkcs7->issuerSz = dCert->issuerRawLen; XMEMCPY(pkcs7->issuerSn, dCert->serial, dCert->serialSz); pkcs7->issuerSnSz = dCert->serialSz; + XMEMCPY(pkcs7->issuerSubjKeyId, dCert->extSubjKeyId, KEYID_SIZE); + + /* default to IssuerAndSerialNumber for SignerIdentifier */ + pkcs7->sidType = CMS_ISSUER_AND_SERIAL_NUMBER; + + /* free existing recipient list if existing */ + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + FreeDecodedCert(dCert); #ifdef WOLFSSL_SMALL_STACK - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); #endif } @@ -204,10 +1008,265 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) } +/* Adds one DER-formatted certificate to the internal PKCS7/CMS certificate + * list, to be added as part of the certificates CertificateSet. Currently + * used in SignedData content type. + * + * Must be called after wc_PKCS7_Init() or wc_PKCS7_InitWithCert(). + * + * Does not represent the recipient/signer certificate, only certificates that + * are part of the certificate chain used to build and verify signer + * certificates. + * + * This API does not currently validate certificates. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_AddCertificate(PKCS7* pkcs7, byte* derCert, word32 derCertSz) +{ + Pkcs7Cert* cert; + + if (pkcs7 == NULL || derCert == NULL || derCertSz == 0) + return BAD_FUNC_ARG; + + cert = (Pkcs7Cert*)XMALLOC(sizeof(Pkcs7Cert), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (cert == NULL) + return MEMORY_E; + + cert->der = derCert; + cert->derSz = derCertSz; + + if (pkcs7->certList == NULL) { + pkcs7->certList = cert; + } else { + cert->next = pkcs7->certList; + pkcs7->certList = cert; + } + + return 0; +} + + +/* free linked list of PKCS7DecodedAttrib structs */ +static void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib, void* heap) +{ + PKCS7DecodedAttrib* current; + + if (attrib == NULL) { + return; + } + + current = attrib; + while (current != NULL) { + PKCS7DecodedAttrib* next = current->next; + if (current->oid != NULL) { + XFREE(current->oid, heap, DYNAMIC_TYPE_PKCS7); + } + if (current->value != NULL) { + XFREE(current->value, heap, DYNAMIC_TYPE_PKCS7); + } + XFREE(current, heap, DYNAMIC_TYPE_PKCS7); + current = next; + } + + (void)heap; +} + + +/* return 0 on success */ +static int wc_PKCS7_SignerInfoNew(PKCS7* pkcs7) +{ + if (pkcs7->signerInfo != NULL) { + XFREE(pkcs7->signerInfo, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->signerInfo = NULL; + } + + pkcs7->signerInfo = (PKCS7SignerInfo*)XMALLOC(sizeof(PKCS7SignerInfo), + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->signerInfo == NULL) { + WOLFSSL_MSG("Unable to malloc memory for signer info"); + return MEMORY_E; + } + XMEMSET(pkcs7->signerInfo, 0, sizeof(PKCS7SignerInfo)); + return 0; +} + + +static void wc_PKCS7_SignerInfoFree(PKCS7* pkcs7) +{ + if (pkcs7->signerInfo != NULL) { + if (pkcs7->signerInfo->sid != NULL) { + XFREE(pkcs7->signerInfo->sid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->signerInfo->sid = NULL; + } + XFREE(pkcs7->signerInfo, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->signerInfo = NULL; + } +} + + +/* free's any current SID and sets it to "in" + * returns 0 on success + */ +static int wc_PKCS7_SignerInfoSetSID(PKCS7* pkcs7, byte* in, int inSz) +{ + if (pkcs7 == NULL || in == NULL || inSz < 0) { + return BAD_FUNC_ARG; + } + + if (pkcs7->signerInfo->sid != NULL) { + XFREE(pkcs7->signerInfo->sid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->signerInfo->sid = NULL; + } + pkcs7->signerInfo->sid = (byte*)XMALLOC(inSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->signerInfo->sid == NULL) { + return MEMORY_E; + } + XMEMCPY(pkcs7->signerInfo->sid, in, inSz); + pkcs7->signerInfo->sidSz = inSz; + return 0; +} + + /* releases any memory allocated by a PKCS7 initializer */ void wc_PKCS7_Free(PKCS7* pkcs7) { - (void)pkcs7; + if (pkcs7 == NULL) + return; + +#ifndef NO_PKCS7_STREAM + wc_PKCS7_FreeStream(pkcs7); +#endif + + wc_PKCS7_SignerInfoFree(pkcs7); + wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); + wc_PKCS7_FreeCertSet(pkcs7); + +#ifdef ASN_BER_TO_DER + if (pkcs7->der != NULL) + XFREE(pkcs7->der, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + if (pkcs7->contentDynamic != NULL) + XFREE(pkcs7->contentDynamic, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + if (pkcs7->cek != NULL) { + ForceZero(pkcs7->cek, pkcs7->cekSz); + XFREE(pkcs7->cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + + pkcs7->contentTypeSz = 0; + + if (pkcs7->signature) { + XFREE(pkcs7->signature, pkcs7->heap, DYNAMIC_TYPE_SIGNATURE); + pkcs7->signature = NULL; + pkcs7->signatureSz = 0; + } + if (pkcs7->plainDigest) { + XFREE(pkcs7->plainDigest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); + pkcs7->plainDigest = NULL; + pkcs7->plainDigestSz = 0; + } + if (pkcs7->pkcs7Digest) { + XFREE(pkcs7->pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); + pkcs7->pkcs7Digest = NULL; + pkcs7->pkcs7DigestSz = 0; + } + if (pkcs7->cachedEncryptedContent != NULL) { + XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->cachedEncryptedContent = NULL; + pkcs7->cachedEncryptedContentSz = 0; + } + + if (pkcs7->isDynamic) { + pkcs7->isDynamic = 0; + XFREE(pkcs7, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } +} + + +/* helper function for parsing through attributes and finding a specific one. + * returns PKCS7DecodedAttrib pointer on success */ +static PKCS7DecodedAttrib* findAttrib(PKCS7* pkcs7, const byte* oid, word32 oidSz) +{ + PKCS7DecodedAttrib* list; + + if (pkcs7 == NULL || oid == NULL) { + return NULL; + } + + /* search attributes for pkiStatus */ + list = pkcs7->decodedAttrib; + while (list != NULL) { + word32 sz = oidSz; + word32 idx = 0; + int length = 0; + byte tag; + + if (GetASNTag(list->oid, &idx, &tag, list->oidSz) < 0) { + return NULL; + } + if (tag != ASN_OBJECT_ID) { + WOLFSSL_MSG("Bad attribute ASN1 syntax"); + return NULL; + } + + if (GetLength(list->oid, &idx, &length, list->oidSz) < 0) { + WOLFSSL_MSG("Bad attribute length"); + return NULL; + } + + sz = (sz < (word32)length)? sz : (word32)length; + if (XMEMCMP(oid, list->oid + idx, sz) == 0) { + return list; + } + list = list->next; + } + return NULL; +} + + +/* Searches through decoded attributes and returns the value for the first one + * matching the oid passed in. Note that this value includes the leading ASN1 + * syntax. So for a printable string of "3" this would be something like + * + * 0x13, 0x01, 0x33 + * ID SIZE "3" + * + * pkcs7 structure to get value from + * oid OID value to search for with attributes + * oidSz size of oid buffer + * out buffer to hold result + * outSz size of out buffer (if out is NULL this is set to needed size and + LENGTH_ONLY_E is returned) + * + * returns size of value on success + */ +int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid, word32 oidSz, + byte* out, word32* outSz) +{ + PKCS7DecodedAttrib* attrib; + + if (pkcs7 == NULL || oid == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + attrib = findAttrib(pkcs7, oid, oidSz); + if (attrib == NULL) { + return ASN_PARSE_E; + } + + if (out == NULL) { + *outSz = attrib->valueSz; + return LENGTH_ONLY_E; + } + + if (*outSz < attrib->valueSz) { + return BUFFER_E; + } + + XMEMCPY(out, attrib->value, attrib->valueSz); + return attrib->valueSz; } @@ -224,6 +1283,10 @@ int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz) word32 oidSz = (word32)sizeof(oid); int idx = 0; + if (pkcs7 == NULL || output == NULL) { + return BAD_FUNC_ARG; + } + octetStrSz = SetOctetString(pkcs7->contentSz, octetStr); seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq); @@ -253,10 +1316,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]; @@ -274,20 +1338,24 @@ typedef struct ESD { byte signerInfoSet[MAX_SET_SZ]; byte signerInfoSeq[MAX_SEQ_SZ]; byte signerVersion[MAX_VERSION_SZ]; + /* issuerAndSerialNumber ...*/ byte issuerSnSeq[MAX_SEQ_SZ]; byte issuerName[MAX_SEQ_SZ]; byte issuerSn[MAX_SN_SZ]; + /* OR subjectKeyIdentifier */ + byte issuerSKIDSeq[MAX_SEQ_SZ]; + byte issuerSKID[MAX_OCTET_STR_SZ]; byte signerDigAlgoId[MAX_ALGO_SZ]; byte digEncAlgoId[MAX_ALGO_SZ]; byte signedAttribSet[MAX_SET_SZ]; - EncodedAttrib signedAttribs[6]; + EncodedAttrib signedAttribs[7]; byte signerDigest[MAX_OCTET_STR_SZ]; word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz; word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz, singleDigAlgoIdSz, certsSetSz; word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz, - issuerSnSeqSz, issuerNameSz, issuerSnSz, - signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz; + issuerSnSeqSz, issuerNameSz, issuerSnSz, issuerSKIDSz, + issuerSKIDSeqSz, signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz; word32 encContentDigestSz, signedAttribsSz, signedAttribsCount, signedAttribSetSz; } ESD; @@ -322,12 +1390,112 @@ static int EncodeAttributes(EncodedAttrib* ea, int eaSz, } -static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz) -{ - int i, idx; +typedef struct FlatAttrib { + byte* data; + word32 dataSz; +} FlatAttrib; + +/* Returns a pointer to FlatAttrib whose members are initialized to 0. +* Caller is expected to free. +*/ +static FlatAttrib* NewAttrib(void* heap) +{ + FlatAttrib* fb = (FlatAttrib*) XMALLOC(sizeof(FlatAttrib), heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (fb != NULL) { + ForceZero(fb, sizeof(FlatAttrib)); + } + (void)heap; + return fb; +} + +/* Free FlatAttrib array and memory allocated to internal struct members */ +static void FreeAttribArray(PKCS7* pkcs7, FlatAttrib** arr, int rows) +{ + int i; + + if (arr) { + for (i = 0; i < rows; i++) { + if (arr[i]) { + if (arr[i]->data) { + ForceZero(arr[i]->data, arr[i]->dataSz); + XFREE(arr[i]->data, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + ForceZero(arr[i], sizeof(FlatAttrib)); + XFREE(arr[i], pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + } + ForceZero(arr, rows); + XFREE(arr, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + (void)pkcs7; +} + + +/* Sort FlatAttrib array in ascending order */ +static int SortAttribArray(FlatAttrib** arr, int rows) +{ + int i, j; + word32 minSz, minIdx; + FlatAttrib* a = NULL; + FlatAttrib* b = NULL; + FlatAttrib* tmp = NULL; + + if (arr == NULL) { + return BAD_FUNC_ARG; + } + + for (i = 0; i < rows; i++) { + a = arr[i]; + minSz = a->dataSz; + minIdx = i; + for (j = i+1; j < rows; j++) { + b = arr[j]; + if (b->dataSz < minSz) { + minSz = b->dataSz; + minIdx = j; + } + } + if (minSz < a->dataSz) { + /* swap array positions */ + tmp = arr[i]; + arr[i] = arr[minIdx]; + arr[minIdx] = tmp; + } + } + + return 0; +} + + +/* Build up array of FlatAttrib structs from EncodedAttrib ones. FlatAttrib + * holds flattened DER encoding of each attribute */ +static int FlattenEncodedAttribs(PKCS7* pkcs7, FlatAttrib** derArr, int rows, + EncodedAttrib* ea, int eaSz) +{ + int i, idx, sz; + byte* output = NULL; + FlatAttrib* fa = NULL; + + if (pkcs7 == NULL || derArr == NULL || ea == NULL) { + WOLFSSL_MSG("Invalid arguments to FlattenEncodedAttribs"); + return BAD_FUNC_ARG; + } + + if (rows != eaSz) { + WOLFSSL_MSG("DER array not large enough to hold attribute count"); + return BAD_FUNC_ARG; + } - idx = 0; for (i = 0; i < eaSz; i++) { + sz = ea[i].valueSeqSz + ea[i].oidSz + ea[i].valueSetSz + ea[i].valueSz; + + output = (byte*)XMALLOC(sz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + return MEMORY_E; + } + + idx = 0; XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz); idx += ea[i].valueSeqSz; XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz); @@ -335,293 +1503,893 @@ static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz) XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz); idx += ea[i].valueSetSz; XMEMCPY(output + idx, ea[i].value, ea[i].valueSz); - idx += ea[i].valueSz; + + fa = derArr[i]; + fa->data = output; + fa->dataSz = sz; } + return 0; } -/* build PKCS#7 signedData content type */ -int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) +/* Sort and Flatten EncodedAttrib attributes into output buffer */ +static int FlattenAttributes(PKCS7* pkcs7, byte* output, EncodedAttrib* ea, + int eaSz) { - static const byte outerOid[] = - { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, - 0x07, 0x02 }; - static const byte innerOid[] = - { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, - 0x07, 0x01 }; + int i, idx, ret; + FlatAttrib** derArr = NULL; + FlatAttrib* fa = NULL; + if (pkcs7 == NULL || output == NULL || ea == NULL) { + return BAD_FUNC_ARG; + } + + /* create array of FlatAttrib struct pointers to hold DER attribs */ + derArr = (FlatAttrib**) XMALLOC(eaSz * sizeof(FlatAttrib*), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (derArr == NULL) { + return MEMORY_E; + } + XMEMSET(derArr, 0, eaSz * sizeof(FlatAttrib*)); + + for (i = 0; i < eaSz; i++) { + derArr[i] = NewAttrib(pkcs7->heap); + if (derArr[i] == NULL) { + FreeAttribArray(pkcs7, derArr, eaSz); + return MEMORY_E; + } + ForceZero(derArr[i], sizeof(FlatAttrib)); + } + + /* flatten EncodedAttrib into DER byte arrays */ + ret = FlattenEncodedAttribs(pkcs7, derArr, eaSz, ea, eaSz); + if (ret != 0) { + FreeAttribArray(pkcs7, derArr, eaSz); + return ret; + } + + /* SET OF DER signed attributes must be sorted in ascending order */ + ret = SortAttribArray(derArr, eaSz); + if (ret != 0) { + FreeAttribArray(pkcs7, derArr, eaSz); + return ret; + } + + /* copy sorted DER attribute arrays into output buffer */ + idx = 0; + for (i = 0; i < eaSz; i++) { + fa = derArr[i]; + XMEMCPY(output + idx, fa->data, fa->dataSz); + idx += fa->dataSz; + } + + FreeAttribArray(pkcs7, derArr, eaSz); + + return 0; +} + + +#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 - ESD* esd = NULL; + RsaKey* privKey; #else - ESD stack_esd; - ESD* esd = &stack_esd; + RsaKey privKey[1]; #endif - word32 signerInfoSz = 0; - word32 totalSz = 0; - int idx = 0, ret = 0; - byte* flatSignedAttribs = NULL; - word32 flatSignedAttribsSz = 0; - word32 innerOidSz = sizeof(innerOid); - word32 outerOidSz = sizeof(outerOid); + if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { + return BAD_FUNC_ARG; + } - if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || - pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 || - pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 || - pkcs7->privateKey == NULL || pkcs7->privateKeySz == 0 || - output == NULL || outputSz == 0) +#ifdef WOLFSSL_SMALL_STACK + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId); + if (ret == 0) { + if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { + idx = 0; + ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + else if (pkcs7->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } + } + if (ret == 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + do { + ret = wc_AsyncWait(ret, &privKey->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret >= 0) + #endif + { + ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest, + sizeof(esd->encContentDigest), + privKey, pkcs7->rng); + } + #ifdef WOLFSSL_ASYNC_CRYPT + } while (ret == WC_PENDING_E); + #endif + } + + wc_FreeRsaKey(privKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, pkcs7->heap, 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 privKey[1]; +#endif + + if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_ecc_init_ex(privKey, pkcs7->heap, pkcs7->devId); + if (ret == 0) { + if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { + idx = 0; + ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + else if (pkcs7->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } + } + if (ret == 0) { + outSz = sizeof(esd->encContentDigest); + #ifdef WOLFSSL_ASYNC_CRYPT + do { + ret = wc_AsyncWait(ret, &privKey->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret >= 0) + #endif + { + ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest, + &outSz, pkcs7->rng, privKey); + } + #ifdef WOLFSSL_ASYNC_CRYPT + } while (ret == WC_PENDING_E); + #endif + if (ret == 0) + ret = (int)outSz; + } + + wc_ecc_free(privKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, pkcs7->heap, 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, + const byte* contentType, word32 contentTypeSz, + const byte* contentTypeOid, word32 contentTypeOidSz, + const byte* messageDigestOid, word32 messageDigestOidSz, + const byte* signingTimeOid, word32 signingTimeOidSz, + byte* signingTime, word32 signingTimeSz) +{ + int hashSz; +#ifdef NO_ASN_TIME + PKCS7Attrib cannedAttribs[2]; +#else + time_t tm; + int timeSz; + PKCS7Attrib cannedAttribs[3]; +#endif + word32 idx = 0; + word32 cannedAttribsCount; + + if (pkcs7 == NULL || esd == NULL || contentType == NULL || + contentTypeOid == NULL || messageDigestOid == NULL || + signingTimeOid == NULL) { + return BAD_FUNC_ARG; + } + + if (pkcs7->skipDefaultSignedAttribs == 0) { + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) + return hashSz; + + #ifndef NO_ASN_TIME + if (signingTime == NULL || signingTimeSz == 0) + return BAD_FUNC_ARG; + + tm = XTIME(0); + timeSz = GetAsnTimeString(&tm, signingTime, signingTimeSz); + if (timeSz < 0) + return timeSz; + #endif + + cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); + + cannedAttribs[idx].oid = contentTypeOid; + cannedAttribs[idx].oidSz = contentTypeOidSz; + cannedAttribs[idx].value = contentType; + cannedAttribs[idx].valueSz = contentTypeSz; + idx++; + #ifndef NO_ASN_TIME + cannedAttribs[idx].oid = signingTimeOid; + cannedAttribs[idx].oidSz = signingTimeOidSz; + cannedAttribs[idx].value = signingTime; + cannedAttribs[idx].valueSz = timeSz; + idx++; + #endif + cannedAttribs[idx].oid = messageDigestOid; + cannedAttribs[idx].oidSz = messageDigestOidSz; + cannedAttribs[idx].value = esd->contentDigest; + cannedAttribs[idx].valueSz = hashSz + 2; /* ASN.1 heading */ + + esd->signedAttribsCount += cannedAttribsCount; + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 3, + cannedAttribs, cannedAttribsCount); + } else { + esd->signedAttribsCount = 0; + esd->signedAttribsSz = 0; + } + + /* add custom signed attributes if set */ + if (pkcs7->signedAttribsSz > 0 && pkcs7->signedAttribs != NULL) { + esd->signedAttribsCount += pkcs7->signedAttribsSz; + #ifdef NO_ASN_TIME + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, + pkcs7->signedAttribs, pkcs7->signedAttribsSz); + #else + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[3], 4, + pkcs7->signedAttribs, pkcs7->signedAttribsSz); + #endif + } + +#ifdef NO_ASN_TIME + (void)signingTimeOidSz; + (void)signingTime; + (void)signingTimeSz; +#endif + + return 0; +} + + +/* gets correct encryption algo ID for SignedData, either CTC_wRSA or + * CTC_wECDSA, from pkcs7->publicKeyOID and pkcs7->hashOID. + * + * 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) { + + algoType = oidSigType; + + switch (pkcs7->hashOID) { + #ifndef NO_SHA + case SHAh: + algoId = CTC_SHAwRSA; + break; + #endif + #ifdef WOLFSSL_SHA224 + case SHA224h: + algoId = CTC_SHA224wRSA; + break; + #endif + #ifndef NO_SHA256 + case SHA256h: + algoId = CTC_SHA256wRSA; + break; + #endif + #ifdef WOLFSSL_SHA384 + case SHA384h: + algoId = CTC_SHA384wRSA; + break; + #endif + #ifdef WOLFSSL_SHA512 + case SHA512h: + algoId = CTC_SHA512wRSA; + break; + #endif + } + + } +#ifdef HAVE_ECC + else if (pkcs7->publicKeyOID == ECDSAk) { + + algoType = oidSigType; + + switch (pkcs7->hashOID) { + #ifndef NO_SHA + case SHAh: + algoId = CTC_SHAwECDSA; + break; + #endif + #ifdef WOLFSSL_SHA224 + case SHA224h: + algoId = CTC_SHA224wECDSA; + break; + #endif + #ifndef NO_SHA256 + case SHA256h: + algoId = CTC_SHA256wECDSA; + break; + #endif + #ifdef WOLFSSL_SHA384 + case SHA384h: + algoId = CTC_SHA384wECDSA; + break; + #endif + #ifdef WOLFSSL_SHA512 + case SHA512h: + algoId = CTC_SHA512wECDSA; + break; + #endif + } + } +#endif /* HAVE_ECC */ + + 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 (flatSignedAttribsSz != 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) + ret = wc_HashUpdate(&esd->hash, esd->hashType, + flatSignedAttribs, flatSignedAttribsSz); + if (ret == 0) + ret = wc_HashFinal(&esd->hash, esd->hashType, + esd->contentAttribsDigest); + wc_HashFree(&esd->hash, esd->hashType); + + 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 initialized 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 = 0; +#if defined(HAVE_ECC) || \ + (defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)) + int hashSz = 0; +#endif +#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) + int hashOID; +#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 - esd = (ESD*)XMALLOC(sizeof(ESD), NULL, DYNAMIC_TYPE_TMP_BUFFER); + digestInfo = (byte*)XMALLOC(digestInfoSz, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (digestInfo == NULL) { + return MEMORY_E; + } +#endif + XMEMSET(digestInfo, 0, digestInfoSz); + + ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd, digestInfo, + &digestInfoSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + +#if defined(HAVE_ECC) || \ + (defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)) + /* get digest size from hash type */ + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return hashSz; + } +#endif + + /* sign digestInfo */ + switch (pkcs7->publicKeyOID) { + +#ifndef NO_RSA + case RSAk: + #ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK + if (pkcs7->rsaSignRawDigestCb != NULL) { + /* get hash OID */ + hashOID = wc_HashGetOID(esd->hashType); + + /* user signing plain digest, build DigestInfo themselves */ + ret = pkcs7->rsaSignRawDigestCb(pkcs7, + esd->contentAttribsDigest, hashSz, + esd->encContentDigest, sizeof(esd->encContentDigest), + pkcs7->privateKey, pkcs7->privateKeySz, pkcs7->devId, + hashOID); + break; + } + #endif + 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 */ + 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, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret >= 0) { + esd->encContentDigestSz = (word32)ret; + } + + return ret; +} + + +/* build PKCS#7 signedData content type */ +static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, + const byte* hashBuf, word32 hashSz, byte* output, word32* outputSz, + byte* output2, word32* output2Sz) +{ + /* contentType OID (1.2.840.113549.1.9.3) */ + const byte contentTypeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, + 0x09, 0x03 }; + + /* messageDigest OID (1.2.840.113549.1.9.4) */ + const byte messageDigestOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x04 }; + + /* signingTime OID () */ + byte signingTimeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x05}; + + Pkcs7Cert* certPtr = NULL; + word32 certSetSz = 0; + + word32 signerInfoSz = 0; + word32 totalSz, total2Sz; + int idx = 0, ret = 0; + int digEncAlgoId, digEncAlgoType; + byte* flatSignedAttribs = NULL; + word32 flatSignedAttribsSz = 0; + + byte signedDataOid[MAX_OID_SZ]; + word32 signedDataOidSz; + + byte signingTime[MAX_TIME_STRING_SZ]; + + if (pkcs7 == NULL || pkcs7->contentSz == 0 || + pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 || + output == NULL || outputSz == NULL || *outputSz == 0 || hashSz == 0 || + hashBuf == NULL) { + return BAD_FUNC_ARG; + } + + /* verify the hash size matches */ +#ifdef WOLFSSL_SMALL_STACK + esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); if (esd == NULL) return MEMORY_E; #endif XMEMSET(esd, 0, sizeof(ESD)); - ret = wc_InitSha(&esd->sha); - if (ret != 0) { + + /* set content type based on contentOID, unless user has set custom one + with wc_PKCS7_SetContentType() */ + if (pkcs7->contentTypeSz == 0) { + + /* default to DATA content type if user has not set */ + if (pkcs7->contentOID == 0) { + pkcs7->contentOID = DATA; + } + + ret = wc_SetContentType(pkcs7->contentOID, pkcs7->contentType, + sizeof(pkcs7->contentType)); + if (ret < 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + pkcs7->contentTypeSz = ret; + } + + /* set signedData outer content type */ + ret = wc_SetContentType(SIGNED_DATA, signedDataOid, sizeof(signedDataOid)); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } + signedDataOidSz = ret; - if (pkcs7->contentSz != 0) - { - wc_ShaUpdate(&esd->sha, pkcs7->content, pkcs7->contentSz); + if (pkcs7->sidType != DEGENERATE_SID) { + esd->hashType = wc_OidGetHash(pkcs7->hashOID); + if (wc_HashGetDigestSize(esd->hashType) != (int)hashSz) { + WOLFSSL_MSG("hashSz did not match hashOID"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + + /* include hash */ esd->contentDigest[0] = ASN_OCTET_STRING; - esd->contentDigest[1] = SHA_DIGEST_SIZE; - wc_ShaFinal(&esd->sha, &esd->contentDigest[2]); + esd->contentDigest[1] = (byte)hashSz; + XMEMCPY(&esd->contentDigest[2], hashBuf, hashSz); } - esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets); - esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz + pkcs7->contentSz, - esd->innerContSeq); - esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd->innerOctetsSz + - innerOidSz + esd->innerContSeqSz, - esd->contentInfoSeq); + if (pkcs7->detached == 1) { + /* do not include content if generating detached signature */ + esd->innerOctetsSz = 0; + esd->innerContSeqSz = 0; + esd->contentInfoSeqSz = SetSequence(pkcs7->contentTypeSz, + esd->contentInfoSeq); + } else { + esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets); + esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz + + pkcs7->contentSz, esd->innerContSeq); + esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz + + esd->innerOctetsSz + pkcs7->contentTypeSz + + esd->innerContSeqSz, esd->contentInfoSeq); + } - esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, - esd->issuerSn); - signerInfoSz += esd->issuerSnSz; - esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName); - signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz; - esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq); - signerInfoSz += esd->issuerSnSeqSz; - esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0); - signerInfoSz += esd->signerVersionSz; - esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId, - hashType, 0); - signerInfoSz += esd->signerDigAlgoIdSz; - esd->digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd->digEncAlgoId, - keyType, 0); - signerInfoSz += esd->digEncAlgoIdSz; + /* SignerIdentifier */ + if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + /* IssuerAndSerialNumber */ + esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, + esd->issuerSn, MAX_SN_SZ, MAX_SN_SZ); + signerInfoSz += esd->issuerSnSz; + esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName); + signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz; + esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq); + signerInfoSz += esd->issuerSnSeqSz; - 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] = - { - { contentTypeOid, sizeof(contentTypeOid), - contentType, sizeof(contentType) }, - { messageDigestOid, sizeof(messageDigestOid), - esd->contentDigest, sizeof(esd->contentDigest) } - }; - word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); - - 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); - - flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, 0, NULL); - flatSignedAttribsSz = esd->signedAttribsSz; - if (flatSignedAttribs == NULL) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return MEMORY_E; + if (pkcs7->version == 3) { + /* RFC 4108 version MUST be 3 for firmware package signer */ + esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0); } - FlattenAttributes(flatSignedAttribs, - esd->signedAttribs, esd->signedAttribsCount); - esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz, - esd->signedAttribSet); + else { + /* version MUST be 1 otherwise*/ + esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0); + } + + } else if (pkcs7->sidType == CMS_SKID) { + /* SubjectKeyIdentifier */ + esd->issuerSKIDSz = SetOctetString(KEYID_SIZE, esd->issuerSKID); + esd->issuerSKIDSeqSz = SetExplicit(0, esd->issuerSKIDSz + KEYID_SIZE, + esd->issuerSKIDSeq); + signerInfoSz += (esd->issuerSKIDSz + esd->issuerSKIDSeqSz + + KEYID_SIZE); + + /* version MUST be 3 */ + esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0); + } else if (pkcs7->sidType == DEGENERATE_SID) { + /* no signer info added */ + } else { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return SKID_E; } - /* Calculate the final hash and encrypt it. */ - { - int result; - word32 scratch = 0; -#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]; -#endif - byte digestInfoSeq[MAX_SEQ_SZ]; - byte digestStr[MAX_OCTET_STR_SZ]; - word32 digestInfoSeqSz, digestStrSz; - int digIdx = 0; + if (pkcs7->sidType != DEGENERATE_SID) { + signerInfoSz += esd->signerVersionSz; + esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId, + oidHashType, 0); + signerInfoSz += esd->signerDigAlgoIdSz; - if (pkcs7->signedAttribsSz != 0) { - byte attribSet[MAX_SET_SZ]; - word32 attribSetSz; + /* set signatureAlgorithm */ + ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId, + &digEncAlgoType); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + esd->digEncAlgoIdSz = SetAlgoID(digEncAlgoId, esd->digEncAlgoId, + digEncAlgoType, 0); + signerInfoSz += esd->digEncAlgoIdSz; - attribSetSz = SetSet(flatSignedAttribsSz, attribSet); + /* build up signed attributes, include contentType, signingTime, and + messageDigest by default */ + ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, pkcs7->contentType, + pkcs7->contentTypeSz, + contentTypeOid, sizeof(contentTypeOid), + messageDigestOid, sizeof(messageDigestOid), + signingTimeOid, sizeof(signingTimeOid), + signingTime, sizeof(signingTime)); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } - ret = wc_InitSha(&esd->sha); - if (ret < 0) { - XFREE(flatSignedAttribs, 0, NULL); -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; + if (esd->signedAttribsSz > 0) { + flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + flatSignedAttribsSz = esd->signedAttribsSz; + if (flatSignedAttribs == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; } - wc_ShaUpdate(&esd->sha, attribSet, attribSetSz); - wc_ShaUpdate(&esd->sha, flatSignedAttribs, flatSignedAttribsSz); + + FlattenAttributes(pkcs7, flatSignedAttribs, + esd->signedAttribs, esd->signedAttribsCount); + esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz, + esd->signedAttribSet); + } else { + esd->signedAttribSetSz = 0; } - wc_ShaFinal(&esd->sha, esd->contentAttribsDigest); - 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) { + /* Calculate the final hash and encrypt it. */ + ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd); + if (ret < 0) { 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, NULL); - if (result == 0) - result = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, privKey, - pkcs7->privateKeySz); - if (result < 0) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, 0, NULL); -#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; + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; } - result = wc_RsaSSL_Sign(digestInfo, digIdx, - esd->encContentDigest, - sizeof(esd->encContentDigest), - privKey, pkcs7->rng); + signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz; - wc_FreeRsaKey(privKey); + esd->signerDigestSz = SetOctetString(esd->encContentDigestSz, + esd->signerDigest); + signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz; -#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, 0, NULL); -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return result; - } - esd->encContentDigestSz = (word32)result; + esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq); + signerInfoSz += esd->signerInfoSeqSz; } - signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz; - - esd->signerDigestSz = SetOctetString(esd->encContentDigestSz, - esd->signerDigest); - signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz; - - esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq); - signerInfoSz += esd->signerInfoSeqSz; esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet); signerInfoSz += esd->signerInfoSetSz; - esd->certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz, - esd->certsSet); + /* certificates [0] IMPLICIT CertificateSet */ + /* get total certificates size */ + certPtr = pkcs7->certList; + while (certPtr != NULL) { + certSetSz += certPtr->derSz; + certPtr = certPtr->next; + } + certPtr = NULL; - esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId, - hashType, 0); + if (certSetSz > 0) + esd->certsSetSz = SetImplicit(ASN_SET, 0, certSetSz, esd->certsSet); + + if (pkcs7->sidType != DEGENERATE_SID) { + esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId, + oidHashType, 0); + } esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet); - - esd->versionSz = SetMyVersion(1, esd->version, 0); + if (pkcs7->version == 3) { + /* RFC 4108 version MUST be 3 for firmware package signer */ + esd->versionSz = SetMyVersion(3, esd->version, 0); + } + else { + esd->versionSz = SetMyVersion(1, esd->version, 0); + } totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz + - esd->contentInfoSeqSz + esd->certsSetSz + pkcs7->singleCertSz + - esd->innerOctetsSz + esd->innerContSeqSz + - innerOidSz + pkcs7->contentSz + - signerInfoSz; - esd->innerSeqSz = SetSequence(totalSz, esd->innerSeq); + esd->contentInfoSeqSz + pkcs7->contentTypeSz + + esd->innerContSeqSz + esd->innerOctetsSz + pkcs7->contentSz; + total2Sz = esd->certsSetSz + certSetSz + signerInfoSz; + + if (pkcs7->detached) { + totalSz -= pkcs7->contentSz; + } + + esd->innerSeqSz = SetSequence(totalSz + total2Sz, esd->innerSeq); totalSz += esd->innerSeqSz; - esd->outerContentSz = SetExplicit(0, totalSz, esd->outerContent); - totalSz += esd->outerContentSz + outerOidSz; - esd->outerSeqSz = SetSequence(totalSz, esd->outerSeq); + esd->outerContentSz = SetExplicit(0, totalSz + total2Sz, esd->outerContent); + totalSz += esd->outerContentSz + signedDataOidSz; + esd->outerSeqSz = SetSequence(totalSz + total2Sz, esd->outerSeq); totalSz += esd->outerSeqSz; - if (outputSz < totalSz) { + /* if using header/footer, we are not returning the content */ + if (output2 && output2Sz) { + if (total2Sz > *output2Sz) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + + if (!pkcs7->detached) { + totalSz -= pkcs7->contentSz; + } + } + else { + /* if using single output buffer include content and footer */ + totalSz += total2Sz; + } + + if (totalSz > *outputSz) { if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, 0, NULL); -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif return BUFFER_E; } idx = 0; XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz); idx += esd->outerSeqSz; - XMEMCPY(output + idx, outerOid, outerOidSz); - idx += outerOidSz; + XMEMCPY(output + idx, signedDataOid, signedDataOidSz); + idx += signedDataOidSz; XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz); idx += esd->outerContentSz; XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz); @@ -634,326 +2402,3617 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) idx += esd->singleDigAlgoIdSz; XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz); idx += esd->contentInfoSeqSz; - XMEMCPY(output + idx, innerOid, innerOidSz); - idx += innerOidSz; + XMEMCPY(output + idx, pkcs7->contentType, pkcs7->contentTypeSz); + idx += pkcs7->contentTypeSz; XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz); idx += esd->innerContSeqSz; XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz); idx += esd->innerOctetsSz; - XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); - idx += pkcs7->contentSz; - XMEMCPY(output + idx, esd->certsSet, esd->certsSetSz); + + /* support returning header and footer without content */ + if (output2 && output2Sz) { + *outputSz = idx; + idx = 0; + } + else { + if (!pkcs7->detached) { + XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); + idx += pkcs7->contentSz; + } + output2 = output; + } + + /* certificates */ + XMEMCPY(output2 + idx, esd->certsSet, esd->certsSetSz); idx += esd->certsSetSz; - XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz); - idx += pkcs7->singleCertSz; - XMEMCPY(output + idx, esd->signerInfoSet, esd->signerInfoSetSz); + certPtr = pkcs7->certList; + while (certPtr != NULL) { + XMEMCPY(output2 + idx, certPtr->der, certPtr->derSz); + idx += certPtr->derSz; + certPtr = certPtr->next; + } + wc_PKCS7_FreeCertSet(pkcs7); + + XMEMCPY(output2 + idx, esd->signerInfoSet, esd->signerInfoSetSz); idx += esd->signerInfoSetSz; - XMEMCPY(output + idx, esd->signerInfoSeq, esd->signerInfoSeqSz); + XMEMCPY(output2 + idx, esd->signerInfoSeq, esd->signerInfoSeqSz); idx += esd->signerInfoSeqSz; - XMEMCPY(output + idx, esd->signerVersion, esd->signerVersionSz); + XMEMCPY(output2 + idx, esd->signerVersion, esd->signerVersionSz); idx += esd->signerVersionSz; - XMEMCPY(output + idx, esd->issuerSnSeq, esd->issuerSnSeqSz); - idx += esd->issuerSnSeqSz; - XMEMCPY(output + idx, esd->issuerName, esd->issuerNameSz); - idx += esd->issuerNameSz; - XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz); - idx += pkcs7->issuerSz; - XMEMCPY(output + idx, esd->issuerSn, esd->issuerSnSz); - idx += esd->issuerSnSz; - XMEMCPY(output + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz); + /* SignerIdentifier */ + if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + /* IssuerAndSerialNumber */ + XMEMCPY(output2 + idx, esd->issuerSnSeq, esd->issuerSnSeqSz); + idx += esd->issuerSnSeqSz; + XMEMCPY(output2 + idx, esd->issuerName, esd->issuerNameSz); + idx += esd->issuerNameSz; + XMEMCPY(output2 + idx, pkcs7->issuer, pkcs7->issuerSz); + idx += pkcs7->issuerSz; + XMEMCPY(output2 + idx, esd->issuerSn, esd->issuerSnSz); + idx += esd->issuerSnSz; + } else if (pkcs7->sidType == CMS_SKID) { + /* SubjectKeyIdentifier */ + XMEMCPY(output2 + idx, esd->issuerSKIDSeq, esd->issuerSKIDSeqSz); + idx += esd->issuerSKIDSeqSz; + XMEMCPY(output2 + idx, esd->issuerSKID, esd->issuerSKIDSz); + idx += esd->issuerSKIDSz; + XMEMCPY(output2 + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE); + idx += KEYID_SIZE; + } else if (pkcs7->sidType == DEGENERATE_SID) { + /* no signer infos in degenerate case */ + } else { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return SKID_E; + } + XMEMCPY(output2 + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz); idx += esd->signerDigAlgoIdSz; /* SignerInfo:Attributes */ - if (pkcs7->signedAttribsSz != 0) { - XMEMCPY(output + idx, esd->signedAttribSet, esd->signedAttribSetSz); + if (flatSignedAttribsSz > 0) { + XMEMCPY(output2 + idx, esd->signedAttribSet, esd->signedAttribSetSz); idx += esd->signedAttribSetSz; - XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz); + XMEMCPY(output2 + idx, flatSignedAttribs, flatSignedAttribsSz); idx += flatSignedAttribsSz; - XFREE(flatSignedAttribs, 0, NULL); + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); } - XMEMCPY(output + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz); + XMEMCPY(output2 + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz); idx += esd->digEncAlgoIdSz; - XMEMCPY(output + idx, esd->signerDigest, esd->signerDigestSz); + XMEMCPY(output2 + idx, esd->signerDigest, esd->signerDigestSz); idx += esd->signerDigestSz; - XMEMCPY(output + idx, esd->encContentDigest, esd->encContentDigestSz); + XMEMCPY(output2 + idx, esd->encContentDigest, esd->encContentDigestSz); idx += esd->encContentDigestSz; -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + if (output2 && output2Sz) { + *output2Sz = idx; + idx = 0; /* success */ + } + else { + *outputSz = idx; + } +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif return idx; } - -/* Finds the certificates in the message and saves it. */ -int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) +/* hashBuf: The computed digest for the pkcs7->content + * hashSz: The size of computed digest for the pkcs7->content based on hashOID + * outputHead: The PKCS7 header that goes on top of the raw data signed. + * outputFoot: The PKCS7 footer that goes at the end of the raw data signed. + * pkcs7->content: Not used + * pkcs7->contentSz: Must be provided as actual sign of raw data + * return codes: 0=success, negative=error + */ +int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf, + word32 hashSz, byte* outputHead, word32* outputHeadSz, byte* outputFoot, + word32* outputFootSz) { - word32 idx, contentType; - int length, version, ret; - byte* content = NULL; - byte* sig = NULL; - byte* cert = NULL; - int contentSz = 0, sigSz = 0, certSz = 0; + int ret; +#ifdef WOLFSSL_SMALL_STACK + ESD* esd; +#else + ESD esd[1]; +#endif - if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0) + /* other args checked in wc_PKCS7_EncodeSigned_ex */ + if (pkcs7 == NULL || outputFoot == NULL || outputFootSz == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (esd == NULL) + return MEMORY_E; +#endif + + XMEMSET(esd, 0, sizeof(ESD)); + + ret = PKCS7_EncodeSigned(pkcs7, esd, hashBuf, hashSz, + outputHead, outputHeadSz, outputFoot, outputFootSz); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +/* Toggle detached signature mode on/off for PKCS#7/CMS SignedData content type. + * By default wolfCrypt includes the data to be signed in the SignedData + * bundle. This data can be omitted in the case when a detached signature is + * being created. To enable generation of detached signatures, set flag to "1", + * otherwise set to "0": + * + * flag 1 turns on support + * flag 0 turns off support + * + * pkcs7 - pointer to initialized PKCS7 structure + * flag - turn on/off detached signature generation (1 or 0) + * + * Returns 0 on success, negative upon error. */ +int wc_PKCS7_SetDetached(PKCS7* pkcs7, word16 flag) +{ + if (pkcs7 == NULL || (flag != 0 && flag != 1)) return BAD_FUNC_ARG; - idx = 0; + pkcs7->detached = flag; - /* Get the contentInfo sequence */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; + return 0; +} - /* Get the contentInfo contentType */ - if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) - return ASN_PARSE_E; +/* By default, SignedData bundles have the following signed attributes attached: + * contentType (1.2.840.113549.1.9.3) + * signgingTime (1.2.840.113549.1.9.5) + * messageDigest (1.2.840.113549.1.9.4) + * + * Calling this API before wc_PKCS7_EncodeSignedData() will disable the + * inclusion of those attributes. + * + * pkcs7 - pointer to initialized PKCS7 structure + * + * Returns 0 on success, negative upon error. */ +int wc_PKCS7_NoDefaultSignedAttribs(PKCS7* pkcs7) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; - if (contentType != SIGNED_DATA) { - WOLFSSL_MSG("PKCS#7 input not of type SignedData"); - return PKCS7_OID_E; - } + pkcs7->skipDefaultSignedAttribs = 1; - /* get the ContentInfo content */ - if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) - return ASN_PARSE_E; - - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* Get the signedData sequence */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* Get the version */ - if (GetMyVersion(pkiMsg, &idx, &version) < 0) - return ASN_PARSE_E; - - if (version != 1) { - WOLFSSL_MSG("PKCS#7 signedData needs to be of version 1"); - return ASN_VERSION_E; - } - - /* Get the set of DigestAlgorithmIdentifiers */ - if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* Skip the set. */ - idx += length; - - /* Get the inner ContentInfo sequence */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* Get the inner ContentInfo contentType */ - if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (contentType != DATA) { - WOLFSSL_MSG("PKCS#7 inner input not of type Data"); - return PKCS7_OID_E; - } - - if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) - return ASN_PARSE_E; - - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (pkiMsg[idx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* Save the inner data as the content. */ - if (length > 0) { - /* Local pointer for calculating hashes later */ - pkcs7->content = content = &pkiMsg[idx]; - pkcs7->contentSz = contentSz = length; - idx += length; - } - - /* Get the implicit[0] set of certificates */ - if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { - idx++; - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (length > 0) { - /* At this point, idx is at the first certificate in - * a set of certificates. There may be more than one, - * or none, or they may be a PKCS 6 extended - * certificate. We want to save the first cert if it - * is X.509. */ - - word32 certIdx = idx; - - if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { - if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0) - return ASN_PARSE_E; - - cert = &pkiMsg[idx]; - certSz += (certIdx - idx); - } - wc_PKCS7_InitWithCert(pkcs7, cert, certSz); - } - idx += length; - } - - /* Get the implicit[1] set of crls */ - if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { - idx++; - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* Skip the set */ - idx += length; - } - - /* Get the set of signerInfos */ - if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (length > 0) { - /* Get the sequence of the first signerInfo */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* Get the version */ - if (GetMyVersion(pkiMsg, &idx, &version) < 0) - return ASN_PARSE_E; - - if (version != 1) { - WOLFSSL_MSG("PKCS#7 signerInfo needs to be of version 1"); - return ASN_VERSION_E; - } - - /* Get the sequence of IssuerAndSerialNumber */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* Skip it */ - idx += length; - - /* Get the sequence of digestAlgorithm */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* Skip it */ - idx += length; - - /* Get the IMPLICIT[0] SET OF signedAttributes */ - if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { - idx++; - - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - idx += length; - } - - /* Get the sequence of digestEncryptionAlgorithm */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* Skip it */ - idx += length; - - /* Get the signature */ - if (pkiMsg[idx] == ASN_OCTET_STRING) { - idx++; - - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* save pointer and length */ - sig = &pkiMsg[idx]; - sigSz = length; - - idx += length; - } - - pkcs7->content = content; - pkcs7->contentSz = contentSz; - - { - word32 scratch = 0; - int plainSz = 0; - int digestSz = MAX_SEQ_SZ + MAX_ALGO_SZ + - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE; + return 0; +} +/* return codes: >0: Size of signed PKCS7 output buffer, negative: error */ +int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) +{ + int ret; + int hashSz; + enum wc_HashType hashType; + byte hashBuf[WC_MAX_DIGEST_SIZE]; #ifdef WOLFSSL_SMALL_STACK - byte* digest; - RsaKey* key; - - digest = (byte*)XMALLOC(digestSz, 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; - } + ESD* esd; #else - byte digest[digestSz]; - RsaKey stack_key; - RsaKey* key = &stack_key; + ESD esd[1]; #endif - XMEMSET(digest, 0, digestSz); + /* other args checked in wc_PKCS7_EncodeSigned_ex */ + if (pkcs7 == NULL || pkcs7->contentSz == 0 || pkcs7->content == NULL) { + return BAD_FUNC_ARG; + } - ret = wc_InitRsaKey(key, NULL); - 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, digestSz, key); - wc_FreeRsaKey(key); + /* get hash type and size, validate hashOID */ + hashType = wc_OidGetHash(pkcs7->hashOID); + hashSz = wc_HashGetDigestSize(hashType); + if (hashSz < 0) + return hashSz; #ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (esd == NULL) + return MEMORY_E; #endif - if (plainSz < 0) - return plainSz; + XMEMSET(esd, 0, sizeof(ESD)); + esd->hashType = hashType; + + /* calculate hash for content */ + ret = wc_HashInit(&esd->hash, esd->hashType); + if (ret == 0) { + ret = wc_HashUpdate(&esd->hash, esd->hashType, + pkcs7->content, pkcs7->contentSz); + if (ret == 0) { + ret = wc_HashFinal(&esd->hash, esd->hashType, hashBuf); } + wc_HashFree(&esd->hash, esd->hashType); + } + + if (ret == 0) { + ret = PKCS7_EncodeSigned(pkcs7, esd, hashBuf, hashSz, + output, &outputSz, NULL, NULL); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +/* Single-shot API to generate a CMS SignedData bundle that encapsulates a + * content of type FirmwarePkgData. Any recipient certificates should be + * loaded into the PKCS7 structure prior to calling this function, using + * wc_PKCS7_InitWithCert() and/or wc_PKCS7_AddCertificate(). + * + * pkcs7 - pointer to initialized PKCS7 struct + * privateKey - private RSA/ECC key, used for signing SignedData + * privateKeySz - size of privateKey, octets + * signOID - public key algorithm OID, used for sign operation + * hashOID - hash algorithm OID, used for signature generation + * content - content to be encapsulated, of type FirmwarePkgData + * contentSz - size of content, octets + * signedAttribs - optional signed attributes + * signedAttribsSz - number of PKCS7Attrib members in signedAttribs + * output - output buffer for final bundle + * outputSz - size of output buffer, octets + * + * Returns length of generated bundle on success, negative upon error. */ +int wc_PKCS7_EncodeSignedFPD(PKCS7* pkcs7, byte* privateKey, + word32 privateKeySz, int signOID, int hashOID, + byte* content, word32 contentSz, + PKCS7Attrib* signedAttribs, word32 signedAttribsSz, + byte* output, word32 outputSz) +{ + int ret = 0; + WC_RNG rng; + + if (pkcs7 == NULL || privateKey == NULL || privateKeySz == 0 || + content == NULL || contentSz == 0 || output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + pkcs7->rng = &rng; + pkcs7->content = content; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + pkcs7->hashOID = hashOID; + pkcs7->encryptOID = signOID; + pkcs7->privateKey = privateKey; + pkcs7->privateKeySz = privateKeySz; + pkcs7->signedAttribs = signedAttribs; + pkcs7->signedAttribsSz = signedAttribsSz; + pkcs7->version = 3; + + ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + if (ret <= 0) { + WOLFSSL_MSG("Error encoding CMS SignedData content type"); + } + + pkcs7->rng = NULL; + wc_FreeRng(&rng); + + return ret; +} + +#ifndef NO_PKCS7_ENCRYPTED_DATA + +/* Single-shot API to generate a CMS SignedData bundle that encapsulates a + * CMS EncryptedData bundle. Content of inner EncryptedData is set to that + * of FirmwarePkgData. Any recipient certificates should be loaded into the + * PKCS7 structure prior to calling this function, using wc_PKCS7_InitWithCert() + * and/or wc_PKCS7_AddCertificate(). + * + * pkcs7 - pointer to initialized PKCS7 struct + * encryptKey - encryption key used for encrypting EncryptedData + * encryptKeySz - size of encryptKey, octets + * privateKey - private RSA/ECC key, used for signing SignedData + * privateKeySz - size of privateKey, octets + * encryptOID - encryption algorithm OID, to be used as encryption + * algorithm for EncryptedData + * signOID - public key algorithm OID, to be used for sign + * operation in SignedData generation + * hashOID - hash algorithm OID, to be used for signature in + * SignedData generation + * content - content to be encapsulated + * contentSz - size of content, octets + * unprotectedAttribs - optional unprotected attributes, for EncryptedData + * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs + * signedAttribs - optional signed attributes, for SignedData + * signedAttribsSz - number of PKCS7Attrib members in signedAttribs + * output - output buffer for final bundle + * outputSz - size of output buffer, octets + * + * Returns length of generated bundle on success, negative upon error. */ +int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, byte* encryptKey, + word32 encryptKeySz, byte* privateKey, + word32 privateKeySz, int encryptOID, + int signOID, int hashOID, + byte* content, word32 contentSz, + PKCS7Attrib* unprotectedAttribs, + word32 unprotectedAttribsSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, + byte* output, word32 outputSz) +{ + int ret = 0, encryptedSz = 0; + byte* encrypted = NULL; + WC_RNG rng; + + if (pkcs7 == NULL || encryptKey == NULL || encryptKeySz == 0 || + privateKey == NULL || privateKeySz == 0 || content == NULL || + contentSz == 0 || output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* 1: build up EncryptedData using FirmwarePkgData type, use output + * buffer as tmp for storage and to get size */ + + /* set struct elements, inner content type is FirmwarePkgData */ + pkcs7->content = content; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + pkcs7->encryptOID = encryptOID; + pkcs7->encryptionKey = encryptKey; + pkcs7->encryptionKeySz = encryptKeySz; + pkcs7->unprotectedAttribs = unprotectedAttribs; + pkcs7->unprotectedAttribsSz = unprotectedAttribsSz; + pkcs7->version = 3; + + encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, output, outputSz); + if (encryptedSz < 0) { + WOLFSSL_MSG("Error encoding CMS EncryptedData content type"); + return encryptedSz; + } + + /* save encryptedData, reset output buffer and struct */ + encrypted = (byte*)XMALLOC(encryptedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (encrypted == NULL) { + ForceZero(output, outputSz); + return MEMORY_E; + } + + XMEMCPY(encrypted, output, encryptedSz); + ForceZero(output, outputSz); + + ret = wc_InitRng(&rng); + if (ret != 0) { + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* 2: build up SignedData, encapsulating EncryptedData */ + pkcs7->rng = &rng; + pkcs7->content = encrypted; + pkcs7->contentSz = encryptedSz; + pkcs7->contentOID = ENCRYPTED_DATA; + pkcs7->hashOID = hashOID; + pkcs7->encryptOID = signOID; + pkcs7->privateKey = privateKey; + pkcs7->privateKeySz = privateKeySz; + pkcs7->signedAttribs = signedAttribs; + pkcs7->signedAttribsSz = signedAttribsSz; + + ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + if (ret <= 0) { + WOLFSSL_MSG("Error encoding CMS SignedData content type"); + } + + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->rng = NULL; + wc_FreeRng(&rng); + + return ret; +} + +#endif /* NO_PKCS7_ENCRYPTED_DATA */ + +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) +/* Single-shot API to generate a CMS SignedData bundle that encapsulates a + * CMS CompressedData bundle. Content of inner CompressedData is set to that + * of FirmwarePkgData. Any recipient certificates should be loaded into the + * PKCS7 structure prior to calling this function, using wc_PKCS7_InitWithCert() + * and/or wc_PKCS7_AddCertificate(). + * + * pkcs7 - pointer to initialized PKCS7 struct + * privateKey - private RSA/ECC key, used for signing SignedData + * privateKeySz - size of privateKey, octets + * signOID - public key algorithm OID, to be used for sign + * operation in SignedData generation + * hashOID - hash algorithm OID, to be used for signature in + * SignedData generation + * content - content to be encapsulated + * contentSz - size of content, octets + * signedAttribs - optional signed attributes, for SignedData + * signedAttribsSz - number of PKCS7Attrib members in signedAttribs + * output - output buffer for final bundle + * outputSz - size of output buffer, octets + * + * Returns length of generated bundle on success, negative upon error. */ +int wc_PKCS7_EncodeSignedCompressedFPD(PKCS7* pkcs7, byte* privateKey, + word32 privateKeySz, int signOID, + int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, byte* output, + word32 outputSz) +{ + int ret = 0, compressedSz = 0; + byte* compressed = NULL; + WC_RNG rng; + + if (pkcs7 == NULL || privateKey == NULL || privateKeySz == 0 || + content == NULL || contentSz == 0 || output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* 1: build up CompressedData using FirmwarePkgData type, use output + * buffer as tmp for storage and to get size */ + + /* set struct elements, inner content type is FirmwarePkgData */ + pkcs7->content = content; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + pkcs7->version = 3; + + compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, output, outputSz); + if (compressedSz < 0) { + WOLFSSL_MSG("Error encoding CMS CompressedData content type"); + return compressedSz; + } + + /* save compressedData, reset output buffer and struct */ + compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (compressed == NULL) { + ForceZero(output, outputSz); + return MEMORY_E; + } + + XMEMCPY(compressed, output, compressedSz); + ForceZero(output, outputSz); + + ret = wc_InitRng(&rng); + if (ret != 0) { + ForceZero(compressed, compressedSz); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* 2: build up SignedData, encapsulating EncryptedData */ + pkcs7->rng = &rng; + pkcs7->content = compressed; + pkcs7->contentSz = compressedSz; + pkcs7->contentOID = COMPRESSED_DATA; + pkcs7->hashOID = hashOID; + pkcs7->encryptOID = signOID; + pkcs7->privateKey = privateKey; + pkcs7->privateKeySz = privateKeySz; + pkcs7->signedAttribs = signedAttribs; + pkcs7->signedAttribsSz = signedAttribsSz; + + ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + if (ret <= 0) { + WOLFSSL_MSG("Error encoding CMS SignedData content type"); + } + + ForceZero(compressed, compressedSz); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->rng = NULL; + wc_FreeRng(&rng); + + return ret; +} + +#ifndef NO_PKCS7_ENCRYPTED_DATA + +/* Single-shot API to generate a CMS SignedData bundle that encapsulates a + * CMS EncryptedData bundle, which then encapsulates a CMS CompressedData + * bundle. Content of inner CompressedData is set to that of FirmwarePkgData. + * Any recipient certificates should be loaded into the PKCS7 structure prior + * to calling this function, using wc_PKCS7_InitWithCert() and/or + * wc_PKCS7_AddCertificate(). + * + * pkcs7 - pointer to initialized PKCS7 struct + * encryptKey - encryption key used for encrypting EncryptedData + * encryptKeySz - size of encryptKey, octets + * privateKey - private RSA/ECC key, used for signing SignedData + * privateKeySz - size of privateKey, octets + * encryptOID - encryption algorithm OID, to be used as encryption + * algorithm for EncryptedData + * signOID - public key algorithm OID, to be used for sign + * operation in SignedData generation + * hashOID - hash algorithm OID, to be used for signature in + * SignedData generation + * content - content to be encapsulated + * contentSz - size of content, octets + * unprotectedAttribs - optional unprotected attributes, for EncryptedData + * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs + * signedAttribs - optional signed attributes, for SignedData + * signedAttribsSz - number of PKCS7Attrib members in signedAttribs + * output - output buffer for final bundle + * outputSz - size of output buffer, octets + * + * Returns length of generated bundle on success, negative upon error. */ +int wc_PKCS7_EncodeSignedEncryptedCompressedFPD(PKCS7* pkcs7, byte* encryptKey, + word32 encryptKeySz, byte* privateKey, + word32 privateKeySz, int encryptOID, + int signOID, int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* unprotectedAttribs, + word32 unprotectedAttribsSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, + byte* output, word32 outputSz) +{ + int ret = 0, compressedSz = 0, encryptedSz = 0; + byte* compressed = NULL; + byte* encrypted = NULL; + WC_RNG rng; + + if (pkcs7 == NULL || encryptKey == NULL || encryptKeySz == 0 || + privateKey == NULL || privateKeySz == 0 || content == NULL || + contentSz == 0 || output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* 1: build up CompressedData using FirmwarePkgData type, use output + * buffer as tmp for storage and to get size */ + pkcs7->content = content; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + pkcs7->version = 3; + + compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, output, outputSz); + if (compressedSz < 0) { + WOLFSSL_MSG("Error encoding CMS CompressedData content type"); + return compressedSz; + } + + /* save compressedData, reset output buffer and struct */ + compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (compressed == NULL) + return MEMORY_E; + + XMEMCPY(compressed, output, compressedSz); + ForceZero(output, outputSz); + + /* 2: build up EncryptedData using CompressedData, use output + * buffer as tmp for storage and to get size */ + pkcs7->content = compressed; + pkcs7->contentSz = compressedSz; + pkcs7->contentOID = COMPRESSED_DATA; + pkcs7->encryptOID = encryptOID; + pkcs7->encryptionKey = encryptKey; + pkcs7->encryptionKeySz = encryptKeySz; + pkcs7->unprotectedAttribs = unprotectedAttribs; + pkcs7->unprotectedAttribsSz = unprotectedAttribsSz; + + encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, output, outputSz); + if (encryptedSz < 0) { + WOLFSSL_MSG("Error encoding CMS EncryptedData content type"); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return encryptedSz; + } + + /* save encryptedData, reset output buffer and struct */ + encrypted = (byte*)XMALLOC(encryptedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (encrypted == NULL) { + ForceZero(compressed, compressedSz); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + XMEMCPY(encrypted, output, encryptedSz); + ForceZero(compressed, compressedSz); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + ForceZero(output, outputSz); + + ret = wc_InitRng(&rng); + if (ret != 0) { + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* 3: build up SignedData, encapsulating EncryptedData */ + pkcs7->rng = &rng; + pkcs7->content = encrypted; + pkcs7->contentSz = encryptedSz; + pkcs7->contentOID = ENCRYPTED_DATA; + pkcs7->hashOID = hashOID; + pkcs7->encryptOID = signOID; + pkcs7->privateKey = privateKey; + pkcs7->privateKeySz = privateKeySz; + pkcs7->signedAttribs = signedAttribs; + pkcs7->signedAttribsSz = signedAttribsSz; + + ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + if (ret <= 0) { + WOLFSSL_MSG("Error encoding CMS SignedData content type"); + } + + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->rng = NULL; + wc_FreeRng(&rng); + + return ret; +} + +#endif /* !NO_PKCS7_ENCRYPTED_DATA */ +#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + + +#ifndef NO_RSA + +#ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK +/* register raw RSA sign digest callback */ +int wc_PKCS7_SetRsaSignRawDigestCb(PKCS7* pkcs7, CallbackRsaSignRawDigest cb) +{ + if (pkcs7 == NULL || cb == NULL) { + return BAD_FUNC_ARG; + } + + pkcs7->rsaSignRawDigestCb = cb; + + return 0; +} +#endif + +/* 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, i; + word32 scratch = 0, verified = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + RsaKey* key; + DecodedCert* dCert; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + RsaKey key[1]; + DecodedCert stack_dCert; + DecodedCert* dCert = &stack_dCert; +#endif + + if (pkcs7 == NULL || sig == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (digest == NULL) + return MEMORY_E; + + key = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_DCERT); + if (dCert == NULL) { + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + /* loop over certs received in certificates set, try to find one + * that will validate signature */ + for (i = 0; i < MAX_PKCS7_CERTS; i++) { + + verified = 0; + scratch = 0; + + if (pkcs7->certSz[i] == 0) + continue; + + ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); +#endif + return ret; + } + + InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap); + /* not verifying, only using this to extract public key */ + ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); + if (ret < 0) { + WOLFSSL_MSG("ASN RSA cert parse error"); + FreeDecodedCert(dCert); + wc_FreeRsaKey(key); + continue; + } + + if (wc_RsaPublicKeyDecode(dCert->publicKey, &scratch, key, + dCert->pubKeySize) < 0) { + WOLFSSL_MSG("ASN RSA key decode error"); + FreeDecodedCert(dCert); + wc_FreeRsaKey(key); + continue; + } + + #ifdef WOLFSSL_ASYNC_CRYPT + do { + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, + key); + } + #ifdef WOLFSSL_ASYNC_CRYPT + } while (ret == WC_PENDING_E); + #endif + FreeDecodedCert(dCert); + wc_FreeRsaKey(key); + + if ((ret > 0) && (hashSz == (word32)ret)) { + if (XMEMCMP(digest, hash, hashSz) == 0) { + /* found signer that successfully verified signature */ + verified = 1; + break; + } + } + } + + if (verified == 0) { + ret = SIG_VERIFY_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); +#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, i; + int res = 0; + int verified = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + ecc_key* key; + DecodedCert* dCert; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + ecc_key key[1]; + DecodedCert stack_dCert; + DecodedCert* dCert = &stack_dCert; +#endif + word32 idx = 0; + + if (pkcs7 == NULL || sig == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (digest == NULL) + return MEMORY_E; + + key = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_DCERT); + if (dCert == NULL) { + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + /* loop over certs received in certificates set, try to find one + * that will validate signature */ + for (i = 0; i < MAX_PKCS7_CERTS; i++) { + + verified = 0; + + if (pkcs7->certSz[i] == 0) + continue; + + ret = wc_ecc_init_ex(key, pkcs7->heap, pkcs7->devId); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); +#endif + return ret; + } + + InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap); + /* not verifying, only using this to extract public key */ + ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); + if (ret < 0) { + WOLFSSL_MSG("ASN ECC cert parse error"); + FreeDecodedCert(dCert); + wc_ecc_free(key); + continue; + } + + if (wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, key, + pkcs7->publicKeySz) < 0) { + WOLFSSL_MSG("ASN ECC key decode error"); + FreeDecodedCert(dCert); + wc_ecc_free(key); + continue; + } + + #ifdef WOLFSSL_ASYNC_CRYPT + do { + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key); + } + #ifdef WOLFSSL_ASYNC_CRYPT + } while (ret == WC_PENDING_E); + #endif + + FreeDecodedCert(dCert); + wc_ecc_free(key); + + if (ret == 0 && res == 1) { + /* found signer that successfully verified signature */ + verified = 1; + break; + } + } + + if (verified == 0) { + ret = SIG_VERIFY_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); +#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, + const byte* hashBuf, word32 hashBufSz) +{ + int ret = 0, digIdx = 0; + word32 attribSetSz = 0, hashSz = 0; + 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; + + /* check arguments */ + if (pkcs7 == NULL || pkcs7Digest == NULL || + pkcs7DigestSz == NULL || plainDigest == NULL) { + return BAD_FUNC_ARG; + } + + hashType = wc_OidGetHash(pkcs7->hashOID); + ret = wc_HashGetDigestSize(hashType); + if (ret < 0) + return ret; + hashSz = ret; + + if (signedAttribSz > 0) { + if (signedAttrib == NULL) + return BAD_FUNC_ARG; + } + else { + if (hashBuf && hashBufSz > 0) { + if (hashSz != hashBufSz) + return BAD_FUNC_ARG; + } + else if (pkcs7->content == NULL) + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + digestInfo = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, + 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); + + + /* calculate digest */ + if (hashBuf && hashBufSz > 0 && signedAttribSz == 0) { + XMEMCPY(digest, hashBuf, hashBufSz); + } + else { + ret = wc_HashInit(&hash, hashType); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + if (signedAttribSz > 0) { + attribSetSz = SetSet(signedAttribSz, attribSet); + + /* calculate digest */ + ret = wc_HashUpdate(&hash, hashType, attribSet, attribSetSz); + if (ret == 0) + ret = wc_HashUpdate(&hash, hashType, signedAttrib, signedAttribSz); + if (ret == 0) + ret = wc_HashFinal(&hash, hashType, digest); + } else { + ret = wc_HashUpdate(&hash, hashType, pkcs7->content, pkcs7->contentSz); + if (ret == 0) + ret = wc_HashFinal(&hash, hashType, digest); + } + + wc_HashFree(&hash, hashType); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, pkcs7->heap, 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, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return 0; +} + + +/* Verifies CMS/PKCS7 SignedData content digest matches that which is + * included in the messageDigest signed attribute. Only called when + * signed attributes are present, otherwise original signature verification + * is done over content. + * + * pkcs7 - pointer to initialized PKCS7 struct + * hashBuf - pointer to user-provided hash buffer, used with + * wc_PKCS7_VerifySignedData_ex() + * hashBufSz - size of hashBuf, octets + * + * return 0 on success, negative on error */ +static int wc_PKCS7_VerifyContentMessageDigest(PKCS7* pkcs7, + const byte* hashBuf, + word32 hashSz) +{ + int ret = 0, digestSz = 0, innerAttribSz = 0; + word32 idx = 0; + byte* digestBuf = NULL; +#ifdef WOLFSSL_SMALL_STACK + byte* digest = NULL; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; +#endif + PKCS7DecodedAttrib* attrib; + enum wc_HashType hashType; + + /* messageDigest OID (1.2.840.113549.1.9.4) */ + const byte mdOid[] = + { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04 }; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + if ((pkcs7->content == NULL || pkcs7->contentSz == 0) && + (hashBuf == NULL || hashSz == 0)) { + WOLFSSL_MSG("SignedData bundle has no content or hash to verify"); + return BAD_FUNC_ARG; + } + + /* lookup messageDigest attribute */ + attrib = findAttrib(pkcs7, mdOid, sizeof(mdOid)); + if (attrib == NULL) { + WOLFSSL_MSG("messageDigest attribute not in bundle, must be when " + "signed attribs are present"); + return ASN_PARSE_E; + } + + /* advance past attrib->value ASN.1 header and length */ + if (attrib->value == NULL || attrib->valueSz == 0) + return ASN_PARSE_E; + + if (attrib->value[idx++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(attrib->value, &idx, &innerAttribSz, attrib->valueSz) < 0) + return ASN_PARSE_E; + + /* get hash type and size */ + hashType = wc_OidGetHash(pkcs7->hashOID); + if (hashType == WC_HASH_TYPE_NONE) { + WOLFSSL_MSG("Error getting hash type for PKCS7 content verification"); + return BAD_FUNC_ARG; + } + + /* build content hash if needed, or use existing hash value */ + if (hashBuf == NULL) { + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (digest == NULL) + return MEMORY_E; +#endif + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + ret = wc_Hash(hashType, pkcs7->content, pkcs7->contentSz, digest, + MAX_PKCS7_DIGEST_SZ); + if (ret < 0) { + WOLFSSL_MSG("Error hashing PKCS7 content for verification"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + digestBuf = digest; + digestSz = wc_HashGetDigestSize(hashType); + if (digestSz < 0) { + WOLFSSL_MSG("Invalid hash type"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return digestSz; + } + } else { + + /* user passed in pre-computed hash */ + digestBuf = (byte*)hashBuf; + digestSz = (int)hashSz; + } + + /* compare generated to hash in messageDigest attribute */ + if ((innerAttribSz != digestSz) || + (XMEMCMP(attrib->value + idx, digestBuf, (word32)digestSz) != 0)) { + WOLFSSL_MSG("Content digest does not match messageDigest attrib value"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return SIG_VERIFY_E; + } + + if (hashBuf == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif } return 0; } -/* create ASN.1 fomatted RecipientInfo structure, returns sequence size */ -WOLFSSL_LOCAL int wc_CreateRecipientInfo(const byte* cert, word32 certSz, - int keyEncAlgo, int blockKeySz, - RNG* rng, byte* contentKeyPlain, - byte* contentKeyEnc, - int* keyEncSz, byte* out, word32 outSz) +/* 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, + const byte* hashBuf, word32 hashSz) { + 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; + + /* allocate space to build hash */ + pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ; +#ifdef WOLFSSL_SMALL_STACK + pkcs7Digest = (byte*)XMALLOC(pkcs7DigestSz, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (pkcs7Digest == NULL) + return MEMORY_E; +#endif + + XMEMSET(pkcs7Digest, 0, pkcs7DigestSz); + + /* verify signed attrib digest matches that of content */ + if (signedAttrib != NULL) { + ret = wc_PKCS7_VerifyContentMessageDigest(pkcs7, hashBuf, hashSz); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + } + + /* build hash to verify against */ + ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib, + signedAttribSz, pkcs7Digest, + &pkcs7DigestSz, &plainDigest, + &plainDigestSz, hashBuf, hashSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* If no certificates are available then store the signature and hash for + * user to verify. Make sure that different return value than success is + * returned because the signature was not verified here. */ + if (ret == 0) { + byte haveCert = 0; + int i; + + for (i = 0; i < MAX_PKCS7_CERTS; i++) { + if (pkcs7->certSz[i] == 0) + continue; + haveCert = 1; + } + + if (!haveCert) { + WOLFSSL_MSG("No certificates in bundle to verify signature"); + + /* store signature */ + XFREE(pkcs7->signature, pkcs7->heap, DYNAMIC_TYPE_SIGNATURE); + pkcs7->signature = NULL; + pkcs7->signatureSz = 0; + pkcs7->signature = (byte*)XMALLOC(sigSz, pkcs7->heap, + DYNAMIC_TYPE_SIGNATURE); + if (pkcs7->signature == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + XMEMCPY(pkcs7->signature, sig, sigSz); + pkcs7->signatureSz = sigSz; + + /* store plain digest (CMS and ECC) */ + XFREE(pkcs7->plainDigest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); + pkcs7->plainDigest = NULL; + pkcs7->plainDigestSz = 0; + pkcs7->plainDigest = (byte*)XMALLOC(plainDigestSz, pkcs7->heap, + DYNAMIC_TYPE_DIGEST); + if (pkcs7->plainDigest == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + XMEMCPY(pkcs7->plainDigest, plainDigest, plainDigestSz); + pkcs7->plainDigestSz = plainDigestSz; + + /* store pkcs7 digest (default RSA) */ + XFREE(pkcs7->pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); + pkcs7->pkcs7Digest = NULL; + pkcs7->pkcs7DigestSz = 0; + pkcs7->pkcs7Digest = (byte*)XMALLOC(pkcs7DigestSz, pkcs7->heap, + DYNAMIC_TYPE_DIGEST); + if (pkcs7->pkcs7Digest == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + XMEMCPY(pkcs7->pkcs7Digest, pkcs7Digest, pkcs7DigestSz); + pkcs7->pkcs7DigestSz = pkcs7DigestSz; + + #ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return PKCS7_SIGNEEDS_CHECK; + } + } + + + + 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, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} + + +/* set correct public key OID based on signature OID, stores in + * pkcs7->publicKeyOID and returns same value */ +static int wc_PKCS7_SetPublicKeyOID(PKCS7* pkcs7, int sigOID) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->publicKeyOID = 0; + + switch (sigOID) { + + #ifndef NO_RSA + /* RSA signature types */ + case CTC_MD2wRSA: + case CTC_MD5wRSA: + case CTC_SHAwRSA: + case CTC_SHA224wRSA: + case CTC_SHA256wRSA: + case CTC_SHA384wRSA: + case CTC_SHA512wRSA: + pkcs7->publicKeyOID = RSAk; + break; + + /* if sigOID is already RSAk */ + case RSAk: + pkcs7->publicKeyOID = sigOID; + break; + #endif + + #ifndef NO_DSA + /* DSA signature types */ + case CTC_SHAwDSA: + pkcs7->publicKeyOID = DSAk; + break; + + /* if sigOID is already DSAk */ + case DSAk: + pkcs7->publicKeyOID = sigOID; + break; + #endif + + #ifdef HAVE_ECC + /* ECDSA signature types */ + case CTC_SHAwECDSA: + case CTC_SHA224wECDSA: + case CTC_SHA256wECDSA: + case CTC_SHA384wECDSA: + case CTC_SHA512wECDSA: + pkcs7->publicKeyOID = ECDSAk; + break; + + /* if sigOID is already ECDSAk */ + case ECDSAk: + pkcs7->publicKeyOID = sigOID; + break; + #endif + + default: + WOLFSSL_MSG("Unsupported public key algorithm"); + return ASN_SIG_KEY_E; + } + + return pkcs7->publicKeyOID; +} + + +/* Parses through the attributes and adds them to the PKCS7 structure + * Creates dynamic attribute structures that are free'd with calling + * wc_PKCS7_Free() + * + * NOTE: An attribute has the ASN1 format of + ** Sequence + ****** Object ID + ****** Set + ********** {PritnableString, UTCTime, OCTET STRING ...} + * + * pkcs7 the PKCS7 structure to put the parsed attributes into + * in buffer holding all attributes + * inSz size of in buffer + * + * returns the number of attributes parsed on success + */ +static int wc_PKCS7_ParseAttribs(PKCS7* pkcs7, byte* in, int inSz) +{ + int found = 0; + word32 idx = 0; + word32 oid; + + if (pkcs7 == NULL || in == NULL || inSz < 0) { + return BAD_FUNC_ARG; + } + + while (idx < (word32)inSz) { + int length = 0; + int oidIdx; + PKCS7DecodedAttrib* attrib; + + if (GetSequence(in, &idx, &length, inSz) < 0) + return ASN_PARSE_E; + + attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib), + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (attrib == NULL) { + return MEMORY_E; + } + XMEMSET(attrib, 0, sizeof(PKCS7DecodedAttrib)); + + oidIdx = idx; + if (GetObjectId(in, &idx, &oid, oidIgnoreType, inSz) + < 0) { + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + attrib->oidSz = idx - oidIdx; + attrib->oid = (byte*)XMALLOC(attrib->oidSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (attrib->oid == NULL) { + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + XMEMCPY(attrib->oid, in + oidIdx, attrib->oidSz); + + /* Get Set that contains the printable string value */ + if (GetSet(in, &idx, &length, inSz) < 0) { + XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if ((inSz - idx) < (word32)length) { + 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_PKCS7); + if (attrib->value == NULL) { + XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + XMEMCPY(attrib->value, in + idx, attrib->valueSz); + idx += length; + + /* store attribute in linked list */ + if (pkcs7->decodedAttrib != NULL) { + attrib->next = pkcs7->decodedAttrib; + pkcs7->decodedAttrib = attrib; + } else { + pkcs7->decodedAttrib = attrib; + } + found++; + } + + return found; +} + + +/* option to turn off support for degenerate cases + * flag 0 turns off support + * flag 1 turns on support + * + * by default support for SignedData degenerate cases is on + */ +void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag) +{ + if (pkcs7) { + if (flag) { /* flag of 1 turns on support for degenerate */ + pkcs7->noDegenerate = 0; + } + else { /* flag of 0 turns off support */ + pkcs7->noDegenerate = 1; + } + } +} + +/* Parses through a signerInfo set. Reads buffer "in" from "idxIn" to "idxIn" + + * length treating the current "idxIn" plus the length of set as max possible + * index. + * + * In the case that signed attributes are found "signedAttrib" gets set to point + * at their location in the buffer "in". Also in this case signedAttribSz gets + * set to the size of the signedAttrib buffer. + * + * returns 0 on success + */ +static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, word32 inSz, + word32* idxIn, int degenerate, byte** signedAttrib, int* signedAttribSz) +{ + int ret = 0; + int length; + int version; + word32 sigOID = 0, hashOID = 0; + word32 idx = *idxIn, localIdx; + byte tag; + + WOLFSSL_ENTER("wc_PKCS7_ParseSignerInfo"); + /* require a signer if degenerate case not allowed */ + if (inSz == 0 && pkcs7->noDegenerate == 1) { + WOLFSSL_MSG("Set to not allow degenerate cases"); + return PKCS7_NO_SIGNER_E; + } + + if (inSz == 0 && degenerate == 0) { + WOLFSSL_MSG("PKCS7 signers expected"); + return PKCS7_NO_SIGNER_E; + } + + /* not a degenerate case and there is elements in the set */ + if (inSz > 0 && degenerate == 0) { + ret = wc_PKCS7_SignerInfoNew(pkcs7); + + /* Get the sequence of the first signerInfo */ + if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0) + ret = ASN_PARSE_E; + + /* Get the version */ + if (ret == 0 && GetMyVersion(in, &idx, &version, inSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0) { + pkcs7->signerInfo->version = version; + } + + if (ret == 0 && version == 1) { + /* Get the sequence of IssuerAndSerialNumber */ + if (GetSequence(in, &idx, &length, inSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0) { + ret = wc_PKCS7_SignerInfoSetSID(pkcs7, in + idx, length); + idx += length; + } + + } else if (ret == 0 && version == 3) { + /* Get the sequence of SubjectKeyIdentifier */ + if (idx + 1 > inSz) + ret = BUFFER_E; + + localIdx = idx; + if (ret == 0 && GetASNTag(in, &localIdx, &tag, inSz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + idx++; + + if (GetLength(in, &idx, &length, inSz) <= 0) + ret = ASN_PARSE_E; + + if (ret == 0 && idx + 1 > inSz) + ret = BUFFER_E; + + if (ret == 0 && GetASNTag(in, &idx, &tag, inSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && tag != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0) + ret = ASN_PARSE_E; + } + else { + /* check if SKID with ASN_CONTEXT_SPECIFIC otherwise in version + * 3 try to get issuerAndSerial */ + localIdx = idx; + if (GetASNTag(in, &localIdx, &tag, inSz) == 0 && + tag == ASN_CONTEXT_SPECIFIC) { + idx++; + if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0) + ret = ASN_PARSE_E; + } + else { + if (pkcs7->version != 3) { + WOLFSSL_MSG("Unexpected signer info found with version"); + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0) + ret = ASN_PARSE_E; + } + } + + if (ret == 0) { + ret = wc_PKCS7_SignerInfoSetSID(pkcs7, in + idx, length); + idx += length; + } + + } else { + WOLFSSL_MSG("PKCS#7 signerInfo version must be 1 or 3"); + ret = ASN_VERSION_E; + } + + /* Get the sequence of digestAlgorithm */ + if (ret == 0 && GetAlgoId(in, &idx, &hashOID, oidHashType, inSz) < 0) { + ret = ASN_PARSE_E; + } + pkcs7->hashOID = (int)hashOID; + + /* Get the IMPLICIT[0] SET OF signedAttributes */ + localIdx = idx; + if (ret == 0 && GetASNTag(in, &localIdx, &tag, inSz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + idx++; + + if (GetLength(in, &idx, &length, inSz) < 0) + ret = ASN_PARSE_E; + + /* save pointer and length */ + *signedAttrib = &in[idx]; + *signedAttribSz = length; + + if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, *signedAttrib, + *signedAttribSz) < 0) { + WOLFSSL_MSG("Error parsing signed attributes"); + ret = ASN_PARSE_E; + } + + idx += length; + } + + /* Get digestEncryptionAlgorithm */ + if (ret == 0 && GetAlgoId(in, &idx, &sigOID, oidSigType, inSz) < 0) { + ret = ASN_PARSE_E; + } + + /* store public key type based on digestEncryptionAlgorithm */ + if (ret == 0) { + ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID); + if (ret < 0) { + WOLFSSL_MSG("Failed to set public key OID from signature"); + } + else { + /* if previous return was positive then was success */ + ret = 0; + } + } + } + + /* update index on success */ + if (ret == 0) { + *idxIn = idx; + } + + return ret; +} + + +/* Finds the certificates in the message and saves it. By default allows + * degenerate cases which can have no signer. + * + * By default expects type SIGNED_DATA (SignedData) which can have any number of + * elements in signerInfos collection, including zero. (RFC2315 section 9.1) + * When adding support for the case of SignedAndEnvelopedData content types a + * signer is required. In this case the PKCS7 flag noDegenerate could be set. + */ +static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, + word32 hashSz, byte* in, word32 inSz, + byte* in2, word32 in2Sz) +{ + word32 idx, maxIdx = inSz, outerContentType, contentTypeSz = 0, totalSz = 0; + int length = 0, version = 0, ret = 0; + byte* content = NULL; + byte* contentDynamic = NULL; + byte* sig = NULL; + byte* cert = NULL; + byte* signedAttrib = NULL; + byte* contentType = NULL; + int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0; + word32 localIdx, start; + byte degenerate = 0; + byte detached = 0; + byte tag = 0; +#ifdef ASN_BER_TO_DER + byte* der; +#endif + int multiPart = 0, keepContent; + int contentLen = 0; + + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 stateIdx = 0; + long rc; +#endif + + byte* pkiMsg2 = in2; + word32 pkiMsg2Sz = in2Sz; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + +#ifndef NO_PKCS7_STREAM + /* allow for 0 size inputs with stream mode */ + if (pkiMsg == NULL && pkiMsgSz > 0) + return BAD_FUNC_ARG; + +#else + if (pkiMsg == NULL || pkiMsgSz == 0) + return BAD_FUNC_ARG; +#endif + + if ((hashSz > 0 && hashBuf == NULL) || (pkiMsg2Sz > 0 && pkiMsg2 == NULL)) { + return BAD_FUNC_ARG; + } + idx = 0; + +#ifdef ASN_BER_TO_DER + if (pkcs7->derSz > 0 && pkcs7->der) { + pkiMsg = in = pkcs7->der; + } +#endif + +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } + } +#endif + + switch (pkcs7->state) { + case WC_PKCS7_START: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_LENGTH_SZ + + ASN_TAG_SZ + MAX_OID_SZ + MAX_SEQ_SZ, + &pkiMsg, &idx)) != 0) { + break; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz; + #endif + + /* determine total message size */ + totalSz = pkiMsgSz; + if (pkiMsg2 && pkiMsg2Sz > 0) { + totalSz += pkiMsg2Sz + pkcs7->contentSz; + } + + /* Get the contentInfo sequence */ + if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, totalSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && length == 0 && pkiMsg[idx-1] == 0x80) { + #ifdef ASN_BER_TO_DER + word32 len = 0; + + ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); + if (ret != LENGTH_ONLY_E) + return ret; + pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->der == NULL) + return MEMORY_E; + ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); + if (ret < 0) + return ret; + + pkiMsg = in = pkcs7->der; + pkiMsgSz = pkcs7->derSz = len; + idx = 0; + if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) + return ASN_PARSE_E; + + #ifndef NO_PKCS7_STREAM + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, + pkiMsg, pkiMsgSz); + if (rc < 0) { + ret = (int)rc; + break; + } + #endif + #else + ret = BER_INDEF_E; + #endif + } + + /* Get the contentInfo contentType */ + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &outerContentType, + pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && outerContentType != SIGNED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type SignedData"); + ret = PKCS7_OID_E; + } + + /* get the ContentInfo content */ + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, totalSz) != 0) + ret = ASN_PARSE_E; + + if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength_ex(pkiMsg, &idx, &length, totalSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + /* Get the signedData sequence */ + if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, totalSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + /* Get the version */ + if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + + /* version 1 follows RFC 2315 */ + /* version 3 follows RFC 4108 */ + if (ret == 0 && (version != 1 && version != 3)) { + WOLFSSL_MSG("PKCS#7 signedData needs to be version 1 or 3"); + ret = ASN_VERSION_E; + } + pkcs7->version = version; + + /* Get the set of DigestAlgorithmIdentifiers */ + if (ret == 0 && GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + /* Skip the set. */ + idx += length; + degenerate = (length == 0)? 1 : 0; + if (pkcs7->noDegenerate == 1 && degenerate == 1) { + ret = PKCS7_NO_SIGNER_E; + } + + if (ret != 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + if (pkiMsg2 && pkiMsg2Sz > 0) { + pkcs7->stream->maxLen += pkiMsg2Sz + pkcs7->contentSz; + } + wc_PKCS7_StreamStoreVar(pkcs7, totalSz, 0, 0); + #endif + + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE2); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE2: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, + MAX_SEQ_SZ + MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ + + ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { + break; + } + + wc_PKCS7_StreamGetVar(pkcs7, &totalSz, 0, 0); + if (pkcs7->stream->length > 0) + pkiMsgSz = pkcs7->stream->length; + #ifdef ASN_BER_TO_DER + else if (pkcs7->der) + pkiMsgSz = pkcs7->derSz; + #endif + else + pkiMsgSz = inSz; + + #endif + /* Get the inner ContentInfo sequence */ + if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + /* Get the inner ContentInfo contentType */ + if (ret == 0) { + word32 tmpIdx = idx; + + if (GetASNObjectId(pkiMsg, &idx, &length, pkiMsgSz) != 0) + ret = ASN_PARSE_E; + + contentType = pkiMsg + tmpIdx; + contentTypeSz = length + (idx - tmpIdx); + + idx += length; + } + + if (ret != 0) + break; + + /* Check for content info, it could be omitted when degenerate */ + localIdx = idx; + ret = 0; + if (localIdx + 1 > pkiMsgSz) { + ret = BUFFER_E; + break; + } + + if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) != 0) + ret = ASN_PARSE_E; + + if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz, + NO_USER_CHECK) <= 0) + ret = ASN_PARSE_E; + + if (localIdx >= pkiMsgSz) { + ret = BUFFER_E; + } + + /* get length of content in the case that there is multiple parts */ + if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && tag == (ASN_OCTET_STRING | ASN_CONSTRUCTED)) { + multiPart = 1; + + /* Get length of all OCTET_STRINGs. */ + if (GetLength_ex(pkiMsg, &localIdx, &contentLen, pkiMsgSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + /* Check whether there is one OCTET_STRING inside. */ + start = localIdx; + if (localIdx >= pkiMsgSz) { + ret = BUFFER_E; + } + + if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) + != 0) + ret = ASN_PARSE_E; + + if (ret == 0 && tag != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + if (ret == 0) { + /* Use single OCTET_STRING directly. */ + if (localIdx - start + length == (word32)contentLen) + multiPart = 0; + localIdx = start; + } + } + + /* get length of content in case of single part */ + if (ret == 0 && !multiPart) { + if (tag != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, + &length, pkiMsgSz, NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + } + + /* update idx if successful */ + if (ret == 0) { + /* support using header and footer without content */ + if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) { + localIdx = 0; + } + idx = localIdx; + } + else { + + /* if pkcs7->content and pkcs7->contentSz are set, try to + process as a detached signature */ + if (!degenerate && + (pkcs7->content != NULL && pkcs7->contentSz != 0)) { + detached = 1; + } + + if (!degenerate && !detached && ret != 0) + break; + + length = 0; /* no content to read */ + pkiMsg2 = pkiMsg; + pkiMsg2Sz = pkiMsgSz; + } + + #ifndef NO_PKCS7_STREAM + /* save detached flag value */ + pkcs7->stream->detached = detached; + + /* save contentType */ + pkcs7->stream->nonce = (byte*)XMALLOC(contentTypeSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->nonce == NULL) { + ret = MEMORY_E; + break; + } + else { + pkcs7->stream->nonceSz = contentTypeSz; + XMEMCPY(pkcs7->stream->nonce, contentType, contentTypeSz); + } + + /* content expected? */ + if ((ret == 0 && length > 0) && + !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0)) { + pkcs7->stream->expected = length + ASN_TAG_SZ + MAX_LENGTH_SZ; + } + else { + pkcs7->stream->expected = ASN_TAG_SZ + MAX_LENGTH_SZ; + } + + if (pkcs7->stream->expected > (pkcs7->stream->maxLen - idx)) { + pkcs7->stream->expected = pkcs7->stream->maxLen - idx; + } + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, localIdx, length); + + /* content length is in multiple parts */ + if (multiPart) { + pkcs7->stream->expected = contentLen + ASN_TAG_SZ; + } + pkcs7->stream->multi = multiPart; + + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE3); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE3: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + break; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + pkiMsg, pkiMsgSz); + if (rc < 0) { + ret = (int)rc; + break; + } + #ifdef ASN_BER_TO_DER + if (pkcs7->derSz != 0) + pkiMsgSz = pkcs7->derSz; + else + #endif + pkiMsgSz = (word32)rc; + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, (int*)&localIdx, &length); + + if (pkcs7->stream->length > 0) { + localIdx = 0; + } + multiPart = pkcs7->stream->multi; + detached = pkcs7->stream->detached; + maxIdx = idx + pkcs7->stream->expected; + #endif + + /* Break out before content because it can be optional in degenerate + * cases. */ + if (ret != 0 && !degenerate) + break; + + /* get parts of content */ + if (ret == 0 && multiPart) { + int i = 0; + keepContent = !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0); + + if (keepContent) { + /* Create a buffer to hold content of OCTET_STRINGs. */ + pkcs7->contentDynamic = (byte*)XMALLOC(contentLen, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->contentDynamic == NULL) + ret = MEMORY_E; + } + + start = localIdx; + /* Use the data from each OCTET_STRING. */ + while (ret == 0 && localIdx < start + contentLen) { + if (GetASNTag(pkiMsg, &localIdx, &tag, totalSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && length + localIdx > start + contentLen) + ret = ASN_PARSE_E; + + if (ret == 0) { + if (keepContent) { + XMEMCPY(pkcs7->contentDynamic + i, pkiMsg + localIdx, + length); + } + i += length; + localIdx += length; + } + } + localIdx = start; /* reset for sanity check, increment later */ + length = i; + } + + /* Save the inner data as the content. */ + if (ret == 0 && length > 0) { + contentSz = length; + + /* support using header and footer without content */ + if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) { + /* Content not provided, use provided pkiMsg2 footer */ + content = NULL; + localIdx = 0; + if (contentSz != (int)pkcs7->contentSz) { + WOLFSSL_MSG("Data signed does not match contentSz provided"); + ret = BUFFER_E; + } + } + else { + if ((word32)length > pkiMsgSz - localIdx) { + ret = BUFFER_E; + } + + /* Content pointer for calculating hashes later */ + if (ret == 0 && !multiPart) { + content = &pkiMsg[localIdx]; + } + if (ret == 0 && multiPart) { + content = pkcs7->contentDynamic; + } + + if (ret == 0) { + idx += length; + + pkiMsg2 = pkiMsg; + pkiMsg2Sz = pkiMsgSz; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->varOne = pkiMsg2Sz; + pkcs7->stream->flagOne = 1; + #endif + } + } + } + else { + pkiMsg2 = pkiMsg; + pkiMsg2Sz = pkiMsgSz; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->varOne = pkiMsg2Sz; + pkcs7->stream->flagOne = 1; + #endif + } + + /* If getting the content info failed with non degenerate then return the + * error case. Otherwise with a degenerate it is ok if the content + * info was omitted */ + if (!degenerate && !detached && (ret != 0)) { + break; + } + else { + ret = 0; /* reset ret state on degenerate case */ + } + + #ifndef NO_PKCS7_STREAM + /* save content */ + if (detached == 1) { + /* if detached, use content from user in pkcs7 struct */ + content = pkcs7->content; + contentSz = pkcs7->contentSz; + } + + if (content != NULL) { + XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->content = (byte*)XMALLOC(contentSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->content == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->content, content, contentSz); + pkcs7->stream->contentSz = contentSz; + } + } + #endif /* !NO_PKCS7_STREAM */ + + /* Get the implicit[0] set of certificates */ + if (ret == 0 && idx >= pkiMsg2Sz) + ret = BUFFER_E; + + length = 0; /* set length to 0 to check if reading in any certs */ + localIdx = idx; + if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, pkiMsg2Sz) == 0 + && tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + idx++; + if (GetLength_ex(pkiMsg2, &idx, &length, maxIdx, NO_USER_CHECK) + < 0) + ret = ASN_PARSE_E; + } + + if (ret != 0) { + break; + } + #ifndef NO_PKCS7_STREAM + if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) { + stateIdx = idx; /* case where all data was read from in2 */ + } + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); + if (length > 0) { + pkcs7->stream->expected = length; + } + else { + pkcs7->stream->expected = MAX_SEQ_SZ; + if (pkcs7->stream->expected > (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length) { + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + } + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE4); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE4: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + break; + } + + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); + if (pkcs7->stream->flagOne) { + pkiMsg2 = pkiMsg; + } + + /* restore content */ + content = pkcs7->stream->content; + contentSz = pkcs7->stream->contentSz; + + /* restore detached flag */ + detached = pkcs7->stream->detached; + + /* store certificate if needed */ + if (length > 0 && in2Sz == 0) { + /* free tmpCert if not NULL */ + XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->tmpCert = (byte*)XMALLOC(length, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if ((pkiMsg2 == NULL) || (pkcs7->stream->tmpCert == NULL)) { + ret = MEMORY_E; + break; + } + XMEMCPY(pkcs7->stream->tmpCert, pkiMsg2 + idx, length); + pkiMsg2 = pkcs7->stream->tmpCert; + pkiMsg2Sz = length; + idx = 0; + } + #endif + + if (length > 0) { + /* At this point, idx is at the first certificate in + * a set of certificates. There may be more than one, + * or none, or they may be a PKCS 6 extended + * certificate. We want to save the first cert if it + * is X.509. */ + + word32 certIdx = idx; + + if (length < MAX_LENGTH_SZ + ASN_TAG_SZ) + ret = BUFFER_E; + + if (ret == 0) + ret = GetASNTag(pkiMsg2, &certIdx, &tag, pkiMsg2Sz); + + if (ret == 0 && tag == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { + if (GetLength(pkiMsg2, &certIdx, &certSz, pkiMsg2Sz) < 0) + ret = ASN_PARSE_E; + + cert = &pkiMsg2[idx]; + certSz += (certIdx - idx); + if (certSz > length) { + ret = BUFFER_E; + break; + } + } + #ifdef ASN_BER_TO_DER + der = pkcs7->der; + #endif + contentDynamic = pkcs7->contentDynamic; + version = pkcs7->version; + + + if (ret == 0) { + #ifndef NO_PKCS7_STREAM + PKCS7State* stream = pkcs7->stream; + #endif + /* This will reset PKCS7 structure and then set the + * certificate */ + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + #ifndef NO_PKCS7_STREAM + pkcs7->stream = stream; + #endif + } + pkcs7->contentDynamic = contentDynamic; + pkcs7->version = version; + #ifdef ASN_BER_TO_DER + pkcs7->der = der; + #endif + if (ret != 0) + break; + + /* iterate through any additional certificates */ + if (ret == 0 && MAX_PKCS7_CERTS > 0) { + int sz = 0; + int i; + + pkcs7->cert[0] = cert; + pkcs7->certSz[0] = certSz; + certIdx = idx + certSz; + + for (i = 1; i < MAX_PKCS7_CERTS && + certIdx + 1 < pkiMsg2Sz && + certIdx + 1 < (word32)length; i++) { + localIdx = certIdx; + + if (ret == 0 && GetASNTag(pkiMsg2, &certIdx, &tag, + pkiMsg2Sz) < 0) { + ret = ASN_PARSE_E; + break; + } + + if (ret == 0 && + tag == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { + if (GetLength(pkiMsg2, &certIdx, &sz, + pkiMsg2Sz) < 0) { + ret = ASN_PARSE_E; + break; + } + + pkcs7->cert[i] = &pkiMsg2[localIdx]; + pkcs7->certSz[i] = sz + (certIdx - localIdx); + certIdx += sz; + } + } + } + } + idx += length; + + if (!detached) { + /* set content and size after init of PKCS7 structure */ + pkcs7->content = content; + pkcs7->contentSz = contentSz; + } + #ifndef NO_PKCS7_STREAM + else { + /* save content if detached and using streaming API */ + if (pkcs7->content != NULL) { + XFREE(pkcs7->stream->content, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + pkcs7->stream->content = (byte*)XMALLOC(pkcs7->contentSz, + pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->content == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->content, pkcs7->content, + contentSz); + pkcs7->stream->contentSz = pkcs7->contentSz; + } + } + } + #endif + + if (ret != 0) { + break; + } + #ifndef NO_PKCS7_STREAM + /* factor in that recent idx was in cert buffer. If in2 buffer was + * used then don't advance idx. */ + if (length > 0 && pkcs7->stream->flagOne && + pkcs7->stream->length == 0) { + idx = stateIdx + idx; + if (idx > inSz) { + /* index is more than input size */ + ret = BUFFER_E; + break; + } + } + else { + stateIdx = idx; /* didn't read any from internal buffer */ + } + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + if (pkcs7->stream->flagOne && pkcs7->stream->length > 0) { + idx = stateIdx + idx; + } + + pkcs7->stream->expected = MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ + + MAX_SET_SZ; + + if (pkcs7->stream->expected > (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length) + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, 0); + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE5); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE5: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + break; + } + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); + if (pkcs7->stream->flagOne) { + pkiMsg2 = pkiMsg; + } + + /* restore content type */ + contentType = pkcs7->stream->nonce; + contentTypeSz = pkcs7->stream->nonceSz; + + maxIdx = idx + pkcs7->stream->expected; + if (maxIdx > pkiMsg2Sz) { + ret = BUFFER_E; + break; + } + stateIdx = idx; + #endif + + /* set contentType and size after init of PKCS7 structure */ + if (ret == 0 && wc_PKCS7_SetContentType(pkcs7, contentType, + contentTypeSz) < 0) + ret = ASN_PARSE_E; + + /* Get the implicit[1] set of crls */ + if (ret == 0 && idx >= maxIdx) + ret = BUFFER_E; + + localIdx = idx; + if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, pkiMsg2Sz) == 0 + && tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + idx++; + if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + ret = ASN_PARSE_E; + + /* Skip the set */ + idx += length; + } + + /* Get the set of signerInfos */ + if (ret == 0 && GetSet_ex(pkiMsg2, &idx, &length, maxIdx, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + if (ret != 0) + break; + #ifndef NO_PKCS7_STREAM + if (!pkcs7->stream->flagOne) { + stateIdx = idx; /* didn't read any from internal buffer */ + } + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); + + if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) { + if (length > 0) { + pkcs7->stream->expected = length; + } + else { + pkcs7->stream->expected = 0; + } + } + else { + /* last state expect the reset of the buffer */ + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + } + + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE6); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE6: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + break; + } + + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); + if (pkcs7->stream->flagOne) { + pkiMsg2 = pkiMsg; + } + + /* restore content */ + content = pkcs7->stream->content; + contentSz = pkcs7->stream->contentSz; + #endif + + ret = wc_PKCS7_ParseSignerInfo(pkcs7, pkiMsg2, pkiMsg2Sz, &idx, + degenerate, &signedAttrib, &signedAttribSz); + + /* parse out the signature if present and verify it */ + if (ret == 0 && length > 0 && degenerate == 0) { + WOLFSSL_MSG("Parsing signature and verifying"); + if (idx >= pkiMsg2Sz) + ret = BUFFER_E; + + /* Get the signature */ + localIdx = idx; + if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, + pkiMsg2Sz) == 0 && tag == ASN_OCTET_STRING) { + idx++; + + if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + ret = ASN_PARSE_E; + + /* save pointer and length */ + sig = &pkiMsg2[idx]; + sigSz = length; + + idx += length; + } + + pkcs7->content = content; + pkcs7->contentSz = contentSz; + + if (ret == 0) { + ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, + signedAttrib, signedAttribSz, + hashBuf, hashSz); + } + } + + if (ret < 0) + break; + + ret = 0; /* success */ + #ifndef NO_PKCS7_STREAM + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + break; + + default: + WOLFSSL_MSG("PKCS7 Unknown verify state"); + ret = BAD_FUNC_ARG; + } + + if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + #ifndef NO_PKCS7_STREAM + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + } + return ret; +} + + +/* Gets a copy of the SID parsed from signerInfo. This can be called after + * wc_PKCS7_VerifySignedData has been called. SID can be SKID in version 3 case + * or issuerAndSerialNumber. + * + * return 0 on success and LENGTH_ONLY_E if just setting "outSz" for buffer + * length needed. + */ +int wc_PKCS7_GetSignerSID(PKCS7* pkcs7, byte* out, word32* outSz) +{ + if (outSz == NULL || pkcs7 == NULL) { + return BAD_FUNC_ARG; + } + + if (pkcs7->signerInfo == NULL) { + WOLFSSL_MSG("Either the bundle had no signers or" + "wc_PKCS7_VerifySignedData needs called yet"); + return PKCS7_NO_SIGNER_E; + } + + if (pkcs7->signerInfo->sidSz == 0) { + WOLFSSL_MSG("Bundle had no signer SID set"); + return PKCS7_NO_SIGNER_E; + } + + if (out == NULL) { + *outSz = pkcs7->signerInfo->sidSz; + return LENGTH_ONLY_E; + } + + if (*outSz < pkcs7->signerInfo->sidSz) { + WOLFSSL_MSG("Buffer being passed in is not large enough for SKID"); + return BUFFER_E; + } + XMEMCPY(out, pkcs7->signerInfo->sid, pkcs7->signerInfo->sidSz); + *outSz = pkcs7->signerInfo->sidSz; + return 0; +} + + +/* variant that allows computed data hash and header/foot, + * which is useful for large data signing */ +int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf, + word32 hashSz, byte* pkiMsgHead, word32 pkiMsgHeadSz, byte* pkiMsgFoot, + word32 pkiMsgFootSz) +{ + return PKCS7_VerifySignedData(pkcs7, hashBuf, hashSz, + pkiMsgHead, pkiMsgHeadSz, pkiMsgFoot, pkiMsgFootSz); +} + +int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) +{ + return PKCS7_VerifySignedData(pkcs7, NULL, 0, pkiMsg, pkiMsgSz, NULL, 0); +} + + +/* Generate random content encryption key, store into pkcs7->cek and + * pkcs7->cekSz. + * + * pkcs7 - pointer to initialized PKCS7 structure + * len - length of key to be generated + * + * Returns 0 on success, negative upon error */ +static int PKCS7_GenerateContentEncryptionKey(PKCS7* pkcs7, word32 len) +{ + int ret; + WC_RNG rng; + byte* tmpKey; + + if (pkcs7 == NULL || len == 0) + return BAD_FUNC_ARG; + + /* if key already exists, don't need to re-generate */ + if (pkcs7->cek != NULL && pkcs7->cekSz != 0) { + + /* if key exists, but is different size, return error */ + if (pkcs7->cekSz != len) { + WOLFSSL_MSG("Random content-encryption key size is inconsistent " + "between CMS recipients"); + return WC_KEY_SIZE_E; + } + + return 0; + } + + /* allocate space for cek */ + tmpKey = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (tmpKey == NULL) + return MEMORY_E; + + XMEMSET(tmpKey, 0, len); + + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + XFREE(tmpKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + ret = wc_RNG_GenerateBlock(&rng, tmpKey, len); + if (ret != 0) { + wc_FreeRng(&rng); + XFREE(tmpKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* store into PKCS7, memory freed during final cleanup */ + pkcs7->cek = tmpKey; + pkcs7->cekSz = len; + + wc_FreeRng(&rng); + + return 0; +} + + +/* wrap CEK (content encryption key) with KEK, 0 on success, < 0 on error */ +static int wc_PKCS7_KeyWrap(byte* cek, word32 cekSz, byte* kek, + word32 kekSz, byte* out, word32 outSz, + int keyWrapAlgo, int direction) +{ + int ret = 0; + + if (cek == NULL || kek == NULL || out == NULL) + return BAD_FUNC_ARG; + + switch (keyWrapAlgo) { +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + #endif + + if (direction == AES_ENCRYPTION) { + + ret = wc_AesKeyWrap(kek, kekSz, cek, cekSz, + out, outSz, NULL); + + } else if (direction == AES_DECRYPTION) { + + ret = wc_AesKeyUnWrap(kek, kekSz, cek, cekSz, + out, outSz, NULL); + } else { + WOLFSSL_MSG("Bad key un/wrap direction"); + return BAD_FUNC_ARG; + } + + if (ret <= 0) + return ret; + break; +#endif /* NO_AES */ + + default: + WOLFSSL_MSG("Unsupported key wrap algorithm"); + return BAD_KEYWRAP_ALG_E; + }; + + (void)cekSz; + (void)kekSz; + (void)outSz; + (void)direction; + return ret; +} + + +#ifdef HAVE_ECC + +/* KARI == KeyAgreeRecipientInfo (key agreement) */ +typedef struct WC_PKCS7_KARI { + DecodedCert* decoded; /* decoded recip cert */ + void* heap; /* user heap, points to PKCS7->heap */ + int devId; /* device ID for HW based private key */ + ecc_key* recipKey; /* recip key (pub | priv) */ + ecc_key* senderKey; /* sender key (pub | priv) */ + byte* senderKeyExport; /* sender ephemeral key DER */ + byte* kek; /* key encryption key */ + byte* ukm; /* OPTIONAL user keying material */ + byte* sharedInfo; /* ECC-CMS-SharedInfo ASN.1 encoded blob */ + word32 senderKeyExportSz; /* size of sender ephemeral key DER */ + word32 kekSz; /* size of key encryption key */ + word32 ukmSz; /* size of user keying material */ + word32 sharedInfoSz; /* size of ECC-CMS-SharedInfo encoded */ + byte ukmOwner; /* do we own ukm buffer? 1:yes, 0:no */ + byte direction; /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */ + byte decodedInit : 1; /* indicates decoded was initialized */ + byte recipKeyInit : 1; /* indicates recipKey was initialized */ + byte senderKeyInit : 1; /* indicates senderKey was initialized */ +} WC_PKCS7_KARI; + + +/* allocate and create new WC_PKCS7_KARI struct, + * returns struct pointer on success, NULL on failure */ +static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) +{ + WC_PKCS7_KARI* kari = NULL; + + if (pkcs7 == NULL) + return NULL; + + kari = (WC_PKCS7_KARI*)XMALLOC(sizeof(WC_PKCS7_KARI), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (kari == NULL) { + WOLFSSL_MSG("Failed to allocate WC_PKCS7_KARI"); + return NULL; + } + + kari->decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (kari->decoded == NULL) { + WOLFSSL_MSG("Failed to allocate DecodedCert"); + XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return NULL; + } + + kari->recipKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (kari->recipKey == NULL) { + WOLFSSL_MSG("Failed to allocate recipient ecc_key"); + XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return NULL; + } + + kari->senderKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (kari->senderKey == NULL) { + WOLFSSL_MSG("Failed to allocate sender ecc_key"); + XFREE(kari->recipKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return NULL; + } + + kari->senderKeyExport = NULL; + kari->senderKeyExportSz = 0; + kari->kek = NULL; + kari->kekSz = 0; + kari->ukm = NULL; + kari->ukmSz = 0; + kari->ukmOwner = 0; + kari->sharedInfo = NULL; + kari->sharedInfoSz = 0; + kari->direction = direction; + kari->decodedInit = 0; + kari->recipKeyInit = 0; + kari->senderKeyInit = 0; + + kari->heap = pkcs7->heap; + kari->devId = pkcs7->devId; + + return kari; +} + + +/* free WC_PKCS7_KARI struct, return 0 on success */ +static int wc_PKCS7_KariFree(WC_PKCS7_KARI* kari) +{ + void* heap; + + if (kari) { + heap = kari->heap; + + if (kari->decoded) { + if (kari->decodedInit) + FreeDecodedCert(kari->decoded); + XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7); + } + if (kari->senderKey) { + if (kari->senderKeyInit) + wc_ecc_free(kari->senderKey); + XFREE(kari->senderKey, heap, DYNAMIC_TYPE_PKCS7); + } + if (kari->recipKey) { + if (kari->recipKeyInit) + wc_ecc_free(kari->recipKey); + XFREE(kari->recipKey, heap, DYNAMIC_TYPE_PKCS7); + } + if (kari->senderKeyExport) { + ForceZero(kari->senderKeyExport, kari->senderKeyExportSz); + XFREE(kari->senderKeyExport, heap, DYNAMIC_TYPE_PKCS7); + kari->senderKeyExportSz = 0; + } + if (kari->kek) { + ForceZero(kari->kek, kari->kekSz); + XFREE(kari->kek, heap, DYNAMIC_TYPE_PKCS7); + kari->kekSz = 0; + } + if (kari->ukm) { + if (kari->ukmOwner == 1) { + XFREE(kari->ukm, heap, DYNAMIC_TYPE_PKCS7); + } + kari->ukmSz = 0; + } + if (kari->sharedInfo) { + ForceZero(kari->sharedInfo, kari->sharedInfoSz); + XFREE(kari->sharedInfo, heap, DYNAMIC_TYPE_PKCS7); + kari->sharedInfoSz = 0; + } + XFREE(kari, heap, DYNAMIC_TYPE_PKCS7); + } + + (void)heap; + + return 0; +} + + +/* parse recipient cert/key, return 0 on success, negative on error + * key/keySz only needed during decoding (WC_PKCS7_DECODE) */ +static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, + word32 certSz, const byte* key, + word32 keySz) +{ + int ret; + word32 idx; + + if (kari == NULL || kari->decoded == NULL || + cert == NULL || certSz == 0) + return BAD_FUNC_ARG; + + /* decode certificate */ + InitDecodedCert(kari->decoded, (byte*)cert, certSz, kari->heap); + kari->decodedInit = 1; + ret = ParseCert(kari->decoded, CA_TYPE, NO_VERIFY, 0); + if (ret < 0) + return ret; + + /* only supports ECDSA for now */ + if (kari->decoded->keyOID != ECDSAk) { + WOLFSSL_MSG("CMS KARI only supports ECDSA key types"); + return BAD_FUNC_ARG; + } + + /* make sure subject key id was read from cert */ + if (kari->decoded->extSubjKeyIdSet == 0) { + WOLFSSL_MSG("Failed to read subject key ID from recipient cert"); + return BAD_FUNC_ARG; + } + + ret = wc_ecc_init_ex(kari->recipKey, kari->heap, kari->devId); + if (ret != 0) + return ret; + + kari->recipKeyInit = 1; + + /* get recip public key */ + if (kari->direction == WC_PKCS7_ENCODE) { + + idx = 0; + ret = wc_EccPublicKeyDecode(kari->decoded->publicKey, &idx, + kari->recipKey, kari->decoded->pubKeySize); + if (ret != 0) + return ret; + } + /* get recip private key */ + else if (kari->direction == WC_PKCS7_DECODE) { + if (key != NULL && keySz > 0) { + idx = 0; + ret = wc_EccPrivateKeyDecode(key, &idx, kari->recipKey, keySz); + } + else if (kari->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } + if (ret != 0) + return ret; + + } else { + /* bad direction */ + return BAD_FUNC_ARG; + } + + (void)idx; + + return 0; +} + + +/* create ephemeral ECC key, places ecc_key in kari->senderKey, + * DER encoded in kari->senderKeyExport. return 0 on success, + * negative on error */ +static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari) +{ + int ret; + WC_RNG rng; + + if (kari == NULL || kari->decoded == NULL || + kari->recipKey == NULL || kari->recipKey->dp == NULL) + return BAD_FUNC_ARG; + + kari->senderKeyExport = (byte*)XMALLOC(kari->decoded->pubKeySize, + kari->heap, DYNAMIC_TYPE_PKCS7); + if (kari->senderKeyExport == NULL) + return MEMORY_E; + + kari->senderKeyExportSz = kari->decoded->pubKeySize; + + ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId); + if (ret != 0) { + XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + kari->senderKeyInit = 1; + + ret = wc_InitRng_ex(&rng, kari->heap, kari->devId); + if (ret != 0) { + XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + ret = wc_ecc_make_key_ex(&rng, kari->recipKey->dp->size, + kari->senderKey, kari->recipKey->dp->id); + if (ret != 0) { + XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + return ret; + } + + wc_FreeRng(&rng); + + /* dump generated key to X.963 DER for output in CMS bundle */ + ret = wc_ecc_export_x963(kari->senderKey, kari->senderKeyExport, + &kari->senderKeyExportSz); + if (ret != 0) { + XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + return 0; +} + + +/* create ASN.1 encoded ECC-CMS-SharedInfo using specified key wrap algorithm, + * place in kari->sharedInfo. returns 0 on success, negative on error */ +static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) +{ + int idx = 0; + int sharedInfoSeqSz = 0; + int keyInfoSz = 0; + int suppPubInfoSeqSz = 0; + int entityUInfoOctetSz = 0; + int entityUInfoExplicitSz = 0; + int kekOctetSz = 0; + int sharedInfoSz = 0; + + word32 kekBitSz = 0; + + byte sharedInfoSeq[MAX_SEQ_SZ]; + 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) + return BAD_FUNC_ARG; + + if ((kari->ukmSz > 0) && (kari->ukm == NULL)) + return BAD_FUNC_ARG; + + /* kekOctet */ + kekOctetSz = SetOctetString(sizeof(word32), kekOctet); + sharedInfoSz += (kekOctetSz + sizeof(word32)); + + /* suppPubInfo */ + suppPubInfoSeqSz = SetImplicit(ASN_SEQUENCE, 2, + kekOctetSz + sizeof(word32), + suppPubInfoSeq); + sharedInfoSz += suppPubInfoSeqSz; + + /* optional ukm/entityInfo */ + if (kari->ukmSz > 0) { + entityUInfoOctetSz = SetOctetString(kari->ukmSz, entityUInfoOctet); + sharedInfoSz += (entityUInfoOctetSz + kari->ukmSz); + + entityUInfoExplicitSz = SetExplicit(0, entityUInfoOctetSz + + kari->ukmSz, + entityUInfoExplicitSeq); + sharedInfoSz += entityUInfoExplicitSz; + } + + /* keyInfo */ + keyInfoSz = SetAlgoID(keyWrapOID, keyInfo, oidKeyWrapType, 0); + sharedInfoSz += keyInfoSz; + + /* sharedInfo */ + sharedInfoSeqSz = SetSequence(sharedInfoSz, sharedInfoSeq); + sharedInfoSz += sharedInfoSeqSz; + + kari->sharedInfo = (byte*)XMALLOC(sharedInfoSz, kari->heap, + DYNAMIC_TYPE_PKCS7); + if (kari->sharedInfo == NULL) + return MEMORY_E; + + kari->sharedInfoSz = sharedInfoSz; + + XMEMCPY(kari->sharedInfo + idx, sharedInfoSeq, sharedInfoSeqSz); + idx += sharedInfoSeqSz; + 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); + idx += kari->ukmSz; + } + XMEMCPY(kari->sharedInfo + idx, suppPubInfoSeq, suppPubInfoSeqSz); + idx += suppPubInfoSeqSz; + XMEMCPY(kari->sharedInfo + idx, kekOctet, kekOctetSz); + idx += kekOctetSz; + + kekBitSz = (kari->kekSz) * 8; /* convert to bits */ +#ifdef LITTLE_ENDIAN_ORDER + kekBitSz = ByteReverseWord32(kekBitSz); /* network byte order */ +#endif + XMEMCPY(kari->sharedInfo + idx, &kekBitSz, sizeof(kekBitSz)); + + return 0; +} + + +/* create key encryption key (KEK) using key wrap algorithm and key encryption + * algorithm, place in kari->kek. return 0 on success, <0 on error. */ +static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, + int keyWrapOID, int keyEncOID) +{ + int ret; + int kSz; + enum wc_HashType kdfType; + byte* secret; + word32 secretSz; + + if (kari == NULL || kari->recipKey == NULL || + kari->senderKey == NULL || kari->senderKey->dp == NULL) + return BAD_FUNC_ARG; + + /* get KEK size, allocate buff */ + kSz = wc_PKCS7_GetOIDKeySize(keyWrapOID); + if (kSz < 0) + return kSz; + + kari->kek = (byte*)XMALLOC(kSz, kari->heap, DYNAMIC_TYPE_PKCS7); + if (kari->kek == NULL) + return MEMORY_E; + + kari->kekSz = (word32)kSz; + + /* generate ECC-CMS-SharedInfo */ + ret = wc_PKCS7_KariGenerateSharedInfo(kari, keyWrapOID); + if (ret != 0) + return ret; + + /* generate shared secret */ + secretSz = kari->senderKey->dp->size; + secret = (byte*)XMALLOC(secretSz, kari->heap, DYNAMIC_TYPE_PKCS7); + if (secret == NULL) + return MEMORY_E; + + if (kari->direction == WC_PKCS7_ENCODE) { + + ret = wc_ecc_shared_secret(kari->senderKey, kari->recipKey, + secret, &secretSz); + + } else if (kari->direction == WC_PKCS7_DECODE) { + + ret = wc_ecc_shared_secret(kari->recipKey, kari->senderKey, + secret, &secretSz); + + } else { + /* bad direction */ + XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + + if (ret != 0) { + XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* run through KDF */ + switch (keyEncOID) { + + #ifndef NO_SHA + case dhSinglePass_stdDH_sha1kdf_scheme: + kdfType = WC_HASH_TYPE_SHA; + break; + #endif + #ifndef WOLFSSL_SHA224 + case dhSinglePass_stdDH_sha224kdf_scheme: + kdfType = WC_HASH_TYPE_SHA224; + break; + #endif + #ifndef NO_SHA256 + case dhSinglePass_stdDH_sha256kdf_scheme: + kdfType = WC_HASH_TYPE_SHA256; + break; + #endif + #ifdef WOLFSSL_SHA384 + case dhSinglePass_stdDH_sha384kdf_scheme: + kdfType = WC_HASH_TYPE_SHA384; + break; + #endif + #ifdef WOLFSSL_SHA512 + case dhSinglePass_stdDH_sha512kdf_scheme: + kdfType = WC_HASH_TYPE_SHA512; + break; + #endif + default: + WOLFSSL_MSG("Unsupported key agreement algorithm"); + XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + }; + + ret = wc_X963_KDF(kdfType, secret, secretSz, kari->sharedInfo, + kari->sharedInfoSz, kari->kek, kari->kekSz); + if (ret != 0) { + XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); + + return 0; +} + + +/* Encode and add CMS EnvelopedData KARI (KeyAgreeRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, + int keyWrapOID, int keyAgreeOID, byte* ukm, + word32 ukmSz, int options) +{ + Pkcs7EncodedRecip* recip; + Pkcs7EncodedRecip* lastRecip = NULL; + WC_PKCS7_KARI* kari = NULL; + word32 idx = 0; - int ret = 0, totalSz = 0; - int verSz, issuerSz, snSz, keyEncAlgSz; - int issuerSeqSz, recipSeqSz, issuerSerialSeqSz; + word32 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + + int ret = 0; + int keySz, direction = 0; + int blockKeySz = 0; + + /* ASN.1 layout */ + int totalSz = 0; + int kariSeqSz = 0; + byte kariSeq[MAX_SEQ_SZ]; /* IMPLICIT [1] */ + int verSz = 0; + byte ver[MAX_VERSION_SZ]; + + int origIdOrKeySeqSz = 0; + byte origIdOrKeySeq[MAX_SEQ_SZ]; /* IMPLICIT [0] */ + int origPubKeySeqSz = 0; + byte origPubKeySeq[MAX_SEQ_SZ]; /* IMPLICIT [1] */ + int origAlgIdSz = 0; + byte origAlgId[MAX_ALGO_SZ]; + int origPubKeyStrSz = 0; + byte origPubKeyStr[MAX_OCTET_STR_SZ]; + + /* optional user keying material */ + int ukmOctetSz = 0; + byte ukmOctetStr[MAX_OCTET_STR_SZ]; + int ukmExplicitSz = 0; + byte ukmExplicitSeq[MAX_SEQ_SZ]; + + int keyEncryptAlgoIdSz = 0; + byte keyEncryptAlgoId[MAX_ALGO_SZ]; + int keyWrapAlgSz = 0; + byte keyWrapAlg[MAX_ALGO_SZ]; + + int recipEncKeysSeqSz = 0; + byte recipEncKeysSeq[MAX_SEQ_SZ]; + int recipEncKeySeqSz = 0; + byte recipEncKeySeq[MAX_SEQ_SZ]; + int recipKeyIdSeqSz = 0; + byte recipKeyIdSeq[MAX_SEQ_SZ]; /* IMPLICIT [0] */ + int subjKeyIdOctetSz = 0; + byte subjKeyIdOctet[MAX_OCTET_STR_SZ]; + int encryptedKeyOctetSz = 0; + byte encryptedKeyOctet[MAX_OCTET_STR_SZ]; + +#ifdef WOLFSSL_SMALL_STACK + byte* encryptedKey; + + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedKey == NULL) { + return MEMORY_E; + } +#else + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; +#endif + + /* allocate and init memory for recipient */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (recip == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + + /* get key size for content-encryption key based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockKeySz; + } + + /* generate random content encryption key, if needed */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* set direction based on keyWrapAlgo */ + switch (keyWrapOID) { +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + #endif + direction = AES_ENCRYPTION; + break; +#endif + default: + WOLFSSL_MSG("Unsupported key wrap algorithm"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BAD_KEYWRAP_ALG_E; + } + + kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_ENCODE); + if (kari == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* set user keying material if available */ + if (ukmSz > 0 && ukm != NULL) { + kari->ukm = ukm; + kari->ukmSz = ukmSz; + kari->ukmOwner = 0; + } + + /* parse recipient cert, get public key */ + ret = wc_PKCS7_KariParseRecipCert(kari, cert, certSz, NULL, 0); + if (ret != 0) { + wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* generate sender ephemeral ECC key */ + ret = wc_PKCS7_KariGenerateEphemeralKey(kari); + if (ret != 0) { + wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* generate KEK (key encryption key) */ + ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, keyAgreeOID); + if (ret != 0) { + wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* encrypt CEK with KEK */ + keySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kari->kek, + kari->kekSz, encryptedKey, encryptedKeySz, + keyWrapOID, direction); + if (keySz <= 0) { + wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return keySz; + } + encryptedKeySz = (word32)keySz; + + /* Start of RecipientEncryptedKeys */ + + /* EncryptedKey */ + encryptedKeyOctetSz = SetOctetString(encryptedKeySz, encryptedKeyOctet); + totalSz += (encryptedKeyOctetSz + encryptedKeySz); + + /* SubjectKeyIdentifier */ + subjKeyIdOctetSz = SetOctetString(KEYID_SIZE, subjKeyIdOctet); + totalSz += (subjKeyIdOctetSz + KEYID_SIZE); + + /* RecipientKeyIdentifier IMPLICIT [0] */ + recipKeyIdSeqSz = SetImplicit(ASN_SEQUENCE, 0, subjKeyIdOctetSz + + KEYID_SIZE, recipKeyIdSeq); + totalSz += recipKeyIdSeqSz; + + /* RecipientEncryptedKey */ + recipEncKeySeqSz = SetSequence(totalSz, recipEncKeySeq); + totalSz += recipEncKeySeqSz; + + /* RecipientEncryptedKeys */ + recipEncKeysSeqSz = SetSequence(totalSz, recipEncKeysSeq); + totalSz += recipEncKeysSeqSz; + + /* Start of optional UserKeyingMaterial */ + + if (kari->ukmSz > 0) { + ukmOctetSz = SetOctetString(kari->ukmSz, ukmOctetStr); + totalSz += (ukmOctetSz + kari->ukmSz); + + ukmExplicitSz = SetExplicit(1, ukmOctetSz + kari->ukmSz, + ukmExplicitSeq); + totalSz += ukmExplicitSz; + } + + /* Start of KeyEncryptionAlgorithmIdentifier */ + + /* KeyWrapAlgorithm */ + keyWrapAlgSz = SetAlgoID(keyWrapOID, keyWrapAlg, oidKeyWrapType, 0); + totalSz += keyWrapAlgSz; + + /* KeyEncryptionAlgorithmIdentifier */ + keyEncryptAlgoIdSz = SetAlgoID(keyAgreeOID, keyEncryptAlgoId, + oidCmsKeyAgreeType, keyWrapAlgSz); + totalSz += keyEncryptAlgoIdSz; + + /* Start of OriginatorIdentifierOrKey */ + + /* recipient ECPoint, public key */ + XMEMSET(origPubKeyStr, 0, sizeof(origPubKeyStr)); /* no unused bits */ + origPubKeyStr[0] = ASN_BIT_STRING; + origPubKeyStrSz = SetLength(kari->senderKeyExportSz + 1, + origPubKeyStr + 1) + 2; + totalSz += (origPubKeyStrSz + kari->senderKeyExportSz); + + /* Originator AlgorithmIdentifier, params set to NULL for interop + compatibility */ + origAlgIdSz = SetAlgoID(ECDSAk, origAlgId, oidKeyType, 2); + origAlgId[origAlgIdSz++] = ASN_TAG_NULL; + origAlgId[origAlgIdSz++] = 0; + totalSz += origAlgIdSz; + + /* outer OriginatorPublicKey IMPLICIT [1] */ + origPubKeySeqSz = SetImplicit(ASN_SEQUENCE, 1, + origAlgIdSz + origPubKeyStrSz + + kari->senderKeyExportSz, origPubKeySeq); + totalSz += origPubKeySeqSz; + + /* outer OriginatorIdentiferOrKey IMPLICIT [0] */ + origIdOrKeySeqSz = SetImplicit(ASN_SEQUENCE, 0, + origPubKeySeqSz + origAlgIdSz + + origPubKeyStrSz + kari->senderKeyExportSz, + origIdOrKeySeq); + totalSz += origIdOrKeySeqSz; + + /* version, always 3 */ + verSz = SetMyVersion(3, ver, 0); + totalSz += verSz; + recip->recipVersion = 3; + + /* outer IMPLICIT [1] kari */ + kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq); + totalSz += kariSeqSz; + + if (totalSz > MAX_RECIP_SZ) { + WOLFSSL_MSG("KeyAgreeRecipientInfo output buffer too small"); + wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + XMEMCPY(recip->recip + idx, kariSeq, kariSeqSz); + idx += kariSeqSz; + XMEMCPY(recip->recip + idx, ver, verSz); + idx += verSz; + + XMEMCPY(recip->recip + idx, origIdOrKeySeq, origIdOrKeySeqSz); + idx += origIdOrKeySeqSz; + XMEMCPY(recip->recip + idx, origPubKeySeq, origPubKeySeqSz); + idx += origPubKeySeqSz; + + /* AlgorithmIdentifier with NULL parameter */ + XMEMCPY(recip->recip + idx, origAlgId, origAlgIdSz); + idx += origAlgIdSz; + + XMEMCPY(recip->recip + idx, origPubKeyStr, origPubKeyStrSz); + idx += origPubKeyStrSz; + /* ephemeral public key */ + XMEMCPY(recip->recip + idx, kari->senderKeyExport, kari->senderKeyExportSz); + idx += kari->senderKeyExportSz; + + if (kari->ukmSz > 0) { + XMEMCPY(recip->recip + idx, ukmExplicitSeq, ukmExplicitSz); + idx += ukmExplicitSz; + XMEMCPY(recip->recip + idx, ukmOctetStr, ukmOctetSz); + idx += ukmOctetSz; + XMEMCPY(recip->recip + idx, kari->ukm, kari->ukmSz); + idx += kari->ukmSz; + } + + XMEMCPY(recip->recip + idx, keyEncryptAlgoId, keyEncryptAlgoIdSz); + idx += keyEncryptAlgoIdSz; + XMEMCPY(recip->recip + idx, keyWrapAlg, keyWrapAlgSz); + idx += keyWrapAlgSz; + + XMEMCPY(recip->recip + idx, recipEncKeysSeq, recipEncKeysSeqSz); + idx += recipEncKeysSeqSz; + XMEMCPY(recip->recip + idx, recipEncKeySeq, recipEncKeySeqSz); + idx += recipEncKeySeqSz; + XMEMCPY(recip->recip + idx, recipKeyIdSeq, recipKeyIdSeqSz); + idx += recipKeyIdSeqSz; + XMEMCPY(recip->recip + idx, subjKeyIdOctet, subjKeyIdOctetSz); + idx += subjKeyIdOctetSz; + /* subject key id */ + XMEMCPY(recip->recip + idx, kari->decoded->extSubjKeyId, KEYID_SIZE); + idx += KEYID_SIZE; + XMEMCPY(recip->recip + idx, encryptedKeyOctet, encryptedKeyOctetSz); + idx += encryptedKeyOctetSz; + /* encrypted CEK */ + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; + + wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + /* store recipient size */ + recip->recipSz = idx; + recip->recipType = PKCS7_KARI; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + (void)options; + + return idx; +} + +#endif /* HAVE_ECC */ + +#ifndef NO_RSA + +/* Encode and add CMS EnvelopedData KTRI (KeyTransRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, + int options) +{ + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + WC_RNG rng; + word32 idx = 0; + word32 encryptedKeySz = 0; + + int ret = 0, blockKeySz; + int verSz = 0, issuerSz = 0, snSz = 0, keyEncAlgSz = 0; + int issuerSeqSz = 0, recipSeqSz = 0, issuerSerialSeqSz = 0; int encKeyOctetStrSz; + int sidType; byte ver[MAX_VERSION_SZ]; byte issuerSerialSeq[MAX_SEQ_SZ]; @@ -961,213 +6020,4406 @@ WOLFSSL_LOCAL int wc_CreateRecipientInfo(const byte* cert, word32 certSz, byte issuerSeq[MAX_SEQ_SZ]; byte encKeyOctetStr[MAX_OCTET_STR_SZ]; + byte issuerSKIDSeq[MAX_SEQ_SZ]; + byte issuerSKID[MAX_OCTET_STR_SZ]; + word32 issuerSKIDSeqSz = 0, issuerSKIDSz = 0; + #ifdef WOLFSSL_SMALL_STACK - byte *serial; - byte *keyAlgArray; - + byte* serial; + byte* keyAlgArray; + byte* encryptedKey; RsaKey* pubKey; DecodedCert* decoded; - serial = (byte*)XMALLOC(MAX_SN_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); + serial = (byte*)XMALLOC(MAX_SN_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); - if (decoded == NULL || serial == NULL || keyAlgArray == NULL) { - if (serial) XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (keyAlgArray) XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (decoded) XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (decoded == NULL || serial == NULL || + encryptedKey == NULL || keyAlgArray == NULL) { + if (serial) + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (keyAlgArray) + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedKey) + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (decoded) + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } - #else byte serial[MAX_SN_SZ]; byte keyAlgArray[MAX_ALGO_SZ]; - - RsaKey stack_pubKey; - RsaKey* pubKey = &stack_pubKey; - DecodedCert stack_decoded; - DecodedCert* decoded = &stack_decoded; + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; + + RsaKey pubKey[1]; + DecodedCert decoded[1]; #endif - InitDecodedCert(decoded, (byte*)cert, certSz, 0); + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + XMEMSET(encryptedKey, 0, encryptedKeySz); + + /* default to IssuerAndSerialNumber if not set */ + if (pkcs7->sidType != 0) { + sidType = pkcs7->sidType; + } else { + sidType = CMS_ISSUER_AND_SERIAL_NUMBER; + } + + /* allow options to override SubjectIdentifier type if set */ + if (options & CMS_SKID) { + sidType = CMS_SKID; + } else if (options & CMS_ISSUER_AND_SERIAL_NUMBER) { + sidType = CMS_ISSUER_AND_SERIAL_NUMBER; + } + + /* allocate recipient struct */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (recip == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + + /* get key size for content-encryption key based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockKeySz; + } + + /* generate random content encryption key, if needed */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + InitDecodedCert(decoded, (byte*)cert, certSz, pkcs7->heap); ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } - /* version */ - verSz = SetMyVersion(0, ver, 0); + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { - /* IssuerAndSerialNumber */ - if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) { - WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length"); + /* version, must be 0 for IssuerAndSerialNumber */ + verSz = SetMyVersion(0, ver, 0); + recip->recipVersion = 0; + + /* IssuerAndSerialNumber */ + if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) { + WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length"); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return -1; + } + issuerSz = decoded->issuerRawLen; + issuerSeqSz = SetSequence(issuerSz, issuerSeq); + + if (decoded->serialSz == 0) { + WOLFSSL_MSG("DecodedCert missing serial number"); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return -1; + } + snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial, + MAX_SN_SZ, MAX_SN_SZ); + + issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz, + issuerSerialSeq); + + } else if (sidType == CMS_SKID) { + + /* version, must be 2 for SubjectKeyIdentifier */ + verSz = SetMyVersion(2, ver, 0); + recip->recipVersion = 2; + + issuerSKIDSz = SetOctetString(KEYID_SIZE, issuerSKID); + issuerSKIDSeqSz = SetExplicit(0, issuerSKIDSz + KEYID_SIZE, + issuerSKIDSeq); + } else { FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return -1; + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return PKCS7_RECIP_E; } - issuerSz = decoded->issuerRawLen; - issuerSeqSz = SetSequence(issuerSz, issuerSeq); - if (decoded->serialSz == 0) { - WOLFSSL_MSG("DecodedCert missing serial number"); - FreeDecodedCert(decoded); -#ifdef WOLFSSL_SMALL_STACK - XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return -1; - } - snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial); - - issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz, - issuerSerialSeq); + pkcs7->publicKeyOID = decoded->keyOID; /* KeyEncryptionAlgorithmIdentifier, only support RSA now */ - if (keyEncAlgo != RSAk) { + if (pkcs7->publicKeyOID != RSAk) { FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ALGO_ID_E; } - keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, keyType, 0); + keyEncAlgSz = SetAlgoID(pkcs7->publicKeyOID, keyAlgArray, oidKeyType, 0); if (keyEncAlgSz == 0) { FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return BAD_FUNC_ARG; } #ifdef WOLFSSL_SMALL_STACK - pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); + pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); if (pubKey == NULL) { FreeDecodedCert(decoded); - XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return MEMORY_E; } #endif /* EncryptedKey */ - ret = wc_InitRsaKey(pubKey, 0); + ret = wc_InitRsaKey_ex(pubKey, pkcs7->heap, INVALID_DEVID); if (ret != 0) { FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } if (wc_RsaPublicKeyDecode(decoded->publicKey, &idx, pubKey, - decoded->pubKeySize) < 0) { + decoded->pubKeySize) < 0) { WOLFSSL_MSG("ASN RSA key decode error"); wc_FreeRsaKey(pubKey); FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return PUBLIC_KEY_E; } - *keyEncSz = wc_RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc, - MAX_ENCRYPTED_KEY_SZ, pubKey, rng); + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + wc_FreeRsaKey(pubKey); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + + ret = wc_RsaPublicEncrypt(pkcs7->cek, pkcs7->cekSz, encryptedKey, + encryptedKeySz, pubKey, &rng); wc_FreeRsaKey(pubKey); + wc_FreeRng(&rng); #ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - if (*keyEncSz < 0) { + if (ret < 0) { WOLFSSL_MSG("RSA Public Encrypt failed"); FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return *keyEncSz; + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; } + encryptedKeySz = ret; - encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr); + encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); /* RecipientInfo */ - recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz + - issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz + - *keyEncSz, recipSeq); + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz + + issuerSz + snSz + keyEncAlgSz + + encKeyOctetStrSz + encryptedKeySz, recipSeq); - if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz + - keyEncAlgSz + encKeyOctetStrSz + *keyEncSz > (int)outSz) { - WOLFSSL_MSG("RecipientInfo output buffer too small"); - FreeDecodedCert(decoded); + if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz + + keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) { + WOLFSSL_MSG("RecipientInfo output buffer too small"); + FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return BUFFER_E; + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + } else { + recipSeqSz = SetSequence(verSz + issuerSKIDSeqSz + issuerSKIDSz + + KEYID_SIZE + keyEncAlgSz + encKeyOctetStrSz + + encryptedKeySz, recipSeq); + + if (recipSeqSz + verSz + issuerSKIDSeqSz + issuerSKIDSz + KEYID_SIZE + + keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) { + WOLFSSL_MSG("RecipientInfo output buffer too small"); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } } - XMEMCPY(out + totalSz, recipSeq, recipSeqSz); - totalSz += recipSeqSz; - XMEMCPY(out + totalSz, ver, verSz); - totalSz += verSz; - XMEMCPY(out + totalSz, issuerSerialSeq, issuerSerialSeqSz); - totalSz += issuerSerialSeqSz; - XMEMCPY(out + totalSz, issuerSeq, issuerSeqSz); - totalSz += issuerSeqSz; - XMEMCPY(out + totalSz, decoded->issuerRaw, issuerSz); - totalSz += issuerSz; - XMEMCPY(out + totalSz, serial, snSz); - totalSz += snSz; - XMEMCPY(out + totalSz, keyAlgArray, keyEncAlgSz); - totalSz += keyEncAlgSz; - XMEMCPY(out + totalSz, encKeyOctetStr, encKeyOctetStrSz); - totalSz += encKeyOctetStrSz; - XMEMCPY(out + totalSz, contentKeyEnc, *keyEncSz); - totalSz += *keyEncSz; + idx = 0; + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + XMEMCPY(recip->recip + idx, ver, verSz); + idx += verSz; + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + XMEMCPY(recip->recip + idx, issuerSerialSeq, issuerSerialSeqSz); + idx += issuerSerialSeqSz; + XMEMCPY(recip->recip + idx, issuerSeq, issuerSeqSz); + idx += issuerSeqSz; + XMEMCPY(recip->recip + idx, decoded->issuerRaw, issuerSz); + idx += issuerSz; + XMEMCPY(recip->recip + idx, serial, snSz); + idx += snSz; + } else { + XMEMCPY(recip->recip + idx, issuerSKIDSeq, issuerSKIDSeqSz); + idx += issuerSKIDSeqSz; + XMEMCPY(recip->recip + idx, issuerSKID, issuerSKIDSz); + idx += issuerSKIDSz; + XMEMCPY(recip->recip + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE); + idx += KEYID_SIZE; + } + XMEMCPY(recip->recip + idx, keyAlgArray, keyEncAlgSz); + idx += keyEncAlgSz; + XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); + idx += encKeyOctetStrSz; + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return totalSz; + /* store recipient size */ + recip->recipSz = idx; + recip->recipType = PKCS7_KTRI; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + return idx; +} + +#endif /* !NO_RSA */ + + +/* encrypt content using encryptOID algo */ +static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, + byte* iv, int ivSz, byte* aad, word32 aadSz, + byte* authTag, word32 authTagSz, byte* in, + int inSz, byte* out) +{ + int ret; +#ifndef NO_AES + Aes aes; +#endif +#ifndef NO_DES3 + Des des; + Des3 des3; +#endif + + if (key == NULL || iv == NULL || in == NULL || out == NULL) + return BAD_FUNC_ARG; + + switch (encryptOID) { +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + #endif + if ( + #ifdef WOLFSSL_AES_128 + (encryptOID == AES128CBCb && keySz != 16 ) || + #endif + #ifdef WOLFSSL_AES_192 + (encryptOID == AES192CBCb && keySz != 24 ) || + #endif + #ifdef WOLFSSL_AES_256 + (encryptOID == AES256CBCb && keySz != 32 ) || + #endif + (ivSz != AES_BLOCK_SIZE) ) + return BAD_FUNC_ARG; + + 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); + } + break; + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + if (authTag == NULL) + return BAD_FUNC_ARG; + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesGcmEncrypt(&aes, out, in, inSz, iv, ivSz, + authTag, authTagSz, aad, aadSz); + wc_AesFree(&aes); + } + break; + #endif + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + if (authTag == NULL) + return BAD_FUNC_ARG; + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesCcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesCcmEncrypt(&aes, out, in, inSz, iv, ivSz, + authTag, authTagSz, aad, aadSz); + wc_AesFree(&aes); + } + break; + #endif + #endif /* HAVE_AESCCM */ +#endif /* NO_AES */ +#ifndef NO_DES3 + case DESb: + if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + ret = wc_Des_SetKey(&des, key, iv, DES_ENCRYPTION); + if (ret == 0) + ret = wc_Des_CbcEncrypt(&des, out, in, inSz); + + break; + + case DES3b: + if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + 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, inSz); + wc_Des3Free(&des3); + } + break; +#endif + default: + WOLFSSL_MSG("Unsupported content cipher type"); + return ALGO_ID_E; + }; + +#if defined(NO_AES) || (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM)) + (void)authTag; + (void)authTagSz; + (void)aad; + (void)aadSz; +#endif + return ret; +} + + +/* decrypt content using encryptOID algo + * returns 0 on success */ +static int wc_PKCS7_DecryptContent(PKCS7* pkcs7, int encryptOID, byte* key, + int keySz, byte* iv, int ivSz, byte* aad, word32 aadSz, byte* authTag, + word32 authTagSz, byte* in, int inSz, byte* out) +{ + int ret; +#ifndef NO_AES + Aes aes; +#endif +#ifndef NO_DES3 + Des des; + Des3 des3; +#endif + + if (iv == NULL || in == NULL || out == NULL) + return BAD_FUNC_ARG; + + if (pkcs7->decryptionCb != NULL) { + return pkcs7->decryptionCb(pkcs7, encryptOID, iv, ivSz, + aad, aadSz, authTag, authTagSz, in, + inSz, out, pkcs7->decryptionCtx); + } + + if (key == NULL) + return BAD_FUNC_ARG; + + switch (encryptOID) { +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + #endif + if ( + #ifdef WOLFSSL_AES_128 + (encryptOID == AES128CBCb && keySz != 16 ) || + #endif + #ifdef WOLFSSL_AES_192 + (encryptOID == AES192CBCb && keySz != 24 ) || + #endif + #ifdef WOLFSSL_AES_256 + (encryptOID == AES256CBCb && keySz != 32 ) || + #endif + (ivSz != AES_BLOCK_SIZE) ) + return BAD_FUNC_ARG; + 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); + } + break; + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + if (authTag == NULL) + return BAD_FUNC_ARG; + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesGcmDecrypt(&aes, out, in, inSz, iv, ivSz, + authTag, authTagSz, aad, aadSz); + wc_AesFree(&aes); + } + break; + #endif + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + if (authTag == NULL) + return BAD_FUNC_ARG; + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesCcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesCcmDecrypt(&aes, out, in, inSz, iv, ivSz, + authTag, authTagSz, aad, aadSz); + wc_AesFree(&aes); + } + break; + #endif + #endif /* HAVE_AESCCM */ +#endif /* NO_AES */ +#ifndef NO_DES3 + case DESb: + if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + ret = wc_Des_SetKey(&des, key, iv, DES_DECRYPTION); + if (ret == 0) + ret = wc_Des_CbcDecrypt(&des, out, in, inSz); + + break; + case DES3b: + if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + 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, inSz); + wc_Des3Free(&des3); + } + + break; +#endif + default: + WOLFSSL_MSG("Unsupported content cipher type"); + return ALGO_ID_E; + }; + +#if defined(NO_AES) || (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM)) + (void)authTag; + (void)authTagSz; + (void)aad; + (void)aadSz; +#endif + + return ret; +} + + +/* Generate random block, place in out, return 0 on success negative on error. + * Used for generation of IV, nonce, etc */ +static int wc_PKCS7_GenerateBlock(PKCS7* pkcs7, WC_RNG* rng, byte* out, + word32 outSz) +{ + int ret; + WC_RNG* rnd = NULL; + + if (out == NULL || outSz == 0) + return BAD_FUNC_ARG; + + /* input RNG is optional, init local one if input rng is NULL */ + if (rng == NULL) { + rnd = (WC_RNG*)XMALLOC(sizeof(WC_RNG), pkcs7->heap, DYNAMIC_TYPE_RNG); + if (rnd == NULL) + return MEMORY_E; + + ret = wc_InitRng_ex(rnd, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG); + return ret; + } + + } else { + rnd = rng; + } + + ret = wc_RNG_GenerateBlock(rnd, out, outSz); + + if (rng == NULL) { + wc_FreeRng(rnd); + XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG); + } + + return ret; +} + + +/* Set default SignerIdentifier type to be used. Is either + * IssuerAndSerialNumber or SubjectKeyIdentifier. Encoding defaults to using + * IssuerAndSerialNumber unless set with this function or explicitly + * overridden via options when adding RecipientInfo type. + * + * Using the type DEGENERATE_SID skips over signer information. In degenerate + * cases there are no signers. + * + * pkcs7 - pointer to initialized PKCS7 structure + * type - either CMS_ISSUER_AND_SERIAL_NUMBER, CMS_SKID or DEGENERATE_SID + * + * return 0 on success, negative upon error */ +int wc_PKCS7_SetSignerIdentifierType(PKCS7* pkcs7, int type) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + if (type != CMS_ISSUER_AND_SERIAL_NUMBER && + type != CMS_SKID && + type != DEGENERATE_SID) { + return BAD_FUNC_ARG; + } + + pkcs7->sidType = type; + + return 0; +} + + +/* Set custom contentType, currently supported with SignedData type + * + * pkcs7 - pointer to initialized PKCS7 structure + * contentType - pointer to array with ASN.1 encoded OID value + * sz - length of contentType array, octets + * + * return 0 on success, negative upon error */ +int wc_PKCS7_SetContentType(PKCS7* pkcs7, byte* contentType, word32 sz) +{ + if (pkcs7 == NULL || contentType == NULL || sz == 0) + return BAD_FUNC_ARG; + + if (sz > MAX_OID_SZ) { + WOLFSSL_MSG("input array too large, bounded by MAX_OID_SZ"); + return BAD_FUNC_ARG; + } + + XMEMCPY(pkcs7->contentType, contentType, sz); + pkcs7->contentTypeSz = sz; + + return 0; +} + + +/* return size of padded data, padded to blockSz chunks, or negative on error */ +int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz) +{ + int padSz; + + if (blockSz == 0) + return BAD_FUNC_ARG; + + padSz = blockSz - (inputSz % blockSz); + + return padSz; +} + + +/* pad input data to blockSz chunk, place in outSz. out must be big enough + * for input + pad bytes. See wc_PKCS7_GetPadSize() helper. */ +int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, + word32 blockSz) +{ + int i, padSz; + + if (in == NULL || inSz == 0 || + out == NULL || outSz == 0) + return BAD_FUNC_ARG; + + padSz = wc_PKCS7_GetPadSize(inSz, blockSz); + + if (outSz < (inSz + padSz)) + return BAD_FUNC_ARG; + + XMEMCPY(out, in, inSz); + + for (i = 0; i < padSz; i++) { + out[inSz + i] = (byte)padSz; + } + + return inSz + padSz; +} + + +/* Encode and add CMS EnvelopedData ORI (OtherRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Return 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb, + int options) +{ + int oriTypeLenSz, blockKeySz, ret; + word32 idx, recipSeqSz; + + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + byte recipSeq[MAX_SEQ_SZ]; + byte oriTypeLen[MAX_LENGTH_SZ]; + + byte oriType[MAX_ORI_TYPE_SZ]; + byte oriValue[MAX_ORI_VALUE_SZ]; + word32 oriTypeSz = MAX_ORI_TYPE_SZ; + word32 oriValueSz = MAX_ORI_VALUE_SZ; + + if (pkcs7 == NULL || oriEncryptCb == NULL) { + return BAD_FUNC_ARG; + } + + /* allocate memory for RecipientInfo, KEK, encrypted key */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (recip == NULL) + return MEMORY_E; + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + + /* get key size for content-encryption key based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockKeySz; + } + + /* generate random content encryption key, if needed */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* call user callback to encrypt CEK and get oriType and oriValue + values back */ + ret = oriEncryptCb(pkcs7, pkcs7->cek, pkcs7->cekSz, oriType, &oriTypeSz, + oriValue, &oriValueSz, pkcs7->oriEncryptCtx); + if (ret != 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + oriTypeLenSz = SetLength(oriTypeSz, oriTypeLen); + + recipSeqSz = SetImplicit(ASN_SEQUENCE, 4, 1 + oriTypeLenSz + oriTypeSz + + oriValueSz, recipSeq); + + idx = 0; + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + /* oriType */ + recip->recip[idx] = ASN_OBJECT_ID; + idx += 1; + XMEMCPY(recip->recip + idx, oriTypeLen, oriTypeLenSz); + idx += oriTypeLenSz; + XMEMCPY(recip->recip + idx, oriType, oriTypeSz); + idx += oriTypeSz; + /* oriValue, input MUST already be ASN.1 encoded */ + XMEMCPY(recip->recip + idx, oriValue, oriValueSz); + idx += oriValueSz; + + /* store recipient size */ + recip->recipSz = idx; + recip->recipType = PKCS7_ORI; + recip->recipVersion = 4; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + (void)options; + + return idx; +} + +#if !defined(NO_PWDBASED) && !defined(NO_SHA) + + +static int wc_PKCS7_GenerateKEK_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, + byte* salt, word32 saltSz, int kdfOID, + int prfOID, int iterations, byte* out, + word32 outSz) +{ + int ret; + + if (pkcs7 == NULL || passwd == NULL || salt == NULL || out == NULL) + return BAD_FUNC_ARG; + + switch (kdfOID) { + + case PBKDF2_OID: + + ret = wc_PBKDF2(out, passwd, pLen, salt, saltSz, iterations, + outSz, prfOID); + if (ret != 0) { + return ret; + } + + break; + + default: + WOLFSSL_MSG("Unsupported KDF OID"); + return PKCS7_OID_E; + } + + return 0; +} + + +/* RFC3211 (Section 2.3.1) key wrap algorithm (id-alg-PWRI-KEK). + * + * Returns output size on success, negative upon error */ +static int wc_PKCS7_PwriKek_KeyWrap(PKCS7* pkcs7, const byte* kek, word32 kekSz, + const byte* cek, word32 cekSz, + byte* out, word32 *outSz, + const byte* iv, word32 ivSz, int algID) +{ + WC_RNG rng; + int blockSz, outLen, ret; + word32 padSz; + byte* lastBlock; + + if (kek == NULL || cek == NULL || iv == NULL || outSz == NULL) + return BAD_FUNC_ARG; + + /* get encryption algorithm block size */ + blockSz = wc_PKCS7_GetOIDBlockSize(algID); + if (blockSz < 0) + return blockSz; + + /* get pad bytes needed to block boundary */ + padSz = blockSz - ((4 + cekSz) % blockSz); + outLen = 4 + cekSz + padSz; + + /* must be at least two blocks long */ + if (outLen < 2 * blockSz) + padSz += blockSz; + + /* if user set out to NULL, give back required length */ + if (out == NULL) { + *outSz = outLen; + return LENGTH_ONLY_E; + } + + /* verify output buffer is large enough */ + if (*outSz < (word32)outLen) + return BUFFER_E; + + out[0] = cekSz; + out[1] = ~cek[0]; + out[2] = ~cek[1]; + out[3] = ~cek[2]; + XMEMCPY(out + 4, cek, cekSz); + + /* random padding of size padSz */ + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) + return ret; + + ret = wc_RNG_GenerateBlock(&rng, out + 4 + cekSz, padSz); + + if (ret == 0) { + /* encrypt, normal */ + ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, (byte*)iv, + ivSz, NULL, 0, NULL, 0, out, outLen, out); + } + + if (ret == 0) { + /* encrypt again, using last ciphertext block as IV */ + lastBlock = out + (((outLen / blockSz) - 1) * blockSz); + ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, lastBlock, + blockSz, NULL, 0, NULL, 0, out, + outLen, out); + } + + if (ret == 0) { + *outSz = outLen; + } else { + outLen = ret; + } + + wc_FreeRng(&rng); + + return outLen; +} + + +/* RFC3211 (Section 2.3.2) key unwrap algorithm (id-alg-PWRI-KEK). + * + * Returns cek size on success, negative upon error */ +static int wc_PKCS7_PwriKek_KeyUnWrap(PKCS7* pkcs7, const byte* kek, + word32 kekSz, const byte* in, word32 inSz, + byte* out, word32 outSz, const byte* iv, + word32 ivSz, int algID) +{ + int blockSz, cekLen, ret; + byte* tmpIv = NULL; + byte* lastBlock = NULL; + byte* outTmp = NULL; + + if (pkcs7 == NULL || kek == NULL || in == NULL || + out == NULL || iv == NULL) { + return BAD_FUNC_ARG; + } + + outTmp = (byte*)XMALLOC(inSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (outTmp == NULL) + return MEMORY_E; + + /* get encryption algorithm block size */ + blockSz = wc_PKCS7_GetOIDBlockSize(algID); + if (blockSz < 0) { + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return blockSz; + } + + /* input needs to be blockSz multiple and at least 2 * blockSz */ + if (((inSz % blockSz) != 0) || (inSz < (2 * (word32)blockSz))) { + WOLFSSL_MSG("PWRI-KEK unwrap input must of block size and >= 2 " + "times block size"); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } + + /* use block out[n-1] as IV to decrypt block out[n] */ + lastBlock = (byte*)in + inSz - blockSz; + tmpIv = lastBlock - blockSz; + + /* decrypt last block */ + ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, tmpIv, + blockSz, NULL, 0, NULL, 0, lastBlock, blockSz, + outTmp + inSz - blockSz); + + if (ret == 0) { + /* using last decrypted block as IV, decrypt [0 ... n-1] blocks */ + lastBlock = outTmp + inSz - blockSz; + ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, + lastBlock, blockSz, NULL, 0, NULL, 0, (byte*)in, inSz - blockSz, + outTmp); + } + + if (ret == 0) { + /* decrypt using original kek and iv */ + ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, + (byte*)iv, ivSz, NULL, 0, NULL, 0, outTmp, inSz, outTmp); + } + + if (ret != 0) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + cekLen = outTmp[0]; + + /* verify length */ + if ((word32)cekLen > inSz) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } + + /* verify check bytes */ + if ((outTmp[1] ^ outTmp[4]) != 0xFF || + (outTmp[2] ^ outTmp[5]) != 0xFF || + (outTmp[3] ^ outTmp[6]) != 0xFF) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } + + if (outSz < (word32)cekLen) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BUFFER_E; + } + + XMEMCPY(out, outTmp + 4, outTmp[0]); + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return cekLen; +} + + +/* Encode and add CMS EnvelopedData PWRI (PasswordRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Return 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, + byte* salt, word32 saltSz, int kdfOID, + int hashOID, int iterations, int kekEncryptOID, + int options) +{ + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + /* PasswordRecipientInfo */ + byte recipSeq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + word32 recipSeqSz, verSz; + + /* KeyDerivationAlgorithmIdentifier */ + byte kdfAlgoIdSeq[MAX_SEQ_SZ]; + byte kdfAlgoId[MAX_OID_SZ]; + byte kdfParamsSeq[MAX_SEQ_SZ]; /* PBKDF2-params */ + byte kdfSaltOctetStr[MAX_OCTET_STR_SZ]; /* salt OCTET STRING */ + byte kdfIterations[MAX_VERSION_SZ]; + word32 kdfAlgoIdSeqSz, kdfAlgoIdSz; + word32 kdfParamsSeqSz, kdfSaltOctetStrSz, kdfIterationsSz; + /* OPTIONAL: keyLength, not supported yet */ + /* OPTIONAL: prf AlgorithIdentifier, not supported yet */ + + /* KeyEncryptionAlgorithmIdentifier */ + byte keyEncAlgoIdSeq[MAX_SEQ_SZ]; + byte keyEncAlgoId[MAX_OID_SZ]; /* id-alg-PWRI-KEK */ + byte pwriEncAlgoId[MAX_ALGO_SZ]; + byte ivOctetString[MAX_OCTET_STR_SZ]; + word32 keyEncAlgoIdSeqSz, keyEncAlgoIdSz; + word32 pwriEncAlgoIdSz, ivOctetStringSz; + + /* EncryptedKey */ + byte encKeyOctetStr[MAX_OCTET_STR_SZ]; + word32 encKeyOctetStrSz; + + byte tmpIv[MAX_CONTENT_IV_SIZE]; + byte* encryptedKey = NULL; + byte* kek = NULL; + + int cekKeySz = 0, kekKeySz = 0, kekBlockSz = 0, ret = 0; + int encryptOID; + word32 idx, totalSz = 0, encryptedKeySz; + + if (pkcs7 == NULL || passwd == NULL || pLen == 0 || + salt == NULL || saltSz == 0) { + return BAD_FUNC_ARG; + } + + /* allow user to use different KEK encryption algorithm than used for + * main content encryption algorithm, if passed in */ + if (kekEncryptOID != 0) { + encryptOID = kekEncryptOID; + } else { + encryptOID = pkcs7->encryptOID; + } + + /* get content-encryption key size, based on algorithm */ + cekKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (cekKeySz < 0) + return cekKeySz; + + /* get KEK encryption key size, based on algorithm */ + if (encryptOID != pkcs7->encryptOID) { + kekKeySz = wc_PKCS7_GetOIDKeySize(encryptOID); + } else { + kekKeySz = cekKeySz; + } + + /* get KEK encryption block size */ + kekBlockSz = wc_PKCS7_GetOIDBlockSize(encryptOID); + if (kekBlockSz < 0) + return kekBlockSz; + + /* generate random CEK */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, cekKeySz); + if (ret < 0) + return ret; + + /* generate random IV */ + ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, kekBlockSz); + if (ret != 0) + return ret; + + /* allocate memory for RecipientInfo, KEK, encrypted key */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (recip == NULL) + return MEMORY_E; + + kek = (byte*)XMALLOC(kekKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (kek == NULL) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (encryptedKey == NULL) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + XMEMSET(kek, 0, kekKeySz); + XMEMSET(encryptedKey, 0, encryptedKeySz); + + /* generate KEK: expand password into KEK */ + ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, passwd, pLen, salt, saltSz, + kdfOID, hashOID, iterations, kek, + kekKeySz); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* generate encrypted key: encrypt CEK with KEK */ + ret = wc_PKCS7_PwriKek_KeyWrap(pkcs7, kek, kekKeySz, pkcs7->cek, + pkcs7->cekSz, encryptedKey, &encryptedKeySz, + tmpIv, kekBlockSz, encryptOID); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + encryptedKeySz = ret; + + /* put together encrypted key OCTET STRING */ + encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); + totalSz += (encKeyOctetStrSz + encryptedKeySz); + + /* put together IV OCTET STRING */ + ivOctetStringSz = SetOctetString(kekBlockSz, ivOctetString); + totalSz += (ivOctetStringSz + kekBlockSz); + + /* set PWRIAlgorithms AlgorithmIdentifier, adding (ivOctetStringSz + + blockKeySz) for IV OCTET STRING */ + pwriEncAlgoIdSz = SetAlgoID(encryptOID, pwriEncAlgoId, + oidBlkType, ivOctetStringSz + kekBlockSz); + totalSz += pwriEncAlgoIdSz; + + /* set KeyEncryptionAlgorithms OID */ + ret = wc_SetContentType(PWRI_KEK_WRAP, keyEncAlgoId, sizeof(keyEncAlgoId)); + if (ret <= 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + keyEncAlgoIdSz = ret; + totalSz += keyEncAlgoIdSz; + + /* KeyEncryptionAlgorithm SEQ */ + keyEncAlgoIdSeqSz = SetSequence(keyEncAlgoIdSz + pwriEncAlgoIdSz + + ivOctetStringSz + kekBlockSz, + keyEncAlgoIdSeq); + totalSz += keyEncAlgoIdSeqSz; + + /* set KDF salt */ + kdfSaltOctetStrSz = SetOctetString(saltSz, kdfSaltOctetStr); + totalSz += (kdfSaltOctetStrSz + saltSz); + + /* set KDF iteration count */ + kdfIterationsSz = SetMyVersion(iterations, kdfIterations, 0); + totalSz += kdfIterationsSz; + + /* set KDF params SEQ */ + kdfParamsSeqSz = SetSequence(kdfSaltOctetStrSz + saltSz + kdfIterationsSz, + kdfParamsSeq); + totalSz += kdfParamsSeqSz; + + /* set KDF algo OID */ + ret = wc_SetContentType(kdfOID, kdfAlgoId, sizeof(kdfAlgoId)); + if (ret <= 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + kdfAlgoIdSz = ret; + totalSz += kdfAlgoIdSz; + + /* set KeyDerivationAlgorithmIdentifier EXPLICIT [0] SEQ */ + kdfAlgoIdSeqSz = SetExplicit(0, kdfAlgoIdSz + kdfParamsSeqSz + + kdfSaltOctetStrSz + saltSz + kdfIterationsSz, + kdfAlgoIdSeq); + totalSz += kdfAlgoIdSeqSz; + + /* set PasswordRecipientInfo CMSVersion, MUST be 0 */ + verSz = SetMyVersion(0, ver, 0); + totalSz += verSz; + recip->recipVersion = 0; + + /* set PasswordRecipientInfo SEQ */ + recipSeqSz = SetImplicit(ASN_SEQUENCE, 3, totalSz, recipSeq); + totalSz += recipSeqSz; + + if (totalSz > MAX_RECIP_SZ) { + WOLFSSL_MSG("CMS Recipient output buffer too small"); + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + idx = 0; + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + XMEMCPY(recip->recip + idx, ver, verSz); + idx += verSz; + XMEMCPY(recip->recip + idx, kdfAlgoIdSeq, kdfAlgoIdSeqSz); + idx += kdfAlgoIdSeqSz; + XMEMCPY(recip->recip + idx, kdfAlgoId, kdfAlgoIdSz); + idx += kdfAlgoIdSz; + XMEMCPY(recip->recip + idx, kdfParamsSeq, kdfParamsSeqSz); + idx += kdfParamsSeqSz; + XMEMCPY(recip->recip + idx, kdfSaltOctetStr, kdfSaltOctetStrSz); + idx += kdfSaltOctetStrSz; + XMEMCPY(recip->recip + idx, salt, saltSz); + idx += saltSz; + XMEMCPY(recip->recip + idx, kdfIterations, kdfIterationsSz); + idx += kdfIterationsSz; + XMEMCPY(recip->recip + idx, keyEncAlgoIdSeq, keyEncAlgoIdSeqSz); + idx += keyEncAlgoIdSeqSz; + XMEMCPY(recip->recip + idx, keyEncAlgoId, keyEncAlgoIdSz); + idx += keyEncAlgoIdSz; + XMEMCPY(recip->recip + idx, pwriEncAlgoId, pwriEncAlgoIdSz); + idx += pwriEncAlgoIdSz; + XMEMCPY(recip->recip + idx, ivOctetString, ivOctetStringSz); + idx += ivOctetStringSz; + XMEMCPY(recip->recip + idx, tmpIv, kekBlockSz); + idx += kekBlockSz; + XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); + idx += encKeyOctetStrSz; + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; + + ForceZero(kek, kekBlockSz); + ForceZero(encryptedKey, encryptedKeySz); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + /* store recipient size */ + recip->recipSz = idx; + recip->recipType = PKCS7_PWRI; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + (void)options; + + return idx; +} + +/* Import password and KDF settings into a PKCS7 structure. Used for setting + * the password info for decryption a EnvelopedData PWRI RecipientInfo. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen) +{ + if (pkcs7 == NULL || passwd == NULL || pLen == 0) + return BAD_FUNC_ARG; + + pkcs7->pass = passwd; + pkcs7->passSz = pLen; + + return 0; +} + +#endif /* NO_PWDBASED */ + + +/* Encode and add CMS EnvelopedData KEKRI (KEKRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * pkcs7 - pointer to initialized PKCS7 structure + * keyWrapOID - OID sum of key wrap algorithm identifier + * kek - key encryption key + * kekSz - size of kek, bytes + * keyID - key-encryption key identifier, pre-distributed to endpoints + * keyIDSz - size of keyID, bytes + * timePtr - pointer to "time_t", which is typically "long" (OPTIONAL) + * otherOID - ASN.1 encoded OID of other attribute (OPTIONAL) + * otherOIDSz - size of otherOID, bytes (OPTIONAL) + * other - other attribute (OPTIONAL) + * otherSz - size of other (OPTIONAL) + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, + word32 kekSz, byte* keyId, word32 keyIdSz, + void* timePtr, byte* otherOID, + word32 otherOIDSz, byte* other, word32 otherSz, + int options) +{ + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + byte recipSeq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + byte kekIdSeq[MAX_SEQ_SZ]; + byte kekIdOctetStr[MAX_OCTET_STR_SZ]; + byte genTime[ASN_GENERALIZED_TIME_SIZE]; + byte otherAttSeq[MAX_SEQ_SZ]; + byte encAlgoId[MAX_ALGO_SZ]; + byte encKeyOctetStr[MAX_OCTET_STR_SZ]; +#ifdef WOLFSSL_SMALL_STACK + byte* encryptedKey; +#else + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; +#endif + + int blockKeySz = 0, ret = 0, direction; + word32 idx = 0; + word32 totalSz = 0; + word32 recipSeqSz = 0, verSz = 0; + word32 kekIdSeqSz = 0, kekIdOctetStrSz = 0; + word32 otherAttSeqSz = 0, encAlgoIdSz = 0, encKeyOctetStrSz = 0; + int encryptedKeySz; + + int timeSz = 0; +#ifndef NO_ASN_TIME + time_t* tm = NULL; +#endif + + if (pkcs7 == NULL || kek == NULL || keyId == NULL) + return BAD_FUNC_ARG; + + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (recip == NULL) + return MEMORY_E; + + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + + /* get key size for content-encryption key based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockKeySz; + } + + /* generate random content encryption key, if needed */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* EncryptedKey */ +#ifdef WOLFSSL_SMALL_STACK + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedKey == NULL) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } +#endif + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + XMEMSET(encryptedKey, 0, encryptedKeySz); + + #ifndef NO_AES + direction = AES_ENCRYPTION; + #else + direction = DES_ENCRYPTION; + #endif + + encryptedKeySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kek, kekSz, + encryptedKey, encryptedKeySz, keyWrapOID, + direction); + if (encryptedKeySz < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return encryptedKeySz; + } + /* handle a zero size encKey case as WC_KEY_SIZE_E */ + if (encryptedKeySz == 0 || encryptedKeySz > MAX_ENCRYPTED_KEY_SZ) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return WC_KEY_SIZE_E; + } + + encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); + totalSz += (encKeyOctetStrSz + encryptedKeySz); + + /* KeyEncryptionAlgorithmIdentifier */ + encAlgoIdSz = SetAlgoID(keyWrapOID, encAlgoId, oidKeyWrapType, 0); + totalSz += encAlgoIdSz; + + /* KEKIdentifier: keyIdentifier */ + kekIdOctetStrSz = SetOctetString(keyIdSz, kekIdOctetStr); + totalSz += (kekIdOctetStrSz + keyIdSz); + + /* KEKIdentifier: GeneralizedTime (OPTIONAL) */ +#ifndef NO_ASN_TIME + if (timePtr != NULL) { + tm = (time_t*)timePtr; + timeSz = GetAsnTimeString(tm, genTime, sizeof(genTime)); + if (timeSz < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return timeSz; + } + totalSz += timeSz; + } +#endif + + /* KEKIdentifier: OtherKeyAttribute SEQ (OPTIONAL) */ + if (other != NULL && otherSz > 0) { + otherAttSeqSz = SetSequence(otherOIDSz + otherSz, otherAttSeq); + totalSz += otherAttSeqSz + otherOIDSz + otherSz; + } + + /* KEKIdentifier SEQ */ + kekIdSeqSz = SetSequence(kekIdOctetStrSz + keyIdSz + timeSz + + otherAttSeqSz + otherOIDSz + otherSz, kekIdSeq); + totalSz += kekIdSeqSz; + + /* version */ + verSz = SetMyVersion(4, ver, 0); + totalSz += verSz; + recip->recipVersion = 4; + + /* KEKRecipientInfo SEQ */ + recipSeqSz = SetImplicit(ASN_SEQUENCE, 2, totalSz, recipSeq); + totalSz += recipSeqSz; + + if (totalSz > MAX_RECIP_SZ) { + WOLFSSL_MSG("CMS Recipient output buffer too small"); + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return BUFFER_E; + } + + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + XMEMCPY(recip->recip + idx, ver, verSz); + idx += verSz; + XMEMCPY(recip->recip + idx, kekIdSeq, kekIdSeqSz); + idx += kekIdSeqSz; + XMEMCPY(recip->recip + idx, kekIdOctetStr, kekIdOctetStrSz); + idx += kekIdOctetStrSz; + XMEMCPY(recip->recip + idx, keyId, keyIdSz); + idx += keyIdSz; + if (timePtr != NULL) { + XMEMCPY(recip->recip + idx, genTime, timeSz); + idx += timeSz; + } + if (other != NULL && otherSz > 0) { + XMEMCPY(recip->recip + idx, otherAttSeq, otherAttSeqSz); + idx += otherAttSeqSz; + XMEMCPY(recip->recip + idx, otherOID, otherOIDSz); + idx += otherOIDSz; + XMEMCPY(recip->recip + idx, other, otherSz); + idx += otherSz; + } + XMEMCPY(recip->recip + idx, encAlgoId, encAlgoIdSz); + idx += encAlgoIdSz; + XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); + idx += encKeyOctetStrSz; + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + + /* store recipient size */ + recip->recipSz = idx; + recip->recipType = PKCS7_KEKRI; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while(lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + (void)options; + + return idx; +} + + +static int wc_PKCS7_GetCMSVersion(PKCS7* pkcs7, int cmsContentType) +{ + int version = -1; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + switch (cmsContentType) { + case ENVELOPED_DATA: + + /* NOTE: EnvelopedData does not currently support + originatorInfo or unprotectedAttributes. When either of these + are added, version checking below needs to be updated to match + Section 6.1 of RFC 5652 */ + + /* if RecipientInfos include pwri or ori, version is 3 */ + if (wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_PWRI) || + wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_ORI)) { + version = 3; + break; + } + + /* if unprotectedAttrs is absent AND all RecipientInfo structs + are version 0, version is 0 */ + if (wc_PKCS7_RecipientListVersionsAllZero(pkcs7)) { + version = 0; + break; + } + + /* otherwise, version is 2 */ + version = 2; + break; + + default: + break; + } + + return version; } /* build PKCS#7 envelopedData content type, return enveloped size */ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) { - int i, ret = 0, idx = 0; - int totalSz = 0, padSz = 0, desOutSz = 0; + int ret, idx = 0; + int totalSz, padSz, encryptedOutSz; + + int contentInfoSeqSz = 0, outerContentTypeSz = 0, outerContentSz; + byte contentInfoSeq[MAX_SEQ_SZ]; + byte outerContentType[MAX_ALGO_SZ]; + byte outerContent[MAX_SEQ_SZ]; + + int kariVersion; + int envDataSeqSz, verSz; + byte envDataSeq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + + WC_RNG rng; + int blockSz, blockKeySz; + byte* plain; + byte* encryptedContent; + + Pkcs7EncodedRecip* tmpRecip = NULL; + int recipSz, recipSetSz; + byte recipSet[MAX_SET_SZ]; + + int encContentOctetSz, encContentSeqSz, contentTypeSz; + int contentEncAlgoSz, ivOctetStringSz; + byte encContentSeq[MAX_SEQ_SZ]; + byte contentType[MAX_ALGO_SZ]; + byte contentEncAlgo[MAX_ALGO_SZ]; + byte tmpIv[MAX_CONTENT_IV_SIZE]; + byte ivOctetString[MAX_OCTET_STR_SZ]; + byte encContentOctet[MAX_OCTET_STR_SZ]; + + if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0) + return BAD_FUNC_ARG; + + if (output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) + return blockKeySz; + + blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); + if (blockSz < 0) + return blockSz; + + if (pkcs7->contentOID != FIRMWARE_PKG_DATA) { + /* outer content type */ + ret = wc_SetContentType(ENVELOPED_DATA, outerContentType, + sizeof(outerContentType)); + if (ret < 0) + return ret; + + outerContentTypeSz = ret; + } + + /* generate random content encryption key */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret != 0) { + return ret; + } + + /* build RecipientInfo, only if user manually set singleCert and size */ + if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) { + switch (pkcs7->publicKeyOID) { + #ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert, + pkcs7->singleCertSz, 0); + break; + #endif + #ifdef HAVE_ECC + case ECDSAk: + ret = wc_PKCS7_AddRecipient_KARI(pkcs7, pkcs7->singleCert, + pkcs7->singleCertSz, + pkcs7->keyWrapOID, + pkcs7->keyAgreeOID, pkcs7->ukm, + pkcs7->ukmSz, 0); + break; + #endif + + default: + WOLFSSL_MSG("Unsupported RecipientInfo public key type"); + return BAD_FUNC_ARG; + }; + + if (ret < 0) { + WOLFSSL_MSG("Failed to create RecipientInfo"); + return ret; + } + } + + recipSz = wc_PKCS7_GetRecipientListSize(pkcs7); + if (recipSz < 0) { + return ret; + + } else if (recipSz == 0) { + WOLFSSL_MSG("You must add at least one CMS recipient"); + return PKCS7_RECIP_E; + } + recipSetSz = SetSet(recipSz, recipSet); + + /* version, defined in Section 6.1 of RFC 5652 */ + kariVersion = wc_PKCS7_GetCMSVersion(pkcs7, ENVELOPED_DATA); + if (kariVersion < 0) { + WOLFSSL_MSG("Failed to set CMS EnvelopedData version"); + return PKCS7_RECIP_E; + } + + verSz = SetMyVersion(kariVersion, ver, 0); + + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) + return ret; + + /* generate IV for block cipher */ + ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, tmpIv, blockSz); + wc_FreeRng(&rng); + if (ret != 0) + return ret; + + /* EncryptedContentInfo */ + ret = wc_SetContentType(pkcs7->contentOID, contentType, + sizeof(contentType)); + if (ret < 0) + return ret; + + contentTypeSz = ret; + + /* allocate encrypted content buffer and PKCS#7 padding */ + padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz); + if (padSz < 0) + return padSz; + + encryptedOutSz = pkcs7->contentSz + padSz; + + plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (plain == NULL) + return MEMORY_E; + + ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain, + encryptedOutSz, blockSz); + if (ret < 0) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedContent == NULL) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* put together IV OCTET STRING */ + ivOctetStringSz = SetOctetString(blockSz, ivOctetString); + + /* build up our ContentEncryptionAlgorithmIdentifier sequence, + * adding (ivOctetStringSz + blockSz) for IV OCTET STRING */ + contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, + oidBlkType, ivOctetStringSz + blockSz); + + if (contentEncAlgoSz == 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + + /* encrypt content */ + ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek, + pkcs7->cekSz, tmpIv, blockSz, NULL, 0, NULL, 0, plain, + encryptedOutSz, encryptedContent); + + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz, + encContentOctet); + + encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + + ivOctetStringSz + blockSz + + encContentOctetSz + encryptedOutSz, + encContentSeq); + + /* keep track of sizes for outer wrapper layering */ + totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + + contentEncAlgoSz + ivOctetStringSz + blockSz + + encContentOctetSz + encryptedOutSz; + + /* EnvelopedData */ + envDataSeqSz = SetSequence(totalSz, envDataSeq); + totalSz += envDataSeqSz; + + /* outer content */ + outerContentSz = SetExplicit(0, totalSz, outerContent); + totalSz += outerContentTypeSz; + totalSz += outerContentSz; + + if (pkcs7->contentOID != FIRMWARE_PKG_DATA) { + /* ContentInfo */ + contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); + totalSz += contentInfoSeqSz; + } + + if (totalSz > (int)outputSz) { + WOLFSSL_MSG("Pkcs7_encrypt output buffer too small"); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BUFFER_E; + } + + if (pkcs7->contentOID != FIRMWARE_PKG_DATA) { + XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); + idx += contentInfoSeqSz; + XMEMCPY(output + idx, outerContentType, outerContentTypeSz); + idx += outerContentTypeSz; + XMEMCPY(output + idx, outerContent, outerContentSz); + idx += outerContentSz; + } + XMEMCPY(output + idx, envDataSeq, envDataSeqSz); + idx += envDataSeqSz; + XMEMCPY(output + idx, ver, verSz); + idx += verSz; + XMEMCPY(output + idx, recipSet, recipSetSz); + idx += recipSetSz; + /* copy in recipients from list */ + tmpRecip = pkcs7->recipList; + while (tmpRecip != NULL) { + XMEMCPY(output + idx, tmpRecip->recip, tmpRecip->recipSz); + idx += tmpRecip->recipSz; + tmpRecip = tmpRecip->next; + } + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + XMEMCPY(output + idx, encContentSeq, encContentSeqSz); + idx += encContentSeqSz; + XMEMCPY(output + idx, contentType, contentTypeSz); + idx += contentTypeSz; + XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); + idx += contentEncAlgoSz; + XMEMCPY(output + idx, ivOctetString, ivOctetStringSz); + idx += ivOctetStringSz; + XMEMCPY(output + idx, tmpIv, blockSz); + idx += blockSz; + XMEMCPY(output + idx, encContentOctet, encContentOctetSz); + idx += encContentOctetSz; + XMEMCPY(output + idx, encryptedContent, encryptedOutSz); + idx += encryptedOutSz; + + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + return idx; +} + +#ifndef NO_RSA +/* decode KeyTransRecipientInfo (ktri), return 0 on success, <0 on error */ +static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + int length, encryptedKeySz = 0, ret = 0; + int keySz, version, sidType = 0; + word32 encOID; + word32 keyIdx; + byte issuerHash[KEYID_SIZE]; + byte* outKey = NULL; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + byte tag; + + +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = *idx; + long rc; +#endif +#ifdef WC_RSA_BLINDING + WC_RNG rng; +#endif + +#ifdef WOLFSSL_SMALL_STACK + mp_int* serialNum = NULL; + byte* encryptedKey = NULL; + RsaKey* privKey = NULL; +#else + mp_int serialNum[1]; + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; + RsaKey privKey[1]; +#endif + + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_KTRI: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_VERSION_SZ, + &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + #endif + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (version == 0) { + sidType = CMS_ISSUER_AND_SERIAL_NUMBER; + } else if (version == 2) { + sidType = CMS_SKID; + } else { + return ASN_VERSION_E; + } + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, 0, sidType, version); + + /* @TODO getting total amount left because of GetInt call later on + * this could be optimized to stream better */ + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_2); + FALL_THROUGH; + + case WC_PKCS7_DECRYPT_KTRI_2: + #ifndef NO_PKCS7_STREAM + + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, + &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + wc_PKCS7_StreamGetVar(pkcs7, NULL, &sidType, &version); + + /* @TODO get expected size for next part, does not account for + * GetInt call well */ + if (pkcs7->stream->expected == MAX_SEQ_SZ) { + int sz; + word32 lidx; + + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + lidx = *idx; + ret = GetSequence(pkiMsg, &lidx, &sz, pkiMsgSz); + if (ret < 0) + return ret; + } + else { + lidx = *idx + ASN_TAG_SZ; + ret = GetLength(pkiMsg, &lidx, &sz, pkiMsgSz); + if (ret < 0) + return ret; + } + + pkcs7->stream->expected = sz + MAX_ALGO_SZ + ASN_TAG_SZ + + MAX_LENGTH_SZ; + if (pkcs7->stream->length > 0 && + pkcs7->stream->length < pkcs7->stream->expected) { + return WC_PKCS7_WANT_READ_E; + } + } + #endif /* !NO_PKCS7_STREAM */ + + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + + /* 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, pkcs7->issuerHash, KEYID_SIZE) == 0) { + *recipFound = 1; + } + + #ifdef WOLFSSL_SMALL_STACK + serialNum = (mp_int*)XMALLOC(sizeof(mp_int), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (serialNum == NULL) + return MEMORY_E; + #endif + + if (GetInt(serialNum, pkiMsg, idx, pkiMsgSz) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ASN_PARSE_E; + } + + mp_clear(serialNum); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + } else { + /* remove SubjectKeyIdentifier */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* if we found correct recipient, SKID will match */ + if (XMEMCMP(pkiMsg + (*idx), pkcs7->issuerSubjKeyId, + KEYID_SIZE) == 0) { + *recipFound = 1; + } + (*idx) += KEYID_SIZE; + } + + if (GetAlgoId(pkiMsg, idx, &encOID, oidKeyType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* key encryption algorithm must be RSA for now */ + if (encOID != RSAk) + return ALGO_ID_E; + + /* read encryptedKey */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &encryptedKeySz, pkiMsgSz) < 0) { + return ASN_PARSE_E; + } + if (encryptedKeySz > MAX_ENCRYPTED_KEY_SZ) { + return BUFFER_E; + } + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, encryptedKeySz, sidType, version); + pkcs7->stream->expected = encryptedKeySz; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_3); + FALL_THROUGH; + + case WC_PKCS7_DECRYPT_KTRI_3: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, idx)) != 0) { + return ret; + } + encryptedKeySz = pkcs7->stream->expected; + #endif + + #ifdef WOLFSSL_SMALL_STACK + encryptedKey = (byte*)XMALLOC(encryptedKeySz, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedKey == NULL) + return MEMORY_E; + #endif + + if (*recipFound == 1) + XMEMCPY(encryptedKey, &pkiMsg[*idx], encryptedKeySz); + *idx += encryptedKeySz; + + /* load private key */ + #ifdef WOLFSSL_SMALL_STACK + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) { + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + #endif + + ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, INVALID_DEVID); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { + keyIdx = 0; + ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &keyIdx, + privKey, pkcs7->privateKeySz); + } + else if (pkcs7->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } + if (ret != 0) { + WOLFSSL_MSG("Failed to decode RSA private key"); + wc_FreeRsaKey(privKey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + /* decrypt encryptedKey */ + #ifdef WC_RSA_BLINDING + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret == 0) { + ret = wc_RsaSetRNG(privKey, &rng); + } + #endif + if (ret == 0) { + keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, + &outKey, privKey); + #ifdef WC_RSA_BLINDING + wc_FreeRng(&rng); + #endif + } else { + keySz = ret; + } + wc_FreeRsaKey(privKey); + + if (keySz <= 0 || outKey == NULL) { + ForceZero(encryptedKey, encryptedKeySz); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return keySz; + } else { + *decryptedKeySz = keySz; + XMEMCPY(decryptedKey, outKey, keySz); + ForceZero(encryptedKey, encryptedKeySz); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + break; + + default: + WOLFSSL_MSG("PKCS7 Unknown KTRI decrypt state"); + ret = BAD_FUNC_ARG; + } + + return ret; +} +#endif /* !NO_RSA */ + +#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) +{ + int ret, length; + word32 keyOID, oidSum = 0; + int curve_id = ECC_CURVE_DEF; + byte tag; + + if (kari == NULL || pkiMsg == NULL || idx == NULL) + return BAD_FUNC_ARG; + + /* remove OriginatorIdentifierOrKey */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + } else { + return ASN_PARSE_E; + } + + /* remove OriginatorPublicKey */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + } else { + return ASN_PARSE_E; + } + + /* remove AlgorithmIdentifier */ + if (GetAlgoId(pkiMsg, idx, &keyOID, oidKeyType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (keyOID != ECDSAk) + return ASN_PARSE_E; + + /* optional algorithm parameters */ + ret = GetObjectId(pkiMsg, idx, &oidSum, oidIgnoreType, pkiMsgSz); + if (ret == 0) { + /* get curve id */ + curve_id = wc_ecc_get_oid(oidSum, NULL, 0); + if (curve_id < 0) + return ECC_CURVE_OID_E; + } + + /* remove ECPoint BIT STRING */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_BIT_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_EXPECT_0_E; + + if (tag != ASN_OTHER_TYPE) + return ASN_EXPECT_0_E; + + /* get sender ephemeral public ECDSA key */ + ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId); + if (ret != 0) + return ret; + + kari->senderKeyInit = 1; + + /* length-1 for unused bits counter */ + ret = wc_ecc_import_x963_ex(pkiMsg + (*idx), length - 1, kari->senderKey, + curve_id); + if (ret != 0) { + ret = wc_EccPublicKeyDecode(pkiMsg, idx, kari->senderKey, *idx + length - 1); + if (ret != 0) + return ret; + } + else { + (*idx) += length - 1; + } + + return 0; +} + + +/* remove optional UserKeyingMaterial if available, return 0 on success, + * < 0 on error */ +static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari, + byte* pkiMsg, word32 pkiMsgSz, word32* idx) +{ + int length; + word32 savedIdx; + byte tag; + + if (kari == NULL || pkiMsg == NULL || idx == NULL) + return BAD_FUNC_ARG; + + savedIdx = *idx; + + /* starts with EXPLICIT [1] */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { + *idx = savedIdx; + return 0; + } + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + *idx = savedIdx; + return 0; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + *idx = savedIdx; + return 0; + } + + /* get OCTET STRING */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { + *idx = savedIdx; + return 0; + } + if (tag != ASN_OCTET_STRING) { + *idx = savedIdx; + return 0; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + *idx = savedIdx; + return 0; + } + + kari->ukm = NULL; + if (length > 0) { + kari->ukm = (byte*)XMALLOC(length, kari->heap, DYNAMIC_TYPE_PKCS7); + if (kari->ukm == NULL) + return MEMORY_E; + + XMEMCPY(kari->ukm, pkiMsg + (*idx), length); + kari->ukmOwner = 1; + } + + (*idx) += length; + kari->ukmSz = length; + + return 0; +} + + +/* remove ASN.1 KeyEncryptionAlgorithmIdentifier, return 0 on success, + * < 0 on error */ +static int wc_PKCS7_KariGetKeyEncryptionAlgorithmId(WC_PKCS7_KARI* kari, + byte* pkiMsg, word32 pkiMsgSz, word32* idx, + word32* keyAgreeOID, word32* keyWrapOID) +{ + int length = 0; + word32 localIdx; + + if (kari == NULL || pkiMsg == NULL || idx == NULL || + keyAgreeOID == NULL || keyWrapOID == NULL) + return BAD_FUNC_ARG; + + localIdx = *idx; + + /* remove KeyEncryptionAlgorithmIdentifier */ + if (GetSequence(pkiMsg, &localIdx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + localIdx = *idx; + if (GetAlgoId(pkiMsg, &localIdx, keyAgreeOID, oidCmsKeyAgreeType, + pkiMsgSz) < 0) { + return ASN_PARSE_E; + } + + if (localIdx < *idx + length) { + *idx = localIdx; + } + /* remove KeyWrapAlgorithm, stored in parameter of KeyEncAlgoId */ + if (GetAlgoId(pkiMsg, idx, keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + return 0; +} + + +/* 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* rid) +{ + int length; + byte tag; + + if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL || + rid == NULL) + return BAD_FUNC_ARG; + + /* remove RecipientKeyIdentifier IMPLICIT [0] */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { + return ASN_PARSE_E; + } + + if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + } else { + return ASN_PARSE_E; + } + + /* remove SubjectKeyIdentifier */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { + return ASN_PARSE_E; + } + + if (tag != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (length != KEYID_SIZE) + return ASN_PARSE_E; + + XMEMCPY(rid, pkiMsg + (*idx), KEYID_SIZE); + (*idx) += length; + + /* subject key id should match if recipient found */ + if (XMEMCMP(rid, kari->decoded->extSubjKeyId, KEYID_SIZE) == 0) { + *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, byte* rid) +{ + int length, ret; +#ifdef WOLFSSL_SMALL_STACK + mp_int* serial; + mp_int* recipSerial; +#else + mp_int serial[1]; + mp_int recipSerial[1]; +#endif + + if (rid == NULL) { + return BAD_FUNC_ARG; + } + + /* remove IssuerAndSerialNumber */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetNameHash(pkiMsg, idx, rid, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* if we found correct recipient, issuer hashes will match */ + if (XMEMCMP(rid, kari->decoded->issuerHash, KEYID_SIZE) == 0) { + *recipFound = 1; + } + +#ifdef WOLFSSL_SMALL_STACK + serial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (serial == NULL) + return MEMORY_E; + + recipSerial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (recipSerial == NULL) { + XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + if (GetInt(serial, pkiMsg, idx, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, kari->heap, 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, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, kari->heap, 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, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PKCS7_RECIP_E; + } + + mp_clear(serial); + mp_clear(recipSerial); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, kari->heap, 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, byte* rid) +{ + int length; + int ret = 0; + byte tag; + word32 localIdx; + + 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 */ + localIdx = *idx; + if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + /* try to get RecipientKeyIdentifier */ + ret = wc_PKCS7_KariGetSubjectKeyIdentifier(kari, pkiMsg, pkiMsgSz, + idx, recipFound, rid); + } else { + /* try to get IssuerAndSerialNumber */ + ret = wc_PKCS7_KariGetIssuerAndSerialNumber(kari, pkiMsg, pkiMsgSz, + idx, recipFound, rid); + } + + /* if we don't have either option, malformed CMS */ + if (ret != 0) + return ret; + + /* remove EncryptedKey */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* put encrypted CEK in decryptedKey buffer for now, decrypt later */ + if (length > *encryptedKeySz) + return BUFFER_E; + + XMEMCPY(encryptedKey, pkiMsg + (*idx), length); + *encryptedKeySz = length; + (*idx) += length; + + return 0; +} + +#endif /* HAVE_ECC */ + + +int wc_PKCS7_SetOriEncryptCtx(PKCS7* pkcs7, void* ctx) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->oriEncryptCtx = ctx; + + return 0; +} + + +int wc_PKCS7_SetOriDecryptCtx(PKCS7* pkcs7, void* ctx) +{ + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->oriDecryptCtx = ctx; + + return 0; +} + + +int wc_PKCS7_SetOriDecryptCb(PKCS7* pkcs7, CallbackOriDecrypt cb) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->oriDecryptCb = cb; + + return 0; +} + + +/* return 0 on success */ +int wc_PKCS7_SetWrapCEKCb(PKCS7* pkcs7, CallbackWrapCEK cb) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->wrapCEKCb = cb; + + return 0; +} + +/* Decrypt ASN.1 OtherRecipientInfo (ori), as defined by: + * + * OtherRecipientInfo ::= SEQUENCE { + * oriType OBJECT IDENTIFIER, + * oriValue ANY DEFINED BY oriType } + * + * pkcs7 - pointer to initialized PKCS7 structure + * pkiMsg - pointer to encoded CMS bundle + * pkiMsgSz - size of pkiMsg, bytes + * idx - [IN/OUT] pointer to index into pkiMsg + * decryptedKey - [OUT] output buf for decrypted content encryption key + * decryptedKeySz - [IN/OUT] size of buffer, size of decrypted key + * recipFound - [OUT] 1 if recipient has been found, 0 if not + * + * Return 0 on success, negative upon error. + */ +static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* in, word32 inSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + int ret, seqSz, oriOIDSz; + word32 oriValueSz, tmpIdx; + byte* oriValue; + byte oriOID[MAX_OID_SZ]; + + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 stateIdx = *idx; + long rc; +#endif + + if (pkcs7->oriDecryptCb == NULL) { + WOLFSSL_MSG("You must register an ORI Decrypt callback"); + return BAD_FUNC_ARG; + } + + switch (pkcs7->state) { + + case WC_PKCS7_DECRYPT_ORI: + #ifndef NO_PKCS7_STREAM + /* @TODO for now just get full buffer, needs divided up */ + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + + pkcs7->stream->length, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + /* get OtherRecipientInfo sequence length */ + if (GetLength(pkiMsg, idx, &seqSz, pkiMsgSz) < 0) + return ASN_PARSE_E; + + tmpIdx = *idx; + + /* remove and store oriType OBJECT IDENTIFIER */ + if (GetASNObjectId(pkiMsg, idx, &oriOIDSz, pkiMsgSz) != 0) + return ASN_PARSE_E; + + XMEMCPY(oriOID, pkiMsg + *idx, oriOIDSz); + *idx += oriOIDSz; + + /* get oriValue, increment idx */ + oriValue = pkiMsg + *idx; + oriValueSz = seqSz - (*idx - tmpIdx); + *idx += oriValueSz; + + /* pass oriOID and oriValue to user callback, expect back + decryptedKey and size */ + ret = pkcs7->oriDecryptCb(pkcs7, oriOID, (word32)oriOIDSz, oriValue, + oriValueSz, decryptedKey, decryptedKeySz, + pkcs7->oriDecryptCtx); + + if (ret != 0 || decryptedKey == NULL || *decryptedKeySz == 0) { + /* decrypt operation failed */ + *recipFound = 0; + return PKCS7_RECIP_E; + } + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + break; + + default: + WOLFSSL_MSG("PKCS7 ORI unknown state"); + ret = BAD_FUNC_ARG; + + } + + return ret; +} + +#if !defined(NO_PWDBASED) && !defined(NO_SHA) + +/* decode ASN.1 PasswordRecipientInfo (pwri), return 0 on success, + * < 0 on error */ +static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + byte* salt; + byte* cek; + byte* kek; + + byte tmpIv[MAX_CONTENT_IV_SIZE]; + + int ret = 0, length, saltSz, iterations, blockSz, kekKeySz; + int hashOID = WC_SHA; /* default to SHA1 */ + word32 kdfAlgoId, pwriEncAlgoId, keyEncAlgoId, cekSz; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + byte tag; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = *idx; + long rc; +#endif + + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_PWRI: + #ifndef NO_PKCS7_STREAM + /*@TODO for now just get full buffer, needs divided up */ + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + + pkcs7->stream->length, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + /* remove KeyDerivationAlgorithmIdentifier */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KeyDerivationAlgorithmIdentifier */ + if (wc_GetContentType(pkiMsg, idx, &kdfAlgoId, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KDF params SEQ */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KDF salt OCTET STRING */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &saltSz, pkiMsgSz) < 0) + return ASN_PARSE_E; + + salt = (byte*)XMALLOC(saltSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (salt == NULL) + return MEMORY_E; + + XMEMCPY(salt, pkiMsg + (*idx), saltSz); + *idx += saltSz; + + /* get KDF iterations */ + if (GetMyVersion(pkiMsg, idx, &iterations, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get KeyEncAlgoId SEQ */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get KeyEncAlgoId */ + if (wc_GetContentType(pkiMsg, idx, &keyEncAlgoId, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get pwriEncAlgoId */ + if (GetAlgoId(pkiMsg, idx, &pwriEncAlgoId, oidBlkType, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + blockSz = wc_PKCS7_GetOIDBlockSize(pwriEncAlgoId); + if (blockSz < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockSz; + } + + /* get content-encryption key size, based on algorithm */ + kekKeySz = wc_PKCS7_GetOIDKeySize(pwriEncAlgoId); + if (kekKeySz < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return kekKeySz; + } + + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (tag != ASN_OCTET_STRING) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (length != blockSz) { + WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + XMEMCPY(tmpIv, pkiMsg + (*idx), length); + *idx += length; + + /* get EncryptedKey */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (tag != ASN_OCTET_STRING) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* allocate temporary space for decrypted key */ + cekSz = length; + cek = (byte*)XMALLOC(cekSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cek == NULL) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* generate KEK */ + kek = (byte*)XMALLOC(kekKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (kek == NULL) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, pkcs7->pass, pkcs7->passSz, + salt, saltSz, kdfAlgoId, hashOID, + iterations, kek, kekKeySz); + if (ret < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* decrypt CEK with KEK */ + ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, kekKeySz, + pkiMsg + (*idx), length, cek, + cekSz, tmpIv, blockSz, + pwriEncAlgoId); + if (ret < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + cekSz = ret; + + if (*decryptedKeySz < cekSz) { + WOLFSSL_MSG("Decrypted key buffer too small for CEK"); + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + XMEMCPY(decryptedKey, cek, cekSz); + *decryptedKeySz = cekSz; + + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + *idx += length; + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + break; + + default: + WOLFSSL_MSG("PKCS7 PWRI unknown state"); + ret = BAD_FUNC_ARG; + } + + return ret; +} + +#endif /* NO_PWDBASED | NO_SHA */ + +/* decode ASN.1 KEKRecipientInfo (kekri), return 0 on success, + * < 0 on error */ +static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + int length, keySz, dateLen, direction; + byte* keyId = NULL; + const byte* datePtr = NULL; + byte dateFormat, tag; + word32 keyIdSz, kekIdSz, keyWrapOID, localIdx; + + int ret = 0; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = *idx; + long rc; +#endif + + WOLFSSL_ENTER("wc_PKCS7_DecryptKekri"); + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_KEKRI: + #ifndef NO_PKCS7_STREAM + /* @TODO for now just get full buffer, needs divided up */ + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + + pkcs7->stream->length, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + /* remove KEKIdentifier */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + kekIdSz = length; + + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* save keyIdentifier and length */ + keyId = pkiMsg + *idx; + keyIdSz = length; + *idx += keyIdSz; + + /* may have OPTIONAL GeneralizedTime */ + localIdx = *idx; + if ((*idx < kekIdSz) && GetASNTag(pkiMsg, &localIdx, &tag, + pkiMsgSz) == 0 && tag == ASN_GENERALIZED_TIME) { + if (wc_GetDateInfo(pkiMsg + *idx, pkiMsgSz, &datePtr, &dateFormat, + &dateLen) != 0) { + return ASN_PARSE_E; + } + *idx += (dateLen + 1); + } + + /* may have OPTIONAL OtherKeyAttribute */ + localIdx = *idx; + if ((*idx < kekIdSz) && GetASNTag(pkiMsg, &localIdx, &tag, + pkiMsgSz) == 0 && tag == (ASN_SEQUENCE | + ASN_CONSTRUCTED)) { + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* skip it */ + *idx += length; + } + + /* get KeyEncryptionAlgorithmIdentifier */ + if (GetAlgoId(pkiMsg, idx, &keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get EncryptedKey */ + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + #ifndef NO_AES + direction = AES_DECRYPTION; + #else + direction = DES_DECRYPTION; + #endif + + /* decrypt CEK with KEK */ + if (pkcs7->wrapCEKCb) { + keySz = pkcs7->wrapCEKCb(pkcs7, pkiMsg + *idx, length, keyId, + keyIdSz, NULL, 0, decryptedKey, + *decryptedKeySz, keyWrapOID, + (int)PKCS7_KEKRI, direction); + } + else { + keySz = wc_PKCS7_KeyWrap(pkiMsg + *idx, length, pkcs7->privateKey, + pkcs7->privateKeySz, decryptedKey, *decryptedKeySz, + keyWrapOID, direction); + } + if (keySz <= 0) + return keySz; + + *decryptedKeySz = (word32)keySz; + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + *idx += length; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + break; + + default: + WOLFSSL_MSG("PKCS7 KEKRI unknown state"); + ret = BAD_FUNC_ARG; + + } + + (void)keyId; + return ret; +} + + +/* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success, + * < 0 on error */ +static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ +#ifdef HAVE_ECC + int ret, keySz; + int encryptedKeySz; + int direction = 0; + word32 keyAgreeOID, keyWrapOID; + byte rid[KEYID_SIZE]; + +#ifdef WOLFSSL_SMALL_STACK + byte* encryptedKey; +#else + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; +#endif + + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = (idx) ? *idx : 0; + long rc; +#endif + + WOLFSSL_ENTER("wc_PKCS7_DecryptKari"); + if (pkcs7 == NULL || pkiMsg == NULL || + ((pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) && + pkcs7->wrapCEKCb == NULL) || + idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL) { + return BAD_FUNC_ARG; + } + + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_KARI: { + #ifndef NO_PKCS7_STREAM + /* @TODO for now just get full buffer, needs divided up */ + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + + pkcs7->stream->length, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + WC_PKCS7_KARI* kari; + + kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_DECODE); + if (kari == NULL) + return MEMORY_E; + + #ifdef WOLFSSL_SMALL_STACK + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedKey == NULL) { + wc_PKCS7_KariFree(kari); + return MEMORY_E; + } + #endif + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + + /* parse cert and key */ + if (pkcs7->singleCert != NULL) { + ret = wc_PKCS7_KariParseRecipCert(kari, (byte*)pkcs7->singleCert, + pkcs7->singleCertSz, pkcs7->privateKey, + pkcs7->privateKeySz); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + } + + /* remove OriginatorIdentifierOrKey */ + ret = wc_PKCS7_KariGetOriginatorIdentifierOrKey(kari, pkiMsg, + pkiMsgSz, idx); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* try and remove optional UserKeyingMaterial */ + ret = wc_PKCS7_KariGetUserKeyingMaterial(kari, pkiMsg, pkiMsgSz, idx); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* remove KeyEncryptionAlgorithmIdentifier */ + ret = wc_PKCS7_KariGetKeyEncryptionAlgorithmId(kari, pkiMsg, + pkiMsgSz, idx, &keyAgreeOID, &keyWrapOID); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* if user has not explicitly set keyAgreeOID, set from one in bundle */ + if (pkcs7->keyAgreeOID == 0) + pkcs7->keyAgreeOID = keyAgreeOID; + + /* set direction based on key wrap algorithm */ + switch (keyWrapOID) { + #ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + #endif + direction = AES_DECRYPTION; + break; + #endif + default: + WOLFSSL_MSG("AES key wrap algorithm unsupported"); + if (pkcs7->wrapCEKCb) { + WOLFSSL_MSG("Direction not set!"); + break; /* if unwrapping callback is set then do not + * force restriction of supported wrap + * algorithms */ + } + + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return BAD_KEYWRAP_ALG_E; + } + + /* remove RecipientEncryptedKeys */ + ret = wc_PKCS7_KariGetRecipientEncryptedKeys(kari, pkiMsg, pkiMsgSz, + idx, recipFound, encryptedKey, &encryptedKeySz, rid); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* decrypt CEK with KEK */ + if (pkcs7->wrapCEKCb) { + word32 tmpKeySz = 0; + byte* tmpKeyDer = NULL; + + ret = wc_ecc_export_x963(kari->senderKey, NULL, &tmpKeySz); + if (ret != LENGTH_ONLY_E) { + return ret; + } + + /* buffer space for algorithm/curve */ + tmpKeySz += MAX_SEQ_SZ; + tmpKeySz += 2 * MAX_ALGO_SZ; + + /* buffer space for public key sequence */ + tmpKeySz += MAX_SEQ_SZ; + tmpKeySz += TRAILING_ZERO; + + tmpKeyDer = (byte*)XMALLOC(tmpKeySz, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmpKeyDer == NULL) { + return MEMORY_E; + } + + ret = wc_EccPublicKeyToDer(kari->senderKey, tmpKeyDer, + tmpKeySz, 1); + if (ret < 0) { + XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + tmpKeySz = (word32)ret; + + keySz = pkcs7->wrapCEKCb(pkcs7, encryptedKey, encryptedKeySz, + rid, KEYID_SIZE, tmpKeyDer, tmpKeySz, + decryptedKey, *decryptedKeySz, + keyWrapOID, (int)PKCS7_KARI, direction); + XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + + if (keySz > 0) { + /* If unwrapping was successful then consider recipient + * found. Checking for NULL singleCert to confirm previous + * SID check was not done */ + if (pkcs7->singleCert == NULL) + *recipFound = 1; + } + } + else { + /* create KEK */ + ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, pkcs7->keyAgreeOID); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* decrypt CEK with KEK */ + keySz = wc_PKCS7_KeyWrap(encryptedKey, encryptedKeySz, kari->kek, + kari->kekSz, decryptedKey, *decryptedKeySz, + keyWrapOID, direction); + } + if (keySz <= 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return keySz; + } + *decryptedKeySz = (word32)keySz; + + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + } + break; + + default: + WOLFSSL_MSG("PKCS7 kari unknown state"); + ret = BAD_FUNC_ARG; + + } + + (void)pkiMsg; + (void)pkiMsgSz; + + return ret; +#else + (void)in; + (void)inSz; + (void)pkcs7; + (void)idx; + (void)decryptedKey; + (void)decryptedKeySz; + (void)recipFound; + + return NOT_COMPILED_IN; +#endif /* HAVE_ECC */ +} + + +/* decode ASN.1 RecipientInfos SET, return 0 on success, < 0 on error */ +static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, + word32 inSz, word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + word32 savedIdx; + int version, ret = 0, length; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + byte tag; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx; + long rc; +#endif + + if (pkcs7 == NULL || pkiMsg == NULL || idx == NULL || + decryptedKey == NULL || decryptedKeySz == NULL || + recipFound == NULL) { + return BAD_FUNC_ARG; + } + + WOLFSSL_ENTER("wc_PKCS7_DecryptRecipientInfos"); +#ifndef NO_PKCS7_STREAM + tmpIdx = *idx; +#endif + + /* check if in the process of decrypting */ + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_KTRI: + case WC_PKCS7_DECRYPT_KTRI_2: + case WC_PKCS7_DECRYPT_KTRI_3: + #ifndef NO_RSA + ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + #else + return NOT_COMPILED_IN; + #endif + break; + + case WC_PKCS7_DECRYPT_KARI: + ret = wc_PKCS7_DecryptKari(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + break; + + case WC_PKCS7_DECRYPT_KEKRI: + ret = wc_PKCS7_DecryptKekri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + break; + + case WC_PKCS7_DECRYPT_PWRI: + #if !defined(NO_PWDBASED) && !defined(NO_SHA) + ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + #else + return NOT_COMPILED_IN; + #endif + break; + + case WC_PKCS7_DECRYPT_ORI: + ret = wc_PKCS7_DecryptOri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + break; + + default: + /* not in decrypting state */ + break; + } + + if (ret < 0) { + return ret; + } + + savedIdx = *idx; +#ifndef NO_PKCS7_STREAM + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + if (rc < 0) { + return (int)rc; + } + pkiMsgSz = (word32)rc; + if (pkcs7->stream->length > 0) + pkiMsg = pkcs7->stream->buffer; +#endif + + /* when looking for next recipient, use first sequence and version to + * indicate there is another, if not, move on */ + while(*recipFound == 0) { + + /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to + * last good saved one */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) > 0) { + + #ifndef NO_RSA + /* found ktri */ + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI); + ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + #else + return NOT_COMPILED_IN; + #endif + } + else { + word32 localIdx; + /* kari is IMPLICIT[1] */ + *idx = savedIdx; + localIdx = *idx; + + if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) != 0) { + /* no room for recipient info */ + break; + } + + if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + (*idx)++; + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { + *idx = savedIdx; + break; + } + + if (version != 3) + return ASN_VERSION_E; + + /* found kari */ + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KARI); + ret = wc_PKCS7_DecryptKari(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + + /* kekri is IMPLICIT[2] */ + } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2)) { + (*idx)++; + + if (GetLength(pkiMsg, idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { + *idx = savedIdx; + break; + } + + if (version != 4) + return ASN_VERSION_E; + + /* found kekri */ + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KEKRI); + ret = wc_PKCS7_DecryptKekri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + + /* pwri is IMPLICIT[3] */ + } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 3)) { + #if !defined(NO_PWDBASED) && !defined(NO_SHA) + (*idx)++; + + if (GetLength(pkiMsg, idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { + *idx = savedIdx; + break; + } + + if (version != 0) + return ASN_VERSION_E; + + /* found pwri */ + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_PWRI); + ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + #else + return NOT_COMPILED_IN; + #endif + + /* ori is IMPLICIT[4] */ + } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 4)) { + (*idx)++; + + /* found ori */ + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_ORI); + ret = wc_PKCS7_DecryptOri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + + } else { + /* failed to find RecipientInfo, restore idx and continue */ + *idx = savedIdx; + break; + } + } + + /* update good idx */ + savedIdx = *idx; + } + + return ret; +} + + +/* Parse encoded EnvelopedData bundle up to RecipientInfo set. + * + * return size of RecipientInfo SET on success, negative upon error */ +static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, + word32 inSz, word32* idx, + int type) +{ + int version = 0, length, ret = 0; + word32 contentType; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + byte tag; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = 0; + long rc; +#endif + + if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || idx == NULL) + return BAD_FUNC_ARG; + + if ((type != ENVELOPED_DATA) && (type != AUTH_ENVELOPED_DATA) && + pkcs7->contentOID != FIRMWARE_PKG_DATA) + return BAD_FUNC_ARG; + +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } + } +#endif + + switch (pkcs7->state) { + case WC_PKCS7_INFOSET_START: + case WC_PKCS7_INFOSET_BER: + case WC_PKCS7_INFOSET_STAGE1: + case WC_PKCS7_INFOSET_STAGE2: + case WC_PKCS7_INFOSET_END: + break; + + default: + WOLFSSL_MSG("Warning, setting PKCS7 info state to start"); + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_START); + } + + switch (pkcs7->state) { + case WC_PKCS7_INFOSET_START: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + ASN_TAG_SZ, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + /* read past ContentInfo, verify type is envelopedData */ + if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + { + ret = ASN_PARSE_E; + } + + if (ret == 0 && length == 0 && pkiMsg[(*idx)-1] == 0x80) { + #ifdef ASN_BER_TO_DER + word32 len; + + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_BER); + FALL_THROUGH; + + /* full buffer is needed for conversion */ + case WC_PKCS7_INFOSET_BER: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->maxLen - pkcs7->stream->length, + &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + + len = 0; + + ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); + if (ret != LENGTH_ONLY_E) + return ret; + pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->der == NULL) + return MEMORY_E; + ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); + if (ret < 0) + return ret; + + pkiMsg = in = pkcs7->der; + pkiMsgSz = pkcs7->derSz = len; + *idx = 0; + + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + #else + return BER_INDEF_E; + #endif + } + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_STAGE1); + FALL_THROUGH; + + case WC_PKCS7_INFOSET_STAGE1: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_OID_SZ + + MAX_LENGTH_SZ + ASN_TAG_SZ, &pkiMsg, idx)) != 0) { + return ret; + } + + pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz; + #endif + if (pkcs7->contentOID != FIRMWARE_PKG_DATA || + type == AUTH_ENVELOPED_DATA) { + if (ret == 0 && wc_GetContentType(pkiMsg, idx, &contentType, + pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0) { + if (type == ENVELOPED_DATA && contentType != ENVELOPED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData"); + ret = PKCS7_OID_E; + } else if (type == AUTH_ENVELOPED_DATA && + contentType != AUTH_ENVELOPED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type AuthEnvelopedData"); + ret = PKCS7_OID_E; + } + } + + if (ret == 0 && GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) != 0) + ret = ASN_PARSE_E; + + if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC + | 0)) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength_ex(pkiMsg, idx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + } + + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_STAGE2); + FALL_THROUGH; + + case WC_PKCS7_INFOSET_STAGE2: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_VERSION_SZ, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + /* remove EnvelopedData and version */ + if (pkcs7->contentOID != FIRMWARE_PKG_DATA || + type == AUTH_ENVELOPED_DATA) { + if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + + pkcs7->stream->varOne = version; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_END); + FALL_THROUGH; + + case WC_PKCS7_INFOSET_END: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + MAX_SET_SZ, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + version = pkcs7->stream->varOne; + #endif + + if (type == ENVELOPED_DATA) { + /* TODO :: make this more accurate */ + if ((pkcs7->publicKeyOID == RSAk && + (version != 0 && version != 2)) + #ifdef HAVE_ECC + || (pkcs7->publicKeyOID == ECDSAk && + (version != 0 && version != 2 && version != 3)) + #endif + ) { + WOLFSSL_MSG("PKCS#7 envelopedData version incorrect"); + ret = ASN_VERSION_E; + } + } else { + /* AuthEnvelopedData version MUST be 0 */ + if (version != 0) { + WOLFSSL_MSG("PKCS#7 AuthEnvelopedData needs to be of version 0"); + ret = ASN_VERSION_E; + } + } + + /* remove RecipientInfo set, get length of set */ + if (ret == 0 && GetSet(pkiMsg, idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + + if (ret == 0) + ret = length; + + break; + + default: + WOLFSSL_MSG("Bad PKCS7 info set state"); + ret = BAD_FUNC_ARG; + break; + } + + return ret; +} + + +/* Import secret/private key into a PKCS7 structure. Used for setting + * the secret key for decryption a EnvelopedData KEKRI RecipientInfo. + * + * Returns 0 on success, negative upon error */ +WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz) +{ + if (pkcs7 == NULL || key == NULL || keySz == 0) + return BAD_FUNC_ARG; + + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + + return 0; +} + + +/* append data to encrypted content cache in PKCS7 structure + * return 0 on success, negative on error */ +static int PKCS7_CacheEncryptedContent(PKCS7* pkcs7, byte* in, word32 inSz) +{ + byte* oldCache; + word32 oldCacheSz; + + if (pkcs7 == NULL || in == NULL) + return BAD_FUNC_ARG; + + /* save pointer to old cache */ + oldCache = pkcs7->cachedEncryptedContent; + oldCacheSz = pkcs7->cachedEncryptedContentSz; + + /* re-allocate new buffer to fit appended data */ + pkcs7->cachedEncryptedContent = (byte*)XMALLOC(oldCacheSz + inSz, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->cachedEncryptedContent == NULL) { + pkcs7->cachedEncryptedContentSz = 0; + XFREE(oldCache, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + if (oldCache != NULL) { + XMEMCPY(pkcs7->cachedEncryptedContent, oldCache, oldCacheSz); + } + XMEMCPY(pkcs7->cachedEncryptedContent + oldCacheSz, in, inSz); + pkcs7->cachedEncryptedContentSz += inSz; + + XFREE(oldCache, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + return 0; +} + + +/* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */ +WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, + word32 inSz, byte* output, + word32 outputSz) +{ + int recipFound = 0; + int ret, length = 0; + word32 idx = 0; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = 0; + long rc; +#endif + word32 contentType, encOID = 0; + word32 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + + int expBlockSz = 0, blockKeySz = 0; + byte tmpIvBuf[MAX_CONTENT_IV_SIZE]; + byte* tmpIv = tmpIvBuf; + + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + byte* decryptedKey = NULL; + int encryptedContentTotalSz = 0; + int encryptedContentSz = 0; + byte padLen; + byte* encryptedContent = NULL; + int explicitOctet = 0; + word32 localIdx; + byte tag; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + if (pkiMsg == NULL || pkiMsgSz == 0 || + output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + +#ifndef NO_PKCS7_STREAM + (void)tmpIv; /* help out static analysis */ + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } + } +#endif + + switch (pkcs7->state) { + case WC_PKCS7_START: + case WC_PKCS7_INFOSET_START: + case WC_PKCS7_INFOSET_BER: + case WC_PKCS7_INFOSET_STAGE1: + case WC_PKCS7_INFOSET_STAGE2: + case WC_PKCS7_INFOSET_END: + ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, + &idx, ENVELOPED_DATA); + if (ret < 0) { + break; + } + + #ifdef ASN_BER_TO_DER + /* check if content was BER and has been converted to DER */ + if (pkcs7->derSz > 0) + pkiMsg = in = pkcs7->der; + #endif + + decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (decryptedKey == NULL) + return MEMORY_E; + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_2); + #ifndef NO_PKCS7_STREAM + tmpIdx = idx; + pkcs7->stream->aad = decryptedKey; + #endif + FALL_THROUGH; + + case WC_PKCS7_ENV_2: + #ifndef NO_PKCS7_STREAM + /* store up enough buffer for initial info set decode */ + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + #endif + FALL_THROUGH; + + case WC_PKCS7_DECRYPT_KTRI: + case WC_PKCS7_DECRYPT_KTRI_2: + case WC_PKCS7_DECRYPT_KTRI_3: + case WC_PKCS7_DECRYPT_KARI: + case WC_PKCS7_DECRYPT_KEKRI: + case WC_PKCS7_DECRYPT_PWRI: + case WC_PKCS7_DECRYPT_ORI: + #ifndef NO_PKCS7_STREAM + decryptedKey = pkcs7->stream->aad; + decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + #endif + + ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx, + decryptedKey, &decryptedKeySz, + &recipFound); + if (ret == 0 && recipFound == 0) { + WOLFSSL_MSG("No recipient found in envelopedData that matches input"); + ret = PKCS7_RECIP_E; + } + + if (ret != 0) + break; + #ifndef NO_PKCS7_STREAM + tmpIdx = idx; + pkcs7->stream->aadSz = decryptedKeySz; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_3); + FALL_THROUGH; + + case WC_PKCS7_ENV_3: + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + MAX_VERSION_SZ + ASN_TAG_SZ + + MAX_LENGTH_SZ, &pkiMsg, &idx)) + != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #else + ret = 0; + #endif + + /* remove EncryptedContentInfo */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, + pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, + pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); + if (ret == 0 && blockKeySz < 0) { + ret = blockKeySz; + } + + expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); + if (ret == 0 && expBlockSz < 0) { + ret = expBlockSz; + } + + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) != 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && tag != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && length != expBlockSz) { + WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); + ret = ASN_PARSE_E; + } + + if (ret != 0) + break; + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, length); + pkcs7->stream->contentSz = blockKeySz; + pkcs7->stream->expected = length + MAX_LENGTH_SZ + MAX_LENGTH_SZ + + ASN_TAG_SZ + ASN_TAG_SZ; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_4); + FALL_THROUGH; + + case WC_PKCS7_ENV_4: + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length); + tmpIv = pkcs7->stream->tmpIv; + if (tmpIv == NULL) { + /* check added to help out static analysis tool */ + ret = MEMORY_E; + break; + } + #else + ret = 0; + #endif + + XMEMCPY(tmpIv, &pkiMsg[idx], length); + idx += length; + + explicitOctet = 0; + localIdx = idx; + if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + explicitOctet = 1; + } + + /* read encryptedContent, cont[0] */ + if (tag != (ASN_CONTEXT_SPECIFIC | 0) && + tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + ret = ASN_PARSE_E; + } + idx++; + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentTotalSz, + pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + } + + if (ret != 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + pkcs7->stream->expected = encryptedContentTotalSz; + wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, 0); + wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, explicitOctet); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_5); + FALL_THROUGH; + + case WC_PKCS7_ENV_5: + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, &explicitOctet); + tmpIv = pkcs7->stream->tmpIv; + encryptedContentTotalSz = pkcs7->stream->expected; + + /* restore decrypted key */ + decryptedKey = pkcs7->stream->aad; + decryptedKeySz = pkcs7->stream->aadSz; + blockKeySz = pkcs7->stream->contentSz; + #else + ret = 0; + #endif + + if (explicitOctet) { + /* encrypted content may be fragmented into multiple + * consecutive OCTET STRINGs, if so loop through + * collecting and caching encrypted content bytes */ + localIdx = idx; + while (idx < (localIdx + encryptedContentTotalSz)) { + + if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && (tag != ASN_OCTET_STRING)) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, + &encryptedContentSz, pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0) { + ret = PKCS7_CacheEncryptedContent(pkcs7, &pkiMsg[idx], + encryptedContentSz); + } + + if (ret != 0) { + break; + } + + /* advance idx past encrypted content */ + idx += encryptedContentSz; + } + + if (ret != 0) { + break; + } + + } else { + /* cache encrypted content, no OCTET STRING */ + ret = PKCS7_CacheEncryptedContent(pkcs7, &pkiMsg[idx], + encryptedContentTotalSz); + if (ret != 0) { + break; + } + idx += encryptedContentTotalSz; + } + + /* use cached content */ + encryptedContent = pkcs7->cachedEncryptedContent; + encryptedContentSz = pkcs7->cachedEncryptedContentSz; + + /* decrypt encryptedContent */ + ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey, + blockKeySz, tmpIv, expBlockSz, NULL, 0, NULL, 0, + encryptedContent, encryptedContentSz, encryptedContent); + if (ret != 0) { + break; + } + + padLen = encryptedContent[encryptedContentSz-1]; + + /* copy plaintext to output */ + if (padLen > encryptedContentSz || + (word32)(encryptedContentSz - padLen) > outputSz) { + ret = BUFFER_E; + break; + } + XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); + + /* free memory, zero out keys */ + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->cachedEncryptedContent != NULL) { + XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + pkcs7->cachedEncryptedContent = NULL; + pkcs7->cachedEncryptedContentSz = 0; + } + + ret = encryptedContentSz - padLen; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->aad = NULL; + pkcs7->stream->aadSz = 0; + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + break; + + default: + WOLFSSL_MSG("PKCS#7 unknown decode enveloped state"); + ret = BAD_FUNC_ARG; + } + +#ifndef NO_PKCS7_STREAM + if (ret < 0 && ret != WC_PKCS7_WANT_READ_E) { + wc_PKCS7_ResetStream(pkcs7); + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + if (pkcs7->cachedEncryptedContent != NULL) { + XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + pkcs7->cachedEncryptedContent = NULL; + pkcs7->cachedEncryptedContentSz = 0; + } + } +#else + if (decryptedKey != NULL && ret < 0) { + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + if (pkcs7->cachedEncryptedContent != NULL && ret < 0) { + XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->cachedEncryptedContent = NULL; + pkcs7->cachedEncryptedContentSz = 0; + } +#endif + return ret; +} + + +/* build PKCS#7 authEnvelopedData content type, return enveloped size */ +int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, + word32 outputSz) +{ +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + int ret, idx = 0; + int totalSz, encryptedOutSz; int contentInfoSeqSz, outerContentTypeSz, outerContentSz; byte contentInfoSeq[MAX_SEQ_SZ]; @@ -1178,229 +10430,396 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) byte envDataSeq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; - RNG rng; - int contentKeyEncSz, blockKeySz; - int dynamicFlag = 0; - byte contentKeyPlain[MAX_CONTENT_KEY_LEN]; -#ifdef WOLFSSL_SMALL_STACK - byte* contentKeyEnc; -#else - byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ]; -#endif - byte* plain; + WC_RNG rng; + int blockSz, blockKeySz; byte* encryptedContent; + Pkcs7EncodedRecip* tmpRecip = NULL; int recipSz, recipSetSz; -#ifdef WOLFSSL_SMALL_STACK - byte* recip; -#else - byte recip[MAX_RECIP_SZ]; -#endif byte recipSet[MAX_SET_SZ]; int encContentOctetSz, encContentSeqSz, contentTypeSz; - int contentEncAlgoSz, ivOctetStringSz; + int contentEncAlgoSz, nonceOctetStringSz, macOctetStringSz; byte encContentSeq[MAX_SEQ_SZ]; byte contentType[MAX_ALGO_SZ]; byte contentEncAlgo[MAX_ALGO_SZ]; - byte tmpIv[DES_BLOCK_SIZE]; - byte ivOctetString[MAX_OCTET_STR_SZ]; + byte nonceOctetString[MAX_OCTET_STR_SZ]; byte encContentOctet[MAX_OCTET_STR_SZ]; + byte macOctetString[MAX_OCTET_STR_SZ]; - if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || - pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL) + byte authTag[AES_BLOCK_SIZE]; + byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */ + byte macInt[MAX_VERSION_SZ]; + word32 nonceSz = 0, macIntSz = 0; + + /* authAttribs */ + byte* flatAuthAttribs = NULL; + byte authAttribSet[MAX_SET_SZ]; + EncodedAttrib authAttribs[MAX_AUTH_ATTRIBS_SZ]; + word32 authAttribsSz = 0, authAttribsCount = 0; + word32 authAttribsSetSz = 0; + + byte* aadBuffer = NULL; + word32 aadBufferSz = 0; + byte authAttribAadSet[MAX_SET_SZ]; + word32 authAttribsAadSetSz = 0; + + /* unauthAttribs */ + byte* flatUnauthAttribs = NULL; + byte unauthAttribSet[MAX_SET_SZ]; + EncodedAttrib unauthAttribs[MAX_UNAUTH_ATTRIBS_SZ]; + word32 unauthAttribsSz = 0, unauthAttribsCount = 0; + word32 unauthAttribsSetSz = 0; + + + PKCS7Attrib contentTypeAttrib; + byte contentTypeValue[MAX_OID_SZ]; + /* contentType OID (1.2.840.113549.1.9.3) */ + const byte contentTypeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, + 0x09, 0x03 }; + + if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0) return BAD_FUNC_ARG; if (output == NULL || outputSz == 0) return BAD_FUNC_ARG; - /* PKCS#7 only supports DES, 3DES for now */ switch (pkcs7->encryptOID) { - case DESb: - blockKeySz = DES_KEYLEN; +#ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: break; - - case DES3b: - blockKeySz = DES3_KEYLEN; + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: break; - + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + break; + #endif +#endif +#ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + break; + #endif +#endif default: - WOLFSSL_MSG("Unsupported content cipher type"); - return ALGO_ID_E; - }; + WOLFSSL_MSG("CMS AuthEnvelopedData must use AES-GCM or AES-CCM"); + return BAD_FUNC_ARG; + } + + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) + return blockKeySz; + + blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); + if (blockSz < 0) + return blockSz; /* outer content type */ - outerContentTypeSz = wc_SetContentType(ENVELOPED_DATA, outerContentType); + ret = wc_SetContentType(AUTH_ENVELOPED_DATA, outerContentType, + sizeof(outerContentType)); + if (ret < 0) + return ret; - /* version, defined as 0 in RFC 2315 */ + outerContentTypeSz = ret; + + /* version, defined as 0 in RFC 5083 */ verSz = SetMyVersion(0, ver, 0); /* generate random content encryption key */ - ret = wc_InitRng(&rng); - if (ret != 0) - return ret; - - ret = wc_RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz); + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); if (ret != 0) { - wc_FreeRng(&rng); return ret; } -#ifdef WOLFSSL_SMALL_STACK - recip = (byte*)XMALLOC(MAX_RECIP_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - contentKeyEnc = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (contentKeyEnc == NULL || recip == NULL) { - if (recip) XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (contentKeyEnc) XFREE(contentKeyEnc, NULL, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - return MEMORY_E; + /* build RecipientInfo, only if user manually set singleCert and size */ + if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) { + switch (pkcs7->publicKeyOID) { + #ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert, + pkcs7->singleCertSz, 0); + break; + #endif + #ifdef HAVE_ECC + case ECDSAk: + ret = wc_PKCS7_AddRecipient_KARI(pkcs7, pkcs7->singleCert, + pkcs7->singleCertSz, + pkcs7->keyWrapOID, + pkcs7->keyAgreeOID, pkcs7->ukm, + pkcs7->ukmSz, 0); + break; + #endif + + default: + WOLFSSL_MSG("Unsupported RecipientInfo public key type"); + return BAD_FUNC_ARG; + }; + + if (ret < 0) { + WOLFSSL_MSG("Failed to create RecipientInfo"); + return ret; + } } - -#endif - - /* build RecipientInfo, only handle 1 for now */ - recipSz = wc_CreateRecipientInfo(pkcs7->singleCert, pkcs7->singleCertSz, RSAk, - blockKeySz, &rng, contentKeyPlain, - contentKeyEnc, &contentKeyEncSz, recip, - MAX_RECIP_SZ); - - ForceZero(contentKeyEnc, MAX_ENCRYPTED_KEY_SZ); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(contentKeyEnc, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + recipSz = wc_PKCS7_GetRecipientListSize(pkcs7); if (recipSz < 0) { - WOLFSSL_MSG("Failed to create RecipientInfo"); - wc_FreeRng(&rng); -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); -#endif - return recipSz; + return ret; + + } else if (recipSz == 0) { + WOLFSSL_MSG("You must add at least one CMS recipient"); + return PKCS7_RECIP_E; } recipSetSz = SetSet(recipSz, recipSet); - /* generate IV for block cipher */ - ret = wc_RNG_GenerateBlock(&rng, tmpIv, DES_BLOCK_SIZE); + /* generate random nonce and IV for encryption */ + switch (pkcs7->encryptOID) { +#ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + FALL_THROUGH; + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + FALL_THROUGH; + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + /* GCM nonce is GCM_NONCE_MID_SZ (12) */ + nonceSz = GCM_NONCE_MID_SZ; + break; + #endif +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + FALL_THROUGH; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + FALL_THROUGH; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + /* CCM nonce is CCM_NONCE_MIN_SZ (7) */ + nonceSz = CCM_NONCE_MIN_SZ; + break; + #endif +#endif /* HAVE_AESCCM */ + } + + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) + return ret; + + ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, nonce, nonceSz); wc_FreeRng(&rng); if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); -#endif + return ret; + } + + + /* authAttribs: add contentType attrib if needed */ + if (pkcs7->contentOID != DATA) { + + /* if type is not id-data, contentType attribute MUST be added */ + contentTypeAttrib.oid = contentTypeOid; + contentTypeAttrib.oidSz = sizeof(contentTypeOid); + + /* try to set from contentOID first, known types */ + ret = wc_SetContentType(pkcs7->contentOID, contentTypeValue, + sizeof(contentTypeValue)); + if (ret > 0) { + contentTypeAttrib.value = contentTypeValue; + contentTypeAttrib.valueSz = ret; + + /* otherwise, try to set from custom content type */ + } else { + if (pkcs7->contentTypeSz == 0) { + WOLFSSL_MSG("CMS pkcs7->contentType must be set if " + "contentOID is not"); + return BAD_FUNC_ARG; + } + contentTypeAttrib.value = pkcs7->contentType; + contentTypeAttrib.valueSz = pkcs7->contentTypeSz; + } + + authAttribsSz += EncodeAttributes(authAttribs, 1, + &contentTypeAttrib, 1); + authAttribsCount += 1; + } + + /* authAttribs: add in user authenticated attributes */ + if (pkcs7->authAttribs != NULL && pkcs7->authAttribsSz > 0) { + authAttribsSz += EncodeAttributes(authAttribs + authAttribsCount, + MAX_AUTH_ATTRIBS_SZ - authAttribsCount, + pkcs7->authAttribs, + pkcs7->authAttribsSz); + authAttribsCount += pkcs7->authAttribsSz; + } + + /* authAttribs: flatten authAttribs */ + if (authAttribsSz > 0 && authAttribsCount > 0) { + flatAuthAttribs = (byte*)XMALLOC(authAttribsSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (flatAuthAttribs == NULL) { + return MEMORY_E; + } + + FlattenAttributes(pkcs7, flatAuthAttribs, authAttribs, + authAttribsCount); + + authAttribsSetSz = SetImplicit(ASN_SET, 1, authAttribsSz, + authAttribSet); + + /* From RFC5083, "For the purpose of constructing the AAD, the + * IMPLICIT [1] tag in the authAttrs field is not used for the + * DER encoding: rather a universal SET OF tag is used. */ + authAttribsAadSetSz = SetSet(authAttribsSz, authAttribAadSet); + + /* allocate temp buffer to hold alternate attrib encoding for aad */ + aadBuffer = (byte*)XMALLOC(authAttribsSz + authAttribsAadSetSz, + pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (aadBuffer == NULL) { + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* build up alternate attrib encoding for aad */ + aadBufferSz = 0; + XMEMCPY(aadBuffer + aadBufferSz, authAttribAadSet, authAttribsAadSetSz); + aadBufferSz += authAttribsAadSetSz; + XMEMCPY(aadBuffer + aadBufferSz, flatAuthAttribs, authAttribsSz); + aadBufferSz += authAttribsSz; + } + + /* build up unauthenticated attributes (unauthAttrs) */ + if (pkcs7->unauthAttribsSz > 0) { + unauthAttribsSz = EncodeAttributes(unauthAttribs + unauthAttribsCount, + MAX_UNAUTH_ATTRIBS_SZ - unauthAttribsCount, + pkcs7->unauthAttribs, + pkcs7->unauthAttribsSz); + unauthAttribsCount = pkcs7->unauthAttribsSz; + + flatUnauthAttribs = (byte*)XMALLOC(unauthAttribsSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (flatUnauthAttribs == NULL) { + if (aadBuffer) + XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + FlattenAttributes(pkcs7, flatUnauthAttribs, unauthAttribs, + unauthAttribsCount); + unauthAttribsSetSz = SetImplicit(ASN_SET, 2, unauthAttribsSz, + unauthAttribSet); + } + + /* allocate encrypted content buffer */ + encryptedOutSz = pkcs7->contentSz; + encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedContent == NULL) { + if (aadBuffer) + XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* encrypt content */ + ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek, + pkcs7->cekSz, nonce, nonceSz, aadBuffer, aadBufferSz, authTag, + sizeof(authTag), pkcs7->content, encryptedOutSz, encryptedContent); + + if (aadBuffer) { + XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + aadBuffer = NULL; + } + + if (ret != 0) { + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } /* EncryptedContentInfo */ - contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType); - if (contentTypeSz == 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); -#endif - return BAD_FUNC_ARG; + ret = wc_SetContentType(pkcs7->contentOID, contentType, + sizeof(contentType)); + if (ret < 0) { + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; } - /* allocate encrypted content buffer, pad if necessary, PKCS#7 padding */ - padSz = DES_BLOCK_SIZE - (pkcs7->contentSz % DES_BLOCK_SIZE); - desOutSz = pkcs7->contentSz + padSz; + contentTypeSz = ret; - if (padSz != 0) { - plain = (byte*)XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (plain == NULL) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); -#endif - return MEMORY_E; - } - XMEMCPY(plain, pkcs7->content, pkcs7->contentSz); - dynamicFlag = 1; + /* put together nonce OCTET STRING */ + nonceOctetStringSz = SetOctetString(nonceSz, nonceOctetString); - for (i = 0; i < padSz; i++) { - plain[pkcs7->contentSz + i] = padSz; - } - - } else { - plain = pkcs7->content; - desOutSz = pkcs7->contentSz; - } - - encryptedContent = (byte*)XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (encryptedContent == NULL) { - if (dynamicFlag) - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); -#endif - return MEMORY_E; - } - - /* put together IV OCTET STRING */ - ivOctetStringSz = SetOctetString(DES_BLOCK_SIZE, ivOctetString); + /* put together aes-ICVlen INTEGER */ + macIntSz = SetMyVersion(sizeof(authTag), macInt, 0); /* build up our ContentEncryptionAlgorithmIdentifier sequence, - * adding (ivOctetStringSz + DES_BLOCK_SIZE) for IV OCTET STRING */ + * adding (nonceOctetStringSz + blockSz + macIntSz) for nonce OCTET STRING + * and tag size */ contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, - blkType, ivOctetStringSz + DES_BLOCK_SIZE); + oidBlkType, nonceOctetStringSz + nonceSz + + macIntSz); if (contentEncAlgoSz == 0) { - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (dynamicFlag) - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); -#endif + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return BAD_FUNC_ARG; } - /* encrypt content */ - if (pkcs7->encryptOID == DESb) { - Des des; - - ret = wc_Des_SetKey(&des, contentKeyPlain, tmpIv, DES_ENCRYPTION); - - if (ret == 0) - wc_Des_CbcEncrypt(&des, encryptedContent, plain, desOutSz); - - if (ret != 0) { - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (dynamicFlag) - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - } - else if (pkcs7->encryptOID == DES3b) { - Des3 des3; - - ret = wc_Des3_SetKey(&des3, contentKeyPlain, tmpIv, DES_ENCRYPTION); - - if (ret == 0) - ret = wc_Des3_CbcEncrypt(&des3, encryptedContent, plain, desOutSz); - - if (ret != 0) { - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (dynamicFlag) - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - } - - encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, - desOutSz, encContentOctet); + encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz, + encContentOctet); encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + - ivOctetStringSz + DES_BLOCK_SIZE + - encContentOctetSz + desOutSz, encContentSeq); + nonceOctetStringSz + nonceSz + macIntSz + + encContentOctetSz + encryptedOutSz, + encContentSeq); + + macOctetStringSz = SetOctetString(sizeof(authTag), macOctetString); /* keep track of sizes for outer wrapper layering */ totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + - contentEncAlgoSz + ivOctetStringSz + DES_BLOCK_SIZE + - encContentOctetSz + desOutSz; + contentEncAlgoSz + nonceOctetStringSz + nonceSz + macIntSz + + encContentOctetSz + encryptedOutSz + authAttribsSz + + authAttribsSetSz + macOctetStringSz + sizeof(authTag) + + unauthAttribsSz + unauthAttribsSetSz; /* EnvelopedData */ envDataSeqSz = SetSequence(totalSz, envDataSeq); @@ -1417,12 +10836,11 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (totalSz > (int)outputSz) { WOLFSSL_MSG("Pkcs7_encrypt output buffer too small"); - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (dynamicFlag) - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); -#endif + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return BUFFER_E; } @@ -1438,8 +10856,905 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) idx += verSz; XMEMCPY(output + idx, recipSet, recipSetSz); idx += recipSetSz; - XMEMCPY(output + idx, recip, recipSz); - idx += recipSz; + /* copy in recipients from list */ + tmpRecip = pkcs7->recipList; + while (tmpRecip != NULL) { + XMEMCPY(output + idx, tmpRecip->recip, tmpRecip->recipSz); + idx += tmpRecip->recipSz; + tmpRecip = tmpRecip->next; + } + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + XMEMCPY(output + idx, encContentSeq, encContentSeqSz); + idx += encContentSeqSz; + XMEMCPY(output + idx, contentType, contentTypeSz); + idx += contentTypeSz; + XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); + idx += contentEncAlgoSz; + XMEMCPY(output + idx, nonceOctetString, nonceOctetStringSz); + idx += nonceOctetStringSz; + XMEMCPY(output + idx, nonce, nonceSz); + idx += nonceSz; + XMEMCPY(output + idx, macInt, macIntSz); + idx += macIntSz; + XMEMCPY(output + idx, encContentOctet, encContentOctetSz); + idx += encContentOctetSz; + XMEMCPY(output + idx, encryptedContent, encryptedOutSz); + idx += encryptedOutSz; + + /* authenticated attributes */ + if (flatAuthAttribs && authAttribsSz > 0) { + XMEMCPY(output + idx, authAttribSet, authAttribsSetSz); + idx += authAttribsSetSz; + XMEMCPY(output + idx, flatAuthAttribs, authAttribsSz); + idx += authAttribsSz; + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + + XMEMCPY(output + idx, macOctetString, macOctetStringSz); + idx += macOctetStringSz; + XMEMCPY(output + idx, authTag, sizeof(authTag)); + idx += sizeof(authTag); + + /* unauthenticated attributes */ + if (unauthAttribsSz > 0) { + XMEMCPY(output + idx, unauthAttribSet, unauthAttribsSetSz); + idx += unauthAttribsSetSz; + XMEMCPY(output + idx, flatUnauthAttribs, unauthAttribsSz); + idx += unauthAttribsSz; + } + + if (flatUnauthAttribs != NULL) { + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + return idx; + +#else + WOLFSSL_MSG("AuthEnvelopedData requires AES-GCM or AES-CCM to be enabled"); + (void)pkcs7; + (void)output; + (void)outputSz; + + return NOT_COMPILED_IN; +#endif /* HAVE_AESGCM | HAVE_AESCCM */ +} + + +/* unwrap and decrypt PKCS#7 AuthEnvelopedData object, return decoded size */ +WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, + word32 inSz, byte* output, + word32 outputSz) +{ +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + int recipFound = 0; + int ret = 0, length; + word32 idx = 0; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = 0; + long rc; +#endif + word32 contentType, encOID = 0; + word32 decryptedKeySz = 0; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + + int expBlockSz = 0, blockKeySz = 0; + byte authTag[AES_BLOCK_SIZE]; + byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */ + int nonceSz = 0, authTagSz = 0, macSz = 0; + +#ifdef WOLFSSL_SMALL_STACK + byte* decryptedKey = NULL; +#else + byte decryptedKey[MAX_ENCRYPTED_KEY_SZ]; +#endif + int encryptedContentSz = 0; + byte* encryptedContent = NULL; + int explicitOctet = 0; + + byte authAttribSetByte = 0; + byte* encodedAttribs = NULL; + word32 encodedAttribIdx = 0, encodedAttribSz = 0; + byte* authAttrib = NULL; + int authAttribSz = 0; + word32 localIdx; + byte tag; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + if (pkiMsg == NULL || pkiMsgSz == 0 || + output == NULL || outputSz == 0) + return BAD_FUNC_ARG; +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } + } +#endif + + switch (pkcs7->state) { + case WC_PKCS7_START: + case WC_PKCS7_INFOSET_START: + case WC_PKCS7_INFOSET_STAGE1: + case WC_PKCS7_INFOSET_STAGE2: + case WC_PKCS7_INFOSET_END: + ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, + &idx, AUTH_ENVELOPED_DATA); + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + tmpIdx = idx; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_2); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_2: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { + break; + } + #endif + #ifdef WOLFSSL_SMALL_STACK + decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (decryptedKey == NULL) { + ret = MEMORY_E; + break; + } + #ifndef NO_PKCS7_STREAM + pkcs7->stream->key = decryptedKey; + #endif + #endif + FALL_THROUGH; + + case WC_PKCS7_DECRYPT_KTRI: + case WC_PKCS7_DECRYPT_KTRI_2: + case WC_PKCS7_DECRYPT_KTRI_3: + case WC_PKCS7_DECRYPT_KARI: + case WC_PKCS7_DECRYPT_KEKRI: + case WC_PKCS7_DECRYPT_PWRI: + case WC_PKCS7_DECRYPT_ORI: + + decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + #ifdef WOLFSSL_SMALL_STACK + #ifndef NO_PKCS7_STREAM + decryptedKey = pkcs7->stream->key; + #endif + #endif + + ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx, + decryptedKey, &decryptedKeySz, + &recipFound); + if (ret != 0) { + break; + } + + if (recipFound == 0) { + WOLFSSL_MSG("No recipient found in envelopedData that matches input"); + ret = PKCS7_RECIP_E; + break; + } + + #ifndef NO_PKCS7_STREAM + tmpIdx = idx; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_3); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_3: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_ALGO_SZ + MAX_ALGO_SZ + ASN_TAG_SZ, + &pkiMsg, &idx)) != 0) { + break; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + + /* remove EncryptedContentInfo */ + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, + pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, + pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); + if (ret == 0 && blockKeySz < 0) { + ret = blockKeySz; + } + + expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); + if (ret == 0 && expBlockSz < 0) { + ret = expBlockSz; + } + + /* get nonce, stored in OPTIONAL parameter of AlgoID */ + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && tag != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + } + + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, 0); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_4); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_4: + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + MAX_VERSION_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ, + &pkiMsg, &idx)) != 0) { + break; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + if (ret == 0 && GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && nonceSz > (int)sizeof(nonce)) { + WOLFSSL_MSG("AuthEnvelopedData nonce too large for buffer"); + ret = ASN_PARSE_E; + } + + if (ret == 0) { + XMEMCPY(nonce, &pkiMsg[idx], nonceSz); + idx += nonceSz; + } + + /* get mac size, also stored in OPTIONAL parameter of AlgoID */ + if (ret == 0 && GetMyVersion(pkiMsg, &idx, &macSz, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0) { + explicitOctet = 0; + localIdx = idx; + if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) + explicitOctet = 1; + + /* read encryptedContent, cont[0] */ + ret = GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz); + } + + if (ret == 0 && + tag != (ASN_CONTEXT_SPECIFIC | 0) && + tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + } + + if (explicitOctet) { + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + if (ret == 0 && tag != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + } + } + + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + + /* store nonce for later */ + if (nonceSz > 0) { + pkcs7->stream->nonceSz = nonceSz; + pkcs7->stream->nonce = (byte*)XMALLOC(nonceSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->nonce == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->nonce, nonce, nonceSz); + } + } + + pkcs7->stream->expected = encryptedContentSz; + wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, + encryptedContentSz); + #endif + + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_5); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_5: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + ASN_TAG_SZ + ASN_TAG_SZ + pkcs7->stream->expected, + &pkiMsg, &idx)) != 0) { + break; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + encryptedContentSz = pkcs7->stream->expected; + #endif + + encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (ret == 0 && encryptedContent == NULL) { + ret = MEMORY_E; + } + + if (ret == 0) { + XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); + idx += encryptedContentSz; + } + #ifndef NO_PKCS7_STREAM + pkcs7->stream->bufferPt = encryptedContent; + #endif + + /* may have IMPLICIT [1] authenticatedAttributes */ + localIdx = idx; + if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + encodedAttribIdx = idx; + encodedAttribs = pkiMsg + idx; + idx++; + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->expected = length; + #endif + encodedAttribSz = length + (idx - encodedAttribIdx); + + if (ret != 0) + break; + + #ifndef NO_PKCS7_STREAM + if (encodedAttribSz > 0) { + pkcs7->stream->aadSz = encodedAttribSz; + pkcs7->stream->aad = (byte*)XMALLOC(encodedAttribSz, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->aad == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->aad, encodedAttribs, + (idx - encodedAttribIdx)); + } + } + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRB); + } + else { + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + #endif + goto authenv_atrbend; /* jump over attribute cases */ + } + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_ATRB: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + length = pkcs7->stream->expected; + encodedAttribs = pkcs7->stream->aad; + #else + length = 0; + #endif + + /* save pointer and length */ + authAttrib = &pkiMsg[idx]; + authAttribSz = length; + + if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, authAttrib, authAttribSz) < 0) { + WOLFSSL_MSG("Error parsing authenticated attributes"); + ret = ASN_PARSE_E; + break; + } + + idx += length; + + #ifndef NO_PKCS7_STREAM + if (encodedAttribSz > 0) { + XMEMCPY(pkcs7->stream->aad + (encodedAttribSz - length), + authAttrib, authAttribSz); + } + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRBEND); + FALL_THROUGH; + +authenv_atrbend: + case WC_PKCS7_AUTHENV_ATRBEND: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + if (pkcs7->stream->aadSz > 0) { + encodedAttribSz = pkcs7->stream->aadSz; + encodedAttribs = pkcs7->stream->aad; + } + #endif + + + /* get authTag OCTET STRING */ + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + if (ret == 0 && tag != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, &authTagSz, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && authTagSz > (int)sizeof(authTag)) { + WOLFSSL_MSG("AuthEnvelopedData authTag too large for buffer"); + ret = ASN_PARSE_E; + } + + if (ret == 0) { + XMEMCPY(authTag, &pkiMsg[idx], authTagSz); + idx += authTagSz; + } + + if (ret == 0 && authAttrib != NULL) { + /* temporarily swap authAttribs byte[0] to SET OF instead of + * IMPLICIT [1], for aad calculation */ + authAttribSetByte = encodedAttribs[0]; + + encodedAttribs[0] = ASN_SET | ASN_CONSTRUCTED; + } + + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + + + /* store tag for later */ + if (authTagSz > 0) { + pkcs7->stream->tagSz = authTagSz; + pkcs7->stream->tag = (byte*)XMALLOC(authTagSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->tag == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->tag, authTag, authTagSz); + } + } + + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_6); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_6: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + break; + } + + /* restore all variables needed */ + if (pkcs7->stream->nonceSz > 0) { + nonceSz = pkcs7->stream->nonceSz; + if (nonceSz > GCM_NONCE_MID_SZ) { + WOLFSSL_MSG("PKCS7 saved nonce is too large"); + ret = BUFFER_E; + break; + } + else { + XMEMCPY(nonce, pkcs7->stream->nonce, nonceSz); + } + } + + if (pkcs7->stream->tagSz > 0) { + authTagSz = pkcs7->stream->tagSz; + if (authTagSz > AES_BLOCK_SIZE) { + WOLFSSL_MSG("PKCS7 saved tag is too large"); + ret = BUFFER_E; + break; + } + else { + XMEMCPY(authTag, pkcs7->stream->tag, authTagSz); + } + } + + if (pkcs7->stream->aadSz > 0) { + encodedAttribSz = pkcs7->stream->aadSz; + encodedAttribs = pkcs7->stream->aad; + } + + wc_PKCS7_StreamGetVar(pkcs7, &encOID, &blockKeySz, + &encryptedContentSz); + encryptedContent = pkcs7->stream->bufferPt; + #ifdef WOLFSSL_SMALL_STACK + decryptedKey = pkcs7->stream->key; + #endif + #endif + + /* decrypt encryptedContent */ + ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey, + blockKeySz, nonce, nonceSz, encodedAttribs, encodedAttribSz, + authTag, authTagSz, encryptedContent, encryptedContentSz, + encryptedContent); + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + if (authAttrib != NULL) { + /* restore authAttrib IMPLICIT [1] */ + encodedAttribs[0] = authAttribSetByte; + } + + /* copy plaintext to output */ + XMEMCPY(output, encryptedContent, encryptedContentSz); + + /* free memory, zero out keys */ + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); + #ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + decryptedKey = NULL; + #ifdef WOLFSSL_SMALL_STACK + #ifndef NO_PKCS7_STREAM + pkcs7->stream->key = NULL; + #endif + #endif + #endif + ret = encryptedContentSz; + #ifndef NO_PKCS7_STREAM + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + break; + default: + WOLFSSL_MSG("Unknown PKCS7 state"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + if (decryptedKey != NULL) { + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); + } + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } +#endif +#ifndef NO_PKCS7_STREAM + if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + wc_PKCS7_ResetStream(pkcs7); + } +#endif + + return ret; + +#else + WOLFSSL_MSG("AuthEnvelopedData requires AES-GCM or AES-CCM to be enabled"); + (void)pkcs7; + (void)in; + (void)inSz; + (void)output; + (void)outputSz; + + return NOT_COMPILED_IN; +#endif /* HAVE_AESGCM | HAVE_AESCCM */ +} + + +#ifndef NO_PKCS7_ENCRYPTED_DATA + +/* build PKCS#7 encryptedData content type, return encrypted size */ +int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) +{ + int ret, idx = 0; + int totalSz, padSz, encryptedOutSz; + + int contentInfoSeqSz, outerContentTypeSz, outerContentSz; + byte contentInfoSeq[MAX_SEQ_SZ]; + byte outerContentType[MAX_ALGO_SZ]; + byte outerContent[MAX_SEQ_SZ]; + + int encDataSeqSz, verSz, blockSz; + byte encDataSeq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + + byte* plain = NULL; + byte* encryptedContent = NULL; + + int encContentOctetSz, encContentSeqSz, contentTypeSz; + int contentEncAlgoSz, ivOctetStringSz; + byte encContentSeq[MAX_SEQ_SZ]; + byte contentType[MAX_OID_SZ]; + byte contentEncAlgo[MAX_ALGO_SZ]; + byte tmpIv[MAX_CONTENT_IV_SIZE]; + byte ivOctetString[MAX_OCTET_STR_SZ]; + byte encContentOctet[MAX_OCTET_STR_SZ]; + + byte attribSet[MAX_SET_SZ]; + EncodedAttrib* attribs = NULL; + word32 attribsSz; + word32 attribsCount; + word32 attribsSetSz; + + byte* flatAttribs = NULL; + + if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || + pkcs7->encryptOID == 0 || pkcs7->encryptionKey == NULL || + pkcs7->encryptionKeySz == 0) + return BAD_FUNC_ARG; + + if (output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + + if (pkcs7->version == 3) { + verSz = SetMyVersion(0, ver, 0); + outerContentTypeSz = 0; + } + else { + /* outer content type */ + ret = wc_SetContentType(ENCRYPTED_DATA, outerContentType, + sizeof(outerContentType)); + if (ret < 0) + return ret; + + outerContentTypeSz = ret; + + /* version, 2 if unprotectedAttrs present, 0 if absent */ + if (pkcs7->unprotectedAttribsSz > 0) { + verSz = SetMyVersion(2, ver, 0); + } else { + verSz = SetMyVersion(0, ver, 0); + } + } + + /* EncryptedContentInfo */ + ret = wc_SetContentType(pkcs7->contentOID, contentType, + sizeof(contentType)); + if (ret < 0) + return ret; + + contentTypeSz = ret; + + /* allocate encrypted content buffer, do PKCS#7 padding */ + blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); + if (blockSz < 0) + return blockSz; + + padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz); + if (padSz < 0) + return padSz; + + encryptedOutSz = pkcs7->contentSz + padSz; + + plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (plain == NULL) + return MEMORY_E; + + ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain, + encryptedOutSz, blockSz); + if (ret < 0) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedContent == NULL) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* put together IV OCTET STRING */ + ivOctetStringSz = SetOctetString(blockSz, ivOctetString); + + /* build up ContentEncryptionAlgorithmIdentifier sequence, + adding (ivOctetStringSz + blockSz) for IV OCTET STRING */ + contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, + oidBlkType, ivOctetStringSz + blockSz); + if (contentEncAlgoSz == 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + + /* encrypt content */ + WOLFSSL_MSG("Encrypting the content"); + ret = wc_PKCS7_GenerateBlock(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, NULL, 0, NULL, 0, + plain, encryptedOutSz, encryptedContent); + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, + encryptedOutSz, encContentOctet); + + encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + + ivOctetStringSz + blockSz + + encContentOctetSz + encryptedOutSz, + encContentSeq); + + /* optional UnprotectedAttributes */ + if (pkcs7->unprotectedAttribsSz != 0) { + + if (pkcs7->unprotectedAttribs == NULL) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + + attribs = (EncodedAttrib*)XMALLOC( + sizeof(EncodedAttrib) * pkcs7->unprotectedAttribsSz, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (attribs == NULL) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + attribsCount = pkcs7->unprotectedAttribsSz; + attribsSz = EncodeAttributes(attribs, pkcs7->unprotectedAttribsSz, + pkcs7->unprotectedAttribs, + pkcs7->unprotectedAttribsSz); + + flatAttribs = (byte*)XMALLOC(attribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (flatAttribs == NULL) { + XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + FlattenAttributes(pkcs7, flatAttribs, attribs, attribsCount); + attribsSetSz = SetImplicit(ASN_SET, 1, attribsSz, attribSet); + + } else { + attribsSz = 0; + attribsSetSz = 0; + } + + /* keep track of sizes for outer wrapper layering */ + totalSz = verSz + encContentSeqSz + contentTypeSz + contentEncAlgoSz + + ivOctetStringSz + blockSz + encContentOctetSz + encryptedOutSz + + attribsSz + attribsSetSz; + + /* EncryptedData */ + encDataSeqSz = SetSequence(totalSz, encDataSeq); + totalSz += encDataSeqSz; + + if (pkcs7->version != 3) { + /* outer content */ + outerContentSz = SetExplicit(0, totalSz, outerContent); + totalSz += outerContentTypeSz; + totalSz += outerContentSz; + /* ContentInfo */ + contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); + totalSz += contentInfoSeqSz; + } else { + contentInfoSeqSz = 0; + outerContentSz = 0; + } + + if (totalSz > (int)outputSz) { + WOLFSSL_MSG("PKCS#7 output buffer too small"); + if (pkcs7->unprotectedAttribsSz != 0) { + 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); + return BUFFER_E; + } + + XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); + idx += contentInfoSeqSz; + XMEMCPY(output + idx, outerContentType, outerContentTypeSz); + idx += outerContentTypeSz; + XMEMCPY(output + idx, outerContent, outerContentSz); + idx += outerContentSz; + XMEMCPY(output + idx, encDataSeq, encDataSeqSz); + idx += encDataSeqSz; + XMEMCPY(output + idx, ver, verSz); + idx += verSz; XMEMCPY(output + idx, encContentSeq, encContentSeqSz); idx += encContentSeqSz; XMEMCPY(output + idx, contentType, contentTypeSz); @@ -1448,402 +11763,752 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) idx += contentEncAlgoSz; XMEMCPY(output + idx, ivOctetString, ivOctetStringSz); idx += ivOctetStringSz; - XMEMCPY(output + idx, tmpIv, DES_BLOCK_SIZE); - idx += DES_BLOCK_SIZE; + XMEMCPY(output + idx, tmpIv, blockSz); + idx += blockSz; XMEMCPY(output + idx, encContentOctet, encContentOctetSz); idx += encContentOctetSz; - XMEMCPY(output + idx, encryptedContent, desOutSz); - idx += desOutSz; + XMEMCPY(output + idx, encryptedContent, encryptedOutSz); + idx += encryptedOutSz; - ForceZero(contentKeyPlain, MAX_CONTENT_KEY_LEN); + if (pkcs7->unprotectedAttribsSz != 0) { + XMEMCPY(output + idx, attribSet, attribsSetSz); + idx += attribsSetSz; + XMEMCPY(output + idx, flatAttribs, attribsSz); + idx += attribsSz; + XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } - if (dynamicFlag) - XFREE(plain, NULL, DYNAMMIC_TYPE_TMP_BUFFER); - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); -#endif + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return idx; } -/* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */ -WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, - word32 pkiMsgSz, byte* output, - word32 outputSz) + +/* decode and store unprotected attributes in PKCS7->decodedAttrib. Return + * 0 on success, negative on error. User must call wc_PKCS7_Free(). */ +static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg, + word32 pkiMsgSz, word32* inOutIdx) { - int recipFound = 0; - int ret, version, length; - word32 savedIdx = 0, idx = 0; - word32 contentType, encOID; - byte issuerHash[SHA_DIGEST_SIZE]; + int ret, attribLen; + word32 idx; + byte tag; - int encryptedKeySz, keySz; - byte tmpIv[DES_BLOCK_SIZE]; - byte* decryptedKey = NULL; + if (pkcs7 == NULL || pkiMsg == NULL || + pkiMsgSz == 0 || inOutIdx == NULL) + return BAD_FUNC_ARG; -#ifdef WOLFSSL_SMALL_STACK - mp_int* serialNum; - byte* encryptedKey; - RsaKey* privKey; -#else - mp_int stack_serialNum; - mp_int* serialNum = &stack_serialNum; - byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; - - RsaKey stack_privKey; - RsaKey* privKey = &stack_privKey; + idx = *inOutIdx; + + if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &attribLen, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* loop through attributes */ + if ((ret = wc_PKCS7_ParseAttribs(pkcs7, pkiMsg + idx, attribLen)) < 0) { + return ret; + } + + *inOutIdx = idx; + + return 0; +} + + +/* unwrap and decrypt PKCS#7/CMS encrypted-data object, returned decoded size */ +int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, + byte* output, word32 outputSz) +{ + int ret = 0, version, length = 0, haveAttribs = 0; + word32 idx = 0; + +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = 0; + long rc; #endif - int encryptedContentSz; + word32 contentType, encOID; + + int expBlockSz = 0; + byte tmpIvBuf[MAX_CONTENT_IV_SIZE]; + byte *tmpIv = tmpIvBuf; + + int encryptedContentSz = 0; byte padLen; byte* encryptedContent = NULL; - if (pkcs7 == NULL || pkcs7->singleCert == NULL || - pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL || - pkcs7->privateKeySz == 0) + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + byte tag; + + if (pkcs7 == NULL || + ((pkcs7->encryptionKey == NULL || pkcs7->encryptionKeySz == 0) && + pkcs7->decryptionCb == NULL)) return BAD_FUNC_ARG; if (pkiMsg == NULL || pkiMsgSz == 0 || output == NULL || outputSz == 0) return BAD_FUNC_ARG; - /* read past ContentInfo, verify type is envelopedData */ +#ifndef NO_PKCS7_STREAM + (void)tmpIv; /* help out static analysis */ + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } + } +#endif + + switch (pkcs7->state) { + case WC_PKCS7_START: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_ALGO_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; +#endif + + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (pkcs7->version != 3) { /* ContentInfo not in firmware bundles */ + /* read past ContentInfo, verify type is encrypted-data */ + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, + pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && contentType != ENCRYPTED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type EncryptedData"); + ret = PKCS7_OID_E; + } + } + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } +#endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE2); + FALL_THROUGH; + /* end of stage 1 */ + + case WC_PKCS7_STAGE2: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + MAX_LENGTH_SZ + MAX_SEQ_SZ + ASN_TAG_SZ, &pkiMsg, + &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; +#endif + if (pkcs7->version != 3) { + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + /* remove EncryptedData and version */ + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + } + + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } +#endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE3); + FALL_THROUGH; + /* end of stage 2 */ + + case WC_PKCS7_STAGE3: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_ALGO_SZ * 2, + &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; +#endif + /* get version, check later */ + haveAttribs = 0; + if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + /* remove EncryptedContentInfo */ + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, + pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && (ret = GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, + pkiMsgSz)) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && (expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID)) < 0) + ret = expBlockSz; + + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + /* store expBlockSz for later */ + pkcs7->stream->varOne = expBlockSz; + pkcs7->stream->varTwo = encOID; + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + + /* store version for later */ + pkcs7->stream->vers = version; +#endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE4); + FALL_THROUGH; + /* end of stage 3 */ + + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ + case WC_PKCS7_STAGE4: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + /* restore saved variables */ + expBlockSz = pkcs7->stream->varOne; +#endif + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && length != expBlockSz) { + WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); + ret = ASN_PARSE_E; + } + + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + /* next chunk of data expected should have the IV */ + pkcs7->stream->expected = length; + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } +#endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE5); + FALL_THROUGH; + /* end of stage 4 */ + + case WC_PKCS7_STAGE5: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected + ASN_TAG_SZ + + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + /* use IV buffer from stream structure */ + tmpIv = pkcs7->stream->tmpIv; + length = pkcs7->stream->expected; +#endif + XMEMCPY(tmpIv, &pkiMsg[idx], length); + idx += length; + /* read encryptedContent, cont[0] */ + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != (ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) + ret = ASN_PARSE_E; + + if (ret < 0) + break; +#ifndef NO_PKCS7_STREAM + /* next chunk of data should contain encrypted content */ + pkcs7->stream->varThree = encryptedContentSz; + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + + if (pkcs7->stream->totalRd + encryptedContentSz < pkiMsgSz) { + pkcs7->stream->flagOne = 1; + } + + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + +#endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE6); + FALL_THROUGH; + /* end of stage 5 */ + + case WC_PKCS7_STAGE6: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + /* restore saved variables */ + expBlockSz = pkcs7->stream->varOne; + encOID = pkcs7->stream->varTwo; + encryptedContentSz = pkcs7->stream->varThree; + version = pkcs7->stream->vers; + tmpIv = pkcs7->stream->tmpIv; +#else + encOID = 0; +#endif + if (ret == 0 && (encryptedContent = (byte*)XMALLOC( + encryptedContentSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7)) == NULL) { + ret = MEMORY_E; + break; + } + + if (ret == 0) { + XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); + idx += encryptedContentSz; + + /* decrypt encryptedContent */ + ret = wc_PKCS7_DecryptContent(pkcs7, encOID, + pkcs7->encryptionKey, pkcs7->encryptionKeySz, tmpIv, + expBlockSz, NULL, 0, NULL, 0, encryptedContent, + encryptedContentSz, encryptedContent); + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + } + + if (ret == 0) { + padLen = encryptedContent[encryptedContentSz-1]; + + if (padLen > encryptedContentSz) { + WOLFSSL_MSG("Bad padding size found"); + ret = BUFFER_E; + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + break; + } + + /* copy plaintext to output */ + XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); + + /* get implicit[1] unprotected attributes, optional */ + wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); + pkcs7->decodedAttrib = NULL; + #ifndef NO_PKCS7_STREAM + if (pkcs7->stream->flagOne) + #else + if (idx < pkiMsgSz) + #endif + { + haveAttribs = 1; + + ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg, + pkiMsgSz, &idx); + if (ret != 0) { + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + ret = ASN_PARSE_E; + } + } + } + + if (ret == 0) { + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + /* go back and check the version now that attribs have been processed */ + if (pkcs7->version == 3 && version != 0) { + WOLFSSL_MSG("Wrong PKCS#7 FirmwareEncryptedData version"); + return ASN_VERSION_E; + } + + if (pkcs7->version != 3 && + ((haveAttribs == 0 && version != 0) || + (haveAttribs == 1 && version != 2))) { + WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version"); + return ASN_VERSION_E; + } + ret = encryptedContentSz - padLen; + } + + if (ret != 0) break; + #ifndef NO_PKCS7_STREAM + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + break; + + default: + WOLFSSL_MSG("Error in unknown PKCS#7 Decode Encrypted Data state"); + return BAD_STATE_E; + } + + if (ret != 0) { + #ifndef NO_PKCS7_STREAM + /* restart in error case */ + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + } + return ret; +} + + +/* Function to set callback during decryption, this overrides the default + * decryption function and can be used for choosing a key at run time based + * on the parsed bundle so far. + * returns 0 on success + */ +int wc_PKCS7_SetDecodeEncryptedCb(PKCS7* pkcs7, + CallbackDecryptContent decryptionCb) +{ + if (pkcs7 != NULL) { + pkcs7->decryptionCb = decryptionCb; + } + return 0; +} + + +/* Set an optional user context that gets passed to callback + * returns 0 on success + */ +int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx) +{ + if (pkcs7 != NULL) { + pkcs7->decryptionCtx = ctx; + } + return 0; +} +#endif /* NO_PKCS7_ENCRYPTED_DATA */ + +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + +/* build PKCS#7 compressedData content type, return encrypted size */ +int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz) +{ + byte contentInfoSeq[MAX_SEQ_SZ]; + byte contentInfoTypeOid[MAX_OID_SZ]; + byte contentInfoContentSeq[MAX_SEQ_SZ]; /* EXPLICIT [0] */ + byte compressedDataSeq[MAX_SEQ_SZ]; + byte cmsVersion[MAX_VERSION_SZ]; + byte compressAlgId[MAX_ALGO_SZ]; + byte encapContentInfoSeq[MAX_SEQ_SZ]; + byte contentTypeOid[MAX_OID_SZ]; + byte contentSeq[MAX_SEQ_SZ]; /* EXPLICIT [0] */ + byte contentOctetStr[MAX_OCTET_STR_SZ]; + + int ret; + word32 totalSz, idx; + word32 contentInfoSeqSz, contentInfoContentSeqSz, contentInfoTypeOidSz; + word32 compressedDataSeqSz, cmsVersionSz, compressAlgIdSz; + word32 encapContentInfoSeqSz, contentTypeOidSz, contentSeqSz; + word32 contentOctetStrSz; + + byte* compressed; + word32 compressedSz; + + if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || + output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* allocate space for compressed content. The libz code says the compressed + * buffer should be srcSz + 0.1% + 12. */ + compressedSz = (pkcs7->contentSz + (word32)(pkcs7->contentSz * 0.001) + 12); + compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (compressed == NULL) { + WOLFSSL_MSG("Error allocating memory for CMS compressed content"); + return MEMORY_E; + } + + /* compress content */ + ret = wc_Compress(compressed, compressedSz, pkcs7->content, + pkcs7->contentSz, 0); + if (ret < 0) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + compressedSz = (word32)ret; + + /* eContent OCTET STRING, working backwards */ + contentOctetStrSz = SetOctetString(compressedSz, contentOctetStr); + totalSz = contentOctetStrSz + compressedSz; + + /* EXPLICIT [0] eContentType */ + contentSeqSz = SetExplicit(0, totalSz, contentSeq); + totalSz += contentSeqSz; + + /* eContentType OBJECT IDENTIFIER */ + ret = wc_SetContentType(pkcs7->contentOID, contentTypeOid, + sizeof(contentTypeOid)); + if (ret < 0) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + contentTypeOidSz = ret; + totalSz += contentTypeOidSz; + + /* EncapsulatedContentInfo SEQUENCE */ + encapContentInfoSeqSz = SetSequence(totalSz, encapContentInfoSeq); + totalSz += encapContentInfoSeqSz; + + /* compressionAlgorithm AlgorithmIdentifier */ + /* Only supports zlib for compression currently: + * id-alg-zlibCompress (1.2.840.113549.1.9.16.3.8) */ + compressAlgIdSz = SetAlgoID(ZLIBc, compressAlgId, oidCompressType, 0); + totalSz += compressAlgIdSz; + + /* version */ + cmsVersionSz = SetMyVersion(0, cmsVersion, 0); + totalSz += cmsVersionSz; + + /* CompressedData SEQUENCE */ + compressedDataSeqSz = SetSequence(totalSz, compressedDataSeq); + totalSz += compressedDataSeqSz; + + /* ContentInfo content EXPLICIT SEQUENCE */ + contentInfoContentSeqSz = SetExplicit(0, totalSz, contentInfoContentSeq); + totalSz += contentInfoContentSeqSz; + + /* ContentInfo ContentType (compressedData) */ + if (pkcs7->version == 3) { + contentInfoTypeOidSz = 0; + } + else { + ret = wc_SetContentType(COMPRESSED_DATA, contentInfoTypeOid, + sizeof(contentInfoTypeOid)); + if (ret < 0) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + contentInfoTypeOidSz = ret; + totalSz += contentInfoTypeOidSz; + } + + /* ContentInfo SEQUENCE */ + contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); + totalSz += contentInfoSeqSz; + + if (outputSz < totalSz) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + idx = 0; + XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); + idx += contentInfoSeqSz; + XMEMCPY(output + idx, contentInfoTypeOid, contentInfoTypeOidSz); + idx += contentInfoTypeOidSz; + XMEMCPY(output + idx, contentInfoContentSeq, contentInfoContentSeqSz); + idx += contentInfoContentSeqSz; + XMEMCPY(output + idx, compressedDataSeq, compressedDataSeqSz); + idx += compressedDataSeqSz; + XMEMCPY(output + idx, cmsVersion, cmsVersionSz); + idx += cmsVersionSz; + XMEMCPY(output + idx, compressAlgId, compressAlgIdSz); + idx += compressAlgIdSz; + XMEMCPY(output + idx, encapContentInfoSeq, encapContentInfoSeqSz); + idx += encapContentInfoSeqSz; + XMEMCPY(output + idx, contentTypeOid, contentTypeOidSz); + idx += contentTypeOidSz; + XMEMCPY(output + idx, contentSeq, contentSeqSz); + idx += contentSeqSz; + XMEMCPY(output + idx, contentOctetStr, contentOctetStrSz); + idx += contentOctetStrSz; + XMEMCPY(output + idx, compressed, compressedSz); + idx += compressedSz; + + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + return idx; +} + +/* unwrap and decompress PKCS#7/CMS compressedData object, + * returned decoded size */ +int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, + byte* output, word32 outputSz) +{ + int length, version, ret; + word32 idx = 0, algOID, contentType; + byte tag; + + byte* decompressed; + word32 decompressedSz; + + if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || + output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* get ContentInfo SEQUENCE */ if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; - if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) - return ASN_PARSE_E; + if (pkcs7->version != 3) { + /* get ContentInfo contentType */ + if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) + return ASN_PARSE_E; - if (contentType != ENVELOPED_DATA) { - WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData"); - return PKCS7_OID_E; + if (contentType != COMPRESSED_DATA) + return ASN_PARSE_E; } - if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + /* get ContentInfo content EXPLICIT SEQUENCE */ + if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) return ASN_PARSE_E; if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; - /* remove EnvelopedData and version */ + /* get CompressedData SEQUENCE */ if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; - if (GetMyVersion(pkiMsg, &idx, &version) < 0) + /* get version */ + if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) return ASN_PARSE_E; if (version != 0) { - WOLFSSL_MSG("PKCS#7 envelopedData needs to be of version 0"); - return ASN_VERSION_E; - } - - /* walk through RecipientInfo set, find correct recipient */ - if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - -#ifdef WOLFSSL_SMALL_STACK - encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encryptedKey == NULL) - return MEMORY_E; -#endif - - savedIdx = idx; - recipFound = 0; - - /* when looking for next recipient, use first sequence and version to - * indicate there is another, if not, move on */ - while(recipFound == 0) { - - /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to - * last good saved one */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { - idx = savedIdx; - break; - } - - if (GetMyVersion(pkiMsg, &idx, &version) < 0) { - idx = savedIdx; - break; - } - - if (version != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_VERSION_E; - } - - /* remove IssuerAndSerialNumber */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (GetNameHash(pkiMsg, &idx, issuerHash, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - /* if we found correct recipient, issuer hashes will match */ - if (XMEMCMP(issuerHash, pkcs7->issuerHash, SHA_DIGEST_SIZE) == 0) { - recipFound = 1; - } - -#ifdef WOLFSSL_SMALL_STACK - serialNum = (mp_int*)XMALLOC(sizeof(mp_int), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (serialNum == NULL) { - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - if (GetInt(serialNum, pkiMsg, &idx, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(serialNum, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - mp_clear(serialNum); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(serialNum, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - /* key encryption algorithm must be RSA for now */ - if (encOID != RSAk) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ALGO_ID_E; - } - - /* read encryptedKey */ - if (pkiMsg[idx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (GetLength(pkiMsg, &idx, &encryptedKeySz, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (recipFound == 1) - XMEMCPY(encryptedKey, &pkiMsg[idx], encryptedKeySz); - idx += encryptedKeySz; - - /* update good idx */ - savedIdx = idx; - } - - if (recipFound == 0) { - WOLFSSL_MSG("No recipient found in envelopedData that matches input"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return PKCS7_RECIP_E; - } - - /* remove EncryptedContentInfo */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + WOLFSSL_MSG("CMS CompressedData version MUST be 0, but is not"); return ASN_PARSE_E; } - if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* get CompressionAlgorithmIdentifier */ + if (GetAlgoId(pkiMsg, &idx, &algOID, oidIgnoreType, pkiMsgSz) < 0) return ASN_PARSE_E; - } - - /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ - if (pkiMsg[idx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (length != DES_BLOCK_SIZE) { - WOLFSSL_MSG("Incorrect IV length, must be of DES_BLOCK_SIZE"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + + /* Only supports zlib for compression currently: + * id-alg-zlibCompress (1.2.840.113549.1.9.16.3.8) */ + if (algOID != ZLIBc) { + WOLFSSL_MSG("CMS CompressedData only supports zlib algorithm"); return ASN_PARSE_E; } - XMEMCPY(tmpIv, &pkiMsg[idx], length); - idx += length; - - /* read encryptedContent, cont[0] */ - if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* get EncapsulatedContentInfo SEQUENCE */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; - } - if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* get ContentType OID */ + if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) return ASN_PARSE_E; - } - - encryptedContent = (byte*)XMALLOC(encryptedContentSz, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encryptedContent == NULL) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + + pkcs7->contentOID = contentType; + + /* get eContent EXPLICIT SEQUENCE */ + if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get content OCTET STRING */ + if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* allocate space for decompressed data */ + decompressed = (byte*)XMALLOC(length, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (decompressed == NULL) { + WOLFSSL_MSG("Error allocating memory for CMS decompression buffer"); return MEMORY_E; } - XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); - - /* load private key */ -#ifdef WOLFSSL_SMALL_STACK - privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (privKey == NULL) { - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; - } -#endif - - ret = wc_InitRsaKey(privKey, 0); - if (ret != 0) { - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* decompress content */ + ret = wc_DeCompress(decompressed, length, &pkiMsg[idx], length); + if (ret < 0) { + XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } + decompressedSz = (word32)ret; - idx = 0; - - ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, - pkcs7->privateKeySz); - if (ret != 0) { - WOLFSSL_MSG("Failed to decode RSA private key"); - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; + /* get content */ + if (outputSz < decompressedSz) { + WOLFSSL_MSG("CMS output buffer too small to hold decompressed data"); + XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; } - /* decrypt encryptedKey */ - keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, - &decryptedKey, privKey); - wc_FreeRsaKey(privKey); + XMEMCPY(output, decompressed, decompressedSz); + XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#ifdef WOLFSSL_SMALL_STACK - XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - if (keySz <= 0) { - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return keySz; - } - - /* decrypt encryptedContent */ - if (encOID == DESb) { - Des des; - ret = wc_Des_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION); - - if (ret == 0) - wc_Des_CbcDecrypt(&des, encryptedContent, encryptedContent, - encryptedContentSz); - - if (ret != 0) { - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - } - else if (encOID == DES3b) { - Des3 des; - ret = wc_Des3_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION); - if (ret == 0) - ret = wc_Des3_CbcDecrypt(&des, encryptedContent, encryptedContent, - encryptedContentSz); - - if (ret != 0) { - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - } else { - WOLFSSL_MSG("Unsupported content encryption OID type"); - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ALGO_ID_E; - } - - padLen = encryptedContent[encryptedContentSz-1]; - - /* copy plaintext to output */ - XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); - - /* free memory, zero out keys */ - ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ); - ForceZero(encryptedContent, encryptedContentSz); - XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return encryptedContentSz - padLen; + return decompressedSz; } +#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ #else /* HAVE_PKCS7 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/poly1305.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/poly1305.c index 3cc86e1bb..651664884 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/poly1305.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/poly1305.c @@ -1,8 +1,8 @@ /* poly1305.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,12 +16,15 @@ * * 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 - * - * Based off the public domain implementations by Andrew Moon + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* + * Based off the public domain implementations by Andrew Moon * and Daniel J. Bernstein */ + #ifdef HAVE_CONFIG_H #include #endif @@ -32,9 +35,11 @@ #include #include #include +#include #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif #ifdef CHACHA_AEAD_TEST @@ -46,222 +51,354 @@ #pragma warning(disable: 4127) #endif -#if defined(POLY130564) - - #if defined(_MSC_VER) - #define POLY1305_NOINLINE __declspec(noinline) - #elif defined(__GNUC__) - #define POLY1305_NOINLINE __attribute__((noinline)) - #else - #define POLY1305_NOINLINE - #endif - - #if defined(_MSC_VER) - #include - - typedef struct word128 { - word64 lo; - word64 hi; - } word128; - - #define MUL(out, x, y) out.lo = _umul128((x), (y), &out.hi) - #define ADD(out, in) { word64 t = out.lo; out.lo += in.lo; - out.hi += (out.lo < t) + in.hi; } - #define ADDLO(out, in) { word64 t = out.lo; out.lo += in; - out.hi += (out.lo < t); } - #define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift))) - #define LO(in) (in.lo) - - #elif defined(__GNUC__) - #if defined(__SIZEOF_INT128__) - typedef unsigned __int128 word128; - #else - typedef unsigned word128 __attribute__((mode(TI))); - #endif - - #define MUL(out, x, y) out = ((word128)x * y) - #define ADD(out, in) out += in - #define ADDLO(out, in) out += in - #define SHR(in, shift) (word64)(in >> (shift)) - #define LO(in) (word64)(in) - #endif - - static word64 U8TO64(const byte* p) { - return - (((word64)(p[0] & 0xff) ) | - ((word64)(p[1] & 0xff) << 8) | - ((word64)(p[2] & 0xff) << 16) | - ((word64)(p[3] & 0xff) << 24) | - ((word64)(p[4] & 0xff) << 32) | - ((word64)(p[5] & 0xff) << 40) | - ((word64)(p[6] & 0xff) << 48) | - ((word64)(p[7] & 0xff) << 56)); - } - - static void U64TO8(byte* p, word64 v) { - p[0] = (v ) & 0xff; - p[1] = (v >> 8) & 0xff; - p[2] = (v >> 16) & 0xff; - p[3] = (v >> 24) & 0xff; - p[4] = (v >> 32) & 0xff; - p[5] = (v >> 40) & 0xff; - p[6] = (v >> 48) & 0xff; - p[7] = (v >> 56) & 0xff; - } +#ifdef USE_INTEL_SPEEDUP + #include + #include + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #undef NO_AVX2_SUPPORT + #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__) + #define POLY1305_NOINLINE __attribute__((noinline)) + #else + #define POLY1305_NOINLINE + #endif + + #if defined(_MSC_VER) + #include + + typedef struct word128 { + word64 lo; + word64 hi; + } word128; + + #define MUL(out, x, y) out.lo = _umul128((x), (y), &out.hi) + #define ADD(out, in) { word64 t = out.lo; out.lo += in.lo; \ + out.hi += (out.lo < t) + in.hi; } + #define ADDLO(out, in) { word64 t = out.lo; out.lo += in; \ + out.hi += (out.lo < t); } + #define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift))) + #define LO(in) (in.lo) + + #elif defined(__GNUC__) + #if defined(__SIZEOF_INT128__) + typedef unsigned __int128 word128; + #else + typedef unsigned word128 __attribute__((mode(TI))); + #endif + + #define MUL(out, x, y) out = ((word128)x * y) + #define ADD(out, in) out += in + #define ADDLO(out, in) out += in + #define SHR(in, shift) (word64)(in >> (shift)) + #define LO(in) (word64)(in) + #endif +#endif + +#ifdef USE_INTEL_SPEEDUP +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef HAVE_INTEL_AVX1 +/* Process one block (16 bytes) of data. + * + * ctx Poly1305 context. + * m One block of message data. + */ +extern void poly1305_block_avx(Poly1305* ctx, const unsigned char *m); +/* Process multiple blocks (n * 16 bytes) of data. + * + * ctx Poly1305 context. + * m Blocks of message data. + * bytes The number of bytes to process. + */ +extern void poly1305_blocks_avx(Poly1305* ctx, const unsigned char* m, + size_t bytes); +/* Set the key to use when processing data. + * Initialize the context. + * + * ctx Poly1305 context. + * key The key data (16 bytes). + */ +extern void poly1305_setkey_avx(Poly1305* ctx, const byte* key); +/* Calculate the final result - authentication data. + * Zeros out the private data in the context. + * + * ctx Poly1305 context. + * mac Buffer to hold 16 bytes. + */ +extern void poly1305_final_avx(Poly1305* ctx, byte* mac); +#endif + +#ifdef HAVE_INTEL_AVX2 +/* Process multiple blocks (n * 16 bytes) of data. + * + * ctx Poly1305 context. + * m Blocks of message data. + * bytes The number of bytes to process. + */ +extern void poly1305_blocks_avx2(Poly1305* ctx, const unsigned char* m, + size_t bytes); +/* Calculate R^1, R^2, R^3 and R^4 and store them in the context. + * + * ctx Poly1305 context. + */ +extern void poly1305_calc_powers_avx2(Poly1305* ctx); +/* Set the key to use when processing data. + * Initialize the context. + * Calls AVX set key function as final function calls AVX code. + * + * ctx Poly1305 context. + * key The key data (16 bytes). + */ +extern void poly1305_setkey_avx2(Poly1305* ctx, const byte* key); +/* Calculate the final result - authentication data. + * Zeros out the private data in the context. + * Calls AVX final function to quickly process last blocks. + * + * ctx Poly1305 context. + * mac Buffer to hold 16 bytes - authentication data. + */ +extern void poly1305_final_avx2(Poly1305* ctx, byte* mac); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#elif defined(POLY130564) +#ifndef WOLFSSL_ARMASM + static word64 U8TO64(const byte* p) + { + return + (((word64)(p[0] & 0xff) ) | + ((word64)(p[1] & 0xff) << 8) | + ((word64)(p[2] & 0xff) << 16) | + ((word64)(p[3] & 0xff) << 24) | + ((word64)(p[4] & 0xff) << 32) | + ((word64)(p[5] & 0xff) << 40) | + ((word64)(p[6] & 0xff) << 48) | + ((word64)(p[7] & 0xff) << 56)); + } + + static void U64TO8(byte* p, word64 v) { + p[0] = (v ) & 0xff; + p[1] = (v >> 8) & 0xff; + p[2] = (v >> 16) & 0xff; + p[3] = (v >> 24) & 0xff; + p[4] = (v >> 32) & 0xff; + p[5] = (v >> 40) & 0xff; + p[6] = (v >> 48) & 0xff; + p[7] = (v >> 56) & 0xff; + } +#endif/* WOLFSSL_ARMASM */ #else /* if not 64 bit then use 32 bit */ - - static word32 U8TO32(const byte *p) { - return - (((word32)(p[0] & 0xff) ) | - ((word32)(p[1] & 0xff) << 8) | - ((word32)(p[2] & 0xff) << 16) | - ((word32)(p[3] & 0xff) << 24)); - } - - static void U32TO8(byte *p, word32 v) { - p[0] = (v ) & 0xff; - p[1] = (v >> 8) & 0xff; - p[2] = (v >> 16) & 0xff; - p[3] = (v >> 24) & 0xff; - } + + static word32 U8TO32(const byte *p) + { + return + (((word32)(p[0] & 0xff) ) | + ((word32)(p[1] & 0xff) << 8) | + ((word32)(p[2] & 0xff) << 16) | + ((word32)(p[3] & 0xff) << 24)); + } + + static void U32TO8(byte *p, word32 v) { + p[0] = (v ) & 0xff; + p[1] = (v >> 8) & 0xff; + p[2] = (v >> 16) & 0xff; + p[3] = (v >> 24) & 0xff; + } #endif -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 */ - word64 r0,r1,r2; - word64 s1,s2; - word64 h0,h1,h2; - word64 c; - word128 d0,d1,d2,d; - +/* convert 32-bit unsigned to little endian 64 bit type as byte array */ +static WC_INLINE void u32tole64(const word32 inLe32, byte outLe64[8]) +{ +#ifndef WOLFSSL_X86_64_BUILD + outLe64[0] = (byte)(inLe32 & 0x000000FF); + outLe64[1] = (byte)((inLe32 & 0x0000FF00) >> 8); + outLe64[2] = (byte)((inLe32 & 0x00FF0000) >> 16); + outLe64[3] = (byte)((inLe32 & 0xFF000000) >> 24); + outLe64[4] = 0; + outLe64[5] = 0; + outLe64[6] = 0; + outLe64[7] = 0; #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; - + *(word64*)outLe64 = inLe32; #endif +} -#ifdef POLY130564 + +#if !defined(WOLFSSL_ARMASM) || !defined(__aarch64__) +void poly1305_blocks(Poly1305* ctx, const unsigned char *m, + 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; r0 = ctx->r[0]; - r1 = ctx->r[1]; - r2 = ctx->r[2]; + r1 = ctx->r[1]; + r2 = ctx->r[2]; - h0 = ctx->h[0]; - h1 = ctx->h[1]; - h2 = ctx->h[2]; + h0 = ctx->h[0]; + h1 = ctx->h[1]; + h2 = ctx->h[2]; - s1 = r1 * (5 << 2); - s2 = r2 * (5 << 2); + s1 = r1 * (5 << 2); + s2 = r2 * (5 << 2); - while (bytes >= POLY1305_BLOCK_SIZE) { - word64 t0,t1; + while (bytes >= POLY1305_BLOCK_SIZE) { + word64 t0,t1; - /* h += m[i] */ - t0 = U8TO64(&m[0]); - t1 = U8TO64(&m[8]); + /* h += m[i] */ + t0 = U8TO64(&m[0]); + t1 = U8TO64(&m[8]); - h0 += (( t0 ) & 0xfffffffffff); - h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff); - h2 += (((t1 >> 24) ) & 0x3ffffffffff) | hibit; + h0 += (( t0 ) & 0xfffffffffff); + h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff); + h2 += (((t1 >> 24) ) & 0x3ffffffffff) | hibit; - /* h *= r */ - MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d); - MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d); - MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d); + /* h *= r */ + MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d); + MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d); + MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d); - /* (partial) h %= p */ - c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff; - ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff; - ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff; - h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff; - h1 += c; + /* (partial) h %= p */ + c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff; + ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff; + ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff; + h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff; + h1 += c; - m += POLY1305_BLOCK_SIZE; - bytes -= POLY1305_BLOCK_SIZE; - } + m += POLY1305_BLOCK_SIZE; + bytes -= POLY1305_BLOCK_SIZE; + } - ctx->h[0] = h0; - ctx->h[1] = h1; - ctx->h[2] = h2; + ctx->h[0] = h0; + ctx->h[1] = h1; + ctx->h[2] = h2; #else /* if not 64 bit then use 32 bit */ - - r0 = ctx->r[0]; - r1 = ctx->r[1]; - r2 = ctx->r[2]; - r3 = ctx->r[3]; - r4 = ctx->r[4]; + const word32 hibit = (ctx->finished) ? 0 : ((word32)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; - s1 = r1 * 5; - s2 = r2 * 5; - s3 = r3 * 5; - s4 = r4 * 5; - h0 = ctx->h[0]; - h1 = ctx->h[1]; - h2 = ctx->h[2]; - h3 = ctx->h[3]; - h4 = ctx->h[4]; + r0 = ctx->r[0]; + r1 = ctx->r[1]; + r2 = ctx->r[2]; + r3 = ctx->r[3]; + r4 = ctx->r[4]; - while (bytes >= POLY1305_BLOCK_SIZE) { - /* h += m[i] */ - h0 += (U8TO32(m+ 0) ) & 0x3ffffff; - h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff; - h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff; - h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff; - h4 += (U8TO32(m+12) >> 8) | hibit; + s1 = r1 * 5; + s2 = r2 * 5; + s3 = r3 * 5; + s4 = r4 * 5; - /* h *= r */ - d0 = ((word64)h0 * r0) + ((word64)h1 * s4) + ((word64)h2 * s3) + + h0 = ctx->h[0]; + h1 = ctx->h[1]; + h2 = ctx->h[2]; + h3 = ctx->h[3]; + h4 = ctx->h[4]; + + while (bytes >= POLY1305_BLOCK_SIZE) { + /* h += m[i] */ + h0 += (U8TO32(m+ 0) ) & 0x3ffffff; + h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff; + h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff; + h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff; + h4 += (U8TO32(m+12) >> 8) | hibit; + + /* h *= r */ + d0 = ((word64)h0 * r0) + ((word64)h1 * s4) + ((word64)h2 * s3) + ((word64)h3 * s2) + ((word64)h4 * s1); - d1 = ((word64)h0 * r1) + ((word64)h1 * r0) + ((word64)h2 * s4) + + d1 = ((word64)h0 * r1) + ((word64)h1 * r0) + ((word64)h2 * s4) + ((word64)h3 * s3) + ((word64)h4 * s2); - d2 = ((word64)h0 * r2) + ((word64)h1 * r1) + ((word64)h2 * r0) + + d2 = ((word64)h0 * r2) + ((word64)h1 * r1) + ((word64)h2 * r0) + ((word64)h3 * s4) + ((word64)h4 * s3); - d3 = ((word64)h0 * r3) + ((word64)h1 * r2) + ((word64)h2 * r1) + + d3 = ((word64)h0 * r3) + ((word64)h1 * r2) + ((word64)h2 * r1) + ((word64)h3 * r0) + ((word64)h4 * s4); - d4 = ((word64)h0 * r4) + ((word64)h1 * r3) + ((word64)h2 * r2) + + d4 = ((word64)h0 * r4) + ((word64)h1 * r3) + ((word64)h2 * r2) + ((word64)h3 * r1) + ((word64)h4 * r0); - /* (partial) h %= p */ - c = (word32)(d0 >> 26); h0 = (word32)d0 & 0x3ffffff; - d1 += c; c = (word32)(d1 >> 26); h1 = (word32)d1 & 0x3ffffff; - d2 += c; c = (word32)(d2 >> 26); h2 = (word32)d2 & 0x3ffffff; - d3 += c; c = (word32)(d3 >> 26); h3 = (word32)d3 & 0x3ffffff; - d4 += c; c = (word32)(d4 >> 26); h4 = (word32)d4 & 0x3ffffff; - h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; - h1 += c; + /* (partial) h %= p */ + c = (word32)(d0 >> 26); h0 = (word32)d0 & 0x3ffffff; + d1 += c; c = (word32)(d1 >> 26); h1 = (word32)d1 & 0x3ffffff; + d2 += c; c = (word32)(d2 >> 26); h2 = (word32)d2 & 0x3ffffff; + d3 += c; c = (word32)(d3 >> 26); h3 = (word32)d3 & 0x3ffffff; + d4 += c; c = (word32)(d4 >> 26); h4 = (word32)d4 & 0x3ffffff; + h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; + h1 += c; - m += POLY1305_BLOCK_SIZE; - bytes -= POLY1305_BLOCK_SIZE; - } + m += POLY1305_BLOCK_SIZE; + bytes -= POLY1305_BLOCK_SIZE; + } - ctx->h[0] = h0; - ctx->h[1] = h1; - ctx->h[2] = h2; - ctx->h[3] = h3; - ctx->h[4] = h4; + ctx->h[0] = h0; + ctx->h[1] = h1; + ctx->h[2] = h2; + ctx->h[3] = h3; + ctx->h[4] = h4; #endif /* end of 64 bit cpu blocks or 32 bit cpu */ } +void poly1305_block(Poly1305* ctx, const unsigned char *m) +{ +#ifdef USE_INTEL_SPEEDUP + /* No call to poly1305_block when AVX2, AVX2 does 4 blocks at a time. */ + poly1305_block_avx(ctx, m); +#else + poly1305_blocks(ctx, m, POLY1305_BLOCK_SIZE); +#endif +} +#endif /* !defined(WOLFSSL_ARMASM) || !defined(__aarch64__) */ -int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) { - -#if defined(POLY130564) +#if !defined(WOLFSSL_ARMASM) || !defined(__aarch64__) +int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) +{ +#if defined(POLY130564) && !defined(USE_INTEL_SPEEDUP) word64 t0,t1; #endif + if (key == NULL) + return BAD_FUNC_ARG; + #ifdef CHACHA_AEAD_TEST word32 k; printf("Poly key used:\n"); @@ -270,239 +407,261 @@ int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) { if ((k+1) % 8 == 0) printf("\n"); } - printf("\n"); + printf("\n"); #endif 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); - t1 = U8TO64(key + 8); + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + t0 = U8TO64(key + 0); + t1 = U8TO64(key + 8); - ctx->r[0] = ( t0 ) & 0xffc0fffffff; - ctx->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff; - ctx->r[2] = ((t1 >> 24) ) & 0x00ffffffc0f; + ctx->r[0] = ( t0 ) & 0xffc0fffffff; + ctx->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff; + ctx->r[2] = ((t1 >> 24) ) & 0x00ffffffc0f; - /* h (accumulator) = 0 */ - ctx->h[0] = 0; - ctx->h[1] = 0; - ctx->h[2] = 0; + /* h (accumulator) = 0 */ + ctx->h[0] = 0; + ctx->h[1] = 0; + ctx->h[2] = 0; - /* save pad for later */ - ctx->pad[0] = U8TO64(key + 16); - ctx->pad[1] = U8TO64(key + 24); + /* save pad for later */ + 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 */ - ctx->r[0] = (U8TO32(key + 0) ) & 0x3ffffff; - ctx->r[1] = (U8TO32(key + 3) >> 2) & 0x3ffff03; - ctx->r[2] = (U8TO32(key + 6) >> 4) & 0x3ffc0ff; - ctx->r[3] = (U8TO32(key + 9) >> 6) & 0x3f03fff; - ctx->r[4] = (U8TO32(key + 12) >> 8) & 0x00fffff; + ctx->r[0] = (U8TO32(key + 0) ) & 0x3ffffff; + ctx->r[1] = (U8TO32(key + 3) >> 2) & 0x3ffff03; + ctx->r[2] = (U8TO32(key + 6) >> 4) & 0x3ffc0ff; + ctx->r[3] = (U8TO32(key + 9) >> 6) & 0x3f03fff; + ctx->r[4] = (U8TO32(key + 12) >> 8) & 0x00fffff; - /* h = 0 */ - ctx->h[0] = 0; - ctx->h[1] = 0; - ctx->h[2] = 0; - ctx->h[3] = 0; - ctx->h[4] = 0; + /* h = 0 */ + ctx->h[0] = 0; + ctx->h[1] = 0; + ctx->h[2] = 0; + ctx->h[3] = 0; + ctx->h[4] = 0; - /* save pad for later */ - ctx->pad[0] = U8TO32(key + 16); - ctx->pad[1] = U8TO32(key + 20); - ctx->pad[2] = U8TO32(key + 24); - ctx->pad[3] = U8TO32(key + 28); + /* save pad for later */ + ctx->pad[0] = U8TO32(key + 16); + ctx->pad[1] = U8TO32(key + 20); + ctx->pad[2] = U8TO32(key + 24); + ctx->pad[3] = U8TO32(key + 28); + + ctx->leftover = 0; + ctx->finished = 0; #endif - ctx->leftover = 0; - ctx->final = 0; - 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; - word64 t0,t1; + word64 g0,g1,g2; + word64 t0,t1; #else word32 h0,h1,h2,h3,h4,c; - word32 g0,g1,g2,g3,g4; - word64 f; - word32 mask; + word32 g0,g1,g2,g3,g4; + word64 f; + word32 mask; #endif 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) { - size_t i = ctx->leftover; - 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); - } + /* 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 = 1; + poly1305_block(ctx, ctx->buffer); + } - /* fully carry h */ - h0 = ctx->h[0]; - h1 = ctx->h[1]; - h2 = ctx->h[2]; + /* fully carry h */ + h0 = ctx->h[0]; + h1 = ctx->h[1]; + h2 = ctx->h[2]; - 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; + 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); + /* 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; + /* 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; - /* h = (h + pad) */ - t0 = ctx->pad[0]; - t1 = ctx->pad[1]; + /* h = (h + pad) */ + t0 = ctx->pad[0]; + t1 = ctx->pad[1]; - h0 += (( t0 ) & 0xfffffffffff) ; + h0 += (( t0 ) & 0xfffffffffff) ; c = (h0 >> 44); h0 &= 0xfffffffffff; - h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; + h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; c = (h1 >> 44); h1 &= 0xfffffffffff; - h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; + h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; h2 &= 0x3ffffffffff; - /* mac = h % (2^128) */ - h0 = ((h0 ) | (h1 << 44)); - h1 = ((h1 >> 20) | (h2 << 24)); + /* mac = h % (2^128) */ + h0 = ((h0 ) | (h1 << 44)); + h1 = ((h1 >> 20) | (h2 << 24)); - U64TO8(mac + 0, h0); - U64TO8(mac + 8, h1); + U64TO8(mac + 0, h0); + U64TO8(mac + 8, h1); - /* 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->r[2] = 0; - ctx->pad[0] = 0; - ctx->pad[1] = 0; + /* 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->r[2] = 0; + ctx->pad[0] = 0; + ctx->pad[1] = 0; #else /* if not 64 bit then use 32 bit */ - - /* process the remaining block */ - if (ctx->leftover) { - size_t i = ctx->leftover; - 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); - } - /* fully carry h */ - h0 = ctx->h[0]; - h1 = ctx->h[1]; - h2 = ctx->h[2]; - h3 = ctx->h[3]; - h4 = ctx->h[4]; + /* process the remaining block */ + if (ctx->leftover) { + size_t i = ctx->leftover; + ctx->buffer[i++] = 1; + for (; i < POLY1305_BLOCK_SIZE; i++) + ctx->buffer[i] = 0; + ctx->finished = 1; + poly1305_block(ctx, ctx->buffer); + } - c = h1 >> 26; h1 = h1 & 0x3ffffff; - h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; - h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; - h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; - h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; - h1 += c; + /* fully carry h */ + h0 = ctx->h[0]; + h1 = ctx->h[1]; + h2 = ctx->h[2]; + h3 = ctx->h[3]; + h4 = ctx->h[4]; - /* compute h + -p */ - g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; - g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; - g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; - g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; - g4 = h4 + c - (1 << 26); + c = h1 >> 26; h1 = h1 & 0x3ffffff; + h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; + h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; + h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; + h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; + h1 += c; - /* select h if h < p, or h + -p if h >= p */ - mask = (g4 >> ((sizeof(word32) * 8) - 1)) - 1; - g0 &= mask; - g1 &= mask; - g2 &= mask; - g3 &= mask; - g4 &= mask; - mask = ~mask; - h0 = (h0 & mask) | g0; - h1 = (h1 & mask) | g1; - h2 = (h2 & mask) | g2; - h3 = (h3 & mask) | g3; - h4 = (h4 & mask) | g4; + /* compute h + -p */ + g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; + g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; + g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; + g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; + g4 = h4 + c - ((word32)1 << 26); - /* h = h % (2^128) */ - h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; - h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; - h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; - h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; + /* select h if h < p, or h + -p if h >= p */ + mask = ((word32)g4 >> ((sizeof(word32) * 8) - 1)) - 1; + g0 &= mask; + g1 &= mask; + g2 &= mask; + g3 &= mask; + g4 &= mask; + mask = ~mask; + h0 = (h0 & mask) | g0; + h1 = (h1 & mask) | g1; + h2 = (h2 & mask) | g2; + h3 = (h3 & mask) | g3; + h4 = (h4 & mask) | g4; - /* mac = (h + pad) % (2^128) */ - f = (word64)h0 + ctx->pad[0] ; h0 = (word32)f; - f = (word64)h1 + ctx->pad[1] + (f >> 32); h1 = (word32)f; - f = (word64)h2 + ctx->pad[2] + (f >> 32); h2 = (word32)f; - f = (word64)h3 + ctx->pad[3] + (f >> 32); h3 = (word32)f; + /* h = h % (2^128) */ + h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; + h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; + h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; + h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; - U32TO8(mac + 0, h0); - U32TO8(mac + 4, h1); - U32TO8(mac + 8, h2); - U32TO8(mac + 12, h3); + /* mac = (h + pad) % (2^128) */ + f = (word64)h0 + ctx->pad[0] ; h0 = (word32)f; + f = (word64)h1 + ctx->pad[1] + (f >> 32); h1 = (word32)f; + f = (word64)h2 + ctx->pad[2] + (f >> 32); h2 = (word32)f; + f = (word64)h3 + ctx->pad[3] + (f >> 32); h3 = (word32)f; - /* zero out the state */ - ctx->h[0] = 0; - ctx->h[1] = 0; - ctx->h[2] = 0; - ctx->h[3] = 0; - ctx->h[4] = 0; - ctx->r[0] = 0; - ctx->r[1] = 0; - ctx->r[2] = 0; - ctx->r[3] = 0; - ctx->r[4] = 0; - ctx->pad[0] = 0; - ctx->pad[1] = 0; - ctx->pad[2] = 0; - ctx->pad[3] = 0; + U32TO8(mac + 0, h0); + U32TO8(mac + 4, h1); + U32TO8(mac + 8, h2); + U32TO8(mac + 12, h3); + + /* zero out the state */ + ctx->h[0] = 0; + ctx->h[1] = 0; + ctx->h[2] = 0; + ctx->h[3] = 0; + ctx->h[4] = 0; + ctx->r[0] = 0; + ctx->r[1] = 0; + ctx->r[2] = 0; + ctx->r[3] = 0; + ctx->r[4] = 0; + ctx->pad[0] = 0; + ctx->pad[1] = 0; + ctx->pad[2] = 0; + ctx->pad[3] = 0; #endif return 0; } +#endif /* !defined(WOLFSSL_ARMASM) || !defined(__aarch64__) */ -int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) { - - size_t i; +int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) +{ + size_t i; #ifdef CHACHA_AEAD_TEST word32 k; @@ -512,43 +671,198 @@ int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) { if ((k+1) % 16 == 0) printf("\n"); } - printf("\n"); + printf("\n"); #endif - + 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 -= 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 = sizeof(ctx->buffer) - ctx->leftover; + if (want > bytes) + want = 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 -= want; - } + for (i = 0; i < want; i++) + ctx->buffer[ctx->leftover + i] = m[i]; + bytes -= (word32)want; + m += want; + ctx->leftover += want; + if (ctx->leftover < sizeof(ctx->buffer)) + return 0; + + if (!ctx->started) + poly1305_calc_powers_avx2(ctx); + poly1305_blocks_avx2(ctx, ctx->buffer, sizeof(ctx->buffer)); + ctx->leftover = 0; + } + + /* process full blocks */ + if (bytes >= sizeof(ctx->buffer)) { + size_t want = bytes & ~(sizeof(ctx->buffer) - 1); + + if (!ctx->started) + poly1305_calc_powers_avx2(ctx); + 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; + } + } - /* store leftover */ - if (bytes) { - for (i = 0; i < bytes; i++) - ctx->buffer[ctx->leftover + i] = m[i]; - ctx->leftover += bytes; - } return 0; } -#endif /* HAVE_POLY1305 */ +/* Takes a Poly1305 struct that has a key loaded and pads the provided length + ctx : Initialized Poly1305 struct to use + lenToPad : Current number of bytes updated that needs padding to 16 + */ +int wc_Poly1305_Pad(Poly1305* ctx, word32 lenToPad) +{ + int ret = 0; + word32 paddingLen; + byte padding[WC_POLY1305_PAD_SZ - 1]; + + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + if (lenToPad == 0) { + return 0; /* nothing needs to be done */ + } + + XMEMSET(padding, 0, sizeof(padding)); + + /* Pad length to 16 bytes */ + paddingLen = -(int)lenToPad & (WC_POLY1305_PAD_SZ - 1); + if (paddingLen > 0) { + ret = wc_Poly1305Update(ctx, padding, paddingLen); + } + return ret; +} + +/* Takes a Poly1305 struct that has a key loaded and adds the AEAD length + encoding in 64-bit little endian + aadSz : Size of the additional authentication data + dataSz : Size of the plaintext or ciphertext + */ +int wc_Poly1305_EncodeSizes(Poly1305* ctx, word32 aadSz, word32 dataSz) +{ + int ret; + byte little64[16]; /* sizeof(word64) * 2 */ + + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(little64, 0, sizeof(little64)); + + /* size of additional data and input data as little endian 64 bit types */ + u32tole64(aadSz, little64); + u32tole64(dataSz, little64 + 8); + ret = wc_Poly1305Update(ctx, little64, sizeof(little64)); + + return ret; +} + +/* Takes in an initialized Poly1305 struct that has a key loaded and creates + a MAC (tag) using recent TLS AEAD padding scheme. + ctx : Initialized Poly1305 struct to use + additional : Additional data to use + addSz : Size of additional buffer + input : Input buffer to create tag from + sz : Size of input buffer + tag : Buffer to hold created tag + tagSz : Size of input tag buffer (must be at least + WC_POLY1305_MAC_SZ(16)) + */ +int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, + byte* input, word32 sz, byte* tag, word32 tagSz) +{ + int ret; + + /* sanity check on arguments */ + if (ctx == NULL || input == NULL || tag == NULL || + tagSz < WC_POLY1305_MAC_SZ) { + 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; + } + /* pad additional data */ + if ((ret = wc_Poly1305_Pad(ctx, addSz)) != 0) { + return ret; + } + } + + /* input plus padding */ + if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) { + return ret; + } + /* pad input data */ + if ((ret = wc_Poly1305_Pad(ctx, sz)) != 0) { + return ret; + } + + /* encode size of AAD and input data as little endian 64 bit types */ + if ((ret = wc_Poly1305_EncodeSizes(ctx, addSz, sz)) != 0) { + return ret; + } + + /* Finalize the auth tag */ + ret = wc_Poly1305Final(ctx, tag); + + return ret; + +} +#endif /* HAVE_POLY1305 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/poly1305_asm.S b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/poly1305_asm.S new file mode 100644 index 000000000..95711075b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/poly1305_asm.S @@ -0,0 +1,1105 @@ +/* poly1305_asm + * + * Copyright (C) 2006-2020 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 HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX1 +#endif /* HAVE_INTEL_AVX1 */ +#ifndef NO_AVX2_SUPPORT +#define HAVE_INTEL_AVX2 +#endif /* NO_AVX2_SUPPORT */ + +#ifdef HAVE_INTEL_AVX1 +#ifndef __APPLE__ +.text +.globl poly1305_setkey_avx +.type poly1305_setkey_avx,@function +.align 4 +poly1305_setkey_avx: +#else +.section __TEXT,__text +.globl _poly1305_setkey_avx +.p2align 2 +_poly1305_setkey_avx: +#endif /* __APPLE__ */ + movabsq $0xffffffc0fffffff, %r10 + movabsq $0xffffffc0ffffffc, %r11 + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + andq %r10, %rdx + andq %r11, %rax + movq %rdx, %r10 + movq %rax, %r11 + xorq %r9, %r9 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %r9, 24(%rdi) + movq %r9, 32(%rdi) + movq %r9, 40(%rdi) + movq %rcx, 48(%rdi) + movq %r8, 56(%rdi) + movq %r9, 352(%rdi) + movq %r9, 408(%rdi) + movq %rdx, 360(%rdi) + movq %rax, 416(%rdi) + addq %rdx, %r10 + addq %rax, %r11 + movq %r10, 368(%rdi) + movq %r11, 424(%rdi) + addq %rdx, %r10 + addq %rax, %r11 + movq %r10, 376(%rdi) + movq %r11, 432(%rdi) + addq %rdx, %r10 + addq %rax, %r11 + movq %r10, 384(%rdi) + movq %r11, 440(%rdi) + addq %rdx, %r10 + addq %rax, %r11 + movq %r10, 392(%rdi) + movq %r11, 448(%rdi) + addq %rdx, %r10 + addq %rax, %r11 + movq %r10, 400(%rdi) + movq %r11, 456(%rdi) + movq %r9, 608(%rdi) + movb $0x01, 616(%rdi) + repz retq +#ifndef __APPLE__ +.size poly1305_setkey_avx,.-poly1305_setkey_avx +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl poly1305_block_avx +.type poly1305_block_avx,@function +.align 4 +poly1305_block_avx: +#else +.section __TEXT,__text +.globl _poly1305_block_avx +.p2align 2 +_poly1305_block_avx: +#endif /* __APPLE__ */ + pushq %r15 + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + movq (%rdi), %r15 + movq 8(%rdi), %rbx + movq 24(%rdi), %r8 + movq 32(%rdi), %r9 + movq 40(%rdi), %r10 + xorq %r14, %r14 + movb 616(%rdi), %r14b + # h += m + movq (%rsi), %r11 + movq 8(%rsi), %r12 + addq %r11, %r8 + adcq %r12, %r9 + movq %rbx, %rax + adcq %r14, %r10 + # r[1] * h[0] => rdx, rax ==> t2, t1 + mulq %r8 + movq %rax, %r12 + movq %rdx, %r13 + # r[0] * h[1] => rdx, rax ++> t2, t1 + movq %r15, %rax + mulq %r9 + addq %rax, %r12 + movq %r15, %rax + adcq %rdx, %r13 + # r[0] * h[0] => rdx, rax ==> t4, t0 + mulq %r8 + movq %rax, %r11 + movq %rdx, %r8 + # r[1] * h[1] => rdx, rax =+> t3, t2 + movq %rbx, %rax + mulq %r9 + # r[0] * h[2] +> t2 + addq 352(%rdi,%r10,8), %r13 + movq %rdx, %r14 + addq %r8, %r12 + adcq %rax, %r13 + # r[1] * h[2] +> t3 + adcq 408(%rdi,%r10,8), %r14 + # r * h in r14, r13, r12, r11 + # h = (r * h) mod 2^130 - 5 + movq %r13, %r10 + andq $-4, %r13 + andq $3, %r10 + addq %r13, %r11 + movq %r13, %r8 + adcq %r14, %r12 + adcq $0x00, %r10 + shrdq $2, %r14, %r8 + shrq $2, %r14 + addq %r11, %r8 + adcq %r14, %r12 + movq %r12, %r9 + adcq $0x00, %r10 + # h in r10, r9, r8 + # Store h to ctx + movq %r8, 24(%rdi) + movq %r9, 32(%rdi) + movq %r10, 40(%rdi) + popq %r14 + popq %r13 + popq %r12 + popq %rbx + popq %r15 + repz retq +#ifndef __APPLE__ +.size poly1305_block_avx,.-poly1305_block_avx +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl poly1305_blocks_avx +.type poly1305_blocks_avx,@function +.align 4 +poly1305_blocks_avx: +#else +.section __TEXT,__text +.globl _poly1305_blocks_avx +.p2align 2 +_poly1305_blocks_avx: +#endif /* __APPLE__ */ + pushq %r15 + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + movq %rdx, %rcx + movq (%rdi), %r15 + movq 8(%rdi), %rbx + movq 24(%rdi), %r8 + movq 32(%rdi), %r9 + movq 40(%rdi), %r10 +L_poly1305_avx_blocks_start: + # h += m + movq (%rsi), %r11 + movq 8(%rsi), %r12 + addq %r11, %r8 + adcq %r12, %r9 + movq %rbx, %rax + adcq $0x00, %r10 + # r[1] * h[0] => rdx, rax ==> t2, t1 + mulq %r8 + movq %rax, %r12 + movq %rdx, %r13 + # r[0] * h[1] => rdx, rax ++> t2, t1 + movq %r15, %rax + mulq %r9 + addq %rax, %r12 + movq %r15, %rax + adcq %rdx, %r13 + # r[0] * h[0] => rdx, rax ==> t4, t0 + mulq %r8 + movq %rax, %r11 + movq %rdx, %r8 + # r[1] * h[1] => rdx, rax =+> t3, t2 + movq %rbx, %rax + mulq %r9 + # r[0] * h[2] +> t2 + addq 360(%rdi,%r10,8), %r13 + movq %rdx, %r14 + addq %r8, %r12 + adcq %rax, %r13 + # r[1] * h[2] +> t3 + adcq 416(%rdi,%r10,8), %r14 + # r * h in r14, r13, r12, r11 + # h = (r * h) mod 2^130 - 5 + movq %r13, %r10 + andq $-4, %r13 + andq $3, %r10 + addq %r13, %r11 + movq %r13, %r8 + adcq %r14, %r12 + adcq $0x00, %r10 + shrdq $2, %r14, %r8 + shrq $2, %r14 + addq %r11, %r8 + adcq %r14, %r12 + movq %r12, %r9 + adcq $0x00, %r10 + # h in r10, r9, r8 + # Next block from message + addq $16, %rsi + subq $16, %rcx + jg L_poly1305_avx_blocks_start + # Store h to ctx + movq %r8, 24(%rdi) + movq %r9, 32(%rdi) + movq %r10, 40(%rdi) + popq %r14 + popq %r13 + popq %r12 + popq %rbx + popq %r15 + repz retq +#ifndef __APPLE__ +.size poly1305_blocks_avx,.-poly1305_blocks_avx +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl poly1305_final_avx +.type poly1305_final_avx,@function +.align 4 +poly1305_final_avx: +#else +.section __TEXT,__text +.globl _poly1305_final_avx +.p2align 2 +_poly1305_final_avx: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + movq %rsi, %rbx + movq 608(%rdi), %rax + testq %rax, %rax + je L_poly1305_avx_final_no_more + movb $0x01, 480(%rdi,%rax,1) + jmp L_poly1305_avx_final_cmp_rem +L_poly1305_avx_final_zero_rem: + movb $0x00, 480(%rdi,%rax,1) +L_poly1305_avx_final_cmp_rem: + incb %al + cmpq $16, %rax + jl L_poly1305_avx_final_zero_rem + movb $0x00, 616(%rdi) + leaq 480(%rdi), %rsi +#ifndef __APPLE__ + callq poly1305_block_avx@plt +#else + callq _poly1305_block_avx +#endif /* __APPLE__ */ +L_poly1305_avx_final_no_more: + movq 24(%rdi), %rax + movq 32(%rdi), %rdx + movq 40(%rdi), %rcx + movq 48(%rdi), %r11 + movq 56(%rdi), %r12 + # h %= p + # h = (h + pad) + # mod 2^130 - 5 + movq %rcx, %r8 + andq $3, %rcx + shrq $2, %r8 + # Multily by 5 + leaq 0(%r8,%r8,4), %r8 + addq %r8, %rax + adcq $0x00, %rdx + adcq $0x00, %rcx + # Fixup when between (1 << 130) - 1 and (1 << 130) - 5 + movq %rax, %r8 + movq %rdx, %r9 + movq %rcx, %r10 + addq $5, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + cmpq $4, %r10 + cmoveq %r8, %rax + cmoveq %r9, %rdx + # h += pad + addq %r11, %rax + adcq %r12, %rdx + movq %rax, (%rbx) + movq %rdx, 8(%rbx) + # Zero out r + movq $0x00, (%rdi) + movq $0x00, 8(%rdi) + # Zero out h + movq $0x00, 24(%rdi) + movq $0x00, 32(%rdi) + movq $0x00, 40(%rdi) + # Zero out pad + movq $0x00, 48(%rdi) + movq $0x00, 56(%rdi) + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size poly1305_final_avx,.-poly1305_final_avx +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX1 */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ +.text +.globl poly1305_calc_powers_avx2 +.type poly1305_calc_powers_avx2,@function +.align 4 +poly1305_calc_powers_avx2: +#else +.section __TEXT,__text +.globl _poly1305_calc_powers_avx2 +.p2align 2 +_poly1305_calc_powers_avx2: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + pushq %rbp + movq (%rdi), %rcx + movq 8(%rdi), %r8 + xorq %r9, %r9 + # Convert to 26 bits in 32 + movq %rcx, %rax + movq %rcx, %rdx + movq %rcx, %rsi + movq %r8, %rbx + movq %r8, %rbp + shrq $26, %rdx + shrdq $52, %r8, %rsi + shrq $14, %rbx + shrdq $40, %r9, %rbp + andq $0x3ffffff, %rax + andq $0x3ffffff, %rdx + andq $0x3ffffff, %rsi + andq $0x3ffffff, %rbx + andq $0x3ffffff, %rbp + movl %eax, 224(%rdi) + movl %edx, 228(%rdi) + movl %esi, 232(%rdi) + movl %ebx, 236(%rdi) + movl %ebp, 240(%rdi) + movl $0x00, 244(%rdi) + # Square 128-bit + movq %r8, %rax + mulq %rcx + xorq %r13, %r13 + movq %rax, %r11 + movq %rdx, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + movq %rcx, %rax + mulq %rax + movq %rax, %r10 + movq %rdx, %r15 + movq %r8, %rax + mulq %rax + addq %r15, %r11 + adcq %rax, %r12 + adcq %rdx, %r13 + # Reduce 256-bit to 130-bit + movq %r12, %rax + movq %r13, %rdx + andq $-4, %rax + andq $3, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + shrdq $2, %rdx, %rax + shrq $2, %rdx + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + movq %r12, %rax + shrq $2, %rax + leaq 0(%rax,%rax,4), %rax + andq $3, %r12 + addq %rax, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Convert to 26 bits in 32 + movq %r10, %rax + movq %r10, %rdx + movq %r10, %rsi + movq %r11, %rbx + movq %r11, %rbp + shrq $26, %rdx + shrdq $52, %r11, %rsi + shrq $14, %rbx + shrdq $40, %r12, %rbp + andq $0x3ffffff, %rax + andq $0x3ffffff, %rdx + andq $0x3ffffff, %rsi + andq $0x3ffffff, %rbx + andq $0x3ffffff, %rbp + movl %eax, 256(%rdi) + movl %edx, 260(%rdi) + movl %esi, 264(%rdi) + movl %ebx, 268(%rdi) + movl %ebp, 272(%rdi) + movl $0x00, 276(%rdi) + # Multiply 128-bit by 130-bit + # r1[0] * r2[0] + movq %rcx, %rax + mulq %r10 + movq %rax, %r13 + movq %rdx, %r14 + # r1[0] * r2[1] + movq %rcx, %rax + mulq %r11 + movq $0x00, %r15 + addq %rax, %r14 + adcq %rdx, %r15 + # r1[1] * r2[0] + movq %r8, %rax + mulq %r10 + movq $0x00, %rsi + addq %rax, %r14 + adcq %rdx, %r15 + adcq $0x00, %rsi + # r1[0] * r2[2] + movq %rcx, %rax + mulq %r12 + addq %rax, %r15 + adcq %rdx, %rsi + # r1[1] * r2[1] + movq %r8, %rax + mulq %r11 + movq $0x00, %rbx + addq %rax, %r15 + adcq %rdx, %rsi + adcq $0x00, %rbx + # r1[1] * r2[2] + movq %r8, %rax + mulq %r12 + addq %rax, %rsi + adcq %rdx, %rbx + # Reduce 260-bit to 130-bit + movq %r15, %rax + movq %rsi, %rdx + movq %rbx, %rbx + andq $-4, %rax + andq $3, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq %rbx, %r15 + shrdq $2, %rdx, %rax + shrdq $2, %rbx, %rdx + shrq $2, %rbx + addq %rax, %r13 + adcq %rdx, %r14 + adcq %rbx, %r15 + movq %r15, %rax + andq $3, %r15 + shrq $2, %rax + leaq 0(%rax,%rax,4), %rax + addq %rax, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Convert to 26 bits in 32 + movq %r13, %rax + movq %r13, %rdx + movq %r13, %rsi + movq %r14, %rbx + movq %r14, %rbp + shrq $26, %rdx + shrdq $52, %r14, %rsi + shrq $14, %rbx + shrdq $40, %r15, %rbp + andq $0x3ffffff, %rax + andq $0x3ffffff, %rdx + andq $0x3ffffff, %rsi + andq $0x3ffffff, %rbx + andq $0x3ffffff, %rbp + movl %eax, 288(%rdi) + movl %edx, 292(%rdi) + movl %esi, 296(%rdi) + movl %ebx, 300(%rdi) + movl %ebp, 304(%rdi) + movl $0x00, 308(%rdi) + # Square 130-bit + movq %r11, %rax + mulq %r10 + xorq %r13, %r13 + movq %rax, %r8 + movq %rdx, %r9 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r13 + movq %r10, %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %r15 + movq %r11, %rax + mulq %rax + addq %r15, %r8 + adcq %rax, %r9 + adcq %rdx, %r13 + movq %r12, %rax + mulq %rax + movq %rax, %r14 + movq %r12, %rax + mulq %r10 + addq %rax, %r9 + adcq %rdx, %r13 + adcq $0x00, %r14 + addq %rax, %r9 + adcq %rdx, %r13 + adcq $0x00, %r14 + movq %r12, %rax + mulq %r11 + addq %rax, %r13 + adcq %rdx, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Reduce 260-bit to 130-bit + movq %r9, %rax + movq %r13, %rdx + movq %r14, %r15 + andq $-4, %rax + andq $3, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq %r15, %r9 + shrdq $2, %rdx, %rax + shrdq $2, %r15, %rdx + shrq $2, %r15 + addq %rax, %rcx + adcq %rdx, %r8 + adcq %r15, %r9 + movq %r9, %rax + andq $3, %r9 + shrq $2, %rax + leaq 0(%rax,%rax,4), %rax + addq %rax, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + # Convert to 26 bits in 32 + movq %rcx, %rax + movq %rcx, %rdx + movq %rcx, %rsi + movq %r8, %rbx + movq %r8, %rbp + shrq $26, %rdx + shrdq $52, %r8, %rsi + shrq $14, %rbx + shrdq $40, %r9, %rbp + andq $0x3ffffff, %rax + andq $0x3ffffff, %rdx + andq $0x3ffffff, %rsi + andq $0x3ffffff, %rbx + andq $0x3ffffff, %rbp + movl %eax, 320(%rdi) + movl %edx, 324(%rdi) + movl %esi, 328(%rdi) + movl %ebx, 332(%rdi) + movl %ebp, 336(%rdi) + movl $0x00, 340(%rdi) + popq %rbp + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size poly1305_calc_powers_avx2,.-poly1305_calc_powers_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl poly1305_setkey_avx2 +.type poly1305_setkey_avx2,@function +.align 4 +poly1305_setkey_avx2: +#else +.section __TEXT,__text +.globl _poly1305_setkey_avx2 +.p2align 2 +_poly1305_setkey_avx2: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + callq poly1305_setkey_avx@plt +#else + callq _poly1305_setkey_avx +#endif /* __APPLE__ */ + vpxor %ymm0, %ymm0, %ymm0 + vmovdqu %ymm0, 64(%rdi) + vmovdqu %ymm0, 96(%rdi) + vmovdqu %ymm0, 128(%rdi) + vmovdqu %ymm0, 160(%rdi) + vmovdqu %ymm0, 192(%rdi) + movq $0x00, 608(%rdi) + movw $0x00, 616(%rdi) + repz retq +#ifndef __APPLE__ +.size poly1305_setkey_avx2,.-poly1305_setkey_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_poly1305_avx2_blocks_mask: +.quad 0x3ffffff, 0x3ffffff +.quad 0x3ffffff, 0x3ffffff +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_poly1305_avx2_blocks_hibit: +.quad 0x1000000, 0x1000000 +.quad 0x1000000, 0x1000000 +#ifndef __APPLE__ +.text +.globl poly1305_blocks_avx2 +.type poly1305_blocks_avx2,@function +.align 4 +poly1305_blocks_avx2: +#else +.section __TEXT,__text +.globl _poly1305_blocks_avx2 +.p2align 2 +_poly1305_blocks_avx2: +#endif /* __APPLE__ */ + pushq %r12 + pushq %rbx + subq $0x140, %rsp + movq %rsp, %rcx + andq $-32, %rcx + addq $32, %rcx + vpxor %ymm15, %ymm15, %ymm15 + movq %rcx, %rbx + leaq 64(%rdi), %rax + addq $0xa0, %rbx + cmpw $0x00, 616(%rdi) + jne L_poly1305_avx2_blocks_begin_h + # Load the message data + vmovdqu (%rsi), %ymm0 + vmovdqu 32(%rsi), %ymm1 + vperm2i128 $32, %ymm1, %ymm0, %ymm2 + vperm2i128 $49, %ymm1, %ymm0, %ymm0 + vpunpckldq %ymm0, %ymm2, %ymm1 + vpunpckhdq %ymm0, %ymm2, %ymm3 + vpunpckldq %ymm15, %ymm1, %ymm0 + vpunpckhdq %ymm15, %ymm1, %ymm1 + vpunpckldq %ymm15, %ymm3, %ymm2 + vpunpckhdq %ymm15, %ymm3, %ymm3 + vmovdqu L_poly1305_avx2_blocks_hibit(%rip), %ymm4 + vpsllq $6, %ymm1, %ymm1 + vpsllq $12, %ymm2, %ymm2 + vpsllq $18, %ymm3, %ymm3 + vmovdqu L_poly1305_avx2_blocks_mask(%rip), %ymm14 + # Reduce, in place, the message data + vpsrlq $26, %ymm0, %ymm10 + vpsrlq $26, %ymm3, %ymm11 + vpand %ymm14, %ymm0, %ymm0 + vpand %ymm14, %ymm3, %ymm3 + vpaddq %ymm1, %ymm10, %ymm1 + vpaddq %ymm4, %ymm11, %ymm4 + vpsrlq $26, %ymm1, %ymm10 + vpsrlq $26, %ymm4, %ymm11 + vpand %ymm14, %ymm1, %ymm1 + vpand %ymm14, %ymm4, %ymm4 + vpaddq %ymm2, %ymm10, %ymm2 + vpslld $2, %ymm11, %ymm12 + vpaddd %ymm12, %ymm11, %ymm12 + vpsrlq $26, %ymm2, %ymm10 + vpaddq %ymm0, %ymm12, %ymm0 + vpsrlq $26, %ymm0, %ymm11 + vpand %ymm14, %ymm2, %ymm2 + vpand %ymm14, %ymm0, %ymm0 + vpaddq %ymm3, %ymm10, %ymm3 + vpaddq %ymm1, %ymm11, %ymm1 + vpsrlq $26, %ymm3, %ymm10 + vpand %ymm14, %ymm3, %ymm3 + vpaddq %ymm4, %ymm10, %ymm4 + addq $0x40, %rsi + subq $0x40, %rdx + jz L_poly1305_avx2_blocks_store + jmp L_poly1305_avx2_blocks_load_r4 +L_poly1305_avx2_blocks_begin_h: + # Load the H values. + vmovdqu (%rax), %ymm0 + vmovdqu 32(%rax), %ymm1 + vmovdqu 64(%rax), %ymm2 + vmovdqu 96(%rax), %ymm3 + vmovdqu 128(%rax), %ymm4 + # Check if there is a power of r to load - otherwise use r^4. + cmpb $0x00, 616(%rdi) + je L_poly1305_avx2_blocks_load_r4 + # Load the 4 powers of r - r^4, r^3, r^2, r^1. + vmovdqu 224(%rdi), %ymm8 + vmovdqu 256(%rdi), %ymm7 + vmovdqu 288(%rdi), %ymm6 + vmovdqu 320(%rdi), %ymm5 + vpermq $0xd8, %ymm5, %ymm5 + vpermq $0xd8, %ymm6, %ymm6 + vpermq $0xd8, %ymm7, %ymm7 + vpermq $0xd8, %ymm8, %ymm8 + vpunpcklqdq %ymm6, %ymm5, %ymm10 + vpunpckhqdq %ymm6, %ymm5, %ymm11 + vpunpcklqdq %ymm8, %ymm7, %ymm12 + vpunpckhqdq %ymm8, %ymm7, %ymm13 + vperm2i128 $32, %ymm12, %ymm10, %ymm5 + vperm2i128 $49, %ymm12, %ymm10, %ymm7 + vperm2i128 $32, %ymm13, %ymm11, %ymm9 + vpsrlq $32, %ymm5, %ymm6 + vpsrlq $32, %ymm7, %ymm8 + jmp L_poly1305_avx2_blocks_mul_5 +L_poly1305_avx2_blocks_load_r4: + # Load r^4 into all four positions. + vmovdqu 320(%rdi), %ymm13 + vpermq $0x00, %ymm13, %ymm5 + vpsrlq $32, %ymm13, %ymm14 + vpermq $0x55, %ymm13, %ymm7 + vpermq $0xaa, %ymm13, %ymm9 + vpermq $0x00, %ymm14, %ymm6 + vpermq $0x55, %ymm14, %ymm8 +L_poly1305_avx2_blocks_mul_5: + # Multiply top 4 26-bit values of all four H by 5 + vpslld $2, %ymm6, %ymm10 + vpslld $2, %ymm7, %ymm11 + vpslld $2, %ymm8, %ymm12 + vpslld $2, %ymm9, %ymm13 + vpaddq %ymm10, %ymm6, %ymm10 + vpaddq %ymm11, %ymm7, %ymm11 + vpaddq %ymm12, %ymm8, %ymm12 + vpaddq %ymm13, %ymm9, %ymm13 + # Store powers of r and multiple of 5 for use in multiply. + vmovdqa %ymm10, (%rbx) + vmovdqa %ymm11, 32(%rbx) + vmovdqa %ymm12, 64(%rbx) + vmovdqa %ymm13, 96(%rbx) + vmovdqa %ymm5, (%rcx) + vmovdqa %ymm6, 32(%rcx) + vmovdqa %ymm7, 64(%rcx) + vmovdqa %ymm8, 96(%rcx) + vmovdqa %ymm9, 128(%rcx) + vmovdqu L_poly1305_avx2_blocks_mask(%rip), %ymm14 + # If not finished then loop over data + cmpb $0x01, 616(%rdi) + jne L_poly1305_avx2_blocks_start + # Do last multiply, reduce, add the four H together and move to + # 32-bit registers + vpmuludq (%rbx), %ymm4, %ymm5 + vpmuludq 32(%rbx), %ymm3, %ymm10 + vpmuludq 32(%rbx), %ymm4, %ymm6 + vpmuludq 64(%rbx), %ymm3, %ymm11 + vpmuludq 64(%rbx), %ymm4, %ymm7 + vpaddq %ymm5, %ymm10, %ymm5 + vpmuludq 64(%rbx), %ymm2, %ymm12 + vpmuludq 96(%rbx), %ymm4, %ymm8 + vpaddq %ymm6, %ymm11, %ymm6 + vpmuludq 96(%rbx), %ymm1, %ymm13 + vpmuludq 96(%rbx), %ymm2, %ymm10 + vpaddq %ymm5, %ymm12, %ymm5 + vpmuludq 96(%rbx), %ymm3, %ymm11 + vpmuludq (%rcx), %ymm3, %ymm12 + vpaddq %ymm5, %ymm13, %ymm5 + vpmuludq (%rcx), %ymm4, %ymm9 + vpaddq %ymm6, %ymm10, %ymm6 + vpmuludq (%rcx), %ymm0, %ymm13 + vpaddq %ymm7, %ymm11, %ymm7 + vpmuludq (%rcx), %ymm1, %ymm10 + vpaddq %ymm8, %ymm12, %ymm8 + vpmuludq (%rcx), %ymm2, %ymm11 + vpmuludq 32(%rcx), %ymm2, %ymm12 + vpaddq %ymm5, %ymm13, %ymm5 + vpmuludq 32(%rcx), %ymm3, %ymm13 + vpaddq %ymm6, %ymm10, %ymm6 + vpmuludq 32(%rcx), %ymm0, %ymm10 + vpaddq %ymm7, %ymm11, %ymm7 + vpmuludq 32(%rcx), %ymm1, %ymm11 + vpaddq %ymm8, %ymm12, %ymm8 + vpmuludq 64(%rcx), %ymm1, %ymm12 + vpaddq %ymm9, %ymm13, %ymm9 + vpmuludq 64(%rcx), %ymm2, %ymm13 + vpaddq %ymm6, %ymm10, %ymm6 + vpmuludq 64(%rcx), %ymm0, %ymm10 + vpaddq %ymm7, %ymm11, %ymm7 + vpmuludq 96(%rcx), %ymm0, %ymm11 + vpaddq %ymm8, %ymm12, %ymm8 + vpmuludq 96(%rcx), %ymm1, %ymm12 + vpaddq %ymm9, %ymm13, %ymm9 + vpaddq %ymm7, %ymm10, %ymm7 + vpmuludq 128(%rcx), %ymm0, %ymm13 + vpaddq %ymm8, %ymm11, %ymm8 + vpaddq %ymm9, %ymm12, %ymm9 + vpaddq %ymm9, %ymm13, %ymm9 + vpsrlq $26, %ymm5, %ymm10 + vpsrlq $26, %ymm8, %ymm11 + vpand %ymm14, %ymm5, %ymm5 + vpand %ymm14, %ymm8, %ymm8 + vpaddq %ymm6, %ymm10, %ymm6 + vpaddq %ymm9, %ymm11, %ymm9 + vpsrlq $26, %ymm6, %ymm10 + vpsrlq $26, %ymm9, %ymm11 + vpand %ymm14, %ymm6, %ymm1 + vpand %ymm14, %ymm9, %ymm4 + vpaddq %ymm7, %ymm10, %ymm7 + vpslld $2, %ymm11, %ymm12 + vpaddd %ymm12, %ymm11, %ymm12 + vpsrlq $26, %ymm7, %ymm10 + vpaddq %ymm5, %ymm12, %ymm5 + vpsrlq $26, %ymm5, %ymm11 + vpand %ymm14, %ymm7, %ymm2 + vpand %ymm14, %ymm5, %ymm0 + vpaddq %ymm8, %ymm10, %ymm8 + vpaddq %ymm1, %ymm11, %ymm1 + vpsrlq $26, %ymm8, %ymm10 + vpand %ymm14, %ymm8, %ymm3 + vpaddq %ymm4, %ymm10, %ymm4 + vpsrldq $8, %ymm0, %ymm5 + vpsrldq $8, %ymm1, %ymm6 + vpsrldq $8, %ymm2, %ymm7 + vpsrldq $8, %ymm3, %ymm8 + vpsrldq $8, %ymm4, %ymm9 + vpaddq %ymm0, %ymm5, %ymm0 + vpaddq %ymm1, %ymm6, %ymm1 + vpaddq %ymm2, %ymm7, %ymm2 + vpaddq %ymm3, %ymm8, %ymm3 + vpaddq %ymm4, %ymm9, %ymm4 + vpermq $2, %ymm0, %ymm5 + vpermq $2, %ymm1, %ymm6 + vpermq $2, %ymm2, %ymm7 + vpermq $2, %ymm3, %ymm8 + vpermq $2, %ymm4, %ymm9 + vpaddq %ymm0, %ymm5, %ymm0 + vpaddq %ymm1, %ymm6, %ymm1 + vpaddq %ymm2, %ymm7, %ymm2 + vpaddq %ymm3, %ymm8, %ymm3 + vpaddq %ymm4, %ymm9, %ymm4 + vmovd %xmm0, %r8d + vmovd %xmm1, %r9d + vmovd %xmm2, %r10d + vmovd %xmm3, %r11d + vmovd %xmm4, %r12d + jmp L_poly1305_avx2_blocks_end_calc +L_poly1305_avx2_blocks_start: + vmovdqu (%rsi), %ymm5 + vmovdqu 32(%rsi), %ymm6 + vperm2i128 $32, %ymm6, %ymm5, %ymm7 + vperm2i128 $49, %ymm6, %ymm5, %ymm5 + vpunpckldq %ymm5, %ymm7, %ymm6 + vpunpckhdq %ymm5, %ymm7, %ymm8 + vpunpckldq %ymm15, %ymm6, %ymm5 + vpunpckhdq %ymm15, %ymm6, %ymm6 + vpunpckldq %ymm15, %ymm8, %ymm7 + vpunpckhdq %ymm15, %ymm8, %ymm8 + vmovdqu L_poly1305_avx2_blocks_hibit(%rip), %ymm9 + vpsllq $6, %ymm6, %ymm6 + vpsllq $12, %ymm7, %ymm7 + vpsllq $18, %ymm8, %ymm8 + vpmuludq (%rbx), %ymm4, %ymm10 + vpaddq %ymm5, %ymm10, %ymm5 + vpmuludq 32(%rbx), %ymm3, %ymm10 + vpmuludq 32(%rbx), %ymm4, %ymm11 + vpaddq %ymm6, %ymm11, %ymm6 + vpmuludq 64(%rbx), %ymm3, %ymm11 + vpmuludq 64(%rbx), %ymm4, %ymm12 + vpaddq %ymm7, %ymm12, %ymm7 + vpaddq %ymm5, %ymm10, %ymm5 + vpmuludq 64(%rbx), %ymm2, %ymm12 + vpmuludq 96(%rbx), %ymm4, %ymm13 + vpaddq %ymm8, %ymm13, %ymm8 + vpaddq %ymm6, %ymm11, %ymm6 + vpmuludq 96(%rbx), %ymm1, %ymm13 + vpmuludq 96(%rbx), %ymm2, %ymm10 + vpaddq %ymm5, %ymm12, %ymm5 + vpmuludq 96(%rbx), %ymm3, %ymm11 + vpmuludq (%rcx), %ymm3, %ymm12 + vpaddq %ymm5, %ymm13, %ymm5 + vpmuludq (%rcx), %ymm4, %ymm13 + vpaddq %ymm9, %ymm13, %ymm9 + vpaddq %ymm6, %ymm10, %ymm6 + vpmuludq (%rcx), %ymm0, %ymm13 + vpaddq %ymm7, %ymm11, %ymm7 + vpmuludq (%rcx), %ymm1, %ymm10 + vpaddq %ymm8, %ymm12, %ymm8 + vpmuludq (%rcx), %ymm2, %ymm11 + vpmuludq 32(%rcx), %ymm2, %ymm12 + vpaddq %ymm5, %ymm13, %ymm5 + vpmuludq 32(%rcx), %ymm3, %ymm13 + vpaddq %ymm6, %ymm10, %ymm6 + vpmuludq 32(%rcx), %ymm0, %ymm10 + vpaddq %ymm7, %ymm11, %ymm7 + vpmuludq 32(%rcx), %ymm1, %ymm11 + vpaddq %ymm8, %ymm12, %ymm8 + vpmuludq 64(%rcx), %ymm1, %ymm12 + vpaddq %ymm9, %ymm13, %ymm9 + vpmuludq 64(%rcx), %ymm2, %ymm13 + vpaddq %ymm6, %ymm10, %ymm6 + vpmuludq 64(%rcx), %ymm0, %ymm10 + vpaddq %ymm7, %ymm11, %ymm7 + vpmuludq 96(%rcx), %ymm0, %ymm11 + vpaddq %ymm8, %ymm12, %ymm8 + vpmuludq 96(%rcx), %ymm1, %ymm12 + vpaddq %ymm9, %ymm13, %ymm9 + vpaddq %ymm7, %ymm10, %ymm7 + vpmuludq 128(%rcx), %ymm0, %ymm13 + vpaddq %ymm8, %ymm11, %ymm8 + vpaddq %ymm9, %ymm12, %ymm9 + vpaddq %ymm9, %ymm13, %ymm9 + vpsrlq $26, %ymm5, %ymm10 + vpsrlq $26, %ymm8, %ymm11 + vpand %ymm14, %ymm5, %ymm5 + vpand %ymm14, %ymm8, %ymm8 + vpaddq %ymm6, %ymm10, %ymm6 + vpaddq %ymm9, %ymm11, %ymm9 + vpsrlq $26, %ymm6, %ymm10 + vpsrlq $26, %ymm9, %ymm11 + vpand %ymm14, %ymm6, %ymm1 + vpand %ymm14, %ymm9, %ymm4 + vpaddq %ymm7, %ymm10, %ymm7 + vpslld $2, %ymm11, %ymm12 + vpaddd %ymm12, %ymm11, %ymm12 + vpsrlq $26, %ymm7, %ymm10 + vpaddq %ymm5, %ymm12, %ymm5 + vpsrlq $26, %ymm5, %ymm11 + vpand %ymm14, %ymm7, %ymm2 + vpand %ymm14, %ymm5, %ymm0 + vpaddq %ymm8, %ymm10, %ymm8 + vpaddq %ymm1, %ymm11, %ymm1 + vpsrlq $26, %ymm8, %ymm10 + vpand %ymm14, %ymm8, %ymm3 + vpaddq %ymm4, %ymm10, %ymm4 + addq $0x40, %rsi + subq $0x40, %rdx + jnz L_poly1305_avx2_blocks_start +L_poly1305_avx2_blocks_store: + # Store four H values - state + vmovdqu %ymm0, (%rax) + vmovdqu %ymm1, 32(%rax) + vmovdqu %ymm2, 64(%rax) + vmovdqu %ymm3, 96(%rax) + vmovdqu %ymm4, 128(%rax) +L_poly1305_avx2_blocks_end_calc: + cmpb $0x00, 616(%rdi) + je L_poly1305_avx2_blocks_complete + movq %r8, %rax + movq %r10, %rdx + movq %r12, %rcx + shrq $12, %rdx + shrq $24, %rcx + shlq $26, %r9 + shlq $52, %r10 + shlq $14, %r11 + shlq $40, %r12 + addq %r9, %rax + adcq %r10, %rax + adcq %r11, %rdx + adcq %r12, %rdx + adcq $0x00, %rcx + movq %rcx, %r8 + andq $3, %rcx + shrq $2, %r8 + leaq 0(%r8,%r8,4), %r8 + addq %r8, %rax + adcq $0x00, %rdx + adcq $0x00, %rcx + movq %rax, 24(%rdi) + movq %rdx, 32(%rdi) + movq %rcx, 40(%rdi) +L_poly1305_avx2_blocks_complete: + movb $0x01, 617(%rdi) + addq $0x140, %rsp + popq %rbx + popq %r12 + repz retq +#ifndef __APPLE__ +.size poly1305_blocks_avx2,.-poly1305_blocks_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl poly1305_final_avx2 +.type poly1305_final_avx2,@function +.align 4 +poly1305_final_avx2: +#else +.section __TEXT,__text +.globl _poly1305_final_avx2 +.p2align 2 +_poly1305_final_avx2: +#endif /* __APPLE__ */ + movb $0x01, 616(%rdi) + movb 617(%rdi), %cl + cmpb $0x00, %cl + je L_poly1305_avx2_final_done_blocks_X4 + pushq %rsi + movq $0x40, %rdx + xorq %rsi, %rsi +#ifndef __APPLE__ + callq poly1305_blocks_avx2@plt +#else + callq _poly1305_blocks_avx2 +#endif /* __APPLE__ */ + popq %rsi +L_poly1305_avx2_final_done_blocks_X4: + movq 608(%rdi), %rax + movq %rax, %rcx + andq $-16, %rcx + cmpb $0x00, %cl + je L_poly1305_avx2_final_done_blocks + pushq %rcx + pushq %rax + pushq %rsi + movq %rcx, %rdx + leaq 480(%rdi), %rsi +#ifndef __APPLE__ + callq poly1305_blocks_avx@plt +#else + callq _poly1305_blocks_avx +#endif /* __APPLE__ */ + popq %rsi + popq %rax + popq %rcx +L_poly1305_avx2_final_done_blocks: + subq %rcx, 608(%rdi) + xorq %rdx, %rdx + jmp L_poly1305_avx2_final_cmp_copy +L_poly1305_avx2_final_start_copy: + movb 480(%rdi,%rcx,1), %r8b + movb %r8b, 480(%rdi,%rdx,1) + incb %cl + incb %dl +L_poly1305_avx2_final_cmp_copy: + cmp %rcx, %rax + jne L_poly1305_avx2_final_start_copy +#ifndef __APPLE__ + callq poly1305_final_avx@plt +#else + callq _poly1305_final_avx +#endif /* __APPLE__ */ + vpxor %ymm0, %ymm0, %ymm0 + vmovdqu %ymm0, 64(%rdi) + vmovdqu %ymm0, 96(%rdi) + vmovdqu %ymm0, 128(%rdi) + vmovdqu %ymm0, 160(%rdi) + vmovdqu %ymm0, 192(%rdi) + vmovdqu %ymm0, 224(%rdi) + vmovdqu %ymm0, 256(%rdi) + vmovdqu %ymm0, 288(%rdi) + vmovdqu %ymm0, 320(%rdi) + movq $0x00, 608(%rdi) + movw $0x00, 616(%rdi) + repz retq +#ifndef __APPLE__ +.size poly1305_final_avx2,.-poly1305_final_avx2 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/README.md b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/README.md new file mode 100644 index 000000000..4f0d0b512 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/README.md @@ -0,0 +1,109 @@ +# ESP32 Port + +Support for the ESP32-WROOM-32 on-board crypto hardware acceleration for symmetric AES, SHA1/SHA256/SHA384/SHA512 and RSA primitive including mul, mulmod and exptmod. + +## ESP32 Acceleration + +For detail about ESP32 HW Acceleration, you can find in [Technical Reference Manual](https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf) + +### Building + +To enable hw acceleration : + +Uncomment out #define WOLFSSL_ESPIDF in /path/to/wolfssl/wolfssl/wolfcrypt/settings.h +Uncomment out #define WOLFSSL_ESPWROOM32 in /path/to/wolfssl/wolfssl/wolfcrypt/settings.h + +To disable portions of the hardware acceleration you can optionally define: + +``` +/* Disabled SHA, AES and RSA acceleration */ +#define NO_ESP32WROOM32_CRYPT +/* Disabled AES acceleration */ +#define NO_WOLFSSL_ESP32WROOM32_CRYPT_AES +/* Disabled SHA acceleration */ +#define NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH +/* Disabled RSA Primitive acceleration */ +#define NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI +``` + +### Coding + +In your application you must include before any other wolfSSL headers. If building the sources directly we recommend defining `WOLFSSL_USER_SETTINGS` and adding your own `user_settings.h` file. You can find a good reference for this in `IDE/GCC-ARM/Header/user_settings.h`. + + +### Benchmarks + +w/ USE_FAST_MATH and WOLFSSL_SMALL_STACK options + +Software only implementation : + +``` +AES-128-CBC-enc 1 MB took 1.001 seconds, 1.146 MB/s +AES-128-CBC-dec 1 MB took 1.017 seconds, 1.104 MB/s +AES-192-CBC-enc 1 MB took 1.018 seconds, 1.055 MB/s +AES-192-CBC-dec 1 MB took 1.006 seconds, 1.019 MB/s +AES-256-CBC-enc 1000 KB took 1.000 seconds, 1000.000 KB/s +AES-256-CBC-dec 975 KB took 1.007 seconds, 968.222 KB/s +AES-128-GCM-enc 350 KB took 1.055 seconds, 331.754 KB/s +AES-128-GCM-dec 350 KB took 1.054 seconds, 332.068 KB/s +AES-192-GCM-enc 325 KB took 1.013 seconds, 320.829 KB/s +AES-192-GCM-dec 325 KB took 1.013 seconds, 320.829 KB/s +AES-256-GCM-enc 325 KB took 1.041 seconds, 312.200 KB/s +AES-256-GCM-dec 325 KB took 1.041 seconds, 312.200 KB/s +SHA 6 MB took 1.004 seconds, 5.714 MB/s +SHA-256 2 MB took 1.006 seconds, 1.747 MB/s +SHA-384 1 MB took 1.011 seconds, 1.159 MB/s +SHA-512 1 MB took 1.009 seconds, 1.161 MB/s +HMAC-SHA 6 MB took 1.001 seconds, 5.634 MB/s +HMAC-SHA256 2 MB took 1.000 seconds, 1.733 MB/s +HMAC-SHA384 1 MB took 1.004 seconds, 1.046 MB/s +HMAC-SHA512 1 MB took 1.002 seconds, 1.048 MB/s +RSA 2048 public 16 ops took 1.056 sec, avg 66.000 ms, 15.152 ops/sec +RSA 2048 private 2 ops took 2.488 sec, avg 1244.000 ms, 0.804 ops/sec +ECC 256 key gen 4 ops took 1.101 sec, avg 275.250 ms, 3.633 ops/sec +ECDHE 256 agree 4 ops took 1.098 sec, avg 274.500 ms, 3.643 ops/sec +ECDSA 256 sign 4 ops took 1.111 sec, avg 277.750 ms, 3.600 ops/sec +ECDSA 256 verify 2 ops took 1.099 sec, avg 549.500 ms, 1.820 ops/sec +``` + +Hardware Acceleration : + + +``` +AES-128-CBC-enc 6 MB took 1.004 seconds, 5.958 MB/s +AES-128-CBC-dec 5 MB took 1.002 seconds, 5.287 MB/s +AES-192-CBC-enc 6 MB took 1.004 seconds, 5.958 MB/s +AES-192-CBC-dec 5 MB took 1.002 seconds, 5.287 MB/s +AES-256-CBC-enc 6 MB took 1.001 seconds, 5.951 MB/s +AES-256-CBC-dec 5 MB took 1.004 seconds, 5.277 MB/s +AES-128-GCM-enc 375 KB took 1.067 seconds, 351.453 KB/s +AES-128-GCM-dec 375 KB took 1.067 seconds, 351.453 KB/s +AES-192-GCM-enc 350 KB took 1.010 seconds, 346.535 KB/s +AES-192-GCM-dec 350 KB took 1.009 seconds, 346.878 KB/s +AES-256-GCM-enc 350 KB took 1.016 seconds, 344.488 KB/s +AES-256-GCM-dec 350 KB took 1.016 seconds, 344.488 KB/s +SHA 14 MB took 1.000 seconds, 14.062 MB/s +SHA-256 15 MB took 1.000 seconds, 15.234 MB/s +SHA-384 17 MB took 1.000 seconds, 17.383 MB/s +SHA-512 18 MB took 1.001 seconds, 17.512 MB/s +HMAC-SHA 14 MB took 1.000 seconds, 13.818 MB/s +HMAC-SHA256 15 MB took 1.001 seconds, 14.951 MB/s +HMAC-SHA384 17 MB took 1.001 seconds, 16.683 MB/s +HMAC-SHA512 17 MB took 1.000 seconds, 16.943 MB/s +RSA 2048 public 20 ops took 1.017 sec, avg 50.850 ms, 19.666 ops/sec +RSA 2048 private 4 ops took 1.059 sec, avg 264.750 ms, 3.777 ops/sec +ECC 256 key gen 4 ops took 1.092 sec, avg 273.000 ms, 3.663 ops/sec +ECDHE 256 agree 4 ops took 1.089 sec, avg 272.250 ms, 3.673 ops/sec +ECDSA 256 sign 4 ops took 1.101 sec, avg 275.250 ms, 3.633 ops/sec +ECDSA 256 verify 2 ops took 1.092 sec, avg 546.000 ms, 1.832 ops/sec +``` + +Condition : +- Model : ESP32-WROOM-32 +- CPU Speed: 240Mhz +- ESP-IDF : v3.3-beta1-39-g6cb37ecc5(commit hash : 6cb37ecc5) +- OS : Ubuntu 18.04.1 LTS (Bionic Beaver) + +## Support + +Email us at [support@wolfssl.com](mailto:support@wolfssl.com). diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_aes.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_aes.c new file mode 100644 index 000000000..f2fb8a5be --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_aes.c @@ -0,0 +1,299 @@ +/* esp32_aes.c + * + * Copyright (C) 2006-2020 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 + */ + +#include +#include + +#ifdef HAVE_CONFIG_H + #include +#endif +#include + +#ifndef NO_AES + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES) + +#include +#include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h" + +static const char* TAG = "wolf_hw_aes"; +/* mutex */ +static wolfSSL_Mutex aes_mutex; +static int espaes_CryptHwMutexInit = 0; + +/* +* lock hw engine. +* this should be called before using engine. +*/ +static int esp_aes_hw_InUse() +{ + int ret = 0; + + ESP_LOGV(TAG, "enter esp_aes_hw_InUse"); + + if(espaes_CryptHwMutexInit == 0) { + ret = esp_CryptHwMutexInit(&aes_mutex); + if(ret == 0){ + espaes_CryptHwMutexInit = 1; + } else { + ESP_LOGE(TAG, "aes mutx initialization failed."); + return -1; + } + } + /* lock hardware */ + ret = esp_CryptHwMutexLock(&aes_mutex, portMAX_DELAY); + if(ret != 0) { + ESP_LOGE(TAG, "aes engine lock failed."); + return -1; + } + /* Enable AES hardware */ + periph_module_enable(PERIPH_AES_MODULE); + + ESP_LOGV(TAG, "leave esp_aes_hw_InUse"); + return ret; +} + +/* +* release hw engine +*/ +static void esp_aes_hw_Leave( void ) +{ + ESP_LOGV(TAG, "enter esp_aes_hw_Leave"); + /* Disable AES hardware */ + periph_module_disable(PERIPH_AES_MODULE); + + /* unlock */ + esp_CryptHwMutexUnLock(&aes_mutex); + + ESP_LOGV(TAG, "leave esp_aes_hw_Leave"); +} + +/* + * set key to hardware key registers. + */ +static void esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode) +{ + int i; + word32 mode_ = 0; + + ESP_LOGV(TAG, "enter esp_aes_hw_Set_KeyMode"); + + /* check mode */ + if(mode == ESP32_AES_UPDATEKEY_ENCRYPT) { + mode_ = 0; + } else if(mode == ESP32_AES_UPDATEKEY_DECRYPT){ + mode_ = 4; + } else { + ESP_LOGE(TAG, "unexpected error."); + return; + } + + /* update key */ + for(i=0;i<(ctx->keylen)/sizeof(word32);i++){ + DPORT_REG_WRITE(AES_KEY_BASE + (i*4), *(((word32*)ctx->key) + i)); + } + + /* mode + * 0 AES-128 Encryption + * 1 AES-192 Encryption + * 2 AES-256 Encryption + * 4 AES-128 Decryption + * 5 AES-192 Decryption + * 6 AES-256 Decryption + */ + switch(ctx->keylen){ + case 24: mode_ += 1; break; + case 32: mode_ += 2; break; + default: break; + } + + DPORT_REG_WRITE(AES_MODE_REG, mode_); + ESP_LOGV(TAG, "leave esp_aes_hw_Setkey"); +} + +/* + * Process a one block of AES + */ +static void esp_aes_bk(const byte* in, byte* out) +{ + const word32 *inwords = (const word32 *)in; + word32 *outwords = (word32 *)out; + + ESP_LOGV(TAG, "enter esp_aes_bk"); + + /* copy text for encrypting/decrypting blocks */ + DPORT_REG_WRITE(AES_TEXT_BASE, inwords[0]); + DPORT_REG_WRITE(AES_TEXT_BASE + 4, inwords[1]); + DPORT_REG_WRITE(AES_TEXT_BASE + 8, inwords[2]); + DPORT_REG_WRITE(AES_TEXT_BASE + 12, inwords[3]); + + /* start engine */ + DPORT_REG_WRITE(AES_START_REG, 1); + + /* wait until finishing the process */ + while(1) { + if(DPORT_REG_READ(AES_IDLE_REG) == 1) + break; + } + + /* read-out blocks */ + esp_dport_access_read_buffer(outwords, AES_TEXT_BASE, 4); + ESP_LOGV(TAG, "leave esp_aes_bk"); +} + +/* +* wc_esp32AesEncrypt +* @brief: a one block encrypt of the input block, into the output block +* @param aes: a pointer of the AES object used to encrypt data +* @param in : a pointer of the input buffer containing plain text to be encrypted +* @param out: a pointer of the output buffer in which to store the cipher text of +* the encrypted message +*/ +int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out) +{ + ESP_LOGV(TAG, "enter wc_esp32AesEncrypt"); + /* lock the hw engine */ + esp_aes_hw_InUse(); + /* load the key into the register */ + esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT); + /* process a one block of AES */ + esp_aes_bk(in, out); + /* release hw */ + esp_aes_hw_Leave(); + return 0; +} +/* +* wc_esp32AesDecrypt +* @brief: a one block decrypt of the input block, into the output block +* @param aes: a pointer of the AES object used to decrypt data +* @param in : a pointer of the input buffer containing plain text to be decrypted +* @param out: a pointer of the output buffer in which to store the cipher text of +* the decrypted message +*/ +int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out) +{ + ESP_LOGV(TAG, "enter wc_esp32AesDecrypt"); + /* lock the hw engine */ + esp_aes_hw_InUse(); + /* load the key into the register */ + esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT); + /* process a one block of AES */ + esp_aes_bk(in, out); + /* release hw engine */ + esp_aes_hw_Leave(); + return 0; +} +/* +* wc_esp32AesCbcEncrypt +* @brief: Encrypts a plain text message from the input buffer, and places the +* resulting cipher text into the output buffer using cipher block chaining +* with AES. +* @param aes: a pointer of the AES object used to encrypt data +* @param out: a pointer of the output buffer in which to store the cipher text of +* the encrypted message +* @param in : a pointer of the input buffer containing plain text to be encrypted +* @param sz : size of input message +*/ +int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int i; + int offset = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + byte *iv; + byte temp_block[AES_BLOCK_SIZE]; + + ESP_LOGV(TAG, "enter wc_esp32AesCbcEncrypt"); + + iv = (byte*)aes->reg; + + esp_aes_hw_InUse(); + + esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT); + + while (blocks--) { + XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE); + + /* XOR block with IV for CBC */ + for (i = 0; i < AES_BLOCK_SIZE; i++) + temp_block[i] ^= iv[i]; + + esp_aes_bk(temp_block, (out + offset)); + + offset += AES_BLOCK_SIZE; + + /* store IV for next block */ + XMEMCPY(iv, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + } + + esp_aes_hw_Leave(); + ESP_LOGV(TAG, "leave wc_esp32AesCbcEncrypt"); + return 0; +} +/* +* wc_esp32AesCbcDecrypt +* @brief: Encrypts a plain text message from the input buffer, and places the +* resulting cipher text into the output buffer using cipher block chaining +* with AES. +* @param aes: a pointer of the AES object used to decrypt data +* @param out: a pointer of the output buffer in which to store the cipher text of +* the decrypted message +* @param in : a pointer of the input buffer containing plain text to be decrypted +* @param sz : size of input message +*/ +int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int i; + int offset = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + byte* iv; + byte temp_block[AES_BLOCK_SIZE]; + + ESP_LOGV(TAG, "enter wc_esp32AesCbcDecrypt"); + + iv = (byte*)aes->reg; + + esp_aes_hw_InUse(); + + esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT); + + while (blocks--) { + XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE); + + esp_aes_bk((in + offset), (out + offset)); + + /* XOR block with IV for CBC */ + for (i = 0; i < AES_BLOCK_SIZE; i++) + (out + offset)[i] ^= iv[i]; + + /* store IV for next block */ + XMEMCPY(iv, temp_block, AES_BLOCK_SIZE); + + offset += AES_BLOCK_SIZE; + } + + esp_aes_hw_Leave(); + ESP_LOGV(TAG, "leave wc_esp32AesCbcDecrypt"); + return 0; +} + +#endif /* WOLFSSL_ESP32WROOM32_CRYPT */ +#endif /* NO_AES */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_mp.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_mp.c new file mode 100644 index 000000000..2174089b1 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_mp.c @@ -0,0 +1,514 @@ +/* esp32_mp.c + * + * Copyright (C) 2006-2020 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 + */ +#include +#include + +#ifdef HAVE_CONFIG_H + #include +#endif +#include + +#include "wolfssl/wolfcrypt/logging.h" + +#if !defined(NO_RSA) || defined(HAVE_ECC) + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif +#include + +static const char* const TAG = "wolfssl_mp"; + +#define ESP_HW_RSAMAX_BIT 4096 +#define ESP_HW_MULTI_RSAMAX_BITS 2048 +#define ESP_HW_RSAMIN_BIT 512 +#define BYTE_TO_WORDS(s) (((s+3)>>2)) /* (s+(4-1))/ 4 */ +#define BITS_TO_WORDS(s) (((s+31)>>3)>>2) /* (s+(32-1))/ 8/ 4*/ + +#define MP_NG -1 + +/* mutex */ +static wolfSSL_Mutex mp_mutex; +static int espmp_CryptHwMutexInit = 0; +/* +* check if the hw is ready before accessing it +*/ +static int esp_mp_hw_wait_clean() +{ + int timeout = 0; + while(++timeout < ESP_RSA_TIMEOUT && DPORT_REG_READ(RSA_CLEAN_REG) != 1){} + + if(timeout >= ESP_RSA_TIMEOUT) { + ESP_LOGE(TAG, "waiting hw ready is time-outed."); + return MP_NG; + } + return MP_OKAY; +} +/* +* lock hw engine. +* this should be called before using engine. +*/ +static int esp_mp_hw_lock() +{ + int ret = 0; + + if(espmp_CryptHwMutexInit == 0) { + ret = esp_CryptHwMutexInit(&mp_mutex); + if(ret == 0){ + espmp_CryptHwMutexInit = 1; + } else { + ESP_LOGE(TAG, "mp mutx initialization failed."); + return MP_NG; + } + } + /* lock hardware */ + ret = esp_CryptHwMutexLock(&mp_mutex, portMAX_DELAY); + if(ret != 0) { + ESP_LOGE(TAG, "mp engine lock failed."); + return MP_NG; + } + /* Enable RSA hardware */ + periph_module_enable(PERIPH_RSA_MODULE); + + return ret; +} +/* +* Release hw engine +*/ +static void esp_mp_hw_unlock( void ) +{ + /* Disable RSA hardware */ + periph_module_disable(PERIPH_RSA_MODULE); + + /* unlock */ + esp_CryptHwMutexUnLock(&mp_mutex); +} +/* this is based on an article by Cetin Kaya Koc, A New Algorithm for Inversion*/ +/* mod p^k, June 28 2017. */ +static int esp_calc_Mdash(mp_int *M, word32 k, mp_digit* md) +{ + int i; + int xi; + int b0 = 1; + int bi; + word32 N = 0; + word32 x; + + N = M->dp[0]; + bi = b0; + x = 0; + + for(i = 0; i < k; i++) { + xi = bi % 2; + if(xi < 0){ + xi *= -1; + } + bi = (bi - N * xi) / 2; + x |= (xi << i); + } + /* 2's complement */ + *md = ~x + 1; + return MP_OKAY; +} +/* start hw process */ +static void process_start(word32 reg) +{ + /* clear interrupt */ + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1); + /* start process */ + DPORT_REG_WRITE(reg, 1); +} +/* wait until done */ +static int wait_uitil_done(word32 reg) +{ + int timeout = 0; + /* wait until done && not timeout */ + while(1) { + if(++timeout < ESP_RSA_TIMEOUT && DPORT_REG_READ(reg) == 1){ + break; + } + } + + /* clear interrupt */ + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1); + + if(timeout >= ESP_RSA_TIMEOUT) { + ESP_LOGE(TAG, "rsa operation is time-outed."); + return MP_NG; + } + + return MP_OKAY; +} +/* read data from memory into mp_init */ +static void esp_memblock_to_mpint(word32 mem_address, mp_int* mp, word32 numwords) +{ + esp_dport_access_read_buffer((uint32_t*)mp->dp, mem_address, numwords); + mp->used = numwords; +} + +/* write mp_init into memory block */ +static void esp_mpint_to_memblock(word32 mem_address, const mp_int* mp, + const word32 bits, + const word32 hwords) +{ + word32 i; + word32 len = (bits / 8 + ((bits & 7) != 0 ? 1 : 0)); + + len = (len+sizeof(word32)-1)/sizeof(word32); + + for(i=0;i < hwords; i++) { + if(i < len) { + DPORT_REG_WRITE(mem_address + (i * sizeof(word32)), mp->dp[i]); + } else { + DPORT_REG_WRITE(mem_address + (i * sizeof(word32)), 0); + } + } +} +/* return needed hw words. */ +/* supported words length */ +/* words : {16 , 32, 48, 64, 80, 96, 112, 128} */ +/* bits : {512,1024, 1536, 2048, 2560, 3072, 3584, 4096} */ +static word32 words2hwords(word32 wd) +{ + const word32 shit_ = 4; + + return (((wd + 0xf)>>shit_)<sign == Y->sign)? MP_ZPOS : MP_NEG; + + word32 Xs; + word32 Ys; + word32 Zs; + word32 maxWords_sz; + word32 hwWords_sz; + + /* ask bits number */ + Xs = mp_count_bits(X); + Ys = mp_count_bits(Y); + Zs = Xs + Ys; + + /* maximum bits and words for writing to hw */ + maxWords_sz = bits2words(max(Xs, Ys)); + hwWords_sz = words2hwords(maxWords_sz); + + /* sanity check */ + if((hwWords_sz<<5) > ESP_HW_MULTI_RSAMAX_BITS) { + ESP_LOGW(TAG, "exceeds max bit length(2048)"); + return -2; + } + + /*Steps to use hw in the following order: + * 1. wait until clean hw engine + * 2. Write(2*N/512bits - 1 + 8) to MULT_MODE_REG + * 3. Write X and Y to memory blocks + * need to write data to each memory block only according to the length + * of the number. + * 4. Write 1 to MUL_START_REG + * 5. Wait for the first operation to be done. Poll INTERRUPT_REG until it reads 1. + * (Or until the INTER interrupt is generated.) + * 6. Write 1 to RSA_INTERRUPT_REG to clear the interrupt. + * 7. Read the Z from RSA_Z_MEM + * 8. Write 1 to RSA_INTERUPT_REG to clear the interrupt. + * 9. Release the hw engine + */ + /* lock hw for use */ + if((ret = esp_mp_hw_lock()) != MP_OKAY) + return ret; + + if((ret = esp_mp_hw_wait_clean()) != MP_OKAY){ + return ret; + } + + /* step.1 (2*N/512) => N/256. 512 bits => 16 words */ + DPORT_REG_WRITE(RSA_MULT_MODE_REG, (hwWords_sz >> 3) - 1 + 8); + /* step.2 write X, M and r_inv into memory */ + esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz); + /* Y(let-extend) */ + esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE + (hwWords_sz<<2), Y, Ys, hwWords_sz); + /* step.3 start process */ + process_start(RSA_MULT_START_REG); + + /* step.4,5 wait until done */ + wait_uitil_done(RSA_INTERRUPT_REG); + /* step.6 read the result form MEM_Z */ + esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(Zs)); + + /* step.7 clear and release hw */ + esp_mp_hw_unlock(); + + Z->sign = (Z->used > 0)? neg : MP_ZPOS; + + return ret; +} +/* Z = X * Y (mod M) */ +int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z) +{ + int ret = 0; + int negcheck = 0; + word32 Xs; + word32 Ys; + word32 Ms; + word32 maxWords_sz; + word32 hwWords_sz; + word32 zwords; + + mp_int r_inv; + mp_int tmpZ; + mp_digit mp; + + /* neg check */ + if(X->sign != Y->sign) { + /* X*Y becomes negative */ + negcheck = 1; + } + /* ask bits number */ + Xs = mp_count_bits(X); + Ys = mp_count_bits(Y); + Ms = mp_count_bits(M); + + /* maximum bits and words for writing to hw */ + maxWords_sz = bits2words(max(Xs, max(Ys, Ms))); + zwords = bits2words(min(Ms, Xs + Ys)); + hwWords_sz = words2hwords(maxWords_sz); + + if((hwWords_sz<<5) > ESP_HW_RSAMAX_BIT) { + ESP_LOGE(TAG, "exceeds hw maximum bits"); + return -2; + } + /* calculate r_inv = R^2 mode M + * where: R = b^n, and b = 2^32 + * accordingly R^2 = 2^(n*32*2) + */ + ret = mp_init_multi(&tmpZ, &r_inv, NULL, NULL, NULL, NULL); + if(ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz<<6))) != MP_OKAY) { + ESP_LOGE(TAG, "calculate r_inv failed."); + mp_clear(&tmpZ); + mp_clear(&r_inv); + return ret; + } + /* lock hw for use */ + if((ret = esp_mp_hw_lock()) != MP_OKAY){ + mp_clear(&tmpZ); + mp_clear(&r_inv); + return ret; + } + /* Calculate M' */ + if((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) { + ESP_LOGE(TAG, "failed to calculate M dash"); + mp_clear(&tmpZ); + mp_clear(&r_inv); + return -1; + } + /*Steps to use hw in the following order: + * 1. wait until clean hw engine + * 2. Write(N/512bits - 1) to MULT_MODE_REG + * 3. Write X,M(=G, X, P) to memory blocks + * need to write data to each memory block only according to the length + * of the number. + * 4. Write M' to M_PRIME_REG + * 5. Write 1 to MODEXP_START_REG + * 6. Wait for the first operation to be done. Poll INTERRUPT_REG until it reads 1. + * (Or until the INTER interrupt is generated.) + * 7. Write 1 to RSA_INTERRUPT_REG to clear the interrupt. + * 8. Write Y to RSA_X_MEM + * 9. Write 1 to RSA_MULT_START_REG + * 10. Wait for the second operation to be completed. Poll INTERRUPT_REG until it reads 1. + * 11. Read the Z from RSA_Z_MEM + * 12. Write 1 to RSA_INTERUPT_REG to clear the interrupt. + * 13. Release the hw engine + */ + + if((ret = esp_mp_hw_wait_clean()) != MP_OKAY){ + return ret; + } + /* step.1 512 bits => 16 words */ + DPORT_REG_WRITE(RSA_MULT_MODE_REG, (hwWords_sz >> 4) - 1); + + /* step.2 write X, M and r_inv into memory */ + esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, M, Ms, hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE, &r_inv, mp_count_bits(&r_inv), + hwWords_sz); + /* step.3 write M' into memory */ + DPORT_REG_WRITE(RSA_M_DASH_REG, mp); + /* step.4 start process */ + process_start(RSA_MULT_START_REG); + + /* step.5,6 wait until done */ + wait_uitil_done(RSA_INTERRUPT_REG); + /* step.7 Y to MEM_X */ + esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, Y, Ys, hwWords_sz); + + /* step.8 start process */ + process_start(RSA_MULT_START_REG); + + /* step.9,11 wait until done */ + wait_uitil_done(RSA_INTERRUPT_REG); + + /* step.12 read the result from MEM_Z */ + esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, &tmpZ, zwords); + + /* step.13 clear and release hw */ + esp_mp_hw_unlock(); + + /* additional steps */ + /* this needs for known issue when Z is greater than M */ + if(mp_cmp(&tmpZ, M)==FP_GT) { + /* Z -= M */ + mp_sub(&tmpZ, M, &tmpZ); + } + if(negcheck) { + mp_sub(M, &tmpZ, &tmpZ); + } + + mp_copy(&tmpZ, Z); + + mp_clear(&tmpZ); + mp_clear(&r_inv); + + return ret; +} +/* Z = X^Y mod M */ +int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z) +{ + int ret = 0; + + word32 Xs; + word32 Ms; + word32 maxWords_sz; + word32 hwWords_sz; + + mp_int r_inv; + mp_digit mp; + + /* ask bits number */ + Xs = mp_count_bits(X); + Ms = mp_count_bits(M); + /* maximum bits and words for writing to hw */ + maxWords_sz = bits2words(max(Xs, max(Ys, Ms))); + hwWords_sz = words2hwords(maxWords_sz); + + if((hwWords_sz<<5) > ESP_HW_RSAMAX_BIT) { + ESP_LOGE(TAG, "exceeds hw maximum bits"); + return -2; + } + /* calculate r_inv = R^2 mode M + * where: R = b^n, and b = 2^32 + * accordingly R^2 = 2^(n*32*2) + */ + ret = mp_init(&r_inv); + if(ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz<<6))) != MP_OKAY) { + ESP_LOGE(TAG, "calculate r_inv failed."); + mp_clear(&r_inv); + return ret; + } + /* lock and init the hw */ + if((ret = esp_mp_hw_lock()) != MP_OKAY) { + mp_clear(&r_inv); + return ret; + } + /* calc M' */ + /* if Pm is odd, uses mp_montgomery_setup() */ + if((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) { + ESP_LOGE(TAG, "failed to calculate M dash"); + mp_clear(&r_inv); + return -1; + } + + /*Steps to use hw in the following order: + * 1. Write(N/512bits - 1) to MODEXP_MODE_REG + * 2. Write X, Y, M and r_inv to memory blocks + * need to write data to each memory block only according to the length + * of the number. + * 3. Write M' to M_PRIME_REG + * 4. Write 1 to MODEXP_START_REG + * 5. Wait for the operation to be done. Poll INTERRUPT_REG until it reads 1. + * (Or until the INTER interrupt is generated.) + * 6. Read the result Z(=Y) from Z_MEM + * 7. Write 1 to INTERRUPT_REG to clear the interrupt. + */ + if((ret = esp_mp_hw_wait_clean()) != MP_OKAY){ + return ret; + } + + /* step.1 */ + DPORT_REG_WRITE(RSA_MODEXP_MODE_REG, (hwWords_sz >> 4) - 1); + /* step.2 write G, X, P, r_inv and M' into memory */ + esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_Y_BLOCK_BASE, Y, Ys, hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, M, Ms, hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE, &r_inv, mp_count_bits(&r_inv), + hwWords_sz); + /* step.3 write M' into memory */ + DPORT_REG_WRITE(RSA_M_DASH_REG, mp); + /* step.4 start process */ + process_start(RSA_START_MODEXP_REG); + + /* step.5 wait until done */ + wait_uitil_done(RSA_INTERRUPT_REG); + /* step.6 read a result form memory */ + esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(Ms)); + /* step.7 clear and release hw */ + esp_mp_hw_unlock(); + + mp_clear(&r_inv); + + return ret; +} +#endif /* !NO_RSA || HAVE_ECC */ +#endif /* (WOLFSS_ESP32WROOM32_CRYPT) && (NO_WOLFSSL_ESP32WROOM32_CRYPT_RES_PRI)*/ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_sha.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_sha.c new file mode 100644 index 000000000..94789cd64 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_sha.c @@ -0,0 +1,434 @@ +/* esp32_sha.c + * + * Copyright (C) 2006-2020 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 + */ +#include +#include + +#ifdef HAVE_CONFIG_H + #include +#endif +#include + +#if !defined(NO_SHA) || !defined(NO_SHA256) || defined(WC_SHA384) || \ + defined(WC_SHA512) + +#include "wolfssl/wolfcrypt/logging.h" + + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + +#include +#include +#include + +#include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h" +#include "wolfssl/wolfcrypt/error-crypt.h" + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +static const char* TAG = "wolf_hw_sha"; +/* continue register offset */ +#define CONTINUE_REG_OFFSET (0x04) /* start_reg + 0x04 */ + +#ifdef NO_SHA + #define WC_SHA_DIGEST_SIZE 20 +#endif +/* mutex */ +#if defined(SINGLE_THREADED) +static int InUse = 0; +#else +static wolfSSL_Mutex sha_mutex; +static int espsha_CryptHwMutexInit = 0; +#endif +/* + enum SHA_TYPE { + SHA1 = 0, + SHA2_256, + SHA2_384, + SHA2_512, + SHA_INVALID = -1, + }; +*/ +static word32 esp_sha_digest_size(enum SHA_TYPE type) +{ + ESP_LOGV(TAG, "enter esp_sha_digest_size"); + + switch(type){ +#ifndef NO_SHA + case SHA1: + return WC_SHA_DIGEST_SIZE; +#endif +#ifndef NO_SHA256 + case SHA2_256: + return WC_SHA256_DIGEST_SIZE; +#endif +#ifdef WOLFSSL_SHA384 + case SHA2_384: + return WC_SHA384_DIGEST_SIZE; +#endif +#ifdef WOLFSSL_SHA512 + case SHA2_512: + return WC_SHA512_DIGEST_SIZE; +#endif + default: + ESP_LOGE(TAG, "Bad sha type"); + return WC_SHA_DIGEST_SIZE; + } + ESP_LOGV(TAG, "leave esp_sha_digest_size"); +} +/* +* wait until engines becomes idle +*/ +static void esp_wait_until_idle() +{ + while((DPORT_REG_READ(SHA_1_BUSY_REG) !=0) || + (DPORT_REG_READ(SHA_256_BUSY_REG)!=0) || + (DPORT_REG_READ(SHA_384_BUSY_REG)!=0) || + (DPORT_REG_READ(SHA_512_BUSY_REG)!=0)){ } +} +/* +* lock hw engine. +* this should be called before using engine. +*/ +int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) +{ + int ret = 0; + + ESP_LOGV(TAG, "enter esp_sha_hw_lock"); + + /* Init mutex */ +#if defined(SINGLE_THREADED) + if(ctx->mode == ESP32_SHA_INIT) { + if(!InUse) { + ctx->mode = ESP32_SHA_HW; + InUse = 1; + } else { + ctx->mode = ESP32_SHA_SW; + } + } else { + /* this should not happens */ + ESP_LOGE(TAG, "unexpected error in esp_sha_try_hw_lock."); + return -1; + } +#else + if(espsha_CryptHwMutexInit == 0){ + ret = esp_CryptHwMutexInit(&sha_mutex); + if(ret == 0) { + espsha_CryptHwMutexInit = 1; + } else { + ESP_LOGE(TAG, " mutex initialization failed."); + ctx->mode = ESP32_SHA_SW; + return 0; + } + } + /* check if this sha has been operated as sw or hw, or not yet init */ + if(ctx->mode == ESP32_SHA_INIT){ + /* try to lock the hw engine */ + if(esp_CryptHwMutexLock(&sha_mutex, (TickType_t)0) == 0) { + ctx->mode = ESP32_SHA_HW; + } else { + ESP_LOGI(TAG, "someone used. hw is locked....."); + ESP_LOGI(TAG, "the rest of operation will use sw implementation for this sha"); + ctx->mode = ESP32_SHA_SW; + return 0; + } + } else { + /* this should not happens */ + ESP_LOGE(TAG, "unexpected error in esp_sha_try_hw_lock."); + return -1; + } +#endif + /* Enable SHA hardware */ + periph_module_enable(PERIPH_SHA_MODULE); + + ESP_LOGV(TAG, "leave esp_sha_hw_lock"); + return ret; +} +/* +* release hw engine +*/ +void esp_sha_hw_unlock( void ) +{ + ESP_LOGV(TAG, "enter esp_sha_hw_unlock"); + + /* Disable AES hardware */ + periph_module_disable(PERIPH_SHA_MODULE); +#if defined(SINGLE_THREADED) + InUse = 0; +#else + /* unlock hw engine for next use */ + esp_CryptHwMutexUnLock(&sha_mutex); +#endif + ESP_LOGV(TAG, "leave esp_sha_hw_unlock"); +} +/* +* start sha process by using hw engine +*/ +static void esp_sha_start_process(WC_ESP32SHA* sha, word32 address) +{ + ESP_LOGV(TAG, "enter esp_sha_start_process"); + + if(sha->isfirstblock){ + /* start first message block */ + DPORT_REG_WRITE(address, 1); + sha->isfirstblock = 0; + } else { + /* CONTINU_REG */ + DPORT_REG_WRITE(address + CONTINUE_REG_OFFSET , 1); + } + + ESP_LOGV(TAG, "leave esp_sha_start_process"); +} +/* +* process message block +*/ +static void esp_process_block(WC_ESP32SHA* ctx, word32 address, + const word32* data, word32 len) +{ + int i; + + ESP_LOGV(TAG, "enter esp_process_block"); + + /* check if there are any busy engine */ + esp_wait_until_idle(); + /* load message data into hw */ + for(i=0;i<((len)/(sizeof(word32)));++i){ + DPORT_REG_WRITE(SHA_TEXT_BASE+(i*sizeof(word32)),*(data+i)); + } + /* notify hw to start process */ + esp_sha_start_process(ctx, address); + + ESP_LOGV(TAG, "leave esp_process_block"); +} +/* +* retrieve sha digest from memory +*/ +static void esp_digest_state(WC_ESP32SHA* ctx, byte* hash, enum SHA_TYPE sha_type) +{ + /* registers */ + word32 SHA_LOAD_REG = SHA_1_LOAD_REG; + word32 SHA_BUSY_REG = SHA_1_BUSY_REG; + + ESP_LOGV(TAG, "enter esp_digest_state"); + + /* sanity check */ + if(sha_type == SHA_INVALID) { + ESP_LOGE(TAG, "unexpected error. sha_type is invalid."); + return; + } + + SHA_LOAD_REG += (sha_type << 4); + SHA_BUSY_REG += (sha_type << 4); + + if(ctx->isfirstblock == 1){ + /* no hardware use yet. Nothing to do yet */ + return ; + } + + /* wait until idle */ + esp_wait_until_idle(); + + /* LOAD final digest */ + DPORT_REG_WRITE(SHA_LOAD_REG, 1); + /* wait until done */ + while(DPORT_REG_READ(SHA_BUSY_REG) == 1){ } + + esp_dport_access_read_buffer((word32*)(hash), SHA_TEXT_BASE, + esp_sha_digest_size(sha_type)/sizeof(word32)); + +#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) + if(sha_type==SHA2_384||sha_type==SHA2_512) { + word32 i; + word32* pwrd1 = (word32*)(hash); + /* swap value */ + for(i = 0; i ctx, SHA_START_REG, (const word32*)data, + WC_SHA_BLOCK_SIZE); + + ESP_LOGV(TAG, "leave esp_sha_process"); + return ret; +} +/* +* retrieve sha1 digest +*/ +int esp_sha_digest_process(struct wc_Sha* sha, byte blockproc) +{ + int ret = 0; + + ESP_LOGV(TAG, "enter esp_sha_digest_process"); + + if(blockproc) { + word32 SHA_START_REG = SHA_1_START_REG; + + esp_process_block(&sha->ctx, SHA_START_REG, sha->buffer, + WC_SHA_BLOCK_SIZE); + } + + esp_digest_state(&sha->ctx, (byte*)sha->digest, SHA1); + + ESP_LOGV(TAG, "leave esp_sha_digest_process"); + + return ret; +} +#endif /* NO_SHA */ + + +#ifndef NO_SHA256 +/* +* sha256 process +*/ +int esp_sha256_process(struct wc_Sha256* sha, const byte* data) +{ + int ret = 0; + word32 SHA_START_REG = SHA_1_START_REG; + + ESP_LOGV(TAG, "enter esp_sha256_process"); + + /* start register offset */ + SHA_START_REG += (SHA2_256 << 4); + + esp_process_block(&sha->ctx, SHA_START_REG, (const word32*)data, + WC_SHA256_BLOCK_SIZE); + + ESP_LOGV(TAG, "leave esp_sha256_process"); + + return ret; +} +/* +* retrieve sha256 digest +*/ +int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockproc) +{ + int ret = 0; + + ESP_LOGV(TAG, "enter esp_sha256_digest_process"); + + if(blockproc) { + word32 SHA_START_REG = SHA_1_START_REG + (SHA2_256 << 4); + + esp_process_block(&sha->ctx, SHA_START_REG, sha->buffer, + WC_SHA256_BLOCK_SIZE); + } + + esp_digest_state(&sha->ctx, (byte*)sha->digest, SHA2_256); + + ESP_LOGV(TAG, "leave esp_sha256_digest_process"); + return ret; +} +#endif /* NO_SHA256 */ + +#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) +/* +* sha512 proess. this is used for sha384 too. +*/ +void esp_sha512_block(struct wc_Sha512* sha, const word32* data, byte isfinal) +{ + enum SHA_TYPE sha_type = sha->ctx.sha_type; + word32 SHA_START_REG = SHA_1_START_REG; + + ESP_LOGV(TAG, "enter esp_sha512_block"); + /* start register offset */ + SHA_START_REG += (sha_type << 4); + + if(sha->ctx.mode == ESP32_SHA_SW){ + ByteReverseWords64(sha->buffer, sha->buffer, + WC_SHA512_BLOCK_SIZE); + if(isfinal){ + sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha->hiLen; + sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha->loLen; + } + + } else { + ByteReverseWords((word32*)sha->buffer, (word32*)sha->buffer, + WC_SHA512_BLOCK_SIZE); + if(isfinal){ + sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = + rotlFixed64(sha->hiLen, 32U); + sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = + rotlFixed64(sha->loLen, 32U); + } + + esp_process_block(&sha->ctx, SHA_START_REG, data, WC_SHA512_BLOCK_SIZE); + } + ESP_LOGV(TAG, "leave esp_sha512_block"); +} +/* +* sha512 process. this is used for sha384 too. +*/ +int esp_sha512_process(struct wc_Sha512* sha) +{ + word32 *data = (word32*)sha->buffer; + + ESP_LOGV(TAG, "enter esp_sha512_process"); + + esp_sha512_block(sha, data, 0); + + ESP_LOGV(TAG, "leave esp_sha512_process"); + return 0; +} +/* +* retrieve sha512 digest. this is used for sha384 too. +*/ +int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc) +{ + ESP_LOGV(TAG, "enter esp_sha512_digest_process"); + + if(blockproc) { + word32* data = (word32*)sha->buffer; + + esp_sha512_block(sha, data, 1); + } + if(sha->ctx.mode != ESP32_SHA_SW) + esp_digest_state(&sha->ctx, (byte*)sha->digest, sha->ctx.sha_type); + + ESP_LOGV(TAG, "leave esp_sha512_digest_process"); + return 0; +} +#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */ +#endif /* WOLFSSL_ESP32WROOM32_CRYPT */ +#endif /* !defined(NO_SHA) ||... */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_util.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_util.c new file mode 100644 index 000000000..b501b5ea6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Espressif/esp32_util.c @@ -0,0 +1,67 @@ +/* esp32_util.c + * + * Copyright (C) 2006-2020 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 + */ +#include + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + (!defined(NO_AES) || !defined(NO_SHA) || !defined(NO_SHA256) ||\ + defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)) + +#include +#include + +int esp_CryptHwMutexInit(wolfSSL_Mutex* mutex) { + return wc_InitMutex(mutex); +} + +int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, TickType_t xBlockTime) { +#ifdef SINGLE_THREADED + return wc_LockMutex(mutex); +#else + return ((xSemaphoreTake( *mutex, xBlockTime ) == pdTRUE) ? 0 : BAD_MUTEX_E); +#endif +} + +int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) { + return wc_UnLockMutex(mutex); +} + +#endif + +#ifdef WOLFSSL_ESP32WROOM32_CRYPT_DEBUG + +#include "esp_timer.h" +#include "esp_log.h" + +static uint64_t startTime = 0; + + +void wc_esp32TimerStart() +{ + startTime = esp_timer_get_time(); +} + +uint64_t wc_esp32elapsedTime() +{ + /* return elapsed time since wc_esp32AesTimeStart() is called in us */ + return esp_timer_get_time() - startTime; +} + +#endif /*WOLFSSL_ESP32WROOM32_CRYPT_DEBUG */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/README.md b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/README.md new file mode 100644 index 000000000..ca60bc574 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/README.md @@ -0,0 +1,176 @@ +# TSIP FIT Module port +Support for TSIP FIT driver for symmetric AES, SHA1/SHA256 hardware acceleration and TLS-linked capability including Root CA, the server certificate or intermediate certificate verification. + +## Overview +Renesas TSIP FIT module with wolfSSL by setting *WOLFSSL_RENESAS_TSIP* definition. + +Including the following examples: + +* simple tls_client/tls_server +* crypt test +* crypt benchmark + + The *user_settings.h* file enables some of the hardened settings. + +## Requirements +### 1. [Renesas TSIP FIT module](https://www.renesas.com/us/en/products/software-tools/software-os-middleware-driver/security-crypto/trusted-secure-ip-driver.html) +[FIT module](https://www.renesas.com/us/en/products/software-tools/software-os-middleware-driver/software-package/fit.html) +Note : The included example program is tested with TSIP FIT version **1.06**. + +### 2. [e2studio](https://www.renesas.com/us/en/products/software-tools/tools/ide/e2studio.html) + +### 3. Evaluation Board that supports TSIP +Note : The included example program is tested with [GR-ROSE](http://gadget.renesas.com/en/product/rose.html), which is classified to RX65N. + +## Setup and Build wolfSSL library + 1. Uncomment out #define WOLFSSL_RENESAS_TSIP in /path/to/wolfssl/wolfssl/wolfcrypt/settings.h + Uncomment out #define WOLFSSL_RENESAS_RX65N in /path/to/wolfssl/wolfssl/wolfcrypt/settings.h + 2. Open a project file at /path/to/wolfssl/IDE/Renesas/e2studio/Projects/wolfssl/ by e2studio and build to create wolfssl library +Note : Generating FIT module source files in advance are required to compile wolfSSL when enabling WOLFSSL_RENESAS_TSIP and WOLFSSL_RENESAS_RX65N. Please see for creating FIT module files at "Setup and Build and example program" in this readme below. + +To disable portions of the hardware acceleration you can optionally define: + +``` +/* Disabled SHA acceleration */ +#define NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH +/* Disabled TLS-linked acceleration */ +#define NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION +``` +### Benchmarks +**Software only implementation:** +*block cipher* +``` +RNG 200 KB took 1.099 seconds, 182.000 KB/s +SHA 1 MB took 1.005 seconds, 1.166 MB/s +SHA-256 425 KB took 1.038 seconds, 409.520 KB/s +``` + +*TLS establishment time* +``` +TLS_RSA_WITH_AES_128_CBC_SHA : 0.651 (s) +TLS_RSA_WITH_AES_128_CBC_SHA256 : 0.651 (s) +TLS_RSA_WITH_AES_256_CBC_SHA : 0.642 (s) +TLS_RSA_WITH_AES_256_CBAC_SHA256 : 0.662 (s) +TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : 2.050 (s) +``` +**Hardware acceleration:** +*block cipher* +``` +RNG 1 MB took 1.011 seconds, 1.038 MB/s +SHA 12 MB took 1.001 seconds, 11.515 MB/s +SHA-256 13 MB took 1.001 seconds, 12.900 MB/s +``` +*TLS establishment time with TLS-linked capability* +*Perform full TlS-linked capability* +``` +TLS_RSA_WITH_AES_128_CBC_SHA : 0.141 (s) +TLS_RSA_WITH_AES_128_CBC_SHA256 : 0.141 (s) +TLS_RSA_WITH_AES_256_CBC_SHA : 0.141 (s) +TLS_RSA_WITH_AES_256_CBAC_SHA256 : 0.144 (s) +``` +*Perform certificate verification by TSIP TLS-linked API* +``` +TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : 1.721 (s) +``` +Condition: +Renesas : e2Studio v7.4.0 +ToolChain : Renesas CCRX version 3.00.00 +TSIP FIT : version 1.0.6 +Board : [GR-ROSE](http://gadget.renesas.com/en/product/rose.html) +wolfSSL : 4.1.0 + + +## Setup and Build an example program +An example program expects the following FIT modules: + +* r_bsp +* r_cmt_rx +* r_config +* r_ether_rx +* r_sys_time_rx +* r_t4_driver_rx +* r_t4_rx +* r_tsip_rx + +These needed source files can be generated by creating a dummy project including Renesas Smart Configurator as steps below: + + 1. Create a dummy project including Renesas Smart Configurator for your evaluation board type + 2. Open Smart Configurator and add FIT modules above + It would need to expand *User Stack Size* property and *Heap Size* of r_bsp. + Change IP ADDRESS and PORT NUMBER in r_t4_rx_config.h + `#define T4_CFG_FIXED_IP_ADDRESS_CH0 192,168,1,33` + `#define T4_CFG_TCP_REPID1_PORT_NUMBER 11111` + Note: It would need to modify other configuration base on evaluation board. + + When using GR-ROSE, you can choose "GR-ROSE" from "board" tab and "board" drop-down list and then is able to follow settings below: + + Go to component tab and open r_ether_rx properties: + Ethernet interface : RMII + The register bus of PHY0 for ETHER0/1: Use ETHER0 + Resource, ETHERC: Check ETHERC0_RMII + + Go to component tab and open r_t4_rx properties: + Enable/Disable DHCP function : 0 + IP address for ch0, when DHCP disable : 192,168,1,33 + TCP REPID1 prot number : 11111 + + Go to pins tab and select ethernet controller + Check to use pins + + 3. Generate source code +Now, it is able to copy these FIT modules into an example project. + 4. Make "smc_gen" folder under /path/to/wolfssl/IDE/Renesas/e2studio/Projects/test/src/ + 5. Copy the FIT modules into the folder that is created at step 4. + 6. Open an example project file at /path/to/wolfssl/IDE/Renesas/e2studio/Projects/test/ by e2studio + 7. Enable a macro definition in /path/to/wolfssl/IDE/Renesas/e2studio/Projects/test/src/wolfssl_demo.h for application type + `#define CRYPT_TEST // enable crypt test` + `#define BENCHMARK // enable benchmark application` + `#define TLS_CLIENT // enable simple tls client application` + `#define TLS_SERVER // enable simple tls server application` + `#define USE_TSIP_TLS // to inform user key and flash keying, when using TSIP` + Note: CRYPT_TEST and BENCHMARK can be enabled at the same time. TLS_CLIENT and TLS_SERVER cannot be enabled together other definitions. + 7. Setup debug configuration based on your debug hardware + +## Run client/server program on the device +When testing the embedded client or server on the device, it is recommended to test against one of the standard wolfSSL example application running on a desktop machine. + + +For the embedded client, an example server commands for running on a desktop machine, IP address 192.168.1.45, is as follows: +`$./example/server/server -b -d -i` + + +For the embedded server, an example client commands for running on a desktop machine is as follows: +`$./example/client/client -h 192.168.1.33 -p 11111` + +## Modify an example program +To use own TSIP keys for TSIP TLS-linked API use, it needs own flash keyring, PSS signed signature and RSA key. + +### Create flash keyring and use it in an example program + 1. Please follow the instruction at TSIP manual, chapter 7. Key Data Operations. + 2. Copy and paste s_flash[] data to s_flash[] data in example-program/key_data.c +`const uint32_t s_flash[] =` + +### Create RSA key pair for signing Root CA verification and use them in an example program + To use TSIP TLS-linked APIs, it needs RSA key pair and Root CA certificate bundle signature by RSA 2048 PSS with SHA256. + Shell and Perl script program in /path/to/wolfssl/IDE/Renesas/e2studio/Projects/tools/ can be used for the purpose. + + * generate_rsa_keypair.sh : generate RSA 2048 bit key pair. Show modulus and public exponent when specifying "-s" option + * rsa_pss_sign.sh : sign the file by the specified private key + * genhexbuf.pl : generate C header file including a byte array generated from the specified file in the script + + Modulus and public exponent showed by `generate_rsa_keypair.sh` can be used for input date to Renesas Secure Flash Programmer to generate encrypted RSA keys for TSIP TLS-linked API use. Please follow the instruction about how to generate RSA keys in the TSIP manual. + + + Generated byte array of signed signature by genhexbuf.pl can be replaced signature data in key_data.c of an example program. + + + Encrypted RSA key and generated byte array of signed signature need to be informed wolfSSL library before loading CA certification. Please see SetTsipTlskey() function an example program about how to inform them. + +### Coding + +In your application you must include before any other wolfSSL headers. If building the sources directly we recommend defining `WOLFSSL_USER_SETTINGS` and adding your own `user_settings.h` file. You can find a good reference for this in `/path/to/Renesas/e2studio/Projects/common/user_settings.h`. + +## Support + For question please email [support@wolfssl.com] + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c new file mode 100644 index 000000000..ce04ff54f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c @@ -0,0 +1,156 @@ +/* renesas_tsip_aes.c + * + * Copyright (C) 2006-2020 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 + */ + +#include +#include + +#ifdef HAVE_CONFIG_H + #include +#endif +#include +#include + +#ifndef NO_AES + +#if defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_AES) + +#include +#include + +#include +#include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h" + +struct Aes; + +int wc_tsip_AesCbcEncrypt(struct Aes* aes, byte* out, const byte* in, word32 sz) +{ + tsip_aes_handle_t _handle; + word32 ret; + word32 blocks = (sz / AES_BLOCK_SIZE); + uint32_t dataLength; + byte *iv; + + if ((in == NULL) || (out == NULL) || (aes == NULL)) + return BAD_FUNC_ARG; + + /* while doing TLS handshake, TSIP driver keeps true-key and iv * + * on the device. iv is dummy */ + iv = (uint8_t*)aes->reg; + + if((ret = tsip_hw_lock()) != 0){ + WOLFSSL_MSG("Failed to lock"); + return ret; + } + + if (aes->ctx.keySize == 16) { + ret = R_TSIP_Aes128CbcEncryptInit(&_handle, &aes->ctx.tsip_keyIdx, iv); + } else if (aes->ctx.keySize == 32) { + ret = R_TSIP_Aes256CbcEncryptInit(&_handle, &aes->ctx.tsip_keyIdx, iv); + } else { + tsip_hw_unlock(); + return -1; + } + + while (ret == TSIP_SUCCESS && blocks--) { + + if (aes->ctx.keySize == 16) + ret = R_TSIP_Aes128CbcEncryptUpdate(&_handle, (uint8_t*)in, + (uint8_t*)out, (uint32_t)AES_BLOCK_SIZE); + else + ret = R_TSIP_Aes256CbcEncryptUpdate(&_handle, (uint8_t*)in, + (uint8_t*)out, (uint32_t)AES_BLOCK_SIZE); + + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + if (ret == TSIP_SUCCESS) { + if (aes->ctx.keySize == 16) { + ret = R_TSIP_Aes128CbcEncryptFinal(&_handle, out, &dataLength); + } else { + ret = R_TSIP_Aes256CbcEncryptFinal(&_handle, out, &dataLength); + } + } else { + WOLFSSL_MSG("TSIP AES CBC encryption failed"); + ret = -1; + } + + tsip_hw_unlock(); + return ret; +} + +int wc_tsip_AesCbcDecrypt(struct Aes* aes, byte* out, const byte* in, word32 sz) +{ + tsip_aes_handle_t _handle; + word32 ret; + word32 blocks = (sz / AES_BLOCK_SIZE); + uint32_t dataLength; + byte *iv; + + if ((in == NULL) || (out == NULL) || (aes == NULL)) + return BAD_FUNC_ARG; + + iv = (uint8_t*)aes->reg; + + if((ret = tsip_hw_lock()) != 0){ + WOLFSSL_MSG("Failed to lock"); + return ret; + } + + if (aes->ctx.keySize == 16) { + ret = R_TSIP_Aes128CbcDecryptInit(&_handle, &aes->ctx.tsip_keyIdx, iv); + } else if (aes->ctx.keySize == 32) { + ret = R_TSIP_Aes256CbcDecryptInit(&_handle, &aes->ctx.tsip_keyIdx, iv); + } else { + tsip_hw_unlock(); + return -1; + } + + while (ret == TSIP_SUCCESS && blocks--) { + + if (aes->ctx.keySize == 16) + ret = R_TSIP_Aes128CbcDecryptUpdate(&_handle, (uint8_t*)in, + (uint8_t*)out, (uint32_t)AES_BLOCK_SIZE); + else + ret = R_TSIP_Aes256CbcDecryptUpdate(&_handle, (uint8_t*)in, + (uint8_t*)out, (uint32_t)AES_BLOCK_SIZE); + + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + if (ret == TSIP_SUCCESS) { + if (aes->ctx.keySize == 16) + ret = R_TSIP_Aes128CbcDecryptFinal(&_handle, out, &dataLength); + else + ret = R_TSIP_Aes256CbcDecryptFinal(&_handle, out, &dataLength); + } else { + WOLFSSL_MSG("TSIP AES CBC decryption failed"); + ret = -1; + } + + tsip_hw_unlock(); + return ret; +} + +#endif /* WOLFSSL_RENESAS_TSIP_CRYPT */ +#endif /* NO_AES */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c new file mode 100644 index 000000000..b12d8eee9 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c @@ -0,0 +1,274 @@ +/* renesas_tsip_sha.c + * + * Copyright (C) 2006-2020 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 + */ +#include +#include + +#ifdef HAVE_CONFIG_H + #include +#endif +#include + +#if !defined(NO_SHA) || !defined(NO_SHA256) + +#include + +#if defined(WOLFSSL_RENESAS_TSIP_CRYPT) + +#include +#include + +#if !defined(NO_SHA) +#include + +static void TSIPHashFree(wolfssl_TSIP_Hash* hash) +{ + if (hash == NULL) + return; + + if (hash->msg != NULL) { + XFREE(hash->msg, hash->heap, DYNAMIC_TYPE_TMP_BUFFER); + hash->msg = NULL; + } +} + +static int TSIPHashInit(wolfssl_TSIP_Hash* hash, void* heap, int devId, + word32 sha_type) +{ + if (hash == NULL) { + return BAD_FUNC_ARG; + } + + (void)devId; + XMEMSET(hash, 0, sizeof(wolfssl_TSIP_Hash)); + + hash->heap = heap; + hash->len = 0; + hash->used = 0; + hash->msg = NULL; + hash->sha_type = sha_type; + + return 0; +} + +static int TSIPHashUpdate(wolfssl_TSIP_Hash* hash, const byte* data, word32 sz) +{ + if (hash == NULL || (sz > 0 && data == NULL)) { + return BAD_FUNC_ARG; + } + + if (hash->len < hash->used + sz) { + if (hash->msg == NULL) { + hash->msg = (byte*)XMALLOC(hash->used + sz, hash->heap, + DYNAMIC_TYPE_TMP_BUFFER); + } else { +#ifdef FREERTOS + byte* pt = (byte*)XMALLOC(hash->used + sz, hash->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (pt == NULL) { + return MEMORY_E; + } + XMEMCPY(pt, hash->msg, hash->used); + XFREE(hash->msg, hash->heap, DYNAMIC_TYPE_TMP_BUFFER); + hash->msg = NULL; + hash->msg = pt; +#else + byte* pt = (byte*)XREALLOC(hash->msg, hash->used + sz, hash->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (pt == NULL) { + return MEMORY_E; + } + hash->msg = pt; +#endif + } + if (hash->msg == NULL) { + return MEMORY_E; + } + hash->len = hash->used + sz; + } + XMEMCPY(hash->msg + hash->used, data , sz); + hash->used += sz; + + return 0; +} + +static int TSIPHashFinal(wolfssl_TSIP_Hash* hash, byte* out, word32 outSz) +{ + int ret; + void* heap; + tsip_sha_md5_handle_t handle; + uint32_t sz; + + e_tsip_err_t (*Init)(tsip_sha_md5_handle_t*); + e_tsip_err_t (*Update)(tsip_sha_md5_handle_t*, uint8_t*, uint32_t); + e_tsip_err_t (*Final )(tsip_sha_md5_handle_t*, uint8_t*, uint32_t*); + + if (hash == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + if (hash->sha_type == TSIP_SHA1) { + Init = R_TSIP_Sha1Init; + Update = R_TSIP_Sha1Update; + Final = R_TSIP_Sha1Final; + } else if (hash->sha_type == TSIP_SHA256) { + Init = R_TSIP_Sha256Init; + Update = R_TSIP_Sha256Update; + Final = R_TSIP_Sha256Final; + } else + return BAD_FUNC_ARG; + + heap = hash->heap; + + tsip_hw_lock(); + + if (Init(&handle) == TSIP_SUCCESS) { + ret = Update(&handle, (uint8_t*)hash->msg, hash->used); + if (ret == TSIP_SUCCESS) { + ret = Final(&handle, out, (uint32_t*)&sz); + if (ret != TSIP_SUCCESS || sz != outSz) { + return ret; + } + } + } + tsip_hw_unlock(); + + TSIPHashFree(hash); + return TSIPHashInit(hash, heap, 0, hash->sha_type); +} + +static int TSIPHashGet(wolfssl_TSIP_Hash* hash, byte* out, word32 outSz) +{ + int ret; + tsip_sha_md5_handle_t handle; + uint32_t sz; + + e_tsip_err_t (*Init)(tsip_sha_md5_handle_t*); + e_tsip_err_t (*Update)(tsip_sha_md5_handle_t*, uint8_t*, uint32_t); + e_tsip_err_t (*Final )(tsip_sha_md5_handle_t*, uint8_t*, uint32_t*); + + if (hash == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + if (hash->sha_type == TSIP_SHA1) { + Init = R_TSIP_Sha1Init; + Update = R_TSIP_Sha1Update; + Final = R_TSIP_Sha1Final; + } else if (hash->sha_type == TSIP_SHA256) { + Init = R_TSIP_Sha256Init; + Update = R_TSIP_Sha256Update; + Final = R_TSIP_Sha256Final; + } else + return BAD_FUNC_ARG; + + tsip_hw_lock(); + + if (Init(&handle) == TSIP_SUCCESS) { + ret = Update(&handle, (uint8_t*)hash->msg, hash->used); + if (ret == TSIP_SUCCESS) { + ret = Final(&handle, out, &sz); + if (ret != TSIP_SUCCESS || sz != outSz) { + return ret; + } + } + } + + tsip_hw_unlock(); + + return 0; +} + +static int TSIPHashCopy(wolfssl_TSIP_Hash* src, wolfssl_TSIP_Hash* dst) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + + XMEMCPY(dst, src, sizeof(wolfssl_TSIP_Hash)); + + if (src->len > 0 && src->msg != NULL) { + dst->msg = (byte*)XMALLOC(src->len, dst->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (dst->msg == NULL) { + return MEMORY_E; + } + XMEMCPY(dst->msg, src->msg, src->len); + } + + return 0; +} + /* */ +int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) +{ + return TSIPHashInit(sha, heap, devId, TSIP_SHA1); +} + +int wc_ShaUpdate(wc_Sha* sha, const byte* in, word32 sz) +{ + return TSIPHashUpdate(sha, in, sz); +} + +int wc_ShaFinal(wc_Sha* sha, byte* hash) +{ + return TSIPHashFinal(sha, hash, WC_SHA_DIGEST_SIZE); +} + +int wc_ShaGetHash(wc_Sha* sha, byte* hash) +{ + return TSIPHashGet(sha, hash, WC_SHA_DIGEST_SIZE); +} + +int wc_ShaCopy(wc_Sha256* src, wc_Sha256* dst) +{ + return TSIPHashCopy(src, dst); +} +#endif /* !NO_SHA */ + +#if !defined(NO_SHA256) +#include + +/* */ +int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId) +{ + return TSIPHashInit(sha, heap, devId, TSIP_SHA256); +} + +int wc_Sha256Update(wc_Sha256* sha, const byte* in, word32 sz) +{ + return TSIPHashUpdate(sha, in, sz); +} + +int wc_Sha256Final(wc_Sha256* sha, byte* hash) +{ + return TSIPHashFinal(sha, hash, WC_SHA256_DIGEST_SIZE); +} + +int wc_Sha256GetHash(wc_Sha256* sha, byte* hash) +{ + return TSIPHashGet(sha, hash, WC_SHA256_DIGEST_SIZE); +} + +int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) +{ + return TSIPHashCopy(src, dst); +} +#endif /* !NO_SHA256 */ +#endif /* WOLFSSL_RENESAS_TSIP_CRYPT */ +#endif /* #if !defined(NO_SHA) || !defined(NO_SHA256) */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/renesas_tsip_util.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/renesas_tsip_util.c new file mode 100644 index 000000000..e3cd7ad24 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/Renesas/renesas_tsip_util.c @@ -0,0 +1,719 @@ +/* renesas_tsip_util.c + * + * Copyright (C) 2006-2020 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 + */ +#include + +#if defined(WOLFSSL_RENESAS_TSIP) + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +/* mutex */ +wolfSSL_Mutex tsip_mutex; +static int tsip_CryptHwMutexInit_ = 0; + +/* ./ca-cert.der.sign, */ +/* expect to have these variables defined at user application */ +extern uint32_t s_flash[]; +extern uint32_t s_inst1[R_TSIP_SINST_WORD_SIZE]; +extern uint32_t s_inst2[R_TSIP_SINST2_WORD_SIZE]; +static const byte *ca_cert_sig; + +/* user key */ +static tsip_key_data g_user_key_info; +/* tsip only keep one encrypted ca public key */ +#if defined(WOLFSSL_RENESAS_TSIP_TLS) +static uint32_t g_encrypted_publicCA_key[R_TSIP_SINST_WORD_SIZE]; +static uint32_t g_CAscm_Idx; /* index of CM table */ +#endif + +static int tsip_CryptHwMutexInit(wolfSSL_Mutex* mutex) { + return wc_InitMutex(mutex); +} + +static int tsip_CryptHwMutexLock(wolfSSL_Mutex* mutex) { + return wc_LockMutex(mutex); +} + +static int tsip_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) { + return wc_UnLockMutex(mutex); +} + +/* +* lock hw engine. +* this should be called before using engine. +*/ +int tsip_hw_lock() +{ + int ret = 0; + + WOLFSSL_MSG("enter esp_sha_hw_lock"); + + if(tsip_CryptHwMutexInit_ == 0){ + ret = tsip_CryptHwMutexInit(&tsip_mutex); + if(ret == 0) { + tsip_CryptHwMutexInit_ = 1; + } else { + WOLFSSL_MSG(" mutex initialization failed."); + return -1; + } + } + if(tsip_CryptHwMutexLock(&tsip_mutex) != 0) { + /* this should not happens */ + return -1; + } + + WOLFSSL_MSG("leave tsip_sha_try_hw_lock"); + return ret; +} + +/* +* release hw engine +*/ +void tsip_hw_unlock( void ) +{ + WOLFSSL_MSG("enter tsip_hw_unlock"); + /* unlock hw engine for next use */ + tsip_CryptHwMutexUnLock(&tsip_mutex); + WOLFSSL_MSG("leave tsip_hw_unlock"); +} +/* check if tsip tls functions can be used for the cipher */ +/* cipher0 : in the some cipher suite, */ +/* first byte becomes greater than 0, otherwise 0x00 */ +/* side : CLIENT END or SEVER END */ +int tsip_useable(const struct WOLFSSL *ssl) +{ + byte cipher0; + byte cipher; + byte side; + + /* sanity check */ + if (ssl == NULL) + return BAD_FUNC_ARG; + + /* when rsa key index == NULL, tsip isn't used for cert verification. */ + /* in the case, we cannot use TSIP. */ + if (!ssl->peerTsipEncRsaKeyIndex) + return 0; + + /* when enabled Extended Master Secret, we cannot use TSIP. */ + if (ssl->options.haveEMS) + return 0; + + cipher0 = ssl->options.cipherSuite0; + cipher = ssl->options.cipherSuite; + side = ssl->options.side; + + if (cipher0 > 0x00) + return 0; + + if ((cipher == l_TLS_RSA_WITH_AES_128_CBC_SHA || + cipher == l_TLS_RSA_WITH_AES_128_CBC_SHA256 || + cipher == l_TLS_RSA_WITH_AES_256_CBC_SHA || + cipher == l_TLS_RSA_WITH_AES_256_CBC_SHA256) && + side == WOLFSSL_CLIENT_END) + return 1; + else + return 0; +} + +/* check if the g_alreadyVerified CA's key can be used for * + * peer's certification */ +byte tsip_checkCA(word32 cmIdx) +{ + return (cmIdx == g_CAscm_Idx? 1:0); +} + +/* check if the root CA has been verified by TSIP, * + * and it exists in the CM table. */ +byte tsip_rootCAverified( ) +{ + return (g_CAscm_Idx != (uint32_t)-1 ? 1:0); +} + +/* open TSIP driver for use */ +int tsip_Open( ) { + + int ret; + + if ((ret = tsip_hw_lock()) == 0) { + /* open the TSIP */ + ret = R_TSIP_Open((uint32_t*)s_flash, s_inst1, s_inst2); + if( ret != TSIP_SUCCESS ) { + WOLFSSL_MSG("RENESAS TSIP Open failed"); + } + +#if defined(WOLFSSL_RENESAS_TSIP_TLS) + /* generate TLS Rsa public key for Certificate verification */ + if (ret == TSIP_SUCCESS && g_user_key_info.encrypted_user_tls_key) { + ret = R_TSIP_GenerateTlsRsaPublicKeyIndex( + g_user_key_info.encrypted_session_key, + g_user_key_info.iv, + g_user_key_info.encrypted_user_tls_key, + &g_user_key_info.user_rsa2048_tls_pubindex); + + if (ret != TSIP_SUCCESS) { + WOLFSSL_MSG("R_TSIP_GenerateTlsRsaPublicKeyIndex failed"); + } else { + /* close once */ + tsip_Close( ); + /* open again with s_inst[] */ + XMEMCPY(s_inst1, + g_user_key_info.user_rsa2048_tls_pubindex.value, + sizeof(s_inst1)); + ret = R_TSIP_Open((uint32_t*)s_flash, s_inst1, s_inst2); + if (ret != TSIP_SUCCESS) { + WOLFSSL_MSG("R_TSIP_(Re)Open failed"); + } + /* init vars */ + g_CAscm_Idx = (uint32_t)-1; + } + } +#endif + /* unlock hw */ + tsip_hw_unlock(); + } else + WOLFSSL_MSG("Failed to lock tsip hw \n"); + + return ret; +} + +/* close TSIP driver */ +void tsip_Close( ) { + int ret; + + if ((ret = tsip_hw_lock()) == 0) { + /* close TSIP */ + ret = R_TSIP_Close(); +#if defined(WOLFSSL_RENESAS_TSIP_TLS) + g_CAscm_Idx = (uint32_t)-1; +#endif + /* unlock hw */ + tsip_hw_unlock(); + if( ret != TSIP_SUCCESS ) { + WOLFSSL_MSG("RENESAS TSIP Close failed"); + } + } else + WOLFSSL_MSG("Failed to unlock tsip hw \n"); +} + +/* Support functions for TSIP TLS Capability */ +#if defined(WOLFSSL_RENESAS_TSIP_TLS) + +/* to inform ca certificate sign */ +/* signature format expects RSA 2048 PSS with SHA256 */ +void tsip_inform_cert_sign(const byte *sign) +{ + if(sign) + ca_cert_sig = sign; +} + +/* inform user key */ +/* the function expects to be called from user application */ +/* user has to create these key information by Renesas tool in advance.*/ +void tsip_inform_user_keys( + byte *encrypted_session_key, + byte *iv, + byte *encrypted_user_tls_key +) +{ + g_user_key_info.encrypted_session_key = NULL; + g_user_key_info.iv = NULL; + g_user_key_info.encrypted_user_tls_key = NULL; + + if ( encrypted_session_key ) { + g_user_key_info.encrypted_session_key = encrypted_session_key; + } + if ( iv ) { + g_user_key_info.iv = iv; + } + if ( encrypted_user_tls_key ) { + g_user_key_info.encrypted_user_tls_key = encrypted_user_tls_key; + } +} + +#ifndef NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION +/* convert def to tsip define */ +static byte _tls2tsipdef(byte cipher) +{ + byte def = R_TSIP_TLS_RSA_WITH_AES_128_CBC_SHA; + switch(cipher){ + case l_TLS_RSA_WITH_AES_128_CBC_SHA: + break; + case l_TLS_RSA_WITH_AES_128_CBC_SHA256: + def = R_TSIP_TLS_RSA_WITH_AES_128_CBC_SHA256; + break; + case l_TLS_RSA_WITH_AES_256_CBC_SHA: + def = R_TSIP_TLS_RSA_WITH_AES_256_CBC_SHA; + break; + case l_TLS_RSA_WITH_AES_256_CBC_SHA256: + def = R_TSIP_TLS_RSA_WITH_AES_256_CBC_SHA256; + break; + default:break; + } + return def; +} + +/* Sha1Hmac */ +int tsip_Sha1Hmac(const struct WOLFSSL *ssl, const byte *myInner, + word32 innerSz, const byte *in, word32 sz, byte *digest, + word32 verify) +{ + tsip_hmac_sha_handle_t _handle; + tsip_hmac_sha_key_index_t key_index; + int ret; + + if ((ssl == NULL) || (myInner == NULL) || (in == NULL) || + (digest == NULL)) + return BAD_FUNC_ARG; + + if ((ret = tsip_hw_lock()) != 0) { + WOLFSSL_MSG("hw lock failed\n"); + return ret; + } + + if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) || + (ssl->options.side == WOLFSSL_SERVER_END && verify) ) + XMEMCPY(key_index.value, ssl->keys.tsip_client_write_MAC_secret, + sizeof(key_index.value)); + else + XMEMCPY(key_index.value, ssl->keys.tsip_server_write_MAC_secret, + sizeof(key_index.value)); + + ret = R_TSIP_Sha1HmacGenerateInit(&_handle, &key_index); + + if (ret == TSIP_SUCCESS) + ret = R_TSIP_Sha1HmacGenerateUpdate(&_handle, (uint8_t*)myInner, + (uint32_t)innerSz); + + if (ret == TSIP_SUCCESS) + ret = R_TSIP_Sha1HmacGenerateUpdate(&_handle, (uint8_t*)in, sz); + + if (ret == TSIP_SUCCESS) + ret = R_TSIP_Sha1HmacGenerateFinal(&_handle, digest); + + /* unlock hw */ + tsip_hw_unlock(); + + return ret; +} + +/* Sha256Hmac */ +int tsip_Sha256Hmac(const struct WOLFSSL *ssl, const byte *myInner, + word32 innerSz, const byte *in, word32 sz, byte *digest, + word32 verify) +{ + tsip_hmac_sha_handle_t _handle; + tsip_hmac_sha_key_index_t key_index; + int ret; + + if ((ssl == NULL) || (myInner == NULL) || (in == NULL) || + (digest == NULL)) + return BAD_FUNC_ARG; + + if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) || + (ssl->options.side == WOLFSSL_SERVER_END && verify) ) + XMEMCPY(key_index.value, ssl->keys.tsip_client_write_MAC_secret, + sizeof(key_index.value)); + else + XMEMCPY(key_index.value, ssl->keys.tsip_server_write_MAC_secret, + sizeof(key_index.value)); + + if ((ret = tsip_hw_lock()) != 0) { + WOLFSSL_MSG("hw lock failed\n"); + return ret; + } + + ret = R_TSIP_Sha256HmacGenerateInit(&_handle, &key_index); + + if (ret == TSIP_SUCCESS) + ret = R_TSIP_Sha256HmacGenerateUpdate(&_handle, (uint8_t*)myInner, + innerSz); + + if (ret == TSIP_SUCCESS) + ret = R_TSIP_Sha256HmacGenerateUpdate(&_handle, (uint8_t*)in, sz); + + if (ret == TSIP_SUCCESS) + ret = R_TSIP_Sha256HmacGenerateFinal(&_handle, digest); + + /* unlock hw */ + tsip_hw_unlock(); + + return ret; +} + +/* generate Verify Data based on master secret */ +int tsip_generateVerifyData(const byte *ms, /* master secret */ + const byte *side, const byte *handshake_hash, + byte *hashes /* out */) +{ + int ret ; + uint32_t l_side = R_TSIP_TLS_GENERATE_CLIENT_VERIFY; + + if ((ms == NULL) || (side == NULL) || (handshake_hash == NULL) || + (hashes == NULL)) + return BAD_FUNC_ARG; + + if (XSTRNCMP((const char*)side, (const char*)tls_server, FINISHED_LABEL_SZ) + == 0) + { + l_side = R_TSIP_TLS_GENERATE_SERVER_VERIFY; + } + + if ((ret = tsip_hw_lock()) == 0) { + ret = R_TSIP_TlsGenerateVerifyData(l_side, (uint32_t*)ms, + (uint8_t*)handshake_hash, hashes/* out */); + if (ret != TSIP_SUCCESS) { + WOLFSSL_MSG("R_TSIP_TlsGenerateSessionKey failed\n"); + } + } + /* unlock hw */ + tsip_hw_unlock(); + + return ret; +} + +/* generate keys for TLS communication */ +int tsip_generateSeesionKey(struct WOLFSSL *ssl) +{ + int ret; + Ciphers *enc; + Ciphers *dec; + tsip_hmac_sha_key_index_t key_client_mac; + tsip_hmac_sha_key_index_t key_server_mac; + tsip_aes_key_index_t key_client_aes; + tsip_aes_key_index_t key_server_aes; + + if (ssl== NULL) + return BAD_FUNC_ARG; + + if ((ret = tsip_hw_lock()) == 0) { + ret = R_TSIP_TlsGenerateSessionKey( + _tls2tsipdef(ssl->options.cipherSuite), + (uint32_t*)ssl->arrays->tsip_masterSecret, + (uint8_t*)ssl->arrays->clientRandom, + (uint8_t*)ssl->arrays->serverRandom, &key_client_mac, + &key_server_mac, &key_client_aes, &key_server_aes, + NULL, NULL); + if (ret != TSIP_SUCCESS) { + WOLFSSL_MSG("R_TSIP_TlsGenerateSessionKey failed\n"); + } else { + /* succeeded creating session keys */ + /* alloc aes instance for both enc and dec */ + enc = &ssl->encrypt; + dec = &ssl->decrypt; + + if (enc) { + if (enc->aes == NULL) { + enc->aes = (Aes*)XMALLOC(sizeof(Aes), ssl->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), ssl->heap, + DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) { + if (enc) { + XFREE(enc->aes, NULL, DYNAMIC_TYPE_CIPHER); + } + return MEMORY_E; + } + } + + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + /* copy key index into aes */ + if (ssl->options.side == PROVISION_CLIENT) { + XMEMCPY(&enc->aes->ctx.tsip_keyIdx, &key_client_aes, + sizeof(key_client_aes)); + XMEMCPY(&dec->aes->ctx.tsip_keyIdx, &key_server_aes, + sizeof(key_server_aes)); + } else { + XMEMCPY(&enc->aes->ctx.tsip_keyIdx, &key_server_aes, + sizeof(key_server_aes)); + XMEMCPY(&dec->aes->ctx.tsip_keyIdx, &key_client_aes, + sizeof(key_client_aes)); + } + /* copy hac key index into keys */ + XMEMCPY(ssl->keys.tsip_client_write_MAC_secret, key_client_mac.value, + sizeof(key_client_mac.value)); + XMEMCPY(ssl->keys.tsip_server_write_MAC_secret, key_server_mac.value, + sizeof(key_client_mac.value)); + /* set up key size and marked readly */ + if (enc){ + enc->aes->ctx.keySize = ssl->specs.key_size; + /* ready for use */ + enc->setup = 1; + } + /* set up key size and marked readly */ + if (dec) { + dec->aes->ctx.keySize = ssl->specs.key_size; + /* ready for use */ + dec->setup = 1; + } + } + /* unlock hw */ + tsip_hw_unlock(); + } else + WOLFSSL_MSG("hw lock failed\n"); + + return ret; +} +/* generate Master secrete by TSIP */ +int tsip_generateMasterSecret(const byte *pr, /* pre-master */ + const byte *cr, /* client random */ + const byte *sr, /* server random */ + byte *ms) +{ + int ret; + + if ((pr == NULL) || (cr == NULL) || (sr == NULL) || + (ms == NULL)) + return BAD_FUNC_ARG; + + if ((ret = tsip_hw_lock()) == 0) { + ret = R_TSIP_TlsGenerateMasterSecret( (uint32_t*)pr, + (uint8_t*)cr, (uint8_t*)sr, (uint32_t*)ms); + if (ret != TSIP_SUCCESS) { + WOLFSSL_MSG("R_TSIP_TlsGenerateMasterSecret failed\n"); + } + /* unlock hw */ + tsip_hw_unlock(); + } else { + WOLFSSL_MSG(" hw lock failed "); + } + + return ret; +} +/* generate pre-Master secrete by TSIP */ +int tsip_generatePremasterSecret(byte *premaster, word32 preSz ) +{ + int ret; + + if (premaster == NULL) + return BAD_FUNC_ARG; + + if ((ret = tsip_hw_lock()) == 0 && preSz >= + (R_TSIP_TLS_MASTER_SECRET_WORD_SIZE*4)) { + /* generate pre-master, 80 bytes */ + ret = R_TSIP_TlsGeneratePreMasterSecret( (uint32_t*)premaster ); + if (ret != TSIP_SUCCESS) { + WOLFSSL_MSG(" R_TSIP_TlsGeneratePreMasterSecret failed\n"); + } + /* unlock hw */ + tsip_hw_unlock(); + } else { + WOLFSSL_MSG(" hw lock failed or preSz is smaller than 80"); + } + + return ret; +} +/* generate encrypted pre-Master secrete by TSIP */ +int tsip_generateEncryptPreMasterSecret(WOLFSSL *ssl, byte *out, word32 *outSz) +{ + int ret; + + if ((ssl == NULL) || (out == NULL) || (outSz == NULL)) + return BAD_FUNC_ARG; + + if ((ret = tsip_hw_lock()) == 0) { + if (*outSz >= 256) + ret = R_TSIP_TlsEncryptPreMasterSecret( + (uint32_t*)ssl->peerTsipEncRsaKeyIndex, + (uint32_t*)&ssl->arrays->preMasterSecret[VERSION_SZ], + (uint8_t*)out); + else + ret = -1; + + if (ret != TSIP_SUCCESS) { + WOLFSSL_MSG(" R_TSIP_TlsEncryptPreMasterSecret failed\n"); + } else { + *outSz = 256; /* TSIP can only handles 2048 RSA */ + } + /* unlock hw */ + tsip_hw_unlock(); + } else { + WOLFSSL_MSG(" hw lock failed "); + } + + return ret; +} +#endif /* NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION */ + +/* Certificate verification by TSIP */ +int tsip_tls_CertVerify(const byte *cert, word32 certSz, + const byte *signature, word32 sigSz, + word32 key_n_start, word32 key_n_len, + word32 key_e_start, word32 key_e_len, + byte *tsip_encRsaKeyIndex) +{ + int ret; + + if (cert == NULL) + return BAD_FUNC_ARG; + + if (!signature) { + WOLFSSL_MSG(" signature for ca verification is not set\n"); + return -1; + } + if (!tsip_encRsaKeyIndex) { + WOLFSSL_MSG(" tsip_encRsaKeyIndex is NULL.\n"); + return -1; + } + + if ((ret = tsip_hw_lock()) == 0) { + ret = R_TSIP_TlsCertificateVerification( + (uint32_t*)g_encrypted_publicCA_key,/* encrypted public key */ + (uint8_t*)cert, /* certificate der */ + certSz, /* length of der */ + (uint8_t*)signature, /* sign data by RSA PSS */ + key_n_start, /* start position of public key n in bytes */ + (key_n_start + key_n_len), /* length of the public key n */ + key_e_start, /* start pos, key e in bytes */ + (key_e_start + key_e_len), /* length of the public key e */ + (uint32_t*)tsip_encRsaKeyIndex /* returned encrypted key */ + ); + + if (ret != TSIP_SUCCESS) { + WOLFSSL_MSG(" R_TSIP_TlsCertificateVerification() failed"); + } + tsip_hw_unlock(); + } else { + WOLFSSL_MSG(" hw lock failed "); + } + + return ret; +} +/* Root Certificate verification */ +int tsip_tls_RootCertVerify(const byte *cert, word32 cert_len, + word32 key_n_start, word32 key_n_len, + word32 key_e_start, word32 key_e_len, + word32 cm_row) +{ + int ret; + /* call to generate encrypted public key for certificate verification */ + uint8_t *signature = (uint8_t*)ca_cert_sig; + + if (cert == NULL) + return BAD_FUNC_ARG; + + if (!signature) { + WOLFSSL_MSG(" signature for ca verification is not set\n"); + return -1; + } + + if ((ret = tsip_hw_lock()) == 0) { + ret = R_TSIP_TlsRootCertificateVerification( + /* CA cert */ + (uint8_t*)cert, + /* length of CA cert */ + (uint32_t)cert_len, + /* Byte position of public key */ + key_n_start, + (key_n_start + key_n_len), + key_e_start, + (key_e_start + key_e_len), + /* signature by "RSA 2048 PSS with SHA256" */ + (uint8_t*)ca_cert_sig, + /* RSA-2048 public key used by + RSA-2048 PSS with SHA256. 560 Bytes*/ + g_encrypted_publicCA_key + ); + + if (ret != TSIP_SUCCESS) { + WOLFSSL_MSG(" R_TSIP_TlsRootCertVerify() failed"); + } else { + g_CAscm_Idx = cm_row; + } + + tsip_hw_unlock(); + } else { + WOLFSSL_MSG(" hw lock failed "); + } + + return ret; +} +#endif /* WOLFSSL_RENESAS_TSIP_TLS */ + +#ifdef WOLFSSL_RENESAS_TSIP_CRYPT_DEBUG + +/* err + * e_tsip_err + TSIP_SUCCESS = 0, + TSIP_ERR_SELF_CHECK1, // Self-check 1 fail or TSIP function internal err. + TSIP_ERR_RESOURCE_CONFLICT, // A resource conflict occurred. + TSIP_ERR_SELF_CHECK2, // Self-check 2 fail. + TSIP_ERR_KEY_SET, // setting the invalid key. + TSIP_ERR_AUTHENTICATION, // Authentication failed. + TSIP_ERR_CALLBACK_UNREGIST, // Callback function is not registered. + TSIP_ERR_PARAMETER, // Illegal Input data. + TSIP_ERR_PROHIBIT_FUNCTION, // An invalid function call occurred. + * TSIP_RESUME_FIRMWARE_GENERATE_MAC, + // There is a continuation of R_TSIP_GenerateFirmwareMAC. +*/ + +static void hexdump(const uint8_t* in, uint32_t len) +{ + uint32_t i; + + if (in == NULL) + return; + + for (i = 0; i <= len;i++, in++){ + printf("%02x:", *in); + if (((i+1)%16)==0){ + printf("\n"); + } + } + printf("\n"); +} + +byte *ret2err(word32 ret) +{ + switch(ret){ + case TSIP_SUCCESS: return "success"; + case TSIP_ERR_SELF_CHECK1: return "selfcheck1"; + case TSIP_ERR_RESOURCE_CONFLICT: return "rsconflict"; + case TSIP_ERR_SELF_CHECK2: return "selfcheck2"; + case TSIP_ERR_KEY_SET: return "keyset"; + case TSIP_ERR_AUTHENTICATION: return "authentication"; + case TSIP_ERR_CALLBACK_UNREGIST: return "callback unreg"; + case TSIP_ERR_PARAMETER: return "badarg"; + case TSIP_ERR_PROHIBIT_FUNCTION: return "prohibitfunc"; + case TSIP_RESUME_FIRMWARE_GENERATE_MAC: return "conti-generate-mac"; + default:return "unknown"; + } +} + +#endif /* WOLFSSL_RENESAS_TSIP_CRYPT_DEBUG */ +#endif /* WOLFSSL_RENESAS_TSIP */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/af_alg/afalg_aes.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/af_alg/afalg_aes.c new file mode 100644 index 000000000..2d1d41a6a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/af_alg/afalg_aes.c @@ -0,0 +1,900 @@ +/* afalg_aes.c + * + * Copyright (C) 2006-2020 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(NO_AES) && (defined(WOLFSSL_AFALG) || \ + defined(WOLFSSL_AFALG_XILINX_AES)) + +#include +#include +#include + +#include /* for readv */ + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef WOLFSSL_AFALG_XILINX_AES + #define WOLFSSL_XILINX_ALIGN sizeof(wolfssl_word) +#endif + +static const char WC_TYPE_SYMKEY[] = "skcipher"; + +static int wc_AesSetup(Aes* aes, const char* type, const char* name, int ivSz, int aadSz) +{ +#ifdef WOLFSSL_AFALG_XILINX_AES + byte* key = (byte*)aes->msgBuf; +#else + byte* key = (byte*)aes->key; +#endif + + aes->rdFd = wc_Afalg_CreateRead(aes->alFd, type, name); + if (aes->rdFd < 0) { + WOLFSSL_MSG("Unable to accept and get AF_ALG read socket"); + aes->rdFd = WC_SOCK_NOTSET; + return aes->rdFd; + } + + if (setsockopt(aes->alFd, SOL_ALG, ALG_SET_KEY, key, aes->keylen) != 0) { + WOLFSSL_MSG("Unable to set AF_ALG key"); + aes->rdFd = WC_SOCK_NOTSET; + return WC_AFALG_SOCK_E; + } + ForceZero(key, sizeof(aes->key)); + + /* set up CMSG headers */ + XMEMSET((byte*)&(aes->msg), 0, sizeof(struct msghdr)); + + aes->msg.msg_control = key; /* use existing key buffer for + * control buffer */ +#ifdef WOLFSSL_AFALG_XILINX_AES + aes->msg.msg_controllen = CMSG_SPACE(4) + + CMSG_SPACE(sizeof(struct af_alg_iv) + ivSz); + (void)aadSz; +#else + aes->msg.msg_controllen = CMSG_SPACE(4); + if (aadSz > 0) { + aes->msg.msg_controllen += CMSG_SPACE(4); + } + if (ivSz > 0) { + aes->msg.msg_controllen += CMSG_SPACE((sizeof(struct af_alg_iv) + ivSz)); + } +#endif + + if (wc_Afalg_SetOp(CMSG_FIRSTHDR(&(aes->msg)), aes->dir) < 0) { + WOLFSSL_MSG("Error with setting AF_ALG operation"); + aes->rdFd = WC_SOCK_NOTSET; + return -1; + } + + return 0; +} + + +#ifdef WOLFSSL_AFALG +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 || + !((keylen == 16) || (keylen == 24) || (keylen == 32))) { + return BAD_FUNC_ARG; + } + +#if defined(AES_MAX_KEY_SIZE) + /* Check key length */ + if (keylen > max_key_len) { + return BAD_FUNC_ARG; + } +#endif + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + +#ifdef WOLFSSL_AES_COUNTER + aes->left = 0; +#endif + + aes->rdFd = WC_SOCK_NOTSET; + aes->alFd = wc_Afalg_Socket(); + if (aes->alFd < 0) { + WOLFSSL_MSG("Unable to open an AF_ALG socket"); + return WC_AFALG_SOCK_E; + } + + /* save key until type is known i.e. CBC, ECB, ... */ + XMEMCPY((byte*)(aes->key), userKey, keylen); + aes->dir = dir; + + return wc_AesSetIV(aes, iv); +} +#endif + +/* AES-CBC */ +#if defined(HAVE_AES_CBC) && defined(WOLFSSL_AFALG) + static const char WC_NAME_AESCBC[] = "cbc(aes)"; + + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + struct cmsghdr* cmsg; + struct iovec iov; + int ret; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + if (aes->rdFd == WC_SOCK_NOTSET) { + if ((ret = wc_AesSetup(aes, WC_TYPE_SYMKEY, WC_NAME_AESCBC, + AES_IV_SIZE, 0)) != 0) { + WOLFSSL_MSG("Error with first time setup of AF_ALG socket"); + return ret; + } + } + + sz = sz - (sz % AES_BLOCK_SIZE); + if ((sz / AES_BLOCK_SIZE) > 0) { + /* update IV */ + cmsg = CMSG_FIRSTHDR(&(aes->msg)); + ret = wc_Afalg_SetIv(CMSG_NXTHDR(&(aes->msg), cmsg), + (byte*)(aes->reg), AES_IV_SIZE); + if (ret < 0) { + WOLFSSL_MSG("Error setting IV"); + return ret; + } + + /* set data to be encrypted */ + iov.iov_base = (byte*)in; + iov.iov_len = sz; + + aes->msg.msg_iov = &iov; + aes->msg.msg_iovlen = 1; /* # of iov structures */ + + ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0); + if (ret < 0) { + return ret; + } + ret = (int)read(aes->rdFd, out, sz); + if (ret < 0) { + return ret; + } + + /* set IV for next CBC call */ + XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + } + + return 0; + } + + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + struct cmsghdr* cmsg; + struct iovec iov; + int ret; + + if (aes == NULL || out == NULL || in == NULL + || sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + if (aes->rdFd == WC_SOCK_NOTSET) { + if ((ret = wc_AesSetup(aes, WC_TYPE_SYMKEY, WC_NAME_AESCBC, + AES_IV_SIZE, 0)) != 0) { + return ret; + } + } + + if ((sz / AES_BLOCK_SIZE) > 0) { + /* update IV */ + cmsg = CMSG_FIRSTHDR(&(aes->msg)); + ret = wc_Afalg_SetIv(CMSG_NXTHDR(&(aes->msg), cmsg), + (byte*)(aes->reg), AES_IV_SIZE); + if (ret != 0) { + return ret; + } + + /* set data to be decrypted */ + iov.iov_base = (byte*)in; + iov.iov_len = sz; + + aes->msg.msg_iov = &iov; + aes->msg.msg_iovlen = 1; /* # of iov structures */ + + /* set IV for next CBC call */ + XMEMCPY(aes->reg, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0); + if (ret < 0) { + return ret; + } + ret = (int)read(aes->rdFd, out, sz); + if (ret < 0) { + return ret; + } + + } + + return 0; + } + #endif + +#endif /* HAVE_AES_CBC */ + + +/* AES-DIRECT */ +#if (defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AES_ECB)) && \ + defined(WOLFSSL_AFALG) + +static const char WC_NAME_AESECB[] = "ecb(aes)"; + +/* common code between ECB encrypt and decrypt + * returns 0 on success */ +static int wc_Afalg_AesDirect(Aes* aes, byte* out, const byte* in, word32 sz) +{ + struct iovec iov; + int ret; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + if (aes->rdFd == WC_SOCK_NOTSET) { + if ((ret = wc_AesSetup(aes, WC_TYPE_SYMKEY, WC_NAME_AESECB, + 0, 0)) != 0) { + WOLFSSL_MSG("Error with first time setup of AF_ALG socket"); + return ret; + } + } + + /* set data to be encrypted */ + iov.iov_base = (byte*)in; + iov.iov_len = sz; + + aes->msg.msg_iov = &iov; + aes->msg.msg_iovlen = 1; /* # of iov structures */ + + ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0); + if (ret < 0) { + return ret; + } + ret = (int)read(aes->rdFd, out, sz); + if (ret < 0) { + return ret; + } + + return 0; +} +#endif + + +#if defined(WOLFSSL_AES_DIRECT) && defined(WOLFSSL_AFALG) +void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) +{ + if (wc_Afalg_AesDirect(aes, out, in, AES_BLOCK_SIZE) != 0) { + WOLFSSL_MSG("Error with AES encrypt direct call"); + } +} + + +void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) +{ + if (wc_Afalg_AesDirect(aes, out, in, AES_BLOCK_SIZE) != 0) { + WOLFSSL_MSG("Error with AES decrypt direct call"); + } +} + + +int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) +{ + return wc_AesSetKey(aes, userKey, keylen, iv, dir); +} +#endif + + +/* AES-CTR */ +#if defined(WOLFSSL_AES_COUNTER) && defined(WOLFSSL_AFALG) + static const char WC_NAME_AESCTR[] = "ctr(aes)"; + + /* Increment AES counter */ + static WC_INLINE void IncrementAesCounter(byte* inOutCtr) + { + /* 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; + } + } + + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + struct cmsghdr* cmsg; + struct iovec iov[2]; + int ret; + 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--; + sz--; + } + + if (aes->rdFd == WC_SOCK_NOTSET) { + if ((ret = wc_AesSetup(aes, WC_TYPE_SYMKEY, WC_NAME_AESCTR, + AES_IV_SIZE, 0)) != 0) { + WOLFSSL_MSG("Error with first time setup of AF_ALG socket"); + return ret; + } + } + + if (sz > 0) { + aes->left = sz % AES_BLOCK_SIZE; + + /* clear previously leftover data */ + tmp = (byte*)aes->tmp; + XMEMSET(tmp, 0, AES_BLOCK_SIZE); + + /* update IV */ + cmsg = CMSG_FIRSTHDR(&(aes->msg)); + ret = wc_Afalg_SetIv(CMSG_NXTHDR(&(aes->msg), cmsg), + (byte*)(aes->reg), AES_IV_SIZE); + if (ret < 0) { + WOLFSSL_MSG("Error setting IV"); + return ret; + } + + /* set data to be encrypted */ + iov[0].iov_base = (byte*)in; + iov[0].iov_len = sz - aes->left; + + iov[1].iov_base = tmp; + if (aes->left > 0) { + XMEMCPY(tmp, in + sz - aes->left, aes->left); + iov[1].iov_len = AES_BLOCK_SIZE; + } + else { + iov[1].iov_len = 0; + } + + aes->msg.msg_iov = iov; + aes->msg.msg_iovlen = 2; /* # of iov structures */ + + ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0); + if (ret < 0) { + return ret; + } + + + /* set buffers to hold result and left over stream */ + iov[0].iov_base = (byte*)out; + iov[0].iov_len = sz - aes->left; + + iov[1].iov_base = tmp; + if (aes->left > 0) { + iov[1].iov_len = AES_BLOCK_SIZE; + } + else { + iov[1].iov_len = 0; + } + + ret = (int)readv(aes->rdFd, iov, 2); + if (ret < 0) { + return ret; + } + + if (aes->left > 0) { + XMEMCPY(out + sz - aes->left, tmp, aes->left); + aes->left = AES_BLOCK_SIZE - aes->left; + } + } + + /* adjust counter after call to hardware */ + while (sz >= AES_BLOCK_SIZE) { + IncrementAesCounter((byte*)aes->reg); + sz -= AES_BLOCK_SIZE; + } + + if (aes->left > 0) { + IncrementAesCounter((byte*)aes->reg); + } + + return 0; + } +#endif /* WOLFSSL_AES_COUNTER */ + + +#ifdef HAVE_AESGCM + + +#ifdef WOLFSSL_AFALG_XILINX_AES + static const char WC_NAME_AESGCM[] = "xilinx-zynqmp-aes"; + static const char* WC_TYPE_AEAD = WC_TYPE_SYMKEY; +#else + static const char WC_NAME_AESGCM[] = "gcm(aes)"; + static const char WC_TYPE_AEAD[] = "aead"; +#endif + +#ifndef WC_SYSTEM_AESGCM_IV +/* size of IV allowed on system for AES-GCM */ +#define WC_SYSTEM_AESGCM_IV 12 +#endif + +#ifndef WOLFSSL_MAX_AUTH_TAG_SZ +/* size of tag is restricted by system for AES-GCM + * check 'cat /proc/crypto' to see restricted size */ +#define WOLFSSL_MAX_AUTH_TAG_SZ 16 +#endif + +#ifdef WOLFSSL_AFALG_XILINX_AES +/* Xilinx uses a slightly different function because the default AES key is also + * needed if handling additional data with creating/validating the TAG. + * + * returns 0 on success + */ +int wc_AesGcmSetKey_ex(Aes* aes, const byte* key, word32 len, word32 kup) +#else +int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) +#endif +{ +#if defined(AES_MAX_KEY_SIZE) + const word32 max_key_len = (AES_MAX_KEY_SIZE / 8); +#endif + + if (aes == NULL || + !((len == 16) || (len == 24) || (len == 32))) { + return BAD_FUNC_ARG; + } + +#if defined(AES_MAX_KEY_SIZE) + /* Check key length */ + if (len > max_key_len) { + return BAD_FUNC_ARG; + } +#endif + aes->keylen = len; + aes->rounds = len/4 + 6; + + aes->rdFd = WC_SOCK_NOTSET; + aes->alFd = wc_Afalg_Socket(); + if (aes->alFd < 0) { + WOLFSSL_MSG("Unable to open an AF_ALG socket"); + return WC_AFALG_SOCK_E; + } + + /* save key until direction is known i.e. encrypt or decrypt */ +#ifdef WOLFSSL_AFALG_XILINX_AES + (void)kup; /* using alternate buffer because software key is needed */ + XMEMCPY((byte*)(aes->msgBuf), key, len); +#else + XMEMCPY((byte*)(aes->key), key, len); +#endif + + return 0; +} + + + +/* Performs AES-GCM encryption and returns 0 on success + * + * Warning: If using Xilinx hardware acceleration it is assumed that the out + * buffer is large enough to hold both cipher text and tag. That is + * sz | 16 bytes. The input and output buffer is expected to be 64 bit + * aligned + * + */ +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) +{ + struct cmsghdr* cmsg; + struct iovec iov[3]; + int ret; + struct msghdr* msg; + byte scratch[AES_BLOCK_SIZE]; + + /* argument checks */ + if (aes == NULL || authTagSz > AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + if (ivSz != WC_SYSTEM_AESGCM_IV || authTagSz > WOLFSSL_MAX_AUTH_TAG_SZ) { + WOLFSSL_MSG("IV/AAD size not supported on system"); + return BAD_FUNC_ARG; + } + + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + + if (aes->rdFd == WC_SOCK_NOTSET) { + aes->dir = AES_ENCRYPTION; + if ((ret = wc_AesSetup(aes, WC_TYPE_AEAD, WC_NAME_AESGCM, ivSz, + authInSz)) != 0) { + WOLFSSL_MSG("Error with first time setup of AF_ALG socket"); + return ret; + } + + /* note that if the ivSz was to change, the msg_controllen would need + reset */ + +#ifndef WOLFSSL_AFALG_XILINX_AES + /* set auth tag + * @TODO case where tag size changes between calls? */ + ret = setsockopt(aes->alFd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, + authTagSz); + if (ret != 0) { + perror("set tag"); + WOLFSSL_MSG("Unable to set AF_ALG tag size "); + return WC_AFALG_SOCK_E; + } +#endif + } + + + msg = &(aes->msg); + cmsg = CMSG_FIRSTHDR(msg); + cmsg = CMSG_NXTHDR(msg, cmsg); + + /* set IV and AAD size */ + ret = wc_Afalg_SetIv(cmsg, (byte*)iv, ivSz); + if (ret < 0) { + WOLFSSL_MSG("Error setting IV"); + return ret; + + } +#ifdef WOLFSSL_AFALG_XILINX_AES + if (sz > 0) { + #ifndef NO_WOLFSSL_ALLOC_ALIGN + byte* tmp = NULL; + #endif + if ((wolfssl_word)in % WOLFSSL_XILINX_ALIGN) { + #ifndef NO_WOLFSSL_ALLOC_ALIGN + byte* tmp_align; + tmp = (byte*)XMALLOC(sz + WOLFSSL_XILINX_ALIGN + + AES_BLOCK_SIZE, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + tmp_align = tmp + (WOLFSSL_XILINX_ALIGN - + ((size_t)tmp % WOLFSSL_XILINX_ALIGN)); + XMEMCPY(tmp_align, in, sz); + iov[0].iov_base = tmp_align; + #else + WOLFSSL_MSG("Buffer expected to be word aligned"); + return BAD_ALIGN_E; + #endif + } + else { + iov[0].iov_base = (byte*)in; + } + iov[0].iov_len = sz + AES_BLOCK_SIZE; + + msg->msg_iov = iov; + msg->msg_iovlen = 1; /* # of iov structures */ + + ret = (int)sendmsg(aes->rdFd, msg, 0); + #ifndef NO_WOLFSSL_ALLOC_ALIGN + XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + if (ret < 0) { + return ret; + } + + ret = read(aes->rdFd, out, sz + AES_BLOCK_SIZE); + if (ret < 0) { + return ret; + } + XMEMCPY(authTag, out + sz, authTagSz); + } + + /* handle completing tag with using software if additional data added */ + if (authIn != NULL && authInSz > 0) { + byte initalCounter[AES_BLOCK_SIZE]; + 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); + } +#else + if (authInSz > 0) { + cmsg = CMSG_NXTHDR(msg, cmsg); + ret = wc_Afalg_SetAad(cmsg, authInSz); + if (ret < 0) { + WOLFSSL_MSG("Unable to set AAD size"); + return ret; + } + } + + /* set data to be encrypted*/ + iov[0].iov_base = (byte*)authIn; + iov[0].iov_len = authInSz; + + iov[1].iov_base = (byte*)in; + iov[1].iov_len = sz; + + msg->msg_iov = iov; + msg->msg_iovlen = 2; /* # of iov structures */ + + ret = (int)sendmsg(aes->rdFd, msg, 0); + if (ret < 0) { + return ret; + } + + { + byte* tmp = (byte*)XMALLOC(authInSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + /* first 16 bytes was all 0's */ + iov[0].iov_base = tmp; + (void)scratch; + iov[0].iov_len = authInSz; + + iov[1].iov_base = out; + iov[1].iov_len = sz; + + iov[2].iov_base = authTag; + iov[2].iov_len = authTagSz; + + ret = (int)readv(aes->rdFd, iov, 3); + XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (ret < 0) { + return ret; + } +#endif + + + return 0; +} + +#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT) +/* Performs AES-GCM decryption and returns 0 on success + * + * Warning: If using Xilinx hardware acceleration it is assumed that the in + * buffer is large enough to hold both cipher text and tag. That is + * sz | 16 bytes + */ +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) +{ + struct cmsghdr* cmsg; + struct msghdr* msg; + struct iovec iov[3]; + byte scratch[AES_BLOCK_SIZE]; + int ret; +#ifdef WOLFSSL_AFALG_XILINX_AES + byte* tag = (byte*)authTag; + byte buf[AES_BLOCK_SIZE]; + byte initalCounter[AES_BLOCK_SIZE]; +#ifndef NO_WOLFSSL_ALLOC_ALIGN + byte* tmp = NULL; +#endif +#endif + + /* argument checks */ + if (aes == NULL || authTagSz > AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + if (ivSz != WC_SYSTEM_AESGCM_IV || authTagSz > WOLFSSL_MAX_AUTH_TAG_SZ) { + WOLFSSL_MSG("IV/AAD size not supported on system"); + return BAD_FUNC_ARG; + } + + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + + if (aes->rdFd == WC_SOCK_NOTSET) { + aes->dir = AES_DECRYPTION; + if ((ret = wc_AesSetup(aes, WC_TYPE_AEAD, WC_NAME_AESGCM, ivSz, + authInSz)) != 0) { + WOLFSSL_MSG("Error with first time setup of AF_ALG socket"); + return ret; + } + +#ifndef WOLFSSL_AFALG_XILINX_AES + /* set auth tag + * @TODO case where tag size changes between calls? */ + ret = setsockopt(aes->alFd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, + authTagSz); + if (ret != 0) { + WOLFSSL_MSG("Unable to set AF_ALG tag size "); + return WC_AFALG_SOCK_E; + } +#endif + } + + /* set IV and AAD size */ + msg = &aes->msg; + if ((cmsg = CMSG_FIRSTHDR(msg)) == NULL) { + return WC_AFALG_SOCK_E; + } + if (wc_Afalg_SetOp(cmsg, aes->dir) < 0) { + WOLFSSL_MSG("Error with setting AF_ALG operation"); + return WC_AFALG_SOCK_E; + } + if ((cmsg = CMSG_NXTHDR(msg, cmsg)) == NULL) { + return WC_AFALG_SOCK_E; + } + ret = wc_Afalg_SetIv(cmsg, (byte*)iv, ivSz); + if (ret < 0) { + return ret; + } + +#ifdef WOLFSSL_AFALG_XILINX_AES + /* check for and handle 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_BLOCK_SIZE); + wc_AesEncryptDirect(aes, scratch, initalCounter); + xorbuf(tag, scratch, AES_BLOCK_SIZE); + if (ret != 0) { + return AES_GCM_AUTH_E; + } + } + + /* it is assumed that in buffer size is large enough to hold TAG */ + XMEMCPY((byte*)in + sz, tag, AES_BLOCK_SIZE); + if ((wolfssl_word)in % WOLFSSL_XILINX_ALIGN) { + #ifndef NO_WOLFSSL_ALLOC_ALIGN + byte* tmp_align; + tmp = (byte*)XMALLOC(sz + WOLFSSL_XILINX_ALIGN + + AES_BLOCK_SIZE, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + tmp_align = tmp + (WOLFSSL_XILINX_ALIGN - + ((size_t)tmp % WOLFSSL_XILINX_ALIGN)); + XMEMCPY(tmp_align, in, sz + AES_BLOCK_SIZE); + iov[0].iov_base = tmp_align; + #else + WOLFSSL_MSG("Buffer expected to be word aligned"); + return BAD_ALIGN_E; + #endif + } + else { + iov[0].iov_base = (byte*)in; + } + iov[0].iov_len = sz + AES_BLOCK_SIZE; + + msg->msg_iov = iov; + msg->msg_iovlen = 1; + + ret = sendmsg(aes->rdFd, msg, 0); +#ifndef NO_WOLFSSL_ALLOC_ALIGN + XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + if (ret < 0) { + return ret; + } + + ret = read(aes->rdFd, out, sz + AES_BLOCK_SIZE); + if (ret < 0) { + return AES_GCM_AUTH_E; + } + + /* check on tag */ + if (authIn != NULL && authInSz > 0) { + GHASH(aes, authIn, authInSz, in, sz, tag, AES_BLOCK_SIZE); + wc_AesEncryptDirect(aes, scratch, initalCounter); + xorbuf(tag, scratch, AES_BLOCK_SIZE); + if (ConstantCompare(tag, authTag, authTagSz) != 0) { + return AES_GCM_AUTH_E; + } + } + +#else + if (authInSz > 0) { + cmsg = CMSG_NXTHDR(msg, cmsg); + ret = wc_Afalg_SetAad(cmsg, authInSz); + if (ret < 0) { + return ret; + } + } + + /* set data to be decrypted*/ + iov[0].iov_base = (byte*)authIn; + iov[0].iov_len = authInSz; + iov[1].iov_base = (byte*)in; + iov[1].iov_len = sz; + iov[2].iov_base = (byte*)authTag; + iov[2].iov_len = authTagSz; + + msg->msg_iov = iov; + msg->msg_iovlen = 3; /* # of iov structures */ + ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0); + if (ret < 0) { + return ret; + } + + { + byte* tmp = (byte*)XMALLOC(authInSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + iov[0].iov_base = tmp; + iov[0].iov_len = authInSz; + iov[1].iov_base = out; + iov[1].iov_len = sz; + ret = (int)readv(aes->rdFd, iov, 2); + XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (ret < 0) { + return AES_GCM_AUTH_E; + } + (void)scratch; +#endif + + return 0; +} +#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */ +#endif /* HAVE_AESGCM */ + + +#ifdef HAVE_AES_ECB +int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_Afalg_AesDirect(aes, out, in, sz); +} + + +int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_Afalg_AesDirect(aes, out, in, sz); +} +#endif /* HAVE_AES_ECB */ +#endif /* !NO_AES && WOLFSSL_AFALG */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/af_alg/afalg_hash.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/af_alg/afalg_hash.c new file mode 100644 index 000000000..41e57bc80 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/af_alg/afalg_hash.c @@ -0,0 +1,339 @@ +/* afalg_hash.c + * + * Copyright (C) 2006-2020 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_AFALG_HASH) || (defined(WOLFSSL_AFALG_XILINX_SHA3) \ + && defined(WOLFSSL_SHA3)) + +#include +#include +#include +#include + +static const char WC_TYPE_HASH[] = "hash"; + + +/* generic AF_ALG hash free */ +static void AfalgHashFree(wolfssl_AFALG_Hash* hash) +{ + if (hash == NULL) + return; + + if (hash->alFd > 0) { + close(hash->alFd); + hash->alFd = -1; /* avoid possible double close on socket */ + } + if (hash->rdFd > 0) { + close(hash->rdFd); + hash->rdFd = -1; /* avoid possible double close on socket */ + } + + #if defined(WOLFSSL_AFALG_HASH_KEEP) + if (hash->msg != NULL) { + XFREE(hash->msg, hash->heap, DYNAMIC_TYPE_TMP_BUFFER); + hash->msg = NULL; + } + #endif +} + + +/* generic hash init for AF_ALG, returns 0 on success */ +static int AfalgHashInit(wolfssl_AFALG_Hash* hash, void* heap, int devId, + const char* type) +{ + if (hash == NULL) { + return BAD_FUNC_ARG; + } + + (void)devId; /* no async for now */ + XMEMSET(hash, 0, sizeof(wolfssl_AFALG_Hash)); + hash->heap = heap; + + hash->len = 0; + hash->used = 0; + hash->msg = NULL; + hash->alFd = -1; + hash->rdFd = -1; + + hash->alFd = wc_Afalg_Socket(); + if (hash->alFd < 0) { + return WC_AFALG_SOCK_E; + } + + hash->rdFd = wc_Afalg_CreateRead(hash->alFd, WC_TYPE_HASH, type); + if (hash->rdFd < 0) { + close(hash->alFd); + return WC_AFALG_SOCK_E; + } + + return 0; + +} + + +/* generic hash update for AF_ALG, returns 0 on success */ +static int AfalgHashUpdate(wolfssl_AFALG_Hash* hash, const byte* in, word32 sz) +{ + if (hash == NULL || (sz > 0 && in == NULL)) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_AFALG_HASH_KEEP + /* keep full message to hash at end instead of incremental updates */ + if (hash->len < hash->used + sz) { + if (hash->msg == NULL) { + hash->msg = (byte*)XMALLOC(hash->used + sz, hash->heap, + DYNAMIC_TYPE_TMP_BUFFER); + } else { + byte* pt = (byte*)XREALLOC(hash->msg, hash->used + sz, hash->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (pt == NULL) { + return MEMORY_E; + } + hash->msg = pt; + } + if (hash->msg == NULL) { + return MEMORY_E; + } + hash->len = hash->used + sz; + } + XMEMCPY(hash->msg + hash->used, in, sz); + hash->used += sz; +#else + int ret; + + if ((ret = (int)send(hash->rdFd, in, sz, MSG_MORE)) < 0) { + return ret; + } +#endif + return 0; +} + + +/* generic hash final for AF_ALG, return 0 on success */ +static int AfalgHashFinal(wolfssl_AFALG_Hash* hash, byte* out, word32 outSz, + const char* type) +{ + int ret; + void* heap; + + if (hash == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + heap = hash->heap; /* keep because AfalgHashInit clears the pointer */ +#ifdef WOLFSSL_AFALG_HASH_KEEP + /* keep full message to out at end instead of incremental updates */ + if ((ret = (int)send(hash->rdFd, hash->msg, hash->used, 0)) < 0) { + return ret; + } + XFREE(hash->msg, heap, DYNAMIC_TYPE_TMP_BUFFER); + hash->msg = NULL; +#else + if ((ret = (int)send(hash->rdFd, NULL, 0, 0)) < 0) { + return ret; + } +#endif + + if ((ret = (int)read(hash->rdFd, out, outSz)) != (int)outSz) { + return ret; + } + + AfalgHashFree(hash); + return AfalgHashInit(hash, heap, 0, type); +} + + +/* generic function to get intermediate hash */ +static int AfalgHashGet(wolfssl_AFALG_Hash* hash, byte* out, word32 outSz) +{ + int ret; + + if (hash == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + (void)ret; +#ifdef WOLFSSL_AFALG_HASH_KEEP + if ((ret = (int)send(hash->rdFd, hash->msg, hash->used, 0)) < 0) { + return ret; + } + + if ((ret = (int)read(hash->rdFd, out, outSz)) != (int)outSz) { + return ret; + } + return 0; +#else + (void)hash; + (void)out; + (void)outSz; + + WOLFSSL_MSG("Compile with WOLFSSL_AFALG_HASH_KEEP for this feature"); + return NOT_COMPILED_IN; +#endif +} + + +/* generic struct copy for AF_ALG, returns 0 on success */ +static int AfalgHashCopy(wolfssl_AFALG_Hash* src, wolfssl_AFALG_Hash* dst) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + + XMEMCPY(dst, src, sizeof(wolfssl_AFALG_Hash)); + +#ifdef WOLFSSL_AFALG_HASH_KEEP + dst->msg = (byte*)XMALLOC(src->len, dst->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (dst->msg == NULL) { + return MEMORY_E; + } + XMEMCPY(dst->msg, src->msg, src->len); +#endif + + dst->rdFd = accept(src->rdFd, NULL, 0); + dst->alFd = accept(src->alFd, NULL, 0); + + if (dst->rdFd == -1 || dst->alFd == -1) { + AfalgHashFree(dst); + return -1; + } + + return 0; +} + + +#if !defined(NO_SHA256) && defined(WOLFSSL_AFALG_HASH) +#include + +static const char WC_NAME_SHA256[] = "sha256"; + + +/* create AF_ALG sockets for SHA256 operation */ +int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId) +{ + return AfalgHashInit(sha, heap, devId, WC_NAME_SHA256); +} + + +int wc_Sha256Update(wc_Sha256* sha, const byte* in, word32 sz) +{ + return AfalgHashUpdate(sha, in, sz); +} + + +int wc_Sha256Final(wc_Sha256* sha, byte* hash) +{ + return AfalgHashFinal(sha, hash, WC_SHA256_DIGEST_SIZE, WC_NAME_SHA256); +} + + +int wc_Sha256GetHash(wc_Sha256* sha, byte* hash) +{ + return AfalgHashGet(sha, hash, WC_SHA256_DIGEST_SIZE); +} + + +int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) +{ + return AfalgHashCopy(src, dst); +} +#endif /* !NO_SHA256 */ + + + +#if defined(WOLFSSL_SHA3) && defined(WOLFSSL_AFALG_XILINX_SHA3) +#include + +static const char WC_NAME_SHA3[] = "xilinx-keccak-384"; + +void wc_Sha3_384_Free(wc_Sha3* sha) +{ + AfalgHashFree(sha); +} + + +/* create AF_ALG sockets for SHA256 operation */ +int wc_InitSha3_384(wc_Sha3* sha, void* heap, int devId) +{ + return AfalgHashInit(sha, heap, devId, WC_NAME_SHA3); +} + + +int wc_Sha3_384_Update(wc_Sha3* sha, const byte* in, word32 sz) +{ +#ifndef WOLFSSL_AFALG_HASH_KEEP + if (sz % 4) { + WOLFSSL_MSG("Alignment issue. Message size needs to be divisible by 4") + return BAD_FUNC_ARG; + } +#endif + + return AfalgHashUpdate(sha, in, sz); +} + + +int wc_Sha3_384_Final(wc_Sha3* sha, byte* hash) +{ + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_AFALG_HASH_KEEP + if (sha->used % 4) { + WOLFSSL_MSG("Alignment issue. Message size needs to be divisible by 4"); + return BAD_FUNC_ARG; + } +#endif + + return AfalgHashFinal(sha, hash, WC_SHA3_384_DIGEST_SIZE, WC_NAME_SHA3); +} + + +int wc_Sha3_384_GetHash(wc_Sha3* sha, byte* hash) +{ + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_AFALG_HASH_KEEP + if (sha->used % 4) { + WOLFSSL_MSG("Alignment issue. Message size needs to be divisible by 4"); + return BAD_FUNC_ARG; + } +#endif + + return AfalgHashGet(sha, hash, WC_SHA3_384_DIGEST_SIZE); +} + +int wc_Sha3_384_Copy(wc_Sha3* src, wc_Sha3* dst) +{ + return AfalgHashCopy(src, dst); +} +#endif /* WOLFSSL_SHA3 && WOLFSSL_AFALG_XILINX_SHA3 */ + +#endif /* WOLFSSL_AFALG */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/af_alg/wc_afalg.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/af_alg/wc_afalg.c new file mode 100644 index 000000000..0a91b5180 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/af_alg/wc_afalg.c @@ -0,0 +1,141 @@ +/* wc_afalg.c + * + * Copyright (C) 2006-2020 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 +#include + +#if defined(WOLFSSL_AFALG) || defined(WOLFSSL_AFALG_XILINX) + +#include +#include + + +/* Sets the type of socket address to use */ +void wc_Afalg_SockAddr(struct sockaddr_alg* in, const char* type, const char* name) +{ + in->salg_family = AF_ALG; + XSTRNCPY((char*)in->salg_type, type, XSTRLEN(type)); + in->salg_type[XSTRLEN(type)] = '\0'; + XSTRNCPY((char*)in->salg_name, name, XSTRLEN(name)); + in->salg_name[XSTRLEN(name)] = '\0'; +} + + +/* returns the socket accepting on with success + * negative values are returned in fail cases */ +int wc_Afalg_Accept(struct sockaddr_alg* in, int inSz, int sock) +{ + if (bind(sock, (const struct sockaddr*)in, inSz) < 0) { + WOLFSSL_MSG("Failed to bind with AF_ALG"); + return WC_AFALG_SOCK_E; + } + + return accept(sock, NULL, 0); +} + + +/* creates a new AF_ALG socket and returns it + * negative values are returned in fail cases */ +int wc_Afalg_Socket(void) +{ + int sock; + + if ((sock = socket(AF_ALG, SOCK_SEQPACKET, 0)) < 0) { + WOLFSSL_MSG("Failed to get AF_ALG socket"); + return WC_AFALG_SOCK_E; + } + + return sock; +} + + +/* binds and creates the read fd */ +int wc_Afalg_CreateRead(int sock, const char* type, const char* name) +{ + struct sockaddr_alg sa = {0}; + wc_Afalg_SockAddr(&sa, type, name); + return wc_Afalg_Accept(&sa, sizeof(sa), sock); +} + + +/* sets the IV in CMSG structure, returns 0 on success */ +int wc_Afalg_SetIv(struct cmsghdr* cmsg, byte* iv, word32 ivSz) +{ + struct af_alg_iv* afIv; + + if (cmsg == NULL || iv == NULL) { + WOLFSSL_MSG("Null cmsg or iv passed in"); + return BAD_FUNC_ARG; + } + + cmsg->cmsg_level = SOL_ALG; + cmsg->cmsg_type = ALG_SET_IV; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct af_alg_iv) + ivSz); + afIv = (void*)CMSG_DATA(cmsg); + afIv->ivlen = ivSz; + XMEMCPY(afIv->iv, iv, ivSz); + + return 0; +} + + +/* sets the AAD size in CMSG structure, returns 0 on success */ +int wc_Afalg_SetAad(struct cmsghdr* cmsg, word32 sz) +{ + if (cmsg == NULL) { + WOLFSSL_MSG("Null cmsg passed in"); + return BAD_FUNC_ARG; + } + + cmsg->cmsg_level = SOL_ALG; + cmsg->cmsg_type = ALG_SET_AEAD_ASSOCLEN; + cmsg->cmsg_len = CMSG_LEN(sizeof(word32)); + *((word32*)CMSG_DATA(cmsg)) = sz; + + return 0; +} + + +/* sets the operation type in CMSG structure, returns 0 on success + * + * dir 0 is encryption 1 is decryption + */ +int wc_Afalg_SetOp(struct cmsghdr* cmsg, int dir) +{ + if (cmsg == NULL) { + return BAD_FUNC_ARG; + } + + cmsg->cmsg_level = SOL_ALG; + cmsg->cmsg_type = ALG_SET_OP; + cmsg->cmsg_len = CMSG_LEN(4); + *((word32*)CMSG_DATA(cmsg)) = (dir == 1)? ALG_OP_DECRYPT : ALG_OP_ENCRYPT; + + return 0; +} + +#endif /* !NO_AES && WOLFSSL_AFALG */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-curve25519.S b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-curve25519.S new file mode 100644 index 000000000..6fd1ed3f2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-curve25519.S @@ -0,0 +1,6012 @@ +/* armv8-32-curve25519 + * + * Copyright (C) 2006-2020 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 + */ + +/* Generated using (from wolfssl): + * cd ../scripts + * ruby ./x25519/x25519.rb arm32 ../wolfssl/wolfcrypt/src/port/arm/armv8-32-curve25519.S + */ + +#ifdef WOLFSSL_ARMASM +#ifndef __aarch64__ + .text + .align 2 + .globl fe_init + .type fe_init, %function +fe_init: + bx lr + .size fe_init,.-fe_init + .text + .align 2 + .globl fe_frombytes + .type fe_frombytes, %function +fe_frombytes: + push {r4, r5, r6, r7, lr} + ldrd r2, r3, [r1] + ldr r12, [r1, #8] + ldr lr, [r1, #12] + ldrd r4, r5, [r1, #16] + ldrd r6, r7, [r1, #24] + and r7, r7, #0x7fffffff + strd r2, r3, [r0] + str r12, [r0, #8] + str lr, [r0, #12] + strd r4, r5, [r0, #16] + strd r6, r7, [r0, #24] + pop {r4, r5, r6, r7, pc} + .size fe_frombytes,.-fe_frombytes + .text + .align 2 + .globl fe_tobytes + .type fe_tobytes, %function +fe_tobytes: + push {r4, r5, r6, r7, r8, lr} + ldrd r2, r3, [r1] + ldr r12, [r1, #8] + ldr lr, [r1, #12] + ldrd r4, r5, [r1, #16] + ldrd r6, r7, [r1, #24] + adds r8, r2, #19 + adcs r8, r3, #0 + adcs r8, r12, #0 + adcs r8, lr, #0 + adcs r8, r4, #0 + adcs r8, r5, #0 + adcs r8, r6, #0 + adc r8, r7, #0 + asr r8, r8, #31 + and r8, r8, #19 + adds r2, r2, r8 + adcs r3, r3, #0 + adcs r12, r12, #0 + adcs lr, lr, #0 + adcs r4, r4, #0 + adcs r5, r5, #0 + adcs r6, r6, #0 + adc r7, r7, #0 + and r7, r7, #0x7fffffff + strd r2, r3, [r0] + str r12, [r0, #8] + str lr, [r0, #12] + strd r4, r5, [r0, #16] + strd r6, r7, [r0, #24] + pop {r4, r5, r6, r7, r8, pc} + .size fe_tobytes,.-fe_tobytes + .text + .align 2 + .globl fe_1 + .type fe_1, %function +fe_1: + # Set one + mov r2, #1 + mov r1, #0 + str r2, [r0] + str r1, [r0, #4] + str r1, [r0, #8] + str r1, [r0, #12] + str r1, [r0, #16] + str r1, [r0, #20] + str r1, [r0, #24] + str r1, [r0, #28] + bx lr + .size fe_1,.-fe_1 + .text + .align 2 + .globl fe_0 + .type fe_0, %function +fe_0: + # Set zero + mov r1, #0 + str r1, [r0] + str r1, [r0, #4] + str r1, [r0, #8] + str r1, [r0, #12] + str r1, [r0, #16] + str r1, [r0, #20] + str r1, [r0, #24] + str r1, [r0, #28] + bx lr + .size fe_0,.-fe_0 + .text + .align 2 + .globl fe_copy + .type fe_copy, %function +fe_copy: + push {lr} + # Copy + ldrd r2, r3, [r1] + ldr r12, [r1, #8] + ldr lr, [r1, #12] + strd r2, r3, [r0] + str r12, [r0, #8] + str lr, [r0, #12] + ldrd r2, r3, [r1, #16] + ldr r12, [r1, #24] + ldr lr, [r1, #28] + strd r2, r3, [r0, #16] + str r12, [r0, #24] + str lr, [r0, #28] + pop {pc} + .size fe_copy,.-fe_copy + .text + .align 2 + .globl fe_sub + .type fe_sub, %function +fe_sub: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + # Sub + ldr r12, [r1] + ldr lr, [r1, #4] + ldrd r4, r5, [r1, #8] + ldrd r6, r7, [r2] + ldrd r8, r9, [r2, #8] + subs r6, r12, r6 + sbcs r7, lr, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + strd r6, r7, [r0] + strd r8, r9, [r0, #8] + ldr r12, [r1, #16] + ldr lr, [r1, #20] + ldrd r4, r5, [r1, #24] + ldrd r6, r7, [r2, #16] + ldrd r8, r9, [r2, #24] + sbcs r6, r12, r6 + sbcs r7, lr, r7 + sbcs r8, r4, r8 + sbc r9, r5, r9 + mov r10, #-19 + asr r3, r9, #31 + # Mask the modulus + and r10, r3, r10 + and r11, r3, #0x7fffffff + # Add modulus (if underflow) + ldr r12, [r0] + ldr lr, [r0, #4] + ldrd r4, r5, [r0, #8] + adds r12, r12, r10 + adcs lr, lr, r3 + adcs r4, r4, r3 + adcs r5, r5, r3 + adcs r6, r6, r3 + adcs r7, r7, r3 + adcs r8, r8, r3 + adc r9, r9, r11 + str r12, [r0] + str lr, [r0, #4] + strd r4, r5, [r0, #8] + strd r6, r7, [r0, #16] + strd r8, r9, [r0, #24] + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size fe_sub,.-fe_sub + .text + .align 2 + .globl fe_add + .type fe_add, %function +fe_add: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + # Add + ldr r12, [r1] + ldr lr, [r1, #4] + ldrd r4, r5, [r1, #8] + ldrd r6, r7, [r2] + ldrd r8, r9, [r2, #8] + adds r6, r12, r6 + adcs r7, lr, r7 + adcs r8, r4, r8 + adcs r9, r5, r9 + strd r6, r7, [r0] + strd r8, r9, [r0, #8] + ldr r12, [r1, #16] + ldr lr, [r1, #20] + ldrd r4, r5, [r1, #24] + ldrd r6, r7, [r2, #16] + ldrd r8, r9, [r2, #24] + adcs r6, r12, r6 + adcs r7, lr, r7 + adcs r8, r4, r8 + adc r9, r5, r9 + mov r10, #-19 + asr r3, r9, #31 + # Mask the modulus + and r10, r3, r10 + and r11, r3, #0x7fffffff + # Sub modulus (if overflow) + ldr r12, [r0] + ldr lr, [r0, #4] + ldrd r4, r5, [r0, #8] + subs r12, r12, r10 + sbcs lr, lr, r3 + sbcs r4, r4, r3 + sbcs r5, r5, r3 + sbcs r6, r6, r3 + sbcs r7, r7, r3 + sbcs r8, r8, r3 + sbc r9, r9, r11 + str r12, [r0] + str lr, [r0, #4] + strd r4, r5, [r0, #8] + strd r6, r7, [r0, #16] + strd r8, r9, [r0, #24] + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size fe_add,.-fe_add + .text + .align 2 + .globl fe_neg + .type fe_neg, %function +fe_neg: + push {r4, r5, lr} + mov r5, #-1 + mov r4, #-19 + ldrd r2, r3, [r1] + ldr r12, [r1, #8] + ldr lr, [r1, #12] + subs r2, r4, r2 + sbcs r3, r5, r3 + sbcs r12, r5, r12 + sbcs lr, r5, lr + strd r2, r3, [r0] + str r12, [r0, #8] + str lr, [r0, #12] + mov r4, #0x7fffffff + ldrd r2, r3, [r1, #16] + ldr r12, [r1, #24] + ldr lr, [r1, #28] + sbcs r2, r5, r2 + sbcs r3, r5, r3 + sbcs r12, r5, r12 + sbc lr, r4, lr + strd r2, r3, [r0, #16] + str r12, [r0, #24] + str lr, [r0, #28] + pop {r4, r5, pc} + .size fe_neg,.-fe_neg + .text + .align 2 + .globl fe_isnonzero + .type fe_isnonzero, %function +fe_isnonzero: + push {r4, r5, r6, r7, r8, lr} + ldrd r2, r3, [r0] + ldr r12, [r0, #8] + ldr lr, [r0, #12] + ldrd r4, r5, [r0, #16] + ldrd r6, r7, [r0, #24] + adds r1, r2, #19 + adcs r1, r3, #0 + adcs r1, r12, #0 + adcs r1, lr, #0 + adcs r1, r4, #0 + adcs r1, r5, #0 + adcs r1, r6, #0 + adc r1, r7, #0 + asr r1, r1, #31 + and r1, r1, #19 + adds r2, r2, r1 + adcs r3, r3, #0 + adcs r12, r12, #0 + adcs lr, lr, #0 + adcs r4, r4, #0 + adcs r5, r5, #0 + adcs r6, r6, #0 + adc r7, r7, #0 + and r7, r7, #0x7fffffff + orr r2, r2, r3 + orr r12, r12, lr + orr r4, r4, r5 + orr r6, r6, r7 + orr r12, r12, r4 + orr r2, r2, r6 + orr r0, r2, r12 + pop {r4, r5, r6, r7, r8, pc} + .size fe_isnonzero,.-fe_isnonzero + .text + .align 2 + .globl fe_isnegative + .type fe_isnegative, %function +fe_isnegative: + push {lr} + ldrd r2, r3, [r0] + ldr r12, [r0, #8] + ldr lr, [r0, #12] + adds r1, r2, #19 + adcs r1, r3, #0 + adcs r1, r12, #0 + adcs r1, lr, #0 + ldrd r2, r3, [r0, #16] + ldr r12, [r0, #24] + ldr lr, [r0, #28] + adcs r1, r2, #0 + adcs r1, r3, #0 + adcs r1, r12, #0 + ldr r2, [r0] + adc r1, lr, #0 + and r0, r2, #1 + lsr r1, r1, #31 + eor r0, r0, r1 + pop {pc} + .size fe_isnegative,.-fe_isnegative + .text + .align 2 + .globl fe_cmov_table + .type fe_cmov_table, %function +fe_cmov_table: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + sxtb r2, r2 + sbfx r7, r2, #7, #1 + eor r10, r2, r7 + sub r10, r10, r7 + mov r3, #1 + mov r12, #0 + mov lr, #1 + mov r4, #0 + mov r5, #0 + mov r6, #0 + mov r7, #0x80000000 + ror r7, r7, #31 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #32] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #64] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #30 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #32] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #64] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #29 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #32] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #64] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #28 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #32] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #64] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #27 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #32] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #64] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #26 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #32] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #64] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #25 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #32] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #64] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #24 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #32] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #64] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + sub r1, r1, #0x2a0 + mov r8, #-19 + mov r9, #-1 + subs r8, r8, r5 + sbcs r9, r9, r6 + sbc r11, r11, r11 + asr r10, r2, #31 + eor r7, r3, lr + and r7, r7, r10 + eor r3, r3, r7 + eor lr, lr, r7 + eor r7, r12, r4 + and r7, r7, r10 + eor r12, r12, r7 + eor r4, r4, r7 + eor r8, r8, r5 + and r8, r8, r10 + eor r5, r5, r8 + eor r9, r9, r6 + and r9, r9, r10 + eor r6, r6, r9 + str r3, [r0] + str r12, [r0, #4] + str lr, [r0, #32] + str r4, [r0, #36] + str r5, [r0, #64] + str r6, [r0, #68] + sbfx r7, r2, #7, #1 + eor r10, r2, r7 + sub r10, r10, r7 + mov r3, #0 + mov r12, #0 + mov lr, #0 + mov r4, #0 + mov r5, #0 + mov r6, #0 + mov r7, #0x80000000 + ror r7, r7, #31 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #8] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #40] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #72] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #30 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #8] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #40] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #72] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #29 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #8] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #40] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #72] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #28 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #8] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #40] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #72] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #27 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #8] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #40] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #72] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #26 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #8] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #40] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #72] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #25 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #8] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #40] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #72] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #24 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #8] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #40] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #72] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + sub r1, r1, #0x2a0 + mov r8, #-1 + mov r9, #-1 + rsbs r11, r11, #0 + sbcs r8, r8, r5 + sbcs r9, r9, r6 + sbc r11, r11, r11 + asr r10, r2, #31 + eor r7, r3, lr + and r7, r7, r10 + eor r3, r3, r7 + eor lr, lr, r7 + eor r7, r12, r4 + and r7, r7, r10 + eor r12, r12, r7 + eor r4, r4, r7 + eor r8, r8, r5 + and r8, r8, r10 + eor r5, r5, r8 + eor r9, r9, r6 + and r9, r9, r10 + eor r6, r6, r9 + str r3, [r0, #8] + str r12, [r0, #12] + str lr, [r0, #40] + str r4, [r0, #44] + str r5, [r0, #72] + str r6, [r0, #76] + sbfx r7, r2, #7, #1 + eor r10, r2, r7 + sub r10, r10, r7 + mov r3, #0 + mov r12, #0 + mov lr, #0 + mov r4, #0 + mov r5, #0 + mov r6, #0 + mov r7, #0x80000000 + ror r7, r7, #31 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #16] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #48] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #80] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #30 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #16] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #48] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #80] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #29 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #16] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #48] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #80] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #28 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #16] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #48] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #80] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #27 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #16] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #48] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #80] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #26 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #16] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #48] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #80] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #25 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #16] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #48] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #80] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #24 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #16] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #48] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #80] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + sub r1, r1, #0x2a0 + mov r8, #-1 + mov r9, #-1 + rsbs r11, r11, #0 + sbcs r8, r8, r5 + sbcs r9, r9, r6 + sbc r11, r11, r11 + asr r10, r2, #31 + eor r7, r3, lr + and r7, r7, r10 + eor r3, r3, r7 + eor lr, lr, r7 + eor r7, r12, r4 + and r7, r7, r10 + eor r12, r12, r7 + eor r4, r4, r7 + eor r8, r8, r5 + and r8, r8, r10 + eor r5, r5, r8 + eor r9, r9, r6 + and r9, r9, r10 + eor r6, r6, r9 + str r3, [r0, #16] + str r12, [r0, #20] + str lr, [r0, #48] + str r4, [r0, #52] + str r5, [r0, #80] + str r6, [r0, #84] + sbfx r7, r2, #7, #1 + eor r10, r2, r7 + sub r10, r10, r7 + mov r3, #0 + mov r12, #0 + mov lr, #0 + mov r4, #0 + mov r5, #0 + mov r6, #0 + mov r7, #0x80000000 + ror r7, r7, #31 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #24] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #56] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #88] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #30 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #24] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #56] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #88] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #29 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #24] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #56] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #88] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #28 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #24] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #56] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #88] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #27 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #24] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #56] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #88] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #26 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #24] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #56] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #88] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #25 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #24] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #56] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #88] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + add r1, r1, #0x60 + mov r7, #0x80000000 + ror r7, r7, #24 + ror r7, r7, r10 + asr r7, r7, #31 + ldrd r8, r9, [r1, #24] + eor r8, r8, r3 + eor r9, r9, r12 + and r8, r8, r7 + and r9, r9, r7 + eor r3, r3, r8 + eor r12, r12, r9 + ldrd r8, r9, [r1, #56] + eor r8, r8, lr + eor r9, r9, r4 + and r8, r8, r7 + and r9, r9, r7 + eor lr, lr, r8 + eor r4, r4, r9 + ldrd r8, r9, [r1, #88] + eor r8, r8, r5 + eor r9, r9, r6 + and r8, r8, r7 + and r9, r9, r7 + eor r5, r5, r8 + eor r6, r6, r9 + sub r1, r1, #0x2a0 + mov r8, #-1 + mov r9, #0x7fffffff + rsbs r11, r11, #0 + sbcs r8, r8, r5 + sbc r9, r9, r6 + asr r10, r2, #31 + eor r7, r3, lr + and r7, r7, r10 + eor r3, r3, r7 + eor lr, lr, r7 + eor r7, r12, r4 + and r7, r7, r10 + eor r12, r12, r7 + eor r4, r4, r7 + eor r8, r8, r5 + and r8, r8, r10 + eor r5, r5, r8 + eor r9, r9, r6 + and r9, r9, r10 + eor r6, r6, r9 + str r3, [r0, #24] + str r12, [r0, #28] + str lr, [r0, #56] + str r4, [r0, #60] + str r5, [r0, #88] + str r6, [r0, #92] + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size fe_cmov_table,.-fe_cmov_table + .text + .align 2 + .globl fe_mul + .type fe_mul, %function +fe_mul: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + sub sp, sp, #0x40 + # Multiply + ldr r7, [r1] + ldr r8, [r1, #4] + ldr r9, [r2] + ldr lr, [r2, #4] + # A[0] * B[0] = 0 + umull r4, r5, r7, r9 + str r4, [sp] + # A[0] * B[1] = 1 + umull r3, r6, r7, lr + adds r5, r5, r3 + adc r6, r6, #0 + # A[1] * B[0] = 1 + umull r3, r12, r8, r9 + adds r5, r5, r3 + mov r4, #0 + adcs r6, r6, r12 + adc r4, r4, #0 + str r5, [sp, #4] + # A[2] * B[0] = 2 + ldr r10, [r1, #8] + umull r3, r12, r10, r9 + adds r6, r6, r3 + adc r4, r4, r12 + # A[1] * B[1] = 2 + umull r3, r12, r8, lr + adds r6, r6, r3 + mov r5, #0 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[0] * B[2] = 2 + ldr r11, [r2, #8] + umull r3, r12, r7, r11 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + str r6, [sp, #8] + # A[0] * B[3] = 3 + ldr r11, [r2, #12] + umull r3, r12, r7, r11 + adds r4, r4, r3 + mov r6, #0 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[1] * B[2] = 3 + ldr r11, [r2, #8] + umull r3, r12, r8, r11 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[2] * B[1] = 3 + umull r3, r12, r10, lr + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[3] * B[0] = 3 + ldr r10, [r1, #12] + umull r3, r12, r10, r9 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + str r4, [sp, #12] + # A[4] * B[0] = 4 + ldr r10, [r1, #16] + umull r3, r12, r10, r9 + adds r5, r5, r3 + mov r4, #0 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[3] * B[1] = 4 + ldr r10, [r1, #12] + umull r3, r12, r10, lr + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[2] * B[2] = 4 + ldr r10, [r1, #8] + umull r3, r12, r10, r11 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[1] * B[3] = 4 + ldr r11, [r2, #12] + umull r3, r12, r8, r11 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[0] * B[4] = 4 + ldr r11, [r2, #16] + umull r3, r12, r7, r11 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + str r5, [sp, #16] + # A[0] * B[5] = 5 + ldr r11, [r2, #20] + umull r3, r12, r7, r11 + adds r6, r6, r3 + mov r5, #0 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[1] * B[4] = 5 + ldr r11, [r2, #16] + umull r3, r12, r8, r11 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[2] * B[3] = 5 + ldr r11, [r2, #12] + umull r3, r12, r10, r11 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[3] * B[2] = 5 + ldr r10, [r1, #12] + ldr r11, [r2, #8] + umull r3, r12, r10, r11 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[4] * B[1] = 5 + ldr r10, [r1, #16] + umull r3, r12, r10, lr + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[5] * B[0] = 5 + ldr r10, [r1, #20] + umull r3, r12, r10, r9 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + str r6, [sp, #20] + # A[6] * B[0] = 6 + ldr r10, [r1, #24] + umull r3, r12, r10, r9 + adds r4, r4, r3 + mov r6, #0 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[5] * B[1] = 6 + ldr r10, [r1, #20] + umull r3, r12, r10, lr + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[4] * B[2] = 6 + ldr r10, [r1, #16] + umull r3, r12, r10, r11 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[3] * B[3] = 6 + ldr r10, [r1, #12] + ldr r11, [r2, #12] + umull r3, r12, r10, r11 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[2] * B[4] = 6 + ldr r10, [r1, #8] + ldr r11, [r2, #16] + umull r3, r12, r10, r11 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[1] * B[5] = 6 + ldr r11, [r2, #20] + umull r3, r12, r8, r11 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[0] * B[6] = 6 + ldr r11, [r2, #24] + umull r3, r12, r7, r11 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + str r4, [sp, #24] + # A[0] * B[7] = 7 + ldr r11, [r2, #28] + umull r3, r12, r7, r11 + adds r5, r5, r3 + mov r4, #0 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[1] * B[6] = 7 + ldr r11, [r2, #24] + umull r3, r12, r8, r11 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[2] * B[5] = 7 + ldr r11, [r2, #20] + umull r3, r12, r10, r11 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[3] * B[4] = 7 + ldr r10, [r1, #12] + ldr r11, [r2, #16] + umull r3, r12, r10, r11 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[4] * B[3] = 7 + ldr r10, [r1, #16] + ldr r11, [r2, #12] + umull r3, r12, r10, r11 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[5] * B[2] = 7 + ldr r10, [r1, #20] + ldr r11, [r2, #8] + umull r3, r12, r10, r11 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[6] * B[1] = 7 + ldr r10, [r1, #24] + umull r3, r12, r10, lr + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[7] * B[0] = 7 + ldr r10, [r1, #28] + umull r3, r12, r10, r9 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + str r5, [sp, #28] + ldr r7, [r1, #24] + ldr r9, [r2, #24] + # A[7] * B[1] = 8 + umull r3, r12, r10, lr + adds r6, r6, r3 + mov r5, #0 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[6] * B[2] = 8 + umull r3, r12, r7, r11 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[5] * B[3] = 8 + ldr r10, [r1, #20] + ldr r11, [r2, #12] + umull r3, r12, r10, r11 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[4] * B[4] = 8 + ldr r10, [r1, #16] + ldr r11, [r2, #16] + umull r3, r12, r10, r11 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[3] * B[5] = 8 + ldr r10, [r1, #12] + ldr r11, [r2, #20] + umull r3, r12, r10, r11 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[2] * B[6] = 8 + ldr r10, [r1, #8] + umull r3, r12, r10, r9 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[1] * B[7] = 8 + ldr r11, [r2, #28] + umull r3, r12, r8, r11 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + str r6, [sp, #32] + ldr r8, [r1, #28] + mov lr, r11 + # A[2] * B[7] = 9 + umull r3, r12, r10, lr + adds r4, r4, r3 + mov r6, #0 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[3] * B[6] = 9 + ldr r10, [r1, #12] + umull r3, r12, r10, r9 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[4] * B[5] = 9 + ldr r10, [r1, #16] + ldr r11, [r2, #20] + umull r3, r12, r10, r11 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[5] * B[4] = 9 + ldr r10, [r1, #20] + ldr r11, [r2, #16] + umull r3, r12, r10, r11 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[6] * B[3] = 9 + ldr r11, [r2, #12] + umull r3, r12, r7, r11 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[7] * B[2] = 9 + ldr r11, [r2, #8] + umull r3, r12, r8, r11 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + str r4, [sp, #36] + # A[7] * B[3] = 10 + ldr r11, [r2, #12] + umull r3, r12, r8, r11 + adds r5, r5, r3 + mov r4, #0 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[6] * B[4] = 10 + ldr r11, [r2, #16] + umull r3, r12, r7, r11 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[5] * B[5] = 10 + ldr r11, [r2, #20] + umull r3, r12, r10, r11 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[4] * B[6] = 10 + ldr r10, [r1, #16] + umull r3, r12, r10, r9 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[3] * B[7] = 10 + ldr r10, [r1, #12] + umull r3, r12, r10, lr + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + str r5, [sp, #40] + # A[4] * B[7] = 11 + ldr r10, [r1, #16] + umull r3, r12, r10, lr + adds r6, r6, r3 + mov r5, #0 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[5] * B[6] = 11 + ldr r10, [r1, #20] + umull r3, r12, r10, r9 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[6] * B[5] = 11 + umull r3, r12, r7, r11 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + # A[7] * B[4] = 11 + ldr r11, [r2, #16] + umull r3, r12, r8, r11 + adds r6, r6, r3 + adcs r4, r4, r12 + adc r5, r5, #0 + str r6, [sp, #44] + # A[7] * B[5] = 12 + ldr r11, [r2, #20] + umull r3, r12, r8, r11 + adds r4, r4, r3 + mov r6, #0 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[6] * B[6] = 12 + umull r3, r12, r7, r9 + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + # A[5] * B[7] = 12 + umull r3, r12, r10, lr + adds r4, r4, r3 + adcs r5, r5, r12 + adc r6, r6, #0 + str r4, [sp, #48] + # A[6] * B[7] = 13 + umull r3, r12, r7, lr + adds r5, r5, r3 + mov r4, #0 + adcs r6, r6, r12 + adc r4, r4, #0 + # A[7] * B[6] = 13 + umull r3, r12, r8, r9 + adds r5, r5, r3 + adcs r6, r6, r12 + adc r4, r4, #0 + str r5, [sp, #52] + # A[7] * B[7] = 14 + umull r3, r12, r8, lr + adds r6, r6, r3 + adc r4, r4, r12 + str r6, [sp, #56] + str r4, [sp, #60] + # Reduce + # Load bottom half + ldrd r4, r5, [sp] + ldrd r6, r7, [sp, #8] + ldrd r8, r9, [sp, #16] + ldrd r10, r11, [sp, #24] + lsr r3, r11, #31 + and r11, r11, #0x7fffffff + mov lr, #19 + ldr r1, [sp, #32] + orr r3, r3, r1, lsl #1 + umull r3, r12, lr, r3 + adds r4, r4, r3 + mov r2, #0 + adcs r5, r5, r12 + adc r2, r2, #0 + lsr r3, r1, #31 + ldr r1, [sp, #36] + orr r3, r3, r1, lsl #1 + umull r3, r12, lr, r3 + add r12, r12, r2 + adds r5, r5, r3 + mov r2, #0 + adcs r6, r6, r12 + adc r2, r2, #0 + lsr r3, r1, #31 + ldr r1, [sp, #40] + orr r3, r3, r1, lsl #1 + umull r3, r12, lr, r3 + add r12, r12, r2 + adds r6, r6, r3 + mov r2, #0 + adcs r7, r7, r12 + adc r2, r2, #0 + lsr r3, r1, #31 + ldr r1, [sp, #44] + orr r3, r3, r1, lsl #1 + umull r3, r12, lr, r3 + add r12, r12, r2 + adds r7, r7, r3 + mov r2, #0 + adcs r8, r8, r12 + adc r2, r2, #0 + lsr r3, r1, #31 + ldr r1, [sp, #48] + orr r3, r3, r1, lsl #1 + umull r3, r12, lr, r3 + add r12, r12, r2 + adds r8, r8, r3 + mov r2, #0 + adcs r9, r9, r12 + adc r2, r2, #0 + lsr r3, r1, #31 + ldr r1, [sp, #52] + orr r3, r3, r1, lsl #1 + umull r3, r12, lr, r3 + add r12, r12, r2 + adds r9, r9, r3 + mov r2, #0 + adcs r10, r10, r12 + adc r2, r2, #0 + lsr r3, r1, #31 + ldr r1, [sp, #56] + orr r3, r3, r1, lsl #1 + umull r3, r12, lr, r3 + add r12, r12, r2 + adds r10, r10, r3 + mov r2, #0 + adcs r11, r11, r12 + adc r2, r2, #0 + lsr r3, r1, #31 + ldr r1, [sp, #60] + orr r3, r3, r1, lsl #1 + umull r3, r12, lr, r3 + adds r11, r11, r3 + adc r3, r12, r2 + # Overflow + lsl r3, r3, #1 + orr r3, r3, r11, lsr #31 + mul r3, r3, lr + and r11, r11, #0x7fffffff + adds r4, r4, r3 + adcs r5, r5, #0 + adcs r6, r6, #0 + adcs r7, r7, #0 + adcs r8, r8, #0 + adcs r9, r9, #0 + adcs r10, r10, #0 + adc r11, r11, #0 + # Reduce if top bit set + asr r3, r11, #31 + and r3, r3, lr + and r11, r11, #0x7fffffff + adds r4, r4, r3 + adcs r5, r5, #0 + adcs r6, r6, #0 + adcs r7, r7, #0 + adcs r8, r8, #0 + adcs r9, r9, #0 + adcs r10, r10, #0 + adc r11, r11, #0 + # Store + strd r4, r5, [r0] + strd r6, r7, [r0, #8] + strd r8, r9, [r0, #16] + strd r10, r11, [r0, #24] + add sp, sp, #0x40 + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size fe_mul,.-fe_mul + .text + .align 2 + .globl fe_sq + .type fe_sq, %function +fe_sq: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + sub sp, sp, #0x40 + # Square + ldr r7, [r1] + ldr r8, [r1, #4] + ldr r9, [r1, #8] + ldr r10, [r1, #12] + ldr r12, [r1, #16] + # A[0] * A[0] = 0 + umull r4, r5, r7, r7 + str r4, [sp] + # A[0] * A[1] = 1 + umull r2, r3, r7, r8 + mov r6, #0 + adds r5, r5, r2 + adc r6, r6, r3 + adds r5, r5, r2 + mov r4, #0 + adcs r6, r6, r3 + adc r4, r4, #0 + str r5, [sp, #4] + # A[1] * A[1] = 2 + umull r2, r3, r8, r8 + adds r6, r6, r2 + adc r4, r4, r3 + # A[0] * A[2] = 2 + umull r2, r3, r7, r9 + adds r6, r6, r2 + mov r5, #0 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + str r6, [sp, #8] + # A[0] * A[3] = 3 + umull r2, r3, r7, r10 + adds r4, r4, r2 + adc r5, r5, r3 + adds r4, r4, r2 + mov r6, #0 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[1] * A[2] = 3 + umull r2, r3, r8, r9 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + str r4, [sp, #12] + # A[2] * A[2] = 4 + umull r2, r3, r9, r9 + adds r5, r5, r2 + mov r4, #0 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[1] * A[3] = 4 + umull r2, r3, r8, r10 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[0] * A[4] = 4 + umull r2, r3, r7, r12 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + str r5, [sp, #16] + # A[0] * A[5] = 5 + ldr r11, [r1, #20] + umull r2, r3, r7, r11 + adds r6, r6, r2 + mov r5, #0 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + # A[1] * A[4] = 5 + umull r2, r3, r8, r12 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + # A[2] * A[3] = 5 + umull r2, r3, r9, r10 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + str r6, [sp, #20] + # A[3] * A[3] = 6 + umull r2, r3, r10, r10 + adds r4, r4, r2 + mov r6, #0 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[2] * A[4] = 6 + umull r2, r3, r9, r12 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[1] * A[5] = 6 + umull r2, r3, r8, r11 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[0] * A[6] = 6 + ldr r11, [r1, #24] + umull r2, r3, r7, r11 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + str r4, [sp, #24] + # A[0] * A[7] = 7 + ldr r11, [r1, #28] + umull r2, r3, r7, r11 + adds r5, r5, r2 + mov r4, #0 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[1] * A[6] = 7 + ldr r11, [r1, #24] + umull r2, r3, r8, r11 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[2] * A[5] = 7 + ldr r11, [r1, #20] + umull r2, r3, r9, r11 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[3] * A[4] = 7 + umull r2, r3, r10, r12 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + str r5, [sp, #28] + # A[4] * A[4] = 8 + umull r2, r3, r12, r12 + adds r6, r6, r2 + mov r5, #0 + adcs r4, r4, r3 + adc r5, r5, #0 + # A[3] * A[5] = 8 + umull r2, r3, r10, r11 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + # A[2] * A[6] = 8 + ldr r11, [r1, #24] + umull r2, r3, r9, r11 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + # A[1] * A[7] = 8 + ldr r11, [r1, #28] + umull r2, r3, r8, r11 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + str r6, [sp, #32] + ldr r7, [r1, #20] + # A[2] * A[7] = 9 + umull r2, r3, r9, r11 + adds r4, r4, r2 + mov r6, #0 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[3] * A[6] = 9 + ldr r11, [r1, #24] + umull r2, r3, r10, r11 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[4] * A[5] = 9 + umull r2, r3, r12, r7 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + str r4, [sp, #36] + mov r8, r11 + # A[5] * A[5] = 10 + umull r2, r3, r7, r7 + adds r5, r5, r2 + mov r4, #0 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[4] * A[6] = 10 + umull r2, r3, r12, r8 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[3] * A[7] = 10 + ldr r11, [r1, #28] + umull r2, r3, r10, r11 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + str r5, [sp, #40] + mov r9, r11 + # A[4] * A[7] = 11 + umull r2, r3, r12, r9 + adds r6, r6, r2 + mov r5, #0 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + # A[5] * A[6] = 11 + umull r2, r3, r7, r8 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + str r6, [sp, #44] + # A[6] * A[6] = 12 + umull r2, r3, r8, r8 + adds r4, r4, r2 + mov r6, #0 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[5] * A[7] = 12 + umull r2, r3, r7, r9 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + str r4, [sp, #48] + # A[6] * A[7] = 13 + umull r2, r3, r8, r9 + adds r5, r5, r2 + mov r4, #0 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + str r5, [sp, #52] + # A[7] * A[7] = 14 + umull r2, r3, r9, r9 + adds r6, r6, r2 + adc r4, r4, r3 + str r6, [sp, #56] + str r4, [sp, #60] + # Reduce + # Load bottom half + ldrd r4, r5, [sp] + ldrd r6, r7, [sp, #8] + ldrd r8, r9, [sp, #16] + ldrd r10, r11, [sp, #24] + lsr r2, r11, #31 + and r11, r11, #0x7fffffff + mov r12, #19 + ldr r1, [sp, #32] + orr r2, r2, r1, lsl #1 + umull r2, r3, r12, r2 + adds r4, r4, r2 + mov lr, #0 + adcs r5, r5, r3 + adc lr, lr, #0 + lsr r2, r1, #31 + ldr r1, [sp, #36] + orr r2, r2, r1, lsl #1 + umull r2, r3, r12, r2 + add r3, r3, lr + adds r5, r5, r2 + mov lr, #0 + adcs r6, r6, r3 + adc lr, lr, #0 + lsr r2, r1, #31 + ldr r1, [sp, #40] + orr r2, r2, r1, lsl #1 + umull r2, r3, r12, r2 + add r3, r3, lr + adds r6, r6, r2 + mov lr, #0 + adcs r7, r7, r3 + adc lr, lr, #0 + lsr r2, r1, #31 + ldr r1, [sp, #44] + orr r2, r2, r1, lsl #1 + umull r2, r3, r12, r2 + add r3, r3, lr + adds r7, r7, r2 + mov lr, #0 + adcs r8, r8, r3 + adc lr, lr, #0 + lsr r2, r1, #31 + ldr r1, [sp, #48] + orr r2, r2, r1, lsl #1 + umull r2, r3, r12, r2 + add r3, r3, lr + adds r8, r8, r2 + mov lr, #0 + adcs r9, r9, r3 + adc lr, lr, #0 + lsr r2, r1, #31 + ldr r1, [sp, #52] + orr r2, r2, r1, lsl #1 + umull r2, r3, r12, r2 + add r3, r3, lr + adds r9, r9, r2 + mov lr, #0 + adcs r10, r10, r3 + adc lr, lr, #0 + lsr r2, r1, #31 + ldr r1, [sp, #56] + orr r2, r2, r1, lsl #1 + umull r2, r3, r12, r2 + add r3, r3, lr + adds r10, r10, r2 + mov lr, #0 + adcs r11, r11, r3 + adc lr, lr, #0 + lsr r2, r1, #31 + ldr r1, [sp, #60] + orr r2, r2, r1, lsl #1 + umull r2, r3, r12, r2 + adds r11, r11, r2 + adc r2, r3, lr + # Overflow + lsl r2, r2, #1 + orr r2, r2, r11, lsr #31 + mul r2, r2, r12 + and r11, r11, #0x7fffffff + adds r4, r4, r2 + adcs r5, r5, #0 + adcs r6, r6, #0 + adcs r7, r7, #0 + adcs r8, r8, #0 + adcs r9, r9, #0 + adcs r10, r10, #0 + adc r11, r11, #0 + # Reduce if top bit set + asr r2, r11, #31 + and r2, r2, r12 + and r11, r11, #0x7fffffff + adds r4, r4, r2 + adcs r5, r5, #0 + adcs r6, r6, #0 + adcs r7, r7, #0 + adcs r8, r8, #0 + adcs r9, r9, #0 + adcs r10, r10, #0 + adc r11, r11, #0 + # Store + strd r4, r5, [r0] + strd r6, r7, [r0, #8] + strd r8, r9, [r0, #16] + strd r10, r11, [r0, #24] + add sp, sp, #0x40 + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size fe_sq,.-fe_sq + .text + .align 2 + .globl fe_mul121666 + .type fe_mul121666, %function +fe_mul121666: + push {r4, r5, r6, r7, r8, r9, r10, lr} + # Multiply by 121666 + ldrd r2, r3, [r1] + ldrd r4, r5, [r1, #8] + ldrd r6, r7, [r1, #16] + ldrd r8, r9, [r1, #24] + movw lr, #0xdb42 + movt lr, #1 + umull r2, r10, r2, lr + umull r3, r12, r3, lr + adds r3, r3, r10 + adc r10, r12, #0 + umull r4, r12, r4, lr + adds r4, r4, r10 + adc r10, r12, #0 + umull r5, r12, r5, lr + adds r5, r5, r10 + adc r10, r12, #0 + umull r6, r12, r6, lr + adds r6, r6, r10 + adc r10, r12, #0 + umull r7, r12, r7, lr + adds r7, r7, r10 + adc r10, r12, #0 + umull r8, r12, r8, lr + adds r8, r8, r10 + adc r10, r12, #0 + umull r9, r12, r9, lr + adds r9, r9, r10 + adc r10, r12, #0 + mov lr, #19 + lsl r10, r10, #1 + orr r10, r10, r9, lsr #31 + mul r10, r10, lr + and r9, r9, #0x7fffffff + adds r2, r2, r10 + adcs r3, r3, #0 + adcs r4, r4, #0 + adcs r5, r5, #0 + adcs r6, r6, #0 + adcs r7, r7, #0 + adcs r8, r8, #0 + adc r9, r9, #0 + strd r2, r3, [r0] + strd r4, r5, [r0, #8] + strd r6, r7, [r0, #16] + strd r8, r9, [r0, #24] + pop {r4, r5, r6, r7, r8, r9, r10, pc} + .size fe_mul121666,.-fe_mul121666 + .text + .align 2 + .globl fe_sq2 + .type fe_sq2, %function +fe_sq2: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + sub sp, sp, #0x40 + # Square * 2 + ldr r7, [r1] + ldr r8, [r1, #4] + ldr r9, [r1, #8] + ldr r10, [r1, #12] + ldr r12, [r1, #16] + # A[0] * A[0] = 0 + umull r4, r5, r7, r7 + str r4, [sp] + # A[0] * A[1] = 1 + umull r2, r3, r7, r8 + mov r6, #0 + adds r5, r5, r2 + adc r6, r6, r3 + adds r5, r5, r2 + mov r4, #0 + adcs r6, r6, r3 + adc r4, r4, #0 + str r5, [sp, #4] + # A[1] * A[1] = 2 + umull r2, r3, r8, r8 + adds r6, r6, r2 + adc r4, r4, r3 + # A[0] * A[2] = 2 + umull r2, r3, r7, r9 + adds r6, r6, r2 + mov r5, #0 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + str r6, [sp, #8] + # A[0] * A[3] = 3 + umull r2, r3, r7, r10 + adds r4, r4, r2 + adc r5, r5, r3 + adds r4, r4, r2 + mov r6, #0 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[1] * A[2] = 3 + umull r2, r3, r8, r9 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + str r4, [sp, #12] + # A[2] * A[2] = 4 + umull r2, r3, r9, r9 + adds r5, r5, r2 + mov r4, #0 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[1] * A[3] = 4 + umull r2, r3, r8, r10 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[0] * A[4] = 4 + umull r2, r3, r7, r12 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + str r5, [sp, #16] + # A[0] * A[5] = 5 + ldr r11, [r1, #20] + umull r2, r3, r7, r11 + adds r6, r6, r2 + mov r5, #0 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + # A[1] * A[4] = 5 + umull r2, r3, r8, r12 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + # A[2] * A[3] = 5 + umull r2, r3, r9, r10 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + str r6, [sp, #20] + # A[3] * A[3] = 6 + umull r2, r3, r10, r10 + adds r4, r4, r2 + mov r6, #0 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[2] * A[4] = 6 + umull r2, r3, r9, r12 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[1] * A[5] = 6 + umull r2, r3, r8, r11 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[0] * A[6] = 6 + ldr r11, [r1, #24] + umull r2, r3, r7, r11 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + str r4, [sp, #24] + # A[0] * A[7] = 7 + ldr r11, [r1, #28] + umull r2, r3, r7, r11 + adds r5, r5, r2 + mov r4, #0 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[1] * A[6] = 7 + ldr r11, [r1, #24] + umull r2, r3, r8, r11 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[2] * A[5] = 7 + ldr r11, [r1, #20] + umull r2, r3, r9, r11 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[3] * A[4] = 7 + umull r2, r3, r10, r12 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + str r5, [sp, #28] + # A[4] * A[4] = 8 + umull r2, r3, r12, r12 + adds r6, r6, r2 + mov r5, #0 + adcs r4, r4, r3 + adc r5, r5, #0 + # A[3] * A[5] = 8 + umull r2, r3, r10, r11 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + # A[2] * A[6] = 8 + ldr r11, [r1, #24] + umull r2, r3, r9, r11 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + # A[1] * A[7] = 8 + ldr r11, [r1, #28] + umull r2, r3, r8, r11 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + str r6, [sp, #32] + ldr r7, [r1, #20] + # A[2] * A[7] = 9 + umull r2, r3, r9, r11 + adds r4, r4, r2 + mov r6, #0 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[3] * A[6] = 9 + ldr r11, [r1, #24] + umull r2, r3, r10, r11 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[4] * A[5] = 9 + umull r2, r3, r12, r7 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + str r4, [sp, #36] + mov r8, r11 + # A[5] * A[5] = 10 + umull r2, r3, r7, r7 + adds r5, r5, r2 + mov r4, #0 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[4] * A[6] = 10 + umull r2, r3, r12, r8 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + # A[3] * A[7] = 10 + ldr r11, [r1, #28] + umull r2, r3, r10, r11 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + str r5, [sp, #40] + mov r9, r11 + # A[4] * A[7] = 11 + umull r2, r3, r12, r9 + adds r6, r6, r2 + mov r5, #0 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + # A[5] * A[6] = 11 + umull r2, r3, r7, r8 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + adds r6, r6, r2 + adcs r4, r4, r3 + adc r5, r5, #0 + str r6, [sp, #44] + # A[6] * A[6] = 12 + umull r2, r3, r8, r8 + adds r4, r4, r2 + mov r6, #0 + adcs r5, r5, r3 + adc r6, r6, #0 + # A[5] * A[7] = 12 + umull r2, r3, r7, r9 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + adds r4, r4, r2 + adcs r5, r5, r3 + adc r6, r6, #0 + str r4, [sp, #48] + # A[6] * A[7] = 13 + umull r2, r3, r8, r9 + adds r5, r5, r2 + mov r4, #0 + adcs r6, r6, r3 + adc r4, r4, #0 + adds r5, r5, r2 + adcs r6, r6, r3 + adc r4, r4, #0 + str r5, [sp, #52] + # A[7] * A[7] = 14 + umull r2, r3, r9, r9 + adds r6, r6, r2 + adc r4, r4, r3 + str r6, [sp, #56] + str r4, [sp, #60] + # Double and Reduce + # Load bottom half + ldrd r4, r5, [sp] + ldrd r6, r7, [sp, #8] + ldrd r8, r9, [sp, #16] + ldrd r10, r11, [sp, #24] + lsr r2, r11, #30 + lsl r11, r11, #1 + orr r11, r11, r10, lsr #31 + lsl r10, r10, #1 + orr r10, r10, r9, lsr #31 + lsl r9, r9, #1 + orr r9, r9, r8, lsr #31 + lsl r8, r8, #1 + orr r8, r8, r7, lsr #31 + lsl r7, r7, #1 + orr r7, r7, r6, lsr #31 + lsl r6, r6, #1 + orr r6, r6, r5, lsr #31 + lsl r5, r5, #1 + orr r5, r5, r4, lsr #31 + lsl r4, r4, #1 + and r11, r11, #0x7fffffff + mov r12, #19 + ldr r1, [sp, #32] + orr r2, r2, r1, lsl #2 + umull r2, r3, r12, r2 + adds r4, r4, r2 + mov lr, #0 + adcs r5, r5, r3 + adc lr, lr, #0 + lsr r2, r1, #30 + ldr r1, [sp, #36] + orr r2, r2, r1, lsl #2 + umull r2, r3, r12, r2 + add r3, r3, lr + adds r5, r5, r2 + mov lr, #0 + adcs r6, r6, r3 + adc lr, lr, #0 + lsr r2, r1, #30 + ldr r1, [sp, #40] + orr r2, r2, r1, lsl #2 + umull r2, r3, r12, r2 + add r3, r3, lr + adds r6, r6, r2 + mov lr, #0 + adcs r7, r7, r3 + adc lr, lr, #0 + lsr r2, r1, #30 + ldr r1, [sp, #44] + orr r2, r2, r1, lsl #2 + umull r2, r3, r12, r2 + add r3, r3, lr + adds r7, r7, r2 + mov lr, #0 + adcs r8, r8, r3 + adc lr, lr, #0 + lsr r2, r1, #30 + ldr r1, [sp, #48] + orr r2, r2, r1, lsl #2 + umull r2, r3, r12, r2 + add r3, r3, lr + adds r8, r8, r2 + mov lr, #0 + adcs r9, r9, r3 + adc lr, lr, #0 + lsr r2, r1, #30 + ldr r1, [sp, #52] + orr r2, r2, r1, lsl #2 + umull r2, r3, r12, r2 + add r3, r3, lr + adds r9, r9, r2 + mov lr, #0 + adcs r10, r10, r3 + adc lr, lr, #0 + lsr r2, r1, #30 + ldr r1, [sp, #56] + orr r2, r2, r1, lsl #2 + umull r2, r3, r12, r2 + add r3, r3, lr + adds r10, r10, r2 + mov lr, #0 + adcs r11, r11, r3 + adc lr, lr, #0 + lsr r2, r1, #30 + ldr r1, [sp, #60] + orr r2, r2, r1, lsl #2 + umull r2, r3, r12, r2 + adds r11, r11, r2 + adc r2, r3, lr + # Overflow + lsl r2, r2, #1 + orr r2, r2, r11, lsr #31 + mul r2, r2, r12 + and r11, r11, #0x7fffffff + adds r4, r4, r2 + adcs r5, r5, #0 + adcs r6, r6, #0 + adcs r7, r7, #0 + adcs r8, r8, #0 + adcs r9, r9, #0 + adcs r10, r10, #0 + adc r11, r11, #0 + # Reduce if top bit set + asr r2, r11, #31 + and r2, r2, r12 + and r11, r11, #0x7fffffff + adds r4, r4, r2 + adcs r5, r5, #0 + adcs r6, r6, #0 + adcs r7, r7, #0 + adcs r8, r8, #0 + adcs r9, r9, #0 + adcs r10, r10, #0 + adc r11, r11, #0 + # Store + strd r4, r5, [r0] + strd r6, r7, [r0, #8] + strd r8, r9, [r0, #16] + strd r10, r11, [r0, #24] + add sp, sp, #0x40 + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size fe_sq2,.-fe_sq2 + .text + .align 2 + .globl fe_invert + .type fe_invert, %function +fe_invert: + push {r4, lr} + sub sp, sp, #0x88 + # Invert + str r0, [sp, #128] + str r1, [sp, #132] + mov r0, sp + ldr r1, [sp, #132] + bl fe_sq + add r0, sp, #32 + mov r1, sp + bl fe_sq + add r0, sp, #32 + add r1, sp, #32 + bl fe_sq + add r0, sp, #32 + ldr r1, [sp, #132] + add r2, sp, #32 + bl fe_mul + mov r0, sp + mov r1, sp + add r2, sp, #32 + bl fe_mul + add r0, sp, #0x40 + mov r1, sp + bl fe_sq + add r0, sp, #32 + add r1, sp, #32 + add r2, sp, #0x40 + bl fe_mul + add r0, sp, #0x40 + add r1, sp, #32 + bl fe_sq + mov r4, #4 +L_fe_invert1: + add r0, sp, #0x40 + add r1, sp, #0x40 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_invert1 + add r0, sp, #32 + add r1, sp, #0x40 + add r2, sp, #32 + bl fe_mul + add r0, sp, #0x40 + add r1, sp, #32 + bl fe_sq + mov r4, #9 +L_fe_invert2: + add r0, sp, #0x40 + add r1, sp, #0x40 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_invert2 + add r0, sp, #0x40 + add r1, sp, #0x40 + add r2, sp, #32 + bl fe_mul + add r0, sp, #0x60 + add r1, sp, #0x40 + bl fe_sq + mov r4, #19 +L_fe_invert3: + add r0, sp, #0x60 + add r1, sp, #0x60 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_invert3 + add r0, sp, #0x40 + add r1, sp, #0x60 + add r2, sp, #0x40 + bl fe_mul + mov r4, #10 +L_fe_invert4: + add r0, sp, #0x40 + add r1, sp, #0x40 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_invert4 + add r0, sp, #32 + add r1, sp, #0x40 + add r2, sp, #32 + bl fe_mul + add r0, sp, #0x40 + add r1, sp, #32 + bl fe_sq + mov r4, #49 +L_fe_invert5: + add r0, sp, #0x40 + add r1, sp, #0x40 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_invert5 + add r0, sp, #0x40 + add r1, sp, #0x40 + add r2, sp, #32 + bl fe_mul + add r0, sp, #0x60 + add r1, sp, #0x40 + bl fe_sq + mov r4, #0x63 +L_fe_invert6: + add r0, sp, #0x60 + add r1, sp, #0x60 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_invert6 + add r0, sp, #0x40 + add r1, sp, #0x60 + add r2, sp, #0x40 + bl fe_mul + mov r4, #50 +L_fe_invert7: + add r0, sp, #0x40 + add r1, sp, #0x40 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_invert7 + add r0, sp, #32 + add r1, sp, #0x40 + add r2, sp, #32 + bl fe_mul + mov r4, #5 +L_fe_invert8: + add r0, sp, #32 + add r1, sp, #32 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_invert8 + ldr r0, [sp, #128] + add r1, sp, #32 + mov r2, sp + bl fe_mul + ldr r1, [sp, #132] + ldr r0, [sp, #128] + add sp, sp, #0x88 + pop {r4, pc} + .size fe_invert,.-fe_invert + .text + .align 2 + .globl curve25519 + .type curve25519, %function +curve25519: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + sub sp, sp, #0xbc + str r0, [sp, #160] + str r1, [sp, #164] + str r2, [sp, #168] + mov r1, #0 + str r1, [sp, #172] + # Set one + mov r11, #1 + mov r10, #0 + str r11, [r0] + str r10, [r0, #4] + str r10, [r0, #8] + str r10, [r0, #12] + str r10, [r0, #16] + str r10, [r0, #20] + str r10, [r0, #24] + str r10, [r0, #28] + # Set zero + mov r10, #0 + str r10, [sp] + str r10, [sp, #4] + str r10, [sp, #8] + str r10, [sp, #12] + str r10, [sp, #16] + str r10, [sp, #20] + str r10, [sp, #24] + str r10, [sp, #28] + # Set one + mov r11, #1 + mov r10, #0 + str r11, [sp, #32] + str r10, [sp, #36] + str r10, [sp, #40] + str r10, [sp, #44] + str r10, [sp, #48] + str r10, [sp, #52] + str r10, [sp, #56] + str r10, [sp, #60] + # Copy + ldrd r4, r5, [r2] + ldrd r6, r7, [r2, #8] + strd r4, r5, [sp, #64] + strd r6, r7, [sp, #72] + ldrd r4, r5, [r2, #16] + ldrd r6, r7, [r2, #24] + strd r4, r5, [sp, #80] + strd r6, r7, [sp, #88] + mov r1, #30 + str r1, [sp, #180] + mov r2, #28 + str r2, [sp, #176] +L_curve25519_words: +L_curve25519_bits: + ldr r1, [sp, #164] + ldr r2, [r1, r2] + ldr r1, [sp, #180] + lsr r2, r2, r1 + and r2, r2, #1 + str r2, [sp, #184] + ldr r1, [sp, #172] + eor r1, r1, r2 + str r1, [sp, #172] + ldr r0, [sp, #160] + # Conditional Swap + neg r1, r1 + ldrd r4, r5, [r0] + ldrd r6, r7, [sp, #64] + eor r8, r4, r6 + eor r9, r5, r7 + and r8, r8, r1 + and r9, r9, r1 + eor r4, r4, r8 + eor r5, r5, r9 + eor r6, r6, r8 + eor r7, r7, r9 + strd r4, r5, [r0] + strd r6, r7, [sp, #64] + ldrd r4, r5, [r0, #8] + ldrd r6, r7, [sp, #72] + eor r8, r4, r6 + eor r9, r5, r7 + and r8, r8, r1 + and r9, r9, r1 + eor r4, r4, r8 + eor r5, r5, r9 + eor r6, r6, r8 + eor r7, r7, r9 + strd r4, r5, [r0, #8] + strd r6, r7, [sp, #72] + ldrd r4, r5, [r0, #16] + ldrd r6, r7, [sp, #80] + eor r8, r4, r6 + eor r9, r5, r7 + and r8, r8, r1 + and r9, r9, r1 + eor r4, r4, r8 + eor r5, r5, r9 + eor r6, r6, r8 + eor r7, r7, r9 + strd r4, r5, [r0, #16] + strd r6, r7, [sp, #80] + ldrd r4, r5, [r0, #24] + ldrd r6, r7, [sp, #88] + eor r8, r4, r6 + eor r9, r5, r7 + and r8, r8, r1 + and r9, r9, r1 + eor r4, r4, r8 + eor r5, r5, r9 + eor r6, r6, r8 + eor r7, r7, r9 + strd r4, r5, [r0, #24] + strd r6, r7, [sp, #88] + ldr r1, [sp, #172] + # Conditional Swap + neg r1, r1 + ldrd r4, r5, [sp] + ldrd r6, r7, [sp, #32] + eor r8, r4, r6 + eor r9, r5, r7 + and r8, r8, r1 + and r9, r9, r1 + eor r4, r4, r8 + eor r5, r5, r9 + eor r6, r6, r8 + eor r7, r7, r9 + strd r4, r5, [sp] + strd r6, r7, [sp, #32] + ldrd r4, r5, [sp, #8] + ldrd r6, r7, [sp, #40] + eor r8, r4, r6 + eor r9, r5, r7 + and r8, r8, r1 + and r9, r9, r1 + eor r4, r4, r8 + eor r5, r5, r9 + eor r6, r6, r8 + eor r7, r7, r9 + strd r4, r5, [sp, #8] + strd r6, r7, [sp, #40] + ldrd r4, r5, [sp, #16] + ldrd r6, r7, [sp, #48] + eor r8, r4, r6 + eor r9, r5, r7 + and r8, r8, r1 + and r9, r9, r1 + eor r4, r4, r8 + eor r5, r5, r9 + eor r6, r6, r8 + eor r7, r7, r9 + strd r4, r5, [sp, #16] + strd r6, r7, [sp, #48] + ldrd r4, r5, [sp, #24] + ldrd r6, r7, [sp, #56] + eor r8, r4, r6 + eor r9, r5, r7 + and r8, r8, r1 + and r9, r9, r1 + eor r4, r4, r8 + eor r5, r5, r9 + eor r6, r6, r8 + eor r7, r7, r9 + strd r4, r5, [sp, #24] + strd r6, r7, [sp, #56] + ldr r1, [sp, #184] + str r1, [sp, #172] + # Add-Sub + # Add + ldrd r4, r5, [r0] + ldrd r6, r7, [sp] + adds r8, r4, r6 + mov r3, #0 + adcs r9, r5, r7 + adc r3, r3, #0 + strd r8, r9, [r0] + # Sub + subs r10, r4, r6 + mov r12, #0 + sbcs r11, r5, r7 + adc r12, r12, #0 + strd r10, r11, [sp, #128] + # Add + ldrd r4, r5, [r0, #8] + ldrd r6, r7, [sp, #8] + adds r3, r3, #-1 + adcs r8, r4, r6 + mov r3, #0 + adcs r9, r5, r7 + adc r3, r3, #0 + strd r8, r9, [r0, #8] + # Sub + adds r12, r12, #-1 + sbcs r10, r4, r6 + mov r12, #0 + sbcs r11, r5, r7 + adc r12, r12, #0 + strd r10, r11, [sp, #136] + # Add + ldrd r4, r5, [r0, #16] + ldrd r6, r7, [sp, #16] + adds r3, r3, #-1 + adcs r8, r4, r6 + mov r3, #0 + adcs r9, r5, r7 + adc r3, r3, #0 + strd r8, r9, [r0, #16] + # Sub + adds r12, r12, #-1 + sbcs r10, r4, r6 + mov r12, #0 + sbcs r11, r5, r7 + adc r12, r12, #0 + strd r10, r11, [sp, #144] + # Add + ldrd r4, r5, [r0, #24] + ldrd r6, r7, [sp, #24] + adds r3, r3, #-1 + adcs r8, r4, r6 + adc r9, r5, r7 + # Sub + adds r12, r12, #-1 + sbcs r10, r4, r6 + sbc r11, r5, r7 + mov r3, #-19 + asr r2, r9, #31 + # Mask the modulus + and r3, r2, r3 + and r12, r2, #0x7fffffff + # Sub modulus (if overflow) + ldrd r4, r5, [r0] + subs r4, r4, r3 + sbcs r5, r5, r2 + strd r4, r5, [r0] + ldrd r4, r5, [r0, #8] + sbcs r4, r4, r2 + sbcs r5, r5, r2 + strd r4, r5, [r0, #8] + ldrd r4, r5, [r0, #16] + sbcs r4, r4, r2 + sbcs r5, r5, r2 + strd r4, r5, [r0, #16] + sbcs r8, r8, r2 + sbc r9, r9, r12 + strd r8, r9, [r0, #24] + mov r3, #-19 + asr r2, r11, #31 + # Mask the modulus + and r3, r2, r3 + and r12, r2, #0x7fffffff + # Add modulus (if underflow) + ldrd r4, r5, [sp, #128] + adds r4, r4, r3 + adcs r5, r5, r2 + strd r4, r5, [sp, #128] + ldrd r4, r5, [sp, #136] + adcs r4, r4, r2 + adcs r5, r5, r2 + strd r4, r5, [sp, #136] + ldrd r4, r5, [sp, #144] + adcs r4, r4, r2 + adcs r5, r5, r2 + strd r4, r5, [sp, #144] + adcs r10, r10, r2 + adc r11, r11, r12 + strd r10, r11, [sp, #152] + # Add-Sub + # Add + ldrd r4, r5, [sp, #64] + ldrd r6, r7, [sp, #32] + adds r8, r4, r6 + mov r3, #0 + adcs r9, r5, r7 + adc r3, r3, #0 + strd r8, r9, [sp] + # Sub + subs r10, r4, r6 + mov r12, #0 + sbcs r11, r5, r7 + adc r12, r12, #0 + strd r10, r11, [sp, #96] + # Add + ldrd r4, r5, [sp, #72] + ldrd r6, r7, [sp, #40] + adds r3, r3, #-1 + adcs r8, r4, r6 + mov r3, #0 + adcs r9, r5, r7 + adc r3, r3, #0 + strd r8, r9, [sp, #8] + # Sub + adds r12, r12, #-1 + sbcs r10, r4, r6 + mov r12, #0 + sbcs r11, r5, r7 + adc r12, r12, #0 + strd r10, r11, [sp, #104] + # Add + ldrd r4, r5, [sp, #80] + ldrd r6, r7, [sp, #48] + adds r3, r3, #-1 + adcs r8, r4, r6 + mov r3, #0 + adcs r9, r5, r7 + adc r3, r3, #0 + strd r8, r9, [sp, #16] + # Sub + adds r12, r12, #-1 + sbcs r10, r4, r6 + mov r12, #0 + sbcs r11, r5, r7 + adc r12, r12, #0 + strd r10, r11, [sp, #112] + # Add + ldrd r4, r5, [sp, #88] + ldrd r6, r7, [sp, #56] + adds r3, r3, #-1 + adcs r8, r4, r6 + adc r9, r5, r7 + # Sub + adds r12, r12, #-1 + sbcs r10, r4, r6 + sbc r11, r5, r7 + mov r3, #-19 + asr r2, r9, #31 + # Mask the modulus + and r3, r2, r3 + and r12, r2, #0x7fffffff + # Sub modulus (if overflow) + ldrd r4, r5, [sp] + subs r4, r4, r3 + sbcs r5, r5, r2 + strd r4, r5, [sp] + ldrd r4, r5, [sp, #8] + sbcs r4, r4, r2 + sbcs r5, r5, r2 + strd r4, r5, [sp, #8] + ldrd r4, r5, [sp, #16] + sbcs r4, r4, r2 + sbcs r5, r5, r2 + strd r4, r5, [sp, #16] + sbcs r8, r8, r2 + sbc r9, r9, r12 + strd r8, r9, [sp, #24] + mov r3, #-19 + asr r2, r11, #31 + # Mask the modulus + and r3, r2, r3 + and r12, r2, #0x7fffffff + # Add modulus (if underflow) + ldrd r4, r5, [sp, #96] + adds r4, r4, r3 + adcs r5, r5, r2 + strd r4, r5, [sp, #96] + ldrd r4, r5, [sp, #104] + adcs r4, r4, r2 + adcs r5, r5, r2 + strd r4, r5, [sp, #104] + ldrd r4, r5, [sp, #112] + adcs r4, r4, r2 + adcs r5, r5, r2 + strd r4, r5, [sp, #112] + adcs r10, r10, r2 + adc r11, r11, r12 + strd r10, r11, [sp, #120] + ldr r2, [sp, #160] + add r1, sp, #0x60 + add r0, sp, #32 + bl fe_mul + add r2, sp, #0x80 + add r1, sp, #0 + add r0, sp, #0 + bl fe_mul + add r1, sp, #0x80 + add r0, sp, #0x60 + bl fe_sq + ldr r1, [sp, #160] + add r0, sp, #0x80 + bl fe_sq + # Add-Sub + # Add + ldrd r4, r5, [sp, #32] + ldrd r6, r7, [sp] + adds r8, r4, r6 + mov r3, #0 + adcs r9, r5, r7 + adc r3, r3, #0 + strd r8, r9, [sp, #64] + # Sub + subs r10, r4, r6 + mov r12, #0 + sbcs r11, r5, r7 + adc r12, r12, #0 + strd r10, r11, [sp] + # Add + ldrd r4, r5, [sp, #40] + ldrd r6, r7, [sp, #8] + adds r3, r3, #-1 + adcs r8, r4, r6 + mov r3, #0 + adcs r9, r5, r7 + adc r3, r3, #0 + strd r8, r9, [sp, #72] + # Sub + adds r12, r12, #-1 + sbcs r10, r4, r6 + mov r12, #0 + sbcs r11, r5, r7 + adc r12, r12, #0 + strd r10, r11, [sp, #8] + # Add + ldrd r4, r5, [sp, #48] + ldrd r6, r7, [sp, #16] + adds r3, r3, #-1 + adcs r8, r4, r6 + mov r3, #0 + adcs r9, r5, r7 + adc r3, r3, #0 + strd r8, r9, [sp, #80] + # Sub + adds r12, r12, #-1 + sbcs r10, r4, r6 + mov r12, #0 + sbcs r11, r5, r7 + adc r12, r12, #0 + strd r10, r11, [sp, #16] + # Add + ldrd r4, r5, [sp, #56] + ldrd r6, r7, [sp, #24] + adds r3, r3, #-1 + adcs r8, r4, r6 + adc r9, r5, r7 + # Sub + adds r12, r12, #-1 + sbcs r10, r4, r6 + sbc r11, r5, r7 + mov r3, #-19 + asr r2, r9, #31 + # Mask the modulus + and r3, r2, r3 + and r12, r2, #0x7fffffff + # Sub modulus (if overflow) + ldrd r4, r5, [sp, #64] + subs r4, r4, r3 + sbcs r5, r5, r2 + strd r4, r5, [sp, #64] + ldrd r4, r5, [sp, #72] + sbcs r4, r4, r2 + sbcs r5, r5, r2 + strd r4, r5, [sp, #72] + ldrd r4, r5, [sp, #80] + sbcs r4, r4, r2 + sbcs r5, r5, r2 + strd r4, r5, [sp, #80] + sbcs r8, r8, r2 + sbc r9, r9, r12 + strd r8, r9, [sp, #88] + mov r3, #-19 + asr r2, r11, #31 + # Mask the modulus + and r3, r2, r3 + and r12, r2, #0x7fffffff + # Add modulus (if underflow) + ldrd r4, r5, [sp] + adds r4, r4, r3 + adcs r5, r5, r2 + strd r4, r5, [sp] + ldrd r4, r5, [sp, #8] + adcs r4, r4, r2 + adcs r5, r5, r2 + strd r4, r5, [sp, #8] + ldrd r4, r5, [sp, #16] + adcs r4, r4, r2 + adcs r5, r5, r2 + strd r4, r5, [sp, #16] + adcs r10, r10, r2 + adc r11, r11, r12 + strd r10, r11, [sp, #24] + add r2, sp, #0x60 + add r1, sp, #0x80 + ldr r0, [sp, #160] + bl fe_mul + # Sub + ldrd r4, r5, [sp, #128] + ldrd r6, r7, [sp, #136] + ldrd r8, r9, [sp, #96] + ldrd r10, r11, [sp, #104] + subs r8, r4, r8 + sbcs r9, r5, r9 + sbcs r10, r6, r10 + sbcs r11, r7, r11 + strd r8, r9, [sp, #128] + strd r10, r11, [sp, #136] + ldrd r4, r5, [sp, #144] + ldrd r6, r7, [sp, #152] + ldrd r8, r9, [sp, #112] + ldrd r10, r11, [sp, #120] + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbcs r10, r6, r10 + sbc r11, r7, r11 + mov r3, #-19 + asr r2, r11, #31 + # Mask the modulus + and r3, r2, r3 + and r12, r2, #0x7fffffff + # Add modulus (if underflow) + ldrd r4, r5, [sp, #128] + ldrd r6, r7, [sp, #136] + adds r4, r4, r3 + adcs r5, r5, r2 + adcs r6, r6, r2 + adcs r7, r7, r2 + adcs r8, r8, r2 + adcs r9, r9, r2 + adcs r10, r10, r2 + adc r11, r11, r12 + strd r4, r5, [sp, #128] + strd r6, r7, [sp, #136] + strd r8, r9, [sp, #144] + strd r10, r11, [sp, #152] + add r1, sp, #0 + add r0, sp, #0 + bl fe_sq + # Multiply by 121666 + ldrd r4, r5, [sp, #128] + ldrd r6, r7, [sp, #136] + ldrd r8, r9, [sp, #144] + ldrd r10, r11, [sp, #152] + movw r12, #0xdb42 + movt r12, #1 + umull r4, r2, r4, r12 + umull r5, r3, r5, r12 + adds r5, r5, r2 + adc r2, r3, #0 + umull r6, r3, r6, r12 + adds r6, r6, r2 + adc r2, r3, #0 + umull r7, r3, r7, r12 + adds r7, r7, r2 + adc r2, r3, #0 + umull r8, r3, r8, r12 + adds r8, r8, r2 + adc r2, r3, #0 + umull r9, r3, r9, r12 + adds r9, r9, r2 + adc r2, r3, #0 + umull r10, r3, r10, r12 + adds r10, r10, r2 + adc r2, r3, #0 + umull r11, r3, r11, r12 + adds r11, r11, r2 + adc r2, r3, #0 + mov r12, #19 + lsl r2, r2, #1 + orr r2, r2, r11, lsr #31 + mul r2, r2, r12 + and r11, r11, #0x7fffffff + adds r4, r4, r2 + adcs r5, r5, #0 + adcs r6, r6, #0 + adcs r7, r7, #0 + adcs r8, r8, #0 + adcs r9, r9, #0 + adcs r10, r10, #0 + adc r11, r11, #0 + strd r4, r5, [sp, #32] + strd r6, r7, [sp, #40] + strd r8, r9, [sp, #48] + strd r10, r11, [sp, #56] + add r1, sp, #0x40 + add r0, sp, #0x40 + bl fe_sq + # Add + ldrd r4, r5, [sp, #96] + ldrd r6, r7, [sp, #104] + ldrd r8, r9, [sp, #32] + ldrd r10, r11, [sp, #40] + adds r8, r4, r8 + adcs r9, r5, r9 + adcs r10, r6, r10 + adcs r11, r7, r11 + strd r8, r9, [sp, #96] + strd r10, r11, [sp, #104] + ldrd r4, r5, [sp, #112] + ldrd r6, r7, [sp, #120] + ldrd r8, r9, [sp, #48] + ldrd r10, r11, [sp, #56] + adcs r8, r4, r8 + adcs r9, r5, r9 + adcs r10, r6, r10 + adc r11, r7, r11 + mov r3, #-19 + asr r2, r11, #31 + # Mask the modulus + and r3, r2, r3 + and r12, r2, #0x7fffffff + # Sub modulus (if overflow) + ldrd r4, r5, [sp, #96] + ldrd r6, r7, [sp, #104] + subs r4, r4, r3 + sbcs r5, r5, r2 + sbcs r6, r6, r2 + sbcs r7, r7, r2 + sbcs r8, r8, r2 + sbcs r9, r9, r2 + sbcs r10, r10, r2 + sbc r11, r11, r12 + strd r4, r5, [sp, #96] + strd r6, r7, [sp, #104] + strd r8, r9, [sp, #112] + strd r10, r11, [sp, #120] + add r2, sp, #0 + ldr r1, [sp, #168] + add r0, sp, #32 + bl fe_mul + add r2, sp, #0x60 + add r1, sp, #0x80 + add r0, sp, #0 + bl fe_mul + ldr r2, [sp, #176] + ldr r1, [sp, #180] + subs r1, r1, #1 + str r1, [sp, #180] + bge L_curve25519_bits + mov r1, #31 + str r1, [sp, #180] + subs r2, r2, #4 + str r2, [sp, #176] + bge L_curve25519_words + # Invert + add r0, sp, #32 + add r1, sp, #0 + bl fe_sq + add r0, sp, #0x40 + add r1, sp, #32 + bl fe_sq + add r0, sp, #0x40 + add r1, sp, #0x40 + bl fe_sq + add r0, sp, #0x40 + add r1, sp, #0 + add r2, sp, #0x40 + bl fe_mul + add r0, sp, #32 + add r1, sp, #32 + add r2, sp, #0x40 + bl fe_mul + add r0, sp, #0x60 + add r1, sp, #32 + bl fe_sq + add r0, sp, #0x40 + add r1, sp, #0x40 + add r2, sp, #0x60 + bl fe_mul + add r0, sp, #0x60 + add r1, sp, #0x40 + bl fe_sq + mov r4, #4 +L_curve25519_inv_1: + add r0, sp, #0x60 + add r1, sp, #0x60 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_curve25519_inv_1 + add r0, sp, #0x40 + add r1, sp, #0x60 + add r2, sp, #0x40 + bl fe_mul + add r0, sp, #0x60 + add r1, sp, #0x40 + bl fe_sq + mov r4, #9 +L_curve25519_inv_2: + add r0, sp, #0x60 + add r1, sp, #0x60 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_curve25519_inv_2 + add r0, sp, #0x60 + add r1, sp, #0x60 + add r2, sp, #0x40 + bl fe_mul + add r0, sp, #0x80 + add r1, sp, #0x60 + bl fe_sq + mov r4, #19 +L_curve25519_inv_3: + add r0, sp, #0x80 + add r1, sp, #0x80 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_curve25519_inv_3 + add r0, sp, #0x60 + add r1, sp, #0x80 + add r2, sp, #0x60 + bl fe_mul + mov r4, #10 +L_curve25519_inv_4: + add r0, sp, #0x60 + add r1, sp, #0x60 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_curve25519_inv_4 + add r0, sp, #0x40 + add r1, sp, #0x60 + add r2, sp, #0x40 + bl fe_mul + add r0, sp, #0x60 + add r1, sp, #0x40 + bl fe_sq + mov r4, #49 +L_curve25519_inv_5: + add r0, sp, #0x60 + add r1, sp, #0x60 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_curve25519_inv_5 + add r0, sp, #0x60 + add r1, sp, #0x60 + add r2, sp, #0x40 + bl fe_mul + add r0, sp, #0x80 + add r1, sp, #0x60 + bl fe_sq + mov r4, #0x63 +L_curve25519_inv_6: + add r0, sp, #0x80 + add r1, sp, #0x80 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_curve25519_inv_6 + add r0, sp, #0x60 + add r1, sp, #0x80 + add r2, sp, #0x60 + bl fe_mul + mov r4, #50 +L_curve25519_inv_7: + add r0, sp, #0x60 + add r1, sp, #0x60 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_curve25519_inv_7 + add r0, sp, #0x40 + add r1, sp, #0x60 + add r2, sp, #0x40 + bl fe_mul + mov r4, #5 +L_curve25519_inv_8: + add r0, sp, #0x40 + add r1, sp, #0x40 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_curve25519_inv_8 + add r0, sp, #0 + add r1, sp, #0x40 + add r2, sp, #32 + bl fe_mul + add r2, sp, #0 + ldr r1, [sp, #160] + ldr r0, [sp, #160] + bl fe_mul + mov r0, #0 + add sp, sp, #0xbc + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size curve25519,.-curve25519 + .text + .align 2 + .globl fe_pow22523 + .type fe_pow22523, %function +fe_pow22523: + push {r4, lr} + sub sp, sp, #0x68 + # pow22523 + str r0, [sp, #96] + str r1, [sp, #100] + mov r0, sp + ldr r1, [sp, #100] + bl fe_sq + add r0, sp, #32 + mov r1, sp + bl fe_sq + add r0, sp, #32 + add r1, sp, #32 + bl fe_sq + add r0, sp, #32 + ldr r1, [sp, #100] + add r2, sp, #32 + bl fe_mul + mov r0, sp + mov r1, sp + add r2, sp, #32 + bl fe_mul + mov r0, sp + mov r1, sp + bl fe_sq + mov r0, sp + add r1, sp, #32 + mov r2, sp + bl fe_mul + add r0, sp, #32 + mov r1, sp + bl fe_sq + mov r4, #4 +L_fe_pow22523_1: + add r0, sp, #32 + add r1, sp, #32 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_pow22523_1 + mov r0, sp + add r1, sp, #32 + mov r2, sp + bl fe_mul + add r0, sp, #32 + mov r1, sp + bl fe_sq + mov r4, #9 +L_fe_pow22523_2: + add r0, sp, #32 + add r1, sp, #32 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_pow22523_2 + add r0, sp, #32 + add r1, sp, #32 + mov r2, sp + bl fe_mul + add r0, sp, #0x40 + add r1, sp, #32 + bl fe_sq + mov r4, #19 +L_fe_pow22523_3: + add r0, sp, #0x40 + add r1, sp, #0x40 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_pow22523_3 + add r0, sp, #32 + add r1, sp, #0x40 + add r2, sp, #32 + bl fe_mul + mov r4, #10 +L_fe_pow22523_4: + add r0, sp, #32 + add r1, sp, #32 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_pow22523_4 + mov r0, sp + add r1, sp, #32 + mov r2, sp + bl fe_mul + add r0, sp, #32 + mov r1, sp + bl fe_sq + mov r4, #49 +L_fe_pow22523_5: + add r0, sp, #32 + add r1, sp, #32 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_pow22523_5 + add r0, sp, #32 + add r1, sp, #32 + mov r2, sp + bl fe_mul + add r0, sp, #0x40 + add r1, sp, #32 + bl fe_sq + mov r4, #0x63 +L_fe_pow22523_6: + add r0, sp, #0x40 + add r1, sp, #0x40 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_pow22523_6 + add r0, sp, #32 + add r1, sp, #0x40 + add r2, sp, #32 + bl fe_mul + mov r4, #50 +L_fe_pow22523_7: + add r0, sp, #32 + add r1, sp, #32 + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_pow22523_7 + mov r0, sp + add r1, sp, #32 + mov r2, sp + bl fe_mul + mov r4, #2 +L_fe_pow22523_8: + mov r0, sp + mov r1, sp + bl fe_sq + sub r4, r4, #1 + cmp r4, #0 + bne L_fe_pow22523_8 + ldr r0, [sp, #96] + mov r1, sp + ldr r2, [sp, #100] + bl fe_mul + ldr r1, [sp, #100] + ldr r0, [sp, #96] + add sp, sp, #0x68 + pop {r4, pc} + .size fe_pow22523,.-fe_pow22523 + .text + .align 2 + .globl fe_ge_to_p2 + .type fe_ge_to_p2, %function +fe_ge_to_p2: + push {lr} + sub sp, sp, #16 + str r0, [sp] + str r1, [sp, #4] + str r2, [sp, #8] + str r3, [sp, #12] + ldr r2, [sp, #28] + ldr r1, [sp, #12] + ldr r0, [sp] + bl fe_mul + ldr r2, [sp, #24] + ldr r1, [sp, #20] + ldr r0, [sp, #4] + bl fe_mul + ldr r2, [sp, #28] + ldr r1, [sp, #24] + ldr r0, [sp, #8] + bl fe_mul + add sp, sp, #16 + pop {pc} + .size fe_ge_to_p2,.-fe_ge_to_p2 + .text + .align 2 + .globl fe_ge_to_p3 + .type fe_ge_to_p3, %function +fe_ge_to_p3: + push {lr} + sub sp, sp, #16 + str r0, [sp] + str r1, [sp, #4] + str r2, [sp, #8] + str r3, [sp, #12] + ldr r2, [sp, #32] + ldr r1, [sp, #20] + ldr r0, [sp] + bl fe_mul + ldr r2, [sp, #28] + ldr r1, [sp, #24] + ldr r0, [sp, #4] + bl fe_mul + ldr r2, [sp, #32] + ldr r1, [sp, #28] + ldr r0, [sp, #8] + bl fe_mul + ldr r2, [sp, #24] + ldr r1, [sp, #20] + ldr r0, [sp, #12] + bl fe_mul + add sp, sp, #16 + pop {pc} + .size fe_ge_to_p3,.-fe_ge_to_p3 + .text + .align 2 + .globl fe_ge_dbl + .type fe_ge_dbl, %function +fe_ge_dbl: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + sub sp, sp, #16 + str r0, [sp] + str r1, [sp, #4] + str r2, [sp, #8] + str r3, [sp, #12] + ldr r1, [sp, #52] + ldr r0, [sp] + bl fe_sq + ldr r1, [sp, #56] + ldr r0, [sp, #8] + bl fe_sq + ldr r0, [sp, #4] + ldr r1, [sp, #52] + ldr r2, [sp, #56] + # Add + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r2] + ldr r8, [r2, #4] + ldr r9, [r2, #8] + ldr r10, [r2, #12] + adds r7, r3, r7 + adcs r8, r4, r8 + adcs r9, r5, r9 + adcs r10, r6, r10 + str r7, [r0] + str r8, [r0, #4] + str r9, [r0, #8] + str r10, [r0, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + ldr r5, [r1, #24] + ldr r6, [r1, #28] + ldr r7, [r2, #16] + ldr r8, [r2, #20] + ldr r9, [r2, #24] + ldr r10, [r2, #28] + adcs r7, r3, r7 + adcs r8, r4, r8 + adcs r9, r5, r9 + adc r10, r6, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + subs r3, r3, r12 + sbcs r4, r4, r11 + sbcs r5, r5, r11 + sbcs r6, r6, r11 + sbcs r7, r7, r11 + sbcs r8, r8, r11 + sbcs r9, r9, r11 + sbc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r1, [sp, #4] + ldr r0, [sp, #12] + bl fe_sq + ldr r0, [sp, #4] + ldr r1, [sp, #8] + ldr r2, [sp] + # Add-Sub + # Add + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r2] + ldr r6, [r2, #4] + adds r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0] + str r8, [r0, #4] + # Sub + subs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1] + str r10, [r1, #4] + # Add + ldr r3, [r1, #8] + ldr r4, [r1, #12] + ldr r5, [r2, #8] + ldr r6, [r2, #12] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #8] + str r8, [r0, #12] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #8] + str r10, [r1, #12] + # Add + ldr r3, [r1, #16] + ldr r4, [r1, #20] + ldr r5, [r2, #16] + ldr r6, [r2, #20] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #16] + str r8, [r0, #20] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #16] + str r10, [r1, #20] + # Add + ldr r3, [r1, #24] + ldr r4, [r1, #28] + ldr r5, [r2, #24] + ldr r6, [r2, #28] + adds r12, r12, #-1 + adcs r7, r3, r5 + adc r8, r4, r6 + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + sbc r10, r4, r6 + mov r12, #-19 + asr r11, r8, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + subs r3, r3, r12 + sbcs r4, r4, r11 + str r3, [r0] + str r4, [r0, #4] + ldr r3, [r0, #8] + ldr r4, [r0, #12] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #8] + str r4, [r0, #12] + ldr r3, [r0, #16] + ldr r4, [r0, #20] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #16] + str r4, [r0, #20] + sbcs r7, r7, r11 + sbc r8, r8, lr + str r7, [r0, #24] + str r8, [r0, #28] + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r1] + ldr r4, [r1, #4] + adds r3, r3, r12 + adcs r4, r4, r11 + str r3, [r1] + str r4, [r1, #4] + ldr r3, [r1, #8] + ldr r4, [r1, #12] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #8] + str r4, [r1, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #16] + str r4, [r1, #20] + adcs r9, r9, r11 + adc r10, r10, lr + str r9, [r1, #24] + str r10, [r1, #28] + ldr r0, [sp] + ldr r1, [sp, #12] + ldr r2, [sp, #4] + # Sub + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r2] + ldr r8, [r2, #4] + ldr r9, [r2, #8] + ldr r10, [r2, #12] + subs r7, r3, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbcs r10, r6, r10 + str r7, [r0] + str r8, [r0, #4] + str r9, [r0, #8] + str r10, [r0, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + ldr r5, [r1, #24] + ldr r6, [r1, #28] + ldr r7, [r2, #16] + ldr r8, [r2, #20] + ldr r9, [r2, #24] + ldr r10, [r2, #28] + sbcs r7, r3, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbc r10, r6, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + adds r3, r3, r12 + adcs r4, r4, r11 + adcs r5, r5, r11 + adcs r6, r6, r11 + adcs r7, r7, r11 + adcs r8, r8, r11 + adcs r9, r9, r11 + adc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r1, [sp, #60] + ldr r0, [sp, #12] + bl fe_sq2 + ldr r0, [sp, #12] + ldr r1, [sp, #8] + # Sub + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + ldr r7, [r1] + ldr r8, [r1, #4] + ldr r9, [r1, #8] + ldr r10, [r1, #12] + subs r7, r3, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbcs r10, r6, r10 + str r7, [r0] + str r8, [r0, #4] + str r9, [r0, #8] + str r10, [r0, #12] + ldr r3, [r0, #16] + ldr r4, [r0, #20] + ldr r5, [r0, #24] + ldr r6, [r0, #28] + ldr r7, [r1, #16] + ldr r8, [r1, #20] + ldr r9, [r1, #24] + ldr r10, [r1, #28] + sbcs r7, r3, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbc r10, r6, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + adds r3, r3, r12 + adcs r4, r4, r11 + adcs r5, r5, r11 + adcs r6, r6, r11 + adcs r7, r7, r11 + adcs r8, r8, r11 + adcs r9, r9, r11 + adc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + add sp, sp, #16 + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size fe_ge_dbl,.-fe_ge_dbl + .text + .align 2 + .globl fe_ge_madd + .type fe_ge_madd, %function +fe_ge_madd: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + sub sp, sp, #32 + str r0, [sp] + str r1, [sp, #4] + str r2, [sp, #8] + str r3, [sp, #12] + ldr r0, [sp] + ldr r1, [sp, #72] + ldr r2, [sp, #68] + # Add + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r2] + ldr r8, [r2, #4] + ldr r9, [r2, #8] + ldr r10, [r2, #12] + adds r7, r3, r7 + adcs r8, r4, r8 + adcs r9, r5, r9 + adcs r10, r6, r10 + str r7, [r0] + str r8, [r0, #4] + str r9, [r0, #8] + str r10, [r0, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + ldr r5, [r1, #24] + ldr r6, [r1, #28] + ldr r7, [r2, #16] + ldr r8, [r2, #20] + ldr r9, [r2, #24] + ldr r10, [r2, #28] + adcs r7, r3, r7 + adcs r8, r4, r8 + adcs r9, r5, r9 + adc r10, r6, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + subs r3, r3, r12 + sbcs r4, r4, r11 + sbcs r5, r5, r11 + sbcs r6, r6, r11 + sbcs r7, r7, r11 + sbcs r8, r8, r11 + sbcs r9, r9, r11 + sbc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r0, [sp, #4] + ldr r1, [sp, #72] + ldr r2, [sp, #68] + # Sub + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r2] + ldr r8, [r2, #4] + ldr r9, [r2, #8] + ldr r10, [r2, #12] + subs r7, r3, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbcs r10, r6, r10 + str r7, [r0] + str r8, [r0, #4] + str r9, [r0, #8] + str r10, [r0, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + ldr r5, [r1, #24] + ldr r6, [r1, #28] + ldr r7, [r2, #16] + ldr r8, [r2, #20] + ldr r9, [r2, #24] + ldr r10, [r2, #28] + sbcs r7, r3, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbc r10, r6, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + adds r3, r3, r12 + adcs r4, r4, r11 + adcs r5, r5, r11 + adcs r6, r6, r11 + adcs r7, r7, r11 + adcs r8, r8, r11 + adcs r9, r9, r11 + adc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r2, [sp, #88] + ldr r1, [sp] + ldr r0, [sp, #8] + bl fe_mul + ldr r2, [sp, #92] + ldr r1, [sp, #4] + ldr r0, [sp, #4] + bl fe_mul + ldr r2, [sp, #80] + ldr r1, [sp, #84] + ldr r0, [sp, #12] + bl fe_mul + ldr r0, [sp, #4] + ldr r1, [sp] + ldr r2, [sp, #8] + # Add-Sub + # Add + ldr r3, [r2] + ldr r4, [r2, #4] + ldr r5, [r0] + ldr r6, [r0, #4] + adds r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0] + str r8, [r0, #4] + # Sub + subs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1] + str r10, [r1, #4] + # Add + ldr r3, [r2, #8] + ldr r4, [r2, #12] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #8] + str r8, [r0, #12] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #8] + str r10, [r1, #12] + # Add + ldr r3, [r2, #16] + ldr r4, [r2, #20] + ldr r5, [r0, #16] + ldr r6, [r0, #20] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #16] + str r8, [r0, #20] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #16] + str r10, [r1, #20] + # Add + ldr r3, [r2, #24] + ldr r4, [r2, #28] + ldr r5, [r0, #24] + ldr r6, [r0, #28] + adds r12, r12, #-1 + adcs r7, r3, r5 + adc r8, r4, r6 + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + sbc r10, r4, r6 + mov r12, #-19 + asr r11, r8, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + subs r3, r3, r12 + sbcs r4, r4, r11 + str r3, [r0] + str r4, [r0, #4] + ldr r3, [r0, #8] + ldr r4, [r0, #12] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #8] + str r4, [r0, #12] + ldr r3, [r0, #16] + ldr r4, [r0, #20] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #16] + str r4, [r0, #20] + sbcs r7, r7, r11 + sbc r8, r8, lr + str r7, [r0, #24] + str r8, [r0, #28] + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r1] + ldr r4, [r1, #4] + adds r3, r3, r12 + adcs r4, r4, r11 + str r3, [r1] + str r4, [r1, #4] + ldr r3, [r1, #8] + ldr r4, [r1, #12] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #8] + str r4, [r1, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #16] + str r4, [r1, #20] + adcs r9, r9, r11 + adc r10, r10, lr + str r9, [r1, #24] + str r10, [r1, #28] + ldr r0, [sp, #8] + ldr r1, [sp, #76] + # Double + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r1, #16] + ldr r8, [r1, #20] + ldr r9, [r1, #24] + ldr r10, [r1, #28] + adds r3, r3, r3 + adcs r4, r4, r4 + adcs r5, r5, r5 + adcs r6, r6, r6 + adcs r7, r7, r7 + adcs r8, r8, r8 + adcs r9, r9, r9 + adc r10, r10, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + subs r3, r3, r12 + sbcs r4, r4, r11 + sbcs r5, r5, r11 + sbcs r6, r6, r11 + sbcs r7, r7, r11 + sbcs r8, r8, r11 + sbcs r9, r9, r11 + sbc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r0, [sp, #8] + ldr r1, [sp, #12] + # Add-Sub + # Add + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r1] + ldr r6, [r1, #4] + adds r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0] + str r8, [r0, #4] + # Sub + subs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1] + str r10, [r1, #4] + # Add + ldr r3, [r0, #8] + ldr r4, [r0, #12] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #8] + str r8, [r0, #12] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #8] + str r10, [r1, #12] + # Add + ldr r3, [r0, #16] + ldr r4, [r0, #20] + ldr r5, [r1, #16] + ldr r6, [r1, #20] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #16] + str r8, [r0, #20] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #16] + str r10, [r1, #20] + # Add + ldr r3, [r0, #24] + ldr r4, [r0, #28] + ldr r5, [r1, #24] + ldr r6, [r1, #28] + adds r12, r12, #-1 + adcs r7, r3, r5 + adc r8, r4, r6 + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + sbc r10, r4, r6 + mov r12, #-19 + asr r11, r8, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + subs r3, r3, r12 + sbcs r4, r4, r11 + str r3, [r0] + str r4, [r0, #4] + ldr r3, [r0, #8] + ldr r4, [r0, #12] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #8] + str r4, [r0, #12] + ldr r3, [r0, #16] + ldr r4, [r0, #20] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #16] + str r4, [r0, #20] + sbcs r7, r7, r11 + sbc r8, r8, lr + str r7, [r0, #24] + str r8, [r0, #28] + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r1] + ldr r4, [r1, #4] + adds r3, r3, r12 + adcs r4, r4, r11 + str r3, [r1] + str r4, [r1, #4] + ldr r3, [r1, #8] + ldr r4, [r1, #12] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #8] + str r4, [r1, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #16] + str r4, [r1, #20] + adcs r9, r9, r11 + adc r10, r10, lr + str r9, [r1, #24] + str r10, [r1, #28] + add sp, sp, #32 + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size fe_ge_madd,.-fe_ge_madd + .text + .align 2 + .globl fe_ge_msub + .type fe_ge_msub, %function +fe_ge_msub: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + sub sp, sp, #32 + str r0, [sp] + str r1, [sp, #4] + str r2, [sp, #8] + str r3, [sp, #12] + ldr r0, [sp] + ldr r1, [sp, #72] + ldr r2, [sp, #68] + # Add + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r2] + ldr r8, [r2, #4] + ldr r9, [r2, #8] + ldr r10, [r2, #12] + adds r7, r3, r7 + adcs r8, r4, r8 + adcs r9, r5, r9 + adcs r10, r6, r10 + str r7, [r0] + str r8, [r0, #4] + str r9, [r0, #8] + str r10, [r0, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + ldr r5, [r1, #24] + ldr r6, [r1, #28] + ldr r7, [r2, #16] + ldr r8, [r2, #20] + ldr r9, [r2, #24] + ldr r10, [r2, #28] + adcs r7, r3, r7 + adcs r8, r4, r8 + adcs r9, r5, r9 + adc r10, r6, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + subs r3, r3, r12 + sbcs r4, r4, r11 + sbcs r5, r5, r11 + sbcs r6, r6, r11 + sbcs r7, r7, r11 + sbcs r8, r8, r11 + sbcs r9, r9, r11 + sbc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r0, [sp, #4] + ldr r1, [sp, #72] + ldr r2, [sp, #68] + # Sub + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r2] + ldr r8, [r2, #4] + ldr r9, [r2, #8] + ldr r10, [r2, #12] + subs r7, r3, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbcs r10, r6, r10 + str r7, [r0] + str r8, [r0, #4] + str r9, [r0, #8] + str r10, [r0, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + ldr r5, [r1, #24] + ldr r6, [r1, #28] + ldr r7, [r2, #16] + ldr r8, [r2, #20] + ldr r9, [r2, #24] + ldr r10, [r2, #28] + sbcs r7, r3, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbc r10, r6, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + adds r3, r3, r12 + adcs r4, r4, r11 + adcs r5, r5, r11 + adcs r6, r6, r11 + adcs r7, r7, r11 + adcs r8, r8, r11 + adcs r9, r9, r11 + adc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r2, [sp, #92] + ldr r1, [sp] + ldr r0, [sp, #8] + bl fe_mul + ldr r2, [sp, #88] + ldr r1, [sp, #4] + ldr r0, [sp, #4] + bl fe_mul + ldr r2, [sp, #80] + ldr r1, [sp, #84] + ldr r0, [sp, #12] + bl fe_mul + ldr r0, [sp, #4] + ldr r1, [sp] + ldr r2, [sp, #8] + # Add-Sub + # Add + ldr r3, [r2] + ldr r4, [r2, #4] + ldr r5, [r0] + ldr r6, [r0, #4] + adds r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0] + str r8, [r0, #4] + # Sub + subs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1] + str r10, [r1, #4] + # Add + ldr r3, [r2, #8] + ldr r4, [r2, #12] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #8] + str r8, [r0, #12] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #8] + str r10, [r1, #12] + # Add + ldr r3, [r2, #16] + ldr r4, [r2, #20] + ldr r5, [r0, #16] + ldr r6, [r0, #20] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #16] + str r8, [r0, #20] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #16] + str r10, [r1, #20] + # Add + ldr r3, [r2, #24] + ldr r4, [r2, #28] + ldr r5, [r0, #24] + ldr r6, [r0, #28] + adds r12, r12, #-1 + adcs r7, r3, r5 + adc r8, r4, r6 + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + sbc r10, r4, r6 + mov r12, #-19 + asr r11, r8, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + subs r3, r3, r12 + sbcs r4, r4, r11 + str r3, [r0] + str r4, [r0, #4] + ldr r3, [r0, #8] + ldr r4, [r0, #12] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #8] + str r4, [r0, #12] + ldr r3, [r0, #16] + ldr r4, [r0, #20] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #16] + str r4, [r0, #20] + sbcs r7, r7, r11 + sbc r8, r8, lr + str r7, [r0, #24] + str r8, [r0, #28] + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r1] + ldr r4, [r1, #4] + adds r3, r3, r12 + adcs r4, r4, r11 + str r3, [r1] + str r4, [r1, #4] + ldr r3, [r1, #8] + ldr r4, [r1, #12] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #8] + str r4, [r1, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #16] + str r4, [r1, #20] + adcs r9, r9, r11 + adc r10, r10, lr + str r9, [r1, #24] + str r10, [r1, #28] + ldr r0, [sp, #8] + ldr r1, [sp, #76] + # Double + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r1, #16] + ldr r8, [r1, #20] + ldr r9, [r1, #24] + ldr r10, [r1, #28] + adds r3, r3, r3 + adcs r4, r4, r4 + adcs r5, r5, r5 + adcs r6, r6, r6 + adcs r7, r7, r7 + adcs r8, r8, r8 + adcs r9, r9, r9 + adc r10, r10, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + subs r3, r3, r12 + sbcs r4, r4, r11 + sbcs r5, r5, r11 + sbcs r6, r6, r11 + sbcs r7, r7, r11 + sbcs r8, r8, r11 + sbcs r9, r9, r11 + sbc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r0, [sp, #12] + ldr r1, [sp, #8] + # Add-Sub + # Add + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r0] + ldr r6, [r0, #4] + adds r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0] + str r8, [r0, #4] + # Sub + subs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1] + str r10, [r1, #4] + # Add + ldr r3, [r1, #8] + ldr r4, [r1, #12] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #8] + str r8, [r0, #12] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #8] + str r10, [r1, #12] + # Add + ldr r3, [r1, #16] + ldr r4, [r1, #20] + ldr r5, [r0, #16] + ldr r6, [r0, #20] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #16] + str r8, [r0, #20] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #16] + str r10, [r1, #20] + # Add + ldr r3, [r1, #24] + ldr r4, [r1, #28] + ldr r5, [r0, #24] + ldr r6, [r0, #28] + adds r12, r12, #-1 + adcs r7, r3, r5 + adc r8, r4, r6 + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + sbc r10, r4, r6 + mov r12, #-19 + asr r11, r8, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + subs r3, r3, r12 + sbcs r4, r4, r11 + str r3, [r0] + str r4, [r0, #4] + ldr r3, [r0, #8] + ldr r4, [r0, #12] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #8] + str r4, [r0, #12] + ldr r3, [r0, #16] + ldr r4, [r0, #20] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #16] + str r4, [r0, #20] + sbcs r7, r7, r11 + sbc r8, r8, lr + str r7, [r0, #24] + str r8, [r0, #28] + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r1] + ldr r4, [r1, #4] + adds r3, r3, r12 + adcs r4, r4, r11 + str r3, [r1] + str r4, [r1, #4] + ldr r3, [r1, #8] + ldr r4, [r1, #12] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #8] + str r4, [r1, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #16] + str r4, [r1, #20] + adcs r9, r9, r11 + adc r10, r10, lr + str r9, [r1, #24] + str r10, [r1, #28] + add sp, sp, #32 + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size fe_ge_msub,.-fe_ge_msub + .text + .align 2 + .globl fe_ge_add + .type fe_ge_add, %function +fe_ge_add: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + sub sp, sp, #0x60 + str r0, [sp] + str r1, [sp, #4] + str r2, [sp, #8] + str r3, [sp, #12] + ldr r0, [sp] + ldr r1, [sp, #136] + ldr r2, [sp, #132] + # Add + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r2] + ldr r8, [r2, #4] + ldr r9, [r2, #8] + ldr r10, [r2, #12] + adds r7, r3, r7 + adcs r8, r4, r8 + adcs r9, r5, r9 + adcs r10, r6, r10 + str r7, [r0] + str r8, [r0, #4] + str r9, [r0, #8] + str r10, [r0, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + ldr r5, [r1, #24] + ldr r6, [r1, #28] + ldr r7, [r2, #16] + ldr r8, [r2, #20] + ldr r9, [r2, #24] + ldr r10, [r2, #28] + adcs r7, r3, r7 + adcs r8, r4, r8 + adcs r9, r5, r9 + adc r10, r6, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + subs r3, r3, r12 + sbcs r4, r4, r11 + sbcs r5, r5, r11 + sbcs r6, r6, r11 + sbcs r7, r7, r11 + sbcs r8, r8, r11 + sbcs r9, r9, r11 + sbc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r0, [sp, #4] + ldr r1, [sp, #136] + ldr r2, [sp, #132] + # Sub + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r2] + ldr r8, [r2, #4] + ldr r9, [r2, #8] + ldr r10, [r2, #12] + subs r7, r3, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbcs r10, r6, r10 + str r7, [r0] + str r8, [r0, #4] + str r9, [r0, #8] + str r10, [r0, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + ldr r5, [r1, #24] + ldr r6, [r1, #28] + ldr r7, [r2, #16] + ldr r8, [r2, #20] + ldr r9, [r2, #24] + ldr r10, [r2, #28] + sbcs r7, r3, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbc r10, r6, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + adds r3, r3, r12 + adcs r4, r4, r11 + adcs r5, r5, r11 + adcs r6, r6, r11 + adcs r7, r7, r11 + adcs r8, r8, r11 + adcs r9, r9, r11 + adc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r2, [sp, #156] + ldr r1, [sp] + ldr r0, [sp, #8] + bl fe_mul + ldr r2, [sp, #160] + ldr r1, [sp, #4] + ldr r0, [sp, #4] + bl fe_mul + ldr r2, [sp, #144] + ldr r1, [sp, #152] + ldr r0, [sp, #12] + bl fe_mul + ldr r2, [sp, #148] + ldr r1, [sp, #140] + ldr r0, [sp] + bl fe_mul + add r0, sp, #16 + ldr r1, [sp] + # Double + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r1, #16] + ldr r8, [r1, #20] + ldr r9, [r1, #24] + ldr r10, [r1, #28] + adds r3, r3, r3 + adcs r4, r4, r4 + adcs r5, r5, r5 + adcs r6, r6, r6 + adcs r7, r7, r7 + adcs r8, r8, r8 + adcs r9, r9, r9 + adc r10, r10, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + subs r3, r3, r12 + sbcs r4, r4, r11 + sbcs r5, r5, r11 + sbcs r6, r6, r11 + sbcs r7, r7, r11 + sbcs r8, r8, r11 + sbcs r9, r9, r11 + sbc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r0, [sp, #4] + ldr r1, [sp] + ldr r2, [sp, #8] + # Add-Sub + # Add + ldr r3, [r2] + ldr r4, [r2, #4] + ldr r5, [r0] + ldr r6, [r0, #4] + adds r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0] + str r8, [r0, #4] + # Sub + subs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1] + str r10, [r1, #4] + # Add + ldr r3, [r2, #8] + ldr r4, [r2, #12] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #8] + str r8, [r0, #12] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #8] + str r10, [r1, #12] + # Add + ldr r3, [r2, #16] + ldr r4, [r2, #20] + ldr r5, [r0, #16] + ldr r6, [r0, #20] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #16] + str r8, [r0, #20] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #16] + str r10, [r1, #20] + # Add + ldr r3, [r2, #24] + ldr r4, [r2, #28] + ldr r5, [r0, #24] + ldr r6, [r0, #28] + adds r12, r12, #-1 + adcs r7, r3, r5 + adc r8, r4, r6 + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + sbc r10, r4, r6 + mov r12, #-19 + asr r11, r8, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + subs r3, r3, r12 + sbcs r4, r4, r11 + str r3, [r0] + str r4, [r0, #4] + ldr r3, [r0, #8] + ldr r4, [r0, #12] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #8] + str r4, [r0, #12] + ldr r3, [r0, #16] + ldr r4, [r0, #20] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #16] + str r4, [r0, #20] + sbcs r7, r7, r11 + sbc r8, r8, lr + str r7, [r0, #24] + str r8, [r0, #28] + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r1] + ldr r4, [r1, #4] + adds r3, r3, r12 + adcs r4, r4, r11 + str r3, [r1] + str r4, [r1, #4] + ldr r3, [r1, #8] + ldr r4, [r1, #12] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #8] + str r4, [r1, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #16] + str r4, [r1, #20] + adcs r9, r9, r11 + adc r10, r10, lr + str r9, [r1, #24] + str r10, [r1, #28] + ldr r0, [sp, #8] + ldr r1, [sp, #12] + add r2, sp, #16 + # Add-Sub + # Add + ldr r3, [r2] + ldr r4, [r2, #4] + ldr r5, [r1] + ldr r6, [r1, #4] + adds r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0] + str r8, [r0, #4] + # Sub + subs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1] + str r10, [r1, #4] + # Add + ldr r3, [r2, #8] + ldr r4, [r2, #12] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #8] + str r8, [r0, #12] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #8] + str r10, [r1, #12] + # Add + ldr r3, [r2, #16] + ldr r4, [r2, #20] + ldr r5, [r1, #16] + ldr r6, [r1, #20] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #16] + str r8, [r0, #20] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #16] + str r10, [r1, #20] + # Add + ldr r3, [r2, #24] + ldr r4, [r2, #28] + ldr r5, [r1, #24] + ldr r6, [r1, #28] + adds r12, r12, #-1 + adcs r7, r3, r5 + adc r8, r4, r6 + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + sbc r10, r4, r6 + mov r12, #-19 + asr r11, r8, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + subs r3, r3, r12 + sbcs r4, r4, r11 + str r3, [r0] + str r4, [r0, #4] + ldr r3, [r0, #8] + ldr r4, [r0, #12] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #8] + str r4, [r0, #12] + ldr r3, [r0, #16] + ldr r4, [r0, #20] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #16] + str r4, [r0, #20] + sbcs r7, r7, r11 + sbc r8, r8, lr + str r7, [r0, #24] + str r8, [r0, #28] + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r1] + ldr r4, [r1, #4] + adds r3, r3, r12 + adcs r4, r4, r11 + str r3, [r1] + str r4, [r1, #4] + ldr r3, [r1, #8] + ldr r4, [r1, #12] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #8] + str r4, [r1, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #16] + str r4, [r1, #20] + adcs r9, r9, r11 + adc r10, r10, lr + str r9, [r1, #24] + str r10, [r1, #28] + add sp, sp, #0x60 + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size fe_ge_add,.-fe_ge_add + .text + .align 2 + .globl fe_ge_sub + .type fe_ge_sub, %function +fe_ge_sub: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + sub sp, sp, #0x60 + str r0, [sp] + str r1, [sp, #4] + str r2, [sp, #8] + str r3, [sp, #12] + ldr r0, [sp] + ldr r1, [sp, #136] + ldr r2, [sp, #132] + # Add + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r2] + ldr r8, [r2, #4] + ldr r9, [r2, #8] + ldr r10, [r2, #12] + adds r7, r3, r7 + adcs r8, r4, r8 + adcs r9, r5, r9 + adcs r10, r6, r10 + str r7, [r0] + str r8, [r0, #4] + str r9, [r0, #8] + str r10, [r0, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + ldr r5, [r1, #24] + ldr r6, [r1, #28] + ldr r7, [r2, #16] + ldr r8, [r2, #20] + ldr r9, [r2, #24] + ldr r10, [r2, #28] + adcs r7, r3, r7 + adcs r8, r4, r8 + adcs r9, r5, r9 + adc r10, r6, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + subs r3, r3, r12 + sbcs r4, r4, r11 + sbcs r5, r5, r11 + sbcs r6, r6, r11 + sbcs r7, r7, r11 + sbcs r8, r8, r11 + sbcs r9, r9, r11 + sbc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r0, [sp, #4] + ldr r1, [sp, #136] + ldr r2, [sp, #132] + # Sub + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r2] + ldr r8, [r2, #4] + ldr r9, [r2, #8] + ldr r10, [r2, #12] + subs r7, r3, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbcs r10, r6, r10 + str r7, [r0] + str r8, [r0, #4] + str r9, [r0, #8] + str r10, [r0, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + ldr r5, [r1, #24] + ldr r6, [r1, #28] + ldr r7, [r2, #16] + ldr r8, [r2, #20] + ldr r9, [r2, #24] + ldr r10, [r2, #28] + sbcs r7, r3, r7 + sbcs r8, r4, r8 + sbcs r9, r5, r9 + sbc r10, r6, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r0] + ldr r4, [r0, #4] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + adds r3, r3, r12 + adcs r4, r4, r11 + adcs r5, r5, r11 + adcs r6, r6, r11 + adcs r7, r7, r11 + adcs r8, r8, r11 + adcs r9, r9, r11 + adc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r2, [sp, #160] + ldr r1, [sp] + ldr r0, [sp, #8] + bl fe_mul + ldr r2, [sp, #156] + ldr r1, [sp, #4] + ldr r0, [sp, #4] + bl fe_mul + ldr r2, [sp, #144] + ldr r1, [sp, #152] + ldr r0, [sp, #12] + bl fe_mul + ldr r2, [sp, #148] + ldr r1, [sp, #140] + ldr r0, [sp] + bl fe_mul + add r0, sp, #16 + ldr r1, [sp] + # Double + ldr r3, [r1] + ldr r4, [r1, #4] + ldr r5, [r1, #8] + ldr r6, [r1, #12] + ldr r7, [r1, #16] + ldr r8, [r1, #20] + ldr r9, [r1, #24] + ldr r10, [r1, #28] + adds r3, r3, r3 + adcs r4, r4, r4 + adcs r5, r5, r5 + adcs r6, r6, r6 + adcs r7, r7, r7 + adcs r8, r8, r8 + adcs r9, r9, r9 + adc r10, r10, r10 + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + subs r3, r3, r12 + sbcs r4, r4, r11 + sbcs r5, r5, r11 + sbcs r6, r6, r11 + sbcs r7, r7, r11 + sbcs r8, r8, r11 + sbcs r9, r9, r11 + sbc r10, r10, lr + str r3, [r0] + str r4, [r0, #4] + str r5, [r0, #8] + str r6, [r0, #12] + str r7, [r0, #16] + str r8, [r0, #20] + str r9, [r0, #24] + str r10, [r0, #28] + ldr r0, [sp, #4] + ldr r1, [sp] + ldr r2, [sp, #8] + # Add-Sub + # Add + ldr r3, [r2] + ldr r4, [r2, #4] + ldr r5, [r0] + ldr r6, [r0, #4] + adds r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0] + str r8, [r0, #4] + # Sub + subs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1] + str r10, [r1, #4] + # Add + ldr r3, [r2, #8] + ldr r4, [r2, #12] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #8] + str r8, [r0, #12] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #8] + str r10, [r1, #12] + # Add + ldr r3, [r2, #16] + ldr r4, [r2, #20] + ldr r5, [r0, #16] + ldr r6, [r0, #20] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #16] + str r8, [r0, #20] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #16] + str r10, [r1, #20] + # Add + ldr r3, [r2, #24] + ldr r4, [r2, #28] + ldr r5, [r0, #24] + ldr r6, [r0, #28] + adds r12, r12, #-1 + adcs r7, r3, r5 + adc r8, r4, r6 + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + sbc r10, r4, r6 + mov r12, #-19 + asr r11, r8, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + subs r3, r3, r12 + sbcs r4, r4, r11 + str r3, [r0] + str r4, [r0, #4] + ldr r3, [r0, #8] + ldr r4, [r0, #12] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #8] + str r4, [r0, #12] + ldr r3, [r0, #16] + ldr r4, [r0, #20] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #16] + str r4, [r0, #20] + sbcs r7, r7, r11 + sbc r8, r8, lr + str r7, [r0, #24] + str r8, [r0, #28] + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r1] + ldr r4, [r1, #4] + adds r3, r3, r12 + adcs r4, r4, r11 + str r3, [r1] + str r4, [r1, #4] + ldr r3, [r1, #8] + ldr r4, [r1, #12] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #8] + str r4, [r1, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #16] + str r4, [r1, #20] + adcs r9, r9, r11 + adc r10, r10, lr + str r9, [r1, #24] + str r10, [r1, #28] + ldr r0, [sp, #12] + ldr r1, [sp, #8] + add r2, sp, #16 + # Add-Sub + # Add + ldr r3, [r2] + ldr r4, [r2, #4] + ldr r5, [r0] + ldr r6, [r0, #4] + adds r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0] + str r8, [r0, #4] + # Sub + subs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1] + str r10, [r1, #4] + # Add + ldr r3, [r2, #8] + ldr r4, [r2, #12] + ldr r5, [r0, #8] + ldr r6, [r0, #12] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #8] + str r8, [r0, #12] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #8] + str r10, [r1, #12] + # Add + ldr r3, [r2, #16] + ldr r4, [r2, #20] + ldr r5, [r0, #16] + ldr r6, [r0, #20] + adds r12, r12, #-1 + adcs r7, r3, r5 + mov r12, #0 + adcs r8, r4, r6 + adc r12, r12, #0 + str r7, [r0, #16] + str r8, [r0, #20] + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + mov lr, #0 + sbcs r10, r4, r6 + adc lr, lr, #0 + str r9, [r1, #16] + str r10, [r1, #20] + # Add + ldr r3, [r2, #24] + ldr r4, [r2, #28] + ldr r5, [r0, #24] + ldr r6, [r0, #28] + adds r12, r12, #-1 + adcs r7, r3, r5 + adc r8, r4, r6 + # Sub + adds lr, lr, #-1 + sbcs r9, r3, r5 + sbc r10, r4, r6 + mov r12, #-19 + asr r11, r8, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Sub modulus (if overflow) + ldr r3, [r0] + ldr r4, [r0, #4] + subs r3, r3, r12 + sbcs r4, r4, r11 + str r3, [r0] + str r4, [r0, #4] + ldr r3, [r0, #8] + ldr r4, [r0, #12] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #8] + str r4, [r0, #12] + ldr r3, [r0, #16] + ldr r4, [r0, #20] + sbcs r3, r3, r11 + sbcs r4, r4, r11 + str r3, [r0, #16] + str r4, [r0, #20] + sbcs r7, r7, r11 + sbc r8, r8, lr + str r7, [r0, #24] + str r8, [r0, #28] + mov r12, #-19 + asr r11, r10, #31 + # Mask the modulus + and r12, r11, r12 + and lr, r11, #0x7fffffff + # Add modulus (if underflow) + ldr r3, [r1] + ldr r4, [r1, #4] + adds r3, r3, r12 + adcs r4, r4, r11 + str r3, [r1] + str r4, [r1, #4] + ldr r3, [r1, #8] + ldr r4, [r1, #12] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #8] + str r4, [r1, #12] + ldr r3, [r1, #16] + ldr r4, [r1, #20] + adcs r3, r3, r11 + adcs r4, r4, r11 + str r3, [r1, #16] + str r4, [r1, #20] + adcs r9, r9, r11 + adc r10, r10, lr + str r9, [r1, #24] + str r10, [r1, #28] + add sp, sp, #0x60 + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size fe_ge_sub,.-fe_ge_sub +#endif /* !__aarch64__ */ +#endif /* WOLFSSL_ARMASM */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-curve25519.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-curve25519.c new file mode 100644 index 000000000..f7ef3795c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-curve25519.c @@ -0,0 +1,5581 @@ +/* armv8-32-curve25519 + * + * Copyright (C) 2006-2020 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 + */ + +/* Generated using (from wolfssl): + * cd ../scripts + * ruby ./x25519/x25519.rb arm32 ../wolfssl/wolfcrypt/src/port/arm/armv8-32-curve25519.c + */ + +#ifndef __aarch64__ + +#include +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_ARMASM +#include +#include + +void fe_init() +{ + __asm__ __volatile__ ( + "\n\t" + : + : + : "memory" + ); +} + +void fe_frombytes(fe out, const unsigned char* in) +{ + __asm__ __volatile__ ( + "ldrd r2, r3, [%[in]]\n\t" + "ldrd r12, lr, [%[in], #8]\n\t" + "ldrd r4, r5, [%[in], #16]\n\t" + "ldrd r6, r7, [%[in], #24]\n\t" + "and r7, r7, #0x7fffffff\n\t" + "strd r2, r3, [%[out]]\n\t" + "strd r12, lr, [%[out], #8]\n\t" + "strd r4, r5, [%[out], #16]\n\t" + "strd r6, r7, [%[out], #24]\n\t" + : [out] "+r" (out), [in] "+r" (in) + : + : "memory", "r2", "r3", "r12", "lr", "r4", "r5", "r6", "r7" + ); +} + +void fe_tobytes(unsigned char* out, const fe n) +{ + __asm__ __volatile__ ( + "ldrd r2, r3, [%[in]]\n\t" + "ldrd r12, lr, [%[in], #8]\n\t" + "ldrd r4, r5, [%[in], #16]\n\t" + "ldrd r6, r7, [%[in], #24]\n\t" + "adds r8, r2, #19\n\t" + "adcs r8, r3, #0\n\t" + "adcs r8, r12, #0\n\t" + "adcs r8, lr, #0\n\t" + "adcs r8, r4, #0\n\t" + "adcs r8, r5, #0\n\t" + "adcs r8, r6, #0\n\t" + "adc r8, r7, #0\n\t" + "asr r8, r8, #31\n\t" + "and r8, r8, #19\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, #0\n\t" + "adcs r12, r12, #0\n\t" + "adcs lr, lr, #0\n\t" + "adcs r4, r4, #0\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adc r7, r7, #0\n\t" + "and r7, r7, #0x7fffffff\n\t" + "strd r2, r3, [%[out]]\n\t" + "strd r12, lr, [%[out], #8]\n\t" + "strd r4, r5, [%[out], #16]\n\t" + "strd r6, r7, [%[out], #24]\n\t" + : [out] "+r" (out), [n] "+r" (n) + : + : "memory", "r2", "r3", "r12", "lr", "r4", "r5", "r6", "r7", "r8" + ); +} + +void fe_1(fe n) +{ + __asm__ __volatile__ ( + /* Set one */ + "mov r2, #1\n\t" + "mov r1, #0\n\t" + "strd r2, r1, [%[n]]\n\t" + "strd r1, r1, [%[n], #8]\n\t" + "strd r1, r1, [%[n], #16]\n\t" + "strd r1, r1, [%[n], #24]\n\t" + : [n] "+r" (n) + : + : "memory", "r1", "r2" + ); +} + +void fe_0(fe n) +{ + __asm__ __volatile__ ( + /* Set zero */ + "mov r1, #0\n\t" + "strd r1, r1, [%[n]]\n\t" + "strd r1, r1, [%[n], #8]\n\t" + "strd r1, r1, [%[n], #16]\n\t" + "strd r1, r1, [%[n], #24]\n\t" + : [n] "+r" (n) + : + : "memory", "r1" + ); +} + +void fe_copy(fe r, const fe a) +{ + __asm__ __volatile__ ( + /* Copy */ + "ldrd r2, r3, [%[a]]\n\t" + "ldrd r12, lr, [%[a], #8]\n\t" + "strd r2, r3, [%[r]]\n\t" + "strd r12, lr, [%[r], #8]\n\t" + "ldrd r2, r3, [%[a], #16]\n\t" + "ldrd r12, lr, [%[a], #24]\n\t" + "strd r2, r3, [%[r], #16]\n\t" + "strd r12, lr, [%[r], #24]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : + : "memory", "r2", "r3", "r12", "lr" + ); +} + +void fe_sub(fe r, const fe a, const fe b) +{ + __asm__ __volatile__ ( + /* Sub */ + "ldrd r12, lr, [%[a]]\n\t" + "ldrd r4, r5, [%[a], #8]\n\t" + "ldrd r6, r7, [%[b]]\n\t" + "ldrd r8, r9, [%[b], #8]\n\t" + "subs r6, r12, r6\n\t" + "sbcs r7, lr, r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "strd r6, r7, [%[r]]\n\t" + "strd r8, r9, [%[r], #8]\n\t" + "ldrd r12, lr, [%[a], #16]\n\t" + "ldrd r4, r5, [%[a], #24]\n\t" + "ldrd r6, r7, [%[b], #16]\n\t" + "ldrd r8, r9, [%[b], #24]\n\t" + "sbcs r6, r12, r6\n\t" + "sbcs r7, lr, r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbc r9, r5, r9\n\t" + "mov r10, #-19\n\t" + "asr r3, r9, #31\n\t" + /* Mask the modulus */ + "and r10, r3, r10\n\t" + "and r11, r3, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd r12, lr, [%[r]]\n\t" + "ldrd r4, r5, [%[r], #8]\n\t" + "adds r12, r12, r10\n\t" + "adcs lr, lr, r3\n\t" + "adcs r4, r4, r3\n\t" + "adcs r5, r5, r3\n\t" + "adcs r6, r6, r3\n\t" + "adcs r7, r7, r3\n\t" + "adcs r8, r8, r3\n\t" + "adc r9, r9, r11\n\t" + "strd r12, lr, [%[r]]\n\t" + "strd r4, r5, [%[r], #8]\n\t" + "strd r6, r7, [%[r], #16]\n\t" + "strd r8, r9, [%[r], #24]\n\t" + : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +void fe_add(fe r, const fe a, const fe b) +{ + __asm__ __volatile__ ( + /* Add */ + "ldrd r12, lr, [%[a]]\n\t" + "ldrd r4, r5, [%[a], #8]\n\t" + "ldrd r6, r7, [%[b]]\n\t" + "ldrd r8, r9, [%[b], #8]\n\t" + "adds r6, r12, r6\n\t" + "adcs r7, lr, r7\n\t" + "adcs r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "strd r6, r7, [%[r]]\n\t" + "strd r8, r9, [%[r], #8]\n\t" + "ldrd r12, lr, [%[a], #16]\n\t" + "ldrd r4, r5, [%[a], #24]\n\t" + "ldrd r6, r7, [%[b], #16]\n\t" + "ldrd r8, r9, [%[b], #24]\n\t" + "adcs r6, r12, r6\n\t" + "adcs r7, lr, r7\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "mov r10, #-19\n\t" + "asr r3, r9, #31\n\t" + /* Mask the modulus */ + "and r10, r3, r10\n\t" + "and r11, r3, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd r12, lr, [%[r]]\n\t" + "ldrd r4, r5, [%[r], #8]\n\t" + "subs r12, r12, r10\n\t" + "sbcs lr, lr, r3\n\t" + "sbcs r4, r4, r3\n\t" + "sbcs r5, r5, r3\n\t" + "sbcs r6, r6, r3\n\t" + "sbcs r7, r7, r3\n\t" + "sbcs r8, r8, r3\n\t" + "sbc r9, r9, r11\n\t" + "strd r12, lr, [%[r]]\n\t" + "strd r4, r5, [%[r], #8]\n\t" + "strd r6, r7, [%[r], #16]\n\t" + "strd r8, r9, [%[r], #24]\n\t" + : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +void fe_neg(fe r, const fe a) +{ + __asm__ __volatile__ ( + "mov r5, #-1\n\t" + "mov r4, #-19\n\t" + "ldrd r2, r3, [%[a]]\n\t" + "ldrd r12, lr, [%[a], #8]\n\t" + "subs r2, r4, r2\n\t" + "sbcs r3, r5, r3\n\t" + "sbcs r12, r5, r12\n\t" + "sbcs lr, r5, lr\n\t" + "strd r2, r3, [%[r]]\n\t" + "strd r12, lr, [%[r], #8]\n\t" + "mov r4, #0x7fffffff\n\t" + "ldrd r2, r3, [%[a], #16]\n\t" + "ldrd r12, lr, [%[a], #24]\n\t" + "sbcs r2, r5, r2\n\t" + "sbcs r3, r5, r3\n\t" + "sbcs r12, r5, r12\n\t" + "sbc lr, r4, lr\n\t" + "strd r2, r3, [%[r], #16]\n\t" + "strd r12, lr, [%[r], #24]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : + : "memory", "r2", "r3", "r12", "lr", "r4", "r5" + ); +} + +int fe_isnonzero(const fe a) +{ + __asm__ __volatile__ ( + "ldrd r2, r3, [%[a]]\n\t" + "ldrd r12, lr, [%[a], #8]\n\t" + "ldrd r4, r5, [%[a], #16]\n\t" + "ldrd r6, r7, [%[a], #24]\n\t" + "adds r1, r2, #19\n\t" + "adcs r1, r3, #0\n\t" + "adcs r1, r12, #0\n\t" + "adcs r1, lr, #0\n\t" + "adcs r1, r4, #0\n\t" + "adcs r1, r5, #0\n\t" + "adcs r1, r6, #0\n\t" + "adc r1, r7, #0\n\t" + "asr r1, r1, #31\n\t" + "and r1, r1, #19\n\t" + "adds r2, r2, r1\n\t" + "adcs r3, r3, #0\n\t" + "adcs r12, r12, #0\n\t" + "adcs lr, lr, #0\n\t" + "adcs r4, r4, #0\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adc r7, r7, #0\n\t" + "and r7, r7, #0x7fffffff\n\t" + "orr r2, r2, r3\n\t" + "orr r12, r12, lr\n\t" + "orr r4, r4, r5\n\t" + "orr r6, r6, r7\n\t" + "orr r12, r12, r4\n\t" + "orr r2, r2, r6\n\t" + "orr %[a], r2, r12\n\t" + : [a] "+r" (a) + : + : "memory", "r1", "r2", "r3", "r12", "lr", "r4", "r5", "r6", "r7", "r8" + ); + return (uint32_t)(size_t)a; +} + +int fe_isnegative(const fe a) +{ + __asm__ __volatile__ ( + "ldrd r2, r3, [%[a]]\n\t" + "ldrd r12, lr, [%[a], #8]\n\t" + "adds r1, r2, #19\n\t" + "adcs r1, r3, #0\n\t" + "adcs r1, r12, #0\n\t" + "adcs r1, lr, #0\n\t" + "ldrd r2, r3, [%[a], #16]\n\t" + "ldrd r12, lr, [%[a], #24]\n\t" + "adcs r1, r2, #0\n\t" + "adcs r1, r3, #0\n\t" + "adcs r1, r12, #0\n\t" + "ldr r2, [%[a]]\n\t" + "adc r1, lr, #0\n\t" + "and %[a], r2, #1\n\t" + "lsr r1, r1, #31\n\t" + "eor %[a], %[a], r1\n\t" + : [a] "+r" (a) + : + : "memory", "r1", "r2", "r3", "r12", "lr" + ); + return (uint32_t)(size_t)a; +} + +void fe_cmov_table(fe* r, fe* base, signed char b) +{ + __asm__ __volatile__ ( + "sxtb %[b], %[b]\n\t" + "sbfx r7, %[b], #7, #1\n\t" + "eor r10, %[b], r7\n\t" + "sub r10, r10, r7\n\t" + "mov r3, #1\n\t" + "mov r12, #0\n\t" + "mov lr, #1\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #31\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base]]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #32]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #64]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #30\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base]]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #32]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #64]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #29\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base]]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #32]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #64]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #28\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base]]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #32]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #64]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #27\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base]]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #32]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #64]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #26\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base]]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #32]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #64]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #25\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base]]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #32]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #64]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #24\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base]]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #32]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #64]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "sub %[base], %[base], #0x2a0\n\t" + "mov r8, #-19\n\t" + "mov r9, #-1\n\t" + "subs r8, r8, r5\n\t" + "sbcs r9, r9, r6\n\t" + "sbc r11, r11, r11\n\t" + "asr r10, %[b], #31\n\t" + "eor r7, r3, lr\n\t" + "and r7, r7, r10\n\t" + "eor r3, r3, r7\n\t" + "eor lr, lr, r7\n\t" + "eor r7, r12, r4\n\t" + "and r7, r7, r10\n\t" + "eor r12, r12, r7\n\t" + "eor r4, r4, r7\n\t" + "eor r8, r8, r5\n\t" + "and r8, r8, r10\n\t" + "eor r5, r5, r8\n\t" + "eor r9, r9, r6\n\t" + "and r9, r9, r10\n\t" + "eor r6, r6, r9\n\t" + "strd r3, r12, [%[r]]\n\t" + "strd lr, r4, [%[r], #32]\n\t" + "strd r5, r6, [%[r], #64]\n\t" + "sbfx r7, %[b], #7, #1\n\t" + "eor r10, %[b], r7\n\t" + "sub r10, r10, r7\n\t" + "mov r3, #0\n\t" + "mov r12, #0\n\t" + "mov lr, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #31\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #8]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #40]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #72]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #30\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #8]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #40]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #72]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #29\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #8]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #40]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #72]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #28\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #8]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #40]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #72]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #27\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #8]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #40]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #72]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #26\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #8]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #40]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #72]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #25\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #8]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #40]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #72]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #24\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #8]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #40]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #72]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "sub %[base], %[base], #0x2a0\n\t" + "mov r8, #-1\n\t" + "mov r9, #-1\n\t" + "rsbs r11, r11, #0\n\t" + "sbcs r8, r8, r5\n\t" + "sbcs r9, r9, r6\n\t" + "sbc r11, r11, r11\n\t" + "asr r10, %[b], #31\n\t" + "eor r7, r3, lr\n\t" + "and r7, r7, r10\n\t" + "eor r3, r3, r7\n\t" + "eor lr, lr, r7\n\t" + "eor r7, r12, r4\n\t" + "and r7, r7, r10\n\t" + "eor r12, r12, r7\n\t" + "eor r4, r4, r7\n\t" + "eor r8, r8, r5\n\t" + "and r8, r8, r10\n\t" + "eor r5, r5, r8\n\t" + "eor r9, r9, r6\n\t" + "and r9, r9, r10\n\t" + "eor r6, r6, r9\n\t" + "strd r3, r12, [%[r], #8]\n\t" + "strd lr, r4, [%[r], #40]\n\t" + "strd r5, r6, [%[r], #72]\n\t" + "sbfx r7, %[b], #7, #1\n\t" + "eor r10, %[b], r7\n\t" + "sub r10, r10, r7\n\t" + "mov r3, #0\n\t" + "mov r12, #0\n\t" + "mov lr, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #31\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #16]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #48]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #80]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #30\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #16]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #48]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #80]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #29\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #16]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #48]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #80]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #28\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #16]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #48]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #80]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #27\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #16]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #48]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #80]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #26\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #16]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #48]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #80]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #25\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #16]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #48]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #80]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #24\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #16]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #48]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #80]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "sub %[base], %[base], #0x2a0\n\t" + "mov r8, #-1\n\t" + "mov r9, #-1\n\t" + "rsbs r11, r11, #0\n\t" + "sbcs r8, r8, r5\n\t" + "sbcs r9, r9, r6\n\t" + "sbc r11, r11, r11\n\t" + "asr r10, %[b], #31\n\t" + "eor r7, r3, lr\n\t" + "and r7, r7, r10\n\t" + "eor r3, r3, r7\n\t" + "eor lr, lr, r7\n\t" + "eor r7, r12, r4\n\t" + "and r7, r7, r10\n\t" + "eor r12, r12, r7\n\t" + "eor r4, r4, r7\n\t" + "eor r8, r8, r5\n\t" + "and r8, r8, r10\n\t" + "eor r5, r5, r8\n\t" + "eor r9, r9, r6\n\t" + "and r9, r9, r10\n\t" + "eor r6, r6, r9\n\t" + "strd r3, r12, [%[r], #16]\n\t" + "strd lr, r4, [%[r], #48]\n\t" + "strd r5, r6, [%[r], #80]\n\t" + "sbfx r7, %[b], #7, #1\n\t" + "eor r10, %[b], r7\n\t" + "sub r10, r10, r7\n\t" + "mov r3, #0\n\t" + "mov r12, #0\n\t" + "mov lr, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #31\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #24]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #56]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #88]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #30\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #24]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #56]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #88]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #29\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #24]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #56]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #88]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #28\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #24]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #56]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #88]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #27\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #24]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #56]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #88]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #26\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #24]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #56]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #88]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #25\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #24]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #56]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #88]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "add %[base], %[base], #0x60\n\t" + "mov r7, #0x80000000\n\t" + "ror r7, r7, #24\n\t" + "ror r7, r7, r10\n\t" + "asr r7, r7, #31\n\t" + "ldrd r8, r9, [%[base], #24]\n\t" + "eor r8, r8, r3\n\t" + "eor r9, r9, r12\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r3, r3, r8\n\t" + "eor r12, r12, r9\n\t" + "ldrd r8, r9, [%[base], #56]\n\t" + "eor r8, r8, lr\n\t" + "eor r9, r9, r4\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor lr, lr, r8\n\t" + "eor r4, r4, r9\n\t" + "ldrd r8, r9, [%[base], #88]\n\t" + "eor r8, r8, r5\n\t" + "eor r9, r9, r6\n\t" + "and r8, r8, r7\n\t" + "and r9, r9, r7\n\t" + "eor r5, r5, r8\n\t" + "eor r6, r6, r9\n\t" + "sub %[base], %[base], #0x2a0\n\t" + "mov r8, #-1\n\t" + "mov r9, #0x7fffffff\n\t" + "rsbs r11, r11, #0\n\t" + "sbcs r8, r8, r5\n\t" + "sbc r9, r9, r6\n\t" + "asr r10, %[b], #31\n\t" + "eor r7, r3, lr\n\t" + "and r7, r7, r10\n\t" + "eor r3, r3, r7\n\t" + "eor lr, lr, r7\n\t" + "eor r7, r12, r4\n\t" + "and r7, r7, r10\n\t" + "eor r12, r12, r7\n\t" + "eor r4, r4, r7\n\t" + "eor r8, r8, r5\n\t" + "and r8, r8, r10\n\t" + "eor r5, r5, r8\n\t" + "eor r9, r9, r6\n\t" + "and r9, r9, r10\n\t" + "eor r6, r6, r9\n\t" + "strd r3, r12, [%[r], #24]\n\t" + "strd lr, r4, [%[r], #56]\n\t" + "strd r5, r6, [%[r], #88]\n\t" + : [r] "+r" (r), [base] "+r" (base), [b] "+r" (b) + : + : "memory", "r3", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +void fe_mul(fe r, const fe a, const fe b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #0x40\n\t" + /* Multiply */ + "ldr r7, [%[a]]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b]]\n\t" + "ldr lr, [%[b], #4]\n\t" + /* A[0] * B[0] = 0 */ + "umull r4, r5, r7, r9\n\t" + "str r4, [sp]\n\t" + /* A[0] * B[1] = 1 */ + "umull r3, r6, r7, lr\n\t" + "adds r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[1] * B[0] = 1 */ + "umull r3, r12, r8, r9\n\t" + "adds r5, r5, r3\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #4]\n\t" + /* A[2] * B[0] = 2 */ + "ldr r10, [%[a], #8]\n\t" + "umull r3, r12, r10, r9\n\t" + "adds r6, r6, r3\n\t" + "adc r4, r4, r12\n\t" + /* A[1] * B[1] = 2 */ + "umull r3, r12, r8, lr\n\t" + "adds r6, r6, r3\n\t" + "mov r5, #0\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[0] * B[2] = 2 */ + "ldr r11, [%[b], #8]\n\t" + "umull r3, r12, r7, r11\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + "str r6, [sp, #8]\n\t" + /* A[0] * B[3] = 3 */ + "ldr r11, [%[b], #12]\n\t" + "umull r3, r12, r7, r11\n\t" + "adds r4, r4, r3\n\t" + "mov r6, #0\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[1] * B[2] = 3 */ + "ldr r11, [%[b], #8]\n\t" + "umull r3, r12, r8, r11\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[2] * B[1] = 3 */ + "umull r3, r12, r10, lr\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[3] * B[0] = 3 */ + "ldr r10, [%[a], #12]\n\t" + "umull r3, r12, r10, r9\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + "str r4, [sp, #12]\n\t" + /* A[4] * B[0] = 4 */ + "ldr r10, [%[a], #16]\n\t" + "umull r3, r12, r10, r9\n\t" + "adds r5, r5, r3\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * B[1] = 4 */ + "ldr r10, [%[a], #12]\n\t" + "umull r3, r12, r10, lr\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * B[2] = 4 */ + "ldr r10, [%[a], #8]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * B[3] = 4 */ + "ldr r11, [%[b], #12]\n\t" + "umull r3, r12, r8, r11\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[0] * B[4] = 4 */ + "ldr r11, [%[b], #16]\n\t" + "umull r3, r12, r7, r11\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #16]\n\t" + /* A[0] * B[5] = 5 */ + "ldr r11, [%[b], #20]\n\t" + "umull r3, r12, r7, r11\n\t" + "adds r6, r6, r3\n\t" + "mov r5, #0\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[1] * B[4] = 5 */ + "ldr r11, [%[b], #16]\n\t" + "umull r3, r12, r8, r11\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[2] * B[3] = 5 */ + "ldr r11, [%[b], #12]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * B[2] = 5 */ + "ldr r10, [%[a], #12]\n\t" + "ldr r11, [%[b], #8]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[4] * B[1] = 5 */ + "ldr r10, [%[a], #16]\n\t" + "umull r3, r12, r10, lr\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[5] * B[0] = 5 */ + "ldr r10, [%[a], #20]\n\t" + "umull r3, r12, r10, r9\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + "str r6, [sp, #20]\n\t" + /* A[6] * B[0] = 6 */ + "ldr r10, [%[a], #24]\n\t" + "umull r3, r12, r10, r9\n\t" + "adds r4, r4, r3\n\t" + "mov r6, #0\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[5] * B[1] = 6 */ + "ldr r10, [%[a], #20]\n\t" + "umull r3, r12, r10, lr\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[4] * B[2] = 6 */ + "ldr r10, [%[a], #16]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[3] * B[3] = 6 */ + "ldr r10, [%[a], #12]\n\t" + "ldr r11, [%[b], #12]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[2] * B[4] = 6 */ + "ldr r10, [%[a], #8]\n\t" + "ldr r11, [%[b], #16]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[1] * B[5] = 6 */ + "ldr r11, [%[b], #20]\n\t" + "umull r3, r12, r8, r11\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[0] * B[6] = 6 */ + "ldr r11, [%[b], #24]\n\t" + "umull r3, r12, r7, r11\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + "str r4, [sp, #24]\n\t" + /* A[0] * B[7] = 7 */ + "ldr r11, [%[b], #28]\n\t" + "umull r3, r12, r7, r11\n\t" + "adds r5, r5, r3\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * B[6] = 7 */ + "ldr r11, [%[b], #24]\n\t" + "umull r3, r12, r8, r11\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * B[5] = 7 */ + "ldr r11, [%[b], #20]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * B[4] = 7 */ + "ldr r10, [%[a], #12]\n\t" + "ldr r11, [%[b], #16]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[4] * B[3] = 7 */ + "ldr r10, [%[a], #16]\n\t" + "ldr r11, [%[b], #12]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * B[2] = 7 */ + "ldr r10, [%[a], #20]\n\t" + "ldr r11, [%[b], #8]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[6] * B[1] = 7 */ + "ldr r10, [%[a], #24]\n\t" + "umull r3, r12, r10, lr\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[7] * B[0] = 7 */ + "ldr r10, [%[a], #28]\n\t" + "umull r3, r12, r10, r9\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #28]\n\t" + "ldr r7, [%[a], #24]\n\t" + "ldr r9, [%[b], #24]\n\t" + /* A[7] * B[1] = 8 */ + "umull r3, r12, r10, lr\n\t" + "adds r6, r6, r3\n\t" + "mov r5, #0\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * B[2] = 8 */ + "umull r3, r12, r7, r11\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[5] * B[3] = 8 */ + "ldr r10, [%[a], #20]\n\t" + "ldr r11, [%[b], #12]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[4] * B[4] = 8 */ + "ldr r10, [%[a], #16]\n\t" + "ldr r11, [%[b], #16]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * B[5] = 8 */ + "ldr r10, [%[a], #12]\n\t" + "ldr r11, [%[b], #20]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[2] * B[6] = 8 */ + "ldr r10, [%[a], #8]\n\t" + "umull r3, r12, r10, r9\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[1] * B[7] = 8 */ + "ldr r11, [%[b], #28]\n\t" + "umull r3, r12, r8, r11\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + "str r6, [sp, #32]\n\t" + "ldr r8, [%[a], #28]\n\t" + "mov lr, r11\n\t" + /* A[2] * B[7] = 9 */ + "umull r3, r12, r10, lr\n\t" + "adds r4, r4, r3\n\t" + "mov r6, #0\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[3] * B[6] = 9 */ + "ldr r10, [%[a], #12]\n\t" + "umull r3, r12, r10, r9\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[4] * B[5] = 9 */ + "ldr r10, [%[a], #16]\n\t" + "ldr r11, [%[b], #20]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[5] * B[4] = 9 */ + "ldr r10, [%[a], #20]\n\t" + "ldr r11, [%[b], #16]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[6] * B[3] = 9 */ + "ldr r11, [%[b], #12]\n\t" + "umull r3, r12, r7, r11\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[7] * B[2] = 9 */ + "ldr r11, [%[b], #8]\n\t" + "umull r3, r12, r8, r11\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + "str r4, [sp, #36]\n\t" + /* A[7] * B[3] = 10 */ + "ldr r11, [%[b], #12]\n\t" + "umull r3, r12, r8, r11\n\t" + "adds r5, r5, r3\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[6] * B[4] = 10 */ + "ldr r11, [%[b], #16]\n\t" + "umull r3, r12, r7, r11\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * B[5] = 10 */ + "ldr r11, [%[b], #20]\n\t" + "umull r3, r12, r10, r11\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[4] * B[6] = 10 */ + "ldr r10, [%[a], #16]\n\t" + "umull r3, r12, r10, r9\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * B[7] = 10 */ + "ldr r10, [%[a], #12]\n\t" + "umull r3, r12, r10, lr\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #40]\n\t" + /* A[4] * B[7] = 11 */ + "ldr r10, [%[a], #16]\n\t" + "umull r3, r12, r10, lr\n\t" + "adds r6, r6, r3\n\t" + "mov r5, #0\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[5] * B[6] = 11 */ + "ldr r10, [%[a], #20]\n\t" + "umull r3, r12, r10, r9\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * B[5] = 11 */ + "umull r3, r12, r7, r11\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + /* A[7] * B[4] = 11 */ + "ldr r11, [%[b], #16]\n\t" + "umull r3, r12, r8, r11\n\t" + "adds r6, r6, r3\n\t" + "adcs r4, r4, r12\n\t" + "adc r5, r5, #0\n\t" + "str r6, [sp, #44]\n\t" + /* A[7] * B[5] = 12 */ + "ldr r11, [%[b], #20]\n\t" + "umull r3, r12, r8, r11\n\t" + "adds r4, r4, r3\n\t" + "mov r6, #0\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[6] * B[6] = 12 */ + "umull r3, r12, r7, r9\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + /* A[5] * B[7] = 12 */ + "umull r3, r12, r10, lr\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r12\n\t" + "adc r6, r6, #0\n\t" + "str r4, [sp, #48]\n\t" + /* A[6] * B[7] = 13 */ + "umull r3, r12, r7, lr\n\t" + "adds r5, r5, r3\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + /* A[7] * B[6] = 13 */ + "umull r3, r12, r8, r9\n\t" + "adds r5, r5, r3\n\t" + "adcs r6, r6, r12\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #52]\n\t" + /* A[7] * B[7] = 14 */ + "umull r3, r12, r8, lr\n\t" + "adds r6, r6, r3\n\t" + "adc r4, r4, r12\n\t" + "str r6, [sp, #56]\n\t" + "str r4, [sp, #60]\n\t" + /* Reduce */ + /* Load bottom half */ + "ldrd r4, r5, [sp]\n\t" + "ldrd r6, r7, [sp, #8]\n\t" + "ldrd r8, r9, [sp, #16]\n\t" + "ldrd r10, r11, [sp, #24]\n\t" + "lsr r3, r11, #31\n\t" + "and r11, r11, #0x7fffffff\n\t" + "mov lr, #19\n\t" + "ldr %[a], [sp, #32]\n\t" + "orr r3, r3, %[a], lsl #1\n\t" + "umull r3, r12, lr, r3\n\t" + "adds r4, r4, r3\n\t" + "mov %[b], #0\n\t" + "adcs r5, r5, r12\n\t" + "adc %[b], %[b], #0\n\t" + "lsr r3, %[a], #31\n\t" + "ldr %[a], [sp, #36]\n\t" + "orr r3, r3, %[a], lsl #1\n\t" + "umull r3, r12, lr, r3\n\t" + "add r12, r12, %[b]\n\t" + "adds r5, r5, r3\n\t" + "mov %[b], #0\n\t" + "adcs r6, r6, r12\n\t" + "adc %[b], %[b], #0\n\t" + "lsr r3, %[a], #31\n\t" + "ldr %[a], [sp, #40]\n\t" + "orr r3, r3, %[a], lsl #1\n\t" + "umull r3, r12, lr, r3\n\t" + "add r12, r12, %[b]\n\t" + "adds r6, r6, r3\n\t" + "mov %[b], #0\n\t" + "adcs r7, r7, r12\n\t" + "adc %[b], %[b], #0\n\t" + "lsr r3, %[a], #31\n\t" + "ldr %[a], [sp, #44]\n\t" + "orr r3, r3, %[a], lsl #1\n\t" + "umull r3, r12, lr, r3\n\t" + "add r12, r12, %[b]\n\t" + "adds r7, r7, r3\n\t" + "mov %[b], #0\n\t" + "adcs r8, r8, r12\n\t" + "adc %[b], %[b], #0\n\t" + "lsr r3, %[a], #31\n\t" + "ldr %[a], [sp, #48]\n\t" + "orr r3, r3, %[a], lsl #1\n\t" + "umull r3, r12, lr, r3\n\t" + "add r12, r12, %[b]\n\t" + "adds r8, r8, r3\n\t" + "mov %[b], #0\n\t" + "adcs r9, r9, r12\n\t" + "adc %[b], %[b], #0\n\t" + "lsr r3, %[a], #31\n\t" + "ldr %[a], [sp, #52]\n\t" + "orr r3, r3, %[a], lsl #1\n\t" + "umull r3, r12, lr, r3\n\t" + "add r12, r12, %[b]\n\t" + "adds r9, r9, r3\n\t" + "mov %[b], #0\n\t" + "adcs r10, r10, r12\n\t" + "adc %[b], %[b], #0\n\t" + "lsr r3, %[a], #31\n\t" + "ldr %[a], [sp, #56]\n\t" + "orr r3, r3, %[a], lsl #1\n\t" + "umull r3, r12, lr, r3\n\t" + "add r12, r12, %[b]\n\t" + "adds r10, r10, r3\n\t" + "mov %[b], #0\n\t" + "adcs r11, r11, r12\n\t" + "adc %[b], %[b], #0\n\t" + "lsr r3, %[a], #31\n\t" + "ldr %[a], [sp, #60]\n\t" + "orr r3, r3, %[a], lsl #1\n\t" + "umull r3, r12, lr, r3\n\t" + "adds r11, r11, r3\n\t" + "adc r3, r12, %[b]\n\t" + /* Overflow */ + "lsl r3, r3, #1\n\t" + "orr r3, r3, r11, lsr #31\n\t" + "mul r3, r3, lr\n\t" + "and r11, r11, #0x7fffffff\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adcs r7, r7, #0\n\t" + "adcs r8, r8, #0\n\t" + "adcs r9, r9, #0\n\t" + "adcs r10, r10, #0\n\t" + "adc r11, r11, #0\n\t" + /* Reduce if top bit set */ + "asr r3, r11, #31\n\t" + "and r3, r3, lr\n\t" + "and r11, r11, #0x7fffffff\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adcs r7, r7, #0\n\t" + "adcs r8, r8, #0\n\t" + "adcs r9, r9, #0\n\t" + "adcs r10, r10, #0\n\t" + "adc r11, r11, #0\n\t" + /* Store */ + "strd r4, r5, [%[r]]\n\t" + "strd r6, r7, [%[r], #8]\n\t" + "strd r8, r9, [%[r], #16]\n\t" + "strd r10, r11, [%[r], #24]\n\t" + "add sp, sp, #0x40\n\t" + : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +void fe_sq(fe r, const fe a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #0x40\n\t" + /* Square */ + "ldr r7, [%[a]]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[a], #8]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r12, [%[a], #16]\n\t" + /* A[0] * A[0] = 0 */ + "umull r4, r5, r7, r7\n\t" + "str r4, [sp]\n\t" + /* A[0] * A[1] = 1 */ + "umull r2, r3, r7, r8\n\t" + "mov r6, #0\n\t" + "adds r5, r5, r2\n\t" + "adc r6, r6, r3\n\t" + "adds r5, r5, r2\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #4]\n\t" + /* A[1] * A[1] = 2 */ + "umull r2, r3, r8, r8\n\t" + "adds r6, r6, r2\n\t" + "adc r4, r4, r3\n\t" + /* A[0] * A[2] = 2 */ + "umull r2, r3, r7, r9\n\t" + "adds r6, r6, r2\n\t" + "mov r5, #0\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "str r6, [sp, #8]\n\t" + /* A[0] * A[3] = 3 */ + "umull r2, r3, r7, r10\n\t" + "adds r4, r4, r2\n\t" + "adc r5, r5, r3\n\t" + "adds r4, r4, r2\n\t" + "mov r6, #0\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[1] * A[2] = 3 */ + "umull r2, r3, r8, r9\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "str r4, [sp, #12]\n\t" + /* A[2] * A[2] = 4 */ + "umull r2, r3, r9, r9\n\t" + "adds r5, r5, r2\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * A[3] = 4 */ + "umull r2, r3, r8, r10\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[0] * A[4] = 4 */ + "umull r2, r3, r7, r12\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #16]\n\t" + /* A[0] * A[5] = 5 */ + "ldr r11, [%[a], #20]\n\t" + "umull r2, r3, r7, r11\n\t" + "adds r6, r6, r2\n\t" + "mov r5, #0\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + /* A[1] * A[4] = 5 */ + "umull r2, r3, r8, r12\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + /* A[2] * A[3] = 5 */ + "umull r2, r3, r9, r10\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "str r6, [sp, #20]\n\t" + /* A[3] * A[3] = 6 */ + "umull r2, r3, r10, r10\n\t" + "adds r4, r4, r2\n\t" + "mov r6, #0\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[2] * A[4] = 6 */ + "umull r2, r3, r9, r12\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[1] * A[5] = 6 */ + "umull r2, r3, r8, r11\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[0] * A[6] = 6 */ + "ldr r11, [%[a], #24]\n\t" + "umull r2, r3, r7, r11\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "str r4, [sp, #24]\n\t" + /* A[0] * A[7] = 7 */ + "ldr r11, [%[a], #28]\n\t" + "umull r2, r3, r7, r11\n\t" + "adds r5, r5, r2\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * A[6] = 7 */ + "ldr r11, [%[a], #24]\n\t" + "umull r2, r3, r8, r11\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * A[5] = 7 */ + "ldr r11, [%[a], #20]\n\t" + "umull r2, r3, r9, r11\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * A[4] = 7 */ + "umull r2, r3, r10, r12\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #28]\n\t" + /* A[4] * A[4] = 8 */ + "umull r2, r3, r12, r12\n\t" + "adds r6, r6, r2\n\t" + "mov r5, #0\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * A[5] = 8 */ + "umull r2, r3, r10, r11\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + /* A[2] * A[6] = 8 */ + "ldr r11, [%[a], #24]\n\t" + "umull r2, r3, r9, r11\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + /* A[1] * A[7] = 8 */ + "ldr r11, [%[a], #28]\n\t" + "umull r2, r3, r8, r11\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "str r6, [sp, #32]\n\t" + "ldr r7, [%[a], #20]\n\t" + /* A[2] * A[7] = 9 */ + "umull r2, r3, r9, r11\n\t" + "adds r4, r4, r2\n\t" + "mov r6, #0\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[3] * A[6] = 9 */ + "ldr r11, [%[a], #24]\n\t" + "umull r2, r3, r10, r11\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[4] * A[5] = 9 */ + "umull r2, r3, r12, r7\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "str r4, [sp, #36]\n\t" + "mov r8, r11\n\t" + /* A[5] * A[5] = 10 */ + "umull r2, r3, r7, r7\n\t" + "adds r5, r5, r2\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[4] * A[6] = 10 */ + "umull r2, r3, r12, r8\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * A[7] = 10 */ + "ldr r11, [%[a], #28]\n\t" + "umull r2, r3, r10, r11\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #40]\n\t" + "mov r9, r11\n\t" + /* A[4] * A[7] = 11 */ + "umull r2, r3, r12, r9\n\t" + "adds r6, r6, r2\n\t" + "mov r5, #0\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + /* A[5] * A[6] = 11 */ + "umull r2, r3, r7, r8\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "str r6, [sp, #44]\n\t" + /* A[6] * A[6] = 12 */ + "umull r2, r3, r8, r8\n\t" + "adds r4, r4, r2\n\t" + "mov r6, #0\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[5] * A[7] = 12 */ + "umull r2, r3, r7, r9\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "str r4, [sp, #48]\n\t" + /* A[6] * A[7] = 13 */ + "umull r2, r3, r8, r9\n\t" + "adds r5, r5, r2\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #52]\n\t" + /* A[7] * A[7] = 14 */ + "umull r2, r3, r9, r9\n\t" + "adds r6, r6, r2\n\t" + "adc r4, r4, r3\n\t" + "str r6, [sp, #56]\n\t" + "str r4, [sp, #60]\n\t" + /* Reduce */ + /* Load bottom half */ + "ldrd r4, r5, [sp]\n\t" + "ldrd r6, r7, [sp, #8]\n\t" + "ldrd r8, r9, [sp, #16]\n\t" + "ldrd r10, r11, [sp, #24]\n\t" + "lsr r2, r11, #31\n\t" + "and r11, r11, #0x7fffffff\n\t" + "mov r12, #19\n\t" + "ldr %[a], [sp, #32]\n\t" + "orr r2, r2, %[a], lsl #1\n\t" + "umull r2, r3, r12, r2\n\t" + "adds r4, r4, r2\n\t" + "mov lr, #0\n\t" + "adcs r5, r5, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #31\n\t" + "ldr %[a], [sp, #36]\n\t" + "orr r2, r2, %[a], lsl #1\n\t" + "umull r2, r3, r12, r2\n\t" + "add r3, r3, lr\n\t" + "adds r5, r5, r2\n\t" + "mov lr, #0\n\t" + "adcs r6, r6, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #31\n\t" + "ldr %[a], [sp, #40]\n\t" + "orr r2, r2, %[a], lsl #1\n\t" + "umull r2, r3, r12, r2\n\t" + "add r3, r3, lr\n\t" + "adds r6, r6, r2\n\t" + "mov lr, #0\n\t" + "adcs r7, r7, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #31\n\t" + "ldr %[a], [sp, #44]\n\t" + "orr r2, r2, %[a], lsl #1\n\t" + "umull r2, r3, r12, r2\n\t" + "add r3, r3, lr\n\t" + "adds r7, r7, r2\n\t" + "mov lr, #0\n\t" + "adcs r8, r8, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #31\n\t" + "ldr %[a], [sp, #48]\n\t" + "orr r2, r2, %[a], lsl #1\n\t" + "umull r2, r3, r12, r2\n\t" + "add r3, r3, lr\n\t" + "adds r8, r8, r2\n\t" + "mov lr, #0\n\t" + "adcs r9, r9, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #31\n\t" + "ldr %[a], [sp, #52]\n\t" + "orr r2, r2, %[a], lsl #1\n\t" + "umull r2, r3, r12, r2\n\t" + "add r3, r3, lr\n\t" + "adds r9, r9, r2\n\t" + "mov lr, #0\n\t" + "adcs r10, r10, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #31\n\t" + "ldr %[a], [sp, #56]\n\t" + "orr r2, r2, %[a], lsl #1\n\t" + "umull r2, r3, r12, r2\n\t" + "add r3, r3, lr\n\t" + "adds r10, r10, r2\n\t" + "mov lr, #0\n\t" + "adcs r11, r11, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #31\n\t" + "ldr %[a], [sp, #60]\n\t" + "orr r2, r2, %[a], lsl #1\n\t" + "umull r2, r3, r12, r2\n\t" + "adds r11, r11, r2\n\t" + "adc r2, r3, lr\n\t" + /* Overflow */ + "lsl r2, r2, #1\n\t" + "orr r2, r2, r11, lsr #31\n\t" + "mul r2, r2, r12\n\t" + "and r11, r11, #0x7fffffff\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adcs r7, r7, #0\n\t" + "adcs r8, r8, #0\n\t" + "adcs r9, r9, #0\n\t" + "adcs r10, r10, #0\n\t" + "adc r11, r11, #0\n\t" + /* Reduce if top bit set */ + "asr r2, r11, #31\n\t" + "and r2, r2, r12\n\t" + "and r11, r11, #0x7fffffff\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adcs r7, r7, #0\n\t" + "adcs r8, r8, #0\n\t" + "adcs r9, r9, #0\n\t" + "adcs r10, r10, #0\n\t" + "adc r11, r11, #0\n\t" + /* Store */ + "strd r4, r5, [%[r]]\n\t" + "strd r6, r7, [%[r], #8]\n\t" + "strd r8, r9, [%[r], #16]\n\t" + "strd r10, r11, [%[r], #24]\n\t" + "add sp, sp, #0x40\n\t" + : [r] "+r" (r), [a] "+r" (a) + : + : "memory", "r2", "r3", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +void fe_mul121666(fe r, fe a) +{ + __asm__ __volatile__ ( + /* Multiply by 121666 */ + "ldrd r2, r3, [%[a]]\n\t" + "ldrd r4, r5, [%[a], #8]\n\t" + "ldrd r6, r7, [%[a], #16]\n\t" + "ldrd r8, r9, [%[a], #24]\n\t" + "movw lr, #0xdb42\n\t" + "movt lr, #1\n\t" + "umull r2, r10, r2, lr\n\t" + "umull r3, r12, r3, lr\n\t" + "adds r3, r3, r10\n\t" + "adc r10, r12, #0\n\t" + "umull r4, r12, r4, lr\n\t" + "adds r4, r4, r10\n\t" + "adc r10, r12, #0\n\t" + "umull r5, r12, r5, lr\n\t" + "adds r5, r5, r10\n\t" + "adc r10, r12, #0\n\t" + "umull r6, r12, r6, lr\n\t" + "adds r6, r6, r10\n\t" + "adc r10, r12, #0\n\t" + "umull r7, r12, r7, lr\n\t" + "adds r7, r7, r10\n\t" + "adc r10, r12, #0\n\t" + "umull r8, r12, r8, lr\n\t" + "adds r8, r8, r10\n\t" + "adc r10, r12, #0\n\t" + "umull r9, r12, r9, lr\n\t" + "adds r9, r9, r10\n\t" + "adc r10, r12, #0\n\t" + "mov lr, #19\n\t" + "lsl r10, r10, #1\n\t" + "orr r10, r10, r9, lsr #31\n\t" + "mul r10, r10, lr\n\t" + "and r9, r9, #0x7fffffff\n\t" + "adds r2, r2, r10\n\t" + "adcs r3, r3, #0\n\t" + "adcs r4, r4, #0\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adcs r7, r7, #0\n\t" + "adcs r8, r8, #0\n\t" + "adc r9, r9, #0\n\t" + "strd r2, r3, [%[r]]\n\t" + "strd r4, r5, [%[r], #8]\n\t" + "strd r6, r7, [%[r], #16]\n\t" + "strd r8, r9, [%[r], #24]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : + : "memory", "r2", "r3", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +} + +void fe_sq2(fe r, const fe a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #0x40\n\t" + /* Square * 2 */ + "ldr r7, [%[a]]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[a], #8]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r12, [%[a], #16]\n\t" + /* A[0] * A[0] = 0 */ + "umull r4, r5, r7, r7\n\t" + "str r4, [sp]\n\t" + /* A[0] * A[1] = 1 */ + "umull r2, r3, r7, r8\n\t" + "mov r6, #0\n\t" + "adds r5, r5, r2\n\t" + "adc r6, r6, r3\n\t" + "adds r5, r5, r2\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #4]\n\t" + /* A[1] * A[1] = 2 */ + "umull r2, r3, r8, r8\n\t" + "adds r6, r6, r2\n\t" + "adc r4, r4, r3\n\t" + /* A[0] * A[2] = 2 */ + "umull r2, r3, r7, r9\n\t" + "adds r6, r6, r2\n\t" + "mov r5, #0\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "str r6, [sp, #8]\n\t" + /* A[0] * A[3] = 3 */ + "umull r2, r3, r7, r10\n\t" + "adds r4, r4, r2\n\t" + "adc r5, r5, r3\n\t" + "adds r4, r4, r2\n\t" + "mov r6, #0\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[1] * A[2] = 3 */ + "umull r2, r3, r8, r9\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "str r4, [sp, #12]\n\t" + /* A[2] * A[2] = 4 */ + "umull r2, r3, r9, r9\n\t" + "adds r5, r5, r2\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * A[3] = 4 */ + "umull r2, r3, r8, r10\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[0] * A[4] = 4 */ + "umull r2, r3, r7, r12\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #16]\n\t" + /* A[0] * A[5] = 5 */ + "ldr r11, [%[a], #20]\n\t" + "umull r2, r3, r7, r11\n\t" + "adds r6, r6, r2\n\t" + "mov r5, #0\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + /* A[1] * A[4] = 5 */ + "umull r2, r3, r8, r12\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + /* A[2] * A[3] = 5 */ + "umull r2, r3, r9, r10\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "str r6, [sp, #20]\n\t" + /* A[3] * A[3] = 6 */ + "umull r2, r3, r10, r10\n\t" + "adds r4, r4, r2\n\t" + "mov r6, #0\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[2] * A[4] = 6 */ + "umull r2, r3, r9, r12\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[1] * A[5] = 6 */ + "umull r2, r3, r8, r11\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[0] * A[6] = 6 */ + "ldr r11, [%[a], #24]\n\t" + "umull r2, r3, r7, r11\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "str r4, [sp, #24]\n\t" + /* A[0] * A[7] = 7 */ + "ldr r11, [%[a], #28]\n\t" + "umull r2, r3, r7, r11\n\t" + "adds r5, r5, r2\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * A[6] = 7 */ + "ldr r11, [%[a], #24]\n\t" + "umull r2, r3, r8, r11\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * A[5] = 7 */ + "ldr r11, [%[a], #20]\n\t" + "umull r2, r3, r9, r11\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * A[4] = 7 */ + "umull r2, r3, r10, r12\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #28]\n\t" + /* A[4] * A[4] = 8 */ + "umull r2, r3, r12, r12\n\t" + "adds r6, r6, r2\n\t" + "mov r5, #0\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * A[5] = 8 */ + "umull r2, r3, r10, r11\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + /* A[2] * A[6] = 8 */ + "ldr r11, [%[a], #24]\n\t" + "umull r2, r3, r9, r11\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + /* A[1] * A[7] = 8 */ + "ldr r11, [%[a], #28]\n\t" + "umull r2, r3, r8, r11\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "str r6, [sp, #32]\n\t" + "ldr r7, [%[a], #20]\n\t" + /* A[2] * A[7] = 9 */ + "umull r2, r3, r9, r11\n\t" + "adds r4, r4, r2\n\t" + "mov r6, #0\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[3] * A[6] = 9 */ + "ldr r11, [%[a], #24]\n\t" + "umull r2, r3, r10, r11\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[4] * A[5] = 9 */ + "umull r2, r3, r12, r7\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "str r4, [sp, #36]\n\t" + "mov r8, r11\n\t" + /* A[5] * A[5] = 10 */ + "umull r2, r3, r7, r7\n\t" + "adds r5, r5, r2\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[4] * A[6] = 10 */ + "umull r2, r3, r12, r8\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * A[7] = 10 */ + "ldr r11, [%[a], #28]\n\t" + "umull r2, r3, r10, r11\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #40]\n\t" + "mov r9, r11\n\t" + /* A[4] * A[7] = 11 */ + "umull r2, r3, r12, r9\n\t" + "adds r6, r6, r2\n\t" + "mov r5, #0\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + /* A[5] * A[6] = 11 */ + "umull r2, r3, r7, r8\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "adds r6, r6, r2\n\t" + "adcs r4, r4, r3\n\t" + "adc r5, r5, #0\n\t" + "str r6, [sp, #44]\n\t" + /* A[6] * A[6] = 12 */ + "umull r2, r3, r8, r8\n\t" + "adds r4, r4, r2\n\t" + "mov r6, #0\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + /* A[5] * A[7] = 12 */ + "umull r2, r3, r7, r9\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, r3\n\t" + "adc r6, r6, #0\n\t" + "str r4, [sp, #48]\n\t" + /* A[6] * A[7] = 13 */ + "umull r2, r3, r8, r9\n\t" + "adds r5, r5, r2\n\t" + "mov r4, #0\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r2\n\t" + "adcs r6, r6, r3\n\t" + "adc r4, r4, #0\n\t" + "str r5, [sp, #52]\n\t" + /* A[7] * A[7] = 14 */ + "umull r2, r3, r9, r9\n\t" + "adds r6, r6, r2\n\t" + "adc r4, r4, r3\n\t" + "str r6, [sp, #56]\n\t" + "str r4, [sp, #60]\n\t" + /* Double and Reduce */ + /* Load bottom half */ + "ldrd r4, r5, [sp]\n\t" + "ldrd r6, r7, [sp, #8]\n\t" + "ldrd r8, r9, [sp, #16]\n\t" + "ldrd r10, r11, [sp, #24]\n\t" + "lsr r2, r11, #30\n\t" + "lsl r11, r11, #1\n\t" + "orr r11, r11, r10, lsr #31\n\t" + "lsl r10, r10, #1\n\t" + "orr r10, r10, r9, lsr #31\n\t" + "lsl r9, r9, #1\n\t" + "orr r9, r9, r8, lsr #31\n\t" + "lsl r8, r8, #1\n\t" + "orr r8, r8, r7, lsr #31\n\t" + "lsl r7, r7, #1\n\t" + "orr r7, r7, r6, lsr #31\n\t" + "lsl r6, r6, #1\n\t" + "orr r6, r6, r5, lsr #31\n\t" + "lsl r5, r5, #1\n\t" + "orr r5, r5, r4, lsr #31\n\t" + "lsl r4, r4, #1\n\t" + "and r11, r11, #0x7fffffff\n\t" + "mov r12, #19\n\t" + "ldr %[a], [sp, #32]\n\t" + "orr r2, r2, %[a], lsl #2\n\t" + "umull r2, r3, r12, r2\n\t" + "adds r4, r4, r2\n\t" + "mov lr, #0\n\t" + "adcs r5, r5, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #30\n\t" + "ldr %[a], [sp, #36]\n\t" + "orr r2, r2, %[a], lsl #2\n\t" + "umull r2, r3, r12, r2\n\t" + "add r3, r3, lr\n\t" + "adds r5, r5, r2\n\t" + "mov lr, #0\n\t" + "adcs r6, r6, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #30\n\t" + "ldr %[a], [sp, #40]\n\t" + "orr r2, r2, %[a], lsl #2\n\t" + "umull r2, r3, r12, r2\n\t" + "add r3, r3, lr\n\t" + "adds r6, r6, r2\n\t" + "mov lr, #0\n\t" + "adcs r7, r7, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #30\n\t" + "ldr %[a], [sp, #44]\n\t" + "orr r2, r2, %[a], lsl #2\n\t" + "umull r2, r3, r12, r2\n\t" + "add r3, r3, lr\n\t" + "adds r7, r7, r2\n\t" + "mov lr, #0\n\t" + "adcs r8, r8, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #30\n\t" + "ldr %[a], [sp, #48]\n\t" + "orr r2, r2, %[a], lsl #2\n\t" + "umull r2, r3, r12, r2\n\t" + "add r3, r3, lr\n\t" + "adds r8, r8, r2\n\t" + "mov lr, #0\n\t" + "adcs r9, r9, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #30\n\t" + "ldr %[a], [sp, #52]\n\t" + "orr r2, r2, %[a], lsl #2\n\t" + "umull r2, r3, r12, r2\n\t" + "add r3, r3, lr\n\t" + "adds r9, r9, r2\n\t" + "mov lr, #0\n\t" + "adcs r10, r10, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #30\n\t" + "ldr %[a], [sp, #56]\n\t" + "orr r2, r2, %[a], lsl #2\n\t" + "umull r2, r3, r12, r2\n\t" + "add r3, r3, lr\n\t" + "adds r10, r10, r2\n\t" + "mov lr, #0\n\t" + "adcs r11, r11, r3\n\t" + "adc lr, lr, #0\n\t" + "lsr r2, %[a], #30\n\t" + "ldr %[a], [sp, #60]\n\t" + "orr r2, r2, %[a], lsl #2\n\t" + "umull r2, r3, r12, r2\n\t" + "adds r11, r11, r2\n\t" + "adc r2, r3, lr\n\t" + /* Overflow */ + "lsl r2, r2, #1\n\t" + "orr r2, r2, r11, lsr #31\n\t" + "mul r2, r2, r12\n\t" + "and r11, r11, #0x7fffffff\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adcs r7, r7, #0\n\t" + "adcs r8, r8, #0\n\t" + "adcs r9, r9, #0\n\t" + "adcs r10, r10, #0\n\t" + "adc r11, r11, #0\n\t" + /* Reduce if top bit set */ + "asr r2, r11, #31\n\t" + "and r2, r2, r12\n\t" + "and r11, r11, #0x7fffffff\n\t" + "adds r4, r4, r2\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adcs r7, r7, #0\n\t" + "adcs r8, r8, #0\n\t" + "adcs r9, r9, #0\n\t" + "adcs r10, r10, #0\n\t" + "adc r11, r11, #0\n\t" + /* Store */ + "strd r4, r5, [%[r]]\n\t" + "strd r6, r7, [%[r], #8]\n\t" + "strd r8, r9, [%[r], #16]\n\t" + "strd r10, r11, [%[r], #24]\n\t" + "add sp, sp, #0x40\n\t" + : [r] "+r" (r), [a] "+r" (a) + : + : "memory", "r2", "r3", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +void fe_invert(fe r, const fe a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #0x88\n\t" + /* Invert */ + "str %[r], [sp, #128]\n\t" + "str %[a], [sp, #132]\n\t" + "mov r0, sp\n\t" + "ldr r1, [sp, #132]\n\t" + "bl fe_sq\n\t" + "add r0, sp, #32\n\t" + "mov r1, sp\n\t" + "bl fe_sq\n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "add r0, sp, #32\n\t" + "ldr r1, [sp, #132]\n\t" + "add r2, sp, #32\n\t" + "bl fe_mul\n\t" + "mov r0, sp\n\t" + "mov r1, sp\n\t" + "add r2, sp, #32\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x40\n\t" + "mov r1, sp\n\t" + "bl fe_sq\n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #32\n\t" + "add r2, sp, #0x40\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "mov r4, #4\n\t" + "\n" + "L_fe_invert1_%=: \n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_invert1_%=\n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #0x40\n\t" + "add r2, sp, #32\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "mov r4, #9\n\t" + "\n" + "L_fe_invert2_%=: \n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_invert2_%=\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x40\n\t" + "add r2, sp, #32\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "mov r4, #19\n\t" + "\n" + "L_fe_invert3_%=: \n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x60\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_invert3_%=\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x60\n\t" + "add r2, sp, #0x40\n\t" + "bl fe_mul\n\t" + "mov r4, #10\n\t" + "\n" + "L_fe_invert4_%=: \n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_invert4_%=\n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #0x40\n\t" + "add r2, sp, #32\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "mov r4, #49\n\t" + "\n" + "L_fe_invert5_%=: \n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_invert5_%=\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x40\n\t" + "add r2, sp, #32\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "mov r4, #0x63\n\t" + "\n" + "L_fe_invert6_%=: \n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x60\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_invert6_%=\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x60\n\t" + "add r2, sp, #0x40\n\t" + "bl fe_mul\n\t" + "mov r4, #50\n\t" + "\n" + "L_fe_invert7_%=: \n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_invert7_%=\n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #0x40\n\t" + "add r2, sp, #32\n\t" + "bl fe_mul\n\t" + "mov r4, #5\n\t" + "\n" + "L_fe_invert8_%=: \n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_invert8_%=\n\t" + "ldr r0, [sp, #128]\n\t" + "add r1, sp, #32\n\t" + "mov r2, sp\n\t" + "bl fe_mul\n\t" + "ldr %[a], [sp, #132]\n\t" + "ldr %[r], [sp, #128]\n\t" + "add sp, sp, #0x88\n\t" + : [r] "+r" (r), [a] "+r" (a) + : + : "memory", "lr", "r4" + ); +} + +int curve25519(byte* r, byte* n, byte* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #0xbc\n\t" + "str %[r], [sp, #160]\n\t" + "str %[n], [sp, #164]\n\t" + "str %[a], [sp, #168]\n\t" + "mov %[n], #0\n\t" + "str %[n], [sp, #172]\n\t" + /* Set one */ + "mov r11, #1\n\t" + "mov r10, #0\n\t" + "strd r11, r10, [%[r]]\n\t" + "strd r10, r10, [%[r], #8]\n\t" + "strd r10, r10, [%[r], #16]\n\t" + "strd r10, r10, [%[r], #24]\n\t" + /* Set zero */ + "mov r10, #0\n\t" + "strd r10, r10, [sp]\n\t" + "strd r10, r10, [sp, #8]\n\t" + "strd r10, r10, [sp, #16]\n\t" + "strd r10, r10, [sp, #24]\n\t" + /* Set one */ + "mov r11, #1\n\t" + "mov r10, #0\n\t" + "strd r11, r10, [sp, #32]\n\t" + "strd r10, r10, [sp, #40]\n\t" + "strd r10, r10, [sp, #48]\n\t" + "strd r10, r10, [sp, #56]\n\t" + /* Copy */ + "ldrd r4, r5, [%[a]]\n\t" + "ldrd r6, r7, [%[a], #8]\n\t" + "strd r4, r5, [sp, #64]\n\t" + "strd r6, r7, [sp, #72]\n\t" + "ldrd r4, r5, [%[a], #16]\n\t" + "ldrd r6, r7, [%[a], #24]\n\t" + "strd r4, r5, [sp, #80]\n\t" + "strd r6, r7, [sp, #88]\n\t" + "mov %[n], #30\n\t" + "str %[n], [sp, #180]\n\t" + "mov %[a], #28\n\t" + "str %[a], [sp, #176]\n\t" + "\n" + "L_curve25519_words_%=: \n\t" + "\n" + "L_curve25519_bits_%=: \n\t" + "ldr %[n], [sp, #164]\n\t" + "ldr %[a], [%[n], r2]\n\t" + "ldr %[n], [sp, #180]\n\t" + "lsr %[a], %[a], %[n]\n\t" + "and %[a], %[a], #1\n\t" + "str %[a], [sp, #184]\n\t" + "ldr %[n], [sp, #172]\n\t" + "eor %[n], %[n], %[a]\n\t" + "str %[n], [sp, #172]\n\t" + "ldr %[r], [sp, #160]\n\t" + /* Conditional Swap */ + "neg %[n], %[n]\n\t" + "ldrd r4, r5, [%[r]]\n\t" + "ldrd r6, r7, [sp, #64]\n\t" + "eor r8, r4, r6\n\t" + "eor r9, r5, r7\n\t" + "and r8, r8, %[n]\n\t" + "and r9, r9, %[n]\n\t" + "eor r4, r4, r8\n\t" + "eor r5, r5, r9\n\t" + "eor r6, r6, r8\n\t" + "eor r7, r7, r9\n\t" + "strd r4, r5, [%[r]]\n\t" + "strd r6, r7, [sp, #64]\n\t" + "ldrd r4, r5, [%[r], #8]\n\t" + "ldrd r6, r7, [sp, #72]\n\t" + "eor r8, r4, r6\n\t" + "eor r9, r5, r7\n\t" + "and r8, r8, %[n]\n\t" + "and r9, r9, %[n]\n\t" + "eor r4, r4, r8\n\t" + "eor r5, r5, r9\n\t" + "eor r6, r6, r8\n\t" + "eor r7, r7, r9\n\t" + "strd r4, r5, [%[r], #8]\n\t" + "strd r6, r7, [sp, #72]\n\t" + "ldrd r4, r5, [%[r], #16]\n\t" + "ldrd r6, r7, [sp, #80]\n\t" + "eor r8, r4, r6\n\t" + "eor r9, r5, r7\n\t" + "and r8, r8, %[n]\n\t" + "and r9, r9, %[n]\n\t" + "eor r4, r4, r8\n\t" + "eor r5, r5, r9\n\t" + "eor r6, r6, r8\n\t" + "eor r7, r7, r9\n\t" + "strd r4, r5, [%[r], #16]\n\t" + "strd r6, r7, [sp, #80]\n\t" + "ldrd r4, r5, [%[r], #24]\n\t" + "ldrd r6, r7, [sp, #88]\n\t" + "eor r8, r4, r6\n\t" + "eor r9, r5, r7\n\t" + "and r8, r8, %[n]\n\t" + "and r9, r9, %[n]\n\t" + "eor r4, r4, r8\n\t" + "eor r5, r5, r9\n\t" + "eor r6, r6, r8\n\t" + "eor r7, r7, r9\n\t" + "strd r4, r5, [%[r], #24]\n\t" + "strd r6, r7, [sp, #88]\n\t" + "ldr %[n], [sp, #172]\n\t" + /* Conditional Swap */ + "neg %[n], %[n]\n\t" + "ldrd r4, r5, [sp]\n\t" + "ldrd r6, r7, [sp, #32]\n\t" + "eor r8, r4, r6\n\t" + "eor r9, r5, r7\n\t" + "and r8, r8, %[n]\n\t" + "and r9, r9, %[n]\n\t" + "eor r4, r4, r8\n\t" + "eor r5, r5, r9\n\t" + "eor r6, r6, r8\n\t" + "eor r7, r7, r9\n\t" + "strd r4, r5, [sp]\n\t" + "strd r6, r7, [sp, #32]\n\t" + "ldrd r4, r5, [sp, #8]\n\t" + "ldrd r6, r7, [sp, #40]\n\t" + "eor r8, r4, r6\n\t" + "eor r9, r5, r7\n\t" + "and r8, r8, %[n]\n\t" + "and r9, r9, %[n]\n\t" + "eor r4, r4, r8\n\t" + "eor r5, r5, r9\n\t" + "eor r6, r6, r8\n\t" + "eor r7, r7, r9\n\t" + "strd r4, r5, [sp, #8]\n\t" + "strd r6, r7, [sp, #40]\n\t" + "ldrd r4, r5, [sp, #16]\n\t" + "ldrd r6, r7, [sp, #48]\n\t" + "eor r8, r4, r6\n\t" + "eor r9, r5, r7\n\t" + "and r8, r8, %[n]\n\t" + "and r9, r9, %[n]\n\t" + "eor r4, r4, r8\n\t" + "eor r5, r5, r9\n\t" + "eor r6, r6, r8\n\t" + "eor r7, r7, r9\n\t" + "strd r4, r5, [sp, #16]\n\t" + "strd r6, r7, [sp, #48]\n\t" + "ldrd r4, r5, [sp, #24]\n\t" + "ldrd r6, r7, [sp, #56]\n\t" + "eor r8, r4, r6\n\t" + "eor r9, r5, r7\n\t" + "and r8, r8, %[n]\n\t" + "and r9, r9, %[n]\n\t" + "eor r4, r4, r8\n\t" + "eor r5, r5, r9\n\t" + "eor r6, r6, r8\n\t" + "eor r7, r7, r9\n\t" + "strd r4, r5, [sp, #24]\n\t" + "strd r6, r7, [sp, #56]\n\t" + "ldr %[n], [sp, #184]\n\t" + "str %[n], [sp, #172]\n\t" + /* Add-Sub */ + /* Add */ + "ldrd r4, r5, [%[r]]\n\t" + "ldrd r6, r7, [sp]\n\t" + "adds r8, r4, r6\n\t" + "mov r3, #0\n\t" + "adcs r9, r5, r7\n\t" + "adc r3, r3, #0\n\t" + "strd r8, r9, [%[r]]\n\t" + /* Sub */ + "subs r10, r4, r6\n\t" + "mov r12, #0\n\t" + "sbcs r11, r5, r7\n\t" + "adc r12, r12, #0\n\t" + "strd r10, r11, [sp, #128]\n\t" + /* Add */ + "ldrd r4, r5, [%[r], #8]\n\t" + "ldrd r6, r7, [sp, #8]\n\t" + "adds r3, r3, #-1\n\t" + "adcs r8, r4, r6\n\t" + "mov r3, #0\n\t" + "adcs r9, r5, r7\n\t" + "adc r3, r3, #0\n\t" + "strd r8, r9, [%[r], #8]\n\t" + /* Sub */ + "adds r12, r12, #-1\n\t" + "sbcs r10, r4, r6\n\t" + "mov r12, #0\n\t" + "sbcs r11, r5, r7\n\t" + "adc r12, r12, #0\n\t" + "strd r10, r11, [sp, #136]\n\t" + /* Add */ + "ldrd r4, r5, [%[r], #16]\n\t" + "ldrd r6, r7, [sp, #16]\n\t" + "adds r3, r3, #-1\n\t" + "adcs r8, r4, r6\n\t" + "mov r3, #0\n\t" + "adcs r9, r5, r7\n\t" + "adc r3, r3, #0\n\t" + "strd r8, r9, [%[r], #16]\n\t" + /* Sub */ + "adds r12, r12, #-1\n\t" + "sbcs r10, r4, r6\n\t" + "mov r12, #0\n\t" + "sbcs r11, r5, r7\n\t" + "adc r12, r12, #0\n\t" + "strd r10, r11, [sp, #144]\n\t" + /* Add */ + "ldrd r4, r5, [%[r], #24]\n\t" + "ldrd r6, r7, [sp, #24]\n\t" + "adds r3, r3, #-1\n\t" + "adcs r8, r4, r6\n\t" + "adc r9, r5, r7\n\t" + /* Sub */ + "adds r12, r12, #-1\n\t" + "sbcs r10, r4, r6\n\t" + "sbc r11, r5, r7\n\t" + "mov r3, #-19\n\t" + "asr %[a], r9, #31\n\t" + /* Mask the modulus */ + "and r3, %[a], r3\n\t" + "and r12, %[a], #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd r4, r5, [%[r]]\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, %[a]\n\t" + "strd r4, r5, [%[r]]\n\t" + "ldrd r4, r5, [%[r], #8]\n\t" + "sbcs r4, r4, %[a]\n\t" + "sbcs r5, r5, %[a]\n\t" + "strd r4, r5, [%[r], #8]\n\t" + "ldrd r4, r5, [%[r], #16]\n\t" + "sbcs r4, r4, %[a]\n\t" + "sbcs r5, r5, %[a]\n\t" + "strd r4, r5, [%[r], #16]\n\t" + "sbcs r8, r8, %[a]\n\t" + "sbc r9, r9, r12\n\t" + "strd r8, r9, [%[r], #24]\n\t" + "mov r3, #-19\n\t" + "asr %[a], r11, #31\n\t" + /* Mask the modulus */ + "and r3, %[a], r3\n\t" + "and r12, %[a], #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd r4, r5, [sp, #128]\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #128]\n\t" + "ldrd r4, r5, [sp, #136]\n\t" + "adcs r4, r4, %[a]\n\t" + "adcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #136]\n\t" + "ldrd r4, r5, [sp, #144]\n\t" + "adcs r4, r4, %[a]\n\t" + "adcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #144]\n\t" + "adcs r10, r10, %[a]\n\t" + "adc r11, r11, r12\n\t" + "strd r10, r11, [sp, #152]\n\t" + /* Add-Sub */ + /* Add */ + "ldrd r4, r5, [sp, #64]\n\t" + "ldrd r6, r7, [sp, #32]\n\t" + "adds r8, r4, r6\n\t" + "mov r3, #0\n\t" + "adcs r9, r5, r7\n\t" + "adc r3, r3, #0\n\t" + "strd r8, r9, [sp]\n\t" + /* Sub */ + "subs r10, r4, r6\n\t" + "mov r12, #0\n\t" + "sbcs r11, r5, r7\n\t" + "adc r12, r12, #0\n\t" + "strd r10, r11, [sp, #96]\n\t" + /* Add */ + "ldrd r4, r5, [sp, #72]\n\t" + "ldrd r6, r7, [sp, #40]\n\t" + "adds r3, r3, #-1\n\t" + "adcs r8, r4, r6\n\t" + "mov r3, #0\n\t" + "adcs r9, r5, r7\n\t" + "adc r3, r3, #0\n\t" + "strd r8, r9, [sp, #8]\n\t" + /* Sub */ + "adds r12, r12, #-1\n\t" + "sbcs r10, r4, r6\n\t" + "mov r12, #0\n\t" + "sbcs r11, r5, r7\n\t" + "adc r12, r12, #0\n\t" + "strd r10, r11, [sp, #104]\n\t" + /* Add */ + "ldrd r4, r5, [sp, #80]\n\t" + "ldrd r6, r7, [sp, #48]\n\t" + "adds r3, r3, #-1\n\t" + "adcs r8, r4, r6\n\t" + "mov r3, #0\n\t" + "adcs r9, r5, r7\n\t" + "adc r3, r3, #0\n\t" + "strd r8, r9, [sp, #16]\n\t" + /* Sub */ + "adds r12, r12, #-1\n\t" + "sbcs r10, r4, r6\n\t" + "mov r12, #0\n\t" + "sbcs r11, r5, r7\n\t" + "adc r12, r12, #0\n\t" + "strd r10, r11, [sp, #112]\n\t" + /* Add */ + "ldrd r4, r5, [sp, #88]\n\t" + "ldrd r6, r7, [sp, #56]\n\t" + "adds r3, r3, #-1\n\t" + "adcs r8, r4, r6\n\t" + "adc r9, r5, r7\n\t" + /* Sub */ + "adds r12, r12, #-1\n\t" + "sbcs r10, r4, r6\n\t" + "sbc r11, r5, r7\n\t" + "mov r3, #-19\n\t" + "asr %[a], r9, #31\n\t" + /* Mask the modulus */ + "and r3, %[a], r3\n\t" + "and r12, %[a], #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd r4, r5, [sp]\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp]\n\t" + "ldrd r4, r5, [sp, #8]\n\t" + "sbcs r4, r4, %[a]\n\t" + "sbcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #8]\n\t" + "ldrd r4, r5, [sp, #16]\n\t" + "sbcs r4, r4, %[a]\n\t" + "sbcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #16]\n\t" + "sbcs r8, r8, %[a]\n\t" + "sbc r9, r9, r12\n\t" + "strd r8, r9, [sp, #24]\n\t" + "mov r3, #-19\n\t" + "asr %[a], r11, #31\n\t" + /* Mask the modulus */ + "and r3, %[a], r3\n\t" + "and r12, %[a], #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd r4, r5, [sp, #96]\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #96]\n\t" + "ldrd r4, r5, [sp, #104]\n\t" + "adcs r4, r4, %[a]\n\t" + "adcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #104]\n\t" + "ldrd r4, r5, [sp, #112]\n\t" + "adcs r4, r4, %[a]\n\t" + "adcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #112]\n\t" + "adcs r10, r10, %[a]\n\t" + "adc r11, r11, r12\n\t" + "strd r10, r11, [sp, #120]\n\t" + "ldr r2, [sp, #160]\n\t" + "add r1, sp, #0x60\n\t" + "add r0, sp, #32\n\t" + "bl fe_mul\n\t" + "add r2, sp, #0x80\n\t" + "add r1, sp, #0\n\t" + "add r0, sp, #0\n\t" + "bl fe_mul\n\t" + "add r1, sp, #0x80\n\t" + "add r0, sp, #0x60\n\t" + "bl fe_sq\n\t" + "ldr r1, [sp, #160]\n\t" + "add r0, sp, #0x80\n\t" + "bl fe_sq\n\t" + /* Add-Sub */ + /* Add */ + "ldrd r4, r5, [sp, #32]\n\t" + "ldrd r6, r7, [sp]\n\t" + "adds r8, r4, r6\n\t" + "mov r3, #0\n\t" + "adcs r9, r5, r7\n\t" + "adc r3, r3, #0\n\t" + "strd r8, r9, [sp, #64]\n\t" + /* Sub */ + "subs r10, r4, r6\n\t" + "mov r12, #0\n\t" + "sbcs r11, r5, r7\n\t" + "adc r12, r12, #0\n\t" + "strd r10, r11, [sp]\n\t" + /* Add */ + "ldrd r4, r5, [sp, #40]\n\t" + "ldrd r6, r7, [sp, #8]\n\t" + "adds r3, r3, #-1\n\t" + "adcs r8, r4, r6\n\t" + "mov r3, #0\n\t" + "adcs r9, r5, r7\n\t" + "adc r3, r3, #0\n\t" + "strd r8, r9, [sp, #72]\n\t" + /* Sub */ + "adds r12, r12, #-1\n\t" + "sbcs r10, r4, r6\n\t" + "mov r12, #0\n\t" + "sbcs r11, r5, r7\n\t" + "adc r12, r12, #0\n\t" + "strd r10, r11, [sp, #8]\n\t" + /* Add */ + "ldrd r4, r5, [sp, #48]\n\t" + "ldrd r6, r7, [sp, #16]\n\t" + "adds r3, r3, #-1\n\t" + "adcs r8, r4, r6\n\t" + "mov r3, #0\n\t" + "adcs r9, r5, r7\n\t" + "adc r3, r3, #0\n\t" + "strd r8, r9, [sp, #80]\n\t" + /* Sub */ + "adds r12, r12, #-1\n\t" + "sbcs r10, r4, r6\n\t" + "mov r12, #0\n\t" + "sbcs r11, r5, r7\n\t" + "adc r12, r12, #0\n\t" + "strd r10, r11, [sp, #16]\n\t" + /* Add */ + "ldrd r4, r5, [sp, #56]\n\t" + "ldrd r6, r7, [sp, #24]\n\t" + "adds r3, r3, #-1\n\t" + "adcs r8, r4, r6\n\t" + "adc r9, r5, r7\n\t" + /* Sub */ + "adds r12, r12, #-1\n\t" + "sbcs r10, r4, r6\n\t" + "sbc r11, r5, r7\n\t" + "mov r3, #-19\n\t" + "asr %[a], r9, #31\n\t" + /* Mask the modulus */ + "and r3, %[a], r3\n\t" + "and r12, %[a], #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd r4, r5, [sp, #64]\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #64]\n\t" + "ldrd r4, r5, [sp, #72]\n\t" + "sbcs r4, r4, %[a]\n\t" + "sbcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #72]\n\t" + "ldrd r4, r5, [sp, #80]\n\t" + "sbcs r4, r4, %[a]\n\t" + "sbcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #80]\n\t" + "sbcs r8, r8, %[a]\n\t" + "sbc r9, r9, r12\n\t" + "strd r8, r9, [sp, #88]\n\t" + "mov r3, #-19\n\t" + "asr %[a], r11, #31\n\t" + /* Mask the modulus */ + "and r3, %[a], r3\n\t" + "and r12, %[a], #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd r4, r5, [sp]\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp]\n\t" + "ldrd r4, r5, [sp, #8]\n\t" + "adcs r4, r4, %[a]\n\t" + "adcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #8]\n\t" + "ldrd r4, r5, [sp, #16]\n\t" + "adcs r4, r4, %[a]\n\t" + "adcs r5, r5, %[a]\n\t" + "strd r4, r5, [sp, #16]\n\t" + "adcs r10, r10, %[a]\n\t" + "adc r11, r11, r12\n\t" + "strd r10, r11, [sp, #24]\n\t" + "add r2, sp, #0x60\n\t" + "add r1, sp, #0x80\n\t" + "ldr r0, [sp, #160]\n\t" + "bl fe_mul\n\t" + /* Sub */ + "ldrd r4, r5, [sp, #128]\n\t" + "ldrd r6, r7, [sp, #136]\n\t" + "ldrd r8, r9, [sp, #96]\n\t" + "ldrd r10, r11, [sp, #104]\n\t" + "subs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbcs r10, r6, r10\n\t" + "sbcs r11, r7, r11\n\t" + "strd r8, r9, [sp, #128]\n\t" + "strd r10, r11, [sp, #136]\n\t" + "ldrd r4, r5, [sp, #144]\n\t" + "ldrd r6, r7, [sp, #152]\n\t" + "ldrd r8, r9, [sp, #112]\n\t" + "ldrd r10, r11, [sp, #120]\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbcs r10, r6, r10\n\t" + "sbc r11, r7, r11\n\t" + "mov r3, #-19\n\t" + "asr %[a], r11, #31\n\t" + /* Mask the modulus */ + "and r3, %[a], r3\n\t" + "and r12, %[a], #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd r4, r5, [sp, #128]\n\t" + "ldrd r6, r7, [sp, #136]\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, %[a]\n\t" + "adcs r6, r6, %[a]\n\t" + "adcs r7, r7, %[a]\n\t" + "adcs r8, r8, %[a]\n\t" + "adcs r9, r9, %[a]\n\t" + "adcs r10, r10, %[a]\n\t" + "adc r11, r11, r12\n\t" + "strd r4, r5, [sp, #128]\n\t" + "strd r6, r7, [sp, #136]\n\t" + "strd r8, r9, [sp, #144]\n\t" + "strd r10, r11, [sp, #152]\n\t" + "add r1, sp, #0\n\t" + "add r0, sp, #0\n\t" + "bl fe_sq\n\t" + /* Multiply by 121666 */ + "ldrd r4, r5, [sp, #128]\n\t" + "ldrd r6, r7, [sp, #136]\n\t" + "ldrd r8, r9, [sp, #144]\n\t" + "ldrd r10, r11, [sp, #152]\n\t" + "movw r12, #0xdb42\n\t" + "movt r12, #1\n\t" + "umull r4, %[a], r4, r12\n\t" + "umull r5, r3, r5, r12\n\t" + "adds r5, r5, %[a]\n\t" + "adc %[a], r3, #0\n\t" + "umull r6, r3, r6, r12\n\t" + "adds r6, r6, %[a]\n\t" + "adc %[a], r3, #0\n\t" + "umull r7, r3, r7, r12\n\t" + "adds r7, r7, %[a]\n\t" + "adc %[a], r3, #0\n\t" + "umull r8, r3, r8, r12\n\t" + "adds r8, r8, %[a]\n\t" + "adc %[a], r3, #0\n\t" + "umull r9, r3, r9, r12\n\t" + "adds r9, r9, %[a]\n\t" + "adc %[a], r3, #0\n\t" + "umull r10, r3, r10, r12\n\t" + "adds r10, r10, %[a]\n\t" + "adc %[a], r3, #0\n\t" + "umull r11, r3, r11, r12\n\t" + "adds r11, r11, %[a]\n\t" + "adc %[a], r3, #0\n\t" + "mov r12, #19\n\t" + "lsl %[a], %[a], #1\n\t" + "orr %[a], %[a], r11, lsr #31\n\t" + "mul %[a], %[a], r12\n\t" + "and r11, r11, #0x7fffffff\n\t" + "adds r4, r4, %[a]\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adcs r7, r7, #0\n\t" + "adcs r8, r8, #0\n\t" + "adcs r9, r9, #0\n\t" + "adcs r10, r10, #0\n\t" + "adc r11, r11, #0\n\t" + "strd r4, r5, [sp, #32]\n\t" + "strd r6, r7, [sp, #40]\n\t" + "strd r8, r9, [sp, #48]\n\t" + "strd r10, r11, [sp, #56]\n\t" + "add r1, sp, #0x40\n\t" + "add r0, sp, #0x40\n\t" + "bl fe_sq\n\t" + /* Add */ + "ldrd r4, r5, [sp, #96]\n\t" + "ldrd r6, r7, [sp, #104]\n\t" + "ldrd r8, r9, [sp, #32]\n\t" + "ldrd r10, r11, [sp, #40]\n\t" + "adds r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "adcs r10, r6, r10\n\t" + "adcs r11, r7, r11\n\t" + "strd r8, r9, [sp, #96]\n\t" + "strd r10, r11, [sp, #104]\n\t" + "ldrd r4, r5, [sp, #112]\n\t" + "ldrd r6, r7, [sp, #120]\n\t" + "ldrd r8, r9, [sp, #48]\n\t" + "ldrd r10, r11, [sp, #56]\n\t" + "adcs r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "adcs r10, r6, r10\n\t" + "adc r11, r7, r11\n\t" + "mov r3, #-19\n\t" + "asr %[a], r11, #31\n\t" + /* Mask the modulus */ + "and r3, %[a], r3\n\t" + "and r12, %[a], #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd r4, r5, [sp, #96]\n\t" + "ldrd r6, r7, [sp, #104]\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, %[a]\n\t" + "sbcs r6, r6, %[a]\n\t" + "sbcs r7, r7, %[a]\n\t" + "sbcs r8, r8, %[a]\n\t" + "sbcs r9, r9, %[a]\n\t" + "sbcs r10, r10, %[a]\n\t" + "sbc r11, r11, r12\n\t" + "strd r4, r5, [sp, #96]\n\t" + "strd r6, r7, [sp, #104]\n\t" + "strd r8, r9, [sp, #112]\n\t" + "strd r10, r11, [sp, #120]\n\t" + "add r2, sp, #0\n\t" + "ldr r1, [sp, #168]\n\t" + "add r0, sp, #32\n\t" + "bl fe_mul\n\t" + "add r2, sp, #0x60\n\t" + "add r1, sp, #0x80\n\t" + "add r0, sp, #0\n\t" + "bl fe_mul\n\t" + "ldr %[a], [sp, #176]\n\t" + "ldr %[n], [sp, #180]\n\t" + "subs %[n], %[n], #1\n\t" + "str %[n], [sp, #180]\n\t" + "bge L_curve25519_bits_%=\n\t" + "mov %[n], #31\n\t" + "str %[n], [sp, #180]\n\t" + "subs %[a], %[a], #4\n\t" + "str %[a], [sp, #176]\n\t" + "bge L_curve25519_words_%=\n\t" + /* Invert */ + "add r0, sp, #32\n\t" + "add r1, sp, #0\n\t" + "bl fe_sq\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0\n\t" + "add r2, sp, #0x40\n\t" + "bl fe_mul\n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #32\n\t" + "add r2, sp, #0x40\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x40\n\t" + "add r2, sp, #0x60\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "mov r4, #4\n\t" + "\n" + "L_curve25519_inv_1_%=: \n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x60\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_curve25519_inv_1_%=\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x60\n\t" + "add r2, sp, #0x40\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "mov r4, #9\n\t" + "\n" + "L_curve25519_inv_2_%=: \n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x60\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_curve25519_inv_2_%=\n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x60\n\t" + "add r2, sp, #0x40\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x80\n\t" + "add r1, sp, #0x60\n\t" + "bl fe_sq\n\t" + "mov r4, #19\n\t" + "\n" + "L_curve25519_inv_3_%=: \n\t" + "add r0, sp, #0x80\n\t" + "add r1, sp, #0x80\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_curve25519_inv_3_%=\n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x80\n\t" + "add r2, sp, #0x60\n\t" + "bl fe_mul\n\t" + "mov r4, #10\n\t" + "\n" + "L_curve25519_inv_4_%=: \n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x60\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_curve25519_inv_4_%=\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x60\n\t" + "add r2, sp, #0x40\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "mov r4, #49\n\t" + "\n" + "L_curve25519_inv_5_%=: \n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x60\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_curve25519_inv_5_%=\n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x60\n\t" + "add r2, sp, #0x40\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x80\n\t" + "add r1, sp, #0x60\n\t" + "bl fe_sq\n\t" + "mov r4, #0x63\n\t" + "\n" + "L_curve25519_inv_6_%=: \n\t" + "add r0, sp, #0x80\n\t" + "add r1, sp, #0x80\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_curve25519_inv_6_%=\n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x80\n\t" + "add r2, sp, #0x60\n\t" + "bl fe_mul\n\t" + "mov r4, #50\n\t" + "\n" + "L_curve25519_inv_7_%=: \n\t" + "add r0, sp, #0x60\n\t" + "add r1, sp, #0x60\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_curve25519_inv_7_%=\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x60\n\t" + "add r2, sp, #0x40\n\t" + "bl fe_mul\n\t" + "mov r4, #5\n\t" + "\n" + "L_curve25519_inv_8_%=: \n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_curve25519_inv_8_%=\n\t" + "add r0, sp, #0\n\t" + "add r1, sp, #0x40\n\t" + "add r2, sp, #32\n\t" + "bl fe_mul\n\t" + "add r2, sp, #0\n\t" + "ldr r1, [sp, #160]\n\t" + "ldr r0, [sp, #160]\n\t" + "bl fe_mul\n\t" + "mov r0, #0\n\t" + "add sp, sp, #0xbc\n\t" + : [r] "+r" (r), [n] "+r" (n), [a] "+r" (a) + : + : "memory", "r3", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); + return (uint32_t)(size_t)r; +} + +void fe_pow22523(fe r, const fe a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #0x68\n\t" + /* pow22523 */ + "str %[r], [sp, #96]\n\t" + "str %[a], [sp, #100]\n\t" + "mov r0, sp\n\t" + "ldr r1, [sp, #100]\n\t" + "bl fe_sq\n\t" + "add r0, sp, #32\n\t" + "mov r1, sp\n\t" + "bl fe_sq\n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "add r0, sp, #32\n\t" + "ldr r1, [sp, #100]\n\t" + "add r2, sp, #32\n\t" + "bl fe_mul\n\t" + "mov r0, sp\n\t" + "mov r1, sp\n\t" + "add r2, sp, #32\n\t" + "bl fe_mul\n\t" + "mov r0, sp\n\t" + "mov r1, sp\n\t" + "bl fe_sq\n\t" + "mov r0, sp\n\t" + "add r1, sp, #32\n\t" + "mov r2, sp\n\t" + "bl fe_mul\n\t" + "add r0, sp, #32\n\t" + "mov r1, sp\n\t" + "bl fe_sq\n\t" + "mov r4, #4\n\t" + "\n" + "L_fe_pow22523_1_%=: \n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_pow22523_1_%=\n\t" + "mov r0, sp\n\t" + "add r1, sp, #32\n\t" + "mov r2, sp\n\t" + "bl fe_mul\n\t" + "add r0, sp, #32\n\t" + "mov r1, sp\n\t" + "bl fe_sq\n\t" + "mov r4, #9\n\t" + "\n" + "L_fe_pow22523_2_%=: \n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_pow22523_2_%=\n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #32\n\t" + "mov r2, sp\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "mov r4, #19\n\t" + "\n" + "L_fe_pow22523_3_%=: \n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_pow22523_3_%=\n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #0x40\n\t" + "add r2, sp, #32\n\t" + "bl fe_mul\n\t" + "mov r4, #10\n\t" + "\n" + "L_fe_pow22523_4_%=: \n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_pow22523_4_%=\n\t" + "mov r0, sp\n\t" + "add r1, sp, #32\n\t" + "mov r2, sp\n\t" + "bl fe_mul\n\t" + "add r0, sp, #32\n\t" + "mov r1, sp\n\t" + "bl fe_sq\n\t" + "mov r4, #49\n\t" + "\n" + "L_fe_pow22523_5_%=: \n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_pow22523_5_%=\n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #32\n\t" + "mov r2, sp\n\t" + "bl fe_mul\n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "mov r4, #0x63\n\t" + "\n" + "L_fe_pow22523_6_%=: \n\t" + "add r0, sp, #0x40\n\t" + "add r1, sp, #0x40\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_pow22523_6_%=\n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #0x40\n\t" + "add r2, sp, #32\n\t" + "bl fe_mul\n\t" + "mov r4, #50\n\t" + "\n" + "L_fe_pow22523_7_%=: \n\t" + "add r0, sp, #32\n\t" + "add r1, sp, #32\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_pow22523_7_%=\n\t" + "mov r0, sp\n\t" + "add r1, sp, #32\n\t" + "mov r2, sp\n\t" + "bl fe_mul\n\t" + "mov r4, #2\n\t" + "\n" + "L_fe_pow22523_8_%=: \n\t" + "mov r0, sp\n\t" + "mov r1, sp\n\t" + "bl fe_sq\n\t" + "sub r4, r4, #1\n\t" + "cmp r4, #0\n\t" + "bne L_fe_pow22523_8_%=\n\t" + "ldr r0, [sp, #96]\n\t" + "mov r1, sp\n\t" + "ldr r2, [sp, #100]\n\t" + "bl fe_mul\n\t" + "ldr %[a], [sp, #100]\n\t" + "ldr %[r], [sp, #96]\n\t" + "add sp, sp, #0x68\n\t" + : [r] "+r" (r), [a] "+r" (a) + : + : "memory", "lr", "r4" + ); +} + +void fe_ge_to_p2(fe rx, fe ry, fe rz, const fe px, const fe py, const fe pz, const fe pt) +{ + __asm__ __volatile__ ( + "sub sp, sp, #16\n\t" + "str %[rx], [sp]\n\t" + "str %[ry], [sp, #4]\n\t" + "str %[rz], [sp, #8]\n\t" + "str %[px], [sp, #12]\n\t" + "ldr r2, [sp, #32]\n\t" + "ldr r1, [sp, #12]\n\t" + "ldr r0, [sp]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #28]\n\t" + "ldr r1, [sp, #24]\n\t" + "ldr r0, [sp, #4]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #32]\n\t" + "ldr r1, [sp, #28]\n\t" + "ldr r0, [sp, #8]\n\t" + "bl fe_mul\n\t" + "add sp, sp, #16\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + : + : "memory", "lr" + ); +} + +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) +{ + __asm__ __volatile__ ( + "sub sp, sp, #16\n\t" + "str %[rx], [sp]\n\t" + "str %[ry], [sp, #4]\n\t" + "str %[rz], [sp, #8]\n\t" + "str %[rt], [sp, #12]\n\t" + "ldr r2, [sp, #36]\n\t" + "ldr r1, [sp, #24]\n\t" + "ldr r0, [sp]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #32]\n\t" + "ldr r1, [sp, #28]\n\t" + "ldr r0, [sp, #4]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #36]\n\t" + "ldr r1, [sp, #32]\n\t" + "ldr r0, [sp, #8]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #28]\n\t" + "ldr r1, [sp, #24]\n\t" + "ldr r0, [sp, #12]\n\t" + "bl fe_mul\n\t" + "add sp, sp, #16\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + : + : "memory", "lr" + ); +} + +void fe_ge_dbl(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz) +{ + __asm__ __volatile__ ( + "sub sp, sp, #16\n\t" + "str %[rx], [sp]\n\t" + "str %[ry], [sp, #4]\n\t" + "str %[rz], [sp, #8]\n\t" + "str %[rt], [sp, #12]\n\t" + "ldr r1, [sp, #88]\n\t" + "ldr r0, [sp]\n\t" + "bl fe_sq\n\t" + "ldr r1, [sp, #92]\n\t" + "ldr r0, [sp, #8]\n\t" + "bl fe_sq\n\t" + "ldr r0, [sp, #4]\n\t" + "ldr r1, [sp, #88]\n\t" + "ldr r2, [sp, #92]\n\t" + /* Add */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r2]\n\t" + "ldrd r9, r10, [r2, #8]\n\t" + "adds r7, %[rt], r7\n\t" + "adcs r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "adcs r10, r6, r10\n\t" + "strd r7, r8, [r0]\n\t" + "strd r9, r10, [r0, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "ldrd r5, r6, [r1, #24]\n\t" + "ldrd r7, r8, [r2, #16]\n\t" + "ldrd r9, r10, [r2, #24]\n\t" + "adcs r7, %[rt], r7\n\t" + "adcs r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "adc r10, r6, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "sbcs r5, r5, r11\n\t" + "sbcs r6, r6, r11\n\t" + "sbcs r7, r7, r11\n\t" + "sbcs r8, r8, r11\n\t" + "sbcs r9, r9, r11\n\t" + "sbc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r1, [sp, #4]\n\t" + "ldr r0, [sp, #12]\n\t" + "bl fe_sq\n\t" + "ldr r0, [sp, #4]\n\t" + "ldr r1, [sp, #8]\n\t" + "ldr r2, [sp]\n\t" + /* Add-Sub */ + /* Add */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r2]\n\t" + "adds r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0]\n\t" + /* Sub */ + "subs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1]\n\t" + /* Add */ + "ldrd %[rt], r4, [r1, #8]\n\t" + "ldrd r5, r6, [r2, #8]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #8]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #8]\n\t" + /* Add */ + "ldrd %[rt], r4, [r1, #16]\n\t" + "ldrd r5, r6, [r2, #16]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #16]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #16]\n\t" + /* Add */ + "ldrd %[rt], r4, [r1, #24]\n\t" + "ldrd r5, r6, [r2, #24]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "adc r8, r4, r6\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "sbc r10, r4, r6\n\t" + "mov r12, #-19\n\t" + "asr r11, r8, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0]\n\t" + "ldrd %[rt], r4, [r0, #8]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #8]\n\t" + "ldrd %[rt], r4, [r0, #16]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #16]\n\t" + "sbcs r7, r7, r11\n\t" + "sbc r8, r8, lr\n\t" + "strd r7, r8, [r0, #24]\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r1]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1]\n\t" + "ldrd %[rt], r4, [r1, #8]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #16]\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd r9, r10, [r1, #24]\n\t" + "ldr r0, [sp]\n\t" + "ldr r1, [sp, #12]\n\t" + "ldr r2, [sp, #4]\n\t" + /* Sub */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r2]\n\t" + "ldrd r9, r10, [r2, #8]\n\t" + "subs r7, %[rt], r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbcs r10, r6, r10\n\t" + "strd r7, r8, [r0]\n\t" + "strd r9, r10, [r0, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "ldrd r5, r6, [r1, #24]\n\t" + "ldrd r7, r8, [r2, #16]\n\t" + "ldrd r9, r10, [r2, #24]\n\t" + "sbcs r7, %[rt], r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbc r10, r6, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "adcs r5, r5, r11\n\t" + "adcs r6, r6, r11\n\t" + "adcs r7, r7, r11\n\t" + "adcs r8, r8, r11\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r1, [sp, #96]\n\t" + "ldr r0, [sp, #12]\n\t" + "bl fe_sq2\n\t" + "ldr r0, [sp, #12]\n\t" + "ldr r1, [sp, #8]\n\t" + /* Sub */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "ldrd r7, r8, [r1]\n\t" + "ldrd r9, r10, [r1, #8]\n\t" + "subs r7, %[rt], r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbcs r10, r6, r10\n\t" + "strd r7, r8, [r0]\n\t" + "strd r9, r10, [r0, #8]\n\t" + "ldrd %[rt], r4, [r0, #16]\n\t" + "ldrd r5, r6, [r0, #24]\n\t" + "ldrd r7, r8, [r1, #16]\n\t" + "ldrd r9, r10, [r1, #24]\n\t" + "sbcs r7, %[rt], r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbc r10, r6, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "adcs r5, r5, r11\n\t" + "adcs r6, r6, r11\n\t" + "adcs r7, r7, r11\n\t" + "adcs r8, r8, r11\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "add sp, sp, #16\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz) + : + : "memory", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +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) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "str %[rx], [sp]\n\t" + "str %[ry], [sp, #4]\n\t" + "str %[rz], [sp, #8]\n\t" + "str %[rt], [sp, #12]\n\t" + "ldr r0, [sp]\n\t" + "ldr r1, [sp, #108]\n\t" + "ldr r2, [sp, #104]\n\t" + /* Add */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r2]\n\t" + "ldrd r9, r10, [r2, #8]\n\t" + "adds r7, %[rt], r7\n\t" + "adcs r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "adcs r10, r6, r10\n\t" + "strd r7, r8, [r0]\n\t" + "strd r9, r10, [r0, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "ldrd r5, r6, [r1, #24]\n\t" + "ldrd r7, r8, [r2, #16]\n\t" + "ldrd r9, r10, [r2, #24]\n\t" + "adcs r7, %[rt], r7\n\t" + "adcs r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "adc r10, r6, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "sbcs r5, r5, r11\n\t" + "sbcs r6, r6, r11\n\t" + "sbcs r7, r7, r11\n\t" + "sbcs r8, r8, r11\n\t" + "sbcs r9, r9, r11\n\t" + "sbc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r0, [sp, #4]\n\t" + "ldr r1, [sp, #108]\n\t" + "ldr r2, [sp, #104]\n\t" + /* Sub */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r2]\n\t" + "ldrd r9, r10, [r2, #8]\n\t" + "subs r7, %[rt], r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbcs r10, r6, r10\n\t" + "strd r7, r8, [r0]\n\t" + "strd r9, r10, [r0, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "ldrd r5, r6, [r1, #24]\n\t" + "ldrd r7, r8, [r2, #16]\n\t" + "ldrd r9, r10, [r2, #24]\n\t" + "sbcs r7, %[rt], r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbc r10, r6, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "adcs r5, r5, r11\n\t" + "adcs r6, r6, r11\n\t" + "adcs r7, r7, r11\n\t" + "adcs r8, r8, r11\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r2, [sp, #124]\n\t" + "ldr r1, [sp]\n\t" + "ldr r0, [sp, #8]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #128]\n\t" + "ldr r1, [sp, #4]\n\t" + "ldr r0, [sp, #4]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #116]\n\t" + "ldr r1, [sp, #120]\n\t" + "ldr r0, [sp, #12]\n\t" + "bl fe_mul\n\t" + "ldr r0, [sp, #4]\n\t" + "ldr r1, [sp]\n\t" + "ldr r2, [sp, #8]\n\t" + /* Add-Sub */ + /* Add */ + "ldrd %[rt], r4, [r2]\n\t" + "ldrd r5, r6, [r0]\n\t" + "adds r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0]\n\t" + /* Sub */ + "subs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #8]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #8]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #8]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #16]\n\t" + "ldrd r5, r6, [r0, #16]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #16]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #16]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #24]\n\t" + "ldrd r5, r6, [r0, #24]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "adc r8, r4, r6\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "sbc r10, r4, r6\n\t" + "mov r12, #-19\n\t" + "asr r11, r8, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0]\n\t" + "ldrd %[rt], r4, [r0, #8]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #8]\n\t" + "ldrd %[rt], r4, [r0, #16]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #16]\n\t" + "sbcs r7, r7, r11\n\t" + "sbc r8, r8, lr\n\t" + "strd r7, r8, [r0, #24]\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r1]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1]\n\t" + "ldrd %[rt], r4, [r1, #8]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #16]\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd r9, r10, [r1, #24]\n\t" + "ldr r0, [sp, #8]\n\t" + "ldr r1, [sp, #112]\n\t" + /* Double */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r1, #16]\n\t" + "ldrd r9, r10, [r1, #24]\n\t" + "adds %[rt], %[rt], %[rt]\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adc r10, r10, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "sbcs r5, r5, r11\n\t" + "sbcs r6, r6, r11\n\t" + "sbcs r7, r7, r11\n\t" + "sbcs r8, r8, r11\n\t" + "sbcs r9, r9, r11\n\t" + "sbc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r0, [sp, #8]\n\t" + "ldr r1, [sp, #12]\n\t" + /* Add-Sub */ + /* Add */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r1]\n\t" + "adds r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0]\n\t" + /* Sub */ + "subs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1]\n\t" + /* Add */ + "ldrd %[rt], r4, [r0, #8]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #8]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #8]\n\t" + /* Add */ + "ldrd %[rt], r4, [r0, #16]\n\t" + "ldrd r5, r6, [r1, #16]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #16]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #16]\n\t" + /* Add */ + "ldrd %[rt], r4, [r0, #24]\n\t" + "ldrd r5, r6, [r1, #24]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "adc r8, r4, r6\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "sbc r10, r4, r6\n\t" + "mov r12, #-19\n\t" + "asr r11, r8, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0]\n\t" + "ldrd %[rt], r4, [r0, #8]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #8]\n\t" + "ldrd %[rt], r4, [r0, #16]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #16]\n\t" + "sbcs r7, r7, r11\n\t" + "sbc r8, r8, lr\n\t" + "strd r7, r8, [r0, #24]\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r1]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1]\n\t" + "ldrd %[rt], r4, [r1, #8]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #16]\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd r9, r10, [r1, #24]\n\t" + "add sp, sp, #32\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + : + : "memory", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); + (void)qxy2d; + (void)qyplusx; + (void)qyminusx; +} + +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) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "str %[rx], [sp]\n\t" + "str %[ry], [sp, #4]\n\t" + "str %[rz], [sp, #8]\n\t" + "str %[rt], [sp, #12]\n\t" + "ldr r0, [sp]\n\t" + "ldr r1, [sp, #108]\n\t" + "ldr r2, [sp, #104]\n\t" + /* Add */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r2]\n\t" + "ldrd r9, r10, [r2, #8]\n\t" + "adds r7, %[rt], r7\n\t" + "adcs r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "adcs r10, r6, r10\n\t" + "strd r7, r8, [r0]\n\t" + "strd r9, r10, [r0, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "ldrd r5, r6, [r1, #24]\n\t" + "ldrd r7, r8, [r2, #16]\n\t" + "ldrd r9, r10, [r2, #24]\n\t" + "adcs r7, %[rt], r7\n\t" + "adcs r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "adc r10, r6, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "sbcs r5, r5, r11\n\t" + "sbcs r6, r6, r11\n\t" + "sbcs r7, r7, r11\n\t" + "sbcs r8, r8, r11\n\t" + "sbcs r9, r9, r11\n\t" + "sbc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r0, [sp, #4]\n\t" + "ldr r1, [sp, #108]\n\t" + "ldr r2, [sp, #104]\n\t" + /* Sub */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r2]\n\t" + "ldrd r9, r10, [r2, #8]\n\t" + "subs r7, %[rt], r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbcs r10, r6, r10\n\t" + "strd r7, r8, [r0]\n\t" + "strd r9, r10, [r0, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "ldrd r5, r6, [r1, #24]\n\t" + "ldrd r7, r8, [r2, #16]\n\t" + "ldrd r9, r10, [r2, #24]\n\t" + "sbcs r7, %[rt], r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbc r10, r6, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "adcs r5, r5, r11\n\t" + "adcs r6, r6, r11\n\t" + "adcs r7, r7, r11\n\t" + "adcs r8, r8, r11\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r2, [sp, #128]\n\t" + "ldr r1, [sp]\n\t" + "ldr r0, [sp, #8]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #124]\n\t" + "ldr r1, [sp, #4]\n\t" + "ldr r0, [sp, #4]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #116]\n\t" + "ldr r1, [sp, #120]\n\t" + "ldr r0, [sp, #12]\n\t" + "bl fe_mul\n\t" + "ldr r0, [sp, #4]\n\t" + "ldr r1, [sp]\n\t" + "ldr r2, [sp, #8]\n\t" + /* Add-Sub */ + /* Add */ + "ldrd %[rt], r4, [r2]\n\t" + "ldrd r5, r6, [r0]\n\t" + "adds r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0]\n\t" + /* Sub */ + "subs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #8]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #8]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #8]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #16]\n\t" + "ldrd r5, r6, [r0, #16]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #16]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #16]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #24]\n\t" + "ldrd r5, r6, [r0, #24]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "adc r8, r4, r6\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "sbc r10, r4, r6\n\t" + "mov r12, #-19\n\t" + "asr r11, r8, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0]\n\t" + "ldrd %[rt], r4, [r0, #8]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #8]\n\t" + "ldrd %[rt], r4, [r0, #16]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #16]\n\t" + "sbcs r7, r7, r11\n\t" + "sbc r8, r8, lr\n\t" + "strd r7, r8, [r0, #24]\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r1]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1]\n\t" + "ldrd %[rt], r4, [r1, #8]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #16]\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd r9, r10, [r1, #24]\n\t" + "ldr r0, [sp, #8]\n\t" + "ldr r1, [sp, #112]\n\t" + /* Double */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r1, #16]\n\t" + "ldrd r9, r10, [r1, #24]\n\t" + "adds %[rt], %[rt], %[rt]\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adc r10, r10, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "sbcs r5, r5, r11\n\t" + "sbcs r6, r6, r11\n\t" + "sbcs r7, r7, r11\n\t" + "sbcs r8, r8, r11\n\t" + "sbcs r9, r9, r11\n\t" + "sbc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r0, [sp, #12]\n\t" + "ldr r1, [sp, #8]\n\t" + /* Add-Sub */ + /* Add */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r0]\n\t" + "adds r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0]\n\t" + /* Sub */ + "subs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1]\n\t" + /* Add */ + "ldrd %[rt], r4, [r1, #8]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #8]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #8]\n\t" + /* Add */ + "ldrd %[rt], r4, [r1, #16]\n\t" + "ldrd r5, r6, [r0, #16]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #16]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #16]\n\t" + /* Add */ + "ldrd %[rt], r4, [r1, #24]\n\t" + "ldrd r5, r6, [r0, #24]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "adc r8, r4, r6\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "sbc r10, r4, r6\n\t" + "mov r12, #-19\n\t" + "asr r11, r8, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0]\n\t" + "ldrd %[rt], r4, [r0, #8]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #8]\n\t" + "ldrd %[rt], r4, [r0, #16]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #16]\n\t" + "sbcs r7, r7, r11\n\t" + "sbc r8, r8, lr\n\t" + "strd r7, r8, [r0, #24]\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r1]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1]\n\t" + "ldrd %[rt], r4, [r1, #8]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #16]\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd r9, r10, [r1, #24]\n\t" + "add sp, sp, #32\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + : + : "memory", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); + (void)qxy2d; + (void)qyplusx; + (void)qyminusx; +} + +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) +{ + __asm__ __volatile__ ( + "sub sp, sp, #0x60\n\t" + "str %[rx], [sp]\n\t" + "str %[ry], [sp, #4]\n\t" + "str %[rz], [sp, #8]\n\t" + "str %[rt], [sp, #12]\n\t" + "ldr r0, [sp]\n\t" + "ldr r1, [sp, #172]\n\t" + "ldr r2, [sp, #168]\n\t" + /* Add */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r2]\n\t" + "ldrd r9, r10, [r2, #8]\n\t" + "adds r7, %[rt], r7\n\t" + "adcs r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "adcs r10, r6, r10\n\t" + "strd r7, r8, [r0]\n\t" + "strd r9, r10, [r0, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "ldrd r5, r6, [r1, #24]\n\t" + "ldrd r7, r8, [r2, #16]\n\t" + "ldrd r9, r10, [r2, #24]\n\t" + "adcs r7, %[rt], r7\n\t" + "adcs r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "adc r10, r6, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "sbcs r5, r5, r11\n\t" + "sbcs r6, r6, r11\n\t" + "sbcs r7, r7, r11\n\t" + "sbcs r8, r8, r11\n\t" + "sbcs r9, r9, r11\n\t" + "sbc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r0, [sp, #4]\n\t" + "ldr r1, [sp, #172]\n\t" + "ldr r2, [sp, #168]\n\t" + /* Sub */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r2]\n\t" + "ldrd r9, r10, [r2, #8]\n\t" + "subs r7, %[rt], r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbcs r10, r6, r10\n\t" + "strd r7, r8, [r0]\n\t" + "strd r9, r10, [r0, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "ldrd r5, r6, [r1, #24]\n\t" + "ldrd r7, r8, [r2, #16]\n\t" + "ldrd r9, r10, [r2, #24]\n\t" + "sbcs r7, %[rt], r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbc r10, r6, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "adcs r5, r5, r11\n\t" + "adcs r6, r6, r11\n\t" + "adcs r7, r7, r11\n\t" + "adcs r8, r8, r11\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r2, [sp, #192]\n\t" + "ldr r1, [sp]\n\t" + "ldr r0, [sp, #8]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #196]\n\t" + "ldr r1, [sp, #4]\n\t" + "ldr r0, [sp, #4]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #180]\n\t" + "ldr r1, [sp, #188]\n\t" + "ldr r0, [sp, #12]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #184]\n\t" + "ldr r1, [sp, #176]\n\t" + "ldr r0, [sp]\n\t" + "bl fe_mul\n\t" + "add r0, sp, #16\n\t" + "ldr r1, [sp]\n\t" + /* Double */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r1, #16]\n\t" + "ldrd r9, r10, [r1, #24]\n\t" + "adds %[rt], %[rt], %[rt]\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adc r10, r10, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "sbcs r5, r5, r11\n\t" + "sbcs r6, r6, r11\n\t" + "sbcs r7, r7, r11\n\t" + "sbcs r8, r8, r11\n\t" + "sbcs r9, r9, r11\n\t" + "sbc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r0, [sp, #4]\n\t" + "ldr r1, [sp]\n\t" + "ldr r2, [sp, #8]\n\t" + /* Add-Sub */ + /* Add */ + "ldrd %[rt], r4, [r2]\n\t" + "ldrd r5, r6, [r0]\n\t" + "adds r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0]\n\t" + /* Sub */ + "subs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #8]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #8]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #8]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #16]\n\t" + "ldrd r5, r6, [r0, #16]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #16]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #16]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #24]\n\t" + "ldrd r5, r6, [r0, #24]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "adc r8, r4, r6\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "sbc r10, r4, r6\n\t" + "mov r12, #-19\n\t" + "asr r11, r8, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0]\n\t" + "ldrd %[rt], r4, [r0, #8]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #8]\n\t" + "ldrd %[rt], r4, [r0, #16]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #16]\n\t" + "sbcs r7, r7, r11\n\t" + "sbc r8, r8, lr\n\t" + "strd r7, r8, [r0, #24]\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r1]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1]\n\t" + "ldrd %[rt], r4, [r1, #8]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #16]\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd r9, r10, [r1, #24]\n\t" + "ldr r0, [sp, #8]\n\t" + "ldr r1, [sp, #12]\n\t" + "add r2, sp, #16\n\t" + /* Add-Sub */ + /* Add */ + "ldrd %[rt], r4, [r2]\n\t" + "ldrd r5, r6, [r1]\n\t" + "adds r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0]\n\t" + /* Sub */ + "subs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #8]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #8]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #8]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #16]\n\t" + "ldrd r5, r6, [r1, #16]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #16]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #16]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #24]\n\t" + "ldrd r5, r6, [r1, #24]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "adc r8, r4, r6\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "sbc r10, r4, r6\n\t" + "mov r12, #-19\n\t" + "asr r11, r8, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0]\n\t" + "ldrd %[rt], r4, [r0, #8]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #8]\n\t" + "ldrd %[rt], r4, [r0, #16]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #16]\n\t" + "sbcs r7, r7, r11\n\t" + "sbc r8, r8, lr\n\t" + "strd r7, r8, [r0, #24]\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r1]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1]\n\t" + "ldrd %[rt], r4, [r1, #8]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #16]\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd r9, r10, [r1, #24]\n\t" + "add sp, sp, #0x60\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + : + : "memory", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); + (void)qz; + (void)qt2d; + (void)qyplusx; + (void)qyminusx; +} + +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) +{ + __asm__ __volatile__ ( + "sub sp, sp, #0x60\n\t" + "str %[rx], [sp]\n\t" + "str %[ry], [sp, #4]\n\t" + "str %[rz], [sp, #8]\n\t" + "str %[rt], [sp, #12]\n\t" + "ldr r0, [sp]\n\t" + "ldr r1, [sp, #172]\n\t" + "ldr r2, [sp, #168]\n\t" + /* Add */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r2]\n\t" + "ldrd r9, r10, [r2, #8]\n\t" + "adds r7, %[rt], r7\n\t" + "adcs r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "adcs r10, r6, r10\n\t" + "strd r7, r8, [r0]\n\t" + "strd r9, r10, [r0, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "ldrd r5, r6, [r1, #24]\n\t" + "ldrd r7, r8, [r2, #16]\n\t" + "ldrd r9, r10, [r2, #24]\n\t" + "adcs r7, %[rt], r7\n\t" + "adcs r8, r4, r8\n\t" + "adcs r9, r5, r9\n\t" + "adc r10, r6, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "sbcs r5, r5, r11\n\t" + "sbcs r6, r6, r11\n\t" + "sbcs r7, r7, r11\n\t" + "sbcs r8, r8, r11\n\t" + "sbcs r9, r9, r11\n\t" + "sbc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r0, [sp, #4]\n\t" + "ldr r1, [sp, #172]\n\t" + "ldr r2, [sp, #168]\n\t" + /* Sub */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r2]\n\t" + "ldrd r9, r10, [r2, #8]\n\t" + "subs r7, %[rt], r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbcs r10, r6, r10\n\t" + "strd r7, r8, [r0]\n\t" + "strd r9, r10, [r0, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "ldrd r5, r6, [r1, #24]\n\t" + "ldrd r7, r8, [r2, #16]\n\t" + "ldrd r9, r10, [r2, #24]\n\t" + "sbcs r7, %[rt], r7\n\t" + "sbcs r8, r4, r8\n\t" + "sbcs r9, r5, r9\n\t" + "sbc r10, r6, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "adcs r5, r5, r11\n\t" + "adcs r6, r6, r11\n\t" + "adcs r7, r7, r11\n\t" + "adcs r8, r8, r11\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r2, [sp, #196]\n\t" + "ldr r1, [sp]\n\t" + "ldr r0, [sp, #8]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #192]\n\t" + "ldr r1, [sp, #4]\n\t" + "ldr r0, [sp, #4]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #180]\n\t" + "ldr r1, [sp, #188]\n\t" + "ldr r0, [sp, #12]\n\t" + "bl fe_mul\n\t" + "ldr r2, [sp, #184]\n\t" + "ldr r1, [sp, #176]\n\t" + "ldr r0, [sp]\n\t" + "bl fe_mul\n\t" + "add r0, sp, #16\n\t" + "ldr r1, [sp]\n\t" + /* Double */ + "ldrd %[rt], r4, [r1]\n\t" + "ldrd r5, r6, [r1, #8]\n\t" + "ldrd r7, r8, [r1, #16]\n\t" + "ldrd r9, r10, [r1, #24]\n\t" + "adds %[rt], %[rt], %[rt]\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adc r10, r10, r10\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "sbcs r5, r5, r11\n\t" + "sbcs r6, r6, r11\n\t" + "sbcs r7, r7, r11\n\t" + "sbcs r8, r8, r11\n\t" + "sbcs r9, r9, r11\n\t" + "sbc r10, r10, lr\n\t" + "strd %[rt], r4, [r0]\n\t" + "strd r5, r6, [r0, #8]\n\t" + "strd r7, r8, [r0, #16]\n\t" + "strd r9, r10, [r0, #24]\n\t" + "ldr r0, [sp, #4]\n\t" + "ldr r1, [sp]\n\t" + "ldr r2, [sp, #8]\n\t" + /* Add-Sub */ + /* Add */ + "ldrd %[rt], r4, [r2]\n\t" + "ldrd r5, r6, [r0]\n\t" + "adds r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0]\n\t" + /* Sub */ + "subs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #8]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #8]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #8]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #16]\n\t" + "ldrd r5, r6, [r0, #16]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #16]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #16]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #24]\n\t" + "ldrd r5, r6, [r0, #24]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "adc r8, r4, r6\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "sbc r10, r4, r6\n\t" + "mov r12, #-19\n\t" + "asr r11, r8, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0]\n\t" + "ldrd %[rt], r4, [r0, #8]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #8]\n\t" + "ldrd %[rt], r4, [r0, #16]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #16]\n\t" + "sbcs r7, r7, r11\n\t" + "sbc r8, r8, lr\n\t" + "strd r7, r8, [r0, #24]\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r1]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1]\n\t" + "ldrd %[rt], r4, [r1, #8]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #16]\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd r9, r10, [r1, #24]\n\t" + "ldr r0, [sp, #12]\n\t" + "ldr r1, [sp, #8]\n\t" + "add r2, sp, #16\n\t" + /* Add-Sub */ + /* Add */ + "ldrd %[rt], r4, [r2]\n\t" + "ldrd r5, r6, [r0]\n\t" + "adds r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0]\n\t" + /* Sub */ + "subs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #8]\n\t" + "ldrd r5, r6, [r0, #8]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #8]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #8]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #16]\n\t" + "ldrd r5, r6, [r0, #16]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "mov r12, #0\n\t" + "adcs r8, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "strd r7, r8, [r0, #16]\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "mov lr, #0\n\t" + "sbcs r10, r4, r6\n\t" + "adc lr, lr, #0\n\t" + "strd r9, r10, [r1, #16]\n\t" + /* Add */ + "ldrd %[rt], r4, [r2, #24]\n\t" + "ldrd r5, r6, [r0, #24]\n\t" + "adds r12, r12, #-1\n\t" + "adcs r7, %[rt], r5\n\t" + "adc r8, r4, r6\n\t" + /* Sub */ + "adds lr, lr, #-1\n\t" + "sbcs r9, %[rt], r5\n\t" + "sbc r10, r4, r6\n\t" + "mov r12, #-19\n\t" + "asr r11, r8, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Sub modulus (if overflow) */ + "ldrd %[rt], r4, [r0]\n\t" + "subs %[rt], %[rt], r12\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0]\n\t" + "ldrd %[rt], r4, [r0, #8]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #8]\n\t" + "ldrd %[rt], r4, [r0, #16]\n\t" + "sbcs %[rt], %[rt], r11\n\t" + "sbcs r4, r4, r11\n\t" + "strd %[rt], r4, [r0, #16]\n\t" + "sbcs r7, r7, r11\n\t" + "sbc r8, r8, lr\n\t" + "strd r7, r8, [r0, #24]\n\t" + "mov r12, #-19\n\t" + "asr r11, r10, #31\n\t" + /* Mask the modulus */ + "and r12, r11, r12\n\t" + "and lr, r11, #0x7fffffff\n\t" + /* Add modulus (if underflow) */ + "ldrd %[rt], r4, [r1]\n\t" + "adds %[rt], %[rt], r12\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1]\n\t" + "ldrd %[rt], r4, [r1, #8]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #8]\n\t" + "ldrd %[rt], r4, [r1, #16]\n\t" + "adcs %[rt], %[rt], r11\n\t" + "adcs r4, r4, r11\n\t" + "strd %[rt], r4, [r1, #16]\n\t" + "adcs r9, r9, r11\n\t" + "adc r10, r10, lr\n\t" + "strd r9, r10, [r1, #24]\n\t" + "add sp, sp, #0x60\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + : + : "memory", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); + (void)qz; + (void)qt2d; + (void)qyplusx; + (void)qyminusx; +} + +#endif /* WOLFSSL_ARMASM */ +#endif /* !__aarch64__ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S new file mode 100644 index 000000000..d2b899c12 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S @@ -0,0 +1,5335 @@ +/* armv8-32-sha512-asm + * + * Copyright (C) 2006-2020 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 + */ + +/* Generated using (from wolfssl): + * cd ../scripts + * ruby ./sha2/sha512.rb arm32 ../wolfssl/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S + */ + +#ifdef WOLFSSL_ARMASM +#ifndef __aarch64__ +#ifdef WOLFSSL_ARMASM_NO_NEON + .text + .type L_SHA512_transform_len_k, %object + .size L_SHA512_transform_len_k, 640 + .align 3 +L_SHA512_transform_len_k: + .word 0xd728ae22 + .word 0x428a2f98 + .word 0x23ef65cd + .word 0x71374491 + .word 0xec4d3b2f + .word 0xb5c0fbcf + .word 0x8189dbbc + .word 0xe9b5dba5 + .word 0xf348b538 + .word 0x3956c25b + .word 0xb605d019 + .word 0x59f111f1 + .word 0xaf194f9b + .word 0x923f82a4 + .word 0xda6d8118 + .word 0xab1c5ed5 + .word 0xa3030242 + .word 0xd807aa98 + .word 0x45706fbe + .word 0x12835b01 + .word 0x4ee4b28c + .word 0x243185be + .word 0xd5ffb4e2 + .word 0x550c7dc3 + .word 0xf27b896f + .word 0x72be5d74 + .word 0x3b1696b1 + .word 0x80deb1fe + .word 0x25c71235 + .word 0x9bdc06a7 + .word 0xcf692694 + .word 0xc19bf174 + .word 0x9ef14ad2 + .word 0xe49b69c1 + .word 0x384f25e3 + .word 0xefbe4786 + .word 0x8b8cd5b5 + .word 0xfc19dc6 + .word 0x77ac9c65 + .word 0x240ca1cc + .word 0x592b0275 + .word 0x2de92c6f + .word 0x6ea6e483 + .word 0x4a7484aa + .word 0xbd41fbd4 + .word 0x5cb0a9dc + .word 0x831153b5 + .word 0x76f988da + .word 0xee66dfab + .word 0x983e5152 + .word 0x2db43210 + .word 0xa831c66d + .word 0x98fb213f + .word 0xb00327c8 + .word 0xbeef0ee4 + .word 0xbf597fc7 + .word 0x3da88fc2 + .word 0xc6e00bf3 + .word 0x930aa725 + .word 0xd5a79147 + .word 0xe003826f + .word 0x6ca6351 + .word 0xa0e6e70 + .word 0x14292967 + .word 0x46d22ffc + .word 0x27b70a85 + .word 0x5c26c926 + .word 0x2e1b2138 + .word 0x5ac42aed + .word 0x4d2c6dfc + .word 0x9d95b3df + .word 0x53380d13 + .word 0x8baf63de + .word 0x650a7354 + .word 0x3c77b2a8 + .word 0x766a0abb + .word 0x47edaee6 + .word 0x81c2c92e + .word 0x1482353b + .word 0x92722c85 + .word 0x4cf10364 + .word 0xa2bfe8a1 + .word 0xbc423001 + .word 0xa81a664b + .word 0xd0f89791 + .word 0xc24b8b70 + .word 0x654be30 + .word 0xc76c51a3 + .word 0xd6ef5218 + .word 0xd192e819 + .word 0x5565a910 + .word 0xd6990624 + .word 0x5771202a + .word 0xf40e3585 + .word 0x32bbd1b8 + .word 0x106aa070 + .word 0xb8d2d0c8 + .word 0x19a4c116 + .word 0x5141ab53 + .word 0x1e376c08 + .word 0xdf8eeb99 + .word 0x2748774c + .word 0xe19b48a8 + .word 0x34b0bcb5 + .word 0xc5c95a63 + .word 0x391c0cb3 + .word 0xe3418acb + .word 0x4ed8aa4a + .word 0x7763e373 + .word 0x5b9cca4f + .word 0xd6b2b8a3 + .word 0x682e6ff3 + .word 0x5defb2fc + .word 0x748f82ee + .word 0x43172f60 + .word 0x78a5636f + .word 0xa1f0ab72 + .word 0x84c87814 + .word 0x1a6439ec + .word 0x8cc70208 + .word 0x23631e28 + .word 0x90befffa + .word 0xde82bde9 + .word 0xa4506ceb + .word 0xb2c67915 + .word 0xbef9a3f7 + .word 0xe372532b + .word 0xc67178f2 + .word 0xea26619c + .word 0xca273ece + .word 0x21c0c207 + .word 0xd186b8c7 + .word 0xcde0eb1e + .word 0xeada7dd6 + .word 0xee6ed178 + .word 0xf57d4f7f + .word 0x72176fba + .word 0x6f067aa + .word 0xa2c898a6 + .word 0xa637dc5 + .word 0xbef90dae + .word 0x113f9804 + .word 0x131c471b + .word 0x1b710b35 + .word 0x23047d84 + .word 0x28db77f5 + .word 0x40c72493 + .word 0x32caab7b + .word 0x15c9bebc + .word 0x3c9ebe0a + .word 0x9c100d4c + .word 0x431d67c4 + .word 0xcb3e42b6 + .word 0x4cc5d4be + .word 0xfc657e2a + .word 0x597f299c + .word 0x3ad6faec + .word 0x5fcb6fab + .word 0x4a475817 + .word 0x6c44198c + .text + .align 2 + .globl Transform_Sha512_Len + .type Transform_Sha512_Len, %function +Transform_Sha512_Len: + push {r4, r5, r6, r7, r8, r9, r10, lr} + sub sp, sp, #0xc0 + adr r3, L_SHA512_transform_len_k + # Copy digest to add in at end + ldr r12, [r0] + ldr lr, [r0, #4] + ldrd r4, r5, [r0, #8] + ldrd r6, r7, [r0, #16] + ldrd r8, r9, [r0, #24] + str r12, [sp, #128] + str lr, [sp, #132] + strd r4, r5, [sp, #136] + strd r6, r7, [sp, #144] + strd r8, r9, [sp, #152] + ldr r12, [r0, #32] + ldr lr, [r0, #36] + ldrd r4, r5, [r0, #40] + ldrd r6, r7, [r0, #48] + ldrd r8, r9, [r0, #56] + str r12, [sp, #160] + str lr, [sp, #164] + strd r4, r5, [sp, #168] + strd r6, r7, [sp, #176] + strd r8, r9, [sp, #184] + # Start of loop processing a block +L_sha512_len_neon_begin: + # Load, Reverse and Store W + ldr r12, [r1] + ldr lr, [r1, #4] + ldrd r4, r5, [r1, #8] + ldrd r6, r7, [r1, #16] + ldrd r8, r9, [r1, #24] + rev r12, r12 + rev lr, lr + rev r4, r4 + rev r5, r5 + rev r6, r6 + rev r7, r7 + rev r8, r8 + rev r9, r9 + str lr, [sp] + str r12, [sp, #4] + str r5, [sp, #8] + str r4, [sp, #12] + str r7, [sp, #16] + str r6, [sp, #20] + str r9, [sp, #24] + str r8, [sp, #28] + ldr r12, [r1, #32] + ldr lr, [r1, #36] + ldrd r4, r5, [r1, #40] + ldrd r6, r7, [r1, #48] + ldrd r8, r9, [r1, #56] + rev r12, r12 + rev lr, lr + rev r4, r4 + rev r5, r5 + rev r6, r6 + rev r7, r7 + rev r8, r8 + rev r9, r9 + str lr, [sp, #32] + str r12, [sp, #36] + str r5, [sp, #40] + str r4, [sp, #44] + str r7, [sp, #48] + str r6, [sp, #52] + str r9, [sp, #56] + str r8, [sp, #60] + ldr r12, [r1, #64] + ldr lr, [r1, #68] + ldrd r4, r5, [r1, #72] + ldrd r6, r7, [r1, #80] + ldrd r8, r9, [r1, #88] + rev r12, r12 + rev lr, lr + rev r4, r4 + rev r5, r5 + rev r6, r6 + rev r7, r7 + rev r8, r8 + rev r9, r9 + str lr, [sp, #64] + str r12, [sp, #68] + str r5, [sp, #72] + str r4, [sp, #76] + str r7, [sp, #80] + str r6, [sp, #84] + str r9, [sp, #88] + str r8, [sp, #92] + ldr r12, [r1, #96] + ldr lr, [r1, #100] + ldrd r4, r5, [r1, #104] + ldrd r6, r7, [r1, #112] + ldrd r8, r9, [r1, #120] + rev r12, r12 + rev lr, lr + rev r4, r4 + rev r5, r5 + rev r6, r6 + rev r7, r7 + rev r8, r8 + rev r9, r9 + str lr, [sp, #96] + str r12, [sp, #100] + str r5, [sp, #104] + str r4, [sp, #108] + str r7, [sp, #112] + str r6, [sp, #116] + str r9, [sp, #120] + str r8, [sp, #124] + # Pre-calc: b ^ c + ldrd r8, r9, [r0, #8] + ldr r12, [r0, #16] + ldr lr, [r0, #20] + eor r8, r8, r12 + eor r9, r9, lr + mov r10, #4 + # Start of 16 rounds +L_sha512_len_neon_start: + # Round 0 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #56] + str lr, [r0, #60] + ldr r12, [r0, #32] + ldr lr, [r0, #36] + ldrd r4, r5, [r0, #40] + ldrd r6, r7, [r0, #48] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + ldrd r6, r7, [sp] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #24] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #56] + str lr, [r0, #60] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0] + ldr lr, [r0, #4] + strd r6, r7, [r0, #24] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0] + ldrd r4, r5, [r0, #8] + str r12, [r0, #56] + str lr, [r0, #60] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #56] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #56] + mov r8, r6 + mov r9, r7 + # Calc new W[0] + ldr r12, [sp, #112] + ldr lr, [sp, #116] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp] + ldr lr, [sp, #4] + ldrd r6, r7, [sp, #72] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp] + str lr, [sp, #4] + ldr r12, [sp, #8] + ldr lr, [sp, #12] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp] + ldr lr, [sp, #4] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp] + str lr, [sp, #4] + # Round 1 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #48] + str lr, [r0, #52] + ldr r12, [r0, #24] + ldr lr, [r0, #28] + ldrd r4, r5, [r0, #32] + ldrd r6, r7, [r0, #40] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + ldrd r6, r7, [sp, #8] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #8] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #16] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #48] + str lr, [r0, #52] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #56] + ldr lr, [r0, #60] + strd r6, r7, [r0, #16] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #56] + ldrd r4, r5, [r0] + str r12, [r0, #48] + str lr, [r0, #52] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #48] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #48] + mov r8, r6 + mov r9, r7 + # Calc new W[1] + ldr r12, [sp, #120] + ldr lr, [sp, #124] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #8] + ldr lr, [sp, #12] + ldrd r6, r7, [sp, #80] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #8] + str lr, [sp, #12] + ldr r12, [sp, #16] + ldr lr, [sp, #20] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #8] + ldr lr, [sp, #12] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #8] + str lr, [sp, #12] + # Round 2 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #40] + str lr, [r0, #44] + ldr r12, [r0, #16] + ldr lr, [r0, #20] + ldrd r4, r5, [r0, #24] + ldrd r6, r7, [r0, #32] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + ldrd r6, r7, [sp, #16] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #16] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #8] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #40] + str lr, [r0, #44] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #48] + ldr lr, [r0, #52] + strd r6, r7, [r0, #8] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #48] + ldrd r4, r5, [r0, #56] + str r12, [r0, #40] + str lr, [r0, #44] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #40] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #40] + mov r8, r6 + mov r9, r7 + # Calc new W[2] + ldr r12, [sp] + ldr lr, [sp, #4] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #16] + ldr lr, [sp, #20] + ldrd r6, r7, [sp, #88] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #16] + str lr, [sp, #20] + ldr r12, [sp, #24] + ldr lr, [sp, #28] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #16] + ldr lr, [sp, #20] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #16] + str lr, [sp, #20] + # Round 3 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #32] + str lr, [r0, #36] + ldr r12, [r0, #8] + ldr lr, [r0, #12] + ldrd r4, r5, [r0, #16] + ldrd r6, r7, [r0, #24] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + ldrd r6, r7, [sp, #24] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #24] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #32] + str lr, [r0, #36] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #40] + ldr lr, [r0, #44] + strd r6, r7, [r0] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #40] + ldrd r4, r5, [r0, #48] + str r12, [r0, #32] + str lr, [r0, #36] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #32] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #32] + mov r8, r6 + mov r9, r7 + # Calc new W[3] + ldr r12, [sp, #8] + ldr lr, [sp, #12] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #24] + ldr lr, [sp, #28] + ldrd r6, r7, [sp, #96] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #24] + str lr, [sp, #28] + ldr r12, [sp, #32] + ldr lr, [sp, #36] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #24] + ldr lr, [sp, #28] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #24] + str lr, [sp, #28] + # Round 4 + ldr r12, [r0] + ldr lr, [r0, #4] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #24] + str lr, [r0, #28] + ldr r12, [r0] + ldr lr, [r0, #4] + ldrd r4, r5, [r0, #8] + ldrd r6, r7, [r0, #16] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + ldrd r6, r7, [sp, #32] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #32] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #56] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #24] + str lr, [r0, #28] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #32] + ldr lr, [r0, #36] + strd r6, r7, [r0, #56] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #32] + ldrd r4, r5, [r0, #40] + str r12, [r0, #24] + str lr, [r0, #28] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #24] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #24] + mov r8, r6 + mov r9, r7 + # Calc new W[4] + ldr r12, [sp, #16] + ldr lr, [sp, #20] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #32] + ldr lr, [sp, #36] + ldrd r6, r7, [sp, #104] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #32] + str lr, [sp, #36] + ldr r12, [sp, #40] + ldr lr, [sp, #44] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #32] + ldr lr, [sp, #36] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #32] + str lr, [sp, #36] + # Round 5 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #16] + str lr, [r0, #20] + ldr r12, [r0, #56] + ldr lr, [r0, #60] + ldrd r4, r5, [r0] + ldrd r6, r7, [r0, #8] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + ldrd r6, r7, [sp, #40] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #40] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #48] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #16] + str lr, [r0, #20] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #24] + ldr lr, [r0, #28] + strd r6, r7, [r0, #48] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #24] + ldrd r4, r5, [r0, #32] + str r12, [r0, #16] + str lr, [r0, #20] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #16] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #16] + mov r8, r6 + mov r9, r7 + # Calc new W[5] + ldr r12, [sp, #24] + ldr lr, [sp, #28] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #40] + ldr lr, [sp, #44] + ldrd r6, r7, [sp, #112] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #40] + str lr, [sp, #44] + ldr r12, [sp, #48] + ldr lr, [sp, #52] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #40] + ldr lr, [sp, #44] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #40] + str lr, [sp, #44] + # Round 6 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #8] + str lr, [r0, #12] + ldr r12, [r0, #48] + ldr lr, [r0, #52] + ldrd r4, r5, [r0, #56] + ldrd r6, r7, [r0] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + ldrd r6, r7, [sp, #48] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #48] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #40] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #8] + str lr, [r0, #12] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #16] + ldr lr, [r0, #20] + strd r6, r7, [r0, #40] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #16] + ldrd r4, r5, [r0, #24] + str r12, [r0, #8] + str lr, [r0, #12] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #8] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #8] + mov r8, r6 + mov r9, r7 + # Calc new W[6] + ldr r12, [sp, #32] + ldr lr, [sp, #36] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #48] + ldr lr, [sp, #52] + ldrd r6, r7, [sp, #120] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #48] + str lr, [sp, #52] + ldr r12, [sp, #56] + ldr lr, [sp, #60] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #48] + ldr lr, [sp, #52] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #48] + str lr, [sp, #52] + # Round 7 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0] + ldr lr, [r0, #4] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0] + str lr, [r0, #4] + ldr r12, [r0, #40] + ldr lr, [r0, #44] + ldrd r4, r5, [r0, #48] + ldrd r6, r7, [r0, #56] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0] + ldr lr, [r0, #4] + ldrd r6, r7, [sp, #56] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #56] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #32] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0] + str lr, [r0, #4] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #8] + ldr lr, [r0, #12] + strd r6, r7, [r0, #32] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0] + ldr lr, [r0, #4] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #8] + ldrd r4, r5, [r0, #16] + str r12, [r0] + str lr, [r0, #4] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0] + mov r8, r6 + mov r9, r7 + # Calc new W[7] + ldr r12, [sp, #40] + ldr lr, [sp, #44] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #56] + ldr lr, [sp, #60] + ldrd r6, r7, [sp] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #56] + str lr, [sp, #60] + ldr r12, [sp, #64] + ldr lr, [sp, #68] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #56] + ldr lr, [sp, #60] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #56] + str lr, [sp, #60] + # Round 8 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #56] + str lr, [r0, #60] + ldr r12, [r0, #32] + ldr lr, [r0, #36] + ldrd r4, r5, [r0, #40] + ldrd r6, r7, [r0, #48] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + ldrd r6, r7, [sp, #64] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #64] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #24] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #56] + str lr, [r0, #60] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0] + ldr lr, [r0, #4] + strd r6, r7, [r0, #24] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0] + ldrd r4, r5, [r0, #8] + str r12, [r0, #56] + str lr, [r0, #60] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #56] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #56] + mov r8, r6 + mov r9, r7 + # Calc new W[8] + ldr r12, [sp, #48] + ldr lr, [sp, #52] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #64] + ldr lr, [sp, #68] + ldrd r6, r7, [sp, #8] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #64] + str lr, [sp, #68] + ldr r12, [sp, #72] + ldr lr, [sp, #76] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #64] + ldr lr, [sp, #68] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #64] + str lr, [sp, #68] + # Round 9 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #48] + str lr, [r0, #52] + ldr r12, [r0, #24] + ldr lr, [r0, #28] + ldrd r4, r5, [r0, #32] + ldrd r6, r7, [r0, #40] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + ldrd r6, r7, [sp, #72] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #72] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #16] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #48] + str lr, [r0, #52] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #56] + ldr lr, [r0, #60] + strd r6, r7, [r0, #16] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #56] + ldrd r4, r5, [r0] + str r12, [r0, #48] + str lr, [r0, #52] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #48] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #48] + mov r8, r6 + mov r9, r7 + # Calc new W[9] + ldr r12, [sp, #56] + ldr lr, [sp, #60] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #72] + ldr lr, [sp, #76] + ldrd r6, r7, [sp, #16] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #72] + str lr, [sp, #76] + ldr r12, [sp, #80] + ldr lr, [sp, #84] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #72] + ldr lr, [sp, #76] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #72] + str lr, [sp, #76] + # Round 10 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #40] + str lr, [r0, #44] + ldr r12, [r0, #16] + ldr lr, [r0, #20] + ldrd r4, r5, [r0, #24] + ldrd r6, r7, [r0, #32] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + ldrd r6, r7, [sp, #80] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #80] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #8] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #40] + str lr, [r0, #44] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #48] + ldr lr, [r0, #52] + strd r6, r7, [r0, #8] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #48] + ldrd r4, r5, [r0, #56] + str r12, [r0, #40] + str lr, [r0, #44] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #40] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #40] + mov r8, r6 + mov r9, r7 + # Calc new W[10] + ldr r12, [sp, #64] + ldr lr, [sp, #68] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #80] + ldr lr, [sp, #84] + ldrd r6, r7, [sp, #24] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #80] + str lr, [sp, #84] + ldr r12, [sp, #88] + ldr lr, [sp, #92] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #80] + ldr lr, [sp, #84] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #80] + str lr, [sp, #84] + # Round 11 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #32] + str lr, [r0, #36] + ldr r12, [r0, #8] + ldr lr, [r0, #12] + ldrd r4, r5, [r0, #16] + ldrd r6, r7, [r0, #24] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + ldrd r6, r7, [sp, #88] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #88] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #32] + str lr, [r0, #36] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #40] + ldr lr, [r0, #44] + strd r6, r7, [r0] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #40] + ldrd r4, r5, [r0, #48] + str r12, [r0, #32] + str lr, [r0, #36] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #32] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #32] + mov r8, r6 + mov r9, r7 + # Calc new W[11] + ldr r12, [sp, #72] + ldr lr, [sp, #76] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #88] + ldr lr, [sp, #92] + ldrd r6, r7, [sp, #32] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #88] + str lr, [sp, #92] + ldr r12, [sp, #96] + ldr lr, [sp, #100] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #88] + ldr lr, [sp, #92] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #88] + str lr, [sp, #92] + # Round 12 + ldr r12, [r0] + ldr lr, [r0, #4] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #24] + str lr, [r0, #28] + ldr r12, [r0] + ldr lr, [r0, #4] + ldrd r4, r5, [r0, #8] + ldrd r6, r7, [r0, #16] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + ldrd r6, r7, [sp, #96] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #96] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #56] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #24] + str lr, [r0, #28] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #32] + ldr lr, [r0, #36] + strd r6, r7, [r0, #56] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #32] + ldrd r4, r5, [r0, #40] + str r12, [r0, #24] + str lr, [r0, #28] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #24] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #24] + mov r8, r6 + mov r9, r7 + # Calc new W[12] + ldr r12, [sp, #80] + ldr lr, [sp, #84] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #96] + ldr lr, [sp, #100] + ldrd r6, r7, [sp, #40] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #96] + str lr, [sp, #100] + ldr r12, [sp, #104] + ldr lr, [sp, #108] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #96] + ldr lr, [sp, #100] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #96] + str lr, [sp, #100] + # Round 13 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #16] + str lr, [r0, #20] + ldr r12, [r0, #56] + ldr lr, [r0, #60] + ldrd r4, r5, [r0] + ldrd r6, r7, [r0, #8] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + ldrd r6, r7, [sp, #104] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #104] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #48] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #16] + str lr, [r0, #20] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #24] + ldr lr, [r0, #28] + strd r6, r7, [r0, #48] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #24] + ldrd r4, r5, [r0, #32] + str r12, [r0, #16] + str lr, [r0, #20] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #16] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #16] + mov r8, r6 + mov r9, r7 + # Calc new W[13] + ldr r12, [sp, #88] + ldr lr, [sp, #92] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #104] + ldr lr, [sp, #108] + ldrd r6, r7, [sp, #48] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #104] + str lr, [sp, #108] + ldr r12, [sp, #112] + ldr lr, [sp, #116] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #104] + ldr lr, [sp, #108] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #104] + str lr, [sp, #108] + # Round 14 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #8] + str lr, [r0, #12] + ldr r12, [r0, #48] + ldr lr, [r0, #52] + ldrd r4, r5, [r0, #56] + ldrd r6, r7, [r0] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + ldrd r6, r7, [sp, #112] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #112] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #40] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #8] + str lr, [r0, #12] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #16] + ldr lr, [r0, #20] + strd r6, r7, [r0, #40] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #16] + ldrd r4, r5, [r0, #24] + str r12, [r0, #8] + str lr, [r0, #12] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #8] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #8] + mov r8, r6 + mov r9, r7 + # Calc new W[14] + ldr r12, [sp, #96] + ldr lr, [sp, #100] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #112] + ldr lr, [sp, #116] + ldrd r6, r7, [sp, #56] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #112] + str lr, [sp, #116] + ldr r12, [sp, #120] + ldr lr, [sp, #124] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #112] + ldr lr, [sp, #116] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #112] + str lr, [sp, #116] + # Round 15 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0] + ldr lr, [r0, #4] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0] + str lr, [r0, #4] + ldr r12, [r0, #40] + ldr lr, [r0, #44] + ldrd r4, r5, [r0, #48] + ldrd r6, r7, [r0, #56] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0] + ldr lr, [r0, #4] + ldrd r6, r7, [sp, #120] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #120] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #32] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0] + str lr, [r0, #4] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #8] + ldr lr, [r0, #12] + strd r6, r7, [r0, #32] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0] + ldr lr, [r0, #4] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #8] + ldrd r4, r5, [r0, #16] + str r12, [r0] + str lr, [r0, #4] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0] + mov r8, r6 + mov r9, r7 + # Calc new W[15] + ldr r12, [sp, #104] + ldr lr, [sp, #108] + lsrs r4, r12, #19 + lsrs r5, lr, #19 + orr r5, r5, r12, lsl #13 + orr r4, r4, lr, lsl #13 + lsls r6, r12, #3 + lsls r7, lr, #3 + orr r7, r7, r12, lsr #29 + orr r6, r6, lr, lsr #29 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #6 + lsrs r7, lr, #6 + orr r6, r6, lr, lsl #26 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #120] + ldr lr, [sp, #124] + ldrd r6, r7, [sp, #64] + adds r12, r12, r4 + adc lr, lr, r5 + adds r12, r12, r6 + adc lr, lr, r7 + str r12, [sp, #120] + str lr, [sp, #124] + ldr r12, [sp] + ldr lr, [sp, #4] + lsrs r4, r12, #1 + lsrs r5, lr, #1 + orr r5, r5, r12, lsl #31 + orr r4, r4, lr, lsl #31 + lsrs r6, r12, #8 + lsrs r7, lr, #8 + orr r7, r7, r12, lsl #24 + orr r6, r6, lr, lsl #24 + eor r5, r5, r7 + eor r4, r4, r6 + lsrs r6, r12, #7 + lsrs r7, lr, #7 + orr r6, r6, lr, lsl #25 + eor r5, r5, r7 + eor r4, r4, r6 + ldr r12, [sp, #120] + ldr lr, [sp, #124] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [sp, #120] + str lr, [sp, #124] + add r3, r3, #0x80 + subs r10, r10, #1 + bne L_sha512_len_neon_start + # Round 0 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #56] + str lr, [r0, #60] + ldr r12, [r0, #32] + ldr lr, [r0, #36] + ldrd r4, r5, [r0, #40] + ldrd r6, r7, [r0, #48] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + ldrd r6, r7, [sp] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #24] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #56] + str lr, [r0, #60] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0] + ldr lr, [r0, #4] + strd r6, r7, [r0, #24] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0] + ldrd r4, r5, [r0, #8] + str r12, [r0, #56] + str lr, [r0, #60] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #56] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #56] + mov r8, r6 + mov r9, r7 + # Round 1 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #48] + str lr, [r0, #52] + ldr r12, [r0, #24] + ldr lr, [r0, #28] + ldrd r4, r5, [r0, #32] + ldrd r6, r7, [r0, #40] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + ldrd r6, r7, [sp, #8] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #8] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #16] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #48] + str lr, [r0, #52] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #56] + ldr lr, [r0, #60] + strd r6, r7, [r0, #16] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #56] + ldrd r4, r5, [r0] + str r12, [r0, #48] + str lr, [r0, #52] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #48] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #48] + mov r8, r6 + mov r9, r7 + # Round 2 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #40] + str lr, [r0, #44] + ldr r12, [r0, #16] + ldr lr, [r0, #20] + ldrd r4, r5, [r0, #24] + ldrd r6, r7, [r0, #32] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + ldrd r6, r7, [sp, #16] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #16] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #8] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #40] + str lr, [r0, #44] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #48] + ldr lr, [r0, #52] + strd r6, r7, [r0, #8] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #48] + ldrd r4, r5, [r0, #56] + str r12, [r0, #40] + str lr, [r0, #44] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #40] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #40] + mov r8, r6 + mov r9, r7 + # Round 3 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #32] + str lr, [r0, #36] + ldr r12, [r0, #8] + ldr lr, [r0, #12] + ldrd r4, r5, [r0, #16] + ldrd r6, r7, [r0, #24] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + ldrd r6, r7, [sp, #24] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #24] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #32] + str lr, [r0, #36] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #40] + ldr lr, [r0, #44] + strd r6, r7, [r0] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #40] + ldrd r4, r5, [r0, #48] + str r12, [r0, #32] + str lr, [r0, #36] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #32] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #32] + mov r8, r6 + mov r9, r7 + # Round 4 + ldr r12, [r0] + ldr lr, [r0, #4] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #24] + str lr, [r0, #28] + ldr r12, [r0] + ldr lr, [r0, #4] + ldrd r4, r5, [r0, #8] + ldrd r6, r7, [r0, #16] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + ldrd r6, r7, [sp, #32] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #32] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #56] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #24] + str lr, [r0, #28] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #32] + ldr lr, [r0, #36] + strd r6, r7, [r0, #56] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #32] + ldrd r4, r5, [r0, #40] + str r12, [r0, #24] + str lr, [r0, #28] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #24] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #24] + mov r8, r6 + mov r9, r7 + # Round 5 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #16] + str lr, [r0, #20] + ldr r12, [r0, #56] + ldr lr, [r0, #60] + ldrd r4, r5, [r0] + ldrd r6, r7, [r0, #8] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + ldrd r6, r7, [sp, #40] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #40] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #48] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #16] + str lr, [r0, #20] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #24] + ldr lr, [r0, #28] + strd r6, r7, [r0, #48] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #24] + ldrd r4, r5, [r0, #32] + str r12, [r0, #16] + str lr, [r0, #20] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #16] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #16] + mov r8, r6 + mov r9, r7 + # Round 6 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #8] + str lr, [r0, #12] + ldr r12, [r0, #48] + ldr lr, [r0, #52] + ldrd r4, r5, [r0, #56] + ldrd r6, r7, [r0] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + ldrd r6, r7, [sp, #48] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #48] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #40] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #8] + str lr, [r0, #12] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #16] + ldr lr, [r0, #20] + strd r6, r7, [r0, #40] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #16] + ldrd r4, r5, [r0, #24] + str r12, [r0, #8] + str lr, [r0, #12] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #8] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #8] + mov r8, r6 + mov r9, r7 + # Round 7 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0] + ldr lr, [r0, #4] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0] + str lr, [r0, #4] + ldr r12, [r0, #40] + ldr lr, [r0, #44] + ldrd r4, r5, [r0, #48] + ldrd r6, r7, [r0, #56] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0] + ldr lr, [r0, #4] + ldrd r6, r7, [sp, #56] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #56] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #32] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0] + str lr, [r0, #4] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #8] + ldr lr, [r0, #12] + strd r6, r7, [r0, #32] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0] + ldr lr, [r0, #4] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #8] + ldrd r4, r5, [r0, #16] + str r12, [r0] + str lr, [r0, #4] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0] + mov r8, r6 + mov r9, r7 + # Round 8 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #56] + str lr, [r0, #60] + ldr r12, [r0, #32] + ldr lr, [r0, #36] + ldrd r4, r5, [r0, #40] + ldrd r6, r7, [r0, #48] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + ldrd r6, r7, [sp, #64] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #64] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #24] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #56] + str lr, [r0, #60] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0] + ldr lr, [r0, #4] + strd r6, r7, [r0, #24] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0] + ldrd r4, r5, [r0, #8] + str r12, [r0, #56] + str lr, [r0, #60] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #56] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #56] + mov r8, r6 + mov r9, r7 + # Round 9 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #48] + str lr, [r0, #52] + ldr r12, [r0, #24] + ldr lr, [r0, #28] + ldrd r4, r5, [r0, #32] + ldrd r6, r7, [r0, #40] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + ldrd r6, r7, [sp, #72] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #72] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #16] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #48] + str lr, [r0, #52] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #56] + ldr lr, [r0, #60] + strd r6, r7, [r0, #16] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #56] + ldrd r4, r5, [r0] + str r12, [r0, #48] + str lr, [r0, #52] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #48] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #48] + mov r8, r6 + mov r9, r7 + # Round 10 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #40] + str lr, [r0, #44] + ldr r12, [r0, #16] + ldr lr, [r0, #20] + ldrd r4, r5, [r0, #24] + ldrd r6, r7, [r0, #32] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + ldrd r6, r7, [sp, #80] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #80] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #8] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #40] + str lr, [r0, #44] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #48] + ldr lr, [r0, #52] + strd r6, r7, [r0, #8] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #48] + ldrd r4, r5, [r0, #56] + str r12, [r0, #40] + str lr, [r0, #44] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #40] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #40] + mov r8, r6 + mov r9, r7 + # Round 11 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #32] + str lr, [r0, #36] + ldr r12, [r0, #8] + ldr lr, [r0, #12] + ldrd r4, r5, [r0, #16] + ldrd r6, r7, [r0, #24] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + ldrd r6, r7, [sp, #88] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #88] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #32] + str lr, [r0, #36] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #40] + ldr lr, [r0, #44] + strd r6, r7, [r0] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #32] + ldr lr, [r0, #36] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #40] + ldrd r4, r5, [r0, #48] + str r12, [r0, #32] + str lr, [r0, #36] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #32] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #32] + mov r8, r6 + mov r9, r7 + # Round 12 + ldr r12, [r0] + ldr lr, [r0, #4] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #24] + str lr, [r0, #28] + ldr r12, [r0] + ldr lr, [r0, #4] + ldrd r4, r5, [r0, #8] + ldrd r6, r7, [r0, #16] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + ldrd r6, r7, [sp, #96] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #96] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #56] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #24] + str lr, [r0, #28] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #32] + ldr lr, [r0, #36] + strd r6, r7, [r0, #56] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #24] + ldr lr, [r0, #28] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #32] + ldrd r4, r5, [r0, #40] + str r12, [r0, #24] + str lr, [r0, #28] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #24] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #24] + mov r8, r6 + mov r9, r7 + # Round 13 + ldr r12, [r0, #56] + ldr lr, [r0, #60] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #16] + str lr, [r0, #20] + ldr r12, [r0, #56] + ldr lr, [r0, #60] + ldrd r4, r5, [r0] + ldrd r6, r7, [r0, #8] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + ldrd r6, r7, [sp, #104] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #104] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #48] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #16] + str lr, [r0, #20] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #24] + ldr lr, [r0, #28] + strd r6, r7, [r0, #48] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #16] + ldr lr, [r0, #20] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #24] + ldrd r4, r5, [r0, #32] + str r12, [r0, #16] + str lr, [r0, #20] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #16] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #16] + mov r8, r6 + mov r9, r7 + # Round 14 + ldr r12, [r0, #48] + ldr lr, [r0, #52] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #8] + str lr, [r0, #12] + ldr r12, [r0, #48] + ldr lr, [r0, #52] + ldrd r4, r5, [r0, #56] + ldrd r6, r7, [r0] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + ldrd r6, r7, [sp, #112] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #112] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #40] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0, #8] + str lr, [r0, #12] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #16] + ldr lr, [r0, #20] + strd r6, r7, [r0, #40] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0, #8] + ldr lr, [r0, #12] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #16] + ldrd r4, r5, [r0, #24] + str r12, [r0, #8] + str lr, [r0, #12] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0, #8] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0, #8] + mov r8, r6 + mov r9, r7 + # Round 15 + ldr r12, [r0, #40] + ldr lr, [r0, #44] + lsrs r4, r12, #14 + lsrs r5, lr, #14 + orr r5, r5, r12, lsl #18 + orr r4, r4, lr, lsl #18 + lsrs r6, r12, #18 + lsrs r7, lr, #18 + orr r7, r7, r12, lsl #14 + orr r6, r6, lr, lsl #14 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #23 + lsls r7, lr, #23 + orr r7, r7, r12, lsr #9 + orr r6, r6, lr, lsr #9 + ldr r12, [r0] + ldr lr, [r0, #4] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0] + str lr, [r0, #4] + ldr r12, [r0, #40] + ldr lr, [r0, #44] + ldrd r4, r5, [r0, #48] + ldrd r6, r7, [r0, #56] + eor r4, r4, r6 + eor r5, r5, r7 + and r4, r4, r12 + and r5, r5, lr + eor r4, r4, r6 + eor r5, r5, r7 + ldr r12, [r0] + ldr lr, [r0, #4] + ldrd r6, r7, [sp, #120] + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r4, r5, [r3, #120] + adds r12, r12, r6 + adc lr, lr, r7 + ldrd r6, r7, [r0, #32] + adds r12, r12, r4 + adc lr, lr, r5 + str r12, [r0] + str lr, [r0, #4] + adds r6, r6, r12 + adc r7, r7, lr + ldr r12, [r0, #8] + ldr lr, [r0, #12] + strd r6, r7, [r0, #32] + lsrs r4, r12, #28 + lsrs r5, lr, #28 + orr r5, r5, r12, lsl #4 + orr r4, r4, lr, lsl #4 + lsls r6, r12, #30 + lsls r7, lr, #30 + orr r7, r7, r12, lsr #2 + orr r6, r6, lr, lsr #2 + eor r4, r4, r6 + eor r5, r5, r7 + lsls r6, r12, #25 + lsls r7, lr, #25 + orr r7, r7, r12, lsr #7 + orr r6, r6, lr, lsr #7 + ldr r12, [r0] + ldr lr, [r0, #4] + eor r4, r4, r6 + eor r5, r5, r7 + adds r12, r12, r4 + adc lr, lr, r5 + ldrd r6, r7, [r0, #8] + ldrd r4, r5, [r0, #16] + str r12, [r0] + str lr, [r0, #4] + eor r6, r6, r4 + eor r7, r7, r5 + and r8, r8, r6 + and r9, r9, r7 + eor r8, r8, r4 + eor r9, r9, r5 + ldrd r4, r5, [r0] + adds r4, r4, r8 + adc r5, r5, r9 + strd r4, r5, [r0] + mov r8, r6 + mov r9, r7 + # Add in digest from start + ldr r12, [r0] + ldr lr, [r0, #4] + ldrd r4, r5, [r0, #8] + ldrd r6, r7, [sp, #128] + ldrd r8, r9, [sp, #136] + adds r12, r12, r6 + adc lr, lr, r7 + adds r4, r4, r8 + adc r5, r5, r9 + str r12, [r0] + str lr, [r0, #4] + strd r4, r5, [r0, #8] + str r12, [sp, #128] + str lr, [sp, #132] + strd r4, r5, [sp, #136] + ldr r12, [r0, #16] + ldr lr, [r0, #20] + ldrd r4, r5, [r0, #24] + ldrd r6, r7, [sp, #144] + ldrd r8, r9, [sp, #152] + adds r12, r12, r6 + adc lr, lr, r7 + adds r4, r4, r8 + adc r5, r5, r9 + str r12, [r0, #16] + str lr, [r0, #20] + strd r4, r5, [r0, #24] + str r12, [sp, #144] + str lr, [sp, #148] + strd r4, r5, [sp, #152] + ldr r12, [r0, #32] + ldr lr, [r0, #36] + ldrd r4, r5, [r0, #40] + ldrd r6, r7, [sp, #160] + ldrd r8, r9, [sp, #168] + adds r12, r12, r6 + adc lr, lr, r7 + adds r4, r4, r8 + adc r5, r5, r9 + str r12, [r0, #32] + str lr, [r0, #36] + strd r4, r5, [r0, #40] + str r12, [sp, #160] + str lr, [sp, #164] + strd r4, r5, [sp, #168] + ldr r12, [r0, #48] + ldr lr, [r0, #52] + ldrd r4, r5, [r0, #56] + ldrd r6, r7, [sp, #176] + ldrd r8, r9, [sp, #184] + adds r12, r12, r6 + adc lr, lr, r7 + adds r4, r4, r8 + adc r5, r5, r9 + str r12, [r0, #48] + str lr, [r0, #52] + strd r4, r5, [r0, #56] + str r12, [sp, #176] + str lr, [sp, #180] + strd r4, r5, [sp, #184] + subs r2, r2, #0x80 + sub r3, r3, #0x200 + add r1, r1, #0x80 + bne L_sha512_len_neon_begin + eor r0, r0, r0 + add sp, sp, #0xc0 + pop {r4, r5, r6, r7, r8, r9, r10, pc} + .size Transform_Sha512_Len,.-Transform_Sha512_Len +#endif /* WOLFSSL_ARMASM_NO_NEON */ +#ifndef WOLFSSL_ARMASM_NO_NEON + .text + .type L_SHA512_transform_neon_len_k, %object + .size L_SHA512_transform_neon_len_k, 640 + .align 3 +L_SHA512_transform_neon_len_k: + .word 0xd728ae22 + .word 0x428a2f98 + .word 0x23ef65cd + .word 0x71374491 + .word 0xec4d3b2f + .word 0xb5c0fbcf + .word 0x8189dbbc + .word 0xe9b5dba5 + .word 0xf348b538 + .word 0x3956c25b + .word 0xb605d019 + .word 0x59f111f1 + .word 0xaf194f9b + .word 0x923f82a4 + .word 0xda6d8118 + .word 0xab1c5ed5 + .word 0xa3030242 + .word 0xd807aa98 + .word 0x45706fbe + .word 0x12835b01 + .word 0x4ee4b28c + .word 0x243185be + .word 0xd5ffb4e2 + .word 0x550c7dc3 + .word 0xf27b896f + .word 0x72be5d74 + .word 0x3b1696b1 + .word 0x80deb1fe + .word 0x25c71235 + .word 0x9bdc06a7 + .word 0xcf692694 + .word 0xc19bf174 + .word 0x9ef14ad2 + .word 0xe49b69c1 + .word 0x384f25e3 + .word 0xefbe4786 + .word 0x8b8cd5b5 + .word 0xfc19dc6 + .word 0x77ac9c65 + .word 0x240ca1cc + .word 0x592b0275 + .word 0x2de92c6f + .word 0x6ea6e483 + .word 0x4a7484aa + .word 0xbd41fbd4 + .word 0x5cb0a9dc + .word 0x831153b5 + .word 0x76f988da + .word 0xee66dfab + .word 0x983e5152 + .word 0x2db43210 + .word 0xa831c66d + .word 0x98fb213f + .word 0xb00327c8 + .word 0xbeef0ee4 + .word 0xbf597fc7 + .word 0x3da88fc2 + .word 0xc6e00bf3 + .word 0x930aa725 + .word 0xd5a79147 + .word 0xe003826f + .word 0x6ca6351 + .word 0xa0e6e70 + .word 0x14292967 + .word 0x46d22ffc + .word 0x27b70a85 + .word 0x5c26c926 + .word 0x2e1b2138 + .word 0x5ac42aed + .word 0x4d2c6dfc + .word 0x9d95b3df + .word 0x53380d13 + .word 0x8baf63de + .word 0x650a7354 + .word 0x3c77b2a8 + .word 0x766a0abb + .word 0x47edaee6 + .word 0x81c2c92e + .word 0x1482353b + .word 0x92722c85 + .word 0x4cf10364 + .word 0xa2bfe8a1 + .word 0xbc423001 + .word 0xa81a664b + .word 0xd0f89791 + .word 0xc24b8b70 + .word 0x654be30 + .word 0xc76c51a3 + .word 0xd6ef5218 + .word 0xd192e819 + .word 0x5565a910 + .word 0xd6990624 + .word 0x5771202a + .word 0xf40e3585 + .word 0x32bbd1b8 + .word 0x106aa070 + .word 0xb8d2d0c8 + .word 0x19a4c116 + .word 0x5141ab53 + .word 0x1e376c08 + .word 0xdf8eeb99 + .word 0x2748774c + .word 0xe19b48a8 + .word 0x34b0bcb5 + .word 0xc5c95a63 + .word 0x391c0cb3 + .word 0xe3418acb + .word 0x4ed8aa4a + .word 0x7763e373 + .word 0x5b9cca4f + .word 0xd6b2b8a3 + .word 0x682e6ff3 + .word 0x5defb2fc + .word 0x748f82ee + .word 0x43172f60 + .word 0x78a5636f + .word 0xa1f0ab72 + .word 0x84c87814 + .word 0x1a6439ec + .word 0x8cc70208 + .word 0x23631e28 + .word 0x90befffa + .word 0xde82bde9 + .word 0xa4506ceb + .word 0xb2c67915 + .word 0xbef9a3f7 + .word 0xe372532b + .word 0xc67178f2 + .word 0xea26619c + .word 0xca273ece + .word 0x21c0c207 + .word 0xd186b8c7 + .word 0xcde0eb1e + .word 0xeada7dd6 + .word 0xee6ed178 + .word 0xf57d4f7f + .word 0x72176fba + .word 0x6f067aa + .word 0xa2c898a6 + .word 0xa637dc5 + .word 0xbef90dae + .word 0x113f9804 + .word 0x131c471b + .word 0x1b710b35 + .word 0x23047d84 + .word 0x28db77f5 + .word 0x40c72493 + .word 0x32caab7b + .word 0x15c9bebc + .word 0x3c9ebe0a + .word 0x9c100d4c + .word 0x431d67c4 + .word 0xcb3e42b6 + .word 0x4cc5d4be + .word 0xfc657e2a + .word 0x597f299c + .word 0x3ad6faec + .word 0x5fcb6fab + .word 0x4a475817 + .word 0x6c44198c + .text + .align 2 + .globl Transform_Sha512_Len + .type Transform_Sha512_Len, %function +Transform_Sha512_Len: + vpush {d8-d15} + # Load digest into working vars + vldm.64 r0, {d0-d7} + # Start of loop processing a block +L_sha512_len_neon_begin: + # Load W + vldm.64 r1!, {d16-d31} + vrev64.8 q8, q8 + vrev64.8 q9, q9 + vrev64.8 q10, q10 + vrev64.8 q11, q11 + vrev64.8 q12, q12 + vrev64.8 q13, q13 + vrev64.8 q14, q14 + vrev64.8 q15, q15 + adr r3, L_SHA512_transform_neon_len_k + mov r12, #4 + # Start of 16 rounds +L_sha512_len_neon_start: + # Round 0 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d4, #50 + vsri.u64 d8, d4, #14 + vshl.u64 d9, d0, #36 + vsri.u64 d9, d0, #28 + vshl.u64 d10, d4, #46 + vsri.u64 d10, d4, #18 + vshl.u64 d11, d0, #30 + vsri.u64 d11, d0, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d4, #23 + vsri.u64 d10, d4, #41 + vshl.u64 d11, d0, #25 + vsri.u64 d11, d0, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d7, d8 + vadd.i64 d12, d16 + vmov d8, d4 + veor d10, d1, d2 + vadd.i64 d7, d12 + vbsl d8, d5, d6 + vbsl d10, d0, d2 + vadd.i64 d7, d8 + vadd.i64 d10, d9 + vadd.i64 d3, d7 + vadd.i64 d7, d10 + # Round 1 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d3, #50 + vsri.u64 d8, d3, #14 + vshl.u64 d9, d7, #36 + vsri.u64 d9, d7, #28 + vshl.u64 d10, d3, #46 + vsri.u64 d10, d3, #18 + vshl.u64 d11, d7, #30 + vsri.u64 d11, d7, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d3, #23 + vsri.u64 d10, d3, #41 + vshl.u64 d11, d7, #25 + vsri.u64 d11, d7, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d6, d8 + vadd.i64 d12, d17 + vmov d8, d3 + veor d10, d0, d1 + vadd.i64 d6, d12 + vbsl d8, d4, d5 + vbsl d10, d7, d1 + vadd.i64 d6, d8 + vadd.i64 d10, d9 + vadd.i64 d2, d6 + vadd.i64 d6, d10 + # Calc new W[0]-W[1] + vext.8 q6, q8, q9, #8 + vshl.u64 q4, q15, #45 + vsri.u64 q4, q15, #19 + vshl.u64 q5, q15, #3 + vsri.u64 q5, q15, #61 + veor q5, q4 + vshr.u64 q4, q15, #6 + veor q5, q4 + vadd.i64 q8, q5 + vext.8 q7, q12, q13, #8 + vadd.i64 q8, q7 + vshl.u64 q4, q6, #63 + vsri.u64 q4, q6, #1 + vshl.u64 q5, q6, #56 + vsri.u64 q5, q6, #8 + veor q5, q4 + vshr.u64 q6, #7 + veor q5, q6 + vadd.i64 q8, q5 + # Round 2 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d2, #50 + vsri.u64 d8, d2, #14 + vshl.u64 d9, d6, #36 + vsri.u64 d9, d6, #28 + vshl.u64 d10, d2, #46 + vsri.u64 d10, d2, #18 + vshl.u64 d11, d6, #30 + vsri.u64 d11, d6, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d2, #23 + vsri.u64 d10, d2, #41 + vshl.u64 d11, d6, #25 + vsri.u64 d11, d6, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d5, d8 + vadd.i64 d12, d18 + vmov d8, d2 + veor d10, d7, d0 + vadd.i64 d5, d12 + vbsl d8, d3, d4 + vbsl d10, d6, d0 + vadd.i64 d5, d8 + vadd.i64 d10, d9 + vadd.i64 d1, d5 + vadd.i64 d5, d10 + # Round 3 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d1, #50 + vsri.u64 d8, d1, #14 + vshl.u64 d9, d5, #36 + vsri.u64 d9, d5, #28 + vshl.u64 d10, d1, #46 + vsri.u64 d10, d1, #18 + vshl.u64 d11, d5, #30 + vsri.u64 d11, d5, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d1, #23 + vsri.u64 d10, d1, #41 + vshl.u64 d11, d5, #25 + vsri.u64 d11, d5, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d4, d8 + vadd.i64 d12, d19 + vmov d8, d1 + veor d10, d6, d7 + vadd.i64 d4, d12 + vbsl d8, d2, d3 + vbsl d10, d5, d7 + vadd.i64 d4, d8 + vadd.i64 d10, d9 + vadd.i64 d0, d4 + vadd.i64 d4, d10 + # Calc new W[2]-W[3] + vext.8 q6, q9, q10, #8 + vshl.u64 q4, q8, #45 + vsri.u64 q4, q8, #19 + vshl.u64 q5, q8, #3 + vsri.u64 q5, q8, #61 + veor q5, q4 + vshr.u64 q4, q8, #6 + veor q5, q4 + vadd.i64 q9, q5 + vext.8 q7, q13, q14, #8 + vadd.i64 q9, q7 + vshl.u64 q4, q6, #63 + vsri.u64 q4, q6, #1 + vshl.u64 q5, q6, #56 + vsri.u64 q5, q6, #8 + veor q5, q4 + vshr.u64 q6, #7 + veor q5, q6 + vadd.i64 q9, q5 + # Round 4 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d0, #50 + vsri.u64 d8, d0, #14 + vshl.u64 d9, d4, #36 + vsri.u64 d9, d4, #28 + vshl.u64 d10, d0, #46 + vsri.u64 d10, d0, #18 + vshl.u64 d11, d4, #30 + vsri.u64 d11, d4, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d0, #23 + vsri.u64 d10, d0, #41 + vshl.u64 d11, d4, #25 + vsri.u64 d11, d4, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d3, d8 + vadd.i64 d12, d20 + vmov d8, d0 + veor d10, d5, d6 + vadd.i64 d3, d12 + vbsl d8, d1, d2 + vbsl d10, d4, d6 + vadd.i64 d3, d8 + vadd.i64 d10, d9 + vadd.i64 d7, d3 + vadd.i64 d3, d10 + # Round 5 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d7, #50 + vsri.u64 d8, d7, #14 + vshl.u64 d9, d3, #36 + vsri.u64 d9, d3, #28 + vshl.u64 d10, d7, #46 + vsri.u64 d10, d7, #18 + vshl.u64 d11, d3, #30 + vsri.u64 d11, d3, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d7, #23 + vsri.u64 d10, d7, #41 + vshl.u64 d11, d3, #25 + vsri.u64 d11, d3, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d2, d8 + vadd.i64 d12, d21 + vmov d8, d7 + veor d10, d4, d5 + vadd.i64 d2, d12 + vbsl d8, d0, d1 + vbsl d10, d3, d5 + vadd.i64 d2, d8 + vadd.i64 d10, d9 + vadd.i64 d6, d2 + vadd.i64 d2, d10 + # Calc new W[4]-W[5] + vext.8 q6, q10, q11, #8 + vshl.u64 q4, q9, #45 + vsri.u64 q4, q9, #19 + vshl.u64 q5, q9, #3 + vsri.u64 q5, q9, #61 + veor q5, q4 + vshr.u64 q4, q9, #6 + veor q5, q4 + vadd.i64 q10, q5 + vext.8 q7, q14, q15, #8 + vadd.i64 q10, q7 + vshl.u64 q4, q6, #63 + vsri.u64 q4, q6, #1 + vshl.u64 q5, q6, #56 + vsri.u64 q5, q6, #8 + veor q5, q4 + vshr.u64 q6, #7 + veor q5, q6 + vadd.i64 q10, q5 + # Round 6 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d6, #50 + vsri.u64 d8, d6, #14 + vshl.u64 d9, d2, #36 + vsri.u64 d9, d2, #28 + vshl.u64 d10, d6, #46 + vsri.u64 d10, d6, #18 + vshl.u64 d11, d2, #30 + vsri.u64 d11, d2, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d6, #23 + vsri.u64 d10, d6, #41 + vshl.u64 d11, d2, #25 + vsri.u64 d11, d2, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d1, d8 + vadd.i64 d12, d22 + vmov d8, d6 + veor d10, d3, d4 + vadd.i64 d1, d12 + vbsl d8, d7, d0 + vbsl d10, d2, d4 + vadd.i64 d1, d8 + vadd.i64 d10, d9 + vadd.i64 d5, d1 + vadd.i64 d1, d10 + # Round 7 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d5, #50 + vsri.u64 d8, d5, #14 + vshl.u64 d9, d1, #36 + vsri.u64 d9, d1, #28 + vshl.u64 d10, d5, #46 + vsri.u64 d10, d5, #18 + vshl.u64 d11, d1, #30 + vsri.u64 d11, d1, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d5, #23 + vsri.u64 d10, d5, #41 + vshl.u64 d11, d1, #25 + vsri.u64 d11, d1, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d0, d8 + vadd.i64 d12, d23 + vmov d8, d5 + veor d10, d2, d3 + vadd.i64 d0, d12 + vbsl d8, d6, d7 + vbsl d10, d1, d3 + vadd.i64 d0, d8 + vadd.i64 d10, d9 + vadd.i64 d4, d0 + vadd.i64 d0, d10 + # Calc new W[6]-W[7] + vext.8 q6, q11, q12, #8 + vshl.u64 q4, q10, #45 + vsri.u64 q4, q10, #19 + vshl.u64 q5, q10, #3 + vsri.u64 q5, q10, #61 + veor q5, q4 + vshr.u64 q4, q10, #6 + veor q5, q4 + vadd.i64 q11, q5 + vext.8 q7, q15, q8, #8 + vadd.i64 q11, q7 + vshl.u64 q4, q6, #63 + vsri.u64 q4, q6, #1 + vshl.u64 q5, q6, #56 + vsri.u64 q5, q6, #8 + veor q5, q4 + vshr.u64 q6, #7 + veor q5, q6 + vadd.i64 q11, q5 + # Round 8 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d4, #50 + vsri.u64 d8, d4, #14 + vshl.u64 d9, d0, #36 + vsri.u64 d9, d0, #28 + vshl.u64 d10, d4, #46 + vsri.u64 d10, d4, #18 + vshl.u64 d11, d0, #30 + vsri.u64 d11, d0, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d4, #23 + vsri.u64 d10, d4, #41 + vshl.u64 d11, d0, #25 + vsri.u64 d11, d0, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d7, d8 + vadd.i64 d12, d24 + vmov d8, d4 + veor d10, d1, d2 + vadd.i64 d7, d12 + vbsl d8, d5, d6 + vbsl d10, d0, d2 + vadd.i64 d7, d8 + vadd.i64 d10, d9 + vadd.i64 d3, d7 + vadd.i64 d7, d10 + # Round 9 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d3, #50 + vsri.u64 d8, d3, #14 + vshl.u64 d9, d7, #36 + vsri.u64 d9, d7, #28 + vshl.u64 d10, d3, #46 + vsri.u64 d10, d3, #18 + vshl.u64 d11, d7, #30 + vsri.u64 d11, d7, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d3, #23 + vsri.u64 d10, d3, #41 + vshl.u64 d11, d7, #25 + vsri.u64 d11, d7, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d6, d8 + vadd.i64 d12, d25 + vmov d8, d3 + veor d10, d0, d1 + vadd.i64 d6, d12 + vbsl d8, d4, d5 + vbsl d10, d7, d1 + vadd.i64 d6, d8 + vadd.i64 d10, d9 + vadd.i64 d2, d6 + vadd.i64 d6, d10 + # Calc new W[8]-W[9] + vext.8 q6, q12, q13, #8 + vshl.u64 q4, q11, #45 + vsri.u64 q4, q11, #19 + vshl.u64 q5, q11, #3 + vsri.u64 q5, q11, #61 + veor q5, q4 + vshr.u64 q4, q11, #6 + veor q5, q4 + vadd.i64 q12, q5 + vext.8 q7, q8, q9, #8 + vadd.i64 q12, q7 + vshl.u64 q4, q6, #63 + vsri.u64 q4, q6, #1 + vshl.u64 q5, q6, #56 + vsri.u64 q5, q6, #8 + veor q5, q4 + vshr.u64 q6, #7 + veor q5, q6 + vadd.i64 q12, q5 + # Round 10 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d2, #50 + vsri.u64 d8, d2, #14 + vshl.u64 d9, d6, #36 + vsri.u64 d9, d6, #28 + vshl.u64 d10, d2, #46 + vsri.u64 d10, d2, #18 + vshl.u64 d11, d6, #30 + vsri.u64 d11, d6, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d2, #23 + vsri.u64 d10, d2, #41 + vshl.u64 d11, d6, #25 + vsri.u64 d11, d6, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d5, d8 + vadd.i64 d12, d26 + vmov d8, d2 + veor d10, d7, d0 + vadd.i64 d5, d12 + vbsl d8, d3, d4 + vbsl d10, d6, d0 + vadd.i64 d5, d8 + vadd.i64 d10, d9 + vadd.i64 d1, d5 + vadd.i64 d5, d10 + # Round 11 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d1, #50 + vsri.u64 d8, d1, #14 + vshl.u64 d9, d5, #36 + vsri.u64 d9, d5, #28 + vshl.u64 d10, d1, #46 + vsri.u64 d10, d1, #18 + vshl.u64 d11, d5, #30 + vsri.u64 d11, d5, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d1, #23 + vsri.u64 d10, d1, #41 + vshl.u64 d11, d5, #25 + vsri.u64 d11, d5, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d4, d8 + vadd.i64 d12, d27 + vmov d8, d1 + veor d10, d6, d7 + vadd.i64 d4, d12 + vbsl d8, d2, d3 + vbsl d10, d5, d7 + vadd.i64 d4, d8 + vadd.i64 d10, d9 + vadd.i64 d0, d4 + vadd.i64 d4, d10 + # Calc new W[10]-W[11] + vext.8 q6, q13, q14, #8 + vshl.u64 q4, q12, #45 + vsri.u64 q4, q12, #19 + vshl.u64 q5, q12, #3 + vsri.u64 q5, q12, #61 + veor q5, q4 + vshr.u64 q4, q12, #6 + veor q5, q4 + vadd.i64 q13, q5 + vext.8 q7, q9, q10, #8 + vadd.i64 q13, q7 + vshl.u64 q4, q6, #63 + vsri.u64 q4, q6, #1 + vshl.u64 q5, q6, #56 + vsri.u64 q5, q6, #8 + veor q5, q4 + vshr.u64 q6, #7 + veor q5, q6 + vadd.i64 q13, q5 + # Round 12 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d0, #50 + vsri.u64 d8, d0, #14 + vshl.u64 d9, d4, #36 + vsri.u64 d9, d4, #28 + vshl.u64 d10, d0, #46 + vsri.u64 d10, d0, #18 + vshl.u64 d11, d4, #30 + vsri.u64 d11, d4, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d0, #23 + vsri.u64 d10, d0, #41 + vshl.u64 d11, d4, #25 + vsri.u64 d11, d4, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d3, d8 + vadd.i64 d12, d28 + vmov d8, d0 + veor d10, d5, d6 + vadd.i64 d3, d12 + vbsl d8, d1, d2 + vbsl d10, d4, d6 + vadd.i64 d3, d8 + vadd.i64 d10, d9 + vadd.i64 d7, d3 + vadd.i64 d3, d10 + # Round 13 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d7, #50 + vsri.u64 d8, d7, #14 + vshl.u64 d9, d3, #36 + vsri.u64 d9, d3, #28 + vshl.u64 d10, d7, #46 + vsri.u64 d10, d7, #18 + vshl.u64 d11, d3, #30 + vsri.u64 d11, d3, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d7, #23 + vsri.u64 d10, d7, #41 + vshl.u64 d11, d3, #25 + vsri.u64 d11, d3, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d2, d8 + vadd.i64 d12, d29 + vmov d8, d7 + veor d10, d4, d5 + vadd.i64 d2, d12 + vbsl d8, d0, d1 + vbsl d10, d3, d5 + vadd.i64 d2, d8 + vadd.i64 d10, d9 + vadd.i64 d6, d2 + vadd.i64 d2, d10 + # Calc new W[12]-W[13] + vext.8 q6, q14, q15, #8 + vshl.u64 q4, q13, #45 + vsri.u64 q4, q13, #19 + vshl.u64 q5, q13, #3 + vsri.u64 q5, q13, #61 + veor q5, q4 + vshr.u64 q4, q13, #6 + veor q5, q4 + vadd.i64 q14, q5 + vext.8 q7, q10, q11, #8 + vadd.i64 q14, q7 + vshl.u64 q4, q6, #63 + vsri.u64 q4, q6, #1 + vshl.u64 q5, q6, #56 + vsri.u64 q5, q6, #8 + veor q5, q4 + vshr.u64 q6, #7 + veor q5, q6 + vadd.i64 q14, q5 + # Round 14 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d6, #50 + vsri.u64 d8, d6, #14 + vshl.u64 d9, d2, #36 + vsri.u64 d9, d2, #28 + vshl.u64 d10, d6, #46 + vsri.u64 d10, d6, #18 + vshl.u64 d11, d2, #30 + vsri.u64 d11, d2, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d6, #23 + vsri.u64 d10, d6, #41 + vshl.u64 d11, d2, #25 + vsri.u64 d11, d2, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d1, d8 + vadd.i64 d12, d30 + vmov d8, d6 + veor d10, d3, d4 + vadd.i64 d1, d12 + vbsl d8, d7, d0 + vbsl d10, d2, d4 + vadd.i64 d1, d8 + vadd.i64 d10, d9 + vadd.i64 d5, d1 + vadd.i64 d1, d10 + # Round 15 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d5, #50 + vsri.u64 d8, d5, #14 + vshl.u64 d9, d1, #36 + vsri.u64 d9, d1, #28 + vshl.u64 d10, d5, #46 + vsri.u64 d10, d5, #18 + vshl.u64 d11, d1, #30 + vsri.u64 d11, d1, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d5, #23 + vsri.u64 d10, d5, #41 + vshl.u64 d11, d1, #25 + vsri.u64 d11, d1, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d0, d8 + vadd.i64 d12, d31 + vmov d8, d5 + veor d10, d2, d3 + vadd.i64 d0, d12 + vbsl d8, d6, d7 + vbsl d10, d1, d3 + vadd.i64 d0, d8 + vadd.i64 d10, d9 + vadd.i64 d4, d0 + vadd.i64 d0, d10 + # Calc new W[14]-W[15] + vext.8 q6, q15, q8, #8 + vshl.u64 q4, q14, #45 + vsri.u64 q4, q14, #19 + vshl.u64 q5, q14, #3 + vsri.u64 q5, q14, #61 + veor q5, q4 + vshr.u64 q4, q14, #6 + veor q5, q4 + vadd.i64 q15, q5 + vext.8 q7, q11, q12, #8 + vadd.i64 q15, q7 + vshl.u64 q4, q6, #63 + vsri.u64 q4, q6, #1 + vshl.u64 q5, q6, #56 + vsri.u64 q5, q6, #8 + veor q5, q4 + vshr.u64 q6, #7 + veor q5, q6 + vadd.i64 q15, q5 + subs r12, r12, #1 + bne L_sha512_len_neon_start + # Round 0 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d4, #50 + vsri.u64 d8, d4, #14 + vshl.u64 d9, d0, #36 + vsri.u64 d9, d0, #28 + vshl.u64 d10, d4, #46 + vsri.u64 d10, d4, #18 + vshl.u64 d11, d0, #30 + vsri.u64 d11, d0, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d4, #23 + vsri.u64 d10, d4, #41 + vshl.u64 d11, d0, #25 + vsri.u64 d11, d0, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d7, d8 + vadd.i64 d12, d16 + vmov d8, d4 + veor d10, d1, d2 + vadd.i64 d7, d12 + vbsl d8, d5, d6 + vbsl d10, d0, d2 + vadd.i64 d7, d8 + vadd.i64 d10, d9 + vadd.i64 d3, d7 + vadd.i64 d7, d10 + # Round 1 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d3, #50 + vsri.u64 d8, d3, #14 + vshl.u64 d9, d7, #36 + vsri.u64 d9, d7, #28 + vshl.u64 d10, d3, #46 + vsri.u64 d10, d3, #18 + vshl.u64 d11, d7, #30 + vsri.u64 d11, d7, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d3, #23 + vsri.u64 d10, d3, #41 + vshl.u64 d11, d7, #25 + vsri.u64 d11, d7, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d6, d8 + vadd.i64 d12, d17 + vmov d8, d3 + veor d10, d0, d1 + vadd.i64 d6, d12 + vbsl d8, d4, d5 + vbsl d10, d7, d1 + vadd.i64 d6, d8 + vadd.i64 d10, d9 + vadd.i64 d2, d6 + vadd.i64 d6, d10 + # Round 2 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d2, #50 + vsri.u64 d8, d2, #14 + vshl.u64 d9, d6, #36 + vsri.u64 d9, d6, #28 + vshl.u64 d10, d2, #46 + vsri.u64 d10, d2, #18 + vshl.u64 d11, d6, #30 + vsri.u64 d11, d6, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d2, #23 + vsri.u64 d10, d2, #41 + vshl.u64 d11, d6, #25 + vsri.u64 d11, d6, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d5, d8 + vadd.i64 d12, d18 + vmov d8, d2 + veor d10, d7, d0 + vadd.i64 d5, d12 + vbsl d8, d3, d4 + vbsl d10, d6, d0 + vadd.i64 d5, d8 + vadd.i64 d10, d9 + vadd.i64 d1, d5 + vadd.i64 d5, d10 + # Round 3 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d1, #50 + vsri.u64 d8, d1, #14 + vshl.u64 d9, d5, #36 + vsri.u64 d9, d5, #28 + vshl.u64 d10, d1, #46 + vsri.u64 d10, d1, #18 + vshl.u64 d11, d5, #30 + vsri.u64 d11, d5, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d1, #23 + vsri.u64 d10, d1, #41 + vshl.u64 d11, d5, #25 + vsri.u64 d11, d5, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d4, d8 + vadd.i64 d12, d19 + vmov d8, d1 + veor d10, d6, d7 + vadd.i64 d4, d12 + vbsl d8, d2, d3 + vbsl d10, d5, d7 + vadd.i64 d4, d8 + vadd.i64 d10, d9 + vadd.i64 d0, d4 + vadd.i64 d4, d10 + # Round 4 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d0, #50 + vsri.u64 d8, d0, #14 + vshl.u64 d9, d4, #36 + vsri.u64 d9, d4, #28 + vshl.u64 d10, d0, #46 + vsri.u64 d10, d0, #18 + vshl.u64 d11, d4, #30 + vsri.u64 d11, d4, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d0, #23 + vsri.u64 d10, d0, #41 + vshl.u64 d11, d4, #25 + vsri.u64 d11, d4, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d3, d8 + vadd.i64 d12, d20 + vmov d8, d0 + veor d10, d5, d6 + vadd.i64 d3, d12 + vbsl d8, d1, d2 + vbsl d10, d4, d6 + vadd.i64 d3, d8 + vadd.i64 d10, d9 + vadd.i64 d7, d3 + vadd.i64 d3, d10 + # Round 5 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d7, #50 + vsri.u64 d8, d7, #14 + vshl.u64 d9, d3, #36 + vsri.u64 d9, d3, #28 + vshl.u64 d10, d7, #46 + vsri.u64 d10, d7, #18 + vshl.u64 d11, d3, #30 + vsri.u64 d11, d3, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d7, #23 + vsri.u64 d10, d7, #41 + vshl.u64 d11, d3, #25 + vsri.u64 d11, d3, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d2, d8 + vadd.i64 d12, d21 + vmov d8, d7 + veor d10, d4, d5 + vadd.i64 d2, d12 + vbsl d8, d0, d1 + vbsl d10, d3, d5 + vadd.i64 d2, d8 + vadd.i64 d10, d9 + vadd.i64 d6, d2 + vadd.i64 d2, d10 + # Round 6 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d6, #50 + vsri.u64 d8, d6, #14 + vshl.u64 d9, d2, #36 + vsri.u64 d9, d2, #28 + vshl.u64 d10, d6, #46 + vsri.u64 d10, d6, #18 + vshl.u64 d11, d2, #30 + vsri.u64 d11, d2, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d6, #23 + vsri.u64 d10, d6, #41 + vshl.u64 d11, d2, #25 + vsri.u64 d11, d2, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d1, d8 + vadd.i64 d12, d22 + vmov d8, d6 + veor d10, d3, d4 + vadd.i64 d1, d12 + vbsl d8, d7, d0 + vbsl d10, d2, d4 + vadd.i64 d1, d8 + vadd.i64 d10, d9 + vadd.i64 d5, d1 + vadd.i64 d1, d10 + # Round 7 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d5, #50 + vsri.u64 d8, d5, #14 + vshl.u64 d9, d1, #36 + vsri.u64 d9, d1, #28 + vshl.u64 d10, d5, #46 + vsri.u64 d10, d5, #18 + vshl.u64 d11, d1, #30 + vsri.u64 d11, d1, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d5, #23 + vsri.u64 d10, d5, #41 + vshl.u64 d11, d1, #25 + vsri.u64 d11, d1, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d0, d8 + vadd.i64 d12, d23 + vmov d8, d5 + veor d10, d2, d3 + vadd.i64 d0, d12 + vbsl d8, d6, d7 + vbsl d10, d1, d3 + vadd.i64 d0, d8 + vadd.i64 d10, d9 + vadd.i64 d4, d0 + vadd.i64 d0, d10 + # Round 8 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d4, #50 + vsri.u64 d8, d4, #14 + vshl.u64 d9, d0, #36 + vsri.u64 d9, d0, #28 + vshl.u64 d10, d4, #46 + vsri.u64 d10, d4, #18 + vshl.u64 d11, d0, #30 + vsri.u64 d11, d0, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d4, #23 + vsri.u64 d10, d4, #41 + vshl.u64 d11, d0, #25 + vsri.u64 d11, d0, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d7, d8 + vadd.i64 d12, d24 + vmov d8, d4 + veor d10, d1, d2 + vadd.i64 d7, d12 + vbsl d8, d5, d6 + vbsl d10, d0, d2 + vadd.i64 d7, d8 + vadd.i64 d10, d9 + vadd.i64 d3, d7 + vadd.i64 d7, d10 + # Round 9 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d3, #50 + vsri.u64 d8, d3, #14 + vshl.u64 d9, d7, #36 + vsri.u64 d9, d7, #28 + vshl.u64 d10, d3, #46 + vsri.u64 d10, d3, #18 + vshl.u64 d11, d7, #30 + vsri.u64 d11, d7, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d3, #23 + vsri.u64 d10, d3, #41 + vshl.u64 d11, d7, #25 + vsri.u64 d11, d7, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d6, d8 + vadd.i64 d12, d25 + vmov d8, d3 + veor d10, d0, d1 + vadd.i64 d6, d12 + vbsl d8, d4, d5 + vbsl d10, d7, d1 + vadd.i64 d6, d8 + vadd.i64 d10, d9 + vadd.i64 d2, d6 + vadd.i64 d6, d10 + # Round 10 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d2, #50 + vsri.u64 d8, d2, #14 + vshl.u64 d9, d6, #36 + vsri.u64 d9, d6, #28 + vshl.u64 d10, d2, #46 + vsri.u64 d10, d2, #18 + vshl.u64 d11, d6, #30 + vsri.u64 d11, d6, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d2, #23 + vsri.u64 d10, d2, #41 + vshl.u64 d11, d6, #25 + vsri.u64 d11, d6, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d5, d8 + vadd.i64 d12, d26 + vmov d8, d2 + veor d10, d7, d0 + vadd.i64 d5, d12 + vbsl d8, d3, d4 + vbsl d10, d6, d0 + vadd.i64 d5, d8 + vadd.i64 d10, d9 + vadd.i64 d1, d5 + vadd.i64 d5, d10 + # Round 11 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d1, #50 + vsri.u64 d8, d1, #14 + vshl.u64 d9, d5, #36 + vsri.u64 d9, d5, #28 + vshl.u64 d10, d1, #46 + vsri.u64 d10, d1, #18 + vshl.u64 d11, d5, #30 + vsri.u64 d11, d5, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d1, #23 + vsri.u64 d10, d1, #41 + vshl.u64 d11, d5, #25 + vsri.u64 d11, d5, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d4, d8 + vadd.i64 d12, d27 + vmov d8, d1 + veor d10, d6, d7 + vadd.i64 d4, d12 + vbsl d8, d2, d3 + vbsl d10, d5, d7 + vadd.i64 d4, d8 + vadd.i64 d10, d9 + vadd.i64 d0, d4 + vadd.i64 d4, d10 + # Round 12 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d0, #50 + vsri.u64 d8, d0, #14 + vshl.u64 d9, d4, #36 + vsri.u64 d9, d4, #28 + vshl.u64 d10, d0, #46 + vsri.u64 d10, d0, #18 + vshl.u64 d11, d4, #30 + vsri.u64 d11, d4, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d0, #23 + vsri.u64 d10, d0, #41 + vshl.u64 d11, d4, #25 + vsri.u64 d11, d4, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d3, d8 + vadd.i64 d12, d28 + vmov d8, d0 + veor d10, d5, d6 + vadd.i64 d3, d12 + vbsl d8, d1, d2 + vbsl d10, d4, d6 + vadd.i64 d3, d8 + vadd.i64 d10, d9 + vadd.i64 d7, d3 + vadd.i64 d3, d10 + # Round 13 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d7, #50 + vsri.u64 d8, d7, #14 + vshl.u64 d9, d3, #36 + vsri.u64 d9, d3, #28 + vshl.u64 d10, d7, #46 + vsri.u64 d10, d7, #18 + vshl.u64 d11, d3, #30 + vsri.u64 d11, d3, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d7, #23 + vsri.u64 d10, d7, #41 + vshl.u64 d11, d3, #25 + vsri.u64 d11, d3, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d2, d8 + vadd.i64 d12, d29 + vmov d8, d7 + veor d10, d4, d5 + vadd.i64 d2, d12 + vbsl d8, d0, d1 + vbsl d10, d3, d5 + vadd.i64 d2, d8 + vadd.i64 d10, d9 + vadd.i64 d6, d2 + vadd.i64 d2, d10 + # Round 14 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d6, #50 + vsri.u64 d8, d6, #14 + vshl.u64 d9, d2, #36 + vsri.u64 d9, d2, #28 + vshl.u64 d10, d6, #46 + vsri.u64 d10, d6, #18 + vshl.u64 d11, d2, #30 + vsri.u64 d11, d2, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d6, #23 + vsri.u64 d10, d6, #41 + vshl.u64 d11, d2, #25 + vsri.u64 d11, d2, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d1, d8 + vadd.i64 d12, d30 + vmov d8, d6 + veor d10, d3, d4 + vadd.i64 d1, d12 + vbsl d8, d7, d0 + vbsl d10, d2, d4 + vadd.i64 d1, d8 + vadd.i64 d10, d9 + vadd.i64 d5, d1 + vadd.i64 d1, d10 + # Round 15 + vld1.64 {d12}, [r3:64]! + vshl.u64 d8, d5, #50 + vsri.u64 d8, d5, #14 + vshl.u64 d9, d1, #36 + vsri.u64 d9, d1, #28 + vshl.u64 d10, d5, #46 + vsri.u64 d10, d5, #18 + vshl.u64 d11, d1, #30 + vsri.u64 d11, d1, #34 + veor d8, d10 + veor d9, d11 + vshl.u64 d10, d5, #23 + vsri.u64 d10, d5, #41 + vshl.u64 d11, d1, #25 + vsri.u64 d11, d1, #39 + veor d8, d10 + veor d9, d11 + vadd.i64 d0, d8 + vadd.i64 d12, d31 + vmov d8, d5 + veor d10, d2, d3 + vadd.i64 d0, d12 + vbsl d8, d6, d7 + vbsl d10, d1, d3 + vadd.i64 d0, d8 + vadd.i64 d10, d9 + vadd.i64 d4, d0 + vadd.i64 d0, d10 + # Add in digest from start + vldm.64 r0, {d8-d15} + vadd.i64 q0, q0, q4 + vadd.i64 q1, q1, q5 + vadd.i64 q2, q2, q6 + vadd.i64 q3, q3, q7 + vstm.64 r0, {d0-d7} + subs r2, r2, #0x80 + bne L_sha512_len_neon_begin + vpop {d8-d15} + bx lr + .size Transform_Sha512_Len,.-Transform_Sha512_Len +#endif /* !WOLFSSL_ARMASM_NO_NEON */ +#endif /* !__aarch64__ */ +#endif /* WOLFSSL_ARMASM */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-sha512-asm.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-sha512-asm.c new file mode 100644 index 000000000..c502a3997 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-32-sha512-asm.c @@ -0,0 +1,4783 @@ +/* armv8-32-sha512-asm + * + * Copyright (C) 2006-2020 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 + */ + +/* Generated using (from wolfssl): + * cd ../scripts + * ruby ./sha2/sha512.rb arm32 ../wolfssl/wolfcrypt/src/port/arm/armv8-32-sha512-asm.c + */ + +#ifndef __aarch64__ +#include + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_ARMASM +#include + +#ifdef WOLFSSL_ARMASM_NO_NEON +static const uint64_t L_SHA512_transform_len_k[] = { + 0x428a2f98d728ae22UL, + 0x7137449123ef65cdUL, + 0xb5c0fbcfec4d3b2fUL, + 0xe9b5dba58189dbbcUL, + 0x3956c25bf348b538UL, + 0x59f111f1b605d019UL, + 0x923f82a4af194f9bUL, + 0xab1c5ed5da6d8118UL, + 0xd807aa98a3030242UL, + 0x12835b0145706fbeUL, + 0x243185be4ee4b28cUL, + 0x550c7dc3d5ffb4e2UL, + 0x72be5d74f27b896fUL, + 0x80deb1fe3b1696b1UL, + 0x9bdc06a725c71235UL, + 0xc19bf174cf692694UL, + 0xe49b69c19ef14ad2UL, + 0xefbe4786384f25e3UL, + 0xfc19dc68b8cd5b5UL, + 0x240ca1cc77ac9c65UL, + 0x2de92c6f592b0275UL, + 0x4a7484aa6ea6e483UL, + 0x5cb0a9dcbd41fbd4UL, + 0x76f988da831153b5UL, + 0x983e5152ee66dfabUL, + 0xa831c66d2db43210UL, + 0xb00327c898fb213fUL, + 0xbf597fc7beef0ee4UL, + 0xc6e00bf33da88fc2UL, + 0xd5a79147930aa725UL, + 0x6ca6351e003826fUL, + 0x142929670a0e6e70UL, + 0x27b70a8546d22ffcUL, + 0x2e1b21385c26c926UL, + 0x4d2c6dfc5ac42aedUL, + 0x53380d139d95b3dfUL, + 0x650a73548baf63deUL, + 0x766a0abb3c77b2a8UL, + 0x81c2c92e47edaee6UL, + 0x92722c851482353bUL, + 0xa2bfe8a14cf10364UL, + 0xa81a664bbc423001UL, + 0xc24b8b70d0f89791UL, + 0xc76c51a30654be30UL, + 0xd192e819d6ef5218UL, + 0xd69906245565a910UL, + 0xf40e35855771202aUL, + 0x106aa07032bbd1b8UL, + 0x19a4c116b8d2d0c8UL, + 0x1e376c085141ab53UL, + 0x2748774cdf8eeb99UL, + 0x34b0bcb5e19b48a8UL, + 0x391c0cb3c5c95a63UL, + 0x4ed8aa4ae3418acbUL, + 0x5b9cca4f7763e373UL, + 0x682e6ff3d6b2b8a3UL, + 0x748f82ee5defb2fcUL, + 0x78a5636f43172f60UL, + 0x84c87814a1f0ab72UL, + 0x8cc702081a6439ecUL, + 0x90befffa23631e28UL, + 0xa4506cebde82bde9UL, + 0xbef9a3f7b2c67915UL, + 0xc67178f2e372532bUL, + 0xca273eceea26619cUL, + 0xd186b8c721c0c207UL, + 0xeada7dd6cde0eb1eUL, + 0xf57d4f7fee6ed178UL, + 0x6f067aa72176fbaUL, + 0xa637dc5a2c898a6UL, + 0x113f9804bef90daeUL, + 0x1b710b35131c471bUL, + 0x28db77f523047d84UL, + 0x32caab7b40c72493UL, + 0x3c9ebe0a15c9bebcUL, + 0x431d67c49c100d4cUL, + 0x4cc5d4becb3e42b6UL, + 0x597f299cfc657e2aUL, + 0x5fcb6fab3ad6faecUL, + 0x6c44198c4a475817UL, +}; + +void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, word32 len) +{ + __asm__ __volatile__ ( + "sub sp, sp, #0xc0\n\t" + "mov r3, %[L_SHA512_transform_len_k]\n\t" + /* Copy digest to add in at end */ + "ldrd r12, lr, [%[sha512]]\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "ldrd r8, r9, [%[sha512], #24]\n\t" + "strd r12, lr, [sp, #128]\n\t" + "strd r4, r5, [sp, #136]\n\t" + "strd r6, r7, [sp, #144]\n\t" + "strd r8, r9, [sp, #152]\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "ldrd r8, r9, [%[sha512], #56]\n\t" + "strd r12, lr, [sp, #160]\n\t" + "strd r4, r5, [sp, #168]\n\t" + "strd r6, r7, [sp, #176]\n\t" + "strd r8, r9, [sp, #184]\n\t" + /* Start of loop processing a block */ + "\n" + "L_sha512_len_neon_begin_%=: \n\t" + /* Load, Reverse and Store W */ + "ldrd r12, lr, [%[data]]\n\t" + "ldrd r4, r5, [%[data], #8]\n\t" + "ldrd r6, r7, [%[data], #16]\n\t" + "ldrd r8, r9, [%[data], #24]\n\t" + "rev r12, r12\n\t" + "rev lr, lr\n\t" + "rev r4, r4\n\t" + "rev r5, r5\n\t" + "rev r6, r6\n\t" + "rev r7, r7\n\t" + "rev r8, r8\n\t" + "rev r9, r9\n\t" + "str lr, [sp]\n\t" + "str r12, [sp, #4]\n\t" + "str r5, [sp, #8]\n\t" + "str r4, [sp, #12]\n\t" + "str r7, [sp, #16]\n\t" + "str r6, [sp, #20]\n\t" + "str r9, [sp, #24]\n\t" + "str r8, [sp, #28]\n\t" + "ldrd r12, lr, [%[data], #32]\n\t" + "ldrd r4, r5, [%[data], #40]\n\t" + "ldrd r6, r7, [%[data], #48]\n\t" + "ldrd r8, r9, [%[data], #56]\n\t" + "rev r12, r12\n\t" + "rev lr, lr\n\t" + "rev r4, r4\n\t" + "rev r5, r5\n\t" + "rev r6, r6\n\t" + "rev r7, r7\n\t" + "rev r8, r8\n\t" + "rev r9, r9\n\t" + "str lr, [sp, #32]\n\t" + "str r12, [sp, #36]\n\t" + "str r5, [sp, #40]\n\t" + "str r4, [sp, #44]\n\t" + "str r7, [sp, #48]\n\t" + "str r6, [sp, #52]\n\t" + "str r9, [sp, #56]\n\t" + "str r8, [sp, #60]\n\t" + "ldrd r12, lr, [%[data], #64]\n\t" + "ldrd r4, r5, [%[data], #72]\n\t" + "ldrd r6, r7, [%[data], #80]\n\t" + "ldrd r8, r9, [%[data], #88]\n\t" + "rev r12, r12\n\t" + "rev lr, lr\n\t" + "rev r4, r4\n\t" + "rev r5, r5\n\t" + "rev r6, r6\n\t" + "rev r7, r7\n\t" + "rev r8, r8\n\t" + "rev r9, r9\n\t" + "str lr, [sp, #64]\n\t" + "str r12, [sp, #68]\n\t" + "str r5, [sp, #72]\n\t" + "str r4, [sp, #76]\n\t" + "str r7, [sp, #80]\n\t" + "str r6, [sp, #84]\n\t" + "str r9, [sp, #88]\n\t" + "str r8, [sp, #92]\n\t" + "ldrd r12, lr, [%[data], #96]\n\t" + "ldrd r4, r5, [%[data], #104]\n\t" + "ldrd r6, r7, [%[data], #112]\n\t" + "ldrd r8, r9, [%[data], #120]\n\t" + "rev r12, r12\n\t" + "rev lr, lr\n\t" + "rev r4, r4\n\t" + "rev r5, r5\n\t" + "rev r6, r6\n\t" + "rev r7, r7\n\t" + "rev r8, r8\n\t" + "rev r9, r9\n\t" + "str lr, [sp, #96]\n\t" + "str r12, [sp, #100]\n\t" + "str r5, [sp, #104]\n\t" + "str r4, [sp, #108]\n\t" + "str r7, [sp, #112]\n\t" + "str r6, [sp, #116]\n\t" + "str r9, [sp, #120]\n\t" + "str r8, [sp, #124]\n\t" + /* Pre-calc: b ^ c */ + "ldrd r8, r9, [%[sha512], #8]\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "eor r8, r8, r12\n\t" + "eor r9, r9, lr\n\t" + "mov r10, #4\n\t" + /* Start of 16 rounds */ + "\n" + "L_sha512_len_neon_start_%=: \n\t" + /* Round 0 */ + "ldrd r12, lr, [%[sha512], #32]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #56]\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "ldrd r6, r7, [sp]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #24]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #56]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "strd r6, r7, [%[sha512], #24]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512]]\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "strd r12, lr, [%[sha512], #56]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #56]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[0] */ + "ldrd r12, lr, [sp, #112]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp]\n\t" + "ldrd r6, r7, [sp, #72]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp]\n\t" + "ldrd r12, lr, [sp, #8]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp]\n\t" + /* Round 1 */ + "ldrd r12, lr, [%[sha512], #24]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "ldrd r4, r5, [%[sha512], #32]\n\t" + "ldrd r6, r7, [%[sha512], #40]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "ldrd r6, r7, [sp, #8]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #8]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "strd r6, r7, [%[sha512], #16]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #56]\n\t" + "ldrd r4, r5, [%[sha512]]\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #48]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #48]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[1] */ + "ldrd r12, lr, [sp, #120]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #8]\n\t" + "ldrd r6, r7, [sp, #80]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #8]\n\t" + "ldrd r12, lr, [sp, #16]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #8]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #8]\n\t" + /* Round 2 */ + "ldrd r12, lr, [%[sha512], #16]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #40]\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "ldrd r6, r7, [%[sha512], #32]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "ldrd r6, r7, [sp, #16]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #16]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #8]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #40]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "strd r6, r7, [%[sha512], #8]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "strd r12, lr, [%[sha512], #40]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #40]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[2] */ + "ldrd r12, lr, [sp]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #16]\n\t" + "ldrd r6, r7, [sp, #88]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #16]\n\t" + "ldrd r12, lr, [sp, #24]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #16]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #16]\n\t" + /* Round 3 */ + "ldrd r12, lr, [%[sha512], #8]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "ldrd r4, r5, [%[sha512], #16]\n\t" + "ldrd r6, r7, [%[sha512], #24]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "ldrd r6, r7, [sp, #24]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #24]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512]]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "strd r6, r7, [%[sha512]]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #40]\n\t" + "ldrd r4, r5, [%[sha512], #48]\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #32]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #32]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[3] */ + "ldrd r12, lr, [sp, #8]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #24]\n\t" + "ldrd r6, r7, [sp, #96]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #24]\n\t" + "ldrd r12, lr, [sp, #32]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #24]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #24]\n\t" + /* Round 4 */ + "ldrd r12, lr, [%[sha512]]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #24]\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "ldrd r6, r7, [sp, #32]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #32]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #56]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #24]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "strd r6, r7, [%[sha512], #56]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #32]\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "strd r12, lr, [%[sha512], #24]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #24]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[4] */ + "ldrd r12, lr, [sp, #16]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #32]\n\t" + "ldrd r6, r7, [sp, #104]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #32]\n\t" + "ldrd r12, lr, [sp, #40]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #32]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #32]\n\t" + /* Round 5 */ + "ldrd r12, lr, [%[sha512], #56]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "ldrd r4, r5, [%[sha512]]\n\t" + "ldrd r6, r7, [%[sha512], #8]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "ldrd r6, r7, [sp, #40]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #40]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "strd r6, r7, [%[sha512], #48]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #24]\n\t" + "ldrd r4, r5, [%[sha512], #32]\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #16]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #16]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[5] */ + "ldrd r12, lr, [sp, #24]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #40]\n\t" + "ldrd r6, r7, [sp, #112]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #40]\n\t" + "ldrd r12, lr, [sp, #48]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #40]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #40]\n\t" + /* Round 6 */ + "ldrd r12, lr, [%[sha512], #48]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #8]\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "ldrd r6, r7, [%[sha512]]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "ldrd r6, r7, [sp, #48]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #48]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #40]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #8]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "strd r6, r7, [%[sha512], #40]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "strd r12, lr, [%[sha512], #8]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #8]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[6] */ + "ldrd r12, lr, [sp, #32]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #48]\n\t" + "ldrd r6, r7, [sp, #120]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #48]\n\t" + "ldrd r12, lr, [sp, #56]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #48]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #48]\n\t" + /* Round 7 */ + "ldrd r12, lr, [%[sha512], #40]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "ldrd r4, r5, [%[sha512], #48]\n\t" + "ldrd r6, r7, [%[sha512], #56]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "ldrd r6, r7, [sp, #56]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #56]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #32]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "strd r6, r7, [%[sha512], #32]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #8]\n\t" + "ldrd r4, r5, [%[sha512], #16]\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512]]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512]]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[7] */ + "ldrd r12, lr, [sp, #40]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #56]\n\t" + "ldrd r6, r7, [sp]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #56]\n\t" + "ldrd r12, lr, [sp, #64]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #56]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #56]\n\t" + /* Round 8 */ + "ldrd r12, lr, [%[sha512], #32]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #56]\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "ldrd r6, r7, [sp, #64]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #64]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #24]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #56]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "strd r6, r7, [%[sha512], #24]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512]]\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "strd r12, lr, [%[sha512], #56]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #56]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[8] */ + "ldrd r12, lr, [sp, #48]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #64]\n\t" + "ldrd r6, r7, [sp, #8]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #64]\n\t" + "ldrd r12, lr, [sp, #72]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #64]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #64]\n\t" + /* Round 9 */ + "ldrd r12, lr, [%[sha512], #24]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "ldrd r4, r5, [%[sha512], #32]\n\t" + "ldrd r6, r7, [%[sha512], #40]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "ldrd r6, r7, [sp, #72]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #72]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "strd r6, r7, [%[sha512], #16]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #56]\n\t" + "ldrd r4, r5, [%[sha512]]\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #48]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #48]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[9] */ + "ldrd r12, lr, [sp, #56]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #72]\n\t" + "ldrd r6, r7, [sp, #16]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #72]\n\t" + "ldrd r12, lr, [sp, #80]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #72]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #72]\n\t" + /* Round 10 */ + "ldrd r12, lr, [%[sha512], #16]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #40]\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "ldrd r6, r7, [%[sha512], #32]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "ldrd r6, r7, [sp, #80]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #80]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #8]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #40]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "strd r6, r7, [%[sha512], #8]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "strd r12, lr, [%[sha512], #40]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #40]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[10] */ + "ldrd r12, lr, [sp, #64]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #80]\n\t" + "ldrd r6, r7, [sp, #24]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #80]\n\t" + "ldrd r12, lr, [sp, #88]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #80]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #80]\n\t" + /* Round 11 */ + "ldrd r12, lr, [%[sha512], #8]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "ldrd r4, r5, [%[sha512], #16]\n\t" + "ldrd r6, r7, [%[sha512], #24]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "ldrd r6, r7, [sp, #88]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #88]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512]]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "strd r6, r7, [%[sha512]]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #40]\n\t" + "ldrd r4, r5, [%[sha512], #48]\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #32]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #32]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[11] */ + "ldrd r12, lr, [sp, #72]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #88]\n\t" + "ldrd r6, r7, [sp, #32]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #88]\n\t" + "ldrd r12, lr, [sp, #96]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #88]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #88]\n\t" + /* Round 12 */ + "ldrd r12, lr, [%[sha512]]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #24]\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "ldrd r6, r7, [sp, #96]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #96]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #56]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #24]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "strd r6, r7, [%[sha512], #56]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #32]\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "strd r12, lr, [%[sha512], #24]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #24]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[12] */ + "ldrd r12, lr, [sp, #80]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #96]\n\t" + "ldrd r6, r7, [sp, #40]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #96]\n\t" + "ldrd r12, lr, [sp, #104]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #96]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #96]\n\t" + /* Round 13 */ + "ldrd r12, lr, [%[sha512], #56]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "ldrd r4, r5, [%[sha512]]\n\t" + "ldrd r6, r7, [%[sha512], #8]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "ldrd r6, r7, [sp, #104]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #104]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "strd r6, r7, [%[sha512], #48]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #24]\n\t" + "ldrd r4, r5, [%[sha512], #32]\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #16]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #16]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[13] */ + "ldrd r12, lr, [sp, #88]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #104]\n\t" + "ldrd r6, r7, [sp, #48]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #104]\n\t" + "ldrd r12, lr, [sp, #112]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #104]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #104]\n\t" + /* Round 14 */ + "ldrd r12, lr, [%[sha512], #48]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #8]\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "ldrd r6, r7, [%[sha512]]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "ldrd r6, r7, [sp, #112]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #112]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #40]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #8]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "strd r6, r7, [%[sha512], #40]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "strd r12, lr, [%[sha512], #8]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #8]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[14] */ + "ldrd r12, lr, [sp, #96]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #112]\n\t" + "ldrd r6, r7, [sp, #56]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #112]\n\t" + "ldrd r12, lr, [sp, #120]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #112]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #112]\n\t" + /* Round 15 */ + "ldrd r12, lr, [%[sha512], #40]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "ldrd r4, r5, [%[sha512], #48]\n\t" + "ldrd r6, r7, [%[sha512], #56]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "ldrd r6, r7, [sp, #120]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #120]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #32]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "strd r6, r7, [%[sha512], #32]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #8]\n\t" + "ldrd r4, r5, [%[sha512], #16]\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512]]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512]]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Calc new W[15] */ + "ldrd r12, lr, [sp, #104]\n\t" + "lsrs r4, r12, #19\n\t" + "lsrs r5, lr, #19\n\t" + "orr r5, r5, r12, lsl 13\n\t" + "orr r4, r4, lr, lsl 13\n\t" + "lsls r6, r12, #3\n\t" + "lsls r7, lr, #3\n\t" + "orr r7, r7, r12, lsr 29\n\t" + "orr r6, r6, lr, lsr 29\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #6\n\t" + "lsrs r7, lr, #6\n\t" + "orr r6, r6, lr, lsl 26\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #120]\n\t" + "ldrd r6, r7, [sp, #64]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "strd r12, lr, [sp, #120]\n\t" + "ldrd r12, lr, [sp]\n\t" + "lsrs r4, r12, #1\n\t" + "lsrs r5, lr, #1\n\t" + "orr r5, r5, r12, lsl 31\n\t" + "orr r4, r4, lr, lsl 31\n\t" + "lsrs r6, r12, #8\n\t" + "lsrs r7, lr, #8\n\t" + "orr r7, r7, r12, lsl 24\n\t" + "orr r6, r6, lr, lsl 24\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "lsrs r6, r12, #7\n\t" + "lsrs r7, lr, #7\n\t" + "orr r6, r6, lr, lsl 25\n\t" + "eor r5, r5, r7\n\t" + "eor r4, r4, r6\n\t" + "ldrd r12, lr, [sp, #120]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [sp, #120]\n\t" + "add r3, r3, #0x80\n\t" + "subs r10, r10, #1\n\t" + "bne L_sha512_len_neon_start_%=\n\t" + /* Round 0 */ + "ldrd r12, lr, [%[sha512], #32]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #56]\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "ldrd r6, r7, [sp]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #24]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #56]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "strd r6, r7, [%[sha512], #24]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512]]\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "strd r12, lr, [%[sha512], #56]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #56]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 1 */ + "ldrd r12, lr, [%[sha512], #24]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "ldrd r4, r5, [%[sha512], #32]\n\t" + "ldrd r6, r7, [%[sha512], #40]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "ldrd r6, r7, [sp, #8]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #8]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "strd r6, r7, [%[sha512], #16]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #56]\n\t" + "ldrd r4, r5, [%[sha512]]\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #48]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #48]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 2 */ + "ldrd r12, lr, [%[sha512], #16]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #40]\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "ldrd r6, r7, [%[sha512], #32]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "ldrd r6, r7, [sp, #16]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #16]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #8]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #40]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "strd r6, r7, [%[sha512], #8]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "strd r12, lr, [%[sha512], #40]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #40]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 3 */ + "ldrd r12, lr, [%[sha512], #8]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "ldrd r4, r5, [%[sha512], #16]\n\t" + "ldrd r6, r7, [%[sha512], #24]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "ldrd r6, r7, [sp, #24]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #24]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512]]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "strd r6, r7, [%[sha512]]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #40]\n\t" + "ldrd r4, r5, [%[sha512], #48]\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #32]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #32]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 4 */ + "ldrd r12, lr, [%[sha512]]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #24]\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "ldrd r6, r7, [sp, #32]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #32]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #56]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #24]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "strd r6, r7, [%[sha512], #56]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #32]\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "strd r12, lr, [%[sha512], #24]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #24]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 5 */ + "ldrd r12, lr, [%[sha512], #56]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "ldrd r4, r5, [%[sha512]]\n\t" + "ldrd r6, r7, [%[sha512], #8]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "ldrd r6, r7, [sp, #40]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #40]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "strd r6, r7, [%[sha512], #48]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #24]\n\t" + "ldrd r4, r5, [%[sha512], #32]\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #16]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #16]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 6 */ + "ldrd r12, lr, [%[sha512], #48]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #8]\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "ldrd r6, r7, [%[sha512]]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "ldrd r6, r7, [sp, #48]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #48]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #40]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #8]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "strd r6, r7, [%[sha512], #40]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "strd r12, lr, [%[sha512], #8]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #8]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 7 */ + "ldrd r12, lr, [%[sha512], #40]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "ldrd r4, r5, [%[sha512], #48]\n\t" + "ldrd r6, r7, [%[sha512], #56]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "ldrd r6, r7, [sp, #56]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #56]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #32]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "strd r6, r7, [%[sha512], #32]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #8]\n\t" + "ldrd r4, r5, [%[sha512], #16]\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512]]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512]]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 8 */ + "ldrd r12, lr, [%[sha512], #32]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #56]\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "ldrd r6, r7, [sp, #64]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #64]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #24]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #56]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "strd r6, r7, [%[sha512], #24]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512]]\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "strd r12, lr, [%[sha512], #56]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #56]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 9 */ + "ldrd r12, lr, [%[sha512], #24]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "ldrd r4, r5, [%[sha512], #32]\n\t" + "ldrd r6, r7, [%[sha512], #40]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "ldrd r6, r7, [sp, #72]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #72]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "strd r6, r7, [%[sha512], #16]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #56]\n\t" + "ldrd r4, r5, [%[sha512]]\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #48]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #48]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 10 */ + "ldrd r12, lr, [%[sha512], #16]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #40]\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "ldrd r6, r7, [%[sha512], #32]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "ldrd r6, r7, [sp, #80]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #80]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #8]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #40]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "strd r6, r7, [%[sha512], #8]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "strd r12, lr, [%[sha512], #40]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #40]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 11 */ + "ldrd r12, lr, [%[sha512], #8]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "ldrd r4, r5, [%[sha512], #16]\n\t" + "ldrd r6, r7, [%[sha512], #24]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "ldrd r6, r7, [sp, #88]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #88]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512]]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "strd r6, r7, [%[sha512]]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #40]\n\t" + "ldrd r4, r5, [%[sha512], #48]\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #32]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #32]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 12 */ + "ldrd r12, lr, [%[sha512]]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #24]\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "ldrd r6, r7, [sp, #96]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #96]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #56]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #24]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "strd r6, r7, [%[sha512], #56]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #32]\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "strd r12, lr, [%[sha512], #24]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #24]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 13 */ + "ldrd r12, lr, [%[sha512], #56]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "ldrd r12, lr, [%[sha512], #56]\n\t" + "ldrd r4, r5, [%[sha512]]\n\t" + "ldrd r6, r7, [%[sha512], #8]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "ldrd r6, r7, [sp, #104]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #104]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #48]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #24]\n\t" + "strd r6, r7, [%[sha512], #48]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #24]\n\t" + "ldrd r4, r5, [%[sha512], #32]\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #16]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #16]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 14 */ + "ldrd r12, lr, [%[sha512], #48]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #8]\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "ldrd r6, r7, [%[sha512]]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "ldrd r6, r7, [sp, #112]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #112]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #40]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512], #8]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "strd r6, r7, [%[sha512], #40]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #16]\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "strd r12, lr, [%[sha512], #8]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512], #8]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Round 15 */ + "ldrd r12, lr, [%[sha512], #40]\n\t" + "lsrs r4, r12, #14\n\t" + "lsrs r5, lr, #14\n\t" + "orr r5, r5, r12, lsl 18\n\t" + "orr r4, r4, lr, lsl 18\n\t" + "lsrs r6, r12, #18\n\t" + "lsrs r7, lr, #18\n\t" + "orr r7, r7, r12, lsl 14\n\t" + "orr r6, r6, lr, lsl 14\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #23\n\t" + "lsls r7, lr, #23\n\t" + "orr r7, r7, r12, lsr 9\n\t" + "orr r6, r6, lr, lsr 9\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "ldrd r12, lr, [%[sha512], #40]\n\t" + "ldrd r4, r5, [%[sha512], #48]\n\t" + "ldrd r6, r7, [%[sha512], #56]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "and r4, r4, r12\n\t" + "and r5, r5, lr\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "ldrd r6, r7, [sp, #120]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r4, r5, [r3, #120]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "ldrd r6, r7, [%[sha512], #32]\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "adds r6, r6, r12\n\t" + "adc r7, r7, lr\n\t" + "ldrd r12, lr, [%[sha512], #8]\n\t" + "strd r6, r7, [%[sha512], #32]\n\t" + "lsrs r4, r12, #28\n\t" + "lsrs r5, lr, #28\n\t" + "orr r5, r5, r12, lsl 4\n\t" + "orr r4, r4, lr, lsl 4\n\t" + "lsls r6, r12, #30\n\t" + "lsls r7, lr, #30\n\t" + "orr r7, r7, r12, lsr 2\n\t" + "orr r6, r6, lr, lsr 2\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "lsls r6, r12, #25\n\t" + "lsls r7, lr, #25\n\t" + "orr r7, r7, r12, lsr 7\n\t" + "orr r6, r6, lr, lsr 7\n\t" + "ldrd r12, lr, [%[sha512]]\n\t" + "eor r4, r4, r6\n\t" + "eor r5, r5, r7\n\t" + "adds r12, r12, r4\n\t" + "adc lr, lr, r5\n\t" + "ldrd r6, r7, [%[sha512], #8]\n\t" + "ldrd r4, r5, [%[sha512], #16]\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "eor r6, r6, r4\n\t" + "eor r7, r7, r5\n\t" + "and r8, r8, r6\n\t" + "and r9, r9, r7\n\t" + "eor r8, r8, r4\n\t" + "eor r9, r9, r5\n\t" + "ldrd r4, r5, [%[sha512]]\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r4, r5, [%[sha512]]\n\t" + "mov r8, r6\n\t" + "mov r9, r7\n\t" + /* Add in digest from start */ + "ldrd r12, lr, [%[sha512]]\n\t" + "ldrd r4, r5, [%[sha512], #8]\n\t" + "ldrd r6, r7, [sp, #128]\n\t" + "ldrd r8, r9, [sp, #136]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r12, lr, [%[sha512]]\n\t" + "strd r4, r5, [%[sha512], #8]\n\t" + "strd r12, lr, [sp, #128]\n\t" + "strd r4, r5, [sp, #136]\n\t" + "ldrd r12, lr, [%[sha512], #16]\n\t" + "ldrd r4, r5, [%[sha512], #24]\n\t" + "ldrd r6, r7, [sp, #144]\n\t" + "ldrd r8, r9, [sp, #152]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r12, lr, [%[sha512], #16]\n\t" + "strd r4, r5, [%[sha512], #24]\n\t" + "strd r12, lr, [sp, #144]\n\t" + "strd r4, r5, [sp, #152]\n\t" + "ldrd r12, lr, [%[sha512], #32]\n\t" + "ldrd r4, r5, [%[sha512], #40]\n\t" + "ldrd r6, r7, [sp, #160]\n\t" + "ldrd r8, r9, [sp, #168]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r12, lr, [%[sha512], #32]\n\t" + "strd r4, r5, [%[sha512], #40]\n\t" + "strd r12, lr, [sp, #160]\n\t" + "strd r4, r5, [sp, #168]\n\t" + "ldrd r12, lr, [%[sha512], #48]\n\t" + "ldrd r4, r5, [%[sha512], #56]\n\t" + "ldrd r6, r7, [sp, #176]\n\t" + "ldrd r8, r9, [sp, #184]\n\t" + "adds r12, r12, r6\n\t" + "adc lr, lr, r7\n\t" + "adds r4, r4, r8\n\t" + "adc r5, r5, r9\n\t" + "strd r12, lr, [%[sha512], #48]\n\t" + "strd r4, r5, [%[sha512], #56]\n\t" + "strd r12, lr, [sp, #176]\n\t" + "strd r4, r5, [sp, #184]\n\t" + "subs %[len], %[len], #0x80\n\t" + "sub r3, r3, #0x200\n\t" + "add %[data], %[data], #0x80\n\t" + "bne L_sha512_len_neon_begin_%=\n\t" + "eor r0, r0, r0\n\t" + "add sp, sp, #0xc0\n\t" + : [sha512] "+r" (sha512), [data] "+r" (data), [len] "+r" (len) + : [L_SHA512_transform_len_k] "r" (L_SHA512_transform_len_k) + : "memory", "r3", "r12", "lr", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +} + +#endif /* WOLFSSL_ARMASM_NO_NEON */ +#include + +#ifndef WOLFSSL_ARMASM_NO_NEON +static const uint64_t L_SHA512_transform_neon_len_k[] = { + 0x428a2f98d728ae22UL, + 0x7137449123ef65cdUL, + 0xb5c0fbcfec4d3b2fUL, + 0xe9b5dba58189dbbcUL, + 0x3956c25bf348b538UL, + 0x59f111f1b605d019UL, + 0x923f82a4af194f9bUL, + 0xab1c5ed5da6d8118UL, + 0xd807aa98a3030242UL, + 0x12835b0145706fbeUL, + 0x243185be4ee4b28cUL, + 0x550c7dc3d5ffb4e2UL, + 0x72be5d74f27b896fUL, + 0x80deb1fe3b1696b1UL, + 0x9bdc06a725c71235UL, + 0xc19bf174cf692694UL, + 0xe49b69c19ef14ad2UL, + 0xefbe4786384f25e3UL, + 0xfc19dc68b8cd5b5UL, + 0x240ca1cc77ac9c65UL, + 0x2de92c6f592b0275UL, + 0x4a7484aa6ea6e483UL, + 0x5cb0a9dcbd41fbd4UL, + 0x76f988da831153b5UL, + 0x983e5152ee66dfabUL, + 0xa831c66d2db43210UL, + 0xb00327c898fb213fUL, + 0xbf597fc7beef0ee4UL, + 0xc6e00bf33da88fc2UL, + 0xd5a79147930aa725UL, + 0x6ca6351e003826fUL, + 0x142929670a0e6e70UL, + 0x27b70a8546d22ffcUL, + 0x2e1b21385c26c926UL, + 0x4d2c6dfc5ac42aedUL, + 0x53380d139d95b3dfUL, + 0x650a73548baf63deUL, + 0x766a0abb3c77b2a8UL, + 0x81c2c92e47edaee6UL, + 0x92722c851482353bUL, + 0xa2bfe8a14cf10364UL, + 0xa81a664bbc423001UL, + 0xc24b8b70d0f89791UL, + 0xc76c51a30654be30UL, + 0xd192e819d6ef5218UL, + 0xd69906245565a910UL, + 0xf40e35855771202aUL, + 0x106aa07032bbd1b8UL, + 0x19a4c116b8d2d0c8UL, + 0x1e376c085141ab53UL, + 0x2748774cdf8eeb99UL, + 0x34b0bcb5e19b48a8UL, + 0x391c0cb3c5c95a63UL, + 0x4ed8aa4ae3418acbUL, + 0x5b9cca4f7763e373UL, + 0x682e6ff3d6b2b8a3UL, + 0x748f82ee5defb2fcUL, + 0x78a5636f43172f60UL, + 0x84c87814a1f0ab72UL, + 0x8cc702081a6439ecUL, + 0x90befffa23631e28UL, + 0xa4506cebde82bde9UL, + 0xbef9a3f7b2c67915UL, + 0xc67178f2e372532bUL, + 0xca273eceea26619cUL, + 0xd186b8c721c0c207UL, + 0xeada7dd6cde0eb1eUL, + 0xf57d4f7fee6ed178UL, + 0x6f067aa72176fbaUL, + 0xa637dc5a2c898a6UL, + 0x113f9804bef90daeUL, + 0x1b710b35131c471bUL, + 0x28db77f523047d84UL, + 0x32caab7b40c72493UL, + 0x3c9ebe0a15c9bebcUL, + 0x431d67c49c100d4cUL, + 0x4cc5d4becb3e42b6UL, + 0x597f299cfc657e2aUL, + 0x5fcb6fab3ad6faecUL, + 0x6c44198c4a475817UL, +}; + +void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, word32 len) +{ + __asm__ __volatile__ ( + /* Load digest into working vars */ + "vldm.64 %[sha512], {d0-d7}\n\t" + /* Start of loop processing a block */ + "\n" + "L_sha512_len_neon_begin_%=: \n\t" + /* Load W */ + "vldm.64 %[data]!, {d16-d31}\n\t" + "vrev64.8 q8, q8\n\t" + "vrev64.8 q9, q9\n\t" + "vrev64.8 q10, q10\n\t" + "vrev64.8 q11, q11\n\t" + "vrev64.8 q12, q12\n\t" + "vrev64.8 q13, q13\n\t" + "vrev64.8 q14, q14\n\t" + "vrev64.8 q15, q15\n\t" + "mov r3, %[L_SHA512_transform_neon_len_k]\n\t" + "mov r12, #4\n\t" + /* Start of 16 rounds */ + "\n" + "L_sha512_len_neon_start_%=: \n\t" + /* Round 0 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d4, #50\n\t" + "vsri.u64 d8, d4, #14\n\t" + "vshl.u64 d9, d0, #36\n\t" + "vsri.u64 d9, d0, #28\n\t" + "vshl.u64 d10, d4, #46\n\t" + "vsri.u64 d10, d4, #18\n\t" + "vshl.u64 d11, d0, #30\n\t" + "vsri.u64 d11, d0, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d4, #23\n\t" + "vsri.u64 d10, d4, #41\n\t" + "vshl.u64 d11, d0, #25\n\t" + "vsri.u64 d11, d0, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d7, d8\n\t" + "vadd.i64 d12, d16\n\t" + "vmov d8, d4\n\t" + "veor d10, d1, d2\n\t" + "vadd.i64 d7, d12\n\t" + "vbsl d8, d5, d6\n\t" + "vbsl d10, d0, d2\n\t" + "vadd.i64 d7, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d3, d7\n\t" + "vadd.i64 d7, d10\n\t" + /* Round 1 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d3, #50\n\t" + "vsri.u64 d8, d3, #14\n\t" + "vshl.u64 d9, d7, #36\n\t" + "vsri.u64 d9, d7, #28\n\t" + "vshl.u64 d10, d3, #46\n\t" + "vsri.u64 d10, d3, #18\n\t" + "vshl.u64 d11, d7, #30\n\t" + "vsri.u64 d11, d7, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d3, #23\n\t" + "vsri.u64 d10, d3, #41\n\t" + "vshl.u64 d11, d7, #25\n\t" + "vsri.u64 d11, d7, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d6, d8\n\t" + "vadd.i64 d12, d17\n\t" + "vmov d8, d3\n\t" + "veor d10, d0, d1\n\t" + "vadd.i64 d6, d12\n\t" + "vbsl d8, d4, d5\n\t" + "vbsl d10, d7, d1\n\t" + "vadd.i64 d6, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d2, d6\n\t" + "vadd.i64 d6, d10\n\t" + /* Calc new W[0]-W[1] */ + "vext.8 q6, q8, q9, #8\n\t" + "vshl.u64 q4, q15, #45\n\t" + "vsri.u64 q4, q15, #19\n\t" + "vshl.u64 q5, q15, #3\n\t" + "vsri.u64 q5, q15, #61\n\t" + "veor q5, q4\n\t" + "vshr.u64 q4, q15, #6\n\t" + "veor q5, q4\n\t" + "vadd.i64 q8, q5\n\t" + "vext.8 q7, q12, q13, #8\n\t" + "vadd.i64 q8, q7\n\t" + "vshl.u64 q4, q6, #63\n\t" + "vsri.u64 q4, q6, #1\n\t" + "vshl.u64 q5, q6, #56\n\t" + "vsri.u64 q5, q6, #8\n\t" + "veor q5, q4\n\t" + "vshr.u64 q6, #7\n\t" + "veor q5, q6\n\t" + "vadd.i64 q8, q5\n\t" + /* Round 2 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d2, #50\n\t" + "vsri.u64 d8, d2, #14\n\t" + "vshl.u64 d9, d6, #36\n\t" + "vsri.u64 d9, d6, #28\n\t" + "vshl.u64 d10, d2, #46\n\t" + "vsri.u64 d10, d2, #18\n\t" + "vshl.u64 d11, d6, #30\n\t" + "vsri.u64 d11, d6, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d2, #23\n\t" + "vsri.u64 d10, d2, #41\n\t" + "vshl.u64 d11, d6, #25\n\t" + "vsri.u64 d11, d6, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d5, d8\n\t" + "vadd.i64 d12, d18\n\t" + "vmov d8, d2\n\t" + "veor d10, d7, d0\n\t" + "vadd.i64 d5, d12\n\t" + "vbsl d8, d3, d4\n\t" + "vbsl d10, d6, d0\n\t" + "vadd.i64 d5, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d1, d5\n\t" + "vadd.i64 d5, d10\n\t" + /* Round 3 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d1, #50\n\t" + "vsri.u64 d8, d1, #14\n\t" + "vshl.u64 d9, d5, #36\n\t" + "vsri.u64 d9, d5, #28\n\t" + "vshl.u64 d10, d1, #46\n\t" + "vsri.u64 d10, d1, #18\n\t" + "vshl.u64 d11, d5, #30\n\t" + "vsri.u64 d11, d5, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d1, #23\n\t" + "vsri.u64 d10, d1, #41\n\t" + "vshl.u64 d11, d5, #25\n\t" + "vsri.u64 d11, d5, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d4, d8\n\t" + "vadd.i64 d12, d19\n\t" + "vmov d8, d1\n\t" + "veor d10, d6, d7\n\t" + "vadd.i64 d4, d12\n\t" + "vbsl d8, d2, d3\n\t" + "vbsl d10, d5, d7\n\t" + "vadd.i64 d4, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d0, d4\n\t" + "vadd.i64 d4, d10\n\t" + /* Calc new W[2]-W[3] */ + "vext.8 q6, q9, q10, #8\n\t" + "vshl.u64 q4, q8, #45\n\t" + "vsri.u64 q4, q8, #19\n\t" + "vshl.u64 q5, q8, #3\n\t" + "vsri.u64 q5, q8, #61\n\t" + "veor q5, q4\n\t" + "vshr.u64 q4, q8, #6\n\t" + "veor q5, q4\n\t" + "vadd.i64 q9, q5\n\t" + "vext.8 q7, q13, q14, #8\n\t" + "vadd.i64 q9, q7\n\t" + "vshl.u64 q4, q6, #63\n\t" + "vsri.u64 q4, q6, #1\n\t" + "vshl.u64 q5, q6, #56\n\t" + "vsri.u64 q5, q6, #8\n\t" + "veor q5, q4\n\t" + "vshr.u64 q6, #7\n\t" + "veor q5, q6\n\t" + "vadd.i64 q9, q5\n\t" + /* Round 4 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d0, #50\n\t" + "vsri.u64 d8, d0, #14\n\t" + "vshl.u64 d9, d4, #36\n\t" + "vsri.u64 d9, d4, #28\n\t" + "vshl.u64 d10, d0, #46\n\t" + "vsri.u64 d10, d0, #18\n\t" + "vshl.u64 d11, d4, #30\n\t" + "vsri.u64 d11, d4, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d0, #23\n\t" + "vsri.u64 d10, d0, #41\n\t" + "vshl.u64 d11, d4, #25\n\t" + "vsri.u64 d11, d4, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d3, d8\n\t" + "vadd.i64 d12, d20\n\t" + "vmov d8, d0\n\t" + "veor d10, d5, d6\n\t" + "vadd.i64 d3, d12\n\t" + "vbsl d8, d1, d2\n\t" + "vbsl d10, d4, d6\n\t" + "vadd.i64 d3, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d7, d3\n\t" + "vadd.i64 d3, d10\n\t" + /* Round 5 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d7, #50\n\t" + "vsri.u64 d8, d7, #14\n\t" + "vshl.u64 d9, d3, #36\n\t" + "vsri.u64 d9, d3, #28\n\t" + "vshl.u64 d10, d7, #46\n\t" + "vsri.u64 d10, d7, #18\n\t" + "vshl.u64 d11, d3, #30\n\t" + "vsri.u64 d11, d3, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d7, #23\n\t" + "vsri.u64 d10, d7, #41\n\t" + "vshl.u64 d11, d3, #25\n\t" + "vsri.u64 d11, d3, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d2, d8\n\t" + "vadd.i64 d12, d21\n\t" + "vmov d8, d7\n\t" + "veor d10, d4, d5\n\t" + "vadd.i64 d2, d12\n\t" + "vbsl d8, d0, d1\n\t" + "vbsl d10, d3, d5\n\t" + "vadd.i64 d2, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d6, d2\n\t" + "vadd.i64 d2, d10\n\t" + /* Calc new W[4]-W[5] */ + "vext.8 q6, q10, q11, #8\n\t" + "vshl.u64 q4, q9, #45\n\t" + "vsri.u64 q4, q9, #19\n\t" + "vshl.u64 q5, q9, #3\n\t" + "vsri.u64 q5, q9, #61\n\t" + "veor q5, q4\n\t" + "vshr.u64 q4, q9, #6\n\t" + "veor q5, q4\n\t" + "vadd.i64 q10, q5\n\t" + "vext.8 q7, q14, q15, #8\n\t" + "vadd.i64 q10, q7\n\t" + "vshl.u64 q4, q6, #63\n\t" + "vsri.u64 q4, q6, #1\n\t" + "vshl.u64 q5, q6, #56\n\t" + "vsri.u64 q5, q6, #8\n\t" + "veor q5, q4\n\t" + "vshr.u64 q6, #7\n\t" + "veor q5, q6\n\t" + "vadd.i64 q10, q5\n\t" + /* Round 6 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d6, #50\n\t" + "vsri.u64 d8, d6, #14\n\t" + "vshl.u64 d9, d2, #36\n\t" + "vsri.u64 d9, d2, #28\n\t" + "vshl.u64 d10, d6, #46\n\t" + "vsri.u64 d10, d6, #18\n\t" + "vshl.u64 d11, d2, #30\n\t" + "vsri.u64 d11, d2, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d6, #23\n\t" + "vsri.u64 d10, d6, #41\n\t" + "vshl.u64 d11, d2, #25\n\t" + "vsri.u64 d11, d2, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d1, d8\n\t" + "vadd.i64 d12, d22\n\t" + "vmov d8, d6\n\t" + "veor d10, d3, d4\n\t" + "vadd.i64 d1, d12\n\t" + "vbsl d8, d7, d0\n\t" + "vbsl d10, d2, d4\n\t" + "vadd.i64 d1, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d5, d1\n\t" + "vadd.i64 d1, d10\n\t" + /* Round 7 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d5, #50\n\t" + "vsri.u64 d8, d5, #14\n\t" + "vshl.u64 d9, d1, #36\n\t" + "vsri.u64 d9, d1, #28\n\t" + "vshl.u64 d10, d5, #46\n\t" + "vsri.u64 d10, d5, #18\n\t" + "vshl.u64 d11, d1, #30\n\t" + "vsri.u64 d11, d1, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d5, #23\n\t" + "vsri.u64 d10, d5, #41\n\t" + "vshl.u64 d11, d1, #25\n\t" + "vsri.u64 d11, d1, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d0, d8\n\t" + "vadd.i64 d12, d23\n\t" + "vmov d8, d5\n\t" + "veor d10, d2, d3\n\t" + "vadd.i64 d0, d12\n\t" + "vbsl d8, d6, d7\n\t" + "vbsl d10, d1, d3\n\t" + "vadd.i64 d0, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d4, d0\n\t" + "vadd.i64 d0, d10\n\t" + /* Calc new W[6]-W[7] */ + "vext.8 q6, q11, q12, #8\n\t" + "vshl.u64 q4, q10, #45\n\t" + "vsri.u64 q4, q10, #19\n\t" + "vshl.u64 q5, q10, #3\n\t" + "vsri.u64 q5, q10, #61\n\t" + "veor q5, q4\n\t" + "vshr.u64 q4, q10, #6\n\t" + "veor q5, q4\n\t" + "vadd.i64 q11, q5\n\t" + "vext.8 q7, q15, q8, #8\n\t" + "vadd.i64 q11, q7\n\t" + "vshl.u64 q4, q6, #63\n\t" + "vsri.u64 q4, q6, #1\n\t" + "vshl.u64 q5, q6, #56\n\t" + "vsri.u64 q5, q6, #8\n\t" + "veor q5, q4\n\t" + "vshr.u64 q6, #7\n\t" + "veor q5, q6\n\t" + "vadd.i64 q11, q5\n\t" + /* Round 8 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d4, #50\n\t" + "vsri.u64 d8, d4, #14\n\t" + "vshl.u64 d9, d0, #36\n\t" + "vsri.u64 d9, d0, #28\n\t" + "vshl.u64 d10, d4, #46\n\t" + "vsri.u64 d10, d4, #18\n\t" + "vshl.u64 d11, d0, #30\n\t" + "vsri.u64 d11, d0, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d4, #23\n\t" + "vsri.u64 d10, d4, #41\n\t" + "vshl.u64 d11, d0, #25\n\t" + "vsri.u64 d11, d0, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d7, d8\n\t" + "vadd.i64 d12, d24\n\t" + "vmov d8, d4\n\t" + "veor d10, d1, d2\n\t" + "vadd.i64 d7, d12\n\t" + "vbsl d8, d5, d6\n\t" + "vbsl d10, d0, d2\n\t" + "vadd.i64 d7, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d3, d7\n\t" + "vadd.i64 d7, d10\n\t" + /* Round 9 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d3, #50\n\t" + "vsri.u64 d8, d3, #14\n\t" + "vshl.u64 d9, d7, #36\n\t" + "vsri.u64 d9, d7, #28\n\t" + "vshl.u64 d10, d3, #46\n\t" + "vsri.u64 d10, d3, #18\n\t" + "vshl.u64 d11, d7, #30\n\t" + "vsri.u64 d11, d7, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d3, #23\n\t" + "vsri.u64 d10, d3, #41\n\t" + "vshl.u64 d11, d7, #25\n\t" + "vsri.u64 d11, d7, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d6, d8\n\t" + "vadd.i64 d12, d25\n\t" + "vmov d8, d3\n\t" + "veor d10, d0, d1\n\t" + "vadd.i64 d6, d12\n\t" + "vbsl d8, d4, d5\n\t" + "vbsl d10, d7, d1\n\t" + "vadd.i64 d6, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d2, d6\n\t" + "vadd.i64 d6, d10\n\t" + /* Calc new W[8]-W[9] */ + "vext.8 q6, q12, q13, #8\n\t" + "vshl.u64 q4, q11, #45\n\t" + "vsri.u64 q4, q11, #19\n\t" + "vshl.u64 q5, q11, #3\n\t" + "vsri.u64 q5, q11, #61\n\t" + "veor q5, q4\n\t" + "vshr.u64 q4, q11, #6\n\t" + "veor q5, q4\n\t" + "vadd.i64 q12, q5\n\t" + "vext.8 q7, q8, q9, #8\n\t" + "vadd.i64 q12, q7\n\t" + "vshl.u64 q4, q6, #63\n\t" + "vsri.u64 q4, q6, #1\n\t" + "vshl.u64 q5, q6, #56\n\t" + "vsri.u64 q5, q6, #8\n\t" + "veor q5, q4\n\t" + "vshr.u64 q6, #7\n\t" + "veor q5, q6\n\t" + "vadd.i64 q12, q5\n\t" + /* Round 10 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d2, #50\n\t" + "vsri.u64 d8, d2, #14\n\t" + "vshl.u64 d9, d6, #36\n\t" + "vsri.u64 d9, d6, #28\n\t" + "vshl.u64 d10, d2, #46\n\t" + "vsri.u64 d10, d2, #18\n\t" + "vshl.u64 d11, d6, #30\n\t" + "vsri.u64 d11, d6, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d2, #23\n\t" + "vsri.u64 d10, d2, #41\n\t" + "vshl.u64 d11, d6, #25\n\t" + "vsri.u64 d11, d6, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d5, d8\n\t" + "vadd.i64 d12, d26\n\t" + "vmov d8, d2\n\t" + "veor d10, d7, d0\n\t" + "vadd.i64 d5, d12\n\t" + "vbsl d8, d3, d4\n\t" + "vbsl d10, d6, d0\n\t" + "vadd.i64 d5, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d1, d5\n\t" + "vadd.i64 d5, d10\n\t" + /* Round 11 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d1, #50\n\t" + "vsri.u64 d8, d1, #14\n\t" + "vshl.u64 d9, d5, #36\n\t" + "vsri.u64 d9, d5, #28\n\t" + "vshl.u64 d10, d1, #46\n\t" + "vsri.u64 d10, d1, #18\n\t" + "vshl.u64 d11, d5, #30\n\t" + "vsri.u64 d11, d5, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d1, #23\n\t" + "vsri.u64 d10, d1, #41\n\t" + "vshl.u64 d11, d5, #25\n\t" + "vsri.u64 d11, d5, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d4, d8\n\t" + "vadd.i64 d12, d27\n\t" + "vmov d8, d1\n\t" + "veor d10, d6, d7\n\t" + "vadd.i64 d4, d12\n\t" + "vbsl d8, d2, d3\n\t" + "vbsl d10, d5, d7\n\t" + "vadd.i64 d4, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d0, d4\n\t" + "vadd.i64 d4, d10\n\t" + /* Calc new W[10]-W[11] */ + "vext.8 q6, q13, q14, #8\n\t" + "vshl.u64 q4, q12, #45\n\t" + "vsri.u64 q4, q12, #19\n\t" + "vshl.u64 q5, q12, #3\n\t" + "vsri.u64 q5, q12, #61\n\t" + "veor q5, q4\n\t" + "vshr.u64 q4, q12, #6\n\t" + "veor q5, q4\n\t" + "vadd.i64 q13, q5\n\t" + "vext.8 q7, q9, q10, #8\n\t" + "vadd.i64 q13, q7\n\t" + "vshl.u64 q4, q6, #63\n\t" + "vsri.u64 q4, q6, #1\n\t" + "vshl.u64 q5, q6, #56\n\t" + "vsri.u64 q5, q6, #8\n\t" + "veor q5, q4\n\t" + "vshr.u64 q6, #7\n\t" + "veor q5, q6\n\t" + "vadd.i64 q13, q5\n\t" + /* Round 12 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d0, #50\n\t" + "vsri.u64 d8, d0, #14\n\t" + "vshl.u64 d9, d4, #36\n\t" + "vsri.u64 d9, d4, #28\n\t" + "vshl.u64 d10, d0, #46\n\t" + "vsri.u64 d10, d0, #18\n\t" + "vshl.u64 d11, d4, #30\n\t" + "vsri.u64 d11, d4, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d0, #23\n\t" + "vsri.u64 d10, d0, #41\n\t" + "vshl.u64 d11, d4, #25\n\t" + "vsri.u64 d11, d4, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d3, d8\n\t" + "vadd.i64 d12, d28\n\t" + "vmov d8, d0\n\t" + "veor d10, d5, d6\n\t" + "vadd.i64 d3, d12\n\t" + "vbsl d8, d1, d2\n\t" + "vbsl d10, d4, d6\n\t" + "vadd.i64 d3, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d7, d3\n\t" + "vadd.i64 d3, d10\n\t" + /* Round 13 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d7, #50\n\t" + "vsri.u64 d8, d7, #14\n\t" + "vshl.u64 d9, d3, #36\n\t" + "vsri.u64 d9, d3, #28\n\t" + "vshl.u64 d10, d7, #46\n\t" + "vsri.u64 d10, d7, #18\n\t" + "vshl.u64 d11, d3, #30\n\t" + "vsri.u64 d11, d3, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d7, #23\n\t" + "vsri.u64 d10, d7, #41\n\t" + "vshl.u64 d11, d3, #25\n\t" + "vsri.u64 d11, d3, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d2, d8\n\t" + "vadd.i64 d12, d29\n\t" + "vmov d8, d7\n\t" + "veor d10, d4, d5\n\t" + "vadd.i64 d2, d12\n\t" + "vbsl d8, d0, d1\n\t" + "vbsl d10, d3, d5\n\t" + "vadd.i64 d2, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d6, d2\n\t" + "vadd.i64 d2, d10\n\t" + /* Calc new W[12]-W[13] */ + "vext.8 q6, q14, q15, #8\n\t" + "vshl.u64 q4, q13, #45\n\t" + "vsri.u64 q4, q13, #19\n\t" + "vshl.u64 q5, q13, #3\n\t" + "vsri.u64 q5, q13, #61\n\t" + "veor q5, q4\n\t" + "vshr.u64 q4, q13, #6\n\t" + "veor q5, q4\n\t" + "vadd.i64 q14, q5\n\t" + "vext.8 q7, q10, q11, #8\n\t" + "vadd.i64 q14, q7\n\t" + "vshl.u64 q4, q6, #63\n\t" + "vsri.u64 q4, q6, #1\n\t" + "vshl.u64 q5, q6, #56\n\t" + "vsri.u64 q5, q6, #8\n\t" + "veor q5, q4\n\t" + "vshr.u64 q6, #7\n\t" + "veor q5, q6\n\t" + "vadd.i64 q14, q5\n\t" + /* Round 14 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d6, #50\n\t" + "vsri.u64 d8, d6, #14\n\t" + "vshl.u64 d9, d2, #36\n\t" + "vsri.u64 d9, d2, #28\n\t" + "vshl.u64 d10, d6, #46\n\t" + "vsri.u64 d10, d6, #18\n\t" + "vshl.u64 d11, d2, #30\n\t" + "vsri.u64 d11, d2, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d6, #23\n\t" + "vsri.u64 d10, d6, #41\n\t" + "vshl.u64 d11, d2, #25\n\t" + "vsri.u64 d11, d2, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d1, d8\n\t" + "vadd.i64 d12, d30\n\t" + "vmov d8, d6\n\t" + "veor d10, d3, d4\n\t" + "vadd.i64 d1, d12\n\t" + "vbsl d8, d7, d0\n\t" + "vbsl d10, d2, d4\n\t" + "vadd.i64 d1, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d5, d1\n\t" + "vadd.i64 d1, d10\n\t" + /* Round 15 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d5, #50\n\t" + "vsri.u64 d8, d5, #14\n\t" + "vshl.u64 d9, d1, #36\n\t" + "vsri.u64 d9, d1, #28\n\t" + "vshl.u64 d10, d5, #46\n\t" + "vsri.u64 d10, d5, #18\n\t" + "vshl.u64 d11, d1, #30\n\t" + "vsri.u64 d11, d1, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d5, #23\n\t" + "vsri.u64 d10, d5, #41\n\t" + "vshl.u64 d11, d1, #25\n\t" + "vsri.u64 d11, d1, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d0, d8\n\t" + "vadd.i64 d12, d31\n\t" + "vmov d8, d5\n\t" + "veor d10, d2, d3\n\t" + "vadd.i64 d0, d12\n\t" + "vbsl d8, d6, d7\n\t" + "vbsl d10, d1, d3\n\t" + "vadd.i64 d0, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d4, d0\n\t" + "vadd.i64 d0, d10\n\t" + /* Calc new W[14]-W[15] */ + "vext.8 q6, q15, q8, #8\n\t" + "vshl.u64 q4, q14, #45\n\t" + "vsri.u64 q4, q14, #19\n\t" + "vshl.u64 q5, q14, #3\n\t" + "vsri.u64 q5, q14, #61\n\t" + "veor q5, q4\n\t" + "vshr.u64 q4, q14, #6\n\t" + "veor q5, q4\n\t" + "vadd.i64 q15, q5\n\t" + "vext.8 q7, q11, q12, #8\n\t" + "vadd.i64 q15, q7\n\t" + "vshl.u64 q4, q6, #63\n\t" + "vsri.u64 q4, q6, #1\n\t" + "vshl.u64 q5, q6, #56\n\t" + "vsri.u64 q5, q6, #8\n\t" + "veor q5, q4\n\t" + "vshr.u64 q6, #7\n\t" + "veor q5, q6\n\t" + "vadd.i64 q15, q5\n\t" + "subs r12, r12, #1\n\t" + "bne L_sha512_len_neon_start_%=\n\t" + /* Round 0 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d4, #50\n\t" + "vsri.u64 d8, d4, #14\n\t" + "vshl.u64 d9, d0, #36\n\t" + "vsri.u64 d9, d0, #28\n\t" + "vshl.u64 d10, d4, #46\n\t" + "vsri.u64 d10, d4, #18\n\t" + "vshl.u64 d11, d0, #30\n\t" + "vsri.u64 d11, d0, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d4, #23\n\t" + "vsri.u64 d10, d4, #41\n\t" + "vshl.u64 d11, d0, #25\n\t" + "vsri.u64 d11, d0, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d7, d8\n\t" + "vadd.i64 d12, d16\n\t" + "vmov d8, d4\n\t" + "veor d10, d1, d2\n\t" + "vadd.i64 d7, d12\n\t" + "vbsl d8, d5, d6\n\t" + "vbsl d10, d0, d2\n\t" + "vadd.i64 d7, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d3, d7\n\t" + "vadd.i64 d7, d10\n\t" + /* Round 1 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d3, #50\n\t" + "vsri.u64 d8, d3, #14\n\t" + "vshl.u64 d9, d7, #36\n\t" + "vsri.u64 d9, d7, #28\n\t" + "vshl.u64 d10, d3, #46\n\t" + "vsri.u64 d10, d3, #18\n\t" + "vshl.u64 d11, d7, #30\n\t" + "vsri.u64 d11, d7, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d3, #23\n\t" + "vsri.u64 d10, d3, #41\n\t" + "vshl.u64 d11, d7, #25\n\t" + "vsri.u64 d11, d7, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d6, d8\n\t" + "vadd.i64 d12, d17\n\t" + "vmov d8, d3\n\t" + "veor d10, d0, d1\n\t" + "vadd.i64 d6, d12\n\t" + "vbsl d8, d4, d5\n\t" + "vbsl d10, d7, d1\n\t" + "vadd.i64 d6, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d2, d6\n\t" + "vadd.i64 d6, d10\n\t" + /* Round 2 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d2, #50\n\t" + "vsri.u64 d8, d2, #14\n\t" + "vshl.u64 d9, d6, #36\n\t" + "vsri.u64 d9, d6, #28\n\t" + "vshl.u64 d10, d2, #46\n\t" + "vsri.u64 d10, d2, #18\n\t" + "vshl.u64 d11, d6, #30\n\t" + "vsri.u64 d11, d6, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d2, #23\n\t" + "vsri.u64 d10, d2, #41\n\t" + "vshl.u64 d11, d6, #25\n\t" + "vsri.u64 d11, d6, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d5, d8\n\t" + "vadd.i64 d12, d18\n\t" + "vmov d8, d2\n\t" + "veor d10, d7, d0\n\t" + "vadd.i64 d5, d12\n\t" + "vbsl d8, d3, d4\n\t" + "vbsl d10, d6, d0\n\t" + "vadd.i64 d5, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d1, d5\n\t" + "vadd.i64 d5, d10\n\t" + /* Round 3 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d1, #50\n\t" + "vsri.u64 d8, d1, #14\n\t" + "vshl.u64 d9, d5, #36\n\t" + "vsri.u64 d9, d5, #28\n\t" + "vshl.u64 d10, d1, #46\n\t" + "vsri.u64 d10, d1, #18\n\t" + "vshl.u64 d11, d5, #30\n\t" + "vsri.u64 d11, d5, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d1, #23\n\t" + "vsri.u64 d10, d1, #41\n\t" + "vshl.u64 d11, d5, #25\n\t" + "vsri.u64 d11, d5, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d4, d8\n\t" + "vadd.i64 d12, d19\n\t" + "vmov d8, d1\n\t" + "veor d10, d6, d7\n\t" + "vadd.i64 d4, d12\n\t" + "vbsl d8, d2, d3\n\t" + "vbsl d10, d5, d7\n\t" + "vadd.i64 d4, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d0, d4\n\t" + "vadd.i64 d4, d10\n\t" + /* Round 4 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d0, #50\n\t" + "vsri.u64 d8, d0, #14\n\t" + "vshl.u64 d9, d4, #36\n\t" + "vsri.u64 d9, d4, #28\n\t" + "vshl.u64 d10, d0, #46\n\t" + "vsri.u64 d10, d0, #18\n\t" + "vshl.u64 d11, d4, #30\n\t" + "vsri.u64 d11, d4, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d0, #23\n\t" + "vsri.u64 d10, d0, #41\n\t" + "vshl.u64 d11, d4, #25\n\t" + "vsri.u64 d11, d4, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d3, d8\n\t" + "vadd.i64 d12, d20\n\t" + "vmov d8, d0\n\t" + "veor d10, d5, d6\n\t" + "vadd.i64 d3, d12\n\t" + "vbsl d8, d1, d2\n\t" + "vbsl d10, d4, d6\n\t" + "vadd.i64 d3, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d7, d3\n\t" + "vadd.i64 d3, d10\n\t" + /* Round 5 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d7, #50\n\t" + "vsri.u64 d8, d7, #14\n\t" + "vshl.u64 d9, d3, #36\n\t" + "vsri.u64 d9, d3, #28\n\t" + "vshl.u64 d10, d7, #46\n\t" + "vsri.u64 d10, d7, #18\n\t" + "vshl.u64 d11, d3, #30\n\t" + "vsri.u64 d11, d3, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d7, #23\n\t" + "vsri.u64 d10, d7, #41\n\t" + "vshl.u64 d11, d3, #25\n\t" + "vsri.u64 d11, d3, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d2, d8\n\t" + "vadd.i64 d12, d21\n\t" + "vmov d8, d7\n\t" + "veor d10, d4, d5\n\t" + "vadd.i64 d2, d12\n\t" + "vbsl d8, d0, d1\n\t" + "vbsl d10, d3, d5\n\t" + "vadd.i64 d2, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d6, d2\n\t" + "vadd.i64 d2, d10\n\t" + /* Round 6 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d6, #50\n\t" + "vsri.u64 d8, d6, #14\n\t" + "vshl.u64 d9, d2, #36\n\t" + "vsri.u64 d9, d2, #28\n\t" + "vshl.u64 d10, d6, #46\n\t" + "vsri.u64 d10, d6, #18\n\t" + "vshl.u64 d11, d2, #30\n\t" + "vsri.u64 d11, d2, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d6, #23\n\t" + "vsri.u64 d10, d6, #41\n\t" + "vshl.u64 d11, d2, #25\n\t" + "vsri.u64 d11, d2, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d1, d8\n\t" + "vadd.i64 d12, d22\n\t" + "vmov d8, d6\n\t" + "veor d10, d3, d4\n\t" + "vadd.i64 d1, d12\n\t" + "vbsl d8, d7, d0\n\t" + "vbsl d10, d2, d4\n\t" + "vadd.i64 d1, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d5, d1\n\t" + "vadd.i64 d1, d10\n\t" + /* Round 7 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d5, #50\n\t" + "vsri.u64 d8, d5, #14\n\t" + "vshl.u64 d9, d1, #36\n\t" + "vsri.u64 d9, d1, #28\n\t" + "vshl.u64 d10, d5, #46\n\t" + "vsri.u64 d10, d5, #18\n\t" + "vshl.u64 d11, d1, #30\n\t" + "vsri.u64 d11, d1, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d5, #23\n\t" + "vsri.u64 d10, d5, #41\n\t" + "vshl.u64 d11, d1, #25\n\t" + "vsri.u64 d11, d1, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d0, d8\n\t" + "vadd.i64 d12, d23\n\t" + "vmov d8, d5\n\t" + "veor d10, d2, d3\n\t" + "vadd.i64 d0, d12\n\t" + "vbsl d8, d6, d7\n\t" + "vbsl d10, d1, d3\n\t" + "vadd.i64 d0, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d4, d0\n\t" + "vadd.i64 d0, d10\n\t" + /* Round 8 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d4, #50\n\t" + "vsri.u64 d8, d4, #14\n\t" + "vshl.u64 d9, d0, #36\n\t" + "vsri.u64 d9, d0, #28\n\t" + "vshl.u64 d10, d4, #46\n\t" + "vsri.u64 d10, d4, #18\n\t" + "vshl.u64 d11, d0, #30\n\t" + "vsri.u64 d11, d0, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d4, #23\n\t" + "vsri.u64 d10, d4, #41\n\t" + "vshl.u64 d11, d0, #25\n\t" + "vsri.u64 d11, d0, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d7, d8\n\t" + "vadd.i64 d12, d24\n\t" + "vmov d8, d4\n\t" + "veor d10, d1, d2\n\t" + "vadd.i64 d7, d12\n\t" + "vbsl d8, d5, d6\n\t" + "vbsl d10, d0, d2\n\t" + "vadd.i64 d7, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d3, d7\n\t" + "vadd.i64 d7, d10\n\t" + /* Round 9 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d3, #50\n\t" + "vsri.u64 d8, d3, #14\n\t" + "vshl.u64 d9, d7, #36\n\t" + "vsri.u64 d9, d7, #28\n\t" + "vshl.u64 d10, d3, #46\n\t" + "vsri.u64 d10, d3, #18\n\t" + "vshl.u64 d11, d7, #30\n\t" + "vsri.u64 d11, d7, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d3, #23\n\t" + "vsri.u64 d10, d3, #41\n\t" + "vshl.u64 d11, d7, #25\n\t" + "vsri.u64 d11, d7, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d6, d8\n\t" + "vadd.i64 d12, d25\n\t" + "vmov d8, d3\n\t" + "veor d10, d0, d1\n\t" + "vadd.i64 d6, d12\n\t" + "vbsl d8, d4, d5\n\t" + "vbsl d10, d7, d1\n\t" + "vadd.i64 d6, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d2, d6\n\t" + "vadd.i64 d6, d10\n\t" + /* Round 10 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d2, #50\n\t" + "vsri.u64 d8, d2, #14\n\t" + "vshl.u64 d9, d6, #36\n\t" + "vsri.u64 d9, d6, #28\n\t" + "vshl.u64 d10, d2, #46\n\t" + "vsri.u64 d10, d2, #18\n\t" + "vshl.u64 d11, d6, #30\n\t" + "vsri.u64 d11, d6, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d2, #23\n\t" + "vsri.u64 d10, d2, #41\n\t" + "vshl.u64 d11, d6, #25\n\t" + "vsri.u64 d11, d6, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d5, d8\n\t" + "vadd.i64 d12, d26\n\t" + "vmov d8, d2\n\t" + "veor d10, d7, d0\n\t" + "vadd.i64 d5, d12\n\t" + "vbsl d8, d3, d4\n\t" + "vbsl d10, d6, d0\n\t" + "vadd.i64 d5, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d1, d5\n\t" + "vadd.i64 d5, d10\n\t" + /* Round 11 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d1, #50\n\t" + "vsri.u64 d8, d1, #14\n\t" + "vshl.u64 d9, d5, #36\n\t" + "vsri.u64 d9, d5, #28\n\t" + "vshl.u64 d10, d1, #46\n\t" + "vsri.u64 d10, d1, #18\n\t" + "vshl.u64 d11, d5, #30\n\t" + "vsri.u64 d11, d5, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d1, #23\n\t" + "vsri.u64 d10, d1, #41\n\t" + "vshl.u64 d11, d5, #25\n\t" + "vsri.u64 d11, d5, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d4, d8\n\t" + "vadd.i64 d12, d27\n\t" + "vmov d8, d1\n\t" + "veor d10, d6, d7\n\t" + "vadd.i64 d4, d12\n\t" + "vbsl d8, d2, d3\n\t" + "vbsl d10, d5, d7\n\t" + "vadd.i64 d4, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d0, d4\n\t" + "vadd.i64 d4, d10\n\t" + /* Round 12 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d0, #50\n\t" + "vsri.u64 d8, d0, #14\n\t" + "vshl.u64 d9, d4, #36\n\t" + "vsri.u64 d9, d4, #28\n\t" + "vshl.u64 d10, d0, #46\n\t" + "vsri.u64 d10, d0, #18\n\t" + "vshl.u64 d11, d4, #30\n\t" + "vsri.u64 d11, d4, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d0, #23\n\t" + "vsri.u64 d10, d0, #41\n\t" + "vshl.u64 d11, d4, #25\n\t" + "vsri.u64 d11, d4, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d3, d8\n\t" + "vadd.i64 d12, d28\n\t" + "vmov d8, d0\n\t" + "veor d10, d5, d6\n\t" + "vadd.i64 d3, d12\n\t" + "vbsl d8, d1, d2\n\t" + "vbsl d10, d4, d6\n\t" + "vadd.i64 d3, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d7, d3\n\t" + "vadd.i64 d3, d10\n\t" + /* Round 13 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d7, #50\n\t" + "vsri.u64 d8, d7, #14\n\t" + "vshl.u64 d9, d3, #36\n\t" + "vsri.u64 d9, d3, #28\n\t" + "vshl.u64 d10, d7, #46\n\t" + "vsri.u64 d10, d7, #18\n\t" + "vshl.u64 d11, d3, #30\n\t" + "vsri.u64 d11, d3, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d7, #23\n\t" + "vsri.u64 d10, d7, #41\n\t" + "vshl.u64 d11, d3, #25\n\t" + "vsri.u64 d11, d3, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d2, d8\n\t" + "vadd.i64 d12, d29\n\t" + "vmov d8, d7\n\t" + "veor d10, d4, d5\n\t" + "vadd.i64 d2, d12\n\t" + "vbsl d8, d0, d1\n\t" + "vbsl d10, d3, d5\n\t" + "vadd.i64 d2, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d6, d2\n\t" + "vadd.i64 d2, d10\n\t" + /* Round 14 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d6, #50\n\t" + "vsri.u64 d8, d6, #14\n\t" + "vshl.u64 d9, d2, #36\n\t" + "vsri.u64 d9, d2, #28\n\t" + "vshl.u64 d10, d6, #46\n\t" + "vsri.u64 d10, d6, #18\n\t" + "vshl.u64 d11, d2, #30\n\t" + "vsri.u64 d11, d2, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d6, #23\n\t" + "vsri.u64 d10, d6, #41\n\t" + "vshl.u64 d11, d2, #25\n\t" + "vsri.u64 d11, d2, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d1, d8\n\t" + "vadd.i64 d12, d30\n\t" + "vmov d8, d6\n\t" + "veor d10, d3, d4\n\t" + "vadd.i64 d1, d12\n\t" + "vbsl d8, d7, d0\n\t" + "vbsl d10, d2, d4\n\t" + "vadd.i64 d1, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d5, d1\n\t" + "vadd.i64 d1, d10\n\t" + /* Round 15 */ + "vld1.64 {d12}, [r3]!\n\t" + "vshl.u64 d8, d5, #50\n\t" + "vsri.u64 d8, d5, #14\n\t" + "vshl.u64 d9, d1, #36\n\t" + "vsri.u64 d9, d1, #28\n\t" + "vshl.u64 d10, d5, #46\n\t" + "vsri.u64 d10, d5, #18\n\t" + "vshl.u64 d11, d1, #30\n\t" + "vsri.u64 d11, d1, #34\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vshl.u64 d10, d5, #23\n\t" + "vsri.u64 d10, d5, #41\n\t" + "vshl.u64 d11, d1, #25\n\t" + "vsri.u64 d11, d1, #39\n\t" + "veor d8, d10\n\t" + "veor d9, d11\n\t" + "vadd.i64 d0, d8\n\t" + "vadd.i64 d12, d31\n\t" + "vmov d8, d5\n\t" + "veor d10, d2, d3\n\t" + "vadd.i64 d0, d12\n\t" + "vbsl d8, d6, d7\n\t" + "vbsl d10, d1, d3\n\t" + "vadd.i64 d0, d8\n\t" + "vadd.i64 d10, d9\n\t" + "vadd.i64 d4, d0\n\t" + "vadd.i64 d0, d10\n\t" + /* Add in digest from start */ + "vldm.64 %[sha512], {d8-d15}\n\t" + "vadd.i64 q0, q0, q4\n\t" + "vadd.i64 q1, q1, q5\n\t" + "vadd.i64 q2, q2, q6\n\t" + "vadd.i64 q3, q3, q7\n\t" + "vstm.64 %[sha512], {d0-d7}\n\t" + "subs %[len], %[len], #0x80\n\t" + "bne L_sha512_len_neon_begin_%=\n\t" + : [sha512] "+r" (sha512), [data] "+r" (data), [len] "+r" (len) + : [L_SHA512_transform_len_k] "r" (L_SHA512_transform_len_k), [L_SHA512_transform_neon_len_k] "r" (L_SHA512_transform_neon_len_k) + : "memory", "r3", "r12", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + ); +} + +#endif /* !WOLFSSL_ARMASM_NO_NEON */ +#endif /* WOLFSSL_ARMASM */ +#endif /* !__aarch64__ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-aes.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-aes.c new file mode 100644 index 000000000..d0f8a9c5c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-aes.c @@ -0,0 +1,4653 @@ +/* armv8-aes.c + * + * Copyright (C) 2006-2020 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 + */ + + +/* + * There are two versions one for 64 (Aarch64) and one for 32 bit (Aarch32). + * If changing one check the other. + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if !defined(NO_AES) && defined(WOLFSSL_ARMASM) + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef _MSC_VER + /* 4127 warning constant while(1) */ + #pragma warning(disable: 4127) +#endif + + +static const byte rcon[] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,0x1B, 0x36 + /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +/* get table value from hardware */ +#ifdef __aarch64__ + #define SBOX(x) \ + do { \ + __asm__ volatile ( \ + "DUP v1.4s, %w[in] \n" \ + "MOVI v0.16b, #0 \n" \ + "AESE v0.16b, v1.16b \n" \ + "UMOV %w[out], v0.s[0] \n" \ + : [out] "=r"((x)) \ + : [in] "r" ((x)) \ + : "cc", "memory", "v0", "v1"\ + ); \ + } while(0) + + #define IMIX(x) \ + do { \ + __asm__ volatile ( \ + "LD1 {v0.16b}, [%[in]] \n" \ + "AESIMC v0.16b, v0.16b \n" \ + "ST1 {v0.16b}, [%[out]]\n" \ + : [out] "=r" ((x)) \ + : [in] "0" ((x)) \ + : "cc", "memory", "v0" \ + ); \ + } while(0) +#else /* if not defined __aarch64__ then use 32 bit version */ + #define SBOX(x) \ + do { \ + __asm__ volatile ( \ + "VDUP.32 q1, %[in] \n" \ + "VMOV.i32 q0, #0 \n" \ + "AESE.8 q0, q1 \n" \ + "VMOV.32 %[out], d0[0] \n" \ + : [out] "=r"((x)) \ + : [in] "r" ((x)) \ + : "cc", "memory", "q0", "q1"\ + ); \ + } while(0) + + #define IMIX(x) \ + do { \ + __asm__ volatile ( \ + "VLD1.32 {q0}, [%[in]] \n" \ + "AESIMC.8 q0, q0 \n" \ + "VST1.32 {q0}, [%[out]] \n" \ + : [out] "=r" ((x)) \ + : [in] "0" ((x)) \ + : "cc", "memory", "q0" \ + ); \ + } while(0) +#endif /* aarch64 */ + + +#ifdef HAVE_AESGCM + +static WC_INLINE void IncrementGcmCounter(byte* inOutCtr) +{ + int i; + + /* in network byte order so start at end and work back */ + for (i = AES_BLOCK_SIZE - 1; i >= AES_BLOCK_SIZE - CTR_SZ; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } +} + + +static WC_INLINE void FlattenSzInBits(byte* buf, word32 sz) +{ + /* Multiply the sz by 8 */ + word32 szHi = (sz >> (8*sizeof(sz) - 3)); + sz <<= 3; + + /* copy over the words of the sz into the destination buffer */ + buf[0] = (szHi >> 24) & 0xff; + buf[1] = (szHi >> 16) & 0xff; + buf[2] = (szHi >> 8) & 0xff; + buf[3] = szHi & 0xff; + buf[4] = (sz >> 24) & 0xff; + buf[5] = (sz >> 16) & 0xff; + buf[6] = (sz >> 8) & 0xff; + buf[7] = sz & 0xff; +} + +#endif /* HAVE_AESGCM */ + +/* Similar to wolfSSL software implementation of expanding the AES key. + * Changed out the locations of where table look ups where made to + * use hardware instruction. Also altered decryption key to match. */ +int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) +{ + word32 temp; + word32 *rk; + unsigned int i = 0; + +#if defined(AES_MAX_KEY_SIZE) + const word32 max_key_len = (AES_MAX_KEY_SIZE / 8); +#endif + + if (!((keylen == 16) || (keylen == 24) || (keylen == 32)) || + aes == NULL || userKey == NULL) + return BAD_FUNC_ARG; + + rk = aes->key; +#if defined(AES_MAX_KEY_SIZE) + /* Check key length */ + if (keylen > max_key_len) { + return BAD_FUNC_ARG; + } +#endif + + #ifdef WOLFSSL_AES_COUNTER + aes->left = 0; + #endif /* WOLFSSL_AES_COUNTER */ + + aes->rounds = keylen/4 + 6; + XMEMCPY(rk, userKey, keylen); + + switch(keylen) + { +#if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 128 && \ + defined(WOLFSSL_AES_128) + case 16: + while (1) + { + temp = rk[3]; + SBOX(temp); + temp = rotrFixed(temp, 8); + rk[4] = rk[0] ^ temp ^ rcon[i]; + rk[5] = rk[4] ^ rk[1]; + rk[6] = rk[5] ^ rk[2]; + rk[7] = rk[6] ^ rk[3]; + if (++i == 10) + break; + rk += 4; + } + break; +#endif /* 128 */ + +#if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 192 && \ + defined(WOLFSSL_AES_192) + case 24: + /* for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack */ + while (1) + { + temp = rk[5]; + SBOX(temp); + temp = rotrFixed(temp, 8); + rk[ 6] = rk[ 0] ^ temp ^ rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) + break; + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + break; +#endif /* 192 */ + +#if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 256 && \ + defined(WOLFSSL_AES_256) + case 32: + while (1) + { + temp = rk[7]; + SBOX(temp); + temp = rotrFixed(temp, 8); + rk[8] = rk[0] ^ temp ^ rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) + break; + temp = rk[11]; + SBOX(temp); + rk[12] = rk[ 4] ^ temp; + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + break; +#endif /* 256 */ + + default: + return BAD_FUNC_ARG; + } + + if (dir == AES_DECRYPTION) + { +#ifdef HAVE_AES_DECRYPT + unsigned int j; + rk = aes->key; + + /* invert the order of the round keys: */ + for (i = 0, j = 4* aes->rounds; i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the + first and the last: */ + for (i = 1; i < aes->rounds; i++) { + rk += 4; + IMIX(rk); + } +#else + WOLFSSL_MSG("AES Decryption not compiled in"); + return BAD_FUNC_ARG; +#endif /* HAVE_AES_DECRYPT */ + } + + return wc_AesSetIV(aes, iv); +} + +#if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKey(aes, userKey, keylen, iv, dir); + } +#endif + +/* wc_AesSetIV is shared between software and hardware */ +int wc_AesSetIV(Aes* aes, const byte* iv) +{ + if (aes == NULL) + return BAD_FUNC_ARG; + + if (iv) + XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); + else + XMEMSET(aes->reg, 0, AES_BLOCK_SIZE); + + return 0; +} + + +#ifdef __aarch64__ +/* AES CCM/GCM use encrypt direct but not decrypt */ +#if defined(HAVE_AESCCM) || defined(HAVE_AESGCM) || \ + defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + word32* keyPt = aes->key; + + /* + AESE exor's input with round key + shift rows of exor'ed result + sub bytes for shifted rows + */ + + __asm__ __volatile__ ( + "LD1 {v0.16b}, [%[CtrIn]] \n" + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + + "LD1 {v1.2d-v2.2d}, [%[Key]], #32 \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + + "#subtract rounds done so far and see if should continue\n" + "MOV w12, %w[R] \n" + "SUB w12, w12, #10 \n" + "CBZ w12, 1f \n" + "LD1 {v1.2d-v2.2d}, [%[Key]], #32 \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + + "SUB w12, w12, #2 \n" + "CBZ w12, 1f \n" + "LD1 {v1.2d-v2.2d}, [%[Key]], #32 \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + + "#Final AddRoundKey then store result \n" + "1: \n" + "LD1 {v1.2d}, [%[Key]], #16 \n" + "EOR v0.16b, v0.16b, v1.16b \n" + "ST1 {v0.16b}, [%[CtrOut]] \n" + + :[CtrOut] "=r" (outBlock), "=r" (keyPt), "=r" (aes->rounds), + "=r" (inBlock) + :"0" (outBlock), [Key] "1" (keyPt), [R] "2" (aes->rounds), + [CtrIn] "3" (inBlock) + : "cc", "memory", "w12", "v0", "v1", "v2", "v3", "v4" + ); + + return 0; + } +#endif /* AES_GCM, AES_CCM, DIRECT or COUNTER */ +#if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) + #ifdef HAVE_AES_DECRYPT + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + word32* keyPt = aes->key; + + /* + AESE exor's input with round key + shift rows of exor'ed result + sub bytes for shifted rows + */ + + __asm__ __volatile__ ( + "LD1 {v0.16b}, [%[CtrIn]] \n" + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + + "AESD v0.16b, v1.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v2.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v3.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v4.16b \n" + "AESIMC v0.16b, v0.16b \n" + + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + "AESD v0.16b, v1.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v2.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v3.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v4.16b \n" + "AESIMC v0.16b, v0.16b \n" + + "LD1 {v1.2d-v2.2d}, [%[Key]], #32 \n" + "AESD v0.16b, v1.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v2.16b \n" + + "#subtract rounds done so far and see if should continue\n" + "MOV w12, %w[R] \n" + "SUB w12, w12, #10 \n" + "CBZ w12, 1f \n" + "LD1 {v1.2d-v2.2d}, [%[Key]], #32 \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v1.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v2.16b \n" + + "SUB w12, w12, #2 \n" + "CBZ w12, 1f \n" + "LD1 {v1.2d-v2.2d}, [%[Key]], #32 \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v1.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v2.16b \n" + + "#Final AddRoundKey then store result \n" + "1: \n" + "LD1 {v1.2d}, [%[Key]], #16 \n" + "EOR v0.16b, v0.16b, v1.16b \n" + "ST1 {v0.4s}, [%[CtrOut]] \n" + + :[CtrOut] "=r" (outBlock), "=r" (keyPt), "=r" (aes->rounds), + "=r" (inBlock) + :[Key] "1" (aes->key), "0" (outBlock), [R] "2" (aes->rounds), + [CtrIn] "3" (inBlock) + : "cc", "memory", "w12", "v0", "v1", "v2", "v3", "v4" + ); + + return 0; +} + #endif /* HAVE_AES_DECRYPT */ +#endif /* DIRECT or COUNTER */ + +/* AES-CBC */ +#ifdef HAVE_AES_CBC + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + word32 numBlocks = sz / AES_BLOCK_SIZE; + + if (aes == NULL || out == NULL || (in == NULL && sz > 0)) { + return BAD_FUNC_ARG; + } + + /* do as many block size ops as possible */ + if (numBlocks > 0) { + word32* key = aes->key; + word32* reg = aes->reg; + /* + AESE exor's input with round key + shift rows of exor'ed result + sub bytes for shifted rows + + note: grouping AESE & AESMC together as pairs reduces latency + */ + switch(aes->rounds) { +#ifdef WOLFSSL_AES_128 + case 10: /* AES 128 BLOCK */ + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "LD1 {v9.2d-v11.2d},[%[Key]], #48 \n" + "LD1 {v0.2d}, [%[reg]] \n" + + "LD1 {v12.2d}, [%[input]], #16 \n" + "1:\n" + "#CBC operations, xorbuf in with current aes->reg \n" + "EOR v0.16b, v0.16b, v12.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "SUB w11, w11, #1 \n" + "EOR v0.16b, v0.16b, v11.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + + "CBZ w11, 2f \n" + "LD1 {v12.2d}, [%[input]], #16 \n" + "B 1b \n" + + "2:\n" + "#store current counter value at the end \n" + "ST1 {v0.2d}, [%[regOut]] \n" + + :[out] "=r" (out), [regOut] "=r" (reg), "=r" (in) + :"0" (out), [Key] "r" (key), [input] "2" (in), + [blocks] "r" (numBlocks), [reg] "1" (reg) + : "cc", "memory", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13" + ); + break; +#endif /* WOLFSSL_AES_128 */ +#ifdef WOLFSSL_AES_192 + case 12: /* AES 192 BLOCK */ + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v1.2d-v4.2d}, %[Key], #64 \n" + "LD1 {v5.2d-v8.2d}, %[Key], #64 \n" + "LD1 {v9.2d-v12.2d},%[Key], #64 \n" + "LD1 {v13.2d}, %[Key], #16 \n" + "LD1 {v0.2d}, %[reg] \n" + + "LD1 {v14.2d}, [%[input]], #16 \n" + "1:\n" + "#CBC operations, xorbuf in with current aes->reg \n" + "EOR v0.16b, v0.16b, v14.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v12.16b \n" + "EOR v0.16b, v0.16b, v13.16b \n" + "SUB w11, w11, #1 \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + + "CBZ w11, 2f \n" + "LD1 {v14.2d}, [%[input]], #16\n" + "B 1b \n" + + "2:\n" + "#store current counter value at the end \n" + "ST1 {v0.2d}, %[regOut] \n" + + + :[out] "=r" (out), [regOut] "=m" (aes->reg), "=r" (in) + :"0" (out), [Key] "m" (aes->key), [input] "2" (in), + [blocks] "r" (numBlocks), [reg] "m" (aes->reg) + : "cc", "memory", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14" + ); + break; +#endif /* WOLFSSL_AES_192*/ +#ifdef WOLFSSL_AES_256 + case 14: /* AES 256 BLOCK */ + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v1.2d-v4.2d}, %[Key], #64 \n" + + "LD1 {v5.2d-v8.2d}, %[Key], #64 \n" + "LD1 {v9.2d-v12.2d}, %[Key], #64 \n" + "LD1 {v13.2d-v15.2d}, %[Key], #48 \n" + "LD1 {v0.2d}, %[reg] \n" + + "LD1 {v16.2d}, [%[input]], #16 \n" + "1: \n" + "#CBC operations, xorbuf in with current aes->reg \n" + "EOR v0.16b, v0.16b, v16.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v12.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v13.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v14.16b \n" + "EOR v0.16b, v0.16b, v15.16b \n" + "SUB w11, w11, #1 \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + + "CBZ w11, 2f \n" + "LD1 {v16.2d}, [%[input]], #16 \n" + "B 1b \n" + + "2: \n" + "#store current counter value at the end \n" + "ST1 {v0.2d}, %[regOut] \n" + + + :[out] "=r" (out), [regOut] "=m" (aes->reg), "=r" (in) + :"0" (out), [Key] "m" (aes->key), [input] "2" (in), + [blocks] "r" (numBlocks), [reg] "m" (aes->reg) + : "cc", "memory", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14","v15", + "v16" + ); + break; +#endif /* WOLFSSL_AES_256 */ + default: + WOLFSSL_MSG("Bad AES-CBC round value"); + return BAD_FUNC_ARG; + } + } + + return 0; + } + + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + word32 numBlocks = sz / AES_BLOCK_SIZE; + + if (aes == NULL || out == NULL || (in == NULL && sz > 0) + || sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + /* do as many block size ops as possible */ + if (numBlocks > 0) { + word32* key = aes->key; + word32* reg = aes->reg; + + switch(aes->rounds) { +#ifdef WOLFSSL_AES_128 + case 10: /* AES 128 BLOCK */ + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "LD1 {v9.2d-v11.2d},[%[Key]], #48 \n" + "LD1 {v13.2d}, [%[reg]] \n" + + "1:\n" + "LD1 {v0.2d}, [%[input]], #16 \n" + "MOV v12.16b, v0.16b \n" + "AESD v0.16b, v1.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v2.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v3.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v4.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v5.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v6.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v7.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v8.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v9.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v10.16b \n" + "EOR v0.16b, v0.16b, v11.16b \n" + + "EOR v0.16b, v0.16b, v13.16b \n" + "SUB w11, w11, #1 \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + "MOV v13.16b, v12.16b \n" + + "CBZ w11, 2f \n" + "B 1b \n" + + "2: \n" + "#store current counter value at the end \n" + "ST1 {v13.2d}, [%[regOut]] \n" + + :[out] "=r" (out), [regOut] "=r" (reg), "=r" (in) + :"0" (out), [Key] "r" (key), [input] "2" (in), + [blocks] "r" (numBlocks), [reg] "1" (reg) + : "cc", "memory", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13" + ); + break; +#endif /* WOLFSSL_AES_128 */ +#ifdef WOLFSSL_AES_192 + case 12: /* AES 192 BLOCK */ + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "LD1 {v9.2d-v12.2d},[%[Key]], #64 \n" + "LD1 {v13.16b}, [%[Key]], #16 \n" + "LD1 {v15.2d}, [%[reg]] \n" + + "LD1 {v0.2d}, [%[input]], #16 \n" + "1: \n" + "MOV v14.16b, v0.16b \n" + "AESD v0.16b, v1.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v2.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v3.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v4.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v5.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v6.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v7.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v8.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v9.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v10.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v11.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v12.16b \n" + "EOR v0.16b, v0.16b, v13.16b \n" + + "EOR v0.16b, v0.16b, v15.16b \n" + "SUB w11, w11, #1 \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + "MOV v15.16b, v14.16b \n" + + "CBZ w11, 2f \n" + "LD1 {v0.2d}, [%[input]], #16 \n" + "B 1b \n" + + "2:\n" + "#store current counter value at the end \n" + "ST1 {v15.2d}, [%[regOut]] \n" + + :[out] "=r" (out), [regOut] "=r" (reg), "=r" (in) + :"0" (out), [Key] "r" (key), [input] "2" (in), + [blocks] "r" (numBlocks), [reg] "1" (reg) + : "cc", "memory", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15" + ); + break; +#endif /* WOLFSSL_AES_192 */ +#ifdef WOLFSSL_AES_256 + case 14: /* AES 256 BLOCK */ + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "LD1 {v9.2d-v12.2d}, [%[Key]], #64 \n" + "LD1 {v13.2d-v15.2d}, [%[Key]], #48 \n" + "LD1 {v17.2d}, [%[reg]] \n" + + "LD1 {v0.2d}, [%[input]], #16 \n" + "1: \n" + "MOV v16.16b, v0.16b \n" + "AESD v0.16b, v1.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v2.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v3.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v4.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v5.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v6.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v7.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v8.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v9.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v10.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v11.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v12.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v13.16b \n" + "AESIMC v0.16b, v0.16b \n" + "AESD v0.16b, v14.16b \n" + "EOR v0.16b, v0.16b, v15.16b \n" + + "EOR v0.16b, v0.16b, v17.16b \n" + "SUB w11, w11, #1 \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + "MOV v17.16b, v16.16b \n" + + "CBZ w11, 2f \n" + "LD1 {v0.2d}, [%[input]], #16 \n" + "B 1b \n" + + "2:\n" + "#store current counter value at the end \n" + "ST1 {v17.2d}, [%[regOut]] \n" + + :[out] "=r" (out), [regOut] "=r" (reg), "=r" (in) + :"0" (out), [Key] "r" (key), [input] "2" (in), + [blocks] "r" (numBlocks), [reg] "1" (reg) + : "cc", "memory", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14","v15", + "v16", "v17" + ); + break; +#endif /* WOLFSSL_AES_256 */ + default: + WOLFSSL_MSG("Bad AES-CBC round value"); + return BAD_FUNC_ARG; + } + } + + return 0; + } + #endif + +#endif /* HAVE_AES_CBC */ + +/* AES-CTR */ +#ifdef WOLFSSL_AES_COUNTER + + /* Increment AES counter */ + static WC_INLINE void IncrementAesCounter(byte* inOutCtr) + { + int i; + + /* in network byte order so start at end and work back */ + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } + } + + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + 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++); + aes->left--; + sz--; + } + + /* do as many block size ops as possible */ + numBlocks = sz/AES_BLOCK_SIZE; + if (numBlocks > 0) { + /* pointer needed because it is incremented when read, causing + * an issue with call to encrypt/decrypt leftovers */ + byte* keyPt = (byte*)aes->key; + sz -= numBlocks * AES_BLOCK_SIZE; + switch(aes->rounds) { +#ifdef WOLFSSL_AES_128 + case 10: /* AES 128 BLOCK */ + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + + "#Create vector with the value 1 \n" + "MOVI v15.16b, #1 \n" + "USHR v15.2d, v15.2d, #56 \n" + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "EOR v14.16b, v14.16b, v14.16b \n" + "EXT v14.16b, v15.16b, v14.16b, #8\n" + + "LD1 {v9.2d-v11.2d}, [%[Key]], #48\n" + "LD1 {v13.2d}, %[reg] \n" + + /* double block */ + "1: \n" + "CMP w11, #1 \n" + "BEQ 2f \n" + "CMP w11, #0 \n" + "BEQ 3f \n" + + "MOV v0.16b, v13.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "REV64 v13.16b, v13.16b \n" /* network order */ + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "SUB w11, w11, #2 \n" + "ADD v15.2d, v13.2d, v14.2d \n" /* add 1 to counter */ + "ADD v13.2d, v15.2d, v14.2d \n" /* add 1 to counter */ + + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v15.16b, v15.16b, v15.16b, #8 \n" + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "REV64 v15.16b, v15.16b \n" /* revert from network order */ + "REV64 v13.16b, v13.16b \n" /* revert from network order */ + + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v15.16b, v1.16b \n" + "AESMC v15.16b, v15.16b \n" + + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v15.16b, v2.16b \n" + "AESMC v15.16b, v15.16b \n" + + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v15.16b, v3.16b \n" + "AESMC v15.16b, v15.16b \n" + + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v15.16b, v4.16b \n" + "AESMC v15.16b, v15.16b \n" + + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v15.16b, v5.16b \n" + "AESMC v15.16b, v15.16b \n" + + "AESE v0.16b, v10.16b \n" + "AESE v15.16b, v6.16b \n" + "AESMC v15.16b, v15.16b \n" + + "EOR v0.16b, v0.16b, v11.16b \n" + "AESE v15.16b, v7.16b \n" + "AESMC v15.16b, v15.16b \n" + + "LD1 {v12.2d}, [%[input]], #16 \n" + "AESE v15.16b, v8.16b \n" + "AESMC v15.16b, v15.16b \n" + + "EOR v0.16b, v0.16b, v12.16b \n" + "AESE v15.16b, v9.16b \n" + "AESMC v15.16b, v15.16b \n" + + "LD1 {v12.2d}, [%[input]], #16 \n" + "AESE v15.16b, v10.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + "EOR v15.16b, v15.16b, v11.16b \n" + "EOR v15.16b, v15.16b, v12.16b \n" + "ST1 {v15.2d}, [%[out]], #16 \n" + + "B 1b \n" + + /* single block */ + "2: \n" + "MOV v0.16b, v13.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "REV64 v13.16b, v13.16b \n" /* network order */ + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "ADD v13.2d, v13.2d, v14.2d \n" /* add 1 to counter */ + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "SUB w11, w11, #1 \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "REV64 v13.16b, v13.16b \n" /* revert from network order */ + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "EOR v0.16b, v0.16b, v11.16b \n" + "#CTR operations, increment counter and xorbuf \n" + "LD1 {v12.2d}, [%[input]], #16 \n" + "EOR v0.16b, v0.16b, v12.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + + "3: \n" + "#store current counter value at the end \n" + "ST1 {v13.2d}, %[regOut] \n" + + :[out] "=r" (out), "=r" (keyPt), [regOut] "=m" (aes->reg), + "=r" (in) + :"0" (out), [Key] "1" (keyPt), [input] "3" (in), + [blocks] "r" (numBlocks), [reg] "m" (aes->reg) + : "cc", "memory", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14","v15" + ); + break; +#endif /* WOLFSSL_AES_128 */ +#ifdef WOLFSSL_AES_192 + case 12: /* AES 192 BLOCK */ + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + + "#Create vector with the value 1 \n" + "MOVI v16.16b, #1 \n" + "USHR v16.2d, v16.2d, #56 \n" + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "EOR v14.16b, v14.16b, v14.16b \n" + "EXT v16.16b, v16.16b, v14.16b, #8\n" + + "LD1 {v9.2d-v12.2d}, [%[Key]], #64\n" + "LD1 {v15.2d}, %[reg] \n" + "LD1 {v13.16b}, [%[Key]], #16 \n" + + /* double block */ + "1: \n" + "CMP w11, #1 \n" + "BEQ 2f \n" + "CMP w11, #0 \n" + "BEQ 3f \n" + + "MOV v0.16b, v15.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "REV64 v15.16b, v15.16b \n" /* network order */ + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v15.16b, v15.16b, v15.16b, #8 \n" + "SUB w11, w11, #2 \n" + "ADD v17.2d, v15.2d, v16.2d \n" /* add 1 to counter */ + "ADD v15.2d, v17.2d, v16.2d \n" /* add 1 to counter */ + + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v17.16b, v17.16b, v17.16b, #8 \n" + "EXT v15.16b, v15.16b, v15.16b, #8 \n" + + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "REV64 v17.16b, v17.16b \n" /* revert from network order */ + "REV64 v15.16b, v15.16b \n" /* revert from network order */ + + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v17.16b, v1.16b \n" + "AESMC v17.16b, v17.16b \n" + + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v17.16b, v2.16b \n" + "AESMC v17.16b, v17.16b \n" + + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v17.16b, v3.16b \n" + "AESMC v17.16b, v17.16b \n" + + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v17.16b, v4.16b \n" + "AESMC v17.16b, v17.16b \n" + + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v17.16b, v5.16b \n" + "AESMC v17.16b, v17.16b \n" + + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v17.16b, v6.16b \n" + "AESMC v17.16b, v17.16b \n" + + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v17.16b, v7.16b \n" + "AESMC v17.16b, v17.16b \n" + + "AESE v0.16b, v12.16b \n" + "AESE v17.16b, v8.16b \n" + "AESMC v17.16b, v17.16b \n" + + "EOR v0.16b, v0.16b, v13.16b \n" + "AESE v17.16b, v9.16b \n" + "AESMC v17.16b, v17.16b \n" + + "LD1 {v14.2d}, [%[input]], #16 \n" + "AESE v17.16b, v10.16b \n" + "AESMC v17.16b, v17.16b \n" + + "EOR v0.16b, v0.16b, v14.16b \n" + "AESE v17.16b, v11.16b \n" + "AESMC v17.16b, v17.16b \n" + + "LD1 {v14.2d}, [%[input]], #16 \n" + "AESE v17.16b, v12.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + "EOR v17.16b, v17.16b, v13.16b \n" + "EOR v17.16b, v17.16b, v14.16b \n" + "ST1 {v17.2d}, [%[out]], #16 \n" + + "B 1b \n" + + "2: \n" + "LD1 {v14.2d}, [%[input]], #16 \n" + "MOV v0.16b, v15.16b \n" + + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "REV64 v15.16b, v15.16b \n" /* network order */ + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v15.16b, v15.16b, v15.16b, #8 \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "ADD v15.2d, v15.2d, v16.2d \n" /* add 1 to counter */ + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "SUB w11, w11, #1 \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v15.16b, v15.16b, v15.16b, #8 \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "REV64 v15.16b, v15.16b \n" /* revert from network order */ + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v12.16b \n" + "EOR v0.16b, v0.16b, v13.16b \n" + "#CTR operations, increment counter and xorbuf \n" + "EOR v0.16b, v0.16b, v14.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + + "3: \n" + "#store current counter value at the end \n" + "ST1 {v15.2d}, %[regOut] \n" + + :[out] "=r" (out), "=r" (keyPt), [regOut] "=m" (aes->reg), + "=r" (in) + :"0" (out), [Key] "1" (keyPt), [input] "3" (in), + [blocks] "r" (numBlocks), [reg] "m" (aes->reg) + : "cc", "memory", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14","v15", + "v16", "v17" + ); + break; +#endif /* WOLFSSL_AES_192 */ +#ifdef WOLFSSL_AES_256 + case 14: /* AES 256 BLOCK */ + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + + "#Create vector with the value 1 \n" + "MOVI v18.16b, #1 \n" + "USHR v18.2d, v18.2d, #56 \n" + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "EOR v19.16b, v19.16b, v19.16b \n" + "EXT v18.16b, v18.16b, v19.16b, #8\n" + + "LD1 {v9.2d-v12.2d}, [%[Key]], #64 \n" + "LD1 {v13.2d-v15.2d}, [%[Key]], #48 \n" + "LD1 {v17.2d}, %[reg] \n" + + /* double block */ + "1: \n" + "CMP w11, #1 \n" + "BEQ 2f \n" + "CMP w11, #0 \n" + "BEQ 3f \n" + + "MOV v0.16b, v17.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "REV64 v17.16b, v17.16b \n" /* network order */ + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v17.16b, v17.16b, v17.16b, #8 \n" + "SUB w11, w11, #2 \n" + "ADD v19.2d, v17.2d, v18.2d \n" /* add 1 to counter */ + "ADD v17.2d, v19.2d, v18.2d \n" /* add 1 to counter */ + + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v19.16b, v19.16b, v19.16b, #8 \n" + "EXT v17.16b, v17.16b, v17.16b, #8 \n" + + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "REV64 v19.16b, v19.16b \n" /* revert from network order */ + "REV64 v17.16b, v17.16b \n" /* revert from network order */ + + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v19.16b, v1.16b \n" + "AESMC v19.16b, v19.16b \n" + + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v19.16b, v2.16b \n" + "AESMC v19.16b, v19.16b \n" + + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v19.16b, v3.16b \n" + "AESMC v19.16b, v19.16b \n" + + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v19.16b, v4.16b \n" + "AESMC v19.16b, v19.16b \n" + + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v19.16b, v5.16b \n" + "AESMC v19.16b, v19.16b \n" + + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v19.16b, v6.16b \n" + "AESMC v19.16b, v19.16b \n" + + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v19.16b, v7.16b \n" + "AESMC v19.16b, v19.16b \n" + + "AESE v0.16b, v12.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v19.16b, v8.16b \n" + "AESMC v19.16b, v19.16b \n" + + "AESE v0.16b, v13.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v19.16b, v9.16b \n" + "AESMC v19.16b, v19.16b \n" + + "AESE v0.16b, v14.16b \n" + "AESE v19.16b, v10.16b \n" + "AESMC v19.16b, v19.16b \n" + + "EOR v0.16b, v0.16b, v15.16b \n" + "AESE v19.16b, v11.16b \n" + "AESMC v19.16b, v19.16b \n" + + "LD1 {v16.2d}, [%[input]], #16 \n" + "AESE v19.16b, v12.16b \n" + "AESMC v19.16b, v19.16b \n" + + "EOR v0.16b, v0.16b, v16.16b \n" + "AESE v19.16b, v13.16b \n" + "AESMC v19.16b, v19.16b \n" + + "LD1 {v16.2d}, [%[input]], #16 \n" + "AESE v19.16b, v14.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + "EOR v19.16b, v19.16b, v15.16b \n" + "EOR v19.16b, v19.16b, v16.16b \n" + "ST1 {v19.2d}, [%[out]], #16 \n" + + "B 1b \n" + + "2: \n" + "LD1 {v16.2d}, [%[input]], #16 \n" + "MOV v0.16b, v17.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "REV64 v17.16b, v17.16b \n" /* network order */ + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v17.16b, v17.16b, v17.16b, #8 \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "ADD v17.2d, v17.2d, v18.2d \n" /* add 1 to counter */ + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v17.16b, v17.16b, v17.16b, #8 \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "REV64 v17.16b, v17.16b \n" /* revert from network order */ + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v12.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v13.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v14.16b \n" + "EOR v0.16b, v0.16b, v15.16b \n" + "#CTR operations, increment counter and xorbuf \n" + "EOR v0.16b, v0.16b, v16.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + + "3: \n" + "#store current counter value at the end \n" + "ST1 {v17.2d}, %[regOut] \n" + + + :[out] "=r" (out), "=r" (keyPt), [regOut] "=m" (aes->reg), + "=r" (in) + :"0" (out), [Key] "1" (keyPt), [input] "3" (in), + [blocks] "r" (numBlocks), [reg] "m" (aes->reg) + : "cc", "memory", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14","v15", + "v16", "v17", "v18", "v19" + ); + break; +#endif /* WOLFSSL_AES_256 */ + default: + WOLFSSL_MSG("Bad AES-CTR round value"); + return BAD_FUNC_ARG; + } + + aes->left = 0; + } + + /* handle non block size remaining */ + if (sz) { + wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->tmp); + IncrementAesCounter((byte*)aes->reg); + + aes->left = AES_BLOCK_SIZE; + tmp = (byte*)aes->tmp; + + while (sz--) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + } + } + return 0; + } + +#endif /* WOLFSSL_AES_COUNTER */ + +#ifdef HAVE_AESGCM + +/* + * Based from GCM implementation in wolfcrypt/src/aes.c + */ + +/* PMULL and RBIT only with AArch64 */ +/* Use ARM hardware for polynomial multiply */ +static void GMULT(byte* X, byte* Y) +{ + __asm__ volatile ( + "LD1 {v0.16b}, [%[inX]] \n" + "LD1 {v1.16b}, [%[inY]] \n" /* v1 already reflected from set key */ + "RBIT v0.16b, v0.16b \n" + + + /* Algorithm 1 from Intel GCM white paper. + "Carry-Less Multiplication and Its Usage for Computing the GCM Mode" + */ + "PMULL v3.1q, v0.1d, v1.1d \n" /* a0 * b0 = C */ + "PMULL2 v4.1q, v0.2d, v1.2d \n" /* a1 * b1 = D */ + "EXT v5.16b, v1.16b, v1.16b, #8 \n" /* b0b1 -> b1b0 */ + "PMULL v6.1q, v0.1d, v5.1d \n" /* a0 * b1 = E */ + "PMULL2 v5.1q, v0.2d, v5.2d \n" /* a1 * b0 = F */ + + "#Set a register to all 0s using EOR \n" + "EOR v7.16b, v7.16b, v7.16b \n" + "EOR v5.16b, v5.16b, v6.16b \n" /* F ^ E */ + "EXT v6.16b, v7.16b, v5.16b, #8 \n" /* get (F^E)[0] */ + "EOR v3.16b, v3.16b, v6.16b \n" /* low 128 bits in v3 */ + "EXT v6.16b, v5.16b, v7.16b, #8 \n" /* get (F^E)[1] */ + "EOR v4.16b, v4.16b, v6.16b \n" /* high 128 bits in v4 */ + + + /* Based from White Paper "Implementing GCM on ARMv8" + by Conrado P.L. Gouvea and Julio Lopez + reduction on 256bit value using Algorithm 5 */ + "MOVI v8.16b, #0x87 \n" + "USHR v8.2d, v8.2d, #56 \n" + /* v8 is now 0x00000000000000870000000000000087 reflected 0xe1....*/ + "PMULL2 v5.1q, v4.2d, v8.2d \n" + "EXT v6.16b, v5.16b, v7.16b, #8 \n" /* v7 is all 0's */ + "EOR v4.16b, v4.16b, v6.16b \n" + "EXT v6.16b, v7.16b, v5.16b, #8 \n" + "EOR v3.16b, v3.16b, v6.16b \n" + "PMULL v5.1q, v4.1d, v8.1d \n" + "EOR v4.16b, v3.16b, v5.16b \n" + + "RBIT v4.16b, v4.16b \n" + "STR q4, [%[out]] \n" + : [out] "=r" (X), "=r" (Y) + : [inX] "0" (X), [inY] "1" (Y) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8" + ); +} + + +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]; + word32 blocks, partial; + byte* h = aes->H; + + XMEMSET(x, 0, AES_BLOCK_SIZE); + + /* Hash in A, the Additional Authentication Data */ + if (aSz != 0 && a != NULL) { + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + /* do as many blocks as possible */ + while (blocks--) { + xorbuf(x, a, AES_BLOCK_SIZE); + GMULT(x, h); + a += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, a, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, h); + } + } + + /* Hash in C, the Ciphertext */ + if (cSz != 0 && c != NULL) { + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, c, AES_BLOCK_SIZE); + GMULT(x, h); + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, c, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, h); + } + } + + /* Hash in the lengths of A and C in bits */ + FlattenSzInBits(&scratch[0], aSz); + FlattenSzInBits(&scratch[8], cSz); + xorbuf(x, scratch, AES_BLOCK_SIZE); + + /* Copy the result (minus last GMULT) into s. */ + XMEMCPY(s, x, sSz); +} + + +#ifdef WOLFSSL_AES_128 +/* internal function : see wc_AesGcmEncrypt */ +static int Aes128GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + word32 blocks; + word32 partial; + byte counter[AES_BLOCK_SIZE]; + byte initialCounter[AES_BLOCK_SIZE]; + byte x[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; + + /* Noticed different optimization levels treated head of array different. + Some cases was stack pointer plus offset others was a regester containing + address. To make uniform for passing in to inline assembly code am using + pointers to the head of each local array. + */ + byte* ctr = counter; + byte* iCtr = initialCounter; + byte* xPt = x; + byte* sPt = scratch; + byte* keyPt; /* pointer to handle pointer advencment */ + + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[AES_BLOCK_SIZE - 1] = 1; + } + else { + GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE); + GMULT(initialCounter, aes->H); + } + XMEMCPY(counter, initialCounter, AES_BLOCK_SIZE); + + + /* Hash in the Additional Authentication Data */ + XMEMSET(x, 0, AES_BLOCK_SIZE); + if (authInSz != 0 && authIn != NULL) { + blocks = authInSz / AES_BLOCK_SIZE; + partial = authInSz % AES_BLOCK_SIZE; + /* do as many blocks as possible */ + while (blocks--) { + xorbuf(x, authIn, AES_BLOCK_SIZE); + GMULT(x, aes->H); + authIn += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, authIn, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->H); + } + } + + /* do as many blocks as possible */ + blocks = sz / AES_BLOCK_SIZE; + partial = sz % AES_BLOCK_SIZE; + if (blocks > 0) { + keyPt = (byte*)aes->key; + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v13.2d}, [%[ctr]] \n" + + "#Create vector with the value 1 \n" + "MOVI v14.16b, #1 \n" + "USHR v14.2d, v14.2d, #56 \n" + "EOR v22.16b, v22.16b, v22.16b \n" + "EXT v14.16b, v14.16b, v22.16b, #8\n" + + + /*************************************************** + Get first out block for GHASH using AES encrypt + ***************************************************/ + "REV64 v13.16b, v13.16b \n" /* network order */ + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "ADD v13.2d, v13.2d, v14.2d \n" /* add 1 to counter */ + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "REV64 v13.16b, v13.16b \n" /* revert from network order */ + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "MOV v0.16b, v13.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "LD1 {v16.2d}, %[inY] \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "SUB w11, w11, #1 \n" + "LD1 {v9.2d-v11.2d}, [%[Key]], #48\n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "MOVI v23.16b, #0x87 \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "LD1 {v17.2d}, [%[inX]] \n" /* account for additional data */ + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "USHR v23.2d, v23.2d, #56 \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "LD1 {v12.2d}, [%[input]], #16 \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "EOR v0.16b, v0.16b, v11.16b \n" + + "EOR v0.16b, v0.16b, v12.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + "MOV v15.16b, v0.16b \n" + + "CBZ w11, 1f \n" /* only one block jump to final GHASH */ + + "LD1 {v12.2d}, [%[input]], #16 \n" + + /*************************************************** + Interweave GHASH and encrypt if more then 1 block + ***************************************************/ + "2: \n" + "REV64 v13.16b, v13.16b \n" /* network order */ + "EOR v15.16b, v17.16b, v15.16b \n" + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "ADD v13.2d, v13.2d, v14.2d \n" /* add 1 to counter */ + "RBIT v15.16b, v15.16b \n" /* v15 is encrypted out block (c) */ + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "REV64 v13.16b, v13.16b \n" /* revert from network order */ + "PMULL v18.1q, v15.1d, v16.1d \n" /* a0 * b0 = C */ + "MOV v0.16b, v13.16b \n" + "PMULL2 v19.1q, v15.2d, v16.2d \n" /* a1 * b1 = D */ + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v20.16b, v16.16b, v16.16b, #8 \n" /* b0b1 -> b1b0 */ + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "PMULL v21.1q, v15.1d, v20.1d \n" /* a0 * b1 = E */ + "PMULL2 v20.1q, v15.2d, v20.2d \n" /* a1 * b0 = F */ + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v20.16b, v20.16b, v21.16b \n" /* F ^ E */ + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" /* get (F^E)[0] */ + "SUB w11, w11, #1 \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v18.16b, v18.16b, v21.16b \n" /* low 128 bits in v3 */ + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* get (F^E)[1] */ + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v19.16b, v19.16b, v21.16b \n" /* high 128 bits in v4 */ + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "PMULL2 v20.1q, v19.2d, v23.2d \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* v22 is all 0's */ + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v19.16b, v19.16b, v21.16b \n" + "AESE v0.16b, v10.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" + "EOR v0.16b, v0.16b, v11.16b \n" + "EOR v18.16b, v18.16b, v21.16b \n" + + "EOR v0.16b, v0.16b, v12.16b \n" + "PMULL v20.1q, v19.1d, v23.1d \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + "EOR v19.16b, v18.16b, v20.16b \n" + "MOV v15.16b, v0.16b \n" + "RBIT v17.16b, v19.16b \n" + + "CBZ w11, 1f \n" + "LD1 {v12.2d}, [%[input]], #16 \n" + "B 2b \n" + + /*************************************************** + GHASH on last block + ***************************************************/ + "1: \n" + "EOR v15.16b, v17.16b, v15.16b \n" + "RBIT v15.16b, v15.16b \n" /* v15 is encrypted out block */ + + "#store current AES counter value \n" + "ST1 {v13.2d}, [%[ctrOut]] \n" + "PMULL v18.1q, v15.1d, v16.1d \n" /* a0 * b0 = C */ + "PMULL2 v19.1q, v15.2d, v16.2d \n" /* a1 * b1 = D */ + "EXT v20.16b, v16.16b, v16.16b, #8 \n" /* b0b1 -> b1b0 */ + "PMULL v21.1q, v15.1d, v20.1d \n" /* a0 * b1 = E */ + "PMULL2 v20.1q, v15.2d, v20.2d \n" /* a1 * b0 = F */ + "EOR v20.16b, v20.16b, v21.16b \n" /* F ^ E */ + "EXT v21.16b, v22.16b, v20.16b, #8 \n" /* get (F^E)[0] */ + "EOR v18.16b, v18.16b, v21.16b \n" /* low 128 bits in v3 */ + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* get (F^E)[1] */ + "EOR v19.16b, v19.16b, v21.16b \n" /* high 128 bits in v4 */ + + "#Reduce product from multiplication \n" + "PMULL2 v20.1q, v19.2d, v23.2d \n" + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* v22 is all 0's */ + "EOR v19.16b, v19.16b, v21.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" + "EOR v18.16b, v18.16b, v21.16b \n" + "PMULL v20.1q, v19.1d, v23.1d \n" + "EOR v19.16b, v18.16b, v20.16b \n" + "RBIT v17.16b, v19.16b \n" + "STR q17, [%[xOut]] \n" /* GHASH x value for partial blocks */ + + :[out] "=r" (out), "=r" (keyPt), [ctrOut] "=r" (ctr), "=r" (in) + ,[xOut] "=r" (xPt),"=m" (aes->H) + :"0" (out), [Key] "1" (keyPt), [ctr] "2" (ctr), [blocks] "r" (blocks), + [input] "3" (in) + ,[inX] "4" (xPt), [inY] "m" (aes->H) + : "cc", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14" + ,"v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", "v24" + ); + } + + /* take care of partial block sizes leftover */ + if (partial != 0) { + IncrementGcmCounter(counter); + wc_AesEncrypt(aes, counter, scratch); + xorbuf(scratch, in, partial); + XMEMCPY(out, scratch, partial); + + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, out, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->H); + } + + /* Hash in the lengths of A and C in bits */ + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + FlattenSzInBits(&scratch[0], authInSz); + FlattenSzInBits(&scratch[8], sz); + xorbuf(x, scratch, AES_BLOCK_SIZE); + XMEMCPY(scratch, x, AES_BLOCK_SIZE); + + keyPt = (byte*)aes->key; + __asm__ __volatile__ ( + + "LD1 {v16.16b}, [%[tag]] \n" + "LD1 {v17.16b}, %[h] \n" + "RBIT v16.16b, v16.16b \n" + + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + "PMULL v18.1q, v16.1d, v17.1d \n" /* a0 * b0 = C */ + "PMULL2 v19.1q, v16.2d, v17.2d \n" /* a1 * b1 = D */ + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "EXT v20.16b, v17.16b, v17.16b, #8 \n" /* b0b1 -> b1b0 */ + "LD1 {v9.2d-v11.2d}, [%[Key]], #48\n" + "PMULL v21.1q, v16.1d, v20.1d \n" /* a0 * b1 = E */ + "PMULL2 v20.1q, v16.2d, v20.2d \n" /* a1 * b0 = F */ + "LD1 {v0.2d}, [%[ctr]] \n" + + "#Set a register to all 0s using EOR \n" + "EOR v22.16b, v22.16b, v22.16b \n" + "EOR v20.16b, v20.16b, v21.16b \n" /* F ^ E */ + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" /* get (F^E)[0] */ + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v18.16b, v18.16b, v21.16b \n" /* low 128 bits in v3 */ + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* get (F^E)[1] */ + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v19.16b, v19.16b, v21.16b \n" /* high 128 bits in v4 */ + "MOVI v23.16b, #0x87 \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "USHR v23.2d, v23.2d, #56 \n" + "PMULL2 v20.1q, v19.2d, v23.2d \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v20.16b, v22.16b, #8 \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v19.16b, v19.16b, v21.16b \n" + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v18.16b, v18.16b, v21.16b \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "PMULL v20.1q, v19.1d, v23.1d \n" + "EOR v19.16b, v18.16b, v20.16b \n" + "AESE v0.16b, v10.16b \n" + "RBIT v19.16b, v19.16b \n" + "EOR v0.16b, v0.16b, v11.16b \n" + "EOR v19.16b, v19.16b, v0.16b \n" + "STR q19, [%[out]] \n" + + :[out] "=r" (sPt), "=r" (keyPt), "=r" (iCtr) + :[tag] "0" (sPt), [Key] "1" (keyPt), + [ctr] "2" (iCtr) , [h] "m" (aes->H) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14", + "v15", "v16", "v17","v18", "v19", "v20","v21","v22","v23","v24" + ); + + + if (authTagSz > AES_BLOCK_SIZE) { + XMEMCPY(authTag, scratch, AES_BLOCK_SIZE); + } + else { + /* authTagSz can be smaller than AES_BLOCK_SIZE */ + XMEMCPY(authTag, scratch, authTagSz); + } + return 0; +} +#endif /* WOLFSSL_AES_128 */ + +#ifdef WOLFSSL_AES_192 +/* internal function : see wc_AesGcmEncrypt */ +static int Aes192GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + word32 blocks; + word32 partial; + byte counter[AES_BLOCK_SIZE]; + byte initialCounter[AES_BLOCK_SIZE]; + byte x[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; + + /* Noticed different optimization levels treated head of array different. + Some cases was stack pointer plus offset others was a regester containing + address. To make uniform for passing in to inline assembly code am using + pointers to the head of each local array. + */ + byte* ctr = counter; + byte* iCtr = initialCounter; + byte* xPt = x; + byte* sPt = scratch; + byte* keyPt; /* pointer to handle pointer advencment */ + + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[AES_BLOCK_SIZE - 1] = 1; + } + else { + GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE); + GMULT(initialCounter, aes->H); + } + XMEMCPY(counter, initialCounter, AES_BLOCK_SIZE); + + + /* Hash in the Additional Authentication Data */ + XMEMSET(x, 0, AES_BLOCK_SIZE); + if (authInSz != 0 && authIn != NULL) { + blocks = authInSz / AES_BLOCK_SIZE; + partial = authInSz % AES_BLOCK_SIZE; + /* do as many blocks as possible */ + while (blocks--) { + xorbuf(x, authIn, AES_BLOCK_SIZE); + GMULT(x, aes->H); + authIn += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, authIn, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->H); + } + } + + /* do as many blocks as possible */ + blocks = sz / AES_BLOCK_SIZE; + partial = sz % AES_BLOCK_SIZE; + if (blocks > 0) { + keyPt = (byte*)aes->key; + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v13.2d}, [%[ctr]] \n" + + "#Create vector with the value 1 \n" + "MOVI v14.16b, #1 \n" + "USHR v14.2d, v14.2d, #56 \n" + "EOR v22.16b, v22.16b, v22.16b \n" + "EXT v14.16b, v14.16b, v22.16b, #8\n" + + + /*************************************************** + Get first out block for GHASH using AES encrypt + ***************************************************/ + "REV64 v13.16b, v13.16b \n" /* network order */ + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "ADD v13.2d, v13.2d, v14.2d \n" /* add 1 to counter */ + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "REV64 v13.16b, v13.16b \n" /* revert from network order */ + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "MOV v0.16b, v13.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "LD1 {v16.2d}, %[inY] \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "SUB w11, w11, #1 \n" + "LD1 {v9.2d-v11.2d}, [%[Key]], #48\n" + "LD1 {v30.2d-v31.2d}, [%[Key]], #32\n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "MOVI v23.16b, #0x87 \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "LD1 {v17.2d}, [%[inX]] \n" /* account for additional data */ + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "USHR v23.2d, v23.2d, #56 \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "LD1 {v12.2d}, [%[input]], #16 \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v30.16b \n" + "EOR v0.16b, v0.16b, v31.16b \n" + + "EOR v0.16b, v0.16b, v12.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + "MOV v15.16b, v0.16b \n" + + "CBZ w11, 1f \n" /* only one block jump to final GHASH */ + "LD1 {v12.2d}, [%[input]], #16 \n" + + /*************************************************** + Interweave GHASH and encrypt if more then 1 block + ***************************************************/ + "2: \n" + "REV64 v13.16b, v13.16b \n" /* network order */ + "EOR v15.16b, v17.16b, v15.16b \n" + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "ADD v13.2d, v13.2d, v14.2d \n" /* add 1 to counter */ + "RBIT v15.16b, v15.16b \n" /* v15 is encrypted out block (c) */ + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "REV64 v13.16b, v13.16b \n" /* revert from network order */ + "PMULL v18.1q, v15.1d, v16.1d \n" /* a0 * b0 = C */ + "MOV v0.16b, v13.16b \n" + "PMULL2 v19.1q, v15.2d, v16.2d \n" /* a1 * b1 = D */ + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v20.16b, v16.16b, v16.16b, #8 \n" /* b0b1 -> b1b0 */ + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "PMULL v21.1q, v15.1d, v20.1d \n" /* a0 * b1 = E */ + "PMULL2 v20.1q, v15.2d, v20.2d \n" /* a1 * b0 = F */ + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v20.16b, v20.16b, v21.16b \n" /* F ^ E */ + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" /* get (F^E)[0] */ + "SUB w11, w11, #1 \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v18.16b, v18.16b, v21.16b \n" /* low 128 bits in v3 */ + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* get (F^E)[1] */ + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v19.16b, v19.16b, v21.16b \n" /* high 128 bits in v4 */ + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "PMULL2 v20.1q, v19.2d, v23.2d \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* v22 is all 0's */ + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v19.16b, v19.16b, v21.16b \n" + "AESE v0.16b, v30.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" + "EOR v0.16b, v0.16b, v31.16b \n" + "EOR v18.16b, v18.16b, v21.16b \n" + + "EOR v0.16b, v0.16b, v12.16b \n" + "PMULL v20.1q, v19.1d, v23.1d \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + "EOR v19.16b, v18.16b, v20.16b \n" + "MOV v15.16b, v0.16b \n" + "RBIT v17.16b, v19.16b \n" + + "CBZ w11, 1f \n" + "LD1 {v12.2d}, [%[input]], #16 \n" + "B 2b \n" + + /*************************************************** + GHASH on last block + ***************************************************/ + "1: \n" + "EOR v15.16b, v17.16b, v15.16b \n" + "RBIT v15.16b, v15.16b \n" /* v15 is encrypted out block */ + + "#store current AES counter value \n" + "ST1 {v13.2d}, [%[ctrOut]] \n" + "PMULL v18.1q, v15.1d, v16.1d \n" /* a0 * b0 = C */ + "PMULL2 v19.1q, v15.2d, v16.2d \n" /* a1 * b1 = D */ + "EXT v20.16b, v16.16b, v16.16b, #8 \n" /* b0b1 -> b1b0 */ + "PMULL v21.1q, v15.1d, v20.1d \n" /* a0 * b1 = E */ + "PMULL2 v20.1q, v15.2d, v20.2d \n" /* a1 * b0 = F */ + "EOR v20.16b, v20.16b, v21.16b \n" /* F ^ E */ + "EXT v21.16b, v22.16b, v20.16b, #8 \n" /* get (F^E)[0] */ + "EOR v18.16b, v18.16b, v21.16b \n" /* low 128 bits in v3 */ + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* get (F^E)[1] */ + "EOR v19.16b, v19.16b, v21.16b \n" /* high 128 bits in v4 */ + + "#Reduce product from multiplication \n" + "PMULL2 v20.1q, v19.2d, v23.2d \n" + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* v22 is all 0's */ + "EOR v19.16b, v19.16b, v21.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" + "EOR v18.16b, v18.16b, v21.16b \n" + "PMULL v20.1q, v19.1d, v23.1d \n" + "EOR v19.16b, v18.16b, v20.16b \n" + "RBIT v17.16b, v19.16b \n" + "STR q17, [%[xOut]] \n" /* GHASH x value for partial blocks */ + + :[out] "=r" (out), "=r" (keyPt), [ctrOut] "=r" (ctr), "=r" (in) + ,[xOut] "=r" (xPt),"=m" (aes->H) + :"0" (out), [Key] "1" (keyPt), [ctr] "2" (ctr), [blocks] "r" (blocks), + [input] "3" (in) + ,[inX] "4" (xPt), [inY] "m" (aes->H) + : "cc", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14" + ,"v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", + "v24","v25","v26","v27","v28","v29","v30","v31" + ); + } + + /* take care of partial block sizes leftover */ + if (partial != 0) { + IncrementGcmCounter(counter); + wc_AesEncrypt(aes, counter, scratch); + xorbuf(scratch, in, partial); + XMEMCPY(out, scratch, partial); + + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, out, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->H); + } + + /* Hash in the lengths of A and C in bits */ + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + FlattenSzInBits(&scratch[0], authInSz); + FlattenSzInBits(&scratch[8], sz); + xorbuf(x, scratch, AES_BLOCK_SIZE); + XMEMCPY(scratch, x, AES_BLOCK_SIZE); + + keyPt = (byte*)aes->key; + __asm__ __volatile__ ( + + "LD1 {v16.16b}, [%[tag]] \n" + "LD1 {v17.16b}, %[h] \n" + "RBIT v16.16b, v16.16b \n" + + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + "PMULL v18.1q, v16.1d, v17.1d \n" /* a0 * b0 = C */ + "PMULL2 v19.1q, v16.2d, v17.2d \n" /* a1 * b1 = D */ + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "EXT v20.16b, v17.16b, v17.16b, #8 \n" /* b0b1 -> b1b0 */ + "LD1 {v9.2d-v11.2d}, [%[Key]], #48\n" + "LD1 {v30.2d-v31.2d}, [%[Key]], #32\n" + "PMULL v21.1q, v16.1d, v20.1d \n" /* a0 * b1 = E */ + "PMULL2 v20.1q, v16.2d, v20.2d \n" /* a1 * b0 = F */ + "LD1 {v0.2d}, [%[ctr]] \n" + + "#Set a register to all 0s using EOR \n" + "EOR v22.16b, v22.16b, v22.16b \n" + "EOR v20.16b, v20.16b, v21.16b \n" /* F ^ E */ + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" /* get (F^E)[0] */ + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v18.16b, v18.16b, v21.16b \n" /* low 128 bits in v3 */ + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* get (F^E)[1] */ + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v19.16b, v19.16b, v21.16b \n" /* high 128 bits in v4 */ + "MOVI v23.16b, #0x87 \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "USHR v23.2d, v23.2d, #56 \n" + "PMULL2 v20.1q, v19.2d, v23.2d \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v20.16b, v22.16b, #8 \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v19.16b, v19.16b, v21.16b \n" + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v18.16b, v18.16b, v21.16b \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "PMULL v20.1q, v19.1d, v23.1d \n" + "EOR v19.16b, v18.16b, v20.16b \n" + "AESE v0.16b, v30.16b \n" + "RBIT v19.16b, v19.16b \n" + "EOR v0.16b, v0.16b, v31.16b \n" + "EOR v19.16b, v19.16b, v0.16b \n" + "STR q19, [%[out]] \n" + + :[out] "=r" (sPt), "=r" (keyPt), "=r" (iCtr) + :[tag] "0" (sPt), [Key] "1" (keyPt), + [ctr] "2" (iCtr) , [h] "m" (aes->H) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14", + "v15", "v16", "v17","v18", "v19", "v20","v21","v22","v23","v24" + ); + + + if (authTagSz > AES_BLOCK_SIZE) { + XMEMCPY(authTag, scratch, AES_BLOCK_SIZE); + } + else { + /* authTagSz can be smaller than AES_BLOCK_SIZE */ + XMEMCPY(authTag, scratch, authTagSz); + } + + return 0; +} +#endif /* WOLFSSL_AES_192 */ + +#ifdef WOLFSSL_AES_256 +/* internal function : see wc_AesGcmEncrypt */ +static int Aes256GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + word32 blocks; + word32 partial; + byte counter[AES_BLOCK_SIZE]; + byte initialCounter[AES_BLOCK_SIZE]; + byte x[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; + + /* Noticed different optimization levels treated head of array different. + Some cases was stack pointer plus offset others was a regester containing + address. To make uniform for passing in to inline assembly code am using + pointers to the head of each local array. + */ + byte* ctr = counter; + byte* iCtr = initialCounter; + byte* xPt = x; + byte* sPt = scratch; + byte* keyPt; /* pointer to handle pointer advencment */ + + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[AES_BLOCK_SIZE - 1] = 1; + } + else { + GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE); + GMULT(initialCounter, aes->H); + } + XMEMCPY(counter, initialCounter, AES_BLOCK_SIZE); + + + /* Hash in the Additional Authentication Data */ + XMEMSET(x, 0, AES_BLOCK_SIZE); + if (authInSz != 0 && authIn != NULL) { + blocks = authInSz / AES_BLOCK_SIZE; + partial = authInSz % AES_BLOCK_SIZE; + /* do as many blocks as possible */ + while (blocks--) { + xorbuf(x, authIn, AES_BLOCK_SIZE); + GMULT(x, aes->H); + authIn += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, authIn, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->H); + } + } + + /* do as many blocks as possible */ + blocks = sz / AES_BLOCK_SIZE; + partial = sz % AES_BLOCK_SIZE; + if (blocks > 0) { + keyPt = (byte*)aes->key; + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v13.2d}, [%[ctr]] \n" + + "#Create vector with the value 1 \n" + "MOVI v14.16b, #1 \n" + "USHR v14.2d, v14.2d, #56 \n" + "EOR v22.16b, v22.16b, v22.16b \n" + "EXT v14.16b, v14.16b, v22.16b, #8\n" + + + /*************************************************** + Get first out block for GHASH using AES encrypt + ***************************************************/ + "REV64 v13.16b, v13.16b \n" /* network order */ + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "ADD v13.2d, v13.2d, v14.2d \n" /* add 1 to counter */ + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "REV64 v13.16b, v13.16b \n" /* revert from network order */ + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "MOV v0.16b, v13.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "LD1 {v16.2d}, %[inY] \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "SUB w11, w11, #1 \n" + "LD1 {v9.2d-v11.2d}, [%[Key]], #48\n" + "LD1 {v28.2d-v31.2d}, [%[Key]], #64\n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "MOVI v23.16b, #0x87 \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "LD1 {v17.2d}, [%[inX]] \n" /* account for additional data */ + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "USHR v23.2d, v23.2d, #56 \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "LD1 {v12.2d}, [%[input]], #16 \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v28.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v29.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v30.16b \n" + "EOR v0.16b, v0.16b, v31.16b \n" + + "EOR v0.16b, v0.16b, v12.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + "MOV v15.16b, v0.16b \n" + + "CBZ w11, 1f \n" /* only one block jump to final GHASH */ + "LD1 {v12.2d}, [%[input]], #16 \n" + + /*************************************************** + Interweave GHASH and encrypt if more then 1 block + ***************************************************/ + "2: \n" + "REV64 v13.16b, v13.16b \n" /* network order */ + "EOR v15.16b, v17.16b, v15.16b \n" + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "ADD v13.2d, v13.2d, v14.2d \n" /* add 1 to counter */ + "RBIT v15.16b, v15.16b \n" /* v15 is encrypted out block (c) */ + "EXT v13.16b, v13.16b, v13.16b, #8 \n" + "REV64 v13.16b, v13.16b \n" /* revert from network order */ + "PMULL v18.1q, v15.1d, v16.1d \n" /* a0 * b0 = C */ + "MOV v0.16b, v13.16b \n" + "PMULL2 v19.1q, v15.2d, v16.2d \n" /* a1 * b1 = D */ + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v20.16b, v16.16b, v16.16b, #8 \n" /* b0b1 -> b1b0 */ + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "PMULL v21.1q, v15.1d, v20.1d \n" /* a0 * b1 = E */ + "PMULL2 v20.1q, v15.2d, v20.2d \n" /* a1 * b0 = F */ + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v20.16b, v20.16b, v21.16b \n" /* F ^ E */ + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" /* get (F^E)[0] */ + "SUB w11, w11, #1 \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v18.16b, v18.16b, v21.16b \n" /* low 128 bits in v3 */ + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* get (F^E)[1] */ + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v19.16b, v19.16b, v21.16b \n" /* high 128 bits in v4 */ + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "PMULL2 v20.1q, v19.2d, v23.2d \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* v22 is all 0's */ + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v28.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v29.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v19.16b, v19.16b, v21.16b \n" + "AESE v0.16b, v30.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" + "EOR v0.16b, v0.16b, v31.16b \n" + "EOR v18.16b, v18.16b, v21.16b \n" + + "EOR v0.16b, v0.16b, v12.16b \n" + "PMULL v20.1q, v19.1d, v23.1d \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + "EOR v19.16b, v18.16b, v20.16b \n" + "MOV v15.16b, v0.16b \n" + "RBIT v17.16b, v19.16b \n" + + "CBZ w11, 1f \n" + "LD1 {v12.2d}, [%[input]], #16 \n" + "B 2b \n" + + /*************************************************** + GHASH on last block + ***************************************************/ + "1: \n" + "EOR v15.16b, v17.16b, v15.16b \n" + "RBIT v15.16b, v15.16b \n" /* v15 is encrypted out block */ + + "#store current AES counter value \n" + "ST1 {v13.2d}, [%[ctrOut]] \n" + "PMULL v18.1q, v15.1d, v16.1d \n" /* a0 * b0 = C */ + "PMULL2 v19.1q, v15.2d, v16.2d \n" /* a1 * b1 = D */ + "EXT v20.16b, v16.16b, v16.16b, #8 \n" /* b0b1 -> b1b0 */ + "PMULL v21.1q, v15.1d, v20.1d \n" /* a0 * b1 = E */ + "PMULL2 v20.1q, v15.2d, v20.2d \n" /* a1 * b0 = F */ + "EOR v20.16b, v20.16b, v21.16b \n" /* F ^ E */ + "EXT v21.16b, v22.16b, v20.16b, #8 \n" /* get (F^E)[0] */ + "EOR v18.16b, v18.16b, v21.16b \n" /* low 128 bits in v3 */ + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* get (F^E)[1] */ + "EOR v19.16b, v19.16b, v21.16b \n" /* high 128 bits in v4 */ + + "#Reduce product from multiplication \n" + "PMULL2 v20.1q, v19.2d, v23.2d \n" + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* v22 is all 0's */ + "EOR v19.16b, v19.16b, v21.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" + "EOR v18.16b, v18.16b, v21.16b \n" + "PMULL v20.1q, v19.1d, v23.1d \n" + "EOR v19.16b, v18.16b, v20.16b \n" + "RBIT v17.16b, v19.16b \n" + "STR q17, [%[xOut]] \n" /* GHASH x value for partial blocks */ + + :[out] "=r" (out), "=r" (keyPt), [ctrOut] "=r" (ctr), "=r" (in) + ,[xOut] "=r" (xPt),"=m" (aes->H) + :"0" (out), [Key] "1" (keyPt), [ctr] "2" (ctr), [blocks] "r" (blocks), + [input] "3" (in) + ,[inX] "4" (xPt), [inY] "m" (aes->H) + : "cc", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14" + ,"v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", "v24" + ); + } + + /* take care of partial block sizes leftover */ + if (partial != 0) { + IncrementGcmCounter(counter); + wc_AesEncrypt(aes, counter, scratch); + xorbuf(scratch, in, partial); + XMEMCPY(out, scratch, partial); + + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, out, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->H); + } + + /* Hash in the lengths of A and C in bits */ + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + FlattenSzInBits(&scratch[0], authInSz); + FlattenSzInBits(&scratch[8], sz); + xorbuf(x, scratch, AES_BLOCK_SIZE); + XMEMCPY(scratch, x, AES_BLOCK_SIZE); + + keyPt = (byte*)aes->key; + __asm__ __volatile__ ( + + "LD1 {v16.16b}, [%[tag]] \n" + "LD1 {v17.16b}, %[h] \n" + "RBIT v16.16b, v16.16b \n" + + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + "PMULL v18.1q, v16.1d, v17.1d \n" /* a0 * b0 = C */ + "PMULL2 v19.1q, v16.2d, v17.2d \n" /* a1 * b1 = D */ + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "EXT v20.16b, v17.16b, v17.16b, #8 \n" /* b0b1 -> b1b0 */ + "LD1 {v9.2d-v11.2d}, [%[Key]], #48\n" + "LD1 {v28.2d-v31.2d}, [%[Key]], #64\n" + "PMULL v21.1q, v16.1d, v20.1d \n" /* a0 * b1 = E */ + "PMULL2 v20.1q, v16.2d, v20.2d \n" /* a1 * b0 = F */ + "LD1 {v0.2d}, [%[ctr]] \n" + + "#Set a register to all 0s using EOR \n" + "EOR v22.16b, v22.16b, v22.16b \n" + "EOR v20.16b, v20.16b, v21.16b \n" /* F ^ E */ + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" /* get (F^E)[0] */ + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v18.16b, v18.16b, v21.16b \n" /* low 128 bits in v3 */ + "EXT v21.16b, v20.16b, v22.16b, #8 \n" /* get (F^E)[1] */ + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v19.16b, v19.16b, v21.16b \n" /* high 128 bits in v4 */ + "MOVI v23.16b, #0x87 \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "USHR v23.2d, v23.2d, #56 \n" + "PMULL2 v20.1q, v19.2d, v23.2d \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v20.16b, v22.16b, #8 \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v19.16b, v19.16b, v21.16b \n" + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "EXT v21.16b, v22.16b, v20.16b, #8 \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "EOR v18.16b, v18.16b, v21.16b \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v28.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v29.16b \n" + "AESMC v0.16b, v0.16b \n" + "PMULL v20.1q, v19.1d, v23.1d \n" + "EOR v19.16b, v18.16b, v20.16b \n" + "AESE v0.16b, v30.16b \n" + "RBIT v19.16b, v19.16b \n" + "EOR v0.16b, v0.16b, v31.16b \n" + "EOR v19.16b, v19.16b, v0.16b \n" + "STR q19, [%[out]] \n" + + :[out] "=r" (sPt), "=r" (keyPt), "=r" (iCtr) + :[tag] "0" (sPt), [Key] "1" (keyPt), + [ctr] "2" (iCtr) , [h] "m" (aes->H) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14", + "v15", "v16", "v17","v18", "v19", "v20","v21","v22","v23", + "v24","v25","v26","v27","v28","v29","v30","v31" + ); + + + if (authTagSz > AES_BLOCK_SIZE) { + XMEMCPY(authTag, scratch, AES_BLOCK_SIZE); + } + else { + /* authTagSz can be smaller than AES_BLOCK_SIZE */ + XMEMCPY(authTag, scratch, authTagSz); + } + + return 0; +} +#endif /* WOLFSSL_AES_256 */ + + +/* aarch64 with PMULL and PMULL2 + * Encrypt and tag data using AES with GCM mode. + * aes: Aes structure having already been set with set key function + * out: encrypted data output buffer + * in: plain text input buffer + * sz: size of plain text and out buffer + * iv: initialization vector + * ivSz: size of iv buffer + * authTag: buffer to hold tag + * authTagSz: size of tag buffer + * authIn: additional data buffer + * authInSz: size of additional data buffer + * + * Notes: + * GHASH multiplication based from Algorithm 1 from Intel GCM white paper. + * "Carry-Less Multiplication and Its Usage for Computing the GCM Mode" + * + * GHASH reduction Based from White Paper "Implementing GCM on ARMv8" + * by Conrado P.L. Gouvea and Julio Lopez reduction on 256bit value using + * Algorithm 5 + */ +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) +{ + /* sanity checks */ + if (aes == NULL || (iv == NULL && ivSz > 0) || + (authTag == 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) { +#ifdef WOLFSSL_AES_128 + case 10: + return Aes128GcmEncrypt(aes, out, in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz); +#endif +#ifdef WOLFSSL_AES_192 + case 12: + return Aes192GcmEncrypt(aes, out, in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz); +#endif +#ifdef WOLFSSL_AES_256 + case 14: + return Aes256GcmEncrypt(aes, out, in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz); +#endif + default: + WOLFSSL_MSG("AES-GCM invalid round number"); + return BAD_FUNC_ARG; + } +} + + +#ifdef HAVE_AES_DECRYPT +/* + * Check tag and decrypt data using AES with GCM mode. + * aes: Aes structure having already been set with set key function + * out: decrypted data output buffer + * in: cipher text buffer + * sz: size of plain text and out buffer + * iv: initialization vector + * ivSz: size of iv buffer + * authTag: buffer holding tag + * authTagSz: size of tag buffer + * authIn: additional data buffer + * authInSz: size of additional data buffer + */ +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) +{ + 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 scratch[AES_BLOCK_SIZE]; + + ctr = counter ; + + /* sanity checks */ + if (aes == NULL || (iv == NULL && ivSz > 0) || + (authTag == 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; + } + + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[AES_BLOCK_SIZE - 1] = 1; + } + else { + GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE); + GMULT(initialCounter, aes->H); + } + 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]; + + GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime)); + GMULT(Tprime, aes->H); + wc_AesEncrypt(aes, ctr, EKY0); + xorbuf(Tprime, EKY0, sizeof(Tprime)); + + if (ConstantCompare(authTag, Tprime, authTagSz) != 0) { + return AES_GCM_AUTH_E; + } + } + + /* do as many blocks as possible */ + if (blocks > 0) { + /* pointer needed because it is incremented when read, causing + * an issue with call to encrypt/decrypt leftovers */ + byte* keyPt = (byte*)aes->key; + switch(aes->rounds) { +#ifdef WOLFSSL_AES_128 + case 10: /* AES 128 BLOCK */ + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + + "#Create vector with the value 1 \n" + "MOVI v14.16b, #1 \n" + "USHR v14.2d, v14.2d, #56 \n" + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "EOR v13.16b, v13.16b, v13.16b \n" + "EXT v14.16b, v14.16b, v13.16b, #8 \n" + + "LD1 {v9.2d-v11.2d}, [%[Key]], #48 \n" + "LD1 {v12.2d}, [%[ctr]] \n" + "LD1 {v13.2d}, [%[input]], #16 \n" + + "1: \n" + "REV64 v12.16b, v12.16b \n" /* network order */ + "EXT v12.16b, v12.16b, v12.16b, #8 \n" + "ADD v12.2d, v12.2d, v14.2d \n" /* add 1 to counter */ + "EXT v12.16b, v12.16b, v12.16b, #8 \n" + "REV64 v12.16b, v12.16b \n" /* revert from network order */ + "MOV v0.16b, v12.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "SUB w11, w11, #1 \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "EOR v0.16b, v0.16b, v11.16b \n" + + "EOR v0.16b, v0.16b, v13.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + + "CBZ w11, 2f \n" + "LD1 {v13.2d}, [%[input]], #16 \n" + "B 1b \n" + + "2: \n" + "#store current counter value at the end \n" + "ST1 {v12.16b}, [%[ctrOut]] \n" + + :[out] "=r" (p), "=r" (keyPt), [ctrOut] "=r" (ctr), "=r" (c) + :"0" (p), [Key] "1" (keyPt), [ctr] "2" (ctr), [blocks] "r" (blocks), + [input] "3" (c) + : "cc", "memory", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14" + ); + break; +#endif +#ifdef WOLFSSL_AES_192 + case 12: /* AES 192 BLOCK */ + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + + "#Create vector with the value 1 \n" + "MOVI v16.16b, #1 \n" + "USHR v16.2d, v16.2d, #56 \n" + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "EOR v14.16b, v14.16b, v14.16b \n" + "EXT v16.16b, v16.16b, v14.16b, #8 \n" + + "LD1 {v9.2d-v12.2d}, [%[Key]], #64 \n" + "LD1 {v13.2d}, [%[Key]], #16 \n" + "LD1 {v14.2d}, [%[ctr]] \n" + "LD1 {v15.2d}, [%[input]], #16 \n" + + "1: \n" + "REV64 v14.16b, v14.16b \n" /* network order */ + "EXT v14.16b, v14.16b, v14.16b, #8 \n" + "ADD v14.2d, v14.2d, v16.2d \n" /* add 1 to counter */ + "EXT v14.16b, v14.16b, v14.16b, #8 \n" + "REV64 v14.16b, v14.16b \n" /* revert from network order */ + "MOV v0.16b, v14.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "SUB w11, w11, #1 \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v12.16b \n" + "EOR v0.16b, v0.16b, v13.16b \n" + + "EOR v0.16b, v0.16b, v15.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + + "CBZ w11, 2f \n" + "LD1 {v15.2d}, [%[input]], #16 \n" + "B 1b \n" + + "2: \n" + "#store current counter value at the end \n" + "ST1 {v14.2d}, [%[ctrOut]] \n" + + :[out] "=r" (p), "=r" (keyPt), [ctrOut] "=r" (ctr), "=r" (c) + :"0" (p), [Key] "1" (keyPt), [ctr] "2" (ctr), [blocks] "r" (blocks), + [input] "3" (c) + : "cc", "memory", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", + "v16" + ); + break; +#endif /* WOLFSSL_AES_192 */ +#ifdef WOLFSSL_AES_256 + case 14: /* AES 256 BLOCK */ + __asm__ __volatile__ ( + "MOV w11, %w[blocks] \n" + "LD1 {v1.2d-v4.2d}, [%[Key]], #64 \n" + + "#Create vector with the value 1 \n" + "MOVI v18.16b, #1 \n" + "USHR v18.2d, v18.2d, #56 \n" + "LD1 {v5.2d-v8.2d}, [%[Key]], #64 \n" + "EOR v19.16b, v19.16b, v19.16b \n" + "EXT v18.16b, v18.16b, v19.16b, #8 \n" + + "LD1 {v9.2d-v12.2d}, [%[Key]], #64 \n" + "LD1 {v13.2d-v15.2d}, [%[Key]], #48 \n" + "LD1 {v17.2d}, [%[ctr]] \n" + "LD1 {v16.2d}, [%[input]], #16 \n" + + "1: \n" + "REV64 v17.16b, v17.16b \n" /* network order */ + "EXT v17.16b, v17.16b, v17.16b, #8 \n" + "ADD v17.2d, v17.2d, v18.2d \n" /* add 1 to counter */ + "EXT v17.16b, v17.16b, v17.16b, #8 \n" + "REV64 v17.16b, v17.16b \n" /* revert from network order */ + "MOV v0.16b, v17.16b \n" + "AESE v0.16b, v1.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v2.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v3.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v4.16b \n" + "AESMC v0.16b, v0.16b \n" + "SUB w11, w11, #1 \n" + "AESE v0.16b, v5.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v6.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v7.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v8.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v9.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v10.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v11.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v12.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v13.16b \n" + "AESMC v0.16b, v0.16b \n" + "AESE v0.16b, v14.16b \n" + "EOR v0.16b, v0.16b, v15.16b \n" + + "EOR v0.16b, v0.16b, v16.16b \n" + "ST1 {v0.2d}, [%[out]], #16 \n" + + "CBZ w11, 2f \n" + "LD1 {v16.2d}, [%[input]], #16 \n" + "B 1b \n" + + "2: \n" + "#store current counter value at the end \n" + "ST1 {v17.2d}, [%[ctrOut]] \n" + + :[out] "=r" (p), "=r" (keyPt), [ctrOut] "=r" (ctr), "=r" (c) + :"0" (p), [Key] "1" (keyPt), [ctr] "2" (ctr), [blocks] "r" (blocks), + [input] "3" (c) + : "cc", "memory", "w11", "v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", + "v16", "v17", "v18", "v19" + ); + break; +#endif /* WOLFSSL_AES_256 */ + default: + WOLFSSL_MSG("Bad AES-GCM round value"); + return BAD_FUNC_ARG; + } + } + if (partial != 0) { + IncrementGcmCounter(ctr); + wc_AesEncrypt(aes, ctr, scratch); + + /* check if pointer is null after main AES-GCM blocks + * helps static analysis */ + if (p == NULL || c == NULL) { + return BAD_STATE_E; + } + xorbuf(scratch, c, partial); + XMEMCPY(p, scratch, partial); + } + return 0; +} + +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AESGCM */ + + +/*************************************** + * not 64 bit so use 32 bit mode +****************************************/ +#else + +/* AES CCM/GCM use encrypt direct but not decrypt */ +#if defined(HAVE_AESCCM) || defined(HAVE_AESGCM) || \ + defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + /* + AESE exor's input with round key + shift rows of exor'ed result + sub bytes for shifted rows + */ + + word32* keyPt = aes->key; + __asm__ __volatile__ ( + "VLD1.32 {q0}, [%[CtrIn]] \n" + "VLDM %[Key]!, {q1-q4} \n" + + "AESE.8 q0, q1\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q2\n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q1}, [%[Key]]! \n" + "AESE.8 q0, q3\n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q2}, [%[Key]]! \n" + "AESE.8 q0, q4\n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q3}, [%[Key]]! \n" + "AESE.8 q0, q1\n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q4}, [%[Key]]! \n" + "AESE.8 q0, q2\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q3\n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q1}, [%[Key]]! \n" + "AESE.8 q0, q4\n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q2}, [%[Key]]! \n" + "AESE.8 q0, q1\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q2\n" + + "MOV r12, %[R] \n" + "CMP r12, #10 \n" + "BEQ 1f \n" + "VLD1.32 {q1}, [%[Key]]! \n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q2}, [%[Key]]! \n" + "AESE.8 q0, q1\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q2\n" + + "CMP r12, #12 \n" + "BEQ 1f \n" + "VLD1.32 {q1}, [%[Key]]! \n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q2}, [%[Key]]! \n" + "AESE.8 q0, q1\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q2\n" + + "#Final AddRoundKey then store result \n" + "1: \n" + "VLD1.32 {q1}, [%[Key]]! \n" + "VEOR.32 q0, q0, q1\n" + "VST1.32 {q0}, [%[CtrOut]] \n" + + :[CtrOut] "=r" (outBlock), "=r" (keyPt), "=r" (aes->rounds), + "=r" (inBlock) + :"0" (outBlock), [Key] "1" (keyPt), [R] "2" (aes->rounds), + [CtrIn] "3" (inBlock) + : "cc", "memory", "r12", "q0", "q1", "q2", "q3", "q4" + ); + + return 0; + } +#endif /* AES_GCM, AES_CCM, DIRECT or COUNTER */ +#if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) + #ifdef HAVE_AES_DECRYPT + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + /* + AESE exor's input with round key + shift rows of exor'ed result + sub bytes for shifted rows + */ + + word32* keyPt = aes->key; + __asm__ __volatile__ ( + "VLD1.32 {q0}, [%[CtrIn]] \n" + "VLDM %[Key]!, {q1-q4} \n" + + "AESD.8 q0, q1\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q2\n" + "AESIMC.8 q0, q0\n" + "VLD1.32 {q1}, [%[Key]]! \n" + "AESD.8 q0, q3\n" + "AESIMC.8 q0, q0\n" + "VLD1.32 {q2}, [%[Key]]! \n" + "AESD.8 q0, q4\n" + "AESIMC.8 q0, q0\n" + "VLD1.32 {q3}, [%[Key]]! \n" + "AESD.8 q0, q1\n" + "AESIMC.8 q0, q0\n" + "VLD1.32 {q4}, [%[Key]]! \n" + "AESD.8 q0, q2\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q3\n" + "AESIMC.8 q0, q0\n" + "VLD1.32 {q1}, [%[Key]]! \n" + "AESD.8 q0, q4\n" + "AESIMC.8 q0, q0\n" + "VLD1.32 {q2}, [%[Key]]! \n" + "AESD.8 q0, q1\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q2\n" + + "MOV r12, %[R] \n" + "CMP r12, #10 \n" + "BEQ 1f \n" + "VLD1.32 {q1}, [%[Key]]! \n" + "AESIMC.8 q0, q0\n" + "VLD1.32 {q2}, [%[Key]]! \n" + "AESD.8 q0, q1\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q2\n" + + "CMP r12, #12 \n" + "BEQ 1f \n" + "VLD1.32 {q1}, [%[Key]]! \n" + "AESIMC.8 q0, q0\n" + "VLD1.32 {q2}, [%[Key]]! \n" + "AESD.8 q0, q1\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q2\n" + + "#Final AddRoundKey then store result \n" + "1: \n" + "VLD1.32 {q1}, [%[Key]]! \n" + "VEOR.32 q0, q0, q1\n" + "VST1.32 {q0}, [%[CtrOut]] \n" + + :[CtrOut] "=r" (outBlock), "=r" (keyPt), "=r" (aes->rounds), + "=r" (inBlock) + :"0" (outBlock), [Key] "1" (keyPt), [R] "2" (aes->rounds), + [CtrIn] "3" (inBlock) + : "cc", "memory", "r12", "q0", "q1", "q2", "q3", "q4" + ); + + return 0; +} + #endif /* HAVE_AES_DECRYPT */ +#endif /* DIRECT or COUNTER */ + +/* AES-CBC */ +#ifdef HAVE_AES_CBC + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + word32 numBlocks = sz / AES_BLOCK_SIZE; + + if (aes == NULL || out == NULL || (in == NULL && sz > 0)) { + return BAD_FUNC_ARG; + } + + /* do as many block size ops as possible */ + if (numBlocks > 0) { + word32* keyPt = aes->key; + word32* regPt = aes->reg; + /* + AESE exor's input with round key + shift rows of exor'ed result + sub bytes for shifted rows + + note: grouping AESE & AESMC together as pairs reduces latency + */ + switch(aes->rounds) { +#ifdef WOLFSSL_AES_128 + case 10: /* AES 128 BLOCK */ + __asm__ __volatile__ ( + "MOV r11, %[blocks] \n" + "VLD1.32 {q1}, [%[Key]]! \n" + "VLD1.32 {q2}, [%[Key]]! \n" + "VLD1.32 {q3}, [%[Key]]! \n" + "VLD1.32 {q4}, [%[Key]]! \n" + "VLD1.32 {q5}, [%[Key]]! \n" + "VLD1.32 {q6}, [%[Key]]! \n" + "VLD1.32 {q7}, [%[Key]]! \n" + "VLD1.32 {q8}, [%[Key]]! \n" + "VLD1.32 {q9}, [%[Key]]! \n" + "VLD1.32 {q10}, [%[Key]]! \n" + "VLD1.32 {q11}, [%[Key]]! \n" + "VLD1.32 {q0}, [%[reg]] \n" + "VLD1.32 {q12}, [%[input]]!\n" + + "1:\n" + "#CBC operations, xorbuf in with current aes->reg \n" + "VEOR.32 q0, q0, q12 \n" + "AESE.8 q0, q1 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q2 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q3 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q4 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q5 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q6 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q7 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q8 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q9 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q10\n" + "VEOR.32 q0, q0, q11 \n" + "SUB r11, r11, #1 \n" + "VST1.32 {q0}, [%[out]]! \n" + + "CMP r11, #0 \n" + "BEQ 2f \n" + "VLD1.32 {q12}, [%[input]]! \n" + "B 1b \n" + + "2:\n" + "#store current counter value at the end \n" + "VST1.32 {q0}, [%[regOut]] \n" + + :[out] "=r" (out), [regOut] "=r" (regPt) + :"0" (out), [Key] "r" (keyPt), [input] "r" (in), + [blocks] "r" (numBlocks), [reg] "1" (regPt) + : "cc", "memory", "r11", "q0", "q1", "q2", "q3", "q4", "q5", + "q6", "q7", "q8", "q9", "q10", "q11", "q12" + ); + break; +#endif /* WOLFSSL_AES_128 */ +#ifdef WOLFSSL_AES_192 + case 12: /* AES 192 BLOCK */ + __asm__ __volatile__ ( + "MOV r11, %[blocks] \n" + "VLD1.32 {q1}, [%[Key]]! \n" + "VLD1.32 {q2}, [%[Key]]! \n" + "VLD1.32 {q3}, [%[Key]]! \n" + "VLD1.32 {q4}, [%[Key]]! \n" + "VLD1.32 {q5}, [%[Key]]! \n" + "VLD1.32 {q6}, [%[Key]]! \n" + "VLD1.32 {q7}, [%[Key]]! \n" + "VLD1.32 {q8}, [%[Key]]! \n" + "VLD1.32 {q9}, [%[Key]]! \n" + "VLD1.32 {q10}, [%[Key]]! \n" + "VLD1.32 {q11}, [%[Key]]! \n" + "VLD1.32 {q0}, [%[reg]] \n" + "VLD1.32 {q12}, [%[input]]!\n" + "VLD1.32 {q13}, [%[Key]]! \n" + "VLD1.32 {q14}, [%[Key]]! \n" + + "1:\n" + "#CBC operations, xorbuf in with current aes->reg \n" + "VEOR.32 q0, q0, q12 \n" + "AESE.8 q0, q1 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q2 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q3 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q4 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q5 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q6 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q7 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q8 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q9 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q10 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q11 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q13\n" + "VEOR.32 q0, q0, q14 \n" + "SUB r11, r11, #1 \n" + "VST1.32 {q0}, [%[out]]! \n" + + "CMP r11, #0 \n" + "BEQ 2f \n" + "VLD1.32 {q12}, [%[input]]! \n" + "B 1b \n" + + "2:\n" + "#store current counter qalue at the end \n" + "VST1.32 {q0}, [%[regOut]] \n" + + :[out] "=r" (out), [regOut] "=r" (regPt) + :"0" (out), [Key] "r" (keyPt), [input] "r" (in), + [blocks] "r" (numBlocks), [reg] "1" (regPt) + : "cc", "memory", "r11", "q0", "q1", "q2", "q3", "q4", "q5", + "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14" + ); + break; +#endif /* WOLFSSL_AES_192 */ +#ifdef WOLFSSL_AES_256 + case 14: /* AES 256 BLOCK */ + __asm__ __volatile__ ( + "MOV r11, %[blocks] \n" + "VLD1.32 {q1}, [%[Key]]! \n" + "VLD1.32 {q2}, [%[Key]]! \n" + "VLD1.32 {q3}, [%[Key]]! \n" + "VLD1.32 {q4}, [%[Key]]! \n" + "VLD1.32 {q5}, [%[Key]]! \n" + "VLD1.32 {q6}, [%[Key]]! \n" + "VLD1.32 {q7}, [%[Key]]! \n" + "VLD1.32 {q8}, [%[Key]]! \n" + "VLD1.32 {q9}, [%[Key]]! \n" + "VLD1.32 {q10}, [%[Key]]! \n" + "VLD1.32 {q11}, [%[Key]]! \n" + "VLD1.32 {q0}, [%[reg]] \n" + "VLD1.32 {q12}, [%[input]]!\n" + "VLD1.32 {q13}, [%[Key]]! \n" + "VLD1.32 {q14}, [%[Key]]! \n" + + "1:\n" + "#CBC operations, xorbuf in with current aes->reg \n" + "VEOR.32 q0, q0, q12 \n" + "AESE.8 q0, q1 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q2 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q3 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q4 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q5 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q6 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q7 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q8 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q9 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q10 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q11 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q13 \n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q15}, [%[Key]]! \n" + "AESE.8 q0, q14 \n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q15\n" + "VLD1.32 {q15}, [%[Key]] \n" + "VEOR.32 q0, q0, q15 \n" + "SUB r11, r11, #1 \n" + "VST1.32 {q0}, [%[out]]! \n" + "SUB %[Key], %[Key], #16 \n" + + "CMP r11, #0 \n" + "BEQ 2f \n" + "VLD1.32 {q12}, [%[input]]! \n" + "B 1b \n" + + "2:\n" + "#store current counter qalue at the end \n" + "VST1.32 {q0}, [%[regOut]] \n" + + :[out] "=r" (out), [regOut] "=r" (regPt), "=r" (keyPt) + :"0" (out), [Key] "2" (keyPt), [input] "r" (in), + [blocks] "r" (numBlocks), [reg] "1" (regPt) + : "cc", "memory", "r11", "q0", "q1", "q2", "q3", "q4", "q5", + "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + ); + break; +#endif /* WOLFSSL_AES_256 */ + default: + WOLFSSL_MSG("Bad AES-CBC round value"); + return BAD_FUNC_ARG; + } + } + + return 0; + } + + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + word32 numBlocks = sz / AES_BLOCK_SIZE; + + if (aes == NULL || out == NULL || (in == NULL && sz > 0) + || sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + /* do as many block size ops as possible */ + if (numBlocks > 0) { + word32* keyPt = aes->key; + word32* regPt = aes->reg; + switch(aes->rounds) { +#ifdef WOLFSSL_AES_128 + case 10: /* AES 128 BLOCK */ + __asm__ __volatile__ ( + "MOV r11, %[blocks] \n" + "VLD1.32 {q1}, [%[Key]]! \n" + "VLD1.32 {q2}, [%[Key]]! \n" + "VLD1.32 {q3}, [%[Key]]! \n" + "VLD1.32 {q4}, [%[Key]]! \n" + "VLD1.32 {q5}, [%[Key]]! \n" + "VLD1.32 {q6}, [%[Key]]! \n" + "VLD1.32 {q7}, [%[Key]]! \n" + "VLD1.32 {q8}, [%[Key]]! \n" + "VLD1.32 {q9}, [%[Key]]! \n" + "VLD1.32 {q10}, [%[Key]]! \n" + "VLD1.32 {q11}, [%[Key]]! \n" + "VLD1.32 {q13}, [%[reg]] \n" + "VLD1.32 {q0}, [%[input]]!\n" + + "1:\n" + "VMOV.32 q12, q0 \n" + "AESD.8 q0, q1\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q2\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q3\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q4\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q5\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q6\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q7\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q8\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q9\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q10\n" + "VEOR.32 q0, q0, q11\n" + + "VEOR.32 q0, q0, q13\n" + "SUB r11, r11, #1 \n" + "VST1.32 {q0}, [%[out]]! \n" + "VMOV.32 q13, q12 \n" + + "CMP r11, #0 \n" + "BEQ 2f \n" + "VLD1.32 {q0}, [%[input]]! \n" + "B 1b \n" + + "2: \n" + "#store current counter qalue at the end \n" + "VST1.32 {q13}, [%[regOut]] \n" + + :[out] "=r" (out), [regOut] "=r" (regPt) + :"0" (out), [Key] "r" (keyPt), [input] "r" (in), + [blocks] "r" (numBlocks), [reg] "1" (regPt) + : "cc", "memory", "r11", "q0", "q1", "q2", "q3", "q4", "q5", + "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13" + ); + break; +#endif /* WOLFSSL_AES_128 */ +#ifdef WOLFSSL_AES_192 + case 12: /* AES 192 BLOCK */ + __asm__ __volatile__ ( + "MOV r11, %[blocks] \n" + "VLD1.32 {q1}, [%[Key]]! \n" + "VLD1.32 {q2}, [%[Key]]! \n" + "VLD1.32 {q3}, [%[Key]]! \n" + "VLD1.32 {q4}, [%[Key]]! \n" + "VLD1.32 {q5}, [%[Key]]! \n" + "VLD1.32 {q6}, [%[Key]]! \n" + "VLD1.32 {q7}, [%[Key]]! \n" + "VLD1.32 {q8}, [%[Key]]! \n" + "VLD1.32 {q9}, [%[Key]]! \n" + "VLD1.32 {q10}, [%[Key]]! \n" + "VLD1.32 {q11}, [%[Key]]! \n" + "VLD1.32 {q12}, [%[Key]]! \n" + "VLD1.32 {q13}, [%[Key]]! \n" + "VLD1.32 {q14}, [%[reg]] \n" + "VLD1.32 {q0}, [%[input]]!\n" + + "1: \n" + "VMOV.32 q15, q0 \n" + "AESD.8 q0, q1\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q2\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q3\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q4\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q5\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q6\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q7\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q8\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q9\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q10\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q11\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q12\n" + "VEOR.32 q0, q0, q13\n" + + "VEOR.32 q0, q0, q14\n" + "SUB r11, r11, #1 \n" + "VST1.32 {q0}, [%[out]]! \n" + "VMOV.32 q14, q15 \n" + + "CMP r11, #0 \n" + "BEQ 2f \n" + "VLD1.32 {q0}, [%[input]]! \n" + "B 1b \n" + + "2:\n" + "#store current counter value at the end \n" + "VST1.32 {q15}, [%[regOut]] \n" + + :[out] "=r" (out), [regOut] "=r" (regPt) + :"0" (out), [Key] "r" (keyPt), [input] "r" (in), + [blocks] "r" (numBlocks), [reg] "1" (regPt) + : "cc", "memory", "r11", "q0", "q1", "q2", "q3", "q4", "q5", + "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + ); + break; +#endif /* WOLFSSL_AES_192 */ +#ifdef WOLFSSL_AES_256 + case 14: /* AES 256 BLOCK */ + __asm__ __volatile__ ( + "MOV r11, %[blocks] \n" + "VLD1.32 {q1}, [%[Key]]! \n" + "VLD1.32 {q2}, [%[Key]]! \n" + "VLD1.32 {q3}, [%[Key]]! \n" + "VLD1.32 {q4}, [%[Key]]! \n" + "VLD1.32 {q5}, [%[Key]]! \n" + "VLD1.32 {q6}, [%[Key]]! \n" + "VLD1.32 {q7}, [%[Key]]! \n" + "VLD1.32 {q8}, [%[Key]]! \n" + "VLD1.32 {q9}, [%[Key]]! \n" + "VLD1.32 {q10}, [%[Key]]! \n" + "VLD1.32 {q11}, [%[Key]]! \n" + "VLD1.32 {q12}, [%[Key]]! \n" + "VLD1.32 {q14}, [%[reg]] \n" + "VLD1.32 {q0}, [%[input]]!\n" + + "1:\n" + "VMOV.32 q15, q0 \n" + "AESD.8 q0, q1\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q2\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q3\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q4\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q5\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q6\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q7\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q8\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q9\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q10\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q11\n" + "AESIMC.8 q0, q0\n" + "VLD1.32 {q13}, [%[Key]]! \n" + "AESD.8 q0, q12\n" + "AESIMC.8 q0, q0\n" + "AESD.8 q0, q13\n" + "AESIMC.8 q0, q0\n" + "VLD1.32 {q13}, [%[Key]]! \n" + "AESD.8 q0, q13\n" + "VLD1.32 {q13}, [%[Key]] \n" + "VEOR.32 q0, q0, q13\n" + "SUB %[Key], %[Key], #32 \n" + + "VEOR.32 q0, q0, q14\n" + "SUB r11, r11, #1 \n" + "VST1.32 {q0}, [%[out]]! \n" + "VMOV.32 q14, q15 \n" + + "CMP r11, #0 \n" + "BEQ 2f \n" + "VLD1.32 {q0}, [%[input]]! \n" + "B 1b \n" + + "2:\n" + "#store current counter value at the end \n" + "VST1.32 {q15}, [%[regOut]] \n" + + :[out] "=r" (out), [regOut] "=r" (regPt) + :"0" (out), [Key] "r" (keyPt), [input] "r" (in), + [blocks] "r" (numBlocks), [reg] "1" (regPt) + : "cc", "memory", "r11", "q0", "q1", "q2", "q3", "q4", "q5", + "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" + ); + break; +#endif /* WOLFSSL_AES_256 */ + default: + WOLFSSL_MSG("Bad AES-CBC round value"); + return BAD_FUNC_ARG; + } + } + + return 0; + } + #endif + +#endif /* HAVE_AES_CBC */ + +/* AES-CTR */ +#ifdef WOLFSSL_AES_COUNTER + + /* Increment AES counter */ + static WC_INLINE void IncrementAesCounter(byte* inOutCtr) + { + int i; + + /* in network byte order so start at end and work back */ + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } + } + + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + 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++); + aes->left--; + sz--; + } + + /* do as many block size ops as possible */ + numBlocks = sz/AES_BLOCK_SIZE; + if (numBlocks > 0) { + /* pointer needed because it is incremented when read, causing + * an issue with call to encrypt/decrypt leftovers */ + word32* keyPt = aes->key; + word32* regPt = aes->reg; + sz -= numBlocks * AES_BLOCK_SIZE; + switch(aes->rounds) { +#ifdef WOLFSSL_AES_128 + case 10: /* AES 128 BLOCK */ + __asm__ __volatile__ ( + "MOV r11, %[blocks] \n" + "VLDM %[Key]!, {q1-q4} \n" + + "#Create vector with the value 1 \n" + "VMOV.u32 q15, #1 \n" + "VSHR.u64 q15, q15, #32 \n" + "VLDM %[Key]!, {q5-q8} \n" + "VEOR.32 q14, q14, q14 \n" + "VLDM %[Key]!, {q9-q11} \n" + "VEXT.8 q14, q15, q14, #8\n" + + "VLD1.32 {q13}, [%[reg]]\n" + + /* double block */ + "1: \n" + "CMP r11, #1 \n" + "BEQ 2f \n" + "CMP r11, #0 \n" + "BEQ 3f \n" + + "VMOV.32 q0, q13 \n" + "AESE.8 q0, q1\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q13, q13 \n" /* network order */ + "AESE.8 q0, q2\n" + "AESMC.8 q0, q0\n" + "VEXT.8 q13, q13, q13, #8 \n" + "SUB r11, r11, #2 \n" + "VADD.i32 q15, q13, q14 \n" /* add 1 to counter */ + "VADD.i32 q13, q15, q14 \n" /* add 1 to counter */ + "AESE.8 q0, q3\n" + "AESMC.8 q0, q0\n" + "VEXT.8 q15, q15, q15, #8 \n" + "VEXT.8 q13, q13, q13, #8 \n" + "AESE.8 q0, q4\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q15, q15\n" /* revert from network order */ + "VREV64.8 q13, q13\n" /* revert from network order */ + "AESE.8 q0, q5\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q1\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q6\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q2\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q7\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q3\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q8\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q4\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q9\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q5\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q10\n" + "AESE.8 q15, q6\n" + "AESMC.8 q15, q15\n" + "VEOR.32 q0, q0, q11\n" + + "AESE.8 q15, q7\n" + "AESMC.8 q15, q15\n" + "VLD1.32 {q12}, [%[input]]! \n" + "AESE.8 q15, q8\n" + "AESMC.8 q15, q15\n" + + "VEOR.32 q0, q0, q12\n" + "AESE.8 q15, q9\n" + "AESMC.8 q15, q15\n" + + "VLD1.32 {q12}, [%[input]]! \n" + "AESE.8 q15, q10\n" + "VST1.32 {q0}, [%[out]]! \n" + "VEOR.32 q15, q15, q11\n" + "VEOR.32 q15, q15, q12\n" + "VST1.32 {q15}, [%[out]]! \n" + + "B 1b \n" + + /* single block */ + "2: \n" + "VMOV.32 q0, q13 \n" + "AESE.8 q0, q1\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q13, q13 \n" /* network order */ + "AESE.8 q0, q2\n" + "AESMC.8 q0, q0\n" + "VEXT.8 q13, q13, q13, #8 \n" + "AESE.8 q0, q3\n" + "AESMC.8 q0, q0\n" + "VADD.i32 q13, q13, q14 \n" /* add 1 to counter */ + "AESE.8 q0, q4\n" + "AESMC.8 q0, q0\n" + "SUB r11, r11, #1 \n" + "AESE.8 q0, q5\n" + "AESMC.8 q0, q0\n" + "VEXT.8 q13, q13, q13, #8 \n" + "AESE.8 q0, q6\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q13, q13\n" /* revert from network order */ + "AESE.8 q0, q7\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q8\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q9\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q10\n" + "VLD1.32 {q12}, [%[input]]! \n" + "VEOR.32 q0, q0, q11\n" + "#CTR operations, increment counter and xorbuf \n" + "VEOR.32 q0, q0, q12\n" + "VST1.32 {q0}, [%[out]]! \n" + + "3: \n" + "#store current counter qalue at the end \n" + "VST1.32 {q13}, [%[regOut]] \n" + + :[out] "=r" (out), "=r" (keyPt), [regOut] "=r" (regPt), + "=r" (in) + :"0" (out), [Key] "1" (keyPt), [input] "3" (in), + [blocks] "r" (numBlocks), [reg] "2" (regPt) + : "cc", "memory", "r11", "q0", "q1", "q2", "q3", "q4", "q5", + "q6", "q7", "q8", "q9", "q10","q11","q12","q13","q14", "q15" + ); + break; +#endif /* WOLFSSL_AES_128 */ +#ifdef WOLFSSL_AES_192 + case 12: /* AES 192 BLOCK */ + __asm__ __volatile__ ( + "MOV r11, %[blocks] \n" + "VLDM %[Key]!, {q1-q4} \n" + + "#Create vector with the value 1 \n" + "VMOV.u32 q15, #1 \n" + "VSHR.u64 q15, q15, #32 \n" + "VLDM %[Key]!, {q5-q8} \n" + "VEOR.32 q14, q14, q14 \n" + "VEXT.8 q14, q15, q14, #8\n" + + "VLDM %[Key]!, {q9-q10} \n" + "VLD1.32 {q13}, [%[reg]]\n" + + /* double block */ + "1: \n" + "CMP r11, #1 \n" + "BEQ 2f \n" + "CMP r11, #0 \n" + "BEQ 3f \n" + + "VMOV.32 q0, q13\n" + "AESE.8 q0, q1\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q13, q13 \n" /* network order */ + "AESE.8 q0, q2\n" + "AESMC.8 q0, q0\n" + "VEXT.8 q13, q13, q13, #8 \n" + "SUB r11, r11, #2 \n" + "VADD.i32 q15, q13, q14 \n" /* add 1 to counter */ + "VADD.i32 q13, q15, q14 \n" /* add 1 to counter */ + "AESE.8 q0, q3\n" + "AESMC.8 q0, q0\n" + "VEXT.8 q15, q15, q15, #8 \n" + "VEXT.8 q13, q13, q13, #8 \n" + "AESE.8 q0, q4\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q15, q15\n" /* revert from network order */ + "VREV64.8 q13, q13\n" /* revert from network order */ + "AESE.8 q0, q5\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q1\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q6\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q2\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q7\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q3\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q8\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q4\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q9\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q5\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q10\n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q11}, [%[Key]]! \n" + "AESE.8 q15, q6\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q11\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q7\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q15, q8\n" + "AESMC.8 q15, q15\n" + + "VLD1.32 {q12}, [%[Key]]! \n" + "AESE.8 q15, q9\n" + "AESMC.8 q15, q15\n" + "AESE.8 q15, q10\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q15, q11\n" + "AESMC.8 q15, q15\n" + "VLD1.32 {q11}, [%[Key]] \n" + "AESE.8 q0, q12\n" + "AESE.8 q15, q12\n" + + "VLD1.32 {q12}, [%[input]]! \n" + "VEOR.32 q0, q0, q11\n" + "VEOR.32 q15, q15, q11\n" + "VEOR.32 q0, q0, q12\n" + + "VLD1.32 {q12}, [%[input]]! \n" + "VST1.32 {q0}, [%[out]]! \n" + "VEOR.32 q15, q15, q12\n" + "VST1.32 {q15}, [%[out]]! \n" + "SUB %[Key], %[Key], #32 \n" + + "B 1b \n" + + + /* single block */ + "2: \n" + "VLD1.32 {q11}, [%[Key]]! \n" + "VMOV.32 q0, q13 \n" + "AESE.8 q0, q1\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q13, q13 \n" /* network order */ + "AESE.8 q0, q2\n" + "AESMC.8 q0, q0\n" + "VEXT.8 q13, q13, q13, #8 \n" + "AESE.8 q0, q3\n" + "AESMC.8 q0, q0\n" + "VADD.i32 q13, q13, q14 \n" /* add 1 to counter */ + "AESE.8 q0, q4\n" + "AESMC.8 q0, q0\n" + "SUB r11, r11, #1 \n" + "AESE.8 q0, q5\n" + "AESMC.8 q0, q0\n" + "VEXT.8 q13, q13, q13, #8 \n" + "AESE.8 q0, q6\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q13, q13\n" /* revert from network order */ + "AESE.8 q0, q7\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q8\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q9\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q10\n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q12}, [%[Key]]! \n" + "AESE.8 q0, q11\n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q11}, [%[Key]] \n" + "AESE.8 q0, q12\n" + "VLD1.32 {q12}, [%[input]]! \n" + "VEOR.32 q0, q0, q11\n" + "#CTR operations, increment counter and xorbuf \n" + "VEOR.32 q0, q0, q12\n" + "VST1.32 {q0}, [%[out]]! \n" + + "3: \n" + "#store current counter qalue at the end \n" + "VST1.32 {q13}, [%[regOut]] \n" + + :[out] "=r" (out), "=r" (keyPt), [regOut] "=r" (regPt), + "=r" (in) + :"0" (out), [Key] "1" (keyPt), [input] "3" (in), + [blocks] "r" (numBlocks), [reg] "2" (regPt) + : "cc", "memory", "r11", "q0", "q1", "q2", "q3", "q4", "q5", + "q6", "q7", "q8", "q9", "q10","q11","q12","q13","q14" + ); + break; +#endif /* WOLFSSL_AES_192 */ +#ifdef WOLFSSL_AES_256 + case 14: /* AES 256 BLOCK */ + __asm__ __volatile__ ( + "MOV r11, %[blocks] \n" + "VLDM %[Key]!, {q1-q4} \n" + + "#Create vector with the value 1 \n" + "VMOV.u32 q15, #1 \n" + "VSHR.u64 q15, q15, #32 \n" + "VLDM %[Key]!, {q5-q8} \n" + "VEOR.32 q14, q14, q14 \n" + "VEXT.8 q14, q15, q14, #8\n" + + "VLDM %[Key]!, {q9-q10} \n" + "VLD1.32 {q13}, [%[reg]]\n" + + /* double block */ + "1: \n" + "CMP r11, #1 \n" + "BEQ 2f \n" + "CMP r11, #0 \n" + "BEQ 3f \n" + + "VMOV.32 q0, q13 \n" + "AESE.8 q0, q1\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q13, q13 \n" /* network order */ + "AESE.8 q0, q2\n" + "AESMC.8 q0, q0\n" + "VEXT.8 q13, q13, q13, #8 \n" + "SUB r11, r11, #2 \n" + "VADD.i32 q15, q13, q14 \n" /* add 1 to counter */ + "VADD.i32 q13, q15, q14 \n" /* add 1 to counter */ + "AESE.8 q0, q3\n" + "AESMC.8 q0, q0\n" + "VEXT.8 q15, q15, q15, #8 \n" + "VEXT.8 q13, q13, q13, #8 \n" + "AESE.8 q0, q4\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q15, q15\n" /* revert from network order */ + "AESE.8 q0, q5\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q13, q13\n" /* revert from network order */ + "AESE.8 q15, q1\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q6\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q2\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q7\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q3\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q8\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q4\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q9\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q5\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q10\n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q11}, [%[Key]]! \n" + "AESE.8 q15, q6\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q0, q11\n" + "AESMC.8 q0, q0\n" + "AESE.8 q15, q7\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q15, q8\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q15, q9\n" + "AESMC.8 q15, q15\n" + "VLD1.32 {q12}, [%[Key]]! \n" + "AESE.8 q15, q10\n" + "AESMC.8 q15, q15\n" + + "AESE.8 q15, q11\n" + "AESMC.8 q15, q15\n" + + "VLD1.32 {q11}, [%[Key]]! \n" + "AESE.8 q0, q12\n" /* rnd 12*/ + "AESMC.8 q0, q0\n" + "AESE.8 q15, q12\n" /* rnd 12 */ + "AESMC.8 q15, q15\n" + + "VLD1.32 {q12}, [%[Key]]! \n" + "AESE.8 q0, q11\n" /* rnd 13 */ + "AESMC.8 q0, q0\n" + "AESE.8 q15, q11\n" /* rnd 13 */ + "AESMC.8 q15, q15\n" + + "VLD1.32 {q11}, [%[Key]] \n" + "AESE.8 q0, q12\n" /* rnd 14 */ + "AESE.8 q15, q12\n" /* rnd 14 */ + + "VLD1.32 {q12}, [%[input]]! \n" + "VEOR.32 q0, q0, q11\n" /* rnd 15 */ + "VEOR.32 q15, q15, q11\n" /* rnd 15 */ + "VEOR.32 q0, q0, q12\n" + + "VLD1.32 {q12}, [%[input]]! \n" + "VST1.32 {q0}, [%[out]]! \n" + "VEOR.32 q15, q15, q12\n" + "VST1.32 {q15}, [%[out]]! \n" + "SUB %[Key], %[Key], #64 \n" + + /* single block */ + "B 1b \n" + + "2: \n" + "VLD1.32 {q11}, [%[Key]]! \n" + "VMOV.32 q0, q13 \n" + "AESE.8 q0, q1\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q13, q13 \n" /* network order */ + "AESE.8 q0, q2\n" + "AESMC.8 q0, q0\n" + "VEXT.8 q13, q13, q13, #8 \n" + "AESE.8 q0, q3\n" + "AESMC.8 q0, q0\n" + "VADD.i32 q13, q13, q14 \n" /* add 1 to counter */ + "AESE.8 q0, q4\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q5\n" + "AESMC.8 q0, q0\n" + "VEXT.8 q13, q13, q13, #8 \n" + "AESE.8 q0, q6\n" + "AESMC.8 q0, q0\n" + "VREV64.8 q13, q13\n" /* revert from network order */ + "AESE.8 q0, q7\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q8\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q9\n" + "AESMC.8 q0, q0\n" + "AESE.8 q0, q10\n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q12}, [%[Key]]! \n" + "AESE.8 q0, q11\n" + "AESMC.8 q0, q0\n" + "VLD1.32 {q11}, [%[Key]]! \n" + "AESE.8 q0, q12\n" /* rnd 12 */ + "AESMC.8 q0, q0\n" + "VLD1.32 {q12}, [%[Key]]! \n" + "AESE.8 q0, q11\n" /* rnd 13 */ + "AESMC.8 q0, q0\n" + "VLD1.32 {q11}, [%[Key]] \n" + "AESE.8 q0, q12\n" /* rnd 14 */ + "VLD1.32 {q12}, [%[input]]! \n" + "VEOR.32 q0, q0, q11\n" /* rnd 15 */ + "#CTR operations, increment counter and xorbuf \n" + "VEOR.32 q0, q0, q12\n" + "VST1.32 {q0}, [%[out]]! \n" + + "3: \n" + "#store current counter qalue at the end \n" + "VST1.32 {q13}, [%[regOut]] \n" + + :[out] "=r" (out), "=r" (keyPt), [regOut] "=r" (regPt), + "=r" (in) + :"0" (out), [Key] "1" (keyPt), [input] "3" (in), + [blocks] "r" (numBlocks), [reg] "2" (regPt) + : "cc", "memory", "r11", "q0", "q1", "q2", "q3", "q4", "q5", + "q6", "q7", "q8", "q9", "q10","q11","q12","q13","q14" + ); + break; +#endif /* WOLFSSL_AES_256 */ + default: + WOLFSSL_MSG("Bad AES-CTR round qalue"); + return BAD_FUNC_ARG; + } + + aes->left = 0; + } + + /* handle non block size remaining */ + if (sz) { + wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->tmp); + IncrementAesCounter((byte*)aes->reg); + + aes->left = AES_BLOCK_SIZE; + tmp = (byte*)aes->tmp; + + while (sz--) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + } + } + + return 0; + } + +#endif /* WOLFSSL_AES_COUNTER */ + +#ifdef HAVE_AESGCM +/* + * Uses Karatsuba algorithm. Reduction algorithm is based on "Implementing GCM + * on ARMv8". Shifting left to account for bit reflection is based on + * "Carry-Less Multiplication and Its Usage for Computing the GCM mode" + */ +static void GMULT(byte* X, byte* Y) +{ + __asm__ __volatile__ ( + "VLD1.32 {q0}, [%[x]] \n" + + /* In GCM format bits are big endian, switch location of bytes to + * allow for logical shifts and carries. + */ + "VREV64.8 q0, q0 \n" + "VLD1.32 {q1}, [%[y]] \n" /* converted on set key */ + "VSWP.8 d0, d1 \n" + + "VMULL.p64 q5, d0, d2 \n" + "VMULL.p64 q6, d1, d3 \n" + "VEOR d15, d2, d3 \n" + "VEOR d14, d0, d1 \n" + "VMULL.p64 q7, d15, d14 \n" + "VEOR q7, q5 \n" + "VEOR q7, q6 \n" + "VEOR d11, d14 \n" + "VEOR d12, d15\n" + + /* shift to left by 1 to account for reflection */ + "VMOV q7, q6 \n" + "VSHL.u64 q6, q6, #1 \n" + "VSHR.u64 q7, q7, #63 \n" + "VEOR d13, d14 \n" + "VMOV q8, q5 \n" + "VSHL.u64 q5, q5, #1 \n" + "VSHR.u64 q8, q8, #63 \n" + "VEOR d12, d17 \n" + "VEOR d11, d16 \n" + + /* create constant 0xc200000000000000 */ + "VMOV.i32 d16, 0xc2000000 \n" + "VSHL.u64 d16, d16, #32 \n" + + /* reduce product of multiplication */ + "VMULL.p64 q9, d10, d16 \n" + "VEOR d11, d18 \n" + "VEOR d12, d19 \n" + "VMULL.p64 q9, d11, d16 \n" + "VEOR q6, q9 \n" + "VEOR q10, q5, q6 \n" + + /* convert to GCM format */ + "VREV64.8 q10, q10 \n" + "VSWP.8 d20, d21 \n" + + "VST1.32 {q10}, [%[xOut]] \n" + + : [xOut] "=r" (X), [yOut] "=r" (Y) + : [x] "0" (X), [y] "1" (Y) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6" ,"q7", "q8", + "q9", "q10", "q11" ,"q12", "q13", "q14", "q15" + ); +} + + +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]; + word32 blocks, partial; + byte* h = aes->H; + + XMEMSET(x, 0, AES_BLOCK_SIZE); + + /* Hash in A, the Additional Authentication Data */ + if (aSz != 0 && a != NULL) { + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, a, AES_BLOCK_SIZE); + GMULT(x, h); + a += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, a, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, h); + } + } + + /* Hash in C, the Ciphertext */ + if (cSz != 0 && c != NULL) { + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, c, AES_BLOCK_SIZE); + GMULT(x, h); + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, c, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, h); + } + } + + /* Hash in the lengths of A and C in bits */ + FlattenSzInBits(&scratch[0], aSz); + FlattenSzInBits(&scratch[8], cSz); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, h); + + /* Copy the result into s. */ + XMEMCPY(s, x, sSz); +} + + +/* Aarch32 + * Encrypt and tag data using AES with GCM mode. + * aes: Aes structure having already been set with set key function + * out: encrypted data output buffer + * in: plain text input buffer + * sz: size of plain text and out buffer + * iv: initialization vector + * ivSz: size of iv buffer + * authTag: buffer to hold tag + * authTagSz: size of tag buffer + * authIn: additional data buffer + * authInSz: size of additional data buffer + */ +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) +{ + 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 scratch[AES_BLOCK_SIZE]; + ctr = counter ; + + /* sanity checks */ + if (aes == NULL || (iv == NULL && ivSz > 0) || + (authTag == 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; + } + + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[AES_BLOCK_SIZE - 1] = 1; + } + else { + GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE); + } + XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE); + + while (blocks--) { + IncrementGcmCounter(ctr); + wc_AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, p, AES_BLOCK_SIZE); + XMEMCPY(c, scratch, AES_BLOCK_SIZE); + p += AES_BLOCK_SIZE; + c += AES_BLOCK_SIZE; + } + + if (partial != 0) { + IncrementGcmCounter(ctr); + wc_AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, p, partial); + XMEMCPY(c, scratch, partial); + + } + + GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz); + wc_AesEncrypt(aes, initialCounter, scratch); + if (authTagSz > AES_BLOCK_SIZE) { + xorbuf(authTag, scratch, AES_BLOCK_SIZE); + } + else { + xorbuf(authTag, scratch, authTagSz); + } + + return 0; +} + + +#ifdef HAVE_AES_DECRYPT +/* + * Check tag and decrypt data using AES with GCM mode. + * aes: Aes structure having already been set with set key function + * out: decrypted data output buffer + * in: cipher text buffer + * sz: size of plain text and out buffer + * iv: initialization vector + * ivSz: size of iv buffer + * authTag: buffer holding tag + * authTagSz: size of tag buffer + * authIn: additional data buffer + * authInSz: size of additional data buffer + */ +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) +{ + 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 scratch[AES_BLOCK_SIZE]; + ctr = counter ; + + /* sanity checks */ + if (aes == NULL || (iv == NULL && ivSz > 0) || + (authTag == 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; + } + + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[AES_BLOCK_SIZE - 1] = 1; + } + else { + GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE); + } + 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]; + + 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; + } + } + + while (blocks--) { + IncrementGcmCounter(ctr); + wc_AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, c, AES_BLOCK_SIZE); + XMEMCPY(p, scratch, AES_BLOCK_SIZE); + p += AES_BLOCK_SIZE; + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + IncrementGcmCounter(ctr); + wc_AesEncrypt(aes, ctr, scratch); + + /* check if pointer is null after main AES-GCM blocks + * helps static analysis */ + if (p == NULL || c == NULL) { + return BAD_STATE_E; + } + xorbuf(scratch, c, partial); + XMEMCPY(p, scratch, partial); + } + return 0; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AESGCM */ + +#endif /* aarch64 */ + + +#ifdef HAVE_AESCCM +/* Software version of AES-CCM from wolfcrypt/src/aes.c + * Gets some speed up from hardware acceleration of wc_AesEncrypt */ + +static void roll_x(Aes* aes, const byte* in, word32 inSz, byte* out) +{ + /* process the bulk of the data */ + while (inSz >= AES_BLOCK_SIZE) { + xorbuf(out, in, AES_BLOCK_SIZE); + in += AES_BLOCK_SIZE; + inSz -= AES_BLOCK_SIZE; + + wc_AesEncrypt(aes, out, out); + } + + /* process remainder of the data */ + if (inSz > 0) { + xorbuf(out, in, inSz); + wc_AesEncrypt(aes, out, out); + } +} + + +static void roll_auth(Aes* aes, const byte* in, word32 inSz, byte* out) +{ + word32 authLenSz; + word32 remainder; + + /* encode the length in */ + if (inSz <= 0xFEFF) { + authLenSz = 2; + out[0] ^= ((inSz & 0xFF00) >> 8); + out[1] ^= (inSz & 0x00FF); + } + else if (inSz <= 0xFFFFFFFF) { + authLenSz = 6; + out[0] ^= 0xFF; out[1] ^= 0xFE; + out[2] ^= ((inSz & 0xFF000000) >> 24); + out[3] ^= ((inSz & 0x00FF0000) >> 16); + out[4] ^= ((inSz & 0x0000FF00) >> 8); + out[5] ^= (inSz & 0x000000FF); + } + /* Note, the protocol handles auth data up to 2^64, but we are + * using 32-bit sizes right now, so the bigger data isn't handled + * else if (inSz <= 0xFFFFFFFFFFFFFFFF) {} */ + else + return; + + /* start fill out the rest of the first block */ + remainder = AES_BLOCK_SIZE - authLenSz; + if (inSz >= remainder) { + /* plenty of bulk data to fill the remainder of this block */ + xorbuf(out + authLenSz, in, remainder); + inSz -= remainder; + in += remainder; + } + else { + /* not enough bulk data, copy what is available, and pad zero */ + xorbuf(out + authLenSz, in, inSz); + inSz = 0; + } + wc_AesEncrypt(aes, out, out); + + if (inSz > 0) + roll_x(aes, in, inSz, out); +} + + +static WC_INLINE void AesCcmCtrInc(byte* B, word32 lenSz) +{ + word32 i; + + for (i = 0; i < lenSz; i++) { + if (++B[AES_BLOCK_SIZE - 1 - i] != 0) return; + } +} + + +/* 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 A[AES_BLOCK_SIZE]; + byte B[AES_BLOCK_SIZE]; + byte lenSz; + word32 i; + byte mask = 0xFF; + word32 wordSz = (word32)sizeof(word32); + + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) + return BAD_FUNC_ARG; + + XMEMCPY(B+1, nonce, nonceSz); + lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz; + B[0] = (authInSz > 0 ? 64 : 0) + + (8 * (((byte)authTagSz - 2) / 2)) + + (lenSz - 1); + for (i = 0; i < lenSz; i++) { + if (mask && i >= wordSz) + mask = 0x00; + B[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask; + } + + wc_AesEncrypt(aes, B, A); + + if (authInSz > 0) + roll_auth(aes, authIn, authInSz, A); + if (inSz > 0) + roll_x(aes, in, inSz, A); + XMEMCPY(authTag, A, authTagSz); + + B[0] = lenSz - 1; + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = 0; + wc_AesEncrypt(aes, B, A); + xorbuf(authTag, A, authTagSz); + + B[15] = 1; + while (inSz >= AES_BLOCK_SIZE) { + wc_AesEncrypt(aes, B, A); + xorbuf(A, in, AES_BLOCK_SIZE); + XMEMCPY(out, A, AES_BLOCK_SIZE); + + AesCcmCtrInc(B, lenSz); + inSz -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + if (inSz > 0) { + wc_AesEncrypt(aes, B, A); + xorbuf(A, in, inSz); + XMEMCPY(out, A, inSz); + } + + ForceZero(A, AES_BLOCK_SIZE); + ForceZero(B, AES_BLOCK_SIZE); + + return 0; +} + +#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 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); + + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) + return BAD_FUNC_ARG; + + o = out; + oSz = inSz; + XMEMCPY(B+1, nonce, nonceSz); + lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz; + + B[0] = lenSz - 1; + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = 0; + B[15] = 1; + + while (oSz >= AES_BLOCK_SIZE) { + wc_AesEncrypt(aes, B, A); + xorbuf(A, in, AES_BLOCK_SIZE); + XMEMCPY(o, A, AES_BLOCK_SIZE); + + AesCcmCtrInc(B, lenSz); + oSz -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + o += AES_BLOCK_SIZE; + } + if (inSz > 0) { + wc_AesEncrypt(aes, B, A); + xorbuf(A, in, oSz); + XMEMCPY(o, A, oSz); + } + + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = 0; + wc_AesEncrypt(aes, B, A); + + o = out; + oSz = inSz; + + B[0] = (authInSz > 0 ? 64 : 0) + + (8 * (((byte)authTagSz - 2) / 2)) + + (lenSz - 1); + for (i = 0; i < lenSz; i++) { + if (mask && i >= wordSz) + mask = 0x00; + B[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask; + } + + wc_AesEncrypt(aes, B, A); + + if (authInSz > 0) + roll_auth(aes, authIn, authInSz, A); + if (inSz > 0) + roll_x(aes, o, oSz, A); + + B[0] = lenSz - 1; + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = 0; + wc_AesEncrypt(aes, B, B); + xorbuf(A, B, authTagSz); + + if (ConstantCompare(A, authTag, authTagSz) != 0) { + /* If the authTag check fails, don't keep the decrypted data. + * Unfortunately, you need the decrypted data to calculate the + * check value. */ + XMEMSET(out, 0, inSz); + result = AES_CCM_AUTH_E; + } + + ForceZero(A, AES_BLOCK_SIZE); + ForceZero(B, AES_BLOCK_SIZE); + o = NULL; + + return result; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AESCCM */ + + + +#ifdef HAVE_AESGCM /* common GCM functions 32 and 64 bit */ +int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) +{ + int ret; + byte iv[AES_BLOCK_SIZE]; + + if (!((len == 16) || (len == 24) || (len == 32))) + return BAD_FUNC_ARG; + + XMEMSET(iv, 0, AES_BLOCK_SIZE); + ret = wc_AesSetKey(aes, key, len, iv, AES_ENCRYPTION); + + if (ret == 0) { + wc_AesEncrypt(aes, iv, aes->H); + #if defined(__aarch64__) + { + word32* pt = (word32*)aes->H; + __asm__ volatile ( + "LD1 {v0.16b}, [%[h]] \n" + "RBIT v0.16b, v0.16b \n" + "ST1 {v0.16b}, [%[out]] \n" + : [out] "=r" (pt) + : [h] "0" (pt) + : "cc", "memory", "v0" + ); + } + #else + { + word32* pt = (word32*)aes->H; + __asm__ volatile ( + "VLD1.32 {q0}, [%[h]] \n" + "VREV64.8 q0, q0 \n" + "VSWP.8 d0, d1 \n" + "VST1.32 {q0}, [%[out]] \n" + : [out] "=r" (pt) + : [h] "0" (pt) + : "cc", "memory", "q0" + ); + } + #endif + } + + return ret; +} + +#endif /* HAVE_AESGCM */ + +/* AES-DIRECT */ +#if defined(WOLFSSL_AES_DIRECT) + /* Allow direct access to one block encrypt */ + void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) + { + if (aes == NULL || out == NULL || in == NULL) { + WOLFSSL_MSG("Invalid input to wc_AesEncryptDirect"); + return; + } + wc_AesEncrypt(aes, in, out); + } + #ifdef HAVE_AES_DECRYPT + /* Allow direct access to one block decrypt */ + void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) + { + if (aes == NULL || out == NULL || in == NULL) { + WOLFSSL_MSG("Invalid input to wc_AesDecryptDirect"); + return; + } + wc_AesDecrypt(aes, in, out); + } + #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_DIRECT */ +#endif /* !NO_AES && WOLFSSL_ARMASM */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-chacha.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-chacha.c new file mode 100644 index 000000000..df76bece0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-chacha.c @@ -0,0 +1,2857 @@ +/* armv8-chacha.c + * + * Copyright (C) 2006-2020 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 + * + */ + +/* The paper NEON crypto by Daniel J. Bernstein and Peter Schwabe was used to optimize for ARM + * https://cryptojedi.org/papers/neoncrypto-20120320.pdf + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_ARMASM +#ifdef HAVE_CHACHA + +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef CHACHA_AEAD_TEST + #include +#endif + +#ifdef CHACHA_TEST + #include +#endif + +#ifdef BIG_ENDIAN_ORDER + #define LITTLE32(x) ByteReverseWord32(x) +#else + #define LITTLE32(x) (x) +#endif + +/* Number of rounds */ +#define ROUNDS 20 + +#define U32C(v) (v##U) +#define U32V(v) ((word32)(v) & U32C(0xFFFFFFFF)) +#define U8TO32_LITTLE(p) LITTLE32(((word32*)(p))[0]) + +#define PLUS(v,w) (U32V((v) + (w))) +#define PLUSONE(v) (PLUS((v),1)) + +#define ARM_SIMD_LEN_BYTES 16 + +/** + * 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. + */ +int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter) +{ + word32 temp[CHACHA_IV_WORDS];/* used for alignment of memory */ + +#ifdef CHACHA_AEAD_TEST + word32 i; + printf("NONCE : "); + for (i = 0; i < CHACHA_IV_BYTES; i++) { + printf("%02x", inIv[i]); + } + printf("\n\n"); +#endif + + if (ctx == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(temp, inIv, CHACHA_IV_BYTES); + + ctx->X[CHACHA_IV_BYTES+0] = counter; /* block counter */ + ctx->X[CHACHA_IV_BYTES+1] = LITTLE32(temp[0]); /* fixed variable from nonce */ + ctx->X[CHACHA_IV_BYTES+2] = LITTLE32(temp[1]); /* counter from nonce */ + ctx->X[CHACHA_IV_BYTES+3] = LITTLE32(temp[2]); /* counter from nonce */ + + return 0; +} + +/* "expand 32-byte k" as unsigned 32 byte */ +static const word32 sigma[4] = {0x61707865, 0x3320646e, 0x79622d32, 0x6b206574}; +/* "expand 16-byte k" as unsigned 16 byte */ +static const word32 tau[4] = {0x61707865, 0x3120646e, 0x79622d36, 0x6b206574}; + +/** + * Key setup. 8 word iv (nonce) + */ +int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz) +{ + const word32* constants; + const byte* k; + +#ifdef XSTREAM_ALIGN + word32 alignKey[8]; +#endif + + if (ctx == NULL) + return BAD_FUNC_ARG; + + if (keySz != (CHACHA_MAX_KEY_SZ/2) && keySz != CHACHA_MAX_KEY_SZ) + return BAD_FUNC_ARG; + +#ifdef XSTREAM_ALIGN + if ((wolfssl_word)key % 4) { + WOLFSSL_MSG("wc_ChachaSetKey unaligned key"); + XMEMCPY(alignKey, key, keySz); + k = (byte*)alignKey; + } + else { + k = key; + } +#else + k = key; +#endif /* XSTREAM_ALIGN */ + +#ifdef CHACHA_AEAD_TEST + word32 i; + printf("ChaCha key used :\n"); + for (i = 0; i < keySz; i++) { + printf("%02x", key[i]); + if ((i + 1) % 8 == 0) + printf("\n"); + } + printf("\n\n"); +#endif + + ctx->X[4] = U8TO32_LITTLE(k + 0); + ctx->X[5] = U8TO32_LITTLE(k + 4); + ctx->X[6] = U8TO32_LITTLE(k + 8); + ctx->X[7] = U8TO32_LITTLE(k + 12); + if (keySz == CHACHA_MAX_KEY_SZ) { + k += 16; + constants = sigma; + } + else { + constants = tau; + } + ctx->X[ 8] = U8TO32_LITTLE(k + 0); + ctx->X[ 9] = U8TO32_LITTLE(k + 4); + ctx->X[10] = U8TO32_LITTLE(k + 8); + ctx->X[11] = U8TO32_LITTLE(k + 12); + ctx->X[ 0] = constants[0]; + ctx->X[ 1] = constants[1]; + ctx->X[ 2] = constants[2]; + ctx->X[ 3] = constants[3]; + + return 0; +} + +static const word32 L_chacha20_neon_inc_first_word[] = { + 0x1, + 0x0, + 0x0, + 0x0, +}; + +#ifdef __aarch64__ + +static const word32 L_chacha20_neon_add_all_counters[] = { + 0x0, + 0x1, + 0x2, + 0x3, +}; + +static const word32 L_chacha20_neon_rol8[] = { + 0x2010003, + 0x6050407, + 0xa09080b, + 0xe0d0c0f, +}; + +static WC_INLINE void wc_Chacha_encrypt_320(const word32* input, const byte* m, byte* c, word32 bytes) +{ +#ifdef CHACHA_TEST + printf("Entering wc_Chacha_encrypt_320 with %d bytes\n", bytes); +#endif /*CHACHA_TEST */ + word64 bytes64 = (word64) bytes; + __asm__ __volatile__ ( + /* + * The layout of used registers is: + * ARM + * w4-w19: these registers hold the fifth Chacha block for calculation in regular ARM + * w20: loop counter for how many even-odd rounds need to be executed + * w21: the counter offset for the block in ARM registers + * NEON + * v0-v15: the vi'th register holds the i'th word of four blocks during the quarter rounds. + * these registers are later transposed make ADDing the input and XORing the message easier. + * v16-v19: these are helper registers that are used as temporary location to store data + * v20-v23: load the next message block + * v24-v27: the 64 byte initial Chacha block + * v28: vector to increment the counter words of each block + * v29: vector of 5's to increment counters between L_chacha20_arm64_outer_%= loops + * v30: table lookup indices to rotate values by 8 + */ + + /* Load counter-add values for each block */ + "LD1 {v28.4s}, [%[L_chacha20_neon_add_all_counters]] \n\t" + /* Load index look-up for rotating left 8 bits */ + "LD1 {v30.16b}, [%[L_chacha20_neon_rol8]] \n\t" + /* For adding 5 to each counter-add for next 320-byte chunk */ + "MOVI v29.4s, #5 \n\t" + /* Counter for 5th block in regular registers */ + "MOV w21, #4 \n\t" + /* Load state to encrypt */ + "LD1 {v24.4s-v27.4s}, [%[input]] \n\t" + "\n" + "L_chacha20_arm64_outer_%=: \n\t" + /* Move state into regular registers */ + "MOV x4, v24.d[0] \n\t" + "MOV x6, v24.d[1] \n\t" + "MOV x8, v25.d[0] \n\t" + "MOV x10, v25.d[1] \n\t" + "MOV x12, v26.d[0] \n\t" + "MOV x14, v26.d[1] \n\t" + "MOV x16, v27.d[0] \n\t" + "MOV x22, v27.d[1] \n\t" + /* Move state into vector registers (x4) */ + "DUP v0.4s, v24.s[0] \n\t" + "DUP v1.4s, v24.s[1] \n\t" + "LSR x5, x4, #32 \n\t" + "DUP v2.4s, v24.s[2] \n\t" + "DUP v3.4s, v24.s[3] \n\t" + "LSR x7, x6, #32 \n\t" + "DUP v4.4s, v25.s[0] \n\t" + "DUP v5.4s, v25.s[1] \n\t" + "LSR x9, x8, #32 \n\t" + "DUP v6.4s, v25.s[2] \n\t" + "DUP v7.4s, v25.s[3] \n\t" + "LSR x11, x10, #32 \n\t" + "DUP v8.4s, v26.s[0] \n\t" + "DUP v9.4s, v26.s[1] \n\t" + "LSR x13, x12, #32 \n\t" + "DUP v10.4s, v26.s[2] \n\t" + "DUP v11.4s, v26.s[3] \n\t" + "LSR x15, x14, #32 \n\t" + "DUP v12.4s, v27.s[0] \n\t" + "DUP v13.4s, v27.s[1] \n\t" + "LSR x17, x16, #32 \n\t" + "DUP v14.4s, v27.s[2] \n\t" + "DUP v15.4s, v27.s[3] \n\t" + "LSR x19, x22, #32 \n\t" + /* Add to counter word */ + "ADD v12.4s, v12.4s, v28.4s \n\t" + "ADD w16, w16, w21 \n\t" + /* Set number of odd+even rounds to perform */ + "MOV w20, #10 \n\t" + "\n" + "L_chacha20_arm64_inner_%=: \n\t" + "SUBS w20, w20, #1 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4s, v0.4s, v4.4s \n\t" + "ADD w4, w4, w8 \n\t" + "ADD v1.4s, v1.4s, v5.4s \n\t" + "ADD w5, w5, w9 \n\t" + "ADD v2.4s, v2.4s, v6.4s \n\t" + "ADD w6, w6, w10 \n\t" + "ADD v3.4s, v3.4s, v7.4s \n\t" + "ADD w7, w7, w11 \n\t" + "EOR v12.16b, v12.16b, v0.16b \n\t" + "EOR w16, w16, w4 \n\t" + "EOR v13.16b, v13.16b, v1.16b \n\t" + "EOR w17, w17, w5 \n\t" + "EOR v14.16b, v14.16b, v2.16b \n\t" + "EOR w22, w22, w6 \n\t" + "EOR v15.16b, v15.16b, v3.16b \n\t" + "EOR w19, w19, w7 \n\t" + "REV32 v12.8h, v12.8h \n\t" + "ROR w16, w16, #16 \n\t" + "REV32 v13.8h, v13.8h \n\t" + "ROR w17, w17, #16 \n\t" + "REV32 v14.8h, v14.8h \n\t" + "ROR w22, w22, #16 \n\t" + "REV32 v15.8h, v15.8h \n\t" + "ROR w19, w19, #16 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v8.4s, v8.4s, v12.4s \n\t" + "ADD w12, w12, w16 \n\t" + "ADD v9.4s, v9.4s, v13.4s \n\t" + "ADD w13, w13, w17 \n\t" + "ADD v10.4s, v10.4s, v14.4s \n\t" + "ADD w14, w14, w22 \n\t" + "ADD v11.4s, v11.4s, v15.4s \n\t" + "ADD w15, w15, w19 \n\t" + "EOR v16.16b, v4.16b, v8.16b \n\t" + "EOR w8, w8, w12 \n\t" + "EOR v17.16b, v5.16b, v9.16b \n\t" + "EOR w9, w9, w13 \n\t" + "EOR v18.16b, v6.16b, v10.16b \n\t" + "EOR w10, w10, w14 \n\t" + "EOR v19.16b, v7.16b, v11.16b \n\t" + "EOR w11, w11, w15 \n\t" + "SHL v4.4s, v16.4s, #12 \n\t" + "ROR w8, w8, #20 \n\t" + "SHL v5.4s, v17.4s, #12 \n\t" + "ROR w9, w9, #20 \n\t" + "SHL v6.4s, v18.4s, #12 \n\t" + "ROR w10, w10, #20 \n\t" + "SHL v7.4s, v19.4s, #12 \n\t" + "ROR w11, w11, #20 \n\t" + "SRI v4.4s, v16.4s, #20 \n\t" + "SRI v5.4s, v17.4s, #20 \n\t" + "SRI v6.4s, v18.4s, #20 \n\t" + "SRI v7.4s, v19.4s, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4s, v0.4s, v4.4s \n\t" + "ADD w4, w4, w8 \n\t" + "ADD v1.4s, v1.4s, v5.4s \n\t" + "ADD w5, w5, w9 \n\t" + "ADD v2.4s, v2.4s, v6.4s \n\t" + "ADD w6, w6, w10 \n\t" + "ADD v3.4s, v3.4s, v7.4s \n\t" + "ADD w7, w7, w11 \n\t" + "EOR v12.16b, v12.16b, v0.16b \n\t" + "EOR w16, w16, w4 \n\t" + "EOR v13.16b, v13.16b, v1.16b \n\t" + "EOR w17, w17, w5 \n\t" + "EOR v14.16b, v14.16b, v2.16b \n\t" + "EOR w22, w22, w6 \n\t" + "EOR v15.16b, v15.16b, v3.16b \n\t" + "EOR w19, w19, w7 \n\t" + "TBL v12.16b, { v12.16b }, v30.16b \n\t" + "ROR w16, w16, #24 \n\t" + "TBL v13.16b, { v13.16b }, v30.16b \n\t" + "ROR w17, w17, #24 \n\t" + "TBL v14.16b, { v14.16b }, v30.16b \n\t" + "ROR w22, w22, #24 \n\t" + "TBL v15.16b, { v15.16b }, v30.16b \n\t" + "ROR w19, w19, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v8.4s, v8.4s, v12.4s \n\t" + "ADD w12, w12, w16 \n\t" + "ADD v9.4s, v9.4s, v13.4s \n\t" + "ADD w13, w13, w17 \n\t" + "ADD v10.4s, v10.4s, v14.4s \n\t" + "ADD w14, w14, w22 \n\t" + "ADD v11.4s, v11.4s, v15.4s \n\t" + "ADD w15, w15, w19 \n\t" + "EOR v16.16b, v4.16b, v8.16b \n\t" + "EOR w8, w8, w12 \n\t" + "EOR v17.16b, v5.16b, v9.16b \n\t" + "EOR w9, w9, w13 \n\t" + "EOR v18.16b, v6.16b, v10.16b \n\t" + "EOR w10, w10, w14 \n\t" + "EOR v19.16b, v7.16b, v11.16b \n\t" + "EOR w11, w11, w15 \n\t" + "SHL v4.4s, v16.4s, #7 \n\t" + "ROR w8, w8, #25 \n\t" + "SHL v5.4s, v17.4s, #7 \n\t" + "ROR w9, w9, #25 \n\t" + "SHL v6.4s, v18.4s, #7 \n\t" + "ROR w10, w10, #25 \n\t" + "SHL v7.4s, v19.4s, #7 \n\t" + "ROR w11, w11, #25 \n\t" + "SRI v4.4s, v16.4s, #25 \n\t" + "SRI v5.4s, v17.4s, #25 \n\t" + "SRI v6.4s, v18.4s, #25 \n\t" + "SRI v7.4s, v19.4s, #25 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4s, v0.4s, v5.4s \n\t" + "ADD w4, w4, w9 \n\t" + "ADD v1.4s, v1.4s, v6.4s \n\t" + "ADD w5, w5, w10 \n\t" + "ADD v2.4s, v2.4s, v7.4s \n\t" + "ADD w6, w6, w11 \n\t" + "ADD v3.4s, v3.4s, v4.4s \n\t" + "ADD w7, w7, w8 \n\t" + "EOR v15.16b, v15.16b, v0.16b \n\t" + "EOR w19, w19, w4 \n\t" + "EOR v12.16b, v12.16b, v1.16b \n\t" + "EOR w16, w16, w5 \n\t" + "EOR v13.16b, v13.16b, v2.16b \n\t" + "EOR w17, w17, w6 \n\t" + "EOR v14.16b, v14.16b, v3.16b \n\t" + "EOR w22, w22, w7 \n\t" + "REV32 v15.8h, v15.8h \n\t" + "ROR w19, w19, #16 \n\t" + "REV32 v12.8h, v12.8h \n\t" + "ROR w16, w16, #16 \n\t" + "REV32 v13.8h, v13.8h \n\t" + "ROR w17, w17, #16 \n\t" + "REV32 v14.8h, v14.8h \n\t" + "ROR w22, w22, #16 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v10.4s, v10.4s, v15.4s \n\t" + "ADD w14, w14, w19 \n\t" + "ADD v11.4s, v11.4s, v12.4s \n\t" + "ADD w15, w15, w16 \n\t" + "ADD v8.4s, v8.4s, v13.4s \n\t" + "ADD w12, w12, w17 \n\t" + "ADD v9.4s, v9.4s, v14.4s \n\t" + "ADD w13, w13, w22 \n\t" + "EOR v16.16b, v5.16b, v10.16b \n\t" + "EOR w9, w9, w14 \n\t" + "EOR v17.16b, v6.16b, v11.16b \n\t" + "EOR w10, w10, w15 \n\t" + "EOR v18.16b, v7.16b, v8.16b \n\t" + "EOR w11, w11, w12 \n\t" + "EOR v19.16b, v4.16b, v9.16b \n\t" + "EOR w8, w8, w13 \n\t" + "SHL v5.4s, v16.4s, #12 \n\t" + "ROR w9, w9, #20 \n\t" + "SHL v6.4s, v17.4s, #12 \n\t" + "ROR w10, w10, #20 \n\t" + "SHL v7.4s, v18.4s, #12 \n\t" + "ROR w11, w11, #20 \n\t" + "SHL v4.4s, v19.4s, #12 \n\t" + "ROR w8, w8, #20 \n\t" + "SRI v5.4s, v16.4s, #20 \n\t" + "SRI v6.4s, v17.4s, #20 \n\t" + "SRI v7.4s, v18.4s, #20 \n\t" + "SRI v4.4s, v19.4s, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4s, v0.4s, v5.4s \n\t" + "ADD w4, w4, w9 \n\t" + "ADD v1.4s, v1.4s, v6.4s \n\t" + "ADD w5, w5, w10 \n\t" + "ADD v2.4s, v2.4s, v7.4s \n\t" + "ADD w6, w6, w11 \n\t" + "ADD v3.4s, v3.4s, v4.4s \n\t" + "ADD w7, w7, w8 \n\t" + "EOR v15.16b, v15.16b, v0.16b \n\t" + "EOR w19, w19, w4 \n\t" + "EOR v12.16b, v12.16b, v1.16b \n\t" + "EOR w16, w16, w5 \n\t" + "EOR v13.16b, v13.16b, v2.16b \n\t" + "EOR w17, w17, w6 \n\t" + "EOR v14.16b, v14.16b, v3.16b \n\t" + "EOR w22, w22, w7 \n\t" + "TBL v15.16b, { v15.16b }, v30.16b \n\t" + "ROR w19, w19, #24 \n\t" + "TBL v12.16b, { v12.16b }, v30.16b \n\t" + "ROR w16, w16, #24 \n\t" + "TBL v13.16b, { v13.16b }, v30.16b \n\t" + "ROR w17, w17, #24 \n\t" + "TBL v14.16b, { v14.16b }, v30.16b \n\t" + "ROR w22, w22, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v10.4s, v10.4s, v15.4s \n\t" + "ADD w14, w14, w19 \n\t" + "ADD v11.4s, v11.4s, v12.4s \n\t" + "ADD w15, w15, w16 \n\t" + "ADD v8.4s, v8.4s, v13.4s \n\t" + "ADD w12, w12, w17 \n\t" + "ADD v9.4s, v9.4s, v14.4s \n\t" + "ADD w13, w13, w22 \n\t" + "EOR v16.16b, v5.16b, v10.16b \n\t" + "EOR w9, w9, w14 \n\t" + "EOR v17.16b, v6.16b, v11.16b \n\t" + "EOR w10, w10, w15 \n\t" + "EOR v18.16b, v7.16b, v8.16b \n\t" + "EOR w11, w11, w12 \n\t" + "EOR v19.16b, v4.16b, v9.16b \n\t" + "EOR w8, w8, w13 \n\t" + "SHL v5.4s, v16.4s, #7 \n\t" + "ROR w9, w9, #25 \n\t" + "SHL v6.4s, v17.4s, #7 \n\t" + "ROR w10, w10, #25 \n\t" + "SHL v7.4s, v18.4s, #7 \n\t" + "ROR w11, w11, #25 \n\t" + "SHL v4.4s, v19.4s, #7 \n\t" + "ROR w8, w8, #25 \n\t" + "SRI v5.4s, v16.4s, #25 \n\t" + "SRI v6.4s, v17.4s, #25 \n\t" + "SRI v7.4s, v18.4s, #25 \n\t" + "SRI v4.4s, v19.4s, #25 \n\t" + "BNE L_chacha20_arm64_inner_%= \n\t" + /* Add counter now rather than after transposed */ + "ADD v12.4s, v12.4s, v28.4s \n\t" + "ADD w16, w16, w21 \n\t" + /* Load message */ + "LD1 {v20.4s-v23.4s}, [%[m]], #64 \n\t" + /* Transpose vectors */ + "TRN1 v16.4s, v0.4s, v1.4s \n\t" + "TRN1 v18.4s, v2.4s, v3.4s \n\t" + "TRN2 v17.4s, v0.4s, v1.4s \n\t" + "TRN2 v19.4s, v2.4s, v3.4s \n\t" + "TRN1 v0.2d, v16.2d, v18.2d \n\t" + "TRN1 v1.2d, v17.2d, v19.2d \n\t" + "TRN2 v2.2d, v16.2d, v18.2d \n\t" + "TRN2 v3.2d, v17.2d, v19.2d \n\t" + "TRN1 v16.4s, v4.4s, v5.4s \n\t" + "TRN1 v18.4s, v6.4s, v7.4s \n\t" + "TRN2 v17.4s, v4.4s, v5.4s \n\t" + "TRN2 v19.4s, v6.4s, v7.4s \n\t" + "TRN1 v4.2d, v16.2d, v18.2d \n\t" + "TRN1 v5.2d, v17.2d, v19.2d \n\t" + "TRN2 v6.2d, v16.2d, v18.2d \n\t" + "TRN2 v7.2d, v17.2d, v19.2d \n\t" + "TRN1 v16.4s, v8.4s, v9.4s \n\t" + "TRN1 v18.4s, v10.4s, v11.4s \n\t" + "TRN2 v17.4s, v8.4s, v9.4s \n\t" + "TRN2 v19.4s, v10.4s, v11.4s \n\t" + "TRN1 v8.2d, v16.2d, v18.2d \n\t" + "TRN1 v9.2d, v17.2d, v19.2d \n\t" + "TRN2 v10.2d, v16.2d, v18.2d \n\t" + "TRN2 v11.2d, v17.2d, v19.2d \n\t" + "TRN1 v16.4s, v12.4s, v13.4s \n\t" + "TRN1 v18.4s, v14.4s, v15.4s \n\t" + "TRN2 v17.4s, v12.4s, v13.4s \n\t" + "TRN2 v19.4s, v14.4s, v15.4s \n\t" + "TRN1 v12.2d, v16.2d, v18.2d \n\t" + "TRN1 v13.2d, v17.2d, v19.2d \n\t" + "TRN2 v14.2d, v16.2d, v18.2d \n\t" + "TRN2 v15.2d, v17.2d, v19.2d \n\t" + /* Add back state, XOR in message and store (load next block) */ + "ADD v16.4s, v0.4s, v24.4s \n\t" + "ADD v17.4s, v4.4s, v25.4s \n\t" + "ADD v18.4s, v8.4s, v26.4s \n\t" + "ADD v19.4s, v12.4s, v27.4s \n\t" + "EOR v16.16b, v16.16b, v20.16b \n\t" + "EOR v17.16b, v17.16b, v21.16b \n\t" + "EOR v18.16b, v18.16b, v22.16b \n\t" + "EOR v19.16b, v19.16b, v23.16b \n\t" + "LD1 {v20.4s-v23.4s}, [%[m]], #64 \n\t" + "ST1 {v16.4s-v19.4s}, [%[c]], #64 \n\t" + "ADD v16.4s, v1.4s, v24.4s \n\t" + "ADD v17.4s, v5.4s, v25.4s \n\t" + "ADD v18.4s, v9.4s, v26.4s \n\t" + "ADD v19.4s, v13.4s, v27.4s \n\t" + "EOR v16.16b, v16.16b, v20.16b \n\t" + "EOR v17.16b, v17.16b, v21.16b \n\t" + "EOR v18.16b, v18.16b, v22.16b \n\t" + "EOR v19.16b, v19.16b, v23.16b \n\t" + "LD1 {v20.4s-v23.4s}, [%[m]], #64 \n\t" + "ST1 {v16.4s-v19.4s}, [%[c]], #64 \n\t" + "ADD v16.4s, v2.4s, v24.4s \n\t" + "ADD v17.4s, v6.4s, v25.4s \n\t" + "ADD v18.4s, v10.4s, v26.4s \n\t" + "ADD v19.4s, v14.4s, v27.4s \n\t" + "EOR v16.16b, v16.16b, v20.16b \n\t" + "EOR v17.16b, v17.16b, v21.16b \n\t" + "EOR v18.16b, v18.16b, v22.16b \n\t" + "EOR v19.16b, v19.16b, v23.16b \n\t" + "LD1 {v20.4s-v23.4s}, [%[m]], #64 \n\t" + "ST1 {v16.4s-v19.4s}, [%[c]], #64 \n\t" + "ADD v16.4s, v3.4s, v24.4s \n\t" + "ADD v17.4s, v7.4s, v25.4s \n\t" + "ADD v18.4s, v11.4s, v26.4s \n\t" + "ADD v19.4s, v15.4s, v27.4s \n\t" + "EOR v16.16b, v16.16b, v20.16b \n\t" + "EOR v17.16b, v17.16b, v21.16b \n\t" + "EOR v18.16b, v18.16b, v22.16b \n\t" + "EOR v19.16b, v19.16b, v23.16b \n\t" + "LD1 {v20.4s-v23.4s}, [%[m]], #64 \n\t" + "ST1 {v16.4s-v19.4s}, [%[c]], #64 \n\t" + /* Move regular registers into vector registers for adding and xor */ + "ORR x4, x4, x5, LSL #32 \n\t" + "ORR x6, x6, x7, LSL #32 \n\t" + "ORR x8, x8, x9, LSL #32 \n\t" + "MOV v16.d[0], x4 \n\t" + "ORR x10, x10, x11, LSL #32 \n\t" + "MOV v16.d[1], x6 \n\t" + "ORR x12, x12, x13, LSL #32 \n\t" + "MOV v17.d[0], x8 \n\t" + "ORR x14, x14, x15, LSL #32 \n\t" + "MOV v17.d[1], x10 \n\t" + "ORR x16, x16, x17, LSL #32 \n\t" + "MOV v18.d[0], x12 \n\t" + "ORR x22, x22, x19, LSL #32 \n\t" + "MOV v18.d[1], x14 \n\t" + "MOV v19.d[0], x16 \n\t" + "MOV v19.d[1], x22 \n\t" + /* Add back state, XOR in message and store */ + "ADD v16.4s, v16.4s, v24.4s \n\t" + "ADD v17.4s, v17.4s, v25.4s \n\t" + "ADD v18.4s, v18.4s, v26.4s \n\t" + "ADD v19.4s, v19.4s, v27.4s \n\t" + "EOR v16.16b, v16.16b, v20.16b \n\t" + "EOR v17.16b, v17.16b, v21.16b \n\t" + "EOR v18.16b, v18.16b, v22.16b \n\t" + "EOR v19.16b, v19.16b, v23.16b \n\t" + "ADD w21, w21, #5 \n\t" + "ST1 {v16.4s-v19.4s}, [%[c]], #64 \n\t" + "SUBS %[bytes], %[bytes], #320 \n\t" + "ADD v28.4s, v28.4s, v29.4s \n\t" + "BNE L_chacha20_arm64_outer_%= \n\t" + : [input] "+r" (input), [m] "+r" (m), [c] "+r" (c), + [bytes] "+r" (bytes64) + : [L_chacha20_neon_add_all_counters] "r" (L_chacha20_neon_add_all_counters), + [L_chacha20_neon_rol8] "r" (L_chacha20_neon_rol8) + : "memory", "cc", + "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", + "x13", "x14", "x15", "x16", "x17", "x22", "x19", "x20", "x21", + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", + "v19", "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27" + ); +} +#endif /* __aarch64__ */ + +/** + * Converts word into bytes with rotations having been done. + */ +static WC_INLINE int wc_Chacha_encrypt_256(const word32 input[CHACHA_CHUNK_WORDS], const byte* m, byte* c) +{ +#ifdef CHACHA_TEST + printf("Entering wc_Chacha_encrypt_256\n"); +#endif /*CHACHA_TEST */ + +#ifdef __aarch64__ + __asm__ __volatile__ ( + // v0-v3 - first block + // v12 first block helper + // v4-v7 - second block + // v13 second block helper + // v8-v11 - third block + // v14 third block helper + // w4-w19 - fourth block + + // v0 0 1 2 3 + // v1 4 5 6 7 + // v2 8 9 10 11 + // v3 12 13 14 15 + // load CHACHA state with indices placed as shown above + /* Load state to encrypt */ + "LD1 {v20.4S-v23.4S}, [%[input]] \n\t" + /* Load index look-up for rotating left 8 bits */ + "LD1 {v24.16B}, [%[L_chacha20_neon_rol8]] \n\t" + /* Move state into regular registers */ + "MOV x4, v20.D[0] \n\t" + "MOV x6, v20.D[1] \n\t" + "MOV x8, v21.D[0] \n\t" + "MOV x10, v21.D[1] \n\t" + "MOV x12, v22.D[0] \n\t" + "MOV x14, v22.D[1] \n\t" + "MOV x16, v23.D[0] \n\t" + "MOV x22, v23.D[1] \n\t" + /* Move state into vector registers (x3) */ + "MOV v0.16B, v20.16B \n\t" + "MOV v1.16B, v21.16B \n\t" + "LSR x19, x22, #32 \n\t" + "MOV v2.16B, v22.16B \n\t" + "ADD w20, w16, #1 \n\t" + "MOV v3.16B, v23.16B \n\t" + "LSR x17, x16, #32 \n\t" + "MOV v4.16B, v20.16B \n\t" + "MOV v5.16B, v21.16B \n\t" + "LSR x15, x14, #32 \n\t" + "MOV v6.16B, v22.16B \n\t" + "ADD w21, w16, #2 \n\t" + "MOV v7.16B, v23.16B \n\t" + "LSR x13, x12, #32 \n\t" + "MOV v8.16B, v20.16B \n\t" + "MOV v9.16B, v21.16B \n\t" + "LSR x11, x10, #32 \n\t" + "MOV v10.16B, v22.16B \n\t" + "ADD w16, w16, #3 \n\t" + "MOV v11.16B, v23.16B \n\t" + "LSR x9, x8, #32 \n\t" + /* Set counter word */ + "MOV v7.S[0], w20 \n\t" + "LSR x7, x6, #32 \n\t" + "MOV v11.S[0], w21 \n\t" + "LSR x5, x4, #32 \n\t" + /* Set number of odd+even rounds to perform */ + "MOV w3, #10 \n\t" + "\n" + "L_chacha20_arm64_256_loop_%=: \n\t" + "SUBS w3, w3, #1 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD w4, w4, w8 \n\t" + "ADD v0.4S, v0.4S, v1.4S \n\t" + "ADD w5, w5, w9 \n\t" + "ADD v4.4S, v4.4S, v5.4S \n\t" + "ADD w6, w6, w10 \n\t" + "ADD v8.4S, v8.4S, v9.4S \n\t" + "ADD w7, w7, w11 \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "EOR w16, w16, w4 \n\t" + "EOR v7.16B, v7.16B, v4.16B \n\t" + "EOR w17, w17, w5 \n\t" + "EOR v11.16B, v11.16B, v8.16B \n\t" + "EOR w22, w22, w6 \n\t" + "REV32 v3.8H, v3.8H \n\t" + "EOR w19, w19, w7 \n\t" + "REV32 v7.8H, v7.8H \n\t" + "ROR w16, w16, #16 \n\t" + "REV32 v11.8H, v11.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ROR w17, w17, #16 \n\t" + "ADD v2.4S, v2.4S, v3.4S \n\t" + "ROR w22, w22, #16 \n\t" + "ADD v6.4S, v6.4S, v7.4S \n\t" + "ROR w19, w19, #16 \n\t" + "ADD v10.4S, v10.4S, v11.4S \n\t" + "ADD w12, w12, w16 \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "ADD w13, w13, w17 \n\t" + "EOR v13.16B, v5.16B, v6.16B \n\t" + "ADD w14, w14, w22 \n\t" + "EOR v14.16B, v9.16B, v10.16B \n\t" + "ADD w15, w15, w19 \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "EOR w8, w8, w12 \n\t" + "SHL v5.4S, v13.4S, #12 \n\t" + "EOR w9, w9, w13 \n\t" + "SHL v9.4S, v14.4S, #12 \n\t" + "EOR w10, w10, w14 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + "EOR w11, w11, w15 \n\t" + "SRI v5.4S, v13.4S, #20 \n\t" + "ROR w8, w8, #20 \n\t" + "SRI v9.4S, v14.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ROR w9, w9, #20 \n\t" + "ADD v0.4S, v0.4S, v1.4S \n\t" + "ROR w10, w10, #20 \n\t" + "ADD v4.4S, v4.4S, v5.4S \n\t" + "ROR w11, w11, #20 \n\t" + "ADD v8.4S, v8.4S, v9.4S \n\t" + "ADD w4, w4, w8 \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "ADD w5, w5, w9 \n\t" + "EOR v7.16B, v7.16B, v4.16B \n\t" + "ADD w6, w6, w10 \n\t" + "EOR v11.16B, v11.16B, v8.16B \n\t" + "ADD w7, w7, w11 \n\t" + "TBL v3.16B, { v3.16B }, v24.16B \n\t" + "EOR w16, w16, w4 \n\t" + "TBL v7.16B, { v7.16B }, v24.16B \n\t" + "EOR w17, w17, w5 \n\t" + "TBL v11.16B, { v11.16B }, v24.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "EOR w22, w22, w6 \n\t" + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR w19, w19, w7 \n\t" + "ADD v6.4S, v6.4S, v7.4S \n\t" + "ROR w16, w16, #24 \n\t" + "ADD v10.4S, v10.4S, v11.4S \n\t" + "ROR w17, w17, #24 \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "ROR w22, w22, #24 \n\t" + "EOR v13.16B, v5.16B, v6.16B \n\t" + "ROR w19, w19, #24 \n\t" + "EOR v14.16B, v9.16B, v10.16B \n\t" + "ADD w12, w12, w16 \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "ADD w13, w13, w17 \n\t" + "SHL v5.4S, v13.4S, #7 \n\t" + "ADD w14, w14, w22 \n\t" + "SHL v9.4S, v14.4S, #7 \n\t" + "ADD w15, w15, w19 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EOR w8, w8, w12 \n\t" + "SRI v5.4S, v13.4S, #25 \n\t" + "EOR w9, w9, w13 \n\t" + "SRI v9.4S, v14.4S, #25 \n\t" + "EOR w10, w10, w14 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #4 \n\t" + "EOR w11, w11, w15 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + "ROR w8, w8, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #12 \n\t" + "ROR w9, w9, #25 \n\t" + "EXT v5.16B, v5.16B, v5.16B, #4 \n\t" + "ROR w10, w10, #25 \n\t" + "EXT v6.16B, v6.16B, v6.16B, #8 \n\t" + "ROR w11, w11, #25 \n\t" + "EXT v7.16B, v7.16B, v7.16B, #12 \n\t" + "EXT v9.16B, v9.16B, v9.16B, #4 \n\t" + "EXT v10.16B, v10.16B, v10.16B, #8 \n\t" + "EXT v11.16B, v11.16B, v11.16B, #12 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD w4, w4, w9 \n\t" + "ADD v0.4S, v0.4S, v1.4S \n\t" + "ADD w5, w5, w10 \n\t" + "ADD v4.4S, v4.4S, v5.4S \n\t" + "ADD w6, w6, w11 \n\t" + "ADD v8.4S, v8.4S, v9.4S \n\t" + "ADD w7, w7, w8 \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "EOR w19, w19, w4 \n\t" + "EOR v7.16B, v7.16B, v4.16B \n\t" + "EOR w16, w16, w5 \n\t" + "EOR v11.16B, v11.16B, v8.16B \n\t" + "EOR w17, w17, w6 \n\t" + "REV32 v3.8H, v3.8H \n\t" + "EOR w22, w22, w7 \n\t" + "REV32 v7.8H, v7.8H \n\t" + "ROR w19, w19, #16 \n\t" + "REV32 v11.8H, v11.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ROR w16, w16, #16 \n\t" + "ADD v2.4S, v2.4S, v3.4S \n\t" + "ROR w17, w17, #16 \n\t" + "ADD v6.4S, v6.4S, v7.4S \n\t" + "ROR w22, w22, #16 \n\t" + "ADD v10.4S, v10.4S, v11.4S \n\t" + "ADD w14, w14, w19 \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "ADD w15, w15, w16 \n\t" + "EOR v13.16B, v5.16B, v6.16B \n\t" + "ADD w12, w12, w17 \n\t" + "EOR v14.16B, v9.16B, v10.16B \n\t" + "ADD w13, w13, w22 \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "EOR w9, w9, w14 \n\t" + "SHL v5.4S, v13.4S, #12 \n\t" + "EOR w10, w10, w15 \n\t" + "SHL v9.4S, v14.4S, #12 \n\t" + "EOR w11, w11, w12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + "EOR w8, w8, w13 \n\t" + "SRI v5.4S, v13.4S, #20 \n\t" + "ROR w9, w9, #20 \n\t" + "SRI v9.4S, v14.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ROR w10, w10, #20 \n\t" + "ADD v0.4S, v0.4S, v1.4S \n\t" + "ROR w11, w11, #20 \n\t" + "ADD v4.4S, v4.4S, v5.4S \n\t" + "ROR w8, w8, #20 \n\t" + "ADD v8.4S, v8.4S, v9.4S \n\t" + "ADD w4, w4, w9 \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "ADD w5, w5, w10 \n\t" + "EOR v7.16B, v7.16B, v4.16B \n\t" + "ADD w6, w6, w11 \n\t" + "EOR v11.16B, v11.16B, v8.16B \n\t" + "ADD w7, w7, w8 \n\t" + "TBL v3.16B, { v3.16B }, v24.16B \n\t" + "EOR w19, w19, w4 \n\t" + "TBL v7.16B, { v7.16B }, v24.16B \n\t" + "EOR w16, w16, w5 \n\t" + "TBL v11.16B, { v11.16B }, v24.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "EOR w17, w17, w6 \n\t" + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR w22, w22, w7 \n\t" + "ADD v6.4S, v6.4S, v7.4S \n\t" + "ROR w19, w19, #24 \n\t" + "ADD v10.4S, v10.4S, v11.4S \n\t" + "ROR w16, w16, #24 \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "ROR w17, w17, #24 \n\t" + "EOR v13.16B, v5.16B, v6.16B \n\t" + "ROR w22, w22, #24 \n\t" + "EOR v14.16B, v9.16B, v10.16B \n\t" + "ADD w14, w14, w19 \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "ADD w15, w15, w16 \n\t" + "SHL v5.4S, v13.4S, #7 \n\t" + "ADD w12, w12, w17 \n\t" + "SHL v9.4S, v14.4S, #7 \n\t" + "ADD w13, w13, w22 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EOR w9, w9, w14 \n\t" + "SRI v5.4S, v13.4S, #25 \n\t" + "EOR w10, w10, w15 \n\t" + "SRI v9.4S, v14.4S, #25 \n\t" + "EOR w11, w11, w12 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #12 \n\t" + "EOR w8, w8, w13 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + "ROR w9, w9, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #4 \n\t" + "ROR w10, w10, #25 \n\t" + "EXT v5.16B, v5.16B, v5.16B, #12 \n\t" + "ROR w11, w11, #25 \n\t" + "EXT v6.16B, v6.16B, v6.16B, #8 \n\t" + "ROR w8, w8, #25 \n\t" + "EXT v7.16B, v7.16B, v7.16B, #4 \n\t" + "EXT v9.16B, v9.16B, v9.16B, #12 \n\t" + "EXT v10.16B, v10.16B, v10.16B, #8 \n\t" + "EXT v11.16B, v11.16B, v11.16B, #4 \n\t" + "BNE L_chacha20_arm64_256_loop_%= \n\t" + /* Load message */ + "LD1 {v16.4S-v19.4S}, [%[m]], #64 \n\t" + /* Add one (2 added during calculating vector results) */ + "ADD w16, w16, #1 \n\t" + /* Add back state, XOR in message and store (load next block) */ + "ADD v0.4S, v0.4S, v20.4S \n\t" + "ADD v1.4S, v1.4S, v21.4S \n\t" + "ADD v2.4S, v2.4S, v22.4S \n\t" + "ADD v3.4S, v3.4S, v23.4S \n\t" + "EOR v0.16B, v0.16B, v16.16B \n\t" + "EOR v1.16B, v1.16B, v17.16B \n\t" + "EOR v2.16B, v2.16B, v18.16B \n\t" + "EOR v3.16B, v3.16B, v19.16B \n\t" + "LD1 {v16.4S-v19.4S}, [%[m]], #64 \n\t" + "ST1 {v0.4S-v3.4S}, [%[c]], #64 \n\t" + "MOV v23.S[0], w20 \n\t" + "ADD v4.4S, v4.4S, v20.4S \n\t" + "ADD v5.4S, v5.4S, v21.4S \n\t" + "ADD v6.4S, v6.4S, v22.4S \n\t" + "ADD v7.4S, v7.4S, v23.4S \n\t" + "EOR v4.16B, v4.16B, v16.16B \n\t" + "EOR v5.16B, v5.16B, v17.16B \n\t" + "EOR v6.16B, v6.16B, v18.16B \n\t" + "EOR v7.16B, v7.16B, v19.16B \n\t" + "LD1 {v16.4S-v19.4S}, [%[m]], #64 \n\t" + "ST1 {v4.4S-v7.4S}, [%[c]], #64 \n\t" + "MOV v23.S[0], w21 \n\t" + "ADD v8.4S, v8.4S, v20.4S \n\t" + "ADD v9.4S, v9.4S, v21.4S \n\t" + "ADD v10.4S, v10.4S, v22.4S \n\t" + "ADD v11.4S, v11.4S, v23.4S \n\t" + "EOR v8.16B, v8.16B, v16.16B \n\t" + "EOR v9.16B, v9.16B, v17.16B \n\t" + "EOR v10.16B, v10.16B, v18.16B \n\t" + "EOR v11.16B, v11.16B, v19.16B \n\t" + "LD1 {v16.4S-v19.4S}, [%[m]], #64 \n\t" + "ST1 {v8.4S-v11.4S}, [%[c]], #64 \n\t" + /* Move regular registers into vector registers for adding and xor */ + "ORR x4, x4, x5, lsl #32 \n\t" + "ORR x6, x6, x7, lsl #32 \n\t" + "ORR x8, x8, x9, lsl #32 \n\t" + "MOV v12.D[0], x4 \n\t" + "ORR x10, x10, x11, lsl #32 \n\t" + "MOV v12.D[1], x6 \n\t" + "ORR x12, x12, x13, lsl #32 \n\t" + "MOV v13.D[0], x8 \n\t" + "ORR x14, x14, x15, lsl #32 \n\t" + "MOV v13.D[1], x10 \n\t" + "ORR x16, x16, x17, lsl #32 \n\t" + "MOV v14.D[0], x12 \n\t" + "ORR x22, x22, x19, lsl #32 \n\t" + "MOV v14.D[1], x14 \n\t" + "MOV v15.D[0], x16 \n\t" + "MOV v15.D[1], x22 \n\t" + /* Add back state, XOR in message and store */ + "ADD v12.4S, v12.4S, v20.4S \n\t" + "ADD v13.4S, v13.4S, v21.4S \n\t" + "ADD v14.4S, v14.4S, v22.4S \n\t" + "ADD v15.4S, v15.4S, v23.4S \n\t" + "EOR v12.16B, v12.16B, v16.16B \n\t" + "EOR v13.16B, v13.16B, v17.16B \n\t" + "EOR v14.16B, v14.16B, v18.16B \n\t" + "EOR v15.16B, v15.16B, v19.16B \n\t" + "ST1 {v12.4S-v15.4S}, [%[c]], #64 \n\t" + : [input] "+r" (input), [m] "+r" (m), [c] "+r" (c) + : [L_chacha20_neon_rol8] "r" (L_chacha20_neon_rol8) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", + "x10", "x11", "x12", "x13", "x14", "x15", "x16", + "x17", "x22", "x19", "x20", "x21", "v0", "v1", + "v2", "v3", "v4", "v5", "v6", "v7", "v8", + "v9", "v10", "v11", "v12", "v13", "v14", + "v15", "v16", "v17", "v18", "v19", "v20", + "v21", "v22", "v23" + ); +#else + word32 x[CHACHA_CHUNK_WORDS]; + word32* x_addr = x; + __asm__ __volatile__ ( + // The paper NEON crypto by Daniel J. Bernstein and Peter Schwabe was used to optimize for ARM + // https://cryptojedi.org/papers/neoncrypto-20120320.pdf + + ".align 2 \n\t" + "LDR r14, %[input] \n\t" // load input address + + "LDM r14, { r0-r12 } \n\t" + // r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + "VMOV d0, r0, r1 \n\t" + "VMOV d1, r2, r3 \n\t" + "VMOV d2, r4, r5 \n\t" + "VMOV d3, r6, r7 \n\t" + "VMOV d4, r8, r9 \n\t" + "STRD r10, r11, %[x_10] \n\t" + "VMOV d5, r10, r11 \n\t" + "LDRD r11, r10, [r14, #4*14] \n\t" + "VMOV q4, q0 \n\t" + "VMOV q5, q1 \n\t" + "VMOV q6, q2 \n\t" + "VMOV q8, q0 \n\t" + "VMOV q9, q1 \n\t" + "VMOV q10, q2 \n\t" + // r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 + // 0 1 2 3 4 5 6 7 8 9 15 14 12 + "VMOV d7, r11, r10 \n\t" + "STR r10, %[x_15] \n\t" + "VMOV d15, r11, r10 \n\t" + "VMOV d23, r11, r10 \n\t" + "MOV r10, r12 \n\t" + "MOV r12, r11 \n\t" + "LDR r11, [r14, #4*13] \n\t" + // r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 + // 0 1 2 3 4 5 6 7 8 9 12 13 14 + + "MOV r14, %[rounds] \n\t" + + "VMOV d6, r10, r11 \n\t" + "ADD r10, r10, #1 \n\t" + "VMOV d14, r10, r11 \n\t" + "ADD r10, r10, #1 \n\t" + "VMOV d22, r10, r11 \n\t" + "ADD r10, r10, #1 \n\t" // ARM calculates the fourth block (two was already added earlier) + "\n" + "L_chacha20_arm32_256_loop_%=: \n\t" + "SUBS r14, r14, #1 \n\t" + + // 0, 4, 8, 12 + // 1, 5, 9, 13 + + // ODD ROUND + "ADD r0, r0, r4 \n\t" // 0 0 4 + "VADD.I32 q0, q0, q1 \n\t" + "ADD r1, r1, r5 \n\t" // 1 1 5 + "VADD.I32 q4, q4, q5 \n\t" + "EOR r10, r10, r0 \n\t" // 12 12 0 + "VADD.I32 q8, q8, q9 \n\t" + "EOR r11, r11, r1 \n\t" // 13 13 1 + "VEOR q12, q3, q0 \n\t" + "ROR r10, r10, #16 \n\t" // 12 12 + "VEOR q13, q7, q4 \n\t" + "ROR r11, r11, #16 \n\t" // 13 13 + "VEOR q14, q11, q8 \n\t" + "ADD r8, r8, r10 \n\t" // 8 8 12 + // rotation by 16 bits may be done by reversing the 16 bit elements in 32 bit words + "VREV32.16 q3, q12 \n\t" + "ADD r9, r9, r11 \n\t" // 9 9 13 + "VREV32.16 q7, q13 \n\t" + "EOR r4, r4, r8 \n\t" // 4 4 8 + "VREV32.16 q11, q14 \n\t" + + "EOR r5, r5, r9 \n\t" // 5 5 9 + "VADD.I32 q2, q2, q3 \n\t" + "ROR r4, r4, #20 \n\t" // 4 4 + "VADD.I32 q6, q6, q7 \n\t" + "ROR r5, r5, #20 \n\t" // 5 5 + "VADD.I32 q10, q10, q11 \n\t" + "ADD r0, r0, r4 \n\t" // 0 0 4 + "VEOR q12, q1, q2 \n\t" + "ADD r1, r1, r5 \n\t" // 1 1 5 + "VEOR q13, q5, q6 \n\t" + "EOR r10, r10, r0 \n\t" // 12 12 0 + "VEOR q14, q9, q10 \n\t" + "EOR r11, r11, r1 \n\t" // 13 13 1 + // SIMD instructions don't support rotation so we have to cheat using shifts and a help register + "VSHL.I32 q1, q12, #12 \n\t" + "ROR r10, r10, #24 \n\t" // 12 12 + "VSHL.I32 q5, q13, #12 \n\t" + "ROR r11, r11, #24 \n\t" // 13 13 + "VSHL.I32 q9, q14, #12 \n\t" + "ADD r8, r8, r10 \n\t" // 8 8 12 + "VSRI.I32 q1, q12, #20 \n\t" + "ADD r9, r9, r11 \n\t" // 9 9 13 + "VSRI.I32 q5, q13, #20 \n\t" + "STR r11, %[x_13] \n\t" + "VSRI.I32 q9, q14, #20 \n\t" + + "LDR r11, %[x_15] \n\t" + "VADD.I32 q0, q0, q1 \n\t" + "EOR r4, r4, r8 \n\t" // 4 4 8 + "VADD.I32 q4, q4, q5 \n\t" + "STR r8, %[x_8] \n\t" + "VADD.I32 q8, q8, q9 \n\t" + "LDR r8, %[x_10] \n\t" + "VEOR q12, q3, q0 \n\t" + "EOR r5, r5, r9 \n\t" // 5 5 9 + "VEOR q13, q7, q4 \n\t" + "STR r9, %[x_9] \n\t" + "VEOR q14, q11, q8 \n\t" + "LDR r9, %[x_11] \n\t" + // SIMD instructions don't support rotation so we have to cheat using shifts and a help register + "VSHL.I32 q3, q12, #8 \n\t" + "ROR r4, r4, #25 \n\t" // 4 4 + "VSHL.I32 q7, q13, #8 \n\t" + "ROR r5, r5, #25 \n\t" // 5 5 + "VSHL.I32 q11, q14, #8 \n\t" + + // r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 + // 0 1 2 3 4 5 6 7 10 11 12 15 14 + + // 2, 6, 10, 14 + // 3, 7, 11, 15 + + "ADD r2, r2, r6 \n\t" // 2 2 6 + "VSRI.I32 q3, q12, #24 \n\t" + "ADD r3, r3, r7 \n\t" // 3 3 7 + "VSRI.I32 q7, q13, #24 \n\t" + "EOR r12, r12, r2 \n\t" // 14 14 2 + "VSRI.I32 q11, q14, #24 \n\t" + + "EOR r11, r11, r3 \n\t" // 15 15 3 + "VADD.I32 q2, q2, q3 \n\t" + "ROR r12, r12, #16 \n\t" // 14 14 + "VADD.I32 q6, q6, q7 \n\t" + "ROR r11, r11, #16 \n\t" // 15 15 + "VADD.I32 q10, q10, q11 \n\t" + "ADD r8, r8, r12 \n\t" // 10 10 14 + "VEOR q12, q1, q2 \n\t" + "ADD r9, r9, r11 \n\t" // 11 11 15 + "VEOR q13, q5, q6 \n\t" + "EOR r6, r6, r8 \n\t" // 6 6 10 + "VEOR q14, q9, q10 \n\t" + "EOR r7, r7, r9 \n\t" // 7 7 11 + // SIMD instructions don't support rotation so we have to cheat using shifts and a help register + "VSHL.I32 q1, q12, #7 \n\t" + "ROR r6, r6, #20 \n\t" // 6 6 + "VSHL.I32 q5, q13, #7 \n\t" + "ROR r7, r7, #20 \n\t" // 7 7 + "VSHL.I32 q9, q14, #7 \n\t" + "ADD r2, r2, r6 \n\t" // 2 2 6 + "VSRI.I32 q1, q12, #25 \n\t" + "ADD r3, r3, r7 \n\t" // 3 3 7 + "VSRI.I32 q5, q13, #25 \n\t" + "EOR r12, r12, r2 \n\t" // 14 14 2 + "VSRI.I32 q9, q14, #25 \n\t" + + // EVEN ROUND + + "EOR r11, r11, r3 \n\t" // 15 15 3 + "VEXT.8 q1, q1, q1, #4 \n\t" // permute elements left by one + "ROR r12, r12, #24 \n\t" // 14 14 + "VEXT.8 q2, q2, q2, #8 \n\t" // permute elements left by two + "ROR r11, r11, #24 \n\t" // 15 15 + "VEXT.8 q3, q3, q3, #12 \n\t" // permute elements left by three + + "ADD r8, r8, r12 \n\t" // 10 10 14 + "VEXT.8 q5, q5, q5, #4 \n\t" // permute elements left by one + "ADD r9, r9, r11 \n\t" // 11 11 15 + "VEXT.8 q6, q6, q6, #8 \n\t" // permute elements left by two + "EOR r6, r6, r8 \n\t" // 6 6 10 + "VEXT.8 q7, q7, q7, #12 \n\t" // permute elements left by three + + "EOR r7, r7, r9 \n\t" // 7 7 11 + "VEXT.8 q9, q9, q9, #4 \n\t" // permute elements left by one + "ROR r6, r6, #25 \n\t" // 6 6 + "VEXT.8 q10, q10, q10, #8 \n\t" // permute elements left by two + "ROR r7, r7, #25 \n\t" // 7 7 + "VEXT.8 q11, q11, q11, #12 \n\t" // permute elements left by three + + // 0, 5, 10, 15 + // 1, 6, 11, 12 + + "ADD r0, r0, r5 \n\t" // 0 0 5 + "VADD.I32 q0, q0, q1 \n\t" + "ADD r1, r1, r6 \n\t" // 1 1 6 + "VADD.I32 q4, q4, q5 \n\t" + "EOR r11, r11, r0 \n\t" // 15 15 0 + "VADD.I32 q8, q8, q9 \n\t" + "EOR r10, r10, r1 \n\t" // 12 12 1 + "VEOR q12, q3, q0 \n\t" + "ROR r11, r11, #16 \n\t" // 15 15 + "VEOR q13, q7, q4 \n\t" + "ROR r10, r10, #16 \n\t" // 12 12 + "VEOR q14, q11, q8 \n\t" + "ADD r8, r8, r11 \n\t" // 10 10 15 + // rotation by 16 bits may be done by reversing the 16 bit elements in 32 bit words + "VREV32.16 q3, q12 \n\t" + "ADD r9, r9, r10 \n\t" // 11 11 12 + "VREV32.16 q7, q13 \n\t" + "EOR r5, r5, r8 \n\t" // 5 5 10 + "VREV32.16 q11, q14 \n\t" + + "EOR r6, r6, r9 \n\t" // 6 6 11 + "VADD.I32 q2, q2, q3 \n\t" + "ROR r5, r5, #20 \n\t" // 5 5 + "VADD.I32 q6, q6, q7 \n\t" + "ROR r6, r6, #20 \n\t" // 6 6 + "VADD.I32 q10, q10, q11 \n\t" + "ADD r0, r0, r5 \n\t" // 0 0 5 + "VEOR q12, q1, q2 \n\t" + "ADD r1, r1, r6 \n\t" // 1 1 6 + "VEOR q13, q5, q6 \n\t" + "EOR r11, r11, r0 \n\t" // 15 15 0 + "VEOR q14, q9, q10 \n\t" + "EOR r10, r10, r1 \n\t" // 12 12 1 + // SIMD instructions don't support rotation so we have to cheat using shifts and a help register + "VSHL.I32 q1, q12, #12 \n\t" + "ROR r11, r11, #24 \n\t" // 15 15 + "VSHL.I32 q5, q13, #12 \n\t" + "ROR r10, r10, #24 \n\t" // 12 12 + "VSHL.I32 q9, q14, #12 \n\t" + "ADD r8, r8, r11 \n\t" // 10 10 15 + "VSRI.I32 q1, q12, #20 \n\t" + "STR r11, %[x_15] \n\t" + "VSRI.I32 q5, q13, #20 \n\t" + "LDR r11, %[x_13] \n\t" + "VSRI.I32 q9, q14, #20 \n\t" + + "ADD r9, r9, r10 \n\t" // 11 11 12 + "VADD.I32 q0, q0, q1 \n\t" + "EOR r5, r5, r8 \n\t" // 5 5 10 + "VADD.I32 q4, q4, q5 \n\t" + "STR r8, %[x_10] \n\t" + "VADD.I32 q8, q8, q9 \n\t" + "LDR r8, %[x_8] \n\t" + "VEOR q12, q3, q0 \n\t" + "EOR r6, r6, r9 \n\t" // 6 6 11 + "VEOR q13, q7, q4 \n\t" + "STR r9, %[x_11] \n\t" + "VEOR q14, q11, q8 \n\t" + "LDR r9, %[x_9] \n\t" + // SIMD instructions don't support rotation so we have to cheat using shifts and a help register + "VSHL.I32 q3, q12, #8 \n\t" + "ROR r5, r5, #25 \n\t" // 5 5 + "VSHL.I32 q7, q13, #8 \n\t" + "ROR r6, r6, #25 \n\t" // 6 6 + "VSHL.I32 q11, q14, #8 \n\t" + + // r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 + // 0 1 2 3 4 5 6 7 8 9 12 13 14 + + // 2, 7, 8, 13 + // 3, 4, 9, 14 + + "ADD r2, r2, r7 \n\t" // 2 2 7 + "VSRI.I32 q3, q12, #24 \n\t" + "ADD r3, r3, r4 \n\t" // 3 3 4 + "VSRI.I32 q7, q13, #24 \n\t" + "EOR r11, r11, r2 \n\t" // 13 13 2 + "VSRI.I32 q11, q14, #24 \n\t" + + "EOR r12, r12, r3 \n\t" // 14 14 3 + "VADD.I32 q2, q2, q3 \n\t" + "ROR r11, r11, #16 \n\t" // 13 13 + "VADD.I32 q6, q6, q7 \n\t" + "ROR r12, r12, #16 \n\t" // 14 14 + "VADD.I32 q10, q10, q11 \n\t" + "ADD r8, r8, r11 \n\t" // 8 8 13 + "VEOR q12, q1, q2 \n\t" + "ADD r9, r9, r12 \n\t" // 9 9 14 + "VEOR q13, q5, q6 \n\t" + "EOR r7, r7, r8 \n\t" // 7 7 8 + "VEOR q14, q9, q10 \n\t" + "EOR r4, r4, r9 \n\t" // 4 4 9 + // SIMD instructions don't support rotation so we have to cheat using shifts and a help register + "VSHL.I32 q1, q12, #7 \n\t" + "ROR r7, r7, #20 \n\t" // 7 7 + "VSHL.I32 q5, q13, #7 \n\t" + "ROR r4, r4, #20 \n\t" // 4 4 + "VSHL.I32 q9, q14, #7 \n\t" + "ADD r2, r2, r7 \n\t" // 2 2 7 + "VSRI.I32 q1, q12, #25 \n\t" + "ADD r3, r3, r4 \n\t" // 3 3 4 + "VSRI.I32 q5, q13, #25 \n\t" + "EOR r11, r11, r2 \n\t" // 13 13 2 + "VSRI.I32 q9, q14, #25 \n\t" + + "EOR r12, r12, r3 \n\t" // 14 14 3 + "VEXT.8 q1, q1, q1, #12 \n\t" // permute elements left by three + "ROR r11, r11, #24 \n\t" // 13 13 + "VEXT.8 q2, q2, q2, #8 \n\t" // permute elements left by two + "ROR r12, r12, #24 \n\t" // 14 14 + "VEXT.8 q3, q3, q3, #4 \n\t" // permute elements left by one + + "ADD r8, r8, r11 \n\t" // 8 8 13 + "VEXT.8 q5, q5, q5, #12 \n\t" // permute elements left by three + "ADD r9, r9, r12 \n\t" // 9 9 14 + "VEXT.8 q6, q6, q6, #8 \n\t" // permute elements left by two + "EOR r7, r7, r8 \n\t" // 7 7 8 + "VEXT.8 q7, q7, q7, #4 \n\t" // permute elements left by one + + "EOR r4, r4, r9 \n\t" // 4 4 9 + "VEXT.8 q9, q9, q9, #12 \n\t" // permute elements left by three + "ROR r7, r7, #25 \n\t" // 7 7 + "VEXT.8 q10, q10, q10, #8 \n\t" // permute elements left by two + "ROR r4, r4, #25 \n\t" // 4 4 + "VEXT.8 q11, q11, q11, #4 \n\t" // permute elements left by one + + "BNE L_chacha20_arm32_256_loop_%= \n\t" + + "LDR r14, %[x_addr] \n\t" // load address of x to r14 + // r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 + // 0 1 2 3 4 5 6 7 8 9 12 13 14 + "ADD r10, r10, #3 \n\t" // add three here to make later NEON easier + "STM r14, { r0-r9 } \n\t" + "STRD r10, r11, [r14, #4*12] \n\t" + "LDR r9, %[input] \n\t" // load input address + "STR r12, [r14, #4*14] \n\t" + "LDR r10, %[c] \n\t" // load c address + + "VLDM r9, { q12-q15 } \n\t" + "LDR r12, %[m] \n\t" // load m address + + "VADD.I32 q0, q0, q12 \n\t" + "VADD.I32 q1, q1, q13 \n\t" + "VADD.I32 q2, q2, q14 \n\t" + "VADD.I32 q3, q3, q15 \n\t" + + "VADD.I32 q4, q4, q12 \n\t" + "VADD.I32 q5, q5, q13 \n\t" + "VADD.I32 q6, q6, q14 \n\t" + "VADD.I32 q7, q7, q15 \n\t" + + "MOV r11, #1 \n\t" + + "VADD.I32 q8, q8, q12 \n\t" + "VMOV.I32 q12, #0 \n\t" + "VADD.I32 q9, q9, q13 \n\t" + "VMOV.I32 d24[0], r11 \n\t" + "VADD.I32 q10, q10, q14 \n\t" + "VADD.I32 q11, q11, q15 \n\t" + + "VADD.I32 q11, q11, q12 \n\t" // add one to counter + "VADD.I32 q7, q7, q12 \n\t" // add one to counter + "VADD.I32 q11, q11, q12 \n\t" // add one to counter + + "VLDM r12!, { q12-q15 } \n\t" // load m + "VEOR q0, q0, q12 \n\t" + "VEOR q1, q1, q13 \n\t" + "VEOR q2, q2, q14 \n\t" + "VEOR q3, q3, q15 \n\t" + "VSTM r10!, { q0-q3 } \n\t" // store to c + + "VLDM r14, { q0-q3 } \n\t " // load final block from x + + "VLDM r12!, { q12-q15 } \n\t" // load m + "VEOR q4, q4, q12 \n\t" + "VEOR q5, q5, q13 \n\t" + "VEOR q6, q6, q14 \n\t" + "VEOR q7, q7, q15 \n\t" + "VSTM r10!, { q4-q7 } \n\t" // store to c + + "VLDM r9, { q4-q7 } \n\t" // load input + + "VLDM r12!, { q12-q15 } \n\t" // load m + "VEOR q8, q8, q12 \n\t" + "VEOR q9, q9, q13 \n\t" + "VEOR q10, q10, q14 \n\t" + "VEOR q11, q11, q15 \n\t" + "VSTM r10!, { q8-q11 } \n\t" // store to c + + "VLDM r12!, { q12-q15 } \n\t" // load m + "VADD.I32 q0, q0, q4 \n\t" + "VADD.I32 q1, q1, q5 \n\t" + "VADD.I32 q2, q2, q6 \n\t" + "VADD.I32 q3, q3, q7 \n\t" // three was added earlier + "VEOR q0, q0, q12 \n\t" + "VEOR q1, q1, q13 \n\t" + "VEOR q2, q2, q14 \n\t" + "VEOR q3, q3, q15 \n\t" + "VSTM r10!, { q0-q3 } \n\t" // store to c + + : [c] "+m" (c), + [x_0] "=m" (x), + [x_8] "=m" (x[8]), + [x_9] "=m" (x[9]), + [x_10] "=m" (x[10]), + [x_11] "=m" (x[11]), + [x_13] "=m" (x[13]), + [x_15] "=m" (x[15]) + : [rounds] "I" (ROUNDS/2), [input] "m" (input), + [chacha_chunk_bytes] "I" (CHACHA_CHUNK_BYTES), + [m] "m" (m), [x_addr] "m" (x_addr) + : "memory", "cc", + "r0", "r1", "r2", "r3", + "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r14", + "q0", "q1", "q2", "q3", "q4", + "q5", "q6", "q7", "q8", "q9", + "q10", "q11", "q12", "q13", "q14", "q15" + ); + +#endif /* __aarch64__ */ + return CHACHA_CHUNK_BYTES * 4; +} + + +static WC_INLINE int wc_Chacha_encrypt_128(const word32 input[CHACHA_CHUNK_WORDS], const byte* m, byte* c) +{ +#ifdef CHACHA_TEST + printf("Entering wc_Chacha_encrypt_128\n"); +#endif /*CHACHA_TEST */ + +#ifdef __aarch64__ + __asm__ __volatile__ ( + /* Load incrementer register to modify counter */ + "LD1 {v22.16B}, [%[L_chacha20_neon_inc_first_word]] \n\t" + /* Load index look-up for rotating left 8 bits */ + "LD1 {v23.16B}, [%[L_chacha20_neon_rol8]] \n\t" + /* Load state to encrypt */ + "LD1 {v18.4S-v21.4S}, [%[input]] \n\t" + /* Load message */ + "LD1 {v14.4S-v17.4S}, [%[m]], #64 \n\t" + /* Move state into vector registers (x3) */ + "MOV v0.16B, v18.16B \n\t" + "MOV v1.16B, v19.16B \n\t" + "MOV v2.16B, v20.16B \n\t" + "MOV v3.16B, v21.16B \n\t" + "MOV v4.16B, v18.16B \n\t" + "MOV v5.16B, v19.16B \n\t" + "MOV v6.16B, v20.16B \n\t" + "MOV v7.16B, v21.16B \n\t" + /* Add counter word */ + "ADD v7.4S, v7.4S, v22.4S \n\t" + /* Set number of odd+even rounds to perform */ + "MOV w3, #10 \n\t" + "\n" + "L_chacha20_arm64_128_loop_%=: \n\t" + "SUBS w3, w3, #1 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "ADD v4.4S, v4.4S, v5.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "EOR v7.16B, v7.16B, v4.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + "REV32 v7.8H, v7.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "ADD v6.4S, v6.4S, v7.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "EOR v13.16B, v5.16B, v6.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SHL v5.4S, v13.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + "SRI v5.4S, v13.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "ADD v4.4S, v4.4S, v5.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "EOR v7.16B, v7.16B, v4.16B \n\t" + "TBL v3.16B, { v3.16B }, v23.16B \n\t" + "TBL v7.16B, { v7.16B }, v23.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "ADD v6.4S, v6.4S, v7.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "EOR v13.16B, v5.16B, v6.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SHL v5.4S, v13.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "SRI v5.4S, v13.4S, #25 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #4 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #12 \n\t" + "EXT v5.16B, v5.16B, v5.16B, #4 \n\t" + "EXT v6.16B, v6.16B, v6.16B, #8 \n\t" + "EXT v7.16B, v7.16B, v7.16B, #12 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "ADD v4.4S, v4.4S, v5.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "EOR v7.16B, v7.16B, v4.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + "REV32 v7.8H, v7.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "ADD v6.4S, v6.4S, v7.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "EOR v13.16B, v5.16B, v6.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SHL v5.4S, v13.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + "SRI v5.4S, v13.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "ADD v4.4S, v4.4S, v5.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "EOR v7.16B, v7.16B, v4.16B \n\t" + "TBL v3.16B, { v3.16B }, v23.16B \n\t" + "TBL v7.16B, { v7.16B }, v23.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "ADD v6.4S, v6.4S, v7.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "EOR v13.16B, v5.16B, v6.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SHL v5.4S, v13.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "SRI v5.4S, v13.4S, #25 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #12 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #4 \n\t" + "EXT v5.16B, v5.16B, v5.16B, #12 \n\t" + "EXT v6.16B, v6.16B, v6.16B, #8 \n\t" + "EXT v7.16B, v7.16B, v7.16B, #4 \n\t" + "BNE L_chacha20_arm64_128_loop_%= \n\t" + /* Add back state, XOR in message and store (load next block) */ + "ADD v0.4S, v0.4S, v18.4S \n\t" + "ADD v1.4S, v1.4S, v19.4S \n\t" + "ADD v2.4S, v2.4S, v20.4S \n\t" + "ADD v3.4S, v3.4S, v21.4S \n\t" + "EOR v0.16B, v0.16B, v14.16B \n\t" + "EOR v1.16B, v1.16B, v15.16B \n\t" + "EOR v2.16B, v2.16B, v16.16B \n\t" + "EOR v3.16B, v3.16B, v17.16B \n\t" + "LD1 {v14.4S-v17.4S}, [%[m]], #64 \n\t" + "ST1 {v0.4S-v3.4S}, [%[c]], #64 \n\t" + "ADD v21.4S, v21.4S, v22.4S \n\t" + "ADD v4.4S, v4.4S, v18.4S \n\t" + "ADD v5.4S, v5.4S, v19.4S \n\t" + "ADD v6.4S, v6.4S, v20.4S \n\t" + "ADD v7.4S, v7.4S, v21.4S \n\t" + "EOR v4.16B, v4.16B, v14.16B \n\t" + "EOR v5.16B, v5.16B, v15.16B \n\t" + "EOR v6.16B, v6.16B, v16.16B \n\t" + "EOR v7.16B, v7.16B, v17.16B \n\t" + "ST1 {v4.4S-v7.4S}, [%[c]], #64 \n\t" + : [input] "+r" (input), [m] "+r" (m), [c] "+r" (c) + : [L_chacha20_neon_rol8] "r" (L_chacha20_neon_rol8), + [L_chacha20_neon_inc_first_word] "r" (L_chacha20_neon_inc_first_word) + : "memory", "x3", "v0", "v1", "v2", "v3", "v4", "v5", "v6", + "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", + "v16", "v17", "v18", "v19", "v20", "v21" + ); +#else + __asm__ __volatile__ ( + "MOV r11, %[rounds] \n\t" + "MOV r12, #1 \n\t" + "VLDM %[input], { q0-q3 } \n\t" + "VMOV.I32 q8, #0 \n\t" + "VMOV q4, q0 \n\t" + "VMOV.I32 d16[0], r12 \n\t" + "VMOV q5, q1 \n\t" + "VMOV q6, q2 \n\t" + "VADD.I32 q7, q3, q8 \n\t" // add one to counter + + // store input + "VMOV q10, q0 \n\t" + "VMOV q11, q1 \n\t" + "VMOV q12, q2 \n\t" + "VMOV q13, q3 \n\t" + "\n" + "L_chacha20_arm32_128_loop_%=: \n\t" + "SUBS r11, r11, #1 \n\t" + + // ODD ROUND + "VADD.I32 q0, q0, q1 \n\t" + "VADD.I32 q4, q4, q5 \n\t" + "VEOR q8, q3, q0 \n\t" + "VEOR q9, q7, q4 \n\t" + // rotation by 16 bits may be done by reversing the 16 bit elements in 32 bit words + "VREV32.16 q3, q8 \n\t" + "VREV32.16 q7, q9 \n\t" + + "VADD.I32 q2, q2, q3 \n\t" + "VADD.I32 q6, q6, q7 \n\t" + "VEOR q8, q1, q2 \n\t" + "VEOR q9, q5, q6 \n\t" + // SIMD instructions don't support rotation so we have to cheat using shifts and a help register + "VSHL.I32 q1, q8, #12 \n\t" + "VSHL.I32 q5, q9, #12 \n\t" + "VSRI.I32 q1, q8, #20 \n\t" + "VSRI.I32 q5, q9, #20 \n\t" + + "VADD.I32 q0, q0, q1 \n\t" + "VADD.I32 q4, q4, q5 \n\t" + "VEOR q8, q3, q0 \n\t" + "VEOR q9, q7, q4 \n\t" + // SIMD instructions don't support rotation so we have to cheat using shifts and a help register + "VSHL.I32 q3, q8, #8 \n\t" + "VSHL.I32 q7, q9, #8 \n\t" + "VSRI.I32 q3, q8, #24 \n\t" + "VSRI.I32 q7, q9, #24 \n\t" + + "VADD.I32 q2, q2, q3 \n\t" + "VADD.I32 q6, q6, q7 \n\t" + "VEOR q8, q1, q2 \n\t" + "VEOR q9, q5, q6 \n\t" + // SIMD instructions don't support rotation so we have to cheat using shifts and a help register + "VSHL.I32 q1, q8, #7 \n\t" + "VSHL.I32 q5, q9, #7 \n\t" + "VSRI.I32 q1, q8, #25 \n\t" + "VSRI.I32 q5, q9, #25 \n\t" + + // EVEN ROUND + + "VEXT.8 q1, q1, q1, #4 \n\t" // permute elements left by one + "VEXT.8 q2, q2, q2, #8 \n\t" // permute elements left by two + "VEXT.8 q3, q3, q3, #12 \n\t" // permute elements left by three + + "VEXT.8 q5, q5, q5, #4 \n\t" // permute elements left by one + "VEXT.8 q6, q6, q6, #8 \n\t" // permute elements left by two + "VEXT.8 q7, q7, q7, #12 \n\t" // permute elements left by three + + "VADD.I32 q0, q0, q1 \n\t" + "VADD.I32 q4, q4, q5 \n\t" + "VEOR q8, q3, q0 \n\t" + "VEOR q9, q7, q4 \n\t" + // rotation by 16 bits may be done by reversing the 16 bit elements in 32 bit words + "VREV32.16 q3, q8 \n\t" + "VREV32.16 q7, q9 \n\t" + + "VADD.I32 q2, q2, q3 \n\t" + "VADD.I32 q6, q6, q7 \n\t" + "VEOR q8, q1, q2 \n\t" + "VEOR q9, q5, q6 \n\t" + // SIMD instructions don't support rotation so we have to cheat using shifts and a help register + "VSHL.I32 q1, q8, #12 \n\t" + "VSHL.I32 q5, q9, #12 \n\t" + "VSRI.I32 q1, q8, #20 \n\t" + "VSRI.I32 q5, q9, #20 \n\t" + + "VADD.I32 q0, q0, q1 \n\t" + "VADD.I32 q4, q4, q5 \n\t" + "VEOR q8, q3, q0 \n\t" + "VEOR q9, q7, q4 \n\t" + // SIMD instructions don't support rotation so we have to cheat using shifts and a help register + "VSHL.I32 q3, q8, #8 \n\t" + "VSHL.I32 q7, q9, #8 \n\t" + "VSRI.I32 q3, q8, #24 \n\t" + "VSRI.I32 q7, q9, #24 \n\t" + + "VADD.I32 q2, q2, q3 \n\t" + "VADD.I32 q6, q6, q7 \n\t" + "VEOR q8, q1, q2 \n\t" + "VEOR q9, q5, q6 \n\t" + // SIMD instructions don't support rotation so we have to cheat using shifts and a help register + "VSHL.I32 q1, q8, #7 \n\t" + "VSHL.I32 q5, q9, #7 \n\t" + "VSRI.I32 q1, q8, #25 \n\t" + "VSRI.I32 q5, q9, #25 \n\t" + + "VEXT.8 q1, q1, q1, #12 \n\t" // permute elements left by three + "VEXT.8 q2, q2, q2, #8 \n\t" // permute elements left by two + "VEXT.8 q3, q3, q3, #4 \n\t" // permute elements left by one + + "VEXT.8 q5, q5, q5, #12 \n\t" // permute elements left by three + "VEXT.8 q6, q6, q6, #8 \n\t" // permute elements left by two + "VEXT.8 q7, q7, q7, #4 \n\t" // permute elements left by one + + "BNE L_chacha20_arm32_128_loop_%= \n\t" + + "VMOV.I32 q8, #0 \n\t" + "VADD.I32 q0, q0, q10 \n\t" + "VADD.I32 q1, q1, q11 \n\t" + "VMOV.I32 d16[0], r12 \n\t" + "VADD.I32 q2, q2, q12 \n\t" + "VADD.I32 q3, q3, q13 \n\t" + + "VADD.I32 q13, q13, q8 \n\t" // add one to counter + + "VADD.I32 q4, q4, q10 \n\t" + "VADD.I32 q5, q5, q11 \n\t" + "VADD.I32 q6, q6, q12 \n\t" + "VADD.I32 q7, q7, q13 \n\t" + + "VLDM %[m], { q8-q15 } \n\t" + "VEOR q0, q0, q8 \n\t" + "VEOR q1, q1, q9 \n\t" + "VEOR q2, q2, q10 \n\t" + "VEOR q3, q3, q11 \n\t" + "VEOR q4, q4, q12 \n\t" + "VEOR q5, q5, q13 \n\t" + "VEOR q6, q6, q14 \n\t" + "VEOR q7, q7, q15 \n\t" + "VSTM %[c], { q0-q7 } \n\t" + + : [c] "+r" (c), [m] "+r" (m) + : [rounds] "I" (ROUNDS/2), [input] "r" (input), + [chacha_chunk_bytes] "I" (CHACHA_CHUNK_BYTES) + : "memory", "cc", + "r11", "r12", + "q0", "q1", "q2", "q3", "q4", + "q5", "q6", "q7", "q8", "q9", + "q10", "q11", "q12", "q13", "q14", "q15" + ); +#endif /* __aarch64__ */ + return CHACHA_CHUNK_BYTES * 2; +} + +static WC_INLINE void wc_Chacha_encrypt_64(const word32* input, const byte* m, + byte* c, word32 bytes) +{ +#ifdef CHACHA_TEST + printf("Entering wc_Chacha_encrypt_64 with %d bytes\n", bytes); +#endif /*CHACHA_TEST */ + +#ifdef __aarch64__ + word64 bytes64 = (word64) bytes; + __asm__ __volatile__ ( + /* Load index look-up for rotating left 8 bits */ + "LD1 {v13.16B}, [%[L_chacha20_neon_rol8]] \n\t" + "LD1 {v14.4S}, [%[L_chacha20_neon_inc_first_word]] \n\t" + /* Load state to encrypt */ + "LD1 {v8.4S-v11.4S}, [%[input]] \n\t" + "\n" + "L_chacha20_arm64_64_loop_%=: \n\t" + /* Move state into vector registers (x3) */ + "MOV v0.16B, v8.16B \n\t" + "MOV v1.16B, v9.16B \n\t" + "MOV v2.16B, v10.16B \n\t" + "MOV v3.16B, v11.16B \n\t" + /* Add counter word */ + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #12 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #4 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #4 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #12 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #12 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #4 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #4 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #12 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #12 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #4 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #4 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #12 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #12 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #4 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #4 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #12 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #12 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #4 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #4 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #12 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #12 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #4 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #4 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #12 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #12 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #4 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #4 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #12 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #12 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #4 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #4 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #12 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #12 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #4 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #4 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #12 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #12 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #4 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "REV32 v3.8H, v3.8H \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #12 \n\t" + "SRI v1.4S, v12.4S, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "ADD v0.4S, v0.4S, v1.4S \n\t" + "EOR v3.16B, v3.16B, v0.16B \n\t" + "TBL v3.16B, { v3.16B }, v13.16B \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "ADD v2.4S, v2.4S, v3.4S \n\t" + "EOR v12.16B, v1.16B, v2.16B \n\t" + "SHL v1.4S, v12.4S, #7 \n\t" + "SRI v1.4S, v12.4S, #25 \n\t" + "EXT v3.16B, v3.16B, v3.16B, #4 \n\t" + "EXT v1.16B, v1.16B, v1.16B, #12 \n\t" + "EXT v2.16B, v2.16B, v2.16B, #8 \n\t" + /* Add back state */ + "ADD v0.4S, v0.4S, v8.4S \n\t" + "ADD v1.4S, v1.4S, v9.4S \n\t" + "ADD v2.4S, v2.4S, v10.4S \n\t" + "ADD v3.4S, v3.4S, v11.4S \n\t" + "CMP %[bytes], #64 \n\t" + "BLT L_chacha20_arm64_64_lt_64_%= \n\t" + "LD1 {v4.4S-v7.4S}, [%[m]], #64 \n\t" + "EOR v4.16B, v4.16B, v0.16B \n\t" + "EOR v5.16B, v5.16B, v1.16B \n\t" + "EOR v6.16B, v6.16B, v2.16B \n\t" + "EOR v7.16B, v7.16B, v3.16B \n\t" + "ST1 {v4.4S-v7.4S}, [%[c]], #64 \n\t" + "SUBS %[bytes], %[bytes], #64 \n\t" + "ADD v11.4S, v11.4S, v14.4S \n\t" + "BNE L_chacha20_arm64_64_loop_%= \n\t" + "B L_chacha20_arm64_64_done_%= \n\t" + "\n" + "L_chacha20_arm64_64_lt_64_%=: \n\t" + "CMP %[bytes], #32 \n\t" + "BLT L_chacha20_arm64_64_lt_32_%= \n\t" + "LD1 {v4.4S, v5.4S}, [%[m]], #32 \n\t" + "EOR v4.16B, v4.16B, v0.16B \n\t" + "EOR v5.16B, v5.16B, v1.16B \n\t" + "ST1 {v4.4S, v5.4S}, [%[c]], #32 \n\t" + "SUBS %[bytes], %[bytes], #32 \n\t" + "MOV v0.16B, v2.16B \n\t" + "MOV v1.16B, v3.16B \n\t" + "BEQ L_chacha20_arm64_64_done_%= \n\t" + "\n" + "L_chacha20_arm64_64_lt_32_%=: \n\t" + "CMP %[bytes], #16 \n\t" + "BLT L_chacha20_arm64_64_lt_16_%= \n\t" + "LD1 {v4.4S}, [%[m]], #16 \n\t" + "EOR v4.16B, v4.16B, v0.16B \n\t" + "ST1 {v4.4S}, [%[c]], #16 \n\t" + "SUBS %[bytes], %[bytes], #16 \n\t" + "MOV v0.16B, v1.16B \n\t" + "BEQ L_chacha20_arm64_64_done_%= \n\t" + "\n" + "L_chacha20_arm64_64_lt_16_%=: \n\t" + "CMP %[bytes], #8 \n\t" + "BLT L_chacha20_arm64_64_lt_8_%= \n\t" + "LD1 {v4.2S}, [%[m]], #8 \n\t" + "EOR v4.8B, v4.8B, v0.8B \n\t" + "ST1 {v4.2S}, [%[c]], #8 \n\t" + "SUBS %[bytes], %[bytes], #8 \n\t" + "MOV v0.D[0], v0.D[1] \n\t" + "BEQ L_chacha20_arm64_64_done_%= \n\t" + "\n" + "L_chacha20_arm64_64_lt_8_%=: \n\t" + "MOV x4, v0.D[0] \n\t" + "LSL x5, %[bytes], #3 \n\t" + "\n" + "L_chacha20_arm64_64_loop_lt_8_%=: \n\t" + "LDRB w6, [%[m], %[bytes]] \n\t" + "ROR x7, x4, x5 \n\t" + "EOR w6, w6, w7 \n\t" + "STRB w6, [%[c], %[bytes]] \n\t" + "SUBS %[bytes], %[bytes], #1 \n\t" + "SUB x5, x5, #8 \n\t" + "BGE L_chacha20_arm64_64_loop_lt_8_%= \n\t" + "\n" + "L_chacha20_arm64_64_done_%=: \n\t" + : [input] "+r" (input), [m] "+r" (m), [c] "+r" (c), [bytes] "+r" (bytes64) + : [L_chacha20_neon_rol8] "r" (L_chacha20_neon_rol8), + [L_chacha20_neon_inc_first_word] "r" (L_chacha20_neon_inc_first_word) + : "memory", "x4", "x5", "x6", "x7", "v0", "v1", "v2", "v3", + "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11" + ); +#else + __asm__ __volatile__ ( + /* Get the input state */ + "VLDM %[input], { q8-q11 } \n\t" + /* Get the incrementer register */ + "VLDM %[L_chacha20_neon_inc_first_word], { q14 } \n\t" + "\n" + "L_chacha20_arm32_64_outer_loop_%=: \n\t" + /* Copy over the input state */ + "VMOV q0, q8 \n\t" + "VMOV q1, q9 \n\t" + "VMOV q2, q10 \n\t" + "VMOV q3, q11 \n\t" + /* Compute quarter rounds */ + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Odd->Even */ + "VEXT.8 q1, q1, q1, #4 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #12 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Even->Odd */ + "VEXT.8 q1, q1, q1, #12 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #4 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Odd->Even */ + "VEXT.8 q1, q1, q1, #4 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #12 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Even->Odd */ + "VEXT.8 q1, q1, q1, #12 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #4 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Odd->Even */ + "VEXT.8 q1, q1, q1, #4 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #12 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Even->Odd */ + "VEXT.8 q1, q1, q1, #12 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #4 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Odd->Even */ + "VEXT.8 q1, q1, q1, #4 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #12 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Even->Odd */ + "VEXT.8 q1, q1, q1, #12 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #4 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Odd->Even */ + "VEXT.8 q1, q1, q1, #4 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #12 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Even->Odd */ + "VEXT.8 q1, q1, q1, #12 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #4 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Odd->Even */ + "VEXT.8 q1, q1, q1, #4 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #12 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Even->Odd */ + "VEXT.8 q1, q1, q1, #12 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #4 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Odd->Even */ + "VEXT.8 q1, q1, q1, #4 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #12 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Even->Odd */ + "VEXT.8 q1, q1, q1, #12 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #4 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Odd->Even */ + "VEXT.8 q1, q1, q1, #4 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #12 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Even->Odd */ + "VEXT.8 q1, q1, q1, #12 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #4 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Odd->Even */ + "VEXT.8 q1, q1, q1, #4 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #12 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Even->Odd */ + "VEXT.8 q1, q1, q1, #12 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #4 \n\t" + /* Odd Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Odd->Even */ + "VEXT.8 q1, q1, q1, #4 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #12 \n\t" + /* Even Round */ + /* a += b; d ^= a; d <<<= 16; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VREV32.16 q3, q4 \n\t" + /* c += d; b ^= c; b <<<= 12; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #12 \n\t" + "VSRI.I32 q1, q4, #20 \n\t" + /* a += b; d ^= a; d <<<= 8; */ + "VADD.I32 q0, q0, q1 \n\t" + "VEOR q4, q3, q0 \n\t" + "VSHL.I32 q3, q4, #8 \n\t" + "VSRI.I32 q3, q4, #24 \n\t" + /* c += d; b ^= c; b <<<= 7; */ + "VADD.I32 q2, q2, q3 \n\t" + "VEOR q4, q1, q2 \n\t" + "VSHL.I32 q1, q4, #7 \n\t" + "VSRI.I32 q1, q4, #25 \n\t" + /* Permute Even->Odd */ + "VEXT.8 q1, q1, q1, #12 \n\t" + "VEXT.8 q2, q2, q2, #8 \n\t" + "VEXT.8 q3, q3, q3, #4 \n\t" + /* Add back state */ + "VADD.I32 q0, q0, q8 \n\t" + "VADD.I32 q1, q1, q9 \n\t" + "VADD.I32 q2, q2, q10 \n\t" + "VADD.I32 q3, q3, q11 \n\t" + "CMP %[bytes], #64 \n\t" + "BLT L_chacha20_arm32_64_lt_64_%= \n\t" + /* XOR full 64 byte block */ + "VLDM %[m], { q4-q7 } \n\t" + "ADD %[m], %[m], #64 \n\t" + "VEOR q0, q0, q4 \n\t" + "VEOR q1, q1, q5 \n\t" + "VEOR q2, q2, q6 \n\t" + "VEOR q3, q3, q7 \n\t" + "VSTM %[c], { q0-q3 } \n\t" + "ADD %[c], %[c], #64 \n\t" + "SUBS %[bytes], %[bytes], #64 \n\t" + "VADD.I32 q11, q11, q14 \n\t" + "BNE L_chacha20_arm32_64_outer_loop_%= \n\t" + "B L_chacha20_arm32_64_done_%= \n\t" + "\n" + "L_chacha20_arm32_64_lt_64_%=: \n\t" + /* XOR 32 bytes */ + "CMP %[bytes], #32 \n\t" + "BLT L_chacha20_arm32_64_lt_32_%= \n\t" + "VLDM %[m], { q4-q5 } \n\t" + "ADD %[m], %[m], #32 \n\t" + "VEOR q4, q4, q0 \n\t" + "VEOR q5, q5, q1 \n\t" + "VSTM %[c], { q4-q5 } \n\t" + "ADD %[c], %[c], #32 \n\t" + "SUBS %[bytes], %[bytes], #32 \n\t" + "VMOV q0, q2 \n\t" + "VMOV q1, q3 \n\t" + "BEQ L_chacha20_arm32_64_done_%= \n\t" + "\n" + "L_chacha20_arm32_64_lt_32_%=: \n\t" + /* XOR 16 bytes */ + "CMP %[bytes], #16 \n\t" + "BLT L_chacha20_arm32_64_lt_16_%= \n\t" + "VLDM %[m], { q4 } \n\t" + "ADD %[m], %[m], #16 \n\t" + "VEOR q4, q4, q0 \n\t" + "VSTM %[c], { q4 } \n\t" + "ADD %[c], %[c], #16 \n\t" + "SUBS %[bytes], %[bytes], #16 \n\t" + "VMOV q0, q1 \n\t" + "BEQ L_chacha20_arm32_64_done_%= \n\t" + "\n" + "L_chacha20_arm32_64_lt_16_%=: \n\t" + /* XOR 8 bytes */ + "CMP %[bytes], #8 \n\t" + "BLT L_chacha20_arm32_64_lt_8_%= \n\t" + "VLDR d8, [%[m], #0] \n\t" + "ADD %[m], %[m], #8 \n\t" + "VEOR d8, d8, d0 \n\t" + "VSTR d8, [%[c], #0] \n\t" + "ADD %[c], %[c], #8 \n\t" + "SUBS %[bytes], %[bytes], #8 \n\t" + "VMOV d0, d1 \n\t" + "BEQ L_chacha20_arm32_64_done_%= \n\t" + "\n" + "L_chacha20_arm32_64_lt_8_%=: \n\t" + /* XOR 4 bytes */ + "CMP %[bytes], #4 \n\t" + "BLT L_chacha20_arm32_64_lt_4_%= \n\t" + "LDR r12, [%[m]], #4 \n\t" + "VMOV r14, d0[0] \n\t" + "EOR r12, r12, r14 \n\t" + "STR r12, [%[c]], #4 \n\t" + "SUBS %[bytes], %[bytes], #4 \n\t" + "VTRN.32 d0, d0 \n\t" + "BEQ L_chacha20_arm32_64_done_%= \n\t" + "\n" + "L_chacha20_arm32_64_lt_4_%=: \n\t" + /* XOR remaining bytes */ + "VMOV r14, d0[0] \n\t" + "\n" + "L_chacha20_arm32_64_lt_4_loop_%=: \n\t" + "LDRB r12, [%[m]], #1 \n\t" + "EOR r12, r12, r14 \n\t" + "STRB r12, [%[c]], #1 \n\t" + "SUBS %[bytes], %[bytes], #1 \n\t" + "LSR r14, r14, #8 \n\t" + "BGT L_chacha20_arm32_64_lt_4_loop_%= \n\t" + "\n" + "L_chacha20_arm32_64_done_%=: \n\t" + : [input] "+r" (input), [m] "+r" (m), [c] "+r" (c), [bytes] "+r" (bytes) + : [L_chacha20_neon_inc_first_word] "r" (L_chacha20_neon_inc_first_word) + : "memory", "cc", + "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q14", "r12", "r14" + ); +#endif /* __aarch64__ */ +} + +/** + * Encrypt a stream of bytes + */ +static void wc_Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c, + word32 bytes) +{ + int processed; + +#ifdef __aarch64__ + if (bytes >= CHACHA_CHUNK_BYTES * 5) { + processed = (bytes / (CHACHA_CHUNK_BYTES * 5)) * CHACHA_CHUNK_BYTES * 5; + wc_Chacha_encrypt_320(ctx->X, m, c, processed); + + bytes -= processed; + c += processed; + m += processed; + ctx->X[CHACHA_IV_BYTES] = PLUS(ctx->X[CHACHA_IV_BYTES], processed / CHACHA_CHUNK_BYTES); + } + if (bytes >= CHACHA_CHUNK_BYTES * 4) { +#else + while (bytes >= CHACHA_CHUNK_BYTES * 4) { +#endif /*__aarch64__ */ + processed = wc_Chacha_encrypt_256(ctx->X, m, c); + + bytes -= processed; + c += processed; + m += processed; + ctx->X[CHACHA_IV_BYTES] = PLUS(ctx->X[CHACHA_IV_BYTES], processed / CHACHA_CHUNK_BYTES); + } + if (bytes >= CHACHA_CHUNK_BYTES * 2) { + processed = wc_Chacha_encrypt_128(ctx->X, m, c); + + bytes -= processed; + c += processed; + m += processed; + ctx->X[CHACHA_IV_BYTES] = PLUS(ctx->X[CHACHA_IV_BYTES], processed / CHACHA_CHUNK_BYTES); + } + if (bytes > 0) { + wc_Chacha_encrypt_64(ctx->X, m, c, bytes); + if (bytes > 64) + ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]); + ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]); + } +} + +/** + * API to encrypt/decrypt a message of any size. + */ +int wc_Chacha_Process(ChaCha* ctx, byte* output, const byte* input, + word32 msglen) +{ + if (ctx == NULL || output == NULL || input == NULL) + return BAD_FUNC_ARG; + + wc_Chacha_encrypt_bytes(ctx, input, output, msglen); + + return 0; +} + +#endif /* HAVE_CHACHA */ +#endif /* WOLFSSL_ARMASM */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-curve25519.S b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-curve25519.S new file mode 100644 index 000000000..891c6d815 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-curve25519.S @@ -0,0 +1,6715 @@ +/* armv8-curve25519 + * + * Copyright (C) 2006-2020 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 + */ + +/* Generated using (from wolfssl): + * cd ../scripts + * ruby ./x25519/x25519.rb arm64 ../wolfssl/wolfcrypt/src/port/arm/armv8-curve25519.S + */ +#ifdef __aarch64__ + .text + .align 2 + .globl fe_init + .type fe_init, %function +fe_init: + ret + .size fe_init,.-fe_init + .text + .align 2 + .globl fe_frombytes + .type fe_frombytes, %function +fe_frombytes: + ldp x2, x3, [x1] + ldp x4, x5, [x1, #16] + and x5, x5, #0x7fffffffffffffff + stp x2, x3, [x0] + stp x4, x5, [x0, #16] + ret + .size fe_frombytes,.-fe_frombytes + .text + .align 2 + .globl fe_tobytes + .type fe_tobytes, %function +fe_tobytes: + mov x7, #19 + ldp x2, x3, [x1] + ldp x4, x5, [x1, #16] + adds x6, x2, x7 + adcs x6, x3, xzr + adcs x6, x4, xzr + adc x6, x5, xzr + and x6, x7, x6, asr 63 + adds x2, x2, x6 + adcs x3, x3, xzr + adcs x4, x4, xzr + adc x5, x5, xzr + and x5, x5, #0x7fffffffffffffff + stp x2, x3, [x0] + stp x4, x5, [x0, #16] + ret + .size fe_tobytes,.-fe_tobytes + .text + .align 2 + .globl fe_1 + .type fe_1, %function +fe_1: + # Set one + mov x1, #1 + stp x1, xzr, [x0] + stp xzr, xzr, [x0, #16] + ret + .size fe_1,.-fe_1 + .text + .align 2 + .globl fe_0 + .type fe_0, %function +fe_0: + # Set zero + stp xzr, xzr, [x0] + stp xzr, xzr, [x0, #16] + ret + .size fe_0,.-fe_0 + .text + .align 2 + .globl fe_copy + .type fe_copy, %function +fe_copy: + # Copy + ldp x2, x3, [x1] + ldp x4, x5, [x1, #16] + stp x2, x3, [x0] + stp x4, x5, [x0, #16] + ret + .size fe_copy,.-fe_copy + .text + .align 2 + .globl fe_sub + .type fe_sub, %function +fe_sub: + # Sub + ldp x3, x4, [x1] + ldp x5, x6, [x1, #16] + ldp x7, x8, [x2] + ldp x9, x10, [x2, #16] + subs x3, x3, x7 + sbcs x4, x4, x8 + sbcs x5, x5, x9 + sbcs x6, x6, x10 + mov x12, #-19 + csetm x11, cc + # Mask the modulus + and x12, x11, x12 + and x13, x11, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x3, x3, x12 + adcs x4, x4, x11 + adcs x5, x5, x11 + adc x6, x6, x13 + stp x3, x4, [x0] + stp x5, x6, [x0, #16] + ret + .size fe_sub,.-fe_sub + .text + .align 2 + .globl fe_add + .type fe_add, %function +fe_add: + # Add + ldp x3, x4, [x1] + ldp x5, x6, [x1, #16] + ldp x7, x8, [x2] + ldp x9, x10, [x2, #16] + adds x3, x3, x7 + adcs x4, x4, x8 + adcs x5, x5, x9 + adc x6, x6, x10 + mov x12, #-19 + asr x11, x6, #63 + # Mask the modulus + and x12, x11, x12 + and x13, x11, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x3, x3, x12 + sbcs x4, x4, x11 + sbcs x5, x5, x11 + sbc x6, x6, x13 + stp x3, x4, [x0] + stp x5, x6, [x0, #16] + ret + .size fe_add,.-fe_add + .text + .align 2 + .globl fe_neg + .type fe_neg, %function +fe_neg: + ldp x2, x3, [x1] + ldp x4, x5, [x1, #16] + mov x6, #-19 + mov x7, #-1 + mov x8, #-1 + mov x9, #0x7fffffffffffffff + subs x6, x6, x2 + sbcs x7, x7, x3 + sbcs x8, x8, x4 + sbc x9, x9, x5 + stp x6, x7, [x0] + stp x8, x9, [x0, #16] + ret + .size fe_neg,.-fe_neg + .text + .align 2 + .globl fe_isnonzero + .type fe_isnonzero, %function +fe_isnonzero: + mov x6, #19 + ldp x1, x2, [x0] + ldp x3, x4, [x0, #16] + adds x5, x1, x6 + adcs x5, x2, xzr + adcs x5, x3, xzr + adc x5, x4, xzr + and x5, x6, x5, asr 63 + adds x1, x1, x5 + adcs x2, x2, xzr + adcs x3, x3, xzr + adc x4, x4, xzr + and x4, x4, #0x7fffffffffffffff + orr x0, x1, x2 + orr x3, x3, x4 + orr x0, x0, x3 + ret + .size fe_isnonzero,.-fe_isnonzero + .text + .align 2 + .globl fe_isnegative + .type fe_isnegative, %function +fe_isnegative: + mov x6, #19 + ldp x1, x2, [x0] + ldp x3, x4, [x0, #16] + adds x5, x1, x6 + adcs x5, x2, xzr + adcs x5, x3, xzr + adc x5, x4, xzr + and x0, x1, #1 + eor x0, x0, x5, lsr 63 + ret + .size fe_isnegative,.-fe_isnegative + .text + .align 2 + .globl fe_cmov_table + .type fe_cmov_table, %function +fe_cmov_table: + stp x29, x30, [sp, #-128]! + add x29, sp, #0 + str x17, [x29, #40] + str x19, [x29, #48] + stp x20, x21, [x29, #56] + stp x22, x23, [x29, #72] + stp x24, x25, [x29, #88] + stp x26, x27, [x29, #104] + str x28, [x29, #120] + str x0, [x29, #16] + sxtb x2, w2 + sbfx x3, x2, #7, #1 + eor x0, x2, x3 + sub x0, x0, x3 + mov x4, #1 + mov x5, xzr + mov x6, xzr + mov x7, xzr + mov x8, #1 + mov x9, xzr + mov x10, xzr + mov x11, xzr + mov x12, xzr + mov x13, xzr + mov x14, xzr + mov x15, xzr + cmp x0, #1 + ldp x16, x17, [x1] + ldp x19, x20, [x1, #16] + ldp x21, x22, [x1, #32] + ldp x23, x24, [x1, #48] + ldp x25, x26, [x1, #64] + ldp x27, x28, [x1, #80] + csel x4, x16, x4, eq + csel x5, x17, x5, eq + csel x6, x19, x6, eq + csel x7, x20, x7, eq + csel x8, x21, x8, eq + csel x9, x22, x9, eq + csel x10, x23, x10, eq + csel x11, x24, x11, eq + csel x12, x25, x12, eq + csel x13, x26, x13, eq + csel x14, x27, x14, eq + csel x15, x28, x15, eq + cmp x0, #2 + ldp x16, x17, [x1, #96] + ldp x19, x20, [x1, #112] + ldp x21, x22, [x1, #128] + ldp x23, x24, [x1, #144] + ldp x25, x26, [x1, #160] + ldp x27, x28, [x1, #176] + csel x4, x16, x4, eq + csel x5, x17, x5, eq + csel x6, x19, x6, eq + csel x7, x20, x7, eq + csel x8, x21, x8, eq + csel x9, x22, x9, eq + csel x10, x23, x10, eq + csel x11, x24, x11, eq + csel x12, x25, x12, eq + csel x13, x26, x13, eq + csel x14, x27, x14, eq + csel x15, x28, x15, eq + cmp x0, #3 + ldp x16, x17, [x1, #192] + ldp x19, x20, [x1, #208] + ldp x21, x22, [x1, #224] + ldp x23, x24, [x1, #240] + ldp x25, x26, [x1, #256] + ldp x27, x28, [x1, #272] + csel x4, x16, x4, eq + csel x5, x17, x5, eq + csel x6, x19, x6, eq + csel x7, x20, x7, eq + csel x8, x21, x8, eq + csel x9, x22, x9, eq + csel x10, x23, x10, eq + csel x11, x24, x11, eq + csel x12, x25, x12, eq + csel x13, x26, x13, eq + csel x14, x27, x14, eq + csel x15, x28, x15, eq + cmp x0, #4 + ldp x16, x17, [x1, #288] + ldp x19, x20, [x1, #304] + ldp x21, x22, [x1, #320] + ldp x23, x24, [x1, #336] + ldp x25, x26, [x1, #352] + ldp x27, x28, [x1, #368] + csel x4, x16, x4, eq + csel x5, x17, x5, eq + csel x6, x19, x6, eq + csel x7, x20, x7, eq + csel x8, x21, x8, eq + csel x9, x22, x9, eq + csel x10, x23, x10, eq + csel x11, x24, x11, eq + csel x12, x25, x12, eq + csel x13, x26, x13, eq + csel x14, x27, x14, eq + csel x15, x28, x15, eq + add x1, x1, #0x180 + cmp x0, #5 + ldp x16, x17, [x1] + ldp x19, x20, [x1, #16] + ldp x21, x22, [x1, #32] + ldp x23, x24, [x1, #48] + ldp x25, x26, [x1, #64] + ldp x27, x28, [x1, #80] + csel x4, x16, x4, eq + csel x5, x17, x5, eq + csel x6, x19, x6, eq + csel x7, x20, x7, eq + csel x8, x21, x8, eq + csel x9, x22, x9, eq + csel x10, x23, x10, eq + csel x11, x24, x11, eq + csel x12, x25, x12, eq + csel x13, x26, x13, eq + csel x14, x27, x14, eq + csel x15, x28, x15, eq + cmp x0, #6 + ldp x16, x17, [x1, #96] + ldp x19, x20, [x1, #112] + ldp x21, x22, [x1, #128] + ldp x23, x24, [x1, #144] + ldp x25, x26, [x1, #160] + ldp x27, x28, [x1, #176] + csel x4, x16, x4, eq + csel x5, x17, x5, eq + csel x6, x19, x6, eq + csel x7, x20, x7, eq + csel x8, x21, x8, eq + csel x9, x22, x9, eq + csel x10, x23, x10, eq + csel x11, x24, x11, eq + csel x12, x25, x12, eq + csel x13, x26, x13, eq + csel x14, x27, x14, eq + csel x15, x28, x15, eq + cmp x0, #7 + ldp x16, x17, [x1, #192] + ldp x19, x20, [x1, #208] + ldp x21, x22, [x1, #224] + ldp x23, x24, [x1, #240] + ldp x25, x26, [x1, #256] + ldp x27, x28, [x1, #272] + csel x4, x16, x4, eq + csel x5, x17, x5, eq + csel x6, x19, x6, eq + csel x7, x20, x7, eq + csel x8, x21, x8, eq + csel x9, x22, x9, eq + csel x10, x23, x10, eq + csel x11, x24, x11, eq + csel x12, x25, x12, eq + csel x13, x26, x13, eq + csel x14, x27, x14, eq + csel x15, x28, x15, eq + cmp x0, #8 + ldp x16, x17, [x1, #288] + ldp x19, x20, [x1, #304] + ldp x21, x22, [x1, #320] + ldp x23, x24, [x1, #336] + ldp x25, x26, [x1, #352] + ldp x27, x28, [x1, #368] + csel x4, x16, x4, eq + csel x5, x17, x5, eq + csel x6, x19, x6, eq + csel x7, x20, x7, eq + csel x8, x21, x8, eq + csel x9, x22, x9, eq + csel x10, x23, x10, eq + csel x11, x24, x11, eq + csel x12, x25, x12, eq + csel x13, x26, x13, eq + csel x14, x27, x14, eq + csel x15, x28, x15, eq + mov x16, #-19 + mov x17, #-1 + mov x19, #-1 + mov x20, #0x7fffffffffffffff + subs x16, x16, x12 + sbcs x17, x17, x13 + sbcs x19, x19, x14 + sbc x20, x20, x15 + cmp x2, #0 + mov x3, x4 + csel x4, x8, x4, lt + csel x8, x3, x8, lt + mov x3, x5 + csel x5, x9, x5, lt + csel x9, x3, x9, lt + mov x3, x6 + csel x6, x10, x6, lt + csel x10, x3, x10, lt + mov x3, x7 + csel x7, x11, x7, lt + csel x11, x3, x11, lt + csel x12, x16, x12, lt + csel x13, x17, x13, lt + csel x14, x19, x14, lt + csel x15, x20, x15, lt + ldr x0, [x29, #16] + stp x4, x5, [x0] + stp x6, x7, [x0, #16] + stp x8, x9, [x0, #32] + stp x10, x11, [x0, #48] + stp x12, x13, [x0, #64] + stp x14, x15, [x0, #80] + ldr x17, [x29, #40] + ldr x19, [x29, #48] + ldp x20, x21, [x29, #56] + ldp x22, x23, [x29, #72] + ldp x24, x25, [x29, #88] + ldp x26, x27, [x29, #104] + ldr x28, [x29, #120] + ldp x29, x30, [sp], #0x80 + ret + .size fe_cmov_table,.-fe_cmov_table + .text + .align 2 + .globl fe_mul + .type fe_mul, %function +fe_mul: + stp x29, x30, [sp, #-64]! + add x29, sp, #0 + str x17, [x29, #24] + str x19, [x29, #32] + stp x20, x21, [x29, #40] + str x22, [x29, #56] + # Multiply + ldp x14, x15, [x1] + ldp x16, x17, [x1, #16] + ldp x19, x20, [x2] + ldp x21, x22, [x2, #16] + # A[0] * B[0] + mul x6, x14, x19 + umulh x7, x14, x19 + # A[0] * B[1] + mul x3, x14, x20 + umulh x8, x14, x20 + adds x7, x7, x3 + adc x8, x8, xzr + # A[1] * B[0] + mul x3, x15, x19 + umulh x4, x15, x19 + adds x7, x7, x3 + adcs x8, x8, x4 + adc x9, xzr, xzr + # A[0] * B[2] + mul x3, x14, x21 + umulh x4, x14, x21 + adds x8, x8, x3 + adc x9, x9, x4 + # A[1] * B[1] + mul x3, x15, x20 + umulh x4, x15, x20 + adds x8, x8, x3 + adcs x9, x9, x4 + adc x10, xzr, xzr + # A[2] * B[0] + mul x3, x16, x19 + umulh x4, x16, x19 + adds x8, x8, x3 + adcs x9, x9, x4 + adc x10, x10, xzr + # A[0] * B[3] + mul x3, x14, x22 + umulh x4, x14, x22 + adds x9, x9, x3 + adcs x10, x10, x4 + adc x11, xzr, xzr + # A[1] * B[2] + mul x3, x15, x21 + umulh x4, x15, x21 + adds x9, x9, x3 + adcs x10, x10, x4 + adc x11, x11, xzr + # A[2] * B[1] + mul x3, x16, x20 + umulh x4, x16, x20 + adds x9, x9, x3 + adcs x10, x10, x4 + adc x11, x11, xzr + # A[3] * B[0] + mul x3, x17, x19 + umulh x4, x17, x19 + adds x9, x9, x3 + adcs x10, x10, x4 + adc x11, x11, xzr + # A[1] * B[3] + mul x3, x15, x22 + umulh x4, x15, x22 + adds x10, x10, x3 + adcs x11, x11, x4 + adc x12, xzr, xzr + # A[2] * B[2] + mul x3, x16, x21 + umulh x4, x16, x21 + adds x10, x10, x3 + adcs x11, x11, x4 + adc x12, x12, xzr + # A[3] * B[1] + mul x3, x17, x20 + umulh x4, x17, x20 + adds x10, x10, x3 + adcs x11, x11, x4 + adc x12, x12, xzr + # A[2] * B[3] + mul x3, x16, x22 + umulh x4, x16, x22 + adds x11, x11, x3 + adcs x12, x12, x4 + adc x13, xzr, xzr + # A[3] * B[2] + mul x3, x17, x21 + umulh x4, x17, x21 + adds x11, x11, x3 + adcs x12, x12, x4 + adc x13, x13, xzr + # A[3] * B[3] + mul x3, x17, x22 + umulh x4, x17, x22 + adds x12, x12, x3 + adc x13, x13, x4 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x13, x13, x12, #63 + extr x12, x12, x11, #63 + extr x11, x11, x10, #63 + extr x10, x10, x9, #63 + and x9, x9, #0x7fffffffffffffff + # Multiply top half by 19 + mov x3, #19 + mul x4, x3, x10 + umulh x10, x3, x10 + adds x6, x6, x4 + mul x4, x3, x11 + umulh x11, x3, x11 + adcs x7, x7, x4 + mul x4, x3, x12 + umulh x12, x3, x12 + adcs x8, x8, x4 + mul x4, x3, x13 + umulh x5, x3, x13 + adcs x9, x9, x4 + adc x5, x5, xzr + # Add remaining product results in + adds x7, x7, x10 + adcs x8, x8, x11 + adcs x9, x9, x12 + adc x5, x5, xzr + # Overflow + extr x5, x5, x9, #63 + mul x5, x5, x3 + and x9, x9, #0x7fffffffffffffff + adds x6, x6, x5 + adcs x7, x7, xzr + adcs x8, x8, xzr + adc x9, x9, xzr + # Reduce if top bit set + and x5, x3, x9, asr 63 + and x9, x9, #0x7fffffffffffffff + adds x6, x6, x5 + adcs x7, x7, xzr + adcs x8, x8, xzr + adc x9, x9, xzr + # Store + stp x6, x7, [x0] + stp x8, x9, [x0, #16] + ldr x17, [x29, #24] + ldr x19, [x29, #32] + ldp x20, x21, [x29, #40] + ldr x22, [x29, #56] + ldp x29, x30, [sp], #0x40 + ret + .size fe_mul,.-fe_mul + .text + .align 2 + .globl fe_sq + .type fe_sq, %function +fe_sq: + # Square + ldp x13, x14, [x1] + ldp x15, x16, [x1, #16] + # A[0] * A[1] + mul x6, x13, x14 + umulh x7, x13, x14 + # A[0] * A[2] + mul x2, x13, x15 + umulh x8, x13, x15 + adds x7, x7, x2 + adc x8, x8, xzr + # A[0] * A[3] + mul x2, x13, x16 + umulh x9, x13, x16 + adds x8, x8, x2 + adc x9, x9, xzr + # A[1] * A[2] + mul x2, x14, x15 + umulh x3, x14, x15 + adds x8, x8, x2 + adcs x9, x9, x3 + adc x10, xzr, xzr + # A[1] * A[3] + mul x2, x14, x16 + umulh x3, x14, x16 + adds x9, x9, x2 + adc x10, x10, x3 + # A[2] * A[3] + mul x2, x15, x16 + umulh x11, x15, x16 + adds x10, x10, x2 + adc x11, x11, xzr + # Double + adds x6, x6, x6 + adcs x7, x7, x7 + adcs x8, x8, x8 + adcs x9, x9, x9 + adcs x10, x10, x10 + adcs x11, x11, x11 + adc x12, xzr, xzr + # A[0] * A[0] + mul x5, x13, x13 + umulh x4, x13, x13 + # A[1] * A[1] + mul x2, x14, x14 + umulh x3, x14, x14 + adds x6, x6, x4 + adcs x7, x7, x2 + adc x4, x3, xzr + # A[2] * A[2] + mul x2, x15, x15 + umulh x3, x15, x15 + adds x8, x8, x4 + adcs x9, x9, x2 + adc x4, x3, xzr + # A[3] * A[3] + mul x2, x16, x16 + umulh x3, x16, x16 + adds x10, x10, x4 + adcs x11, x11, x2 + adc x12, x12, x3 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x12, x12, x11, #63 + extr x11, x11, x10, #63 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + and x8, x8, #0x7fffffffffffffff + # Multiply top half by 19 + mov x2, #19 + mul x3, x2, x9 + umulh x9, x2, x9 + adds x5, x5, x3 + mul x3, x2, x10 + umulh x10, x2, x10 + adcs x6, x6, x3 + mul x3, x2, x11 + umulh x11, x2, x11 + adcs x7, x7, x3 + mul x3, x2, x12 + umulh x4, x2, x12 + adcs x8, x8, x3 + adc x4, x4, xzr + # Add remaining product results in + adds x6, x6, x9 + adcs x7, x7, x10 + adcs x8, x8, x11 + adc x4, x4, xzr + # Overflow + extr x4, x4, x8, #63 + mul x4, x4, x2 + and x8, x8, #0x7fffffffffffffff + adds x5, x5, x4 + adcs x6, x6, xzr + adcs x7, x7, xzr + adc x8, x8, xzr + # Reduce if top bit set + and x4, x2, x8, asr 63 + and x8, x8, #0x7fffffffffffffff + adds x5, x5, x4 + adcs x6, x6, xzr + adcs x7, x7, xzr + adc x8, x8, xzr + # Store + stp x5, x6, [x0] + stp x7, x8, [x0, #16] + ret + .size fe_sq,.-fe_sq + .text + .align 2 + .globl fe_invert + .type fe_invert, %function +fe_invert: + stp x29, x30, [sp, #-176]! + add x29, sp, #0 + str x20, [x29, #168] + # Invert + str x0, [x29, #144] + str x1, [x29, #152] + add x0, x29, #16 + bl fe_sq + add x0, x29, #48 + add x1, x29, #16 + bl fe_sq + add x1, x29, #48 + bl fe_sq + ldr x1, [x29, #152] + add x2, x29, #48 + bl fe_mul + add x0, x29, #16 + add x1, x29, #16 + add x2, x29, #48 + bl fe_mul + add x0, x29, #0x50 + bl fe_sq + add x0, x29, #48 + add x1, x29, #48 + add x2, x29, #0x50 + bl fe_mul + add x0, x29, #0x50 + bl fe_sq + mov x20, #4 + add x1, x29, #0x50 +L_fe_invert1: + bl fe_sq + sub x20, x20, #1 + cmp x20, #0 + bne L_fe_invert1 + add x0, x29, #48 + add x2, x29, #48 + bl fe_mul + add x0, x29, #0x50 + add x1, x29, #48 + bl fe_sq + mov x20, #9 + add x1, x29, #0x50 +L_fe_invert2: + bl fe_sq + sub x20, x20, #1 + cmp x20, #0 + bne L_fe_invert2 + add x2, x29, #48 + bl fe_mul + add x0, x29, #0x70 + bl fe_sq + mov x20, #19 + add x1, x29, #0x70 +L_fe_invert3: + bl fe_sq + sub x20, x20, #1 + cmp x20, #0 + bne L_fe_invert3 + add x0, x29, #0x50 + add x2, x29, #0x50 + bl fe_mul + mov x20, #10 + add x1, x29, #0x50 +L_fe_invert4: + bl fe_sq + sub x20, x20, #1 + cmp x20, #0 + bne L_fe_invert4 + add x0, x29, #48 + add x2, x29, #48 + bl fe_mul + add x0, x29, #0x50 + add x1, x29, #48 + bl fe_sq + mov x20, #49 + add x1, x29, #0x50 +L_fe_invert5: + bl fe_sq + sub x20, x20, #1 + cmp x20, #0 + bne L_fe_invert5 + add x2, x29, #48 + bl fe_mul + add x0, x29, #0x70 + bl fe_sq + mov x20, #0x63 + add x1, x29, #0x70 +L_fe_invert6: + bl fe_sq + sub x20, x20, #1 + cmp x20, #0 + bne L_fe_invert6 + add x0, x29, #0x50 + add x2, x29, #0x50 + bl fe_mul + mov x20, #50 + add x1, x29, #0x50 +L_fe_invert7: + bl fe_sq + sub x20, x20, #1 + cmp x20, #0 + bne L_fe_invert7 + add x0, x29, #48 + add x2, x29, #48 + bl fe_mul + mov x20, #5 + add x1, x29, #48 +L_fe_invert8: + bl fe_sq + sub x20, x20, #1 + cmp x20, #0 + bne L_fe_invert8 + ldr x0, [x29, #144] + add x2, x29, #16 + bl fe_mul + ldr x20, [x29, #168] + ldp x29, x30, [sp], #0xb0 + ret + .size fe_invert,.-fe_invert + .text + .align 2 + .globl curve25519 + .type curve25519, %function +curve25519: + stp x29, x30, [sp, #-288]! + add x29, sp, #0 + str x17, [x29, #200] + str x19, [x29, #208] + stp x20, x21, [x29, #216] + stp x22, x23, [x29, #232] + stp x24, x25, [x29, #248] + stp x26, x27, [x29, #264] + str x28, [x29, #280] + mov x23, xzr + str x0, [x29, #176] + str x2, [x29, #184] + # Copy + ldp x6, x7, [x2] + ldp x8, x9, [x2, #16] + stp x6, x7, [x29, #80] + stp x8, x9, [x29, #96] + # Set one + mov x2, #1 + stp x2, xzr, [x0] + stp xzr, xzr, [x0, #16] + # Set zero + stp xzr, xzr, [x29, #16] + stp xzr, xzr, [x29, #32] + # Set one + mov x2, #1 + stp x2, xzr, [x29, #48] + stp xzr, xzr, [x29, #64] + mov x25, #62 + mov x24, #24 +L_curve25519_words: +L_curve25519_bits: + ldr x2, [x1, x24] + lsr x2, x2, x25 + and x2, x2, #1 + eor x23, x23, x2 + # Conditional Swap + cmp x23, #1 + ldp x10, x11, [x0] + ldp x12, x13, [x0, #16] + ldp x6, x7, [x29, #80] + ldp x8, x9, [x29, #96] + csel x14, x10, x6, eq + csel x10, x6, x10, eq + csel x15, x11, x7, eq + csel x11, x7, x11, eq + csel x16, x12, x8, eq + csel x12, x8, x12, eq + csel x17, x13, x9, eq + csel x13, x9, x13, eq + # Conditional Swap + cmp x23, #1 + ldp x19, x20, [x29, #16] + ldp x21, x22, [x29, #32] + ldp x6, x7, [x29, #48] + ldp x8, x9, [x29, #64] + csel x5, x19, x6, eq + csel x19, x6, x19, eq + csel x26, x20, x7, eq + csel x20, x7, x20, eq + csel x27, x21, x8, eq + csel x21, x8, x21, eq + csel x28, x22, x9, eq + csel x22, x9, x22, eq + mov x23, x2 + # Add + adds x6, x10, x19 + adcs x7, x11, x20 + adcs x8, x12, x21 + adc x9, x13, x22 + mov x3, #-19 + asr x2, x9, #63 + # Mask the modulus + and x3, x2, x3 + and x4, x2, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x6, x6, x3 + sbcs x7, x7, x2 + sbcs x8, x8, x2 + sbc x9, x9, x4 + # Sub + subs x19, x10, x19 + sbcs x20, x11, x20 + sbcs x21, x12, x21 + sbcs x22, x13, x22 + mov x3, #-19 + csetm x2, cc + # Mask the modulus + and x3, x2, x3 + and x4, x2, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x19, x19, x3 + adcs x20, x20, x2 + adcs x21, x21, x2 + adc x22, x22, x4 + stp x19, x20, [x29, #144] + stp x21, x22, [x29, #160] + # Add + adds x10, x14, x5 + adcs x11, x15, x26 + adcs x12, x16, x27 + adc x13, x17, x28 + mov x3, #-19 + asr x2, x13, #63 + # Mask the modulus + and x3, x2, x3 + and x4, x2, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x10, x10, x3 + sbcs x11, x11, x2 + sbcs x12, x12, x2 + sbc x13, x13, x4 + # Sub + subs x14, x14, x5 + sbcs x15, x15, x26 + sbcs x16, x16, x27 + sbcs x17, x17, x28 + mov x3, #-19 + csetm x2, cc + # Mask the modulus + and x3, x2, x3 + and x4, x2, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x14, x14, x3 + adcs x15, x15, x2 + adcs x16, x16, x2 + adc x17, x17, x4 + # Multiply + # A[0] * B[0] + mul x19, x14, x6 + umulh x20, x14, x6 + # A[0] * B[1] + mul x3, x14, x7 + umulh x21, x14, x7 + adds x20, x20, x3 + adc x21, x21, xzr + # A[1] * B[0] + mul x3, x15, x6 + umulh x4, x15, x6 + adds x20, x20, x3 + adcs x21, x21, x4 + adc x22, xzr, xzr + # A[0] * B[2] + mul x3, x14, x8 + umulh x4, x14, x8 + adds x21, x21, x3 + adc x22, x22, x4 + # A[1] * B[1] + mul x3, x15, x7 + umulh x4, x15, x7 + adds x21, x21, x3 + adcs x22, x22, x4 + adc x2, xzr, xzr + # A[2] * B[0] + mul x3, x16, x6 + umulh x4, x16, x6 + adds x21, x21, x3 + adcs x22, x22, x4 + adc x2, x2, xzr + # A[0] * B[3] + mul x3, x14, x9 + umulh x4, x14, x9 + adds x22, x22, x3 + adcs x2, x2, x4 + adc x26, xzr, xzr + # A[1] * B[2] + mul x3, x15, x8 + umulh x4, x15, x8 + adds x22, x22, x3 + adcs x2, x2, x4 + adc x26, x26, xzr + # A[2] * B[1] + mul x3, x16, x7 + umulh x4, x16, x7 + adds x22, x22, x3 + adcs x2, x2, x4 + adc x26, x26, xzr + # A[3] * B[0] + mul x3, x17, x6 + umulh x4, x17, x6 + adds x22, x22, x3 + adcs x2, x2, x4 + adc x26, x26, xzr + # A[1] * B[3] + mul x3, x15, x9 + umulh x4, x15, x9 + adds x2, x2, x3 + adcs x26, x26, x4 + adc x27, xzr, xzr + # A[2] * B[2] + mul x3, x16, x8 + umulh x4, x16, x8 + adds x2, x2, x3 + adcs x26, x26, x4 + adc x27, x27, xzr + # A[3] * B[1] + mul x3, x17, x7 + umulh x4, x17, x7 + adds x2, x2, x3 + adcs x26, x26, x4 + adc x27, x27, xzr + # A[2] * B[3] + mul x3, x16, x9 + umulh x4, x16, x9 + adds x26, x26, x3 + adcs x27, x27, x4 + adc x28, xzr, xzr + # A[3] * B[2] + mul x3, x17, x8 + umulh x4, x17, x8 + adds x26, x26, x3 + adcs x27, x27, x4 + adc x28, x28, xzr + # A[3] * B[3] + mul x3, x17, x9 + umulh x4, x17, x9 + adds x27, x27, x3 + adc x28, x28, x4 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x28, x28, x27, #63 + extr x27, x27, x26, #63 + extr x26, x26, x2, #63 + extr x2, x2, x22, #63 + and x22, x22, #0x7fffffffffffffff + # Multiply top half by 19 + mov x3, #19 + mul x4, x3, x2 + umulh x2, x3, x2 + adds x19, x19, x4 + mul x4, x3, x26 + umulh x26, x3, x26 + adcs x20, x20, x4 + mul x4, x3, x27 + umulh x27, x3, x27 + adcs x21, x21, x4 + mul x4, x3, x28 + umulh x5, x3, x28 + adcs x22, x22, x4 + adc x5, x5, xzr + # Add remaining product results in + adds x20, x20, x2 + adcs x21, x21, x26 + adcs x22, x22, x27 + adc x5, x5, xzr + # Overflow + extr x5, x5, x22, #63 + mul x5, x5, x3 + and x22, x22, #0x7fffffffffffffff + adds x19, x19, x5 + adcs x20, x20, xzr + adcs x21, x21, xzr + adc x22, x22, xzr + # Reduce if top bit set + and x5, x3, x22, asr 63 + and x22, x22, #0x7fffffffffffffff + adds x19, x19, x5 + adcs x20, x20, xzr + adcs x21, x21, xzr + adc x22, x22, xzr + # Store + stp x19, x20, [x29, #112] + stp x21, x22, [x29, #128] + # Multiply + ldp x2, x26, [x29, #144] + ldp x27, x28, [x29, #160] + # A[0] * B[0] + mul x19, x10, x2 + umulh x20, x10, x2 + # A[0] * B[1] + mul x3, x10, x26 + umulh x21, x10, x26 + adds x20, x20, x3 + adc x21, x21, xzr + # A[1] * B[0] + mul x3, x11, x2 + umulh x4, x11, x2 + adds x20, x20, x3 + adcs x21, x21, x4 + adc x22, xzr, xzr + # A[0] * B[2] + mul x3, x10, x27 + umulh x4, x10, x27 + adds x21, x21, x3 + adc x22, x22, x4 + # A[1] * B[1] + mul x3, x11, x26 + umulh x4, x11, x26 + adds x21, x21, x3 + adcs x22, x22, x4 + adc x14, xzr, xzr + # A[2] * B[0] + mul x3, x12, x2 + umulh x4, x12, x2 + adds x21, x21, x3 + adcs x22, x22, x4 + adc x14, x14, xzr + # A[0] * B[3] + mul x3, x10, x28 + umulh x4, x10, x28 + adds x22, x22, x3 + adcs x14, x14, x4 + adc x15, xzr, xzr + # A[1] * B[2] + mul x3, x11, x27 + umulh x4, x11, x27 + adds x22, x22, x3 + adcs x14, x14, x4 + adc x15, x15, xzr + # A[2] * B[1] + mul x3, x12, x26 + umulh x4, x12, x26 + adds x22, x22, x3 + adcs x14, x14, x4 + adc x15, x15, xzr + # A[3] * B[0] + mul x3, x13, x2 + umulh x4, x13, x2 + adds x22, x22, x3 + adcs x14, x14, x4 + adc x15, x15, xzr + # A[1] * B[3] + mul x3, x11, x28 + umulh x4, x11, x28 + adds x14, x14, x3 + adcs x15, x15, x4 + adc x16, xzr, xzr + # A[2] * B[2] + mul x3, x12, x27 + umulh x4, x12, x27 + adds x14, x14, x3 + adcs x15, x15, x4 + adc x16, x16, xzr + # A[3] * B[1] + mul x3, x13, x26 + umulh x4, x13, x26 + adds x14, x14, x3 + adcs x15, x15, x4 + adc x16, x16, xzr + # A[2] * B[3] + mul x3, x12, x28 + umulh x4, x12, x28 + adds x15, x15, x3 + adcs x16, x16, x4 + adc x17, xzr, xzr + # A[3] * B[2] + mul x3, x13, x27 + umulh x4, x13, x27 + adds x15, x15, x3 + adcs x16, x16, x4 + adc x17, x17, xzr + # A[3] * B[3] + mul x3, x13, x28 + umulh x4, x13, x28 + adds x16, x16, x3 + adc x17, x17, x4 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x17, x17, x16, #63 + extr x16, x16, x15, #63 + extr x15, x15, x14, #63 + extr x14, x14, x22, #63 + and x22, x22, #0x7fffffffffffffff + # Multiply top half by 19 + mov x3, #19 + mul x4, x3, x14 + umulh x14, x3, x14 + adds x19, x19, x4 + mul x4, x3, x15 + umulh x15, x3, x15 + adcs x20, x20, x4 + mul x4, x3, x16 + umulh x16, x3, x16 + adcs x21, x21, x4 + mul x4, x3, x17 + umulh x5, x3, x17 + adcs x22, x22, x4 + adc x5, x5, xzr + # Add remaining product results in + adds x20, x20, x14 + adcs x21, x21, x15 + adcs x22, x22, x16 + adc x5, x5, xzr + # Overflow + extr x5, x5, x22, #63 + mul x5, x5, x3 + and x22, x22, #0x7fffffffffffffff + adds x19, x19, x5 + adcs x20, x20, xzr + adcs x21, x21, xzr + adc x22, x22, xzr + # Reduce if top bit set + and x5, x3, x22, asr 63 + and x22, x22, #0x7fffffffffffffff + adds x19, x19, x5 + adcs x20, x20, xzr + adcs x21, x21, xzr + adc x22, x22, xzr + # Store + # Square + # A[0] * A[1] + mul x11, x2, x26 + umulh x12, x2, x26 + # A[0] * A[2] + mul x3, x2, x27 + umulh x13, x2, x27 + adds x12, x12, x3 + adc x13, x13, xzr + # A[0] * A[3] + mul x3, x2, x28 + umulh x14, x2, x28 + adds x13, x13, x3 + adc x14, x14, xzr + # A[1] * A[2] + mul x3, x26, x27 + umulh x4, x26, x27 + adds x13, x13, x3 + adcs x14, x14, x4 + adc x15, xzr, xzr + # A[1] * A[3] + mul x3, x26, x28 + umulh x4, x26, x28 + adds x14, x14, x3 + adc x15, x15, x4 + # A[2] * A[3] + mul x3, x27, x28 + umulh x16, x27, x28 + adds x15, x15, x3 + adc x16, x16, xzr + # Double + adds x11, x11, x11 + adcs x12, x12, x12 + adcs x13, x13, x13 + adcs x14, x14, x14 + adcs x15, x15, x15 + adcs x16, x16, x16 + adc x17, xzr, xzr + # A[0] * A[0] + mul x10, x2, x2 + umulh x5, x2, x2 + # A[1] * A[1] + mul x3, x26, x26 + umulh x4, x26, x26 + adds x11, x11, x5 + adcs x12, x12, x3 + adc x5, x4, xzr + # A[2] * A[2] + mul x3, x27, x27 + umulh x4, x27, x27 + adds x13, x13, x5 + adcs x14, x14, x3 + adc x5, x4, xzr + # A[3] * A[3] + mul x3, x28, x28 + umulh x4, x28, x28 + adds x15, x15, x5 + adcs x16, x16, x3 + adc x17, x17, x4 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x17, x17, x16, #63 + extr x16, x16, x15, #63 + extr x15, x15, x14, #63 + extr x14, x14, x13, #63 + and x13, x13, #0x7fffffffffffffff + # Multiply top half by 19 + mov x3, #19 + mul x4, x3, x14 + umulh x14, x3, x14 + adds x10, x10, x4 + mul x4, x3, x15 + umulh x15, x3, x15 + adcs x11, x11, x4 + mul x4, x3, x16 + umulh x16, x3, x16 + adcs x12, x12, x4 + mul x4, x3, x17 + umulh x5, x3, x17 + adcs x13, x13, x4 + adc x5, x5, xzr + # Add remaining product results in + adds x11, x11, x14 + adcs x12, x12, x15 + adcs x13, x13, x16 + adc x5, x5, xzr + # Overflow + extr x5, x5, x13, #63 + mul x5, x5, x3 + and x13, x13, #0x7fffffffffffffff + adds x10, x10, x5 + adcs x11, x11, xzr + adcs x12, x12, xzr + adc x13, x13, xzr + # Reduce if top bit set + and x5, x3, x13, asr 63 + and x13, x13, #0x7fffffffffffffff + adds x10, x10, x5 + adcs x11, x11, xzr + adcs x12, x12, xzr + adc x13, x13, xzr + # Store + # Square + # A[0] * A[1] + mul x15, x6, x7 + umulh x16, x6, x7 + # A[0] * A[2] + mul x3, x6, x8 + umulh x17, x6, x8 + adds x16, x16, x3 + adc x17, x17, xzr + # A[0] * A[3] + mul x3, x6, x9 + umulh x2, x6, x9 + adds x17, x17, x3 + adc x2, x2, xzr + # A[1] * A[2] + mul x3, x7, x8 + umulh x4, x7, x8 + adds x17, x17, x3 + adcs x2, x2, x4 + adc x26, xzr, xzr + # A[1] * A[3] + mul x3, x7, x9 + umulh x4, x7, x9 + adds x2, x2, x3 + adc x26, x26, x4 + # A[2] * A[3] + mul x3, x8, x9 + umulh x27, x8, x9 + adds x26, x26, x3 + adc x27, x27, xzr + # Double + adds x15, x15, x15 + adcs x16, x16, x16 + adcs x17, x17, x17 + adcs x2, x2, x2 + adcs x26, x26, x26 + adcs x27, x27, x27 + adc x28, xzr, xzr + # A[0] * A[0] + mul x14, x6, x6 + umulh x5, x6, x6 + # A[1] * A[1] + mul x3, x7, x7 + umulh x4, x7, x7 + adds x15, x15, x5 + adcs x16, x16, x3 + adc x5, x4, xzr + # A[2] * A[2] + mul x3, x8, x8 + umulh x4, x8, x8 + adds x17, x17, x5 + adcs x2, x2, x3 + adc x5, x4, xzr + # A[3] * A[3] + mul x3, x9, x9 + umulh x4, x9, x9 + adds x26, x26, x5 + adcs x27, x27, x3 + adc x28, x28, x4 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x28, x28, x27, #63 + extr x27, x27, x26, #63 + extr x26, x26, x2, #63 + extr x2, x2, x17, #63 + and x17, x17, #0x7fffffffffffffff + # Multiply top half by 19 + mov x3, #19 + mul x4, x3, x2 + umulh x2, x3, x2 + adds x14, x14, x4 + mul x4, x3, x26 + umulh x26, x3, x26 + adcs x15, x15, x4 + mul x4, x3, x27 + umulh x27, x3, x27 + adcs x16, x16, x4 + mul x4, x3, x28 + umulh x5, x3, x28 + adcs x17, x17, x4 + adc x5, x5, xzr + # Add remaining product results in + adds x15, x15, x2 + adcs x16, x16, x26 + adcs x17, x17, x27 + adc x5, x5, xzr + # Overflow + extr x5, x5, x17, #63 + mul x5, x5, x3 + and x17, x17, #0x7fffffffffffffff + adds x14, x14, x5 + adcs x15, x15, xzr + adcs x16, x16, xzr + adc x17, x17, xzr + # Reduce if top bit set + and x5, x3, x17, asr 63 + and x17, x17, #0x7fffffffffffffff + adds x14, x14, x5 + adcs x15, x15, xzr + adcs x16, x16, xzr + adc x17, x17, xzr + # Store + # Multiply + # A[0] * B[0] + mul x6, x14, x10 + umulh x7, x14, x10 + # A[0] * B[1] + mul x3, x14, x11 + umulh x8, x14, x11 + adds x7, x7, x3 + adc x8, x8, xzr + # A[1] * B[0] + mul x3, x15, x10 + umulh x4, x15, x10 + adds x7, x7, x3 + adcs x8, x8, x4 + adc x9, xzr, xzr + # A[0] * B[2] + mul x3, x14, x12 + umulh x4, x14, x12 + adds x8, x8, x3 + adc x9, x9, x4 + # A[1] * B[1] + mul x3, x15, x11 + umulh x4, x15, x11 + adds x8, x8, x3 + adcs x9, x9, x4 + adc x2, xzr, xzr + # A[2] * B[0] + mul x3, x16, x10 + umulh x4, x16, x10 + adds x8, x8, x3 + adcs x9, x9, x4 + adc x2, x2, xzr + # A[0] * B[3] + mul x3, x14, x13 + umulh x4, x14, x13 + adds x9, x9, x3 + adcs x2, x2, x4 + adc x26, xzr, xzr + # A[1] * B[2] + mul x3, x15, x12 + umulh x4, x15, x12 + adds x9, x9, x3 + adcs x2, x2, x4 + adc x26, x26, xzr + # A[2] * B[1] + mul x3, x16, x11 + umulh x4, x16, x11 + adds x9, x9, x3 + adcs x2, x2, x4 + adc x26, x26, xzr + # A[3] * B[0] + mul x3, x17, x10 + umulh x4, x17, x10 + adds x9, x9, x3 + adcs x2, x2, x4 + adc x26, x26, xzr + # A[1] * B[3] + mul x3, x15, x13 + umulh x4, x15, x13 + adds x2, x2, x3 + adcs x26, x26, x4 + adc x27, xzr, xzr + # A[2] * B[2] + mul x3, x16, x12 + umulh x4, x16, x12 + adds x2, x2, x3 + adcs x26, x26, x4 + adc x27, x27, xzr + # A[3] * B[1] + mul x3, x17, x11 + umulh x4, x17, x11 + adds x2, x2, x3 + adcs x26, x26, x4 + adc x27, x27, xzr + # A[2] * B[3] + mul x3, x16, x13 + umulh x4, x16, x13 + adds x26, x26, x3 + adcs x27, x27, x4 + adc x28, xzr, xzr + # A[3] * B[2] + mul x3, x17, x12 + umulh x4, x17, x12 + adds x26, x26, x3 + adcs x27, x27, x4 + adc x28, x28, xzr + # A[3] * B[3] + mul x3, x17, x13 + umulh x4, x17, x13 + adds x27, x27, x3 + adc x28, x28, x4 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x28, x28, x27, #63 + extr x27, x27, x26, #63 + extr x26, x26, x2, #63 + extr x2, x2, x9, #63 + and x9, x9, #0x7fffffffffffffff + # Multiply top half by 19 + mov x3, #19 + mul x4, x3, x2 + umulh x2, x3, x2 + adds x6, x6, x4 + mul x4, x3, x26 + umulh x26, x3, x26 + adcs x7, x7, x4 + mul x4, x3, x27 + umulh x27, x3, x27 + adcs x8, x8, x4 + mul x4, x3, x28 + umulh x5, x3, x28 + adcs x9, x9, x4 + adc x5, x5, xzr + # Add remaining product results in + adds x7, x7, x2 + adcs x8, x8, x26 + adcs x9, x9, x27 + adc x5, x5, xzr + # Overflow + extr x5, x5, x9, #63 + mul x5, x5, x3 + and x9, x9, #0x7fffffffffffffff + adds x6, x6, x5 + adcs x7, x7, xzr + adcs x8, x8, xzr + adc x9, x9, xzr + # Reduce if top bit set + and x5, x3, x9, asr 63 + and x9, x9, #0x7fffffffffffffff + adds x6, x6, x5 + adcs x7, x7, xzr + adcs x8, x8, xzr + adc x9, x9, xzr + # Store + stp x6, x7, [x0] + stp x8, x9, [x0, #16] + # Sub + subs x14, x14, x10 + sbcs x15, x15, x11 + sbcs x16, x16, x12 + sbcs x17, x17, x13 + mov x3, #-19 + csetm x2, cc + # Mask the modulus + and x3, x2, x3 + and x4, x2, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x14, x14, x3 + adcs x15, x15, x2 + adcs x16, x16, x2 + adc x17, x17, x4 + # Multiply by 121666 + mov x5, #0xdb42 + movk x5, #1, lsl 16 + mul x6, x14, x5 + umulh x7, x14, x5 + mul x3, x15, x5 + umulh x4, x15, x5 + adds x7, x7, x3 + adc x8, xzr, x4 + mul x3, x16, x5 + umulh x4, x16, x5 + adds x8, x8, x3 + adc x9, xzr, x4 + mul x3, x17, x5 + umulh x4, x17, x5 + adds x9, x9, x3 + adc x4, xzr, x4 + mov x5, #19 + extr x4, x4, x9, #63 + mul x4, x4, x5 + and x9, x9, #0x7fffffffffffffff + adds x6, x6, x4 + adcs x7, x7, xzr + adcs x8, x8, xzr + adc x9, x9, xzr + # Add + adds x10, x10, x6 + adcs x11, x11, x7 + adcs x12, x12, x8 + adc x13, x13, x9 + mov x3, #-19 + asr x2, x13, #63 + # Mask the modulus + and x3, x2, x3 + and x4, x2, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x10, x10, x3 + sbcs x11, x11, x2 + sbcs x12, x12, x2 + sbc x13, x13, x4 + # Multiply + # A[0] * B[0] + mul x6, x14, x10 + umulh x7, x14, x10 + # A[0] * B[1] + mul x3, x14, x11 + umulh x8, x14, x11 + adds x7, x7, x3 + adc x8, x8, xzr + # A[1] * B[0] + mul x3, x15, x10 + umulh x4, x15, x10 + adds x7, x7, x3 + adcs x8, x8, x4 + adc x9, xzr, xzr + # A[0] * B[2] + mul x3, x14, x12 + umulh x4, x14, x12 + adds x8, x8, x3 + adc x9, x9, x4 + # A[1] * B[1] + mul x3, x15, x11 + umulh x4, x15, x11 + adds x8, x8, x3 + adcs x9, x9, x4 + adc x2, xzr, xzr + # A[2] * B[0] + mul x3, x16, x10 + umulh x4, x16, x10 + adds x8, x8, x3 + adcs x9, x9, x4 + adc x2, x2, xzr + # A[0] * B[3] + mul x3, x14, x13 + umulh x4, x14, x13 + adds x9, x9, x3 + adcs x2, x2, x4 + adc x26, xzr, xzr + # A[1] * B[2] + mul x3, x15, x12 + umulh x4, x15, x12 + adds x9, x9, x3 + adcs x2, x2, x4 + adc x26, x26, xzr + # A[2] * B[1] + mul x3, x16, x11 + umulh x4, x16, x11 + adds x9, x9, x3 + adcs x2, x2, x4 + adc x26, x26, xzr + # A[3] * B[0] + mul x3, x17, x10 + umulh x4, x17, x10 + adds x9, x9, x3 + adcs x2, x2, x4 + adc x26, x26, xzr + # A[1] * B[3] + mul x3, x15, x13 + umulh x4, x15, x13 + adds x2, x2, x3 + adcs x26, x26, x4 + adc x27, xzr, xzr + # A[2] * B[2] + mul x3, x16, x12 + umulh x4, x16, x12 + adds x2, x2, x3 + adcs x26, x26, x4 + adc x27, x27, xzr + # A[3] * B[1] + mul x3, x17, x11 + umulh x4, x17, x11 + adds x2, x2, x3 + adcs x26, x26, x4 + adc x27, x27, xzr + # A[2] * B[3] + mul x3, x16, x13 + umulh x4, x16, x13 + adds x26, x26, x3 + adcs x27, x27, x4 + adc x28, xzr, xzr + # A[3] * B[2] + mul x3, x17, x12 + umulh x4, x17, x12 + adds x26, x26, x3 + adcs x27, x27, x4 + adc x28, x28, xzr + # A[3] * B[3] + mul x3, x17, x13 + umulh x4, x17, x13 + adds x27, x27, x3 + adc x28, x28, x4 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x28, x28, x27, #63 + extr x27, x27, x26, #63 + extr x26, x26, x2, #63 + extr x2, x2, x9, #63 + and x9, x9, #0x7fffffffffffffff + # Multiply top half by 19 + mov x3, #19 + mul x4, x3, x2 + umulh x2, x3, x2 + adds x6, x6, x4 + mul x4, x3, x26 + umulh x26, x3, x26 + adcs x7, x7, x4 + mul x4, x3, x27 + umulh x27, x3, x27 + adcs x8, x8, x4 + mul x4, x3, x28 + umulh x5, x3, x28 + adcs x9, x9, x4 + adc x5, x5, xzr + # Add remaining product results in + adds x7, x7, x2 + adcs x8, x8, x26 + adcs x9, x9, x27 + adc x5, x5, xzr + # Overflow + extr x5, x5, x9, #63 + mul x5, x5, x3 + and x9, x9, #0x7fffffffffffffff + adds x6, x6, x5 + adcs x7, x7, xzr + adcs x8, x8, xzr + adc x9, x9, xzr + # Reduce if top bit set + and x5, x3, x9, asr 63 + and x9, x9, #0x7fffffffffffffff + adds x6, x6, x5 + adcs x7, x7, xzr + adcs x8, x8, xzr + adc x9, x9, xzr + # Store + stp x6, x7, [x29, #16] + stp x8, x9, [x29, #32] + # Add + ldp x6, x7, [x29, #112] + ldp x8, x9, [x29, #128] + adds x10, x6, x19 + adcs x11, x7, x20 + adcs x12, x8, x21 + adc x13, x9, x22 + mov x3, #-19 + asr x2, x13, #63 + # Mask the modulus + and x3, x2, x3 + and x4, x2, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x10, x10, x3 + sbcs x11, x11, x2 + sbcs x12, x12, x2 + sbc x13, x13, x4 + # Sub + subs x19, x6, x19 + sbcs x20, x7, x20 + sbcs x21, x8, x21 + sbcs x22, x9, x22 + mov x3, #-19 + csetm x2, cc + # Mask the modulus + and x3, x2, x3 + and x4, x2, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x19, x19, x3 + adcs x20, x20, x2 + adcs x21, x21, x2 + adc x22, x22, x4 + # Square + # A[0] * A[1] + mul x7, x10, x11 + umulh x8, x10, x11 + # A[0] * A[2] + mul x3, x10, x12 + umulh x9, x10, x12 + adds x8, x8, x3 + adc x9, x9, xzr + # A[0] * A[3] + mul x3, x10, x13 + umulh x2, x10, x13 + adds x9, x9, x3 + adc x2, x2, xzr + # A[1] * A[2] + mul x3, x11, x12 + umulh x4, x11, x12 + adds x9, x9, x3 + adcs x2, x2, x4 + adc x26, xzr, xzr + # A[1] * A[3] + mul x3, x11, x13 + umulh x4, x11, x13 + adds x2, x2, x3 + adc x26, x26, x4 + # A[2] * A[3] + mul x3, x12, x13 + umulh x27, x12, x13 + adds x26, x26, x3 + adc x27, x27, xzr + # Double + adds x7, x7, x7 + adcs x8, x8, x8 + adcs x9, x9, x9 + adcs x2, x2, x2 + adcs x26, x26, x26 + adcs x27, x27, x27 + adc x28, xzr, xzr + # A[0] * A[0] + mul x6, x10, x10 + umulh x5, x10, x10 + # A[1] * A[1] + mul x3, x11, x11 + umulh x4, x11, x11 + adds x7, x7, x5 + adcs x8, x8, x3 + adc x5, x4, xzr + # A[2] * A[2] + mul x3, x12, x12 + umulh x4, x12, x12 + adds x9, x9, x5 + adcs x2, x2, x3 + adc x5, x4, xzr + # A[3] * A[3] + mul x3, x13, x13 + umulh x4, x13, x13 + adds x26, x26, x5 + adcs x27, x27, x3 + adc x28, x28, x4 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x28, x28, x27, #63 + extr x27, x27, x26, #63 + extr x26, x26, x2, #63 + extr x2, x2, x9, #63 + and x9, x9, #0x7fffffffffffffff + # Multiply top half by 19 + mov x3, #19 + mul x4, x3, x2 + umulh x2, x3, x2 + adds x6, x6, x4 + mul x4, x3, x26 + umulh x26, x3, x26 + adcs x7, x7, x4 + mul x4, x3, x27 + umulh x27, x3, x27 + adcs x8, x8, x4 + mul x4, x3, x28 + umulh x5, x3, x28 + adcs x9, x9, x4 + adc x5, x5, xzr + # Add remaining product results in + adds x7, x7, x2 + adcs x8, x8, x26 + adcs x9, x9, x27 + adc x5, x5, xzr + # Overflow + extr x5, x5, x9, #63 + mul x5, x5, x3 + and x9, x9, #0x7fffffffffffffff + adds x6, x6, x5 + adcs x7, x7, xzr + adcs x8, x8, xzr + adc x9, x9, xzr + # Reduce if top bit set + and x5, x3, x9, asr 63 + and x9, x9, #0x7fffffffffffffff + adds x6, x6, x5 + adcs x7, x7, xzr + adcs x8, x8, xzr + adc x9, x9, xzr + # Store + stp x6, x7, [x29, #80] + stp x8, x9, [x29, #96] + # Square + # A[0] * A[1] + mul x7, x19, x20 + umulh x8, x19, x20 + # A[0] * A[2] + mul x3, x19, x21 + umulh x9, x19, x21 + adds x8, x8, x3 + adc x9, x9, xzr + # A[0] * A[3] + mul x3, x19, x22 + umulh x2, x19, x22 + adds x9, x9, x3 + adc x2, x2, xzr + # A[1] * A[2] + mul x3, x20, x21 + umulh x4, x20, x21 + adds x9, x9, x3 + adcs x2, x2, x4 + adc x26, xzr, xzr + # A[1] * A[3] + mul x3, x20, x22 + umulh x4, x20, x22 + adds x2, x2, x3 + adc x26, x26, x4 + # A[2] * A[3] + mul x3, x21, x22 + umulh x27, x21, x22 + adds x26, x26, x3 + adc x27, x27, xzr + # Double + adds x7, x7, x7 + adcs x8, x8, x8 + adcs x9, x9, x9 + adcs x2, x2, x2 + adcs x26, x26, x26 + adcs x27, x27, x27 + adc x28, xzr, xzr + # A[0] * A[0] + mul x6, x19, x19 + umulh x5, x19, x19 + # A[1] * A[1] + mul x3, x20, x20 + umulh x4, x20, x20 + adds x7, x7, x5 + adcs x8, x8, x3 + adc x5, x4, xzr + # A[2] * A[2] + mul x3, x21, x21 + umulh x4, x21, x21 + adds x9, x9, x5 + adcs x2, x2, x3 + adc x5, x4, xzr + # A[3] * A[3] + mul x3, x22, x22 + umulh x4, x22, x22 + adds x26, x26, x5 + adcs x27, x27, x3 + adc x28, x28, x4 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x28, x28, x27, #63 + extr x27, x27, x26, #63 + extr x26, x26, x2, #63 + extr x2, x2, x9, #63 + and x9, x9, #0x7fffffffffffffff + # Multiply top half by 19 + mov x3, #19 + mul x4, x3, x2 + umulh x2, x3, x2 + adds x6, x6, x4 + mul x4, x3, x26 + umulh x26, x3, x26 + adcs x7, x7, x4 + mul x4, x3, x27 + umulh x27, x3, x27 + adcs x8, x8, x4 + mul x4, x3, x28 + umulh x5, x3, x28 + adcs x9, x9, x4 + adc x5, x5, xzr + # Add remaining product results in + adds x7, x7, x2 + adcs x8, x8, x26 + adcs x9, x9, x27 + adc x5, x5, xzr + # Overflow + extr x5, x5, x9, #63 + mul x5, x5, x3 + and x9, x9, #0x7fffffffffffffff + adds x6, x6, x5 + adcs x7, x7, xzr + adcs x8, x8, xzr + adc x9, x9, xzr + # Reduce if top bit set + and x5, x3, x9, asr 63 + and x9, x9, #0x7fffffffffffffff + adds x6, x6, x5 + adcs x7, x7, xzr + adcs x8, x8, xzr + adc x9, x9, xzr + # Store + ldr x2, [x29, #184] + # Multiply + ldp x14, x15, [x2] + ldp x16, x17, [x2, #16] + # A[0] * B[0] + mul x10, x14, x6 + umulh x11, x14, x6 + # A[0] * B[1] + mul x3, x14, x7 + umulh x12, x14, x7 + adds x11, x11, x3 + adc x12, x12, xzr + # A[1] * B[0] + mul x3, x15, x6 + umulh x4, x15, x6 + adds x11, x11, x3 + adcs x12, x12, x4 + adc x13, xzr, xzr + # A[0] * B[2] + mul x3, x14, x8 + umulh x4, x14, x8 + adds x12, x12, x3 + adc x13, x13, x4 + # A[1] * B[1] + mul x3, x15, x7 + umulh x4, x15, x7 + adds x12, x12, x3 + adcs x13, x13, x4 + adc x2, xzr, xzr + # A[2] * B[0] + mul x3, x16, x6 + umulh x4, x16, x6 + adds x12, x12, x3 + adcs x13, x13, x4 + adc x2, x2, xzr + # A[0] * B[3] + mul x3, x14, x9 + umulh x4, x14, x9 + adds x13, x13, x3 + adcs x2, x2, x4 + adc x26, xzr, xzr + # A[1] * B[2] + mul x3, x15, x8 + umulh x4, x15, x8 + adds x13, x13, x3 + adcs x2, x2, x4 + adc x26, x26, xzr + # A[2] * B[1] + mul x3, x16, x7 + umulh x4, x16, x7 + adds x13, x13, x3 + adcs x2, x2, x4 + adc x26, x26, xzr + # A[3] * B[0] + mul x3, x17, x6 + umulh x4, x17, x6 + adds x13, x13, x3 + adcs x2, x2, x4 + adc x26, x26, xzr + # A[1] * B[3] + mul x3, x15, x9 + umulh x4, x15, x9 + adds x2, x2, x3 + adcs x26, x26, x4 + adc x27, xzr, xzr + # A[2] * B[2] + mul x3, x16, x8 + umulh x4, x16, x8 + adds x2, x2, x3 + adcs x26, x26, x4 + adc x27, x27, xzr + # A[3] * B[1] + mul x3, x17, x7 + umulh x4, x17, x7 + adds x2, x2, x3 + adcs x26, x26, x4 + adc x27, x27, xzr + # A[2] * B[3] + mul x3, x16, x9 + umulh x4, x16, x9 + adds x26, x26, x3 + adcs x27, x27, x4 + adc x28, xzr, xzr + # A[3] * B[2] + mul x3, x17, x8 + umulh x4, x17, x8 + adds x26, x26, x3 + adcs x27, x27, x4 + adc x28, x28, xzr + # A[3] * B[3] + mul x3, x17, x9 + umulh x4, x17, x9 + adds x27, x27, x3 + adc x28, x28, x4 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x28, x28, x27, #63 + extr x27, x27, x26, #63 + extr x26, x26, x2, #63 + extr x2, x2, x13, #63 + and x13, x13, #0x7fffffffffffffff + # Multiply top half by 19 + mov x3, #19 + mul x4, x3, x2 + umulh x2, x3, x2 + adds x10, x10, x4 + mul x4, x3, x26 + umulh x26, x3, x26 + adcs x11, x11, x4 + mul x4, x3, x27 + umulh x27, x3, x27 + adcs x12, x12, x4 + mul x4, x3, x28 + umulh x5, x3, x28 + adcs x13, x13, x4 + adc x5, x5, xzr + # Add remaining product results in + adds x11, x11, x2 + adcs x12, x12, x26 + adcs x13, x13, x27 + adc x5, x5, xzr + # Overflow + extr x5, x5, x13, #63 + mul x5, x5, x3 + and x13, x13, #0x7fffffffffffffff + adds x10, x10, x5 + adcs x11, x11, xzr + adcs x12, x12, xzr + adc x13, x13, xzr + # Reduce if top bit set + and x5, x3, x13, asr 63 + and x13, x13, #0x7fffffffffffffff + adds x10, x10, x5 + adcs x11, x11, xzr + adcs x12, x12, xzr + adc x13, x13, xzr + # Store + stp x10, x11, [x29, #48] + stp x12, x13, [x29, #64] + sub x25, x25, #1 + cmp x25, #0 + bge L_curve25519_bits + mov x25, #63 + sub x24, x24, #8 + cmp x24, #0 + bge L_curve25519_words + # Invert + add x0, x29, #48 + add x1, x29, #16 + bl fe_sq + add x0, x29, #0x50 + add x1, x29, #48 + bl fe_sq + add x1, x29, #0x50 + bl fe_sq + add x1, x29, #16 + add x2, x29, #0x50 + bl fe_mul + add x0, x29, #48 + add x1, x29, #48 + add x2, x29, #0x50 + bl fe_mul + add x0, x29, #0x70 + bl fe_sq + add x0, x29, #0x50 + add x1, x29, #0x50 + add x2, x29, #0x70 + bl fe_mul + add x0, x29, #0x70 + bl fe_sq + mov x24, #4 + add x1, x29, #0x70 +L_curve25519_inv_1: + bl fe_sq + sub x24, x24, #1 + cmp x24, #0 + bne L_curve25519_inv_1 + add x0, x29, #0x50 + add x2, x29, #0x50 + bl fe_mul + add x0, x29, #0x70 + add x1, x29, #0x50 + bl fe_sq + mov x24, #9 + add x1, x29, #0x70 +L_curve25519_inv_2: + bl fe_sq + sub x24, x24, #1 + cmp x24, #0 + bne L_curve25519_inv_2 + add x2, x29, #0x50 + bl fe_mul + add x0, x29, #0x90 + bl fe_sq + mov x24, #19 + add x1, x29, #0x90 +L_curve25519_inv_3: + bl fe_sq + sub x24, x24, #1 + cmp x24, #0 + bne L_curve25519_inv_3 + add x0, x29, #0x70 + add x2, x29, #0x70 + bl fe_mul + mov x24, #10 + add x1, x29, #0x70 +L_curve25519_inv_4: + bl fe_sq + sub x24, x24, #1 + cmp x24, #0 + bne L_curve25519_inv_4 + add x0, x29, #0x50 + add x2, x29, #0x50 + bl fe_mul + add x0, x29, #0x70 + add x1, x29, #0x50 + bl fe_sq + mov x24, #49 + add x1, x29, #0x70 +L_curve25519_inv_5: + bl fe_sq + sub x24, x24, #1 + cmp x24, #0 + bne L_curve25519_inv_5 + add x2, x29, #0x50 + bl fe_mul + add x0, x29, #0x90 + bl fe_sq + mov x24, #0x63 + add x1, x29, #0x90 +L_curve25519_inv_6: + bl fe_sq + sub x24, x24, #1 + cmp x24, #0 + bne L_curve25519_inv_6 + add x0, x29, #0x70 + add x2, x29, #0x70 + bl fe_mul + mov x24, #50 + add x1, x29, #0x70 +L_curve25519_inv_7: + bl fe_sq + sub x24, x24, #1 + cmp x24, #0 + bne L_curve25519_inv_7 + add x0, x29, #0x50 + add x2, x29, #0x50 + bl fe_mul + mov x24, #5 + add x1, x29, #0x50 +L_curve25519_inv_8: + bl fe_sq + sub x24, x24, #1 + cmp x24, #0 + bne L_curve25519_inv_8 + add x0, x29, #16 + add x2, x29, #48 + bl fe_mul + ldr x0, [x29, #176] + # Multiply + ldp x6, x7, [x0] + ldp x8, x9, [x0, #16] + ldp x10, x11, [x29, #16] + ldp x12, x13, [x29, #32] + # A[0] * B[0] + mul x14, x6, x10 + umulh x15, x6, x10 + # A[0] * B[1] + mul x3, x6, x11 + umulh x16, x6, x11 + adds x15, x15, x3 + adc x16, x16, xzr + # A[1] * B[0] + mul x3, x7, x10 + umulh x4, x7, x10 + adds x15, x15, x3 + adcs x16, x16, x4 + adc x17, xzr, xzr + # A[0] * B[2] + mul x3, x6, x12 + umulh x4, x6, x12 + adds x16, x16, x3 + adc x17, x17, x4 + # A[1] * B[1] + mul x3, x7, x11 + umulh x4, x7, x11 + adds x16, x16, x3 + adcs x17, x17, x4 + adc x19, xzr, xzr + # A[2] * B[0] + mul x3, x8, x10 + umulh x4, x8, x10 + adds x16, x16, x3 + adcs x17, x17, x4 + adc x19, x19, xzr + # A[0] * B[3] + mul x3, x6, x13 + umulh x4, x6, x13 + adds x17, x17, x3 + adcs x19, x19, x4 + adc x20, xzr, xzr + # A[1] * B[2] + mul x3, x7, x12 + umulh x4, x7, x12 + adds x17, x17, x3 + adcs x19, x19, x4 + adc x20, x20, xzr + # A[2] * B[1] + mul x3, x8, x11 + umulh x4, x8, x11 + adds x17, x17, x3 + adcs x19, x19, x4 + adc x20, x20, xzr + # A[3] * B[0] + mul x3, x9, x10 + umulh x4, x9, x10 + adds x17, x17, x3 + adcs x19, x19, x4 + adc x20, x20, xzr + # A[1] * B[3] + mul x3, x7, x13 + umulh x4, x7, x13 + adds x19, x19, x3 + adcs x20, x20, x4 + adc x21, xzr, xzr + # A[2] * B[2] + mul x3, x8, x12 + umulh x4, x8, x12 + adds x19, x19, x3 + adcs x20, x20, x4 + adc x21, x21, xzr + # A[3] * B[1] + mul x3, x9, x11 + umulh x4, x9, x11 + adds x19, x19, x3 + adcs x20, x20, x4 + adc x21, x21, xzr + # A[2] * B[3] + mul x3, x8, x13 + umulh x4, x8, x13 + adds x20, x20, x3 + adcs x21, x21, x4 + adc x22, xzr, xzr + # A[3] * B[2] + mul x3, x9, x12 + umulh x4, x9, x12 + adds x20, x20, x3 + adcs x21, x21, x4 + adc x22, x22, xzr + # A[3] * B[3] + mul x3, x9, x13 + umulh x4, x9, x13 + adds x21, x21, x3 + adc x22, x22, x4 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x22, x22, x21, #63 + extr x21, x21, x20, #63 + extr x20, x20, x19, #63 + extr x19, x19, x17, #63 + and x17, x17, #0x7fffffffffffffff + # Multiply top half by 19 + mov x3, #19 + mul x4, x3, x19 + umulh x19, x3, x19 + adds x14, x14, x4 + mul x4, x3, x20 + umulh x20, x3, x20 + adcs x15, x15, x4 + mul x4, x3, x21 + umulh x21, x3, x21 + adcs x16, x16, x4 + mul x4, x3, x22 + umulh x5, x3, x22 + adcs x17, x17, x4 + adc x5, x5, xzr + # Add remaining product results in + adds x15, x15, x19 + adcs x16, x16, x20 + adcs x17, x17, x21 + adc x5, x5, xzr + # Overflow + extr x5, x5, x17, #63 + mul x5, x5, x3 + and x17, x17, #0x7fffffffffffffff + adds x14, x14, x5 + adcs x15, x15, xzr + adcs x16, x16, xzr + adc x17, x17, xzr + # Reduce if top bit set + and x5, x3, x17, asr 63 + and x17, x17, #0x7fffffffffffffff + adds x14, x14, x5 + adcs x15, x15, xzr + adcs x16, x16, xzr + adc x17, x17, xzr + # Store + stp x14, x15, [x0] + stp x16, x17, [x0, #16] + mov x0, xzr + ldr x17, [x29, #200] + ldr x19, [x29, #208] + ldp x20, x21, [x29, #216] + ldp x22, x23, [x29, #232] + ldp x24, x25, [x29, #248] + ldp x26, x27, [x29, #264] + ldr x28, [x29, #280] + ldp x29, x30, [sp], #0x120 + ret + .size curve25519,.-curve25519 + .text + .align 2 + .globl fe_pow22523 + .type fe_pow22523, %function +fe_pow22523: + stp x29, x30, [sp, #-144]! + add x29, sp, #0 + str x21, [x29, #136] + # pow22523 + str x0, [x29, #112] + str x1, [x29, #120] + add x0, x29, #16 + bl fe_sq + add x0, x29, #48 + add x1, x29, #16 + bl fe_sq + add x1, x29, #48 + bl fe_sq + ldr x1, [x29, #120] + add x2, x29, #48 + bl fe_mul + add x0, x29, #16 + add x1, x29, #16 + add x2, x29, #48 + bl fe_mul + bl fe_sq + add x1, x29, #48 + add x2, x29, #16 + bl fe_mul + add x0, x29, #48 + add x1, x29, #16 + bl fe_sq + mov x21, #4 + add x1, x29, #48 +L_fe_pow22523_1: + bl fe_sq + sub x21, x21, #1 + cmp x21, #0 + bne L_fe_pow22523_1 + add x0, x29, #16 + add x2, x29, #16 + bl fe_mul + add x0, x29, #48 + add x1, x29, #16 + bl fe_sq + mov x21, #9 + add x1, x29, #48 +L_fe_pow22523_2: + bl fe_sq + sub x21, x21, #1 + cmp x21, #0 + bne L_fe_pow22523_2 + add x2, x29, #16 + bl fe_mul + add x0, x29, #0x50 + bl fe_sq + mov x21, #19 + add x1, x29, #0x50 +L_fe_pow22523_3: + bl fe_sq + sub x21, x21, #1 + cmp x21, #0 + bne L_fe_pow22523_3 + add x0, x29, #48 + add x2, x29, #48 + bl fe_mul + mov x21, #10 + add x1, x29, #48 +L_fe_pow22523_4: + bl fe_sq + sub x21, x21, #1 + cmp x21, #0 + bne L_fe_pow22523_4 + add x0, x29, #16 + add x2, x29, #16 + bl fe_mul + add x0, x29, #48 + add x1, x29, #16 + bl fe_sq + mov x21, #49 + add x1, x29, #48 +L_fe_pow22523_5: + bl fe_sq + sub x21, x21, #1 + cmp x21, #0 + bne L_fe_pow22523_5 + add x2, x29, #16 + bl fe_mul + add x0, x29, #0x50 + bl fe_sq + mov x21, #0x63 + add x1, x29, #0x50 +L_fe_pow22523_6: + bl fe_sq + sub x21, x21, #1 + cmp x21, #0 + bne L_fe_pow22523_6 + add x0, x29, #48 + add x2, x29, #48 + bl fe_mul + mov x21, #50 + add x1, x29, #48 +L_fe_pow22523_7: + bl fe_sq + sub x21, x21, #1 + cmp x21, #0 + bne L_fe_pow22523_7 + add x0, x29, #16 + add x2, x29, #16 + bl fe_mul + mov x21, #2 + add x1, x29, #16 +L_fe_pow22523_8: + bl fe_sq + sub x21, x21, #1 + cmp x21, #0 + bne L_fe_pow22523_8 + ldr x0, [x29, #112] + ldr x2, [x29, #120] + bl fe_mul + ldr x21, [x29, #136] + ldp x29, x30, [sp], #0x90 + ret + .size fe_pow22523,.-fe_pow22523 + .text + .align 2 + .globl fe_ge_to_p2 + .type fe_ge_to_p2, %function +fe_ge_to_p2: + stp x29, x30, [sp, #-112]! + add x29, sp, #0 + str x17, [x29, #72] + str x19, [x29, #80] + stp x20, x21, [x29, #88] + str x22, [x29, #104] + str x1, [x29, #16] + str x2, [x29, #24] + str x3, [x29, #32] + str x4, [x29, #40] + str x5, [x29, #48] + str x6, [x29, #56] + ldr x1, [x29, #32] + ldr x2, [x29, #56] + # Multiply + ldp x11, x12, [x1] + ldp x13, x14, [x1, #16] + ldp x15, x16, [x2] + ldp x17, x19, [x2, #16] + # A[0] * B[0] + mul x3, x11, x15 + umulh x4, x11, x15 + # A[0] * B[1] + mul x20, x11, x16 + umulh x5, x11, x16 + adds x4, x4, x20 + adc x5, x5, xzr + # A[1] * B[0] + mul x20, x12, x15 + umulh x21, x12, x15 + adds x4, x4, x20 + adcs x5, x5, x21 + adc x6, xzr, xzr + # A[0] * B[2] + mul x20, x11, x17 + umulh x21, x11, x17 + adds x5, x5, x20 + adc x6, x6, x21 + # A[1] * B[1] + mul x20, x12, x16 + umulh x21, x12, x16 + adds x5, x5, x20 + adcs x6, x6, x21 + adc x7, xzr, xzr + # A[2] * B[0] + mul x20, x13, x15 + umulh x21, x13, x15 + adds x5, x5, x20 + adcs x6, x6, x21 + adc x7, x7, xzr + # A[0] * B[3] + mul x20, x11, x19 + umulh x21, x11, x19 + adds x6, x6, x20 + adcs x7, x7, x21 + adc x8, xzr, xzr + # A[1] * B[2] + mul x20, x12, x17 + umulh x21, x12, x17 + adds x6, x6, x20 + adcs x7, x7, x21 + adc x8, x8, xzr + # A[2] * B[1] + mul x20, x13, x16 + umulh x21, x13, x16 + adds x6, x6, x20 + adcs x7, x7, x21 + adc x8, x8, xzr + # A[3] * B[0] + mul x20, x14, x15 + umulh x21, x14, x15 + adds x6, x6, x20 + adcs x7, x7, x21 + adc x8, x8, xzr + # A[1] * B[3] + mul x20, x12, x19 + umulh x21, x12, x19 + adds x7, x7, x20 + adcs x8, x8, x21 + adc x9, xzr, xzr + # A[2] * B[2] + mul x20, x13, x17 + umulh x21, x13, x17 + adds x7, x7, x20 + adcs x8, x8, x21 + adc x9, x9, xzr + # A[3] * B[1] + mul x20, x14, x16 + umulh x21, x14, x16 + adds x7, x7, x20 + adcs x8, x8, x21 + adc x9, x9, xzr + # A[2] * B[3] + mul x20, x13, x19 + umulh x21, x13, x19 + adds x8, x8, x20 + adcs x9, x9, x21 + adc x10, xzr, xzr + # A[3] * B[2] + mul x20, x14, x17 + umulh x21, x14, x17 + adds x8, x8, x20 + adcs x9, x9, x21 + adc x10, x10, xzr + # A[3] * B[3] + mul x20, x14, x19 + umulh x21, x14, x19 + adds x9, x9, x20 + adc x10, x10, x21 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + extr x8, x8, x7, #63 + extr x7, x7, x6, #63 + and x6, x6, #0x7fffffffffffffff + # Multiply top half by 19 + mov x20, #19 + mul x21, x20, x7 + umulh x7, x20, x7 + adds x3, x3, x21 + mul x21, x20, x8 + umulh x8, x20, x8 + adcs x4, x4, x21 + mul x21, x20, x9 + umulh x9, x20, x9 + adcs x5, x5, x21 + mul x21, x20, x10 + umulh x22, x20, x10 + adcs x6, x6, x21 + adc x22, x22, xzr + # Add remaining product results in + adds x4, x4, x7 + adcs x5, x5, x8 + adcs x6, x6, x9 + adc x22, x22, xzr + # Overflow + extr x22, x22, x6, #63 + mul x22, x22, x20 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x22 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Reduce if top bit set + and x22, x20, x6, asr 63 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x22 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Store + stp x3, x4, [x0] + stp x5, x6, [x0, #16] + ldr x0, [x29, #16] + ldr x1, [x29, #40] + ldr x2, [x29, #48] + # Multiply + ldp x11, x12, [x1] + ldp x13, x14, [x1, #16] + ldp x15, x16, [x2] + ldp x17, x19, [x2, #16] + # A[0] * B[0] + mul x3, x11, x15 + umulh x4, x11, x15 + # A[0] * B[1] + mul x20, x11, x16 + umulh x5, x11, x16 + adds x4, x4, x20 + adc x5, x5, xzr + # A[1] * B[0] + mul x20, x12, x15 + umulh x21, x12, x15 + adds x4, x4, x20 + adcs x5, x5, x21 + adc x6, xzr, xzr + # A[0] * B[2] + mul x20, x11, x17 + umulh x21, x11, x17 + adds x5, x5, x20 + adc x6, x6, x21 + # A[1] * B[1] + mul x20, x12, x16 + umulh x21, x12, x16 + adds x5, x5, x20 + adcs x6, x6, x21 + adc x7, xzr, xzr + # A[2] * B[0] + mul x20, x13, x15 + umulh x21, x13, x15 + adds x5, x5, x20 + adcs x6, x6, x21 + adc x7, x7, xzr + # A[0] * B[3] + mul x20, x11, x19 + umulh x21, x11, x19 + adds x6, x6, x20 + adcs x7, x7, x21 + adc x8, xzr, xzr + # A[1] * B[2] + mul x20, x12, x17 + umulh x21, x12, x17 + adds x6, x6, x20 + adcs x7, x7, x21 + adc x8, x8, xzr + # A[2] * B[1] + mul x20, x13, x16 + umulh x21, x13, x16 + adds x6, x6, x20 + adcs x7, x7, x21 + adc x8, x8, xzr + # A[3] * B[0] + mul x20, x14, x15 + umulh x21, x14, x15 + adds x6, x6, x20 + adcs x7, x7, x21 + adc x8, x8, xzr + # A[1] * B[3] + mul x20, x12, x19 + umulh x21, x12, x19 + adds x7, x7, x20 + adcs x8, x8, x21 + adc x9, xzr, xzr + # A[2] * B[2] + mul x20, x13, x17 + umulh x21, x13, x17 + adds x7, x7, x20 + adcs x8, x8, x21 + adc x9, x9, xzr + # A[3] * B[1] + mul x20, x14, x16 + umulh x21, x14, x16 + adds x7, x7, x20 + adcs x8, x8, x21 + adc x9, x9, xzr + # A[2] * B[3] + mul x20, x13, x19 + umulh x21, x13, x19 + adds x8, x8, x20 + adcs x9, x9, x21 + adc x10, xzr, xzr + # A[3] * B[2] + mul x20, x14, x17 + umulh x21, x14, x17 + adds x8, x8, x20 + adcs x9, x9, x21 + adc x10, x10, xzr + # A[3] * B[3] + mul x20, x14, x19 + umulh x21, x14, x19 + adds x9, x9, x20 + adc x10, x10, x21 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + extr x8, x8, x7, #63 + extr x7, x7, x6, #63 + and x6, x6, #0x7fffffffffffffff + # Multiply top half by 19 + mov x20, #19 + mul x21, x20, x7 + umulh x7, x20, x7 + adds x3, x3, x21 + mul x21, x20, x8 + umulh x8, x20, x8 + adcs x4, x4, x21 + mul x21, x20, x9 + umulh x9, x20, x9 + adcs x5, x5, x21 + mul x21, x20, x10 + umulh x22, x20, x10 + adcs x6, x6, x21 + adc x22, x22, xzr + # Add remaining product results in + adds x4, x4, x7 + adcs x5, x5, x8 + adcs x6, x6, x9 + adc x22, x22, xzr + # Overflow + extr x22, x22, x6, #63 + mul x22, x22, x20 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x22 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Reduce if top bit set + and x22, x20, x6, asr 63 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x22 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Store + stp x3, x4, [x0] + stp x5, x6, [x0, #16] + ldr x0, [x29, #24] + ldr x2, [x29, #56] + # Multiply + ldp x11, x12, [x2] + ldp x13, x14, [x2, #16] + # A[0] * B[0] + mul x3, x15, x11 + umulh x4, x15, x11 + # A[0] * B[1] + mul x20, x15, x12 + umulh x5, x15, x12 + adds x4, x4, x20 + adc x5, x5, xzr + # A[1] * B[0] + mul x20, x16, x11 + umulh x21, x16, x11 + adds x4, x4, x20 + adcs x5, x5, x21 + adc x6, xzr, xzr + # A[0] * B[2] + mul x20, x15, x13 + umulh x21, x15, x13 + adds x5, x5, x20 + adc x6, x6, x21 + # A[1] * B[1] + mul x20, x16, x12 + umulh x21, x16, x12 + adds x5, x5, x20 + adcs x6, x6, x21 + adc x7, xzr, xzr + # A[2] * B[0] + mul x20, x17, x11 + umulh x21, x17, x11 + adds x5, x5, x20 + adcs x6, x6, x21 + adc x7, x7, xzr + # A[0] * B[3] + mul x20, x15, x14 + umulh x21, x15, x14 + adds x6, x6, x20 + adcs x7, x7, x21 + adc x8, xzr, xzr + # A[1] * B[2] + mul x20, x16, x13 + umulh x21, x16, x13 + adds x6, x6, x20 + adcs x7, x7, x21 + adc x8, x8, xzr + # A[2] * B[1] + mul x20, x17, x12 + umulh x21, x17, x12 + adds x6, x6, x20 + adcs x7, x7, x21 + adc x8, x8, xzr + # A[3] * B[0] + mul x20, x19, x11 + umulh x21, x19, x11 + adds x6, x6, x20 + adcs x7, x7, x21 + adc x8, x8, xzr + # A[1] * B[3] + mul x20, x16, x14 + umulh x21, x16, x14 + adds x7, x7, x20 + adcs x8, x8, x21 + adc x9, xzr, xzr + # A[2] * B[2] + mul x20, x17, x13 + umulh x21, x17, x13 + adds x7, x7, x20 + adcs x8, x8, x21 + adc x9, x9, xzr + # A[3] * B[1] + mul x20, x19, x12 + umulh x21, x19, x12 + adds x7, x7, x20 + adcs x8, x8, x21 + adc x9, x9, xzr + # A[2] * B[3] + mul x20, x17, x14 + umulh x21, x17, x14 + adds x8, x8, x20 + adcs x9, x9, x21 + adc x10, xzr, xzr + # A[3] * B[2] + mul x20, x19, x13 + umulh x21, x19, x13 + adds x8, x8, x20 + adcs x9, x9, x21 + adc x10, x10, xzr + # A[3] * B[3] + mul x20, x19, x14 + umulh x21, x19, x14 + adds x9, x9, x20 + adc x10, x10, x21 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + extr x8, x8, x7, #63 + extr x7, x7, x6, #63 + and x6, x6, #0x7fffffffffffffff + # Multiply top half by 19 + mov x20, #19 + mul x21, x20, x7 + umulh x7, x20, x7 + adds x3, x3, x21 + mul x21, x20, x8 + umulh x8, x20, x8 + adcs x4, x4, x21 + mul x21, x20, x9 + umulh x9, x20, x9 + adcs x5, x5, x21 + mul x21, x20, x10 + umulh x22, x20, x10 + adcs x6, x6, x21 + adc x22, x22, xzr + # Add remaining product results in + adds x4, x4, x7 + adcs x5, x5, x8 + adcs x6, x6, x9 + adc x22, x22, xzr + # Overflow + extr x22, x22, x6, #63 + mul x22, x22, x20 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x22 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Reduce if top bit set + and x22, x20, x6, asr 63 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x22 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Store + stp x3, x4, [x0] + stp x5, x6, [x0, #16] + ldr x17, [x29, #72] + ldr x19, [x29, #80] + ldp x20, x21, [x29, #88] + ldr x22, [x29, #104] + ldp x29, x30, [sp], #0x70 + ret + .size fe_ge_to_p2,.-fe_ge_to_p2 + .text + .align 2 + .globl fe_ge_to_p3 + .type fe_ge_to_p3, %function +fe_ge_to_p3: + stp x29, x30, [sp, #-160]! + add x29, sp, #0 + str x17, [x29, #88] + str x19, [x29, #96] + stp x20, x21, [x29, #104] + stp x22, x23, [x29, #120] + stp x24, x25, [x29, #136] + str x26, [x29, #152] + str x1, [x29, #16] + str x2, [x29, #24] + str x3, [x29, #32] + str x4, [x29, #40] + str x5, [x29, #48] + str x6, [x29, #56] + str x7, [x29, #64] + ldr x1, [x29, #40] + ldr x2, [x29, #64] + # Multiply + ldp x11, x12, [x1] + ldp x13, x14, [x1, #16] + ldp x15, x16, [x2] + ldp x17, x19, [x2, #16] + # A[0] * B[0] + mul x3, x11, x15 + umulh x4, x11, x15 + # A[0] * B[1] + mul x24, x11, x16 + umulh x5, x11, x16 + adds x4, x4, x24 + adc x5, x5, xzr + # A[1] * B[0] + mul x24, x12, x15 + umulh x25, x12, x15 + adds x4, x4, x24 + adcs x5, x5, x25 + adc x6, xzr, xzr + # A[0] * B[2] + mul x24, x11, x17 + umulh x25, x11, x17 + adds x5, x5, x24 + adc x6, x6, x25 + # A[1] * B[1] + mul x24, x12, x16 + umulh x25, x12, x16 + adds x5, x5, x24 + adcs x6, x6, x25 + adc x7, xzr, xzr + # A[2] * B[0] + mul x24, x13, x15 + umulh x25, x13, x15 + adds x5, x5, x24 + adcs x6, x6, x25 + adc x7, x7, xzr + # A[0] * B[3] + mul x24, x11, x19 + umulh x25, x11, x19 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, xzr, xzr + # A[1] * B[2] + mul x24, x12, x17 + umulh x25, x12, x17 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, x8, xzr + # A[2] * B[1] + mul x24, x13, x16 + umulh x25, x13, x16 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, x8, xzr + # A[3] * B[0] + mul x24, x14, x15 + umulh x25, x14, x15 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, x8, xzr + # A[1] * B[3] + mul x24, x12, x19 + umulh x25, x12, x19 + adds x7, x7, x24 + adcs x8, x8, x25 + adc x9, xzr, xzr + # A[2] * B[2] + mul x24, x13, x17 + umulh x25, x13, x17 + adds x7, x7, x24 + adcs x8, x8, x25 + adc x9, x9, xzr + # A[3] * B[1] + mul x24, x14, x16 + umulh x25, x14, x16 + adds x7, x7, x24 + adcs x8, x8, x25 + adc x9, x9, xzr + # A[2] * B[3] + mul x24, x13, x19 + umulh x25, x13, x19 + adds x8, x8, x24 + adcs x9, x9, x25 + adc x10, xzr, xzr + # A[3] * B[2] + mul x24, x14, x17 + umulh x25, x14, x17 + adds x8, x8, x24 + adcs x9, x9, x25 + adc x10, x10, xzr + # A[3] * B[3] + mul x24, x14, x19 + umulh x25, x14, x19 + adds x9, x9, x24 + adc x10, x10, x25 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + extr x8, x8, x7, #63 + extr x7, x7, x6, #63 + and x6, x6, #0x7fffffffffffffff + # Multiply top half by 19 + mov x24, #19 + mul x25, x24, x7 + umulh x7, x24, x7 + adds x3, x3, x25 + mul x25, x24, x8 + umulh x8, x24, x8 + adcs x4, x4, x25 + mul x25, x24, x9 + umulh x9, x24, x9 + adcs x5, x5, x25 + mul x25, x24, x10 + umulh x26, x24, x10 + adcs x6, x6, x25 + adc x26, x26, xzr + # Add remaining product results in + adds x4, x4, x7 + adcs x5, x5, x8 + adcs x6, x6, x9 + adc x26, x26, xzr + # Overflow + extr x26, x26, x6, #63 + mul x26, x26, x24 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x26 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Reduce if top bit set + and x26, x24, x6, asr 63 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x26 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Store + stp x3, x4, [x0] + stp x5, x6, [x0, #16] + ldr x0, [x29, #32] + ldr x2, [x29, #48] + # Multiply + ldp x20, x21, [x2] + ldp x22, x23, [x2, #16] + # A[0] * B[0] + mul x3, x11, x20 + umulh x4, x11, x20 + # A[0] * B[1] + mul x24, x11, x21 + umulh x5, x11, x21 + adds x4, x4, x24 + adc x5, x5, xzr + # A[1] * B[0] + mul x24, x12, x20 + umulh x25, x12, x20 + adds x4, x4, x24 + adcs x5, x5, x25 + adc x6, xzr, xzr + # A[0] * B[2] + mul x24, x11, x22 + umulh x25, x11, x22 + adds x5, x5, x24 + adc x6, x6, x25 + # A[1] * B[1] + mul x24, x12, x21 + umulh x25, x12, x21 + adds x5, x5, x24 + adcs x6, x6, x25 + adc x7, xzr, xzr + # A[2] * B[0] + mul x24, x13, x20 + umulh x25, x13, x20 + adds x5, x5, x24 + adcs x6, x6, x25 + adc x7, x7, xzr + # A[0] * B[3] + mul x24, x11, x23 + umulh x25, x11, x23 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, xzr, xzr + # A[1] * B[2] + mul x24, x12, x22 + umulh x25, x12, x22 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, x8, xzr + # A[2] * B[1] + mul x24, x13, x21 + umulh x25, x13, x21 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, x8, xzr + # A[3] * B[0] + mul x24, x14, x20 + umulh x25, x14, x20 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, x8, xzr + # A[1] * B[3] + mul x24, x12, x23 + umulh x25, x12, x23 + adds x7, x7, x24 + adcs x8, x8, x25 + adc x9, xzr, xzr + # A[2] * B[2] + mul x24, x13, x22 + umulh x25, x13, x22 + adds x7, x7, x24 + adcs x8, x8, x25 + adc x9, x9, xzr + # A[3] * B[1] + mul x24, x14, x21 + umulh x25, x14, x21 + adds x7, x7, x24 + adcs x8, x8, x25 + adc x9, x9, xzr + # A[2] * B[3] + mul x24, x13, x23 + umulh x25, x13, x23 + adds x8, x8, x24 + adcs x9, x9, x25 + adc x10, xzr, xzr + # A[3] * B[2] + mul x24, x14, x22 + umulh x25, x14, x22 + adds x8, x8, x24 + adcs x9, x9, x25 + adc x10, x10, xzr + # A[3] * B[3] + mul x24, x14, x23 + umulh x25, x14, x23 + adds x9, x9, x24 + adc x10, x10, x25 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + extr x8, x8, x7, #63 + extr x7, x7, x6, #63 + and x6, x6, #0x7fffffffffffffff + # Multiply top half by 19 + mov x24, #19 + mul x25, x24, x7 + umulh x7, x24, x7 + adds x3, x3, x25 + mul x25, x24, x8 + umulh x8, x24, x8 + adcs x4, x4, x25 + mul x25, x24, x9 + umulh x9, x24, x9 + adcs x5, x5, x25 + mul x25, x24, x10 + umulh x26, x24, x10 + adcs x6, x6, x25 + adc x26, x26, xzr + # Add remaining product results in + adds x4, x4, x7 + adcs x5, x5, x8 + adcs x6, x6, x9 + adc x26, x26, xzr + # Overflow + extr x26, x26, x6, #63 + mul x26, x26, x24 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x26 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Reduce if top bit set + and x26, x24, x6, asr 63 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x26 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Store + stp x3, x4, [x0] + stp x5, x6, [x0, #16] + ldr x0, [x29, #16] + ldr x2, [x29, #56] + # Multiply + ldp x11, x12, [x2] + ldp x13, x14, [x2, #16] + # A[0] * B[0] + mul x3, x20, x11 + umulh x4, x20, x11 + # A[0] * B[1] + mul x24, x20, x12 + umulh x5, x20, x12 + adds x4, x4, x24 + adc x5, x5, xzr + # A[1] * B[0] + mul x24, x21, x11 + umulh x25, x21, x11 + adds x4, x4, x24 + adcs x5, x5, x25 + adc x6, xzr, xzr + # A[0] * B[2] + mul x24, x20, x13 + umulh x25, x20, x13 + adds x5, x5, x24 + adc x6, x6, x25 + # A[1] * B[1] + mul x24, x21, x12 + umulh x25, x21, x12 + adds x5, x5, x24 + adcs x6, x6, x25 + adc x7, xzr, xzr + # A[2] * B[0] + mul x24, x22, x11 + umulh x25, x22, x11 + adds x5, x5, x24 + adcs x6, x6, x25 + adc x7, x7, xzr + # A[0] * B[3] + mul x24, x20, x14 + umulh x25, x20, x14 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, xzr, xzr + # A[1] * B[2] + mul x24, x21, x13 + umulh x25, x21, x13 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, x8, xzr + # A[2] * B[1] + mul x24, x22, x12 + umulh x25, x22, x12 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, x8, xzr + # A[3] * B[0] + mul x24, x23, x11 + umulh x25, x23, x11 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, x8, xzr + # A[1] * B[3] + mul x24, x21, x14 + umulh x25, x21, x14 + adds x7, x7, x24 + adcs x8, x8, x25 + adc x9, xzr, xzr + # A[2] * B[2] + mul x24, x22, x13 + umulh x25, x22, x13 + adds x7, x7, x24 + adcs x8, x8, x25 + adc x9, x9, xzr + # A[3] * B[1] + mul x24, x23, x12 + umulh x25, x23, x12 + adds x7, x7, x24 + adcs x8, x8, x25 + adc x9, x9, xzr + # A[2] * B[3] + mul x24, x22, x14 + umulh x25, x22, x14 + adds x8, x8, x24 + adcs x9, x9, x25 + adc x10, xzr, xzr + # A[3] * B[2] + mul x24, x23, x13 + umulh x25, x23, x13 + adds x8, x8, x24 + adcs x9, x9, x25 + adc x10, x10, xzr + # A[3] * B[3] + mul x24, x23, x14 + umulh x25, x23, x14 + adds x9, x9, x24 + adc x10, x10, x25 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + extr x8, x8, x7, #63 + extr x7, x7, x6, #63 + and x6, x6, #0x7fffffffffffffff + # Multiply top half by 19 + mov x24, #19 + mul x25, x24, x7 + umulh x7, x24, x7 + adds x3, x3, x25 + mul x25, x24, x8 + umulh x8, x24, x8 + adcs x4, x4, x25 + mul x25, x24, x9 + umulh x9, x24, x9 + adcs x5, x5, x25 + mul x25, x24, x10 + umulh x26, x24, x10 + adcs x6, x6, x25 + adc x26, x26, xzr + # Add remaining product results in + adds x4, x4, x7 + adcs x5, x5, x8 + adcs x6, x6, x9 + adc x26, x26, xzr + # Overflow + extr x26, x26, x6, #63 + mul x26, x26, x24 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x26 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Reduce if top bit set + and x26, x24, x6, asr 63 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x26 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Store + stp x3, x4, [x0] + stp x5, x6, [x0, #16] + ldr x0, [x29, #24] + # Multiply + # A[0] * B[0] + mul x3, x11, x15 + umulh x4, x11, x15 + # A[0] * B[1] + mul x24, x11, x16 + umulh x5, x11, x16 + adds x4, x4, x24 + adc x5, x5, xzr + # A[1] * B[0] + mul x24, x12, x15 + umulh x25, x12, x15 + adds x4, x4, x24 + adcs x5, x5, x25 + adc x6, xzr, xzr + # A[0] * B[2] + mul x24, x11, x17 + umulh x25, x11, x17 + adds x5, x5, x24 + adc x6, x6, x25 + # A[1] * B[1] + mul x24, x12, x16 + umulh x25, x12, x16 + adds x5, x5, x24 + adcs x6, x6, x25 + adc x7, xzr, xzr + # A[2] * B[0] + mul x24, x13, x15 + umulh x25, x13, x15 + adds x5, x5, x24 + adcs x6, x6, x25 + adc x7, x7, xzr + # A[0] * B[3] + mul x24, x11, x19 + umulh x25, x11, x19 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, xzr, xzr + # A[1] * B[2] + mul x24, x12, x17 + umulh x25, x12, x17 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, x8, xzr + # A[2] * B[1] + mul x24, x13, x16 + umulh x25, x13, x16 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, x8, xzr + # A[3] * B[0] + mul x24, x14, x15 + umulh x25, x14, x15 + adds x6, x6, x24 + adcs x7, x7, x25 + adc x8, x8, xzr + # A[1] * B[3] + mul x24, x12, x19 + umulh x25, x12, x19 + adds x7, x7, x24 + adcs x8, x8, x25 + adc x9, xzr, xzr + # A[2] * B[2] + mul x24, x13, x17 + umulh x25, x13, x17 + adds x7, x7, x24 + adcs x8, x8, x25 + adc x9, x9, xzr + # A[3] * B[1] + mul x24, x14, x16 + umulh x25, x14, x16 + adds x7, x7, x24 + adcs x8, x8, x25 + adc x9, x9, xzr + # A[2] * B[3] + mul x24, x13, x19 + umulh x25, x13, x19 + adds x8, x8, x24 + adcs x9, x9, x25 + adc x10, xzr, xzr + # A[3] * B[2] + mul x24, x14, x17 + umulh x25, x14, x17 + adds x8, x8, x24 + adcs x9, x9, x25 + adc x10, x10, xzr + # A[3] * B[3] + mul x24, x14, x19 + umulh x25, x14, x19 + adds x9, x9, x24 + adc x10, x10, x25 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + extr x8, x8, x7, #63 + extr x7, x7, x6, #63 + and x6, x6, #0x7fffffffffffffff + # Multiply top half by 19 + mov x24, #19 + mul x25, x24, x7 + umulh x7, x24, x7 + adds x3, x3, x25 + mul x25, x24, x8 + umulh x8, x24, x8 + adcs x4, x4, x25 + mul x25, x24, x9 + umulh x9, x24, x9 + adcs x5, x5, x25 + mul x25, x24, x10 + umulh x26, x24, x10 + adcs x6, x6, x25 + adc x26, x26, xzr + # Add remaining product results in + adds x4, x4, x7 + adcs x5, x5, x8 + adcs x6, x6, x9 + adc x26, x26, xzr + # Overflow + extr x26, x26, x6, #63 + mul x26, x26, x24 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x26 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Reduce if top bit set + and x26, x24, x6, asr 63 + and x6, x6, #0x7fffffffffffffff + adds x3, x3, x26 + adcs x4, x4, xzr + adcs x5, x5, xzr + adc x6, x6, xzr + # Store + stp x3, x4, [x0] + stp x5, x6, [x0, #16] + ldr x17, [x29, #88] + ldr x19, [x29, #96] + ldp x20, x21, [x29, #104] + ldp x22, x23, [x29, #120] + ldp x24, x25, [x29, #136] + ldr x26, [x29, #152] + ldp x29, x30, [sp], #0xa0 + ret + .size fe_ge_to_p3,.-fe_ge_to_p3 + .text + .align 2 + .globl fe_ge_dbl + .type fe_ge_dbl, %function +fe_ge_dbl: + stp x29, x30, [sp, #-176]! + add x29, sp, #0 + str x17, [x29, #88] + str x19, [x29, #96] + stp x20, x21, [x29, #104] + stp x22, x23, [x29, #120] + stp x24, x25, [x29, #136] + stp x26, x27, [x29, #152] + str x28, [x29, #168] + str x0, [x29, #16] + str x1, [x29, #24] + str x2, [x29, #32] + str x3, [x29, #40] + str x4, [x29, #48] + str x5, [x29, #56] + str x6, [x29, #64] + ldr x1, [x29, #48] + # Square + ldp x12, x13, [x1] + ldp x14, x15, [x1, #16] + # A[0] * A[1] + mul x5, x12, x13 + umulh x6, x12, x13 + # A[0] * A[2] + mul x25, x12, x14 + umulh x7, x12, x14 + adds x6, x6, x25 + adc x7, x7, xzr + # A[0] * A[3] + mul x25, x12, x15 + umulh x8, x12, x15 + adds x7, x7, x25 + adc x8, x8, xzr + # A[1] * A[2] + mul x25, x13, x14 + umulh x26, x13, x14 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, xzr, xzr + # A[1] * A[3] + mul x25, x13, x15 + umulh x26, x13, x15 + adds x8, x8, x25 + adc x9, x9, x26 + # A[2] * A[3] + mul x25, x14, x15 + umulh x10, x14, x15 + adds x9, x9, x25 + adc x10, x10, xzr + # Double + adds x5, x5, x5 + adcs x6, x6, x6 + adcs x7, x7, x7 + adcs x8, x8, x8 + adcs x9, x9, x9 + adcs x10, x10, x10 + adc x11, xzr, xzr + # A[0] * A[0] + mul x4, x12, x12 + umulh x27, x12, x12 + # A[1] * A[1] + mul x25, x13, x13 + umulh x26, x13, x13 + adds x5, x5, x27 + adcs x6, x6, x25 + adc x27, x26, xzr + # A[2] * A[2] + mul x25, x14, x14 + umulh x26, x14, x14 + adds x7, x7, x27 + adcs x8, x8, x25 + adc x27, x26, xzr + # A[3] * A[3] + mul x25, x15, x15 + umulh x26, x15, x15 + adds x9, x9, x27 + adcs x10, x10, x25 + adc x11, x11, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x11, x11, x10, #63 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + extr x8, x8, x7, #63 + and x7, x7, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x8 + umulh x8, x25, x8 + adds x4, x4, x26 + mul x26, x25, x9 + umulh x9, x25, x9 + adcs x5, x5, x26 + mul x26, x25, x10 + umulh x10, x25, x10 + adcs x6, x6, x26 + mul x26, x25, x11 + umulh x27, x25, x11 + adcs x7, x7, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x5, x5, x8 + adcs x6, x6, x9 + adcs x7, x7, x10 + adc x27, x27, xzr + # Overflow + extr x27, x27, x7, #63 + mul x27, x27, x25 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Reduce if top bit set + and x27, x25, x7, asr 63 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Store + stp x4, x5, [x0] + stp x6, x7, [x0, #16] + ldr x0, [x29, #32] + ldr x1, [x29, #56] + # Square + ldp x21, x22, [x1] + ldp x23, x24, [x1, #16] + # A[0] * A[1] + mul x9, x21, x22 + umulh x10, x21, x22 + # A[0] * A[2] + mul x25, x21, x23 + umulh x11, x21, x23 + adds x10, x10, x25 + adc x11, x11, xzr + # A[0] * A[3] + mul x25, x21, x24 + umulh x16, x21, x24 + adds x11, x11, x25 + adc x16, x16, xzr + # A[1] * A[2] + mul x25, x22, x23 + umulh x26, x22, x23 + adds x11, x11, x25 + adcs x16, x16, x26 + adc x17, xzr, xzr + # A[1] * A[3] + mul x25, x22, x24 + umulh x26, x22, x24 + adds x16, x16, x25 + adc x17, x17, x26 + # A[2] * A[3] + mul x25, x23, x24 + umulh x19, x23, x24 + adds x17, x17, x25 + adc x19, x19, xzr + # Double + adds x9, x9, x9 + adcs x10, x10, x10 + adcs x11, x11, x11 + adcs x16, x16, x16 + adcs x17, x17, x17 + adcs x19, x19, x19 + adc x20, xzr, xzr + # A[0] * A[0] + mul x8, x21, x21 + umulh x27, x21, x21 + # A[1] * A[1] + mul x25, x22, x22 + umulh x26, x22, x22 + adds x9, x9, x27 + adcs x10, x10, x25 + adc x27, x26, xzr + # A[2] * A[2] + mul x25, x23, x23 + umulh x26, x23, x23 + adds x11, x11, x27 + adcs x16, x16, x25 + adc x27, x26, xzr + # A[3] * A[3] + mul x25, x24, x24 + umulh x26, x24, x24 + adds x17, x17, x27 + adcs x19, x19, x25 + adc x20, x20, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x20, x20, x19, #63 + extr x19, x19, x17, #63 + extr x17, x17, x16, #63 + extr x16, x16, x11, #63 + and x11, x11, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x16 + umulh x16, x25, x16 + adds x8, x8, x26 + mul x26, x25, x17 + umulh x17, x25, x17 + adcs x9, x9, x26 + mul x26, x25, x19 + umulh x19, x25, x19 + adcs x10, x10, x26 + mul x26, x25, x20 + umulh x27, x25, x20 + adcs x11, x11, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x9, x9, x16 + adcs x10, x10, x17 + adcs x11, x11, x19 + adc x27, x27, xzr + # Overflow + extr x27, x27, x11, #63 + mul x27, x27, x25 + and x11, x11, #0x7fffffffffffffff + adds x8, x8, x27 + adcs x9, x9, xzr + adcs x10, x10, xzr + adc x11, x11, xzr + # Reduce if top bit set + and x27, x25, x11, asr 63 + and x11, x11, #0x7fffffffffffffff + adds x8, x8, x27 + adcs x9, x9, xzr + adcs x10, x10, xzr + adc x11, x11, xzr + # Store + stp x8, x9, [x0] + stp x10, x11, [x0, #16] + ldr x0, [x29, #24] + # Add + adds x12, x12, x21 + adcs x13, x13, x22 + adcs x14, x14, x23 + adc x15, x15, x24 + mov x25, #-19 + asr x28, x15, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x12, x12, x25 + sbcs x13, x13, x28 + sbcs x14, x14, x28 + sbc x15, x15, x26 + ldr x0, [x29, #40] + # Square + # A[0] * A[1] + mul x17, x12, x13 + umulh x19, x12, x13 + # A[0] * A[2] + mul x25, x12, x14 + umulh x20, x12, x14 + adds x19, x19, x25 + adc x20, x20, xzr + # A[0] * A[3] + mul x25, x12, x15 + umulh x21, x12, x15 + adds x20, x20, x25 + adc x21, x21, xzr + # A[1] * A[2] + mul x25, x13, x14 + umulh x26, x13, x14 + adds x20, x20, x25 + adcs x21, x21, x26 + adc x22, xzr, xzr + # A[1] * A[3] + mul x25, x13, x15 + umulh x26, x13, x15 + adds x21, x21, x25 + adc x22, x22, x26 + # A[2] * A[3] + mul x25, x14, x15 + umulh x23, x14, x15 + adds x22, x22, x25 + adc x23, x23, xzr + # Double + adds x17, x17, x17 + adcs x19, x19, x19 + adcs x20, x20, x20 + adcs x21, x21, x21 + adcs x22, x22, x22 + adcs x23, x23, x23 + adc x24, xzr, xzr + # A[0] * A[0] + mul x16, x12, x12 + umulh x27, x12, x12 + # A[1] * A[1] + mul x25, x13, x13 + umulh x26, x13, x13 + adds x17, x17, x27 + adcs x19, x19, x25 + adc x27, x26, xzr + # A[2] * A[2] + mul x25, x14, x14 + umulh x26, x14, x14 + adds x20, x20, x27 + adcs x21, x21, x25 + adc x27, x26, xzr + # A[3] * A[3] + mul x25, x15, x15 + umulh x26, x15, x15 + adds x22, x22, x27 + adcs x23, x23, x25 + adc x24, x24, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x24, x24, x23, #63 + extr x23, x23, x22, #63 + extr x22, x22, x21, #63 + extr x21, x21, x20, #63 + and x20, x20, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x21 + umulh x21, x25, x21 + adds x16, x16, x26 + mul x26, x25, x22 + umulh x22, x25, x22 + adcs x17, x17, x26 + mul x26, x25, x23 + umulh x23, x25, x23 + adcs x19, x19, x26 + mul x26, x25, x24 + umulh x27, x25, x24 + adcs x20, x20, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x17, x17, x21 + adcs x19, x19, x22 + adcs x20, x20, x23 + adc x27, x27, xzr + # Overflow + extr x27, x27, x20, #63 + mul x27, x27, x25 + and x20, x20, #0x7fffffffffffffff + adds x16, x16, x27 + adcs x17, x17, xzr + adcs x19, x19, xzr + adc x20, x20, xzr + # Reduce if top bit set + and x27, x25, x20, asr 63 + and x20, x20, #0x7fffffffffffffff + adds x16, x16, x27 + adcs x17, x17, xzr + adcs x19, x19, xzr + adc x20, x20, xzr + # Store + stp x16, x17, [x0] + stp x19, x20, [x0, #16] + ldr x0, [x29, #24] + ldr x1, [x29, #32] + # Add + adds x12, x8, x4 + adcs x13, x9, x5 + adcs x14, x10, x6 + adc x15, x11, x7 + mov x25, #-19 + asr x28, x15, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x12, x12, x25 + sbcs x13, x13, x28 + sbcs x14, x14, x28 + sbc x15, x15, x26 + # Sub + subs x21, x8, x4 + sbcs x22, x9, x5 + sbcs x23, x10, x6 + sbcs x24, x11, x7 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x21, x21, x25 + adcs x22, x22, x28 + adcs x23, x23, x28 + adc x24, x24, x26 + stp x12, x13, [x0] + stp x14, x15, [x0, #16] + stp x21, x22, [x1] + stp x23, x24, [x1, #16] + ldr x0, [x29, #16] + # Sub + subs x16, x16, x12 + sbcs x17, x17, x13 + sbcs x19, x19, x14 + sbcs x20, x20, x15 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x16, x16, x25 + adcs x17, x17, x28 + adcs x19, x19, x28 + adc x20, x20, x26 + stp x16, x17, [x0] + stp x19, x20, [x0, #16] + ldr x0, [x29, #40] + ldr x1, [x29, #64] + # Square * 2 + ldp x12, x13, [x1] + ldp x14, x15, [x1, #16] + # A[0] * A[1] + mul x5, x12, x13 + umulh x6, x12, x13 + # A[0] * A[2] + mul x25, x12, x14 + umulh x7, x12, x14 + adds x6, x6, x25 + adc x7, x7, xzr + # A[0] * A[3] + mul x25, x12, x15 + umulh x8, x12, x15 + adds x7, x7, x25 + adc x8, x8, xzr + # A[1] * A[2] + mul x25, x13, x14 + umulh x26, x13, x14 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, xzr, xzr + # A[1] * A[3] + mul x25, x13, x15 + umulh x26, x13, x15 + adds x8, x8, x25 + adc x9, x9, x26 + # A[2] * A[3] + mul x25, x14, x15 + umulh x10, x14, x15 + adds x9, x9, x25 + adc x10, x10, xzr + # Double + adds x5, x5, x5 + adcs x6, x6, x6 + adcs x7, x7, x7 + adcs x8, x8, x8 + adcs x9, x9, x9 + adcs x10, x10, x10 + adc x11, xzr, xzr + # A[0] * A[0] + mul x4, x12, x12 + umulh x28, x12, x12 + # A[1] * A[1] + mul x25, x13, x13 + umulh x26, x13, x13 + adds x5, x5, x28 + adcs x6, x6, x25 + adc x28, x26, xzr + # A[2] * A[2] + mul x25, x14, x14 + umulh x26, x14, x14 + adds x7, x7, x28 + adcs x8, x8, x25 + adc x28, x26, xzr + # A[3] * A[3] + mul x25, x15, x15 + umulh x26, x15, x15 + adds x9, x9, x28 + adcs x10, x10, x25 + adc x11, x11, x26 + # Double and Reduce + mov x25, #0x169 + # Move top half into t4-t7 and remove top bit from t3 + lsr x28, x11, #61 + extr x11, x11, x10, #62 + extr x10, x10, x9, #62 + extr x9, x9, x8, #62 + extr x8, x8, x7, #62 + extr x7, x7, x6, #63 + extr x6, x6, x5, #63 + extr x5, x5, x4, #63 + lsl x4, x4, #1 + and x7, x7, #0x7fffffffffffffff + # Two left, only one right + and x11, x11, #0x7fffffffffffffff + # Multiply top bits by 19*19 + mul x28, x28, x25 + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x8 + umulh x8, x25, x8 + adds x4, x4, x26 + mul x26, x25, x9 + umulh x9, x25, x9 + adcs x5, x5, x26 + mul x26, x25, x10 + umulh x10, x25, x10 + adcs x6, x6, x26 + mul x26, x25, x11 + umulh x27, x25, x11 + adcs x7, x7, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x4, x4, x28 + adcs x5, x5, x8 + adcs x6, x6, x9 + adcs x7, x7, x10 + adc x27, x27, xzr + # Overflow + extr x27, x27, x7, #63 + mul x27, x27, x25 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Reduce if top bit set + and x27, x25, x7, asr 63 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Store + ldr x0, [x29, #40] + # Sub + subs x4, x4, x21 + sbcs x5, x5, x22 + sbcs x6, x6, x23 + sbcs x7, x7, x24 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x4, x4, x25 + adcs x5, x5, x28 + adcs x6, x6, x28 + adc x7, x7, x26 + stp x4, x5, [x0] + stp x6, x7, [x0, #16] + ldr x17, [x29, #88] + ldr x19, [x29, #96] + ldp x20, x21, [x29, #104] + ldp x22, x23, [x29, #120] + ldp x24, x25, [x29, #136] + ldp x26, x27, [x29, #152] + ldr x28, [x29, #168] + ldp x29, x30, [sp], #0xb0 + ret + .size fe_ge_dbl,.-fe_ge_dbl + .text + .align 2 + .globl fe_ge_madd + .type fe_ge_madd, %function +fe_ge_madd: + stp x29, x30, [sp, #-176]! + add x29, sp, #0 + str x17, [x29, #88] + str x19, [x29, #96] + stp x20, x21, [x29, #104] + stp x22, x23, [x29, #120] + stp x24, x25, [x29, #136] + stp x26, x27, [x29, #152] + str x28, [x29, #168] + str x0, [x29, #16] + str x1, [x29, #24] + str x2, [x29, #32] + str x3, [x29, #40] + str x4, [x29, #48] + str x5, [x29, #56] + str x6, [x29, #64] + str x7, [x29, #72] + ldr x2, [x29, #56] + ldr x3, [x29, #48] + # Add + ldp x12, x13, [x2] + ldp x14, x15, [x2, #16] + ldp x16, x17, [x3] + ldp x19, x20, [x3, #16] + adds x4, x12, x16 + adcs x5, x13, x17 + adcs x6, x14, x19 + adc x7, x15, x20 + mov x25, #-19 + asr x28, x7, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x4, x4, x25 + sbcs x5, x5, x28 + sbcs x6, x6, x28 + sbc x7, x7, x26 + # Sub + subs x8, x12, x16 + sbcs x9, x13, x17 + sbcs x10, x14, x19 + sbcs x11, x15, x20 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x8, x8, x25 + adcs x9, x9, x28 + adcs x10, x10, x28 + adc x11, x11, x26 + ldr x0, [x29, #32] + ldr x2, [x29, #184] + # Multiply + ldp x21, x22, [x2] + ldp x23, x24, [x2, #16] + # A[0] * B[0] + mul x12, x4, x21 + umulh x13, x4, x21 + # A[0] * B[1] + mul x25, x4, x22 + umulh x14, x4, x22 + adds x13, x13, x25 + adc x14, x14, xzr + # A[1] * B[0] + mul x25, x5, x21 + umulh x26, x5, x21 + adds x13, x13, x25 + adcs x14, x14, x26 + adc x15, xzr, xzr + # A[0] * B[2] + mul x25, x4, x23 + umulh x26, x4, x23 + adds x14, x14, x25 + adc x15, x15, x26 + # A[1] * B[1] + mul x25, x5, x22 + umulh x26, x5, x22 + adds x14, x14, x25 + adcs x15, x15, x26 + adc x16, xzr, xzr + # A[2] * B[0] + mul x25, x6, x21 + umulh x26, x6, x21 + adds x14, x14, x25 + adcs x15, x15, x26 + adc x16, x16, xzr + # A[0] * B[3] + mul x25, x4, x24 + umulh x26, x4, x24 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, xzr, xzr + # A[1] * B[2] + mul x25, x5, x23 + umulh x26, x5, x23 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[2] * B[1] + mul x25, x6, x22 + umulh x26, x6, x22 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[3] * B[0] + mul x25, x7, x21 + umulh x26, x7, x21 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[1] * B[3] + mul x25, x5, x24 + umulh x26, x5, x24 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, xzr, xzr + # A[2] * B[2] + mul x25, x6, x23 + umulh x26, x6, x23 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[3] * B[1] + mul x25, x7, x22 + umulh x26, x7, x22 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[2] * B[3] + mul x25, x6, x24 + umulh x26, x6, x24 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, xzr, xzr + # A[3] * B[2] + mul x25, x7, x23 + umulh x26, x7, x23 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, x20, xzr + # A[3] * B[3] + mul x25, x7, x24 + umulh x26, x7, x24 + adds x19, x19, x25 + adc x20, x20, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x20, x20, x19, #63 + extr x19, x19, x17, #63 + extr x17, x17, x16, #63 + extr x16, x16, x15, #63 + and x15, x15, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x16 + umulh x16, x25, x16 + adds x12, x12, x26 + mul x26, x25, x17 + umulh x17, x25, x17 + adcs x13, x13, x26 + mul x26, x25, x19 + umulh x19, x25, x19 + adcs x14, x14, x26 + mul x26, x25, x20 + umulh x27, x25, x20 + adcs x15, x15, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x13, x13, x16 + adcs x14, x14, x17 + adcs x15, x15, x19 + adc x27, x27, xzr + # Overflow + extr x27, x27, x15, #63 + mul x27, x27, x25 + and x15, x15, #0x7fffffffffffffff + adds x12, x12, x27 + adcs x13, x13, xzr + adcs x14, x14, xzr + adc x15, x15, xzr + # Reduce if top bit set + and x27, x25, x15, asr 63 + and x15, x15, #0x7fffffffffffffff + adds x12, x12, x27 + adcs x13, x13, xzr + adcs x14, x14, xzr + adc x15, x15, xzr + # Store + ldr x0, [x29, #24] + ldr x1, [x29, #192] + # Multiply + ldp x21, x22, [x1] + ldp x23, x24, [x1, #16] + # A[0] * B[0] + mul x4, x8, x21 + umulh x5, x8, x21 + # A[0] * B[1] + mul x25, x8, x22 + umulh x6, x8, x22 + adds x5, x5, x25 + adc x6, x6, xzr + # A[1] * B[0] + mul x25, x9, x21 + umulh x26, x9, x21 + adds x5, x5, x25 + adcs x6, x6, x26 + adc x7, xzr, xzr + # A[0] * B[2] + mul x25, x8, x23 + umulh x26, x8, x23 + adds x6, x6, x25 + adc x7, x7, x26 + # A[1] * B[1] + mul x25, x9, x22 + umulh x26, x9, x22 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x16, xzr, xzr + # A[2] * B[0] + mul x25, x10, x21 + umulh x26, x10, x21 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x16, x16, xzr + # A[0] * B[3] + mul x25, x8, x24 + umulh x26, x8, x24 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, xzr, xzr + # A[1] * B[2] + mul x25, x9, x23 + umulh x26, x9, x23 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[2] * B[1] + mul x25, x10, x22 + umulh x26, x10, x22 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[3] * B[0] + mul x25, x11, x21 + umulh x26, x11, x21 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[1] * B[3] + mul x25, x9, x24 + umulh x26, x9, x24 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, xzr, xzr + # A[2] * B[2] + mul x25, x10, x23 + umulh x26, x10, x23 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[3] * B[1] + mul x25, x11, x22 + umulh x26, x11, x22 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[2] * B[3] + mul x25, x10, x24 + umulh x26, x10, x24 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, xzr, xzr + # A[3] * B[2] + mul x25, x11, x23 + umulh x26, x11, x23 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, x20, xzr + # A[3] * B[3] + mul x25, x11, x24 + umulh x26, x11, x24 + adds x19, x19, x25 + adc x20, x20, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x20, x20, x19, #63 + extr x19, x19, x17, #63 + extr x17, x17, x16, #63 + extr x16, x16, x7, #63 + and x7, x7, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x16 + umulh x16, x25, x16 + adds x4, x4, x26 + mul x26, x25, x17 + umulh x17, x25, x17 + adcs x5, x5, x26 + mul x26, x25, x19 + umulh x19, x25, x19 + adcs x6, x6, x26 + mul x26, x25, x20 + umulh x27, x25, x20 + adcs x7, x7, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x5, x5, x16 + adcs x6, x6, x17 + adcs x7, x7, x19 + adc x27, x27, xzr + # Overflow + extr x27, x27, x7, #63 + mul x27, x27, x25 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Reduce if top bit set + and x27, x25, x7, asr 63 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Store + ldr x0, [x29, #24] + ldr x1, [x29, #16] + # Add + adds x8, x12, x4 + adcs x9, x13, x5 + adcs x10, x14, x6 + adc x11, x15, x7 + mov x25, #-19 + asr x28, x11, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x8, x8, x25 + sbcs x9, x9, x28 + sbcs x10, x10, x28 + sbc x11, x11, x26 + # Sub + subs x16, x12, x4 + sbcs x17, x13, x5 + sbcs x19, x14, x6 + sbcs x20, x15, x7 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x16, x16, x25 + adcs x17, x17, x28 + adcs x19, x19, x28 + adc x20, x20, x26 + stp x8, x9, [x0] + stp x10, x11, [x0, #16] + stp x16, x17, [x1] + stp x19, x20, [x1, #16] + ldr x0, [x29, #40] + ldr x1, [x29, #176] + ldr x3, [x29, #72] + # Multiply + ldp x16, x17, [x1] + ldp x19, x20, [x1, #16] + ldp x21, x22, [x3] + ldp x23, x24, [x3, #16] + # A[0] * B[0] + mul x4, x16, x21 + umulh x5, x16, x21 + # A[0] * B[1] + mul x25, x16, x22 + umulh x6, x16, x22 + adds x5, x5, x25 + adc x6, x6, xzr + # A[1] * B[0] + mul x25, x17, x21 + umulh x26, x17, x21 + adds x5, x5, x25 + adcs x6, x6, x26 + adc x7, xzr, xzr + # A[0] * B[2] + mul x25, x16, x23 + umulh x26, x16, x23 + adds x6, x6, x25 + adc x7, x7, x26 + # A[1] * B[1] + mul x25, x17, x22 + umulh x26, x17, x22 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x8, xzr, xzr + # A[2] * B[0] + mul x25, x19, x21 + umulh x26, x19, x21 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x8, x8, xzr + # A[0] * B[3] + mul x25, x16, x24 + umulh x26, x16, x24 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, xzr, xzr + # A[1] * B[2] + mul x25, x17, x23 + umulh x26, x17, x23 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, x9, xzr + # A[2] * B[1] + mul x25, x19, x22 + umulh x26, x19, x22 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, x9, xzr + # A[3] * B[0] + mul x25, x20, x21 + umulh x26, x20, x21 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, x9, xzr + # A[1] * B[3] + mul x25, x17, x24 + umulh x26, x17, x24 + adds x8, x8, x25 + adcs x9, x9, x26 + adc x10, xzr, xzr + # A[2] * B[2] + mul x25, x19, x23 + umulh x26, x19, x23 + adds x8, x8, x25 + adcs x9, x9, x26 + adc x10, x10, xzr + # A[3] * B[1] + mul x25, x20, x22 + umulh x26, x20, x22 + adds x8, x8, x25 + adcs x9, x9, x26 + adc x10, x10, xzr + # A[2] * B[3] + mul x25, x19, x24 + umulh x26, x19, x24 + adds x9, x9, x25 + adcs x10, x10, x26 + adc x11, xzr, xzr + # A[3] * B[2] + mul x25, x20, x23 + umulh x26, x20, x23 + adds x9, x9, x25 + adcs x10, x10, x26 + adc x11, x11, xzr + # A[3] * B[3] + mul x25, x20, x24 + umulh x26, x20, x24 + adds x10, x10, x25 + adc x11, x11, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x11, x11, x10, #63 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + extr x8, x8, x7, #63 + and x7, x7, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x8 + umulh x8, x25, x8 + adds x4, x4, x26 + mul x26, x25, x9 + umulh x9, x25, x9 + adcs x5, x5, x26 + mul x26, x25, x10 + umulh x10, x25, x10 + adcs x6, x6, x26 + mul x26, x25, x11 + umulh x27, x25, x11 + adcs x7, x7, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x5, x5, x8 + adcs x6, x6, x9 + adcs x7, x7, x10 + adc x27, x27, xzr + # Overflow + extr x27, x27, x7, #63 + mul x27, x27, x25 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Reduce if top bit set + and x27, x25, x7, asr 63 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Store + ldr x0, [x29, #32] + ldr x1, [x29, #64] + # Double + ldp x8, x9, [x1] + ldp x10, x11, [x1, #16] + adds x8, x8, x8 + adcs x9, x9, x9 + adcs x10, x10, x10 + adc x11, x11, x11 + mov x25, #-19 + asr x28, x11, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x8, x8, x25 + sbcs x9, x9, x28 + sbcs x10, x10, x28 + sbc x11, x11, x26 + ldr x1, [x29, #40] + # Add + adds x12, x8, x4 + adcs x13, x9, x5 + adcs x14, x10, x6 + adc x15, x11, x7 + mov x25, #-19 + asr x28, x15, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x12, x12, x25 + sbcs x13, x13, x28 + sbcs x14, x14, x28 + sbc x15, x15, x26 + # Sub + subs x16, x8, x4 + sbcs x17, x9, x5 + sbcs x19, x10, x6 + sbcs x20, x11, x7 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x16, x16, x25 + adcs x17, x17, x28 + adcs x19, x19, x28 + adc x20, x20, x26 + stp x12, x13, [x0] + stp x14, x15, [x0, #16] + stp x16, x17, [x1] + stp x19, x20, [x1, #16] + ldr x17, [x29, #88] + ldr x19, [x29, #96] + ldp x20, x21, [x29, #104] + ldp x22, x23, [x29, #120] + ldp x24, x25, [x29, #136] + ldp x26, x27, [x29, #152] + ldr x28, [x29, #168] + ldp x29, x30, [sp], #0xb0 + ret + .size fe_ge_madd,.-fe_ge_madd + .text + .align 2 + .globl fe_ge_msub + .type fe_ge_msub, %function +fe_ge_msub: + stp x29, x30, [sp, #-176]! + add x29, sp, #0 + str x17, [x29, #88] + str x19, [x29, #96] + stp x20, x21, [x29, #104] + stp x22, x23, [x29, #120] + stp x24, x25, [x29, #136] + stp x26, x27, [x29, #152] + str x28, [x29, #168] + str x0, [x29, #16] + str x1, [x29, #24] + str x2, [x29, #32] + str x3, [x29, #40] + str x4, [x29, #48] + str x5, [x29, #56] + str x6, [x29, #64] + str x7, [x29, #72] + ldr x2, [x29, #56] + ldr x3, [x29, #48] + # Add + ldp x12, x13, [x2] + ldp x14, x15, [x2, #16] + ldp x16, x17, [x3] + ldp x19, x20, [x3, #16] + adds x4, x12, x16 + adcs x5, x13, x17 + adcs x6, x14, x19 + adc x7, x15, x20 + mov x25, #-19 + asr x28, x7, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x4, x4, x25 + sbcs x5, x5, x28 + sbcs x6, x6, x28 + sbc x7, x7, x26 + # Sub + subs x8, x12, x16 + sbcs x9, x13, x17 + sbcs x10, x14, x19 + sbcs x11, x15, x20 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x8, x8, x25 + adcs x9, x9, x28 + adcs x10, x10, x28 + adc x11, x11, x26 + ldr x0, [x29, #32] + ldr x2, [x29, #192] + # Multiply + ldp x21, x22, [x2] + ldp x23, x24, [x2, #16] + # A[0] * B[0] + mul x12, x4, x21 + umulh x13, x4, x21 + # A[0] * B[1] + mul x25, x4, x22 + umulh x14, x4, x22 + adds x13, x13, x25 + adc x14, x14, xzr + # A[1] * B[0] + mul x25, x5, x21 + umulh x26, x5, x21 + adds x13, x13, x25 + adcs x14, x14, x26 + adc x15, xzr, xzr + # A[0] * B[2] + mul x25, x4, x23 + umulh x26, x4, x23 + adds x14, x14, x25 + adc x15, x15, x26 + # A[1] * B[1] + mul x25, x5, x22 + umulh x26, x5, x22 + adds x14, x14, x25 + adcs x15, x15, x26 + adc x16, xzr, xzr + # A[2] * B[0] + mul x25, x6, x21 + umulh x26, x6, x21 + adds x14, x14, x25 + adcs x15, x15, x26 + adc x16, x16, xzr + # A[0] * B[3] + mul x25, x4, x24 + umulh x26, x4, x24 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, xzr, xzr + # A[1] * B[2] + mul x25, x5, x23 + umulh x26, x5, x23 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[2] * B[1] + mul x25, x6, x22 + umulh x26, x6, x22 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[3] * B[0] + mul x25, x7, x21 + umulh x26, x7, x21 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[1] * B[3] + mul x25, x5, x24 + umulh x26, x5, x24 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, xzr, xzr + # A[2] * B[2] + mul x25, x6, x23 + umulh x26, x6, x23 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[3] * B[1] + mul x25, x7, x22 + umulh x26, x7, x22 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[2] * B[3] + mul x25, x6, x24 + umulh x26, x6, x24 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, xzr, xzr + # A[3] * B[2] + mul x25, x7, x23 + umulh x26, x7, x23 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, x20, xzr + # A[3] * B[3] + mul x25, x7, x24 + umulh x26, x7, x24 + adds x19, x19, x25 + adc x20, x20, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x20, x20, x19, #63 + extr x19, x19, x17, #63 + extr x17, x17, x16, #63 + extr x16, x16, x15, #63 + and x15, x15, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x16 + umulh x16, x25, x16 + adds x12, x12, x26 + mul x26, x25, x17 + umulh x17, x25, x17 + adcs x13, x13, x26 + mul x26, x25, x19 + umulh x19, x25, x19 + adcs x14, x14, x26 + mul x26, x25, x20 + umulh x27, x25, x20 + adcs x15, x15, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x13, x13, x16 + adcs x14, x14, x17 + adcs x15, x15, x19 + adc x27, x27, xzr + # Overflow + extr x27, x27, x15, #63 + mul x27, x27, x25 + and x15, x15, #0x7fffffffffffffff + adds x12, x12, x27 + adcs x13, x13, xzr + adcs x14, x14, xzr + adc x15, x15, xzr + # Reduce if top bit set + and x27, x25, x15, asr 63 + and x15, x15, #0x7fffffffffffffff + adds x12, x12, x27 + adcs x13, x13, xzr + adcs x14, x14, xzr + adc x15, x15, xzr + # Store + ldr x0, [x29, #24] + ldr x1, [x29, #184] + # Multiply + ldp x21, x22, [x1] + ldp x23, x24, [x1, #16] + # A[0] * B[0] + mul x4, x8, x21 + umulh x5, x8, x21 + # A[0] * B[1] + mul x25, x8, x22 + umulh x6, x8, x22 + adds x5, x5, x25 + adc x6, x6, xzr + # A[1] * B[0] + mul x25, x9, x21 + umulh x26, x9, x21 + adds x5, x5, x25 + adcs x6, x6, x26 + adc x7, xzr, xzr + # A[0] * B[2] + mul x25, x8, x23 + umulh x26, x8, x23 + adds x6, x6, x25 + adc x7, x7, x26 + # A[1] * B[1] + mul x25, x9, x22 + umulh x26, x9, x22 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x16, xzr, xzr + # A[2] * B[0] + mul x25, x10, x21 + umulh x26, x10, x21 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x16, x16, xzr + # A[0] * B[3] + mul x25, x8, x24 + umulh x26, x8, x24 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, xzr, xzr + # A[1] * B[2] + mul x25, x9, x23 + umulh x26, x9, x23 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[2] * B[1] + mul x25, x10, x22 + umulh x26, x10, x22 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[3] * B[0] + mul x25, x11, x21 + umulh x26, x11, x21 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[1] * B[3] + mul x25, x9, x24 + umulh x26, x9, x24 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, xzr, xzr + # A[2] * B[2] + mul x25, x10, x23 + umulh x26, x10, x23 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[3] * B[1] + mul x25, x11, x22 + umulh x26, x11, x22 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[2] * B[3] + mul x25, x10, x24 + umulh x26, x10, x24 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, xzr, xzr + # A[3] * B[2] + mul x25, x11, x23 + umulh x26, x11, x23 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, x20, xzr + # A[3] * B[3] + mul x25, x11, x24 + umulh x26, x11, x24 + adds x19, x19, x25 + adc x20, x20, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x20, x20, x19, #63 + extr x19, x19, x17, #63 + extr x17, x17, x16, #63 + extr x16, x16, x7, #63 + and x7, x7, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x16 + umulh x16, x25, x16 + adds x4, x4, x26 + mul x26, x25, x17 + umulh x17, x25, x17 + adcs x5, x5, x26 + mul x26, x25, x19 + umulh x19, x25, x19 + adcs x6, x6, x26 + mul x26, x25, x20 + umulh x27, x25, x20 + adcs x7, x7, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x5, x5, x16 + adcs x6, x6, x17 + adcs x7, x7, x19 + adc x27, x27, xzr + # Overflow + extr x27, x27, x7, #63 + mul x27, x27, x25 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Reduce if top bit set + and x27, x25, x7, asr 63 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Store + ldr x0, [x29, #24] + ldr x1, [x29, #16] + # Add + adds x8, x12, x4 + adcs x9, x13, x5 + adcs x10, x14, x6 + adc x11, x15, x7 + mov x25, #-19 + asr x28, x11, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x8, x8, x25 + sbcs x9, x9, x28 + sbcs x10, x10, x28 + sbc x11, x11, x26 + # Sub + subs x16, x12, x4 + sbcs x17, x13, x5 + sbcs x19, x14, x6 + sbcs x20, x15, x7 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x16, x16, x25 + adcs x17, x17, x28 + adcs x19, x19, x28 + adc x20, x20, x26 + stp x8, x9, [x0] + stp x10, x11, [x0, #16] + stp x16, x17, [x1] + stp x19, x20, [x1, #16] + ldr x0, [x29, #40] + ldr x1, [x29, #176] + ldr x3, [x29, #72] + # Multiply + ldp x16, x17, [x1] + ldp x19, x20, [x1, #16] + ldp x21, x22, [x3] + ldp x23, x24, [x3, #16] + # A[0] * B[0] + mul x4, x16, x21 + umulh x5, x16, x21 + # A[0] * B[1] + mul x25, x16, x22 + umulh x6, x16, x22 + adds x5, x5, x25 + adc x6, x6, xzr + # A[1] * B[0] + mul x25, x17, x21 + umulh x26, x17, x21 + adds x5, x5, x25 + adcs x6, x6, x26 + adc x7, xzr, xzr + # A[0] * B[2] + mul x25, x16, x23 + umulh x26, x16, x23 + adds x6, x6, x25 + adc x7, x7, x26 + # A[1] * B[1] + mul x25, x17, x22 + umulh x26, x17, x22 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x8, xzr, xzr + # A[2] * B[0] + mul x25, x19, x21 + umulh x26, x19, x21 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x8, x8, xzr + # A[0] * B[3] + mul x25, x16, x24 + umulh x26, x16, x24 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, xzr, xzr + # A[1] * B[2] + mul x25, x17, x23 + umulh x26, x17, x23 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, x9, xzr + # A[2] * B[1] + mul x25, x19, x22 + umulh x26, x19, x22 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, x9, xzr + # A[3] * B[0] + mul x25, x20, x21 + umulh x26, x20, x21 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, x9, xzr + # A[1] * B[3] + mul x25, x17, x24 + umulh x26, x17, x24 + adds x8, x8, x25 + adcs x9, x9, x26 + adc x10, xzr, xzr + # A[2] * B[2] + mul x25, x19, x23 + umulh x26, x19, x23 + adds x8, x8, x25 + adcs x9, x9, x26 + adc x10, x10, xzr + # A[3] * B[1] + mul x25, x20, x22 + umulh x26, x20, x22 + adds x8, x8, x25 + adcs x9, x9, x26 + adc x10, x10, xzr + # A[2] * B[3] + mul x25, x19, x24 + umulh x26, x19, x24 + adds x9, x9, x25 + adcs x10, x10, x26 + adc x11, xzr, xzr + # A[3] * B[2] + mul x25, x20, x23 + umulh x26, x20, x23 + adds x9, x9, x25 + adcs x10, x10, x26 + adc x11, x11, xzr + # A[3] * B[3] + mul x25, x20, x24 + umulh x26, x20, x24 + adds x10, x10, x25 + adc x11, x11, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x11, x11, x10, #63 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + extr x8, x8, x7, #63 + and x7, x7, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x8 + umulh x8, x25, x8 + adds x4, x4, x26 + mul x26, x25, x9 + umulh x9, x25, x9 + adcs x5, x5, x26 + mul x26, x25, x10 + umulh x10, x25, x10 + adcs x6, x6, x26 + mul x26, x25, x11 + umulh x27, x25, x11 + adcs x7, x7, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x5, x5, x8 + adcs x6, x6, x9 + adcs x7, x7, x10 + adc x27, x27, xzr + # Overflow + extr x27, x27, x7, #63 + mul x27, x27, x25 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Reduce if top bit set + and x27, x25, x7, asr 63 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Store + ldr x0, [x29, #32] + ldr x1, [x29, #64] + # Double + ldp x8, x9, [x1] + ldp x10, x11, [x1, #16] + adds x8, x8, x8 + adcs x9, x9, x9 + adcs x10, x10, x10 + adc x11, x11, x11 + mov x25, #-19 + asr x28, x11, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x8, x8, x25 + sbcs x9, x9, x28 + sbcs x10, x10, x28 + sbc x11, x11, x26 + ldr x1, [x29, #40] + # Add + adds x12, x8, x4 + adcs x13, x9, x5 + adcs x14, x10, x6 + adc x15, x11, x7 + mov x25, #-19 + asr x28, x15, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x12, x12, x25 + sbcs x13, x13, x28 + sbcs x14, x14, x28 + sbc x15, x15, x26 + # Sub + subs x16, x8, x4 + sbcs x17, x9, x5 + sbcs x19, x10, x6 + sbcs x20, x11, x7 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x16, x16, x25 + adcs x17, x17, x28 + adcs x19, x19, x28 + adc x20, x20, x26 + stp x12, x13, [x1] + stp x14, x15, [x1, #16] + stp x16, x17, [x0] + stp x19, x20, [x0, #16] + ldr x17, [x29, #88] + ldr x19, [x29, #96] + ldp x20, x21, [x29, #104] + ldp x22, x23, [x29, #120] + ldp x24, x25, [x29, #136] + ldp x26, x27, [x29, #152] + ldr x28, [x29, #168] + ldp x29, x30, [sp], #0xb0 + ret + .size fe_ge_msub,.-fe_ge_msub + .text + .align 2 + .globl fe_ge_add + .type fe_ge_add, %function +fe_ge_add: + stp x29, x30, [sp, #-176]! + add x29, sp, #0 + str x17, [x29, #88] + str x19, [x29, #96] + stp x20, x21, [x29, #104] + stp x22, x23, [x29, #120] + stp x24, x25, [x29, #136] + stp x26, x27, [x29, #152] + str x28, [x29, #168] + str x0, [x29, #16] + str x1, [x29, #24] + str x2, [x29, #32] + str x3, [x29, #40] + str x4, [x29, #48] + str x5, [x29, #56] + str x6, [x29, #64] + str x7, [x29, #72] + ldr x2, [x29, #56] + ldr x3, [x29, #48] + # Add + ldp x12, x13, [x2] + ldp x14, x15, [x2, #16] + ldp x16, x17, [x3] + ldp x19, x20, [x3, #16] + adds x4, x12, x16 + adcs x5, x13, x17 + adcs x6, x14, x19 + adc x7, x15, x20 + mov x25, #-19 + asr x28, x7, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x4, x4, x25 + sbcs x5, x5, x28 + sbcs x6, x6, x28 + sbc x7, x7, x26 + # Sub + subs x8, x12, x16 + sbcs x9, x13, x17 + sbcs x10, x14, x19 + sbcs x11, x15, x20 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x8, x8, x25 + adcs x9, x9, x28 + adcs x10, x10, x28 + adc x11, x11, x26 + ldr x0, [x29, #32] + ldr x2, [x29, #192] + # Multiply + ldp x21, x22, [x2] + ldp x23, x24, [x2, #16] + # A[0] * B[0] + mul x12, x4, x21 + umulh x13, x4, x21 + # A[0] * B[1] + mul x25, x4, x22 + umulh x14, x4, x22 + adds x13, x13, x25 + adc x14, x14, xzr + # A[1] * B[0] + mul x25, x5, x21 + umulh x26, x5, x21 + adds x13, x13, x25 + adcs x14, x14, x26 + adc x15, xzr, xzr + # A[0] * B[2] + mul x25, x4, x23 + umulh x26, x4, x23 + adds x14, x14, x25 + adc x15, x15, x26 + # A[1] * B[1] + mul x25, x5, x22 + umulh x26, x5, x22 + adds x14, x14, x25 + adcs x15, x15, x26 + adc x16, xzr, xzr + # A[2] * B[0] + mul x25, x6, x21 + umulh x26, x6, x21 + adds x14, x14, x25 + adcs x15, x15, x26 + adc x16, x16, xzr + # A[0] * B[3] + mul x25, x4, x24 + umulh x26, x4, x24 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, xzr, xzr + # A[1] * B[2] + mul x25, x5, x23 + umulh x26, x5, x23 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[2] * B[1] + mul x25, x6, x22 + umulh x26, x6, x22 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[3] * B[0] + mul x25, x7, x21 + umulh x26, x7, x21 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[1] * B[3] + mul x25, x5, x24 + umulh x26, x5, x24 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, xzr, xzr + # A[2] * B[2] + mul x25, x6, x23 + umulh x26, x6, x23 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[3] * B[1] + mul x25, x7, x22 + umulh x26, x7, x22 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[2] * B[3] + mul x25, x6, x24 + umulh x26, x6, x24 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, xzr, xzr + # A[3] * B[2] + mul x25, x7, x23 + umulh x26, x7, x23 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, x20, xzr + # A[3] * B[3] + mul x25, x7, x24 + umulh x26, x7, x24 + adds x19, x19, x25 + adc x20, x20, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x20, x20, x19, #63 + extr x19, x19, x17, #63 + extr x17, x17, x16, #63 + extr x16, x16, x15, #63 + and x15, x15, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x16 + umulh x16, x25, x16 + adds x12, x12, x26 + mul x26, x25, x17 + umulh x17, x25, x17 + adcs x13, x13, x26 + mul x26, x25, x19 + umulh x19, x25, x19 + adcs x14, x14, x26 + mul x26, x25, x20 + umulh x27, x25, x20 + adcs x15, x15, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x13, x13, x16 + adcs x14, x14, x17 + adcs x15, x15, x19 + adc x27, x27, xzr + # Overflow + extr x27, x27, x15, #63 + mul x27, x27, x25 + and x15, x15, #0x7fffffffffffffff + adds x12, x12, x27 + adcs x13, x13, xzr + adcs x14, x14, xzr + adc x15, x15, xzr + # Reduce if top bit set + and x27, x25, x15, asr 63 + and x15, x15, #0x7fffffffffffffff + adds x12, x12, x27 + adcs x13, x13, xzr + adcs x14, x14, xzr + adc x15, x15, xzr + # Store + ldr x0, [x29, #24] + ldr x1, [x29, #200] + # Multiply + ldp x21, x22, [x1] + ldp x23, x24, [x1, #16] + # A[0] * B[0] + mul x4, x8, x21 + umulh x5, x8, x21 + # A[0] * B[1] + mul x25, x8, x22 + umulh x6, x8, x22 + adds x5, x5, x25 + adc x6, x6, xzr + # A[1] * B[0] + mul x25, x9, x21 + umulh x26, x9, x21 + adds x5, x5, x25 + adcs x6, x6, x26 + adc x7, xzr, xzr + # A[0] * B[2] + mul x25, x8, x23 + umulh x26, x8, x23 + adds x6, x6, x25 + adc x7, x7, x26 + # A[1] * B[1] + mul x25, x9, x22 + umulh x26, x9, x22 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x16, xzr, xzr + # A[2] * B[0] + mul x25, x10, x21 + umulh x26, x10, x21 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x16, x16, xzr + # A[0] * B[3] + mul x25, x8, x24 + umulh x26, x8, x24 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, xzr, xzr + # A[1] * B[2] + mul x25, x9, x23 + umulh x26, x9, x23 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[2] * B[1] + mul x25, x10, x22 + umulh x26, x10, x22 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[3] * B[0] + mul x25, x11, x21 + umulh x26, x11, x21 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[1] * B[3] + mul x25, x9, x24 + umulh x26, x9, x24 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, xzr, xzr + # A[2] * B[2] + mul x25, x10, x23 + umulh x26, x10, x23 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[3] * B[1] + mul x25, x11, x22 + umulh x26, x11, x22 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[2] * B[3] + mul x25, x10, x24 + umulh x26, x10, x24 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, xzr, xzr + # A[3] * B[2] + mul x25, x11, x23 + umulh x26, x11, x23 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, x20, xzr + # A[3] * B[3] + mul x25, x11, x24 + umulh x26, x11, x24 + adds x19, x19, x25 + adc x20, x20, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x20, x20, x19, #63 + extr x19, x19, x17, #63 + extr x17, x17, x16, #63 + extr x16, x16, x7, #63 + and x7, x7, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x16 + umulh x16, x25, x16 + adds x4, x4, x26 + mul x26, x25, x17 + umulh x17, x25, x17 + adcs x5, x5, x26 + mul x26, x25, x19 + umulh x19, x25, x19 + adcs x6, x6, x26 + mul x26, x25, x20 + umulh x27, x25, x20 + adcs x7, x7, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x5, x5, x16 + adcs x6, x6, x17 + adcs x7, x7, x19 + adc x27, x27, xzr + # Overflow + extr x27, x27, x7, #63 + mul x27, x27, x25 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Reduce if top bit set + and x27, x25, x7, asr 63 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Store + ldr x0, [x29, #24] + ldr x1, [x29, #16] + # Add + adds x8, x12, x4 + adcs x9, x13, x5 + adcs x10, x14, x6 + adc x11, x15, x7 + mov x25, #-19 + asr x28, x11, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x8, x8, x25 + sbcs x9, x9, x28 + sbcs x10, x10, x28 + sbc x11, x11, x26 + # Sub + subs x16, x12, x4 + sbcs x17, x13, x5 + sbcs x19, x14, x6 + sbcs x20, x15, x7 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x16, x16, x25 + adcs x17, x17, x28 + adcs x19, x19, x28 + adc x20, x20, x26 + stp x8, x9, [x0] + stp x10, x11, [x0, #16] + stp x16, x17, [x1] + stp x19, x20, [x1, #16] + ldr x0, [x29, #48] + ldr x1, [x29, #64] + ldr x2, [x29, #176] + # Multiply + ldp x12, x13, [x1] + ldp x14, x15, [x1, #16] + ldp x16, x17, [x2] + ldp x19, x20, [x2, #16] + # A[0] * B[0] + mul x4, x12, x16 + umulh x5, x12, x16 + # A[0] * B[1] + mul x25, x12, x17 + umulh x6, x12, x17 + adds x5, x5, x25 + adc x6, x6, xzr + # A[1] * B[0] + mul x25, x13, x16 + umulh x26, x13, x16 + adds x5, x5, x25 + adcs x6, x6, x26 + adc x7, xzr, xzr + # A[0] * B[2] + mul x25, x12, x19 + umulh x26, x12, x19 + adds x6, x6, x25 + adc x7, x7, x26 + # A[1] * B[1] + mul x25, x13, x17 + umulh x26, x13, x17 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x8, xzr, xzr + # A[2] * B[0] + mul x25, x14, x16 + umulh x26, x14, x16 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x8, x8, xzr + # A[0] * B[3] + mul x25, x12, x20 + umulh x26, x12, x20 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, xzr, xzr + # A[1] * B[2] + mul x25, x13, x19 + umulh x26, x13, x19 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, x9, xzr + # A[2] * B[1] + mul x25, x14, x17 + umulh x26, x14, x17 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, x9, xzr + # A[3] * B[0] + mul x25, x15, x16 + umulh x26, x15, x16 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, x9, xzr + # A[1] * B[3] + mul x25, x13, x20 + umulh x26, x13, x20 + adds x8, x8, x25 + adcs x9, x9, x26 + adc x10, xzr, xzr + # A[2] * B[2] + mul x25, x14, x19 + umulh x26, x14, x19 + adds x8, x8, x25 + adcs x9, x9, x26 + adc x10, x10, xzr + # A[3] * B[1] + mul x25, x15, x17 + umulh x26, x15, x17 + adds x8, x8, x25 + adcs x9, x9, x26 + adc x10, x10, xzr + # A[2] * B[3] + mul x25, x14, x20 + umulh x26, x14, x20 + adds x9, x9, x25 + adcs x10, x10, x26 + adc x11, xzr, xzr + # A[3] * B[2] + mul x25, x15, x19 + umulh x26, x15, x19 + adds x9, x9, x25 + adcs x10, x10, x26 + adc x11, x11, xzr + # A[3] * B[3] + mul x25, x15, x20 + umulh x26, x15, x20 + adds x10, x10, x25 + adc x11, x11, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x11, x11, x10, #63 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + extr x8, x8, x7, #63 + and x7, x7, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x8 + umulh x8, x25, x8 + adds x4, x4, x26 + mul x26, x25, x9 + umulh x9, x25, x9 + adcs x5, x5, x26 + mul x26, x25, x10 + umulh x10, x25, x10 + adcs x6, x6, x26 + mul x26, x25, x11 + umulh x27, x25, x11 + adcs x7, x7, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x5, x5, x8 + adcs x6, x6, x9 + adcs x7, x7, x10 + adc x27, x27, xzr + # Overflow + extr x27, x27, x7, #63 + mul x27, x27, x25 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Reduce if top bit set + and x27, x25, x7, asr 63 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Store + ldr x0, [x29, #48] + # Double + adds x4, x4, x4 + adcs x5, x5, x5 + adcs x6, x6, x6 + adc x7, x7, x7 + mov x25, #-19 + asr x28, x7, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x4, x4, x25 + sbcs x5, x5, x28 + sbcs x6, x6, x28 + sbc x7, x7, x26 + ldr x0, [x29, #40] + ldr x1, [x29, #184] + ldr x2, [x29, #72] + # Multiply + ldp x16, x17, [x1] + ldp x19, x20, [x1, #16] + ldp x21, x22, [x2] + ldp x23, x24, [x2, #16] + # A[0] * B[0] + mul x8, x16, x21 + umulh x9, x16, x21 + # A[0] * B[1] + mul x25, x16, x22 + umulh x10, x16, x22 + adds x9, x9, x25 + adc x10, x10, xzr + # A[1] * B[0] + mul x25, x17, x21 + umulh x26, x17, x21 + adds x9, x9, x25 + adcs x10, x10, x26 + adc x11, xzr, xzr + # A[0] * B[2] + mul x25, x16, x23 + umulh x26, x16, x23 + adds x10, x10, x25 + adc x11, x11, x26 + # A[1] * B[1] + mul x25, x17, x22 + umulh x26, x17, x22 + adds x10, x10, x25 + adcs x11, x11, x26 + adc x12, xzr, xzr + # A[2] * B[0] + mul x25, x19, x21 + umulh x26, x19, x21 + adds x10, x10, x25 + adcs x11, x11, x26 + adc x12, x12, xzr + # A[0] * B[3] + mul x25, x16, x24 + umulh x26, x16, x24 + adds x11, x11, x25 + adcs x12, x12, x26 + adc x13, xzr, xzr + # A[1] * B[2] + mul x25, x17, x23 + umulh x26, x17, x23 + adds x11, x11, x25 + adcs x12, x12, x26 + adc x13, x13, xzr + # A[2] * B[1] + mul x25, x19, x22 + umulh x26, x19, x22 + adds x11, x11, x25 + adcs x12, x12, x26 + adc x13, x13, xzr + # A[3] * B[0] + mul x25, x20, x21 + umulh x26, x20, x21 + adds x11, x11, x25 + adcs x12, x12, x26 + adc x13, x13, xzr + # A[1] * B[3] + mul x25, x17, x24 + umulh x26, x17, x24 + adds x12, x12, x25 + adcs x13, x13, x26 + adc x14, xzr, xzr + # A[2] * B[2] + mul x25, x19, x23 + umulh x26, x19, x23 + adds x12, x12, x25 + adcs x13, x13, x26 + adc x14, x14, xzr + # A[3] * B[1] + mul x25, x20, x22 + umulh x26, x20, x22 + adds x12, x12, x25 + adcs x13, x13, x26 + adc x14, x14, xzr + # A[2] * B[3] + mul x25, x19, x24 + umulh x26, x19, x24 + adds x13, x13, x25 + adcs x14, x14, x26 + adc x15, xzr, xzr + # A[3] * B[2] + mul x25, x20, x23 + umulh x26, x20, x23 + adds x13, x13, x25 + adcs x14, x14, x26 + adc x15, x15, xzr + # A[3] * B[3] + mul x25, x20, x24 + umulh x26, x20, x24 + adds x14, x14, x25 + adc x15, x15, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x15, x15, x14, #63 + extr x14, x14, x13, #63 + extr x13, x13, x12, #63 + extr x12, x12, x11, #63 + and x11, x11, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x12 + umulh x12, x25, x12 + adds x8, x8, x26 + mul x26, x25, x13 + umulh x13, x25, x13 + adcs x9, x9, x26 + mul x26, x25, x14 + umulh x14, x25, x14 + adcs x10, x10, x26 + mul x26, x25, x15 + umulh x27, x25, x15 + adcs x11, x11, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x9, x9, x12 + adcs x10, x10, x13 + adcs x11, x11, x14 + adc x27, x27, xzr + # Overflow + extr x27, x27, x11, #63 + mul x27, x27, x25 + and x11, x11, #0x7fffffffffffffff + adds x8, x8, x27 + adcs x9, x9, xzr + adcs x10, x10, xzr + adc x11, x11, xzr + # Reduce if top bit set + and x27, x25, x11, asr 63 + and x11, x11, #0x7fffffffffffffff + adds x8, x8, x27 + adcs x9, x9, xzr + adcs x10, x10, xzr + adc x11, x11, xzr + # Store + ldr x0, [x29, #32] + ldr x1, [x29, #40] + # Add + adds x12, x4, x8 + adcs x13, x5, x9 + adcs x14, x6, x10 + adc x15, x7, x11 + mov x25, #-19 + asr x28, x15, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x12, x12, x25 + sbcs x13, x13, x28 + sbcs x14, x14, x28 + sbc x15, x15, x26 + # Sub + subs x16, x4, x8 + sbcs x17, x5, x9 + sbcs x19, x6, x10 + sbcs x20, x7, x11 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x16, x16, x25 + adcs x17, x17, x28 + adcs x19, x19, x28 + adc x20, x20, x26 + stp x12, x13, [x0] + stp x14, x15, [x0, #16] + stp x16, x17, [x1] + stp x19, x20, [x1, #16] + ldr x17, [x29, #88] + ldr x19, [x29, #96] + ldp x20, x21, [x29, #104] + ldp x22, x23, [x29, #120] + ldp x24, x25, [x29, #136] + ldp x26, x27, [x29, #152] + ldr x28, [x29, #168] + ldp x29, x30, [sp], #0xb0 + ret + .size fe_ge_add,.-fe_ge_add + .text + .align 2 + .globl fe_ge_sub + .type fe_ge_sub, %function +fe_ge_sub: + stp x29, x30, [sp, #-176]! + add x29, sp, #0 + str x17, [x29, #88] + str x19, [x29, #96] + stp x20, x21, [x29, #104] + stp x22, x23, [x29, #120] + stp x24, x25, [x29, #136] + stp x26, x27, [x29, #152] + str x28, [x29, #168] + str x0, [x29, #16] + str x1, [x29, #24] + str x2, [x29, #32] + str x3, [x29, #40] + str x4, [x29, #48] + str x5, [x29, #56] + str x6, [x29, #64] + str x7, [x29, #72] + ldr x2, [x29, #56] + ldr x3, [x29, #48] + # Add + ldp x12, x13, [x2] + ldp x14, x15, [x2, #16] + ldp x16, x17, [x3] + ldp x19, x20, [x3, #16] + adds x4, x12, x16 + adcs x5, x13, x17 + adcs x6, x14, x19 + adc x7, x15, x20 + mov x25, #-19 + asr x28, x7, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x4, x4, x25 + sbcs x5, x5, x28 + sbcs x6, x6, x28 + sbc x7, x7, x26 + # Sub + subs x8, x12, x16 + sbcs x9, x13, x17 + sbcs x10, x14, x19 + sbcs x11, x15, x20 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x8, x8, x25 + adcs x9, x9, x28 + adcs x10, x10, x28 + adc x11, x11, x26 + ldr x0, [x29, #32] + ldr x2, [x29, #200] + # Multiply + ldp x21, x22, [x2] + ldp x23, x24, [x2, #16] + # A[0] * B[0] + mul x12, x4, x21 + umulh x13, x4, x21 + # A[0] * B[1] + mul x25, x4, x22 + umulh x14, x4, x22 + adds x13, x13, x25 + adc x14, x14, xzr + # A[1] * B[0] + mul x25, x5, x21 + umulh x26, x5, x21 + adds x13, x13, x25 + adcs x14, x14, x26 + adc x15, xzr, xzr + # A[0] * B[2] + mul x25, x4, x23 + umulh x26, x4, x23 + adds x14, x14, x25 + adc x15, x15, x26 + # A[1] * B[1] + mul x25, x5, x22 + umulh x26, x5, x22 + adds x14, x14, x25 + adcs x15, x15, x26 + adc x16, xzr, xzr + # A[2] * B[0] + mul x25, x6, x21 + umulh x26, x6, x21 + adds x14, x14, x25 + adcs x15, x15, x26 + adc x16, x16, xzr + # A[0] * B[3] + mul x25, x4, x24 + umulh x26, x4, x24 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, xzr, xzr + # A[1] * B[2] + mul x25, x5, x23 + umulh x26, x5, x23 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[2] * B[1] + mul x25, x6, x22 + umulh x26, x6, x22 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[3] * B[0] + mul x25, x7, x21 + umulh x26, x7, x21 + adds x15, x15, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[1] * B[3] + mul x25, x5, x24 + umulh x26, x5, x24 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, xzr, xzr + # A[2] * B[2] + mul x25, x6, x23 + umulh x26, x6, x23 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[3] * B[1] + mul x25, x7, x22 + umulh x26, x7, x22 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[2] * B[3] + mul x25, x6, x24 + umulh x26, x6, x24 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, xzr, xzr + # A[3] * B[2] + mul x25, x7, x23 + umulh x26, x7, x23 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, x20, xzr + # A[3] * B[3] + mul x25, x7, x24 + umulh x26, x7, x24 + adds x19, x19, x25 + adc x20, x20, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x20, x20, x19, #63 + extr x19, x19, x17, #63 + extr x17, x17, x16, #63 + extr x16, x16, x15, #63 + and x15, x15, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x16 + umulh x16, x25, x16 + adds x12, x12, x26 + mul x26, x25, x17 + umulh x17, x25, x17 + adcs x13, x13, x26 + mul x26, x25, x19 + umulh x19, x25, x19 + adcs x14, x14, x26 + mul x26, x25, x20 + umulh x27, x25, x20 + adcs x15, x15, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x13, x13, x16 + adcs x14, x14, x17 + adcs x15, x15, x19 + adc x27, x27, xzr + # Overflow + extr x27, x27, x15, #63 + mul x27, x27, x25 + and x15, x15, #0x7fffffffffffffff + adds x12, x12, x27 + adcs x13, x13, xzr + adcs x14, x14, xzr + adc x15, x15, xzr + # Reduce if top bit set + and x27, x25, x15, asr 63 + and x15, x15, #0x7fffffffffffffff + adds x12, x12, x27 + adcs x13, x13, xzr + adcs x14, x14, xzr + adc x15, x15, xzr + # Store + ldr x0, [x29, #24] + ldr x1, [x29, #192] + # Multiply + ldp x21, x22, [x1] + ldp x23, x24, [x1, #16] + # A[0] * B[0] + mul x4, x8, x21 + umulh x5, x8, x21 + # A[0] * B[1] + mul x25, x8, x22 + umulh x6, x8, x22 + adds x5, x5, x25 + adc x6, x6, xzr + # A[1] * B[0] + mul x25, x9, x21 + umulh x26, x9, x21 + adds x5, x5, x25 + adcs x6, x6, x26 + adc x7, xzr, xzr + # A[0] * B[2] + mul x25, x8, x23 + umulh x26, x8, x23 + adds x6, x6, x25 + adc x7, x7, x26 + # A[1] * B[1] + mul x25, x9, x22 + umulh x26, x9, x22 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x16, xzr, xzr + # A[2] * B[0] + mul x25, x10, x21 + umulh x26, x10, x21 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x16, x16, xzr + # A[0] * B[3] + mul x25, x8, x24 + umulh x26, x8, x24 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, xzr, xzr + # A[1] * B[2] + mul x25, x9, x23 + umulh x26, x9, x23 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[2] * B[1] + mul x25, x10, x22 + umulh x26, x10, x22 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[3] * B[0] + mul x25, x11, x21 + umulh x26, x11, x21 + adds x7, x7, x25 + adcs x16, x16, x26 + adc x17, x17, xzr + # A[1] * B[3] + mul x25, x9, x24 + umulh x26, x9, x24 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, xzr, xzr + # A[2] * B[2] + mul x25, x10, x23 + umulh x26, x10, x23 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[3] * B[1] + mul x25, x11, x22 + umulh x26, x11, x22 + adds x16, x16, x25 + adcs x17, x17, x26 + adc x19, x19, xzr + # A[2] * B[3] + mul x25, x10, x24 + umulh x26, x10, x24 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, xzr, xzr + # A[3] * B[2] + mul x25, x11, x23 + umulh x26, x11, x23 + adds x17, x17, x25 + adcs x19, x19, x26 + adc x20, x20, xzr + # A[3] * B[3] + mul x25, x11, x24 + umulh x26, x11, x24 + adds x19, x19, x25 + adc x20, x20, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x20, x20, x19, #63 + extr x19, x19, x17, #63 + extr x17, x17, x16, #63 + extr x16, x16, x7, #63 + and x7, x7, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x16 + umulh x16, x25, x16 + adds x4, x4, x26 + mul x26, x25, x17 + umulh x17, x25, x17 + adcs x5, x5, x26 + mul x26, x25, x19 + umulh x19, x25, x19 + adcs x6, x6, x26 + mul x26, x25, x20 + umulh x27, x25, x20 + adcs x7, x7, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x5, x5, x16 + adcs x6, x6, x17 + adcs x7, x7, x19 + adc x27, x27, xzr + # Overflow + extr x27, x27, x7, #63 + mul x27, x27, x25 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Reduce if top bit set + and x27, x25, x7, asr 63 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Store + ldr x0, [x29, #24] + ldr x1, [x29, #16] + # Add + adds x8, x12, x4 + adcs x9, x13, x5 + adcs x10, x14, x6 + adc x11, x15, x7 + mov x25, #-19 + asr x28, x11, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x8, x8, x25 + sbcs x9, x9, x28 + sbcs x10, x10, x28 + sbc x11, x11, x26 + # Sub + subs x16, x12, x4 + sbcs x17, x13, x5 + sbcs x19, x14, x6 + sbcs x20, x15, x7 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x16, x16, x25 + adcs x17, x17, x28 + adcs x19, x19, x28 + adc x20, x20, x26 + stp x8, x9, [x0] + stp x10, x11, [x0, #16] + stp x16, x17, [x1] + stp x19, x20, [x1, #16] + ldr x0, [x29, #48] + ldr x1, [x29, #64] + ldr x2, [x29, #176] + # Multiply + ldp x12, x13, [x1] + ldp x14, x15, [x1, #16] + ldp x16, x17, [x2] + ldp x19, x20, [x2, #16] + # A[0] * B[0] + mul x4, x12, x16 + umulh x5, x12, x16 + # A[0] * B[1] + mul x25, x12, x17 + umulh x6, x12, x17 + adds x5, x5, x25 + adc x6, x6, xzr + # A[1] * B[0] + mul x25, x13, x16 + umulh x26, x13, x16 + adds x5, x5, x25 + adcs x6, x6, x26 + adc x7, xzr, xzr + # A[0] * B[2] + mul x25, x12, x19 + umulh x26, x12, x19 + adds x6, x6, x25 + adc x7, x7, x26 + # A[1] * B[1] + mul x25, x13, x17 + umulh x26, x13, x17 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x8, xzr, xzr + # A[2] * B[0] + mul x25, x14, x16 + umulh x26, x14, x16 + adds x6, x6, x25 + adcs x7, x7, x26 + adc x8, x8, xzr + # A[0] * B[3] + mul x25, x12, x20 + umulh x26, x12, x20 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, xzr, xzr + # A[1] * B[2] + mul x25, x13, x19 + umulh x26, x13, x19 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, x9, xzr + # A[2] * B[1] + mul x25, x14, x17 + umulh x26, x14, x17 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, x9, xzr + # A[3] * B[0] + mul x25, x15, x16 + umulh x26, x15, x16 + adds x7, x7, x25 + adcs x8, x8, x26 + adc x9, x9, xzr + # A[1] * B[3] + mul x25, x13, x20 + umulh x26, x13, x20 + adds x8, x8, x25 + adcs x9, x9, x26 + adc x10, xzr, xzr + # A[2] * B[2] + mul x25, x14, x19 + umulh x26, x14, x19 + adds x8, x8, x25 + adcs x9, x9, x26 + adc x10, x10, xzr + # A[3] * B[1] + mul x25, x15, x17 + umulh x26, x15, x17 + adds x8, x8, x25 + adcs x9, x9, x26 + adc x10, x10, xzr + # A[2] * B[3] + mul x25, x14, x20 + umulh x26, x14, x20 + adds x9, x9, x25 + adcs x10, x10, x26 + adc x11, xzr, xzr + # A[3] * B[2] + mul x25, x15, x19 + umulh x26, x15, x19 + adds x9, x9, x25 + adcs x10, x10, x26 + adc x11, x11, xzr + # A[3] * B[3] + mul x25, x15, x20 + umulh x26, x15, x20 + adds x10, x10, x25 + adc x11, x11, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x11, x11, x10, #63 + extr x10, x10, x9, #63 + extr x9, x9, x8, #63 + extr x8, x8, x7, #63 + and x7, x7, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x8 + umulh x8, x25, x8 + adds x4, x4, x26 + mul x26, x25, x9 + umulh x9, x25, x9 + adcs x5, x5, x26 + mul x26, x25, x10 + umulh x10, x25, x10 + adcs x6, x6, x26 + mul x26, x25, x11 + umulh x27, x25, x11 + adcs x7, x7, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x5, x5, x8 + adcs x6, x6, x9 + adcs x7, x7, x10 + adc x27, x27, xzr + # Overflow + extr x27, x27, x7, #63 + mul x27, x27, x25 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Reduce if top bit set + and x27, x25, x7, asr 63 + and x7, x7, #0x7fffffffffffffff + adds x4, x4, x27 + adcs x5, x5, xzr + adcs x6, x6, xzr + adc x7, x7, xzr + # Store + ldr x0, [x29, #48] + # Double + adds x4, x4, x4 + adcs x5, x5, x5 + adcs x6, x6, x6 + adc x7, x7, x7 + mov x25, #-19 + asr x28, x7, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x4, x4, x25 + sbcs x5, x5, x28 + sbcs x6, x6, x28 + sbc x7, x7, x26 + ldr x0, [x29, #40] + ldr x1, [x29, #184] + ldr x2, [x29, #72] + # Multiply + ldp x16, x17, [x1] + ldp x19, x20, [x1, #16] + ldp x21, x22, [x2] + ldp x23, x24, [x2, #16] + # A[0] * B[0] + mul x8, x16, x21 + umulh x9, x16, x21 + # A[0] * B[1] + mul x25, x16, x22 + umulh x10, x16, x22 + adds x9, x9, x25 + adc x10, x10, xzr + # A[1] * B[0] + mul x25, x17, x21 + umulh x26, x17, x21 + adds x9, x9, x25 + adcs x10, x10, x26 + adc x11, xzr, xzr + # A[0] * B[2] + mul x25, x16, x23 + umulh x26, x16, x23 + adds x10, x10, x25 + adc x11, x11, x26 + # A[1] * B[1] + mul x25, x17, x22 + umulh x26, x17, x22 + adds x10, x10, x25 + adcs x11, x11, x26 + adc x12, xzr, xzr + # A[2] * B[0] + mul x25, x19, x21 + umulh x26, x19, x21 + adds x10, x10, x25 + adcs x11, x11, x26 + adc x12, x12, xzr + # A[0] * B[3] + mul x25, x16, x24 + umulh x26, x16, x24 + adds x11, x11, x25 + adcs x12, x12, x26 + adc x13, xzr, xzr + # A[1] * B[2] + mul x25, x17, x23 + umulh x26, x17, x23 + adds x11, x11, x25 + adcs x12, x12, x26 + adc x13, x13, xzr + # A[2] * B[1] + mul x25, x19, x22 + umulh x26, x19, x22 + adds x11, x11, x25 + adcs x12, x12, x26 + adc x13, x13, xzr + # A[3] * B[0] + mul x25, x20, x21 + umulh x26, x20, x21 + adds x11, x11, x25 + adcs x12, x12, x26 + adc x13, x13, xzr + # A[1] * B[3] + mul x25, x17, x24 + umulh x26, x17, x24 + adds x12, x12, x25 + adcs x13, x13, x26 + adc x14, xzr, xzr + # A[2] * B[2] + mul x25, x19, x23 + umulh x26, x19, x23 + adds x12, x12, x25 + adcs x13, x13, x26 + adc x14, x14, xzr + # A[3] * B[1] + mul x25, x20, x22 + umulh x26, x20, x22 + adds x12, x12, x25 + adcs x13, x13, x26 + adc x14, x14, xzr + # A[2] * B[3] + mul x25, x19, x24 + umulh x26, x19, x24 + adds x13, x13, x25 + adcs x14, x14, x26 + adc x15, xzr, xzr + # A[3] * B[2] + mul x25, x20, x23 + umulh x26, x20, x23 + adds x13, x13, x25 + adcs x14, x14, x26 + adc x15, x15, xzr + # A[3] * B[3] + mul x25, x20, x24 + umulh x26, x20, x24 + adds x14, x14, x25 + adc x15, x15, x26 + # Reduce + # Move top half into t4-t7 and remove top bit from t3 + extr x15, x15, x14, #63 + extr x14, x14, x13, #63 + extr x13, x13, x12, #63 + extr x12, x12, x11, #63 + and x11, x11, #0x7fffffffffffffff + # Multiply top half by 19 + mov x25, #19 + mul x26, x25, x12 + umulh x12, x25, x12 + adds x8, x8, x26 + mul x26, x25, x13 + umulh x13, x25, x13 + adcs x9, x9, x26 + mul x26, x25, x14 + umulh x14, x25, x14 + adcs x10, x10, x26 + mul x26, x25, x15 + umulh x27, x25, x15 + adcs x11, x11, x26 + adc x27, x27, xzr + # Add remaining product results in + adds x9, x9, x12 + adcs x10, x10, x13 + adcs x11, x11, x14 + adc x27, x27, xzr + # Overflow + extr x27, x27, x11, #63 + mul x27, x27, x25 + and x11, x11, #0x7fffffffffffffff + adds x8, x8, x27 + adcs x9, x9, xzr + adcs x10, x10, xzr + adc x11, x11, xzr + # Reduce if top bit set + and x27, x25, x11, asr 63 + and x11, x11, #0x7fffffffffffffff + adds x8, x8, x27 + adcs x9, x9, xzr + adcs x10, x10, xzr + adc x11, x11, xzr + # Store + ldr x0, [x29, #40] + ldr x1, [x29, #32] + # Add + adds x12, x4, x8 + adcs x13, x5, x9 + adcs x14, x6, x10 + adc x15, x7, x11 + mov x25, #-19 + asr x28, x15, #63 + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Sub modulus (if overflow) + subs x12, x12, x25 + sbcs x13, x13, x28 + sbcs x14, x14, x28 + sbc x15, x15, x26 + # Sub + subs x16, x4, x8 + sbcs x17, x5, x9 + sbcs x19, x6, x10 + sbcs x20, x7, x11 + mov x25, #-19 + csetm x28, cc + # Mask the modulus + and x25, x28, x25 + and x26, x28, #0x7fffffffffffffff + # Add modulus (if underflow) + adds x16, x16, x25 + adcs x17, x17, x28 + adcs x19, x19, x28 + adc x20, x20, x26 + stp x12, x13, [x0] + stp x14, x15, [x0, #16] + stp x16, x17, [x1] + stp x19, x20, [x1, #16] + ldr x17, [x29, #88] + ldr x19, [x29, #96] + ldp x20, x21, [x29, #104] + ldp x22, x23, [x29, #120] + ldp x24, x25, [x29, #136] + ldp x26, x27, [x29, #152] + ldr x28, [x29, #168] + ldp x29, x30, [sp], #0xb0 + ret + .size fe_ge_sub,.-fe_ge_sub +#endif /* __aarch64__ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-curve25519.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-curve25519.c new file mode 100644 index 000000000..d1ab4c89c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-curve25519.c @@ -0,0 +1,6725 @@ +/* armv8-curve25519 + * + * Copyright (C) 2006-2020 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 + */ + +/* Generated using (from wolfssl): + * cd ../scripts + * ruby ./x25519/x25519.rb arm64 ../wolfssl/wolfcrypt/src/port/arm/armv8-curve25519.c + */ +#ifdef __aarch64__ +#include +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_ARMASM +#include +#include + +void fe_init() +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + "\n\t" + "ldp x29, x30, [sp], #16\n\t" + : + : + : "memory" + ); +} + +void fe_frombytes(fe out, const unsigned char* in) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + "ldp x2, x3, [%x[in]]\n\t" + "ldp x4, x5, [%x[in], #16]\n\t" + "and x5, x5, #0x7fffffffffffffff\n\t" + "stp x2, x3, [%x[out]]\n\t" + "stp x4, x5, [%x[out], #16]\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [out] "+r" (out), [in] "+r" (in) + : + : "memory", "x2", "x3", "x4", "x5", "x6" + ); +} + +void fe_tobytes(unsigned char* out, const fe n) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + "mov x7, #19\n\t" + "ldp x2, x3, [%x[n]]\n\t" + "ldp x4, x5, [%x[n], #16]\n\t" + "adds x6, x2, x7\n\t" + "adcs x6, x3, xzr\n\t" + "adcs x6, x4, xzr\n\t" + "adc x6, x5, xzr\n\t" + "and x6, x7, x6, asr 63\n\t" + "adds x2, x2, x6\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adc x5, x5, xzr\n\t" + "and x5, x5, #0x7fffffffffffffff\n\t" + "stp x2, x3, [%x[out]]\n\t" + "stp x4, x5, [%x[out], #16]\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [out] "+r" (out), [n] "+r" (n) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7" + ); +} + +void fe_1(fe n) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + /* Set one */ + "mov x1, #1\n\t" + "stp x1, xzr, [%x[n]]\n\t" + "stp xzr, xzr, [%x[n], #16]\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [n] "+r" (n) + : + : "memory", "x1" + ); +} + +void fe_0(fe n) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + /* Set zero */ + "stp xzr, xzr, [%x[n]]\n\t" + "stp xzr, xzr, [%x[n], #16]\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [n] "+r" (n) + : + : "memory" + ); +} + +void fe_copy(fe r, const fe a) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + /* Copy */ + "ldp x2, x3, [%x[a]]\n\t" + "ldp x4, x5, [%x[a], #16]\n\t" + "stp x2, x3, [%x[r]]\n\t" + "stp x4, x5, [%x[r], #16]\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [r] "+r" (r), [a] "+r" (a) + : + : "memory", "x2", "x3", "x4", "x5" + ); +} + +void fe_sub(fe r, const fe a, const fe b) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + /* Sub */ + "ldp x3, x4, [%x[a]]\n\t" + "ldp x5, x6, [%x[a], #16]\n\t" + "ldp x7, x8, [%x[b]]\n\t" + "ldp x9, x10, [%x[b], #16]\n\t" + "subs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "sbcs x6, x6, x10\n\t" + "mov x12, #-19\n\t" + "csetm x11, cc\n\t" + /* Mask the modulus */ + "and x12, x11, x12\n\t" + "and x13, x11, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x3, x3, x12\n\t" + "adcs x4, x4, x11\n\t" + "adcs x5, x5, x11\n\t" + "adc x6, x6, x13\n\t" + "stp x3, x4, [%x[r]]\n\t" + "stp x5, x6, [%x[r], #16]\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13" + ); +} + +void fe_add(fe r, const fe a, const fe b) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + /* Add */ + "ldp x3, x4, [%x[a]]\n\t" + "ldp x5, x6, [%x[a], #16]\n\t" + "ldp x7, x8, [%x[b]]\n\t" + "ldp x9, x10, [%x[b], #16]\n\t" + "adds x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adc x6, x6, x10\n\t" + "mov x12, #-19\n\t" + "asr x11, x6, #63\n\t" + /* Mask the modulus */ + "and x12, x11, x12\n\t" + "and x13, x11, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x3, x3, x12\n\t" + "sbcs x4, x4, x11\n\t" + "sbcs x5, x5, x11\n\t" + "sbc x6, x6, x13\n\t" + "stp x3, x4, [%x[r]]\n\t" + "stp x5, x6, [%x[r], #16]\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13" + ); +} + +void fe_neg(fe r, const fe a) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + "ldp x2, x3, [%x[a]]\n\t" + "ldp x4, x5, [%x[a], #16]\n\t" + "mov x6, #-19\n\t" + "mov x7, #-1\n\t" + "mov x8, #-1\n\t" + "mov x9, #0x7fffffffffffffff\n\t" + "subs x6, x6, x2\n\t" + "sbcs x7, x7, x3\n\t" + "sbcs x8, x8, x4\n\t" + "sbc x9, x9, x5\n\t" + "stp x6, x7, [%x[r]]\n\t" + "stp x8, x9, [%x[r], #16]\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [r] "+r" (r), [a] "+r" (a) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +} + +int fe_isnonzero(const fe a) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + "mov x6, #19\n\t" + "ldp x1, x2, [%x[a]]\n\t" + "ldp x3, x4, [%x[a], #16]\n\t" + "adds x5, x1, x6\n\t" + "adcs x5, x2, xzr\n\t" + "adcs x5, x3, xzr\n\t" + "adc x5, x4, xzr\n\t" + "and x5, x6, x5, asr 63\n\t" + "adds x1, x1, x5\n\t" + "adcs x2, x2, xzr\n\t" + "adcs x3, x3, xzr\n\t" + "adc x4, x4, xzr\n\t" + "and x4, x4, #0x7fffffffffffffff\n\t" + "orr %x[a], x1, x2\n\t" + "orr x3, x3, x4\n\t" + "orr %x[a], %x[a], x3\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [a] "+r" (a) + : + : "memory", "x1", "x2", "x3", "x4", "x5", "x6" + ); + return (uint32_t)(size_t)a; +} + +int fe_isnegative(const fe a) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + "mov x6, #19\n\t" + "ldp x1, x2, [%x[a]]\n\t" + "ldp x3, x4, [%x[a], #16]\n\t" + "adds x5, x1, x6\n\t" + "adcs x5, x2, xzr\n\t" + "adcs x5, x3, xzr\n\t" + "adc x5, x4, xzr\n\t" + "and %x[a], x1, #1\n\t" + "eor %x[a], %x[a], x5, lsr 63\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [a] "+r" (a) + : + : "memory", "x1", "x2", "x3", "x4", "x5", "x6" + ); + return (uint32_t)(size_t)a; +} + +void fe_cmov_table(fe* r, fe* base, signed char b) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-32]!\n\t" + "add x29, sp, #0\n\t" + "str %x[r], [x29, #16]\n\t" + "sxtb %x[b], %w[b]\n\t" + "sbfx x3, %x[b], #7, #1\n\t" + "eor %x[r], %x[b], x3\n\t" + "sub %x[r], %x[r], x3\n\t" + "mov x4, #1\n\t" + "mov x5, xzr\n\t" + "mov x6, xzr\n\t" + "mov x7, xzr\n\t" + "mov x8, #1\n\t" + "mov x9, xzr\n\t" + "mov x10, xzr\n\t" + "mov x11, xzr\n\t" + "mov x12, xzr\n\t" + "mov x13, xzr\n\t" + "mov x14, xzr\n\t" + "mov x15, xzr\n\t" + "cmp %x[r], #1\n\t" + "ldp x16, x17, [%x[base]]\n\t" + "ldp x19, x20, [%x[base], #16]\n\t" + "ldp x21, x22, [%x[base], #32]\n\t" + "ldp x23, x24, [%x[base], #48]\n\t" + "ldp x25, x26, [%x[base], #64]\n\t" + "ldp x27, x28, [%x[base], #80]\n\t" + "csel x4, x16, x4, eq\n\t" + "csel x5, x17, x5, eq\n\t" + "csel x6, x19, x6, eq\n\t" + "csel x7, x20, x7, eq\n\t" + "csel x8, x21, x8, eq\n\t" + "csel x9, x22, x9, eq\n\t" + "csel x10, x23, x10, eq\n\t" + "csel x11, x24, x11, eq\n\t" + "csel x12, x25, x12, eq\n\t" + "csel x13, x26, x13, eq\n\t" + "csel x14, x27, x14, eq\n\t" + "csel x15, x28, x15, eq\n\t" + "cmp %x[r], #2\n\t" + "ldp x16, x17, [%x[base], #96]\n\t" + "ldp x19, x20, [%x[base], #112]\n\t" + "ldp x21, x22, [%x[base], #128]\n\t" + "ldp x23, x24, [%x[base], #144]\n\t" + "ldp x25, x26, [%x[base], #160]\n\t" + "ldp x27, x28, [%x[base], #176]\n\t" + "csel x4, x16, x4, eq\n\t" + "csel x5, x17, x5, eq\n\t" + "csel x6, x19, x6, eq\n\t" + "csel x7, x20, x7, eq\n\t" + "csel x8, x21, x8, eq\n\t" + "csel x9, x22, x9, eq\n\t" + "csel x10, x23, x10, eq\n\t" + "csel x11, x24, x11, eq\n\t" + "csel x12, x25, x12, eq\n\t" + "csel x13, x26, x13, eq\n\t" + "csel x14, x27, x14, eq\n\t" + "csel x15, x28, x15, eq\n\t" + "cmp %x[r], #3\n\t" + "ldp x16, x17, [%x[base], #192]\n\t" + "ldp x19, x20, [%x[base], #208]\n\t" + "ldp x21, x22, [%x[base], #224]\n\t" + "ldp x23, x24, [%x[base], #240]\n\t" + "ldp x25, x26, [%x[base], #256]\n\t" + "ldp x27, x28, [%x[base], #272]\n\t" + "csel x4, x16, x4, eq\n\t" + "csel x5, x17, x5, eq\n\t" + "csel x6, x19, x6, eq\n\t" + "csel x7, x20, x7, eq\n\t" + "csel x8, x21, x8, eq\n\t" + "csel x9, x22, x9, eq\n\t" + "csel x10, x23, x10, eq\n\t" + "csel x11, x24, x11, eq\n\t" + "csel x12, x25, x12, eq\n\t" + "csel x13, x26, x13, eq\n\t" + "csel x14, x27, x14, eq\n\t" + "csel x15, x28, x15, eq\n\t" + "cmp %x[r], #4\n\t" + "ldp x16, x17, [%x[base], #288]\n\t" + "ldp x19, x20, [%x[base], #304]\n\t" + "ldp x21, x22, [%x[base], #320]\n\t" + "ldp x23, x24, [%x[base], #336]\n\t" + "ldp x25, x26, [%x[base], #352]\n\t" + "ldp x27, x28, [%x[base], #368]\n\t" + "csel x4, x16, x4, eq\n\t" + "csel x5, x17, x5, eq\n\t" + "csel x6, x19, x6, eq\n\t" + "csel x7, x20, x7, eq\n\t" + "csel x8, x21, x8, eq\n\t" + "csel x9, x22, x9, eq\n\t" + "csel x10, x23, x10, eq\n\t" + "csel x11, x24, x11, eq\n\t" + "csel x12, x25, x12, eq\n\t" + "csel x13, x26, x13, eq\n\t" + "csel x14, x27, x14, eq\n\t" + "csel x15, x28, x15, eq\n\t" + "add %x[base], %x[base], #0x180\n\t" + "cmp %x[r], #5\n\t" + "ldp x16, x17, [%x[base]]\n\t" + "ldp x19, x20, [%x[base], #16]\n\t" + "ldp x21, x22, [%x[base], #32]\n\t" + "ldp x23, x24, [%x[base], #48]\n\t" + "ldp x25, x26, [%x[base], #64]\n\t" + "ldp x27, x28, [%x[base], #80]\n\t" + "csel x4, x16, x4, eq\n\t" + "csel x5, x17, x5, eq\n\t" + "csel x6, x19, x6, eq\n\t" + "csel x7, x20, x7, eq\n\t" + "csel x8, x21, x8, eq\n\t" + "csel x9, x22, x9, eq\n\t" + "csel x10, x23, x10, eq\n\t" + "csel x11, x24, x11, eq\n\t" + "csel x12, x25, x12, eq\n\t" + "csel x13, x26, x13, eq\n\t" + "csel x14, x27, x14, eq\n\t" + "csel x15, x28, x15, eq\n\t" + "cmp %x[r], #6\n\t" + "ldp x16, x17, [%x[base], #96]\n\t" + "ldp x19, x20, [%x[base], #112]\n\t" + "ldp x21, x22, [%x[base], #128]\n\t" + "ldp x23, x24, [%x[base], #144]\n\t" + "ldp x25, x26, [%x[base], #160]\n\t" + "ldp x27, x28, [%x[base], #176]\n\t" + "csel x4, x16, x4, eq\n\t" + "csel x5, x17, x5, eq\n\t" + "csel x6, x19, x6, eq\n\t" + "csel x7, x20, x7, eq\n\t" + "csel x8, x21, x8, eq\n\t" + "csel x9, x22, x9, eq\n\t" + "csel x10, x23, x10, eq\n\t" + "csel x11, x24, x11, eq\n\t" + "csel x12, x25, x12, eq\n\t" + "csel x13, x26, x13, eq\n\t" + "csel x14, x27, x14, eq\n\t" + "csel x15, x28, x15, eq\n\t" + "cmp %x[r], #7\n\t" + "ldp x16, x17, [%x[base], #192]\n\t" + "ldp x19, x20, [%x[base], #208]\n\t" + "ldp x21, x22, [%x[base], #224]\n\t" + "ldp x23, x24, [%x[base], #240]\n\t" + "ldp x25, x26, [%x[base], #256]\n\t" + "ldp x27, x28, [%x[base], #272]\n\t" + "csel x4, x16, x4, eq\n\t" + "csel x5, x17, x5, eq\n\t" + "csel x6, x19, x6, eq\n\t" + "csel x7, x20, x7, eq\n\t" + "csel x8, x21, x8, eq\n\t" + "csel x9, x22, x9, eq\n\t" + "csel x10, x23, x10, eq\n\t" + "csel x11, x24, x11, eq\n\t" + "csel x12, x25, x12, eq\n\t" + "csel x13, x26, x13, eq\n\t" + "csel x14, x27, x14, eq\n\t" + "csel x15, x28, x15, eq\n\t" + "cmp %x[r], #8\n\t" + "ldp x16, x17, [%x[base], #288]\n\t" + "ldp x19, x20, [%x[base], #304]\n\t" + "ldp x21, x22, [%x[base], #320]\n\t" + "ldp x23, x24, [%x[base], #336]\n\t" + "ldp x25, x26, [%x[base], #352]\n\t" + "ldp x27, x28, [%x[base], #368]\n\t" + "csel x4, x16, x4, eq\n\t" + "csel x5, x17, x5, eq\n\t" + "csel x6, x19, x6, eq\n\t" + "csel x7, x20, x7, eq\n\t" + "csel x8, x21, x8, eq\n\t" + "csel x9, x22, x9, eq\n\t" + "csel x10, x23, x10, eq\n\t" + "csel x11, x24, x11, eq\n\t" + "csel x12, x25, x12, eq\n\t" + "csel x13, x26, x13, eq\n\t" + "csel x14, x27, x14, eq\n\t" + "csel x15, x28, x15, eq\n\t" + "mov x16, #-19\n\t" + "mov x17, #-1\n\t" + "mov x19, #-1\n\t" + "mov x20, #0x7fffffffffffffff\n\t" + "subs x16, x16, x12\n\t" + "sbcs x17, x17, x13\n\t" + "sbcs x19, x19, x14\n\t" + "sbc x20, x20, x15\n\t" + "cmp %x[b], #0\n\t" + "mov x3, x4\n\t" + "csel x4, x8, x4, lt\n\t" + "csel x8, x3, x8, lt\n\t" + "mov x3, x5\n\t" + "csel x5, x9, x5, lt\n\t" + "csel x9, x3, x9, lt\n\t" + "mov x3, x6\n\t" + "csel x6, x10, x6, lt\n\t" + "csel x10, x3, x10, lt\n\t" + "mov x3, x7\n\t" + "csel x7, x11, x7, lt\n\t" + "csel x11, x3, x11, lt\n\t" + "csel x12, x16, x12, lt\n\t" + "csel x13, x17, x13, lt\n\t" + "csel x14, x19, x14, lt\n\t" + "csel x15, x20, x15, lt\n\t" + "ldr %x[r], [x29, #16]\n\t" + "stp x4, x5, [%x[r]]\n\t" + "stp x6, x7, [%x[r], #16]\n\t" + "stp x8, x9, [%x[r], #32]\n\t" + "stp x10, x11, [%x[r], #48]\n\t" + "stp x12, x13, [%x[r], #64]\n\t" + "stp x14, x15, [%x[r], #80]\n\t" + "ldp x29, x30, [sp], #32\n\t" + : [r] "+r" (r), [base] "+r" (base), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); +} + +void fe_mul(fe r, const fe a, const fe b) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + /* Multiply */ + "ldp x14, x15, [%x[a]]\n\t" + "ldp x16, x17, [%x[a], #16]\n\t" + "ldp x19, x20, [%x[b]]\n\t" + "ldp x21, x22, [%x[b], #16]\n\t" + /* A[0] * B[0] */ + "mul x6, x14, x19\n\t" + "umulh x7, x14, x19\n\t" + /* A[0] * B[1] */ + "mul x3, x14, x20\n\t" + "umulh x8, x14, x20\n\t" + "adds x7, x7, x3\n\t" + "adc x8, x8, xzr\n\t" + /* A[1] * B[0] */ + "mul x3, x15, x19\n\t" + "umulh x4, x15, x19\n\t" + "adds x7, x7, x3\n\t" + "adcs x8, x8, x4\n\t" + "adc x9, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x3, x14, x21\n\t" + "umulh x4, x14, x21\n\t" + "adds x8, x8, x3\n\t" + "adc x9, x9, x4\n\t" + /* A[1] * B[1] */ + "mul x3, x15, x20\n\t" + "umulh x4, x15, x20\n\t" + "adds x8, x8, x3\n\t" + "adcs x9, x9, x4\n\t" + "adc x10, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x3, x16, x19\n\t" + "umulh x4, x16, x19\n\t" + "adds x8, x8, x3\n\t" + "adcs x9, x9, x4\n\t" + "adc x10, x10, xzr\n\t" + /* A[0] * B[3] */ + "mul x3, x14, x22\n\t" + "umulh x4, x14, x22\n\t" + "adds x9, x9, x3\n\t" + "adcs x10, x10, x4\n\t" + "adc x11, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x3, x15, x21\n\t" + "umulh x4, x15, x21\n\t" + "adds x9, x9, x3\n\t" + "adcs x10, x10, x4\n\t" + "adc x11, x11, xzr\n\t" + /* A[2] * B[1] */ + "mul x3, x16, x20\n\t" + "umulh x4, x16, x20\n\t" + "adds x9, x9, x3\n\t" + "adcs x10, x10, x4\n\t" + "adc x11, x11, xzr\n\t" + /* A[3] * B[0] */ + "mul x3, x17, x19\n\t" + "umulh x4, x17, x19\n\t" + "adds x9, x9, x3\n\t" + "adcs x10, x10, x4\n\t" + "adc x11, x11, xzr\n\t" + /* A[1] * B[3] */ + "mul x3, x15, x22\n\t" + "umulh x4, x15, x22\n\t" + "adds x10, x10, x3\n\t" + "adcs x11, x11, x4\n\t" + "adc x12, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x3, x16, x21\n\t" + "umulh x4, x16, x21\n\t" + "adds x10, x10, x3\n\t" + "adcs x11, x11, x4\n\t" + "adc x12, x12, xzr\n\t" + /* A[3] * B[1] */ + "mul x3, x17, x20\n\t" + "umulh x4, x17, x20\n\t" + "adds x10, x10, x3\n\t" + "adcs x11, x11, x4\n\t" + "adc x12, x12, xzr\n\t" + /* A[2] * B[3] */ + "mul x3, x16, x22\n\t" + "umulh x4, x16, x22\n\t" + "adds x11, x11, x3\n\t" + "adcs x12, x12, x4\n\t" + "adc x13, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x3, x17, x21\n\t" + "umulh x4, x17, x21\n\t" + "adds x11, x11, x3\n\t" + "adcs x12, x12, x4\n\t" + "adc x13, x13, xzr\n\t" + /* A[3] * B[3] */ + "mul x3, x17, x22\n\t" + "umulh x4, x17, x22\n\t" + "adds x12, x12, x3\n\t" + "adc x13, x13, x4\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x13, x13, x12, #63\n\t" + "extr x12, x12, x11, #63\n\t" + "extr x11, x11, x10, #63\n\t" + "extr x10, x10, x9, #63\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x3, #19\n\t" + "mul x4, x3, x10\n\t" + "umulh x10, x3, x10\n\t" + "adds x6, x6, x4\n\t" + "mul x4, x3, x11\n\t" + "umulh x11, x3, x11\n\t" + "adcs x7, x7, x4\n\t" + "mul x4, x3, x12\n\t" + "umulh x12, x3, x12\n\t" + "adcs x8, x8, x4\n\t" + "mul x4, x3, x13\n\t" + "umulh x5, x3, x13\n\t" + "adcs x9, x9, x4\n\t" + "adc x5, x5, xzr\n\t" + /* Add remaining product results in */ + "adds x7, x7, x10\n\t" + "adcs x8, x8, x11\n\t" + "adcs x9, x9, x12\n\t" + "adc x5, x5, xzr\n\t" + /* Overflow */ + "extr x5, x5, x9, #63\n\t" + "mul x5, x5, x3\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + "adds x6, x6, x5\n\t" + "adcs x7, x7, xzr\n\t" + "adcs x8, x8, xzr\n\t" + "adc x9, x9, xzr\n\t" + /* Reduce if top bit set */ + "and x5, x3, x9, asr 63\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + "adds x6, x6, x5\n\t" + "adcs x7, x7, xzr\n\t" + "adcs x8, x8, xzr\n\t" + "adc x9, x9, xzr\n\t" + /* Store */ + "stp x6, x7, [%x[r]]\n\t" + "stp x8, x9, [%x[r], #16]\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22" + ); +} + +void fe_sq(fe r, const fe a) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + /* Square */ + "ldp x13, x14, [%x[a]]\n\t" + "ldp x15, x16, [%x[a], #16]\n\t" + /* A[0] * A[1] */ + "mul x6, x13, x14\n\t" + "umulh x7, x13, x14\n\t" + /* A[0] * A[2] */ + "mul x2, x13, x15\n\t" + "umulh x8, x13, x15\n\t" + "adds x7, x7, x2\n\t" + "adc x8, x8, xzr\n\t" + /* A[0] * A[3] */ + "mul x2, x13, x16\n\t" + "umulh x9, x13, x16\n\t" + "adds x8, x8, x2\n\t" + "adc x9, x9, xzr\n\t" + /* A[1] * A[2] */ + "mul x2, x14, x15\n\t" + "umulh x3, x14, x15\n\t" + "adds x8, x8, x2\n\t" + "adcs x9, x9, x3\n\t" + "adc x10, xzr, xzr\n\t" + /* A[1] * A[3] */ + "mul x2, x14, x16\n\t" + "umulh x3, x14, x16\n\t" + "adds x9, x9, x2\n\t" + "adc x10, x10, x3\n\t" + /* A[2] * A[3] */ + "mul x2, x15, x16\n\t" + "umulh x11, x15, x16\n\t" + "adds x10, x10, x2\n\t" + "adc x11, x11, xzr\n\t" + /* Double */ + "adds x6, x6, x6\n\t" + "adcs x7, x7, x7\n\t" + "adcs x8, x8, x8\n\t" + "adcs x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adcs x11, x11, x11\n\t" + "adc x12, xzr, xzr\n\t" + /* A[0] * A[0] */ + "mul x5, x13, x13\n\t" + "umulh x4, x13, x13\n\t" + /* A[1] * A[1] */ + "mul x2, x14, x14\n\t" + "umulh x3, x14, x14\n\t" + "adds x6, x6, x4\n\t" + "adcs x7, x7, x2\n\t" + "adc x4, x3, xzr\n\t" + /* A[2] * A[2] */ + "mul x2, x15, x15\n\t" + "umulh x3, x15, x15\n\t" + "adds x8, x8, x4\n\t" + "adcs x9, x9, x2\n\t" + "adc x4, x3, xzr\n\t" + /* A[3] * A[3] */ + "mul x2, x16, x16\n\t" + "umulh x3, x16, x16\n\t" + "adds x10, x10, x4\n\t" + "adcs x11, x11, x2\n\t" + "adc x12, x12, x3\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x12, x12, x11, #63\n\t" + "extr x11, x11, x10, #63\n\t" + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "and x8, x8, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x2, #19\n\t" + "mul x3, x2, x9\n\t" + "umulh x9, x2, x9\n\t" + "adds x5, x5, x3\n\t" + "mul x3, x2, x10\n\t" + "umulh x10, x2, x10\n\t" + "adcs x6, x6, x3\n\t" + "mul x3, x2, x11\n\t" + "umulh x11, x2, x11\n\t" + "adcs x7, x7, x3\n\t" + "mul x3, x2, x12\n\t" + "umulh x4, x2, x12\n\t" + "adcs x8, x8, x3\n\t" + "adc x4, x4, xzr\n\t" + /* Add remaining product results in */ + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adcs x8, x8, x11\n\t" + "adc x4, x4, xzr\n\t" + /* Overflow */ + "extr x4, x4, x8, #63\n\t" + "mul x4, x4, x2\n\t" + "and x8, x8, #0x7fffffffffffffff\n\t" + "adds x5, x5, x4\n\t" + "adcs x6, x6, xzr\n\t" + "adcs x7, x7, xzr\n\t" + "adc x8, x8, xzr\n\t" + /* Reduce if top bit set */ + "and x4, x2, x8, asr 63\n\t" + "and x8, x8, #0x7fffffffffffffff\n\t" + "adds x5, x5, x4\n\t" + "adcs x6, x6, xzr\n\t" + "adcs x7, x7, xzr\n\t" + "adc x8, x8, xzr\n\t" + /* Store */ + "stp x5, x6, [%x[r]]\n\t" + "stp x7, x8, [%x[r], #16]\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [r] "+r" (r), [a] "+r" (a) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16" + ); +} + +void fe_invert(fe r, const fe a) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-160]!\n\t" + "add x29, sp, #0\n\t" + /* Invert */ + "str %x[r], [x29, #144]\n\t" + "str %x[a], [x29, #152]\n\t" + "add x0, x29, #16\n\t" + "bl fe_sq\n\t" + "add x0, x29, #48\n\t" + "add x1, x29, #16\n\t" + "bl fe_sq\n\t" + "add x1, x29, #48\n\t" + "bl fe_sq\n\t" + "ldr x1, [x29, #152]\n\t" + "add x2, x29, #48\n\t" + "bl fe_mul\n\t" + "add x0, x29, #16\n\t" + "add x1, x29, #16\n\t" + "add x2, x29, #48\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x50\n\t" + "bl fe_sq\n\t" + "add x0, x29, #48\n\t" + "add x1, x29, #48\n\t" + "add x2, x29, #0x50\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x50\n\t" + "bl fe_sq\n\t" + "mov x20, #4\n\t" + "add x1, x29, #0x50\n\t" + "\n" + "L_fe_invert1_%=: \n\t" + "bl fe_sq\n\t" + "sub x20, x20, #1\n\t" + "cmp x20, #0\n\t" + "bne L_fe_invert1_%=\n\t" + "add x0, x29, #48\n\t" + "add x2, x29, #48\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x50\n\t" + "add x1, x29, #48\n\t" + "bl fe_sq\n\t" + "mov x20, #9\n\t" + "add x1, x29, #0x50\n\t" + "\n" + "L_fe_invert2_%=: \n\t" + "bl fe_sq\n\t" + "sub x20, x20, #1\n\t" + "cmp x20, #0\n\t" + "bne L_fe_invert2_%=\n\t" + "add x2, x29, #48\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x70\n\t" + "bl fe_sq\n\t" + "mov x20, #19\n\t" + "add x1, x29, #0x70\n\t" + "\n" + "L_fe_invert3_%=: \n\t" + "bl fe_sq\n\t" + "sub x20, x20, #1\n\t" + "cmp x20, #0\n\t" + "bne L_fe_invert3_%=\n\t" + "add x0, x29, #0x50\n\t" + "add x2, x29, #0x50\n\t" + "bl fe_mul\n\t" + "mov x20, #10\n\t" + "add x1, x29, #0x50\n\t" + "\n" + "L_fe_invert4_%=: \n\t" + "bl fe_sq\n\t" + "sub x20, x20, #1\n\t" + "cmp x20, #0\n\t" + "bne L_fe_invert4_%=\n\t" + "add x0, x29, #48\n\t" + "add x2, x29, #48\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x50\n\t" + "add x1, x29, #48\n\t" + "bl fe_sq\n\t" + "mov x20, #49\n\t" + "add x1, x29, #0x50\n\t" + "\n" + "L_fe_invert5_%=: \n\t" + "bl fe_sq\n\t" + "sub x20, x20, #1\n\t" + "cmp x20, #0\n\t" + "bne L_fe_invert5_%=\n\t" + "add x2, x29, #48\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x70\n\t" + "bl fe_sq\n\t" + "mov x20, #0x63\n\t" + "add x1, x29, #0x70\n\t" + "\n" + "L_fe_invert6_%=: \n\t" + "bl fe_sq\n\t" + "sub x20, x20, #1\n\t" + "cmp x20, #0\n\t" + "bne L_fe_invert6_%=\n\t" + "add x0, x29, #0x50\n\t" + "add x2, x29, #0x50\n\t" + "bl fe_mul\n\t" + "mov x20, #50\n\t" + "add x1, x29, #0x50\n\t" + "\n" + "L_fe_invert7_%=: \n\t" + "bl fe_sq\n\t" + "sub x20, x20, #1\n\t" + "cmp x20, #0\n\t" + "bne L_fe_invert7_%=\n\t" + "add x0, x29, #48\n\t" + "add x2, x29, #48\n\t" + "bl fe_mul\n\t" + "mov x20, #5\n\t" + "add x1, x29, #48\n\t" + "\n" + "L_fe_invert8_%=: \n\t" + "bl fe_sq\n\t" + "sub x20, x20, #1\n\t" + "cmp x20, #0\n\t" + "bne L_fe_invert8_%=\n\t" + "ldr x0, [x29, #144]\n\t" + "add x2, x29, #16\n\t" + "bl fe_mul\n\t" + "ldp x29, x30, [sp], #0xa0\n\t" + : [r] "+r" (r), [a] "+r" (a) + : + : "memory", "x20" + ); +} + +int curve25519(byte* r, byte* n, byte* a) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-192]!\n\t" + "add x29, sp, #0\n\t" + "mov x23, xzr\n\t" + "str %x[r], [x29, #176]\n\t" + "str %x[a], [x29, #184]\n\t" + /* Copy */ + "ldp x6, x7, [%x[a]]\n\t" + "ldp x8, x9, [%x[a], #16]\n\t" + "stp x6, x7, [x29, #80]\n\t" + "stp x8, x9, [x29, #96]\n\t" + /* Set one */ + "mov %x[a], #1\n\t" + "stp %x[a], xzr, [%x[r]]\n\t" + "stp xzr, xzr, [%x[r], #16]\n\t" + /* Set zero */ + "stp xzr, xzr, [x29, #16]\n\t" + "stp xzr, xzr, [x29, #32]\n\t" + /* Set one */ + "mov %x[a], #1\n\t" + "stp %x[a], xzr, [x29, #48]\n\t" + "stp xzr, xzr, [x29, #64]\n\t" + "mov x25, #62\n\t" + "mov x24, #24\n\t" + "\n" + "L_curve25519_words_%=: \n\t" + "\n" + "L_curve25519_bits_%=: \n\t" + "ldr %x[a], [%x[n], x24]\n\t" + "lsr %x[a], %x[a], x25\n\t" + "and %x[a], %x[a], #1\n\t" + "eor x23, x23, %x[a]\n\t" + /* Conditional Swap */ + "cmp x23, #1\n\t" + "ldp x10, x11, [%x[r]]\n\t" + "ldp x12, x13, [%x[r], #16]\n\t" + "ldp x6, x7, [x29, #80]\n\t" + "ldp x8, x9, [x29, #96]\n\t" + "csel x14, x10, x6, eq\n\t" + "csel x10, x6, x10, eq\n\t" + "csel x15, x11, x7, eq\n\t" + "csel x11, x7, x11, eq\n\t" + "csel x16, x12, x8, eq\n\t" + "csel x12, x8, x12, eq\n\t" + "csel x17, x13, x9, eq\n\t" + "csel x13, x9, x13, eq\n\t" + /* Conditional Swap */ + "cmp x23, #1\n\t" + "ldp x19, x20, [x29, #16]\n\t" + "ldp x21, x22, [x29, #32]\n\t" + "ldp x6, x7, [x29, #48]\n\t" + "ldp x8, x9, [x29, #64]\n\t" + "csel x5, x19, x6, eq\n\t" + "csel x19, x6, x19, eq\n\t" + "csel x26, x20, x7, eq\n\t" + "csel x20, x7, x20, eq\n\t" + "csel x27, x21, x8, eq\n\t" + "csel x21, x8, x21, eq\n\t" + "csel x28, x22, x9, eq\n\t" + "csel x22, x9, x22, eq\n\t" + "mov x23, %x[a]\n\t" + /* Add */ + "adds x6, x10, x19\n\t" + "adcs x7, x11, x20\n\t" + "adcs x8, x12, x21\n\t" + "adc x9, x13, x22\n\t" + "mov x3, #-19\n\t" + "asr %x[a], x9, #63\n\t" + /* Mask the modulus */ + "and x3, %x[a], x3\n\t" + "and x4, %x[a], #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x6, x6, x3\n\t" + "sbcs x7, x7, %x[a]\n\t" + "sbcs x8, x8, %x[a]\n\t" + "sbc x9, x9, x4\n\t" + /* Sub */ + "subs x19, x10, x19\n\t" + "sbcs x20, x11, x20\n\t" + "sbcs x21, x12, x21\n\t" + "sbcs x22, x13, x22\n\t" + "mov x3, #-19\n\t" + "csetm %x[a], cc\n\t" + /* Mask the modulus */ + "and x3, %x[a], x3\n\t" + "and x4, %x[a], #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x19, x19, x3\n\t" + "adcs x20, x20, %x[a]\n\t" + "adcs x21, x21, %x[a]\n\t" + "adc x22, x22, x4\n\t" + "stp x19, x20, [x29, #144]\n\t" + "stp x21, x22, [x29, #160]\n\t" + /* Add */ + "adds x10, x14, x5\n\t" + "adcs x11, x15, x26\n\t" + "adcs x12, x16, x27\n\t" + "adc x13, x17, x28\n\t" + "mov x3, #-19\n\t" + "asr %x[a], x13, #63\n\t" + /* Mask the modulus */ + "and x3, %x[a], x3\n\t" + "and x4, %x[a], #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x10, x10, x3\n\t" + "sbcs x11, x11, %x[a]\n\t" + "sbcs x12, x12, %x[a]\n\t" + "sbc x13, x13, x4\n\t" + /* Sub */ + "subs x14, x14, x5\n\t" + "sbcs x15, x15, x26\n\t" + "sbcs x16, x16, x27\n\t" + "sbcs x17, x17, x28\n\t" + "mov x3, #-19\n\t" + "csetm %x[a], cc\n\t" + /* Mask the modulus */ + "and x3, %x[a], x3\n\t" + "and x4, %x[a], #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x14, x14, x3\n\t" + "adcs x15, x15, %x[a]\n\t" + "adcs x16, x16, %x[a]\n\t" + "adc x17, x17, x4\n\t" + /* Multiply */ + /* A[0] * B[0] */ + "mul x19, x14, x6\n\t" + "umulh x20, x14, x6\n\t" + /* A[0] * B[1] */ + "mul x3, x14, x7\n\t" + "umulh x21, x14, x7\n\t" + "adds x20, x20, x3\n\t" + "adc x21, x21, xzr\n\t" + /* A[1] * B[0] */ + "mul x3, x15, x6\n\t" + "umulh x4, x15, x6\n\t" + "adds x20, x20, x3\n\t" + "adcs x21, x21, x4\n\t" + "adc x22, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x3, x14, x8\n\t" + "umulh x4, x14, x8\n\t" + "adds x21, x21, x3\n\t" + "adc x22, x22, x4\n\t" + /* A[1] * B[1] */ + "mul x3, x15, x7\n\t" + "umulh x4, x15, x7\n\t" + "adds x21, x21, x3\n\t" + "adcs x22, x22, x4\n\t" + "adc %x[a], xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x3, x16, x6\n\t" + "umulh x4, x16, x6\n\t" + "adds x21, x21, x3\n\t" + "adcs x22, x22, x4\n\t" + "adc %x[a], %x[a], xzr\n\t" + /* A[0] * B[3] */ + "mul x3, x14, x9\n\t" + "umulh x4, x14, x9\n\t" + "adds x22, x22, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x3, x15, x8\n\t" + "umulh x4, x15, x8\n\t" + "adds x22, x22, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, x26, xzr\n\t" + /* A[2] * B[1] */ + "mul x3, x16, x7\n\t" + "umulh x4, x16, x7\n\t" + "adds x22, x22, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, x26, xzr\n\t" + /* A[3] * B[0] */ + "mul x3, x17, x6\n\t" + "umulh x4, x17, x6\n\t" + "adds x22, x22, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, x26, xzr\n\t" + /* A[1] * B[3] */ + "mul x3, x15, x9\n\t" + "umulh x4, x15, x9\n\t" + "adds %x[a], %x[a], x3\n\t" + "adcs x26, x26, x4\n\t" + "adc x27, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x3, x16, x8\n\t" + "umulh x4, x16, x8\n\t" + "adds %x[a], %x[a], x3\n\t" + "adcs x26, x26, x4\n\t" + "adc x27, x27, xzr\n\t" + /* A[3] * B[1] */ + "mul x3, x17, x7\n\t" + "umulh x4, x17, x7\n\t" + "adds %x[a], %x[a], x3\n\t" + "adcs x26, x26, x4\n\t" + "adc x27, x27, xzr\n\t" + /* A[2] * B[3] */ + "mul x3, x16, x9\n\t" + "umulh x4, x16, x9\n\t" + "adds x26, x26, x3\n\t" + "adcs x27, x27, x4\n\t" + "adc x28, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x3, x17, x8\n\t" + "umulh x4, x17, x8\n\t" + "adds x26, x26, x3\n\t" + "adcs x27, x27, x4\n\t" + "adc x28, x28, xzr\n\t" + /* A[3] * B[3] */ + "mul x3, x17, x9\n\t" + "umulh x4, x17, x9\n\t" + "adds x27, x27, x3\n\t" + "adc x28, x28, x4\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x28, x28, x27, #63\n\t" + "extr x27, x27, x26, #63\n\t" + "extr x26, x26, %x[a], #63\n\t" + "extr %x[a], %x[a], x22, #63\n\t" + "and x22, x22, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x3, #19\n\t" + "mul x4, x3, %x[a]\n\t" + "umulh %x[a], x3, %x[a]\n\t" + "adds x19, x19, x4\n\t" + "mul x4, x3, x26\n\t" + "umulh x26, x3, x26\n\t" + "adcs x20, x20, x4\n\t" + "mul x4, x3, x27\n\t" + "umulh x27, x3, x27\n\t" + "adcs x21, x21, x4\n\t" + "mul x4, x3, x28\n\t" + "umulh x5, x3, x28\n\t" + "adcs x22, x22, x4\n\t" + "adc x5, x5, xzr\n\t" + /* Add remaining product results in */ + "adds x20, x20, %x[a]\n\t" + "adcs x21, x21, x26\n\t" + "adcs x22, x22, x27\n\t" + "adc x5, x5, xzr\n\t" + /* Overflow */ + "extr x5, x5, x22, #63\n\t" + "mul x5, x5, x3\n\t" + "and x22, x22, #0x7fffffffffffffff\n\t" + "adds x19, x19, x5\n\t" + "adcs x20, x20, xzr\n\t" + "adcs x21, x21, xzr\n\t" + "adc x22, x22, xzr\n\t" + /* Reduce if top bit set */ + "and x5, x3, x22, asr 63\n\t" + "and x22, x22, #0x7fffffffffffffff\n\t" + "adds x19, x19, x5\n\t" + "adcs x20, x20, xzr\n\t" + "adcs x21, x21, xzr\n\t" + "adc x22, x22, xzr\n\t" + /* Store */ + "stp x19, x20, [x29, #112]\n\t" + "stp x21, x22, [x29, #128]\n\t" + /* Multiply */ + "ldp %x[a], x26, [x29, #144]\n\t" + "ldp x27, x28, [x29, #160]\n\t" + /* A[0] * B[0] */ + "mul x19, x10, %x[a]\n\t" + "umulh x20, x10, %x[a]\n\t" + /* A[0] * B[1] */ + "mul x3, x10, x26\n\t" + "umulh x21, x10, x26\n\t" + "adds x20, x20, x3\n\t" + "adc x21, x21, xzr\n\t" + /* A[1] * B[0] */ + "mul x3, x11, %x[a]\n\t" + "umulh x4, x11, %x[a]\n\t" + "adds x20, x20, x3\n\t" + "adcs x21, x21, x4\n\t" + "adc x22, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x3, x10, x27\n\t" + "umulh x4, x10, x27\n\t" + "adds x21, x21, x3\n\t" + "adc x22, x22, x4\n\t" + /* A[1] * B[1] */ + "mul x3, x11, x26\n\t" + "umulh x4, x11, x26\n\t" + "adds x21, x21, x3\n\t" + "adcs x22, x22, x4\n\t" + "adc x14, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x3, x12, %x[a]\n\t" + "umulh x4, x12, %x[a]\n\t" + "adds x21, x21, x3\n\t" + "adcs x22, x22, x4\n\t" + "adc x14, x14, xzr\n\t" + /* A[0] * B[3] */ + "mul x3, x10, x28\n\t" + "umulh x4, x10, x28\n\t" + "adds x22, x22, x3\n\t" + "adcs x14, x14, x4\n\t" + "adc x15, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x3, x11, x27\n\t" + "umulh x4, x11, x27\n\t" + "adds x22, x22, x3\n\t" + "adcs x14, x14, x4\n\t" + "adc x15, x15, xzr\n\t" + /* A[2] * B[1] */ + "mul x3, x12, x26\n\t" + "umulh x4, x12, x26\n\t" + "adds x22, x22, x3\n\t" + "adcs x14, x14, x4\n\t" + "adc x15, x15, xzr\n\t" + /* A[3] * B[0] */ + "mul x3, x13, %x[a]\n\t" + "umulh x4, x13, %x[a]\n\t" + "adds x22, x22, x3\n\t" + "adcs x14, x14, x4\n\t" + "adc x15, x15, xzr\n\t" + /* A[1] * B[3] */ + "mul x3, x11, x28\n\t" + "umulh x4, x11, x28\n\t" + "adds x14, x14, x3\n\t" + "adcs x15, x15, x4\n\t" + "adc x16, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x3, x12, x27\n\t" + "umulh x4, x12, x27\n\t" + "adds x14, x14, x3\n\t" + "adcs x15, x15, x4\n\t" + "adc x16, x16, xzr\n\t" + /* A[3] * B[1] */ + "mul x3, x13, x26\n\t" + "umulh x4, x13, x26\n\t" + "adds x14, x14, x3\n\t" + "adcs x15, x15, x4\n\t" + "adc x16, x16, xzr\n\t" + /* A[2] * B[3] */ + "mul x3, x12, x28\n\t" + "umulh x4, x12, x28\n\t" + "adds x15, x15, x3\n\t" + "adcs x16, x16, x4\n\t" + "adc x17, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x3, x13, x27\n\t" + "umulh x4, x13, x27\n\t" + "adds x15, x15, x3\n\t" + "adcs x16, x16, x4\n\t" + "adc x17, x17, xzr\n\t" + /* A[3] * B[3] */ + "mul x3, x13, x28\n\t" + "umulh x4, x13, x28\n\t" + "adds x16, x16, x3\n\t" + "adc x17, x17, x4\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x17, x17, x16, #63\n\t" + "extr x16, x16, x15, #63\n\t" + "extr x15, x15, x14, #63\n\t" + "extr x14, x14, x22, #63\n\t" + "and x22, x22, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x3, #19\n\t" + "mul x4, x3, x14\n\t" + "umulh x14, x3, x14\n\t" + "adds x19, x19, x4\n\t" + "mul x4, x3, x15\n\t" + "umulh x15, x3, x15\n\t" + "adcs x20, x20, x4\n\t" + "mul x4, x3, x16\n\t" + "umulh x16, x3, x16\n\t" + "adcs x21, x21, x4\n\t" + "mul x4, x3, x17\n\t" + "umulh x5, x3, x17\n\t" + "adcs x22, x22, x4\n\t" + "adc x5, x5, xzr\n\t" + /* Add remaining product results in */ + "adds x20, x20, x14\n\t" + "adcs x21, x21, x15\n\t" + "adcs x22, x22, x16\n\t" + "adc x5, x5, xzr\n\t" + /* Overflow */ + "extr x5, x5, x22, #63\n\t" + "mul x5, x5, x3\n\t" + "and x22, x22, #0x7fffffffffffffff\n\t" + "adds x19, x19, x5\n\t" + "adcs x20, x20, xzr\n\t" + "adcs x21, x21, xzr\n\t" + "adc x22, x22, xzr\n\t" + /* Reduce if top bit set */ + "and x5, x3, x22, asr 63\n\t" + "and x22, x22, #0x7fffffffffffffff\n\t" + "adds x19, x19, x5\n\t" + "adcs x20, x20, xzr\n\t" + "adcs x21, x21, xzr\n\t" + "adc x22, x22, xzr\n\t" + /* Store */ + /* Square */ + /* A[0] * A[1] */ + "mul x11, %x[a], x26\n\t" + "umulh x12, %x[a], x26\n\t" + /* A[0] * A[2] */ + "mul x3, %x[a], x27\n\t" + "umulh x13, %x[a], x27\n\t" + "adds x12, x12, x3\n\t" + "adc x13, x13, xzr\n\t" + /* A[0] * A[3] */ + "mul x3, %x[a], x28\n\t" + "umulh x14, %x[a], x28\n\t" + "adds x13, x13, x3\n\t" + "adc x14, x14, xzr\n\t" + /* A[1] * A[2] */ + "mul x3, x26, x27\n\t" + "umulh x4, x26, x27\n\t" + "adds x13, x13, x3\n\t" + "adcs x14, x14, x4\n\t" + "adc x15, xzr, xzr\n\t" + /* A[1] * A[3] */ + "mul x3, x26, x28\n\t" + "umulh x4, x26, x28\n\t" + "adds x14, x14, x3\n\t" + "adc x15, x15, x4\n\t" + /* A[2] * A[3] */ + "mul x3, x27, x28\n\t" + "umulh x16, x27, x28\n\t" + "adds x15, x15, x3\n\t" + "adc x16, x16, xzr\n\t" + /* Double */ + "adds x11, x11, x11\n\t" + "adcs x12, x12, x12\n\t" + "adcs x13, x13, x13\n\t" + "adcs x14, x14, x14\n\t" + "adcs x15, x15, x15\n\t" + "adcs x16, x16, x16\n\t" + "adc x17, xzr, xzr\n\t" + /* A[0] * A[0] */ + "mul x10, %x[a], %x[a]\n\t" + "umulh x5, %x[a], %x[a]\n\t" + /* A[1] * A[1] */ + "mul x3, x26, x26\n\t" + "umulh x4, x26, x26\n\t" + "adds x11, x11, x5\n\t" + "adcs x12, x12, x3\n\t" + "adc x5, x4, xzr\n\t" + /* A[2] * A[2] */ + "mul x3, x27, x27\n\t" + "umulh x4, x27, x27\n\t" + "adds x13, x13, x5\n\t" + "adcs x14, x14, x3\n\t" + "adc x5, x4, xzr\n\t" + /* A[3] * A[3] */ + "mul x3, x28, x28\n\t" + "umulh x4, x28, x28\n\t" + "adds x15, x15, x5\n\t" + "adcs x16, x16, x3\n\t" + "adc x17, x17, x4\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x17, x17, x16, #63\n\t" + "extr x16, x16, x15, #63\n\t" + "extr x15, x15, x14, #63\n\t" + "extr x14, x14, x13, #63\n\t" + "and x13, x13, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x3, #19\n\t" + "mul x4, x3, x14\n\t" + "umulh x14, x3, x14\n\t" + "adds x10, x10, x4\n\t" + "mul x4, x3, x15\n\t" + "umulh x15, x3, x15\n\t" + "adcs x11, x11, x4\n\t" + "mul x4, x3, x16\n\t" + "umulh x16, x3, x16\n\t" + "adcs x12, x12, x4\n\t" + "mul x4, x3, x17\n\t" + "umulh x5, x3, x17\n\t" + "adcs x13, x13, x4\n\t" + "adc x5, x5, xzr\n\t" + /* Add remaining product results in */ + "adds x11, x11, x14\n\t" + "adcs x12, x12, x15\n\t" + "adcs x13, x13, x16\n\t" + "adc x5, x5, xzr\n\t" + /* Overflow */ + "extr x5, x5, x13, #63\n\t" + "mul x5, x5, x3\n\t" + "and x13, x13, #0x7fffffffffffffff\n\t" + "adds x10, x10, x5\n\t" + "adcs x11, x11, xzr\n\t" + "adcs x12, x12, xzr\n\t" + "adc x13, x13, xzr\n\t" + /* Reduce if top bit set */ + "and x5, x3, x13, asr 63\n\t" + "and x13, x13, #0x7fffffffffffffff\n\t" + "adds x10, x10, x5\n\t" + "adcs x11, x11, xzr\n\t" + "adcs x12, x12, xzr\n\t" + "adc x13, x13, xzr\n\t" + /* Store */ + /* Square */ + /* A[0] * A[1] */ + "mul x15, x6, x7\n\t" + "umulh x16, x6, x7\n\t" + /* A[0] * A[2] */ + "mul x3, x6, x8\n\t" + "umulh x17, x6, x8\n\t" + "adds x16, x16, x3\n\t" + "adc x17, x17, xzr\n\t" + /* A[0] * A[3] */ + "mul x3, x6, x9\n\t" + "umulh %x[a], x6, x9\n\t" + "adds x17, x17, x3\n\t" + "adc %x[a], %x[a], xzr\n\t" + /* A[1] * A[2] */ + "mul x3, x7, x8\n\t" + "umulh x4, x7, x8\n\t" + "adds x17, x17, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, xzr, xzr\n\t" + /* A[1] * A[3] */ + "mul x3, x7, x9\n\t" + "umulh x4, x7, x9\n\t" + "adds %x[a], %x[a], x3\n\t" + "adc x26, x26, x4\n\t" + /* A[2] * A[3] */ + "mul x3, x8, x9\n\t" + "umulh x27, x8, x9\n\t" + "adds x26, x26, x3\n\t" + "adc x27, x27, xzr\n\t" + /* Double */ + "adds x15, x15, x15\n\t" + "adcs x16, x16, x16\n\t" + "adcs x17, x17, x17\n\t" + "adcs %x[a], %x[a], %x[a]\n\t" + "adcs x26, x26, x26\n\t" + "adcs x27, x27, x27\n\t" + "adc x28, xzr, xzr\n\t" + /* A[0] * A[0] */ + "mul x14, x6, x6\n\t" + "umulh x5, x6, x6\n\t" + /* A[1] * A[1] */ + "mul x3, x7, x7\n\t" + "umulh x4, x7, x7\n\t" + "adds x15, x15, x5\n\t" + "adcs x16, x16, x3\n\t" + "adc x5, x4, xzr\n\t" + /* A[2] * A[2] */ + "mul x3, x8, x8\n\t" + "umulh x4, x8, x8\n\t" + "adds x17, x17, x5\n\t" + "adcs %x[a], %x[a], x3\n\t" + "adc x5, x4, xzr\n\t" + /* A[3] * A[3] */ + "mul x3, x9, x9\n\t" + "umulh x4, x9, x9\n\t" + "adds x26, x26, x5\n\t" + "adcs x27, x27, x3\n\t" + "adc x28, x28, x4\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x28, x28, x27, #63\n\t" + "extr x27, x27, x26, #63\n\t" + "extr x26, x26, %x[a], #63\n\t" + "extr %x[a], %x[a], x17, #63\n\t" + "and x17, x17, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x3, #19\n\t" + "mul x4, x3, %x[a]\n\t" + "umulh %x[a], x3, %x[a]\n\t" + "adds x14, x14, x4\n\t" + "mul x4, x3, x26\n\t" + "umulh x26, x3, x26\n\t" + "adcs x15, x15, x4\n\t" + "mul x4, x3, x27\n\t" + "umulh x27, x3, x27\n\t" + "adcs x16, x16, x4\n\t" + "mul x4, x3, x28\n\t" + "umulh x5, x3, x28\n\t" + "adcs x17, x17, x4\n\t" + "adc x5, x5, xzr\n\t" + /* Add remaining product results in */ + "adds x15, x15, %x[a]\n\t" + "adcs x16, x16, x26\n\t" + "adcs x17, x17, x27\n\t" + "adc x5, x5, xzr\n\t" + /* Overflow */ + "extr x5, x5, x17, #63\n\t" + "mul x5, x5, x3\n\t" + "and x17, x17, #0x7fffffffffffffff\n\t" + "adds x14, x14, x5\n\t" + "adcs x15, x15, xzr\n\t" + "adcs x16, x16, xzr\n\t" + "adc x17, x17, xzr\n\t" + /* Reduce if top bit set */ + "and x5, x3, x17, asr 63\n\t" + "and x17, x17, #0x7fffffffffffffff\n\t" + "adds x14, x14, x5\n\t" + "adcs x15, x15, xzr\n\t" + "adcs x16, x16, xzr\n\t" + "adc x17, x17, xzr\n\t" + /* Store */ + /* Multiply */ + /* A[0] * B[0] */ + "mul x6, x14, x10\n\t" + "umulh x7, x14, x10\n\t" + /* A[0] * B[1] */ + "mul x3, x14, x11\n\t" + "umulh x8, x14, x11\n\t" + "adds x7, x7, x3\n\t" + "adc x8, x8, xzr\n\t" + /* A[1] * B[0] */ + "mul x3, x15, x10\n\t" + "umulh x4, x15, x10\n\t" + "adds x7, x7, x3\n\t" + "adcs x8, x8, x4\n\t" + "adc x9, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x3, x14, x12\n\t" + "umulh x4, x14, x12\n\t" + "adds x8, x8, x3\n\t" + "adc x9, x9, x4\n\t" + /* A[1] * B[1] */ + "mul x3, x15, x11\n\t" + "umulh x4, x15, x11\n\t" + "adds x8, x8, x3\n\t" + "adcs x9, x9, x4\n\t" + "adc %x[a], xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x3, x16, x10\n\t" + "umulh x4, x16, x10\n\t" + "adds x8, x8, x3\n\t" + "adcs x9, x9, x4\n\t" + "adc %x[a], %x[a], xzr\n\t" + /* A[0] * B[3] */ + "mul x3, x14, x13\n\t" + "umulh x4, x14, x13\n\t" + "adds x9, x9, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x3, x15, x12\n\t" + "umulh x4, x15, x12\n\t" + "adds x9, x9, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, x26, xzr\n\t" + /* A[2] * B[1] */ + "mul x3, x16, x11\n\t" + "umulh x4, x16, x11\n\t" + "adds x9, x9, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, x26, xzr\n\t" + /* A[3] * B[0] */ + "mul x3, x17, x10\n\t" + "umulh x4, x17, x10\n\t" + "adds x9, x9, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, x26, xzr\n\t" + /* A[1] * B[3] */ + "mul x3, x15, x13\n\t" + "umulh x4, x15, x13\n\t" + "adds %x[a], %x[a], x3\n\t" + "adcs x26, x26, x4\n\t" + "adc x27, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x3, x16, x12\n\t" + "umulh x4, x16, x12\n\t" + "adds %x[a], %x[a], x3\n\t" + "adcs x26, x26, x4\n\t" + "adc x27, x27, xzr\n\t" + /* A[3] * B[1] */ + "mul x3, x17, x11\n\t" + "umulh x4, x17, x11\n\t" + "adds %x[a], %x[a], x3\n\t" + "adcs x26, x26, x4\n\t" + "adc x27, x27, xzr\n\t" + /* A[2] * B[3] */ + "mul x3, x16, x13\n\t" + "umulh x4, x16, x13\n\t" + "adds x26, x26, x3\n\t" + "adcs x27, x27, x4\n\t" + "adc x28, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x3, x17, x12\n\t" + "umulh x4, x17, x12\n\t" + "adds x26, x26, x3\n\t" + "adcs x27, x27, x4\n\t" + "adc x28, x28, xzr\n\t" + /* A[3] * B[3] */ + "mul x3, x17, x13\n\t" + "umulh x4, x17, x13\n\t" + "adds x27, x27, x3\n\t" + "adc x28, x28, x4\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x28, x28, x27, #63\n\t" + "extr x27, x27, x26, #63\n\t" + "extr x26, x26, %x[a], #63\n\t" + "extr %x[a], %x[a], x9, #63\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x3, #19\n\t" + "mul x4, x3, %x[a]\n\t" + "umulh %x[a], x3, %x[a]\n\t" + "adds x6, x6, x4\n\t" + "mul x4, x3, x26\n\t" + "umulh x26, x3, x26\n\t" + "adcs x7, x7, x4\n\t" + "mul x4, x3, x27\n\t" + "umulh x27, x3, x27\n\t" + "adcs x8, x8, x4\n\t" + "mul x4, x3, x28\n\t" + "umulh x5, x3, x28\n\t" + "adcs x9, x9, x4\n\t" + "adc x5, x5, xzr\n\t" + /* Add remaining product results in */ + "adds x7, x7, %x[a]\n\t" + "adcs x8, x8, x26\n\t" + "adcs x9, x9, x27\n\t" + "adc x5, x5, xzr\n\t" + /* Overflow */ + "extr x5, x5, x9, #63\n\t" + "mul x5, x5, x3\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + "adds x6, x6, x5\n\t" + "adcs x7, x7, xzr\n\t" + "adcs x8, x8, xzr\n\t" + "adc x9, x9, xzr\n\t" + /* Reduce if top bit set */ + "and x5, x3, x9, asr 63\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + "adds x6, x6, x5\n\t" + "adcs x7, x7, xzr\n\t" + "adcs x8, x8, xzr\n\t" + "adc x9, x9, xzr\n\t" + /* Store */ + "stp x6, x7, [%x[r]]\n\t" + "stp x8, x9, [%x[r], #16]\n\t" + /* Sub */ + "subs x14, x14, x10\n\t" + "sbcs x15, x15, x11\n\t" + "sbcs x16, x16, x12\n\t" + "sbcs x17, x17, x13\n\t" + "mov x3, #-19\n\t" + "csetm %x[a], cc\n\t" + /* Mask the modulus */ + "and x3, %x[a], x3\n\t" + "and x4, %x[a], #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x14, x14, x3\n\t" + "adcs x15, x15, %x[a]\n\t" + "adcs x16, x16, %x[a]\n\t" + "adc x17, x17, x4\n\t" + /* Multiply by 121666 */ + "mov x5, #0xdb42\n\t" + "movk x5, #1, lsl 16\n\t" + "mul x6, x14, x5\n\t" + "umulh x7, x14, x5\n\t" + "mul x3, x15, x5\n\t" + "umulh x4, x15, x5\n\t" + "adds x7, x7, x3\n\t" + "adc x8, xzr, x4\n\t" + "mul x3, x16, x5\n\t" + "umulh x4, x16, x5\n\t" + "adds x8, x8, x3\n\t" + "adc x9, xzr, x4\n\t" + "mul x3, x17, x5\n\t" + "umulh x4, x17, x5\n\t" + "adds x9, x9, x3\n\t" + "adc x4, xzr, x4\n\t" + "mov x5, #19\n\t" + "extr x4, x4, x9, #63\n\t" + "mul x4, x4, x5\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + "adds x6, x6, x4\n\t" + "adcs x7, x7, xzr\n\t" + "adcs x8, x8, xzr\n\t" + "adc x9, x9, xzr\n\t" + /* Add */ + "adds x10, x10, x6\n\t" + "adcs x11, x11, x7\n\t" + "adcs x12, x12, x8\n\t" + "adc x13, x13, x9\n\t" + "mov x3, #-19\n\t" + "asr %x[a], x13, #63\n\t" + /* Mask the modulus */ + "and x3, %x[a], x3\n\t" + "and x4, %x[a], #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x10, x10, x3\n\t" + "sbcs x11, x11, %x[a]\n\t" + "sbcs x12, x12, %x[a]\n\t" + "sbc x13, x13, x4\n\t" + /* Multiply */ + /* A[0] * B[0] */ + "mul x6, x14, x10\n\t" + "umulh x7, x14, x10\n\t" + /* A[0] * B[1] */ + "mul x3, x14, x11\n\t" + "umulh x8, x14, x11\n\t" + "adds x7, x7, x3\n\t" + "adc x8, x8, xzr\n\t" + /* A[1] * B[0] */ + "mul x3, x15, x10\n\t" + "umulh x4, x15, x10\n\t" + "adds x7, x7, x3\n\t" + "adcs x8, x8, x4\n\t" + "adc x9, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x3, x14, x12\n\t" + "umulh x4, x14, x12\n\t" + "adds x8, x8, x3\n\t" + "adc x9, x9, x4\n\t" + /* A[1] * B[1] */ + "mul x3, x15, x11\n\t" + "umulh x4, x15, x11\n\t" + "adds x8, x8, x3\n\t" + "adcs x9, x9, x4\n\t" + "adc %x[a], xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x3, x16, x10\n\t" + "umulh x4, x16, x10\n\t" + "adds x8, x8, x3\n\t" + "adcs x9, x9, x4\n\t" + "adc %x[a], %x[a], xzr\n\t" + /* A[0] * B[3] */ + "mul x3, x14, x13\n\t" + "umulh x4, x14, x13\n\t" + "adds x9, x9, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x3, x15, x12\n\t" + "umulh x4, x15, x12\n\t" + "adds x9, x9, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, x26, xzr\n\t" + /* A[2] * B[1] */ + "mul x3, x16, x11\n\t" + "umulh x4, x16, x11\n\t" + "adds x9, x9, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, x26, xzr\n\t" + /* A[3] * B[0] */ + "mul x3, x17, x10\n\t" + "umulh x4, x17, x10\n\t" + "adds x9, x9, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, x26, xzr\n\t" + /* A[1] * B[3] */ + "mul x3, x15, x13\n\t" + "umulh x4, x15, x13\n\t" + "adds %x[a], %x[a], x3\n\t" + "adcs x26, x26, x4\n\t" + "adc x27, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x3, x16, x12\n\t" + "umulh x4, x16, x12\n\t" + "adds %x[a], %x[a], x3\n\t" + "adcs x26, x26, x4\n\t" + "adc x27, x27, xzr\n\t" + /* A[3] * B[1] */ + "mul x3, x17, x11\n\t" + "umulh x4, x17, x11\n\t" + "adds %x[a], %x[a], x3\n\t" + "adcs x26, x26, x4\n\t" + "adc x27, x27, xzr\n\t" + /* A[2] * B[3] */ + "mul x3, x16, x13\n\t" + "umulh x4, x16, x13\n\t" + "adds x26, x26, x3\n\t" + "adcs x27, x27, x4\n\t" + "adc x28, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x3, x17, x12\n\t" + "umulh x4, x17, x12\n\t" + "adds x26, x26, x3\n\t" + "adcs x27, x27, x4\n\t" + "adc x28, x28, xzr\n\t" + /* A[3] * B[3] */ + "mul x3, x17, x13\n\t" + "umulh x4, x17, x13\n\t" + "adds x27, x27, x3\n\t" + "adc x28, x28, x4\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x28, x28, x27, #63\n\t" + "extr x27, x27, x26, #63\n\t" + "extr x26, x26, %x[a], #63\n\t" + "extr %x[a], %x[a], x9, #63\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x3, #19\n\t" + "mul x4, x3, %x[a]\n\t" + "umulh %x[a], x3, %x[a]\n\t" + "adds x6, x6, x4\n\t" + "mul x4, x3, x26\n\t" + "umulh x26, x3, x26\n\t" + "adcs x7, x7, x4\n\t" + "mul x4, x3, x27\n\t" + "umulh x27, x3, x27\n\t" + "adcs x8, x8, x4\n\t" + "mul x4, x3, x28\n\t" + "umulh x5, x3, x28\n\t" + "adcs x9, x9, x4\n\t" + "adc x5, x5, xzr\n\t" + /* Add remaining product results in */ + "adds x7, x7, %x[a]\n\t" + "adcs x8, x8, x26\n\t" + "adcs x9, x9, x27\n\t" + "adc x5, x5, xzr\n\t" + /* Overflow */ + "extr x5, x5, x9, #63\n\t" + "mul x5, x5, x3\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + "adds x6, x6, x5\n\t" + "adcs x7, x7, xzr\n\t" + "adcs x8, x8, xzr\n\t" + "adc x9, x9, xzr\n\t" + /* Reduce if top bit set */ + "and x5, x3, x9, asr 63\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + "adds x6, x6, x5\n\t" + "adcs x7, x7, xzr\n\t" + "adcs x8, x8, xzr\n\t" + "adc x9, x9, xzr\n\t" + /* Store */ + "stp x6, x7, [x29, #16]\n\t" + "stp x8, x9, [x29, #32]\n\t" + /* Add */ + "ldp x6, x7, [x29, #112]\n\t" + "ldp x8, x9, [x29, #128]\n\t" + "adds x10, x6, x19\n\t" + "adcs x11, x7, x20\n\t" + "adcs x12, x8, x21\n\t" + "adc x13, x9, x22\n\t" + "mov x3, #-19\n\t" + "asr %x[a], x13, #63\n\t" + /* Mask the modulus */ + "and x3, %x[a], x3\n\t" + "and x4, %x[a], #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x10, x10, x3\n\t" + "sbcs x11, x11, %x[a]\n\t" + "sbcs x12, x12, %x[a]\n\t" + "sbc x13, x13, x4\n\t" + /* Sub */ + "subs x19, x6, x19\n\t" + "sbcs x20, x7, x20\n\t" + "sbcs x21, x8, x21\n\t" + "sbcs x22, x9, x22\n\t" + "mov x3, #-19\n\t" + "csetm %x[a], cc\n\t" + /* Mask the modulus */ + "and x3, %x[a], x3\n\t" + "and x4, %x[a], #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x19, x19, x3\n\t" + "adcs x20, x20, %x[a]\n\t" + "adcs x21, x21, %x[a]\n\t" + "adc x22, x22, x4\n\t" + /* Square */ + /* A[0] * A[1] */ + "mul x7, x10, x11\n\t" + "umulh x8, x10, x11\n\t" + /* A[0] * A[2] */ + "mul x3, x10, x12\n\t" + "umulh x9, x10, x12\n\t" + "adds x8, x8, x3\n\t" + "adc x9, x9, xzr\n\t" + /* A[0] * A[3] */ + "mul x3, x10, x13\n\t" + "umulh %x[a], x10, x13\n\t" + "adds x9, x9, x3\n\t" + "adc %x[a], %x[a], xzr\n\t" + /* A[1] * A[2] */ + "mul x3, x11, x12\n\t" + "umulh x4, x11, x12\n\t" + "adds x9, x9, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, xzr, xzr\n\t" + /* A[1] * A[3] */ + "mul x3, x11, x13\n\t" + "umulh x4, x11, x13\n\t" + "adds %x[a], %x[a], x3\n\t" + "adc x26, x26, x4\n\t" + /* A[2] * A[3] */ + "mul x3, x12, x13\n\t" + "umulh x27, x12, x13\n\t" + "adds x26, x26, x3\n\t" + "adc x27, x27, xzr\n\t" + /* Double */ + "adds x7, x7, x7\n\t" + "adcs x8, x8, x8\n\t" + "adcs x9, x9, x9\n\t" + "adcs %x[a], %x[a], %x[a]\n\t" + "adcs x26, x26, x26\n\t" + "adcs x27, x27, x27\n\t" + "adc x28, xzr, xzr\n\t" + /* A[0] * A[0] */ + "mul x6, x10, x10\n\t" + "umulh x5, x10, x10\n\t" + /* A[1] * A[1] */ + "mul x3, x11, x11\n\t" + "umulh x4, x11, x11\n\t" + "adds x7, x7, x5\n\t" + "adcs x8, x8, x3\n\t" + "adc x5, x4, xzr\n\t" + /* A[2] * A[2] */ + "mul x3, x12, x12\n\t" + "umulh x4, x12, x12\n\t" + "adds x9, x9, x5\n\t" + "adcs %x[a], %x[a], x3\n\t" + "adc x5, x4, xzr\n\t" + /* A[3] * A[3] */ + "mul x3, x13, x13\n\t" + "umulh x4, x13, x13\n\t" + "adds x26, x26, x5\n\t" + "adcs x27, x27, x3\n\t" + "adc x28, x28, x4\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x28, x28, x27, #63\n\t" + "extr x27, x27, x26, #63\n\t" + "extr x26, x26, %x[a], #63\n\t" + "extr %x[a], %x[a], x9, #63\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x3, #19\n\t" + "mul x4, x3, %x[a]\n\t" + "umulh %x[a], x3, %x[a]\n\t" + "adds x6, x6, x4\n\t" + "mul x4, x3, x26\n\t" + "umulh x26, x3, x26\n\t" + "adcs x7, x7, x4\n\t" + "mul x4, x3, x27\n\t" + "umulh x27, x3, x27\n\t" + "adcs x8, x8, x4\n\t" + "mul x4, x3, x28\n\t" + "umulh x5, x3, x28\n\t" + "adcs x9, x9, x4\n\t" + "adc x5, x5, xzr\n\t" + /* Add remaining product results in */ + "adds x7, x7, %x[a]\n\t" + "adcs x8, x8, x26\n\t" + "adcs x9, x9, x27\n\t" + "adc x5, x5, xzr\n\t" + /* Overflow */ + "extr x5, x5, x9, #63\n\t" + "mul x5, x5, x3\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + "adds x6, x6, x5\n\t" + "adcs x7, x7, xzr\n\t" + "adcs x8, x8, xzr\n\t" + "adc x9, x9, xzr\n\t" + /* Reduce if top bit set */ + "and x5, x3, x9, asr 63\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + "adds x6, x6, x5\n\t" + "adcs x7, x7, xzr\n\t" + "adcs x8, x8, xzr\n\t" + "adc x9, x9, xzr\n\t" + /* Store */ + "stp x6, x7, [x29, #80]\n\t" + "stp x8, x9, [x29, #96]\n\t" + /* Square */ + /* A[0] * A[1] */ + "mul x7, x19, x20\n\t" + "umulh x8, x19, x20\n\t" + /* A[0] * A[2] */ + "mul x3, x19, x21\n\t" + "umulh x9, x19, x21\n\t" + "adds x8, x8, x3\n\t" + "adc x9, x9, xzr\n\t" + /* A[0] * A[3] */ + "mul x3, x19, x22\n\t" + "umulh %x[a], x19, x22\n\t" + "adds x9, x9, x3\n\t" + "adc %x[a], %x[a], xzr\n\t" + /* A[1] * A[2] */ + "mul x3, x20, x21\n\t" + "umulh x4, x20, x21\n\t" + "adds x9, x9, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, xzr, xzr\n\t" + /* A[1] * A[3] */ + "mul x3, x20, x22\n\t" + "umulh x4, x20, x22\n\t" + "adds %x[a], %x[a], x3\n\t" + "adc x26, x26, x4\n\t" + /* A[2] * A[3] */ + "mul x3, x21, x22\n\t" + "umulh x27, x21, x22\n\t" + "adds x26, x26, x3\n\t" + "adc x27, x27, xzr\n\t" + /* Double */ + "adds x7, x7, x7\n\t" + "adcs x8, x8, x8\n\t" + "adcs x9, x9, x9\n\t" + "adcs %x[a], %x[a], %x[a]\n\t" + "adcs x26, x26, x26\n\t" + "adcs x27, x27, x27\n\t" + "adc x28, xzr, xzr\n\t" + /* A[0] * A[0] */ + "mul x6, x19, x19\n\t" + "umulh x5, x19, x19\n\t" + /* A[1] * A[1] */ + "mul x3, x20, x20\n\t" + "umulh x4, x20, x20\n\t" + "adds x7, x7, x5\n\t" + "adcs x8, x8, x3\n\t" + "adc x5, x4, xzr\n\t" + /* A[2] * A[2] */ + "mul x3, x21, x21\n\t" + "umulh x4, x21, x21\n\t" + "adds x9, x9, x5\n\t" + "adcs %x[a], %x[a], x3\n\t" + "adc x5, x4, xzr\n\t" + /* A[3] * A[3] */ + "mul x3, x22, x22\n\t" + "umulh x4, x22, x22\n\t" + "adds x26, x26, x5\n\t" + "adcs x27, x27, x3\n\t" + "adc x28, x28, x4\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x28, x28, x27, #63\n\t" + "extr x27, x27, x26, #63\n\t" + "extr x26, x26, %x[a], #63\n\t" + "extr %x[a], %x[a], x9, #63\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x3, #19\n\t" + "mul x4, x3, %x[a]\n\t" + "umulh %x[a], x3, %x[a]\n\t" + "adds x6, x6, x4\n\t" + "mul x4, x3, x26\n\t" + "umulh x26, x3, x26\n\t" + "adcs x7, x7, x4\n\t" + "mul x4, x3, x27\n\t" + "umulh x27, x3, x27\n\t" + "adcs x8, x8, x4\n\t" + "mul x4, x3, x28\n\t" + "umulh x5, x3, x28\n\t" + "adcs x9, x9, x4\n\t" + "adc x5, x5, xzr\n\t" + /* Add remaining product results in */ + "adds x7, x7, %x[a]\n\t" + "adcs x8, x8, x26\n\t" + "adcs x9, x9, x27\n\t" + "adc x5, x5, xzr\n\t" + /* Overflow */ + "extr x5, x5, x9, #63\n\t" + "mul x5, x5, x3\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + "adds x6, x6, x5\n\t" + "adcs x7, x7, xzr\n\t" + "adcs x8, x8, xzr\n\t" + "adc x9, x9, xzr\n\t" + /* Reduce if top bit set */ + "and x5, x3, x9, asr 63\n\t" + "and x9, x9, #0x7fffffffffffffff\n\t" + "adds x6, x6, x5\n\t" + "adcs x7, x7, xzr\n\t" + "adcs x8, x8, xzr\n\t" + "adc x9, x9, xzr\n\t" + /* Store */ + "ldr %x[a], [x29, #184]\n\t" + /* Multiply */ + "ldp x14, x15, [%x[a]]\n\t" + "ldp x16, x17, [%x[a], #16]\n\t" + /* A[0] * B[0] */ + "mul x10, x14, x6\n\t" + "umulh x11, x14, x6\n\t" + /* A[0] * B[1] */ + "mul x3, x14, x7\n\t" + "umulh x12, x14, x7\n\t" + "adds x11, x11, x3\n\t" + "adc x12, x12, xzr\n\t" + /* A[1] * B[0] */ + "mul x3, x15, x6\n\t" + "umulh x4, x15, x6\n\t" + "adds x11, x11, x3\n\t" + "adcs x12, x12, x4\n\t" + "adc x13, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x3, x14, x8\n\t" + "umulh x4, x14, x8\n\t" + "adds x12, x12, x3\n\t" + "adc x13, x13, x4\n\t" + /* A[1] * B[1] */ + "mul x3, x15, x7\n\t" + "umulh x4, x15, x7\n\t" + "adds x12, x12, x3\n\t" + "adcs x13, x13, x4\n\t" + "adc %x[a], xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x3, x16, x6\n\t" + "umulh x4, x16, x6\n\t" + "adds x12, x12, x3\n\t" + "adcs x13, x13, x4\n\t" + "adc %x[a], %x[a], xzr\n\t" + /* A[0] * B[3] */ + "mul x3, x14, x9\n\t" + "umulh x4, x14, x9\n\t" + "adds x13, x13, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x3, x15, x8\n\t" + "umulh x4, x15, x8\n\t" + "adds x13, x13, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, x26, xzr\n\t" + /* A[2] * B[1] */ + "mul x3, x16, x7\n\t" + "umulh x4, x16, x7\n\t" + "adds x13, x13, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, x26, xzr\n\t" + /* A[3] * B[0] */ + "mul x3, x17, x6\n\t" + "umulh x4, x17, x6\n\t" + "adds x13, x13, x3\n\t" + "adcs %x[a], %x[a], x4\n\t" + "adc x26, x26, xzr\n\t" + /* A[1] * B[3] */ + "mul x3, x15, x9\n\t" + "umulh x4, x15, x9\n\t" + "adds %x[a], %x[a], x3\n\t" + "adcs x26, x26, x4\n\t" + "adc x27, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x3, x16, x8\n\t" + "umulh x4, x16, x8\n\t" + "adds %x[a], %x[a], x3\n\t" + "adcs x26, x26, x4\n\t" + "adc x27, x27, xzr\n\t" + /* A[3] * B[1] */ + "mul x3, x17, x7\n\t" + "umulh x4, x17, x7\n\t" + "adds %x[a], %x[a], x3\n\t" + "adcs x26, x26, x4\n\t" + "adc x27, x27, xzr\n\t" + /* A[2] * B[3] */ + "mul x3, x16, x9\n\t" + "umulh x4, x16, x9\n\t" + "adds x26, x26, x3\n\t" + "adcs x27, x27, x4\n\t" + "adc x28, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x3, x17, x8\n\t" + "umulh x4, x17, x8\n\t" + "adds x26, x26, x3\n\t" + "adcs x27, x27, x4\n\t" + "adc x28, x28, xzr\n\t" + /* A[3] * B[3] */ + "mul x3, x17, x9\n\t" + "umulh x4, x17, x9\n\t" + "adds x27, x27, x3\n\t" + "adc x28, x28, x4\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x28, x28, x27, #63\n\t" + "extr x27, x27, x26, #63\n\t" + "extr x26, x26, %x[a], #63\n\t" + "extr %x[a], %x[a], x13, #63\n\t" + "and x13, x13, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x3, #19\n\t" + "mul x4, x3, %x[a]\n\t" + "umulh %x[a], x3, %x[a]\n\t" + "adds x10, x10, x4\n\t" + "mul x4, x3, x26\n\t" + "umulh x26, x3, x26\n\t" + "adcs x11, x11, x4\n\t" + "mul x4, x3, x27\n\t" + "umulh x27, x3, x27\n\t" + "adcs x12, x12, x4\n\t" + "mul x4, x3, x28\n\t" + "umulh x5, x3, x28\n\t" + "adcs x13, x13, x4\n\t" + "adc x5, x5, xzr\n\t" + /* Add remaining product results in */ + "adds x11, x11, %x[a]\n\t" + "adcs x12, x12, x26\n\t" + "adcs x13, x13, x27\n\t" + "adc x5, x5, xzr\n\t" + /* Overflow */ + "extr x5, x5, x13, #63\n\t" + "mul x5, x5, x3\n\t" + "and x13, x13, #0x7fffffffffffffff\n\t" + "adds x10, x10, x5\n\t" + "adcs x11, x11, xzr\n\t" + "adcs x12, x12, xzr\n\t" + "adc x13, x13, xzr\n\t" + /* Reduce if top bit set */ + "and x5, x3, x13, asr 63\n\t" + "and x13, x13, #0x7fffffffffffffff\n\t" + "adds x10, x10, x5\n\t" + "adcs x11, x11, xzr\n\t" + "adcs x12, x12, xzr\n\t" + "adc x13, x13, xzr\n\t" + /* Store */ + "stp x10, x11, [x29, #48]\n\t" + "stp x12, x13, [x29, #64]\n\t" + "sub x25, x25, #1\n\t" + "cmp x25, #0\n\t" + "bge L_curve25519_bits_%=\n\t" + "mov x25, #63\n\t" + "sub x24, x24, #8\n\t" + "cmp x24, #0\n\t" + "bge L_curve25519_words_%=\n\t" + /* Invert */ + "add x0, x29, #48\n\t" + "add x1, x29, #16\n\t" + "bl fe_sq\n\t" + "add x0, x29, #0x50\n\t" + "add x1, x29, #48\n\t" + "bl fe_sq\n\t" + "add x1, x29, #0x50\n\t" + "bl fe_sq\n\t" + "add x1, x29, #16\n\t" + "add x2, x29, #0x50\n\t" + "bl fe_mul\n\t" + "add x0, x29, #48\n\t" + "add x1, x29, #48\n\t" + "add x2, x29, #0x50\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x70\n\t" + "bl fe_sq\n\t" + "add x0, x29, #0x50\n\t" + "add x1, x29, #0x50\n\t" + "add x2, x29, #0x70\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x70\n\t" + "bl fe_sq\n\t" + "mov x24, #4\n\t" + "add x1, x29, #0x70\n\t" + "\n" + "L_curve25519_inv_1_%=: \n\t" + "bl fe_sq\n\t" + "sub x24, x24, #1\n\t" + "cmp x24, #0\n\t" + "bne L_curve25519_inv_1_%=\n\t" + "add x0, x29, #0x50\n\t" + "add x2, x29, #0x50\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x70\n\t" + "add x1, x29, #0x50\n\t" + "bl fe_sq\n\t" + "mov x24, #9\n\t" + "add x1, x29, #0x70\n\t" + "\n" + "L_curve25519_inv_2_%=: \n\t" + "bl fe_sq\n\t" + "sub x24, x24, #1\n\t" + "cmp x24, #0\n\t" + "bne L_curve25519_inv_2_%=\n\t" + "add x2, x29, #0x50\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x90\n\t" + "bl fe_sq\n\t" + "mov x24, #19\n\t" + "add x1, x29, #0x90\n\t" + "\n" + "L_curve25519_inv_3_%=: \n\t" + "bl fe_sq\n\t" + "sub x24, x24, #1\n\t" + "cmp x24, #0\n\t" + "bne L_curve25519_inv_3_%=\n\t" + "add x0, x29, #0x70\n\t" + "add x2, x29, #0x70\n\t" + "bl fe_mul\n\t" + "mov x24, #10\n\t" + "add x1, x29, #0x70\n\t" + "\n" + "L_curve25519_inv_4_%=: \n\t" + "bl fe_sq\n\t" + "sub x24, x24, #1\n\t" + "cmp x24, #0\n\t" + "bne L_curve25519_inv_4_%=\n\t" + "add x0, x29, #0x50\n\t" + "add x2, x29, #0x50\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x70\n\t" + "add x1, x29, #0x50\n\t" + "bl fe_sq\n\t" + "mov x24, #49\n\t" + "add x1, x29, #0x70\n\t" + "\n" + "L_curve25519_inv_5_%=: \n\t" + "bl fe_sq\n\t" + "sub x24, x24, #1\n\t" + "cmp x24, #0\n\t" + "bne L_curve25519_inv_5_%=\n\t" + "add x2, x29, #0x50\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x90\n\t" + "bl fe_sq\n\t" + "mov x24, #0x63\n\t" + "add x1, x29, #0x90\n\t" + "\n" + "L_curve25519_inv_6_%=: \n\t" + "bl fe_sq\n\t" + "sub x24, x24, #1\n\t" + "cmp x24, #0\n\t" + "bne L_curve25519_inv_6_%=\n\t" + "add x0, x29, #0x70\n\t" + "add x2, x29, #0x70\n\t" + "bl fe_mul\n\t" + "mov x24, #50\n\t" + "add x1, x29, #0x70\n\t" + "\n" + "L_curve25519_inv_7_%=: \n\t" + "bl fe_sq\n\t" + "sub x24, x24, #1\n\t" + "cmp x24, #0\n\t" + "bne L_curve25519_inv_7_%=\n\t" + "add x0, x29, #0x50\n\t" + "add x2, x29, #0x50\n\t" + "bl fe_mul\n\t" + "mov x24, #5\n\t" + "add x1, x29, #0x50\n\t" + "\n" + "L_curve25519_inv_8_%=: \n\t" + "bl fe_sq\n\t" + "sub x24, x24, #1\n\t" + "cmp x24, #0\n\t" + "bne L_curve25519_inv_8_%=\n\t" + "add x0, x29, #16\n\t" + "add x2, x29, #48\n\t" + "bl fe_mul\n\t" + "ldr %x[r], [x29, #176]\n\t" + /* Multiply */ + "ldp x6, x7, [%x[r]]\n\t" + "ldp x8, x9, [%x[r], #16]\n\t" + "ldp x10, x11, [x29, #16]\n\t" + "ldp x12, x13, [x29, #32]\n\t" + /* A[0] * B[0] */ + "mul x14, x6, x10\n\t" + "umulh x15, x6, x10\n\t" + /* A[0] * B[1] */ + "mul x3, x6, x11\n\t" + "umulh x16, x6, x11\n\t" + "adds x15, x15, x3\n\t" + "adc x16, x16, xzr\n\t" + /* A[1] * B[0] */ + "mul x3, x7, x10\n\t" + "umulh x4, x7, x10\n\t" + "adds x15, x15, x3\n\t" + "adcs x16, x16, x4\n\t" + "adc x17, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x3, x6, x12\n\t" + "umulh x4, x6, x12\n\t" + "adds x16, x16, x3\n\t" + "adc x17, x17, x4\n\t" + /* A[1] * B[1] */ + "mul x3, x7, x11\n\t" + "umulh x4, x7, x11\n\t" + "adds x16, x16, x3\n\t" + "adcs x17, x17, x4\n\t" + "adc x19, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x3, x8, x10\n\t" + "umulh x4, x8, x10\n\t" + "adds x16, x16, x3\n\t" + "adcs x17, x17, x4\n\t" + "adc x19, x19, xzr\n\t" + /* A[0] * B[3] */ + "mul x3, x6, x13\n\t" + "umulh x4, x6, x13\n\t" + "adds x17, x17, x3\n\t" + "adcs x19, x19, x4\n\t" + "adc x20, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x3, x7, x12\n\t" + "umulh x4, x7, x12\n\t" + "adds x17, x17, x3\n\t" + "adcs x19, x19, x4\n\t" + "adc x20, x20, xzr\n\t" + /* A[2] * B[1] */ + "mul x3, x8, x11\n\t" + "umulh x4, x8, x11\n\t" + "adds x17, x17, x3\n\t" + "adcs x19, x19, x4\n\t" + "adc x20, x20, xzr\n\t" + /* A[3] * B[0] */ + "mul x3, x9, x10\n\t" + "umulh x4, x9, x10\n\t" + "adds x17, x17, x3\n\t" + "adcs x19, x19, x4\n\t" + "adc x20, x20, xzr\n\t" + /* A[1] * B[3] */ + "mul x3, x7, x13\n\t" + "umulh x4, x7, x13\n\t" + "adds x19, x19, x3\n\t" + "adcs x20, x20, x4\n\t" + "adc x21, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x3, x8, x12\n\t" + "umulh x4, x8, x12\n\t" + "adds x19, x19, x3\n\t" + "adcs x20, x20, x4\n\t" + "adc x21, x21, xzr\n\t" + /* A[3] * B[1] */ + "mul x3, x9, x11\n\t" + "umulh x4, x9, x11\n\t" + "adds x19, x19, x3\n\t" + "adcs x20, x20, x4\n\t" + "adc x21, x21, xzr\n\t" + /* A[2] * B[3] */ + "mul x3, x8, x13\n\t" + "umulh x4, x8, x13\n\t" + "adds x20, x20, x3\n\t" + "adcs x21, x21, x4\n\t" + "adc x22, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x3, x9, x12\n\t" + "umulh x4, x9, x12\n\t" + "adds x20, x20, x3\n\t" + "adcs x21, x21, x4\n\t" + "adc x22, x22, xzr\n\t" + /* A[3] * B[3] */ + "mul x3, x9, x13\n\t" + "umulh x4, x9, x13\n\t" + "adds x21, x21, x3\n\t" + "adc x22, x22, x4\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x22, x22, x21, #63\n\t" + "extr x21, x21, x20, #63\n\t" + "extr x20, x20, x19, #63\n\t" + "extr x19, x19, x17, #63\n\t" + "and x17, x17, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x3, #19\n\t" + "mul x4, x3, x19\n\t" + "umulh x19, x3, x19\n\t" + "adds x14, x14, x4\n\t" + "mul x4, x3, x20\n\t" + "umulh x20, x3, x20\n\t" + "adcs x15, x15, x4\n\t" + "mul x4, x3, x21\n\t" + "umulh x21, x3, x21\n\t" + "adcs x16, x16, x4\n\t" + "mul x4, x3, x22\n\t" + "umulh x5, x3, x22\n\t" + "adcs x17, x17, x4\n\t" + "adc x5, x5, xzr\n\t" + /* Add remaining product results in */ + "adds x15, x15, x19\n\t" + "adcs x16, x16, x20\n\t" + "adcs x17, x17, x21\n\t" + "adc x5, x5, xzr\n\t" + /* Overflow */ + "extr x5, x5, x17, #63\n\t" + "mul x5, x5, x3\n\t" + "and x17, x17, #0x7fffffffffffffff\n\t" + "adds x14, x14, x5\n\t" + "adcs x15, x15, xzr\n\t" + "adcs x16, x16, xzr\n\t" + "adc x17, x17, xzr\n\t" + /* Reduce if top bit set */ + "and x5, x3, x17, asr 63\n\t" + "and x17, x17, #0x7fffffffffffffff\n\t" + "adds x14, x14, x5\n\t" + "adcs x15, x15, xzr\n\t" + "adcs x16, x16, xzr\n\t" + "adc x17, x17, xzr\n\t" + /* Store */ + "stp x14, x15, [%x[r]]\n\t" + "stp x16, x17, [%x[r], #16]\n\t" + "mov x0, xzr\n\t" + "ldp x29, x30, [sp], #0xc0\n\t" + : [r] "+r" (r), [n] "+r" (n), [a] "+r" (a) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); + return (uint32_t)(size_t)r; +} + +void fe_pow22523(fe r, const fe a) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-128]!\n\t" + "add x29, sp, #0\n\t" + /* pow22523 */ + "str %x[r], [x29, #112]\n\t" + "str %x[a], [x29, #120]\n\t" + "add x0, x29, #16\n\t" + "bl fe_sq\n\t" + "add x0, x29, #48\n\t" + "add x1, x29, #16\n\t" + "bl fe_sq\n\t" + "add x1, x29, #48\n\t" + "bl fe_sq\n\t" + "ldr x1, [x29, #120]\n\t" + "add x2, x29, #48\n\t" + "bl fe_mul\n\t" + "add x0, x29, #16\n\t" + "add x1, x29, #16\n\t" + "add x2, x29, #48\n\t" + "bl fe_mul\n\t" + "bl fe_sq\n\t" + "add x1, x29, #48\n\t" + "add x2, x29, #16\n\t" + "bl fe_mul\n\t" + "add x0, x29, #48\n\t" + "add x1, x29, #16\n\t" + "bl fe_sq\n\t" + "mov x21, #4\n\t" + "add x1, x29, #48\n\t" + "\n" + "L_fe_pow22523_1_%=: \n\t" + "bl fe_sq\n\t" + "sub x21, x21, #1\n\t" + "cmp x21, #0\n\t" + "bne L_fe_pow22523_1_%=\n\t" + "add x0, x29, #16\n\t" + "add x2, x29, #16\n\t" + "bl fe_mul\n\t" + "add x0, x29, #48\n\t" + "add x1, x29, #16\n\t" + "bl fe_sq\n\t" + "mov x21, #9\n\t" + "add x1, x29, #48\n\t" + "\n" + "L_fe_pow22523_2_%=: \n\t" + "bl fe_sq\n\t" + "sub x21, x21, #1\n\t" + "cmp x21, #0\n\t" + "bne L_fe_pow22523_2_%=\n\t" + "add x2, x29, #16\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x50\n\t" + "bl fe_sq\n\t" + "mov x21, #19\n\t" + "add x1, x29, #0x50\n\t" + "\n" + "L_fe_pow22523_3_%=: \n\t" + "bl fe_sq\n\t" + "sub x21, x21, #1\n\t" + "cmp x21, #0\n\t" + "bne L_fe_pow22523_3_%=\n\t" + "add x0, x29, #48\n\t" + "add x2, x29, #48\n\t" + "bl fe_mul\n\t" + "mov x21, #10\n\t" + "add x1, x29, #48\n\t" + "\n" + "L_fe_pow22523_4_%=: \n\t" + "bl fe_sq\n\t" + "sub x21, x21, #1\n\t" + "cmp x21, #0\n\t" + "bne L_fe_pow22523_4_%=\n\t" + "add x0, x29, #16\n\t" + "add x2, x29, #16\n\t" + "bl fe_mul\n\t" + "add x0, x29, #48\n\t" + "add x1, x29, #16\n\t" + "bl fe_sq\n\t" + "mov x21, #49\n\t" + "add x1, x29, #48\n\t" + "\n" + "L_fe_pow22523_5_%=: \n\t" + "bl fe_sq\n\t" + "sub x21, x21, #1\n\t" + "cmp x21, #0\n\t" + "bne L_fe_pow22523_5_%=\n\t" + "add x2, x29, #16\n\t" + "bl fe_mul\n\t" + "add x0, x29, #0x50\n\t" + "bl fe_sq\n\t" + "mov x21, #0x63\n\t" + "add x1, x29, #0x50\n\t" + "\n" + "L_fe_pow22523_6_%=: \n\t" + "bl fe_sq\n\t" + "sub x21, x21, #1\n\t" + "cmp x21, #0\n\t" + "bne L_fe_pow22523_6_%=\n\t" + "add x0, x29, #48\n\t" + "add x2, x29, #48\n\t" + "bl fe_mul\n\t" + "mov x21, #50\n\t" + "add x1, x29, #48\n\t" + "\n" + "L_fe_pow22523_7_%=: \n\t" + "bl fe_sq\n\t" + "sub x21, x21, #1\n\t" + "cmp x21, #0\n\t" + "bne L_fe_pow22523_7_%=\n\t" + "add x0, x29, #16\n\t" + "add x2, x29, #16\n\t" + "bl fe_mul\n\t" + "mov x21, #2\n\t" + "add x1, x29, #16\n\t" + "\n" + "L_fe_pow22523_8_%=: \n\t" + "bl fe_sq\n\t" + "sub x21, x21, #1\n\t" + "cmp x21, #0\n\t" + "bne L_fe_pow22523_8_%=\n\t" + "ldr x0, [x29, #112]\n\t" + "ldr x2, [x29, #120]\n\t" + "bl fe_mul\n\t" + "ldp x29, x30, [sp], #0x80\n\t" + : [r] "+r" (r), [a] "+r" (a) + : + : "memory", "x21" + ); +} + +void fe_ge_to_p2(fe rx, fe ry, fe rz, const fe px, const fe py, const fe pz, const fe pt) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-64]!\n\t" + "add x29, sp, #0\n\t" + "str %x[ry], [x29, #16]\n\t" + "str %x[rz], [x29, #24]\n\t" + "str %x[px], [x29, #32]\n\t" + "str %x[py], [x29, #40]\n\t" + "str %x[pz], [x29, #48]\n\t" + "str %x[pt], [x29, #56]\n\t" + "ldr x1, [x29, #32]\n\t" + "ldr x2, [x29, #56]\n\t" + /* Multiply */ + "ldp x11, x12, [x1]\n\t" + "ldp x13, x14, [x1, #16]\n\t" + "ldp x15, x16, [x2]\n\t" + "ldp x17, x19, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x3, x11, x15\n\t" + "umulh x4, x11, x15\n\t" + /* A[0] * B[1] */ + "mul x20, x11, x16\n\t" + "umulh x5, x11, x16\n\t" + "adds x4, x4, x20\n\t" + "adc x5, x5, xzr\n\t" + /* A[1] * B[0] */ + "mul x20, x12, x15\n\t" + "umulh x21, x12, x15\n\t" + "adds x4, x4, x20\n\t" + "adcs x5, x5, x21\n\t" + "adc x6, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x20, x11, x17\n\t" + "umulh x21, x11, x17\n\t" + "adds x5, x5, x20\n\t" + "adc x6, x6, x21\n\t" + /* A[1] * B[1] */ + "mul x20, x12, x16\n\t" + "umulh x21, x12, x16\n\t" + "adds x5, x5, x20\n\t" + "adcs x6, x6, x21\n\t" + "adc x7, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x20, x13, x15\n\t" + "umulh x21, x13, x15\n\t" + "adds x5, x5, x20\n\t" + "adcs x6, x6, x21\n\t" + "adc x7, x7, xzr\n\t" + /* A[0] * B[3] */ + "mul x20, x11, x19\n\t" + "umulh x21, x11, x19\n\t" + "adds x6, x6, x20\n\t" + "adcs x7, x7, x21\n\t" + "adc x8, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x20, x12, x17\n\t" + "umulh x21, x12, x17\n\t" + "adds x6, x6, x20\n\t" + "adcs x7, x7, x21\n\t" + "adc x8, x8, xzr\n\t" + /* A[2] * B[1] */ + "mul x20, x13, x16\n\t" + "umulh x21, x13, x16\n\t" + "adds x6, x6, x20\n\t" + "adcs x7, x7, x21\n\t" + "adc x8, x8, xzr\n\t" + /* A[3] * B[0] */ + "mul x20, x14, x15\n\t" + "umulh x21, x14, x15\n\t" + "adds x6, x6, x20\n\t" + "adcs x7, x7, x21\n\t" + "adc x8, x8, xzr\n\t" + /* A[1] * B[3] */ + "mul x20, x12, x19\n\t" + "umulh x21, x12, x19\n\t" + "adds x7, x7, x20\n\t" + "adcs x8, x8, x21\n\t" + "adc x9, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x20, x13, x17\n\t" + "umulh x21, x13, x17\n\t" + "adds x7, x7, x20\n\t" + "adcs x8, x8, x21\n\t" + "adc x9, x9, xzr\n\t" + /* A[3] * B[1] */ + "mul x20, x14, x16\n\t" + "umulh x21, x14, x16\n\t" + "adds x7, x7, x20\n\t" + "adcs x8, x8, x21\n\t" + "adc x9, x9, xzr\n\t" + /* A[2] * B[3] */ + "mul x20, x13, x19\n\t" + "umulh x21, x13, x19\n\t" + "adds x8, x8, x20\n\t" + "adcs x9, x9, x21\n\t" + "adc x10, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x20, x14, x17\n\t" + "umulh x21, x14, x17\n\t" + "adds x8, x8, x20\n\t" + "adcs x9, x9, x21\n\t" + "adc x10, x10, xzr\n\t" + /* A[3] * B[3] */ + "mul x20, x14, x19\n\t" + "umulh x21, x14, x19\n\t" + "adds x9, x9, x20\n\t" + "adc x10, x10, x21\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "extr x8, x8, x7, #63\n\t" + "extr x7, x7, x6, #63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x20, #19\n\t" + "mul x21, x20, x7\n\t" + "umulh x7, x20, x7\n\t" + "adds x3, x3, x21\n\t" + "mul x21, x20, x8\n\t" + "umulh x8, x20, x8\n\t" + "adcs x4, x4, x21\n\t" + "mul x21, x20, x9\n\t" + "umulh x9, x20, x9\n\t" + "adcs x5, x5, x21\n\t" + "mul x21, x20, x10\n\t" + "umulh x22, x20, x10\n\t" + "adcs x6, x6, x21\n\t" + "adc x22, x22, xzr\n\t" + /* Add remaining product results in */ + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x22, x22, xzr\n\t" + /* Overflow */ + "extr x22, x22, x6, #63\n\t" + "mul x22, x22, x20\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x22\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Reduce if top bit set */ + "and x22, x20, x6, asr 63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x22\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Store */ + "stp x3, x4, [x0]\n\t" + "stp x5, x6, [x0, #16]\n\t" + "ldr x0, [x29, #16]\n\t" + "ldr x1, [x29, #40]\n\t" + "ldr x2, [x29, #48]\n\t" + /* Multiply */ + "ldp x11, x12, [x1]\n\t" + "ldp x13, x14, [x1, #16]\n\t" + "ldp x15, x16, [x2]\n\t" + "ldp x17, x19, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x3, x11, x15\n\t" + "umulh x4, x11, x15\n\t" + /* A[0] * B[1] */ + "mul x20, x11, x16\n\t" + "umulh x5, x11, x16\n\t" + "adds x4, x4, x20\n\t" + "adc x5, x5, xzr\n\t" + /* A[1] * B[0] */ + "mul x20, x12, x15\n\t" + "umulh x21, x12, x15\n\t" + "adds x4, x4, x20\n\t" + "adcs x5, x5, x21\n\t" + "adc x6, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x20, x11, x17\n\t" + "umulh x21, x11, x17\n\t" + "adds x5, x5, x20\n\t" + "adc x6, x6, x21\n\t" + /* A[1] * B[1] */ + "mul x20, x12, x16\n\t" + "umulh x21, x12, x16\n\t" + "adds x5, x5, x20\n\t" + "adcs x6, x6, x21\n\t" + "adc x7, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x20, x13, x15\n\t" + "umulh x21, x13, x15\n\t" + "adds x5, x5, x20\n\t" + "adcs x6, x6, x21\n\t" + "adc x7, x7, xzr\n\t" + /* A[0] * B[3] */ + "mul x20, x11, x19\n\t" + "umulh x21, x11, x19\n\t" + "adds x6, x6, x20\n\t" + "adcs x7, x7, x21\n\t" + "adc x8, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x20, x12, x17\n\t" + "umulh x21, x12, x17\n\t" + "adds x6, x6, x20\n\t" + "adcs x7, x7, x21\n\t" + "adc x8, x8, xzr\n\t" + /* A[2] * B[1] */ + "mul x20, x13, x16\n\t" + "umulh x21, x13, x16\n\t" + "adds x6, x6, x20\n\t" + "adcs x7, x7, x21\n\t" + "adc x8, x8, xzr\n\t" + /* A[3] * B[0] */ + "mul x20, x14, x15\n\t" + "umulh x21, x14, x15\n\t" + "adds x6, x6, x20\n\t" + "adcs x7, x7, x21\n\t" + "adc x8, x8, xzr\n\t" + /* A[1] * B[3] */ + "mul x20, x12, x19\n\t" + "umulh x21, x12, x19\n\t" + "adds x7, x7, x20\n\t" + "adcs x8, x8, x21\n\t" + "adc x9, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x20, x13, x17\n\t" + "umulh x21, x13, x17\n\t" + "adds x7, x7, x20\n\t" + "adcs x8, x8, x21\n\t" + "adc x9, x9, xzr\n\t" + /* A[3] * B[1] */ + "mul x20, x14, x16\n\t" + "umulh x21, x14, x16\n\t" + "adds x7, x7, x20\n\t" + "adcs x8, x8, x21\n\t" + "adc x9, x9, xzr\n\t" + /* A[2] * B[3] */ + "mul x20, x13, x19\n\t" + "umulh x21, x13, x19\n\t" + "adds x8, x8, x20\n\t" + "adcs x9, x9, x21\n\t" + "adc x10, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x20, x14, x17\n\t" + "umulh x21, x14, x17\n\t" + "adds x8, x8, x20\n\t" + "adcs x9, x9, x21\n\t" + "adc x10, x10, xzr\n\t" + /* A[3] * B[3] */ + "mul x20, x14, x19\n\t" + "umulh x21, x14, x19\n\t" + "adds x9, x9, x20\n\t" + "adc x10, x10, x21\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "extr x8, x8, x7, #63\n\t" + "extr x7, x7, x6, #63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x20, #19\n\t" + "mul x21, x20, x7\n\t" + "umulh x7, x20, x7\n\t" + "adds x3, x3, x21\n\t" + "mul x21, x20, x8\n\t" + "umulh x8, x20, x8\n\t" + "adcs x4, x4, x21\n\t" + "mul x21, x20, x9\n\t" + "umulh x9, x20, x9\n\t" + "adcs x5, x5, x21\n\t" + "mul x21, x20, x10\n\t" + "umulh x22, x20, x10\n\t" + "adcs x6, x6, x21\n\t" + "adc x22, x22, xzr\n\t" + /* Add remaining product results in */ + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x22, x22, xzr\n\t" + /* Overflow */ + "extr x22, x22, x6, #63\n\t" + "mul x22, x22, x20\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x22\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Reduce if top bit set */ + "and x22, x20, x6, asr 63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x22\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Store */ + "stp x3, x4, [x0]\n\t" + "stp x5, x6, [x0, #16]\n\t" + "ldr x0, [x29, #24]\n\t" + "ldr x2, [x29, #56]\n\t" + /* Multiply */ + "ldp x11, x12, [x2]\n\t" + "ldp x13, x14, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x3, x15, x11\n\t" + "umulh x4, x15, x11\n\t" + /* A[0] * B[1] */ + "mul x20, x15, x12\n\t" + "umulh x5, x15, x12\n\t" + "adds x4, x4, x20\n\t" + "adc x5, x5, xzr\n\t" + /* A[1] * B[0] */ + "mul x20, x16, x11\n\t" + "umulh x21, x16, x11\n\t" + "adds x4, x4, x20\n\t" + "adcs x5, x5, x21\n\t" + "adc x6, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x20, x15, x13\n\t" + "umulh x21, x15, x13\n\t" + "adds x5, x5, x20\n\t" + "adc x6, x6, x21\n\t" + /* A[1] * B[1] */ + "mul x20, x16, x12\n\t" + "umulh x21, x16, x12\n\t" + "adds x5, x5, x20\n\t" + "adcs x6, x6, x21\n\t" + "adc x7, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x20, x17, x11\n\t" + "umulh x21, x17, x11\n\t" + "adds x5, x5, x20\n\t" + "adcs x6, x6, x21\n\t" + "adc x7, x7, xzr\n\t" + /* A[0] * B[3] */ + "mul x20, x15, x14\n\t" + "umulh x21, x15, x14\n\t" + "adds x6, x6, x20\n\t" + "adcs x7, x7, x21\n\t" + "adc x8, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x20, x16, x13\n\t" + "umulh x21, x16, x13\n\t" + "adds x6, x6, x20\n\t" + "adcs x7, x7, x21\n\t" + "adc x8, x8, xzr\n\t" + /* A[2] * B[1] */ + "mul x20, x17, x12\n\t" + "umulh x21, x17, x12\n\t" + "adds x6, x6, x20\n\t" + "adcs x7, x7, x21\n\t" + "adc x8, x8, xzr\n\t" + /* A[3] * B[0] */ + "mul x20, x19, x11\n\t" + "umulh x21, x19, x11\n\t" + "adds x6, x6, x20\n\t" + "adcs x7, x7, x21\n\t" + "adc x8, x8, xzr\n\t" + /* A[1] * B[3] */ + "mul x20, x16, x14\n\t" + "umulh x21, x16, x14\n\t" + "adds x7, x7, x20\n\t" + "adcs x8, x8, x21\n\t" + "adc x9, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x20, x17, x13\n\t" + "umulh x21, x17, x13\n\t" + "adds x7, x7, x20\n\t" + "adcs x8, x8, x21\n\t" + "adc x9, x9, xzr\n\t" + /* A[3] * B[1] */ + "mul x20, x19, x12\n\t" + "umulh x21, x19, x12\n\t" + "adds x7, x7, x20\n\t" + "adcs x8, x8, x21\n\t" + "adc x9, x9, xzr\n\t" + /* A[2] * B[3] */ + "mul x20, x17, x14\n\t" + "umulh x21, x17, x14\n\t" + "adds x8, x8, x20\n\t" + "adcs x9, x9, x21\n\t" + "adc x10, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x20, x19, x13\n\t" + "umulh x21, x19, x13\n\t" + "adds x8, x8, x20\n\t" + "adcs x9, x9, x21\n\t" + "adc x10, x10, xzr\n\t" + /* A[3] * B[3] */ + "mul x20, x19, x14\n\t" + "umulh x21, x19, x14\n\t" + "adds x9, x9, x20\n\t" + "adc x10, x10, x21\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "extr x8, x8, x7, #63\n\t" + "extr x7, x7, x6, #63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x20, #19\n\t" + "mul x21, x20, x7\n\t" + "umulh x7, x20, x7\n\t" + "adds x3, x3, x21\n\t" + "mul x21, x20, x8\n\t" + "umulh x8, x20, x8\n\t" + "adcs x4, x4, x21\n\t" + "mul x21, x20, x9\n\t" + "umulh x9, x20, x9\n\t" + "adcs x5, x5, x21\n\t" + "mul x21, x20, x10\n\t" + "umulh x22, x20, x10\n\t" + "adcs x6, x6, x21\n\t" + "adc x22, x22, xzr\n\t" + /* Add remaining product results in */ + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x22, x22, xzr\n\t" + /* Overflow */ + "extr x22, x22, x6, #63\n\t" + "mul x22, x22, x20\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x22\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Reduce if top bit set */ + "and x22, x20, x6, asr 63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x22\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Store */ + "stp x3, x4, [x0]\n\t" + "stp x5, x6, [x0, #16]\n\t" + "ldp x29, x30, [sp], #0x40\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + : + : "memory", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22" + ); +} + +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) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-80]!\n\t" + "add x29, sp, #0\n\t" + "str %x[ry], [x29, #16]\n\t" + "str %x[rz], [x29, #24]\n\t" + "str %x[rt], [x29, #32]\n\t" + "str %x[px], [x29, #40]\n\t" + "str %x[py], [x29, #48]\n\t" + "str %x[pz], [x29, #56]\n\t" + "str %x[pt], [x29, #64]\n\t" + "ldr x1, [x29, #40]\n\t" + "ldr x2, [x29, #64]\n\t" + /* Multiply */ + "ldp x11, x12, [x1]\n\t" + "ldp x13, x14, [x1, #16]\n\t" + "ldp x15, x16, [x2]\n\t" + "ldp x17, x19, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x3, x11, x15\n\t" + "umulh x4, x11, x15\n\t" + /* A[0] * B[1] */ + "mul x24, x11, x16\n\t" + "umulh x5, x11, x16\n\t" + "adds x4, x4, x24\n\t" + "adc x5, x5, xzr\n\t" + /* A[1] * B[0] */ + "mul x24, x12, x15\n\t" + "umulh x25, x12, x15\n\t" + "adds x4, x4, x24\n\t" + "adcs x5, x5, x25\n\t" + "adc x6, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x24, x11, x17\n\t" + "umulh x25, x11, x17\n\t" + "adds x5, x5, x24\n\t" + "adc x6, x6, x25\n\t" + /* A[1] * B[1] */ + "mul x24, x12, x16\n\t" + "umulh x25, x12, x16\n\t" + "adds x5, x5, x24\n\t" + "adcs x6, x6, x25\n\t" + "adc x7, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x24, x13, x15\n\t" + "umulh x25, x13, x15\n\t" + "adds x5, x5, x24\n\t" + "adcs x6, x6, x25\n\t" + "adc x7, x7, xzr\n\t" + /* A[0] * B[3] */ + "mul x24, x11, x19\n\t" + "umulh x25, x11, x19\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x24, x12, x17\n\t" + "umulh x25, x12, x17\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[2] * B[1] */ + "mul x24, x13, x16\n\t" + "umulh x25, x13, x16\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[3] * B[0] */ + "mul x24, x14, x15\n\t" + "umulh x25, x14, x15\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[1] * B[3] */ + "mul x24, x12, x19\n\t" + "umulh x25, x12, x19\n\t" + "adds x7, x7, x24\n\t" + "adcs x8, x8, x25\n\t" + "adc x9, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x24, x13, x17\n\t" + "umulh x25, x13, x17\n\t" + "adds x7, x7, x24\n\t" + "adcs x8, x8, x25\n\t" + "adc x9, x9, xzr\n\t" + /* A[3] * B[1] */ + "mul x24, x14, x16\n\t" + "umulh x25, x14, x16\n\t" + "adds x7, x7, x24\n\t" + "adcs x8, x8, x25\n\t" + "adc x9, x9, xzr\n\t" + /* A[2] * B[3] */ + "mul x24, x13, x19\n\t" + "umulh x25, x13, x19\n\t" + "adds x8, x8, x24\n\t" + "adcs x9, x9, x25\n\t" + "adc x10, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x24, x14, x17\n\t" + "umulh x25, x14, x17\n\t" + "adds x8, x8, x24\n\t" + "adcs x9, x9, x25\n\t" + "adc x10, x10, xzr\n\t" + /* A[3] * B[3] */ + "mul x24, x14, x19\n\t" + "umulh x25, x14, x19\n\t" + "adds x9, x9, x24\n\t" + "adc x10, x10, x25\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "extr x8, x8, x7, #63\n\t" + "extr x7, x7, x6, #63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x24, #19\n\t" + "mul x25, x24, x7\n\t" + "umulh x7, x24, x7\n\t" + "adds x3, x3, x25\n\t" + "mul x25, x24, x8\n\t" + "umulh x8, x24, x8\n\t" + "adcs x4, x4, x25\n\t" + "mul x25, x24, x9\n\t" + "umulh x9, x24, x9\n\t" + "adcs x5, x5, x25\n\t" + "mul x25, x24, x10\n\t" + "umulh x26, x24, x10\n\t" + "adcs x6, x6, x25\n\t" + "adc x26, x26, xzr\n\t" + /* Add remaining product results in */ + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x26, x26, xzr\n\t" + /* Overflow */ + "extr x26, x26, x6, #63\n\t" + "mul x26, x26, x24\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x26\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Reduce if top bit set */ + "and x26, x24, x6, asr 63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x26\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Store */ + "stp x3, x4, [x0]\n\t" + "stp x5, x6, [x0, #16]\n\t" + "ldr x0, [x29, #32]\n\t" + "ldr x2, [x29, #48]\n\t" + /* Multiply */ + "ldp x20, x21, [x2]\n\t" + "ldp x22, x23, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x3, x11, x20\n\t" + "umulh x4, x11, x20\n\t" + /* A[0] * B[1] */ + "mul x24, x11, x21\n\t" + "umulh x5, x11, x21\n\t" + "adds x4, x4, x24\n\t" + "adc x5, x5, xzr\n\t" + /* A[1] * B[0] */ + "mul x24, x12, x20\n\t" + "umulh x25, x12, x20\n\t" + "adds x4, x4, x24\n\t" + "adcs x5, x5, x25\n\t" + "adc x6, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x24, x11, x22\n\t" + "umulh x25, x11, x22\n\t" + "adds x5, x5, x24\n\t" + "adc x6, x6, x25\n\t" + /* A[1] * B[1] */ + "mul x24, x12, x21\n\t" + "umulh x25, x12, x21\n\t" + "adds x5, x5, x24\n\t" + "adcs x6, x6, x25\n\t" + "adc x7, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x24, x13, x20\n\t" + "umulh x25, x13, x20\n\t" + "adds x5, x5, x24\n\t" + "adcs x6, x6, x25\n\t" + "adc x7, x7, xzr\n\t" + /* A[0] * B[3] */ + "mul x24, x11, x23\n\t" + "umulh x25, x11, x23\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x24, x12, x22\n\t" + "umulh x25, x12, x22\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[2] * B[1] */ + "mul x24, x13, x21\n\t" + "umulh x25, x13, x21\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[3] * B[0] */ + "mul x24, x14, x20\n\t" + "umulh x25, x14, x20\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[1] * B[3] */ + "mul x24, x12, x23\n\t" + "umulh x25, x12, x23\n\t" + "adds x7, x7, x24\n\t" + "adcs x8, x8, x25\n\t" + "adc x9, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x24, x13, x22\n\t" + "umulh x25, x13, x22\n\t" + "adds x7, x7, x24\n\t" + "adcs x8, x8, x25\n\t" + "adc x9, x9, xzr\n\t" + /* A[3] * B[1] */ + "mul x24, x14, x21\n\t" + "umulh x25, x14, x21\n\t" + "adds x7, x7, x24\n\t" + "adcs x8, x8, x25\n\t" + "adc x9, x9, xzr\n\t" + /* A[2] * B[3] */ + "mul x24, x13, x23\n\t" + "umulh x25, x13, x23\n\t" + "adds x8, x8, x24\n\t" + "adcs x9, x9, x25\n\t" + "adc x10, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x24, x14, x22\n\t" + "umulh x25, x14, x22\n\t" + "adds x8, x8, x24\n\t" + "adcs x9, x9, x25\n\t" + "adc x10, x10, xzr\n\t" + /* A[3] * B[3] */ + "mul x24, x14, x23\n\t" + "umulh x25, x14, x23\n\t" + "adds x9, x9, x24\n\t" + "adc x10, x10, x25\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "extr x8, x8, x7, #63\n\t" + "extr x7, x7, x6, #63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x24, #19\n\t" + "mul x25, x24, x7\n\t" + "umulh x7, x24, x7\n\t" + "adds x3, x3, x25\n\t" + "mul x25, x24, x8\n\t" + "umulh x8, x24, x8\n\t" + "adcs x4, x4, x25\n\t" + "mul x25, x24, x9\n\t" + "umulh x9, x24, x9\n\t" + "adcs x5, x5, x25\n\t" + "mul x25, x24, x10\n\t" + "umulh x26, x24, x10\n\t" + "adcs x6, x6, x25\n\t" + "adc x26, x26, xzr\n\t" + /* Add remaining product results in */ + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x26, x26, xzr\n\t" + /* Overflow */ + "extr x26, x26, x6, #63\n\t" + "mul x26, x26, x24\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x26\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Reduce if top bit set */ + "and x26, x24, x6, asr 63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x26\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Store */ + "stp x3, x4, [x0]\n\t" + "stp x5, x6, [x0, #16]\n\t" + "ldr x0, [x29, #16]\n\t" + "ldr x2, [x29, #56]\n\t" + /* Multiply */ + "ldp x11, x12, [x2]\n\t" + "ldp x13, x14, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x3, x20, x11\n\t" + "umulh x4, x20, x11\n\t" + /* A[0] * B[1] */ + "mul x24, x20, x12\n\t" + "umulh x5, x20, x12\n\t" + "adds x4, x4, x24\n\t" + "adc x5, x5, xzr\n\t" + /* A[1] * B[0] */ + "mul x24, x21, x11\n\t" + "umulh x25, x21, x11\n\t" + "adds x4, x4, x24\n\t" + "adcs x5, x5, x25\n\t" + "adc x6, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x24, x20, x13\n\t" + "umulh x25, x20, x13\n\t" + "adds x5, x5, x24\n\t" + "adc x6, x6, x25\n\t" + /* A[1] * B[1] */ + "mul x24, x21, x12\n\t" + "umulh x25, x21, x12\n\t" + "adds x5, x5, x24\n\t" + "adcs x6, x6, x25\n\t" + "adc x7, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x24, x22, x11\n\t" + "umulh x25, x22, x11\n\t" + "adds x5, x5, x24\n\t" + "adcs x6, x6, x25\n\t" + "adc x7, x7, xzr\n\t" + /* A[0] * B[3] */ + "mul x24, x20, x14\n\t" + "umulh x25, x20, x14\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x24, x21, x13\n\t" + "umulh x25, x21, x13\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[2] * B[1] */ + "mul x24, x22, x12\n\t" + "umulh x25, x22, x12\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[3] * B[0] */ + "mul x24, x23, x11\n\t" + "umulh x25, x23, x11\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[1] * B[3] */ + "mul x24, x21, x14\n\t" + "umulh x25, x21, x14\n\t" + "adds x7, x7, x24\n\t" + "adcs x8, x8, x25\n\t" + "adc x9, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x24, x22, x13\n\t" + "umulh x25, x22, x13\n\t" + "adds x7, x7, x24\n\t" + "adcs x8, x8, x25\n\t" + "adc x9, x9, xzr\n\t" + /* A[3] * B[1] */ + "mul x24, x23, x12\n\t" + "umulh x25, x23, x12\n\t" + "adds x7, x7, x24\n\t" + "adcs x8, x8, x25\n\t" + "adc x9, x9, xzr\n\t" + /* A[2] * B[3] */ + "mul x24, x22, x14\n\t" + "umulh x25, x22, x14\n\t" + "adds x8, x8, x24\n\t" + "adcs x9, x9, x25\n\t" + "adc x10, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x24, x23, x13\n\t" + "umulh x25, x23, x13\n\t" + "adds x8, x8, x24\n\t" + "adcs x9, x9, x25\n\t" + "adc x10, x10, xzr\n\t" + /* A[3] * B[3] */ + "mul x24, x23, x14\n\t" + "umulh x25, x23, x14\n\t" + "adds x9, x9, x24\n\t" + "adc x10, x10, x25\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "extr x8, x8, x7, #63\n\t" + "extr x7, x7, x6, #63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x24, #19\n\t" + "mul x25, x24, x7\n\t" + "umulh x7, x24, x7\n\t" + "adds x3, x3, x25\n\t" + "mul x25, x24, x8\n\t" + "umulh x8, x24, x8\n\t" + "adcs x4, x4, x25\n\t" + "mul x25, x24, x9\n\t" + "umulh x9, x24, x9\n\t" + "adcs x5, x5, x25\n\t" + "mul x25, x24, x10\n\t" + "umulh x26, x24, x10\n\t" + "adcs x6, x6, x25\n\t" + "adc x26, x26, xzr\n\t" + /* Add remaining product results in */ + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x26, x26, xzr\n\t" + /* Overflow */ + "extr x26, x26, x6, #63\n\t" + "mul x26, x26, x24\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x26\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Reduce if top bit set */ + "and x26, x24, x6, asr 63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x26\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Store */ + "stp x3, x4, [x0]\n\t" + "stp x5, x6, [x0, #16]\n\t" + "ldr x0, [x29, #24]\n\t" + /* Multiply */ + /* A[0] * B[0] */ + "mul x3, x11, x15\n\t" + "umulh x4, x11, x15\n\t" + /* A[0] * B[1] */ + "mul x24, x11, x16\n\t" + "umulh x5, x11, x16\n\t" + "adds x4, x4, x24\n\t" + "adc x5, x5, xzr\n\t" + /* A[1] * B[0] */ + "mul x24, x12, x15\n\t" + "umulh x25, x12, x15\n\t" + "adds x4, x4, x24\n\t" + "adcs x5, x5, x25\n\t" + "adc x6, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x24, x11, x17\n\t" + "umulh x25, x11, x17\n\t" + "adds x5, x5, x24\n\t" + "adc x6, x6, x25\n\t" + /* A[1] * B[1] */ + "mul x24, x12, x16\n\t" + "umulh x25, x12, x16\n\t" + "adds x5, x5, x24\n\t" + "adcs x6, x6, x25\n\t" + "adc x7, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x24, x13, x15\n\t" + "umulh x25, x13, x15\n\t" + "adds x5, x5, x24\n\t" + "adcs x6, x6, x25\n\t" + "adc x7, x7, xzr\n\t" + /* A[0] * B[3] */ + "mul x24, x11, x19\n\t" + "umulh x25, x11, x19\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x24, x12, x17\n\t" + "umulh x25, x12, x17\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[2] * B[1] */ + "mul x24, x13, x16\n\t" + "umulh x25, x13, x16\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[3] * B[0] */ + "mul x24, x14, x15\n\t" + "umulh x25, x14, x15\n\t" + "adds x6, x6, x24\n\t" + "adcs x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[1] * B[3] */ + "mul x24, x12, x19\n\t" + "umulh x25, x12, x19\n\t" + "adds x7, x7, x24\n\t" + "adcs x8, x8, x25\n\t" + "adc x9, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x24, x13, x17\n\t" + "umulh x25, x13, x17\n\t" + "adds x7, x7, x24\n\t" + "adcs x8, x8, x25\n\t" + "adc x9, x9, xzr\n\t" + /* A[3] * B[1] */ + "mul x24, x14, x16\n\t" + "umulh x25, x14, x16\n\t" + "adds x7, x7, x24\n\t" + "adcs x8, x8, x25\n\t" + "adc x9, x9, xzr\n\t" + /* A[2] * B[3] */ + "mul x24, x13, x19\n\t" + "umulh x25, x13, x19\n\t" + "adds x8, x8, x24\n\t" + "adcs x9, x9, x25\n\t" + "adc x10, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x24, x14, x17\n\t" + "umulh x25, x14, x17\n\t" + "adds x8, x8, x24\n\t" + "adcs x9, x9, x25\n\t" + "adc x10, x10, xzr\n\t" + /* A[3] * B[3] */ + "mul x24, x14, x19\n\t" + "umulh x25, x14, x19\n\t" + "adds x9, x9, x24\n\t" + "adc x10, x10, x25\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "extr x8, x8, x7, #63\n\t" + "extr x7, x7, x6, #63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x24, #19\n\t" + "mul x25, x24, x7\n\t" + "umulh x7, x24, x7\n\t" + "adds x3, x3, x25\n\t" + "mul x25, x24, x8\n\t" + "umulh x8, x24, x8\n\t" + "adcs x4, x4, x25\n\t" + "mul x25, x24, x9\n\t" + "umulh x9, x24, x9\n\t" + "adcs x5, x5, x25\n\t" + "mul x25, x24, x10\n\t" + "umulh x26, x24, x10\n\t" + "adcs x6, x6, x25\n\t" + "adc x26, x26, xzr\n\t" + /* Add remaining product results in */ + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x26, x26, xzr\n\t" + /* Overflow */ + "extr x26, x26, x6, #63\n\t" + "mul x26, x26, x24\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x26\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Reduce if top bit set */ + "and x26, x24, x6, asr 63\n\t" + "and x6, x6, #0x7fffffffffffffff\n\t" + "adds x3, x3, x26\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "adc x6, x6, xzr\n\t" + /* Store */ + "stp x3, x4, [x0]\n\t" + "stp x5, x6, [x0, #16]\n\t" + "ldp x29, x30, [sp], #0x50\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + : + : "memory", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26" + ); +} + +void fe_ge_dbl(fe rx, fe ry, fe rz, fe rt, const fe px, const fe py, const fe pz) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-80]!\n\t" + "add x29, sp, #0\n\t" + "str %x[rx], [x29, #16]\n\t" + "str %x[ry], [x29, #24]\n\t" + "str %x[rz], [x29, #32]\n\t" + "str %x[rt], [x29, #40]\n\t" + "str %x[px], [x29, #48]\n\t" + "str %x[py], [x29, #56]\n\t" + "str %x[pz], [x29, #64]\n\t" + "ldr x1, [x29, #48]\n\t" + /* Square */ + "ldp x12, x13, [x1]\n\t" + "ldp x14, x15, [x1, #16]\n\t" + /* A[0] * A[1] */ + "mul x5, x12, x13\n\t" + "umulh x6, x12, x13\n\t" + /* A[0] * A[2] */ + "mul x25, x12, x14\n\t" + "umulh x7, x12, x14\n\t" + "adds x6, x6, x25\n\t" + "adc x7, x7, xzr\n\t" + /* A[0] * A[3] */ + "mul x25, x12, x15\n\t" + "umulh x8, x12, x15\n\t" + "adds x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[1] * A[2] */ + "mul x25, x13, x14\n\t" + "umulh x26, x13, x14\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, xzr, xzr\n\t" + /* A[1] * A[3] */ + "mul x25, x13, x15\n\t" + "umulh x26, x13, x15\n\t" + "adds x8, x8, x25\n\t" + "adc x9, x9, x26\n\t" + /* A[2] * A[3] */ + "mul x25, x14, x15\n\t" + "umulh x10, x14, x15\n\t" + "adds x9, x9, x25\n\t" + "adc x10, x10, xzr\n\t" + /* Double */ + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adcs x7, x7, x7\n\t" + "adcs x8, x8, x8\n\t" + "adcs x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adc x11, xzr, xzr\n\t" + /* A[0] * A[0] */ + "mul x4, x12, x12\n\t" + "umulh x27, x12, x12\n\t" + /* A[1] * A[1] */ + "mul x25, x13, x13\n\t" + "umulh x26, x13, x13\n\t" + "adds x5, x5, x27\n\t" + "adcs x6, x6, x25\n\t" + "adc x27, x26, xzr\n\t" + /* A[2] * A[2] */ + "mul x25, x14, x14\n\t" + "umulh x26, x14, x14\n\t" + "adds x7, x7, x27\n\t" + "adcs x8, x8, x25\n\t" + "adc x27, x26, xzr\n\t" + /* A[3] * A[3] */ + "mul x25, x15, x15\n\t" + "umulh x26, x15, x15\n\t" + "adds x9, x9, x27\n\t" + "adcs x10, x10, x25\n\t" + "adc x11, x11, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x11, x11, x10, #63\n\t" + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "extr x8, x8, x7, #63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x8\n\t" + "umulh x8, x25, x8\n\t" + "adds x4, x4, x26\n\t" + "mul x26, x25, x9\n\t" + "umulh x9, x25, x9\n\t" + "adcs x5, x5, x26\n\t" + "mul x26, x25, x10\n\t" + "umulh x10, x25, x10\n\t" + "adcs x6, x6, x26\n\t" + "mul x26, x25, x11\n\t" + "umulh x27, x25, x11\n\t" + "adcs x7, x7, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x7, #63\n\t" + "mul x27, x27, x25\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x7, asr 63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Store */ + "stp x4, x5, [x0]\n\t" + "stp x6, x7, [x0, #16]\n\t" + "ldr x0, [x29, #32]\n\t" + "ldr x1, [x29, #56]\n\t" + /* Square */ + "ldp x21, x22, [x1]\n\t" + "ldp x23, x24, [x1, #16]\n\t" + /* A[0] * A[1] */ + "mul x9, x21, x22\n\t" + "umulh x10, x21, x22\n\t" + /* A[0] * A[2] */ + "mul x25, x21, x23\n\t" + "umulh x11, x21, x23\n\t" + "adds x10, x10, x25\n\t" + "adc x11, x11, xzr\n\t" + /* A[0] * A[3] */ + "mul x25, x21, x24\n\t" + "umulh x16, x21, x24\n\t" + "adds x11, x11, x25\n\t" + "adc x16, x16, xzr\n\t" + /* A[1] * A[2] */ + "mul x25, x22, x23\n\t" + "umulh x26, x22, x23\n\t" + "adds x11, x11, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, xzr, xzr\n\t" + /* A[1] * A[3] */ + "mul x25, x22, x24\n\t" + "umulh x26, x22, x24\n\t" + "adds x16, x16, x25\n\t" + "adc x17, x17, x26\n\t" + /* A[2] * A[3] */ + "mul x25, x23, x24\n\t" + "umulh x19, x23, x24\n\t" + "adds x17, x17, x25\n\t" + "adc x19, x19, xzr\n\t" + /* Double */ + "adds x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adcs x11, x11, x11\n\t" + "adcs x16, x16, x16\n\t" + "adcs x17, x17, x17\n\t" + "adcs x19, x19, x19\n\t" + "adc x20, xzr, xzr\n\t" + /* A[0] * A[0] */ + "mul x8, x21, x21\n\t" + "umulh x27, x21, x21\n\t" + /* A[1] * A[1] */ + "mul x25, x22, x22\n\t" + "umulh x26, x22, x22\n\t" + "adds x9, x9, x27\n\t" + "adcs x10, x10, x25\n\t" + "adc x27, x26, xzr\n\t" + /* A[2] * A[2] */ + "mul x25, x23, x23\n\t" + "umulh x26, x23, x23\n\t" + "adds x11, x11, x27\n\t" + "adcs x16, x16, x25\n\t" + "adc x27, x26, xzr\n\t" + /* A[3] * A[3] */ + "mul x25, x24, x24\n\t" + "umulh x26, x24, x24\n\t" + "adds x17, x17, x27\n\t" + "adcs x19, x19, x25\n\t" + "adc x20, x20, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x20, x20, x19, #63\n\t" + "extr x19, x19, x17, #63\n\t" + "extr x17, x17, x16, #63\n\t" + "extr x16, x16, x11, #63\n\t" + "and x11, x11, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x16\n\t" + "umulh x16, x25, x16\n\t" + "adds x8, x8, x26\n\t" + "mul x26, x25, x17\n\t" + "umulh x17, x25, x17\n\t" + "adcs x9, x9, x26\n\t" + "mul x26, x25, x19\n\t" + "umulh x19, x25, x19\n\t" + "adcs x10, x10, x26\n\t" + "mul x26, x25, x20\n\t" + "umulh x27, x25, x20\n\t" + "adcs x11, x11, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x9, x9, x16\n\t" + "adcs x10, x10, x17\n\t" + "adcs x11, x11, x19\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x11, #63\n\t" + "mul x27, x27, x25\n\t" + "and x11, x11, #0x7fffffffffffffff\n\t" + "adds x8, x8, x27\n\t" + "adcs x9, x9, xzr\n\t" + "adcs x10, x10, xzr\n\t" + "adc x11, x11, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x11, asr 63\n\t" + "and x11, x11, #0x7fffffffffffffff\n\t" + "adds x8, x8, x27\n\t" + "adcs x9, x9, xzr\n\t" + "adcs x10, x10, xzr\n\t" + "adc x11, x11, xzr\n\t" + /* Store */ + "stp x8, x9, [x0]\n\t" + "stp x10, x11, [x0, #16]\n\t" + "ldr x0, [x29, #24]\n\t" + /* Add */ + "adds x12, x12, x21\n\t" + "adcs x13, x13, x22\n\t" + "adcs x14, x14, x23\n\t" + "adc x15, x15, x24\n\t" + "mov x25, #-19\n\t" + "asr x28, x15, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x12, x12, x25\n\t" + "sbcs x13, x13, x28\n\t" + "sbcs x14, x14, x28\n\t" + "sbc x15, x15, x26\n\t" + "ldr x0, [x29, #40]\n\t" + /* Square */ + /* A[0] * A[1] */ + "mul x17, x12, x13\n\t" + "umulh x19, x12, x13\n\t" + /* A[0] * A[2] */ + "mul x25, x12, x14\n\t" + "umulh x20, x12, x14\n\t" + "adds x19, x19, x25\n\t" + "adc x20, x20, xzr\n\t" + /* A[0] * A[3] */ + "mul x25, x12, x15\n\t" + "umulh x21, x12, x15\n\t" + "adds x20, x20, x25\n\t" + "adc x21, x21, xzr\n\t" + /* A[1] * A[2] */ + "mul x25, x13, x14\n\t" + "umulh x26, x13, x14\n\t" + "adds x20, x20, x25\n\t" + "adcs x21, x21, x26\n\t" + "adc x22, xzr, xzr\n\t" + /* A[1] * A[3] */ + "mul x25, x13, x15\n\t" + "umulh x26, x13, x15\n\t" + "adds x21, x21, x25\n\t" + "adc x22, x22, x26\n\t" + /* A[2] * A[3] */ + "mul x25, x14, x15\n\t" + "umulh x23, x14, x15\n\t" + "adds x22, x22, x25\n\t" + "adc x23, x23, xzr\n\t" + /* Double */ + "adds x17, x17, x17\n\t" + "adcs x19, x19, x19\n\t" + "adcs x20, x20, x20\n\t" + "adcs x21, x21, x21\n\t" + "adcs x22, x22, x22\n\t" + "adcs x23, x23, x23\n\t" + "adc x24, xzr, xzr\n\t" + /* A[0] * A[0] */ + "mul x16, x12, x12\n\t" + "umulh x27, x12, x12\n\t" + /* A[1] * A[1] */ + "mul x25, x13, x13\n\t" + "umulh x26, x13, x13\n\t" + "adds x17, x17, x27\n\t" + "adcs x19, x19, x25\n\t" + "adc x27, x26, xzr\n\t" + /* A[2] * A[2] */ + "mul x25, x14, x14\n\t" + "umulh x26, x14, x14\n\t" + "adds x20, x20, x27\n\t" + "adcs x21, x21, x25\n\t" + "adc x27, x26, xzr\n\t" + /* A[3] * A[3] */ + "mul x25, x15, x15\n\t" + "umulh x26, x15, x15\n\t" + "adds x22, x22, x27\n\t" + "adcs x23, x23, x25\n\t" + "adc x24, x24, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x24, x24, x23, #63\n\t" + "extr x23, x23, x22, #63\n\t" + "extr x22, x22, x21, #63\n\t" + "extr x21, x21, x20, #63\n\t" + "and x20, x20, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x21\n\t" + "umulh x21, x25, x21\n\t" + "adds x16, x16, x26\n\t" + "mul x26, x25, x22\n\t" + "umulh x22, x25, x22\n\t" + "adcs x17, x17, x26\n\t" + "mul x26, x25, x23\n\t" + "umulh x23, x25, x23\n\t" + "adcs x19, x19, x26\n\t" + "mul x26, x25, x24\n\t" + "umulh x27, x25, x24\n\t" + "adcs x20, x20, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x17, x17, x21\n\t" + "adcs x19, x19, x22\n\t" + "adcs x20, x20, x23\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x20, #63\n\t" + "mul x27, x27, x25\n\t" + "and x20, x20, #0x7fffffffffffffff\n\t" + "adds x16, x16, x27\n\t" + "adcs x17, x17, xzr\n\t" + "adcs x19, x19, xzr\n\t" + "adc x20, x20, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x20, asr 63\n\t" + "and x20, x20, #0x7fffffffffffffff\n\t" + "adds x16, x16, x27\n\t" + "adcs x17, x17, xzr\n\t" + "adcs x19, x19, xzr\n\t" + "adc x20, x20, xzr\n\t" + /* Store */ + "stp x16, x17, [x0]\n\t" + "stp x19, x20, [x0, #16]\n\t" + "ldr x0, [x29, #24]\n\t" + "ldr x1, [x29, #32]\n\t" + /* Add */ + "adds x12, x8, x4\n\t" + "adcs x13, x9, x5\n\t" + "adcs x14, x10, x6\n\t" + "adc x15, x11, x7\n\t" + "mov x25, #-19\n\t" + "asr x28, x15, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x12, x12, x25\n\t" + "sbcs x13, x13, x28\n\t" + "sbcs x14, x14, x28\n\t" + "sbc x15, x15, x26\n\t" + /* Sub */ + "subs x21, x8, x4\n\t" + "sbcs x22, x9, x5\n\t" + "sbcs x23, x10, x6\n\t" + "sbcs x24, x11, x7\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x21, x21, x25\n\t" + "adcs x22, x22, x28\n\t" + "adcs x23, x23, x28\n\t" + "adc x24, x24, x26\n\t" + "stp x12, x13, [x0]\n\t" + "stp x14, x15, [x0, #16]\n\t" + "stp x21, x22, [x1]\n\t" + "stp x23, x24, [x1, #16]\n\t" + "ldr x0, [x29, #16]\n\t" + /* Sub */ + "subs x16, x16, x12\n\t" + "sbcs x17, x17, x13\n\t" + "sbcs x19, x19, x14\n\t" + "sbcs x20, x20, x15\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x16, x16, x25\n\t" + "adcs x17, x17, x28\n\t" + "adcs x19, x19, x28\n\t" + "adc x20, x20, x26\n\t" + "stp x16, x17, [x0]\n\t" + "stp x19, x20, [x0, #16]\n\t" + "ldr x0, [x29, #40]\n\t" + "ldr x1, [x29, #64]\n\t" + /* Square * 2 */ + "ldp x12, x13, [x1]\n\t" + "ldp x14, x15, [x1, #16]\n\t" + /* A[0] * A[1] */ + "mul x5, x12, x13\n\t" + "umulh x6, x12, x13\n\t" + /* A[0] * A[2] */ + "mul x25, x12, x14\n\t" + "umulh x7, x12, x14\n\t" + "adds x6, x6, x25\n\t" + "adc x7, x7, xzr\n\t" + /* A[0] * A[3] */ + "mul x25, x12, x15\n\t" + "umulh x8, x12, x15\n\t" + "adds x7, x7, x25\n\t" + "adc x8, x8, xzr\n\t" + /* A[1] * A[2] */ + "mul x25, x13, x14\n\t" + "umulh x26, x13, x14\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, xzr, xzr\n\t" + /* A[1] * A[3] */ + "mul x25, x13, x15\n\t" + "umulh x26, x13, x15\n\t" + "adds x8, x8, x25\n\t" + "adc x9, x9, x26\n\t" + /* A[2] * A[3] */ + "mul x25, x14, x15\n\t" + "umulh x10, x14, x15\n\t" + "adds x9, x9, x25\n\t" + "adc x10, x10, xzr\n\t" + /* Double */ + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adcs x7, x7, x7\n\t" + "adcs x8, x8, x8\n\t" + "adcs x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adc x11, xzr, xzr\n\t" + /* A[0] * A[0] */ + "mul x4, x12, x12\n\t" + "umulh x28, x12, x12\n\t" + /* A[1] * A[1] */ + "mul x25, x13, x13\n\t" + "umulh x26, x13, x13\n\t" + "adds x5, x5, x28\n\t" + "adcs x6, x6, x25\n\t" + "adc x28, x26, xzr\n\t" + /* A[2] * A[2] */ + "mul x25, x14, x14\n\t" + "umulh x26, x14, x14\n\t" + "adds x7, x7, x28\n\t" + "adcs x8, x8, x25\n\t" + "adc x28, x26, xzr\n\t" + /* A[3] * A[3] */ + "mul x25, x15, x15\n\t" + "umulh x26, x15, x15\n\t" + "adds x9, x9, x28\n\t" + "adcs x10, x10, x25\n\t" + "adc x11, x11, x26\n\t" + /* Double and Reduce */ + "mov x25, #0x169\n\t" + /* Move top half into t4-t7 and remove top bit from t3 */ + "lsr x28, x11, #61\n\t" + "extr x11, x11, x10, #62\n\t" + "extr x10, x10, x9, #62\n\t" + "extr x9, x9, x8, #62\n\t" + "extr x8, x8, x7, #62\n\t" + "extr x7, x7, x6, #63\n\t" + "extr x6, x6, x5, #63\n\t" + "extr x5, x5, x4, #63\n\t" + "lsl x4, x4, #1\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + /* Two left, only one right */ + "and x11, x11, #0x7fffffffffffffff\n\t" + /* Multiply top bits by 19*19 */ + "mul x28, x28, x25\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x8\n\t" + "umulh x8, x25, x8\n\t" + "adds x4, x4, x26\n\t" + "mul x26, x25, x9\n\t" + "umulh x9, x25, x9\n\t" + "adcs x5, x5, x26\n\t" + "mul x26, x25, x10\n\t" + "umulh x10, x25, x10\n\t" + "adcs x6, x6, x26\n\t" + "mul x26, x25, x11\n\t" + "umulh x27, x25, x11\n\t" + "adcs x7, x7, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x4, x4, x28\n\t" + "adcs x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x7, #63\n\t" + "mul x27, x27, x25\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x7, asr 63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Store */ + "ldr x0, [x29, #40]\n\t" + /* Sub */ + "subs x4, x4, x21\n\t" + "sbcs x5, x5, x22\n\t" + "sbcs x6, x6, x23\n\t" + "sbcs x7, x7, x24\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x4, x4, x25\n\t" + "adcs x5, x5, x28\n\t" + "adcs x6, x6, x28\n\t" + "adc x7, x7, x26\n\t" + "stp x4, x5, [x0]\n\t" + "stp x6, x7, [x0, #16]\n\t" + "ldp x29, x30, [sp], #0x50\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz) + : + : "memory", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); +} + +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) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-80]!\n\t" + "add x29, sp, #0\n\t" + "str %x[rx], [x29, #16]\n\t" + "str %x[ry], [x29, #24]\n\t" + "str %x[rz], [x29, #32]\n\t" + "str %x[rt], [x29, #40]\n\t" + "str %x[px], [x29, #48]\n\t" + "str %x[py], [x29, #56]\n\t" + "str %x[pz], [x29, #64]\n\t" + "str %x[pt], [x29, #72]\n\t" + "ldr x2, [x29, #56]\n\t" + "ldr x3, [x29, #48]\n\t" + /* Add */ + "ldp x12, x13, [x2]\n\t" + "ldp x14, x15, [x2, #16]\n\t" + "ldp x16, x17, [x3]\n\t" + "ldp x19, x20, [x3, #16]\n\t" + "adds x4, x12, x16\n\t" + "adcs x5, x13, x17\n\t" + "adcs x6, x14, x19\n\t" + "adc x7, x15, x20\n\t" + "mov x25, #-19\n\t" + "asr x28, x7, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x4, x4, x25\n\t" + "sbcs x5, x5, x28\n\t" + "sbcs x6, x6, x28\n\t" + "sbc x7, x7, x26\n\t" + /* Sub */ + "subs x8, x12, x16\n\t" + "sbcs x9, x13, x17\n\t" + "sbcs x10, x14, x19\n\t" + "sbcs x11, x15, x20\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x8, x8, x25\n\t" + "adcs x9, x9, x28\n\t" + "adcs x10, x10, x28\n\t" + "adc x11, x11, x26\n\t" + "ldr x0, [x29, #32]\n\t" + "ldr x2, [x29, #168]\n\t" + /* Multiply */ + "ldp x21, x22, [x2]\n\t" + "ldp x23, x24, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x12, x4, x21\n\t" + "umulh x13, x4, x21\n\t" + /* A[0] * B[1] */ + "mul x25, x4, x22\n\t" + "umulh x14, x4, x22\n\t" + "adds x13, x13, x25\n\t" + "adc x14, x14, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x5, x21\n\t" + "umulh x26, x5, x21\n\t" + "adds x13, x13, x25\n\t" + "adcs x14, x14, x26\n\t" + "adc x15, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x4, x23\n\t" + "umulh x26, x4, x23\n\t" + "adds x14, x14, x25\n\t" + "adc x15, x15, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x5, x22\n\t" + "umulh x26, x5, x22\n\t" + "adds x14, x14, x25\n\t" + "adcs x15, x15, x26\n\t" + "adc x16, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x6, x21\n\t" + "umulh x26, x6, x21\n\t" + "adds x14, x14, x25\n\t" + "adcs x15, x15, x26\n\t" + "adc x16, x16, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x4, x24\n\t" + "umulh x26, x4, x24\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x5, x23\n\t" + "umulh x26, x5, x23\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x6, x22\n\t" + "umulh x26, x6, x22\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x7, x21\n\t" + "umulh x26, x7, x21\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x5, x24\n\t" + "umulh x26, x5, x24\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x6, x23\n\t" + "umulh x26, x6, x23\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x7, x22\n\t" + "umulh x26, x7, x22\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x6, x24\n\t" + "umulh x26, x6, x24\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x7, x23\n\t" + "umulh x26, x7, x23\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, x20, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x7, x24\n\t" + "umulh x26, x7, x24\n\t" + "adds x19, x19, x25\n\t" + "adc x20, x20, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x20, x20, x19, #63\n\t" + "extr x19, x19, x17, #63\n\t" + "extr x17, x17, x16, #63\n\t" + "extr x16, x16, x15, #63\n\t" + "and x15, x15, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x16\n\t" + "umulh x16, x25, x16\n\t" + "adds x12, x12, x26\n\t" + "mul x26, x25, x17\n\t" + "umulh x17, x25, x17\n\t" + "adcs x13, x13, x26\n\t" + "mul x26, x25, x19\n\t" + "umulh x19, x25, x19\n\t" + "adcs x14, x14, x26\n\t" + "mul x26, x25, x20\n\t" + "umulh x27, x25, x20\n\t" + "adcs x15, x15, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x13, x13, x16\n\t" + "adcs x14, x14, x17\n\t" + "adcs x15, x15, x19\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x15, #63\n\t" + "mul x27, x27, x25\n\t" + "and x15, x15, #0x7fffffffffffffff\n\t" + "adds x12, x12, x27\n\t" + "adcs x13, x13, xzr\n\t" + "adcs x14, x14, xzr\n\t" + "adc x15, x15, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x15, asr 63\n\t" + "and x15, x15, #0x7fffffffffffffff\n\t" + "adds x12, x12, x27\n\t" + "adcs x13, x13, xzr\n\t" + "adcs x14, x14, xzr\n\t" + "adc x15, x15, xzr\n\t" + /* Store */ + "ldr x0, [x29, #24]\n\t" + "ldr x1, [x29, #176]\n\t" + /* Multiply */ + "ldp x21, x22, [x1]\n\t" + "ldp x23, x24, [x1, #16]\n\t" + /* A[0] * B[0] */ + "mul x4, x8, x21\n\t" + "umulh x5, x8, x21\n\t" + /* A[0] * B[1] */ + "mul x25, x8, x22\n\t" + "umulh x6, x8, x22\n\t" + "adds x5, x5, x25\n\t" + "adc x6, x6, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x9, x21\n\t" + "umulh x26, x9, x21\n\t" + "adds x5, x5, x25\n\t" + "adcs x6, x6, x26\n\t" + "adc x7, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x8, x23\n\t" + "umulh x26, x8, x23\n\t" + "adds x6, x6, x25\n\t" + "adc x7, x7, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x9, x22\n\t" + "umulh x26, x9, x22\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x16, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x10, x21\n\t" + "umulh x26, x10, x21\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x16, x16, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x8, x24\n\t" + "umulh x26, x8, x24\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x9, x23\n\t" + "umulh x26, x9, x23\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x10, x22\n\t" + "umulh x26, x10, x22\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x11, x21\n\t" + "umulh x26, x11, x21\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x9, x24\n\t" + "umulh x26, x9, x24\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x10, x23\n\t" + "umulh x26, x10, x23\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x11, x22\n\t" + "umulh x26, x11, x22\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x10, x24\n\t" + "umulh x26, x10, x24\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x11, x23\n\t" + "umulh x26, x11, x23\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, x20, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x11, x24\n\t" + "umulh x26, x11, x24\n\t" + "adds x19, x19, x25\n\t" + "adc x20, x20, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x20, x20, x19, #63\n\t" + "extr x19, x19, x17, #63\n\t" + "extr x17, x17, x16, #63\n\t" + "extr x16, x16, x7, #63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x16\n\t" + "umulh x16, x25, x16\n\t" + "adds x4, x4, x26\n\t" + "mul x26, x25, x17\n\t" + "umulh x17, x25, x17\n\t" + "adcs x5, x5, x26\n\t" + "mul x26, x25, x19\n\t" + "umulh x19, x25, x19\n\t" + "adcs x6, x6, x26\n\t" + "mul x26, x25, x20\n\t" + "umulh x27, x25, x20\n\t" + "adcs x7, x7, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x5, x5, x16\n\t" + "adcs x6, x6, x17\n\t" + "adcs x7, x7, x19\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x7, #63\n\t" + "mul x27, x27, x25\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x7, asr 63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Store */ + "ldr x0, [x29, #24]\n\t" + "ldr x1, [x29, #16]\n\t" + /* Add */ + "adds x8, x12, x4\n\t" + "adcs x9, x13, x5\n\t" + "adcs x10, x14, x6\n\t" + "adc x11, x15, x7\n\t" + "mov x25, #-19\n\t" + "asr x28, x11, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x8, x8, x25\n\t" + "sbcs x9, x9, x28\n\t" + "sbcs x10, x10, x28\n\t" + "sbc x11, x11, x26\n\t" + /* Sub */ + "subs x16, x12, x4\n\t" + "sbcs x17, x13, x5\n\t" + "sbcs x19, x14, x6\n\t" + "sbcs x20, x15, x7\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x16, x16, x25\n\t" + "adcs x17, x17, x28\n\t" + "adcs x19, x19, x28\n\t" + "adc x20, x20, x26\n\t" + "stp x8, x9, [x0]\n\t" + "stp x10, x11, [x0, #16]\n\t" + "stp x16, x17, [x1]\n\t" + "stp x19, x20, [x1, #16]\n\t" + "ldr x0, [x29, #40]\n\t" + "ldr x1, [x29, #160]\n\t" + "ldr x3, [x29, #72]\n\t" + /* Multiply */ + "ldp x16, x17, [x1]\n\t" + "ldp x19, x20, [x1, #16]\n\t" + "ldp x21, x22, [x3]\n\t" + "ldp x23, x24, [x3, #16]\n\t" + /* A[0] * B[0] */ + "mul x4, x16, x21\n\t" + "umulh x5, x16, x21\n\t" + /* A[0] * B[1] */ + "mul x25, x16, x22\n\t" + "umulh x6, x16, x22\n\t" + "adds x5, x5, x25\n\t" + "adc x6, x6, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x17, x21\n\t" + "umulh x26, x17, x21\n\t" + "adds x5, x5, x25\n\t" + "adcs x6, x6, x26\n\t" + "adc x7, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x16, x23\n\t" + "umulh x26, x16, x23\n\t" + "adds x6, x6, x25\n\t" + "adc x7, x7, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x17, x22\n\t" + "umulh x26, x17, x22\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x8, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x19, x21\n\t" + "umulh x26, x19, x21\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x8, x8, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x16, x24\n\t" + "umulh x26, x16, x24\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x17, x23\n\t" + "umulh x26, x17, x23\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, x9, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x19, x22\n\t" + "umulh x26, x19, x22\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, x9, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x20, x21\n\t" + "umulh x26, x20, x21\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, x9, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x17, x24\n\t" + "umulh x26, x17, x24\n\t" + "adds x8, x8, x25\n\t" + "adcs x9, x9, x26\n\t" + "adc x10, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x19, x23\n\t" + "umulh x26, x19, x23\n\t" + "adds x8, x8, x25\n\t" + "adcs x9, x9, x26\n\t" + "adc x10, x10, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x20, x22\n\t" + "umulh x26, x20, x22\n\t" + "adds x8, x8, x25\n\t" + "adcs x9, x9, x26\n\t" + "adc x10, x10, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x19, x24\n\t" + "umulh x26, x19, x24\n\t" + "adds x9, x9, x25\n\t" + "adcs x10, x10, x26\n\t" + "adc x11, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x20, x23\n\t" + "umulh x26, x20, x23\n\t" + "adds x9, x9, x25\n\t" + "adcs x10, x10, x26\n\t" + "adc x11, x11, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x20, x24\n\t" + "umulh x26, x20, x24\n\t" + "adds x10, x10, x25\n\t" + "adc x11, x11, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x11, x11, x10, #63\n\t" + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "extr x8, x8, x7, #63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x8\n\t" + "umulh x8, x25, x8\n\t" + "adds x4, x4, x26\n\t" + "mul x26, x25, x9\n\t" + "umulh x9, x25, x9\n\t" + "adcs x5, x5, x26\n\t" + "mul x26, x25, x10\n\t" + "umulh x10, x25, x10\n\t" + "adcs x6, x6, x26\n\t" + "mul x26, x25, x11\n\t" + "umulh x27, x25, x11\n\t" + "adcs x7, x7, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x7, #63\n\t" + "mul x27, x27, x25\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x7, asr 63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Store */ + "ldr x0, [x29, #32]\n\t" + "ldr x1, [x29, #64]\n\t" + /* Double */ + "ldp x8, x9, [x1]\n\t" + "ldp x10, x11, [x1, #16]\n\t" + "adds x8, x8, x8\n\t" + "adcs x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adc x11, x11, x11\n\t" + "mov x25, #-19\n\t" + "asr x28, x11, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x8, x8, x25\n\t" + "sbcs x9, x9, x28\n\t" + "sbcs x10, x10, x28\n\t" + "sbc x11, x11, x26\n\t" + "ldr x1, [x29, #40]\n\t" + /* Add */ + "adds x12, x8, x4\n\t" + "adcs x13, x9, x5\n\t" + "adcs x14, x10, x6\n\t" + "adc x15, x11, x7\n\t" + "mov x25, #-19\n\t" + "asr x28, x15, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x12, x12, x25\n\t" + "sbcs x13, x13, x28\n\t" + "sbcs x14, x14, x28\n\t" + "sbc x15, x15, x26\n\t" + /* Sub */ + "subs x16, x8, x4\n\t" + "sbcs x17, x9, x5\n\t" + "sbcs x19, x10, x6\n\t" + "sbcs x20, x11, x7\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x16, x16, x25\n\t" + "adcs x17, x17, x28\n\t" + "adcs x19, x19, x28\n\t" + "adc x20, x20, x26\n\t" + "stp x12, x13, [x0]\n\t" + "stp x14, x15, [x0, #16]\n\t" + "stp x16, x17, [x1]\n\t" + "stp x19, x20, [x1, #16]\n\t" + "ldp x29, x30, [sp], #0x50\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + : + : "memory", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); + (void)qxy2d; + (void)qyplusx; + (void)qyminusx; +} + +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) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-80]!\n\t" + "add x29, sp, #0\n\t" + "str %x[rx], [x29, #16]\n\t" + "str %x[ry], [x29, #24]\n\t" + "str %x[rz], [x29, #32]\n\t" + "str %x[rt], [x29, #40]\n\t" + "str %x[px], [x29, #48]\n\t" + "str %x[py], [x29, #56]\n\t" + "str %x[pz], [x29, #64]\n\t" + "str %x[pt], [x29, #72]\n\t" + "ldr x2, [x29, #56]\n\t" + "ldr x3, [x29, #48]\n\t" + /* Add */ + "ldp x12, x13, [x2]\n\t" + "ldp x14, x15, [x2, #16]\n\t" + "ldp x16, x17, [x3]\n\t" + "ldp x19, x20, [x3, #16]\n\t" + "adds x4, x12, x16\n\t" + "adcs x5, x13, x17\n\t" + "adcs x6, x14, x19\n\t" + "adc x7, x15, x20\n\t" + "mov x25, #-19\n\t" + "asr x28, x7, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x4, x4, x25\n\t" + "sbcs x5, x5, x28\n\t" + "sbcs x6, x6, x28\n\t" + "sbc x7, x7, x26\n\t" + /* Sub */ + "subs x8, x12, x16\n\t" + "sbcs x9, x13, x17\n\t" + "sbcs x10, x14, x19\n\t" + "sbcs x11, x15, x20\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x8, x8, x25\n\t" + "adcs x9, x9, x28\n\t" + "adcs x10, x10, x28\n\t" + "adc x11, x11, x26\n\t" + "ldr x0, [x29, #32]\n\t" + "ldr x2, [x29, #176]\n\t" + /* Multiply */ + "ldp x21, x22, [x2]\n\t" + "ldp x23, x24, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x12, x4, x21\n\t" + "umulh x13, x4, x21\n\t" + /* A[0] * B[1] */ + "mul x25, x4, x22\n\t" + "umulh x14, x4, x22\n\t" + "adds x13, x13, x25\n\t" + "adc x14, x14, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x5, x21\n\t" + "umulh x26, x5, x21\n\t" + "adds x13, x13, x25\n\t" + "adcs x14, x14, x26\n\t" + "adc x15, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x4, x23\n\t" + "umulh x26, x4, x23\n\t" + "adds x14, x14, x25\n\t" + "adc x15, x15, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x5, x22\n\t" + "umulh x26, x5, x22\n\t" + "adds x14, x14, x25\n\t" + "adcs x15, x15, x26\n\t" + "adc x16, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x6, x21\n\t" + "umulh x26, x6, x21\n\t" + "adds x14, x14, x25\n\t" + "adcs x15, x15, x26\n\t" + "adc x16, x16, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x4, x24\n\t" + "umulh x26, x4, x24\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x5, x23\n\t" + "umulh x26, x5, x23\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x6, x22\n\t" + "umulh x26, x6, x22\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x7, x21\n\t" + "umulh x26, x7, x21\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x5, x24\n\t" + "umulh x26, x5, x24\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x6, x23\n\t" + "umulh x26, x6, x23\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x7, x22\n\t" + "umulh x26, x7, x22\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x6, x24\n\t" + "umulh x26, x6, x24\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x7, x23\n\t" + "umulh x26, x7, x23\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, x20, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x7, x24\n\t" + "umulh x26, x7, x24\n\t" + "adds x19, x19, x25\n\t" + "adc x20, x20, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x20, x20, x19, #63\n\t" + "extr x19, x19, x17, #63\n\t" + "extr x17, x17, x16, #63\n\t" + "extr x16, x16, x15, #63\n\t" + "and x15, x15, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x16\n\t" + "umulh x16, x25, x16\n\t" + "adds x12, x12, x26\n\t" + "mul x26, x25, x17\n\t" + "umulh x17, x25, x17\n\t" + "adcs x13, x13, x26\n\t" + "mul x26, x25, x19\n\t" + "umulh x19, x25, x19\n\t" + "adcs x14, x14, x26\n\t" + "mul x26, x25, x20\n\t" + "umulh x27, x25, x20\n\t" + "adcs x15, x15, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x13, x13, x16\n\t" + "adcs x14, x14, x17\n\t" + "adcs x15, x15, x19\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x15, #63\n\t" + "mul x27, x27, x25\n\t" + "and x15, x15, #0x7fffffffffffffff\n\t" + "adds x12, x12, x27\n\t" + "adcs x13, x13, xzr\n\t" + "adcs x14, x14, xzr\n\t" + "adc x15, x15, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x15, asr 63\n\t" + "and x15, x15, #0x7fffffffffffffff\n\t" + "adds x12, x12, x27\n\t" + "adcs x13, x13, xzr\n\t" + "adcs x14, x14, xzr\n\t" + "adc x15, x15, xzr\n\t" + /* Store */ + "ldr x0, [x29, #24]\n\t" + "ldr x1, [x29, #168]\n\t" + /* Multiply */ + "ldp x21, x22, [x1]\n\t" + "ldp x23, x24, [x1, #16]\n\t" + /* A[0] * B[0] */ + "mul x4, x8, x21\n\t" + "umulh x5, x8, x21\n\t" + /* A[0] * B[1] */ + "mul x25, x8, x22\n\t" + "umulh x6, x8, x22\n\t" + "adds x5, x5, x25\n\t" + "adc x6, x6, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x9, x21\n\t" + "umulh x26, x9, x21\n\t" + "adds x5, x5, x25\n\t" + "adcs x6, x6, x26\n\t" + "adc x7, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x8, x23\n\t" + "umulh x26, x8, x23\n\t" + "adds x6, x6, x25\n\t" + "adc x7, x7, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x9, x22\n\t" + "umulh x26, x9, x22\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x16, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x10, x21\n\t" + "umulh x26, x10, x21\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x16, x16, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x8, x24\n\t" + "umulh x26, x8, x24\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x9, x23\n\t" + "umulh x26, x9, x23\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x10, x22\n\t" + "umulh x26, x10, x22\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x11, x21\n\t" + "umulh x26, x11, x21\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x9, x24\n\t" + "umulh x26, x9, x24\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x10, x23\n\t" + "umulh x26, x10, x23\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x11, x22\n\t" + "umulh x26, x11, x22\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x10, x24\n\t" + "umulh x26, x10, x24\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x11, x23\n\t" + "umulh x26, x11, x23\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, x20, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x11, x24\n\t" + "umulh x26, x11, x24\n\t" + "adds x19, x19, x25\n\t" + "adc x20, x20, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x20, x20, x19, #63\n\t" + "extr x19, x19, x17, #63\n\t" + "extr x17, x17, x16, #63\n\t" + "extr x16, x16, x7, #63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x16\n\t" + "umulh x16, x25, x16\n\t" + "adds x4, x4, x26\n\t" + "mul x26, x25, x17\n\t" + "umulh x17, x25, x17\n\t" + "adcs x5, x5, x26\n\t" + "mul x26, x25, x19\n\t" + "umulh x19, x25, x19\n\t" + "adcs x6, x6, x26\n\t" + "mul x26, x25, x20\n\t" + "umulh x27, x25, x20\n\t" + "adcs x7, x7, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x5, x5, x16\n\t" + "adcs x6, x6, x17\n\t" + "adcs x7, x7, x19\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x7, #63\n\t" + "mul x27, x27, x25\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x7, asr 63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Store */ + "ldr x0, [x29, #24]\n\t" + "ldr x1, [x29, #16]\n\t" + /* Add */ + "adds x8, x12, x4\n\t" + "adcs x9, x13, x5\n\t" + "adcs x10, x14, x6\n\t" + "adc x11, x15, x7\n\t" + "mov x25, #-19\n\t" + "asr x28, x11, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x8, x8, x25\n\t" + "sbcs x9, x9, x28\n\t" + "sbcs x10, x10, x28\n\t" + "sbc x11, x11, x26\n\t" + /* Sub */ + "subs x16, x12, x4\n\t" + "sbcs x17, x13, x5\n\t" + "sbcs x19, x14, x6\n\t" + "sbcs x20, x15, x7\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x16, x16, x25\n\t" + "adcs x17, x17, x28\n\t" + "adcs x19, x19, x28\n\t" + "adc x20, x20, x26\n\t" + "stp x8, x9, [x0]\n\t" + "stp x10, x11, [x0, #16]\n\t" + "stp x16, x17, [x1]\n\t" + "stp x19, x20, [x1, #16]\n\t" + "ldr x0, [x29, #40]\n\t" + "ldr x1, [x29, #160]\n\t" + "ldr x3, [x29, #72]\n\t" + /* Multiply */ + "ldp x16, x17, [x1]\n\t" + "ldp x19, x20, [x1, #16]\n\t" + "ldp x21, x22, [x3]\n\t" + "ldp x23, x24, [x3, #16]\n\t" + /* A[0] * B[0] */ + "mul x4, x16, x21\n\t" + "umulh x5, x16, x21\n\t" + /* A[0] * B[1] */ + "mul x25, x16, x22\n\t" + "umulh x6, x16, x22\n\t" + "adds x5, x5, x25\n\t" + "adc x6, x6, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x17, x21\n\t" + "umulh x26, x17, x21\n\t" + "adds x5, x5, x25\n\t" + "adcs x6, x6, x26\n\t" + "adc x7, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x16, x23\n\t" + "umulh x26, x16, x23\n\t" + "adds x6, x6, x25\n\t" + "adc x7, x7, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x17, x22\n\t" + "umulh x26, x17, x22\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x8, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x19, x21\n\t" + "umulh x26, x19, x21\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x8, x8, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x16, x24\n\t" + "umulh x26, x16, x24\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x17, x23\n\t" + "umulh x26, x17, x23\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, x9, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x19, x22\n\t" + "umulh x26, x19, x22\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, x9, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x20, x21\n\t" + "umulh x26, x20, x21\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, x9, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x17, x24\n\t" + "umulh x26, x17, x24\n\t" + "adds x8, x8, x25\n\t" + "adcs x9, x9, x26\n\t" + "adc x10, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x19, x23\n\t" + "umulh x26, x19, x23\n\t" + "adds x8, x8, x25\n\t" + "adcs x9, x9, x26\n\t" + "adc x10, x10, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x20, x22\n\t" + "umulh x26, x20, x22\n\t" + "adds x8, x8, x25\n\t" + "adcs x9, x9, x26\n\t" + "adc x10, x10, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x19, x24\n\t" + "umulh x26, x19, x24\n\t" + "adds x9, x9, x25\n\t" + "adcs x10, x10, x26\n\t" + "adc x11, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x20, x23\n\t" + "umulh x26, x20, x23\n\t" + "adds x9, x9, x25\n\t" + "adcs x10, x10, x26\n\t" + "adc x11, x11, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x20, x24\n\t" + "umulh x26, x20, x24\n\t" + "adds x10, x10, x25\n\t" + "adc x11, x11, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x11, x11, x10, #63\n\t" + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "extr x8, x8, x7, #63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x8\n\t" + "umulh x8, x25, x8\n\t" + "adds x4, x4, x26\n\t" + "mul x26, x25, x9\n\t" + "umulh x9, x25, x9\n\t" + "adcs x5, x5, x26\n\t" + "mul x26, x25, x10\n\t" + "umulh x10, x25, x10\n\t" + "adcs x6, x6, x26\n\t" + "mul x26, x25, x11\n\t" + "umulh x27, x25, x11\n\t" + "adcs x7, x7, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x7, #63\n\t" + "mul x27, x27, x25\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x7, asr 63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Store */ + "ldr x0, [x29, #32]\n\t" + "ldr x1, [x29, #64]\n\t" + /* Double */ + "ldp x8, x9, [x1]\n\t" + "ldp x10, x11, [x1, #16]\n\t" + "adds x8, x8, x8\n\t" + "adcs x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adc x11, x11, x11\n\t" + "mov x25, #-19\n\t" + "asr x28, x11, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x8, x8, x25\n\t" + "sbcs x9, x9, x28\n\t" + "sbcs x10, x10, x28\n\t" + "sbc x11, x11, x26\n\t" + "ldr x1, [x29, #40]\n\t" + /* Add */ + "adds x12, x8, x4\n\t" + "adcs x13, x9, x5\n\t" + "adcs x14, x10, x6\n\t" + "adc x15, x11, x7\n\t" + "mov x25, #-19\n\t" + "asr x28, x15, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x12, x12, x25\n\t" + "sbcs x13, x13, x28\n\t" + "sbcs x14, x14, x28\n\t" + "sbc x15, x15, x26\n\t" + /* Sub */ + "subs x16, x8, x4\n\t" + "sbcs x17, x9, x5\n\t" + "sbcs x19, x10, x6\n\t" + "sbcs x20, x11, x7\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x16, x16, x25\n\t" + "adcs x17, x17, x28\n\t" + "adcs x19, x19, x28\n\t" + "adc x20, x20, x26\n\t" + "stp x12, x13, [x1]\n\t" + "stp x14, x15, [x1, #16]\n\t" + "stp x16, x17, [x0]\n\t" + "stp x19, x20, [x0, #16]\n\t" + "ldp x29, x30, [sp], #0x50\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + : + : "memory", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); + (void)qxy2d; + (void)qyplusx; + (void)qyminusx; +} + +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) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-80]!\n\t" + "add x29, sp, #0\n\t" + "str %x[rx], [x29, #16]\n\t" + "str %x[ry], [x29, #24]\n\t" + "str %x[rz], [x29, #32]\n\t" + "str %x[rt], [x29, #40]\n\t" + "str %x[px], [x29, #48]\n\t" + "str %x[py], [x29, #56]\n\t" + "str %x[pz], [x29, #64]\n\t" + "str %x[pt], [x29, #72]\n\t" + "ldr x2, [x29, #56]\n\t" + "ldr x3, [x29, #48]\n\t" + /* Add */ + "ldp x12, x13, [x2]\n\t" + "ldp x14, x15, [x2, #16]\n\t" + "ldp x16, x17, [x3]\n\t" + "ldp x19, x20, [x3, #16]\n\t" + "adds x4, x12, x16\n\t" + "adcs x5, x13, x17\n\t" + "adcs x6, x14, x19\n\t" + "adc x7, x15, x20\n\t" + "mov x25, #-19\n\t" + "asr x28, x7, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x4, x4, x25\n\t" + "sbcs x5, x5, x28\n\t" + "sbcs x6, x6, x28\n\t" + "sbc x7, x7, x26\n\t" + /* Sub */ + "subs x8, x12, x16\n\t" + "sbcs x9, x13, x17\n\t" + "sbcs x10, x14, x19\n\t" + "sbcs x11, x15, x20\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x8, x8, x25\n\t" + "adcs x9, x9, x28\n\t" + "adcs x10, x10, x28\n\t" + "adc x11, x11, x26\n\t" + "ldr x0, [x29, #32]\n\t" + "ldr x2, [x29, #176]\n\t" + /* Multiply */ + "ldp x21, x22, [x2]\n\t" + "ldp x23, x24, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x12, x4, x21\n\t" + "umulh x13, x4, x21\n\t" + /* A[0] * B[1] */ + "mul x25, x4, x22\n\t" + "umulh x14, x4, x22\n\t" + "adds x13, x13, x25\n\t" + "adc x14, x14, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x5, x21\n\t" + "umulh x26, x5, x21\n\t" + "adds x13, x13, x25\n\t" + "adcs x14, x14, x26\n\t" + "adc x15, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x4, x23\n\t" + "umulh x26, x4, x23\n\t" + "adds x14, x14, x25\n\t" + "adc x15, x15, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x5, x22\n\t" + "umulh x26, x5, x22\n\t" + "adds x14, x14, x25\n\t" + "adcs x15, x15, x26\n\t" + "adc x16, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x6, x21\n\t" + "umulh x26, x6, x21\n\t" + "adds x14, x14, x25\n\t" + "adcs x15, x15, x26\n\t" + "adc x16, x16, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x4, x24\n\t" + "umulh x26, x4, x24\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x5, x23\n\t" + "umulh x26, x5, x23\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x6, x22\n\t" + "umulh x26, x6, x22\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x7, x21\n\t" + "umulh x26, x7, x21\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x5, x24\n\t" + "umulh x26, x5, x24\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x6, x23\n\t" + "umulh x26, x6, x23\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x7, x22\n\t" + "umulh x26, x7, x22\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x6, x24\n\t" + "umulh x26, x6, x24\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x7, x23\n\t" + "umulh x26, x7, x23\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, x20, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x7, x24\n\t" + "umulh x26, x7, x24\n\t" + "adds x19, x19, x25\n\t" + "adc x20, x20, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x20, x20, x19, #63\n\t" + "extr x19, x19, x17, #63\n\t" + "extr x17, x17, x16, #63\n\t" + "extr x16, x16, x15, #63\n\t" + "and x15, x15, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x16\n\t" + "umulh x16, x25, x16\n\t" + "adds x12, x12, x26\n\t" + "mul x26, x25, x17\n\t" + "umulh x17, x25, x17\n\t" + "adcs x13, x13, x26\n\t" + "mul x26, x25, x19\n\t" + "umulh x19, x25, x19\n\t" + "adcs x14, x14, x26\n\t" + "mul x26, x25, x20\n\t" + "umulh x27, x25, x20\n\t" + "adcs x15, x15, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x13, x13, x16\n\t" + "adcs x14, x14, x17\n\t" + "adcs x15, x15, x19\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x15, #63\n\t" + "mul x27, x27, x25\n\t" + "and x15, x15, #0x7fffffffffffffff\n\t" + "adds x12, x12, x27\n\t" + "adcs x13, x13, xzr\n\t" + "adcs x14, x14, xzr\n\t" + "adc x15, x15, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x15, asr 63\n\t" + "and x15, x15, #0x7fffffffffffffff\n\t" + "adds x12, x12, x27\n\t" + "adcs x13, x13, xzr\n\t" + "adcs x14, x14, xzr\n\t" + "adc x15, x15, xzr\n\t" + /* Store */ + "ldr x0, [x29, #24]\n\t" + "ldr x1, [x29, #184]\n\t" + /* Multiply */ + "ldp x21, x22, [x1]\n\t" + "ldp x23, x24, [x1, #16]\n\t" + /* A[0] * B[0] */ + "mul x4, x8, x21\n\t" + "umulh x5, x8, x21\n\t" + /* A[0] * B[1] */ + "mul x25, x8, x22\n\t" + "umulh x6, x8, x22\n\t" + "adds x5, x5, x25\n\t" + "adc x6, x6, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x9, x21\n\t" + "umulh x26, x9, x21\n\t" + "adds x5, x5, x25\n\t" + "adcs x6, x6, x26\n\t" + "adc x7, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x8, x23\n\t" + "umulh x26, x8, x23\n\t" + "adds x6, x6, x25\n\t" + "adc x7, x7, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x9, x22\n\t" + "umulh x26, x9, x22\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x16, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x10, x21\n\t" + "umulh x26, x10, x21\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x16, x16, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x8, x24\n\t" + "umulh x26, x8, x24\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x9, x23\n\t" + "umulh x26, x9, x23\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x10, x22\n\t" + "umulh x26, x10, x22\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x11, x21\n\t" + "umulh x26, x11, x21\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x9, x24\n\t" + "umulh x26, x9, x24\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x10, x23\n\t" + "umulh x26, x10, x23\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x11, x22\n\t" + "umulh x26, x11, x22\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x10, x24\n\t" + "umulh x26, x10, x24\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x11, x23\n\t" + "umulh x26, x11, x23\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, x20, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x11, x24\n\t" + "umulh x26, x11, x24\n\t" + "adds x19, x19, x25\n\t" + "adc x20, x20, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x20, x20, x19, #63\n\t" + "extr x19, x19, x17, #63\n\t" + "extr x17, x17, x16, #63\n\t" + "extr x16, x16, x7, #63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x16\n\t" + "umulh x16, x25, x16\n\t" + "adds x4, x4, x26\n\t" + "mul x26, x25, x17\n\t" + "umulh x17, x25, x17\n\t" + "adcs x5, x5, x26\n\t" + "mul x26, x25, x19\n\t" + "umulh x19, x25, x19\n\t" + "adcs x6, x6, x26\n\t" + "mul x26, x25, x20\n\t" + "umulh x27, x25, x20\n\t" + "adcs x7, x7, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x5, x5, x16\n\t" + "adcs x6, x6, x17\n\t" + "adcs x7, x7, x19\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x7, #63\n\t" + "mul x27, x27, x25\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x7, asr 63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Store */ + "ldr x0, [x29, #24]\n\t" + "ldr x1, [x29, #16]\n\t" + /* Add */ + "adds x8, x12, x4\n\t" + "adcs x9, x13, x5\n\t" + "adcs x10, x14, x6\n\t" + "adc x11, x15, x7\n\t" + "mov x25, #-19\n\t" + "asr x28, x11, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x8, x8, x25\n\t" + "sbcs x9, x9, x28\n\t" + "sbcs x10, x10, x28\n\t" + "sbc x11, x11, x26\n\t" + /* Sub */ + "subs x16, x12, x4\n\t" + "sbcs x17, x13, x5\n\t" + "sbcs x19, x14, x6\n\t" + "sbcs x20, x15, x7\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x16, x16, x25\n\t" + "adcs x17, x17, x28\n\t" + "adcs x19, x19, x28\n\t" + "adc x20, x20, x26\n\t" + "stp x8, x9, [x0]\n\t" + "stp x10, x11, [x0, #16]\n\t" + "stp x16, x17, [x1]\n\t" + "stp x19, x20, [x1, #16]\n\t" + "ldr x0, [x29, #48]\n\t" + "ldr x1, [x29, #64]\n\t" + "ldr x2, [x29, #160]\n\t" + /* Multiply */ + "ldp x12, x13, [x1]\n\t" + "ldp x14, x15, [x1, #16]\n\t" + "ldp x16, x17, [x2]\n\t" + "ldp x19, x20, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x4, x12, x16\n\t" + "umulh x5, x12, x16\n\t" + /* A[0] * B[1] */ + "mul x25, x12, x17\n\t" + "umulh x6, x12, x17\n\t" + "adds x5, x5, x25\n\t" + "adc x6, x6, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x13, x16\n\t" + "umulh x26, x13, x16\n\t" + "adds x5, x5, x25\n\t" + "adcs x6, x6, x26\n\t" + "adc x7, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x12, x19\n\t" + "umulh x26, x12, x19\n\t" + "adds x6, x6, x25\n\t" + "adc x7, x7, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x13, x17\n\t" + "umulh x26, x13, x17\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x8, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x14, x16\n\t" + "umulh x26, x14, x16\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x8, x8, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x12, x20\n\t" + "umulh x26, x12, x20\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x13, x19\n\t" + "umulh x26, x13, x19\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, x9, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x14, x17\n\t" + "umulh x26, x14, x17\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, x9, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x15, x16\n\t" + "umulh x26, x15, x16\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, x9, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x13, x20\n\t" + "umulh x26, x13, x20\n\t" + "adds x8, x8, x25\n\t" + "adcs x9, x9, x26\n\t" + "adc x10, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x14, x19\n\t" + "umulh x26, x14, x19\n\t" + "adds x8, x8, x25\n\t" + "adcs x9, x9, x26\n\t" + "adc x10, x10, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x15, x17\n\t" + "umulh x26, x15, x17\n\t" + "adds x8, x8, x25\n\t" + "adcs x9, x9, x26\n\t" + "adc x10, x10, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x14, x20\n\t" + "umulh x26, x14, x20\n\t" + "adds x9, x9, x25\n\t" + "adcs x10, x10, x26\n\t" + "adc x11, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x15, x19\n\t" + "umulh x26, x15, x19\n\t" + "adds x9, x9, x25\n\t" + "adcs x10, x10, x26\n\t" + "adc x11, x11, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x15, x20\n\t" + "umulh x26, x15, x20\n\t" + "adds x10, x10, x25\n\t" + "adc x11, x11, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x11, x11, x10, #63\n\t" + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "extr x8, x8, x7, #63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x8\n\t" + "umulh x8, x25, x8\n\t" + "adds x4, x4, x26\n\t" + "mul x26, x25, x9\n\t" + "umulh x9, x25, x9\n\t" + "adcs x5, x5, x26\n\t" + "mul x26, x25, x10\n\t" + "umulh x10, x25, x10\n\t" + "adcs x6, x6, x26\n\t" + "mul x26, x25, x11\n\t" + "umulh x27, x25, x11\n\t" + "adcs x7, x7, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x7, #63\n\t" + "mul x27, x27, x25\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x7, asr 63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Store */ + "ldr x0, [x29, #48]\n\t" + /* Double */ + "adds x4, x4, x4\n\t" + "adcs x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "mov x25, #-19\n\t" + "asr x28, x7, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x4, x4, x25\n\t" + "sbcs x5, x5, x28\n\t" + "sbcs x6, x6, x28\n\t" + "sbc x7, x7, x26\n\t" + "ldr x0, [x29, #40]\n\t" + "ldr x1, [x29, #168]\n\t" + "ldr x2, [x29, #72]\n\t" + /* Multiply */ + "ldp x16, x17, [x1]\n\t" + "ldp x19, x20, [x1, #16]\n\t" + "ldp x21, x22, [x2]\n\t" + "ldp x23, x24, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x8, x16, x21\n\t" + "umulh x9, x16, x21\n\t" + /* A[0] * B[1] */ + "mul x25, x16, x22\n\t" + "umulh x10, x16, x22\n\t" + "adds x9, x9, x25\n\t" + "adc x10, x10, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x17, x21\n\t" + "umulh x26, x17, x21\n\t" + "adds x9, x9, x25\n\t" + "adcs x10, x10, x26\n\t" + "adc x11, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x16, x23\n\t" + "umulh x26, x16, x23\n\t" + "adds x10, x10, x25\n\t" + "adc x11, x11, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x17, x22\n\t" + "umulh x26, x17, x22\n\t" + "adds x10, x10, x25\n\t" + "adcs x11, x11, x26\n\t" + "adc x12, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x19, x21\n\t" + "umulh x26, x19, x21\n\t" + "adds x10, x10, x25\n\t" + "adcs x11, x11, x26\n\t" + "adc x12, x12, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x16, x24\n\t" + "umulh x26, x16, x24\n\t" + "adds x11, x11, x25\n\t" + "adcs x12, x12, x26\n\t" + "adc x13, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x17, x23\n\t" + "umulh x26, x17, x23\n\t" + "adds x11, x11, x25\n\t" + "adcs x12, x12, x26\n\t" + "adc x13, x13, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x19, x22\n\t" + "umulh x26, x19, x22\n\t" + "adds x11, x11, x25\n\t" + "adcs x12, x12, x26\n\t" + "adc x13, x13, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x20, x21\n\t" + "umulh x26, x20, x21\n\t" + "adds x11, x11, x25\n\t" + "adcs x12, x12, x26\n\t" + "adc x13, x13, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x17, x24\n\t" + "umulh x26, x17, x24\n\t" + "adds x12, x12, x25\n\t" + "adcs x13, x13, x26\n\t" + "adc x14, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x19, x23\n\t" + "umulh x26, x19, x23\n\t" + "adds x12, x12, x25\n\t" + "adcs x13, x13, x26\n\t" + "adc x14, x14, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x20, x22\n\t" + "umulh x26, x20, x22\n\t" + "adds x12, x12, x25\n\t" + "adcs x13, x13, x26\n\t" + "adc x14, x14, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x19, x24\n\t" + "umulh x26, x19, x24\n\t" + "adds x13, x13, x25\n\t" + "adcs x14, x14, x26\n\t" + "adc x15, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x20, x23\n\t" + "umulh x26, x20, x23\n\t" + "adds x13, x13, x25\n\t" + "adcs x14, x14, x26\n\t" + "adc x15, x15, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x20, x24\n\t" + "umulh x26, x20, x24\n\t" + "adds x14, x14, x25\n\t" + "adc x15, x15, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x15, x15, x14, #63\n\t" + "extr x14, x14, x13, #63\n\t" + "extr x13, x13, x12, #63\n\t" + "extr x12, x12, x11, #63\n\t" + "and x11, x11, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x12\n\t" + "umulh x12, x25, x12\n\t" + "adds x8, x8, x26\n\t" + "mul x26, x25, x13\n\t" + "umulh x13, x25, x13\n\t" + "adcs x9, x9, x26\n\t" + "mul x26, x25, x14\n\t" + "umulh x14, x25, x14\n\t" + "adcs x10, x10, x26\n\t" + "mul x26, x25, x15\n\t" + "umulh x27, x25, x15\n\t" + "adcs x11, x11, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x9, x9, x12\n\t" + "adcs x10, x10, x13\n\t" + "adcs x11, x11, x14\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x11, #63\n\t" + "mul x27, x27, x25\n\t" + "and x11, x11, #0x7fffffffffffffff\n\t" + "adds x8, x8, x27\n\t" + "adcs x9, x9, xzr\n\t" + "adcs x10, x10, xzr\n\t" + "adc x11, x11, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x11, asr 63\n\t" + "and x11, x11, #0x7fffffffffffffff\n\t" + "adds x8, x8, x27\n\t" + "adcs x9, x9, xzr\n\t" + "adcs x10, x10, xzr\n\t" + "adc x11, x11, xzr\n\t" + /* Store */ + "ldr x0, [x29, #32]\n\t" + "ldr x1, [x29, #40]\n\t" + /* Add */ + "adds x12, x4, x8\n\t" + "adcs x13, x5, x9\n\t" + "adcs x14, x6, x10\n\t" + "adc x15, x7, x11\n\t" + "mov x25, #-19\n\t" + "asr x28, x15, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x12, x12, x25\n\t" + "sbcs x13, x13, x28\n\t" + "sbcs x14, x14, x28\n\t" + "sbc x15, x15, x26\n\t" + /* Sub */ + "subs x16, x4, x8\n\t" + "sbcs x17, x5, x9\n\t" + "sbcs x19, x6, x10\n\t" + "sbcs x20, x7, x11\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x16, x16, x25\n\t" + "adcs x17, x17, x28\n\t" + "adcs x19, x19, x28\n\t" + "adc x20, x20, x26\n\t" + "stp x12, x13, [x0]\n\t" + "stp x14, x15, [x0, #16]\n\t" + "stp x16, x17, [x1]\n\t" + "stp x19, x20, [x1, #16]\n\t" + "ldp x29, x30, [sp], #0x50\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + : + : "memory", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); + (void)qz; + (void)qt2d; + (void)qyplusx; + (void)qyminusx; +} + +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) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-80]!\n\t" + "add x29, sp, #0\n\t" + "str %x[rx], [x29, #16]\n\t" + "str %x[ry], [x29, #24]\n\t" + "str %x[rz], [x29, #32]\n\t" + "str %x[rt], [x29, #40]\n\t" + "str %x[px], [x29, #48]\n\t" + "str %x[py], [x29, #56]\n\t" + "str %x[pz], [x29, #64]\n\t" + "str %x[pt], [x29, #72]\n\t" + "ldr x2, [x29, #56]\n\t" + "ldr x3, [x29, #48]\n\t" + /* Add */ + "ldp x12, x13, [x2]\n\t" + "ldp x14, x15, [x2, #16]\n\t" + "ldp x16, x17, [x3]\n\t" + "ldp x19, x20, [x3, #16]\n\t" + "adds x4, x12, x16\n\t" + "adcs x5, x13, x17\n\t" + "adcs x6, x14, x19\n\t" + "adc x7, x15, x20\n\t" + "mov x25, #-19\n\t" + "asr x28, x7, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x4, x4, x25\n\t" + "sbcs x5, x5, x28\n\t" + "sbcs x6, x6, x28\n\t" + "sbc x7, x7, x26\n\t" + /* Sub */ + "subs x8, x12, x16\n\t" + "sbcs x9, x13, x17\n\t" + "sbcs x10, x14, x19\n\t" + "sbcs x11, x15, x20\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x8, x8, x25\n\t" + "adcs x9, x9, x28\n\t" + "adcs x10, x10, x28\n\t" + "adc x11, x11, x26\n\t" + "ldr x0, [x29, #32]\n\t" + "ldr x2, [x29, #184]\n\t" + /* Multiply */ + "ldp x21, x22, [x2]\n\t" + "ldp x23, x24, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x12, x4, x21\n\t" + "umulh x13, x4, x21\n\t" + /* A[0] * B[1] */ + "mul x25, x4, x22\n\t" + "umulh x14, x4, x22\n\t" + "adds x13, x13, x25\n\t" + "adc x14, x14, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x5, x21\n\t" + "umulh x26, x5, x21\n\t" + "adds x13, x13, x25\n\t" + "adcs x14, x14, x26\n\t" + "adc x15, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x4, x23\n\t" + "umulh x26, x4, x23\n\t" + "adds x14, x14, x25\n\t" + "adc x15, x15, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x5, x22\n\t" + "umulh x26, x5, x22\n\t" + "adds x14, x14, x25\n\t" + "adcs x15, x15, x26\n\t" + "adc x16, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x6, x21\n\t" + "umulh x26, x6, x21\n\t" + "adds x14, x14, x25\n\t" + "adcs x15, x15, x26\n\t" + "adc x16, x16, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x4, x24\n\t" + "umulh x26, x4, x24\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x5, x23\n\t" + "umulh x26, x5, x23\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x6, x22\n\t" + "umulh x26, x6, x22\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x7, x21\n\t" + "umulh x26, x7, x21\n\t" + "adds x15, x15, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x5, x24\n\t" + "umulh x26, x5, x24\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x6, x23\n\t" + "umulh x26, x6, x23\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x7, x22\n\t" + "umulh x26, x7, x22\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x6, x24\n\t" + "umulh x26, x6, x24\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x7, x23\n\t" + "umulh x26, x7, x23\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, x20, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x7, x24\n\t" + "umulh x26, x7, x24\n\t" + "adds x19, x19, x25\n\t" + "adc x20, x20, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x20, x20, x19, #63\n\t" + "extr x19, x19, x17, #63\n\t" + "extr x17, x17, x16, #63\n\t" + "extr x16, x16, x15, #63\n\t" + "and x15, x15, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x16\n\t" + "umulh x16, x25, x16\n\t" + "adds x12, x12, x26\n\t" + "mul x26, x25, x17\n\t" + "umulh x17, x25, x17\n\t" + "adcs x13, x13, x26\n\t" + "mul x26, x25, x19\n\t" + "umulh x19, x25, x19\n\t" + "adcs x14, x14, x26\n\t" + "mul x26, x25, x20\n\t" + "umulh x27, x25, x20\n\t" + "adcs x15, x15, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x13, x13, x16\n\t" + "adcs x14, x14, x17\n\t" + "adcs x15, x15, x19\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x15, #63\n\t" + "mul x27, x27, x25\n\t" + "and x15, x15, #0x7fffffffffffffff\n\t" + "adds x12, x12, x27\n\t" + "adcs x13, x13, xzr\n\t" + "adcs x14, x14, xzr\n\t" + "adc x15, x15, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x15, asr 63\n\t" + "and x15, x15, #0x7fffffffffffffff\n\t" + "adds x12, x12, x27\n\t" + "adcs x13, x13, xzr\n\t" + "adcs x14, x14, xzr\n\t" + "adc x15, x15, xzr\n\t" + /* Store */ + "ldr x0, [x29, #24]\n\t" + "ldr x1, [x29, #176]\n\t" + /* Multiply */ + "ldp x21, x22, [x1]\n\t" + "ldp x23, x24, [x1, #16]\n\t" + /* A[0] * B[0] */ + "mul x4, x8, x21\n\t" + "umulh x5, x8, x21\n\t" + /* A[0] * B[1] */ + "mul x25, x8, x22\n\t" + "umulh x6, x8, x22\n\t" + "adds x5, x5, x25\n\t" + "adc x6, x6, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x9, x21\n\t" + "umulh x26, x9, x21\n\t" + "adds x5, x5, x25\n\t" + "adcs x6, x6, x26\n\t" + "adc x7, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x8, x23\n\t" + "umulh x26, x8, x23\n\t" + "adds x6, x6, x25\n\t" + "adc x7, x7, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x9, x22\n\t" + "umulh x26, x9, x22\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x16, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x10, x21\n\t" + "umulh x26, x10, x21\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x16, x16, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x8, x24\n\t" + "umulh x26, x8, x24\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x9, x23\n\t" + "umulh x26, x9, x23\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x10, x22\n\t" + "umulh x26, x10, x22\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x11, x21\n\t" + "umulh x26, x11, x21\n\t" + "adds x7, x7, x25\n\t" + "adcs x16, x16, x26\n\t" + "adc x17, x17, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x9, x24\n\t" + "umulh x26, x9, x24\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x10, x23\n\t" + "umulh x26, x10, x23\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x11, x22\n\t" + "umulh x26, x11, x22\n\t" + "adds x16, x16, x25\n\t" + "adcs x17, x17, x26\n\t" + "adc x19, x19, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x10, x24\n\t" + "umulh x26, x10, x24\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x11, x23\n\t" + "umulh x26, x11, x23\n\t" + "adds x17, x17, x25\n\t" + "adcs x19, x19, x26\n\t" + "adc x20, x20, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x11, x24\n\t" + "umulh x26, x11, x24\n\t" + "adds x19, x19, x25\n\t" + "adc x20, x20, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x20, x20, x19, #63\n\t" + "extr x19, x19, x17, #63\n\t" + "extr x17, x17, x16, #63\n\t" + "extr x16, x16, x7, #63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x16\n\t" + "umulh x16, x25, x16\n\t" + "adds x4, x4, x26\n\t" + "mul x26, x25, x17\n\t" + "umulh x17, x25, x17\n\t" + "adcs x5, x5, x26\n\t" + "mul x26, x25, x19\n\t" + "umulh x19, x25, x19\n\t" + "adcs x6, x6, x26\n\t" + "mul x26, x25, x20\n\t" + "umulh x27, x25, x20\n\t" + "adcs x7, x7, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x5, x5, x16\n\t" + "adcs x6, x6, x17\n\t" + "adcs x7, x7, x19\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x7, #63\n\t" + "mul x27, x27, x25\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x7, asr 63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Store */ + "ldr x0, [x29, #24]\n\t" + "ldr x1, [x29, #16]\n\t" + /* Add */ + "adds x8, x12, x4\n\t" + "adcs x9, x13, x5\n\t" + "adcs x10, x14, x6\n\t" + "adc x11, x15, x7\n\t" + "mov x25, #-19\n\t" + "asr x28, x11, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x8, x8, x25\n\t" + "sbcs x9, x9, x28\n\t" + "sbcs x10, x10, x28\n\t" + "sbc x11, x11, x26\n\t" + /* Sub */ + "subs x16, x12, x4\n\t" + "sbcs x17, x13, x5\n\t" + "sbcs x19, x14, x6\n\t" + "sbcs x20, x15, x7\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x16, x16, x25\n\t" + "adcs x17, x17, x28\n\t" + "adcs x19, x19, x28\n\t" + "adc x20, x20, x26\n\t" + "stp x8, x9, [x0]\n\t" + "stp x10, x11, [x0, #16]\n\t" + "stp x16, x17, [x1]\n\t" + "stp x19, x20, [x1, #16]\n\t" + "ldr x0, [x29, #48]\n\t" + "ldr x1, [x29, #64]\n\t" + "ldr x2, [x29, #160]\n\t" + /* Multiply */ + "ldp x12, x13, [x1]\n\t" + "ldp x14, x15, [x1, #16]\n\t" + "ldp x16, x17, [x2]\n\t" + "ldp x19, x20, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x4, x12, x16\n\t" + "umulh x5, x12, x16\n\t" + /* A[0] * B[1] */ + "mul x25, x12, x17\n\t" + "umulh x6, x12, x17\n\t" + "adds x5, x5, x25\n\t" + "adc x6, x6, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x13, x16\n\t" + "umulh x26, x13, x16\n\t" + "adds x5, x5, x25\n\t" + "adcs x6, x6, x26\n\t" + "adc x7, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x12, x19\n\t" + "umulh x26, x12, x19\n\t" + "adds x6, x6, x25\n\t" + "adc x7, x7, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x13, x17\n\t" + "umulh x26, x13, x17\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x8, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x14, x16\n\t" + "umulh x26, x14, x16\n\t" + "adds x6, x6, x25\n\t" + "adcs x7, x7, x26\n\t" + "adc x8, x8, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x12, x20\n\t" + "umulh x26, x12, x20\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x13, x19\n\t" + "umulh x26, x13, x19\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, x9, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x14, x17\n\t" + "umulh x26, x14, x17\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, x9, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x15, x16\n\t" + "umulh x26, x15, x16\n\t" + "adds x7, x7, x25\n\t" + "adcs x8, x8, x26\n\t" + "adc x9, x9, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x13, x20\n\t" + "umulh x26, x13, x20\n\t" + "adds x8, x8, x25\n\t" + "adcs x9, x9, x26\n\t" + "adc x10, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x14, x19\n\t" + "umulh x26, x14, x19\n\t" + "adds x8, x8, x25\n\t" + "adcs x9, x9, x26\n\t" + "adc x10, x10, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x15, x17\n\t" + "umulh x26, x15, x17\n\t" + "adds x8, x8, x25\n\t" + "adcs x9, x9, x26\n\t" + "adc x10, x10, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x14, x20\n\t" + "umulh x26, x14, x20\n\t" + "adds x9, x9, x25\n\t" + "adcs x10, x10, x26\n\t" + "adc x11, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x15, x19\n\t" + "umulh x26, x15, x19\n\t" + "adds x9, x9, x25\n\t" + "adcs x10, x10, x26\n\t" + "adc x11, x11, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x15, x20\n\t" + "umulh x26, x15, x20\n\t" + "adds x10, x10, x25\n\t" + "adc x11, x11, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x11, x11, x10, #63\n\t" + "extr x10, x10, x9, #63\n\t" + "extr x9, x9, x8, #63\n\t" + "extr x8, x8, x7, #63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x8\n\t" + "umulh x8, x25, x8\n\t" + "adds x4, x4, x26\n\t" + "mul x26, x25, x9\n\t" + "umulh x9, x25, x9\n\t" + "adcs x5, x5, x26\n\t" + "mul x26, x25, x10\n\t" + "umulh x10, x25, x10\n\t" + "adcs x6, x6, x26\n\t" + "mul x26, x25, x11\n\t" + "umulh x27, x25, x11\n\t" + "adcs x7, x7, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x7, #63\n\t" + "mul x27, x27, x25\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x7, asr 63\n\t" + "and x7, x7, #0x7fffffffffffffff\n\t" + "adds x4, x4, x27\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, xzr\n\t" + "adc x7, x7, xzr\n\t" + /* Store */ + "ldr x0, [x29, #48]\n\t" + /* Double */ + "adds x4, x4, x4\n\t" + "adcs x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "mov x25, #-19\n\t" + "asr x28, x7, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x4, x4, x25\n\t" + "sbcs x5, x5, x28\n\t" + "sbcs x6, x6, x28\n\t" + "sbc x7, x7, x26\n\t" + "ldr x0, [x29, #40]\n\t" + "ldr x1, [x29, #168]\n\t" + "ldr x2, [x29, #72]\n\t" + /* Multiply */ + "ldp x16, x17, [x1]\n\t" + "ldp x19, x20, [x1, #16]\n\t" + "ldp x21, x22, [x2]\n\t" + "ldp x23, x24, [x2, #16]\n\t" + /* A[0] * B[0] */ + "mul x8, x16, x21\n\t" + "umulh x9, x16, x21\n\t" + /* A[0] * B[1] */ + "mul x25, x16, x22\n\t" + "umulh x10, x16, x22\n\t" + "adds x9, x9, x25\n\t" + "adc x10, x10, xzr\n\t" + /* A[1] * B[0] */ + "mul x25, x17, x21\n\t" + "umulh x26, x17, x21\n\t" + "adds x9, x9, x25\n\t" + "adcs x10, x10, x26\n\t" + "adc x11, xzr, xzr\n\t" + /* A[0] * B[2] */ + "mul x25, x16, x23\n\t" + "umulh x26, x16, x23\n\t" + "adds x10, x10, x25\n\t" + "adc x11, x11, x26\n\t" + /* A[1] * B[1] */ + "mul x25, x17, x22\n\t" + "umulh x26, x17, x22\n\t" + "adds x10, x10, x25\n\t" + "adcs x11, x11, x26\n\t" + "adc x12, xzr, xzr\n\t" + /* A[2] * B[0] */ + "mul x25, x19, x21\n\t" + "umulh x26, x19, x21\n\t" + "adds x10, x10, x25\n\t" + "adcs x11, x11, x26\n\t" + "adc x12, x12, xzr\n\t" + /* A[0] * B[3] */ + "mul x25, x16, x24\n\t" + "umulh x26, x16, x24\n\t" + "adds x11, x11, x25\n\t" + "adcs x12, x12, x26\n\t" + "adc x13, xzr, xzr\n\t" + /* A[1] * B[2] */ + "mul x25, x17, x23\n\t" + "umulh x26, x17, x23\n\t" + "adds x11, x11, x25\n\t" + "adcs x12, x12, x26\n\t" + "adc x13, x13, xzr\n\t" + /* A[2] * B[1] */ + "mul x25, x19, x22\n\t" + "umulh x26, x19, x22\n\t" + "adds x11, x11, x25\n\t" + "adcs x12, x12, x26\n\t" + "adc x13, x13, xzr\n\t" + /* A[3] * B[0] */ + "mul x25, x20, x21\n\t" + "umulh x26, x20, x21\n\t" + "adds x11, x11, x25\n\t" + "adcs x12, x12, x26\n\t" + "adc x13, x13, xzr\n\t" + /* A[1] * B[3] */ + "mul x25, x17, x24\n\t" + "umulh x26, x17, x24\n\t" + "adds x12, x12, x25\n\t" + "adcs x13, x13, x26\n\t" + "adc x14, xzr, xzr\n\t" + /* A[2] * B[2] */ + "mul x25, x19, x23\n\t" + "umulh x26, x19, x23\n\t" + "adds x12, x12, x25\n\t" + "adcs x13, x13, x26\n\t" + "adc x14, x14, xzr\n\t" + /* A[3] * B[1] */ + "mul x25, x20, x22\n\t" + "umulh x26, x20, x22\n\t" + "adds x12, x12, x25\n\t" + "adcs x13, x13, x26\n\t" + "adc x14, x14, xzr\n\t" + /* A[2] * B[3] */ + "mul x25, x19, x24\n\t" + "umulh x26, x19, x24\n\t" + "adds x13, x13, x25\n\t" + "adcs x14, x14, x26\n\t" + "adc x15, xzr, xzr\n\t" + /* A[3] * B[2] */ + "mul x25, x20, x23\n\t" + "umulh x26, x20, x23\n\t" + "adds x13, x13, x25\n\t" + "adcs x14, x14, x26\n\t" + "adc x15, x15, xzr\n\t" + /* A[3] * B[3] */ + "mul x25, x20, x24\n\t" + "umulh x26, x20, x24\n\t" + "adds x14, x14, x25\n\t" + "adc x15, x15, x26\n\t" + /* Reduce */ + /* Move top half into t4-t7 and remove top bit from t3 */ + "extr x15, x15, x14, #63\n\t" + "extr x14, x14, x13, #63\n\t" + "extr x13, x13, x12, #63\n\t" + "extr x12, x12, x11, #63\n\t" + "and x11, x11, #0x7fffffffffffffff\n\t" + /* Multiply top half by 19 */ + "mov x25, #19\n\t" + "mul x26, x25, x12\n\t" + "umulh x12, x25, x12\n\t" + "adds x8, x8, x26\n\t" + "mul x26, x25, x13\n\t" + "umulh x13, x25, x13\n\t" + "adcs x9, x9, x26\n\t" + "mul x26, x25, x14\n\t" + "umulh x14, x25, x14\n\t" + "adcs x10, x10, x26\n\t" + "mul x26, x25, x15\n\t" + "umulh x27, x25, x15\n\t" + "adcs x11, x11, x26\n\t" + "adc x27, x27, xzr\n\t" + /* Add remaining product results in */ + "adds x9, x9, x12\n\t" + "adcs x10, x10, x13\n\t" + "adcs x11, x11, x14\n\t" + "adc x27, x27, xzr\n\t" + /* Overflow */ + "extr x27, x27, x11, #63\n\t" + "mul x27, x27, x25\n\t" + "and x11, x11, #0x7fffffffffffffff\n\t" + "adds x8, x8, x27\n\t" + "adcs x9, x9, xzr\n\t" + "adcs x10, x10, xzr\n\t" + "adc x11, x11, xzr\n\t" + /* Reduce if top bit set */ + "and x27, x25, x11, asr 63\n\t" + "and x11, x11, #0x7fffffffffffffff\n\t" + "adds x8, x8, x27\n\t" + "adcs x9, x9, xzr\n\t" + "adcs x10, x10, xzr\n\t" + "adc x11, x11, xzr\n\t" + /* Store */ + "ldr x0, [x29, #40]\n\t" + "ldr x1, [x29, #32]\n\t" + /* Add */ + "adds x12, x4, x8\n\t" + "adcs x13, x5, x9\n\t" + "adcs x14, x6, x10\n\t" + "adc x15, x7, x11\n\t" + "mov x25, #-19\n\t" + "asr x28, x15, #63\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Sub modulus (if overflow) */ + "subs x12, x12, x25\n\t" + "sbcs x13, x13, x28\n\t" + "sbcs x14, x14, x28\n\t" + "sbc x15, x15, x26\n\t" + /* Sub */ + "subs x16, x4, x8\n\t" + "sbcs x17, x5, x9\n\t" + "sbcs x19, x6, x10\n\t" + "sbcs x20, x7, x11\n\t" + "mov x25, #-19\n\t" + "csetm x28, cc\n\t" + /* Mask the modulus */ + "and x25, x28, x25\n\t" + "and x26, x28, #0x7fffffffffffffff\n\t" + /* Add modulus (if underflow) */ + "adds x16, x16, x25\n\t" + "adcs x17, x17, x28\n\t" + "adcs x19, x19, x28\n\t" + "adc x20, x20, x26\n\t" + "stp x12, x13, [x0]\n\t" + "stp x14, x15, [x0, #16]\n\t" + "stp x16, x17, [x1]\n\t" + "stp x19, x20, [x1, #16]\n\t" + "ldp x29, x30, [sp], #0x50\n\t" + : [rx] "+r" (rx), [ry] "+r" (ry), [rz] "+r" (rz), [rt] "+r" (rt), [px] "+r" (px), [py] "+r" (py), [pz] "+r" (pz), [pt] "+r" (pt) + : + : "memory", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); + (void)qz; + (void)qt2d; + (void)qyplusx; + (void)qyminusx; +} + +#endif /* WOLFSSL_ARMASM */ +#endif /* __aarch64__ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-poly1305.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-poly1305.c new file mode 100644 index 000000000..3df07f701 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-poly1305.c @@ -0,0 +1,1166 @@ +/* armv8-poly1305.c + * + * Copyright (C) 2006-2020 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 + */ + +/* + * Based off the public domain implementations by Andrew Moon + * and Daniel J. Bernstein + */ + + +#ifdef __aarch64__ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_ARMASM +#ifdef HAVE_POLY1305 +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif +#ifdef CHACHA_AEAD_TEST + #include +#endif + +static WC_INLINE void poly1305_blocks_16(Poly1305* ctx, const unsigned char *m, + size_t bytes) +{ + __asm__ __volatile__ ( + "CMP %[bytes], %[POLY1305_BLOCK_SIZE] \n\t" + "BLO L_poly1305_16_64_done_%= \n\t" + /* Load r and h */ + "LDP x21, x23, %[ctx_r] \n\t" + "LDR w25, %[ctx_r_4] \n\t" + "LDP x2, x4, %[ctx_h] \n\t" + "LDR w6, %[ctx_h_4] \n\t" + "LSR x22, x21, #32 \n\t" + "LSR x24, x23, #32 \n\t" + "LSR x3, x2, #32 \n\t" + "LSR x5, x4, #32 \n\t" + "AND x21, x21, #0x3ffffff \n\t" + "AND x23, x23, #0x3ffffff \n\t" + "AND x2, x2, #0x3ffffff \n\t" + "AND x4, x4, #0x3ffffff \n\t" + /* s1 = r1 * 5; */ + /* s2 = r2 * 5; */ + /* s3 = r3 * 5; */ + /* s4 = r4 * 5; */ + "MOV x15, #5 \n\t" + "CMP %[finished], #0 \n\t" + "MUL w7, w22, w15 \n\t" + "CSET %[finished], EQ \n\t" + "MUL w8, w23, w15 \n\t" + "LSL %[finished], %[finished], #24 \n\t" + "MUL w9, w24, w15 \n\t" + "MOV x14, #0x3ffffff \n\t" + "MUL w10, w25, w15 \n\t" + "\n" + ".align 2 \n\t" + "L_poly1305_16_64_loop_%=: \n\t" + /* t0 = U8TO64(&m[0]); */ + /* t1 = U8TO64(&m[8]); */ + "LDP x16, x17, [%[m]], #16 \n\t" + /* h0 += (U8TO32(m + 0)) & 0x3ffffff; */ + "AND x26, x16, #0x3ffffff \n\t" + "ADD x2, x2, x26 \n\t" + /* h1 += (U8TO32(m + 3) >> 2) & 0x3ffffff; */ + "AND x26, x14, x16, LSR #26 \n\t" + "ADD x3, x3, x26 \n\t" + /* h2 += (U8TO32(m + 6) >> 4) & 0x3ffffff; */ + "EXTR x26, x17, x16, #52 \n\t" + "AND x26, x26, #0x3ffffff \n\t" + "ADD x4, x4, x26 \n\t" + /* h3 += (U8TO32(m + 9) >> 6) & 0x3ffffff; */ + "AND x26, x14, x17, LSR #14 \n\t" + "ADD x5, x5, x26 \n\t" + /* h4 += (U8TO32(m + 12) >> 8) | hibit; */ + "ORR x17, %[finished], x17, LSR #40 \n\t" + "ADD x6, x6, x17 \n\t" + /* d0 = h0 * r0 + h1 * s4 + h2 * s3 + h3 * s2 + h4 * s1 */ + /* d1 = h0 * r1 + h1 * r0 + h2 * s4 + h3 * s3 + h4 * s2 */ + /* d2 = h0 * r2 + h1 * r1 + h2 * r0 + h3 * s4 + h4 * s3 */ + /* d3 = h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * s4 */ + /* d4 = h0 * r4 + h1 * r3 + h2 * r2 + h3 * r1 + h4 * r0 */ + "MUL x16, x2, x21 \n\t" + "MUL x17, x2, x22 \n\t" + "MUL x26, x2, x23 \n\t" + "MUL x19, x2, x24 \n\t" + "MUL x20, x2, x25 \n\t" + "MADD x16, x3, x10, x16 \n\t" + "MADD x17, x3, x21, x17 \n\t" + "MADD x26, x3, x22, x26 \n\t" + "MADD x19, x3, x23, x19 \n\t" + "MADD x20, x3, x24, x20 \n\t" + "MADD x16, x4, x9, x16 \n\t" + "MADD x17, x4, x10, x17 \n\t" + "MADD x26, x4, x21, x26 \n\t" + "MADD x19, x4, x22, x19 \n\t" + "MADD x20, x4, x23, x20 \n\t" + "MADD x16, x5, x8, x16 \n\t" + "MADD x17, x5, x9, x17 \n\t" + "MADD x26, x5, x10, x26 \n\t" + "MADD x19, x5, x21, x19 \n\t" + "MADD x20, x5, x22, x20 \n\t" + "MADD x16, x6, x7, x16 \n\t" + "MADD x17, x6, x8, x17 \n\t" + "MADD x26, x6, x9, x26 \n\t" + "MADD x19, x6, x10, x19 \n\t" + "MADD x20, x6, x21, x20 \n\t" + /* d1 = d1 + d0 >> 26 */ + /* d2 = d2 + d1 >> 26 */ + /* d3 = d3 + d2 >> 26 */ + /* d4 = d4 + d3 >> 26 */ + /* h0 = d0 & 0x3ffffff */ + /* h1 = d1 & 0x3ffffff */ + /* h2 = d2 & 0x3ffffff */ + /* h0 = h0 + (d4 >> 26) * 5 */ + /* h1 = h1 + h0 >> 26 */ + /* h3 = d3 & 0x3ffffff */ + /* h4 = d4 & 0x3ffffff */ + /* h0 = h0 & 0x3ffffff */ + "ADD x17, x17, x16, LSR #26 \n\t" + "ADD x20, x20, x19, LSR #26 \n\t" + "AND x16, x16, #0x3ffffff \n\t" + "LSR x2, x20, #26 \n\t" + "AND x19, x19, #0x3ffffff \n\t" + "MADD x16, x2, x15, x16 \n\t" + "ADD x26, x26, x17, LSR #26 \n\t" + "AND x17, x17, #0x3ffffff \n\t" + "AND x20, x20, #0x3ffffff \n\t" + "ADD x19, x19, x26, LSR #26 \n\t" + "AND x4, x26, #0x3ffffff \n\t" + "ADD x3, x17, x16, LSR #26 \n\t" + "AND x2, x16, #0x3ffffff \n\t" + "ADD x6, x20, x19, LSR #26 \n\t" + "AND x5, x19, #0x3ffffff \n\t" + "SUB %[bytes], %[bytes], %[POLY1305_BLOCK_SIZE] \n\t" + "CMP %[bytes], %[POLY1305_BLOCK_SIZE] \n\t" + "BHS L_poly1305_16_64_loop_%= \n\t" + /* Store h */ + "ORR x2, x2, x3, LSL #32 \n\t" + "ORR x4, x4, x5, LSL #32 \n\t" + "STP x2, x4, %[ctx_h] \n\t" + "STR w6, %[ctx_h_4] \n\t" + "\n" + ".align 2 \n\t" + "L_poly1305_16_64_done_%=: \n\t" + : [ctx_h] "+m" (ctx->h[0]), + [ctx_h_4] "+m" (ctx->h[4]), + [bytes] "+r" (bytes), + [m] "+r" (m) + : [POLY1305_BLOCK_SIZE] "I" (POLY1305_BLOCK_SIZE), + [ctx_r] "m" (ctx->r[0]), + [ctx_r_4] "m" (ctx->r[4]), + [finished] "r" ((word64)ctx->finished) + : "memory", "cc", + "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w15", + "w21", "w22", "w23", "w24", "w25", "x2", "x3", "x4", "x5", "x6", + "x7", "x8", "x9", "x10", "x14", "x15", "x16", "x17", "x19", "x20", + "x21", "x22", "x23", "x24", "x25", "x26" + ); +} + +void poly1305_blocks(Poly1305* ctx, const unsigned char *m, + size_t bytes) +{ + __asm__ __volatile__ ( + /* If less than 4 blocks to process then use regular method */ + "CMP %[bytes], %[POLY1305_BLOCK_SIZE]*4 \n\t" + "BLO L_poly1305_64_done_%= \n\t" + "MOV x9, #0x3ffffff \n\t" + /* Load h */ + "LDP x20, x22, [%[h]] \n\t" + "MOV v27.D[0], x9 \n\t" + "LDR w24, [%[h], #16] \n\t" + "MOV v27.D[1], x9 \n\t" + "LSR x21, x20, #32 \n\t" + "DUP v29.4S, v27.S[0] \n\t" + "LSR x23, x22, #32 \n\t" + "MOV x9, #5 \n\t" + "AND x20, x20, #0x3ffffff \n\t" + "MOV v28.D[0], x9 \n\t" + "AND x22, x22, #0x3ffffff \n\t" + /* Zero accumulator registers */ + "MOVI v15.2D, #0x0 \n\t" + "MOVI v16.2D, #0x0 \n\t" + "MOVI v17.2D, #0x0 \n\t" + "MOVI v18.2D, #0x0 \n\t" + "MOVI v19.2D, #0x0 \n\t" + /* Set hibit */ + "CMP %[finished], #0 \n\t" + "CSET x9, EQ \n\t" + "LSL x9, x9, #24 \n\t" + "MOV v26.D[0], x9 \n\t" + "MOV v26.D[1], x9 \n\t" + "DUP v30.4S, v26.S[0] \n\t" + "CMP %[bytes], %[POLY1305_BLOCK_SIZE]*6 \n\t" + "BLO L_poly1305_64_start_block_size_64_%= \n\t" + /* Load r^2 to NEON v0, v1, v2, v3, v4 */ + "LD4 { v0.S-v3.S }[2], [%[r_2]], #16 \n\t" + "LD1 { v4.S }[2], [%[r_2]] \n\t" + "SUB %[r_2], %[r_2], #16 \n\t" + /* Load r^4 to NEON v0, v1, v2, v3, v4 */ + "LD4 { v0.S-v3.S }[0], [%[r_4]], #16 \n\t" + "LD1 { v4.S }[0], [%[r_4]] \n\t" + "SUB %[r_4], %[r_4], #16 \n\t" + "MOV v0.S[1], v0.S[0] \n\t" + "MOV v0.S[3], v0.S[2] \n\t" + "MOV v1.S[1], v1.S[0] \n\t" + "MOV v1.S[3], v1.S[2] \n\t" + "MOV v2.S[1], v2.S[0] \n\t" + "MOV v2.S[3], v2.S[2] \n\t" + "MOV v3.S[1], v3.S[0] \n\t" + "MOV v3.S[3], v3.S[2] \n\t" + "MOV v4.S[1], v4.S[0] \n\t" + "MOV v4.S[3], v4.S[2] \n\t" + /* Store [r^4, r^2] * 5 */ + "MUL v5.4S, v0.4S, v28.S[0] \n\t" + "MUL v6.4S, v1.4S, v28.S[0] \n\t" + "MUL v7.4S, v2.4S, v28.S[0] \n\t" + "MUL v8.4S, v3.4S, v28.S[0] \n\t" + "MUL v9.4S, v4.4S, v28.S[0] \n\t" + /* Copy r^4 to ARM */ + "MOV w25, v0.S[0] \n\t" + "MOV w26, v1.S[0] \n\t" + "MOV w27, v2.S[0] \n\t" + "MOV w28, v3.S[0] \n\t" + "MOV w30, v4.S[0] \n\t" + /* Copy 5*r^4 to ARM */ + "MOV w15, v5.S[0] \n\t" + "MOV w16, v6.S[0] \n\t" + "MOV w17, v7.S[0] \n\t" + "MOV w8, v8.S[0] \n\t" + "MOV w19, v9.S[0] \n\t" + /* Load m */ + /* Load four message blocks to NEON v10, v11, v12, v13, v14 */ + "LD4 { v10.4S-v13.4S }, [%[m]], #64 \n\t" + "SUB %[bytes], %[bytes], %[POLY1305_BLOCK_SIZE]*4 \n\t" + "USHR v14.4S, v13.4S, #8 \n\t" + "ORR v14.16B, v14.16B, v30.16B \n\t" + "SHL v13.4S, v13.4S, #18 \n\t" + "SRI v13.4S, v12.4S, #14 \n\t" + "SHL v12.4S, v12.4S, #12 \n\t" + "SRI v12.4S, v11.4S, #20 \n\t" + "SHL v11.4S, v11.4S, #6 \n\t" + "SRI v11.4S, v10.4S, #26 \n\t" + "AND v10.16B, v10.16B, v29.16B \n\t" + "AND v11.16B, v11.16B, v29.16B \n\t" + "AND v12.16B, v12.16B, v29.16B \n\t" + "AND v13.16B, v13.16B, v29.16B \n\t" + "AND v14.16B, v14.16B, v29.16B \n\t" + /* Four message blocks loaded */ + /* Add messages to accumulator */ + "ADD v15.2S, v15.2S, v10.2S \n\t" + "ADD v16.2S, v16.2S, v11.2S \n\t" + "ADD v17.2S, v17.2S, v12.2S \n\t" + "ADD v18.2S, v18.2S, v13.2S \n\t" + "ADD v19.2S, v19.2S, v14.2S \n\t" + "\n" + ".align 2 \n\t" + "L_poly1305_64_loop_128_%=: \n\t" + /* d0 = h0*r0 + h1*s4 + h2*s3 + h3*s2 + h4*s1 */ + /* d1 = h0*r1 + h1*r0 + h2*s4 + h3*s3 + h4*s2 */ + /* d2 = h0*r2 + h1*r1 + h2*r0 + h3*s4 + h4*s3 */ + /* d3 = h0*r3 + h1*r2 + h2*r1 + h3*r0 + h4*s4 */ + /* d4 = h0*r4 + h1*r3 + h2*r2 + h3*r1 + h4*r0 */ + "UMULL v21.2D, v15.2S, v0.2S \n\t" + /* Compute h*r^2 */ + /* d0 = h0 * r0 + h1 * s4 + h2 * s3 + h3 * s2 + h4 * s1 */ + /* d1 = h0 * r1 + h1 * r0 + h2 * s4 + h3 * s3 + h4 * s2 */ + /* d2 = h0 * r2 + h1 * r1 + h2 * r0 + h3 * s4 + h4 * s3 */ + /* d3 = h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * s4 */ + /* d4 = h0 * r4 + h1 * r3 + h2 * r2 + h3 * r1 + h4 * r0 */ + "MUL x9, x20, x25 \n\t" + "UMULL v22.2D, v15.2S, v1.2S \n\t" + "MUL x10, x20, x26 \n\t" + "UMULL v23.2D, v15.2S, v2.2S \n\t" + "MUL x11, x20, x27 \n\t" + "UMULL v24.2D, v15.2S, v3.2S \n\t" + "MUL x12, x20, x28 \n\t" + "UMULL v25.2D, v15.2S, v4.2S \n\t" + "MUL x13, x20, x30 \n\t" + "UMLAL v21.2D, v16.2S, v9.2S \n\t" + "MADD x9, x21, x19, x9 \n\t" + "UMLAL v22.2D, v16.2S, v0.2S \n\t" + "MADD x10, x21, x25, x10 \n\t" + "UMLAL v23.2D, v16.2S, v1.2S \n\t" + "MADD x11, x21, x26, x11 \n\t" + "UMLAL v24.2D, v16.2S, v2.2S \n\t" + "MADD x12, x21, x27, x12 \n\t" + "UMLAL v25.2D, v16.2S, v3.2S \n\t" + "MADD x13, x21, x28, x13 \n\t" + "UMLAL v21.2D, v17.2S, v8.2S \n\t" + "MADD x9, x22, x8, x9 \n\t" + "UMLAL v22.2D, v17.2S, v9.2S \n\t" + "MADD x10, x22, x19, x10 \n\t" + "UMLAL v23.2D, v17.2S, v0.2S \n\t" + "MADD x11, x22, x25, x11 \n\t" + "UMLAL v24.2D, v17.2S, v1.2S \n\t" + "MADD x12, x22, x26, x12 \n\t" + "UMLAL v25.2D, v17.2S, v2.2S \n\t" + "MADD x13, x22, x27, x13 \n\t" + "UMLAL v21.2D, v18.2S, v7.2S \n\t" + "MADD x9, x23, x17, x9 \n\t" + "UMLAL v22.2D, v18.2S, v8.2S \n\t" + "MADD x10, x23, x8, x10 \n\t" + "UMLAL v23.2D, v18.2S, v9.2S \n\t" + "MADD x11, x23, x19, x11 \n\t" + "UMLAL v24.2D, v18.2S, v0.2S \n\t" + "MADD x12, x23, x25, x12 \n\t" + "UMLAL v25.2D, v18.2S, v1.2S \n\t" + "MADD x13, x23, x26, x13 \n\t" + "UMLAL v21.2D, v19.2S, v6.2S \n\t" + "MADD x9, x24, x16, x9 \n\t" + "UMLAL v22.2D, v19.2S, v7.2S \n\t" + "MADD x10, x24, x17, x10 \n\t" + "UMLAL v23.2D, v19.2S, v8.2S \n\t" + "MADD x11, x24, x8, x11 \n\t" + "UMLAL v24.2D, v19.2S, v9.2S \n\t" + "MADD x12, x24, x19, x12 \n\t" + "UMLAL v25.2D, v19.2S, v0.2S \n\t" + "MADD x13, x24, x25, x13 \n\t" + /* d0 = h0*r0 + h1*s4 + h2*s3 + h3*s2 + h4*s1 */ + /* d1 = h0*r1 + h1*r0 + h2*s4 + h3*s3 + h4*s2 */ + /* d2 = h0*r2 + h1*r1 + h2*r0 + h3*s4 + h4*s3 */ + /* d3 = h0*r3 + h1*r2 + h2*r1 + h3*r0 + h4*s4 */ + /* d4 = h0*r4 + h1*r3 + h2*r2 + h3*r1 + h4*r0 */ + "UMLAL2 v21.2D, v10.4S, v0.4S \n\t" + /* Reduce h % P */ + "MOV x14, #5 \n\t" + "UMLAL2 v22.2D, v10.4S, v1.4S \n\t" + "ADD x10, x10, x9, LSR #26 \n\t" + "UMLAL2 v23.2D, v10.4S, v2.4S \n\t" + "ADD x13, x13, x12, LSR #26 \n\t" + "UMLAL2 v24.2D, v10.4S, v3.4S \n\t" + "AND x9, x9, #0x3ffffff \n\t" + "UMLAL2 v25.2D, v10.4S, v4.4S \n\t" + "LSR x20, x13, #26 \n\t" + "UMLAL2 v21.2D, v11.4S, v9.4S \n\t" + "AND x12, x12, #0x3ffffff \n\t" + "UMLAL2 v22.2D, v11.4S, v0.4S \n\t" + "MADD x9, x20, x14, x9 \n\t" + "UMLAL2 v23.2D, v11.4S, v1.4S \n\t" + "ADD x11, x11, x10, LSR #26 \n\t" + "UMLAL2 v24.2D, v11.4S, v2.4S \n\t" + "AND x10, x10, #0x3ffffff \n\t" + "UMLAL2 v25.2D, v11.4S, v3.4S \n\t" + "AND x13, x13, #0x3ffffff \n\t" + "UMLAL2 v21.2D, v12.4S, v8.4S \n\t" + "ADD x12, x12, x11, LSR #26 \n\t" + "UMLAL2 v22.2D, v12.4S, v9.4S \n\t" + "AND x22, x11, #0x3ffffff \n\t" + "UMLAL2 v23.2D, v12.4S, v0.4S \n\t" + "ADD x21, x10, x9, LSR #26 \n\t" + "UMLAL2 v24.2D, v12.4S, v1.4S \n\t" + "AND x20, x9, #0x3ffffff \n\t" + "UMLAL2 v25.2D, v12.4S, v2.4S \n\t" + "ADD x24, x13, x12, LSR #26 \n\t" + "UMLAL2 v21.2D, v13.4S, v7.4S \n\t" + "AND x23, x12, #0x3ffffff \n\t" + "UMLAL2 v22.2D, v13.4S, v8.4S \n\t" + "UMLAL2 v23.2D, v13.4S, v9.4S \n\t" + "UMLAL2 v24.2D, v13.4S, v0.4S \n\t" + "UMLAL2 v25.2D, v13.4S, v1.4S \n\t" + "UMLAL2 v21.2D, v14.4S, v6.4S \n\t" + "UMLAL2 v22.2D, v14.4S, v7.4S \n\t" + "UMLAL2 v23.2D, v14.4S, v8.4S \n\t" + "UMLAL2 v24.2D, v14.4S, v9.4S \n\t" + "UMLAL2 v25.2D, v14.4S, v0.4S \n\t" + /* If less than six message blocks left then leave loop */ + "CMP %[bytes], %[POLY1305_BLOCK_SIZE]*6 \n\t" + "BLS L_poly1305_64_loop_128_final_%= \n\t" + /* Load m */ + /* Load four message blocks to NEON v10, v11, v12, v13, v14 */ + "LD4 { v10.4S-v13.4S }, [%[m]], #64 \n\t" + "SUB %[bytes], %[bytes], %[POLY1305_BLOCK_SIZE]*4 \n\t" + "USHR v14.4S, v13.4S, #8 \n\t" + "ORR v14.16B, v14.16B, v30.16B \n\t" + "SHL v13.4S, v13.4S, #18 \n\t" + "SRI v13.4S, v12.4S, #14 \n\t" + "SHL v12.4S, v12.4S, #12 \n\t" + "SRI v12.4S, v11.4S, #20 \n\t" + "SHL v11.4S, v11.4S, #6 \n\t" + "SRI v11.4S, v10.4S, #26 \n\t" + "AND v10.16B, v10.16B, v29.16B \n\t" + "AND v11.16B, v11.16B, v29.16B \n\t" + "AND v12.16B, v12.16B, v29.16B \n\t" + "AND v13.16B, v13.16B, v29.16B \n\t" + "AND v14.16B, v14.16B, v29.16B \n\t" + /* Four message blocks loaded */ + /* Add new message block to accumulator */ + "UADDW v21.2D, v21.2D, v10.2S \n\t" + "UADDW v22.2D, v22.2D, v11.2S \n\t" + "UADDW v23.2D, v23.2D, v12.2S \n\t" + "UADDW v24.2D, v24.2D, v13.2S \n\t" + "UADDW v25.2D, v25.2D, v14.2S \n\t" + /* Reduce radix 26 NEON */ + /* Interleave h0 -> h1 -> h2 -> h3 -> h4 */ + /* with h3 -> h4 -> h0 -> h1 */ + "USRA v22.2D, v21.2D, #26 \n\t" + "AND v21.16B, v21.16B, v27.16B \n\t" + "USRA v25.2D, v24.2D, #26 \n\t" + "AND v24.16B, v24.16B, v27.16B \n\t" + "USHR v15.2D, v25.2D, #26 \n\t" + "USRA v23.2D, v22.2D, #26 \n\t" + /* Simulate multiplying by 5 using adding and shifting */ + "SHL v18.2D, v15.2D, #2 \n\t" + "AND v16.16B, v22.16B, v27.16B \n\t" + "ADD v18.2D, v18.2D, v15.2D \n\t" + "AND v19.16B, v25.16B, v27.16B \n\t" + "ADD v21.2D, v21.2D, v18.2D \n\t" + "USRA v24.2D, v23.2D, #26 \n\t" + "AND v17.16B, v23.16B, v27.16B \n\t" + "USRA v16.2D, v21.2D, #26 \n\t" + "AND v15.16B, v21.16B, v27.16B \n\t" + "USRA v19.2D, v24.2D, #26 \n\t" + "AND v18.16B, v24.16B, v27.16B \n\t" + /* Copy values to lower halves of result registers */ + "MOV v15.S[1], v15.S[2] \n\t" + "MOV v16.S[1], v16.S[2] \n\t" + "MOV v17.S[1], v17.S[2] \n\t" + "MOV v18.S[1], v18.S[2] \n\t" + "MOV v19.S[1], v19.S[2] \n\t" + "B L_poly1305_64_loop_128_%= \n\t" + "\n" + ".align 2 \n\t" + "L_poly1305_64_loop_128_final_%=: \n\t" + /* Load m */ + /* Load two message blocks to NEON v10, v11, v12, v13, v14 */ + "LD2 { v10.2D-v11.2D }, [%[m]], #32 \n\t" + /* Copy r^2 to lower half of registers */ + "MOV v0.D[0], v0.D[1] \n\t" + "SUB %[bytes], %[bytes], %[POLY1305_BLOCK_SIZE]*2 \n\t" + "MOV v5.D[0], v5.D[1] \n\t" + "USHR v14.2D, v11.2D, #40 \n\t" + "MOV v1.D[0], v1.D[1] \n\t" + "ORR v14.16B, v14.16B, v26.16B \n\t" + "MOV v6.D[0], v6.D[1] \n\t" + "USHR v13.2D, v11.2D, #14 \n\t" + "MOV v2.D[0], v2.D[1] \n\t" + "AND v13.16B, v13.16B, v27.16B \n\t" + "MOV v7.D[0], v7.D[1] \n\t" + "SHL v12.2D, v11.2D, #12 \n\t" + "MOV v3.D[0], v3.D[1] \n\t" + "SRI v12.2D, v10.2D, #52 \n\t" + "MOV v8.D[0], v8.D[1] \n\t" + "AND v12.16B, v12.16B, v27.16B \n\t" + "MOV v4.D[0], v4.D[1] \n\t" + "USHR v11.2D, v10.2D, #26 \n\t" + "MOV v9.D[0], v9.D[1] \n\t" + "AND v11.16B, v11.16B, v27.16B \n\t" + /* Copy r^2 to ARM */ + "MOV w25, v0.S[2] \n\t" + "AND v10.16B, v10.16B, v27.16B \n\t" + "MOV w26, v1.S[2] \n\t" + /* Two message blocks loaded */ + /* Add last messages */ + "ADD v21.2D, v21.2D, v10.2D \n\t" + "MOV w27, v2.S[2] \n\t" + "ADD v22.2D, v22.2D, v11.2D \n\t" + "MOV w28, v3.S[2] \n\t" + "ADD v23.2D, v23.2D, v12.2D \n\t" + "MOV w30, v4.S[2] \n\t" + "ADD v24.2D, v24.2D, v13.2D \n\t" + /* Copy 5*r^2 to ARM */ + "MOV w15, v5.S[2] \n\t" + "ADD v25.2D, v25.2D, v14.2D \n\t" + "MOV w16, v6.S[2] \n\t" + /* Reduce message to be ready for next multiplication */ + /* Reduce radix 26 NEON */ + /* Interleave h0 -> h1 -> h2 -> h3 -> h4 */ + /* with h3 -> h4 -> h0 -> h1 */ + "USRA v22.2D, v21.2D, #26 \n\t" + "MOV w17, v7.S[2] \n\t" + "AND v21.16B, v21.16B, v27.16B \n\t" + "MOV w8, v8.S[2] \n\t" + "USRA v25.2D, v24.2D, #26 \n\t" + "MOV w19, v9.S[2] \n\t" + "AND v24.16B, v24.16B, v27.16B \n\t" + "USHR v15.2D, v25.2D, #26 \n\t" + "USRA v23.2D, v22.2D, #26 \n\t" + /* Simulate multiplying by 5 using adding and shifting */ + "SHL v18.2D, v15.2D, #2 \n\t" + "AND v16.16B, v22.16B, v27.16B \n\t" + "ADD v18.2D, v18.2D, v15.2D \n\t" + "AND v19.16B, v25.16B, v27.16B \n\t" + "ADD v21.2D, v21.2D, v18.2D \n\t" + "USRA v24.2D, v23.2D, #26 \n\t" + "AND v17.16B, v23.16B, v27.16B \n\t" + "USRA v16.2D, v21.2D, #26 \n\t" + "AND v15.16B, v21.16B, v27.16B \n\t" + "USRA v19.2D, v24.2D, #26 \n\t" + "AND v18.16B, v24.16B, v27.16B \n\t" + /* Copy values to lower halves of result registers */ + "MOV v15.S[1], v15.S[2] \n\t" + "MOV v16.S[1], v16.S[2] \n\t" + "MOV v17.S[1], v17.S[2] \n\t" + "MOV v18.S[1], v18.S[2] \n\t" + "MOV v19.S[1], v19.S[2] \n\t" + /* If less than 2 blocks left go straight to final multiplication. */ + "CMP %[bytes], %[POLY1305_BLOCK_SIZE]*2 \n\t" + "BLO L_poly1305_64_last_mult_%= \n\t" + /* Else go to one loop of L_poly1305_64_loop_64 */ + "B L_poly1305_64_loop_64_%= \n\t" + "\n" + ".align 2 \n\t" + "L_poly1305_64_start_block_size_64_%=: \n\t" + /* Load r^2 to NEON v0, v1, v2, v3, v4 */ + "LD4R { v0.2S-v3.2S }, [%[r_2]], #16 \n\t" + "LD1R { v4.2S }, [%[r_2]] \n\t" + "SUB %[r_2], %[r_2], #16 \n\t" + /* Store r^2 * 5 */ + "MUL v5.4S, v0.4S, v28.S[0] \n\t" + "MUL v6.4S, v1.4S, v28.S[0] \n\t" + "MUL v7.4S, v2.4S, v28.S[0] \n\t" + "MUL v8.4S, v3.4S, v28.S[0] \n\t" + "MUL v9.4S, v4.4S, v28.S[0] \n\t" + /* Copy r^2 to ARM */ + "MOV w25, v0.S[0] \n\t" + "MOV w26, v1.S[0] \n\t" + "MOV w27, v2.S[0] \n\t" + "MOV w28, v3.S[0] \n\t" + "MOV w30, v4.S[0] \n\t" + /* Copy 5*r^2 to ARM */ + "MOV w15, v5.S[0] \n\t" + "MOV w16, v6.S[0] \n\t" + "MOV w17, v7.S[0] \n\t" + "MOV w8, v8.S[0] \n\t" + "MOV w19, v9.S[0] \n\t" + /* Load m */ + /* Load two message blocks to NEON v10, v11, v12, v13, v14 */ + "LD2 { v10.2D-v11.2D }, [%[m]], #32 \n\t" + "SUB %[bytes], %[bytes], %[POLY1305_BLOCK_SIZE]*2 \n\t" + "USHR v14.2D, v11.2D, #40 \n\t" + "ORR v14.16B, v14.16B, v26.16B \n\t" + "USHR v13.2D, v11.2D, #14 \n\t" + "AND v13.16B, v13.16B, v27.16B \n\t" + "SHL v12.2D, v11.2D, #12 \n\t" + "SRI v12.2D, v10.2D, #52 \n\t" + "AND v12.16B, v12.16B, v27.16B \n\t" + "USHR v11.2D, v10.2D, #26 \n\t" + "AND v11.16B, v11.16B, v27.16B \n\t" + "AND v10.16B, v10.16B, v27.16B \n\t" + "MOV v10.S[1], v10.S[2] \n\t" + "MOV v11.S[1], v11.S[2] \n\t" + "MOV v12.S[1], v12.S[2] \n\t" + "MOV v13.S[1], v13.S[2] \n\t" + "MOV v14.S[1], v14.S[2] \n\t" + /* Two message blocks loaded */ + /* Add messages to accumulator */ + "ADD v15.2S, v15.2S, v10.2S \n\t" + "ADD v16.2S, v16.2S, v11.2S \n\t" + "ADD v17.2S, v17.2S, v12.2S \n\t" + "ADD v18.2S, v18.2S, v13.2S \n\t" + "ADD v19.2S, v19.2S, v14.2S \n\t" + "\n" + ".align 2 \n\t" + "L_poly1305_64_loop_64_%=: \n\t" + /* d0 = h0*r0 + h1*s4 + h2*s3 + h3*s2 + h4*s1 */ + /* d1 = h0*r1 + h1*r0 + h2*s4 + h3*s3 + h4*s2 */ + /* d2 = h0*r2 + h1*r1 + h2*r0 + h3*s4 + h4*s3 */ + /* d3 = h0*r3 + h1*r2 + h2*r1 + h3*r0 + h4*s4 */ + /* d4 = h0*r4 + h1*r3 + h2*r2 + h3*r1 + h4*r0 */ + "UMULL v21.2D, v15.2S, v0.2S \n\t" + /* Compute h*r^2 */ + /* d0 = h0 * r0 + h1 * s4 + h2 * s3 + h3 * s2 + h4 * s1 */ + /* d1 = h0 * r1 + h1 * r0 + h2 * s4 + h3 * s3 + h4 * s2 */ + /* d2 = h0 * r2 + h1 * r1 + h2 * r0 + h3 * s4 + h4 * s3 */ + /* d3 = h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * s4 */ + /* d4 = h0 * r4 + h1 * r3 + h2 * r2 + h3 * r1 + h4 * r0 */ + "MUL x9, x20, x25 \n\t" + "UMULL v22.2D, v15.2S, v1.2S \n\t" + "MUL x10, x20, x26 \n\t" + "UMULL v23.2D, v15.2S, v2.2S \n\t" + "MUL x11, x20, x27 \n\t" + "UMULL v24.2D, v15.2S, v3.2S \n\t" + "MUL x12, x20, x28 \n\t" + "UMULL v25.2D, v15.2S, v4.2S \n\t" + "MUL x13, x20, x30 \n\t" + "UMLAL v21.2D, v16.2S, v9.2S \n\t" + "MADD x9, x21, x19, x9 \n\t" + "UMLAL v22.2D, v16.2S, v0.2S \n\t" + "MADD x10, x21, x25, x10 \n\t" + "UMLAL v23.2D, v16.2S, v1.2S \n\t" + "MADD x11, x21, x26, x11 \n\t" + "UMLAL v24.2D, v16.2S, v2.2S \n\t" + "MADD x12, x21, x27, x12 \n\t" + "UMLAL v25.2D, v16.2S, v3.2S \n\t" + "MADD x13, x21, x28, x13 \n\t" + "UMLAL v21.2D, v17.2S, v8.2S \n\t" + "MADD x9, x22, x8, x9 \n\t" + "UMLAL v22.2D, v17.2S, v9.2S \n\t" + "MADD x10, x22, x19, x10 \n\t" + "UMLAL v23.2D, v17.2S, v0.2S \n\t" + "MADD x11, x22, x25, x11 \n\t" + "UMLAL v24.2D, v17.2S, v1.2S \n\t" + "MADD x12, x22, x26, x12 \n\t" + "UMLAL v25.2D, v17.2S, v2.2S \n\t" + "MADD x13, x22, x27, x13 \n\t" + "UMLAL v21.2D, v18.2S, v7.2S \n\t" + "MADD x9, x23, x17, x9 \n\t" + "UMLAL v22.2D, v18.2S, v8.2S \n\t" + "MADD x10, x23, x8, x10 \n\t" + "UMLAL v23.2D, v18.2S, v9.2S \n\t" + "MADD x11, x23, x19, x11 \n\t" + "UMLAL v24.2D, v18.2S, v0.2S \n\t" + "MADD x12, x23, x25, x12 \n\t" + "UMLAL v25.2D, v18.2S, v1.2S \n\t" + "MADD x13, x23, x26, x13 \n\t" + "UMLAL v21.2D, v19.2S, v6.2S \n\t" + "MADD x9, x24, x16, x9 \n\t" + "UMLAL v22.2D, v19.2S, v7.2S \n\t" + "MADD x10, x24, x17, x10 \n\t" + "UMLAL v23.2D, v19.2S, v8.2S \n\t" + "MADD x11, x24, x8, x11 \n\t" + "UMLAL v24.2D, v19.2S, v9.2S \n\t" + "MADD x12, x24, x19, x12 \n\t" + "UMLAL v25.2D, v19.2S, v0.2S \n\t" + "MADD x13, x24, x25, x13 \n\t" + /* Load m */ + /* Load two message blocks to NEON v10, v11, v12, v13, v14 */ + "LD2 { v10.2D-v11.2D }, [%[m]], #32 \n\t" + /* Reduce h % P */ + "MOV x14, #5 \n\t" + "SUB %[bytes], %[bytes], %[POLY1305_BLOCK_SIZE]*2 \n\t" + "ADD x10, x10, x9, LSR #26 \n\t" + "USHR v14.2D, v11.2D, #40 \n\t" + "ADD x13, x13, x12, LSR #26 \n\t" + "ORR v14.16B, v14.16B, v26.16B \n\t" + "AND x9, x9, #0x3ffffff \n\t" + "USHR v13.2D, v11.2D, #14 \n\t" + "LSR x20, x13, #26 \n\t" + "AND v13.16B, v13.16B, v27.16B \n\t" + "AND x12, x12, #0x3ffffff \n\t" + "SHL v12.2D, v11.2D, #12 \n\t" + "MADD x9, x20, x14, x9 \n\t" + "SRI v12.2D, v10.2D, #52 \n\t" + "ADD x11, x11, x10, LSR #26 \n\t" + "AND v12.16B, v12.16B, v27.16B \n\t" + "AND x10, x10, #0x3ffffff \n\t" + "USHR v11.2D, v10.2D, #26 \n\t" + "AND x13, x13, #0x3ffffff \n\t" + "AND v11.16B, v11.16B, v27.16B \n\t" + "ADD x12, x12, x11, LSR #26 \n\t" + "AND v10.16B, v10.16B, v27.16B \n\t" + "AND x22, x11, #0x3ffffff \n\t" + /* Two message blocks loaded */ + "ADD v21.2D, v21.2D, v10.2D \n\t" + "ADD x21, x10, x9, LSR #26 \n\t" + "ADD v22.2D, v22.2D, v11.2D \n\t" + "AND x20, x9, #0x3ffffff \n\t" + "ADD v23.2D, v23.2D, v12.2D \n\t" + "ADD x24, x13, x12, LSR #26 \n\t" + "ADD v24.2D, v24.2D, v13.2D \n\t" + "AND x23, x12, #0x3ffffff \n\t" + "ADD v25.2D, v25.2D, v14.2D \n\t" + /* Reduce radix 26 NEON */ + /* Interleave h0 -> h1 -> h2 -> h3 -> h4 */ + /* with h3 -> h4 -> h0 -> h1 */ + "USRA v22.2D, v21.2D, #26 \n\t" + "AND v21.16B, v21.16B, v27.16B \n\t" + "USRA v25.2D, v24.2D, #26 \n\t" + "AND v24.16B, v24.16B, v27.16B \n\t" + "USHR v15.2D, v25.2D, #26 \n\t" + "USRA v23.2D, v22.2D, #26 \n\t" + /* Simulate multiplying by 5 using adding and shifting */ + "SHL v18.2D, v15.2D, #2 \n\t" + "AND v16.16B, v22.16B, v27.16B \n\t" + "ADD v18.2D, v18.2D, v15.2D \n\t" + "AND v19.16B, v25.16B, v27.16B \n\t" + "ADD v21.2D, v21.2D, v18.2D \n\t" + "USRA v24.2D, v23.2D, #26 \n\t" + "AND v17.16B, v23.16B, v27.16B \n\t" + "USRA v16.2D, v21.2D, #26 \n\t" + "AND v15.16B, v21.16B, v27.16B \n\t" + "USRA v19.2D, v24.2D, #26 \n\t" + "AND v18.16B, v24.16B, v27.16B \n\t" + /* Copy values to lower halves of result registers */ + "MOV v15.S[1], v15.S[2] \n\t" + "MOV v16.S[1], v16.S[2] \n\t" + "MOV v17.S[1], v17.S[2] \n\t" + "MOV v18.S[1], v18.S[2] \n\t" + "MOV v19.S[1], v19.S[2] \n\t" + /* If at least two message blocks left then loop_64 */ + "CMP %[bytes], %[POLY1305_BLOCK_SIZE]*2 \n\t" + "BHS L_poly1305_64_loop_64_%= \n\t" + "\n" + ".align 2 \n\t" + "L_poly1305_64_last_mult_%=: \n\t" + /* Load r */ + "LD4 { v0.S-v3.S }[1], [%[r]], #16 \n\t" + /* Compute h*r^2 */ + /* d0 = h0 * r0 + h1 * s4 + h2 * s3 + h3 * s2 + h4 * s1 */ + /* d1 = h0 * r1 + h1 * r0 + h2 * s4 + h3 * s3 + h4 * s2 */ + /* d2 = h0 * r2 + h1 * r1 + h2 * r0 + h3 * s4 + h4 * s3 */ + /* d3 = h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * s4 */ + /* d4 = h0 * r4 + h1 * r3 + h2 * r2 + h3 * r1 + h4 * r0 */ + "MUL x9, x20, x25 \n\t" + "LD1 { v4.S }[1], [%[r]] \n\t" + "MUL x10, x20, x26 \n\t" + "SUB %[r], %[r], #16 \n\t" + "MUL x11, x20, x27 \n\t" + /* Store [r^2, r] * 5 */ + "MUL v5.2S, v0.2S, v28.S[0] \n\t" + "MUL x12, x20, x28 \n\t" + "MUL v6.2S, v1.2S, v28.S[0] \n\t" + "MUL x13, x20, x30 \n\t" + "MUL v7.2S, v2.2S, v28.S[0] \n\t" + "MADD x9, x21, x19, x9 \n\t" + "MUL v8.2S, v3.2S, v28.S[0] \n\t" + "MADD x10, x21, x25, x10 \n\t" + "MUL v9.2S, v4.2S, v28.S[0] \n\t" + "MADD x11, x21, x26, x11 \n\t" + /* Final multiply by [r^2, r] */ + /* d0 = h0*r0 + h1*s4 + h2*s3 + h3*s2 + h4*s1 */ + /* d1 = h0*r1 + h1*r0 + h2*s4 + h3*s3 + h4*s2 */ + /* d2 = h0*r2 + h1*r1 + h2*r0 + h3*s4 + h4*s3 */ + /* d3 = h0*r3 + h1*r2 + h2*r1 + h3*r0 + h4*s4 */ + /* d4 = h0*r4 + h1*r3 + h2*r2 + h3*r1 + h4*r0 */ + "UMULL v21.2D, v15.2S, v0.2S \n\t" + "MADD x12, x21, x27, x12 \n\t" + "UMULL v22.2D, v15.2S, v1.2S \n\t" + "MADD x13, x21, x28, x13 \n\t" + "UMULL v23.2D, v15.2S, v2.2S \n\t" + "MADD x9, x22, x8, x9 \n\t" + "UMULL v24.2D, v15.2S, v3.2S \n\t" + "MADD x10, x22, x19, x10 \n\t" + "UMULL v25.2D, v15.2S, v4.2S \n\t" + "MADD x11, x22, x25, x11 \n\t" + "UMLAL v21.2D, v16.2S, v9.2S \n\t" + "MADD x12, x22, x26, x12 \n\t" + "UMLAL v22.2D, v16.2S, v0.2S \n\t" + "MADD x13, x22, x27, x13 \n\t" + "UMLAL v23.2D, v16.2S, v1.2S \n\t" + "MADD x9, x23, x17, x9 \n\t" + "UMLAL v24.2D, v16.2S, v2.2S \n\t" + "MADD x10, x23, x8, x10 \n\t" + "UMLAL v25.2D, v16.2S, v3.2S \n\t" + "MADD x11, x23, x19, x11 \n\t" + "UMLAL v21.2D, v17.2S, v8.2S \n\t" + "MADD x12, x23, x25, x12 \n\t" + "UMLAL v22.2D, v17.2S, v9.2S \n\t" + "MADD x13, x23, x26, x13 \n\t" + "UMLAL v23.2D, v17.2S, v0.2S \n\t" + "MADD x9, x24, x16, x9 \n\t" + "UMLAL v24.2D, v17.2S, v1.2S \n\t" + "MADD x10, x24, x17, x10 \n\t" + "UMLAL v25.2D, v17.2S, v2.2S \n\t" + "MADD x11, x24, x8, x11 \n\t" + "UMLAL v21.2D, v18.2S, v7.2S \n\t" + "MADD x12, x24, x19, x12 \n\t" + "UMLAL v22.2D, v18.2S, v8.2S \n\t" + "MADD x13, x24, x25, x13 \n\t" + "UMLAL v23.2D, v18.2S, v9.2S \n\t" + /* Reduce h % P */ + "MOV x14, #5 \n\t" + "UMLAL v24.2D, v18.2S, v0.2S \n\t" + "ADD x10, x10, x9, LSR #26 \n\t" + "UMLAL v25.2D, v18.2S, v1.2S \n\t" + "ADD x13, x13, x12, LSR #26 \n\t" + "UMLAL v21.2D, v19.2S, v6.2S \n\t" + "AND x9, x9, #0x3ffffff \n\t" + "UMLAL v22.2D, v19.2S, v7.2S \n\t" + "LSR x20, x13, #26 \n\t" + "UMLAL v23.2D, v19.2S, v8.2S \n\t" + "AND x12, x12, #0x3ffffff \n\t" + "UMLAL v24.2D, v19.2S, v9.2S \n\t" + "MADD x9, x20, x14, x9 \n\t" + "UMLAL v25.2D, v19.2S, v0.2S \n\t" + "ADD x11, x11, x10, LSR #26 \n\t" + /* Add even and odd elements */ + "ADDP d21, v21.2D \n\t" + "AND x10, x10, #0x3ffffff \n\t" + "ADDP d22, v22.2D \n\t" + "AND x13, x13, #0x3ffffff \n\t" + "ADDP d23, v23.2D \n\t" + "ADD x12, x12, x11, LSR #26 \n\t" + "ADDP d24, v24.2D \n\t" + "AND x22, x11, #0x3ffffff \n\t" + "ADDP d25, v25.2D \n\t" + "ADD x21, x10, x9, LSR #26 \n\t" + "AND x20, x9, #0x3ffffff \n\t" + "ADD x24, x13, x12, LSR #26 \n\t" + "AND x23, x12, #0x3ffffff \n\t" + /* Load h to NEON */ + "MOV v5.D[0], x20 \n\t" + "MOV v6.D[0], x21 \n\t" + "MOV v7.D[0], x22 \n\t" + "MOV v8.D[0], x23 \n\t" + "MOV v9.D[0], x24 \n\t" + /* Add ctx->h to current accumulator */ + "ADD v21.2D, v21.2D, v5.2D \n\t" + "ADD v22.2D, v22.2D, v6.2D \n\t" + "ADD v23.2D, v23.2D, v7.2D \n\t" + "ADD v24.2D, v24.2D, v8.2D \n\t" + "ADD v25.2D, v25.2D, v9.2D \n\t" + /* Reduce h (h % P) */ + /* Reduce radix 26 NEON */ + /* Interleave h0 -> h1 -> h2 -> h3 -> h4 */ + /* with h3 -> h4 -> h0 -> h1 */ + "USRA v22.2D, v21.2D, #26 \n\t" + "AND v21.16B, v21.16B, v27.16B \n\t" + "USRA v25.2D, v24.2D, #26 \n\t" + "AND v24.16B, v24.16B, v27.16B \n\t" + "USHR v5.2D, v25.2D, #26 \n\t" + "USRA v23.2D, v22.2D, #26 \n\t" + /* Simulate multiplying by 5 using adding and shifting */ + "SHL v8.2D, v5.2D, #2 \n\t" + "AND v6.16B, v22.16B, v27.16B \n\t" + "ADD v8.2D, v8.2D, v5.2D \n\t" + "AND v9.16B, v25.16B, v27.16B \n\t" + "ADD v21.2D, v21.2D, v8.2D \n\t" + "USRA v24.2D, v23.2D, #26 \n\t" + "AND v7.16B, v23.16B, v27.16B \n\t" + "USRA v6.2D, v21.2D, #26 \n\t" + "AND v5.16B, v21.16B, v27.16B \n\t" + "USRA v9.2D, v24.2D, #26 \n\t" + "AND v8.16B, v24.16B, v27.16B \n\t" + /* Copy values to lower halves of result registers */ + /* Store h */ + "ST4 { v5.S-v8.S }[0], [%[h]], #16 \n\t" + "ST1 { v9.S }[0], [%[h]] \n\t" + "SUB %[h], %[h], #16 \n\t" + "\n" + ".align 2 \n\t" + "L_poly1305_64_done_%=: \n\t" + : [bytes] "+r" (bytes), + [m] "+r" (m), + [ctx] "+m" (ctx) + : [POLY1305_BLOCK_SIZE] "I" (POLY1305_BLOCK_SIZE), + [h] "r" (ctx->h), + [r] "r" (ctx->r), + [r_2] "r" (ctx->r_2), + [r_4] "r" (ctx->r_4), + [finished] "r" ((word64)ctx->finished) + : "memory", "cc", + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", + "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", + "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", + "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15", "w16", "w17", + "w19", "w20", "w21", "w22", "w23", "w24", "w25", "w26", "w27", "w28", + "w30", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", + "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", + "x28", "x30" + ); + poly1305_blocks_16(ctx, m, bytes); +} + +void poly1305_block(Poly1305* ctx, const unsigned char *m) +{ + poly1305_blocks_16(ctx, m, POLY1305_BLOCK_SIZE); +} + +#if defined(POLY130564) +static word64 clamp[] = { + 0x0ffffffc0fffffff, + 0x0ffffffc0ffffffc, +}; +#endif /* POLY130564 */ + + +int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) +{ + if (key == NULL) + return BAD_FUNC_ARG; + +#ifdef CHACHA_AEAD_TEST + word32 k; + printf("Poly key used:\n"); + for (k = 0; k < keySz; k++) { + printf("%02x", key[k]); + if ((k+1) % 8 == 0) + printf("\n"); + } + printf("\n"); +#endif + + if (keySz != 32 || ctx == NULL) + return BAD_FUNC_ARG; + + __asm__ __volatile__ ( + /* Load key material */ + "LDP x8, x9, [%[key]] \n\t" + "LDP x10, x11, [%[key], #16] \n\t" + /* Load clamp */ + "LDP x12, x13, [%[clamp]] \n\t" + /* Apply clamp */ + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + "AND x8, x8, x12 \n\t" + "AND x9, x9, x13 \n\t" + "MOV x19, xzr \n\t" + "MOV x20, xzr \n\t" + "MOV x21, xzr \n\t" + "MOV x22, xzr \n\t" + "MOV x23, xzr \n\t" + "BFI x19, x8, #0, #26 \n\t" + "LSR x8, x8, #26 \n\t" + "BFI x20, x8, #0, #26 \n\t" + "LSR x8, x8, #26 \n\t" + "BFI x21, x8, #0, #12 \n\t" + "BFI x21, x9, #12, #14 \n\t" + "LSR x9, x9, #14 \n\t" + "BFI x22, x9, #0, #26 \n\t" + "LSR x9, x9, #26 \n\t" + "BFI x23, x9, #0, #24 \n\t" + /* Compute r^2 */ + /* r*5 */ + "MOV x8, #5 \n\t" + "MUL x24, x20, x8 \n\t" + "MUL x25, x21, x8 \n\t" + "MUL x26, x22, x8 \n\t" + "MUL x27, x23, x8 \n\t" + /* d = r*r */ + /* d0 = h0 * r0 + h1 * s4 + h2 * s3 + h3 * s2 + h4 * s1 */ + /* d1 = h0 * r1 + h1 * r0 + h2 * s4 + h3 * s3 + h4 * s2 */ + /* d2 = h0 * r2 + h1 * r1 + h2 * r0 + h3 * s4 + h4 * s3 */ + /* d3 = h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * s4 */ + /* d4 = h0 * r4 + h1 * r3 + h2 * r2 + h3 * r1 + h4 * r0 */ + "MUL x14, x19, x19 \n\t" + "MUL x15, x19, x20 \n\t" + "MUL x16, x19, x21 \n\t" + "MUL x17, x19, x22 \n\t" + "MUL x7, x19, x23 \n\t" + "MADD x14, x20, x27, x14 \n\t" + "MADD x15, x20, x19, x15 \n\t" + "MADD x16, x20, x20, x16 \n\t" + "MADD x17, x20, x21, x17 \n\t" + "MADD x7, x20, x22, x7 \n\t" + "MADD x14, x21, x26, x14 \n\t" + "MADD x15, x21, x27, x15 \n\t" + "MADD x16, x21, x19, x16 \n\t" + "MADD x17, x21, x20, x17 \n\t" + "MADD x7, x21, x21, x7 \n\t" + "MADD x14, x22, x25, x14 \n\t" + "MADD x15, x22, x26, x15 \n\t" + "MADD x16, x22, x27, x16 \n\t" + "MADD x17, x22, x19, x17 \n\t" + "MADD x7, x22, x20, x7 \n\t" + "MADD x14, x23, x24, x14 \n\t" + "MADD x15, x23, x25, x15 \n\t" + "MADD x16, x23, x26, x16 \n\t" + "MADD x17, x23, x27, x17 \n\t" + "MADD x7, x23, x19, x7 \n\t" + /* r_2 = r^2 % P */ + "ADD x15, x15, x14, LSR #26 \n\t" + "ADD x7, x7, x17, LSR #26 \n\t" + "AND x14, x14, #0x3ffffff \n\t" + "LSR x9, x7, #26 \n\t" + "AND x17, x17, #0x3ffffff \n\t" + "MADD x14, x9, x8, x14 \n\t" + "ADD x16, x16, x15, LSR #26 \n\t" + "AND x15, x15, #0x3ffffff \n\t" + "AND x7, x7, #0x3ffffff \n\t" + "ADD x17, x17, x16, LSR #26 \n\t" + "AND x16, x16, #0x3ffffff \n\t" + "ADD x15, x15, x14, LSR #26 \n\t" + "AND x14, x14, #0x3ffffff \n\t" + "ADD x7, x7, x17, LSR #26 \n\t" + "AND x17, x17, #0x3ffffff \n\t" + /* Store r */ + "ORR x19, x19, x20, LSL #32 \n\t" + "ORR x21, x21, x22, LSL #32 \n\t" + "STP x19, x21, [%[ctx_r]] \n\t" + "STR w23, [%[ctx_r], #16] \n\t" + "MOV x8, #5 \n\t" + "MUL x24, x15, x8 \n\t" + "MUL x25, x16, x8 \n\t" + "MUL x26, x17, x8 \n\t" + "MUL x27, x7, x8 \n\t" + /* Compute r^4 */ + /* d0 = h0 * r0 + h1 * s4 + h2 * s3 + h3 * s2 + h4 * s1 */ + /* d1 = h0 * r1 + h1 * r0 + h2 * s4 + h3 * s3 + h4 * s2 */ + /* d2 = h0 * r2 + h1 * r1 + h2 * r0 + h3 * s4 + h4 * s3 */ + /* d3 = h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * s4 */ + /* d4 = h0 * r4 + h1 * r3 + h2 * r2 + h3 * r1 + h4 * r0 */ + "MUL x19, x14, x14 \n\t" + "MUL x20, x14, x15 \n\t" + "MUL x21, x14, x16 \n\t" + "MUL x22, x14, x17 \n\t" + "MUL x23, x14, x7 \n\t" + "MADD x19, x15, x27, x19 \n\t" + "MADD x20, x15, x14, x20 \n\t" + "MADD x21, x15, x15, x21 \n\t" + "MADD x22, x15, x16, x22 \n\t" + "MADD x23, x15, x17, x23 \n\t" + "MADD x19, x16, x26, x19 \n\t" + "MADD x20, x16, x27, x20 \n\t" + "MADD x21, x16, x14, x21 \n\t" + "MADD x22, x16, x15, x22 \n\t" + "MADD x23, x16, x16, x23 \n\t" + "MADD x19, x17, x25, x19 \n\t" + "MADD x20, x17, x26, x20 \n\t" + "MADD x21, x17, x27, x21 \n\t" + "MADD x22, x17, x14, x22 \n\t" + "MADD x23, x17, x15, x23 \n\t" + "MADD x19, x7, x24, x19 \n\t" + "MADD x20, x7, x25, x20 \n\t" + "MADD x21, x7, x26, x21 \n\t" + "MADD x22, x7, x27, x22 \n\t" + "MADD x23, x7, x14, x23 \n\t" + /* r^4 % P */ + "ADD x20, x20, x19, LSR #26 \n\t" + "ADD x23, x23, x22, LSR #26 \n\t" + "AND x19, x19, #0x3ffffff \n\t" + "LSR x9, x23, #26 \n\t" + "AND x22, x22, #0x3ffffff \n\t" + "MADD x19, x9, x8, x19 \n\t" + "ADD x21, x21, x20, LSR #26 \n\t" + "AND x20, x20, #0x3ffffff \n\t" + "AND x23, x23, #0x3ffffff \n\t" + "ADD x22, x22, x21, LSR #26 \n\t" + "AND x21, x21, #0x3ffffff \n\t" + "ADD x20, x20, x19, LSR #26 \n\t" + "AND x19, x19, #0x3ffffff \n\t" + "ADD x23, x23, x22, LSR #26 \n\t" + "AND x22, x22, #0x3ffffff \n\t" + /* Store r^2 */ + "ORR x14, x14, x15, LSL #32 \n\t" + "ORR x16, x16, x17, LSL #32 \n\t" + "STP x14, x16, [%[ctx_r_2]] \n\t" + "STR w7, [%[ctx_r_2], #16] \n\t" + /* Store r^4 */ + "ORR x19, x19, x20, LSL #32 \n\t" + "ORR x21, x21, x22, LSL #32 \n\t" + "STP x19, x21, [%[ctx_r_4]] \n\t" + "STR w23, [%[ctx_r_4], #16] \n\t" + /* h (accumulator) = 0 */ + "STP xzr, xzr, [%[ctx_h_0]] \n\t" + "STR wzr, [%[ctx_h_0], #16] \n\t" + /* Save pad for later */ + "STP x10, x11, [%[ctx_pad]] \n\t" + /* Zero leftover */ + "STR xzr, [%[ctx_leftover]] \n\t" + /* Zero finished */ + "STRB wzr, [%[ctx_finished]] \n\t" + : + : [clamp] "r" (clamp), + [key] "r" (key), + [ctx_r] "r" (ctx->r), + [ctx_r_2] "r" (ctx->r_2), + [ctx_r_4] "r" (ctx->r_4), + [ctx_h_0] "r" (ctx->h), + [ctx_pad] "r" (ctx->pad), + [ctx_leftover] "r" (&ctx->leftover), + [ctx_finished] "r" (&ctx->finished) + : "memory", "cc", + "w7", "w14", "w15", "w16", "w17", "w19", "w20", "w21", "w22", "w23", + "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", + "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27" + ); + + return 0; +} + + +int wc_Poly1305Final(Poly1305* ctx, byte* mac) +{ + + if (ctx == NULL) + return BAD_FUNC_ARG; + + /* process the remaining block */ + if (ctx->leftover) { + size_t i = ctx->leftover; + ctx->buffer[i++] = 1; + for (; i < POLY1305_BLOCK_SIZE; i++) + ctx->buffer[i] = 0; + ctx->finished = 1; + poly1305_block(ctx, ctx->buffer); + } + + __asm__ __volatile__ ( + /* Load raw h and zero h registers */ + "LDP x2, x3, %[h_addr] \n\t" + "MOV x5, xzr \n\t" + "LDR w4, %[h_4_addr] \n\t" + "MOV x6, xzr \n\t" + "LDP x16, x17, %[pad_addr] \n\t" + /* Base 26 -> Base 64 */ + "MOV w5, w2 \n\t" + "LSR x2, x2, #32 \n\t" + "ORR x5, x5, x2, LSL #26 \n\t" + "ORR x5, x5, x3, LSL #52 \n\t" + "LSR w6, w3, #12 \n\t" + "LSR x3, x3, #32 \n\t" + "ORR x6, x6, x3, LSL #14 \n\t" + "ORR x6, x6, x4, LSL #40 \n\t" + "LSR x7, x4, #24 \n\t" + /* Check if h is larger than p */ + "ADDS x2, x5, #5 \n\t" + "ADCS x3, x6, xzr \n\t" + "ADC x4, x7, xzr \n\t" + /* Check if h+5 is larger than 2^130 */ + "CMP x4, #3 \n\t" + "CSEL x5, x2, x5, HI \n\t" + "CSEL x6, x3, x6, HI \n\t" + "ADDS x5, x5, x16 \n\t" + "ADC x6, x6, x17 \n\t" + "STP x5, x6, [%[mac]] \n\t" + : [mac] "+r" (mac) + : [pad_addr] "m" (ctx->pad), + [h_addr] "m" (ctx->h), + [h_4_addr] "m" (ctx->h[4]) + : "memory", "cc", + "w2", "w3", "w4", "w5", "w6", "w7", "x2", "x3", "x4", "x5", + "x6", "x7", "x16", "x17" + ); + + /* zero out the state */ + ctx->h[0] = 0; + ctx->h[1] = 0; + ctx->h[2] = 0; + ctx->h[3] = 0; + ctx->h[4] = 0; + ctx->r[0] = 0; + ctx->r[1] = 0; + ctx->r[2] = 0; + ctx->r[3] = 0; + ctx->r[4] = 0; + ctx->r_2[0] = 0; + ctx->r_2[1] = 0; + ctx->r_2[2] = 0; + ctx->r_2[3] = 0; + ctx->r_2[4] = 0; + ctx->r_4[0] = 0; + ctx->r_4[1] = 0; + ctx->r_4[2] = 0; + ctx->r_4[3] = 0; + ctx->r_4[4] = 0; + ctx->pad[0] = 0; + ctx->pad[1] = 0; + ctx->pad[2] = 0; + ctx->pad[3] = 0; + + return 0; +} + +#endif /* HAVE_POLY1305 */ +#endif /* WOLFSSL_ARMASM */ +#endif /* __aarch64__ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha256.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha256.c new file mode 100644 index 000000000..7f214d47c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha256.c @@ -0,0 +1,1508 @@ +/* armv8-sha256.c + * + * Copyright (C) 2006-2020 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_ARMASM +#if !defined(NO_SHA256) || defined(WOLFSSL_SHA224) + +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +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 +}; + + +static int InitSha256(wc_Sha256* sha256) +{ + int ret = 0; + + if (sha256 == NULL) { + return BAD_FUNC_ARG; + } + + 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; + + return ret; +} + +static WC_INLINE void AddLength(wc_Sha256* sha256, word32 len) +{ + word32 tmp = sha256->loLen; + if ((sha256->loLen += len) < tmp) + sha256->hiLen++; /* carry low to high */ +} + + +#ifdef __aarch64__ + +/* ARMv8 hardware acceleration */ +static WC_INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) +{ + word32 add; + word32 numBlocks; + + /* only perform actions if a buffer is passed in */ + if (len > 0) { + /* fill leftover buffer with data */ + 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)/WC_SHA256_BLOCK_SIZE; + + if (numBlocks > 0) { + word32* k = (word32*)K; + + /* get leftover amount after blocks */ + add = (len + sha256->buffLen) - numBlocks * WC_SHA256_BLOCK_SIZE; + __asm__ volatile ( + "#load leftover data\n" + "LD1 {v0.2d-v3.2d}, %[buffer] \n" + + "#load current digest\n" + "LD1 {v12.2d-v13.2d}, %[digest] \n" + "MOV w8, %w[blocks] \n" + "REV32 v0.16b, v0.16b \n" + "REV32 v1.16b, v1.16b \n" + "REV32 v2.16b, v2.16b \n" + "REV32 v3.16b, v3.16b \n" + + "#load K values in \n" + "LD1 {v16.4s-v19.4s}, [%[k]], #64 \n" + "LD1 {v20.4s-v23.4s}, [%[k]], #64 \n" + "MOV v14.16b, v12.16b \n" /* store digest for add at the end */ + "MOV v15.16b, v13.16b \n" + "LD1 {v24.4s-v27.4s}, [%[k]], #64 \n" + "LD1 {v28.4s-v31.4s}, [%[k]], #64 \n" + + /* beginning of SHA256 block operation */ + "1:\n" + /* Round 1 */ + "MOV v4.16b, v0.16b \n" + "ADD v0.4s, v0.4s, v16.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 2 */ + "SHA256SU0 v4.4s, v1.4s \n" + "ADD v0.4s, v1.4s, v17.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v4.4s, v2.4s, v3.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 3 */ + "SHA256SU0 v1.4s, v2.4s \n" + "ADD v0.4s, v2.4s, v18.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v1.4s, v3.4s, v4.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 4 */ + "SHA256SU0 v2.4s, v3.4s \n" + "ADD v0.4s, v3.4s, v19.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v2.4s, v4.4s, v1.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 5 */ + "SHA256SU0 v3.4s, v4.4s \n" + "ADD v0.4s, v4.4s, v20.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v3.4s, v1.4s, v2.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 6 */ + "SHA256SU0 v4.4s, v1.4s \n" + "ADD v0.4s, v1.4s, v21.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v4.4s, v2.4s, v3.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 7 */ + "SHA256SU0 v1.4s, v2.4s \n" + "ADD v0.4s, v2.4s, v22.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v1.4s, v3.4s, v4.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 8 */ + "SHA256SU0 v2.4s, v3.4s \n" + "ADD v0.4s, v3.4s, v23.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v2.4s, v4.4s, v1.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 9 */ + "SHA256SU0 v3.4s, v4.4s \n" + "ADD v0.4s, v4.4s, v24.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v3.4s, v1.4s, v2.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 10 */ + "SHA256SU0 v4.4s, v1.4s \n" + "ADD v0.4s, v1.4s, v25.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v4.4s, v2.4s, v3.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 11 */ + "SHA256SU0 v1.4s, v2.4s \n" + "ADD v0.4s, v2.4s, v26.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v1.4s, v3.4s, v4.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 12 */ + "SHA256SU0 v2.4s, v3.4s \n" + "ADD v0.4s, v3.4s, v27.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v2.4s, v4.4s, v1.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 13 */ + "SHA256SU0 v3.4s, v4.4s \n" + "ADD v0.4s, v4.4s, v28.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256SU1 v3.4s, v1.4s, v2.4s \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 14 */ + "ADD v0.4s, v1.4s, v29.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 15 */ + "ADD v0.4s, v2.4s, v30.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + /* Round 16 */ + "ADD v0.4s, v3.4s, v31.4s \n" + "MOV v11.16b, v12.16b \n" + "SHA256H q12, q13, v0.4s \n" + "SHA256H2 q13, q11, v0.4s \n" + + "#Add working vars back into digest state \n" + "SUB w8, w8, #1 \n" + "ADD v12.4s, v12.4s, v14.4s \n" + "ADD v13.4s, v13.4s, v15.4s \n" + + "#check if more blocks should be done\n" + "CBZ w8, 2f \n" + + "#load in message and schedule updates \n" + "LD1 {v0.2d-v3.2d}, [%[dataIn]], #64 \n" + "MOV v14.16b, v12.16b \n" + "MOV v15.16b, v13.16b \n" + "REV32 v0.16b, v0.16b \n" + "REV32 v1.16b, v1.16b \n" + "REV32 v2.16b, v2.16b \n" + "REV32 v3.16b, v3.16b \n" + "B 1b \n" /* do another block */ + + "2:\n" + "STP q12, q13, %[out] \n" + + : [out] "=m" (sha256->digest), "=m" (sha256->buffer), "=r" (numBlocks), + "=r" (data), "=r" (k) + : [k] "4" (k), [digest] "m" (sha256->digest), [buffer] "m" (sha256->buffer), + [blocks] "2" (numBlocks), [dataIn] "3" (data) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", "v12", "v13", "v14", + "v15", "v16", "v17", "v18", "v19", "v20", "v21", + "v22", "v23", "v24", "v25", "v26", "v27", "v28", + "v29", "v30", "v31", "w8" + ); + + AddLength(sha256, WC_SHA256_BLOCK_SIZE * numBlocks); + + /* copy over any remaining data leftover */ + XMEMCPY(sha256->buffer, data, add); + sha256->buffLen = add; + } + } + + /* account for possibility of not used if len = 0 */ + (void)add; + (void)numBlocks; + + return 0; +} + + +static WC_INLINE int Sha256Final(wc_Sha256* sha256, byte* hash) +{ + byte* local; + + local = (byte*)sha256->buffer; + 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; + __asm__ volatile ( + "LD1 {v4.2d-v7.2d}, %[buffer] \n" + "MOV v0.16b, v4.16b \n" + "MOV v1.16b, v5.16b \n" + "REV32 v0.16b, v0.16b \n" + "REV32 v1.16b, v1.16b \n" + "MOV v2.16b, v6.16b \n" + "MOV v3.16b, v7.16b \n" + "REV32 v2.16b, v2.16b \n" + "REV32 v3.16b, v3.16b \n" + "MOV v4.16b, v0.16b \n" + "MOV v5.16b, v1.16b \n" + "LD1 {v20.2d-v21.2d}, %[digest] \n" + + "#SHA256 operation on updated message \n" + "MOV v16.16b, v20.16b \n" + "MOV v17.16b, v21.16b \n" + + "LD1 {v22.16b-v25.16b}, [%[k]], #64 \n" + "SHA256SU0 v4.4s, v1.4s \n" + "ADD v0.4s, v0.4s, v22.4s \n" + "MOV v6.16b, v2.16b \n" + "MOV v18.16b, v16.16b \n" + "SHA256SU1 v4.4s, v2.4s, v3.4s \n" + "SHA256H q16, q17, v0.4s \n" + "SHA256H2 q17, q18, v0.4s \n" + + "SHA256SU0 v5.4s, v2.4s \n" + "ADD v1.4s, v1.4s, v23.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v7.16b, v3.16b \n" + "SHA256SU1 v5.4s, v3.4s, v4.4s \n" + "SHA256H q16, q17, v1.4s \n" + "SHA256H2 q17, q18, v1.4s \n" + + "SHA256SU0 v6.4s, v3.4s \n" + "ADD v2.4s, v2.4s, v24.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v8.16b, v4.16b \n" + "SHA256SU1 v6.4s, v4.4s, v5.4s \n" + "SHA256H q16, q17, v2.4s \n" + "SHA256H2 q17, q18, v2.4s \n" + + "SHA256SU0 v7.4s, v4.4s \n" + "ADD v3.4s, v3.4s, v25.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v9.16b, v5.16b \n" + "SHA256SU1 v7.4s, v5.4s, v6.4s \n" + "SHA256H q16, q17, v3.4s \n" + "SHA256H2 q17, q18, v3.4s \n" + + "LD1 {v22.16b-v25.16b}, [%[k]], #64 \n" + "SHA256SU0 v8.4s, v5.4s \n" + "ADD v4.4s, v4.4s, v22.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v10.16b, v6.16b \n" + "SHA256SU1 v8.4s, v6.4s, v7.4s \n" + "SHA256H q16, q17, v4.4s \n" + "SHA256H2 q17, q18, v4.4s \n" + + "SHA256SU0 v9.4s, v6.4s \n" + "ADD v5.4s, v5.4s, v23.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v11.16b, v7.16b \n" + "SHA256SU1 v9.4s, v7.4s, v8.4s \n" + "SHA256H q16, q17, v5.4s \n" + "SHA256H2 q17, q18, v5.4s \n" + + "SHA256SU0 v10.4s, v7.4s \n" + "ADD v6.4s, v6.4s, v24.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v12.16b, v8.16b \n" + "SHA256SU1 v10.4s, v8.4s, v9.4s \n" + "SHA256H q16, q17, v6.4s \n" + "SHA256H2 q17, q18, v6.4s \n" + + "SHA256SU0 v11.4s, v8.4s \n" + "ADD v7.4s, v7.4s, v25.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v13.16b, v9.16b \n" + "SHA256SU1 v11.4s, v9.4s, v10.4s \n" + "SHA256H q16, q17, v7.4s \n" + "SHA256H2 q17, q18, v7.4s \n" + + "LD1 {v22.16b-v25.16b}, [%[k]], #64 \n" + "SHA256SU0 v12.4s, v9.4s \n" + "ADD v8.4s, v8.4s, v22.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v14.16b, v10.16b \n" + "SHA256SU1 v12.4s, v10.4s, v11.4s \n" + "SHA256H q16, q17, v8.4s \n" + "SHA256H2 q17, q18, v8.4s \n" + + "SHA256SU0 v13.4s, v10.4s \n" + "ADD v9.4s, v9.4s, v23.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v15.16b, v11.16b \n" + "SHA256SU1 v13.4s, v11.4s, v12.4s \n" + "SHA256H q16, q17, v9.4s \n" + "SHA256H2 q17, q18, v9.4s \n" + + "SHA256SU0 v14.4s, v11.4s \n" + "ADD v10.4s, v10.4s, v24.4s \n" + "MOV v18.16b, v16.16b \n" + "SHA256SU1 v14.4s, v12.4s, v13.4s \n" + "SHA256H q16, q17, v10.4s \n" + "SHA256H2 q17, q18, v10.4s \n" + + "SHA256SU0 v15.4s, v12.4s \n" + "ADD v11.4s, v11.4s, v25.4s \n" + "MOV v18.16b, v16.16b \n" + "SHA256SU1 v15.4s, v13.4s, v14.4s \n" + "SHA256H q16, q17, v11.4s \n" + "SHA256H2 q17, q18, v11.4s \n" + + "LD1 {v22.16b-v25.16b}, [%[k]] \n" + "ADD v12.4s, v12.4s, v22.4s \n" + "MOV v18.16b, v16.16b \n" + "SHA256H q16, q17, v12.4s \n" + "SHA256H2 q17, q18, v12.4s \n" + + "ADD v13.4s, v13.4s, v23.4s \n" + "MOV v18.16b, v16.16b \n" + "SHA256H q16, q17, v13.4s \n" + "SHA256H2 q17, q18, v13.4s \n" + + "ADD v14.4s, v14.4s, v24.4s \n" + "MOV v18.16b, v16.16b \n" + "SHA256H q16, q17, v14.4s \n" + "SHA256H2 q17, q18, v14.4s \n" + + "ADD v15.4s, v15.4s, v25.4s \n" + "MOV v18.16b, v16.16b \n" + "SHA256H q16, q17, v15.4s \n" + "SHA256H2 q17, q18, v15.4s \n" + + "#Add working vars back into digest state \n" + "ADD v16.4s, v16.4s, v20.4s \n" + "ADD v17.4s, v17.4s, v21.4s \n" + "STP q16, q17, %[out] \n" + + : [out] "=m" (sha256->digest) + : [k] "r" (K), [digest] "m" (sha256->digest), + [buffer] "m" (sha256->buffer) + : "cc", "memory", "v0", "v1", "v2", "v3", "v8", "v9", "v10", "v11" + , "v12", "v13", "v14", "v15", "v16", "v17", "v18" + , "v19", "v20", "v21", "v22", "v23", "v24", "v25" + ); + + 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) + __asm__ volatile ( + "LD1 {v0.2d-v3.2d}, %[in] \n" + "REV32 v0.16b, v0.16b \n" + "REV32 v1.16b, v1.16b \n" + "REV32 v2.16b, v2.16b \n" + "REV32 v3.16b, v3.16b \n" + "ST1 {v0.2d-v3.2d}, %[out] \n" + : [out] "=m" (sha256->buffer) + : [in] "m" (sha256->buffer) + : "cc", "memory", "v0", "v1", "v2", "v3" + ); + #endif + /* ! 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)); + + __asm__ volatile ( + "#load in message and schedule updates \n" + "LD1 {v4.2d-v7.2d}, %[buffer] \n" + "MOV v0.16b, v4.16b \n" + "MOV v1.16b, v5.16b \n" + "MOV v2.16b, v6.16b \n" + "MOV v3.16b, v7.16b \n" + "LD1 {v20.2d-v21.2d}, %[digest] \n" + + "MOV v16.16b, v20.16b \n" + "MOV v17.16b, v21.16b \n" + "LD1 {v22.16b-v25.16b}, [%[k]], #64 \n" + "SHA256SU0 v4.4s, v1.4s \n" + "ADD v0.4s, v0.4s, v22.4s \n" + "MOV v6.16b, v2.16b \n" + "MOV v18.16b, v16.16b \n" + "SHA256SU1 v4.4s, v2.4s, v3.4s \n" + "SHA256H q16, q17, v0.4s \n" + "SHA256H2 q17, q18, v0.4s \n" + + "SHA256SU0 v5.4s, v2.4s \n" + "ADD v1.4s, v1.4s, v23.4s \n" + "MOV v7.16b, v3.16b \n" + "MOV v18.16b, v16.16b \n" + "SHA256SU1 v5.4s, v3.4s, v4.4s \n" + "SHA256H q16, q17, v1.4s \n" + "SHA256H2 q17, q18, v1.4s \n" + + "SHA256SU0 v6.4s, v3.4s \n" + "ADD v2.4s, v2.4s, v24.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v8.16b, v4.16b \n" + "SHA256SU1 v6.4s, v4.4s, v5.4s \n" + "SHA256H q16, q17, v2.4s \n" + "SHA256H2 q17, q18, v2.4s \n" + + "SHA256SU0 v7.4s, v4.4s \n" + "ADD v3.4s, v3.4s, v25.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v9.16b, v5.16b \n" + "SHA256SU1 v7.4s, v5.4s, v6.4s \n" + "SHA256H q16, q17, v3.4s \n" + "SHA256H2 q17, q18, v3.4s \n" + + "LD1 {v22.16b-v25.16b}, [%[k]], #64 \n" + "SHA256SU0 v8.4s, v5.4s \n" + "ADD v4.4s, v4.4s, v22.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v10.16b, v6.16b \n" + "SHA256SU1 v8.4s, v6.4s, v7.4s \n" + "SHA256H q16, q17, v4.4s \n" + "SHA256H2 q17, q18, v4.4s \n" + + "SHA256SU0 v9.4s, v6.4s \n" + "ADD v5.4s, v5.4s, v23.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v11.16b, v7.16b \n" + "SHA256SU1 v9.4s, v7.4s, v8.4s \n" + "SHA256H q16, q17, v5.4s \n" + "SHA256H2 q17, q18, v5.4s \n" + + "SHA256SU0 v10.4s, v7.4s \n" + "ADD v6.4s, v6.4s, v24.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v12.16b, v8.16b \n" + "SHA256SU1 v10.4s, v8.4s, v9.4s \n" + "SHA256H q16, q17, v6.4s \n" + "SHA256H2 q17, q18, v6.4s \n" + + "SHA256SU0 v11.4s, v8.4s \n" + "ADD v7.4s, v7.4s, v25.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v13.16b, v9.16b \n" + "SHA256SU1 v11.4s, v9.4s, v10.4s \n" + "SHA256H q16, q17, v7.4s \n" + "SHA256H2 q17, q18, v7.4s \n" + + "LD1 {v22.16b-v25.16b}, [%[k]], #64 \n" + "SHA256SU0 v12.4s, v9.4s \n" + "ADD v8.4s, v8.4s, v22.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v14.16b, v10.16b \n" + "SHA256SU1 v12.4s, v10.4s, v11.4s \n" + "SHA256H q16, q17, v8.4s \n" + "SHA256H2 q17, q18, v8.4s \n" + + "SHA256SU0 v13.4s, v10.4s \n" + "ADD v9.4s, v9.4s, v23.4s \n" + "MOV v18.16b, v16.16b \n" + "MOV v15.16b, v11.16b \n" + "SHA256SU1 v13.4s, v11.4s, v12.4s \n" + "SHA256H q16, q17, v9.4s \n" + "SHA256H2 q17, q18, v9.4s \n" + + "SHA256SU0 v14.4s, v11.4s \n" + "ADD v10.4s, v10.4s, v24.4s \n" + "MOV v18.16b, v16.16b \n" + "SHA256SU1 v14.4s, v12.4s, v13.4s \n" + "SHA256H q16, q17, v10.4s \n" + "SHA256H2 q17, q18, v10.4s \n" + + "SHA256SU0 v15.4s, v12.4s \n" + "ADD v11.4s, v11.4s, v25.4s \n" + "MOV v18.16b, v16.16b \n" + "SHA256SU1 v15.4s, v13.4s, v14.4s \n" + "SHA256H q16, q17, v11.4s \n" + "SHA256H2 q17, q18, v11.4s \n" + + "LD1 {v22.16b-v25.16b}, [%[k]] \n" + "ADD v12.4s, v12.4s, v22.4s \n" + "MOV v18.16b, v16.16b \n" + "SHA256H q16, q17, v12.4s \n" + "SHA256H2 q17, q18, v12.4s \n" + + "ADD v13.4s, v13.4s, v23.4s \n" + "MOV v18.16b, v16.16b \n" + "SHA256H q16, q17, v13.4s \n" + "SHA256H2 q17, q18, v13.4s \n" + + "ADD v14.4s, v14.4s, v24.4s \n" + "MOV v18.16b, v16.16b \n" + "SHA256H q16, q17, v14.4s \n" + "SHA256H2 q17, q18, v14.4s \n" + + "ADD v15.4s, v15.4s, v25.4s \n" + "MOV v18.16b, v16.16b \n" + "SHA256H q16, q17, v15.4s \n" + "SHA256H2 q17, q18, v15.4s \n" + + "#Add working vars back into digest state \n" + "ADD v16.4s, v16.4s, v20.4s \n" + "ADD v17.4s, v17.4s, v21.4s \n" + + "#Store value as hash output \n" + #if defined(LITTLE_ENDIAN_ORDER) + "REV32 v16.16b, v16.16b \n" + #endif + "ST1 {v16.16b}, [%[hashOut]], #16 \n" + #if defined(LITTLE_ENDIAN_ORDER) + "REV32 v17.16b, v17.16b \n" + #endif + "ST1 {v17.16b}, [%[hashOut]] \n" + : [hashOut] "=r" (hash) + : [k] "r" (K), [digest] "m" (sha256->digest), + [buffer] "m" (sha256->buffer), + "0" (hash) + : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", "v12", "v13", "v14", + "v15", "v16", "v17", "v18", "v19", "v20", "v21", + "v22", "v23", "v24", "v25" + ); + + return 0; +} + +#else /* not using 64 bit */ + +/* ARMv8 hardware acceleration Aarch32 */ +static WC_INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) +{ + word32 add; + word32 numBlocks; + + /* only perform actions if a buffer is passed in */ + if (len > 0) { + /* fill leftover buffer with data */ + 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)/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 * WC_SHA256_BLOCK_SIZE; + __asm__ volatile ( + "#load leftover data\n" + "VLDM %[buffer]!, {q0-q3} \n" + + "#load current digest\n" + "VLDM %[digest], {q12-q13} \n" + "MOV r8, %[blocks] \n" + "VREV32.8 q0, q0 \n" + "VREV32.8 q1, q1 \n" + "VREV32.8 q2, q2 \n" + "VREV32.8 q3, q3 \n" + "VLDM %[k]! ,{q5-q8} \n" + "VLDM %[k]! ,{q9}\n" + + "VMOV.32 q14, q12 \n" /* store digest for add at the end */ + "VMOV.32 q15, q13 \n" + + /* beginning of SHA256 block operation */ + "1:\n" + + /* Round 1 */ + "VMOV.32 q4, q0 \n" + "VADD.i32 q0, q0, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 2 */ + "SHA256SU0.32 q4, q1 \n" + "VADD.i32 q0, q1, q6 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q4, q2, q3 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 3 */ + "SHA256SU0.32 q1, q2 \n" + "VADD.i32 q0, q2, q7 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q1, q3, q4 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 4 */ + "SHA256SU0.32 q2, q3 \n" + "VADD.i32 q0, q3, q8 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q2, q4, q1 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 5 */ + "SHA256SU0.32 q3, q4 \n" + "VADD.i32 q0, q4, q9 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q3, q1, q2 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 6 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q4, q1 \n" + "VADD.i32 q0, q1, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q4, q2, q3 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 7 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q1, q2 \n" + "VADD.i32 q0, q2, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q1, q3, q4 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 8 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q2, q3 \n" + "VADD.i32 q0, q3, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q2, q4, q1 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 9 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q3, q4 \n" + "VADD.i32 q0, q4, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q3, q1, q2 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 10 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q4, q1 \n" + "VADD.i32 q0, q1, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q4, q2, q3 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 11 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q1, q2 \n" + "VADD.i32 q0, q2, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q1, q3, q4 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 12 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q2, q3 \n" + "VADD.i32 q0, q3, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q2, q4, q1 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 13 */ + "VLD1.32 {q10}, [%[k]]! \n" + "SHA256SU0.32 q3, q4 \n" + "VADD.i32 q0, q4, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q3, q1, q2 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 14 */ + "VLD1.32 {q10}, [%[k]]! \n" + "VADD.i32 q0, q1, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 15 */ + "VLD1.32 {q10}, [%[k]]! \n" + "VADD.i32 q0, q2, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 16 */ + "VLD1.32 {q10}, [%[k]] \n" + "SUB r8, r8, #1 \n" + "VADD.i32 q0, q3, q10 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + "#Add working vars back into digest state \n" + "VADD.i32 q12, q12, q14 \n" + "VADD.i32 q13, q13, q15 \n" + + "#check if more blocks should be done\n" + "CMP r8, #0 \n" + "BEQ 2f \n" + + "#load in message and schedule updates \n" + "VLD1.32 {q0}, [%[dataIn]]! \n" + "VLD1.32 {q1}, [%[dataIn]]! \n" + "VLD1.32 {q2}, [%[dataIn]]! \n" + "VLD1.32 {q3}, [%[dataIn]]! \n" + + /* reset K pointer */ + "SUB %[k], %[k], #160 \n" + "VREV32.8 q0, q0 \n" + "VREV32.8 q1, q1 \n" + "VREV32.8 q2, q2 \n" + "VREV32.8 q3, q3 \n" + "VMOV.32 q14, q12 \n" + "VMOV.32 q15, q13 \n" + "B 1b \n" /* do another block */ + + "2:\n" + "VST1.32 {q12, q13}, [%[out]] \n" + + : [out] "=r" (digPt), "=r" (bufPt), "=r" (numBlocks), + "=r" (data) + : [k] "r" (K), [digest] "0" (digPt), [buffer] "1" (bufPt), + [blocks] "2" (numBlocks), [dataIn] "3" (data) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", + "q8", "q9", "q10", "q11", "q12", "q13", "q14", + "q15", "r8" + ); + + AddLength(sha256, WC_SHA256_BLOCK_SIZE * numBlocks); + + /* copy over any remaining data leftover */ + XMEMCPY(sha256->buffer, data, add); + sha256->buffLen = add; + } + } + + /* account for possibility of not used if len = 0 */ + (void)add; + (void)numBlocks; + + return 0; +} + + +static WC_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 > WC_SHA256_PAD_SIZE) { + word32* bufPt = sha256->buffer; + word32* digPt = sha256->digest; + 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" + + "#load current digest\n" + "VLDM %[digest], {q12-q13} \n" + "VREV32.8 q0, q0 \n" + "VREV32.8 q1, q1 \n" + "VREV32.8 q2, q2 \n" + "VREV32.8 q3, q3 \n" + + "#load K values in \n" + "VMOV.32 q14, q12 \n" /* store digest for add at the end */ + "VMOV.32 q15, q13 \n" + + /* beginning of SHA256 block operation */ + /* Round 1 */ + "VLD1.32 {q5}, [%[k]]! \n" + "VMOV.32 q4, q0 \n" + "VADD.i32 q0, q0, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 2 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q4, q1 \n" + "VADD.i32 q0, q1, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q4, q2, q3 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 3 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q1, q2 \n" + "VADD.i32 q0, q2, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q1, q3, q4 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 4 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q2, q3 \n" + "VADD.i32 q0, q3, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q2, q4, q1 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 5 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q3, q4 \n" + "VADD.i32 q0, q4, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q3, q1, q2 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 6 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q4, q1 \n" + "VADD.i32 q0, q1, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q4, q2, q3 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 7 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q1, q2 \n" + "VADD.i32 q0, q2, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q1, q3, q4 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 8 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q2, q3 \n" + "VADD.i32 q0, q3, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q2, q4, q1 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 9 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q3, q4 \n" + "VADD.i32 q0, q4, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q3, q1, q2 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 10 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q4, q1 \n" + "VADD.i32 q0, q1, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q4, q2, q3 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 11 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q1, q2 \n" + "VADD.i32 q0, q2, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q1, q3, q4 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 12 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q2, q3 \n" + "VADD.i32 q0, q3, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q2, q4, q1 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 13 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q3, q4 \n" + "VADD.i32 q0, q4, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q3, q1, q2 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 14 */ + "VLD1.32 {q5}, [%[k]]! \n" + "VADD.i32 q0, q1, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 15 */ + "VLD1.32 {q5}, [%[k]]! \n" + "VADD.i32 q0, q2, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 16 */ + "VLD1.32 {q5}, [%[k]]! \n" + "VADD.i32 q0, q3, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + "#Add working vars back into digest state \n" + "VADD.i32 q12, q12, q14 \n" + "VADD.i32 q13, q13, q15 \n" + + /* reset K pointer */ + "SUB %[k], %[k], #256 \n" + "VST1.32 {q12, q13}, [%[out]] \n" + + : [out] "=r" (digPt), "=r" (bufPt) + : [k] "r" (K), [digest] "0" (digPt), [buffer] "1" (bufPt) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", + "q8", "q9", "q10", "q11", "q12", "q13", "q14", + "q15" + ); + + 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) + { + word32* bufPt = sha256->buffer; + __asm__ volatile ( + "VLD1.32 {q0}, [%[in]] \n" + "VREV32.8 q0, q0 \n" + "VST1.32 {q0}, [%[out]]!\n" + "VLD1.32 {q1}, [%[in]] \n" + "VREV32.8 q1, q1 \n" + "VST1.32 {q1}, [%[out]]!\n" + "VLD1.32 {q2}, [%[in]] \n" + "VREV32.8 q2, q2 \n" + "VST1.32 {q2}, [%[out]]!\n" + "VLD1.32 {q3}, [%[in]] \n" + "VREV32.8 q3, q3 \n" + "VST1.32 {q3}, [%[out]] \n" + : [out] "=r" (bufPt) + : [in] "0" (bufPt) + : "cc", "memory", "q0", "q1", "q2", "q3" + ); + } + #endif + /* ! 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)); + + bufPt = sha256->buffer; + word32* digPt = sha256->digest; + __asm__ volatile ( + "#load leftover data\n" + "VLDM %[buffer]!, {q0-q3} \n" + + "#load current digest\n" + "VLDM %[digest], {q12-q13} \n" + + "VMOV.32 q14, q12 \n" /* store digest for add at the end */ + "VMOV.32 q15, q13 \n" + + /* beginning of SHA256 block operation */ + /* Round 1 */ + "VLD1.32 {q5}, [%[k]]! \n" + "VMOV.32 q4, q0 \n" + "VADD.i32 q0, q0, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 2 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q4, q1 \n" + "VADD.i32 q0, q1, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q4, q2, q3 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 3 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q1, q2 \n" + "VADD.i32 q0, q2, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q1, q3, q4 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 4 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q2, q3 \n" + "VADD.i32 q0, q3, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q2, q4, q1 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 5 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q3, q4 \n" + "VADD.i32 q0, q4, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q3, q1, q2 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 6 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q4, q1 \n" + "VADD.i32 q0, q1, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q4, q2, q3 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 7 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q1, q2 \n" + "VADD.i32 q0, q2, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q1, q3, q4 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 8 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q2, q3 \n" + "VADD.i32 q0, q3, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q2, q4, q1 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 9 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q3, q4 \n" + "VADD.i32 q0, q4, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q3, q1, q2 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 10 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q4, q1 \n" + "VADD.i32 q0, q1, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q4, q2, q3 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 11 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q1, q2 \n" + "VADD.i32 q0, q2, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q1, q3, q4 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 12 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q2, q3 \n" + "VADD.i32 q0, q3, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q2, q4, q1 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 13 */ + "VLD1.32 {q5}, [%[k]]! \n" + "SHA256SU0.32 q3, q4 \n" + "VADD.i32 q0, q4, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256SU1.32 q3, q1, q2 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 14 */ + "VLD1.32 {q5}, [%[k]]! \n" + "VADD.i32 q0, q1, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 15 */ + "VLD1.32 {q5}, [%[k]]! \n" + "VADD.i32 q0, q2, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + /* Round 16 */ + "VLD1.32 {q5}, [%[k]]! \n" + "VADD.i32 q0, q3, q5 \n" + "VMOV.32 q11, q12 \n" + "SHA256H.32 q12, q13, q0 \n" + "SHA256H2.32 q13, q11, q0 \n" + + "#Add working vars back into digest state \n" + "VADD.i32 q12, q12, q14 \n" + "VADD.i32 q13, q13, q15 \n" + + "#Store value as hash output \n" + #if defined(LITTLE_ENDIAN_ORDER) + "VREV32.8 q12, q12 \n" + #endif + "VST1.32 {q12}, [%[hashOut]]! \n" + #if defined(LITTLE_ENDIAN_ORDER) + "VREV32.8 q13, q13 \n" + #endif + "VST1.32 {q13}, [%[hashOut]] \n" + + : [out] "=r" (digPt), "=r" (bufPt), + [hashOut] "=r" (hash) + : [k] "r" (K), [digest] "0" (digPt), [buffer] "1" (bufPt), + "2" (hash) + : "cc", "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", + "q8", "q9", "q10", "q11", "q12", "q13", "q14", + "q15" + ); + + return 0; +} + +#endif /* __aarch64__ */ + + +#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; +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Sha256SetFlags(wc_Sha256* sha256, word32 flags) +{ + if (sha256) { + sha256->flags = flags; + } + return 0; +} +int wc_Sha256GetFlags(wc_Sha256* sha256, word32* flags) +{ + if (sha256 && flags) { + *flags = sha256->flags; + } + return 0; +} +#endif + +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; + } + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + int wc_Sha224SetFlags(wc_Sha224* sha224, word32 flags) + { + if (sha224) { + sha224->flags = flags; + } + return 0; + } + int wc_Sha224GetFlags(wc_Sha224* sha224, word32* flags) + { + if (sha224 && flags) { + *flags = sha224->flags; + } + return 0; + } +#endif + + 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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha512-asm.S b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha512-asm.S new file mode 100644 index 000000000..a35bccbda --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha512-asm.S @@ -0,0 +1,1046 @@ +/* armv8-sha512-asm + * + * Copyright (C) 2006-2020 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 + */ + +/* Generated using (from wolfssl): + * cd ../scripts + * ruby ./sha2/sha512.rb arm64 ../wolfssl/wolfcrypt/src/port/arm/armv8-sha512-asm.S + */ +#ifdef __aarch64__ + .text + .section .rodata + .type L_SHA512_transform_neon_len_k, %object + .size L_SHA512_transform_neon_len_k, 640 + .align 3 +L_SHA512_transform_neon_len_k: + .xword 0x428a2f98d728ae22 + .xword 0x7137449123ef65cd + .xword 0xb5c0fbcfec4d3b2f + .xword 0xe9b5dba58189dbbc + .xword 0x3956c25bf348b538 + .xword 0x59f111f1b605d019 + .xword 0x923f82a4af194f9b + .xword 0xab1c5ed5da6d8118 + .xword 0xd807aa98a3030242 + .xword 0x12835b0145706fbe + .xword 0x243185be4ee4b28c + .xword 0x550c7dc3d5ffb4e2 + .xword 0x72be5d74f27b896f + .xword 0x80deb1fe3b1696b1 + .xword 0x9bdc06a725c71235 + .xword 0xc19bf174cf692694 + .xword 0xe49b69c19ef14ad2 + .xword 0xefbe4786384f25e3 + .xword 0xfc19dc68b8cd5b5 + .xword 0x240ca1cc77ac9c65 + .xword 0x2de92c6f592b0275 + .xword 0x4a7484aa6ea6e483 + .xword 0x5cb0a9dcbd41fbd4 + .xword 0x76f988da831153b5 + .xword 0x983e5152ee66dfab + .xword 0xa831c66d2db43210 + .xword 0xb00327c898fb213f + .xword 0xbf597fc7beef0ee4 + .xword 0xc6e00bf33da88fc2 + .xword 0xd5a79147930aa725 + .xword 0x6ca6351e003826f + .xword 0x142929670a0e6e70 + .xword 0x27b70a8546d22ffc + .xword 0x2e1b21385c26c926 + .xword 0x4d2c6dfc5ac42aed + .xword 0x53380d139d95b3df + .xword 0x650a73548baf63de + .xword 0x766a0abb3c77b2a8 + .xword 0x81c2c92e47edaee6 + .xword 0x92722c851482353b + .xword 0xa2bfe8a14cf10364 + .xword 0xa81a664bbc423001 + .xword 0xc24b8b70d0f89791 + .xword 0xc76c51a30654be30 + .xword 0xd192e819d6ef5218 + .xword 0xd69906245565a910 + .xword 0xf40e35855771202a + .xword 0x106aa07032bbd1b8 + .xword 0x19a4c116b8d2d0c8 + .xword 0x1e376c085141ab53 + .xword 0x2748774cdf8eeb99 + .xword 0x34b0bcb5e19b48a8 + .xword 0x391c0cb3c5c95a63 + .xword 0x4ed8aa4ae3418acb + .xword 0x5b9cca4f7763e373 + .xword 0x682e6ff3d6b2b8a3 + .xword 0x748f82ee5defb2fc + .xword 0x78a5636f43172f60 + .xword 0x84c87814a1f0ab72 + .xword 0x8cc702081a6439ec + .xword 0x90befffa23631e28 + .xword 0xa4506cebde82bde9 + .xword 0xbef9a3f7b2c67915 + .xword 0xc67178f2e372532b + .xword 0xca273eceea26619c + .xword 0xd186b8c721c0c207 + .xword 0xeada7dd6cde0eb1e + .xword 0xf57d4f7fee6ed178 + .xword 0x6f067aa72176fba + .xword 0xa637dc5a2c898a6 + .xword 0x113f9804bef90dae + .xword 0x1b710b35131c471b + .xword 0x28db77f523047d84 + .xword 0x32caab7b40c72493 + .xword 0x3c9ebe0a15c9bebc + .xword 0x431d67c49c100d4c + .xword 0x4cc5d4becb3e42b6 + .xword 0x597f299cfc657e2a + .xword 0x5fcb6fab3ad6faec + .xword 0x6c44198c4a475817 + .text + .section .rodata + .type L_SHA512_transform_neon_len_ror8, %object + .size L_SHA512_transform_neon_len_ror8, 16 + .align 4 +L_SHA512_transform_neon_len_ror8: + .xword 0x7060504030201, 0x80f0e0d0c0b0a09 + .text + .align 2 + .globl Transform_Sha512_Len + .type Transform_Sha512_Len, %function +Transform_Sha512_Len: + stp x29, x30, [sp, #-128]! + add x29, sp, #0 + str x17, [x29, #16] + str x19, [x29, #24] + stp x20, x21, [x29, #32] + stp x22, x23, [x29, #48] + stp x24, x25, [x29, #64] + stp x26, x27, [x29, #80] + stp d8, d9, [x29, #96] + stp d10, d11, [x29, #112] + adr x3, L_SHA512_transform_neon_len_k + adr x27, L_SHA512_transform_neon_len_ror8 + ld1 {v11.16b}, [x27] + # Load digest into working vars + ldp x4, x5, [x0] + ldp x6, x7, [x0, #16] + ldp x8, x9, [x0, #32] + ldp x10, x11, [x0, #48] + # Start of loop processing a block +L_sha512_len_neon_begin: + # Load W + # Copy digest to add in at end + ld1 {v0.2d, v1.2d, v2.2d, v3.2d}, [x1], #0x40 + mov x19, x4 + ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [x1], #0x40 + mov x20, x5 + rev64 v0.16b, v0.16b + mov x21, x6 + rev64 v1.16b, v1.16b + mov x22, x7 + rev64 v2.16b, v2.16b + mov x23, x8 + rev64 v3.16b, v3.16b + mov x24, x9 + rev64 v4.16b, v4.16b + mov x25, x10 + rev64 v5.16b, v5.16b + mov x26, x11 + rev64 v6.16b, v6.16b + rev64 v7.16b, v7.16b + # Pre-calc: b ^ c + eor x16, x5, x6 + mov x27, #4 + # Start of 16 rounds +L_sha512_len_neon_start: + # Round 0 + mov x13, v0.d[0] + ldr x15, [x3], #8 + ror x12, x8, #14 + ror x14, x4, #28 + eor x12, x12, x8, ror 18 + eor x14, x14, x4, ror 34 + eor x12, x12, x8, ror 41 + eor x14, x14, x4, ror 39 + add x11, x11, x12 + eor x17, x4, x5 + eor x12, x9, x10 + and x16, x17, x16 + and x12, x12, x8 + add x11, x11, x13 + eor x12, x12, x10 + add x11, x11, x15 + eor x16, x16, x5 + add x11, x11, x12 + add x14, x14, x16 + add x7, x7, x11 + add x11, x11, x14 + # Round 1 + mov x13, v0.d[1] + ldr x15, [x3], #8 + ext v10.16b, v0.16b, v1.16b, #8 + ror x12, x7, #14 + shl v8.2d, v7.2d, #45 + ror x14, x11, #28 + sri v8.2d, v7.2d, #19 + eor x12, x12, x7, ror 18 + shl v9.2d, v7.2d, #3 + eor x14, x14, x11, ror 34 + sri v9.2d, v7.2d, #61 + eor x12, x12, x7, ror 41 + eor v9.16b, v9.16b, v8.16b + eor x14, x14, x11, ror 39 + ushr v8.2d, v7.2d, #6 + add x10, x10, x12 + eor v9.16b, v9.16b, v8.16b + eor x16, x11, x4 + add v0.2d, v0.2d, v9.2d + eor x12, x8, x9 + ext v9.16b, v4.16b, v5.16b, #8 + and x17, x16, x17 + add v0.2d, v0.2d, v9.2d + and x12, x12, x7 + shl v8.2d, v10.2d, #63 + add x10, x10, x13 + sri v8.2d, v10.2d, #1 + eor x12, x12, x9 + tbl v9.16b, {v10.16b}, v11.16b + add x10, x10, x15 + eor v9.16b, v9.16b, v8.16b + eor x17, x17, x4 + ushr v10.2d, v10.2d, #7 + add x10, x10, x12 + eor v9.16b, v9.16b, v10.16b + add x14, x14, x17 + add v0.2d, v0.2d, v9.2d + add x6, x6, x10 + add x10, x10, x14 + # Round 2 + mov x13, v1.d[0] + ldr x15, [x3], #8 + ror x12, x6, #14 + ror x14, x10, #28 + eor x12, x12, x6, ror 18 + eor x14, x14, x10, ror 34 + eor x12, x12, x6, ror 41 + eor x14, x14, x10, ror 39 + add x9, x9, x12 + eor x17, x10, x11 + eor x12, x7, x8 + and x16, x17, x16 + and x12, x12, x6 + add x9, x9, x13 + eor x12, x12, x8 + add x9, x9, x15 + eor x16, x16, x11 + add x9, x9, x12 + add x14, x14, x16 + add x5, x5, x9 + add x9, x9, x14 + # Round 3 + mov x13, v1.d[1] + ldr x15, [x3], #8 + ext v10.16b, v1.16b, v2.16b, #8 + ror x12, x5, #14 + shl v8.2d, v0.2d, #45 + ror x14, x9, #28 + sri v8.2d, v0.2d, #19 + eor x12, x12, x5, ror 18 + shl v9.2d, v0.2d, #3 + eor x14, x14, x9, ror 34 + sri v9.2d, v0.2d, #61 + eor x12, x12, x5, ror 41 + eor v9.16b, v9.16b, v8.16b + eor x14, x14, x9, ror 39 + ushr v8.2d, v0.2d, #6 + add x8, x8, x12 + eor v9.16b, v9.16b, v8.16b + eor x16, x9, x10 + add v1.2d, v1.2d, v9.2d + eor x12, x6, x7 + ext v9.16b, v5.16b, v6.16b, #8 + and x17, x16, x17 + add v1.2d, v1.2d, v9.2d + and x12, x12, x5 + shl v8.2d, v10.2d, #63 + add x8, x8, x13 + sri v8.2d, v10.2d, #1 + eor x12, x12, x7 + tbl v9.16b, {v10.16b}, v11.16b + add x8, x8, x15 + eor v9.16b, v9.16b, v8.16b + eor x17, x17, x10 + ushr v10.2d, v10.2d, #7 + add x8, x8, x12 + eor v9.16b, v9.16b, v10.16b + add x14, x14, x17 + add v1.2d, v1.2d, v9.2d + add x4, x4, x8 + add x8, x8, x14 + # Round 4 + mov x13, v2.d[0] + ldr x15, [x3], #8 + ror x12, x4, #14 + ror x14, x8, #28 + eor x12, x12, x4, ror 18 + eor x14, x14, x8, ror 34 + eor x12, x12, x4, ror 41 + eor x14, x14, x8, ror 39 + add x7, x7, x12 + eor x17, x8, x9 + eor x12, x5, x6 + and x16, x17, x16 + and x12, x12, x4 + add x7, x7, x13 + eor x12, x12, x6 + add x7, x7, x15 + eor x16, x16, x9 + add x7, x7, x12 + add x14, x14, x16 + add x11, x11, x7 + add x7, x7, x14 + # Round 5 + mov x13, v2.d[1] + ldr x15, [x3], #8 + ext v10.16b, v2.16b, v3.16b, #8 + ror x12, x11, #14 + shl v8.2d, v1.2d, #45 + ror x14, x7, #28 + sri v8.2d, v1.2d, #19 + eor x12, x12, x11, ror 18 + shl v9.2d, v1.2d, #3 + eor x14, x14, x7, ror 34 + sri v9.2d, v1.2d, #61 + eor x12, x12, x11, ror 41 + eor v9.16b, v9.16b, v8.16b + eor x14, x14, x7, ror 39 + ushr v8.2d, v1.2d, #6 + add x6, x6, x12 + eor v9.16b, v9.16b, v8.16b + eor x16, x7, x8 + add v2.2d, v2.2d, v9.2d + eor x12, x4, x5 + ext v9.16b, v6.16b, v7.16b, #8 + and x17, x16, x17 + add v2.2d, v2.2d, v9.2d + and x12, x12, x11 + shl v8.2d, v10.2d, #63 + add x6, x6, x13 + sri v8.2d, v10.2d, #1 + eor x12, x12, x5 + tbl v9.16b, {v10.16b}, v11.16b + add x6, x6, x15 + eor v9.16b, v9.16b, v8.16b + eor x17, x17, x8 + ushr v10.2d, v10.2d, #7 + add x6, x6, x12 + eor v9.16b, v9.16b, v10.16b + add x14, x14, x17 + add v2.2d, v2.2d, v9.2d + add x10, x10, x6 + add x6, x6, x14 + # Round 6 + mov x13, v3.d[0] + ldr x15, [x3], #8 + ror x12, x10, #14 + ror x14, x6, #28 + eor x12, x12, x10, ror 18 + eor x14, x14, x6, ror 34 + eor x12, x12, x10, ror 41 + eor x14, x14, x6, ror 39 + add x5, x5, x12 + eor x17, x6, x7 + eor x12, x11, x4 + and x16, x17, x16 + and x12, x12, x10 + add x5, x5, x13 + eor x12, x12, x4 + add x5, x5, x15 + eor x16, x16, x7 + add x5, x5, x12 + add x14, x14, x16 + add x9, x9, x5 + add x5, x5, x14 + # Round 7 + mov x13, v3.d[1] + ldr x15, [x3], #8 + ext v10.16b, v3.16b, v4.16b, #8 + ror x12, x9, #14 + shl v8.2d, v2.2d, #45 + ror x14, x5, #28 + sri v8.2d, v2.2d, #19 + eor x12, x12, x9, ror 18 + shl v9.2d, v2.2d, #3 + eor x14, x14, x5, ror 34 + sri v9.2d, v2.2d, #61 + eor x12, x12, x9, ror 41 + eor v9.16b, v9.16b, v8.16b + eor x14, x14, x5, ror 39 + ushr v8.2d, v2.2d, #6 + add x4, x4, x12 + eor v9.16b, v9.16b, v8.16b + eor x16, x5, x6 + add v3.2d, v3.2d, v9.2d + eor x12, x10, x11 + ext v9.16b, v7.16b, v0.16b, #8 + and x17, x16, x17 + add v3.2d, v3.2d, v9.2d + and x12, x12, x9 + shl v8.2d, v10.2d, #63 + add x4, x4, x13 + sri v8.2d, v10.2d, #1 + eor x12, x12, x11 + tbl v9.16b, {v10.16b}, v11.16b + add x4, x4, x15 + eor v9.16b, v9.16b, v8.16b + eor x17, x17, x6 + ushr v10.2d, v10.2d, #7 + add x4, x4, x12 + eor v9.16b, v9.16b, v10.16b + add x14, x14, x17 + add v3.2d, v3.2d, v9.2d + add x8, x8, x4 + add x4, x4, x14 + # Round 8 + mov x13, v4.d[0] + ldr x15, [x3], #8 + ror x12, x8, #14 + ror x14, x4, #28 + eor x12, x12, x8, ror 18 + eor x14, x14, x4, ror 34 + eor x12, x12, x8, ror 41 + eor x14, x14, x4, ror 39 + add x11, x11, x12 + eor x17, x4, x5 + eor x12, x9, x10 + and x16, x17, x16 + and x12, x12, x8 + add x11, x11, x13 + eor x12, x12, x10 + add x11, x11, x15 + eor x16, x16, x5 + add x11, x11, x12 + add x14, x14, x16 + add x7, x7, x11 + add x11, x11, x14 + # Round 9 + mov x13, v4.d[1] + ldr x15, [x3], #8 + ext v10.16b, v4.16b, v5.16b, #8 + ror x12, x7, #14 + shl v8.2d, v3.2d, #45 + ror x14, x11, #28 + sri v8.2d, v3.2d, #19 + eor x12, x12, x7, ror 18 + shl v9.2d, v3.2d, #3 + eor x14, x14, x11, ror 34 + sri v9.2d, v3.2d, #61 + eor x12, x12, x7, ror 41 + eor v9.16b, v9.16b, v8.16b + eor x14, x14, x11, ror 39 + ushr v8.2d, v3.2d, #6 + add x10, x10, x12 + eor v9.16b, v9.16b, v8.16b + eor x16, x11, x4 + add v4.2d, v4.2d, v9.2d + eor x12, x8, x9 + ext v9.16b, v0.16b, v1.16b, #8 + and x17, x16, x17 + add v4.2d, v4.2d, v9.2d + and x12, x12, x7 + shl v8.2d, v10.2d, #63 + add x10, x10, x13 + sri v8.2d, v10.2d, #1 + eor x12, x12, x9 + tbl v9.16b, {v10.16b}, v11.16b + add x10, x10, x15 + eor v9.16b, v9.16b, v8.16b + eor x17, x17, x4 + ushr v10.2d, v10.2d, #7 + add x10, x10, x12 + eor v9.16b, v9.16b, v10.16b + add x14, x14, x17 + add v4.2d, v4.2d, v9.2d + add x6, x6, x10 + add x10, x10, x14 + # Round 10 + mov x13, v5.d[0] + ldr x15, [x3], #8 + ror x12, x6, #14 + ror x14, x10, #28 + eor x12, x12, x6, ror 18 + eor x14, x14, x10, ror 34 + eor x12, x12, x6, ror 41 + eor x14, x14, x10, ror 39 + add x9, x9, x12 + eor x17, x10, x11 + eor x12, x7, x8 + and x16, x17, x16 + and x12, x12, x6 + add x9, x9, x13 + eor x12, x12, x8 + add x9, x9, x15 + eor x16, x16, x11 + add x9, x9, x12 + add x14, x14, x16 + add x5, x5, x9 + add x9, x9, x14 + # Round 11 + mov x13, v5.d[1] + ldr x15, [x3], #8 + ext v10.16b, v5.16b, v6.16b, #8 + ror x12, x5, #14 + shl v8.2d, v4.2d, #45 + ror x14, x9, #28 + sri v8.2d, v4.2d, #19 + eor x12, x12, x5, ror 18 + shl v9.2d, v4.2d, #3 + eor x14, x14, x9, ror 34 + sri v9.2d, v4.2d, #61 + eor x12, x12, x5, ror 41 + eor v9.16b, v9.16b, v8.16b + eor x14, x14, x9, ror 39 + ushr v8.2d, v4.2d, #6 + add x8, x8, x12 + eor v9.16b, v9.16b, v8.16b + eor x16, x9, x10 + add v5.2d, v5.2d, v9.2d + eor x12, x6, x7 + ext v9.16b, v1.16b, v2.16b, #8 + and x17, x16, x17 + add v5.2d, v5.2d, v9.2d + and x12, x12, x5 + shl v8.2d, v10.2d, #63 + add x8, x8, x13 + sri v8.2d, v10.2d, #1 + eor x12, x12, x7 + tbl v9.16b, {v10.16b}, v11.16b + add x8, x8, x15 + eor v9.16b, v9.16b, v8.16b + eor x17, x17, x10 + ushr v10.2d, v10.2d, #7 + add x8, x8, x12 + eor v9.16b, v9.16b, v10.16b + add x14, x14, x17 + add v5.2d, v5.2d, v9.2d + add x4, x4, x8 + add x8, x8, x14 + # Round 12 + mov x13, v6.d[0] + ldr x15, [x3], #8 + ror x12, x4, #14 + ror x14, x8, #28 + eor x12, x12, x4, ror 18 + eor x14, x14, x8, ror 34 + eor x12, x12, x4, ror 41 + eor x14, x14, x8, ror 39 + add x7, x7, x12 + eor x17, x8, x9 + eor x12, x5, x6 + and x16, x17, x16 + and x12, x12, x4 + add x7, x7, x13 + eor x12, x12, x6 + add x7, x7, x15 + eor x16, x16, x9 + add x7, x7, x12 + add x14, x14, x16 + add x11, x11, x7 + add x7, x7, x14 + # Round 13 + mov x13, v6.d[1] + ldr x15, [x3], #8 + ext v10.16b, v6.16b, v7.16b, #8 + ror x12, x11, #14 + shl v8.2d, v5.2d, #45 + ror x14, x7, #28 + sri v8.2d, v5.2d, #19 + eor x12, x12, x11, ror 18 + shl v9.2d, v5.2d, #3 + eor x14, x14, x7, ror 34 + sri v9.2d, v5.2d, #61 + eor x12, x12, x11, ror 41 + eor v9.16b, v9.16b, v8.16b + eor x14, x14, x7, ror 39 + ushr v8.2d, v5.2d, #6 + add x6, x6, x12 + eor v9.16b, v9.16b, v8.16b + eor x16, x7, x8 + add v6.2d, v6.2d, v9.2d + eor x12, x4, x5 + ext v9.16b, v2.16b, v3.16b, #8 + and x17, x16, x17 + add v6.2d, v6.2d, v9.2d + and x12, x12, x11 + shl v8.2d, v10.2d, #63 + add x6, x6, x13 + sri v8.2d, v10.2d, #1 + eor x12, x12, x5 + tbl v9.16b, {v10.16b}, v11.16b + add x6, x6, x15 + eor v9.16b, v9.16b, v8.16b + eor x17, x17, x8 + ushr v10.2d, v10.2d, #7 + add x6, x6, x12 + eor v9.16b, v9.16b, v10.16b + add x14, x14, x17 + add v6.2d, v6.2d, v9.2d + add x10, x10, x6 + add x6, x6, x14 + # Round 14 + mov x13, v7.d[0] + ldr x15, [x3], #8 + ror x12, x10, #14 + ror x14, x6, #28 + eor x12, x12, x10, ror 18 + eor x14, x14, x6, ror 34 + eor x12, x12, x10, ror 41 + eor x14, x14, x6, ror 39 + add x5, x5, x12 + eor x17, x6, x7 + eor x12, x11, x4 + and x16, x17, x16 + and x12, x12, x10 + add x5, x5, x13 + eor x12, x12, x4 + add x5, x5, x15 + eor x16, x16, x7 + add x5, x5, x12 + add x14, x14, x16 + add x9, x9, x5 + add x5, x5, x14 + # Round 15 + mov x13, v7.d[1] + ldr x15, [x3], #8 + ext v10.16b, v7.16b, v0.16b, #8 + ror x12, x9, #14 + shl v8.2d, v6.2d, #45 + ror x14, x5, #28 + sri v8.2d, v6.2d, #19 + eor x12, x12, x9, ror 18 + shl v9.2d, v6.2d, #3 + eor x14, x14, x5, ror 34 + sri v9.2d, v6.2d, #61 + eor x12, x12, x9, ror 41 + eor v9.16b, v9.16b, v8.16b + eor x14, x14, x5, ror 39 + ushr v8.2d, v6.2d, #6 + add x4, x4, x12 + eor v9.16b, v9.16b, v8.16b + eor x16, x5, x6 + add v7.2d, v7.2d, v9.2d + eor x12, x10, x11 + ext v9.16b, v3.16b, v4.16b, #8 + and x17, x16, x17 + add v7.2d, v7.2d, v9.2d + and x12, x12, x9 + shl v8.2d, v10.2d, #63 + add x4, x4, x13 + sri v8.2d, v10.2d, #1 + eor x12, x12, x11 + tbl v9.16b, {v10.16b}, v11.16b + add x4, x4, x15 + eor v9.16b, v9.16b, v8.16b + eor x17, x17, x6 + ushr v10.2d, v10.2d, #7 + add x4, x4, x12 + eor v9.16b, v9.16b, v10.16b + add x14, x14, x17 + add v7.2d, v7.2d, v9.2d + add x8, x8, x4 + add x4, x4, x14 + subs x27, x27, #1 + bne L_sha512_len_neon_start + # Round 0 + mov x13, v0.d[0] + ldr x15, [x3], #8 + ror x12, x8, #14 + ror x14, x4, #28 + eor x12, x12, x8, ror 18 + eor x14, x14, x4, ror 34 + eor x12, x12, x8, ror 41 + eor x14, x14, x4, ror 39 + add x11, x11, x12 + eor x17, x4, x5 + eor x12, x9, x10 + and x16, x17, x16 + and x12, x12, x8 + add x11, x11, x13 + eor x12, x12, x10 + add x11, x11, x15 + eor x16, x16, x5 + add x11, x11, x12 + add x14, x14, x16 + add x7, x7, x11 + add x11, x11, x14 + # Round 1 + mov x13, v0.d[1] + ldr x15, [x3], #8 + ror x12, x7, #14 + ror x14, x11, #28 + eor x12, x12, x7, ror 18 + eor x14, x14, x11, ror 34 + eor x12, x12, x7, ror 41 + eor x14, x14, x11, ror 39 + add x10, x10, x12 + eor x16, x11, x4 + eor x12, x8, x9 + and x17, x16, x17 + and x12, x12, x7 + add x10, x10, x13 + eor x12, x12, x9 + add x10, x10, x15 + eor x17, x17, x4 + add x10, x10, x12 + add x14, x14, x17 + add x6, x6, x10 + add x10, x10, x14 + # Round 2 + mov x13, v1.d[0] + ldr x15, [x3], #8 + ror x12, x6, #14 + ror x14, x10, #28 + eor x12, x12, x6, ror 18 + eor x14, x14, x10, ror 34 + eor x12, x12, x6, ror 41 + eor x14, x14, x10, ror 39 + add x9, x9, x12 + eor x17, x10, x11 + eor x12, x7, x8 + and x16, x17, x16 + and x12, x12, x6 + add x9, x9, x13 + eor x12, x12, x8 + add x9, x9, x15 + eor x16, x16, x11 + add x9, x9, x12 + add x14, x14, x16 + add x5, x5, x9 + add x9, x9, x14 + # Round 3 + mov x13, v1.d[1] + ldr x15, [x3], #8 + ror x12, x5, #14 + ror x14, x9, #28 + eor x12, x12, x5, ror 18 + eor x14, x14, x9, ror 34 + eor x12, x12, x5, ror 41 + eor x14, x14, x9, ror 39 + add x8, x8, x12 + eor x16, x9, x10 + eor x12, x6, x7 + and x17, x16, x17 + and x12, x12, x5 + add x8, x8, x13 + eor x12, x12, x7 + add x8, x8, x15 + eor x17, x17, x10 + add x8, x8, x12 + add x14, x14, x17 + add x4, x4, x8 + add x8, x8, x14 + # Round 4 + mov x13, v2.d[0] + ldr x15, [x3], #8 + ror x12, x4, #14 + ror x14, x8, #28 + eor x12, x12, x4, ror 18 + eor x14, x14, x8, ror 34 + eor x12, x12, x4, ror 41 + eor x14, x14, x8, ror 39 + add x7, x7, x12 + eor x17, x8, x9 + eor x12, x5, x6 + and x16, x17, x16 + and x12, x12, x4 + add x7, x7, x13 + eor x12, x12, x6 + add x7, x7, x15 + eor x16, x16, x9 + add x7, x7, x12 + add x14, x14, x16 + add x11, x11, x7 + add x7, x7, x14 + # Round 5 + mov x13, v2.d[1] + ldr x15, [x3], #8 + ror x12, x11, #14 + ror x14, x7, #28 + eor x12, x12, x11, ror 18 + eor x14, x14, x7, ror 34 + eor x12, x12, x11, ror 41 + eor x14, x14, x7, ror 39 + add x6, x6, x12 + eor x16, x7, x8 + eor x12, x4, x5 + and x17, x16, x17 + and x12, x12, x11 + add x6, x6, x13 + eor x12, x12, x5 + add x6, x6, x15 + eor x17, x17, x8 + add x6, x6, x12 + add x14, x14, x17 + add x10, x10, x6 + add x6, x6, x14 + # Round 6 + mov x13, v3.d[0] + ldr x15, [x3], #8 + ror x12, x10, #14 + ror x14, x6, #28 + eor x12, x12, x10, ror 18 + eor x14, x14, x6, ror 34 + eor x12, x12, x10, ror 41 + eor x14, x14, x6, ror 39 + add x5, x5, x12 + eor x17, x6, x7 + eor x12, x11, x4 + and x16, x17, x16 + and x12, x12, x10 + add x5, x5, x13 + eor x12, x12, x4 + add x5, x5, x15 + eor x16, x16, x7 + add x5, x5, x12 + add x14, x14, x16 + add x9, x9, x5 + add x5, x5, x14 + # Round 7 + mov x13, v3.d[1] + ldr x15, [x3], #8 + ror x12, x9, #14 + ror x14, x5, #28 + eor x12, x12, x9, ror 18 + eor x14, x14, x5, ror 34 + eor x12, x12, x9, ror 41 + eor x14, x14, x5, ror 39 + add x4, x4, x12 + eor x16, x5, x6 + eor x12, x10, x11 + and x17, x16, x17 + and x12, x12, x9 + add x4, x4, x13 + eor x12, x12, x11 + add x4, x4, x15 + eor x17, x17, x6 + add x4, x4, x12 + add x14, x14, x17 + add x8, x8, x4 + add x4, x4, x14 + # Round 8 + mov x13, v4.d[0] + ldr x15, [x3], #8 + ror x12, x8, #14 + ror x14, x4, #28 + eor x12, x12, x8, ror 18 + eor x14, x14, x4, ror 34 + eor x12, x12, x8, ror 41 + eor x14, x14, x4, ror 39 + add x11, x11, x12 + eor x17, x4, x5 + eor x12, x9, x10 + and x16, x17, x16 + and x12, x12, x8 + add x11, x11, x13 + eor x12, x12, x10 + add x11, x11, x15 + eor x16, x16, x5 + add x11, x11, x12 + add x14, x14, x16 + add x7, x7, x11 + add x11, x11, x14 + # Round 9 + mov x13, v4.d[1] + ldr x15, [x3], #8 + ror x12, x7, #14 + ror x14, x11, #28 + eor x12, x12, x7, ror 18 + eor x14, x14, x11, ror 34 + eor x12, x12, x7, ror 41 + eor x14, x14, x11, ror 39 + add x10, x10, x12 + eor x16, x11, x4 + eor x12, x8, x9 + and x17, x16, x17 + and x12, x12, x7 + add x10, x10, x13 + eor x12, x12, x9 + add x10, x10, x15 + eor x17, x17, x4 + add x10, x10, x12 + add x14, x14, x17 + add x6, x6, x10 + add x10, x10, x14 + # Round 10 + mov x13, v5.d[0] + ldr x15, [x3], #8 + ror x12, x6, #14 + ror x14, x10, #28 + eor x12, x12, x6, ror 18 + eor x14, x14, x10, ror 34 + eor x12, x12, x6, ror 41 + eor x14, x14, x10, ror 39 + add x9, x9, x12 + eor x17, x10, x11 + eor x12, x7, x8 + and x16, x17, x16 + and x12, x12, x6 + add x9, x9, x13 + eor x12, x12, x8 + add x9, x9, x15 + eor x16, x16, x11 + add x9, x9, x12 + add x14, x14, x16 + add x5, x5, x9 + add x9, x9, x14 + # Round 11 + mov x13, v5.d[1] + ldr x15, [x3], #8 + ror x12, x5, #14 + ror x14, x9, #28 + eor x12, x12, x5, ror 18 + eor x14, x14, x9, ror 34 + eor x12, x12, x5, ror 41 + eor x14, x14, x9, ror 39 + add x8, x8, x12 + eor x16, x9, x10 + eor x12, x6, x7 + and x17, x16, x17 + and x12, x12, x5 + add x8, x8, x13 + eor x12, x12, x7 + add x8, x8, x15 + eor x17, x17, x10 + add x8, x8, x12 + add x14, x14, x17 + add x4, x4, x8 + add x8, x8, x14 + # Round 12 + mov x13, v6.d[0] + ldr x15, [x3], #8 + ror x12, x4, #14 + ror x14, x8, #28 + eor x12, x12, x4, ror 18 + eor x14, x14, x8, ror 34 + eor x12, x12, x4, ror 41 + eor x14, x14, x8, ror 39 + add x7, x7, x12 + eor x17, x8, x9 + eor x12, x5, x6 + and x16, x17, x16 + and x12, x12, x4 + add x7, x7, x13 + eor x12, x12, x6 + add x7, x7, x15 + eor x16, x16, x9 + add x7, x7, x12 + add x14, x14, x16 + add x11, x11, x7 + add x7, x7, x14 + # Round 13 + mov x13, v6.d[1] + ldr x15, [x3], #8 + ror x12, x11, #14 + ror x14, x7, #28 + eor x12, x12, x11, ror 18 + eor x14, x14, x7, ror 34 + eor x12, x12, x11, ror 41 + eor x14, x14, x7, ror 39 + add x6, x6, x12 + eor x16, x7, x8 + eor x12, x4, x5 + and x17, x16, x17 + and x12, x12, x11 + add x6, x6, x13 + eor x12, x12, x5 + add x6, x6, x15 + eor x17, x17, x8 + add x6, x6, x12 + add x14, x14, x17 + add x10, x10, x6 + add x6, x6, x14 + # Round 14 + mov x13, v7.d[0] + ldr x15, [x3], #8 + ror x12, x10, #14 + ror x14, x6, #28 + eor x12, x12, x10, ror 18 + eor x14, x14, x6, ror 34 + eor x12, x12, x10, ror 41 + eor x14, x14, x6, ror 39 + add x5, x5, x12 + eor x17, x6, x7 + eor x12, x11, x4 + and x16, x17, x16 + and x12, x12, x10 + add x5, x5, x13 + eor x12, x12, x4 + add x5, x5, x15 + eor x16, x16, x7 + add x5, x5, x12 + add x14, x14, x16 + add x9, x9, x5 + add x5, x5, x14 + # Round 15 + mov x13, v7.d[1] + ldr x15, [x3], #8 + ror x12, x9, #14 + ror x14, x5, #28 + eor x12, x12, x9, ror 18 + eor x14, x14, x5, ror 34 + eor x12, x12, x9, ror 41 + eor x14, x14, x5, ror 39 + add x4, x4, x12 + eor x16, x5, x6 + eor x12, x10, x11 + and x17, x16, x17 + and x12, x12, x9 + add x4, x4, x13 + eor x12, x12, x11 + add x4, x4, x15 + eor x17, x17, x6 + add x4, x4, x12 + add x14, x14, x17 + add x8, x8, x4 + add x4, x4, x14 + add x11, x11, x26 + add x10, x10, x25 + add x9, x9, x24 + add x8, x8, x23 + add x7, x7, x22 + add x6, x6, x21 + add x5, x5, x20 + add x4, x4, x19 + adr x3, L_SHA512_transform_neon_len_k + subs w2, w2, #0x80 + bne L_sha512_len_neon_begin + stp x4, x5, [x0] + stp x6, x7, [x0, #16] + stp x8, x9, [x0, #32] + stp x10, x11, [x0, #48] + ldr x17, [x29, #16] + ldr x19, [x29, #24] + ldp x20, x21, [x29, #32] + ldp x22, x23, [x29, #48] + ldp x24, x25, [x29, #64] + ldp x26, x27, [x29, #80] + ldp d8, d9, [x29, #96] + ldp d10, d11, [x29, #112] + ldp x29, x30, [sp], #0x80 + ret + .size Transform_Sha512_Len,.-Transform_Sha512_Len +#endif /* __aarch64__ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha512-asm.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha512-asm.c new file mode 100644 index 000000000..d323598dd --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha512-asm.c @@ -0,0 +1,1041 @@ +/* armv8-sha512-asm + * + * Copyright (C) 2006-2020 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 + */ + +/* Generated using (from wolfssl): + * cd ../scripts + * ruby ./sha2/sha512.rb arm64 ../wolfssl/wolfcrypt/src/port/arm/armv8-sha512-asm.c + */ +#ifdef __aarch64__ +#include + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_ARMASM +#include + +static const uint64_t L_SHA512_transform_neon_len_k[] = { + 0x428a2f98d728ae22UL, + 0x7137449123ef65cdUL, + 0xb5c0fbcfec4d3b2fUL, + 0xe9b5dba58189dbbcUL, + 0x3956c25bf348b538UL, + 0x59f111f1b605d019UL, + 0x923f82a4af194f9bUL, + 0xab1c5ed5da6d8118UL, + 0xd807aa98a3030242UL, + 0x12835b0145706fbeUL, + 0x243185be4ee4b28cUL, + 0x550c7dc3d5ffb4e2UL, + 0x72be5d74f27b896fUL, + 0x80deb1fe3b1696b1UL, + 0x9bdc06a725c71235UL, + 0xc19bf174cf692694UL, + 0xe49b69c19ef14ad2UL, + 0xefbe4786384f25e3UL, + 0xfc19dc68b8cd5b5UL, + 0x240ca1cc77ac9c65UL, + 0x2de92c6f592b0275UL, + 0x4a7484aa6ea6e483UL, + 0x5cb0a9dcbd41fbd4UL, + 0x76f988da831153b5UL, + 0x983e5152ee66dfabUL, + 0xa831c66d2db43210UL, + 0xb00327c898fb213fUL, + 0xbf597fc7beef0ee4UL, + 0xc6e00bf33da88fc2UL, + 0xd5a79147930aa725UL, + 0x6ca6351e003826fUL, + 0x142929670a0e6e70UL, + 0x27b70a8546d22ffcUL, + 0x2e1b21385c26c926UL, + 0x4d2c6dfc5ac42aedUL, + 0x53380d139d95b3dfUL, + 0x650a73548baf63deUL, + 0x766a0abb3c77b2a8UL, + 0x81c2c92e47edaee6UL, + 0x92722c851482353bUL, + 0xa2bfe8a14cf10364UL, + 0xa81a664bbc423001UL, + 0xc24b8b70d0f89791UL, + 0xc76c51a30654be30UL, + 0xd192e819d6ef5218UL, + 0xd69906245565a910UL, + 0xf40e35855771202aUL, + 0x106aa07032bbd1b8UL, + 0x19a4c116b8d2d0c8UL, + 0x1e376c085141ab53UL, + 0x2748774cdf8eeb99UL, + 0x34b0bcb5e19b48a8UL, + 0x391c0cb3c5c95a63UL, + 0x4ed8aa4ae3418acbUL, + 0x5b9cca4f7763e373UL, + 0x682e6ff3d6b2b8a3UL, + 0x748f82ee5defb2fcUL, + 0x78a5636f43172f60UL, + 0x84c87814a1f0ab72UL, + 0x8cc702081a6439ecUL, + 0x90befffa23631e28UL, + 0xa4506cebde82bde9UL, + 0xbef9a3f7b2c67915UL, + 0xc67178f2e372532bUL, + 0xca273eceea26619cUL, + 0xd186b8c721c0c207UL, + 0xeada7dd6cde0eb1eUL, + 0xf57d4f7fee6ed178UL, + 0x6f067aa72176fbaUL, + 0xa637dc5a2c898a6UL, + 0x113f9804bef90daeUL, + 0x1b710b35131c471bUL, + 0x28db77f523047d84UL, + 0x32caab7b40c72493UL, + 0x3c9ebe0a15c9bebcUL, + 0x431d67c49c100d4cUL, + 0x4cc5d4becb3e42b6UL, + 0x597f299cfc657e2aUL, + 0x5fcb6fab3ad6faecUL, + 0x6c44198c4a475817UL, +}; + +static const uint64_t L_SHA512_transform_neon_len_ror8[] = { + 0x7060504030201UL, + 0x80f0e0d0c0b0a09UL, +}; + +void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, word32 len) +{ + __asm__ __volatile__ ( + "stp x29, x30, [sp, #-16]!\n\t" + "add x29, sp, #0\n\t" + "adr x3, %[L_SHA512_transform_neon_len_k]\n\t" + "adr x27, %[L_SHA512_transform_neon_len_ror8]\n\t" + "ld1 {v11.16b}, [x27]\n\t" + /* Load digest into working vars */ + "ldp x4, x5, [%x[sha512]]\n\t" + "ldp x6, x7, [%x[sha512], #16]\n\t" + "ldp x8, x9, [%x[sha512], #32]\n\t" + "ldp x10, x11, [%x[sha512], #48]\n\t" + /* Start of loop processing a block */ + "\n" + "L_sha512_len_neon_begin_%=: \n\t" + /* Load W */ + /* Copy digest to add in at end */ + "ld1 {v0.2d, v1.2d, v2.2d, v3.2d}, [%x[data]], #0x40\n\t" + "mov x19, x4\n\t" + "ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [%x[data]], #0x40\n\t" + "mov x20, x5\n\t" + "rev64 v0.16b, v0.16b\n\t" + "mov x21, x6\n\t" + "rev64 v1.16b, v1.16b\n\t" + "mov x22, x7\n\t" + "rev64 v2.16b, v2.16b\n\t" + "mov x23, x8\n\t" + "rev64 v3.16b, v3.16b\n\t" + "mov x24, x9\n\t" + "rev64 v4.16b, v4.16b\n\t" + "mov x25, x10\n\t" + "rev64 v5.16b, v5.16b\n\t" + "mov x26, x11\n\t" + "rev64 v6.16b, v6.16b\n\t" + "rev64 v7.16b, v7.16b\n\t" + /* Pre-calc: b ^ c */ + "eor x16, x5, x6\n\t" + "mov x27, #4\n\t" + /* Start of 16 rounds */ + "\n" + "L_sha512_len_neon_start_%=: \n\t" + /* Round 0 */ + "mov x13, v0.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x8, #14\n\t" + "ror x14, x4, #28\n\t" + "eor x12, x12, x8, ror 18\n\t" + "eor x14, x14, x4, ror 34\n\t" + "eor x12, x12, x8, ror 41\n\t" + "eor x14, x14, x4, ror 39\n\t" + "add x11, x11, x12\n\t" + "eor x17, x4, x5\n\t" + "eor x12, x9, x10\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x8\n\t" + "add x11, x11, x13\n\t" + "eor x12, x12, x10\n\t" + "add x11, x11, x15\n\t" + "eor x16, x16, x5\n\t" + "add x11, x11, x12\n\t" + "add x14, x14, x16\n\t" + "add x7, x7, x11\n\t" + "add x11, x11, x14\n\t" + /* Round 1 */ + "mov x13, v0.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ext v10.16b, v0.16b, v1.16b, #8\n\t" + "ror x12, x7, #14\n\t" + "shl v8.2d, v7.2d, #45\n\t" + "ror x14, x11, #28\n\t" + "sri v8.2d, v7.2d, #19\n\t" + "eor x12, x12, x7, ror 18\n\t" + "shl v9.2d, v7.2d, #3\n\t" + "eor x14, x14, x11, ror 34\n\t" + "sri v9.2d, v7.2d, #61\n\t" + "eor x12, x12, x7, ror 41\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x14, x14, x11, ror 39\n\t" + "ushr v8.2d, v7.2d, #6\n\t" + "add x10, x10, x12\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x16, x11, x4\n\t" + "add v0.2d, v0.2d, v9.2d\n\t" + "eor x12, x8, x9\n\t" + "ext v9.16b, v4.16b, v5.16b, #8\n\t" + "and x17, x16, x17\n\t" + "add v0.2d, v0.2d, v9.2d\n\t" + "and x12, x12, x7\n\t" + "shl v8.2d, v10.2d, #63\n\t" + "add x10, x10, x13\n\t" + "sri v8.2d, v10.2d, #1\n\t" + "eor x12, x12, x9\n\t" + "tbl v9.16b, {v10.16b}, v11.16b\n\t" + "add x10, x10, x15\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x17, x17, x4\n\t" + "ushr v10.2d, v10.2d, #7\n\t" + "add x10, x10, x12\n\t" + "eor v9.16b, v9.16b, v10.16b\n\t" + "add x14, x14, x17\n\t" + "add v0.2d, v0.2d, v9.2d\n\t" + "add x6, x6, x10\n\t" + "add x10, x10, x14\n\t" + /* Round 2 */ + "mov x13, v1.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x6, #14\n\t" + "ror x14, x10, #28\n\t" + "eor x12, x12, x6, ror 18\n\t" + "eor x14, x14, x10, ror 34\n\t" + "eor x12, x12, x6, ror 41\n\t" + "eor x14, x14, x10, ror 39\n\t" + "add x9, x9, x12\n\t" + "eor x17, x10, x11\n\t" + "eor x12, x7, x8\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x6\n\t" + "add x9, x9, x13\n\t" + "eor x12, x12, x8\n\t" + "add x9, x9, x15\n\t" + "eor x16, x16, x11\n\t" + "add x9, x9, x12\n\t" + "add x14, x14, x16\n\t" + "add x5, x5, x9\n\t" + "add x9, x9, x14\n\t" + /* Round 3 */ + "mov x13, v1.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ext v10.16b, v1.16b, v2.16b, #8\n\t" + "ror x12, x5, #14\n\t" + "shl v8.2d, v0.2d, #45\n\t" + "ror x14, x9, #28\n\t" + "sri v8.2d, v0.2d, #19\n\t" + "eor x12, x12, x5, ror 18\n\t" + "shl v9.2d, v0.2d, #3\n\t" + "eor x14, x14, x9, ror 34\n\t" + "sri v9.2d, v0.2d, #61\n\t" + "eor x12, x12, x5, ror 41\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x14, x14, x9, ror 39\n\t" + "ushr v8.2d, v0.2d, #6\n\t" + "add x8, x8, x12\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x16, x9, x10\n\t" + "add v1.2d, v1.2d, v9.2d\n\t" + "eor x12, x6, x7\n\t" + "ext v9.16b, v5.16b, v6.16b, #8\n\t" + "and x17, x16, x17\n\t" + "add v1.2d, v1.2d, v9.2d\n\t" + "and x12, x12, x5\n\t" + "shl v8.2d, v10.2d, #63\n\t" + "add x8, x8, x13\n\t" + "sri v8.2d, v10.2d, #1\n\t" + "eor x12, x12, x7\n\t" + "tbl v9.16b, {v10.16b}, v11.16b\n\t" + "add x8, x8, x15\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x17, x17, x10\n\t" + "ushr v10.2d, v10.2d, #7\n\t" + "add x8, x8, x12\n\t" + "eor v9.16b, v9.16b, v10.16b\n\t" + "add x14, x14, x17\n\t" + "add v1.2d, v1.2d, v9.2d\n\t" + "add x4, x4, x8\n\t" + "add x8, x8, x14\n\t" + /* Round 4 */ + "mov x13, v2.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x4, #14\n\t" + "ror x14, x8, #28\n\t" + "eor x12, x12, x4, ror 18\n\t" + "eor x14, x14, x8, ror 34\n\t" + "eor x12, x12, x4, ror 41\n\t" + "eor x14, x14, x8, ror 39\n\t" + "add x7, x7, x12\n\t" + "eor x17, x8, x9\n\t" + "eor x12, x5, x6\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x4\n\t" + "add x7, x7, x13\n\t" + "eor x12, x12, x6\n\t" + "add x7, x7, x15\n\t" + "eor x16, x16, x9\n\t" + "add x7, x7, x12\n\t" + "add x14, x14, x16\n\t" + "add x11, x11, x7\n\t" + "add x7, x7, x14\n\t" + /* Round 5 */ + "mov x13, v2.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ext v10.16b, v2.16b, v3.16b, #8\n\t" + "ror x12, x11, #14\n\t" + "shl v8.2d, v1.2d, #45\n\t" + "ror x14, x7, #28\n\t" + "sri v8.2d, v1.2d, #19\n\t" + "eor x12, x12, x11, ror 18\n\t" + "shl v9.2d, v1.2d, #3\n\t" + "eor x14, x14, x7, ror 34\n\t" + "sri v9.2d, v1.2d, #61\n\t" + "eor x12, x12, x11, ror 41\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x14, x14, x7, ror 39\n\t" + "ushr v8.2d, v1.2d, #6\n\t" + "add x6, x6, x12\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x16, x7, x8\n\t" + "add v2.2d, v2.2d, v9.2d\n\t" + "eor x12, x4, x5\n\t" + "ext v9.16b, v6.16b, v7.16b, #8\n\t" + "and x17, x16, x17\n\t" + "add v2.2d, v2.2d, v9.2d\n\t" + "and x12, x12, x11\n\t" + "shl v8.2d, v10.2d, #63\n\t" + "add x6, x6, x13\n\t" + "sri v8.2d, v10.2d, #1\n\t" + "eor x12, x12, x5\n\t" + "tbl v9.16b, {v10.16b}, v11.16b\n\t" + "add x6, x6, x15\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x17, x17, x8\n\t" + "ushr v10.2d, v10.2d, #7\n\t" + "add x6, x6, x12\n\t" + "eor v9.16b, v9.16b, v10.16b\n\t" + "add x14, x14, x17\n\t" + "add v2.2d, v2.2d, v9.2d\n\t" + "add x10, x10, x6\n\t" + "add x6, x6, x14\n\t" + /* Round 6 */ + "mov x13, v3.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x10, #14\n\t" + "ror x14, x6, #28\n\t" + "eor x12, x12, x10, ror 18\n\t" + "eor x14, x14, x6, ror 34\n\t" + "eor x12, x12, x10, ror 41\n\t" + "eor x14, x14, x6, ror 39\n\t" + "add x5, x5, x12\n\t" + "eor x17, x6, x7\n\t" + "eor x12, x11, x4\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x10\n\t" + "add x5, x5, x13\n\t" + "eor x12, x12, x4\n\t" + "add x5, x5, x15\n\t" + "eor x16, x16, x7\n\t" + "add x5, x5, x12\n\t" + "add x14, x14, x16\n\t" + "add x9, x9, x5\n\t" + "add x5, x5, x14\n\t" + /* Round 7 */ + "mov x13, v3.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ext v10.16b, v3.16b, v4.16b, #8\n\t" + "ror x12, x9, #14\n\t" + "shl v8.2d, v2.2d, #45\n\t" + "ror x14, x5, #28\n\t" + "sri v8.2d, v2.2d, #19\n\t" + "eor x12, x12, x9, ror 18\n\t" + "shl v9.2d, v2.2d, #3\n\t" + "eor x14, x14, x5, ror 34\n\t" + "sri v9.2d, v2.2d, #61\n\t" + "eor x12, x12, x9, ror 41\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x14, x14, x5, ror 39\n\t" + "ushr v8.2d, v2.2d, #6\n\t" + "add x4, x4, x12\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x16, x5, x6\n\t" + "add v3.2d, v3.2d, v9.2d\n\t" + "eor x12, x10, x11\n\t" + "ext v9.16b, v7.16b, v0.16b, #8\n\t" + "and x17, x16, x17\n\t" + "add v3.2d, v3.2d, v9.2d\n\t" + "and x12, x12, x9\n\t" + "shl v8.2d, v10.2d, #63\n\t" + "add x4, x4, x13\n\t" + "sri v8.2d, v10.2d, #1\n\t" + "eor x12, x12, x11\n\t" + "tbl v9.16b, {v10.16b}, v11.16b\n\t" + "add x4, x4, x15\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x17, x17, x6\n\t" + "ushr v10.2d, v10.2d, #7\n\t" + "add x4, x4, x12\n\t" + "eor v9.16b, v9.16b, v10.16b\n\t" + "add x14, x14, x17\n\t" + "add v3.2d, v3.2d, v9.2d\n\t" + "add x8, x8, x4\n\t" + "add x4, x4, x14\n\t" + /* Round 8 */ + "mov x13, v4.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x8, #14\n\t" + "ror x14, x4, #28\n\t" + "eor x12, x12, x8, ror 18\n\t" + "eor x14, x14, x4, ror 34\n\t" + "eor x12, x12, x8, ror 41\n\t" + "eor x14, x14, x4, ror 39\n\t" + "add x11, x11, x12\n\t" + "eor x17, x4, x5\n\t" + "eor x12, x9, x10\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x8\n\t" + "add x11, x11, x13\n\t" + "eor x12, x12, x10\n\t" + "add x11, x11, x15\n\t" + "eor x16, x16, x5\n\t" + "add x11, x11, x12\n\t" + "add x14, x14, x16\n\t" + "add x7, x7, x11\n\t" + "add x11, x11, x14\n\t" + /* Round 9 */ + "mov x13, v4.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ext v10.16b, v4.16b, v5.16b, #8\n\t" + "ror x12, x7, #14\n\t" + "shl v8.2d, v3.2d, #45\n\t" + "ror x14, x11, #28\n\t" + "sri v8.2d, v3.2d, #19\n\t" + "eor x12, x12, x7, ror 18\n\t" + "shl v9.2d, v3.2d, #3\n\t" + "eor x14, x14, x11, ror 34\n\t" + "sri v9.2d, v3.2d, #61\n\t" + "eor x12, x12, x7, ror 41\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x14, x14, x11, ror 39\n\t" + "ushr v8.2d, v3.2d, #6\n\t" + "add x10, x10, x12\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x16, x11, x4\n\t" + "add v4.2d, v4.2d, v9.2d\n\t" + "eor x12, x8, x9\n\t" + "ext v9.16b, v0.16b, v1.16b, #8\n\t" + "and x17, x16, x17\n\t" + "add v4.2d, v4.2d, v9.2d\n\t" + "and x12, x12, x7\n\t" + "shl v8.2d, v10.2d, #63\n\t" + "add x10, x10, x13\n\t" + "sri v8.2d, v10.2d, #1\n\t" + "eor x12, x12, x9\n\t" + "tbl v9.16b, {v10.16b}, v11.16b\n\t" + "add x10, x10, x15\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x17, x17, x4\n\t" + "ushr v10.2d, v10.2d, #7\n\t" + "add x10, x10, x12\n\t" + "eor v9.16b, v9.16b, v10.16b\n\t" + "add x14, x14, x17\n\t" + "add v4.2d, v4.2d, v9.2d\n\t" + "add x6, x6, x10\n\t" + "add x10, x10, x14\n\t" + /* Round 10 */ + "mov x13, v5.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x6, #14\n\t" + "ror x14, x10, #28\n\t" + "eor x12, x12, x6, ror 18\n\t" + "eor x14, x14, x10, ror 34\n\t" + "eor x12, x12, x6, ror 41\n\t" + "eor x14, x14, x10, ror 39\n\t" + "add x9, x9, x12\n\t" + "eor x17, x10, x11\n\t" + "eor x12, x7, x8\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x6\n\t" + "add x9, x9, x13\n\t" + "eor x12, x12, x8\n\t" + "add x9, x9, x15\n\t" + "eor x16, x16, x11\n\t" + "add x9, x9, x12\n\t" + "add x14, x14, x16\n\t" + "add x5, x5, x9\n\t" + "add x9, x9, x14\n\t" + /* Round 11 */ + "mov x13, v5.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ext v10.16b, v5.16b, v6.16b, #8\n\t" + "ror x12, x5, #14\n\t" + "shl v8.2d, v4.2d, #45\n\t" + "ror x14, x9, #28\n\t" + "sri v8.2d, v4.2d, #19\n\t" + "eor x12, x12, x5, ror 18\n\t" + "shl v9.2d, v4.2d, #3\n\t" + "eor x14, x14, x9, ror 34\n\t" + "sri v9.2d, v4.2d, #61\n\t" + "eor x12, x12, x5, ror 41\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x14, x14, x9, ror 39\n\t" + "ushr v8.2d, v4.2d, #6\n\t" + "add x8, x8, x12\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x16, x9, x10\n\t" + "add v5.2d, v5.2d, v9.2d\n\t" + "eor x12, x6, x7\n\t" + "ext v9.16b, v1.16b, v2.16b, #8\n\t" + "and x17, x16, x17\n\t" + "add v5.2d, v5.2d, v9.2d\n\t" + "and x12, x12, x5\n\t" + "shl v8.2d, v10.2d, #63\n\t" + "add x8, x8, x13\n\t" + "sri v8.2d, v10.2d, #1\n\t" + "eor x12, x12, x7\n\t" + "tbl v9.16b, {v10.16b}, v11.16b\n\t" + "add x8, x8, x15\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x17, x17, x10\n\t" + "ushr v10.2d, v10.2d, #7\n\t" + "add x8, x8, x12\n\t" + "eor v9.16b, v9.16b, v10.16b\n\t" + "add x14, x14, x17\n\t" + "add v5.2d, v5.2d, v9.2d\n\t" + "add x4, x4, x8\n\t" + "add x8, x8, x14\n\t" + /* Round 12 */ + "mov x13, v6.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x4, #14\n\t" + "ror x14, x8, #28\n\t" + "eor x12, x12, x4, ror 18\n\t" + "eor x14, x14, x8, ror 34\n\t" + "eor x12, x12, x4, ror 41\n\t" + "eor x14, x14, x8, ror 39\n\t" + "add x7, x7, x12\n\t" + "eor x17, x8, x9\n\t" + "eor x12, x5, x6\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x4\n\t" + "add x7, x7, x13\n\t" + "eor x12, x12, x6\n\t" + "add x7, x7, x15\n\t" + "eor x16, x16, x9\n\t" + "add x7, x7, x12\n\t" + "add x14, x14, x16\n\t" + "add x11, x11, x7\n\t" + "add x7, x7, x14\n\t" + /* Round 13 */ + "mov x13, v6.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ext v10.16b, v6.16b, v7.16b, #8\n\t" + "ror x12, x11, #14\n\t" + "shl v8.2d, v5.2d, #45\n\t" + "ror x14, x7, #28\n\t" + "sri v8.2d, v5.2d, #19\n\t" + "eor x12, x12, x11, ror 18\n\t" + "shl v9.2d, v5.2d, #3\n\t" + "eor x14, x14, x7, ror 34\n\t" + "sri v9.2d, v5.2d, #61\n\t" + "eor x12, x12, x11, ror 41\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x14, x14, x7, ror 39\n\t" + "ushr v8.2d, v5.2d, #6\n\t" + "add x6, x6, x12\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x16, x7, x8\n\t" + "add v6.2d, v6.2d, v9.2d\n\t" + "eor x12, x4, x5\n\t" + "ext v9.16b, v2.16b, v3.16b, #8\n\t" + "and x17, x16, x17\n\t" + "add v6.2d, v6.2d, v9.2d\n\t" + "and x12, x12, x11\n\t" + "shl v8.2d, v10.2d, #63\n\t" + "add x6, x6, x13\n\t" + "sri v8.2d, v10.2d, #1\n\t" + "eor x12, x12, x5\n\t" + "tbl v9.16b, {v10.16b}, v11.16b\n\t" + "add x6, x6, x15\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x17, x17, x8\n\t" + "ushr v10.2d, v10.2d, #7\n\t" + "add x6, x6, x12\n\t" + "eor v9.16b, v9.16b, v10.16b\n\t" + "add x14, x14, x17\n\t" + "add v6.2d, v6.2d, v9.2d\n\t" + "add x10, x10, x6\n\t" + "add x6, x6, x14\n\t" + /* Round 14 */ + "mov x13, v7.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x10, #14\n\t" + "ror x14, x6, #28\n\t" + "eor x12, x12, x10, ror 18\n\t" + "eor x14, x14, x6, ror 34\n\t" + "eor x12, x12, x10, ror 41\n\t" + "eor x14, x14, x6, ror 39\n\t" + "add x5, x5, x12\n\t" + "eor x17, x6, x7\n\t" + "eor x12, x11, x4\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x10\n\t" + "add x5, x5, x13\n\t" + "eor x12, x12, x4\n\t" + "add x5, x5, x15\n\t" + "eor x16, x16, x7\n\t" + "add x5, x5, x12\n\t" + "add x14, x14, x16\n\t" + "add x9, x9, x5\n\t" + "add x5, x5, x14\n\t" + /* Round 15 */ + "mov x13, v7.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ext v10.16b, v7.16b, v0.16b, #8\n\t" + "ror x12, x9, #14\n\t" + "shl v8.2d, v6.2d, #45\n\t" + "ror x14, x5, #28\n\t" + "sri v8.2d, v6.2d, #19\n\t" + "eor x12, x12, x9, ror 18\n\t" + "shl v9.2d, v6.2d, #3\n\t" + "eor x14, x14, x5, ror 34\n\t" + "sri v9.2d, v6.2d, #61\n\t" + "eor x12, x12, x9, ror 41\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x14, x14, x5, ror 39\n\t" + "ushr v8.2d, v6.2d, #6\n\t" + "add x4, x4, x12\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x16, x5, x6\n\t" + "add v7.2d, v7.2d, v9.2d\n\t" + "eor x12, x10, x11\n\t" + "ext v9.16b, v3.16b, v4.16b, #8\n\t" + "and x17, x16, x17\n\t" + "add v7.2d, v7.2d, v9.2d\n\t" + "and x12, x12, x9\n\t" + "shl v8.2d, v10.2d, #63\n\t" + "add x4, x4, x13\n\t" + "sri v8.2d, v10.2d, #1\n\t" + "eor x12, x12, x11\n\t" + "tbl v9.16b, {v10.16b}, v11.16b\n\t" + "add x4, x4, x15\n\t" + "eor v9.16b, v9.16b, v8.16b\n\t" + "eor x17, x17, x6\n\t" + "ushr v10.2d, v10.2d, #7\n\t" + "add x4, x4, x12\n\t" + "eor v9.16b, v9.16b, v10.16b\n\t" + "add x14, x14, x17\n\t" + "add v7.2d, v7.2d, v9.2d\n\t" + "add x8, x8, x4\n\t" + "add x4, x4, x14\n\t" + "subs x27, x27, #1\n\t" + "bne L_sha512_len_neon_start_%=\n\t" + /* Round 0 */ + "mov x13, v0.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x8, #14\n\t" + "ror x14, x4, #28\n\t" + "eor x12, x12, x8, ror 18\n\t" + "eor x14, x14, x4, ror 34\n\t" + "eor x12, x12, x8, ror 41\n\t" + "eor x14, x14, x4, ror 39\n\t" + "add x11, x11, x12\n\t" + "eor x17, x4, x5\n\t" + "eor x12, x9, x10\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x8\n\t" + "add x11, x11, x13\n\t" + "eor x12, x12, x10\n\t" + "add x11, x11, x15\n\t" + "eor x16, x16, x5\n\t" + "add x11, x11, x12\n\t" + "add x14, x14, x16\n\t" + "add x7, x7, x11\n\t" + "add x11, x11, x14\n\t" + /* Round 1 */ + "mov x13, v0.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x7, #14\n\t" + "ror x14, x11, #28\n\t" + "eor x12, x12, x7, ror 18\n\t" + "eor x14, x14, x11, ror 34\n\t" + "eor x12, x12, x7, ror 41\n\t" + "eor x14, x14, x11, ror 39\n\t" + "add x10, x10, x12\n\t" + "eor x16, x11, x4\n\t" + "eor x12, x8, x9\n\t" + "and x17, x16, x17\n\t" + "and x12, x12, x7\n\t" + "add x10, x10, x13\n\t" + "eor x12, x12, x9\n\t" + "add x10, x10, x15\n\t" + "eor x17, x17, x4\n\t" + "add x10, x10, x12\n\t" + "add x14, x14, x17\n\t" + "add x6, x6, x10\n\t" + "add x10, x10, x14\n\t" + /* Round 2 */ + "mov x13, v1.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x6, #14\n\t" + "ror x14, x10, #28\n\t" + "eor x12, x12, x6, ror 18\n\t" + "eor x14, x14, x10, ror 34\n\t" + "eor x12, x12, x6, ror 41\n\t" + "eor x14, x14, x10, ror 39\n\t" + "add x9, x9, x12\n\t" + "eor x17, x10, x11\n\t" + "eor x12, x7, x8\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x6\n\t" + "add x9, x9, x13\n\t" + "eor x12, x12, x8\n\t" + "add x9, x9, x15\n\t" + "eor x16, x16, x11\n\t" + "add x9, x9, x12\n\t" + "add x14, x14, x16\n\t" + "add x5, x5, x9\n\t" + "add x9, x9, x14\n\t" + /* Round 3 */ + "mov x13, v1.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x5, #14\n\t" + "ror x14, x9, #28\n\t" + "eor x12, x12, x5, ror 18\n\t" + "eor x14, x14, x9, ror 34\n\t" + "eor x12, x12, x5, ror 41\n\t" + "eor x14, x14, x9, ror 39\n\t" + "add x8, x8, x12\n\t" + "eor x16, x9, x10\n\t" + "eor x12, x6, x7\n\t" + "and x17, x16, x17\n\t" + "and x12, x12, x5\n\t" + "add x8, x8, x13\n\t" + "eor x12, x12, x7\n\t" + "add x8, x8, x15\n\t" + "eor x17, x17, x10\n\t" + "add x8, x8, x12\n\t" + "add x14, x14, x17\n\t" + "add x4, x4, x8\n\t" + "add x8, x8, x14\n\t" + /* Round 4 */ + "mov x13, v2.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x4, #14\n\t" + "ror x14, x8, #28\n\t" + "eor x12, x12, x4, ror 18\n\t" + "eor x14, x14, x8, ror 34\n\t" + "eor x12, x12, x4, ror 41\n\t" + "eor x14, x14, x8, ror 39\n\t" + "add x7, x7, x12\n\t" + "eor x17, x8, x9\n\t" + "eor x12, x5, x6\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x4\n\t" + "add x7, x7, x13\n\t" + "eor x12, x12, x6\n\t" + "add x7, x7, x15\n\t" + "eor x16, x16, x9\n\t" + "add x7, x7, x12\n\t" + "add x14, x14, x16\n\t" + "add x11, x11, x7\n\t" + "add x7, x7, x14\n\t" + /* Round 5 */ + "mov x13, v2.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x11, #14\n\t" + "ror x14, x7, #28\n\t" + "eor x12, x12, x11, ror 18\n\t" + "eor x14, x14, x7, ror 34\n\t" + "eor x12, x12, x11, ror 41\n\t" + "eor x14, x14, x7, ror 39\n\t" + "add x6, x6, x12\n\t" + "eor x16, x7, x8\n\t" + "eor x12, x4, x5\n\t" + "and x17, x16, x17\n\t" + "and x12, x12, x11\n\t" + "add x6, x6, x13\n\t" + "eor x12, x12, x5\n\t" + "add x6, x6, x15\n\t" + "eor x17, x17, x8\n\t" + "add x6, x6, x12\n\t" + "add x14, x14, x17\n\t" + "add x10, x10, x6\n\t" + "add x6, x6, x14\n\t" + /* Round 6 */ + "mov x13, v3.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x10, #14\n\t" + "ror x14, x6, #28\n\t" + "eor x12, x12, x10, ror 18\n\t" + "eor x14, x14, x6, ror 34\n\t" + "eor x12, x12, x10, ror 41\n\t" + "eor x14, x14, x6, ror 39\n\t" + "add x5, x5, x12\n\t" + "eor x17, x6, x7\n\t" + "eor x12, x11, x4\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x10\n\t" + "add x5, x5, x13\n\t" + "eor x12, x12, x4\n\t" + "add x5, x5, x15\n\t" + "eor x16, x16, x7\n\t" + "add x5, x5, x12\n\t" + "add x14, x14, x16\n\t" + "add x9, x9, x5\n\t" + "add x5, x5, x14\n\t" + /* Round 7 */ + "mov x13, v3.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x9, #14\n\t" + "ror x14, x5, #28\n\t" + "eor x12, x12, x9, ror 18\n\t" + "eor x14, x14, x5, ror 34\n\t" + "eor x12, x12, x9, ror 41\n\t" + "eor x14, x14, x5, ror 39\n\t" + "add x4, x4, x12\n\t" + "eor x16, x5, x6\n\t" + "eor x12, x10, x11\n\t" + "and x17, x16, x17\n\t" + "and x12, x12, x9\n\t" + "add x4, x4, x13\n\t" + "eor x12, x12, x11\n\t" + "add x4, x4, x15\n\t" + "eor x17, x17, x6\n\t" + "add x4, x4, x12\n\t" + "add x14, x14, x17\n\t" + "add x8, x8, x4\n\t" + "add x4, x4, x14\n\t" + /* Round 8 */ + "mov x13, v4.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x8, #14\n\t" + "ror x14, x4, #28\n\t" + "eor x12, x12, x8, ror 18\n\t" + "eor x14, x14, x4, ror 34\n\t" + "eor x12, x12, x8, ror 41\n\t" + "eor x14, x14, x4, ror 39\n\t" + "add x11, x11, x12\n\t" + "eor x17, x4, x5\n\t" + "eor x12, x9, x10\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x8\n\t" + "add x11, x11, x13\n\t" + "eor x12, x12, x10\n\t" + "add x11, x11, x15\n\t" + "eor x16, x16, x5\n\t" + "add x11, x11, x12\n\t" + "add x14, x14, x16\n\t" + "add x7, x7, x11\n\t" + "add x11, x11, x14\n\t" + /* Round 9 */ + "mov x13, v4.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x7, #14\n\t" + "ror x14, x11, #28\n\t" + "eor x12, x12, x7, ror 18\n\t" + "eor x14, x14, x11, ror 34\n\t" + "eor x12, x12, x7, ror 41\n\t" + "eor x14, x14, x11, ror 39\n\t" + "add x10, x10, x12\n\t" + "eor x16, x11, x4\n\t" + "eor x12, x8, x9\n\t" + "and x17, x16, x17\n\t" + "and x12, x12, x7\n\t" + "add x10, x10, x13\n\t" + "eor x12, x12, x9\n\t" + "add x10, x10, x15\n\t" + "eor x17, x17, x4\n\t" + "add x10, x10, x12\n\t" + "add x14, x14, x17\n\t" + "add x6, x6, x10\n\t" + "add x10, x10, x14\n\t" + /* Round 10 */ + "mov x13, v5.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x6, #14\n\t" + "ror x14, x10, #28\n\t" + "eor x12, x12, x6, ror 18\n\t" + "eor x14, x14, x10, ror 34\n\t" + "eor x12, x12, x6, ror 41\n\t" + "eor x14, x14, x10, ror 39\n\t" + "add x9, x9, x12\n\t" + "eor x17, x10, x11\n\t" + "eor x12, x7, x8\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x6\n\t" + "add x9, x9, x13\n\t" + "eor x12, x12, x8\n\t" + "add x9, x9, x15\n\t" + "eor x16, x16, x11\n\t" + "add x9, x9, x12\n\t" + "add x14, x14, x16\n\t" + "add x5, x5, x9\n\t" + "add x9, x9, x14\n\t" + /* Round 11 */ + "mov x13, v5.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x5, #14\n\t" + "ror x14, x9, #28\n\t" + "eor x12, x12, x5, ror 18\n\t" + "eor x14, x14, x9, ror 34\n\t" + "eor x12, x12, x5, ror 41\n\t" + "eor x14, x14, x9, ror 39\n\t" + "add x8, x8, x12\n\t" + "eor x16, x9, x10\n\t" + "eor x12, x6, x7\n\t" + "and x17, x16, x17\n\t" + "and x12, x12, x5\n\t" + "add x8, x8, x13\n\t" + "eor x12, x12, x7\n\t" + "add x8, x8, x15\n\t" + "eor x17, x17, x10\n\t" + "add x8, x8, x12\n\t" + "add x14, x14, x17\n\t" + "add x4, x4, x8\n\t" + "add x8, x8, x14\n\t" + /* Round 12 */ + "mov x13, v6.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x4, #14\n\t" + "ror x14, x8, #28\n\t" + "eor x12, x12, x4, ror 18\n\t" + "eor x14, x14, x8, ror 34\n\t" + "eor x12, x12, x4, ror 41\n\t" + "eor x14, x14, x8, ror 39\n\t" + "add x7, x7, x12\n\t" + "eor x17, x8, x9\n\t" + "eor x12, x5, x6\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x4\n\t" + "add x7, x7, x13\n\t" + "eor x12, x12, x6\n\t" + "add x7, x7, x15\n\t" + "eor x16, x16, x9\n\t" + "add x7, x7, x12\n\t" + "add x14, x14, x16\n\t" + "add x11, x11, x7\n\t" + "add x7, x7, x14\n\t" + /* Round 13 */ + "mov x13, v6.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x11, #14\n\t" + "ror x14, x7, #28\n\t" + "eor x12, x12, x11, ror 18\n\t" + "eor x14, x14, x7, ror 34\n\t" + "eor x12, x12, x11, ror 41\n\t" + "eor x14, x14, x7, ror 39\n\t" + "add x6, x6, x12\n\t" + "eor x16, x7, x8\n\t" + "eor x12, x4, x5\n\t" + "and x17, x16, x17\n\t" + "and x12, x12, x11\n\t" + "add x6, x6, x13\n\t" + "eor x12, x12, x5\n\t" + "add x6, x6, x15\n\t" + "eor x17, x17, x8\n\t" + "add x6, x6, x12\n\t" + "add x14, x14, x17\n\t" + "add x10, x10, x6\n\t" + "add x6, x6, x14\n\t" + /* Round 14 */ + "mov x13, v7.d[0]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x10, #14\n\t" + "ror x14, x6, #28\n\t" + "eor x12, x12, x10, ror 18\n\t" + "eor x14, x14, x6, ror 34\n\t" + "eor x12, x12, x10, ror 41\n\t" + "eor x14, x14, x6, ror 39\n\t" + "add x5, x5, x12\n\t" + "eor x17, x6, x7\n\t" + "eor x12, x11, x4\n\t" + "and x16, x17, x16\n\t" + "and x12, x12, x10\n\t" + "add x5, x5, x13\n\t" + "eor x12, x12, x4\n\t" + "add x5, x5, x15\n\t" + "eor x16, x16, x7\n\t" + "add x5, x5, x12\n\t" + "add x14, x14, x16\n\t" + "add x9, x9, x5\n\t" + "add x5, x5, x14\n\t" + /* Round 15 */ + "mov x13, v7.d[1]\n\t" + "ldr x15, [x3], #8\n\t" + "ror x12, x9, #14\n\t" + "ror x14, x5, #28\n\t" + "eor x12, x12, x9, ror 18\n\t" + "eor x14, x14, x5, ror 34\n\t" + "eor x12, x12, x9, ror 41\n\t" + "eor x14, x14, x5, ror 39\n\t" + "add x4, x4, x12\n\t" + "eor x16, x5, x6\n\t" + "eor x12, x10, x11\n\t" + "and x17, x16, x17\n\t" + "and x12, x12, x9\n\t" + "add x4, x4, x13\n\t" + "eor x12, x12, x11\n\t" + "add x4, x4, x15\n\t" + "eor x17, x17, x6\n\t" + "add x4, x4, x12\n\t" + "add x14, x14, x17\n\t" + "add x8, x8, x4\n\t" + "add x4, x4, x14\n\t" + "add x11, x11, x26\n\t" + "add x10, x10, x25\n\t" + "add x9, x9, x24\n\t" + "add x8, x8, x23\n\t" + "add x7, x7, x22\n\t" + "add x6, x6, x21\n\t" + "add x5, x5, x20\n\t" + "add x4, x4, x19\n\t" + "adr x3, %[L_SHA512_transform_neon_len_k]\n\t" + "subs %w[len], %w[len], #0x80\n\t" + "bne L_sha512_len_neon_begin_%=\n\t" + "stp x4, x5, [%x[sha512]]\n\t" + "stp x6, x7, [%x[sha512], #16]\n\t" + "stp x8, x9, [%x[sha512], #32]\n\t" + "stp x10, x11, [%x[sha512], #48]\n\t" + "ldp x29, x30, [sp], #16\n\t" + : [sha512] "+r" (sha512), [data] "+r" (data), [len] "+r" (len) + : [L_SHA512_transform_neon_len_k] "S" (L_SHA512_transform_neon_len_k), [L_SHA512_transform_neon_len_ror8] "S" (L_SHA512_transform_neon_len_ror8) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11" + ); +} + +#endif /* WOLFSSL_ARMASM */ +#endif /* __aarch64__ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha512.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha512.c new file mode 100644 index 000000000..e909c7c25 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/armv8-sha512.c @@ -0,0 +1,715 @@ +/* sha512.c + * + * Copyright (C) 2006-2020 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_ARMASM +#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) + +#include +#include +#include +#include + +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef WOLFSSL_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); + sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1); + sha512->digest[4] = W64LIT(0x510e527fade682d1); + sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f); + sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b); + sha512->digest[7] = W64LIT(0x5be0cd19137e2179); + + sha512->buffLen = 0; + sha512->loLen = 0; + sha512->hiLen = 0; +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + sha512->flags = 0; +#endif + + return 0; +} + +#endif /* WOLFSSL_SHA512 */ + +#ifdef WOLFSSL_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; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + sha512->W = NULL; +#endif + + (void)devId; + + return ret; +} + +#endif /* WOLFSSL_SHA512 */ + +#ifndef WOLFSSL_ARMASM +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) +}; + +#ifdef LITTLE_ENDIAN_ORDER +#define blk0(i) (W[i] = ByteReverseWord64(DATA[i])) +#else +#define blk0(i) (W[i] = DATA[i]) +#endif + +#define blk2(i) ( \ + W[ i ] += \ + s1(W[(i- 2) & 15])+ \ + W[(i- 7) & 15] + \ + s0(W[(i-15) & 15]) \ + ) + +#define Ch(x,y,z) (z ^ ((z ^ y) & x)) +#define Maj(x,y,z) (y ^ ((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 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 R0(i) \ + h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + 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] + blk2(i); \ + d(i) += h(i); \ + h(i) += S0(a(i)) + Maj(a(i),b(i),c(i)) + +#define DATA sha512->buffer +static void Transform_Sha512(wc_Sha512* sha512) +{ + const word64* K = K512; + word32 j; + word64 T[8]; + word64 W[16]; + + /* Copy digest to working vars */ + T[0] = sha512->digest[0]; + T[1] = sha512->digest[1]; + T[2] = sha512->digest[2]; + T[3] = sha512->digest[3]; + T[4] = sha512->digest[4]; + T[5] = sha512->digest[5]; + T[6] = sha512->digest[6]; + T[7] = sha512->digest[7]; + + /* 80 operations, partially loop unrolled */ + j = 0; + R0( 0); R0( 1); R0( 2); R0( 3); + R0( 4); R0( 5); R0( 6); R0( 7); + R0( 8); R0( 9); R0(10); R0(11); + R0(12); R0(13); R0(14); R0(15); + for (j = 16; j < 80; j += 16) { + R( 0); R( 1); R( 2); R( 3); + R( 4); R( 5); R( 6); R( 7); + R( 8); R( 9); R(10); R(11); + R(12); R(13); R(14); R(15); + } + + /* Add the working vars back into digest */ + sha512->digest[0] += T[0]; + sha512->digest[1] += T[1]; + sha512->digest[2] += T[2]; + sha512->digest[3] += T[3]; + sha512->digest[4] += T[4]; + sha512->digest[5] += T[5]; + sha512->digest[6] += T[6]; + sha512->digest[7] += T[7]; + + return 0; +} +#undef DATA + +#define DATA ((word64*)data) +static void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, word32 len) +{ + const word64* K = K512; + word32 j; + word64 T[8]; + word64 TO[8]; + word64 W[16]; + + /* Copy digest to working vars */ + T[0] = sha512->digest[0]; + T[1] = sha512->digest[1]; + T[2] = sha512->digest[2]; + T[3] = sha512->digest[3]; + T[4] = sha512->digest[4]; + T[5] = sha512->digest[5]; + T[6] = sha512->digest[6]; + T[7] = sha512->digest[7]; + + do { + TO[0] = T[0]; + TO[1] = T[1]; + TO[2] = T[2]; + TO[3] = T[3]; + TO[4] = T[4]; + TO[5] = T[5]; + TO[6] = T[6]; + TO[7] = T[7]; + + /* 80 operations, partially loop unrolled */ + j = 0; + R0( 0); R0( 1); R0( 2); R0( 3); + R0( 4); R0( 5); R0( 6); R0( 7); + R0( 8); R0( 9); R0(10); R0(11); + R0(12); R0(13); R0(14); R0(15); + for (j = 16; j < 80; j += 16) { + R( 0); R( 1); R( 2); R( 3); + R( 4); R( 5); R( 6); R( 7); + R( 8); R( 9); R(10); R(11); + R(12); R(13); R(14); R(15); + } + + T[0] += TO[0]; + T[1] += TO[1]; + T[2] += TO[2]; + T[3] += TO[3]; + T[4] += TO[4]; + T[5] += TO[5]; + T[6] += TO[6]; + T[7] += TO[7]; + + data += 128; + len -= 128; + } + while (len > 0); + + /* Add the working vars back into digest */ + sha512->digest[0] = T[0]; + sha512->digest[1] = T[1]; + sha512->digest[2] = T[2]; + sha512->digest[3] = T[3]; + sha512->digest[4] = T[4]; + sha512->digest[5] = T[5]; + sha512->digest[6] = T[6]; + sha512->digest[7] = T[7]; + + return 0; +} +#undef DATA +#endif + + +static WC_INLINE void AddLength(wc_Sha512* sha512, word32 len) +{ + word64 tmp = sha512->loLen; + if ( (sha512->loLen += len) < tmp) + sha512->hiLen++; /* carry low to high */ +} + +static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) +{ + int ret = 0; + /* do block size increments */ + byte* local = (byte*)sha512->buffer; + word32 blocksLen; + + /* check that internal buffLen is valid */ + if (sha512->buffLen >= WC_SHA512_BLOCK_SIZE) + return BUFFER_E; + + AddLength(sha512, len); + + if (sha512->buffLen > 0) { + word32 add = min(len, WC_SHA512_BLOCK_SIZE - sha512->buffLen); + if (add > 0) { + XMEMCPY(&local[sha512->buffLen], data, add); + + sha512->buffLen += add; + data += add; + len -= add; + } + + if (sha512->buffLen == WC_SHA512_BLOCK_SIZE) { +#ifndef WOLFSSL_ARMASM + Transform_Sha512(sha512); +#else + Transform_Sha512_Len(sha512, (const byte*)sha512->buffer, + WC_SHA512_BLOCK_SIZE); +#endif + sha512->buffLen = 0; + } + } + + blocksLen = len & ~(WC_SHA512_BLOCK_SIZE-1); + if (blocksLen > 0) { + /* Byte reversal performed in function if required. */ + Transform_Sha512_Len(sha512, data, blocksLen); + data += blocksLen; + len -= blocksLen; + } + + if (len > 0) { + XMEMCPY(local, data, len); + sha512->buffLen = len; + } + + return ret; +} + +#ifdef WOLFSSL_SHA512 + +int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) +{ + if (sha512 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + return Sha512Update(sha512, data, len); +} + +#endif /* WOLFSSL_SHA512 */ + +static WC_INLINE int Sha512Final(wc_Sha512* sha512) +{ + byte* local = (byte*)sha512->buffer; + + if (sha512 == NULL) { + return BAD_FUNC_ARG; + } + + local[sha512->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + 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; +#ifndef WOLFSSL_ARMASM + Transform_Sha512(sha512); +#else + Transform_Sha512_Len(sha512, (const byte*)sha512->buffer, + WC_SHA512_BLOCK_SIZE); +#endif + + sha512->buffLen = 0; + } + 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->loLen = sha512->loLen << 3; + + /* store lengths */ + /* ! length ordering dependent on digest endian type ! */ + + sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen; + sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen; + + 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); +#ifndef WOLFSSL_ARMASM + Transform_Sha512(sha512); +#else + Transform_Sha512_Len(sha512, (const byte*)sha512->buffer, + WC_SHA512_BLOCK_SIZE); +#endif + +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(sha512->digest, sha512->digest, WC_SHA512_DIGEST_SIZE); +#endif + + return 0; +} + +#ifdef WOLFSSL_SHA512 + +int wc_Sha512FinalRaw(wc_Sha512* sha512, byte* hash) +{ +#ifdef LITTLE_ENDIAN_ORDER + word64 digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)]; +#endif + + if (sha512 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64((word64*)digest, (word64*)sha512->digest, + WC_SHA512_DIGEST_SIZE); + XMEMCPY(hash, digest, WC_SHA512_DIGEST_SIZE); +#else + XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE); +#endif + + return 0; +} + +int wc_Sha512Final(wc_Sha512* sha512, byte* hash) +{ + int ret; + + if (sha512 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = Sha512Final(sha512); + if (ret != 0) + return ret; + + XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE); + + 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; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (sha512->W != NULL) { + XFREE(sha512->W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha512->W = NULL; + } +#endif +} + +#endif /* WOLFSSL_SHA512 */ + +/* -------------------------------------------------------------------------- */ +/* 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); + sha384->digest[3] = W64LIT(0x152fecd8f70e5939); + sha384->digest[4] = W64LIT(0x67332667ffc00b31); + sha384->digest[5] = W64LIT(0x8eb44a8768581511); + sha384->digest[6] = W64LIT(0xdb0c2e0d64f98fa7); + sha384->digest[7] = W64LIT(0x47b5481dbefa4fa4); + + sha384->buffLen = 0; + sha384->loLen = 0; + sha384->hiLen = 0; +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + sha384->flags = 0; +#endif + + return 0; +} + +int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len) +{ + if (sha384 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + return Sha512Update((wc_Sha512*)sha384, data, len); +} + + +int wc_Sha384FinalRaw(wc_Sha384* sha384, byte* hash) +{ +#ifdef LITTLE_ENDIAN_ORDER + word64 digest[WC_SHA384_DIGEST_SIZE / sizeof(word64)]; +#endif + + if (sha384 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64((word64*)digest, (word64*)sha384->digest, + WC_SHA384_DIGEST_SIZE); + XMEMCPY(hash, digest, WC_SHA384_DIGEST_SIZE); +#else + XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE); +#endif + + return 0; +} + +int wc_Sha384Final(wc_Sha384* sha384, byte* hash) +{ + int ret; + + if (sha384 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = Sha512Final((wc_Sha512*)sha384); + if (ret != 0) + return ret; + + XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE); + + return InitSha384(sha384); /* reset state */ +} + +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; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + sha384->W = NULL; +#endif + + (void)devId; + + return ret; +} + +int wc_InitSha384(wc_Sha384* sha384) +{ + return wc_InitSha384_ex(sha384, NULL, INVALID_DEVID); +} + +void wc_Sha384Free(wc_Sha384* sha384) +{ + if (sha384 == NULL) + return; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (sha384->W != NULL) { + XFREE(sha384->W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha384->W = NULL; + } +#endif +} + +#endif /* WOLFSSL_SHA384 */ + +#ifdef 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); + wc_Sha512Free(&tmpSha512); + } + 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_SMALL_STACK_CACHE + dst->W = NULL; +#endif + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + + return ret; +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Sha512SetFlags(wc_Sha512* sha512, word32 flags) +{ + if (sha512) { + sha512->flags = flags; + } + return 0; +} +int wc_Sha512GetFlags(wc_Sha512* sha512, word32* flags) +{ + if (sha512 && flags) { + *flags = sha512->flags; + } + return 0; +} +#endif + +#endif /* WOLFSSL_SHA512 */ + +#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); + wc_Sha384Free(&tmpSha384); + } + 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_SMALL_STACK_CACHE + dst->W = NULL; +#endif + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + + return ret; +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Sha384SetFlags(wc_Sha384* sha384, word32 flags) +{ + if (sha384) { + sha384->flags = flags; + } + return 0; +} +int wc_Sha384GetFlags(wc_Sha384* sha384, word32* flags) +{ + if (sha384 && flags) { + *flags = sha384->flags; + } + return 0; +} +#endif + +#endif /* WOLFSSL_SHA384 */ + +#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */ +#endif /* WOLFSSL_ARMASM */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/cryptoCell.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/cryptoCell.c new file mode 100644 index 000000000..c3bd2d9c5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/cryptoCell.c @@ -0,0 +1,309 @@ +/* cryptoCell.c + * + * Copyright (C) 2020 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 + +/* This source is included in wc_port.c */ +/* WOLFSSL_CRYPTOCELL_C is defined by wc_port.c in case compile tries to + include this .c directly */ +#ifdef WOLFSSL_CRYPTOCELL_C + +#ifdef WOLFSSL_CRYPTOCELL + +#include +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* Global Variables (extern) */ +CRYS_RND_State_t wc_rndState; +CRYS_RND_WorkBuff_t wc_rndWorkBuff; +SaSiRndGenerateVectWorkFunc_t wc_rndGenVectFunc = CRYS_RND_GenerateVector; + +static word32 cc310_enableCount = 0; + +static void cc310_enable(void) +{ + cc310_enableCount++; + + /* Enable the CC310 HW/IQ once*/ + + NRF_CRYPTOCELL->ENABLE = 1; + NVIC_EnableIRQ(CRYPTOCELL_IRQn); +} + +static void cc310_disable(void) +{ + cc310_enableCount--; + + /* Disable HW/IRQ if no more users */ + if (cc310_enableCount == 0) { + NRF_CRYPTOCELL->ENABLE = 0; + NVIC_DisableIRQ(CRYPTOCELL_IRQn); + } +} + +int cc310_Init(void) +{ + int ret = 0; + static int initialized = 0; + + if (!initialized) { + /* Enable the CC310 HW. */ + cc310_enable(); + + /*Initialize the CC310 run-time library*/ + ret = SaSi_LibInit(); + + if (ret != SA_SILIB_RET_OK) { + WOLFSSL_MSG("Error SaSi_LibInit"); + return ret; + } + + /* RNG CryptoCell CC310 */ + ret = CRYS_RndInit(&wc_rndState, &wc_rndWorkBuff); + if (ret != CRYS_OK) { + WOLFSSL_MSG("Error CRYS_RndInit"); + return ret; + } + initialized = 1; + } + return ret; +} + +void cc310_Free(void) +{ + CRYSError_t crys_result; + + SaSi_LibFini(); + + crys_result = CRYS_RND_UnInstantiation(&wc_rndState); + + if (crys_result != CRYS_OK) { + WOLFSSL_MSG("Error RYS_RND_UnInstantiation"); + } + cc310_disable(); +} + +int cc310_random_generate(byte* output, word32 size) +{ + CRYSError_t crys_result; + + crys_result = CRYS_RND_GenerateVector(&wc_rndState, size, output); + + return (crys_result == CRYS_OK) ? 0 : -1; +} +#ifdef HAVE_ECC +CRYS_ECPKI_DomainID_t cc310_mapCurve(int curve_id) +{ + switch(curve_id) + { + case ECC_CURVE_DEF: return CRYS_ECPKI_DomainID_secp256r1; /* default */ + case ECC_SECP160K1: return CRYS_ECPKI_DomainID_secp160k1; + case ECC_SECP160R1: return CRYS_ECPKI_DomainID_secp160r1; + case ECC_SECP160R2: return CRYS_ECPKI_DomainID_secp160r2; + case ECC_SECP192K1: return CRYS_ECPKI_DomainID_secp192k1; + case ECC_SECP192R1: return CRYS_ECPKI_DomainID_secp192r1; + case ECC_SECP224K1: return CRYS_ECPKI_DomainID_secp224k1; + case ECC_SECP224R1: return CRYS_ECPKI_DomainID_secp224r1; + case ECC_SECP256K1: return CRYS_ECPKI_DomainID_secp256k1; + case ECC_SECP256R1: return CRYS_ECPKI_DomainID_secp256r1; + case ECC_SECP384R1: return CRYS_ECPKI_DomainID_secp384r1; + case ECC_SECP521R1: return CRYS_ECPKI_DomainID_secp521r1; + default: WOLFSSL_MSG("Curve not identified"); + return CRYS_ECPKI_DomainID_Builded; + } +} +#endif /* HAVE_ECC */ + +#ifndef NO_RSA +CRYS_RSA_HASH_OpMode_t cc310_hashModeRSA(enum wc_HashType hash_type, int isHashed) +{ + switch(hash_type) + { + case WC_HASH_TYPE_MD5: + #ifndef NO_MD5 + return isHashed? CRYS_RSA_After_MD5_mode : CRYS_RSA_HASH_MD5_mode; + #endif + case WC_HASH_TYPE_SHA: + #ifndef NO_SHA + return isHashed? CRYS_RSA_After_SHA1_mode : CRYS_RSA_HASH_SHA1_mode; + #endif + case WC_HASH_TYPE_SHA224: + #ifdef WOLFSSL_SHA224 + return isHashed? CRYS_RSA_After_SHA224_mode : CRYS_RSA_HASH_SHA224_mode; + #endif + case WC_HASH_TYPE_SHA256: + #ifndef NO_SHA256 + return isHashed? CRYS_RSA_After_SHA256_mode : CRYS_RSA_HASH_SHA256_mode; + #endif + case WC_HASH_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + return isHashed? CRYS_RSA_After_SHA384_mode : CRYS_RSA_HASH_SHA384_mode; + #endif + case WC_HASH_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + return isHashed? CRYS_RSA_After_SHA512_mode : CRYS_RSA_HASH_SHA512_mode; + #endif + case WC_HASH_TYPE_NONE: + /* default to SHA256 */ + return isHashed? CRYS_RSA_After_SHA256_mode : CRYS_RSA_HASH_SHA256_mode; + default: + return CRYS_RSA_After_HASH_NOT_KNOWN_mode; + } +} +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +CRYS_ECPKI_HASH_OpMode_t cc310_hashModeECC(int hash_size) +{ + CRYS_ECPKI_HASH_OpMode_t hash_mode; + switch (hash_size) + { + case 20: + hash_mode = CRYS_ECPKI_AFTER_HASH_SHA1_mode; + break; + case 28: + hash_mode = CRYS_ECPKI_AFTER_HASH_SHA224_mode; + break; + case 32: + hash_mode = CRYS_ECPKI_AFTER_HASH_SHA256_mode; + break; + case 48: + hash_mode = CRYS_ECPKI_AFTER_HASH_SHA384_mode; + break; + case 64: + hash_mode = CRYS_ECPKI_AFTER_HASH_SHA512_mode; + break; + default: + hash_mode = CRYS_ECPKI_HASH_OpModeLast; + break; + } + return hash_mode; +} +#endif /* HAVE_ECC */ +#endif /* WOLFSSL_CRYPTOCELL*/ + +#if !defined(NO_CRYPT_BENCHMARK) && defined(WOLFSSL_nRF5x_SDK_15_2) + +static int mRtcSec = 0; +static const nrfx_rtc_t rtc = NRFX_RTC_INSTANCE(0); + +static void rtc_handler(nrfx_rtc_int_type_t int_type) +{ + if (int_type == NRFX_RTC_INT_COMPARE0) { + mRtcSec++; + nrfx_rtc_counter_clear(&rtc); + nrfx_rtc_int_enable(&rtc, RTC_CHANNEL_INT_MASK(0)); +#ifdef BSP_LED_1 + nrf_gpio_pin_toggle(BSP_LED_1); +#endif + } + else if (int_type == NRF_DRV_RTC_INT_TICK) { +#ifdef BSP_LED_0 + nrf_gpio_pin_toggle(BSP_LED_0); +#endif + } +} + +static void rtc_config(void) +{ + uint32_t err_code; + nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG; + + /* configure gpio for pin toggling. */ + bsp_board_init(BSP_INIT_LEDS); + + /* start the internal LFCLK XTAL oscillator.*/ + err_code = nrf_drv_clock_init(); + APP_ERROR_CHECK(err_code); + nrf_drv_clock_lfclk_request(NULL); + + /* Initialize RTC instance */ + err_code = nrfx_rtc_init(&rtc, &config, rtc_handler); + APP_ERROR_CHECK(err_code); + + /* Enable tick event */ + nrfx_rtc_tick_enable(&rtc, false); + + /* Set compare channel to trigger interrupt after 1 seconds */ + err_code = nrfx_rtc_cc_set(&rtc, 0, RTC_INPUT_FREQ, true); + APP_ERROR_CHECK(err_code); + + /* Power on RTC instance */ + nrfx_rtc_enable(&rtc); +} + +static int rtc_get_ms(void) +{ + /* Prescaler is 12-bit for COUNTER: frequency = (32768/(PRESCALER+1)) */ + int frequency = (RTC_INPUT_FREQ / (rtc_prescaler_get(rtc.p_reg) + 1)); + uint32_t counter = nrfx_rtc_counter_get(&rtc); + + /* Convert with rounding frequency to milliseconds */ + return ((counter * 1000) + (frequency / 2) ) / frequency; +} + +double current_time(int reset) +{ + double time; + static int initialized = 0; + + if (!initialized) { + rtc_config(); + initialized = 1; + } + time = mRtcSec; + time += (double)rtc_get_ms() / 1000; + + return time; +} + +int nrf_random_generate(byte* output, word32 size) +{ + uint32_t err_code; + static int initialized = 0; + + /* RNG must be initialized once */ + if (!initialized) { + err_code = nrf_drv_rng_init(NULL); + if (err_code != NRF_SUCCESS) { + return -1; + } + initialized = 1; + } + nrf_drv_rng_block_rand(output, size); + return 0; +} +#endif /* !NO_CRYPT_BENCHMARK && WOLFSSL_nRF5x_SDK_15_2 */ + +#endif /* WOLFSSL_CRYPTOCELL_C */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/cryptoCellHash.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/cryptoCellHash.c new file mode 100644 index 000000000..bc729f7f0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/arm/cryptoCellHash.c @@ -0,0 +1,134 @@ +/* cryptoCellHash.c + * + * Copyright (C) 2020 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 + +/* This source is included in wc_port.c */ +/* WOLFSSL_CRYPTOCELL_HASH_C is defined by wc_port.c in case compile tries + to include this .c directly */ +#ifdef WOLFSSL_CRYPTOCELL_HASH_C +#if !defined(NO_SHA256) && defined(WOLFSSL_CRYPTOCELL) + +#include +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) +{ + CRYSError_t ret = 0; + + (void)heap; + (void)devId; + + if (sha256 == NULL) + return BAD_FUNC_ARG; + + XMEMSET(sha256->digest, 0, sizeof(sha256->digest)); + + /* initializes the HASH context and machine to the supported mode.*/ + ret = CRYS_HASH_Init(&sha256->ctx, CRYS_HASH_SHA256_mode); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("Error CRYS_HASH_Init failed"); + } + + return ret; +} + +int wc_InitSha256(Sha256* sha256) +{ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); +} + +int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) +{ + CRYSError_t ret = 0; + size_t length; + size_t remaining = len; + byte const * p_cur = data; + + if (sha256 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + + /* If the input is larger than CC310_MAX_LENGTH_DMA, split into smaller */ + do { + length = (remaining > CC310_MAX_LENGTH_DMA) ? + CC310_MAX_LENGTH_DMA : remaining; + + ret = CRYS_HASH_Update(&sha256->ctx, (uint8_t *)p_cur, length); + + remaining -= length; + p_cur += length; + + } while (ret == CRYS_OK && remaining > 0); + + return ret; +} + +int wc_Sha256Final(wc_Sha256* sha256, byte* hash) +{ + CRYSError_t ret = 0; + CRYS_HASH_Result_t hashResult; + + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = CRYS_HASH_Finish(&sha256->ctx, hashResult); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("Error CRYS_HASH_Finish failed"); + return ret; + } + XMEMCPY(sha256->digest, hashResult, WC_SHA256_DIGEST_SIZE); + + XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE); + + /* reset state */ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); +} + +void wc_Sha256Free(wc_Sha256* sha256) +{ + if (sha256 == NULL) + return; +} + +#endif /* !NO_SHA256 && WOLFSSL_CRYPTOCELL */ +#endif /* WOLFSSL_CRYPTOCELL_HASH_C */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/atmel/README.md b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/atmel/README.md new file mode 100644 index 000000000..50352fcd2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/atmel/README.md @@ -0,0 +1,94 @@ +# Microchip/Atmel ATECC508A/ATECC608A Support + +Support for ATECC508A using these methods: +* TLS: Using the PK callbacks and reference ATECC508A callbacks. See Coding section below. Requires options `HAVE_PK_CALLBACKS` and `WOLFSSL_ATECC_PKCB or WOLFSSL_ATECC508A` +* wolfCrypt: Native wc_ecc_* API's using the `./configure CFLAGS="-DWOLFSSL_ATECC508A"` or `#define WOLFSSL_ATECC508A`. + +## Dependency + +Requires the Microchip CryptoAuthLib. The examples in `wolfcrypt/src/port/atmel/atmel.c` make calls to the `atcatls_*` API's. + + +## Building + +### Build Options + +* `HAVE_PK_CALLBACKS`: Option for enabling wolfSSL's PK callback support for TLS. +* `WOLFSSL_ATECC508A`: Enables support for initializing the CryptoAuthLib and setting up the encryption key used for the I2C communication. +* `WOLFSSL_ATECC_PKCB`: Enables support for the reference PK callbacks without init. +* `WOLFSSL_ATMEL`: Enables ASF hooks seeding random data using the `atmel_get_random_number` function. +* `WOLFSSL_ATMEL_TIME`: Enables the built-in `atmel_get_curr_time_and_date` function get getting time from ASF RTC. +* `ATECC_GET_ENC_KEY`: Macro to define your own function for getting the encryption key. +* `ATECC_SLOT_I2C_ENC`: Macro for the default encryption key slot. Can also get via the slot callback with `ATMEL_SLOT_ENCKEY`. +* `ATECC_MAX_SLOT`: Macro for the maximum dynamically allocated slots. + +### Build Command Examples + +`./configure --enable-pkcallbacks CFLAGS="-DWOLFSSL_ATECC_PKCB"` +`#define HAVE_PK_CALLBACKS` +`#define WOLFSSL_ATECC_PKCB` + +or + +`./configure CFLAGS="-DWOLFSSL_ATECC508A"` +`#define WOLFSSL_ATECC508A` + + +## Coding + +Setup the PK callbacks for TLS using: + +``` +/* Setup PK Callbacks for ATECC508A */ +WOLFSSL_CTX* ctx; +wolfSSL_CTX_SetEccKeyGenCb(ctx, atcatls_create_key_cb); +wolfSSL_CTX_SetEccVerifyCb(ctx, atcatls_verify_signature_cb); +wolfSSL_CTX_SetEccSignCb(ctx, atcatls_sign_certificate_cb); +wolfSSL_CTX_SetEccSharedSecretCb(ctx, atcatls_create_pms_cb); +``` + +The reference ATECC508A PK callback functions are located in the `wolfcrypt/src/port/atmel/atmel.c` file. + + +Adding a custom context to the callbacks: + +``` +/* Setup PK Callbacks context */ +WOLFSSL* ssl; +void* myOwnCtx; +wolfSSL_SetEccKeyGenCtx(ssl, myOwnCtx); +wolfSSL_SetEccVerifyCtx(ssl, myOwnCtx); +wolfSSL_SetEccSignCtx(ssl, myOwnCtx); +wolfSSL_SetEccSharedSecretCtx(ssl, myOwnCtx); +``` + +## Benchmarks + +Supports ECC SECP256R1 (NIST P-256) + +### TLS + +TLS Establishment Times: + +* Hardware accelerated ATECC508A: 2.342 seconds average +* Software only: 13.422 seconds average + +The TLS connection establishment time is 5.73 times faster with the ATECC508A. + +### Cryptographic ECC + +Software only implementation (SAMD21 48Mhz Cortex-M0, Fast Math TFM-ASM): + +`EC-DHE key generation 3123.000 milliseconds, avg over 5 iterations, 1.601 ops/sec` +`EC-DHE key agreement 3117.000 milliseconds, avg over 5 iterations, 1.604 ops/sec` +`EC-DSA sign time 1997.000 milliseconds, avg over 5 iterations, 2.504 ops/sec` +`EC-DSA verify time 5057.000 milliseconds, avg over 5 iterations, 0.988 ops/sec` + +ATECC508A HW accelerated implementation: +`EC-DHE key generation 144.400 milliseconds, avg over 5 iterations, 34.722 ops/sec` +`EC-DHE key agreement 134.200 milliseconds, avg over 5 iterations, 37.313 ops/sec` +`EC-DSA sign time 293.400 milliseconds, avg over 5 iterations, 17.065 ops/sec` +`EC-DSA verify time 208.400 milliseconds, avg over 5 iterations, 24.038 ops/sec` + + +For details see our [wolfSSL Atmel ATECC508A](https://wolfssl.com/wolfSSL/wolfssl-atmel.html) page. diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/atmel/atmel.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/atmel/atmel.c new file mode 100644 index 000000000..04d2aeb3d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/atmel/atmel.c @@ -0,0 +1,843 @@ +/* atmel.c + * + * Copyright (C) 2006-2020 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_ATMEL) || defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC_PKCB) + +#include +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef WOLFSSL_ATMEL +/* remap name conflicts */ +#define Aes Aes_Remap +#define Gmac Gmac_Remap +#include "asf.h" +#undef Aes +#undef Gmac +#endif /* WOLFSSL_ATMEL */ + +#include + +#ifdef WOLFSSL_ATECC508A + +#ifdef WOLFSSL_ATECC508A_TLS + extern ATCA_STATUS device_init_default(void); +#endif + +static int mAtcaInitDone = 0; + +/* ATECC slotId handling */ +static atmel_slot_alloc_cb mSlotAlloc; +static atmel_slot_dealloc_cb mSlotDealloc; +static byte mSlotList[ATECC_MAX_SLOT]; +#ifndef SINGLE_THREADED +static wolfSSL_Mutex mSlotMutex; +#endif + +/* Raspberry Pi uses /dev/i2c-1 */ +#ifndef ATECC_I2C_ADDR +#define ATECC_I2C_ADDR 0xC0 +#endif +#ifndef ATECC_I2C_BUS +#define ATECC_I2C_BUS 1 +#endif +#ifndef ATECC_DEV_TYPE +#define ATECC_DEV_TYPE ATECC508A +#endif +static ATCAIfaceCfg cfg_ateccx08a_i2c_pi; +#endif /* WOLFSSL_ATECC508A */ + + +/** + * \brief Generate random number to be used for hash. + */ +int atmel_get_random_number(uint32_t count, uint8_t* rand_out) +{ + int ret = 0; +#ifdef WOLFSSL_ATECC508A + uint8_t i = 0; + uint32_t copy_count = 0; + uint8_t rng_buffer[RANDOM_NUM_SIZE]; + + if (rand_out == NULL) { + return -1; + } + + while (i < count) { + ret = atcab_random(rng_buffer); + if (ret != ATCA_SUCCESS) { + WOLFSSL_MSG("Failed to create random number!"); + return -1; + } + copy_count = (count - i > RANDOM_NUM_SIZE) ? RANDOM_NUM_SIZE : count - i; + XMEMCPY(&rand_out[i], rng_buffer, copy_count); + i += copy_count; + } + #ifdef ATCAPRINTF + atcab_printbin_label((const char*)"\r\nRandom Number", rand_out, count); + #endif +#else + /* TODO: Use on-board TRNG */ +#endif + return ret; +} + +int atmel_get_random_block(unsigned char* output, unsigned int sz) +{ + return atmel_get_random_number((uint32_t)sz, (uint8_t*)output); +} + +#if defined(WOLFSSL_ATMEL) && defined(WOLFSSL_ATMEL_TIME) +#include "asf.h" +#include "rtc_calendar.h" +extern struct rtc_module *_rtc_instance[RTC_INST_NUM]; + +long atmel_get_curr_time_and_date(long* tm) +{ + long rt = 0; + + /* Get current time */ + struct rtc_calendar_time rtcTime; + const int monthDay[] = {0,31,59,90,120,151,181,212,243,273,304,334}; + int month, year, yearLeap; + + rtc_calendar_get_time(_rtc_instance[0], &rtcTime); + + /* Convert rtc_calendar_time to seconds since UTC */ + month = rtcTime.month % 12; + year = rtcTime.year + rtcTime.month / 12; + if (month < 0) { + month += 12; + year--; + } + yearLeap = (month > 1) ? year + 1 : year; + rt = rtcTime.second + + 60 * (rtcTime.minute + + 60 * (rtcTime.hour + + 24 * (monthDay[month] + rtcTime.day - 1 + + 365 * (year - 70) + + (yearLeap - 69) / 4 + - (yearLeap - 1) / 100 + + (yearLeap + 299) / 400 + ) + ) + ); + + (void)tm; + return rt; +} +#endif + + +#ifdef WOLFSSL_ATECC508A + +int atmel_ecc_translate_err(int status) +{ + switch (status) { + case ATCA_SUCCESS: + return 0; + case ATCA_BAD_PARAM: + return BAD_FUNC_ARG; + case ATCA_ALLOC_FAILURE: + return MEMORY_E; + default: + #ifdef WOLFSSL_ATECC508A_DEBUG + printf("ATECC Failure: %x\n", (word32)status); + #endif + break; + } + return WC_HW_E; +} + +/* Function to set the slotId allocator and deallocator */ +int atmel_set_slot_allocator(atmel_slot_alloc_cb alloc, + atmel_slot_dealloc_cb dealloc) +{ +#ifndef SINGLE_THREADED + wc_LockMutex(&mSlotMutex); +#endif + mSlotAlloc = alloc; + mSlotDealloc = dealloc; +#ifndef SINGLE_THREADED + wc_UnLockMutex(&mSlotMutex); +#endif + return 0; +} + +/* Function to allocate new slotId number */ +int atmel_ecc_alloc(int slotType) +{ + int slotId = ATECC_INVALID_SLOT, i; + +#ifndef SINGLE_THREADED + wc_LockMutex(&mSlotMutex); +#endif + + if (mSlotAlloc) { + slotId = mSlotAlloc(slotType); + } + else { + switch (slotType) { + case ATMEL_SLOT_ENCKEY: + /* not reserved in mSlotList, so return */ + slotId = ATECC_SLOT_I2C_ENC; + goto exit; + case ATMEL_SLOT_DEVICE: + /* not reserved in mSlotList, so return */ + slotId = ATECC_SLOT_AUTH_PRIV; + goto exit; + case ATMEL_SLOT_ECDHE: + slotId = ATECC_SLOT_ECDHE_PRIV; + break; + case ATMEL_SLOT_ECDHE_ENC: + slotId = ATECC_SLOT_ENC_PARENT; + break; + case ATMEL_SLOT_ANY: + for (i=0; i < ATECC_MAX_SLOT; i++) { + /* Find free slotId */ + if (mSlotList[i] == ATECC_INVALID_SLOT) { + slotId = i; + break; + } + } + break; + } + + /* is slot available */ + if (mSlotList[slotId] != ATECC_INVALID_SLOT) { + slotId = ATECC_INVALID_SLOT; + } + else { + mSlotList[slotId] = slotId; + } + } + +exit: +#ifndef SINGLE_THREADED + wc_UnLockMutex(&mSlotMutex); +#endif + + return slotId; +} + + +/* Function to return slotId number to available list */ +void atmel_ecc_free(int slotId) +{ +#ifndef SINGLE_THREADED + wc_LockMutex(&mSlotMutex); +#endif + if (mSlotDealloc) { + mSlotDealloc(slotId); + } + else if (slotId >= 0 && slotId < ATECC_MAX_SLOT) { + if (slotId != ATECC_SLOT_AUTH_PRIV && slotId != ATECC_SLOT_I2C_ENC) { + /* Mark slotId free */ + mSlotList[slotId] = ATECC_INVALID_SLOT; + } + } +#ifndef SINGLE_THREADED + wc_UnLockMutex(&mSlotMutex); +#endif +} + + +/** + * \brief Callback function for getting the current encryption key + */ +int atmel_get_enc_key_default(byte* enckey, word16 keysize) +{ + if (enckey == NULL || keysize != ATECC_KEY_SIZE) { + return BAD_FUNC_ARG; + } + + XMEMSET(enckey, 0xFF, keysize); /* use default value */ + + return 0; +} + +/** + * \brief Write enc key before. + */ +static int atmel_init_enc_key(void) +{ + int ret; + uint8_t read_key[ATECC_KEY_SIZE]; + uint8_t writeBlock = 0; + uint8_t writeOffset = 0; + int slotId; + + slotId = atmel_ecc_alloc(ATMEL_SLOT_ENCKEY); + + /* check for encryption key slotId */ + if (slotId == ATECC_INVALID_SLOT) + return BAD_FUNC_ARG; + + /* get encryption key */ + ATECC_GET_ENC_KEY(read_key, sizeof(read_key)); + + ret = atcab_write_zone(ATCA_ZONE_DATA, slotId, writeBlock, writeOffset, + read_key, ATCA_BLOCK_SIZE); + ForceZero(read_key, sizeof(read_key)); + ret = atmel_ecc_translate_err(ret); + + return ret; +} + +int atmel_get_rev_info(word32* revision) +{ + int ret; + ret = atcab_info((uint8_t*)revision); + ret = atmel_ecc_translate_err(ret); + return ret; +} + +void atmel_show_rev_info(void) +{ +#ifdef WOLFSSL_ATECC508A_DEBUG + word32 revision = 0; + atmel_get_rev_info(&revision); + printf("ATECC508A Revision: %x\n", (word32)revision); +#endif +} + +int atmel_ecc_create_pms(int slotId, const uint8_t* peerKey, uint8_t* pms) +{ + int ret; + uint8_t read_key[ATECC_KEY_SIZE]; + int slotIdEnc; + + slotIdEnc = atmel_ecc_alloc(ATMEL_SLOT_ECDHE_ENC); + if (slotIdEnc == ATECC_INVALID_SLOT) + return BAD_FUNC_ARG; + + /* get encryption key */ + ATECC_GET_ENC_KEY(read_key, sizeof(read_key)); + + /* send the encrypted version of the ECDH command */ + ret = atcab_ecdh_enc(slotId, peerKey, pms, read_key, slotIdEnc); + ret = atmel_ecc_translate_err(ret); + + /* free the ECDHE slot */ + atmel_ecc_free(slotIdEnc); + + return ret; +} + +int atmel_ecc_create_key(int slotId, byte* peerKey) +{ + int ret; + + /* verify provided slotId */ + if (slotId == ATECC_INVALID_SLOT) { + return WC_HW_WAIT_E; + } + + /* generate new ephemeral key on device */ + ret = atcab_genkey(slotId, peerKey); + ret = atmel_ecc_translate_err(ret); + return ret; +} + +int atmel_ecc_sign(int slotId, const byte* message, byte* signature) +{ + int ret; + + ret = atcab_sign(slotId, message, signature); + ret = atmel_ecc_translate_err(ret); + return ret; +} + +int atmel_ecc_verify(const byte* message, const byte* signature, + const byte* pubkey, int* verified) +{ + int ret; + + ret = atcab_verify_extern(message, signature, pubkey, (bool*)verified); + ret = atmel_ecc_translate_err(ret); + return ret; +} + +#endif /* WOLFSSL_ATECC508A */ + + + +int atmel_init(void) +{ + int ret = 0; + +#ifdef WOLFSSL_ATECC508A + if (!mAtcaInitDone) { + ATCA_STATUS status; + int i; + + #ifndef SINGLE_THREADED + wc_InitMutex(&mSlotMutex); + #endif + + /* Init the free slotId list */ + for (i=0; islot = slotId; + } + else { + atmel_ecc_free(slotId); + #ifdef WOLFSSL_ATECC508A_DEBUG + printf("atcatls_create_key_cb: ret %d\n", ret); + #endif + } + } + else { + #ifndef WOLFSSL_ATECC508A_NOSOFTECC + /* use software for non P-256 cases */ + WC_RNG rng; + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_make_key_ex(&rng, keySz, key, ecc_curve); + wc_FreeRng(&rng); + } + #else + ret = NOT_COMPILED_IN; + #endif /* !WOLFSSL_ATECC508A_NOSOFTECC */ + } + return ret; +} + +/** + * \brief Creates a shared secret using a peer public key and a device key + */ +int atcatls_create_pms_cb(WOLFSSL* ssl, ecc_key* otherKey, + unsigned char* pubKeyDer, word32* pubKeySz, + unsigned char* out, word32* outlen, + int side, void* ctx) +{ + int ret; + ecc_key tmpKey; + uint8_t peerKeyBuf[ATECC_PUBKEY_SIZE]; + uint8_t* peerKey = peerKeyBuf; + uint8_t* qx = &peerKey[0]; + uint8_t* qy = &peerKey[ATECC_PUBKEY_SIZE/2]; + word32 qxLen = ATECC_PUBKEY_SIZE/2, qyLen = ATECC_PUBKEY_SIZE/2; + + if (pubKeyDer == NULL || pubKeySz == NULL || out == NULL || outlen == NULL) { + return BAD_FUNC_ARG; + } + + (void)ssl; + (void)ctx; + (void)otherKey; + + ret = wc_ecc_init(&tmpKey); + if (ret != 0) { + return ret; + } + + /* ATECC508A only supports P-256 */ + if (otherKey->dp->id == ECC_SECP256R1) { + XMEMSET(peerKey, 0, ATECC_PUBKEY_SIZE); + + /* for client: create and export public key */ + if (side == WOLFSSL_CLIENT_END) { + int slotId = atmel_ecc_alloc(ATMEL_SLOT_ECDHE); + if (slotId == ATECC_INVALID_SLOT) + return WC_HW_WAIT_E; + tmpKey.slot = slotId; + + /* generate new ephemeral key on device */ + ret = atmel_ecc_create_key(slotId, peerKey); + if (ret != ATCA_SUCCESS) { + goto exit; + } + + /* convert raw unsigned public key to X.963 format for TLS */ + ret = wc_ecc_import_unsigned(&tmpKey, qx, qy, NULL, ECC_SECP256R1); + if (ret == 0) { + ret = wc_ecc_export_x963(&tmpKey, pubKeyDer, pubKeySz); + } + + /* export peer's key as raw unsigned for hardware */ + if (ret == 0) { + ret = wc_ecc_export_public_raw(otherKey, qx, &qxLen, qy, &qyLen); + } + } + + /* for server: import public key */ + else if (side == WOLFSSL_SERVER_END) { + tmpKey.slot = otherKey->slot; + + /* import peer's key and export as raw unsigned for hardware */ + ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, &tmpKey, ECC_SECP256R1); + if (ret == 0) { + ret = wc_ecc_export_public_raw(&tmpKey, qx, &qxLen, qy, &qyLen); + } + } + else { + ret = BAD_FUNC_ARG; + } + + if (ret != 0) { + goto exit; + } + + ret = atmel_ecc_create_pms(tmpKey.slot, peerKey, out); + *outlen = ATECC_KEY_SIZE; + + #ifndef WOLFSSL_ATECC508A_NOIDLE + /* put chip into idle to prevent watchdog situation on chip */ + atcab_idle(); + #endif + + (void)qxLen; + (void)qyLen; + } + else { + #ifndef WOLFSSL_ATECC508A_NOSOFTECC + /* use software for non P-256 cases */ + ecc_key* privKey = NULL; + ecc_key* pubKey = NULL; + + /* 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_ecc_make_key_ex(&rng, 0, privKey, otherKey->dp->id); + if (ret == 0) { + ret = wc_ecc_export_x963(privKey, pubKeyDer, pubKeySz); + } + wc_FreeRng(&rng); + } + } + /* for server: import public key */ + else if (side == WOLFSSL_SERVER_END) { + privKey = otherKey; + pubKey = &tmpKey; + + ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, pubKey, + otherKey->dp->id); + } + else { + ret = BAD_FUNC_ARG; + } + + /* generate shared secret and return it */ + if (ret == 0) { + ret = wc_ecc_shared_secret(privKey, pubKey, out, outlen); + } + #else + ret = NOT_COMPILED_IN; + #endif /* !WOLFSSL_ATECC508A_NOSOFTECC */ + } + +exit: + wc_ecc_free(&tmpKey); + +#ifdef WOLFSSL_ATECC508A_DEBUG + if (ret != 0) { + printf("atcab_ecdh_enc: ret %d\n", ret); + } +#endif + + return ret; +} + + +/** + * \brief Sign received digest using private key on device + */ +int atcatls_sign_certificate_cb(WOLFSSL* ssl, const byte* in, unsigned int inSz, + byte* out, word32* outSz, const byte* key, unsigned int keySz, void* ctx) +{ + int ret; + byte sigRs[ATECC_SIG_SIZE]; + int slotId; + + (void)ssl; + (void)inSz; + (void)key; + (void)keySz; + (void)ctx; + + if (in == NULL || out == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + slotId = atmel_ecc_alloc(ATMEL_SLOT_DEVICE); + if (slotId == ATECC_INVALID_SLOT) + return WC_HW_WAIT_E; + + /* We can only sign with P-256 */ + ret = atmel_ecc_sign(slotId, in, sigRs); + if (ret != ATCA_SUCCESS) { + ret = WC_HW_E; goto exit; + } + +#ifndef WOLFSSL_ATECC508A_NOIDLE + /* put chip into idle to prevent watchdog situation on chip */ + atcab_idle(); +#endif + + /* Encode with ECDSA signature */ + ret = wc_ecc_rs_raw_to_sig( + &sigRs[0], ATECC_SIG_SIZE/2, + &sigRs[ATECC_SIG_SIZE/2], ATECC_SIG_SIZE/2, + out, outSz); + if (ret != 0) { + goto exit; + } + +exit: + + atmel_ecc_free(slotId); + +#ifdef WOLFSSL_ATECC508A_DEBUG + if (ret != 0) { + printf("atcatls_sign_certificate_cb: ret %d\n", ret); + } +#endif + + return ret; +} + +/** + * \brief Verify signature received from peers to prove peer's private key. + */ +int atcatls_verify_signature_cb(WOLFSSL* ssl, const byte* sig, unsigned int sigSz, + const byte* hash, unsigned int hashSz, const byte* key, unsigned int keySz, int* result, + void* ctx) +{ + int ret; + ecc_key tmpKey; + word32 idx = 0; + uint8_t peerKey[ATECC_PUBKEY_SIZE]; + uint8_t* qx = &peerKey[0]; + uint8_t* qy = &peerKey[ATECC_PUBKEY_SIZE/2]; + word32 qxLen = ATECC_PUBKEY_SIZE/2, qyLen = ATECC_PUBKEY_SIZE/2; + byte sigRs[ATECC_SIG_SIZE]; + word32 rSz = ATECC_SIG_SIZE/2; + word32 sSz = ATECC_SIG_SIZE/2; + + (void)sigSz; + (void)hashSz; + (void)ctx; + + if (ssl == NULL || key == NULL || sig == NULL || hash == NULL || result == NULL) { + return BAD_FUNC_ARG; + } + + /* import public key */ + ret = wc_ecc_init(&tmpKey); + if (ret == 0) { + ret = wc_EccPublicKeyDecode(key, &idx, &tmpKey, keySz); + } + if (ret != 0) { + goto exit; + } + + if (tmpKey.dp->id == ECC_SECP256R1) { + /* export public as unsigned bin for hardware */ + ret = wc_ecc_export_public_raw(&tmpKey, qx, &qxLen, qy, &qyLen); + wc_ecc_free(&tmpKey); + if (ret != 0) { + goto exit; + } + + /* decode the ECDSA signature */ + ret = wc_ecc_sig_to_rs(sig, sigSz, + &sigRs[0], &rSz, + &sigRs[ATECC_SIG_SIZE/2], &sSz); + if (ret != 0) { + goto exit; + } + + ret = atmel_ecc_verify(hash, sigRs, peerKey, result); + if (ret != ATCA_SUCCESS || !*result) { + ret = WC_HW_E; goto exit; + } + + #ifndef WOLFSSL_ATECC508A_NOIDLE + /* put chip into idle to prevent watchdog situation on chip */ + atcab_idle(); + #endif + } + else { + #ifndef WOLFSSL_ATECC508A_NOSOFTECC + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, result, &tmpKey); + #else + ret = NOT_COMPILED_IN; + #endif /* !WOLFSSL_ATECC508A_NOSOFTECC */ + } + + (void)rSz; + (void)sSz; + (void)qxLen; + (void)qyLen; + + ret = 0; /* success */ + +exit: + +#ifdef WOLFSSL_ATECC508A_DEBUG + if (ret != 0) { + printf("atcatls_verify_signature_cb: ret %d\n", ret); + } +#endif + + return ret; +} + +int atcatls_set_callbacks(WOLFSSL_CTX* ctx) +{ + wolfSSL_CTX_SetEccKeyGenCb(ctx, atcatls_create_key_cb); + wolfSSL_CTX_SetEccVerifyCb(ctx, atcatls_verify_signature_cb); + wolfSSL_CTX_SetEccSignCb(ctx, atcatls_sign_certificate_cb); + wolfSSL_CTX_SetEccSharedSecretCb(ctx, atcatls_create_pms_cb); + return 0; +} + +int atcatls_set_callback_ctx(WOLFSSL* ssl, void* user_ctx) +{ + wolfSSL_SetEccKeyGenCtx(ssl, user_ctx); + wolfSSL_SetEccVerifyCtx(ssl, user_ctx); + wolfSSL_SetEccSignCtx(ssl, user_ctx); + wolfSSL_SetEccSharedSecretCtx(ssl, user_ctx); + return 0; +} + + +#endif /* HAVE_PK_CALLBACKS */ + +#endif /* WOLFSSL_ATMEL || WOLFSSL_ATECC508A || WOLFSSL_ATECC_PKCB */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_aes.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_aes.c new file mode 100644 index 000000000..e00214df3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_aes.c @@ -0,0 +1,649 @@ +/* caam_aes.c + * + * Copyright (C) 2006-2020 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 + */ + + +#include + +#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_AES) && \ + !defined(NO_IMX6_CAAM_AES) + +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#include +#include + +#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) +#include +#endif + +int wc_AesSetKey(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir) +{ + int ret; + + if (aes == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + if (len > 32) { + byte out[32]; /* max AES key size */ + word32 outSz; + int ret; + + if (len != 64 && len != 72 && len != 80) { + return BAD_FUNC_ARG; + } + + outSz = sizeof(out); + /* if length greater then 32 then try to unencapsulate */ + if ((ret = wc_caamOpenBlob((byte*)key, len, out, &outSz)) != 0) { + return ret; + } + + XMEMCPY((byte*)aes->key, out, outSz); + aes->keylen = outSz; + } + else { + if (len != 16 && len != 24 && len != 32) { + return BAD_FUNC_ARG; + } + + XMEMCPY((byte*)aes->key, key, len); + aes->keylen = len; + } + + switch (aes->keylen) { + case 16: aes->rounds = 10; break; + case 24: aes->rounds = 12; break; + case 32: aes->rounds = 14; break; + default: + return BAD_FUNC_ARG; + } + + if ((ret = wc_AesSetIV(aes, iv)) != 0) { + return ret; + } + +#ifdef WOLFSSL_AES_COUNTER + aes->left = 0; +#endif + + return 0; +} + + +int wc_AesCbcEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + word32 blocks; + + WOLFSSL_ENTER("wc_AesCbcEncrypt"); + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + blocks = sz / AES_BLOCK_SIZE; + + if (blocks > 0) { + Buffer buf[4]; + word32 arg[4]; + word32 keySz; + int ret; + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + return BAD_FUNC_ARG; + } + + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)aes->reg; + buf[1].Length = AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer; + buf[2].TheAddress = (Address)in; + buf[2].Length = blocks * AES_BLOCK_SIZE; + + buf[3].BufferType = DataBuffer | LastBuffer; + buf[3].TheAddress = (Address)out; + buf[3].Length = blocks * AES_BLOCK_SIZE; + + arg[0] = CAAM_ENC; + arg[1] = keySz; + arg[2] = blocks * AES_BLOCK_SIZE; + + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCBC)) != 0) { + WOLFSSL_MSG("Error with CAAM AES CBC encrypt"); + return ret; + } + } + + return 0; +} + + +int wc_AesCbcDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + word32 blocks; + + WOLFSSL_ENTER("wc_AesCbcDecrypt"); + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + blocks = sz / AES_BLOCK_SIZE; + + if (blocks > 0) { + Buffer buf[4]; + word32 arg[4]; + word32 keySz; + int ret; + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + return BAD_FUNC_ARG; + } + + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)aes->reg; + buf[1].Length = AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer; + buf[2].TheAddress = (Address)in; + buf[2].Length = blocks * AES_BLOCK_SIZE; + + buf[3].BufferType = DataBuffer | LastBuffer; + buf[3].TheAddress = (Address)out; + buf[3].Length = blocks * AES_BLOCK_SIZE; + + arg[0] = CAAM_DEC; + arg[1] = keySz; + arg[2] = blocks * AES_BLOCK_SIZE; + + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCBC)) != 0) { + WOLFSSL_MSG("Error with CAAM AES CBC decrypt"); + return ret; + } + } + + return 0; +} + +#if defined(HAVE_AES_ECB) +/* is assumed that input size is a multiple of AES_BLOCK_SIZE */ +int wc_AesEcbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + word32 blocks; + Buffer buf[3]; + word32 arg[4]; + word32 keySz; + int ret; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + blocks = sz / AES_BLOCK_SIZE; + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + return BAD_FUNC_ARG; + } + + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)in; + buf[1].Length = blocks * AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer | LastBuffer; + buf[2].TheAddress = (Address)out; + buf[2].Length = blocks * AES_BLOCK_SIZE; + + arg[0] = CAAM_ENC; + arg[1] = keySz; + arg[2] = blocks * AES_BLOCK_SIZE; + + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESECB)) != 0) { + WOLFSSL_MSG("Error with CAAM AES ECB encrypt"); + return ret; + } + + return 0; +} + + +int wc_AesEcbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + word32 blocks; + Buffer buf[3]; + word32 arg[4]; + word32 keySz; + int ret; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + blocks = sz / AES_BLOCK_SIZE; + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + return BAD_FUNC_ARG; + } + + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)in; + buf[1].Length = blocks * AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer | LastBuffer; + buf[2].TheAddress = (Address)out; + buf[2].Length = blocks * AES_BLOCK_SIZE; + + arg[0] = CAAM_DEC; + arg[1] = keySz; + arg[2] = blocks * AES_BLOCK_SIZE; + + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESECB)) != 0) { + WOLFSSL_MSG("Error with CAAM AES ECB decrypt"); + return ret; + } + + return 0; +} +#endif + +/* AES-CTR */ +#ifdef WOLFSSL_AES_COUNTER +/* Increment AES counter (from wolfcrypt/src/aes.c) */ +static WC_INLINE void IncrementAesCounter(byte* inOutCtr) +{ + /* 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; + } +} + + +int wc_AesCtrEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + byte* tmp; + Buffer buf[4]; + word32 arg[4]; + word32 keySz; + int ret, blocks; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + 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--; + sz--; + } + + /* do full blocks to then get potential left over amount */ + blocks = sz / AES_BLOCK_SIZE; + if (blocks > 0) { + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)aes->reg; + buf[1].Length = AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer; + buf[2].TheAddress = (Address)in; + buf[2].Length = blocks * AES_BLOCK_SIZE; + + buf[3].BufferType = DataBuffer | LastBuffer; + buf[3].TheAddress = (Address)out; + buf[3].Length = blocks * AES_BLOCK_SIZE; + + arg[0] = CAAM_ENC; + arg[1] = keySz; + arg[2] = blocks * AES_BLOCK_SIZE; + + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCTR)) != 0) { + WOLFSSL_MSG("Error with CAAM AES CTR encrypt"); + return ret; + } + + out += blocks * AES_BLOCK_SIZE; + in += blocks * AES_BLOCK_SIZE; + sz -= blocks * AES_BLOCK_SIZE; + } + + if (sz) { + wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg); + IncrementAesCounter((byte*)aes->reg); + + aes->left = AES_BLOCK_SIZE; + tmp = (byte*)aes->tmp; + + while (sz--) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + } + } + + return 0; +} +#endif + + +/* AES-DIRECT */ +#if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) +void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) +{ + Buffer buf[3]; + word32 arg[4]; + word32 keySz; + + if (aes == NULL || out == NULL || in == NULL) { + /* return BAD_FUNC_ARG; */ + return; + } + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + /* return BAD_FUNC_ARG; */ + return; + } + + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)in; + buf[1].Length = AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer | LastBuffer; + buf[2].TheAddress = (Address)out; + buf[2].Length = AES_BLOCK_SIZE; + + arg[0] = CAAM_ENC; + arg[1] = keySz; + arg[2] = AES_BLOCK_SIZE; + + if (wc_caamAddAndWait(buf, arg, CAAM_AESECB) != 0) { + WOLFSSL_MSG("Error with CAAM AES direct encrypt"); + } +} + + +void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) +{ + Buffer buf[3]; + word32 arg[4]; + word32 keySz; + + if (aes == NULL || out == NULL || in == NULL) { + /* return BAD_FUNC_ARG; */ + return; + } + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + /* return BAD_FUNC_ARG; */ + return; + } + + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)in; + buf[1].Length = AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer | LastBuffer; + buf[2].TheAddress = (Address)out; + buf[2].Length = AES_BLOCK_SIZE; + + arg[0] = CAAM_DEC; + arg[1] = keySz; + arg[2] = AES_BLOCK_SIZE; + + if (wc_caamAddAndWait(buf, arg, CAAM_AESECB) != 0) { + WOLFSSL_MSG("Error with CAAM AES direct decrypt"); + } +} + + +int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir) +{ + return wc_AesSetKey(aes, key, len, iv, dir); +} +#endif + +#ifdef HAVE_AESCCM +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) +{ + Buffer buf[5]; + word32 arg[4]; + word32 keySz; + word32 i; + byte B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE]; + int lenSz; + byte mask = 0xFF; + const word32 wordSz = (word32)sizeof(word32); + int ret; + + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13 || + authTagSz > AES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + return BAD_FUNC_ARG; + } + + /* set up B0 and CTR0 similar to how wolfcrypt/src/aes.c does */ + XMEMCPY(B0Ctr0+1, nonce, nonceSz); + XMEMCPY(B0Ctr0+AES_BLOCK_SIZE+1, nonce, nonceSz); + lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz; + B0Ctr0[0] = (authInSz > 0 ? 64 : 0) + + (8 * (((byte)authTagSz - 2) / 2)) + + (lenSz - 1); + for (i = 0; i < lenSz; i++) { + if (mask && i >= wordSz) + mask = 0x00; + B0Ctr0[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask; + B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE - 1 - i] = 0; + } + B0Ctr0[AES_BLOCK_SIZE] = lenSz - 1; + + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)B0Ctr0; + buf[1].Length = AES_BLOCK_SIZE + AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer; + buf[2].TheAddress = (Address)authIn; + buf[2].Length = authInSz; + + buf[3].BufferType = DataBuffer; + buf[3].TheAddress = (Address)in; + buf[3].Length = inSz; + + buf[4].BufferType = DataBuffer | LastBuffer; + buf[4].TheAddress = (Address)out; + buf[4].Length = inSz; + + arg[0] = CAAM_ENC; + arg[1] = keySz; + arg[2] = inSz; + arg[3] = authInSz; + + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCCM)) != 0) { + WOLFSSL_MSG("Error with CAAM AES-CCM encrypt"); + return ret; + } + + XMEMCPY(authTag, B0Ctr0, authTagSz); + return 0; +} + + +#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) +{ + Buffer buf[5]; + word32 arg[4]; + word32 keySz; + word32 i; + byte B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE]; + byte tag[AES_BLOCK_SIZE]; + int lenSz; + byte mask = 0xFF; + const word32 wordSz = (word32)sizeof(word32); + int ret; + + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13 || + authTagSz > AES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + if (wc_AesGetKeySize(aes, &keySz) != 0) { + return BAD_FUNC_ARG; + } + + /* set up B0 and CTR0 similar to how wolfcrypt/src/aes.c does */ + XMEMCPY(B0Ctr0+1, nonce, nonceSz); + XMEMCPY(B0Ctr0+AES_BLOCK_SIZE+1, nonce, nonceSz); + lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz; + B0Ctr0[0] = (authInSz > 0 ? 64 : 0) + + (8 * (((byte)authTagSz - 2) / 2)) + + (lenSz - 1); + for (i = 0; i < lenSz; i++) { + if (mask && i >= wordSz) + mask = 0x00; + B0Ctr0[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask; + B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE - 1 - i] = 0; + } + B0Ctr0[AES_BLOCK_SIZE] = lenSz - 1; + wc_AesEncryptDirect(aes, tag, B0Ctr0 + AES_BLOCK_SIZE); + + /* Set buffers for key, cipher text, and plain text */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)aes->key; + buf[0].Length = keySz; + + buf[1].BufferType = DataBuffer; + buf[1].TheAddress = (Address)B0Ctr0; + buf[1].Length = AES_BLOCK_SIZE + AES_BLOCK_SIZE; + + buf[2].BufferType = DataBuffer; + buf[2].TheAddress = (Address)authIn; + buf[2].Length = authInSz; + + buf[3].BufferType = DataBuffer; + buf[3].TheAddress = (Address)in; + buf[3].Length = inSz; + + buf[4].BufferType = DataBuffer | LastBuffer; + buf[4].TheAddress = (Address)out; + buf[4].Length = inSz; + + arg[0] = CAAM_DEC; + arg[1] = keySz; + arg[2] = inSz; + arg[3] = authInSz; + + if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCCM)) != 0) { + WOLFSSL_MSG("Error with CAAM AES-CCM derypt"); + return ret; + } + + xorbuf(tag, B0Ctr0, authTagSz); + if (ConstantCompare(tag, authTag, authTagSz) != 0) { + /* If the authTag check fails, don't keep the decrypted data. + * Unfortunately, you need the decrypted data to calculate the + * check value. */ + XMEMSET(out, 0, inSz); + ret = AES_CCM_AUTH_E; + } + + ForceZero(tag, AES_BLOCK_SIZE); + ForceZero(B0Ctr0, AES_BLOCK_SIZE * 2); + + return ret; + +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AESCCM */ + +#endif /* WOLFSSL_IMX6_CAAM && !NO_AES */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_doc.pdf b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_doc.pdf new file mode 100644 index 0000000000000000000000000000000000000000..821363441e4a33996276c6a3fbaeb5a64f4723ec GIT binary patch literal 1107370 zcmc$_2UwHMmN*`qiLMJ42Yy_l>NeCqbDWN13O(1maN--cHAYJJs5TpbQ zRp}imp@T^80@6YK2fzF6-rc?b=l9&b`|VC1GI{5nnRDj!IWq{|R@ab_kp!~}Rcs{v zWChFcOY^%}VOdpF_@#6moH3So2QQ2bzYOzx!Ut9Fju7E;OL6MGiygnSByHw+Qo+1>yP@jCEkg^zej|dE{<+a&IEqu zx^Ck!HV)RVE_i+!S>~enrI1WI$nb-he@rT9Ion`7m<>!4%E|uGVC%vUk!Rv@hhOTB zi;F8i81%;jj7d{|MbPgViGL##J~?WhYOrS$FsXP_ zugJz9w!rbqM%UzMq|^RTPbL1aOm=l`{lh_&C%3pD(j~!<0+uVR&-Usbs{N$F0suI$ z=It@|Z*%`|v-m&J>;K@9^*2BN)E0FN!Ii+TxF>f^e&4pV!w~o(3V%HPA%Hh6T`e75 z?EX$4z;ev@e@^fZ#Sz9YyQflrlUi9>`TxkxyLb0kNwvOfd3WTq-6^YwEYh*h9&y#% zn0&l^rT$1*0|h_g^U>Sm5o6Zcpw!Qot;4`d;r{KJkJbBu&)5)b9mlhj*m};fos^b- zZ;+^zPcCy^cWx<vm>jzGzV3e<06}Q|Cc*^mK zJRF7+z00T6RGM}!AdW4#Pr)*}Cu{0%S=v-=uwqMBV?ta1wF20~Yf;xfcCg+04#?%d z_0TZ>`opcttXT2%@EGnSNs8uNOg2^UK3t?$15;Kn4!rVgWpzH$MGe<%?-* z{+(pkot<5nL^u1bsW)8kHcWLkW4_<}FjaDoCHzwMk~Ut>7#s*J<3e<@VX8a798(`L z)~?L1^0NH03Lr@^Q=_H%WfkQl<-vOcVQyBgzikH71mc*c?Dy~A!1nZh&n*1^19KvH z%34|3SbAVB{}V77X$5{+IVKz#<{wx_lF8VA5tf1i-hpU)Pu9wj_>W-8DD1(IQB-6u zP*!&D`(K1dbYYr&h=QD(t)u6EA*75VWRH;2d*8Cs^8W**1lhR|oMhc>ZSdIt1a6O% zGV;IKB_l7-^f!=yb!k{?$DfXA%XPuXgoWeak2xE(PV~YRZ>i`o9lWV_aM26|hWTpQHIOlXv z9tXi%-@C8i$#ir78Jfax;gFR9?Lksh{C~5KDYiFVoLw=_Ol1fE&79$ zhDXbZ=>%^4t-krUT5AtOV*@Mfo&nlJ$XJ>m4EYm)s{mp?tl4F^}k zZ4CaVi_<+9=e?ye!!2f<;(~|Wv$Xyl!w?;;F?TeXuzxqh@s`d6TNk_&bB=$Ddem>i z|BQKVVI1u2UHRn|WdF|e{l@-JZ2m-83h7|OjGknqW%eS%KSC*xqP(2K-?^ncl* z%X#Ju51-IQ9$vxoXU_18^9u@#hyq2=U6hcPxFRidMfA$vB>N5@KFoTAm4lU);|k9i zo-6-!`SlUNeq{fN{onWR69BNV@7vG5?^iW|kBKA;%lA`TsO45&nX~Jcoh0BH!q*-tSlIUcMbd0 z-XRFOaR*^!^*SP{@(lM)82s_m@Pew#a@KB7zAizNg@ikonX~gU!Tv|sfP;tjA2|FQ zv>H1T*8Y754jemt;BTGwK(ilY0zP!z@IHrtEXa}x_EY;;PA<7Sut!U0Zdl>1lLRj> zKMwoV4`5^B%EG>%9dH%U`0CHK{dek9!v7X4Qmm*`&0w;9z7eCkJPYnA1=)7wLHr09@hF4J11(lU$Gy6xnfZAgh0s47!x_*h-I`i>fIlY4cJ(LNWuh@hg~;^$Vw`OY8_ z3@e`Ja0XnrI+YNbcZ;gK)>kB?hN_HpZGovIEPLJ5(3^Fv;o#XedJAYbe)!*^&A&26 z4nI0t*HF)^UPqePNmD1Ea&zVlWj8DZ3(hpkH&gBd1(2gZS>F#+UM z6Rd5R!&&cfJRMn?&R*ui;=eM5a2H7_n)_<|CQX&FqDxh}Sqh)*hd&REiy?KplLl1$ zHE>in#v&q{lHm8E454!L!^{(W5ZrLQ^7Kz<4b6C}-O%hffQ@u_j{&o^1JAE>dg6=>}6^t(y2Waw&GS>cqKd{6pSth zH*hpsQhyYyWIB({&u0ZgrlW(04d)_!{E~oV0by)v+x3T8u5|HNO?Or&VxZrJZ{4zA z=z?qg0vy#cIAp=7C4J|iIk5^hkYH!LKz>wtod5dnYpBrkIV1mq_1PktyK*4hfM;IS z%kl7oSP880SLj5T(GOO#`Q1-OpQ)bemz`FvFQ^nx`Wk+Rf41+KoR7p7Lwpc~sOA@V zRc=+-Vw6#OO?umAkQ{e9WOc1@X8PxGm6@K62-hL*kHLDlIC5OWX^{@^Hx`FKy;wYr zxQP&N_0c&)>G$^!%%K0A5j`B3=iI}iyX4r{rx1w?Txd_JOY^%6_!#=nvi85-U*)_( zKt|Rn-yx6wbYaIwlmRL2?;-|qYkDBmV&{3|9CT6*2Y!6!)Y=^IZF0KL8a|KPIGX+q z70O!2Im3dD_wp7lIJIcfV?D&!EcZ*2@Rwrr^d~?H(d}mo0!p}BQ?}g`w8X4gV^px4 zjZp=}A5Gf>b;}M5bBW<=i-bX{7bT7oL#ATMegGHB+r#)C$E;%bWjW4oG5Y54-eKBc z0>^l>I!>yf6G7nY5(PTobkhiS39?aCXZQ^WG3CR+^X{Q*q%dLI-wDHkrm=6ke}c%L!F^W(ZTE z!OF1#e3x@jgBy}q^8LrymO#ha*YtJ2_Of{NTEkZcpW*HT;1JOtf1NFYL-vZGPgofq z#}iG?xpATUT;*ENjG?6q*R7!NbT4A&=eW6FfJU=7-Y3lFZznqlbVtKPnt$ZDcf}vU zerZbTIf0Mr8{k=Y2~m^aD=Vuv;%Ofk?@HMGDN)i9173(4Qx4Bmu{Z9LgLiSZJPtnc z^;tOEb%%!@rS!zZN$JyJL9T!9r*IX9N>`f(#a@A?!YOafG`6wF3^+ZW>_<&{D3rA1ke8Hn|kt<$$*x)mwF=e1i zHNT0f`yB@(!y%Ph*x|TP(B)++TDQK17&dn?=Jw}Ltc1o1uPs@zC8zdh*o5rcQR_c3 z!wBcPBsH(bnLah2y>D-8D|&*fM7EKY zE#7=Pr&QKqws1$xzLOSa^eyV$Rn4}p>i`i6(=>*10eu*4-dqxnpI_c^2b?b`SYg05 z56U@5+EMkaVPJ&n3Qk?O_0^a<0;ao0JVfr<%@Bl1zK4Xkw&^9r5zl!r-b^SYQYf?bC zX;%ZgV(5u$M;K&5{ZjyqWl71R-u8CIp-_{C12~$R?2701Nw^_`kSasr+F4(o{!(J} z>Q&hSDcC0%XWZ3-qJ#;YD!rM)!^7nRsZDj9$+u8RHaIEuq!#(%2?r`C1Wt~3@f(Cy0)SX~0RFRXi$>Le?Z5^R5hjEl=v>l)q!%dSDWkje!bdDAR* zH-}T|EY^zKd9tQa_)V|_ zn`8*8u0n5?642qz_jcd;f`|W2N&F{`!4VGKz-PcHoly&Fc2F7 zm7}fXIgR$m7KuDn@f93x{?G(1)GIMF6hm&X`}~x|)2|z9P9KF6&2no)xBD-MJrTr!UJ$izd4UV-E5`E2%)!Tk+y6l6u$& z>!Z_^+@^^qJLgJ7aS4g8Q4(L0hHbtldfYtz>BY30w~5$g-HB+92RB?rUcY*^WdbAA zq(_x`_3rSN?K910pd;KjT%?NsoLtb?*?9%7zv&G6>JZ+{w`-rlT zo%9@8kq($gEPMBtSvN9YraogQ?l_uJCe~Ue+^Pmfepq>`(b>QL-r7ChH&HHxYix@g zvDyuFJ>|>{9lk6-;8H15KZ-z+sR)EQnbPRTVmm~3(s*4N5Ebn$S+^@OUuf3; zj=Vm}v(X=lS>12>)0LpTwQHHyy{_(1ZBpc%0HZn9qj0jfbH+l%@bMz_OljumtExWF zb8$|cRfV1plq2Hvddyv;f{Hqtl<96TD>v%+QaDb7WEYOuz!p{y8;|JO`AqaC2#Gg( z2&6sBg;m!lIoIZrG?F|{O$bu$dXTIN5(@F>>u9yB-wenXj^`Zh%PyuINB$X1GmN~nXO3aTdoyvYG)mAYS z59#ixi{-akk&pL6&fcsPUUu{Vx+UPJO6(l;ord~Fs?(#=J6Bc#`<+gVKRyQ(4(8^b zY7z|1#xd=tdA+%U2pjZna!&-$&eO~d&9ou-E`0iX&cpAnZqI&@(w!R1uWt64Z9o*& zRvFvKmi)N5&~wqs-{}TI1D5lN`*m&5Av~U%c0GfD;|E_0_7-u#EVt1EqPWY@(XY@S zQv{K?v0CG#V+SRZ!I+#-wW+hCKf{YvCZx;|s!s3-@Es+S6mvVp!L&t5si(`7iEqfl z+P;^@u@H}*#cjHC5s;FNo28_h2)PGjHV4$d&}Fd_5RiMuLnc!*$(h|Yfc2$r-t3Al zY^QusI(FjnqCTVSXlvO8>j?yuJsXvvZ;U2({qB*(w%RNumQjd#m{5KCtu z=i0|$capZ}d%R#W#0Q>VZg@02=d0>E!{cju>w9!V_@rOY)miAsGasxrjAneg{4yYL3*9XvPj3plG-@{+*Aa0Yp!k_ z1e}^1*%SD`vKaNls(G??z+#0|gADj`vR}j!2TF?=++?4Shl*&?Gw!W;zBZWnqdxF< z1gr@G6aP-P5T_#PO^xIdyG60fcMhE$4twCW9}h97dOrm zUqoa}R=pIxiZ)A#vG8y3-s-B7XuL#!NV<3O<0YFSH;nnGi^mVGr%mZGn&Z_ZT?=PK z-=(Anvl_>8itEPIrrmlWW=g_>GyDT`*%ePFomkt>(a&%ATV)WIV8U4)LqUOnfY^i$8~=Eq=6wz6ce!&n81pe-W{pdDm!rZdp0F=2J;w(7*E)f@ zXCc)?FJ12VDz}tyM+}XrTsm3+8H&@hPp{3%&o76~Ur#ah;QHK`G#|iW$0q=kQ406k zVqIDA{9vBi^8uj+F^f&m(@#sQR$0Np);A~aM%n~-}GLD zUSO*}jiES&f_Ck4%iV;Em8zo5po`cbk`%|W%po4-m)0d10#ZB_8Lj6STcB5*Bz$^D z>ZCwii5tV&O2BhQj2m!6>C|7T3e4>FS8L@;6GvDV*bsPeLjkrL74t)#n!e;AgR35Gb>0CMS|n9Lkc_UP zpApnV9$RLic(MzMP-kv5$FCkOeCdd;M|FR_-8_@Y1ttv6D5{w4-dLzF(q%|}c*B@L zr?s4)Q2N--ncLSNMpKscNtFFgkpDE*90ownQE_B!lwPjYOYi&G;M?a3x9Y8!`^a;= z?5HV4yt?`@8P7$1oqP5d;Cb=`5E+#qXV+1FB77(oM*NV*P56GLDqkM^Be~Gf(ZS#1 z0iE)O>cnYMct%QIEGqTEs^&wH>7*-ZqRhkEFJ|-Z(lz(-=j&O*Jf%nTDjvAeJyG&+P|;4&_bTe zrmcA!I)Ywh!95?5K+oB9%J*`idc=5rw9&i$G5uIOzOw)_FaI; z)^vUma#MvAKqjfR_=b*e8G&IRdhZ*M2#HqFG~yZ(oKI4M^{5htrv1p22t*^9LPK~O zd_2l^7qBj_fS>RQRX%b4U7LuW2y?%%vI$aQz+pTLDPlH~n2|Jy1NAPq-C$ro3?))r zQX*~IguI0H^ot}bJKm4*V#;`h@I<#8eo7dg2kuc-(NZL4v2nt2cQx>IHJtiflE_}^ z&%jhqGa7dt0}EC)uUbfX<?~1OzY`m&x)JAM_GBijxbw-29h|G^y|I+I2Vz2 zBSYhtKep!p7knlx>-xBfDlr0fopr+_X{qU{w%OwBH-_zdNd}i%_dSWx5D+Et0}g-w zYxM*GNOw(ipWpdrSv^0J47F`V<`i#pd`x}k@2pqQN1ii}yf5R%?ujblNl2=Y#yBm;|ci?i!HiTo@GJv{8Xke>SO8w}SxMego& zAhlX*{wglG%|1OTNN99mKzTW?q^A~XDw@BpS7{d4(yHX#A-*BTfaE+#uSj9Gxrq7`uCrT_w*zE?jrb zCr=SICAr27&9z*g`K+VYr@#8SzNXh*(8+Du)L+_q6~y5Y>BGmy4Z@ZTM4aYQvOqmp3gE_ISNi$+_3mrI~5swOab&OY`S+OFmiwPQQB8jruzanwo-7EkEn{3qbx>iw<_V2v?7)t{Eh4Z)FU);98+DtLDwnR&T$AC1!r| zU4y{^8Yqv);|nu~6;msWrF6MF61_?o1c!{|ZsJCnZxcs6oPMvIC;2_>M@^;#EL>Cs z?}UCjssF@GP&ig5T~T{}DBNAiZ9>zf;ap|ETCjw6?BX4*GG>m4?1Rz!p_QNY-ij2e z(K~8w!V43oWrhj3URpnbE5em1F~o+2kH;y=OK2n{(7!R$f4wJoV*DK}U1_p)YU9m(Dp@C$&u`)lVQH1sXNfhSK#I1(oqY+nT zGG_)_=g09LM3GlZwn~rLOpJHA0U`UZT^sCNruUHuuJ-dVo zXaPXZNcyi-y5AYtgSgazw0<2M=U;#vph!UGjFf+N2#jOUXwEO2(gsn3YWS%4ei67} za<{H%WT8e9Q;=8A2sdxd_He)EmrI@!G!3L8n28zqu8@)fZAUP`Ds-Wh2R;_xoiL%| z?ZfI#M;YoeRP}stTsG!u43$Y&(+^hN1FB(>BzAEBkOP+@x&+xYsd|@n0ig#2Nv1jv zK{5hGC(g5gLcXb0^WP zKl4;?HSMdUM(MkAh52etB#`bV<6g)VUK}8TnieURc)yOYrqU!@dE6M!&MqakjeO6! z&RW!=V_|+!NSP36m(2ThVpeJgdH_=5q{^q{+j?epDspWCF=w6@?6lA*ZylGuef80L z&@j)3W&4daFZy=;=Y1#254xlbYG-MhOj`^9A5@o7=vO)BmI+~{mOf6;+b++9byXBR zqckr1rFtzF&Jrr*f#IG#G z8?`kS`?t6t^^0y`**vRehx47vf*5@_@3o~Q#cf~qWnbe3&PdZU9ql0DZ-l5JRZoV2 zI?EYbY&_;ck#nqT4W~vZ-~f(mv{9K2ciMND4x>GzEPA0z117#F+9#2xh;K%h{eF~s z2~YHOTw3f#z}jKOUi4@-iQy^gEoK(&)|S}2+^R$o8|{Q3zY6xlWy6#lgo>L_<8E0K zhxNIx#NG55?Y>WG3Gxb!v56gGMYi_8k2bcI-FZovMrTNQn#q?2>Ow$QZ1_hvfP9jG z;4LJUOrG+}?7p^dZApYjU{edWqUq(xKmKoV;B&S_@SU4BKOtYdnA@8Zk$IOGz<_FrTIrrsLz!v)!Bg)^1TA`iLZ6^l3!F8Tu;;NTNa}# z&ZPM5a=ih(SA1)>EmlMnzUXE)@H)b!yKR*>SEab=D^T0s!qAYDT^O&uY7L7=;BN|C z5jBBA4Rp>9f3?yWPSN$>-H9>e)HH2q&+^?_LnkhTIQ~#w{0ImzAJ!M8rzTY)jRFG% zO(+-Z%mXG+y9W=Df0xo!QtDhJ-f+OUgeT4?preF$7cD3D*zVBqLfInYSc)Q=SL{wWV&A8htL3$9<`kCWq0IaFdPdcCkeQ~ zR{b4>zt3X=9KI3};ON?D7Y)DDTll2}iFSElpmlblm_Qs3fzEj?R(jvtY-mxlc7DdP zRRI>SX#UkgSlxrA3d#L5+LAMq+J%o~Z5U2G(kkQz!hb$Z^Y{+@I*mai&yFLK}Wmn%}e~68LY4$C0 zrbIY*e2<85Io&lxR}tJw9y>oKS12|u;f$lWtLe?0)zm4iF%S=l)YK9i+&WLEx1t!x zRD&oWy^)!?L$ojh#Y!UcOs6wNvD@!+Nj$-?+}yBl??}hi|Kx)cmSz#l^_zmDnS=qA zfN-DlKUtb`?*{4RX8Yt4F*hD)$=U{V4GpXGq;!`>IQJYK6Gcgcgh!95I~X|bDkH#o zb%bJ@0#2AN14V16%TGzRiHf{yFYB;@k~7lM4Qg7@sEJ%4{+91Pg%7dr9nK;|m6gR#*BF`?%f0!w^>9DSwZBp$Mfn7ch_>QnbyOb<jf&2TKjZEJ5sA26!a8|j|y6)i%7m{lAT`h8B>%A;tLl{2hweQPj6C#BC6 zs?fF3Ry7JZ3WW~kn@toCiDtarAY4UWtTsaA4-9=pxe@e@qR$X=nZ=2d{Wzt$kiTlrvSr=y#0blxE;F?!Ftt80yhG>#^iN_gvrmUu8yv2~c7 zo)h%VrFnx=Mk9{#a8Zh`l! zABPe`c>>AI;~#t^`ou>)_29zo=D`vZ?UL}+UjSstn{OlM`3D?zKcJGKRAO)MLaDZI zj*Ox}UcRu8jvuYg#_>v;z)#)#vmuEMOSKRPIE$HTi53vB@%MdlL;*2#I{mb@!_va> zo3Xa}^|^{Ki4A0qA^PApr9T~_kG`Xbv)zM`hzSS9LyN+bn$jNm*IihAMfOmFwp}j`R z+7bwbH*|`nTCh^l>NoUVvsQluI3%SvIo{3<8o^!~5{m*3Q?YI;I_N_+XLbYxdr$dF zAeJFVL}N*JNFPu=**rHLzrFO6~qtiDa`H_+v;?$c{$?5mxIsH@jj{# z)DHmk>78rr%sXUU2v4@>dF`p?otn22KUa54X(u^ZT)

nyD;*df+a+g(9oi&`Mf} zs(-c(U10stsr{whTTP;=b2{YZE?^%|p_raj&%(PRn&*_4-`oTL?0^$$S@VNP^f>tuXX6#eR}zFfuOmJ(WDo32D2e{oK%J(b01 z)IY_`jt^vnX-mX2Z?5eNoA7?!Voq{2;|TSNHSAH67|=T=QP_x8C~KBU22G(6OVlq% z2LaUPIi;pdn69BN%;3rqjn_GR&+IV=Bpb1%YkA`&`OO}?m$9$aK=kYZc1CM(tFUrl zP%NTEg%Y!=m!)jB0ZzF6d|>N=T}_O`6!PRi&csfs^ghVcSIg%MC?j}>FPX+79_&O3?4~_d!g{=YUFsx=1J%*=e6dJVK+N7jC=+hplu_gU8FwPh z6NnW`c()klfX?wADr;prHy`0fxp!<4JaRSf_cq|Bz~0()V3w5nP19?~EUx$8rQ45A zH)10q^N+Xg&WeIstPwxMR5q03<)zTt5!d$HcbjD&TxGahmACm4qk$uhHpyXqlFX7+PhD#vjZ;#zE+1Bg|ZsXlk)RTxw&s&>%W zgl?2QFYut-J6};V*CTA6(F^ zm`oB`=DKg`@EkR_&~CSAMaY|jZwIc%RguK2;+^_8@+qqhiw_q}N9JSWFQ2okZLY<1 zkKZJF8%s(mbM+5Idg_L3mH0hTC8UC`%zLQ__1iDJ3Bhgyxay2pZ{F%$-YhS2!Cgpk z7{S_2G?z5{Rj*`i2G0mkJ-g}yx`N>bmn!nd>Y`W0%tdl^y{;@Iy85E;GIty>3C_;t z-uMon_(q_tCmUF%yn|T$zgNhb+7!5N#w4iPM1z2P1 zA=7>|#dtvuo|zvUjV`;=wLO?1kSQ#ErDJ#l8_=P%vt{T)ezV?o@zuUH4nFahq=4AL zj4pjQn5V@gP0j#&OCleY;xYu}%jB7$2UOIS+lbWNVQ4h@7Dk4t&@4$=ZSjVXoTm#B z13fB21X#vhYYj=&Gs$FyjkSmSd7UQFQbyj^$&bI|i#jCqoow7-d1~_U?B~mJvzy&q zicE7OW}nv?Hx8hE$UXk9L{;@Fp!XJ*5i<6f$QE+EDC|o>)dj zQ}qpiwhtX0PnGdFh@5md(Hn6_Da8rK6Qs)77$7Is5tq5G72`qVxc1j+4p3F{stQzh zu-&jAyRVtN@nHH%xT?6%6}yJMsrzgq%cTrS2UxLi52#!0Euip7sNtCODg2EXjfcHYbuIrQV`mb((p8qr>pS z`6bz3vuQ2Dy2gjDweZwM3UJ!jxX8;a9YOcDJ^=e%;=JENw(U~!qfDG$~FkP$+3G1xhaAYW1MKpLV zC#h==(O*(7^>*Kx4?tfjgKV$lCn_BZ;9W`lkJtP*McT5s(FU`kf&kKr-D;@710Fe= zPK=Z3#&^lK^r4Tc%^W&?9@GJzH2bjSpdVe`+b7xH*yqXl0dY}Fm%PL46SZb{7YE3` zY-VbMsKz4Q^|~@Vfc1L@03hI{{*n8^#eVN&r`l73t)$pt7jbf|rCIJlR+B+twt;si zqgD;Q+Ou1DjpL*2;~QTW9T^C>*p@W-F}8!)B#@( zm>GqePiHWlJ{D+uDCdz{CnT66=Mt1!q?;2nq=x_8MOWLo;2pIZOZPcOzy0tbQ_A)Y z&<1f5;3cFPFg+#fQGa{OF-C~hD)5|Yk{X9t_VN5%FLk4Y^XB%;yLXGEbp8A$8u;;e z+HIpwl>NJ`w;6$Hk+#WWF(S#m>(mLTULcX}(nxxsjN1iBdTyUUSb5#;1+Q68E{|ec zd~@*bL4B9X-q;m*%gA3P--5<34i9{z%^;aqS1xM^$_BKkH-M(F-xFMD*@-)PRlBvm zkDb}N#!+cXh(NjSa98+3Ze(EQA(Fks)a@~u$+%|XWCc>ObP)4pGTg2AiJcD=$Q4bc9D zEl{$V;E7uO1fDnXr$TUMSJz`-Y`xss-{0N#Bkk)?Yqd}Ehbsz(c3U14OIPS$Kwr%3 z?9DI=3tcG(dsQeRxCkhEsA9Mc-)A2&Hyw4wFkkkVogp)uZ!do%JrZAq>g3pjcFwdvO5>>kSN2pSBLhfESk zalr~#H${+LeY2TK>wf2plc0Hyd$uow3Ti`PH_D;{@R?M~eb5!nf1~)5uBs0jk3XTd z$%^De!7<|qAp$}c0UgH@PD=wT@EIML_2HHp8XO7z5bzLS>9QvrSBAMEWbGl2Y@g{a z^4qL{)o*>-1JvZ0c-ElA4cMDco!}4lNC~x<606y$cm#pOrP$v)j^A?A72O-XKQb|J z-oND1h4(m-b2Ssp+wz0?eF+-qk>KN-tP2irOY6K!%DGaNtUg;Q5j*cH(?X<012}C<&WNqpr7A zk^SDjlAaVR=bjwpxU&4HR0Mqev7|$c^ByAq2gUm0iF2q(UD4B+jM=~!Ql?=4gs?Zk zn4S|y&d*P#Tr0nBL zVa#|7=RV(N&kHzs{fWYjySkbjye8;5A*&?Z&3k%AQ%$b}`X{A@GadEC`%SJ0zUcHmvbo$|1x!U$j=M`s}p@y$xG*jsmH z63(LX=URMaTCHOy6;1c3M+b_o09N0X4~^KSoYmg!OYq9d@DlbrsC;j9S7$$%zgpgZ zuPr-*hsIgk^CqxsauVSGbnWzkJPA{hp@CB3+Fq>%NyA|40GDg!L z*+&@I)S5XHC8<{YIA3aRx;J{a_Igwtk2y=TB{r1`PhSnR4i!j{Rogkyk%xodfElm|)$2P1h z4FUNk{P0f-{?#>`?brMlk=|TSPE|H{huO6^XT-YM=-HB21#%m@$AoXShAovEx3LU6 z%FZT}N8kaigAK4k($KAOmnYKTq!Tr6msh!HoNl2?JTabpoVj#aBUMTm&CAeG|HFSp zosZ(?hA1rLY4TMsVBDi$WD?VKT~U$gyU!(l>eNeYvT?pp-Dcwv2mw|p5i?DhcN2PJ z*{1_yl3a8dvJJYz%7wTHM9hLFzDWCh_Z{uNcU~^I7<&4fT z2#5s_E=J<#fN8?K`dMku3&XrjGdi?A-%O8N7b#M8BhF@Xb_c6gg?|;tc;v$8aG$%B zAawV#*xql)5R|VhYX1P|{rnz+GbguH11+8{!mtBUC-pC(N(9MGm$#<D-2%Q^AR^~coz z0jR&EsYaiNThwrU5Cc6^qn<=HN}K4~noU z8E9~P2HF5iJ$3vp%gqq!Y(Lf-w{y%Z;>Q(!l4Ce}J!0jBITW z+rA(N7h>xd*rMAh;CSDtg=@{SZBTtip!!E%rBA()13~W>_!b+k@^mb992cpFO5XD>dL=x;*&j!(xT zg2teF%=nb+EEZ^UIPD)`^j9>o>`xuyF_nArf^sP%HQi}Jv|9J}3-u!evM z>DwtwkZ~O|*AX~6;x_7%E7$A1;&VxU>rCxU+PvMb6*MU6il#|Z6>>kt<$}+-1_aPr z^hmLiPkR?%Muo!JbpH|BBHNccNZ&MiFfsk(nT5^crW7A4JQzL&-90-&Z} z=X-vJLJkq7)N6Fvxf@mO9`+n8QKByOsVdnh0opHM>*E;eX z2ZT=f1sK?pkNE}Yd`<$oItB6FVuayT(fH5s67T4QZp8=Z=t)v)_9dWt))4@JFVciD&J(Q9X$`(O`(TV9%YF)<06*(b*%+S=Cvmq8BD#KEO(*HN?2M+~VmyRBw{h ze5fut{D^UcAz>loP39=Pe(_WCF7N(`&z9n<91*ezOyL>wX3U|2P>^|S8?o=nvIN6W z;*H-oWTH4HURA~Zd1FTQYtD-+a&iSjlfwDUFYX=p>svjV;+;l`eUYfc^OFy?ToYx6 z=pVlEG56l>3jJ)e$xDUpAg{tm`7UKjVV8m8n`^ARC+}H&g8V=ZktN+7IEElvVcb0* zt2IShRpM3b2?xIZ;6OWjcr`ZiK06J)Ot`#KhBqE|xoDCp6cT{u13 zYZ613$iL+u+ha)Ht#CblZ;#Wj?uzNS^cD};6HR*R3$hUE3+Q!<=|X8M++yD-{H6q0 z{k?vjrkuW!YOrnu7206vb2(idW#xc8eBZQxxcQD9r9x7Xz6BCSiAq0tU;df`d>3N$ zcqKlbHOa9Du|x4%`|b|=%<97gb>NGpmqCpJ%eymG_uVbYliNHm#~=Ly47JhFkz^^Y zaBh)jCwS<23ilCwdNG+qCHr=}CpmI@uCokuJ{y1+^xhgJ<8R8y`?3&0B~C)`FdjUk z&xt%cdX${s^{)DCte3!Tb1G*>?1z}Be2Hkhlr-TQ2Yy^ zntU7;IfgiJ%usCf*$gjFFwS=%lpTR+C{aUOo7Lsqt&Yl4i9mlc2QIXdtu#S17~{e9 zq{)D+Sf6W-m1zqusX6IMnK>!X3*X_N$A1UsY18fcX-IHyV2NVz%%ixo8Q2`Jdo)DT z<$MW2k*ti+R-_^<$Vh;kGoxA#Qu(;YslTppX&xO^JjCCAd>EN~hTI!qzJH~kVYUAA zpcP$3r`~ibA}~9^t8ydAG|j0K!1_X_;*WGWO(R^;M>>;%2b+9hpAHT?=5Qf8Ht~vN|tt1kfk@yPNW({c|kT zo3mA?XXJt&UrtHYfGji5BHnpNT}Dn6g3;=D$2pChOD{`LE*!hpF(-yM*THZy&aL1S zPhU3R3|>B0f9Qyrhw_+LGoOiPSVRHiJ>7$X8W4#ONXQQlJ*(PcP8}$*rKzgO!djT- zZZnP4SeLtCMBmdILwBGkjU~3z@5zG4Pf=$g6*v@NNKe_q@ab#i<|W}*1jDiT$>@EL zM%I=!_)08s&D|wGI13QDE;a#WiszZx1vFIe#j8I^2H1Z^L23E|HZTxn7%a-i1>zD) zD$v~3ISbq+IVxqpNWRZ<$2EdycsoUI>c<*0CXseoWjvW> zoMqSkHsN1Z?KkzhP1`w^;;84Wu5NSoTz|DeHIiJkfjC0PFBQaLdY*xfi(>j(i0<8rW8L&( z>v&Y4|138b7tG5hb5+WpRTppweNUk9W3zmKq=fwPLrStA0MqQ}Fq&K)! zCzesiQ(JRa1l=ZU2L~hM<`H4SzW`k%NSejV=yV|28PvRwoTp{*=spHPO_acU0Bub4CrR$`&7{dk$v7yU`KNv7bAxUxylK zYI0bnrIT`@ys*pGJkbIoHw5^3%CifRpML>b+YvDL>9{r}J`nbWc3P)%CR97t_i{ZY ztJFq-ftA@!uzA)BgGi zr(yn{#>^$jaoi~z><`ApB>t@PczG9O{T!2@w`!q@>Ym)@ed&y!poif4D@wDZ9jz~vOxmWYfHtMpo2gi>FJdUMLi+>5t$N-VX;XeaeZ(+!v(5_V{`K8}&=awBvwG^WY?-brEd!rDDxJRF^RP4?R(w8(rZ$g_%2p?F1D zJA)mGtrM;ja21SA+-MF5FMn#|_yrIuD8j^OfknkEdN~$)v!gCM`yTlLUE)3bx20Jg zW=oiR#f*zCt&W3yD$99>x)vbKN(BlbXe!wfbJp<86fi_I;<)oHF=s~{U5@|xVd+tO*>N4_)wb42 zN$qJ-jJMATjq&n>a2XMU4=Yi(ysk&iIRzV;jih6QWE*302s~6g9i|#hUtF>|=zKCO zN_+)XWb5-NkHm4?`)o3ss8*zYaG!pTL5FdB>k2unD%&wlTg**D4BvPp`m_x>vp-4X zGx6I02BZIk!CvY~5`S~1c8)4Q8Rc)gqtGAIq5BI^W9^Bok7XDhz4S6p`aN2x0^Ubm z$0`Mp3WE>V$Z;+p%g<8sk+W$GsBXBNUQFz@@Ar#XJ;a>2x{R%=3^^I>#li?9?XJ=G zhRDKXLW^gK)9%hoQ*|Uz&=7%SUJ9b<+>TIv`Cg~*+(ZplvfQW7MfU$A?mM8G+PZZ& za=?aq5D}>=Rk{KJ=^p7_3?Y<2lul?$=v_VZCLkanK|xvqK{}x-N^ep^@4fe4-$wuQ zd)^!OzvJHjjr-nqjBFg)d(F94)|zXUZ_Xw7%I{BGN0EIAjo?|+J<+Ph z9hI2pOp+fn3u_pJao4c%UEjAml)Dh^tP##jYV`r{_Tn_ESxATOZHHg)Gl~dAl0mup zu7we;_p{Nk_<^XQ>A1y~%re)&yB0J`P%UBp$>uB=BDyWpmoAa3bo9a9BW&`4XK{Z< zlvsR!z}!S%lJyQV$1BVH#tS+b7M63Io!U28tX0*`3I#NnuW9>iQoN-bA2?>mTqqmR z%TD)W7@`)oj07DU)NM^dg8^~)!wr=mGm}L1S?>GFK_RVe9a@P`by^MF<1eTUXDJ!$ z6JQxja)wzu%(3@LVdnGfo`~rNem9{n@X~ax!POct&xJ2PbfL}7x_&@q633+-bInTIRDPZ(C;{fExd$S&9~c*o<71qmU+sL`A49)|psILX z4JtaMdE>D7W%(2+qzN)v?GXH|Mi?bLldY*w!5MQnxT*1RT_yMxA1T4ehFNcUPIWV1 zkBc4#QHf&D3R!wvo5Nigfs19fF;x93;q%u#`~Psie4$_2ZC;lX_arDeUW*vX`8M3R zGfvZqvlV!iFIz$q?fLqxd`qo4MnyHK?QKQQ>$u0zKjhRHB^fCH(4aG^Pd2)jt!^UQ z>wowE1M~kcNK(*rZj017Rq&51bDMEgYPQ#KU%k({e6^0A(#UAh3K5V1Q$85D$>8N` zq|qOB^j`S!B`bI1iSRZarGv-b1(LaIbu%%nN14+7q^7sJi;JZ0AFh8(D&#nj`LDi| zQ$YGGtJLDvrS8G`d2VjDAh}34uqsHnR`gt9YYW_nBjD2ma3maUoiB(RP!Nm7GC1#y zsabMhWQ}jUo5$q>OJ`oxmUDbc#VCC7x8%ynFE+nH9KW^KDrdh-AFK4(a97hT7lAC1Zsw=-amW9Z_e)tay&s9m_->rAE@$;KH1VhTZop{9mo~EqUp<9JC2;nRjFU_}CN-U*6OT z*ZAITm#DRsv6-N_C7V^;Mx$z{u(!_j-4%Dac}tjgsd-+y%5c|r&ZcHtc}uO5Cb#*9r)91w0YgOMmBe7hg*uD z+|6>2^y&KFA3WQR;6z2g9%fP2g`3kgcS8){43BV%hsmqZBkB9MMFkZgXgPIXmSsKs z;G7muFQLeOZa81N@&te`0>(B!7U4v^&S+pq^L8CQSndGCP&i~FjU<`#*gUS^?||Ea z>7j+k3$AWG-_lgH!OR@!CDrnU8xAXmI1L3v7Hw+SxfrF7CeMrAF_W?y7b42SL~}K{ z3b_m(ZywS)Ex5v2*Q3c==fF|~Avu|m&h{*^Mvm;0tBlO@!)<921lYQphJ9v74V{AZ z+OfN~sbN%nP^OYKY}z4jYEpJzgU^O_=pC*GswtmD-B=m>{f{rXH)2u_G#!_+`u7Gq z%M?|56yZdemZz8ltHQYDg@dHBbmXC|EYoqD)%w>f!>&mcn9%$L1@5SWIqt|;io(j#vT>aq1n=x{p|xTG zH94db@+Peulwxs8XE>}WhlNpH*>x%{Id^>Hz}cM6s6d&zCvlWMXxkeiXcLgQjr zjppna&ucOnqYmooP<_UROnvetJ2bP4GrxbWuC~e)**sa~O9!{~($E2>;Q}GPi5{!Q zu#4>1iFM6mwhp*F*CTK94B#%S4{(#u9)iVd$*RMo#F=j{r0mtZxSRl^zD?sIotEqD(u$$E>g*;&zTbdJ^^*Zc3!9@}63dAl)6aRNAd$L7)>L8Vid_64N# zZXcIQzkBub=69cD$9d2F%6!}rzg>I8QN)$4_QOfWpSOFTuas3a^?GZy&AEGpge#51 z8rVYNAL{MjZW!$>kE{nAu?pNEHq@jskD-45vmN>iqeFu#7oFoI(M@-#OYJ|sKej{P%JjhEZ5?3P_@s7 z{HB~qah|xVK4ZUR_-Dh_FJrDD>=kpDcz&<1tn1SWA$gEoayYqnUvHg;@~Lxq>!qIOhp{!3dZ>@ zy6oz1PPzBM>_dVS=Hp}ktjzd4tX@!TR+RD-`dvBJcHG!SX&Cp0`v8qbKauF9P?d%|6&~uW~KV z*$M2?ya{{N;s8b15*cW%M+inG1eC*D6FK~t2Kqw~K6HPzJ}!A3{Fg2|$Z2!a=&bJY z(o1vxr&@#?o3P$Gd+~+YdA`Vt%-{NO>glq5?hggCR@SliRlUU@ki1}J)DN}3J}-*G zPAZOt3W6o$5;-i=HbVmp90{dii6_9SR;%`+LAckH^LGprT1qmm!Z1;BDLqO3QsOaM zf?1L;jHd?Tyhn^HrMsSEd4caZ7M&AuZuYmSYfxF+&W6^U5rP+iVDA_QoGrTbk6r>Z z$v8|rypY+H%iPwrYV~=yVM+7q`@D zk4Y3%Bt3HL({|RB z!i$QjI;6G7a6MQfQghLJ_2JYS{aiuH#kQM=zY{#<_igS}BhB{+E1LTnyYb#V6Ssg7 z_$il+3p7DQY0 zV7eNyJP_o*>6Pkxnv)M+FPpf`QcCw{09rL3-njCTiDt(6+Q2SCN`4+b17cGHr z)+%)C8Z+Zl-X&<##o21X;Os-e7^wcHlFuE=OmfQn3ab5mhlI}NOZK$XpJT_4c8+^1 z3;m!nFYbm=bopQCHMVt~Y;w30w@c?HTt*h(E;wD#Z?h>-QHuA32r{FiB-UXl_7)$v zCjgfk528DH;}R+3j+nODve0+pO^rxj~JPqJz> zwdl270f?E<*ezfm45@6$#*+E1Kp##mak2EEyrR4}K~vg1_tm_1)HQuJxu)eMqa2ws z*v4DC_A1+_g!~+}5S-(_XH+$O6v!!clMFvThp1%n6n^v6b>akgNy8s7qLz9?W$^?M zk(`$XYgkfg>>rwdSqYBc zLe{FJx%DURex}$ueqJhkm;>Dp88Pv`KSb{Z&peX1%X{*ORMPvMZD(Z_R|ox7UC+s?ZObSZMhT-aT2jkM z`$VxlnyOQ%N0ncTi|2iB0kS&WYA{&s!(E-OHC7A1XV06&QgO7b^I0rkhz9z z*1cS{*;kR=pW=b6<>q);r$wqpG{oDWxNIe)e~pH!O6OL)?Y?o1BVB(3qj6@`32>Da z`5FG%JZB@cy?DwksmttuWv_O2V7)?PUeGh@jL(18lj1)O!x$#5Y>CQKh={9x);&8a z9^Kj`A5_xBz7|}FONG^9sMYp<0mz&=e)d4b(Ci<|Afm)VF- znM{W~>gX(hv~wsSYW`LP{u9M}!r?O1avFi7KfTEFV7El=HsBEgD?2Iie*A2`2lHM$St(H+-tJ2*O6NU2I@84;c2nd2cp?F!e zno;|Ri_H<=pxp{n{21Carhs)lPkiMYnr6;ow~H!@5Jf78o3Bnzni)dwQIO<@+)iz# z3^uIK7TMRrd3{UEY&{Qijkp<;cZg^h!{)WL567>CopX59*^^z{-5mAFD%!+IBrdE? z7em&RcBKq@)_|}>6A;KInawGZr4~>X!dyHkM_}b3w zk;;YddAo``HZ_v_(vPbPz#j&@NS`9;%L1R;ZgAjTO{sIpm&bMV%NrIjx(`VHcoxyo z&C=eo+@|E;_h1$~H^P$`brC~I$y3dm)45{fpSLdTcS zV$**X6&6Ilc%vFFyJd%R>M$@vm+qECHT$kwO(^JD*4!YyQrcz|)<3VHKJTj+z_4Q_ zN=btf6?V!{mQK7Zd7Rd;k2~(At)#eh>~Mc)KY?RD=fJf1OP$JYl;Yd88M~^y;eIz1 zU%k2U!)bASgY16nR9|EU?Ky`W!E6Yo)M4b>Rq1a;XsOFv;-TR+LYY}Ftjx{HlLO15 zmwdyXd$7>JAVO-20^kYLIvoZoNg6%loQejRxMsU%Aw#HEZw?YY-T=@3-S0X+fCZ&z zHF?OP9*QJ|EhiGc0=q@b3<6mMc{1DX8`!L zDan`Z*m$!pG<=OKeT{ldq@88!Iin2BNi2Fmv`4q<0J5H<4`D5m)F%|pbguZ80=Ep< zG%O8m1*wXp6f^q=OJOjt$Qw#R!5p+9w)9RSnwg`%#=q>y7i~5y!7upk-A2P8qAQoGC>{ zG&Yd~m(qI37%r*l^ao5Gn%fiHx;6psC_%xj(!y&{+qcPYJ8nO=GzZ`<#N zZuV>X&ivZc`1213cQP3{4%MU=)?S0PGkn0``SMoqNSSvd%jWBPVC(d{lN>gubw6+8zU8NsW-oldKL;HfK`96mJr@?s=k?9v>$UEbLL_6UQ?4s! znp=NLixkllKQp+zMO;rG;!2Nnb|f@TZ6w}0B?{!Zh&^(@otDLWA!8|wj{kg=^cs*z_r(J%kFEDURmLIYC+evEM2zf!NBhcL@?$7 z7O}10RAn85eykgR_vlarm2?7(@jm7@(dKIm`m=Y&A;qas%rQ0^2)4{uaaLnB7@}w7 zWoH6GBdY~s!wb9}N-;Y*fn`zA+BrWM`}uKMhdl=4GMyf=rbZvp?9KrC)rFIj)20M= zUf~l*yy9ao8jD8tDX^z9erXJd=5Ank*EWr;9$K#GW=c{;znvz8X%leqTztww9bp5S*Qc9$>X+Zeu0~u0&B;sd&wgq7x*n|VMdO&Go0(7b zezHUI3I9vW59)d4{G5k(*kr4X=lwlWzn$tV$U3K_AYDlGSj8&tl1Gq+YVG^KI`f~} zu?o2-z?X}$-|W&l9{&2flPyV9!vlh@x`aM5A4~zr0-Jom=FarAlScKTx@QL1s|11pxq(Axy{o*ZPNY1v9LiHt|TMiNs*fhaK=vt+ZWJ>%h@d+4MYHkRpbA z)!7p7mc|z0vm3e;5$aCO(8F$#+34S=@92eEP(`kHSA}!Lr9RQ!Hv%C+g@>*ZE!=0& z7n{FgY*y;v2k!3ydd1Vdl3YfoVzSr+BQ1A%tv%Ph!FEr=D~NHt7#_`+W8Ts^bnZVE zG~7P~jpx5BXc!=%j+}ytH)$13aj>1&YVerO#y;_csD4t8Q=%ezZKIaua?J($wfU|4q4QIStw$8=6QrAkwjF1Hl zf9)M*NG&P~O`8bNVjzX6uACodK%L=^LKjDzZs)w1Kc znxktGnw7E-S4J0j020GF-v-cJRZB3 z@3-`YrCP^!ASJ-gi&dkTI8CV7t$rwkK$lraM^p`qZaXY z#(I;+WN9WryPR8Paqf!x9d8XZMd+QE+mN>X_CP64A?PXBd1-<*aWI`0y&*kXB+TvijH4bKG>XmaI;u--3 z3IVzjJRV&_tvN5|6O0`c@i6tGl!P%-FrW1FV$-`3@G=jpXC}YdDN+`S>I=gWwCBo9BMO;pr#gUSJS2K`yxnLdXS8AQyR(Ev`pNz z!W^lEo4=s!&s=*@3IJ9Ee}+2^LPt`zc(@-n{Y_{5K^M5>`^LzsG_UH(gF zBne;;sic0I6QMNsw#!;j+3n^hORg~)UC*r2&L#z_spJ5axtf5M=VBcE?b$%Dh^IIAc7M5-v#~lpdSBQ z)s>Yhu#$TgPt|lLxD9ZPYjoc_0S=Wg!444r0vi`xN$&z5k*e!U?~08{ZbinBiIXLc z9xl=U?!B&maLB~Ov+Q<)`J2m5%QjViEHS$Kiow2Xb>el^s8ZI_kV^A`Ls+(;Bc`iF zEvIi^8NTdiWMIK`pm+XbCibAW_W?lK@wHf&rzgm*w;d6Jz;qq5<7+gIXC=OSVBcbe zVsT&*#0-33$I}R>{d&G@&tZ=hBV|||<0m)xmHO^@@CS0=JyI{YSPPZ(nj?)ZbXG?5 zD?J-KI3n9l3Q3M#4u}J5fVqoxCZwKI4bjV1&#h%VYi8rFTTmldUD*~XqMs74jBS`_ zM2Z{mghgo5B?ux~Z(4ClH$raSOMQ9eUbK@mA;wAgT5G=D$Oe44Tg&?mO3GNFF#6^c zUHIFMFQiM(Rf02vCDQ3kggxBKKi*8~Zwy}#RcN++@?yJe3!DsEFWrZWXCu;^w! z@D0>NZ-H~+qPu)=kl2BPQ@?+*HdF)_fZM5MUo3?>KW2_Hrk|UR!8oar4l!gIm{owl z>=?||y4T&1H^s5S7ZMw!rloV%;0;}}Q%0()Jqm1X#x|u~$@kVdl)@+_D~@9;f>sCb z2Z@=fX|i&jA!zCZ5N2YfH5s?_QVvrzH|TUOY1uP_O6D?jlbFIhMOmi0syf{FmO$Oo z^u|hXIHw{j;{>?VjJ3N-Peg^2laNZ9{6Z+Hrmp^l(?gaRa4@p^>pnNyB@7UJ8 zD=g}mJ!xyV9uOgZ21oF$Tg}Q))fDBvqRG8*VScYAkm>LancD%`DN~P2HuYNuS9|~k z-Ur~LBtD2c7FS=X6(4EO*FAdOC1Q4Dp_^4D%3wa{TP~C#ep5-iw6>U?sDC4HD0aTM?>>wD2Fq{=lI4vbW0R!O0Dcpa-KH1sq#EZH9O307 z{90Zp$zahe?4FzvpSoY)iagzfHAH<} zEla;d6HSDm`A+(Max%krMFby6d}6!;CZe zkQfwLfex*AKdZg80<&}VPJWN-`oS>J$V9rsX46EiH@FljL#6_a)0=?|CwM3tt$98Z z!0HHP!!PHtpm^=`VQ?NIYv=$0ZnXEHe#^dz@p2|x@ z1J8=RqPog2{pkaK|KWM!g@Ig%hp0)NVxHi5S&@d6A!!ZoC0;#kJ(T-LwU+NkjmRKe ze@-Y&;tp)`7}9p$maRn?&of~PSI}Aun>)4uC}w}`{ZnZf@i9&p0!3uexvE$WK*@-jK?^vT?eu1kVgV2OI;of)&6a9A>{cm4&2kKp5B?B z4{@4773J#vbzA8je!hovs0q72vl65~itt*>YlLdpA$x|azR-TXQTcK=G+3%OyUCg# z>9_`uZB+^=oy7)rWFV|f^y^cq^%9=|OuDCi{M~@}5zn@sTWy+^8oTE9dMNX)dt$B&U zn0ogu#{S`A1vPagzg*AS`s`4~J|W8^ieQ4YoU6nT8O}eKt@7aJA!})Vve_(a@Ai>p zhcAWaSDx36eYf3HB5+_@MT4f>wXTXlx#4@&P>uGxw)H!*fG+{x33k%w#buCWyQMsUnJBQpG$2*A?Y^@yF zvFjuBzuyUJ1i)K1w|=N~aIM(PC)#w`;S`!NaS z%H-@nC;(Kvm%5$EqgO-bm$VN!)a&?K0%lU+_2YETS&qTB75WQ$OR%(zFcYmdGhBqL z@H$C>F`^Wmy)C1%TWY;QEKxbTXH^5*#^ECO8RFS- zEQA`70fJ=UuP-4Cxy1RF^fj}>Cd@tJ8whB7yt(QR_Q`Nx&}BumCjj+v%wsIC;l;$E zPi?z7n|UviX8sZ;=@#=t74z9E{F_>re)v29fJWrExJXH%M-WYTXljO$gHupdHI(hk z7wIyar1Gx)SQ3m6@P85IBK~v?l9;aAE)V#YZDLZVEOb5S%ZkQqk2o@2=+A?^lk{Y# z1{Fo3P<{(vxnW`IzIPBZmhnxF@nH^aFtqU=6LGNWs44EXtT)YA{c|$%G@CHIL^mx= zgkNBjvp6_n6x-pdOk-m`Qq(`3(gYq7(7vwuWO2{}Wka-wYJZzeGuzHd6#c$HrFrjO zmgtdIi=YsZP8A?s82vGDq+8f*dv2JfCWz2@=>6x~;hX(8#WfC}mTexg+u7A>RI4W* znR-z;+d!R!u=MxiVm~d66pFd0S43=X)Idqu(0=&gnuY#wHIsKhpvlp#}{!ewRlZ8R>_o#pwX0~ zH_!^93O5X#42RNLRCF1*mgbY*q>Ylw83VvCXGTW|zr;U-y5~KUre`V?=A_3hPXJ_y z52+{U9{>R7tbcm&Zu|}O5Y#UP;|`ZAA8OqNezX6vVN&~_M=`a1$FLc(+XmfFmz(a2 z4ns0?nnw(=e0S$eSyXu#+U+P;lq{S+$73tIK1rVc;K!Jli;&I_H-6u^-6B24J@X1D zsVhCmB}Gp?Xe*WXC?#Ln-Ht93Gv$$^!KA8jTWD0qp!VrI4ZAjL>IjWk52NCvAs=*U1aqwZer9$wRHo0( zJUM~q;BsWLS5_Y=d`ifj81;)QU=>rxL5V3iryXo@c~$!($d5=V0O*y|h?hN0T0_p6 zawQW-2}1)Q93|)kP`N{U>}Wf@rM(lo&*c=BJur+NUOxfk9uR*BZGhz2GmYf|^A(6x zYK;_vf$E^B@1R8^^BL_dKx#Pn%L#TJ`3o=N^RvU&+`pV)$%TKzi-5i~*w1IKBgvPS zO7yFg<_$rV$(OP++v_VGZm};uz5dYzlN9qOO=PAEw$_xzYe&$tlV*OFb5O~jJBw<* zE8p-epK4-Yf7!g@%l-SP%rWeX)vj+1Ms6n4l7ezF<~O-;5~9^Cme%gN?G+5%OMAKB zu9I_rzS_w>pA|6oVR+uLfBO(ws~&n}LQ43NCYIE-&X^kX?824GT&{pPfm#Hz>JpcEyyNxd(B^hfeG1ND(FX_O2RTC2BSCh}Fg}cbKTA zqH2~mDg5%|S@D~ewT=~B>k~=o9Wwx3Cg?0@$j#FkV#v1Yoor~aHw$`KV;;OpHQtkz z3qdmVNF}%@tciA}cnh1przpySp&V0F6JD4Lhc@L7Nj|Hs`74Es|MsqdOU_wMBxR>u zG{ku;TP=LIp{b`llV3P!0P^??@uQ|Qkh7$8|QA7wBpyd2i&9C5!n;#2F?j(76Z%(S6l#WrWCWv-JQpBm#hq+Gu{ zCVQ{D6O8|tnV3yFBbj$a>$93I(!p#8hSDC%SA}US$AxnfM9IoOKZ7>Qf9B=SIQn;; zZ=}=m!t$cwvS@}lF1{(5SrVLk1$}lgs-KopbF;IO#=J_Hpy^SknqY~4)!V{r)bDAa zr61A>p%i9TTykjoJbv}G*W@bCZsW(-k7*$!>(wRc7wI-dRl$ zXI^G(e*%C4#pjeel1Pbjvo6i10l4*p8qz0im5O1YaZ@|NS90b1niB;S89Orn;g!^O zo%m7f6MAeWDXg>sS_6NWEw^)3#Oh{OmHbAtfIv|srZjGI>sg)! zGPlLe%oiDa_u8i3mbQtfoS2P+_;71Ztp>j?x3O^iq28`?Y(WuOv!|`jTIS+Hcs%); zMT4?0m3W_1#0CId4-2%#@$$;y;bya53s?EavD*!!h}eS~gnJ1y!Dcu4B@FR)XH8?? zsZA_-mx5OKkd5%CUt_~NYb^IXhH6N<1zrO9ID9&7Yktsz(^d z_(uG}0oA=)CR7?%Xn%^1mQFeeOn+;h*KJEHvrsp7=td&)&qRHdip6VsC3_4PgQ16s}<8NC-RuHrDqzeVp;zrA=~rojujFA14iF zCuiiQ#8}^{s#;x$c7Vx2)ighT2BgY;K(5Ya`r*U#hcj_>xQseeW^}F-mrHquf6NsK zlv+M=%XUh8A!u%fL6^0Tr9aFlxezL(1unZVi(`V-YBv2lLc;}~%g4*#)=d-}mmFHC z)daidU3QX>u(ovw*_7U2_(~egKZAaM;@dXR!)cpIYeHbn_1Xs{mH5-~5%2!x{|Ir- zb>Feull6+ErI53^$rW9fJZwAT0m2ghu@gSAyGVEWYbUJ30Fj_eCi&1iCS)U5*`a=z zUW-Bd{wIV$0~c@8Wse1hFyzkfb+=C2XQ$(+NMo!kT1YN~2bjta+gPyLt${V9UY{DT zSJfEw^gZi#ow`qe3L^aLwIoWz_<>SE7Sj)3Fu`C<&o3^bMkBS0wRld(^&m)~&PeaBP#LfJgU zK_M%k&~W%b_n(f1|G*ab+wxY<_}_dKiT{aC@k2ckiM-Cst;s5R^9*EhysCx9S-9a8k0($UbdVH-A8lC#5M6}i1H@aRVO z*`blC#r;ZeEiljM1h7kCBME)tdHPu95eOxxIjRhKLk@{*`Q3d-f8BfBGHm(Et7O#h z)U5T`rvDOrE`M~hCkL4f4gO@nJC&1>BHsyL>6UHC^Dvp2+lXeY4oV(^vq4PMgUtAp zdt5scDS{<l{bBNt!+y1;`N9V#(zy=XI~2Fs4_Y7j!Y(L zf@!evsupY%>hgdI_qh6u=Tr<`x`BZm4@fq_!-~5JI+JLaW<4Q!Y~hCvF!EdWjjT$CNG@S6$7!YALB%k1R|32=ZVLeCqVG=h`cf>-RFa{ z!-^#6e)=*0fhX-93M^$18)pu2(z6d#?Ks0&Q}f5 zrezdz>-^5OotJE5E)x}%W50K?U?N6Xg+3)Z)WcTw-D#Yz1Eo`sZC;&>?-%Flc9d{| z5v8Sija}G4FTg zz6JjN7sX|WT=Q1ZTsbA~Y$(U%5_?|I2PAi*>08>jP;{FYi8lu zIRz>@$ls17Elz;JyB4SO_w*uhUlsnan9ZZ{D6_vq-z-Wh8ciD;*ff6U)t!VXOR&>I_f4Z*FWmY;=af{wHL1*^85s!K8iJ)2L%}qR-u~ceNVZwBW9^#E!*4K0 z)wSw?gbj3rRFp*vSfjZctO+k5t5)yh^-BW0C&zyN(c(q;%Nb{D!DH?to>Z;BSr(+y zt^YJ2)Z2+=?nM1zj954#=zHV8gxh`Qa7N5c*?f$gbf82>eKav3NC7 zIs)S7sMI`iAdgjy!DAAQE$D$!<}(IQ#MRfmxSc3xTpnY=7brV9jzmgf!|QAA72WS_b;1{qFO&dJoSQIyU9JcoXduei)Fy9^P)<2a|5rit{L`R$vfKX!G@HBicL$~h z3uEdpF>Y@XBaWd19IJH8!mc5AB%`ZE%A9n!4JbDE&41e&n0Q z{1Rfafe7cgC#F~57r8sQLg_pGx#ZqJMcDT=CItvRn~Z6u6QXpTpjRcLb-~;J5_$I5 z^MiCld2*WSQ@hwYj;(=1I#l7)(Ek)okx&*_4x;#zb&=@o)Pc93V9XQL6q6j zbV)#Tn3X4%+q6hIze%QeJ*uFP6S8*67U^1C#ISzoN>_FQti5>qKkxbrgDrL8GmLEH z>nGRWolOli9?zw2c}Em5C1w$rEKSlJ)7To8JIm~`?(87=WE226;&1IN7f*uG7Mp4`Rakf;DdzA`S^)pj3dDuy%#g*lwO0FbjhmIal>3uZ`C}D4bt)0Id-VVQ^ zuSo^zwm+T-ZvI$c-C}L}5IjeKIj7m)ldWH7=?b_y>*PUyzBahObM8F+7dUY1A2{$? z{C^T)ye=m{Y{4)ki_((E;u;2Sdu@B(+%EOrpju$w{!^8x9_%mA6=XBm?Kakb7M?$Q z0u*+h0B@6Y7Wbu>98Q2~j&23pHly~jJ4^l+jD~F~$2}UyMxN#i+?IxuR$Nceu|~{_ zL0F-vYH0tW&z0~e07(`F+-{rWnjvrFkm0wi_#~dZCe8Vg_kDZ#7U_Yb&`v&{S8!gp znv9{?5xq$78`P(&_~}KG?{U^l_F+E>*J7Sl!nnYhc`Hx4GpW+Gpu<_I2JItsQ&l z1L8DMiJ>yeLtfJdAj!G>d(l*pWdilX?4}Ux;-7O9I(^as_z?fGl&6l@B@2gjY7}j? zJoFRWc+?xb9ou(9Tz-(#m0-Y@T~Twnn|`^^LF|=d=L` znU*83>JE+}tSQsJsha%z6?!@?HulSvT?AOR-%D3&JpvcA{8Zog4VA0?&uzjmOHXlO z*f6K$X`-4LKQ|)j<>Ztcw-=Sp^oU=9onv7t!m!!ksh*-`{3d)}+ITp#f<7}VZXKIU z^5W+ZkQ=VvF3i%gqcVV%aiPZ3xdy!v=J6ol)@@>-zsbnpvqeh|8@+~@6L=B?2jqGZrbQ6w!iB`Dh@WlCMJxt;p0hD zz^f(V{UI}2EfN_R0Ul5J9R(I7eRK{gIVA#g7ouw#Mdsq&b#rsnf(wSiG6PLsb2Vv4 zVsF359kdvDw4H{qx|xCNj^i8oz08t5*@BU=D1viv>7CUGKC>&%G%3XIfO^QG-TmMM zxQO<44>ya-Y3g497eynkS?IYaL%%#(_!NyMp9Oodt;zDW}n4u;%)3D^WgkE915Y=e_U%*oBR zx}Y7(xBJwXCYzE{eGEa+-a_-?g6+QOCXblNx_!9Zkt)sTTk=h#ytOXJU-$%|RHr$< zlcMj(R04$vx{uixiVh|~8v`Ewmez*TM>9sIZN_vjtBHsk4;}h|=-c-o`HLIpVMS$^ z2GZqPTw-!ZXe+RLni@}1?iO)nf1RHlw=z$4TM(nc>+*}kBb1Cc6KQA?c!o`j3%X7Rh|yI;5Nq`?khS;Einvg!0sHW@NxMH{?{y!SLz6xOO*o&f)>c{V3t zjm+jaGp}1T+gMO>+{mQcd~*}?M^&)#=k|{q(dO1R=UOW&6rvbdrh!WzAA#JRF;5QA zR(&+HE~mcZLZq7GyISyli)#UaB?_C=$5%p-V?23O!r8WMAHIu8+o3PSEyX4Ie_{F? zCZl}qpRmjj5n=BH%qES}|DHwzk^um>U4=0@+!VzI=8uK3o4(g`-Uzn35GFOy!u&}o zm68ja0Gv?^0PY(5Zk>HP7iPKMlyC7QW1-=?^mg;iJu1JWvory#6?Obo9cmg$?r!2o z-|xNs(J+|(l<=i=U=b7lsTmcQM~i$sH9bCo?%auxF#FQXGm5lXOk^9h0uST~>py}` zyAOZUV3ugPd*8}3PFF!v2n4Uo&kl8EM((xf6aN6M(XI`4FmT;oAsS7?Cj8FISOv_R zGuliF%A^#q;&Z(4ZQ2Thw~Kgm?k|OhqJPv}rnjFvE7RVI2p2UB-sd&3kzGqEH{FB{ z(ptEmeW+uDS0C0^5!+m7-qK)~O9nZXu8uki0n;awQb|6zG#uJ6grF<-ZNQ65U zQd|`NxLvq}Hta%!wZXvp%zl-dCqPQ3gL@c9P&|kGc?2HwQeD>8vp{zv7tWW8T7RMA z^J6R)+u^Y9^?8~w4b?5x=ixkbZY_oCR9B5k=7 z$!4b+8J^V7PRdKI!Eq3emVt!z-fzenTkt>xY*`utT^c!bv5CfeJTU|UazhX+hl4gx1jn>!1ThM;^+zwP&vuByS%BNqcnBL zpzM{X&VD-+M8bIDg2hb`mY0zk`C(U$FbiCH{}-oV;#u%-IyXJba&u7I3|!%HgLC!6 zg&StB_>$x}tgf{#{s=q-7ZRsiDp|~1cCnLX0LQb}y16@0<@kGKQm8D78N6&|Ht{`L zJz7Lb+YjMpJbK^(i^)R&Dky1i8kAJ~KZBB|{9HkvJG@iq@d1Obm-Jv+O(w4Uxwg?r z1TLG^Y-~E$Re1San85k~2iwcbo zWKT7}VQ^T@!(i?hsiuTx)TRqCoA}=XMJn&dca&CjyL!n@E~pelDVRsmvbml%Q(T*o z*%*|e{D7{zLzt}M3B@10_yhIqejJ$$r3=>2UNm?{ZLU%7QlilyzgbPUE3b>6A6KKu z5)q8!iLb>^_7mr1u5Ctq@!PP8(JQBX9IMBRR~GXZ7W3l}5I061;2I)dgx%WY*S1Ow zD(rH`dBVt`&NWb~6lXo=w5~aczx2XMKk$4$7T>T)1uP^RWrl}M%JN-eT6M40$zE%D zo~D1Pu#c-nuSN+bEzj?mR7+HU&1Gd;iC;i!$k?RCVDp?)nEkHf-tF)+Gt=gLS$X*U ziK4E@H{Ku*HEsc8z0&3sR9bhTt6^rYL3dz2L>C_-1ozu?R*1&LnUz!!)ShL?I<(Em z8noEWrpvqHJ3t@l|GcC)t3GF!Uizp>NtdZyfPL7(P)=?VT5=^nPgaXwzW%=2iznK6F<0?uRMlB2|HrRMFa zB)Dj|$heV9bspSBQ?Kf5>d*huSb3)H>kZ+T z_1STAeXz_U?oMO)CNwI?HQSvl7$MpSJ!?E^rm8BxB$>aur0|UIJle3ycb+G&p&d#P zbsbDn2+8xgy*z|n(kJq}=xBe+-WAszk+cUW)II}b?qQ$cW@0L#i2>0U2UN~jPe?0O zNHSEo&+p{6S2VlB@Tkdbdy|YbCCX;CKeKnb9K!4SP)NpH2tK~!y%tLQRpH>z+2<0l?We3YZXJnspil_*D03SlQo#D zJ=N%tqzFjf^Z7Xhi<+8RJ?gL9zwoT*jMfri9J^=*b(nQeA4I<@cif4%+qz$F#$B9I zNJr#tR=v0vZHdA#Ru~qjTzc9+aP(LpuJkp;Yfe0>(7d~XjA&B$xG#fNNw!62pb$|u zybK3X$sf~Rh9$m!{H^{es2<%DkQJ@>2#L>8fA_()FM)mdlGp~`wXGVox?=v71pJR- z8K><37bW0X?WsQ$96rPZ%_wQ;DsY*yQd546s1R%sw2IJlO6K=j0+=g%Zrt1uxpdt0 zYBAg@_dtCTMrZpYtJ6GeD%&7Jz&lFufC*_ z;o$!2R=nub>ibTo)e^!@^RA&`G(uWhwl!=&=MDIIIkCIPuB;;)((e~j8aFVW>6@49 zaarzRe$}d1`_R~O1P{KracSj4VtaaXiyr1TULSH{#4d-9N%uDYRRhkwGWHwOP1Ey~ z{gvk(m%0}v^i}vp=pW8*tV!1D`P^Ohx^N>fW0>Xlex~x$#R!5+ghq)A#|SZ0HZ-1))$5NBt=4ugX~~0QKXQ3`))Fso+~IAKR2QGA{zktq3C6MpwqqOn zMLH*+(BPTKY?X9|mJi4iO0SAJ_)iGvh06zMf$_*NgndLdti@O)|9`Ct|L@ffsLCe4sAYac#Jaew zs3?Ll7Ser@eLdr}gXMoX3M~ zer#B2(lBF5X|3{*2>(CJ>fds#Zf#<2BT8f~_-TY&t7uWuqzJ7ice4srj%1TUj|cjV z>06pzaz+pdnpNBJY>ag@7Y0MgCZS(WWp0~j8~TcBVr{1Dqg7#p+CU3;S)4*312ARZ zJ>-+Ds`$#>K(5I?Os3QA7!L`OQ<1yNJLj15*R#Cs5Zb?w`OV80C(%lWCOBQ)4wA~Q zA)ut$P=27jU6dD=v%(iY?oVW9b;VE0m)6PPx0#i{xiPc=eXyjgxsp8O}h{ zH&8hW(8d1@1y^5zpxBJJ8pw5t4bhkE5Hn)V@?>*ePaSkx8Y#8(KnN-3^{z3DB4B`>XGKpD?49TNpP7PZ8Vmm zqjdRBX-R{*T|8lVS&?tY^iOGUpniIeZ@g=%2$@osI;E3vu#_ zLvg%#21iuxPRAoI+anv?k4)TI-xV?bvy6+Q-tu>%z5g=X;jPZ-wI#k1H1?vLofFTg~@*Xy^@|Cwnb zJU7eS3~$pl`(Bw`C9nAZ=er6xsP(mY&NCSO=JZi`6zfZ9_j|PV9n34*yZcbsC zlj9%#?`Kg*jx7`px7>YP)PK{-&L4Y5P`G63ZE}?We_|ScH%x4eotzy_3~V6(?b#Vx zLb9;o)8qfQ!_AFPCu(8sY~uJYwKi}z5jHWhGd97elQyw6b2i6kU}omP=jDa`-!FI1 zKGEE%C1Qc@y;GWILEKo6%@Gz9-=W>Hk|${gb0sMTY3S|?W}3*JkiK%=bYidOUuj-4 zzFyDsOF{*$tE&^(GaNlQlk4JhGZ6+D3z+M>_5HGZ(-G4-e%QEB!V4+r_I2l5&YHt> zv)lbVIMO2u17`F$qoC&1#+ukI<9zDr{WuvQ;L`)lU7cctHF;7Tk zk$sMGS)zBPew{m$lIu|fFMV#lyc&<2h@`Pp%1((-PX#Z=iH}BT8gS1%q;A%)a7xWh zgi<{FMkw$UZG)KVmB|zQfBE)>KmPK)hv3BCtWE$)89`A z!ghW^UNWN;Twf*Q>TY~?Q1E#Z@&@ zk-G4iZED;^36<>I@-m%Va; z7R2#H)PN@}ckQvksP_vX{qS9hKrO!UQMgW*kXZ2o3&Y%H{Xq-@E-}~4aR5emR!72) zBu-A*PIwI>0Z5{i*}^^J5~2!8EJ3!zpz0ZVFU4Beg>Y8R?Ibj7OcbIZc)( zusNuVc|K~>v8%$}X)0EHwDQ+nLLzfPqQ6rLMaJRNUs<=KOo!{ia-b zNPPO{RQEqdp}j%^OqWAiRxnadSi|PT@vF(HyG#krJ!Lf>wmE&(+w;kmyCEoh5yiA} z*Xp0;?K_`Ue+{N@ML$g(;l2O7wvhky-A;K;wajY{EfZ-G5Q2tBMI@@`>GRQg%d+A5 zpU3lrb#I(ij^#&_QNp=v^WMGuybrFk)}UPztO2#Hltv5br$K`G-EyV9u z%0PS{wOjx`0IBckWmTij#nLem77a|wf~B^*dS^uSHE9oN9{D=VIQP$oSqh>vwj&di z*4(aD$7!k{nn}jF>y6Ld_c|Sdb>H1C8k&l9A!gaW*QvrUrS+zRl84?Z-!6cb*Cxy+ z8l|whj(M4`yC9!zoA7E2ceFvuiH+~~8-eT0>dx|a)2!0;Wg2F=9Ni^Nb#5Kc4Cn+! zsna~{w~~!KMep;H`Qo?JKyDcXA#A7Dz6v6(GQbHGthTfi+KqHxWG<9=pA5f1u5OHt z9{#DOgYUy%rPFxBYngoqew&&w7^vU^Z3DzP(@7mn^TC`VFLSi5U-*LYl|EK%e{@=B z`J2Q&^mR5|XZZ8U=2EBsvpf4Q)c4;InmB4~|HFKPX^uDIES!8y044dsDcJqM)$#Y5 z>`_{=(!c7RjnbH(EQ4i*kcv^1Zx7NKoIW#z9$m)}NR_yMhnq7dOD^(jfjH1fd=xr3 zoLhFUCtpVoO_`Q9^Y-z@7GU;lW^SCItlG@;-0Ut_KSs8E^=LpWfl}UCZ@)u<=iP1w znh)kkcAWd@ctfJ%TOqS;<)*QGkNnWod?~Dc&=ucpQt48A9^)eV{-ifEi2grYeD?qE zT6_k4W;SMe=Ks|JFtRW+GXLLtfa`7#Z>5nnK3~(@ZLcOanJs3CG-4PFDWK+LK?-Hh zDN^+SLU0;&iqAvAsaQy5V?AJzKOiNx`T2;Nsf`i?C~0u*{`lo80wN;s{n3UG1R ztRv5VBgS^Y#-qUExne1>yylt)=N15H#{Pt}#r1fdrVkL!kN^nL0+H**Vexn`cTqjz z)Q|Xt!yeW5KYAW>rT2!LGu-AOO~=JlDqMKcER zB3>b4t-9@SedR9P#lU5Qs)vc6tFc-*Z#b=XFaX$m0i1RP#O3(DEjjXN@KO`Ly2a=K zecf%?IU=#|I4G?oP^n>J&hRi3)z_j5EJM1dbOC<|vN36QAfDUZBGB6XASro3==z0d zqeBqN(+hDP1Bv_8>-{N5HZ9;VunxsM;2}3k8VEe6AmeX%V}&Nz8^CeDqZMW&_;a{1 zWzV&m7x_LRuC|b^Pqc~`?2ftsy8xCDjUI`PJqjSq`-m-SJ<1yT;HvxqBOTA@pH)xC zUo8qP#!U(vIQFoMNdYE$?|5y6(RwiOgrxqH+>C)c@TA$TH+@x^{1+}z>)w}2x(*Qx zBI&>*!Bc$QjIKw*&5s z)8Ipu(TA6P#;G0*Hd5Xi$1qrUky^}+Cv_iaQbE_etPUTq8BrnAH$Z2hHlVle;l@55 zc6kPwy{;DmAr^=Y3;cHU(KJ%qkmj@*p`(g4=-}#*@Bv}%fNQ&)Cd`~Z$9!wJ)P4zH zfY75L>tr4H7G5-Zj7@Lt3-}eQeUw1Q ztWdNVMzx6a;nC2~QpdEz&M$rtAf3Su=XIGs(5G`{e@ECVN-3cqN2|!PuizDYA$T|6 zACnKtLx4kkJRu}y9w;FjD<*Jfr+c=u8pd5h2yrp;$vr9-?!XOg^K_7>nZ-aOjOAN4QQJ}69RK{Oq=517U zLaRuy18WNQ!ZIXO%1mRkGn>(3`AQH?Mvf@y-oQW z=oR7?+Y{l%2q)=?hWio#LbKe-Qdo(m3o9x9DHl&iOv~_7l=zxJG4T-d1^gL=Z+@x|Qs>yzFhM=&Gi?q{=-G&k{P0@j zTu>`q@6;Nu&2B-3f0;2q&JSj;v6}sC3;S4`N~i1!*{l{$_uv_sTd2B1|N8?c_$(1G zNNqj0YE@&oipf)Z%+KuSR0E3$~<_T$s4gZ1jF{& z{V&kUhvB&LBf5TK3#fl9YYKO<2fFsqYd2!qQ#$hqOL6ry1D@4eKwAL2Y^kqmM@YSL z6az)uy2qOJ6Ob=)E^p||Z*ZR|vxn|#1B6c`@0oZ991|l)n1b@JhzK@9@_(J+n-Hc1 z<)@|zB)8W`saw36yM@@Gke{>m_@;FQx3s|C2TA7}7|{8?0Gup1sgXYlcXP&gg!p-< zn^fZ|v%>%n8ascfkzL|zR+|oae|V4^4Ug+W6sjRbAq1qi;NyyT3G>u}goYE)&2}Pg zf(5wn<4_?>O44QFdZ(`{e6(RTIo74emEUUvIaf*V8ThntVV=sS44?`VeM24GX{Jf57}Pc3cqTN4Kj?J> zbSZa2&*6ABtQ)}BYt<>f4Jg_;tM9}fln?uSZlx(uYLi_>I!LP7kV}Se!u^^M*nK< zf6NL*tDNXT*eK(C;GWP0rCtYdN#I=WdA6qzWz(sgyfbh5xaZV+CusWad=%6=!`lL# zd^k$aotRJR_0|6B;BM`BvSdExLpYL-5`w>gtcq#pjeYC?2^)5)PRYz0SxC0Kea)kX zZcI!nwy+d^h89D>bXDc1D-= zHpM!x`cpCU%lF6TOlNp2yzSq2d6XB%Ez$J0oOkp?D4x;E*?sgoE;X3BHn6-Oe7*tt z2LZPVTX&#In-M3*MIQnyHC7z5Tao8-Bk1yIKUp{&doL`LV!ejNO%2wxi`3I-gr0^!Lep*n^3raC z*+Tp5SoF~r;$lB#2utqVk8Ef2zit2%_Cr@cF&4PU%ai084NB z^9CNr^5+p=8#s(XJd(MEzK)q877agGd8GN!!tud12Z*LoQ^BW#&4T?HfUd@F^@r9e zTSIw9a*bB3>9{6lBf3V`M(~EC5(OfYvK7fLSTATVa4WPkX=vhCCFi8*B(zFiONpOGHXI5_2SJlD;Q;lEBDe-W1?AjopCIJ!5v8+BL78#=N%Pw?3MB zIQ6)BQFZ_Aj_RK3uIiq1*LzX*cy)jE*t_pN<2mHH_-5r`(~!8$)XwB)^pJkk*^AoS z>b-Lg&^6bRyV7~axpcbfT0UEItGiRv)8?!4wfH`I9tcH<@rdaI#SDZQ!1oh`NvS-h zoKSuI(-D~H1x4Z}=x;hPBQ(K7%{>Or)bMjH+nQKoD%WVXQB@t9qrVsB>rm&e+zp?a zt)*DJ*q5>$G8{Q9nKpoO66w+*?`T2ZA+08>?uaDsI9G7Ysz=oE=eFQBWhOC7cw!?7 zaVU{W2D3zR_8Bgb$~tvh(yqkKsp)uEWFm)u!o@Om`}`PU4@t%G7_f?ryrcOemYk!c zSIcMaL*V&!g|5P{y|>_Cc9fR91Cq7_pHGelH@ft0@mtXIp4kVFh7geDQGqdMTZEKF z+0d7JZNr}~9@QK}eB>C&9#1-`%K&>DQU{aQj(x|z`JgAXGc*n}_C6Cvj=9>#z2gAm ztJ*SsiN4OjcIYkC6<{wJz}x5FJYk=ie%{t5PFdG(!?YiJj`YQeTdP zsSFpdUJI4i`!qV=j*qAnJ?_sDMSnV0$6Y$3KJs5co-Z^EJ#xL~&%%+5+%m81S)LrH z&Y=s}GA7wJ?i^>%TjwVW$ICM%zTA(W9%gISj6vLCPY1jYWYuBz1_9mCQwNpq5xL_C z1`(03gz6z_`}-E8>HiWUaA*c+HyP=8>Y}lcH z17G)j-T-=o814zM1B&h`qeJoz5Z-`!1LG9b<_6;G(MkK=+o5g+ZhFut4G5EkFr)(~ z=ut}ZW#z)|3_vYkrQ7jL3v%xQ&GccXLm}Paef{(F*)(KU;U$3w!@-~D`BxLk#*>V3 zm<9dCg-J2N6Q7SM9+@}%d(SZnNjMA1Kp&|+U}*>Njy)a$H^f;J&?cmenKlG&(q+Sxx4N0cP zeIGG7_$?;{9K(kZv8+M(8j!#|a=HZ$#knQ$BaUSrQNJM6_O0GR*(0LbB@jKbx`kkq z+$Ow^eV#IY32_$#-6a?~1Y;B7Cd7`79wDv?D2P*iUr}p-5{V1@PW~cC`^(M(inT0qD(F^ul@>|louzMo>&e1LOo1c1; z^9)&C0u>-T2LZaJ1txpu_6o2u&RUPUCTY#EF`#Qwvsc@g{IbTX8qD$F+8S_e)M=l) zHubX4+Z}spT3i34ItAM(bnWs2>Xp7t#8;2EA$QIFnejbHTkqGT zw_$fp_?hD^G+Qrq4dEY{AZB=Eyr8T>fH&|9dNeDq!%DAky~Bhaf0~~{1&Zh+_{_pF8=Sand&TQ z1K5UffjT-NG|DZ!IT*>B3fR8g$qYA4^8(ZB}J{$cg+^tq}&D8CLPsJ*bN*fPM6u93aQ-0 zy%w!kTpqjImCw{bt zbB6AEUw^=UIUSLCzs`^3VsU<-h9~A^bAG;}=Etzsf# z8-+88q(y^t%T~q{$AKmDRp8|26w~-Rmgf?AdOTZBJ?8AG(S20}D)vG|crd0KEGY{zC7ompT~7pUuT*PsanpW-ZgJIMFc$m3m!`VBB6WWLT6V@|>QX)^<(FN$T)?@s!1AEfzI%v9`(7U7cRAYOZynST9{LRE#C_t^QM3A9f|M z3>})(siN{lPQ|~8AH@V6sE6eoDQ1q)JOQEe(&~Y{d0Ex zXVUN})m8+mt{01p`oaL~?r?)d3bpgACal~xU3?*~VTnUlqN$yQtC+kFl@`TvkDv5#H}6{n@3v; z6xCzNv6F}zV*{b;K#xIy_Lp2c;lbCYZIR?uwmbXprwCnW zxRkHhn(igX?@|lN&=5)D+85V7@mi9p%Fw5bMc>?+oYWB|q1zD42!pG_-y5yAOjRK+ z_sMBmVsc(`;SE^2+vM0ox2|_Ux*7$2VAC&@?#~wBS(~Mt^sV=t z$WpGE>k{1M}I8_|ewce9|=XkH3a_J@YnL3A(0LG?~ECmJ#rBW~GIMtDH=95Ty zdTR5eCDUT)B2}XwIArihxh}~#FC{kOmdHS9B5gM@&+a*CFvuEWUo2z3K*H=*@N)tJnHO=&mT(ScYXp3s7(8j83P#gKi^JAs}1rM9Emo*G1afp|A#jKf@mmM84i4BI1Ku$PqM9j%swNsh6mF zCAS5ByHqST9~Ez!Pgc*YLF(Ms;uZa90^iw~xHyhUkISJd5&#J(lsnP0g!x72ss~n( zv`b6bTcqwUQV%Fl|A9EV9&tBgSd~D#4PrFltQNNJXC5Los+14xS`m&~p56)6sV^X& z_EK;Kmcm)lM8eCcnM5p6ZBoIK&hYpQnV5$YaJW~hG_uJ+dWE#ORMu44I%F5pNLlqS zjDo2FVbpxbyhb|=5mrHjs099cmz_omhtKA}-}gwC3iFkYdw4DpqyMLlWAGu6{zD}k z)beD`@=~}wAIDxZ6<21~&|vW7wC+zK`MS790EEF?#Nv(oM7#szAugxyi@dlazD2O3 zbmBXvA!JpVu)n^hf>Gn$`1DMv=gEHX6pGZ~a1cC_nQ>PVb}kS;M#?L)33wr(2_+#8 zhu=a_Q=)XAept+9?sXpR?3Lat@am9L+I22_9^TwJIUKfMm&mc9N#gKmi4yD>axv@k zq|yn3t^S-+X$+RytDdtxh|z$yMf3#1SwcBrF|oE_CXUb%o8+85fgUCvwf&USSzGI8a>z zO|8M&&zER6VlGM$M3-tsnL>AJ8F_zY+xs;zbF%1f0bZaXRuh5~JW4oNz`--`@OL;E zeA99wMR-N{#X0X}d=WIqKS-aD3&k=X|A&+!=^G!)K&NCvF$%|jsF+lU#4Z{C50qed zcK>XZ*dgNz;s2rB5t&eo;6D^h{vQ_d@dEs?K`DgVRxfgo(!4? zlmU**_#)WB<1?8 zydGg-b5G(h;j!-{s7IAIKWf{g3u8?DhXht}&Eg-4ZORpir`n!c)RVgpBZ2aJs>Y)DnYl zLK2GYV_sp%!5I4o+WtwrE)7DKNn1-|tg1ccz|_~I#7J+iDn-WlW#y75p~fmolVB!2 zDOW*AxS(-Z?G768HdT(f{TnsG;}gm=U1B;_j;8oz<&tIr#%9VBAhX_tZCKe+4Y1G) zfNZw1HWdyqgO(qa*;H|F6^e;&S4`LAkuDkuglvIJ7^fES=i`4rD2OI1pG+ULu*46d z<%-X1;^cS{`EJZYW+*(*Im@Za<|FuwBUe|BORB{TJq~XRg;sQ)^{L4loqV6I z^v0=+`y6VefBrYh?O5nq?||JR+|8LK%eKjeYpY$*e{jTpHEfBZJk#bzvsNhlH!y%c zOI|h0PReOx596|PN_B7Op7aQF!owp)P9p3yDQkkqx{hhOSLLvKSuGd3zR12%&Zd~f zUgM?JJ4d%<>w4y;{WA{zybF1fby{=4>FebR6QR6#4D~4KQNFEmOYL<`%%LC~U&MkM zqhYj&&deDjN@S59YRQkJgH)~L{Z*pSYKQKV&8^;HP#qpliueGk94h@!OQ*?Z2ME$ZX z$`Tx!x{^RZmzgg%&#nz2y^q_L4c;)Xue%-Hdey?Cm0K!pJUe&i_f!$H_v7cINhe48 zzK#}M{&+82{(9~>LSOKo1E+xR$Bqn9d4t&N&hoH?!-B1JkQlMon5ZQ{^-I!E$P{F5JkDTg>c2+MT;Zr zpGXASwbl)#Avw%MDY0nmv5WhKpNiato$n@|9i6Ss-XFF$y|cD0&rZ9bH7{uD&6iHb zPA?U$5*xU=``eKfj}DRdwWpT$j=I9_J`3tJHr3(J$*JG0t@kfi+&ikg*Oa->Nu|f- zUeD+=Pd)W!86cgg2Y{+Y%gVI^*tF4(s4mSJ6PIL`nyu^E+jgGgk$V~@R58y^!6fqlHOl+8JH353ICRBfm61B= z-%pmT>EGoo)^mnluAiYVWR$m#PEzTgtv(9BS2mZ+<%uuG6*i3g{yf(F{=GkQdt1gB zU6ePv(Iz&TlfVKrTcs;6$a3 zt3JpqW{4h*`lO*6S=Fq(#b*41#|ijK?9Pj<&0%Ji>B8OY%0_*~ZJ-BARsn9QQ6OaC zIc5TSUiZ+wqvRidTTX)Ddp(qH=)6Sb!$3<%5W@q;hNRYcER{RB=&4pgBJS9*=YaZ5 z^?QEPkgWnX1NAYmsqxPJ=6#NK2;2~}psw-lebeqfz}>(p_CPv&tm)8R^BXR7LV!csk%aINvZzRFDex(g*w4W-_01sA>3X#4qU3L0fmQ zvnjq7Yw|5(SeRpwJV@NZqG#GdqR(*w1|{$Ihk<>j0kr}DBa0}+i>U8t|FC_0>`=d< zI%ipX*r&ih>wmL|1KPzICBN8PmNuMQ?-`m0Hd6P^%LYO3k0P%Fdg}2^oFFgvsUt`o zj!_u{xdnYoKsh6E5mq6#Lgdg5=nA@d_C+vc0?_o!K2mSN5gNXs6~#&8BaC4@B9|5T zz9W7Hn6C*`=P*Z(`E~Mn*V*2{&w5Pj>whY%M8$dAGnv7RNTTH&!;ZcWE zCXnq=!NTbxwT6WbK`7KPNm3;CrkqYZGGDQlF#Evy^|kx)%0+ip@=15X65TO#MSAvP zt?p?hpY+%dIordl_VH~K1CM42cqIN@2!SSXjhi#3Q4_}{wix4hq;^L#^>fH$jNKN! zI|JaziY<9K6X?jc9ht%LNXIQ9J#oi!tKNh27SzmZ`NTQV%^F00$V7_WH)*gFdQ*Fo zdDCT&sYIDXSW|Yz@eHsw+*}Jis6OC+aZ};KTaCbtfHnveCJIHSEtWtmMlG&261&Ai zos2w^J=$e5BFZh=AJJ#or7j0lW;zA+biz5Uuy&iBv^H;sWJO%^QMn&w6 zHH^q}MIB}*4t{+F0B=CuOk~lE6#|O-RKr$|TWF5ymaz>mC`w*iC)wA%(Yg$wK8aFY z@OGv-hukoy!4_VD;F~#2aYcRb0^t(5B}~+ZWRvBLQzy!t_LD7BLgW9%XM3YI5ti~y zg7PQw2iqWT|I62>M8;u{ISZ0&D*6KOQHH4=L-oPvEukAoB@F!&yeq?R$Bf-G&A9yf z-ru7OvAKcWEXL&--&I0XpX28yIh)#9|G5wN1#vdaQ?8)1kmQSoK9_5{2iz1?voJV6 zxi8Y(>%!8O0=axTTVPzhxK9v!H0{)`Lp5p)#<2Vw?FHt03(71B(o zCQhO$4C8n_$n~c2hipQzc_{1mFZb^S9X+Jw0hl3?ZeqlXy>2#XEizlw*2vm0TyZP; zjYmB!%ZJsnDbB1uu{SthKb~-ql~I^#e8|yFxDj1omqkN8UMB)ra=}b#A>JKk?u4<`}4RvRnVPec%FOR5ND8&ozB65b`qvbuXgYeW7AZDba#8*&sZJUD8Da zxvd)hfmGF^waO8OoKQQ3O#v6}nt3{BvY`4JK7IP=L0nFLf?qxHft>S-4?(vBpJX>E z!_Zpd2<|xV67vF5aewRwEWrYme7kxg9J=c<9@6lWly=E3NTaGPMZ zLkz(`w?BA?-+rJAA^bAoDdtG901kkf(>>)fE&!U`)D{i7zOLwGKNzCRtV^c;;dOte z$B{aK<+djP6xc(}K^|uH!Y%&5TLIJ?=y2WM#_|vhlK~PJ_7Lj=+xr6Ue_-H4SVS%V z`f~}2--5(1;^4Oc=9^&n-~I7d4QK5DxWLx?3W?SN*aQV&>;p3oGn)G#4t`+)z;S@( zxC3;q1U!#^wY3B%xa0l7;%2i4`hVU0^S`vV2z~hhFgk6^i18;_nB^h>6F`9HC#d=R zYZHb6P+k&@=MniD0%pv5lef~h*1Q?o`k z(5g=M4%&s*MR8GI_1$!kuK*w55+o1N9Wu%N$>9lgi}9D?V+zmi(#hW?FPCOchj=AF zm<4t7{&Em6CMGSh21!%KA#QdV1&eJaO|z~WAD>JG=(&GZ-9Ium9BFHkGc*&On>zxt z4}f5>V{&0}-CUk-nl=wL)E?690q#Bgj&PH|;V?zC=nMXH;2eP7A>1Kt)Yz@wG2Sfk z5v#&L*082=g?5aM!8XG=L%&)+p2w~TY7J^&yP=lEPvNPYK&n+%1mTS&K zCz@eRi`jhJ(ytrIG}$U=;3QfkG7k>y2#>)h%|0IkcOn+ao8Q{O!&4kvJM-52Tk^c(ZvEU=XmFQzc>7n84lR^xW|k@Ctl?m!HUYZ=1}@lOBiYjfz5m zVUiyr5cxvu$)_{<`>6(Fp}`|fYzWiilqO1rNN;XHMn%d^3@ z)%L{}Rt8E7$_pw?U&b_Oop9@;{rTYviFM3Qc3vHSAbVfZJd2*jKzDF5_y{5sxR-YI zJiQv&l2w>E-C>7f4Fv=xyl;GrB@pvNnuR13{3nMxZYkb2AGFssG)AHDC3r>h;~*Yq zHXP~nVmWuc*&l5MWqRhuXjH`dDJ4$;=piNftneps+_e|+Cln7cutg<-!y8%!fl@*G z6uXq+EId=ZIDw-e?Qz8W8R`S=Cahf_XP5{v&;^Ifm74T~q#P;X7BcX^aO zA)ntZUBODe%lk}2}@EsH3gd34v=bB35{%(weXW`7%A4^F$_Y1h~e zSDp1B5QACBLy#Q>rpl(}PiVp4TU}>+$L-#CFd($q!kT<}4Y%Yn*l2t835ND)4$YvQ zeI{u7ZIic6{2VsK2#t)i5=<|QFibWKH;g?-ONbSJ0mjKfS-a!`eR@o*@v2B6{e{4O zU`u_`0r3o2;}LbMf3b>sh*6l&*W2!ZN8|rkiZ8f2gv6e|F{)2Lg1-AxkH>~{bA~Be zvfU80CF)j=c~$BHpIluF!muJAPlS^f?Npc?d3K{ zS)(0A5GMrB+IlDO-Y?DO1V9DU5T7L8YY*l40n085KYH=Uak3!0RQ9wZ)NEBZFQ;pV zT1)+FQa+JJ%Veym^D>%K$H}9(7L79O1j+=XIkW3X7#l-XDOHmgHjNoIofo{_LI6mZnocSg-?jX%t-QmHtJG$T+8t;SJFI2ji$WZ9OS zopL+!H0b|Un(nG83kOGtq$}LSjv|tz4s&LgVjikek6sw>Dd0m|``4Tk&mX!aWev^7 zQXOC@i?R&lX{bb;_+dGa8h4Bj2 zU_~R!3Drb_z+J0y%FWBIP%l?E*del6=rY>GZrW^ObnsQOK8hzZh+e~Q?0Dz7fPIg9 zGi&ZbiN)t2Y?%J5$cN_GXa?AkmBq_(n z7wx2xo%jrdo7YdnNZ-)I`}do&>en>2TbHzK@{Mn|@n;z&(*YbGGH4gJ5KTIP=J?on3rhfbiti`@+=#2XuEwDGnOP2n2zu z=g=ZWS4pBE-H^c#7!2o6!lMe(?orKOVy?t2dh4oSEi$|5DHn5z7Ba8eG#JC7!pinN z;X{0B@&2NEg@)hB!E7Uja|$z_NAoG*fdTiKG!XvIQPbcDwYwRcBW7z%unbI1I!kxs zyt^)!9hNahEsSLvPBSbh%`6q3Wt%EoEJx8QpkKxzd|b%2tf?wQh*dTZvsK+duj!=wr7X8GEf zXYo84Y&Th^kXO-EQTGz&s*WbTxlb6%l2mBtHLEibsYsMmusj)zSTk@YiR&u%5oZo> zi64f*N;v1v%f9BEqX`gVXS^T{I^RK5_1yUF04|4D6m!=#46E6m-u7*~^%56Ll3-Wz zRw&ZY1w10=#SxRW&0WIp(szuRAA0)E9 zO`GXRvrqLv?qDk4#&gbktNTsh=IY<$tJ3{O1TH(r-coDms~Fpq9%goCaH zqxK|Q=vz`92wog&IKRJ~2yGLRYWX^k+Fu{K8j?_^<99Y*y1x@ki@H-&(_k03u+t|} zBv5dC^1=~Ul@;rdN|(m99@4a{zCJn{VLdye^EQgrehK3H?GNZ@_)CE912Mp#5_<6h z3`Cw8YJ+&S&Va2PGDzE|)eq+&1`+6vf3GQWG@B97W^R_4^m40JESImjy;L9EiFsvz zqFPiemS0>%?`sW0mfU?|VVrFty4iM(Xr$>Dttx4A@}fyIo9@fNOk`>W9TO4pLhM1K zfT`A;1`s1fkwi&MiBeo@Eh2STP^Ov}lC{n_lCvOcp|oDwETfSX$x5}Q+`7=dX`HVk zLe|lbk`nMo1x816r}M_Y)V~WMXg2Xts#jjTICq*|*-CzBHeFvtMNk$RjteJS**fYl z!IVMO^08y4FmivdXr)7*n%mgXjC7GyD1p8oc?W&k)YNUiH6igDfpF(Qy3vfK=VXNj zDoh%?Ro`TSX~`BM8wOqCvOsOo7DwA&stS$`Nvfpo3c%#F>o7N%D;J&h#YAtim!s$< z4T~kY2gO}v8Me3M^G375!A(DORerJU3de#Q7YFxCwp-~79s8dasab%l!;|3^s5(_o z&A0HI@NZZCv!xPD#c1jRO^wn>#U@ChXl$a9QIVmM)*|x&)ntVs?uA$`{F*r&l-;F? zV^+qm?;}Vv3hjfqR;r|nXt8lPqLtMQGwF!&1S1M`6#n)*IYTQoH+V6nMCvLh!6Dib z{u@ZWgd{e``KqBJr3oSd*9kOqo&7`Qktv)xEX+rygB_HeGunbg&V$1w(wDNZJ2{=? z^wHsG<`#-o42+Gtd#}*h&|`R$)qYSOU>Q)+wyZjJeZakz*fwq-=7;X_nmn2>_g-s4m>6{QzuH9F9 zvF{JRYn?$yha22^qtG@|o;UgZPM<5cGDjo+%mge;Gn)ozPlw0fSq4<3HTa*YcQpG_ zPxXrJVg!f3&yuKR;*7&J=b|Dt{oU^KD;7PT^W%yE{9YFTYz|>l=?2R5&Ze4Z2Vnfm z;MoZWmlzdSVO`F*Binrpln6Bx1Y*Kgf<=gR43q-GzeT)O;SOOB>{C|kVpo_tf?N)B zC;hv8fG2+Y=WF}tX9wpk^b!+83sQw@t`>~UV9a`!>Yb(~p_a_>nSrQdd1TK*c@A0q ze#IjPi)QB)KbsF%Kek^a1xM~iwIOgnccX2h?0f4Ov6k9%V=sdzqhjsGV)-{WVp~oH zeped|4fqc6+%ilv^m>ejDD6sv(|`*Bxr1`BNyWikL3Y~hB0c{RH}psan`U0&~E z?%Nh?l=m4UTdv{bDTQQ^G3+hb94+4xYM@`1d^}A+!GreA`C3-;50Ux^>UiP`( zW#UTDe>p~~ObTW5HFMH5S|9Zyfh3R}C`@8NTa=dDi-|19+m$60qeDg&i{wqK=@n}$ zQ`{GgL@VKFTxt9?3o5UctzhgIOA_ywI9!5;q4bPCtN-@ixFq?R)|wv z$tnVnVm^m?V!+IQQgWXLL~-fpgr3)9oe=d4Ex}eYG&Bg^&~fV|Q@YRBso_x?&#!Dv|&&DYJ`JoF4@DefG z=~uO6JKtTzUGbyIDy{>)%%W>#*4ZS7kjOHoUDbp@)28*fk6tM3+~AzWe7(^-M#{gJLGV0kt+5*$N)ATr;8Y~1A@3Nnk)$(2=~hW`eb;q1qD!gYB(dOv!v z69)e;EKb9aM|Bcrq3TZCz_|k9%Eu}ef$iT}4ZUo;(B*NdR`^xXxd*DxsV^ne{)Dn= zhEL=j5j$?8zYEv}_Ol1jGXyq4@93ZXIbNPQ?swITdOF*~Pq$H#(Gr|r4bgya$`9RF z5^fRA8?z0W$y6qTryw=?n`xoB423OaDj2mdqzD}?pMD43By$%2cIZ-Jr2Y`{rqrWQ zS~t5Ooz3L(NDWN8g?7<;lbJ$05x2SJiZt>2-%^`mUUr6cS zwsGb|(fbLN{U^S&x^MdB=HZe2T81`tl#bMP3*-nGz(s+~Sb?OZi$H7g^0f@~(#TB=c2L5^KQnfP?LWB_$YZrzcv&b8>OV)H(|fKSC@l4J!GpC2M&Fgmf0Zs=ljfN$uKK!HNqsgs#~ zyNtSMT^-rZq}PD8fX{%ffVJYQwvARF;A^d}>qAm!i>Yd_T!1&IJVY*x%&@=1W?p~+ z!>U6^?nHpNc$#8Y2W}~~p5!K8&j$G>O=82oV}cfOk604){v=Ot_>Y*!J`rCvb0IMg zU!y?IeXBTZKik_C-1iXBn7(~}9R@hNAxNmWF*!%8J>by6AsXWrn>R3=)rSI?@8xpY za_jnXsaI*!*wwGs)o|)%JbhGttw6vs3;8wVAe!qk{id`XM-Z-kuaSwJqR@TVz%$S{ zFrcrY;^C4dXZD;lrZ{Rz!xc}4SC*H=Bt{bl%QiALoXwrVHN2hEsM50Z)i}pD)GgFU zYmoSg_&pFz(mG}tn^*=^Mp+gp6PJ<896_Eohh)owO$^64s!_%M7gtuQh`Pwqg{6H{ zM~AW#(vc)M{2qZxB4w5}v;=JjMyuwtNf~>orZ~j*{(e%=lLrLh5v;0-nd) zOL2gE>>plN8zH+sJ=#`3itDrI>rD*4n45M3>0Rr@wvyGYcD>V$!tx7RVR+)5S3Br` z$a~QZOVN+NvRx$BC~l>_OObm6zabFS7}<6#99_=QEJGco&LxK&|FJUNyUw19jb=E8 zFefygUlto`N-1b0G_Ke*cmVD)E@qCE(XHH#ZxoNuxH4R)hDVY|xsXZt4}g@16!H7B z`DofiEf1$?&0G-OfCg_R_8G7Piy4^%AIYc~=|r}3HY|Oa$ocbTF)GRXRadtnR!O=0 z)9C17ghnbi^<@#942uneqE=oPmf->nCWCk^@qI0E*x4wDw#ALTzx#3Vu#!}olD{MJ z7E$0|GpJ&5nMtZ$Gnb#F8B<D>i60fICSw7R4}^%wLWr$^CpKV`}z)S|$i_?KKdX zV^iQlucEl_J(ia6NqXU|+jMUjb|)91c%9xQM|aY-f=Ug(50^d-yyw6!-BA%eA}#QU zH@J342|0=Vjhu>GG?7@Oj65*Wt1bgU!+d;dgR987@?k!^Us|LF1RkP2F7QOh&nO%K#xa?)?>k-e9sv%^DXR=-lY@gL|p?oJ)OawX* z-u{c;yz+b{h%&#MKgKpSpYd26SDDtuy*}z1zm7jia%yfrFg{=EbG<+427j;q{?=!( zX?sJnO5B%RF{_7bP|z-|nXO&?i-KH{2CV`S!^XBeaD3~N*sSJ~cu9=a??)A3P6Dn> zL|gRBh0JuZ))K%;^Y|sYK`F({{?H3T&nxE6kNU*fVMRHnFMEp$|H?EQMvM4h8b+sI zd(yYi4C5Y*&heX@Mv?0;wkCDfoTP>Q@@91kq%~xQde(|aZH%V*mdUp1C(CiQi{v~G zJOmHg#5QG(;0+W0UPC-~=Gd>%lu>9?$6t<%ztWJ^vD9(K_Mt}W>AXXGmg!bI3b?-* zS@`R)yRhfQI!GKPt1Hj;bIsTkc`fBKq`yZq)CD>qvdnZcLvDmc;E-rs7mvAY@ z&LrKG&^%{3gmr|~7ARJ=9D~G2{Pm<(Zu^^6m~+P6>ZNFjG|%DLrGp%QflKLv6*@YS z6}(2|DF};GdO^$6!W|F@jqti~d=LDt?er2mu7`P4r^l)y@)BhiFGuP{J7@40)7}hV zWzgCbeh_$V>V*>u*X=#mB+yd$Gm?mscLi`}@c3F+V0e(K0|S5wgR<`t5fr?QMv>;p zkQ+;ujqVKdKGrp5Eh-1X5z?!Yyq=&%$=^!S`Ec`sLPLfICMXCkNrY5cr1bEPn(k0( zebFq$VhAfEc*q_8%k)?ap*!!1j_ztPaS)1apmb}!W?yp;5v=pO`e6>YjSO|R!RHN7 zU``OQfBZ0SS*N|^bd0(NAJS8!yDKu!)I5@HUR9 zIm5ECu$onf$8_%BY62|X+?(mwcB|B|dJcZmc<`_LlbL!1hY|m6YuS}c^FqeEg z8TQx90*KCoT!7kx%R%yqONXQRTJ|3hkKXs3TMO~a(If1h*r3$#p#Ir+`CLQ7+aR_} z{zpz&$s^7ip9g$u-KXCcw~P5Iy{CVP-goD_#$$4(kWP%4#PjHD5Yx?BHA$Ffth>^s z)?Q58Ex|8M8Be&x)x&p6Jwd+In0=o&EIL?$u31`ISWW>$dE02|ElK-iYA)F#u0P3ig4g zem1NP4^$tLTOSH%$70&}UWpR?Yzp$znwC_^N4Lrj=IH2%p@J4#GvfEs4rtCeQlgBG zi9V+Zfmu zKi#J|)R&4nq6Trj-jO7p-4nFa#8wUKL74QQI{F7ewmaRxbrWTUy0`5)`E^3V7Sdb( zefN;@so@W7B0)=?la0$|toO#9T()3hG^5%dJJ|%SQM8S+1#p+5W??UBCfso@%Tj1s zrVX)Hrd9=jZKD>YWQ9iqg^8@q+-zX$X@zeZ@eo>qt1`&m&g(73M@ByiidKSKz5!L- zDAne*+CB+zQz{#ao=rTpD^zZ6z$8dbT6tr9bU{Xxzk-myZJbxjOTu$^#%+O1ggArHgj|a}_>M1ms%~m< zR(Ws7ukP1CS|Yh-e1)!=HV`5JMfkGDF2tQ8!z)=4_orK~aZDyl6mgdRO)7q?pT!i< zRK6P;ACHk}=4qD)jOo~U8c`NMo%|2Vw*2OZthiV^p^$(iW-g{7_TOa&hV<=ZIUoD} zO~Rc=2#Rz>#Gq~4Yj8{a>WLa23>daM;#R3fqt^_Lr^WW_9PGbMB?dk$0ON((f#`N^ zcK?y(D#X_mr}YwWOoe~68S6YF%-c4kF7;g)ZY15{sx#~{;c-E;A@h#iIeMG=O1n{Z ze9-DV&pFjm?#!50QXZ>_XKdH7X>?^t%@)l*oWFBVFPx!C{FrZ`s!)&LtR11%4*3if+NRUM zv{y0=e_fD+3kBVBbl=ERI^j3ET+YkHy0_FI%hji;YJiug`Y8R={UhVM)ixzPZ@F&;F&* z(^#BVhrcdw|MmC)psb)?NR-RdhBIkF!TZQ5Z;{7R z%hpF}H-EKs&AQCNl4&s?wN3N5_$UpSYgb-B^U!{d-D|%N-fR2_o5LhPCMX&vGZ~>Q z9j^{g2W1pD3dU5$K>?~*MT$zLQG3L!4ejEAF_EwF}vICu)V3 z*SUtT@2ggdkku*jVrx1eX$%cQ2Bpv#iceaq zDlbLtDF~YW=r;Vb7gQU0G^}5<8di}kyp5!m?nDe}SdCAz-^jraoiFYY=ssUYt zG`OloL)4EMEQmA_15)+Rtz3`cO?b!>KwcYjwM=Shi#i5Ps;|A_sD;|kdiWxP(`J|X zRE4whX+Il;z@7$VpJp-$yIVU`_TA>O)So|= zNqs+UK%aZw!JjkfM4a8P%d%ZD#!}ZQ8di6fk#O?GYkl*ld z@MN1ilJtLVgH6`@9Ll&H{Z6Pw`W3dHjf4pPKz_I8zx&7u9yf8)+;KH*=-fmg0+b-{ z3b}68X@NpFgK7%ky5jR%68E`uqk7+Jj=D5o+{ABMWH-TPwq-t(v5l>FZc}#1EihWN za)tz-v2)sVpQd<8mzQuFRzKl)P?NCG&fp>}ZrtilqcGG`bO(FHOuGWLc4`H~$NSK^6X4?jEW~{7yz89}78yBgY`I@q_)If;Y#jUb zeni`$K7G#H?&D7)4!W4S%zPwzr$W)KWnT4cc$KTGSVYYhUKIEU<KfJZ~J^4mzCr_?5NYBRjUaH~!6Q zarW-3rS*bEe-!aYpA2mpDR?4|ny#4fBI*NTOniH0^zk>};oDt9I4k-H%n}*ARS0p) zx5gU!sL^Rr@WUFohL zUf8~lpY**wB&3yxEPvkxrLhBm7X-TAPd~G6D=2zzOX$D$?&$rc_+Xpfp~JWMoS4=P z%O*|xWv(^0l-rabQ;e~hArf@lV--9%aKDLP_q_j|5wN(`-?Wdl))!;)OO>!`nXtr9zLr4 z%NVR%-zflz$FQQf4e{W;&PI4AU!l?YQKdb+Tc<~L6E2S6zI(3IoO4&UQ;LCbCVx6} zra#+PLHh@9ksu6&m!T*~MF^v~coN#=b;WVe5(xhQ0KY~J#*7uRN0`HzPIR;2g>EMF z`l}ZtAA3q%DnU5UL|n~YgBaaB9!a;^E4;qoTmGr>PJoHe{FU(0yl43;@(z1d*SaC$ z-R^_KRU;^Q~jwhJL z>?Qt!}oZPf~9inCC+^jqDlMuuJpptotQsJ!B;lRc@{*iNW7t`fgkI(tVq$=dg5kL25YIFwrx?j_jeqVZ~wPrNKwiLkiIU20bHt4g3n+W34)1 zTyPKRV+3qGq&4=@)XW7TU75X#M>fa+sK+IYSqZfHJdcy&Xoik zLpV)|2o%#~FG#u%m)O3Va?b=!SQ|Y*z1Q-*Ib&1#oS5g)_V^H};!Bkg02p$7B`m)1 ztlH}yKC<}feco%U;{5LJ#^U(jUJhio-=!t*4C7aRdOniOT`yh7*bV%egV%!GN(e>X zBEKMimKf@SN6E@c0bWUuy5q>q`dOVA@(#1~SQ00GLLVE-M$Gm4$cm01q_3q|#=#eNEtGF1-!R&Xe57 z%n^eu+ho&xH9D0#RlGc1PEuA}&EGf==ew<6>ZZ3@guTM;J-UL`e@lDD8*V>-jO zi~I|!6P|PcALT6X_&Z?dAt)mY>_a?Mlice2uTc zevt2EvaNk~N9WKVbYcs^sS;S(4;;YLy&e*8a=zxhQJmJWk=-G0@i)J<$B_6~-??3u=5!(7vc9A8i}I7b*&u4tBJ)L(_Fh9?YwzAO3fdbDdRCnE8t$6P zN5P4q+Of=;zoV|SbIS?4Hb9qK{1x8Zt}Ong-|%27IAXMI8e^A5vh3_QS=zz_KRfy= z`a1eb`j#vhE^?HV`>_+Vva+!A4E~-EapyI_1JO9cD z;#6p<+1l^O$KVtD;y6>MvJYM1LRm%Ivm7i}NdUkhbvk@cG$HBB<&zMz=y`IHx0kHk}9CyD~d5{@2o+Eqay z(rj~@%aTI5El=i4@gZFw2CB0W1=jUMfbnb}QfipK+z8o*xvp3czW}zwpk#J;CPVPr zR++;svEMpP8odxB6H)ghw}Ms~F-12IZ{7?h5o;YDW6A^=*p0&D$xlWe};}-C0ulpE2^? z_etts1vL+?&d*mF_$7=I-!}VCZQFoX7t1_42frIxc6wk7 z%_H0NX5;JijPDJYq2J{p>mKtPy}-xUhDDc}| zxybgX?(EI_8QwiEkmqRb>JIlFunr77DHNCIK|p+u7kOA*BH+-&e__wV^yl*dwWEL1 z;T=mY{WtY0$F@13KSKCYK&#F)&G5aw&{!o7CjSZIdc=82jB6_CtMltnZU<(QEn;?( zF+66qZF5>A_+GSG^k4#7Sib(mj)tnMJ#4l1J`29N*Y&T>InvC&O#J-vHkt}lcdw6 z67GoHYfeP=CePn`Xn>XEwfISj4AUe^C->Yd&F&)8p6to@NKLEF=6!Z_6GqG3=44U4 z_dedC8_h$t$FSNXH#aC5{jgbJ+6i*plIR=%@qFWa2$_T%YxU2tTqm>o_ZgZFV}{!K ziU>Y(g`hcO#$+S78C;;WI{i{smSozIXA~UXl~J>81PUW+&xr6j&BPxV>EP;yO<_`4 z#wheAQfLs?A2jfd>~?bk#@fS1x}n};qE$QkHw=gwV-Bbi@{7bULFkSWxTvoCDTb9}w71iP6O0-WRupda-a)|J&lRtg6IN;7>*Hm7NnXJCRg zDblkd<<+aWoL|J?TUM-5O|-);8(}TNWB)ty$BsRZ#lFokeh@f;P>2*odn`0zjB*04 z!0_>kQ!#(~>jZ0wD*Q%QF@>Ax{m1`{+%nk)iS3jfn_Uuk=+9BdPl(4bGw~chw9orC zG;avxy`MNVy(9aSo}V~QJIqVWi#&NeDap&6nYc-GACZ1@k4`IgpGrHV`^>1K7b^*6 zMP`JeIGbEjznz}EKD=ihyoP%rc8O`lnSk*pgQ4g(YYnN(*uvKRvpmUXfj6076O=L3 zN|e=)J|uHN`j-!s4T{PrfJDk=(M_wsb@^m^-pe-M{K5c$C8G_V^d`{@`?4K*gf_{!dFi)a zyf7Cr4}A{!!m|2acduxBFge4R$%gnB*~m5=tJ6cy?QTQ`46Aj@ZX)pQmnJOKvhlh$ zA#)IJkdWss;WIWS1>`*NQKB}(cUcoNl%Uq2XAKY`wF$bw63-gbXFv5zxP|ila@D+C zuCIxq+{VAbuZxwPcLX4aIb2^`>0sYAK7I-6vM6A1hQr1bl#}k}2!Okt6b6y5xBni* z=;4{UqueNKp|^7)#ZYoKo%xm)%eub~*qJhpsIl3(ne`xlOAAEaQK z1m87OyXt+Z_%7HrpoiGW59wLE%ar*xPV~A!!wS(B|07KCsfl~tF>(G`Qo}?-BO8)W zO-@6DiDxarxf^^4WaF`4YFq1FOdO#v?&HYwsRyS^=_`S|m`Y_siC#d1O&fw10Skee z>mBUuqO1x6PRz$IDGgiwk<~Nn3{-h<+qT5p^=w`|4h`q5;%4E-WQgl`_ZOf72pny@ zW7lwxaz}ZBg?tfi^)O>Fd3zv7fE_OWCJJ*sbo=D|$4xBy#t(ZW&G(BLfyEwpQi}H(2#L_L=X4 z5k@t);rGWdAiVYwcR4|B<@diYUt;gq=Z@EEbJ+awh#V4QI+Ai;71^{S2qSCUZVMbT zBQo=g7($=Fm~hY__vt;rZ9Tts=;=4aIeY4X%2rT>>|Xm&Lx?Kg{^zd{?pPz(|2J~J zAcEl)>~43)4HMcwdZ2JJbU%!7A+%q@kl6$~F5{dvNPm8ZA*Htauxd2bL0CU68BFzJ zSFfoDvA$c?o9V+ZUserd{vR(PvJ}+`4j2|xAq-)YyFL(|G)SdCpNVOTzj?z%=TE<3gYm*o(893rYkF~9zaYXgroX`r5$~Pcs7_=5Z{7DA9Oh&=ITh)3^)Vd#k_M3&WqedSzVg&3W3jE0T$^`XmSAevQ&6yX;LkNm+W&wlQ~qN*NyP&>=|(LL!tokPs@~#vZ*oztNc&BWr=DJ zdAl34P9oSc{l4x}rRT#csnhc|pW-#=Yb4F3Cd{3x8c(u0WRBoZ_T&X7GAi8er#4P)19(>h$D?ZKuy{xhvtcS3TI(e zDXDn53-#BG((da|y9_j^A%Jp|cJA|`Nk|;pwrWqCgKYO7eG>ibg>)e}(Zz=c;vJPg ze3bOosjqI`#CvdWt$}69-&8XGPyRAQS9!sXB?EgB`SB;WfS;EkwkhmLp z$5@B5$I4gbmMZ3n*_t+_(Wn$tE|^`N+Tj<;@eSs~JNE7i z^J#8BGX1^LUbkkJDlVKd)^1fjUw<9UC`hzX-y;+#VGo-<=KloeWv^*H$qy{Q0Rx8=<#iCvYBqKh>AUANLlU3J3^auoW3(5M3ijRP}+Rz z*Q2f@-+?QxIUH@Mh6-9KS$oA3r+y>eh2z7oi@JbO+Z6JbIdeU?C=chStLZ~M&@pp~cM+1ucu zLU+)$9h=!&x#o!LsJ9b0fgYt>bdm9m+@?yaFK_5**N{$cs@+chWM3@GeU0)D3r@*Mxr z(tZ36k$Tm9!S<`(#n&INWNv7$y`Y|4=|Vdm5zM4Y77_{XD-359yt zSGI&fxb$+IG^(1k&PGbOYkOcImyV<6Qf-+m>F?9?i`uRBMXDY$4}wrw(zd%Dw`1s()C8jGXFmWQ7J-0zKtjhXx%wy+9Cv2ziD& zq(eh1z#LY}Oic1eij7>3+JO~c-k+ls4KJ;TpI=4*IY|eVh-M|qQdLtv#q^-#-^pgB zn${2$#sZ-0WBwUVnudC^7%0CNV?h-rX*H0d|6SN8nX4@7{7x9f?wHgQzybX_5G70& zn=VCdScCKC<4^kmeX?kR&XTBThWf5r?XMO~C8-dWs3hoqCW2cz)~NYwF+H|QKt$O+ zkV;w+(Vu~ewIko(#*@J*aZiFQv3wikIg6(ZBMe=+QfabkA(L&%M|9MNar&Wd(nP?d zA4=#KOvD2XDsNff7VN8>St(CB+$WTsa>LqcP6SK78tk2%tmQ0#D`AG*7&aQrI!EmU zxTb-w5%hbZ--sx|JY4h9hA!zZVe55cUG1Dm7iUtoUK1=fW18+-k5|cjD;e^PX?nnV zgA_(pqbcs*Sjru)2LG>#D^n)F_?sY>rrprr9=Kk=RJJ;V*U+gc1x*1_Ol-^xG1V1+ zy1Dovmpa>GW9+fFSi0>13#)3THYy#i3%74I+{@G#Y&QCRz7uaX2Wm}AJbaL&loy#; zp+pdO0@onx1%rqWJ(D(csX5vLT$7&}rKRY}AuBUp?{JMh|$RCe)P}- zj{+-Wa*b$bUf{Mx!jTjxJ}n1vJ}Py!;V-vqjWQQ1+bR;!tG@y_=e4;K@^PeBn{Xk# zJv|9f*^qA#$pNaLL7zctK%IhkT~vgbnHl%8zoBvFN-aJ@s$xzJo~5v-f&FL(>$w?$ z_?^EB)gXib6c@!EB0R{-Zo~EVhlZ0{J@-BiVJ9#ZCLF2~V@g&WDLZ(^j)hsjzSwal zt0XB^{d`c}Fpj;3*Q4~(Y(~@(IkN*t(0QriiCYF4zTXPxv1D+prNv$^N;8?Z47b`` zX3la$fGgWcTKim9Z6L+6uuLz_?WboDGS7dNMcIh7CI>DYwxsC)sU;N90@Y)R9DGaG5z+J^8OO90}=A?NRKJ!bVj0tr&lAQ`(_JVzl7;$?MvgsjtHx zMM<})yLw|R%tamMYW{v(aV3swqPpj{BKbQ=l@UCLCDO=@jtvAx`|VEK@4zX zH=dEWUBci6#apDoi*u^`^@uUoKM5Iii;)ZC@jc$byRM2w15fSW&AA;DEBO|e!EymF zimXT;_SH`eF&K6J?hb6J5z*E~gQ|P_@HNJg!C9U#42!JMA2TJ2;*}L09{g)lzkY37C6YuWRu9DZ*>4@jl5XFUCJav&|rRglWrh zSgq1^s`}fW;Ho7KetSAbSD6?*^7oNeUM#s^FnXaDEwD&St9UDMs|dw=5xEMqtQGxb zR!OYX0rGA)?qne+>+zsUt2SoetF<2mMvKD`5!TJNCzz1xn5l5}h0tuI-ex;UzN9)x zwihd3L8T2#a!p^KdHt~R>}W7;e0D64dUizN@WmZ)dL1473~8UEUA+GUajz&Y{9jdI zWBC77fsv4vfq{wPzjY}bjEt=Rqb!%*?f@0lXZmh8PIE8WtmZ#5yJW zJL!1#xp^OZHzeO_a-+AdYk68f$%aPyF)PT)Ac4ba`I6k=4WkAU>;r@J4@Vzu8Oy57 zm;Q5h6oRlUCWFas{!_N~6C$1kLEt{N$Ne~ceh239$EP3IDZAO`>0XiC@uo%yExu4Q zei-z!Wa<@WZ>$6+yX874MO(7x4+%Db(^7AWI9$2qt5ewBv(UQ}a(F+3$Yb5lgY>x1 zfP>z>B(XlZ(PI#sD?}vQbSBq_WCFKTU-0i_i=wKV|VMK|m{D zi&S&A=j!*)o3;9eBWKELX-}oo+9jbC!YEfwjSPOy3t-Bi4d4DZzN{jm>1jKPS6{7Z&f08ab?)sd!4e{qDZG~5kM3qp9&kwFvtv~KKcSz^o( z&ImNL?Y7RaDjPJ3;R|<}d-7+a2v&8I*fxSSm*qgcSPL#O zxafF#ZtxWi{B#?%H=Y)d={t=hjo7A%+lc5%F}xYJ5Hb~7a2>fJ95-y_u-y;#m?T8J z{#%q7Z;n%<%a9wEfgkaL%-{nVPJEBUq?kMybuPIVjFSZofk<}b6%l3<#}Rilf|Gq3 zdW-;f!B5m6n%55E>Gk)ZsPo4T;nF5c>&D%-cE5<~?@y80De6^f0_c3BQmt zC-QM2z;*QLgow=`OC8M<6a2H`8(o6=g*_6ER)l7#x0dZz@)qI%=%D*;M%IP`g^0umnHFh>u$7RUc%4vBkY%Lz=eucSci|+|n#v)lsW4Y8 z&u{}36HfXNgefm5R}<%I>ggC&9~f$oLnK>BFI2`z!=;^t_Gxl_21Mofvk1}ip*f>G zk#Y>0Yuxt_-4RSQJdri4e4!hMNg;ye*`M{8XI{w%;=z-VcdQBn7(~`E@(L7zEYGDK zrBqyj$v@iz8^0t#ZFfaU@E~Ulv&inDnyIq#aq=LxR*M({^@FBqptU6aLCb&xje2jO z52^$Ka5@v)nELKGy43k^=`!)LyFBiM{QRNj@&DMP#@I9by%g>QL*842!Lv+G+wdY{YZ0{}iMSHW9AF%d32+5$E5QMidKjAm7? zM5QWdKh42*X!<1Ytk}H(I)C5=YN#8&>(2#93H?FCR@~IvxX-){S@v84Su~(j-GbFm}gn4a$&W1M*mHoPOw&hZKz^}Z6a`!n>Stj*Y#SIUF zW6<2>Rx?8H+ZM9U)n~6L#|9Dd0*M5BVi60uWACc+uZ!?TAMp>LCv-pP|9XFDXDs!p z%8lKYLH+qAo_-G)<#ny!!Pt~f!hV_;;5x;AQltVU2ftc#j_i2_&sBJu3;6rOa!;2| zy|mw11g|pMMO7X&E|2>xq8G@ck2v9gpJ0Q0PEtw|3X@A|{nG&TJ#ZCu&FZjeH7a$8 z-R0vU<=n`h#D^hPq~!``-iBCn+h!%Pkkx{|JY}~+6>+`c z@$>_*Hp&P=y^;KPpf<@6{e+7JQ8H@ut7Deqd*ONe@xirD5a;1B?tEN6{BX^ zsJUZ*;&0)P78}Uvlb_8OP-?L}>p$5la6LH`GrZ05>l>nizv{1c(V2+r#JFibB9;^e zlnM27p(Yq@JA&O%-gP4_fr@?$3hrqJpY8cu5SQN2rBR)pgK5ZofwLGXkV1z}BZxmt z;RfXgzSi99GhD+)D97*?s}c}l^Et0Ez)WXiEwKDi{3ydse^Oc={~(hy3+0sZf&d7# zG2{KMSrvW;dNSl92D>by5O;uQ0-qJtzk|!tp+o<9q|xd^O^K(4^QnOQAJ6&rRP*w} z1rlWh1^`;Py$%gO#?7%XL9C6K#%E-US4lSV@wV&sQVu=jUej)l;QF+wIiNTE*zm=(OyR(QnvI>+Qjpp3*NF1yBDygP@BO0sG?SQf zum;d4!^U5Hc?E1tkmP9_`_*`IA5wsrI;QyZV1$;N?Y^-NxNx_6YU933o_HG$_TkL* zfpWrI!XSd)Zt{$UJ_=xe5$tZtE)rQd*uVI(^nRoM^P-5NQGa|w4+b)skeUv8-9IisZZC=PaOE8D^E^U?j*%~l%#vKI*=U?1%< zrqlNW>v{H{+TXw?G2*{NJip)S9KZJa29PAoE>ai+h>hDuj<(y)i7h~4S*0qPWbzq( zv0br<{{DW1uh$Wn(*@fCJpjiBY8QNpZ4R$22iC2YCGOPo!CyGNzwN&8eCQ4%ZBlQC zuoQpByIJJN+~YN4w2cGu{JYslLug-*TbcYWhIcw0wJuq|H;=#b{5zdd9C7cCzpr|O zQ;^vPX)cF3AB68`<32Dyle+eh{k@vWTr0vcW)U96-=ItPuCJtpFd1wHnj0kYewKg2 z4=FQ#9{l)779T3j*T;&md=GS88hCmGKVRtuzr~PR)b9d$v~D9IH+V50#)b0>cyKMY z{-;{iu;-gE3ix<4#LNre2)-j=@TE6m2vsM77hZ=$4y-r&WCa-{c%}a*L|HlG&*T46 zj^vw=z%|cqKM8Spx-t*{PG_q==__c= z4s+^9!zR;;3Pu+q<)1|{!dXIst~CFnBK^}bjfaMf>og|vh_Rv4bBcd7hvSz~oMJ>X zjIvCQ;2Zt2!P=PIKJwbmLOdFJIrxzLg7ZsNzYF?c{>o|A_Y!{7>!iClvfz}nBY94t z_?vX7^h)Ge(5>bxw@rSNxRb!2`rS-l|9!^5If&~f-aT|>u_xhd!m-Zbgm;CPgO`No zj5oun=hA(coJ}>O)-octXI&oL(VGYm#r~q^TN&qQ9+socvk?x|Y z8z(AJ0{J=WR762U>u~yT@UU4#Mnp%%GkGe-w7gDsJI&qQ@KgjnnHo911W&RD&E3`T zLPQ>!p4&+$?{(}o%Cp2X=JPQ1{I87^ww2SC)RyLD#f?t3wpJh8u=VMd9_uKplSR53 zUEPa19K}5K@2I+I{gdY??!|h^y-o7QsBB_CqLXcrX`jFO3C_R-XX@3aYzLB?p_{#` z7wq0#`#pM~)fZJCv1dupy!U(y;YoI*INhuGv~E+{20Q0NERuNeP(Ze{*mMcEQ($(M zf3`O|XWJ+G^rQ3kmCn*QC#(}4(>DI0j^qbrh;!_BsB=h6wsuN8m7_Pwi5&3>pXhXp z<>98qb1=2Y9&X2|HMA352OAFONyU}QMv0rjRrPx0`mYvO*XPAH@#z%U>DNB70i7$v z5{k1bnkB#3-XLs4p$I_qraXCKg=-cApWb*i{YcuS^gZjyu1z{P^R6ByByWMw7KZD| z`F53e*R|0Wq-&YzpH5d->kGZgjp&`Ri{s^~I`4KnfG$M;%E%A>9N5jJzV;stZxdbg z(|s=|Y1;JLaSiH77V7kBI@!RZ2Ut|P$!?F`3o{ILomDTxsaMvMwrqVEhc9r&XQAQO zd7wqcOj*uz_6$d!L+wPzhjYh?({u}8nj_tn&V0v<^W2HhOhOZX&gb4`O4CmEr_>_X z`|;Y4xjuJPPxj}^+R4l{SC(Jv!5V@&>hx%yYi^4;Uc?*qxirxF^sJ}UOYkxJ+;T~| z^0CsjvZWHWGN*E?GN#?nhoUX**5$7l%obUVy^owAJ*0#52R5vIc$4BSKR|=NndLjX z38djCZ=qf{J-r~;{;`fPqLIvx@2xNlnA_d~jk<43+_ohbU}?-=@OMM;Q{U8?r*!f_ z69WNyy|)3pPH0FyNa`SSJ$$Y(Mghp$8x#-1%C5Nvg8ZNn2h7RtZyW!sTj~#x6+_r= zF#Cb5dQ`D~2@UX~UDD{#0|$`pkhVQM4)C2pOb-INA@5tJe>Rj|#TO_(e?&#Kz90ev zXc_-I24wPrhi%9#1E%Cbv~(C#2E5V&nH@y+-Ji+V8MlO!f}DQfY(qL8P=5{a0f_vA zzKx+gl9YzQsL)mgvDIW3<6ie@i$QVYBBG1C6!J;t;}DI=wsU5ML|TO;UX397^*3@gvQc3*%0?J4J%YIxbONQW0t3ssVY4aLMStl zG!ZUs7w4WaI{@|;3xHt0#{&S-kFPq!e#LsO)E}=qI8nQK*I`I5ZKRB|0=oB~gr|JVtDu5?j{T zf~IAG<2-+&JZUs3l{BYQ0zx)FVo^40wv;7;d;zU9oi1TAF+|T4xJqL4Q+qhI{>X;R zJG;j0VwJhwnQx}G0ndhFW5lhg$A;fKrDytUM6O=Byy~VYZq57>_KEC0)Mw0URrQJa zGviChuVm$)4F%#e=S%Rr*l$itYphvj?4i92DSOfR!}ANoFTwt3T z`_)b_f*Xk6n|5 z^GnM+zPWpTh5QiyLjF$A+soUfd&K(A&O17J!T8|m>!-h`e^vjm_Kolxq6gZ){`$iE z&i(H9J7oQ!@J-P_;0Nlz)O~P$#{gvM?r=Wb|0y?;zDKML*;VFY5}~~f3AzKyihi$x zj_n$H;Gq}Lo=?3s3N44h8-T76vZX&7f9|p0)A9}y1Pa$9SSc{)g^fwzSCit6!`)L} zW5gxB7i3P7vmR3D{Vluq?2i7`Ky+!xmi!C&3gGI?qu*tI5#mdt-;a7l(Hls+H~ske z1*Si(ew)%x!e4p$NB*vCu58UecS@@_c4iOfmAn_r{oGuWdO7p+?=Y4kgoTHK45i+w ztr;XUR+>qQR?*TKyjaqj5j-?JY+SvlnCRH>`T_2=hq_QP`!@^-MzAFrUhq>B>BN~&_ z>LI=1U{pTcvg=;x5xjtDEia3!}<6x+q?UT_#Y7pa~|Mr?ZkY>$MI_rZ|5%d#$(LA`+$4< z4)5kA)*Ud$-FxuwF+UKG7mv&1e!XqNc7vRPyGqqe%xj`~5q&DFgp`8Sc3)1$VT2pc z@o6>vv|K`4#6!a(e94Fn3*IY7tw`+;ig~g?6F@x;C2U1^|Hw|g&2CC`lNA>=bSGJ1 z-_<}VO?$!vk4%bjtcHwN!)el%j5i=LcQkSMay(@7cnbHGF6>#wJgq1b?u;38=)VAn zKzF~(JG+V;-WnxbpoCW`VFQMpPORX_w~g!U@RAZozPHPaaTWO`ow2#yI&CLcr_tKx z&0x1yhd~{Nyb-P`yGcZQq6BC}ew*DC)CL@sH_FvH-y7-bEJomEiTT4vc?1^eynjhJ=G_IDH;w{{x5=;qvLR*`QT?-0?7ibW3Zrapsj&UK1wQ4zL* zb!lRkl8P?a^)h5)kA4p9jV>q}>?I4ZONW?=m{nkYqh0wTrDTG`t8sO7jjNbYf=d%s z;f204ot05hp8fud5S8z!=s(!y^yWpoiiUTN*&PZMeP>ohdK{6r<}`1%+iVFicDKy4g;heI?Wpp-FjLgPj_$eY-%R35J zWV~0?sieZ(Mx=}SUMUfM#ERe0wwJhSe!MkhcrZmyH2(%7DCDG3)G)sx>`h7WCMOFK zQFX#K#WA*5;;ouDn^8?&t|?{*5@a6~B5#KmwMj+xJDp;ImsWdV1V+5&eFg{O4j2(# z37*uHA}=iwIY%0D!Ul+(@`jwo>Lo6eh{K3$N{)v`R6dsBsYbF?AypIZ zO;@7B1JR+yO0;TFQGgco3DC}W1&Xx^6l<9oNN&+FK$|oRP-|j(xu9A@`jHOd=(@j$ zpfClmgdPJEArJ?fSQvN_l*z#q53^P!xYIWtW*pERUhZu&~h&YV6icrxn@M@;#ggz-(5za$UdJeB(ExQiFlG#9$yIIvB8qr&rStD*sH1tEOL9Ia1;_bx5NhffqrsvyZUxkHCQ_ zM3f+=AY=@k!O$5fN323@LU<7});WW9&S0IBh<6ZYAPwO`6e860y-Mt+nx3w7cZ};0 zPT!@+Ap)6tioT`Lcj%i6eVhJEp(l{qk)EV)R@&pBgAVfn>zI+6k)~q4L|?B;u*Ug2 zSm$H@s*?Etk}pwIH?9KSqa}M^aa?W2G4{zkGm7fm_uCL zZQ5Z7FB=^j-PGe=vks%;;$HC>hQ!4^e;J0v#XV~thQ!5v?+gryi+j`r42g?-$S@3v zi@SG!4B@4kZg?f3NnBR%iNw*tMDIr~-H%+lAGvftaC*P^!k=7>?WxM-WaQX-PfAj9 zT=@Y~eu$L!CFNU4`Djx95GkKW%5zEiJ)}H^l*f>AJ1O^&@`EHBSy4_rdv1y5cxa4sgLm~MJsp=r~3TeCc=_VYb6FKTcv38=`AI9rx zgkOnyu#h7@P&m>qXna+2ULfA0P5R^x-RK)w@eN#tH{b$-;{v^bV)O6SxC6u} zYVC{rGv-p#(mq)4>xS)hju{c>DZ@7R#pT7^ z6PFt()k@Ua7ng=ZNC^a!aj;1-N~bQn(%^usYBJ8#OtnTeSk+tAT9vM9rgEy{RI#dP zRjAskHmi+ly;`eQt7SD;Q#GhVtNj-}DdGljsB9KQyfZ+6D`7JgS8=ac*fpZ2&>g%X ztOxDUuOsQxLk!QHQ#_(jr!XyK~v2SO|hmPZTPbiwkXBCv(e$g|~H+gozFbpD4+N${HT z_s4ciIM%zSN58?|?XgAPbP@2!7WMExE_~Vjcz(W?-+4bCrI8d3-p|^TU-J8kbk@Fe zQBjX-GEgZ84)QaWLy7rWDW|rBLzDxD+8!vkK2RtneDL9m=g1BptxM2$u%$B8Jn zyDTBU^X`NMrA&ka%9Ju?5ssV7oJ_i2IZn{wqrFA0(Ve{`U7a1f+YbGQ?4csNt*i5H z7@FUI@b00W(VZ*XdfMi@hIcNi>ROnYbxU7M8vDvD{D;O0MPr$wudZ4Dkewy6yNbTD zL|<8=udbf1N?)MJc;VpPYUo&mZl^-4s7{OWS`zIn>KJaG(q0kXwocna(FeGAu}_Cy zxE@b*2876J-l2I1k%c-XvW()e7tFFf)Ych&fNTwBnK9Yo>If;*rk70zTmJaYfxj~R zVA8bdg5iN{O4)z+!MuDtw{f>5B=QTDix-dh$(s7G^FWt`RHy25?f$m z8o{?miBlhA^4da#Ok>|`306)~^9M}LZ@pnuS-K7j6$*dEG? zaDrtdg_Je4p$r=WVG#3ez_jVXP>>JPf;3PItCTgcqw#}v&{RnWAQBNJy$F%q4K@J( zw}>l(`o{aOhpzC2VxSnt z!Fo7AT9K~QDGl`(_)kGN_VEC=x(+H~AAYOhRrs9frEC7@{MR57n!#N-pFQv{Il_GP z^L%-N(a5DF$ibY+@ERP4_lS$UPA5xxDP8hNv-}@HD71tDINBGn=4J9beF(pE*_*tJ zzatotFOLdt!@uB55=Bx;Z!(Z3(aCfJn+j^|u_b;-!Fc5NT5SD1O3gm1r>EJodMqCj$JO$6d>%@RFb&xXhFgZiMrk&_8`V{?&J;Ar}4^+c(*7v|9SPnbjcVZ>k zqz}29j3cwjBJwC%M^2IV$Q9aw_NNo+RW^>5vR8RW{PyEz{1IuPv{b(08|*vgd*AoF zKi$6&`k*|_!_lvX4LGy?a2h_t?*;gZNJK}B_!W132apHx`w&@9wkY?Y_h2vYk*~;i zxC8x0YAJ54RHo75E-QXrbSgTOPtd37Y5cxNf24o12o}#$SSyyxir8cv)grbEzkAu2 zJc^&@e&lnyv_{$}ZIyONN5%6r)x)@@zf<>YeRBPIANUsg*7z!Yd;DKQ7_K317I=ip z#nBJP?*v@$H7Ier;6tKE-bImQ(w_80&I}_HNGW*$IXR!KC(kQmf0-OYE`36-;+PFI zMj3Mp+KP6hz43bw9ZgHo_j-)(p=an{OvQA}#KKrI>&lARXf}<_WNVn0y~Dm>U$Gmk z4!?e`<#9ZoyLk%l%7^jkd;|ZMe=7}@-j=?Rwelo+p&bGlVlVh3o9Ul%!Y5_1=NZp={`AG4kIV% zcwRw6$R414oA^C5NgzxLh54kIt(ULT&tN*7=2|$ zqMhIv7xu{gX*GfOY<{aG(D%XpZ(^k$*O}xD~#E zm9Uj8@I44q@Z|Uz>UK}53q37$@i(Ux^fTIzuDNx6k=u#H2H)fNW#|I!rGrqxKY@Ob z=U?Xk7^S-@TG(|k0{zoVILn`~hi>c$WcYf~-Tp3Y3eNWe^zpywk0V+b=f4+v!y$NH zCBbl2O0a`_Z^JMD4DtJaf;$Fn4IrL4vWE~iaK5>S2N1Z=2p3v@4nXx2fTkm^`V`#b zUjxwp0bsy%6V@{iLF@ytOuGqx{f!XJ4=n)*!}i0+Ag%#Ki~_J70EjF^)CCZY@fa;Y zES|aT=kP3w)G;N1_+|hu>^C7Dfn#ywUf2}R(#hCwGdDnU&p%*V0I4{?v7%IyVfOa1Nw8u103_yoA2%JY}9CLmeKo{gs z*LMNBzXQ;789*=WqcHOh{%@eqJpg?x0_fM`4({L%{y)cmgFCo`JGg^8 zxPv>mga2(%qC9Ys#9RF;=(vZHOR}n(uJeR|#4j<>s`w=Wk!o4GMA;$Q5;SBTX#utr z^Nrm4++ODExdrvPkcVM&9bQ_dIW100B3=k^sB^F*bsq7Oy@MYSzYX&Okd@K_>`nuN zcE?E7beG4i&Xp<1THV`B(?-hXxsWZlAuN|t2O;EbtyVYBxp}QEB?UVx&Mh$4m@i$b zzjVp`6XfL;nCmb1=r_1Z;y{Qw*PL6_GA)EzGAxX>$_V>5>q6$Ur^&rcL-KtG>wfn= zaq5(K<6sD@B2AQ0xIJMYF(Um$fz5M}RfLiWa_Ng=cEvT2S3@k;oE*_4w#F8>IF*Jq zt-t-|`w3f_?dwBJqz}Oi?L68hCIV)wN^Le*lZ-0ZXjCKhSX3L0_W(092V?9d%QMTA zhU;(Cm~UX~xp~MgQcT>`l9|;yD??V{H_S}Ph1KsC3^_D!W|MZV6q4fWbBO#wj6Z!| zU;AEB#hQb!`r>?!+xpixrA^ILqcsz-YQzY%8yOKJFu_K4kI5Kkq{f%5|J;9w3oMyU z-1yB1j|dMl)B1TNB_+OHlUef)4JkP7>q9P*FAwcsQ!(U&+WOCb^8MmdWA7d|l75W6 z+hC!myN>9z(Ii^SwHm$niJwZ=5o#0fY^#7Xb%fQRQpu8di(7e#+o0Elaurh(tt{yP z%#KhJdRUe~_q<$9R(lN6^Wd?BWI|-*6dW-wdrHCe`b$E{igR;PbFC3M_=iiQP(fOz zL2*b{cmz&CR<+KGkX7LkDt8lE)ueTn+tXrWw-E9u3mvvORHdpN9UaX7@=dS#uxG z@=uA}mq&Y3N+b1yhA2ZUF1VgslWV?|n+vJeQ4y}UOiQ#lTRBk{oncN3CB9O!aywb+ zE3F}qZ54E@?>_8jyYD=C1Wth#dhOMs3hqD_6nfl>{1Yw71ubP50XbXMrZ)_O$uJi- zq2zAT37x=xuU|4_zo>%Zipo*12yM%>3>4W=!GYFU`%V=OO3!J{PMs=U>Mn>JemC~p zfmG88bP{TPGf(6cI)%{!Qh;5$fJRAEus|fAvRusUQnC3mq!!d5k4sTlS~lT|%7$uELXQTNcJ;S<3c8cyFGBj*xWZ&qCs)@RhA@_z&j4X+s zN$;0u=w_J~$!k?>%qMK0(=+lJ-C0vql$}eVc7q|JOyhC7GSf5!G-eIetctUgLAC#g z$B3y8@Ziu^*^e((*pz~rSzMYTm?hXnic6swvc-oWLd@3I8R_BSR#Z~i72m`iVh+zp zZ*4KVUGXY;z{C$X&8VE#al(h2KbraI{%x~oZ`=0J?C!<%L&8bBmxfjO{Ga=LzBhKR zeT6*Zd-CcvGLB66Y5YR578j5~wa6PSlzAM?W3XgSVgDz;N}a|ZY(G2h<*p}(iSdbNU@9D+9lrInZY#Bw4@!sSgR0}| z6EUj0^hNsq#)tlva^6MZd8e^~cQ2#q$!m}AX$v;3O>8mMrA)krn| zYn~{()~uH0lQB`DF)>l<{_l{SR++d-3R&q4u3SJLHZ$^3btw#!P(t>57okpMAe`@b*K`Egs$yIXTdO znTI1MQ{Y2SQ^^o+$TuuB@O;Z4%ZzB&H~e1ngwRpp(+x927aA%;mqb5r&`J&_Uggt? zpKo&&aT)YPFvx?A9VFsK4FhSlN3Rd#wgdDzh@|5@31RjaiQAJ5*0N!a$qwo$SCzRH z9dHwHo88pCs=2M2WLHLhNDheSo+vrGzm=g`HF<1zgFajjYQ**8fKt>W|8i2%%n3#Y z_=r-3oI^n(rML+QjZj#o%4!TYa8IyLC9dF#cMseXw|e5-U0dd4^bED?%BmMm7{4rZ zkMsMNA2>O2%&3P~`L3LK-A^8|ty|=Mc=qPd4fKIIBOjhW-?8`j*ve7Eo^D}(b;S|i zZDTMG=}+jTo~)3iNt|;Uwds zjB#cFsyE$Ds1WyE0Yf&Q_{b zCMq<}UuIFh}ok=jh{OkT%az zUXLn5cdr%6uw;a}EX+dan)>uMu2z8D3`2d6g=DDoG?^GlI;%Wk zog+IthFJSMCbChgQR)fSQI2Wq=`jn`3uDfxKMJ>~P@(rUakv~#q1l$Ec8{UZKv9&U z$%n%P?@);~l090Aw}%>Vzs*KBd2eEwS>YY}m}aw?npZW`3TD|!jz^mpF)U(o#M}rT zQB4!7Qi8i#O#`Qbs;j7MYH>{iTZGD@o2Kku=(iz1tiryz;=y9h68cI)Z{ixOt+F+{ zYvRBT14hsehsN%yzyH1YU-~XRv*gOoFY2>;ujn=Pxh)UQ+RpnKC!`gmwg2hd$P(Z0 zA5_#lM0$|fWZUaokJf!ryuGM;!`fZD#GW!7wKiOO5p{No$9T*@IQ~&J*PuoUbDu^D z*XRvpj8QS|-im=|G|Hqd)BFIv$uKgEvOFY{$z0rEBaJ~R5x!t)Zo&1MUgjHOw-erp zu>CofoPePh(tuu+3`|zJT3fAI!`a?tzM3AbP5aryzb@f_?Oe9nXZ6)qpWR8mC&!-_ zC$oOI%8|Ir5#WL}xZufZ6;6`E?+U-meOdoqnxsi1b6^gc&8MkLbyM}z4YMMaLIqjI z7pmv!=Ia+4mPfo}c{9WskIP*d5KJ(ppbi~4m;}$F#Gj?&CyH@p^w{_>kb6;f9Noyx;`uxJCF;6BnJGS_c zAJ2?OR=!U9kDLF$#;|+C zCq<2Q&5D|1Ulz60zCL_g)S;;F!!J8-I6~TmZwTKR&e|l6l4%oRzFf##o6{jXn%a9C zhY4F1gE}RV4+{fowntc~xC0~ybf{&P+pJSFp?iCT>RB3DYw=j9WmU@Y+c(IXn~hO} zib1jP*%jN(tB9sd$AaC&?CY(q&Q8*Z;uy)GM@Y%!r%_(e6S|6OWua2nRTv_wr zte>~M^f`U|`DqVSZks)4GwElZbzjf9pH9)+22LdEPcIPjdf(T0D*V=0_3~ks`P9B+ zPcIW1Mqxjy*+TAC?kr?`99#lfrJ-^zXSqb?cveV-JfOmd+^i0sW=e&&phvF=M&Rr% zj^2p|P&-EK5eN+o2U_ESHqam0`>SkYrUZ*JkV5NU1!JQwJw}v#DW7xp>5?R}NQV zAFZ#iF$Yds${@jfLZ~!MEo~TRW0G?&UXrY#oKc68 z9ngbxi1?8N9a1TIa4#wZ2}c?RJLDY>#&TtdQadCfO;?Fir}=U*+L+ve8i-7ds=<#f zDmbdZiI|X9;*YnjYsE;NpS?}z`G!}KJd#`G8-wfPug8fOq2HncBe8o%rkc~tW7Xp{ zCFaF!mHCA9rhLSF&8$;PMPwi?G>_AH&A;k@HT-JSa6LD0BhzU$66fd^s%4c*k72c} zSK-0Vq0)z90%gp>^`TfoW0xegU1oAMo#N4eTK}C#{4;?AM29M<^H}u`7_DM`3;Ah& zfwNV}{c1uyx0H53jCY53jw?kimPniK$fw z@RR`lKZFhyk*TG{E<8@Un3IJ#nYgdOXvX_=@E1GkpW6Hx`FUNJ_?Qgoz+YX+Azx=Y zgsjCzMp3a<2sPHqyeVYVj8 z_V8GZCd6t_PEJaKm{>b_VCA6l z*O&PoC++5Cckj{V;SIjCWYRtEPD9%CU%kw?Q#w$zfAl>sWHdQcK6ZCWOV-yCKBnNV z$w{@FRQl|RUHZ;!DP(<&|66GWp7Ud&+EX%;PKZT~PdAK29heqd4)bGI!Fp*2d)~00 z?J*oTya$(Je~q;mt+AHaSe7g|wIs(l;<_3Jh7JlF7&%Uw82g}gsdYVDXIvk%l{`nc zT0S<0Kqy3+L(NfK+(4*onnQ%OY|=ExYy!fgL+pAMZRZ-Z+teN0;-+F$T!h=9ChAE0 z$f3czH)6XkE@*I7EDFm~Qi{a^oJ=JVGIzx%Aa|?@8R9H-otB)S^ zeOGY^?brs?!67IkCgjh2kJ}MPI;jH-Z!z0VpvHmX{u>n+YYwiv{qJ=T+@uUHddsv< zGd--G>dQ&s}V0Yb&QjQYb{PlNx``$ z<7XaGgd`$7A{<>YiXxKeOb;GH(NA-3Ab;){@=(#VvR<aAS|}$2;b>rFZz7jhNtgr-7^2X7cT#vY!_0nMZCd^^VGrJo-kRmtJNwMFfJyl z)!22QR*5x>F-|!|sS|tc?LBX0U(|g=z4e8n*ET!r$6yPSPzUy-4kW^-p8V+0=rCH+gxsSJAy$@< z08VQJO$6+n$PsoUL)S|~h`UK*0@{2WOOq1xJExX6Ax&c44lU6}x<}sKAhiYN;v3?o zczv#Lt%I&rYOWFuoR4#a&xxYZnY*H6qGBRrn5=i36T{qbZgnDeyAo}NSSN&=LY!DQ zG{m98SiF?zBr!Uakx&a>>>8&N5*S{T-_xM1h#j!;*D*qBP)k}RT5i#j@Ca24ifSTm zYKK}mDoU1x^`w(l`rh00sc+++DpGiMBO#BucR5Gwo4nxY{m$$~gg*Mvwe~dcB~pKJ zYT15r&!=Zd*`Bf0PozyLFX%JB_u`Gme1DV=&mtDFlFy;;#49p2PMly-~E6P=T zBUd>(qlBTes%RKV$q@H*5iYzwca;8h^k}^-9jJeS4*9DKt*S4;#t-Ar=HaLqJh4~E z6BT#HsQES>X(YBIXYrAR(v4!jtrkbJsjD4nMO{HbLLfX#1S4&z>TJbZS zYQ(`oV|8XShq$2Wtk%KksQ5i9IDIwo_{&Bio^bXtWx& zR$`nxByFf9VGI{dMkhknYC)o$P?b&%YAvHW^p2`&8;>bXBAXfC9|G2b9_?SX`bH&o;<_e(32tPsGi$iKt?v1F_=3I3y z`UN)h3!>34*bm(QX?BsaEj0W%&12ET<4l@G=5T@d=p0iEzc z?g`Bi6W^PN!LXd0ep*%}REm^NErwEDD6u%iN$^i)S#y+rN>ugh=)-=fzi|zvEQx+n z|8m`0dii^w@>^QrUnDEfu`)b*LQ(Q1Pz&F+n!e~UswfMZFZre|<8pDpY6b+s8HT-l zfWq+WPAs?kll8&YR57>#C7YiNnJ+)Awn=vFY0mX(r2T}@hgw0e!!;nC045#0eg5dBph z=Fn<%9yNFzb(p4@iMg5%e8nM^NaYffs_E7$i_qst@ra~2*M?J9{6h>!HAXHKqqm3> zV7}>#KD6RBE}ElwjY!a!{@Xo#74-gEQ2WoI|9nRA4tsd@nAcPh5rhAa-A1iQ4c=Az zXrD93*vzTiS=*PDV@%Idf_s}|YVht^N)h^(xcbW0OTr^sXAvjb7vdt8wIqSuofaP1 ziVP#tLEpe#zQNLg+Fu^+R`?XF`>P9oyS5d-SnCk7@HA?2oU*HZzuT%4mZKFKIJNM> zRccfuHB~XD)^JKSDm7;gJP8#$bi|=6)RpL_=*o4HPL120VjA^WGq~>s3`&Y(4@<8% z8bqr&x}zV>TLc(Hgf{F^d%EPH891`9OOD!;9tfuAs8B_OU$!q2gXw{wNOc7s_vlS4>oj3*2RaQ=<*_8zwc-FKQ~lISX;d))U81pG)|kLzy$8w~Qa z8f}>vN_&`lgx+nwJCy76c2q%#umwCEt6LrAh$8qGWiteAMC8rKiPGX51vQNxPGIW` zo*yFY==M^l(}LkfuaG7^R&eiQML+pY_!g4~4{a#!*>b*biFCkd9ldYTL0^6SON=a= zJM@t-1CDevN-7>5aGdd^r^jT~8Hu%Z%#gS->Pd0jTJ8U;${Ll4^jcMXlT3?<$2Q3{ z2dODYG5^!5Sa%>F%bSB#7uF=mLUH>bCsldy6L{_;H9n{eeggN{wQ7$k z$7F6}v9=NNO-dCrVnj8Gip;T~B3ThePfU&(Hx+Yy9HLP(if%gIp#vY{Vl61Hj!Ri7 za3|0N)+DjDDbv+CF+X*PW1wq5;=Q^FhKa^8p`&dxb+Zh! zOmocB6Uq`7vI^Z2LxpL%c|pP>iH{l9nAU{Z6BCREo#ez*QM6hmb4F#7m=KR?=)6Za zUx`v&6AsPI#6b#437JAx5t&pIuP3p&-5$;)dvi^+JF2_J4M`*^D&6U}61TO#qO&a< z9qCIo=37sI;sF!ly11EQ5pNmf1P{{6Ew$2+EIZ9e51xw>nkY9cl_yNWvtd|hL^zL7 zRzpT@cMpBVFzl^4lehOP9NN}*Z=dmFANu8qXa8I%9Wd?O=G~l=O+Fi3K5Jp^Gsk_u zt|OnA?^`~oV_E0?v95^WDOt~sp8Wc#@$bwtE?qJ2?%o+06Pvc(J7fCkvT5Jp9MVwl z4=DF=dV35KwIh2#`S*C5YFbw12;53}MRpLHD(=$~vX=y0V9ZtTTNluIA-d-JOU0MX z%9{jv4KMPvQeIsM@x}5AU$kV{x%01Ig%oT?t1A5NP$>0i-KN2Ou=<3Whl{Nv9Jh{4 z-d5d(cUR9ay&zpNsq{cC;)Z&RtO<3~Vn;Y}gcpX>lJF_v<>4&cpqyz$T@BXN7Ke#F zN4)b9BL^P&k^WRJE#;&siYxP`p%(6Z)LQajHYTadR^0;LNzH@uTo>2 z5RZX+n&u3nWF_55DHSOehg2xhH1tqbq1$>*lF&<8T%{}78t_s|#WQjNn>p}GLsVpq zE$~{yO?R*Yo=7Nq8Hn?y`2Z4TeFM!PY@G^IG*<6J;D-JXwXj((3ejjlpO#=|e-TR`LJ7ZDG~^ z+$srd4ng%+i=dt%Vd! zYV>Mbm}Ih;QLdygy~J#0lSzXI28wptX0=)@ppJ@&h%$H3kUro5Jzm2Q9*{_%eGYN^ zCo-~{EZrTn*-?=N_2?1SM@81#dgYJqe7VtbH+Y1?Y>WGb4M4xA;Aa2uR)UszkbooKO}x<4;g z57iAZ_P35Dqxl5&MBRAfXzO%7OD#5s`>pqfEaVlc3hioMt$xM&CO@J6gnz33%y`E7 zEx)3^V!Ui^CjP^`hKPR)%5-LPh{WFNnAsTH+hyyfe z4>XJ#3=TaD)$185I%AZE7z}zns8hp87)p^t@6l6zH5vAbL%T|QM9Z|*qc5U|L87ril>6(5?S8h1?WIPX^6T2Kn3gG)S$6X8H8r5^X(^ZxyYhulW{F&np~67StEi{YiDrTNT=UMEP%0K|8J|nfuh5HjKB$$$eX8jS!;u zt;dJ~9*GwwE*jx2+7zk$)YAn6yeVF+D2(c4ZK{!vBje<8y7Mv@;v=h78d=uJOykh% zLbY0*%w!F7P=c19$aGTd@ zeS6cDimdFdBx2XK?K2pI@^M4#yEWp`k|3AGzKciE>$#SI!CBNIMU56;5~3jji^LNP zGhTXlBhWC!h-VdQy++Ru_^$)=UsoRZ6)6vX6kk%K+?zn40G!_)Dcr=r|J9Du^7m3$ zXxsX?eT8Cvt zw@JP$x!6#gJi#zNxg@Q^urO(T_)}5a3}G)sZg09T@?g_rk*Aw}5cWk=b?0yr7ZGPm zX_lOs!*iP5#k(~ds4hwwqaL3!L%&FWLjR}X&lF2mrjc-SYC>j2x---^ENOBQO^Qi1 z<{4KSHyZs$X`^wM@v4y-jWH~unr`=m+g69h#Hb*@i8eik>5_(p_<<9F*osu zm$)46H1{sI-i<_NzxhUZb(b1m=)&C6z%A>Xzn@=<+aig=e^$KfEalrOvq|6;n)Xz2x5LB2Lc=3m zZYHaYH1HG~3$ff$`zP!=)U~WztBIeFB^mjP=gy4v+U|RA$>QyWW=%x=p_qsf$0iR= zpEQ2l7I*9;1G?;3&}&|=P@^F#AyIo@^L9n0w$i0NJj1)Uc;H&?f_B;Di>5K=rUj|p zO78C6?tiuREr3x~XTs;)duQ%r?##XO$hHC5}jJ{DXbU2zrqi(AxE*)CgRVtOPsisCHWV%9GVrnxT&G{4el`5-QHqOkT>;ULaDJx*JcngnMuxbfe z)><}OI7n8m)_`L#xfN`mYfkezM1=YFaY{?qM3 zU4ir_P;XuVSlHmyfXA<*g8UK|e42@niz!bGC3dgd*&7=D;|tGkV5(PqxBrXUn{o2`$_`^0CZeX{J9Z-I*v|*F{3CJP+5+Eh4%(HOF+R&p)EffdQoU83xX;JJ8(fD ztMD+7gM1^;@YAxZU!mSmFA1nf7_ag@2m%hq*r~*sQ;GEMioLE<1?RBkMA{j|9zAHO znuh0&dw>L4Y{TxHFMf7(^uH3H-ucsi3-0vYwEB*p?6`IPJ@_`y{=+y2OV42D=ADmZ zZ|Hpa?e|{#7I4-)z|t{e*Z95A(-Om3i>%ewIaX7Rt0r(Ivs_x{Y7VqBt){3Lajgvu z2j4Nh>-^C7iSrZJ7oN|3pHL2R2ZLpP!gdS&ga`QwrqEj9u4ihj3z@mrd9DS4E2Wjz zcIzkR-?_iSXKX6YVr>>x0nW1Ub_A@&TD(;l71@;{RXt+Isy$?1Yu{|=>?ud#i~M2! z7(d2y1b0n5%lmSxml%w-h%B?yNc4si)N>=B3DzP)omWGI8l+lB7+Lhr4DFd2edVTi z`_{j6%i8Z(?j6yd>FfXTlh<#2L@C%CihSd(TqVHbXTc`e5i18bq2}|Su9&La$>RC3l>3d z8TEEYj4+;tk=_O)62>t5dJ}18)0Yojd>(ayaUPAMGqcwmD*wa5Pe;GNu77(M+wfmb zN_%dL+&yxXSt`$5dFQ65@Ji2PLpTV!K*pt`AB}#gYC8{g;QMc%-SIe?=bbP;Z8p7) zJZNty*Ck@bSLvJT3;B9{KahWDeab5Mt)Gpp(PvJ?nbZ-urV^ZK60hfp3mizP%1qLwleD-AO` zIKZb`bc2XQP1o7=JxrHsH;cSkfGI^49ofikRdpA_iyVCI^Y2Mm(cmJggc<9p6rR-9Bky{VB^y0SCnim-(Jqo$eS^#v3#CoUf$eE%k!2`it&-W$fUL9o6C=uoXq<}!51ZVkK3Ge zfZ07%8gTMdgQ*&tO7+)fG>ncQ!d*9nW|;y3MVgx*kR^9kRZ*2xB@I~dYa!eUhxS-OgG=Wz1m6fORh(Ll5LIm;*SD*bOhlml$^wd<@>H1Z1X5?MlPRsP!sT=O_+Hn7_4^DT#^_}Ohdp!EV z_MdCabHSApWkd>n`=Y<|$wMVeab{A{HNC}vDmqn6`#8B0Y z>M;=yi&$Jtmz_M-GpcvFPrI2O_jdO#_n4b=Gp-_IqZcxtCg)8w!0d6vp~YGAmw1iC z2y|bg?2LZqqCuYniSbR@&1SaoMK-gXjjaMO8X_*u&8VzJ-v-tL%IyVqiWPH~eap~| z!~H*7IMlac$#)uH8vNsZEjxZVaxL@7mg}4Exnblv;ITVE#2V<{Fpq8swKR!a#qHuQ zaacSio)&o|2E`t6v$)MjIxdchQc#4sisu*>Jdzv1?=hJ<$;=m-5dBGwUEDBtoHGw| zr#S|38g~S~aol1dJ;Fo-js9*hj&3%F0;dh5&UAF?gDk6UwY z`zwoDiFO10vwx=h-EV~aym_U0wa6;g|1_O7vn$vEiE)@UCv_7~?{$XiGon1Z+x>HSEO%-OF(%} zz(8N}J9>h}f+UW-O4^h!z%5juQTxTe6{a3b5n_tK?nB^*Gy%W)Wb1G9=C@7Yoi20t zrq{WRg$S6QJ$1xQ;?g_dWGkEp3J47>z3RsVLXudXQzr^JISpiUdruD8<9=t4MsK_G zjKctQFS8dJOB3d?;XQeDD{zmS+&z$1SU6!u$42^&C>F9d=;zy&8++;fRm*?@W(f*NECV1T_ zIrnx8ut6>5?z;~n6HH3AGxdOr>Kgq%b(((9*8?&_MWB@wQ_!@{bj-vx!R54x4VrpP zn@wXTj{J5s!|IBL)I=4IA7-F!2oHl9%4BFAZd@kI%5qVK@mQJFtL}JAR^qtB41(A0labVgrI_t zFmi&dPMm2Op^I1G7SN!HMxB-Hp3Dd%o9uEHyJUMdc3890>XIJtB1c2$_K1f@byJ;5 zC+AG<`N;Ig*Y`gVyz#Yv{K?*eHJ9}K!_ZZ&SKM6B72m)3+I3eQ+WG8A3G<`QYwPdd zG4cSjXXC~t4}W*$ePbT^cfgh#y%BPnShJIPQazx4%>K@Knmy|@b3|sR0RjhA{GfWo zd)zzb5FX0Y zSu+e5Hv?f?9_{;Z?ITN6X=w6>%aTuU#SiS9+p}o;4I@eB_U^7(_q{Pfq6+7LJzN4f zu_7P(MX1HWOFntN`7&Xpd6m#^jtN4wTJNZL*Ldfu3mpsHbG>U!Ys6)0i=)N8%-dz^ z5?j?SN0+GBT!l1l&skVhJ(b6ZS9uLg z+iAxLqd~fl7{3793Q-8M5JqFrG(RzX_0x{MWi4l0S|$!W67PU6%QTys#dW52A_p?= zq^CiUaW*8=7MZi-&R>3j-PeD9*Rj!42ls5beb3(8w(Mb?xa6Mx(cg}|`T4hSF1Eh$ z`WtWk^7YrC=`Eu%E)VeH04wis=*O};MZH*EsB(?kE{zFlljMSoonvq&QP-}6i6_a# zwr$(CJ+YlUv2EM7ZF6GVwvCfI^;MmE&-ds3)vE5Q-fLH{-TPkqzA{fW<{fD#PiLDg z1iMOj-yNn8S1ST54q38UR?mZA9i%VstVVH{wg6rypEKWpE2!nLjs3OMBifzuh5Aa& zYTc|6o$6{;zMs^~RIYi!dV?L>U;_wfh_>qPCqh&$ifvR~qqbLs=Bh}g6hjc)KBI6 zqy1NIXmJ2G!R^L^WVn^WcjJBWweWns>Z6Z5p`qh_!)0xP)~YmmRHs6)=S-=tA~>#T z+|W-!@y_O&#nE=W+SVTDQM@bok*jOPmid4YZ0wQ!PlNZ>4}~t$8^Py&Snr9KGyZvE z_+X#w{T&x8ilJX5!XE6XC1&gHg-37F#OLiOgYJ8t>-rO^j?@O!@l>TZ8fO!+y>u>2 z1rE(_al@)Q&2nEcQ{%_{5??b5FdME8tVNE6FG0OY`IkV?(SR($_Pav0-0+KPU-b;C z=}_8#Ff(3Yu_)%2;Bi^YikY{JL?A!J>FwMb9=?6AS&S}>Mb~SRB;^Mm$WpCc{SvqJ z?<|KrZM&6~;STQ9XMaTk!1mxn>CNZFlX5*?gGPsTj9fhtb7YHnjbKaTx$)}sDpjfS z@Y0oC2J>(GKD9m#<#&PXNW4o_t*ACpRb6G=vidU2`OxE>`#*QLF6UC$Qegs*y`TgW zh;21aIS z_m)E%nMH&na@Ym@Gs`EIcRJ_mr(73IRNc9BS6oN?{@os4k=Gn1V6GpbFLIPega zwehv#7>GdK%ZJs)emiZf9xTHsmJXbbshRw!(_oa;0(?(sZ-TP6P1itx_i`b0jCw;9Cg3BFbDVv^5w~FpzX?*rKwS}#PARp}* zO=yD@y?9V(dC|K2xQA2cY}S<&Z(9}cER*RRuN{+YowaM-QnJIWRW2P=4Yppleo1v| zw(K9g-R!jl2w9Hyel2Ei{uyY~c+{}TIsmT@m(_IRCNMwj5@mH3%lY)h^=i*xJI&n{ zytJ|6kXQ(7-cVx1D^2Oh)7=?rAlCQZfw(F}lQ=Duf5=eEB$f&bo{2G4(S#T=xBc4o zSDM`++Y`2j9KReV0N!YP6L`Cm9|R^mcY7Ee>rVQ4H9|l&SHEUKN=A8sW zo*-%&3jK^Y{-}>nm$6nDki6d<5Cg5CXJ$rK`s=u4lgf2#{EX#LcO}EiKo9e*1hXib z?dLm|xt9txgQ=gcilnaF%uYgtQk+>9iPPRipS(@iK8hxvxB3?R8bZg$OrMB%1pAjS zYJkyrwspx6%$wKFh3RX`!5sAABE6c?u2x#5jMl{_CM!gX?EGxWgb3BwM`6)k0L+aw zjro}7b_xd)rOMRFXYx@_80mCXgH&lM{VE1nHiia*(i@@RH$Y6}R>%;AG_Ej?TpnaT zAve~yVkZK(9dk@43a4O=IomX!n4gNA;af@GF}%rBc}$9Jfzt74ZAFU0(cvrvH&)UF zAsuVTAVLZtWEJ9x+WF)J$-qA0qNKif!Nfchy%SP|5w&HC!w%hlpo4l%O$R~QJ@g`v`Nbq`W! zW=<5~>qA&!M(gQ4pkPz`cC_m9_V9B8XV7E$S>zd11bgBtw!HPm$R>VJ+oosDJ0`0M z=?gi)ZP5Z>?Ab<$4;EF`(L}>3y+I^rV31(S3W0{TFOQJyd=FHxnFJ!Th0wcR-lRg5 z#k0#U&Kizu8+#883Wla3>GkO!jvCcJY^)d6yiEqP?r1qEh{=#dQyd@093&~4Cq-oo znz|%Pl4!|gY2|bDKQ?H%MtHF~y>g6lnz$*?d8U&gRy`m!FJ8CAE{d;N`;o6y3_E|# z$)Ri!NhE4V>kHQ|@%3Py(_@9W=$r8uNGVt^jk)N|IyZO8nQnI|?^z|1BPv-_7A=r2 z!WBuOXvt;wq<&Kpg5Sf*%3st^Qm&FjJF6R~Wr`3OIg=CrSY>3XRHb4=u2>mYLEIn_ zNLa?(X}5=6Trg4z8YJM1T(Yf7sLzMTim>c9E#MjX-N;=Gm}Z%-pET}hITaTT!C2sZ zA%UCSdOKQ$^&tSZyR|fm~G`Ha5fcfFRNJvLeo4fr)<3seC+x@QKz_WH;-&-&5mMe zGVfmwsUMQ)Ck5X?S8BJt-a~##o;kR|-<35sO?O^b@BKo}AxZl4wQi|CItWRz9aGbs zL(~;|Reg`i8Mi#Bd2{w8E#Z2`ZR1Zs-tz7<^*J2)-{W`bm#~lI@6|8KkD!l8W4rVj z8az9L)N`>&A_@|NVfpHdw{}P>j8u_?Wi|O~BBC^y@a%4j;Z-7O3}hxr!7;KBh$V@}5Fg=J8wts=@{M~*Czx78b*Wzy~%_%jN)%l~V zsIX)}FCTHM2!g01C?u&nTVuCxo*Gs+&SZ3dv@m-EFD09md0l3>E7W~GR-try=cS4> zHC=%u{0fyDB9Y39At-uwc_% z*&=1zP5p_TR#)^7;9lDxi(tBTX$7}lOA@DO>fc5Mc131Iy+L#;Q!N5Igh!UuGf_J=wsRg*K$rJ(OF7$9Y1X;kOr6+Nc#4%17`$wJWMw^ zBY7lY#6i6}amfI|KU5~H8w&DV@YM0%2w+k>U-OL;cA@ClbD#!pBXg%f?1`pmG@QtN zpza3^u;YTZRYbP~d1fi{!ZD>o(li~ynAwwjsb^J6di7#^a;^1W;{(@9VxxJgxs)8m zJ1WzeH*snwnRgzGO2~q`1{;ME)JE0o2tWN(2*zcVpRfx*ZkoXDg1A01YY^k^1oQo5 zb&Zpvr+ErI;ikKivjahqp*6GQ2b8<>p1mrQlUI2P^wN`y@E zY;_7R^*{JzFK*^FjtaZ8;-tlbOS!V5pjE6y>}scjyzUIPM<%SPPmANCigc(fDFNAS zV9xa$9D<5{pnFR{`<+wwn<>5!VW1n5HYb9oqM1V=X#>e2$tJjE378vhlk8f4E5+rV z!wCodrdHw0K?G6|+R;aL5^cJzAX}s>hqF*)kSY(N(2rAaYwYLt5v&i+I^_ z|9JJP{M&8&_aOaz2+#L?e&UO)VeNsn-dE(iCXZ#km&dSsr^k+Qqrm=tNSF(heUYyT(+i|EcgaH|#O8 zQU(79tGd9y#amCTd>VPrcKhr<5|hQG1It>m0i@(Sx?j`$sPA1o)BAU!xBi(i_110d z{5?_)EIO8k?hS+#I#1N06PUYc0`%hz!+Q@WSJ>8;?uzAW7d2CbzZubz$Al^8XJ&Po zu5nB)Wm&c11#j-p^SBmYcbEQHp<8xEO{Oo9(*3Gj+EB5clC;+!O=$*aP4-KJT3?+B z`>)mnj($9Q#(|I8gw>&I2gaDY7|yi!m-ozxmKR%&G~DiyG2x)n2y@hQSZRv-Ad%{l ztY2*PDDoztM*6$v*~HRAzWm@Uf31`-je6C>79GQ=wV>K7y?zg{;`3`j5ysV?cMbo8 zi*mvKqYNCAoqOylds>qqwLLAi#GdUw)&c+UiH=s&^Oj2q+I@%CS6}hZbfNY;9lVtf z)Sp(9)4cnA?FcH=EJ*fA$&+D7g;M#0^_yY(;z;i(jSu?8qn`*Q0lAxmo+^+$bq53$ z2z1!j@zl2tEI4vlOf2L$!H1cB>i2M|D5G9N$eaK}vF#bn={~L#nOd)RQ00xW z`*4SZ2|ZT(_9-5Y7vTHE?3?RCEzAWGNZ-Wg?lSO;i~oLQD75om&<9qLTJqOdQ6L?| zU+`6FJPi7XY6e&=`johlz|LYm^jeJ7i8k6maSS)^%0T=Jb$>64;gCrIo2Uy*tux8^vS{dUm04A9VTv*AZ$^6NMtfc3?*g zH)(MIHT_?v19&X@m?aL*-|GCbB^JGe>F2b}f5V`tY%yxVWE@9+tAmHU>4P@cSK!oO z)WWK?j=e)Nj0kQUJ##>30IBkzLT5;{lV$XC%h2W3^6zRwM}S8;sh7mToioqrXNhu7 z7$3}<7Y=a#$H~fh@epUs(^^>~oTdMJ5t7@i_ zeIvgZAI%XtWBBVL+8&de+T9PG#1V2tD!FetYqw6;joRetQLV>e`8Uof*QKw zL%dF-D5F2zi5FTG1Gt7AoEt0Z~V)SKU*Skr!xRk7eC-s2_T9s{n^smN- zz7y+}UZ23bMw1&aOw+2yOF(*g3Z5?+LqIUG9NCQSaU8q$`mRQgpLJI-lm?uV=IKVB z0=8)6?FjiIr+GFmr70&HU_Sm$oUx6IbxH%1d)rLDIN~YzrdYP6kYFrp|MMh&o3xef zk;Nx7`%afUi6QN!a5B$Tdmvq!KDdja-IgUEa-~`^s+gBWKN#;MrrmNs zytdFee1SuOlmZD1XBv?1?3X8|@na~Vs}8eEtYPzy@A7-+_C~C9dW(}5D4wF_c90`b zSem>;7G>#mtzXNeW*t!uHkgKiYzfHgIHJ}lW()^fa1A5eFB8EC2(3_x60dG{UH-+> zL5U`X|S;5oTu&wQ3}98nSJyudv)zQ6=X*OB6r#F#thS+QAs!;~`)OsBs(| zW*2vE^U0i}66c3g{DW&OTPDV8A?J<9*?OdQIty`#S$U*4&1ED8AvQAD%~@H?u;_DL z{~sCBQaIuPi_>HCrLv?Y?F}nc;(n>O6*Uqw9tS5S>(``Lh^0A@h@&}s3P!LUtGx=ko}PO>3)RLH%#qYh}Av5CMLvhdMxS}EpYzh`Nm zGp1(-$k)$LVKL#JV>LfaRHo7?UB22t4%~7+4A{NbuOy}e4`qa59mXU z|J3ENlxLttcMq%FA2Yb5DL?z}8PmShJZp)ZWChr&>AVP7E-D-K8)4qZG-iREL2|J4 zT}}quKh=cUD0N6*rk~Y?uN}EnlC8z1!T62kg^trriBe7;`3Bs_-!?Fy3*a;NqTgzo z5_}aOn0(R8U7odMYpBt}O(l(oI11JZom|=e#MS`rStPkYr8?J^rFo39nWI3Z-JXQ9 zc;#Z25w3S}Nky$0*u&z*MVTy+lv9)+&akYtMr9XK(n7LG!mO}QqcfnB3+0k9i5R@e z2pw9$y;8<9iq!CO^Kh+Fn0lj31YeCE9KK^OtaNF18RaUPL`k!dC=*glQ64`nTqItz zoM@w}uR(xjt9U3kDO*H%s3PbUY-F>9lcyzmW?iLhuR_$SbT5Ix3%d3r{9c-?dDbIrGe4tdPGDJ~)*) zie%qes z3=qqo35~u&7f43kgbX+h2f$g-HxvJ9OIVmiIWIhs!SGCAUW?!lb5^LL!?0eg!??U8 z%DRmB^I>UikIuLN86a6?uz6{85=K75lSEBsBndK3j@P$bZRhdQuFj^6BO@~ITqtn6 zq+Vab#4VnVU(`_mI+kq*?*v=lD2S$1M_iU_bS*L1vDerf&Rnx}E~JHOeSQ9$>`YCN zqrYjM%0zZq5^abuj6H9bINfsA!QDeqD;sFdB?t*?H1r$wctCy452~QoHn9Z%Jlw=u zg1rdE@*kSHjI}jNqv7n7ky9>cy$ZFBX7}GM|J8Td);SB_nsb6i;L*t=*&yGHP6u)DD_U7)M21b0dz$2_sGFD>e;bLxSqq&aA8O9rpK8%yxjSHzf?O6&vW2}D^gJzP3^7F{W>QcXtS+1PBMbAC5g7FL{!+*_ zsFE{@V3f&*MheZ-iL*5c&CA9#rD9dNEXr^yRKdLk^ZD|MT}>^Oip8nYvWl_>Nt`le zIWObG-d=tYwe*`fSG8hk;Uo;t*Rwc=`w|x1)s8{^_QLaDiWR zUdhVb#x_QdP7cQU*3dtDwgwi^tPKAhEAEHb$Ar(z3;jQLyJqSr{QDvH{pq|%;cX6q zTu&8_`=f{-Hkb#W^aL8(RhS%J_nYJ9xv7ge&H}13Z4)B~FyGF>DmqQ<+CRHDkgEG~M ztk3xfT0-EHLc;#3M7p=s$Jwu3imrzXt)1h3Gts1k5xTPTD~8?p-FHRzSK{(X z2j|7t2kx}#tbe$xJ!aMk0U4d;-%;y2`!>CX^-i}p*IF+0Hl1r^*8cwv0ONlb00w*pRyOwk z2kT>Hq-Xn&fLv-qIcYDteQkF!#ZyN`T4mx>2UK&rrjYCht@Qg^(TM9BO96-n2;9@% z=D5)(e>aFXLr44aN2>3&T1kkX$tyk`q{S}fC34cpKtf4KlFOeRpvNOZ2ZIx0Sw(Sw zUU}Jy77SULJFGc!?|*lFe?D)gcx+>*F%weedha!kE?0>uelxy!eb8+_2bVnbzIp!HV_s)FwY&G9s`|$y@(*X&7 z^&AVJ!GcUdIgPaR+&nb#`Bona2YLJuePx|a(1hpndTzFCygUYZ*vNt&4Q?W0x2!Yu zc~)UR1zzw86^I=6n~$TBP+ELT;tQ{@mN~a83odiGtPc?=$B156pF#Jp4?fATwy4oJ z>?(V1P9^4V*uzreWAo&zztwvHrw5&Vume3*o@;rgyxjN{t-OM64=CdyMhGhNCZRuI z?E}&y!h_#cX>00WD)(4s;6ACS_a(jG%rdjt1s41q(YqO~7nZNg%&9y0y?hULuh!JH28CH4f_^dk81!t_K0%!-U3r|b%GwQauVUAOpR znW;=EIM+;7m7IONDrY5x9DDXka;nYE$2No(w}G@GStmVr%9~ingEoJhH$uO-#gl1y zgOq~Cf`*eiOX5gAQE}Z+*^$J7;b%GaCY`K(>GJ$Jqgwi%qh2K(Z?kvbJjDRR)beDZCE;Hc#J zf;&h5!mz~ID#8)}%5KU@9XHu&GkvKAoZpUwZPB$5xUpQg0)_bX_;ujbejhv#OsFGv z`8?!VWp-sy?k1*BZ;5A3W%I>3sg+1>$dtWal`k+qPasJEDD|M_ejiu;}B+%Upm6c}}l~E49(>ob%h3pK>Lc4Q^X-KpF@X_<1y@j2u z7&l`(Gn&b4i;9iNmcCFQJn)wxJmYYdzk{Rm*hB|zhYEJPcnSoT=wQX7qk{9eLCZqwdHJFi()%5|Piz6Qg@^ zO>oTm936qtOPNdM8*Pgi|LBEf`uFvjfFVH7*cL}Sifdez+FY=%?*~yQfAO2=Q?# z`8qrJBC*~MCurbtj@n=Uyt%j8c$PiM0OMK`yOlY*CjQz4+P1N~dlq|facB!W?Idf0 zc(-PFa&5czH$4&Q^$|ofA$^s6yXq!zCd6{kJavEqOHokxa#TLx4Rx#l=6o^)uP5*_ z*$jGgDQo{@T4;)2LFZzKN?fUYtljjUBN}jF4prOm8<315>vDi`nY@Ep_>Z`?AQ$+~ zf)D1E z)bUj>*%p#jY?GJn9$<52^3;)|4TQ&Trux~#RgXK|@qV=CcCEFqyJR}>VJm0r`0{fj zONyOIsR0N=hh$;Loh!+qOU9+WMILKMHmsw1;2!urO{VzzM$Eh{e>#`T@rY8lsrmrU z=%AV3raR#H7`wz^;~rUCO!tZB4ekI7c$t6OVgrT$+Z@h2>d6|ajI6HOZlzsxZvH%+ zFYiE&Uv}q}a%Wzj3I2Hu5n{r`mB>zC&FJ5$N2omsT>;&GwF?!hGng%? zbqB6LBaa7*n&tt&PSko+W*#r--|~DZ6T2YH$qY1U9{;7P6KukJk^UvHstTaP%n<$d zJ&wB2U)zc9{lcFdS)&)juS3$*B%K%QPA1m7iQQVoGW61Bj z$2Wy%F!Q*?$GQ5_D0kea_Z*oOI-%@jHc}}Ysrol-&%82VxH6Y zIkMBmPB%7do>UR5TCd6(x-I7YZ0JkQ za=0*K$iWA(1Iu8UgA232jTc>FVK>#L?KtC;@|Vx~$tm-nN<67gI!Di0@oozZy)`F( z2qWJk^Dy!BNzBKh*tZ^U&WsY82hK9!gV!k`cY0pe-A{3?O|zlca=j^Q4fl!YiIHnG zC$-Tnes>o)reu_9xnZ!OU+LWZrt;b9vC+*lyY~1#UmiKk+@PIZYXZ4ph){vVLPUFm z4wp8A!|`l_$@G&sX#1|VE~Q(7uD{=;3J0}1I0%mul~v}>gE?lMX_aY_X}e*<(XV8y zVYp#v{>=Q@$-OxOM4ep+IRZnF9EOUtk$?YoqfaCt zDF7t^2I5xA&~9qyqHnG*2Pnh+VLQ~D>5&cQvhm|+LT$hGsPk>FB2R70?J!v_8N2;* zC+j2>aA|dt3EZj;vv<}jjCav&e!=K$-BOc|*Rx52npzt9@mqId+9=DDlWv#kMdQOt zcN~mvpQ$Y+XTbD!)e|n~-|_9MCotVHj2l?ZLBva&Cxc%95BR4t0xWfm)>N$)|J;NC z)dT@R5>byH(eUeBzsrhiz3**BueM@k(TePy`~3L$cKYVf6RgHyxz=*k`2yy`9RT`H zxIScK1bRUVVCo3k9Pb_kG|)BhT+pprUjP6Q9SNI5-TmF;-NVzzRIgwkf&jLU8dKZ) zfeV@^)_2<{k0&^flutj{dZG(*kC?9M=(>HYP?A-8u0F-g)?tj}jiF8MkmEaU-mv96 zPu*Ug&RDsll3POFpv@6n<81@fjvTL)PZryq^U{QNa(+@BSvC1sce{M%2GrkmIT#nf zPx$ZP9-%xFPxZF-9xFr_wky2(XXP?7SZtMgEdUwAfgcP(6HA4fik{Oh7}a!*X59zV zF-=9Kx;n4RQ>9}klT<{B3qepGcOP`t*|fkhk@EvFc9Cg8O>l zV{-p8)dq_e5At4KMETDjYl3ozxF51lXbONz5ObNJGA8a?hlY$u-?kH ztx;aGbVL_HV6E!yD}PwBEGJ81l#B2F~!9uu5WjcAyuCcb@k|r3ZI4>`1Ag~ zhIKAaV7KKcU|Z{|td?Zeigr}-rmI2C7Fz|9mq)-a{c&b1izdo01j}@nrb!_GSQh#W zt)x&Q6Pb#-(#>OWjU?x$IXVTl8C^>*a%VTTChwf&LbyvUO3Chyz+}aYhk-XI*l@-U zo7}~1^Q7jKm)V@G{HDT*avPzywazNhjLP_y(R3Hcqwz!$lAx7gyOK2HgSLh{VJfO! z>v~Q6P>_ps^y z1OMS%(KsWNh#(P}{6$OG_0E&Lvtm_@jESc5>ot?>HJNoym8L9ObBsr$8oKF94)r%G z@VidS3<%zqwmfXAo-;51(aUa5dz2a2Hw~0DQ$| z+AJ%P{^t_hp0dI6p0-I!3wSdX#h#W~z8z~DoiOInfksZ&F_x+a<`i-oCzO<<_HoIY z-YQ;Q@XP2)P!vEZIcWg`0b!yJ&>pepZ&NQyOD{mBjHolP4R z+pTUoy^H>$-GRP0Ol{&ZYDPCy8@jnU1C^ zqf2jV7gpeo{_0Q6CiQBacMKaP%VwRqc0Dd7T3x+6uQ}%WrDi=Jsf3D7_S$>qERhXTevwa&ow!ZU}o8})Y0zX}`->5~%hoW!G8*26> zUs7L3VZUB=azIBuADr8Bx-LR%c)?0`kTd<2?4V`)DA@n!;Km0i_2b*7Gp9#3)4|-` z*)K!RL7`fdmRjfGLS)(^X&UwOZPgKtCQXsmSamhA-dlFyGg5Zv*t)(|?{m`6EV!BF z9wK!}IPE(oC4vmgv{#Lty(CTfa;KUamkmWRB;eR+_Wnc(8E_-f_@{^7nmgyJ&@RSc<~xabstx(Xs;c^29_Odm&$=8UakC53wug41(buOxWT3h$y!}i6I}w za)X`0#hNPibmWrjjb#uC83 zi13HR>IVjHho*{nXEi22`XSB&wbvoOs zZM-&vQR8y95&0t(JxZ>aj5--{;>_3$g!j3GTa~2Mflx}r2>;b`0zz?i0}~&EJR-?K zWbrQn2K%CoT%?O9gphnfj4(P111GGpAhY0gzFPsm0HcwDjJ)GGt9o7T3x9&4j1_j( zP~fiqWX;+=yG|Q14Cn+KTm}t>c5X)w6_|(-!XeqQVKWxW%?TVPP17474Qa;7%8SNX z5zZDsAi0alqcWQelA&%OLSxpYN=AnNxh-Ev&2vSkG(Z?I1>_$O8;dxJJj!ba6B#@A zY$qlZm5h{Y$6o>z5hCqr%>WsU;^+$01aYCGA+kuk6FRJN55Wa$gL@X5DteUGyIZlL z#GL-5!BD{j=F7!e+XR2m&oEaB8o1(zXOoSyF}cM27lpV6lc0!5t46E&{R;@l3eDVo zVmIpe*%2NLD^3`qw&L6)$3qT;R$+yATK-YKG71dPu*7!1yadMrpG7}sAyuSQ>skFZ zi`8fPOdgFDIWlP_HuQOyA~^C_ZtMJDX^?OO z6jqq5-QQ`EXP>2$P<@lg7~3X^HykKZgML0TD!jBGkQo@K)=Pmt$M+XUSZi2!9oBg5 zvS<=7u829J=pUHF{1Nfg-nRomYJ^D80LxN?iv*4eG3Pdy(YKptz0>r6*U< zIO8WCEgQyNJ^(>=UQ_qGaMV5;#mD5ko`(T*Qow1#){=`Xs6Y(;Ld}P+tjx#n260mQ zWZ{9Mcs1Iw+1U!Hz{^AvqV-eBYVT{qSfJ&GxWx_d1}M_?uM?pYW5&%yw`S;%hP-(|0O1oYA+5g%Tdv*q*k@$Z5f!u;9T@ z&cqluDWLr)FUo&GS_CHo%Xn*#yxEjfpN`K*Ng9$%xs=?oU;R~7(>|@|d8~MYG`lIQ z6sv9jGY8HXCy!AkpLrXZ1*aZf#tBKrrDd0-*+0&8+BRKRR#7QlhH57F*Lkp}Hk_c8 zJyQCYq9wmZZ1QiE2zhtIax%f_Lnmse!w5TKr$ZS-)diIDh`m}3k))TWa$7J)w)W_w zQcBfQ$o9VP5ec@kspkQyoU=odk_h8wBjKbp&xPo4`tmcJV49qSOW0B?7{UsOg}<`I z-3ZDWx9-}@6z(|WldaMr2(+kL6*B$U;LXcAgKWlXmh$%Vmr!pK%V! z*%S2HkHs!P{->NN&0~zbitnj`4 z-Iw@zL&>I{#SR`zmAThGm9?qmLEr;L7GAedAysM2*yrHs(co%)6sDA zOx7Zs%8qo7+bI%DGRJmdw);p$U2=oV*#iZ>hosv3`b%0^DaA6*DefXuaf2FhX4VY9 z9#n{p7#iN;?g+6w*}1{cd}b9Or$dlb|v$XRsm=4oCZ`! zcj6t_jWXiTXz7MC-n^|NP8=KtQ@R8MA5{@-$0>~cX+%pU(rtt$pOFQlX$}dW$Q+T) zw76Wy=9fi`RNn8R;=uUk=Zp)SadZ-wyRw*y>?9>34*zK3wlhpn=J~uwV`2k~qkXu^ zDb0nnDLzvZ=R>!*E+QTuLsPkIRUdhb*{sU9#Ki5io7#KtJH7C2_c z3&~3xh7l(zZRdz;r|^jk!MChQ<#Ur_zL8@=mplD(v&+bsDG7GVkU15IDSMO6=9v)N z7rE>VzOR;OYx7EPoh}LMZ@k#-KGXj#OECR+vIIUOp7YC7&W}sksQIQ2rb6@r|@SxBOK`mc!p;Ukgf_%FQv%Vr7LO zn#ohv4t#9Q+3v7DBwPfB`^2(4H;=5m4szn6usq0>iK~r%Tlql6WhBRx$y*cfFo3$x zMk@|Qx#+xO7cW6ax;5dS3j;XKI^n%U)BnQ8^AI+Z)cY>3>)XYQ5@BU7u%Ie~TQe<_ zC1~?`6NpOqWYpehYRxEjr@q?faeVc8mIoLna~ngEh)3^0U3-KRm{8{6{g}W={O@LB z{_mRUN4?=-q-V#clQy<7buz=}U|?eYPxZ#b%~Q#^{rf)KF}}D+DxI~+T3r@Xs?Vme zsZxbdXQie2Z$QC3Gl#k2e4$Amvi1!jB^ZjZk-{rOYb57y$MF6IV{C2F;5Npy(gOAr zn9%5GH5}S0_Gm$eoM#>~^LBQ3zMO5o=X-{bgXNAw#cCfX zUrfP}F@0lk@P;rCMd4tqassdW2(=GxVrYI!ZZWms*O;?^JJ)RMf1BMw_<)nE!{U3+ znd@zmeE4rf?zge)J*;vSVO%F4f=YY;#{W*Q_FZ`Vs44LVr>}Hf_1ouREz=HhU4!)vr;QRjX#%`&>|q=Ikm>?yooreF1Oqt#(8IbUkY_U?9WM zJx`{i2M1%H$XzLdpu9( zLQ}mNc8Om}Cblb^>4NIqn$X;2+wZm`)UZBu{uhU7Y!fd1^bv43`*jGDJAP z4WT4R@}noBQIC>&k9{)FP@Jm=kB*ft&g^Rgou}+*GvTEZBPWKCC#VtOH1+Nm%%l`? z+EFom^5Ge{F-~9|Uq4UCrvQtd${clYzCL4!5@-=|L;Sk4^$APaUy+MtB2GMZh z(7Y|XnVX5qzjgZT?pys4LL*QT<9UsF%LN$;6eg@h<_Ljnf+)9uR5ns(0+?aUNi`5w z@rs%3KV=adUs3sH&5=0L{|Yh{KEB()INoX_TEb3*y_6a*_%rJ#)GS8Ns*`iQ%s z{TEOx_mikwO0U2hjhXLm1{eg;KDA$v%bDqVNhiVvZd-S8g+D{Qxn-Y$7rKDUB%2Ir z6=4){F2yh=TR$g@Vv(cPS({3}@+B zQW`#Qp{n2IRu!f|Alkh~QN1mv6ZGzn* zSU!IrKS7($s6l5#t(CQ!?s*q&f@)D*FRfa@)@#&Pldf04T3Y>;*HGx0+b2rBg+VGk+E5`!E0HB*` znl+RL&ypLdqieP`>lXClT=2qV&{##H?`|bK!GA+}OPI`KRl?iB{ObYps8Hd5dFBp! zSTZjiw;(I#Gvk#NT@}c>={0J}H+3zH=gmT& zb2^XynGs$Waod({Yy1v?9=IuUg#%L6f<{%y(TRB5j<4;RFL7t>eJg?x>{^O?$KPCL z+g0aSQiC^Gv9Zblt2%;OYQa68o=d;wV0&}MJ`R{=OZ#YB5#3O}%`$k^po#i+qGWp` zofqN|I?<5n8ouL~`V?@UE8O?a2&og(Q}liy4;dsf-p7&i@kdi@+LN&kV~L$2p9)Cwry$LGq#6{%3pCa{GM8w~M!rcbsz=bJK(7P0b!yTkE_LY_AvU zK1+TSu|Ei6@6WE0NuW!+6sEJMv*+C~oN0_}O-nCFpOTg_xr}NDw&ouRBIH+x-}6^n zz`k$8e+i`Q#^t!RCVv}pmfRu%obW<~ru)c2Awo?)!sYePyaA|%J(@*bmJei;tG`dQ zj{s1f3?!u1a21vdZqq2D;}ApsXk%)%1%hJJs6vw&qh6IoT$tv;P?KFg>aQkWGv>Ev zaufLnzSCDWf3nX}&BCI%HrJYn1yPgz`|(he>xNj`m_kuSTHV$c-Yl=9>=meY>D#nn zCNR^rY2~akUM07;p!w;n?!$+#`Fq(8xt94`B`(=bz!|M4XY5kuT~2*AC8x?uNekoi z$rA;c>qpfpwKYY z?UHDEXv|AkiniRwph)GQ5Xb>$eHe2*9AkzRQA<3%hDdQdO<`7JoCvY7|AA(G^21+J zmH^O9d_S1AJWx&o$jw?z_rEk7;4K59E59oKl3fJ9?*hC2dBWej3JAC%<^~Jdg?xy! zVu$VtGQ8n>ae3kC1itRg+2PwE&h-EGm)mt@hqx99{L_z+4Jj;SLo`O5lRAq2Lxm!C zJ5aP6sMzt_-w9gogSQn#>jVRSA<~Ao6@uIfqR;fj+F{;+G~FR}#j^=+s0IH*`uqak z0Kx0;>C35e;O&QgMQ82R%SHQw&e-kQg?ssZ<$rHS<|#NnX4Hz+^WEILy(_f>{q1Xg zBi9Pi?SFX#y8)v&;AIC45I_d>ihvkFw84Mj%^F0L^~r_8{Ve$1L5PRuBRRbxmk1aU z2j`Z3xM4Er%_2pDi^YE7VDOLJjtm)9e<8tu{}c`^3B$-H0K1{C>#Y$d=;SBui@0H= z@KY1V_y|tycfP@V*@3_LBjNW+4C5^zns91FT1Eylid~B!DmZwK0v(#(vZVG z@KzL|6enqmRQ~p*;@cUAZ@mMp{`ek7Iag7uX{52WvCwWen(YU>Kc38*m)BF{dY3$} zq@t}!<1l<{EK@3{t0=Eb)z($jRP;P83==_urmI6v9lG5gj%GMKK8&7XFfqkoe8f04 zFDp=tcb3qM>UI1jDPEnawXV2LaJ<+&UY5)mp_{0LmZPOi8_;LeY!t3?*sSQBTuG5k zVCk3H)mQ{yId4_p?0S+o#Hd%wXFEI;A#Kn_jl75V&$B}*du7F-`Q+OyJZ9Z4DpPOW zfHlLY`p@^o0Ko^-HZ7;|r{V=$Mq;)bBeiwj0-l!-CZM0W0ronI=B{<6Vv;pJUXJJh z8zcY7V6Ng?YObKV=)w51cwtsqyb9wIZKp*6atho zq^Th(r69PpG%gX2m@n46X1qfDl!Se{`GXd2UfNSG88ZJ?h?rQn7sR^>db~1moA589 zs)G?BXlfV1yygTH%p#p{8qjsmw^g~eEX{2$)l0y>T+Nf#B%7FujEGee7+nOU-!nbBfqZZR`6 zGcz+YSS(qxWJ$Je`=8mpGrRlFn|J2j+kH+~byZe!KO1aY`Bqn`4Z_!ktNRJGO@iixv5TGcl{|g`RCH+ z*05^rgYwf=H=n#Yq^6dpr`TjQ>w5}gQNM(LL!NYeoB(>Y7W)bk;lv{LIGkxWYR%A= zzo#O?)adr}Elm zog4EV1G1Vgt#Bq_=500NO@YI_(~vsy2iI%W`Ocb1sH zVWSHFLNvQCKyF1&MTNAoC4|G#DvI^4DMdM2QG+y&!3@4!;ghoWBj%lJR23r-&`d8O z3t(5ujZl6>_ zDgQLqvX9pdJEyL-LcVQn3F1V|1W8x*M7*0wYuHn5%kd|R-2Y~b0VyZ zVv7LH7$dE2w$?Je3^Qfx$cYRIIc#2nCnFnq`u;`Cr^9YY*u{yp)UWu$U&u|+)i-DuGNdc3H7mAGM}zNNwj7IBZkpm~&xqh-rN zTZ9YS09

`ZnVA=#n44-B>F(Web$;b8KD(4#0H^ITy3T~6V!-WMMiLlf59{Q=Fur$dtvTtcAq;Twh!S{f0p11AX;>B^c7 z_^XTbF89i)ua6+Uk=(qd>xzjrP3lPc%ZDrOaK72SQ(2Y(N);&_=EwaC@s(|bl}B+?}^4 zkB3*>`mx`*cc%m16gf9JOS&QL8IX6#+*_oa?A!PS7}FX{*k`wbT;3UM@2>a=QL-mJ?zM5Etq<*0T+e(SmFIEcYz8|EP04t1ej@FH7OHNHkK ztlzL`n@UqMm91u@(D>Y(6!WzmWg;3aa)A=lR98DoPdQ7;K&p2rk=gER2PgkwW`^D&&c}o~#p6a5Lg^UOQnpKrCV>xvhiuK5H znw67vG$1r1I^zh(7EvD(AXAwUVWSC_mg0ojZ@y^LUg04mz{oz4G7NuoRIJhZfZ~*j z=xut9BwJ>t)duNYhOHn>TWj}?($mEw=$j=G)Dd(w?sXFeR$NLp`uj>u^LR>Ay=fJq zd&Pul!#GRlbEmHl8s*Yt>dNME;>$|M5ct4#-?bBkncpsfb+)a6?o5h#{_nwOaupFE z`-~pZg+t>qeYf^Z>)xdOohe*Tk+xaTiN!-LSjM110Ahx1JjXMq@sqxf=X>sR_t+WvitlG6L4gbKul#%#JA>ywSUc{G7wBk??D}3j@jfa9}0yonhjV2VJ;G?9po`Q-ZkKiydCBHLv;pUHEweW;!jGg7q z;p%?#C?VblYK6o^j*~5BjhC^Erd7)=Sj7MfCQD?qS&Cm8J^~?ZmFJVGwbaC;;-97^ z-umGc5`Oj2H`Z3+`&BDys5txtG+Nn~*F1E}K!8tw*Pj*llI47g(K~B*cRh4vwLV{! zN2t!=_LX|n)v(U=J>14}vxj=&D5NbQ{Adh#?FUOTXacyZUNdZ#@ltJ>ig=r0h+J10 zEmg9ZyU3fdhv8_!MN*iYm&)%q)>l>}ep4U8kTZC(Z2xAR(^X)8f&mCy$XaqI%BQSEg@gj{i4QYO5=VY zc;sgLesd3a?X|;v$h6;%zMyrmf5ELGgioqk|G5#3VC>6ML~+wld=kjqKOqY#J3AzJ z1Z4G|f5)k2AGcvsU><@rD7piydC)wnA8VK3Fm>>2uVXswcPGJps?qEH4n{D=_B#9f zrRO_x%eBphPx#sDHe)TKji05&3;7Kyee-ZgyHTIB0^CMo!8rLib(usYCSWYMVoQr^ ztqgj{2+XJk6QPs@lzopmRr76v)}} z&RY^4rb4V+i9mWrBf=wiF(x(LZNM+Gh4ub^Gt3e*FnlO-z zicjfX1_E?nrz&LGh*Zks(h#+c-C`+VgUB>RsVXM=Ws8VuI!uHgO;a5*e~XWhKbaHw zJ_r2Tl)Rz@RpZV2h!6!E8SMSBvIh&<7xm|rPLZbb!D8c+ZLjGg+-^#eeuDn5w4$%S z7E3vH4tmO6P8vIXzoSg@@#Z>JXB0BwOjNad8Fv_}ssjzf=xKwnS~lx|Np5QnIR&(f zSQRWOoJRehF~njt>(cUp=N0FZCGoS)C!ZV5O=c^(eBb)|gErYDR1)3D$d_f;+h2t_ zdL5rg_w}@szLUlXw=kiN^cOp%FDC;A8dm=8YB_ucIo#X)a!g_eZt?R*Z#NR=1+qIMLie05uzW{ zTTf@`1vVQWb0mV(t7Y8vsD7Fs4ea1g*7!cIU1D;idtAdSJKxRrdYvvcDs6CpD9R~hj8*IJph(NOg_~A_(>xPvv$FIsT(CU$}RiSjt zTFLuUkg)NyoAwgiy<8Ewm}R?t8_AShq&kIrurtF5*@Q{Vgv^f2FMjCa1k6gA^@AnT z;DzV6pD6;Fam8;>2b_mK{d`Umkl-icTIFv%zBbQoH~;QDFg14b`*+;fjnuag_@cLi z%`k;7_p`ZiG%9Q3B9RY;bdchmV;R{H<;G21s(RYuFnwu;LS{&+rV3OAfmVTel2|;>STPo zJhH^>#hrhq48|GD%aLO*G1=o_#PI8?Nc5~|aB5PDz)Tw7E|i<^e!C0^3z^JCw~~Cn zpd>+qnk>&;QPhKZ;i$+^AA^WmW|D3lWS>Y&AwQEcEAb7ZXN6p{66#W`3j}`L@Q(}p zxZI@6BK17Y!M8};vbF7Y7GDCmU$~CSAs_GjQrVt+MUl$t!(5gz%iIL>*?L+MV5JgG zwpcdFWMXnlm1ng=*Rfu3prxhe5i^1-)o?3@xg$K2gSO-Qn{3q2jp`o0<~G}>&TpQFEuV@_m* zEG!L;k*ImhD`zUIPSe=acxI}?n=C9Q(4JHwM*xh!SKRYtd?yi5KJq#IbLhlj+ySi_}?)P@qbhcTx~9GROf6ogFNyy~ZI7uMuI+SbV0U`0CG2?8ev)~*@fbW^d*qz&`GJFyd^7Agg!S(J zGAnX7eL&=QsAab4J(<=z{&Hmx#) z9y~H(t?#v(>HE^qqc&Cq?I!4&t3%$BE0^3**OQ#OH&%pvtwJ~CLlc*zta!wp^v<1{ z`QRp^kF9txPH=0LHbEg!Msh2zT%MJ#TeST&6#5pgks{)vQj%zCq|dsQbL$s=K!;RTgsV!-GBs-4L_`1Lt1pT0@+IHSTM(7!ijRZ=eUmI}72}p? z5NTYC#O)=UAT_KdD<^O80$Eyqp74_hcqijoA_Vx?s~^Ezza1nI+R2r)w?mWzjokat z;H3EHcS5Sv*SiaL0iyNoiS8-r_nempM$~iw=_|upzB-4U19GEsP7m2E{2w0KM#D$r zp!`Es@eo3ByOiq5f~X(CgmgMchv){F!T@Wci$w~!Rtx!ZlSUXBtEDijHE5T>zF~&&lM6N z#AB_$1}3sG@s>8)+O6lcKFegIKQz4#l_;)#yW=3e0k6chFu}ddCa_0-6ins&R3Kaq zad#}kM9s_J$)QPs)3GV6;kFg_@{3)Z$mLLQeX9&zTpBK(-uN|b zzYX1E{zaL@P~PSaIke?Lfm_9iBj1o64?}}@_h%R&lk?RYGvyw#RR4u^+PO<;5|`{p zwc&^JawDC%wy_><-QaImcg@CQx@?Wx6E6jMkUDZm?tO=F&EAR<2#pe1V;&qT$n4L9 z{N{P)sK=|p6SWBtddVTad2gk%1RppTXKf|0<t6ttHb04WOW2h8CX)H(+BN2wg$vi+jo8iHG$UfiikeXz<_c5QIEmx6o zX|+*WnMkf4H$fqwh`mZF7a0;y=3)X)_CmXf3-62?d#-;+-kO8R@E$rH$5ANK%EePR zA-|_5QoT=5ctlmvfn6^=+t5X$F3HTwe>oQY3_-bv?ZRh&hCKoUu~`@q%9*LLV$l~L zQ@2e6QpeT4<`BogSN^^!Vf8ki*opR9-KtfEwbhIa2rbs{RBg7M;CC0+ZXmp6I=O;tI_xO*Vor9wddU|VZGmVIws3stXv@b1F}bButiwOLcQp?PM?2W z>3wt_Q5sRbud70Jg#Ea==>X=Q#2~s(Q1M36i_`9z{ll$-gMmsTAzAz4F|Uhd{sb9z z$U#vIfGl^+E(U4CQ)WqpL#qW~zFr{ckY6tS_#}r6&Fk$gn8?lS{(1MgB!bR?@Ph}F ziSkF5tMhz!!h5809Sh{)Xa8WnvWO!QA9AS}(q(9OJfORa+Sv66#Lp6gaxb?B-s zs9P?VO$eLAm2;?(kNwz2f#0=Wm}U!$i!W`5l;UQO8J|d4?c0Of_?d96`jNlPL4w~3 z^0W~Lk2Z}a&=|517}4gD?bHmd2xlD+Vi4=jL!)USt=>duW<2Vdge(;3YZL=I}!@s@cfBIgx#jTuabnutU%N zwMKJ(`a;0(4|T5c6vRbd%$%~$gf%xN)i;Ompau*S4S28~m8r zzZS(F(^X4WSfj-Tr<41thb*)nX^V6*;HIguZF(JW%?|)40wbET}@^;Fl;x#(+c64o#7XVY?{ZlUTQ`nfIdV-00S+(jQ*ud1VujvS0s1-5A zF?Wf=)CDuaOfZ5>RRvrc(lS$u8qwn@Nmg$LA4YIVXhulCaF69v9=h^9% z=1L$fHj}ciLiA~Jk{JEa9DV4RbSMUbmgQ(pqR?Y;)g9sj`AKKORr(N}_J9Y4S6i6r z=WPsWn4dmvCpAJJJ~isDqhMf1w0LU*Jg_H*+#HJulDF53M`VOj?J(QdEc1hpr4MFs zRlDiS%>&o8`f9ER61`3w3 z3=DSj?X%AbPNn<22x~4)^zhd#jp{$^qCjHvexjwh;C2lw)WeA`$`Rt(RYdHfaRM0% zE5+ZP8Q}@NPI?rpXUI-ze0agC4iYSC&+LTTyzE@3Ar? z|5McryK?uF6##PL?%YfRo5z^^L=U?%aOVB^^1kf}c9lVFA)&{5i)Lhq$>dDS9*pah z3BlSty>Kr&Xqf1PTmeEo;@lnP(JZq=_~-94h-11}){gso!F+6}#g5Z9MXlrvdr`x)epT%j5$R#WAcR%5t5jvA z-i_j4?o|#9333+sIfC8SnO60w^7~wPLX?`jjY4PtdKKVo{C_^M}OJjzb5h~9r zEc52D{rDUB1NN9Fc}ej{<6S@c<$xcltU8-oJHW>5XrlqiF7V&52v!Cl6Q2L-L=X7a ztbjmH^i2O`_46fh(<+$hQ|Qfi^!6=1I-IxP%Mz6dUk#{0laXy< zNSK~C=jUuPtIpGzvlNLNJ0M@x*ClZ-&6CWeK1PS-(1>7K`qgZQ)I|fWqoh|`EyMFE z&c==t-k00+hK?9Qd8?j2w5Xjdh|=j4!k&#CXTQcDuoO(RaaxNG(1o=RENiQV5Cn!B z^(uO+7j6$+eki$_&^bi#PNe40QTSwS{kj3m_4+7!(-<{xtJ;2Au4WuGSk`j++&&Zn#sa;?+)kEMnwJD z7o1Bn&+)%gpZy=Guj=VwO2nvOWToO_`=8cU%p6PrB1Umb8y8b2(ALJ##Z=VP*xm$G zQl5x~{m&^UXBUu(7Uw_p&a$SI^Cmlb&y&Vp8lJ3?z8OpU-2$7P@hV!W+-5XVlcZEK zc|r-*=0fcaB-O_}(b3q_@=bWGy?y$=Cw^W*n&5<`a1=5`7AWfI@B~Q|QEKr>l9By5 z;z05@C($x>$&aF(E0R+2fnmzwPLS_7N>T{QFiLXN3!j;%&=;T(BxBjilG2E#KP@7V zPNT3w{DwXd73>ww3LrEHbcQ@+JBair2x{B^j2#U{G4w+Hq0OACtNCSr8W&w(RjlL8 z9K*}iGn?{mc$|kVGhd0P*h0y0X_Es~P zXoZXJ7qt&M63Ju$9Cd}48D&9wB;NY~ktG03IpJ*4l$lKx^WfxUEPXDhp8!&!&O^8s z`1lx4d&dDqG!V~y(fCZ{qzvtdI6;M|q2ME&oaEtkjvWCv_aFULtFZf8vM3jAIO^pu zOcI}v%?G8-(DqQ3FWvVx!l{UOP>guTqOMJR{KHHVf7G5kTiyMiqswaDBfe z>%bqHpJfi@e|yDuaC)rxKSwM*sx*`(S?)-Ed0Af?CMd0`-p49n_&&Y#*oP!R++IdO zCmNp2nV1ESNhFGf69GFX)V9@UPA@@MRqUTm77VVpWsZyEf`zk5{mVS>jz4qD%yma$ zrcrDK`jcD^;-@=KLAR-11X;FUZXlNfrPLko5GEUuY8IJJW6?f|34BlXUwmYE0z#I? zZ2=;Bv%n)k!xAm&J%M4;bD9(fbel;x+6PflF;?ACgmI^PlDWiC&BqZ$O~BX0xaRd^oTuI z!xBiDtK_{->Uzk6o0;?s0S@xEms#f$%y;*hqkE9gxMO|UeHHiYH3LH@GL$wSF0n!z z`&#q6u;Bde2XshR$`KUy7RhZf_&Ia3aLYxw<-P`VbxuKeNQ|Xz<|-7@jqrT3KowF* zI9@Ql=pu5FkFKdu+lmB6aFm}&>(~3Ic2Jz$6M6DUn=9L^gY-k>9gtnWet<1}9;{cp z-#34HizfM4#6b2*=If9ClfGl(3R)Sn{pRKCZfx5Yvki2krT{)$u%Qg`6%$tL+p(#| zn;9Hq7wc$_5l-)pNTs3B;jhwIK}|S}-Gg_8e!oraSI|Lk*RvmYQrta@7v>XpG=+Y~ z6ESL3M%H%w)1})G1YT^*=4r>!j#`ynS9Y;w4SGZ`)e$? zP;AuB4|2<2nD4&{#D5IwBV=c1@8V3PL&VEV#3*d{Dae?bE{IN7mtxVUg|IsZ>+9PA(n7G}U7Om%_MI2*cpS#bRKwgK4x>Ms_SzsLyS;QDt-X~oHA!Omgo z!D8s;@y~D^9Dk??U}Gm@W@Q335diq>z`xmbuIyZ<4lWiJmS*<
+S{ss8ArZKZI z69HHO|4Q$HY9wNB=VEFH8uNbwODPjE%9)y28VcKc{C(K7gTk?KaIyTMm7<{&s32%` z|E-|1sk6PSld-AuU!zyd!$m^H1vFFs>z@P@XypG@3^ceI#X%5%9To>2=J?yy;><)G zf1Dveh~g|nphw`(?w`VnPWHwsrhoAuMnzF^5UVit0P!3tTSIeG;lFQ1{=St0RqM|+ zf8!>Kpb~#3ghouMsV*4uIMBT$Eyibq>+R;+3Z`A-l31b zgl~1VLobFw6&87j87S33HYLfajH$(a?*wx?4)_1-Nk6 z&(qz=#C@>tZ}qPpHcf`v>_yrE|_&lw8t=~1_nqwNai4SLQH zf1lKJVag!|5B&=LQQo5W1GZvGHdXTrH~V9QG*W-0>eUU^&ZrTlEA~cU~tIt67_j{!A}bqf?0DrU_-vHC7RQr zo=Yl;$1V+cTYLZt&Es+vUP>iUVOy|KDQsr7ew2BZkJ>LdaRVRrZ`plzmCcYDmZ(;RAAQH(pOP;6m*+V?;%!=oMKh3Uy}=5$se z2=J_-uA+wcxalcclPV>|RpPI2>-$wP5Gjb*N<56St>V~CAD0MX$L312wO3vrWVc}r z>%B`{d0y!bx;}DEzgW!o&G08#4JPvh7f0CNl4ZGGe!<<9JypOzwGsW$n9-gkkj)-6 zoy#p$U^eUpv3_C;p`~WX7Z6@`c>d*Pv#xPNtfIp#zOBpJjRB~eLYs&7IrQbnEOO1y z`EE6cFg2wt?4!2=f~hqJDLRd-+pQRJ_ud0k=CA8VB7GaW90Rn>{NN2RkR5 ztC@}GKl5=`mcQ{;kmLmrv2t?!%Z&UV`Rd=f-2Z95`X9`cnTYcb4gSVgIsVM;{_L{; zA7QcoqBk263xM^XRVCB9+mW;!s6Dx*w~xZ;DZil&`+tnI%YR;jU6X?dpd<72TT^ab zssO591AT;@U}oEj)yvN-^~;xG8BqOtAl{A(JKj!L<97L#qad5v-hLmB_P#s*By54R zPxW5y)ek_V*hWfy_&(^K`Z#$b;P>@ccGue*tg@27C`22)}izxNr#slAP zMR7r@*I|!(Tt>K4nV9+UiAY)W6-LSZA3yINA?;lU+9yvH2o=FqCMqURYYFG~hfn<& zcO^fbInl@+%y+O;}*TzPnFe(@*WZ^T!$F^YtK%b{tK(5H}y24fO~{lO8B0; zO(T12zGZryUMau#u(imw>(8C|O`qS_-+x5_Cw7m$;(oeyn_I%uR$t-V0GJnh82yTR z$Z7i&EPIdJZB8DgYgn^Q2~q_jawSrX55M=!m$YxnF^F-g`*u!kD%d$`fMMLU{??!)jTH0<5Jddwxe zJRJHMGxcTTqd-)*NvEz&(fsO+S*<8cMQ#9oOH2KN0DMm>QC2j!EcMKUxFbAT4i(iW zp$G_e!A7PkXFjEqx%h-0mJ3R*bu&RUI8K=6+)VCQErbf^T<8rkY9pp3>3duC4Q4Uk z@wS}-S%^!1m`;yxX3dJw)`fczyck^`!-X?^kp?zUZDt*H9I*%a9fA%kllw8ekDqQbZv`;|i01sandx)xPDb1xAUBR-U3;aO0^a(VbKpoF%<$c_oiz*TS&G~~=VCPfp$cz!Qd7kB(aSOTP&WyU>-**!PM|kj9K3?l zmKl1S<3gdM8j#@}lXB{%z;&Ud&bHdOuR4;on@S%l$=7+@-+gI9y!Mwd-qwR--|Ir+Lwi~(C6Srkk!Vy<2 z0#C=&KQwXGGIxe4n?-&%*|yyGD{)-4)#O`D%9o^L3G5&Y;OR-v?1Z_YHb0OycB!S# zhZ~m0YO03B=**EPL{S`$n+cz%D9h29`V1Y7zh1j&gh$n7e?3V*C)B!?=%qgqAJ3)J zPbrq6J)9t4a*Il`(jO3e?#7!{7mh2Qe6CBJB&^15OIzegTn$x$8kHIQy(cJ}^rk{H zV44DEk*4Fu;B@T5ceBHo{V*pn1v|l?d#-+SK0S>m441q~B=a`g2l=Se3Ew?5+3@HP ze1FIw;Q+>@HwT=|N!HQ-sH{8$04}oe@n@6qB`enFDCE8SG*yDoXon-Ryeem%0kpM= zD(EjFq);`asCOW9>Sz*W&Sf>GAQYQ0bBbN!VoOP$eH~P zQu%dye1nsONLkqCO+MAqOW?#)$@Vo#y$J>EDE3**#a`Wp7DGs|JH$+trr*IMvu!@( zS(f-#Sx3yxDasRGv8CSx^qgQ1EGsNL#>KC!-zV8yPDM`On@I<{AORh(K3zcQ@Arz@@C>v1r_g0jJ$B{yiXYF^DScegIWI(aslMDNjFUBq7m zuvhl|UjLP#CAc(jaXOl(h4U?2;cCePXJVv|!i9-<`&M^1lvlaG%+>4b>dk1(zRE95Z*eM}n4`8H?Z&pCKL3vTXQ zi*Xq`np{+xCZGt{@scLju(~`72KR&P*%Um@1D!>_ib=!kAg9EQDlcF5O4i7xVZP+< zVU>{{Hyojyx9}-?-t>5}%N(1}64=mnOidC|HfMTr`szj$)u=>Lu+xjOU$JrXE6@o^ z?F$h?7yZcf^pGvBzV}5y6;wXDz^5i4*%&Yt`;}OkRYdxBVc?mJQp@7>7Ft*W7t)ic zBP0vBhS}4BBp_EAT-zT{yE-Uc{`053jY1miVxz%E7BBh=jym#ydjWKUNt|S9>L=`x zrgLQ;uC0fmrQ2FCAp?7qlFw;_BXrX(3WSEJ3gm&j>mf`9%%>goBIL7;I z`Qy*wiQ*9Mw=_+S7Jdvtt9tH58{(WPbFB_)-sn`@T(WB^TS#!aw)V(1C#;M8x>_f| zY}?4VW>%@l6B1V@$)IIzr|$HDNxo~*k;4X`H?Chl-q3TZL!h414cq6gk%i^))RW6E znL9(j{~G<;QtNMENOVSkYk{)J<*A{xbgWo9XtlCo$J%_O7Aq6Bqyol{Z_~G zs}}Yh7JJ$L?Y~XW|8eE>KQ#}Wf19NKUz{QTSpxjGH4luMpmoDPTF*baQcaK&>u)#J z1Zg(@+5>4O{vVYS|F{MzZ0X{xXzCSSo=Y-aCd3qtwNRZ3A2)&E$dlr*(8w{QU|U|9Y^?fRGgkA1`-Au0vr(x90C#w8U+Rw7LAx$ zDFGb=Q&r87ghfc%F)@E0i#3UqUD!FG9$@73fs9QgxnESpC9r{Gft-T#PE6c5XkXpL zb>J3sV_Xp6AJl(<{p-dsu%MHoC}0qO{(XRgf`){Ign|Uo5&{whm6#byNGTs0gGAZT zF(3hrrM@3iW&Rchom6?T;Bfq_@d$~%t1;j`$An*D>+o7X(4XOGi`PqEc-y30*+vsg4&&V~CmdP!UTSN#{KL~Yv{F0!S(WVRi}7UkUXg$8A%ihFFj z%IWi#bP;|8XGF=HSdjIV0N06 zuuf9?%D&Pvo~;Y^RSUaloYMG!W{lsza`9VA82~Q1yxBJiV-UbHqhl4h8DcE57F(+8 zR;I=Ua|fUvnRnVsqzs?7&CHhD(`}(AUmxsIyDG zk9l-;L$b7&cr#-kz`z8-AVUr-V(H4iDQ!SQbh(V3#fJIFZpyZV%e9x0XVMj}C+9@y zUi)*3sprSI*u0`uHgnJ}Ek5KZE5&D!9PoT0aH3HiTf|*U&6FN%)2(4hIgGI^EthG! zoNohn!t2B`lFq`XR;G3=${^;$m(g+CamR?Wvci+mX*llJJtq>N&)$?uzhWVN0TBo6 zPcuLtaM@881Q|_b1!NBbUFKfq4{m=1C7@O8MzXgYnHfuj)y%L;M;jP8ls~xk=mMo^euW&@p`|T> zD>mjmqe0bifNqm<#9D)Yg(0u7D;*+EEwQ@tCV*;ojar*>1mM*|QLb_Ur=3)-od)m@ zX|oP^(^B5Wa0ZZltH{hwZC?X(_PTN_CdFfxDIRAdPD$uVqwejbyoLj80lvs{WJacC6RCc2d@`ckA^H{=)#*CT#N zfK>F6waAd>Z3zWu!}GByE`n;5<4Tq0cT1^K<$>g4Ht$ASxKfiuUyB{SvG|&HUKhP? z05@wwR{Y^mkV9Mg+ORkLDs2b9r3pA1TsZ(1l2UI6w*pqP1g*8kTB|a)yf?*OR42n-OUUMD8Hbdo9(lY zje(I(nC@U;tN^asR}r%}#tM_is!V4LTS8T~G}Y%1VhriaJrOw5gVU+u9hNgt9kH<$ z%-`;|l88mcfpaV`;x+)}*LPosJUN zg~tri%y(aJ(eo?kD}oCiQ*w|dk#Y_0CR^Aix=L%fW|kXmqgHmwmJqH4KxK_AT^s4G zyhV-aH3f*2Pg=vETiA7gcvsGZUcTv$F=kTUvgLC|*q0EQBt=nmIe62=hZ;YW;zR86 z$*y;>{%oE%s$qA+?wQ))vtJV8W`xqd>dHO!haJ(fAHGtmdDV-Xsiqp3cJRCnU5%N(gejtWFqH5}M)GE>ska|Um7&&2M2AQ*%%|v+^GHfb zVdpuoKB8{;3jnRA(J&5)W>#1J$Rbo+vfP~4m}$BNtJ*A@X(Zfk>LcQmmc;gaxaON% z9Jzf*w~kJ|A1_wUBMi3XJUo==nY#yK3yyqZIFhoZ`i`m-QALZAtPd)-KQOnr)KYXu zJ?S zPY@7kaq9Jlqy`iXB@Is6(-o@5#(qRyN0YN#-19Q72PT&WZ!+JuGVq#_-pgQndf zhs1fY-KmT#N;SvkcGPEvVs`Na=3w_@?n6X=OJVft2wFR0!UC>}QWa*pWE7mu1Y#-D z1C6?r{$%ZFTVkVig+bT0n;wwqhYqIt4+I>xL071SJ9N)_-Pm$ufl2`Ib!UV&2iDes zEmn& zKsk(J-KBRhd1tHEjl&uw@(AkBLEx)d)rKp0prlAsTY&>UAmMMh_2Z*7LtVK%7d8>wLLvm`3h`r7-0%CF;pUnN365q7Dqb)CkM9j*P*i?a=wAwyDxZt%_Ba z-ad<(+HkfQr2q_%2~CwdVX#5Je?JR z0n#i-Xx733BoYrPsf#n>Q#9l3o5YQx1=RakEY&<7CxRPNh!Hy$ufLFI`h+y%?f;xu zKtgpwkkF05XfC!R1Lf*zlC-Qy;Vu;^5?mFhm|#dMm$NCRqC?Au`6Xq(F~>ID)P##j6pSvv$AbBl0L%0 zCEJa?v!WKa+c-GxE~*w%j7uNgz*sa7Lr%>4E%h16=rF8$T6^K{}w54C5Ppps2nWA$N4M%&d= zzo3)qN7}=N^f<{LCq*3D3X?Bsx||=feBx9(txGY0&xZUr(&id&Q*utRQ5nB+ zsiMlI@1V(~i6ox9#yeORdhRbYzcsi1KIVsv75s(o%Vi#JKI$}u?CW^m_9Wk#(T@uC z=x7+Gks{h5_dw@07tZT!u zfQo?hUW5=JKtQS#0qG<(=^dmKdZ+>lD!tdxi$Fr}5IUmtD$+Yh5do=+^z!rSe)qrM zea?5T^PlTKU)i6zuFP6lYu3y&_uS9SlV?p4l<75|9XGn`Y2zH8cYC*`aTdX*=ai-S%TRhSk?w)*DLES-AOwPGG#}68XVeE zno#p3Wni_7+gm^!4NLKNAv&;Y6;M6u)}fvs-AP(=*>CN&`Mz7EyOgBDF=4ARCfrAB|ZI+@XZ%;aPJnZV|K%ZugZo6)Lh=7N+SfI^M^u7v4v6+*h!Kdc?6VOp{>Dt@ARXyo$FNbq=FH+#t- zBSCh&cKZl9WIhoDJJR4+O>EiFsP+qFe@6ET??`jn-@hJ|jZhJB0rF1Etcc8$BOHc+ zkTI$RYxd-`Tj~4B;p|DN_>UEPnR=z*2}58W`O=)X-zuV{7B#>mf~d-h6|PObfD4ie zkIHYn>1B7FJid1)0InrJy;b+_9wIm)oJQrg?~fuP-+~*QaT`dgRY5<$Pd&~+BFcy3 zr)<5Ie95F?Nz<+SUVc>iWdmNo{NRn4m=Q?m5iZq}>@he+FWCc>jI)QV`J{%d!ibg` zu-@3JoQztv3thimUtG4wwm9B9-yM=~GF=l{Sl#1f%Uj6N;~M=9RPPM+yhF>RT}awH zMvkYxV4$Iq{E+NBthajd+)w*zAMBWo>I1_!1KBcx>w@cjjG}OF`C?NkXq`h2taum! zArk(a&YxqqRIRPI?J>!sC{F$Pt&x!!`HGrA`vv_#!0Gmil;&=UzTBYth7-HX#?9{q z_T!<w}Zy13$!m-rux(y)r%Brh9(X0GBL57<&SgABl;?A*U%~1HYq#2fc>uuccXCU&=QzW-QwdY1 zRmmCdUv-A4tIlwfG^K+qB&l|Rxg`M6e*;S9w zE`o~*Kv}l8+rp4gRTUPGmCuPbQO8c-uJW9ZYcA`%4HQfjLQ2HxdEp*Z2ZS0Y5{@s+KaZ#- z(I?S@ptwW|U<3>Jz6EFv)CP1r!AQFn6Ko@cUxCsK?=3E@?)65bt1DqB`#`!X7M;1_ z6p0GM2`n~V109&S5#IWwNwg+HAgZu(9sWkSNH%sOU1~2lgtgzB%Y~Xs0IhAleve?( z_Cbb4vZpf`j_H7Z^)lup-#I~+phkZ*j08+@S~iPist*U=FQ_}$vk>58LDGVQR}IEz zEgw34(O>MBP;cEC@X?Tj3nz1yZX0U198e(^%GO$2R298Qre}2r!QTY^WnwSd>ci*& zd72117G%g*ZrYb^-7vktJ)fZ}rGw;zLF?cSC|A(88Ig-0EsVAzLPEA~L5b5R;anjL zesb-%)4nCtImEH5UD-zAQfqAlqwrGAMXgN41i?(~$2|OtkmO`?AO#|UyqNBxqVRJM zQiXhu`RFBuAs}!H0YWv2tA?>Lh4RVK86?aE9~3uhd}ie3CX7RB3)BUm$QOFTd7;D}@+mD`@{Am#HQ{K_=B0^$CLdTE}~h zC!yfp=&VUe#S~+I&SJF-hhTrdN>oZF{oOHEHkc?2Q+~v)TDVTQ?M+u zCSKLZyxXyESTQy=bf-qk7!zSt)is3aC4f>O?Gmt2GnBi2=$N=LB9(mgn!m=^vHk(z z2Jp%MbidM-zmk)|d5KLl+c>EISW!f};zY+M2z<(A2(Gp{V@v`7zjS5!^;;T>MO z%~2rcxhzwDe5{&ccoZV~1km$Kq)u#eX-g~9``AjqqGTzBTU1KPT>|Qa4IIx7E}mk~ z|4LaM-FXQZbX=vcF@`UTss|g^eioU$R#9S1_-eh|VpR`et}N^>f#5zRaLe4Ae)!#Y z^Xc7db(JENTUW)1io7s=3%t9HPS9F9*Fg4P%hY?zaP=s*&TBBT2j7`q)i|^kdQ$-? z#so;c0_v(Xn%S6=s4H?}th-_R>qhU)hzwTysspVIyg3AF-XAW%xW)FQNHcIf zUom*FggIO2cDKG5(5h+-w#^J{7T83&ivGfrhld9UK|ST>|9ict^jL~wwzC?y``znq zSp7;Lw{ZVvexFf9<|+e*3QZ)zqRmjn@1Sg2cfR=p2soZ&eqSYmLor6w@h#AkRw$p(6KYsp7%M4Y)N-7C$hyAf0P1e2Hwo$@SNBa;#?#ZDK1eBlkKtdAAkLxii1>HFj@q zD7AdE*mQgG3)Da3P`j2qFxg0#eZ;zsEO}w>zbX^Dq%{Qn930{*Fh{boF2Z#q_ix&m zuo!6WFCDxeV2l|GL*=8C>ee#J|D8=3qI*?bcY7ljUDnkZ!!sC^#y z7p0oJI;%x6SBux#Rl@MG0G%bjhCdnivcLXMe*a|AUn&3l(!U%ygFno-Ig4hmMo`~H z-Hi7Vv0-Fv3LI$+4b~};De1(FChmTwFV+p3E>%~i{s2LJ0TIPDg@?buWoLyw{PZ>` zNLX1FS=Ul<5_esOZz>ZIuh1Qbz&f+AZ|#vSdq{`(&1e@msJTpD}ds z3Nz6e+ax=qgxN$U2eZU4mY7?jGe+oSr)um<^S*u1E=2Cnt-5cP7iKV(kT2=J130ID z()gMp)9T8W8h?UuX3~wA5m9FAWsiVxEx`q?@XGi3Knh3(LdE`bHQgA4rrsr$duto7 zsG?ihRH+JKJpJ`*(J+L^Om({uD4*q1pXqY}v^0XV%Z&*I5s5dD6Bs7D-Ht3Q`d*+p z9NH;4*45(zA~;pgHlqOvt?sJhYCM%!t+P&8RWm!wXFRyW!4iTV&qxm9#!YezffK+r@m?2!pOFV?U{fKrY7k zN@!+G7)1e`_wZRuN;H-`h-o2kI@#%?RrNu5y5uF`!ZUX=HUm4=#83rFc|>?$ew%ET(PlcJrztsHk$ubkTH-3KwD)VrfIvN@g| z`jeJi;V~rg2VBSIfD;CU$C0WpxA?5mZ3Dv#661cALx9pHpwIRk>pbZF;jdm>9KS9w z+7=-lpYWZx{Ko!uGBRd#e|+5*%uy$GeuI&oeKM4m6I?teIc~8QtGqPqpA(M^R^nB^ zdcm$3Y+qYp3kfB$p;?R9;LLlXE1$ADr@0BI8p##c$iJB2jjYp#V_^gi?s8JRSNIS@ z8Xr?9=Pdh;TMgQDR~M;gY7n9XuC^67m)j0|+(9S8Jrol-JpGI*@ClYTy{Ysf2ZX1x z246ysQB;>Uyo)^@T`ZxVBQ_&QmldnP2Gf$&sthyPA*U7h-LEOzRXHThhG*oVZOwbF zPuRVwAgO`-CX|NFo&1)|=8;yfDujt*+s62qkxwFhirRG(ECmX|d1Q}*CWuoMUAt7{ z-WGr?Y;V^Xy^-!n%4#@uxmv6QM5U&~4`FE!xBGOafK#icNxR`<`=T-4t=q0gS-`m6 z<6xWC_3O0Kz{N!n-`c!ryxSbjIwNk#oXnGa48w|@rP6`Oiyp>rwC0`-ZbHFHQMiJ$ zS~_m(x1+SAhCy|K)P{l`d9kb+)@?XMcb<(dv0;j|_TK9WE!`eH1>&4G7z9wo}ZE#ol zZ4!4a4CU-Npvh!nwlr5S zk_N-TOASHAO2jZ((>u!S@x^A6 z4E-JnZ}~x|vcawjV7Iy=rnF)*f~CoYg{2N-GhnNrJ!3Lju0$1DSJJJrHOsgkVzC8) zUoZ$D2}SP60}oOHDx)-_G{cp<^fasBC{q73H#h^k{^mClv!Ue@aXf+SS~nT({G=2 zU^EpzjmSzEs{5#~=t8pt8c-uytcFcKzV}#tCB9n;3f09Y?Y6tU`9Q1f$?fwYMnF)u z&+gbI;G^VIsUh)aHkW`kh6ez@d`;jeUH+4GH?rvxhO}dkf}(BJ=p|R23$9$aDK>54 z(#=7WVO@^cxngtuTVJ7*H>d}OrKh(^_-gt#(N(HK@gF88g=+4%=>!G^KkeyoY$4Js z&0UexJkBilup0%BhedME4Ee^TV4x%LnMw?&p3zXv{U}aZ<^rf!bM?s3R0F?KV)dZ| z*CzPnk&=TzjRQsT4_ls18@Rb`pJVXaFkhBNdO$;PPWflu;nCu4%Zx}1yTikhYG+{? zY9dvd5^=ewpWnZ-VCT-5Ijxz0bgU#>lzm}Q_f^&Tb$+!~VYOU1c{nQ%jc1j@N29e; zj!VEQYi-dQ7qDlV`a!-8lO}FGkw2f-%D4frqpY z6*PqE!mf{ktE@v3{Mw#WZp7+5iYu;4tS7)#2uA6le*-WBE?< zTs6pPxlXK#Ct1arcQ3U+;H%;#U|W$wxy~~%xfjv_zGV@4|HSOU9+HS-8C^c5l=(&cOYBrM7zrlIDO8|eE>XZjZbxz zlFV{yQ6_|fvX%nxu1T~f>0^lp>#_AI{y;sc4vccv>7%~ccteg*?<}>5CE@!ct!5&-E~i83z}`!M>9;7ef$8JE zZu?IsvJo4|0C#(Y`G>&bUS_0=M9hr!C%!XPjdZPSsdkqIv}zWg>e$DL7bdeMNkPTs z9aKTsBF_0Sj5Q85x*67?U#GUj7)@|^KY&T6-6LbB7TU^$m=6W^S!9JcvZe5O)-CNV zkTUIokE!#_`aCn7MjQxCnHk&oiiP1X3tx{XlD8lz%9^ta;}q01LzC)h!!f>>0EQ91 z*0gEGchbhkAAHToaQujVY+Hok_Hj=R=*#6O*cOkw_-uYEs8Um5Ei-q*tPQ_OKSD>v zT>@74HmF3}ai!Mz8nQITgNR@zD0`l_3vad@A993W0_N_YwW5g#nUcWxhVY*YGG$?UN?ngPeHJ7nH)I#`c@qCy{}y zC!)d5vp#jlSJNa?Quy>bOhp5^ZuCwbgq|usHaZZ=mzlBP#;($v z+_W;|aY5XZ#fXPuwBU}rk4~K5yN)!^?+|saxX(V1&jGrYln1RhIMb>nR!5$?M_4=* z4YvHQNF2NMJlALb#wx9Q@p7N0GB*!QWDjJKaSq$OKE4*V}iLs zcxKFP^rB2igFu%6xK#{2*2ui;=8PM*R?a8sY+kAn+uqI(l?hB)DL0@Tg`mXK9(@}P zgImeNE@=iDu3R@A#w)~_+j-NBNMq;3h?%YXPk4zJR#l?&4yN_f!3TYuQ*NnF;3IgKO&I_GuHdGv|V$kHfLQ*d3ET++vlM*L(q4ELY+*c z9t0QD#fx9;FQUI-hA(vzT$ z%{3)-Iy7O%9>$k2gSS6ss20LBUF!25OCmm=dW}by9n!2$9WLJ^is491=sIHtAcb}& zzw>2ty&OVu=|-%>mU5__ZE!beejIw|@;kX&6$&QMbg!vaP+S76bJ+Dh;U}~h8WY~o zy#&za_&&VoWJ&y5v~=HAe7V|j^%5}oj(GdZBgH6I?T&_tf1`-@_)fYs8P}ZnMa@Bei}el-L5swD$fJeTg^I+9xzDOZN$4HK{hf_cP)n` zEfd5YA}!mT$emegSqmYIUs8+pK5TnyDscsgR3SBN8V zje&f|`5Sq*;85PX9A;IO0zprWWgA|l3v6K{5zBPH2mJ+nUbc`%1~%&fEHn0my?494 zCcFmO1F!hIY#anFPk1hLqw?GshNE3lDkHYOI6&##$*cI{8m;noe_RI%i*SOz>l zOB$uuCi1`vFIy8VZTJY2lP2le#wtZ0Tumw)EHojI3)Bb-y5W?`kfH0!OA zs>^8&W==G)*kxHL$V*`1Tu!=>Lp1LNE(sk+OucrxqA!t2AUt;3m!p-Jsc=W>3QngzkIhzVe*J8{ zl>8D%ir?8@ohh3dg zAd~&gVe}+DfIu|zO~z60v3~$hm{Km=9+jTTfYdVp6@QPtRPNj5FeWdSgo_cHQ#lS1 z5n@hv8FSdS4OzH_RGbdHx_qM~)kgHSF|KNyWUft*F-F(x@g2}f*B*V${&T>S{q#Fs z+315|n;!c%M>*uG`7rhC#m_IQctuWSvU3P|O-qp5+}dqNh7Z`8Yns_9se=0u01i@^ zsz$Tv4=F>VKS)An^j!6JvcGXQRRQu&k#v#dP39RP4sl=v{P?BX@?b-Iw# zwyUw05_et#5K1DZteVg87xi2$m|afEPQ78GwXs1O9Rtd~xT7hk{1H*b{3IR`O7_V| zJFj;!dS%?M%dnaBq|gG9qZy~>fX?Mi>vVZk0mlLtu?@GM{ir9Wg_tv`R1PB+o-Th^ zp*yMt+SFA(^x}}VOj0m3ZGa(-_lYDSB(^&-4TDZTZSu`;6o1L;Xri7?Bj6^$Z`oHr z!qtDYVEz3Ab8Au*p5~Ce|MWrvh6=8Zd(J2hKgQn*vX~m9lvEz$Z$CT|uNc5+7jA$- zlf$$36itdDu(ove!bv8YM5WKkTaUWhUfp?59hjOhPM=q+#w%1{!L*k=JD@eq6bS0J z`n%owk0z`*{)O6=&iPI{(cIFr#7BN9%@a(HDnc+huzs6g6*(D6#!(^Sp>ZyFvxdQm z8=ftC1aq@&w3u_D8Cw)sTC7`{Hc?aN$t^Qg(o+t(OVNmJ?k}X`CY_K0Jz-t41WzmH z%6914X1(+LqJ3?{W)7kd7^@i}Aeu?2WfcBpbZ<74#>3Fyb|Is?1TuojXP7KplN0;S zhyayy{&Mqm2*{2a<)`^!y=LcSO^;B$QFiZVYgq9zh=-i`>6(rT#UeR45+>0s3f6@z zt5WK8`dEt zWB*NLQ^*|&iyrUQmb-YkS1(pI3`ieB@CpK`5@bs*q-HA3&?zEA+2zPA4lrKT8MCfC z%i<;tXbTU+i?40tphjU@B~-<1!ZKzevjzN4^CSPcR{ECN#M*p<_e~aD9Gw&|OkPZz z-niBZBOVwh5j;jnL_O`ke15BJUn-Ek{#^)ZCORGD0RynB``T)=*%K53R`%H?Q>Sjs8_%Un*u zwb>{>KTj3pfHexh{t}Bghmh`Py}Ww~SP(i7cNk0PQjV5;Tu|I&wT_lC`_52+HiN=d z$7%Jl=e?u?VB3*z`<`*{YktcdCoS@YKj0WO9JD@~??7jM5fwANUGeYtHN-f~?6 zdL(p*@zG>_({^iN@l6q_r8?nVUlar*1!z#6{)!FRpe!c1_;($9v!+`-+3i+lrdZ-^ zJQ4O(X-dP-Bz5lqvT~5g`JKmz5`b3BZ1J3CMH21cczd-$dI*T^X~{ z|ABG&zvPyTdtmDP-RNK8b&Z?a*6`*}^|yY80MO&V+`b`4`{~3%Ap3`*mHtpw>?Odm zIL|jYoA(U|N1OQ!&&HaB1I&UoI0(9h_ppil{?CvBk0oDd;*%KF&RFIN<}NngP{2JL zWrI4~L{JB57`nkB_IdAVxURR9(hgR)$j|Trx{l}#W8*(ukq15Q4lnkW|BE!&p*1>o z#Yvlq7p?S75xy(D-v~ngA>;cu3$o(o+r$~}m8`&-l>`F24_B1@RsK>uXQg<<-Qe}K!qnKu`xBY6C0V*QLp+`~gLLW&f@z(cnO8kuV_>Ntt(FlEF zTnSvMc#ti$t6JvZA3(gZo5rnx8C9`dg3;@>k>t)Pgs@aGZEHU{{|nS69Yjdi?b-Vk ze{)D${DLb`$utJktiJ=2Z{9QqTn&c%X?5Lu&0ftnL+BbisWnTRm3#Pl1<YmBiqyUfFu_j1gYrnWu?i@Q&RqZ(s{aW58_g_lO^5Ofox1mjf%gkCw0^&M}h5vAIK z@_IOv31a>+8SEfaF#U0ruSTbQoj?qoIuB6+Odr;t_Q9Z3;Pf9TbB%K`Ho;QgpXR5- zj^~%ittkTxJdu({&_@>WV~$U+J3S{f{E6n@FhyP?{Rhw<-%;J~AM^~)_>aWSKfnKt zGDW`B8@FBVFWd@x|JSsh{57jH)jxe=40^@GlrJVyJ(-qMN!;iEChBz!QyUSE5?grg z$6EZaYHHFp;@tFq6)t3QvtfhAEq8p``w5yUd}NpK{68oRuA|T4y9+)4;bt>}AYBwq zy!^wsQVCtQnkC9Vln>N>jqUms$>w(r{CA&!bG}!#Fb@5SWf79V79q=Mvu=sPmv0Z<}@B+*B zrirko3cf57f-L#Gz*ChmBr*vjcQ^j<^dF;Px0tXRPWcK2{W`o9;NQ<6c>AghwHvTc zb?%?#VR5!f`|ALhoEUy4d4l~mu9f_w?Ez81T;lg6_g{w_X2#IPyK7V@Dz}X#%6{cz z@~@ViSlnnF52GTG_rQ*7?iVKPNej3m*1L>7uZL4TPz(=0SXF+y>(`-T9z1W!cKgth zkv&}RCnh?bh?!*7wxP`W>aQpyA#JG^@!!z>zaG|qZPNTM-S770k4E&jn*U4p4Zqd= zx0?S}^Z!juz12tY#0a`V2LSC~{N82=n3at?x)1mB>F0?(dgQ)5>hxB(l<^4@y^nfIChK z*pqUemM}@SM~FGL`6PV@^Oq!xkU+Vti(>6^<60qa30VjDNK{@i>=#z$swq zsIE6M)L+2B0%K5F=F>*45rA5%)w@6g*^5;arpTNClnMXj3%wrMZq)?1rur)EquV;k zhMz*XXMc)%>K%*rfY|3pyQXZ?K|~4NWiFzh@UoPLgN`_i&(*~1W?G*`xJ~gyaL-Ab zQ`*d`+NpZtDY5##?zjYu0Z(57E5wghDK8MdCLe=DuLkfhCs`eLoCit%Q{MmDKW~B4 z{OjKwTk9G!_m&!uzIdMkdGEYCAapF~MH~f*FMz2DBu}cCQ0bGF&|~i&Eh9x2YqtJl^v*<^VQ0{1ZdOQdduta>9VEXlO-ITo`IWBY~dV;o?-Qu zM?5TJ(p0>f0*)!vr95HId|A-@vE$lFV^yyqGzXy@k+8s5`)!*NbwS>`Oj7pwfQvb; zV%OvRDCUGQ=FT&(hRr@U7MRn7^CbKr?CtfqAk@&uCbqyKoG+&K0+3U=rGQrj8a5m$ z=1Puo(Kh_6nuBnAYMqBT>bpqp2Vk!On1e;ywzr%#3N0i$rGJ(@wP@g=bF~o5)%UL- zocRZB9NK19Dx0|i+V)FaP%+84>mk8kD@U+vi!E>5a@Ml_db>Gjul(y{X_>m0RHJJg z>e&yefN*;hX$W{$vJ8E1SEuC!<%>X&Z2hM7U%r zYPyS8c%v9Dyj*9l^5anq{m+x@wtw7sxm9wj<&ESIh+G>yEo_rkL3MZ9it!Y{+-NJY zvxYzY(fi~km)huaf#mMD?|(n~@54k|>=C@~26NTA->Xo%A5W*Yh^YM&tCJLdC>w}5 zUGZuTlDW(Qz{U)WCta{OvBC~iYLG=cvEOB}w-!CWE}%#?ibA2JuNI+0uS!THZJhh(W_fS;0-O{UND-h_ejZZcyZ{RQL_5Ip@aLNP3_TtHqfhF`{Y z7)5!n86nbY9>#aCNBjrH)W1jxf9w1I{Kinz>B|m8`;+7-Tb;{cLeVaR4M3Fz&YXUi zx(M%WTS2sR=5%JE2XRsrv20s>P9_7UVXV72io3Uh_I8n;Qd!E~^Y!3-eU>ed{v`jN zrqhP7s1I%&Zz7g`^?Js4kq8h8n!>Tkab;nPAk(&O+e3#(ofD|?COmctDlNCl8!3Wf z2^FBq6K*nOei2?_k|}2(UY?l(EBkDr3`YE^_w!&y1h6;hMIUD1^^wt7W0i zNn`9Pl2S#c_6+txpYx&`X1xS&W$ul~8VI_2*d^Jg$;X$O3iL^o$7T4X3lxxRu-5FS2^f`|IcIivNwfleZW&L;k zpsKh8EG-;GWEK6{xH+F8(D94H?MaS{8>j>wM&8(A&Z(>6m}NnH9TRaB@Nh02`@EXC zUdN&G%5}#>&a5*uUOF8S@)aBvK*_pHNVqF<$4?2SWWCk9qQq}rn-DmbUR~I!8ywlS zNuSlb+j&17*1>P1WN90VBf@e&Veu4qTN;c!lL(2EYae@t6uM)c5EmRP8p6e(v8OjP z?6bvHZzo_cCh&b>zkgp4{}%A>ve6rdrZlrBK>KV@Rd)+jy@Odkwg$r&&v=4olkdJ_ z%t@}bxWAnX+2R!O-_sw#_-iqz3@wNQhn_wvQ|e-oDCmmq6w25BUIIyz)8~QY*={pz zP;l)B+cnx+LFqplwpHe;liS`&yV?NYe}KDop)UZ-D{mKI`}pi?&ZKHYOv#OJD(AAi zqQ{*2a}Th9)Nm>~s%J^2G@)rZ6{*}WK!k|$;I5LOyz9w_&u&sI>5=W+LwUNv#uQp2G-9~NJ;JL9D9L$#kHh? zZKPu&#)iCax?yVbFFX_9_(%mVHwkGMtxHBbRnX*HF~!%6zUG=Dzdp$V=1-ZY=|J9A z-}uI+B=_0@l_t8u9;)u~I{ru1kE-&_0c&_7Z{5r9pT$xmxYHs1O4P(3&^+Iu<5>dc zaK^*_PRaF@AOT$&EDCrMG%UC68(hn8|5xD)61KoXc=2>lo$s4fJMJWdM6YP)Q=o z9L)orV2?)99n(5W!W~BO;HEF3C^pB4`r8K@iNqg}6Y7C`(l!bAb2ZqW-~+7{a4Ykm zY!$wD2qVmr(xf8tNAmaY5HJwt5AvzoZJ8~UdntZII>Jo2Qc+Lk)lyoY1>kqN-8BeO0;}PMA9!P91aK=qW_1Y;5+7@yJ_<_py*B+V#(@zR zZL3rA&d8D2F)ZqWQAoe_Y*0iSOteg?$x8*U0{mE=CTGHV#Lb)Kq0#p9zGkXu6DsLrq!JNdPJ zfJXd(0rUUTBiO~hN3|C~Yn!gC9fEw91YVMyv+;aA67#kbs3o&6?138eJ6Lb!QNACo z77k!A@0B0Uu1I)q&I6p+zRvD&`@js;v4He%)Y=uyO)D7W7UnB73zjZ?JwiH@9>uUr zpMHNNCdl=HJs3xA#=2^<)T-K;8y}Bto*_z1eI=JdO)F5bmbE#@h1Mivte!>nVYbosf;~R0GZCm!KEo%k!8RoCnf)})KqgiIS>~hde6M@n`zXX*tSLMA4ge^4`tRe8^F!qmpiJWefM-n~>$|~SzU0CHU6PeDy0wyd z5^ncW&^Fd`t+0_(VGpF71Jg_Ald)H>yZTShzBw&U`rJYs8j%|lRN#`;rTaOyU}$u1 z_&KMvNOmmJs|R=#eH0H8D^xSSesji_&i%Y-k6Gm*>&ny@TqzwhxoOF^b2gfK3p$(` zJ{h}N&FxGR!Vowz(Y3-LmtQe=Fn})O#2BGYp{^U&yCQ{Fc;5`9m2SVqAf#iVWE1hQ zxxeNdtCHZAf_KB^(<7|xqoqsq)8mY6Nx z1A?%;Tv?7zHzCzGy^%Ac-zD)52E<|(f_DmGnqLX&+h4}U&c<@R!jUl_ts3LH`{iqr zclqZ$;D=EIZ>}33NdpS2ZQ?_QVwFIXLkTtgN3)^hRKw+IM-(zd_##E_ZqNc$`KLs3)V8tPUA>IoC` zqpr_2?;+5BnWXMoUsaqdG^-*QEW)0iNM9{7h!5C&DcD~ug4WqHdbVdr%={5Ole1G{ zpi@m4T$q%4ozV@k(!!UCKtsS4bej53H?r@AsXd8P8-+scd3h@cPJ|p%5G1+4_M9h~ zpuy;G>L7o6-3LAu$Im6$qo+d~S-5lK9$XNyc5!!o{@UN&KU(WBE%BUjjrSSUV6;%oRe|Q;c z4meO|m;yylgS`M|taXjNLpfUf1%)v~F9D?de^kp+PH&tT7UFRU{JJ7lP6fjg<_`)M zFKqS0)!cx$EFGmR3k)$z@bw?U0Gtn$9YeONbZ*vyr4<$9X`=aJ*bGL)jI;S0U{_uB zWy@}7%IR2kM12D2^n~ki~3j3bcThwP+nK2k-FDD~muO6g{ z^Ve8H|DsXyggB(aLn9kE|pW#s9gksmLiRBL;&@d9S;biQ#=-QjlD)$NxMB1>pfkKyAFcuhJr9{T zrLJrQG0(-6-%yT$^n9d>-gN8I>$A0;mvWMacTBzfV;9K(PoD=ov0(g6!ZcII@3WL7 zo@!R_N&zR=uP27+X6mOZE5IbPQSs>HO_AW0Wy^(j8AZQ4Q&4EK;HkITRAPAtq6pn3 zm1T#~x0z;dVf=Js>E}K$Qfn0-ehGoaY42dGvyCN$PblNY#?L&n$@!XbPX_A9UnHwh z66STa4I=a7e@EUMvsc@ETnl7$t}!=Iw4})K3fiN5e6{%`{y=`8Ct*_FqRs5oWMK)u zlz%P-Qwq*ZDdTyu7&(6cr7}^3ekOZodrkH%ZEOI8CE5{Y>uWUCTiW%oeYubROWI5 zT*LYU6z*=-tbhWM?jZKWu#JJP;sP$FNRb{XpU5R{IaRR9`Rb;d-6_*S*y7xw@H;#& z+d{8Q$_f0h`cTy~#bCR;X(jsiuTsGiZtRP?HbEr<0rLV08pH}=MIR#-$71IuAmofS zt)yy=h{Z#G4fFMe#<&Vg0LknN{Zyy{k^dr4?}VTTxh?B0(L2D&*&0Eqm2rE+;H8fq zuev<%yt%BnWal4JUVYSE1N2knY#84Z$J)NQt<^Uh-n--+r{QB>tK&{xjING}E1YfI zB@K_SKA)V|f3&QmG28PLK=uFtJ}RPp|E5QZ5??CNUG@IC`X|!~!f$b;dBMfXOi0Jz zV&>e`$ju0wCk4uEE?O#5tkDmMjA!V3r*%R*r zh|I4fx~ANPDX2zEvf47)(!ofb-?ni(Nz5@>z0=}pFRhy#ceS`J>jZ&w)_`Qsi>opSXEr45v?e7Bwd10$_lBoGRCk6v25^`IZr&`GAE5|^Fiok}-w*HcX)O;c zLbo@8dp%mK`!fO8KtG}THvvv5&H3lTv)g(B+W0=-#(ZvGrS|SPSvVZ+Liw|2xxxE( z5!>oTE9K*B-Qv^whmyz_=ayHNA`f+4A_1I=R8`TWpZmHSH>+~Vp*fXCN!snemQ!d) zA`q)pgCa@+kvt%5U!9uY!v+-J$0gF9${l75LFdW7Cl0(eYO^a@S%P z*A{PQl1`R!s(-MVV`mK>wS0`9|L8b^PB7&K;&TkTDi0MR*Ki3ST;uNF|LhN1G7uh# zPmAaaUca))y%b=+{^3Sx@#d*Q2ZhQdl#-kS*)8G(pz8E-*0D21SU=QwRLzzm)b1sNkUB1@9=V zA`V>@$M)lqHn&97jAnDK3C`14W`$&ls0D>=;3>;QI3-BO6Yc^ z@TXkCeD}m>F-{8CY9ma|8oNKLU}|VDTy6ZJEl}yX!FNxeBi;>Rw(U5m{-e)vm7hlD zR+M00HxjrlV@D4s&9h@lthHumI8AK{MW3KX)+e1gzGNaF44@TNr`o+8q{xVKKZHe4 z7$hXdJm{fngCtHe@kOb`k0y~ODHV*ou0q(OO3|JKf{W-|%$r+I8!{6C9L31-O#bw! zB**Kc1yzL1MlAXL%KG3$sF2U=2~{srqKvazqQGJQIa&RFO=~I%Lp4b=&LCA2PX}8> zBl8k6WRFxz)XQ(bu2cDeBG9Y3_R2F*K!K)M+sPdLAi_LSJ?=}-&fchN+&e{Y z!xnQ7cfvMCuhQ~SA|-GtDJpp8&G=pbcEa!=?qkywUksvM*rNhDpjETS#rP)8K4<~m ziRyb5-#zRI1lvvX8Fh?|DQIH3!V9BOsdv1!*9i66%^prU-u396XFqho2x&&%8BtpL zup?uh5I#1H&4|?7JXT%g7tCEaz`vsRQ3%ZELA$HA8E=R+0>1yfcbIG>u%t1##3WFe zBpsTgTF45qYk*Tl+~(35e1*#o>pycsfWy_$Qu@lEu||eQrf(TDcRTkA%)h_2MQBo8 zZPJVb9?@JQemd*>QK!T{*NX*1W%~fO>iEO~ zYP7FgfAbS3^9}B%vwjsZJ&iEkVJOj~ZkKQcF%rGBI7cci=nB`jCp}bR333OWPvGh`)RWJnbBp#w$KnMhe#b~)730WQie|X?!kyoH@%AqTMo?N;gZ{CVYT^& zmNs&1!a^4@^bHap+H0FcsYahKf}6^#+)P&yLw5dlXdt|o1lKw|2rlGHG z%~moVycDV(=5PssBsMrscg`s*SrM4#KUvbC520PN+$+eL{o@}#-Ti!My0oUL{tG;z zUMQuN;ZaD_LzRSaNN&T52hsFX3w}yFV1*r#ju%bBo}2wxd38-qcWe$M5V-i+huha6 z($gL%&A>F#g1J&}VP9b1Of`{>V=^vHy)SUJNGE5yIkn%ggIuo=%1+94G(EBkARu_^`tyty|??`)s(edZwR7q01m~3Dn-d zp-e^rn(>`lgKD}QPE|X^@X?X5G-%j zrc|ShFZS@ZC8qTQ^`1Gs`4Djzj$RAXkRZ#^3GMi^Ac_V(U1YTTyd)|89s<-$ns75P_{Pe-Hq(#gl7O zG3(2#f$=Rrst~e@9qzcE7x`J@eK`0>ewu+_c&$1H3YiM)*V1iQE#RR}yhk$5ri{7- zEY4f@Xt#IkXa=#}GvRwQ>cV2CsNM^Q*B3B(2m7N%Xxd%0MkZkG{r0rHET9^ z`qsRj969-EWQ7>c54;%h=^qSSNgKE?9i82qXR^w(h#1LmO0ieaT4Im%gqi$UUR`Bo zk9dGko=^&odKsOqVe^ASNjGnlQVqO?!m#(*F8B-;>mR|m$NTqc8jOi_MtZrm57~M` z^t<>y`y5Kx;>f52hrPICzHqW2Xep9tM8_;>cIUf?FvQnJk~JNwhm4q$h>&GVtnPU2??q`Tj0GU!kp z4{@}=QaFn~*@H*~jfS6~^ufmt^hxS$&!TRN9gi_d#o>+JAIN$8yiwpx>fSouxKoo3 z_nIcCPQF{2*eB#Tq`~5v1_v?U3MFwYo}+%CeGQc|H_U;a^Z()PJ)oNEx^-b}C{h#< zqzFn0Js`aaC_RBt0)!6I2@sGfMG%qR34~sx1QHcCh zrv6>;?d$}0-**D9#(D^&UKXq9K0bnjfS~DsGfJ*;Xh(e-mOp+cot6xYfS~$n>LU}< zSL6A-2r!)OZ!!4@rxc%1?6bMskn^=uo*H3Oy0g4ASsDXgA+(cAp^CGJfSR>zda9~0 z2K2dJViV6PwfY3>suT*>OFK=U%_ro1o}KlE1)n?}a`G0e`OH&Z*i6@1AN1O>s^~*y zL2r0Xs~5=xTqts7_wQ78ahY)R%<=N#z-HzMScG(-VGgKj-wM z9PoHiyTF-e&8DiX73(Mam%IX6DIqAu zmodgbi=UO06erE~0*r4LF5>()j@2(u;lFVxG;+6h(y?a}7*Gz0s@pFQFt)D6MTyb@+$BC%V+ZspYL z6H9kAsB3h~gO;USSWq;&nl|QnWXwergjpp>bfPe^e-6;s;z?Iws(LIw`6FErIM4ndJ)Zeqpj(m~SQ$1X}w6NkimQfjJMeTL-6rdZ&O$tVH< z{sw)8FeDh*`^`!xPmg0DWbGk3cZ+cP#^P^w1bTZub7ZJe*rCnhw!p-T0z zxZi`EEH+I`gM0IrfVG6`!{qSl95y|EkuAS$S>{!X_>KiD4k@DfU{$8yN`X(fO9Koq zTClabcI2=eYXC+~)D(7cQ|xRBz^4Pcg?|*R967wU_aF6$4Uo{^|8W09P~#(Ksrt+X z3%FJ#0kajmm8s;;Jd8>T&|0z2i!#fLD6Q)*QqP_Dp;S+1lh&`5X9qut*f+QE6ldZ` zaTT?c=rk|_>^M#tP#9QN#Zt?gXYcyMmrX=#GC4EfhZ$5!2KHYZsMe;?(=i2R6ZOrp z_CjLaFAmd}WGYzUNC!2jDImqm6xc*@Q0;PomPpxRH3jpAvG{3Ea^}SUikP*KNbz-& zV{4%V(U4uA!9gxK6-4)Ax9C|zc5Iou=POcH9QiT5!|RqTg|;h<(n6`*-(Oc}z0YMq z3mE!(jgRA}1TQqQxajZuZ6p9oK=%RMzSs$ei31kJ8@I1FTC?dQ57)$ka?U9=4WqfO zqh*uW#!9M`vr8u%oqv(SHHX{lBk59?KJqE3XgL3MV)IS0vLkCBXG}*s9NulXix zcLSW0en9weVFw66gfPYCu6h6;@+7j6@#jq&aT*;bxlTjju7_PLMcs8!h=iFa{AX^P z#D@-++L<~xH5u@tf?fpr9s&EyV79^EeVZ;cx#}j)f3Sl~PfV#N3UqjD7D{?t`L(iBwect5H5+5KyHyF# zhV33vSm}p=NO=ezC-@1_j zNDFn*YpFJ;(M6i3I`+|-_w}?kH97R%oPJ+xyy8BlN5ipXTdb!6ANO+-!;}Z8K^{nz zyw&{h?T$LQ@^DWaab)KV&%5eOZOy|FB;Qg{kAAqSMKnoN0MW~0PYr-Q2B}~UvVYaT}r#loVrvUI~DZ1vYVZFDm{GqfBiRn~s1WL;58dPqBI z=7-8B=d^>ySnW`!UtBMR@g`V0J%mKg`PbK^*z0EG9%QeC--WE61ZA)sm$sY2NKq*s z#sa(Dvp-f1sv7tpf^AH4^7YX26m+sZG_zk_5MY&8qS3|hAzwSmJWtIpB90qv1OyB&YC+{>Ln8+VrX_``9=&-QSBb&F z-Ch@Dx8GFJpAj3Bfv8J*WJNkpc9W!CWuKJsO2hK}O=Q;SoIk}^;YmK)-{na}*@CFygR!l0A9 z1#U)&3t1mC^L_gJDy+egM>=z5(6|l&U2kQbIn zrpzvt@6C8zxa9cwXl5ks$GwtF5n&tL41MwnwjR4Do3NR$Uvu_OUM_u&G*gLpYzk5> zDA?|MF+8bcpRbl+>f|Ho5hyAenl8vI9o@5)5nuI-r!v=pX!&WvUbo3r591PiqMu$( zk)f<6fs~__b!8l3Lam<3-J1TUc0I)=r?$24kazlJiFIdR>LdW8jA`_gQdLep+o?{k zwkAV0kMl~|3!thRr^Q=^>;2(SMC;7%UAl`b-&7hl>8IGvT(F4JU?D8)Kvd{?N}guf zQX{6mVa}|$Ky5;*pEje5an5a2*Q!q;^~dFjoKxu$qzIkM&}zGz>TGu0obwj*m2bz3 zz;{^cj>ZD-t2Y)nw0GEh@TISR6cm%mj@EZ1pZFGUYrociCi_dZxJ4_`c?{&WsZ-bq zwP@WO@D#izT5JE@Oig;cq%ViwGh=*gEFG_`Z0bigP<4m?c^fKL zuyVI9o(8OenR8`VRib^2f(t0e9vyF%q#$Q3VagVZSLjzBO6-1H=9upuQ#uzmy16C%f@db2X1qQ3Y?Iq2!x}cb#c;O+ zQO>euf`(^ycT}68*4q=(H!Lz!9$y-WDZ@MmdmK&1S*5WZqF~y(9)WfgZ+gHz12&Bk zupiBr;klv0F?K;NnNrPcm)HU8=u_b_jXNDiVn1^oz{8%E(SBw8CbOoW3JAw>5rl2R zq2FcF)||f2$4<{qLP>RawgKB(LrKY6i`E=Pj|*1MnoqP;Qx(zyTn%Yjh2Tr*ct&*= zIJU1E)ch2BPqc0MB=2pm4=;qHDehcHWKMiJmfZFYYF4(RE9?}_={269gZ1q*O;0gp zwHazBOQ=X^2=`6&#b*zIo2bbz72=O$A0N3$l+YvQ_`vHt^-eCcBAAJS5RYklVTn}_ zH<7&{#ds;V8!2up9rGXhOvDKe2HXPpG1md_wlUf;VOg*FXN-{s{U|FD7zBeBPf0Wb zcX-lUVGSrbpD7t&-Q!lE$RcWU=7zgNEiC!|JN_tO~dZB4qWl$Bq(io1^u71{8a zTVWEw(RhO#isG#~E1yC~=~ncsqhrA`2;vUKi@vVyurJ};EHnvZy>}BkYRr&C)54&q zU)&g4EpPI15(jieI)?C~+*VS}rtL`H$*{Ex^G~13e^{>kCzu!#Vd)>cv4ymGxzpEp zNQiFTz3#yQ-`@!xUs5WANhS%LgV8Ie3KW+nLDx=+zjn1P=CS?5F6{GaO5v!^&l!#7 zLa-HWO2=is^n};wG?9v~;8kGc z7Q>p9M^(5CjkR;SuK#+Ty_+o67Qa@JQ44AA}M6U=L$5kj|9!oGOk#O)2MxFyMVMfkg6cr>Iwa$>K7z5 zIyWLo1|usRtVu|$695_43#|y!DLa1pYBr2dsiiV=M6h5FahZ2(@`{b}Gt?Qkg`T@R z{2`gryHx%ip>rh#tE%;VYq*6OVM6_x+_a1PM8)#v(nUS9>16%XRz||uWKoO|JALq# z(mtbhoUuW2c70IZGh$zZ4DCit&2eVd-`Gf^W*yD4^gBaS>n@; zxexZhhP_WDw;ugZW1MW+mBLI?S7L=Iz7%z zOl3)Fe+a`PG}v|jkUS-wh!nW~l0Wt9U!9QOC%)YXvfz7rpSr7{Ny`g+-RW79%QSbk zJLS8{Wn^fQ*^rv`qj_|5+^ND-1&a4`yUDRQ!AEDj+#bScXjw-|-EyuUX%Xin0vRJ7 z)2rk|00feeP)k|2-lv9UVx9q#1ubTxd#W_Z#g=z^A#x-nw>bam_TM$RbKT8!6@kSglBv(86np*EnY?FiV+au$*q9+lYFV__bSCd0BYsCvq z^zGth&WngF4P;-j`h5dwre(5*0agtqP-R3OP4(T@U~+(+Ex%!opH1$EPycZL3Opqm zD1!gl4f$Q8roXGVVzpKI)_@!Kdu2w+TGqgJv+H0!W0C!AY#&&rP%G&cme4y!W_-fK zY2QG+DXs{K;QqRTSBN|ReOigKiiCvzpFjJTsQ!2L|5*Lcym_79zBP!%Y6S&6Cth5V zJAdnyf2x;j`{R*Zc-5fKKPL+pAEqWIBe>weji89Z%D)YRAYEm z-8h1rDP+JBm$#C+5TbhY!cc>s@GkVk}(} zN;Y^tf0LV1@E6Zub6qCCBgfgG8`u!k%qIx2|=`4wc^;QvqBNPT{VsXOk>W7 z@A3HsYfMDP^k(~zu^VCk^oOdc=DdZWy!00TS1Ib}(NvG|3yAV(x6o`2cZ-s8SDNE5 zzF{hZR~anK9A}?bKFFY`QDdZ^6iEK1*7GYw`{10QEwI`-?zpg>pB>4UC$$1U#M+vOdtja{>%-FnNmH$=K9r~`?*flv~)c~ny22H_7;_CJU#D3q0E=?Gf zvI5iel9;xXTtA?`Y)RA!b7kF5Gv{7ag$D}HA+te@y9&bIuHz;%mJ2EVfYN552ELH? z@lN0O&!)8O4bDF7s7+3@cT;-&l(jIfI9_+0tH$0;liyZRe-36P>cCX@vzc{o5!dSL zD-&3{eoq{{x%@B?td1r4Ug&l7|!bSh;ktN(c@nwo6IeLKf|UECGe zB{o2ctKex13Co@wQi+>7>6HeiQ!1@BMzugsQ!r2mA7?n^63& zYVIW&lx-lkY^^_3CRy&+t?qa!yC9MJCjRNr1D{vS&1^AZ>CsPoWetn6msO4Z_eF)3>|RrhvepS&^n0WLID_Ld}p+fOK_8zAA;;ZDv|&5&wo8R z?#$(-eteVAL41<@ZvEkW&Jg9;XOc~EpeN<5ejex4ip+*z@8Ar8;aYDQRRvL+!wP)M z=#naQ&0W|`DN|U-wMX^mKkr(bb1myh(q{nc-r5eF8#KbnedxNVSmc8qlnKn`u-rzV z`K_9ep!vP$=n!Pu8K(F>uC*t!%t7+buA73w!)s@T_>@yS+x1T!XuFBYm;}R$4OHI8uYSA#{RPmqfLUEKWB_t>Tqm3Z7egBG|Dg@LKnES;p@^QJj@fz<$vlQ zi?|*q>)MHaWlJiSiJcAbbex9ipHlrunH?Bob3t}M90`fDG%4BUMJkuNECsg)>kE0h z=ingh%>eq}1<5c2rpr11)f4{v-t>P+nvwU~IL6nkN}Ot-x+$~uPIll~jk6$0x`w(+ z6U`#8c{af(*9_6TTJ-uQk?Z2;4jeb9bX2#PWU%HCIwJHELErBa%WDv=q`LkDlO@R2 zjbANl%fh*%E4cv$&O+Mmhg~Y$xwiAoJA}Hj2tcW zK|c#yG;7j+n>@!>;s6DZ?8Wep$Z{F`#0D$rv%j}sG;BQF?=wcBJe&C))%qT_4v3OaL{Y+X|=w;N_3#Ly5g0u`Dy}B$~n=`iImkKRC zmI}@aMiyajYFprClVWy_Cy@JT)6tBImz+M=@BovDx6`gU;Q;+YF{iW{OU*L z$qH6nXAe#QVSPR7<$p+C=leU~(@U+9VQ~XjZPwjFajHnx@1ftipz8VM)_zmC;Hwv) z2$@3RL0Pucm7{Lnmvcy>{VWKP<9|6C4AFVa~~YRMF$hljFE z&pmeDyH&kE`+JxMA-G`W)`@@uS21LjV9xI{0_TZ&(f3AJr`^9n=Kjxh$N$A1{{qAQYuXchC2C~E#f~BS z*XbuBfRE&1#7ADsD?k4hBv&M~h70I@mAJcbG z+!M{Whq#q0C+W8{6*Dtqq7R_ynPcGu?eHt`l=k&%Tc$Isc~$;d=N7G3L- zH}2nn%e;v$H8-Goc2bL256o`8Yxh3#cdN>VqducqY{IPcDPWBCey4#0p8+YSSIMm? zFk%JrgDT{zK&6Ks+z9ja_d}f*8ReUr(isk(lBv!j=VmT80<@}KW1~Y>VLXX10TSiW z>xzR{?dBSQooY4TX>&)#)WUi6k_5>;`Up7#vRk^uSva>MgS>K&ZN-zKrmZ2T{)@=i zkzTKT$}@8Q3QiV&a_FX)R%vw4&-@ZzWJ5+;Ml{k(I5b(V&$ctidT?;SqP+E01c=0M zfSCYrTrzoZbWaB^6+l{%!xYE$N@?gPz1BAWzHle+xd^2PmL4E_8@8z-$}!dN4OT>S zR>;}X3tqqLD$b&oH8rhWPeI<3(d~uP4$d@V5Zzx;#bFi6pNNX(^fo18H^#52VXPaR zsCnx7lzmGFiy+3BNee?(BrzJ{FXE_>Jgep>--B!+Hqi-b?CA5?&o+ju$EM2M4-*T9 ze%bBPqQFnUIl?ah?o%>96B8MBoM7g9lM{eC;PwiER5{>NWQ;pm(SmgI*7w(6X!t6lC|HA| zyR1pBTn{D@W#`YB4kmd>Q&e7oqKS!OxcIj*_y1M?y+SKC%4Q8w-?XeYYqaKYF&^8{6{QLul=lcyWc+-O%R|{i;$ow&h#{=Bn>B`ey3wKC$M8% zi7XL7u3~dgzOou3Tp|t*pn-q}1EPPbZ2)FrsUdP{ULG~0T9g2D0ZpyB=^{+b&lu2i zK1TU8Z$akJ9<}E3kx}}pzfOMA{d7rhL`UGTNgU~Of?T<#pY6-GXhmGFnLQB(-=cJH z%1AzX*sMs+X8I+6dKCafd`I}#9J27-aH)*(U5Iekjw{SoU?LZ0imkCrYf;otI9NQRKjutCf?rY_1zvIB zI$`f!bLW}3J)C^IOhUMkM%D?=S?50o?s>f-lTQ~(v>-&T-RgKFGVJ>5>Aww*|8zmT7H{nzOKl1%l)%%BX{cqmN% zuJoIdyN(k70jtKikak*0qjhKM7A5tJ9)xKG=G0g(8yhiOFY)SP5F7+_r})qo%ObH$ zeK3SrA;v6TdN}_f87Ibay0;dkt*UnGr&+5>-{Bk{N*zc@-;Aqhlc|W4HWokqP%?Tf z(WBw`5>x4%l_?fE2$ZE2c!UfcN3_C!q#s8faYY%W3=_@Dw#<8iq=6qlzh1h0J8m<% zk@q`Cwsj4=<`tqlYoA8DJlrQLWJLuu?vy&k#&6wwCB$`2Koubvv~XXp#A?>;gl_*q z-p$u1;UE8y6cYn0I9OvjqS3jlU&K5>OU1MM;&9)O^j0k^kE=h6{M5dv>{dz4i;6E_ zfYHn&Dv)C`b;v$aT!UPDREbMlly4FusG8CDqP;nGsTmRzzU`hE$mV2Ml47w$eVsGg zCP8o_Yrnqp-Q2Wck;Vh&VKijW*N|!nJ9!lKi!VcUr4C>iLJdTIJ|5 zMzNq$jagptX-)n6T!9Z&nPQp>h9%T@`0(Q0smm$Wn-=O}u~>|fwf z`R1#h*IUivr|j0(+l~9|WV1yU+za38b#(Ow+=FT{G|ou)d@Iu}(aZCQ(}`Y*0?qjC zAw`z&$%M?kljN(F;7d_?$?CH6rsD!vE*ZUbTxz-VoJG!cE4fuTX}+ibRYa-L>)WIH zTS>R!*gGZDHAnZNJrZmTBQg=c$)DsotGu>p?&!KFU71YHSIz4ChvW?vb^1gP%I}_; zq@W9jR(+?P}tH2R_SLeRy5L--Xo^nzjio6B4BwGA`?!NI3-b$jEuP>z*HS|B%37BIsAr!6Xb!|2GQpZ*-Zh@yu$Y|>Gxih?qtO#pTwtB>QVUJ>${bFob68NZLitqN(v6KXK}D~gb1$A@jE>ES@^*fl-f*j6RT ztdm&V`G|0?2KI&=3i_Kbq#Zj7l2 z7vOhMWq|Joy7&QzLO^5KVcB*bN4X(D_PkXI(U^wSb7d?-Rh^OV31HeZ-u0uHW+&&w zxqhifJS?D7kvbwPu9?ls)=k5K8(t9*Jx(KqgYkO*>hIvY^Tt2re&Z#2CRJsWAH`;S*vb;fyNdSMB9Wjtz4z5>OP| ze|!=(Yj^^n`+UeAv$JfMr+i+3qP@|f0>!a3?iGmmebIQGzTs3hK1L^EAdHO16)lxn z5hLe2>ih~d70f@~N;3?f&u{`TnH%gSe>l)c{M9T4t^`Yyb6M-(?NHl$7u!JTWMN>( z?BG2#Hy_zO)>+por$XPXk$M!Tn#VH5tYrt_=MWL(5@+d}4or(HalV_l$r8u4X%-86 ze0jg42^_v=qC|;4<496?^xc~?`c&RtYMm{Hrs`MoF@(8ZMr0y~?yB#Abiia&yGIAV z6LMtath0_@Y8ijQnh}J%5`OmxKcl44V1R{jG_?-}ArCF|3~mi*D5Trg90zd>4)wY3m5J^YoBPZy%fb=i70%(co3R3x*XCN7_pizmRF zwgMf%8`DCTawR-*gNngm2}qsTB%eiAvsihOL(xbxH!b7V`e27;ayp;@4SWi`?K83#q0KAhmkG77cY) zMIM_lsyyMw=yKzA<|U2ZVri!lU3zE($~{qj&mDhQOd2k z3k4U~3?*jM$d3rcboTM)CZA3~=?#G@h0Z$1fX7+6^WCaqi(_jL2Kmf+1BuLqC$Y1~ zZM34xG8+`Tju_nJT7JMcAI}F|{+g}<5JO{h%Jt&zVw5+zmO_yxZV8_F&URC)4z6W0 z<8F6Fbhk`|Z5lP!x&KQ}0RN~nIP%yg`ZJB7^IQtZdWSKxzh?4L2cJy^eQ5srfEwP*%lz4c7>eiRO8OOoxcJ*5c47_~O>c96$1F#|Qta#SHI2CN^kTj| zz=RaKrA(lfb!;wJX}`~8@_}2?-wOlW^wq*^&Dt1q2kqy1IbiL-0X6+2c<-TOGy^-uRH9WbhnX?GIy;}Mt?eQBu zy|f})rna9#&Xk%rBi6!oJ zLwntQR##qKVOiFde#cTPNx$Q8S$Uw+9Sx9fH0y-~m*cbVNeWG_b}gj>zfpA%c7ZzB z^6_Q0LOxl5ZDv|SyM@o~%8^cPy`-@|=TH|65|=S@*?}Xe%LRImD2ULTJfIJYI4)5u z^nPNGl_Q5ch+inHTD#iE+HsQ~JKDd^V_Q{tLXd)jF#px^KU4Wn2&71fq5Rb;)}BXmBzDAu2x9$(esy!_Z$U!( z8mMsPC(~|=ZHPd)g2~Dm#g%kY7WbdwO#izoN%X5bFmi1^()i=Fhn5u~8xaSGD#CkV*LE+VyK7F(hAUVX*8 zr(`8s@ehduOIEH+5s2e_+E|%{h70^5=`>ta8oxHSF^l4JsrzQQ?kpOC zD8?FQv)5=cPREW+OD}TcFBv*eFL~>43`j$gn2_VQ&6}yh|8mtX5w_Z>GSIV2Q=Ce6 zeDNXL>J2~hsArh_echTr=8quXqT<6sj-wR2woKq!Pc)uQl(&ylQP(TtBMZ&a2z>T6whPv8-_mR4; zP{Tg{AHFP+H*bH=R4P^O6wu?Z-wK3##1CbQun)L$K;=cc89p>hzZWunb3@q7gooE`dtZds7 znuOp`5RPD2Zpjg4)Z08T1F8CvizgMY`v5~~e4%dsANj+weCEC0J&+}}7VwVA_3rg# zh+&L!QXJ}Tv*kQZdi_i&s+yh~XK1MU8E+iL&byX)G_(%-5?q%I0e;`?>E)L=7g~s~ zyOyZ$JY9Cxs?px&b~Y#;hlkgTEJC#qq4vD}Jx!_EMFhYK_(8h*lkHf%hIGjr#3H*y za?R_bPg&y3mxr=cTzHn7loKm@PHs|BBDXg<-wig-`PQ_`g=70O>n}g^OfvqsBWK+( z+kIYm=R*v&0-g5#W8v00H9jM|Oj^=FIqfW}#$U>d+rMsD05r6|Oi47G3MXeeuYFni zL&9y@p5C7nZHA22D0{JzL9>@d&ajlpT->If6!o>kkFupBG^MGn$da1csH>?3CEml* zeay{(_yU&EF+NPXXg!PL4j0k=u=;%+M%E{}?9X$PsuIp#&o04geycaWpjNRWX76EU zn6o+q%*F5IA_b)1n403mWIsTBBG)O#c<3(gZU<0DS#>s9j_y5|j!)Y1K0hevEwbiA zur=OF_`S>da+-fu7Joy#5(Tb=y_=X^Bg|FbBIZE>cJtGt11CSS+wXU2cs7bQ1~2th z+6>ysXl4Us!pxfJv;Ty=Tbc?P<;- zmh33biR&DAv5XqjKe-7KKi>~z6fspKTj56+&edBeVZTy{Q^lzJ)B+sSBow{(p; z9O6}5i*_77_98C%^;>CSK4J~_2D~#mjkD}x0wc4^Waj2;C6da%q%Z=-DWY>DTbnBW6Battj`4ddDkHW`vL6qS2Nqlt2!{mp=No#-St9 zjeG9rTBw;|muG~97i7XybzJ(uDd^n8s(Sq`3Oy@nKHW?c1Q(i-?)2^oHUF)OO=fa} z>2%r(?$r*_JNwa#I0^uk(@^y0Sd9N4k}O(sEp%#V8%-HgJ;dINjw#)%B3Yy=ykhyh z?#G=DxFDYslcajw&D5@SaWS=@5t^6AL=&rSw{NtYGXVe5*4>|G{)AlolHDgP#Fcs> zNEy1TMk|ylU)dJ*V%|SC96uLtv8lBiE>Ji$&B*jD;6@`iC83}*e9?|pTQoz}kfv6w z#8`ltZ5=pS{ZP}vAlVw_(VX;J7p+`fS2Ln5X$#~1t#y7a_c^lL<7B*ycEwB57^q>= z%6t1X
`#0lg^UK#>xDF3EhcapxHpM}bu{$=ITO4T`3K`_bK%w4)?aDmGv`hsSa9 z2sXHWnq4s;0o2U%-A3f_{%slIzOho8Vgd*6l#UwR^@+IJqh&7VB`h)bGU5jv(RS#z zCnH7W79re(Lu$Z*l+bOkE!Nhh$IDK~?;An;w;n^*x!QK_>Xdjds9o1{dL_N;Gv1miU5GGp9l>GZHho{WFB*G zL$&#YP(_8(LMv7q{)?=|lQtjbdvUyOk49Zr1y(K8-Wxu4jdheVD@x|^fPb*H_q<~Q zKev2wD6to1YHpy%oWSg7bnGLal-rwoBV))*EkanNF5NdAtFFlh&EHBl7W|R?i`y;u znBhDWeT(xQQB77;yRseo>pQlGiEEK_z93-vYCKcR&;OneRPE<*P;c6|L=VX|^YCnl zWra2E*)+$h$M&=8Vc>Nw1=Zz9Lxn9d5U=$srn73;;sc(ggS#dioo#de4>q4>YVS$>yrqAN(6f+w%KI zk`HPn1!ogcZIn>B@CcL<<*63D1Di$QL8V*3wJIlrYGpHnqT9Bay1c!i5hBeg{cBcV z*7d9)jT(_1rwirJ_gF{m|LkjHYr=G(aD(cR?e=>3+dF>xW|Hv-01vgnTBn8M1awo6w{Z1Gwv-rIJ1R#a2s^dW>M$!v6{ z2aY|S-qjRRaU}5U*vj2x${^*t7dg687v{z(p{y!?5t5W82~!&Cf#y|}18>?Dj&!dT z%_BcxRu9Im3~^d@L74`$^bNKmldU=DP1rW@Ioe(0!n7L4i;hXyfvWhkrVs4*>?gz6 zWkJx}eIg)#z^Z62e)i59$SK+I$j-a%*k{!bZ>(>++rByAjoMD$ENYmu>r^^AcH;_e zAg-3}Uc>B{Q~Q#>HH?4k^mofw{ay02)w1s7H_h<}4ug9#P(i`hFI1g5-V6m z)n3g}pQ*)-`P!D{UkUP7T$7Nm0d++)Yc35-qsOZ#eyVOx&LMLEu4`RJ@sYBsW_5-@ zE-uj`;gemEtWXj1r@A}m%bH~O@^4XH`!BzFBpR6>R)5n}5{bLRAap=BQGwKy9Gf+@ zuS1p_&WrI1=s20El(60jO&?9g|CShq4}J0n8}MDP!UdjwjBc zLFgKOisf>gAf??hE-y-?b-W|(TG-cYKlM+Ki*?;?2BHKOOrzLcCcH9s?k0-+PSQ&T zg(Rm&4Dlhjj6G97`*#_=e5j3;!2qpJRCSHwPRTSHyW6JJ;q2I>*yO6qxaTR=Hdg{9W!>*FdrPaS$SjBO zNvVNcamt)dVSc?E*p!{)KGaXz30LyADQ$3e(cl{=kvmO-@lcy_K39w>u;EVJ<8dG@LLyYcvK?7{d!U{vrtK2kLo|P6+Kt*7?BfE3 z3%rt5G-T#r1MgyEFVmR4{MRF7L?QaT)w7uv(PJ3h>0W<8Q}rAeKL;#It5*iGf9!;_ zTupQu^y>9%{6f5UYfwe!cI%q87Sh>CAthxXDLXIK8oi;gtteg*c3>(Chk8WXEds@N zYdg~qSN-l+SAmpu@w8X(}M{m*y9n`!2ZZLmRw7$_M2KWWn_qOAS%Tmje zaZ;*6E62y&Bi_vrPJG>#w$;3oH6ui;Cw?$4!+pLO3x}Dn+BEnCB?O$95v?}>1*9U#hzQu-E)s!~cxD@-P0{(xs6_ zlgdwF7?QsbX5G4ffz7TEd0MZW2OOgIA6EY@NEmUyE#6Z5dQs+JvpX*afNLB#Dze((V z@-ux2?yzwclzhGXEx+2!8-hDEk4F`<@C|kvVX77sQyS>!1Fh|NUrup0@+}7RSh0GH z;WOprGL6JCskH`dbK4JD<5)~d$ABdcVQ_wF{_HsjK(!o;`$W;(m=o;rz|#n`tZ7uv z4{~>5E929^JShd=d2_&G+)zm8GYExw_;XZzBTlYq{1O`ZXMd`(0;$!}c4?ZO;ts3t z`iDOJ$kc3Wd{_#!>NPP40&2a3)I{ACb zX)b8ZfN2*Q&e6Bc8`#*&73f$s2S9o1E?&umDC>F?Rryho zW45jF{wEHOdFvdd9vrrnAe@Lju*#>ZMrODR#-`IPX?T+-Wtx2v{@py3ms+HP! zoHJAZi7r7eMRk^bx6g2yC)Y#UquJTVU5H~$di*nwlk8R5m_?jMMr7#@ zZ-%oX&3HG6eO5q9^q$bIk#b!p?KTlQV1ZYz=cOS81 z#izZ&{N7SqBJp+3|IOukyY( z_yr}GAwMcLFHOtc9XqBEGoipcaR|>=wM@R3yW+}2sI}v=4;Xo_Ru3WgIk+0KYvFa3 z^D!}gNw1!!s5SLol1jO9PT4#N&?z7|jX?81>pD#iwA4$#-V-?2xG~V~ZIQ%UCYY~5 zz&cAV442K>g-G|@tARB;#ZXiUESe2xc(hg4-OS^eg~rf=Cg_U_idLuqz=jaGDo9?o zf&7#WKg1N;K+8u5vfuKgFO@;L#YNI;3Fie|x-dC;L|iKfE_*)juF>^kf}N_q0J0Y` zo}}W2h&6PcwRxwzRr$$7PEje2pD(q8v@Y*cZ-{wX*p_ktsJ`hv$|Kj?y7*qo@wir? zVZ*#~;mH8#`d-xQ@Avzi#!{9o+7cT|(xwm!_>c2E%zFcgsvp-Gj_mYx8Cgia{Z301m) zfLrOkB%y;4dM}|$*-Ge5Ahgh=N=J~Q6#Zg3`<#95x%d0sd%iKgamV=a&r9Ha-?i3U zb3SurtvR2WD1p_0##5=ZIWN32NlodBm`^J%VRONiA%<4z-AMXE&(V2`F)l`9wBhFuo*WqXZU=B~*9($Af0*Zy%s zLqXjr66|US>ar~264L`x!CM(7k%gqc9u&ztr`&Y! zMvl6n?VNZVM@o|7Mt{#&mlLW?4ajll2TZ1WCW0lBk!fhgWw8X@fuzA%)1uMCGFvP3 zM`~&F*dlSmko08DR%e5rhPA;QR=y)LQvCA-X=f>XYov)x?$OxHMW1pPu+PDnRjDTPC)`Zo-lHBDES-7^}hczfAKvW z#QIL!cb=hWBF_+grJOzwVQJN(rCguEl!F(@A%iQ|u@=tK z!ZzHNanEN5rT7X*zz?^ZB4b|LmFoGGrak57oYIVm#BGsCbh3=hULn^M*A$k7#VL7q zSkG{h6y?(-I_n}URlB(d zH!y6|i!7^%nw!ez1qrz0w8#D78bbCgpC%O$HoTtqsGDqr@^tLL#n>H#9-b5d^Z04c zh6tpFsQG76HU%ye8@EF@gkLh8iGKQVZ6+^$H)O99E3iAk-LDHMkYeXf-UDQ}Atpg) zkCqM*H+n~Qn0!!_X>bSt5cn{lD^|RdHg$;yMx$QX1CjzbQYW^9g?-z`ad{E>w++H} z8_biqlcV^i$k@aZ8dFZM>K^DbuZwe}Z-w4oiclH=OQmd6r(5!8OzcmsC!Dw_8g8f) zj~SfhC`2nD5NUz#2>)7l%m^@U<3l`u=Dul6OCMy39`nrZ6pS<$2+F~w(YcpAER0sK zwugLSleCIv)tYSYF6HYu(1n}R<|+rYGy8OKOG}z|X#2{jC6k&mjj#h>iK*K;s`s}m zZlLp{60Dw*PdEIA_ZWNlyOta42m8ipJ#DBmv>+q+L0*^8_{1L@zj2S5Fb{Jh!^QwN zc_;lrU^mp@`>i|NP2k+2Xf1yryAbrM4B)j;7f&WC&V=kDtNvc040PSr2u z)%zype1je{8Gc{z{1U4b^Gl)1FL5My4zIowqA)1^?VG(xm*mENC6N&QO2Qm_8ZN^! zx8Q+ajleh+=rhE08y2|UdGoXEts z0)Gr%{#D2aCo1wZ=h1ifXRvjuIzjopW>mr-X_&XRumP9uj5r?|Wtt8fPLu#EeD;() zQe2rk*J~&gNBOi0&}EJ4*>%QxE5P@aq1Mz-5iiUapR9AzxaPjx3BQq)pSY-CHNzRr zvtqm4UyU@r`!Q?%;g*ZMzo+V*;Gj|Wq|>_MjjGJe8U2(u9;HsXOT6+U^DQ#<XW;8^9SRHQ8Ux#n{tVcw0C z8+_EKfLa$;Y|tcMC=xEJoL5ATdK75_h{rge-yAg5cqA(8pg*P}!fU@=l;Rg??_V@h zc*`c4AGctD&sYS;|86nrFl-;)?FtcOz$9q8q6gX@idYBF8Jo1gSaKj@Mw5B#vOJEK z#zGAP3A7_>V?1W&5gfO2EP7j6aY~_kBC3~0sZ$D4#sL{EX)3+ znbO}%)PkHVq)Kb5c;p1jc{Co|&%ygso7p>$KT49F-Z8t5iGP&HPq3J6#mD5y{+c(E zbUjy`fSl8?_qUjGh_MdEiWiG|Y=CgJoXA=mPg0qfr^;flQkQ6=`78M!sOLU%l!*bl zl|;5Tpk-ufH4M4)s_lj6w;MK+;VRME2)B~~d>@ez0YrJVR88Pn`s+! z0s3B1zv~@QPTFJ;9_6w{s7W8ylKYDXdI6!JvJss&0y4Lr@$RT{-z2=)fX=v|vO_Fb z@bLN9ipXS*%vDi6BKmRqW*$D9WC*p^End{L7R z04Ie+9DVf7wCZ{yta{s+EkEC)q558(qET*_kTB0)!*;4bxNdOJBDJ#{hol`lI|yQ2 zRQHB5`4zcvI5*^B+(xSW_Bv<49=k?JvdED|?tm)d;&b7n$x;D8Go_~9Zg*);1-&!( zofj9)rSX<%?b`d0C83hrwctEC+RJ2Oz>dq_5aN;c>c@>B=AQDvoGC zi3LjuuBfM=)yC+JrHz|_d05KHJ$N

^cbgyx`_eBBzu2o}j@hCfu%UyX}lN5u3Zz zI&`Qa)!sk8{v@G=E>Fiko9$&Geu=BsI8^T~&W`N$%gjNi1>wR>t~GoiMrS@z9XAGa;4farxmRm1E2tazNgl!4(7UX>4_=K*eK`Zm zCR*s3j95s9A7B%rZ1%6w_RsIp^2F5Sc-w8XtBZmjVTvyLOhH$TH2b@HFUO|jjmN_R zvRN$GEwy}S8zcLz3LbGFCi9g{8IB1~ORVBWlg}%)x0GP5dJ|m-Csfd;Sf(2@fxT=Z zVJIH5?p|dZWtHbR&9vrEgi$SImp zsmZ$2ONkIs>hTXP%p2;&%d zt4p7rbzq?Lm%F8dO?4XPiPC2CxEv_cyljnZc|Js@a_4pG8Mq^m5|@gHXBOoP*_=e? z3k;WnPgu)ECW=Psz}h1QJba1?RTRmi?Ww|Ppv=(a#p2x6K0i&KVL{TbB;=%H91T0C zadU{zbOah92z^QFQ9Rh|tY5@5QSSjRroJke((NPjQO#Sdd&mmTx@+Foy|~8;Fs1hC znm@(c<&ib6c&$c_r{xPwIG1op=>{L43%uY+DE)Egec$>(HK9)=7g)c$C){zM`T6}dcgwYZ!zG0Y^L1t4(1OE$I8W*tF1N?dsuW`8 zlPvOu4%3(yc*RLEle;NxJd@}54y;3{V1{W1@0xh|Z6c{+O1XNm|+U{_EPvUlc+4R%v8~M0UjCwo)41#)P)SWadnue}@FdD`H)vk$( zzv#E;IaNB}V1>K|qn)|ZIBI=b>S{x-3x@(;F02;uHWko61W=AO>-p#DN0m8SGbcQM zH}pUs?k_G@hgUg~@GPR#^GooFctaSEJ^0-yr*3Kq=({K$X(;GLm~oag=DVwHSfFFx ziiw-)(pVbQ@5L;9ptcc_5)%#{u0omQgY-EP%7T}9Q*on<8Rz1@G`>8}t)^B=LUHG0 zss?&lz=x`yVVm;lELFg9Muk7)okc7jDW{Z<0yQE2pKqm!P*i-{-4?XK-OknH7P{B4 zn5I@JLYLTFE|01Jf_cQ+;1OQY>P9RrIl}y}N5zs>vW^)x?@;i7gu;#)Wh@{Z!7J@f ze2SgAA%>d81l`Ku3}5k>t^MSK;~75;gC(p!#r0F9-gXZjKH4{kQ>d(rYvRZs9mZTt z8+d>M>A6EGPF0x2n>H@_BvE3*$HUp2rX0`4-N(Yaw^HSPq7#?ezyUjAyjJlAll zw(>%LS8`OS704Py%r|V8baReKuW_5`;EneUf2x;L9Xm!?JNYw#|9@w`*oW_FV~_p@ zM;91E2~q8_ve>#2G9e_Uio%uQlnSAjp$_N9w8xvU`@Sdnm>9Uh5USn~OA&CtCuelE zsn|yap>j2L*lVShbC1I50aRl9P57M;4m*ssuIK#mtKJN0%CibK8e^zZ59kzd0-+r} zq`q)ws8XKh^g8{`3iriY754Zt2Gzc9O>*J29CQZ{B*I2gHCpFvkgF})bX0KtcmE{2 zm{Da>Ol}RgQ6lDn#>O*}_u|v4REROl+y!5I`!T((g5-fD7ERaa-BhL9@K^6V9x=>c zu{2hZ#E!{PneXR`Zx7tfbcnwhRd6e@8l4~~OygRu8LqhNesEy{z*U~e%Fia)^bsN7 zX7^l3;7KsNn%&0wmw^w~79Iol^et2q3Rs1ZX?DVs#DGnN)RdyvJB#riS#CMk^Fe9y zmvVHgyG|AY?SiB`Qn-Q;uFX_*!d`s5wJ6*ttQFzfjVw3(4KZSaJbCKFj*P}r_J{2{ z#LZBSWu)kg>i(3kh-+#do(`L4Hhl#l)fA#b>u+W#dC_*+6z2l_sXd+Il1PgojBw1>`o7!Qo9reD{*3# zX+O@8a7ixfd`A=s+v4>tHH|N<3r$llu9v=&G(2OfWV)tk?It9&Rmv?$M5h62h}df^U=o=q$I5hLHEhe7 znlHTrv3>|JsxQZS z&>K?XmK}#|0K|d#dXCKceeGPg0c&rH6gy@MOLd#nhE#fn2WZ5?j#k>x3zI5smBXkT znYZ&C@?I%)5;ls*@?er;SJ*lXG^t*9j=0{X(NTEt7Ac){lnGl{m7Lm&5AR~|HN%OF^s_~>9DImEUQ;|&6$!1lDe$D~uu9Y3Hlq7Kr%SyJ@cCv{X6>OeD= zfMJWKv>~sr?0fH6Ms@@-h_E`UQ;MRBsalccnaJ1xFx|mVOunbY#zPHGMoCMcjJp$ zAjNN;?vH10wt>__K4R0D^BR1jc5&x9%8@y$wS@!Y#h&)XR&BQXqU?&#Tc?ed*e|Gz z0+Zb;_zOpJbc%Dq+G;#$Hm0wi$43bcP+ZF`xiFO64j$ux^06g?99zmMYgZ!QSD)B! z`h&})nE2**`+kQ(?&;BVdG;!aXGpkdp;P=vnkb*@JiUaWsO41obmIggl$E5FiY?n! zA5Rcdg2pC83?^l%JusJ1M|<&D_)}_9EjJdESq(6^e%I zr*>`ngq1!B<)Ddky_oU=uf>K9%C?^=JEq`=@_d3*$?ILHodiMIF?D$2=uV6pN81JJ9@K+dHQ~M%CUEPqsh$#cWu*pO-;IexNI=j@^ljy$4x{rJ6uOsspLV3#Z9Q-dELKG993|y){u04*} zxiLJQTz^RrS~_OW*Q{vo0%ZpA%uib~J~xqteGoFwLosB=CUVvhOY>r#z-bzPP-JVw zKLtd#aD2f$r- z=EyYO1gf}O*$?rz30;kfv_6g&@QwaT;yF=^-gCSUHRBI#dpnk+nF#B80?}E;&xEq_ zsevOpRVqC-m;=^_zJS{*^HE||ur565D}230HCn%nwSKFAyRu`6p(9@4x`qua*z-^* z2TbOZQGfj?)K{?Ym{`B~+(dPN;>*IQ96E5u{mh!<;reCx#gD12&uV&-_vhb<-bV{{ ziTg&F{`nslADE9^^ce~2=jAdHB3;1=YQa{T@j{S7Yt_9U(dZ(# z!TGqHrAvobI+gN1!y#M<4B`{x$vm~89~JS}jt(|)P44scSm#RERD{E&P~D$zFlMN@ z#MkaVov)&;uK8SZbiQVM-}!p9LdcG+zapDf?wgt(W!C*Mx{$IT~K2qf(E2N zksUtWx|E4=cB?BggokD>9_&AN@f-T`AWpdI2CVIOgbd@cp?fLS-Bk>@nqt}|c~iuR zvHoVbgp9d_TfxiPkOHJtV*Q8hNr_q3D;8|#lYHIz&6+6vTs|p&B;Bs-+LIoU%I8pn z?uezFW>&5NfgP90&P3NY^=z(DQjxS|m&ca+J*`e*D2f_GVoe9tD3b$CwSctX6z-U& z%}rt92e)l22fqyWSD7-|XXn{rC*8=hix}BEuhy4F)y13wa;w{&UY3GD)WPP`I$wBt zdgsvRYJ))GPp-qZy9LEVGuivmZ1-%HLx(wEk^4`ft79(%{=+bMesU9A$3Z( zSE|-wf3<3Lnr0P;H^EBbtvt7GupKbYTOC3flx|&2a-}jz6Tx+ESL|XSIGX5C6R27) zV)%-B*3IB@nKFhleXz-W&HUB0(9omFZ?&?GofLDq%9Tw=NCKW+j@NyZ@!QJ-^oe1C zSn(HBLr5bzmB)Wey#I$c|NZRrvbGd;Kgln7cS|m-Pgn@D*Y?=XbeR>E&T+ahh=GVND4Bn>L;)2@c)Q3d&tzUksn z6Ex5sVNfGh9JAM3y!T~{uivG;x%a|FK>T}U#ju#Xas65z$PxwWDM+(`zN~1OU(G2k zH9=0bI|#J!jaKyKttV2q9)uT0;SH_Tv-_q&{-DvfBqYy?t@G%lGm~Z* zdF89YtMzQx1)RdpgLq$(R7XS%UrBSD`{QT-NdA|7OmY`EP#!sP5=9f8>75{Eg}J3eqE|9TrFsTxEL5SHOB7 z#dZuZzy;f1mzIg#af{x6O+EA^X+&4{cGDRr zP&hTJ-CLN|odxwlaPM6DD@jF&evO&)mC*yL=Ys*9n@Wdw4jE;d8+wJo_vmh}IOST7 zU7b?fY(Tyu4dr3tnV#^Z%-!#FpUF^cOJ2YHbdWMi=^-F+M{xS$tnzp< z|J>SYV(kNe{%C1GxQ2@gUo(b3PI<0Yc6|n<=ZYsd+_L-RERFEA>T>G9o(2Ua++eR; z+W0aooKM!VK(yY5`FNRh9NkO zrPzjS`XW07BClYu5wG55)EF{4M{RW#ZS&{!8YWn;GjqBzHwh}m;qzfz-jqxBGr1Yv zolrxEys(%sq80q9sg#Q<+egpQq@ao{(t1?=lZeKFu2Yw+tk`FT2v$l6F|xo@ zC`%}HDpfSLn`11w4q(vfeNee&%qsgdtp5;6$>NXX5rSckhK7DBvdY^L82iX2_6<(S9$k zcXAe0I;S)kA5$gL5QDdZPC6seH{N*5j_Ou8Ts4qX@APbv2Z{%hcgA&&J|16%-)dHu z*T#4xz!XhrU1>indWB8Pdsxx}VfykF7V}tG4%S}uyso|mU&@H5|MLE{>Qnx@ykup` zAuxdwhc?FZRnI_}YLcJvu`H<$=4dEKt2?9o%J99cP}b<+%eCsd3Rm^xG$c1oYz#*R z_ceOocdL(x1m>Is%b-*%2ITR2+7O+w%JWzJBGvA0dxpM`zml*_KFT?B=PfC!(H{w+ z%V5|U?dJo@@x91FkR3w;_jS)hMItqSR~u2j6R!GrCTN;W&0f@|(eWrIDOZ?nfqT`~ zf2ucI3*m3+ zttx{B>w3V}qG_BGGh4)R>DtuTbg^M%^$H()@b=y!lw)r|@Xa#n-2h?G(PmQ5V zfqGt57)Cl3UGx)x9NRwdP>|}$ht?(7?Oc51HyZfKE_0k=}m2k^?XD+{4;fApL+ z!nJ@>O@73iodVU}P2|!@6e~;oH{t5Pew;}0p&m&&=4=JOYUExp$8Q#XzbP3!LL!a)a*;HJP=*F!Ieq`{AC`9Ggc3sZW6Wbfwvc{bapYl;xd@^q%p+f zw4>jrr1ZUa4^yG}&*thErUGnP`CDV%Q`U{wk0X=Mq;u2ktC9p)=V~(M*#fe|9r?79 zR|4o5kS7Ta1mzkbL2y?4eh@>|`a9DsjZQb{>x%Gs;;s{Rrq7$=^jkZzGK;_}n_yzh4QWmAd(CF!c1i!mRq3%GJ-WXs zF}ts_ai{HD$5>kY@4govX&l|9z5o5yqMqqHpIHyDOAdNJjXw!t3bp>69%`o2*nd#| zZFIulBs*a8Lpn^M#WipHBDoXzkts>r>xTP`KE8rv5_tem(H;_dr>zsVE|{6wqR{%ssDX{R2{lkosu41UK+=m+(qa;7v)`)*SFRHMXv{Gsn)B9FeG&7jw{z?(hO)Ed%P zV<8=;ZzpgE>Q}3Z_MmrJVAEWa$oL(40C7GA-_x*-<(g?7bn&$Tk(M8}2#LVntrS)L zOT67oAI{PSbJ~(VvwJM60e$Yq{|EK8T-PZ`nao#h`*>aMX5U8%iizPJcNy+)V!i%N zi$D7G7PBiR1{iYnE*tg-&}tQmVZbXOaO9-JeY5s~uOxWlFgMH&<{Q_gzuj+3RKu>+ zrXO0x_(OlFK6#m?bjSSNH2!jvoNA#CO%B+)M_2|2xkJ>gvq6Ol%*?8<<~MErKEl

P|rWYpzU`o{+Bm>*TwG$^8-x(qA@?!iu~`Y@*iauJ7Q0L zDI<{|l=bUl+&@gJ&z}e=)+n1psBQ#;b^jQ*-1}+$XHo+F%bKPgfwunzSpNHhyZLkW zzlnnRyT$SRXKHKy-FQ6zNoyy@wZA*LQ#U72i33}&M(>Je=I}QZkDSbGG5P;r{y!D_ zU+e5&UFZGpLjSH1x%5znbSYFTD{~QtvU1LDLb{hdV`!1*r|#Vu zUIXaH@cI!(UsRQurbbJ^FE1Z1mitn&vt&@_oULt%g=(>fB0W3MPfD|Fkg=*J^PK6!R!xgi)-w|+hO(Qs{^9a@ ziZ%++C6SP2F8n&}9$=RmWmj-9t#f^tW%K%OpkR+=?|1+Gccj(t*c0C8tiU)tTJ>&d zaE_)?)K3l@VT?+T=4uOSxW>I_sTr}1Kqy2tB!Uxcn?uw8iq*Hil7zCe+iJ&?739=t zt$HR7i(L_2m1HoU-r-CP<^nxNYo+vS*sBuh=l^&d^UolLD%&Hj3!-;lq>T3|iQmf{ zM^W=M#wW{mnFTRE1lbe1=v{|?3fm7&ZQ(F()tL8_R4;UMG z^UyQndF)&I6pujJ+$^AY3ZGcfpECcs=3ys>eQ9iJ$8Am?OJo3vhVy!xRHUt+MYt)sVihzSb!5j_8^H-|5F&kn72YD8k%=oFKv3@5gP56Gk>g<|0Oy*e8;4r|B1WGAT-y-Ie7VX zgIq)D#0D*!TeLq=O}&LrL2J6Se|J2L@&J9pg* zbvHyQMFujM$A|os7nbMU4qPnjGy3gflPZY$ap-ijwSd^+uOzRBL7Gme`K#-@B?oH# zt&15z3*bj0^GAfEy9PQe-v`zDC1sn1055y>B)fHS4j$87+puv|MK!*J6FEdRp~Cbv9c9 z_61+?iuvhwhC<|5l0(iTCNT&JpEefbnnQ2Oytm#Y5f z12?De;zasmSfIH}IB^`uOvDF;&tyikj@mxAAIjMN=~nh_9XA-vzLFHlReB9(cYGx| zNj$xRTO&$4_RRW(ynR;UD~ZEbl5{!k@xS{>j=$gf=hIIi#FPT!p;@Qd%YWI<*aIrH z)EdX-9;XqAW7DXRP+KLjRd>pt5Oue;@9hV|dNJ0%fcD)`>iUhkHsuLFu?eM42hWKy zt8?=Id~LS&-IQGa*%$uP_nm)m_Kkl!`~S|@oxdT||JXVI-wqMKqW)ZU|Lf(;|CP}H zmC(Pt1pd!-Na%I0+1~qBmO?&XrLQD+{T6{Q@M|vTx&8qKX(RKeMZW$dSRzuo@i6sk z9trBvq{{6mS$+=x(kWRtlpuG8IaHDD`PjyJ0Q`eQa_|xRhos%x0*7J03k0=2$qpp-96!!f{zLogfHl^HO$rhNb9RO_?K`yJ5om#!JE+SJo@`67d&5kXRGG#v_@3o_LeS%^nh zsk9!`;xet`_jsb6?u!u~KcyB~8ssdfuN|3gb`^4dFP5*PW>TF*ze8KJ#{Kqgl$B9;2^(8;xfn}PJ&$H#oSK*g zMQ-e54s+Mp8Pa)zskXJiY+ul;W?`pSCtXxOno+au5?&;sv9QnlTEjNo2l=LO7I0w z%QFThMSAl%Z{A-K0-jg~`Sx+VUk1Vu)F(B4p54w(*bJmqMkhz{m_(Vmk$ZHHCl55E zKlaHCFj3b)(BK8%5s>Y9qZv@|sd}f#dp*>Kq1g1`kbv9;kTPtw+ zW2BS(ng2|WO}i%I#tU&=b;|W2xzVe zn`(e$y#(be9<-3PVz1!cx;^uEVU9Y1n4+P1kH=4Yb908=At+M}34ENW>i)}D!q zLRC%F7*x;0%Ox44kNAQFEhegn6>Q)jQCGsP=?Jh+t#R1#)*S>T zQ;KPNie?#J1XXs`a3-wxh@qzk1ObWO!IUj*=XtE~m{8}L`woja12gwn{kH_s3?+cc zY$-pR*)2f+_y%Oakf9*%g_IS$BMpP4ZUXMkjq1fXheuK4i3F((r+lF(lUJs;x9#4d zdFO5WgfcyPf_j=A1@z!!=AXkMNklql01+;3_6i-5(NH4YEFobh1Il&%aVj|6i*3fs zF;D?i4+r?;B!{2Q0w-j)WMx^8UWAhxDqYi-pSj}HENJ+6D~z1S`smh#E{g+IS~QE$ z+l`p1>vhT4C8Orrd(o|i>n6$i*mBV7#PIT@e?Nu3XZ&;B~O!D`Mq%XiUaby(7g4_| zpd7&?HVw{V`qj6+S?ExNvEK^B32c(12w@O2r$y!Zr`mLsr~_eFJ8J<7b@#6JVzawZ z)XN8>>ghd!DI!yx8lFWf7J~a-a~c+5rTJE-!)-wvTqRrzy`ofI)__R$T4I6UQFKqL zhGt59(l5c_nyC%(E<^Z%SRR;ONhCAAtu7Df%vAi)!H}Q6j5Q+6vH)r?%EtZJqG4an zJXIBb|LHn47fQ^wp&(9UOEhCk?nx#bo9ZEk=yc4pV}%V@uX28F>J7ZyN6XKqVx7nJ zRA-LbZ;!jWNI0ig9YKK(9do$XXV<%ZIe(O2a`^$}bU-zcpa7?^j!(7fk+Sl5&I;WX zV*VutSe>L3AjtruW39^LtTLkzscWjWDatLc2vlhZcf?{e7wfiBEgIb zKF8=Y%*Wpl{<^v^*a1vxRv-|1dM2b@I}dZ=y|Y5NUeg5Y(N%SBQGYLjnPG`>30J=j z%J2;)u_eO5a*)jq3DGQ z%1CJP3uC)-@dW8_lRs=%q0La3FQ~KH<8~xALrA0(P&JXesUhBlJb}go{2oN`wU#__ z%7mxl+xA7a{Z=wQYRacg_13-8eQPrAS9gbCqXf($Sc~LOB!~5wQMeS1S=EOW4YAv3 zmJSIg5iH~wc!YJj)FTZX6Oa`|+r-wT*0N=blL#G-vQ#ytD=!YIaJ8KVP1Q7BK6rR9EE5K)meyq8QfONIesGo%+wJZH5T|J8rH%4eaZ;X zy)9*Vtb<^-Fn_a&;Gh_{0cO!EP#{H%~P-#15NTPd6rl#b|gJ4tK z_~?)NE#>2j(PZShw!&rM*Cyb{2?}HfK6@)1Qp4y_ycZk5NtouuLu~z4oTojqu=5r7 zRjVVwwG{4%jkSsn*RHU+vo5j`eVm>Nv-lAEllP8U_+&>YQn=UDA@)L6#ZBF}Q)OBv zY!s7&?eqt9X%vS$?XG-&o$yPmSvqk$0&(pTqC$!KFKufck7I^>Eo*JEphdaZ(n1*= z)8K?5wi*abelWD2v^`PjJR~a8x zj*hBaq^y@^(t?;j$=$|q`YZ2LKL?J;+w^YW#@kKY<1mA06xG%-5B%hkcuUD0>zU^Bdx(~_dHIv5`M z&ish8i_Mk=itQf9Y`w%F4y6G{^w?AR@@cNKh|g0lA6d|yxg%*c18oBPTC2mww~W=? z78^#!ELfl}0NT)vFee9{2Out)rh5T?vVE>*_D7yN?U#)0MI%AloxCgOK;l+LNu)B%IsWBW zl036xYPY%jlWn5`ZYMQP74J>e)*@x^VmfuSiAPi!@??TyfnCcFpgQfE4f##EDXgqD zAua94d_eCD57*XNd+kN1{p(0UYpy-X@*h;Q$wGhsQhZUI;}6% zio6|6WdnX#xb6Jw&W0T_mG?^CsH8##%c@T)S2!zsJiwq!B?}JJyPHSx#sXq9^bveS z;B@MEqWr+yFQeX-)$+}Xgfx-d-9|qTzc$iSmkk}LzoFEq-xinrd<0%F0fXM;OXCqM zTfqkT3bNP>VXAf3N(0`;3R`0hZP2zn%K?jljW;C+wXk#!1M|L;YvyV0Fvtvby>RAh zVyb{*!9ASoGR5Qoo9M>vb&vO=?gnt4ciAJhz@*C;g?z1&ZSup0wBY3Z9e&jKb)h14 z!5ha`vcZ6&E;2;iI;L){MAYuc?8V8Nxwd7&)n?eX(Md&q-hGlQg+4F;_0fL7)Y&TW zAkl0l;L3K^pv$?^IZozRe3j+yo>yR8yb+DD{}=wDeM%mMG>fk!)9u}B({d9@$t2WG zwel8L4LvDc&a24DQU`vC*74ddInY4{e{^oKj>bH1o6p^f4_`?>d>J0Coh7A=ax9LvsQTPBCI+ns#5X6MkI84Z1I7S@oH&hwpvtjUqkIvu*0BVRU{PhigdENi$15FDtxhYm=kNV-5^+HJ1U6#xwQ*EOXfI)p! zTX2=%W_swrfeUEsK-vM7daR?m`!ubq6s(e&i~y}VH= zHuF1;b`2ETIdv%-*!n#QuA8-=;Iyrc-Eu$LlH9b~b+eYl*zbJ&=l@+Xam?6J_f#I6 zU3G)Tfaowyiu%G2l&aDdYYBb|e5x+06=IhVs?jAxzy&DtYM{~{GW|+x zTi9To)nC$NcB(ilpn@f&bF8!%ir49HWST4uPZe*SUNp{KvF%`>SCX7|ByJf@Tz3CO zDuf4tDSp^MKszYwOix;z{zWAA9(5gh{FG=@^;}5-hXQu-(ur{8JpECc!h@6>MV&Lk z!XVc>+4{4Q`o`G!WwV^zJ?T&K|lM}ML3 zy?)Z?##P14TuV76EDYTd1a^1@74Dr_%N%wi*wWXax3FLSLBZs$N9Zr2szlp(c6k^> zogkm|&@;N)5zMb-R@5Vw;>M$bB2j%Ou@x4QR!!4;cQ$lAPvN4Q2V2CfWdH$I%Rlj zWH-A@l?zRl>J}um;F=M^s<-PA;fnw+-K9$ey4etv_u7KqsfaFzMfW^kfm*&bT*S*F zyOw?VWK#}7_6BPL01NB9S0DPRqt{|pJ)Xiq>zPq9k3_;wSs&;XPyMu zYdOjyk3fGf!`w@hGcvkGg8l zil)pRUGvE70k%=}d7{-zeWmQ90ou^9JyusX0u_0sE*H7%o>&$L$invqV_JTD1&i0= zE_BS=iu3CZRYYODR=7|sxgR4~ssKrq=07x7cY_f-4*fv1gSjZyx@sfNCKSyQ3!P_3 zJDpnrKuS)Sw$drV6`51L&%B8;A`{*QW}eKtSm*^)T|a$)2m!L4>7?F5nXm=C z9xE0Yr3$7CZ~*$}8Q_tOF-!0tPfwf1M!Pmi7FVR*U8%b+R`$xO{2iW9pVHb_wXMUD z7QDL*&0i#SzcphMOflKHZvA-NyOA8brFO0R5?wuY4_hSVjmt_FH1pr3^YDjpBhHRh z7V0?PXPoy2a@L!OB%$?=fWmviWQl_9)9jZt@~oGYhe`x5Q84(|__CIn;5Y*;Z#k5{HT0=p zKX^~@Asz7KiZWpse&t-J(FpTVM_ZCoXb?v$+^+ItgS_&jskm6oiB#=O$gy8n! z1T9{?rMM>qw*tW(f?JDwaW5@e{3}|Dv^QVB|D5~pGw!+P-m&*M-F9xh^X7kSxB%~u_>+E3t{Lcqgi%BS>$R=|hnZ|t@odjxRUJ zTS!-Nq;x>~M{e*YE4De9r&z<=ZM+S?rqJc|%8cHFHe1n#uzp@FLR`SMRx*$7fOls7 zJ0fq{TH*L_^U-wlXKvR>4czeDz`!^Ba7`oIr?-_#8~9X&p}N`JWJ?PL&A9bVv@K9T zH15^bzmdoGu5ri^&38kvTYJnRlaXVB*EF>e#FQrwR?}tYh(SHlTI+VyJfv3Cili|Y zTCWNkoPWG;{_yW~?H}fAd7+T^jmOK=#5#MxaWs&k>|_bPi6{b=7)xbc^5e7-T~np4dV03R}a8_lqzy$WvM+N*ZMNxsQ^p8bhXw zWv|IgXM{bZFrN|@NO*D`yRV|ABRAxgenHTUUA z@kd10m@<05Cw^%*aV3R)dT5tq&L zM6Qb@U`rEugIawje=%Z9F>HwxjKgOC;V*)JmYF?&(j0cuby6)gZR=CD$&j&|q{F>I zk@_r6dNj4NIcxs(o0Ypw{s#(qvn-+ONqmq(z z>l=}*D?8fN;rYA%GI{Skf9^mCD?XJ1Mhe+?N&C|Jk}h(s zV6@IUng*VERQ~gAx}VMrEU%9S6fLy0jza%!y8nFEkkdDTS+mZ|I|Fmi;GeJl_V+;G zf0=&2V7C8fw?*1KFTIqq6I0qUy#7w=-xx2mM~zpL;NJs_|KS#Yr}`EpVikW1qhJ3+ zNB-e1JpQ`*K7^z3vJLRYOvmq`!QXk)HEC8heuvy!%54U-smfXsD%Of?qVo;mEI%&_Plfs zZ2~oud2~?y{P&BF=n) zLZ*ZwE^{*yIw#9mtmhA3aOQ!(Ob!}aJgNR}Om(F_*+Ppje|HjFkpR^HzYI80dPZ0ZB`}tGW@s{2QT~Ly#VD>j>+DqKWi^RY)l7KtvyE3zr zj5j?!@($eMnHm4jbN9Y1^L97HTUn9zdin6HR>~VV98{0%Xq!@`R%KQ zPX&QfrFe2&xx0tXEqH{~V%=W^fB4~H+N5^>xZ1kJv`YTu3LL;61Vl;T{|pf_s#f7WLx1b+Wyi|T_`DhiyF?osuf{9;^VQ&Hg?wiJ)M8~K zUA6yFfo0qOQts5l>;L@b@?X>o{Ht4kP2T+P_Sr&Sqyb0M0k`@7`#STSZ(rx${6z&| z^%pC^d-`Vt1T0}4+@?1!e{TqG{Km2AZL!yXTo&{8dzsr3fz^#Dy|0Z7eX{TGzM%7n z^?fVov_Np5*LJfc=%|sNa9n3Xt2u+4)vGQ#Oudgu`%A0l$GRaB!j8LIriQk;4P4R3 z#nuT6qGtRLaNFpwlv9heb8oA|BNG)k?nLf?Z_lL=SwKk!?e2*BG%4pvO!)#Kl6BWc z;u<2=`N=uQ*$i?Fg3#-zixr2SD8exAFs%Xx6q#7r#L6fAFza#lv|&P+E_KRr>rSZS zBd+i>chnXMk$`?)8oUwD8QJJ)sF+_14bGh6m~b}axx-Xow8{H>8BR0l4b5DR#N#=*TU$ zY$+1M3)9~%j3A1${ysWeJ+-5k#Y?o#V_4qk3>5}&HP8g>NOWu2!p+O`o-27E9Y&P) zg_(9$5YX18KozdKLU!(rM`Z)z(@_PyT}LfUi!_ALj7w7BC%eeLt;l@3P8wjJXrEZj zQzpTp&zmNF&#ioV<6D;3!8|_TO0{*hI1sLR}^fHq`-Y9SuWJm`my?zgIC1zw= zhNZ}6&3GAY6{}KGJ}$M75P34lw9U;se_&W9r+1H`sG1!Syb7Ed)MUhhi?YNkzaV65Dg6`|LUuKe|^U3vbt<>I|S-h%ZMF zCmYKfoll;M`8%r?vNbkW@64=Prs_?ae=-{vannkMcM>KFZbrSRn zb3|qFRJG)Nhq!Z9>krvbTv~J?*Mlg8k-NkiQeLG^q5kj{{D%eK(T3$nJGG&vx4v*I zYN>+TN2yz@i0?Uq>N#T#qoaQ0C2@bWsu_c^d@?~=@l^5)&(A5jRYk~*{YNP_dnvQ{ zWv%qR+&aM?x`OYjWkxZBF%CJ(t%IvcXMl_tHl;j@yqw0)C7qE5kgt+Xu^hR1ncDTE zFv&rSC*_$Zj-z0s+W~Y~L@|S2=(Iseb3#dMEhnu`wZohMG|g4raMJUnzoARB;NW1- zi~Q!&ty}+Z(9!;{Ce(i;rWNgh{r=_@LVX<4eUE=f@fi6kix1o(gr0PwI)p>vaW432 z`!R9Qv^iFBHp6D!M^WDZlr=8@A^TdRn`KD(yP$Bs9d=NMMf{zNqh#50qt;=&)k>Ja zLD%r&N}=|LhhV0enlPa>HwxxBZ(_GhEkPrfM>WuOiHRM(w7O`c{AWed%vs?JrxBpJ z;mA!P#XxeiR@FxddZp4@c2;}&i8XUN?u#*#b(8iB>m@qgEerDx%b9fxbc>IcGi*g0 zSYd_ShGq|59-oo+sACAH>~5sj=>jVS0egxG%~30y zVve987Q>YT{hBI3SFP=>h$kPP!swxq5ZO8>$;GE3P!ua!Uvp0eRQx?p(_8IXn?*Y7;CS3v@wQj(}O8j^5; z)XXCr44zB?iqdyJIhh_CzG~LYZ~^B3(7zsPmPnG=`dR3BqtD$lL(?>Zv{J0ooY;3}x~WWny5jBFl2`jMNg)uy#ywOg4;rS!u z!TD`MF;(&xhrqkpJdJz3>jFF@kh)Ilsoc!t);0$N1UeFV&@?ynlGH7zRBLtGj(TS* z|LK`W^LVLMyvc{Wg~({#Y8qr8VnZ-gxX*q*CA!i~nT2`wt9fK}x{G0E>!Q>;j~I2xRFXg_VUI7!QWia ze*@XzBl+Kdw@KMMshPlu9(7{UAGrZ&zXTM1J$b6Wl@;xzY;yf1QyAqI)DKai}u&tr;SSeyav6y27!=sYLE;~*6Ka`;mA?RkeysqMbz`}4Bd-BT%kn(Mi|Uj$qD3aBsg zFYMrKOhjs2cKUppa|+;G5M>QE@)yDLdRdiHK!BG4R2wi$OF#fg`EMQnkKg_W;Pl*K zSBtf)5~*`KLG!Q4H>rdf7FN(Gl{xQ)2Gt7pk7#3Ckyi)?Ly-#$gQ9Yp_^1PVL@8NV(8HPiHpA7?K}MP4 zkJOEN@k}jhFx42I2)J2dYq!2sA3S(d2QFYnn){TGP+uPje3)wFrqnn9v5S+(e3Pzo ze|fQCrdl!SVkF^4Lm2$1u1>`Jz>iYo&_pIA(hg%g&N^z=4V91nY&mAw@8MtuE<;%4 zQ!_-pAdYgf9#Ax|3#%eA6LlZzq0!;tYp`&dzpqYji^(pi1I8e3dHa5ne$2=mkI46U254>iwAvGUuS69YEtkKYCfcF zyujoGEwSN^6vRxG8n-^>L}h+!v5pgOoGNit=g+B=LU_TxFG7sueZW6Z$SsN@@D9zNvm%V5^V&AzcO_B@<-Yz z&ZP;M%_8%|_T?ZRENB%oV~4|jEaZi*0_#iYsVHLtgUQ#Aui4)FL0u}_e^@+Wq|3%Of!M~FPW0JwP zIJAGZEkWdWb)7F1{R9>c7uD=Uy};Bs;Yr#))o_YAji7)j!4RyZ=UhHz)0K6w;yeGD_`;sZvi?@pm zwBiq}s*K&!87vTy#4~hSMbSG4Ad&GFa{suN+h!p#xVLdJ~_j<5)>vAV0sD$xTRq|QE?AM1n2dO;10X!ZM1>W8tL?-_bHt@Vt$eWooNt` z3u)^*n#NG3VwFlH6!P$%0A9J5!{G~|9AQ!^S`(knNDfG3C7^jXRPj$GAFwSx9PijV&tPIXVS_Kxt>O;Fcxk~>4@FRM*daw7jxnY8Xa#Le z19AP{rPwe7iRvC}*DE{~^GVQUtk9~V1T4uyeQ542lal{%pn^-ikrwh}s$x2d6srPZ z9snr!zPE*>(qp5C7A(2BP04~9K-4j+kfDeV-!`eeMIxqc9m*r$3SnyJF;hX(i^G21 zlR$I5smPt;5*LwE?g6#t*)pAmT$4|0t!PR`O9&hL83oyZ$UI;ImfN>iH9q5{*VZa= znG|C$1GB-y+qo=Qi**X=Od2P~hfSN0jPWW4G7>s4bme24hb}_uJJ%X8BVqzhA0{HD z0bU%2?D)!g;^1J^5?awupah<2B^uA0YH2-G5B#-2z2Nk$7lzXb9;c3Q?827Xiw}vEPX*3p} zlGdPkkN^(;X|b+I$7b(_6trjKzAdu;8a$T$M$cd5@#rQd^{}d5Br&(%UUCRMGKRFADLmkPzcZxMe&mL z2cGflpnfdx7($n+)u~Wq^Q;>!Z(|P;+>mVL;iao)Q7ZUwsDJ8x@Y|+WbdKa8dI_mgt5;K;d@xXzF zatJ9TQXeGr$ueF(_w6Lm*C&2wnMiDOMluw=1}V^{FP)s%iZUP)%qQ$9-)GzivHZyh zDR_r2uE3Qw#hIn<@oQd6`42D0VqM~4J* z&*Y@KeY+X(AA)Owt6hpe$*-LW?zSm`)BN%Qd$~w3*kmMB>~5Xbm5}KXer~q={UdPa zH@mt8nP%Lcu7UY+mK9%33yM<5Qh}03B7xLmknxpg?TgZtwAbXgl`n)K zn+JtQ>UH0po7(eZ>UCPpv!8V>Ib#o)eG!lp~UtaBPBT7}d&k;ir#r5;c-@v?K zk=zS28i0a0ont6(fhyk_|HHE=uA>KkS}+Mm7N5r~40AKHo+!HTKE~JY%eF|w8CT^Q zk`#SUQ~4ObnZd-I+R9N-5jRIrYQAUQ%OWB+rCT_lIX7=%m#}F;KNbDde1G0JDW1BS zRt$wO`^waHN>{MF-i&T;zX>?WIszuZpNwcG)ozF!agRatRpJ}3P?l3@YXZQ zYa57~)()jvty(hQ%>5X}>9|+#H!*qcmeLH#{Ll9|$)o7&{fM>JChPvZv}_*Jz=M=B z-F9Lrtu`!VGja^q88UT=U|+KE=6q;vK&1uM97n-)b0qb(`9Qi*sA#Cpycv&Vx<&&d zcPj3&2306vR0d}lhrMM$1L$qKjZf=Ko8I)Kj zo#$rWXbtN}f{kdw>|f34$iFIv?>2ZsWB4`}z~*5p`F}(rRRU15@Jx=6LR62ZJSk+^ zm?E>NJ+l^L`ot3x`FS=Ci4BBXbK9=dFX^GJ7{kGzUdx_n>BRS%_7~5Tgw%8I@EB|H z_mqf6qy30gS9lSlthRqL&$+^Nwa9$71q5x?MFqlKN=s>gw8y-E5b)alPXzw|8FJjh zaU-o)=;Gu>GmCA|5rI>*dVsHmDYmj-O8)9K<2#XN=vA;kyx_{wq*5TieVrilui0_= z^4SS|>1n^zh3OAT0^WVxTSpEgXfB{m<-3Y@^Ir$=nX3LG;Cy_i5E1A87XJw`tjx#5 zD93x8bR4-77yX7sN!3M;c#^z`(P z`@bi?W-67hdgP@n^xz$JhzB;If5o7uOg49j1I6zAi{N$ju)&%(Q{;TEFt5m4VVR=m z6sF<*9!;EWd{=oYQ`PAqqk`BiGGTC@37PWKTHB+?l~;y+SbSMeT_I`bO$)&!_Abl~zf689~^?mIQS=nka)x%zmqzff*}tnh*ulFE0Mx^*4T+Ok*O5<#Iz4EYOk!E7egbunhUd;4>rHo-UA~P7>$ba~_HooH zoNs2P%_`K#6B((?dvZTA7p7k+No1Whb{E`(~WGySz~2j!=9}r*aG;fxn?Z}-=R1>kw&Nt6(LqI zf~I&dFFvoWVUN~bJ5zoND>8^E-&9$!*cH`<=K(|pAvW9kjNMYYQE`_q)4(xlj#~$R zjDvhyMUaEY>zXrq!v+4Yjol7jga!R+^5n|(10eFD3Eg$^gzf{A7`ZSSs^~QXqaSnE z8y`HT@*9851o1^doFP|=(Y%+R;NhvU;cnpP)S)MvcS^Kv9g52gUnuZAr>L{1aQM{d zSF(b5v0=908_RF5$+20-8NN#*S*)%TAIup9?S3kOZNwJ$F2d1X>>|rurXe&yuEVCZ zd5gCXrizdTQraP71LE$KXhk&W5`66ha{QuQzv!u+`$MHQ7D|UU6T7Oko?#~?up_9ZPBm!val{b2y zZsg-18#6HAnXS|73A}qCMRz>DyG6o}-~4tK|K$!ki2oQRjs#(cB1rh-J6ONt{otcN zzEWV>La_5CN%Lrqb;o=Z{nA-%s*wGYHT%z+30`bXG~Z*yDJLs{ee_6s$PxyNN+m9J zpUEhNBC_tv$E%A>Nd%0mbP;dx4bN*u`0ymf6pQRJ3b#pQF?k0pZaq7&@Hx}vf;Digyq1baA}mddAJ#t_9pldkzwy1ioR zXsst3UVf#X$(%NWLutY40&~7%bo-^=s*rrkM2bt|P)Y?LdRRzb*7RAu-yLS&#g2m! z|3SpNd1xXzdTCDJ;z&iy%%n5N2&SP& zlA2!B8{PAZF)0;lOB0ZzW9G`c;%ZJ|EX7CZ96?Qc!+|@;1nS}Vx$&#Y9bmUo;7{FC z0>%GH3ikW(wfJt~svP^t=Zfs`n=_w_vR_|372o0f^7Qrp-M9X0oqLV_d894(E}I;I z0pUD^2R)_r_BhM@h;Q7Adbwnzq^?Cto{6N`nLWs+FnK>GRvc<=T87>eWuBRCh`Nq@ z6B764_0#)*%bbJPk62kdSDIb76t>@bPSevb9!A+OZ{+^RH2?c)F8y`ci%3hf<|7T;o8BFoayL%M696ds zM=NK2@87c!_*Z{>g8#qwp2fkB7=Pb4zTI17x%GhM7J=Ule2dP1HTstb{(q$f+YbhI z^2OK8E@n%I;=7;D-AFL0yU-_5B{-rSgvX}pi?jm4O2b`fvL67nUi?shJ6a>vgxN#BLjyClL4Ql$PgZEPVXt)u{^hh3Qin9I+3pRiZ zj&i&dPUe!d(tENJSG729rf6L--){}!w&hz_6p(t_>&~!2*obR>>k1Hw;^SThbJLp# zZ#K9MZWL5W6m}$8rHLx!Q;rIkNvX(`^jms9y(`CuK<|aoA-8t@JB)Fu3<-yIrEyH5}CHu zS+7tw5wdwcN6`cCD&u0iMk$||nfvJ*cuJ;g-vt!IS~|=e8&0cs7{n%sI3%YMC${RW zWtj~=B2f(w=aJUe14Ox9J6tYhYhkOf0N$yMR>n6<6Z z0o_ zJEceM-2OAo-^tXV$UfU8DbvhZd^d*!j69D&_W)pWqn(wx@9J_K=tsBT%G~<-H9y0w zeIE6Tz${-}d~HhhY|C!`8XPH(vFI^P94Ka@`$e#jEb3NNfK41kShg{(v)iQuY0ZDW z_5c(>Ez*anc9uR33F1p|K8OT=SDH|gm$%;tT@ra*x2a#(az=PfD<_YNcyY3)H|<&7 z055BT0rx4CFN)>lK3^r4UrR4`U1cWdb1rE-o`HO)>W9#j=`7v6K~#d)v zUO_(p1cRcgzJB>!Yrn@`=Jn0RWasOTTKgMr`of38l5 zmJ(CBe6dk~^(DVMI1{dR_cXyIj=A7BlVff}^atPjR$!}I+CgCg(oXm=q30>UHEGcOX!MQh0!%ej2S%`%r6hal_j-`}1(=~sx$k&d`y zA-oQnDl(vmACj6`6$gBOH|51nTab~if!KFk)qy~4XIf%+XCPbKfyOK^%14cAvQO#L z;*X1fb)^OxE`>-U9l5x>Vg%8V@{lK|F*`?>?H`cuvs+v$-#@g|QoVE>{Y8+Yv-j@& zb7F^jl`YJr{9A2<}bp6(I_G-d<}NiVR1er-B(ORad8foe z7xFc_?S*qoloDLgUJcS9%7wXK2gXxf(9j}xgZh)CMo>UuASZy{C_d|XS;7Hl z{7mN@Ix+lR{q-XQKpmzH5K+x1T1;4&L%SE2=BVnW6AZxfmvyq9$B4pHRmW$B%DF03 zpD)E-MAQ9gOZ#kEdlR%{+ZLYfc9i#&$M9KkQz8}M( zY#|Vy_hmsn2Kh~$RwlIDU8o*|D_z|^;EV=1cZ}p279gpRINT!sh z+GSJ)Qn=FRBB16Zn#^YFsD=Ghx{@zaCS= z`0~=V!ewbR%6p4#c7C7$>!)?9K*Ke&EPN2N*&3}nP#7!=RkrwI5gJ&#WLsvwq!($a z5JkE@-QbIIU~PMI7$R_Y3N&_jJGdwQq>#z#!E%l432I@ z5T^1kOCMy04=y^87}&|+AzeN^kQi7L`9?HgvmMvHMkAr9slf9vs;H0z9^R_xALaN-DbP7$aqHPI{j z4sJ`s<9_khVc3uZQ|~)GYyp48?!Q?T%W1yIV3*G>V^y;w@$TR`k9Rjz8`!H4WDcLP z)D;|bXN`OERl81ID&0oVQpb70{9{3*({NWcK$%@c`Bj#FaKC z>Vw1Ui)69S-rbbx0B+94p_en6x^`KLZrI*f>2C{vJ z#i+OSySVE}Ka3O@OS?%kfnR(w#iETW`t<5M+Z7mDW+wpn^JHkLR^x%oNafSg35N!{UWF)v9SfUi+$r(Z4iB!cs&{$mTdr0`Ab{+->COP zVNmG(C}e8<*EtK-SFkh@&k_$Yb2W&*L#dCNyXb&*se;RvDkpctlV4@wYXs&fTINuY#$2NK?WT#luGw)qS13n43|EFumZV zX14(!>5xV9^XoWPNnX=XLeNdX^p zCUhy+*9|)=D5Y|R&rrVa6%2;Pkr zW^5yOFftEnmV`;BHbi@|E^?h0yfw+;SCfqC4^8?-V4J(7 zXxRO{Nz3gp&|v_rnHEOfcHBR}&_atyh-0u6H)XG`4?z{heGxzXJ$T`yQXjt(w^Hp) zoI5GmNp$lESbK*-$2Q=V+MS#GE_NQ*W@uyG!@@c9Z+c(W8w|5=);dwve!d*8;mC!? z7f>GGJ@VwP5gIoAZ{6RpE2g@Kgd#51HW--toWf{Y%t&iPU5pv2gbHmF3^5Dpy~tIz z>{IUIO2%`2oZ2Ooi;vZ=hnxLxD?L>2htL;uvGEmH%d6RGcXR;*xlQMKYFtxq7nuvABtexr zeP?5(&WqD+{()TAX|SMakPb}1wV8x>2gRPuIkx+zYXw8)wg80lcNHx$sVwmubUW%X zy4oHK!CQx=d`sw^O84wv1lRx^w@Epo)NL*Su5E%|c#t<#hqiH>zZN4J|C#Ft?+ANW z>f_v%I_>e-^CS5kl;i1*q7?>iQk0-g{2fG2JX+t@#3xdu1pvf;H)7H&kqwy$fqHmz z^oYGX>*Gg|huVMwxCQqnk$mL(e5$q3IjR5K%JY%P?~6Kd2MXY(^uy&i`^DTc z1D>OxKS4)$F*613LoQ1*d2;m4(=eIx2)*v|V5hQ#0E^pdFpZQ8{RsH$%aWzgPtd;< zesw`U5t@jdrw}|%c;<-Zk(Au|x)^wQUy4{pqBoVxzVitrg(Go(ih01Q);5x5y37Cj zq(>v3EVsvT;Hhr^NwQvGo4cbuGuwQf7w^oP+2KyalS_xzi;}H zKfCmBm8+Vbu=+(n{mrq`(K{ljd%NQM*1S+m^(!Uef(k4KqUO=YEJUpzQLAY!v}SgC zf!6b=&-RgalJJyASc3D8n6%XFIjUPZM+>Ly)$FM!L5oO-s=grLi%s)avAWeQ+5?s= z?m8p%FnqpqVx+{fvp9>_NuZr4&Ft;bk5AhuGiua+RIPEHp`=zgu6kSa@L*pNjwN-X z_L_6(WVE%-uxqB!*cZ=tLs zGBBIS!>H@s(qk{l!Jq}x-mydZEyuCIjkzU-)4xLdYoLuekEOey|PV_bruZl@ZJ#(yN* zXoB1S+WRfHe@Wv1p-y=HWd8j6qXwJAnJm`g-tQgts~`gKP$z;gj&Y)xJk$Mqu_Hxl zOq$ir1XWRHscZ(p(tz?Bd@u2L`Z20t{U_Ake z4)@qvYlD9D1hf7pDAd8);>L^Z5Q$B9x@)fQE%CK(l#d@gKAsBA3@OrD7B7J3v~T|j zUtkx$PiGRQ;cHBkND}71xxgmaq*Ky~RYa6vlGds+clGDOt=w(7yrY8$zI*}&iJf)pDOYP51j#pl?X!S)x>eC;O%IZEeH*yT9BV_;fEzEv|SRS*M6X{LzP2 zs*0GR484DD9l@wul;7>Fe4)p?)&<#`=Bf! z^}g=URpX92nmtittVN`~8$;+JE}>bA@2!0J`CRwjpb>p_vrJ=IYhNP{mCRZ*3B#p} zERY*f>abKJ&3xEOc6IDTVWCqBkyF+QOoP4ioZ}7em1v2(EL%4eUqjc5Svj>zI`eb# z5rFzmBYm;A`U^X<-QwiA1`voe>Ohd?fMZ5Sbm=Wk|3GX#qZVO3g29ufHPqU`F?4{0 zmFu|^8;Jb+^{v};E?yZ{ z-{jTw|UXQ06T5ZcL z3gGYH3)7Ri!t{@JA%OT#1P_)B`c^j6{qx0+DC?(m;0RrI*4wWHNEm9FDepQ-p=k-o zDExc54(Fo>4PqAz9f9UhXtz9%CryqC$D)SMvOOE_A4WhE|I`{vvWxPX`*5Q9FCj(qc2kRGy+TMBx-49 zK%C0(gF3}Y*7vKHqBY0sM^1YTFOV-DOVo9R4?Qp~vwcpH-EF7dB?9>~;h5WnV*AOm`&nAjIDJam?}lnvt!>!O z_Sjr>EXiZE0y8`WTFT7{f5V_z=+Ydd9UMO%rt?Nj>o9k~adu9oB8Rh%bCX5*0npv7 zz-&i}Z_+hWJ&L{yWR0wWL_E78-dIH;$}0&jZYwX+GVga=cB#>f_=BdZ=^hoK*?C<4 z7A_nnl{uuK2$nZK-)sL+bBr_u>%(|JsQAH~CU(QN2l7gt?)TA@S9XdVS&*fqr10p_ z9`!en60Ste!d|qc4!cW@b~xmWe^?=2awVq?s2=6klSI+AB z9SvsF^{nL((-3+2O4Q3e5zFJZ;|}44ud=GRz!}75eV59>(xoVUA5P`?1tZ%@%tUSz zJ=vn>yv0i^L47k^{RDIXuaJsD1Wr}nE%B3h zH5AQ3% zh3MSsdJF|%=nH^A=3a!U&Vw$fW-&tLu1)I*nv%Q-(=V9#h>32mDz_#+n1Ukty$ZoA zGRpQ=`p}tLgQ9p6u$Qoy3alr3SO-!x!dfuo3fEzyeBG9hqsuEj+cM!*u9B>E&>6y?O$yhzp+mTIq)lPT9IPQ5wxO#J5)9)K-0R#~G<>nCJkq^G?%XXTZ`l5tTl%4ODOf4t6TJ3#no22MU+=jH$ow64 zj;ChqZiB5PfkpcT3hA^foOqb|zMjdP3UjLpVPzoDvKe_2-p+1IK;a=H2PxrA)+_|0 zbI+RRx!6{A6qOlWMWsNh4rL*%HS8Mit(_`w45s5wppIIG5N=0`3q|F|-fz4(GNTcv zH&g`~?Xj~Ek&T&+lk(2B^+kRL_W?Jmh z0^qz($U=0|TD=_ro#eUT8-CM>*;h^ zk$4@|IZZ3EUeVOTOyrsT62lGXI%Wbc&jO4p4;iPJ0cHyunhX9jJ<}85+67Nh+M%cso(I%dnlL9JLSRY-{-Mg|?(5GV;?<7vI(kE3+fV7T zR`tNN#6Y)mYAp#4l(LK5Ebh)}?S-BbsC33+aCM<{YZYU~Ux9YQTcCwBrHW`E7U~o$6(Bb-q;?V=StnBDrcg7YqrJBfW%nBn$YUXZHXwzqZ_(#-jdYN=>U zkT5Gr4jW(vK|vG69r(w){X?Bg&S9Mi5~ODn<>@EZl?!Ig3lDkdICs*(^t*&W#ol_F zi2#P~<3VPA)k6GR$YjQW0P`^ZFw)w>?N6c{*jkEwY-QC)r^6q;FD*Vya!_wM0)ya* zDe1gezfepPCk!vudR-3O%heCp#d1$MHF_l$qJs5R>yl@JG*J{{8GZfQE8AUnhBAi1 z8v~r5bPzx_dZQk3NbP6>cI$YSaHsSRJ-0+zq2y=lMY105M2j*P)gr~NKPN0EKXEc~ z6QkV{%gr}IwUyy({=yw0k+ZMZ7QSScN?+NGb4WXjSljAbgTB$<>juOJK`1C5R)viV z7=`QB+fYqXAnYVIBa|bI6IIL=>_i(o!yEjR0xY33H@c~(yL*I7w=qWyhH&ci$I)lm zxhCfJs#A20agavOY)SR}WCs0ITrIRIeyk^jpEeFSQ9?~fTKt2Od~lMl%WYhkZ}x1T zqPC7KjI*tSamU_7;*w&P?9-;F&jI_}XV{F3+R#NLY#6O8wEXqarf*}{u6C_rG6k>Twik_cT3tZ;=^VpsO zIMQ70;N$genbH3Td+!|=)$=S0q9_UoNKS$<%m71_oKZ3}BpC*fEMb5lXC$lS3`5Qm z1{i|mC_!>Y7;+Fvl0mYHpgVr={oURDV?X=uzJ0r&-FKT$bEf;$sZ(9ueY&f=tLk%g zQLb0ZyZ|46k$Hn6S4FThnwwjXd%4evJ>4a_tVF*Fd>SNb1}Ow)Tq`N4Q+af1cX=!f zi=bg{JXpU=x|`kpNP?WVYaXHxv5THXD6Aq>aP08O+i~8VuTEYq4t!7n12M*{V=3X5 zll3lm(=xC+d0WJX)c+{+*bg=?F_`K^QTth7bQtIH#ss@OkkLbDj&fCv`?c%1!PZom z91iWChAMc_DKP_WjDR${nfFJpkI17PhpsV8y#;C3kF2ULIVHU_M`NCbqZN<9f7X(aw7zv^SMp1YTJ#tR zo}L;3#~T#1M(fr`uS(s=jAggs_%Yg28|VKiX>D zFAb|-oqsO{7C*N$9qQD#Z0_mz@bSQ}sNS2wDZ7p)HYJod6fZy8tRDbV4E1rdTE|)G z|A?BQd{`Iu#KgjI2|C1&zK=U3V?1KrrQ7G?+LI2`g{luzJ~5V0MzQmJaISewE;Q_I z#&7faN0Nqwl9}G(r3@vY>28$7^z64^IdwL?AMOfbilx~!JQ4xw!BVC>R?}v3FS?_R zz8u^TYF5mmm6WD!{GyqoUB-B-%PU*xN%xa|lGhtgozG<_;n0OA8PDUg+M*I0R4=X7~7nIC3zIjQFk+u*tX@Tp%d&bb4Zdb$YuS~j= zB@3%LR1>ib7mQ?>C=M&(3OK4sSvG(tt z4__wGr9=SNk>{Kk*hH!YMnVgm;iqb1*gH{^dl$o(Na9M>wcvmOrjRGnFZN1|$85lB zQpkljE7q|u66(BuN0!zxT_%)=U$CRbK=w!NM?YE0%tK7KKHmtNc3OPPcd-4c8~_dG zlmE&^95Mxabdketx+QggHB+cqDY^(519NiCmrAtp%UxfwY@D{60Jli`H(G8>V`jPL za0IHHv2xIlOC|kccP1+48<^(dEGn+}6;jBJGE{cIBIau$RTeYQ=4IDs z)*iP16MZcPhB>?Ku_s5JV`;FZPG|$s`E$f>3oS0(b$U;v<#2#4UoHtjjPYhcD zKLOn74_2kR+jSm^;XOBp*JGkUBXZ4+z*KndbZ+;GJlJd<`uR&sVN+MmwQT9myn?Fm z1H<*K!a-Lx-d$IEvV>nT0yo5j;QE;_F3D^2kwrF7_sz%39R}VMi(b7$rJTb?myC#m zZd3QfN7)-{_ukJ}e~nE_JseXGWQ?8%@UL?=fA#pbi!;h9oFC1IoxPB{Y6&Cfb0oFZc9XTG4ca45EEMw6wo9!sPP^eE$5RE$( zRxZAT*=>b0d`OFBYE12>@}nwjzx4Aa7T<6QVajU1A*x8;Jk!=+E3fhCG1Tv&iz=Ow z%{)M>y8VPWFsP*`^j$s6Hy49_HW|R84Hp|@{rVy^t>}&@V|wBiN8C^gy&gNolQ5Z-zC)P`nQBw-S9-<#Wk)0g zUM&kgwGv+6%Khr$0bSunYui0%`SfZMV4v9tQ}Q2v?5f9wUh{PwE0-)1_zmBZRY*p@ zHTD)x3Z_#S)EUg$Wr;`na?u=u*0>s3?1auC4@7@K0Cit8IGSGfeOZ&Y_p3W?j~?Ru zME1*h&(XY{+dNxII)BO}xg_3|HyGkhqplSRp0~TbrOPBNoM!>ud-{eHDc@gde$@*l z1r(yVxV2e|g@-^58Akwtd&Ro5?7O6)H1VtvM;SaQH|Sycy6L3P)@uIE+^0dbjMa8Z zYPej_qCxk}-W!Er*3(zt?G1&=|KRD+Zf0;s3?3;<|G^Vek$hGmgI_XjI~dn9^lDtl zfU1D)vm4W5diQ!4GEFzbmYY7>;3aOw=~Wv^K9gxhPrgo0mbS}84`j3u(6Y1&RC)?| z;pD}J29;TkHGn>3l6=zpZS|ydv+&iP{hh2sa(Irwnq(P_E>oCas}2z2YbOt zh|MtdO^*|1z3N?Tym9mDx5;%$11Tv7hP#=FZV~#!-gp2+a&12LZ{tE?X(Wr*$|%Q2 zd^W+e@$ljVyG2B`J69YY7G#$(nNvEE#5BU}^7nZD>0JOpBj=Hp_38}eu zhZtV^TqFknb_&VaoXz6F(Z;wOqc_yU(#13MDZor!lr1++7fu%0<+ev0 zI#)%6U!l%|bb@!LG=w9@I&>G#a)n^EpOf@P4wxFU_0@yOQp}0H^BLTYCwwZ8AI-_t z&+`E+9!D~%fw(QQ*aXkRtvE+1B?}O>_RGV1o9t%0%8SkAez=O()1QQV`QqBW<9=+- zhV@Gkr$&Zr&!9*p7lyOQzu{a3T#ZVS@a}~|dYptno~2QjkKWc%M=T-$aU+i8_3_$3 z(@FQKD2T6EIq*Bf{f>gfG~Ah4Euxi~b_aVpi$!BZCz+6*SB6UnM+R>4pV6v_6t1^6 zdX?V#v9c>iRRb#3TN=fUx(*jDUbBPqQdca+rBu3-Oc@TwD*EtO_XQDvoc`d|ogF4^ zg=VP%U@2R?vZHpcu`SEv#FQaTkohLfDKC;x@D_6tw-i*k6x)?yw$9W1lxgC`L3gN7 zwuxSjJ~KI{Fig9~(zbiIi2J@)5-Ws#7-pG>HXWV&U07~AMc4`bs5$io${29H?Z!<{ z5w|Hn??^ae1ahX)(`ukQar#a8m@Ct&8$KL8VKs&CgUybQ{2w529+P`ojs*scZX|pt8pM@j1u7pCYL|V|V|E2g z28UWtrhm_?_RM}9v-6`>a;2c7gyL;$BxD$IbB})_m#Jh(!^uCaq3ThSc8Z^leO`57 zz2TCJM|n(^{RHApG)p6SklY;4*7SE}+_+&P!j%-a8=#iTiXEqWrwNA!Vb*Crj#^(bv#>~BjG?1GumEcAtbM&V-LOf zae>tS5C_2bfpt40zaK zi^8|Jd4Wx&kv`Eyz>ul=vcutYEf;OqCOD#Ax9;&APv+z2NEQK8-l8?z-W!86c`a8K z+}L?9Ot>VhMnvNY*l7qJN}fR(lc|DFdA%&FF!?%-$vO5hd1%u}{dC zmrJeq=aE|MrqCAW{Q|}E-K#Qp3N)pFp`lJdn77_>-}A!mDeFf&v1ptLG!anku*!$m z?R?l0`fu@*w2PE|5-RY5>r+Y1Cj-;cfOYK`uIHtPjz-Gu8%Bh?LZlWM;WR0%8?R!b zxhpgIN8#tu5nS#kYOkD0*ct4=NHXw(25Kt#COD5z6j;1#_CUxiOVcpH=_tGnr?8Q(l$6~f&D5g{K)(53`x-wyKKcu14Ii#=8~qMM)K7k zyjGmkavR3t{IVz;gTDFJq>wd_vYufD|A*QAK@&O|Q^iDHYU)%i5Z4(B81&`v7Pq8D zYFVIgf#%K;oWU^|q-a|QRtdNyw?-rJDRe0Bkqi|TP+|h?6S{zZokJQDuZslo{k~tR zSNK4!HLrZxYq*iO2wNJen|_)^HG-2bwbMT8?=Tp3&n)7`TY#LjUqdCseVl3hxPW4( z#vrD(A8?!bsO@6NT=8LEZ}`xa1okfCIn+}*X4%VBp&us`qsi%+-pi>qAv;q#6o<^A zV&gc&m|cq}q%0+CR~FmTxkF5Zqt-_1BZJ|$vA>h5w>Z&?p%5?V7YPk|8!N0H+d9X2 z$naeBaSmV6Zgzl|F7+k%MsL8>vak9BDXn;>=E|p717Q?Qv5@;45mG|lS%sTl#S*I3 z@W$%Ud(R6>`$OIAYss&NUl^$PkJCFxv@TgYc%Nou*FT+##~I1edH(;XM(}N^KX|0y zJ|eetntVqVRw%%{%PM zSQPN3!s@=RdN)m|GZV;j#c1u?ecnI!szDkyjORrXrQf*(O9eC zzDG8kdo3bvpT66+W!W*c%7d>C<(gcxm@(_k&cYoZwM^c)p`UX#`i2(ouu>(>85e{p z=iz)L6DwaF@bhv7(Wz%Wi0WfP0<mYg{MulJ?hV$n!KRF@=I)mmgFPfhmR+PezZSRmx-yZu!F@!E%8t;R|~J}m(##*>Xay8-O{ zBut}_-+NJD?pU5{z9Y#*!p`yegVC&}N>}$=R*SCoULlR2zqK1pob~gAn}gLr&?5Mw z{2_JY0fBOB!L|B8djVHjf~ra5q&W7ON!F!Dx+sVC@H%tSv{+#?)jnO}Pl*6y2rxTi zgP(Qjio`*r04hU)+d{~Yb+62|qAJnohWs?vi(N0s)td|WgQs>%?XbBxCSq0Jv}cBi zFHn|t(U|CT%S~RPbo7yT#VjLyx%}+g(4@Wi(U<3<_uxShs z`okXyvF~=?7kt*h(3Ma^sstxdi`MecLG2*&7ZIMX$+fP6z{n;Mn@zau7GZSM%l!N9 z1!Gnfy~!!llP9dOLfbi-kLe@vmRHdSqKIGAAW=bn>$TaBtn=QH6o)FrTy#|gsVtaD zb_rgMvdp8#*$(%H@cqZDo9l~`EL@NQU?umcQow+#Bc1`US?VekhAioNQ91V{hGCpp zL(q<5tudyuxnMEWaE|p;!A=Raf{tVNzy%FJ6p1{mj z$Dy2PwYD(bg!8+j7P2OeyigA{VPGhiA>Z*-H{o-j24a^;S!$b(=cS(Ct?NwVC5Qxl zIMM;Xpl=PlZ9@Xk&T?$jNNQZF)?CXJ&<6KW^JNvO`1i}dxYM|d<|v<=h~`Nn?hH_^ z&{5?&B-NGB%u>8^+XgIis}z=!nJZ~qmlm;a7Bv@Kz>Q)|Uu$D?}ClanUSp zE@&^AZyWq!uq@WZ?C~xZLN0%NHa#l?w z-E+a`hP5c^#;xw!9~$^Xu$CLY*y@}ZyeC}uT={_z9smzWYsHLPgI zX;lAurKJ$n-gso0UG{19I5kf&cMAy_fl)NR9R6xPP|g6V_zO8GVW>S`l%%^;2XUF;aJc5(ac!2Qb1AQHZP#l(|9PANFnKYy$;Oj{phGxY#xstckj<3RUuoHbNU zV4Z`^`sHmsHKM7@z7>$n&Kn+SRQFevIi?1N97N}ceVk9^&fzKv1+?T3-TK&@(_X(%>%tn+`jeHi-v#RQjHcRu&q`Dr(yss1YA(bwL3k>@l?`VZg{@7v z=+VW7VnC!4sA;?LCSFTeyifG~`_bLmdZ(v{QgxY@CbX#>ef4`&DWHalS$j2{Y2oG2 zpYy=4tS;{J$&(FP>w3+fZ|PFyAAh$$Vr)BU_qgQx!A4j@yw;0NV)+6PVRq+s7N~mr z#L%T}uReKLY~1f^gN++;N{dI^yPVxr!-qwF^S;18-4kjoI%;_l_!3}gC%?UQt`4Mz5f2_p1>e|)1#jex>6YCK*qO{Lw+#FkE44d+KoBY0c2ih=| z?z}C??2Sx*pv{FE4JR2eK!6Zm0*>VEZ|(H8aYt;;4Eq+zfa~)Wk&XL@S8)lqS?BfQ z)AA_~SALBnqN-^)%i+t3n*C?Hqnx8dsaR!2W6^|_j|{S=jOm+Kl^Vkh8puJ6W>KVa zp1A|<@%UU!B(_4G1bZK5%3rpC05c~!8BD0{&yC0BVYhpuHJ zJtJvRMEoan(u7;21H+&tJ%l{z19f9>DGCoX7-pa#S?<77>=#%_?Tim7i3K;DrP_*H z70ejTHn-v>FCr@!07g#VS1R0jybJG@U(}Xsm-B0HZ>m|Jf!VYZ{X`Qc(L15D0(bdp zbl%IzI)JwS?Q3+vGnzF{5rNCfPp^t;T z4XwO#u<4yhpE?#Xn+BS`z2s3hg`1ND|l;C=$-bxJjOJeIX}Tm^frk z({?i4p0>u+fj|_dB1Q4BF));?wxQJ4#n%s)L#4CaXis~i>#QH)L``v}hvAcaPqq1+vHODo*S^eD$K`38dRTU)yqj-HUSnt( zPB^A+{j?XEJ+y8-(8pPuQ8YM^d7Mo&E?lAaZs`3e&PF3C1AHVryRy0C_NV;a3p%>t z_HfXcug5D+O%+q!Y43I6kDup$x$^UL!npq6X|(T333k141;Gkq$`ZC9Vr=zSsE`aN z0F&%jKjZh(;8R2Xr7?!OrZP=h-LgL}*j_+*gN_Sq51UfJ|1e z_Tf}`s`E_L=cuH!Azy%>8rj@@H%d2@#KfjfKP~Wt_w6H0i=4S`+vg{Pb=F_}NL`CZ zIY6!IWe3u7I#K(|%IftWSdJ{t3RPBuh^jH9xCOk3SbM3A1L}fb)QmGm-||J=TpBZO z8hFDBc(UK@376X`lko*8xdo2S>* z!b|t$iCE6JAe$15Bj%;%f>q|33`csUU&`xbmF7X5mGgCmmwnJfDjw;kV#SbOk~1<7 z2Xolimh}axnmyOM)58*HbfME{nLh>Bxrlf$+@@a<%#&2V9G$e}IGf9z8$QAQvgR=% zM5f<(;2!qE@cpY!vVr1JxCIJZSCnd%v9tlC+4KKIY zGy6CE-yiNpji?Ps*Z49gJQgZh;j>KNHKNui?h3w5l5l>$WZ;J&KX;_;SnDlqkG5BC zKzM3U=7xS>3S4`5C>B83aIM-}yFP>Sc*AZ%l)^@__G$vis6LWX?gP4p)EqF8q@c1O znNeHDDi3jbZTNvq3WVoMi5-#5QK^AT%qO>EIcJPn37FX|A8G|`&juSKntcmKy#)DL zg)2FgT$A)qT6`nh#67z|w`)QEDX9<#j>Olyd@Xuz7^QFu%fv|;Rb&q|CKiZjYwMGh zqAua4Ueq%CG~FEpFrH<02T=7bIEVhhJMl?KIX~Vm5t{jqW1{()V8Hs8geNthp75)B zjXZ%ugdL=9xYO23>Euyh3vY}Fy{@FE9|a^~pa^H6Q?kL|p^z5UqdVoV7l=UO4%`uG z&m74hT>lMCAa~_hkWxY!PiwJNbLzAmWXXppKnj0GK$OPB@jwd}D*zE;Yuu zNz#y4)vo2_rj=jZDob@J-ti4@b5tHX5)CvQnDL~`p+P}5^>`b+?v3t#k4~SesD>e{ z>YbV=!J^||D$H(eEh`Z{AQb%UOuioMgU*bkpF({-xM+H?d~k3stlc`IGqtg0^{a2x zorG>3(-1)4qT^?Oi1yJ?=@_tRerH|=-mtsw2_o0GP!)4dOi8V1i+1dZFBqEd|W(`KllnY(Z$m}Ni#H&z^%3j2zW z_kn~WHz|WXRDAcdvfiWL84;fgcTVFW1+^in2}5Y7mg@F4K1-Q1r6ufYy~Kd4jr{<;Jf!_%O*$ zw;(`z^2J|pBgK)MmU81VO|0AS_&{mI;CH5vqtQNzq)hqh@Lw~nmDK!@6bfdTb2a7biXj$W+=1prH^Wk%>Z6GLp=EUNsD zq$25=H`s{N$UoNeM|{!b&yuqe_D@09>Rh zM?w3VZS(z%d|UKAioRSfWl5rkFFPiW|0&F~8BOGF@7kjhUw(zLvay|&Uk9w`l`?yA zeDTmk?NYh8G@cYWZHjoC#w`V@rsG50iO#P#xNYbb_TTWlmd`_qelaltLVy)3`RKxH z`h~42&T>z#x5hlZ8PN8Q!pvO`Dkh^xBRyxJ>6g7>AvcE)`rUA9u*eQwfR71H^8b1LQbind*a@W?P{Q`K2%*`#L;F^?gpRb&Y2e&t^0&TIaWK~ ztW;B?mQf+5V=a?1efV-ql0C&0zK9TfAP$81`nv7&I}`&96w)CKm>~`E4uJjKEn=;5mH=rW= zgj0ZZYk@o8^8!?18{nQ98q0?0K?stsT@OACv_&nyECDxW3zrV}7AzvRNRW=k+5VaO zg0a(1znY|e|NZC%v>1NpCgW^it}pxQ8$Wk;@i2D=J!ZZw$mH}o&F)Ipv!!lJ)S+VP zJ;JPB5bz_y`{Py<@cP?tZAbQZ-+xEmFi58UgQoe^(+ln|Mn9Y**&Yd0jrRm$xHT(P zwh?p(;&Cma%2BM-SuTso>qgob4##5o2GHA>vSVJl7R@K$n4bO}!nhdV%6d&8DoIc@f;s+qP?2~StK?EfX5%-h zs6$9MW$Yp7YCb0ysuMgTW?8rj4T*|lwpO1LYOUN8u)xhlyqTSg)>~tp@@U?u>MJ6l z0N1a~x{1s^4ezB=NqhEs>KoU&{4@HKmke0-wc|1)C7^1c=I!D`x&i&RTs#I(FCq?L$}Q*&lzRziWMSWliC^he znWK&JC%D;po^2{bg!#I}qB$i;0)8|vJdIjE@O(6c8@2ibb+iE=Sie#jIiEIn1$Q3F7uBX;P7sQP-(&jO-Zr2#R*ESshT^3@1>pWXPdH@>ckRO1fWHwZHNBXdd0Au zHHMnuL&WO&h13tc_$p0FNAORGrlq|4VCTDjx98DG%l33FQf&Uys1+--=>Qz(EnlxK z-qnIs3|4AXeJbY6HbPo6hCyo82jh2m7&yw|=5u?md>um7tl2`AoOzY)wGF=u6umro znF?zd9$Jv#!Fov^U$H$MZR^kb}?ck|yWjcq#Tg)SySu=BcEx z^7DGhtC(r)!l%_cYU@%wAH>cK0Nj@#30}&kR2A2MMv}*>gWu`t))`<$JzPT)>@5*& zU~fT15e~4sHVFywI!9JNs`SA~mLR3WK4hVc&29Twh+g~mdqXL)11>MhR1DMkv{KvP z>zH`g#5lqt%=pYn5`0LPD~8}<8%CT9AoOE-(8K>$u%G0l%$x|r8*zgOG}mS41v%te z73YE^P_w(l;suQ}A7UEs&TDI>wgXvf$dR`DBX`x5;ZPeoHlm&YmrR~AqrSx$DOr}JXs*CIpO2II6-LV$5P#3S?4 z`l;>CCT@sOxlzfjS+tfazUX`V^NDkpg1y@o6d>3zyfS%_?#Xkn$oB!kzK)&19vQ*_ zVvuY0x}ASdIdi>zQQvCrU|7Q`#z=+;N8w<2w>EAZ{au)aw9D=-)fh^_X%9lkso#}G z{4Q2NP1^7Eh>yoIq`@mRojl$myGuDMP&K(D^vBfb8_23pP+xCKVU)yI_vtVzqtWng z+($l5pu4^YR$lV>dH$63d&$Qy&v1f)(P6+_#)mpwnNNGEzydhYpx8fI_#e?g^)e>} zYeq@>m3^)Z03E5zebG*)l9A{vMV9fm#}3wi(8~c-sk~E0Z7P=mE4~Sq^NOx=(*3#z ze^NM|(%0vi)^N%okJ`xMDa6f+TpzYAo_NXYY4@!~Pn;hP&vkSiCnqfzY>9Uy*Wl0l zrYROAM=Fo*Hy)&Zy2Nlh^L`kRPSdp~Dw9#pFsK?$a6-4kXG-)D%%6v!#AdfKHVkzy z#x~ep%Dk{~+{i_ib;`a8)#pm$c>a_3ZhG73GbA@1oKmGwKFn$)MJb8cBd-6gVEf4E zbK(5Lw9;lsS<*ZTBjU3J%kc4*yON_?o;ig=-1#9Tp%q6}mXkl+6l!;Bm;(%OT@4l= zIS;w-&sInJ@i#Q6hVYGV6xK$DW|{IO-d&Ra+_J@g7c~B#1%#88yN4UX+>r?P%h|$? zNQ~tP%ipWCGz-5x(!>2Z!cD>1(Z$&b;pD+0&cd(Y?BMLC<6>@!VBuFpcp)tjFctZK z&xX61JGomsyE)=;@GB!7JP>X;AO*N0!qV9a2d|1i+Sq!qh>8la@auS5c=)*BG9ixU zHnwiD=!uA!5R0rV(Z5stXa3JB-b1J| zL>ceaE!_Gb?ho(J5}pDc!JWGVckd7o+$FeokKjJhLn0zVLLw?svIh@osp#lvsc2{z zm_Uyi7}*}t(6I2Zu(5N1xxn;~d7todJ^^upIsYQLb?@FiqWeUYL`0OF3^WX!|LO4O zBOdwv+i3*P@NWU|Zj;}_C%^Tl7mo=?`*-f%zJpJQhqIN9D-JmYC9A+aDrz}xSRxHAKnJdC?utsD6ciHCb9<9i!=~@< zkzY_)D=aGSc^_!;wo6O_6kLZ@v`kq$W)JC}vO?73urvOB??2%`UjA>`@8NDfBgeaa z>((6tLVWz&1h?_=@Npa^zm3l-Aa{pC+dMJ z6?S{8P}}`y5$^#$u59G^q(;l=#i zVT0S;Zm@l$4A2F$Aj|8`#F7V}s27M+M1rny-ZG}llAmrr;x3Y(A6%=Y& z7(rkUPdy^JR-Tdk1t7SOO5`?q7p`6As=-`Cke%V4>YY|}EBl{k|6lrdiwTb5qC82r zX2h-psba&XLspYw4z&~AUjv^hoT3#*DTCrzr8S{wq(18S z8uuj81?4sT%ZkbGGa7QELdmyj!Z^D#*J_#7Tvk2i?VjLWe9{~Ms};M8=L?&-0wY|W4FAyEOQh)K}! ze%ahEJ+R)3++q3Y%ORHqb0-Q7Wz;xvwi`4yPx6PCl6+AvS5acIQ~-0E^RkexSF)Ma zTJ8;gdD#*cJ~jH)>&7o}XH;Q&pOF5zF6NM_@GS!x`mQJJ+EeV_4ME}3I42b|F_#FT zv%vEa5)l;0Gd|s;gESYT!|WBR6Z_V3>x*W$wj;9?2~89)Q@xU|g->ODmR%)Rt!Gei z){If{;Sb6t=!z3Y-dGQI*2g+VGu?h$e`n@X@W9KiTicWRW$hBV+}g$#I*vs{wljs| zg8EnS98Eyur8|{&>DSx&GBhwY8R|Y>_Qr+~A4rK;qDTBgBq_iMy9fKRnZ`Js$~cpM zf5i$i^lev&c`6YtiRLY5q9$1B?LnZkGC^%)64I8Bwns&+M*R2d01UXLgkjS9#J4{U zl?}#kdNlT}jp~EZWtD&M*iiu6<`yJ5d14~xc^iPoojd?%c+fgW_h;*YJ)3I)3Dc7L zS@xATvF@h+LwE*EGyYkLoJ+cwqNU*%VN`5AFj|~#-rCyA$eSd6blBo3F4C=e(p8Lv z6nrPezkV~GQT7x-Km59Jb&8zXyg~4`Fk_H@a%oI;0Zgbq{_dymF(+XDCVeGk(;xD8-eFH3fxes1fg{Ge3y;p?@rp7|{VK!?erqM~nZ88J2`>@Wo1Re488$ zWqmiALG$JH^u37AA5jI3=+s1TtzksO4WmTk0mZn)^J4gF6To#OR=|1)l?kQ7o@*!~ zCwbA;Blq%Nbh&ofiO9whv0}m|1&UZE+odiKw<*YXVYJUJOf>BfToTOa`!?|8j8qbp z`qNhnlRIR2uLpr-&|4%)HCyJkH*pc{?woSf-VsRWN|qEU=o@ zn6m=k@g;=Ns3(13w>EtPoB?myQ8L*XP#GxO8*$mQt4&T0aZ5FlZ#;h0oq4NCvqZSJ zK}3+q!!SX0h*^z5IZ37{fd1FV``n1&5kJehd<$@C;KbDFyOFbzg5nggYqbU;`GL@BL0msqI zg@cPl&zv$et=YI>2@CW{Zl8=?tsm*d&`sf|6r1md+}uZ;BpE$>?Iy1jcQ}VQRyS+L zVtn01jlQN~lyo$d?z?L2Ptn4X?CFMppT62W`iavf67DTPYoj(o*4bI_i=Mj{K-hSH zE@fX4L~*)nQ>_+M6qHy#ODtvcNSxsiid_;aOeCQ*E*&dXFDf9u*2N^kPd~|V3HxVT zf;ycfMUN;yN%gT*&cRDWcr%kL$Qi1Qw5+?zG7ZVKLs?T$3{li&giSTe5#>3Pr}-e> z=JWT6%YC8ErSqW&ts%p{=E|_K&bwAnm>W_Coo&PT0Qv!f%0zwb%1$MjotPRj0&YPh zx{6K>IqI*}CIpn5#-jYi+id6hzMfPHIoq|d>BZspB5`iw@!3pN^zCXhoxzl`9Ybwe zm}H8@NojguM77V5CGgdG?B1OWH7|e2`=leqR|#6SC=H}ADjH}c)RgWhfv;IRdSfl( zfXOk9yUt*C&r^9eJ97$;tR3SY1UsP(AJp3kn~U!*8i`#!V|FGxZP&WwqANYiE0cAb z_tsUjimfj~DVIzek*MTg09(9aegiFW)NXgme1rtSZ3`ua=kCC?6P~Lu>s=0J%m8a= znL=nJPo`j+dbCBf^V=%T<=5OcF2jlRLlt8IO`@1mdMp-2 zz-^pg`RTf&P`?nT_L1tIxAyvuksan!nJ$~qbMesuL&6475!gVOd;@9u=tjyrVaB8j zL`A3Of{l#tC>{3X1$S${DNU}Gb9|cgVQPY7O>Vue1m~Cc1daBU6rb!?t;s%I7AAVF zr0ygEg*~>D->khN50+0xGj9kDnJcSc@utx5FK&K`n(C30v)yTxzJPQcJ06GeDAmEi zE1_ytgD+pBybq$!1Zqfuo0y&)8A0I$TPWkpEQqfbG9&Lx{IdbgV%0aKIrNy$f*57Z z)Y4A%7xPBfOdp;xJYUA>&H&&(edJ*)M(XwIXsdSouFTQPLqVC)*z66}vIe%s-CBxM z@%<^-@F>=hU3o24%xT`JG3I@e@HTsyh_AG*ovWtwFe;_8A$P`>*~{u@OuTKpu|8vc zX-w6N;WQaE&XMvg3N|`;dA2%8Tg{&9l@BfL+7QyTLOShHg$gG#+6fA=L5i9j`pIN# z>YPUc4W@teWcp^j7hdV+rJ{LaBx6bY(6z-uy%L`3Nj`c3o=M__#?%y5mZVsMMvc75 zMB~Gm3t6QM5+&vs^aYbp0Ks$S2ejkQa{e{L`|r3i)3o8qYzitUEkHES=w6-rek4>+ zunI9_)_NiS|FOhrosfJa5wM)`!HD?N=dl|@`}c6AxD_9*cYSzonHpyfMtPK=jHIC&ryMwJVcc0dA{lRNf?RJyqtn80n z6UmKA)Q-|BjzG>3WfAV!n${#$QMKat92lZHeEL{`Zo{G>N+( zzuNQtNY;ijbV1~;G@*W-ERthkY#(yyxhR-ve8z+7&G0r+XW6)&?+*NJCS0riuebb9&M{(f za&nsc)dKrV`w#7L5ug3u7{$1Y!7j7N;YGyXcq@TG#xKBv1Q+qFZpE8^c@d0@uj%nD z=bC0&{ziglbQk{u-tC{*imM?sjojr>tqb1eS3UnLBPws+JJ;NoAI zxXQUg4i}&O6^j2w$NxCs?zMiS&8v;tl4$p^w<2CK??uBQz;%jtN)Sz=4S`Yotn_~n zu|Hb>%X;ZBznA&E5{Q_$#Nv)Xf`GV{8*qWz1E3W}HM3>7L0waC*lQFIls(1gAMsd!SW*{B&<*fqky)6~Z(hMib z;6Hd7#Nro*ON&!R(30LWgBJ#^Iv(%udN)T~j>5lnu^a*B�x2RbRYz-=}H+-j}s^ zY0}q4y|T_5FQC(TC-~ptSS|4WxgA%9ST-g%`PWlY5slJ)n%5LGETlE|U;JPE*TetC zuB;1dM4Rd z6>wr%zTi!JNB=`4uE%IyQ;`1G`$>g37#m}gMr>;HCKuUy9{At3e!&SOP|fq#%PB1wkhY&iJ$n3d=FX5X3+DstXdKk)S7UUR$ljo4I+KByo*@{#$+fn9jaQnn(te z8C_gb&{hN@vaQQu1F&5<(mM`c8=k?k!_p|UzvvK8@w|e3c@4F3N&5B=-p3`UHcwv< zxS9w{Ir5f$fJftH&nE@=N-zp@edX(i5A5|5Sdk4n`qxMY9af@tN9}unTDBW$2{|$s1-oGaw zQ>^Wi5X&bN@T~SWM`kY?m(ugph0t!{UHqpjft2r)$_bwJkVlwWk@-Ir68;ZoZ)Jh7 z^n8ioe=C>u-zxS01d9F9Kb1=0kfv(Ys?7XP3vm70Kt9sfny{jF>0bS90hWvh`Soa3 z9%kHzl<410qyK9`rd!r~=;`x>f4}0>-V0LF`h({ZbjFILb|U>9mG^t~58jqMR&wd) zVB7MNEw{zjxQ@^6hHs^TRm&pbimiq9s*_d(qro~BF{sSUUIb5vW?BHfBW?QVk7GW|$Fx3CdBg82 z7w_hhL9p07>xL27FkUIApthP+Hw1+W2gyG6Dci67|^+g~OX_O<68Yc-gb zN(IgCIEpc;E23+7-)b|!ON@;$g0RLPvbTL&y(4eGXOa{l%nBtLD4SkZx3CjUicPvA zGDJbUUIA70rux^$IpLWBWFgUec`C3Z^0GUQbc;QPmR4V64Bc!Ba)yCNyu9f=58n$p zYID=1-5#Gox`LX27jT#P)M{70=iI9&lNwQtIKj$K`I>TP1@`$|4?WHg4eV`^DsPIy z^t~#!8jLTSwU3^Wn)YnJPqIjFYHGqKaGe&^cZH_E4G0W6K%^S<_#9! zG=VSI`#rzMlL!YJjz)_Ec+xjUVO%Nm%Un~XuwmeLd&eD~WgV;fB!TJTG2}4{3Ssbw zMk2}TeKjg>m=E4T>geB1PZCmC>m(z+q=q0oi#~Obozh6fDq=!C)mkHB>Smo*A4n0p zA7_lHLfcMzUpPXSQ@JpjH@RaHBgu}`wyHH=dhqP?+*{ieI*+LTg}wKVYI57!#o2B} zrKq4FMNlB21cK6wfC3?qga8ReilB5t?*dzJOYbFwAiX7ogd)azMCpdcC!@U-?J4uxJ7W;KWiD;@{u1k zRhr5?BD3&S)Xt&Nj*@B!K|e65Jp8if=9OARKmzam;g3EHSkGJ1A~no{0Wf}np2~vq z&x2JS@O}{Mc09W<$dYwk`nn7i`#B?w?R~V4$R(-nuZ%|hjnZ%W#Ml~u;vw4ev(aK4 zd&U9voGW>utY~5eV^3^M=AIhyZiHm}j6cuwiz2yZRWZAbKJX@id@?^9(%m?M4_dfT zg(E?RV&`#98(g202hOgQJi4NO#%Ux1D}wt17%9@1q}X@gj8>u3S}?_e1!_1#Qnqf3 z*xEV$=Wg*HyF4RnJ%RD3KjQ{#G2;mgMrOxb@L(U?-Y69OF*@2*pGSwNgW=o|!)0z{ zk905h`8>Tc|F7*p|L0og*yVbj?Zi8^$~fk69lS&)_-fW#DKNWig1u8!rnz6 zMLyOjJiAmWT(!%Bsc=#XHwhz$nTQNPzW@ zS*1+{PIelEh_s39eh+7Cg{=(<2=9@_&65bI$=Cg)OwAEKuhEUPuiTM%6LAmxr-;hz zl8>v43H#Zgi;;POr6_IA{0 zz~m4)uFj=GgGW50PD((EI$IUC8ucj3gX%ZR|NNDEx#=oys*$bAt2ba(^I~7KM!hw1 zSiRWu{%`?!(F24kI>^_IwTaZ^8Z_N1JNoh9*LRa8#)h(S?LyKX~e|Fw}el2LBPyE1ty_&nM_;S}Uusa%` zA)StQP&?+Od4;?fMURBP?0j@992MvvFt_J!D12BVn)8U&53w?D%a^F0Qi*(xl8 zqU|3sy?v{YemHmi1CVXiu8e$bB00Yg`>P#(xYF{#ei3{$z_LCnH^R28o4#)btaD%D zZg?BE|7QPL{4=vxb>(GK+-UI!m_39d#CTPLzumSGL^gM=M&jS0017-E z0_0gq0IPNaB!N2sdOcnL$tEDo;0b-Ph1y+TtoeKYp5zhOe0IgG#T@RvxjcIBpkf^Ye??jv!5r! zr{1{~kY9X#^^wLId~OsQDVc#!6H~a&bU;qwA}UT(3BhB`R)+EmyaL(jc!u;ByouBZZMr9GJsx{p+BD@SrHxn{00|WvSg=Lt;zVt zbf1n3`tlDcpr<6PBR=)sIt6KP5H$KtiWve7KC>_=iGFUn^3iLs7+CN2MtDhjgaAi4 zwD8{hMK1fZ`MbxSy^Wh!%|wK^lC^!|Lr?Bx!U&Pw_hX(mJlbx^Gny?nW%DIV0i2V{ ztRF`xD=LWHCOmRA6Lc1ZzeN=d7^3Hsd9>sbCyD2cXYl)eGiDLeONI*!N}g*`<7@f@ zL7p-s12<7u9`;7P*M)gk%=#*}1>!?leZtLP8dZA&S9k*D#>P~5T3uvkptJg#Yz#m` zHx#CH$Ovw>d2A?u7}6*@yrwTetW9Ehm7c;%ge~E2b?&uc{@e22@oy$(Om$(}b_seKed3(!QYfYTwtX^(Fjpj@nAD}x$dham<)m?IV1@MeNGK=9COVxiKe9Vp=F9pvxz;ik)JA_ zPw4hY9>$n=I>5*uZW=_O787tX9nObR`9w}m(HF9Emx>)*DQ~=_OzRzoHYHyajX@AknWyPs%@9^0NoUU?EU%a+bV z^Wiv3EgKj>KlC~enN`JBX1iL3Z@t|F`l0eryzr;oJJn!QfWM3j|2FHF3p_G0-`6Wl zP1=I6E+T$P_PV|S8jg9k3NC12J!7BA*I6(|UuaZXn$71N)YI_I?S|($u`4SH{8pLI zKdzgS+_Ti84CJ9RU!p_>KLB5?*60-|xtKVMdBruRez$L5E-#3g<+)~EmC(q z=BPNm5>;Bb5W5XCt<#l!pI&o4_yi-suUtPTxMR1{TPHHY#-NTYt2lVaZD$NCuzZEf zxq_Nb?P0jzL9$KDt-1;V-`L&Yeq@N$wWmPZ4Rt;)*NxrXH0O8~UkEb12qTc~uYj_K zCZ62A4H)#BAU~m%#`YV#Ao3;o&fYXrjg!CTfa!%=d--J{0Mot6 zj>XQF+20;r_-2vVtN-e0fi%p{%+UoBpjiuP%bGMU9;i31+3Eb68RC!=WSN^vQBA|Q zWxrQSjGsTv_sKYJL_3OwTixd*)Q~dJ(&YuKl83RihzhXTOqopi)*)%BP$>@1?Bqso zPk@P~egAE#oKmkTUnhDr^_Ir%#Of#q%rXz|Z#P8Rr71wDPh_#w4EK{Ng#Xj<;k|0N z6_9p7egRkiML@pr6f9}JZ>%onX=v&A{dogSJ2Xs~T(#ymLIp?{>S{&yLa_M)$`MUQ z>$OPnM;FmMeo2Cj`gqb(ZZ!W<0300|`yuXjlLpvrG6UUvW0u3du5R`gf0p~`ep zv}<4r@B3Q=O%dYthMV7I0r`dXJS^x4WAu&1?p9QG6#f~<+b4QBqA8@$5DZ2*kK%-u z@lnV0m*r?Ias2{;WvuIEV;RAt0oZQWWU5hEuDi45ldo%Lj+8-GWm(%@x=U+UP@-E!I zznoK~^~d$6n2_dt8aqhcgOkLn=-U7AY|Z2H zXPCkxE{ufSF<6sjUC7hKl5 zD(F_~)*m?>o1cq6Bw>b-Bx0v<#Vxr^(=1i4gjN~hzOj^I(Fd0fs=i#sZd1+|JLaec zu-41w6fZ_WBCajb!UVZ^;88XUng@BAHfO!o?87z88=uu*tDEmaY_$`*D;kd&0v zVcN3(#C*et_{CJt^y2d*gU@;CZ5_jfL@u07Xah{FsPA*UhcDfL7pLlzWP21q!Vu$O z4l`ITv?0m>$Hz%n7{94O3QKNRVh+}}aa_{un8^FGV<3wyVDgp7Rajv6l_m%j29#gK z74Qovv1Bs}3eo*^*~xS?!&K@`k@J1t`{9}tg9sk@rOMD;d;tJZ5yaq5i_&8}ii8nB@y&*l3f%OpxF z4;qI(WJzLZ5bJPK0?k%BU9-)XT>MR2A+~ATHXWN9)v8`f2CeBNu`Ky&>iop@ic=bb z-k~Uq2UEnjegRX*Q;5!-Tv7dZaZXa*MT0`gQc@DPb>D!$UL$|zh`BRC>e22Z9DbOU zrKP5dNXnE9La=s_XJu5tP|si!ctca zi}V;HV(w5u3-47C6n^Ft>%WNQ{~KzT*m>2EeQS;tW=ytA%!fIaQNjEz&U{}k3_ZN$ zdha9bn8PFdRJXisfH61ZpR#X)w=CZ!Z%ar8uit6$zIKi~R*o7N{&(52w)T9(rF-V* z>568gi)7YIJJU%p=DJjbI=~;6l)4POeB4zI4Gb47H$TrI9?X<`ZRYPi-TQsy%$ut8 zjJd!5Ph>7_^&kZSp|Hb%^S@8%Kbs&rv%=Lsy)s0VeF4NF{_A-;4mZL#Ci(Y)LK9Z@ z7lu@6bN;_BIiGr2~#V~XA*FqgyZr@y0f+SU%aaR-7Fmc!B+p3 z{r)Tq>W)S8strLh(>7RkC6xb@wg24u_Z9fJ?7v3lf3ICQmgVBsCahGPcGj~;W{0eX zY>a2r6g}9ZYuM+{-@X|CVvl?(((UnOFi4@x)Q2?s!_u%KD4s^zQup9{n_#Eei?^BE zL2YhZy5zH#QWeqxGu^HD@E=vDIelCsn=kGS(b50=%fD^#{~iv`=egcFH}mj6@5=vO z65a)#2g}8y0A2U^oPEPhx`&ewG!0+O-2Sn6T?cdBQQ8`DF?P2r>_6OWnUV-cbi#Rv zo!vhjD4C{mE`gh2F3;c_G{V}kP5hFgP04(0f}1Rp@y3_gN)&}nmd#44GPVK<7!*3Y zC=gVyNztoQjbhE?QZG|N2u@pQQ(^p4M>eLPxSWk~W(EtIE+n{tCy*$wTxd4vx0V7f zjfvLYK))r%oy7!teyb@ux}Z;Ci~PJcUrvoZNS>_=eRT1eq+rE2L#~(i`8EdSI7O8y za9xjp$Vbi%EA>#<=iGP$;c6nxyQ_p8*!KjA(G!x#=?LgEDP^ z%7|bPtGmBIH$&D({REG3aXAN_%nk*Gijk)Wg{IUQ8@VmEUQeRnXpHk)mbD}iK&dKA z`qhhARH{6#e@td&`Gma)Mtt{!cTFoTX!;tZ9g$)ZJ9B^%LfiRw?}A&6nw8y!(W@N* zuuGK_6u&fC9^{|@TkwjCp<;7Ty*kdd4iUzO_ol*8X_jy>c=}oVtch)16Yskb^c8jF z`(Z@qj|#vi)?tlg3cPt{tc%=I?{EJo~DV&2nw&FTi};xuukJZMT=Bo z13EUC^Jr8%tMPHZv!a(9`+DBt=7jvL_HwmC#I0py+1U9OzA(x|`*v=-Ouq~9hnW}^aervOtVyC*d3tW~^g0hH{n zpl5sXnT20!3&zKJcNo9I3uRJMq;`yLoyr0)d1%lvr5{#G9pV>gNn3j5Md{axF)ubNs^pE`dK3FWtiW2>Nkb!S zi7LA>`t?m6Gj2ZM}t0_weFr(WT}(W+htj9eJ)5Q`6p26$4Qv z3D0uf`iRq2Jw7bUbEl4&wOK2twmISo?}%D`WPQ!G0nn4az~#ed3GaA z6Eq63Ci>Cqe0rZEOi9X|z1d>{X-I#YU>q8K9RJK#L@bFpp8b|9pwTo>B>Aztm%-9j z2dpZcDRS_W%~_=s#CU(MHsyqYPaG~vV)*2<=Gv$xi+K+`M7B~(rtGikwS=y;N~wAcpKAR-L}wr))FtCvZEp26ah^&0I#r&b7n@F%P&e$VM-V=$4iW7MM z3)ANTfv_Np(ZRjD2S1+ffX6n<5R0Xw{2(0ZW_boWL&QS|>W<{@267&{ z-8yHk708J~;m2DzpXftaG7t*~Ln;I(SYFzDrZ|b@`<9%tT3)l0? zP71DVki@ydpz}<0Tn7F2>ukrR{N-oD)uzvD#_KBcn?l)*3TNR_z>St|ZZW0NaO~0* zzK*dfTo_Bz_htF9#98K4agYs-j@!oro2CnuPQEI1F(o%S(<^&;xbA^f3fJhbW6gYM z4B0s<)xcjyh?|M;33pUL{aFLz8XXhvpL>*o$6lO!L;a`L%JCyfKv;SGW1q_tAuYv_ znIsx3sAlvryu6eK5>4-loOo zKfa>4C|#E5tmXZRR+Iu#dwD0^e=@63Le0gmvslJJXhG;vmAJjrGYwyU8_l2_NDHEN z8t=Z+4tQyH)~_r{&n{JyBwlRnT@?+w1+Y{WESONMZPA7saQAE`s9A>d-I*L#zYv-< zfABI}8jn%BXJDw$??8fJBtBZS6^#(=OjcXY3l-H+bND36jvp8UT&8!mqt^sxs-6i~ zj%UeYNw87*Ck{3CmfP$VWoX>KDJWCGM>8}xM@M(m>i<$-^OjlB4W{Jpmld8D zpc?W_O3mMy&-ETDs=W!9#L3AbbaB9+6}LI!I&#GphRPE#Ca_S{43hbkBZ!$U>$jq9 zxsqgm7}(m2X59`-?--*IE`Xd+03K7*7s~-vm~|YQ>!}J)+FCoZ!Wb#BUn;Bt})u z6i&D4D(w`L2j6YVR>z%Ywl0UG3!$mMseSGx;KQstNo4c{ZFehbiE#WJsCv^K!?oU| z8Dja4>CX(Z9{|fhEET*A$)B>ovNssEbDm0@R2#}5JeHRy6E^_VKu#qaBl$a}`pLE$ z;me^?;tW2ldizlzAyzZ5tVPC9c*so`G#ghcYy1g08LJP9bK(RfrMqijm10cC0w~`X zET*49&OR&hy!TQiOk;~L`A3OKhM>53bl7R`s4q;ojQ9+dC|+WxRZVXx(NW4@UNz00 z-hWQsoPph0bTL(b`9xbyS#X%803odW^Mjv+>ik|)1#rJ8X1KAj-{M4he}oizFV(%h zaaNUdR+1wRMaU<}@VPYzK2I3>?09XZoRr@ie;_hfGXn&?+vgB4+CXOuS{vjkZfpZ& zPYnvbMRs1way2S7bEGU%ybE3ewQHPF88m8S?l3}uSoZ#emCoCTwZbXIsBabkcB04< z)mKG&)U=v+CII68y7z0+bGQ2vV;jV~(OGJIuz`5OoK7|k3<<6V^U|NCmnXWs`;v1> zXwBpq76;aepF)fXRgHoMuKUbT&{YFc}m(*(MB>jIlk&T5vz6t z@fQ#2q85Jjx9+{dPr7;5aaZva*y(Wve6@-omnFm6)h+)q`{g{TP1y)|FW_UwcRs(M zvZRi(FHdS*xl(w!;j&IWE=;n)8&X2LCt-yy^wWiXRaOQoWlHNo=VhsWLN~Np*6bhl z^ANJ9n-1pN&C@LIPAAk4KV)?O=MMb8d;On0(Aq(4Y;3U-mu_XwXvys)($vOcZ zFH`@dCHM2K0B4RiTdrGnG-p^hGuG3bn_m7fz{Ur=G_ojNq0Eowgz*MEV~+oQ6!{r9 zVf*Pj^i|O^l8BDOXm2@lOp74_l)KbOQA3I_2vdHc{JtaIEVZ`OS%C6@NAn&e}eol zo|ys0$r%t{1xG4!r*|dt-&>U+OpCydlbFt2<#19vi5_)xdV@6&nSIv}JC;4dH$Gqc z;Z=eV0os3fnVg*GH2OEX8wq7b?Fz+UfumR59ZUY|Dw7wv<5rly+0eabPtlF676)*Y zfHlInU4VkN8!b%j>KDkq#Weqcm3XoK9 zT_3Hk2!Es#UYO_)XU3)LZ;CNz|H*C_gGuj&n~d}Cq0UgUrpg)Nt-t3gY1Bnp{rQjE z{S@)1h5G3gJ@22oqJPTa_xob}uJ|kGua^Jr;@`ITe+CzD10PNnm0?h#j&vmqw~`%miBZ zrU0SuhmE2LBeE$bqqXk=8?r9VFwE-4Xx%p7YB%XJz@C7e(M$>su{67J`RW6$f{y5| z?jh4e%@m;mOxysx$bVCFf$)5}AtL+ZnRHzDY7cX8F107tJ3st`5GR)p$DX@=GAmP6 zxQRLvfStO8rLpbvv)oG2I~YxPujOf|K8Sw6%-_XNdCqOh1`l4-$?^=5#xid1k5Lssd28g`;YqJhKPz0@aReyZM0-1WF}EiA z`{aXT9%v;z3+Y8op)qABYY@YuLL{%d=14OY@P}IBG9@BA=S({KlV@w=Iab>^ox*8- z%yBh;`egTsixyQjb*p9B@T=l{%O<$XFo3`y4Xg-JM~-+O8e&^EXm8u*y;c4)5&h^a zlQRfL(Z};^KS#}lQuf-O&+EfUD5}g>SAv4_TJt$aApdzu9I8Ne5@u4m{h}0V+#UDV zULV6fy%Izs;UP2#-y;th8qDFzOVNfu!h9-mkr z|Jj~=wSJj$97W?k%^ENH*(C98ey@{=<0F~E2_#yHO`RxM@Tj8Kr3AM8VReTYEZ1LG zqxTw;F6{5tAp~)$V=24=NnbJ7u0Q1S|J~mIFdXfthySHW;EsAKmxYZ14>kn$l|hw# zE-S>2vN=)M<5Sr>G=)oEm%MYqe3!}j0|k-2LeEbu?f1-_PPXu(#R@>@E5Tb)+F5of zyr{|py9&wS?b~-$i@HPKZ`|{)M?QM$ zsK4C+W=|0Zp3C87e=De&uUXaimcQA?9pyTd|1iiL#9bY^R!A11DisUWVq%{Bq5DsB zldD#&cfP-W3sq}&LWy6vM`>3`gFoG$EJcPQs7=N|YR9TC1V@k~7;L^U1kb=O@^=d@}t~^QoCBA)In?>nnYW|Eh z;t$JT`2+THOv{s25lE}dLwYOONZ0f@7Zzt!@rrL;org&nOVO|y!dV)tb}g%$e@5-@ zUvvR1V`W!%;4?=^3W~oASGp?-u%EC7>anq?^%}dylM!mUXJN6%vZjQzXmqyEE~_j#m{uUdDzhE%3Opmq$b)AOQ^5+G#7Q_52!-_x7ETpRSlJ9uh+@p~|%Zq%xlK`_u; z3SS&iUX)3DI_eKDa9urR)&1T)qh8wlkEb5MR35s&iu1RG%$uhd%T$T}=U+V4k~+}( z1`ySA)nxNF-0(6}cj*9>hOr-!G(l2F9LwG(>+pSM(Jp~+KXpmJzLT)cFb4V-*?*y@ zbeLa8QsP}r293ogHVO)P5!AxtZ?U&FSxh!H^qqr0aiKr-vFGJvNnI6Fh}-bf{c>SC z5o4ixd*aIP0|$`C=KJFJmwH^N@c~ykZ+D^CsS>wQO*>OABI&rzDx;@Oel9DbEvVhe z34z9IuYa3c=6aN9KA3Ny=e_D~-)8(|I2X(7+VG(s38?r%zdC`Tpzg ztkqmD^}jQBCfS&E=67|^e<1l>o~L^< zGWVnOl-OhvX9AEY;$)JYBx)CR^ELnbXQLE}(uhs=PuG3bxW@}(HylLd2W4m9gWDBP zoLdwoYpOeOnfB zV6-m4ChNCP1ES*!n&-c88fgDf913FQN*I>7kRtGGM%Ft2?W4Cv zm21N~IqcWnfKK`w7Dx;~IBb&_F@0d7Oj^&#&k$XZL3;imire8+x_eW@Tfc5z?idZT zXAlr*nfLr^WGmC#V*u2m-140eV$D`s>!BXS6GVqaD$JT}2hb9nUCUF3*@0pSNFqZ6 zIYmC_dch&(Fu+AdbS$M-f#3Chyi3iZwMNWOU0qN#St{xZXFvibA>LxJE16!IKN~%V zr_Sg+9)@vwU#fj=gg>Ur7hs=rv;a!v1Z&8vq_#li48Q^IFn{8GNBQv7D9sN5(;oh;J1>mnC0o{=@leZ-hg?g5d8H^9C4 z_n606v#CpNKrFwJ>_ME+-J@!_ty^1sKWuHhmD6J%5dfR=H`$$#Fr3SBc`U=}Ay6q3 z6-N>_z{wW&0|Kq5Gb81tVbySmDMh3d=0kRED$;#QiyF7K%pPpA-!#3S+hS@doH z#Cp0we)^7xX{~z3G^Xd-OyTy;cw20a--Aal(Xn`1-eh=nluHy~ky)X`JH~x#zQ@+c z@Li`!ySfV=A3``zPhH^s@$z^!ba5IVW~PlYsyT$UiCiSD??Kx`$I#4R=}iKU?oBB` z6GA}fQs1CFc)HU`*~Oo{*i@+$U{-DElygw{61{=H$Q8UCXJEDb7*v{~q0Z=UmjG(%lKtK8xq>sWzgt*yqb*4cK`1 zC`-X_l1hK0D<(a~9+_UhKj zWom}c*O!T(srFCec+wSU8NJ5Iw?M!VwnvXAk5cM+JT?TQU=C-pW2Cw_19$QtnB~sg z=q^<)(+E@8cQR2a?qIDdI>2hm{h;^t`{k5v_U`JzVdB*Rtq3DUfa8=Cttt#ZrN~kB zU4e7De#8CiRE@fh6{}*C%Bi{y+++obm9;fP;Vu^*y117QAf?T;jC`Mop;ellV~qe6e7n^1UB699`04?u&dT!DQK(kl#U+$SNr{o-{~*V z+_Rb!61PngXS6&4%2*76Yb>~XK2q!MnUzXQ9K#4ukb7Hnxh@3ueNm19{-){mo)?&W zc)4OJE#q##Pa7xxD!uK?X0O1@LO(w4@?C8~Tx1_fY{AQ*=b*~)>o?_wurGFgEb^4T zF3l_{%VReR!rZor5L$S77Y*8@4C`&yO^cGa%*0kY-C|o&SF2L*KKC%4qjaTq`?evrWqY5Vnl{O{P;~c zU8E#$tr)BA%36;b8pqqR!4i>qmyOI<0nWEcB>g-CZh&qSFPzcS!WpkIB~h(eC>f$| z@HJ9(34ljK{AT-P5Yg2+y(5RgN~|U?RMr4By8#*(iYd$%PAH-KU?<1>6hP_dI({@& zfdOFjp}+}|VeT7-G!W85kN2>TCpGxNHns(B6K#euo`mcBn4#I{wemG+qHo$&T`Gpk zpD(q?U(dshrcS|#D)}Afb(MCP(~mgJQ_gzi&P(@rOHyEkv#>h9o*^gG%a;)}hXe!? z7nU>}Uc%rE@-%pLZK)kzlO{QNC!ySh*TQ%FCB_a2cQzxzCa zdd;D#?n*{EW@t&#HpEPucrn4`+GoKKEm~pKWJK`Rs=pk2E6wHA7oHsPKq3dLo%h&_ zYlFI8yOO_yT)lZdmyGKR6dCp~RuvL_zSej5S-(yWeQyp(yO1NYXcJIJWD#=I<+zT< zl-tTq0p7>&b9V$kcE-Uvw(Z@&2r|J?bxp7O-rjDn3r7EP^=ZGCA=f*lnN$3$LZZ=1 z*Mc-@Lyk$DIk9&eiAjZBx$Z~>6lEA`wNEh_@w@jBG%!qg1|w1k%&>s6rArIrsHui5 z-<|y5BD?uaVPh4z`BTJ&CKnH1zm8^uxkfIAw*Lh%7!FY&fqX$p%0E{eAz5SHL^biv)G zE;|AxYlC#gz*_=N>RQa?M2)Wusv`sAoD0ba<(o0`-^KfqPVdRuK`iT(1j@tB1oexh zYx7M-ludTQZTGFL@1;hKR!l0whJjcFz?^fPSLcSlkQZn2_}SX87Pns$Tq)I=Uk}I+ z)TN6$p8-7OKcm|}T4%CzVjM#&QF-Sx@udm_mwbeRJS^VSpsbVQN?tkOCmr%kFW^#D zy_q%tF3((B1)qj$Dit6nR-@8h^pL*AYHd9lm!L6%pOn66pnY|FsT(kM6f0A_#j!_s z6>E3H?w0=-B=emrT)`?IinvE~922Z$WyV}l`Mh3Z%D|60?JE}&55!&WjQtVyBykak zF=WgMIdy41_n}C`qoW&$4kQo>^9KaDz@Y58m`w~VIwMlFA?@>nhsni~-C}!Ow9!1B z4B1ZO+8-$xP9jxlJkxsbp~mjjHg+jCwKfn6vS0RNn%^@GaYcc;>cY%!JQ3#H7n=ag zs@u5GbA9P0tLygOfuf5mbF*Htrrm2+rKmxc&7;x{&LsBP`~XRP_WRD7{4V%j4Pl*D z{`Fe{c@`A4*Jw%?8SX1RaYe=5NTXN{JBQ$wYNm=x7i0Hv%kU=S)aPMJgpwt2&DZR! zK}=0zEUpZ~`j;U~?XT5|M&l_%WFI+ri_Uh!@ZYV4;jxo2)JG}+I}JkI)7OTR!Xni(yBS+|02hM zCK3*glQW*lR@@h?4zy-=JnfLENrtl~ql&uTB+pr||2+4HSc&dm{b&b@)Aku1r77(MNWrK8((lhzFJ;QR*R(|szv$tG{GdU>P5)V2Tx zz!9ChvoE>QIPW=K1pYU+p#OD~pI*LLVmW4V95?|TF;}Oa_2~Xc=1TqnfBWzf_nk;` zwHkOP_wR3>ChFgX(oT79U#@-lA7SIN;%<2~X5;DaZHm)@f2ZBy?-}eD*iLNG%VEuI zd8>$!n7VtUSOI&%l9iLLImy@Fym&4}&mTE@Q#;^|hLu3WM3LmMdWQ64NtH4t|1EOC z+Z&X$@gkoFA5W1kBEk^?DS)Nl&)%JC50BqE4}zNOk6h-Td`Ksp~51 zY&k0Ngb#!ZPs-0n?X;vie6y@64*y*Gh{RGH-Bjd}SW1|CnZ^~9+ZXFgdG*@RGGXvm zT_(n5xa9Nuwf;^x-A^G;9s7$~Lkc?WpmD^;$D61eBW;%}>Kgg_pSC*c1=nI{);}|Y zHKRXc_}(ttL7uM#vziqfI=hAbl0SoMzM9E7Zi;kcrQeiZ@^)SMW*{U{_I(e!W2^S;YP*Yr0Uprye#n@Foi?kfZ2JPZ}c*AL)(!kO;fX8_wTew+886Z1YvfHau~%5Ro_)W)48Rpj0VE>w1$*l zi907K-4sj~2)&GUwwtz^Ri}@j4mDRGLv&ov1@b;g^jkvnJ`(mA$BG^=7&CcX|q! z0!FLzf6>phS9v3?Am-0j)Fj@SV4k4VUBo?0-oMcqT2!|?-Z)Q`O6~B8l@HJ)Eja8<4#vhH zj~sV%I_r75n?^#Ke_hT5>?MK1%pIc`@{lhj#IEmlrMJ$yK!duYtvE;rP7I^*vyg9;H>!LiY(aUyTVN zq$RPW?ea0I)suZDlNU#9xL>QePX#Ipnu5S9XAtFgM~mODII)H5PnGaFBJL8a9oe(3 zhX)`x&wJA18$F;D2%%azjZujA*Y28B!%EEZzLn_K*evjc^QRCZ`53)#s$ZH+5yLWT z5NtO&FVZ(oyt^7Un`iCW`Fjx2TEkB?PSI?xtCu3ejwiUSr!Hb*X9a}zx!tEQQSw~ItxGunM~ zRl2}zLoH#Mlb6xbEA}~Pv<&p+;^Aou-=^2KEHl9^x0(WXyq#HW0!LR$E!@qazM2ZCQL+YDwRo_IXf;pN)zR! zzy&$_pz2?C2@xBw#WNmS+NThWeW7xk)*ieHClL=b_OEYoMX+cJPVE z1hX|FAJ-R)hstU$h@D<~I3YK3lSN#t4Hpot-It-9j@h`|c<$U`STRzC<}l=WNN_&&%J9)lq~(N^oPO8GX!xh_kk<$YDKF2(PM z5H_)dBv$v#r(v)kjJ!)%Dz7w3%CLO!iPuL@8HBlXgPu>Vc-wfuXP&H&dRqbk?2N1M;L z>(DoV@-o^!R~4oJ0XC2l8=d{P_n(lLKKo1~)J?O*`{ML5$o>bbCr99#2p4<(Ldx?R zjgOpaI@{r|EgLG++Ih5mem6$<3Cbkvs*%W%@mQ3EBTI&CrVlgVs9TD* z+ic&hGg}_#kk@&j69gzwrFqwMu&~>NlZe_aTvzW{PtkkZMgAW4eXZWFk(5GQ-n{Ml zarFztyH6b!B>bd@FiaE%=Wi+MeL)Bqdrh(4jvf=2AP@|!q#ecZ8Qo&34ny^2##LG# z%OcLDSHU8%j8KS;od)(n6OVWCG&noP34_j0f84~pLjw_4^^vw;n31aisk@e+0=k9} zGV@ExG4Z-du#YezA<-kO-u9!xJyEsjlAEyk7K60(60k^`F~^b9<}1e!V-jERxHTcwZd$AP(DRv<-G47UYk|ub&daV2>+EqXlSq5DyPfqTe?(j;F<4X zZKi7+yP}QKw3D>Rh?HbYnhXDgdM-*OBJA6ZA8I+z^qg2+p}S`0HOm8I$#)?>{iYVG zHeFTq34*|>?y-n2@M)QZXi9*T68B?if1__y7W!XiOxEKSNvs7e#R!lTEiThBAwcQV z#lgq+EEPUgb@}#MdjW#B&AZn&@@8-PSco;|i#ci=YZi_gWeFY5OfPVi8&CNC7VP=* z`5VXH>H@T-IOo>o>+vX-BAlJyP)Gj~?5+8uxZwqH|BJ;UucgM?O&iP?7-o_*LoRg8 zg_2;kgwpdi7+5htqp3c8#^Tytlf#pgOYA#fy#=KuG;=p2(DLE}7lIr5J>X;A)BajV zTx6`aFOzx#Uj&a}uOk|26BNrpOp!fIQ7<0Zs5z8rOOiRB!IBBkIc#}}5VuDXD{h0t z_8_%~z9-w`>sjhI!5^Z9h1wFF;PN728t0j^SkdQv8_~ynvuuu8S>AHU=+;{=?<{R_ zQ&iKvwGJyDf7474%<-5wy0i~2^4Pj$0D$;hRncBg*B;bLxR|3i$k1PBYx>9_AezIf zK;Li9R>VZ)0U(C{g?sg8t>}f5aSN<)eaFW(yT_%M*+@IGAKalaTslNWAm@mCY}K>0 zH1^?Em+_r6W~8~*WTT^${L(U+1-2q#ooK5yK-78bosZwYrfPeo5pwW3(8 z6@Gi)($8gkC3x91ST8jNxTb|IEyI1=qvnGSDJAMJ7Jm>Tvld*;{4mU1mb$&4iG^q6v+L0@c4C3myaW4z!wx8+GE z(o|$dse6_|N#9HMQ6lu!a@}JLV_-Y*!h*wmUu8KQeb=$AfyYw+&PcwINc6D(6_xz| zkF@U$YN~zv^ie@UP^n5)AfX2(^r}E8NhpR+0w|qOr72ydNCy*0=qQi?383^)RjPze zXi}wDL7D{+pXJ})-JRKYXJ__&$Yk#G<;*G9T=(^B$+lPhiW8T1&KzRtpr!BC&Zb2m z<$EI8jLB`?w5h{`h*r)%#%-#@gcG!k8sF>9R-K8R@q4CmCts|Us5=x!&!L&Sar7iT zU+hDV>W=DzdK;X;JAp zP^6IH*phd(mA6!Ui8PifZN4I&IAzz|MV29{lAx`Q-3fxz++$<~;X!1!w@y}Tfo@Fw z_h1#}CkYIMFN00L086*-HtlP}7tjyN+n$8FA|!Oh9@Kg_qLb61%DT93faAviMTG@{ zr*clm1{$W(hFZbPxnSt~xtDr%nM;@Q?C8wqe^e|PJJ)jZW_pZS=X6-~rNs=PTUir( zFM{yA!G(S^W`+ZVp^^NEaG?@pT8O*{)PpnD_e*c|Q_+Wae%yKV|04)waz8peO=bD6 zz4_TE%rrBO?)PyxHHk4xF0npxhLCxASG=Qq_whp0{hUP#+3(Zu4#0nHL}e9~JSN`^ zc%nv>7XR4u{QS>A+w=Vo->MT9Czn;s4?RCyu9?P$+e8CA=3z!BSII|o%E*EJWHJ{=&lj(g+ z(uKoo&Mb>*Nwx^plgZ^avryL858MzG7#4)un<#g`%^%-)B1BRhqda|q0vnHW$vk?m zqWSY-w(-?T^&5PA2;<49(7}C|W8}fYZ);d~Ibql9cFLQ+Nb89t-5SkIi}|+CrK1mX z!7WBRN;_=FQ@HSf{M9roch_y@eg11F|Csd*6szDI;t3; z{Ak#)%uNJP82cGLEESsPE3YzW^#>~RCGYQZJ2$dI<;8}k5^g3*)|?rw!sPhXoFygw z4go6|okElX-Fb|%lUg_HTWIOHvabO$ZTX-;2lW{BSjf6&XByuGPYv{y4XpWTaOmq( zHeUOvmyrgV)-}DwiA6Gt&lI#qwVO#+%z)j!)C2Qax1fTCl|1sH1?)Wbx6mI0F z@l~H6iLDQr7vCLR-GDQx#&-&jG>HF{MRsn9v%*-obmPvAdU9nx>PKql>~Je2U5eta zJp(cSlHYVNxrM^SjWrRfjQvAZgOx8?Fr`D!HxyMdZhU!)Z;SMu<|xIgRc+s&7qn(j zKGO5no3@B>idq{-bt(RU^jKWpc!%Ik?pKEkXI2gZ2`y1DK~Q$A|7{LMU&=v;%ILkT zzJ5}yvl1^C3#P9R8qmUIZh@!t;BLT2r;f@fSK*;F5nuR4+1taUT^DLLUsRE4qC2k) zHBX-Nv<))I(_vv!y2`f``us00{-v`kJ9kcQr9Xk$fW3IybrvCTvDN{qTc1Fa|L=P4 z|8CvEXz<;r)<_nz)@`pia(LitirCTj<5ufM{|!u)wW7TufCYG~|FYb~qkSL*WF;>p)_ z68-WUUkn;>V~nPF^cLCTj+=I5OTM3XH&4sl;Edzqhg>mV`EtKuO|Q-{d0Wbzuoag< zOpTKr=>WL>StpS8_qpz`X~&YdxhwCuUm*y0BZLQ6 zFzW|NFeAG0a`6xoL5-)@!y7^<0WYA)IxMlr3&#i*A#k{BU91XzoM@dDQCdO4Qa6BrMeM^MmhF=c{~tCI z>N=_0;(6K<&yW3U+p>|QN3+-hr`*5Kf#;x?C`3h0o}zSr{RR?Pv{rtRmWjxz(;t+= z%X98v+!OdpDyQw0S*HyM*fc@~1OiUR$!;1r#o$MB#l_I8#@|kC!>l&LjH6Br%*D3G zW!}mNPgL|WcFlOMaZ3unE4C{WA)(T-A73Bv+x3 z%RP|Qn$(N<4~{zNsNym7lr-T}fbarmn-5*mpPcIr&o9u_AGbJceNcR7`6~tg+Vc1x zT#|ER?!RZg?Zo|A;+XiH{kW|{(&yDJu{@}jtDq!FY@l7>HeR6Zy{F}WcqKK>d}mKpgwioX^@Z~DdH8S zNIR$QlK}tnl#%1$FrykY`|Pt5gE?6lmY8o#8>IZ29IIX{Kk zS3l|(!$m_*B7M(d<{v?6qBUf0UIQuKK(v4Nr~x6B5ZXRy5ZO9kzi?@yZUd#@oD1rc zE5&!r{rbRUXxN8DnKxQ+#P;{DT!7UWLz>x|WCma04Fm10cMt1GNMQ4S&A(L!hXB^44rDsDbnlpz^^kJm|VH~)Rymdm$f8k%B1Hj*YH zyX7GD?2=T2fV9DDvm}O^YCZ&Zp)R5ojpm&3kGoO?2o%o=GOt6K_Q5 zg!t9_bIHcCTBERn;KlJ=I_}g|@Rt{S@&gnXeQT0`pf}W3HV5VCrs^@rXVYc@p(aSB zS7*7svoeD{Ew4yhtP5w9Yil(thQ)BOTk3!G6dgBwlw(3be|DX+xnOoEBlWSk!9)wp zKqAa#7PbPmF4wvEJo1mLtG((Ubx$gtW9=0LiX2Xr^y1OgF3MGUaFvZ0s+;Pf+bZ+@ za+!EbeeVD-J}zR5jA;w7Y7(6x6%JuA3xYAMc!ikYi%mv+2lH_h4?U3HA`L zm1ywSHLR$VNLX?YR3m>P_=}oyn{v*00WN>dM-L%@ib6*BJK=S%HN|{3@|m3AS;P4L z8W!{ojTm#X;J0{1w(kjm!rG@%X1+G1`*D^zr(_PLw^vzI3vaL8#@BQsSjt5RA&LIS zc3GrK1Km`4th39ez*?%^9zU=%Yq1_Y=5Qu9*V9C4K8OGiff0hM0viR4jD(iz(;0^}uCB&{cc;aS zliUD+*d*QNQ-_4nEjgsY6Al}4&RUNRkSfA3wvtwl@9w4Bl75(P`Ynj{_SmAyol7}k zP#@QDEm%xJAxH>-*?5$o$Y|PjhEQrcsVd$o>rAHJhk+(%@*d@|cb++r1@7+ub{ZCF#T( zu|X$#UaRA}`b|<X8MQSHoC7YzQ@GlNB6?%}aRq^3 z8C53Qj_0 z0+Gv|%S<(~f$Pg7Va6#ubUK-BN#%$V3PYUl^{x0JXbYF;n?c1Rn4my@+n&J6w2!ms z$Y00t*N>hN&pH%~H{QGX=kwlQb3s>8_nt6!PYUjur~MMP#q_Jx=CRR#cOsiR%_OEl z&|t6{!BJMiEYRPTDEwxJl!|-+>w1zo{~<0ptTg}`+E6PjObu|gXLk}{H1FUl^rBPW z5=&=}mh;^lc~#^NLyLR%1uA!7Zp`+{j*LUSR_FT_mOku>JcGqSft*WI>d7LUU&>%D ze3X%=76`hmV15yp?uLO*nRnO40RDxy_Zu=P%VR{C7ay7hrj^h$=dGn^b+9dsMveih zo72fQC~1|&Q9TV3>T-gxtm~L-Kt?IX=qZwBZK4zSDJu00`XkPm2&+A-hC|jScT>z;u9$sMfI8Rz zf>J=6j5ZhGI-zs0`>DeJ~*GJdAEZ=e4$S8C3j^u6Z$P8C0!*tQ z50OZHCFUa58g@qrT87ruUr;(_do7vX*W*-NXmwmbv!o+ZV3rHqM@^gmEhI=yc8wZ; z=e9|z+N|YfxSvRy)xRO<1?ntDO9XjrSt+I8E9Dj* zIO3pYh)Q91$})9>XDNYB9)l#1D|<@eFMfDG<8Nfqc>6Tw6cd!h#@^3WS`B;ZreT6(JBn+Fp&zb2q~{yHC-p1gtWEoW zKK?aB;5K;=YtagLrvAFh{``K{igKhn3ZS!PAO;=yit*^inUM)3c%%lNZA4Nd-jrLziH~!t7n_l>sVpg zC5Eg3!1Qmcv2xRWE6F@bSF{)pRApbq;htBf(5gOF;k;~*n*6AzX>i1<*m7zzmY97^AL7%z8=}MGVEFaDo0*lf zTcrNuC2iNAY;is2g&PB{`5$LV#zp<<=9xwYTyc^$Q|RqX2Qet7?C^=_93W86e?tM( zu9+RBXNuGJ1}4eY7lJ<-F07MJpn;z#3%p`bE4h}CKZe+I7cwjEsq97yzFK3H8UIDMOXyule5XZkYpg$=PrS*Zvu8Wh_MT*t```t`uk+ z(XXuiCgd7VhtLmZq*H=1EDIf9Mhy*+?!BpF4jYo0aj6cRGDYR>lMq?u4{m7389lXL zN(hp2Z)O9rukUP3DXWjb<&3@C#Ig@sa~#Z(ZQ{1Ri{E5jAJ@9HJt>CdnQTe6Jjffl zMvRXve?vp7VgM<0_0a_zM2g35=;IBnu&aE*u+IjgPk(VPS%w;G%XTBch&VOd(V#_GfVf)BI4Jv!W;!x974R%fraJde zbU{X~_)KE0Xuk`Wu$#xX1L@_2ShtrHzbDSd3(?hDExQLcLJQa!ST5Z_-MBX8Gl|2ZVi> zOR(@+_9ND6OE`RZ5jI4zHT1FTM*)%Uvr7 zd4gY{(?|+ytC_32S(hyRev70WnUb#ul7GEQP6ieJ<(KE3#3#?2`zzTHIJyFc?1bPSrYM9?j8NyDbN z%qRu$l`vaXNXSl|!n9|+oLGXiy|C%2pFPoDpWXz_F{>1K(Zu=OW}oDg41L!NGRk+{ ztZ<4DoDnO3jF6IhL2sa()1mU7v9=o(2vjWlhvnW0lUp(8+p;EAk>wrPcloqR&p)?z z19%!=HYNAV^U1gc$r{Qo8qrVJf3|B)3NSk{R@wP|B5wLrrn#RUJ^1BCt$090b$QEzuUK1rcS zaSs%arB^62`e}2om3=DqB`sQ^* zgq)T~ZKiOQ8>aAjB!zSON?kQ3`vqzjn$NuS(DBMyy2DbIIPC)$0vtcNj)$R%YJbXo zmr#yegS{cswjfQ_2X%t_NoXg*(^yU+B)yExpenkF%N|u)gx+G~5!u zC$q2(SgxCYxDDgbWIpvXb&|=yY9~Xo#qi_f^-~^26ifR~DHs^Ap9J)jtNTqYzM6>= zx<6VdL**a&SaW*VQgcv`lOPivk96}zLLR?tWQJy0-`wRV^FU6@dowcDVb_3_y3PBj zn4U`vLu)9r;I#29&tr3#iO;OaD;#)=|n=$4o z68=^{2|oLe#SaRH$QDNt|nbC?MK8FXZBwb#VNUxotAP4eWJvmty99{)4F@WMNj4eZ1-HB0!z{cE~9k(poS53eSP5xxCd z+ZKHd+C$QOjDPW$C~!O>X=OFYo=>o_bJKvB%$@IUpayd6T>9eKL;OU9EH|ceAqfP+ z7Pj^)6*FI<4D>QBF`an$g299UXy#`Nj|th z)mtj8on5JBKP69?+?aANhxtm?e9O%R^DEM#o}i1=&CI1^u^{D#qCXy`WY~(QN8882 zir{Y%Jjo4U1mCiPkfr_xzf8`V_9pN?ah$6GZNYIhi=16KLiQE62Jk2Q<>a-39>9O{ zVeX`pis6CN#=1|=!LtMZsN26r*qo!SU#$3~~wa_iBTB`i06UlDKd`ShUy zmDN1Ky5_Yuva3giU+9t#vdAW-zyayCmrKq+ni%KwE%yX-rph`umvn@Nfu&qiZ|z(8 zhi`bz)hf6*r}zzJZlvDceubs#!8KLEq0Qt`wA>~eos_3izf8O{#H*Oz zQb;W-LdAs%v_{3`Y&fY%uk)^uQG2=5w`Wll-Q<1wdyE0p z(G4^4fb#NUE#wGrtb0fntKTao8Hl=Uw_v;Z7Fv~WNI`cji(PSYdzR#ekCYJ_{3IA4Q#-W~c5sNR7b9GU<1SzxnRvPJCQkiCW#t5#r?x-!k6tPZy zRX5rxr-R^m`u92dQ3=br-|y-t=Z{PM1`}!Shw`^S31dB*ZY!UpSjO!Z%FTb$nhK30KO#Nt#g!5M_Rd(7$q_38nLTVSI+AB8rk}Llx{78Tm-Hb zS!+y+{{+7L2jMZNJ0LZ3HgdC%;hrQ<$yJ3<8m}N;TWq{h{E&4>$&CXwwVXdvSQZ(V zdqPf0nRaQ$oDQyiqD(R0J$JpB@E=x4<=!ojdgb?jXtMqyPaHLTnPofe67CRsxVrYt z-{|Mf?6V91s}L2?g*LW!a*kn*1S7l!w1~z#a?^Vf(q~V?F*|r9NeGf<@n+ZRM&mwv zBZN?g1L;Jz8C%J)!#Jp-prX zDwGu&xAD*1cp-1m>;;cFK>+%3K>Df__Bc2IGd~uoHhG<*JIu|E*t&)py9ZAlM=0voYq5L)PPsNa;YNfk zU<~4qD_>vo8Ws^>NZ?N3FRD@YP=(48VylprpH{{EGI3AL8enIxS=_Phv49@eDU+9k zrN^V$h;;SIXdO3~{@ z;J)8ybvXHLFUDZ}OA_yRDim`gDzr;>`==v9N%-woF5g8d@HE&i6_r#nft?(ZF{m}V zQRUTs%b{R>_LhkiLPh1_Gp7#{y!w<5)BVcYt4C)jw2 zwrMPsKZ5==?U8gDtjd+SY-;7RxlFBEXvgcBc3soxN|Jzb9)MRl8)Yv|Rgur!Qit~E z0;%+gTr0YfAJe9gW^j^fF;)tbzm8{c9|buj0I2& zywspe@rmPcZX631dMC#XaguF8PKN`Sxm ztg#G~#hTcg0f7{x7A*-1Ck-PwuLNBkf09g|^7fp*qnhRX!ojI<%qAC{rfrhgH0mXF z|D4*T*8k;O{eP2pT~CjG&A(^@=FSw%Hg;Jp>guZGFT=db{`crBntQRyt7i5a0^}wq z3Z;&3nMwg-(f;BGSCI3t~rc-!3>AxWBm8yS^nf|+XQ5$b4^K$o8T0HEpR#> z&S>D9gAP4Jg2U9g4moEFEmhu!I{Q56(RXE)3YlyPV02PXIxkZ(YQi%tf-M*ZF>x(d zXoY9Cc5GVL@TniXl{WGW){DS;o2IQT--yid^S;r2u&5U>o`D@nmW8;(Om)ygvzP~^ zGo?ENF|23qz^y@s1sb=h+G)j#GOMl83d+Vu2_G`uS`^Yd?8v);2V=!iz2+%a<@--> zhK=Tk3>_ON?xy8oT98E)GXnMb=IF~W9@BCnK`eOs$e+=Tolx1IrT&M82rM*O9cz`j zBkAZdQ!7VvWpiVaPsg{ze8dp*xCog!pn31=rPVWQrA93ayUk)7dZ=( zkqi`uSf2|1ea^H=lsyyFMK-^!g{=~T8#Ski9<0mov?%Q_oc1kE9vpof^ch;1VW-?4 z<)L|MS6XkVV-MpUy_l@6U&d4X&9>Noq`@IvNbUmg(LEp_5mF=h9%fskgAK`>3LdzuXcDEIa|&WUR)d+)vPlacJk6}wxH<*XisUSIgR0zQ>;sd znMZ+?>6rY2ePc^ObIdJ;`#(O>kN((Zkmb-%tNRkVycg|YiOa++*Es|+9D7cCk8y`h z1vpl|# zr;OiX{G}RyJG0P%sUGod!>VgI;>>w+`B(`em&pxc8ff-EmLe_9&Zo@OL+5hTiwn( zR@m>r&W56>CTm-&@D>SKGNzb{O-b{a1+E|OGBj6N zXL2L1EomDs%G_G8_9=H^Uxs0*r>Vq*u=i~#zq7e-Al4N_i;wSrZGggnwU&_ zk~?`aRV`!sg=6`QY%nXz%&nM}(OUKPva%lSY-a5jg<559aZo|VC<}fkNr|`Exz@W3 zg`UVK4wNf|eol^4-h|8Rqn>oQUBPiw9K79IgN~(Ud=3WWaH?rmyk+{5q_*a&;N+ab zJRuizRqCC&j!WthRA$N{Bw}sZpr}Fmq`c{c6#p}wG*&AaK{ej92qZzLt)6LTg6U89 znq@;dRyoF3SX(0>2O&>oH$rP<5$Ew>u@il3XDqECTRgw{YK6xO0+U(C2DC&gvH080>DRMu9?Q2r4( z;;p=gSPT$Ue+onfD*%35r zR4MYB^+G15E*MoAF-vh>AM&y^J#l`myht9&P(APi&J_?utp9OVSQdg zHUZ}`y{7(6A1PDvc-qfkM&44D1&d3>B&|=VT{V*qxH;x(*s8Hk*5rr2Nhwr`c9oz$ z=lHV?dMiaadXi1jtYLqDH;1*6>7d!=wf_)$JKvAI>yVEgf#n2=0YwNc=k(mSw`YJnycPzI>FqSo%b zzki+^IINjzWW8P+ct=ZPowTf)s&PvrW12X&@!e6G?D%<~MyuiUD8m)Jjr@3D;kh~5 z0!%R9V&5nOMr)d*!1r==F84p|uq&`dCuxA6r@$v1ccy_E`dqq#UoHa<#>{%+RZ zJ3xE$|IzCeU?@wr{|--o0N+eja<((9HfXEl-{3W^WM(7H~WFIF$b^Rbi*TErkvDb817RiLK?4$PmQ9aSFV`$%Nc^S+j zwnqYPPi@ZQYYT{0FF5pCMRUW%x}LfS1LpgZ)Wrd9VGT@@Rp~qkF=5+CmWR(}p8qdh z$Upx6n+k@j@7I6%JLod7YLod2^Z*kl_fJZg*eWENYv*HzhZT zpE9;w2Q|1JLH}!9>t<=lHX5HAH$(cC83K{t`Hyf(1r_#n#pyr7rFMB}JqxF-5T!%_Z z{u{_7KF&kZ>-tziIMZ>NctU~+n-JH!;w09z41YIFu<7H9unl+&O|2#2WU$E5y-4Uf z%l2f%TK8yC^Y&60HNcAtvB5Z27nS#kZwd|!uFxWycDmtkf1kU@^ZTm*n7miX?7_a* zc;LNMW6}rEjig>?sZza+6rh+Ve*}oH9o~}o;a&REma}43)}Li z)7;44=ceu)elBKYLyVr#m}{^B?<6EF2z?&OX3|sJ-~C4gXcATH{yjcG<_AmWHFI z{kHcm%Zbm}t4e`KhbhG2N`O7B_MN3oKU6%J{M*}FS~>9C8n4U%Stk;fqD$5*QWAIY zApMXgK;>BY!IoV8z-)M&ujfk8@JC;rFZGft1-aZrROUmXY2uIM)-Y#!&g!OqN6wJ6qfq^pS$x98#kwzU zOXajUhT*Y~p|5bkXIcl>_@dpX!t6f)Z`}`$`&52qhr^1JP7RP_4+3$06}iTsk&aGIK3TU{ zNvSUo9!f>LeiM~9@S!(K8(Ca#FWb+3rbDOVpS;?QlT@tMy z))R|c)2dT$p%?TCzu8XqZwH;v)?CPAp%w0hOY<1eV2M=N8O2_P?xzWSa7wGKsOrxr zNW=Q|(!PrL?1aU#dPA{tLBJi}p2556j+t)C4CNQAq81d@q9CHp(qr6lXoCc)T&q-8 zEphm}5fo4??JzU*EB^zZk&j=ipEn4%-uKfm`s%mL|JyH-+$5)l=^HN_gH0cdejq{$ zgrFGA4)~Vt?V3QtNJGkc<+6!eLJSE_G>xlLT&@-bv6=hje7zx2_bbV}i3^V&*{pgv zg};3pUu6WvWP0$B+&(DYeFrM+8IN)>fEpUnrFKD_C>AzuIhlqdE+%QuPGqj@S%q~t zi{GHHT3lev)puchVfgpCj8|v6eH$Sm=&c!NmMPP1$#M(C@Hvy6-r?RSR=V006iI|@ zyv<2mBW%@Ct?PrBFG#_C1K!Dnb5$P3xbq_)2f|nE~!Me`1V;Nq%GflKbMDT#(w>7xU? zk>?g=(`3+yp|5oy&E9RSppHPm)*SZ=e#8+U0-^U13D+UZ$LCXQ7g*(#OO_cu`AeJK(!+5;JKajiuLD8X1->|8!g3%M>D>z(i?ji zAwz*;gORh?93;dkDf2V%msmZ)%wcq6#A$DWm>29BZ;v&9_`tm!rY@8~6y9xWgqnBYftc?rq*_#TZL^&7F8awtiV2@6=&y)sFOhw<>kOQJ43kv5zTd@BS(td$JUn?}Y zraZ~Yblfno=dyNoZ;c0DUPv!~2}70fW{kS^#ezssj94Ak^HXakf99I=*W(zy;y&km zx;P&^+-aGW<}~DlvFnKOd+GR3zUl3**RLOz#MG8*GnzB)TD5vh|Ft{oku#PxQv5+z zCFD|mx4`Hd(_fBGlXtxs!!+ur>V^esid0A=N7@vX&c@vjq#rG|ATR`qE$VSHteWv> zO$tqNI$k=#uPp$2KCT0=o#e%FavWs=t*nHVSO!<&}zmJm0drk%?ssCJ@b z?N+yIiO)39ag^m}ET|S1C*Pp+C2@jjbp`ri5@_MvY3V*?an>{eF%1^rKj}pS+za+R zRf3!Aa<%tgZOFzg_XKdseCiokSgmfSW6cDOb1=R+wnCx;#vi1@oeOt;gVt7g(trFu zdXZMG3;WBm>YHdf5|HCswI~+-Xc!1c1+O9={k&O4bVV$PLtnpXJCB|Z=9q4q&>rNg z|29fy5yF4sPFw)q5y=&wtVz_JnK(qs!BZDT#N{%nAd#EJ@`hqnf1fK!?7d)jG7eC2 zBDWZ_e`fSQL`4f+Odo&mi1lkedMQOR)JZG8!WxbkO@5+Sv<_>VJM(;IZ;@i#gYF(-P~SrnwUA^n;NPPFgubJ9{u z%YWGOyD}Cn3&vJWrV+$|o7+UhNJ^S>IjD260ygG7P$diS_ z2HI5RVp&PG zwlN$ML#7j%Q1EML9)5uhkL}AgjK7d!6CfVl8mvtb!%dWwiHr3rNgF7S&39KWu;AsB z@|Yy{b4$lPC&xI#+VDJRB};No6QCUyAlMQCtQASVV`G3?JdA5`s;wyL1@8i>g!# zKM#Tp6}FkC-qVOT>uh5)&FUdltOo=)txMKF=7v$L*Htq;S-m5=oMz~h7e3fMu+s<* zW!MOJ?kZ%xf^=Iolxc=M2(%`QyL2UXDi@76z%&|{&;a=YRo9Y(ihU_5)z}%3%M02$ zKiyx}#i_Jm#yG1S1V0LF#+6o*IjqW!qu6;!hrSsrm=KdD-@Q@HcgRW$kK_!!% zsan4HXgOgd*?`o&!UZT-b#Oji!>qn&<8^Cuku{AkLncD76X&%c>3u1RV8gKU+p`;S z^4?POik`3Aa_vqcDn?74SMgMJv?t*cG{=|fVLls4(S1DUbd{TPvZT78sx`gLv6WxCD?{T)#y3|E0IY`1m$he+yxmzKl>=gxX%MG)* zAEzzuwMgJq>#8fxt(A>?1+TzRvMzR7Xgtb487^EcgK*(tdYJ?7YEoN&AXor)5!b@J zMq<)1Z>kB}xvk^u9V)wX+C$?5A*MYoUn1h(e`|FuwesI2tn{P`65xpCp_y7DKb4=p z-+3a^9Q|_kiNj^b8e@c`*xOmYMbLX7Jmk?DcZtxvZLKW0L3lQ%dbo#LC0k1q*(7 z)v}QX&9Wm%+%;t!0wBq*AC`b1u{btQJh-q2w;{784XJwz`>w$>=xchTpdKdIA#6}Q z1(uvYO!1!4>aX;h5RbR_tD4^fN>V?&*%_!0JNzk}K4XT;rx~w^W=}TRrqKRmSG^r} z8%}HXZesEZq2vNC$*aV#h|)b)TozuBs+QA{Pn-p?WO8k|@XnssNkzUh-=ZO->dQ<% z%cnUnITJzRl9`;>0@uq^-75(i*^ZCKarDhv?_3doaC6}Tp^V2(8sU<@~u6HbRO~ed2 znt;hZ&13^LC>E!gj7~l1aJ@tG_!Lc(i|OAuW?NgES+1kAXBMwTuAq~&O)8eSuWC~1 z*Vg|&H}V?yld+S6fSXyeEm7XVoCkeGxA1WpI{^}gUr6=6IBr=63CGxMlQN=C1nBd? zLM8VXf{ySRiA)GGSu$KO%$baNw713Z{;95T3-pG@QO~^3WZJmNsidlmp;W<}Upjld>VggfXfuaFZ=Bb8yo&cC1JYz8UL+rZ2BxjQ`=ZQa~o2}If zTy&!+g%-%l!ObjOv~_hb8o^+a?)5bi{Xb>st(@rt$Sqatn&891ted@Mhb83x`J6$bQz|aKDw;? zF!-)YF1V)-ZGr%2YZP^+C9XG)`V+N(VwiB*I&=B)UO!vIDmA=+ps_&hQXvnvsBV zYzM*9itwA4^Y_*1^9lOJq*{$g?z7Ax(@4)M!+4oo)Zh9|6VB)`_i=gc-lO(bb%A3W)^P%Q~m4>938RG$NzzH&a#2k7M5 znTsD3)ZsG3_VU}42?l_}hpAf}AAg?+NRK=KjL9C|e0u|ClrTJYrXTck-T6`x)SP`L z7O3Z`{Z6N4267UL%Va~&3T}QKi2ar_L^2kH#-FN7UsMwhlS$Yh{Uy>j3)uybPnDw`3*N2)A&NxAuW8AQn9Lx?Ol z}$^?HC@J0WE-^(Qszye-3n}*(QAIp5IGI$WPaYx^i3CzMG@?@ zN`*>#eRf#kjDhD@6uBP$8bY2``gX?%^;R>BF{MoRD$-{^#x=p$j5w*S@2VEDLh*Yu zZn9Nn>l+?tHgLmMraCK+U3|6*Yrac!(DB_fxJV$ryF{P(wd=IK!2&d;76dA))sIsG z` zP$&x^;UYw0$I84nl^4H4pGA^#F&IhC1qKhE`}WSVUjac5B&zp(y_`JS4^J*(nBWIH zr+RzucCWJ8M0$L*cezC2=AEcda*|v7)ixf@<@hRR<>uk_?M|+Ugw8kudl<9rJN~Q5 z(uw|$G$2);8E0LdII~<_bgD>pG8Vyguy&pz*Z3!p6~``a)eA~P!X;XsGLl^6{Bpn$ z;_aC`7b^>3Q>b7%@N0T9W&87Yk`sIOwk$qu1e{;9(cN8e?aO4yt4JtNCjIlcucYFc-cgVy9ei z;K&_ZVU2%J*gMT)jc{H@$j!Z5lFGdvM6rkRv^DNsk8Jz%Ne@b7$C*Z9GG59iH5C2@ zllas?;n$a&Fgf)(i%wTl1&Q;`Y`;C±u=D|gpuc6zac{Z(54LgA=x zy>niVt#$Ft+uz}KUqgrm_!Xeu8(wfMArr8$z8*HEa_QcD)d&52lQo39FS6Ju3D_x- zRBw&`GiwpFLYxwYU({8iMjpY2pD`vARk$?eY~_0T&eRyZWPbpU4_eh z64mbMEM3GusWi52QE2`)#22y_w-t!r=SBYbB!`zKJOi9@D#X%N?tXdgBc~~BIAiR9 z7jiK6+Dd@moNT)AUTU&HNlzTP@c?HiMAeZ`uy|cvFEDMYXL=BM6~~a_TrT5O7mFdD zy^s;Z>>n<59e$fPpMEIy=>krCq7Zkgtfb+Rz#(Eq8U|gkP45}*lG)(c5|h=QVZYG8 zAJ;iz7>G47&%JPZ=M=>h9=W_8>SU}~s{CEZ+{+b@DK1nypNp8EN97h@p9e%C;Qr>(0=BgZM znKoob|LDGQ8qH@zlC6(rgHx8~Qn=ZD%Emui*cCA!8G%vWFYU3D-3 zRit4nf+W9guu%n}EG&-_e6A?y_OZ&aE-zb4^3=dz#7BkMap-_a8vwxI9m(HplTD8! z78uioLCCS_9_fvWz^d=beaS|;PGM3w)R; z7p$gS%@#kFubX)b5KK7>A%+h*FleG)OYE#pHl(W*4tifq8T=mNRG%gWv!NQ6$_QIK zX0xvjjd(7!O&3IhC6{d!_3Ac2UHR4g`SeMo07GB{6X7#9_#V(PQ0N{s;p-L6+2Wd_ zH^X9k)5dWyxCap6tc$%@?>W9Mo3#b1wkp=n8F5Jy_(63{J#<7jrFrH-xr(_$ZplP+ z=?&i~kMr^b#E_Lz(t2QF;wM z+|8@<%;)*c=j-|2w!2xUbtS^!8$b+ysaN|N=K%dH15_$f2U@rGK1xJ|6>Hum6>-D- z5yb9ip0kQxz*l$9Gz|A%lbX<|qEEg&0b*D8fXF?nXLxxuWN=*E=gD$Cms{X5*GKwt zokGTpHd~T@5;IQp75vpE3R?1$Q@_`>*C(zK9iT{r%Rdj*q*e8>!=$jPDR1uov(f$M z&js#3VfP$60v;tUHbduJRT((`1%Q1y%Z}j2(OGbWGxc)Lw5hGgecKTL{>R_9+yQ{m zC;t!j-aD$PX8#+-ib_$c(xn6pP3avTI!P!J0!k;7}s{V!|pJ+o(K&rD{%^CCXW&#;>C4>i;r>kcp(e&&vPm#)W4qKqa6K4ZXMa^rTEVAKa2?N8J01 z-9QCy5S1{JeVz%H#Mc?q8pdOqUCVQ=8ic7KA9RF0{S2(t;}vh*n1)02ONg{5VJQG6 z+9pPy+rRFZt$GEZQh1_iCnW}C=adWpD@nL&l$aR4R6Ej-jM`>k`4~^qV z2f2)(skQ4Gre|}qvTY`XO8Hs74-!5a4+bk*8k6Z)hzqQ$gT5m(5YkCgm5qbM^?GGb zq^%wPz$5HM^?2~*llMO&7&g(NMbs);M`!YF_CqOJSQxN@is5Z*pqG4cS)DzeYZ2Go z=aIv8=^aX9(T4vfTX>AyT(7@fvZa_sON#mE`~mmn8XN;1A;^FsO^)+ z^h>rF!i-7rh?m3-8ZH)^k(mZW4LOKS&O50Z+jt>g)CfCN_ax?jXT0y%WP{EgYM{}HA7CrE-^aI%Pfl%)1S(bR?o^~v`HHT zx_*JVid&H%s@I9V&X3ydi@F$QA*7h7lVYsy;G%l~zcrz3$O6Fk9!aH0BmB{9{|^(! zlkOj|EM4q(=07n2HME&XTEkcy>TJ8Y|yX7oET zoz1DaY_DQFc7m0?_p(KOnV6$4%|dB+EWgg3;^~IFSl*Slb)9zTG3UF;eUVRp!p)1? zf|V={=P-O3?Kv|MUT(eHo>3bZk@LOw)bt}2M!4p8s$aDB;6zBcN=y;#A|$#PBR6v0 zy5v z+8Pvd#Tv(oWa@Hjz|mC(Ld#HCP!)9tZo^7i?|QN-oHL@h!)arb@Xa^I#$;A{7QMvd&#ZM zE@AU8S;Kn{A+Vo> z+fbizr_@K+@@g)e$LtfcM_NfD%)R+Ht}C!J(>beJf7%8}j^4hb?8}#sV9}lC0vj&M z0Q6r3<~`fiTeq(*4vPDhIQ~Xfwq#;1ut!Oiz6x$Ar+_|@A*B2v!4%Fn}_Uj8uq||dVo7nXb@5%$kYbtqo~!e#9!mzps+Nhzm?_!Llj@5Q_ibvaqd ze#MUI`OkddU-SjdryCo__Rm%w;~EpeR5efSzjQ zD61=Un&Ad)aSIMzs`;xu{}HLVLYuSEJw>6LtBabXP!{rlg@T^MFWtHL^?K?L=W2XR zbf|Mm61=@Zy?)ndlAd_0T*W%j+@|uFLyTKIFGJ>lbRayWpvn<(P8(fB-b$V{ZN8lmkHxeX%Bx@n^~@$vg}=hEDufj z?uLg$ww2(o#&*JqAZ&F2&)|+8_7V&WE&?U{%6!fZE%-Ba0X-+_d<>j2r*_&Af}}o_ zcv76M9q+zi?0F#eVUxijsCbnhEk1BZN+6j{P~5gSM8et}#d$$?#SB_u+Zq)9%q>sH zKR@q_^w^}(V0UyPNH zrbXg~DSUDMuBYjITWj@#mN{5YQ;Acp^3@sL2%j>pRHoC4YceD!cL~JP|Lc?Su1DxM z62i7bzj|l2y8OmRD6o!!Gn&529%U!bNDmU_QizZx)H{!_f7&;A`62sG>JepgTW?7& zh}~y@fMZFRjH@+Xvn>fb0`IY$uH9~IkK`zB0tySh^`8~+Y@@f43E$vnmHj!u*uzf@ zb;bI#I%NvDMc(Cm&sP*m>|I&>Q&Xr^`o?Vua+Zq83J;R}KzS-3TWXYTFRQ8z5)y&0 zZ(@!*d!>%VZX_^wK!OvKt{2X7+OHy;VKjx6Nt&I=@BnvsujZ?pJh` z=~sv*ODeZdeq9Al|CGo(@vzGAzIVd|v!}n|^A@`c@oU*2r(FRF54Kyexu==ry5u0T zsV1SDD04A+^fBez=gg+8<9y2XUrO$ziE<(Op+%wxsC3*mNg}PPL~fjN=aj$5-XS&* zFzr8BmE2!5`xcaKMCm7j3RQ7;s=D#^QZ;dA{~{%-h7Q(pN6P-~bdG2cEp7ck28ibF zIGN%4U>Qb58oD~%R zOC$r(yyE?6IK26)YkZQmfu~p!KVpdXvRb!He@Ehhgr>xZ+*R3pxFn5T7USw{a#LWn zVV_!&DQwVjO$~VKRX@~NT;2{`=c{RA)5Z4mIuvDGmdNeQ;3^Cm2xxs zX=%@&V5!_PO-Y87-rGz|Cf6^+_53A*R=l+hCG`}m7^)sj>SpN4P>f#%$(Wq?)n+_q zTOe&mU%j9MG=U=r2_a{;m~pemI4{gs?PLD-ZTX+=A>zeO%MAa zp3K(JJEikNuchQ`+_TC6jx6Fd;buY$tgUXQr9@jQ-QGV>Px@mtG;YW(nS^sB2e%iM z==>G4OZ9_eqdS*z>Sy{lZboOZoegLWnX{ja)wGsW3 zbH<>OT`N6Y=0gQyG>uu%V+j7x~q*izBf*Z%EcYVaagCYCS2fZhv%hRmV2Y;jFt9v8Bl@Yd@;EV!>F+ ztb2+|@e<$7!PI3tPL*ebC#*HV9a5v~?ja=^H8k=j#*hT;6e+5JK4~y;FGDom+jXNa zE0{kMDII9 z(ZoVt2$9i*jZRqLpva>-mp}K4c0qbFun0*&yKC5k4umkToy+F~gT53`pY=xGLr$N- zl^*M{cx->DrQ!?MWBG}BuMB;PeXg=Te=2hwTtBV;1+Kj#VQIxc?lq!tlRpoH`2J|f zb(ch9%u)?Ydy{HBVf=DvTJ<62q!)kg>(2%i$oRj=RjS=*@wyRv$m>PODYRi>5or06 zN1^Fkf`31Prg-W}j(LK$W~t#GbFF3qe#hu%+Mc*nM&_PiS>qS6`#bIFYvOY`qm*Bt zb9OvDc>lHXvi@fTrooTvT!Y#$@i*Cvm+qCp7eB6(-GUBL2Z-`;HXh>=izC+lk}|4! z+JSQU!g&8L0p9=W6w(T?Xy_j41haQ+%wUa~XigPyTPp^mF_NR{Mqcn4o!kda6vG); zl+A38Yy^?C51Ndfl`%rZjumV0f=N?+l*BGdfuN0fW-)nhYD%`aS|C{>&~3%Ib^G$Nf}yc3Y**Ll(o&=~0;7FlsWo0! z{fB>9>2!FZRWT0b7puvlcAc4OOaoeo2S67}k?4uu@p{)fKhXilEk@62V>7ayGB9f5 z;SA~EH~lV)8gK~|&k)uhag0tWwqH$}EUDA=Ssp98mJ1$DuZe<0b_WRB<9EDz__0WF ze9vR`tZNL}SO=oy=3 zj*}64rh-5Hbgzqu$2_=H&H*TdiD4dp49Wd!4Uhqto1K0@=Evq_pL zY!K}?b@uwpMr%v^tv?Xu62@f*k5E|xi0Jy!wNal3LnSfhl}n?i-mON-HYb9U80Tlc zG|58zQ|Mv;G>bV)>t1C{(<%T2Z)CF22>iGnpi-k)Lv7vFYDu^+dskg0n&9%uCU9O; znFLFv>`$D&Stzur_IUiw=EV!GL5A__&KD8Gy8cG-o<$`I*ztuo$TPJ%{SG_%taKk2 z5$mQ$4#m28E6w5JzbdmqE+C#-oGy{k4Mmb5j>S1=%Oc%70z=c9wC3lb+vS{VcX*Gt zde^q^Y;?NG>3oGpwWq`v>2!6$z($fBZ=T1inG8o=TEV8uKYV*;VU{aC18rIPHhghy zr7YGj=|bG?pHU*F-(*pGv&@9Cg3Vt&FOp`J4sZY9hPNEcfBsZ)ME2-!Q;cC>jSAWQ zy&mR*7uhb8RH@Cwnf4PVqfA-MlwYkw1RoHm{&v?WHE*Jf@zU@25CWaV1jIAOzRjFw zdh|VceTe0z`6Gg~*dYJAPLm2*jIN=d^Sgpu@rb4+c|>wp%N`F!hHD4XP>BTGP=<52-9%nLnT+> zCq7t25f`>p^(pf4i3{o9q@bcH z6MoHKmFYdo7g@wnW5%QZlj@>as5g%~@hkjE73d%8F7H7f~#71&oBi1x7UVT|aT zEG!%^D#XpT%XpVPsSt>53aiOu83@1#u4J&3|0YwXEsSxzBfmpX%jPprq|gKvGqKZG zaSLTrS_X#=I(Sbqh^wRa`ZBQUGP1JYJY#v6ej;i7)!ofBs?=IvG$%VvZGJ3QQ&sy& zNmLvh;#)~~Rd2e=DA8bA(iQ7bi2gR_j^5EVz)>!N>ErBB{ypOWX(1PdQP*FALv>2; zmVWgdr3Ld>-7LdzH!yp_1;B1k5O%w!p!r1)*7eZ)K+%Q$>^I1LluCKHx_-DNCN*E`yvSU2X_ z)>QGynlG|Tf+;=v+ZSex`4(f^LU5>rg}2`L_Wzxv?KP4(kxFVnR2|vHwS@1dB^CCM zQbzc2aSO^!8FoG=rRNDgt8e@+2pPUVf;UD{m!&-cxl!b7Uv~Arv3}|K<6lq6k{$@o zkcFJ)GaPt7Wc7Jpr8MmEp5e;p>HJNZ&oO`Q8kw#9G9^Bq3w+k{=})(%UpNxDZS*IM zJQyCFxfR5Jt;*OZ^4z2NJ@U|e%koNJz{TXxKDooEY?sJiR=HNn z)%^Khc+*o;?EJ-VRmWGdU z;jl#V3sJe)<12?`HhBAoDaSj!I2#K|a>swfaP^(;7wwhNJN+>g8tH?L`*EvgLO&FZ zqS_3kHE`v(hYb52^Cr77_IGXPKm07dHldqsSKEFD*F1wLH*}2JeRXdcTfeLxs_K{( z%DA_B7YQW!RQ~9zJ!`#wj@v*Qlnh2xW^Kw1Iv~?2f6@tCcwk)Xy(jS?)BbNLQ~WG| zea{Lgo?lw*Z#PK{b`M=4ax9NLw#$6zO$#OZw$5QhXri7(Lmorq-JaKR2!-Hms1bnpV9xntfSvtr%E~YdUi{3FWo-y|5X#vikzeS7L@|8V0O^)+7Ml|T=B!`;+n`cN9+ zgoaX8Iq&r0gt&ijUJAaB(YU~ouc(M6;t`)cZlv(=9NEa9#uw)u`xHPzpc5TsGvYoB zSHA0Lzezo8?waG8#TN>{rg3fCD9%?6!D}*({yBwW2Jfn(pz+4o$B$VFTQCX%(d`Dmb?%e*$csfpu+ z=1wAIJZGyRa|sBb8p;hn8j$G{i95|~f37*tO!e;!Wu(qb z->JXApJL8~rRkQ*Zv2lUnE%~h{|uJwgL#UlinzE0vogQ_1&oeJ>zyARFO_1E-4HF* zl{#Rm+QH8W@xwKRRy@LX#3UEZ^FdgUy5V)Ff?j6x+vefPR%fvvzdMO8H4^J8+|xC7 zwaydAuolf1{QZ~Lpy+(LY8W4d?gcQ-@zi~6zMsjF)u-@+Wr z((`|aV1AM_8SbjLeIZ&)E;m2ybVREey-BH}O)IuuNhS%_jjUdF0)&^=8u-&_*K=RI z+NW>d!ytxkyzKzpHRX7#-X%0;Zx=25s1xlSh;e3sb`<8OoSh{&SC7nFr3e}hbw%5W zFiIF{*AG%C!^2xK_d#f_)A&rETxzq{OSi17(kHomM#W6b6!?@m)g0Ff6R3*@G7Y}) zBPdCKV0yj#Q)!Nv=(t$tUhjla{mMXaXa~)#g~29pfPx@wG-DD`qf_;OlrkjFeO@%X z_UXNmx)`r?F*m_4NO{7>V7-S%li=o##C=ol)pKxkgS1T*TNamavf=XQ@K);{MnS(Z zxj~l-HB?jrfTh(faaAyV!#T@iHi3Z|4A|~9&yJ!4g%RIMiVR^h(jm8pId^=oQBIN$& z6GFzG%|~1yRLd7ks=ZcRa?ZYzMyJ^dp-WDMVjWj!mpL@x_Bkn3sMvvP&U*6oV0oMD z(CyGFplpNr01r`K0PY1ZqTlv-A(I$5?+~|2WriU#@v}aHzvXbt*s5G`+IUju6kelj z{a#uqulA4S(;C|44$h&91$r5YM|(h;=cSUX;wXe#kx`a^6BWdHyWvrEyX6$y%L-cC z0Y~(>m`RvzSh^eD%IlHIYM@J~_-Sd6$Ftm^DqnqUss?`@PvvsQiz2u5)J<P2Z()=Ot%Bj2?$k@L`7m* zqvd%Q5hyMp7pYk-jVhdT&@)<_QJ)&Q(M+9`qSR zi>Fkv)8~Wy)toSH`Y$S%L@cJc@oz+1!<7jy=Mkq5TSmYOrfcrIzsc^5%_;Ri-A4?( z6>#pXQgiy`!7Aolj@Kq>8T}?(6k949a28rU_xep1ZoAL1F2R;c8p}_PM1O5|_@1XF zk=-i}ry%nFI<)ZFV%TNaxsTVmT)gtSl+G;w zULl|tlxUn6PfK_{KjC0Rk2@2~HBSYTVwr5)hMJ=??;lLEQ3BvOG`@aIzDqm^^$hBB zTvon}K|b$BR(mlm<&fIj=bWv1)L1PLK#bId1!)+RNAkO!@PaXB!j(PhrR8_Q*8C7# zE^sanDwaG%WYb7uSKD#S;yXV{0N>c&VVEDk$MXY(5%%35ehc#$IC9I`No$)DXlIsV z@($#(21(tEQ+gY%*754GRs$2s18<+3!T3~&*R+X;E~N`7b3r5g zdMQQl=WYCzP9`OA_tX_BwW`wC+0*V7s+f=r=ogkSD=COLghULWVHm_o)@*%~-D1t$@y>jdx6!-O@#lP2%}$Tm znALG^FhW&z+ED-!FDSUz+J@bk%H285wg>nE_(4*pAh(bx9brrT+-veod6I|=a*;~i zwlvR))Dz~+EFR3xc$U3*Mdy6V#3$Js?_E9?0Ps;Q!oXpquxiO_B6|u86zNtx#jWGT zFGaHPwb6WA_nf(Uw0zEkoa#QLc0!0h#%odsqU#z*_aQn%bW;bA!Hr)Q_D?*n;#Wq| znulB2mCYJB=NXlgR>k}9;!^WK#8D#orJQ6!AxVu$Hj6oLuaq00h7|y`q>O6EUTx#6 zF3&i+k&tg|YlXDg!=l^0M;Gb@OaVX;W^(#`yBFxhGB5gkbm8Jgu8W%Xb(!Ls`=UaW zYibuyM0KOOx2rW%=S;1w!vX5a@K_6c5r`x-S6HWlL*X~DI_Xlra<3=h&SE0!RpFR$ zN$)B=(dCAiqP$_4?gl79h?rJ}M z;69iJ_l8wNtzD$&(I+(4{PK(mu2yf9oRnof?M4dxMPLpH+;;)qfB<#(`Q=jqk@0=~ z*@c&R1`z`geOwStmakmLa(QPf8geFQfNwN>x;x|903Cop7p%feVP|_;PF1sDc#e3t zK1L&8L_Ifj?#(l2*?3*mr&bWREPkgZhNo^R$~1f2D&CH4561Ng`}V)Zmy7dKP_k|4Tp3sUEVq3)%YlB@~1fm7110A7eJL0-q+Gsn1WL}qm1 zTeR{{eUUx~$qo5p1oCVjLdkgc2ieUr(){>u40iB8jKBYd!FKtla}XK6sAC0MNW<|9 zAIyn`wjt>Ukg@s|U9o`YqR1I&8oQ692s-)LRBx8=h@Sc$7IyxOP`;iik_Rt-lv>IR zU`l>C9Cbu-0CB-(@Q&tW2|z(0V`e=hlSiVd#b|OrGj=I0t6?2#|CD%$tfOi?UZX=J zd6L)stbD)IeyLe_N)+Ew9abstS6TFj#1k<<6`bDf<1aUYSXw@BYYPWIB+?2?a?fz# zO`&HCVL-dCKvupWy)U#mq|84aFwB%m$ulv4v*~syyHGgUs0-X4m*`h_A;J*4i25Uj z05`D~y3}|(!u0sokeuQ-h8N%QQGK-_HVp*i}3!6XYa?xV^pAu1N%tfZ9JxRGG^EDX$$IU%2LIO&> z`fl3ut8?~oHERJMtHGSym~45%owsR@W!d*ud+X}oj+rwoC-A0*3115|JDpF; zwR~F2+KJLSrD2r3|D?`@p{=k&5i4?@oP{wcZl0~vPR33ZH!^y>1?lEG)~>(%sGC8# z({3@Ev_|cjI7;GBBEQEJu)`)_&Y()U;#T{Iq$l`dZI>Q{D;8!9jkix1PJxskRc>!6 zaljqmDDWbx_a_DQwHDkcsx{kb&{=d{GK-pq{7L$7J=JipkDj6B{zg;BRycRW-S+rJ! zMI|8O2y6sN8|$|9EYEzq=80x#8!#G7{U)o5Cn{Qu1&~MatFS9ke$&SGEtJe2y;HRB z>W7P`{s_`{QmNh}Zve4iL5EQ1S=B(&^tP0- zLPH=N!geI(s~+o_*ki4qtBMF5D(4I=Pven!JW(L1;!%<^F}fU)>5=&(QePQas8iXnB|yOP^@Ahz;tMTpCIZBf{q?9pb^Zjol~PF#l`U5yP7E+@IgzAxEsfa z2sMBPLF_%}r-~pv#-kJA6aLq9F;8mxkQ2udXmrW$LXg5}!Dq$zRqG!&4yn(NUFaTv zdK|Si#V^5IIMlimmY#2Yb1fR8hEUTSwgRCYWxP_m!vTc10Xgs|uU=o6hYG1bvr4R0 zf=)^pLTkRt`uwXda$6Ja+V5X>a3>BRvNG3r{CET>^V^LVn#vB(D%^M6SyDLbjCs)9 zAX_(tiEi|G<*LE^9#lfgq=3_-Hrj9hQKWT3jK@?xt_DpwVwxos$OL&A<5tW(H?7~(Oe(Fcl{l*`L_J)g%)eL}o&deA%EvgFzEucrA|)|%2acqH!JnvrMr zt`=ZhFnyLMcFIzJ*N8+A2sPvz^(zIcpt(T#8p_Asf1V}3-cK{*gCg5*J40!Q!*O{vxwF^rrpI!lmt;)AwQO#hf-MZH=o~VaFfjm=;kCuRb#I`WO4D@Q!!%4^JAMI2bgG| zW;SymNB$pWNu>9QM|q;n%f>YISj5I9*)gyOw(w)%Er%d<5<*q4z!Tt+$7A*w)2>8r z{2!gzV^^J?m{`u*e|%{ zVE~>oEXi4XJ^imP!}+g|Pk+$>j8RueZBg}B89|w#D5uoIIleMz;fVFLnC_@={oI}C zdp2r-4E1dzTq_FcTV#~WU1Hn-iS|>T{_%GQ{C94wfvX)*>6W?`r5yX?K*5U$By3=U zWipNCRDT*y8Rd0(UnRBXz2DG@lknwyLc_lb@$W%V`1An@6hI=#%cpRLA?dnT)_<+Q zL}C>qCj`pNz2FXhyL37P)+5egs*uHHq@xFNbf~NNm zC6x(DMehGEyx!UU5>tO8YsX#}bHak;0@(sT=XNC5e3t#^G{(AG@JkmH^!3ZS3YlB& zwizRCUXQW%(`e(n$Hhb8k#-ckCW=V2Nn- zcdG|%pgfvwN}3cA4#&ixP|)Lkf4$qD;$>5rc#tLuq(MSa(+uR6Y9o*9_MRmjH9Z_h z*nX#Q5Eq}c)7HvR^LNaERdFfs?DWT4fQgw-0OjhF}4&xVWxx!`6Qs{c3 z8GmbxBCrQqv;r#eb$dD3(3#i1vS#^_{3d9 z29gmj&z!KhzPP0BNMjx%OT_H*>to%Ja#-WWm&ZGB2c0scvn+QG&v=e_b}~Y65*M$N zyml6&cc+Qf1f5MryyaS=lDd#8_3-W7v7WS%Ot^M{bt$`>5H4KEUY?euIm^bOY?t}j z>nvwR2MMvg7L@O%S7{0(&S*apKl|!#r!K}XMR|Bsr#>#2u0Etymrun!J=Sv)I_V?MA5dY8lhABYE_SBkDR$kIr^SM`nAA68wpy`;;`G&lLl@Oq zp{9+&?%%w>VnoWSeE6=)jS(%ZrAKaa^+`rWEgx)Krk;SYZh#)b4)v}nyZNp%xl1o3S zgj4amm}S&^sz}ZMn1t!s$}M0Z=swRiv!SvQztyaM2I=gOpuzq z8Q;X5Wa7)+x*mzV$=Qjypkx<&EUvROy$eQ0zIC@<>wkcbYRwB?@qAtq6#lvT?j@Dc z`;pOK+xZ6~lAO%H$)x0d6q204KmE0vDKZisNEY6nV1n2}@Pv+)QhURMyiO1Fp=Q*# z(qCa&zsaujC&YUi?h}t5@O!vz$@Ee@Pjg6V^O1UTG(Tqufw!2C)lV=h#21yfd8bLg zXxMD3)J-#KL3*k>meW$*aji?m+^iQRcHWyw@g>nNEKN{}&|hBuLRhdo`&|o0^*c^* z^f%n#P@2T#4mPH^F#~ceyz;zjh^el}rrwtV8r8W* z3kIlnpC5DuJ5wK!L$kdmR=|(GfG;I)9X|~<`nV8qoye{g*V3m{4?JXQMeKs`Z!>I<6gw$#B@q=yL-#{LG zysKui$3P*V^o}Ye=0uQWFKrtaO!mUvf!;W5@TARA3scfi^NPCq&0(uXY8I_KN-+2e zNwdS~_0639I~ZmKOJ20sm^enV7-&<(4RYFM{IR*6_Qz|9{2crD{>0J%>TI9Gm#giQ`HbFLCz+Uj zYlt@>B6Rx3tmt((;$l$&)*S0NtLiqLK?M{Q1+cr?hOnjP+7SwMAC47iMRs>|r4?qF zNO;o5a+T7wEvdGzA5{jR#Ao-%1@5ikORIF{C-<<GR`ieGd=pV?zn!;HIdAuYlVCgUZA zHW|@$To9Lv2fS>$SFEyPz#p?=K3$1N9#Qc`*F`h8SF9h1DYV?4t_WgPQC zm2mVTx2giLl-|Q6(^&IpJZDpAg1g4e!x`1ztM&Iv z0s2%Js~l{Q++tk%2!v149x)qO^L*JvSiF7&0nQAIgf+sPq|>Y*w@3ZLR8OfU zn4oL=yRPUGUGqi*J<*28AkDOGCiYv2nVuEqYmsgS3mNqBI8Fi%36GTlEsxng$xt0` z$t7nol3G#oWwvKq*V}qMwx7*Y#!#2WfM1OY$+UA(JC40Gs@-h}3C$7(7yh6_O>ObH zZ70~}#X9h8CqHWG_e5jV3c5{(pI~G4eogZ0CZA@`tx*AhQY6LW!qJ#1wU_fgKj-e- ze95NvxSIHiU%bS=p&UG*jioFXH!J{|OEP8U;b~4!qTxCO_7?Xc%s?7jJ(9XBt|Ui4 zc)CbzbYJ@sHVOH-3}Vp68Gg6aH0N&L#h`BN_A4t!~->wm4huqO2d%##pfM76DoR~{L*auCpm0!!qBpU zR@85T>5kX)-jUKmHNVZyi$1uZkU%Gg6o?p4uJN19o1ohhuw1c+$z*7@)Fx zPO^5RPqwuAQ|H4dIc0#*EEw)%qqhyv#f6Xmx zjn_J5&T_RTU$3k;=QkOu=IQaImAaC>B6TtzZj|!tq$r@|-~mGd71}M<-$Ae0SvISN zHa&2wSjzd!(fa3FQj!OihL}M!9XnC+T;-okuL_x}yCh5|X-!6W)aO(Q4!_nEo$@~= z&;|?}S0W7=?S-UhQoLmsbn8Ly#4|nw9x$&M;s5kicrO_C?&@nVD7$_G!;#&P{XHTL zQ{p^QRwo>jf_VlBm{Vf2Dl*ZxFZY~E-LuL4auukleL81qOyPz!ff(sLmq)bT#C*nd z6V+abmFbGKNzX~{7*!GUlS-{Mye0?Mbh_kkOA5iK2ASWChS|BL;4MDtvtO>i3JqsG zHG+-r;B?s+JNnAo1R(I;80NHkrS+|svXsJ<{C9g*6NjuL>5V0)QpEILjxANc$jLmV z^ydI?NB6#8|0W!dN2e)|^sMFzdqNa%e~60amtq|dig%WOyv!p<82XmN-Wg9nfB%&@ zfjzJ3Dx^@76de?gZdRR+(=8NS+>2!;AY=8B(9zH+SiS%9Z@NR-%R4^O#hw zu++u}h>YyqJ6+c#ej%`-@v}}sRv@G(_xwoi8uLB{WL|7(D`BU z{Sr2tHDnVUem@^ooW=1nGuCA(nF*pF1JU7ge|kuBue%Mt?`{k>dCadIe87Ui%*nPn zNbY8XEvvRTitMl$e*V<0tJK)5mi$mwQ_yV}xNWgh7UQqvm(9ew&5`0m8&ys9)-G%Y;ULA6uQ0^gL5ise2R_!@U9cXNK>zAh3Y z)UsEF6hwh|HEg6b@(Z8iD?19Cd#Xc==bPXKSP6lt0o1{#9b|Y4B7Mr4SsSGW65LM=lE2{b%-ecwUdtBKLed}FcRqSUMRRa@>1t97?zX(JFs`et}xXBj>BHLrBE zq?-QxsnU-6m-|Xt2K#B0Wh$n z0&W1R$d7E;DBYPbGc>SSXowLI&3=`2z}cm*2vIUuJ2_P=FS?Ez>Kzo1>KM4~FO+M% zA(m|z)kIZCa*XRA>AC-8Ce6`wjL>|6oi%=xnu=Ak4p}hi3u?05H<&R?Yp@(ufD?=f z^oowtQ=@#g) zjkbV@SSZ}&Ml(mUPd8zjPnn!(U<5)!sf+}7K=if% O1X0Nw1vkUy0!NogIpJx?< z+@LN6lAzL&)BGreIqNoR%}iZZLp8<-q}qTPmHI_JT46MK;q|CvW9Y+Fy_J0H#R6&c zj>d+8!P-MO^+A~=0b!u**^ohL=v=61e_o`s`BOBZTP?z5rvT6OU=!YiAYj}-`EBsI zRdtDR5{*t@7*6d2BZ}yT_ng?$%L}ntAHD^SWzv=mt4x+~X zSSCb&FM|VegD5JrMj0!)MOsdrB}gNMXeFdIL$+DmoOVYAc&02-ljfaF{|-@{~)mb-6S(uquW_8l9D6*~s}fU%MrFt|E| zNVxmxq`S}hV@eM{c=d}Nws1n>TIWT${$`H#N7a$4h7;Ix5l_qT08OOOTlZ`yx!XYB zs3_!MeRZ^RcAaJOZsa?NYg`{hh<7v_TwadP3>Y>11efEtgBc2V<4dlNEC_vEC*M!< zp>RFF@&lou;G=oj)59Kwby)~xGQMJSz_@aB?X+JmygBgC%R1_|qF<}4k+7x%Mas%Q z>;F!~*0rGcN6;*}*#t@1!cDc@{!X*v%<)jkF|?W_lhE8;KoI(o7%K2k zaPjX%u1$B7I2x5_JcAcV5<=;heVu7ZjLv_jX*P-MzdQeMw^ivt_>mVRXl;40pF-;I zB!8FOYmwvoeR^5Ud$+IFh#T2|C;7YFvImJjVq@5#pPSD_>;C7;vi+m3)c;Sb`m!uI z1^c31?)+Y4h!$-6_E?gG;At#w2#niky2{0w)sNg_#1R?0LRAd2@|O72KeEs*%$!Ys%`+l|4(4X2R~Mave~h-6r3Gsa zSd5U1yEWZ3ah0HRS&BwdC4+b;jtr^=@0VG`+nXi7Fqp{nD@}Wcbd4JJB}l@n0rNo7Q>6w^|>ib2_ghKU8kQC znZ`)rdnh~IX1jejZ62)YU5l5e)HR+_tt=?zYA#7`07_BZ*kL33i^9B#Eu&)R(o?vI z9sdUNqFW=5V(>~9@yOD$5-ka7yQy9;Ezw2XS6=?P+copfEcS>I9{cIXAa&gLiX7Fh zhJ!O8)B^Y8dewTQR-OENdovVcc*n<4Ar79Y6{e)E7x-$z^gc57+g#BH!ky_@A-$5V zkAY{|Q~aJK_6!5mbtQAF2gyM7xUHgM)mi;~GuH)GVeGpb>B&69ZECSN3c{3~OfM|Q zZh1*)@!GJQ`%&0ZH5WoOZcCjy`QFS_kr8emh(Bv+?!K?H|8YtA;8ao-fbyyzl<) zcOQH29_r_`@wA4dJK*y?Ia@@o45 zPP@Bf<|V~-1q1wjv+wPHm_#B5|DFmCe*J&?M*sh4@^Z7%eVX&QYvA+wGHF)-lWQC} z{C9|GhmixeHV$hbL3nqo&*VK0<3)>UQAQep_W%By&_2{nzEd_gS{X220Y?X^a zzk#M2)tU?C^izgk6mt1yrU-90n$Wvk$5BTN8d~TfGUe`hC)^6q$^C_d3Rjy17#Igh8L5?V0YY{4{nYS|6M4H@HR^=FPT< z648t7O~cM&R}j^$u)uRlbtQL^b^~=*1~!kbQ%VtVi(%XosK<}$kODqV5_^^YJVcBjhUW@8 zZ;+XQ%qI^X8=K6|b#KKgQhGhglYZ*PDY%f@qDkSGZy>T4psbC-Z%iwB*%{ zq@}oa)}c>SIHuIgtwlTJYJ!b!%Ee%^71>mjHq#39iiR){{|}d#LJJPsygae|wQ-sw zos`OXnTnoUPWov>x&#Npg~ai&OY@t>DYq5EA8Bfe8U>`)IL;S2wKex=kWmOA_XG#i z&wMA)IN&_k2u;K9a2bW^!B^^OU6vZR=zZEGI2bh&;?IowCoB2Jy*dU?e$w24jWcu3 zFrl7wPtrhbGG);58)LF{)h0V(Iy{9Vuo9xrO!Ie_iWN=PuB>REVC83VW+@K9F^u(e z66dVd#^DmQxmCQgsE+>(byfA1V_NS{{czm#Zp~t>sbCF}oZz~#-tO-EUHbx@01*r2 zf?;@7&u`cFs#C?Q=tR1!sAAHIkoanwEX2h5Kqyz@bVY>@%aMQQ*=2tGzo)Oq-3Y;Z zwII9jPqvt(UCr(Es9kM^v7&9BrsR;ApoNlcq5;J~ZV;X}mQ-6sSl%*zW^eI5;w< ze(M2s;uj{*AEQT+tp9d#RV~&^u;J*i&sec-V@HWnCMK0%p1&rpxLH(5dH4LPiI=ZO z!wEC{*qu0;>paS~YbpYP{lM6rHyID>>ecF`xcZGRZF7H)f94%^#*g6e+$`%jRC?sL z8c)NUPf^g>Wg@(2Qbi!EIC-fDJ#GsJJ11d;5C&P#xq}MW;xxvrfNVN4sk|1Ul%hn% z;THt}gIA}jCBWA~Z|hbEF$(7QD)TuOY^Wy#yUMm-_98FMW{sd1yz-&9Lt$bK((U3B zhJ+Tr+3?9fSj=r4@9(t5!OtdV5I?hT7W+e~9;IgHRbtg<{&K5wTQjZGb#&o1)6Nk2 zTqn*(L$mbUD<=bueNDRu!1zlWNmw}_RWZnj(_BNqs> zeIk6W+naImSBbK4cB6S;mxX!Bs3Bj<)VmN7(d{efcM(U}S`);Hv+Z@EC0a=`xT7(i zDgx%_B(!ux0)?Yf`DPY(-h{1D-Pvs2zC2UX&s0UYNwbl7s$7resickFOH=jKHQYO6 zbsn%vnb0N=zeP4gsuq73UgDD+_xt>FZ;S6=)!W#3CY=$bzC--U@TcC~7%V%n*=ZT} zZi@-X1N5KU^h2=aF>nvNID4lb%$TLc84%t3)uMWWL)JJ>m}c-Um1WeI-?a*XgR1$Gg9pX)Sr2IerI+*|RGme_+5{h*rk0qU^WE-yYych=KJyJ$kR)pHjx zj@vVNXyQ8khBv+Cm}NL)hX_$jm%M@)kU)VRe58wrBiud^hfsQV%+?H8>6k1n#ST)p zpV1a5b1AWZXhyIW<1x88glx&wp%J)d@Ec45Igp+9W!sw7NTRBCsBY2<#_&b0U(9eG zI=dN_!I(k(EO%&4C;h>)xIB`MSO^m5h(35*qR2rkvDe_@g(4s}qMnyj_#_>j{NztN zkhR?SUHgphDqZo`Oht#)It9Z5H-y%-`D}@&E5=?-O<#%v0t<}2Wm>XKWkkDv&3E0* z*UL4>v!xBywyL4Q`PU(-n~GG=M&ErUM#+7yt1Q=U{p)1&Uwu19_=Ba*?*7L*%E@=~ zjgXWe)M=G_fKtA<>o+tehW4cVHgz(u6uvrRly3y}_qi^Gc%ap|7DjTV^MTK`62sMm z6vOWP!Sb|;{(vK+s_$;4U}nUuf&0{CW)>GMu)0_4?KvH$!?9!MGv>zy>%^itPsZI(vc z({l!@7G~e_=P>+_6PcN*uUyx@dZ@Fo2%fw8*U&C~*jfD{AzCt_ZL_K3nh)A8f6gU) zu=^{KUxk}6iL$VPkk~`97Cd&{bteJB=~!D_6IIW-8PxnUk3J(V|4$__VEuK+dKxx{ zofLx`2$Yt8P8V+aCz^6}@{5bCLM1QqG3JU>MDEgG_{kMt&Hu`@|If=$0)HO<0xA71 zmBTFcel+uS695xm=Ji07a>B1ghz?UD9!QGoFx4iFGrO%{ry;Ix_4UG z5n9;-D9|KVJjXdtT-L+%Xuh2@laA3t(_cQ>BthmLxHr_;+cb@v_T?s1SbS5cQS%IH zqEynM^S(Y&_Ig{Q{kukH_~F;JB3sCu$<+k9lWuOCT<;57anIv(qC1;=+@Ba8R*Sk{ zGpuoq-4JI`Sb71NniX>KEPJj*x^JgrVSQeJYRx-D>@JZY7q2?a3C~K{dtFeU64$k$ z^^NbaiD&pqf^P|1b8t8;nNcE>?wSvzBVm(;iE=SF=9;hem)@8=8JyIXX04iToSZ(f zV5BsW2N)BX(EfEXk1Er+F=bL3H7T`f8*RJwGrwNEO)8d7OXdA3H23u!u)6iKUP4Y1 zSVQN1d$IP#26@KAX&=<2co(8~FT9Xbit%u~f9mukvbRBGltMgxtC+FU_DXF!M)AGH zwqg^Toacm=`A~pIe<_Npg1||e0RV}zsS&Poz)CH|H0}zZO>#8vs-!KD5QQ1id7l}Q zTs{@yb9)czc5?lzfN0wzWvE~61KX3Ye!1sGxFA-62L#*rC9}|6l*0ultWM~|KUf~L z>s+~K>1XrEWWHVO9Ap9dBI(F0MXu5UZv*ucF#b43mnKP!fa$ax4ox&SIQsv-AHD}C}Ak64`a%32`jej`25FE%^m2J?Tb zGN5`&*3)8K7itA*Jt~@;SV4K5(vf%O?ur1Yc%c)tyTUn`JvJ1m<(%>H1jp0`@n(OE zs^m*A>e%C6o>|1ZoZ3&wKZM6O6|FU6ZhQEfyeHjHA(xa`$<2O22*Kc~X)mB1t!4`% zM>{E_Sg+eYuUP97#7D$gZ*Cxb9_akK#Q&(zyu6V|XFXc@^&twdjxcUw2W`o>iqO|M z$LSL3FA8#!@{wmG>Dnc&-I@GDMJfo!bl8_ux*@l1%n>a=l=E3w4kB*+r*qFSfhX#p z%EE8{O##&V?vbLsItGVemCQ*#$Ev*CNr64RLm9a<%oS!zm=vqwGA{`3#oCqC?*>2$ z(qf63&m){EsmZp}qv`Els?`jYt2A4Y$sPN+iIks4jhd}_aqM`#D`d7e(wUa2V0-L!jHTb?;6~DjjJET9GQf&^ z?ct?r09+}ucIqbC2lfuUFr_M5?Pd8As-l-~2s&Mn9w=jVNs_$}BLWCp;~Tm^n$+V# z%m==h<1FZh8DxC^#J5`K_rCnJMG5hwrH&81Ms*=R7ZfC(IHg@`R->X_HHY7qS?3-` zQi*Il)|LQ?EE?cGX?|FR%|~G6CK{_38B?$&&Aa^>iBZHTt(?XbsFj*8Ny~Kns(<@B zdK0meJ1m}o@nz2hEQT|x6q+ON*NjA#6dNC;2?oTcm6dJOEdN{ree|{U6_HzioC_~* z3$TSi1)^&iPG#T0&B{32H%%G$; z6xXB2q4Dk}-U!pihhIoPu6df>-=FrF>bk=4qc)W8+y}ml{VYPY_PkM-V~|9E^{M6M ziT0lpvA|fAc&{EF|5^$U6cdXakkB41F)F2xr%hsU@}F4E7JE*j|6qCc(MEM>zJ^Sv z`$ZG`c6@)P&$2Ly+Fk0yv}aFPt{+Z2!|)$8P#qs~%7E1(y0HsK?-NCw6~*aRm$X$e zqDodX`rH%dRuhZ6DA#~*x7Kqh6RC|X$6PZ0e(X8UT8E{AOr7QzP@qJe%W)lo`Wv~U z15!3zga;k(IDuPgmYIGZ5g}tNYW0muT3m-rq_+uI9H)5I`7giqJt~6cLfIntDo}bgBl$2OXml){q zp9OhMLKBRbu=xDzBa3}cVA~Ra!@^-NbD5;EJ#{>Gx64qltLPGGa)wn1!Z-e=0E8Ow z3NtUa6ooWOhxVx~=JuLbcyJbJX#<|$e%{boC}U7#9=~8&%g)#cxtVIbJi7XXqbY!+ zi8HKZsTncPo75nFNm*3x`-ytL`xet`-&}m}D+I@C^WVQM1aj9boO|#_c+#VYi)b2K z?PC4Y-upEzi`&UYj@QVo{5REXW#j>|mfs$G^hGB2nh^>~(Vs0 zm$m|2mxHuA(J&YV75fJZ-7wajzs%Gb)ctGPI=^|7%N!2Yhne8(LyLdv2!3ZK?Wx@^ z`5f<4-E;k%D3-^*Fz7yDrq1QF4UVhXN>z+9a)`d0vO3q+5pSgW%|CKL1hrERFSOkJ z{+0W=hkIMqXM&G&qUiKcz3=2>dlAbo5czZBy&h~x7ga7>bF;x%Atn_kpy6$$*Bi40 zNVdCahKGdg1$rHCIO7%9kWRgbV$lWt`x3wU{fZ{6>*e+fEmrY!uKmXPk9O;7s5;KR zv&rBfgOeR|N{KLXiJ*t^zF3J{-@5-9Z&rY^h^WIgknT*ff&6Bakp!+7?nSj1RASx!$|q9D-{~y*uBvti^5c~-OBjK_%yUkbGho=`%jLeE?ZHadc_i4 zi`pARaW=7Q-5F!mt)?#5+HcQ^gy|J0X{=D(ybKE%lDyBmc8X(;7PeS&uA#@pFWmcs zrLPhiJ5Gg6<@FoIB0VM&{bky*Iz4t}Eos9sSTUJEfRuODfkgh0lCnhWNti9T@apiK*jDiV=H&^zY^cm3Hjz?u=&QJ3 z>`$66VdYOs655p8`P{jJtdXPeHa{o;nFs`V+{?tu75^|)s!})$1Rj*P!}T3N?U)nEPe$ zq57LSNI~!O*$)OM!P}X(GB76sbHN*|ymGk&E)=Xx*<-~EqPvOkapx`)z832GjqgRJ zUapS9Q?*(11%T4+=qlAg6jS~DFtDA{E?<=7>-qJB1=SyV|9T59-z(8`q@>*>mO_2) z>_oiIiBruN?P!;(cpU3_1^ZL%mbCwCXrQ?Ru^=h6BeL!m*d>;q00wEORB{a!Lkc?Z zzEeGvig}=j5u%UQn3-~LspFBzINIJK_~rr4_UUw-x!rr-LB>3iF6w)%feHv$E@YORo}Dm_KdXA2Y+VzWQ<%W5_IY+ z{gyKHTZCdsQ9k(xOSzi3e61z)u5Dx$4s0UZx)s1X(2Nu;)k|&Jg~^Kct(tNsjw!y3b|3lxlAY&EUNI|$sQ zHm#KEp{z^M>1uq>o0Q>NqEgDHG&b(EW!(XiJjMMPAhKm!cK2qNSbBH{{~K`DWADBK zbCuIMmNMHij6>UpXkzzsXJT!kwlfoEq=|>t9`T|D*Vh0$oidl&B+Iy35)gE4*Wt!Oa@MD z^7b__*4vo+=6Yi3Q!?lF0TG8{F|J|m0u8V>;mGtK)62az6AAN82DMs+_T!CTlwc$1=x93T8a!o>d~@BiPn>HL#R zfn?P2_YRardPMguU?O&3LbI2g<&A<$Z6oQ%hkghr{eZcum62}?Oo&{!dY71L?F@p~ zV5q% z7BF*zkkl^KXFOJseSz(yd`^^kcLy_@$Zk?C<`(;Kp_MdBb#+{P#Fp*UBN>;}^6P)F z7<*aIAy$d3Y-LGSTtCTCvXYUVed<#foyp^~94OoI_lMk#0pG}hB4Rt}$C)lel&{Vm zaeQ_THffnSHx)_AK|>~e7`MYYDIhk){0|6zhlE@dZgpx>*u0Mt;6*l-_Kr0)*#9~!I51S zQd}ilYo0)CDyNLTEdBa%V(i9`P=II1#0lqu26`%CDh!Xg9C*f+xT*vp8Qb3QtEO*m zr1>EkQtttw7_CUQxFX|XvrB~#X>Bt?tDh4<=6xY3Q1J@R>%QltFVs?+0~q<9+F!J9B2{k2zb;c_3#?lzxx;G z_*Y3tZmzsr_fc*SLapoUaNV&omi4^VZzNvYgyqBtTz1RUxfi+$*ZFj@YIV6}8e!1H z^^!ln7^*jHW}fDuz%~YPcq9;-aO$!E{p`m=6H0rEd6!rXZD)N@Jjho0{q(buw?Vi@ z=ZP9bb(*t6vYN!pzqm?itSn$t^@KtJUdOx+&Kc@2)^^@G5)NI1_8$uE6mo&@}>R$N+7r%wC*L8GqDNx=5cY zcQX%SkAk_I-&W0FA3h4f&vw=DU73=7D9|1=6{|KFPTELvyJExZM+)w3r((o&=y~17 z6;9G6Rf~p?J{!C=CWHM^*!W=#!goIbjw_N$)isH+&qS(>eQ?OfX}p$CFHcSluV6GJ zAIEaYxFyvap-rVbJ3!UipXC-SX;#x^NY0us~_y2?Qx964=&a@5GGe2b+JLXGL^JRh9}T=A3r_bTX_Tn zD1)kV-Bc`|bQ~m4cqqWpx>h{q2LAFR_XLA%$mw}&m%A`pg^5GRzDbSnc16pWtm1`- z)iTG#If^3lQ(Yi7{oA`|o>M!Le!-`Mb~IS^VouC1Xf+u?0Yw(F(fVH4VayOJdJ?pb z6YH9CDG2Auv}naN)h_#256b~4)IK1C5Wc#VP6+I`i>x1+$nAp5Ths}u4_oq?WbGr2 z`c3I7cq>WE)Ujx#ns)rw+-D zQ0@nI*$6zFyG7asX&Szm?vf}fI(7w2SD0SI`H@0oxMt_?md-u+gXM&cifk&dBd^*2 zG*$x+oZJEWmx~+Dxd^D9O*9VOV7r@wS6q#M09AA7AkE-1+C&6u7VCSYC`hM%TLtk& zYMWR>i}u2uYN{p#xJx<}tfflvP1t%^{(`=-i6D2$*?Q$WkBIBNkME7PG&@%tmTN93 z+U3jE#}&+2t8%=yS`Eh*kZmCzBP%Y|B5$XOIuQk5VQIdcxBX3|Lunx<(@Pmn5W(Cd z(nYl$iEt1Sf3h(f9hXBlGp?#e_ypOA3ScX;?9lHlgB*uz z(?qd@5U{D%eq?Z!0HZs-2y7Xk)elT+tT#i<3l5o_kqC}B1-CGtNEuh_6`H`&aKfcp zCu`_l3nygxtlMT|xhejQv1w=>l_)9b^rJeVE=;QAebtk_(S@jwa8#D%DHqL&^R?Lo zbO8$5G3CeFq&n&&z$2rv-+fA1ZLSldWSd!Q|W zt9a~v?G9OU0@;XIDryp41x9CPwBF@kvjUOx)R06ItekTOVj-1l8WH2+V>l>Yf^^|8 z?n~q^5|K6Mf&_+&OAzl=7}mM|(Cqg%F$^MFCBk2X6Nck~p~cf;q%&gofHsy;=w-R0 z0CmEv>xMK)<0wtaBfEC-W#dmFdV{x5Gh3A?ykz9=P^zP3H=N(QXrQbssP6o0+q3H{ z*D^H1)F91YpX zQIm`@rOV-fLDJ-cHCyh$2Izi6$D(`o_t0N>s@$c{YNZU0G&&I zFf`mTgQtKFg)VNGAF%lgw`ZRrI`K1Hr8rV0wRCNEj=nDbdUi>?yHJxyNsI7Fdzj;D zRS{3GKANbyfblNlM}qRqd|xa)yvDEvmGoM)LbKt(sSjKOMm?tdnp)u-S~JVJ8b%%q z1vi|Dic;u^{N}<2GP)uOY<;z`$e2{fzP663$wE$WKPGhk$cYmaQ0xjUs4Uggbku}g(>G4_{;`!V1*_8fNScM^fB=>sNF>`z&~V;~FCq8*!0K_F`p z5&37kESI{%qfj9F=|exGN9F(u3W_^fo(ORYW;vCJJL%*cno3$wn$pFl)9EAmup&^E z&eLOaVlnC>a$m-D1zZt+7NKcD>=8LE40CMVvoNVMGdT$L^yPfi+oGb)iw){PlrJmb4MjQMPzWdVjO)!n4mj- zoxWYM>>p3+LvNqhX)yVasC8oyA>KGAb`aSc3$^=$jmK>! zHPT{qZ6@4K=PPZ`*tKrQb?-{i7K0Si| z9QX44Yx>!hiLYlig;6XglK-yyyIq(oQ}W@js;hsuZe|ZoO?A?GkHe@a(`FdoEC5pepDcPgQaT!uc}jj zx1+Kg?fJV(@c)!csLqbyy%IaZle^Bskru+@6f>a z#$8-|OnHKMuT!`FJbT&7^6^G?s{m=QQX-i%{Hh4*gJPIERz<4kM2P&eN3lN;Df&ZG zusAsyq2RL;x73rvO$1W_&*cx6;+#|c!manSHsARAGP9`FBUopGYk&0({GJHTw(mFB589D(g50;xB|yVcYr{>1CKL;l-iiZ;0)qz5-nM+d-Qh zdQmWC5rj+Dy?djHrx#(B=YXJh*VA}i-^nZ4_XpZQdw@KNpwTWMSAnWZ! z&>c!GiB+@4Ef*@)X6SIsk-$*h=ZZa2UZU@dhaBzN5*^P^AXik}$4L(rz)A|EK|_3p1;JPJZB$qDiu`vjGI3uYe`Z4Gin;lHmxnt+ zgqsvrWx1>~Ihe^0>>7+t(Bk)=tOc<`RTw}Nsk*@((G9T9^9r#{AHkNN#hCOi7kvxccY%*S0l< znthgQ1>u8?K#2)tvlt}d zdvQOdtjQ`q=$-}+kQLW*WixUsoGWERn5Ru-uk48l8zLqXip|Szhu@Gk;O2 z^aC@7#X054w{(zIgyF+^%F@LZiMImZ4A+!7MJ84xWsa?I_2k0~5m1H|3tRcPNu0|4f2sVv!!yPS@dEp-5H`s&zB22 zJ|(?DEv7d9u)~Z-1-%jx7i#UAHIqLb@FT#TI5cDms=l|BlUS7XaKYni zRRLaeB^-a!rmta78AipxCAy3312vr!0Vpo(KUfek-t5V1FNSG#w+}*_LHRo4%5qOQ zOMKD_w&H(O_YU@sb>fnf9-qYXF-0kOTawNFo94eSW@{|E7*tdTur{h>SX#yE#Z|oY zP?W$OW;z?c7ad*2>6wYbWiZosO+7YdYa=J(28&fN>;BI5-q-ahdVWcD?2$cmxl^d8 zHO<3H>E1Y+2VX8IPh{`K@;0BXg*DHINpBEk6)y>@T`3YTKo3+OvBv=u-|5~S!24;P z(Q<>9(5gpFxUA;CG`es%km_rCl0G{6y2`1rj&NRx>r^R=+~+G2I6-zI&2@P1$9B

^mXpk*$&bMTN&~ywzjH%0y(K(2 z*7&s{zHIGl+4%VrgWv%sBYK$)rayfK@WTWm85IYkLz16cABb}J{!NQ{ZD_ps+5{(( z#GqW#rjqy2W6D;#f8qM|OWq!+#vsXwnd|f1|3L148W~dylmAV$u5%s4nmHN3Bwwad zfT>ag0qlNEaPeP3N|1drm48Gv(b9kOUbcAs24(56Pg+#zY6>RRiky=(t;&o&$~f%} z&nv1L0LK{I83mcc{lLm5y7KmkNxvpof-fT1T-ZD*;zjXxO~?FDeS+g1KiJ)Qrq0q% zD%7^bDFM_q+E>H5%Ou}q^(N<6A5VRy6mg@bgj0?`PH^vn(nq_Ho3*dns+CPDHm(7}B($-9U(Y zMymJ+)DY5$o+sy$W3Ki5B?6UiadlX_#-?(?+iDJmf;40JX;EOqy8G8Q?@0L0bz2o% zNoj<<_?!&b!@92>4|F;-o)cdbFv&lasN%YDz21Gx#@*6&r^L4eADx9@fK!Y}l+$44 zZR7omIbq8+7BOJ5QL(8_p7Lpx`aDP~o>{7kZ*8YqX7pNr>BV`v>wSz|Fw#w61%Utx zv;|%n`}8e^9N;}>l(txhHQ#FnbG(Kxr%PRD47nh{q;Aj!fI_9AQwE7A=f9oH0ZI`c z_!mbfntDy4<)!nLO|-?b*qgxLso<+Dj1tBrvc5$sst<90o1hT$Z?30?#)4-Vli>)Uh zEE2o;jv|V#e)j5pDY8$`gFpuS)uNgh&fVu-f8P6yl9XU)uw z#km+W;gf|PB3*H800%*=%%b^}8oz!t28>bKB0NxHF=AnRHTiIeYMAa(?#s#y3JY)| zSMSj=qHp60qY$1)2alyRFd-uwrwYt3=ptT(pde?zvR4sJ?m9#jWa8vq zzjVMv&HPf+XUC5e!HO%*9X$<3UB$8PyMq{Q{Oq?&Q_3xTS@WFJQ8(B)U}5PF*$Co^ zPcmnXVykh}#ux3NmP1MS7nA9&Jc`^Z7LL_``T4aMq3Ydf-LL|N?YY4_FA>oUb#(8^ zSDI$*nhK)`iB~`PT#o%IvGSC`T#88+;ysp3j1HO z47nHzeFS#3Tt=H46mTMM7jhE3&XtJ++bx4Z;-8=7EdIeV`K#@k&2>Y|CsS8`&kI;x za0^Hf<|u^OEF3pT)G5%y{F#G9S@x;?!TI`QpXA1iB{j>^TXk+LFDE%H`Q z92!V4S_jm=LOr}NW%us$^Fy+_pwXe&5`#j81SnV9nK{BWGcSmK`Vr2?T+LLkD=Ora zQ{wo`Bo}k5FnmMG{Wo|9xh^Lt6x-)^ZXbqCup}H2{_DeEWjUv}{-^SPjKF+4{@)nk ztKy9Vg`iHiZSB{&0a5%Gl1!dv#y!}jx5xZWQBU}rRseZMbl;wOAw>K0IA~?@gGJ~@ z(4WU+H|@{G1x&{xM7W9|J`gR3dp|X_69S5Wsh4^=y_w&m=ykMw>*CdSG-ms zpG82rq@O8>VIu1sbmQW`@5=FiZeS|+P9xJEUYOC<+KJwKs)G7A+9*0BNsLj$g|O`% zIIhR@PaqJ+E6X|S+&Vc?Nh!9B@6kJzky2Qx<0QE9@EgO%*bP`;FLyaWA*u3vs7{@D zgk|33CcvK6hA&>rTcjhmtw^cZVs8L3ZX7qX9A5n({ThD8ywimDPW+Ic7*lQsNay6wkyot_E=)}o- zL;I}iq67tBYIsE9hdb-=f|pQl-;2_pPIQaE1VzSOV$@S5Pg+A2EA|tTCQ%W_1cdZ% zedP?G2X{%4WQieRD|3X41pODK1Hp@U-hjh4B~K*-14Z)C8Ye#@PF$F760xNn2TyZt z=UyG9w8OiTAItnC|Lpp-vioWN4d048HDUnL#vdSeXzW-p$%xj9_F*P9^I+xpXt7SA z>@i=Hnxqw_Em^~O`fN+kVor&>i@!tz9?kJYdJ9JIgZ2wZ1kv{*Dl4CrCwsw4RJqrS zR(Y%4nTCo;^8mh&)fn2Ze9umjPga4xU5NHN$EyY|?^%P`8fv%z4kiMP6K{_3X4{Bq zONni1fMl6xb>(pq{K*8JqBoa>H)H6m^a5kj@X+NuU9$0?RZ^8(Va|O;^_KQT<%?{) zIL$^RttMPKJO08V43ba(7`>>$DN2n%4&G;@yvQW!6XWc~Y!6Hq8ueP7|L!ct2s za~#g+fg@?5D%|>}Z~<>LBC}2Z-B;1q>n6=~-UY*gFg_e)_eJk9uu7V*S_+qmcMT>D zere0g*67v0E$aU@eJ~VydMf%Ki*rPIZ~!f)^RsLKh)1WL-ZNBil~E`z;W9h>O=x;q z{+|q8W%j&UBhd{E%s!7v>~^}uhqm2oRq~l4*L|q~O);h#k;bb$dxwVg*ejUS1Aq|d#a@r42kp|o zKPiDyI97#jZ|QB{F1hy`|?+`Q4KMS?Y;^`ob)nJaDF3x%3-hLvl+a`_e9!#Ky5 z*51qax#)RY-ei)^2%G+Wr>5v~&&KgCDctq&3xqC7LxHf9sb;TbIcjX588>7l)vOj- zY2<}d>ks()b&iz`f7b}gzNIESwdYJBSL?zdq6o!(kR z8(kXM_^_k~VSt1r_JBeQ7fDfB{D@jfjBiY)c}S!C0o^J6OHDaUdJue#fI}HPlYD^k zmdE-keheI=iw_8SRTg%zwTi#P9780 zO%(KsnHE7r1empPCXA~G-_>2*-LRg}Bp!lDUpP@}f_G_=^JUdkNf43cS{Rjw7JA5q z$K^XaiW-R1QDXXnb$4NTCX!kur9ICJK zWMu*nHQUIlqN`NmYh_B9&j#ra4WfsYb$~mIvD-Rk4}e&KFFNK_2KIBhM2~E8K9faG z=$6HeL8N-|+oylRnY?G7vT zpZU{o<=UC5oN(%a78>J{eiE*;6KMmk8w%qUGu7jD7C+kg3dF0tDhr(SgkH8ZT(`74 z1UxR(51a=);Tn9`y)J8%;Bh*PQe+-0{{DneUWOV|l1+&AYh5H=UuKxc`uutNh)yTs zeDZi}Gmq4_Ro?jFma`Ep1!QrQj2*P6CLH3y<@74^y4hk3h67u4YDZG#^iaU)z3%vl zbURX4wQZYA_8IYnSvh1)1OH5cH}7Td1+%n_KqnN;?2B^8TS}h_fE?TuFKxo)US9dY zEpCgLdHxIX%_IkQvo-`3rDeWd>tsA_Is%a8XVeu>9K;X`I=nmO3+uQuk6j<4*q+|j zCnIo1z(aezBWVSSDxZYBGL}`oi16%rIkH;l8fzA8p0roH(=@xPr+p{tjhV~i`yqi3 z0y`X<`idTY-)YGhns1yRl&xH&txW>M+E9BnHh|_TUuRZ{EO%B|?Zaq7-upUBpPoc6 zQM533gDbi=;YKWtw!g7*G3BQa)PnUzNgeub5kCw(6Z#y?ndQ^MJ2d~~Wa!3{5qU~Q z^PWfU=|?GTaTlYc#lG8!>a_QYTNNLKJ7XFKdQAfDe9#|ShlgOi_{nN>HD%>a(%Ym{RYpxo;2 zwP|FEnEATvl=b33c{#TGG!XnCQE->Qee68o+{PSe?iob_;V zXP^B|L;d@Y=ah!O6>L9IKTli6s@kvWhc-^@mA6~R)m;Eg>(~@ZP{lUJH2vKpSCy&^ zcCbIg5RBOaZd4Wa!n!3}&!*_jc#Zr+E@rM0C?@?*Bg|3ho_cp|mn@{9H>`HkX06O~ z@41=3&;Ap+g+<~OmUC;nkcalYe95}TSU7ov`hfSBefsl)9|Yt(d9e3X1q7)k$;>l( zk*><`K4KgCW6EN%z)cl%r}wugz+;%{DKpR2{!#3~HHqTRK!fAP`Kf)D7S#`*w@5ZG z5?y9*B;pX4~g2 zQ!(3cS~WVaYW zS`!r;q?4d>d}7}|3kJ;8jpe>F^U*3-_jS4)w#t;>=#8wfe=fgNIcK#d-;*f(ZFJGn zKnbjvm*16LhPGQB%iqGH8T|(4rFQ;}RjZ5@%l&&dV!KrRQgM|vaC}x4>FbAjrGWaS zigCNjD={i(5L^+XFt5SeVhl7h8BpnEOSO+gjZ%VL@en!@g8AUMvNR9jxU2qPf$&A|pYl#T8==r#NTIcr}3uE68_WRy^_72-aU zO4#7X12~7tpA)erQTH?^^d4DWqL9Dt_|=oct8L=a)cXzYOFLOjx&DXKqq18qDMyW+ z#VuLScIhFz{b4#vIvv)+cMC`6EY;t0KFnk&AeT?~7+Ck8h$+yD)BU@TFaFWx^Lq{# zaGI6|-<3`5T$h{N0|9};}~Uk6UFe>v$h zoz@F|1xk7G6-`@XP!-JZ95NAXym7j2cyUX=+n)Rw2_*G03Fhs0Np?%_g5AIVPAYD7 zw!k$}OIL6EVm%vD+PE3-a}7q|vakwQFc*c|k9I0v_q2w}$2tkpXF%i43IE}DB1}^A zn)vo796QpPNc;DcneA(fbcJPUq?H=!{N9IgXCfrH!D|-iDPRCzt99h#aKy zKNv)Fut~zsQ$0VYH{w{Z(zN%<6*BvcDHFtEgn3!^D7Wmk^$!E&f=4x>bF`tle%!7TG zDQvxc@*x0m392fzWA=r`X7A67x?LRA9h&tm`L$_QXjK5V24 zpWy%V{x@tt$ng(9$+Z!t1B%Ty`Rf3KBPwm}k)WULS*+r9LKP>9tY24t3$J{1Z}XC< zKy-BLj0h9fgotd2?Q~)Z9#vrWjLd8h%XJ&8d?s*@Aix~Ld)e~aRhCwIIYP0>gvGtL zf}a0&jq~3&Jybln92^ab5;!g|-nBUL<=^UrSdM&wGw;Kp!t9uDQ}=f}=`#^9F^ZEl zY9O5h+2O?LF^L&k8D&qVMEcy}Y zSCzkJ1sAZpM0<&dK(^ja$`8DEJyKuUbNvYG$;habW81)(@8;?kqA~nSZ6(H{-^3l5O5d zode}Fgxe#h;_iM-D24D7tbay;kGx;eAbmqu9GVtNSu|p*y9=7&9aZ7?lCV1ZP1 z9CLMfxu#U8#+*sZWq`G~mlpI%I1!>mAFr0MSr)WDxhaRCwe7fO3cKYN?dI8S)Y85 zdL}?Gi2$5spu}l65NYWi+m?_uKMF_U8FWXQJ7b>x13}yGjz0_kp*rx3S@)xU;BF>l zglb$;>2S-Zsa(slF;2BkKFaLzF;`o+dj>{<63*625TVVGuA$imeZpQ7D3fQg@&97) zt)t>vwtZn@1PLT)f(K~`9;9&z*3jL!hQ@<7?gR)#aEHd-rEza`6WpzF4FrM)f(Hr7 z>#b*>d-u5Ko;%(*-uvFz|8%Wht7=x&tg5xDru^naq#!FBKqRh2l-DwLS)}qFCk?C1 z;OLQiVS!Cfs8v2cvfV}~B+2IPN0+l=;*vxITBvJdRqj)arQun`BXJV0_A#ux)~r*i zuddk@v@eTO+_c!pJyAPYShh!R{;|_~H2P=%)If~EU9id=<!WW)8goxEKkUDIFvQpg{cCvRa2RS&|MicBLk*UZ*nItbFY+p!Wye1J^>Ieqo<-AsXdEfT5M*aljJ+tIa2Z(dC>lSj{6=2 z<9PD4zCd9c{v14;N|u zRx~$TiHCkLT60l=glsN}Ur08h;GKA~c&b0r-KqaOFVGqJ+3?``xkQWk)ELy=jFl%n zl^)kg8KG%cXzhxF3WGkZt6?b6+^~s$C^VH_1nsgxZ@phVYw5|=grirU#@8-x58Blx z;PgdX$n8)H;(r;<2O5Z+GK&QnKwFY28DSgM<}0ZItCnaHX*cz1--B?&con`H=qhm{ z-u1q_S%YFsRRL75K|3RXpJ!*DIkRQ2;go+Ov+TXSb2vhg6%9zv*z?QKjD=bTkQ*R@ zM1Q`+qy{ z9c5JJ_N5Dvgbv0HDJTzknk7(5HRQW8g$YwH2}W#c%hcgpyjAiI_Y;2z0BhJc$hDvm zjQte$+vF+vz!{Fa+lL=8MmZ#QgfAz?+Ub_r&p6lQ-dch})RSrN^>JDogzxm@10Pqu z1n-F*yM}1Z&#b#cmCxCqJnSnB3hQ$qRPL%yLYz>5noh)G^QRo7|4?WyO=!rhdHcFr)t$oPz0>|_*PG0DV?!6YxIf$GaD&H zEJDqJo)`V(u))-E$F>u$JP~cjdBRkiSU6!!e+GV8YzGMe3#paz3;bA|gB$n*C@yFP$&80M<&I7TVp}p>>m>PNW1{Jh4gb zEP02UoZ$HguS|M*^b~O_bgk};T~o)};xkHDT6GZ4|0w_ow-W0ax~ zj@e{RaNLu=!T5AeojO64$>@Vxm+-YLO@~ytUk&LJGoPY3Df*HCmqGG&-=uF11JNr| zp-;UMZWElbQq4cGxakz@cfzpcw-#bp1Lx*pP}E#w#a% zTq~BI;gU{iC$4(e{s>XEpB(Q|OnSL4U^0c=0V~Mh15vBwP&xVV&!krackEx|6U8`a zlRyzE&O_4$xJwKZoJryx0#Wo%dnMHbQlD~;obuD+iHw&SzzEGbm(M+`Df+s*;!(#5 zTU|>K>xkVo5xMlO%aCe-ThM?}th$n4pWD2HP_6emAM3|YS(Be(O4V1~N}0-)FrQr+GUYLbJQ|Cy z@4<;;j<*%trwWeGJPKc1y&mbCT9Qo!C8`%_(GNyYFxxnx6wt9;v1F;1{zV>l1kz4~ zT@i7|^Qc+PG}b$@OK9J>@|C$%f&uP$#Z~M?Gs?i^p76jFKJ-qZ$z@MI&eo=M&0Jux zRYpn*_=KL71;0aQfO8d+l5l={#^@nF{GI8G+Rn)Z=~os$o`5a~sM2}~t8(PG%-mZL zq`N9B&sv*$Nk{0=J2c$B2@FUCyGEL-+YKlwyA^jR&LI_~=j{L(C)w8`J_V2W*+k16 z1GsLXZbSH)SF16xH;L{G8lzCEO7)Vx|n7V676Xe9)@BbYTq<%Ag>*8a0MM8)oukUIvu2R#*p}^X88&zwUqS ze2CI3E=X#cB%LJ90m}xerlL{<6J#LNS)RrAvG-pdJ1AZ#3o->E8@J(M=C_|H|(6^9=vTn7t{_ah_0z)xI zr3Q1fcUl%;)<2-7T%yIQB)5H`p?k;RgIvBy7i15XiI-CwlZy8;_{fK1`7vkO*OA5( zk3)B!ZyhmYgHCw{+l@kvS|b`M<$@7>%EJWr_IkXq-E!jHHQL%KHHTGt2-~!qtTY3N zt>dkn6ekK~cm31T8SSIA3#VU@7HjsH_ll43mN8{63jw1w&&t`PD|8sL(RrpMnzA6T zkpPz!U0cdmjX>!8Jvj2Mim$XXlYhOkfZ+{t)%4jB4}vC>x`^Qe#~0=*LE@QDxhKk5 zObz2M>7ND&vL@09DxMX}Q}KMoSi)-Gp{2~9GOr=#b*CyXkpp~grM2QUmDh+ zYCW$)zEUZ=ChVmi@Eo*p0=>%WuSFUu#W|*T^b<=I191+X17glaFF~&hf=6C+Ur|D9 zHvwXinZ%#76brdt!CF{MvSDnVgfV$h?tEWED1eWglqDY_CSIAq2;l6L)*s$&QzIs8 z82gnhbzLWR!7rbEqwnA z%l2LpVU@%T!xq8_hC>vi79{D~8sF`f8eGcG1J)-(^c3Tp>%TbfXDZZfO(N}N;Dnt0>T&Z?P*I%Vs4S?S$2x9pcX|DZ zm+c0P&=D2v0O16{80vkYSBe2wObKaJ6!;k_0RR*T$4Fj-32yvC$6mea74_Y-@Q1_d z3EyUD5g(%{X9#NglYJHfIldIc9YYVr@b#hLk?CA}S+WH@YVkV$lXuSqE|(ajuR%cT znE+<-8$cm9h;@p$nTO#k#6;)@C-?I_{nBw`$K)Gi8%Y+?Nz4hvJ76AkE0^DaOL*uS zk?BBPMImGLV6C(++l{T5tjdUjs5a5JauDAaaW9uCgN?XVZdEEbTh#`~P?t{`OY8d+ z#}*tCYt`6?WE@dd%plda?`V3xa@7bAKJQ474X549J>DdW<=T#3TnMG1iI<5&vL1{b z+i>byKAWj*6(WJ>gR)T$K<%;`-K@04MPF(4xN49YjFp$Morrezh5CTeXev1H+%Wby z#HZ<{Qnm(Xp*03}L&90LT8c;v#_Y+l$1N3Rj$L!JQN`YzSA#cM?P1_RZJ0#Wh>(&} zBfH<+U=C2pCve)&h*X*sd=MKePBdnx!)mWKt3~=T%?_jCAjr*4^SYT?H}XLiQttW% zq4bMi6)4LrjsqiT;4BbK{1ujP<6Zb+1IUUgBZmCjJrtf2``j&Ku@F+P*kM}L#xE3f z*Ig`3uY){3)2*|=dPH)^cJN7{C0(R=cKSJ*989;mbanTFu>OO$u&z&VNR8xx=4fTb zK2O)VY`!4vv6t5Pvlv+LZit2ou#Ph;xHkAKdN0B90+M`2cHJXc>4@~ zqz!Y59?(n}%!Kbzn_NSThIIOmhIYOW{PgOg@~e^@FVa`lQz(T0JZ4dVlChs@7=Vxj z8@rhd?L*;%_Hx7(&mwofW#%mm)$3~HwGfriMidCHJH`!irHH09YDK!X^U=4OZ9^O# zjy|j=frnbd4v8?}47``Z75C(XmQj$n;KAhHi4s=fspOTfE4E)pEqA&{_puq-sz?2W zAAFRtSVeu3b<7jw++qSVayj5z3Pmr0OOtES%8;osEp0aE&>dOw%|_){Ys}bg76>pL zZkg$RSN`=6Ea=45+tE!cgO1btaoo6{* z2N}gu>}Dj9%aK7kP~RKKT#T~C)~Jze%I5Q#EED+{lA4AxI+o8|Z}11!0J;6W*IkQ0 zu=er3qaW?I&_dFm7bq4iI&W8P_cK*d6sXqbRr$?(yGM6K-nZdlb1_3#2p=RToHg1q z@L6-Lgn905P)#ef9*-cI^jpHGZ{2HkG*~}Y(53ErhzaL%T}>+_V&3r3d_w8nJ2_ww zrG|n^KN!hu-McI%+`eaCTzV0gI`ZoF5DXJT5W9ip|K4ySJ)vKCZ^)*jF}v^Schx7b6)c#aI;VMBRA+%cRLibs@^~ zG5-CWKUGuK;U9($3Br3F^oK|hQ#Q&sRw?FUHWJ%g<(`^8D_W|eBW!!i<)DQU< zI3@70l!SDaaKLS@@>8nwqL}%l6~+4ZV|v#nyC@W$ zF%8wKSR^dEM!;F!+mu>q>@~(P@r!6Mv1AnMEG*JndN>DH8s+E}c^skE?@(@G`LSSu zN&QcGzU23rS%}Q!?0|7~fG&m{G>jhsJu!<*fzpU}Ic_^u?|pEn0rIHZIFxrLr3-9k zEok1J*wvcToKwtO7wgaic7d6~BZN6jXNCkmP1%&xuQ4oFOtM$ba9YKv1}X^OtCt%y z1NT2_)3)tLWT~&A?Qu0xk5MJlwP>9(4pTV0afAx?5u?VuoWNQ2B zQ4~VDDZhDTN{T!pB&*u>T|;`-hr;X+8ozA}7keFs!X`}tJSvG{)PSt=LE5pH8 z1e+ZJqhB(s%a{oA&qHBE6c5Ivb?7I24GB7D;~bbCKD*@=Ygi~TS)_$5ljwvfm-Q+h z?Yn0ZeCHVWR3-1m;J%epQJot@ zEUR_<=WTkv_Q_Bepa*qnO2g`&?cxP}`)O10u#(0Ot8TA+P%LLC&#Q*ABr^9nxK(nr zER2xF)A)vX>GZ0ZnVGjj->V1Y;UaO^>$1ov2@6cIa5K+-x~G{~I$ZPj2Da%F0Qte| zhQx|rlh(B^!D#D!DUA@vF*6u=QRLG#ucin^F>zcXX&Fho3*l?)`8u{w;6}a&Yfi^` zh1y0>TCwouD$Gan`=U6L_ww->)ML`uUtE?FM^X97J%Ol3A^Z{0eLAcgdL>H-tcb-h z02fKfT$(M98QE3!!i(kyXT)ZCEqC4s-v+B`Ip!#K?K0Z9Cd6)XM0Psp*Y2d|W5;!* zN-K=s*28gr?%oPgvWX3eC-L_s4zDM2jU0DSV^}!A6EllxF~5`-9(qrFv$X^7)II#v zmH2f-fWLNwyvYT*xm-hp&~Xo#Kf8J$3XgGCratoHbYiQovi6Sc&Vfa@bi&Z=U0SHw z8ezR`E$tcy9`MCmDL+~nr?u+ExU3U(kmra1K7<=YiY9i2%u%Y#dIozRu;0muXwJ3L)Xv`ckYyr}y}qePh7d@w}42gGKM}jKL|H4gwnSKSM`qb)bqRE2~vVq zdSwcFd*iIzKGtaUe*c){O<}%Xg{4f{{7EL>Z(BrpVk6VjYi7CfMHl{Wu!rA|m8c=> zg129kVDtB=dqQY!<79nv9~GTlGlV9RfD5_;m0wkx2RVIW<%f0rqWiAYOU&j&u)lGmDLAe1%$$U2$%*@Y&QvWK0I| zW-K`#eNUmBHN(SF=o8xzrm_o$ZDM1rs0wMXY=szN_D?ju8rh{ij`D5i_uRW_iU|k- z!ts>o4qQt4R>PPlSmo*8-+rJ9r&boEW`zZw_p>}pA3vxXj|rGp5}(^j`z-K~2bVv8 zO^UKFDwWX{>j6!Vp1$L!BQntl%G%Q=|82OX@Q7dp(tVH8ObZmR70F!&Tfi=big-kWKS=>$GfjmwXDZ`LI|*^T zw{8ziyvZ1=m(Z}srUB>Ao&dv{qCANrV8b_K^rntl1(=qM`e$mPmA@c)OERjYZRN-KiU6gQ$s)*~5Um671AOWx#)6E_=sVO0@dPND;13ILxpO?KqV{w$twk?urw01RP)?zJm<6zy z9%x|nf3Lcssj`J_tn%?9Yq;v+*Dr}G0r?F&%~A0t2X{7G}S%s4Ek$LF@69dg3Q)ncE);0RQ@|gK zW|ElW2)=X=t(&q`Dw2u-XF~&^St}FFY>aj=476z9pnRGk7CsYos(Oe3slt?qt!{tl zoWNY4ZGxHX^Uc$H-FD-UI9GIjC!1%6vP4nsy=y)H%3Cd=Tj9Y;0!!qXM6;D}$F&}h zO-j2Qh}JGW3R)nQFaPmmHeAkBc+C7Z;xm0c);*hFY^^i~S=H#CE&am=3rpv-CVjDi z53<`N?A(u3grj zxN`SP2zR!BNl6+dqWe$YJoYXrI4=%r;t>5URWZAiVL@a4N{4o<@)vrvTUFw*+xIdR zZr=T^!p>h(4EbLw{s(!we~Zpl@gH+fwzH`fnjs$b=TeoI3lekt~M;lCO7_aym0yD%asFruNUc?Odj z?t3D2oXVAXL_~#DL%OvEp4_K6{P`D{-y1YqD0n>FDpowcY?4KeIgvn!yTQhTM)r_b zeAS4EFWDFK4!AdXWVG|(mSK#-TZL(Aa?SV(uY?-i#G+BhR8woOjTq-I{lI7cXeJTLixu_1(&kwHBT=By-lsC}N)v%Cll+<4?8} z^)GKKanXoTA|1<#znk!TkTU^#%0FBqXZy4M)p`6D#Xp;}%t;>NUNOQNPsBdVmKU-bLczoPg*c>eqM^E;$f#_d;ttk)QTtQ)t?u4yokn~txqf|Y`yEL%GjS3d({ zNgGNJH|&?9^0CdoKG?PUT9Y0%8x@I(PGT~XB6Y%QCc{9A0fG)7MtFxuF$s%jTA;sJ z>+0-Jlc~qDf(j6a$=1Xm^PF@N&Q!iy@TA3X9bvK!j3_l8I9b+3UBhcvOSIRYu8}WLI1>7w5yh)#LCxk+??u|LC2N(-oy0hoWqT3dAU$~A#VsNup~8#m=29Pk1-Ai z4-XF>blRg!%@%j=h;UIUny_*)!KmCW5Ki6O7;Owmjr;1jQ8SlyJV;*;l&LH z5oisjj9@YY_X^y5nk^W0kcout)mDBt-hLz89qTh`<3_0n9%tl7DoLP}@+r2Eb*2`c zf%rB4BJm79+WZRlekv-74D1^^Dl=I*-XSYUd(|V!q?0am@32M9`gAum7T&Ce#Mla} z>mURdb@}7WFitqSeHHU9kB6I#r;Y1R8I;j6*03#fM-Efc*m56Nr%_A; z%T}VEhtqb5Gt7$<5|~f1t34qf<&wsD0raPE2qiu&mG`f}xv1t)Hu4ZXT-VOhcua<( z>4Z!k#i^vITR?aj=7vn&Gzf7jL>dSUb-H_DrO+T7jg_+c+&X%0h-|$@)(@6ue2wodog@2Icq3RHkTW8uSW;PyLngUMj+*)J3G{e5~Z1j6vyVnn-pSj z&g;s|OS#5?Oj1c@Gs8JMSS7*0D`4gwMZ1$Wyr4|--kyQwNId!h1u$|wm@m=*wnl$7tq1c4|wt&At zO9I(w%@~)*9c=xp;viL1o$l4tzi_^S9kxaNCwZ@wfP3+FYn6`eLaNh#+V zNEkMjR#-&&wdFd6c01>bw3lj8(D&o6jyYm7znciJ(t9Rj#DbV_-@3)P`h`PBTgG+m@6B6Dwp?DKqul1iLJ~n3@{#b z-}7_RmK#?~R!!AV6!;K#Vu?%8ng?c{isguW@1Kvul+6?uV;qcna48~k6&X3k0uu2!Sh z9hEY3&7wy8PtR?J6uz>Llz*JBi-PFpX|VMA^`C5eP4+=A^n&{{Cf7{%==AHjpF}e) zIL^OicuU_6hdNz9j1EXn3661H=P!G$0BD#)rls2@Ln=| zhxqMeT4)lS&q053(7t$>?CcS;FRgH1wzCI6a# z8NnT*6sTxVyXG7N1E9GEqm1N9$U{47?2w;MyPtw02A&k8yalXy3%^jZcTJznF;JMQFnTCo4mJjTb@6pFmCf--&|QfHNKk;rg4R6$kHAtAF}J zlG;^s6g^Tkm%}cZ4v)^##)@*w|mxn?RGS_^))fvY+#CWxiN`=j4;y^ zcwJpt8GOL;Si+|u-tM%xx;k4ZT;Fuv^}8g=K+-p9!e0~W(N+Vh0l<|k&Cb@c8u$F; zOA)&Lw#y$_jJxp6+P1xKGGxaJd|z}xMHy{xzW=x|$kq$uX*xS}u?HM0}ldKR5gP?hmYrBZ>OtE9mzR?Gr-Z zRM<=paehl&Bu-r&o+R!)@F>aklx?%}+uC}KiMF}>Evl@*7mYz^K5!lRwdGW|Jvm}N zQ)3{(Y98ywZJ|v>E~il;*vhofTg~kl$bY&s__sj*bjp#DkyI#KzLqcu`^1hJjYgM< z!b~P8Mp)`Z=2h^Vn0&BJH(DzwqpbY#50hhHsTFqY?Ti!~v*Jg#k}S3_qu_!SHa)rX zk7w%E)b<|uuh04_&N~16=*E9~p!{z=@LN9@fr$jxHVOAGD+R6Zy zVzbx5SXk?>{~PN6H%JIq5Wbe0ko4y6(|_>;E5PzI3npYZ^>@Dl-!r4=hVCC&c%!o_ z>kweIrbz`?6T~|CcASO&w#U@RYnX?4kJwANEXb< zVaddhCu&r^Q}rla&$sHPXDZkoqMk_Qg6)k92sic*=u56&TK2#vGD^O2rrs5p1WFBQ zPhLmpslbB=;*h8%W&9Xc=Z_QcUBS3UyHsV2e?~jg*M$2odry`kjz>QN-RsT`=)|0W zRvua}KIO{gjep|Q0#b(Re}4F_$u(*`g2VLA+bPznrLa2*W?=n9RRln!ngK|s+}>|@ zW$)H%CsnS_AQBpe{S)7#M!YYRBy0^Q-r?~&^>FvUT>qHz#JFeMP2cKmq~IQKeTXGUhvhu z{EiEWKO6F@UYXb?6DcU|=MpElo%i^nZ)ga0PmAk8Za1PnXM88Nzh>OiDLNJk*@RSk z_eraUNS6uCaiV-aD zIzpIbKP0iAA$=9Lm*1x z3U=K2vR2|^E5|6&UPUS-6GHC?7RN@a9jf`jCUGMAr-2_>^g@pZxBHCDUq`1=@EhBF zTl}&g@_miu1yRMZOIs7mRk+fdf4TN}{;L=hk8l1SVImju`&HJzB>C@W==sNySWxF@ zi&y@_Z}DDl9tfz6PZ@o^i#Z_s&-(xAs7$bdumF9;8BCg#`Az32{-(FWvIn*Iz-I2S z>`GRc=H45g-Cr&#&tBR1j$`p+{Zj_4zFV}dnUo)DrG71T>+wCWUov9C-Z*Go9;Xk^0!H59hi6D!bHlt;3wrnP~}Jvh@d6sIbZ_NYoV4r|^LA zJf5yZ{Yqs;1oh~b&DI*h%Smrp8XM4c{0}UP{~389xlKn+dn>h%N2CpxDDW^RiT3L^ z`<1~1RJYCjm?tjo>zn+%?ejAnjc}N!9|fb4^*N~`Po^|STtX&5C{-`WcRdx=qm!tkp*s1B$0~-xx_+OfrA2KAi98edW#jaVa~J=OF658MPl+ z9X!H46o*A;!9tx9K-zJv#~3U{Oz<>+lfNvA$M}i4hD<5D147)A5^X-j!ASQ@yXdzG z={?6_S`p`BZ+QOXjQ|c`n_cQ!wKpqW@lIs}`)jyP3 zQUeCUGo)*k$$Ft;NRWIi58a@3bb{Mr4{Z^=@h*^R$RVOaV%uiPK~JsEyp zX8#{ghG)O8H`5m!3YGn@)cI^v4j}x;;aUF=9+ue?G6pzpX!RJ6sdKtf_Ru-4MkRwI z_)vF7!*F%*w$VFT`LyIqd7U~5|FZ8_jK^e|=N^~5n?JB#dR(cCEckrhG(BT9YLy$l ze4o5;bsppumU{Y@Z*lza{&{jD8?aF6iSxRgphZ5O1|cP>x!)Y(!PnuG>vXuF%L17f ziYC~gRw&ZCX{V8eF3P36#7;w*Q)P2D>5H0+ZzZ#LiUj>~&c?N| z;#dAxa`pFdNDDZc-0W)r9HfB=FF+kc8()N#v#{2p?xifM9BxUTPQMQB0V6qBHbCq5`gejPWCQx7%;6C< z4pu&8#9}^cobvwO)|vKl<$dWtusY33Q|-DQPkPCx2g=o=?x9cPa+PG>CI8VhnLk(& z_R0A?du&}jsi2Y>XQ!6}2H^y?}cl(#@gK`mRUfHCl+BI?s43>*XYL5_|UTdBqd zK$TcmFYJKd$ILq*h~P5`7oqoGHH?XtyiB-`N!nW9pVN8_S}qTx z!J`?b0Z3FKQJS-iMXQ);?zFUM?#r;1+`nqolJqLqV!5XI`*+_Wg(s!!bNa~T-L zVkqpEhS^~UDsC?1@pTV7rXK1ig>;F2D(@XBeLJtEEDApU-OrS*o6Fy^h8t~%M z{M22JSPlXE2J?xWw4@2uiusuvVQSS7$v@^c;ps!c-J6z;xgWWwr*>rco)V<}b&fzse?>2JuQH%nuutiyUQUyt6eB%h2cRgl;e?bT%6v-#AP_b~m z3!WWi0poKyQ{Vs2_~llRi|Uh*c-1I^UOv9iY&a|yalxiMF_-@SlXlTd)J^|l`?=}q8+SYz*^s;F*I;k=vx`qL2 z1*Aw~(+eIdzN~W*X8DUwG77OY!}8EJbqgsu7ad+swfzki)hdBG3|#LPMexO#^^~U> zCh#=+W0|V^%K`xSbLpYH?=MqyWZ~rGb-LqFq(+J|m-@Mdi*{}8LNl#0UesSy!i^H& zldE5n(R#R~F}S$s9=9`yHcLy!@eVvM99dbe(#r;`_a~6T`M}v=9jTZ-`i<%_{xBu& zBCk6B*sux_=DK*!kJ`XPmNN}uXH4d+VxfsPU?BH7m1l^c9kaA-`L|n!nKVTV7;}pq$=d07+Au8&(W`YNMZS8rq z3QCH1k-ZyhAO2z#nV#^j4y-aXtL_KN2CmdwIpYfCWydmpNFP{ce&JXGA9QATRKyC6 z+d$Ut#Ha0j7}FDs;w%K|p+Al!YV|j#qYLoM^ZT{`YATm4lXAKj!~Gi_;3@sBaNb-S zg^Sw5sE^F{?A0+2UG{R);H}1p+qJPy)}zu;cqEyXh!Ri(TH~VqP;}UaHGIV5ug1>R zka%y-6+ZQ3R6$R*@3bt@MO7`OfRIIblur2jH%+(bxq#a=N4Is&)B|alw7{p zVV_xb!LqqhhB$;<;kXrFL32tkyIZKCv&&`zcLeb8FG$h^-%T3t_5O>sIs4|u-}f>5 zn7{e(>wfOP$A`;EJbTSD=92F(5Fn6w*LZD{U}VSLhWA8vPlKx%tCw9>)67Phjd@#- z^iJ`Veqeb5?R!2RN~&nStegNZ-|;Y+n7kM0kwpx3!vufGPpu4DX7 zhRrYeF}Po#?D3?Ttj0v`HAt|*qC(2%okuS3u`||k2xc_d|MF-`h&LCGl7`uZ|RlM_T3 zwc|*64bY^_#NMu`%`FfJpg@E%1thajY|V3gV-uQE3Gh}ZbEBWz(g<9OxroiKVdHM` zu0*c>ry{O@EfBnJ#qG_jZmA8D#ThDgW!A=kliplR~qW8@`$E< zwW=&N6k?{mb!Z`x?vKJb{&vqn)NXt^$5}M)j7)KS{Nsipp$IlO}BBNwzK0vR8 zg>R!;=q`TUBZR#&0VO61reRgh!F{nUV$uRi@9$6Yk<;ipW=dDZL65B=x8N3P7!etT z+Sbzrp}`5WzNq)wE{J(RO8wTJj+U-{Mu&B%^1Hm4mln@^M6r?9iIUfCM{0eW>h=)^ zljUUK4k3on_JjBinLso_S4yo`M1Gxg=Cc>3-)=AW6%vP^f2>6#`jcOZb)Eu6W^*Pi zloGMiI*BbX#_3Lgx(`NHSD^Z$$>-IK>d4O^lT*qiY5W&M7egmfQ56 zNd1(A>I})TSP~gq#hnL?n&qkXG)!mofE(7Hb!L}jXyS+Y?f-;B6D-#DFjs~6)*yC9+$70OAQ0Q1EE>5sH zNY`-6#U*lM4<+y3v;-gU#w!*`zYXR+=&K5MCy<*XpWhAA)nZ_s92Ji7LyLXcq(-WN zN`GJ}LBrzgi;9sLLxO&(iyY0k86moIEhD6SVYZps5-*-o1wNn(zDc`lrH+x%E{{5~ z3#x{I(MIzAWosuqj^-Amy#TUSoID{<^%E6lpB&lG3oo|-aw3YR`9zyx#wU{3XA#9Y zr}c?Hu#8-|PGWyxB?9k~t|B*$J56~{|$z`-XcNH#gV|7{4nRb>Es=klv7S?)WfysvIAhYFxA z3LoaZ{LtVVnWN|GMNQV3H!&MVVP;maz!?0AJ@SLH4-DYZUK<B*z?l*-2uQjH;#o%|ry8$bS?@ALq?B5?Njwg4Pd1>L)s3=l{opL%zEATy!BR@F7 zCZQ2=b@~OpDf1pA0S#V1cZw9ynWyoOPIYU{YJSy#z8Vozn%wZH#R%33Eu5olukY5OT>OM~z;uN-?cX|}%eMA;EFP)V!#6KPoy9LX^Jy$biVu`j;)ujy#U(ZlAs0OcPZw%9ynRN| zWYW4Vmnzrb3Gm+DLqnn!K6d{wiADc;Dn;pOA|iVR6-<%K(i?RQ46?IPL6m!_zq z=!Bs8g8IUH!PT;6vgW9La=g=g4}BbSU=n#;SM_t-G`kPCTdCwj<SY2hVLRpkW3I{HWATPao`|9aS-J-RNfRfY!*SV z>uypFG?kZltBx|I9(ai3Hjj6om%LyehK~&f5Pha$C^6Nqvwk~*RNuoT9;&o2!)%Yo zTS4_-L^$MMpmShOrcJr91v`{uuK0$xynNxTMwvmn4J=>|+?r^0n;yP*oVoEDr8Wtv z>Ys4gYeOK-AN_7c>hE{2xanvu>m^7E>@oI5=QdTTr`-Tf&ga z>d4k22(eT6zyXnl9ni)3I?@HMICenkyxleR4Z5 z@#HG1uAf3t(%kGzmDp8!v<*Psa_6YQgERYC#41=uPuJ&X@ABd zz7i#c)M_L?u#r{&Iq4(`yJL8?Wp?eLL=MR~2NVI&h%;5kpk-P@^_7~_zHC#)U%?I< zRQ;#3VJ^6IEYBC3C4+bE(Aw_tS}K!;+WDH-$U;rSY$NBerK@ls!II+dMq;BLZte@B zylcgJ+ve)H%!8u><9U;%YuGOrYJ0gV+PwsCoYlb9;&d`08`e=m;6gY%o#PI{f?%ws zxw>8uydWi~y_b1uT=FB2bglg?e3C3a;xGB^XS|_^7DE>%(=lS{3XTzni*~wRuYw^<@$Riza)&yG>><0WQzN zK*{DNmPiw;d<}J_=8b~<{eX`a#Z+n(fc3Qa(9e$|50<2}CrtT=p5H@W>%lwJEez-! z-xlz}F#G41gKTxYHwTsO4iF7@PQhvU1rouL!BeeXHM-8Fi+XB67Ged>cQQ>N1FCCA zb(HxMa1I`;Q!vk)srWs_^e?A^&5ETZ_h+BM9aFR|(hBIo;``UvT5M zQ@BM|3)THNgWFA6w#h}}*5w4$Ym0^^(le?G2k)KNyf{?q^en>Dt0pO7a2hp%&V zNtjJpXWMw9D)@jZ-jip{Cq=puz%4=S)=qL?A3iPe*zn$oc)gf* zPAD%^`DShDBI7dG=qroFjStCR{ug`i9TwHH`a_9z{AgQ5=DmjBRL1=Q0A`%ruzdq;ObLY;yGvE8p%zM9QzUMjrbk*)% zReSHXtJbbswbt)fCiV;9>9qvdyDxDT?C`Gi(`EnYtG`zOJibXT^Dm_s|Evih@3@xm z_fj|hUh&#r&2!2AB^-QL`>W^tHLU)oP5zZqxF#xi7XeBe@;389^Gw2sw3Iw}*hKKW zT48|QXMwRc@%5D{SyAjw2}JDvtU`%r_pX+E2JOA9ewh(*=PuVsFCHN?(jB1wQP$&& z?#%+eC*OP9lmM{*mQN-4oXKs^@H-iPHF`U*R;>J`;_zkk`}>4ae8Z`%v~=%JlfRSA z2fnZ(Qacyq+QT2v7p{at$43lKHXq-{X?K_&-@ZCt-@c%kOqKY^sff~w=#ID&w`|&<+Dm?K0WUcN`SlV;bV^z zKVhcG@Nbd{K!i`8;g2Ym{u6)B>sMy>o7q)Yi#o_IM7IiB9iQF&zQ}(0?*0sY?Tfs1xXXvjzeF z`jHN{%ZIkT(zj(Zk#1^HfD){2QF#LR>)2{I{|{vYd1$NwM} z@qfMAKmVUw9g`d?{i}!faokCN<}@}b*v|N`o?6u?9_35;SA{>i z$X`>!Sv$r4LwIzwhj6=Y$)IGOOI_` zoH}Nguoc44Pup98-=bb#+#1ZgTweUFw(Isg1XVoxYG|i`wH@b-OF?4;1;>ircl<)i zju32E=UyQ=1TDQ;YHF;hfH#+O=?$KU_+!Lvv5q4{@uE!!8B$`m>m2N^n4l~Uptv9c z^Dk7UZuJO9b?@3jRxE2TqIb~fB7dH|by5(NIi;r#c0(5%CRFGDA$-aDhJViA9DN!py2Ycqzbf1%PyBi?`q#v6v!$!E>V`04p4B_ z=5%7%*)Rd<$A8A`(`yxoHDS$OjXPAC=@sX=R0p~Ts-2QQ?GTt(Pjv^=T==MuQ(Ysd8_ve`Eo}Ce_Qd@R+fKpek*DkePuh zy0)^&8n;Zo(73}JstNn5#=cGY)Cx)&^D|kOCV06-8-k4;#tym@zZmWiYjHJ@NLBuR z<9-Y;h+=9#p#rO#&}xeExjCsO01DZD%-AttpvZf|ceN#3#PK@gCm+2^6G*bj3(W$D z!juBS`qE1xfnw3m^gH3cYA>RtBMdICt9xMJ`s%DQz2Owh4+STB~JG2lj zDRcokO;cT(g51LYp#F)|YZKQjfuGXj#NsI~0^E8raK0YWOBFV^>&QJZO{rl<9RfmJ zDw#*=*BwJ52YnE6QlS{mP2S*dH?!%$((xItjOO)Al#|4$jF3}0`hM?mh za_>pr;Gho}K#5)>u%Rr~x}urCm%I!ND--5-igV3k>Au4)isZFZLRV!09}j-H$6tP$kwp;QW@gjR zCL%^($-}1$-&fa$T()Ovb8jBO#ocmMRj-&fJcwo-tmL(g@SYW5Q~b<>v_V8Esn{qy zC7SATAR|dTL|cd(6i=IBQ|}7FX>MM9e|6_7FEluZSXy=QCE0*3OEv|(^in~&n|)f0 zdngey0t&wVoU4&<)jyGd4(>B6`q()kRZAaz0@9b-CPbE-IJcL$&N)1r%|D28Gv>RY z5z4VIiBT4;F7Ef+$&7KE6T90%zB}W3rNkJeg3zDOlC+QfOk+?8%#~fCFytGE(u~nc z610pFnbPdlWgk@=#gpwBH+~Pkwt2PVTAn+~TP4oLaH%tG*HD&q^>dc3EreCz+`Je4 zhF&o&fVdC~@hoojxpB`;Pyp%3qXL_$=pp_26=F6`+`{wd=$2Q}tBNOZwf&CbSrJ58 z;heX?DNWs^cwD0{&58()Eg_uGq^wta)om9zY*`mmWtfMvQT-NK6;@;C#O2|4Wk8Sw z)yzzC)BJl?ai&4NWSNSQx)B`8o_5sx+#5R0`rvU5+1#o5>4uth7K@fZ z7o3OAu3Usw^cP@>=kwE)ULHQ=Te1VGCE|HhpsrxDzbKrXKK4h$0z{KLri7SPIzS~h zp0cv^WCbB9u##NCiS7@lSE~B$_G8HPhLfolI@YeO{DW6!g~juE;!laQ)W!>+Drz;W z2Xb}q0%2-HZ@?f*qy){Y+bI{tNwOhjUH*_2A~rDryF$n@EfZGmNfbsx6(dL&C127X zgrK!!|KWoMU2qoiUv}zj8VhUUX71jmI$ykbx=v#onauvq)5It=uC`-Nmr10FJy3>C zPn&ou+b?OY%z4o6$FgRx+3~|b?*q$Q3#?&WAf}u)z0A+z z8fzsctI=Z8aRhik-IBAI`mvWEp-}=oWqpC>h;7H}j-0Uv=V-OBXVDWL&ach9=u5Jc zD+mJ0{l<8_Rd}%*6!JmX6agMF+sVdi^HtxuDuqVW58q7JEIO6gW^9&pdVZf;uLrzI z29ZxZJQJiVU~KACan!Z@o}+C>GGUiMO4Eao;otdmU1ghgahxJu9BiIU-4DLdY%0qk0m zf+!4zph+rCC{srNTt-0_44jdeRN#wFeXj6=jTG$Qcwq&T3`@NWEmt!C6K+F6no23} zvqCjEn`Ww`K$nWyEby|H|0M;F`FrR&D@&Po{V%{UrqVVO3KA>1?$7$bgby3263~>E zNKO3dX2S^+|D%ofY(F8_SD_e2XD_8eNj7%IAE{+D!87&SDI9vOz>{YR77@ zKr$17*-&FGD`X|!urF{r$XCRHg^)f^Q-owD*EULWrTcKGwgxX=Ai-Ap8krXvaaaR(i zb|5-&uVD9?=_^GcFFi}l06NNX?UGEy{gn2ue7ev%L2y(@PNiv?YDrfrhp;VEjM5J~ zG)PXqG%}V2Q=XAZH*+_U>LNW16cDPnHiNZXwa?BpwbG)L9Yf$daFx5VM^U4xp&5FU z!Rl6Pp~oa$f~uwo>*o9rhk)n;Xn{=Zu7gnjd&SaMWw=kD2{&JC@OUzP5>+Zv+(Q)! z#=CIz6#JvC8ZRTRDO@eYRF!*%F6l5Xrp^`l8Z^51tR?~~)g3ZF_>sagCi_%s-=`3V1Pg4z($+UJHq_>Ocg>6$^al+YUxuX!iV#)>I zXAH9;(fcK#XJulj7&EgZHej!Tlk}bF_PbggbNn=w-{qUxTbNQ=J_p*WIKD^~wO9S9 z&N@2x$WTZhX{+juX^?D(TmijxheLIp%1VZl*w^m&rJ`anl=z`B$sQXCE>O33F`Hh=Y#BIhf z>w)L-CH4$LiN2ghhT-R!li%@ z&g0nqF1j;G8@QBQHB>2g1!-Ug$^EpXNM2XCT=jixcpf~plT5P!X09o~ZayCsZ%(^eVJE8VHK1q!@<1HquT*)5KMi!X_g>!0 zFt3?T#6&iVTRMq3|HHkUJn9lMa_O)NOj7RhYRd9=g~uutoOHo84|CqM7CT zxxg|R&cI<<96MSBCe3s!JAk)%BvMOTMhs^d5c2f*T8h8_Dm~@yJmS!v#{+*B3_SeN zt9OPc%W@o=aT617iPF-KSikw1)&$OYl4efwK#K?-tR?>I{nF39 z72=wY^3`pJ2EW{_L&=zO))zWGo3opc9m9VS97TjV?iTr-vO(V$&|Vhh&DnGZ6!7N0 znWSOqV`CG`UA!LY@feoREwh*&o$xv1d9Wp~T*EVxgTocy|`_nb&(lQ(8hTP0{67)YS9B>1Mt;bbP!Xyn1R=Mf|IdM~?HmZztK6JRd{vXl`$F zs04juYDUvLIr`Ll>PM}YfNIN-3eQ_&UXc;oSyF3mYj*exX4}CSL~}tBeTz(@<9Z2p zzCNaHW)mVEISQ6gBzIJ=NMWv5&(}Q_JQdkPz4zbqaO~X=g8CWpBR5>sm-$k?@u`s`Rme~frag))CVvwc&eLZ>S!gY z6ivYgJc!nXq-Vzlru?rSJ^6D${@2oLb8MSI$tOgAO95;y|L#7DZQc99lY~X~U~9}T z0QoO~iuo_V7kuiZ3Vzv^y%*dCmQZfwIaUwyEl*h=LJqlSyf9%?gvk2bRcTjh`%Ge) zuHxAO(b6RL;^)TkI){b$4b>_k@ck<~NaAQklFmlWKY~PAP1iOyT<;bkjW^NoV3b1a z+?&bb)TGjb7ms_dSIxBUES^fPuk$o%n+OZqvhlKs?Sj~y4%}Z9`5ti=yJuiarASgH z#J(cyF(1Sy^GzRUDTjv5LUAYEZtP3EhB9r|Puu-?*m{Ho(k4q38^9h^QeF?Sn*$&F zH_?<+nk`l3IXnSL^Ca}?yjjO`vg435_I(nY?mUZzW&J1~j^vstPp}N@g6&Jb{kzj$ z8RmleVp-{hOp%rNI*0JHcRFUD8hUdoOQAq<4|IU>xWv;JHnsAtH$sFs80-`mtrdE zl60C6m6V)Durdf)Pf<2gw@@lUpb* z7avlmE>Ag?vu4VovMkrMQVYdh7mnXqm&MU3`bpa+aN!<%_f=>{ulZ{trx*mNS(K~$ zjCg)9m>Fz>JsBxQoS|5MLQ@&)bV=xOlzK!kWgh7}sMY&Ub1&`@iN+&Wlo~(PJ%Q?u z1YcNY?}mclQK4Y+hY3y|&N*ZI=E2csG`s}p49vybx;brXb6SAnwxaHtlYPSa$WOxa zNp-w%azlwFwfG2@Om8t2u+T>`Uz^S&0skhVZvEA7Kv|NgF7`1&+Ux{XxOqKM3U?~w z?UhC?7ydnII8Dc$Z05Ju9);s~W1DeKqRO(j}m8UUAK>j;b95Nb=I+CdmwE@sFFsnf*NN$F{NF0c~}v`mqR%ux+F z48-!aj zbFeVnY-eu*K3VDkrHA2c_LIsOS#k&{W4uFj@koRkzC`br880|l_(3mPJQuB5b;4Th z5MN6!)oBP2Y02s_?17{apkSPLu8jn~}crtPJqco>zlzTGD;GG@owWo1K>EG!$>}GLhpOmmBl^_*j%?HMq@V7J&?3ZUOQP)9-T~2emfRTal0DA9F*|MGapU8iDx+v-bk;1 zha;DE7KhoJ*pk&X!WYvEt$v)b3ndtb=Phyan@)8~-_fTqGmzy?)6s5Nwmm*|)B3T` zND<8;8J%@PXe|y;Xh_TUj&Xv4BQG=*m~R-tr^rjaP3D3=RXpkL?;G`@tnzmo*5*4?A~`-rcRc&_A<)&+f^Y7K#m^T>8EvfSBmrpDl*~9 zZV4QfK$(P_N!hEDNvC8?*NJM^yJBbc?BG0SciQZgLq_MQ+DyQiD{F>0?cgfb(9SWW z_@tzBJBJu|k9|;g1q)*bm18Pszf%#V_;vUbmHC>V%TR>YTV2%2PQcRS3Wk?;C{DA= zW64RSo;xZ2N{zN1*EMOA)1NVTQnfi6H$znaD7S!{smexU_V=kcX^|;)Dfi{E?NW$8!N zY~M(TG&An7Jm~Eulhlrs?MCBKj$pRKRef(Qe5{A)PTFGV`t|zSfsFho5bZk~X*y;d zY^+8dvuLk!!ztE-I&VfhD67JZvq6ck9TUx}+>@PcAO{|!nu6k4WEjD){p^_(&d@ib zt6MDRnx)#HY(8{%_uE@8DTsQUYD>~+BQQxhwf$1N30>=vEXKv3A)iEd5`~r1t_XOa zR{|_Gi9(=C*i+WB0*ctiv_dfWa4Cz6~5f)fFRRD``&0A2T;0s+3l(LLVL8pdr%CahQvXp5=6>uqp#rs zC^%5Vb0Q$~{a5GgEJJ1eHd$hFS{(y&RXj3bYE->4s7JYiKZ(}yH)Fo!O9oT(`#lzH zMi^XJQA)#Ul30EvrN{%doc9%{8xsPJ?x+BqKCyeQ0!h1qMr1<_lz0fUC6t!{MAp!j z^kH}Old)_Y(s7slZ6{txHfCp#=P$s8xJUG(@6I7F7b$)L#&u@mhezkvm!iGT*~PQ{ zY7LE2>dZv%=8Ns_zcdWygnev}TpSSdGP1w<6<^ zrNb-)VMul*1u5kwwIo9RNBOm-V@46QE`!!oc`&;j$}S}(C2*v%L2*OVT6#f5kQ|e% zmSI4r?xJ}Bu2O%+oP(D8MRc@5aY{d3O$a}<|2R6%vcf0$<`){fj_9GjFFbI;ZZ~-p z$(WW=p8T3GD03v=f^h5;Dt1Ubfm>`Xw&g~{XDNDvYlW=Y?RvvfT+B>FiJJ=Q8RhHS zKU6hcapewZhJo`?I_f*28#bb8AERR}C|T!WB9umTA6MP8d=G0gq3aF(1zK{BPz(5}gljJr+}E6s{^*u|=~#wGcvc)rQbawr2G)N}##^v&{N>`=Bz|Ud z(zM{QlgVsR*8x#w6Q$O)-==Wjo-AQ?3xkU~KnGcbjA^y0zBONurA>m4mOJi#+%o7> z6JyE%6GLYM-X9y5?s5}&oQysWyFD5RS4)~y(DUK zbqK90%nha8|Hywz&Metv5O104IK^EHA-sqmiqL_AyyyC}qO`CxLyFBv_7s>}wUP-d zwHfAyFVd`hz>tpLVPh@9%%82F3FL7cTQBwqvkB)8KzGi0&W_lgS6&Mp2q(&zm`dB` zPvWT)ryX>fMx;MXYgjgzUZ%z61k@`f^V}v)rOO-`N5rv8mktfJT`M=(Lhs~o81#?P z1rR6ayTDy~pNuzr=A}lDSB~)vbt#sl!i4=l)485!E;8A_L~_*#l55@ZoZRstzg4d9 zxPyWC9`*YWkWKGM63ZY06KF-)HttZ_(ZBQFk}mZ$eKo-RCS1Iuuc0BiN3G>1SRCbbMA!y;3K3f!A%CghkU-mwrm9?WkFpG%K2_AcPa3I; zq{u&OwdVsu8+Q0%YBBc&sLAX3evrJ!drh#EOGRmAmpTZtxn@5ini7rKm;lFyg}_qp zV+#lHYX<>0vj{EdI|nJ6w{O?duN^t*z1a0mNtWnu9GY+U@(5krx*NE>CH(e+8$}H1 zCju9%j3sRq8IQgmD*~rPPGGi&L2HE@GEHb=OKP&h4hX` zFbg8!*-#pj@fSnYld+vyy)~FzIDQX29J+I zz8M`%CR0x!2VSJ?Gu~{$P1a33*vG@`P`IPidPaW|Zf+z^@gDd2M3O6@RFxv%($L_} z?tNM#e#%|{II6y9)^S>~5vL}zed5A^ZK|vr$q?U3Nl#dpQ#`sD9({VPx=Bn86je!^ znaw83UcZAY6tuE0(J$9?8w{}XeDB5s72iN*dXcElX+^n7!(9ZErmSZtO3~?%SOv&! zM(nt4OuG!5h_R~%1ni4n^2n}EsDmjO-K+6^*a2r#T>Ht#Emz0>9oD%wD>-ArG*u(Z z9aOh#;9w=NE-B8TT+cIXAH<4RgCC_-Z-|*p^06k1m6n#EkCY%bbl2lbsw4d?-2|WdFg+mfS!A`MN|ows6G-unZdT%(Y)~o3F8~rKopjklyn_m)3!*JE zXSj%HNIZEns6_+2D=4MWtTv}M(N<7Hez0_sF^s$kJ);a^?IAI+DK^|X;G?)hhoo&H zZS@fsf73<`UanEOOt*ulBH2JvuPu|~E{_{9*kA<68z@RJz<2u5Q3!rO^PMcXfun!;> z5uP^RklOsAGO-KuyJe2-NLSC^3*-3qS+W>`NoM2Vk?xUy{>kyQc!!uy;HQk}@RH_r*biaLIxxBN6SLVq#djJYMv?N*1rwU23!< z_c=OuzU#%kY5oLP)ly>#&P>z~W^A^mz>ckLty=8hNOH7zWGgjoI*^2ZHfe`J0BTWb zcA^Rc!5UHW6dLFD&wl~lKa44wn+S9oeDXVL45|NlvP62f{l{o{IkRsdg_dkDh zyvtI^d2aGRDT|U1mIfz#cri>loUE4sA#po$t-qy&;)UZn}QV{C#N z8k^+8sevEI31&z|3*}jOL@{Ad=_ID{O)8qb<~UXhfkC5fDH{qFWCR-(mycFcQMd$z zpGI4f38cw7Fue0gPrGaQZMu#136u}`#bJvOshV7+@jS~%qg=j2p>LRYOE#3k>s^l9 zDc9&WgIj2eV3T6S2gUS|b*0sTES4J-6K~ar39|(pS}{zw@_m7eT9}JF8^`fDnMxW| zGsD~g)$GiyUQP}WWkT1m_%Zh9*yz4cjiCsy`H)}gPesewbBa8if|7{xw7*8Rs|mMsQG9W zbd_jCX(c7SdQ>VDM?IBUl5{`L_NZSbJY)vO;!=5e_tB~PkFZ-ezNEYl#ovE{stv5cO~aW%geV37;AFq$&hDL$C?G%h!cHXIeZS<>97auGeQp>LMJ zF;wA7C+-q3A5dW83U(dO4xnuqUuT$Q&rSa-guBtrMCtHRaoo9>Pn}V!u~fQ2O2$Y$ z1;<CnXR)Q16Zc6gUzyHu0fpmXyWk#^^s7&v$zI4I? zgXq#!*)D4x{LIVC9ABhI8ZU|B<=>Z05^6^p&J1b9HtzMf3YEwgXHF(Le3Tw7C?7MP zN+p8gM(YuHkc*f4wE;3^t|fYq?tb=l|1{vs4PxV80Feu&jM(&_&yX*VL4J!8xHR<(AWw7q%^KyMAsCx9#jW57h$e5D zg^0)Z{p_*N&c41WW>VIO0=J>hbIg`sEh|`Y0f=tpRfTkN5FZEKtk!WwtIALYsr80XEguat;vQCO1$oH=U8m zuyRza`j;}hqG`7o94Wv;sQ+n0D4gCWUN?L+2K zJ~VQIt#Q?Zf%_x-JM8>|x|l@K9>C`vjf7e8f>FJA_8^uqs{6Q1?r;OPdL8z${fH(_ z`Qj&~ppla}=-7c>_C(=MnTPF$1`JmXWEJ@lu^!2tJe2Go;o0tlrR|N z`gH;C{~T|6;6TsymShqd3~W%@4jJGCF(Za*1+#y0%|EHM6@h;R4>_?`1&_lb&Xqn9kh+q>Ko z0p2eC8jwSE>2PHrYW^DA$ZIZFUoYbH8)63IU%V9?;7tsLeO6jPsk#S#*zjQG9BrN#4=*;ethk zj9F#@=IKTK>ML>;KI&SUPBLtx<$n4B>DgX+R%VlyOxWkk>(1;2>ikS3Y%znTQ;^i1 zxw5%vZ=werWIGe~P70o>EJULNA_5sWUf-c}pT}VVBs48&!fbtZD~ZufGKH<|)sQLX zD)(U#!|6w#S>F!0ITXv5K&$tkyV~<=$uN?70OM6yf$(igZCV^&6f}wW3|(Yif^3O0Z*r)-GCf)^uN^gsa4yzMC|k4lo{X(;6?_&MpNrdk zpKV%hV1q$T<th3|Q9)2{j=@nO- za`0acuw#GE+$tYu)OFhc&IR{Caa;eT{bZWDj^m2}iR%5`Ec*vcRyb{yzMF^tTNbL=^B@YrNkJDc0UZSSDolgDqTeR=;Q< zaV;c9=G*7WZo1U`)Mt@Hr@0@Hk2Kn%zH(Tk``%$dv`jFf3SC4$Sc@bX)bWsb*r&2c zOhW{{`V#xS;N)%{(kRk}Q;^HMU1*CK#7w7-)zoR!DqRAxm^ACUU)mCo+NEpYU-DQ@ zzbEWb-8xL%L2^Ol5m$phz4s!0^2*4Mt3}RTaprX_;_I5*dqIdks0ucL(2uSC$W_S2 zt`>q2&(73Sg7vSRl1*xrL)JWtD{bLh07A___4hv`J-c^h{~=-MBFB53uHV7wNT1*@ zb5(Hk+-Ui7TW(rG#~Hi)h)`)WarF&K>rS*l1{-V72Li9~ofMqmy*$YYwG_LgdcKrt zaFlMjhoAK9S;Fu{v@L6Fv$OPloi$xM33OrRu3)x7r9(B=q@9-g5d1vhlaE9VZz6NJ zj@wh}<4gvqt%^F^2K7pHrEo(_9-5wG`tr>5KSBdJ|`IktJ z#t4jo`q5nWcx+{@La_%}Gx73{xFXiR7vQc6v_#=;AHbU)^M4zbDZiqJX@a1;9O$i%H>)Z#= zW+5DSX+z3OTm*!!8(4TJVdT~1DNborAn&y>u|fU&C-LWEh6Y(>8BKe~RG%!oODv=? zmANpd*_R3;7piiNJ(J4ykF{a5cB!a(_87#0*q9Cjj9U#(t;?I0FWE{cD5wBYkP)G6hgd9Jevhd;@mOSM*W<)xCqXrpQ+xM=VHQ3*1(5v(qQ1S5z<~$04=7$ zchXsmiLk;YHB}1L$IQScKB4@cQ1;b|k3@Fk-Bq(5D-kh@ekV~55>|fNn5P7II~Ru` zVTTHrWOk*C zV*}8PCqmXfhlUk(?D%j_m&apTQKfLsJ|)TF8`*~|$))$!swdKD2Dj94rdB{*7hzh! zl^d!U({LWGcgwBg>O;Ph=$JgNZ9yw(BwcFqg7m9vTe0~;lZt2EKb6?K{>A$!DTx;E z-YpZFIlSb%m~3XSk|dTbtz|+d<7~(IPno#+0yNSSj$sHm&twUl({9MT!B@i(N)aN<*_4RM{%4Jo0DDTodqW#eC^cj?lT6|-jKbws{upwYEAiZhG8v+&!bRh zO&nt$y~_&@D`FFKERBtwb8SC zl_iNFs4YZK+au|SRP>t=WK5rqgsi$FSpBvMD`jfAtnQjw_TuWWr4F|^wM9&{j}yk& z+Pq(9fH$f*j)<*4S1tCGW-RqB`J6T(fiuG)54S>8lOvk|0bOjr^5}@vJ>oBBRU}O> z-LtfUt(Ze|%o*sv4vNE7ks2D1+f0g|rFJwSVu+*EyRsUNy-TOd>7M$0&j|wf;qEXr zC0lLrY)1?|rM;i@?VV@*4JWxXM}GV3JOnMgX#y>6HPvf7{NgM z!YuKxoh%$tN}j8YMg8HV$8aZlbvt!w+Tg^YQMCrV&Gw3f*O686CUbI>ZbKy(_X#-O zY@GvJ_AXryrX}Vl&vj$G(I{`}o#}L}E}H?))!V;B2t_!P2{h|8rAU|kI`KiHs56aV z%IooFN-!C(h=|R&iBs`~9tV;gDoK9ysf(>ioEEy;fUrAS=Kv9F>ikB4eTWH>W zJQOCHSC^;$#z)P5N&c)-4|Wr+o3S;q8EvnI6o7WpU-=hh%^ymB*6PU9t9^>lEJtl0 zGIHf4wq_EUDcJ+Hg?(LEf}^L3A46$3<=IVX0Zx|8;sJN;zvv|g&K#Ac`uVi@<`2u( z(-LCMU(|Wj$>(asvD@WzkFXY*377hw3>#Exx%$|9+c_^l2;Ur}z$rMmvR#hj(}eo$ zn)oFKw?J_c$?CAeep;qOh8^UN6lBCd)6g<&K$1bcug+C!7)iU0u)=azpK z=|Wz)$hTpfp}vtDe5k{E;EOA;5aJaEZt%HfHM*cRYsXl7f|u`-gziQgG*A(?QM7^)|3@j4lWQ!qXXv zstrOeR|Q@>H#y5^ch>6PUjz99>GWeMC$mYOT!nJarC)vgbyhmRY~H9YwI$@Wu2Kp* z(`LtCO?2&3N~XI7eHUZ!$L2}BjP(|eUTf0fDj~^KS%}O6A$E+PW_j$Dylqv z$Z}s9__Q^~X(A3-pbo`=bx~UHl1*vh@N$QWZY0c9G{i@#0cwRKw9j znEGwN72BQH`k6`{9E+3X#|_J!}s;gn1*wd*%u)pY&G6ko~z%mB>%&2FUCd``R= zIFPPSa0xel$C$J}G13*J_-Ez`O|H@F^@>1SSw^F5hh#XjjFc_!<-uNpV6iXT3ge#{ zKy6PRD7IaAsDW~Z7ES|q6X}o5uGBv4`46v~w;mg4%kaN1A}ym^+=`v`1QUj*MWw-^ zET&%~Z2f&iYM5{TJws4Ht?o&$a7QRa{U%Jg7<@Bg!KmcB4bu!UCg?HSASx&FTg0E4 zR|3+1T$KEOKoS1(JdpXDT!RL(p1S-1ySm3cTKKzi{-1y2zY7uHsqU?gB73=rP##z< z{yF0}V1uBQ`bF}-!yN}}S(ZOD_er$*^ncVOxP+#newy?)C{+G==C2}u$>p!k@cU@_ zzcomJlc;aM0QY(u6cwOGR}f!?5?sPq4kB!Ae*C60DUc7sNCbc~v=a+mK~HE%cp#p0 ze&CFDpm$Hz z3~;4y=b!jl{m(T0AAEw}IES`K;N){^)V||))t7Y-r~)okL+A($&waGwG+n`5;YiVO zU5eGm{Supidp=@%hx0|5gi1zMagXxLEfRxqh2{pge>&b;L{h@OJ zszrTpNhY<0O2ctua?XCmVmZ}IAJq?!=S|-masS*&cm=rf_eZ?eHkozudxHP~uTne- z`6@514l27S+v&TUgKIni=3mZ}Xr6k1$`UA?tS<`>dHwITa8rSIr9na#lV5CMG><^H zS0t)r0FB0vDTr=Pk)?7zb`x>Il3^&-fnSx` z5iSeT8^IwABI;Ky(8t4?if zyRN1dZ8DMlT|#)#&Dc}+?9bPBCE76DwmWw93s^J+iq1^2qu>g8&dS~!{8{*aDj4f zy-Y!2mqALIhdbo6-mqx3DZ0i?jjyr$AHFJ}E9ll`n$WwRur;3_sSNCh3({9N1_K00 zRLW+>4E(7l#!G@=|01G)c(dO({!1P5_DASG`Nov3UeW9XQuA5u3ONzQ-NjhIE!U_b zU8r)U;Y;<@Zd!D?5ge?yqVac;{^LmKa{T9X`oCKJ=STprOiUZ`Jl(%(v@1oALU-kP zjNR*6=u=xO_W-s^F@pOTe z0Q`>de@2!66U*Z5=zzZ&(to?kwO=!KuC`v@o_1DHVtmfc+KE`={=@sfrP9*(AE-cF zyzM;ksf(4josyl6o2}jb2O4&+4&ILUg(Sru-ItXm{#$Lo>~(WfH~L4ngFjVGZ(g;M zSR=ia&;6`lH<$jN}S#byB}HA zCY}W(Yf{)1;o?z8om*_WyAMe(vn@H;5V0;jG17NZ+fmdxLZoh#Z!SCcFLj@9 z7etIc&P3aF_v|n4jszzE4EWY|q3aBNxx@5x?uFmI?_7+j-V4Rd*?siG@MR#WuVwe~ z`VI6obLVlgJ8`#6_t>YodoG^(JpXkTH$dz0%%8!|zYt7uLz`G!o3%*0j@$Eue?!%5 z%6a(Wm{HiGGW^XMtfwo%#?@~zVb&`4R;S-B?T13$emzOgf;7I2Gn^9q^a}7N*IwQH zw&v=W=i$NNPwT-Y+>avk`z3QYE9XEst(>d1`h2(5PWn4M*SB=?ZJi|$-FC-db{ry! z8B*>arp!g|)_dGTXCk-r>XOB^Y}z>eCR#0-ZA2V-Mt8-iRd1=iyhD~b@V>5?sjc)N zx;(eq-d{%g`C%hd0u{|NMQ>!pi*2ELGhd-nNA56A6599GAEO`S{Yd(vO0EiwbmF;Z zLmefO{v#qaIr~G0Wc+QUprl!W?4x3|(5SUTlSkOC{$`|8$>Ir_SEBYwy~hb86QvRzNM~QaF?NB_LCIJKUVA9}749EyKNE$Mg(^1?YD^32SK+ZkjU>R12dY$1JregQqfFbl zZ5bW5n~`N76PSp~b`Bwnb7zk3O*|UXd+RA_XA+S6&&o0F;#>4+0VT2o%&`E`)LuJG z+0YN~H;)CdYb-o>_yJg3*7&DtlJK2~!|&B33BCy)z7eiC=fR9w5a|h->-Ym@P$%FB zPJR&X?I$~WwB+yQQP-?N3WIr#vp<)Z%#QKxb=Ko$+h0WSSN{T0XW%&?2gP708hIg7 z0gjU2n>!JNT{>jJ zF=)1M`iJDUdL}#tpWlhTSbX1%W(5%zS9To~1%1BF5BMsMWAXfEZyF4|qd_l+1!JNDdq%L3P)JXgGhZ?Zb7DEUod!V|B2dRyBAw$%`8C%2#cN-E;z%bSv6QpX}fBX;lR?Jcv^ znO-mPwc}{|jK5`&-1V)wqqmcg>u2jfciS%-7-?SJ`?j$EF+~$9G5<-@08z zHnnf#4BeV)5))0G?x}V&v{0$XYpV`^QVg&_1BgCM#Oomkz+(;YPDXQ0R04QkP$qLq z$$kVN<8i$R*&(Xa(+x-bN)(Qm1vfjcfG)?5x`^jst9igi^O`K9|ubP%_;pbzQTg0QOABri70!ztsrg*V?xm}b!%%3tsTwbe7 ze*OBf#VBwt#{u3Y6vx@^^4$VIRgfg_lD1jAn6t8zuGI2kqr$OQa=Yp2Vn0G5_@xr98{-k1RH&Mk|Y7iN^X&UN{GP?uz8%C4Z5vfnY!u0;|7BmSj&fYa6cV zH(dCa!CN*EupYb~w<7y`z1I|1&8*s2Opz<@X+<;L{bnznmrM_&V#&>(rd$uAA1eso zLPVne{z}f$<#3I;M&;7d1x2hJ!brsxbzzeGR*z;IPgdl`xz$J~o8t>KIrm|qoGKS` zfxSgUmW~!d3oZA;f?_us_K1u99E3zu4i?>dMxT;YAuFc4mhLtgS$sIy1ULYIovZ4? zxEQptVcQ?MHvrVLxZHTVSf1uIgHLfqnA!R{E1B`z7i9Rf0Xq2S0b)U0#IUU&$u9Nx zz(P{KUvQ_`@B025XD{?G&R*Kd(H-RI?ncSQ1-q(2$)N(WurZZ#@}e|=opVz1b8%A& z2ys&yQF6RBb%otY$^W}L>_!cco0EsDImnIjH)xRca+lY1hXIB^&*V8N1%B7ofMEp~ zkbu$n^RgT#r6B)bwdJ@d1$h7d3#0HiaXB7J!T+<~TURG@O%RMX0~m1`IZ6&Kke53p z2hhRP3MBRSuk_!)z~3CcQ!}##ng2!W9VaE%KOgm*3oUPF7>;=htNRR zj)8_rfJ;b7fQye$Oh!jROhQA7k59=;Nkh-T#LPrQ!N$qP$Vtb@#Q6Ima7ai33vno8W!L@d>TF} zS2y>%1|ELF`Y*J++GbOP(wZKLy>vPsf1a6#tkW~dYBA;)z#dKXn<(t~CtUyl{sr7i z1XvLl7K|wX!pj%%2nc`Q0rvtPi^rwzB^4L8B(=I}9uD^(314WWG}eDk^`8A&0-(Kw zRl$0R1&{z_wG`Zo{{s91WCMQzj>%d!1pocKgrLe|L4`O7K(FyHwEuVc`|RgR@URJb zs(V7Bn24471@N;EY!XjFQhgXWzgzgO=pfO%=OTaU|672Y5yU^`scC; zuIW^bX^I<=pcrwUud4PC24ij6=l(!OU+R0@dN=8czIyxmp^{{`7*YhOWT4s?qL)n`Xa3?B!^cCqZP#Kakd zj=pc>hbc)4e`C7~BP(z#31}m&Vz&c*2yJ%J)lwTauz(EE`J8^QBiYhZqg3c)GwG@f zn$;X-%+zG&G46uSJAO6)xW%#ALHiwoOXt`?#;mBj=ikplB)hXZO;O;IbWh!7>AK4O z3oujKkz773XSHR+h}cO7cBr!D zvys_(z;E26?IKM`Y1dk`s59juj5pS+?M#1scn$4pflSy$z*djwChsuej&xV>f&njI zzdW;rCH*d#!h9mvNM~3ukh7G@pBuEi;L=MwKLX{t>-i3SU^kG!LC^Nn9fac#2^-7MV3c-4My0Z6uH#NePm8hiL?#aXWynPxry&_D30x12PrOhYe{hXZ0hu_?QW5P)S zukGo8^L-C#SCycEl8S+*XD@H7T*aoET>paRRnYeZOZK`XxzZTSoC`c?(dj|VCoVg; z_m73k+P>H%&d{Z{=DFPPb+0>iJu7eA0j08HBO2?8Eq+09Z&RP`0}%Hx>Z@`7HMI_~ zeAV+yzFWI9@5o&dHLnLguW<*yGaRfw&_iJl-g9Q+MOF@P%31jWyRzvlcxaQiB#)W< z$mi-vM4WBH-f2gzYVe(v+G;6vd zgiBw{T`4ht#oY}vtEa}9xUWSQ7g!H!pm>@^te^-U*5|7ahXr5q2a?T6M<$pUpkSKI zsl9<%fm{$K2W;u_x@-)yBvHdr$y_!;-=%c6!~rO^JFeP`=v4wsrY1X)rn6yOoZ9PFt?4Z(lJ|nC2eUmgKvjxtY=D4Y48-a{9z(bEY@^ zLGis{^Z5|!sQFBv6#jsE(Y7yCKr1^J-g4rl06@=Dyv;t=u!G=w~7R1 zHhi>XYrF~PRe2hVSE&gheeOH{7qL39i)Yd&MmQJfOlC^QaS!t*-}??k`Gw}J z%;nFMReWsgW4OEU8)Kp2Fv4$-bF3+5b5aXGzo@ce-Ceb$xlB5G3EuRp69T=`n9B)! z08dw04|)`&Rzh7i4h5aj;9Qx{LnGxO7Ufprm1|3`4>D5SE+uL2V>yFrZd`(2`k5(pJ5gDA1&B_nAq07+GZwQ@-PtdU&gMm>Tl#w(lGP;x z1ozw5c4yqpS^1S6JJXxtu34NnDWiyxm(A@wW;>f z5rHH8jh@X_1R|aH>*wiJcv!q`4>aOd&C7~PLzNJ?Sl%gNL49d4*J=cF?az;oerABI zbH#lpQoH~d{9lG#n;-u0cqWssBAnwiUzGBs?H}qVQ&XG_I4AelAFD_bm~JkfvbmNa z6^l2kt3y^9&wLj)1W8ED7Be8~n7Pp83QuJ50m(T^TL!4PQq!<+dihC)5Z}kf#N5Xg zvy15BS01KEhJ59oYCa+FG*H={C#%B2p`f=(cDktC&7ElD8|7(Z%Ch5YiL1RBiMBqE z&*!7PG%gfkL_PRARlPkuMQ>aZ&mZ*-G|U%OLY7OHRGO1=@+CTC zZh09B>92VA-49a2R77~xndG~rv8z%E%0j*v1?6l2xi$wr@=5O3I-Xr9g0;qY21w^h1dRMRCsT(EiMA+lS81 zovLj=$ks{&)qR6>e5MVeT0xr@=)eHS)RUUn(21b5f8pFFFP|q6K4x-D)=m-HwK9>y zAY$w!q3{$0Aa%$51z?+3EFWY!4_E)5aAd<<)-+=2ivzgzPg%23X#;EE>T`2N$u>l3 zxTe`QVBz3wm@|;b58fUv&3#V*5%YYfRkRsEPLlsgD71CCl_pki3oc3AV#%{UQF=hO zfGw>vILCc}R5H!7l+IqqR_EuumUX3^uT9A>siW*fyiXvA$i+Dx$rj4VE?_@H?v83e zRqUYVC1Fa~7>ymGvTw;(Y_3s3Gejt%m+Y=rVzw0S*Z>mQRYLp+J)1<0!rzU%TC{l@ z#y5H}S)Fpt$X0~mBh_&ZtCN%zeD36{LejiXUk&8#H&J~y9GNDMyq%EP#`F3h6`06g zQ6wTjx_CI>GWP?aT4NL_)_qJKdX9rfN9IB6W?9eu&VFQj#woj#SHhh4~0 zHk(==?RbHIpwd~~Dq=IFk%(_C9XXZmA3Q6@vfEm+ zD0?)>Ez!}J$P#x}rUQEaWUiPZ-_5gD*Wg4_?l^Olh=ss8sURSB&mo0sz@l+|fyL>; zFe_%*Vek~V!LZYB6p?A>SU6ezoh7smZJKH zTNL4)V!TlT>UXuN1ugm-c&Ak3nl8mmDndLg<$9J<{`k_vjZyBu07zwbZcnZ`cLHL{ zRmMeuymBToc0;u*p~0KSor{VYON~D-apVM^UXwh~67Xuzv)0c>TXZZd!qPIXfKEve ziKJiCH6=nr?lG^T9{D3Kcrpj3lQd`^%*=26g8*OOe1k-5Qnn3;M<*GdCA}1=G;Ywl z@odT%Rc78{e@Ns(A?zqN=DrS&PrR{?_7r_=oYehV7d{>3A*Uc7_XlRmyM9~q= zEP5_iEk4bL(awfg(<1@gi(8-$_TTXz_3Im`pw{bt-={@wu-i<^q5ay}Z2rpE$JKFe z;*9%wAEqg^n_02#WP==e->X_2+nJOc)QA{L+wWh?D0$6`UQjJ4P}{H5(dJ)@ujU&M zI-}W9r9|jl#VGibN9wj%=$N|mB}Q5>zHX!hE6}A@N3D>F_-S`O_JI~NZ#!)^*7kAK z$IS`1N9IpP3*^BH^f@2u)l6P;L58c$Kt$h_a3f_Pbj);Jb4f{lqd+2l3i(7j$ahIc zAmw#Vjq_u_^Af8?idHR2%$%=yLdJ*40EX+^k^S}6!d?Exz&7sOWhPm_*z?+>^ooGQ z^VLZ8S0N%0qW;=f>(VL(d`4{{zW7%FXe5_?cDc0sHHxnjc+(%}yGf;JG{mk7Z=g9HH(NiZfQHHd9a zeA7}hr9+QOk01#T6B`WbWzVX!&wAQ5^##jGU|{U)M(z7uB%1Lm4i@VLql?cC4EwIWUte^{;s+go$#tMUy= zfL$XcnW?~|ITs@KVZMO_Uj351+soRGR8Mwg(yKKH1LcQXlEH?{>J~J4eFXW5KZzk@ zWvLOzn*%mH;fL~?qgJ_r4)L>X5#r=NajiIPxo2Fn8?D*6juQNa$wU$2YC!HHEGGGy zpy8dRmSjIoep*CeF*XoLCBCun*n7K)4=D`h_s~=wR>ZbwxVj`B_oX>y?3)QJbxcqJi)Fh=*rrqEDk+K5Haose%fr=<^f(Lfw9g!^vN zFL-z!f&iTV{rwa^-I)H7~fI95eq0i>g=SbUOUCC&?A?3QjgaksI1OrN>=u_EZyUyP2M50zB)aU z&I(Mfq?usk=*wF9%1sRda;u*nVVhl5mY@`94_;pevNhc8KlvC;igB<>mfsnM_MeH3<3OJbx=PDCQ` z>U8VH)?d!_A9f2%Ud7Js^oYLs3s9JMyYnFdvXrvT*7g>>Sh}PW{@-}%+sD4g2xQYw zMS|xOMU1MWqtC=71>@WrY}sV31UHIs4u1okzdg3fx@%*|et85s?d~>%uMG;1y4`&3 zV&Fe1e#T$^%K;)a7hEkrZQ$-qCsiJ(AXp*#X`0MlXxJ=VR&I^>>S!H1ctjUNefW5T z)v$`9wv(@-{`+F8 zcVbzPOiN3oR<%@YEKW(JBYzSBw2J>b70;|Z8;z7%(2HIsp+))w6)_X4%Nu%wI%Cb8 z>N*)7w!~pcu*U_Q^S?{r|0m3%ymP)aD6ZQipEi(@1Mx^mRrgac|7!?FnEekm;)xka zq#f|SJ=+l;p=-tm^UxA3as36Q{@;w^pt!`_hch+uIsT|K`57ry|LdOJUlN~*+k z(A6?n(OAmB`!lNEl^q_@H3lnUv%Ub@(%Tt~U*kndsW2Ofa z)_Lwa`8 zOf2mgV?dm=K>WmA-}RNq80c zdAZ-v21u=*XWYisUAie+zuH+gdxarJ)VrhuKC+;T!`2I6NP7Fmh*)PkLq}%w&;nXi z7~Z*iAUuKSIbHmvEs9;UdLRy}LM2}>X}9vCP21&K#a0s?!C*W|mY96XUz$UM_%V>6 zWzat75B1kW*o%u*kW|B1Hou%Yn-bb$e0tGfvWM#7P#$1tCLj zmDE=F3Z<@ondvdSHCD-ViRxG6?MDcP11BZs*D>#AMeRrI4l1K24Ofwe9Jt5nTe5xb zfMBpUe1lp`_%})dlHT1tox=yUz=WVu9TO;bcc<=MT0as0pMOp6(k?7TCQgSy1AK>* ziDCf&(I6kuk;+o=g`NGx3M3sPq;MvmHX%JX4-=z@2wgg9>9wkyHxq}ZrlpKDDFCTm zomMobxS#{_s1eLfuFBsuXXAn@6*ZHj&q+ZkzU<&w84ty6q{yRfGCy9ZCsNZK6-8nQZ8&c@BX0MEsU-xOxK8iHH&s5>m?uA3$LyJoNeopNtDb(t|GG4lX~W z&1X%=oK9EK8$8OV<4?#Qy!?qM*_#495Uc@vbY@!R#R6U~rcHFn+1DS27++G3`Uy`* z*A&gLq24k=-irhLsZjMJ7=dN-dol)G2U|jHlru*k;=xyZl!HOA2{6y~ArJT_SUYm_ ziV!Vc_8>tg3mKu13@zhAPyyBbw5n)zN~S^NEp7BDQV)hzf%q4!j*+T_d*Vq8(Ki4K zTqet${K&hK`2f8=FIaM$xVoT6xP#FTxohC*SiAW=dY?z6%~9bm38K(to=dvIL8LT{ znS|0oupBI0MEbjP5fx%lzdsZEj^$zkCYm$c(TpAjLs<%$iv;fH(IBs&2bV@jgHovm zuJJa0bO8U-cReZyldXgl(0&wY5aWZH0!U1?_5kNh11;PO02q{EQl(7_pD1J4vsg?g z{HdYB%&ksDyTS1{#|5!x$K zU0Cv_JFCxxJ->z8^_NhKVSRB1w|B_SU7ea~V0+6%FDL#snN21M7F%^m&6XZ?2N%C3 zr1E)Y%jz$|eiDQUHXrCg<{cLiBz7VqKabl9c_F1KeVKtTuqZz zcq4#OG94pK-=*lXEtJXx0Y4hnv&ECm_&^6{jkrm$0S|d~9~df}9ee(#V3A+}D~_Zk z*su&=Bfxv&x4%`^pNUy2hJ{8kY9<XYy~K>3)L8hq#ypIh~qwF-uG^73PkuzL13n* zs4zM)8SdK(8&dg%h%O5|RaDZk00RK>W10AKpN!b^=`%&NL8Ksz63nJKYZvA}O^=(R zioaP02$O5v3V1Q-7VhXs5AC;T9VGB52gAYvXdzNb5O4y~741VpqNRm-&mh!Nk%orD zsVGI?YZwxMy2kqHFL;5#_Oz?ey8O$EabGt+8JCbMcl`$2ev zAJ4_wvQ26)hJtOCm=(1`Q(Z4fvCjQEq?VcTE3B8(`B$=(!Sj==eD0)#T&or2tuH?U@7f6{fh` z;FX>ecCs?_^=CbLQ(+f#n!QV`C&wNUbeu1Cww!mOVYW~!CKSyh`Ahy8`EK=+FLzzz z%ZW>_8{RSl#u{yD&QS_#U(Muuv{FSm25lO#R~SzmP{eY7P@?1ax~z;(dFZBKQ!TRT zn-&%v5_G>8c9iWd%iCc-L>Ee$b{OQPyJ}oXvQzg6OpnOy>oRbOTu(}5EPUV%o0Hjq z=9=V7b)Hwh#EBE4&!|QVqvhXNbe`!px}wz^w;nolDMzyzDc`#=72kNfo0U_;+NNar zMu>E$i(PyDL|oDbYO%~iniMusmyj0IL1VJeoK2m;0b6j&H#fJj#C@esP5V!Ibb8_{7%#ygqRbS9|6ZzbKa5F4KJT?yI#&Q+PXeoUgF7;#U?4(SYYalLP$D=9a%Xo}KyyX1hA&af)V;n0n|lw-fW5cGr2{$*gOe6#ep-<1 z)m$!Qs<1g?E7{&YQ`c?@U7)2|taP_xT%_fs(vVIf|TN5u~ zLF-D$JvdSb;53x{;m&qdQkkVX-L-ug@B;Pc+5P*0Kv*o%XY{pxG=7%z`*(FD^b58G zQrN~DG*tL5*CKie3!UVv+vO?ov4t(`_DO+oY`3rkih<0(0KK_)@imm}_ABgR1V8WG zuc()jw!*`9lq3Ti=Q}j1-11?!NOkvAJbvQ>{OO~sQw(5mgO1+(YVWjG#)*5=A|Ts_ z8!lZ^MfiCtGi#rVBJT62|uCT7W}%4v)~ zGd;0Hrq}P7dapnD@E4XCU7BgF&%3awDks`$CX6;Vx)ePjjnu!j+LONq{L!I?MZmFy zg@xr#GkuEnCP!5FYrYe|kBm^YkaH)_5s^PG!-@rEzj@akQT<3P*5Ce@YWlsPM~aQ- z4C-7`VMf%Lb5wwS0KL$Bx<|5m$I`Oy7aMLa(5<%Q1bW)(Yb@c_E4>Z{M0qxS_( z{O0ybw05;i1du=|`wrC{9OGD~Av|LAYR#1r>&O4ij2U`vbf5yR#Kxr1AJb=X`!B*C z^#OtMr1xts7=K*v&OL;C3vUoPs0!x)p5)?GVwM!Z(Rq}AtJ@YnxWJW&ANVP@JJ>AGeyAfB~HGco_Db@k62(k+

J1c!MasnU zdFGv9b9KAkC1BGXj7G%BS6pRjihd2}5$r?>*4Gv$?~hxQl72dh7U*jef78)W=qwy* zQ+^)r<=z(OYv{2Dwvr^m*#Mi_n4mhA22l}A%vU55l@EVBSkSPbi2XhY{EC@vt z9A(l4E&O+8CE^00)0QJ29Jtk3ID*!!xDYbNjK zEJ^dC`@Ya@dXd=_6&y&9k69<}0w3|JjwC<7bcPokdI*i{^^S_E zJ#v+0Qxh?#i28f)yc^g|2Bt$^` zC9OdYXzV&mIk?Piom%BLC=Ga_x*H9R;~&gd8KBB~cib>pn1Mnf(GvDLN;S?PL02U$ zj#~tS&XK`j5px#sN^D4UHrPTCme@jDI6afD`cu|9c245mo(?7epC+``3B8YVOJ_~H zT)EeI#*Q9n)a8T4!E7>bvDg_}#Dmz!FdFkZ!^h(WT?XKpB@5e^rnQg7pky6Ks79`cp*d@d>v$LZ5rtb_NI6Nt<$g8_Esc_zSps7Y5hC=u^wDNCZIYpzL;cQR5C*V>e6spaV zZBkmg6m^gG*;q;pRzr34j%~Rwc_=7fc>FL{{pK7=RL3nmtLQ%uv{vU;n)+}Xzv11? zTsrEey<~o-%1Q%5rXPdP**@^0>H(lf#Z|3Ofv)EG9Z04Kos%|@o9pjTMp9biP=`6w z8{He3&FtFtoEK;hPbaJ116Xsh-SF|E-q+ezmupkI(N{O4eAKzQ-qY!Un>Z3^ zhZ_qlNyB0sK9A^g#P4~@vzB~qz!=tp*G$G4=5@zLF`78yA`e2D$Q2U6A7?z=*z_0< zf50G~E3i(epD!`P^i`y73#G^-B8m%wv)#X&fQyQduMSAIO$qPPNIlv=sj~B(tZ3q( zmJLbGU{6_bQ3U!SkD3Ee!oI@3gKVbpG?fp%&#DI}CHmN>R#7ZTzslu_Bwam#uXKb( zr>Dfc0yZfuo*q%*1-*_HVM`;Z1r5s^ptU7e39k-D>xmv_)+$x9kJq=Qt0>10q%1v# zq$;+5SPeA*z`bvgPCi2uz}EJZ)G6a0n>NwoRy@Ao#=C?mPkX`~NDtDksIW_pQ)tBY zTd6R}nYwHG-7=O9KE1wWWpU&O9;~ehVZxcV)}+)venm3^A?Oz<3ux5q)dP==I|oC( z0dUq{7nz*;r2I|wpHT71I;G3aPJHPbMW=bW#isIto1`xKwV4*>bgA$!NLpIFIH3)+saq#=8n7S3MUH zq{yOxqc&PU!f-#RJ%YUzx17leW03AaIG|guxzkTp13=+enshK@{K?XSe*EQDr3rF* zE(LA1Rx>ntJ1oK?QyfG^A>;X+ZTaX}B1j5q;y{PuqWoX%s}k9=wQS z(UrL9ry%qGh2HMt1;x011x5eoEV)gHwR23p+=TB9W(*T;Bl;?7I?4g4M5D39U=b@C z6V8^q%cbY&=iOE9e$q;FfwzK5Lm{Nf=Txea=xB7{2O#H`A?Zw%g&^T2b){Ari*FSR zJB+Q(S)m$&gXe+X>L`fsyA?DT0KkPN=)g|ZVQcbX>12&rp*X;PrYz6_+nY5`<= z-+*1BH=0_b9b45&O>H$lIbie4pHsc!%$Gi{l7$q>Slz~P!r5i)DkBJ{>yj~d)+}_y zc3Y{<@6FxRgqPQpraVLeZJ5>5306gW;AeY8i^Ti3H5(AjDP#+j3rljPSePfkx_^Z?L^>aAK?uqQ z840JSQ+1`RoMUH`KMUje0T3eA0}Q{`p)r-W9~1#IQneaj%H=6$*A?msAhTjx)7@&F zEou}&>?1<=;9o2$kv%8!69dm~q(cmp24TLy!lDox<_p3w0jx-Z=S?)}W)Ab4SCLUn z>|mHXplKcr*Zm2=&qUdIM9+O)Sy@}G*+4UJz5?sw>+0tx)TuzG^m$E?oSHO;a8aJ{ zT=?jF0E$UaLpd7xT(2Auc^mQ|^Jy@XZtvzge((%#knqIyN#m@P0gEd>|F=?&P8?BT z0?^8vmt)L{ZW3pf9qAM~BCw*QeaF3UR}{6~eYA@W68w^C7NPpOs?D9Kr2z3PZp}!T zL*Stj`boiH)*>e%PA;!s=1T6DB^8lx9A#pI%m`2*T~3~{6arW7QD<3OLe(d&X>X`c z7e2+so>0BD)K2k?&YawAQ*wdNKI)Rr1mG*Bwnn`guC-~@N@k7|nx&mwuLaIE!<@or z0Bbky1v^f(DW~m;E$-vohq-l5#kI9O_}#h5Q|?0+;<=c#xHdZnMExnhFi`-lIK~Lm z&y~^2bL0|c3NYliOBikUt1iPm=bj;{_ZEH+6qLui-$-Bff?UyguKSVq0~xAG}mXd;-8nSn5u z@c0jxfECELrQNFPB0QHOG!Sy#M#2k*fecQ7r>IK2uGwARD}!Qm8G7Y02e41`4T^5Y zogKy~=VsOC3N4#Y`z)1!Qz zWHnp)c0(QxJOd*_c;xL5e=v8lCzH9bBj%&J6OG+XtO{{5H z5%g*nynI$pb_$p&(rmlWp{@5ZzLt}2AM$$bA;?>qL-*)iyJR<}mJ)mqx+V+;=shd$ zpi7Loz)veiS|=Vd3{XO7Ox{X;Mcu{ED>1f z9LI`DOj&fnHjBAHaz*SJOwVZBYdQAyNvJTjY#Y zW3Zipu_z6iO=oOrQ!NK4U~}xDjySJ#QGvnzOrv<#&X+A&Xb=rDvwWcwQ6K zR(}QvBEGjFfz`dviYa^BsYVlgjtFiS!Nzc|Xlh>icMhM`P@NEQ6?K}P3=$!_Hc z#<&&rMnuHe3WtK%s>Ek&4i$od8M(CK@~IDax@w!1wWZtE5;l z@jFtDiYL}Qr{TsOqFlSOURg}JV$6{EWI(w@(2qB;7gJvu@FfsAfG5&nhI|N?#qt$P z@NICpIpMkM(&ccIsTkIGCE6-10*CbY%Al8JTWHV;z78M%%yv48Ne3~o?8y-=JKNCh zG_Ggys)Yf_M3%j%jG4!N_8LEgk%!q1w5(=}=f)hMSyIRkKCyi9<=lzdB_NOwrz+pj z*PM;SfyB~=qq{cDIe7!QCCS@PGpm|gg0_G~k^QOp2Hni?gBj3MG=!MkK`y!QNuih4 zsu<`fYC#ewSe-=MsobNlMS#V0PJe@MK|7(k7}_xmtBTz369VP_*O^PRe)EtlyW&mxq=V%#^VX^3=C)KyePrydXNrlD7@DSUV1z%i9So@DN?)!DR zim(LN@rUXqyn`}Ybdx!a#qtc~VK24V|9q)s-1Zf<-KBN?ife1&Fv#Pw5$`MBaO)pj zI_{OyfEUcC3NyW2!uCGebk>O<)Udo5|NVnZg77(>G4R`Gx0fZG6i@_=TL|DeR_Lm0 z151E&Sr2#Na#A>^8LBA$QM~GDb)B^pRzkdMo7ZXmJvaty#6b+jq$f!F+^bhpaF~t? zbf-e^$f0;VeYku~MuEQaPRUZm|I=W80=7@ozW;_2As2IAUpBRcX9UI|>~moLP0$2~ zI=RchC39f6?~^PFTBnTn0L5h4^V8`SE@N@%O%1-9gU_*}ZS3t$cLb4Dl|ux1_Zq9; zuAfJ|p4+4HM^?{d{V)TK6xdc#QNG7F(Xpb@_Z>20@hOIaTQeb>ui-1dDGp~V|2qs zg->}$m|a3^y2U{8NDl?8e_55ZuQkI68IgSapF9=gs zw1;p9`v}a<4KHXz=~hcJq0!+_B0hxK(tm8P8f0gxOBZD8r&*!M7;tEEQ*+#-@O%++ zfGs;J%Ls%`>1uDdJDW*%f3mh*Qm4#`4W_0|3BQ@XNn5#Pi=s-KKWQ5&br?^SN=l^G zb#lgV6z}0+Y@G`LT1>NPdx&=PjIr%KPqav{($+H{WhR1DO8s(UQ{E1hcI%1IP}OXc zRDMEtbDvJMsvR!m$Ya(3%jGs4VI3sds+Y-G7Ko+ib|C#gal`mwU%)(2V5lpETOclH zLsub3qx`YxUZl(eJVyU$^}6x$-ag1K$ivSqc+slauChcE7@sos^#VgSpTtplBXe9d z0$Uckpg~(X8OLUDB3p~~6Qe2KQ8+fJ{!pH}q%?LG@WyWa%zqgC+RP!gD}fe`G%Zd{K~dv3%xa z@lugXq);hTW&`3&s%jN8+ILRGdo357OnO-$c@$*b|-k2#`R%=hP5tvweb|qJ{Cbw>$bODik4ce)&0^<;j9$*Y)G8-2i93D zYdnF<2f1bPq6bx5nMuoqM$h}hRX{RY`?$aHBD)ure0s?-Y!kfVhL%3~r{uY_Th|0c zl|Nh_>KLV219|d?YQ1J*Z^1x+9NYxw;Dv7wQrn z+$)MfCqGFBKtz=uuFnODF>F>MRJd+;fF(+^c&fOz@mhU7PFA{Vg6Sb8!qc|W3$*G| z?fb4J%YC}|4j^$NFXuDEmvr?{DdVnCx6$yN!A2u|JGr2F$r}3$g-Qk{wwiq4uJu>O zmu#P;89;Lh4u*p38rFy`(U6(H54B%FP6H_wE32Kfk@8ml?g==oABZ^gByrVNF3>_K zNBWxA>`IF9MLX2rv!IXIM7Ttrgi2tKstZ)Ni9AQn=guj_2-bwI({y58t^q2+t}1j6;2rr@1`U{f_d^?i5Dey+p$q|#%0C) z5V3lmmF$;Y#HKL`5sW*9uIYlLxHK7fgI3sUF z{psu25JPPYkWhvl)nb=-a3z%2zEXDYOs9+6CUaFe|3(~HTd02zj)2K0i!5nsyqOokfp zOxTgS9?A2ZSQRg@&s*EGr;@oBn>+G>G@2VFKD|l@Ul$RtG`>ZIU=OELHCGmRbeRmv zVx`j8Zk1+^CMKrtWvLL47Q$p(w5$|y*YW=8_SX08RfTvY+5`C`LjUHC&|>UAh94-< zZyK~!JUc!A#=;vh0CjcEh>>Aed1MX}5-=}<&6@)K@6>t%Z$a~3vBZL~bG~dZDL}A4 zUZKBpCOB;X4U(_m%ar%WYKYUij+PD#GimpOZ{5A}KbBQLEo zOBXnJV^e5G~{6HQ0fqH;_i#)b1(d z2zvknA^|3daP6~V0TfOkJXNk1L->KdkOuLyjY%z$28*D*+k4PtNW<>I-GCpRzu(JU}|3N1)6>G>#;_!sAUw9_qQ~6VHYr73l>DF zX3QsDTp-(tuhoETDt%9c7#;j4{ZRs$gjnUKi^5QDtU4E)e2#3bPp3NIfl>Pv3;RIj z_6&KM!mE*^JQSMIj1E?f;os|XcU5C&1`QGHNH5@&;7lTxC@nIU@4-ddw(%RqL)b_l zAvyvc^IS6Occ-}3zL*S5CEF;m#^BHcZe-QqDv-$$S*zfcWu8RkpSh0m7w(l?sJ{q` zL*RcFGoBo?$8|GQH0lSEB3_HAZ{LggQ+2|btWgCoAJl7k9$XS@e56Nto3kJ_{U*Pq`UHSAM?^2^Cj6)DPb(`FAWjD`%0iMc4 ze}Xa(V|l2Ylf2><=czJ(!$I_JnKCVSU5lf1=rKohsf|<&5rF8BJYs0zu^B9RWIJn^@ZDtv!n-qkF#VF1LF_{1y!YCLxHWkT5v&hs8i7e)sZ z)~F>%1#-YI(X)a?a?1i+ee5^1G30sKz)6!ocv1{xiDK|~8#LhF@wmVgMu)h-Z^w#( z3y47KscdcKgrz^}kt4fF-ygq?>naOeNi{|qDDggEN)bFpHHMp~ue>YX=bMj?RTmZ7 z1*a}CFGVl%q`Pq(5vYH+WNSdT3zmsP99b{7ZO>oKCA(zCA?Bh^)+tNCZ&TZzy`w0h zUrQcAYy>PS30CMr97J<%ALbSHHpP^Z>yq)7)0UPirSWVLJppGnMw|coEy$tjOrHC! z$Fnf9u6lmdR`Wsz5!Mkn;QD+Wf5EHBB_*sg-r!u&R)AT?qZcpfW5-n{7k&%1`)!5& zhS1FV*?wayEmf3rmjlBy=373DF>!uTPF^@{Rm11;C8~{t>C{x@dMfFyYxKOn5Iy() z=xv`$xRvQaWO-NtIc4CtTr^lK)#!-;ct4^yqzO>^iAbH#TG$X2?ymnj`U1jwRH|-p z#Morgabz&PQMIW9tWMKRn!{Hvjrlc@YWE5Ojj=t1O<19QA8f;Zua|e=YEIBkDPO=S z6O^UPzvGdtm=+NAyux%PSgnIl6e~bW43NY=0(Mnemw5zK`R1Y>RvtC~V&ajX!sFbt zyGMopfGA!QD@ThkMYBmb3Kl3Qd;uSrgq-;vuAz^`g64+%qPfe!YNhE3Ol?*ySki{+ zAMfw3Wv;3{^@A0wW%jAUedQ89-4k>xA^a858x$WuG#2e?dRoQp0$KkM+V6jgr$eu7 zV#GA0yT()5NhiwO_AhS=SWV6T1^g}#R=L=dIdBBlg25I$DGcGYA$S_`&Yjd$AQx5A zA0Cx)HJ$}IJFNMvM*PLUOu0h)9$O#88;5B=iD-m)&8F3d{|oqGO0!jG{VxE9uzVR8 zeE&~M3T1td(68JHmizWMHYN3bkE(m~-s!_eBphcnJ*60@na@ag4xfpC5wl>d17qqk zRi0c{Z422%K)kVY^vEt`mL=}x);dM*-s=1du#LXjYwf1pG%ce zMKl+8EcZ400`H}mTz5?1gGRdt6K(448poA?C?oy_Aj|*qAPDX$n6WC_H&0lCKgB6J z4u*4)f8*hLrI{Y^Q99?Ghq$pW@HhfRp2N@8KxUsK2#0Xlk1Kjj*P1K*Zul@k_x3{& zY9ekyy9DwGX64h0E7vnu$h0(Tz?_LHtK<)vTr01zkBe_XX8P;D7j@_y{C-@p7CR3d z;ZbuM{qv`@3(;|9D#rQH7aS)+Iu5bbj~{EHz6~mjENIRm+2A~shxLkailjSOZk*e+ zJo_ciNM0jMu^6x8j>z)leGP`7UrxpefX4Rym5jT(H9o}0>|4jP<^LqpI44PsUT2qi zT0hO*IK#u-oKp9MwRqgnt6P88oM?lNg{=#2&c|BgsAUY=`H;D*CE+#T6HxOjN1Mp+ z6^;Am=w47%0EfI{xrXee|3;O)QDk~sJyKn7mz}mmD|Pz}`rY>mQh>&c>}&H%xTHnR zp#!;F2%|9}wg;b3x4`;7UPJBYD^)!00&!(g<$ey)%S4_I9^{!|g~r6hoK2MF# z1+D-ySMhaO0`c4{DhX?q=H;r@xpORa^{{p00Rg79@SzIoJ-P>rCNwWN^qG z^Bi^fHJ)Be?Zddn6dhPvD)ZI0Bj%93yRr;a(o1?fWKwTmI_Exw%<{{@HG#ID>s-OS zns3JX<2_-@Dv+Xx=uvZPV*v&>T1M86g0kWIakzUIrG^S*37AD{tJ_ATm1w9dI9}kP zIWRaK(u&KRVO#dQzUXu?SGuT#*+S0*R|52rm@SSCZ=rEz?!*8`%LY|F810B?wz z8-DD+%!%S|V%L7L>ZO!vJ2QSotlxg7zqrv@xM0}@iYhC7%4VxkSR5+RWeRnLB+7?F zsZyingpVOAgb8*$jNp=$3qZK1OwhrxYO3IqCu00;+^J!^(TX+RkBwvkk4qgfH3mMD zAp#pLMe}l2IV@N9L1lHQLxJ=e@@OCISxhhoC$O+?)!gowAZ32Ew@@5EWO_&$oPt*M z%!9HpzsB0;CtpSGv(XvZ)#>s^uD|?~?Gs&WIA){n%eeF0nC@=Zf?7;zz2Jj*ZMqy`W(J>{52OE)sG*_mO25(bWtP;SOprs359rF{90z)` z#50^44LUgylLp^th^xm<`uRr;MzXcO_zv8SDOBMZ}~1Hp!D@ zPW(_w(nDkGw<5JKI5?s-S?fVp0j`C?s)(*xluk&^}*k7 zUH5!CrLh-3-a&?(M#*Gr|G8b>eWh%<%hD=(AEx{qwuG~87@ zPf#l#nb}{MutJGqvz91hMXx=7qR2pTMDPJyjz|uU`Ggv8TuQX{>r^3K+Jyyz0qfFI z7*AhRNil>4baX+y%P6|V&&*F4 zGVqwrOwoG)Hc+5+w9PM$THx*H!7NzLE`dchI9TIlWXF8I6!$bF3G{qRDf?C_$8W&H zB>g^`B9O_13!HcV$dIDEL&29PbxbALGEz<_wA(q`xfG(BVy&daJrf{sH`aRig z(v}Tn$EUR;74r-=?SSUeuw?D+1v{Jux%@QHFBk*9NId~dF=D;(c3Fg2|4WzE;=jT@ zm@1y3SRJv`OpUmopf`Qi>q+rE^hr;_3%A~}hUz0E-A@=bg$JQ*P&7zxk5xD;G`V`# z>R}+Fh0gs%D>oxDPI-J_XF0*|0giE%@$jBt=H%dKu(D6J8&KYGj7aFej8f)C*4G#; zmlj0YBYdo#+#hz4@Fyoo)3ew)Tt4!KHQ>zx-1%(&MeY@A?F0E{Evo?f9MpiHjaaB7#7t4bW&dR2?dF&o?(rpx~ljuPI5C8MTNo7H& z`i&F#&NWZR1?up6f( zV8_ysz5RDju_gKC(6HFLR{z_cIgz|QBf1Xa;@~v*s__L)?1w;7F{c1hSgX^p| zd5${g{E1Fxw9cO4IZ1Zr;NTxsUjXsM)AhkD{D3o6Uxbp`6js2KvEQA=-|ygZ`=zSI zJ1g0SmFB#xYg_OGu5{SE34N&-&6Z??DpxW7^qECfzt|W4zMZ9#`bzffrm|{Mp-KjS zKuo10bP$2mvn$@$8f5!8`bF^^`!?b2fWb%9xP7VdDX>@HD15rsLWa2ipyC$VFR1l2 z)PyZ6m*;{%8$h4w)Mp^<@HC`>a6D#!Kq#9v!={HOkw!;_PfIH14*NXnPQ&I?b*4i( z+T=vnU=5{ncQi6&Np2wKHd@@vC`{nJSXU9w9e7d5mq<8LhcOH z+2dC5$JN{eNSd!WOICE{sEw(|2A&@@I)zAw@FG7l{qP6Gz49y+&MA&IGO|+ZG?U^f z%ti8bI#XyvD>LuUa&w9egMGe^m+ofL1ExO=XtAidz zxz~BXF9PTtGz0-wj0e(WoR@{TrVAu-4!3xOiWbbo*lyn!)RaU0Bm5u# z?aCJYQN6IJY!_nzwp++BGNfwGdzwI4)GsU|0rZcolZ-a?LMz&0w17ao&zclX&!@HL zz=c)O(hu$$xL={>Yql+(0F)cpK~|ph66dH|um|l%{?}M^$Tr}yU+BpuG)!AWAM!!9 z!+r?-HWw*C7bWK^^0GeO*5)V;B-^-XT2n>y3#X~m#YgQ&2 zR)UrLP$gM4VJ<9Yhub75ShjII-9FP;WqE^hz$+J* z*Tl58>)u5(=|{#t_G@nA{`pxFV$PD@g%s>OBr!+)9^g*h?e3G-8+D=ZDo>1_Eod+v zO_JFoK@6$b5Ml~+Ya9=?mH8*;7(i;0CA>x9t}z3tR#|OcPN+UZ79NunU-Dl8B)s_& zKP~}M_v%;t0brfGxwJ{0ZuA!`)T)vaY91*?b`^5sR%kVdR1I{O+>M0GgeLz6&`Uo{ zH(dciW204G9kyl$rWATHU8Zl%T(__BF{8A|=_1m`-O*7x0A#l(B2V~KsgU+Ra7ik; zV?Z!YytigHi2Px5KdsHQZkeanS_!&l56NE+ASKovm&NFoQnY9 zw05{O*^4inBocl$hrZ1%9q@^sba3@m>8rA_SLn4$2r|$_KV{uh6#b5K^S=Nyp5-*i zl>tqDV91)2UCtUm_QwQn+J-|7cvhFLJ;F2d3~m^yB2(R?{pEyMF2GCa#KTPKBGNNW z{W81HpEyZ)s9eCnzOUEvMR2NyEMYwQ`PduOK6R-|L|Iab0alGhjl}A^Sbv_HI(^h; zt8E`l4`re!X3sU^>s0&>kZ6`jbQzQ_IdOk+V$QBvo;T6DDb`%bRN2pKT3zoooP0TB zKv63Mz;%d#QBZXaP$V3A3Q!*g?jh-g&HAscOtjqV;`^?Ga`eG0COwY;50tYv)91r- zge)CWL`XqMTBW}=HuC!;wSbnW@zH+BErezxjY89lwr%ZF$7{a`#@e^C6#YKd4Yj)RE@WT*9eT6M zHo1Ztni$I*)Mt2CQ(iLw5QR_2fZP=bg8;z2UEDp5G(#*(!oDB{mxx6w@0q z&1Ok&ZAQh{I2EpJU~P!_L5Lo@3FvPQ6|0m`O2=x9!vtTR-Q^Q#FhYy>!xyEvA1ZyE zS|*n5`&Ms62YYyG2liv7kI$NbPgqIgGBZ2Ab~m{4^>ECWlvb#iRa@E0j!mIM^^k|r9UCLUfKE?>=sK{Die>1P;BTGtO_j}&^O4o-92PwuvzW4=u$Tdj#bW%#qu^D z=2d6?^Hkys=P}*LgIF^GiqFAc^G2=FX+a5DuGiZSod!K6UJdM}e)%Yx5ix%=9>88$ z-~HqC?#t7Qto1WY^a0-AGLO|VN2GUN^Bx{CsskT2*jHoZ11JWgt&Hw*qw|Ap{3; zyj<#ZwHK2E=vy;yctnn+b?6&|=Ah|>gwttKtrvGT=6y|LYxL>52wjf(R;kX=Rg^39 z7XJpat3}DQ)Gxg-J9Em%prx_)L@ZxY@7ttipIz9v*Q=2O9GsPgz+w6i#nqt5;K|G{ z0z9Zzx#FtL=K20wRcc}73(qHlqF|@I!B%r207Hm-r?`5)9s83Dm1P7_ev5mPThF2f zwv6frKiPG%l9v^b)u|zU7q6LBA8v8(fW~J<8OzG{ z#qFVKt>`|Ott#@KL$x=?lzZIE8P}%Uhb%hSvRtOB2B!UZ?d?Uj(qNEZEqbZZLYJlb zvF+05Jm(G|H>ZIue^QXd+G)IXg_2^hthk58XBLoN?}#6XJ-@Lv^~SJBbrOCQ&x_bT7_j>Zj1n)9Z`fB+7IV&ru7?Da00#)!mv1v=K1s8%xr3f_6HH-jWrsms;7a zn^nG=^=VN=eV(s79>t#taN$)7sJMN9R^21F3*@tzONodWNpOkiuKo&DlMh+XF(6@4 z!rUr`3l^wLCA^}-8XX7x0jH{Bclwq`Oe~Y9>Tq2H20X}%7gl8Bb3CoN z%rwM&feaned7(miE%b9wRYuDdo@2aMFX+25@KiWaIZ7+e$|`5N`azXdO5(JoRKv%U z$jg||vTlaVd@;A}RpE;u$jB(T5bcMQ8=V$ zC&^+QU&Ej=w)|U$95tj|OB&{&v!e_D&9dtxfyUxk6Y(x~@{{rLpc@aCDglAHl$1MF z!$V~Ao6&2G^hP%9~b@27uE@5Tx(xxD*lJI#Q&Wh!iak? zg1&ryg}s|Il2Mtz;?PUKfgP38g{uK_+qs6 ze6{bO+yp&j3}y7|Oc*(Y`IT07pE%uVf4{%ZI^ln5R=Ecka~xr*ZVV)Q7oLh!E!=Arx8>UAgY(GA*qq5~yj2LKBMa6XO84R*T8em!bQ3?ZMWCVqo`2~Ve zIhtQ@BZrNm2XeBEaOq2Wrc4)nCx^~f>md)nuOhxQ&L340iVM~fypj|pc#gzo^^ zSRLPgL$9axhu2d_`nW-v80@X-HMth8Oj_=9+<9HQcv+&~h7#WwPm_ti%`bd!rZAd8 zV&5BnL>rB_l?PM$E%+}WCbD6)Vt%7iGyM7lSPj<3G_M)K=RVFXS28(2j8vjC6HclX z{=MG7gIC?*VCYtJh||z10JD_rF$RB*N#=c6` zz-}+#$y1XZ>oeCl>8LVQJv|LCGCLU|sF_y~dq`hmLydyErlu1SZ^gXEteVlsqLE6# zj?1^*;g_p4J5%J9*1d77FY+NuntzyCq_Ng}eLwa}7}nApm0U2)r5j2@bQW)EUkPT_ zw;p#j^eV7Ntxlh0idbTg07x)5Ph#SknRj?X^$1fveQCE^q7*!Ub~)t(wjJ~FJG&n^ zr2eFq@dDrTppv!s_JrqofHG!8p8&*#;cd#;uF_RCf!V6X1I%E-xR~*sVwmtv^W{^C zqr=%^V<)DfhM%-2#t{2D4t%XiBx_Qq`aKT_c`J5xJT_l@^UiwHOCopyTg4^Xo@-L# z`sc{IjTcfwY&7#O6k(<-ea;lrn$T`N>iEhrUcWdDTNZB~rH0GCKts~2f{I`7pXbag z`q~OFYlBUvT0YV-5?X)Md0#q9QC(Gv(5=op2=D-B6{q+gi0b@u`FXSTQ&%qJn*!;) zBSm7*_SrbV*ZEs~%z)7hjR)wlZx<{hz z-;-JtL%^L%>NgOW5!KwL8koI9Qe~QZwLvmhSg~FItZsQxTJ$knK6=ILz3cv(QUb;` zKfhc>D(}0zBtc9$<9bMiVK9TNC3YY5Q+)_e(P!XbpZ$nT>~_{6P{MxdO~zJjK6Rhs zkkp^{BJ(=6ch=4aKV>tlxO3gcvves&Mh)$UsDe2REJQq#oGqp+`lIAUj3obsDH?gu zxp}IeY9~&+U{!Or|6Tq&8}xboA*Jkwf!VX_9Z{9j<~s43-z4NnS{HAaG}2Z*59Mby z@PYrkkwhs$$Xq8YI9!;2mW|!;N!HwTh76Ing1Tv_9rM}p2gaA|<^}E(U_gaoSEl0)*GoW^F}AfHSo`>qsV1+4N4St@sL@Y0 zDDgaw!5cU4K;qg*mT-zlTN76&8Urm2nC*2`_!mz8rqY4As>eolP5qh&@EzXrkIp2c zPuDsrc>KpS^`!#(Ea%iEZQas77WIig*Oph@eG1i?G{X7)U~b}rvEl_IjcRda*bhzQ zwBo-2-xhD7V{*MdA`vqn$%uV^7b#&Y?LICQ-oVNhefv>HE%(ohR0vojc2jJu^-nit z2q&FN*kMa4$7V)Et(tloe0RL|0Xq(+doGgs23KG(p4P2xh24C ze#q3{N#bcI+ZcY#KnH=U*=Fj=_vr=b*0)IJbLG{X;`I1eHm_h;p~5d3-bWPBVc50e zROol5v;54A{Q-uVVn6D0ItWS=y+9!DbSEd$tg+a;YA#cqPUQyraPoejoWnUVmt~IT zks&JRV4j`AVoavbF_Ere@HOMe0qDGL3=jS`A`MtVuwT=qcO!IJN zFxAJ#Q5ZtL8hsc)xh7pF&gT>pC~}RNVJcXc}-XG6gS`-VlREFr~zK& zSUqZ$&tn2?`-oURJ>=+_{M2bc1w+xN7B=cBe=NFr^9CTJU6!+4&{fg(TbeaK_-(ue z2xPBMi*6S=^FhjZ`0MNX{{4#!gI9J z78w#!F;BelnpP>_ELXZEv#k9k#des0k)^_Ky>XTa;cx;Q0|XAy|&(2l!QdHOd& zdzHMWbl+;EwNa8Gi1mO^1&i@_dG^|z>7Emphkw4P6=tzpO2jGeL@+2Opl1EYO_Q>Qr8{^`wc*QkI* zmhfcNAQR87q71gh-7&8K7P`2?1>hfTO_IA>+`)&naGX`LP8F4cuDk4gQ>*6tduzo% z*c=r)QGq(gob;t4%bQ_6-Pha?8@dMic%LZrKL%2HAWu%_dx3R$M38A6J$G zx{es8F3GMNW|r?ymvawe+0&XDhlUWpco?*04~Z(~r&wPZfA8^qi8Y03DR<`@{{--0 z=EE#InOgg|4Wq$`GLe74eBDgEs$!KfP zRDSjeM7|EGQKas ze~L5cUq#mwcpRzzSlE<@R{|BHxE)gGO-(8osgdwZ`o-A1r#9 zzO1x=6c*L8&xswSU{sIaa4>*jhWx2H+_ z=WaOT2EO_rA8?tD8WWbKma0yA0ls#sNcNVpNLD*G^y68!E$5D3zm9S{T75u?!*%7K z-C0!jt0qu#q7pT|D9Bf$LNY8qXiGUtoeoPb@#JtDJkL9-Cvqk*=oMurd((bksihjx z#FnxPi@P73!d%+uV#RY@U-*ed8#~n1p&UW`-V+)sKX;_FV!|3e*Txk}WRX!Jh;?&K z4P(l3?%p8YNJul6<<|_Ctipzw8f#LnzZo_{j!8#E&FP%fg6K*WwTa(f=V3MXlSpj- zxdJFkqMS`%RkYh#nhr*Uix}+saQZ2#%-vQ$_~t(k+gFH;nH4aF6@_?$ZF(;hGcHJ< z0W{4&)}2xhF*p>3SQl3r-gtZ^dH1xWlUF3*U7g-1x&1~*chA3gboIoM^j$*)aALyF z5DewH#94hXKZ5;9slqV^X;l08jE0brqfNJ?2`Gtn7Hj_2Q%0Qx7?j7qc8N%4aWLt& z9jl${((m(Il7JpN{tFm3pSyCn3l27mC$o&xyRJ2K#_HA<_APVCa}#V*a|W!07>0S` zozNQbl_T4+uLjTjoSZ42{e!j``>o2wkzqPQPhfZhX$^7uX2YM}zMCspqNUB0kQ%49 z9ccnZUxXAA^zBgnopcd_vQwev2I^oG%qWwqA747soN#xZ&WGp+^nE|o= z$H&GejX}66Lgp;8?wsBUTQgu1l2~7W&}rMsySDbE>j;e}z6QsMGwD`pp5c2lWz}9J zBZ4m8dR*E8D}`ekbj?W=){{vDi!gKWufkWqTZJLnC>{Whryj$Nl8*mwpL| zHh!VVF6#whBm2ZE%`tD*(?~imCFKueN?2m*(r_QB&!e`~OR|sHU33|o1ip(Onip^L3dsSjxWuVTEHHX_w_Y5cba@ z9xZSXtxbnS7L8YD_9^Tt@(z3GP

v;$wXEO|_Ov#k&JKCIH5F)g|SJjhU;u9tM*tAHzz%f@T6iBg#Gc>@q8xU zW|H*1GbyR3fSXfT56QSrCRig%G;j?ek1nwT5=1qUN*2Z|k9rl!k1 zV*zDv01qI)53rqd{X%o2SDuNlE&@@#Js(#MF@y}pIp%bV?=4|bc}(IgH}Xu}5T>;7 zWyRVO17>afdDQ{)DczsP%fK0>K9@wM@K3K;&%}3Fr}Hl7C}^f$JVsGin~?SOy`LC_ypqOdE*{9r4|geb>23IvzQ%klG$K4r4HYI?ld#LZl0Du-RzEh;Wy@e?FCYMK}Z zc(V0mrz9b|*<)sh>W3v>P>vQ^#i>XXr=nBx!j;fOkI8CuJNKc+hOqP6VezOOJMj^; z((l6uEvJunuof17rsqqej{?&<7Z$hMuDzRlkx zqMyX2yq>b977jBsqZt?yM8^5tP)Kxoc)n{Uts^Y=A9b8Y)Xe9dQHTp`lscM)e^T|>GvyWZX=uapZr@&c2vcBK@j`t+Z z$8={9x)g?55aFr4+%v{eNlKg^1npC&88WU!{tnMa$lbS$4Kg3TG4T39u#(R}`2ANV z&9gub0+mrDc2DYui#5-%$=U48WcW#Jtr`(pkTe;n49%v@_P8Q6UQRKs?P9T*?LxfM ztHU5rZGspcHHSyI^cRP;#sNIa1-9}Umvgn@W`+vXd|Mk~LGmKv`y{u(Ys+PU( zPefjTFR|iDZ)?<&;%TWKwmym1wpJ3vcIeD{`^wZMg`{q<#;vN$_1(aH*cbc& zFMK*V>Rtq*60pKIZ^B@uP&4XBhDlRzP1o}(%U@3{6k34ce>engH~s|-nlD$(b9i%d zcIN|$U1PuypRAmGhLMJ3{Ieq>Yqi=sO2uO!tDV4{2UABkI*G0CIklxqLjE;usp;Iw zkdm)slir=WpvU@j+>5Plm0!{l&UF$1<0ZR;_8{rN2LI!`^p`dC@QA-|z^Zj(C}3^yn3AH8gN$PI6XsKsV2VOCSQo@y)12F` zqSD;di+}4m;cYpcmD#y-#pu1%Q8A-`YpZq*W(KN zL*d-~9|%fH{l7C9HPr}?Ot~}X&*vAX7!a3tVAcCgrJDhI`m9$X8pC`RwUtIli6ui8 z4xS_}J>OIQ?}jJt)^uAarxsc5(nX&&`LY(8=Z>!$eSBH1FGJGU*Ik-6-e3RoRyZ_2 z+jnGYZ=%g_iK+#TwWs>#RNck>>P~rlPAx%0snQc-iD%`5Cqj2A@hCEDvMym}Fcy}V z+h@d{7wb+@ce$2+(aGHMqNnPBat5F=vOXR7KnI0!q zL}JCFnz_fWH>Q4fT+nkm5wcB%e>VA#i1}*Bl(i&V_PiLHThfwVS`nKRFm(b2gYK%N zZoIzRepvlDv6`dGnd0=i?OU}7hQBD0eilQ~88o@jE5(7&Lrqmd=e|ncEcZN6`5T{& z=(^>m`<`E?tbxxD7&T8|vCw)#q1p(apT6%eszhB^bRI2vrAgc|#SN|ch}_cB=jjZh zvT?kSVuKyFUH2+_eWIhkFUWVlqAp0SNos=efBD`JT@H2*x8|G@wE6} zV}F8n?&fCT+`a7`d9l2$X1+o$%UH~uj;5h8>2MkDNhqUHzxvs0Si_dG`%gI93hgb7 zHJ@X^s;8?y1WtQ7)lf6s)J%LO$w#Z+1jkLKE9KPZ%mF922ZOi>8<^Gw`(M=QAyu?@ ztyqa|)^$##_TewyTrgXf^W}Oi&x~QuQL9<)p4P zh6aC|v^1Yh@DW`s6I2&FC(uHCg0|sXl*XK1UqoMKzZIYEl**Rrf?}lA*9J60+Pu^sC@f zFY@w2@n@o|H5;B8mS?TY@5uY6rzgT3I#c!H1&i5t6$LnL_Z=3s-D8##s!@|_>{jy9 zyjH%NwJEP-N3|HVTV#kb&m<0CtXCsi^7`QA7t2!g^b*tl&eLZox6RMhpYQ%oEYLFU$(848P^h6|6#LrJnJv}QV+v@3&mA&fgBEM77x(WV1y1>QYXQ z;~Aypu^iQz2?enj7OLsQD$aa5IMr~scSv-0``9)_l522#4Qb#^seMpz8?Xh{tGOUn zN;(ZVd1Ty_CwBqTR(2X#`XlvAbQ=LpVIowpRd22u#}0l-i9`o+d6|%FS?fZ~0{&Q{ zX_y&5NgZ2=$rHHqZzWhi^))@8WaCvo##@4iK=RZWt7vcTKb9kBmL9Z4{`BSYvLGk@ zFa_}yZ!HN??Cp+uPy8DDQL>l^dg^Kp-D z9GQLxY6yC7rd}QY-q%68*%z z#!WO4d6q&&wD-wFe%-D0r(_o>@0_%+YAmVK29?NUr_%e^T!OK_E578IcaqL5EWYPv zsD4Qa`#0ReeRCQ#Vh^r@WqKqpbzD)d_Rdq*yaOKXf`b98Aw0bFmXIn zuW_9e`Uu0V(w@`$4zn+$469 zfen)aK1_V4!iE!a^mxtqYsF&!!_{0bu!6pRVv9RqW^PSH7txZ_jnT0ZDXSyNnVkro zN%EY-uEEK4K^!eHLz4}g?oJbnFTc{xeu{c43}TfpO5P*j$+xi|j0j4(FpfHz_k0xm z+=o-8MY${FhqsbYgn10dl-yRj-i_oihPQn6rEyd*`pEh{nXduZQ~k`hY-IFthMGcP zQ@8UTYTessn3T+$x~U2hkTTY-9W^*2FXvqB`W6{yDIu#!{7yr2XpoZG!%s1CsJ9@!bxMpgmHz9x_!GQ%y zGebVTnz%D*We#1DHdmt68wzVIcMu~0p1Z>hameSVhKplV4HP^Cx{bCG;!=d4Dwh(O z2o)XFCI6d}QEMpz>nCjL;V{_?5JY|^sRcW-S|r36B@_3iM!0!3Y)5S4Xb--Kd+5vV z1EqFhn;b9;@UcX80 zd?~WXT$qJ{Flz`XJ(@osb8DTC#c&p~!WXA|pLppRB6Tt+9e5z8$eNZt>>7d0<&nIB zDb&&pC6%6E@91f?tW2a}={5icGPDZBF@olpFmn-2#xASb0WH=hY+Nc*r0I$wgHBgT zLh27uA}&Rl)5>oP2bNlt;DdM5%Pbbhdzza2iW9BYP^{MS}?;Mf)V%iwGKK{-hpHCUY?#_xapgu)J$||59TBdO-4G$un3+F%=3E zp;NhALhl)2Cwk!Fi^L!#u8(7x=~e5Jp;Lymb5vvDBt4nTshyRtUVO_DdrZxiB~Th( za^+th_uhkR&q~e?Yti!`ScmEAs@KNY>nV6>cbX^$O;nBc4>*~mTyxJq z9?~ljo;>)p2lSY7ZmB@^)r?`+S-YaXJ-pEoI!GUr?8r4>(iSN!#*ueAamI&9*( z=sY2b)!jE8tkVCx0Am)`-)NpcZ%rhvIl*b>7GV~>_taK9K_YMNs%F&dDzpEZ-|xe? zt9;oE6<_Ph^c`-H%{32W{-|f%giW8^^`x8DOy>T7%zb50n{C%^>ZKG~pg{5B8YnJB ziWBs~OH!anf(Do3^eL_-gy7KP6c6q#?rs4J#l2A6dv2chocH_ApZC`{XU@;eJ(&I*#x8+9V<`qtwD<0gUiDv=~qGT|egW2p5cYdnG znkeb}{3zxzRd`UZHFRe9X?sUuPtx_hnCexuK5ADHh+x);i#8hrJytW-B$9V4nVEfC zj2pWLw+#Qyx3-v--VMrC4P&Q9@#aH4RvPe$?BaBq0QGv61F_0R{{YsOSY!4sfQAuM zNw8O9B7(zHaY?%vAs+4=ouhL|ZI9~P;G%w%A zN1>S}V~ZD!p7TyA)t z99_tJ*C(GT&zX-XN=t60Y@FI&fqceB-^_|s=(c)l4Z$=8QrClb8kti?tMoplhuM)0 zujU%c)-6b?DpKOq(RF`7$YV@*Q(BSB2?h0hPsnn0!CQIz(hEwRR9E`~#BFYwXNw~N zMES}RMC1(}N3*XO5Mt?WX{H9so{ryOtdIaoo=wf1|-%_vtC?_ z#~m)+9{LLkDyththCgOis_I|nU0k=I>Lo4jkg|VL{Fzoyq-e)h7m}{aE$(tpT5_lPxhL+JV^4T8ovq*5j6aG?1G-F;!y4Hmf>LYT|54`Nxb= z8@1!(joaa+4;{i0az;7A{R=pfnC?UEer=XCtbvf{WSeEOzHF#|2_z<*-Eh$)FQHXX zs{25*njCjIfZaX(r$T}Vu#IGlgdCdtE|leER@7`=#@{%DzQU6?`0@yI@ahd zO!)9xmxKS8^ZpsNklG*BZ!EIhZ6RNx5whkOOu z+yckcCWk(V2`C?l##84^Z@+L~B}3sVx+FV~RA5(XkaZ<689~Ag)Q8Fn&B=3zcT!3| za&%}hN}F`f8;{H2Bg`ZRDe4L$cgO@$nf#5eHIZZ;y%AV!%fUl^>&P8>>b}dOEmP%{ zIX8Q$cJ zDhP`Vdd>rPu1r*Ni87}|IL`eFd1NaeW4O=EcU-+v7*`S%{Z3f970aY3Jgy;-$aIv{ zUp~>qC}VDpP@L*AFi2yejESh#zD(N?Y(MsG!d@BLkLh*BuZmS}87lJ+5k#s>Aswb? z3xG1|p#ul4=>-_&uWNh2jK!` zQZZ6$O8z#Ms{Uv)oHq{HQRqRJ2$uk1c^fa8=#)>N7N!C}1Trds=h-(rOP;olA7%Ux z&ss;8ZwFutu`MfHUZTpz#z5po<`S)Te{)*>75`+qn;@Uo=xFn`0NK<|qb$4UK%J@{ z+J{{`Zz&9lOp{a{L{@m~Uk#8WY+jdPdeAW-6ddC;PaYMFBw+Me4~9BEhoQ;5O#8W93%kmiqYV$dYYCE z2JBtP+ia{^d^IXUxrQf~#p1<$#U$3>ye(-<)~`u9cls<8rG3M^j1@K}g}MHn^X)9h zl@MtXGux?~yq~<^h4vJ{9KUATzl?85SaLmFR|~QcrIG6QkqpKkt*+63o86ny{m4zV zEhwvDEye16L=_CY9zDx^bP&X`s+{uSy{v_8oGbdHb1mJXh@|auz`oiT#rlVBd5Tz@ zT(3>s?mOo20qgI4kBw*qv*CX~hqG_8NCu6`mpEXon9Uyj45o`DmT}y*&`f6W)5x7; z3$*F$Ol!p^0!uO7Dwcmh#m2Wx8QuqFMMlKkdH;dbSP^6Eks8r>y+?X}*2O*3W2jf|@Qe(6?5C)WDH%w~YCI5w4PQm?VKX7!i026I=5t6(QSP79t1aLC)= z-dkhiknJAg-2+9Fsg6g9c_&5Lic=1APo}SF@fiK2wuoJACYJ&Lrb(N!#t;<*LT-4*IF~drORY z$xjPA7R=7-S?~UkvbOzUoKUVmBIS>}_U1M1CcF}nh1*$-??_sV%r7z+N%w7++f3SW z%|UxDR_Ki{DlS4EaQ}yk?0*X%62AL)i_o8LxbvTmpwErqAsz7TJBR;Wn~;g`zdJEx zB$3ZG7)VrZRn~s3T}yytYhC-|&+c*jMWWt1T+yUkt5GoIE(cE{zx4i;{&zT9Hv zXBm=zGwc@OEj@^e8(EF28UcoP(P*yl4X+ELkj|E6{Hpz#{YHd+d12g$mYbF2^-d5E zbihQwI)8v3Sva()6GxuU2ADv}m8Y5xnqRJ&DH^Q2T-r_2#EvMrCt}DuYDfd&l1goB zT;>8Fq08$@syZyW_*4)!Uvb)48VPc{d5=*1WCzL!t7BWo`sah=O=uK_ zN~$_jUzOLT9BzTR0U z|2?q!TgJ%-tsabUW7_PthWOBy-Rsa{sFg`q9%vqz25xbB=g-#fCVrbm>UQzq7^c5F z^zbPSS@CffU3T6|(&bk~)hRMHmiK+25$@KFt z@o0w$&VDq5_F!_T;#Y_Yk2AsX`Ti^4-bC3h7J3mcarA!8s?(+uI`3D+{*rG#psgt( zS*j9$`b(Rh@LF4i(|`g{74p}AL40!Sx5fVPcU-Jqdbg&A#*1hbsZX(%r_J}9>yy<8 zlNJRqD6H&mrdm??Xw9R%J2}g$>gwd^o}8o#@I?I%ZIYC9pFiPfgaZ}V>Te>Gij0Vl z%#s_&Oqp}$X5r*Kft1K}LN`9Bj3#5Z``H*KZrx~)=*-cWit{BGT$E`Anw+Nj;*)|x zk^PuFb?%43Z%(ArDe0?k`E^|F5n0}zGcS%LTAzMMJq$0Rbft*90W+H--oOy<^98io1PLnsP=WH?Q;7V2a`8hYD*|!K}@d z^n-`|)8VVPnQmE}T139&e%&^U8YOw;B8Ot4NDG++E?gTdTBdfcBnpJ`UBfZ+u8##O zUDBl~4%3=w{W(tY%Afo^o1l*84sza3Cf#K2+K?*zctSqS^xPZn-_xfX&4Sq=MD^2- zWcdj;M}5?W@S zvYLiS^X@Kn1D=E>grT1nFpn#Sg(nUzW_ey--<5mu^FM^||7VYGoul)unX-VD%^UNv zOEN~F4M@hzoptc4V?dSc;jBqexQ!s|kCOLKxEc1&e`zbNVB`+=5*#HoFPnAAXUZO~ z=;q~iZQCRn6x9r}R{$&EAw~m?y+uwQ)!p&X?MEGt!>H^8hkV4ImBhX12~3?$srkjH z4uQr@q`Hz_DLr8N5C6yiDAE!%~l9js`a3hXF;RcSrzI!_i0X0Lzip7qpaah>XEp z`+WSDzKE(HdSUeRiyJa_J({$Zbz<>?h%mivg32cmF?QfMy+QI$l!kfdF=hnC&%IbS zr50-j?$$Pf?NdwSw*$%vE<|S!xFT9@%X~x$gyhg!@lzpMyp3>pETrZiC5WrHp5u zV`_^bNIXZbVt98%bKy)l?m50REz(`Wv5n(lEUX9{l9h-p$;woI81DDY#3B)FPwJ@o z&UfTTTxY z8!A_~L8yp|{<>t5Nk84;;5gf_)d78+xyr7_ff|DCve>fTklZhuSmyVzMd@^qwdrMy=P<8M!iwd zW%%cmy|@lb;At6sRnJV!NO8BbPssJKv7g9UFtD%654h|)^Yr@4RVsUobIZg{TQ0|*r=YSX@`Jxi2Z~mfC)h4CCGe2t#%2!Jcg3iPSG*+uiZ{O3 zO?nvq{<1dAJo2H&;FwN`R{BTwd|n!DjS3$ns79T}qHLZ9145lnnP>Z%#f%)#7azL+ z2b3g{q3%p8k*3sNpU+_B^a;vRzut8%qZt_muMk0+Ea}iSgZXnd;Q`P>8&irv0qSUFb=l&~&Helf8f zorVOB3|gxw4^u?EO7_C94d$MPVV4t$y*r;+WSoHdTk>>cmxrvMZt&%+FcAZ~HQf99 z!QIdGSh;uHcDht3uWe%i7pEZ>r4r0+f(AH|AZ@6EHX_2V$k`S(O}S|Bwl|i-&!Czd z`;vM+O=PrnJ7VT(==&e_j-xLI&&t)0zTAllD-i1DFkzrU_SFn)9>I{F47V1NG&w1H zxY#E)#Pgz(5m>M*!94NLVkbh4Gx~f;SP9qc7T^5mWsANTNfiTr=9! zCj1e^cU&7hg%T{`EgxRLo8C9ecS1QPld^+iM#rlaqjRCdwsOeaqPELXzNH86)+NO#qLF9;O4=FJpGhIFqSR7jlgZ7P8()JC`y&~?R{1$ z@$xDHWigg|WNUiBLs{Q3QMw=@$TuL1SYT%^a;FX?RCIi8mns+#g4l(hDNpM6c^er+ z=f#8VSfzN|$dz?Aw!8d2G{3!4331SB`uJ%=z!^3W(p@R@n4XNa8rFK6nYO^Wu)>NpP3bbZWX6^s%@M)GiPft9WO^IL|M zDs6Teb6n===|g_{A~CPp@gCy@$5d^FlBfve3kwf{FjKG;^9fwZ z@eE%(TEs^g+NgT{;?)4nQoJbbro5N7_EVgF-=?O$nML2F!U-k+tK@S2deG!@V%vC^MxkKkk$HU)G-%1oG8M%*%PyqVWp~sJi7@=FG73 z3>(aKUJ~B-1w=Jk(6b>?`MEQaSzy-Lh`YO8Ml@L_r&%-Ev%>VeAbq=nBe)R`5AtXTp26Ytb*!<~vEuvBhVGc|l(^?g zBVc>M5lKX3HrH<_MlysMX=*bDQF4mp-tSP=*4M-?Cf|hei@j#@SKUtA6bL6%F9tk> zwfadpAV!%N`NPp(teQqM-&!JHaT6h=V?a=Od)83kWFfz0q(9px&)+R&xP$O_*5>J; zx@xnH?JOh21}Z^#KZjzRF=tvX4zrtp^H8Asl!g9fZ(iM@ujVMGPO_|~ZMpi`nFIhoq>Bx8}p zBc#eUe2@AYUVQK=iqq$;>cKyyD8dZ6J?T+mAKc7P3b_ib_TJcs@_w92gD2G}( za_hh;D5@5#6wL3WlidOBZLosdU;F@qn1orv$RN}6`gU^^s#>&ri@uup-dG2tFpl60 z0Q(=~w7-6&Pt~i&8<%&P5sYt^&0e^ca*lBlwobw%1O-LTm4nZ{f=T(bN119Fw8H>X zw0s-={Dj`DI&22o$(lui=s*KflsUZh^S08e9j#a7J89HT7&AI9NdUbCB~oEKpp_9W z&L;LFs%q@v-km|#C$p10#qHePtp1VcvGpq;EXpNU-!a=gUnH;P z;95&6lamQEhibVuMoRHIj;1(zwmX-TaQ(1M*@D=}CT4X1%6qzKRhT8Kk~*Qr38N)< z$GBsOui7Sa#8Ee4%lG23Q|T}JcN5vZ20gA|;^-gE?^B$c3Hcn~>b0!6gPRgUw$_;*+ zZlm5@UU^nayj=b2F0I%j?_P$SAWe>dt5kZ=eazCy;WU{ZU9$^viHV zS=NY`D{G?Wo_fn@xR`>k3Fhd_fWeeXMbdWfgGmPM+{%9fd-z1#N-WJ3J^^tOKws%o zNl<{|MV&tyFZChG0FtZ8KFISq_6t72(S-3Q!*;fbiIMD5#W5vU7&!7FK2hkYZR{u0 z@e{T>WLB@m082le{$%y%58Urkk%cu1#pNdL!sEY(Bm2Zp*aHdj%6M2RX(|rCRFq&< zeu_^1a6G|m^#TJmn_AIheRqRf#m#q_-}Hy|Ew_pE#|CASoy^P5C%rG4&2%MzONxKxL2D7ViDws=_U|)G12^1thSf!HBqWU_o(RH7|+bmH` z+*BV@hgGo!1SHr{`G%rhzP78ixbGajAE*6_Et@S_B@Li*O4cvEeGJsKja7poaVo$D zRieG@?bW%KO_QEV%y#~L=mE7vT5zN{PHWmdVS;_%P+OPE5-+H%toSi zq3rLv8n8g?{4QbGj9@o-ftx0^ua-CdhgwZzOq9#rlTJz6EX4biR~2uCY50UMak-vD z!3Sc@W(ET1fpzL%IfHP8;jp2ug8qGIo>HixGoQG*kKPb4k;1frV(oEK?bJIA24dA< zd+eRqFUIfG%Urqp{93W3Mp~%{kE_>VG>UwCy|YN|M>bVT7%gg{bFEYx<_dSzr#)wt{oZs1hL`O1vlt1D z1G#u4p3zHDQ89OTuJN8TBOf2%5&dXo`U+B>t$(gx=!MnB*Y)s_HSa zNa-dCFz+>!G1d~AS?tmA*E7uXq=3BI3EcZrrEK$kJ879w@vqyVkR=8D7NyajS zk(%eL?2)R8MpTIN3zh-qpSfobo?jM^e`Uz+6FMh&bx5?vyr|ORwBd5Y)1ph(9#)ox zswJ2|i;=+OOzS9JZ0^tKg`2@_;C$28D>#UgY8=pBmPquUb8KR3m;?ta&Hf#ge;>X| zVJ{=U;``7K)IPA#tD_7NQCer(8k4Pb)8@#@FmwrKgeZ&VQrEp zD>X%!Zko?A;Pl(#Ak}1x})v$ z)>T;BW~`|^Vl!FL+r_MWVL;d&#m)TM+S-(g;4D=cyzQW6?56Td{Jg*OtzF9esC&vZEOG2DwitM$t*UqE!lD9AXkVSvLM>jDoUZ{Z?E3bjK=3JF zaxBp}--X3kU>1;t8_N6lZIo0(Obn*2GitX;>jE*Fzo*xJMN{>#-OGFM4R|57{tGbPR?$#PeSk)#+tF zgM%x1`uOI*5JFpAk}0B;Q}*XSE$rBF9b5BmX&@yrCMsXi+XhSua=<;w5S~WDsqQb~ z%y82iGWRRlkX^lUV^(&9JDbQ`L)P6RZf;&tmYfWQ;QP3#OrzHoy(kbk_3h194FX~$ zZ^Fci+ce-1DIPPtG2?kidfda_QX2DYe9X26D7zGdhYz;DipzDF9$PbJOW*;aO#aQ; zuBQ5}b`%>>c8yu=z9iPb|83I{&+T<;LyQD@>wt9D>^G7!*4%Vd)SLMweIt6=Pi+PJ;k9kPEjxgRP%#sp~r7wGpk zvGU>SwYsBr&-BE1x&A4-4topWV`3wbgfF@wnw~MAHkj9HRlDru<2(eXezAT*=KG+H zLDb(8PlE&KmQ_7w6pDyQ*<5DU1-51Hc&Wr24|j+hkzq4lT8vp*LBakwrzpw>5>DT^ zZf0h+7`g=cqHPn$Yk|UM?vhO8qKVezkUE8ZmUYpN#amUKdWgC*sze`%=IAioegR80 z_nob1=Kq8BQQAKt&uQ6qMloF|%mie=TkPnmU#80wJ9pDe6mJ>!-1d(>mu@ka(O!&1iOF~dt zOQTRmS#H^ph%jw@IVOhl z6f}SEgtoR*6kpJ;Pqp0frs{%TJV@j3@j&qZ71ra$XiE9GAAGnw<{W<R=j-jo=q`#e z;8d?d7s-g*6F@=Mg5N~_k)>#7G8jFOR0=0djFRnyWD?wHhaYW#b>KMcE+e4 zmQ>JT;Cn35zu_zXem8kgr03H)9%Q(w@tBwE6jN#c{JRMU7Td^Cs)5;zL~n<5HNJYt zkJcziFwJWu)QbKCx+qkoed#wV?sowJTJRr93(W8`b(KOX&Z4suiolb)>wuPC$LJZS z58wa*_$qEZ-}V+`=3MFFgF@sdd?Ko39DWm|8<~2CY8WVOJ#O=16MkwNvun)&Gzar^ zx=WX(KiR6nJ7^hjU*MUvmE+pmbyt5gj)+NCV`B9JlYd)9j#ozNEQ1x4!OSkqlO!|n z5u@D({YxIv`c^f-Hru{x67ck@>V{4B-RZq^`P3zNlHQvJ>okO1r zNvQ$txdg$!qRA9Z)^*Ien{Vzh{>K3x>RrM<^-n;x z-l4pdp8~mNY{wMjGWhAa-$(SaV>zr5*6il`B0YT*xn>@Q#)?bDOQB2La$UULf=8s$ z6(Kw-(%?syXp6B7#@&<9&W?}BT&j+-prKgp9)5wWa6h?wTEV2iOA3huuf_fIlDgkF zEV>C@iY&fYuUiVGp5ZmzaRLchcz9VfMxo;TgqavxQ z6T=qM?6GUM)mpOQ6n%lXQ}H|S5f}Ab?bD@-7DAzZa285&e*5Xe(mCLwd;aVEUh@&@ zGRWo9J*2na$@1vwvw)g~?S6}lVb7>{s=m+ufK*;KmwqNTGLA8u6{M`EC@Ha4Z7bsL zagt?f{_F=+5SXp+tgLlodiyctb3)V-;xK5!kV($?t85~$!KA5wf=7HT`Uix^{RiZ) zf98L-*NT{f1-#+6GPtE^m_w<_mzGVge(cle71kKLB>b?k!ckBQ^oSvp>F9ac zH9p$1ZC{slES-^Ome!jm#SkGL=PvKP#50l24JbB-L>np?edaKTiAkh0qi1lu!!x`Z z=dOny0UWS>l$lCxn8|zRBt166?u&K{=^m+`@oHuh`;H#b>;^~4HK!&Io1u*1uJTov z<(AbY34|(bf>&;`@nsx2mD9(>-`8I#UAU`**=IazB0+>~7WorQ_Lv003)japqdN=;en!_)73iIL;A zVX$R81?3&nqc6ESuwj?PbDy@`RrL`+u+u4S#n7iHT;7ZX5rOTSL1iDV4lBF5%$r@6 zgj7q>XPnEkAA&BiCS5WkUWGvuqU{F>+M*SAYseJ0YR1-3#MHSMz%jD9mFO7cs4 zhpDvrMcNAVvmkE(xxB3K>aI64+$%b`w;O#Ofm(qc0UK_BiPq}q$5#oC-WdZgWFpyy zoRUP;P>(}UK!*4!a!t_6Y5jg;ls)`e_Vi&xfY2tM)j8{o+^YeWo;7%ax&envK$k3! zl2ss6g^>Yq<>dpOg{xj`ZmEifWH28)RC~*gg0+@{?PT`86p^Z=UUt{l{kjB){#4ep zAUu4HJyH#x5=1U*`3EXrRrj%J;jIkv;KwnVaZ6+qr<{G0Ki*_v&UOoW^`~W`0c|-m zjtXn%tivqH496BQaa_~t9o7Hv^8QD=-(M?#2&-|T7n)-YII1`;h5K97k24$Sy(JzXJg+I1oN#6bgicL}0G31=CC{b?_yJfrM@!;07h{*PKRrk}Z zZw5tEhBOd;q~)L~-pY0u>VjU=%+>Md_jmmdVNw?(rwNOOVHc`G2N5+vDd*t=>v8+M zKX0opQQEQ}GvLf?`71{=yI3Fb!I+6qy4c+ly!r&ED8c2h>2(xeb}O5;An_+0oj%g5 zPp3;Wp3nAuzfGSY?%KD?5e7neE%p*!6uCdU}YW{cXP zAe3;(cV@QYQCJ@qk~6BO;-5bJ>N0#e`%PlaRR&M1r>IPMIRHIp@+J(8>od zspS&RfpZ`!=PomrlDTe=f|iw)afxWm*I$`+u?{0q<*s-q6uWbxgcd6Z+XQvtpu_gg zrFd!f*kSS5(@z1f@1d8dPo6Dti^QMtjqXSGEh*22RUF1z6j9i3)6P1(c221+Z>L72 zI@vN+WT(gr$;nl^Z_M|#TUy;;%9HWMMxcz}f8v*9?sB9?NbKa6Ur=31NZ{kHcwW;C z@J8_u;;w!~;1u5E*OXS%WF!?H1YF_Fp|V+7yg4 z>y<48tX7oyl&@QP-p7$FGF%Z4K-u$Sxd7{!b{eL}OZU%I>13l4(Q#YMFG3N$4~?p~ zGU@BP4+@3jUP5bXC5DIlqcS#;S+3_~jf>Sru)cb%uj|KO;s*tSbkGQZZ3Z^WQ0|eW zGnqdpFd`?8CJCn;fzE8WdB%=Z(6xD~yeKRlk!aseEL{-37pz-RIzO&7Mvx||es$F5 zIaMq$Ggy$#;cCdvljvXOl9C+0>J3e?;7Lhx1;~Q*=eo$YEXB(ov8E(MlgF?VNeHm6AEK zi9F14mchZqJz2qNdQxZ-3$3_6AaQlF(UJ;VQL3<#y@#4vKQ2To&g(Q+cub{knTd8B zgs&~ASUk4lK#DIXQdtfkUR*8K`uFAeuVklKs^&j*JVFs?r=ftIG$fgEy97UXmqkdJXwqcFS(udX`_06Y1O7WJQ`Mu++_P29|qE4WQ!emn9@zXaTRPCxSr%8O(ucw$;sA?8kEmwYgmpbk7 zkuwF{tXeL%Sf$P0m8>^+PTY3>sGMK22xo%8N^ZHbxOY%C}1_RRWVMt@z*l(4y^FBU+$=V7JmW z|Hw=dh@G!-zr1knI2LKs+jCJ+-S@KDkICE^@&`TGbRB~oPE|c`Qfx(<3>jeUh;S^z zDmloLt>LSTT+rj0xR>=-VWA}!!aB&UBljs~U)sXGB-}*UAaP5Qwz;ZD{=5$c@a1Bj ze_HiMH!c-gDo~0c9*(`fIfL7bj|4mI7AaS^aDbae|IG>f4kBv>cby`)g}eljEu4Z1 z8*7E-@z`8pOg0#e;Xdf)CJ2)Q+0e(jz%h3Mz6P)RUnY@86b zeqddUJF^*B-GJ+Md`CgXw(9~AAXc8IZkIl02GA5DqLFjGOs^jG`WuKmsCj?67& z(^Z*=wO{?>Mq<*Imx>z0pTK9JN^BnL3;c~T+#o7%NSEqzWigak{gE-GaSX-{D8MSB z_Gw?l1w#3wsvj4T%_Rs3XU<*yXx9hbG8a)k3IA+Dz@Jb}s+YAHsjw*IBT>0a+5mE$ zEn&eRysWQZs>R97&fLXWiCx^cc--6h#e&GFH?;gKgCy3WN;VKgMwME8I?zglEMzCr zHq{_XM@Q0WEOK^%@C`qjd%vQ4RDjs1QM3$M)<{am9i1Hg;v{@sGhjIImcWZ6O|!B@ zJ@uG!?-uyf8{5iRRH&bt9jK@+r+Su;bG0>pA5`&uJ4+|+E`~UO-pCJ~>OPMQaR9-` z+0h2_Iz=9L7uCG33{S{1E|?Z_dGV0a04g$ukKkf`E(g-n+jPF&I$Vuxceyf53piLf zUy3Ryo4J2bp`bG^c@uT%>JhK~Z_BQ+*YsVE+nZQf3HoX&g<^+YZEA)c>yI?cm8-GD z(&O19!rgG}26Yz*5R~+3=XVe-G*xTkgtJQ;0AW|ZJI5&k!k1{PzEpd1-+w@BR<=_8 za@3JZs(kK+q_i(q-2}0N$5f!Rk$iJjsMkR;H5_id#!0cbuTWj%PuS5w?B=8i?)~32 zOZAjuhwnln60KbN=h-PGQ^^7dL6XyatbbXb*Mlzuu?5{C@aG>1AUD__Jdz1uf2x#J zNdD_PbB>{t&rIW=K5BZg(`-r=tc09gyy-aZ@L^?k92R8MfW{sNyME6h95f z1>=)`kM}maLnu@(C$F2HWKj)3|A|+dZXa$I%+OlM)e5kRo401UuYE0J~ z+#%HgA^F@HUVWMpg=GZfqHVW;9~kiQ8<~iY>t*{I1pe39K=Oe$c9ZBYP*Q`;^iMan zalk-qn1(|`KYfMO7#w0pRFxP(HNPEdCFor}``#blMv7@6&Xl{N6$rN!Npzy{eBTC; zKGnTP>_sfkQx!`voe7{+Z%G&c&=M$q0HEWHx3=^LL#(UUGCN1uc+f zWK!^1**6>8SLlL3WKTX6*Gx1&^CTK;wqwOTO8l^P&9Kszfpog82#G@LovJO`)%<3rkU zPl)7NIB?xmL2mg9>4KRSjhF2%eKda`Ya&)4OrLKu{S7P=yadJ85c{$kqm`URRFwT~ z6B+x}d-Gg;U+mOecieMwkW*CY);t3e`IPjxJM~Ln#TCYbfAnBkIgG5@&Xi=$i?Ju? z;ZM5GqNxxya^jBL*_z4GD;r}~3Km0hM#&fVBtSIbsI8Z?*W$BI1~W22i-ySYcnyQg zS9lj9gO1#g&d7qX6at`zL-V=4!HD_TotTeoB}lUcig9x z1{63dfRn*7)gMqQgX_ce*qY7BJLUTJR7)9-ZEtPq&|?z0b&h{%U^ecK`m|t0bM@?4*&GqGM_(;-G2!+W7jK zz|(ZnP|S+z_jJ(^TOw54YFb0f{5VfVd-5s+|6V_S*>1PRWuW?ZFN90|&L5DC{k7>W zo3rY0tMra_>n{c^xsgQ50?Dg#HaKse#nOFRMmmysnuLkpw%udfV=YyXvv9h_O|0SQ z^DN4V$PFHmtS@*c=}LtLzI5&(T~^_z!4#b;R*Vwc{;nzT&c0E&aQyHIGLFsIiOdWQL93Brd5h+ z5{_DdO&6w^5}uIC;|5wZ78(lZ;(JJ}Hh(7^m2@&^PXATBDql)U`zr?yjxDu)bE6MH zNd}cl_$2-c;(cZmn&~mmQ+OS0ur>OVzd;LA>)Bh?^ta!pU=xkfAJ8ioi_A#_|6i9D ze?ZN;%?o~;43d)VZ+f=V!&xQ-O<{@#BIgy#7k6uyL?RBp&UFH^i@=y%iF~sIJ_KcI z5J`uxijaidHxg(=k{~k?751~Hcb9A>w&$7cGQ%#p9g zA)ry&*zwzb)qI;boGP@`p-yRd6C(8&F^7m4@yavvRY8Tbg3mD%u=#J!v-NG|@8<-_ zbJVPr;S?xOiD{a~cG4$=uu3z;$;wRb!xSB1?Ga?&#SzhECrO_Np&ACQGV}hIVh-9X zU^uN?iUu_4SVcg`2|s&c)KcgejK`+3$sp);ETg*?CO%RUl|gf~3>k+&iAN~y6*s1i zIkRr_r_#y!?T~C7kUwbqPO*oSGCQ)k*1Bc%K0G3OU#>es1~cm%fznL6TB@>X{r$?? zH4-jZP|7H9b~j^lzEw73PjhKWYkw2 z*%0e*^BGc#c=XmJQ+Qr~n0uZGw*QMPT{D98hxoBwCUHOhv2peYu&2w)ZTJTiqy*pH zH`qCOLPvPcLs)g?)4VG--}UXaw_{tCN1%7XgE=*%7yBmr6U?WKi^q0Fr$Vqd%k@ys z_tmt6#W@-2nxW-X!>3Tc+)3Qz#sQ_@1E12u;DXV-D_@1%C4ZS=+~X|^J`hd9DZ4p= z?ef3pA_kXP9(YT|3PFnf*o*BvD~x2&hA=6&pqW<9tlGIP1ax$+nV*(ogYJ4f!t)Pk z4#26rhkjzMT&3F|dS-;s0kNqB4e+cQV`8#c|C)}dW|CN2r%bg{pTOKf2nsdK&I-uV zz^J1mKl1drcut&?HZO|#Jz6zRtjEs#G|m7sf-j%`QfV9C%a|Hefaz_{Y&s;$^yV90 zJ(T@etxsz{p$nLM>KD0MIkr=Ecy24sI)VV#(^|Kams>NM^iFSCx)py-eWM|#^=p3S zw-|H%js=oNncWgcDbNsvuhA`u`73j{@cMg3w+L-ZRg}wlJq!44NK^2e$V0T^9?7mC zZLLORl_!t2@nskx;kmlggNDY&`Lox$1A>da-V<`^Z(dG8l9ua?Uq>{mn0@v7Fz1`o zVn}nyshA-=VXG*aO*h4I%`my@#mX?LpUyfuIo3(?v$OJ-X0w{tA5g_>PIC@U_IP=n zHsLs_lFvA%D+Z}gDONQQ7jj*VH|Bd^dIjm{EuiOme($c9S~af6`3B)7HqO@{`P+b{ zOG&inTyyf|;%l*HiqMU=_1MM@&-u>MVB1quZ$e&m^V)t6z9d#})X{K4{H59d;_WTN z+FZXk(NJo%g%&6hv`BCbQk-Ie1S?*gBEf0V7H784WqxE3!C!QH!0 z_WsSxnfdZRGv~wbmFt4{eV?_~v*cd)ecoPq%(pgf`e&)8FEXah%19bV^PxOB=&y^} zP+ME-wAr4jl(z+4S;E}oCy>AsQr}HoLzh|@*jQEglytj+;Y;g5`D`e^%B{~F{sLG{ zDyUr?t&(jqzv;R&_L19vV`Wvwy-Ylp-PA#7%8~*btDU=1XD0_N)S*;V+Lw+X{~aHh zy=u(AoqvOPC2kLN3%*4r;wRGhosroW^y#u~_T!p?Z80eNCz4h;=?aE1u4_E0MqZ^!TB0a>+bk$vI+S4**d=G%;b!<( zNIcgAL$E@}hBf=jw`bbc7uY$t+!WXjM3%jN^NfH zlVS&%uV+(p0ynb#16=b+NxGo#G$B{vYHs>r%H@9pRCeC?{km*kEA0YVG`(YXt|MD> zysJEpmy;aYl@2P?pTOX3zmxp@QVFUWjm3<_rufOMyrG|0|D0Uh|B{J>R9HiN?3a@F zwt?E}(MViM^l*$uN=!r8qSKP-h^s-2nN{QZBK3;kDl(*L#J{SS=9|Cg3|#)H}@ zvbsLcW%=F>FXglPOdhI&@B@{RuO&DyNk_w`y?*T9fJu)3nI_cSeW!3vHesR4^0{F& z`vCMMlQfinBXMzE#;yF>OK%aOiAg<*2zxu>Tu4-k%;@ef_qo$Qw>^KxTDN&1OaEqN z#s0yom`XYnsQ><~o1*)ScB=wynbN8w&o)b_yLCIUN;s4i)T%IoJimEBa>tX1A9?As zA(a`bXGH-igXohib3Bc&W zVTsJ7q~u(3G^%D_tC>r%oW7u*KPD=>p&f?`{ctf zhD@X{wOJE&f&=N3AFlBCmbeus?l?0TP2!>yKWn9EwYvI$hRDna#}&MMI6$v7u5@r7 z6#JgxH8NE1ImbzYJ24+^@JUFRD$C`jmuLXXJ}<32k6jUKCjF>JEsXW1R-t7j;N^;6 z>mBzOE*ML4;3IbJd`$=K$6Jng`lv-}D_}H9M4329kn@xFs-maA290VZWe|k=ZvgA; z>-DFL`0a7OwUh}``efX!{qg=c1&9x#-(G|HQ@t6v~kd5xqu`y+-s%>N#UY$LOwL%b+}-}n&^4Nby#{8x$1 zi|CiF9+DTzGZEdjEE}l#PQ=aP{ZN`FZl9Ub9K7;`-b9FnFY_}fl=7!kuh{yP@AVH? zDzg{6WvJFZ;phAHIW$Dwv>;B_KteF-8F_L;_?&8m3+Blfe%E?D9xtSMy<QW7p_UjL2>bXgk6)*qmk;%jN+3iB2BS2};;?D4IzytU0rrc2WJ1#aDvMN-euEK*Do$7J*-L*ctu=xLX|Mu2d@-_iJ8X|CN1j zAuDfuelF3}4@9W6X^*~u_p{^szpOV>L-x^uI&iT{@If6p`c?M#zM7{D(bg`s`6KH& z*aT@0*U=HxJh6*jheNSs$sS$!<_5@+7g|ct9*^ zS36gfk@X9V!1Wh3wG->b#f6GK)Bc~#57r_r#hdO;4#7J`wc;jM5V1Mmush5IGe_x~ zR5VM}7xO2hao(KKQPmiaD5XQKM?N41@2F_K)li)nL6N$*1;a-<5{@9o>B{+!zRPnT zM1Jz_xUfjt8e@mN*H#!F_mwLDC4W2!}eD;>k zt~Ax=fq8%NuJE>Lh|Jr5yn3xviWjp|5khqv9BfK&P9{xCRP|y-2AuQLYK@F*J?&-K zeHC`ig2rHb?3^kk$lZ|bQNWbSG8tqHcKm#%rUsa?Kp3+!sMpw*)fe9GtQm6UqaJ1s zCE~9L!5ycSl?Yzy2{>BliLjVzC}_&J{zWp?zDNAY_Ee)Q!<73dM{)ODY5-(>@uaWB zJi@tw;6`3V>O@l>{mD}!L!+npm4T5l_K`1q$D-G>fzyy@JON1aeP8*QZ23lER$N4g zzI!Vz>1&`&9%2e}zOTSVMg4k(E?XvB#J@&Ai+N3CbVK7Bi287NLPr0R<}jh0z9F&F zKsb}>kvZBWLkkHgG0ZctNi>zUvO9{e(|2IIs*Qg)r{LI47xwP2A>HsX_GE2!uIMei zfQ9e*<~#B5@@HZ9qg|*W!K#j>lkpqcv4Mma#Gwy$EiRcE3VMxPiw%e%{Rxtz(*cEn zvBWO!{U4I`Xhong3>X$ikrbxeJ7%{kJqQR(_3F-j?7i=9Jd*>i_(VM=7IpP_u|8&1 ztb!m_)nZM(8oC4G@{$Z*hMI*~3k2Oo_L?+!r%RihOwJ%q$VG(fH?mn|t9=eP1kK)3 zR4ujHgn>lhb##G^wKkbR00~~sca6IVGU-$w97YVoiFAEDoAzWFs@Q_NPqZfpeVZEB z*H5eV;N2`>qqZK|1@n<(yy> zr>M5w?Pec@69D#jT{Vo_t#bR}>vfF17U&#X*zxW+T!Hb<8ny(Ir)MwF8PDF|nw)$x z`ib9_6fp--CG~E^F~Cyo1ehRBDWVBPSz9*7=P7s(N9=!gzwZW|GYXGAbYtn`rpO+F=dT=^-j=rmLBiKzbdCfcz#b zUFkoXyqEolfK%MzCu8e548y@M%=c&;R)&E>O5nWr2rsWU&on|y~IWuG|KDQn60(> zHt7Fadhy@>(dNb90IEQNzPDpauEgJ&j6nRu8kf;5T}dJnro{7VTcTvoqVtVBu6!a- z{|3CKh`&3v{5afdi7UqWb(WG^6>D{0j01Grzk}od?7{!Hv7iv@rzcv0e)y7{%-aXi zPVgt3e;+?_(UK3hGxs^PKAS3=TrVmfGT)zz*_Hf*>2P7yaP#C}cl2h|Ycs;Gx|DQy zQP*Qj?c9kLvtI-5;$HpxocOAexceENWEjX=cNSE?Koj`tgY2KNKM-;LdyD&Q5VL)b z@BYh>-z7d8vh7t|_^l|#UVBgHoD3)$tz3G3txO*VDf=A>Q|~P45Rd(psh%h4$WA(r zCrW`3c0XGY6OZAyL8Bd1krr4jIvu`2Cxpkz8xf^}otcJT%-oh_`snq-Ht=HoiFi2) z9rBKgLO_Ip4$bJ&m}fPWHR<-s9;4ocs5w7xH4?eHC!fh;T%hY+s9l3oDhup-l- zNKwmkQLbic%~73f_HUaWdm~?bFmT@{hxsdMJyfK^whZ&D@Uq(O-0&!K_*biSB3k_= zvr%;}_pT77JBzC4ji6zWEVJy z$WtKl+0{zAbhphxLT)7PY@yO39V!#>T{AOkky_XU+Ns}*U5uWYHwxp7-jcAzNc%i7 zBkkiV|2Vo&6$;|4F)}mK-a?UCXYbDaaFuy3fRie`K5G6HrudT`i~CdV+V%RkD<<9c zYmC5>Vt5$W)`(LWYrrRqgTDa;eumy`t-Lju+=6F(&P^^+5DOcqywv|(fsS7 zdoW3|Xq_U@oa$B~JE1)v{*NR>$fS1H$RbgO1%WY?buBvlEjL~?XWoeVrZa5C&$he5 zg0HY)(*1SL^ZCu;fbYYDP4z2HQ!<718Man5i-j0AsW{eC{}ukOvQ}2Bc^Q1)|HnN% z7K&b(`e&4F#z@V|MQsKtPbbJh|0Lau?^3p@`#=CB3^_1yf2;^@N{92B>YmtIx73h%;h^|Up^WU!& zDe#x0uQp6<4R@<>FlgI;HhU5=!i3SU7I+ba7Rz>JlIQZlb zVfsO+GFuiXsxxAQCQKT%y1RPH(ClTl)PK0!-v2Qk6P~b~FT!qU&|9FX4fo3vFL zE{o+kQf!5bE%Ylh;#shv+m`LF8#i3|rsI>1+q<&Ms76w^2-3pT$lxCPdp9GA&{BwL zKX#qH=_PG~`41N>ZEJb;;z(ZBPqA^l={1WM9QD_4Cn~Pr31{O)tK#GMU6DH>rfViC z#)cxtKGIndja0*BIr}@ZALGPiqiC_LMKkLPT3eR84hAWTRocGWIk)pc8qaxOre3`F z>gIr|Cj;yB$D)05dLkg4-%=a$6H+lwl})l*9N7$EYKd|UdtmT&Fvlp=C6oPEWKWPE zp!$@7u~IxK&G+Ry%48Cy<0uA8UvA^6f)Y`lJmJeHqW&t*ovbm-iWY)Fs&n_c#^*k* z6}gm9Jju#si{gkVwmnN~-$=Vt3~2a^EXB3o`7Fvos~|?Xwc>};H&L+@ww-q`+Wq~B zWpJ-^{T}wex!DLhG~xjd&d|?%jRVGr5T}O8Wbe+7-!li0<3Y&>d(vr^4pntEx`ubR zvcI8~X7>f20Z4|>hacaBIPzs-puLeJRH`A?zBdnIC{|*RnwA^Wdyiu%<*Vx+o_?c? zef(fRN+fzo%%QZ%Ie`l*5$_Gh$aEhGn&XFMdosUGjG5cFoo!7^lflN@#@5TK$`|3= zaX%c&nJPZh2UrO%=-BC>V^~fJiV4^b^dA_cFZO+L7hVRBK`>ez5w_<^bMA}OqlecN z#krNb?I^e^ixxx8k-)Rzr*BH*Fow>`Ii=QdvdIxp?)G)INw)983p}fAjMZdP9k(vg zr9L;W^eh-%a$<3#ragFYvI%jghxe%oo-Pj-QcDSiL9LDXn|{c@Vl{i;R{Y+ivav5L zlusg=ofw`av$3}$?!;9X(Vy2?YuutkM$gLYJBj#V_rowi^LLXKW!nyKahdK-(iV#< zd|5NFLq7;W$sc;5L)%}0n4-k*GjL86vQ6`XvUvT}6ikpxR5Sz5TrZ?Iy27_IN#6M@ z5+)POA55|k3iqcJ)x^76ao*2<9~m*WE;;D2Eb-(iZNytmyTW%8=ja@oo)dG1t~(D2 zu23_G7B*fsk)^)@&#OA#8mTlHyD>y0#6v9)hHw~=scCbQZ6o9<2u%Er@AD34nEoKr{H zTV{DSiIsC_)_sLNFaHY|)J9+rE(3IOxe}cr%PChwSS|~dlhQZJHMI<$8wtH&3}R1z zvdj}G*~R*1&WMX;w|Nak^v|d52<-ou_C!c1Ag@TPFESXUxRlIrW^O@3{XnbBgVfD$ z5|j1w*itxAf^vzWQAJIvx2=8w7%c0m=TfMh>iLju0KXBt|2xp)(GGxTh~~Wpf85)I z$w?}hrCM-uDaI94zI>+&Fb~&r(q26i88JD26Mb0wW#5;X{@wj0iiQQurW zk#!c|+A#qgAmws9g5%&3ZtHn1EUDqKa7mQ4&s0x`KpRo_tXz5+j9KXVhj&no`h{P| zL^wtALivnz#Eis$Hzp-R|GTq$FJi0{fTXv-rGBX05Otm;->6c#l;{y_jVpcvk-iHQ zqS5gD>2M$wF8s(lpEnW6P7KMCW}LHN5ui2EZ!UI~~kG5k+YT+o}v`kRlxq2|9u@yuXK5?$ADW>C2kX zUew9?ELRd!H)nYVKwwu11{fR5kGZY9%AMyn!JgD|O%bN#yV*Ax~H#=^E- zq5SefOk(e4$%i+_$=Bzmi)c$^)N@%eyy&`?^*h7_i^uwm=D~2TqC&J=HaXNh$$@3h z=8Tw;K^xL@Ow(65UElNn)sy{S4#}EwR6$+J!%Ld(< zi|Wv>EZ*Gi{UFj0%-721LsD8wL8CvC)!~KFEnAsT5#%N!;+G1u5BS$LdC)Y8>gb-4+vTm#LEfmu$Q%8Z5zbq^Q*~2g zQ4r9tG?Gi|`EK2U={H%7lm*2b;(m_!v1nsWk;z;d#7Uql;+ipJK5CWvU3q5yf~teT zkH`~3vpd5ZY4^g1-=3i>%EnKUN-hyjbI?-;>@LMez`dX)4Z7|sKgC_%-2_VI6uV6j z(u+SC(T;XadK2v|k%f`#4Iga8cbXP|6GjvKa)pRI~obgD7Qk9xD@D z)oZ-)N)YW!c#+2XpC~VY#{?MeN&i;EM|rN@eAB{YaLT_?KIbgZ?ok_|4NA@d^T&^4 z`#CUM2E?4fQ%1Tl=IPt@I|2lP#~VQH!)wo?f8u;xOLIYt z(Iqt^vsP2pCYJ$Klgk!(M+h$-IzD)C8CDrCX&up-7Tj^%%U~H$r*Vqo!uGOCEk8Vi z;@bch1fmE06eAm_qTsTU3F4kT)H9SJWe;{&uC7h_6rDI)1%T%`%3Ayi>T%+U2 zvD~HOU|0`h-cvdY`u#&AZNH;hj8c-sUnDEH>9}hK<;XH(*K+?w2YMXeh9kJRGiLRN z@lcfx21-4TPz<&5?!yP&zR6P@H>lb}u_}Q+*OMv#d2mJt;)f*wUH>%N{_>7#s)5cR zjTIA@9177GIkYQyIAr3j74&ARQdMf5Spl94#ODg<)DOSicjnPmuM4G^@DM#NlutNd zk$%jZ^qz!MJ@m~?=XYa_Rrm4h#iY3Dvt8Vs`zv%g6+46XMw5IQPaaZ*qILnn!C)H$&X+B5$OH#$zUW?vnOV8Gg#8V0a5!OVe{EZrI~@4NLbTiq3B5G-qqT)SU4P z4V|AlT}M8pO#FC*UefPiOZ4f@S(W(2GVOR8G44qnRl>8~-V~`Htze$8qR6HnI;ozh zm3|Gp`Qg4m`yRh2xq?luquA|5^^L0-HLGqW#fVwOSgqfLijohJYrU1oC#IR^WzFV8 ziXI4oKI>_;moG-n_aEu>=aS^A;CpKmTl;h`iLq9Zm!AgNUT-@$NZQ+|m7wE9IQnaC zHVJJ%xOaP)#FoIZ6mJU##MB!ErhY}NWD*}G(BGwNs6F%*R{tXCZ~m%UZKo%U`R$;X z50-bWmlDh>?-HVu0vldzrE5}|RkJ*1DRpq;e8|$MSb%k$P46h?BHC8>c(e)vv zX>u2P5`D9lrr@^*8hn>mMgu|Ay@#&02J#ZvEtL~ z%nJKeVK7{fXPP$sZX9-TMy%ugP6E?@SINXpA6+lKu7bY!)ucZZ>wuI+tVW`(|=b^kvcahY5Nl`=lvYvgg5|zE!Hs^jhER2Xadr zL|wau`P1r0yCtZ;$YRaP9PC)@jI5N#gyk^u-mkoIr!Q)CQ)HZ^Rb}(anDeL)k1P{j zo(NHC#`c%@4v$98ze;W%CjFQ#=!4XeL&r6Ec6w|;ct8micYtHmZXg8})zZ`*? z0S=GWGILVrZ&m~B(auJzJ*SbpIi$}w_druqXBn-QIkU{%UfNnF%V`KzuswbWAb$={ z`0T&v$NXj*AH{9J9czKsNc0 zRh{GHBYs=gkVZdrq+Kj`p8jd43n1Y7_V05AAUDshEN3jeGIvajej~x_P62nF~+id1=^kDay;)@+A zNKqxAWX3|;KD^F|=bTozzWDB}8U%(U;`-xx>x4We;}?0~8O;5Q$5QXH7np_ht1Cme zdDD+q4~>Q~M$dCfVyv^Ifz&;2ZI01Q-Jl*F#8r__k&tH3ne={P{_w9d;u25g_-LGb zvxR^|*w2Gk*5U{pbk;>E(Mz$&uGhtk$6>#5bP&je9U;?;dsC6df z43Crj;dJEWFbj-FOue5AKN=g4FKJeBI{YKud-UjJprF`C&4wY&p6`eF6c3xkGUZOg zV^-SH$M)a;kU0UM9o(!jm z#+QfG6x7Y7c}ka*!g@vC{F%;)MFB6^W?ht)x4&N)OzNK5Rau|{&pgSUQzG#Dag?Et z2j;R_VoPH~P$~tHzL8(pRr!;zJL1v~6vpRl?@_#t_Qx%N#FigJpx~2d5Y13CtA{op z-qVFAYO09%{&4>RAe1P}YMXFWcY3+Tc@M9-Ct~Mp*l`p>$4*^v1YWxevvMInElX*6t|1hp4``4q?50s-kSxRGW zsmM|!o+G8@@ONkABrV&oWKa%O)@vNf{4eTSGnP#z!$VJ{Yb0uIyZ0^T<9FaGsZ%w# zsPY%{mG{#L?q)l1`m1n5F98~H@M_;wb&vP1k9UNK;~`^-dIEiwqBno_=TjJ+F!HwJ z<(@?YIUZiNRx{bC_f^^~;JaObm6)hfoT8f^$Pts|Z2Cz1aV0g0Gq;hxDlA@=WttylX)AcVNS;M*ZRZVqI5~*A>z*Or3yROlzO0uI9Y^tHx)wvyMFJt0WOwv>ZdBB ztDU$r`=>$^+iN9btv>>w3C!AI+UA~XRF*F(9l$rr2*B*5)w#|zr%25hqf<;(lqlTz zGImB>F1c|!v*)F%+?j9z+B)!kiXZ(dCBL<{JzZc?O|4%?wasQZV$s^Cwh%U4DV3Wx$pm%mewvwGv_(b%jJWXzl6b%?T}w;PReIo{wB4+JGIzISbN zy5XiAvO$UYqWR{+e*;YYjebS59BSAwg)G1mPDPiYQ1Cf2XgR}sYVIYYs|(MqE`I2? zY=JHNPwd0H)^lr{^VosrybJ})deO=$25lJ(1x_KmWQDGFkWk2CtYybm2hZE`9Uq>o z->AhdDu%hy;~!y8JK{iyI=iswhnuP$Cg(?q_qt`NiYJu6$OdQrBf#R9X}Wnpc+ZoP z{>0Ivp4Msfb#l;1jjeQEFR^-jFjbZ|4iT~UtJ5gHh6bIj9n*k6jLztFl4o%`>THx^OMp%E7$o&Y+}#frBx)fhsoZ7&kV5NJQz<# z**MNvOPw`Kb*9u@M31z92I%Zb*idqr)-dSyc%(hpPvV?ffx9VaNB8?Fu?>zegJoo= z8Dco|hDL(Kqb$lXe^9^X;FO{IdDZ?7@=l(_D$Ed=TYZ)M49AN9pfr-@&9EzDXSN!K z=7-I%-nTOgPiv|42`5gooU+Xc?;kLF){K^v(0(D#6$f>C$1i(PZ3A@3Pw+hc03M=H4Bs1N8LPh;B(k@oP+H#_r2|wreI=& zls9$GtjraSF8-CjO11zp1o3l{oS?@_9S?pLH6`?t2^GP_CZA-~$;ri)r?-9;IuH7t zoNuTz}X3(S3FOcGRPLX%LjLaTqLC z(cC_ET(p70i_^$!ykO6%4wpb0QE2WA{u|JKcbnFLXe;`sfli3&Py-;B%tj^N+RfZ^ zg|EYfXQI60V=g3tG^anZ`AMi;op!L&Nq#}&%gE0~RHN9KrOdxh&~qPU>f zkwLy?qdvoSCR;E$bQIfBWMnI82!N1HYRfg&E{gL^+y7)X1oelo_k2Efsq|bQH*|&7 zD!}UxGFTAq=9}2Gxh53WBxa#}z}Ma1&&aJsoqLj*#u-obaq;GVC3OM_&;#-7#;ii3 zs&@Q}xf7&R^OXpIOqx-eVQD8POlI8yA5rU%7$aNi@l+?b5~=?jMbHrdNCxkVSJbv{ zIi$)ITPik39Gu`cpa@?c<%TLN*TFU?8~xTC&7W$8ZsTMD_Z96?S;%;Mez5X?0-RqD z>Lvk|)3n{kH|q+|{=?D%@MnU_hpFHtVdo-aAPStb;`^d@UQW5+Zng7utpmNfr~yy% zc-Xq%Wl1#T})qm$L+>F@t@c-21G{XXsOL^TEJ0Jki{|ExhKX2xRmazDk|>25(j z^U|o}-y6{mAc&*!s4o=miofQRSy!*OXSumA060Z5ZSi^bcy=57w?ks&6{}4HRo5`# zGsN`Bmcs)8c(F3&8a{i>T0ec2>r$u~=$h2=pF^T$n@$E*|C3nY!x{_qo>-l}qo;$> z(8NENUJ$`HgThGKcJy`>|5#xSjpiZKIh#`tZ40KyryLb7-m>bjhxnYc3rZ+EK+ zG8!8IV($+VgpI`ss3`jc}Euq z;7M1>M)fpPAtpBXjP*a383K?&=kh{w3&yke@GO&pTQsVN@eYyKB?Z^O+A2Js4#6@& zdbK}}+iZ+!qh@RUUvEPuGhi!Yeh?&iq3=h3{>m{@>T%gO*-DD|*Dx_zIsbEnC1aHa z`MWW=PF#74WozLV>{bCXsYWw~yfvJU`Bw2~6rwt*lkPO@v@ghKw;X-(`{D%s+`#0b`ice8TD2i!a z?bfd*<-^6@WNi?TE^+=Nc6iS4A2$Rr77D=-qi~364|WbbSDn5B4`qjGKdH9Y>HFtl zp8x{T{aCY>rSa~(e*L!R9ma8XSbO2qZF7s+_v*s5duoM$IrK`CcKWjdw=G>aN|rZ> zh6=gt+2SQo_VmsuFGUo1@qj>oH+v{bP<BUd2;j0o}|sbNt3SO z{uX5z9M_0w@nvx7i{0+nE^n+;9dR&BiP)#z@g-{Qv5*$cYM2&Gk><7M>kvl%?m=24 zsnt55@cQ(hPDT6xK7R}_e*-$$0#EUKR|V}x?e=VKX&G0H|R?$GI8 z#QaD)F?3FSSDh_C9FSunll@CAG8%ETDjYMR5DpC_WCZ^wyfqzC4R;w2_X98myrc>W3NYY~+`CrpentA?f)-F_8vDqyAO(C$-65Tjh zJ{By~1v&bTH>YzYO^LJKdJ3%xX5$RK>Z>GN#&YC9h>7QnA(3-+O1#erGeJ9}`}9?0 z?aoH^Ck35crhA+5Ocbs40xq7jd7k)_uWg_+(n+#ea{zFLp}n$9M|My_~K>XCgib^LW4cKrW^Ts+s2zn+R>|1ML@2(JZda$65N3 z)8ma+suM6S?MzdtKCH6{Mh9H z%ySrjG5~W}?zY2nuk@W{ZiKDM_NH(%lRrGZ*l73c*_7Mg0Gd~=Sv(trtYr<$B26Py z^2SiAdVE}-;UK`2G2mg$7LqEHd+oGfZ^K zo@z3)1y=(F@#bLZpvD$ferJb|m~=heDZEaJIx5ZXB-aU{D;0hHqFw>onhciLI+f1$ zZ;|&XUr)1T>e#lhJWoVjSGt6O=M4{N^|U91K%xTUeOGCkBQwG>8%L8Y_&n#dDU`u2 z4j{S|1zmTfc$DFCqLZ4w zgtdA*TZ9Ig>@h<#ME0rMy3l7UstLX-L6vyipiG3191{7iuKYbce@JA=BJ<$>Z?iYD z5{wFAM`i}vp5y-2%;}l|l$--P^D!pvl`N8&$edfkYhmyOHxl>Wq-%6^qHeMSWiBUb z44zItr~AOQss%1t?^D*f)_|wn zY5D@JzJ<0qcBH|ze$jHhD~LPsvIH-c6j9Qqw>4BLL`3%K!q~93bN7lWi@!K7+YrC$ za#64=WhYBO_rxpx>Ih7+F{o^U3F$G6s(LQ?+MjupZ#uR*lbG|ZpG{y%kJ8@OfMS>g z=T*1%?EloZ>_&AaGP^pbzh5xq;_Y73E#$spvyRTX7ABnSx~EI+&C4=kSv`i)tBXgC zl$`I=*YWVaNhH*7jVjnSbLA~mjX6>4@2RzHc7MqR8#)s1Wz7|^EE(ja@hHov{@{7@ zGse2fZ$YxhN!1*c#Wo1^xFtK;|3+5FIHO*7Fk;0wsEV>K3=Px33k;mlz5L8o4<5vs zBn>n$%S7Sn#Dx7qipke`EK$5@{+;8eB(9$oh$a_6jFZ#bJ4}6t860veJAJM?qFc*H zX;;wqjbAsvh_$;#JjfjBuZkYRS+_W%~h}e~9Z9T}73p&z=e2 z7h3<3v7_PP<8+;HIF*uXw2(-{ezBY1-+&^Uy%E58Pa@K7&?{uPrkPJ6B+p3uTKMZZ zGx_mEg}`=7cyT{&DV0zauBCF8@nPih5%#kUxxfvIxAUEHHQ2uqYg7I)#hp)irKGlv zcQ?(^99ucV_gQYM1#^LJ7A4F-j4`~IVidNc?362o0W~R|ppDLxeqG>|Y~LzCtFAPjm4>kWr=2LVD=6_3tAJnlhb% zOnd7_XdoGwbdi0iYv;%SzURP z4xMA?M~nUvc3vnSyAx3md}A{GWidbwgI!V! zSgwvdnUPHq@vE7WzxgZmZveLtrPBluacI?OrVVsLo)9Ve_cY%I84i)ZM0=RnKyDSM zvZS(|qMW%QHlqrCKhZ}|i8(M0P_?u<8_uWS=M{ZVe?^F66FH94*f4p8$s9=PVaJ!` zSv!j6CqS(R)L&)fQc$(No6J>Oe^Xgy3yHr05A@#Cb@4fwy=`^0X@@aRjmmkXpIFIK z4GKQu3GZ|V&r0extP9sie;beA>5r_rxy%1Et)k?S!Y~i%6qFl&$s}oZnl-g-Rs3y8 ztemC*?J+u~GOe-U4rk(t=>1LBwM`rtSQj3pCMjD&%}cA9cIf8=LP#2<|X zSxUzZde&05J9_>ND9P6Pz@)xzuF!KVU)}p=GX#enbYb?9iTS0-L)srAdfCnY-xMz&cqEe-8rpC6%TCT2xOw#ddvR|hE2F%O;QRGCa zjN>tW$(vvDyBgx63l4-jlOpVQ_(bj9{U>Tj-{Er+W3b3X!b!qPueV4}bA=|uRC)E? z>mUnvK^IxmbycKhRxmEiPEF4#KJG+_Y|X>Sc<*_IEBV)!=rI@G1~AqEWGC;D)~?{& z-P)Tj57(Y~2en&D#II`Q_1jp|bw;cpzD6rs+Ar-@*vso0`wJWLo4< zIi8&9RQr{*Af_S0s*C3*aw&n=Sf=2Bid6BqkT*pKv&R);i)In%hxJW_%phFsq0!Nw zMbFQCJEmSH9Ux4!UXp%`vWzbi#Edi<@A;fc12!9o+$znO5GL>29g2Je=_2lHYQD40 z2J;7eQSo+ZWpeyDUWd*W0bV7CwSN+aXApPqa$~$!`xU=X#YcJOf=V4B%vP9i@4u$K z1J7g~jvGa8%}Tdli8y@WNx%>l^gc`BJ8AcfkF_d-0j!JxuJ|aKV zeuD5YvHCzrKd{ZqJNR;ToIUb zDZF2;|D@xZj#up({S2mF9z0AGw)nM2WoqdBIzO)>j-6_itTs>@P!bM{&BoWAS*I+# z)K~V2315 zJQ01vZO9!-AITjgZGZhVW4@7EXl$zYIZDuPp|&B?p=nvHZ9oH9tuoEn6U@^V_Ouo+ zYn?!vu}nDjEBEBoSLjw^;ihU5|CtAlGZ^#9xsG!UYObk}Q#)&?S0c^Z%Us1cP|NbD z5iB0AbRKjImmES~^3<<4`;ggYUL5mb$`VtJZ4b27f(L#`MMYX1?4}yvvknT*RL(cRQoxQO+pQK;{>uC~XHV5G&kvQ&D<~M8{r49Jrd(td5uE zeX^tN;nR<5bQIY3BOLut_aNNx%k+)=1>$Si1A?u`YchQZ2W)N-(H{HTO$ams|T(*0LlNoR1OebxcA z>HCQB;m?BWOQL zE%kcd&0A@z&dAKYk4M%eFhLS>{`D^4WA09=-e4;+HJa}!39=$zPwUml>drUi#7|2k zn;QGNYO?VtvXoglbhY^l8p;&cHIM3<$?{LCaG8b3YgWiHU#;?{qg?F%M_Hcyc6V@9 zk7Zg?0Bi&=+w}pw`^$^&vNx&h9rO<0OOt|f%vPy`Xc#Ro)sG;#&o44z!l%z|2mW!i z;Ujy+#Mjv;EG&W!#o|~%RG6UIE;!nV84sPeWw|nySU5c-&>gDWyj9K?TnG$M)etW? z3r^nj*Kp-mkKMM(;qBxE9k2-U9Xw#N`Y3LQpYdAIwc4>>`q(9w`t{tE!F!~&rf_Zl zEfyMk!7KtKQ|TWXM!@{eQ-{~5Ugxa5ALQm08Lm#Xj>?#mm+H=~x^r~5P-XjVBC00e zc$)N_AhKRNHcop*CO)w+6|Sg2XJm4n`d+e0bhNfMSzRr5NI~`JVWXza{&4Xt>68ej z)l=d2V$DttA*O>BM|*hUvmB0Qs8TlNgJ5s-r|pM?Wj$OIY_=(m+iXz(79Y|NeAXfj z8moEyB?zUTT^p{_#(FvqiTnD#bDHQjIw2qjkHDu?%&AkX`&vhzXI%dteQun zNU1j9jPj{FCo)L6v?akFtdxE$*0m4W;x3tHJ-ghz=M8)q%GrTJ0@qk?pQH-0P%n?T zZirgMi<#=#>M;Z1;yBHDw7WqYypV@koCRwj3D8TiVX=Mg|u;GK_p< z{!0xJjo6pU&6Jo#3{~vcQ;B4@y~|VWWlGDVcg!SW>-CXs3WB^-_Kx!IuV1*87`3Tf zHyx@-_WlPuU$WHLvGSUPse3WGHjH+$Cs>xaqlPz>jyLl$EV6|aLb$mEV?Cv_z4C0n zw9Sm>b=q_L!O$^Z?vkLyt0jdpuS%TSnmjK@6qOgCkHew%Tw2KiFJzJ8@|0FoIu3-< zj~XK;&&-*m-7>(xFZsx2%F;8{)IUaK!hf=x2L$Q6?u|qFvI`6Ld1aq}>kkdW&`D!2 z%s4-H6g3s;h7E8+@`*m__uNWu-g7m2J`=?aL;ZWp-P-5V8{h-)!~xW)Te+7?!0pLk z-(X=JoOX{URW9F%KX&$@R!au~FEw235*I+tpzK)5z9)O_5F&hpc578O0s)0{Q zC6A}rmy>J7Nhn_$6<}yS&KX6aAXue+=4aYZVJx!p0t~%hIH5Q-+X41P>*>vpKp;b8 zwdMHA+)B`o4od@Ap7vS|ZJ*I?T8zVFUGt-#PS;&|N}t088y zJscW8rMusIdqrDUXc)0FaXN)z%%RBJ9I4B5$?jucn)Av6 zWzt$&;d;n4i|zTdhiQoZ9z?C}9@AdIKkk){cQ1D#ryhjQXs-i(6DOE_9IFX()TqO- z?D0%m4O~#v(%Kl`Pgd^_5U-xOO^bl-F8UCdRXjA%2dar(^o>U-abIS`8Z{3oArKRF z>x#-f{jA{jy{@Cw#BxEn?XU0QV_&S}1bM=FJ3lB_3zQ~mIR&r99VyeSizd{GvpQPU zga;#2+3c0IKAcQ-JRlmlF=fA7$?00VCY%rm#^Hy)=aa#Qc)jw6oOs*>9x2qtMB=gb zdB_}o&yDzbWwldW*ywrb2im5`Nn9~8xl5O0{0#Tv;b-pV-#eJ%IM6AyJk$vm&qadVN?85MxgZ1|ISH*eR!d zNno%^kV`q0)GHPt6$@s`?-$bgAjkbf6es_w7# zAITGQrX8unpc$=Jg)(McLQhC|*_kUv-YFZ>XaGIXDAVS4y;QdV@ZeKMx}U{9z%5~^ zom#|H_67GV$)Wq6@68LoR|H5ppxblQn`};EA?a6wwcYNKkOZ{-7+LcbYQ^M&^cuC!%@}3)y=yxH(_8XZNOZ_fyeTaya{5BN)p*u3DQj&a#r7$FwZI}kD7XWD>_^w?iZ(Hc>e0E z_h@i_4(E9`3s3Hmso?~bZ~JFU{^k8BEBceOX_Kb`$f=MMW0NhCoH2Vw%r55EB-Ql< z7S3^1Y*S6zz{EI26IZ_Nvl-yZ&#p5%-1iMzJR4BzT*zU}gKUHZw5q<6yzpxHLVRx^ zf)}kBA)}Zh&O4ZU@;AU*-!}{-I;tCAk+g~%Fw<65jH!6TRc6rke#fkjl3^efW6c^? zttsSMecL79Jfm(J6&V%-B63|z8IPw#ME54CAd$dHHoz z*A#o%`M+piJP>W(1qNo6dKVg<9?V7vGDIII1ulrnHppI%iwSf(O!u?>KfJwVP@C)5 zE*@%>7AR8O3Bjef!!86#f)sCpm*Cc*MFLcC4^ENd#UZ%1#oY;7TC_ODwd|9LqCcgIq zKrGm$xnT@*krp3M;vMRw@FRK+X+)>@FcL5aCuaJ~u zR;(D*Ly5L|)Q(tZXrVuUa`Y&l$1yQmSHNpmGRa>!)D%8gQrL(5V$-1?pi_%fwcek7 zw0SqbwX?kV=*QYgArbW>INL*U--F4^66$R<}wJ0!ig;WjJw2Ne49j$ z$&J~UpgRI}{JEJLJIK5@Q(&a+)~qjzi>xJida$|K=f&qaC!8+j4;!<#ATTTcJyM1q zY&y)S%5jE&mn{$3Uj(-O%}7Xxx?HUwprbWNB6&?>OxZp)YQYYWUjEsQF?QD@f+Pzyc{H&DUoa-i*he*=IELH4tY&j=73R?C$ zQ-zb~(WrE-FBY6IF7bhWaQB1&07&-{3W-RdiHutnF{vs+khnBsx3+}5Egu6&ZXd@~ z@(r*~iXFW)Njgc05QrxM#9a`cR4V^D1kAd9Az8HGv$o00CP$iT*GGdm13pO7jsi^P zmqmnrL3oetAHU9Pj?K@HcZxlr{u{vE(94XqWopyYlDi^Rg1>H|<7)5WD0^4RzS`0x z=1N&j7juG+_W~+uM78e$Zc+Tr`t}#hp?&*ON3o2}Dbmv7c~xZZZ=J^88yWrN2>zWZ zzAvEAOIYVSpl|gzz^0b|;XgC-H}?`cGd!YxNW?2!vFYe{I_O5rU*p*ygB3%o)aekY zere_6dfjl2(dSp$pYWE{ydEQ8^;IZ^T32JaG4IS<{q-u~5iG!Im9$5&A8 z-o!RPUb`btAT@WWB`MPFaS^?cEE(N0*4UG27j~VBJ1U~nf93W`9|x~6{Of8WNkzx8 zDA4X<(EWFT!FH&DM@@9you@d82|w$H;uwv#1-4PQ(I?UodR;AfKJNCWcF7Gmgjm{@ z7r_%ix|Cj&@RCwQA#)Qd66p+$Nj!jDM4yR&{VgDU=l1P27s93$| z8u#RHZ)Knq*qCkY&kg&GY7fkw_xkXb^o$>H@ERmE9;2vs-N70!TzKsvZP8uUA_FuK!Oe;*Hmc-FLxc%Tu%qf4A50daT;~V zk`Zx-Z7@unXP@zX^e=oJt8M2m)-g&~lGnR($7IzF3G#jWDmwXbm^tRKq1Us5_bpSc zN2Uxv;TA~K&CIR~?&S#tt$cl1aQNWCl70qiv7pPCzMokq&vXdf8vTB>Q$()}1JPyD zxfbaMqwSZ%u6=!jR=;YC-v}A#gs8QQmK*81a)%SKZv%lRv~)91Izz+M`l_xeYTh9o zJ)t6y0?@(OLw&q;n^;Q5ITK&k>Gp4fKU{q}#qM&@XVG;Y6ls*_^&!=3EFX*5&5Hna z(F>PB6`y2aPBQZ~f^uHU_dZgZLti+Y{wP8Ty?l)miq^-qr2de-gUt72uvgPnzeV0@ z4@zo!9}!CuNj;IPqnYnh%aY|FaLR`eAdUg800(&sOunm2dF)9z!uk~QM1{6 z`;+^BsYd{AW28^pS6J@ujh3I2UEmk96l}AZ7@}+6l(p z-k(>_HVfg104zQRA@6KlxW3Y0epr9}(K9q~@3FS7CfBBosxoZ(3otwD#nLO93Wh2K zvM+OKQ9ir%cKI=lq|H`|%-S5AFi9oXr;jt^xOPQ?5lg!7XH>izQ2{z?Ue7%mZ8CR* z5S64=pH?N|nfykRlk||BM5)|u9r8f(krx|t(}mtvrYg#&K-<`Y^D*f>2PXz_Z3`CJRcPZG$=iCgfEmg-e&7$*p zw7n}>bLg@_Mc-l5>*3kUtxab>*Ux?J7P4CIUm1HpTWWu&1Z3o7= zd*6F#E^`>1K3D(n49>HK;&#m+YJa8pO1Vs3c~2_8If)`1j6VB|KU7vJ@my|d&_Q%3 zB1t08hg;~H?3nFw-^S3qid&An#eAw>fX-g~ zADNlY(_9Hh@4BgCGNww()x{Vbv_{p=f~w6(fPIl+Yov0W(U>KWB; zF`ID>ay%EdXuyH%R}-Tr%LQJ|U;N2ah7C8>i6ecluBqpvI*1->r);X6$H1Nql)LSS zRJHgBK{!rMLGtoJaC73hgeGlPyq=%nv!Q-X5C_IET-BU_);cv=C2)iqWe-naR-Q0e z?-S$U7HTLRQ_=UDA=OHe_Z*#Tn6FRP9$bW&_*JdMF2gLxJEA-`L*(ezpo{Po&N;%2c}eSRJo9B4sg-ub~h&;9!VQe+h>CWnMUk_W#8tPc&}C0jT&iZ@~p&glN>+-vCK3*)(EoT;XHQEt#>A zE+4#?>`<9&O2tz_cf*&p5o2yt0$v}oGcnY(FC2LSN(bA0C_8vPg{N&wsP-p%>bifEo^+ z9_-#3zX%&DvwJlm|J;Cnx#>aq=egr>MIgKU!yn0eHU0i3Nl2pNXgC`Y;-%A-Df_uS zJ5SDr+(1m0IP&qmr|Mf<{|Qz$Rw^HDCFk-(n7^d_Do#9M#h7xa91#e;k%+jo)k87} zQW7$Nm-DYQ&d~KD_$r!Wd(QgP4DN2a)F%`Rp4?&ye`2w*OYB36Np59IWu==NIbq*T z5n@i~$F%TXHl%co6Oc7Av_D~9ESi=$Mr+N{1^kghbI>UV73cgZT?m!cvl{!xmVKm{ zbRq{eAT5-4*==_QB>!&NTAH+cYHO|{&#xlxd6F)<_#i>5yU23x?#Wrmd(234G$D3h z;n|Rjjd47S|-o7%okD<-)jp_M)M$% zvX~H1Emb%7gdXmlZp)^M5!L=Q0{Rwc=HX3Jw=;>9oo99!{#;^(!_9#jqqquc(tAxA@iv<=Q6ZM)^5kfSp7WRXtizI8m5>h z{nCPzbQc#V9Wj#w+i-gC8iLrqMwMhjuk@DpPHQ~a*R3^kc0C`Niv!L!Ku)3%MG$gc zrcJ_1QEagMm=8Q_-p92Ly7x|px`hm<2Zt2Z#46mmY2xQjp0C?P-q9Xgrv z#TUf37)jyEe6)R>`Y-9VGz?CJ^3RN!w7Bq5nMdQhslYpU$Xq(+z3PeWd5juc)5kay zNNuhAa2lJbix6TiXzr&JI>a>~B0a$=znn8yJS!3`qouZd^Bz!a)3L5IoMLh`xn62p z-T#VCr4Z!ukyo-m+#U$w9z;jE9Ghtmh(b4(%|~E|3+4!22ri0{LZycNB0M>-69>0f zW5&s>_{r}1^aIV&5A9;ruoR}=lE0{?HD*+5ps%n$58trqmT>8Bv&&|1xTh}aby894^I_HRp=eOd0j z3MGgjU6CI0A}!-i4xdRq>L>cq)%!f-m(g5n z*eFsrLOFiI&Ix~3(CxZct+kNq>Czg(%DIyhF7PVv`>pcpNl$g1kriycmX*>7{9kYy zR7G;MD7cL9Z)aDe*d%rPeBrU*Jk?$SD$8emg~*{g=N_Q7_M$~r6G)oYvs25Ndxf)B zM1PmP9f;I(TC2xXDnGGabbei-Gw^y~hILE}MxNYW$1&c%s+@wv`B-=C?*HK0;1B1- zM?hAV)EGq}p1xOlGwF}?lRSWBC&o-mejRvgjA?RrXzZn`D!wQ3ew}p~g=B8O!IashE5Qn>>Ltf-yJq zr%Q*s>R7?VZ@G9ayQAs$HK_+ekH)2d+Q$`NT6j^Wi_E4EZ!220g^axOd<`@5%h z2>tA`ggHQ3{PKdJ0ULrcUOr>>T5aZFa&r1si4OH(AwsE5*G842>p0mX9b3sKb}f{! z=5Z3JhnT7Ss_Ljy?x5RJtX4zt164$A=0-{Jy+Dsh!;0NJwcIz_o5R8|^?vCKLH+U8 z6}gV1QR|%R_eX+iAH>;OeJ$0LH&n4=2fnoMdTY=0my(jK7+nsDm=B*5%E?GH#ockZ zYR6T_5zMkg^p#UrQPOWxgQ&5=`mDwxdJ*50iSn!udT{Bh!H37M_;QsWbCFfPjXS`S z+7G*KbKu}}pgs)c#0nApTmUN&#bY7Ig|WG~64*AP&Ev6ow__NKWFPLWb9{y=v#Rxh~h@CzAhJwsx{WYutuh%sNilvW&pJ9#X zE}x(lb9R*(lU(t45}k2P55uXlQh#kVp+QwF!x0I@e8OqI`A?soIj_@ z+>#wQfBX_&U+(MlAy|93sZAd2Fe?E8t8X4HXshK0k~57Y?#{(R<0^_Wb;@lIMG0_+ zMNA7vPv>-s_4}onm>iFvn1)tz9u|x;%M#HzSgY}H=KDDO_=Nj;IlNB}x}-hHjoI1S zgr|FBnbUCSzzji=BOVntov{8kF2pRU1Ec3a;*i%VZae(`m+^G>JNj_djhA8k3}U<5bH|luqn;8G@~+=> z@)Y=%Y4 zbI@E1R#iRHks>|zbETiFVK3%>D3LJC95NcLm$kIOsU-w`Fxf`N5x9B_Njab3*H-Ar2TfiJ;Mznq_Q z?-}`uDNljak<8?J)}V4q*@yM$C_5*|VRVPH?8#hK$g$*br6@eAzmFp^G+kSX81Lv~ zUz2y~%AipdDQR#4!rvk%1OjXAEN-p7A=b6i-BRN^8$t!9Cv4w9X6`nw-g=z%9m9g) zxR_AN@$!@v;0uaC=HERknL4)ypH19iadx*TgnZm;jlY=-OT2nfjTmF0LiMLJWxr6j zdU)t`fL3l+GP@`Jl_tZ!)yDxh2FBd=9aw1iRxH{x-qAw7s?5g4Jg%pxOzbJ1!CgEn z%nP5*%`ra#d({s{q5A)m&Bf5r^zjQvCJXQ^aoUJ}$0vQEnyGH>@RX@c=e3hBWK+;B z4#!4PVhyP;p*NMlPob{&QBbjbpRjEs^usq0F}dlFI{K<*Yp-B5!yN#I&$6bv~iFW9z#%@|Mz!^?jG`nwzZUFS;0_!qLqneM zQ8pyJ*{X;wS@)5`%|HIVPLI-*2_^GI5GSgg#StZ|;nTecm3aY_d?vrouaoPOomX@y z&d{gtPa$cv3CzD3*SG78nrspx3R@Gj)lNO}EL-<%>gaI=eAD=Ifc3D5a_Q(Pk1pP` zC7F=Hml61BV>57vQOJ%wCE-(*`FiH&XY z!iHgi6`D0WQJuq++_4(a(aW=D{vBKvV$VZisF_zfX~U5*`1UADn1(6i!QO=~K} zr*~WFdN@2A;L~uzr|Y|&RD})|>EHM}?1m=ZtDb&oCFDyQ8|ZN@m>Lz!NFCTThwRpi zRuL<7O7@ZK=sG7RvEoee8qp+X&)p?%msFBIW;r!XPpzDmrw(?BL~5umOL({@P*Nm7 z_y^IkQ-tt-Ipx6KQ=MOn71G$_EQEiZ(;4ucKpMGUuj5BIFYWZ1n#ZhonD+dCay%5+ zS48BLl~TYwGy~fc9jVF~rt{r)L~G_pkumwb*}+iZ&5@n*f^@3Na3X3#$zNm+=@rp7 ziQV>Jcz8BXwCXB#7@_EXT~qYxHmaLGF_7{ZQ#RdUT`$`g;Sv=QXaq+0rgP@=#ag>` z!|EK$>N`(@$%j)QK9!?QmGB9C-vS!)(oxfY$I(=KfK>h^HB#yBLo6RRz(e{hE0K;1 z!OHl@-(V!8%g}Q}4(lv?k+um-X=f1`K+t(jq>!zuIu64@=o5BYHdww zx#&11BPx3KAzwh&d5TIm4@QaB`D;W8Cd;|eCk_JVx6F)zbLUvTI!9(5Pv~%$rEd!bCjGeSa&@)kUFyD^{H}*J zgO@vqo~J(cT+!sMUoO!tg%;B5j|@orq>s~leZI9i)S<`{@G_t)*MPw$H)5ylk;sKd z>cp$o%H&t4AY(mw?l9;!hX9jl52tG>$Tj(AWh>{zamP~>H^I$W!T2IoRQq3C z>BLY@*J$HKTt!C$`xZzpiLR>GXjUzE3_pXh6z(i2R|NUB@Oq+w$QZ=ZYt_`UVKTB^ zsN%73kI`rl24&b1B_GH0AKk7Q_GVAEen)f$C2cSH`5@P9DZ?-3h%x00Pw* zuYRDOygmDcyAJcmuX{3aO8$#6P^swp91j(X8~p!YnfL8+9l=Z*&mj6`FH?`0qXaY+ z7QzIIAA!ix`4$42BcN!M8r8Sjs={bACoEj2cx6045$ubf)W*sI8AlpX8Q6+@4${J7 z4T+PA*TZ(Tfni6k3i%^dkG7eWUpWy{9Fa}TJ5408k8?G}t@wmKZ2gwbo?n#&q>4X* zb1sS}*VSy#EZ(7o>ety5iL-o-v^sSzf3$^onxKeE{t&;63tPi+ij z`Vt<|_e|O=MvgnGYGAk`Um}zIj|c%kpooE8yuLR6iY`9xO2a!5BUZZ{f8Eb1kR84a zrN8l`)Qg)Br|Rd>rS5o`Xt%X5;>z(gXLa7^0%U5C_+V}!7{pODWqd*7{*3Crb9v2V zn6CEE+_CL9I}dAy4-junI;Q667)Hp^;2ZG!VM!@3Wo=TVlpEjCy;_Lgz0u_N7g?d6 zKUXCPh)Ko+#DjA4&~jYzB}<8Lg1$@lhdHRFOBQk8 z;L>&I$t&NIJ$#zinhS&p(y`=VG)P6)j3rFiZ~G%lSxZq_4~ko3H3=@mEptUZbLDqO zo1z-E3>SYnTM6kJNm3YCs_TW>HDd~B8t>B+EFLQeQ<9CA@j6b`sX6t79Z&bAESSf> zD^tvQ_ViD&f%BeUakt;uu&k4Eo}sMdb*BglgQ19Mc(zFZ8tV@B^OMvgniR$&(~L-NxCgPDfM1v{y_-k^&UlWjR9gOltn$EZc0Eeg@aHL)!o(9|7<4wdm=e0Y0*XqqMcvm4Scc4IkHG_)`Kb%={ zCHQMrd2z=+)XYyln8Ti|BJl%gbHH`*Idw}K&8P+Yg9YP{M`Hz!r!cEiCz%hY0!0+& zl#sZ(R-JJDRXK6dXBvhZqn_{0Q$X_SK%taPoMp-*GEMxCZz=gV0!cP=9an)SWbdMq1s6PvRtH8*=VP{u@+lw}a+EA}uUAAN)ZD?+;5L_~EY z-a+^_I20c0GyaMyke5ksYT_?Ijpf&yo+Pk~K6_e~<}p5{SvGmdkrmpZTfiNTp99}# zrxA@RL4hacEYADh8Ie%ncGf3zm0}y9?ed{Qos962iY_TA9)tr*@X@rG#>Pky$ER|ef`al~RB}Kzp1j-P#%&=!x3kv-ZJ_%DsxdRC zQgiT$QTL?}1OzG~j$ML?vIt7lk7}_&6mPn7e6VuDZ_xMUT|mZ~AOZ4%87GZ!2chiN z*8yx*S2VvRgu-91F80{P)w6Rqlc?>?1{r|aT$tmMxNq+nvpB>YsSj&Pfz1l-g)RI= z!QIRn(_hwG;(T~F9SmEuYo!@@mAB?<>m!#Ru zK{|7l9$f#0TH=)2E@E_GIu)+(6eUjBjlKfbcM+~NjnAxC=AAZcE7z^lXMAL?H#Jn_ zgzeS(IpOkj#rMZ=g5Oo;mud$;9pNS)u&p}v`F?-8EgK#5dDFf-KAiy(*0!cFlRoH3w^QDY`F4ps69OFS5Q^NVkc%d9lOn$BhwJ~;fgsK9lJ|F zeEq+SDLy_PPf)X{WdY!n&odrmhbY7b5$m6mK?@VyC);Ip2>fvWn_YNODP#VyLfDQY(b=$fuSo1+JBPfLf-dTHddi*182Gj9j zmwZ|DZb=_wrr)br=?hW{275F~! za}*XWAcYJ#g2enYpFBY9nwVM2BPb0`D$tS&b~^D}iqf9r`0POo(!XIYDIB=#6yK;z z0Y#gmyhRDLal!Sz2z`8s)-E8YuF==|5uV*)T_8L=L-5(nJ1pb&EQS?{hu{k;CapK% zdGm56-#CUx${JYICI}(3pkLC{D*1MCUyW3r9l;#z@sTuL!{@OIP~fvK)w&St3t{4f z{082p=%NiMF4(SK13cHS>6Z8zS#uN}P?+t7XS4iouC0sSlefyZ0(VpYYhHoy1oiKD z0*edUwK4Q7e(@h69cEPT32)#RzdtHO#BE@oUY4=q+dl`VPq_<&&nv05oqhLQ9Exs+ zf+Z6r<_BTQc$S&#sEijs!I2};m++eMQ~E2pu2Yuct?BcBA@duQs-FNvQ$hdi>@JS) z!&GvHj#C^~C#6?aE_8y-MSvUP43#HGe-en^D^wh0)G>cVlK4ovIstk_6Jub^+3Vtu|Eq{LgP)U;1R>Z3Q`l)t#5d{<)HrPZvVV%mU z5?<9gGhNZ`yegIhJ*Z)&eHo%6N!=dp{1OXJ)~-%-ZD>XKtM*cF!1}zXPedb3B-Cf5 zRl(yt_*Uppu-EEM5%Z^5Hkyl8$AU&brSCc^YKKfoGZOVtD)amj@wCS-pQq}2&Cb-e zO^3cZ`77HB7~39hBNf7DhY0bl#)N%zt#$Q8LyVO!xiUIv?RD|f#M35f_rf-Groy|b zawuY|E^8`pF1xG8lL@@AAmO+@t9P^{&xYq}Ao|r+KEfx${{VheWS(#jn)Y;X@EWEZ z_xnf2^A1r-Cag2m!GYo%e=IoW*W&HBuj_Bhdw7H!8^&hHPm79q%v(dE?pF*}58XFP zGc>}?ch=dja#^WF?PuU25h0D0A|+kY(vsW}2Wv|;Fz16U5Z6{U1K_cB|I1Sw&-BhV zTak)zlYHQClq+{qrH>c+6X{ZlXuIz&oGFX?R<~YCS>idPyJ2Mjn^6 zPGrfm;n}k83^hdS2s>({-&u>FIwgQzx-+(#%6F{s@1qx)4c&Nvwu+uzyhrlKJ&8-Wu1Ve(Z$on`^J8y)PB_QZGXpl#x(usVuFL7yWzQ# zLdP!1$(8b`)9u-f+qfo=s1^ZUH{EbGos6OI$i`4UGL`k>N83VOZ%_iB z@)bVtCmaYJ!l=rmW3eD4G+^nEt6QXmjF!DMhact;6ik$ z%tGBpKlkwCZNbVwRR7O$3(Y}3pm8xz&}vsov|295P0t4ag4y8PMSTrnbxO=oOpC;X z>V)pOPTEZ^?{C0kzD`vi2(mvJrbgQo5>4Ya+fl~(#o zT?4GxO)o!ygOsAUci-JGcRePjdGdLBVx33wpYOeaqm9`tI#%RJOAOr0A!`fHwv@Lu z76c&N_HYomaxx}1Cs=_?dC*BvT5)!xniqkAYBPD~cKSaFKDsUNFKD>%#8-vtYo;;Z z##|F=cjDwj%|~igovt-%7m!YuF&?{TN-O}1gD?}nC!cCcRVl8uu&b)B9@5hVPO49x zpZ)2QD5QJp*^GHTbb8{wXc6?-GWn+ojD{qex8BM6Wv-+#SbKNaSI8^)g;DX&SO9+D z{cCCp^U?|yX`}nn!Od*zxxiAw*5$*4^pej!HQp<)VshrYayXONOjX*v_oY|~rVl+H zeU#g%;KXZDyj=aD%>x}L_wO1Veq&2NX@LQ)U}oLM1wUaD<)_eGZD&-qfcyC?y9|;1 zza!@0#C@AJC{C9GZM(i(1eFuORn)G^(%MjGTOayvVF1Rdh84RGwfvgcIJ|*4aq7p- z2Wik_9L*t~{#`ZzE+Miv?T?k=hz%;X6f=|q7lhQ)uC0SS2BNozxh?)2c5BRRac4n1 z2t~efAEaj$@ZyX`^uMer{SqY9sD727$A0PL6GZf-b4mF94`r;OGh1?oGgt$&xHae3 z6Pj&z=)j*WN^3RTLZX35wlml9eAozZKIA?GA?wQE+zCXz6Dd)nV8{;?(nsk2O35zo zgu%VO9jtR3Hu1}pjo*cx!D|4u@`tJ=iKY(vlw_!7i>N0!zkDfS#@UOi72vs8X|7|G zh3M?1PMWUYNYgc#QZ*M&>lF7eqU(B@1`Bhk2BRGi&9Fm8ZoCx1UKr{-C;MWCf*$Fp zWH_g~_vfnsrPd%o-K@m@uH)AwO@_xn&i=l&qOc$1nCt6WKGMI2yaa!VKkQp&TL;wu zm+;Av3ydy&7>548!B_+x6AgG zAVq&cYfi-l5-(Cj0TaD&ZLFi2eL^7|I+#G}WL2eMR!go}v$J*KxWa1zxOyFyp~E#6 zb;6bXWVY}wI`*YvdcSqCoj+#$A3GWkBLk@Wuj|B2Y?MZZHHSJv^3!)@GPs2#(})MA4O?Wm#xc7_%JYQOMj zF+z3UKEe8}dsWiUH$d7R*~>WuN5nFlbio-8Dg~Z<&By_aA5eS9{nH)QpC$fo2jbjK z?>{><^dXv)+cDehdy8IXtkouuLSou>d0~PBs7Y9UsBdj1+1sy#3t-i4B6IzrdVwS} zf-aX8Vo1D%@JmL8I-2YsLt8%z+t~{MPkj2FDUoam3lJ1IJNcR@v=b*8Y@SqfG_S1b zgUseCAIZD{3j#oaWKX3sNfxQA8a{f7%rArlpV}))_rjyuukMOQB~ZD71kzlddHcwToV zg$-B^vWSKK6Zg&8OuhmT71H0N3Ok94ll(+P_%m&bPm2H0@!9T=m3+EupHNLLp=>ei z8?M9P1F`EnQ_Vc1cmmLQl`?ZoH_Yt(`Lk_t4dTixhYCPc+9fFdVNBBSjYdeOUgrOd z^DY!Gnxa6HlMV=oxxhIy>z(=0uTs&p@3HWYw7ZX3;Qw_?ixeQR5ekK3?!NYa9N6>s zWu!&Q)S1=>7VeKHlJ}P9b>oq zW_Y1|i*GPTiN5UGL)tf$A5flVBnoEIf-<{fD(fI2Pr5(zR6&6I$;%l+QG37DF-K{r zg<8ZE47#)>@7MBZ0w5Cudv9c%KG*#TVT4!+(J1D^id;tbKAc*efw$<0%)FSktj*I+ zuE5OExU47wC=V1@Qtwks65R;G1c!__Qiw=TS+v6b3LF0%_D4eDulv~EXUw4Z(5?g- zr&rY`W(^dsoBh83_|0&qQ=Pp)W1(t?sSfMla(gE+KtqAKdQs-qy2Raf-nu?6!FI^K z$hLiTw2N6W?8TfB@DaKQj;fLLW!xSQ3j^5d)OOC0r6(hGa7Vh!X*>9MWalpTI6PkB?s-X(2T;u zy5t3=t-7hQQTDtRJZ9OOCO=TR_Nb~8gU0~R$E!u>-}D?c&VsU1cjk8%>|uT!nb=h1Y{lKA%$m z;I(xBix~9N(nT93LI5>GM+58hs*6@mts?6#%~TqnVO%tI%Pr6z)_ZZI5i&8uHDrm0 zE~Fm;h1np6__|E6HGm1d7b11$y{BW@FT+t5u2GJL>CjZ7q$Q)RN==#e?_-`9>XJ{b z*^i{3o_Sn7Y6b9fg%4&R+*oUf)6?QW$yXaaB1g4|Z2^DPqEN>wr}xY$<~A#(u5lC5 zq9%Shj}%c}WMP1YIyYY75y{$$p~{lVS8Q0A09ane`dC=cIU`~(F=?j0Fqg;1nN6(* zitfTwKmK=@$Bot1UpapRsNW9#SC`}NmDImYjVBEX4U5V@@yi2JK8K+AwyM~Q!%nsO zorPqOE9fVVI^n5pV8xKBj7H9b2Dyi>v>TZ#BD;pgQEFQNrnF{Rv1ed zpH*4a$6r`m$cG#E=!4r6<{d2Fvon!(L?tg7tU5U3N`FYehT#;6&t^K|N+N4kA%o_L zhNBrO(+m0Djr>RPD>1su{o>ue&?(hmG}W0P9@=!!^fy52?fYLZioRM;^!eB3e^=N% z@?NYvBrrTSfzFUNx-~DqSMHmcV87xz5(c4InAXSndEFwYf3~;zM2oHFs|JcNFJ2Cu zw1&bE-AFFFXs0=j8%Q13U1f{pu!6JmFa^PL8iy zLv0fTv*QxxujBoK4BO>bBZp4)D8cj8D9;T~<~B8XL5!2*jD!9}ig1yC0qB1FHTC-r z6^|j5wAjbZk(u5t$R*}+ew#Y#MgjHfO%&44!qqw%`bwA;60kWtY zn2pmqinp}{k~HWv>Z0yiRC#b7w87md%HLA>YUB>Ei4J$uF)@fVx0_jQRZcLU9L82! z*Qtfo)&B~();h2Js;xkrFSQSfOAKX1)yjdv1$3Lu@(mSLS z4lOj$;-b^5E)YW}nyWyB?S7kqJGa~z?pvMABoutcg}$(Hp|1DaeRXHORATRVkf&VP zje^mzKa_GJ|Ib%}C08}8)Zb5Og-w+<+6Q6ct!=Ii=+u(56iQ@jrVRhD+J$QU_L#ya zm1^gYfdiv5y&-m5&sG-TA|r{xc7GIr3_(%9F5cAZuS)Z3*QPNP;jCwGS@~KOxcb&D zZ4<>N0~3fIv{zJIvBkbcMc=xb^I8L)%Ts#`(qol|t-k!OI={fPSEWwAk^URtcEqyB za!LEBEW#(ol*w45xF39gv42jtiGRN8Msh4k`bJ*_;i~M`Ob$*Nf^Ghx=F3-_{$_3s z26<5u^U+hEmT=L=@{W59H!Fp=YT*yE9r%CoYM!0t&ehrS`L zULD!OYp={W<{2Wn3Wx-=Fx&VCU;3mEc%(6C!XOs0kX(#Hi_ks?$+BNWoc1^Rmp$PR zC_l&4eYzSe97O<62&@j=v zht1kZXepKI@%TL4Q4|Mb#&(_G$nsSbrx`K0#kz{QriPmkE9ek)SfIIBtWw4ehq z>COn};B>}0?^DVrp^oaZ3zl+Ri|NBBx=4V=!YP2x_XDEWB-r>s+B(a@DI5m(#I zhmzhq)+5-?5FO)V3=C?xOpd?v6Ne{W1}hk2sQrU+n7g`Ia@*2!{7UXXM@!NtCdW}W zJ8RC61)X@h-MZNzrKT({`!M4sQqX-MY4OSGs2DB=fm9(YkngfOo?QUk3x_-NDcc~eG_D1o9nJeZ z2qi=FLayS2jtMdi^c23Yi^Ivcv^eVR?PW#SwwzV$wbW(Rg}On1%*AD9N$j3X#TSDi z0%=)cA(t<`z^NNo#T%3yS?yo=PbbTF9|RF@CC935OL&S=IZbb@MldIEIKL>zWJKIk_=im|E41VpVe zYAtlAUfrqQN^pj$vDi`wJ_CuEhy@ps=ZX>(0~j`*-2`83q0@aLts&dc{+jWWt_L3o zC&Tnyct|-WYO|tZ7p-IplLwYznkHQT3Y|cff*ij(2^5#v<31pieR-3OAu^dxA(Wcs zGZYK<;sR>9?5Cmxzwe@fWPMgWCZSs!Y>8aOFg@E`p)h=DWx>EIg?fl#x^4nlt2W`_ z%)l-jZf!1zh4fa%ta%SM<#ga7n13<CbrC(%a_@(PITK0CV>~#*^We}Q09pcyt_LdViI>m zXZgsuR3Whdv^eC#xnlI&N)X(f7FG3bKDqt`d{-49N!2*~J>ylpIhDo+P_GxR>^IGp4rQM%A1=-?I+8{SlA3%s71VZIW$U9kpwF z+8+8?EoYsS?--dYr<%MoC=Yrlke2!cz);GFII8E(A1zH{`tZk=I+~n>8$hy1Yx5kYMGmNCnopEZep`YB%M?VbfVwo;cDe zU_K{b+SZ(%m)aMasTwx)pp0;fdQ@dwvab`%1x(m1N-flsM`E2$E5k?tPo_D>@}QAW z;CTFXNKawR$ZF-03C+3(+LcFkjKq%k+9C2$sP6X+$=q_4+JdRgp%4av@?S3&AmWWR z6Zj!w3k86y^@{X8sS))g9pOS_fnoi+R^1^zC0?gTq316}fHSY1 zK>31k(*FulbL3He(Ed7Ixk&Dc9>0G>6rht}k6LzOjV)}rcqZ8wN?|N2T$deTZq#j( zR;N2_$pUwD1^*=$bl1}~atZ!FSbNK;HoNY9Fi0I}p|}_!`qn5f9bJ{WIE}qEVfs@@92F$X{{v`#er@_3 zuV6uBhuc8otUxVK){_6dB*-zf`-Cj7;G$#`lE_k=qzYIYFv_nI&jThe|HY{H5^oW< zHi$~%x~VQ-%^0`_U*@(i9Huu3d0ZQOrp?h1=LW#_r{@jnuu55ZNQ^c?4Uz5EB+FdN&nsFHAm(gnI0Tdh`Sh4+}EFNW?cTF_$gkM}+m1tR6r{bQN zjFX)nBDm6aGGR(p!_%J5jWFAH)f7;q4s=r9EFX0IZBnaskcwBN9LyElRR00AGAi_<7nq*~BJ= z8|fL+5+{o5dGqHsRa?3=zsXZ&KmYI}n@vrFP80FOM*74wyoiVfi{F1jtrCu^*n~G- zCLI->;p(w9KzT>r>uiU*=+&~h{zDCYMvkEUnm8LJBKtEpmf{9K>*qe|Av}n*M1h!j zo8nSkDAn#ZuVkC)mY8YG%J)2Uoy9ZLHHpL;q};+xj(d+5KOzkN(BO$gYuDqYExUMWB#(2YMqM4^qSGxd zALk0Mf1A$F>Ea#tx*%Hqa-lEgNblK)DacvhF*uaN_y%)3sY!LSx`;k{z3a$48@DJE zc}^92-KUWI2UNz@gA7%QSmS)TqYFs6UUtUB+ct@^SC@s0KaQFJB&oi*na9td`oA)n zbIm%hR+Q}i3}-2MIH?QAw1oRj5e38I6-LD<~iZkRnSc2-6#}3=)d%=JrYzKu*p9!aX=F9Z8G_Kc=K1}1u4gJip_V~*Eezp z-?+~}-SDDFMz-Fq*1lSVsl-P^3YfCPW-yTJgSW!$9YlkrHtTaD!L%QQ?ac?Tqkq$r zSFlM(vO^2xW>IK)>ESg%gmBS!=`RRW^T9}YUHRhC&`(eBZ}G4d_uEh%%yQatGPoaK zjnM$pL5cO{KiB*J=ePe6J|KAiKlKQIy7B)1lpm1I|4JbMU&J|Umz4_UMKnDumLKQc z60NKAj>97bxg56x4FKu2}S^vsE!+${x8%NDgk}?FA z;c}BUy0a{J{Q)1_tcciml54}*Ll#)ZOcaM&LFKt-YlrH+PR#7tYSaregs{96g`{K6ZJ#tu9EnnnXu=cLfXr~jmNE5Fu}5-S<*1YiyV7+$!f772Wq3&=t) z5r^_%<{B2tTw44>!apMByYUAkS+#^3^fmv2GAvl;6ql}L^N;Yx*7XprQR20U=4Wmc ztk0R^3>fA@)}lULOz@yaI(U_oIk@h}RxX(Gqvg%tiyFhX((&diTCQi&WnuYg=C2Yv z`2zLB)^*5xCj{KoOHv`((_Anv&nKv+vdF0vQl5+?=L*%)*D;EWj5>`KA=wGP0Zxu| z@yqx^LtZVn)cxt`Q2%%i&qngbx^O$Epj@M}Cs5)b;bn^>fR@XCA|CAL;3zpcgiAXc z;dfL0kN=aupeW(_^hf=%Mke8eLUqY?Ey?_wWvj>@4V1@}C(ZRfYbi`;BB;JjX<0LR zvS%Rt_XvgMv?!^?S>eG!p0_lG6k)8#c*Ncze%BsHp|-C{>Xmj%XdYi4V)c)aDa-{}k`jS-%*!Lgcrun#Lx94DESMlwnJcy%T zNaPRPOZf1ojVJ1Ul-=V-W~@)4DCrAxE8xjx5ix}psFs1e#9Xb8qBLDc-hJv>P{s*? zQ=|(gp5QhB_~fQl5VzpY+*&S~rMqq_`ppJdupi6!QkQR0^(AVawtzw3WIJ+|1ZX-^ zxlsL?!fO%TwrwnSqj?-)c;%hYeZWiC*z zJIzyME>@WkOJ;wUH+WL13aLxm8DN4&)k>MlcB^xN*|bmr;e6gAs`0nJ-v76-92Pl)Hbz_L>#j_6Kx^0J11rI-Jzz5M&cHT z>nvoqIAwe9A$>luCe$ueO^5tkbf{OQtC`aS4Qs3hOr-r^S)KPII%>eGDl%n77P*Mk z*!{#RDPsR83ZYjHmP9>aSLKymsq2(#%x7>(7*$9{zmbf~Q%kDoL|)k=!|4U%y8=m^ zqvNq4f8690XV^;@p*dz&{VO6bmC2K_iu6+6^V>&O7Q;*hy@ZSD?s^p^OMeln;$=#h8s?i*kLVlpOOH+Sk?Pk->^0^?T2mFG1! zf9e5g98l41_-XR}hBfu53<)QE4LXn5il;Af>j;XgKOPSUv-EUxnLR7HSEr!N^%hK> zHYu6t)Gz=&nh4u-Qaan^<>vaG%`MnBRr{f`crzm??z*ME;_)Yt$KpUXV=RyRLF}{H z0mw^Z<4eFkc$(f>?;eUhuIkxKf^k9L*?R}4fb<;Xk6%oigp3rZ67~x-$!(^guKhx) zUV&IfShuFX8;Xci?hxqL)w2)pGAx~6+^{Y&a<;JSwiuX92)4GlNN(s$irlk~-s zd-4Q@%IClI57)-@$8WkNJ1lkNHl*$YIzOOvA**!wTDjYG?UxRRvM`G%Qxt2ww!w#A#*&gE)-seH`;pcSNq>=<{BPD#c|`*YtF~6p!XuzI-;$8&zt%aC_^|r!(g4mf<&=M$THby zl(#rS>KBM3ihdQE;rFt#P#dewiTp%$q~_YV{mysX_;52Zv27qf>I-s8c;ffmHQp;M z=8wtDjFII;rYfxKbMX8L){;*HPaf)(CCFUx2wqarhTkZ2{%NPK^@)kb31Mb}BfOme$dQiDh(VpHdeIg6Ni7a6kF z;^5}y=sjbK@Bh4TYHU?|4`cpeQ1?@cCG(qM^%I{-``!yb-tyKv8sPC_unxG7tdnl$ zXHx39Oz^XM^18$-mnli2Q}qv)CgtwzUAN^x*wD=mr~(sQHtnZh^-KIS*CTIgF!5@6 zbCA&ZCb5U+mU_QJJKhT{vr|VRj`fs+L=kKJfTWouHMivPL!&#nk031J<3}PuBe8Kk zXo9-?R2A4;K$(j=Cy7O1$kHfRuqGkWkH3A}`8`hQ8b^hYvFXzTr}pB!)a=A|1k|T> zWZ3FY$wY3-Dn*m>sYu8jE-?tZ?^g%oTpu^vyu~}JEy5~}#XYWq<(Wy{S6Dz#>*@TV z>xmPU?IqphT6%E&H0zNjl@jyM7!MqAqtcv+?oVmFWkfYH2vqo=r0Hk z;H|l?PpC?J#g!e{ZY^*21Vn0V6&h@AMxX@@7DqBSb&LW~vAgG+Ti@2nJym6}tC0mT zds99sr=+jhHXl=$UQEQT2v1E_X1>^Ljuum=-(YQ&25X)L>X`mhu#f@U%;w_Ihxasu*VM!dDNb(1mj+c-rI!7k5 z8arx`US5Vg2Du8~OY7_Cn>r_nXB2Q%p_i`ZCqhome+j#ID1SXL51x$X@;ayQ1wF}2 zYcA+e$O$zJiw{JIIh>z6`et_e2NNOL82``$P*;;+4Aw92U7e(ruoE!5qP5cZIHaVc8MTM7yqyoJ_!hmIDq;aG2Q|BLKrNYU%CMUcR! zgT;NXpW$qc2|b1CHU>yVRUN~H$R){#4l-XEkQrKFFxbI^m&>m>xSGSuUBjEQv;ub> z7=ngo1+IAaG|_Sibku@7GbyK)h%7NLAwgv=e~r5iU%FOc`+l>X0feSU_q zgVo+{z6gRB$aY!_N+banir4FS^Jrewl#Tcl@&R4#x4)oE=n|^ae*=WOtUFw7v5Ggo zdFGcKHyEl24<9Ea%khd3+e+ylakLUPwF*9UU zaXs_gv6pdN$ZPC~UAT%oKb@y5{FwtuMj%I&wC-Z0@n4Whh`;~CYczX9cKp4Gmu3_y zc{{)&Zv&vPwQ;~a%?O~T*YV#UFZ`w2fgC-c9#LfoJ87b+zj;z0hiPN{p`hKBvk3+r-x^;AUZ*uYTFG&A` z03hoZ@gH5=;{W`VhjLDYv+|6G^1FUR!9wR@Tk+r`mBz6eoep{Il~2)sLBIVT!H98$ zdTQ;;2Ck{*mA%LOn@azJc)FwHg1HS&QAt@rT!Z|Cu|Bx#=Lww7s|_}G`3xj=M0*!z zhXrxZex8oa{xK{^@4_UiURQbXo4bv`g+3nX7eh!8}p>hBnYa zFG3tc9LMn0FDQX4EXips+a}z_s7C~aj-`jWC#7>xnY}P9&N>mW?cS8V27J*)D4i8hkG-ihaL5z6iJFh$%Hx-utLY;uO-Id?rY*^EU8Mzs=<3@C3BPZ$rbfC7-p4P>vSiyU+Debs zOjgb_V41w;p_mjF^DeHWiZ^SXP834ICF|^k=_DIQ_Zf#;Pj06PH;TU1&nnIW>fS%4 zHmvKX>$!$=WUk$H)zS^zcKMbVOP!Pug?wVd961dOd?*=(j>On&^2ZS%kn$3Rx!7M2 z7wqMz(277J7`L9{EZL#=H`NiDGi~(1aH(h|UtXB3We^3T)qS5oi^K+D;cUn*bWG!n zYhN&f>IlO-pY8h#>LYb`~}gsL>o-upINlmuoxpSfwx1>#w59Gnmm^zu~ZV%0njd%=gn37M6LP{ z9aYg);$B}FOe4jRn$(E6IhLP`4_w#xNqqcLb6bXOoY})pVH?+1-e*_as`VMrK=TYU zM#h|Iz9nYj!m%otK3VrBpD$-gIl_5xFNB-Mt9o|Zo`}dqPD$Ll=@}2T3zQ@c-c|6*hoLCXuO_dbJUsK1ofq9)_mZiQ|I}t#8k)DX=C`~ zSwb=D#_t8WYZEP5wsCINGh5hmS#ReN^$!BTNT`XUY2msd8Lf-N*AUYI&oVAvw5Q{p z>fIOf-&Y};<0GQ{6?=2koS zgGv1RMQylR#;MIIbx2k|Q7d5-Rd!QsIV5F9Yj?XSCIJi)@*5!<3K{haNo($y5%pRv zSdy^cA*rEcgjEPAt0O(;Lh^bTDIWMrKBZMoXpipGLH>TS>KEg4xmU>R5%;&h4H})JvdTC>ypn3a}lMPK_dA#S?WKkA2-#t%{DPaicq0%BGKl>Q*p zuKa>`^bXl2c03?0DG^tNbBr_lSjPUiQ$1}Ij4@92aDMBM5*D$J0JR^|-$Xi8dUOLV z0PEQpP2vHveD)n0Q>;c3rb%ZwsaOIhow$lWxGfA@Z9}0fM9Wev z#<@fwtoOg835aSUj30Dy!Yz1Wr&ZGga~_(L6sdcNG%N23jg;hRc%QxJ|HVX0vzF{h zyDR6-`|`z{PsmFIIm!A=i8ass&bIjjMx$5%qNqPGg)g2n7bmt9itD zm8__Y8aEn-S;G&+Y3Q!J>bJ3*LDx>=1gw&!meTqwl{9{Fc7=nMy@XFi1}HT>+WkX8 z9)|7y&A|1K%{VDl2_}1_Pui{^96G`N3iWM@zRN~4gL%N}a2EgVlgpSk(SaUrXrpqI z{aGIaFCxAI_zQ=-(|e1eWN^Boz?+~=~7a!-Bmw1{MkemNMj(%?X7 zSNuo;x^S4weFFE3E#H=gp<3@Qq4RU>(Hn4=#JZD2sxt>GmY{oNvU zAap+joLb!2o=SH2R^Fc}%WCb>CyeXkQ8krLJH#R*)XqSh;9()ftbT8>(vILF^K}Q+ z8*+aRKr*gWTY#JAr><&K%D!jc7lkTEbt$8vI!hA}oj{$^lk3d#0*4;qX}ku}5OIlPCt5Iug{|nm2#s|H;$61+HgNOaoBG-*zR`Lq1RXf85VKoevOi9Izl)(dc zb6f1w(91cP<41JOsAj5qRb>?!8TliFaNn$7)UTdcr8arq^M8J*JpDRJQ^$ru$*tmX zL4s#AJ=Kh6sAR}-}gJZBKrrWbGeF!7-rrLtl4hMTq8+gM6wkB{#yc%5Mxfshb!c1_<$Ih?Whh5fmemgW4+l`GXn)$zoj)ub9dAf39mX3Lo$~#Iq%>2q*(m zme&4ii|H%Z^3Ow*+MItjKY5R81A?L&*B_MCwADSCG5YeW`_ERV2}Zx+G>?kM0lc|7 z{Bfhj@ciA}Ci^s0eLDyPI%tZ=b&09TMhz>eXnQJo0O^!Nke&L;=3b!WEB_voGAjWU z62R4}zaYiOA&(|(_MBMn%os@7I=lHwJ}v04*@SH>!lXPfR&SWoC9ZN)aXCF7=h7M)e9#PHr1fETz1sC?fO!YZEno^>o z{{_}v1F(+(K$F1kwlt;!iY4tqU59W_Zpu^q8igvq7@+>f+`;^-87Lh2>e`MI!ZxXp z4>PYHU&d8~SA-EQ3QWX73NxpG0~dkbBaOa4xu+@(G>pzqMe-?FSkEF6$4vi=@^ECxxqWy>NcZ$oYEtrb{cJj1SCd{%b zD#G1IxbN^puBRApNJYl9^UY-L(hr4iUL-KOyu#OGhYH#+B-OxJCB;J@*D-2iP{ zZ=A>Px$Q?WV%`HKH6B=x(`#W8v-C@9<;0mqT9#(%Sj2kSRBd?kz8FRqM5`CokH z4V;UMZ{PnajBa|F;Tg}IGiQ^KXTy0OYd7it@t2@b5JQbv+yf;V=0w&mM3Ti$HTMbK z*H9sM7M>k+@Un_Cqria3(vPXuwxLXkYPI~E68`yWcg_y%kH%;1R=*2?3zC;#V3yZ5^2X_qWaSEFVn&yR*2?>&*p zvtzr(WafVgt(aMAUL{!OE?t;ZL=_wiC;O>4>5ec)E3k`JTD=w+EK!>1Fx_ErANsyfZW3FvbsT9P zSL#-G6;*o{i?M{C-w0sSZy3uA^62ej)`xPk%}mDC6`&XUOcWXF(fliaY94-La9Y zI!)(m>_Kj?C)c=XAP}4JB-B@ul^wa@lZ{Ek?7yIYss?tM-~9!d>8C}Y-%1pISX9Rm z<mp?bS~1PkWNe!J0|2N6iv82CY%fFj%CrRvL*?i? zB0?JI?R@Ftqkma9qd1isU?IG+kKC0slA9ilf}Aw0CYAv2&?^Rp785DD3EpY6H1yl* zEfrIJChTGECP!gRjSPkmGgsUox9Izazx6X|!*2DQYHpu$ejx?#wK4|T&G1>Q(LPbX zR=}*TzJhfs7gkQDE=94|iF)8W@J8R&^LULY|IOE7bJ^W!MJQci&$wSdIrGctsm|EG zZ2ta*U3V49{BgP=**P?e-N4`nG`*!&N`4NSDJjmlbDcS~jshwBRF4(j9L#(zkKQt#VB}IP#U|V&zr$*9iJ$!V*g{7R%5!qJ8c))Ykl!0s(I#*5 z9(7FdW!!A+*GMUnJE!=CqW97Juyca!tyWk@UmJ#T|M7r&$Yes}mG|uDL zynMLUmYX{lCfBL$NE{NE{=n7a>gkOg-d?%6EG)!LrF_gz>VR#gEvTrn%WQqtsBV8G zb)KqkOnxIHUk2|X3j?p8;5lbizpV>r;JJ= zGrKbSZc*xG17J`)x~;NYd#cYvyuqEAd~m2!ro{$Q3nIdcwM7X(F35!ulr%rq zH8AATlnmJ!jpGGKPAIF(zaW5ge@My7m*k|H8;dPtxpUSy8NiwM=f%LiGEk#h;g!6W z$I%8~S|~bQJ%dFxA(b@SRk}F7en8p(Ib>~2m&mV>$oC`MGd1CC#yGfInKfC|D2I-x zKA*q7O5$W~;?9hzOB#k0S<2$%-L6|o-oF{WJ4T~p&YC$D<5n{~yLSzycCC&nPOA4l zML>4=Ytn2U)I;n6YtPs3*42DcgVE6&?n zCb~mXNk1&#ZIC743;l#7gjj#PPD)Cw%%dP{R#SGtOKGl2XBM~)qe3oOzn~to3kI0>%&W!Gp{NKJP=zIv*{2)@8&xcer zKx+CCw$%-v!1Xv~s+*G;*t7NP%goK*c5^Cv;=c(JS{;QdDO*|!EDzZIbUaZRy^r-j zOHW>ZnZrw9R9BS8Vr{qkr9tRbQ!u7v2m+m*LN9?KpGOdbXn7Y{Rs909xG-xpBd4O^^$?A0qyB)NY0z0f|&t}{ObxJI6%_`N$EU;?4}GPs&$)Yg69U- zH)Ox5SBVNLSfwaR0KV;IN^%n`S)Fjcj$y7~u9|^?rzYb$5$qU}{GL!d{S-XptR0r= zEK@XD-()li#ILfGDU@rz)S{J0zJ61{OZ*xB8fOPJ6{U0#Ny>UYyRX3$(c1@}pOr1% zkGDR=3&oG!o}9-+zvnq}E?c;OTW*f1^Z~h0Fog)YXH=3mH@BEYS?R%MXXx3ppZwX@ z*pBR>AWXTfEX_7o79ymLQ3Rd~?+nLv#4oXyklUa=EoDbt>Q(Y={BLS>I4p|Qj#qQi zn^)2^@=I|A48pB#!j%8ICA3!RoWduVW7he72V%&ykB0N^8H60~nmTTcPEalBpFi?P z7FS9$x4W2evfL;`k|!Y3nKVYQ2eu7V6I zZE0s#FEI_19fMr{n{PpmJ1%%%qFDP%8WITuBr1caa%aatcxXG}hErY65#>1Zsy(5V z{UKlN*`d;m#lal{g@m~Sf>&oYFdhi zMLk^?@~Al*{2VW)n63Pd{SpF6dRwP0Vq49BA%ONRj+KJ9jSRi|#IP4tDQ7%PA&-Z) zv6+AB8m>B=5E{5V$)ep6TLhvj(I}A3&jK_rxF^|Tc5i#Vs7sjx2cjZ zap8K8o2tazIlav}G#Z43(ccml&lhCSGg67A7%iWlso@^>2W{K(8pdT2nNBS#hf^?H zsy0**l26QzBwFy#xh%s^j3f%0YUhgY$0IAAyzld%y6b~*)^*?ipx~{^L_LF zruum9glrA^|AdMxNK!$aN^%hJr_j5sg+~RRf$OTO$$mKh!a3L?JuP#ZqD-otPw*`? zvyzF0k3o7T^d#}sNR#YoTS9E#KAgUxZ|HPtQpirjpitS_4!vcMS4X($Qv zozjL}73EKlZ=e4LhKO6*2RV-x>|4`?f#T2s?rvjFAv8@(ULlWj-Rw8W4UD4Dm%I4T zk-qNgiKIccxK;S#Bx|H4SX$LeYyux}u&(hg#T81kV|{_ynqf|?%vtgDwnEZ#EvkB% z4RFT6i)tAt$FTNDWva~uZmozHhO;$Evw^d48{yKHJ4jV+^>fHqw4k7&em_Ab6@)bg z+w>&i;0e`s+Q?rsz?3tT1B6@*Jh@g(K~}hyy4;EX%R>*1GS>GRJS<8NU)@K z->AIIV~}HI&Fz;HR{6$;M93G3Tp1t>tlxrMe*^nKERZYPmNsb_j|s+f3~>2x(RubS z!K*l?S4T^fBw^f}Ab|w^2lY6W!m8qb9E6P6{!Icp-8q`Rw}pvr?{6op>jK>1J6HIM zpc|WBzEwkez_a*5-gu3M{q}QWC!t1Gds@@3x^#@)zRe#3Ly#}Pm>8YxI}B%U|7P09 zTEWz9)9c0xVVAW!rhJ2y?c!wW@n!?A>~0tU@rflclnJnOwCZUUv8X9A#c&#p3rM;5aHOAeBAnOnt7L`~Dc$}q3QN9pT z*&wvt7pYBO`Rdr`L)Z73 z^^^P{92;*xJD(Gp=8Uuc7Y0h1;;AoY`aMxcIh&-`ZV#3IMZEU4A&~3o>0+Ue;D;dq z^*odd>`RadGASUe&VnIlO2sTR%$|)2dG7h|c9+-JraSVxaO5{LE8W*d(GK;IgN90L zQephfZZ*`A;LcJYsp)H*hn%UJve5R9Y+A@8v=bZ>2?7zMb&3tL=hPFCtOKlQqu2J& z#+f?)8S;Ow&(#XPq(xe;Rnln!N$p3NserVRzFsQII1|+Q?`Bi}z-sCksB|32ZLW@e zlYX6L+lb+Rt&syr0xCiGqkoyLgWTBH@hY6uc#bU7A4Ua8RW+*B=b%&5B8EmSkwd;9 z{3%kH=i7-$nEpWU!q@tO0_%uA$j{-(^-kNyl>KJPol_d|tPUJwkoYfj>_eEdX-lCA z;yR`-+cjlrZi|Ay9NbgglFGnyUu$QK>K6dvP0%AJSX>?`UmI^n)*6YJR;g$W#bvJ%pZ*Q7`l+6>hGr2#{eX08C zH+%y0Vdi$PN7;8=y)H;`l524Q3BP38lF~9Ql7_$%$2ajh4YF44pwden9n#uF<|P>n zn0*hjTyDnv72MoEfGMbs#moFRCZ|qc7KMrVQQ0z4U0bbXT*)W2Og!aGNb10S#ameY zT4MfV_Up9W)0XE&CU2-7@rs3_<@b{vSz+nw(zN_Y1}^`uY^05;bvQ+BmX|YLB-iWv zSZmLJimS5*v%WsLoL8ULd|@fe{Q@2SDOH-dNaY&JWOVr(Yl@7?5?o=~u?`R|SH?je(mv#?tRB!j{$s(Ng$RDyJtaAs#|Oj=v#b7K7=z zFevlXFgx;v+m0hXEp3o_Y}=CwXflI4wpp~>pFievkDog=eH(KFpMhEP(r=lr2*YM{%2`si6t&2w zXWx&b9so4==*;NrqoWp~7M#`kkiJQ{QruiB`EyZpEBhQY)`@>7xw(`PEl->rCDv+59`l+|2 zFPsCH)lxq`Xx77cyil!gS|wmpW&c=LK&Dw|d!xQ26w_;`_rFf3gOGrxY_ZZ5CV+=g z@-wKZ?r_YSoYMtb5cNP4uK?|p4 z_zdbau6*+zA0l^{;MX`ts~&uf-OS^HZyU%};w5?Q36Gk>gxO>$bjS?hvcw$g0_FWay|weQ5at&E++ZM|Avr%pPc$JM-sj zBDN^>^^nNwivUP0A$}vZrH}{lvcNE8eBqxuU6sZ~D9c<(J6=dT@*&AXsbDk1)$l*b z{cH^ykeLikKGovCpi*qhjsXP2iJFwoXxzKisf^&*4VIdF#x#`O>gGLd^eYs({hrYH z^qvElDU;preUvAAQd#OcTv^2m(y|FgewYdBO&fIBncYN*7y8AUOQ7IOTK>+UFoCpQ&ta30$v39v^i{aB2I+564?k zXSqLl8Ik%Iq%C6+b1K)zjefa0%51JF?=$9v!6*((a*sMWxG487er6Uo&#lQ%!~_lL zyQaa8#9!=8FB2=Sv($J~=glv;bvwOF8h53eYv0FZAMnufn0s1eRzK+99cb%RPkT{& z&OJcT8t=HrgBRJq!%kiqytE)qd8SWz@oxPsE_#LctoQjXZ|B*Iv2-7Sxet21QSR>bRz#=e%Z*IpE|;E?>6#LiN_LVf)*Asqh6e9>NbTGx*AmW9=aO z=1b1HwcFq?*%UCsZ&WtW995!LMEK-~PZj;_&z}|#DDlATU!}=J<=5BjFrMA?kYGrEL<82qDD<*OUoR2A-KkobJ!u z86__`?8~62L9vT(Q553YTINJvdV#$U2 zdV#!WUom(s^3~{Wn#xcoO0ik@)w0efe>3XfQ~W8<;XE{RxR+#|{1ind7mf2mBl&tw z(`PR8wQ$aCuJW6EDjGF=M}L*!pCj+rcijgnli>jy$x4&P2iN|i$60YkOCpI#ZFk8Y zD8AYEYGanqw^^A4k^Pvjx(w1#C_e@1ovi4veil1Quh*h~!^EmRIN%S^c21}Z;ok*`hfR!^@j&x_bfZ-`_iHpt5rxKq!3y&~_G zfA@1q*}0fNS{J73N*M3YVFFPt>GphD%bId#L8Wpd`8}49RW|Q>`D28bI;z{jX2oz^ zl49X&lI#v&<$9)<^@mRhs5e8Csf`64g5~52Nhv*1gIrO)pFmhVe>`jdDa&jSJLjHE zERax0%e=YSHvROax*Nf{H}eIY(5uX>b_E@GL*T06SVUH`dyJ8pR+%Xe2zu;HbgT|r zH9vZ;*ae};mu0BeLcXz4@a+_d=!XD#kgpu;&;~~aqxC>1zbI!;^YIg#&wBmk9QfRry0o?w<%LRmpcX z_mshyqQ~>6u#O+Ez7y$+jr3Y=9JB_4b1P016E{f1%a(-2DCReL2KyaCSqzgymUbb@ z>TM4LALMMn51En!^=cz>DGW-$>sQv}N5>?eKo1gE!bjMHzQ|c|$;vda5Zeh7*3Q^_ z_kag#*uYk#Rc3)-O5ueFSJLqON1WJiS6EXPsi%r+iL7@A9!+hMqJ3AEPY?R3X3YrU z|BO@c4jfbsszvAHf^g17cK@rg$FNfPeH)@L`0OOk%(cZ z;o>I0)TxUMELzz`Kd#KQEgaltXXt7uWBAjXTO{7aH&gTw2lv5uv@{A1X#M%|2(==pZXxE9GS&=>xL z{o^;dpGtQXsEiU4@8cij4XcgjEBH+DQm3bPT+pf}YUGGZ=vy~d{t|jcV?w4_7@jfJ z9v4SYz-fP?k7$t{9rno37sZVkp$!Q_ID8wk&r_IK_64+spU#6IEMz9f#D)y@8L=-$ zrdTC~rX#cd^#MmbJQZ+nzbys&8&KVn4JvVP?#?Aa_h*(5F+4MwBSZr;R1cx2$`+H@ zyja4Y0vgu#CZz7A-4+(N& zzD0h5d0WRM{HM^4mBw?C=%S79wC|Y#g^Z-82d<(Fqc3UHO61nBN|qfzjh*h_%6Ee! zHt~{_p76+avWjqiBm9Wp!L-ioY%l}yQhRCwZJ+u#&rm1EQawc9%jBJ=S4eWxCukmz zANd~sVrv4`P=h^s$36z94r#nNfKE}i^&qaj?Ut|`{r8%URXN%&ruN^bvjsIbJgLFB zUEqySBu7h+FtjJXw9=AAny(=IKYrs76g51~xRq=8o-fBv^eN&t-}>5*(D*ILV4sS9 zrSDB?gF||tduWvGRSC`Y&GjY8*H?yCoLig^+Y{Aa&(9R8-GFBNlWrySRuV6!*+wv3 zc_q2bK9l<`4Lo8p`oAuC*wnFATyq|408wIex$vI;2ZfuG1*wKMyRno|JkSQvMfMhV zpqea(q~Y)2L05{aXAS02_g3notJsC0YZv*|7T?NIY0uwxj{Vwy4gx&q8QE;J8SQ{r zDU!#=#iBn=ShRGvZTwziU3!}z>uHg@JL8nQ=CPY+ndq?26i}v|?|7bs&VR&%J>)`j zL_G9kvo@500?rCO8LqQFU-muL{{hlJ1b3`jf8u-SoFF5rbu@fRSbHPBinC5u#$-wA zFczm&ua;ViG2o1$-hM*$rEu*9uckLYb5s>d-%kY2S>aBT9K!A^`aQ2o{&C1aQnJd= zllZ)y@qejZ2Nf@icduI^w?Q>!z(bM;;6okAHWH&yt=P$wJR)32++f;xqDraU&pty;zIC-~m_rHzE6kj-GCL(|m=(9F{% zY2AMIeWnJyp5A)4v;2|r7in#bGc8SQ(0r}zB10Wa=(L{`}0>S z{al93>@=&}T>+%T(WkKHFWPuRyWX=o0@`dd393mUkBD(W08o2zpxp12(e) z=Bj#U%ie0;@J+egbPBM7FTY~qnLJKKeEkSv*?j3E zloCZ6d;caIi^=n(MQ$iSldIXe4E+mAJZefZ#uv{peK9yCYpjt&DS3*e_pdr$*$7+E z7g;M#0GPq-L;nJE>k@XI|E@6PI#jqKeRk(n>Euef_=DWB#g7p~4g?MpbFqAGvY1fW z6+}z@EUqs$a_c5a=zHIa;Fnw;EAXkHSpN34t2C~BOSo_PA zmDo5LU-4+BD!WHJ-R(^))HbxrN>Iyw?;JSZ$p4L#Btj#e$@5e0pNT)#Ad+ClyBN@3T$qLVRE#c^Z3&R8)> zO=ythtHqc@OqYq!?y_{W><6!rL!l!Hl&v!rUdcOfzqG2;*c=5SA{xFti%qxD_Hg-0 zBaCPAEbN?iF2>R_U^$1h_iMF9)m^M+Co7HbKj$sVzC}lbRv}B8pHqkp3^ZlVe-9-9 zc5$`S?GG<;*B5YiHziHmWIx7Dt>36)tu~)o92nlSLKi-RbF51%cH(-XPGu*u<^6b540DGstmF9XD z%9Dr^EtjX$r8YYQ&p5L=61*jPf6o$>iElp3P)Od8b{TMwV=tJZPE-3=S1+WQ_9B1{ zZKj%2uJv$P-&_T4W8Y>lI@ zNQDiRearx6 zssjt4bE$TI?*rO|oFl}TwMxreb4qsxcilCz-OmipsCLO0RiQ`=H+Fi}t}GTqS%owP zpj$uG8hfjP>xA0w-EG#GD6=6tK4WEv*_WBOA6Zn3Em;`P1W$5Ba+tokQ6(fXkrLXy z?;@#LW2#EbAQ`g#bRZ=YXz_&Qj9Bh3s5lL*cU& zIJqFW(t^%&z6tX(8HkW&roG6G{By!}J<-|q7O_4&y(mxHlYNzzBwNYaeXM2SRHOfc zx%Z4}a_icK!G@@apnyS&l+Xht6zNDOR0&PGKnNWS2uNouy%TBxVG9Wmn$kiM0j2jU zU3y1BdS{>8y`Sg2@B96D#`oilaZdg+GR9(NmTS#5=XE_T_!Ng75qSKkyW;fPPwGd) z=brLqCX%2{ZvLls6OniFNLI;ZTEo z!uNmy4Bd;f*$plo&D-1Nd|8tRlhfZ2-apx+57nM2CSl&OvO=inGRq!CaAr5oo&-*L zUD$+=Lyd`o=^`W~T7Uk1C}x~8O3@71fb0lDVh3Z4*%Kp#W}9EIGpK~QX{3agq#fEN zXrkVTyLh8)kD^UCBi$Gzh{7kGC=J6Aq?VFl8ZiEYy$$MxNMnBC<)POKt;2N{%fmL5 z6-{P>T^}V|FHY-SQu^w0l?)AKh)7Ql*_K{hJ{1XIwqA0x(spI|LrJh#X(Zzc9GJW7 zWMg4R0rik`YVpIcx3EWX!lN#itHF~aie_h2RN-FDlChjA8_$x9zR6JVhFnqfCQcytR%ZS&rKf-C%UOF-7!y;e_%VGJrk zAJL!uvxKm!?jK`9N*0H*mf6!18&)@QP8r4JBQeKmlUA>n&a>vzPuplWqjacazzuI? zy)WMQcjs7}s<-RfQ9yb-ipNEfVsF`Y`$wX?zpq_^W;bIMrMQbTC+)}YifVx&*@*o> z+iBq%N@jCgTJ(y=2=q7SD2}veR5dTY&lfKt9hA8AMHH4BVPe( zXL2i#(O^}4E6y>sfLk6TL$w%-+C zX@*lmUQw}d_}d=(DUE!Q)%H$3qKG9fFfq&gq#J%0?zY}DkbkFJ6MOmbmUbGNRwZJg zXLb@F{M9R85txnJ*q^w$X3k7oD!NStZhMd{OrS{DlnJ$Xk=t~YqwY==C`KuC=(~3- zHJlrgUC>6G{nZ6(up;D~D9(`Tc)x@KV%8Cb>mS~FOf~V^uPZ{6rBmOzZUKQK)?QQF zGU5L!-UD^y)0*GdL}}h7`fRYuB>Tn9NIWt<9CBr6-Ca?L&9s*g7DZu%Spea+b@9z4 zM{%n3mN7X~o3>fwB&8~nu&3(#^$It->i8173$f^ZOg&!A3@&tZ*ELCOa_mZ0=rUDD za3xqZ<<03WA;{(nv8VS17=FDyX=QUS+M34?LrP+Ps-DD6E4*>qHA+ob?6cvm$GK4Cq`8V*Ar(mZaU-O(Q@qm!PwM@Z^F?5%ye;GrFp)> zCRx8ZMVV+3pTt+aq5MLE;cB#N#p_+10ZX2BJDgjq!%$u$ZVn|Sel^xr(2Fg(!VX=X zFq-;Y2IsiKM;YNAyR$;48Ef?&%4@@-DWPbgI%IZPUC=u>Mwuv9+SdqS@3vyza|Y1@ z?Ja=9k5oIz)?6^WTIe~la>^A#F7Pq>1(16GZ+{LWK8!JEh;&XhbQJdXte0rUfj~Bfj*Qy=6kegpTc^kRTgr(vHY*UD>3!pY zk&gL{8?P%XbTd0!MS<-r&eO@6$}60tJm@$|?S5!2afhR_8Lek8EHJWf!r<~GVth%Q zb18DgU@zj;l<|NGI~7wMpl;L`l%?Lh{TE4y?sIP?`{y8xUu@3CY_mK^588y!;9#G_(sm_)VH(sefagLsM4uk}~yepzwQAEUxVFsoqnT$JCTu z=#ab{i+800#z;rNHjwgD#*5q5W6{T@!=fm~((*sdyC?!icI?SMn9s4r-`ATV#}tYa zA9$f5sSk*G*35`#1;letzOaY!A)Lpa`%xVftx|G}^R_v|4<)4w+*Nn~?l|CSUw z`+FD>_%hl0f5!l-HXCexVwWM>N85n~@0ElFKEE#absTea*H>HxL3(;px!(%e@0t_{ zLHubXDg@@Nq^JcXDpTBTjh!k(&s*3Vu4xsAtH?!;R;0;X&#6AWQFQhP4^obXo{5KzkH&ZmBKoC`Jga;vC+p(Q*>v>*Savi^IFD~bI#mDJ@wCkpv>v9C#;EJfgCIwTQ z&cxT}Gy48c+yY|0oEBOmaS3alL+7eX)TZdgf?^Fk(b;<`I}ZapVhZv!7ueoJB8Cw{ zV4m{udG3{{Q~dDzgt_9zbH;>=uO*Y?T~(PsYPTV))6(gqzEIwIh8=X+V3~=bjw#%k zJy~)XFMe25{gQ!<)w9n9m~=c+|BD1_D|UB=rux?S;xlITR2lWKAD5SxZ>n~gkcZAr zQRITG3a=9J4_>VS(zic1L|zl+Wa+D|zLqT$HyywrurWBn7l;n7mjP7q(C$Hswc9F7 zglmM1zev7QrT#@yAEvv&m(Vf&&PYG+L=%D%?cCE0(D1=XGh=W2&MR|8aCl-_6+VyqIf#OD3Y0L1A?k`Gl7v4J&kek*^O`8-6JI>52V%LoN} z^ynR}5c=WTy0J{zeoE9d8wsgnJ=nsKmf1ZnGby<^(RlL3g`OFQ#Q}?+va<-T&X*Q7 zR!_8W>gZH8h#MOq)3gtJ-oB(aXi`}d*Oj;pS?AGNYl%yJDf9p&BdKS2`(=rN9io@r z+`=-n@gA|Xp(jG@LUK1<4WV5#L4QVPJrnGkx|-@Oqgdn(%e1*H%^R5P$5#M5Bfm&r z)IKhg;V;Y0Hy2>)TzwYPsk7E=!oTRX@U2C*rLwg0jr@a6KpFc$btvoWBN-o}4^hf! zzslXz@&mU(!yCkfw5QF6NW6H~dZw}FgK;z;TYXgtFUHKlwP^ZXs`#0 z9Y`qYt_|r?NakQvvWJ4g^spLuV{V=cYX;BjeFo$DLLLVmBC{&xS;Fg%Cs|?KouKLH zjW2{m-uY(l>-(`19;1Qxe_RQe&pg@->Fcg`W3_T1tseY*N)>A%J@L8-dG;5{%p>5k z_J+#^HE1LxQFR3JuA(M}I2ME-<(^&3_3s-^h0b!W^9({pUilh7Gj|9WGN}H@xE&LF zD6DM$?$-8kWD|S$rFm6DbNZhZe^Bf?mpj9z`SaC(&IF@Kq^$#I=r1P%({>*@nJ??n zp^Fnh5o*XoO(_%k2IQ4#cT48WK9TQ@N07jHLYf}&#c~x4FYrDT2X-`U3U8^fS&-Om zEAiMR@T5K%9?&E_QuFnVlD~)9&Sq)XWY4OiuTvi&UKx8`5PoPMF}U<_(w|r;p|=>v zc1k#o-llXGAYGVpyi@Qwls$LT-tn@G-uGcp&35wE%L3}T%3;xaIQGOPH5nXx)SNb-hcp55@qk}6L|&1x!?hluNVe*wB6 znyti9XkQ?F(ScLk$d=ZTUCm80ctQ2zPKSoLY)lYc`4ZPDws(yeuZf>}b1qR*RW6Sy24lymQezDl? zy7~B`d6fzOF5U!cg80%1T^xEO@Opf80@*Xhp5Xps%30M{(cX2SQtFpex&d>d!l$4q z7uD!e96liQs(sQsECB2tkxE?kLg$}dD8#)92bHQXR~l+^smHxas9EQx6^YHu)w z(!@VC)%#qoVpwmB4rF=0vs|>dk!G{XsFH%*&I@f$7B`QzBQpm@J^gS?A{2?X3`YrP=$6)JO6LJd1gXZ zOG0brCv^KW8>PZ1(2}YSM0uM4B3XjWSBI=T>hl^*X ztdf8Zk4_n_kd^yNo-Mj_HGa8fy3T&!eKix@UQLA%NP36lXIYj&H_SNi2cd8}fdXZ( z9vqOTkXBE?s@Ssv#AhgzTkB}DEhrayTXJ^(VYhJAz=9+ro<2g$=jg2A3nNPWT68}9 zJ9m+rE{atdQEJjRFPoSjHb~kgPUJPDz;Nn1Ak6JK(Gyoje8lnvWiF3luVQV-yk@En|ZXYk3Dd`)vOrrAu(ymw)<4^GWf> zXnt!x8f~VM7P9?KmWnxHt>f~_OZ*Na=G!x6g4H#!V6%*xUO=8P@Lsp{amoI!;I7Z_ z5kGm&%d{&f@duGg321mMs zLIiud$^MV4I!ZdChuD@lj8f~>JpIwIU3pDWvWuUi$JJq?teAja zi=!PVm(}?ak$Y!{EWs*mN$vGB%bFIeb+y!uz@}>owpWypNAsFaQ}JCfx8=^FL%XS4 zOLn_ybj2*g{X_p+o>2`19MUa&qjL>R8dg`0by4cf5CaM&E@YFb%jlbU6M8pO|P zKBQ!5ChaJ@@zC?~$^vl*`}o^7wEI0r6`uPy_qXbKes?NE%w2Y0yTJ)X8+weh?;%@C zigR5^YN1AS!yM!3YcElKuWA~htlnks@4lCL)s0OmoACDzYEi(@?|qCE9NGDvC+Cmb zom?}$-?rD+*JuBH`_8ClV>F;pNa(ET)p!6|{0c?G^0n)L@RlMF-c~l_@7loPR026X zyqns_2w>MOKk@`M8*AO;kSFYw$lmd7<*ZU9^L>Y?RG3R|NYS10P0bUerjH#Nrv=3s zd9h;nTl7(qs=WFPO46i{y@$Zd{IR?Mofb`}8zr>Q(lKZxsg1tdCV|Me7SqBduc72k zd!!VQ-pZ1qS;&XZ?MYc7+)Ox&pqtM;(;6QxdrKQT**h{MP^k%Hx)&6ps8<=?-yPnL zWlbkCs93*8mFs4GlC8OBAFr$RCo#dqp|cG7b{$=D^l-nefX~fDd6Tf18R6ouM^}$r zIpNFv#F618UipL-QJ0kDbMI*JM;+=u2I_7)?9yQu9l`Iz)P%C}b562K?tJHMTr(JB zcCF$#R!nU=wKo-eLCy1HLCGemcE#h#W@D4mWAXZHLhTgXlQNCVU2^Mk0@HH ze5leW8kob(mUo$~-q7PEx_naLNB7QpUS|9dM-Ru#>*=eqiJmqVD~e7Vb&C4AOPCg> z{gA5VV&{5yMBDy>*DWNUUGjRj-47U=+Fm7jd$xs)oH4n>pJ>dVPn)BrzJQXP@RQC^ zEOm3=-{RnPJ}ET6xL@+){+Yv^{equ|p zC`#1Weou}K->7+S)auC)G&+=~UYNzT)d<3E@jmVDTlR&XPmc(mT?>ScUz0GfnC*I5 zb3~ZzYSH-^C;@JHi%n-1Cc@o_7@KC9W9*Y|H40GB`xc|A8`t8s!525;=6O(F$Y=5P z#b6b8@~aY{BJj@DU&PNJPdnJ%dtb{Kvrh=fZ>&)k*Pl9JJny!*lV?tu|wo0VM9%Sn*|>Rn!rrNFiN{h0YhygKjpW7<2bXD>KEf_V`EMiUzHYJ zTt7FJ0bO#D1lGECquPuYNWx`Vs!(HoV9%uxw$6JEy&)fUD54egk70#J@U z!9S0kNpIQ2MMY6~N;$SuY4$hPi(9O7l9?iG;kc4a&hC);Z3AG>kjFh~>jAQQCH?5a z%+*Q;p~)j$RF<&Tvdr5OtIitX@f+yrGW9tKn7!JZd%Q~PB8JZ{jP7aj5DOqpSl*cl zc=OpU-9|Av-M>v_!W`-xY4qUscwr3JkouZoQ@eF*=4W)fAh?A9Kt8z9-;mG0S*a5{ za{088*HPKnX4ffW-Emm)>N`SdqO(=YLyC-Y3q$#P=6j5ua;@Sa*L6oltN5W*A4&l< z*Rx0`usAmG)9O914{z`S;)4Q=I>mM2Dob}+t={l^1sACp>ZCZtB?(Ky)S{_b%2Ji) zgzmRm)<>bp)SDNt#QqRO|3xA-J1^G#plTpTk}>%=p3AzNqw@H!*QNes^GCXS2+Y|m-F}q8u)1xDqYV)U6n@yhS9<{R% zHv9`Gp6XmOD4ylzrK4z7?aunNso|qN#OKp|lkqtmtY*8WyK@~~MXv`0t?0;cT&E+~ zLjnqbeBCngdI5E#4OeKh!MdnM@K;uoA`vWIOV5pM%CFn*WX!J2!34Dz;nVDA;q5Dy zp)*#L<-O-%CG^6E9DwD#TTS2Dx9xI#(q#-w=4MYmY53_!*3P}FpUtKb!8$2I6YAvEcDrr^NQ_cmk$O*?kESXFcm5B`M z5p4THY~$E+W-2UrMH-f)0f0O8e}TJeUTtDu-S2c=hv702{uVz~8%l$B+~du6WCD$p zERhF4ol@XA_CteIpv}vi@-eMMGwAQ7MFFC(+JF!2KKbh)BDw%C8kuK3IH0QDPgJvT z4d@ASKG#C`dW!$3y>5(Y)=g6SLE!HYg8YCRkTu>^RGRK;{JsZ$esW)$*jJ)ulU`rx zxgI;&n4#5hP4qml+fd8{S-4c*8_n4f)sea%|3&~!6_hOnK3tgEmDNQX3;adG-VUCB zqSR$XXAo79)i?$HqO!7CfMpZ?_*g!2@{#B_3e38_?-7;?kf3i)D4y*ZOpvooU%!TQ za1a=fKiC<#`ypA!Wi_0rwc58+REqf1a0K4^VspZXL zVve+Je5;eF*ZGKc&Tl#O@N2VkRd6kVg!J&}&ZVpdS;e-ByGx;QVrABpUmlqixkx0J z+#W25P*%3Owm7{qcB9tC-y{^5@2>$-8EC|kUzd4Yg5~B3lhdJ9SVKGjgcJ;CM~?oa zmr>1*pV~deagdJ9KvX%#)rj_n{$A9|)*d`v4cUxKU4fnDj4JA$-G(~(=DRFr_^JM6 zyCOQg6d|-U=hcY6Vjz^Kd9~=3zCwtlwviQDXCTamt;F^SOER%XlumwTJ&^7>e`ac? z>a6O4R8;h@Q&*S@brIrWP)6d0`KRbi)Y$C4;qn)(B$u+(YWmq>?w!zF;WzTuFdx_I z_iH}rcFyU!R+gFw7o1uw)FEGFX(lC#w(5`AtRby2WkCSPHO~IGL0?feqUG z53TI~)6d(r`&HR$0_R(QkrbCbBL5!`+diZ2|E$zM{e2$NO&TuKJj5!J`)@^MfYr0{ z-r@{@Lx(e&S7G7~FiJlo;89^?(jZ|hgbsRng%Q!4d zPT$%n|4uGq?e<;GKQsA!o|fp}62lhrx-(0ZuV-V`m%Lot+uZ)Z&S1JoqQfl>y)dKg zrhbQMO6_xd$!%{!Vf*&b#JhJ98&jJDwlJ*W@Fa&JdkBhw?xnm^H?pq0@CG< zL@HI#)R}P7>-KPUj7;|4usLK3$!m9;wum@hXroYS_QD_`#`5a8eIzfr=t1k39A4%8 zWeNYA0=h!dYh=L>xf9+8yQaMGh2 zw1WiLl#nCDuXm>5b-qGyuYqFh+hl$ub#k2G51*|P(W(5Zdqlt6z*wbd;JDX$h#1fy z_whY*_=`l4)+_k+UYz^6ekX5f8a7@v0j#{90P&gWu$n*4ez;P5Jw;YiUq(9k6(44^ zG+SE-lzI{y_QjsMOe#Lfhs`g%e}4Z4)4je&?cT|~CpH@0@#XH9y~7{y71B=Ey_Pie z&xLqWHMv{F7C9SmK6V#mFo{dOuHkf4qRX@P_*8AhnC;;i@&6D9{}23$ba3wBr;||K zyXkD<&J(u=xdYyK^`P$xeJOQVE8WQNEQ=5JkQmM%93-U|H{qEc0$!dmCr7~Hi) z_dbj0dqyTVzj?Fm=X(Bxmgvu7OjlC+@DF>~{`O(ehsS)i%*I&)#Y-y{k;qs%U zx#OjtgA)<998$Jj3KYddVd|&LJEY|dN8rTF%*s8uE67tNHoJK*mV19}%|_R_gW&{o*zW$_{KNr!k)`ktw+OG5#SPwoPw! zIy;6sn2{#q6sw&JWOXWo2-@ZM}_#E^**@r^%+ zh3Y4-@jN4EzPj5d9*0a8m7*0JyQ6CSt2-ui_NFO^`5{*++$O1OF#tH1(uNi{(2bg6!^dw&D1oO}6LD&+lF zF*4fv7Tyx@cLIUhXpeS63^RBxtz;eDTyCKNozjgh-cMpDq5@y6o8l=VlaC?S%IWq73qLuD} zG$IBkjMn+Zl0fG-`{g*0SmQ$irSu1FD5@lYttGmnqhsG@o7BEkN@gK`N1WE#9D;Zh zwTh8yIWp8b*x(uJR@d>PRDc)|Z^^yaT~5DKHRQ@`e6DdX!8~hUh}C4x`PG zJVKpy!hc1q&!KtqSM;EV2rO35%I5Cp4c9y``*J)A4$-VGsnLtz+r(EG zYx|zHy4kl@mYb*pg*+0z)`66@5kKs$Ug`88+eog%Q(d&ZfL@PVaG`7~|G`Aln*23a z&99$OZmbTln!f}&8EILTJ4ck8IDMuL(^IrSKcp!2*JNhy{;@GHy{Zzu{{F73zoNw5 z2hEOq(VuqBDl4LxyF?B!;h$1_UTW1;n~Ky`K^(S#?cM%uW}PKzkUx3`jlZmL5YGNZ zDzexAKxghj@*a2bH|PZABL{dfpgZ>Y5K1nLF)4tbf)Xh0h45W)4!!&txECwBS%+=` z8f5GfM_E(cqa~eD9i{0>z1SN2`&lQxbbNk@Gpzjwl~s5?ISuRJDAX8MXmzEVkL!TIbH z7cdr0O&(I!QD2+)jDU`nmIf-k&QyqP=2D?O3fh4+N1JI|owP@>7@Gw93@m4RPuzVJ zS5s{eP-q;Z9O(U4K&&}<@h+tL_MoaxLh8&@&P)6GOkeV5eP>-K0)l)bw_7CPP&Og* z7>0YUiJ4W5aAQ>YpdL$5ItE2QqxFibxlh;e@pQ_l+5x4Qayt4ujxSk1A%D>qbvQk4 zw@B;pN}4p>VU^X1{f0ZtU>A`<+%u2(ofbY>(>NeT9E@YsWL8kVLZskd24sd=vt1!* z;RWGg<#HXaDBGj7Y4_QOLpx_QMR{d<%@~wAn+~&9gEH&QA)JyEamV-LVhg}%Eak(_z?)$yZgSzT8|7$gLyMc=FVJBHoH^>yj6 znjTKoetGN?s>VkpR56MXl${o)shQpZ@3go^0$cnL-?<(&e|f)Mh>umI6jVV4<4$ zI+_bk^;@jVk}WH-O84$jOo?$6(qV=tY))H=;3FeOe=XDj3&0*+h=yw@DP(s7SI4rd z_ac9b3*Wa7EwAy)$vU#Za9BmxWufIqlM;7jvu$e{H6b#a40JR8%R-mkH3xhh$&f9$P|D^f5)-7}M-WdlXZn1hu z79P$!9Y^J7WX$w_9Rb|>cr9yq>pB)KR^xDTHSnkmfN(rRxD7sn|2 zjCHiYzLK|3$z?^Tu?n5FN8;R1p7oRlU^a z3Jfa``AVO++Q^TDVB!G{)mji!bf_-Tea2~Ee_iYG1tMP$8R*$$8AZ`-DiFI;V{I@> z+=v2eao?EWiz;(mu&R$PI25w3UT(*NaRG&l2=!lVqyxLL()Vfl_|`YG#i^_X@OMGm z1)&!AtUkIk3_+AK6JtO_Lb}076e`d=Zj{+m5=iqU_|%;E zT=*sX74MZTruJV>I-hu=^ws^fFcde+WoFUgH*HiuV!@2mHXYtfpZUe`bUV<_Dn!}Ej*RC=~FM@B*iqNDb+bJRASN%rChrq{#kE5E~(>^t&RS6Os( z#9EcM3yVt!+BmzP5{!qxkGc&ujp2NeORBKn?3K|osKiC|66!_QbM^@TX~`5jG{L`hIZv(NI`*B zVaRkdelzyN!9SRd86rkB1y@$F{1cwPXa!QmR30_|@=m2my_LwF%#N8Tj`N+J!0;a56$EN(1{qiAl-v@Po_H8$jR+Cv<-@1eYZ<1wcqmQR1< zvD-6;3VOXsD~~wFGr<22WwwV~V$}wY9uCI+wFH$4LB=C;%c_$;D}95ZK6Y2Ii+3>6 ztfOIYY_I({Ap6LnYgA|*S7(RNMEbC@9zP6W>+lhJht5LdPd!9``;jzzUn(~{7MAS| zo{ngzPy`AuEk+$p4)7x=LLjzbJqQD?-i*{JjgXeTUM4GF-h7_}8dFqq$s3&k>~1Ih z7+k8vafftK1Xl(PB*PnBume%+|lA%Ie=zEbj}SbvmmZ zQ)Pwn{eJsLv z?CS9wvidH+!C6o%t?xhJtm~8gm;*{9ukJTETbItBUDDv5qA?U@E7}9T32|6{D_0P?-jp zrGNwv1gJywS#iM`h*$y7p1WeU+5pR2JlxdRv?7FY`uplIRqaBl6r8eBy49q?j%pg0 z*HALJo@8G0Z{XFcf5P}R6_%;HEU0p?UdAfgDt01g$Cd>uwX2erT`~;BZsjhVQtXX1 zMh~eBiydtm9B^Mw7b(paHy&FMY|_lU-Kyt(p&4D20akF6#09gbD3!y`G~DWEL&jdz zx;bosGiz45OgBZSj$mhG7Zk&AwPWB_CX0OCND=0R7f-}Q6zC?* zoRRH*DeQHB1Gb2%q}M{A)|Z6QgE5{2@EiVr0WuR4v@>4{pst+ihR{}40B>^l6P-Vc zs)x(!m3#v+Pou8hd)~(~&*uvL%4%vf%_E$uha;35(N-NruE562-Z26ZJ#-0sk?y=P^s$U?vh5{o|Qc>GMxG>q$Oda%I@u6(6fk<3`-!IJ+VIJ+gh zeaPAA-Wz$&Znc}0aLy#94=t7j00hew5&{J6`ThZFpZ)=A@_N64n$zVllixvmve@+) z-v`5eR_vk|*-lj#6m|Y)fCN&!8|>&#HRLxaTUu9> zONrs}R#vuv1g+P^wq+Gbl_n<;Q+c0#Sf$1tP+ffevU}sUrRBS!*`3`#KMSrt6J!D0Q;J?6BEJ#!uLme5@KH`0;RwmtlVW%kw9YSmBl1VpxTe z%B7$9M0;dqHX^zkW&Y+fWAyOrEOCtH0))Evn+KKOq15+ema&Lc3lEpnoRJCa?6DcBDFxpbT)it6RC0ypRI&*beC z#^+Cs1a68u>zf$7LM(Y3+|S&wE-KfCA7$4#albU}JjVn44=o4~QzVd_mlR8_zr zu5&!yloJ1Sb;SWWFsaB9%sx~^9;!0lF=H6GaJ8UIA1)N%lUap@{W%JEGr?C2n~cA^ zA7U)$5bH_hlu;*=>!MJGNy;_f&aoO;;prReq=`Fq=kF-EdU3@W@(tH3pf@`)=XlIg z{bo1+cP&2Pe#fSkK%-pHU)L1}w4HGMzeru?tV`$^jjK8nHlLfQLbPHR%)A5b&klJs z%UP>!z%*Oj9T7%}>N|bB@ac$ zBTIt4#6q@{H}&D4_4gm2v;GE{8kn`SU_^cjpa4o2s4rNJw`eYW)#}YyT$F^GBedsqP$&qk5l}@EAw5} zhp&oP!k2&K4O7~~=E}IueQ#{VH_Wy;7iP4JyESx0+Pree#OE6{q^)h`3PfDwU13?0 zaNvzK*EHwYv?~D?S;MHlv)g`7%Z5O>>!tO+8H(ut++EGb9}OVQQ0A8lpPyOl?#Ni> z6RMmtFe5FVY_raXw6-nD=3r}B(r&kH(P+#G`=r;m>1(zNw_|zZ=;JbV@q$yB;F=$< zx`^aiUz$p@z7h7Kupr^TM;6^$#?Bsatm1Vtm4HIPy8}OUh=U+=Kl4 zRrx3pCJ}9qhdY}lI)`UL20yItG<1%8Z>SyFhz`{m;OMNNKNDVfGf7^{Gc}N=hZg0R zC{0<-88qkP=D1+`kXJFXjJE?!5kse+ju<|PuiSb5U;}$Z{UHfQ(EJ3>HApV~-UO_n zlhYVLSLH2I!66>R4}U}@&f7xkdK?5YJHQX{Drjz}UhsGfYnqyHp>EqOlD=nncf4u_ zP_upybKTbci-en`_(YvI5LyLjzeC&^)KovOj#|s~lXN=Xe@9W;gp5D1r z(pr&bA~qDmtIppq;(u-Q7=ltAc2Z?~m-7wmFg{++zKKe8Kax`q8pJO<&(f zf`3{G?dW`}6-!S0+7H;H2TcXhwXmc_9nm;5x`HYhnxD2P8Y6boEL|dcs1ld(_%u99 z!DD_Ur6g1cM2H^NZqM9vZb-V|7{vRK6jL8p2u9FMP;(<$QZNq2RcngkYK0S?L<+f} zu6IfE`}pe{C`cPPbACVNQ09Be__XMeiDTq01zg*G*3z_=dWF|CO0=8W_g|Zl@>iAE;`dH%c7r1-L&owAwmGDTApdmD zc8zp+LC+Z#ZI6#QwYsW^IO7ug=MA|8l3yfDKU**xF(8u@p6#1Zm~r0x!zk=rpF{Os=J6GHAUN`#C@0?mhw6kURjNeO#mUt93&008B5MH zF$w#nrqRARIAd$>uJxo*s}f7HOL{7O5vjvjG?BeNdbFGsWF16lVBN3-D({Y^^4Vwa zA&aN1Hby7Es+*iL{Gy1o-r)vbY2@gW0)mw)fJ1!ma5I4uI<{HB8xC>_lq7&X72`J~ z(qngrchv55ctdXert2NbIbef;NKQx(hqWY1Q{wSObC`*^YHOJ;pDdfv?gbo(WQPPq z9>NU=a|o>@ZYgX2KF9?OCIozqlK9+X5oVLm06SQNX9al&?R$qA!8p@RPyz4kVdKZF zLNHb~Az3sae-dASz$7AaW#IfPsEIY}Ad*7|p>0k=3L{$f!Jj>T5|fjL>IDdzUpjV8 zek7;z4;CUIcr~3WW?@b0z!ZP7$nSvYCy9i{O^B- zl9-NOepNm>ZTN*-NRa7;w0Z0vyYe2tsLJ|iBFhrVRkm^bs{>!53yGQYih*_#(v2Rk zEVf-EbT44ieubS;GaEAjQDXlb4ok8}dYY7;q=*p`+Gl0j4CAg$&-~jZaG<|k;-^yl z#(%j439}Z9bMerEUI-n5s}d<|;_Om{$8kHzx~ZeC&XHA=Az@kh&pj&tw@cjmmrDR9 z#U{jEWdru)Kp@{}vN=lSzpaX|vDr|Cr(Jl5rHy3{17iXu944eoSNFqv_LVA_R&VKW z7AykhJQMAI3T+~*fM&mrp0F9a`C0R(5b46zpQD-fX8i9}4ZkSmGKb5jLa#&5nKmZI7tT=B1T#Xw5L_w$hUu$fo%Oynz>*fCE4%#?>GZI zd2Nrs9H}iz?78TI#~-tbfT*aj+3)XBHi2%3ag&Si3w6SMutcOHw28!5gjS(*!#>O) zJMtMyVZLp2sF$BbRmTStr3{#H*tw(?VS_;J(SHjyC+}4EA6I|f zko%eh-w^BH-}K$>S70C^D}v7cwrM+HQ*t3@fF_Y=-J|Ng#dWHLpkvbgV1fhtdk#GF zdn%_MpW3_XcK_rqO;y-qCX%b)YcOUix;it)0o-y}l3%3zmE2YTwyE_&UZ#f`ghl+%{A2pm9gvYTif1^@0v7PQV-=X+G)}a%7 zX{PUpHym8?K0TF|r5fAwqJw|oQ!{n0)dXAg)B%v*|KPopQQ+5GfhU1~k)VSL$1iCD zE~0tE^* zXpsbh7A;PTCs=`^L0SmzP@p(%(ISE1UfeB&07Z)i*Wyy#p}6zxJpcFI`0Rn^!KhDdH&69sM};$cg4)k$Gp_~ayNE5iI?L> zSz|}-!4-S7`P$q|#m}n+tcCvpD3~MQ&(eaq^=3a<<<=E&+-H0cJKzD%Wf@$kAdR39 z-<|>g(NcJi_fu$(ZkZPPeRlx^ohGahAnb^>`u0$WYSYuLKh2u%AFkbgbBpDuG?*Pn z$){iP)^xde!@?jHZuTF|%;RVxxM>Om8O88Du}```WNE}wAC)zN^5nZxFok#O*~Lwg)ILju;v~NWg+5_C3ty(Z5D0#e6SR^~!<|d^WGJ9&P>bC>viZiW^+mzi!^GzeTs(vPe3j#`-!mvWrU-Mrz6K zO4i8be*g%_{QrHjyT|`IrbkEt?v1v4H~glv{m%KTS~bh*@$jdU+Bl$1W%{v@$7}9k z%|#;9StsBm&RBy*{8C^s=l1b1F-@58&t7rYb+YwJZA>6UlU8*Y|K2B9zv^cgN?d!f z1=@j`eJtn#k_v8HsC~&-lU@jB_fMWk=yCR~r2kCipQ!C}igcC&np`~J`HGTgUezNs zY8d5LP`^p0m~MUk{UWkGc_b-n__(y%Gv^lHUwd#!c&^7Xndw+DAFhCGz+uL+$UkBv z&t@}KaGH?0JZoukavxu7*QVP=LjNZZyJ_2Gq7MX=t;zW`MRFLyx%to?=_bI!qHbxV zpbbqx|X2v|2C%p_L ztwjyLAatNuqlR;fxRVb~Mb(C|V1Ko9F}(FwTb}ipJhZ1lei#`25Ld=7Q!JU!ic#W& zUT*XSJOT&_?7cBuapy)YwrDo0#Tdqo?hm2G?Rse~x`xep<)~+}^g~rW>UEsCyzd(V z$lRIxmuD15SeBx9$z2%n3d8GV{%;GGX2EMLfXp4uP4+I`E*gr`I{#NjSChoq;#v8-d=?rPJ<&eaUUh4>Z%t2PKgH| z9h2Fo+RwF4N%Wx7myh+m+sTj?8)gT*&x-c$-`ZTLu_1=%FoghRpnq zgR?S4E4LJ?cU9{&(QJ|3<1^tnWUUB(@$rWWZvEv0q|Zu&rcicyScDF(&gAFu zrHCx~USr0Gm@NDxwebZFeH#HS|r$-dz-loEEjHjtNa zIqrFnkvoiSw&30xuW5W-Z*s_@3-!p_wCj4Flh6|0`D*f=4*UETg(sy-ky6eS+szCC z+qv)HK?B{47Gg+M4+?{p3Mh>ucNqf*lNuk`x!zF~e7c10l@H9BVX-|sq-)?IVo#HN z&z7XjY9==uEMkCnwi3f|v90lXT5~ftYEnzpqGr#kdlwD$HOC@TWiH zN=4^!;d35>dOfKpf@JGK|38~gzn1CM@PI!YQi+)6b+@701**r~Jj;CiNk zb7+a~iZ(xEc9z&a#4cZd7+vjkPLO9+>OtBAQmJz(3OafZ-j&A`S%=vcR}OR zKAcMG!){?LxzVVMAwV!`_^CO4*u#q%!pP(sGyF$ zcq-(d4{2H0kdbLCz7Hlu3?f`qU@OcXMIu6ri}B#R8(T9bKNTa}XtPHx>E5?dr5q_R>&(~@KEo2og8wwP`lKO% z8IzdoaYWpxd3IlTTenmDwilGa$)t`s*-`o1)2fo90!@Cz>k)hx6O+BrC0*_hs1)bv z)iq}h6x8$6F67tPinRd~8va|mhW-!rdfcloz^+y{%H5R@WYScyR-41#LB=GAxX*cZ zlq07ixPU1jri_>QzfCpOe{!VoGQODSfJqX4VN*X5T zH9+h4nk>$cJ_#DXVhrIpb>`y8htCIU;x`C@kPe_HFexhaoFv9cnUx`f1XPAs6?msg zhoX#Pvd=c&zPa;eZMGX^e4@PwyByzASturhUha-5W4+DSPM zV)n!}P-NQ95!qn)!!ki$!sN@c5{{o`Ur8x51s`$`2lhj0C7~V(*I^)}&bfdlK z#=mpu9d1DbCu6fw{V_W-A$^{TxBho`bIA;)kwf9(9YrPU^is%BUZWGfNPQ*`aI*#T zrH|;pMWqPv8gSxKiP|>H;p%{Z{xb7&|9$v!Syu#q&I9>D+ib~l;c1yr>eEUCAj_9n zI|f#dL4;@dzxS$q;sQ@GTbw`Ir;qQW!I9-Mmj)TZ#?u@S3bQsX_j3p9s_xXc*>Tud zjg56bJr-!TVA_;OXqGMo04h?MdnVl&LVQ(m928)SQK=F60E-=4MiIv|B^ZalIrlm;|Hm8KiijI5ktBblCYsP3$u*p_Mk#r;YGVg z`tQw7Ns-S8Y%K7DQe$Yn(H!4*{VWfbW(%J3(b9cmQY~Y3uJz}rk@wkr*9t9wRN*Hm zCtIehPDv#r=X9U3(rR+qMp7!AbLwjR$eNy~t&iWcmX{{H z9J!hh=b5lou74Y@4ZaYOyO9YD4pe0@guYjs*A=BeyG`G}V>92GNvl0+JF-ZFh{*WE^noBn2~^0 zzm`wTI3L+!E}!OjWVP+h(w45b001A^rN{bvKq9?F-$V@41xp%}H9i2OZ1ioFr*9b1I5 zE1MFMb3Eqa>$J5GQ;DU--Hs#1$rp8v-3=KSXofzQa4(&*T^a%Q1GpJiGv z8OP-Kw(pk(`tSXm{AuP;YRWP61qn$fc+9X0GjB=ga z8cy@Bhj#J`jiec-dSbqsA-3eh*Z2)0IquRTWkaBaQUfkiA?n42f)24K4yb&M?T6 zK;6UZE?TP*W(_5y9F7?@ZN>+O0S_fSt>WiWqngERd-f7j=Vm&rDSRh1q}*wa@i9Mm zO#jR)048gWkcH!q83@d3698SDJ1W9%HjorGme@_cG$2)r%yqvOQ$p0vpWf7+vlMl* z9I=zQBeMK&(^JDPb!GUKZ~Sj6^sMcO!tBkO@IL8DOk7U_N|PAcwZ(h{t=gOz9C|QH zw3xW}kq0qVvikeYCA*mwcUcZYgN3O#L@Rnqimzy@t1?JWkll%O*lbImjKZhikL54p z@~5L0$d9DhDLts(%Luuu-R8t?;S|caP{*4FLNv4FVrGZyE3}5|i0>i6-Gc>Eb@Qo+ zemlFiurGuxmfkUQ3j2(Gng_EU*X^J2lWb1%&WTjH1z8Zo!;wT&Zrr=0er&#wB8V+y z%*SZ)8&Wogyn{T(Ou-}3DmMG|?Au&4_rkbj3-df;dD7c2Nv1&gcRg?nWaBC~$Kp8| z74u8?CWwF)l-uB@sZwFj5=vjhv?oK}$>}~nn5k%%Kt-pnA-kku9wRx21?^E8{6vxz zxlcVWCZDlV~%^LcH)?N>5#w=kWN?Q7XJ5#@RrtZCu0^(>}S!Wxxz~ zHiqsDVXmsrUYumF&E~(T#=toRzQr~ciG}hh8Jj50;%OaEr~<`^yK}{{s@|d8iihrV z3b_m>=YYtfTI1)qW;VIb@)f1Z@ab3;8hI2ykK5obfV`ZG2!&?5a^_wo4uvS z(hoX%MG@jQYwWMPt`ic5H)b+DjW}y0B$WExwam$G?uufJVNmiLGWkwU~wXPANMt5LOz7iz01< zVq+pivp@`Q-G_ZzM0g&KYjTyAZE_;G<#f=f#w0&YypiYRG{immrCiC%%!VUShBP_K zO2(3lOi|^Q`e0M{sgid+lLoU+?JsOB=cTrJ%zlW|Rvydn8%u)Py23N48c$0|j=l4IMEL@bt2#yXngfqfrhllehA@MJ2NKd%{=XZnl~O2|)RC z;cEeNGnKd=(X|xE8IRWek#he85Av@zl|LWP2va)1Wb249#tOsiXCX+iO2F;gv|To( zqX{1S=O$aw^j^=2S_4(%x(wvsIj^CYd75jZc7;!D$1J%s486krrNuKBZ+0B0?Wcoa z>(~GfssrJ3m1|XS`^r^h{_vVP7&N_ zKa2Nkg&Y4Fy*0lZs&i*)U$uM;K73jO59!1mK*Fj@^i}L@vo<%Ogr*(&8%5u)RQ>_<$Vif0vuB*+WhAdC_#c%O zV{pJQFJ8w#gI5oFfA6oG zh<^}lo8<~h+*Sv2Vk}O4ZUe*yC+W}{6zWm=puNetj7b!G?U(a8o4<%2WnCjRm>>R&74<%YV|9=5gd z+E$x-Io<3h$Gj4&)R@1xcIzVu&jk_7(8LIz6ei@p%b?Q^7#+v63?wTtPsT-Lt2QCq ztv?^;Q&%T}fLe9qd;!r|G}j43i*1!JXI)!?>9l_1^Qa4!ksfWMkFGXwo(9LEMObn! znARc(0;&Q>S@T^3^kx^33+0RJJKKC0qmYqdNI}m|Ad5~314U&YPf|&tO+Q{jnKh3| zJCkaGr%XC)ExMA9(v3#%gz#`i`55~LUUTGXi5D%b$`%2OM5}l2+3nX%-?cMsJC`t$ z?YJNRZdqvWQ$qCc{<}yKn~3#4Kq@qj`TfJx&G3T^*MxQ$Z8==z9{|~3L=~}2^!2z} zzmmDtiIm@una_ivJd1jX)Oor?OvlyY9aJGz4caRrw`P=0FK zn7~Y_07|)Ux@FU%&&yx+{e(i8_DuBGGS2PGZWqfBiHZLK1a0%|NZiWa!DB)hzMUBB z-kSb>nBzVhe&z70N~SbJ1JA}b8T~ARPI5r4RN3Zm%jN?WG{Yp4&KR}ia{j6TPj`6I zof61;rqp0#F-$tn$5Njk*~D?Jw-2Cu&JR=VpC^5Podmt1z-O&QNHP4@n3+xW{_gpw zePc>EAQ|aL+$NP|D#d_0yf4`sk=qRuz$;{6+;hE4VC2)pIGV(cAlZZ0;JF+ww(v## zX?YmJ=cT}Jao(_%zqU`vntbg7%zxq;3<4D@{YxEJeGFbl=8{({}{WfN`Pe6LM(yY1KyFQ4MVZ)RwDc%8nTv$RW4EX8STviA5DV6*uae#ALjlo?kQ zb&Al}Proe8NpUGo5v)TGQ;r*@XNMd-{MOrn;9C|d>nU)IS>?N$vwzvwxN_(1UxgDs zhF#|C5XZ4u9e$A&gCOO$_b_=gQPpnAIrbB#;hW{=znZ{P(*@yeZpP|Da3BOMTh_68 zK;y~TO7c<9hAj&oemRQHJ_)ve%|j zGr@d)+h;K#AMXWFrgR!2i-f2oQ4a3X{+6OO!ygH=)oU6`3fNEzGJp6WS+b=(<7MwWT$yFEC-Gf@_^^MJH*X8blEhpq(6boX zb#n5CXR2H1dAYFj3q74XdLD31vP*6BZ?MQr?zkq6>?O@>l0FH_kcVt{-ma9fH!g2f zA`BtlWCN+ySBrgcjzm9Zo!Hch!bAMM{gX)-7r3<;^-xP*B3-A*@`e2T;_CpuC8C<= zfu1>i;SX{6>WvUaA4Mg`?y@Jcbn<~NzE2cPI7>dX@}I80voifURUy$xZwGTXnjl5R z;H0`l|9tu=M_47>H-#5s=6yfTRDf?czYNkDo}PPLZ1IB>0En%if8Nb+eGfiXBqFcT ze}BA`9(Pawu503Q6|eGlGr`awt8zN9{)gzvvtLfosq{Dfa(X{IOFSd~d@l*- z{W|(XY++UHdzZ-E3$xW?i%OtBAn^b%Bd;@C#b^42h3$+aAE}R(U6OLezUJ6rk@YjO zc_Q??JQUDLFzr-MH*@%OO1)4e%UM)(VvW9@#7KD=o-Xc2%{|tgnv)#8ntlUtY>~+9 zGALB;axkCE;8q;sa?0K^@A}n8xha}>|Z4RtOL_o)|L@+7_ga~kD zu=5}Dk2{Ja>aN&vy-Jbm6fQ|33w=CwM*0RoX!G<>YBpEb@~n0lue_g+g!S+#X{VA3 zD?@#P&g+~NdA&>@$rOSTf-$ExD$}$DUueEik6L`bR4Tp(f{swN@mI*=W#ylm55@wM z$?-1>O+e>=DXn4yQyLqTHVa-{=899C%eD#K*)|>IDsNWB-g!Z=$(YN_IIeS&qW3u`aiI<(4U9kJD*|as5!x z5kDT?XAzBmStikLHU?@IO7tE#k~gB0L8;Kpj+ZwY=JIz}?ge)?sC(gF<-&3`@6EcR zsMa_P`>Z_33DGV4kBk1yh&-4Qxt`j=d=U9S!|9eKcQOXU`A80f5YwWKLMG6@&&+Hc zyce%2Il`S1C)63?uSj14;v9`gx~s%JQodKqvy~;~{`>g}C;&67pZF?^H(mMrS;2fi zsYblG!e{T2RP^r;t83WB#=RUjw8$C;thFd!N4M)-`)Sepj3f#fx%8^Vm!`Kn%T+P) zd?slj=Q0j1!FEQ3$x~5H%~=enPAufZNuN&k2J>$0ZI|XIQ{Y?7UxJx~44PSInj`8Q zO_qW}5Ko_k8}CuKfvZE;$Wqr&p$KR4F(l{NB%T4s)Wp87YQiCUM6V~5cCCC2s$U>U zGUIw$Z>1ErGn{;+E!%WS(ErzLh1MNaRANVeXo4xvX%1>%Si1YHp_iY!A%;49c9L{b zY0l^)9@Xue;pqQ4J*XZuz_HD3B*Z9Q%7ti3^I5X%UY&NNG- zfzjTL0ELEMy_zmXA+F>$nok#bCVcvE7@?6`a~g3@y+U1KXX4ixE8Ez!QsQqN_8=O6Ftr1WYQk9sRNT& z^aO=GN?OTl7#PWLzomrlx^DXW81>A@QKjC6Pd{SKDiPuwjE=QShqUdGPRi?>t#X}YP1F}OQ z5~-)%s%UkPqN~ErHi+~j-;?>4xp|e-$#UExh-QCFf-O_l5|ubm!iI zcNSJi!DM#oK~6zzg6HLbf3yonBc_ioU6tHaA_;F)!9%vdPl$=hwSNku_%-VkHeB)CGfVzhZHC1MzZkk7fQ zIij=pMrbRDL_94V?>-TYkulGj#>5=+eD3UU2|rxmtNf;boRD^ktH&$uJ-*pSuw?K5 z{y{N4LyRr$Rilgg1#X`hiKT9I-<(xCr4A8ppPi^RZ?t zLzL04QtuPq&URn7&9lknfF%cY#V){!kH5!zGI`nRu!0UQx~qX;xe=JhWB!kkGeL2+uqn1%F@k{q?T#c~f|S3^Fmj*d97Fu!e_`MK8HT$gYi4Es z_|%;=EivH#efPLg_Wxf<&lx_rpXbW{e@3T~cpPV+moA*dGk@r?p6UZfyaA9G{@3F? zoPn{320|pDu#i6F!YN)Cb3^qxwd((e8S{?%*|l^#q; zbexnhXwq^3lBbD3NI4tf6=ri|qKr|k8MovyZk8@EcZ=HNgJ^Qtq?CnMUGk8Z=iv9%HVsyHk zlABAA`qX0f7Mt{VF-3?@%GPR7kVD6Z&7sQoEzZTlq%KNHX)EHk7djpcmNoZe;+OJ| z+4>ycvG=;FX9tSw=bI7%(uo~~v{*URNwGC{CTCVACvd=-U~rc0N>6v-3nb@iVw{Fe zAsE|^NJ=8Dsk&BpjK#-h+m(V21d>Q%g=$C?rDOd*+CJ1uT|c|1>kEP7(hNxqvpTb;C)4k$fn07Zob9E9vs(}dxnI~iuLqmC48@q zH#4nqa#&N;h>|05|AFL6hB4g|fi zC!e9Z{CQAfy`&-tj<&>mp;ui=F@UzRu?p}#JnPV zKkwAPCgaPGB_db*G1TLG=0*fkdiIhSqL-r-wj zUY8k+CUpwWJ5vArMrdJpKlFKEgypB)o$S@Vf@4W;ABT4UPxTKzUeUpUt|N38fJ)a?B8+J3Y-Z--0v&J^UNkcp~D^qS#;8#g_(?g|ba z?~Y)WwquZ|7>?uZ;$Y@y`iQ~9JkSo+9%ix!k@Bs@1+Cm-N< zR{Qq;P7Nq!#;yFs9CH+4^)HB%XOgRwV0BuDB{Zj2Y#WYI3(zF*Q|4Hq>Vob^8sUxY za0b}NmFWL&JOt=YJXzF!wOGFfN=|)QtmjI+=PqWU`LUi-B}U1tJ^6Wz&8*+&us07! z!(P*B{62{_w>aXR?p?XgGJ2`od!$kH^{tS~r?btA$d_sjf*qC2+UaKL$6eXT{AV+P zn1+~hJSCcxm^s0~#BJ3~g>5=sQGo3CalQA$(g7=1m)M%9!Kehz89ohz&0X~I4(qK5 zwv~UU)kw0F(U{_!Ou9kV$*>#q$+Ld|%%)DlN2o~BWKNS;=ubms?P$rHmqKdf0!iohQ_-Yb!huDPr`1cy^%D6nhZLQ(dRj&k2s9fm`eek8`wy#g{UIv(HIweNx>+u(q{wH!%cbYqNn- zYvBskw=f2!hZrkr-t8b~ZIxgdPcGUKyWsHHoKguxoKqpR;26a(^@XJR)s~XAReM7F z2;#0!(%NgixUc35u-Ef2!uwgnmQBCT0?iYI5eW-f9z?>2p4v7F+BlaYt9I5xyHdz` z67bnM0Y`?EMQ7x5&8=%Mw`^d;9Wx zM~na|DX_X~_jJb*NOTe;<9w4_ymnlZFrMpGb4dMzU}oOgSKU3l=Iuv8ZfzmdfA{_j zvEmuA>ZaU7Ix0%8Wn`f$$?n_RvraGX9$zJ10{~={T=?#h=Uu;<_}Wy+uodL+)GxB# z6CmonAY9*%sJOWfklcm{{1}N$?-X~OZCxj+6v1dT1oum@qNi+DME(%W&p8k1xv)PC zt%_c2b?HY8MW%7=o=2G5q%W*#FiUwsxa(=dQ#8m&%qn~Q2_;!YEJ#f%>FOUuVBaY! zXu|oJuH1xY>)Elrc3K}jSQb!OO#Iv(Gdt8T37D5>2a}e6bLwaf+7*=K=Mo-XZ6DCi zfh}B>V(X$NaNu29LF!b2eIKL7U}1o$SKr#@KG^!!yQx^{($fHHvvui4=j^dB4hxkt z8C3V==-IzDVFv&ww9$LE8EGFj>p`p3)e6OL_{wlGOkzaLn_rChdSZ=^V zMTdzU0cP5&zUWr*$?qFct=;V$e-L8V-;!P6m!X33Zfwph0mrpp@#w&i2!DY4WH6Um zZG@-|gf%zOO1&h?a>3=Q>kdFDNpR;HwWU&8m9sPTc*_Z)KZP_z~CsR>KDh6t2=edKe%y#$s1x<(0E>q#L+S;gH8yZqkynDdam zPx%(gp6>%)#SbHFq(T$_0_Y@(Qs)=RGNO@Cw!NnGz@&UH#?3T~iHp`{9;Vo&$KmoS zo1)`gY0MUe4(-(fe)-Z%2=Y#P_?nDZ&i6UJx$BjM#4XK_CqPySTL-ToD ztIWfBxwy32#*?=UU&%Usz#vW7iB|tt`hd;o!g~=8#-EXI0E&rSylcAs{DQ8OkF06L zHr{4?-ZFo0s7`RVVe0G{}IeU!rQ^)pEjOR0#jg-^n$|I`8i;GXEfv6|?k zv$6&0HsMh(&lzr7KZ~@1;B1}45=y!0So0)K#^p-!bKx12i~B*m&KF-&BW_Bo=P@n`+&Tu2u67xHP7*pPD z!ol9yviy0yQtR`ih&9sWxkXLG1Y|eczG!+N5MK!W0OER)74cwU;(#A-$O!3V^><|60Qd{-KpN8u73IbW z?4qG|#qiVRz;2bVYWI=; z=|=>)#BA~;n83H-PLpW^4z$~LMNS+mL|XrtL$N;&f<2Gg%#&X+3A z`NxhdL5jwv{QP)e_w=1wvniD_J?na!I`DN|e0XoA?_INiLwdQuYS2$$z^Jp}8pvvk zc__9)*{NSuXiRKN(=Nyy$T~&CjoYmx@KF8adSSD1V@L1rZtpy<-w=_~>;SVsPhsLf z)N0V16lyQ;>Ae|{{iOlwI%g_6x1BYo-qVeCiP{Na9yFfC<3ZWgO`5b3a`u;iol0Uo zAWL1hYRq{2(CZ&SV#Myw>da)bs8^AjQm2V_dH$VAIad%x%8Rn?vGHNuGWOqNST|TbrMGh9A~S?$`fyqHAt##J zKj2+=BV^W6Unsk#y1c{8dy{Xw{Y9_Jn(|ZiBYrce7yF#Dz|yVz*|(Wn!agiiRiwvv z+noTZ22F(M3qP(>j*JEwlR^C#%7_KZuqS?$FgUM`)k!m&( z13dg1^XvOJ6YU+kg;V=J?A$m%ogXmE z(^TQi$q7YE*XK7+-+A0p8MZZ`cAZ4r7#g$0rBX`5(qDR$$GJzPU}a-{O`DuRXH7k= zp}e%I%5w6TR*lvfM5G2;bp(}G$;IYElIpnw;+vR>Lmkg&L}Ft5x=r9R@dwz%$~k@w zQRLX!j9djN1N(^V^1ypHK@*A0kYc57nYnIxuN}V+)uYa(W1+U1P~OliY6fAp;rAiJBPjn)=cbAF zPy*JV5UsI_Uf1+Gi`@6GnhvFPl_H7*Q5;^!B_kTjVu8gqALvf#g~sKS?BFRfKm3EE zpk|XwczBD~cboW$N-fmnub^f=aeRO!MdMD0+IwAXo-mDBJfxEUwfr=pGA}VK)Tpty zw%lD!KH3g4`ADCsv`uIPeLG0BgNo1U`rkP{lO8tYUAKbfDa5jtFA#eBGRP3Li_K_EumsAo+K1F?sIXn*; ze9+5lB(etArRZU0&rg0gvtcy!4IjAaN3j3;eqQxT;cM-wockk^o3#a{I1R1x;Ff!a z1Lv!%R5&h*Ck3dsz+G^RI)o)#V!NhRw}JjC=UL!f@=wpnQ=W>vp`0HfD1<)qWYKKo z?)~%+iRV9!kc8}qD$caqQ~QSS^Cv1_<3Oy>cwV@(m7I3zX+X#7vY-Y29~a-(+T9Yd zlA+mbr+z8Kfu%haFPk7b4JMymJ2w+M4$;oft#TimhFW!L!1!5E)eCzRn#?A0bUQfP zsnqnqjfIbGn=ZSQ3az(Lb)C+H9eq6oB;#*|YIuDZ3(Q9RA&$n>q2>puVJVMX8%oQ#ZV)dmyg1l&mTGl86$X zpfhs*&5Kd`I|6JB+KpLI_wnbXghxQT3`)L4ydSD3!j2@+rsb5J;Cooh@7L;!=hv`A z4m>@ko*)%Y!9Vijc^sU|i|r$QfA zFk+O)ej-J$5R9uRHs~&j$P)#zs{=1AMi4$ylCAF#oT9b#mTRv*ojR?Gw{`tq;W5w1 z-n#p`-7F_nilC$eLVa2koU{R7lh0=2QC*#Mx@OjkeI4@i__1iP2~Ga>Zs@0CKl7V5 zEDo(NLQiYjp%t!E5>3a@pNw6@T}55^G3Bi^F+^w@+E4}|TwoNtPc{WV{pvps^ERhVz!>B^@h?!FcNdfrY5SxL!~`tw2My z73*1qafn!s(wfi??-Wt56WxQJWXUW+s@i**y@xLy$E702M@HYICJ-uWqKB*Ln}*}8 zv~&Xg9+#BS+3IPQgycX-vaM{#j6%*d`%IZPN07CoK4iNM>-SDq{94*(^Bc&n6pA{;L?qeBkbQg9$vgR)(!=*%$4{EK zwRjcad)UeG-kk^iHq4r4ZgE2fN6hk{XY9P@@!@|tG*8Z!pmm8S*0lE2v;0=v^kdK~ zWxUvbpjT>U;xp3`9#rhDh zn6f{I55a}_m?dw$Ct#?m8_ad4;AD@0{~YuWpnk=8M(yHRc~UVXx|=e*9Bq(pDdA0| zPZ`{{tMZzr$~=X$EDPEzknEkioiDdP8CWOtI84ogpACu9RDF0(aFJ`Z9%#bY$c%0r|5k+u3w z^X4|d_i=qHpQFmNL0~(dH7-?(w;x@F5KpsG=&hN3Xw^x#Ob7l_s7x(Rom*< zDsr(6cJFRw3a%(9@ds;u@9Zh2Nu7Zxq^c&7Ci?n2TkEA4!4e!Fdr1}^Vy@(@OsK(B&D+8FL?Agu52bS&eof6uIAvyQ<4X3S_5ifX zb}XCW=ScmGG8li1%3a*bX|`O&T-J|?#>6&`nfo#7_yhEeUbNPZtltacXOC}l`|c!* zDcy^iuycEs0B$KR8Q?N`$Hh@%HLAo8!^&qQ5*yt6(yI01X54yAxpGWU-;!S=z6`Zc zU%P*CM!I}SYr+{Wq{Q8?Imf{wHsO645pFP zvYqUyl(ol(WK1O=8|^;+QLZ`hgQSJ>;TK+d$;J)@t}h2Yw$eEA72e1?dPuq;_y?8AF^iYMYs6(SU4&*N|7{Y?`^BQ% z0jgNdGJFeS^D4Mh^V+$C^?w5Gm}I4#TBJZ95=IXrmXzmU>BG_2{#q3@ebbyT^t56< z2__ zB&87hN?9Lk{hvw)1g-uRv%A3utMp8>snVLngReuuitYuMzW+LAt0#r-c92&T)oCA@ zW_9Ck)JU7NLGEXk+O%I15BAmtAK{i6S3yn3~W@PQC zXE&#@eBv^uiS|-Vxxz}jqQUR7{W1p{>8}960JGmhqgZu#6ap_pMD^X$>~YDRF&uEb z2&nrXw4G&CTi@31LmihEw<5u%xI^&y zzW1DQKfGhyG49=;7(24b&YCl8t@+H~^KPq8=vnW+`0G2-j_lx$w@ilEg|EVT@qAy6 zNq8PVg#FUIKKOc*pQN1>0%yhhxhtAU^a|%$$f(-&0i9J-Q$&$lU7B3j2LokS>rThq zbr1C<0hq4NGz`B&5acN*f=j>kG!?~6AO>|^FcQmVSYHQAn+kM_NN$PIyPDH*01$YG zIrzP+|Nc!L4(yjsyV?SRU9x|@6%`NBGf2_ug=uT*FBT-J#m|%Y848T!@jX{HNlq=6 z8u}@z-XVcB)jUsDCbV0xIe8jx=<>$($jC{{O*J}Ak5*_pe<$GmFVO{RzK?RZ1*X+D zCD(Uh=O%=j5 zf$(Bz7A4{~CL~41cq`qZz6@Y+l;6LJ+_LALQsbJMFZUJt_^RmH^co@YkLt_4F|^pp zf^E%AWHRb_LK>LBW`gQoYo!e`V7)?Fd$KULen@MN>n6`-LUtN5BmFlr-Ty}B7*yr# z-;tT=BWm0Pd=QCmE=$smT`ZQDY7}(KbSFy|Lae)JL5)`r8xH)TiNra+($f_WT{6D} zG0=cM_boL%gNX1e3feXpMQHrl>puYIUrPq+U%|=I3elTsuiElqhk0U6&kX?tI>A+0 zTutAp6$VYKe&){PYHM79_J7Vjw?vt8(j{qGni&P6AzEgZI8BlDl;mMMewjSVmXU?9 zB*EZPMI=eO-X&?E)g6U0Alnlu8SP?lYyz)BwcLzXxSRe4sEfoinJ6jQ-73nrtVsg> z_ln4sE0fDyuVGWW9qq~l^x}B7M?Kwb-VCAR7#S7Vk}ICv?Hgbekm4g^lHw-LIW16o zz`6JVREr!*W4`^_p~Buc-)buC(R>TF9BcW!$o3`zLIceIo$F8kE7#WvWTEsNAD0TK ztD2PbHue3J>F>Pjp0qd~iVG1Au4+$LAK;~GAXY%7{*LIR4jDoz_G?ToVdI>1YY%T& zqVg|%kxPlnHr2SEUgz*T>lav3X6onZ?0&spH>{WCYe6sd7QG|$57#|R zJ1A1)@x`MEwN%+`fLI#XhwfC_w50R=+Wn*xpHh-e!SN0(rva_yS{^z(N3bzA@RlOUH|95^6qH0ikv_TUZ2v)*e)wZ zQF0$ej*yRzHvkt(5N&K4&j@(48>4%y$?Gr64e6nAvBB@2jU+f8io`obG+qkmNffWR zByBi3z|AtfY$S!VE?G(0E!#wy%eq55k`?9l=rJN=OfLad0#Ux^*eB99EhPg<>;u|w zU=I!qB#5-xi^)LM6orkX?6x{B|FM?RFm-NI=naz zy|MiIcESPK`3kN8qd8KHrZbHjbU63T3E6^5rDG~!(L=GTq=wL3e=cv->uF%{yp}E6 zynQpOIc15L>F~9uh#4OV%+m3dV-Wo?y9#@o-`xLYdP|2&xw0G%Ii+h7vONeY9F#PBblj#drgeOyFf@fc)B=imp8ua!z@vKup+~r7Lo0d#sw=8ea}@?7ChmRW#gS zGE8#xx8Rr`vULg3pDwuP=&Nj>J$FcG&oNG!uU;8HH?mPhSz^+W;*niIC-|77zjf(M~ zf*gi|psPv(u&vjDomE8!ECAAMW@5xnS>~qemhA~ECiz{-V_w-c;3SsnbLDmanZ}*x>ymek!czO+3FzRmrPKY$&g zc58vaiIQ4f_2GhQFU)u}V^vv19rIMA5jw{@UI(#`N+!fD+N7tF56)UHd%5F)>p{sD zhbJ7JQVu)E8&4*q&5D_<%9Nu+nJ}9RY9O^MxeLa`g3(swvgTi1Mirp;HQwZL>K7X^ zT1L6DuH@=HzA)sE#Zv-zr-};69F!HLxiQOtl&dOgS?_~mqN?DY6(4@um{L892MSti zf}rjz1{PQf0|Q7ok&M{$`prWe&fXns4u}jr4WrE25d#$VyM6lze@yU)%`u#X!^S3U z8LZ+1g9bQt0iK#jDvI8Yl-w5JQ|n}_*WIT4rghkIB@dzS3YO5ZrGqgHx8h>)Mnh5v zsVj-8K!Ce=qVnV56iLSq)<>bJ-IV9;Rb zsgX1t-T&pVgZiIi-QvKHM)Xh8zSsK}E<`cloL zwSNYQ$Rmu|Yji26V4&O0c9ux97b1Loen zH&-(xW^G4L=DCP&*Z#t#3O}c2R~|x|r^HNYw~$oGc3=PS6~eC{n}!u)_P6~k3LWbF zR?fdkHXMBu-f|9w4H(FM7;EUVdM`iti=`f&oAG0qlouyogo$LR%OfY8}lk5R4_s~S@tR}Rg_7OlMehYy} znaNg$?*7$|q^4}xs`qeH=>P?`mqhGNYDtKE zBBA?%@jSFwe*o`Ebn~7MR9h%-F3+^$32hh5bV^e+2z)lWmmM0(>MfohD$VH)U2L(m zVHuwC6+J;U_V^jC>M&xf%H((jmh!qq_6?FKA7QDE!|LgngBK4N5`vOT6x!D`4FH?F z^xP?>s+K&As4kIrzF)Y^lB^qTr%93f3FN2H#H7}v_rSBQy}NL<0fCBlBlk_xxzO9; zDA|+WCX$1?t$du7VVZhmd&MdCL;MyRh;lECt9y|x<$<8%|aV{Dzg2@+_hkPU6b2+IsHI_ zBGd~sZC^M!u5k#SKgGWxbiS-d79)|HFA-rUSc>r~1&G&*Jos|EG@g2-Vr|Ce!bY*H zRe6JTrc6fboN^1IxsL#THJL4}_- zPQb)wuW{1CgCi4a#EYe*WX#?(9b?WYN00Q|lNG0dbn~qt6BoEgt2s;44t|;@nj~Jh z zo9WYKs^+L~>Zm<+yQjGvy6Z~Svo9kVlZ|`*nj(Vn#p3Ux@jA+;p(P}W{9co~*V>i_ zf`>Sxlir|WyMUq_bg5x|_yh1~_wTK|?{YT$A4c~7TO2{|GKIs>ZT>@sI@m0$jO+ydjCQM)t2^-{SI#}$QN=KDm|afva+&;sV@uNFp11lQ}eo!J|?d( zX63Ol-4%bHRyGdHrGCI}ZFS*+Aw$UfJ^SE7ww zd{F@v_W>yAzsb-GA=!8?U=r}+dge9Po-ij)1LHqtmS;Mqr6<64u1;op zG~vX((av7KclX6;6a3_5k(<}xu9wtE#_z8`fE5$uMsxNV;p-m0ofn07tp0ImnIZF< zQ!9O`_WByQq#`8(SuHV3^elNjm=w}c|XMm>~4wy<~>ott672*Zb|0 zKe5V2Uv*zNcZe2{_-IJ0(0A+?vnY>UxNa_fiPpZ9Ieg6`W-9dIrT<7qRWvAGV~;rz zd#-VAx})M3y^^aXmWOw_Zx0ZBqv+3XTJPl}Ef@v7F5!{!oKZ8)QVKe=Hlr$w&hEa9a0or+j=YS z&0ph~CZ)SF+)WFd;zpb8_Q3hgwqHiMv6SM1BOQL=Oo{`*3%6&N>?gBWV)Mm_phNjSfFbF~^WYu1Ccv#37#$Y?P{j z4H+u+n{nRlQsuE8f&Hf>ZYAZ%r|~G|E_H=M1nnZfXhvVHH`Xqtgl5Yt8xtxS7*R z2952h6FF(hL^lM^*DUM#RKiNzyZ&tQ?YRneG?GH&51H1)zNYMzvYqa2&+^s{_SZY- zK9-)WAbr6$+%+bH7K{Jd_euOPy+4WE+~`03ilNYL7@5BBjI;p3#WrbFi{;$5vDtmi zTP)L&LRXIGzPs`p#md9z3gY2Vt#epDeFJ^~77ag$(lMD)nV703$fU~5w;C>{Thi)q zaR{nj2YoC2rpM|=xiP~MnJ}pP8{*e-@`F9ju}Di#WK<+Pw{9>BuA{ub`@;i zaE(>8E$rJiRge&9U(BWO)46dtN9g&}6Q%y{?d0H6pRJv^wb5kb-Que*K~>WnpSJzD zCx}Znoh$C$H<+CEZQb2QDDvZ@QXzLL=u6P0$Jol=6VWr>DEP{yIl=57Kp-M}Ys&Iq zi_q@JkVm`j(Z=$-Y3G>u!!}FWnmi!Gt$d@AHrG;8%Mk;!7g|j*YkcrL#pNo+Z6_|n zl=E+M#yzdUozbRI^+c5UJ z`9XV2$zUn}5A8jCx|vyX+sPG*X?Y69%IO%{j|cRJq-;V%CpK=VbY}#1Gfw1ZxNoQP zlwy!(w!+uFA}5dB=KI_JmpIectVXcj0bLynm2qiA9&4&ka5B>gO7!MOlkSf0a9uO( z;yTt*xEMGzrs`0|8G8iyX}m{GTMNsTt^MWPY05(& zEe1?nnejTqh@EJs6f6S?RgwyZLnGGSS(qp44GZ+eyvu7z78Dh{LPtrxjxnL`v9XMQ zZ&RWwsw^;NAbW6uqWfaGmbAG(W_wlx4jsLiS>V+n`7GdYCBW4`_oGC&P$1ZjG|OBW z=au#kjFMfZ7=aKXU(q5hivhp)L3BS=>1kbii|VpO;;8-d9*YL*z7aZy4C{M|#A8zf}n=f(7UGAv4{YsgNn zH?vLXT3zTWAD#;@sx zR0mBVg~!8D$|C8*`|MM@D@AAs)4Yk>s7%G@<*n9w5LCR_uZXC8dr9rJmL-+?iaaj7 zKLFG-bX|KLLFPnR?hTgY>FIKdXX=((yd~lsrucJX#P&HoJLkeQvTmw7WBwirviO5BzLV(6$!7%WwPG(B36lXq-Gw!zQ&* zY*Q6eR*&T7bARbR6$^Fayq9rhVu%*ZkHZzTqS<|dz(LoGkbf05hJVwwSsF(8Lyr`p8M+w`ed2-&L)>ep1n6T>LNlxU>P1hHsGls}tB zEj7PhKm?NbwC_*3wM~pDI`N8;)VF*Mv=!QNMNX-Iqo75d5d}-!yL605_15HH03q`` zLu=e15r&vwELkFJ%HbK>GLQnF@eZ~q9Tmk**UX`FR@7B z%5jGO!6fk|_mcbY{vP%09KW5`@I>b3m>%EjdAv1{sQy(sU}IG(PEd}f+tgmP7V+`R zd}>r;5{J9in~gaQx#;f{QFb&^GMv{(v`WAfO}z@Sx&r1*vzd!2pq zb~^0wn~TYkZ;UQ9zuLl^=WXFDw_ko5-+=7Kk{~pHBBfS#9`8yrHxoykitGM2f_TrK z>c%6DtX*Yat+Py7?X76^NDbaMrt3E%ay2^M^O=Th&{K{vd1isZ1_nu9yEB*ENHHqJ zH!>*MzNg2<^WMM(G7FuoHu%2&x&-9!LYF!F0TCbskoCn zw=LOAOh9rtXt0`@1Tvofl9Bw`YEevK=kRl9((om-y-|)2m1T)kUq$d1Wrj?Y z=%Z=3gB@6;TQnJ!v}4zjw_I`U4d333Z@f=vn$*(4{&rq4gLK1D9|z8Z6g+U3VsG1V z=52=UJ?ZI`j8f;8sl{sPv~RQa62RDN`SYRSD zwKnI{CnP1iqWz-6@nB`{RrbR5JObYBo>~I_wlrw}$cuA(n&Ex6pY@#|@r#CJ^GM|~ z{FZ+vwrUwrt6GRAGUnTa_Eq<~vdUejrlj(NQ`6SH1ggl21q!Lw+$)PBv{@~lfy{L{ zE5NmLeQsO}E0RHZH1e*S{}3RD-E=!MXvBu_otDH*Xlz+;yjOBCMPK@5 z7_d|{sZxw9>(XPk?-#v{3TF4z!&fn%9yAKPZK|^fwUk0agmfQA?SqH%q^WvU_dqx8 zQeNW$0K0F-jSaYQ)c9(RbALm1o@ja~@*IS2jBJzIphyTJh>Qd;S+3z`@Zp5WwQxa; z?jBtdq}w0Xh(;>WX$M(Yp<}Ts8GNXn({q@vdNzw%qGNi*^XxlgId#9!Ia#aktb$`V zGkrpfw046VDJK{yf+I9z2L&* z<2jZ0iL=MEc75zo;G39i|Lu^V8eX&YW?eQ#`KNrQ7&*oHQ&D}ISjos{yb?O@L3Ata zbWUojTmnhnlefs?y_RZ0z?^`sCuCdMmtu2eO5>Q+YuIiJA(pMDLnkjZt79>5V>l za+}Mp=AykynJp%vW~=PTNIge+j=3Q$_h@6bAzhrZk41o}YcP|Mlwom0T@#2j!7DFN zN9k}RIUO0zz14g0eXl8-<`|+eIl#^T6#@0jH(@I&@U1Pes-Zz-fNT&5H;Cl^+bU-3 z=1F)bOMXkCpqQrlj*uVzhKpnGRPpHhON4JFd!g4j7SlpBA|uu<)*xK|w!_M`xA_b7CoICBGv0_kKej7f6q%3M6oxNqeP^yc+)i>H& zBQv=Qj+b&>)J~rW46;y6A)TOUB2s?NpGgr|{zJECmQ;N#bW?dmfbDgro|K*-yZG=K zokz6fpsL*xy9u@BKSAjgutweQr5ngWTrYS!29l6BGvl4C)|tairnXgUAVP9L7CEUg zICrX-vO4A!ZhG+%4vP=A-htC_3aU@T9H@0gx%`8%Qu^jd>)ES-N=awEh-EElg%o_J z{C5>S4HGpS1+TC0ozM7r$qC|ILKqc_<<7i98>?`n1}c9*oBmG7-k#^P)Img;tqZi^ z3>PO$u{TL@%%m|%+w2X-!I~lT1diXEjJ|&QR|wuV*|a>Aq4X9f%6b@PF@^rc-g|+4 zU9aVwgjRDsI%X@;gyJcS$i6a#`{@x(ClL&}tvw~&s*~1PB&SwsrArc3G!ge6+mNqp zjTn6bai?}hFc?22Pd6rGfV&-*Dl=p?Dt-f5D!9FEb=j3}4?B$LDaB8z)Bf5&Vm9pm zH)%f9cPi_#Yuc6)mQ)d8KSWaIPbxV?qD)SADp#47GiUA_){C`i3GSkP+%z=g5oKz9U0;b^ zj$c}~^`8A%g|`wixK^=-emRrit%@Z&(E>f1i&+*Bdx^+SPuw_A@SVrJF;Jc+iP*o# zkRj6>CgAs;B&nA8%?!kg8fcv$N!&9jsN5RF@WanOm3_mMjvAFF0z;pVJMz9jNepQS zZqtNITGCQ+sYyXuaowocO;0Jn{ET%it9&<9-Mc`F#*^`qPcrV*5wY`wWjboRw6%^u zmZQu}ayI-7v!R>i%c|Th{c-~R%D6|!h0T+$UmL2z!n$l)p8IkJh>Tkqy~l~6Yjzcw z6r2c}=b4c9AzkZ&Hlneq$1}p&$GKp@RdTH&9w_y4KV!szqrT^*=U=bol z`v)*CF0gB#aPZ+Sc@z6_4X=-KjA)c{+n>JbN3eaIXK;vUL&r()>C3mq^RytPnKg^b zCSQd6BC0p1SkLp+&1R2HKBCFy*lOAw5^aQ0wnR%5@ECVU*U;RL@E^4THJ5zD@8F1FMi{hv(}KZ_4DVWb~6=N|g>q!w8#NcLFh^mcjjO zM771f3i6Q4#N=YsO?|5UM252ID7&k9k@Q7H-^Yr^^85GFORjh(!lkkln}u?+b%o`4 zyjHV|)fPU;)f_jX1Q%K@JdE%|5;?y`Y)LU;Mr+v%G2D0jhLOjym$U6RTaU|gdDcWf z)-;#(<1>3!<4zu6vFnJ%6k%=)ZjaZ9az{M@Vg{<^*m^qUH|BCD)#({n9P)eC@vN5E z1jicsjFz|Z-RD1fVz>BDvGKj*#xcrVVfyyQOCvJ!3buixT}t+YSp zhDai-SHADJoBsPm(3|m&i#7N`rC#}nGJ#_Mb?@(V(#Wiz*Dt2SfAI!~#*|uf(cCL| ztsG+!N|YdK2F!U5_UYzCzZ{y;jH>vqZ4Uf?UGe%Qj~wr9O#axIfv=BL^V&sk{a2Gx zTR90tT`D7e9(%5M_+NY2lA7(5J2m3KTdylZ#s)$}5U$PiHL6T}@SfFi_RxI@eCr*OrMpu?JeM|iMx?1r~i3) z{<_Ez;=`fC^_(RhC7XIw5L4zTLnnQS#Ht=F%(vTNo9 zvZ>{2%YX?k4N0P@UTJPJ{%>)+c8t~tPODShNBTJ{!gJ*#H0_n=j#mib!{&FUao#+% zzO382x3u{W!Gh7Y8(!z?rRY6r5>_efj2CJ0)|}^@Vjh^9FHSl*1{5pE_AQkURi`?E zb%bDX?@J!t#UK+85h&BHE$vW^trt?sM@>u6YSFL$YyCV0$^20FkBc_%S=kNW-^#uX zI9pXGHW(6zGFj*KbGJie89nsaKk11%lLsOkXU_iU~ZwE!} z$7Le>Js)mZnzq`#@Q|vRPhO_+ORg{Lh+X!pqcsBr2uZ)E)GEn7 z+hh_?PA&-ZLctOqDl3AXS=)>))um!{&^z~8g3>mW%}gegxZUP=R20ccMM8T3E}v-8 zbXbByo5}i(zB}A1&P>+M-(tC#PWj9IczmEd!$Ifq@A{;ULB#pHhIpi!$I>>@h0s~^ zTbRJth^=2qwCm(fjLTwo!ZE7KzAdkh!qpkcB&G5h5V<;LGP1})EICsQ6#5aqp-3Hj zYgmL>??kexu2ay=o{Tw+5&zQt9M;TOP>`?_M*CrYCu+pL$}t;lef~L5sYc*FA#2AT zk)_qHD3ohg#76|6fy;3$OQ3f823_;OCL^#Yg7zEK^t?gmDq4uDkL1VMX%QSe9Nryh z?_6G!)C3^*ta`I8%{s1y~tW7Jsx+J<-dBu7?G&ByPd==H( z1j-sJS?53OiWfCVFNt$8P#X)JmN<138p}9?Zzu{346%ft=Wk#U_YtiJ+gGPdlKEb6 z=fAy6rIKASJ*8~UexmxJOQ)`fmUgpdLWoLUe{!DIiaomsttpW4fBQQ2m&R_?eO0Yq zmXKf0C&pPeB&cTKBDq87ZJVq9x##%oufdh$W`{{PXC%_#ibp#oWj9%3R0B;eFzvF9O(ugLa4gr0Qu%O8IL9UKp9{=>TVIR3|f z0ICncoyY?ICwmMH{gY=I&HJdBgO-g1inI}hJNthC%FoaTIe zh}3=*?s})tO;BCaPu>{W{j7$Yv>+-K_b#+ok9V~XuC{boFJUJR8*x|8kGb!%3efh} zr|K@}Pm)oN=u2x{irMP7HTX2<4`6$d*ScRkL6V_~(E2qE=n&2v zRJ?^0u2Knc1a~PzgADX0eC+BA4T?kNdLWwR1{Q-LqEBm_s8!j~>&+N``Q>s-i@P+l z_H_bDV50f~4G^40i*2l^ZPKD4yXm<;3eeGyPd3G=TU{zSJoTb<2z03lZZ&Zn_INJC z48KTl4P2Fso0y$Kk~IM#@4?H|{2d`L`u9u`@%g{wsSUJ_miV*i%lo#g`A_ABK&5gK zL;N3j@Z|N6ahpa8tY~Jcb!uD{x>W`;9f7rSezYt;%Op92@3fLU0zvg>CY3Gb^o5qx zT%s!uWv3*(w1S9^S}ShK;h6U{#)JRSO;nK)_W1Dk2iy6+3;e17`Ks27x1Jb6H-mwTW`*kGdXW*kSn`6a zMUloFr!3UgGqHk-_M~YvAi_Bb{a>Be4mFRve*mW(qaM84uu|$MMmaA5VqD%;>=NH~S`(L! zbK$-*{~KZ+8BZ%)@0m4(M|>heM|4G-j^C6EuA!SjUpM&v;D2BzX-!nsk%z9xX-x1# zsg;R>&dSU*sN&@dGU`|_v77V8b&E?2WJ4^N;2%%-(YXAKcrF5zKN5)Osz#dKyVG68 zz%R+8>q#Ce8xYX>%ezQFV_{H?mV@^VcU}99V#AUK+(6b6MfW{epX_=tLa3zC?{_9o z-)-j0oSt=EuR~=x^ke~+gIRUj+T=e4y1F}mB1EZJSl*M5B&D-xSOz;zQ%HHF+l<|J z?BN9`BkSM5(n<5<-y8z$Q72gf-PUQ13L#EfAOxAk<%$;N4WMt#L%)`6t*KeT8x;%g zTF0`WObD{^bG*XPfGlY;GsGED6|(}n>7ddGUs|9avI{ME@92=^58&;uqiegG$L^Jl z_slUkCvAt~9hYvrDHsgx#R$oi;LrF`uFP1p_Ow&)sUA1q2@U(nDS)z?$qHDDpTjKD+|Qa-d@{zjdn_AxCE| zCPy~#Mmkd~oxDu$8m{d(*T91(#cvXqE<wACFbZ%B>(!Woc)?{%ah{in53{wnL7JZ7~T;&IR7nX z3Y@VWDKwb)@r+D-We|&dfmoMLz8J)HanH?!fLd|^apUeWT!;GJ7YXJQMDFPGo-(& z<%E$<-5MEe&q4<>rLTh>NpK`Rui%w(XWOqM65o4C6p&z+$EBQ_ zdN=&?7dqjuwWR(V$U|d|&<*#Ts^3Iq-tvIyGFHp_hdu|!79tZ}e+%x@H$YyJG1WcWuG6DijL zgv+Kzf5yZpD1t7eTrm(Qol2OS0ppKbP6_|t|kNkFlVTgMfcwZ5mYckA)dvWlBTs2 z#5R2i=BkTI1u3bnP8ktEk+8lonfGk{BE}l2Vw4}%HTzucZ_0to(3K=@*3@X`xEiZN zo;8S}z84FN#`mh-Z|An&mk{QoZD!6tfRkYVqi8!spI+H4-KPQFFg9Ov0&gx92jRB} zZMD@#Y^C7eE<+9((bnvjL6dt19$&e9#svBV2yAwvThY3$Y&+`qZS5P41|&8xD&ENC zNwud5NcSW|DmVsd8qk{mNK<_CgDwrr!N_M2*zhK2|-+Wr?mL}C?$5IF5meF}j08Tzb8)lD8?b7lkcpX*= zoFx_UG&8^>*2g(qtq;~!=VPpCaI|(zxx1A^fSU=&BueL6O-wo9s_i*9SQImB2s5)c zmkn>?2laH5jfX%apuRCVYNS%pqFQA$UB_E&umMZ?eay`22hT6GX&=T`FJHan2{G~< zz{`_PzHxFMLg+&}7qaI>X}7g9iVis++T$aevJz<@Fk%kLrci5{wyD+lbYmE67c{a4 zK>_Wa-kv~%=Q3u&Trh_z7oZ}ZTP~|F+mCM=r%GC~>YQmjUlzhom(J3ZZEh3Hrwq1) z!= z=DKg*+R;aR9d&=>gt`!yoS;}~g`e3lvwg?SsQsWaclTf5#npfl6r>2*OSDgPyt@>v zLgM%j>+fAB>(*@fc~RmuQDeP^>-}n*#<7+s6kN{&VGauZxoHZ+|MwuXT=n!9~pux25 zGDo9dH%uujb^+Zi=g!_zaLZ{+8|0(_OG;P|spUA)GGeN+cG_Rj!P60e^-x3x=wV|L zjf`NE>q<6N`q3ty1!p{*YQpHS?Oe%iOsh89g{uyOMe*k^N z$X|(fwp4uZ_c#XR`s)nbc zrV)d+;Zw6TVpNj?ti>X??SBANpKk_-{qK!3@79x&fxA%MIAE{fS;$m<>9p(#3ZI91 zXUJ119jGa35iMawPOWxUdw8sB|As!a(DXhIx;O{APgEIHSu+*R{#J7*hWm-8ZNq&0 z44qr>>z-W1RHTb@?e78~dSivwl;7s6h=!?-LG}Qwp&(ifYyI@ne?O3u zll!*#0az--Umb4h`hvwMY*knLMGN&H4Iil4?kG~2ao--RH48f|+Cxe#nPQWWuHC7Z zaY&zN+sKZGaM%o&H4ukDMh=pAt`IZj`Eldw)2*H&PeQ1r%VmwF_TD=}u~7R;v$do| z;@qgRxGDYu<8s=>ViM5}=_@qbSd+_Y&Srck!?vX>eN9O;_WbhH9babdfkc~h9-Tpf zUD+h?g)cR@%W$}(F5Ml9obI!qiJMhS<~ib2Tf`mC&hVpc!yCcJ$#S#5Nt0bmE&fxTc#V80L$v zF=V=9$a;loa#_WXW$QA)&c!p6$<3L2E4RniowRoSYE?nP_fqawne)4d;&+1y{h=l1 z5&@cbwx|-Es67dBw4up6QaqaTA~WxkCY?>FjrcB5r|t8fR~%2KyssB7gl%w{8Ua;^ z!p+Yk>-@62tg3T2OKqYjN>M8in(yrRQ^D`_=%8G)PIs@=OCmsZXK|c0@^Sh3kUJ|A?pii? zZulBU?*`b7-{^R2ajrvK+8Xg|R(g!bHwdP%nhvq_CD z^jrgv?rO1<5)LDlXaud{x>_UgHkH=;l1}7Ww8`ggi4-jzdOb$SL9jU%!zR0qpM101Z{*A@|#0X_q&EUm%lq7$c2xc2k6*=zHIP1FLT3l^DrEwr1I3wC7KUU+$^E7{X}H%nzw4 zOKoklG9;k>&k2wo5ZG!}r}1@lYY}T8E|iU@2e#$4lc6f$KL8F3pTF;qJT4U66LjR2 zh$-8kCMPy6Ulta%<<~4ZQMR5QV3v1JTBsnEt&BFl|3bg|J9K#jJaBS~5EB!7NBaGJ zJ+@Tc+T>KyO#VHH4kG$0N;a2<{2r@1dK*T4GUzl?il@QTKEM`3heu zG_76K|H3vSiNB^lsISr#Ud94$CEnCq{__Cx!+NnMld>Wsr-Lq@Y6}1m`_SOU{*f|3 zq#eo5eMIkUGJ%7*vl3)vkKZ9r`eq*3!=3e8cRBuE0Pu90ML0hWR)`U^40=cLUUX(* zQG`DTSpqpD2-zccMao_4345Ss$Q##KEA|KQ-Tex~hyUNt3HW<&up1T}M{X>%>u+Jz zxBtdG1J3?l;O~KQn~)ay&rN?z8StN%_{_>*cY(AV0Ul9vz5NU0{?{R<60aOb8#(;Y z^Yr-N*Y%_{IedEj-_HR6UKY!G3_*s{uFq4>P_F-VUbF>&VjAHqM(&1k3J_5x-^3-+ zb{Kfrh(~^<6aW6oC_`=SDAJJx>YKl?UT^PzV7>kh{b@Sd$%q7o>0|1{ryDO3y1=k5aT|NTGx=U*t3Co#J(zTRuUeD|+* z1mv;~{oucf1Yf_UeoD?(4X&jT!KNJ8`2$#^{Pk4ssp}0n<-O$n(^EmQ>yT@}kN0xDxg|pJaQ)!3H z^xGpr8U1myzg(vXPzx*7EZOq&{{ZF@=99TxvqrkjJat?{<7qZ6I(DEO;4!r?M2e1* zNbHb8>;d_-LGg&0T7HJ1oKNpHKE}bx^3RA6INi=aA5EFTAY7lou~abZ*OE~<(;Un2 z00c^@y~(Zgwo^yO`#LnfJ9*bF=FUvWpLiu7xnXdeeTzCR^yCqIYJlEs9_t7GYDqcl z_$mr9pPHOQ>_)8r##S57Xg;f@@!qjzjkclIln&-ICQ&o9F2J&2I`{rF&)`&CTBg14 zGwJ;!0@Ckd5Qxro;eCMlDsguzA%|j*+2k}`GuN}xMojM2nJypB>#bISj-P-#BlIU!^Cx|n>itBg zPWL|)mksOM$iM6Q!-AaUL`>3kSlfg;X0T%%*)yQs{gCE(h{9mLOTlWMg5S zllZeEVizcl$KSmQYBd=2zG6v%3e4(-=NY9dgL{fcJcm-usWeokC)G+=vf0aK$?5z- zQnH74Qoz-`^LAt9Em%UGt;FDpv#YQTx<% zOpB^-TS*3DsKJ{R>%H4jp=Hv7?z=;~ z$#O+`FPjWm(0MfNf5#K3?RjjoYNmL=$2GWF?^Mlp);x25$H;x))fyL(fV7%)40vH0_a(Y z@q*^8Y!GBANv&W8&I==U=c2ygj=p=^WVRSY4u?!>czd%jf+kUSZ-I+T%>AMJC9OVR zU@q8iSLx7AHyeCoz1aFM!_ES;!uvx^TMglzxUBqkys~*Jz8gAtzTz?mD+l zXb||UPxoEib@Ca_*MUB+n`;@g$DfUEh0ML7yNfG8l^AgMSMT>jdRP#-bg6&^$_=eq z4e>vEdK>~8?(4fwCY~Bgj$!a)i|(V9%d@IAGkTwX``SO+nRCD7UX57%^?e2!LxlK! z+l@VOq|Bui@u7OKmDeJ7PUy$C3EGF%z{Ky7mVcu1p&3v?{%YPmID%YX+=9MTkE1)I zBX_m`Ew>8(QL*la6#abl&pOvHI&*prvPLQuxzXLiM{|++o3z;+yHL`?XS=I!f#n@l zXC1}6$A)&9+*tUePJC21e|6+Srb2B+ymoTv> zCkD^u622%$j+h_q2@An$%Y6B|zkp2NrMR;oT7OT;xtvj_;Y4(HRj_T1I?(B6b-;(Z z3CvL2V&7RaNsbl=mpKd+Sfy0SEcYKOi50C$MTD=$I~k##Z1p;uKFkrl zB{1j~4_qEElRWmgHwBi5wvGRsIS+kUIaDLCB-!-=9oK}HTFw3Wn2sC{u{oQUm!x$1 zqGLIutf^L%+ZsI7@s>a~`_)8cWD1zv&O#z3yb8qa=Cd_+?b97VGH0&gF)SKby;jRO zh77BAqfu#o+<_9vK8Z1rMYz_!4130#Ga!0FOC81&f5>yA{b3?q&MW@~hWg%p?e2d> z_7U&?3A}65KueE(QW5F}{x-3jLyk3b#I#Kvatjw9e1zPjAU<*txMO5dd2E@2k~`TW zoW{`83QV8)aIFc74`4(I^hHl-a{}jH_l60B#5(fU_01c|WW`juZGlS0JV+I)l9iDyu&#-}k7bgcv(HY@_uzu(BX_Ekz5S~L66=K^2fxQi#9 zt|;8*h@lnGg)Aurj)peF+;CgEJHw93m1kZ0e|)c}r{(nv)~jLS?t{T8=&4)slPB$L z>}$Z`$$9B_@OUIj4@fP8^k!rQIewXt~5acB4-Bi;~ zA!cQ5)U*;!=nkM>;rFUpd&8zH7Ed$bCVL7uyi4jDW>_5V&+qMjQLP8|@x#;th})pT z_H~o$Mg2~F!~53!9X%Gc;l^xLWXmsMA(1Ck-Jad;^dvcoy03H-cEZ@WjZ~ax%UenR zgnz5zK_jfIMO$W3peQXxPh5LXm1Bn?hYYn)~}^*l5$%hv62X-duFcXefrtcb|p?(y&Ngji}D>v)nuiL^7ar4zs`~OQyCxR~Ew1$Rdo5 zza4JHA0~Ge+9Kg|SymRW!L=HvbgE%rutWNA({b;yc7x@Z=vzb79*)D!zQumg z%I`uS+3aMlrdVRAtZ#G1HA!WqhqP*iQA^qF3Xel)W@4bK@i6mSg{ebMZ}JL=|}EcUJm zcR$ZXM7X6I(tBl6$a;f!$amae%Ga@mMOa+xg0Az?W+9QF&(%fgZg>n+UEso&Ytg4O zT@VVLaC0D|2K{JJw?lo*4&pA5oqaHZq;)-Rbm>j-KC60&X>-m@Qq`qDHrA2j<4q1# z;sNVk6xmWvWMBbg-v2SS?yv2^O??GZ*6!jb)jig|`>A$J7BXKz7vAT@_#>3{=2sjI zIxKh$Haw~re~KPSTYJPnOos<2ueVc8b9LrCR5fK7B*n}{q z(q!+CMa1t`d0 z;!xx342FKSPa55za+2GIq8Ko$)Zc%wfTn!lk%3ad6plw15QJds`X3iH%5Q<^fQM(lhWnK>f059g#RYe*)&>-aVtKh^8G2g62V-E#JXxIA(J!d=UY?>v(T~EH^5|XD_Kt(E;&bh50b%^vf&1qgk*afxjgX)M0b1F)SRot zg9T-}uZLAE!VG$+GvB?mzU;rv-m}_*PbwEZg^~=OdSg1geLf?%jFx`^@)(D9kps8l zT#)JBwb2-PS)rJ(206(!JR?hVdiD`h3LOZjCgeK%Jy5Alq)-n;BD3dSt@L>O zXv@?0xrIsSDci1ulBIjo6q*;-Mj{x{l7uhJTW?0^;ZAvs6y4`9bVDZ&ZrGy1J+UxV z&aW3amv%1t8~tjR7jN_ElN&U5pJResJ>X4N=RBS$PV|sK>g%dnkHHVaFunba$G)Y=O6nQqwye)Y7BJnljxyZKEow3A#3LVFFJR06ga>TB z%+(unmt8IPyxwu(?%NJ?%>Na~&r@14*X|uFp5Ml%F+MULaAi`dFeCYq(Q1atwb>Zv z8fWz*vp$c|Qi5|pG{JCPW_S9DHI4+L^nVsbA! zf8CHaXgzL;NoGj4&pnk1?jzqn2Nb@0-=A?2|4cZhq4cyiJ!vR_sy@2^r$1WH{%dU> zOBD!2GSSgZr9v2ez7niw;{&IT4w+eu#dL}tE9|*ab(bRKy=o1V%(2xh=5_5^BnvQb z01#+ys|7OGY_r`xUc0kV^bCwZ$>q?}t<*1xJB`@n8&|iWR4Q{rYZi4lBu=ay z*;Z%Frd&tK?CG71FvKJJm{sfu#V`=j=3uS9`S_XC07SH;`1fo|^h3E^S3gJa0^+E5Zx%FGH}g- zwvlz%V-inkIadVb!0p{DTv46K#%d--7Ip*z6C(%erA`IynAR5Yj_3tD0uv(R53$Mt z0IDA9qs7Iskfks&T=h3-sc`9Bl<4ilg<*k5%FllsnQCRRc{%IqE^*VTCSPyeV^>P~ zZDvUF?uOE-I_5zPk3RS+C1*Z_CufY@V_KFhfZ|y^8K1rOVzhB#PM>G0PQeTW{Deza zuxks`qkviQh)fTOkH|5U>fQu>SosSW*A%~J0qq~-^G-AvaA@$`0>4gX85&~>XaA3a z**^>hJzG_dms)Y57GL7V+U;V^WKgO=4C~yfnIU9y>?pogchMDE2{VM!o+4un9((VZ zNUZvnx$6XOAT8w;w#>Kj-sC1k41hF)NpYsicE4;)*P`v6^<(Fl?-t(SD+F<(eb0L{ zk|h;~ge`A(qPgLD!25Dz1kr=M9udfo7~;Uj&e^ioHHX|dq?V%;h0sFcheZ@_`!0J< zb1r#mTEe)VsJER1XWOb~$X`HW!#^ycC8J-Sf(C;MLard;0Vif;;N43Mg#&bP9aTrW z!du_=d|v7cUc8S;K=#f8ozbemfzGC_2nBL~XWC+q?(>)Ez{E+{>(<08{BXC$#gGog z5@9)({=;5{`HEomnZ2GZ`4^Ks4mQqYP=zYSSZ_Mmf;ODgmi$&3CYiwWfzE z;r$P_a><1YQ=u6l)i%OVHaFlesFM;6tdE%olj+uZr2qSvs8j9q)eeOTT6){MI}WKi zvAine?^T27PS)pKNASHYO;GM<;D_yKo-O!)WNqH!{wlhm6upLT>&L+a;m#VJA2Q~Y zDMy~bPXBRIlB9OpKa!rM;!xuTX}vFJPKW!rF;ym8fj0P#J=+^7J%orAHsAbw_Kfc#7G)zJsn0>7tkLVXG9{uKg=d5M2wVa$Jo*@3}^*&=H(Tk04k z_r-PiOEsyRnFyxZ7WXM$zD^k_FPniB{lGq)2HmeUbZW>Ry)K3v+bsj>rBh}tF^rrP)`@3#?Ffl1&2rnD1 zHeEyCa(6HEf<#4*ld=h=WjwLZH8tLfnzM6%WeGI%GT=!-JQJ}BHIh@$yYdmQGI3)u z44_-RWO_->6Ryp;KXW}=0~TdOYPD6I{W*;LHA_Vwvd2xOoFU^-ksDCO4aB$YOr~ad z_cN|NhLLq@Tp_%T$4C?}f#Js-L_>KfN-dUTAP)^~Hh^9w)<4cn2F8?w5yIp(!Xy^V zOCN@Wws}j zdhCI0nF(zznn+AB{If}G-olzKZ>*`~fY&;fi3;&tFb7&TyY8j&kKUGf z7k6~O4*jVS50jtXSt=->K)0O2|P8{0vsEG^W=3xbs9K*nWa7Rg-i zsTo#Jy+Dr6!a0GrY7=&+b_sIl(O)`Cr)iSJrhZaw_h!sP%Pr{Lxi9zRD80Jt1XpQ< zv`h$7M9HaLkvUhS&2Hl&BIcFpjJePf>yA^{I)d!(J1v6c!wguwyHrJ*uQz!g0$iA(dRcf;&+ zS!}gTUB z@Ny?6QX@Qo<$8RVF-XY%0`nk#K3haejNDq2t9FdsJEGxYxyLl-h`0~oQlkB5S5NBe4<5!` z%!<`KX|Hc$$Y8lWLm#ny<0?G2wt*gYpvTb>k=k?d#^t3ca&&>`Wouyl%4x0TUCti1 z#h;O0fo`@?J&9gB7~MGKHNAOjH$?9q#I@cpB1D0&(v8+)-xQ~XsXenpLg_@W@7Cye zSM)Q1J^GDR0^xyQKzzK1nitzyuK-p0f&)`_zc^Pf)Y?F);L}PjDhyfu{c$^SPg1K@ zTKeG1E=~~xSzdQ&F)KPXbhp9^Uw!$fIa`=nN2|%ImzkOF=>cs8mZ)d`(3T5J4TtFj46Xx3 z4o2v{VE*^S_@CS!TtW^Wi}uA$yN?jPn00Xw@L#2T4M@6GHm{xwwj{KFh>oWMUcbx+ zTixKFM0wG@D*DwBr?v;5N||$Fu^N~h8Px<}S(zOxbCeT^_f5{`?zbc@9J?+1h;=;a z2%uf_%y{C3eg159sH@%K%fv#Mo#{<~RtW zBzr^QV7B?>iV^qKh-Mvb4*Mh|-q8mru`jR|UDkjtlVBBwQg@~^N-9GPud5$habObj zw$GCWcsX;=^}2h<9-`h_2B3SyDy*jC%X#rL_$ zB$?v^9?X8v8>yt`SSvb9YH2W3K-Ty@AsWk8wYn2CDf{@G<;P-|fl-u7cR3AfzPhr| z;N*oW*mAqP!fQ>*=?r2|!@yfb8b7Mo&ABnDJaXIYru!aD!ZZksv!vxXY$4_%d8rUYws!*y{uBP;$9CMW$iPRT4_~a zf&MHrigr))nDaa$!dEc+0*f#8puQdHcXZa98WuGS_3uSN2{l?vlOn%AQR*2jVluO% zW2g`y-oCbRDJb#2z!^!tA|*G)3Q_2Bml=l|aPs%LA~E4JSE0fW+c9P^agze8#zrN` zT6(PRWzvD_cQTpbGmZ&jpO0ME?Y*hB{2jcRjWF31U;- zNZYKxJd;GwO;*}0duNWi?&8^9qA7`XUdPn*U<$R>sSQXh-Zy56_dWZ8b+14H-4W9E z0Q{`Xmw^U3Pc*fO6lR)P%f6Mt3R=zp$N#9a&W?4W+NGy)D8+jUNcZCGe3-TjjEC$C zt0J#*Z#&B^bSaH+eh2j8{vd%FbMo%^CJMzEu!ySx{{X6MT`rdfP)UP}1CtAVa7uyB zG1tA8h1n=yiDO<2I+4+uivngWt(sMb3@{J}5(1u!hC7q6^@tc0e`(g)TBNUfILZ6L|T(zrX<;7A^D|gh3DRSzq(uDA_(l75aa>C;yn@<>|MLHJeJk~ z_p2m1xE1M&t%|RwReIIxaqQ1-M;4La+cTkQ2LLzxJ3pyV&!&TLU$6tX*5j znvSS4JA3y{esr_Poe|j~C|LH8s@_lK0WgtAy-`Q^?+S7&g1VAqCd!yGE9V9NIW27s zKekVjb?z7;MdyVcBM!}@GVvKT7G@78BeGcdg#pVblGkTE{ii@>DQNIcwFP2|lPEN9K^$$yzYXARXs*veH-e9!`| z3H%1mtLx1&gdKYQ#7p+ZAWLq$ECD1c5rXijJ;EM>K6+3sZI-o-D#?(6+#fPZ%am10 zV+#!p52Lu9J$GmGQc=b}g!>q2;kS?2I#oqKHjcweby%n5kE7L)BIv!A!-1LacTddI zUCeBB&ZYz&SUIG$Si6+wjEOHakomPYVrV`IWgql+$t}*pN@vysGwQNyqppg@osvF& z2R!UpSw^n?^5E>LuzvK|32ERbcRv`hMEeWNnyU%_ZBGM1k#o znj0?@ylzfZ4zwH9AB2204q z#5#&$tURHbwxo$zPY;%{ro>(JoG;a$392$HgB`G9XjB^XY$<|v>&s*3bdPyIC04^5 zD__$gCr!{$SNQ%yuercnDlpRyX`r_hA=UU1e~ol#OtSB3--=fCg3O_=3F7W0@FsAi zS5x1mx6aL@wn4JpFCVEat6-L!d}skNsQ}=ZrXGtZw@Yi(yV;q^n#%1*B}5G`1xq*m z5agk0Th-B4)&le4@&9-;8JMX0t*%P+*(?A|KyHbNN^Cyh!Czaj&d*X77PTI$Ew$CX z>BQ-EVp%mCkDx|tL^8c}AnMM@*z_6Qlz4de@iII<%%p-vFVFh4OAabvJ60%_49+e) zEYK-J+r!h}Dm^+_uDAVX_IdcaNrx@GxoJ?AX-w3064ND|WBb-B+7-6$+Z4^C526-0 zhdZUlY-~@~LM%sRj80$f0o>UV^@1&r@=eEw=U=`h+;w1Y^d4E6)y7>D>AYg1`uH1BLT z53iTdVM}-`fPIAWcYQg9Q*&?$7}h=R5Y@Y@qLSF!v%EKZx)zc4;89~mU(Uv}L@|YD zT4)wDh#_O7Ab^KB6rfPQ32&arv@Iv4%qdpP%}hWo1s<(RpT)SmTz93m&QPCIfpTgS>>W^=bp_E9xe| zp4UKvjXkT)Q9rjsdm~dqjl9@TKcQWb>9UdnV~}>euAXJp0b9jCr}%#u|64ii$(xd@n6(QLwFSkzu1cS07jcUTRIqU$QM=F(Pz2a<sDb>@{kmu?kGK=j$yG68Fmkbw^<6i`e}f8nRNoQcYjv5(Ma zC3hzH3Z&rNwcg6EQQaclw&7{wm;Du0X9L-woX$>2V$HX^c8w!1RsP}eCdRlQK4^XH=P=>-3$PgIIMZk=xsJJeXyQ z6&hoG_G#H}Ztj|Sa1d`$Ve&SZMrB?Yllb}28X^;5;~MaRAe#GYZ`Nf{rm-01=1$`h zx7*N_H%2!%8`Z3;^hrG4tVwg1qe77%rKUTh>gb;T@Z!ylc_C&FHsa%+jwSrbr7}J-_ z4^0Y>j(5P{(8GVh2{j zbOsho67H*?o|3(`EY3Pdd%1au7WAoRG1vW<_?C%(6oa+c6^v8PiU!`s)#n=Bv|oNq z^p#$9yU@mCgw(=Qi{z+KZVb71qK*~6?3#soivv4T6~iAwGC;hk#oJ2*-h?4<7k>l= zn!Z{L8BdK9CAOqll7Z;GqUQVykUOQB$7HTO6-IbQkGv>}FzeW=`gp7axpkh08(D|h zwmWcY9`M+sgeenkiAwRn2E7rvBNGR-Q@S31@}n@cb2RBy(r;e|BP|jtmzcD;_-`oP z`S*9~28>2$uV46;`B}e30zF(9dX#z7$tifCoW%P0{yDTLk@i5)K?^Qa?TZx=fEkDB;OY`WC&4bLG+j#v^RM2W>uPv=i0 z&z0q4Ym-IkYrQX$%5~&$btYHs4K)XBrch#uK#FY&OH3{P9IsdNr0`atJz4uY38~1N zfj%2cbS57maA5fhAn9^wW5FcuiY7f9>PfOCvmH-GI1yI$fw%>q&1m&1Eux|} zrzoYW``fRDI9VMv!hHfw{JsyT5>8sR_?v%()1x ztOET7EM@!!xPFupiRqm7bo14FoS_u&)3+;#OEQYY{PBI>GRH_9=QPSn-F!fzezKhZ zo@@V$Tdcze7`OaQCq~V4A7-X)?(fv&c9vkp2b8h5r#>5R{XBM0ceU`JeVUrr;&e>( z^`d4cTl3RkIcLa#vW&QW45C0hgdKn6(U3DU&jLJ&zF@!?m0P}U^0s0XdK;F$Nkpq? zBShN|S68^W>55sUmMf&~!)>w3BYXr5E>zE58~vDY0CgngA#J7=H{cee-;a z%y=}7bcTL$8-h5SXmKN*r4R9Zq?*e`;;v*sZd(LJ;j@S7iMt10AX3E7qk5VO?tfMG zxNz93K>Kl}JYL!ikM=#D*eqq9YVE|XbLM|;`Nc@s$Yee$TT8*2FSp^Ckecp093B36 zpUu%&0OeR}pL=d4>P<7x-K?~(gSYl_ySETOHx(XL#dqd*&IR)16HDVif`N0>cxHMk zp2iUTYSPc7%CyF}l~FZtD(5tqw7z_ry;N%;b74IDrk0-nUjR#@5|PydrgUxA+VcKl zSlpMuct0Y;n{Tp|iSZe>iGxi7T@>@UF#}7d*zNCUIf;haZSwT`BU72^&O~4Vax=?| zZ1@tB?i~L;Ky7(!+4w!ii;s77c*MFJWCV_fnGW+`D{Nh#-($BJw6iXF#fJHrbrd_6 ztmR;R1^_rngGk1%3R+#V#Eik-hE0iM;-0@Rc^-WM1sta`R&z(M*JRVN`u5(o>+CKs zy7?1K_BrL%RVRBHj{2Del;q5=xkN5S`@6)LT;^&{7?5;vqz+}88jhHkXMDH3oVKo} zqfxVxB*Uz?acr^{))?|BMvDo^n7771EB;@+y#9ae{=XM3U*hq4L)nC~j&UeSHNTYc z7}|id1EopB%yq7#_{&fAeMK2%=z>x`1<5>CUc0gLM2B{XK9)aF?!9l^=NSl5&64l| z#isGHAOUYtUw#YzxlB^0V8)c7Imsj??fQiAHi2FQ`s_{DuFfE1l=>}9+mT0qt^Rm> zT_(yFsK9` z?$iHanyDG5CsdCo0D-8~W)_qOpK{kfO9b|n!%z$%4BKdxtN7a1xZH>t6UaKHLU=`5 zHWlS{DybQCds~-UlvH*1{wwR{ocfZkI$=NBH#E1cbc21OlJ)ZQYW^F`99{K7lq#1@ zf-bzaI-_n;*6k&K9sSCb1cE*FdI>I6{h)h%+OMk5yHOJTI@wumF0q>J{M5LA_g0Ko~-@_0%t-@u*?)6ecLz^SbHdH+~(ys0eaOrC|k`ik;5O1`sydXO@1z!$+|yR64e!OaaPkSo2$1!h7uxOe)J z_y)mO_+&taM^&KZLYzEjd_T%~@F{D#zYDTLU*kH7XR$LkTw9?Cy6 zofLh?7_m1xb&OBPiPLtA673YY;tf$8JJ}eLP)^1GBulb z-3FTNN;aZ}*ySbSSYVWKCSw1Y88mj)bw8yQzfP}?KrwQ*sKsV++Av~gbG4!Wj`@Bd z^UmLXK<9>pUehf? z9(?-OVPQ3NGH3Lm<#~@Z6P6NwOR1Mjk?01HIt}w#tHzkwi$n-IMcKqTx>mzp6H7c% z>#bi9XqDMxuF4sDe_jm^as!gq*K&Pee#h=Yo|O2UUaR?vVS~KUH8TkhfaB50$Q5R) z=@zx({NjY8+QxJIFga&7^dshjAC<0V@UNxK;5e`FO}wiQ+YTt2xQ2n|lKrt8fA{Bz zAYo3SBam{*Q$lJjc&$O?69MeOKh#(sorx(z5!lAs9UvBbuSQtp{e$iMH$RTA2a;YH zbKu?LJRSonEWE`LoesHYj!~x#RcgCxVzi0mZ{=XAXJSYY=P|H4>7dKcPTpRr z`OA20_821OHPs>Uv3VwCU&5KXJGD9zq?LLwdY!+))|j@WEca?$8S11gOi^-GLv}0w z0o(K!KAWR(!d(z@-0jU^-+Ab1jr)H2_s96MgXivrR;wD{zac}AM{PjS=Y}!fJfKr? z&#Qhx<%Ig*IS1Sy@Xeb# zn3*(WqC0~(ifo*Ed`fKSmajsa0np3xH#%$Dd;N_&Tk`HIM(Swg^lP~`1D{}bo}qKs z4>_-kcFh&dh0bSUAv-avHq+;z*H{xen=>xQZia$SVo^fyt6^17@;DIkCf5|A=)F;lLiTOXig0DT{45qvL0&#uym*Ubg%vbPtt zp|F1##Ei&s*%$lS$qEqCzhHIYY!YVr+8tb_90i;hN8QNr0v>o#fO|pRGM*Pidd82& z;}|ADpi4ZSGVt%0YsGwExf

#h&k&X@@@&E%k=4}h%C$2;nt(Oynd<QF*_L!_%SUqDTz)*1u*q!wI3%}0 z6gyWrfgW#B(VH1`@x<3YSF$%R&jGf0LAei%-cXHshn_@>XQ|!YEblPOoA1zxaUqqz z`+bHYDsBQTkLCye0(Sn(zUQec{ty07BS4&qsGk_>Ik?CqpLkc!r$;0gNpnF!b3Y!i zK})PNrqb7-TvRACClW|>;59&R71l*|ebYI!`Z-ux^3zPb=@^y3Lj}*~Qv?D?a&|=3 zwX5CHZ6FYH)8Fjr0zTfSzPaN$qiTyh9Dn5G(}Ma7ki>tV%yt>9ioe4Kb(`& zSD{n=vAO3grWB>>1_OarBm?~0-3@oO?O6g z_}PEEx9*VlFCg|JLLuhp@L2;5cLbIeCn~D8wh>beUVG4Hu22Un5sSu0MO5m>yqC!r z&rlw09lro{jJn6yxEF2Jawe+37xoM> z9>dUk@^SLuU~f%%$FGgGpkM#KE=h$kF2umifOfjuLA4$4ZIW}uS8006u;*KHm<;a# z>zkmTeOyH@BI0zfj4v(ilKLdSE<;HM{O>;I)}JsVys#2clk-a$TLU2v$wY#6g`seF z2|Hz1N=gxZTry!z&X@K zSr~*qjzD>?hW`#C0TP(yw6sc61wS? zuXWDJ3<|7PsoL~m@xw%98#J z)6A(XX5+ZayP!GS%BR%DXp(^5y&ol($NJDR*Q`gU&6UPiY>~e#^go#*3}$Pn1G8v5 z1tyC4k`a!&v!DLlhy=XcsCUVRxy{R$+hxH05sAHzf_g8{3rK|eFSR8N_N!6jNVJN7 zr)3u9W&G;(qRm6a@UJLf*u&s>9MNmy?7723LUHc)eit@YA4iXylL_V%^s|gm4O|fMxnG(D-vA3d$qB!-PZ{YNSQvSe*{fqj9LMd06rB#eZnFS~O=!a#?^A9;7kiPRi(E6%Sn|pf4gd+{nLH zE<81>OEdL@H}Ra-Zkc;eo~xK6&lpb8=US^@1HGpg|9#|eiZ_Pm2EE4z&xrC#SQoG@>9 zX2JxVrhV|X?_DC4YnxA%29~fJHg+!di`~5K)zpgios9ft;xW<~k#~ioN`G%5NbR#) zT(50rmt7{rIyoVuBE^Am1>BGQba_zM{7F{QvirQyLZ}b+VHnD5VYrV7txL9^>v?lI zW{+;dsdFZ0B7U*BYwLf%{{D48##ewmFdpXh3Zj~9m^hlLSGmdz-9%GD+LL)%%{F*8 zywYV){l~D@9J{0Zu(mtphzS^!feGj77bKRV>-emhfx0pUq3w3*G2{K=fKLuUG4Y@mw!>g&usB}4O-_T{ZRD5Lk$iZk>r-(c3rVLoKm)i zbDpb@o#|Z~Iu2MES@im~Q!3+2Tjfa@9|OI`>m^{txBPYOBYQTO_ab5)T_x&eLwCLW z9Y)jV17jyK&wRbflLKX-u(IGqeuzhlIznEH2=()6x)>NUbWv(Dc!e9*TBK)wAldEA zP>5OEP`L`AQ7TVD9p5LaNR$XF?Tg-PY2G~&)R2=7g{3e!7G6ixSKa1Cc5VEwgvMH+ z!wpey7vI9;b6X)M=wmz!!Kh8u98;H!WOAOM-=*!RaCN3TDkIpZ!*JYSqtE*K+j4~uj}$NsqrRwnA9L#EH#M0!kiugc z_^5^M99h&qx9jKW-5cf42^E`Ys+yMnyzJDz$5{_0;_`Td`$?9BK9E8YLlU;p>U{V> z+DRyQtmIi;TxV@-_P}Id%xB4(O$UhxQraqbnmv`D4S1jBaN_n!K=7a36#REG$#U45 z{OwbDO|*|~ROS&?5Vs)s$)uMXMtQ&g#!3G;b4N^HjB3%x|>RUH2b!1&)wcrZY7Bx^Pn{1WX zvgf9V-bTDuGM>4;%e`Ir1s><_Xw06tC;sYRz^nF3YKF4j4bvzk&sn?aj8gK*frcpD zNCNV8Lpm2wR;euA(U7ew@Qgf+VM~bGBA&{hvSdMeuc+O)JX?WIT;=13xWfHQ=Sq9W z>O?#OKVpn=&Utd=>gh zh~>d+VsBe33%#N0-zoDX*08?-?N*TK%FQ0cu2|7|hD5OlNyV7RKC|2AAIQq+|6l#jXo%HPV)MXnFuj4ysAA0CnfPk>%zsz#0wh?r_Q#SHhC zjVC)L!BBhQoNAz@bKw!9OK_Q+wHgzR^Yc=OIn<>Lrj|386jLvbmq%Puvr z)=$vmOJ*CriN!0!k&bY#h3?hFg%&uJE^{3(Yh@rsT|;LwmU1jP-19$Y@ogC9Sa&h# zov5s`zYTdMpznjh&O8@XqZf#3PDG4jq?6%&Lw^BzA|bbue*p+UWd?D8^u_Xm(QQ5} zU(adv@*yUujVmH+W&X3WcvscRTnn)7H({DN{k4i&Zbsd5U14Fv{=-EVrqpKx{U=df zg17U1<~cmv2NLXBpT*C;2+k4rGJ?^s{sO}0Fbg#De*xT7zXOF>cwbJF@H=$bh}_3l z-X6P~84+F(;ChghuYC)?5%2rWzfgo+HRT-$MC)p`kRfPhCFp2KAIc7JT7|al?PChr zC8yt^?v*02N8E)|uh-}Y1{r{EPjlj3RtB#r;oU1R8XUt8Q#5LTi4e!CaA-aP?Nq`v7aqWNfUf z2E{ELu3X}k_$+ch&RZ*PErsqD*Uxj*WvIjHg0HM@veb86TD9-h%*kGA3(vqAT-0V3uK2(V0%O5<@vB}D`u znLph|7{MDGek!LbRo6_Z$XX)+fLa3ZfP*h`w)7N|NE_$q2d=l~{3T|toXC!Z=e8a( zji%|87=;2J>Wr@f<8(ODayv@jCfdIHK`T>PTElqgg<=fj>uoq!0T2EMj;den>bw)1 zwT;xc4+H(F8BYLMH(-@V{JJ0W1O#|YpnE&qn&)=tr*~L+$mrT252Nq*TQ3+*`!Fec z`4Mm@j1xlBE9jU?one&ZC;qXUj{6@fk~bNKVyaOSp32MWnE z5z@RcT0O*&`}8e|%?#!Uj(HPT8)nFUlNr`b&POrbK9)|H=E#zF_RY&Oh+=hv$lXc+ z-bWTr6JZik$@PQZ`CaRM7&rP3c(P+xz;Gs(jKtX>i9>(5j%=NvmSvTcKmY8vEben6 zG*S}q20+H-Vqs?H&Vw7X=*Wh_uYSfvmSTo~{(ArqS#^bRZf)l_M!_wUH3cO7S-Hll zA7;Y<^P7n?2wl`E95@1C{rcCH#ceVi{~}J+thtYE1`{3|@DV^z#Lr{?cB3zucGCN_ zv_mxj7z%j6SEBb=k8v)Ypa2|329*aJJLAQDVk3BX@RBj;{ z`>2l5btIAQl&fVjV^XGJr zUTgJQC9`DBr>f?xIqkLztZA++lnzHv05Hc#{=J&-^y2U4n8e<9vOfW){ChMxwd3#b zg;c3JDW3oUL8IXW^hrBo{!xuGNR`4f0A`PT#4&KV0n@l~?k>kVfAEwI029cDSDj9r z`L8Yd1K{qhUHuH`GV!@gcn0LBdD1TMS%SC-(z-N?Qq2`;ruzv~CEE^2Z2_1d6EyiA zRW0Ia`h{Ty?tT4bharXQHetzg4>ygv3HoBJ1exfy0+ZM=n@s?0H!hBpG!@R9aj1tA z%mH$ybrxeOciF(rAYG@ZiAgXUJ>#-si3s2KBu+k$UnK)kXhiy^VZ z;QQb0;tl@^!16~MB4nZQ5qH=H;VcB~X4CWyLaXK5t;NJM0OQ*;U|QoT3*~w#davQ_ zRO8xRfdw1e{SW}*>mM=y&mI0_KNR5a4N<>oK^wosn8EL{;&|=!{?5AfMC-wEJ-F>N zATtSfxmjz?%KeCc>Uj=iZS3G^4>Ghuf?nAeSs<~nkTH|}zToF4W0EijJA&+?XRx6o zNDKtDF$R$_$$_j*9nHvC*g09q1O<`)itd`yjlW>M#eUji5M!Es>E5%E>>sVrv>;ej z`0|8aRpf=(txw1q6}3W&`FbtAz`ptV*nnWt}H)=2ek-RFykVx32@8zb1xz5d;JtJ5^uBqRlY@CRAV}z#`OP_j!}5+p?j&#^RuSV=pE`*ms2l>RiaOWEgE?`5fqM`Zwd}(50`h`ih$#zJt>(0C*Xfzft4~x8`JTD(_{kB z7=QTq38vbB-qNc3l`vmrYQLoGA`-vYHY*yU-!bct@)_cf?5_hy03QN)UCRiuV$JlH z<(Cuo&79p1f}JsDK%X_>Vc8GpP%&^s)X63XXkTc@&>xnSaXVBq_`g)@?u!v87p7#Y zz;PrK%J<`Vk#YYn1)2C>o;8rN06fJRP22zkHh-DSF9JzQoe31y;<4l8#C`D-rdW^; zCYbZyz+geVsHooag7w_58r^^48jf$6lXm zy!9i4?bV&?X?T_SGwYJqgO+0Y(_Iv`n9Zl;E_mhdbv7MWr-3jIJ=O?AO=I|qBb7#l zJZyW#u638cR9hjK--kBkEL}=zf*YR2ifSt|xTnLC>MXctO=O;~+4*;Xt+v+6%n0^W%vm9x;Rh zh=rS%RQli?Ztu>St<=-fkzg5xgn8<6h{G3t!tMNd999B8E=UfmWp)TcpF1m?c&lzvSdO(iq zXV}6$pkiYR65!(@lYHkpk8vE zsV>-9?$QU+J!F!2Qj8*YB~L8^H_V;eKrV{|=;1g#iHeWI?@>Bur^Vu~rv>IdsG<}Y z;2!G`_%l(L$X%C8Pu7J^%x5RWYFVu+XijO7jFtE%&R3AkY)n(kjDHV985~3{bvtSsVuF z=?Gfygh$jikfOuLs*&1kZ-35Sb(=1?KH<)>Eb)OMsN=lY;a)$(ZCp#^#11Hm+nk(ErS2oGh$lTs*8~dSpx=4eg;J$vAob45$opuyL{nf*i6hZ#@C&^64^*gpQ6g;5F0?p%(+Y->*e`O=VLdN}{AwJsM098OxDs-UP zh)Iw!se)V`$(W?A3{62If1O4DI!phiMN`qp0tEasRZV6x7Ph}L`<DF;B$Y(cvS=Uew0Q*2emGp}5JIL~Xz}_A0i9KxkYskh3`uq$~-|`;XhI z_J-CDCN}m~&@}!7FvUbw|AtE`kh!UuBN+=bCl?u$ij$G!9~AsS{@>*MO)-;(x$$pg zW#M7@7ntSYV&?uApnaZwUIn1bNJvWnU|^uuIH6y_^8!E=0RIvW9_}SPJRCd%0{kl^ zbR;B1L?kR!G-PyKEId41EF2sHVk%MsLJA@r95Q+`ig(oSY2V|MGB7jHFjLXIr}>=- z3<3fI(kmoPBqU540vrOG|LxE74*0WdFNUc7vP0HyvF9Lx)}-=U$U!FYrDmIXlxi(FXQ&@KiWhn0&U;~&=uM9j!LFL^trQY=T=@PliH{rmi4{3*@2H({6Jz{R&<_Lcm||P8r^n$GUly) zfjFeBC`IB5Tf5+-79a0ooV^0uvLE$^efrx#XXKzB%ly|DJvGfAP8P~e)CZ;wt1u}8 zB^t`iY-jJ09umV_49C8*Te+TBlQ_qEHu)%Y9<8k}9xZ7$qlYeY_2}H}+00iUWFWfP z_vsRBG?2j!lcavpYDr^l@S>T!0LS!B_bUs@W|AK;zY6|5(Z9Y2dW&IfDQU#)g5tVp zo!PpzH#&PMR9{R}l*trR?6CPIzdvVP(&*H6NXf2OIk3US8>V(&+zlepjqlL}H(KUe zm$$bBDUMlojNuFDj^>VdvN%&vl#`C+Z&-+xPes8toX@1Y!8K;S7xKSEBbGeYz8O~J zSYqImf_DHi5uz?()z>ebmwkJUmFjY+GyQ6BCen16h#p+V*YLxMHu>`mN`+sJ>083? zFeZAl2>;LCbe2;4vRdKW+9`)XVE!teq{E!ndaRYRPp1C+cFr5}<=`+j^x)tZHf;k^Fw7SBS zu?Y*F!XOJxx^9*$5f`KZlwJe!U!64KGP;kl&P1GKRtOwqejgk&xAR?Jq}|8h9YcyQ#4!Zt+4+xh|yX_I;7M zY?#bkWoS#np6vy*r(+O^Xh>l$n(w=Z(UtG5PizPTC2 z0}JA6Y1FDHDAVAju88NQ4%G+9%U(p(b&->!L+KZR^?hlLL~i#|O-~@W06bq3^@R_? z-q_MTb+VA0p;kNx>P{ooUrZ$9f33hc_-&jV-wcy~0Y8}hSv3MNXvXl>%7Jz$A^R=A zdK;DNOg*QqqVbZMDN*0l&x9M?R;}$kincxG%qOCp4IF`eLgrsg&3!|0-LdnG;)9RO zM@$)wP_=W@VK>P8#oCAf!R>_&(>o)^0h5M0acDI~_@Tt-U#lf74r1WcWhqt%fOxMZ zFdK$9q@muIo(47O%Glky^}t%qK7`+0i5T}45pT%o4921!KUX{h44}rJSsV8^NymJT z;yU}6J6`L#+rPSsByYR}w2|)8%rS*)UCH#c1a8z>25yual;dtJ!SKtSmGNMvjZu^e z1+-55WD>edvdL=Xbtk=55`sX8d_s`-`wY>!PwS>$K0rqO@NtYET>2G>>?Kx2*5)>V z6W&D{TI1b(8l2PWn+&UlYo!}iDPGC%nO<5NAKf&$FaXgkA~5B|dS#X)7rbf>pz@)! z2lqyifw+106-FVp-Dg0_cGn%dUET@UJ625m%CtXarAywxhZs^2+$E1<3DK4XrMUaq zaO8vyTFT(cvQ?>7zyyqQoU-Lv^{O?kza&t;GRf9X;_T%@+#0w({fsRVsltS6E%R|} zt$(eHX%#&(oY0Z5mp`r7UY_Rd!ELve=1FY|^+4i$101p~tF8 z_@MIZlzSYPyaD=eLVKp!-KARbC1nKEb*xpC-wwrJh%bN8&2v6;$Q3=3l6H7|GG0oshIGC~-;btW6LTJ2AqA zV2~ZxN6qJE^9*o`OskTk&7s z69e^^%5uzxuFj0DTgJq+mwlIqJAO{aw4vk!qf;{~UcX%o?i)PU?^{&UFb5GQVHi;uZ=0 zD%yz&Z>Bb;r=;^NgTBE;XA~Qs30JCDDNcx4ZzXcs;%}`qrq>j4*bY2?8LTE7sL0rs z{(ww&kD$K~c04m_dt_^CH=4Svj#!eWtL)+ZW+FjMbT0Ji)zO$bn*#SFWF9=Or7k_W zajT~M1O|2QqbLRk(KxY$+DHUNKpT`j0Z~%PGJKe8%Z{t!B&!b3&mW(FKX}P);#+up z+}6IS4I5K1`XOa7c&YA}Ha=Pv3ton0=V6NlW=qqcW>d&G=_jNCIu$Et^#!*KB3YHd z1n0Ukm!QF)sb4&BoQ_i=tMi?iRF9kojR&2T>$4u}B?t0c43EQph)i~b)-D=*9R3s< zl6ft}4|{J}5xI789K!7UH3)pv?JmOY<4f#y?kZnv?>9I7N;fq3#xW*mN}&=~ zOr3G1uc4`e6iB0lz;cG9s<$@|3#~^a^O(LWYz0h@JVmUOiTiaSAG0wecZOTdf+4dn zgGcTif*I z`eBc?7CUa{sy>idjs%YyRcJST43F5QOO)c=;Io-?8;~W*KcmKQK))JQuOjNFGX03U zrYCL@ZfR2IEyh9WCWA;>!nFE1Rmqec42jWm4?@ z>U%njheRb}2+#Wtv>GD4_Y4*Z+QJw(lHC6tQ2rNK|2KSwW9zoLQrLN@%&Atqr-Q1E z#bQZ@F(Qw1>28!`q!qzOO%r$%b43N})~FB6er90YN17q9!HT_U?K_C4qGuj2bC$H= zzsx91k5~&E8#ZlDgXyj(u}IB)H?6XI$R{taO>mebT0OLw8l}dP0^w=?0FJ5WPI zNt%09jRrP9Z}Trv#T)bRqq=wnRk9f>y0|ogZ|Vtq>u{Ewb&EPQOH3G-hK*s?Qi8f> zP)qdmG$?tizu#n~XH((t>b5pNdAtqY465i;$f?Ynp$3*IMPF$5SysV{v;^g?zz+XbR~2Ghw`q# z|G;Ha858~hldArf19qn46O9xN(9mD{re4x1PbhF+p=%TZ=5Uev)f7TJP?wo% z-&A=ZD0U=$7yXriA@E169lKGn&jsyusJn&SC9g=e_=)k6!w=$xdW|l5MdgI!klr-S zooPFeci^|~J2=hF3_>@Akcex=q{%*4kDPOy%_;}XmsNc(4#E2}HJLn3l`(^{M3j9) zBnX6G0>+FAE1RwPqE{^L1u=;QmA>IyvdrKu;|zHCZf3`Da9-+fS|rqYN*zYxlE!#i zH)zE+vJ#DZ`8(_2=1;dMU6zQ=k=d@%3k2)X6b%ICnXkMkiG*&0liRTFwT8TVRV?9R zInVngH@izI_CdoyFK|fIL}(u8?zW3-!LG3?B^^huQbA$!aO|EuYM%T$t7_cORV-~O z-o!@S{9&ug@_j^L*QQm^+6>4@9I-~NPm+H9nDHB;sH|bd1!bOcxRQEIGvlX2$=L9+ zwULAp!>Z1p(td3hRM^To@>F|;!vu&qd-gSj1SS!Ku(7%+FGeR}OUWx+*Np^gscF;P zn&uY$C8jN)-+BV`uxwCP z7v0?6Z;HQ5pssL9rcm7+mNVhZWran-(?K>)w5=P;7x2Ko=dMs8#atO(ieh-m|E2Eu z@o@(X>|0~-)I!K&kwp7kq^?j|k<5Kt&?Ro(KcXNv+~nLrPW$=y+5;JMafO^5@ISw# zXY&R_*P*z!dp-~S8PbECqz{>+iEq1#{*UADWO{+;p;x0n1ZBI^2k1J*7AcH4KbVRK znKyS_<9Y9d`y*^Gaz;5fpUG;A`f$V*VZZ+ok+ALXVa3Me8GvmIHI+Fj^guQ847dvN zNecW49*{2cl(&YL%Ie3Lq#BQyM=M&A@k-rLJmTkintcYa!*O+|qby`xJnGhReKeu^ zsv9VXZ)#@_*Xd*N_%_hanLI2-+RoQM?&wlvb(vALVD+?+^WgpdsK*fvx1KI|nS^86 zHvNVJ?ameIZ`~h$ebt4zVqecC)#`xFSJ_|;zUlNK(Nk9z@g3Bwsv6WR(`p(0MEltJ zX3t)BYknsq_a@ZBi*{Q@w3&tc0n~lX@XEE;rwQ~)LolutOZKs-zT{0oe{o=Bj-*yA z{3`aZm8VhpHKM3Zr+Wm+9n5Z7mA!+XvieRAOjv)@L{yzYZ;e8}W_ z1{~Dg1}v^W)OvoowgshmhaorU_1Cre4&oKNa(W*~ z^gt8pp4=XdIqrG7v=M0=|z}X37qy1H5m7~ymx;!!KS*qKR=auQD@ur>ELp=7G=-w?kT|>6y0kRa`f_I z?o$=h@)AgE3Md#A5jPzj8HKPU)MD)#rKtibRYg;;a&;lTOAy<_Mr@rw_s|;Oh}hJ; z$ayb5uh-n#{UD2PYZj9tS-Nm3%q}5{7Zb2i_R4l;x4|Pf3B^Wc0VEi_Pt~2XGCfOk zXmwj;x|9ylz{_>X^6j2zOFYr0FH#QM@s_ve5qj9k>6eZ5w!XS04wmXz|9O>&y5XH+ z=(QhiXL_@}Bm^#{p(TLg}{D$}Fa^c#;v-6aTH zjb*xf{S2|S+Cmd&-4=tqI*hnY8Vh|5t~n-B)%TkvEY|nnZ5|2BBk_0C;>w$HVRbu`?0VoPn1Q-MN1xifPzza*_V744xgE=cV-qEExjUt#yW2XY zwSXi_a`$I<91j0O@>VZMJWtGQ-;v5%%mh3Okw9qVQtTRQGvM&Fx-$+8bLv0eM*F23 zN9R|TZCAYz0O{r2K~}~$W+Y;S^=fV^aM#B+qU#v6S9F~-ExYTiUD+(HlosEM9K6|G z-@`itd0B(Yyh%<>t?!BP7K)c{ibXh2nmVpWgPflrLOS`EL2BLX(_g(kR7?)^D!4Mb zP6-I#zC;ZjEjzPnU*F%f5Hy;n$Edc8t6y2zE}Q06wltZ^+6D>wMu0Sdd~wG|>J6zl z(!h{rWvL#n;oeWpyh|qDbm(>4r?@Or*H6oSq``q2h?Eg=X$W9SdoH}vl?3nXji+=36gN{H&Z|x5uO%~IkFbOFJ(Et=WCe;Sdo94; z0%e~?`EHCEZI=pzk~>gf^6iw3s8c$f?J&D4aW5YCO4)0L=t?RAO=n*$=0ydHaNfGn zUdF}wg>Fyi<2ZiW#iQVhFMShcK4a>1&S$L5s(vPM)$CS%+)^L-Tgm{E_{2PQTHWm) z88ZZHGtONPbq?^&(vkTKzsG$4R!lMFefFXHoM{HQ* zLj!cO$PqnXNCIOa`Tliybd`)g3jK$zmth3-D<{D3KxU zz)}3gsHD+iNC|e!On+O&Zs(mfQIR@-vO~?%y36!({*G=VDW21WP8HQ@_^-?7EG3)DeO1%^=?)E$t z31pImF|d9wAOC-wX~XC^W`0uT{Dv$kUp_PFLfETAiZ^H%rX-94j=i@1vbdAtz8k9oh!H=W?N=6sY*$G z6|B_o<+iIGT{Cz!LBVZ(_QO9m2-Ehvh;-$|wcBqM#kRMDe zi$xUmz^d1&n{zO9!Sj(l`I7|hJUcPvTAv#~^g?1?v^ZK5!bE1mSOP0dzYT${-wf#T zrnO*}#1=?{mpq3k9@z-v?fBCk>S-4$OGjq!nVAo7GtJMLV7xH9fZK>bmizWjo5FQ0 zv$-jPwV$K>5rq~N-6d`aUX2CA=GwXpMC$3C16R{&Dp;j4UG>#bhAPv8GVU&($SW7S z?|X6D+=@KF3B-bYHO97JXK499&B4$LeblRivuBAa2B!@ttTO7QLkq7aRi#R=&89|V z^GD(JFKY#nBU7^Sd1?v4Jw)8bZ(9^&`J=42KCE73o+V_y8|-CprP}=D={0?qk^7 z61Q{gZa2!%E~Yh-Ucbt1Eu>h>5+xv^yB5C8_c!bk>%C4V4M^^FL7L$Tyqiur^*YRR ziw>9& zZ2R|g;Qvto1s7;D9ATnq@-X`oKjx1Y6b%G>-Gp#2!c^#W+@9w57Ha5}qpfoLhBS-i zDn*Fk@*Ump#e|Qs7RY*U2rU-v5+mRF9lh>dJ|sPQ)mn%vF-T>>^fNL2jpJsE^yWt) zk8+=C^1Hmh9(yHn{dmMDnF!j@&z_1Jpj!|E+|p=XlF%M>VOvX5mLC3WPSpqqh6p|g zAMHv!hDMnVI_0eR3V74D$WEq;{|jYLKg0I(<{UiH#$t}Ry*c)6o1J~wGCUQgaas?J z?Kw_HknKg_7f{;zp%|>7@eKGOH+rhacH)e74YYMVwH0A{#17`57HxyW}0!#WJ>T&axWB3I77E{4@an zKP&3r$x&oP(`cio$FT4|XTn#b@`74)8tm?SEzS3wj)?nPlHD6D*XJvt&Rc{5k=`qMMOO#D(WEK`w$d#x8yxs}dqK$M>-O?p`8(93_Zy@%R?vpLj;}$r ziL3B}hf1EwJ1uFoO#M?o1E(+|AtYi3R3|&ZOcK6UHAF<=W4NZ>_RkLT)R`z67^K($ z*%O-D7^lp8Pp5E`a)4dHddJL%{y@CwujGwy2N7(YTg&5^JPE{(MtTX2Eht-8sJ8Bwva;BMpuD>JT@&-QMZEG1n3v*xHCh4?~4 z!!~TJDJAcwUu}lR19Q1#?%n1@#(8_R=}RI@vMV{(Ny-RoXX#oib00?HA)MtkCoqfD z^;)fewV}R25wjvN$sPkNu{624D?skLNTk>52o&1)BHoS!JK>~0(Y2{0t;BXeGK1GM zJ*QU_YEtkgeOtQ~7blpa#D!rE9dd!UixjPoNQ>jOr+8@6=v!|csN)Ad{G!tI{wo*7 zPeU7286`TWtB#Bp@>c~Uei&NFuTIL%AH}^4$Eb;skZvkk9kFDD)EUU=R1mu~ z4qtPcN+77GlNS@rkXrX7_jJR#ky0S*%ERU_SWOlEvmSM39hmxV^4ibQ?iO|9w%g{8r*`uYL2>na#S=M*(%A9PJUj}sMf5$a;h9F%KL}Hk{K+fc zC{H~Q3VbRWo8~|+kg2y(+tuLbDY4++w&+e87wJ!V?b_=-u#&&m?t#gVQ@e%Huw?#t z-2R&jWL4cha4O<6XjYDi>_AniC!udAuQi1JSq)6zO_gLY%u9}26r3I{ z-}Ge{$;g|xDn@QuDq9e3rPAEHx~tRa?p0e8Hn>mM>ol}bDXSl|B4hL&^{Uh3?Q%QGh3woeq8K_Xm7bDEVb z<_nk`O9phv7?W{d@dS#v9ZBMs^Kg>AQim=RFAer)Y0=}gml|!V+U%+63M!LEFaq#i zPa0KnlhS{;jY^80;odg95My`sbp%^VlT6w1)*;k(zJ>C&x%|ndbf@ODLaRc!uFyzg z!1-a>q262ecv7r|(#|M^ONFp^ExR4e%cV!DvM|qpFXK=_&&p=qlyhsrk9Jt{$cMMZ zFyE~!p;-F6b2O5Q5BvDuvGpd(bS$_h7Vw86{IeTN{(-a<^R^F`lWG5scWHyktKQ)r z3ZxP4aed$aX;9I_5bw0nC2e^`4j2SX-NOkwN$Tk zS70xI|F@9;r&^N5w94C(`7ncG60fPNwxoWOo=5?978l9~S$=MkuWV;HdX`Kl?kXCD z&`q|;HP%{Al}}Um1o1j^IoD*_%j}e%;nMGash-y%zpY(!OhyU$rSaFu<}c>17T<^< z6=#tusOog#v#*CsWMLPcZZ-3Bd)m?I#xcB7N3InRnw;6HN8#m z&=fId6?_ypnEBTW^H*U zO_V2OFHccet~8Uyv7!HF`ISdnp(s^MziR-!YXkGu*;M-*+!0>u<-$%APonv>T!SOm zATo@>UrSnlzlmzSKY1k*N*QKoPuTk(Ei-%NG8D|c=~hpweAUM5!>~9O%a{df7PN}d z7Ba{f$}r38tT-W}1k$l7DKirATh9PMG3h^t9Ot_{TX?;)H6!1;+KSpuv}za`D!SVCm~uN)@}<<(BD_#W*TPIKVlNJpQ&#Yl^Z+uiC^lTTW~P$EZI;O zCR_O0k!J;c;BTT83>asiLTHk2Jmh132B_{<#=2*{>U1nU3g1GGB-m#AxN*?BNMAg= zq|bT0E=8u*k?5hXl|E5oD+ zB07I68>}Qup0&!*boYT zHZCf%ip@YEi6~cs-3b3osSGt_oPr=;=bUxVVA9qxpnW+%h{mrefv zi3PtUEE!LKk6h>SSs_e{!G{|;m6e;}3QzoF5; z;FscP*rd_2KA7yH$P$ z4BS-}8k}XVKLt;UiO<^yfIEH4Z*6XR&(%1rJ2*zics}+dlCbY?-}60bdBT=wW)IqdRmj0 ztv2@xq}1{v@VSOMYH=(ULwBYy%3;4jpU@Q{e-DQX`?;c!12uzf+iK!VTu+B!mUa4e zO-*j9H5vlPJa6n}$Oc6q7XU`X2j0lDF-Yq?sh6K0Ou8_e%P%@Hm$IBvAyMLvlCX&` z`uVVxT2R^|fy?>c!&9-W^VMENj%pJh5+uEEDU`Rm>SyRoPOvnl%SuGD%aW#=gWAWL zxo~8xL*?$?-EixPjG%QjB!kw**eARSn22QD|Z1cv3Z-OT-Z@+fq6S;09OV zWH;|em~B_Tak-(t+jYK9+|TO?-h_21SH2k*a-jg7{vaS)-s&~H)Zvk5i0Z?JH0Dic-PRBEVs<=dH_n`&qaP+1Q!D=(k$h%OmC#3~d^ylLAH)n*5MK297uR3*Y z^*j%&qi5K%k_9CVVd|HaL`-{{?=feG{f*@(OY-uWl}?$CqfYkIsN{rXRMz_%yhQM1 zP#epnXIg`~63U@n6LnWiBq8kC=kE%%X%j21XwDz0Quu++4-m~t&35oj z+eI_B(|d!+_SJSWu*nry*q+3173g&G+WK-m35YwLpxUndeUr*=L=25M6oJll5%*RV zi%tf5{`CvPMIFf5M-%1R#k2EGY_7Sf?BXS}c97g0s{D;*ypa)?*rb}w%7h|8)2~F+ zD1DagLgFpKhSt&jES;tZpBv5{`?w2?%#UMQ1w#ZZcraz{t3taL1{4SKNC{_}Yu_Bx z962+O#wMMw5SS7ZFlx@I%@}|uZOdnk67c7pgl?JRYja#o2_L3@SvC1yX z&`nNV2;iwM>VS(gt41@=KSEyYZ`L2e8p9b@Kqts+Nz!ieU{RMBPi+lOjETOdNj&Ld zL-pMWo5~Pd$ic)#ULaoWimi)**{71FY%3AM0o2vS)W#CtL#M*4_md;zC39Gzd#Olr)i-j@RJw>@HQKWIMT(V!_pooMt5ojKM~)j*%AcS!XgD zXP7P+j<-C9&E0l>d}KyC^1wexBjZx~>WmNdKjP_+@Ard{5j3&EZ5c$Z*fA3DGsP5J z5XEXkhde$Mh?{q8yyNNQCy7Xwm>Q%QI^Snb6oJzN)oDR6D6Gp2@51EVjw{`@zEz-%mbE2MjoX0x zQZY@K2nh9=X3{3%&dLGN>exXg6GYN@`?<;A;a%!!YU5oLob>+Pa>{_S;r>f2!`llj z4`qkQL_3#;%-wON*rWo6nIP7r&@qyb0e;_RltpXqv=>{pj>0}*;rrG1c;To6-iMY5h6Wf)8 z6BWYL&dFJFdT5N&=7sYE44$AO>=k~c6GHgS2b|c(z5FHB&5A2o*&$tqHNJ=`^ZJIZ z{yQv&Wd%l(mM^t}G4`>Ea2Is^1a<|CoD*jhV_Jv1%?Yl^m4bDzt`Ol5aD=2bnZ$NF z?p9&zO30ABs^Bc9^P@n+=H?y=lge|RC_}2g5LeWlPufSlQ#NB`4TK2`?25$%$BW7U zwRGujyn+T=V-G1g)w7%`C;>f9e;Fp(&ajX%=7Sw6LN~qMTE;c8ZSCz zi_JPJNAU1?7#*E+8tYVjDka7lN0xn#K{l&g@m^nWP0J4#gUq=x%=5#AGA~=6uDc=TaJEFV{N`r!&q7E8z`BEuI=*jVazdwQGr%wjAS%Xp@k2< zulRUOOQL2o*u~VYcM3=#MES|FNxaGQD^XrB`-$#%8cu4Mg!TE?hdMo0SCSl!undx*0>PGB72QlOCo$KVmqiH z|9!JyQcFU}xW-mR*5gLK%Uv0d7oQ7`Ha$EysU>k2*1ZISmwt|y@29?v5=kR`Y)E88 z|6=Jo!+;V2zh#(@x4Moug9>G)K@lxC3Tto2SroJ>C}$zaF_Cq|5tIhnuOo+Frjr%d zu$w3hJIl>{n69^m-2@a2CX-M(IBJl*-*kclfpDfJ!mH`=Oc)qR_7)k`T>GW9>1gT& zSl6NE0-$;)uhl<4T0BE7KeWZDxe2kXu$BG(-pZS$emb6}(M89+@9{iz$A z0)O$BWt0l|3X#>?CCD#~ec)Q!0Xfvf733O$+?mDsO9}f&%=k#Zw1SV{eEibD`qlOl zvbo1dp8=_NF(+kirBl~X>V)+0(qU%=S~IkVe0KckYEm=D4FiZ|`S~!F0kK9^iD1{D ze2Y^pGr@jCdfc>|f=WE^9hSXM^cW7h)+h=sqqKrG#dCqW_jr9Z{7@=Uq!Uqw_4)35 zZwK0F=1%YUxdQLv8+~dCg|NssKX=-Eb%O9MEbQlvJv#B{di%{u0vrKzI(hc%&MdJG z@JBYEie_7weBNW`_{H~})a?;>_=MI9CgSAKM^L8EmMVmfhX&O4y;N>UA#Rqft;CZ| zMqLwU%va#S$#0TmKN}>R;E*FHZ}|8>*V_4~T2D!m&STPu&kvz?)u}33pDL}<8-yE1 z!PF-vj!Q`mQD{xa-Ld8dhm~(ZRe6|{o`BwlZu(gdJr5m$7-mrGJ0%~X^Gus_q{0&I zXTW74>BZ5Lu$l(-hi5<(W>M}lAWawp*Kk0y8uwn-U{h5By6TPz9Zs^W49o8R+rV)> z=%K)8%S&sD>1OQAN6dnp{D?=S$y}!rc#)>i^)~0obs^ZAk5;DEux-|}?g4nqNRp0C zZ!U<_nr9#q7b!6Vyu)j~Gj3a&hPre_yq=(XI<9;AsphY7MG|#N-a41Q0ZKo~m3>^Y zdHkO4#cFVT;By40Dfav6+oNw!oLZ4pebJJPzvJ|0vku%6*I`EPfYxy88wL3dHX`ti zN8^|_oG~!KCT^#k+?yko-VXZP2wb)!Pa^}rj7qug8AbOs-a+;KbQHgH2xi855;u)4 zxzao8fH@Z)5|#}}lAZz2fb2@4c268nH{LyuvaqdXuU!1j!pMh2!F9cafX0N2vI$D-PXfHwoNA<~Z`0_p0*9Ca&K0gt zh3a1(w;1dp$@13ppOTj3o~OilZs0TshGpj zw(}swIb!6?_u|X{CPA&c_nq*K zSJAc&=a4`991$oN-Zu5INKTK$ykiD_U~>=Mz2GdA{?|%gYG{jQ_*7XB%`#O~#>boRvA+ZuVkAqk|uY{*s_hc&ya=OymOX zPPbsC(wCK}($QUwtWCe3GzFxI`!}3Y1Ik~l1I=;|&f%<-ze>js4x+;i`{P`!7!|q_ z{bE@>W4DeLC|v_wQO}nfRaK7lwR-3B@Jg+)Y?d$v#pYnu>I&E#;>!8S*l+kyRnX;F zYo{ys%q^bJw9S}PgSet2xleB^NERGgLV4wtf`Vl^kR4-mU6kJ1?y8Ep`xAlo&nreC zgE#dFprChJ2OlRoZQ%9sE7s+C^lBeCsfvcl#xP?j+IL{uFbs?!QtTckz9Wt!(KRE- z&L8czp;NRt(m@x(^xp0^@k9mF_3ypH-qeb!e*0(~#f|*qaY}9O2Q_$|*}~lKZZ&-U z|>R&Y< z{rY%^!~<`_lXMKv<<);!VPeC3l>tmSx*_dsJJB4(^m^OvO(F<7+my|+^welT5sIPYT0Jh2`!h3sJ$a@3*6+h;MrvmnP?si7l15-bTi{`CIV|FL+=J38h+X zS0c$dvTyKJvK?wUy2`S%bW0R@@IqDaD+lZou~p?P%t6-4-8d~9&cs(#61&N|JkH{8 zm!ejjs&tfo#$gi6rAm$%Sr3sNRhG4zmm4=+CTWg9x2D5QgdwNBUyrwp+<6BsT!WxF z>A2#$vSOW06_59ca*hw^&Qa{uJ~oz7;JO#l$qXtDD~*2{>+X_NYf0)~|DFSDGvNdg zh_GYeb5gr^Pm8zf#9=Is7V8bdsXwl_lYA$?hTBHCc27J9iX@bQnxCw`FFPK2=v-xD z2)7!`10}OiCa`y-i7z_fA2hT)6*lFcg9kPZK;iVLSJ?0UCe=P=?>AVSRG}`g!`2Q~ z<;OE`&2xg9Kx*51xGHR#tw9Ae9*!;6yKZlNHAlrCiEZC&CgY3f7*zZbo(&oVry z(B-xp%{KH05|nyNdYkvcyD2EQ6h;i|IWM~HumlVNN%!H8U(|L@d*uXvJ)~le^`=ta zn8FLg=y=E#ls;l>YKOJ2PA-&OP}26aW)^#`IckP9zI$sgEG$x;w{1#vlf@M?Fj3OP zb&t^)dw9hf8`OL_6AcjHE7;49H`COeX(ln>M^t-#1($3uGgj^pGN)<#KiGTAs5ZB* zU6^hPv}h?-iWPS+Zlzf9;_hz2gF_3&CAdqA7KcD^DK5b^NN{&|=*iyu*{?j`8RMMy z`}O_!evpw7a^J~XS#zy<&3VmvHHGBAX%`>R^a~TGK?1@m7Ge3-T?&A7*j8UUyKn)0 z4a6LfS+@f|IpvSNMmn6{m?mh0)nkZz?Tzw`vdn!m_qxdAl*T@^xndrg6W1b%sjv2R z1e{lSFq3Dz6p&WY2UeyPeatl7Bo-=vn%!-b%I--!6c)AN&pgTtJE(YNcG{rpoH=;pJq~s~z zEQUdGP))Io)NUwwR6>oiuq4XW!j6ph*Pw^c#Z|eoRM#pAnQvaXthLAHC!j7dtCp@V z$4rsVDX#!>@1{k9stKzD&!Rne;i^51&C_J~jg8H88;<|s@OBDj*8EhwK~HjDp6C&} zZj_H1J@EAU>RROubh2GfB*vKq+oSYAm)AYmhUK%bMmB68VaM(S$|9t1zs@1!MZTmD z^>0---AQ{dD<_;Yosd#s22tIrXpU!jgOQ+E>`*5I7@HF@GA*61va_luL(YdiYWivd z1$Au7o9G3=Xjq{=62oQ@b7^^wdSQNAK(?5vO*_kY{&OqUkWoLyN9<%K&J?f~HB!PW zmfH$d>`rcw%B#QL9pXoNatBlJunFn7H%S&=j)tB%`043bzLQB}i zgNV(Lpn7tG)TKkcw!S_3Da2cQ{!Kb&4iC*SH`3J$bL!lLLEhj;hSeBz1iH%eQrdRM zhRcRlBU2BUZDb_#>(tc2*afgO6mQxk@-$BQqJ#myNrt57=?O~5(6LM}r}b#5lEUVL zMF$p5>=*0MCg=efXvh4Wy$@q#VLs$!V!}Kclr@<)J=k(68&ccbP8}0($BKj&>P0)O zrzt&QPLSQd-yUhIK^r7I4`91)y;|+B8G&C+TX}fyQxt-u=K;3gaTFufEWw5#x4V&}X4{rp_ibC&#lTa~HBU4`RtJL(6h8 zMaTZ;4|UY8IX79Lo6&P!B!GH;66qfs0UkYJ^01HGGz4&NY~x=>v!-yI5_JB49k?pe}2@_p9eg6xdN z!~{^hj|QF8`_(ZY+~vI;vPgGh6eS#lhirq-z-!QCEyd%3LrrgfdJw+muKm%>)wo!E z3XU3{q*27^CU#Z)a>XF|)%VWFWTy4iDx)EsC5ditf}-fDOESrsVGX}R>?qh_mF}Ey z_RCYgg9Eo%IZ_;4;3NLpP6gK_|G@D=Rf=q6gy*8>v?4&8Rj>FbO$3uta={FeM;yYd z@g*=)n`}ju>~a`RHn@Ukd8pB=7}L1YW)L%%y+1ZjnVenV+BITG!3q z%NYuflx6d49fFE#E0JH6pDY|j>1x)^2i5|$_4Y5ZG1$uLtqx_W*L|o>D1YRC1$U(k zduv+E?$vgCHhdB7d4DJsSdVE%9Tjgg50C8nvRGa;!xA^N>f?049jckfBImw5ue!J` ze6&qO!R28@xTUIFqr+D4GJ@SLsjzwN&_Jb!N7eR#imDocUjC;rkgnD~8uVG69fmEs z=`-_Lkz7}Y2JPz+Z4n@Yf#2Ls6|EQObfD4JR@68Dv%kh|*=9V3Fct`7+KO6DvJ7l3 zt}tK8B&Cf2RQfPsMITwcvSB@+0~p^~AR6@bilwJRw@y{fvh)a~E(e5;)|)CnS263w zSYdVPlY!^CvbBYx-)wwyu1&1`)o$CW6F`#a`--d4?88C?hum1_9*I}fCEdLJJDx}W zH*ZUuKy*VDQdiU_#y~iF-`BQ9fE)?CjgwhDjE&#zjSSk#b?Fw+VmHC7E~VMJb>vyE zrTF0phMABkVHttcO*!(Q%@Pq|%rc64j+zuL^GTRKnaP9k@tnQt)P-g4yWuIn+@sIE9>n1h}-MQe5q4f#SjC56nWE?2L6oE9xb zE;p7-BkOlc_osGJrzmB4*1OM}G-U*sZDx%nrKViI{SR6(px93=AI!KuJ$phg{7-c0 zd~tm0Raqj~L~$#eGoJKb(jb%p!EN;hos*nn3|>-f@onLAL`t_m+J-&~1;lD-*#1{= z*(iwi;F)E>_i*+itQlLi=X?7+0&Y^}axLFvRo=!t*&2xl)Iy%5BrV!cg^bS09%k{y zHW96jnfFGD1A0M`choAlL^gv2HCRtwo9*iq0|>DD&r|1%9Yz~AUJuDk0kNkr%?N# zdh=5?WC8<9TWRAxbzwzP*geGe$Y}5O`=+deUkk{C;-W=WZeghza<9(f1#9uorI;bK1^;T zw^OroKFLN_lrL#u#qlRY*v}gNixRC{EzSPDTeVv`uZ+NCy$epYtXVCbaJ?sUx_%mm zQ~~DLpg*zexlU#%Bk9d6L;H5qLJDDsOjUEN1)Rz3p23CnQ4nU%M7LHJs=M*#FPa!I z20N7>#)HR~Uz?kN8rj+%1#IS>*ftQT3;N6aKyex+R?mZv%EAfl5n4n-L&XN-VE|T$ zeqTy>TFuDP6csPx1;b}eOlYOf|m+depB`6Gd=AR5MgxG+K^Io z@mj}B{B%qSpaPem2~2NfL1 zHEGSe3c7fH66&j=pXdoTBVt31hq*6cfB9%GT*Zr}+K|cOae76+)gVgfOc?yUn7E7D zE}dnaK}tE{MHqzPUu1D51X_cdx>6 zSOPTcDl16%K~!zb`6+*pI3kMZWdCNoep+|+!nC(YENi1nXdBjR_o>OLrTxqxm=x6{ z$|#hm=8qaT9FLwy*D~A^B0cj_f_5N_`C)KMFTu>dOG!xC_*Fm925wW@rKrwNkX?7= z+sT@aU)ahYQsbE~60*;#uhGn#WBBH#z?vrdp*e5h4ZQ8yM^!kr6jAY;oh9wlny;`* zrXJn$R7t6K|3s=-b^k32SZj?lgUC=$Hs2CxC7hF;GlOs*GIJiXbOJg+LuX-y&bp4Y ziQyA!q2bXxvO;WW8!^-IzM#AMWoXv~C zXOdi<&eKHJY3td1YU)GQWnGe1FVMzAjUMH7XOae|(-{iCp!EZ-*N$oo*q>)HR;tO2 z*U)+!{dgYHLzumQ=Q4E6n%o@ZiDqF)ZTfMNTzjLH{cGl_+)DvA`ff>G{QsMxx_<_Z zcrUYM@^2)|nw%4y6AhmK*i|t=MFEk+ek#*rzmWzuo}&KQurU5x8u!OHU7r6;+m>qn z=f*lPCbr(ax7)rQD=7tYNoGZPnwY&Mz(ssi_hG=0$GPeq#$!R{851=tf*y}3a!Wnl zYCxodnT&3YG~MN&-uoJjzYPm(R{C5qubG&JMW0al(%L7RcTEU;FuoinBalwdq`fxT zD;QK??R0Um#8VVqSv)&tWA4$JGuCmbI*!aFjQf82C@94l>05WC+EXj7X&G@tcj zzaDh=V_rARX_y^68smyrhExW!W(rkLer+A;EW?T}c`>lkd!cgEQ6R?0 zD-@dmnH#zs6+6qB)veR|&@g~V_+sfBfdIQ~#-5G97}h;t4R*&~=O(Wtp6cf6F}Gib9r(o>K5BU9_FN;9jcENH}D%6kxX!+nkO7Ot zrir(WHJzMyG5_3Lx2V!>FG7ZtJoTq;(!v2krZ}_4m_PGfgZ{f!VM&jLl8h;ZUjv{# zvc@7i1wENgAyCAZX*QgWHU04_R%XKL=M&vufWmPPGtPZ8!ak6e2Coc(GVfh_73sw$ z50sC*nTd5W+@_r!4X`V?O})Y-B-u^f+;tD~bt7Tl;ZSe5Io8K+a!AYVLVrx+2k7V7 z9#~#U!BA7y?LJJnN}g6&W~U6i8C@hYzfg0?mm1*t3i(~C$Jy(!P{h3#=5F^IpKdJH$J0)yHf37vxu5q;;h(G6_w#2>Q95(=~HWdzL@P@*Ys2$x(qV$KqnyC3^rxt8!Iv1i zvgaZ*n!7;Rl=v2aaOwxQZ`t1&h0TK)C6eGLa^}k`=+N-mg*28LiFum%cQcnqDi=}X zkyhqxm3|Qs(=*VjDpgspb2RggjUo2ao%eXnqunC6hv6Awzy*$QegwvAZc zoqR4Q+4#x#ewak5I{T1Txp}VsYVkqGrL}u>xi?ET;!-~CTojz-=yVWRc#&JqUGJb7 z4~9$Xe4PQj1s6adXbUtZ8GarI;(H(LHi0(jw3XM?oKA{XpF5c^Q}WG)(Lj{$jn#~~ zle4^PrKn74Q-Jb11&IqD%*Ivx()(IhAes}6sq7|H@DqzraKUy7Y<3EPl&ujz%vf*q z{Dh1JYfM_|11}wkB(IWXPf@eKU6REBrW2I7Zke6Be69BkiWex$Mq~ZUn34C5OC7yK zy_=KOXY`p!IZ4+lP1mfQn!qg~|7N<99=+;J?hmt2{0ex5H4Tcj`4B)E7j!vAF-d(wl9wrNk{DBI>ncG+m^dwQ^Lf+i5YivDy9MTz8-8tB0-k zl7zv_S&O=MmDS5rqK<7~{%?$+Y> zc#y~0;8kwNRI#p5B4%M}R@a?)^&M-Jp_r1QCbz|GV_*Ao^I%ixfT)DBngDNgh1<%j znUjkh$QjX*$(98R&xgCigKMdt2Q6W5Y1xjCOQpX1p?)NzsQl0}d3XUdC-|{HytdU5 zVk3i>f1$@VR{$piFTK^npsk+>@rrImXlW-NHd?07V9QhHs(Mi7Ir12EH$2`X6h8pe zV|?eRmg0rJ zc27iu7aJquJeJAf;6AS25yDi;fNT{G$%<0_}tYKKHzp>|EQ!U3h)rymAepYU) z4Z76-*txXoXeD+kL~)w4RjYRsc(roGSkpgDKwKLcZI7?XncCN8^C?^DHT(`Ie!lU` zBy0f?N@?okG1nrZxry^Y@)BW2n(mR|Q$RkNgUb!mWQ93>p4$4=HE*>j&XxW5g;(n< z^7RVhgr=qM(luwZ3WlA8$dX6G1ET~YS<+=O%W)_g<+L7sFn%Mw`^m~(J|-Rn7_ zGDF$T9v()Q`x+}ur$l-J!?Qao3JsYs`%(S@I=2>?Fk!dP?mzs(=kU!uS`P4|9~@FF zFagm+TVlrgykv5Vp=5M8pJyW$(&Y_bQiCr|;`vX17VDJ?Kb#~hfW2+#8|gS;2*s8V zORqU|khaX!AEg4oafj&Y%D8c_7I(GuJ~CV1gadKB%?K^P5|Ywj^?R<5N5tA&6!ch0 zf>cw9D+jrvSeVSS&8+&{pAOtM zwdWdz2`4-YN!+DXHKP6XDutGc`*+!OP~j%OLJ=$Uh3?6`Wi=6s$OG}r;rdB;n`{dc zp`-IgLyjz$q~A#E6vICJcJ_t)+#KD%fOG4nEhgR;?|vgi1@MerSSJUi>t4;cVaW#$ zE%rC*0_R92vC=J9pU?@?eQ1UXK7q9`GN|iN;!j^ec;Mk_nTcFFZ+Xd(!*u5bZD>ZP zwmx0oAzD>9GmrFuSiD7BuOx4t6TqwPj*SlSR&0*mN*@tMFv5jOnrf|TZZoF75$%WlKy$9u7tt{AA;T-v zMqro2o4L)4qUZr(+m@eHRD1sskorG#WceFB*4a2-*&&)*BIpJvYMR5WPs3JXD-(e(svOTw94E@-v)2~6^TQCBb8_L1d({kYVT(%f!HCY=x4xW z{Vj@yeirhRuu?_Flh<=Z=#J6!-&wxw{~nUFi=a3w_>GiwX{Fx2F4Oaf`!g)Eb`yOL z(U-&IZ21(lQDXa_&l~O>S3pmBmx%D-xP&$N0cr?oL>0iq!jB7 zy04Ps3&=7~8R3^KV)s@LQ^Zqqb~-*&)o*0k?wA`4w+JE`iy^3V8Rh0~i(^_=Yd#?H z2d$Bfo<~0Y0_J9q?rZ0brym6j(=ICtuzt^QQ~Ex(yl>TqtklUq6iaQ^55h17m2yi> zD09AB3?kj4wC{?NT%MK-<)N|bKn}y%%b}%e6^$Hg5~TyL-OX*gWvAsZd7eG~LB)0+ zwG2sVw5@egWXD$^WuslC&u!H9zGDsO!}A8Jz=J9C^f;gzWIXEYBg}F=XE5{ zcvb1o^83h^TV2_K3Hl@3#nyfWH5ke_`wt`x3pzrYr4r94oMm3k*JbqP;mT}`HpR*u$dXSfdGz0AFD0o7hKdm=18{kWz3j1_25@!1* zXfX0>U)YsuHL>dWd;s0$Uoy)LkID|a>K}iW9m`>zl4H8W(97^?4c|A?nyy$7L@k(} zwVjI*b|`!!>2Sce4=yx61A>8=GaKt(N1E|WD?6ztv;~gyHW>xxL)Sh)JbZU@xo9&K zuLe_UhcLKw#%sY@fxcO`#iU@u>Yf*M6L7>2n5eEdNAyrvQe#-|8eKJW()$dsa5<;x zxTlbG%{gPW#!A^`Qm=s-iD`gC$cC#m@0d`q*N#jnqu$OMI`K; zB=dzcDYP4j*ii$=$K6A!8uh5VB5S+QUWlMRYEaN7K;pnw5PJO3g*h9lBAFe}CSlbG zxGT>t89N=U?-(E~HNWx3AWo5y*Izx><#R6QJQ$T3SPp z#}e@iOVmVbTn21hGS-S#yVX4PDC;vHNeko!cP}d1HGEl^ulq4W9A^9q{A-2cPQweo zEjqZwSz|>ck9BYAAT2|6V=JB5JjbKk!(;(G9mxt{?p>#uMriOynKHX2Xzn zut-a%m!bWl>rJ7dg^NISYewNlBEvay1F}-nc$Yi?!%_^BDkPC>46H-hgyxqK-46=% zkq)gT#00a_o!JEh{wRKVtTt0SRhrYc5o0fMtB}#EAjUPtE)kkL8YsIEq^VWsW^Pr=P$xYb^jS#Ugrt+V2sM>Ow*hmkEc*Ec{Ut z+={+eE*x53&Wo~#suI%EXupw2iykyM3AwwH+C6C52BoW^(d_<&4?5;h7$kyYCh!4B z{dJ+L$_+()v5^PLmhJJkg%PHn{A7EYNaJces5AIhTTGhz|}3{*Q+XW6aVaReX=U6sXS znatYrut2Of=wwCzyT4c49y4`pbzDY<&4cp!oGq0MD!;tCX#x(ftc*m$_pnGcj=#8% z|HFWB;b~J2WAwKkO@Bf!+@^0*lL@3;OzE|*oi0JsL<(txdkV>_*op%|>&t#$=A^`# zSCYWeKv$)eGV9zoKTryp;9EqojH#uKgmaG^%u_*wInFiDg+`rI?-cr|Z#}C1gm`V;fFE%xD}A&DJu2=QRKWa$ z)WJRBWKCRxfgl+6{WEZ=q-F^Jx~_3Cu5d#C5ulTbIq`oIQAVFDXrC+Fen5U8P}F;0 zf6tTo8|h0x;QH?J+PRTBBK>vdC6>ozjYzP4M$F=0DLJB~J+UFjAqEq|=zzOvoI4=G z(Jd*N{;$)_z+hiiMCCOtbG@w^3zPPk4-a*DjA+}%Ou(FpwQs_!wL{!(gXz5R$ zr!JUh@hO;+peC+BtXB7F&*gp5RiqJI^Qz}Wehg$DKS}u zlX%{CkuvCpn<6$zYipmyde6^&EHcL+YT<3*Q*_r4)oj%6TOMr4CQpo~4-n_@;Ha|x zr%_sP{A6!yQG+lId+;c8X5P|M(VU6K3uvPsHpx$S!sOnu-i`P0`a69mFk>;VNUBm- zc;8z28{u;M9#q|*PrT%zD}E*Gq9`G)m2$o7dT)ZaJz*0btIR1k=EzQJwOC(j-XSCM z(#$hYpcERbX+CG02N3&R1%n)!srtC%hnEMq@-`m5LvTY^iM+MF7jQppS?kCYlT|6b zPZ6-=x<0o*AKd+lRnc$LDrHF&p7j~aNS(2mtJr>&e`^{~B>aaUP~U%<>}oThdf|Yp z@Hopmkz+#ngWSbT>}vM}S~v3%hkB2h`CuE}0CV94I#FxYH>+N z-J_jMci6qw91b3v%-?KYk+gjqTZ0_w%gF;42@U%?Rje5??~3yrR6y3q!VS6z0{5h) zO*wn&@V~v5p71o7BHz-&vVGV7TvGKwd@u+c!vlJGfDGsAc1Fp846QQk7Q zk#w8hYSNzAtb&q!A5E&LQ+&a!eZbvrqMZa3Ga_0buojCZ%>T!VvR`0S?^~VBi+EW) z6CbnZoWrY*uMD*B{KN+&;0D`lhM^98>|WRQu3Mao62PoBIe2;?#GaSV1ml^jhx0;H z>fq+)*DEH2z8S35xyld`MC&AUcFhB~C+5)lXG(24MHuRpb;qXrc`~p2E8swnbni~Y zkJrZOYJ>#47hE2Ed#_U;Ccmbl9&YT{O>|S#C znd2olG_*pV#;f!mp9@heWACwGTIqEctLrYGv~KOlSsjZCPlj?{(v0ZGOMe+GdyRzl zvGVYAvN#vK!=*ZrV>PrL9D`t}N6dzoB41?P8sRCFJI!^wqg%#!lTL4&87VbWC7wVI zjj;`}l*NB-QBnkhzYq#EsTX}tbZgeX)v3ddegjoE%r6&dj%H<*Mo%qvsWY};#Ad;5 zabv;}OR|*vNcDrv0d)CC^XDn9u6!dQyASf@#GQI$51L6nalCOOI^{3oHhQVCNJT_3 zSiCI3@(88vUB|Qcduu0sq_kSi3rDU;Xg&z_%}lmy<#B`4yR2JDkbR+*dMApZ}2gpfUK2TuWZZ zGdw!|^;>=!)jCEAa_&E1Tj4QPx4JT~u3m!*HA*oP2WwS-5*#Mp_&vZfG zMAXUN-K)6=PntFplBMDjOjqWNu-+y!B z{ftPQW}_+UhkN^^UtA7#)RpPeHAxQF9VmmGT@0xJGmx?LlMm}-Yhyz%ZwlE{FL`$& zkDP{I560J}-8=TL`B%>?f=gY-%w^~+$VBCJ^J8}(Bt5)1p(4qrsIARk z)cXntKdX)R1-4NcU`YesHaH(KPK8B4$(Z>7k6~&}Gl}loC3mMGy*FQlyvlt?@)8(+ z^-Wj4IFJ6$co-t{4FBGl@Kdk*8C+T+;oFaR+eVG3&p~Q^M8L{W6R8!CrsLcjak37K z{5_UMZFx>9-7Jr6)P&xSjh4k9Mq(0VPSUWP_Zh+*_DCw^*?ZiXOzc_7ekit{>&)?+ zG6I;+2a^{@yh4Z7a5wo|7>A}=-%RoIvaplJ369rwCOuljcZ7`&oG_EP;f3#y{RpK; z{&KZox^l%$Ly{*o1OXEB_$1vim#%BJ z6_O+LY=FPqogib6HK{z*Q-2&B1*hjtmE$b+E2ws}m#6u`Xh7dzX%lgx*Sl=CW|Pcc z|2(F-q%?J_r52>^Ly)1oF?3s$0;#@}9%gm?P++%470MplEaYLK<&1jRz~uduM*}%8 zY|BwCMIVlqCe8A428aJTc3+nKYlNCZAyx5~1JB)yrI7bph_)?=dal zTSydZwFqx9=Iu6q%h3Ax>7Xrc(ksrw=`xBhelFzob~rM?<=%)=a|WoOSMrOJ?Og*0qTT>eg;Q=DE)*Xo$x9k?f(6Za{k3Y^NLj2t>t~zX2_C*i5+W#w zn_=_dePOM>N&a;aIbfp}B%dsu%&-i&(DZxF;V`0Jks`$OEJh^VKXTQEtOFe(7;Q1A zj9FPO7j7b=u!2*#Z>7C%;ZHQl(q$;b>S_JTp>DZR<>HdG6hHo8{fdqZqpWwE@P@Ce zre*uj+bACyVSEyLvD{;CSuI}AS!XYWVUcW*4ZC8UL(Gbb zO8+WNt8A#aYhO9v?zI5u&lxr1H#o}4-E%Q#%KGSRT1Hyb{&i%9Bsc;xSYt`k9Wiz$ z`>y?qvzrP+hhnh2E9rE@2uAH*ndP+Q`dlx~Is^M7kozPwRj}Pkt%be$!H!0uQ4p6nk%>h&iIkA%&q&*Q;OHAp@|C)TT1XO_|pB(zdQ; z*rU9I;sx^%bdq#x{mntS!DGyU0WR&!L4Do%=6g9n?iZO9aDU$1*A1jUBLDIX#?I2y z5?v<5QRL174>Qe;X{~J|4ujZLb)6ui$sB7V1Mf^7o77%qc|us`*h`caJvN^*>$(sZPqPO^BWmeg==&wX<;FP$_{;Ua z8TzwaEbqVUKo7=5O_>nb9FFBvC&X+hqsoVQDpw#l@gfu>iyC#`zHyV7#dFQ$gnbezM+QPX1(bDp`?K#(zn@YJEyl1o-FviAR7HJNA+NkJ@U5Tf)`kI5#T zr=(8dvVO|7_W+CJ2wxKvoM5%btK8KK-Y3CHV5E^6VTnqvrJyA)5ZKf<-nX+i{)SJR zZo6;G3%*fM_uSU$G4u<>Uf{PcyyqYm!-CeV>z#u|5M^}-qJ3=S|xXwJyp->=`6 zn-Q-CHR>eG_E9TJw_q5+`HHNe1NBKs@iFV)7@8Xvky$>>H!{*h_st561?#v=3fj!k zXC_|hiFSo?xT&NL-r!~AFY0ZkczAbeUKm=EPL5Zo=3w_2NlXrhpnFs0?YB?$=|*!F zo;il+DxrNDc!3CGBsVl1O!$ktd969l5hrv0$je0S_%zwA+p894W>UayZtW8t$hY_~ zwZ03*F1&U)_v;V8;ER)Hj`uL6r+bIkd`{g&Y@+F3LxCB(LQ)HaAEg)kH%EyI#+yFw zzM6@_P8eT$Npt&6(g5v$Bo*3M1fHMB}%``D@CwS5(XZL5yI!NKN*Qc zKY#z(upqzfc(c7q`EhzTJ%ELL!diJ5t|NT&M7w8QwQ*zggYmzD6+`zrs>f3NXm4;o z39_!Ij9HaNW%I4$!Jm9!7dKMatW1Q9VUe;z4_~&TRGf8z=-;=Vx^GW@>JYouGBN_K z85Z%WC9L{~T>U$+DdmmqGPko@N$!y~i$ZSB6l7>gMq_vg4&{pKDf}po+^*3_3VSS3 zR()X3@ewSD@E;{8Koq)(QzicE_G(8@diT!}9o7x9{Kdk(Gh3CEgYR(vOPKV>)4zsl z*<wui zg~)a^HQhY~yuK9h&dkBMpcSmsdP+(*BVZ|39wD@i<$C(Le3E z|2e6G|HmuYfBEpkF4<~A8C~8ECmkZkeCYH68hq?=V60adqImonkiNm^%WAO@KbM1R zK1>PkCac#D7^k5Cvj%wi)*0=(X3Huny+;SXp#ozYgP~aXMX+}>(!FIvV;88>D`~hWt}UX zUYk^@;qU+0m7m}f!q8SHBBhY~WI&v?#G=(7}&ozV-e5SGu*-ZR5juFNcr79MC#@?#BVRW(}4 ztu6l2RaQuA<`a(RJ93xt77A^)pA6nRD^Qa+lXW5@Z!SfC!KqI@W;<} zHD98?SaC&bWu}liS>f7lC4P!`tnV;}JoYt&LJ!s>jB#Q%8dHQ`}7f{etg{R1qi*`vg#et(>)tmi~ zn@Wv8#?O@TiJA^YM-);gHP<1}PqgF8?JXww!VafRJGR~dH8+4SSHVl#qH;*aTjlLc)!8p2c+4fh}mL)wUtRDX7ALoY{lALQ#xL$TqHcErSVz{xx(SNXeF9@_q$Ljk6UZ-Siz zCBLA*V>VNXQ38A6x$DPfc#~2_m!6tu2Uqz|TIf7;drh|Z$NV&3Pv!w`*97k?c)O?e z#if2SlLTY0w%hWw6IpU(wT{OIR?1lB(GzRkO<8&$%Q0;QS!uX+OWe*VnUG^m%8?$A zXlepIfN{a47Qs_+YF!~8r2ecQNfK5W9(@?E9lnl;jXfk|$rv#w)y~Og z?)!5|js&=j=9%i6&1|SQI^1Pg4X7pbp*d(AU$ClaL<$r!f-zq8&;q?XWgMDHO$zS0 zc_+4!e<6CAM_^(b0}G7(H&2YYI)2?fe|$)h=3oD2f%bm#WXoj}L7q8!Kg)F$zp;uzdv6%2lut}-3uU$-uN7iCG9|6}*rLF{PkCT%E#$?Z_H~H-qKsm( z;q=1&ebZv3BTji%8g~O!lV8ZLeaF!*EsYMS)qU02%KPr9V5bK=uTx4Zipu zt46{XX!eDbSmQr->kcIst>B1}%=8qAF|482J>wVjRjE#&j5p0)_iH-4Shik7&p3Hp zoAg7DVJFn( z0VbzV$G@(FTW55lVJtpVxdO+oeE$KmTcF-=_ag0TpkAqU*Vj=Pk(i+B(~WZaT8*$f zu8qq)fk$Xg-l}Tfo9+H$mjy(IP1-=ff`tQkdwju0bn@BCzAv^M@FI?e$((QQ-v>?5a|Y$Y1Enqo3G46OC2YN zI*@ndl+Q9NnT+Yx;MyhgcGHtH&ki`5Q66q1MzQUDwH51U)zsyv?)Ks6E%{4?!rhr0 z&5%~mSfy4asXdkxI~EOSsaVX!Qmk70?%l5~G+Ry42n&#gfQ4pr${uxsytlK+&FLcs zj7 z-r`>8B^f?uK0w>z=xSRW6}3bSHlMm7E7ie~6WZs*b0h2U4{O`uO%t+Y)X4l<`*`D8 zZ5@BxFJdS8dy)&uNbuDROyOEo^b=fir6hAjqjAQQHQmFqHpg*43c&WVJEeGX#K~L8 zW3p}QTQ!egQ_u=XD5TE+VHqC~uQnW>j`mL{f+cbfch3jU2m);~~D_f6NW$Fa-UrEnLqDLO@2 zp;3DdgpFEwLZ&(9a1xgV|YkCm-JOS#f{6I6l-V7et3RbC9sa zjYIdzMW$aF*C0cfDJ1Xz-fBNLu`o()s<()#`V|58ju`Rzv)-|% zHm(6`<7Gbm8lm^@zR*~%;<`WH;pMxfhY|Z-UyzU>#3Heo%I$((xV*sd9bfy7G$)|6 z%ft(I5t(7@m`4pLN|b}OK36KUra66Hs8WR1c(u_J#^PPD)ub6{QEor0a;g#xWp)Kr z_FYgrrON2^X+WeeJ`Z6Z*@NvxGfMHV*FcofF&jy6Zlw`ly=P57EuDGkGczserafCH z^87oX35|JX0rA_OCRuygQlsGM>$w&edDOAs*7~JZhU-ipgPgQsC)O*#6yzfbbWoes;t zjOXkdfGY%1YG*hySPWfKrf9ka*qZMO1_$Bgn}-gEIzjM@e_0?bIA^i#Umj;^g~0bD zfy%gH7FEDHVH{z^fB3$CAIS)RT=`FDwBY~jsp|cA){2%NURb+k&!lNtb?Aq!7|O*1 z4d=T67Q;0L1TfG~tuecb0;z5e?F~fuNfM?EO?NN8=Xy2g=sB{t8$h6?+C!GENf~I+ zE<5Z*lBD*J-~Z$55cX6V&SH6*S!UvD93%T5sfG$3#NxHLuhR?!u<76I+UtbaG}Qe; zA2cq$x;V4(o#xBf>D0qa$FD6MZ%v#b_P-s=JLZonpPjQM7fzVt*%YmNC#0_$lj65F z-5l*QCVvW*y%m&}$tu|;eLMD)pY-LgSspzSFFNajAp9mG^{Pw3S@gB=i~-?RKuRw( zIK!!)D0MX{xYzi@a?_LH?uo1fAj^jH>A%5Z;cB%!v=Nu#e|JeIHW<-q>xdZqbu<*1sR09y?VuUt$ls z*aPL1lZCKSb<&S z#;&>^i}i*32>uy1!xEnAijfLowi>M-k;)Z7ERYUsK!-Qw_0}3gWIBjM8GkYA{AAkc zxsaoY4vQ6oR$m`br>^1*+2H&jx&DY!R?r|noj)W{+4y@+dL>>^Ayj~bv>|8g6`!uQ zqGQmM?~Su&R6J*Mtn?s=s;FQ=(mhs@?k1u3thQn<9euJ+)u0mv*T7HAFXWLz*nQb+K?+@j1wTqFWNn$MVxD=HJ?MH!)m&83antpbP>n|V< zbjR&+qY3%eK?&<_G54TWJxYCLB~2*q!AhM5q0y_07RnJk?_7iB;=hu^5jKfm&m4j#OdB;qO&!iv^X0+bwR{n4-$H8H1 zq>ZZ)4y#{A;*bVH!ZBy+*1n?F9aZ$wX1kmZ->Ctz4e0jJwTq01_d!H=g$H{0Sc__! zp1fZF%ysq-B1i~e=F2-n+w079NxsCSI*{lCHwbU7Am7zs6o!*Y&W7vbOWcpz4oZK1% zSPyeJFd(5QexFQ&Ms}y)bg}3uZpOQRrrwn%$4--8xv8U-e(vsU2N0|FkW%=uW|`JH zbm3DWT-{u6xqwomXSl+$P^n8|F);!(UOj@SMV9y~3LZEZ=Ih2uexA}^m^IRDSyZb! zNj^L@Y2(g-CiF`$v|oOhaNY^FtCl+oa|)n}<^+0zY~ zSU|;u>Os3N)F$oj1)-$yK6HvY)dbcGH7#76i%BuTceCqm zNwoG+Hn6y@Qa2t=JT3L~HmoCQgIO9wGMI(!fr)3EN zOT+z;z1?dBWru)|bxkR~d(mC5o^&8%(Fst*;T=krna{djwDnQ?J`ViRIlZA->aKrp z+~?|be{q`F>x&VtgCqyItEI`@FK%}+BN0$_)cr@sj`F$(qvtwQYY0n8;%~H8_U}|7 zpv-32wOY8aT=L+H3B>zlfiB8>$275U zPcGa|UrcuAAmn>@pSOdKKiVhdpR-tjwOxfzM{8_NSA~u59UZs$19i?6RgI!m5?u#< zejctF{&#EDJljxk1I*m{_6U`6Cj#T(@Y$xuZO9h#GZV;}=8#KVTSs&50KtnvrHZG5 zyyQ*hl}J?vKcQmI^pJKTA~9Z3xb&cjjdWb5Wd&O&6{Ye2q#aw;@NIP&6mvP_Ei%_% zHRzNFVLtCTW)6zpfP`)REmk}02#+hcf5j})9 z9(KfgriHUJVAvCYowcj6S#iCPv>IPq`^BJPr##)JheiuuH^F}27END`sCIbA`)JFa zR}I=d9&YAJ%7@}?8JYN2-+xfBJ#e_euGzNRfg*mgbSs5o^4_uR)wlO)-=AoO*HCJGGxBwr;qX0+p06f z$%)gi{K%3MW*F_a__^e`QvKKFfJzw6S65(pkI zU7zdSOO-q&l?aa~>22RD!iAUt9QbcoNUFzY4>th`lW~1`a$hFQ#VeoPu)P$Inj)>v zN-ndir^U6=Mh)QTbJFyXAKf<@r8~^J@zqOA!aGuMkogbD_Oy!C+(8oJ@%)suO~n zR6%LvC*9obthA)IZY7Zy*;K%00ME+N8KpWGv7s2Jk6Nk1F})V1QYcvUfckYL;S9S{ zV|ZTyn8`1XTc8H7rjXI@%*JXjVR#}msRsBzZ^KiVQp2;zswIuh!o-WlEeZx4GT&FM zEJm>@6!%3_kG+%PVF)W>6ZOc=oo@(TS*{h&kvL->!>v~>89Sv~=;eRF(O{!1<3^hJ z6{H2lN*}*V(Zg&l9m%_FiF{|qXekH(Ip@TRaYe(|ip8etstr0;msC>>cgq&1C$Z(I zMogpsxyCaqT&G@DEy@7gF*9(}u@)d6=n2HqdZwIQG`ajoo(~uRA1$W|*B$Qq!xRXX zZ2L05<7`CkPEXVzysa}m;uKP}k7~77Pj_11SL$&#PLMUra01(#1+SBXk_G&|I^@jv z2dEj%J@x7>VlJc`Y z?9{$3kzAE94QQqnceYrm5}C&scFJ}2##I^587t6Kx9%ql(k*181|ZiE3|x2x5b%$y z`7@9BH9?64h*8Co5F9Pp92hajBHbIPL|C0Ry&vyM;B{D$T{(9zI@JFHr>hYq>nlZE z9rL@l($IWXG2$!fz=@Q0=K4xpwr2byLD(`Xo`^nm_=(WbVsu=T1CjCP64N@#C_gNN9$7v61Y|g0_5VY1DE8o#^FNw3iKQZp6c!7bA_+j`HE ztfY4?&`FYK|RNpqb65s z18#e>VhS3C$Q>(w3GWv#M3z<-E3GN*$@%;s&~iN17^mZQ^xoL~sh}hHvY!HT6@wSw z6q>BC&+1VG_kU#C#DemF4NESeTdnYl^hu=>->>U;t8lE4v!8LbzjS9Rb%r&KPe;(S ziMkkw`wnlRd~~ed#^xpV$^oZ6%MjH)BHyTj|B%9yCQ;8he}kWY&Ajqdm|>9#t2Alf$nL2-_rvVLN3k=asn} zP7;^P(VXB7lVFe8`&Zf8MgEq95Zod@7=>K~mO~(uykIB<3^x7)*0=+GTn<=PH5`Wb zv&#&LVwuC0mM1|=JH1DgFg5x-Mlg7(BcX*)N#CeT@~%EZtT<~qZUpXid#Oq67F_I+ zJgD3FC3xx_TN>@m{Ndc-%*NL-C{3PsX;AqG-guo!_lLWZ5-y6y>#Q0)$tBGgdY4Qx zRNl_CfugfL<51sFdo35@ed6*1maK?dRqa|Ih}GxQ0*4J02zPc6*lVgY3ZxOU9REH( zIMcfgrRG7xUFiz=DpbxsX2PLK>CeRTuxZqw`#oj6nTt`ZK4hp{!!W&H$Lj)^_UMG1 z16@!uXEDsy_sH+PH(?sx1gMs1cYdl2Okexf()yM@Cc)zs>XpmS zblypFfQ1l~Ns6B{Uw>jyx3`wNcL$I>59PK$AlR;E59!`Dd`!zk{~y%oe-#w{k{=?l zU4u7-n>BJ<-c|iLZ#~k{FQ%=drz-NKYsvET*qVM)8-UZ{O82PC??)N#Jlv@KhSBl0 zBj8m-P@{;}>WS(fI)_^KZ7^WLZ06u}ze>ZifJLVOb-!wsDFT%*tN5HVtu#;7Y54Pm z?XKAVi(nOhUxvejBBJ25v3xt#RTBtfp_o`E^Y#x%?l6mA^V^=iqP!*v@KeZQ_e`r` zINfvst9WKWq&)2ncml#VQ|%)0yu|Z0V#e>adUM8q?q#yYa;`LhQfdCeFxp!1C-xdA zvpMx-vYB@^qIY+0f&h-}t#dd3vICV4?DMJfS;v^(* zWUo)4zFf;PGeUa>?mM?nwlE&HCBhI8gtn$f-DX=Y$*doe=#R;gu-c9$( znp%I}e%6z*>C-?Ju>#y)A)reLL}AAK}qyh$Q4~{Cue< z=@(`nEdTZzdi6vs7T^3S#Zu;le$qc{4EicF_^k}YYL$jz{oe*n42?Pg#@|O#5{vJD zVU%+{N=1L=zcx}>R&?cVFhJZ)TVf7z%IKKc*e5?RlKNS1&X}hlKm)pOg7Wi^P}y*8 zWjrY17Q8n0A%Yqh{Z91n9^ruY?HTY)PYxHb7%r2CTYJe1?Ur|nDczosx3f8Q*!XJrRK&6Kr9a94eXm}zi|CxP>lc6mJ7+Ok*xnzN>pBBE`HrDWIj1wn zn?!%Hb*x?P;4Eys!yJ>f*zu-Q8utCTA+qTU9xvM5tpPhXX&{+WlEZ`@@_l1@KJJEi zPbe0q_soadA@!LnfMLi!3*uGT-P6Tj#^>xlSXR$T(hRW`1HAS z|2nmgsOkH4rhG{!?YCxD>K=jucO2KwnQ@mT%$sLRYAkz2z6B%{Kw)qQ3pG5X;=lq6u-jnoG$EEt1q70J39? zCKH{p_!1Bn$fs?iy^7x2ZWinI&u%VQQ9?rO&pvb4Ey+g4*NK}rUTOIyj0s3+*rd~N zB)>HQlpgVKp!$YG_(xGxICxL@y#~Yll zvDoqv;!h-^ zIBltfp0w*F*VQ^8`)-JBp^KY&CMm(1mqe^)dHLqroX%gco zBJja`r)EUx@WS{8uu1f-_2Z+BtTA5nry#42F{)2*pI}2FqB9@BfXWQqbDVuN`HDX( ztjgck9ZjGdC;Tof_{7l}H#L^!y!*+gR1U)SMUVCtno};=d9=zS9L;F9zs~$ zGaSr*V{!a2;>>Q09TPl8b#r+7EkE62Wqo-Kx!cpQs1}ZfVZ-fXPZEG{zin#nP!)^MRR)EESaGP2951>7bp_mdIv0` zA`u%y!JX=}7`>S8E_8cu5>8Ydaa1h%DxLOPmq9dPt}-!W>t;W;2k2b`F3493SFqyZ zC&>l8D~GJQ+EWLWG^c@}G5>~mwK0d*&sqb~p(+*?SdonOV=|gQQAWCIEJ;}v6wHA| z>j@1zQ{swyITQxPd}Ls!vj-fB;H`j}AKQL3@&}hX>dr~EHy=I8YtLoaN#EHBeBSp7 zTy*jTUgt$jCnU!J*A|&2+OEs?W(?Xi1RYzYh)h;;#79eCeF2$nB9kYOH^m^7|@YsVMB*4H`SXZex8YyNLp-Vo&u6RXYd z(b=>mpEQAtB=Uh)lI-|}{Z!vcicaMU_Tg(2a~;|ZT29C}lD#o(o1 zpCE+Tl?_mpinhFZNrJXx#pjkdMj(j!*Y|A3Stxh)%|bJgbM{BNNpgHOun9l3*^Xqy zJ9$X;((!$RUw)!Jq~u_(lHKt+uAy59SeaS@bHuxU-eSZzsK)S&TRvm^US}taoPz%{ zC{`;@V1U(JcIK7ZxGpD`5?=l!Zn__boEZKHkmP*NKM~=7pSqcl_Znf8e=l%HKpt_I zvrON|ONOR3`-k+&o#&7v#`Xt3)3)j}zq#qsS6~iwRgP81@TR{oc*~CdWUj2j8}-f} z-l?!lnGofGfIA*5+clkO!J^(JO1DbgwG})AvEl%*=PfyT86rwC$!?pIQz!VHGd6a7 z<47T2mcIm>!u$1H-uwgB47uqSV8ewn@wEE6BJ}wqPmJPJckHE^8E>#C9A?9HHOJ;u zBESNX+X1EK=P?a(YCuxpcNIfdG$`-^H{ma8eeAPGN5ET{g=IzFZ{b8s6|(OWr15j# zP;xiPL~woKhHK2B(#~1?Z7shD7~7%DA)@XfanU5`cRq2z5F>Wms+w*z2knJRlH=yjlt`uPELfr?NjCJ-i zG&fvMOoQ`Al(1WB06>L&i}t+ITv_%JVX2402TF>LD@K>k!Kw%44_?#R(cL`^RuVQe z-M%`vCAezk=bT3NY(lakvlN~dX3#|j^V33-DDp>9Q6T7_59$=E-LLuTERaKbdkmC# z{vQvo6PwrXdLp!){ltcD+f!71b@f)Lnnecw@Wf0t$Ztifo6;7Jc75+Yek~DFEdoev zfgYPDp4ZZ(8j-MYs?`Tuqr(%wuT~h97y4oAS6^b9^h>Y}<`-6tawk7cJM)QRd75Y}BD_IOcyl_r4i)9usli->UL@xP`Gi$kqytMwFYI9 z*5p>+_}jKnJ{Yr%+PNy2c?hd!id#4`wIWQXwbD=g4|a`tvULj4FUs>pydR_d8A*Jy z{O@rcemgb!-Y06R_gHDmST4q=6mx|H@hv^4!5Zh8oA-{V*mpqO2~geScrxCw+h?36 z1xpZ{>T%z`!8AO^vst*U@QW*)oPxctq@J;1QjwA6&;|U#aSZZd8@~ch2s@$-xOIQ@ zX(UY-IrWe&^$nn(pf8xFCcU*$Hb?pp95o_C1q}Q*qBdUOb3dSJE= zVt+I*_WcGFcjHn3U>Z}dPBtRoN3l)t5vL1mck3=m+mmm0x)Q!aL$P}VuQUIyYyJz9 zTay}88()ftp53+Mh$U6bE8!J}Yn_Y+i;6V}dHwsMoXbSfL^*R;6>@AnT3OfLdyLycwbRn)>ClD>rmRhinn)N1AJGrY%?{C|d? zRvdgoY?^`3wf7{};$-Khv|1*kc89OOmIXsur#+3FhP$M_6Vim zTSi>P(rmWDW)hT{p3TAIcb$EbM(xX8r7434c8k|pBWzIt_XKgXEhlSlyXv*Qqg*e% z-2~e5h{^M7lLWXtZd#I>Wc?u5W)@rl0%DNw;jT#;PMhf)%l)$q_RjXccm=sv7UcyY z>ccb8LYchK?mh>8UA~XwY4}9n23wC<^Jf`dJ=G|ieZ@=fn@HDmdy&FU?g>-qK}-FA zs?-1CuZS*x^(^n_W-NjoN22~MOkbe|2Qg$I5AcYk-aqSy|ApFs^r5Qzsrmo;(CQ(%n&MKpNwXU8r;z(aS5!ddx6M`llU(Gqv#6*iom{iW_;pGxSFcQZ49KR z@;CA*nZ<{g<-q4@$MFLl7;l75-e6QDl#c6cxQ*%5_C=DI#4&U0`H@oqJ-!^uF5CWE zEsX8AZlSt%FqY4+weqQO^KCI}tl2Y?ik_Mab=+WtS}*@JBm=L~dq@y-<_xsb7Z7+$dFce4@!Pq zL10r@f2@0@8rQoo51_hkX`;Hx1LL%oNvU}HhfGcmu!;Lb$Ji;4aV%^#B6G`~d)aF1 zV_BWkRTXzb`fTQT*%oRrjp=K_@h&NuVoD?js-?4-7K@IHC)3KbnJinz(!0@CUSmf$ z>R%D|*E9?>Eyo*gYhna$nGNQN2wZWgxn&3E$d2Ct|75m}0LQgW0-$Mg&y)XeCRW530D#jW>CvwCEmZEbJSCn22KDFT{Q$5voFJ)C2D&)RNQO<)kT z;1ioUk78hV9M@-zd=KXs$WLf{lrd;h9=)qBeFT2^!gY_177nRd2v*EVeuI z>kBla;73tgfg$eRoz^eKX`j)fI(7rj-S?ssbuv zqd5%8gy27{1uG+RH$|a-Qh2kvCT^XwfmH`}f3(-0Vb?E7uaz>h8;XQN1!dWp?QSwg zvxCV*gVcc;OHiZWBfEk;|G4a&ADmO^UnEifs-xI(N55Xo3wucG$crSZXLp`S1&!+@4Hd{cFi=`Iwem$Qm8$ zIz|u`Lac%)OHP^Rr*v3^O{qU)waqOq?ZINRaX{m9KmWJdyBHsw=Dy0sYL)+m5j-b4 z-6jv;BTzWn?AOB|H&WN|+z@urkHvC z_3N?o(D9R}=Ku4D!y@i~KbLOv)OaGgvtLCE#MgFRW}R3(T0i(Oo^(_F5VN$<>}O(d zsmz|-T}dG1%&+SjJPbBNDR06xQDNhH9a?cbOZk^ZRf!wwe^eEE3%BklFYqgQAHD^W zLR2ks(#mqpSl2g19$(a*NU)b(jwVd${ZR`Ep$n@TSoH)nWCqsllj5W+d~zf4rBl=R z9zYti4gGPbU3tgG%hLr$McXAB)%U1PbT_Sr8-dd?>6ac|>hp~@$YVQ`lCtd%5^T$MX@hn&}rvftYHD^n| z#|qFl@V0o8xu2;rU#Q$sDR^cib)JiSZD9AFG5EBd+df&trc;d$`CJ!Ar?LW@h1hV? zf&uz0dzrC;ux-b;?brm0_NP9EWlC))~W`_2Gs9gMeNa_Qky$3C2*PkFB$EsT6n zM;2KK5=Jg|ZVDH&4DuS3M%D+=7qjM4*H4+**|;0hjZRj0T(^>89k! z%E<;Thb=0Q#p|2%>K0VMX)ni=o>HJ2i$qJ=tyuUESpUsj09iH2@Wigum zd&9?>gXWbMS6HqV#{`1ULYh!IoWg#Gr;`KgR}2R~#THtHS{MZ}Hxofxben>2=78=_NF@U#)y4R42#z~|`xL&dt!fH?p8Nx;w0I$ppFz$8PeP_|+3Jjc8|dx*miRu=Y3Omyq~S;p z3a_1wO;SGUC@kHp)KEk3A-Wf*d-q~}6KS%pLWjrv*DR{hom*Udfi4X;-1uUiS^S34 z40(12XXG)F)Ad<5OK)PE9L6_`?4|}r+-$s4mDstyvA`S;VtlhZEXH>jh~GCTwcTn- zZ!TLgv*jUakRl=!>?*P2w`@Y8P0o$se@dR1BdQ6iSWZIfm0N*z5-k2Kw*0lu=ie43 zw(ElB_@|vV7HuySc{9L1cvTVU+)Kmkjg_h+B@6+xM1ADDKgA;C7-L!zr!|xmr{I&} zq_x4+86VzX9VlBEYWfj(Hw~#2*7G*o?H>$7SEEKxstn~6_ZDYLdq+&|j`o|mTk^g_ zn~3T1VVkxVE{zU<8Z2LRW3r0gb;lKKCe|ZV(~Y+1CIpq#n%pf;)NCCQ=eI8mp`UX_ zLL&UTa~Ow=iz=DNv%q(vzw3FgQR;3E(Fl;9g_5hs`lh@9?!xSCS#;>@C8#@PG=W#? zDAC(v?_y0*=>S7-qW_-uE%`ylTCBK1(dscY25-YDA`H|b#TJ<*K_xEfHFB(Pd?<@KKx^2g1Hr9CwGi=z(Mti_` z$l!ZybKCbKC$s~)LF(sP1k~HdUSx7SIR3_nm9Y$YaaT6zq9P*)9%@2_?$qzYTFdvy z;S#9oJC+EBg`5`+YpupU1vq}m%sy~cJ%Jm-78{kfR#?OQJp3mi?(_Bucxe*m`?qJK zqIJVG>?`Xr?n&9(#))^4aY-qgwk5Ms4j{A=zfYmXx`25vDz1FQkKRP8@~SYrVceAn?)1C4xGaZ z8bYv!c(CcpudpJ0MQT0;q~93PW0!rqxGT<*&CemW&m@Wqa_1?fE#AXru)_Ey>@(f; zJM%i-A$$>GNJLARko>pDBae8_5Gfry$Kp3Eof`b?sCc;Fn?U5DC9a z{V*p8E#=U2;3T<`Gd8HZV;WZBnTncZ4COx~bDE{nF=av14x%B@##XOL&(hm3zhNXW{9+ zyUPmiU)NqZh7cQ$QhG5kIH*mUc^Dom+>PNsf%fifi&R9ebdr)3+3#rVEf6)g zJU|tkuM@G7r`>8&0oZiK4yH6X!}ic7FdoJ)_1R)cuJvC#%OfQA?3%tSQkTN)AJHVZ3wRcZ!f1aj+<^bpy!}5Tn*SW${vOfP{5`F) ze%T+2mJMQrRKGp^+GSAFiXPwmv!Z7zFFpR15H{=G=eE?G;>Tg`)4st$JKE}*4p+5Z z1;63>zZ?Zu#i_!pJu}zo`H$ob#hoxS-`HGxEE(B-ITLXk!GHKEG4f^1ld<4Je<;;} zy@jewbt9%r=nLa7HkwOJv|*Qp|8Ik~5o4a*3Vz=vXzxUci{5!;>|zL%R2Bb9t;h2r zVu1#)V4?VOukDuj5}gk4hyLSJyBzG%NwgoV)E=utWTyaWh+ROjmw&}EUBk&V(2I}0 zxcqGa(&C%#77I=S!?&d@egpZ2b16f^&pcXts6O6A76C+1p^g}0U$j@?$z#&e1o~+0 zCPF%|U`flx+M^}+Z7Bey5}ldCvDAkpAud4^|I(*EkU0u?!)J7tDGTrXa)nC z%O|=t93Qx%taF1_{I;|u69rf=Atv07B z2JHb78SkYxZ_vVkdBSvM99nStgtuh{R>cuBti*YdxO@G8`7uC@8xb#VqwEE)r6T8XL8)q8Dm#AYNzLNey|Y#wrrpMLfDT=RWsvd zQoahuSipBNC3SBjk)}IZV`AogpZCSEhy=b(?buu`%H_PbpBMjw3~%Eg4jW2pc7h=5GgZ=Dir zq@h!dE7H9r7p_*2Z$F2a@si44X>-yJF|auRewD+d2iX$beQfPcWIuGod!-TbMcRkT z&w$;yq}&T=fJEjld7hqgFzt_#4sh(`^w)BP)@P8s_x8xG-wPU($P20mUuZV6N8XOe z_B68bsuT+klZKC-e$lTT(+2B7TI z`>}UBb}|QLv-b9~>=s8)p>jy(XOpEq9)P;#n~{>@-p8=C@hm|GsJ;RJ0iI?c;L00*<9Dzp3$8g(m6q!O#9#qy1U;1mytGTNv1zTn!p7b{ zYO2!JTFxS$Dw>~mWxG_IS&HFh4Y%|0%=xXM%1MKfEX7Z$TTU68`eMciNbJp=`a|9VSdC7euFPngRN~5u28ppWx&>g zXYJ<23!7*RODQ5E3s?_A$YJlM30T9~Uvf{6}d)R6PK zUtTkZIJ}?59+s6Du-NSBrW&$(b?7N4BM9G3Dq2}ptnL=vHD7x3o^o!(-+$^~Lkm$$C2cVD-mmacjNZ>1m< zd0QsggKPcvK7}^=;VDKnEE#Ja_(B14jBZIg{dd}bPSoK_+OP=gf5dYA&!V)$e_LVO z#_U=+K4VE+MWkQa!~=>~GvFb?m`^Nz*Loc`z35_7oXFgHIZc`?wbsQSs>NBO)9 zsI^yt#iDvJhoH7kggdFSki;4B$`tu8mjmGy9(es2@k8K`=NeAamCu*SXd`bCUs)@x zolxxrn_8QF6%?!)iq6XpgZ|%@eY_QGjA!{4vV!bdZZi5LlonrtGCc7=2pJ>Le2av<{_QC&rtc5+IVaD}Fmf}tLU52}+5i2s(BN%<89ZjJm-dcyvYZ z3hN(Po8>>W1$it1`nvzjko>HM_ITuyvM;cw~g&LIE`UWpw8H7og9KP@{)Bg&aC2Jg_uT?VED3sHKk99$h|Fq;-_@->f0=iFOTd z>_-tAdMm41Y8cRqN-C^(aPDL!0K2Ki_$W*Zm%*FT3lmcQ^MCjgI8<33=7C)VP%V*zI4)**?@fTe9{l(tE5_35)W!bjKo64vT8z* zX`^)UyZ0~~R{6?Y;p$XM>RD?xasQHLynspXbEozpu<{2Tw8szz-xuQ^gb%zf{cGxnauXgrgTVdiWaJW`ftzgmAo-=~d^I zU!@1Y+y;@A4)QTpEy~=ZQeiwL7CCZKfw#88XTQfpurA1xa}unm#TRt|+g*+8^JAJO z-1Ey6LI$xSujj5~q4%O@7C)C*$4vWP z&Avk%mB1nT)S{qT$crykfWlt<33CquuoTatkKAwUds|aAa_l(mip#i;OSEb z9vjrE>r~~q2+P=FfAUnZvMtwpx#KIH^6c$V4X*m1yE z%&kQTC(7WqFW;5q@%b3-mS=Sfj7Z+-+I2mZEC{SwFzI&Oe6If7Ha+4Hv9hqMp|9Jx z(ddv3wkr7(=g1TKupZ5h016V!OT4A$i)p=O{hS;+djW%cL0rtTYwwM;88iH?Ct1 zf(iNUV{S&Jz~IkyPZCnTU@LR*>be-cgcj?jswdwSI#|Jj89iw*n#h7x9({^qLR zgAGi>qXxGL`bw@~B~}G-**HK(r<#!B7_ahz*!@XjyF!I>XEo%vnQ_-6uHdN@!wvG- zA+`8opn_{~J27bLV(2N!aExf*o2YI<2;QJotRzJ*vruDPu0AR8Bn3ogpVEK>sWbOg zUah3=w?CFOEMWM{8JH?*np>fJMMpP!=;m6ZfZ-;QTuvlupS?L^=wuo?$NG78XOLNDH?y0nBw;AAGlu3I+*K$?gnZeJI<>t0D(XUZM(Jp!m!hS z*e^D5PZE&1DX75nD46YWa312)b?sPi45(JwppNw1gZBGhGy2EP6BWp6Msv=AQjX56 ziBylJ{>b5F2bDPPHcfVw_#arJ)pObg4C|wbNtsDHIk9%pVZ%1B7lmWw;t+pf$Xqvj zI_)S>#-1%Eu2tID%r!axEZa#-&`>TUL%bVpF1tIpkAi;lZHa9N&o==+rfV6&#d&<;_uKBz@7H2n(n z6bkBmv@&hHJ^@ZG>&YT{>1@M3ceQ@|z7t=||47wn#IGou)m7bPhblR6XY)g(E06b~ zdcSCEzI)0UP9xGciOn$@R>(7l;vDC%f^(WJkj=d+x`HMS3cO$JOae#I6da?%Y&*ys{;i33#pR3QSC* z18qQpkHn%aN`CN;zS}BajSIqaWkdxbPcL;^_=?y!F38h~5CJTzPsO4KyvOf6j=2qM zU{7oHlcC&`hbZe+r28#t<-TO^{(Hqg+pdFTMXT)de&t=WeoQTkB-sZ-U#~IP?z6ZW z?3u9_i_$;Ub-3oR*0j04?t(i?(DEEwTk1DWl;;Ki6mPU9k>_lRG& zyLl1on6ng`ly|19el1! zN%yO`#0}BBY)0kHIW8?Zan{-wQ3Q8g@7>Z%`(@vA=3hH_gwWgBVsrb85ch?5-#{6J^F^+WT5Ynm1>D0*C)N(h>KXOSJA$NJDk>fgilg>3YSQ-&~so6F89(`>C zpD%Ti5J0c<)T*bdL!K5OydxTh$s)tW+!9TLBM(=}0xT@5ljvhz-gnr<;+3Q1*6kOs z0|T9JAk64aVsR)JTa!@}#VX$q$m2+1e@zpFQCYpgX{v#+kTVF2#C?cVE(0%ZxY3$(ckdF13I_nQ}+vwVuCi#Eq4>|ts7 z*q6V!ZJ&eU?q@T>GqXK(K@)?0(*u4XP^9v&9K(*y)O zddeEY5w`P5wC(eo7}^ZjO!YnXeQmR;BP5$>o)E1ui^_gcyMGH0^=t^Xj^*LHKu&QJu_k%cK&|A_xK`bJl#1}Z z=T~->;AP+yt-~K7_LbbPXWoH%VW~{tI2NU@c1scm+0lj^Apt%r)T!%kUjJ;bu7J-RTEcS%))c?}4XYK}YH#=Mb!Pm@`BmxHOHvDyj1*GHg zGaQf>M}s!FPJ3XKCz5Y#&2w+m~fLhs>9jqB}t06z4Jnc9l)ZybRc?TxxBz@!N8qQAO~%aK7>l z7CB&h5`QWkfN090(GLxo{aG?>SyHy&SL@K_dw8)8qIs;9khTMoO{4xHs>%I~i}NyM^|Bn6dONH+m<(EhV~0X#dBgy2|v@ z<3+x+Sjv2_rAK^7>GbrxgJB&zCR(L#1Uu-P%>nm(Frh!Ac)l92r0k!|d${9#eAF7A zQc9QrT)ug@FOG~})=aSH>x!b{iUg5Sv}4MBczg$+@*+C?6YTab&ZuYPi3n*!5bnd@+#s;xU5X3nZ*CAQwTshWN2!xLmAsGG zJbDeWdp+u}h?<-?ptrMRGZ)<08+|Bk+GSPA;Li>&Xdh=$STSq7s^HS$zF{G@eVS^# z6ue_$SD%M}c3oLA6q46h*1)!x(V7sTC@w#UD_1no?LA)9Fx!>%XRQ@`AYY*aepDNcszFs zZt`|Q1X~nz)rZ8Th^YC$MO*d|wS3amNArSadP+838Z$+&0dAa4u5IIJUT~hkD0C%H zhJL?q*7Zd$8V9HTn1|I66-53UrZ>W(6p2R-GlZ z01a7<7d_?Y`|b69CA86iAYziAbpy^{iUNhatninGC6R2D4rgf<6h@=CHk{+QDxrx2 zTwPAmY;)1M^8wGwY67065{b?5^7>=-G;>U&#Ka5$p))+>IayB!@IFAvHlBEwOHk){ z^omt;RhnQ`00P8v%qIrDdK3q4l7osZ{Nq8;75kSj@uqi2bokOouEuG|bt} zN}Gb}v%Y_@N^CxA6UJcm z3Lo?L_f~{Wk#fp_itWdLzqNL$a2+72`V)6kR|!?-?Ad#vUICxPTf!w>zwT{Kny0Gi z`}2VA<5dnV<{sHcF9D}`3yD;PHK#iUU%JRmzAv&r`K>ikmj<5K;f6}*BOlO;FPtD5 z;*`%f+52=Z0{?J}7R^L3*{Krjoe`xqte@5%mES+wR1w7Y000zEH3xj-q(Qdb2 zL`aCqW*vd9v`ufFkBnnkDj=Y9x>K8P5Bu3r#2>RZjr`c>7!D9LHyBG+T>A0Z;wuO- z%=pTHN8vRQ{9M)p@^OFq<%l{?&Dr`APC5&E@Ks#9nKu&4Tntk=x=X)lW>B`PR?w~h zWvy?_&TFO7GAPFK#yi&1(#AZhw zou}Tm+t}1ucBCKH5jW7_Y=PI-e>(!I0>QC{4(#GPn7*$avIc8-!UGQNxaxGyo@SfI zX-wM5mD1$F9{_V5a%`;RR+aYbhsUiBXsFa*d?cWhlHELfeM(Oo2rqLY z-geX6vaOcQj8JL}KwP9XCh-Tdbs>r~uB*t#QnfWBRtFn;jPG%1S+y;RW}%<>@vS{p z_!9LJCUwy7;kW-q1^GW$*#t7?2ogH-H_!*k7bjwYOVuIt^;JtO=A}%{4nKO#H@7xU zI!qpvJ@#e2@&W`Dc)G~O8yM%J@?o*$%zmU+wc5WxVuBM=HN=l-?q)`el!6hjxxF@Bv-U_gnQ##B8P{en`Av<$=l zqrvz8Anq-L;(EKiO%jqof+Zoi1&847B*C5F?iSnvjg#QP8g~i7-D%vL1{#-!#%bK$ zCDZwz=e+aGnRm`i&096|rK@Y#{?fa5?S0>Ct?T+B``3RBIzxYDI=}waz9#PvtwF_d z7`Z8f{`1+7?38oN{;TDE@-J9X2B!$gH@=O5&mtK`;{;TpC!fr>xR#V$MK-RIM!(Us zWNm-)`JWvygnVf|g&zj*AgjP=TV%8p6hB3&$Q|jeLw7`$pqsT_(%Id^z~nD4YQ(VD z{oyhmz8D)POuZ)WSW@p-YsqFWHPiX;{-9LtJ;?0_Jxo(fZDojTj<6+->qHhXtETG= z*t{Cvlz!>>xs#84G~mE!yoV(QdhIdb0?W4XC=-1{eRo{9|1mBqEvn$N-Ed@hizm*- z{PJ;P`YoIP##G0}r2pv$uA&`9%3!FP!u~62b&C<)HzLTjsl*Z$pXx4?y88J(Uh}=M z zH#q_WAEQa4Dmao$u*Go7>hKbqia$`Nj2}POp>Xk@YY6gm z7UJUdAt`t&b&x2s>||%h&Uv)=3iZYxdv_-XHRRWn$sd%6NXL78f2?b)@=r8E?6Z64 zstLIw*2e*y*6ZQ=tO{N9KXp8pkxqVMclqktylAry)VAE_1Yj>KnehDOj*Gp>ChrV= zv8Y@dc6R!6+M)K;*1M540GV_Q%x&2%OtheG@)(?i)eE=Va!@wXrU;Kxo6Py>oo#cx zKKyR$Kj6f>w@x0x8F3!J`>j)LK65onQ~;DWYp(rZvs1VK;EDbLVJ$Jx9qS#$R>@G* z(?@*0#QB!3D%B;Te%h&0S@fv68~)Z}fhtQI@wwMwx?);+rbb zO8pO;I7mc~WD^(CY=<4szb+}7WMrey`6*v1Y{ggvG-S`h52f}9jssAyR5C~V z2g7zeME&JH)QkuzM;}3xcNJAnm{@k)9;YTJRP!14Oh&fRvfa)YEs}gbch7!5sXl2M zrk(?}DpV^OkWkwu5r}dPKGEd9qqWSPd}@Dn?z+5Lj^X*OV{oqH(XT+qf&om=G!=im zye+SFBdqVY&H^(D#9o*R>D~*KlSz1HH)@* zYc?k2GtylGN5(yi`&0swaSw$wn|)6Dbc?r-SSf?Dd(rBRhi%oQzhK(oA=7<-a}os3 zJDP@`5OakMPmVt6dG7xDRCo|Lek>agSsK!H+!1lF%KjEmrDMJdA}lP0#Ci^@WJMsR zJzUQ?!3YP#eVk;xLYf8`e_c`w^s2aAq{1k@(1o#>_=b=g;b!VIxfTYNKTJS_m}Qm?7zHV(kYg5Bmp@4NpWPHGdDN=g%B}v-RKb39p&f7&3z4gyfXgv-@?!MfsbuDPQ;l%3?909VMb!deYLOfFbownSnwStk zYqVH#ExxU?$L&tMhLK<;{TZ8}BfU4#uOj(qNc;J3mR@@%)xxmUB>kw=asgJ+ z+KzXlfY0~pm;w^KZ6Xco@5r9jy#C{oFSIdm*Q!#w-HKO9y>Ms{K_iMz`b&C zJ$b%2RG>@)7_J4~vS@;>{XvoCL5@rkm24dy&*F(h!6udmlm^e`PpY}&?I^UI7g!C_ z!SjPQq-NIIu|Ruv1jzvkR(I>lsm8uFNkS?vlYTVcN#E$#`Q|(qe$$R%yB5IO#v>F$ zog}AcJlq+j5R)cbfDOw1t%y0{qt&;dyAFS z(feGUL%Iq!MXdl%2rjq9*3i+SdG3*v6I@rmqqRZ%b1_5tbi-pe+Z(QL#^uA4s^NM( z1ulo*?U$Q(w3*9@BEM-d@eA_Zd^r5=D|2pz3Ki_Bm3mylBU^P#GW|x%%N9?{jO{G? z`I}jyK%de%?2+d4$lHLHsjS7|(~HKh)4maGm_Gvn{C5QW*}csB4eJi{3Q+f2gR0c% zZRu<`mU5TZo7^I$9&pSUQI;<9u{`0A)n9hzhJ%M}=Q=5797=x5xyDUvK#x}J;{XL5 zKAsOhGiafF*1UR&2AZlbPO?pxKYb=cXJ{sAuzojDuunx5@ZWbWo`j5A-os4b|6(dX ziP@57!v*~o3tECtYMnHw<-QK4g`ln1zju%r@<43jbWZNSnns8)vhL^&1-H7m-0~qk z2v!-zu9$;%-g-P=sACHYz$VcgS+cu}735?EWK`)v7S~2IRdDcEJ4+IFXk(aJ(HN4U z#@?0Jw!eJd&bk0{Jl7i?RJYii;tUiDef@QB+}h?K`o&Ca)bfB95&{m9B{2=6WOGyL z`v$n>za#z#^2L}02>T3QY4#s%dua=u?(9z6^}&vqo$oaLG0z*YFH-_+Jq9P`5CGTo zsq$g(pgu%h{ZVbPxKX%hE2{l;jgdSrJnVJ@X}H z;BBs(Na{=~`T^njBi@a6>TbKt=&I8tK;zX92w$PN&@G2bvyfa1k0T{?ijU*eb@`V6 z66Hd~t8A)Z%DE@bG1>Nj%slrWlCm=Q!Y;KK%O{FU>`ZDCjjW&CX0GWm>iD4%6MBj> zG~2G$!F`T1?kHHmy}1B%xTb`JvWmrbr1T@M&GUn(WugPa~YX`fj0vt0W-u z>O})~qBPG1bH3^`PVKy}fRYtt0tpZ-lb5&A%aGs67X8&#MkIOaFHKpk-@WsJKO-u= zO5iXFaFWGla?MsYp`Ko(my8piL9EyHU|7-{_B)XW`a?RJg?om;&%#V|drmNp_vd-VGK&|D->sc;PdcIm`9+YEzR?b||~o$f&&_QU^)3`as} zu5OC;mMF~1O{n|MwxY@ago&Y6@n>4x>bu6d1r1Eo;+oA1Ti5=W3})pomt)$#)*X@v zLBHQ7ns@Isr$h!r-7+49=mDs+J_!gGYCMW=WJWXanVQcRh$t*O$>xBrhj*2_8T@k+ zkJD9UaE=p$y?gc=eP{l0aDTIY%?f38U1}Q^5|xHRfl`XjFwlN?Y(7ey4uUJU;XR1w zGj1*$z$mCOS#3knKo+2s&Z)sQMIkJBh7eDun`1AdxpXuuE0*0ATfWWA=#LTStaocg z%OTJjzB2S^1f!w6^5LS+#>7;1N^uOfw|UtFjN2Wq{JYLHSEGN}xUVAlEym%rQ7b0Y zxg)C&|H(ew*5-ghUbPoC%3QyMec!J%a$Cyz0s77Y55GYlV@L1mL|_94!&=>L*j=H+b_9GL5sewMncZY(yJawreLtE>XEtMp`IcfP zUp&DSH^;YnADf!PBX7aItG9qp(kUR<$qIwg_o-bW1o*ctrAxRyLw>A8+IH}o9b#=G zuEuDv{yYgWz?K-N)2@xiS(26Hi~}egWH1xzOjKAkW_(gTQL-h->&|-k>%uZHw`j|J zLc3a3D)ai6FwOm?=DAwjn}OEpv?57qNjvrPr0_t+wvkXu_mM5%LQlYTQ6<4~#efO% zHEPpBUtQAGykF_BN}!n`ueW$;EJ?{mZ_Q`v+8?hW=#pTTY}`1LR$2&DPJk$J0NnU| z$Sw%$p^Z<=OHeRafx5cPbzz3Pej>Y1y0?_!Nv`F0v@X2cMw$sdE@5Bt*M)is3(?;p z2ECfUtg`5495HB2;5}DGDZ+GpHBJJmRm_ z5Ukgdi(QEQLD~Iu3Ipb--U1}Mf{IOB*cPhbA-#jAGB<9TbsEtOlKlC#v(Y8Qw}T5C zr`G}zZt#6@LVx#-LGPh{klSt9$Zg$Sx@X{CD#Z>L1(TCCY z^4BRo7zC%{@Jj&ebikR?PFcDNeX%!I|9n!$f z-UvhN@V3y#eHlZ07wQ5U$1iU-aD31PXFkTYe=<-PQ9i zwM#^1H6X>5!}&Y}fT|_p^DUmAWX39AE^D~m@0P#7=o=uZv;A`k%dDQyfe_A2ErIb`--wpVrhN&4GM{?prs3$% z)hvg3u{8C5RAzX1`AE}soyDuGqB*-bf+;K1C;QT1sa-a#YIu4#)P64Sp@FKU@$>ch zhx70_@Jo$~XaD@ODigZoSbWx#lCdr3u^`M-0-VkA{s<*mbhBt474^TB)c@TH@IOW} z{;!H}&;J?-EdR;~#{M-!h+{4ee-Z++@e~;>fe)%hpJ`>Ff zf+CEtVg{7&VKbk8pLBHl*)hdDwlv#h

jf0Pr-=Ijo=4xYC>PSv&g9aR0-PGBY%}n|+LnSC|aQJ8}?{>4|{& zK9ur2C|cjjG5*RNt{c!HSrE!<)6kSyh+ChySTUOcb7yle=S1iXk zq)h6}7Vj^Xw)4s1#79p#Kqli_b{lTIMI*C;O6KWe#5IKLYYz94o|9vW0HzYtV&g9A z1ypnLk-_rc-x}QI;hxsJFHJZU_dC1+ETCSAL+J+Tx>lnR#F9`<=;4H&G9hEe$d)g+{WC zr!FKPZUi4yBFYRT`dFXpHGZT46guxxI8fVW2r zQad~ewR8d0%l8Q`#7;yLoV>V1JW;FEHT!@_KSvmB$kyE;5ot0>q_q;0RTK>Vw#cGW z;(R(A@kP6^hdK?ZMytMIWT8)j);uaJTd>OVgi&AEwKUPn_g_V+70h@_PT&t0YH1o) z=_WBZs9rFvx{_%u(Dq(^sj+f|&EPr1X#b#SWxKps0)HBBcH}eDwooA2F?k~+@EvF9 z@zrW&$pEkxI3NN()wIIMKNBia^Pl@4(C9^ch6^h(paZREXotFlm9M;Bv6xfcIo5(K z+-|J?F-G|I+ar@hqM~AueR0_)eLw8nWm86~#}}m3#?Vw>vuShYJ@>Y)Y>%PoMM#9| z?yG4Re9p6(A3#=D^yNrTqy%+nq;Ob1vU@q1{DV-4Z0bw|qMSL32ajx-^>CbY2Rztt zcS(lJdjpS7oF?mGCwukd_=?Aj1Np+11v9G=KBkv>sVQzc>yOsg)~xFucCFcW1XNnL zprRJrPx=?Z`L|ZjE{h`1*RMLb9eb2_B{t}C1xwrvK(}O)1Tiim9a3)tjSI_9|inYcjQBwDSO{PP*XN zH-1GZ?am&2ykDj>bZE<%)C~hKCe_+^8zPoXB-2%uKFqtF*3wSo+ViMaZb_R<_N-Kw zFl~u;#xn}n4E8Y8_?HMLG^CDNI5o-7E`Xa@o6*VG6CZ?cXLsDu+P6LeievV6$q?VUn1Rq^|X-$UuaTYg>839~5;gSj@l|$0(+oT46P>2}j^| zbY#TY;(cr5-3!g@06PI7O&3yH?EtOWw(Auf&TLoZqE`7yMuYXWju3yy13f zUCErFLd!%tu*+n*9LkdTf!>~F@xFqd&D^iBaE$-{rTv0LB>hY$)Z$;oizk~pM7S91 zPPWo68mJ-&afZcp(-U{jRuS^u_1BZ@>Z4&-=7sr=qVMHze0g=3h!Le~-O@G;x&!4; zXoCKsU+I4Du>C{7zD7LCbmjBRpLtR$!Kh%OVlPP#5^GsJ8+YHrT`_v?S!cc74cBvZ zkv+R+Eo;U!+e3`S1S_vg-g z_yPXTx>lXS&PPRO*>{J3P!sU1!7rSrC}sGWp7G&oO*B`U1M#}DZ!o>|EHbS( zb|X@Deu*G?*Ra35E2+1lTA>xuM2vR-?p1Zy5>T;^`ozdaoq4LVJ4S!N&~g?SzIUQt ziLr2<6BX^ekOVT->QZgY&Y%QlHZ1sv_?1vcXOP@?@Il8mlBFBv7*G5n(gZXerqZN! zNz1pdokxSKUkY9561CR*dS>Ran?vygB!KSob_C`ix%xh*xd4Im^~->2^*)sX*-}+> z*=>2k7km7xi3|gCQ8Py?x*mD+V>^N!^SxWT#MI4fD6GIfGM(Y>_O`p|9jV#l`*1Hhvp57-H`lo<}K0cjw zh+5ne%tVuK;zcIL)Z4Yuj7;7}R&1Y+2UQy`Z!+i>_kHgVthVpVL%>6%ZiGwt+)UXa z0V>6{1(r!2$c`c2Z94^t!TlGNN|IJ2@M`m6toKTkAqCQL@|u^{I+Q}I1przotR1Ll zmkmTe@4Kx5+pO{}a66NCq@odk0OdY8YLc>X}G)X@&iTobb z+6Sep>eYp;ap0GVgYjfNYyP0@I6#X>Ra-X-zM91c9rCBQLl>$b%$5R#Gwe|j$c&}k z4Ab+r!v}sgvC&tqpzf0PEz+sEEs~O|gI?1m^A?NN=NUqFT4k1^3Vx-NPIBnp?Xx6yT?q7~ zDTiy^lC_a7`bFq{nY$}2TTW@7V1N<=f%dn5Q0@|^MDVel(i29$k~kks`~3S2RZ>0p zftdW{CRfLFy5i<&#WnJ>z0;}+z_e!9EGuE<+*MQSVS_$Fcq|1;Dxm6KqgqZBtK~bY zGj;%(g!7wWB56`I8q-}RQen58a?Ns5oXQF{FCI*RD-Z73DAtJ=PjVq^*|T33~UAW2eji<=%GF{VZ<9wf@^C z2ntT7qmWHN4P{O!g2F`|Y} z`*90l*Ce#44)6F|&rJTDTx$Qs)7uQOg0jiH@aFJVz1}75l-i%eNS?7*o+V;tz1RG} zs4s=An}+1Yxk$kFt(Fu7m^M>5Rmnx0IQskmTSN||)u&Q6G5g^&iLw}R=Q}qgTQ#4K zBv)}HB#+@uzqPL6!(`$fRRMYWa#2%sCPKnyDCov_t<*(v_5rj_pdCQ?%h;Twffu_g z*SKl{qSgY+pANBaajqguf~)7png>>n!A;8K$qpM|&pGO>x{+ioXoSjro;_Sl6zUD{ zEASKggA%|+z!c`06_Gd9H&Fm6)+AJZ3_;1MhrPU6P&59HZEJ3Owd?@4$|BCizY)2+ zlP?Mi6kW@d8<&$=`51_?&lQkvGFFQqkj)P) zx~-0k`Y5On4~dh@o3!0Rm;p)8C+66axt)d;6UJxQ zT_g*4dT3)7BW}E3tGBapbORGQ5{`#eO# z9TEi@(8CvbJ9VdbqoQmXkC=JZU~uVLSclYrp<_cFr2rZfE_q28BdQE@@|g#qRPD*{i9aG}4rvrni+ zxATc)w4!=x@^gKnv`)lal;%BXVU3+*+0J@d{jtn9LL;hikv_)Flji5|qYAylLx91Q zN(m|C)rm8^-DJ1m^JA4Fs&9Tk0v3qN(wpiJz-Z%e28zyupYOloc_m=Brj*-q`Z;P0>w2aJYHD>Tuo~jxnBGYi|_Ds zJ>*23^3){inWjS#fG_TF2e#Keq?ni?yw$n0<5h;RkxDb|-AeB;3CZXG{iM==)u)6^ zU)QE|&KC?{uUmEok8;DBLgi`{EQ^*vG{<6}5Qwjr6^(V}rp}ky5X(eQgU!pQnyk2y z8NaSixS(j{ zkWLEbiddj4#!rU_0$2MF!`|exRM^JwJZ=Y3d9pGM49B&4rI(q1e~O5jBL56eM^s8X zuy)xc_qR(L@52lh-!tawo+cJx=z3ijC-&txNcYp*@T*efs*pJ7 z|I;$t|7lft1L3H+|I}|=E*?1v+ZI6L>PuJ zw|frRn3mmX)MNWeP8r&}qc=iQ-8O20f$(FRs4GvYp0zcMZ)BM-*^TBG2Iyr>WYkaZ z1B@{0FBGkULbP};DqnoRw!F|k18F^3uVgxbDeJ74N=9`APTUY9clewHI`5rQ`WD0; z!!XVZg9QiDwq$z}EdZS>Yq)b~Ge6s2-j>m$;d($-oF%mFbwl!$l7^z9c`sN2#>L;X zhayz%G8sN#aKfV!`xk_>B9NoZ5QEwQArg!R`1-lfr99PmP0+qzImwNWpXiHW_k}OL zha;Y|c;#9m5rfi995Xppn;;j$gG=><38f}1mAZ6~&`RnuHI+ zoYVc3&imxYueQ7d*S}qm=VkT&h~-#`TN`uN5Y}%7XxT8G+Sta5R4M48u&rKbkV|b4 zc9)m3XZfSopt3r>FuYkCB8;9HTge3Xw~ zS1NxzCXdi!IGmh?;Wn$5@(s+oX_Gj#MD$ojCi%T5o8QdoEA7(74sTbji);C1YcQ3l zIDVX-7OL81-gF~a4=3_v{ON7WESBUakyjHqnj>z<|wS%>#lv>Z@ zkJj=7Yc0G3sa1O&<4E4LMbhvG&IXs4D2kNygJXxi2Q!a(V{J70CqbwM<)#8u4tGt3 zzvi1U6S>sk_|)r9n*1J~hD;z~Udy@OJ$7Ep-W_dPfMxttQAu+tnnRCqc|tkOh|mk3 zMY)2__4(ei&xi{TQtx{Wx4Us5y+2iae=Ztro65NTV!2|5dto%bXItm<)BIf!Nt@mq z1>xBhEn?VBnW3vr&(8tFi2ZiM)29caujl6~n_aM23aah1Nh}FVa6#-HPI3iEig)XS z%En!Sr;#3#;zj7c5!0IXU=r4k%(ps@8X4KIl`g7&t4OM{{{CCsH#70(Cfi~z1Lp%; z6&tOAiE6Ij0Yi?lg{EU(0j==C@p9wOrc)|I(gdhLgLqYhVy@denz>q3^dFVv{}z>C8JI@hYbse*XZAuvvCnw>6)*#C?B<)3feH--DLO) z;t%*OXv|8jwC-0;Or>})82*f{WJ6y#ZmH6oDlc8J*}wzG_5YU2>uHu^H@8i0J+5;G zF!9RsMECJj^y`N=0#@0C9C8L|?czWRc7L~Ymacnb(E~;ah2ETvCTx7$QQkQ1t31SF%a_M6ccr z!U~HTMKP8$X>G~pFG{)uHD?@Dt25455PQwbZAm#|Pk5jz;%`Voh4=9;r0NZO`)s66 z8N39uG5nmdgcCjUMbaP+nupS~@+9bK4=F2Q=h&XJ)Nyk2vx&5$Ku%8O%BlMJJngYba~82u=PZoY9)yEv^X zfIICNIy9oA8Yg?gwq5^zKrO2>Pu!BPtKr`GTqRW7dX!}W)c0h2jSt3^F{13|Dd-9(2Sl_v713gw20N3`8D5qwti$bm|E_@cKoG{!a%M_ z#$=-ketu_^-0l_c-xQet!`A=bssR7_^}iHrP$WwenumOe?B%biNfL)dK5FjnxeOE@ z`X=fUI6Wq|oQYCeFekEbXbzgEK}dYA$t(y&CtuqvIJm`F)jWN$;?APuGJe&tE6=6T zGn>}ZNNfAj`c#N9OA_7I?A^kpO{=VgzLnDS3F;TKRIm2j0Kz4u;cw=#_ZnHzA2rOJ zVT-9#JWHn^r75kSgsU%as#}oWf>gd4W?H@&n$2W-RZH2F7=zwhQ_eLcFb%KCShnuxb5hbOZMaOUubyH|E@cu z@DEBW6X$#O)4vCMe*IHYx!Du1jX(yu{7jGi4}YnMMd0Nhlw_A!W0TrnU`-6f=WPBj-KixID zg(KBrdi~d#zuK_-i>*SmdN)B|fiACV{3RjI*A7?T#f@C7u=*A;5^G1*Rcji}RPFX( zwNw`0IwZFdZXyr+Ti*#pCf-?qbgE$w1dEX=~weZqhuGy=V-}aWe z3DVR$2d})ftryyu$A)+Mqta>1BfFJ)jB~eF-N*}vI7bS8%`sO<#PUQVo|Wa0sHmt< zFZ+$c?l3F@l;l)eN-l0x_GGmJsZ*xLbt6R?Nm0{$+Y$_e#yx~C&-533lzr5W`(*A# z@F4QWjw-{Jn_1-OW&DIA4|i-{OlbaOye2R+j5hX}zg-O8iA4D3*sqh78#0flD}VOO zh$AN$JR9?V1=Uj8CB@GSp7rXT-%M_Nmo{a<1c%-ryQ-eSmEJ!dL1IB=zQuEZg3)BhBk?W;i5nkt%rgm66wKReJk1n*mrj0NKRO5htbj0Mld3SMNPPm+h1qiT{F%>u%MhSIb8q2 zIzc<1NZ4uL;coflH>ix;kX~`cZxRfP#;8y2rTw}q2LsRhiK|;TSzTmZzjQ{D!Zh{u z6~F8VhuUcqi?TIk(@vF^Y`j>QTnY+$s04d5;Ut>tADpp$1*v08Cex=V4b!F1(~XUQ*g)| z(S>H~GMM>L@BBfrFgpnm+)|Rek}<2{#q^f`(qblj{Axj*8Kz(2%zMK`Djn_{jhMutwctkp8OkFDV>h$)#${ zV-Mvo!2+qSr?-u|FCb$_ZvzsV?0K*0t)7iK9DcpT%a}7DlEXMwt04IgQrImXLVI25 zx3%Qbrej1M)4#U=5&yn`=F>Q{|1_G(%$1uSUWv73MCIgJ*YkMo&>3Kh(xPTa)}T$F zvaw0^aGN2$AQhzbyKlHMUf$`|fnJ9zE($`zf2P+(Pm+}xvbMaZdStx zMDUkzXtC~k;Jx)+EUZtcb~le{S9}y=Qi>Ve^&WMaA`C0$CJ&CLcly<;QDiHRuYh$m zM^P!MFi`kXJZtIY3C|U6xUPogJ<~VqufsgR>2djlsn<38A=2!wXvR2_6bSqj$aqU| zVZ@I_6SwHMu;_HVTC>&ZH0#x70O3L~BQZtGGDvNz9Gc)J<+nsPB9A{f65=30JmXj; z(~X<(&P>*M1Dd{RJU32D>*BL_Xa;Mhe-qv*8&jysfBJ?iObN~49;VQsMf^YwERQJ| z%HN@Uo|xg)rq6@KPnDHs%aue0GKRmaM;4?Gf4QT2-t1Y8;d{I3*M2Q zK$zl#50gKv4iH@^g?A#jFLs<$u5E`*MO(yvjyL1JiJidPw_uXC(UNY_U%l3xn&D}1 zq_8QFM#XY(O6M8&6iRfQAe`ss&ewHM?GmD1Ww|a?&j-?!0&$dNcEW>ByK`&SswKw> ztPw?4lmjx$p936Ta4deGuPNTh4RPkaet1SYLbVCEJ~}xpKN|OBJV~9+544)i5T!f1 z4(J`=8A`xrUNH@*)$63S9a(<@iYt^+vR_8z>-i2PaDzWrx-T=`;QOOHDg)%|VL#r! zBwYkn;h0w0+{LMM&L_Rqdmow9=>4i>`yOA9;P<|IY;^Ql#KIVk!Kg)B0Xv+r&b4Su z|IGTpRbL-~Orzn8*9G1kb8n|rBZ7z@T4f9+2|N$Qo@1tx2ML*X=iW)thuJ6PKBehB`3aJWJHy)`019~YEzdI1K=F|JP-A9 z$$&e;V!6DwgR9CWhOqE0?f-tN3fZ9gFLTuDJ}R78lsrzjlYi{ z2v)Qxl8npY(dj$s=VeOj5!bdRi3bPdTxQA|^a@nYfA@SIWHGIzn>4X?$uVjTq0%yf z3hoBOP%^Npupvo@9Zj0ty|*CRO!J$4j~tzH>R{l)+w!^avW63`9#oG!S9H`XdKo1T z!v#h54K?@V3JAp*5)w6McUBfxS5`v9ty6UTe2*lgl{eXM^=K~}92AmC{VECPgAIg* z`*eGE`k4%X$y~AvY`Rw@R*c_k4b%BIym_A}+1XG8)&tI@SxGTUn+zro1QLl91Qz*E z7BoM+z~HMTV3h^PeH7?oN`dS9qc4Npd~@4~5hrjJD~d%M|4??u5y zA=k&y@Pzjcq%-lzG*ufU9o_dp%t)`bi4-T3{on3F{=Gx_zvAZkzYxxSGKB1;+RNNk znPwVi>qEQ19T2y`{Wi*nbS&iH;mj6BnpZ>K372jMz3EMKUeAx1q0Jlbr{#MGLeag} z@Pjpql;}xPelq5xRSKS(?gclU_`!PX+>5(!?N5fW9jJbw6;a_|sH$6Q=Ah9fy!niO zcPuqFey$(UooOGNV?+@IQzDP$#)`vGB;|NvKc08DD7GKvu-v9>_iy*A6>kXYp_`7(6M&83MXVa05oR;~N=5d7Ij`Av}tTSH;aTodKC zqWg){{pG8g0YZ&-;a9@3DlU%ZhHt)_xF`;)+J{KeeC{MCdI5GUC$^rX<5bhl?WDTC zdcod!`KnD>W3t|i64QAAtg!!>`6w4{ZE&i!F7IZrUSLIntsA(jvz+vJ$DA^!GFCQA zMN{AQVo&)=W_h~ZW|h-=OK{hcjgFpDvTwdxv|QX0lAU!5`*mQWTVGpW?PxZ17N9Hb z5YD0tdD8R}`Z#WweSpsQVJN;O}ykSFfNOhi%7wph@PX&^_@RH*#LZ z=M|L3j28dO;^!N@h?u5DAuTRpRbB7PNc&D9JW5)IW$AHm>7K4hsD0AJhwbQOV)$Wy zeyJ8Gy^?Y1igk0nmdFqr+v1XiJQZ%$ZrS2tf26v``*wab?!ehHXPpqOrdT;hTXq;~ z(<^eM&i1CjjGvs|`8_UNvH(eOTl}TCxlF3?s=4H8t%N*D4W(;c^2gtNkY)W$lkS`I z=3U%7KUdrrrYYsNekd!4SteHf3l_w{YHIyWP$L|3La0IS_Q{OQ$0Nk928IK>v3<P+*-cD_Y3UA$a796t+ui0ZbPC6&4O@OFyJemUvb9q9=mk^fm2 zp}8rQN%g$tOSiHE-}h?RkXhLPw9>1!@=E7DEv~XT@|@PNaM`~XiVA7zM()!8izDjY)rMdQgIlr(&8m+PC9E#yU?Tkh3+|DHin6jk+rFZR=L38QpcY1EU^q)t|| z^yv~0vTk}?)s=Vg_U_LlRR6h*|2}f@pT(Acf6V<`Vdj73i5H;yY@gOjoA$|M6*6MB zwa>dtAo42UX27aBBgwl6=YM*@%TR#%N~?P8Z(ZYlEic#gUhV|5Myhv}9e%hk#Fn=8 z#PN%9A>^T6qqQ4*-IL|uISwDP6ak^mzBRf1=v`Ai3(5Y2f|jgKe^~Tb$h~^R>w>wN zGJT^U{LOARJbtEV?2@DGee{#Yy}M+`N1(ud*01A7A)<8BI}U|w{>%AXrJfrG0#)V^ z_#OSY|7ZH0kN2vekH4>!vGf0+RHXkwiB-wsP*KDU9-Ol>R`CL|4$-mN)=2FT;d+F< zQjxG3G<|%!=ts`VYhQyHrbicGl~&MbraJW+tS9@3uh6+85QY5)b*5ytsiYLvEgrj( z%qh*&`u^fsg{zd*`soD+DXB{D1O$hQpkJbPIvIzN5&R#xl_c7brTA99evYcnD;}q!S zb#?-eQn6$(5?XVjj6C%I5E43lX>C~(FaHB%mHH8X1xIZ~V_wYJcV)`Q|364VZZ1~oqKx>$ydh6F8tnI)SsF}EKNwQHW)f14Oqezg zK6Ezz0fEtY;eOmM&R>-Ej#)+V&B_B zi;Z^1FxvWWoK=ghOwe_)G8Q?UN7Qp@d*TFitks+J9}xECJJ+q_f^^A9H-u4HJ|) z3#k|N;Dc;ySY~J_I<}myYgaEZ3WB$(KmkpvFO?Q5D=|3oE7hF)rJ|21-*^gL{L81T+ zy+0^2CrbM)O}#29z2f$Z^CjDH*MVdT!mbbT{0#;@+kwW%!m#*`Gr9I<_~Ii*uTSN9 z4qxE`h_+SO&{xyr-MLv`{x#^YjVLKT!9|(&crGeDi*`1SaRXH7s1Z$fLLl1!wl`^& z5U|ytE)J`^E)=nNhF`l`P=6<0*VZX@z=2o1YN2hrLyY8i^T#jd=jy>Fs&S5A?+*yl z28g6y>3c_II3VM=EM|9@WS`~qa<@LRg=xDIPmsDhnMvx<`7`tzPLA3A;<*!rOnr0p zcAEJSBz(vBK}b&GzReb1ignTHO{m=bS-Wh)X+BbIdJQ_&n$IxYlWx;0aFhG(x@^bv zTS66qJx>J-9VdpLdWO&7VV7^ZJj`Lxcz*qkA=g!Zj3xU z4iwCUrdG_!Raegv<9p!5ZXr2eMI-|6-$BB;Z<@VqF?X1~?bLZs%pkGtcpZR`F_36A z9clnTz9VMpc9WUO#Qfbxo23+5n2Bfu_^U~)3}0Sm((z@nAj43Qob(qww^;(KBej0S z>1O%u@r%w=Ai~*WsAVMKV(QQf07>hrBAoHy_o{ zgm%%(MJjV#@mFg+JKnBMxq*I<;JRGVYSU?D_hq<0Kl*yM7K{(#h<$3SwCi~x%q4D% z;Sk~N$h)X+6;hkwR(gE{M5LbLd|#-D@rp{OoBn(qWib@!OtRPFB;2nv;;S&#qNd#T zs3zMjN1Wb}dCh7*^6P|Te?PF)teV%wB)4=gMyz1>K#fk!M`WIV{@nunx=Hm)M2N{M zu&<>$uJK?;N-KV=VNVZ?PMyscXjhI+9zS~@+e2d!y{Jp zP2Xx2f1zj{%=nqM;{~rYqqURLMoBW(H2uoE{HVK8E0SaLC5m3qd_QNqIGQUt#Q%bB z7HjIT42I0lt{(q%*FXWr{DONBqOXQSIkI09yF7cd zU44AwxnJ-$Ns`b&$ofWWXxM51jaC$_rGHc#yTwsqZ|MZe$$sJ<|IF$P&WB?hKI)u=X)UaV`I=h2#-TL@u-g#IsM4nTgp7%$V^GfRsO zKI3p8Mn7RMf%m8j-B|X;Pc_{njge%JT= z`8bDv+I>QPw4m%)t29ROT5BOtEq*9L^>e4s3XbirTQ{FiE=Ir3T6r8%>)KR_hF@o> zHkRSb{xP|W>omg!p$AZ4_Z?ele$E~58IQ10->*~gxy-8yTd{CZv}<})1gyp5(yn)r zsGXL;P?o}W*?r6CgR_!(FX=YmamzYgp`rR(Q9J_kua;#DYW})XH+xEYdA2dqB68Iy zedkA4^q&qWT)DmBycBHMRj6Z|9;jtWXKG8zlQ`dnoaLW5_NzOdbM}|A-e~0-Q>t0_ zGGen|2j*>kueLWS8~)V_Czq3?OgV_flsi}TG2x}cNs~OzyidyNOgc%}8v;*E1ufB< zqw*pX$mZo62kVD=8F#q_*Z!QjM<)w1+YQLe{n!O(_wM-m z+OGu}19>vD6E(-F>W~b3_tHrvmPc3m3jxPNaRy8N6;T80BbuDC_L-%9k>4nu*(tVO zdDtA-7^SfJGAe2fVm|TtaCrau(JxIV7kp_nN*+O;2DOFEP23EafE-)GKqr3L>9!W~ z1_Aty!f~}Rc#x*pmJ$3Mrb+8=DG#4Fnlm3=3l`SvTf`nQBexNBCh3(~qAix5IZeup z>F?GIwitka)u32;v{;v1^ZfPlJko%H-Lop*E>eAWZ#-rMY_o*wdf`ts@>O$p2RC6` z2hLw~HZ^ruzU&}fCzwVXh=&?b5Lg}ruNCsBO>VZp zb^{)tsyMDU*A_-xMunW|+s!fX$2%mtk5^BEwfB#d1gJS%52l|ii5|hdqwt9$X8Bl6 z1ValK1bkntI7!||(i?&5?mQuIK${qTPpw%gRH8y2O9a0< z>r{y!o_6`5mdeh5UZuv01g)m>=e%W`{+47w-gKQ^eOxXgs%TZ>z%%w_V(1HYqgiI@ z$N;{IrDY^Vg_YgdM9 zA%pr9hQ7((!phFy4Ggbt$v21cuq(yH#N^=gsLRD_1c;> zf;BM0o!VAz*-nYmlQUly{N;3hH9PbeG3-XmA*UYmZ=w zh68u|4$Dg%RZ3+$-4RRpRcM^H@?EkZ2)Rj#sV`g14tpQ~rh;Ux!MUs-$H+tPJX9Ck zFuvHM&JUbyf+hodCi(kgNVbm4gtlY4t;o}?wnpc_>(iZuDbxTO)F*`e=x?~O?Mu8o zljDb)S&e!tUKE{YIA98%IVp)oz>g{A<7a(LalcK@Jq{I8ItV>D;M&x$pNUWERZ=mn z^+q?@Og3M~6K+>A)J{!m0{fqQPpQvFkb`gn`*>r(Ll6_T&BciWiKhY>L+UKf{*A?6 zlEnFhKk_aRM(ma}2#dmmu-o3NhtdXA+vN@Vu#+MB-i#}KfybL->SP$<^(wmlCE_F&Em3!~i!@aA z{2w+{-JdUchLfrHv8yI@S?^X&4=Ga24W5f&cTl4-G8CQ}JY1L?Jxo2y_m_w{PBw{c zwP{u<`Il9$#!0_$!nk7E3H)S0F$#sPSAk`{V|&XFnNLusx;v!s)Vf!eX#ji|WR_o`N&c}~AKdV0>r5}K z5DwJvLOVOcwYEOg`Ue~U=-OSJ&#C~8CQr(VLJ>|#J|%GCR8XyvecYR-u&ttn@}X=p zJTEayzd@QxXb6c8K(3B#u?dYnpAHd*P1Zku5R;mn_az9(I6X=OCFry#)Fj0B&hUQQ z&*iErDW&)vY|lZbLcnnRsdAmKO=v0f!xW=0-0pZ)*8B>!h^9~CS2}OOMe$iSQqU`H zj~V9fjh`o;buzLI@Z+qZZ#EBBGYS%>(l@byxr--dui(DP#UOm{sPGIJNG%>bOK%vj zY8<3%6;nh82J8s;ds*GiF7V%PL63~#<(c+DwR;cT=;ZVsOFYd3Q;qDj`I;ew8-%z> zZomgIJh?OZ;O%ZXn|XNRwj(^ z?)eg(bFIMXz|V=zr{&xwa?p;s2x0EhR{x~Cxwqg_wgs+nmb#$m8+%$Eo!i}h?U_HSA^ZE+in;CBkDCL?hXgNsF8e%pstL63w|0HC2xQZnPhtIZ86?5lj34?AJ=j&W@U8e5{ni5hAqs`nYd z6N?GSUuF05sA{fRb^ik*fX!ENcb&DI8ronSV|8T1ipWoH6XUV3*0L9mv>+!$V_G(| zQ(D83n4yb2mB&<+m&JN}^fqLDPM3H(nYGIOD)QwkIhWFV|NlEap=x z?{AH{(_NMTC~ns!A0JlSo=Yk%!U7R zWK87z|I1`3*>C5&36XVZ^-TLTkbs0ifzHp^R7aLcwdWd#dfo9uOZqvXUE%BBP1f`z z7`YRBr&6}ykZpETue6`0Ur_{MWeKHg3(?crj+{1A2a-UMcY-YU1N_lzrc$zTMjE{o z+^s=*QThER>y}PvpWzvTCGYl2fs1`t<;qyrPNFF8r z{squ?Bf{YrbLtR3`!DTT&353muHh$#8pkC+Pq#rI2JMHGy}Br_!^+=jJ(G>ZVd1Y` z87Xk;5mbm6-Se`wAlZ(Y&Fi!g*6ZzMfT6ke7%xQjO2x*=ipMv87rJ86Busjnx7x&G z9Qw*9uaUXpXR@>+5GVVXm~Q*E?AmA5Yds;~?-?=oaa2K!_B~Jcc1zi~5~n9{vB-)d z{n_!b#Rcv^0=BTcoq3+jm6fTT2H3Ez7MGsCf*jXVG!9%ube$gau5@Ne`0V#w12G#Y`uGo~2PkpU_bsf57pd~+<@luRGRl7aFE(>-HQ5LD& ztVlYW-g|AM8T#7y6d84{iY4Ht%WGBz`iM8OwKg37uyMp$A6_OZF|!=_yzFt(c2b|XFXwc{=F#CU>W&0vZl`2%AR@cO}QYwLocvi5dLJK{%-mVB214F{FK zCaZ!fsl9vLkVvZ@dRNVz=bOrcRfkfh-xV}v{= z*@8hX#|JwtKP7KqlYO6P$OxyG0()C&hdU(#+TZE{o4H1tQB~76X11|)S)ieaM*n19R6KYW|6M9n;91mX!#(FW<}N zup?8-C!BU@qbBU-Vw1xH%xFt>7p30I1~uFXoQ%e2WiQ@90J%Y}Z>1={Eams7+Oky zn7l>8L`pS)lI{kU`c3q7w4qynf+)%?uNe=^8B+h@KU7)&Hs!|U85q*mp_R(;4Qk%D z>=l5u-I0v6XIYZMk1A1cSo8A6yz&L@39~ddiu7MfB>jx-F$;m}AV=LOZ(JJyON9(8 zh4h|6;3{i}HT%4}$Rsz3XQmJeqwf(@B-*D!O?%R`1-62hk#{Ahhoc+j#cVOrwSr;c zz652=8FSYWKn*~0SBd5X;lU<1qMhcLZ(}Po{yNDau-C(k^A;e;Y)bO!GE@Ia^DhH5 zLi)(pAf$u*Gm`zGGD#*e`*f->SJ35})`7HPo;B$0RKmv%2!&1F{{cS4F=@s-_><}= zT%o%VVaO5_)?oFo*e3NX|DLZSf4^x#`2o4dfIE`L5?!}$(JA(-MP@|Efb~6UW5)M0 zm+bHh^E%cNm+Q<<=4hP9mvaR)b{%wHQ4st>t2Bp!EAfkq29rBm!cXPE3bAW z(4VMT*;}2*gzfCIg)QnZE55`lGdj@iI%e~7p;RI&!-8Kz(K<3GjE0od6o&%_JJLDX z2N}7)tur*J5CF*hIzyD`;JYX!DojHwqYG|87b0)Zc%$CBhB*;)P3y)A2GSCdqj6Wc zeybI65hQ;Fwy|(0%76+K6?ecU7TyX$$$OsYT((SARPG@rv?d9R(D$oapvpAUt{1-(V;-vYSjVwS^fTyJ}?WT{nx%brjoX0J5X*Y zyY{>$+Ze8r7SaEWl9_F2N%V0CXO%^QSaq|?tj-;p=1uKfoygVMG@jziZq4;M7*X`1{(b{eVF@}~ z`?adbJ0O1_AgiI#mh+?4NO$9`rnw`USI!AmRt&Y&-9vOILbuW_!Y>O#%HJGqHkh~Z z_`pzYXd4BHh5QJZ8~>moPCz`lpPKj*|F9u4=EyRcsg&6SviuHgIm1XO&u|gqTIgFmkVC`wWiLdP?fS3daK67=_6k*{&V&K%~tVQDSt!! z!v*tTT2(dcW`)$f)sMA;>HA<3WEIbxm<6n*w_1~Oyy;q_YfHOstK0LObvCR9#Cup6 zpdTJtyq+K^2 zovXhGeg|Z`(5>jl2-KE72&%np#tNDAZ+Mm)Bv$1$BVzBFUKvlBshkPo6tb7qVvTQB zMi-OQIBm=6|In&x5T-Lbpsf1_`3?ILi%v9Ut8!Ei-!hmm_0mxsE&97V&S`G_h#T14 z@+6p9=-I=tA5x`=z4NAPnzZfLyk@XCS9Tt3vR=NY#^o)1yV(K(Y*NM*Mh$F|MyFWm zy~#1GK)4z1&d*$j>3XQs!G1P8MaYp0kRMG@xg{p*arhTi@yrymF5cr*MkQFaE;g$6 z>YgmVeK{I%&VP8Xbgs9sG~g?o7Qm|nyAWm-4b{FCCsuRm25m9s z5Q%jJ;2$9hEQ{$CezBfbN)#x&*zlGWYr+D5Oij3i!Dn=9FKYKj5}hv=72d_S8OXX9 zmz*46ON_Y7)t1*-^tIK|>P%=_v^0VJM4<{i$d%2u2cN#0-*Q!-`IjFazflS#el;1p z>Q%>X7hY^Tem1>SBpEsClqYI*#nh|*Le*0d#i>16)_SS0Dm!UXIkni~M>>P&GHNT~ z(V^h8*pMQ^LD{EPf1H7?j&x15wn=sY(Ncys zu+|oW#t<2!8`w981jXU0xl#&-30z)%zR^j6p=t8TPDf3HvLf@Z+ghtMqsQqoq6#|N zLv;!^inx&ghO0vN2XQGsjhN`++E*%j^LqC^^_wTMv4!mE?_FuFol#fYB#Bk8GVS`F z9Z}Hq7E9-sZuRkiNrY;-ar=$DQFW82C16g{0b`(me=GTYSY`Xs>1nTXq^XLQlR zYCn&+YSd3yi#LXJi+!oBB*_ER%u(8}5z^Mukfy&a-chYJF^x6=GE5i%P0g0KM#{d^ z-#F8D@#&<=XyxwT7iscZa|S{rHk)E?*oL_xecK<)CxuIgm5yo_CtM|Qzy?t|a@>OF zs%FKeUN>g}ufW`J4t#;>J+C5FT1lWUh>jk1R+Oa-~HZfj?X&ab)9CK#G$7>TGZj z<%w@%mmD4N#lOQO%1bv&->I zSS?)nAd`;28&bc>k)36vC}5XT$z|tHl@C-tH?je&jmrfGR?@|dVGLF_>yay$*D4sc zIS7{G3@ZOMkN8q(pQ4#0N1J|#S!q_I;o|)KoY1to%M;rRZalEctql>L zW_oWhM*e!>sHMPJKFQ)p=HMs*tvC{JA)*F)Xp=_|vE=-0BXH7z+}^Icb~wh={kA0b zPW$LC^?fk4+6(gp5)ue><{0(NZ*Fm#WtNBRl!uoFeouQwSQOUzsD{^Fl(2cYp(7TW z5LhTDv*pKOUHgjOab5CJ^MpD%>bT9w@7^9685xTGfdf<%BteBp;11^ z4LjW%j75ueY9W`4o_O&;*;1J4uDx6y+QPlewmf&n$K(6$R;s8BL3|c&A`xEeg}4?W z_NSxc9!2A%?{PWFgYS|TQ_^}=6Vuhn4H<91pn!HVa8ZKx8&kTtpFI4;ZSSho1CODAJ6dFO@a8W-ayW+ncBqoQ^l0FHxTv2pSsaW^^g( zqMvZnhFEm3t;c}9IcAI-@ljC+52`WQw97oMrT@V&h|vrCwoRVfrjLX5jZC(UvnVr7 z1m4N^MR)f5&!i2Vc`dPrf8hwKUmEf_oM?2Pt~9k?ViN#Cn2pieq-u2R0HJ+2pL2DlWwWPGseql+z)|nYcT6>V`SShsZEP(R=Ub?Sn=N9Wa1EPx_PPOf zQ32cva$R%`lJm(r>J20~h($JMJg?bEGwmmD_Z5qzrVHupf%3<&%Jf}Ae>R;>-bs{s zNrzT8Z#GSetPf%#+J{_}y@rAs+B<02xL!x=(dJ=*)}5APro~L%FT6tJaT~Q<<4nNg z*<{hR;ydb?-zX`Kpgl!G2M!sII-yXA#g*C&s24!gZzupEm+7uJBx=fAM=}{+;wMcP z>k;4*+Q_L1{Q_qg@B>amV|Lv0^SCD=MI6g5xDv{YI2^05G=uvn0J8j;%o^4gp0Nh2 z2z6?U7D^H3KKLe{)BPBXL%HIQlKj*#@}M~-$=x#6MDL+(VoXeQ_BIeVB&Yoz$Tg4u z$&140N{>wK1#bp~F|BOUYNUHO$-|>xe%Jqn43=H4{km-j6iH?9S~^sb_WdDKDbf0+ z5S1pP9f@VY1WCEh3AO{^I}&W(6aDvhGB{i8FKNhw!|+DcK_hd) zw!8Dl`V%Cko}j-Codq6mGD{9rxUp0E9ROY$%S`D_NJEeL?2T^BAjFs`wwGoHkeQV@S zh| zVL-=P7)#>NtW@`kac!@55~q9DO!s~{hkJh$XhQqVp%)=>pYC=}f%*0=kSp!FgK@rv ziWe=aKf(FJxKc&EOF)(C&6llF6CFZ}6JB%M7VoFE_sjRrs0ZHW*>ab z4YzhJ)4Eww&|8RsG)no(AuHPE&#o6`PC zRebMR?H-8eSkyo}NH02mG$Qe84G|awDPrC@w8_fS{=@Ap^FkHHuQ5niPU(haW?GW! z%8Bm?mMs>BKvd&~)UrOeMK@X@Sfo(zryFcdnccjFT{b*NcF1V8P26V1OzIl)i%lr6 zaK$wnIm>tFrl!oD$IJ)wElJkIr=yQJzjuljHAh$QRUYpMx&TJJ6z$wb0qP;(!TA9U zr4&#_!qsAXXP~;(2W>cKZ)b$cj7p}um8wlWogA(1840quGLFZ0>GNv3GcL3}?Q3`q zq;ey#qZjb}%d38Ty;tPuF)*eGzR=tRQ`R$n0~#@X>2^=mBIl%fP03PRihUlH<&R)i zCxdTwfH*nwRw1?nO0TySuVT;z1aL+vQ>5!a^Rt46SFip@j@CbE!GB|dzVewOxo^m6 z1aOY{3OEc$7x4Eh65tNl=#am^9DimZb=`%iEX#8tbHt5LP4}fV^t>B)*fK40PE4Yv z5=2IgF!-_z_&%C|$9Q?u%-KFpz^ondd~wa0L4l{NlIQUI6n%%>ep9+_)7|$5k9H2j zGFIt)<_Yz}VL#B66&<`TmN(aD8?(I$kQU0$g_kQl?brE_!%N5unPyp`HgnHg5WWe} z!&deq7(nhU!phz73H}odkDTH;5b`MA9bSjzQ^jmVsscx|r+}2BCi$oJ^_7COF4)#G zZM+g%;<1^{NF;)r1xpltq>N^`1Wg?U1|T+QZg6i&MqZWv-VeVGyD0}g+`VR9RC+l3 zC}48SU)-!Ufw$}GJvP}>Rd9OA?YUs2VZr+(vVYJFG7;1|2=fp$XJ`?ovkk?;bZbLq zmH!6_>wiVF{sE67IipAh>67%oBb%=fAI0NHY&|?jEwulB{R6;?fou^T<$m=`jrx}d z{hdFulkkU#pp$}RkoNsco&I-EfjZ}x1fy;9WrHVvG4sY|MNDdNq-hOo?@W~}xIgf< z6UolXpjzLpn3=Pa82-hA`BV*$3f{fcHu(5Ungi*|{9k_R`Gy9J*7epaes@7no}JvK zszGonZ?3bBUFY;;f98-KWRSto2wN&$8Bt!)#yL^3w;bX+RbrmabiR7q-$NbrK;JvMtv@6CQO`yeadO?tTQLqKFMU14#lTNA;i z9mzm7=KB>BlgF)6n$|`y)bh!+%&CWFQi2lV*-U{$gZA?Jtazo<@skzv7(LCkHwt2^ ziHELT`a9A~n>I?)^bz3^u^4ln?-w*nrGc}Hk-zHF@$p#|bza2;V8br=>%7U6Own2a zu26|IVb6)BdBh-me!Iy#xaHz6=LW8M-Et7s2cr5XjXYoEsN3ahA7s17&C`Gq*G{ng z1_v?q`PtXt6K4UfZ+st{UXUpG-uC9j1UQoNQVcrI`VP*c55CY)qFdmw1k+JK;tWwP zW0j%IW*|8O*4G)jzHmzZ1n#?2@k-d>aXW|aTHzeevSCGW_C{_ zAVtcBo3%wG(FtEU(7U;dj<=T!$qkMR+;d`$warS_M^px5*!(hqq+RE1EA&W(F3)&P zHkDIlK)}-{j!z!j>dvqq&DDvNYixZvqz$!Z-JK2T!32Ify&mgSnN2 z40q!j&cL-N8!q+rw#e>(Nwu^?TP=~Sn1k1@E@iV3eXB01x63#_9V~!Y2(?z1Vf4G| z$>{pVz4yz}n?a)YaUg!JQNunp?)(6TrdL0P=vIth6zz}puPTswKKJ!%Yuqns(bK`a z4Q5t58t!2-d?pqC6cBx52Js4u7K4yYg$dz>+zR|tpNioaYqTGA93XoNh z23gXml^Y}Mq%l=K8?F*Z-q`s^-w@jlRWF^kQ6^WA?aS=5)1*LB`SXqf7%9JQP|6QE z(x|1O&!qjpXe9p%XUCN3%_0+YM)6KQi!~iMbk&!@aL0?QQ)iFKAOox?_XS=oI*e*0)5-y8xNnKp`d~TegWm8?PS1m_TbGtTLWjcic1-jc z7=W+x?O2YKWLXxR{~JYh!RHxX6LN#3O?6Z~mmHtjDCFEVeNq_x;qfITq|U!FjZGi4 z`xZTJ6hb2E$7m z(Q5Pt4H?82!`{@k)eV{wI#3+a+lDw0nbR@kA_wOGV-Wt|i&=QKo9qyotQ3a(rhzS2 zW_R@R={fVef?Zp!Z%eoWI@hsjI#3q1$>fgpbcPy;`fn6VP3iHA{t6>4q2ZPk`ClKl zQ=Q+91~u%HyG-?si@Q9FHfBeLv3Uo7VB4AG>VWyzMLObD$Vk`;VPE&wVZM@K(;moENu+ z(^U)afT?Gh@@Xrz{cKsk?`-KyfQluF$bK6juLoL?0B??U;xso@g{A^@JK9(D8UE%HO=((rk`l>dV}@T}un`Gx;!-CI=L|9Yqs=1}r4SGg7PPX4-0 znk~6TNKwGI6=%5Dg4~Sq{1Uk&j4UJ5Qr}y`h}6AhSMVV#uMxt29jI3eR;g&?p`964 zy-l8ov1j4V!uPO|(^W_7uwO)w4+fUZUf$Eo2TD&ghVdYurj-7K`#*bLc7{!8)LWZd zH&}i^G=9%12r5F3C}1$g&~x!H50S$@YVN*@9G`pwEi4<}%ncO?fty1!^eB~yQb z$a-DS=gY5i1Z_k6II#BG9GcG0L`=0hQR6nv0u*qip3`3f-w8P`g&dE`>$QB+KpW6z z$*xJtHM*uEUGk%I|mtcy^?^Ff|wK8`I- zw>f@E)A~36FbJU6H~bRi7GxKh8ynveT<+XqWpiUDth-`IwBOO0D&=W?Jy)EHEk6WxR!_wqr(i%J@wchn%@utOIkc7Od9DU8)A#94{&L669@=zH&PNHMM|lA6YA@ zaeU2~oxr9iCfUS%AiZD?1S%!ljgy^v^fJ_SU{EAs#Y&G9Sd?E!nB^cVuM%Imhl>>> zj)I^%SQaGCnG&&K=GG{53pLr%uvGe{Lzl&OD&JTs!4yJB5i7s4-9~*ZYwRRqa9C(U z1OzBm!B15fD^*g4N7tHQnwA51w;NRxfO6AwpDJO)nRa#t0k36>1B_D7GcC#|q3zM* z+jNciFp5|TT*=wP77_7gVSXf!fEW0B@~;M!XsuF88_wFxk{?N1wZwp`k@LV{Fs1@I6B>vERX6mAV zi`Hf|BMBJG8r{e$By_a)&$ywgpFZj3IcAWh%*8CkSYMToX=I<>8{vPx$=$FtAp9Ot z58?oK8(!R|a3^QeMwqz}-H}hZ*Oj|fWRhg4{p7faRNfBdbN7bTwzco>5B`HAuquNv zDS%>40~`^x;L>^lLHRXUYJWAvqs|L@-MCaFaZu|6QdW}KI)A4So2$7EhijIu2jlso znq+(4CTKe^*>4y9H6_Tj4w|sofb zwnBm4A0+?A5rF=3W8nR4ypzjGn!dF2?ZCbPk~dUX_K;XsM}jVtWowFU=8IS=IU+2( z#1SPIw{ytMI27AC;#GlcSNhPZEY-z>v!NgN5%%?{sCRYdKYx%awb{Zar?xEF_?ik* z+x>jS?p}68OlT`)^m192?~tA27*)V(!PklJ)PA5X9xZ@%$tI4D^WH>>7J)K03mGAIPB*diIKa*PDVl5PRo*GjLHZqoVGr*OW>nAUQD&ZeFvp zJ_G!;si`5$UhB-cO88*o^LvG@h|w+2rOQWKVVNnQ7A0);H;QYzoKh*j%bMoZ=BI1R z0&93LU}&>DM|;Vzhq9sH+<`;fw)A8Micc@1vJijLDD@j<3-B8ShkKU$*6`(Ao|{Yb zm2I+~u$EvU_}L8>gM>cNBe(B*Vaj|WgDX_Klr`qDz3QfKmSnNJ6bU4l`?aahcO2ET zH~A~FayP0a8{SgX;93j@{>+I^U>wG+bGMo#i{el94b?*95JIiy6g|1uz=%xtC!5w0 zZ?t}jq!Q>46~}zuIj-EIRXJ+oanjT~-41`?E!?xsaZvwUKkw|DhT;K#vfFVWrbt3k z)8t3Of1s0^%*5!w2x#C~&Y$FXWpX-Y&LZB{wVfS$ykFp&T&G)1u0_Kjpzl8%!xQeC znoFOleF6Dsm<(v13v}3aF1CIY-+SD2DEc`MXAN^OBI>1F9NpktUvX(OtAfn{xU`$M z-d2ND(`FE)5ANTKi~_bxS%E2>({1P-qKPw~-3`tacaaJv#b4=?rMZ z%ujP{RdEMc#5V^F6vXu5L^LQ*e3A`->d#MG(xZVL^{=#cq<=&$eNVWmI=bL85fkm* z;*w%c2_JXx_=VZquwQsj`YpL8buG%7oK3jm*-7=YvJ0PBjaBEWfro_}lQz_pg{wa{ zHRd(Nltb&RtckweauLh86)SNcR@1Dv=L%#C^o^yTtmb0aeP>S|vhl^Or_TTkv1j1# z!DkDuN}T!5ivv}Qw;`c@Q;rKr0E{@b7PqJJVzA`MPWvQ(k@6kYaE&~ocw$N}Hvd~L zqiSxDOmHh+36 z1S=|S4k;W1660+b{_;YK4Hx!C8=qCIiB{^V8K~!#kL%{J3>bpoZDwwGvGm_9YLs<5 z1u_064KNaPrg&h7-W>{lZt24R*4X>=9Nstq;2W@1v#0|G$l^=z{AG<+DH^0%r#6=| zK-KrTzC)JlD@J3U+xM-IIbKC!4S3(C2sK(o#h3L|{M;b0nhKVKF&%RjLQrkvqT}N} zR=uaEWog%>fEF(Ht`5XH?M*X&UUI?lWczi9O#g$Z&C7TZ9sSW@Sum0|fD2!7Um2xn zaw?92!zC;Q@|mN=i|O`1m20}#WqG$ERx+j<&&Ol5xD!5jprHO_oxv7PxU+qBW78&$ zg;pzsWZPGGrI%dD$a|foHJ^ivypv8ZP;xEL^v`3?)Ynv!Pwa+zbdAhG7h+!O;`4Rq zb5-GuG5yc4Y#9y?{N~Iw9%xE=y?vEqS-+-Il8}croiyKqf{u-XSesVz`spq@lb?N* zLZS!$X$Jqd+i?HsAO1hsk$X8ND{HMcM_(66_(6|{a``Hz;NGVqu*ruP!6Arb?YQ5Z z(1vHKc_o*(^KvIvp)t41XeD<&nVNrDVGC5}N+Yc_bxm*7jqd%bz#6PFUN&RwAW}iv z1_ESA0%CFbBFKSg*qy8DO+ZZw@%LK902Xlfk}S!*Lv!Hwmg9qipFR7C2CS?&flpK` zUAu_A)>g*__n+@kf}2yU;o3#4r$^pgj9cqJ9J+X$Z$$3F#62M_YdeoERO{~ zwrZ1K@He)7%zj0_0rexejwdK^He-5f4nlY^;&+a*bfaRD~Ct*h{S(a*gKmT@Jhu4)@YmK~* zj%%H?cvf#eAq`SU$1VYxwJ>3;gSZ!MIz``@(H4Wqy|OQq*vm@xwY}>}MUl;Grly9y7AJ_m{tWtkg2BUU*j{r8%*Ucp{;kyIGhg<~{Rp<#dd&)YC zyYu9Rp7;U**mkEYWOAP5;(-_tsr6~{O41XTrzoB%digNCUs~hC^>!E%H&7LwBG?2* z&Rj&ldM&OJ_@4MRqeq604y_*50gQr3#(7oEuFK3@km>SxhM4t2=wKUx%zlo$lixDyH8Zr(_ zsc(E9UT*VWN2LE9edXWLf*-Zb8x8U6XWs&EgjeZcCH|F$&Zv;@XjZ;t=-dJu zA3x)e$&K6M9QV(!)O8}?nndr2-A*yp%)k;s$e!+@e@USmd9|H@qspnKvvR9xgUP_C z!BT{{XHM?-QtDkKNh?+DH_DvSZ9 zb`+cq_mPA4bkU3I{x;Qtp1+&-+5A~{P3bRQ3k2ZV_oBAnC|ST3*EihW*{XH} zH_sd}LV{g=QUodP zsAjhB1O%31-~@&A{B+mvNm_>p^7c1J8rn4ar+jIHi9L|(Cob70$F4(y8GqlH)TcZ# zk=h#^?08Lf>$2TyrRzKyAM~2Ze$_EX`^9jAFg-nX0XMBxgNy z`C9AA54$WGTTX!eV1mo`lg+0MCYJ_m(X0Sd+r{A%HYd+|7BB zpB6q0Kpq)tqiBs&C&?Q&f{(nTWw|PUR^4E+9d)_Lx79YAd%k!P*q$wjQMPBnJ*EFG z*7Pk0yz*qiR0KlBRZO?KM$`umI}>&Mq9G9WT5u$ws1uL3`S`10B>J5HeSHUnN2G3^0lV-UkideIl=#@N)I=AiWSsxx9- zR$P26hc~e{urr=^p?bTRN)n2}ai$RMsgvZ}SVhvte>(VrY-M8Wi=DJ$bs5o0iwP>d zfj@9dz(CG3B4)ddN+m<45ephp(OmHc1L_k5OU!H0a)=74Ym+}^&Eap992gU%rgKle zvutGset5&l4Z&JQ`hvUApX=)4+9NIK%)6m{zfp*;?$@Dm!@`US*J}Abv5^|~JeHlr z@!#SF!&^QLQV-d0h{^tlZv?!Yu4vO1#RyH9y&oG^Fp?sjB1SQN$Bp-sUGn9wRz<;X z2UC~p26=J=yNip`5p{OHoO^tdDJa&NHhRXL)7cab8YvFZCWSmB9JQ>r4<19yttQ1CxH?tT-*okZQee4 zlUezUIQC_yen#=Ef>GMD13SIZouX1va?#%r55u;Y6}vm!9&B2XRx9{I*_Z?4)Xg8g zq~%-PE>5@`UHQHyNU-2zy zmN_Xs`FX@9#T&l3@m%FdXbI(R1{60by3&jT*t~kRuhohB(Nb&wNuAtlT+1Pa>q3>- zC-fx)ll|4!=bvGaSSmU38ONpT`|sStwsa2HlP8;YHulc4Pp}+PNXrKiVb9knl;`h> zLh<`rNM%P>-ZyLa_0r&THU9N5Tw#jg%NF3RHLS?*_Xd^dmyMtioYg2&0bK2ZX_2U#DQMT*jRw8yA zF9FT@#Xx(1?;~V#YX6;3RDiMcwcLj`G8yI{Kv#oK!vk4aS*+U?K8HhdyZjW&yOc@w z*&4=LF^Lq!!I76e`{8ju~*xtj0CQ*AXG@O@{Nw|!%)+2EB- z7cQo*#Cw;T(b}7bV!1l3d?FUxzIRa&0JNl&iuhlU$HS;IZgi6VIdf& z9b(M(9;-%)ciRzPSjxXA^1q&cYQ4RCy0MBrdJ3`mIY{jfi+a*+{go2vyiVABD4LPc zBk|@z6dG+rP~*Wm^rqN8fh&I4)x-PxTkT5s^|u(PW`>277)Lm65Q z`<^DZhS@_w)lIlz?;70vnQW{U$0|s0-QFZLd&KqG*hObW^z5+CSQdzpY+B+StJBpo zUpm7J9ZkmBX88pN^hIN8iY~J$wgkrpx5~9&a3gC6)z?gz%WS4)OMYwvE7{S=-`YTr z&gFva+69qA1+0-b-HVa;oe8{x)*-Acx>%3#M~w@)o`ti^)7e_|OUrb+(iAye`^mzU zPD^L9Ush$y*H>P|pq5{h>X_)#6N+oRUg?;!l>y}J?857sY|F|lN)W>ex@_PGJM|EN z(}WzvVtn$24Fb%e=^HHE_tcxOkRdH)Hu)vg+%CYS%^rtp&70a~Ho{u5&9-w*#SRe|S|Nsmw_8*T66Zgg(hp3kP?0K27Q%b6HH z_57+8S2rW!%NiRolWQu6oHaUcJ>nf1i3tp9f{Q`jsIZZ5-(npe-fMrrg9(;RdW9 z3mnK)G>Ji79_T;Cfew%I?Tq*AwE9A8F^2p3aaKn(g|$syN9Hb5JW~WKq4 zFevQu6G4+H(dYGXt2^`I)+H0gE3M_-#32?o1c}qELTH6zT}p~YfHXsbzsxRUL^A%= zqpCI_nmeK_X$hiwR;#y|Ul+L!@R#Rkh z>i_>xk=`=2H_G>uok^`(R31~Vl=-r|X+3WzaD7iOl0$QV3SYJ@oJ@#>bSjmZ|;5um}v~~`#KZ?7AX}`@qvJ%y> z;mGg$7&C8|g8!cECL^}k8ex{y_qdARvZuj;gg^sq+9XJIspfF4SVhv6)z&|L$?xLi z;S&!jt}%?aq$?;*VZQa1hD40O21T4%x8vIL9eYoWbn=7UrCf@}&d}qGVa*aVj?yog zt!>W_fm@M0%IwY__wt4{6O#6dFzo}wZ+>=IN8||@HCEOqxD}cmcREX;+61?)v)C@b zJC0DKTb;z|Q3t;lD`vAZyxiEWaiN(lx$4u#1;nwpaZO3IF!Zfr6!3mUAu-mz6Ia?& z+Wtk^an)P6et_q;%T1fucoZ+0Zl2BMmbY_6#a<1sozqPx#n}ryULv zMVqmpkDI&XYVO!cp#qBe0c(V^@Z4xor^D4mqFhiaZJY?A0t`UJcY zkFr&@wrK|Hu?q1g3MWC6&G|U}qiK>Km)q0&Z+YmI~@?vdp-@Brp)=Nr%d8ON+ewOu6 zU))D*%#s<2eX>y{Tq8vLRNyqgG4cM)#cH#=BaBW-3`SJ92zcZrTXFz$bAJmtJ;U4d z(##npn>Djb>=~k3?(eM~-c8%Raj;^8*{9%Q_tJSocMS&4A+)RUJr^ts+MfVwjb zJTRM?1(4U7b1lUO^B%M&A5rV}&TC|`EsPnh{*Z<9F#2 z89hy!d*fmBL6%U%KuDaC^DZo=Zs+JTPkE2bC7KzyWf68qIJ;oSf80@K#;{+Phz0S0 zlz1dJbpvQV+dH6O85p~=s*sx8N*xpVJ>P&-h`vInL4EG*o%*MK&=1*C4}nZ7!}z3I zNv^cs<&e*Pdv7Z%A1$z&vi7j>83gWJPakMe=GISh{rNNXm~9?zW!7>eyw&fs=mrnP zFH%2Ugi#g$P)lb6cjA* z^Wpgw@z=0KvRzo4d;eS~dm60iCf@Zw30^Jr+?};$NN;&fn-AwQLwa9;Se{GYw*v$P z&NO^yLp|vFg=f--LPr5s0X(ECq$Y3RDNlH@eTm58q zQlYDi$T`X0)t;YLJ2FKnV`2N4c&IhRQ4mhWRPT5rE&SbPvb9*~NWXKRKs}p^k!g=$ zmeS($-deNGB6f6PEM&`-`#xp;Uev7Omg7sf8H5X(L-kDf!TU0vnb#9k9?HvhK>NLS zV9sntk8iG*-`8*S9qic>2;7g3C}YZ8iwH-pGudbLjL5F+T?f{T?gj3RT8i1M-5MZe zYhV)%J8{2kMG03gHL8_t{eNhD{ZqH=(VC~Os4_$=lxy*s`1J6p5rvV(4dY~E{#p`i zLwXd*4*jMo_6 zszT!1awf;tUO-Vm>@MaWvsL5?)52(|2Xzd;+ocKO=iy)qz$fnT04B+zKxpXUH{kyE zANE{Ff$ufD+>JLbTrm}9AxP@11{!uDI(;fWu-dcl-~K<&Fsa@0crh#j{DP1UO&6O; zJvsXE)Lh4FeUW*TYWEMx9ra-~dcz{xhYy&W_u|5UB}Th#c|EL6^Yx(Av3ICdA*$Ow zhzqIPR_*OrVt@z+Nrett04G%c2rH%kA7SO(oW&HWD2HBTJo{81jN}R}9*OlAnuE-U zyzH_IIionL;$m6{0Pomskg8l0ayP+o+}e+--!1>#YkfCfkFi&YD5j+gmkE75f#(dn z&lL!ncNzA|w)c8J2p)Chw{i-6y6TRK-r3H;i7<~jb<&Uj(%hBy72%;{(VLe$?-0dM zY#93a!zaDjH;yDr zK$}790qkNo0Od@1+UIBP?S780j_!+OM*yq$H6|yQRcgyRsO2J!_N(s7Yif4E@>Yzg z15*_}{48aUay(d?e@xHE(I&;_#g^+?uLL~F1Ex@iO6TWy_ion8^@xG13{w{TNb9ItyDeZVCcoV%1*;JRPQL)2bRN zR@X$peQ}((jD!3ds|yv^`chXHFci9MBWA0}lJ8LwD$~#K4-XF)HFr1MCk^#{5}5R| zdFn(%j^5oCa^kki7rA4;JUSVB*rYn&WGYQh*f=P!VYad1Yb|1fv3?p(J>Npu>D`_> z*%PI?9AIyB+QMtIE|dyie4z#o24EH+DTMWn`T*V3g#|BxOFqn(-$m^hF|<*BU6QT^ z{a!`~;fqB-<>2tIxqO=YiSPjH#;gOAU%*aakRLSic58#&wq%4tyR@MfA7_X1L_Llr zuzvAuMUO0-&#raDZTeH+p1x-7Hwt~y&L=Ag1j||ZevM^sdz$YzE~vrcHDGXxAV&J| z%!d2O^C`@nN}*2o=ME#{Ao$);{sckL$H}>JY)1E%;y%@8DwMu~uu+Jd3c$IFoX_L+ zy@lAW&c{AKk@JgAn|(8&Ha&42-KjPF-VS=C>$F2!I?IP!5Ej|l&F*2@j_dXnUL9Og zVNp;xfK0%+C4$PFiPU88Zn=LjsIn8j!;7kQ<+P2A>7^$4V84Gq+f0@?Js&z&hGkb3 zc9CnBR7ty17a}bn?>GwYn%-83G`bfV`57LjqH11jJA>*{nLtbxeQ6yv*bPPs2PlH~D}_>5q}W*k$?`LBN4Yv%XoZe3Fn`T7Kr8~9-KzP%atC@35hXYh8e zjdBf;8>PvusVf{Zh@%Y|fJxNa^|k`^tFf3)ALyXF0_!WPZr|r?c41W~5u+3ROSNj1 z&d|!ayKh)m$y4627aBumW(g?6DuTl?+ioAz?nQZ~ZowEG#RJ3D4J)WF#8$}HNX?;f zOtyMq2^pIuB+(mFnm+7NTYX$D09A*4sGDrQVnp%Vts6llGeTUTJRU65=QCSjRak6z z+K8r4L;El6p&>4MlU&hc?cUeg!3C#NPKtnV3=ALz#h@pU@_E zsjCEV%B$tT4%BI;g;~)@V5P>b)=+1rZ&AfGXGkoV9hnt49v8{ra)`3%ijAh2 z-3`dN$L8L|m+h_ZX?X!ula=Upua@zo@@Y1quF2J^=5)dz^^PZjhrdMx_C!iWFMrPH zke*x|jcO@?=r)gf+%zF>6K>PTzu4LO1!{9gV`j&l@AHg}R@UwmXiZa2N-olScxL7l z&1!SuHwU~gq2ZTnoSw8rlT^|%yDQh)@$r5Ptl@S?Zh;^`L4j+0?qDm$%;2b7UlRno;7NbpOgxAxj!X2F4qFmob4xa8OZn)m2NW}T- zNy@zmq|rGO5x59UvQUi;*Sdp*^}n~Z`Xp^I@pez}CsJ+HNZ0!!*q#V%)6e~e-FENq zwDdoE%m4FK`k%A}XmZvI(U?gZi?VABB@)8LCePQqZ{1>CbL(r$wr-KsA^U*TjVVL=iv#XqM)F9{*38!2i%Uk;1)_qwLHgHe zxsla3#SD@g8Z7dremC|u&d5G?9{Wg0>5wkg;smKx#Zj_nhTFLoKh0e z9_7gEQ7b1s*SF`S@3g}3z;q%3lzUye1Ji2-tzCa|csxU}&9NJ&3>qXHZK+TyKQl0M zb$Cf3ce;=@ko|1wS3ofz#MULw$KHLz;OgBTJb@dp+mdaz+8w;kt&I$_7=zxc{c-Vb z{=>yP_8%kx|JTERNi)!Y+evKkH?ZJQiuoKq+8qCfcl>|PQYlC}y-yJ*0$p0#p5}R= z;|9oL{QL->K>hwnfU}lM%S$WelEEz};VJ{Gd2Z)^3WvYYs*Zm>zvzTt2U-7xcAasl zC*!8}sY>mLl^#POs@@{DyDy*!P=E2U^EXNB>5=2@E(!rgA`q-MV7<`Kcagx?Rued~ z@~}B3$}|ofOExeycAcaicFQxYTWB~cO<+luC+dw-ux~7VacHd6tyBK1-l8QKC|qVA zJ&Q>-X$=E8`w3h2+ty7X5?SH^O|hk>+!HGs7mcw=U#=g+x+yrs!C_X#x-o;O(s%Wc zb=|4qa^u^HZaNh6Ssb#e#CbBvx8bU`Z6iSz_$qws^2lJsPOQ#m`K6)N>k&g)ZF^HI zH&oqa=onpEc!oe6Pt^65zx7!pTR?+B9nrxf@7@e(T6}L`;2YG&%Be^cXugKwYrFQ0 zuwQ5 zCa)glB|`KwiuA4iwzz~a#FHr6wjqXk!|nofN_oZpLOYFy;P56e%=H7M^VZ$r4S?wr zU1)P>xc0Bsj1T#-L5z7>mUUF|B!VHs*ZRv@Epx|L3UjEe=dQLJ`85vO`5XruU$GKb zYZV!RDVqfupT|`?x%#=QgO{go)>7h+e{J1+Q6w++JCl*e*Q8rEHRMY;N=MDO$`0%L z^7!OT&25XmTsvuyXw-8~1}Lv>Z>#o5y+}WkOw13@{Wvr^^R;r2Yw?JBMsGDJs8IxY zr209|2BvY%fk9x{yF;E&8IAre(gfF|0;p-sfAh1y9a7%t9?Q79q4IlH{sbGJ!B|BJ z2SlPQw~B;a1+~w*X_hP%EGva@k@~<79uE?81}v=-Umn>w>{}+SGAk_3Ph1!bFywq+ zbyXd18J`P_K0Kj)*zYOKWMBz-uJvyF{gZn~1<0yq3$)ehi_9y4Q(SW9hHP3!d>cm6(htw zosAgMtG4ng>br?~Pek9n$DEsXV@GCSg)R@A^(?t~j*e$wbl4CgisNA6c3zT5ZS zNlv_+6myJlX#I%Dso3Z%aO4>}@R#99* z#Q*}8Y&vxrIW((hk?nl@G^+PN;@0j^3_Z`r`IevM*>%qd!b6LkcO_dley@i%EXcCP zhd427EoZa)8%1pLkA2gxYw=cNu@v_>9DZ8RgQacv%q*sX-y$BgZd9(WB{6q&XLN2eU!?6?mPt;ZRL>v8WHrGIA*U z+NQ9gVS(_(pieu*gg5l-2;xe|ZAxWuzohPCv3x!)=9BDWczLDOxHyHWMQ=ZY4<1>~ zu8~KyJJLTQd(Bzngb1KbiT?R(bK+9FdxMaQ!S%GmlB;Qm{ClZj$Du8l1gkb#scVcm zy@iLuYy30Z1w%Ni@%Q+Y=!rNO{t%<-gjlBI1}~K0jeFhEr*M57k=tj^o7{Mqjn~LcZkP3Bs<2)Rh>NZe?oRaMU^K4fr(6 zCzD3=>wVS!}-H@@Aq_fwpy0Ezf!}=Z=?u)-#g?pL)xXi5u zrH*#vD1iIcS3)UGMMMTVo2*b^EhZD++pK-FC-8%l3aVvIH$51(lBTsiX#we@<)4>@ z)=mxA>?vGYW>#z~oRpWRpDJLW>*bMFNh7wn*dN6S10!BPYdLs`@|rQfZuhxi_ zHZHYc+JC(;*_Jw9g@T7^@-kHB%cNA!^#f$|a%3jCkdb)ShV0s|ii6T9a~>G^rOw^afGFbz z_@F?AC%1C!dRFOqUEKeRm$~?@tRXnk@xE^Oq;eM8-s2^=anLl0(j zU0`crtSp_V7t|ZSn@zTth2AAJnKfh#b8>*TR+_?-OaBJYV(ivCYhb^g6#|5q$o9e<(CkXHW< zf_>5VztJ^<436E4I(!f-y!`Xub}?o-D{heJz^rN`-u)7KlEwaA?-)%J3dgOus?Pju z^K{zl&|%IO1UQ2tcSIiDw$r%LwL9g_Z19?6p`1XNmZ0_2^>ykmy4qRV^U%=wQ9!Aa zs&UT%1?aKX<*NUpWDRF;ewV#+I%!j0Ldc!VTgg7lk{t?!+-}#Jh~uJv+VP#X>P)f= zMHz2X*DuutC8QPZUufMXOyf<4Pz~vmUv>ca!pzr0Mhi8Sf+k_>5HCMo z?~+dLi)C+V3y*8(kSBZs5HxfHdfJb6L|D3rlFBY{mX!w;lv!dE5pPmLzxzpM_aP%c zm)80}eKqvMpg4`P;iatPbEe1-Zk2>{`jd07(d>6E02ymJ-QNwVNt3xpJp~;u^k5sq zW(+fTJTy05OU<$>;Zx8H?GGoE1r&#{N3ZE!4_WR6T$3T_qQRJGT8Tz zH*xDMO>D{a@_M{!3*MG(?;WzjZ0_R!WbI=t7;*;`IMpEo6)%tvz7^`Nc=cEloyXSF z6C55^E&5>#4hnS>({%SaiE_9PSGL7>5#~vqiPCNJ9pD@GSap)1X=H%6ULF+&p>dK= z8&d;vAx0#R`FC6PwsV|#Yc}5u4#-=C-kuG&8mI3yWGDVJO{T^TohwT{4q6ieyLm>U6jRh;e2%~Hj_w#A>Eb@e*6Xz?vxa-d~0 ze9${;R&5QRLf?LEY-mf1o)fOKgtqLoA{j~-=l2!3Gt%OWbGZO4gqdl<8PobFtLZ_q zhV7NnD_E-9>?%133$gX1{7;0k_J_K>AM7YZ0?^n=kaZfYLRx+-sxlXJv z`x_rLWp%Q{#^53PFMED5iav3G{XzzIaV*!3V!GQ^U0Ommu_2@lXS@_cB*?c-*39erF3@|WWfL^^Bc)91)AQwjP;J$FjvVbD&zV=t zYNg+{Xj#S4^z5Z5{AV?eT2vVwTJVXwhr(O7vaA88wZv@~2vr^j`k8XMz_^&d=+r`3R`~w0AW#(1y2GuWEg6N*IWWw#2X=Cr`V{Q_wn- z;^wO(sLh_nTuI!jVl@&s%r&wuwDBhyxWm??>EtUqPRmPY8jV|e+?<>gV;16R3Fu^V z!TZgDVUE(sqT2cYS+4sxM(h7&88(4i3cF{B_F5wZ=v@``I@K+Y28IDzSf9Twyb^9( z-9O%`hH8@Jm0l6{^Ff4j+zB;sIFqN%cn7?bORW=8hGD7Mdm^|P=%Zlc!MjH>ksN3@ z2YFtEZ%U6z^JnbiJ!6>~9%xms!AS+|>pSaU4}uPZ!>Cg&1I=L|)4ac4?X!IJa|2EQ z!HL|+4X-8agGIZ98Ko>Sm!H${+GZ0zdk2_KK)l9V&wuPLQP^b9e+Qa zzBmXZD&?JFqk!ax|M3WA6K)>=LpAgF9vc@|d37(nNzAuqQW;=^gjFC5qkZIjueZ?; z*lje^h@c&2_n%IlQe5n?RN1sy$0MCV2c>5lO%k+uMhOqUekaHX)x^pW1Ooe*E2~J^ zy%n5)eg3v>y^fj~2Ny=|H1Hp9y%WK%4mi~#sU~NsRdCEt$RB>&oPC~lWrI@jk2?Nqq%GNlux`i2-hOdC-)4rmt!sT?gddFY8tDL-ZDC5DOTMg@q0%$+Mnk}LWeJ?@FqZIDfhxcG(B}HNF=J9 zz9GG*>+^T-MX@455&E(-r$H++D{2hcuy?8coL_X!^0Ko}9E->A;aJ0@-Tg|Abs5H+ zDSEa!LI!2|fu<)E5VYg8s7mc~mC$SW6%U>pv@3pV)#^o#>P3!&Ba8bIa*9mkzG>O{Fo6+CF2~fry-Ev8(Nr6CreUBhF)*ya3bM6ZoTF>8qv9t z2{ko`4hG4Ceq*tCbRm=!h^kh+YmptG>v+Qflfw;H#PuF(HAu!X3|)PljL0;&{<#6A z!uG5`Q`vIcO3;o~({IkbwA*m7v2!&oUg{pDO{@D-g2E(`K|23}Tv$5mlGeOjn2XA~J7kGKSgEi(#PWXWrSxG;_Qe z-Uh~{gr8FBr@K!bhaYCNUFT_V=)sn@;0T6A&~5L`o1kS_iG-u+aq0Y-^`QCn@a*!X)ayAAZbyHc)V6k|l+eKmgv1=?(_ zYh=B+jc*DG>0UUYjNkGrGl&tE)Mv&FNRCT*GMH4IyFV=AJkF~$Bh}klUw))T8&%^g zA2|Bv0rHxi6PdTKt~1+bb0~FrBwSM0IZw;=LCgXAHuB92y;<1x^=Zqx&DvF!GHXD+ z@LMZUi5{B+N~GX!nd^|O8Qqc7qA1_Qi$+v%jtkGo4MK3PlNlNC-N@1I1thCmzwpZC zx0TB!ZZvMLp{Q6npCPLZD?UsJK-FD#M11{*+S|ABkBzunsQbOcP?7TN?xCL+KPoX@ zrizmGI#uqu_+-u$d9u&Rz=f~ir~qx73m26T-icqWF#c2tSSIzb%4GPlb&)j~$5?I6GK1N4+$nywi9iq} zCRS`G-_60QYH_~48FNnd^2K6T1JHL07(OfDbUnAHJ$Y3MalM3!)g6_>sBs+Wp^XKc zU3*)|clO+Px+z{|-<}OPtQ#FcGXjoWq@=4RX*O5HjP%0!(h5<9FesU1H>aEpln})>FvQs5!cK&B08Uj)S5Q z7VBLk&*B^bU+fE$+g#3%C<1&CgL?W7o01*P))5N3Hoez%9N=c6@TogHP<(k@2<-t z$9rE?M$W=pzg@O&6Ue_!e1#@Z|iye%BrQ7E&4{PipgnhI}4VQ|| z!KYE|(;0HMNTI97>Q#p^#9&+6ylDoSy5R$ z_>Q!?>xq-vmGyVk32OssW{1gd56#i8WLsUKGv zoQMX`*ef3Sc~^?9bYmxw!HoCJX_B9iDwGPbQNHiJ;W+JRE2f$>g|M+{|I(~+d>r?h zQtN?)$X`qT1zDN2>B@HVe#aok(ZyT*1V$Ywr2B%tTA1cJxyjfVbd)EN z!Pzb6g7V`9aTbqt9sGNkxpSGouU3mO%Sd^{1KJbbsFg<6w`5p+Og%2?3%)7@p)q@L zEqBa645~y8^7SvZ_uQ0OUzkC$L#9!2y_5x~#OEz>J!&awsEV<_Q-FhA{A13(XShY3 z6QcPYXLa$5+)ens%wYL-%-3pQt;i4Ie))xoHUZ9E1k*<7 z$M@*d{WjjQV{6u+#a=8E>z>uK5xG$k`&h;xmtBdDWH<#aI6QoO%vM)9Nm3|XkYCKF zyF_dKElo0QbT6{j*PQIR=b-YM6K>h~K3cKs#wl!>{e39DBPEWF)Pf}?1)+3H-Ot6k zLvaijQCn6}p@ZROsIkp`%g+q5=*iPg!s&jet%7@TAN5st3`Jl8w5h{MK@kV}Ip@O2 zhc&N6i-_xzQ=75)4P{_pw^G~;d0Dz-4}Xt%^JhI>!M(#tY(ra}lwwc@{rw7$xJxZ> z0pv}JF~#Q`bf?w-)^tTBFB zxJ0;p%J(^r+7TT@xwI<;K?mknNq2a0OVuUhCR?H+?Dy78I&9-Ie}Wk4BjJ{ES4(m< z^!Zl@b)xJ8)jUP60xa*@Uif}#jIB32P=lrD8HXQS?_5rvB)^HS{wXHn8=oPoH*C&skvUYmMm*Sw_Yyfhr#Tlru%noBEFE4OQ_8c*af}<} zit-r|jL$H}+s`bC{r(-&XjKGoQVG~L8FQJ^G(?r9*A6Ls-8$ZdjVJE;F`T!9FR=E!^5DSI%#CbYb#frdq%C&V@DA^ zn_Mj7*|2G9?b*u1vMa@%;Kl~Z$4%3d;7nWt9|aZxbQ~{nTBz>p9nLkuTt!v4LBc() zBzBaac#jw;2Ws~`b5gKPVtAW3A!vAx(v)v(JNA?EC@TAo7-_~X-0zN^MX+6hn2$W4 zfKkyse0-@xrxv z>AnR&t#8yC#=)~(+K1ea4+asfPa#)EJY+m%3wSrm=)1HTU8l9mx2>(Xi8C^C6Vi2Z z-0a=OUoXA%cC2dr)UgC|L^Cgb4UQi)S`+5I*CL;(f)UW0qK8%fDF1V@YTOns_sfxC zQ_sFt@CKSz@rzV`CF;qc-E+hCCnl}qH^UGE|@C?(`r#w=_iF?`@=?qztB3A z0>qVb*_89cYR*)G#Tn3Bxy4%X#r+aAbopcwO#X37NO}eNa?;xYr6?CSP(ncVjZ3#} z)yc5I;cH}7*cACM^e;67H>{RI#)zj!#VF!z;R(woVQR`8aj>3e6WBgi3z2tvoi;^T zryqXESIxk!rq%Gom||rn)(3;&X;!Zad&63a$MpSpy@fViLtNWcq4SI3wcOk{IC#jS z(a%>BgmO#grl^Ya4ImZ&c3#UtwqYd@`J>(nH;f7FJ2X0a|*7DZ`o% z`J}bPSLX9Hti-Iz#Y%pybdtK)b~WDPG2;W8*ITKdaymQ4M$iI4gI+|!4ZBVoi&e~a zv!h?pbKX*WRE`vnZ2h9mXj!sQL4}w#&%F!`Eck{3j+xjT$n^c)iUeD_1f9}ESpJ2k z%lLUQ-cTU-jJ}r0eqz$wxj{bPP3>sToSXRTAxqo$Fg1k=rW~X}2MseFlb>pElvosz zxsx>>-ttCHnO=CBhmuGGO8r`4dg|^H4byXRuFMb42rpJm>jvxT{SsTZO?D^43ZQ<5 zbgv0Mz!D1t7p7!8((;kguT?)=JVaJigZ7g&vLVbabTRnYPoz&q>|~B!UTa z#B`!gh$#MbxkR94 zsN&csvMVYR0V)&I4S}KG>e0(Q7w;? zU(H$bZK1#ZHeg3_@)jXcUuklJr()^q?b1zNyTh*?{T>&+DrW4Ym+|`&?OF2GTSb8v zzYY%aN;G@^LbK@e`?w$cdz#o)nd;1X(>oCFWw|NqJKOcwehj>Io^+3uiG2jn{a_qd zD@H}F#WlRzRV84kS))yBjq8MQ z(iH zmL!B4lgoPI0&qrpSE}`CBlb5Iz z^+zUT&7Fdd0*fiYutPf)?|{snTPaNrd65%gj?5XICL+ND12>4>Wb*rGqS?4$CE zTkvGNLIy=7a6_?U_@SuqW15c}%O;*1Qmkh0E-%8W9hic53?l&LY12+6?<>soS15C~g`)GjpMH0ed99YoMyTi}|+< zg7YQz@s7TdgRQ_PZ(m`KE6vUzl8!TM`A(nT#Z;$M*HdGR+L)eti~A%1t7`A1Hk`S- zNqvI?imq(I4#s&uK}jB&a)TK6#JG#^Pj}MH7eI^GPAIo^l`>DEeIv&*cfWSGD6Wi& z7O{bSEERD=hn~PqDLW2XtImpxpX`3|34_y>Eu*PWyf4pJAybI^Zwkb( zeHxtvEAPOtKYr`H?W{XiLscJdDISCE`)Pj#oUW;ArKWdtmA&=#rU6HV6q7$*{hQm` z;@{oY3V4N;H}<~uER72V5kUh^2jP#e;}hB$bp4V720_Zw_)ULO0t9cy&E?6KJgGrd=DGk3w)2-Y`` zrA*$XVRxLC+1j)@p~k0GK3s8r!nQ^vpRW7>&?nN5zgH!JHUa_350V*J*}Bc9HQ`8 zDZBpc+JH`mJG%TpgiUWvxfc0o?8E!A^~%pjk);^ruPg(RqzJ$>SKSJn<&En0QpuM} z2KBAwVcaed-3?zN7Wy5}+&~yTSJnCxv#{=CC>Xj(jsJEQs8w#D>v}+$_`%9?Nz1`Y zrkJ;ToYFI?=>u>EO)KM@PEq`MEm;bIA#FBhSlcUNMC!&y#^%lP*n|q31?l`U{HqXT z>iX`6WFojpdDba<>k!uaV;ZH`{`9G0_r+$2iY6Q!SZMd`p?gN~K1CM8va&}~7-tHI z5h^COuu#efMTOM+*0EBxDDyYuTzK%cd;M?Q^?j0rS+}1AI(CCY6ME%JF#Lu&Qmd-R zvXTdxvnyz3g>RQq{pE&bJGcP`Y*W550dEYyra#0)o~V+_>1ubSE@;Z`C^}#S9YgXF zHR-jC5S4HT53*hkC034UUmT@3YdB1NmTDq0`$*m|GD5&NtsD8S5WjKsZQ5W}{gMTdYsfa^u0n2gz4` zRnotD61-RBZN;o2CNI`wPvW~*ULsPuyzd{6bzH{;55iOpbWOnDjcg3ex0jhg7oo1;wFtt7V|f1!~=bQ|n^FO3T& zLZ=bU#(LJwvKB3!!{6&~3P!OHl7W4ysRs`}3yb&lD5M6Z4h?496V+cwZ!reWjzD-i ztqBuktW6n7*g~U)$qBYLC`DV-D*JOa(AsYj?(Twn`3{rPmb55&=qKSsGfwJHsOIL@ z-ezsO>2H7jcRTIBX+7okPxK!M)^}CDRRTfWHfeMzNoXEQ4=iwp4z{HN!UnR3^2smu zn8tyj%&Tdm9{CC3+^M#J0%c$>)=X@GGTCHThZ(cUzP|S^4QMBa?vm_&^cR}YLwAS-vD@9@t)Ru&5eF{qqt#_Uc%hhCXk}qRCj~KGxlZ)y z^>W8yJmH4;p?VOYxFCXq(+1*QiSuPSZ`)$Js9$Y{uafJYtDlrY)bQOKeY*uUb^2rsJe;77*dg*uVYOp%zmEqOMptdUAJM!h-xa-tr`RJUJKB zmMWIX;i~8~!mmIGz6EAuqn@}8OS7F>89pnEhry;ak48sh4t6=9%rqz?;1ZM3TMz*Wx{X{APuUU?UQKciRhw;z~!oT^TM zP;Q5vCukat z`IDQt>O3pchwj909MPr?Q%iFex&cKLZS2E(TLv3rF1Gp%?G=K zuQw-;wP4yAitkN`%Xu+=8$FVFn6{r1f3sRatZ#&NwFyt3LR^)0v0sT=?QupiGV2qlhFG1y^C zxStACKF2I&2C)t zLyN2u^U}Hp+(G7zkYVly$Gs@iv36?%c$LgjL0`AuA)>ouLeOvv_K`*Eg-K`Yz@5lb zMXtUhdL-1&A7(e zQhWN)HUI3P_b#MqT{E@8FE!&n+E}fe&H)T&U?LnCrPR|}UE0Bf5?I(zw7ou@sHOBU zZF~ldK5d7yle(o;C$af!PQI0*z_H7wE%Z<>&Ri(Q>7&GfV)h&zvL4!=Xhq7Rqmzn# zRj1;^67rZoS$PQF?5Yy+CC^{&E3_S^CVza&9 zmpuEeje?ESc9M|b&iY%NvwQ!6HD}cYPF=ETM+l^Z%n0*TXTEqHvr&>S+n99kFn?MZ zzgtluTd!6oS58_`Gkbc;ZAkU3$Pbb7%U2iTDr6s79Rw^^*R#RaRltD<*9>?)sz6yhMLCXXsYOd~Hu}%PlImlhR=z zR%D3sAwQYe(h@Wy@wxp$O|lWFBt|dWW1g(kptrQ|iWgzYBb~VJh)H3f??pvq0guQB zSt{5*?WYyy%`lzw#c#n?NPgktP~ZOfxc)`VHfR3npx~0uhVQGJRL&187vKZ8U!B_~ z#h->w23@hlW);R^ifaJ+)F0sLxJ0L69&b!mVgX8R09N=9_Hb^6I>#h^JBw#M`x(G3 z!CP)Hs@n`7+va!EvaHKVp$+Pn)?!}nX2q80(0-98G+Uuu=+GgL?Pui`&lXxRXL;Pc z=IO=b*)2ue*H9f~Q$n2E>@t<;TjFL&SO(5KWX#)JjvVung>~KRA0zAOEK+;w9b;Rk zdZr3#GmMBUM?_-9avchF%oMcAA5?>dc}?$HQ+?#v0m1&5SVUyz_7Ka53e9HqtW(#G z-x5m3kZ++VDw&{Tm-c&U`)FOdoa<~02n(e#O?D2KUV6lW`%@#XS?#Ozx zOLI9yeahQ5Wu^9-9FlbNd7>w?R0;_a<*n5*m2CC({D&1GM$BbR5QFxdr^S0rI%<#< z|K@M7#6nx+`pki>aq=qUS}0#?xn;yN(MmGRd|;7>`mSPb`0?+hmH~dU3Qi}wmqe=s zMPO~et8XF9e8~D+p>&ZCdjOBj1dYwCRzlo0aH$P|h$nsG)do*PaqR&=lTGXQiaX6= zqHGNEGX2KRjFFbBk&vjGv2fS zN_LPSZ*%U?jMybsuHskd#U`YV6A)gFdwz!@=^RQru8S!m9J=aWO-W6z7Do3*Fy?x zy_=&G1snQc(J#$>$PoT8c2KsDRI+T0aV*=l<9E20+*55XTGPnp$oP>}3R>qwL!aBX zqoPZILrX74H&9Nbuq+US`5DFIRT7`H_u|tN-lGYg5mF%aB}%E)nQdV>vDX&O$tq2b zvn~(J?z=jaZ7884qPaLPLP^U1X~l?9k63;MBkUXRg*Kzg&}b<*cfJJ9 z$qf$_5b5J^FLW>aD1vWR@wS)aQ*F7cIaR?EuTlf8^3ln@WIfpP<1>)C3>Caly;NOA z#m}P_p?UsY`q$#7Uv9S2o{dXmYMRg+J2KTaO!P(VYT_vuPJ4$OoCrql8KlWb!>e9GD6`4{2i2oT0yz<&jx3N)~%ON+H|K7icj7R?c zEXf~pulx}rXLh5w4yzAPL3ydaAJtxR0WsD7{mq!_vJ-A$U-oE0s-<0iu&m0BcfoZd z6CxTJo0z=VZ1_7uJDsnn7+&8tOJ)6lv*;>pP__adIenfPF%9K38k{9U;P6y~B*HX{ z_rzT0?BMijUvotoJTpD;kyjYat6P({Y45v)Ng$zDOpVHFk)SK%xGJ$s1qJz&3+a5> zJrXPFwreDyxb@4I61xPOM!HVhhznHu|5=ja7wSN0haD?%r7kuxqDTJ82>1)`onuvc z3m$p@K>5Lgbse+300g)=yXdDd&%zI#o~aUqs~MS*0bgIC_)xfm$__rf8P6Nm`BC+J zDz4u~J0nNvJ5`Gf$oVr&+s4JJu5AJL=N^KWj&|+3k++ggwjyE~@lZ;K;zLt=ZU}ib z`$jr?3N{4!jXwKSX#b+~46(B-dPjaZ`+87BTcRs*qu40Bl%Jc{E^YFwA&2dvyit?q zmUf9NJa7xQ1n1Hn#o*;^$Y%u_knDV@s!z(dk)0gc-D&ixhMfUqrkkdPUxe^G3qTJ? zPjz{r`P0JR&JU!tDzYA`8qQz)3bSX%C{3)NpYZz8u!j4GDoV>|7yhc&5Fm+#@MFny z5#Q+%*V$=ryqW3=5f;oatboZ1Eq!L%&;AF2mvg4qf7{5uwH)GPCodMbLAq#CS{-km zf}%&VFu$f-6e^CEP9F^s>K3yI!XuH%egx zLN->;y1L0^Y^u=@RLIzvem^7G_Jdg;eJ|aVVdfqi`*oDFx3x&vl*6&eJx>N((;4w} z)_vFX6|UDRaG9?hGA&${Q>R7abzII?NjE8u_R=33LRQ-2X}NWdc0V=9qFG(vd2x(CO2#nz z#PIYoCtp&2^|KFhE?36-;AC_n-HNNkO^vjV8iOp4ZW^k~$|q(UQ*pVGcFQD&_u0f{ zwondamO+Q4UQ**JtmVMbJ1XPX(nT42=L|)*eZ_E-&pJAM12gqziQn{Z+C3j)&!+|` z|AiJNr8j+BEC4deDVl+%2sjcx6fSsNvcxmHSRQ5jy9g%PYhNJo7d&(ncpTN{G=Hsq zA53mWoWNQP$dGPjnm4KRb`x)9cJ;gT#KH}oDY;T+BtW*mmkQNBj`I{I9)NB+f`0O` z&D~Dc?UN6>FSft7-t9g%bWZMPW-2PZI-n(y(P+WpT2u>+3fnvekA$V}< zN#FN7XMg*fefHjG_8(^^v*wx1GszQ~XRUkP*YCP^BI+b0%%4salniC4pai4tx-zPZ z2IRH(1?XuX7H9Gk;wB^uv%GgEd?zk4|4GuWFlqd?@E_LpE%SfYApCc;+rRXEF=5W? z;{qr5{3@q7)CV2-Y%pwgL3&0CobtMvc_C1A4dvP~&n~0mSxu6h zIL1ft$VP9Orr9t^2x$oxa(81ZX{{OVkr_{AhP$YoTX)ISY*y}*PGNt$c-xCYh&)SY zod}ANLL44;|N7NxiIeUJYx_*&dMr2nQb<8(gfC&gu+3lBHykJ(#lkyZe{2}nec@kt ztX2rlFBIUDI1mC@HK5%~fr^wtQLVCMZxG~)1VIXDR?(+_+!_4Bi}IS3!Yp!x*Odo& zgDxH);-fWSMi+KR{I5r8S?1#QnQ;+99^sS{wesGcR;({xF6(@ld)V`(X&cz42#k%0 z4!ggCi1gcm9eWIm#=u^U=DyrHdeL(w=N}U4HC|fsE^`0;Dy@g-*m|#Od_>7f1kx1K zc;jL_()}TFl^P3+*EU5XANFRFQ^%cH938&K_5ac~!u}I|Gx!I&_|ExvE9qr#NHr#o z&Cq4(z+Yo8y3@rzb(7OlbBGsr1Ue2o8~!08g;x~n$IRhV*_HYyh3&n`l=}np;}fRA z8iBzY{&Sp=n7>h5f{qlrtj9{Ew&md3;!;QVOtzw3 zrD$4uK+0C1=-n+zp;cy<-S~}Bo{kQ^Q6d%+J`(9vjM6puT(!qSli*3UP|=EKHVdSZzD@KPV^J{iDvu5P z;uf_t?ZA*1OL|maH|?%86Hr*N!aOVsTfaRyqeq5 zOazO(6|hPCZr{TC!cf|4Zo_}=>5kjHa8&m!7%s&}n>uGJc+Rxyw9nmOAOGC9{83WK z0a7hWz|J=LPmZp`*4|Gg9c{E<7`>o%N@XieqbzdCZxZw%3c%~#jKF)o*Pb@KlH1i% z(@53<-Ws~bX~oX75atXY|I9;?M}fespF-B6&O+MFFOA~KRJ$)94bje)u7+7lpvl|v z+hP(h|6Br}Ohr>|@s>oA1&+j|^Xt_cVqcs&#LW1^rKBs#&muAhvJXEdrgKh)1Z!it z#obx7{dvn`F;*%s-mM`R8uJ^&BC#R&9gLm1dsxFG zLg+)&wYn@J#0gT99KR;k#Ve@odUlbUHV2IvOJ-F5u~=-0yLlK)^5l)#<$hr^XUsrx z%`lCjo`5&u8BIqf@3*Sqe7R~xj=k|S!6%YbHeG2|cJllSVr|ZKr2TlRX!oZ?O}d%2 z_~qU_OSfB04NwJ_T~(=&d>Vp*$ejw(MI5dn9+WHNC<~agN!sO_NR$ z&EUosz9}S=W(mXlb|^?@)B62eURWv1>z1Kiu}@=3Lr>3?mu{IZ2Baz7q!`;*bTq07 zXQT27dQ)ul9xXArfFgC-wgzpE9b8^{Dn4Bs(LC;RsBJ1^D&GLwPk@;cwJ#@Al@DQT zk%fhu*5S@MG4ijM9e)TTg0mvlygm%-7R~SSM=r zpLJTy*}h<=rJ$r!?GYacY6)>hEHnIr!Ci@x{_wG`jWf&4^K{2j2<5V7#p>n9o8q#v zH?8F*T{7DUbnV&|%r>`}>f7=nR-~Rq>?CX9uHfR%mZZle=$l?KXislcETcwP z{)ZT=bv@SoF=Jp#P{njTXKkLl(-5=EwbLB3Lem>Ru=D*z(F8N7-4Z6a|FlAlp&QXx zp|RY%9xRkWMFc&$?HzuaizV^lCx-oE(NhBX`9SP4j#aviPWl)-5rx3%J*Hek`$T)L zS@j67dhMyVEz-G_Gm(QX>QxCfRanNYy1Ev9(H%Y=#zCbr6o@sbTq4ugu)6H@=^Y`W zK`2t8XQyr^e8Ql7BOW;yF=an#Skw7%L~aiO1@D~ZX)YaG@R#oHGAkz9%qN;_47CPXVw4Jv+Jo@#Wv zdHM}LwlUgj8tnj%y44{GTZ9P$3#Mlu>fv*`QBBsXgZYPmg&Jxnib%(w1a?Z%%S{JM z<`+KQkvNJb{>^$nvc0$xp?jNac3ZOm)FsoMC;%8ltWq-cn3PY<2U{-~i|YL}%FNCC z^Frzy-)PIE}(b{`nozse$dI^tB4+JA5QoTB@q+I$V6*wnwEgg)X^wC`u z!u(Aj4$wM#H86krM$i44qDbLF`x&3gKr;NOcRW*>cWCb=v73FqU*f)qS9|6#oM*(4 zJg`Ao-Cg*E7iVnsD%B(~QASAPS6sC6>SkYcqE@O~F&SWe!UcwYV}(rGZ#YjuRsR z>b5U-KRilo>I>#OkFLOce>@5=Oi?4vK2;8xN3$VT4GY9+PGGq0s#zDxWUO_CO?>N?J)}8~*ceHN(dQry#YiHdgRA9=SiR7&_5n)?6dWb$`L?qBbW zg){6nkpzKo)LTg;$G_fsVJ9LXdbh(#zl!+YrRH3k6p_|q5<^Lo^~;wCP?&3ZBX#tw zRr1rwyZOC+LB{iNB?P&^;v)(7p}ku`$j3(Yw`i*Mk^)V&ZtLKUk<+VzoPAy}M=`p{ z{lt3r?%>B>BUF=QO$JQ8efw%oPgYJh_PCl(97I9ZK}K&wpB1{(rm&T%5;bu_>X4G^ zUMV_ZKWm){``oZrG%rXW`#k2+n&0=B@MXvMbFnb+b|=rGeKqC|Ta+h|*U^vaMU^~_ z9NUuH8$1KGgxZ4Z`|~5IB*G)^OfM|tPOPRpSH7)& zkgd3u^33MI%x)gklV{g)j4do)jXj5ic^gisHi(SI^&;e-plMSR@ikd8&=alxtB z@pNe-15Fgqgq@`hI+;_;*-Rk z`8~12xJ-EQ?#xrM7eWq>b>HAzw4LyFoLTH#5;4AaO6X!H;$;Pgu#Q^)sy$U}d*%?Y zpX*$g@3pw`*9W*Jr(qwzNp{oQ+li-e;-@~#sSEXc&sS#-&_&^&X^5`9L zEjX}*K?mik*(dx&GUv>{!47lS*>H1Q?^A^RlyKh7QP<0kUIRHpZcnN)hzvEZEbAhWqd_%Znbw+AZL{F#mxX^s#_ z!#>M06TfkU9@yBF8x1@0ndHz)TKAsUp(`t?(R4b?%)Z z3HvSHAujO4srx!Mt6IZjLD1HQehpJlM4oFaBZNX4PLkc6$Kyv)EcAK#bMK$JY5 zAU{p4Y&@qfHCxaXNuJJ-Re|`-A`VeVBmNtsK5Ruu>u%l&=`TL;FCSVU-d~&}bwY+G zo>?n5-0oBdueYK^{@;rf|I51Ye^LyxxYswpm-p+4|KxFFx;F>d^2TVz-V6D6M}vaS z`+ul>%#)#zZ^v%QEA$Mdj-4G}?iPl2d`_`X-cxRX0i0mOVjklZBaN zT%prcXbyUvx>tP>LJ(Nzvbs{O3m-O>tcvYF65_1p_^{(5td2ty-e9UROdATGIn~n~ zdL^;!2?+-a>)68s6eVI(Wy8I7&rkjVJBmJCaX)s9(7EiGKWcp>G}UWib>oI_D8<-= zP0Jy1JbAVQHO&|CgHIZfSj_~ic1nVe_gZBnRe8=5CPZx{A0#n~@N|N{H7h8M>1K64 zTX$`jfon1}%U-z<9~^7079>S?wN^;>G*y}?g~w%4)?WR_V4fdKBunVG2z?eOF-?I* zfZOS!)*8i|)XYAy-BaJ{Fv!&Y01 zhz@RImNp?70&aucJv$UTnYC`!6i~!f4OVpT;e)T^5MN>I;}7F;gm2mM4N@mepju;8 zBf`Owem<78`5iJ&b+EpRv*!t**!ulD%hPw;x9sYjgvV|f@Xfe=`YsE@F%+$q7a!Jv zx|d)ZI^FW242)J@vB+|!6IAU~%Dp`LgnUCn@`uyYqvbAHZs<#^>Bzkmx9LtRJez^S z-0M-BVwJ07&akl2?A9A!6}74+qOul%L%Ut0LMCw?fWek3q)*b&R6t|OQB!B{>_H;i zimF8BRjPHHB&M6f;tL2m$QhElLsTO18$&#eXJ`|{Wifld;Yhrn>FKmB;Ii;Uphgyw zkq7gXMc#b{C-iFdjJHI>IOlm;j-f*?o8@cHN(c_L9bAO2l#zWLs{Gr5WAt;X`+3kh z5et5SBnvT``L{-_%Qn}z{#KSOq7KaJJQKtL=As#A_ZnzyelW@JM3rU`NS{wqWfCg= z!5wD{Zr!{}{Rg(6pd#Pa*ct7^xiBM-1{hdGo1CE!SCb~LJUSXhG@rN(Xs|&xC&qJr zeu!v#HWr1|$NY)Q=Qbfyh&#dsGIrzu-spH@xq$WF6$sLZYh!6V92=Rw`(zL41Fn>ne!z->wByhz{ufiVlP2e1Gw=Q5YSx?;k?~>k z-hvVQ){o%4K}|LV+B95qHI+%q??u(lJ2Kf!X%wlFdKYV7ws#|V#C{&6UB^wvS_p~v zqh~_WymfH(r}v`mI$i={QcjtVWO~?FM9S=@g6baAm*^zp$@h+hIYtaCJ93#JN;_erfSkBUd&V&s*eYgR0i|;cizu9vMI!UJxzXK$@-B`Q~Crr!}}cR z5>>-|S34T`TJ)U;&()i(XXX`vrJKk?;_4#F6Rumnibr9s(IaC!89E3yW42G9DlFZV zW2aDOWqWU|K{f8yyoQ6->S3?Qm@;Iqvbf1|gv0`|BEacY?oSrz-0{LVv=`S(uV~0j z*)y7oOe24FSo=v*1e)F#`Z@oRBYme0JG>PwCR`5;jIcafJn4mO&Er3W8ziyz&YR}; z@+`+hv1O^*AK}LKh$~!UXE1UGMx5_w+fPfQ>Y#ntPNl zY+V{LKf4{GH_I<0$yS%2`dEeuy!(rMoKd(X8-#A?o*ldGXskCp63`@HW%=wD*yzqc z4s@Q9Dx24aeecYx(^P+A9L^OY zS|4Jny@SnnJ_CjV6_;0n*2`aA-l8ohua3p@EV~SO+2>tx0YvJ3x;5EQ?xyHs;S!jB zSM4*_S9oX<@D`lHZh%zr@L+fGX2tw5Gz7Rh+;Mr#GNbXSz0hq?3p=U4aZhldtxN3) zftxjwua8wvnYz^3t?Ox2q^y5y5e zCtue$8M-Apq8W0nG#kunQRO1p)00&Fj!pQ-N-6r!s4Ij>=myp@ITi5@5|R#1wSm7e z02ULB{BOy1X(b(XehGlVKcMe?-in(5Pw6_=(m5MRQbNr{#lb93trd?JuPQbPtVX}4 zxr<_JQ&Kk@l4_CCw&z+8JG4{~tr2|e!(hP$AU%WjoSRyPiY6EzhkpNWCd>b85nlK$ ziMAr|fYg_St?_hup6~nEL_Uagn(m9^fTTmdGb>9&1a}&`IkW={azv{I+OpS@sZw$+ z)?UxPx0KMWkxbi+SPgTSgdY0ZHiSr>>(E`WCA&{iKC_9D+M3Z5u*aYHWQlY41J<#a zwAUI2Er7N}N@o~xzny_-d_8hprKuRvI#r>fdoiFnx=A|!3opPa2!d^yT24{fyDyj# zFE%rYZ10?75x^^KSmF=_-6U+7?3a_9Qs0UZdF(&CB`e=A8CkaCXwPS=Hk${u3sdkg zEq=4>6G^G-)!eMFM3VC|PA@H8z#3OqqU1=^drB6us)o0<9G!_X(j-X)NBZ8J(rR!t z#se~Yr(GNtfVGt^BUQC&`!CQ7<1#|_I-{ZOrL8wO)(#Z13O{btpK4)k=|rYYTgfHo zq)Ez5iebI{0iH#AO$sG$t2h-;M%K_n zS_XianOZk8rg#!&0NMy+?0o$+)aEKa*;a0C6~93>p&7TG|8gz-Pbd6Omc@UpsKPn^ zHvSm=w_ICHu&EH`NJBF;BT0;6bGCAy;U!hwy4i1x@0m}oITUZZ2CAniwKI;e)zk}1 ztUzX~8`Gtjc36rbT^gq@+8X9JT(IRyb(U5Ro=}|nwtxwP_^5ITTV~bT%%0l^W}Ijn zP1tXYecx$aR8mUUwveoSy%awYW_Td)VzKJM6R!^f!9g>IeZf^1mG{Rv7$r&%RyEbVy z49j{9z}BDh@@8~G9U_48`+e+$pc-;f2NVY87oNvqvP6*v1?%IuQJkFGs(88~Gx=GO zn79m|#9X5NsOGC<#j`XhIYQ|6V)HF0hlC3qu5Z zhef-(G9Vz&o!LMzsWvN4>c_=^)Rx4+=!gk0e*bA?<=7Y0(pgEP&+dj+EzF1~c}&z0 z{^dyGVm)@$8kSZa{LaNvvX@Qj4_y~Tm~NSZajy~sFW_Q>`>zjo6(;)<*bO^`=B^R4 zmbX8<<5FkEp_XWKJY>{^heAFYXD-J^t(7{lA=&_W#Y{#Zh0bVhEpf$p!`;E2$o#Dd znlL@AhVM9M+6Ix7X^T0iu)T$K5IQ0Cs6X0wz;wie*)n*@O!QrAPC!pA1*isq(w7B# z`uRFsh2F!63=f7?FCo_>>D`yXM$|8eP#e)eAkV-MFys(KJ0#X&YHzheY@TTmI* zs}}q=r%xCdkA7f?Jbq7Oc<z3 zcZ>N3PH6rvn2f;KmCvfjMK~!d^vahhd5p(GspH2i?yFkpya$6fK85WOpwq|RQyBcm&rzcurgrEU}TF(6=e(ckbFv0&KwHd2tZV2@~AkU zy1eYB+2cbVs5tP|9qTkkaqK5RZMr>zwE0|n_wp=1#qs+5U++$z&*j>YB<{1(AaPqyupOgpleKzz*FF{aGdJ+Y%$C9QMnAOVNcPNccD@GLwO2EIo>} z4_DA-w()|Sm}`~NH|wtCm$Yl2qmE+~?p~?goEVG4#=!yKTV$pdP3QKGWAE0~^#dWy zN;?sY<30xK=qNOBcc=QvvGz~EX>Z%Am+Tln)5sXasnH!5{;Eb%RthUJ}>!n9OW;U7kk!j%Jhyc_7 z=o$BizvJ&D#`&f<`w@EZd_7;t%2;Xz&+5I^{GF^wblFGzNF7+~z7Ms6Ec3DOXkKeq zT*$XHlXK3I{rcnX{rPk&Vz{-ZUyV(RnRT)(|8!tTBLZ>Z$9F3$Ab^G%q8h^&=@gSF_u33ozuSJ4bwT4lj(y;}j%vtgKWlXW?(Afr?a z?^%1uq;fdLyt+I)RqT<&9*DTO9*KI|73K8R2~adACXwCZ$aU0YXcQCKQ)5`QyS9?H z65qN}&&H*vMN7ul$^&UXIb~7zQXD-^lY@m~?2R;?D%bC6g$=9}G(=bRV3Tz!%swX) z{aK1D(*4MtMI+3VEDzB8%Vj6`o!Ycmr`!av<5snMWPs|c^D$5!F1?z}HM7qVWtFBb zU(y|SL_h&oO9(!_)aiS3pE$N&IW>eQsj+hr?U7f~|MQ$`p=yi5nvC1WGpZDqImT}P zhYPZx`E!1IFshdva|weB&oDgUb@-e55|l+&Z>fP$Y#&MELbFP({3g_f9#c2o2b-RhRuTAiyx#?pB`4^V$0OwCb&`AD8pLdp1b!Pn=kv;Zn?8U}oAyM|-;cLJ zJ1tzp0Chs+qCCtjec=Kq$@+RBW54ZY-AV`NRmPre?OCccZ?rRU2J7#=qP2Q~tK;B| z39BqKMp$Z2=#$Jf3HC*q|Do%|lY&crTI|GYbZa`bb~L%{6gASjI?cT3jcw(u#+F&+`ih>z-5c{#`Dw=a z`VD!q=^wm4C2~7+?>m~_T3O3s$ky$m)P7^&9;WPSK0Vu;42FM8Z5oWk6)b8|(PKC* zXQSAtV^lO)iOe+tx5^xpg@1M~zG7W`vCEvHr#~<~Twl53B{k-*os-WL<<(QUG_6A} zmi8Dau_KT~K&Hz6OSyc~ztR(gQ8p=0x&ksXB?TPr^Ioy|KJ(tEt3N$T|D>Kbe$m2@ z{ic7o-*TwKpmB7paTBY^#7VP>HE{{~!KS}hrq(^{d9{*}i`VDihS;{EMPKShZaLkj zHmnfk$2#7nU$BK(9b_DrF1?>ND5zLa;Ma$StNiy(asS1hn2R&@(aMqItjp}D`KxjR zZT!qho;NTNi6Ocs%G!^Z^`45gkdQF;maC6w&kN$8oNai{=^YK<VBuT^ zR7MbM^$i>!>Z2`F>Q~n;?!NM*j5c_SW`eR3ps__jSI(DRK&Wb*cwqGwSn~)_XLshL z+_i_h%xdPEbgRl!Nudb<4e|QYQqm!aV+$yhx^Kr4wuLEU#z|8SRZ80HN!a%-dZ_gf~0g)82XV&hcA z)qxTs&(IoX4_hbq7QT&hqOgduDvPEwwkAq3fCsx^2vH7ph{`V;B4X*c-Otx;gHDW- zbjkDT8?Pu~3OjNp*%d=w!|-UBQgw<>&HE*8abaneIk*KBA|QfK>FUvRldPg^=~g)7 z^rer#u*@5sGE)El;vlJMax;Z64z`6y-ut_U`~2*aa15!Xi!0nj^RE%T=DmluYa`mr z^7Bd#r%KSM^SO8Y-usXBBwAsomGq~t^2q4lx>{7JRcRIbqG9BtI#C3)Hh`Ky!1u2W zh1RW94-JyLt+adOnNojaAkkr(d%ChTrA}plI7C}wHc`sZFlhL*k1%olq{q9MN0xww zi{BX2TGBoK8iW@a;j}AV079fBZpt9^SYiWntJ4+W&J=<&sxWK|Q9zX(PkQe4ANB!( z?^)-Zbd`w_U}9NpYA@S+a67Z9pwu$UM{qN8=|=8U};# zh}?#il*i|}+rDO-~>Bp~F!C~P~ zb>`1bn8qdc4v}jPp|w$^{qsRrNfs}}3F^}fzTjR#c%nzo-laxlroQYEGx$-7Iqo&l zMVzu!b%&1EJhHA1TFI1@j3$%%!1*2n;H7Fe>bS{Kk4*7=DDh)~$96J2XKVWDXZ@0$ zv(z4frl7M-sp6m1{>{uUyX4#wXd$hW(O4*!p+C#=whn%lVR;uwKWI6+NhddX}xlfb$<4U zt+Q?(dnz^1b(WAo2$4-q3gcKrW$n2}f<}ZY(CasbE{s!`9Q$&*LGc=Dd636%!{Z@H z%}g`fIEH9cp|RO@5O6{NKB$MIK9m8i)VWmlN6{2|kefM$FLQLwZOUC%UHy39 zkju6#O}=4G=$`777YyCiwMtX z4a%_Pau9jqH3Z19uq>{sxec<3a2gy2NG-J7S>|lDF!1n?E)4Ql8#D6;o4&g$Tq{lS zl9v;Ad`Nm}pG<;(#N=(0OH}ZtSe{yRSBng~Q;>iUb{=oH_WPdyiS!el5*dM3vRpjHdv&SJryB z0!;z?BH9oUUa^hR0TYCWOu<@g5+()?74AUxuTGV0rnNE>Ot9>?i^SIOr{)%`df-RT zxB3P37Kdm(KN*;|FB#;U!<`})9Txhb#VD|iP(!b|^ir_9ZWo(i5v`MvM&H9Y8C#Pk z9QC(F&R$_rF@frx=icj8%IXJWar2FDZHdiNmZNC^(!K-+g6;%Wx|9}c=+w{2wOLaN z&k*Y)wShmF8;MV54qx2Y@3RFCB|vS}Rczx?;+-yK2`u8_-Ip|rGi90-HbqeN32O~u zt(?RRnmC@Faw5wf_16?E%U_VhYD|R6_VXoWgUi8b@lMzE6nW-l_MtUgK$mqorA4#Z zw{!ld%37IB8U3Hb#%q3X+QCeu1b9~(sTohP6_OSvbSI{C4Z^ICU12Ok?uA>s7uHn` z+6h#0yw)j;+LvWB9;P(Jb;&HuOA}tNGbr>H^P*`*8N`h!9K=JwWO{AU%T?&ci6 z=H}mWf>(#PpS6Tuvh307Yjqj)C`}hKYongSKsOU`B72Z#R#S&}gN@t~gRI)v{^QVE z?tj_?{Lc^nB}@wQ;Y^io=>@$lp)KHf!`DVZ)ujW4TN;~M=M7iDEC{iCxYJn8y#7rF zSe|7s7o$Z}AdV@!?5qXn*eHMk)w%PV-=ThE5ZMkXdn2tTR$lQVSsvUZ1TZ8JW@jIw zW5K)tKD54{3<}$qvJ3zG1?U|X1`su!@@YS(inZWYalBu2rxmH|#1THPAHS89S#oRy zG9tBf#J?GZ_9)W;e(Wo@o9T|sB;&_>&4|F=3}TX7YEDn14|L^;ZC^McCcFguou3yp z`E-d&X&~@{_TzQt1CQn(uuL7C{!Oo~_GGKUR`Bt$zy8~N^ncx-`QJLJhks^2lRp#T zFS6Lb+^6x3#HQ~B!%V%3I=E zY3p7m`gX$EqI$NqIVZ*j^Oz`Zg_!DaoXvgEPV9)q9r+9UVh0aaFfUa}p?8LEisqS-@z&Hg%wW-#rUYdk&D1xh zE<#vbmjP|B7Y=V5$Z<=Y)g?OZ-u3o^A9Z}S5sgE(jet)F7AQiDnEOmLOZ%RCg*g5k ztJJx)uOHjv>4}vEmFB#))=o;s4yy8a`xR~PZ>9bsF09T%E+=;#nwQ8mPO{`52Tb%| zq4r=&pQ&#zH0bRDP||?A`O{Gk&gISL9h?TQre<`Tl1?`y?Ibo`rx+gj8z&tSc>KM8Adh;uAV*X^0`N~(t zyDX`9^qs>k{+y8Z9j*Sbo4?1i>_UI^!d%nM$jRmgYoIZ7>}0kgd4dD9LZD^o4|+1| zIHHQ;(NG)fUoV6Nhke<;$Y*sw#fyWlP4IQk09AZU$T(%*d6%n39er&u*`ph9fRyyV zU*JS)@5b}$?|22y*|`DFa>FMQl4F3&a}1(wXOL}#cAGMvZL1i8!D6<^5X2PB!msA) zlUa~*B6-N`JbYO-^2YUnjjMM+$tu*o$(9Mz0%=YeqTg9kX(_Bbj#{D_ z9B$h2Yx-0o8y5f_rW6Tl%;%-03c8wpIYLsXXxj_h*8Mnl2(8tDy}!H9t1^(ht(6rt z-oRJ}xcbz!hqY92*a)ArPcEJM7Tefd9{K&{we6kEyw^*SDm%!vXc}9Xviwgko7Ua6 zff7cO6vPW-dl%ChZ0af!GW@_f+yQl6kJn?r=9B2KIpd~4XZ#&g1@1JFI!&!!*pkdf zWuhx=B{iO^9y|qw-%vhmQV)&}W{nlfDx8HqiPquEuOU$}``dwiuiPuN0CEi#l}VOh zI%$H8#jujhA>s7JxEcmjXuYtI3#z)Wj642N(b|LXR^Zyt@r(IX>;}v!*p@z}VzA%P zsHbV(e%|3(*X`$n7ofCfat>2Q#-$PUNbQXZp3_zf=-XZIRDAdW0){`uJLRfn0N=Mv zw{Csfnwf8$biz0P_R1rZfrQZ?)txe7C=D^m zai~}5l4oZO>FM0Mx7`L87$1j(siTu9d6I3q5McGhSbK%n1_iMMj&Q_;O$*PTB5rKG(2NxpTNm=WX zGIA+*BZWAsdTd@4Xo1KNmT!>w@F!?gP3O37ULqpCPQ<|WRMjV8m{(NUJe`Uy`LzL{ zD3UW~yg_O`TFH>QV5lRgbDxmazv@gv=9WwW?i8I~k*u7H(^OqBJeF(O$2Lf z#PL?K!g{2STvJG;I-Y%w0~%u3ajGHLne@7Q%3G>49{RN^@0`hRyScm^9bCs_Zt%KF z5d5snak$8XRVUTAA!kNfJ5M7|ezgZiytO~$aoZe34EKmH?w8o$^(4$$ood79*3%fJ z&J75V{VeE@TorzrHA=p6JNKi@f?R2&c}Zt##&z!D7)5NKFgx<}kTXQ;t6>>zQD3hk zo7#5FS!&|y=RCkLDyw7wHsj)DBWMK?3M0%ScB+dTzaVi^h0`WaxLWZyAh}d?uyWIm zT{XCK=ILkD$p|n0JLvbnBwk~DCTlSWXdj$%NJTf+mg{kaC+BVBu9*~csweGQBIbxx zeqG6cWpbs3)nDKDFU(`FZfkX27{61Fong^%wcgE%1aBe*kod-wB;th8e zQ}dE}!MHb94vFrctQRDR?E+$ZFKho`at3HjZjW`}IP>Z!O;&bv#q%UVc~-0M*F>e1 z-Mdlk)=AvK;7V#MW+&P?9Hc;TM0p*2*c>@JHO1CW#^Skf_ku$3tCp$(rH<~cJWaYg z&zY)Io+_LK!eY!U5M@&9%)vq-K__Tm-B8v*j}C&S?k)T8eEsOP$p2Z={7=aH;1A8n zd6PdP?&oA~fHeaD)(_sFu!bI8K3KAi(O0^6^4Al8s{bF&g27tNaz~^ZAS!x3tI0Fr z#Ks|B_S=BuUyRVqhbzQ1+MCB$%4Y(Mm;7!6CV zKMqN5D}11jFe&07aVQ#A>Z(2vEB_{JwR>gO_*TL~2AmlL)&C+pTh}F>>t{E0rju$= zj?0wVtjjgT5)wNtEcu9!OMrZ-`v~@4qklwr6#g{@Os@zxLq}A)(95n?xt3~|_Ba;$ z0>Yzil^XS5&aFCRSD?O+F5L2nKGa;b_-u>b_xZ!iwbMVL?MZg`3B6uXRPvWf}oObvd z1Fx_!4(N4B^=c{=tPdM-mRe1Z0I>}?FGAVwPqV}M-`XX*yCk+e9-aSC)X@|YeW-QA z%S;T#;yk>P)X!-I)$WlK?@jwxyZ{RJHOMJ|^TVAB)hzw1_j&hScWUj>_~AMmI|VCO z6TnB3hm?G(fn^<4b|>h+zfxiN89^nIUTQxLfjFT)@7OWOP4`+tB7?6{yCYiG7fOCm z>oY1^M9co_>zWweO9t&30(?iDmmCuPQ>6Q^fVY`#aHFbzn6`rk$}7}uv%CyTP>+sFBrmt42V88~$!O+I+91LnMmQ?R|@ER@*0z$*4U!uFTT@$CSG z=0ZvGV;JmK*Bkj4I_D@|L3FM3c|Zb5XX)GVFck2zV=(%<%vxN&z7gmo(<4Bvxk7J! z2JqC7A2LrPOa8GN>2p}m-%M|lZN2{Pltc4er5e7%vb;U#mDt$O%~M|hX}3xq6e3~N zmT0y8CV50dBe4(@#~3GZNgEM5^Yh6Sg8d5 zWb{9V8_J=7F%Y9=|&PyK5N9zr_AbYo& zi%V6Fnn!nZ@~mP81lg9rO_#-u3VqjN@7lqFAyfg(kMhb2da4lLW1$HkelLab_g_y< z)%0Oxk1J(rX%)ZaflH*kqfP0R#i}8gzVwLTXjdgRP^nW zgRWhSUA>6Ie%NwocY9bik<9l{5P;XQag0#Mncv<>b(61OrYQR&nV?Ebpy3SdmGN`Z zdPCJGyo?1Yj)d0TCC(Xqz0M;NUGaz7_;rtmwv73?)w|x46^lX%GxS;tJK~j+3pX>x zi-QJOxy@aH>dn{+0ySL@d5g(-91Y9jCC(_+&GdIr!>A3#A)YfqplSX^bXt{C(@)Js z9o&%OvocD8vuq{N9Z=G$f8k(B|WLp_gD`BGhru-a2|y z(69Try`!bUOQ4;^)Rm0ecD(hBU6e!Jv&g=bn@9vIk(==f|bWAKyMWo|zksvgp1p+$QA z(?mEkf^CU@tC3@8S6zx}&60w};PVEIIaVvcyOUF#{)X+LLzyF>su4CyJzwf6-Nk#s8}!p0`^pEkqnA`HKFNYs#;^B;IH6{| zE@SV=*35benciO-hPh2)cFd8x-tGX@1}Ml+2rOK=PsMQev0S1`RG5}cuxLHBl^fR_ zq+F>P!Xv`6 zCd(iv<9h{lo|C00nnI4-NMpOr8_zmI-_y6<3KedPb|P4nGR8VOw?Z*5m?T88WKtVE za^G0hwU~wwN$(fN+Kv92q!?lkTtXIIm!=z=bxTl4%=289n6SFp-_aP&$GpywsAV7C;+?ye zX%a86KQhfqw$$IYHN7W@nzr0214N9MeQBjNH<%Nkx63M0Qc>W40UJIO;P|Mb99_7t zC~nc*V`dtL2ITXXO8fH*xL&d;C~TYcSr6IIo&1>#wABX!T4|Ti%slz`&`_QK93@2W zc>PP?iAnGENZeg=6Cut@OpQr2H~w;6ZlTCqrPRFui}X*+^u-MqHWgp7a6%ur6Uhu; zSO>zjQQR$ z>Xdc>xaB7@5f#OOoq(*W*ibWl;F)C@HSR-c;5hj(T`!ix&-#iCTQqLd4QM`roP^hq zjI52dj+<}6(MGrH`YuVzmhlbE^ig^uS!zCN@+{d^X%+(o*|dd1k!`XJc6W@3#-tIc z*+;@pu50n}aen?+IrjgI_;m1Ybl3cG0XO?c_+?1-YouR?c1^1#$KNBGTYTms`nJOA z26L@h^B<-Tm^;+3u(5w*Xc`Vyww(sQ`iBw3U+=tf71%=u;uev`QBlxqqa`_%x{#U{ zpSz1$2z-*ZAK%xG@rwW86-GAK3174H(c=?$K{-+B{j<+6S!;2~Y{S{Maps$PHb`VT zD9O_od)wEOTIjd;n2PML((!R_jE>-d8SFsZn+H)nD+MHLNRj5Tt4Ggt_xO{7Ey}+| z)PzSMv4>`xZyGDc1XPqjry?&YqUbv4{g-SuTySTLbdFW6GUNZZF!zX`C1}m{-Y0Ov zG=p~T3?p&mz#O#b#2%PA9E|1H4Td8j73spIHHe(f4ccxo1u=p^fe5d1rElVq`%G0)(`5xZ6R!0&$_i)&0Uxn6_t%xa| z&FZ_@#8;TEWUoH`y8=>`X zf*2xF;e%0VPp5;*&+|+MG^30Q;PFMv^<%;YindR#c*JN&nvaS}EsA<7xk3jh_j5b* zz3L#Q1kjP~aSfVrGhCnA-4wq;zYzYtIU9V&EvxdSVMe9x;XgrspY0VhZ^A>jr}2rxziO88)iuqHRozqKlCYUOG0Ai>m6@Vn z{vy&2GnR~{e{;#i#9%(!q)U0vja|aCd-%J~PknsuCt!Vv(HeOmZ&IpQqm^*W1mp>X zy5Ib=`dI{zRNBfG>@3mooGa(hUmIB_K5nAPhA$49w6d zN)0ebOG|fmOLun+9ny{Tea8EF%B$wD(71JLtJE|F%vW+Gl|ldaoym{$^> zYDXSp47UPC>SGU&uoVw?l6g0JwcT;O5RlZFs1=Zu1{qvmH*A@A262p9f1#&5l#XCIP>Rh@7|3-$;3A)pPHP);LhQ3w834(5?ix#mU1T`1I$%5=1fy3x z$H9q8Nj;K!%S+)y#ndCQ3b?oiE^Y2GM zW|Y@THD`iGbXz_|@S-zL)$eGKWv)pp3<7&{U-@sx< z2s6R%W+ar2(03>Uy8XUH>X>?DoCaBm0mQQWUG2^*Y$nm)@2&5!$2v~WYH=#jsz-=^ zJ8Io(xy!xylXwGJ9>e&3B_RU`*D6Q0R7nk`Ajb zIF+4n_o!@X$V=ZExj4LyR2dVFfpB~)&&t&(6rF?1e}>I^*|zq1yw^>Tmo<*tD}T`+ zI*6OQGa(0M)3&#MtX$w>J?<7__vita7K;LHKAb`J1pn(mEp)CfgQHjSclI(^O+q8l zWb@E=Wf7aneNzAZM%vG@at`e>CdI84iPCu&P=hcBUc5h*9+2V@r_ek6&BGh1`EjS2 zQIYz+xK!9L38s#1zS_AP->`1eu0V>}01Es)|3qIMOhwz)^`y`&)bd7u`_zZCC0dqK z(cT5*)v+ZuINT<9 zheu0kD8PW&ExT~)F|JHOaQwWIT@AEtmdOgtE{^vF$mvFzH}kU8_{fjXKy!7+5jpdp zYD0pOlBxC>)vWO1LOC*w{U_o~xxSZ9K1R1>V~X5ov+u#FJ`|5vYyA4=-=|&s;O?-@ z_+TjeG=pdDN5mepGJNxO_idAmX+;fGHD>Zsa+nPzJ9)6t;E$_@PNsAdGt6jo$E`bh7o5*XGhOjE8{dcfw3%Fz9sb;YU!xs1M3&$}po4T}fMF@I}}p3qQI z94{S1l2!QACca^{CxzCr+s{@i$<(d-B_!1ss*oVPH~@AXMdiITOt;s*wfi83l)tcc z)CMmk0nmgY^6SZv-52aVK8OcWYNa}3M{hrgT`v^Ux)l6a{J7an&KliA1@QVyuyPA#RV zf_m9ThcV;d2&~UC%TYMoZl4wGgmgy6ej8Q(BwQbgOm_^E3t4XETSTse9~1wwJ|71{f;QVbiS(A8Q~x1NKCwB6QJ!@~m;Cag8L_lJ1bFme zK;3ync8reun`3Q;^Dj8aRo;v3PHOU*_3?-^=S+;We^>EGEyk9d#)b2yop5BL`S`+t zuaV2F+AnHVh^S(b;yGxZJ#_tsLp0##$$al^W&vz$6}pfd!k5yzWh`#coHC)?z#h~l zr-Rb2%{Zt5nB<+81xRftR28=Yw+$lU-@hBe>9`{PgFW21{tGKnsf9nlNU-Z?)t1UD zi--LJyaERSF0;1L)1(Qcml!VC5KwBNE9_Zqk_56cz*;D8h zVX-939gDC>!Rmgi>a)gLFGTr6r#`0$jWS%CEMCg8gyVDGSj#fU&S{gE6`n7uzeIVx z*kBt17C5MtdR*71h5p>ByAYFa0T)}3E!lHTe2qCc(NCsWh<`HEHzsv{q|!bNLSPJP z3oOFDbf0Aqep#9UUAZ$JE0TrnSz3@HbM&a33!(C8aS%=rhPPVrgl7UB*;wRQ5#( z>KRAU`+6{M_o_ZQuNW1&d-t8iKRLH;o?8Q`6^1nubA4QL=U*In`9BMup3X{DP<*PUrJ z^BrD5TLiQds{r42M}DoZktCYOh`9k6q1u084KkV>^%WvL3~qW=J+zn3NK0Bo34~)T z*F;e?b!P@?rA+mB{#|zY;m~cB@vCI~q$k9asd_icVokWjM^r#_9Su{~9ei&#a_l_S zQA14rr>FL`*Sur!D)7$jh?#mWs;p=BLm}+W0dO`byRXSho6@CtwIANl#%Ezc5aY$4 z%DG|}%)3oB`I!b1X&Yr;$qT(z!ui2ndzL_lT>}CmBp>o;d&;$&?^P9A76};m-#EmC zB|^M&e8nX} z4Oz6s5~xRyVs-_a)$a^Hkt;6c_R0O|8a);UR@0uUg2}UTEUVP~4%E;&6gBjFfps~fEe%NW_&(7Me zPp8-}o<|NIRlkisIDPC~5C^5;mP%*aZfb1JJ#T2dLn%0(M?Z|6a4wId!Ug2mnb6_& z+oI|bgjl~dqgeYm5vmm(FKJP4#hBA3I~P*Zodoi&z`Ea60GZY^M&IGg*#@zE)ngPQ zAGWV;;{-W)iYC0j7W;|BMVgzoPc=)()>Cw{D+@SEC>7_)29MVvcpdxOAd80Y(S1oq zv16NM^+oIM0I%e1IhhYhic=2n-ii4BKUPK7FApA^Hdzb9fM!$amC$)7atrncckAhQ zpPaMLLyG^xvPN9yaT;mv^j9^FkH4PvWqaW`dRSR(EJ~O{hx{@Ds%{q-4~%_zs}Jf9 z3|)Z`?%x5mkai*w(*x^BcekVunBuWphPOC2sknn<(SKn{Z?W5jvG!Es%E z7IclRf>*_spSswIl?CFNV;>Xo*uje14I^z`HX zH~S$-0sEhw)!x?x)w0KTKn^ezX*9S?wOM8qReq-4o5ptd}J>~3JBGPSc5&j3838>?$z#A0(vyVM=N6>u(X?xbZsZ<&?oX?ljQc*4w0I6 zEeCTZ+MUm-p`%D3LFlpU@bKPeQ6l7gzFlLYXeNX2ibJewk5pg;kUIUzY5r@^gH%WmfK=<)>(Vs7uux^^tuSqB}gv$Dclp)3?p~0-04c zHd%>yB@qp*2;u(Xjr>uCu zV=CLS^U4J8`~oK`QT&CCTP=_p+OzL)zF^CMg_{?|+x4Kd514TlPwgI!F|4|Fj_V~8e`fE6S?Grx|?3^(>wrN=VgJydvl5$x3^0f@z4gNhT zYh~gglR3SwxIvV+LqBt8GEwAx>kbfHCmm$fkE+(I(JI+5r5tQ!$oNqK*AI_1k+r$tluO&cuo(A6Dpw!KJ-{^hPGXhQBj0K8`#mw9mnwAdyoB7u zSjbS#{M_L0|1CeyWtkO}ZV+X~J+GXPZLk5rD%gjB7s&WXFNsII-tCjfmZU1vbSPe5 z9?#t=%|}~zV?{hl#{IZ)|L=Ddlfi!3Vf0ODPtyCyyXV@dK$DmE%C64&_h$C2Kc5rVT?OKsJo^0L-B11L zLsW2oC9oe6)1W~o_?l$-_jVUFdQtSj!3{feu0ET9sqN1;0?=X7vMIjz zwBWzjng8Y4_y1gouH3MHF@UxEX<8;A!s|FO@*oPwRM(Apk+nzS@{Rf58_NklW9p!A zH_+TfqU|Y9yO>k1jISgmdU@L$X!`wQ%Z+G0Ih4tBEFX;M@=25bg++WL$Ac+DW}<3r z>@wpwVe_eC#|*b!S`}JkZc)&VZCkHF_4uLf;&-VQG#Lf&dq;x86AC3tL+kBCuiqG@ z-Ox?)SbNbBs#gT`0!f1viR`#NJie-^pl- zJyVpgq7az1_z0Rh(CM0TK3}(Sir6iwHS*Vj;@ov zO>(qKl{A#yxASRPQ02BkS!rf~`st;DBr14Nh7F`iAXH)f&3 z4%h`i!xC6IdQ`TEyaVO6b7aSOqW5>(q+w!@ zn-kDc37vmE0>~(qMvYU(Ps9eUgf7)~&CGmw?Pd$i;U|;$*ZBg`Qp%$!;h4$cs9I-ThfF@TyYsU!N@^xeyPtuLeJg zf5P)&4zbf$eEXYqW1OP|{Hys9z&llGK#%}zG}htB@2?;W0x57BG*Jhyfv%Mo9E){; z4dA)|p^GaN8s~0fv>*IMx zRI`kwjA>Nl!pcMuwIU|+lwWHx{)orb(SF!T7+Ix8v~{a;Q>BB9Ly|7VSe=t!tS}Y> zrsZ7T^vaxT*XNC0YD*`sq`oYBeKA+*_LYiMfsS77GOysob)wik8NCymN!eM_({{Yr zb9e5NM-fl9-87(tA3^$zdU@Iw?MYGK_G8DlPn;s%=`XC0c(Kb1yEMVB1LsJ2ytxwx z^_fS^c4XKx$0AHBAFJL-77&%>_W?X0=(;nHo1DPY03Cj?7xCyXYc&72n%+vD5+%{W zfsf(}S|O{mVv6meK02Sfd=^Tq3%NpCq1lFAI!G$5nf4iS0fw9c@oeyeIEOJZYZ0!lC3%iq$HXia_n10T(U%Ez`0}C3FGoHUWf&P8a&%@lD`Bx5=3OB6XJtt>;B5Zb+xsg{xB5SFb61-Au;e zRp70Squ=aJjn?cD=E=`Sc7Yx9=K|3!+7nrF!uE9c4yxnRELO;A5K`mPv3h&3OhDDP zz!%x{-nsr7M>#x(uWoS3wX&T#q;;t1zIALo7kflVB4}a4Rl>WxJIc2;shzj?y|t=RZM!YWr%cXher~eQ*kGTCnO@-v{&Ti@ z)rEoqE>4>ILXO9uJJj+|{6Vk9I$kc#d(-y%v~SbnE7?uib=DAA(*8_af3(uW$<|1j zy`jOKEWZ|vwwtoewk$X2X95x!l$-9$8KAIy50K-X*2*~V8`OKG1+kTqT0I^PxDens zNi#~n0)2I(_IPO-!)mborDT5ZaJ#GnqBP^OSUNxZ+s|p{WoQD<>2}_U0;^&}ZR{Tk z*3Z#%Fa!<#;H= zBCX8h=^{VgvR3*F!L6aux5o1?F$iok&F79)p{Aj90w<3{f>`11-do86#?T}{1a311 zf<<{LpGiO$k;{ge*%URoeIZ7iUG4Q7{6#5kv;4<;EFZrUT!7sRd)vN=2<2THjUj)Wz~F`M$!kUmUq|S9j8nQN2kEmHsj954Y0^X#iJS`>X>lQ9ma8UCL zCs{!Ui4MllZmphivv{5=U0OlwglWI-ihWxAsXz)rG_?(J#qqr0L->ye^qYuRpN z%W3{bEYQmMQl^CIY9D)qyDNY^R3CmBX%{wJHG?FP1uCG62sc*1Xr$SBs51Zm}9)K1&%WSddpz9 zyHsA_vV^RV5+a|T7UhHMk?t3p9M%0#2P|U~BoAB`w3YpvDdN*uzmd5h4S%gj6?ZMT zRR~j#TFHJ|rnzkWZlBcQ>=_Zi?UB6L7TyivOQ*p#jxZv+=M@9o&%Y!BsEzo)ek>bQ z1q1r_A<1(n{>r1+zF59Mb-8VqGso+l4#`d-WZg z=0e9gOQ@D?L(dofhHqE>GP}nJ8AJE35}TEwd-^$!Hce=KlY6fuvgY<~NYbkCxW9DF z!}UM(FhBRwGnC|7ozbk2_*5U$(qYA+;GJ)%IwDuqqP%%pm?WNACfjK;DUFgyJlIY* z(7)lY+w>g7S9d~XlU^M7KsL!p>weNHoTiM>jb5WY@)sbwOC^y4)LBw&$Kf^B$o26I zZVSHExp{3ix@WgP1zQ)bHYDs=>qb@q}&?S1Z8W{^6`NEKuocWWUp6cuW zRp#g)^%nn$`rf;Y#VaVSoF_?yJ^3l5OBs&w-;|2p#OgGD z8{-Cr$69m<{FJDP{Sxeh+QI7CdIl$by?9rsr;t{}nh0ZD8H|oeiqTFDw+RdChrXB> z`6d_fXBv3k;OelcKplQGAH7@*g-+Ky4i}};3Q_SGuH~&QC=SLs+6E)W;qZ4KBfng@k}KhZ&1f~?gRlbUBK2DB4ZbP7;&0@7 zfGYb(Ao2m;TwXV0d+m+~QqSm~`pu!ZklQ&J@HWi<4DI!WiF{ygzv+sV(puG^YlByS z+4_NYBEAP*#98|3-n?n81&F}1oQv8ld#0=|t;tUdZ737Nl6O=d0ZJ{7-{CjO3@cYu zc#MO%|3>n4Ij{U?sq3SrF5>D}1FOzv*SvN+d1+~F`g2VSW`>Wd>*vbDyCwFm`p;z_ zyAV8iTE*=6_!S`V<_f5a97DXGDabe%a^tNbAH0qrnISo9f!r{-JlR*NdM~C~@QbaS zR0bG63&?Fgnme|EG0`I$WU`v!=YcQHU^NzFCT7dycD&|Mt>L2=5lfutU$gqFzjuIR_lvY%Tp&amEc`1J!*k9KGseQ{FdiQOoveRnJ-xJAVLNd*J!E zK4?|x)ZhTj6h1J`>5B||=7?0SIOKO-IWyW2hW(hD0SQ>GZ@)LSx4=`j-)SB(a5fb1 z)K1RT7{0GNQ(h&Si)r0-W{TwrZ`07Qtz)5mjT{_vs*>6mgfFq*C~+pWSCga}P7;>M zbzuakOg)|pN;iFCB^%+v5F0FU($i@Ah?I2VD^6OPfQYtScb?2nwe_o5$A*!FrP%)E zE4I!$I|2B|JasQ#-g9Tv^lwZKKXP<3Urj<&0IO%l9>35SoxWCZ!Oj6@)HM9&5K_}T zDSF1HVD}@^K8&NE`_x@Yb7{Ypx&d>0?LPr8T3Yc{tXf-%jNkv^NiroY1E-L&Izv~6wn<&b9jq$g-#D)nIb|3PQ|XSd(|W(C$E-o z=FxOKmHQmA)dRnMK^OcYgkCK29w%c-O8BojjnTeU;JVe7cvY-iJIz=>n^{*8H`ux2 z#=3&td+o;@+$j-Grt=X`H4@c`bmEh|HNJHX)5u;aE^xZYk1nsw?cD5q=b7!Hb(Lhf z{bo9C@hco{uDu-%wXIyRz~``cnT@^Qn8~fpU1w5B^(qa{`*qjdu7XbhXM=u2L+NvB z71OGDmp5`LSZ#1~VAm)Q^}Va)hjk;yH4q-g{psaey5&a*x?KK!#py!sIE8?uwu~X$ zkrNs&YK>j5Hcpc8s`DoCbuQJdxhQ@+shh%&g}m5$r8^@EJ0UK+ z$@d3rAbsqO348&zQyT>=1xtw^gxN01zP{kBjb_^FDf)GB6vzBr5{nRioz&H##nQII z$+{4#SooN=@|u5Ca&q~~jk5&Fh}zgl&}ko727Ry(kTB0;ouW|*csVK1b@oM+qe3Ph zzB>w3%r6N<;{8jp1@nS`$`PZSp>#CLW`uSgbqfGv2_*AR2WC2BOi9`L_vtYSE#CKB zGW3+5IgKYtti)lOCzXWnzUSxfSx{JObQzL^Mi}^HPkmh zp&mt{y1QcA)PQ=ug^x{>t1F>uS!db_J-xS#)X%4)Vrz807fKC`G4yW57&QMfY8#;9 zBfxqk)maiV=AT)p$|CT~7{2L~RzuI>#$ZIv$5wSCMgPj-e?`^#QxR3r_opoio9A!+ z=hbeY$II7~y9e?8C4c|?lj}_r)(f1I#Jc1n{Wp{0rz^~d{2hN-&i?G%%(R**j*3RZ|N=17rEB%hwzTg&&R z-?EYAQl2hHwa@086;bol-cr`7Mudg6rw|hfMpm?)CLfrc=q;rWEt_}sn$zzGW2*LF3J=mBEEz|hHO5vbkaSQ*vc9qrMvlC?OaIQ9aC#%7r6pQ|{r89Oto6K!xzkU}T zhuG)CIRr8*ES;t@isbpi%-H4q58Si6b5ta)I@p_XlQVGKzAx#MV;sa9!*!9u(%jL> z;^G`A;fv%YAFgGz`LVDncioI&HPl~u|Fu`O`~kVrLHDT5v35jxAnxbe)9r)@|xcgPN}= zWEGxR+SC$ds5_Cp+*iczVyLhH@3lYlt~0er`}rSw7vm<@UX~Cvayd4uB~en@!C60o zb4WBZ$=3{Vc`tcrH^lEhD#7nodTLX)Pal}lxxA|>7VcZ?!`|Q|t2oA)*9g<>&{x-L zuOp*ieh_dlY?C|QpxEbb;8V$W8kMW)J`Jn8w~6-b)iXQMDk%*N9WCV!rnJHI;9 zcnP5R!|oD!HD#vj?yywsP)=$^tjF5CBc{_0<4=*dQaCxgj9l4$k7;z`S-mVcx4&iR zGXBnL5h2t^g>i8Py8YI<7P;F4+juOa&r?MyJq=4}+t3yPJPtcd7l&F~2AO8@7jOJZTt{HjtvWvx~CpP$h5xy^U@LIq+|;TR|QC&`$1~=#!kvrha8up zzM+EC>|6wQIUta=Fe$vCytTE3s_zl=?2pq01a~r0x15}Udl%z##ux=i2$pY-P4-M3 zugMxm6@dC@zfx7R#x@Gw9D(fBS?bHqHy6+2`}F0qGoH36>Ypo6wLL!jbfN)L6BmI0 zi1&0pRiHXlLOUWXP705h2C_afCL0?(J5DjOR5xDGJARzV35kgG+;y7yzd14j*|)*b6AId7K^RI z7ntM0_BFKuCFXcfU$Kpu_B%GAp0~cb(jm*kozM_YXNuS>=EWU#%(p$9-|Ei23f6Of z=&B!5xHXme(Zjmpj6-6A7^?E!yG!`<{(mQ zv%U9SD+W&Tl+>;Uix-7(*AyrBqElsHR{hgkeuw=63Aw!N3aNzs=9edL#W|7`NMN#7 z=2jvRV(qVz0c{K(`ykKgpaXnJ;%YfakkMHIx}r}jzlO?5QHK>^)RjlaT*cXk#l4*i z$Fc|Z)w2axnq1+% zRdYA$P%_zMd(lb`D_nHHgVNqNj8 zQ3Nv>=Hy6k9_gAMxvl?Ym{7aAVP97zXD>b4vKXtToo_Bs?FI>(O;tI8UQiEjJ&QSS zL~tB$_YMq>b;(ggj)K55l6ULb72%at z(nF2>zZ#VC_ziCfNz&h{h3R@Z`f;B{9a+X3xBt3`H%gDW(IULJe9HC5)co~*mBq>5 zre=`M>cL%G@flmeE%%B*(o}pHFmr2lBR?`Wgko{ZE``W)ZUw1Ah2$x=T`bBPO#qXU5hf zoI3Cl109=e;*#_)aK>AZbt;`F!>hPHiLg*YT#sLQevVM=DH(f4w?*9<_6eB2>>N$4 zDmySu{aZ=&Vu-BdhHMhbrZUda7tk|Ez_D~!tfdRFdhhLYVEws6?3qIZ*p+kbBFaj& zP_unX;1|{vFSb%Zwb^P1S(n6*c7Zq??dgX%68gZV!jTFW2HWR7jBfW96Nuz6uyNes z0iAC-!^%X0z3ZF@;mY!*owj3_AbG1|#bWZrUEkW*$;^jVTI)A!Z!O;}=kSyJtgKRD z?qE{dys@p{KPK!K5V<93Cd;yd6dP9JEg0GCA9|%Q{>ID7Gcj@;7T*_0>Ad4I2G!L0 zTq^YkE<0wu z)yv{|WDH5Q;1IAq7rW_K!R7(Qg~Mwa>&LW$DPp#en)U)wv6T1@NTlKMj27^Udtyj4 z)1Wx=n03mD!iz&(41A^+{==xX~adHzJdP51$ZH$D&j{O2aDG2pP(Ut~Dx5^pkC zb-BEuhA3BCnKL0bup3;hH?&%Ya1amZvG?Z*NzCpju9fk(%hgcxn|VJ`>XlUJIH@<{ zhvKAd)v{(4?vl5B_mj?Co$JxLug`w*0t+O?TCI;C9%-E55RNu!-$KR-=d9aOJp68K zvgT;XSTZ%snmEHdFo3<0;O)-4zGSUFq1+ zxVb<~qFH!@RF7!*p#j(XEk(ELDVKomHoW-dmc1Fnq`d6Kxv{KcQ{G z<+9z-o%?_qq)x=xb+xveb0zZzn<;kk43Mufl%@&<`JyM%HBh}=Nil>0j+ycz3`L`H zeKw-Kn#=2N$o!kw?wI>`t{uohlm?p<1`>N(*FXEKF-h#kA87|-s)|NVE7?_Sj{6Lj z4*I|D9^_>}#H^_l=ixrpZvWto!{X15nw94pmViEFYDO7Hx_MCA8wz7dmuweMljb$`KqLl=iFowR0r347g*Fc98EzaF zcp(xcmgk2>;{0LkH4~X=D2PL7dx-o(aJ}W5_cM1f5F9~^lkA*uc9A0ne6YZ{v6i(s zawzB|-l!NdB0<#_pUR&vOdYL5ku2=kP=Po`yV!DNqa3i_x?U&9j#r(uyGt>2TUnb%SQRzvM3ML&2 zl!%p2hmj{U&Sp+}7|<9jIa1+J=_egOUlmY#OSzE}4xZwX=sCi99Jk&6OCB&&JEO}N zgZ!e>I2iB>KDga~%FO))y;jDv-H-(||Qq0{--U<21`nWm(|47Q))z5p&XCgKdPiD9W z)uYlY64Y7){e^qgH9tgHkFS%wiska{F(n@wEqmLCs5UbhX};Y`DRxcje|l_i@)y?c zC(EH@l`JM+_h~uRsh)X62diyextkY88jQ+M)sEKG=h7|&%jc|guT>$91lx->1=4+x zzYoEW&-9P5u(Ry2=VCrQY$h$i_+mArzi~oe?isXmC`kaIXsMxcWjE3*x!mUT8ibx{ zB1}%1rrJmokwQ(S`p$D=8S^MtiqdzV+Bq|OL1WK(81TCx8zy`%f`0luXrpjoD1=}f6f;gXFT#kA6l(Kx$cy5-*{Tyso&)WQ}L z;1Qg+zU6;mrM0nt8?x4%FPrWTFK~N6Q4mHDCo?7C5drI#1#JZZ1{$h;X;tNg}=i71&I9f0m6pt8`&KhP?7v>-Jyoza)1{2u@PjV@bcNsQXku@~UpqH*C6mRv%j82PrbyuK; z&HR@nT=+E9WUvE7-iSr<2*`UrJFx>TR9oxM$t0R>au4m%4n=-1cm8=vlqnf{ef{Jz ztD;d{k|ajUV_{~EM>MQIe~^m-O!vevvsBh~65UK+zRW%m7Z%Tor*ElzjQ9mdJImG< z-7wIFe-Qf%%ir~;>Fwm4`?{czjlRKp`UT0y(K;t_@%L{@>Pg>FIV!KLWK(A{Vovby z0Aluv+QmU4fym7_|2c-jIG_GKpyrBMsV`5U3vVxpEDHIDS8?^G0)Qs-xxrT>0{WchdS| zf4;VCA|g-0P(zv)PqinW&@~ZL|C%YVZ`EWWdN`!?@ctSHz4EZd9C~s!_HB zDj8mjMDbsw@B9=%>sOpp;?oL8ZPyNlChQuZy@pI)4M5g&%?53p2!iZgJcl)I@ZzuH zOj^@X8P!>iSD(8Cv!z9^xYg@K73=x!U-gX(av#GMuY}IA&cxk|YV~E`7rTdM^}O;{%&{yC)(@dRY(K>=~tsIcTw+f&7#|BqlHHO7SbO59qb+FrN zcD>nTybZ?Ut4WqC!Da=rpoR-K$j8#K(7ERLy=wTKv{SSE5-(r*bhkakMo#P*mg{!} z*4_-PN4*R#pGNO1h0&0M+xIzw{+-x1?5g?jn#g zIQ>P{G(n28jC^g??nXv^ZGjbtA-4Y%zG8@ND2CX^tK8y`0}>=V;2dDvPF_vqnXQ}w zt$ewj*HkfMh;6B#n>>iJ+U@-WM}wd51omdk*pY(s1u@&j32Ap5m8%w5%WJZ~CjCR> zvFNb!D6xet*lt2}OjjZr8t#Ef3)L|vOqtvV@BVPxRIG`OIJI4n)mY3WEwEuZ*_7vYw?wqHISccAt;8uO5==W8AhWu&)EL^eVK**6bhpC1%_~)>T?eC7#;W9Xc6fds0pV%oFwhC_;k0yl>~(foEUK z{GwD@?-Z@gqY;%p9eD<1%@N8Typt)x8YzE+y%Zd`L%nZ)mntMKY@=D$8AJp0UkYQi z8+9)KkXupxxylX$6@}dlLgl+%aq=SZ#lps$nt?|8H zB1nK={=#ByUaO)U{`215TsdDg9tD2=`jWU5GwjDHO;zbad?-?j3-O5%@Dr#Z9WQ#c z`wnB_?PbZ3dHHw4PB2Z}S4?!EAOY2GL&$f@P*%g;<S%a|*xJ(^M6!pwyo>mk(~y74!g$os2cS3hL=jl-EB>%(kT;`h z2r=aB)CovOgMBGIk%Mj!T;+nbR2q#X=NBKmSc?`DdY-^bNlTBP%5T~f##s+^y^rbp zZU}(FF@?hwS?M(PpUIEqFnl$!(|1q3a^nUU=O$Up>S^%=n-BYR;Q4ONatGlY~N zzV}@7TADC`^PzY;m5bRrnYedmw^Dv7f4~cp-Pg58LN0izf;mq{+|x2=4TWE1tkgbu zr}3}DKK?5b^Zyz591U7DG{NEySk8_Ht$m(>DhcCDIneV&)4b2e4@?%}9%s9*)kLuYa=_Y7E3T{ZVn%`EhV8X$$3oaK;n5jyr4miI(zTuEO=1~Ti7c66KZ%X79?_Sv$v&bJZM ztz{V$kpw@mct4L9OeUIjbQrQ1bHZbeltt_9wjVyL`5mpUkUcHG4LWzy{k7C(k)&uI z-cU%RI6C^h?;@8;*g)|nm=+yB6_A}mT6V2Gvyz{{2PU$VN2{JfVa9Zu?us0*Cd222iUjdY56BBz<@YHD6zXMtt+M{1-xcR8$_%|Ps z)neyJH7N6YfoYOhgiwrF*iWL5RpC;;>Z3Ide4~|CC;YF+?KHcT9yTNt^slVU$Zw;s zy~tXmmfD(fdxd5kUaD2U*Ir?b`Vjp(E%ttb|7g5_j0TYO3_SS}QtiyxNG(>+ntx?m zRY{_poq1S?6LYw?=<*uL$EH-iuWpR2oQ2uM`q%2~twsfC_Pn^2mbcfg?kg)-$}Z;| z+szn|0oqp1C5XBJ`pQbv^4iGTq?T7izVGY^NA(*?gcgLA31FtzcqToR_FZA1uhP zaE0#c<+=7(jna&{Jtp0Bri3-E)iJlunL?Pod;wT1f*0c!&X>wnoj!*tFrvq6tp_CYTN8P@MR1_%#r?ZAWk%K|EcKn zJx!KuskvI6T;dM$Lh*B$@C|QYy)ct1fjR@MIcvEQe!N={d%ED{DehikrDsx3!Fcj{ z;xDWg5V4jq(%-MG9hD`Lcv*%k|FP^Mhyku6$s|*>OD!;W0rU}0K1RtDGXzUh`ew*e z=#`#DQ)zA$?5ojRbXh?yTi;M;p;CH4>KeM^@%G_RM#jwW>0Ps{X(Fl8SkK7|`O^rI z{k-4K-kAvjkp;}bcGrTf#{>wKb)R~kWGp5&V8X7reU+u%0SFGp_R9VZ>=dPgH_@C~^h#J` zPE6g~g1gn~dJsiU>Og;T2;y0^wEVWnB};aS_7FP(;&~d!FS%GV$Pk2wZ1Hhstk;{N zc1p=-5$}d8w$_v#Wigd`*^r8?)Z!RYiwT$tnC6nPQ8FT7LN_EvI~~wzo{{$)F zE=GptgENa0=1WDxfLGGk-`hdXaRzUhWO)Se9p)gXI)pIsb=qK6h38?Eow>v!UBnUn z0$N%#|lS z99#>){7%GNYJ{Ku=hl1wI~%D+#lx^C=S&*^T+UA4xDQNGP@A4%noqWjqh5sXflh*$1|w;Z|uDXSX14$C>kuNC@NB=OO-AqQ~{-Tq=a6icaVf$RiqOz zp-ERd2}ME;Ri%dBLNC%gNbh*#-}XM|opaxP?|b*0eZTjIFRZ!Nnxo7y#~2xNtvTm7 zx9K*+`gj84tH)e@qK*8X*OCc%UJ`UfikL?#f@R!YXX^R}yw*pP%{g;HC%1$oYC}4{ z{w5#$sj%nIHJQABpIRZ$@OB{vXBNL&xbRG2FKL_gmyyU^`xm{~dQ{qLH@8s^`*$7M zo(03p`G6U2?uTRBLfR-Mp{E(}S+voTg`qvm^GL`%G`o`To59WF;?m;sCLoJIX$i!! zv@z?T(i!(QwSB+XdN{O4B3FuNrR5U+eJwy1Z`>`NV%F8^&0eQK^jI&Sn19SyRW3*O z6+Y63=H*adYP=QCiSLy!NV`hbOAI1iI8N7xGjZ=q{#TYi@&Eo)$X+iwY;l78HI?Om z1?qpES>S&ghIc)yj%pry3mBaT;z2Kc*)EkY22vBxa_~rlnl!(G-2MElg~R6<{Z9)> zW8psmZh6d?tIu@!8jI`gISA{-meU4Yi5g4I&aPjcoYFrcQoVTl6X172yg`1pyz=^; ztkB`@i@kmI&!*cMnOBHNW=46Adiy251~vqQ-IUP^eAzf7Df2H4%bu~$dyf4i-}KH8 zTyZY5;i>tXbf9Eve+ugF;_nLcw;cYr$sz1sYTH?hNX${hUg<7d>F(ouMt`6GEswwT z;ct8R7xD+>X)!Pv{PHBZHnYzX&4fv9FTcqxA8{31Ww2b3-`}~u723)rz~E}@AJmMu z-B)~ZPcLOxixf!$_L#wx%UpDo(18Q8Wm99a?sKZ%kvY6a&)MqTB#g1SJF#7*n#i$( zX+cvOF~tnXkDg1d2{w-DX1HVqp0O89v&NQIteO_^oY$Lz11evN*ft465$6(q&uJ2% zb;TT@Hlf|4R|gFy4naLf{u3#~;%S>IO;c5&5~b@67rsYYp=S|1Rq8#0s)4RerHVfR z7sh@)$CEK6sg=FA0&8wg`4{<(-v#D|m=J&4x^lM-1FqwUnehr)c1qhcyu_=nX@G>q zUN*7@Ch4?RH0ipZkDrk`$7NV3WA*!H;NMHz{eIl4{qaEPlyg8Y`Eln0rvqTJ8v5EO zMFZW`%7-TgP8xI{bRSWrie>z?4=!DoEFJMWk6gVx0!=npcRTcyPqXi~aQKat>PIC! zn+&-iz4`@i{Q4kV;^S70Q$~C2<%5d$a;CG`107B731eu9yo{<}O!iaMty$QY4QT}? zuIS%-faQm4k7yz@n)Sk5ZFx@DfiW|YRHHh!+H(>XmWR~C98jf21)^n}O$%u?|sKYZpcgo!4G=@1lEVIHC$KGGAJZ{mz> zT8g~mu>dFHbbdYPfZzuZ49|msS z-Zh<$8ot5kQOw9FZm_uh^v;BH_V$#ADImOl^&ypIr;l|2+=jMTMbRp{;#*(&?EJ}IX#$GFg7h#@e`9r__f?Llox*s*ky zNVk6!LzPy4Yf2*0qOIK`fam_QP)SZ%F)pd;rDINSlilddUGfUxg|z~!qA1*=)MeS4GKI?yR`3D z-8wcjiH>q-H!fmb^R$S2iCksrb~U|Nnh#woyRG>F{b^_Sa3*pLwUo{>7(_RF?Z-fr zG?g^KL2*SCX~h@VKV&np5_tJ73Mx;Xixxd4e`oljv1_J1If#iE(c^JPOB;aaBsqltDmBg0ueJx_{EL{n#f^vjnU zHE!muxuyS7AhLSDH>jh^y1w=$npDc?vy!B|^alj*WvH#Si3r036xLJDS6JAwzB~55 z&VG2_oA*wQyv=x3-LJSu@FA#<%-Au`*s{Ou`_WEXy{oDQXCGOt2Daz2C zwZb$>T&J=A1RS`zyCQilH~2<(1DC4Khhj_6?{B4XGBA!UJH>39#=9TFzs?Kv=DcW= zzy9W%^!T#N%u=m&7L%72l>WV!*`*RXx$UifBFRb^m)1LPg%u6`WNTNMmFXG514T!5 z5@)|)sD<1D>@$H-Q$r1y>-4~o@+kLx2drq00cVTok>vuT!F%fpz)ACpRt2>$aAKz@Ru6oZEaqW%=sT zHB0xO^}2z!qr|+K@Vra-qF!{${%oJR4S)N<;GhC{n_rOqgq^Qr{<8y<9kXjA5mGvR z2Y>2LtvGus6UCf2y}-dPNbbAq2X*58PFK)FJ&8a)-nNoJzPzmBiWX%j-CeE(Q6MwM zw4--W7Yxm!qv^c=tk*}1lDx+Ist31~;-_Ru?|1i+mkhHzCw@<281-YzLd(K&lf&Bc zt+rP;Wev%LE0~q;j(*S|O>0YzGC4o3YCXK@TIPD9F9K>D-PQp+AvOy~-!d-jUOBl7 zirv|D90>$WO>*Bb+c8o#Af~`6}L2nQxXR)8=hEt z2P}RrK|SPBHm6c=ezPQLaNX3s=z>!(bXpqRtr0@ScZ zcI`j_qN8QPzZ>T|Epk5(CyKqp8-kM&pzkT$0j)z`-fjN;wu(RFSa#-w=OYsqTIa?k(sqyXl39mZE)L}=deK%x7SJIQdJKK`cF=#T04Mt)%eXBC2l(B zoaYJBGXhB8b}VL2sS##j`;yR3{07Kd+rod9DBL}Xk#;bz$=dD%9dVZLJ@e^LK730_G_B`wyHm5KAX;ZLxBGiS`hSzj~PYq%B5ke>j%hPmnted7hyG-av6Rt^z% z4Tb4VKj<~Ch=(7*)FwgB716ZkRX3dWO;dM#d`a`8j`p<2!1G6Q3Gy_(rf+oat*q-% z8f0k=BYKR8>OU1;dw)Y+AmYe!u|*Ekxn=JVTarf8+VE`5cf!Qh5^}ePkp4$T#4-4p z0cq3^pXXFzN7ROXiNZgOo7cGX(X0-6jTre!NaH2Foe-odQ!E#^D$D)emOPz(Bh0Q% zUjHY+v~MjDLZmS<=%f=A5cJ_YHoYFr+00ygynx%a%I9rC!{hI+NqSixQYowu1^Q}O z=|v0Vf+nLw1KU5xK9%s)f%d8cwEEel!&Ax0glOMW#-}AngA*FWr8Tv;OP*noX=D}e z*V+r657=sy$3w?}pMX8XONW@_9UbcE@~@zp9w$#F=?{v4=muqK2|BwMOGF_-{uj%E z$x*63?6}>u(`ntUQ}B2_b8IyZ8v6^L~_~l72sahOgcYR+gL3Wc(8T3 z;R8L#^U!+bw7%<@)aAfjhj~clCN3YH@wp9i1ND-E7_H(4>d&|d8pk69n%$EP5d$mU zOb}{aX`dAK7_%sWlj$9eq~D_aCLO6DMzr)%K!df(o+-T{N)o1Baz!!Vs@4to?5dWh zG)1nnx0#=Jg;S@_oJXFt9pJ(MgACF7A91i!K{v4;HF|*Lp01q$RssW zOqads(F)}eKxrzvdAD_>Rc}ey`6ks{bZ>Z#C$Y~N=R^*5*=P6&-1ElT$2ztlZ(qu+ zjj?T|Q{Jbg@6#%6cR@`TQ|PU;d~1J`^U4D;o?rek{5O4tj|oaCIEY-;?{W(N6jry< zH+O^Rn5UAvp`69=fh_e)XQQpx+>rUmNQkKNJ6Qd;4My>JT-guUo&dkcbU?r}8Fgmt zw}Q1mx6%}#)^P>_MM%@yW}is(C4EqPP{8 zp~2gn4$mgxqSvDremy5gJ7-0HwWPafwZdCC0*kk`KwVKEmSCy zF|p+5*PEd+TkK%p&+kT-*b^HcODJ{5`+{+;Gv2{G+*mreZuMIb{0jOX`Kx`kj)91Q z+-g2pd=+^MQQfZ}GfuK?(QLm?&6e9j6X9ogHA!ROl2sCAHx;YwpjB57T=oDfHZA3f z{)Wfyu^OUxJXqu3^e2eqmE!p&clEWdGP^li$SvZA5!ikjw?);{Q|RUMmpdG}VO>Oh zr(*GCfw*PKR&Ne!e7ldi8=4vPm?9LyCPnI>n{ZhAv-LXRl(|bx_({;W0QS6DBGx8O zJEqun8YQF`^^t!mvX@BANX$8aU^gOanJ(D0E6M2wH%7N7I??mRU=|Pel2qyg&so@P zj!#xPGC-P!1Izi8u+svUY326bdZ~cB+{b#sfLdn^b%_PdBS!0>iBGqM-U*L?D52mU zZu>_68gz{}8@9Qp5h2=0PU)DsjvO(KySUl)2Hy1DvaiM?faQu1-IE4Y_Ab7UmNcl%_s?HP`N*5+U&4VpVmo?h<>#ruK-ZMhYSWL%L#G19><>-mVZ)nm{mM4 zTth9q<3~NTc>`}m>doOv(l?B?pK?eScHeone|>>)gzWNtf_0l!sgRw*ijzFiEG#d7 zt$@<^#bO1wM~=$oYVk0Yusq9z^UVoV@x5(jrOjL|*2C|)C#}7MReb#e;i$67&X+^p1SZ}LU=T@>Qr+r7Pja#ihiA3ay306%^@@t5bL zCw~l4IWD7%xpPu~1y&`P$#bO*oUt~^3QVr9C6dPaYsipH!B${ z3l~c(dL9)kXB#(LdLX|5y@Uk8AJAT@McOkClTYph^qS5tKlg`oj*&%uHLhLXlY8lF zI`Zu!*ZO7PhjT{ELGmjr&acs#y#uTmRR5cLU0W?puq18hjC8+DHp1&f#P95Ty2^U& zP{pP%seqJzba9=ji!reYZO9Z?b*SW$?Bk$L3YxdgbE^T$V?cuUDQl7Sd2c?lp172@ zQ!6W!vPWJ}6Oi0feR40$d!o!N(nIpBW01jrh%&Gu9fdu#i#z8=iaTG4ZPsm9a!z7+WKZ)x={9Ua7Yj zg7_JymZuORatT1`R~BW|_NR3fvbEg?j9Of1d)EB}jhe^xPJe%UQ9=tjg;7BgN=GHl!{H(%=z_VhIHly&2%R`ISZ*YFqm9e3!MgtY9fI_9E z18c2NCX$0HsxI=6kDnQ&^Cv3|>&Ov5?lq*V;G;i&j8O3Eq4B#iAj5h_%kgoVLH1M5 z$vgJCR+fGe+ptYns#}=_vva> zv!dEJ)wHWX*)Oj|AaR7c6qSJKD~D8HSkN1JX{bx)$P@6?Ni|8Q8dmDtxMExoj0beb z$)zmjt1~$!5l>W&tH%E}#EH9t+t@{+2cs2tY<>GQ?VOxx&7SZ7s$IZ;(k^KiXE!Tn zHwZni5bmlbJ&&rDrJb3Six<5i?)(Y8ATJ-ikO&{WF+I-}`RRp!NAU~p1=z(x%L>P)A+9VVN6({e<>f}tqv&L2V8t^9nw}q58wld4)vyaUJmwQ~x>o^E=?a zlANL(01poUz{C9keog?S0r=Oh<6pmqkAEHi#tr{ljcX&LvoxIC#r-v(KPWi!imEZ_Z@!=b0bk^Q&C|3H5OcT<)K za0TzmmFu^z-?(<=3f{G=IDuZdO7!5-HQwhMuGdKz%-+C0mG%?!!N2|>CF7UU{5H#| zWp07LBY*-kNx#jM(H@xlIS#mkgS$d>l?WgSxX^T9b{8Guyv5;BSA*V3;b?cgU>w~N zbU>I>sSH>)<2D^lLS$COdxa})eOVt+Xdf;1g%zob7VNU=b3mZ&3#TOKO;P2ITHYV? zGC#^U6}7OJuov4r`}QF^cTDy{`?4ZcmTc$Kk*CrAJPOfavzuVe#y5jmwq*m__37pA zXnXVU_A%NpWP4H)OhZdxK?IvgStskJgqdFY(sInz%gy+ybxL7;+OoZ#ttOHb#byG} z;bfcI6u*L>M{4*Tk)EcnbMnXodFZwUW;pGGR~W5wmrwXS)Ku8R_;p~Hv;~IEodMoS zXTs?hAP*$S-LRuk3gB~%#_6QbET>j5TCTQF^#^svZEnft({M#DfMi(S^Eez#=se2#|;` zYNNEm=q^n~jTq9cC?1wEaXer81$47&ih5F>rpz+A_>J|rgKMsGg8oB0Ze`8W!!5hH z$r2q0g-N(d-RAOh)c2Wd&eZ6dZQGEF9VTT4G>~X~%yLo9v>N^!aR9@Xki4b|*O1}^ zadvEbiLMnAZi89oo#x)t9R4c(9LEx>!Zd#w$CA2e3B|Q9PoJSgDTb{XnRPPJ`RGiZ zH2%GGoS}KFBauAh?9Aa5aS>hV(Y=QHeTz&jxdGfZisI9i$3?Uk~+Z|J0~8?~gmUc@?qixn~Okq<+S%-+R~SC4Bnb1Qmn0=BW^iAN#gUJyd-X%NOnPUD(=UpUiA{z!Q^=_Zl&$E7S$b<806h)Psrq;TI&;@m< zjYY+W5lF5LeP2Ck0ULJahDWYJH)vi~>Y63bP* z7vQ9218&IE7kq*K3D{J#oMU=olA}E$7N=&R4`OGR!glM!t$xIIA?);>56_&|&O1)4 zUqaR(_Tu1f;ES=Q5~l#x>PcG*$YUB}ixHi*>=N}OhQNg>dn1B+mvD|?XD#C*LPUY1 z6U=03k&>N70qu=d5lpF71&?S>J(+uHZ=dAK>En4${0 z)_Z(UwtEGc%;9}GKTI5N564_?RH5iuDX^Xlu_{knEucABkMw+{Yjl1-J?v?b_RH;0x)N zPsdAykY)B`^4E#!u1n8PC`Aup$iw+$yLHnbGW@gE>>SP&i8a;6YOz3uJlrGrhm7i? zd+e|eQhV|)(Tk*h1!~x$_%65_i&zYl$eUmNJUXv-Npxgbrlok(7znaLRkC|Izb`Y6 zc6K0vn#fyqb}n^=eOvXONvYH{+*Qh+5-B}*NIVlhu14<(6>iV?fi&FT6i>eR64$Sg zUr=F$1!=9!^XhXHY#v7+sTwj!3mg#osd_$Wk4W;PeN}Pca&Nslu42lnpmv%qPa%bn zvP`2}Ru-cHg3O;v1ZgHO`_xuo$--liNSg(H;09xmwV7jg`y*Op1-PvUuDibKaDhY!~SqY4-Y-iU6LH zE;5gedoFf;1i%&^YSFyWhUwTX&kayl075?b-1+H2y^-u9KZbvigEV7}rg204T${^b z{pILoWeRDP{jzT5m}3ZTDHo-LwtWfx9~WB9-^Zp;F{73Ky}4V29h zQN1g@QEy@{o+WOuU9{_8!5-9!2O36n&8*#_Gxt2A670-AI3RClakTAFBooGlHwwvUjW}JJl{01= z9qDCq8f#0iEdggTSgk+hx>$Wj=MG_1N+{LRV#X>$u$`QHi>C@=GA{mWRK&0eDu0!D zwcef{u4GTNZwy>&v6<>CqV|SPj(uK=4YIIcj?vU*q{LOUR-&OgfnXiCG}+dUJ}=t0 zLKzsJgtRcXYF%73dOwV;nRe{9l3k)?%LlcOF=fjG`)!uB!NsF`Z4+BH_G zHE-JCWfaJ$Uw38h$((Ny^BR^J)yv_)j)*UmiG)%lWg=4>Eazx!-Er#~^Q%klv2)uN z$DS$Fs)gY___-;12SbMN9wiC~YsrU|J4h>kb@>EsqUNA0R~2b~zQ9 z3OjAPE^nu%yO{RLl>_{ z2WI9qRqPJG=q##wV_I&>wZ|^jz1H>qvj|nh&I7~_3q}{MxK4Gev%*iO)9oPs;l`XZ zDie%2fl0)hFwj!g$sHT&ttnl5qh$)tN~^@4&X7x1w}oX}Kl%pZGXU9O+Lv+>nP`Ir zkV@jVAlnWIWiKbn20Bn0Qf(jl2_QGjN-XJZm-}H>IfJnO@$N_$MUrn}Qe+Qw_d@fl z?EM79c9S;UH`**ehZl7QYP+bSYh{jP%;k`-q zp*u8{iT7T#>5FRhl8RB5ijz`rBqwp;7OW+)TlJ`2emzfdt2)A(jdu)7!E`jU#+Z2K zTK)I6+k%U!*<87EgvANdmwyVU{yU0SL~)zjzEv2Qa)~I2h$x1v3Hl(r6O@w}0Q5ouk2XYI z0@Meb3=vy<+F2Z%?+2g55$zpmnafKm6))odncwUFfkU_r7k67L~45iAbhPNhgn zr1HPb!8qxgX0STInP_S#Az)&;&F2#T6L1{B6X>!EP~BTg{0T_J;9kj5s>gTw=_(Z} z)A;+>$GOTY9c$@)V(tcYoAR;pB|P~DEqv%~{J;Q{&PW?IN`!LN6z42m(lnl~;c3>Y z0(0ke@o8aaX`3TRi-*PIAkaKSBwh=MTh(%*40@X!kv#UmFcmJ%+N2NZwgfGLOVU&- zkxt?$DBJ2dBDKV~dWtbIzQf!YI6b%+G*@1h5`mnT#gMGL$VwsBn0ZJXb$F{( z20mo&E^rr&?vp7t0qHz~6*(9{?HLVH!@^YV-hn zuHL&14XxtNMh9B_j{&50bka-$ppBwjopqf~Mnet}4G^Dp7Yc9>Y7fjG&SYR^c(m9r zx12RaMY`I)s3su(`W}}BC2pK(FEWV;Z_P`36akWjvxsZ;EM+DE@Q8@`WH9%STY=%R zl*4)43Q2U&Zp1;uiZM`CXCcefhO(|#vQ!mW5rVa8MKXKw*t} zj<&UZ3O8hQ;mfu4ix!kgl4~s$Nlv1DeWP1$eSNLUl(Pag-+l_Xk@iogf`UM!A`1=U z){WT2VIKfRLOQ8E&_fdI{ZakFJX-XbsXxK0PfO>Ev>( z-W3Pjad}H#tG^?+3_)sWA1(nmu@H^!CGGBeAFnpM%9Hs%9_>1D*SLQgWnr`oERq+C z*AO1s2RzY6?+<|+;AzaTe8gyS{*={HZ}aKd20=a*$r<0BbbMmeboTEO=8O;I>oIet6D;01AgcQ{eajN7Nuh zkszANoZfgMXn_%Hs+y}Oj^r|%u!>CdOpH#i7{C}cVCFJt)lU;o40{-sM-#B49& zN6@TO|yfvAtNrH|mLe-9AeJ-!?#j)fn&iOUgswtv`TU7sL z$Xci$V0n8T#|zRGk{*%?TJ0E4+LQ$*29CVAM>Qj)_Y?4@e$PGTm??&@z1_kMj;3hM zwO=%00>n(8)U=(`30<4AxV*D3B+7nRKLpfJi#nbVvVrNM?XFBnzpB>gr0!%UF|;Ek z4%b?ta^x!i%ykD>|6WRjbLmgOjY!pLs-oibnmZFD8zc5&iHzO;yyKZV5Evp!#!|-5D5+~{#;67;Fl?< zRSKqBO?k0L@JzvupMZ!KPs-OelUle&Q2j<0AAf3<=0*8tKGa&KTQ7RPy|-p!0N~7q zYYyS>lyK)%MfLQ*8bbots9}awwrTHF0Uq9x~9JqZvG!%?G`>r=E!oyI#<>0 z5#5VcY#Th&)f-wgJPijZtbZJl5_7N04#It3KM-93_C@1*h5py~T67Je8)KEBkAe{H zi^o_TWPEcI2SoTc;NQaeKU#DAhowX+R85Z_l~U(#3*!&J{DJK{{GWvIcqKPZlA=5j zZHAjb_bBWBKABabx)blH_kl?t`dh|+n5-gqs>F7Chm>?ZZt#2@kP|NXXywm+H+)}x zUQzJUIY2Ax`-VL2qcUduiqB~3LSM+7Lu~wA-giYc${F~YMGdRARt0*9(Wxti$>?G~ zpXLjA&9`Kc{0Nj%*q{p|ZF>&Z5ANOH=xsMn;IC78kD+b*29QNKNOkxXY`)R_c3tZc%X8&3^Yi5`=kC0@2bJj)$;1JYH-&jz9DnFZlj3GeRi$ zn=Eua*>&fmVqI4K5mUYFfM8k!`urB#7PM}5+RvB6 z=rok|q2H^-Us_l~9~S)35E0>H;mMwL8s1i3VkCb&-;lNMu@dyOa>u5-I5?2T-1(0F zl)-2cUuGsFXv`)#wV_ci?#C?4OcvUxs)N$MCU7k+9}%8GNu*cIO}di)wsKWq0wGv| zC>1w|OorL`a@i|N3^Ur;l+HA?+2%Ls)QI^doGKt5z9RD+lpZ4(pL=K<8TEdDG{# zaanz7g6QR+fHGlQ&3BWNRp+oyI{~V9wo8in6Z+Q*+K&@h&=UJ*Pp9a#Du}28n{C6F zl!h*t`zRnaH6;s9-FD7w0qWl`>6-&iGqSNMvWMt3i-P2JKX|5OI0wR@*rmW7B6WU4 z6j^*JojfqL^dcqewgvleL88OFJqW0yjj$KjN)b2e&S3o!c;8&oUwyzBunh7%x$B_p znWVfMcw+~j@o4CR5pz!0Oc67qwV(J*1Z(^|F3t0dujkLhE)FCW{;J5_ch_Av@cmMG zm3Lg@UpV~&V%SWQBrd{IQ#%bJe*%^gU;G1$U)sRo)}y0l9FZv==Q%n*91pMm;z4oO zQ+c8~bcT38hSjaUHq3uVQqkjT8fa!gq=;+UiuEs;r+=bh9{mRk@A|O}U{hX#z)SOh z_cfx~+8CD)!MI&_a3sF`MMB;=`fn*@1H-xw z_1GGdsb-1ejO^pzu~Y}+-rn*`Dti7KR#<;$|373U<4^V#{%TR;%l{fF{NIo!m)Ew> zN8)A+r=DT zvrcV4!sTXM?>gC|B@e=v)DiOE?J@RG7HgEkO*xB$5zF-ukcqq2C)@(|*o;%>^Sk=5 zsq3h!aI2=@4(t}N#~CKH)+Ol;LPat1_5rpHQXBn*A-j|Uoy{S8B6p?pPyh4L-Bpu& zd;FB65$OiCg#P0E8iR_rlUotHh)>B6_2M5O(0nG+61cP;*ET;0yGI*8HgJ3~micX; zzG5F(i+%B!`HHshDvJ%fkYa*%$#~}zlIkI zC73*kCvhL_YUQ(Kiq*)6s`X4h8Bf3*D;19_zC#@Oe%E!4c& zWTlSr#{Pc4hBmMV!aUqv(30_}>{aRf9oE1iY*?&vnF7`i17{mK{G+Yp zSm%a`?c2;2(EgVWi%toft~FYG9E*M&R3GK7hxc3)&-`tO6y#;-b z-(f$-=a3UBPJGql%!#yXXDbpOA)HMy(oyyUx%0Lksj4&86k)uDcO|~7uzF{Z*If9N z4vewta2So-k*=JduOY(RH|vZAsBrzIuUH_m+1ngaLMP7o~#64pIHM% zZeUG=ZtwIP3J=bnB?Z&@_ys5cAXH0mp3n0R>C{bL><$~1$C(Ls`rwERrT}kOaf#ps zkVr`ybThsum0+5n-n8V2b|cZO_mjPOupo;>rD%LS-@MTn<|skx*$s*QOP0DBFXu5h zLHMSpQiKx4fu?{?nYbL<-`hHSGx^9^{w-sj1;WPxX!)eZU^Fwn(Rc7-#yjhW5)ZE6@CYm%0c$uplAex*a!oWGXpb8h zXEDeljW(un^TEP~Kp@cRO{Q2tU&HicPQm1qv}uH>0i`v^V*EK&{k){_oglpSmZ?U= zU3L7pQs(jN#Z8og^+sF-$^An^AX%kV!vROgeVOdK zwYF77Lo4oCQcqB#iZ{ zTdb@-Fl@yo4HM*^iEpru4rb@()pLsx|H=@uPBUIQut5rf#uGtwmY2HuRod-OTqvpz zO{~`D1FQLp%7G7tHU^#|c46(%SixP(@Ex#bOQwVIZsI+=TRcO=&s~w#*iOW#NmRTM zc0SxFti;*@&d&NU2Hz~D!gQm#OJa>})p@s1TP6;xQOG0D8KW(Wn{H#%(%JJ)yXW3J zza%e#+(ujuuBw%UHhqUCvbBi1=inN7EorsVuR5?Sw#zHrDns@>8Qee<8D6{f3tHTx zu)yz@{aly1%b|~p4k~YV=jKi+-r?Um)s<>f7+yojA$JDDbp@8CS&~-}#iH!ZK^cEP>RWnUB>sbwBHJ@2)A3-z8w1;SK9E^EqUcF;nTzz^HkelBI z)brSs)fKouR=^lsVyR-3!U&f`W@J2Anv8|s-#L>T<9>=?F{Euyu;>QTcH3|R` znTFzZr>%w^#*E@voow5~TvJjYXfzh4oAaCHw!asqN?HyGMe89o#JhRTdYgvHCzmO1p}Nx+@jv*(&qG%iRhg4rXvwcy|hmUdKyJ1I`n!8Qr{son?1)(PwBlpex z9}Ubtm4_H&8x~cWWg8k4V6hcl+9T1b+E^1-hRn=I#4ppgGdo+>#z3LPM}8v4hFt!H zR=H{RrVrX{dLk4ie#GKZc6c(J9*2vOa!ov3B?}@o;v&`Y1?DE}*_xGD=cw!|6cjOL zEt)d`iHN*T6haqgGdxSMVd>K%o~QmsktonymsYl;w`IhIhI84(+9!qO;3&8LWlHWI zaccwv`w{{X*_HGlS)_LEwg-$C|8}z{tI0!URhn-R4RSzup}Gg6bY+@Z+f+iay>6)$ z%7q{SL@#beh-S6MdT?{AlnvVDhB=(Qb-vcP9UjI8>8m|J# zs>j`8pgi#o_;a;e#$8c9$e(~FhyHO)B6+Jy^-w*4Op$)iY5U&+{x_dC8D6RduGan# zX^jqWG?e@}nDy8557(@W6tdnGfvJFN)g>%1e*!3<(k1i6rJFxbedo{m;l0hHH|YKU zjQuO@RY#El1?;jqmpd+4K)jj^1Co~}Il?NUcv7 z_9T96nd@AK!=33|*-jk|dFR@2S#6z)N!w{|vk;vY$A*dr1o%D zZ%HbC6@WC4J@PfBiWPw93TTaWAl*Vq6A8yZl}=EJx8{;H5L^SFo0|4nemhmH(Kb$d z9#IG_>pF*D8+ULb^=n>Ct2AvgeE?*d8E(oCiWX8js*O6j`Rb5L>BNpjFEvHgXm?R_ zEUVB-@Uc>aFO=YgQ9-}p(8{Kh(It#z(bsk3ftUM_P42b)FhrfgJ8?DE(m}Nqd+u`A zj%j9#92sp6ALB+<>r!bNrgcJD?d~@vYTCndU7@A6fp#z_CY@i|X<*|#a?60y-08v5!gOM>26&|YJmth5A& zt`NvuyKhHcAxAI$QG+#EN+F8G6}#giT5}1ADTb*Pt{-1DEG&2ig$&rql@n0j$9sFE zku7(Oojm!v4U{KWUk$^#_l)NSRKCze4FmquAkeI zjPebzQSf|}qYc*EFA7H(jE}24#uWB~?LkbFMWDq_zOPW%p-R@V>E%{4EsZA1KUM&teFgA^l zD@&XL2ld){omG_3a#>m#cT+HG|K;BZ{+7YtdhoX`{J-`GzUU$8>vww6ZRhPvHAuH) zWR1|mJ-&ZLGP$@P0LcGf@4cg%TDNv_bgO%BJ3;^{79b#@ZGnKHxfMb$1`;sTEf9o+ zp!AO00@8ve5RlN6o{E$NLRBf!0#Xt>Nbew3z_KrUpL6aQ=X~F}_kLsi#y9TxjhjCp z>t(I1yoZn4FIZV}Eo8u`OtnZ4jYGkZNDvB!M* zxBiTDqL0n}nXdXzUq4aC#}xPT$N>8pYO%3ZQ zT(ug*T&m#qe4jRGh?weUly6f!5dCSySxmlay%FP}ZVG zvhU`U9Br!Xx?l~re}&(&X$%v}7f?4QDT~>zX{hPNe)^Vs+P1;bH}{bnm1v_;%iork zseV#N4_(@>=bo3C1$JT5?w%9hJUmb6NCsFo?r3_-yOHtpb3PQNZA^^30h~uw(j1O- z<4l(4Grk{jf96q8#Gd?;uZ>PdsA3wYE#w4jiIA3RiPeWyid7%XtpyQ9dwvgB^&d3P zYH?YEhS--ViIXRz({Nlb?6m%+{O<32)LizJ3NOIBNslJTwGuU~cY zG4^r=9%sh{*rqJ+iU(>kF|FoKJEtH^Zh?{=j4M4DQXCguO&pS=Si=< zXwdK*W41w;pUuFn@>EUO+sBJ{p+@In=jx!-X!Hi+~l*cz)- zuG-=OEkW`0=)u63Sin01WWg>?+S@|`*`tp+%)t51(!1%UU1ub`!AVY&WoxPEU3 za@q%M=(Tr&l$J&Mj-3Zcq>2+}jT4-!GAbQo1QlvZTpVU}GXb=slmPV1VoR!q5MhYk z;CWmmsjeL`oKQ06eQgY5J&Y84>243;^=}ImxQd-9_iB%vf227bb!nt++Hh%crp3%7 z=!d!nQ)_$YdvT+%+kKe%Tt|1qRF%E<6I<9P+4n~orB-yCx?a!J3l$KRN3b398IScU zh;jb@%__5EvOLM(Hr^TSJ(s$ca9P;RJCpgB}J$!soAZu^%>kk_onwVgBLfW$xJnt z$?ds&Qr*`+Jg*(Vrpj7ZRS_VW7De;K@fG;2T2q+wgXkr~@=T--eFb&bW6I#?Hy7*SZ~|)*C{4*H-BvMgH^Rn8*I*o_;)i&tN55sLh;!jU;8D5MHCe@-i|yG zftL0|ppAGCVWi4t=27n1#ux%eOn5INM##r%`~lxaioh@0@1>-@eQJv>0vRX`<4RV= zal722id&_nImTjQu3=0V!d6m@nX=(3ZWsUZ+7{{8_d?CA;4E zim2uQMNTSH`k5?PoDESi`=G!BzR@Pxb6&b67W^zh74K$`aD3&qx6hU!E-GN*Gn|&+ z&mTJ89@W&pRbX;EWvpZg+hd`p{uy~KI3ns0iLN5(ut+Sec3qgt`^xHDUy0ZBX zdPzzL(){%2{G{-|syuGy=|q?ZE^YZu>HPkmdei^b!5>e4%h$E&-KngvtexMS;BtG{4L`F zH2NzzczNNTZNbpE<%M^~P09eeGv{c3+O`oE8VBm&$8BCp-CgtCqs@QJw9E5+EI#U%C=Hjof=>2DxyVXblYG zZ_6rIJWj#px#oKS)I1D)Jq!Iwo{JNWzyH&BI(Pfgrs*VnjapQXU25zX_@r6CgL=JwUYP#HmTF+ID>%97Skc6`;MMs z)~3Z}zV4(In_}Pef~N`-SB#rYIDopp?Q_jk!_6k>vKt@ypRbG1um5tP1Z+j;v0KGO zWM7uL47w;SYaTSo$c-z=M7R*EIEdNHY8%SSGfyQ-$8OwD@ou55-gt+smMmkRxFr4R zfAi7*;amp;c7ecj<@^UD#a45q|V7@aLw3fSm{mP{H#ekQMruW`2hRFEtDDk19VgF{Ont2w^wY# z`#4(o_8ELkeD=BL*f#-0=4~R8WAw4uhGvPLt${8gAwcSxNc1s@`w7wxoDWD&@&Cv9`(1^0;2S~hc%krH=XB(&VVSn)QSA~Ix zVpZpM?XplUZ{M8YL|nK$O7jx1=@@h|(9+&$-vDZ>`Z}#TozihQ%(08y`Gaq|(uI6s zRD!({hW~;WMhZWhe8tIF95KEi(!d~x`-9aedqnY~ZMd@vA)qhRuo{`|K`Dp5HEZ@7 zl$Ygn>YF90x>p}{IT29TG$qz2KpwfaYoU?S)p`N-~L?=Gp|M5 z_~AHK6r#WH`PJxy|?=1!O-OQX@zT`iMS;pCxE?N z5nkYx_h^{<&cstD~pyu9qu(!ur8{^?7@%{$BAj|)AcQddMs z*H&&v?&*2q8UCxqf%T%YLZ)dh4VAjtMpT`pvwd8Q{HPf6NL!;>YT5}4u}ar!ocmlO z%LHU6%!Kto)k_OUY^PXLG%05tU165hh+-EaRACcM0WmO*rkHb$EVu2I;SEr+`&3E@ zN%XfjJ5}0>rh=9foA=T_1?3bffqk|ihNk!$HmHzd5*IVUhDc`iv@jeIX1l2!_UqWB zvo1A4cpGb|c>pF&5-PUo?ZKW&``M@A#X&vIGqcYoCaXB%NoAtFxw!7O6!9198zN~ZPEo_)L$H%ET*QF zUuo%gZv{}&UR|!aHY~)mwwfFc083N}8e*E1s@N^;0uTGw(V`5d>xrfV&53g2DOVS` zlLPJ!W3$V#np+nLmEM?NI-tNhp>(HIKYfP~L?OW23oDF4W+!6Gth8hH6HomQz7q@$ zZPi$e{4@fQmEw3iqo@WcbJx4-&hf>seqg_WzE=d?2Taa-PVom@y1$*?+b^crNByQg ztY$V;VRNxs8J3_L*TiV=(mht%wy0UWAx}&_iA3bSfMGR+auCa-mZ`hd7oEZzSllRZ}7l1-P1V7NnJgN1b}jX1}&%kUNZj03-ZxF{j*#AzimLzyFZk` zB43WE%Q*r^^oRNgT;luZ$VyarEko!YE&n-vyzV}-t~BM>(;+xvMc^HjJ_klna`>8W zZ?wyp(Ls?XgP@@%LWl6(h&h(4-F#f!GK`J7!KkiwIDG z$JRfr{aFqk7}OfxC7(RsmJ(}jk#(ZYViZ4y%1j{0sv9sl?f6!bpqZ@s4<(rsjA)>~ zt1r|=ctKaH*2L<5hL!4h$FW%m-9`flpR~5Ar&M0Yzkg*+0hE2MSM!=8FV4$}0Rdwv zTv4~U1!N=Qe)BIh)8u5LEd`TPADj4)EoD~8{q$jS0IiINBka{p(uJ-%jeKp#pYHFr zozxVKSEToqQ)Z@&5OH;7v3)7(lb>g@kQcr`&9M%Z#2HPRYs7Vzh7~iWcSPAP;Wu>j zOSq*Z(s80o?%+Bp&b_#5Qf&J>YXVr}?~Q3^E)hI(L2DQ2h@)1L*sja%6&xjq4uA5I_2X!9CIPc;QC(NcD& z^#i0xyf&^kruj~(!>5@XT*{Y~hmMXvz73nox0NiW&ApcchS&qK56rfta(f;p=NoJ* ziZxxCNeKaC!(!WKhKkR96t=OaATQW)!icJdIezE%RdZ`^xaCDO*U2r6G~OQIxzR0L zxnZ8vPde5#c=}IFae6G0`hHQzWAfW6R94EvJ6W2fKq={d987gzaOqJTUA|`g)wFF! zR+N?C%VhYbxqLo$ri0HvTkUVF!=d$qk~FMpRnMg8a4PJ3?(Oe?!sOU};e{jCpzD2@ zi-VN2oz35B{w8=teU1J0uTmu^n995$KZx;YU*@?V1R}qb zN1%Xw>dsmh*QYSGo@sMV7k}+KF2X0X+*SVcgX+6z^S(@hTYSTzoZ5polW?Z6nu}z{ zAABY+2y@ZPS_N$_7i|_qn)6ye1@}wleKpU+sKFdc06O{DQ|5W?7IDP}5r-v|z63^- zv|I~aziVTI=&HKX-G$QTmR4s4MdF4LH!R^yAN|2xW6?qJ7`9lf-zz)wKH`14hEl&H zIIO{jr;qZdndF<=w=`P9EE@xBpw4y+iWLP`Z))%~qvcq%7PpiIO(fKjf^yvHiTa3^ zcxny&`dO=<4~XGWOH$r?mHv>dx{;MX(IDsBsjUc^P_;}WWLY?=aMANEsR`)FyLc_!)|>1UNL8)JUKp#n-FIZCFG1aX0LF1&Y- zA{e8{{LV&Xr(7~@_RFcQBD9RLsHESq&gSB`2N~^~C!VNBu-e1tci1yjrr9PaNIOj8 z!nK_8DhjULx1{YeyOjj;^&ylI>^m}h?)mh5w(>Vvw1|Cmq`Oa_peN<#a-dmCl6%fi z8y+?879(rQyyW}O-VFs3n-y+%AIh0+4bR}sfQAHS~n{J~em zx>pAOeo~ouQSP%C@3ZHpZyoQR)#_eno_#?o2t^;$Ofk<$#M5}&+4k-=?4s($4A1Pw zUnaXY&OUI=j>X1Lr)}SQGeTQaoMR@v(MZ`GYW=9lceuEwB8z9qH)h|3k^Q~=qWH8c zq7$xfsrkFj-*ype4_R^hB&3Oc0eVqfNFYCdpk&oqLC^Ta~$BmMGmQ^fCI)LI3 zf_To2hyP|WhyJp=Lmqs9h`&tc*k9&!^d%qS^IxXu(5%XVM0YrmN(2uhD zF-w;Up_As+ZuaNj4TkAKBA|dJ`JQ0Bt_;IqXd^v&`xfFYGe3>cOm3XjQd8?E{(8-M zMQ$T7o7wcOY0WTOoj%^}ssA7HpPIrSb>&+#*4C%q?&W+oo|Qh|V)$1fRDABn|0&EX zp>e!!LVVMH zvG;OodeH44%r&zCXp-kK?%kpy+g?3=nqLV2o}6Oh@+T|a?O$q{LBN6#@m3e;WT>$0 zozSNDAI5g@-ZnQ&sD8Uh@|@AY&2T*c7*Pt3TQHz320?tiOE>Xh23f#}@49x&CXNu~ za{JP(-^iV4Y}IudvwvbBNIR)rLc6FRv?N)4KK-2CJXX`7%;AdM4gzrHvq{m+t_jY{ z;PH=>!^EEB2|>2r0d;u(6_bEg7-t&Mu@_0ttzEd#*zQK7#z_RW&D$c+la!Slq6pY# zxveV4*h17-K_Xp-XDq*6oiUr1>R@W^Z0-0c^{h@=ojRPhp9cO@_>~E637e-<@fp7Y9JbEHZb3lQJ!Az`M_A1Ajyq7-E^^?o-VQ$s-Z&}1t z%|LkxmhXf(c~rhnSfpAm7UapkI>Mc!fR#r=5qFJQ}$@AhCD**<#D zzCp_(NQIy7gct2uR*qFvTRvTN7mQd~|5jA|&pw^(@-HsFaN%a%6t=9V3r*~<1tH7f zn`LTU-%pu&#-h(Z%yjg`+au&vV_VzPT$=@dzTd#?My2=2QguRn#GOxBe4$l(H>i;| zdNJx`x|4-hqkZ~Lgy&AA3+jVO&XQw&@oBOJN+tkU-UK#BE*B?$}~7EhRt%Xkp- zc5z`{XWVG}J`%{Rw;})sMg)-LZR-s7M>7E&c9(a8zG14bW`^tVS5vfE0&OT6_~*t$ zPyxPZEu}=JYuWD^zmqTh`LF)};B_cOkXP|Fsjl?9OxuPW{obBz1nTRrDt*^cmI^Ux zi(to8^6AUoX3lv(Q@m|5V8Fz*Qca;=DgLimhq5o7Q}TB6S^ZxTQ0TTerO;q&Ytu61 z?Ps}kM-o+JkN8`^Mc}Jb`57tpp96*J4Z8aSM$5}S(m$8mQN`k@5}I$O4f<;N!9y`@ zhC%*?l=}gW&6*-g9Ra4}MLaafy%5y&qT-y>FA_t9DWJA3NOS%r(#8BXH~0^}kF9TT zl8#sfFS)2G+=^L2oI+N%Mfhx5TTlu$|6`ealz|+!qk4fVQFiiHw<7qhXFkCrgA$wN zLruEA+fjYzq&23Iw_}N>m_+Bo999r|sh(E7m9G(TCmMbuQREgT!{gFstLEdI3!O_o z^uRvcO!i;D$#wBD=(GIg5fkF9n^f@-sXn5PN^2|cc~KC}N-SuNm3~!7GI;lzrRD^7 zvYNUPk^fGeB&vW2A4RNsn`#XbTF7ne%Rd%$ZSd+@hP%)Ap{yHzJxaoHg-F-_NRI>N zuN7`Y>L|;~v2B*97;fpp4l4CjK0dZ8ujgH*VwX2*gQf^8Stl%5aBg52uiL!~5=l^M zY@)xp0X1o%Wf}hUzG`0-F%zuBs!kZ~TPf{V;X9u4Uo??JbmtAZ?dOAF>UXGaDW6xN zBw*PuCRoEQzy-?0cMdjpY;f9JqM{&YXGtNJfAHC0*ZiDliB+=I)*Uf5==vKVkujl_ zi2Q{w?efpnuK5{>kOZq` z5K>oD6Aw%^xoxoR7dP%*Rcgl;mMKG6t46LTe%j6|FbRu#i#HVu7#Sh@TKHvp26DVg ze|xb+d#!iM?Mk|wBw8x{h)r92;P=hf0V@sjy<8uAj&aco)8xm?_kmU3i!=;En~ zxb!}rp;g0y;hlETPYq$5EV|u|Xo(@G7^l6vs;>MlINSK352Urjv(h)s%XZU&Mq3<- z7H5Xgkg0dd%7OK?1?R;s+(fMwe@UsMt^orGZ ziY0rXb_71rpj%+4_ABcNlUH$Olu-BZp!eaaBCa_BwI19aw?XbGSEm=$PHNtkG|;Q+ zmqxqAHa<0XLa1e|w{F|Fo^L)4QH}cElP&A{#ld;RX)9zCJ^D>3*>cEwdgVGM{!8qL za4dO#+5fe7$SgsGlxWneiu#MTne;W_?OrYgsPF%QR;Go(nQ@JeYsM^k4yq~fa0?`5 z2$b;6GO(1J=hJ#(Sd>z#-+Jpas_FGDJ2^=^5E~{EQ;bVvo(^EmuA$m=Pjz<@2@ z2cNcRPC6c zG9P|ka%@}3R8dsvyA^jWyje_9O?;ZwYg@Xm82%Y%T>2+=E+oXLLoD_|hn|j(-5-20 zb6D~0qvR#Uq$Hz+KJQ%#K7bwV?h#dX!b@6O3>z!uj&-iV7d67~4-eZ^bz&;4eh$;wae1Z zGVR0i3)%4U6}*t!LFJ>g7_DS74c$&&{JiR5Xn31Pbs+$4B{ydCpyoOf4FWvYlurst zy@b+d9B?Zt$a{F_+y=XczojNFe$jdX+7PBGKh&Uy078XwGv;dd2bF0Adb8Tr_US}T z(bl2yZ_{QR>gS{sM>qMoK0C-^kn&~w8mFnqiv&t0p;`^zT7RCJnt^*;`3!@Olam9D z?8u67**Q^6Z!v)}$A{Jvd2*VDKo&cePG!t*=mK<^e`dp;t8g$bNqFfgq{^!CfpEwKytpzNfQ~SArRZ@yLKz(SVQ@m5%e55K1`%RMiAh=?YkcYUpCiKn9NNR09v3?LA0!}XRLU!M* zjof?dzTbxAldnt_7`)&2TxCVQbyJecFG@{2HKY9VHd!Yg=inpmyC8K!-5tEXXhb=v z@pWRRykIC62b(ykSkf6`Wq6B3ceL62W+=X74$;a>KZtf8v-Y$N?COj_t z)}b>V{cX_ro6PrP$%V4A=hb$_?ILkEGk-$lpNFz~t%CYet;X&Ss^&z4?c5xQ>p9<) zZVFs*oGrV3(b|IRpBUz%uirJL1oe$K^sfNfa2*#hLJWOgVCP+M&4U}Bot{Jd?38D( zdWgzcr(l;+B5{~iTQskjC@X_CI0%zQ<2A4Nh3oiI8#It~4Y|M%xsD1DAGS!wVnL9n zrtGgty-07sSq+Y>YLV*=tJ$i>=ij4~1Kzb&|-cdNNdHivm&VNZZh zf4nntUAoK;`^j1p!Rfr05!)zI0HR$~j5wldn*GL4YRXSo`Fas`pu`Pv%}PWma5zZ{ zr-Eejk3^!xC$AQLWX??5rApaSjX89yGGu6GfFv%2|4g-z|E*k}>!PU_zWc2n!dmK% zG1zqq?rj*WmSmEQ=bWlypq!Ik1;DW(85fd_u__Mu0%Mt%%e$ee#6)R_RD|lB&Y$Lx zcE5I5KA+jSm1$#)KVP(rm)Od>H?YSGWxt9@oRXJvVA1ZrwL&?awM{R%z2St16}{7u zEdz3Es+N)6H%jh8kK;~jU<0C*{CQRVOh0py#)OZE*T5d}^MUAs9i|AJq!ytUaI2L5 zqk=}qv(l}+yiZ|On@;(yuCW0A0GMrux(^2R$!`|ouHD!>ydL#~)GK-#-Z%>;E12Qr z651a5lHRC=l%p)5t&WD~wI{*qBBeA#_1%}NzMh(E1>7+JXB8Be^;Q4l+W@=?A0HJM z^bS!eyKOnSQT8gO-&_h{I=fa>Qcbr+5XQ=1c=HE31E=G2jQ4#fPXrfa$>#l=>f zgV`Kw$`riv$@847gKI%idB3&(cB?F&ty)vlyhTv2t-<=bN0Iw*&^XNmwanA3_x`~OR?~*rei6LnpEiHnw60yrxB7#AyIy7x)-0+REG z=W9%zUT!7|7tOusH6&_KoA(CS{E&;>qW8K&l9a+RgP|>$ng%)y*Y-^(0&eby*tp8? zNb=2u^NSQwm8nUx@kowax1;>)Mf-HS**=w5+x+m{NI`Gkxu!))i5xMan|b1PJZSZl zYd2@eAj2rWCGf1hK+`kt(hKPK*P5zSO_@*~RMvuG!DORBU4c*zdp@=?&g)~x`N)zH zLe9d$p|5j5UMLqy;g6R-q4(M6ZWCYdoi+L|MpXZHcPA+LfFdHjMyro4t%<|jlFYN{ z%Bzn#7J@8~UG7qJr?~qfhglxYAcTR%+l}_Y zm9An>RH3mTk4y2g(h4phjBLhe#r%Hok^(d6L?f4}zPyQF(MS5tY4V+opAAERAT6Al% zL)_~EM`^wR3w^a>^)^iHk#ZuQWt0_{CRdda^OGmo-2|(Z`#eOZ)=H;)@G22o_4xWj zb8!#4i{Itz$8hBFsBAPFQN;?tqp;S)pGe>FANbJg@4ikgi7HIs4F z{392?N|)q-Z&eO`^0)blP@IMIPrP}ahxC!W>}kss2Ku_ICoEhJw{*UEPTX1^uxm^V zE=}BFDq+Y2vw0ytN_R;oFG|Q~yL2*>LlkJkQ5IEkJ34;LuMl&;3oRQlT5B`D06VQ~22FKY_ zVUCos>y^>}Gi$~6=!v_c;9pjz6Ox0;@V_x^m9Pa zhtz2*ziK>qRY#@CPxgE8Zsv0)i&q|1@auJ4n>DxWFdVs21jvo#U3(Zox5L_fUZ)0BR>uK@2S2THKiXMzDe2~$o*G0`v9RUh zo_8aaQ(Ozln}sKO-(nvT?9&PGbjQ+}wmhcO307a9E-FAzeCD8V4!WG>Ab&%#Hu;`^ zyO<*_p2415QX1Wq^5i#mMi>VdzADalYvEB;sP9uI8p{w6mf~} z*X03-YjgPh_thz4Ih8i*6vteYS>?cT+0TQ8W6)BMzUEIDd#m8@utYN=ByJ`#Zak!( zr(1VrS|7*8$c0mLT~`=|tqy(YoV(3dv};N!!Q%TXz2b{A9J_6Aj{`-AloTIBQjE*X z+SUWWl1f_Nn%_{T8OQAET?)P8!Q=3hOjU|-qD)1DG z+gBH)89cHI$1V2B+SqMKIl~@hacXuWOTiR7qAz4|#`0w!Yc#0(C{+8D7Xe%^tQ`-o z>ax6{zkfT$u=(p|e<0cr`b4pWMyhtS-KcPmuQXNP|9-03Vs}JzLW?ZYfah6l5k2Glv znvN-Yo&2TQCVdH1#*H?BIB(Z9MEmYYynkcbYJTi;MG5+2inK!}WmWdFy^aTySAd?l zlH}X!3_>Zy6;W!ML*Gyw)H1t&CNtFbC}?LCGcgN^@w`1*8wZ5KZxh7rUw| z9i615-R(&7`F5lo5^$F3xFj3%Ph^%KZhqT*#Mw?R1yuh7soJ?-_F`0e0!8Ftz|v4# zCF42p)w<*5w&qwuuko*mCV7PXfFV-H=G^;c`x1+@Oczhj=_*61?8Bg|x3|#+kvRgb zPU7?2FAepoarx(sTkn`(r@!x+&&a=-EN6^JMjh!jcGMpJW*TxnFFqiP`;g*N4mCa2 z6HMg9T2Cn5g)$?T^S&oNIGjFRd};~o2ry+L#A6ml$Ryzxu3lGF)P2A)I7=(ho+rr} zd4!Mm7xv9XlP{ZO%&4bhTkY*k!$uJPS*@ed2+!Ohoic+N%U2R40#A!85x_VeU97k*rsnrV=+HBSozleXBP&1FYwzyEBhhflZD_ zKOgZLHkV&w*;I`n7zlpns{zmmrLtEA4?pQ3RLt6Cejq(cKm6;UbQFynh~-(ndBG^X z0ezaETk*E3h^}v;p)3rsct^Tg&Otpg%>Z~&5Qs3FyRz9Y=HRm>H@r>0&CwO*p*?C| zs!0hhlLv8eX#^&O`s7kd_HpN|S?Zktv*LTgAfK!`avWBq2W`Z4bdJv!4Oen4gx)KR z8%s9Bojc-Q;A{Z(R=jZA#h=nr&<5q$mpfF)wQ$nCALrUg9HK;m6ozmVPjUgJKZ)D< z`Xd_viF}-E`p9czaFV49u_1vG-o8qucegf3<#t-HdnBcO%$73}%|j3)o=caz)5)=G zwQC!q${>$EA*-OyZ-AaU-f-2&m>PuE<)+{V=oPqs2DP=d)5EDB6Tg@uE7j|BT?f&n zrhNPHso~Ob5pUM7*5u`(CYZL(@$oCYmvJdTOo#q zg(iyQ=i+Txc54TkxRPa$sfr2R`>J;8Zrpy?RN&04TwijjX1~c04+Hl0nC~7H@0H4N zQ1kh%m=OX0&_U4ggS%09pD$}zKc#PTgL_HGb! ziN%-2()7`xxCvolnVsrgsYYs^L8zJ>*1Yb^#XqH+#2C|Rl=uv&Qtmf{l5ZsHr#pUs zX5I_n4~lr#|5R~O3i#K;JK!tw`^_^;W$TJ1;Yqp_fWkj*iil;!#CJ+Dk%M$cq=3qd zxqnyXUVI_Bpn-r%jC?rw`Z}8)RwpPY-@MoRR}7IuF(w+8v82qC0RfO+6{y`umgxe!PZ4f2Ze!{3#jn zGCk-`g0xW#m9gzR_c>$i4?gV|T}H6Mf$gy&VJhfFd|OSC6M9=G<3c^KJWp)L+i!3S z&r>9Rav+Pr%qS&Vc!Y|2g8v5s7oYy^jL)XJ!dA%GDNrf0^>;bGyx65E#M+7+k`#IB}h{#S=`V@&x(aPf;syGn2W zZlIncP;Z1A=rH&VC9E1ua?Tkxb&hwkAJzuM}y}ANiEx|0<;1gt-K@6u2lBWW7ra37?Hq9{Mdj zOl4bMC{sgc=*w~>K0;q1Ryw?d1wLr$$>!JUFe}c*x9||X?Dm#eNziv$*IKxbh_ZXo^8;HPMj{6?XW#hfaG(Lib9XNszepC~cQ}yg=cnJP>2|(y9(ga-^TeKZ`{!4M(b5saKf^R@*>$0T zE2uAiPc*Ud0!SQ|jE*Dam)E&Rf^y%vAH< zn`rCao`M@+;88X(O2~}0W1hO&H-Z96OS=)6VgtxZ^eby*OYAJ9Ijw}#T^T+2!!O&M zghC>s7}_ecEtvFfvfh@s>;zhLbV|K$C^?%}cnQMz;eCZx#|Ieqj(z44Pf?{YH* z)kwS$=Y9a7pvyLtjPp%PuECu91}u184R~sddR>1Q_o)2gg-g^3z`J3XM==`X9hxOe z4R14?y+sz=cAs$f#^*ztF9I4nWdhK2l?(I_ny-{;{~li>f;aIRe-8}&APtn zV<;ott%PLCh+_X%d#{Ok;p=6ap?M`WAFdVKQJ`0yQebe`RLm*CKfzEr%^~f1aA3ht zpK4Tx7xIi?X{8FAK}8=$#xIVh8Vha|h*g!jaP*&QvtqNG_0`B8Jb22cW)M-?>gT{PsJ!51U#*##`2ja(_TrEUj;cQ9*PN85H`G(?fBN!5~4MXrSLSgJEc&$X2J7= zZTqQbXKbB3rzY*<9Ej|_4+$naKq%9X{3!QHNz(;M794IU@Uo~7O)Kwmj&9QL0`8l5 zg`%-2)x5Ha#ifLVur%rWAW#{w9W3K0?0%Eu;-F>mCV1#QgEpkg0P^L_ z_?_>#jQV?+y<0?8M-!vkSK+FXH!d<+LF9%K)f2NuV40)|JMxQBDe<$g3j{2BzYo~$ zsZ%iW2Onq+nb3N@t(x~6$>zq18Dh)8K-$6D6?14AP;)&&v4V;-m(a!;O9oP}eTP9l zl=7hp4?J>n4aM#6zYo1TNYDQrWd0ABrHSl+z=wROKeX;-HuvD!g)`>M!k|qGM5C=8mQ>$+^h~{T-?O*KwEEl`iKrl$#>%+b(bF z@1EiWw|$dIQV0NFeV0IUX<f*e^SVN+DFYnEL-r7mep^@)mhygZ_Ba+JS?W z2Y`1)V_Zh2>kS4u0?DqT@ zQSVNG6fkqBmRJ^4wZZPaFzpIxZ;2+B&YgOXeQj9Kx}SJJ&wg;D6Ij#~DBmP#E8iF3 zW3h#1mY}D9D{cyUf#t3h;Dv0sd1kFOF?otW3}$f${8Z8c{UHMthAdcN48!^lwKG&) zmP}pPeWQbl7n>tAp@f+w_2S!))&q-km;-JjWt_tni&5ro`kMv%bjiItLACU4{G;iR z*215gn#R_&+ktn3p}1deHP^8 ztHQ!qZ!^U4kn0%;+GORsBtsy9V@i|~5d zQ4T_6W@a(MVA^nQ>H4pZ*saeda-Q;{jA#R@Lk!zTuJPrEXo++{2VrQ@{@3?kg%uXr zg|w~{0m9x93Dqeg>UCwZTc?7nYzHX|t16~2an;&{tb>AtzQgnW?)0f=#xGh4GFG}} z>a!U&Mgj7QIf?Bz+f2ia1y7mbPh%6Y#B28ey)GC(K;KXs6UNllEIy}nSDym37iy-B zcQMnNuA{Ey^HP5dllTp=xa^8z*~zVHXwH+#Gy3{|{qgonH-+0~fBb$aZ_QeV1$0ju zb9$@4!G3s9IF!@s3vqb!2VbLL=Hj7Og&>IYQ>%l1P6sy)6k`pxGUQro0rQqj;QoFFt{sTa3)*HI$W?-$6fK#gqhlK0OI|bQOR4O^MEppl@6t{zP3M;@k&R@lN4xs%(kEFa$#k@m zolh)@9cRAYFdi#l%ARknBqoU4xCyTupDjCi^#JB;e7?D^>;Yi1-Lb+D%_S##<`)>K zT+2xGt(M-rTx+d#st3nHOY{QT(kL-I%`;{=jKR}iumx43RhmCrd1NHI*R&nfMde73 zcYO1;lY*8#mGMEqM6gu4$(V-re57E-9U-0#`x44T-E!U5R!KSU_l63SV+*-wO%~hy zaUTp~X7DQ3g)RzO-i_+1!``>3Wbq;jPs=u`4`zKsgkRb=zsf&!quP79uLkwa%p8RY zM9tr{$(v&CkMO?b@-u^vt2Zf`6AILfMc6ax>|3+J@yADA2LN;Sz@4S*Ubuj{NAw{M z#&`4bzG(H2gG)63oj6KB#L44aT->S}cX~>FH8^tAx765^_Sh+ErO!`wQ!s8P=zf3P zx2TciDUmLlpp}x%<0Epb2k8QeKE{P`(EGRsH#rT7BqC&byw4hY)!s@tZhPReNYT7(V#DFV{wvp$R{^0xJ zT7^ZDrM-=_qtOz4o_xe(6^?dy^-&MEx zdwg~n__9imSwO5}c!wxCl?i2+6#^LQpMtPy_ps$I!easgh%wMkXgrHp z3`d8?nQ)!ynl~E}A{L;ZQ;^;6CJTWfN)$=-W@gaI`JIL*Ht6`HY9$u4Aoo4QAAGUz zrrbp;T}Mntfqh=;0Y4?PTS{g};ay3o2^yiX&_xF=%~qs!GKtqSUZM1(WjBgYGVqA; zEu4g_Ku!&69!J7f402`<+D6G}tC}7mSyfu>zF0_;#}~t=^yPLBM{|!6@&cdr*bcE2 zhAhi%nIjmIPbM$vj6GS&cjVGj8w%7GGPps0z_G|_mF8B9I!0qr*D%<^$l)?9Z%6~N zT4-&+ypW`%nz=AEVff}VwCd$hzJ5rVqv~$!tY%2p`stYa(U%wm#)6(gnNd~eAAILw zs@vk+-{!3>$U*~d*HlJ8^Z3Q3zLWvv!l1Te2%R#uXP2qL{*9e+aycY8Z+c2#`%9Ge%> z{&S!4J=?ods^|?Rq@d$Zj##ze163L6Xws{)mSQgo4zX+68GuH6kjd$m0=}_ig6s#_ z+P?HVjivY{hM72$$Z|QS9v}j_ur3dAjR7OX?P@*?$YqN zN0><{)mja8soNk`V8`pOmmo!N9`*>xeOp6S*_Ppv$LsW0Mfa3>c(mY8J2kJoO<)6B ztsC9q5H|EM2CP9paiam7WcvxXikgRYowQnn@ynolv31muA-?XsAT5#O8@;<%-`3$p zEsy1%LHK-wstcDB(7P36kKf(4vP`5NFZ15%pt_AiD-%!z4|5S4OQEi&)4G?{PZAR`nMJ!=q(4HkTm4 zFxRq@miRufOHm-G5tJmUzAT7nw#QaN7rtV( z=wU!wW*+WE=EKL8L!T=SQ;4<0#jGzPBze2cvPuW%3!1qff0)8LDYvC{E^@# z?7rmtz{HD5tvEDquSdPc;)RSJm0f^av*5QpLd_Z}na~3x(DEWREM=ujTfa z5CeaRdHsOxDp$&6O8>XlzaG5)?~7;&bIJPNcCQOY;{KPU+y5Bc1@Hd5u1YT2zjk?9 zYw+>vVjx`)@?X#jsqm$Gtvu&iKftv-Y9+kus&oJZ?aC+3d)M*ct| zYX{}Nn)}ihon&>toffkpD<60O@}-eHm`U;C{wj#Y0h4t)w?xySH=3M;6ONBv z-p|cqGnI5)6h24_gi>Bmbx73i!EB}7fx_pQSR^ZPn(C7uBfh6~s? z9Qg@#*!hwzW|~l|R7rbC%v7%_x*=D%j8+$ic8LU7u2fhIDc~H&CEq%z4QTe|3B3cP zp#%_fyYdY!DwF?kJ*82bSB9W1e7kDJcUPo!|KZAhKE8q#R3*v_YQ&r2<|8S0ex@Y@ zNf@Ogqb{v!wMD}L)2PHT>TNa-w1I$NvsN1y+Y}+9w zrO`I)1=89DMBsD2jwv^LaE_2roD zj)1nhfu4xGg(^y&F<=bh8~&hweOos8m6yEd%cN=Fm@KhH7tU(TxB^Jyf|vaSxQ^WW z@uyE+PIfJijsNp%cJ+6X!uV45M_6>Cs;JMZ+MJ~_gi>kvObAN{vvgDKY)>x>J1its9BPY4o&4NN zV(d{XBCzoRnhGF=H~30hfk1gdNaeRF=Bh)HJ%|I1kgbpI&llI=d#&=C7-z;vnhYMB z*S;7=w@P3*>i~8BI(B(QpL<)Z^UJtnl>>JfPJw3Ouxw#U#2kj4#Op}aKKcH;Rm`yu zrKZ%|X#9Ro=vqg{jG;@Y6rK7#-D=gVLIL%~_rrE@HX?r9i#^wS5o_-Qnp76b6oXgj zY&gGlJk2_!R>qYjm9hG4LqDsoe_nzGwDp(KQ(Vao%WMbd$ThJSO};{>H#Tc<_TS_; zZU639+X!o#lDljtf*l@%h+ZcFJvclB8piwd&v!@NmHW=Y_8a%H7VkH#zO?FUeo8*EmOxwa|VztlOG$Dkl8G{EOWo zsl&CTc7~l-S5o{+zYwLnZ;6TT7>V%yI~x+x^iA+|j{i^h?5#1=yqIKzzdi=mr}2P`Fo5ea76 zWAks8wY2dtHvn*!H%d0JM?p!{F0DI0b1zbiJTKxj4Mre9@0NsBVW3;G2m$qilL4&w z1@!8JW>%k)>~)WuPW|R)} zP$)`&am2>K&3O+i_XPBizX~I1OQWm#_cmisfMA5u0^Z4`Ls{EQ#9!t)3y#3b5CosU zxV2EO2o)A+$_W^G4ZXIl)iyeJU6q<#(@|5bI^lrslcy$i^sCBl!7S6w1o@W($1pUH@k` zXAD^Bgb$C|voNnc(n$-n?#vp(L1AK2VP4HnxB*eQ;L8w^YKnwQ!xSy6Fg2ELwBUxH z^c0uaJrs%8x*^N6#}sBQ!!hpd9seo9*w%)4uu^h`^{o+#}^2Ib%exx7Lgnum)cI9oi}|jurVeta}YCA z#kpUcxj%CA#%r+ZPO#>h2@gNmi0W!#Q_0@izGi`?cpLh)xDe|5msjpamp-ChDuG1Z zylm!`wV>LNG-60Ti=h)Vru99b&)B7g;kv;eagF45hyaX!w29tXT`_A{#yW5 zC9RS9ARM~GS*J!*NChYTd~o=f(stR0r0e?#ma}UnrPSl~v?Bk`tPj<7tg&%wqaTF} zD1E$6nbxydihQ zfvT#}B=Iu;sj(@7UxneN-Q&UcDaiS2f3ug5t+zvFi0ZX1V#BtDk!p6f)<|rPZq2cY zr{y*@Zo|25e3Cs67KM^bli34Ie_@-V)$Q4jllbJa_nxDx&vKS7%Qst09rYoDcfm)O zW?RuV9)WOZ9a3~EnE+hI`$pefp0z6x8QK7)qMBDWo;tq}d_P?p)|xJe@G1DLbGt}$ zt$xU(X43Oon0OfDAaiVywNK1(111)@tf;)DcS$cbI7qQ6cU5l&4y! z*X4Pv7w`^AN8kQ)+@&JCI`l!FYy z+cQ{AhGcGBHg)__ecS~iHnlo_sJz9&WSAliC);(%u0*$Z;k~`*0vf}~07F?hz`dSp z1ZE}JP~RZnWtMvz!1XusOd@U=VF`LrGAC^2Uo)Lk^`0)+Ju%%qt`Ol?f5z!lMh*lC z4Db>UcShi8y_qT8KpCV|~@9Y=aP>v0=z?L~Oiw zm#+1@RAW*5YbBls4&nysPUX^fW90!ELZfylo3$2t$~U^915iKf#P-T9=Jd;y;c8NT z?H*HGYq`vbDA_WICsp0?nXeQ=$6~s@ZMagM0ps+7as0ZNS|Ac;lY* zf#!FCrRSo{zeb)V_GBrLrM3M-Tq=%HfwRq)Yuw&y2VX-xh@TFomf;^knGuX0g`SLy z9*{gV1?cX72~o;h*A`st#vJ1*_e>kx3G#Z8Gg5CoQI>6N6)SziaO*@v*}#ZV>GbYGG&GQirEGP<06HI8Hn0X%!r||+a&E%TQ7FVCNMy{ z_kbWHIY-cGsW9==3v`#P6Sq(JK$FS&NHS*<0RHcLo_cvbSRph1u zyf~z<_2F%Tyq3{*iP@cCT!+2GxE*rMg*q}vC&R?xtb>u>W}<5>wFI4z%dJDMVYLaR z5}`weT1iT6bu+hp<3Dj| z1OZ9Zj#yNEI5>nxHP$=YvKF(n7VxiHs*RQhDzK~ZSk{fQjobN!Nm=ALVdWAUI?q*! zB_jD))_!5kdh>rG-^9E9&$FHu-=G)2%?x5Wrk4NnHGUU*Nm4Zl8=9)Q;#}2pAmjSb zx3l3&gkBQ<^Zi~1x+9!?yF67hd(%q!RAS#u&%4z|S|-;_b*gLF}!1kN7bldCY zJYV%C;%h2AG+&ukfYRp`Hw%vDtmcfmRRb@J$e&aH%B(sv2dLJly)K;?%tr^KKfbby0S5h@0qcR$ry3R7)V{olA2Wt z^KABXx2%y;_Ia+S=Ab52@|%SKkxRM}YkuJNh?8=x^XuO}mCR2)1Dmzp3xwENrWW~> z+2?s?u4E`r`bFo-L1Sn;7vK{kR1ndD1xBu|X|+hiRf+NKSu1Fk2VPRazNwNhor|+6 zFJh=4a$rz$Ja*ZQ+p?%|vPGAH5V~x^Ssir3*Hda!Le4Xr*a_O){dH;Rggf&Am_7l1 z@YNaT1;}E$LSGJpe#lXd-H>$y_BcV6zVSdCMw^+>Hkb5<$Hf_qV|ReyKJ z--bNoY*dX;)r0TzCz7an?eq`iZkM0O^{Kg6n@CTXC4Ls&&$ z8+G)H1RIsmsF*noMSWxa!eLA4m&D-ipgo$bS{?BU`z*Zdhy1yM3GbJ72K((e18vf z%yuvd^W|{;wC;8H+%q7Nk|aS>*QE16&i>hu+_Ry^`v=1z@7V(#zO~!eRLsc zYI$jpR69!`OB402xvBv8yv(Iwy-&7&W*fU)hz22p%v$*Ed0?$C&ez+k7&qCs7Ryd4 zb0)4;8B;>X0-WE^mTdV0yHDRo%(UCf;>0Y5K9oLRQ*XKAEbHA{(3mZZR1eE2Tn*~c z7tC+Wlc`Sa0r>(`k_4}-H-+eA->OaDv~znJeyHK_(WlRGaVxY&Dx-JX;B{S?2(ah^ zE=AQC`VBJ-lXpAJtrz%^;f$6w1c3(eX{zdOsVGni^tXonpJC23n$!4^ZC5PAPFn+H zo}nu9XcV%w;V^4AZd;T^x!$poikf|tf`2(#%y;2j4}O}q*%!NXT>1|er1X*~<)P|^ zLxth~UamUp+&QJMwvIM6Dw!`Xq9iaT{+M%o&ueb6op0DstPDh7{*6l6anSASoLNxY zCHbx_x@W_0if1G19rwz&@t6sg119+;Ky+c8$WgoJTZ&q+~?TA0;{AYjv5YCn&A)(ILgg`MOE8w!TjLZ#WLfV7k@{w#P zd9JPViD2S8ZXA?{M~EazG0oK%DQNW?JUTt_pR~H{%XyNV`lxQ27a*aepQza2PysS` zL_iJ4dc0-@fgB$F!rAvrI>djt0%-FbZn@3p<-WmyS?%~zL=!>T7M7#&57&8|HUU4%y@u)lV{5Fwh&3v%AiPpsVD@FiBxKN3ZGAT6-i**ebwmuhsG z_xrKoX^L~UYeJ>4XMD5qdD3M>LPvw|l5DQVp+)JEUEUeZSc@6Z%`lr>^ zHf1^wix4w}-R$D-*UGm>*;q?0Y$u6{Vt21QW>EsHBYLrwqN+=d8ULAFvoatEUm&4BFbLz!8iur9>!G! zs9kKQ(_+qqZPt4p_;9>cm$kgz3i`|p1bBh&CU7-!VTB;;p6SFdn=EYNi2N^u*%;EM5X{DyOQDFxo+8bsZrbl18?DU0l1>C6WGKb;ieiN&~w|;k?8j{=-%AZloq5yGKj%L!W-E*P^*Wtf#YK)*RXQ_)=%*9zpP# zjkk1(%&}O#^)|wm+Cfy=KS?V5`vFmbuU`MUJ)?{~wck%6b^i$beQ!6}qg_Kvfj^-+ zJ!@h%yErbB_IQ1)gdKv&o==ti*jW(j%$jSt)Y3X>;Nx5uMG_36u5uP{OC~wndJjK3 z7n5{4j&QX}L7pdqv1K_OMYRnx(QmjelKzXE?7!Z=jJU(2=MLjIQ><*x!k0ll;j{+> zEvMO~h(OSZ>b|?T44SL_Kf=?WO*k9 zMu<3=w?+x@FN8l7&$p2+z%qG1=)s637-`SEKD?=Ed>3M~@{ND0Jo4mOt^GpuitnxE z@|JIAzE3~l|24IG-k~57;$Otb|W>A=Lg_fqU`P4Iw%6l!R=D*yTh1XcMd1VAT;d?Nd;$r{+9@75_uI zYACEYN%Ll>tSc_VZXMHej4qE(bU-q$9yte^U&iF>S~$3c-IkV`n>OvO-GmY4Q(Br# zzXjcxPOuF?)i|fnKoKXDWWfcBuTCB{#xQ=tl)8>tIoA3vo}Y{xRoAMp48ROr%x)3a zi%=tUQ*>#m=(x-riowOl+uG7zVa5!iN%%05Ra3bNU-#T=w=}Gv*SF^KE{NK8mLcg^ zo#XuU_Cv6qi|$Qd4D# z-Y)GO%@Sx;21LOYUG8<;t`&2GfJpdIUzN)Rf3UMK-rtCOBQdt%`zvVq2*{6V{$1%>Y z(VdVHP|Kw0c&s--86zu=tg`!YsSs=kJ~eS)(1rM?=RS`qh(d>u0V2FA54{d@ZDPO#HoqYS{>wJKo9WZCQpkA;law(HTY{bfm+`_u zN%+)MXJ4b>s)B{_58K>dc?LePLzC;&o{*x+bPD=tzIk3B_TQF0m{IsrnzTnt$s*2`B~;5uQRh zs4xWDQ)FnXg)!!9agBrK%^kayE-`8=VpFz2#{Zld|KCwqlj7%g^lve9YX2`mrw&~3 zJnG<-s;ZmK6^2W&GgGayZmnUB(Y>0_D;=#RJl4J;igoP?Bn9rNf*HW2f4EA^Ac2^J zweAXqbWX@6ML{0i=P`N*oH9PGC%zj!#wceKC;dug1Va=mwrriF>~>_ms4Pl0dIvwM zV9hAPL!nkEGv^vD71k9H%9QKFThQ zyOiedPg1Y&WF2Pb({!%pvffB*BRT;g`tLTUE~+DjvP50{tHA@N=#5*#b_FFBubtwt zI5U=rSbrvl?xAl8USze-7H47maQ!=fP}z&xz2BtzDtL;MmUPRKk|diD0D+vBA@v0vm2vgJhw#Q{0^nF!bvi$Q_s`M@Z^r=yOvj8@@D)|kN zd|NZPR?*@3AFlrFE}Pzs=vQz7i1%>g;uqzlQk0))Zb!NsB+H@`c~DZ`uIZCSVgXlA zCKaj~TAyXl(;B)Wo6I2f0Lk$W0T{qzDJ7!l#?C&gze~p!S%3)Rh_5_=V!7jqI*sxp zv|GB`d(37g)sJuX`eN85j`r&NVJ~A$hB&1cvfSS?Q?hti2yzp~!L&`zX^yn)mPkvL zr&F2I6@Yn(;}e+plJrShaFc-Pm++chZB1DePCjy!`z?g?Lya$mf~ca$lgs|Oyk=qf zodP-*BPXbUqzedQz*ZOOw(Kla zxO;i|L-mw-hOy9OM(F6@0|)uR74^>MvfLuDh4=!Btt^@;I;sFx{Dg$H2#%FSJ7x%q zjw+ECi(7yE+T-M4q6`;G^x!H!mU>?GFTyv!FnUF& znz}3)U%PL(I;1f4y??(TI%kZ3#5*;0Ea~NCt8|$li79uDjqsG;QV^r2J2uqYVf&!< zmsD2f^P9Ki{3?%=T_SNQL`H2z7>J=Ho6%1KmWd5swxUGcNy}3I?g6}MU7d;Gk-0q( zsxRpGm&d;%KU`clT~ku((VR1Bjj-&TRGn@t%DJvx2Sd(<{gm^s$u>-@*wt%r4S4G| zCCWD?OPbTD;5c`LQ#%By5LrP=U-_~@dtll~6H+_YVb{F{@P}$tYVuyqgZ86|MLe%O zyh#IR5=%E{nt`iVtnAD#6Y~J!Q%NjNWA}VQd$yg(lSX;TdexBYt7S35b)&{NBQ=2M zskbv#V?39wRtVC+cVG6-lWei+aq%A|mn|a%L=p-?DA$TG?cs^ z>1KXS%Z_6*>ggpCWd3qHdkzUx2G~O{K?TGI)?-Xcl3WL+uOF=8QvT3;e3=n2tb;_y z+HlmSJmx7q!gO}rPI%}P^X0jhTwK@1%1h#=s>lB9^4D6Acf}8DW$mQI50bQ0xQ;Gg zvNccY!QLLqw*L(}W&o7wQu8%jVG$JmxN-MyRxRBS1%DIUoY@^?GuI{E_25jB*uNG0>V~4n!6doIBZI<0_I|a1IG6S?I

f> zuEl#I93Md{IKMw-Aw*bV6C}VG#BQI&jw?dRAsK&cYTR?TKFdSGOx)mbHiK^VcZ^J9 zD8gELF|1T@vqj+d&BmY#%d%*JOo!-fUt2h7%>Aqc{LPomYR{Zq*D#q(6EQBAtb*$g z(Vk1EyM|nC0R>4*2J&));VvmE24_hmr4OM9>z3qj?h9YV~UgFhNo+8IwrkYR~$_Jpf?XFZEtrUzLAzx_rnC8|d3 zX|NCexcsI=#QYk_UU*NB(n}AMxou4A8h9*3Ctk~RGGa`77li)!R6~kk--Hq-5(W${ z@-6@$b%Y~mo7S?IoTlVdeP)o$VFndz-^2&}5d#n#?Cos5#NnQdyWOR6veE@X<&3LU zGlOBkX!2<%!$nh9-DYMWsJp`hBAj`?Bni33ml)>H=ze+gEitwI5bj#Vgpql=nb&9S zO;|mwd%%6U*q>f;3vpN{v-rF^R6!drV3X3-{ZuOG*&aQ>r@`hE3xpugUzB-jMqSf* z0puN=Zc1Aw`jqdbLFKPnp8RGls#8O_*DDAE)KSV zNz|#%23ZVW@%pxY*F{sgu0Wv5p{LNFm)yM!*VV2gQ)4%u^Kc{-yotYP>VtOt1GAQq z`vrT~`5RM2sEm7}OqD5#`$Am6!c;XleC-depAbB%2u`GP7DA^rzGScd`_oSwg;-#t z5l|6Gd)Cz?O+d^lE$6&m{Qc|$m)Wb^heuVL0gP0I{deq?ZRXD&vGY z2pm9GrnkwlQFb8r^@dGXj!q?i$SrS$Kuj5kw~tH3?=^f#X& zEycARusvS38`xOFoAX5s{(F7+lNJ}3V7<&~c%ba2%rf4Op~~42*w&!xtcX%M_`pRR zIiAY0RH|vIJ4ddpJ^WX6%SFZNU*+AK|G(9B{^dU1^F@hrsh~>tqWH4q0o~O)jShBr z0K0n!W``J}nry<{SuBqi1MT>w;I5k_rJ7=Y^Z zJYp5D!!79MZYD+Ysq&dKy`#VG4GDXtQyIHPR2e^l09o5VwIiEPhCO^BH8x!BW1-I2 zL^`-!vdwia%sOYj0b~zk4I<#aBUEc2lxzH#hZTMDox}hu2e9MIW~;Db3Ikk#c zmHAzZPm1o3T;D7y79FROY3;9fm-e3{gF~@q4m)`$jrR&`+EbQH&90#O;1A6f)0XEF zc&x>{c*fvnP>nXCQ|54iawxBu^>DP(rqh?Pj>|)lvSf9Oa8~cwDZ>1^=v63k;y$*w z+tG3?dM9jidD%Q8Evt|@GUHAuEzYq0w5K(&ytE1nd6%OaHPpX4TAQn4O))C|B%gh) z6*=S7&Pu(9_Q=bHin$=52-WN8I$U&2615oWmXgVYs%ZUCdUNRap2boSV`|aLcSuxh z>2SCE8%=FW`c`DvBIno|8}g@?lz#BAEH>7X6qybb>ict;KbnX{wKgjT6&86I}`uRqO3nv?%8_|?Tfl`@3gG)%SEF?l}SSit>X({IUs6tOQr(- zJbvj)XG8`Rws3m*2S8M_9+a3C{?s z$LcPg(om;+M7rBagzrl`GaaNRDOSQe5u>YYQGh^ViRV$pyao5J*5U2!fEN48_6n=! z!VtHpD?PH=!(B!1&_7?5YsFH(|%)h+xKR)YAX#HcUwO zW;Y@`A4YmoFeh=e*`pKW(7y9RxXlqN2jEj3F`bW}40YTT9f#-`LBs*1I;zwR9o5yD zV^ktdOzc#jMHaXx4Jkrf3ghE1Vzl5SvrBinQZVt$Lus*tMX4L;zSZxS#S7M-6%GO< zK0cLgskf?hT3w0v4o>)a%fjs_qb!||M`>blt<#g^BK&wlEAcN_`9 z$?y20jp~@Sq_>yv!Nmx7NN~8X(8DCr5;(_+;um=Xs-DU_G1K?t&`Vrwi=yE8VVSsS zGUJ>VDkSVmEy(?!Qj4dg>()?TT6o2 zKg7#1YJ}S@9j6oI9aevbHjYYIlx*xej&i`*X-l z=p_kcGka-#0d%kEzKMOnNV-HB4IcKMg*ABb6$-s15&r=596hZ{6Qw$&9IyI!QzFiH!{3xmWLD~;_vFJ#;|vrNb=$%PmaWWg|eRC`VAcC z=_it9DWg%KuG^5pO~r0I6&lfeQs}D#f^I_6z#bRhOvJ+{@<9<=L2sXfo!j1bJ!stA z+s$w*e{Gs?*TC99??J@RxZkRMYoU!_PD!OQ=?;iL2O0vrwoEy3Gf1QgMOq=RWZI53 z&o(xD8{S2C zty+PBl1I=NGiXIWumW)nzk|zc7$vLj-v*TA=mfWGdf%@C3p2d^G3@T`6auC<5L^#= zo-}Xe*7P1a?L8?*7_v~Iv6yb%B^R`YbH(XBCvpQqP};?0Ye#i-0DnjFmBBIgWML`{ zwAiPpT>SJ7dmDTd(kFvfurWJpY#jZ2d}AX&gJ}8`Tlj+v*NQxImMpaw8TdV22v$mS zu~}yavJ4G8d$ebf95uB`2UW$&?vUyIy-3XFfvgw~u-RKSL$pNn%ska?S<2i4QKw_5 zbcA~B=IeL1o5LXcj#cgSlyZT7R8$$IURRDOHf$#6`7vrH1Jq-#efN#^;$?t{o{r#j zi_V=lVG6c73jUe_yd7EX)hC6>y)vmL9W%Z0s<1Xb^LiU8X_qj)sz2FVz&!;>FJbm} z$^M4bWdtmOn?*R7@^$LCM;4Gk8B*AKwD_8?YirT$QW3lw0kz=PFaN7c3S}v}#^{ zjvXx)(!Wh*s(0ZCEc0p;RwltGf_V{lCg{kvbUgjfNNv4PJDP6a&AbgN_M@hyptK#| zM;ZaN)t!)XCP|4;^UrxmtUNi;D==cOXfV=XrpvuKlmn=hM_X1c(%M5FE_fA`kd_Qo zdXMwIW%mpkA|{o8sFf8Lbimcpr}0*J>ZxrY89{5$lvYZBLLb+r$*C4h`rtK{?4Y2e^Exe+}OEp>gbxf1q%Xf1hY6h;NLnnG{1T| z^=MQE*s!rx8xizKzm~;^seqO_ZTT@S^04tkQ*LRr6rc) zMh(x}Rlt9i3wg~wqY&JOu#gq3f^|{9jSpppMN=niSSv;a(tPRHd&=`9XWc%yPy0x3 zzH8dQqv@>U?Y4E(!n=Z=;a8ny>oBqGk8qf&hQl5HWX9k}Ag=jMa3n(CMx4+dr&B!u zfF&mz za0)KT<5vS~&0?AT%31&LE41Iz;C6tehOYLHG+(pDYVML`X}%M4mnHcIV^W5TMr09a zYF+^N&)_TT$yc1FbAn~g%^(YeSxxBrmX_X<3eqb?Z}r~U+ikw=#`f5O)LiN~NNcPo z#%Ice($og{(Sa|iZ&D+fl%TZq7t>UdY|V6DFOO9C{KJ*rr>Gmx8ceqbE=^_2_ZE0= zA5@7ElWy>9Y)M}GCZ?;yEkWGNtxCU`Mf^y`Him3U1W;*t5E6Bd_j=RCMIC+VpxbZn zb--Y%LVRiacM!38frokc5PyI(-q<3j^Htm3hG9ECz7d@AdUI%nbCegXE!E+R!w-!K zFlKLF?fV>kM!q(_3wcUAdgh$(4NtM|?ev}+r}<;odNP2i$l0sb97hLe@U0z6$firh z$m-q+&*b-uMFZ|PDj({452|bU6<(j&Us~*cO@8?bX5so#VQXd58LJ^(duSW#{xD!P zCRwg0sD>p=Q)l^ansF3ZL70T@%sr7`eqOKtZQ=V+KtW{K7{11y4x5`>!Nhq>Eo9}~ z^>o?kPO2;(G!b0s0nD2|JHA)M9xG?hl;>b1>N=0f4&;xv z0LKFv3ckGob#1~A^JN?GD~Q0B@qU?mTJD3%Bhlx#z_1>8YQEWq1nJJ28F z=$GZrxbrTFzXeU~OI5Q3T2@|~=g{m)7_hM4 z2{$~%&oqAQu~~7@OuZ7v7&WPWtdqv$h%aP$*{-LuRf6s5*|T$1 z@e~=m&73h}D4EAXM=>`~czS7FS*eF1I3cHIw}3{cu#2Y0 z71u=P7%JG!J-3b&W??@dPD(A#?oq2KNJg5Zn{u+e%_49Zu!T}(wTGHb+XL072CZ`1 zEcyq}dl=tF{nvA%kulXf+!0?*mWw@jc~cWd-T*Q#rDrNI04dr6jd>s&vI??v#K8|S zWKuP=64l{aH}nUU4sp$dPBoug6TI`bqIyV=Nfe5~tfRH#r;!Q`_w`Bg+j++~iJ!Gk@8FXB)P4<&r zKW9PoxN`RS8k9o)tqyf>V|~4eTSM(@zM2{Oyfg3r8JT6uWs1jQhuF^G8UIS!)xW~Dz&QJZ4_CRjMw0`@TB!jz}XhKRia z!Agd~X$y>~`A6ZrunGbZW~7;li%BFtd-qOC$0vBEwEF_7ZEhzcDOjD3Cs+?GA~$Uv z+eG6B9G+LV)>WKv`U!(Js}bf|QNhMHsfyQJ6M6%=&kTemnMH#v>KbEMLc`L9mU=29Z~^;6qry70N=k%Dy!{-W5LPt;6ar z8uf!TY}U~o&dA#LEY8<#0nhPm2rjrbwkEx}U{9ME15f`s#)}ZMF&>uSl*5H@}ajydEckh4THJs z!{2)+qZHJzonVx$iUo7(BBne??COV@=v<>FdIW z8jlozCKpBu87F)yLWIOORwEp?Zdx=y}fbik`op74cqMo;r!(%Bc$zQ zXsL=X8Js?GX9grVdu-bo%KD>I85**038PFQ{90@x2ue?l(iW>9{lhh$|HnHv^23he zT^Gg}ym1<8CYJ0vstq2JVgF6ad_%KT=%wHmxp5486nnd66s}? z11=iB!iVAp*-LE4mvbW}H_Bh5UDC(ctxKly>*#+UJI}3ViY4jjuRD(nkQudENhM8+ z?p_}(1ZL;o)Rc{fx|~I6tBMNa|rwg-ZsuFVZZt#<7^ktmHg> zeD~?dRCZ}?*`&|NNoq+t}%A{5c51&j>V5F@8ZG<9>uBm6g zOFLD{*z6l>uU!9g10?ZG249<|Ar#mmeMGTx1h!hZIbc|!7jWb#474bIE7BgbQzw^c zCM52UX@;bmCbUC7nBR!=3Lxs=ZY|_Vg^2=qPBxn|^`nM8+k!9R{q6k8L{nQ=Hg>Hm z-Q-D+bFP3mMQ7(*<*GptLdm<$=aBFkTyW$hxE1}b!_IojR{Bsxc)t~VN*J&-3#(%x zo%#+JOX>;(hS^|l{h~oEsKP;aRA2SbZR*_EG}b9jHGG0@kjPs9{8i#gtKBqTcmcIq zy3oQ$9Eb2%wW+G()ZlRuL>K(M*6|mYA~CV=)JrG*?CbJnsA74=Hj|)Y|13&+M0}}P zXUONKE92F9*_Sc976gylQcE$>+wTOBb998Pkb1yo$D?lxiH3Sc3_`kV_qDEBg@`^vlrN0OwNDqo;F-nB6OT+t|$(F)u_e1LCv zGqc3_dc%So;>jKe-1lo6cLc&RfYb()ph0_I-_3rvDJf2_UV6O+rCLqa<^|hNo7rca zol*<;uB6q_U2;}ecba!oQ?o%*Hg;#*ie~47J3t6alGgmM5G$PmLuW;P&-j4LqWTKW zFg9#S2La%-^nvb%0#0X6R;^!FEzJNNQ5H`;y%f|p<3v;%srCpQhg})BD*pB3%~07u z--VPL3+rxqk?yNWH&9QNEk=JUHdv`QDw_%jCl6xXICt#dm3~|`cZ*ZF>VVxuPIYmn zjWDewV~@dvZim|NCq8fnE2ICK!?*h1k@I*qN7%cdwh2F1v?7FZ{P*v}mECF)@ z7u#!_avyVhVb5y98|GObg-VLAyoeKdQtR5UB_AoT=Vq{jupDq9d1$S_Fd&C;A_2qR zk9%|KcEY|7t}?d%;i5jQ!}WD#p8mCx1!>dx{v+z^lZ^!m9c&oke+SW6hCHHOFauFO z^)o6j6w^;uJ{!(voJT+4E@-qfpk}Bu|KVC1+|c}d3jcP(4O6x&ZJ1XY6m4K>8`t<6 z+*@CQgW={WeBUobyLF(lE|w{itCN!L0p+HlfEm-AX1AMB14Wm4pn7Kk^}{ptu-+qm zsyzzG^mh;wFInAd$&5I@_Tp}tZ~w&mWsL+fX~n1c{rJ82-hj02G6aMt)6ade@ zbmrja5f(j(*e!Jccm4awK-u zXbTeM%4VuMC@ObWffR)4jYtdMwveorGG?&_$mPiA&@b2j{G^|GkR3VwfGrNJ+8gap z9_XDR3&Qa>k4)0dBGNCK1@a#@sTVtpe}kLv4*|(YY4z7u#v@-ZyQj&Hx$_JuD@2nkZ}?%#pZA_g?+RUWi2Z z-WAX8yA-tW=Kc3<$9vBStzIb(O(kwUT8A02*^L{2u7CscNV+#d%UpfOAkR5t^^xel zGYeF_qNlfr0xp~Ukx(kg3>kaT&G3@8+*lUPokq_NqKbtWZtlOh;dw0XTJPX9fy=8E zkY2x&R|mt3ayq{TvP`}bf1%0%Jc3NOhcz3Hli!C~Rw3uN?b7GijSl*f3Sb5Nxv+<# zZHPGGa6zGP%BsDOu}tZ*hlL!$+jTzXmTX2-j|Nq-_2khRpXp0GHUfZqBV+#?d+#0B zRMxf&Gh-RWHY!D_BUM6^E`3y5LNkOA2mzE%=v|u3ptR5o)r2-uQ%Dd(D4|*C5Rj74 zVSs=XK>_KaU&eW!_j#W0yyrXT`<;JJ{z%!`Yp=cTd+oLFz1DSKmpLUa$0jv0H4qK$ zeh=*%i2v+xVc}$ZXfw>p*g;T-`IElIZZVi2>zdHy+;QV=-8t1u?SYJ{gl>-jSK|WD zil=gXgdy+8SBm~9rP$hdXY+Jql=N2O@Y!L3EU0}D)_$jW>=UW+jkU#es$EAr<+`10 z_>KC$4A0S_w)I?w5*_>~^>L58G~QzF^?9gxzurWxt7Wq&Y@4ln?ivcx<{Pdv419R7 z6i!!0j+(bupqgAlMvkSdMT~&H+9F+?1-%a9rY~pLr>1? z#@^mnwae8lyB{u@s(j6MW!7puto1F* z#>GP3dygp062ek9)OuIZ&~3?N;N5kJ!#mw)4|mBj&3n7OJ2PFB|xnU1?A{q3OL& z4(F=VxzaMgL`|^^zj(Opy=`cyoH1s^U+71gaomU9Lvdif5tG`p=iCGmj*&l?;*%qm zs!azQ3dq>`Xge=Ta#}MR8$wv5g?T-fs4%#~$M(Yb-;LVL@bP-v7DFR_?WwdgPT^g& zE^JqxXMuC}jloRi+W;?p@nEOQcXz13D=$`r!u%rzwsbrsdi|^1CrUF6=DjfwXqd=$(6>I7dTqy{mv`lI5bFgL;^~|07}0n)bMSnaP!8sf9gX znYyJ~K_vs2`o<%xbWph`s6&Mus==~7gV1*MPP=sPjtSv?=M^=ZFa$1-aQ{p2Q=_bOU|A37d#KSuWjRC@;O_po|@H^ z(0T_{kOZ{GqO(1BXsEcUuTlVyB`Er`PV6m|kL*3ESqH2B_0D@9Ky|ls$nB3~?khUA zb0M!ExrpL}pcXJi@dyNo9$@BlT4}J4{m5G;T1u*z?V4(jV7^%6BUB2%9uP4!wOUQ$ z;eD&jEUOL25it}XuUKHU8HDalF{&Rr<82)`t?xtC1`nBL4ac*)U$N)`$ow^ao-| z0Z3>wzEEC7YBJw3{)r;oww-@&oNzoWjR77j1P5G8@<=VVQ$P{P@S{kPH3wK zsDm$0V#Y(CkI!_xe>g!Yd4lXu=UO8z5fGZIOW`$QQe5^(D%Q+}iCH=T_>;eHp&Q%5(jC zvt4yc#iV<~H(X)EKn>hLAfzOI9Jxy$=UHdhrCPCaqjODpGWO=o(umJ4a;w2(IwveU z$7GC+{#Q@5Pj(7s^p^)n+|gWm(rd%qtzc`?P)gzjeR4k)4+?Zl*)v#H!|Gt;;G}C4 zAFV%zvxp6lmIJ|r!%O~G#!^o#{8OO~tY*0k|wFJEOzKOe7AUt{1GdBTSyE{~E&+cC~sj zgY8ve_-;dhzP^R>0C1~&m1Fup^z80mIQI{c5UY=~w`FE+jDIHR2MST-?+)SntfDh*{7Ny4FCf(4&|A)8X!$jy+zKe0m>DfT=4L}!4Vxz5ScWD9 z%!`mX)%L5Rj?PRG6>X#NQ!mVZ-h(E8PEl;haDn?+F+v0TlD(1xg%U`ADRt;j4E96F zY^9EqU3>oI62iy^TW>D%p;z43NzG}A)qo<&*ZW%0KsdTwB6Fzattn?&4zCNmcpNiwv_etsVYzWTB;$==s-M!v!Z8=zxZ5_}H;%0nG+zd88bE0jQI*q+QqRMXQK`Wvzw5jT~ys60o8 zpxuJe2`$@?m~%qcYYp98s$P;=j?O6qX-xw*jxUI*n2a{Ew?>)YPDeC`3m`zT|b2B^R5kJ;;~D+;@lz9n0td$V=PC~WIwBmq&IIu0SH_fYTa!9siATyM5Gzn&Ya9&B8;0< zZ(u`LbyZoIlz`e%4Bv~9)Tr08(%(4v-$h`*I>o?YU)BEDQ~A>0cJ>tS2^;@>8Uf~* ze9tr>Hekf-zO>>uj`Ytz$iZ$%bNp~J^Gk$Bd#LQdYvXC{N+_=fHP(TxSNjpJ;9ckahPbFbU;}};a8jU}z0XeNk)eMb<~NShDXZB<)zivc6fs33hEH`_ z*w2ryo?(NrfdXWp=lg{MAM8QW{d2`3wa*yqQSlfNXN>o?QI`%(S(wmo?DGG32?=uf zgsb-<8`QZWDVHAnbMt@yd7`gkG?6|aGc5Yn@fCwMDI+V zZf{vM-+N<`;w|X>d{;@?i;5b@McnG2@o!-2|`7jp$0`W;7?VqQsSvzYQ?#2x>(M7`~n&4ZqTmWg~0Dpfx2J8fd;R;`hab zvZ4dOJqVwuiCp`P7cb7UgThGeE#U4`9a)Nj*!FQ^*j35!gbLmJy<{|DLx$d0WcY@- zBw^9=th@>zYCWLqBDOQ_kV0o#$bFwCA8J@c(u6b8Fwo&wlUS?&mQl)Ap^viktV<@%5ycPC4 z$+#&ZE2lE0&!@WECTUalO}sL>*h)jDWgd3j-l=&)#(dsJl#G(P9Bzci=oWX0JyvcT z>OG%=vNMH71nAG-eNlqY4y<*Ybln?Xn{XyLr!w@RhQ#_&v2EV+EYSV%0^Zk?OM2Kx zOSKO54IZfM{CWvD)idaEwUld^t=#8W?3o&G>4ow%J1M1kq)6p!t(EYzY*p9lYlWg) zzORw4O=U~s&WXhsK6LW{$Q+f3{bIR&-TafwH;&$SRNcn{7d?KjqBGOZ+pf&N;?DAN zc2Cp{R*W7pUa&2-+lp&97H=`W2Urb(KpJIsU?ZM?rpQjn)H}w^+ITgu|CxC07|wJX(#W!wNp|0OjWPE^|ne! z&E*ipQ@hrSG`NhUxvj6wFVnt(#X(_3Dv%^)5l#zyQl))o&>Q5fw+!rr`NC0q4$tuY zcXLuVDoEZY0h)mlpcMTDSw5?Br2F9uaVO|{>}`gUCF_QN$Q6WS@RO?#HE!n0n2sBp zFzvvqvhc>o&rvs)wLl> z)klmZtfV4ZL#rGsxOj6NtaqL-`eMB${W^1 z@l~0z0w-Goo^kRXXA?NkWTp>_tU$2s&Ms2h&VQG$j-i1n`)JAy4=`9

&6HCT~*X zfFw~mc2HI5Uze1Q3Bkl{t}3YZj?x5P4A;9T$S0jD3h~6D;(umKmZYsRP zm9^+rDJQfgx5XwMJJnxoWOaD$vAFh>=D=ynI)r#x01aJk8{J`5y z={ddPZx$a^#+loie9-$3PFw3I|AXw{_ko{p?`(Pj%0r+5Sq0ThRfifK;I492ay@Gp z2o=U~E%OWbw**r8l8(_}k*g)D>O>N2QVHARSEEgC9{m6$qZJHp!uKi?4 zooNRxnbCcw*L%p;fFBprGOA*yEwggY`X!M8)>@7uktWwr4@fWX1(qbH_QS*D)X`C0 zI1_@scX{ro-jK4;dwMAvkQfwDJqT;6Qsrw-x=tD;G9_uS>ggzNuFpg2c!MQZvYtJH z{>3y&T9#+cu7yUuNkn2<>7;I~0lxpK{?_&#KM+b1E@v5fG7CO|0)?swv>I2l6k+3Q z>$^vS9W;#RT#09Ph&o}fQO8VF%Z!=S>)AhpTi)eD{JHvC-z%j!Z|m&WcK62~ybbm< zX>i^H6T!Tr=*BpFxzpywCPg)SJ*%ZD%KY|~;Y?xBt~u-~=XR{56z#Ti`d(%r-3usd zrzaK~X>9A|GOxjiDfo%#{JSl-6_%5>a*Jt+@V#9yAYQ9qTJT8Vm~69}!Ltf~`idJZ zqbNo=P()G#?G;Z;=YCr6X@^36N!h9pg8GfveoKdPFF(Ge&{ zvD#c0w^)dJn}b`f%(*bj4KML;;3uYIGwV}sEvD~S=+I9;OdTq-wib%Y&|okqiriO?7-n19#Jqca-!Y_fvOGLm&`1*O8Sz z%E&Ih^ZX6+tP>&RR$Oxet=D8Mi+k1}?CSQcZ(XE5P~S6uqxfUZR`AG3seoSV8IBDd#el$!j0p}7{N_|#7MS*z&h?Ku|DXBE zDQgim`;V6%8qO37PoTcaeB-$B)6V#Q_E-zB5XzbTpTEyvpr1Py_jai@^3L)ATHt8a ziv@;Dxdyx)79K(irWd81gGuPiJN&}QEyX+PZ~g6p>iLZ<>;bYn)XXejre$gD5Wr>i z-t7sM`I+))Nym+?QZee{64^oanS);~4;j}woxTn}Cn%y_!C-9*^rH~Li51oJ(jhV~ zr^HATokq)OXd)f+4sz`^$`9H@$WARw$(5wq+Fj{r?s*(u2aLBp5o+rnQL>1>DH=Xp z$>>(>sv*C>*(>QqYgA2`yKnlq;)p63p})~_E$63^0cZjmuv>k1Tor*Orb`WcisS8o zEF{%%JtsYbRtEzm#@>?~B!z4Q-|Fr4$}U{!Y`RZ3KPN!4E_W@#lwTpd7}#Jh%tWNE zdJ<)+JDJqVAY9Ee4O4r)h3<1BH9;lo&cj>1t!+KnOdQbDqf+ZAwd#p?PLdt<{Cc7NXUAM8Pmkp_DeI5BmTgsy4aPrs%pBj~xBZ3VruBaXy8nk?CPJP9q6Y`e* zJg2?w(}HpxA_#R%t4YF~vnj~PP81D>!j$#wg8(m&^ivkyW~;)o>5z<=fyJ75DqOxc zMSUETP$^3@S+#*y8X#B8yyqo8XO$SLahW=mx1k?S_l$&(7}0}rbXAQE;RN|>NhZwP zn%#rBI*n{QEKM9q<+g3xa8dP-;(DYh#IPst!lu`==w4o4mTO95_zq&a2+MBv!p#Ah z!lGGXOeZ{g2uxs>j@h`X&Wi( z#2~b0QXW-My;Iz09_O1Agc^=rU8fX7LnvSw;0!L#TYbn9`moJg=8DNW%-?_!uod-V zQGY%&)NU+?(U)1BU#D}VOB7PJjaRU1;RFy{#Jz)0;D;?RA`HgTf=Cc0gh;is#;19F z0Cy3I=bsTNhqs@tUh_zE<*%!vTXj8C;pR;e@0z<7(_9|`9Z5O?+lj8nj9hs^_}j)r_N`(ql@lVm>27ojN5)V)atB{ zDVp=FhrSNV7mFQvreRWzloSHCcX=er+^+V~(J7e(pmgU)!y7y)j-I6k&o``Wklfyz z;A$(w9MLQoTQD&OV)~8a79pA_JReBsZP^SQIv!dNc#(a^rP#^(y#dLDnj^Nbovz`_ z#_f+n9AgGT3(Ap`V(n0PNpAN*vPM?LqKOB9q{v;vT9)h2i_@ynS z;muMR@rtaS#b@v>3AB^~qQAVHIxQu56`}@((3Bml+>suEybibM+JLc}f-sr%DsqoX zxG40|0Vg9PrOLaT=c#Xm7c&TGhv(1l!{h;^v*p>qlFVJ1yOS!i0%@@iBf}?p7>k;x z2-QWEm#WL~Bvh!9nrMdDy{+k>Y`ZTFvYk)O@{z)wuAcckHU~T4M?JuYggM!P)+LX# zQsB1QnjrcWgul1_FU`Xa@_1YBAB#l9!aQA{`mhC0KDe(vRpt$~osTKf^ENIv6h-sO zB9esSed|NYrfq#Gkf~pAu?Aw@+PxtDpHv?6Gl`TMqi2^20>=s|a#7|MA@stD#ociR9|hc{XEuM}45s z5O_+?vc5wV($;D8Oy>G#U;w{{1a%ZPLw=M#cMiW$ffg%IVH4l-HH$f@M|93Au>rSk z{@EFih9O}rS;Se^#u-XmfJ3(aH!$&R+eHoU>GRh!sYIMXtHSmvb99Z;W z?!Mr)Wg^MX-l(IXj5hn6<2v8}YB*G|{GzvmG5L$T=fQQzv)8uJ3*5?C-0}wceA0P~ z+alM8pKU6G2l$J#5_Z)Utq86ty-J_dYG@^@U}Dza~L@9TfbH=0q5{CWpS_37%5Sn zeHKegS2d7+d?jG9@Oh2wlj2J0V;^bAEQ~>UKXG>^I?Q}cIc0L-qtvl0`s8mMr=Fbu z0@QXr+`_+zdn{H!i3+nk5&LzhP||}<(l>?p#4YXeHsshFsvp|~!ekEoQ&}P*Sv^4@*vmrS=;a}H?3-Ny{>ZTA?OS?&orfptzYtUdMa84%*X0o zRu3kOrulO1SUxHM@r8ScT2+1a?Orb1K*=$JvKaN@i=wPxncUlA;Y;tSTB|LAXNYzD z?>))Q#~oWCu#X2kA50$->L=cp*FvjNWd;PX2@I>mmFpG#<=Co}?fr3S0NBc7Yk$D9 z*ShgXyp2jzPJZP}+=ED=`hdx*f>HodfSs==Ls^i~oV*zJVSb3XhODIGJU$xt$!sLSbrcRy!kGQkC#{q$WQ^oowSzt)6s27L3ud@(J_{YbFwePAD zGcJ?NoJ~?*{qRTa7&OrOuR~snh|NQo&a>uOY8x*nOP1QNP0;GxirrdWaj!W3SK5as7V?;1+(g1h4r<&?o8K!9 zxm-MQLa6&>7Zve^VUMGdQ49oSNqLj!+{>~2yKEhqP@jf$9^{B-BCIfZDJx9kL$#e7 z)iC2`KiAZ%id5MUxTTEQNb0nnP%4|*9_*<4`cv`Su`nNHl|8{m@sz9fFM9Gk*EAMM zQ12Q75nExpaFjHRmjZTxnCdmn7qbAjNCsu%5=`U-iMf{xNND;arUM3C=Xr`RWlYFa zxV9F#;IDR?6&7eYs1I!+L zA9YTAX9o&q$JqBz{r^$Ao^sr6_e%VTz>Z@Htp=_mk0xF*Rd^aOMIx6cem!XU#!(T^ zYY)|y1F=@a9W!!~%n`qU>_Y9!?RRAQ_ueM`WdCq;Z1j@mf>lRL&FvfVo^SWgCFNF^ zhbv5_S#1iH9GufHt5mOPyre2XDKVW(hD4R$>kM5JTst=khQJi6yRV{gi9HPhNoPE+ z9LM@GWa9+nsNiA4Do|{=M0H>;w1&c#dqG}X(k6D{oNM2i`r(ZJFjLvyzPx)nxmYq~ zE_^5as+{eR;2(dI3*f!332WX=5OB?BXL({ZzM($_GG9avi|!ue<(qpSi5wec#-Fb& zg@a-f2Rs?-(6WZ|F%9MPH`BF#fCD$9q(|v3Gm;S|-tiL{anGwG@iPL}8rv67|1^Cp zyrcW0&QxWC;C4LE#irNa8~)lcWvh#+#|WHmOUNVm%4V|?3+4*t308>MqRyFIJ6!c5 zNd#WhWH$cS?hoeLpH$wOlPS&L_QG6c+M^_|&pCwyDOLnsEo$UJ#_s8q!@}Q%y;p=w zALYOQS1oV$xXl<h$bG5Alw!6kk8($SzxuZA(>)KvfIztx}!F%_7U zY}@S~v|P|K<$Bg?WhE`xSDN#S`@pvDkCoXqv1IACk6O211}|Ow-oC4*rYa`b%uOA` zZ51VmtFeBEgfy!tzrsuf>U#s$1qXx#MlEOcYM4;Kc75wj|0;MIpU(QD^}mdB2%f#| z|6r|8;IBOdB(k%^%U6f*9@zDb^o?PM{o+*8;p)%Z76a-MId$$1LMXYdT%g5#3DBx^ zLw@7GHP{1Rjz>F{CvIu$PK?k^NvsAo!RZO`pO>E1SU0M-eEzEtyr>Z~`ERw!@o8X6 zt&3s|yYfhS3-^?nxld(ay@pEH@(84Pc0tPzOGobzl#=HA>?Tb8s|mdKK&!O+KRvOd z+7k_p=<_+6k<8Vcdm8>loAQ`h(506(Ue^AayWyvLHSQ&)qpCIIFUkmpJ^AZw-~OJi z>S;0x6za-jvdQIOni&b0t&1tAP!=JFt0G#|5+Dvo%&+`c!(NxU_8TfGBXVTkeKMau z7X0cqw|sArwld!S@4f2PYu(V#(Ia2Z90jznLi_*n&`*EW8P8Kak-Z{UWcl`|VG)*F z+wI2@fI4rP0MQ0+l;Z)v9%R>t9m&`kR4sY~?gxUc9BljB|J5u0tg3Qmix~S8Sa7>1 zuBj)}k%!j#+2Ls+AV7d>B4})h@wJXKl2i)qxop0cIP&OUeiSN_P5zi>BS>g)%|kh< zIBXsZzE3<3x!z(+&d>V~kDtG~7j1ZK{wl3bdc!dCdw2Jne?9u#zmYp-)TNtx|1Mj1 zUCyRJe%Gdgah7XKVYMY>>)LTjk@}I=_fsck)s$cIh_zj-`0(XlE;@aoiB1l1fuH%0 zX9vG=Kt3sa@5MD8^U#YE^b#ba;4WjKC%971oW40#v|ZkJyB~Pc1g3 zjJ9}EB!)72*Zf0!HSU7U0DT`lQv9~Vq@Bzygkk)1JBwt;KZ{-niY1P5le=3ka{kL)xjmM;AbmQh zfme@EdA4rn)lj*#hb1XhD#~AT!pTc3soj<@>a{;v$R7UJ&En+g*6$bN`If)N{&j^~ zAv4g}@P>|@@>@bvFuHQe&!W@i&6eH6QB*A^wO89vGr7M~#Jwh4ie9=iVqYlZp(1px zU2TUM{PepCM9nQub&N$pQmIL6_u>)Dg?Fr$#RJso+b>W6k5b2$n|Vv+fT92%#FJu` zq^orga%5H%vU#}!8zofU()X!V<@g^LymXqVRqR%sIT!V}jiq)Mqq;U=GIkG$FR&-; z6=>_01EMi=CJ#ejDIu2Ece!c9BT$_XI*Hgu?DG1N_e*$;H(qNiy!o7tUByCdyJyR+ zMKs5hBe8YL|Kcw>egkT6QnMi1W-`@%d4t^Z)6TUp!=NlQP#lr2B9KRd&RZm$Gkm7} zh^XHPpVh^{db1`xN^{K{#X`gLf}K$L8!`B_a0&O3`Mw3~V$gHcu{qd1?NUoR_Jx%s zR1C99jh;sHc}?Pl?QFQUkO>EZ1XLM&Z8Xh&Vo}m(;O^$)>e|hA#Ok%v+YjE>BT%k4u2+v4PI|iGncqL8+&YF;@xf+L4yT}7Eol8eGoho*?UwID z&-XjT?Q6pS{fK(v#KzaO!@}SG-y`k+-TwC-=YQW0=WF)M2K~a@fmY*UdQ3|*XI)($ z#EGMMhh^PQ3Pb7_V*wV}44UeTUT%VAGM`QUL;vPj0*=~8znzx%JzC)N&5mY5UK7~e z;P0_s2k}?1_4k!Lt)p0Fsw5IeMeUJ^;Hz0?9KK`GQSZKS*t8~IWpQ3kdQ|xPtwq{U zx|JcK>G4)B(<3)0dPXUnuEa9Oad4bFeSJSYoW8RNx%ZC;S=>+Oj!SjShIi{*>j@78 zG^3jAeJUxA*GXQUm|W|=?RnYgn)2?6$D_P^KactJCX@UJLaL@@Eo->lJBfsSbW;L` zuo;kl-@|>YWrx)tCJERCPkosW{&FH-p6M}j)GvZv?o<ErquvO>w z9g)pE#UYPj;&qU**p6S-`hAwHE~s1_ltCwj$%gjq>Y6?$5FV72rx%gk|BO*)My9jz z&*d6~%^L@)Yo!P~KSu@W`C=aewHwH(W~&n%QeCtS0C4pj(sGm63l<48IE-0MwQZ1E-P8un?d596u`ZK$gaJh=>3A3>1YoE zx=1kZ%K zfdmI!)byhKy3WpO2#5bS4!P`>_WJ#WFP%BY4vtfi{$HK)EspPPe3Xjz*sFxR{O`_0 zU^Qn|I5f=o$h|FC%Z!+=5& zU`6_zh#aT_t+ccVpc%c{djwcFPyfcjo-J7eUt^dI34B>;v#XlnYn=AAYRpO{bB3do z14MeJoe^JSbd1fOxiBW|yv-SiVK|0YTiX@Rimv%+`%zZ-+)H-ICc?OQRLCsq&dX{lG@sSx}|t zRB}8NCjMT-Tfq2~n1Xtsl>#4e^&V1c!G|s_8&#g$6D;!i(VdaxMU?3r1B)31v6J*l18e2Wxu=~%lX&gY!w zd7~Su?Mf|~LR<;QWC4O!mtUHdIL=Q}ns<@CxFY5-$&^4A3$GINLjub4mF^BCz04{b zMtXOk(r*$Md}^ohpR!E9o?vW*6;EGYIxNY*-PF|-o5MA}*f=2wygJcIWGBi+KOAhP z&<=#CKF}DVDFi>**j(pQ!P=89eUo!}NLCriDo7!vBlaiQV2X@A+U<(^i{ZJ_L-3Ue z)FIi>sNtYju<=ayg(3A-2Z3j$a<6T3gd&&H9}v2)`~6XXPpvV{?ol4F!>{dR?n1fz zCf!298;yH2gFJf90>$~&zFLJhsv&P~TFX&}-hxe^xZ7Bg3`-%-`=AdkY86?wrlxN% z&#ih6kw;yRYdkwpCDVdwg7+6s$lpE|GN6h~ z=#s1%%G-H8s&;zBz7-%g*?GZ&VrIIO-@I-Y8#nA#QZpp3(sKG9r(8J6OosmI;=)3? zx|x|ps29f%Y$V!WuS=;cWkSj*8xQ#_7cFgvuX7h!`8u}0cu{8_^PkIwzP8ilZ}*fq zzia0}YkuF3Vn6p>lxre{r2G;&8$Eh2sS;3l?;D38143DP6xmD`ETdPtwQwCd>!;b# z#~8S}Naiix2WcoHd+nierzU{tx-Rdb(Oi@3E~wrM${ zBFNvg9G`MS5#t)CXHaTUMO&T`Gn3O1UEfTSyHcy2l9QmXK#??%Ow&~vJS~_t z*$AZWG?g1IMojJb6LVCwehZJsRB&)e+=}mqUs}BpjgP-7&KLmY_=trdr;8#Tz`wo` zR(IFMJw5K34!1q*7J%AbC<|MnHMoZHd07(2YiOD<`?rIG{FW}xJ0yc0nP^SywcNRc+VwK@1DoL8gc%viqEvDJtsG373f3lde{>5Guyi97nr$ySnYJOl4l zL!K%pETva4Mq& z0Xzbk73BKVoG#;Q3N_QY$6a|5CcEtmJGZj3fJVIU!bsTUF`APJBf+wG+fFcv+e$;@ ze)FcTctu)A(9eSiw8tP{H^h#wz_G=A0noL&0k2XQ=*j>K*S&2n$*>1 zUwL1gD9mjNSqPxgV|!5XL^*LXzR|}x`6Ipz4Hf9Dy!_tKBq)p9)Ct;ejYvp{d^xw; zwQ*ENQ-eS{7NJ3j=|aIS#uJR)?B=YxT|vvJO11dv)~2s;I{#Mh!{!ENcRpt`ZM-f? z%t7Hni^B%`VXxO9vu9i^1-hZXV9}5eQkUC1d5^!`N)09<5mpq|y|!L3C&6E9&;!gD z6}1cmH$5G(oUPieZJC_(FF_oW9NZ$@a6^MTdj0jIeU$;dRZ!;kl8LpPnsjVO*}2Sg zW4(kALuPvO^EW<+)|A$d66&O`bCS)>)gMr2u6(72^o%%(2at=4kxFQtCl?f=t%|{> zHg1h1-gmQiZf7(yClVPryiZgQ=iV)MfgD}tN0q8PGi(QMIJT+sPh z4=UAAUS7eoDthImOW@)@8Lc=l63z$Bd}yIDY_+bg9C73UNv{s29Zp$PFLc!p6Kwn% z8FW1&ri=8RVfjmiva}zqQ^?^5yH7co3w;g2O(x|&y-5S;@L2|)&sK#35FSn@ zYGdSdUvFls_Bsc@t|l~JRdGe+xn7guHinsV-wW}^Tn0amm9ZAmp7p3K3;1FsVaKAM zOm29!wD?s;p2wqaIJFF8ky$D@Ks!uDh06ejlc}nW)5n}dKY}kwPYz>|ddjq9Jm5yY zAHA9&Wx?=|(%UR*uqO2;WTyr--nYYhOeI1kjF{!p&3g9NYpf<$2@+(dl_CTAH{s5y zhnz>@sj@vG$Z_ApRh1wQy!aVA)gvXwb|3D;G`F$!=k6{R{aoDb<5|NU+x;7-RK)dr z)}@ypMAAp~_s?RG9U+7j@6VGOHg-7Xn)8gAXc5)=2x*;fe3L7S?4| ztN>R$7Q$&XT0$w<&;aWXXMUwPTpTZM7}52XE-pjL`66ALJK874oy*F@hY%&%K`bW> zI_bRSG`=Ko{g%v(i>axz478ROzNT;I-IEHpO}bt{X*q{zICzF-xR}*}>;$T@#*TTb<$83J1l`lONARJ*<#sQ#iz&)FHXUSVtq1c>dvHjDvGOE!|I>Mhf?-Z z)JE_2mI!a(KW3?HN97v6mVPg=ab^Q?O1 z#2!_5y!h+L?bT@3@SHq)m@Nb&6bb9A;L*G&lvDlPuHz?InY7DgRZuDJMv&x<|jq%L&CI%bxSS=AS z&J9x56zd!KGB`2wV|iI)Y5L9)otaFWmwDIx!h_ zZ&ivhLF@Oayp9i~sIuX*R_Vm-7ucSuhTFYl@oX~UT6?9@r0VE=Rl-!uJYepg_P}}D zD{*Qj%f;QxZ3A*DiZ4pd&m$HOuu&b1AY|w=$-kMl|8s!#^C>m%0VHhzZG+EI*gh5c zXZ&hC#eP}X=T*(S9u{mJ3RSOv7WbNmHflGA^HwHaBz)1TPvJqYD~G3N)|EWexOk;3 zonAo~ut>388(hnP$&5ayJ%sZcdu50PZv<$jtPwY1BE)3xtg5LJ%;zChnHI(J%dNkE ziHJ2svUPsmz7v;V#*D|)9(3@G7`MgOa?eUHn5gMqrXbvOT zgy-^3A=FsL1d7O_ca6QRz5X#n=e7_NNwv#udD3z<7VxN4v$XDOnofy}1`5FA>vsHX zr2`jB%eio0UtgdO^?s;Z0>mt412CSEm_r(=4I>`|q@Opq#v9>cvI#M0Y406q&)8(f z$|yS|x>smQo`3N>YY+Zao!`AiUR|n!c?|m?Z5@AMa=msR;ITHVI9nd$PbM`*? z?fJcPPhP|s6cwYD7913aN#(f5tl!<2%1V+@56>F12TQmH!biyMHFM1EwQRB z<(g40FNQe*Iw0AaS(%*|b@WEpBFm{<&wDV*6^;beq#t&1T+GP)pN<57|M7#%E8Q0H zuTQ>l{8(e-cj;qdG#hj9YH>Jv^Zlz8_QZ#f7U;t)8wgiX{?z2)QeY(IYjxp+tam2k z*Rv@wWxCS6a#uqornOfs&j)_HppXvs;&LP#O&FWS#kf`w>;A$EtZGG7iJtE4F=@8} zCgQFXyy!g@2oVdZC2~jUo#N)Ixt5-KeGqKn%4!HGi!9GStKM*A=pnW>?u(gOxYnUF zpghqy88vNa(fD=q-{xEX9H{vzu{8C}Zbnzv0*kG-jGrkh-2gPKbNk!68hHxyl~~9h z!Pw_dNt*TB6+;0_8z4}Ie;wSa+0{@Em^0KgRp3<6>}G7~6M;Z?TQ=Nj^{}}+DOC4X zW#{F3(8Qg$R#rw?p*+n;ruxq3Z3L1&7lqX~fas&9w~C7367o$3o)2jCt7&~f2tfr6KgY?ud0ur`r6mo$#h;+qSwJ+rf3; zICxo)b2x-H_s9M>p4RQ#ueFTEm6fBG4z2(PtyHV9Jq!ZgKBN69(|#%@wTT`} z;{#XJ2Sxnl-1MoBKa_mUh&};=WMm|H1g$r098ZnDv|G0*lRwi%Ve%(d~3JX&QPSJjyiV&t|?D{QGLGV za%x(UMNo4KT1&yFr)T}+L{tA0fn;<;$8LlAV4yZP!0Jwn%rK1*^@xpqd4sGJem8Z{ z)$4;6$B|?BCNH>fYxSmEf>;dmk_dN)b78UFROEa?YSkU@ZilK?>3j~Z+$HVQ*?=j_ z+JiNh@pZ6BfPc-fomeq$QdYa5%p-T}9krXpTR|N1kS%$O{@mRTyeG+QHhanm?Gzre zu$5Y!G!-MV1)@^OCWBKQnc@2B8e{Vf*2J40h2J>Z*cIRHZ{m76t8me1Sfc8t??kO< zb&JcyTtL|$F+hTtp669HmkwMUoU@*Yo5zc`k^i2{;*Ch^;1!Gfr?&W#&TbYCs9qV*kcRPoQb#^=!k_d_Bixb)G`yw)1*w z181XV^xL?kAM4_<3m3HCUSi(Y7x_{{_928`xt7bP?~cj*9278xoJv?v1|+bM2m9T- zpK7HsEuf(+edCM1+Q{j>xNZv9q=_A#naCGy33nUt ztzs}bM%4++Q+YOW`t}*7(o?Nt6E2_r+_V}X@2V00L+Cfv*QKd5qLW7>VZk~tlVP+! z)j)(v_)84|bRZj=L^n=f;?lqkNEU#4L&ddlUEfx?>`~Nmo+mk85Drfs{c<)E5YlAZ zdFS-w{K7@PM7ln{ihdcZ{oe}ZDVbnN+a0U#!rHBhFKC*fJf1i zORL$;k*;d9?vn5W2K&*et+F81)6UC6EZ_@F8ulkEg#LHwk@8qxWt6f5A*NCe@a*k} z^~o=sk!d&0g=+@lxBSldHTMt}WM#DgWM4k%`V4u68?3|QWzo(2c2Ot0ie#j`#*O8Y zRu=a+4uJkbS7u<__*<<)hvt)y75=ebANNr-aH^%zI4ZIDquURaZ}x~1r6%ZAbz&}} zoqqpKUG5cYiK(OZk3&ap=V<=yL6V)bk7jElv`}PBT!KeA=I7 zqd#pKZCC#OOkE^YO3OQ+A}K^u2^6!~OMraiKoK{-aTK@yd)YHNa&I2*h<&X;vn8`Y zAReyk-tJj@N|n}1)GQm&4n{8dmahFQA|h^T5BwZGIQ#Doi9s};^(-kI{ShW=s!6C^ ztNHS2V)89A^e)gMUC%7lW3`}D0))ydUzYve(kFp;mYqKRaTHR}>e$lw zBg=yXbr|({C9@A-2~8O&eUeB_U)#K*V_rEEqkDbIhF{d=c}Lv{Mktw$q4l($xZ}kj&%r`^C|nPIhZ11Ap7; zTxSl1f(NSmiXc+F@FN~Ry0-^4=JWx*pp15QdH@}nelDVo6C-PCZ(n(+xx4h_UFY1L zhCe1rywdTGNz3gyw+9{%=855#?ppD4@5x z_WGY*(D~4h3468SkJK8&#|}5tZ-7BCE0Ro^U*|#{h;7|PDLUV5=^nXP6Hq3+++H2i zJgZ`NH-eCEYb*U>;JooU5|S0s0KI_ghz7@I$XcMkGCVf(Qi-)Mo!=Y1cd*xG1w+Q? zl!7QdXo>)pkRGbx`T?pho);oZ$e`etiw=#yOML7@5a+R|GbKzW30083A{P=R!gk38 zwXCiLYV*WukKBzE3Q?2zTpx95|-S!;x97y^kW z+LuB3hFlK%B9WOt;(Li2dbQO=u;+gI5sm0;Xh9A@)AOLP4S$y7A0MmHR$ltyvha<# z>x6Hwp{uohAk9I`00mee;wjk(I2;OSyVI7JNM|ZWWaoYF@^=jqQU8fBIr5plY7ToJ zKKAL0ad!ofL+>;MYw^r`j*3V_if;fDSC?@`i5cC9>>U3;DW3?NfA6;=8V&Oxm2Z<7 z4F?~xiH?KLNo(SRi%GSnEk#fvgW`E_$O+^3&*u9`>tkz_+y+6R8Xa$&`2nB z#^zB$R|jZO=u^=l{Lf-`*^fC1Q-5pxD!k{-aX$s2db*yCI|chee+s-)`R5NibowiU zO~NPbVfBTNVJ>6jE01i>#r;<;s%?gsw0!2f`;{U4;X#4dKoDKeD@tm=Onq0d`gnum@HqV8-lc=jd>H?44Pn2x8kX|sukBK; z&C2GNvw!#R-2b5bNXiy*SoJrlXmvW;)0O_tBcgJd2t`rerIEUrGsgaH*12&1HVX~E zI84aSEVPrdYBB*{L)4G&0TcMA3PkOO+|m=eYQBGQev$brH?wAZHI%lN$;Q1Z-!A_d zKJnXodd4C>B08C5t&u3Jm>{KB^Ooy+HTgJp=<4-(d;pJDP)F@%U6LAZHE4d;w1g{5 z)T#Q8Qa63PLdW#+)ESi%I?#@9zFti5%Ph9pV6L>w;>eySWFJ?po-<1N zP|TuH8;=AFG_s{oR_1dfKB?h(Dig6_g@tatxmvNeASy9v_V%o~e%|urO4Px$UQp4M zg?ce)wigf2v_s&ir{7LY74WkW=EuIONN z*_kfAVf&~tx_pFW#tN$7VpbsQS2s@uTF>WeXs0rN$#C8aXXmqRcT;x>CyAUQ(p6(~ zECH2oDw5U(X5^^?2tje9jf6(JzOS_KH07)rSPym!<<%IOD{P!OK7Zz$g1SXja_Ie% zv3PGeFyz_M<+e%McnNV~fxQJR3AQhchT%)zK@ppovMcU&)V@BIOR68d3!qU*u%~$RoM|H?itCEPtsGaL30D3z9x!ZN!X>n zbTb!Q@~D0ZeuN7$yPpm&BiE-jE_2@}W%Aw`p*w-v=Zl=nKE@OSlXrb(uy<{-R8YW{ z3hMGQj|lAr52jvhmAjXAEdOjB_SQ1H+r32CIp@8!pv!JHUmXS z;Wu+meb?mbbi^M3r5J=if&9a=>6_a%I(IIM)bKHSEOxo8tH%cP-zn*wf(hwe`b2of z=D*SBk+|;Mab#X7H0bS5DlCesYX;9>d}V00%)}aPBz!XdrjdRAI%6n5(mQwP*P~sU zBI2b)G>H3d+tRo2S}m`YdHQTjBW*zjsI!8l!3o39{ypdnp#C7uH#fi+AjdO9JP!r=M9UJ`=?csIBBR+Z9m1C2OD<;KqWy?2%;wMOvd8$9>vh zg40IopQW?^8Pdg3$9p_l6|RXBY8$}mc3G+5KAv21(*DZuVrd6o2+>1y%@^+yN8HB3 zyb?*#PMYFYJjBnPK?sVfbFFiTx)o$(t;);~rhLxgHMMouwO1e!dgIu^aVck2+`4*a zlR7$90;9M%PFo(+O0K^<2nR3zPP7$N0 z>Kb2)Jg>+ne8I<~%rvvJBNmH}W{!5)wA#`-Hj=SAm-OXNtve6SnttGorv~F2gr+C; zEuNQU+UY$@JWMN2o68ms6!8qY?<@GSG9xG~jrXi}N+Qsg8?oXN(rt2SaP0KE?Dr`p zzD~2(e~D0kDrvpk)4DRxGLevWw15qFx4u#^`#h}jqcH0i9&#{2{puS7v128~zG>L) z7sf$+Av+#x9q$K@QU7&A-oI?z-pGnOp#%hFqi!CKK6nBC>_uHKK7RVcwSrG`gmLqO zi}zF)L$`Yys-!Q0w{+Cu_gT(`U$m&BW*?3A`q{cWSiq%Wr%sn~J)I zD`09nwO(-qdlwxG@ygdwPm++M@~v5VcE^sQ%3My|)ew}K};-*K-@24O1eUCrs=?LY@)Z~#PkdmMp2a&Df_RBT=ae^c(*>b`3JFJE798C za^U&<*QjyNinq#;rc3O2dIF|pbcSWLQEPK+i_Bs))d0;}H0Zo>aS)>HQp8JIx6CTE zaL*0pmN$tA<;ssQbm1^{%SZ37n7Xoul%e*-mvndK^7`W~>LBz}ml{btUw1f0&TVlBu(g2VzHXf*NSXH4p+%G2 zLu_saxn;$rvJqX)A>zJlBL@k|l?Z?f!ahX@=or(gHXvvD=s$bGFatmO&^#WLR-orKZ#cHV-#@V0{!>ds|x2mMvr~phJnh43Pq?1|KxV2r$AE9l`%z+W| zuT*FwA>ER4$up+OMMdo}G6_Y_+>?`RIZm$6MPq{wb;R7`F!-Oxt1}xHa>arZ;}WA= z^4+Y3#I_el8M{D&Jy^d!ZSjmE{(OYc<)Y~bGEX(H8!sr6YpvLHAc;zQ#-k}G!!DKQ z%dFH{sbs1>_X#GyEu9gQUt{`V>fl~(TNKE$R87;8%mj-A8R1;ZK8%Vo(@8DtMbjMG z>*k9;oA#^L?U;ZUjP{G8$G$R*cRMZ`N@N~Or-#dZC}^*~VS*E_`k6MyHa>~0i-$!Q zgWxW?nXjWs)$Wiudu_#yHr-VvdHL5<-IQf*{@!v^?M?oZW%DAR(5FR-ZEON%Uh|YX zNMs)yw|&T+{L4kvT8$do?@lZm<}Q3v=2dZ{W)0L`Y~6~Jl%>hKjmwXM;%j_y(=O8% z&k&w*vTx1MIw8dq z!!icy-@4(ddWk@Zpyzl3ISf4~kJU5d4x$}2fRoVlZC4i}bGrMmcZb8iLS;t!5BV0_ z?v~ky8MP8BLfY-2O+RLh8+!Bs3%ts~Za;x1cSr`(yL@8%SK>4yGl5^!6++e!?e&SK zdA*h zyznWHT7~#w(xIEFr=xSK<58GQ8+=A>q0@)yg0sBM8N_4O^gdQkm9yi}Ra?r{If&+V z&eA}#KzrPP;Z90{Q|Mt@d~CG>d@`*d_w!ofR3Y3U#YN1^AjNdK<~80cR^CWq!F1CYAxH-0Y{5?+qll(C+NXq46n9!9vM8jEu zG}~bpTwn72QBY0JK$=qV^mI?`)6XW5$yZdB6eR};(#smy5u4g(p=wqHu60l9Q4t^6 zl$f27kPQxzm~373Uxm7r>FTw&)S2Se;#Dz7M?$OSbREC>{efOhGc>r3--)2l+)mt` zYxNoi2-iXSJ{ZJXRC55CI8r}u(!G#BC23y3rL)_*jp7d*GmG$FZq%RiPL$Hi!S?$C zCd{BTV=J2eBeAv2U1XI5bz7QKo15mTrxHBqJTU=`&s9yYNsWEb&lWi(#gSE}$H@yp z$%#RuiZeoHt>B`$eH~SG7HEAIg*Yc|;5NIPG~hmcD;B#{;c#n7uY1&c zWYEW?q2hjuUsV+O!K|AaQ=~TkvW#3?QCgdPOJ0mavmm+YrzT>&qZ_bjEY8o!U~577 zOM;iBj8TT3NyX@Con%0wR&-el1`E!Q97_X;Cr^@N+}B5F6BlL;TQuBU6I!45;(C4_ zUx1XF<8Vb0M3}B5e-q~9Ty0*Zc%NY^BdjvMQh6lb+qW$Lp}ofLEL`+zw6e45_2DK{ zMIaJ%qvd+T-IXq(J^ilydPR+ABws*tJnUdg6O2l(uoBlzBKmUMXH;%hwbEofAHPqR zx~|U#vJKKKd>M^b;CDi6=yUChU5c(qwSVu=np+%S?SihJJalH)Fs{4ArPdrGP*jpr zNUk0+*LjB0SS_E~W#TBl8dPN?R7*o*QKvP%3kT)BvuY{)Me;j_SGXWWOXBA$^*Q`? zMP>zrKhnDPISj<33QK_k1v%0A3L*ew=F;Hg+$Gd|M0EV5Iqy#@h?F8qd#s`R)>~|? zjI z4G1u&MYgQfiNa*;9pGwJohbU6@~~fK6K2%1()#4;&evJ?8X~f^bkY?YS2Op;-n>H3 z?>gk*aaH#$(#KWu!ibhZ6e)LWDPYgD9g6tPf;=s6d`aYpEof+P-(6Zb8Eg!49|Hd3)5v$C|5etR!>MY!eFExUP6L|XE<0P&ijwTMy|>#{mrLg+B!QL4JlKnSK?pT1P>tZs zf-~=wY@gL3+Y&^S*6GNN%&_9^NnE*$L!l}{pgA)!laxsU*rRZ zS%rV8xjFG+{6U@hfb3^kuPzj|{^-RiK7+B)H8%uk%3%tJ@J^_06ngyOshCZ-D}4EW zh;pcOQ?&e`<(K5!-sem$k!vm>-$&Q&gXWt{!$;?PmXr)B-S39m%}ad+=FM%Iyo2Vr zPLvA}I1C`#Pv2<1S|nE-s>F5)X4E^C+ZX#=Nyw&asQy7u(dBW)*1>U+rtD#o*~_WXGv=%vw; zz1I1{HF_9I(?R12i*9SA_{jvfW?g@qyo8sRV1m}X19sM9EicJG+y-vc6tT$&T#hKi8Or5DA*R~=0CX@3NExvGTs-WK zIhRtUS~F{zh>vMbL#wimeuApTY9c(3x#+0op*$FQekZYu~T|T%gz};w>z2lNQWHDjA9hAHuA|v~ueywxx zc}t#!er>QvV$Tp1ml`7#4WvWy?(%!_vhtMUemQF0sR+B%=VSA>aAq{s5Bp$zhu1f% zl@7MT3ud!QN0=>I4t!-m@K>4h)KZSEjSHfUwUVJ0iaB+bbY#suH@#b}IrecW+6W|` zWC%5==i>KVz({ilhY|xXss`mvT}jQ&A$nCuXJv}G>bH?%+U*#b&*9%Db?#Io9I&V5 zEtcn46^Xc|1ghXttk0aB$+*^J1^;bq-`RIaGO%#0S%e6CRyVfERz2Rkxau7&{ManU`9hWsC+PoTmrN(rfDbV-I6FNwe}Z-N}3CS*PWs|dPbU?Muli) zDpsd-z*Pg)u#Hco`h&=Rs~gHfC58cr891*zWXO4Jw~bGd`^Chrva7K!9R&I_Ny95B zd5(R|?k))%Js#`UJB*kpD$mar3@)>g&7r#ND&Byzb*n>I6GjL7RJg=o$US7uh>dq{@Z@>!;(5fe{B)0`wPkx| zx}lllT9Ce#grY_f-6e0G*gAMP)Tv=&ax=1`deng&-EKh#kP>nX%&n0>?g>!iOyad| z(!pwK$w@!TuzXTUj6=K|uO8I6{<>J&YB1Db4Bwy6UO>po_8y-Lkv3Jb%?(b+go;{z z+5_Y@4n`E0iKCat`jnDDZ7W6)r7Q8J6PHRg1M}*}3Ude+blVtRi=>+i=^7Pf5ZlTApeozRk;DgPN{t3`^QVUv4^Wysv($Bo9SU`dC; zc#J95#jP_fPD?oGu-2*lr#{{lMzHnAhRS$VL;qWg-mrq=I$f>dzV`N$!aM;44+*SJUqsR9Yp$jlkG#kk!>C{Cht$d%UB zW5psUEDv;Ugg{d0u$lR$CTiK&r(A=oi&B{#ouGQxliK@qDl8DPaIo^o_dG20cX0aD z-##>id@K)jkce_V$jXEc*qGNqGKB*>Jln;_A$PS^(kvx^=qc%%iHzlEq@sjq%qDkh zv>PN}_`O>JWo*L)Y9jJ3h0R^(nadh|IHZK=_aqAE&%{Zrv2Fx9gl70^F&LzbN2&IWh5#w#&6G+{-4cPR`c+4`xs~>BcKf&JJ`qFOi0Eyi6vJZXtqHDAg?sr6- z>eE_Kuq69>8U0@ITA{c7;FOL}UD*s$)zZy_dF5GYU1gh8+hz|`B(tK^oJ}>5EBX2! zYT-hWwjuaJ7Xq)43v>(&>T+ZKpmAiMs+(&#sxmf23E0-K<_~AR)4#5S-_s#qh_e_H zQP6<++8K7$VXFKRO;RGXN)+z9>yEPReHy1ZyyMXIV84z8(8+CfArKD{<|Gl`cYCY4 z@CbA8O<&X_VWsxrM9M<52h*{pj)s;;`ZT+bl#SHfi$iFKeRaxhvHfvUzIUg)Zq_TD)v(h}TV{*}sd6BRXr&6AV zAf5uwQTIw$6)Xf3SiA9GOW!hzlj(ENtY$<`LcHGR1j%w~TBDm$3*Av@Y z>x>K@_u82-n;K4-kD8QG!%yYbJjYIV-Uk2F$L*U_+6EyR=Bg(a;sy;yPSIiCwD9xZ zmMYA~QSLDFFjkUdzBSGS(UFf0MtVHD?sM)A!WSW4Se&xAdu2M)p^rBXr4*wg2Jm~< z)WrnlKHz9iNIr^Jd^m@~>TX~l5HF%Wcp%Q*COQ*EPd}R}b8F93*biIcVJkdhPO!sX48g7*x6e%FOy%FOe#ZOj zg1k%e?UIDze*s$H2DqIMH4VAK`jX0dwH4kgi{!qi_70d>t-B-D_l;8(O2%|%B(H#{ zqo})z`cE!+@k`uqOM^wb_^z>SEHe=(* zI80?3?&d?c0keGgtZ}M`0FWJM^KhlLugOB8YLYN&*4|zdGPz*^TSk^BZ>PSrxRI0B zjL1!|HeD5JQkirwBRshVJ;Q~}33GyMn5>88%gT zpZDjVz2cM3k!l?`Rr5siileVw>TOcs#MAn%+~ulzJA~cVMP!WFu#GP4t08eC6q2Fl zyk!T2xT?BN5o}b?N^%z9soOjv*XgP=gQQ~_J@Ywvmo*g(Z|D4o zQA>quC85R4%et)0ia#FnX-58*Skc!7l8;K7PxB70L;OBbagTAZS})bc{R4ptGf^r- z@czp6KH295#20dC48N)=6oC*AxczhQz34yz9LgM*I@1N1-wzrfO!G2*m_&@LT1_vZ zYRm<6!_LDNZ|DE$vXzpghb8_(7O4=;dqvb#IdhlJyhXiB85$r5a^JwTJ}q{5u=bfm zLgm)GV3u8&wFEd~Rkid_u<|EGo6GXgQ!A&I(u~IQ+eP^K^8+`<-reVo z9*vSTE~%bYjxp4qPh`gclB0+k{<7KFD+9qiEy8YI_C-6ah&7gvwB^(uuv64lowwI^ z=5czv{7#T}gx2(If3v#K9Tg~4ZN!V@{|b6wm`sBI<; zu(y-*>BY)QcvE+_i@Mhn;jJ4p7m#@1XA@#Xiv$a z*RoR=fX^XDd$YqiK}zkE?W&pHaBnloK_R&NiHJo{pJcm~Ot1}s8d zU7RX`jY81cWOMZ$8PIZOuSPINBbAgzV2rkx>xLzgthlQHG{N{j=^Uf zgo;>X&snWpl>tW5lfB(Tfp8|6^n*G2N?)#hr2GX%@U5nAxs#e7KKGJK~j>!VndSF<1_aj9K_ay`$;o7CLg!fn>rM%2(SetAk& zy*;!UI0qK`{(I*l$B|x0X2F_gxF;_1D#`#HAsqdSfzD-z!~bC4+>Z1 zJd7j;PaAZ&Qz0lrCshhDelBCj?2b#!UA^{t7dRpTjvtFP z@X8RI{P$%UsKU`U*VWNcGGA7O=S^Xu5)6`&XYi1xp4&doZqUeG_9Taplm-tWQ~9;! zq3%c~x@$&bPFXUNmV!UiFOWC_AUUV8@#sFli%YN8n5`pSi?qZo=c{f|LlzA3v7o80 z8?_!`9P8ThcTcjyw#pCSHH{6AQHBpnS7xD(>V-&HSLy8*2AMxX`U8Mhnl5x<%9S_U zcA{Kfn|t0cD;sFhi?!91H#DG{FSN0A-}`t*{VT)98SHS5|65adS8i0VO^I=h9v+_% zEZe5^$msL*YAKnd8mF`ky=|KU&yRbBlP@!o zG@|9$XTB=6p4Ijw={&X38IHlo6xL&x$vkNQ{(?T$fln*pl8>#D$pYK!VofP^0;|Nz zbhc*hn5-e${QSh;QC(2phe(HRrmwes&O-l8V zYE;C4&jbp6~#(R^EhbiuED&NG5%Jd4i z*A6_!q2j%TMcovKd3879I^KpSLa-%a?}?eh?LA!WPq#KG2b@0Z>HHkJfIxoIGL0!2*j z-F&Z?;2O1)G%S6pzQwDEVo5NqpQ3Z*cDw5h0yY)b6;`inx(%Zi{0fUk>7227ZjcVg zG%u!~p8n{*WK}N>eJv~GA4jazkDS=?zF_E1m~s~|TXOV4dT0S#o7!MP)3+ zrE3uA%)F4iZnU|l0~>CK?E|Fmc3I-qJNotwODFy*w2ett!yw^VbMAbc20i)Gcv-iq zsNx88UJx}{G9CIC#x9eaIbjEH9S_^h&y61~{FJ^TX3ub{W7a+pSx4;2^t$2xOjSNi zkVE8r@P(I6)mL|VKR<6jWr!55HXT*?&~~*T#n-;rt5RW}!jF+^@g5UnjvPUhL{@5H z1yIgtI)@LP!M9JgC)qxu)w^19+_o(%lUFU-xf!izmH~H}psf+z2E5Ocn2EUe7CVRW zB=dBTtO!5elcbf|_mu$@Q}nW|as+-V|1-0$U?5O!o0!dJG0^2@jMMdz8%i-6V=UTw zzmI>=(X{@A1!w<52^ zt-lWG1Z?FJ4aMH)p-Fi|7sx!MAuF2)%T76jyu#utJR#SNljH>;A=3n3WD$NXP6Wf3 zU*bk;;BHs+NFAL%LK@b8JlMt9jQe`#zigoa3AApMui|9$XnV@J0t^ouk4f{q?x*^5 z1$<)qDRg|?rvxir_0NezZcvn>s$&5kGw+kn3&4iUAXSIuUMROee}cFXT6ZAUJE`H5 z*NUH5MV)P=rT87xG1PC?py8C`uEb|LlrQ7fIi>u(6xIX>7CCS4!;48M@88;#p84dh zZeW%r4va9FGseOgm$sUMS+83C@F{3~?$46YQoMaMswu^>|F@#IyR2XkxI>cd7BD_4 z3PYx&mL~R<8QGr(Fy4T5?>DrD5;)(2B2>WL%lmbQofndPOpsV;_1dg8M5!s>p~{Xs zqB2J|&MY38nh1qGUn0!{%t|gQtbiCb*v{*NxXCG61>E(IsQjBnxX{elg%5=Ocx7MN z*i`RflUFC1dzk?3^z!I@rFkbl{@DSWV_uU#a53T&t0hA3+9#M_p;_d?O0uIOrvF&4 zkn-+>3)pJ*b+&P)Py!?)bA0HD?SID6m$W2)D*4I~-_uyy1gTL7;gh}0?0yR7E3M&< zTYTX5t@Ivt-|RP^XN{J%Zd72I33C<1u$o@O*`X4njPuzEYnfSr(C+}~CZ*?Epul;@SUkSnf z(U&DhI|WfpM@rxW#|5!P$G!&otUhO}(`Y+S#Wf%Zo! z>Qbyb*yNr*SyL`WX*xf6cxMig>nVCVnVy0*^Y+avVYcQMgmZVS9r_r%IjC}0c3Lu^ zhOZ32+}(1C4L@qB4psDSBoP}(=VGIR3V*j=vFVeI5slaJ&JM9 ziIesB&Fjlje!pm!SIs_NTFFyotf~R&2Och6h;E{TR|92)&%dwaxFe*o|8$*#I)k9r zM8UfAD&-A!&=H9o5+nRhUG30{geUHIptL;S!)jdlU@j2f*v@mj7)Ul*>R=o{xl}QG zh(c=Tu3Xn_s&PuMt-7xu|M21BwLM3*)oVm;Zh=#c}r^=uLAX`Ea}kjm~l~43tLvHKObmWU;*{fbN7{@ znZQ=#kGoQpxafor{Epswt1ezKT$;LEEp;A2if~xM(u_1`N?pnd&|pi-Pz&I+ayv@@ z+1mLhIBiLNQZHew=MyZ>dwNDJ&-5+O2^lhp>r%S(``$7beM5K0*LrAl*uMp$F|5!N zq;R8r5IWtOYgcQC%<7WxQM_)YoUfDE)~sQ@zBTqrv-ElQqUF9;n`H(8vze34c~4xZ z{Nh?s;XSuoit>pp39`FRV%D@IYv;`Kzhkk3kNdbAXZ!R<6~}6)jw0lfqR zwRuoms}~tf9>>r&MyejR!G3>|j!%E@c;tcfuQ11#3Sm+lqVs1Ad7|2fRGAEkJ2_)f z;OgA5<+MD^n4TAMH2WC<@APUa=zN5VoE=^`sI+xBsQ86%^0m$&)q63xx7;5ms+_MmujLL}E+cg*tTD!B#)L8!A|_yd>Z+K)tbS z1uY6;lz`Eld-RxBGko&=C&F|!tj$Is_roO7cf(tBgCX|3sS!H&?VOPzaW6k1Wl}|@ljrY_6u6}a_eHgGWg#<@e30i z3m2X=`SnG^zK=RRpvkah%We1S!`H#1+&ueuAklyd>x^J7(KTHptylG%^uPcrP{JiH zl>wKf$eF;rO01}@DX1oDTPBR7FU^~YcDc$tn+2Z^F!VG)cLh0=+h8+J5pD_({ya-H zT>)}H1Mdt~(>X{3D-l-VZ8v^={jW6B|5W|u#qe&;-PkiheA|hkchBGabQtpITLayF zk+*M4>fJg>k?#Rz5S9U^y!@k5Rhl^=CMN9}=A9JJ?Vyh8Ezb;f{Q(6GcZM(fK_yJ6 zZB(>BD&UJk$Vc9{*FQXJ376dnw@*6KA#x5`trQ#h(s*9bK_M?fZJvB(un3H@^xu}+ z-_upE`0>=u>?Mb%heDrn7UfPPUVUZIsHb=5vdedG{eR)LkC{kNbAvbJ_C@{MZcuRV zLKne*$HGVYO$aPWX>z9J@wVoAQm2mG^Mt%@<_oh*-H-p}*81tc(6s&VpBImLGquuw zwbpL_;zB;GXjbRhZc{>e&wzG)OF~|U^?|FOKE~-slD5_v*&O!Knx5jFB`-39*;>QK7KsW(rW_M9f&RN|GGfi&PUp))2+tJBYd{R2+6UxP?(gF%1!&FYa%fnT9%yC6`z9ZzQUc=#!+dj?Z(| zC!V%z%lz5mF03<=3ZrzbIb0=$one8-8QHfU{!lv4K<88agPwVX!U%YI&Pw|*&h7{Z z`}l6*zanB*B(C>Q9i>I^1%-qo#E1W)k{Dw+7e=SGfR;6moBU1-!dS%WXk%^E{58dE zgJ4Z_V?nkH+Rb|eD4SBZeHZtbWYsR|)licmi&Z-34zy#?*AO}n!q>L{5Pv%OZk(`} zvIYVP@B(1=ZMKXRfv_~gpwEJsv`#yi`S0QklM{H-BmcN%{Gv#}nFosdc*4ufnIL>M z-8_HEc=E0K+Zhj>PlbQ0R{Z0Pk6eFW__uKWfA-}(%zAn}YhyP2Z9Js8xRGTBwD#qq zIDic4YJ9%1G%ftL=-D@+RBHz=Lg!1qANHYv$%qo!2O;#R;_n0U(|al0s;tNVH!XG zuP-*{tu|Is;V!E5@qTmW#l$gp5R!92$wg2@!+;w0^H0J5oMf?!T9@zjMno%NLp*c> zX!CeLXw$+U?R`{RE|HCc&fmE}U+RhNa}J>mDi#aB$XnlL{{M76_Gi=NFJ(0qx&f$Y z)#?IeFj@W!mP)k4Uv+MshhO%ku};yW{+T0CRG*-s_c)3ULy9lB`s?fF&gjA_Q8^+a6~ z#JE!F=d1YOlzybCd*9>Q`|Vw{JO1f4L$0gK9t;yTPEOze2Km>2U--9h{{C|Q9vy$H zj{hsvW7~PRdCUTL_U$`uFQ{$MdIvRamrA8I&8mLSlHW;ppN%m39$v@9+9Arc3iv%4 zEERedxSh6NJUC-je$YH}JWqtI=0DulqsSCtim;j?xy9)YtVP6~!qfDFGp=8}PgxHs zSq$-0lt3KMcYa89{o+{}uJlN|Oo5Q+1uR;Cwzlv>Z^R^fH_y#$^FMG~%kHM%L5AT% zjnj5q`9YUY3NS2JwfcBuGwY4)e>m8wR~Uuayvmxo%=X${K2d=(*U|U`urmDmsCq_Y z48}3z!6~Wlo%ofZ;~&)=G0Fd^^t!STl2e5>b;0249Z3jRxcJoT{^EfHf?NlX;W@pD z&t;U>LJB|{0N{LcMoXs{0em({R$^iiRHOF;vT3zmISSV{yvgGcve>}4coknN`33Wf z5bB(jsc_k5W<|w0vTZ&w+q?~ISYTu%b>Pd(@%`cT-+j)v7<^yvYOj9>)2r0LA&t`y zl5)X#@$42F#lGsKp`EGmqG^7Ah`}Cl|KFG-|Hn59{$ii}>CgWr$sU)Y`Z(F9&;O(5 zM`H{m+ zDJcC$ulC(`VTX37e$BG_vR>AmIP-gvTJ<_f3Fd_qyghj5UetZ6=F%s9+cEDt&}G4a z)<(o(YffL0_&SwVyT@cT^~9~g#%@c>Y@Y?z=8r48M~jFiFOOW=+njCMP94=?lOJ5X zN-P`)UT`-~l^~~P%m*lB0mcOeVLH`)f`I02`U7joK~R@w9kKZHsw5OHx;{c$ zFnRyEv?}DLm8+X_xwlNoP|u8GaPu(kT9-UCQMreVE}e}@F(+x>){aM3JPtAYBGr7O z=J{~H)A~_3Jq2V|+I2~qirhoTyIX0IMEZP}d!E@=f~Q=TQ4Z~wx%q`Dj^#6##XWgU zqoX;%oy$I%BQ>hfdGUang?aWbxnIs!OYhP*z3k{n9C@VNEUNTbds7eL!MSPp=DeUE z$E&XU4gjjMya86TLpHKYWZLmIFVyjT(W3|u&(fd<1R2fK4##=6FBqyzsjg39X7sF{W-O>$;Z4flXG~HlI}X3U9$7bNI*1zHtfWyXk2CX*>LH5j|1u8E)1-axw3J zHe3h|-IJP$cgM8G^j%4m;xymcz`p9ZpO-GE`(j6<3nqBmWFxPmss7R6+TNsv#xJ~hZhHHweX`qS^-k&` zio(%^fvZ1qAI&2aLpQafUX2X~nL{~8W`h9Ysfmnhg3w7x!-6`CmCU+NA!0>|Y9Nj! zv7uNHJ8EUIc#x(Stu%#3OX>9&oyCK zhewAeAJrX2)#K`HdU@|z56pRk2XO*={`eKu+{?uBVq>391l}94nX%sWgy8d78x~SM zPGT)bs$HMSEA(;wEROQzPel8-t-K-|l8V+72iu32(gji#m6*VBux=doY`jcRKg`N7 z#SexAVj9eQed40U3tc4HR~)q7)z8+*XR7ZbQBr{{X3YKJm0&_C<5z}|v32>b>gtA@ z?K|m@irin9U+Mz-`XEjBN==lYOlgYf+7LY#J8stDpd(#74E_Wd?I=yxw>UA zp3Tf;JYGMd_;GDyn;+Cl>&!dQ_J*(OvX# zBlUc|ctanwyX>aHUY?=NUT#jPl4DFFm~$Ee)wJ^SEGS%dm@US>4P-OgO8xc!Aa(t} z%?fRo+RFzauRJy+Ztl@D@rJ{oS!KA#;eoc7$X^*g{^+>v6FvGP;8mM&hdlZ>UM_(p#&VAvxgVyW@@G+F*CY4!9a1`MI# zQ8oIL(X-F?258DwPR}M0AK6=up?>*E->a?A7VpabBHK#a6JtL0*)VPkPll!Quj${f z95Ctcf(dcY1v6R3w|U(;w-*aQ5Hh{9DBV8MM9YDi7tVOmiJ{7;-g95pP$FM0y!rL@ zI}~DtQG>OWAf6N>5GMr;1G}G<}EQk=y(Py7O^XU`Jqn88gCq^z*p}XBUK=|FRk&J^^3(&Hj zp66#_Z#hfRy_G4Y2L@3nK#5p@67EcbIOi~eKQq=VS4oXsTPwF9RPq9o!AYRSSOz_X z;s-iDHy~i^%aP%g?ki%}8TvcS9G3dpu6Q#5FtKf6n`cr7h6yGc7~`N+q?hFzaUC=a zfQAgBw8chWsb1LO^cBF{macm#F$Km4V+l?517s;uT#0ug&|AYYJ^|5~TooM`2T+NU zo1JDzVPF7z+9GXZZ(Qohh$C*HPz+Y)|F?YGIx4mq^-ClS?c zipqh{-$I?qzf+V`(9yMNrN0ioE6Kw)u~C#obIp>33=$a$x7b9x@+Jlxv`h+2#mKK0 z8JdhijJE)9#RWB{p@@aV3{nBdHuFt;rJi!#2@qv>A`u$;g0xYPRnIF=B^l;ZyA`dO0{`>K9dfX(7anm z3sLvJhTSkuSksE@*>{8OWPWA}V3|kr4f;>(S$<{kqlW8FKIC|)<^no#3KKpvD~xhz zge0dITzo^0&M+?M5$x!uWYk=QZ?a3*15?Fs!SBXRUes!U3+!mbX_t2T3nU52yQScR zz2|(@D!oEn2cmUv8P=Y-XZyj}f;@E{mK^JyBnoKv7=>h#C?=CY6IB&&V#e%Jw$=NbP58%Md+o4&@` z%7d>AB0A&Of&yxt6%DRrNptbMZ;g0NmaadXn!WXwmO2^g`P&f=qtayPn^kr3LyKn$ z3hTVsr(q=V48K?!sfx)O340}!MOOwegAw3o8YS0ZC)I!tOK@Z>M&(DA&B;wXi$=4Z z+gUeRG%$IjZ&m*BeNvKNhq&czYOuo9cV^M>O0Ji1JQP?Qa&8S`3smyHrk2WXm;Qul z`nq3RTglL%DarY%?T?bpL*2CMhQ%mxf&|G^!fVV<7?^`6PvsTmy$o{=8sG{>_3;iQITlZMz$Lnye@a2x4QuYI7UJ((%D-@rHU}&# zP|@e&F;2753!y^kK5v(%H*<2LT%X&XH>fL$%)Bzs%3h24i+8d{bC zPZR{VU2Lk=w5u327S1+IlKN~0R7j*aes|%LH7*^8WwBKTff& zoLv|T>2cd_FRXSaP5~v%G$-rR#JKwJtIrMqp=wxDXvBQXffdj4aw-yLzDR})A*OFh zevuJKUD_OIp(igb9JS3uGS5+M^A2>oO9dA%r&x6+$xA`;`be*M4ap_MVLK02T*@l9 zIGkrc(?3@UHI^B!Zbfbot?=lNF2&%+Q7>sHpGz_+>4B;>5zH&a2O z6D#8Gfm!PS{dPVtB%eSvj$V8;Q8*x4dqUcbVX)$os$TB03XZr^Ga?}JgTQLigo?lQ zYDi|T!vK#80`f`AVfA&d9jD1=POM$Lx)^T#(-0$A%TcIvmT-0);<>%?%h^|J=7_uq z7%`2mqo7qvJ{!>j;!P~iT*LcDW(aLa7!U}06`RbkI0;WN7QT|%gvh&l=~1QB`OTE) z_M^tZOz}#rw1O;FXiY>=E98A6DrMO@AfH2LqYxrUs0*0DjYQDJW|1bwrLa=~QEetA zgK!51LmlJK0Eg1P3r^JP?|gY?E%0vnVX!)1pyvPpjt#MXsSQD=2T6cpKttvHy|RxT zHV99yVkONoyX2I>HHP{Jx+!wu_xNOAUkKGeIuUC&J(g>PK+uqzlRg`}yp$>85^#ie z^3`$2qg$nVw|XXzXe8iz%9XjZwA!=wb8jgD00M0g6`!=aPA*s?w;Gzg#EwrRQ^QCZ zaP5q-j`u|RAvY#3GgQ-ammGH&!bPP8*V0lu+3ognVsc@MO1qLJogTeb7*dxK6{iNu zsSR07LzF4^c2gU{Rw3e&_bJ`#i#aCabP~CgCyR7amNV$z1U4N&)6q(D(GMp?3e_}P zcil6_A8VV`bm^z3SkcxyN>Y_|pmA@TCZzoN2#EjZ?1wfhgN25>LK9g9?&8ag@+Qs{fb z74ty>Rzxie*dT$b64{Z_a)lkT?;r3nlWqr8T)Ks|v={TX<9k}W`fQ=_`L(8#DeKzb zhd%>8P9(?=KJd^xV)=AFzlJ~l{nNdg9lm*d=j#*$XF>dc9GgzMmAen~PH!AGjQxHY zdk{(K1pJTdQy_Dx#44H0wi;-|mU)rl9~MW?2Od+lo-9vaigW=yUjK(BIXKB<=+;OP z)>(YEzncGq7r#LF3vGUp%+DO~|2OR73GFg|N=lmVm+eDx^d3-8ZaHe7f%IZAmla-S z*bt7$lk#^ZtrjMMfQnpxjWd9RsK4VI{x=7g#6pPD}0&hNI&byQS(U@e5G z9#efeYmi;kk(no+37&p(7_rT062}y0`oRk=A={pM#}kKChCeR79w-U2*3leZbjGV; z=?>KeQomQ(MB+@5SW1f=s3>5($N7u3C_koog5%tv;+MpC;cEvnFN$q;L$8{G(@fH7}E++KFjp-z5p z(_pz(#?Bf1MXzb5vXv8X007*zLS(6EXO^+!y{W~1^ykvq2gsmkRa2Hrj|+6;gM$x3 zc1iY0jYTq|+ zMf<*0nJ!d=G(7+@UlBmqDyPa|s9CV7cBfU{Ihs6TXOvgA*KUmuB|$xyiPYr=KfKNE zK!oj)ly5yC{L1_VkZ&mZ9T|kB2Dl(j7zdT7jY=(D>X#I6h1&D68n->T z^_G%s2J4zC+VeRj-68!coX*4JmRnUhi|gtfAg#G-55)d z_>%}TI$?cty7n+-|LbW4Y{`hxmq>7fXq)N{;lBw=OGB zEliIUUt7%{X)R+XGJTTsqL@4K(PuyqGhxvFyQal=jU>WlU@`Mzkb7}!&7|0!rIpI% zR^xk3d_nztCn2-M4959Og3;6wOt?-ujqmd@N>64DVf+V?++rbG?-S>Vhf*7yh?jlH zw$m$qd#Mcvy+vuR@h20@tAQK}yG-E`i7OJVnd`4I%NR9Mkxg$@huA37>Ua6>!sVq9 zgP8#_A`-4f3CMLV_-;*rD_TekvVAlP9Njb?-}SZH?CwJoiZMrouUizTQQ4VPH6$_A z?aR?$cUf2;xHm6JRh=a55Ef$3i+^sEwLe~qadC{LGuH~-60pfNt$p0q6lDd8k>f1d zc_3(B9KWH`Z^bMjqcjjyxBQ`%H=_Q~@+?`S!?DCy$Fp32X~-J#x;$-@OPS9oSUWOA zB=TYPnA*$yF+w35mupLIzj+3>#&XH^zAiBsA#Xz3_Rpt#>~rUrYu60>2gJ_b(Jvnf z6)FK+n+k>$ZE5b?rD{W$(Zmg7=v9yoe;vA)Dvi-2L)tGFiX5Vq0BA5W}8_qyVvAyMjL1 zLq~XHKO!zpt>A7ZFUb8cu^q^tK{tz7M-$jXud+JxaTwQhjaIiJ!5F$_EqMCWfopI zx|?;u5EUzj_wD^HPZL8ObRstCll=qlR6*#Gl?Oyf!j%o=I2|kXB(TDqsT($2p6r;N zm;h>132L`iQdQHpRB}$Us!J~r^ziQCP8>R6<8+YPtLWf4>u@jZmewuuFW=w_P!mlJ zDH+V;_rn`qS|b{=TFH7hSgcz%vnJY}%ISM|MY+an;02cpRC&Z^CMdOzI6=(Fn>Gm> z3^qM8o-rPDy-XsYBWBcGheLk+Gr;&gDllD&&da`6YEFoy8=p!hsfI+|3RI7cM~@hU zxAHHO%t$P4&+f&T|CF6QQ zxi@)9%RUXLj89gNLX91BEEeY?`OomfiT%qBNk#5gVg{LVcA2l^NewZPgtcjuSNe9s zkUS+?1hyX^Ev8Dt?TZD%TM!lo^HT`-?2FEqTB43ttu%QANVDgUTWe2reDwWPF%mkg9+drg6m`9wykXFZ-9h7CoF0;E zxW;8Pp>*KR*Hu`5pFE0b8pbJgBx1!M6*0B6tY905JsY4ncxHw^pYCch`7}{F)!T4Z zyoMo?0d}IA#49Iu@7m;(#$(8cEj+CA1u{F-5V;zgfe$a=16jCy+S0uUma(|#%u>3% zP0b+#&*x>fw`V=ih_QuKC(Xm#ba+%q4#woh!CkcT0*wmyY9RgN^Iqj(jfH#oqOmOj z4UV!h+AHOvCG|M?GkHd=A%?(dgYDDC2&H#Ep8;XvH_E{Bgfb&M`{&vt2iL5y@i5qW zgo0b*0#4GFFHF73=eZcc$!HjN*>bku01g@V(sg7)osvVw>7+M1YOOn<%e53T9a!f= zGm8Y=wu(K?AXySg0xOAP{5J)yypa`KM@PoS33-&qD@UJ90R$}nY}@$1oW}vS=ju29 zdOa8Qv7);=_u`P$oK$1KwQOtp0pR7kN=vvSWa5(9L6wOhZ=VjdCvDBqaYcJLpfT

+ /// Example of a PSK function call back + /// + /// pointer to ssl structure + /// identity of client connecting + /// buffer to hold key + /// max key size + /// size of key set + public static uint my_psk_server_cb(IntPtr ssl, string identity, IntPtr key, uint max_key) + { + /* perform a check on the identity sent across + * log function must be set for print out of logging information + */ + wolfssl.log(wolfssl.INFO_LOG, "PSK Client Identity = " + identity); + + /* Use desired key, note must be a key smaller than max key size parameter + Replace this with desired key. Is trivial one for testing */ + if (max_key < 4) + return 0; + byte[] tmp = { 26, 43, 60, 77 }; + Marshal.Copy(tmp, 0, key, 4); + + return (uint)4; + } + + + private static void clean(IntPtr ssl, IntPtr ctx) + { + wolfssl.free(ssl); + wolfssl.CTX_free(ctx); + wolfssl.Cleanup(); + } + + + public static void Main(string[] args) + { + IntPtr ctx; + IntPtr ssl; + + /* These paths should be changed according to use */ + string fileCert = @"server-cert.pem"; + string fileKey = @"server-key.pem"; + StringBuilder dhparam = new StringBuilder("dh2048.pem"); + + wolfssl.psk_delegate psk_cb = new wolfssl.psk_delegate(my_psk_server_cb); + + StringBuilder buff = new StringBuilder(1024); + StringBuilder reply = new StringBuilder("Hello, this is the wolfSSL C# wrapper"); + + wolfssl.Init(); + + Console.WriteLine("Calling ctx Init from wolfSSL"); + ctx = wolfssl.CTX_dtls_new(wolfssl.useDTLSv1_2_server()); + if (ctx == IntPtr.Zero) + { + Console.WriteLine("Error creating ctx structure"); + return; + } + + Console.WriteLine("Finished init of ctx .... now load in cert and key"); + + if (!File.Exists(fileCert) || !File.Exists(fileKey)) + { + Console.WriteLine("Could not find cert or key file"); + wolfssl.CTX_free(ctx); + return; + } + + + if (wolfssl.CTX_use_certificate_file(ctx, fileCert, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error setting cert file"); + wolfssl.CTX_free(ctx); + return; + } + + + if (wolfssl.CTX_use_PrivateKey_file(ctx, fileKey, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error setting key file"); + wolfssl.CTX_free(ctx); + return; + } + + + /* Test psk use with DHE */ + StringBuilder hint = new StringBuilder("cyassl server"); + if (wolfssl.CTX_use_psk_identity_hint(ctx, hint) != wolfssl.SUCCESS) + { + Console.WriteLine("Error setting hint"); + wolfssl.CTX_free(ctx); + return; + } + wolfssl.CTX_set_psk_server_callback(ctx, psk_cb); + + short minDhKey = 128; + wolfssl.CTX_SetMinDhKey_Sz(ctx, minDhKey); + Console.Write("Setting cipher suite to "); + StringBuilder set_cipher = new StringBuilder("DHE-PSK-AES128-CBC-SHA256"); + Console.WriteLine(set_cipher); + if (wolfssl.CTX_set_cipher_list(ctx, set_cipher) != wolfssl.SUCCESS) + { + Console.WriteLine("Failed to set cipher suite"); + wolfssl.CTX_free(ctx); + return; + } + + IPAddress ip = IPAddress.Parse("0.0.0.0"); + UdpClient udp = new UdpClient(11111); + IPEndPoint ep = new IPEndPoint(ip, 11111); + Console.WriteLine("Started UDP and waiting for a connection"); + + ssl = wolfssl.new_ssl(ctx); + if (ssl == IntPtr.Zero) + { + Console.WriteLine("Error creating ssl object"); + udp.Close(); + wolfssl.CTX_free(ctx); + return; + } + + if (wolfssl.SetTmpDH_file(ssl, dhparam, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error in setting dhparam"); + Console.WriteLine(wolfssl.get_error(ssl)); + udp.Close(); + clean(ssl, ctx); + return; + } + + if (wolfssl.set_dtls_fd(ssl, udp, ep) != wolfssl.SUCCESS) + { + Console.WriteLine(wolfssl.get_error(ssl)); + udp.Close(); + clean(ssl, ctx); + return; + } + + if (wolfssl.accept(ssl) != wolfssl.SUCCESS) + { + Console.WriteLine(wolfssl.get_error(ssl)); + udp.Close(); + clean(ssl, ctx); + return; + } + + /* print out results of TLS/SSL accept */ + Console.WriteLine("SSL version is " + wolfssl.get_version(ssl)); + Console.WriteLine("SSL cipher suite is " + wolfssl.get_current_cipher(ssl)); + + /* get connection information and print ip - port */ + wolfssl.DTLS_con con = wolfssl.get_dtls_fd(ssl); + Console.Write("Connected to ip "); + Console.Write(con.ep.Address.ToString()); + Console.Write(" on port "); + Console.WriteLine(con.ep.Port.ToString()); + + /* read information sent and send a reply */ + if (wolfssl.read(ssl, buff, 1023) < 0) + { + Console.WriteLine("Error reading message"); + Console.WriteLine(wolfssl.get_error(ssl)); + udp.Close(); + clean(ssl, ctx); + return; + } + Console.WriteLine(buff); + + if (wolfssl.write(ssl, reply, reply.Length) != reply.Length) + { + Console.WriteLine("Error writing message"); + Console.WriteLine(wolfssl.get_error(ssl)); + udp.Close(); + clean(ssl, ctx); + return; + } + + Console.WriteLine("At the end freeing stuff"); + wolfssl.shutdown(ssl); + udp.Close(); + clean(ssl, ctx); + } +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.csproj b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.csproj new file mode 100644 index 000000000..50a590a1a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.csproj @@ -0,0 +1,87 @@ + + + + + Debug + AnyCPU + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5} + Exe + Properties + wolfSSL_DTLS_PSK_Server + wolfSSL-DTLS-PSK-Server + v4.5 + 512 + + + AnyCPU + true + full + false + ..\DLL Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + ..\DLL Release\ + TRACE + prompt + 4 + + + true + ..\x64\DLL Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + ..\x64\DLL Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + + + + + + + + {52609808-0418-46d3-8e17-141927a1a39a} + wolfSSL_CSharp + + + + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/App.config b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/App.config new file mode 100644 index 000000000..fad249e40 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/Properties/AssemblyInfo.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..56a4dcf9e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("wolfSSL-DTLS-Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("wolfSSL")] +[assembly: AssemblyProduct("wolfSSL-DTLS-Server")] +[assembly: AssemblyCopyright("Copyright wolfSSL 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("9da922fb-8459-479f-ab06-42b5c0378d2f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.cs new file mode 100644 index 000000000..c7cdd43a7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.cs @@ -0,0 +1,181 @@ +/* wolfSSL-DTLS-Server.cs + * + * Copyright (C) 2006-2020 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 + */ + + +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.IO; +using System.Net; +using System.Net.Sockets; +using wolfSSL.CSharp; + +public class wolfSSL_DTLS_Server +{ + /// + /// Example of a logging function + /// + /// level of log + /// message to log + public static void standard_log(int lvl, StringBuilder msg) + { + Console.WriteLine(msg); + } + + + private static void clean(IntPtr ssl, IntPtr ctx) + { + wolfssl.free(ssl); + wolfssl.CTX_free(ctx); + wolfssl.Cleanup(); + } + + + public static void Main(string[] args) + { + IntPtr ctx; + IntPtr ssl; + + /* These paths should be changed for use */ + string fileCert = @"server-cert.pem"; + string fileKey = @"server-key.pem"; + StringBuilder dhparam = new StringBuilder("dh2048.pem"); + + StringBuilder buff = new StringBuilder(1024); + StringBuilder reply = new StringBuilder("Hello, this is the wolfSSL C# wrapper"); + + //example of function used for setting logging + wolfssl.SetLogging(standard_log); + + wolfssl.Init(); + + Console.WriteLine("Calling ctx Init from wolfSSL"); + ctx = wolfssl.CTX_dtls_new(wolfssl.useDTLSv1_2_server()); + if (ctx == IntPtr.Zero) + { + Console.WriteLine("Error creating ctx structure"); + wolfssl.CTX_free(ctx); + return; + } + + Console.WriteLine("Finished init of ctx .... now load in cert and key"); + if (!File.Exists(fileCert) || !File.Exists(fileKey)) + { + Console.WriteLine("Could not find cert or key file"); + wolfssl.CTX_free(ctx); + return; + } + + + if (wolfssl.CTX_use_certificate_file(ctx, fileCert, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error setting cert file"); + wolfssl.CTX_free(ctx); + return; + } + + + if (wolfssl.CTX_use_PrivateKey_file(ctx, fileKey, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error setting key file"); + wolfssl.CTX_free(ctx); + return; + } + + short minDhKey = 128; + wolfssl.CTX_SetMinDhKey_Sz(ctx, minDhKey); + + IPAddress ip = IPAddress.Parse("0.0.0.0"); + UdpClient udp = new UdpClient(11111); + IPEndPoint ep = new IPEndPoint(ip, 11111); + Console.WriteLine("Started UDP and waiting for a connection"); + + ssl = wolfssl.new_ssl(ctx); + if (ssl == IntPtr.Zero) + { + Console.WriteLine("Error creating ssl object"); + wolfssl.CTX_free(ctx); + return; + } + + if (wolfssl.SetTmpDH_file(ssl, dhparam, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error in setting dhparam"); + Console.WriteLine(wolfssl.get_error(ssl)); + udp.Close(); + clean(ssl, ctx); + return; + } + + if (wolfssl.set_dtls_fd(ssl, udp, ep) != wolfssl.SUCCESS) + { + Console.WriteLine(wolfssl.get_error(ssl)); + udp.Close(); + clean(ssl, ctx); + return; + } + + if (wolfssl.accept(ssl) != wolfssl.SUCCESS) + { + Console.WriteLine(wolfssl.get_error(ssl)); + udp.Close(); + clean(ssl, ctx); + return; + } + + /* print out results of TLS/SSL accept */ + Console.WriteLine("SSL version is " + wolfssl.get_version(ssl)); + Console.WriteLine("SSL cipher suite is " + wolfssl.get_current_cipher(ssl)); + + /* get connection information and print ip - port */ + wolfssl.DTLS_con con = wolfssl.get_dtls_fd(ssl); + Console.Write("Connected to ip "); + Console.Write(con.ep.Address.ToString()); + Console.Write(" on port "); + Console.WriteLine(con.ep.Port.ToString()); + + /* read information sent and send a reply */ + if (wolfssl.read(ssl, buff, 1023) < 0) + { + Console.WriteLine("Error reading message"); + Console.WriteLine(wolfssl.get_error(ssl)); + udp.Close(); + clean(ssl, ctx); + return; + } + Console.WriteLine(buff); + + if (wolfssl.write(ssl, reply, reply.Length) != reply.Length) + { + Console.WriteLine("Error writing message"); + Console.WriteLine(wolfssl.get_error(ssl)); + udp.Close(); + clean(ssl, ctx); + return; + } + + Console.WriteLine("At the end freeing stuff"); + wolfssl.shutdown(ssl); + udp.Close(); + clean(ssl, ctx); + } +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.csproj b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.csproj new file mode 100644 index 000000000..915ed3201 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.csproj @@ -0,0 +1,88 @@ + + + + + Debug + AnyCPU + {730F047E-37A6-498F-A543-B6C98AA7B338} + Exe + Properties + wolfSSL_DTLS_Server + wolfSSL-DTLS-Server + v4.5 + 512 + + + AnyCPU + true + full + false + ..\DLL Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + ..\DLL Release\ + TRACE + prompt + 4 + + + true + ..\x64\DLL Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + 0 + + + ..\x64\DLL Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + + + + + + + + {52609808-0418-46d3-8e17-141927a1a39a} + wolfSSL_CSharp + + + + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/App.config b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/App.config new file mode 100644 index 000000000..fad249e40 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/Properties/AssemblyInfo.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..066aa71c2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("wolfSSL-Example-IOCallbacks")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("wolfSSL")] +[assembly: AssemblyProduct("wolfSSL-Example-IOCallbacks")] +[assembly: AssemblyCopyright("Copyright wolfSSL 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c0ac38b1-1984-4659-b36a-20362dc47f99")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs new file mode 100644 index 000000000..f57a63224 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs @@ -0,0 +1,280 @@ +/* wolfSSL-Example-IOCallbacks.cs + * + * Copyright (C) 2006-2020 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 + */ + + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Net; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.IO; +using wolfSSL.CSharp; + + +class wolfSSL_Example_IOCallbacks +{ + /// + /// Example call back to allow receiving TLS information + /// + /// structure of ssl passed in + /// buffer to contain received msg + /// size of buffer for receiving + /// information passed in from set_fd + /// size of message received + private static int wolfSSLCbIORecv(IntPtr ssl, IntPtr buf, int sz, IntPtr ctx) + { + if (sz <= 0) + { + wolfssl.log(wolfssl.ERROR_LOG, "wolfssl receive error, size less than 0"); + return wolfssl.CBIO_ERR_GENERAL; + } + + int amtRecv = 0; + + try + { + System.Runtime.InteropServices.GCHandle gch; + gch = GCHandle.FromIntPtr(ctx); + Socket con = (System.Net.Sockets.Socket)gch.Target; + + Byte[] msg = new Byte[sz]; + amtRecv = con.Receive(msg, msg.Length, 0); + Marshal.Copy(msg, 0, buf, sz); + } + catch (Exception e) + { + wolfssl.log(wolfssl.ENTER_LOG, "Error in receive " + e.ToString()); + return wolfssl.CBIO_ERR_CONN_CLOSE; + } + + Console.WriteLine("Example custom receive got {0:D} bytes", amtRecv); + return amtRecv; + } + + + /// + /// Example call back used for sending TLS information + /// + /// pointer to ssl struct + /// buffer containing information to send + /// size of buffer to send + /// object that was set as fd + /// amount of information sent + private static int wolfSSLCbIOSend(IntPtr ssl, IntPtr buf, int sz, IntPtr ctx) + { + if (sz <= 0) + { + wolfssl.log(wolfssl.ERROR_LOG, "wolfssl send error, size less than 0"); + return wolfssl.CBIO_ERR_GENERAL; + } + + try + { + System.Runtime.InteropServices.GCHandle gch; + gch = GCHandle.FromIntPtr(ctx); + Socket con = (System.Net.Sockets.Socket)gch.Target; + + Byte[] msg = new Byte[sz]; + Marshal.Copy(buf, msg, 0, sz); + + con.Send(msg, 0, msg.Length, SocketFlags.None); + Console.WriteLine("Example custom send sent {0:D} bytes", sz); + return sz; + } + catch (Exception e) + { + wolfssl.log(wolfssl.ERROR_LOG, "socket connection issue " + e.ToString()); + return wolfssl.CBIO_ERR_CONN_CLOSE; + } + } + + + /// + /// Example of a PSK function call back + /// + /// pointer to ssl structure + /// identity of client connecting + /// buffer to hold key + /// max key size + /// size of key set + public static uint my_psk_server_cb(IntPtr ssl, string identity, IntPtr key, uint max_key) + { + /* perform a check on the identity sent across + * log function must be set for print out of logging information + */ + wolfssl.log(wolfssl.INFO_LOG, "PSK Client Identity = " + identity); + + /* Use desired key, note must be a key smaller than max key size parameter + Replace this with desired key. Is trivial one for testing */ + if (max_key < 4) + return 0; + byte[] tmp = { 26, 43, 60, 77 }; + Marshal.Copy(tmp, 0, key, 4); + + return (uint)4; + } + + + private static void clean(IntPtr ssl, IntPtr ctx) + { + wolfssl.free(ssl); + wolfssl.CTX_free(ctx); + wolfssl.Cleanup(); + } + + + static void Main(string[] args) + { + IntPtr ctx; + IntPtr ssl; + Socket fd; + + wolfssl.psk_delegate psk_cb = new wolfssl.psk_delegate(my_psk_server_cb); + + /* These paths should be changed according to use */ + string fileCert = @"server-cert.pem"; + string fileKey = @"server-key.pem"; + + StringBuilder buff = new StringBuilder(1024); + StringBuilder reply = new StringBuilder("Hello, this is the wolfSSL C# wrapper"); + + wolfssl.Init(); + + Console.WriteLine("Calling ctx Init from wolfSSL"); + ctx = wolfssl.CTX_new(wolfssl.useTLSv1_2_server()); + if (ctx == IntPtr.Zero) + { + Console.WriteLine("Error creating ctx structure"); + return; + } + Console.WriteLine("Finished init of ctx .... now load in cert and key"); + + if (!File.Exists(fileCert) || !File.Exists(fileKey)) + { + Console.WriteLine("Could not find cert or key file"); + wolfssl.CTX_free(ctx); + return; + } + + if (wolfssl.CTX_use_certificate_file(ctx, fileCert, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error in setting cert file"); + wolfssl.CTX_free(ctx); + return; + } + + if (wolfssl.CTX_use_PrivateKey_file(ctx, fileKey, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error in setting key file"); + wolfssl.CTX_free(ctx); + return; + } + + StringBuilder ciphers = new StringBuilder(new String(' ', 4096)); + wolfssl.get_ciphers(ciphers, 4096); + Console.WriteLine("Ciphers : " + ciphers.ToString()); + + Console.Write("Setting cipher suite to "); + /* To use static PSK build wolfSSL with WOLFSSL_STATIC_PSK preprocessor flag */ + StringBuilder set_cipher = new StringBuilder("PSK-AES128-CBC-SHA256"); + Console.WriteLine(set_cipher); + if (wolfssl.CTX_set_cipher_list(ctx, set_cipher) != wolfssl.SUCCESS) + { + Console.WriteLine("Failed to set cipher suite"); + Console.WriteLine("If using static PSK make sure wolfSSL was built with preprocessor flag WOLFSSL_STATIC_PSK"); + wolfssl.CTX_free(ctx); + return; + } + + /* Test psk use */ + StringBuilder hint = new StringBuilder("cyassl server"); + if (wolfssl.CTX_use_psk_identity_hint(ctx, hint) != wolfssl.SUCCESS) + { + Console.WriteLine("Error setting hint"); + return; + } + wolfssl.CTX_set_psk_server_callback(ctx, psk_cb); + + /* Set using custom IO callbacks + delegate memory is allocated when calling SetIO**** function and freed with ctx free + */ + wolfssl.SetIORecv(ctx, new wolfssl.CallbackIORecv_delegate(wolfSSLCbIORecv)); + wolfssl.SetIOSend(ctx, new wolfssl.CallbackIOSend_delegate(wolfSSLCbIOSend)); + + /* set up TCP socket */ + IPAddress ip = IPAddress.Parse("0.0.0.0"); //bind to any + TcpListener tcp = new TcpListener(ip, 11111); + tcp.Start(); + + Console.WriteLine("Started TCP and waiting for a connection"); + fd = tcp.AcceptSocket(); + ssl = wolfssl.new_ssl(ctx); + + Console.WriteLine("Connection made wolfSSL_accept "); + if (wolfssl.set_fd(ssl, fd) != wolfssl.SUCCESS) + { + /* get and print out the error */ + Console.WriteLine(wolfssl.get_error(ssl)); + tcp.Stop(); + clean(ssl, ctx); + return; + } + + if (wolfssl.accept(ssl) != wolfssl.SUCCESS) + { + /* get and print out the error */ + Console.WriteLine(wolfssl.get_error(ssl)); + tcp.Stop(); + clean(ssl, ctx); + return; + } + + /* print out results of TLS/SSL accept */ + Console.WriteLine("SSL version is " + wolfssl.get_version(ssl)); + Console.WriteLine("SSL cipher suite is " + wolfssl.get_current_cipher(ssl)); + + /* read and print out the message then reply */ + if (wolfssl.read(ssl, buff, 1023) < 0) + { + Console.WriteLine("Error in read"); + tcp.Stop(); + clean(ssl, ctx); + return; + } + Console.WriteLine(buff); + + if (wolfssl.write(ssl, reply, reply.Length) != reply.Length) + { + Console.WriteLine("Error in write"); + tcp.Stop(); + clean(ssl, ctx); + return; + } + + wolfssl.shutdown(ssl); + fd.Close(); + tcp.Stop(); + clean(ssl, ctx); + } +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.csproj b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.csproj new file mode 100644 index 000000000..8b9bd133e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.csproj @@ -0,0 +1,84 @@ + + + + + Debug + AnyCPU + {E2415718-0A15-48DB-A774-01FB0093B626} + Exe + Properties + wolfSSL_Example_IOCallbacks + wolfSSL-Example-IOCallbacks + v4.5 + 512 + + + AnyCPU + true + full + false + ..\DLL Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + ..\DLL Release\ + TRACE + prompt + 4 + + + true + ..\x64\DLL Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + ..\x64\DLL Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + 0 + + + + + + + + + + + + + + + + + + + {52609808-0418-46d3-8e17-141927a1a39a} + wolfSSL_CSharp + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/App.config b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/App.config new file mode 100644 index 000000000..b540b1fdf --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/Properties/AssemblyInfo.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..a1063125b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("wolfSSL-TLS-Client")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("wolfSSL")] +[assembly: AssemblyProduct("wolfSSL-TLS-Client")] +[assembly: AssemblyCopyright("Copyright wolfSSL 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("05aad2b4-445e-4f0e-8e16-8f8512696505")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/Properties/Settings.Designer.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/Properties/Settings.Designer.cs new file mode 100644 index 000000000..524c01375 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.17929 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace wolfSSL_TLS_CSharp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/Properties/Settings.settings b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/Properties/Settings.settings new file mode 100644 index 000000000..049245f40 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/Properties/Settings.settings @@ -0,0 +1,6 @@ + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs new file mode 100644 index 000000000..dcba3568e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs @@ -0,0 +1,210 @@ +/* wolfSSL-TLS-Client.cs + * + * Copyright (C) 2006-2020 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 + */ + + +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.IO; +using System.Net; +using System.Net.Sockets; +using wolfSSL.CSharp; + +public class wolfSSL_TLS_Client +{ + /// + /// Example of a logging function + /// + /// level of log + /// message to log + public static void standard_log(int lvl, StringBuilder msg) + { + Console.WriteLine(msg); + } + + + private static void clean(IntPtr ssl, IntPtr ctx) + { + wolfssl.free(ssl); + wolfssl.CTX_free(ctx); + wolfssl.Cleanup(); + } + + /// + /// Verification callback + /// + /// 1=Verify Okay, 0=Failure + /// Certificate in WOLFSSL_X509_STORE_CTX format + private static int myVerify(int preverify, IntPtr x509_ctx) + { + /* Use the provided verification */ + /* Can optionally override failures by returning non-zero value */ + return preverify; + } + + public static void Main(string[] args) + { + IntPtr ctx; + IntPtr ssl; + Socket tcp; + + /* These paths should be changed for use */ + string caCert = @"ca-cert.pem"; + StringBuilder dhparam = new StringBuilder("dh2048.pem"); + + StringBuilder buff = new StringBuilder(1024); + StringBuilder reply = new StringBuilder("Hello, this is the wolfSSL C# wrapper"); + + //example of function used for setting logging + wolfssl.SetLogging(standard_log); + + wolfssl.Init(); + + + Console.WriteLine("Calling ctx Init from wolfSSL"); + ctx = wolfssl.CTX_new(wolfssl.usev23_client()); + if (ctx == IntPtr.Zero) + { + Console.WriteLine("Error in creating ctx structure"); + return; + } + Console.WriteLine("Finished init of ctx .... now load in CA"); + + + if (!File.Exists(caCert)) + { + Console.WriteLine("Could not find CA cert file"); + wolfssl.CTX_free(ctx); + return; + } + + + if (wolfssl.CTX_load_verify_locations(ctx, caCert, null) + != wolfssl.SUCCESS) + { + Console.WriteLine("Error loading CA cert"); + } + + StringBuilder ciphers = new StringBuilder(new String(' ', 4096)); + wolfssl.get_ciphers(ciphers, 4096); + Console.WriteLine("Ciphers : " + ciphers.ToString()); + + /* Uncomment Section to enable specific cipher suite */ +#if false + ciphers = new StringBuilder("ECDHE-ECDSA-AES128-GCM-SHA256"); + if (wolfssl.CTX_set_cipher_list(ctx, ciphers) != wolfssl.SUCCESS) + { + Console.WriteLine("ERROR CTX_set_cipher_list()"); + wolfssl.CTX_free(ctx); + return; + } +#endif + + short minDhKey = 128; + wolfssl.CTX_SetMinDhKey_Sz(ctx, minDhKey); + + /* Setup Verify Callback */ + if (wolfssl.CTX_set_verify(ctx, wolfssl.SSL_VERIFY_PEER, myVerify) + != wolfssl.SUCCESS) + { + Console.WriteLine("Error setting verify callback!"); + } + + + /* set up TCP socket */ + tcp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, + ProtocolType.Tcp); + try + { + tcp.Connect("localhost", 11111); + } + catch (Exception e) + { + Console.WriteLine("tcp.Connect() error " + e.ToString()); + wolfssl.CTX_free(ctx); + return; + } + if (!tcp.Connected) + { + Console.WriteLine("tcp.Connect() failed!"); + tcp.Close(); + wolfssl.CTX_free(ctx); + return; + } + + Console.WriteLine("Connected TCP"); + ssl = wolfssl.new_ssl(ctx); + if (ssl == IntPtr.Zero) + { + Console.WriteLine("Error in creating ssl object"); + wolfssl.CTX_free(ctx); + return; + } + + Console.WriteLine("Connection made wolfSSL_connect "); + if (wolfssl.set_fd(ssl, tcp) != wolfssl.SUCCESS) + { + /* get and print out the error */ + Console.WriteLine(wolfssl.get_error(ssl)); + tcp.Close(); + clean(ssl, ctx); + return; + } + + wolfssl.SetTmpDH_file(ssl, dhparam, wolfssl.SSL_FILETYPE_PEM); + + if (wolfssl.connect(ssl) != wolfssl.SUCCESS) + { + /* get and print out the error */ + Console.WriteLine(wolfssl.get_error(ssl)); + tcp.Close(); + clean(ssl, ctx); + return; + } + + /* print out results of TLS/SSL accept */ + Console.WriteLine("SSL version is " + wolfssl.get_version(ssl)); + Console.WriteLine("SSL cipher suite is " + wolfssl.get_current_cipher(ssl)); + + + if (wolfssl.write(ssl, reply, reply.Length) != reply.Length) + { + Console.WriteLine("Error in write"); + tcp.Close(); + clean(ssl, ctx); + return; + } + + /* read and print out the message then reply */ + if (wolfssl.read(ssl, buff, 1023) < 0) + { + Console.WriteLine("Error in read"); + tcp.Close(); + clean(ssl, ctx); + return; + } + Console.WriteLine(buff); + + wolfssl.shutdown(ssl); + tcp.Close(); + clean(ssl, ctx); + } +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.csproj b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.csproj new file mode 100644 index 000000000..2959f6f90 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.csproj @@ -0,0 +1,132 @@ + + + + + Debug + AnyCPU + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8} + Exe + Properties + wolfSSL_TLS_Client + wolfSSL-TLS-Client + v4.5 + 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + AnyCPU + true + full + false + ..\DLL Debug\ + DEBUG;TRACE + prompt + 3 + + + AnyCPU + pdbonly + true + ..\DLL Release\ + TRACE + prompt + 4 + + + + + + true + ..\x64\DLL Debug\ + DEBUG;TRACE + 4 + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + ..\x64\DLL Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + + True + True + Settings.settings + + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + {52609808-0418-46d3-8e17-141927a1a39a} + wolfSSL_CSharp + + + + + False + Microsoft .NET Framework 4.5 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/App.config b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/App.config new file mode 100644 index 000000000..fad249e40 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/Properties/AssemblyInfo.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..5704ac236 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("wolfSSL-TLS-PSK-Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("wolfSSL")] +[assembly: AssemblyProduct("wolfSSL-TLS-PSK-Server")] +[assembly: AssemblyCopyright("Copyright wolfSSL 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("1de70ade-16d5-4c90-9657-c19c2762bca6")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.cs new file mode 100644 index 000000000..e8697062a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.cs @@ -0,0 +1,212 @@ +/* wolfSSL-TLS-PSK-Server.cs + * + * Copyright (C) 2006-2020 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 + */ + + +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.IO; +using System.Net; +using System.Net.Sockets; +using wolfSSL.CSharp; + + + +public class wolfSSL_TLS_PSK_Server +{ + + + /// + /// Example of a PSK function call back + /// + /// pointer to ssl structure + /// identity of client connecting + /// buffer to hold key + /// max key size + /// size of key set + public static uint my_psk_server_cb(IntPtr ssl, string identity, IntPtr key, uint max_key) + { + /* perform a check on the identity sent across + * log function must be set for print out of logging information + */ + wolfssl.log(wolfssl.INFO_LOG, "PSK Client Identity = " + identity); + + /* Use desired key, note must be a key smaller than max key size parameter + Replace this with desired key. Is trivial one for testing */ + if (max_key < 4) + return 0; + byte[] tmp = { 26, 43, 60, 77 }; + Marshal.Copy(tmp, 0, key, 4); + + return (uint)4; + } + + + private static void clean(IntPtr ssl, IntPtr ctx) + { + wolfssl.free(ssl); + wolfssl.CTX_free(ctx); + wolfssl.Cleanup(); + } + + + public static void Main(string[] args) + { + IntPtr ctx; + IntPtr ssl; + Socket fd; + + wolfssl.psk_delegate psk_cb = new wolfssl.psk_delegate(my_psk_server_cb); + + /* These paths should be changed according to use */ + string fileCert = @"server-cert.pem"; + string fileKey = @"server-key.pem"; + StringBuilder dhparam = new StringBuilder("dh2048.pem"); + + StringBuilder buff = new StringBuilder(1024); + StringBuilder reply = new StringBuilder("Hello, this is the wolfSSL C# wrapper"); + + wolfssl.Init(); + + Console.WriteLine("Calling ctx Init from wolfSSL"); + ctx = wolfssl.CTX_new(wolfssl.useTLSv1_2_server()); + if (ctx == IntPtr.Zero) + { + Console.WriteLine("Error creating ctx structure"); + return; + } + Console.WriteLine("Finished init of ctx .... now load in cert and key"); + + if (!File.Exists(fileCert) || !File.Exists(fileKey)) + { + Console.WriteLine("Could not find cert or key file"); + wolfssl.CTX_free(ctx); + return; + } + + if (wolfssl.CTX_use_certificate_file(ctx, fileCert, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error in setting cert file"); + wolfssl.CTX_free(ctx); + return; + } + + if (wolfssl.CTX_use_PrivateKey_file(ctx, fileKey, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error in setting key file"); + wolfssl.CTX_free(ctx); + return; + } + + + StringBuilder ciphers = new StringBuilder(new String(' ', 4096)); + wolfssl.get_ciphers(ciphers, 4096); + Console.WriteLine("Ciphers : " + ciphers.ToString()); + + short minDhKey = 128; + wolfssl.CTX_SetMinDhKey_Sz(ctx, minDhKey); + Console.Write("Setting cipher suite to "); + + /* In order to use static PSK build wolfSSL with the preprocessor flag WOLFSSL_STATIC_PSK */ + StringBuilder set_cipher = new StringBuilder("DHE-PSK-AES128-CBC-SHA256"); + Console.WriteLine(set_cipher); + if (wolfssl.CTX_set_cipher_list(ctx, set_cipher) != wolfssl.SUCCESS) + { + Console.WriteLine("Failed to set cipher suite"); + return; + } + + /* Test psk use with DHE */ + StringBuilder hint = new StringBuilder("cyassl server"); + if (wolfssl.CTX_use_psk_identity_hint(ctx, hint) != wolfssl.SUCCESS) + { + Console.WriteLine("Error setting hint"); + wolfssl.CTX_free(ctx); + return; + } + wolfssl.CTX_set_psk_server_callback(ctx, psk_cb); + + /* set up TCP socket */ + IPAddress ip = IPAddress.Parse("0.0.0.0"); //bind to any + TcpListener tcp = new TcpListener(ip, 11111); + tcp.Start(); + + Console.WriteLine("Started TCP and waiting for a connection"); + fd = tcp.AcceptSocket(); + ssl = wolfssl.new_ssl(ctx); + if (ssl == IntPtr.Zero) + { + Console.WriteLine("Error creating ssl object"); + tcp.Stop(); + wolfssl.CTX_free(ctx); + return; + } + + Console.WriteLine("Connection made wolfSSL_accept "); + if (wolfssl.set_fd(ssl, fd) != wolfssl.SUCCESS) + { + /* get and print out the error */ + Console.WriteLine(wolfssl.get_error(ssl)); + tcp.Stop(); + clean(ssl, ctx); + return; + } + + wolfssl.SetTmpDH_file(ssl, dhparam, wolfssl.SSL_FILETYPE_PEM); + + if (wolfssl.accept(ssl) != wolfssl.SUCCESS) + { + /* get and print out the error */ + Console.WriteLine(wolfssl.get_error(ssl)); + tcp.Stop(); + clean(ssl, ctx); + return; + } + + /* print out results of TLS/SSL accept */ + Console.WriteLine("SSL version is " + wolfssl.get_version(ssl)); + Console.WriteLine("SSL cipher suite is " + wolfssl.get_current_cipher(ssl)); + + /* read and print out the message then reply */ + if (wolfssl.read(ssl, buff, 1023) < 0) + { + Console.WriteLine("Error in read"); + tcp.Stop(); + clean(ssl, ctx); + return; + } + Console.WriteLine(buff); + + if (wolfssl.write(ssl, reply, reply.Length) != reply.Length) + { + Console.WriteLine("Error in write"); + tcp.Stop(); + clean(ssl, ctx); + return; + } + + wolfssl.shutdown(ssl); + fd.Close(); + tcp.Stop(); + clean(ssl, ctx); + } +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.csproj b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.csproj new file mode 100644 index 000000000..b9bdf26eb --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.csproj @@ -0,0 +1,87 @@ + + + + + Debug + AnyCPU + {030431C7-26AB-4447-815B-F27E88BE5D5B} + Exe + Properties + wolfSSL_TLS_PSK_Server + wolfSSL-TLS-PSK-Server + v4.5 + 512 + + + AnyCPU + true + full + false + ..\DLL Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + ..\DLL Release\ + TRACE + prompt + 4 + + + true + ..\x64\DLL Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + ..\x64\DLL Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + + + + + + + + {52609808-0418-46d3-8e17-141927a1a39a} + wolfSSL_CSharp + + + + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/App.config b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/App.config new file mode 100644 index 000000000..fad249e40 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/Properties/AssemblyInfo.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..ef8b02522 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("wolfSSL-TLS-Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("wolfSSL")] +[assembly: AssemblyProduct("wolfSSL-TLS-Server")] +[assembly: AssemblyCopyright("Copyright wolfSSL 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("716e8f30-1318-4e3b-b788-d0380b397a4c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/Properties/Settings.Designer.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/Properties/Settings.Designer.cs new file mode 100644 index 000000000..6409d3ec6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.17929 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace wolfSSL_TLS_CSharp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/Properties/Settings.settings b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/Properties/Settings.settings new file mode 100644 index 000000000..15034e76c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/Properties/Settings.settings @@ -0,0 +1,6 @@ + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs new file mode 100644 index 000000000..262bd74be --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs @@ -0,0 +1,173 @@ +/* wolfSSL-TLS-Server.cs + * + * Copyright (C) 2006-2020 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 + */ + + +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.IO; +using System.Net; +using System.Net.Sockets; +using wolfSSL.CSharp; + +public class wolfSSL_TLS_CSHarp +{ + /// + /// Example of a logging function + /// + /// level of log + /// message to log + public static void standard_log(int lvl, StringBuilder msg) + { + Console.WriteLine(msg); + } + + + private static void clean(IntPtr ssl, IntPtr ctx) + { + wolfssl.free(ssl); + wolfssl.CTX_free(ctx); + wolfssl.Cleanup(); + } + + + public static void Main(string[] args) + { + IntPtr ctx; + IntPtr ssl; + Socket fd; + + /* These paths should be changed for use */ + string fileCert = @"server-cert.pem"; + string fileKey = @"server-key.pem"; + StringBuilder dhparam = new StringBuilder("dh2048.pem"); + + StringBuilder buff = new StringBuilder(1024); + StringBuilder reply = new StringBuilder("Hello, this is the wolfSSL C# wrapper"); + + //example of function used for setting logging + wolfssl.SetLogging(standard_log); + + wolfssl.Init(); + + + Console.WriteLine("Calling ctx Init from wolfSSL"); + ctx = wolfssl.CTX_new(wolfssl.usev23_server()); + if (ctx == IntPtr.Zero) + { + Console.WriteLine("Error in creating ctx structure"); + return; + } + Console.WriteLine("Finished init of ctx .... now load in cert and key"); + + if (!File.Exists(fileCert) || !File.Exists(fileKey)) + { + Console.WriteLine("Could not find cert or key file"); + wolfssl.CTX_free(ctx); + return; + } + + if (wolfssl.CTX_use_certificate_file(ctx, fileCert, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error in setting cert file"); + wolfssl.CTX_free(ctx); + return; + } + + if (wolfssl.CTX_use_PrivateKey_file(ctx, fileKey, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error in setting key file"); + wolfssl.CTX_free(ctx); + return; + } + + + StringBuilder ciphers = new StringBuilder(new String(' ', 4096)); + wolfssl.get_ciphers(ciphers, 4096); + Console.WriteLine("Ciphers : " + ciphers.ToString()); + + short minDhKey = 128; + wolfssl.CTX_SetMinDhKey_Sz(ctx, minDhKey); + + /* set up TCP socket */ + IPAddress ip = IPAddress.Parse("0.0.0.0"); /* bind to any */ + TcpListener tcp = new TcpListener(ip, 11111); + tcp.Start(); + + Console.WriteLine("Started TCP and waiting for a connection"); + fd = tcp.AcceptSocket(); + ssl = wolfssl.new_ssl(ctx); + if (ssl == IntPtr.Zero) + { + Console.WriteLine("Error in creating ssl object"); + wolfssl.CTX_free(ctx); + return; + } + + Console.WriteLine("Connection made wolfSSL_accept "); + if (wolfssl.set_fd(ssl, fd) != wolfssl.SUCCESS) + { + /* get and print out the error */ + Console.WriteLine(wolfssl.get_error(ssl)); + tcp.Stop(); + clean(ssl, ctx); + return; + } + + wolfssl.SetTmpDH_file(ssl, dhparam, wolfssl.SSL_FILETYPE_PEM); + + if (wolfssl.accept(ssl) != wolfssl.SUCCESS) + { + /* get and print out the error */ + Console.WriteLine(wolfssl.get_error(ssl)); + tcp.Stop(); + clean(ssl, ctx); + return; + } + + /* print out results of TLS/SSL accept */ + Console.WriteLine("SSL version is " + wolfssl.get_version(ssl)); + Console.WriteLine("SSL cipher suite is " + wolfssl.get_current_cipher(ssl)); + + /* read and print out the message then reply */ + if (wolfssl.read(ssl, buff, 1023) < 0) + { + Console.WriteLine("Error in read"); + tcp.Stop(); + clean(ssl, ctx); + return; + } + Console.WriteLine(buff); + + if (wolfssl.write(ssl, reply, reply.Length) != reply.Length) + { + Console.WriteLine("Error in write"); + tcp.Stop(); + clean(ssl, ctx); + return; + } + + wolfssl.shutdown(ssl); + fd.Close(); + tcp.Stop(); + clean(ssl, ctx); + } +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.csproj b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.csproj new file mode 100644 index 000000000..7ab3a6f07 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.csproj @@ -0,0 +1,132 @@ + + + + + Debug + AnyCPU + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2} + Exe + Properties + wolfSSL_TLS_Server + wolfSSL-TLS-Server + v4.5 + 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + AnyCPU + true + full + false + ..\DLL Debug\ + DEBUG;TRACE + prompt + 3 + + + AnyCPU + pdbonly + true + ..\DLL Release\ + TRACE + prompt + 4 + + + + + + true + ..\x64\DLL Debug\ + DEBUG;TRACE + 4 + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + ..\x64\DLL Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + + True + True + Settings.settings + + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + {52609808-0418-46d3-8e17-141927a1a39a} + wolfSSL_CSharp + + + + + False + Microsoft .NET Framework 4.5 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/App.config b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/App.config new file mode 100644 index 000000000..8e1564635 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/AssemblyInfo.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..e786a4dd2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("wolfSSL-TLS-Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("wolfSSL")] +[assembly: AssemblyProduct("wolfSSL-TLS-Server")] +[assembly: AssemblyCopyright("Copyright wolfSSL 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("716e8f30-1318-4e3b-b788-d0380b397a4c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/Settings.Designer.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/Settings.Designer.cs new file mode 100644 index 000000000..524c01375 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.17929 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace wolfSSL_TLS_CSharp.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/Settings.settings b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/Settings.settings new file mode 100644 index 000000000..049245f40 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/Settings.settings @@ -0,0 +1,6 @@ + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.cs new file mode 100644 index 000000000..2f9da4e24 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.cs @@ -0,0 +1,194 @@ +/* wolfSSL-TLS-ServerThreaded.cs + * + * Copyright (C) 2006-2020 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 + */ + + +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Threading; + +using wolfSSL.CSharp; + +public class wolfSSL_TLS_ServerThread +{ + private IntPtr _ctx; + private Socket _fd; + + public wolfSSL_TLS_ServerThread(IntPtr ctx, Socket fd) + { + _ctx = ctx; + _fd = fd; + } + + private const int kEchoBufSz = 1024; + public void start_client() + { + StringBuilder buff = new StringBuilder(kEchoBufSz); + IntPtr ssl = wolfssl.new_ssl(_ctx); + if (ssl == IntPtr.Zero) + { + Console.WriteLine("Error in creating ssl object"); + return; + } + + if (wolfssl.set_fd(ssl, _fd) != wolfssl.SUCCESS) + { + /* get and print out the error */ + Console.WriteLine(wolfssl.get_error(ssl)); + _fd.Close(); + wolfssl.free(ssl); + return; + } + + Console.WriteLine("Starting TLS handshake"); + if (wolfssl.accept(ssl) != wolfssl.SUCCESS) + { + /* get and print out the error */ + Console.WriteLine("Failed " + wolfssl.get_error(ssl)); + _fd.Close(); + wolfssl.free(ssl); + return; + } + + /* print out results of TLS/SSL accept */ + Console.WriteLine("SSL version is " + wolfssl.get_version(ssl)); + Console.WriteLine("SSL cipher suite is " + wolfssl.get_current_cipher(ssl)); + + /* echo data until error */ + while (true) + { + /* read and print out the message then reply */ + if (wolfssl.read(ssl, buff, kEchoBufSz-1) < 0) + { + Console.WriteLine("Error in read"); + break; + } + Console.WriteLine(buff); + + if (wolfssl.write(ssl, buff, buff.Length) != buff.Length) + { + Console.WriteLine("Error in write"); + break; + } + } + + Console.WriteLine("Closing " + wolfssl.get_error(ssl)); + _fd.Close(); + wolfssl.free(ssl); + } +} + +public class wolfSSL_TLS_ServerThreaded +{ + /// + /// Example of a logging function + /// + /// level of log + /// message to log + public static void standard_log(int lvl, StringBuilder msg) + { + Console.WriteLine(msg); + } + + public static void Main(string[] args) + { + IntPtr ctx; + + /* These paths should be changed for use */ + string fileCert = @"server-cert.pem"; + string fileKey = @"server-key.pem"; + StringBuilder dhparam = new StringBuilder("dh2048.pem"); + + /* example of function used for setting logging */ + wolfssl.SetLogging(standard_log); + wolfssl.Init(); + + Console.WriteLine("Calling ctx Init from wolfSSL"); + ctx = wolfssl.CTX_new(wolfssl.usev23_server()); + if (ctx == IntPtr.Zero) + { + Console.WriteLine("Error in creating ctx structure"); + return; + } + Console.WriteLine("Finished init of ctx .... now load in cert and key"); + + if (!File.Exists(fileCert) || !File.Exists(fileKey)) + { + Console.WriteLine("Could not find cert or key file"); + wolfssl.CTX_free(ctx); + return; + } + + if (wolfssl.CTX_use_certificate_file(ctx, fileCert, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error in setting cert file"); + wolfssl.CTX_free(ctx); + return; + } + + if (wolfssl.CTX_use_PrivateKey_file(ctx, fileKey, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS) + { + Console.WriteLine("Error in setting key file"); + wolfssl.CTX_free(ctx); + return; + } + + StringBuilder ciphers = new StringBuilder(new String(' ', 4096)); + wolfssl.get_ciphers(ciphers, 4096); + Console.WriteLine("Ciphers : " + ciphers.ToString()); + + short minDhKey = 128; + wolfssl.CTX_SetMinDhKey_Sz(ctx, minDhKey); + wolfssl.CTX_SetTmpDH_file(ctx, dhparam, wolfssl.SSL_FILETYPE_PEM); + + /* set up TCP socket */ + IPAddress ip = IPAddress.Parse("0.0.0.0"); /* bind to any */ + TcpListener tcp = new TcpListener(ip, 11111); + tcp.Start(); + + Console.WriteLine("Started TCP and waiting for a connection"); + + while (true) { + try + { + Socket fd = tcp.AcceptSocket(); + Console.WriteLine("Got client connection"); + + /* Spin up thread for client */ + wolfSSL_TLS_ServerThread thread = new wolfSSL_TLS_ServerThread(ctx, fd); + Thread thr = new Thread(new ThreadStart(thread.start_client)); + thr.Start(); + } + catch(Exception ex) + { + Console.WriteLine("Server Exception " + ex.ToString()); + break; + } + } + + tcp.Stop(); + wolfssl.CTX_free(ctx); + wolfssl.Cleanup(); + } +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.csproj b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.csproj new file mode 100644 index 000000000..bbbe57a4e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.csproj @@ -0,0 +1,132 @@ + + + + + Debug + AnyCPU + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F} + Exe + Properties + wolfSSL_TLS_ServerThreaded + wolfSSL-TLS-ServerThreaded + v4.5 + 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + AnyCPU + true + full + false + ..\DLL Debug\ + DEBUG;TRACE + prompt + 3 + + + AnyCPU + pdbonly + true + ..\DLL Release\ + TRACE + prompt + 4 + + + + + + true + ..\x64\DLL Debug\ + DEBUG;TRACE + 4 + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + ..\x64\DLL Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + + True + True + Settings.settings + + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + {52609808-0418-46d3-8e17-141927a1a39a} + wolfSSL_CSharp + + + + + False + Microsoft .NET Framework 4.5 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp.sln b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp.sln new file mode 100644 index 000000000..f3b4dc707 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp.sln @@ -0,0 +1,173 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL_CSharp", "wolfSSL_CSharp\wolfSSL_CSharp.csproj", "{52609808-0418-46D3-8E17-141927A1A39A}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL-TLS-Server", "wolfSSL-TLS-Server\wolfSSL-TLS-Server.csproj", "{8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL-TLS-PSK-Server", "wolfSSL-TLS-PSK-Server\wolfSSL-TLS-PSK-Server.csproj", "{030431C7-26AB-4447-815B-F27E88BE5D5B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL-DTLS-Server", "wolfSSL-DTLS-Server\wolfSSL-DTLS-Server.csproj", "{730F047E-37A6-498F-A543-B6C98AA7B338}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL-DTLS-PSK-Server", "wolfSSL-DTLS-PSK-Server\wolfSSL-DTLS-PSK-Server.csproj", "{77AEF1BE-4BE3-4837-8188-2A06E4D963F5}" + ProjectSection(ProjectDependencies) = postProject + {52609808-0418-46D3-8E17-141927A1A39A} = {52609808-0418-46D3-8E17-141927A1A39A} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wolfSSL", "wolfSSL", "{252D09D0-D007-4AEB-9F7A-A74408039A8A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfssl", "..\..\wolfssl.vcxproj", "{73973223-5EE8-41CA-8E88-1D60E89A237B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsuite", "..\..\testsuite\testsuite.vcxproj", "{611E8971-46E0-4D0A-B5A1-632C3B00CB80}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL-Example-IOCallbacks", "wolfSSL-Example-IOCallbacks\wolfSSL-Example-IOCallbacks.csproj", "{E2415718-0A15-48DB-A774-01FB0093B626}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL-TLS-Client", "wolfSSL-TLS-Client\wolfSSL-TLS-Client.csproj", "{B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wolfSSL-TLS-ServerThreaded", "wolfSSL-TLS-ServerThreaded\wolfSSL-TLS-ServerThreaded.csproj", "{8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DLL Debug|Any CPU = DLL Debug|Any CPU + DLL Debug|Win32 = DLL Debug|Win32 + DLL Debug|x64 = DLL Debug|x64 + DLL Release|Any CPU = DLL Release|Any CPU + DLL Release|Win32 = DLL Release|Win32 + DLL Release|x64 = DLL Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {52609808-0418-46D3-8E17-141927A1A39A}.DLL Debug|Any CPU.ActiveCfg = Debug|Any CPU + {52609808-0418-46D3-8E17-141927A1A39A}.DLL Debug|Any CPU.Build.0 = Debug|Any CPU + {52609808-0418-46D3-8E17-141927A1A39A}.DLL Debug|Win32.ActiveCfg = Debug|Any CPU + {52609808-0418-46D3-8E17-141927A1A39A}.DLL Debug|Win32.Build.0 = Debug|Any CPU + {52609808-0418-46D3-8E17-141927A1A39A}.DLL Debug|x64.ActiveCfg = Debug|x64 + {52609808-0418-46D3-8E17-141927A1A39A}.DLL Debug|x64.Build.0 = Debug|x64 + {52609808-0418-46D3-8E17-141927A1A39A}.DLL Release|Any CPU.ActiveCfg = Release|Any CPU + {52609808-0418-46D3-8E17-141927A1A39A}.DLL Release|Any CPU.Build.0 = Release|Any CPU + {52609808-0418-46D3-8E17-141927A1A39A}.DLL Release|Win32.ActiveCfg = Release|Any CPU + {52609808-0418-46D3-8E17-141927A1A39A}.DLL Release|Win32.Build.0 = Release|Any CPU + {52609808-0418-46D3-8E17-141927A1A39A}.DLL Release|x64.ActiveCfg = Release|x64 + {52609808-0418-46D3-8E17-141927A1A39A}.DLL Release|x64.Build.0 = Release|x64 + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}.DLL Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}.DLL Debug|Any CPU.Build.0 = Debug|Any CPU + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}.DLL Debug|Win32.ActiveCfg = Debug|Any CPU + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}.DLL Debug|Win32.Build.0 = Debug|Any CPU + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}.DLL Debug|x64.ActiveCfg = Debug|x64 + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}.DLL Debug|x64.Build.0 = Debug|x64 + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}.DLL Release|Any CPU.ActiveCfg = Release|Any CPU + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}.DLL Release|Any CPU.Build.0 = Release|Any CPU + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}.DLL Release|Win32.ActiveCfg = Release|Any CPU + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}.DLL Release|Win32.Build.0 = Release|Any CPU + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}.DLL Release|x64.ActiveCfg = Release|x64 + {8921AD35-4E62-4DAC-8FEE-8C9F8E57DDD2}.DLL Release|x64.Build.0 = Release|x64 + {030431C7-26AB-4447-815B-F27E88BE5D5B}.DLL Debug|Any CPU.ActiveCfg = Debug|Any CPU + {030431C7-26AB-4447-815B-F27E88BE5D5B}.DLL Debug|Any CPU.Build.0 = Debug|Any CPU + {030431C7-26AB-4447-815B-F27E88BE5D5B}.DLL Debug|Win32.ActiveCfg = Debug|Any CPU + {030431C7-26AB-4447-815B-F27E88BE5D5B}.DLL Debug|Win32.Build.0 = Debug|Any CPU + {030431C7-26AB-4447-815B-F27E88BE5D5B}.DLL Debug|x64.ActiveCfg = Debug|x64 + {030431C7-26AB-4447-815B-F27E88BE5D5B}.DLL Debug|x64.Build.0 = Debug|x64 + {030431C7-26AB-4447-815B-F27E88BE5D5B}.DLL Release|Any CPU.ActiveCfg = Release|Any CPU + {030431C7-26AB-4447-815B-F27E88BE5D5B}.DLL Release|Any CPU.Build.0 = Release|Any CPU + {030431C7-26AB-4447-815B-F27E88BE5D5B}.DLL Release|Win32.ActiveCfg = Release|Any CPU + {030431C7-26AB-4447-815B-F27E88BE5D5B}.DLL Release|Win32.Build.0 = Release|Any CPU + {030431C7-26AB-4447-815B-F27E88BE5D5B}.DLL Release|x64.ActiveCfg = Release|x64 + {030431C7-26AB-4447-815B-F27E88BE5D5B}.DLL Release|x64.Build.0 = Release|x64 + {730F047E-37A6-498F-A543-B6C98AA7B338}.DLL Debug|Any CPU.ActiveCfg = Debug|Any CPU + {730F047E-37A6-498F-A543-B6C98AA7B338}.DLL Debug|Any CPU.Build.0 = Debug|Any CPU + {730F047E-37A6-498F-A543-B6C98AA7B338}.DLL Debug|Win32.ActiveCfg = Debug|Any CPU + {730F047E-37A6-498F-A543-B6C98AA7B338}.DLL Debug|Win32.Build.0 = Debug|Any CPU + {730F047E-37A6-498F-A543-B6C98AA7B338}.DLL Debug|x64.ActiveCfg = Debug|x64 + {730F047E-37A6-498F-A543-B6C98AA7B338}.DLL Debug|x64.Build.0 = Debug|x64 + {730F047E-37A6-498F-A543-B6C98AA7B338}.DLL Release|Any CPU.ActiveCfg = Release|Any CPU + {730F047E-37A6-498F-A543-B6C98AA7B338}.DLL Release|Any CPU.Build.0 = Release|Any CPU + {730F047E-37A6-498F-A543-B6C98AA7B338}.DLL Release|Win32.ActiveCfg = Release|Any CPU + {730F047E-37A6-498F-A543-B6C98AA7B338}.DLL Release|Win32.Build.0 = Release|Any CPU + {730F047E-37A6-498F-A543-B6C98AA7B338}.DLL Release|x64.ActiveCfg = Release|x64 + {730F047E-37A6-498F-A543-B6C98AA7B338}.DLL Release|x64.Build.0 = Release|x64 + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Debug|Any CPU.ActiveCfg = Debug|Any CPU + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Debug|Any CPU.Build.0 = Debug|Any CPU + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Debug|Win32.ActiveCfg = Debug|Any CPU + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Debug|Win32.Build.0 = Debug|Any CPU + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Debug|x64.ActiveCfg = Debug|x64 + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Debug|x64.Build.0 = Debug|x64 + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Release|Any CPU.ActiveCfg = Release|Any CPU + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Release|Any CPU.Build.0 = Release|Any CPU + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Release|Win32.ActiveCfg = Release|Any CPU + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Release|Win32.Build.0 = Release|Any CPU + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Release|x64.ActiveCfg = Release|x64 + {77AEF1BE-4BE3-4837-8188-2A06E4D963F5}.DLL Release|x64.Build.0 = Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Any CPU.ActiveCfg = DLL Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Any CPU.Build.0 = DLL Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Any CPU.ActiveCfg = DLL Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Any CPU.Build.0 = DLL Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|x64.Build.0 = DLL Release|x64 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|Any CPU.ActiveCfg = DLL Debug|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|Any CPU.Build.0 = DLL Debug|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|Any CPU.ActiveCfg = DLL Release|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|Any CPU.Build.0 = DLL Release|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|x64.Build.0 = DLL Release|x64 + {E2415718-0A15-48DB-A774-01FB0093B626}.DLL Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2415718-0A15-48DB-A774-01FB0093B626}.DLL Debug|Any CPU.Build.0 = Debug|Any CPU + {E2415718-0A15-48DB-A774-01FB0093B626}.DLL Debug|Win32.ActiveCfg = Debug|Any CPU + {E2415718-0A15-48DB-A774-01FB0093B626}.DLL Debug|Win32.Build.0 = Debug|Any CPU + {E2415718-0A15-48DB-A774-01FB0093B626}.DLL Debug|x64.ActiveCfg = Debug|x64 + {E2415718-0A15-48DB-A774-01FB0093B626}.DLL Debug|x64.Build.0 = Debug|x64 + {E2415718-0A15-48DB-A774-01FB0093B626}.DLL Release|Any CPU.ActiveCfg = Release|Any CPU + {E2415718-0A15-48DB-A774-01FB0093B626}.DLL Release|Any CPU.Build.0 = Release|Any CPU + {E2415718-0A15-48DB-A774-01FB0093B626}.DLL Release|Win32.ActiveCfg = Release|Any CPU + {E2415718-0A15-48DB-A774-01FB0093B626}.DLL Release|Win32.Build.0 = Release|Any CPU + {E2415718-0A15-48DB-A774-01FB0093B626}.DLL Release|x64.ActiveCfg = Release|x64 + {E2415718-0A15-48DB-A774-01FB0093B626}.DLL Release|x64.Build.0 = Release|x64 + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}.DLL Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}.DLL Debug|Any CPU.Build.0 = Debug|Any CPU + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}.DLL Debug|Win32.ActiveCfg = Debug|Any CPU + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}.DLL Debug|Win32.Build.0 = Debug|Any CPU + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}.DLL Debug|x64.ActiveCfg = Debug|x64 + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}.DLL Debug|x64.Build.0 = Debug|x64 + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}.DLL Release|Any CPU.ActiveCfg = Release|Any CPU + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}.DLL Release|Any CPU.Build.0 = Release|Any CPU + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}.DLL Release|Win32.ActiveCfg = Release|Any CPU + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}.DLL Release|Win32.Build.0 = Release|Any CPU + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}.DLL Release|x64.ActiveCfg = Release|x64 + {B9DF2972-38F6-4B42-B228-E3C1A47DF8E8}.DLL Release|x64.Build.0 = Release|x64 + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}.DLL Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}.DLL Debug|Any CPU.Build.0 = Debug|Any CPU + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}.DLL Debug|Win32.ActiveCfg = Debug|Any CPU + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}.DLL Debug|Win32.Build.0 = Debug|Any CPU + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}.DLL Debug|x64.ActiveCfg = Debug|x64 + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}.DLL Debug|x64.Build.0 = Debug|x64 + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}.DLL Release|Any CPU.ActiveCfg = Release|Any CPU + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}.DLL Release|Any CPU.Build.0 = Release|Any CPU + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}.DLL Release|Win32.ActiveCfg = Release|Any CPU + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}.DLL Release|Win32.Build.0 = Release|Any CPU + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}.DLL Release|x64.ActiveCfg = Release|x64 + {8ABD2E8F-AEE7-40ED-A966-900ACFAE555F}.DLL Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {252D09D0-D007-4AEB-9F7A-A74408039A8A} + {611E8971-46E0-4D0A-B5A1-632C3B00CB80} = {252D09D0-D007-4AEB-9F7A-A74408039A8A} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {63D316F8-C4EE-449A-B9A6-FC673C4D5D31} + EndGlobalSection +EndGlobal diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/Properties/AssemblyInfo.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..d34afd6b9 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("wolfSSL.CSharp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("wolfSSL")] +[assembly: AssemblyProduct("wolfSSL.CSharp")] +[assembly: AssemblyCopyright("Copyright wolfSSL 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b50b8d16-ff19-4ea4-8881-13cf972765db")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.Designer.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.Designer.cs new file mode 100644 index 000000000..dd0327fd4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.17929 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace wolfssl_wrapper.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("wolfSSL.CSharp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.resx b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.resx new file mode 100644 index 000000000..85c909092 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs new file mode 100644 index 000000000..7acbe77ea --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs @@ -0,0 +1,1889 @@ +/* wolfSSL.cs + * + * Copyright (C) 2006-2020 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 + */ + +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.IO; +using System.Net; +using System.Net.Sockets; + +namespace wolfSSL.CSharp { + public class wolfssl + { + private const string wolfssl_dll = "wolfssl.dll"; + + /* wait for 6 seconds default on TCP socket state poll if timeout not set */ + private const int WC_WAIT = 6000000; + + /******************************** + * Class for DTLS connections + */ + /// + /// Contains information regarding a DTLS connection having UdpClient udp and IPEndPoint ep. + /// Used to keep memory alive. + /// + public class DTLS_con + { + public UdpClient udp; + public IPEndPoint ep; + } + + + /******************************** + * Class for keeping ctx handles alive + */ + [StructLayout(LayoutKind.Sequential)] + private class ctx_handle + { + private GCHandle rec_cb; + private GCHandle snd_cb; + private GCHandle psk_cb; + private IntPtr ctx; + + public void set_receive(GCHandle input) + { + this.rec_cb = input; + } + public GCHandle get_receive() + { + return this.rec_cb; + } + + public void set_send(GCHandle input) + { + this.snd_cb = input; + } + public GCHandle get_send() + { + return this.snd_cb; + } + + public void set_psk(GCHandle input) + { + this.psk_cb = input; + } + public GCHandle get_psk() + { + return this.psk_cb; + } + + public void set_ctx(IntPtr input) + { + this.ctx = input; + } + public IntPtr get_ctx() + { + return this.ctx; + } + + /// + /// Called to free the pointers keeping handles alive + /// + public void free() + { + log(INFO_LOG, "freeing ctx handle"); + if (!Object.Equals(this.rec_cb, default(GCHandle))) + { + this.rec_cb.Free(); + } + if (!Object.Equals(this.snd_cb, default(GCHandle))) + { + this.snd_cb.Free(); + } + if (!Object.Equals(this.psk_cb, default(GCHandle))) + { + this.psk_cb.Free(); + } + } + } + + /******************************** + * Class for keeping ssl handle alive + */ + [StructLayout(LayoutKind.Sequential)] + private class ssl_handle + { + private GCHandle fd_pin; + private GCHandle psk_cb; + private IntPtr ssl; + + public void set_fd(GCHandle input) + { + this.fd_pin = input; + } + public GCHandle get_fd() + { + return this.fd_pin; + } + + public void set_psk(GCHandle input) + { + this.psk_cb = input; + } + public GCHandle get_psk() + { + return this.psk_cb; + } + + public void set_ssl(IntPtr input) + { + this.ssl = input; + } + public IntPtr get_ssl() + { + return this.ssl; + } + public void free() + { + log(INFO_LOG, "freeing ssl handle"); + + if (!Object.Equals(this.fd_pin, default(GCHandle))) + { + this.fd_pin.Free(); + } + if (!Object.Equals(this.psk_cb, default(GCHandle))) + { + this.psk_cb.Free(); + } + } + } + + + /******************************** + * Init wolfSSL library + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_Init(); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_Cleanup(); + + + /******************************** + * Methods of connection + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfTLSv1_2_server_method(); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfTLSv1_3_server_method(); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfSSLv23_server_method(); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfTLSv1_2_client_method(); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfTLSv1_3_client_method(); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfSSLv23_client_method(); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfDTLSv1_2_server_method(); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfDTLSv1_2_client_method(); + + + /******************************** + * Call backs + */ + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int CallbackIORecv_delegate(IntPtr ssl, IntPtr buf, int sz, IntPtr ctx); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_CTX_SetIORecv(IntPtr ctx, CallbackIORecv_delegate recv); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_SetIOReadCtx(IntPtr ssl, IntPtr rctx); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfSSL_GetIOReadCtx(IntPtr ssl); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int CallbackIOSend_delegate(IntPtr ssl, IntPtr buf, int sz, IntPtr ctx); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_CTX_SetIOSend(IntPtr ctx, CallbackIOSend_delegate send); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_SetIOWriteCtx(IntPtr ssl, IntPtr wctx); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfSSL_GetIOWriteCtx(IntPtr ssl); + + + /******************************** + * CTX structure + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfSSL_CTX_new(IntPtr method); + [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); + + + + /******************************** + * PSK + */ + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate uint psk_delegate(IntPtr ssl, string identity, IntPtr key, uint max_sz); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate uint psk_client_delegate(IntPtr ssl, string hint, IntPtr identity, uint id_max_len, IntPtr key, uint max_sz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static void wolfSSL_set_psk_server_callback(IntPtr ssl, psk_delegate psk_cb); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static void wolfSSL_CTX_set_psk_server_callback(IntPtr ctx, psk_delegate psk_cb); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static void wolfSSL_CTX_set_psk_client_callback(IntPtr ctx, psk_client_delegate psk_cb); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_CTX_use_psk_identity_hint(IntPtr ctx, StringBuilder identity); + + + /******************************** + * SSL Structure + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfSSL_new(IntPtr ctx); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_accept(IntPtr ssl); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_connect(IntPtr ssl); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_read(IntPtr ssl, IntPtr buf, int sz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_write(IntPtr ssl, IntPtr buf, int sz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_shutdown(IntPtr ssl); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static void wolfSSL_free(IntPtr ssl); + + + /******************************** + * Cipher lists + */ + /* only supports full name from cipher_name[] delimited by : */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_CTX_set_cipher_list(IntPtr ctx, StringBuilder ciphers); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_set_cipher_list(IntPtr ssl, StringBuilder ciphers); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_get_ciphers(StringBuilder ciphers, int sz); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfSSL_get_cipher(IntPtr ssl); + [DllImport(wolfssl_dll, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfSSL_CIPHER_get_name(IntPtr cipher); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfSSL_get_current_cipher(IntPtr ssl); + [DllImport(wolfssl_dll, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfSSL_get_version(IntPtr ssl); + [DllImport(wolfssl_dll, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] + private extern static IntPtr wolfSSL_get_cipher_list(IntPtr ssl); + + + /******************************** + * Error logging + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl, CharSet=CharSet.Ansi)] + private extern static IntPtr wolfSSL_ERR_error_string(uint err, StringBuilder errOut); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_get_error(IntPtr ssl, int err); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void loggingCb(int lvl, StringBuilder msg); + private static loggingCb internal_log; + + + /******************************** + * DH + */ + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_CTX_SetMinDhKey_Sz(IntPtr ctx, short size); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_SetTmpDH_file(IntPtr ssl, StringBuilder dhParam, int type); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_CTX_SetTmpDH_file(IntPtr ctx, StringBuilder dhParam, int type); + + + /******************************** + * Verify Callback + */ + public delegate int CallbackVerify_delegate(int ret, IntPtr x509_ctx); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static void wolfSSL_CTX_set_verify(IntPtr ctx, int mode, CallbackVerify_delegate vc); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static void wolfSSL_set_verify(IntPtr ssl, int mode, CallbackVerify_delegate vc); + + + /******************************** + * Enum types from wolfSSL library + */ + public static readonly int SSL_FILETYPE_PEM = 1; + public static readonly int SSL_FILETYPE_ASN1= 2; + public static readonly int SSL_FILETYPE_RAW = 3; + + public static readonly int SSL_VERIFY_NONE = 0; + public static readonly int SSL_VERIFY_PEER = 1; + public static readonly int SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2; + public static readonly int SSL_VERIFY_CLIENT_ONCE = 4; + public static readonly int SSL_VERIFY_FAIL_EXCEPT_PSK = 8; + + public static readonly int CBIO_ERR_GENERAL = -1; + public static readonly int CBIO_ERR_WANT_READ = -2; + public static readonly int CBIO_ERR_WANT_WRITE = -2; + public static readonly int CBIO_ERR_CONN_RST = -3; + public static readonly int CBIO_ERR_ISR = -4; + public static readonly int CBIO_ERR_CONN_CLOSE = -5; + public static readonly int CBIO_ERR_TIMEOUT = -6; + + public static readonly int ERROR_LOG = 0; + public static readonly int INFO_LOG = 1; + public static readonly int ENTER_LOG = 2; + public static readonly int LEAVE_LOG = 3; + public static readonly int OTHER_LOG = 4; + + public static readonly int SUCCESS = 1; + public static readonly int FAILURE = 0; + + + private static IntPtr unwrap_ctx(IntPtr ctx) + { + try { + GCHandle gch = GCHandle.FromIntPtr(ctx); + ctx_handle handles = (ctx_handle)gch.Target; + return handles.get_ctx(); + } catch (Exception e) + { + log(ERROR_LOG, "wolfssl ctx pointer is incorrect " + e); + return IntPtr.Zero; + } + } + private static IntPtr unwrap_ssl(IntPtr ssl) + { + try { + GCHandle gch = GCHandle.FromIntPtr(ssl); + ssl_handle handles = (ssl_handle)gch.Target; + return handles.get_ssl(); + } catch (Exception e) + { + log(ERROR_LOG, "wolfssl pointer is incorrect " + e); + return IntPtr.Zero; + } + } + + + /// + /// Call back to allow receiving TLS information + /// + /// structure of ssl passed in + /// buffer to contain received msg + /// size of buffer + /// optional information passed in + /// size of message received + private static int wolfSSLCbIORecv(IntPtr ssl, IntPtr buf, int sz, IntPtr ctx) + { + if (sz <= 0) + { + log(ERROR_LOG, "wolfssl receive error, size less than 0"); + return wolfssl.CBIO_ERR_GENERAL; + } + + int amtRecv = 0; + + try + { + System.Runtime.InteropServices.GCHandle gch; + gch = GCHandle.FromIntPtr(ctx); + Socket con = (System.Net.Sockets.Socket)gch.Target; + Byte[] msg = new Byte[sz]; + amtRecv = con.Receive(msg, msg.Length, 0); + if (amtRecv == 0) + { + /* No data received so check for a response to see if connection is still open */ + if (con.Poll((con.ReceiveTimeout > 0) ? con.ReceiveTimeout : WC_WAIT, SelectMode.SelectRead)) + { + log(ERROR_LOG, "socket connection issue, suspected connection termination."); + return wolfssl.CBIO_ERR_CONN_CLOSE; + } + } + Marshal.Copy(msg, 0, buf, sz); + } + catch (Exception e) + { + log(ERROR_LOG, "Error in receive " + e.ToString()); + return wolfssl.CBIO_ERR_CONN_CLOSE; + } + + return amtRecv; + } + + + /// + /// Call back used for sending TLS information + /// + /// pointer to ssl struct + /// buffer containing information to send + /// size of buffer to send + /// optional information + /// amount of information sent + private static int wolfSSLCbIOSend(IntPtr ssl, IntPtr buf, int sz, IntPtr ctx) + { + if (sz <= 0) + { + log(ERROR_LOG, "wolfssl send error, size less than 0"); + return wolfssl.CBIO_ERR_GENERAL; + } + + try + { + System.Runtime.InteropServices.GCHandle gch; + gch = GCHandle.FromIntPtr(ctx); + + Socket con = (System.Net.Sockets.Socket)gch.Target; + Byte[] msg = new Byte[sz]; + Marshal.Copy(buf, msg, 0, sz); + if (con.Send(msg, 0, msg.Length, SocketFlags.None) == 0 && sz !=0) + { + /* no data sent and msg size is larger then 0, check for lost connection */ + if (con.Poll((con.SendTimeout > 0) ? con.SendTimeout : WC_WAIT, SelectMode.SelectWrite)) + { + log(ERROR_LOG, "socket connection issue, suspect connection termination"); + return wolfssl.CBIO_ERR_CONN_CLOSE; + } + } + return sz; + } + catch (Exception e) + { + log(ERROR_LOG, "socket connection issue "+ e.ToString()); + return wolfssl.CBIO_ERR_CONN_CLOSE; + } + } + + + /// + /// Call back used for sending DTLS information + /// + /// pointer to ssl struct + /// buffer containing information to send + /// size of buffer to send + /// optional information + /// amount of information sent + private static int wolfSSL_dtlsCbIOSend(IntPtr ssl, IntPtr buf, int sz, IntPtr ctx) + { + if (sz <= 0) + { + log(ERROR_LOG, "wolfssl dtls send error, size less than 0"); + return wolfssl.CBIO_ERR_GENERAL; + } + + try + { + System.Runtime.InteropServices.GCHandle gch; + gch = GCHandle.FromIntPtr(ctx); + + DTLS_con con = (DTLS_con)gch.Target; + + Byte[] msg = new Byte[sz]; + Marshal.Copy(buf, msg, 0, sz); + con.udp.Send(msg, msg.Length, con.ep); + return msg.Length; + } + catch (Exception e) + { + log(ERROR_LOG, "socket connection issue " + e.ToString()); + return wolfssl.CBIO_ERR_CONN_CLOSE; + } + } + + + /// + /// Call back to allow receiving DTLS information + /// + /// structure of ssl passed in + /// buffer to contain received msg + /// size of buffer + /// optional information passed in + /// size of message received + private static int wolfSSL_dtlsCbIORecv(IntPtr ssl, IntPtr buf, int sz, IntPtr ctx) + { + if (sz <= 0) + { + log(ERROR_LOG, "wolfssl dtls receive error, size less than 0"); + return wolfssl.CBIO_ERR_GENERAL; + } + + try + { + System.Runtime.InteropServices.GCHandle gch; + gch = GCHandle.FromIntPtr(ctx); + DTLS_con con = (DTLS_con)gch.Target; + + Byte[] msg = con.udp.Receive(ref con.ep); + if (msg.Length > sz) + { + log(ERROR_LOG, "wolfssl DTLS packet received was larger than buffer"); + return wolfssl.CBIO_ERR_GENERAL; + } + + Marshal.Copy(msg, 0, buf, msg.Length); + return msg.Length; + } + catch (Exception e) + { + /* issue with receive or size of buffer */ + log(ERROR_LOG, "socket read issue "+ e.ToString()); + return wolfssl.CBIO_ERR_CONN_CLOSE; + } + } + + + /// + /// Create a new ssl structure + /// + /// structure to create ssl structure from + /// pointer to ssl structure + public static IntPtr new_ssl(IntPtr ctx) + { + if (ctx == IntPtr.Zero) + return IntPtr.Zero; + + try + { + ssl_handle io; + IntPtr local_ctx = unwrap_ctx(ctx); + if (local_ctx == IntPtr.Zero) + { + log(ERROR_LOG, "new_ssl ctx unwrap error"); + return IntPtr.Zero; + } + + io = new ssl_handle(); + io.set_ssl(wolfSSL_new(local_ctx)); + + /* check if null */ + if (io.get_ssl() == IntPtr.Zero) + { + return IntPtr.Zero; + } + + /* keep memory pinned to be able to reference by address */ + return GCHandle.ToIntPtr(GCHandle.Alloc(io, GCHandleType.Pinned)); + } + catch (Exception e) + { + log(ERROR_LOG, e.ToString()); + return IntPtr.Zero; + } + } + + + /// + /// Used for a server to accept a connection + /// + /// structure containing info for connection + /// 1 on success + public static int accept(IntPtr ssl) + { + if (ssl == IntPtr.Zero) + return FAILURE; + try + { + IntPtr sslCtx = unwrap_ssl(ssl); + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "accept ssl unwrap error"); + return FAILURE; + } + + return wolfSSL_accept(sslCtx); + } + catch (Exception e) + { + log(ERROR_LOG, "accept error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Used for a client to connect + /// + /// structure containing connection info + /// 1 on success + public static int connect(IntPtr ssl) + { + if (ssl == IntPtr.Zero) + return FAILURE; + try + { + IntPtr sslCtx = unwrap_ssl(ssl); + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "connect ssl unwrap error"); + return FAILURE; + } + + return wolfSSL_connect(sslCtx); + } + catch (Exception e) + { + log(ERROR_LOG, "connect error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Read message from secure connection + /// + /// structure containing info about connection + /// object to hold incoming message (Unicode format) + /// size of available memory in buf + /// amount of data read on success + public static int read(IntPtr ssl, StringBuilder buf, int sz) + { + if (ssl == IntPtr.Zero) + return FAILURE; + try + { + IntPtr sslCtx = unwrap_ssl(ssl); + IntPtr data; + int ret; + byte[] msg; + + buf.Clear(); /* Clear incomming buffer */ + + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "read ssl unwrap error"); + return FAILURE; + } + data = Marshal.AllocHGlobal(sz); + + ret = wolfSSL_read(sslCtx, data, sz); + + if (ret >= 0) + { + /* Get data that was sent across and store it using a literal read of + * the conversion from bytes to character. Takes care of if + * a null terminator is part of the message read. + */ + msg = new byte[ret]; + Marshal.Copy(data, msg, 0, ret); + for (int i = 0; i < ret; i++) + { + buf.Append(@Convert.ToChar(msg[i])); + } + } + Marshal.FreeHGlobal(data); + + return ret; + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl read error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Read message from secure connection using a byte array + /// + /// structure containing info about connection + /// object to hold incoming message (raw bytes) + /// size of available memory in buf + /// amount of data read on success + public static int read(IntPtr ssl, byte[] buf, int sz) + { + if (ssl == IntPtr.Zero) + return FAILURE; + try + { + IntPtr sslCtx = unwrap_ssl(ssl); + IntPtr data; + int ret; + + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "read ssl unwrap error"); + return FAILURE; + } + data = Marshal.AllocHGlobal(sz); + + ret = wolfSSL_read(sslCtx, data, sz); + + if (ret >= 0) + { + Marshal.Copy(data, buf, 0, ret); + } + Marshal.FreeHGlobal(data); + + return ret; + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl read error " + e.ToString()); + return FAILURE; + } + } + + + + /// + /// Write message to secure connection + /// + /// structure containing connection info + /// message to send + /// size of the message + /// amount sent on success + public static int write(IntPtr ssl, StringBuilder buf, int sz) + { + if (ssl == IntPtr.Zero) + return FAILURE; + try + { + IntPtr sslCtx = unwrap_ssl(ssl); + IntPtr data; + int ret; + + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "write ssl unwrap error"); + return FAILURE; + } + + data = Marshal.AllocHGlobal(sz); + Marshal.Copy(System.Text.Encoding.Default.GetBytes(buf.ToString()), 0, + data, System.Text.Encoding.Default.GetByteCount(buf.ToString())); + ret = wolfSSL_write(sslCtx, data, sz); + Marshal.FreeHGlobal(data); + return ret; + + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl write error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Write message to secure connection + /// + /// structure containing connection info + /// message to send + /// size of the message + /// amount sent on success + public static int write(IntPtr ssl, byte[] buf, int sz) + { + if (ssl == IntPtr.Zero) + return FAILURE; + try + { + IntPtr sslCtx = unwrap_ssl(ssl); + IntPtr data; + int ret; + + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "write ssl unwrap error"); + return FAILURE; + } + data = Marshal.AllocHGlobal(sz); + Marshal.Copy(buf, 0, data, sz); + ret = wolfSSL_write(sslCtx, data, sz); + Marshal.FreeHGlobal(data); + return ret; + + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl write error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Free information stored in ssl struct + /// + /// pointer to ssl struct to free + public static void free(IntPtr ssl) + { + try + { + IntPtr sslCtx; + GCHandle gch = GCHandle.FromIntPtr(ssl); + ssl_handle handles = (ssl_handle)gch.Target; + + sslCtx = handles.get_ssl(); + wolfSSL_free(sslCtx); + handles.free(); + gch.Free(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl free error " + e.ToString()); + } + } + + + /// + /// Shutdown a connection + /// + /// pointer to ssl struct to close connection of + /// 1 on success + public static int shutdown(IntPtr ssl) + { + if (ssl == IntPtr.Zero) + return FAILURE; + try + { + IntPtr sslCtx = unwrap_ssl(ssl); + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "shutdown ssl unwrap error"); + return FAILURE; + } + + return wolfSSL_shutdown(sslCtx); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl shutdwon error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Optional, can be used to set a custom receive function + /// + /// structure to set receive function in + /// function to use when reading socket + public static void SetIORecv(IntPtr ctx, CallbackIORecv_delegate func) + { + try + { + GCHandle gch = GCHandle.FromIntPtr(ctx); + ctx_handle handles = (ctx_handle)gch.Target; + + /* check if already stored handle needs freed */ + gch = handles.get_receive(); + if (!Object.Equals(gch, default(GCHandle))) + { + gch.Free(); + } + + /* keep new function alive */ + handles.set_receive(GCHandle.Alloc(func)); + + wolfSSL_CTX_SetIORecv(handles.get_ctx(), func); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl setIORecv error " + e.ToString()); + } + } + + + /// + /// Optional, can be used to set a custom send function + /// + /// structure to set function in + /// function to use when sending data + public static void SetIOSend(IntPtr ctx, CallbackIOSend_delegate func) + { + try + { + GCHandle gch = GCHandle.FromIntPtr(ctx); + ctx_handle handles = (ctx_handle)gch.Target; + + /* check if already stored handle needs freed */ + gch = handles.get_send(); + if (!Object.Equals(gch, default(GCHandle))) + { + gch.Free(); + } + + /* keep new function alive */ + handles.set_send(GCHandle.Alloc(func)); + + wolfSSL_CTX_SetIOSend(handles.get_ctx(), func); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl setIOSend error " + e.ToString()); + } + } + + + /// + /// Create a new CTX structure + /// + /// method to use such as TLSv1.2 + /// pointer to CTX structure + public static IntPtr CTX_new(IntPtr method) + { + try + { + IntPtr ctx = wolfSSL_CTX_new(method); + if (ctx == IntPtr.Zero) + return ctx; + + ctx_handle io = new ctx_handle(); + io.set_ctx(ctx); + + CallbackIORecv_delegate recv = new CallbackIORecv_delegate(wolfssl.wolfSSLCbIORecv); + io.set_receive(GCHandle.Alloc(recv)); + wolfSSL_CTX_SetIORecv(ctx, recv); + + CallbackIOSend_delegate send = new CallbackIOSend_delegate(wolfssl.wolfSSLCbIOSend); + io.set_send(GCHandle.Alloc(send)); + wolfSSL_CTX_SetIOSend(ctx, send); + + /* keep memory pinned */ + return GCHandle.ToIntPtr(GCHandle.Alloc(io, GCHandleType.Pinned)); + } + catch (Exception e) + { + log(ERROR_LOG, "ctx_new error " + e.ToString()); + return IntPtr.Zero; + } + } + + + /// + /// Create a new CTX structure for a DTLS connection + /// + /// Method to use in connection ie DTLSv1.2 + /// + public static IntPtr CTX_dtls_new(IntPtr method) + { + try + { + IntPtr ctx = wolfSSL_CTX_new(method); + if (ctx == IntPtr.Zero) + return ctx; + + ctx_handle io = new ctx_handle(); + io.set_ctx(ctx); + + CallbackIORecv_delegate recv = new CallbackIORecv_delegate(wolfssl.wolfSSL_dtlsCbIORecv); + io.set_receive(GCHandle.Alloc(recv)); + wolfSSL_CTX_SetIORecv(ctx, recv); + + CallbackIOSend_delegate send = new CallbackIOSend_delegate(wolfssl.wolfSSL_dtlsCbIOSend); + io.set_send(GCHandle.Alloc(send)); + wolfSSL_CTX_SetIOSend(ctx, send); + + /* keep memory pinned */ + return GCHandle.ToIntPtr(GCHandle.Alloc(io, GCHandleType.Pinned)); + } + catch (Exception e) + { + log(ERROR_LOG, "ctx_dtls_new error " + e.ToString()); + return IntPtr.Zero; + } + } + + + /// + /// Free information used in CTX structure + /// + /// structure to free + public static void CTX_free(IntPtr ctx) + { + try + { + GCHandle gch = GCHandle.FromIntPtr(ctx); + ctx_handle handles = (ctx_handle)gch.Target; + wolfSSL_CTX_free(handles.get_ctx()); + handles.free(); + gch.Free(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl ctx free error " + e.ToString()); + } + } + + + /// + /// Set identity hint to use + /// + /// pointer to structure of ctx to set hint in + /// hint to use + /// 1 on success + public static int CTX_use_psk_identity_hint(IntPtr ctx, StringBuilder hint) + { + try + { + IntPtr local_ctx = unwrap_ctx(ctx); + if (local_ctx == IntPtr.Zero) + { + log(ERROR_LOG, "CTX use psk identity hint unwrap error"); + return FAILURE; + } + + return wolfSSL_CTX_use_psk_identity_hint(local_ctx, hint); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl psk identity hint error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Set the function to use for PSK connections + /// + /// pointer to CTX that the function is set in + /// PSK function to use + public static void CTX_set_psk_server_callback(IntPtr ctx, psk_delegate psk_cb) + { + try + { + GCHandle gch = GCHandle.FromIntPtr(ctx); + ctx_handle handles = (ctx_handle)gch.Target; + + handles.set_psk(GCHandle.Alloc(psk_cb)); + wolfSSL_CTX_set_psk_server_callback(handles.get_ctx(), psk_cb); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl psk server callback error " + e.ToString()); + } + } + + + /// + /// Set the function to use for PSK connections + /// + /// pointer to CTX that the function is set in + /// PSK function to use + public static void CTX_set_psk_client_callback(IntPtr ctx, psk_client_delegate psk_cb) + { + try + { + GCHandle gch = GCHandle.FromIntPtr(ctx); + ctx_handle handles = (ctx_handle)gch.Target; + + handles.set_psk(GCHandle.Alloc(psk_cb)); + wolfSSL_CTX_set_psk_client_callback(handles.get_ctx(), psk_cb); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl psk client callback error " + e.ToString()); + } + } + + + /// + /// Set the function to use for PSK connections on a single TLS/DTLS connection + /// + /// pointer to SSL that the function is set in + /// PSK function to use + public static void set_psk_server_callback(IntPtr ssl, psk_delegate psk_cb) + { + try + { + GCHandle gch = GCHandle.FromIntPtr(ssl); + ssl_handle handles = (ssl_handle)gch.Target; + + handles.set_psk(GCHandle.Alloc(psk_cb)); + wolfSSL_set_psk_server_callback(handles.get_ssl(), psk_cb); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl psk server callback error " + e.ToString()); + } + } + + + /// + /// Set Socket for TLS connection + /// + /// structure to set Socket in + /// Socket to use + /// 1 on success + public static int set_fd(IntPtr ssl, Socket fd) + { + /* sanity check on inputs */ + if (ssl == IntPtr.Zero) + { + return FAILURE; + } + + try + { + if (!fd.Equals(null)) + { + GCHandle gch = GCHandle.FromIntPtr(ssl); + ssl_handle handles = (ssl_handle)gch.Target; + IntPtr sslCtx = handles.get_ssl(); + IntPtr ptr; + GCHandle fd_pin = GCHandle.Alloc(fd); + + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "wolfssl error setting up fd!!"); + return FAILURE; + } + + handles.set_fd(fd_pin); + ptr = GCHandle.ToIntPtr(fd_pin); + wolfSSL_SetIOWriteCtx(sslCtx, ptr); //pass along the socket for writing to + wolfSSL_SetIOReadCtx(sslCtx, ptr); //pass along the socket for reading from + + return SUCCESS; + } + + return FAILURE; + } + catch (Exception e) + { + log(ERROR_LOG, "Error setting up fd!! " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Get socket of a TLS connection + /// + /// structure to get socket from + /// Socket object used for connection + public static Socket get_fd(IntPtr ssl) + { + try + { + IntPtr ptr; + IntPtr sslCtx = unwrap_ssl(ssl); + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "wolfssl get_fd error"); + return null; + } + + ptr = wolfSSL_GetIOReadCtx(sslCtx); + if (ptr != IntPtr.Zero) + { + GCHandle gch = GCHandle.FromIntPtr(ptr); + return (System.Net.Sockets.Socket)gch.Target; + } + return null; + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl get_fd error " + e.ToString()); + return null; + } + } + + + + /// + /// Set information needed to send and receive a DTLS connection + /// + /// structure to set information in + /// UDP object to send and receive + /// End point of connection + /// 1 on success + public static int set_dtls_fd(IntPtr ssl, UdpClient udp, IPEndPoint ep) + { + /* sanity check on inputs */ + if (ssl == IntPtr.Zero) + { + return FAILURE; + } + + try + { + if (!udp.Equals(null) && !ep.Equals(null)) + { + IntPtr ptr; + DTLS_con con; + GCHandle gch = GCHandle.FromIntPtr(ssl); + ssl_handle handles = (ssl_handle)gch.Target; + GCHandle fd_pin; + + con = new DTLS_con(); + con.udp = udp; + con.ep = ep; + fd_pin = GCHandle.Alloc(con); + handles.set_fd(fd_pin); + ptr = GCHandle.ToIntPtr(fd_pin); + wolfSSL_SetIOWriteCtx(handles.get_ssl(), ptr); //pass along the socket for writing to + wolfSSL_SetIOReadCtx(handles.get_ssl(), ptr); //pass along the socket for reading from + + return SUCCESS; + } + return FAILURE; + } + catch (Exception e) + { + log(ERROR_LOG, "Error setting up fd!! " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Get the pointer to DTLS_con class used for connection + /// + /// structure to get connection from + /// DTLS_con object + public static DTLS_con get_dtls_fd(IntPtr ssl) + { + try + { + IntPtr ptr; + IntPtr sslCtx = unwrap_ssl(ssl); + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "wolfssl get_dtls_fd error"); + return null; + } + + ptr = wolfSSL_GetIOReadCtx(sslCtx); + if (ptr != IntPtr.Zero) + { + GCHandle gch = GCHandle.FromIntPtr(ptr); + return (DTLS_con)gch.Target; + } + return null; + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl get_dtls_fd error " + e.ToString()); + return null; + } + } + + + /// + /// Get available cipher suites + /// + /// list to fill with cipher suite names + /// size of list available to fill + /// 1 on success + public static int get_ciphers(StringBuilder list, int sz) + { + try + { + return wolfSSL_get_ciphers(list, sz); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl get_ciphers error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Initialize wolfSSL library + /// + /// 1 on success + public static int Init() + { + try + { + return wolfSSL_Init(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl init error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Clean up wolfSSL library memory + /// + /// 1 on success + public static int Cleanup() + { + try + { + return wolfSSL_Cleanup(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl cleanup error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Set up TLS version 1.2 method + /// + /// pointer to TLSv1.2 method + public static IntPtr useTLSv1_2_server() + { + try + { + return wolfTLSv1_2_server_method(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl error " + e.ToString()); + return IntPtr.Zero; + } + } + + /// + /// Set up TLS version 1.3 method + /// + /// pointer to TLSv1.3 method + public static IntPtr useTLSv1_3_server() + { + try + { + return wolfTLSv1_3_server_method(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl error " + e.ToString()); + return IntPtr.Zero; + } + } + + + /// + /// Use any TLS version + /// + /// pointer to method + public static IntPtr usev23_server() + { + try + { + return wolfSSLv23_server_method(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl error " + e.ToString()); + return IntPtr.Zero; + } + } + + + /// + /// Set up TLS version 1.2 method + /// + /// pointer to TLSv1.2 method + public static IntPtr useTLSv1_2_client() + { + try + { + return wolfTLSv1_2_client_method(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl error " + e.ToString()); + return IntPtr.Zero; + } + } + + /// + /// Set up TLS version 1.3 method + /// + /// pointer to TLSv1.3 method + public static IntPtr useTLSv1_3_client() + { + try + { + return wolfTLSv1_3_client_method(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl error " + e.ToString()); + return IntPtr.Zero; + } + } + + /// + /// Use any TLS version + /// + /// pointer to method + public static IntPtr usev23_client() + { + try + { + return wolfSSLv23_client_method(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl error " + e.ToString()); + return IntPtr.Zero; + } + } + + + /// + /// Set up DTLS version 1.2 + /// + /// pointer to DTLSv1.2 method + public static IntPtr useDTLSv1_2_server() + { + try + { + return wolfDTLSv1_2_server_method(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl error " + e.ToString()); + return IntPtr.Zero; + } + } + + + /// + /// Set up DTLS version 1.2 + /// + /// pointer to DTLSv1.2 method + public static IntPtr useDTLSv1_2_client() + { + try + { + return wolfDTLSv1_2_client_method(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl error " + e.ToString()); + return IntPtr.Zero; + } + } + + + /// + /// Gets the current cipher suite being used in connection + /// + /// SSL struct to get cipher suite from + /// string containing current cipher suite + public static string get_current_cipher(IntPtr ssl) + { + if (ssl == IntPtr.Zero) + return null; + try + { + IntPtr ssl_cipher; + IntPtr ssl_cipher_ptr; + string ssl_cipher_str; + + IntPtr sslCtx = unwrap_ssl(ssl); + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "wolfssl get_current_cipher error"); + return null; + } + + ssl_cipher = wolfSSL_get_current_cipher(sslCtx); + ssl_cipher_ptr = wolfSSL_CIPHER_get_name(ssl_cipher); + ssl_cipher_str = Marshal.PtrToStringAnsi(ssl_cipher_ptr); + + return ssl_cipher_str; + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl get current cipher error " + e.ToString()); + return null; + } + } + + + /// + /// Set available cipher suites for all ssl structs created from ctx + /// + /// CTX structure to set + /// List full of ciphers suites + /// 1 on success + public static int CTX_set_cipher_list(IntPtr ctx, StringBuilder list) + { + try + { + IntPtr local_ctx = unwrap_ctx(ctx); + if (local_ctx == IntPtr.Zero) + { + log(ERROR_LOG, "CTX set cipher list error"); + return FAILURE; + } + + return wolfSSL_CTX_set_cipher_list(local_ctx, list); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl ctx set cipher list error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Set available cipher suite in local connection + /// + /// Structure to set cipher suite in + /// List of cipher suites + /// 1 on success + public static int set_cipher_list(IntPtr ssl, StringBuilder list) + { + try + { + IntPtr sslCtx = unwrap_ssl(ssl); + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "wolfssl set_cipher_list error"); + return FAILURE; + } + + return wolfSSL_set_cipher_list(sslCtx, list); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl set cipher error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Gets the version of the connection made ie TLSv1.2 + /// + /// SSL struct to get version of + /// string containing version + public static string get_version(IntPtr ssl) + { + if (ssl == IntPtr.Zero) + return null; + + try + { + IntPtr version_ptr; + string version; + + IntPtr sslCtx = unwrap_ssl(ssl); + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "wolfssl get_version error"); + return null; + } + + version_ptr = wolfSSL_get_version(sslCtx); + version = Marshal.PtrToStringAnsi(version_ptr); + + return version; + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl get version error " + e.ToString()); + return null; + } + } + + + /// + /// Get a string containing error value and reason + /// + /// SSL struct that had error + /// String containing error value and reason + public static string get_error(IntPtr ssl) + { + if (ssl == IntPtr.Zero) + return null; + + try + { + int err; + StringBuilder err_name; + StringBuilder ret; + + IntPtr sslCtx = unwrap_ssl(ssl); + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "wolfssl get_error error"); + return null; + } + + /* wolfSSL max error length is 80 */ + ret = new StringBuilder(' ', 100); + err = wolfSSL_get_error(sslCtx, 0); + err_name = new StringBuilder(new String(' ', 80)); + wolfSSL_ERR_error_string((uint)err, err_name); + ret.Append("Error " + err + " " + err_name.ToString()); + + return ret.ToString(); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl get error, error " + e.ToString()); + return null; + } + } + + + /// + /// Used to load in the certificate file + /// + /// CTX structure for TLS/SSL connections + /// Name of the file to load including absolute path + /// Type of file ie PEM or DER + /// 1 on success + public static int CTX_use_certificate_file(IntPtr ctx, string fileCert, int type) + { + try + { + IntPtr local_ctx = unwrap_ctx(ctx); + if (local_ctx == IntPtr.Zero) + { + log(ERROR_LOG, "CTX use certificate file error"); + return FAILURE; + } + + return wolfSSL_CTX_use_certificate_file(local_ctx, fileCert, type); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl ctx use cert file error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// 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(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 + /// + /// CTX structure for TLS/SSL connections + /// Name of the file, includeing absolute directory + /// Type of file ie PEM or DER + /// 1 on success + public static int CTX_use_PrivateKey_file(IntPtr ctx, string fileKey, int type) + { + try + { + IntPtr local_ctx = unwrap_ctx(ctx); + if (local_ctx == IntPtr.Zero) + { + log(ERROR_LOG, "CTX use PrivateKey file error"); + return FAILURE; + } + + return wolfSSL_CTX_use_PrivateKey_file(local_ctx, fileKey, type); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl ctx use key file error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Set temporary DH parameters + /// + /// Structure to set in + /// file name + /// type of file ie PEM + /// 1 on success + public static int SetTmpDH_file(IntPtr ssl, StringBuilder dhparam, int file_type) + { + try + { + IntPtr sslCtx = unwrap_ssl(ssl); + if (sslCtx == IntPtr.Zero) + { + log(ERROR_LOG, "SetTmpDH_file ssl unwrap error"); + return FAILURE; + } + + return wolfSSL_SetTmpDH_file(sslCtx, dhparam, file_type); + } + catch (Exception e) + { + log(ERROR_LOG, "SetTmpDH_file error " + e.ToString()); + return FAILURE; + } + } + + /// + /// Set temporary DH parameters + /// + /// Structure to set in + /// file name + /// type of file ie PEM + /// 1 on success + public static int CTX_SetTmpDH_file(IntPtr ctx, StringBuilder dhparam, int file_type) + { + try + { + IntPtr local_ctx = unwrap_ctx(ctx); + if (local_ctx == IntPtr.Zero) + { + log(ERROR_LOG, "CTX_SetTmpDH_file ctx unwrap error"); + return FAILURE; + } + + return wolfSSL_CTX_SetTmpDH_file(local_ctx, dhparam, file_type); + } + catch (Exception e) + { + log(ERROR_LOG, "CTX_SetTmpDH_file error " + e.ToString()); + return FAILURE; + } + } + + + /// + /// Used to set the minimum size of DH key + /// + /// Structure to store key size + /// Min key size + /// 1 on success + public static int CTX_SetMinDhKey_Sz(IntPtr ctx, short minDhKey) + { + try + { + IntPtr local_ctx = unwrap_ctx(ctx); + if (local_ctx == IntPtr.Zero) + { + log(ERROR_LOG, "CTX SetMinDhKey_Sz error"); + return FAILURE; + } + + return wolfSSL_CTX_SetMinDhKey_Sz(local_ctx, minDhKey); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl ctx set min dh key error " + e.ToString()); + return FAILURE; + } + } + + /// + /// Set the certificate verification mode and optional callback function + /// + /// pointer to CTX that the function is set in + /// See SSL_VERIFY options + /// Optional verify callback function to use + public static int CTX_set_verify(IntPtr ctx, int mode, CallbackVerify_delegate vc) + { + try + { + IntPtr local_ctx = unwrap_ctx(ctx); + if (local_ctx == IntPtr.Zero) + { + log(ERROR_LOG, "CTX set_verify error"); + return FAILURE; + } + + wolfSSL_CTX_set_verify(local_ctx, mode, vc); + return SUCCESS; + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl ctx set verify error " + e.ToString()); + return FAILURE; + } + } + + /// + /// Set the certificate verification mode and optional callback function + /// + /// pointer to SSL object that the function is set in + /// See SSL_VERIFY options + /// Optional verify callback function to use + public static int set_verify(IntPtr ssl, int mode, CallbackVerify_delegate vc) + { + try + { + IntPtr local_ssl = unwrap_ssl(ssl); + if (local_ssl == IntPtr.Zero) + { + log(ERROR_LOG, "set_verify error"); + return FAILURE; + } + + wolfSSL_set_verify(local_ssl, mode, vc); + return SUCCESS; + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl set verify error " + e.ToString()); + return FAILURE; + } + + } + + /// + /// Set the function to use for logging + /// + /// Function that conforms as to loggingCb + /// 1 on success + public static int SetLogging(loggingCb input) + { + internal_log = input; + return SUCCESS; + } + + + /// + /// Log a message to set logging function + /// + /// Level of log message + /// Message to log + public static void log(int lvl, string msg) + { + /* if log is not set then print nothing */ + if (internal_log == null) + return; + StringBuilder ptr = new StringBuilder(msg); + internal_log(lvl, ptr); + } + } +} diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/wolfSSL_CSharp.csproj b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/wolfSSL_CSharp.csproj new file mode 100644 index 000000000..128b84a37 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL_CSharp/wolfSSL_CSharp.csproj @@ -0,0 +1,80 @@ + + + + + Debug + AnyCPU + {52609808-0418-46D3-8E17-141927A1A39A} + Library + Properties + wolfSSL.CSharp + wolfSSL_CSharp + v4.5 + 512 + + + true + full + false + ..\DLL Debug\ + DEBUG;TRACE + prompt + 3 + + + pdbonly + true + ..\DLL Release\ + TRACE + prompt + 4 + + + true + ..\x64\DLL Debug\ + DEBUG;TRACE + 3 + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + ..\x64\DLL Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + + + + + xcopy "$(ProjectDir)..\..\..\certs\server-key.pem" "$(TargetDir)" /Y /R +xcopy "$(ProjectDir)..\..\..\certs\server-cert.pem" "$(TargetDir)" /Y /R +xcopy "$(ProjectDir)..\..\..\certs\dh2048.pem" "$(TargetDir)" /Y /R +xcopy "$(ProjectDir)..\..\..\certs\ca-cert.pem" "$(TargetDir)" /Y /R + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/include.am b/FreeRTOS-Plus/Source/WolfSSL/wrapper/include.am new file mode 100644 index 000000000..5185523e6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/include.am @@ -0,0 +1,7 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +include wrapper/python/wolfcrypt/include.am +include wrapper/python/wolfssl/include.am +include wrapper/CSharp/include.am diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/.gitignore b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/.gitignore new file mode 100644 index 000000000..5e6f6f9bd --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/.gitignore @@ -0,0 +1,18 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Distribution +build/ +dist/ +.eggs/ +*.egg-info/ + +# Unit test +.tox/ +# Sphinx documentation +docs/_build/ + +# Virtual env +.env diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/LICENSING.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/LICENSING.rst new file mode 100644 index 000000000..a7f0f3727 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/MANIFEST.in b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/MANIFEST.in new file mode 100644 index 000000000..3c56fcf44 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/MANIFEST.in @@ -0,0 +1 @@ +include LICENSING.rst diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/README.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/README.rst new file mode 100644 index 000000000..1732c906b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/README.rst @@ -0,0 +1,144 @@ + + +wolfcrypt: the wolfSSL Crypto Engine +==================================== + +**wolfCrypt Python**, a.k.a. ``wolfcrypt`` is a Python library that encapsulates +**wolfSSL's wolfCrypt API**. + +`wolfCrypt `_ is a +lightweight, portable, C-language-based crypto library +targeted at IoT, embedded, and RTOS environments primarily because of its size, +speed, and feature set. It works seamlessly in desktop, enterprise, and cloud +environments as well. It is the crypto engine behind `wolfSSl's embedded ssl +library `_. + + +Installation +------------ + +In order to use ``wolfcrypt``, first you'll need to install ``wolfssl`` C +embedded ssl library. + +Installing ``wolfssl`` : +~~~~~~~~~~~~~~~~~~~~~~~~ + +**Mac OSX** + +.. code-block:: console + + brew install wolfssl + +or + +.. code-block:: console + + git clone https://github.com/wolfssl/wolfssl.git + cd wolfssl/ + ./autogen.sh + ./configure --enable-sha512 + make + sudo make install + + +**Ubuntu** + +.. code-block:: console + + sudo apt-get update + sudo apt-get install -y git autoconf libtool + + git clone https://github.com/wolfssl/wolfssl.git + cd wolfssl/ + ./autogen.sh + ./configure --enable-sha512 + make + sudo make install + + sudo ldconfig + +**CentOS** + +.. code-block:: console + + sudo rpm -ivh http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-6.noarch.rpm + sudo yum update + sudo yum install -y git autoconf libtool + + git clone git@github.com:wolfssl/wolfssl.git + cd wolfssl + ./autogen.sh + ./configure --enable-sha512 + make + sudo make install + + echo /usr/local/lib > wolfssl.conf + sudo mv wolfssl.conf /etc/ld.so.conf + sudo ldconfig + + +Installing ``wolfcrypt`` : +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Mac OSX** + +.. code-block:: console + + sudo -H pip install wolfcrypt + + +**Ubuntu** + +.. code-block:: console + + sudo apt-get install -y python-dev python3-dev python-pip libffi-dev + sudo -H pip install wolfcrypt + + +**CentOS** + +.. code-block:: console + + sudo yum install -y python-devel python3-devel python-pip libffi-devel + sudo -H pip install wolfcrypt + + +Testing ``wolfcrypt`` : +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: console + + python -c "from wolfcrypt.hashes import Sha; print Sha().hexdigest()" + +expected output: **da39a3ee5e6b4b0d3255bfef95601890afd80709** + + +Testing ``wolfcrypt``'s source code with ``tox`` : +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To run the unit tests in the source code, you'll need ``tox`` and a few other +requirements. The source code relies at 'WOLFSSL_DIR/wrapper/python/wolfcrypt' +where WOLFSSL_DIR is the path of ``wolfssl``'s source code. + +1. Make sure that the testing requirements are installed: + +.. code-block:: console + + $ sudo -H pip install -r requirements-testing.txt + + +2. Run ``tox``: + +.. code-block:: console + + $ tox + ... + _________________________________ summary _________________________________ + py27: commands succeeded + SKIPPED: py34: InterpreterNotFound: python3.4 + py35: 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/Makefile b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/Makefile new file mode 100644 index 000000000..c552bc9b3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/Makefile @@ -0,0 +1,230 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) + $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " epub3 to make an epub3" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + @echo " dummy to check syntax errors of document sources" + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + +.PHONY: html +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +.PHONY: dirhtml +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +.PHONY: singlehtml +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +.PHONY: pickle +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +.PHONY: json +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +.PHONY: htmlhelp +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +.PHONY: qthelp +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/wolfcrypt.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/wolfcrypt.qhc" + +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/wolfcrypt" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/wolfcrypt" + @echo "# devhelp" + +.PHONY: epub +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +.PHONY: epub3 +epub3: + $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 + @echo + @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." + +.PHONY: latex +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +.PHONY: latexpdf +latexpdf: + $(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." + +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +.PHONY: man +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +.PHONY: texinfo +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +.PHONY: info +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +.PHONY: gettext +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +.PHONY: changes +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +.PHONY: linkcheck +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +.PHONY: doctest +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." + +.PHONY: dummy +dummy: + $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy + @echo + @echo "Build finished. Dummy builder generates no files." diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/asymmetric.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/asymmetric.rst new file mode 100644 index 000000000..970078dee --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/asymmetric.rst @@ -0,0 +1,74 @@ +Asymmetric Key Algorithms +========================= + +.. module:: wolfcrypt.ciphers + +**Asymmetric key algorithms** are encryption algorithms that use **a pair +of cryptographic keys**, one for data encryption and signing and the other +one for data decryption and signature verification. + +``wolfcrypt`` provides access to the following **Asymmetric Key Ciphers**: + +Asymmetric Key Encryption Classes +--------------------------------- + +.. autoclass:: RsaPublic + :members: + :inherited-members: + +.. autoclass:: RsaPrivate + :members: + :inherited-members: + + +Example +------- + + >>> from wolfcrypt.ciphers import RsaPrivate, RsaPublic + >>> from wolfcrypt.utils import h2b + >>> + >>> private = "3082025C02010002818100BC730EA849F374A2A9EF18A5DA559921F9C8ECB36D" \ + ... + "48E53535757737ECD161905F3ED9E4D5DF94CAC1A9D719DA86C9E84DC4613682" \ + ... + "FEABAD7E7725BB8D11A5BC623AA838CC39A20466B4F7F7F3AADA4D020EBB5E8D" \ + ... + "6948DC77C9280E22E96BA426BA4CE8C1FD4A6F2B1FEF8AAEF69062E5641EEB2B" \ + ... + "3C67C8DC2700F6916865A902030100010281801397EAE8387825A25C04CE0D40" \ + ... + "7C31E5C470CD9B823B5809863B665FDC3190F14FD5DB15DDDED73B9593311831" \ + ... + "0E5EA3D6A21A716E81481C4BCFDB8E7A866132DCFB55C1166D279224458BF1B8" \ + ... + "48B14B1DACDEDADD8E2FC291FBA5A96EF83A6AF1FD5018EF9FE7C3CA78EA56D3" \ + ... + "D3725B96DD4E064E3AC3D9BE72B66507074C01024100FA47D47A7C923C55EF81" \ + ... + "F041302DA3CF8F1CE6872705700DDF9835D6F18B382F24B5D084B6794F712994" \ + ... + "5AF0646AACE772C6ED4D59983E673AF3742CF9611769024100C0C1820D0CEBC6" \ + ... + "2FDC92F99D821A31E9E9F74BF282871CEE166AD11D188270F3C0B62FF6F3F71D" \ + ... + "F18623C84EEB8F568E8FF5BFF1F72BB5CC3DC657390C1B54410241009D7E05DE" \ + ... + "EDF4B7B2FBFC304B551DE32F0147966905CD0E2E2CBD8363B6AB7CB76DCA5B64" \ + ... + "A7CEBE86DF3B53DE61D21EEBA5F637EDACAB78D94CE755FBD71199C102401898" \ + ... + "1829E61E2739702168AC0A2FA172C121869538C65890A0579CBAE3A7B115C8DE" \ + ... + "F61BC2612376EFB09D1C44BE1343396717C89DCAFBF545648B38822CF2810240" \ + ... + "3989E59C195530BAB7488C48140EF49F7E779743E1B419353123759C3B44AD69" \ + ... + "1256EE0061641666D37C742B15B4A2FEBF086B1A5D3F9012B105863129DBD9E2" + >>> + >>> prv = RsaPrivate(h2b(private)) + >>> + >>> public = "30819F300D06092A864886F70D010101050003818D0030818902818100BC730E" \ + ... + "A849F374A2A9EF18A5DA559921F9C8ECB36D48E53535757737ECD161905F3ED9" \ + ... + "E4D5DF94CAC1A9D719DA86C9E84DC4613682FEABAD7E7725BB8D11A5BC623AA8" \ + ... + "38CC39A20466B4F7F7F3AADA4D020EBB5E8D6948DC77C9280E22E96BA426BA4C" \ + ... + "E8C1FD4A6F2B1FEF8AAEF69062E5641EEB2B3C67C8DC2700F6916865A90203010001" + >>> + >>> pub = RsaPublic(h2b(public)) + >>> + >>> plaintext = b"Everyone gets Friday off." + >>> + >>> ciphertext = pub.encrypt(plaintext) + >>> ciphertext # doctest: +SKIP + b'e\xb7\xc2\xad\x0c\x04.\xefU8\x17QB\x852\x03\x01\xef\xbe=\xb4\xaf\xaf\x97\x9e4\x96\x9f\xc3\x8e\x87\x9a8o$.|_e\x1d\xa2yi?\x83\x18\xf9Yr|\x1fQ\x1a\x18\x1e\xab\xd17\xc5\x8c\xae\x08c)\xbc\nIr\x8d\xc3\x88\x7f\xde\x1f\x1a^lB\r\xf1\xc0\xfd0\xdeA\xf3\xd2\xe5q\x9a0\xee\xb4,\x97\x80\xa4|U;\xe6\x11\xf0\xc2Q\x987\xe1>F\xf5\x14\x186@G~(Q\xf2;\xcb\x05\xee\x88\x0b\xd8\xa7' + >>> + >>> prv.decrypt(ciphertext) + b'Everyone gets Friday off.' + >>> + >>> signature = prv.sign(plaintext) + >>> signature # doctest: +SKIP + b'~\xc4\xe65\x15\xb17\x7fX\xaf,\xc2lw\xbd\x8f\t\x9d\xbf\xac\xdez\x90\xb4\x9f\x1aM\x88#Z\xea\xcb\xa6\xdb\x99\xf55\xd0\xfe|Mu\xb6\xb79(t\x81+h\xf2\xcd\x88v\xa8\xbaM\x86\xcfk\xe8\xf3\x0b\xb8\x8ew\xda>\xf8\xd5[H\xeaAh\xc6\xdaQlo]\xdd\xf8w\xe7#M-\x12f\xae,\xdd\xa6d FP<;R\xa2\x96hJ\xee_\x1fh\xaa\xc8\xdfAJ\xa5\xdd\x05\xc4\x89\x0c\xd7\xa0C\xb7u"U\x03' + >>> + >>> pub.verify(signature) + b'Everyone gets Friday off.' diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/conf.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/conf.py new file mode 100644 index 000000000..3e9de701c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/conf.py @@ -0,0 +1,299 @@ +# -*- 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. + +import sys +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'wolfcrypt' +copyright = u'2016, 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) +about = {} +with open(os.path.join(base_dir, "wolfcrypt", "__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 = 'wolfcrypt-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, 'wolfcrypt.tex', u'wolfcrypt 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, 'wolfcrypt', u'wolfcrypt 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, 'wolfcrypt', u'wolfcrypt Python Documentation', + author, 'wolfcrypt', '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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/digest.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/digest.rst new file mode 100644 index 000000000..0d79f8ef0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/digest.rst @@ -0,0 +1,71 @@ +Message Digests +=============== + +.. module:: wolfcrypt.hashes + +A **message digest** is the output of a **cryptographic hash function** +containing a string of bytes created by a **one-way formula** using the +original message as input. + +Message digests are designed to protect the integrity of a piece of data or +media to detect changes and alterations to any part of a message. + + +Hashing Classes +--------------- + +Interface +~~~~~~~~~ + +All Hashing Functions available in this module implements the following +interface: + +.. autoclass:: _Hash + :members: + +SHA-1 +~~~~~ + +.. attention:: + + NIST has deprecated SHA-1 in favor of the SHA-2 variants. New applications + are strongly suggested to use SHA-2 over SHA-1. + +.. autoclass:: Sha + +SHA-2 family +~~~~~~~~~~~~ + +.. autoclass:: Sha256 + + +.. autoclass:: Sha384 + + +.. autoclass:: Sha512 + + +Example +------- + +.. doctest:: + + >>> from wolfcrypt.hashes import Sha256 + >>> + >>> s = Sha256() + >>> s.update(b'wolf') + >>> s.update(b'crypt') + >>> s.digest() + b'\x96\xe0.{\x1c\xbc\xd6\xf1\x04\xfe\x1f\xdbFR\x02zU\x05\xb6\x86R\xb7\x00\x95\xc61\x8f\x9d\xce\r\x18D' + >>> s.hexdigest() + b'96e02e7b1cbcd6f104fe1fdb4652027a5505b68652b70095c6318f9dce0d1844' + >>> + >>> s.update(b'rocks') + >>> s.hexdigest() + b'e1a50df419d65715c48316bdc6a6f7f0485f4b26c1b107228faf17988b61c83f' + >>> + >>> Sha256(b'wolfcryptrocks').hexdigest() + b'e1a50df419d65715c48316bdc6a6f7f0485f4b26c1b107228faf17988b61c83f' + >>> + >>> Sha256.new(b'wolfcryptrocks').hexdigest() + b'e1a50df419d65715c48316bdc6a6f7f0485f4b26c1b107228faf17988b61c83f' diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/index.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/index.rst new file mode 100644 index 000000000..efd3431a8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/index.rst @@ -0,0 +1,15 @@ +.. include:: ../README.rst + +Summary +------- + +.. toctree:: + :maxdepth: 1 + + symmetric + asymmetric + digest + mac + random + +.. include:: ../LICENSING.rst diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/mac.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/mac.rst new file mode 100644 index 000000000..14b39cd78 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/mac.rst @@ -0,0 +1,74 @@ +Message Authentication Codes +============================ + +.. module:: wolfcrypt.hashes + +A **message authentication code** (MAC) is a short piece of information used +to authenticate a message — in other words, to confirm that the message came +from the stated sender (its authenticity) and has not been changed in transit +(its integrity). + +``wolfcrypt`` implements the **Hash-based message authentication code** (HMAC), +which uses a cryptographic hash function coupled with a secret key to produce +**message authentication codes**. + + +Hmac Classes +------------ + +Interface +~~~~~~~~~ + +All Hmac classes available in this module implements the following +interface: + +.. autoclass:: _Hmac + :members: + :inherited-members: + +SHA-1 +~~~~~ + +.. attention:: + + NIST has deprecated SHA-1 in favor of the SHA-2 variants. New applications + are strongly suggested to use SHA-2 over SHA-1. + +.. autoclass:: HmacSha + +SHA-2 family +~~~~~~~~~~~~ + +.. autoclass:: HmacSha256 + + +.. autoclass:: HmacSha384 + + +.. autoclass:: HmacSha512 + + +Example +------- + +.. doctest:: + + >>> from wolfcrypt.hashes import HmacSha256 + >>> + >>> h = HmacSha256('secret') + >>> h.update("wolf") + >>> h.update("crypt") + >>> h.digest() + b'\x18\xbf*\t9\xa2o\xdf\\\xc8\xe0\xc2U\x94,\x8dY\x02;\x1c>> h.hexdigest() + b'18bf2a0939a26fdf5cc8e0c255942c8d59023b1c3c51df8ddb8633fbc166236f' + >>> + >>> h.update("rocks") + >>> h.hexdigest() + b'85dc8c1995d20b17942d52773d8a597d028ad958e5736beafb59a4742f63889e' + >>> + >>> HmacSha256('secret', 'wolfcryptrocks').hexdigest() + b'85dc8c1995d20b17942d52773d8a597d028ad958e5736beafb59a4742f63889e' + >>> + >>> HmacSha256.new('secret', 'wolfcryptrocks').hexdigest() + b'85dc8c1995d20b17942d52773d8a597d028ad958e5736beafb59a4742f63889e' diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/random.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/random.rst new file mode 100644 index 000000000..ba8e33bda --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/random.rst @@ -0,0 +1,30 @@ +Random Number Generation +======================== + +A **cryptographically secure pseudo-random number generator** (CSPRNG) is a +**pseudo-random number generator** (PRNG) with properties that make it suitable +for use in cryptography. + +Using the standard random module APIs for cryptographic keys or initialization +vectors can result in major security issues depending on the algorithms in use. + +``wolfcrypt`` provides the following CSPRNG implementation: + +.. module:: wolfcrypt.random + +.. autoclass:: Random + :members: + + +Example +------- + + >>> from wolfcrypt.random import Random + >>> + >>> r = Random() + >>> b = r.byte() + >>> b # doctest: +SKIP + b'\x8c' + >>> b16 = r.bytes(16) + >>> b16 # doctest: +SKIP + b']\x93nk\x95\xbc@\xffX\xab\xdcB\xda\x11\xf7\x03' diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/symmetric.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/symmetric.rst new file mode 100644 index 000000000..a4939838d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/docs/symmetric.rst @@ -0,0 +1,42 @@ +Symmetric Key Algorithms +======================== + +.. module:: wolfcrypt.ciphers + +**Symmetric key algorithms** are encryption algorithms that use the **same +cryptographic keys** for both encryption and decryption of data. +This operation is also known as **Symmetric Key Encryption**. + +``wolfcrypt`` provides access to the following **Symmetric Key Ciphers**: + +Symmetric Key Encryption Classes +-------------------------------- + +Interface +~~~~~~~~~ + +All **Symmetric Key Ciphers** available in this module implements the following +interface: + +.. autoclass:: _Cipher + :members: + +Classes +~~~~~~~ + +.. autoclass:: Aes + + +Example +------- + +.. doctest:: + + >>> from wolfcrypt.ciphers import Aes, MODE_CBC + >>> + >>> cipher = Aes(b'0123456789abcdef', MODE_CBC, b'1234567890abcdef') + >>> ciphertext = cipher.encrypt('now is the time ') + >>> ciphertext + b'\x95\x94\x92W_B\x81S,\xcc\x9dFw\xa23\xcb' + >>> cipher.decrypt(ciphertext) + b'now is the time ' diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/include.am b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/include.am new file mode 100644 index 000000000..4d62bcf51 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/include.am @@ -0,0 +1,30 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +EXTRA_DIST+= wrapper/python/wolfcrypt/.gitignore +EXTRA_DIST+= wrapper/python/wolfcrypt/docs/asymmetric.rst +EXTRA_DIST+= wrapper/python/wolfcrypt/docs/conf.py +EXTRA_DIST+= wrapper/python/wolfcrypt/docs/digest.rst +EXTRA_DIST+= wrapper/python/wolfcrypt/docs/index.rst +EXTRA_DIST+= wrapper/python/wolfcrypt/docs/mac.rst +EXTRA_DIST+= wrapper/python/wolfcrypt/docs/Makefile +EXTRA_DIST+= wrapper/python/wolfcrypt/docs/random.rst +EXTRA_DIST+= wrapper/python/wolfcrypt/docs/symmetric.rst +EXTRA_DIST+= wrapper/python/wolfcrypt/LICENSING.rst +EXTRA_DIST+= wrapper/python/wolfcrypt/MANIFEST.in +EXTRA_DIST+= wrapper/python/wolfcrypt/README.rst +EXTRA_DIST+= wrapper/python/wolfcrypt/requirements-testing.txt +EXTRA_DIST+= wrapper/python/wolfcrypt/setup.py +EXTRA_DIST+= wrapper/python/wolfcrypt/test/test_ciphers.py +EXTRA_DIST+= wrapper/python/wolfcrypt/test/test_hashes.py +EXTRA_DIST+= wrapper/python/wolfcrypt/test/test_random.py +EXTRA_DIST+= wrapper/python/wolfcrypt/tox.ini +EXTRA_DIST+= wrapper/python/wolfcrypt/wolfcrypt/__about__.py +EXTRA_DIST+= wrapper/python/wolfcrypt/wolfcrypt/__init__.py +EXTRA_DIST+= wrapper/python/wolfcrypt/wolfcrypt/build_ffi.py +EXTRA_DIST+= wrapper/python/wolfcrypt/wolfcrypt/ciphers.py +EXTRA_DIST+= wrapper/python/wolfcrypt/wolfcrypt/exceptions.py +EXTRA_DIST+= wrapper/python/wolfcrypt/wolfcrypt/hashes.py +EXTRA_DIST+= wrapper/python/wolfcrypt/wolfcrypt/random.py +EXTRA_DIST+= wrapper/python/wolfcrypt/wolfcrypt/utils.py diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/requirements-testing.txt b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/requirements-testing.txt new file mode 100644 index 000000000..61def5278 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/requirements-testing.txt @@ -0,0 +1,3 @@ +pytest>=2.9.1 +cffi>=1.6.0 +tox>=2.3.1 diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/setup.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/setup.py new file mode 100644 index 000000000..c22149a58 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/setup.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) 2006-2020 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 +#/ + +# Python 2.7 Standard Library +from __future__ import absolute_import +import os +import sys +from wolfcrypt.__about__ import metadata +from setuptools import setup, find_packages + +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(), + "cffi_modules": ["./wolfcrypt/build_ffi.py:ffi"], + }, + requirements = { + "setup_requires": ["cffi>=1.6.0"], + "install_requires": ["cffi>=1.6.0"], + }, + scripts = {}, + plugins = {}, + tests = {}, +) + +if __name__ == "__main__": + kwargs = {k:v for dct in info.values() for (k,v) in dct.items()} + setup(**kwargs) diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/test/test_ciphers.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/test/test_ciphers.py new file mode 100644 index 000000000..24ccb897b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/test/test_ciphers.py @@ -0,0 +1,192 @@ +# test_ciphers.py +# +# Copyright (C) 2006-2020 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 +#/ +import unittest +from wolfcrypt.ciphers import * +from wolfcrypt.utils import t2b, h2b + + +class TestAes(unittest.TestCase): + key = "0123456789abcdef" + IV = "1234567890abcdef" + plain = t2b("now is the time ") + cipher = h2b("959492575f4281532ccc9d4677a233cb") + + + def setUp(self): + self.aes = Aes.new(self.key, MODE_CBC, self.IV) + + + def test_raises(self): + # invalid key length + self.assertRaises(ValueError, Aes.new, "key", MODE_CBC, self.IV) + + # invalid mode + self.assertRaises(ValueError, Aes.new, self.key, MODE_ECB, self.IV) + + # invalid iv length + self.assertRaises(ValueError, Aes.new, self.key, MODE_CBC, "IV") + + # invalid data length + self.assertRaises(ValueError, self.aes.encrypt, "foo") + self.assertRaises(ValueError, self.aes.decrypt, "bar") + + + def test_single_encryption(self): + assert self.aes.encrypt(self.plain) == self.cipher + + + def test_multi_encryption(self): + result = t2b("") + segments = tuple(self.plain[i:i + self.aes.block_size] \ + for i in range(0, len(self.plain), self.aes.block_size)) + + for segment in segments: + result += self.aes.encrypt(segment) + + assert result == self.cipher + + + def test_single_decryption(self): + assert self.aes.decrypt(self.cipher) == self.plain + + + def test_multi_decryption(self): + result = t2b("") + segments = tuple(self.cipher[i:i + self.aes.block_size] \ + for i in range(0, len(self.cipher), self.aes.block_size)) + + for segment in segments: + result += self.aes.decrypt(segment) + + assert result == self.plain + + +class TestRsaPrivate(unittest.TestCase): + key = "3082025C02010002818100BC730EA849F374A2A9EF18A5DA559921F9C8ECB36D" \ + + "48E53535757737ECD161905F3ED9E4D5DF94CAC1A9D719DA86C9E84DC4613682" \ + + "FEABAD7E7725BB8D11A5BC623AA838CC39A20466B4F7F7F3AADA4D020EBB5E8D" \ + + "6948DC77C9280E22E96BA426BA4CE8C1FD4A6F2B1FEF8AAEF69062E5641EEB2B" \ + + "3C67C8DC2700F6916865A902030100010281801397EAE8387825A25C04CE0D40" \ + + "7C31E5C470CD9B823B5809863B665FDC3190F14FD5DB15DDDED73B9593311831" \ + + "0E5EA3D6A21A716E81481C4BCFDB8E7A866132DCFB55C1166D279224458BF1B8" \ + + "48B14B1DACDEDADD8E2FC291FBA5A96EF83A6AF1FD5018EF9FE7C3CA78EA56D3" \ + + "D3725B96DD4E064E3AC3D9BE72B66507074C01024100FA47D47A7C923C55EF81" \ + + "F041302DA3CF8F1CE6872705700DDF9835D6F18B382F24B5D084B6794F712994" \ + + "5AF0646AACE772C6ED4D59983E673AF3742CF9611769024100C0C1820D0CEBC6" \ + + "2FDC92F99D821A31E9E9F74BF282871CEE166AD11D188270F3C0B62FF6F3F71D" \ + + "F18623C84EEB8F568E8FF5BFF1F72BB5CC3DC657390C1B54410241009D7E05DE" \ + + "EDF4B7B2FBFC304B551DE32F0147966905CD0E2E2CBD8363B6AB7CB76DCA5B64" \ + + "A7CEBE86DF3B53DE61D21EEBA5F637EDACAB78D94CE755FBD71199C102401898" \ + + "1829E61E2739702168AC0A2FA172C121869538C65890A0579CBAE3A7B115C8DE" \ + + "F61BC2612376EFB09D1C44BE1343396717C89DCAFBF545648B38822CF2810240" \ + + "3989E59C195530BAB7488C48140EF49F7E779743E1B419353123759C3B44AD69" \ + + "1256EE0061641666D37C742B15B4A2FEBF086B1A5D3F9012B105863129DBD9E2" + + plain = t2b("Everyone gets Friday off.") + + + def setUp(self): + self.rsa = RsaPrivate(h2b(self.key)) + + + def test_raises(self): + # invalid key + self.assertRaises(WolfCryptError, RsaPrivate, 'key') + + + def test_output_size(self): + assert self.rsa.output_size == 1024 / 8 + + + def test_encrypt_decrypt(self): + cipher = self.rsa.encrypt(self.plain) + result = self.rsa.decrypt(cipher) + + assert len(cipher) == self.rsa.output_size == 1024 / 8 + assert self.plain == result + + + def test_sign_verify(self): + signature = self.rsa.sign(self.plain) + result = self.rsa.verify(signature) + + assert len(signature) == self.rsa.output_size == 1024 / 8 + assert self.plain == result + + +class TestRsaPublic(unittest.TestCase): + prv = "3082025C02010002818100BC730EA849F374A2A9EF18A5DA559921F9C8ECB36D" \ + + "48E53535757737ECD161905F3ED9E4D5DF94CAC1A9D719DA86C9E84DC4613682" \ + + "FEABAD7E7725BB8D11A5BC623AA838CC39A20466B4F7F7F3AADA4D020EBB5E8D" \ + + "6948DC77C9280E22E96BA426BA4CE8C1FD4A6F2B1FEF8AAEF69062E5641EEB2B" \ + + "3C67C8DC2700F6916865A902030100010281801397EAE8387825A25C04CE0D40" \ + + "7C31E5C470CD9B823B5809863B665FDC3190F14FD5DB15DDDED73B9593311831" \ + + "0E5EA3D6A21A716E81481C4BCFDB8E7A866132DCFB55C1166D279224458BF1B8" \ + + "48B14B1DACDEDADD8E2FC291FBA5A96EF83A6AF1FD5018EF9FE7C3CA78EA56D3" \ + + "D3725B96DD4E064E3AC3D9BE72B66507074C01024100FA47D47A7C923C55EF81" \ + + "F041302DA3CF8F1CE6872705700DDF9835D6F18B382F24B5D084B6794F712994" \ + + "5AF0646AACE772C6ED4D59983E673AF3742CF9611769024100C0C1820D0CEBC6" \ + + "2FDC92F99D821A31E9E9F74BF282871CEE166AD11D188270F3C0B62FF6F3F71D" \ + + "F18623C84EEB8F568E8FF5BFF1F72BB5CC3DC657390C1B54410241009D7E05DE" \ + + "EDF4B7B2FBFC304B551DE32F0147966905CD0E2E2CBD8363B6AB7CB76DCA5B64" \ + + "A7CEBE86DF3B53DE61D21EEBA5F637EDACAB78D94CE755FBD71199C102401898" \ + + "1829E61E2739702168AC0A2FA172C121869538C65890A0579CBAE3A7B115C8DE" \ + + "F61BC2612376EFB09D1C44BE1343396717C89DCAFBF545648B38822CF2810240" \ + + "3989E59C195530BAB7488C48140EF49F7E779743E1B419353123759C3B44AD69" \ + + "1256EE0061641666D37C742B15B4A2FEBF086B1A5D3F9012B105863129DBD9E2" + + pub = "30819F300D06092A864886F70D010101050003818D0030818902818100BC730E" \ + + "A849F374A2A9EF18A5DA559921F9C8ECB36D48E53535757737ECD161905F3ED9" \ + + "E4D5DF94CAC1A9D719DA86C9E84DC4613682FEABAD7E7725BB8D11A5BC623AA8" \ + + "38CC39A20466B4F7F7F3AADA4D020EBB5E8D6948DC77C9280E22E96BA426BA4C" \ + + "E8C1FD4A6F2B1FEF8AAEF69062E5641EEB2B3C67C8DC2700F6916865A90203010001" + + plain = t2b("Everyone gets Friday off.") + + + def setUp(self): + self.private = RsaPrivate(h2b(self.prv)) + self.public = RsaPublic(h2b(self.pub)) + + + def test_raises(self): + # invalid key + self.assertRaises(WolfCryptError, RsaPublic, 'key') + + + def test_output_size(self): + assert self.public.output_size == 1024 / 8 + + + def test_encrypt_decrypt(self): + cipher = self.public.encrypt(self.plain) + result = self.private.decrypt(cipher) + + assert len(cipher) == self.public.output_size == 1024 / 8 + assert self.plain == result + + + def test_sign_verify(self): + signature = self.private.sign(self.plain) + result = self.public.verify(signature) + + assert len(signature) == self.public.output_size == 1024 / 8 + assert self.plain == result diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/test/test_hashes.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/test/test_hashes.py new file mode 100644 index 000000000..b9f2ccc20 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/test/test_hashes.py @@ -0,0 +1,150 @@ +# test_hashes.py +# +# Copyright (C) 2006-2020 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 +#/ +import unittest +from wolfcrypt.hashes import * +from wolfcrypt.utils import t2b, h2b + + +class TestSha(unittest.TestCase): + _class = Sha + digest = t2b("1b6182d68ae91ce0853bd9c6b6edfedd4b6a510d") + + + def setUp(self): + self.hash = self._class() + + + def test_new(self): + # update inside constructor + assert self._class.new("wolfcrypt").hexdigest() == self.digest + + + def test_hash_update_001(self): + self.hash.update("wolfcrypt") + + assert self.hash.hexdigest() == self.digest + assert self.hash.digest() == h2b(self.digest) + + + def test_hash_update_002(self): + self.hash.update("wolf") + self.hash.update("crypt") + + assert self.hash.hexdigest() == self.digest + assert self.hash.digest() == h2b(self.digest) + + + def test_hash_copy(self): + copy = self.hash.copy() + + assert self.hash.hexdigest() == copy.hexdigest() + + self.hash.update("wolfcrypt") + + assert self.hash.hexdigest() != copy.hexdigest() + + copy.update("wolfcrypt") + + assert self.hash.hexdigest() == copy.hexdigest() == self.digest + + +class TestSha256(TestSha): + _class = Sha256 + digest = t2b("96e02e7b1cbcd6f104fe1fdb4652027a" \ + + "5505b68652b70095c6318f9dce0d1844") + + +class TestSha384(TestSha): + _class = Sha384 + digest = t2b("4c79d80531203a16f91bee325f18c6aada47f9382fe44fc1" \ + + "1f92917837e9b7902f5dccb7d3656f667a1dce3460bc884b") + + +class TestSha512(TestSha): + _class = Sha512 + digest = t2b("88fcf67ffd8558d713f9cedcd852db47" \ + + "9e6573f0bd9955610a993f609637553c" \ + + "e8fff55e644ee8a106aae19c07f91b3f" \ + + "2a2a6d40dfa7302c0fa6a1a9a5bfa03f") + + +_HMAC_KEY = "python" + + +class TestHmacSha(unittest.TestCase): + _class = HmacSha + digest = t2b("5dfabcfb3a25540824867cd21f065f52f73491e0") + + + def setUp(self): + self.hash = self._class(_HMAC_KEY) + + + def test_new(self): + # update inside constructor + assert self._class.new(_HMAC_KEY,"wolfcrypt").hexdigest() == self.digest + + + def test_hash_update_001(self): + self.hash.update("wolfcrypt") + + assert self.hash.hexdigest() == self.digest + + + def test_hash_update_002(self): + self.hash.update("wolf") + self.hash.update("crypt") + + assert self.hash.hexdigest() == self.digest + + + def test_hash_copy(self): + copy = self.hash.copy() + + assert self.hash.hexdigest() == copy.hexdigest() + + self.hash.update("wolfcrypt") + + assert self.hash.hexdigest() != copy.hexdigest() + + copy.update("wolfcrypt") + + assert self.hash.hexdigest() == copy.hexdigest() == self.digest + + +class TestHmacSha256(TestHmacSha): + _class = HmacSha256 + digest = t2b("4b641d721493d80f019d9447830ebfee" \ + + "89234a7d594378b89f8bb73873576bf6") + + +class TestHmacSha384(TestHmacSha): + _class = HmacSha384 + digest = t2b("e72c72070c9c5c78e3286593068a510c1740cdf9dc34b512" \ + + "ccec97320295db1fe673216b46fe72e81f399a9ec04780ab") + + +class TestHmacSha512(TestHmacSha): + _class = HmacSha512 + digest = t2b("c7f48db79314fc2b5be9a93fd58601a1" \ + + "bf42f397ec7f66dba034d44503890e6b" \ + + "5708242dcd71a248a78162d815c685f6" \ + + "038a4ac8cb34b8bf18986dbd300c9b41") diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/test/test_random.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/test/test_random.py new file mode 100644 index 000000000..1425f370c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/test/test_random.py @@ -0,0 +1,39 @@ +# test_random.py +# +# Copyright (C) 2006-2020 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 +#/ +import unittest +from wolfcrypt.random import * + + +class TestRandom(unittest.TestCase): + + + def setUp(self): + self.random = Random() + + + def test_byte(self): + assert len(self.random.byte()) == 1 + + + def test_bytes(self): + assert len(self.random.bytes(1)) == 1 + assert len(self.random.bytes(10)) == 10 + assert len(self.random.bytes(100)) == 100 diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/tox.ini b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/tox.ini new file mode 100644 index 000000000..98ec7f995 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/tox.ini @@ -0,0 +1,7 @@ +[tox] +envlist=py27,py34,py35 +skip_missing_interpreters=true + +[testenv] +deps=-rrequirements-testing.txt +commands=py.test test/ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/__about__.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/__about__.py new file mode 100644 index 000000000..d3c58086d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/__about__.py @@ -0,0 +1,46 @@ +# __about__.py +# +# Copyright (C) 2006-2020 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 +#/ + +metadata = dict( + __name__ = "wolfcrypt", + __version__ = "0.1.9", + __license__ = "GPLv2 or Commercial License", + __author__ = "wolfSSL Inc.", + __author_email__ = "info@wolfssl.com", + __url__ = "https://wolfssl.github.io/wolfcrypt-py", + __description__ = \ + u"A Python library that encapsulates wolfSSL's wolfCrypt API.", + __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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/__init__.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/__init__.py new file mode 100644 index 000000000..31d0235ef --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/__init__.py @@ -0,0 +1,22 @@ +# __init__.py +# +# Copyright (C) 2006-2020 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 +#/ + +from .__about__ import * diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/build_ffi.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/build_ffi.py new file mode 100644 index 000000000..ac03955cc --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/build_ffi.py @@ -0,0 +1,128 @@ +# build_ffi.py +# +# Copyright (C) 2006-2020 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 +#/ +import os + +from cffi import FFI + +ffi = FFI() + +ffi.set_source("wolfcrypt._ffi", + """ + #include + + #include + #include + #include + + #include + + #include + #include + #include + + #include + + #include + """, + include_dirs=["/usr/local/include"], + library_dirs=["/usr/local/lib"], + libraries=["wolfssl"], +) + +ffi.cdef( +""" + + typedef unsigned char byte; + typedef unsigned int word32; + + typedef struct { ...; } Sha; + + int wc_InitSha(Sha*); + int wc_ShaUpdate(Sha*, const byte*, word32); + int wc_ShaFinal(Sha*, byte*); + + + typedef struct { ...; } Sha256; + + int wc_InitSha256(Sha256*); + int wc_Sha256Update(Sha256*, const byte*, word32); + int wc_Sha256Final(Sha256*, byte*); + + + typedef struct { ...; } Sha384; + + int wc_InitSha384(Sha384*); + int wc_Sha384Update(Sha384*, const byte*, word32); + int wc_Sha384Final(Sha384*, byte*); + + + typedef struct { ...; } Sha512; + + int wc_InitSha512(Sha512*); + int wc_Sha512Update(Sha512*, const byte*, word32); + int wc_Sha512Final(Sha512*, byte*); + + + typedef struct { ...; } Hmac; + + int wc_HmacSetKey(Hmac*, int, const byte*, word32); + int wc_HmacUpdate(Hmac*, const byte*, word32); + int wc_HmacFinal(Hmac*, byte*); + + + typedef struct { ...; } Aes; + + int wc_AesSetKey(Aes*, const byte*, word32, const byte*, int); + int wc_AesCbcEncrypt(Aes*, byte*, const byte*, word32); + int wc_AesCbcDecrypt(Aes*, byte*, const byte*, word32); + + + typedef struct { ...; } WC_RNG; + + int wc_InitRng(WC_RNG*); + int wc_RNG_GenerateBlock(WC_RNG*, byte*, word32); + int wc_RNG_GenerateByte(WC_RNG*, byte*); + int wc_FreeRng(WC_RNG*); + + + typedef struct {...; } RsaKey; + + int wc_InitRsaKey(RsaKey* key, void*); + int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng); + int wc_FreeRsaKey(RsaKey* key); + + int wc_RsaPrivateKeyDecode(const byte*, word32*, RsaKey*, word32); + int wc_RsaPublicKeyDecode(const byte*, word32*, RsaKey*, word32); + int wc_RsaEncryptSize(RsaKey*); + + int wc_RsaPrivateDecrypt(const byte*, word32, byte*, word32, + RsaKey* key); + int wc_RsaPublicEncrypt(const byte*, word32, byte*, word32, + RsaKey*, WC_RNG*); + + int wc_RsaSSL_Sign(const byte*, word32, byte*, word32, RsaKey*, WC_RNG*); + int wc_RsaSSL_Verify(const byte*, word32, byte*, word32, RsaKey*); + +""" +) + +if __name__ == "__main__": + ffi.compile(verbose=1) diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/ciphers.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/ciphers.py new file mode 100644 index 000000000..c02cdbe33 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/ciphers.py @@ -0,0 +1,326 @@ +# ciphers.py +# +# Copyright (C) 2006-2020 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 +#/ +from wolfcrypt._ffi import ffi as _ffi +from wolfcrypt._ffi import lib as _lib +from wolfcrypt.utils import t2b +from wolfcrypt.random import Random + +from wolfcrypt.exceptions import * + + +# key direction flags +_ENCRYPTION = 0 +_DECRYPTION = 1 + + +# feedback modes +MODE_ECB = 1 # Electronic Code Book +MODE_CBC = 2 # Cipher Block Chaining +MODE_CFB = 3 # Cipher Feedback +MODE_OFB = 5 # Output Feedback +MODE_CTR = 6 # Counter + +_FEEDBACK_MODES = [MODE_ECB, MODE_CBC, MODE_CFB, MODE_OFB, MODE_CTR] + + +class _Cipher(object): + """ + A **PEP 272: Block Encryption Algorithms** compliant + **Symmetric Key Cipher**. + """ + def __init__(self, key, mode, IV=None): + if mode not in _FEEDBACK_MODES: + raise ValueError("this mode is not supported") + + if mode == MODE_CBC: + if IV is None: + raise ValueError("this mode requires an 'IV' string") + else: + raise ValueError("this mode is not supported by this cipher") + + if self.key_size: + if self.key_size != len(key): + raise ValueError("key must be %d in length" % self.key_size) + elif self._key_sizes: + if len(key) not in self._key_sizes: + raise ValueError("key must be %s in length" % self._key_sizes) + else: + if not len(key): + raise ValueError("key must not be 0 in length") + + if IV is not None and len(IV) != self.block_size: + raise ValueError("IV must be %d in length" % self.block_size) + + self._native_object = _ffi.new(self._native_type) + self._enc = None + self._dec = None + self._key = t2b(key) + + if IV: + self._IV = t2b(IV) + else: + self._IV = t2b("\0" * self.block_size) + + + @classmethod + def new(cls, key, mode, IV=None, **kwargs): + """ + Returns a ciphering object, using the secret key contained in + the string **key**, and using the feedback mode **mode**, which + must be one of MODE_* defined in this module. + + If **mode** is MODE_CBC or MODE_CFB, **IV** must be provided and + must be a string of the same length as the block size. Not + providing a value of **IV** will result in a ValueError exception + being raised. + """ + return cls(key, mode, IV) + + + def encrypt(self, string): + """ + Encrypts a non-empty string, using the key-dependent data in + the object, and with the appropriate feedback mode. The + string's length must be an exact multiple of the algorithm's + block size or, in CFB mode, of the segment size. Returns a + string containing the ciphertext. + """ + string = t2b(string) + + if not string or len(string) % self.block_size: + raise ValueError( + "string must be a multiple of %d in length" % self.block_size) + + if self._enc is None: + self._enc = _ffi.new(self._native_type) + ret = self._set_key(_ENCRYPTION) + if ret < 0: + raise WolfCryptError("Invalid key error (%d)" % ret) + + result = t2b("\0" * len(string)) + ret = self._encrypt(result, string) + if ret < 0: + raise WolfCryptError("Encryption error (%d)" % ret) + + return result + + + def decrypt(self, string): + """ + Decrypts **string**, using the key-dependent data in the + object and with the appropriate feedback mode. The string's + length must be an exact multiple of the algorithm's block + size or, in CFB mode, of the segment size. Returns a string + containing the plaintext. + """ + string = t2b(string) + + if not string or len(string) % self.block_size: + raise ValueError( + "string must be a multiple of %d in length" % self.block_size) + + if self._dec is None: + self._dec = _ffi.new(self._native_type) + ret = self._set_key(_DECRYPTION) + if ret < 0: + raise WolfCryptError("Invalid key error (%d)" % ret) + + result = t2b("\0" * len(string)) + ret = self._decrypt(result, string) + if ret < 0: + raise WolfCryptError("Decryption error (%d)" % ret) + + return result + + +class Aes(_Cipher): + """ + The **Advanced Encryption Standard** (AES), a.k.a. Rijndael, is + a symmetric-key cipher standardized by **NIST**. + """ + block_size = 16 + key_size = None # 16, 24, 32 + _key_sizes = [16, 24, 32] + _native_type = "Aes *" + + + def _set_key(self, direction): + if direction == _ENCRYPTION: + return _lib.wc_AesSetKey( + self._enc, self._key, len(self._key), self._IV, _ENCRYPTION) + else: + return _lib.wc_AesSetKey( + self._dec, self._key, len(self._key), self._IV, _DECRYPTION) + + + def _encrypt(self, destination, source): + return _lib.wc_AesCbcEncrypt(self._enc, destination, source,len(source)) + + + def _decrypt(self, destination, source): + return _lib.wc_AesCbcDecrypt(self._dec, destination, source,len(source)) + + +class _Rsa(object): + RSA_MIN_PAD_SIZE = 11 + + def __init__(self): + self.native_object = _ffi.new("RsaKey *") + ret = _lib.wc_InitRsaKey(self.native_object, _ffi.NULL) + if ret < 0: + raise WolfCryptError("Invalid key error (%d)" % ret) + + self._random = Random() + ret = _lib.wc_RsaSetRNG(self.native_object, self._random.native_object) + if ret < 0: + raise WolfCryptError("Key initialization error (%d)" % ret) + + + def __del__(self): + if self.native_object: + _lib.wc_FreeRsaKey(self.native_object) + + +class RsaPublic(_Rsa): + def __init__(self, key): + key = t2b(key) + + _Rsa.__init__(self) + + idx = _ffi.new("word32*") + idx[0] = 0 + + ret = _lib.wc_RsaPublicKeyDecode(key, idx, self.native_object, len(key)) + if ret < 0: + raise WolfCryptError("Invalid key error (%d)" % ret) + + self.output_size = _lib.wc_RsaEncryptSize(self.native_object) + if self.output_size <= 0: + raise WolfCryptError("Invalid key error (%d)" % self.output_size) + + + def encrypt(self, plaintext): + """ + Encrypts **plaintext**, using the public key data in the + object. The plaintext's length must not be greater than: + + **self.output_size - self.RSA_MIN_PAD_SIZE** + + Returns a string containing the ciphertext. + """ + + plaintext = t2b(plaintext) + ciphertext = t2b("\0" * self.output_size) + + ret = _lib.wc_RsaPublicEncrypt(plaintext, len(plaintext), + ciphertext, len(ciphertext), + self.native_object, + self._random.native_object) + + if ret != self.output_size: + raise WolfCryptError("Encryption error (%d)" % ret) + + return ciphertext + + + def verify(self, signature): + """ + Verifies **signature**, using the public key data in the + object. The signature's length must be equal to: + + **self.output_size** + + Returns a string containing the plaintext. + """ + signature = t2b(signature) + plaintext = t2b("\0" * self.output_size) + + ret = _lib.wc_RsaSSL_Verify(signature, len(signature), + plaintext, len(plaintext), + self.native_object) + + if ret < 0: + raise WolfCryptError("Verify error (%d)" % ret) + + return plaintext[:ret] + + +class RsaPrivate(RsaPublic): + def __init__(self, key): + key = t2b(key) + + _Rsa.__init__(self) + + idx = _ffi.new("word32*") + idx[0] = 0 + + ret = _lib.wc_RsaPrivateKeyDecode(key, idx, self.native_object,len(key)) + if ret < 0: + raise WolfCryptError("Invalid key error (%d)" % ret) + + self.output_size = _lib.wc_RsaEncryptSize(self.native_object) + if self.output_size <= 0: + raise WolfCryptError("Invalid key error (%d)" % self.output_size) + + + def decrypt(self, ciphertext): + """ + Decrypts **ciphertext**, using the private key data in the + object. The ciphertext's length must be equal to: + + **self.output_size** + + Returns a string containing the plaintext. + """ + ciphertext = t2b(ciphertext) + plaintext = t2b("\0" * self.output_size) + + ret = _lib.wc_RsaPrivateDecrypt(ciphertext, len(ciphertext), + plaintext, len(plaintext), + self.native_object) + + if ret < 0: + raise WolfCryptError("Decryption error (%d)" % ret) + + return plaintext[:ret] + + + def sign(self, plaintext): + """ + Signs **plaintext**, using the private key data in the object. + The plaintext's length must not be greater than: + + **self.output_size - self.RSA_MIN_PAD_SIZE** + + Returns a string containing the signature. + """ + plaintext = t2b(plaintext) + signature = t2b("\0" * self.output_size) + + ret = _lib.wc_RsaSSL_Sign(plaintext, len(plaintext), + signature, len(signature), + self.native_object, + self._random.native_object) + + if ret != self.output_size: + raise WolfCryptError("Signature error (%d)" % ret) + + return signature diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/exceptions.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/exceptions.py new file mode 100644 index 000000000..26322b364 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/exceptions.py @@ -0,0 +1,24 @@ +# exceptions.py +# +# Copyright (C) 2006-2020 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 +#/ + + +class WolfCryptError(Exception): + pass diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/hashes.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/hashes.py new file mode 100644 index 000000000..346cb7bc0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/hashes.py @@ -0,0 +1,303 @@ +# hashes.py +# +# Copyright (C) 2006-2020 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 +#/ +from wolfcrypt._ffi import ffi as _ffi +from wolfcrypt._ffi import lib as _lib +from wolfcrypt.utils import t2b, b2h + +from wolfcrypt.exceptions import * + +class _Hash(object): + """ + A **PEP 247: Cryptographic Hash Functions** compliant + **Hash Function Interface**. + """ + def __init__(self, string=None): + self._native_object = _ffi.new(self._native_type) + ret = self._init() + if ret < 0: + raise WolfCryptError("Hash init error (%d)" % ret) + + if (string): + self.update(string) + + + @classmethod + def new(cls, string=None): + """ + Creates a new hashing object and returns it. The optional + **string** parameter, if supplied, will be immediately + hashed into the object's starting state, as if + obj.update(string) was called. + """ + return cls(string) + + + def copy(self): + """ + Returns a separate copy of this hashing object. An update + to this copy won't affect the original object. + """ + copy = self.new("") + + _ffi.memmove(copy._native_object, + self._native_object, + self._native_size) + + return copy + + + def update(self, string): + """ + Hashes **string** into the current state of the hashing + object. update() can be called any number of times during + a hashing object's lifetime. + """ + string = t2b(string) + + ret = self._update(string) + if ret < 0: + raise WolfCryptError("Hash update error (%d)" % ret) + + + def digest(self): + """ + Returns the hash value of this hashing object as a string + containing 8-bit data. The object is not altered in any + way by this function; you can continue updating the object + after calling this function. + """ + result = t2b("\0" * self.digest_size) + + if self._native_object: + obj = _ffi.new(self._native_type) + + _ffi.memmove(obj, self._native_object, self._native_size) + + ret = self._final(obj, result) + if ret < 0: + raise WolfCryptError("Hash finalize error (%d)" % ret) + + return result + + + def hexdigest(self): + """ + Returns the hash value of this hashing object as a string + containing hexadecimal digits. Lowercase letters are used + for the digits 'a' through 'f'. Like the .digest() method, + this method doesn't alter the object. + """ + return b2h(self.digest()) + + +class Sha(_Hash): + """ + **SHA-1** is a cryptographic hash function standardized by **NIST**. + + It produces an [ **160-bit | 20 bytes** ] message digest. + """ + digest_size = 20 + _native_type = "Sha *" + _native_size = _ffi.sizeof("Sha") + + + def _init(self): + return _lib.wc_InitSha(self._native_object) + + + def _update(self, data): + return _lib.wc_ShaUpdate(self._native_object, data, len(data)) + + + def _final(self, obj, ret): + return _lib.wc_ShaFinal(obj, ret) + + +class Sha256(_Hash): + """ + **SHA-256** is a cryptographic hash function from the + **SHA-2 family** and is standardized by **NIST**. + + It produces a [ **256-bit | 32 bytes** ] message digest. + """ + digest_size = 32 + _native_type = "Sha256 *" + _native_size = _ffi.sizeof("Sha256") + + + def _init(self): + return _lib.wc_InitSha256(self._native_object) + + + def _update(self, data): + return _lib.wc_Sha256Update(self._native_object, data, len(data)) + + + def _final(self, obj, ret): + return _lib.wc_Sha256Final(obj, ret) + + +class Sha384(_Hash): + """ + **SHA-384** is a cryptographic hash function from the + **SHA-2 family** and is standardized by **NIST**. + + It produces a [ **384-bit | 48 bytes** ] message digest. + """ + digest_size = 48 + _native_type = "Sha384 *" + _native_size = _ffi.sizeof("Sha384") + + + def _init(self): + return _lib.wc_InitSha384(self._native_object) + + + def _update(self, data): + return _lib.wc_Sha384Update(self._native_object, data, len(data)) + + + def _final(self, obj, ret): + return _lib.wc_Sha384Final(obj, ret) + + +class Sha512(_Hash): + """ + **SHA-512** is a cryptographic hash function from the + **SHA-2 family** and is standardized by **NIST**. + + It produces a [ **512-bit | 64 bytes** ] message digest. + """ + digest_size = 64 + _native_type = "Sha512 *" + _native_size = _ffi.sizeof("Sha512") + + + def _init(self): + return _lib.wc_InitSha512(self._native_object) + + + def _update(self, data): + return _lib.wc_Sha512Update(self._native_object, data, len(data)) + + + def _final(self, obj, ret): + return _lib.wc_Sha512Final(obj, ret) + + +# Hmac types + +_TYPE_SHA = 1 +_TYPE_SHA256 = 2 +_TYPE_SHA384 = 5 +_TYPE_SHA512 = 4 +_HMAC_TYPES = [_TYPE_SHA, _TYPE_SHA256, _TYPE_SHA384, _TYPE_SHA512] + + +class _Hmac(_Hash): + """ + A **PEP 247: Cryptographic Hash Functions** compliant + **Keyed Hash Function Interface**. + """ + digest_size = None + _native_type = "Hmac *" + _native_size = _ffi.sizeof("Hmac") + + + def __init__(self, key, string=None): + key = t2b(key) + + self._native_object = _ffi.new(self._native_type) + ret = self._init(self._type, key) + if ret < 0: + raise WolfCryptError("Hmac init error (%d)" % ret) + + if (string): + self.update(string) + + + + @classmethod + def new(cls, key, string=None): + """ + Creates a new hashing object and returns it. **key** is + a required parameter containing a string giving the key + to use. The optional **string** parameter, if supplied, + will be immediately hashed into the object's starting + state, as if obj.update(string) was called. + """ + return cls(key, string) + + + def _init(self, type, key): + return _lib.wc_HmacSetKey(self._native_object, type, key, len(key)) + + + def _update(self, data): + return _lib.wc_HmacUpdate(self._native_object, data, len(data)) + + + def _final(self, obj, ret): + return _lib.wc_HmacFinal(obj, ret) + + +class HmacSha(_Hmac): + """ + A HMAC function using **SHA-1** as it's cryptographic + hash function. + + It produces a [ **512-bit | 64 bytes** ] message digest. + """ + _type = _TYPE_SHA + digest_size = Sha.digest_size + + +class HmacSha256(_Hmac): + """ + A HMAC function using **SHA-256** as it's cryptographic + hash function. + + It produces a [ **512-bit | 64 bytes** ] message digest. + """ + _type = _TYPE_SHA256 + digest_size = Sha256.digest_size + + +class HmacSha384(_Hmac): + """ + A HMAC function using **SHA-384** as it's cryptographic + hash function. + + It produces a [ **512-bit | 64 bytes** ] message digest. + """ + _type = _TYPE_SHA384 + digest_size = Sha384.digest_size + + +class HmacSha512(_Hmac): + """ + A HMAC function using **SHA-512** as it's cryptographic + hash function. + + It produces a [ **512-bit | 64 bytes** ] message digest. + """ + _type = _TYPE_SHA512 + digest_size = Sha512.digest_size diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/random.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/random.py new file mode 100644 index 000000000..f32b9b77c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/random.py @@ -0,0 +1,73 @@ +# random.py +# +# Copyright (C) 2006-2020 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 +#/ +from wolfcrypt._ffi import ffi as _ffi +from wolfcrypt._ffi import lib as _lib +from wolfcrypt.utils import t2b + +from wolfcrypt.exceptions import * + + +class Random(object): + """ + A Cryptographically Secure Pseudo Random Number Generator - CSPRNG + """ + def __init__(self): + self.native_object = _ffi.new("WC_RNG *") + + ret = _lib.wc_InitRng(self.native_object) + if ret < 0: + self.native_object = None + raise WolfCryptError("RNG init error (%d)" % ret) + + + def __del__(self): + if self.native_object: + try: + _lib.wc_FreeRng(self.native_object) + except AttributeError: + # Can occur during interpreter shutdown + pass + + + def byte(self): + """ + Generate and return a random byte. + """ + result = _ffi.new('byte[1]') + + ret = _lib.wc_RNG_GenerateByte(self.native_object, result) + if ret < 0: + raise WolfCryptError("RNG generate byte error (%d)" % ret) + + return _ffi.buffer(result, 1)[:] + + + def bytes(self, length): + """ + Generate and return a random sequence of length bytes. + """ + result = _ffi.new('byte[%d]' % length) + + ret = _lib.wc_RNG_GenerateBlock(self.native_object, result, length) + if ret < 0: + raise WolfCryptError("RNG generate block error (%d)" % ret) + + return _ffi.buffer(result, length)[:] diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/utils.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/utils.py new file mode 100644 index 000000000..537800f4c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfcrypt/wolfcrypt/utils.py @@ -0,0 +1,37 @@ +# utils.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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 + +def t2b(string): + """ + Converts text to bynary. + """ + if isinstance(string, _BINARY_TYPE): + return string + return _TEXT_TYPE(string).encode("utf-8") diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/.centos-provisioner.sh b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/.centos-provisioner.sh new file mode 100644 index 000000000..fc0ec19a7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/.gitignore b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/.gitignore new file mode 100644 index 000000000..d3d507b23 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/.ubuntu-provisioner.sh b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/.ubuntu-provisioner.sh new file mode 100644 index 000000000..30ee7f6fc --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/LICENSING.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/LICENSING.rst new file mode 100644 index 000000000..2fc46fc9c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/MANIFEST.in b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/MANIFEST.in new file mode 100644 index 000000000..31b8bcfa9 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/MANIFEST.in @@ -0,0 +1,2 @@ +include LICENSING.rst +recursive-include certs *.pem diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/Makefile b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/Makefile new file mode 100644 index 000000000..5b3f9f869 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/Makefile @@ -0,0 +1,59 @@ +# Makefile +# +# Copyright (C) 2006-2020 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 +#/ + +.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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/README.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/README.rst new file mode 100644 index 000000000..1a8e7250a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/Vagrantfile b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/Vagrantfile new file mode 100644 index 000000000..cd83995c6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/Makefile b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/Makefile new file mode 100644 index 000000000..7d24fb014 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/Makefile @@ -0,0 +1,60 @@ +# Makefile +# +# Copyright (C) 2006-2020 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 +#/ + +.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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/api.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/api.rst new file mode 100644 index 000000000..e6d2538ae --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/conf.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/conf.py new file mode 100644 index 000000000..612116f38 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/examples.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/examples.rst new file mode 100644 index 000000000..5d2279f62 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/index.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/index.rst new file mode 100644 index 000000000..344919f7f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/index.rst @@ -0,0 +1,8 @@ +.. toctree:: + :maxdepth: 2 + + installation + usage + api + examples + licensing diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/installation.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/installation.rst new file mode 100644 index 000000000..72a335581 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/installation.rst @@ -0,0 +1 @@ +.. include:: ../README.rst diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/licensing.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/licensing.rst new file mode 100644 index 000000000..f5cc633bb --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/licensing.rst @@ -0,0 +1 @@ +.. include:: ../LICENSING.rst diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/requirements.txt b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/requirements.txt new file mode 100644 index 000000000..ab3f3dd41 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/requirements.txt @@ -0,0 +1,2 @@ +Sphinx +sphinx_rtd_theme diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/usage.rst b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/docs/usage.rst new file mode 100644 index 000000000..47c2f0981 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/examples/client.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/examples/client.py new file mode 100644 index 000000000..0ae7d57ce --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/examples/client.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python +# +# -*- coding: utf-8 -*- +# +# client.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/examples/server.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/examples/server.py new file mode 100644 index 000000000..a44b7e116 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/examples/server.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python +# +# -*- coding: utf-8 -*- +# +# server.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/include.am b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/include.am new file mode 100644 index 000000000..0c5d06bc1 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/requirements-testing.txt b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/requirements-testing.txt new file mode 100644 index 000000000..c422b4d23 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/requirements-testing.txt @@ -0,0 +1,3 @@ +pytest +cffi +tox diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/setup.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/setup.py new file mode 100644 index 000000000..217b59700 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/setup.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# setup.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/__about__.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/__about__.py new file mode 100644 index 000000000..35b983ab7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/__about__.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# +# __about__.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/__init__.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/__init__.py new file mode 100644 index 000000000..decef9595 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/__init__.py @@ -0,0 +1,678 @@ +# -*- coding: utf-8 -*- +# +# __init__.py +# +# Copyright (C) 2006-2020 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 +#/ + +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, wrapping 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 with 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/_memory.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/_memory.py new file mode 100644 index 000000000..0b6bb9f82 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/_memory.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# +# _memory.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/_methods.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/_methods.py new file mode 100644 index 000000000..bde5eb1bf --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/_methods.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# +# _methods.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/build_ffi.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/build_ffi.py new file mode 100644 index 000000000..acfe013da --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/build_ffi.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# +# build_ffi.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/exceptions.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/exceptions.py new file mode 100644 index 000000000..748732254 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/exceptions.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# +# exceptions.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/utils.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/utils.py new file mode 100644 index 000000000..721f2b96f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/src/wolfssl/utils.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# +# utils.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/conftest.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/conftest.py new file mode 100644 index 000000000..d87164325 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/conftest.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# +# conftest.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/test_client.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/test_client.py new file mode 100644 index 000000000..7ebf91fee --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/test_client.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# +# test_client.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/test_context.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/test_context.py new file mode 100644 index 000000000..6575ed6da --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/test_context.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# +# test_context.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/test_methods.py b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/test_methods.py new file mode 100644 index 000000000..f94038341 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/test/test_methods.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# +# test_methods.py +# +# Copyright (C) 2006-2020 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 +#/ + +# 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/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/tox.ini b/FreeRTOS-Plus/Source/WolfSSL/wrapper/python/wolfssl/tox.ini new file mode 100644 index 000000000..d552f72b3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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}

2G&UN!6tmu;_)+V*#?OF% zgZ%Vk&AClox%p>d6t_Bv%fDDdKN0zA2RAQx>+N4b1P@YEskJMu{B?uQyyWxUYYMZ= zcjM^4Y6rL#I>U_!8NgaQJt8Ro$@Fq6_UDb-Mr$miexK`_$j-r8pMgm7xfi7($zS>v zd04*U-~jI6?6~#zLY%Inw4`HhM7s84&mg^M{v|@vu~^r7l&01Vl%Sw61}P5osOB0- z#2Q||!CPoP-$#p;)D$jm0M6}TU+@99GCq9i5&(FL+Uy%J-nrKSOph%@({SaupJe)< z;~WYn2|%n(uZ;<^-QROcv>U58)fgZjJ;za^5ajzS^A|vVA;T|1`0wKkVRuCJAb8oW zK+9#p=?dS@!d#)!^NzPQVP6PS`Jeo=wuyL#QNA{CrX*636fM{Y1m-x)?oce=AAAzr z-{01GuA%0C&6WYUOZxmPZ~yPPSf~yte=N?;$qXfMxx+jbZIb&LFzg`_Gkm{u=lHn1 zKlzNg<~#)ke#HXWhher2&t}Fu${d&L(v0?jA7AN5@{vv$?^4L?@Ja1$!6o8gNYrp= zSIu76x1jUiL*g~QPJ zWbKDrDrE`7-a+I?>pxdL0R_y2DC3B)y<{j=f@0utE3!*DDpZ2jfFri9Ka^qUZna0cN-) zIhh*vs_;95Vqd?g>yWVSFXn{GM$nIf0RMZ;816p5bm`N757mAhl?)E5saVy+=zS>F z4~y^r3|J`HU_A0Voq(Pp&T#6ldybcU1^{bbESpmv5R?|8v7tz|mo~)T0JcEtBqdBo z9!@kcLS>%te69{PmJWEldB}P+DTJ-OfD!s;;4^@e{f(b$&ELKB#oVA3A{o5f0fyQe z*R4`N@#5Z zjNXzzDeyC(Pc|7FxO&RD9y1%(tc^EoFZxM@B@eV64O)0tZvH)WlSFuiuZDzrjD}dK z@Ibc7_C5nrmpr^2vXIe;k*1WH{qFPv4!5ZHi{}xVaMw-TiTlN#`b4b+y^-AyHj6WwvnHg}6owoXZxYr%X3*=>)8+waRg# zhO_iF(b{Oj+_r$*qm^3grJU8FleA~3YJph`%8Q)`to?c%o~+WqSr_Y(DCJ5!)&ZfX z0z92sD82?RE#y8^kT!vU1zMrfrbBoxojnuT-AQJ$P^CIbuELA%K{qXQk2|(?`mjgX zFfVZ{HEcAOWUd6Yq_K_oGebF6br6z#_LAoxX2nprB`CA#-$0}=4U@@xmC0d1rz{@@ z?yejjghu|pq?#wS-8lo+V0beNJd(eU+j`7$yv3Ce5ws$hzjNTlpx$3EN>OoCb3lJZ zm}_&nCi^qsrR@b@@1A6O^J8tjQQaN4ZRpr3Q55LUqN?6^-WR4SW3dj~DTFEG*d3D$ z9w)r=`lUz>_IaQ8cL`TCVxRM#i?Stc}OfBUO;07`PKtu|>c_Qd#{ z(dj4U+D1*4RtMOQnFz^=iHuE`|W#0yKQWk`Y$OEN>$?_R=Ynd%p5 zH^LZIDW%z8eL5DEJ{wsRI{VmNQ(DoMrP_0eOj`_UXyAIlLX*;Z zA!M8WBzof8ux>K%kEA_mPLtDwO613Oone~ZA!IP1H4W&(Z0S>`EAbR_WxY*-7%*Ce zO*mkcQpXzBhkIkr7wYz|qkM}_YDR&kWnc@YzY}pF8I^r2HKtDM&7xZ5o{b1H)nS#W z?I>_Lr~FS#%^Nxb?M>K;nwd?E>df|G!yo&vD@WCQo6x~3%^(C3FYP8sy>d!_Y*XrR zN_rernY-|Je8<^8-B?06FHSUoT6gXUrZDAX-->!2IU1@f;nF>#HKdz7&yw6N=GdL( zpcO!)#zbWq88tE@xkx(hMxO)KV_hj9X38`=C~V5ntDGguPN)6=iXJ{@HJ%C~hY4kk zG&E(zDm0?PdiW}>;5#Af_jP#t$Bar`Cp{G)5S?dD&K{L2T1>0&%L%1YV4U`O$SX`j zX`Re>H15}8LgM&$i4an8GxjO=^Q|tdMc(06(^izJHm>GE$T0PaHh2C|lKOo!4Ik7F z7thngwU|${nL(Y}J872Lr9B^cBNDfveNFS!D&cspeO0Sph9@;UrS|Bc6_)4ApJT%Bdo2^*(xpZmh4VQBGmaHR#>;dMc5!T?nBoo@ zW_;shR8yGJrGnZW|F#Y{CuU(ShfRilbyfJ#PV?WO#H8Nn>;2GW_t}QRZC8CI9jsV2 z9lIA^{B-&HKM0Hdt33DpB`^3ld5Rdbi~Y@F)nz&k|Cr2M~6a1g{4NqF6 z9Q9gpV5K~^D8tj0-)L6UBMGBBFwA5Rk=Ff*r-Xj(HNU;+*=p_#(2cL2{IMrgIDRtp zZ8ZrbpiU@iQ#dAykudvZZlg#U|^&73cn+^6&)`}fZE?uxoZhhes6ycJuku{9zW zhJ`ky+)8V=Oj?8r`$e!V`}2&Bk{tn}G_OD^zkXr10U z@cnuX7N+t;U_5xpz9oQ;Z-d?cr(-_)j}CcW#@F{6kw8&9Mv~2<$?|o=x6$~JE|;{4 z#6uYk`{b~Z;tB!NqJN7R|IJfv8vY+a1^3}y@v7?!MGJb*5Ax_7{(H5~1!viwJ(l~E z;oDDJpYSSitdMWFTV(0R^&4Ftz&VA-y;h}i%{cH^5Wua53Gkfddiwls<3fb<~R7=JnBCKx<1)`B))C7Nlc5(H(fHFk<-+# z+js4kHR5eer$0^!K_ovfu5Z&o|GCjH-^=cyDDTFa*Wb6WuLNM@_n8}7OqVDLgvxa*6K#G5eCW@mP-vgl z{oY9UJ9e#-{+Q&C8U1#XeRloUXMpI7`frF5+WljWzCWe}m^%AYKT91ZgkH5~q=ZNd zJbQIz-eszz0vea^$QN$@L~$SHr_}Ug)E_wgkLU?}{MX1A{!Zi4U3gYt5(3vqrL{cA za2m=SvoOVaSH`+qjog&(J8&nzPrupJDzI|~XoU(;^28#(L8e&CZmDtAG9(amz`H8_YONEDYPLXtXQkd? zJ_Bltirn)<=`UOD8R_UYGyQqpx}}QxBaXN{PPFA$B180O@!oSJ~!IA$dy8VN){&VF2tDC=OjlW>?3pW3eE%g`PJQq+U?Zqj<)BO#l33n`Z zV3UIutB6)EhELtNcfhr}PB&0bBs z=lS9NX@uwpzuuA~E$=hGGsRCm&u;9wB@XjVO9l#5zbJC^u_?ud8%c|fNO{-8WJS?F z@H)WKiG;gnjPOP^FtkgDDdkZDb`O5LAX*4&r~M*-$5prjD_5;A+F1v}3M#l2z(UJ> zH+beIC-vi>$uI4Qpu`Y2Jf?UXErnC6X!l}4$7W5Xbya>PCH-HL< zMbhMIhwI!)aY;}ipThMS!POVkETb&+lD#|61L29JnG#BM7pdQ0p|?rRg+n=Vpl~=k zY)Uu6E=DoJKC&;(ca*2%&9Qi&a{u(RC#HncK@>#rG(-i)ax%*~M*(VKQf6XOI<+ic zbCdH>MG!T<1C(4kjEVHeo`8yWbCbG!Hf9Mas+$Bepvz_2HN=V1IoJreE2omD{J|MQ ziZDol>I&a0cI7C_IgR~9wq#0m)4IF{j=nN0OK6!9W}BWJ50@?W!7Jw-q$XMil%&}a z0G>hVeFm5ab`_!zBFeAle-sigF{gP^@KA$lo{G9a2QtrtcrQ5e&IX^MB2#ahw<0uj z^?^PC3aC3gLA#t`Ri<+002Z&Y4p$a4tQ!OUrerYvXCy zB(?W7JEKbRe%gube!gNI7Inc@3ssp0n3IzRB4NRYQB&zv^4!KQyE3|y#@n~) z?os_KsQKF}3=1ciD#t9OOW0q-vH6ujX+4nDC@0QX+@wgxzwDHr{4{NFsiOam45}>8 zfmkEEA+x+i-ut6!tBek*Mta7J@D37q++H!>(9-r6EU1WJ{^)(QQZqxH;4JB3ObFK^ z8w<5>tcqAdWLHE}W>7RDkIl5|`XYrNp*n;v34-(?+{y_7i_0DM%^it5FPXUgo?;`rl{Hml$KjTV8P;pvFd0T|tJ{j|kG^?&#qr_K7?)bh? zpSQ9wkcOaRm;_u~J_CmAc5RaJ9;?nq(52AHHjP7O9!+iZ1r6NA+I!TR!qSU%C*+bp z4BG|HhB292=fyF}y8!Vu8=WnZ@8oeXJEA59c6xz2tm7u*&RG9ELz_&qoe*vuc@SMx z9-0R4At`s61qU&kD91eBrgu+~06k6iY5Hqv@LN=AiFcD&MTl4Hp)-6(f~Ju-fk!G* zhe?^&xFrEvW2gJx+~%5|MZ7dngGy!=&6}T%U!}krI9wW|uv6qhUsd$6p&7+v4~HnZ z1?jCa>c1`dgq#q&V7_F&>qL1C>UQ?~-3}&2mH5=+Mm^Mk;5b_ouP6QE z8^&{RV-Q#I-5I%UP zn+NxqX`qX>E9RJpt-P40;!rwqvCbi878cl33^IzDuhAd3A{NvtzV776N%Q(47uGpS z2s^=^oREeZc)mD*G@K9#(Z=wHdK`0r+mzsePO(d~(z^bLvct}Jf4EV!On*yLRR!^; z02e3_4)QBh33evz&IriS>S{TxmaHC!oAFU`g!NS!Vzl-*s6*m4-tqpsGm&1lX@DX7LzR?kSe4wOY5Fu+^+Y zV-*VQ7Y8YCk`@Olr4$r_D}|35CE$WE`efN_)6b~O^;z%hpMZCb)3da9J_9U6`gCVG z3_57^+nF7Vai);n;HvUfD32O9e{^gXyq*M9?-XsMX-=1@v}!PeL1)h?P%+DMpk~up z*oyUVbs4nR)0|#6CGS=xUC-xDCeW3Bq7pPjCb=+59kMc*E90w416#f%b?S<#tS)F& zqY{&+2`r=5%#KBxy-Q1hhZMaB64%OMg2f@bGiHWysqnfO0SC15WuqDeiN3|GzF_L& zRAtz#NhkhuCD@T^m5veG@TCh|Nq6`FRgd?*=&Q4V$SzB!xhj%I2oQ*N4JA$qFnL?6 z9(u@`TZlmnrvXKn-yC@If+Jh zOA;z;aJrUAR;MRrSNcLqcAtB0c7Y9LcZ=OA1rNKRL8TgdofKYfSA4qwquI`^o>X_9 z?*sSU^ewuII5^E-QN_I>>(b$7!wMBmW+)-dJ_X7_n&g%%(Zt$B6wD|~4xDrHWyI%2 z(77duOeC@P#;xL;-=HS*&uR(8v`_T*wO1O%-w0QN@CFW0xg7*bhBG+Canp_4HHsk1 zh#YE}lGAaQXPgl^l2&Pjob$p9!;-}m1MEyG>7G6mvuTxFTGp9?f$5Og4zP6*v`?4K zA<0}J7h3t)Z=(U^=!mpbu&0_$(y$}a5mIMGbx^Q4ek@?TZ@?1@rDA6nup*6c)U;2@ z)@jXd?NY8*YZE=+oyDTAT9kXTBH`V!Dc&@;ekWVAxr>u|AYMbk2a=YOJYRRkT1s%VCl;mDZBaPUX5m5C}Y4)BL?vr%cw}~#75VJ6KFw+)Kw9I$Unn{`nRjjRuDk?$5wB*o>Nns(2aZHTa{!Gdd z9U4rz8sh7FwV2+U13n#i#+K`G5GYR)~hpGM;?AiVqplfv7$-cIa9 zm?NWQo#7Egi6k&4tBRU%mtN`>7a?*&!o5XST&QMdJnyoF9sWn%_h%RCP;-4?W=66m zjxfx$vv~u;kG==7?kiFs?Z;NojEx44yhT}rpUi@iz0QUSM-xeRw8SQG3-Izx!p#cf z>sgd7SfWoQN?ga;+er5c^CeR~1!(Ky0$_oKeWscI6Ac4Z=Cao{mic&ewBzLpb)+yY z$?jxx+s_$nbj(nS#_hK<8C`nsSTBF8X^7`Pi zo~#yx4wDtPGOb4CwP4%Mc>?r#&&HU92+j4=SQ%YS7NNlgEUvnuA1Bz3&$7>d$89NT z$0JqV80`jgyUrad(d|eph%uVQp@GF!lvh{wKjG0;av$+(Gk0))&7w^fu}dzNEYSdj zNHFD5(&Kf$SAdNK$(D|)P|u%;tF7UXr6sS*q&3Nq*Gd%ZtlV`B9<1? zDc&y*R4}GSZqZhNiV301tWzBGi{gI~=X^;`_yP^Vdi!G}(4?O40b{gYo9-?Ynqt?RHwT2ur(k zbB1^EO0VH@`=)b1xsSz*hSxPV*e++K7d7pP6vyQ`jOFB_RT37$s29K)Pa>nLa(bLq z3%c~|as@ohp9sPi?U&zW0|UDab8?H+1at4vI))`lEFnyrGNshaEv|K|R!6&+@rG!_ zlzCM56YB9X5dB14#R5NGS@0g!Y-{Gs3^s5d(U_8oNXQt}@3MAAc5JM56G>*}sEWtxuXTdQnO)pzkRYI<7SGi{u3*|bVV z6xZ+ zjxN=~D16HSVIQkBbAzx6-Y_>cT%=hpYlVtfmf`N3jjpJ^yp%aUL~SuxR@@R8=>9;F zlYil@l*7;xpBhhB5F53?=9a3nq_`Gz1#pGtFZHDU-31(dClPVQqT~-HFd#Hzw#sI2 z-#L7*ik=~>El7V$u%XI2MBqk^G{!tY4+3tcMM3&7(-;H#G-8lxa8z-ZfjTHwjuX2b!fB(dOFs#(_)%zJ=?jS`Df7r_*#2A>M&30E9sh+`;H z9Wq-3!xrg3B-05D&CImHL|*RwKO;!NlTr z)v_o3Mxo${m|-#KPMJ;~O=}?NDUx(_Dc^l6SPwD0<6L1rxN5@V{d?i>mNrCu>o%OW z3j9Q}c1@1SDNAihG{56bmg$f;5kP4)mWo@FjPF|y3Q-uM%@;Wwxp#Q?m@KT#or(*z z54J@goqw&a99opvGio_EQjQ*OW^X=X�QzBq6oWA>4oa&9pVvnY^TFY}WG~JFg;hg;|f>K$?=y0XT#_ZnHu}to*#4 zFx11!y3V*Kcna%Prh;FUxx4D9J7l(DkToYM<=wHgKI|x`izTGZ_;)G(-|zJHPsxNV zr2P(Y=2o5?A{1_mbL;H6l0JGzb7N@iPu+>2JD|jRW-!U z#7Ljcg74CBK=E?O!pJ%+h}FoU02CD7|5%Rsd`7;|UbG4nYN4sRa%4(XzHl^Y|8bR$ z9F`;dN~th_IEeR@hVXYB!)xtVb$r(Q9E)};=y|UiMDhu!C9FTHjEfeQWi&ZhXTJF| zP%nCKwcp#m{*9J2O6dB5_ccL2MNwYVJCg&m(E{2cQnt&}etv`vr%7E_3gRM5c!O5{1~}KD-<(qw9ur0lt&wyM%#(9e z5C2#f#o}JJ6gI6uU3u=FzO9F0#AIe=63esMoM}N&x0CU}?Op@nhg|To4=%C5i&5%y zyys)BE_tchx{@O}%QDO!uEvc9SL^6|$)nQm9*iH1_U$4_9~HZ-<^`Fn1I5(v1I$Dv zU2>QmE808)X?(M%pcTRg7^$OGk|{a*AVgm2eJ$`(j6hdL;!#cqc>Qe*eSo}CPl>+8 z1R)k_YRv0$jszR{V~CX}?AkPNvncb(g+cu$Zbn``CL!xC9n_j^s8WMb0%S;T#}JcI z*%tZ7E0vtT2cpPz-j%S(pBY=%lM6v!=jYCfi!;S3ryxr8p@Ew84QOMaiG3AGf|*u} zoSH9dX}V8TjI-2%`l_SEL(Q_Ijvc}LG+iE=mB{Ms1LHYyEx&TRH?~ezyaCbmIPy0S zq?)LEtz%7mnlBH>8+IdsaHsAxk2kB}5jxFQ%fowh2>2gPI?sh_5L_HC?ts@_#TD0NQSDH$&3jzdB0q3uBp$d-VYjb60_B(rr~ zBg>2k&+R^HNEsrJ2sqKwd3y=ty)ijsdc_G^<7#KxI?RpeOkLv5u*kr%EcQ0=iZ4c@ zPSbsFr<5xVvvKLNhj-~IhhkoA7pu2-yS@(ncy`a3!l~Z_10iLCcB^PaQsp(Zzjyo7 zggKKL79xD4JS3u4Jsz`aMl4>x)0Q=%+Z#XpevYQDw5NK}&pcjeFYSEN!T~5 zEs3k5>(yJw>;%aY_@9C^p(*6Vf1d3Cn@;!GIA1_Bt}Ef{CJaW`t6E^a&Y7LoPPU9$ z3f%XzCdk%NK#GU-@{nZuxR4L!Cvl~u1(sV_i8QmCNGb=0O>ZZ1{kc~i%IG2}UV1)i za;*f%=`&zW7pm+cGo;>AJ*j2Yd%j0=Oh>M@+!=e!gw>GaiEcsefkF@r<}97acPVdQ z;8h^5MGZ4i&FTJlS`-qteyZ8~es{ZPAKpo@Eh{s1a-}!fcML>W0fDSCV?G6F2=K9$ z@73J*UDPU*54TEql;hI_rR{icM~@k2!#%sgL($t*^mk$_zd!#UJ(6iY)Vbv2x`>y> zB0Vvx`WZ0T!#|Z1E>*|FzkE|YrKnd~gNVo^9*8&q`d!e!Cdk}SGIH8^Ek1G^9I{oc z*?!U@`{ySml)aT600CVe)!r?>KH)hOY*rL8h|;4HNEDuU z9Eq=A9zPzD#n#*P1hqgdk+K>o+^y2C`RA42DbtcrR))|<+2+1Pduq0I-brFUv&kkR zQz1-0eVU2t(2)y6Ljf#0+?jF{yX7bv(et1 zqD3x5S~-AootG71Bs`nrt#5?t$fN!+U)__3eiO8R?Qe6 z)$*8xq!z9(Lvz_B<`zwDNHTiN7KVGZBz-I%toFCPP#bY+ZnB!x(-?_~n4GtRD+lmPBIRK>Wvvl!Gu;t_&?uk*lW_yc zZ2vOQC?}^%hs|-9FYpzxRXQ#cqhQSP@j+1&FqW4BQBEW3YJ*TxWg$=9S@qP96 z-^l>0Q@Nw-SX5)qBCX*_Sgf^+bB~tU+vZKff%|}aEjP+t1L%;j2G_#rp1PFx{A!IlSx%&8d}yVl(>Y_7p#3FRQebP&_D3{u%PQNFELZThJB zW={nUYYFo%n5&Uy@kDC#k6(5g2rusgTrzt8?|v`;s|J?@lOt4AGo~{#hqDf8nFm_Y zZ*wFhR^k!Q@BEg#4g<*x`5uCIdP~nYTwD8k^STHltGJ(<+kwaboPYlhIakfOhiJb{ zJVI~jYkq%ZmYh48czYH>j=MogIMeC!HG+d%TKI|HRrxuolWNZJzHvjZ1V4d~M#G}1 zaI>?BB*5h=_>l~6*dpU6fXDywOuZ(&u?Y)@703jfam&Q~$N_;C}_}e;)Pg z4~d&B&cCcYN8Is4-d0HXhv+S?baY`gvk@7aPhG~fjg9{G{M95RCa-avA7Z?`>GDOF z-bYophS>F6?iU*qLJjv5o#}76Ukon3Rt)```{|37%CF|XK=%u6{`ZlLb=B>QgB;3z zjcON6GTcS@?3vu!-`-vFmX^t-{tOUFhTuZ5A8jBF&*poV-d_+QwSj3{Q#JhMXf&K+sz??>O%;$k1tX0%@0^_%N?U6a zbAR!E)L^&?(}6D>MkIt&-b@yZ>P6ADlvQ*!om;;(qS|ZW8{Uf+%;%q=noDh@Z==ur zV48YpvS{jhn_bjtt zv=HKbof#{84{L|kEM`6Zo3Vr%)*lz;8_cs_75DK~5z4YRO8Xhjdnt!-_BTY71(FAM z9bfpALZold6jU==4wx;BMRtq)&ig~LLL>M_C;iNw`r&~ZSEcW%3JP%ZSKcoe{KA78 z*IzLB1%ofV@$d0Kh3Dq)mSEUxFz>vpM~eGHl0}S?{Wjy!^Gj7^tiIfqRuWDA{(Zav zK(or048)G|aOWsf6Y;kV4?y(+a9*{3E8@sMfc=l-OB>+Py#9!Ly0&dm`q`hI zXC(gpp~faH{TcE7>Q>X)Ibr4RPLH$7l6P*je+IlA1(0~eeg-@m?K-;g;atZ5iP~kTC~0(dPP>izCQ9Kb z)3=^d4WU{w;Pk9Ec9kp1!;*76dOLkFVW+@Cuegj2eY}5WZS+qMOojiwZo~fiMFU&% zA9@*kDuB@PTfhtK00(fkXZ?YxTDFuON4FO5|70d6qp{3iIy7oikW$E|ejLK|=P$cd=Iokm5PSHZz^DJ$Hn0p&hIgqKwgo?y~~+z><;IE0hriFbj| ze+Im6IoW?FtfmvjG7#5RJl1zdNr+)^2!HZ~>}0;<+LY{?XhTVmmlH&um6e34S=iI; zBq6J{@)6}bdlACj+FcH2y_(`qbW0hVwsFAb%9b^>jLI(aB5Qv^I#a)x!dwco!?ax2 zmE(fhXsqnMRz$nT>+!DKVDzSjb!JL>NpCavE)!DRea7FZ6`DZZtpN`Qb}CmUNw9j9 zY#m5cO@vKtK4YABn#yfU-3#Q?Wx~pnhN6-|2SH6L3G6*V9+X?ANQ;{8u1$&JiJ&R0 zCDWJ6)$Ly^Gf#i5EO`*rAW(P8@U`xjZb4ue53*DeM>$;qs9n%EcheWQr@Zbof~}Id?2mX&mfwf-$bbA+f^O^PFza<=wGDH|Hi^E-|3XI{js)=8JH)SzinpchyZ{) zD9WgqKH#_H9QxT02al|!x8_bS@4U|X!}HTWWeL!)Jm5)uyG`Nif5{~~mCeEb0`hL&F_Kb|`$CBm-)Dbu#t*bVIh?FgIUadydRbG`*Mrv54 zOtVZMSWnfI^EB12(fj&`O|a%2K55NeKl9{9p!k7Q<%!9WNH{Bn>r~`aq)xkUt}Ww^ zm_^Y*+haP>5*2Xqa99A|s*bfWS|RPl16`*25U1a7Obdw_1yq;<%OG766`k41_vznN zQA{puh}rD#OKNF2LFHM2)_Ri_kpbYr?xZ^=cY8wSW@1{QOV?UW8ZV?~S)}z#GA+#} zQ;|=aAUD<`_l; ztAbhg+2f^K2)Bl30xT3p!|cR-cuQY%TpI$CsNOrU1U1jkVD0C{UUbQhC*P^{uF+y4 zFo(G21V$w4Wam+Bnzox3k1ni5A1otxuO~%__ge<*(u!@5C%mU#B`7Kh$aS$O7RtRI zAwy5q(o`ZmKzE9>F7C)PJTMYZa$tLEq13-*no?{C<)f7c?QPCE#7}TyD8e74#$0@7 zycQ0{9CHVdl`We_1M|4sL^%$oB6>xxzs+mvi#FA^?ir&^x8mMF6o*LKJ>)O*jVImHqT4XhT&Nl8Qp?5WmX1jmmc_+5sQM+O~@(8^l#Q!H`FDIr7)3eQC|1V ziSh`i)JC)(LvEDEg@;Nn-FF~66d>epYi!#;<&~)+bd%3q_Pi%k9zy`ttaj9{N$q*+ zSM0e^_DnjpHarVA_{?&^>q((h6K!?Oq(u9ag6b(w{JoQ*+#?_NSn{eqccjm=I-6$g znAaEZ!>gkyuWp7*@>b9|+CWoMQuwH80{D&%(>E#TJ+iX25AWgAw4G+p0Y>Y>TiQB= z!DhLse%vm};0mE>_8i~Zo%~)+<*YD!G&rs`$%sz))9q4+6U_Wk)9m96KhX}|XF1m3 z=k__bgwlH2yYm`D3K3qbpq8i~j7FM7MxAjd66(pp6B?bAri%mxm+?h~{wP-H;7rMS zDZ6trgid+f+e~~^EmdvSHizT45`KpBCTHRM?Zu9zd5|dztfnfYdIcNFUMx^qNzK$i zzJl73O!K;7YW(qBRvpR$jGC*`Y{tmtmwB&3=xh~Uv)NBXHwI@>!OP2r^HcAYh3bit zV0{dtN32)VjA_Ysk;gaR0)BgqWmCk$F>H!}->kMLO4f=?uDP3N#`(XOYM$HG6ESn3 zH>~vVs_d`*-Ac7JP)0)se?o;R-vLx6RW%$ql6+Grz^=f?rG53OUtPqwN#UatNgQEf zLeS>D3&n4Ob{HRM%5*lWlmc!`eP@RRp7O!zsHt)-RvNho4fQbRl2|VK$>^OD7nBrZ z&sZa3$E6Oui$@$lSIj$L8v`6#169TX?qFM=Q!FvOq|IRz9cMDv0_zBGO$dF0Um4|G z^Li*q-{xDD&7q~-JoYyaye^W5TI|G-?2Roh!r>NM>5ia|PMh9#1$=$f2f!n2ZwztZ zCLUJ_-#~W;Ls%~ccpiSzGEc?y8Gv?z!%WjdCFx}5QX*i}0nn;f(L|BMCKoAaqmS{; z_g^N(8EfFtj)itm1|P@*;$~!f|;Vx?>sd=+BFcv{C?+wymm5Pq!1)~|D|$8KHE*VFpk9D>yM3q=`VWw!Oa)Z z$@mVlEep4+^hmWU5i)9_w1`!g+gs)j%aT4^{L+~ccUCZTBjm>QKE+1n3`F2%>hGXx z(LhUjXCaHf;b6L&IMqt3N74E!VRmg!?WA(fIT9d+4aP-I6O3XEp0wB^;9*dSy;>dQBls& z{@?Pmkpt|{8)d25KxBcj%#mD-tQvy|m%m@M;$}5x&ig5g8|6uNCkVYH&}%NtD*qpO z?-`cn*6n-ytn{LZvBX%C6>IF#h{l?gM6qiuh=^!ni-K6N*Q^wcV$_9-1&t^1go4r}f8Jp0-2-XGpC=eo|h4qxEr2IgekFz0{HF~)Dq%bHX|qEY)_ zrKWPJ5B^BfnhYWbvgEpGa~r=|F6uMUY=P&c+>VZ&2Fr>%I!fIs6`Wm;N)|s*FKqC; zs4Uu$U~W!WP880IhbkQS|547XCnM9|`IoWHi_S>uB~ys!2UDS1mr>1>;*pa%kNBsUL?oM2>`ij0ZCRmDNV4%MsYdLM zf!SMW!@RJL^0pFeYZY>8Q{W#_1@)lKkK#5G&|7VSHx0$8)(0%VGW&UEdTK_Qe6M^# zG;v1uEXfxg6=bFmqPaNW=a6F^*AD^C>7AQfR*EepM&yygM;wZY^D~x?1Nr7HEge7f zrS|5yhF1N3UtfLlq`}N1!%_axHVU8-*4+J&mPKWXP1vzjXZaNjxr80u`L-up%*TV} z^zY1O|GxbnDq{Bix{Wxi#&YNbU#qv{m2Wb=n+5}Yj~3RnOYGGyu~rO7Xo;NL!!+V? zEpdWEX61{dJ^Z3FTdFfMv0DFlxZ)9NYhxazT3%|FR$>!*FEib*sdguA()thg#`doG~(-{)65eCZ; z=>ZY`y};{{GX-dV6R3o$m9BkckA!Sb{#%po@w2s-wJ8HZTnB3c`tc4s6~Vc{yc9F+ z)s@)_CYfOH#i?ycG&J@r*DbMK9QBs??oDTB(-D{4ELV!&A5@-LjF(pp*6dF))083{ z@1mOd?;7S(+lk=%=K4*tZOw;+ymxvjQ~DPJcA{EZn%$wJZ%?HsRm%wX->K(zRd?5` zdI&lL5T%i;@Hi*nkQ^+Ydt`Cw&1&DK%4tKt`ZSZ{A^t<1`$hv{(n-(;@1&qQBKvxi zUVe$9QYFR&--0PV1oU^So?aETf;$uOd|3V2Jj)$Il}jAKbDf`J86O3RYfQ80m6Xd# zM8sK*ypvunfcOTnCf%$Fa7?t$X}NpMFjN1LyK`Zm|ChB$QvZt7SfP2cRrL=F=GjZ7 zOAO)@^ruVlCx#X3DpNyuJ36T4sNymob3IK*VO&bUrge;ly>W1j*kZs>mggqNrh7Sy z%*aP5!WquB4f1Gh64iMZ&DZEpFFcvZ-Gdx)-S1lNijo8MR8%k`oEL?1?WC4*nM#1x z8Cx_OKdTDpQfDSocF9Imy$y{tG&7Q`$s>)zFs z&RufF?qIsShQzG{H_7iqm__}OW&7iesmnd9T@;bpqk`rcF}a+oz$^ilS)N|>OifZN zX5KVz)4OtD`8{5ujT#-WD`;0b9G7jc)IPc&lZ~TQt@!#dm!U^&%CwBo@hLGsadAlzV)#kV zA0xB3tL;Y3oO0+Qs=vM@p2DUqO6<3?p`ASqSrvr~Umew>(_Ku~m-oiEjNidL0_Spq ztv;Pxb_k6Lb+vy$HQp1y^zj^^@HB*^nIm?Ncx^+P=fO?T<4nt9u2sYCCxeX6O$66I zEc;BEN1WuL#RRErG)TDXd0S#=rcAe6KK-Oq{EQ^mhLmKyRSIDpXOVV2{8m_sbf`>) zJg`1G5kqxmW_TchI8ZAUNO2*0d^3UT2VoCYb_5>f={O(r$cW@cnrcN~f1bey0t@CK zb9)3}m;EXXm;rZwsxIZJ*O=?w3MMD}%d+fbsX!f#fSRKzO*8D_vz}`N#iw3x_W*Z}nP> zPZ*l-%v_fuPEW^XIldlpoDt8|35D#_>SU~FQvw7S;h z7uYsUp4DQvw>(!w(IQ@EQhUukiRVP7!CDKGWsz+&WeXaVaKdugbQyr%0eNXki}{j` zcKSS&6Kv-y(L$zIkYc@Twl}Bg{HcK}epS+(g=*)re)^|tJoI-B(o_b`6H98t_qbbN%XKCPK{(SyyKGx(0A6MJ%?FM`yPn!-G z6?ETjrdn|@=}3tlv6a;4qvp;rTZfH~<^nsd3UBkTY5J$PICU?Zbf|fP9+Sy0J2f%> z2Wq(&a$-=Si#Do3(o-&yIb2+%W0?tz{ufXgf{c}TUbCbDzo^|%YTj~-c=A2V($laN z8gejcWqwbu3ZKbAT~F=3D6>NYlF*Atb^ zbf-s6C&kq=Jp4n5$myJ)EK8iL4s~T!_CY1)<6`tR9}(eI6b&f2BIJHkcj@t1%|f*2 z$TXp7>{{<{T@ky*{Be0I+)FDZW?G2T>;#0V)0UlQ;pgv%ow~1zEN=L6z6wkOd4J3Y z{$z>N!&;%E+M{Pg4fVX*?krC296OjQJ$XI6HdeXc?|pP7nrN3>-eac)27LuC*h;J; z0BX}*Tmv^;E)p{HSV#R5$2cg_Yj*0QTGQqVq;kCp<5#jtmpFG-Qbh9N#H8&A^p-8J zL}~7+Adw911W$d?Wx$i)BKB;yw27428Iei<9Cc59qIy9xEvwsV`e2zRBWkTGqxjLM zb|4V5&5L=?)dgb5wQYr*Ij6<_4w#&G)rL?gt!HKRHfy-}D33cJiC|#sTk}+MtUou^ ztCu2vO_*U(jj}Fj?(II%0%cVUi90!z^Z^_&1t>|3PXL#4`)JNNm1yrQuJLik=Tz~A zhd~r78vR|TnYEEGamV}YULBX?)slMhg`YW_c35O}GaKH& z)FI*J0cp@0+t=7g@`@3Qub?c}kf-#zf*bGG><4C32c%i0&ZqLemE-Se%8FVU!vYd` zV(1cidD_gRc}53mGxdNgQ!kiZUnuoN3OC$o1Ny$1#+=l|J!Uc7=Ph?dYTrL?iA>i! zkz$rCOA#~5%pnbtrG+DH8Ac`y^b)fc;86G7=*78^`hn}&gv5NCR2dnuystKSD4G}n zmC3boYjF21t7%V5lf2R-J;1!k{OI+u7Ch(tWK8|9>uubPM~eRZh3D*u)Y|Q+Z-o4T zm~cne3rP(ICE|OEYq6fyWa<{U{-ck&CP^2@O;P5ZVSEvG12v$Z-r)EA9sumU+sGi(&lX@qa5QT<7Mk} z?40vT?QleX8IVt7u|zlF(~8#jBZGrS@WC~ui#*uoviy`&R%t1jg6n>q#=}x3%n)cP zNj%B5L@%{=qI_M0nnYYx@Q(MX7KUm>pevVQx(Jx8YKXeIPSUy?^);;MD9B2n$w$8c%MljGL}Jl8>Wu~x^OQJ+zFBOvBFidRPio^M%D_(2UW(UmO zT50BwQ@iE+QOc|x%6h}r&t4Or!*qnm{Xqkfyf|WO9_az&A>{Q+TyJZOy^r<97(|J2 zOqjUnLhn1=%hiY%=plM`icle?S;r^L+7$*k> zS@+9DW;A&9M(P~PXDVr8nf}VZ$suP=2O{d0-17^XM(c!I^3+`5(<+dc>A(5 zj-|D4xbV6w#-9fZ@J;2W>6ebj_l6GqhezIgL>Fj;Ho6DPD=!%f)Xt}{FqeoxopG_airsrSV=KfVz$aWq2+aI|l zsjboN8OI-_H~S{f^?hy;9wdS+>pQ@)$=Fi+HrAWhUS;adgMQRU%wN+SmdHd21$f=f zbCpjG$W3yxahvU_{?18p*| z)2;G)Tt|!sGOMj4(yXeoX+3E@3wC;A5Z9&l@rMvKz%fMN&MFvuwnwfXhti zIv8sPn3nJXs60%%sEdXM>p2VARXfA3NhZnWEvUo9MRLF9oXSNcF9=+s@~24p_eKd$ zc>QDn5>7fly|n5YI&^8Wwnj3@GcHo0tyj!Y)*uEtN2KkhUAsyW5!r&2%8eEOHBJH5 zo}aQL81Jiw^dfZwK&@b+Ti^QZ+{|2;%p-m6j0LLk7WmLSbCTMoxyu~fnBc&pX)&F| zD=z03O^nNAO`QvDI^DOSB@Z5p#N_D=5;_30xMf;1ewc2iA&lxEq|8QbrE=kPt3Cm- z+pJ#rLi0O)*u@9}f!J;^KXL=|{j-m_y7`kf4*pben`mZ+mb|QZ2YG9w>-S=>36%03*|6C9}z;}Uk$ATJBIOs0qg*gSE3(B6yZoz7@gK#D>%+VhlWHKF4v zX>^$w)-}NBl1eBvf4Y2IJD{X`Fnq-?zXOVdXAGb zP%AGtuj(GV{E~5cMR(IRp|rH2^asvXgrujH(gvlgj;4%Wx}A-=FU6Cq%FwBF^3c@A zqeh%WD2P4M$uBci=C2ko7u}+R)kA-&WpEW(bcw)(($OiN#9?<=xBIBlp2?(0&OiXS zUzM%9Q=P!hT+H3$$YcVv@T5IDV)yT9!)_&7Zo0pU3rWh29HD$Gh)h8hcN&Q(lukvA zv4aIgb?L4Bf8b}_&el>fjr%t^ze;xF(+Q#w0@mN5s47v_7s9N&tY|)6f>bLj4WhSY zUlwqUy=o)d;+YjCl87mW6XqIPjlVCuc;@ETadFdkq{;b_lrpJJZ9$2TQTjX-hDZ09 zrs86<#9|(B@gYa|s*Q%jcgetqnTccJMPZsNp&i(}Eut>#93bU@$afVmfJ2@;t7b3Q zB*@zK$5H3YoTJB{Mc;P%N5qEAC6k%E)~(A4`7Rm(5=0NFUR5jYen6*<599G{YOyqV z^7n6!tmYs#%sSabU4ZzbYM*B-YNPzzit9-qXOfZ9vHMRJ)29dQORx7iaKQTA6!-ok zxv;!Z21BlZXqHHk<7FZnG6K4a8Eg{NsdgbYk@B@P1muSZ0$_3-q_4FPeOub%Tt2Ww zV-`{IN(mJLf#`yTf;`?W5y)LB$m^#c-cxz0bmDiE@+bCjZ*gsyxYUT-iL#HQ-EFE` zTnudZU{|1X;zaKj;jKo`iCAGtPQ?g36~(Z&E~ey|DMSV^*j_XHC~}4IC^koB$k*JG*-(okvk_7~;CRfw_4yP+7<-cXqK))1t0v?r|!Z`RCM!z~ij7{VH`z zitWQyqG`mc)@dV6v90$(?`3_hrLeMPBTNi?4-x7#J6&aasa?4E4yh~zBDFkW!rnr6 zt;-;2!lou;J=CXK4?FhD^i+n!YiH$!-3pb(v(;b`{w~i;1_`^82)iJLj|r+xwtepY zRFiYb)Mb?s(hXlJygh12BG;MD+flY4Q(wy19P8iaOX~~aHxaUqAjXkj zJlr%W?fTfj178wy@R9OCLb&iaId)=WRm1Q~w(A4evM*1DX`ljhf3|t2?yW{TO6-Oe zssaQk6H9W_8*^4z{pd;xRoz@v?o3;PRPSETUa^eRw_zp_cb;?D(C|3=NhRp3Xk60 z0aYvtolmgZ<~qbHTa(ULPu9G1=ngKm;I^Klsib4Ms74v634 zA;|dm{=<5uWJuA?da7$yjzo(-am$w55_=*&G)3HHVczma#fF6 zXQdu!JL4pV-b4A){!qSI;I1;$Y;`T! zNPgN(GyuyRId`D1y>h+j^-zXo)Zy2W9z7xN$EMK+@k|2ie!e4Hw36)R7X9l~o{C2x z&WX`>%T4;`lkp7R94#nMf0>4YS2;!x=CF6jW>ObHR_gDET2|`f`FI7h0!j`$44yfs zFMZ_W`&FAD_=s$QqTb&$RUw{zc9RXcxb8TdLzoED6|gB8+k$W4;CMwU9$NAi@=m>3 z8@3kOS(8PwEf(l0Ib#N%B#2AE7cqE3gTYik)Azf{-^Gy|S40*FIVibC$-Hl7qh}t* zj_Qh+_v4$$cvEzSz{la_sBV_|(jkS5zfm;`Fl(-*+!4`%=dMHIHVW>Q8KBXKAB}e zkV!W~TXhyVJvbU;vA(|{nrTv%SmpbzFv-7rBw-qKUPU^cDD=n2+BhB250! zTz$<9-}sF&V4udBP)6KdC{smHbj3$_0agUM*o_<6QBni0?BQt)Y{E*SlCH3|k-d-q zzymp=@0Vl^RRfN`snqHQvKJWD04hb1gKf{S-rJ!hj#?~_xls~&c06JlGZ<}&*y8v7 zXk0DrVssSwS{4_oORAfbnYI4vCyV|=;d1oi@NWBbaKJsV)3`luK?Zj*aFm@(<$)dc z9YdERR@!_;0 zf`FTxyn)NG*INM&#EC|O*2smye&GOkai?Y*-KZpYZEIuYnCs}ttmWacXzj#6_Q@=^ zoATns#V^}iA!oUFNp$P2P;S#6o9=Zbl`MemNu1wJJ7^AQ@$$WJLR`$$tZ>^Cd_ly7 ziUYWKt*h$PvG+-jkS-5gW$ccbIZTp3>bqn}tauulR|}f%zb#4d3@nsYa&Snu+{u@r zv_1V~XCM;gQZPuHN&tBNu+vc~rD2h>pz>NNz+18*wS(e1lGD+zEx1pS>>m|+ zGcQNVv8#c(b4APy(M3mqU8JPjPCZx7$|^+^3_##WtY>kd9@E3{78j68&aOI64Om+I zbbPvCt{57fzUh8WJGx+C$HaCqaZ_7*2%2t;VV9sImjBah1{JUbx)dHTEInZoi zC_MRUwPG}6y$Yd;2lyhAFWv>lr!;+8{s|#n^crp+rM;60Nux}j!hpsvHHn*U$jI*}?q6T%vW4wkL2o=)J@Wq%>Rf3S5WR!q<@`IzGUQ)P{`Ut$vNY1R<2~O> z^#r_V0BTzIch>Asos22mfP`KU_Hv&OA+EQbVLym(MF+E7Er*_&Jd!p98QW*0aT3^0 zi_GVw2F&+M--1=cmKG7N-tThoc!Qjv7h_E+DlCd1lTo821v#T>Z#2pJYa`3AtA9Ed zbAuRX3=KEB6xfNGFBd5gQyLSuWfv!iGu?r@f6PQraG9JaY=1YijjsmC$X#8A*702I*)O+uXA~ zE~rX5($o+^uQRs|s7bL&M+#!TU0rHNL$|Iy&$SMID|R=h`pCHN+o4SOez57b!gBxc zqAqqD8)eFv0xr%Z_1MvK!3XZIlRn#4VTLP(zfW6txO{M>y5^(Em1e@K-p;^RwbbVW zv))bG=HEWDf`>;og{1$EigY$HskzhvgJKm?#k>(|xqB)sET`r*{;E!YyJ&8o*tH$q z8s9*O-tq$1XldzA_q%CV{Bg11zxmhx|3^AY2q?VNYc zh6n?DmeeV%&YNJ&a!4JYpX z)`~VDfQv0EY%3t#qv27P15L|NVtq-0QWKZ5xsq|(C^a5tm9m@CoL!y9X;F2gWt2wV zhWKCgCte&{2MLK6Cb$y9q6+#e+jDC;zi?l^6DJZrAt0es(aG4vI{=o5cxS<33uAuv zxx|tIVNvy4el9W_x@yah?W*|f8a%ZHcEVM18!I}r0}>j-JQQ!%<{y7AYtk=ltjI}J zq5*}Hr@g?@TxxUOH)9GS+_?%q1D5dnoB+!`S?ocCM$N+X^ip8tLIE0%v@23M(Nyle^MN28)hq4ZKZ=T-VDs<}MPy z_(IO5R%)o{?9DG5 zb)`4=fl$+tbAl~unsckz!_dpc(0r$??2iuK8_g8;$T>e{sv;lNP@7dMfn<4mFM3uf zpSU22S<*J)AC6)8W|g!AM8|dRb`k4LZrS9De&KV8I}LZmR8)L=s88xPVk6O2YBIYx z7Sk$PkB(-h*~_@QOW5kH(!AYOCY=szTZ!EKZbafkP|N zdHXbhf^>bYt@SpgBEZ)#0u_61!Y1;Xnwz)yBW4M*g5d;Zb}M@3epmM02sr;emyh`* zTp|Y3VzuJJcrc!;fAbb?Fn>ayc?GYkuLj{JROnuyHId(jo^A@d?)eTm;fc(R3EB<# zL}^OP$(&=NLlFQ@=1hod5HQp<(Eu^*t(UQF?Qh143+3f2FANb2pNtXmlMnW+3LJ>7 z5ubjtJoKyeMO24~AZsJz&3jaBt`{DHr6T*RdlgR0M3ah?f+k$pgX$71$JFjxFF@6v zR8!=LvtD2Yn=ScqSKq@9(#}$}s#A854~%z1;@WR7hQz5(w5vXQ7G1Ww`i3B2%k3O5 z7zg;6kQUys^95NmlJU?x*LADV0E^aR*|cyFLja0$pRL?@rlt<9Sm92_FRJJmF`kXU zKvTE{bx9b^2tAmyNxhzsczSH6Pr9%mvg+BA<5Zw7nX?0@2VS`i`pJTzw^(EX*f}s) zK13&8k>}uih5+8lMXIkxW95{hdDrAfGUto*;o-vvXQlaN5GlMHf>f_Z&8GuZA}ibS zqbnhIWcr&%mKH{&g+>VT1DGc*0)!YfRjbO|=Thsp)5XG-r@T>A{w7g9vs)GddSCoN2t)(?Pl+88Ld1M};7 z7uCE{DH8Hc$QfMttMNq%OFn^n@gU2z2GyH`q#f8z*c8o-#;u~E;GPl9_R1f3XD+(C zy|IOlZZ+M(nPaJfK_Hr|m7m51z3){0y%ZT%NDD-S^)vVxu5F;zna8={XQ_rhSZRR5 zyO6UG*Q%jwU+Xw8_k}A0$DML@f|SyV)hNIxM#?MWkHC`%^V#pW zrRbih8nQ7YQZr{Xv~X)Zxdx@f314id__~n7v@g%kU7Ey|fgngvGlS_C>o*O+n>2Hq zrxhIr1K?VQD{8;{ub;y7?j^+1+3H$!`lQ|gyu3%pCPkSzr}z(xcngQze&>(SQtekO z13XLl%U_$!_^88Mo8nH@lWnlo^z$<21-LslLp+R4Wg<@Y=-M~xI80OOefN!kV(6M; z*$7!-1sA=-@J2M}2Zf}E?T}W3S*_F!)4Mu|EllGE-g`p{{R%y1#BIIRRG_He#XIE%6qKXjq z>eFQ_M1Le4e?zdFe(UUuWpmM&N&!A+Fjpdej1k#K62sT^TG5W?Ap4qE*IolHjb6G~ zB=&M}rwp&Zkl0MR`)I!MW3hBoqg;U<03XjBRD?XwpvNMlH%wsoR1-r%I6Y?bqv&}T zeM_TZw39%03`ZSxgwpMTPS28}#wSy3Rye_x-la-+_yAJ)_~aU|U=EqM(pU49B*zD= z^CK50D`pBxhBNb+0e#ltCz4-iQWniaAs-#h>(UNY{nzs&>CZ+SJ1H>)8kSbzo2w`dwV;%$au5JtM6(i50TqNIXx*Q+492g zy4t6wP0d-$ZhQN%gGV1Q#~}gt3Nyt(W}t7A*HwQ6upG<^R-tsj(di$}KsIR&_2;)> zUjqtcP1wP2rG5O+h#W0RTjpSd(W@eLB_tUMv$z%oR8r)R?aFNNrnn`ep-F8aDy%aK zcazL*bt#P0zgW&E!k3a?TqtT?AHgSOIMzGr+%xQqM&f)q*T z8If%=LT#O=R0g%w=(-7xJf+e44&i1>%$;~fY)2dx4dZy)YUzl+q#zvw(h7XuYV$?a z6M5UAK)a&r(UKXd?UWy1N{Qvsa8-j{M`rtNC%R(Im@}F;cSHSBxrnO%wf+Y(0&fgQ z*hXY}dkk&$h8%K2d$??OD$}rVA*+bAh>+7v6U@5UNP8!tZ#b`B&Fl<0RVNuFxQG2U@S<^}bIo5_yO3JA*5jQ%z4r9Hkv{dxQ!Y)sH7mqs-38-5E8VL9XOVSWG*mfG6*yw7d1n3>0Z=if_7{7uv0lKofJ zcDGaepB^3yt6cx4A=#3)w*LLge&&kdtkO`k^IuCp{<()+|9!3Z&u306E>`c@tJ(Y5 z9LlB3<7eJp_L)DMsKog(1mZJY(RR_UG>i0nh3L0v|ZPZe!zF>ORzD zp{^1qobEL$f!0cHe3wYK^k}k)9sYHrE?i|Rw3|gbh_E~KZatb2wA|?5nwQ8gH;}ax zp;j~*Q+=!Sw@Wtv&oykyu-P~s?7D$BF$-*q8Sc7a3%fh{?o$`j(ES!x-86TPcLuu184TcQ+NJ@ z9QvPCI`eJ~|7X1ph(nOQ9eptxjv`=5|Kta~?G399@{J+)n$n?yS~$sofG0C}F`h92 z^T`-Ju@-Oo8@mekpj9@#_qlD-xEWHqb!+h6X^$V;~# zhKAIL`Jh?!zNe~M$&9F^Hz5N=_G|f-d5R5CjB^=(MgzHai_RLMxcrk zwq2-FGc{YePX<~T!?9Mg$}84bFJ?+*oaFVNEZL^VVGoMg{30KG zO%-F}#!jY87XTF|u&G$RyGe_mFvH8`nJo~{klZm9X-#&((oKj1V_MP8A2)=gYdr*O z>|DF4v+z2?C`Db{?~`SlU?d!paL&+~OBb<)vv z$0kCa5^|T-(t-G~GD#h%SNJ!2GZa46Nd5z5hdc*s82P25I)pfUzI!y3sygDA}LdA5TRC z#ie%WzD}XxHFlE7xW1+6+K)ona6w}4J0i%%@4P9a!5HwRMK~Wl@nb+LDgNE8Qm%E< zZ?56%m%nyms9Yt%4tqAJ0o(AEt%_fR5^-XNbj3&sDpzv_es1O-?hD%3)Wx&9TGK*` zeMEBaX6g6rJFdy5=?GAxULZOL!8GxVTX3-BoOXG7EXU*loS-}*zbL5Q3C|?VGlN;%>GEPS)faGiwR5VSY`L#8u9yg4ZMr69Xr0_=EYExA4$x)J<$^yl_MdA`znHega208=h43^S`3w0lC zk%_?(YgvN3#@R>Wwh%5(5K*{9*|JY(K*Sc(R_dS4&eT(qvq^+628`qm_$Gb%$cBxE%={=ps-$E*A>@o`=?>qCxi8 zV;pVN+OVx_+DMwlBv?Wo8;Scg|3Ks0l7!9OL=glu^;?DRy$~cwbaBnh#v?ks?OqAK zP+L)RGgtp7%cD#`Ppj3+jE`VPr4YT{@*ea1* zcr@*Khvvsej?E?H*-yu1Y6ezE5SB3k0d2DxSq>KM8qI_K02zgSAv58;ohL3f)!%GCeE#;#yQJ zv?lPkFFOZVSn~`@17IVz9?;wA>OyGIa?36TK{I3GoGgIoVnI3Uv{CC^6BjEphUh@+ z@r+%u$oa$mPhht1nG@?dadoz=0`cP<#ir)E?+sx#89mZKLBMKI>utAE{xknR>sn?$#{Q&-MY! zfz8~4=?UAs`8pEFi(Y~wk1-X+y^cC$Es*x{ne?QXbhZ7M2f4BD_moy9_5>vlieh#* z9C{ZXwh`vE8tzwgggHaa{P2UdbU}xd!dqX%!#R6o_!|Jmc_sZ)aV61Ke;OerM^&Ve zZ@cnZoxxHxtCaqwdCM_Bb&!cyTYQwzqc0I2Gn?EaJ(Mr7XXTn(mOdMilu8)`%>ARO zSi_;E$~K>>*1q{()0mkFs({;E1afD19xpNNg4C54{0oLR; zh1(DQnYFGqSuF^W=H9zQSWIsDU?;Z%&UDCo^lw-(?_qfA0JlZIe@Fk{s!BJnXO`Cu z(%-alb<{1{qtSMbsW!ddpDFoE+RFVUWN(=NEl$tK$_oeO=_+z zsu*rz50M2;0tq<4aj#`F~ z^q-e~ZGb>LUhzUueVDfT<^A)Eq+g#|nMcEA6Fjpst}Ds%{M!3JbiEoD>rs8llImBX zgPBJ&yy#DoOULqMwpvVF2{E~647!)Czb2%%M`f1$4;?q%epj>|hs5@;80w1wwH@4t z+!NbIF98S?iTwEEZnE>EE(QJh>DIabq0d3#GDRcgOOK)6x#1-FPBGQkcV8aI6m^84 zx=qGiLf=JDYQX_-5|So;@^Cv z_!7M)7nu$|YxIt3A2B|Ki!bS0_Vs@jnt+UR?uE`i(;mnFJGYRpyrzy#xCk^N!B28n zVf1TuJn8vQ_hQE#yyU%1c~3v>t9fp5D@CNl@Fw6AN~Q%H^#m^jX(@-BkP0z9#UUkE zvwG>5@kIqQSIXl{Fx#_TFv6;gm{Zkrr?biF)n&$1u2^9I5V17NUP=z^_c=<-@P~}a zPIMK*5Qa<4r9&L_o~oUTklINd-_g?Nr% z!6$Y-`|zrwLkMe1fKY8Z96L~&kIPS~DVJ44wi9bC4zxMCch1&xS6qISq%%@RiqkHc zoJ)6xdV}7|C|*9tN}1toW>^Y;P4d= zORP_vUVD<-@bZRW5jkdQek;if2UKS%VTu?wwV5GHb`ntYsh zx92QRWzR%beYqY^r81ZBXkOSi3zW8>ewU=7Ty6WUu;Hrq^H-?~dT;^!|%Js5{9&-t_*6S-Puia4r)pGHm z6JyB3Gx}ktQ~e>$u_&=?68mUr#|)kOj0D;{LwGK2#NNwhF+vPXZ)J2vbFuw6pZ7J0 zvF1kUiAPAiCxvE3F7!_bE4Hg^Yi>J`FjfO%G6A{ zlh5Edr(*P=)@;g!6#FXkzG)mNh>8JQQlI=*+V`Y(M#}=gOGrnRCIKxss|wv}DJ@?f zOG?_7elP#Y!eS#nz-B&q|ArZWv>Mu}4Huk6XY4B#@9@|A6Y3nayR`%yxI8-UvF~RJ zS);3-L(gL3jn>rGhV_{4AN1H;xgH=J9h^g1x7Q3AA4C`bMkEYz1@w`0pEcc|`u>nj zhSocr@0{)05u!Gt6%^l|pYL~9^X9n_Uq6^ZY%6mPTq$n%WMikByNK3#XNM6V>I`JZ z^tYI47zv3ccu+eJz3MihnTR1>iy=plF9g7ra2jg)qDkZMAU;Ty)W59u8^b{gK{sLZ z%C3_2sZ%Qe8utZeeSzymhzyjOy>4$}&h zZw3#Sz0mqEVjOAa+;mn|>c{c5pDbJWiZSkQ1vPGe${VSKbi0Rtvfa(p62BEr{yCr7 zx42zA5%~C{a2CdLM)qF^|2psZmBsYv|Be@1LbQzCb6&-vMeB??d?0)QylM3*c<6fS zB1`{Sm6WO6mzzdg4h9CJGt-*NAh(2}n|B;MfpbtuntPkn=C$mAV!v+mYY&C zCDqC0=5!zPJehD6A0QAv@>X#^jHRG;Vp3;9aX$1Y4QO?F(79ZCc)`|ea~Gl2+cw#bO^mjmoB}DbE7lPob#PI=gj%;`O5v>;g8MA z-fQpmu6Mof>g##1Z3iDSKE|Acq!$ycZD)Z6l_=z%Sk;XbRD zvqCZ~sZ>_D8Btl@nmB}cm$$L*{+1dV%F5=c0ZIi2CcsnDw@}Q^X<@dt8WSR<5*9fMcr)OzI z#49IMhn;&I9Ed~+K;{lyUeD)RM=?)Q+Ld`t`9z>Ne1fP(hWUHLT$_s@gE$(t!ZRXl z46TxxifqWWjt*VjszI*A;QXe;0ycpe=7rh$B`#VNO(uc&%=5|e24){hboLQutoU2} z@3dl`4II4sl)QEjB1C`+6DT113`n_TD_cybVe{j692W=dQUkkvpkOM9#}8|Qip8;v zLX->6X&b9~-ETgt+SIQ+o|Qern^sdI&v-ktyU9K$HqWmYm3mSYKm}P}my}$1oL`zK z9Gy-934^sc-+KsYQM`*9pVsyIYoj)hp!5AWVPf&w$Sb^BBYZi@a$y7e$ByhR?9m0pXQYwA9^>;iGxBhc9d+-M#bX;lzn5|)>d-_Y&%g}aR*1uyv8e#PvOr7UFWBg zOfDj38!kLP^yzNDPI=ILYf|hPOL)cHgpe=W`_g7%mXXEM@)No9oJ6(FA#{mDw1976 zold3E5G*f5vg!riHYGrrd68gUqG?wKQ3svEPUt=al#WY>w`A%BPir`dOvpqj@SLGi zgokRL2@-G>Ia5GACpw-mtKUZAbyj<(^?X0wl+*uJSI~U<93tf;Ye+0UYOZ$W2`(yc z6wp7J`)(*g`EJdvOq&AcV7{AosATa6!sZ-)@#`H1hBD8xV^AcU7Qe3PBB3MUj+-x$ zMzPU7z{p_5M}2(Cb=}7-wN6DM#4d7Xrp#&@aAzWgXeTEprmsSb#iXLem>u6N3vsX6dk89vCUAoa`QWY ztkgV5O%}}kLY?D@8(U&NYwe14wBOMrE8m=9q8!9VB7Bz|Ik(uk~Pfy9TJ^uK6!oZEFppGble(9ui&!JY2D%$$|h!K#Z2@uO`B+u4J zMG);v??kcPtN1u;ae!F!ZH%|=)895-VwOuTnJ5@| zABq`Xhuc0sHP8`0Abeovln_x^o|{!EsH@8JGSR)_EX z-4y?aAN-O2U)9I;8A`>T@Rihm*x@suyI%WP=J=kj*rmTq>hL4)7ve@y?K5T5ZUu2i zyyctqa|d9W?lFgQVYVe{Q06_FsIOruJY~&L7qg+PMVPouyU)MdUiQP-FCCr<-)3)4 zoMdO=FiFNuzWaV$_&omycRcSMG8#|@ES6TsYatA%z(lNE*aMa;NA~?OH`S9X$4J4Vx1)esAW(OxfQoq zeZOy??@Nri(`gGBITAs|dT5f~c;Ima6CA)bV8p`4hX)$@;!;etsI&jycr*0*RlPMz zPg?C=TPQFvL#LmJ&5y+-${T8}HPOc@?(n|(kMtT?*8|M2U{imAuzBR=+u`4Q?k*l1 z9EOI5#j~-C5lv?SYh11mY>z1xIy^oyCektFR2njkiyzFhHL=aP0Rkx-ns(m!_VP(4 z>DvC1PUBwVt7H+6J#2oI4Ta1V>)4eqOX|@+!gM@ztu~${^*MD-**XgoFC^PGb-Yr> z@^Xb##>TJ^>cPd}6L!IB!;SOY z2#PpJmCrthvsB`oY8EosR7nqVqv_gQY%aEk+@tIZX1F-CBN!v{jC~tc*S|!w&hrc< z5w!%rFFxh&2P-twiL#|`YIYQ>(nBEzF&mAlS-cl7Pcw^Lw9}xe-yOG{+O>kO3r5k1 zA7;x5!o_5va2up^TU1C)Cqu*88)skD?}ZqX6zm77$3>ME-5U6t8XE#2To3%HFHd}X z`9MUOrt!2>3bTkd8fcN$=$%IeT1j4O*&^b#zMP*@@`T(KoO<>lcbwgvd;qSCu)bQO zwc+S8$iEZX-VC)u%P43sc~MNs#uwkMwy9)08!FEluo}L_Me8#84}QEM{va$YK8N+f zn5165zD9k)y3D!5m&D4wp&|KbNzhblqp$jfyk6B(NUFl6vp4FS#{G({3rRjvjcMyO ztiNS$@?u}Mqq}L+M^fs~CHR{S{MUp|BNchF@wyGVdPFKFGrZ@s$0p6)uSu~>{CYHJ z_JN>7Mor09({(4eTRn#0DS=;W*mFjBRx_8|s%F~Z08Dx^X6tP|R|b9J^N$t}b_)31 z-!w!Xn~Cg{EM-*?JAump22_8%eV_ zN4%QD@t_H|X;5$aD!W8u*8a}7N0D4{E0a`^G3&9eL&Mwuf5myyf!}3hbUpCR_D|&d z^8C!^kDYC;_U3)1$+-CE&kA7!PHDjjjJ=2pA+sCFajemIejrj;T3VDg4U1y)AYUvw zv9HeEpgHu$`X?HhZPud)F`s9L54mLjL?g=Fqx-fI6W(m~>yJb0;L1iItmSFPe@keZ z3SJW8U`UjCKKhlX=#U0RS)1E$%AzA;!rzhD^F_ zL)#-}NlF}P1X&{a3#-!VI+cbX@T_&q`;uTVcb8{ZeWdEz0zBI%$_USKR}=gmun>So zpTxwOL<1}BvtH8}h*e+nWR5Q^X>cPUY#KCLI#0bc1WhaJvpV-$XO|>}ldq?~^L{*V zztiRIPG^5s7k6IiDd!9-G6+Rli0q8>6&MasR-RJ6)s%&2bg0s*1Aj4c!Mu6c>S4AX zu|$QdZ4yICMm~LAi&I6S(+Fw}@XUL-?k{H`4<&Ph@zRMXkYj9KnBmSTQgTDRevD2= zG$m*^9iH=0xGXM45hUMOFGFq&O-O3qh9T>jeR1;H+U-hb8M+G2S23q!%!Q?WwUq3k ziS8*MZS3Abq`}_ZFQv5UWKGM0OYzt;_ zg8I!T@Ob_ji{yyM5m%GX07`k7S;HEwP{{S{cq=dFuBX>JQaEi&87HoNz~fV>0L>)~ zDK@^;!*E)bD6w(41|sOZu1N)JLm^%9vSIILtT4-*>dC>}ETl*5vwWxW9z+goS9k@mj5JXF*`;-x+<`ADok0c~tt=ru`rYmUtaT+@$hjOEC zO4*QiiW0!(VPa1!t8zP-=BDN)*BE=z4m)pb8s9(Bi7$n~kaAL0`RlICS=PPm8374p zbb@u)efP-AqP1s<9q$-LVC8u6r;@D_WQAK<1{op@K%y~v+_Whvep+2FLwW!C^DZ++ zQ!hb|!4!@x;i~!F7zJgrh!V(SAc%@7B8r0&&6I6tJ)y$`@hSk5%CV@-7^4!LcPy*v zAJiWh2M!R2g6D)7;b)6 zrn5R|u~bV`)fHDzDGq(vxln|2*C~DU$?VPXTQj!}ds`^&z}$H2&l*e&U2PZAUw1-3 zav1KFO{z#q8;~%#1=)-ABr{Q|KC)+;4Qmzn0?N~;w56(klTF9GU0-H0A+osl^U2ot z*y(4>MD&nVa~{FPeN|F5ozrjU)3h;QH<6=Ln#JbeG}AW>79pI2uw1Gdt31@cC$+ED^h+ z?-rLQ;r#gcc!N45L2YW#P=+1|v8m7D>^c*Bb!q0n%1Lg)C^{j{C~ZG^SUoytLJ*47 z4{wz`2(&~^GL2HVR76Gz2Yc9f*D`6SPAuf@mN4{Z@#Lcn!oy*a&#L-Ap`4`Ha*H6n z)fy0KBYxsSu`Vp~rG)x51Rc1+k)W-=o6yq9^Uye+zso$F0x2)iou9ego4Ad>Z>D;p zBak^bY{@lc+`@wQy-Z54xH`pz0GgQ4m(Vmy@YjoU5Jp4iw|eE5hss$fEUX7tl7a(x z#sHtppPLt-PK!}w5tT!FScPizXSPGSHp6+gqM#!wI6}XXny!%>o9`N$>dm0IzETZ}0zhjZ) zkIahnM$$3U!U)Q{OfM|{<5Wp^THxV{%J?=ahU<0C1W`l0jtGx*fA4f-FpB@>bGyrJ z9<)a5mnbgcoHvfO{yRd4=;*09|ANK^pKBGtngVHVk7Ug2qC%#X*B=-hvK{vL5}M)K zy~p>!Nc-EkI_~S8oU+`B(810^);BkP#7pmbSEmOaRpR(1aO3ZGkQL;p)Q8e$jSgTM z{dvV61m^(u%~8gmXnq0yeQo%+oQPE}o~dVtTdwSPPwwma|F%`&FApV`{Y`?0@On4Z z^{0>^A#u|66-$9|pQWl>aRbt8(hrV>q(?AuTUr_StOLcBI6#a*9awsbfZJRlLmLe+ zo$A2XN(d(Hu=& z@;EPNvSGOFC0ifnSabSzsnLc0`mciZ)9h?Xso>0e+##`y5|UjM7gYo=tyGE6Y>`%L z$Dvg`f;FUvdQkN8n%aOMxJax3zMB-E_L0V+gyLdFOay5~%&K(^A@rz6zvyJ1@6lW} z)ay2+g2Uv5S>)FmOfg8lSV&^%sIOe4igWapzaQ(?uW6w>oh`on@Uym#66LESlJ__1zKg)OlBSEZRj4Ru0E>6DQj~Z=^DbxnVxQkAcNc^7Y4yj; zxw^GfE(SP{zrRMM-JEAS7Z;axQbUJ{$<3R>ASWLg`B#5QO7J&@`0u-MC?aR-1toW9 zZeEJY*rp9ljYxTQ`V#f~hl775v@zfCS%;4tFul5d*FB8`}x+{h$%@ds?UuTe1oC3)s`Eo5FH9Hm*!@jrIp2)C2Nr<3a%; z0%EX5;|W$zLqP*OUWvdTu)73_oNje|dHGUVmF`?g3fTfXYj%vU_Cf>0NCA?;_>8Qy zRFrAch+*oojwMX>!eIUqFQ|a7=$eaUE?!(EUV_(L=!vgh9VM`J0&%pO{aW(rRf(j= z;TdU@#w7JN*ZD=KXJU-Y*u)={K%`vLLXEwWHIhvDnPYX#^O*(dwZ*82NtK@7Xg(YI zxR3h4cVr{TB5$5}N#&yMkk}DNG&#toYk>EpK4}l{N9cp!uUNSv=?kf4mH}@$vVcuM z_!u|~m-W;vmtbMAVBH0_bLzL6`I@v1gk=}_EXK1PMj=<3c~D~K5t zJQ4wIgof4?ySdtJFl5%3t-X^Mu3>uTGAg4W+g&0!&#P43f^XE7}oEbjT(BW z)OGY4j3YQKefSv?>=!K?;L(cN)aq7zh1HvI;vUS-#@4cz^35lyKb`fhLY zn;zA7!8FfZV-KHvz<$4#TCu(xrnY1zkY zx8=lN#&(Ti;(v6$T+wZem+0%2yJG1KcVnzC+nYNA8g0_PF~kEXZ;}v?YSjVjmbEiE zIZM7@EZ;;XpE+&Cp#q2|ACawEtpKlpcCeZz`CuYJqq)Lw4oWdZB#{=_r9sS1IK-+7 zZ*HXC9Jgr?HDNmcI1W>Xt3umhWfLP;wo9al*JA0P7snC8YS-1N3w=#f;En7_jslU| z{ED`h%SsxUX{kz|Fs63UeNvq&ZR{#SgQAt$>LY$j+|(*^`Ni6Z6T=JPV%3EC){FW8 zerY;!W1fjE#QcP^IZwh6F0cG|n3UI#TQbxdSJ&O1nb+k2YT7uPSTDW|_?24;b@^I- zf?u`c`zJ55q)IM}azcphS@b4`f&HJyCU97e}UzMSvtGJkc-bNgFWsoM1m*XZw_@&pP7N(873{IVRxKjXNRSdnbLSAO?2x6}J#LERhCYSUma+NRg{V5+_|hB{7y?ZlJmpA!1|*3Ilh-}SLl*O*7< z=6Ml((Kbe0yF1VKGi6x3y5x%@`Z4nf4lp5Xo8sf>D9Ih2r;KywceTxgl?6&oGjjqn zy2D#ANPp&xeI0tgsdOYrxm^nlja%Y~!)tUvvNZJjQ=Ogs$$g(SqF_z~FDx1-UcydK zoLsaBWpl1`>)*rnFN!9rr@}opXHr%mreuU>dAUa1R*k^dE{Q7R_ zv%mo=8g`5Z73R{;_dX_d)Dxz2xOi~Mi}j>a$@_BECJ_R`bc7t|6FMkQs5nkIBQkUk zD6SjyiR3;l`64DJz%^j7l>seDb^PiLw<@6yaPJ*c{<0aQT(tfD2DlwzLPz2Z_d98a z*9)8>9#KN*QbBNMp0Mf8PE4qTT+)tju-{3jjb(W}_W%(x2^1$wn!Cl>b&LcLxP=u0 zmceYm*2^hr7MwvED*Xw*1@|-Un0mOY1Op`61WLzi-=l|+qeM1AA`GNIQ}8ZEg#WTq zt$LWG-x1-a{t`{fd6_&7kd+=Iqu%vK&(EsCPJR3O9Yzf=pyhb?Ye{2S%q>|`b!mx5 zvd0;rU{h?bVmOE40=L|Y1ed*+Df_F7EC4uDweFjU$+W?FCM=cMDG^&>WtzKiD>*CA z{Ih_i<7?$;ZAnxpt`j0+a!@xfB_#!XrmT`~9rA=vw1(+31dcq?nm+(YpQ&qV%x%d= zG6_QqK0qT?`rF$F)d-dv*O?7WkPXq~(~G?t@-bkJ4cidUWI7S=iz5xGJ6ebgqxJkk{6#Fcv2G23U;K6k6h!) zQu*n2b#;v{9koTx3*#E(+O{?IAq(|!?fd39F8|z{ zj`7Cqz-ZoxP)iU+4NBruuWR%g8p%hm-sI(VwBJdI2LRXyY0nyC5M5csI2m!zA`tH_ zQc51_*@voW;r#6{r>?)a_XUi&&vO*zsBT?X5~~@WF96onlNy2H@<>3L6BfS=Qxnyw zXnkA9)8If<7FJnVH|+`kFa2<&!U4sQ97qp`r#B&k8Y`0VM}$WUIZs7|bHgbqkaBW2qWgAd?g>{$bgxp`>&3PuGe zIR%rWY5MT^?6hzP$n|>-O?jJ5r%zW7rSi}fl^pS(OVU=&cF}z$w0YS7YXwdHqlFFy zah#O!G^{&Q5ryybG%2`xwBtBt3Iu9p_<eS6cYq9?V}3IvDaH@;WioQ|(X@t!#J} zt?c_4N)2lZCTc;3-YoF3E3;&)%wN6ucYj=%=Zi>T)|4A!chaJ?nMNJSFh?a^~_x0~kF4!$SGvxvRZW-nf zXCx&vAQ%@5Wo+$D>X2ZV(F5ZA5o!>^gY+&Uh=A^IfjIVOttfh zO!U59^R&I;V7@E{6$XOWiEUxY;oMP`*btQui+bu|_8brpdsKZmT6Y>is46)Yn>eWZ zOLDZnd-JdW39MjF#BsLfU5;q}QPta)iHz?9P>h2SKE7hjVQF^JXL&ufzP)f1)wSYM zTv$Ldx~b9UCRCs@b0pv8@DWBEpvMUyduQwUHJR`PmKviIf3X7nOTPZ&zu(=Lag)}g z*3gJtC42;mg2Z030l(iW}H1YU1(U@RUuB z(U4Ed1AiK0ChZ%dkOc8-s$324B<0_0$SZpgds((Seo_f@15t6N_ zqKysRt(FDqe#vxbyyqlTvS{#B?8lJuZB-cx%Wlz>kQm4_^PT=}@kd$h$T}_+Vr3LI z9pM|g=yL~~)wu!dJ5M%KY5z39YC8>{kqsDJ#*W5WS1nIosB4bS?5(J#ET>8?nUs_a z+TZnbGX#raLtC<-+YHy-)h@`Md^!)({xJlr+v}jy5k!EPIqAKfLIXS({DpQ1my0LatcM)7j@P$er{W`X@E@P!rk!YR za&V+XM%yPuxLc!4>b4W5hrR9;nz6W$zJA$fE~c`I+Usjzmd){=FssIfYYaq8v8_Trt53EMP%yM>r;TW;1?c$RnqKaCdLe zhw%>5T2vKaQ|ml;v3_rf=WZCrX--~_&#je9B`hTVe%Wr0ANzK=b~buUljoTRX0wZ7 z2fv;R^}3z8HL*+ZuPTAQMg!yl<0`|Ggz|D_yzb-Z`f}3V?kPO74NV0_n~&EkZn5n& z+pvjmDvo`U@l^G67Ev#cSO~=QsSHns-@iiDskBdRK39UGT8jsf=k)i&!a^{l^wc=lKuJy*W~Cq*{c+%j-+z! zl;^Xung9Ui&q716(*~*C4yi{CAw?0gyCrRb>2@d6?G}I@Q$s<>2*4>v`j%*I)~dVH z%Dq}Y(R_H_@YoUQ?S$S7Q|s@m4VeXEB0+|elj1>xZoUOBkdNj@+NubMko)l5rBdfP z8-xQ9x%uT$jC1$JGi9b3Y1sv_c2R@)-XJ}R&F6!rgdW22p~bB$Sl%$1boe{~JI@_+ zy|2gFs^zjeUj)Db-{Yt;qx6NfzDISzrcI0|S#^1IB)~D2ZT#s>0NKmO_Z!y57>CpQ zfMkhb6rxk274ke+H=CW~i04#vwQ}5b!hlGDk6~@e0*VYmH=huIbLz226)uv;twZZG zQ7b15B$VAcx^FM^I(E{3NGGTGf6i3@(7>M%Zk8K$1a(U`sbIi1%BpG(cG3iX_fa`% z$v;n(Xu?VoH`kHmpQ>ZRd|ERfq4xL*vA}4p$_9m+3%AgzD#RB=2Il}+x^JmtLVG(T zicw7#rrjhdXM#Wq?OUr5qX7Ow1U}pr+`)Fzu2z4pOgh@Ry{Ej-A@XP^xFo@MS1Ll; z(5M!hbYGn}bj2HrJFR-JswxJWWrPD8T&F<7!+RlDZI6{2*zctW`zo%^SP@M07(ZfD zY-FmCVXGI9RSa^!!bQC{tnH^W0J`h>-0nUJmQU9KUV<)QaaW<;U7B15Jt}kH+>~@~ z|Ea)O!DU0^3Cit#;Q%U{-O0$XA-pgi+qEGZ$-O@tNh6a)IFy54Z%daRTX8UNI_JXlQZ|)!R)-lnv!% z1%?fm5gG~R_YQ3Ov`U)G!&Iw7i*-~RXJ%?W9cnegV^Bp^D+8s);aQ=Ti`1&i?~H}L zD`SyhP`;|VHh-OaBDSjL+!%f*Fp4OxUUHT6vDVXMHMc^m+1DP%P8%V`W9mXM#L{$L#8nzA|O^+?hgxQwQ^E8s|ip^;muKd&~$GCWhN1!y!e8W&s%;>$xUKM?UQ4wt8@MdhB?o2r4`K z5h}65&6a|ow=jdI1o}5OVJ1>)mwLC0?mFCs*`(6;$^KZ%YK)P#nuZ(9FCb>?qLd$N z^^5yGwx29Wbex^%yN8ulG`Ug!E+9sQX-HhJSJudJ@N>+#4Za?!;m>BBTO$UW7vQ#3 zkW`gn4cP!Iw?8XklNOFET7MIIVk&)ew#L;C`98knV6Z5Awx_Rm?OR6@lcTz^am_O&JNLEbdB+JeJ5p$~d!BlzSHsEjv6~MH3^$i- z^>m&SfoAQgqB3etGV*=Il2y^*PDt-c3Kd=0ZcZ+%H+sM&z{wiZ>`BEn*gL76qvb8T z;2IVdT@Frxz)Q^;;efryQ(9CZ#|6Kz8BVvM|9hB(*-@7DO>RdwfRdUoOP zCs1!P`d{DiKy0iD>p1@3GQ!UqFyqFDHw`w zcYVhUg}4bDa3Sc#*JpwpHnO|N5J(q369fHuugTZTUZ+sP)nmL)hSW?+n3-)bESy1K zP2O50J5`scf)(Wr{WW?lsx+z-lU=h52TbhKad|nxwnDGp$CHdhk~D6AYancYX&^j) zYanh3RO)+C{E(|clbx`^s;zs9s$&H&m;~Jy@(mp42IFy263YPZ`any`Rl!pbExUu3=@vZAZR?<^$0 z2LPaRXdg4|h&`CPUqO^{TULY34+pnVF(8&Vue=(U+TY|IJn6^Let6`rTYf9WwYHZl zKqiO9rmM9&A9uzCU-A-Qamp^7TCrorWZZ#CZW^pZ#4T5Wvw_`Byk0%p(BhiM%W+pQ zRJucxDbqy!Ng`u_P5MEYlM!E+?4%yS$q*I6tK4ovZq)ZcJrUsP-1r2=^v4z!N+Ia= zI8*#Tf(v7h^o|FA!krIGSI@=R3ieKUebq#b2GYTh8gPdMN zd&k}5Ewi+$nM~FaAT0>%qT2?&!*H~$&zjl@F2!dxRvy?vF_rY)^S!{6a{u9{3-JX4 z&@Qux@>%=$44?Eh`P#C9@vNzI<&{1!)GOoWOKl2V8ImkVd&XS59WTt+1!m%MODQrP zUHSSli$>Fk$-2P~up+6S`lVfg}!xHWnQU%vL2st~3hE>e(B?=Iz?@Ve;3 zH0a1?jj7S=Fw|G+iRMuy{p|gbNr`48VfCSi?T=K7u9T93nq6VG>f|fZww=-n+0~^T z`oe?e@0m{(dk(_qjIgTnK#ue2RF~Ags%Hc(4mfg@{ZV$-C4Yxp)&+TJcztq%Os#jK z|JCRr%xlK^lUs%QGF?pR8Aa3WFY>IDQWge>yyI%@aSLAUmekgF^DuiKk(~m9ucoJw z746wAKzH5|Jz}(W=BcxVOgON2rw`ePI{)w?h*Zi~EgM|h<8HmvR5yFsW5@}Xe>^`7 z9SguB6%IptAa)6EbmmOa!Q=vQ4|Pkp)~xXvCnn*PAu|I_HryCD3(;RAyu@Oke|6|( zIrJS&GzOw5YNYHbU9&0ju3sN;3Q@9ZXi#q3z{*uBL;&-y+7y)p@O&7=IM@VSKe?0_ zlB6}Uo-B}~f7U&EzNcjZuf189OwTYeq(WcX0QSWgr@PH(=nde&F=-b`mX-B-Kn?jHPk1Ck}vMnLFwa+oUVU?!XO_>Z0=mwy)Mf%>BP5ua8 zz}_q$o_1SxgQ*~krYhB(b<;{zAr^EfkBqJ)l(K)FLrEb}5Hh&v}ccH>#D=fEmI zJw4dFXFHo+B-ge`s^QkGp%O$V(u1~%x>>swe48jVd7NwzV}`1%QzNPK7M#7?sdN0#zCO$rOR-AWt>hsl{1*G=a5l!uzKgOPyS=+ag&JQZ zln+v2uy5KXU6q?viyjx3F~cRir6Oy!m#{H__W-3sE6;nd4W};dBrK+2d(64xt=Mns z!h&#)=*2_c5jOA!hJB`05r5J_EjdG9ug?}=<7{)O@SSuFb%zgkMc1UDFt`gnMr%X_ z8^XL3cWU=^YA(RD zW&QBh&(JD}ba9{;^RV&N-b&9Y7%pxW|ZPt&DJh!Z^w{Gs+p9 zcqhqxjA_Oq-D*vCmh;?J5L>gYXLFay8?E;>07pCPg6EgJS}4tGma5!xZP4v^HpPQs z#`$e5P7N-1 zsYX|zicwGU+}j;$C7Q!#rn%2Ex&cJHo>U*kzlK0P`_1r9Y(?gLQ;rki0US2jg=XqM zc9#Q{!6?RNNU@$OwHpKD&=Pqpz%Uqzi$I@Zqu}P_%<1YuoUvDB)qFSghK7hCJKzdOHP%3ASDJ*D!5ufkhZNm`K z)2fF}vdnwoFd5dOBFc)|#3jTn360A!B61N6HtGo^fa-aYTn8D^g=QjUp3;PF4mC!J zak3J@!^3u!$EYyI!-_i1So`T*cX!{m9=F-lF2|93phwdd+7O`=>@QZ-FGTq>v?@Fi znMk`X-s*H^I@B^$-lw?J9K(}N>Mlx0>!R3543lv}0yZ_iH(!lHkLLoXY)f*ImiARV zp3l5256kv($C3)}}%nO8*xXXQoJs=6i#Q^)L-+&hJ~^}!>Vd>U!d+;z;f?IQO74y2y>A^ zvZqMBls~^t%xJd1UO{pmB=D%eK~e`xv4-e|0-pt?7VB#!EhxIeBCtwM{JEyk z;*6kABW_)0f;^5NNrG0P7CYy5R89`@p>X5Y=cyom`%(aZUemG&mnULR&{(Ie*&oai z&bpImP!K!CB10m(_yxAf0$ia3rK8@0(~qZahxj_-GA{wHp>eg{!@)Y-~|hhVUXZ^v)k@dD$r;Y-)S z#iC$rw(etApU=Bga)XKRgRY@7oR(@t*#)-bRJQIIaNy$&jn$~z#=@V>rb()Y^|Mtn zAmO3nGc+Nc^(=v`1X-C(h_-CzS0Ased;ORAb>EM}>ivpZC+d5Bm+1T@T<0$dc&fgw z&(m%Ef`swA1U$4FW6#F)N(@CWES&1>txm|_SE5zc#O{poX;5ZvpMaO!W9OzGrG-$} z!l+>QN-;(s2^I`ucYRCxKTo-(`-9h|xfZ6+9=}fqt9rHe^oe2!ezfCRq{T|o-rgHrr^`wkwULVci*vSH&FRRsz=E(;$nE$b#1IYI{(YX6Q zxq24hxv|jzb0w%XO-E5X4;3pbuN?yKHnd4i49!tPX9Iobn_J?-Cok6)TDhDvx@mA1 zqN?AY6$uXs&&A_rz&bWpRNQb~B1MD1fI=1jZLv*g4?HqYYG);AbuN2kGVKdCPn3J3$-L}YG`Y);=Na>s#c zNn{s+8l5xiccZ7Z!jb-Zo9y$c7B!+un->QaHQLY976-PPU>1ebaC-W*6Br(Rp`=4bH@ zMSZ8qjl9*%>;Ix8=28E4N%WR7sFGY7Qk^rIP+FV$E-u@5Rk}lyEf@k+Wqwwmdg)gM zK5Z@j*Cg>(`2#xngOdE?qHH1C%KPcHkaX}C3azP_zm{I^FN?n=u{&~K<-Touk8}>_ z*0V2PW5a*W>(j5rzcD%}`djgfyXYt`u^c2S-X2Z5KPa&;6`0nF{bnpP9AAsS`>%?> zsp{HKG{tsXjt5G+hWnqC-1n>D z{v*i~z8U(jIsI0s|0w>?Io1AVV3)UDzByfs-#^v*SEu9jT>a)p4gWxqzlu}EeO)bJ zsNt&tuV37l{L+~^K-i?6YdFYIB-qWf5B}_UcfZvD(%($r=}6@_rxsiJyQTVFlYdm2 z@0m^Cct-Um&>Ra@7`}fZjLdg$`Xc>fnV{})|@_UF3yA4vW$%JQopeQm$~xgR-vYrwvn%eQ9Z z-*4#uiqaFkzY6aEa|`xQMUnoc$MAD)^at92|BB-ORpno+E~(BxT$BD>x%@Gm|952c z4-5XakMW1?d}j1prAyVzKWmZxGnMXly?pC3{^5rATYu*d_}qW0K>t{4@u%Rw+wJ;a zrg0WNOi&w0-K42YY5nLwY5)K0O7s+Di3hXeBx1QBjjXFra##%yJ`~mT6#p@dzX2^>`oxU4^R#^Zc?HZ$^E&Roi}0m3@tj`C@yep&VDq!G;( zT-SY)^J8Z)W8nn*-AJ1%n8N~3#1zUZ%NZVudFriWD8uwb0qJn+Cz=HQtxHD;P1$F@ zaK75Izn*YsWqj|fZO~g9gU`Q&pO$&JKDiSgU3WLl@tK=UzFN1W;gtR$jpXtM;$CU1 z)y4n!a$v4brqV)f&fc*f;x}3Gq1VnZhOa+(^`W|wE++FmGj1()M=q> zZ{-J^i%Y|fV?So9s%*52%KEmh@zp$C>SaLt7rZ@r%>5T`r<|`oH2wQ1FOy zxGLv)H`XDp2B)V#(SSHHKghZAi__L7HEJ)a)c!#K=Z`;i@c*wJT$Ggr?ON*H?m#DT!L=0~jl>jGO17FO@FdctwG+}yc zKS>*U(lD?nPw|*&+MApGqAyk2{jej<02{PvQM-vjNNh=m!I1q#RtAbYSds$gzk1Z0 zg%BZy5G3l+1E&q5KPt@{J%6*Ce&3P*D>U&xN}pKb@Kjj+`R-w7gtdO-EUB$km#y=d`plcZdT8Z)Y3{mR0H(D3F%3*Yq-4UZSmZ1$%?eb3p{^Z)*^^sCUTT9Er-N_Mh_f8l828A0sNJSBeF>-}P-Q?U%RGQ6PqvDe5x$LQ4) zdBMseD-~OEl~#Y=_){N$n#2FI-tg+y^8OpEihAjQvBHr_nuH(!+O7W=JxYYiS!HgK{C`{BXrWGRn(Z*qL=qu zzK5s2J!V-3ED$oSEF9dS*brPn{YxGP8N%oOnVsu);0G0=yOXUvDoL*t+UwnR3xW15^3Zch`iJwua6MjY{ z)D)-r9IZLX@!pQTc=Pp7G!CQk)0!ZK7x$7u>=ZFmux03Az8R>MxyQL=4cU;im9)N3!vGOOH8)m#n z%=P4yqVOrUvs=lNqlVwVBc$8ad)CI^(3vE|AFIcj2yAlS(>$`xII!rMSvHJ~mZjo~ zy79qD2S1wKt$Ph!In$k}n|57Tmzz6f(*w08qK&{(7|9zfKNpQ(^Yi}47mZzw#A-TC z0AmvIhGA1ig5D7g_fs_dgq2^Dpj-9WuoUOZA}C(H&7G@+lpozK{;DwAD|4MY!Oi&# zPXy)>GalWfc90(l!h5~fEZ4r!6U>}LWYH;r%9{(t91O%I-P1jMSq_(;^EbHymc!ol zXra1?lTcA^@DiXt`3x^n+ZL9Gyi%+-VspO}?H}Y4<3}fF=t)T0{hPAn&C%FVS#pbb z6gDwy*hm8Ahw3q}hzh&OU}o~|a}((85aF{EamcSh;EEa|4NUtAE>yk>OD z2I&!{4aRP@0xBdM55(```S0f$%Ppnu+&;4^-CWV@E#JD9znMZq!+;Wn^ub;ut$Ul} z3=FvgPot)9u@Uj5B5R!y{FbXxpC&r)EZUQ`q-FiBU|_yhUJV;dF2!(pQ*z1=bp<47 zj?;LkwwZDQQ3zs(o#-_a+C&HhXv1y#830bgANCRxg+C1^5k+HcQN|Q{*maU7_2?8G zOo*w}R3!EUBf#cUl*CUok1lG`_dxs59GS1LcvAQ0oC+Rt8#Z5xL8c~Y#9wv}TTmA+ zEIq23%pIQ}NpATXS*6sMGugQejl zB(tQ&ZRgtliXYCr3tQaYck6=zqM_DWl;(JA2t>0?MnvwZe`+~!%f~V9E0HVT!1&;; zR!eC3C&4&>gk^F0kNJ4DUJr02PrKwTg__J^;XsmX@X$RIfI)0N3byl{;0dkqG)_sM zIRgy$hzD7B$sgg>u2;iA`=mU%84Y0JT+<$1w#-Dm8UvW=mJ(o!q896ZS@J_p;emf> zG~D=N(agzu)&?ndUES*?@VfXyt_9mVc(!`#J574;|`HU4ZQHk1y&i9Wcy$dRS8oUb9oLi)jCG$*U z^DRqP1uw=F@osQBG;vjX{_ zt!dk7m27P*#kmKX5+Rb@Uco~YV|9IfB~=h1$5Jd|VCuoe&5^bYv*CFknu|ng$YgjP zvQpIJf|5L^^D$}(3|3;A&R;qq_duw;ZB{RD87T-uR}}LsvwgeL6fMXls}M*%cxUKx zM@-qz*B{8#c&u%+`a}|<;+D?%x9f*fBGh;YxnzyrZyyZ)7e2erEAP(jUh1Euo_gs> zDpgqENL!{YXM*}tRJEO8YQhXw?LmOK!FYit?1-T-T7V6+tkuUY(yK^af2Q#hOt|%M z^McA$V`p>4F<0qW@9?AFo?Nu{5U-z6n~}-aie+r7H*&4bgPyP9X;uhcm;+o55*C*0 zw9B>>x3&9}P}%G}Csi(WSFo6_4HbV0>;`mmH%KZN^{{NpcL(>o9s$KUmUk7!>d`H< zWd^gn)f>_$1gwaUGGXOodb13k6D=0_Hsxzo_uR-pH>Mh!qBkn1ldXc)&2;nUOhfYf zC=-)1n^Dnb4xhrEugs=HaVS+j z>yx1r)6kSUYyI^9Veh@8+Gw_YK{JIj1L|bH01-%-nxwz4zv>H|uMyRaISGReN`JY47UlUHcam zJ-}}?I3ZPJUfXdR6EpO-xc+$KfP-9zom}K>LI)m{Ob%~UDzNOGZp)mEp$Wf@z*Vxr+{My9Bc-`H+T;%M+# z`Ek@P*NolvE_?jXCfO%cP3pnSVYtY9mO}gxbsiRw1{nx6UW%iQj1>$+A+dhfEY2imO~+P)kV$~&k8aSBZHaAs2NCib{S{eoPn~ub1H|Kxtto}NAnDfpH8Jf ze$RfKxyq!rlUkX!#6?ggF}R@9BCFqym~!G2QY*C%J#0TJ*2Qlj%qz0tLa%q^boJC> zOR>|YIOe9q2|HS;ey}3iPPj}NmDpaxmYl8oH5lvjV}F#b<`*}0ab{f5OvPSG>Z)aK zwegW&8Ys*(W85Yq$2)-{q!pRBURWU*J<0}xYPLqS=swX~`P8aov9#BFNr^FrJo$jk zwFrFWr|gi~GG-n91>C~AW^YYHM#Y5;3%Ya|_EVdEFJEc(gQ5D@$dn_6{7+Ba2MV?3 zuZC9Q#N7*ub_Z%LN}1tRx)h@2FJqWIA5l8UQ0noXqBNlLsxN2xtbOaQ01pzv$n}+6 z*c-i^{WmFta1V*cUz>)+NQsLXMDT%`yG!e?fjf*kJ3|VVQaGRqy@(w9zKfQ1y{xID z+<7_AJI$Z_k#vF=+aBN`ylL_i zy3)b%x96^TYaj(a3ZY@JG(U+H{lrl)YEnwpLfOK3BVyc=X0$go9l!4z1VR=Tjg1RV zM>f`B9=r#?+c}u<7v}c){H2a%;>GQPvQr9@Ijh{**h!6BvJty&G!UCi0Izq#}LN3!}oCLs$)nO0jn5UMH_Fwy94qrp-}EZ8N$ z)}VJmgXPDYF8c@ky%FsRtp_&c2G!k3Iv03LlWQAatxJ|5mU)eKrg$^8r?9q1zQkaY z)JYbLWo0mTCWXMuvRdn+FzF?udu$0+=859oe9D421%*!6nqDKhS6_a+xk>BUn(E&y zR-sO;6pJiH$lF`DXV1sUR}mgMYJ}kg`m2~-B&HIJ9prsK?EJ9dG(IS=By!GzuC48u z?^DKBN%glb6_ep|uxNKwCC#U;Q%maM|9i zpR=aKh>gcvH&)z-ydlPsYYbHeCtMs=5#fZJck4M?5PfabXUNG$soeQ(UkGl_FKk|V z*$a)8a&xQPD4MM(DtkR_ws-PY$T`NYs{eQG(cl2MC0cbmzFD1Vv&?EdW5Tj#QvrvE zutq8BRk(nOA#7I52KEogeyG{q~Vw*hyNzGp_JwSd~6Z3MlV^(>^rY4<)y zDYxne(`7_bAN(jx5XzhmpWoxf?^FH#b@y9)BxROFSZ8U5H-(XRhy6!<)qj;qXzgo>O&Z9sgGQRHxD-N0&EwLd`_YFAkZ3+!Q=Ta{Jj<2p&&R6BH7| z1+-Z@9-q*R6h1}b#(dM9v~?)&FuqEwxumv8K3{$vaC6ela7HgbNt3RP+dVB-IRY9k zkKP}Y@Y+HDj7=~qwk1Qs(PE)<1;kZ~KUj7Jqb8~_4{EE8;IA}3amRH;X1MDdHgp@Y z@jf;gFfWVzuo*BbfAg&rd~8@}A`CAR4MK!?h{NJ&)LbAVc!6{qWzzr_6WGgt8vJZp z=rY4!7k+4?%Bd0Rx}@xi?0A0We#|e4ZD1c9G+MJ__L_@;M28MJ zu%+CY5|Ni>jo2ZFX{av?vvM+)QZYIaui$8;PVb`Cmh{%}Xw%v%`AOw_X^te}rq%OQ zhDAsDMdiw|!%y*kfyv0bvvYARHY@0#I4r1F!%L$Y8xv9xQ0xdCVW->}g21sYiH=k$ zEE7ep8`o;>B3^a|W{&tP2$6L*mi@5n$5y6x=-L;cR4Vc!%txcRCUA%clNoU@4AoE1 zHMI@p@0P15Lxd>ALMoG*MpBL@W)dhHYVq*PZR`9EpNsmZ_dnW1F1C0bl?E5NF%~O# z>hQ7L61p9=jhhep!ZfvM7ABC`$s8bj*`D>C3SZ7yoAsA zfz>$sFr-laRZ4tlWQ<7d(dMg6ZIA|BKBYd8^bVI*8av*yxX>4GTF$N_m8^J}e9@$O z;f`q_8U2SS3b=cbS@5*DLiQeKVPu=;1E5|)Nt?Rd&6L{Vv$Bv=GCT%7nGOtF46_13 zhZ6MJBRpKWE{7PuVY&<&e|;tY{$G5y{BOy+mUIR1KkH_7xTM+o;}i0Iz3+MEDawwz zDttED52E(<+J~~@)ZmoC;qG>0xW#ewh~Y!x z@&lV%c3AO{LsDqngZchDvkdNOi_E7eFG-Ev2R;ynsFBAPgY-py543`tWNJ+hO6FDG zIi9P&bBvK+%h11fnix5S?PWJ=fxtc6F>Ia+m+YB`HYX{+0B`?&7XEksKYHc=-Vb{J z>aDmGy5Dk59V|XG3Q!oEnr^P#@nbet6z@|n0BzHgH-)N>b;91Jm`l;2lAdGA+ z+3tWcG%{AI1m**t9$k00mN_QpF%4h0|tzEX#t$$M!uQPINAngOHkJHC_Ew1xFpb$$7)N0vF!v zNts?GcfMBlX?_N}si`JJjoO#-z&r*B3#4hw$5WRliiY-)c<^mXUDMxcCd3P#!SrzyyP{ah~W`#4Pv9}Pvo6(W=*U~oun(IkFtlMDK>%2 zsxGL(>i)F|yEk~yqCHer&-wikJi3B>kQZkMuH5ew@mj|4<1QP14#=fC4%KkM&#?yM zrZ{pv>vBknYe!`*f{RmNNnpdksi@yeEuN^Q`ra3%c+fFlf<=wXA)UCgjns9KD?l!{ z=tqs?4;`Nihh3m`Duz7bgG|DpHGXWnod3H z=V`eiQf0GNcDSfHRpOo~5ESpM!WHkN&#A_}+g(;8E>zyS1SzgctKA+aY7)a77VeO5 z27x^Q_=XbPZmKnE9-P-VNA0KuKs{^FbgD{`b~;lrE-{nZLSp3IxsbeO7snq=1LIHZ z;3ae~FW=o|;Eb&Y>*C$2_EpLj;zDt9xM8rvCkn#^`g-0Kz_;rOuFa1Ebdv@hs)R7O zX%erqGH4Rz)C;$%*)x?%rSfI`jl}fW8)Yl{GEjcgj=Mk1$hl?ayN&r88E%A! ziT}L(I7-M_$1md!`*rQjEx*4W3oQd`qy1ve@A<8F6qolQuK(!ow;u}1nT|eR04M?4 z$1fn`5obRy-~S{k?hc=!+6U-dgU#L2wou%Bas&-G3$rESjkxJh8mv9yRmk54Gsy~WY@7@mk zpCf-~XQUu1F%R9{0p<<%{)_j2i*gQlmL4bT^JS)C$rbzmLMhPqJ%9HksMR;`A|~B7 zQL4HiD%^+p3UH!HXHl6bnbLf1N6+R8ux8nOnCDBY(UNF~0I%|7uM8phN+lp3RLqN< z$C&$lL0jt8!?F)ap~8Ylt^>WWS5eV7RycfV)y2HJKLMyI0081IQl)(~Gp+3-HME6p zOc7KO%7vCes8Yje^suA+?JPBaQIkH+Foy(zQ;7B!;QGyfuGG=-9=gM2R4V1%SjS~< z$-Er}D^};uUja-m0RSswPpgqG0xFq#RePP2cL03gj}4CpkcMZ6Yfc%N6tD<-DLQ%# z0Z1hhrHyMcmjKuB0ZpRx8vs7|-g_*URZWwChlNAW9Z6{}$;$GVo0K^5W)so2Ssl<;8a2)7Qj# zO73S1+v}u*uvZk&Hn+hm4Ko*Sx}5E^6LS?(hglL0Uc~7kuM=OO1>z0smx-I|Fh#ip zb|aNICCs)1kdQEYRt=BX_A-yLpGH?c;=Qcr83 zGJ2j=gA9|Iwx^fWW=t|ryZuU9Cg6nJ&tNH^yzd+9hNAFbpLN=?Ef73GOX|qTjvr40WuXW{Qn{az`|kJBANjsPmR)MW8X(@kwd>rwg)HAt-Z;2MQ4*)KdQbiF5NaGwI)Lj;XJ!h9_Dh$2QsN z@7|23e*1hn=dEdWNjCP06%)H9x(oj#?<1r?ZgOwtwAMX+^n&_Y0rK_9BER18)GxQs zq<3%k-CaSymmnM}$l@c~jSNg31#c2BQ?>#tC>7qK-X@+Tmki>#`jSyq^Y6*O0q)if ze2e)V8yHAgxA<^{`Tm8D*M?*5A!w%(AN?HB9=5S~ejWszg=H_4=A zgJ0i{BVq{CRq1SCs)X2BfeaC08vTpDB%-DmFBmb+aLcy!`&m-~9=(S)DPTS>YB#=V z%4JZsS}$3#@a;VbMKRkBGmcuZndO&ZLYU@w9_JbydW?T{f~TXETvHfq4wot!hT7<@ ze(JZdd?>LdXfj=}I5W1IMYi~G$WU~WO9C3`7ef=qzYA85CR??OT znJj#q)E}1cO!uV(lW4@_DO33`K7NB+wXt`*I^B9c2SNKQfg%<`goWQO*8(eeMUW?w zi8OY-HmB4A+KN*@-fy@H+8>ncFm%uO-qIQ^>88_`9&>nZxs(x&EA;Ry!U56K{^}Rk zV#EiX^~gO|eF)V+5oI4Pg14W&4Dgn|pT6~Ft9(i!>U)YB%~<31jPlV}N)B4#*c;x& zE6OilX?xrlhL*17%hpW#BW8!cyLJ7D-+fiX{$g^i?B1rb_{#^aQZp#zShwgb0(xgF z8BQ+<^NtRQ9Y}~R3{jK!r?4tA+MNzi0=2lKF?(9Sh9`#$Voi&voEB%Q)j1oy7KitR zwc|W!>ITM7YhB}~b?I%E(!FPLmnQPpGehgeZx~o6)6DGNlWFLX82_34`c{4l8e|Lu zsuuT*jDLB_PxV>hmrJ|tm+$-N0f$aTbMqv52J;9*m(tZ#ur02WQkSS#fHAs4(cxRG z_jW|PPE9_i2-wqkL}D4&U{EM7HjC+AsXvi#gTexedlOUWFbKn^7qiQ$G$M-nuhW=c zb{W1$e9H-A*vdIw-s`IP8qIt1_PQC*oT?~hiU91r_r#pwS;q*&$@!`jyACdlm=Rk9 zZ(QJa{CQWp(38n z-tCtKtG4}Ea_%I*8C+=JjP@Yi9%-LhYgqb9PzX>Y7fci-Vf9a1H{H<^J$_epw5c8k z=fd4uXBGST`uOdEIf{bsWaQ4r37buvMxN^Xm1BL&;NQEU11`@a%U|C6DeA3uPM=g} z9q|9u9-{wAd&oN2JDb}(J2CJ-!{>q+c-73!tc_nfxHIVE&z~^}^YJr?i19NRGVs1O zM&L^_2#fu*AjsUw!3AMz?!@p%3(31XD}tTz8t5Nqiq9BC{?(o$AA{&WYe-Aul@y-b zKT0UzO9=k6Aq74L5x##V`58n7{*@G95dCKpf9kzPIGBRX@oehj({c(7yjte&&J4WD zcE*o>m3EbTDpR{zIG4TBd3x8VE@_38ak+1P}|0u`5liSs`=_y_xcvGW(lyxP`ge^j@Cn9#rVxS)WL zfXIK+TVdr4~)5tXf0sTLia>2yb4$3%GV2fAuyQ!Govdd@nQ~GV&WcQcyCzk4P^S zcqt1)I1y4Y3kgR?{pg<)6ai~NpeD}I1B2T;EFa2DT|Sm){FKw4$2UxaC-{fze`ymr(=e7XY zgn|kt_y+#A$Zn7UWB^}qP+MF=zGL*%;rv2aZ=?b$;|MJk-f*Y5 zGc1*rjj&Bh#xprlJP!QK8CRLI0n21;R0PHc{O4sWOa9*$?EUXZP#oF)$R@qSreiPpOM>!xMBJx!^~@C)Rp~IaI>g_BM+v4 zK`tt7w{5?dPHv^0hY%RWfz0b0+7Bn~(uvGy+wk9%BXl=Vc9igx`zZx@gm)2+!VV*s z!oaef15KY`8ponMvw=D8Tg@58>rl&kcBsX^Kt#P3-fjB`Kf>_~lLmLyj&7ZVafL71e*9yjQOA%WTW6zN)h> zW;vYAz9?_|!lYbSSD)4%HF8?!?%Z|8_}ZX9Z+5Q9cN|1J{CjnkU8&1y3|vd+3c#T+ud>Rx-MiJ`d&_aSC^%L1 z?a12Tl2-6MFRG6lMt@7-Aosy!O_9$ybJDIG;xs%6LV-u;+vebUHlKEvcKbDiP1#*v zPqz>y#)HeSQ?A2}`Cmv#c8i zTl3oV0ycdo=_hU4Xw0S0WMqsuX@{qQ)RV1($z`0(^YwuZ($R>MJe#(dO(R|E-5HfL z*(*TNtAL}sm%FnOn_f`4ayB`9PJQR=iAsV-hezo=eoa-#zZLp6L^t70DIpUmXx-Fp2KTzK}Y zd#SuZ)B(cMO5VBjq^ua(1^fd)F!j1jVsvv{o>upv z+#9w1Ao2;4Gb7`%vfR?7;&JRguNoB)|b|f{)+TC0oroDn}*WTmT zL-5t}RuSb2+-tNIJ?~M`_j24k)vq%-We&UoO#UG4SU26eLbvm|ayQAc!kK!s5! z$5C8tYWq5fgCcN8hsluol5p*;Us_Y-VAJ=v$4qxxaUyWx&5~UVJtKdox*a!gO8<5H zxQT7(8IStweRqH17IK}wvY|Or%eLBvdytWAi6JEr_Yyi43onSDjr5AL+^p_$Lp-ud z-O3&bqBzgJx3>#wxB?K~wfnjTu8Y2qAfu3ZDE63AoY>Ir0}GTJQvi(dB{WCY-OfI? z_dJ$PBUgqw*m!>SnXO)2w4caiZBr*WKuLDVqvD=Afy;BLn_5A?Ya3dSRx|WINJwij3#gLdve7rP;de zMVJ%ete}T$jkibI*ysITvbQ6pc9hpThY))csoqb=R@+V;+|EcYIT7O4#5F0I zPm^@A%rs9+g$$D2*wWbTtj2A9W!!7yibsnZLe4Y$F%&1E>IP#cR{$!Dt&x7QxP_uR z`F$RzJ>=xK-`i61Xx1Ofhndb(8N#I6A1<M6xjT-f}@ zz@vv=nzPNFN%MT#X;%PB8`fCbIP8JKWmLVjM|U%1JKh60>E_=s)F3SbyQzUnEvCs6 zLW~FIlzz08LIxG;lGnH|ti?48a(u_Fz(>P6cFe3o&c6KWGW+%l@{t1`Vz787AXb05 zrz{?APB$7vRvT^99ljdpLOlJbc!6W!{nU04vt8JE?leyB^hlKi`Bsj zU+b2|e0W`|S`u2>uCnK|kDE9}Op(LFHm^6+Gg4I4+*~$IR(Q<=X1Ev`c+tNSF;nox zUvK5+7yB4wt9mmu@|Exb$i_GZLcZpYn)s1%dfgW9vpOvVvi z?E;O>(>qlL_UR+4Bm9ozUUY`ksi7(d$LHZGN^3|`o4QX$$lyI@JEZo=`)&<~`Y&sc z^zxCAeE6g6D*&^+mKWKK_jzxwfz{CaF{&3(!noBZ8(}otXQ7tUO&`+?8TF`_ySnhI z?d6Mai_$@ZX(}QaImU1w1=Eaq|rP-OFac%=N&V`ojA!y3?Q7I{rlC z&Y4HjIAxwU92A*=y!a}0C}lMDif~xb<+1cCsXFy8v}1g->~G8(5G0>F7FfU2=XNW7 za2lDN0unJq-*`~Q{6GvRr@p98bxfVqD63umuDWy2bn)BDROmiM%EgrX;jU$~Y^3^u zk^Z^r_TEx(5&d5J@T$GIw^5opx@N#Ssk0#BV)abfQE#6zdm>Rt!RUa@!|e{6)NFkj z63KLFT26e29Z~!aU}F2%yzjp`Rxmd;59{_sj522AP9eV4;v|Tc>*z^yN+6KEJ@Mb% zbYBm&NQ8WB9>X|z6xc=4z`Ep1pP`L+6>dY$U;pqft`ojWthru2hLav-n72fs>Y{j< zPGz%<#8~cPT}*vQEXWCDi8>O(0|sqNbm^C;wU+I~q2yL@R+EyVpL=ue%ITt0XUITSZzJzWaPp*$ zog4_+;z6Y-IF_yaINVc;D*EE7R1uVOSl5Vkhn!|C=;-l#vE%M@HP=Bz36&YUyo4$^ zTvosJb!SIJ5rJI|&BXE^EBG zmX3UN5OL`<)wm>jkZjPeiVvcvOSUR6vG3ktUxuv=PEzh?)(Ih zylf+|9xA1g`7=H9rx zQol=eB15M?STH#`QPB5+!zrUyt!`j4i5i=z=vD(#myCVRQWqxzq6~?#wOZhV@I~u` zl9k%2XNENDkc1XaS=7D`3}-dOUTMZN6z!LHZxYPJ2~6>pse$kR!SJS&Z?|MymQ|4Y^c1b*pnciyEzNmawHNjIO)>(aK(eKHf z@0{~VWg}~WPwEDIRE-+;yDg+l(~x3LC*u0PpWjXD(>S>p@+;I=1vviTyxF*`y#LhN z&IK6iCSOtLGFAj_tzixGfEOl56+G&!OBeK3PZg}E=rgL_sR%?c zE;8EeY?=4mcunT`g8rb-(LS+Ka}`89ES44bldohqm;PMCD(%EGcSE?efqT#~&ZJ6_ zKo3Y(!sP|-g?fn@Wobna;)?J09Jkjtss zX^7XYLZJ$!qHuRP=}#xlLHC?|nF2JRE#O||*bf-HRhlvU$n`fktV8yB(no(i@F8$3 z?<-4r3&|SLFjMKTtTOX@oNMe@HI2wN>LM}1y2+4N*;hb+I}23RinwbDT!(oe8b0(- zO!=3nxx_Tw@HGJS8{HhW&&dfocEhn#~akp(vU?0??lT%Kuao4x5pS(dDuJCXw zF%`!>8W2z)T7<~G7o|GtbwraC@Y|T26s09 z5e}J_;_yuzoA_|`Mu9_u{l^6ZBwS1?`t-Uh06@p37!HmKNSmAto#Y#HwzXG%r45Xk z0e>uj3add~mDzGyGN;;_02+B8nNeRfsTz9jg zR(+&f5UP2xUvd*`EpBQLht8LnM+n7=Gky)xx&8#`+o*yfY9Fs=%!!*on6mo!al^h~w}+%71$0X0Q7 z*qK!Z=9|bP*uoo>t8`sw+jmU)N}LOGonm{BHK7W*Y2`nBnZ|$3KW#FeGw*@x4cngI zt(-AB43et?=?uFoKPtG$deAwx;FP?S!RUn5=%nO7mejI#yYXe5YcVl@oWfsuwPfCK z@Xe^((45Pe>ndizChivk?SnKD7%TX+n5vAvy*6ci&J}15igDkNEBDiw7CC#=IiB=r zqEs$i@%!R#qu*~`YIU@5gQ32(Nvmq~Laq7B;9*ZYy~861+KoyDVSb)1%}A7(&!uGC zC8kK;|2r$EgsY{Akp5aHR{L_WWD?X8Kr8AkCYYVe?X~6Sn5^Fssjg}5X z=>{in(DLBn5lxn3M13*|i)l!iqmZ@3Qm4m>l{0qU(o4Ht)Lspk3ZYH6aVPC<@Lprm zyG|Sx|M2D_w|tmgzKk+0DqLRPh)jB+ba1h%=zxC)vtP3bLSpieDQnA!`tz=(LoUAj zRx$gx&|&9;o!!T*zp;3eE&d&+iP?%pjTU!lVFihehJs^`ldXI&7uCtn^}-gdFVWQX z;%vWcV%7@welOb4+#qOX^ zbi)+>bs)J@Ur54}4B>Lz`B+9Ft)sOAvkgdH?1l!kr4IVJN2$#4oFzpAGb6MRv zhvJempP`&tTAX=DYv(~}J+CLPWN!Fz1jU;Ana`f?5BNcmDfL!9e|uiBL*LlvrD5rm zNHcr4bVom>G!oKZ6Fxc&LwRlF)S>(2<5E4qL>}vnj0PM>)t*3T{;p7+!*urmj43YN z{@3QCnrtmw*WVD^2(}*`xU}lCg3ZAtfxU&r_n~HX5Jkol7@~eqroA>Ck!?1Ahbaap zceuE@zi=T^cM;%6!F{_-ogW4I=(21Tbo4MIZ7$JhjXUEj9xel|HMZEYE-K1fKtF~$ zLUA~xrBqrU#(RcYyHFokB#oSQNK~u8qVcH|-FMr!owRj|gTS=ZUAUw2+?-xFrHudw zzHU_sm_eYI3l2VOH^;neTYdu-y+jW)Cw13<0)2rUA!=1a31tygR+(YJ!56tNFAdL0 zG(dudla)G^YI>sC?XvWiX1#Ou-hS^Z)#f~T(3tvSaqm8qo>6Nnrox4F=B2Q?kjn5{ z4LE^@^N(BvH`>P>csioJU|&iP7=mW{{MrL-rVWEbf6Z4Oo0Y^mMWkf}`N&9ui`aZ!TpmV1wkwcjF+RxyAzwxkPQ|+oPtUDWi)u9ol zy)`J6nP8e_3We&Lk~Z4$s%kJfyO20W?Tob!dvdGX=n--O@_w7cf*3Fk7~1#Rt-||o+q1{Z z{nH*TE<)2_HjS2?Cu&_|bU!$LGJj@&xu$qGnIp}oXThZh-sj0zFR<1^&4{{a|9qU- zCMIh0JNRwb;wP=zgI($Ut+(N}ZPJQDrIVjE%UfqHBo@8aNapmx%^eoUnN zOXwMa1IWaI^GucyI}CY7L}#xVf^oZ%^jAQ$js8Yp+6Q90pWdtcB~wA!?7J8m27Q<& ze4UCiIX*co+Y)(fs?E0j^wElg3%OHntevj)KsuYJuq%)@4|B<~v@(XpcEd|%0!B&; z&$w;;ZvHmKp*i3q&0UZ#I&#UM%}CZ#sR&W2cOp+YwE%!96LCJXyzzYT8m0(Q2z(n; zkrkI6Kj~%Ln2F#pEOz5LFzj0c9X0zYIeY2%NwRH7@!Xh5IKIUagzi~_I)cN2JMwo1 zcoGJcOAKn`GGl=xW=gBHfkjyNbG3#9{CxgAVKzep9{r{Ap&7BZXgyipteM<7Dbm#N zFmd=C998T)-4!QUwq(#BnNyM*#W60Q&pCCzUS-aI=GszXRHD$VvoxV76e*W?czhfs zje28yI#$1_6lq~PY!=JnfT)`tziY^3;@Cv9fRjcs<`MHd?&` zh;Vmw<2+a8MUZRAr>hSI;BgHOmJ%zzVpjmIN*k4~N6oS9vBDkn2mvI8n1=nmGzH!> zVLwzrqo@V}DOL0D9t{!^`iq_j!cJZvqBzA|3!a>rL?vchRZ_wOcm{8c^=w)6YL9WZ z(}3`iD_RV4PTW3{u^SkOktRhY=SJ4Us4k%LVw_oV-{WOtI*uzZ*_Q3I9m2Y>Ru@!v zqUQ_Z8lY4j=aQ7r_q9#mOd|{3Cx>A)5)_tUdcpO+H~0F3d=@NE^L%V=9mY+;+p<-G zhvE0)0+57r#fE7DekLq;#P(ou)rI1`pcX4986|(Evtp(EsTnbKt>uACbI)l{w-=n+ zE(%pcn?}+y4}L3T`b3a#znGZ8d4bc?Zn11acd=bv$N0(KDOKVU7`E6cYgHm0Q#aA8 z`eJltdM=38(G%%FpRY_(J|wAN3cRIvI@~!RHN_kW*;Ke}9O!kT-l`aawTMY(X`(%B zZRO9tRBBk8^n@u2OC&C&LbKL+nBZHc5K(9@Jr5B(I_!s(-Qae^ zXnhsG$HR%q&GIAqv>m-^yaU8Kd$b48FqX$uIWaE}^FE1mxaO^B&YZ)WvO$BwS;b)_ z0g%Gi`gdbuD_Yb>lYBAIUB?81HL;W#msL0lKIf^}hhQ=ULP07=+9d_GoT+g(x`dYr ziCv7Idq=gbJ3lk&`Uvy)7%7fm-3=3y#l{F%oh200*Uz1)cu2v06-LIlfq?-5vgC1b z3N5gPJcU7!e-LXyN0c^Yc7go`)+fhBp}5~;*tp4TO|0I>dLEj)B^wu(Yu=z-$N7U% zt{j2fG`b5ZRT#z=n($5q6p!rn-RbLludGh4-+FPFNHWDjFw&^rS1?Dk;Ix*lX383! z^ApQmqu=L!zaZ%x|NUtt6S2E8R&bPlPeLzNP4lG9wl5dF`77Q3$5c9(K&54mNo{#- zMlRA_Bf?_2>X9?CniBUy$qeGc$c7Kr7XCx^)*s@frBpaM=|*9h&C=p?aHO^??UzA) zUo+{w8fUHWKK(RJ8wb&#?f45PrdxG(8)kzeS_&n7sgmS{7S~5;a+INF&QYgo*rL5X zt}K6MBakrT6~LSn9+>|#<1O^H#>1T=u`2US;oQeknfWIRuhuH4d-S!6ZN?Mm*Ex?A zZ^Te_UbNI?+P}3!`?#|k_&(>bkySb0| zlal6M)!r>u9s_JpguMv)ovRT)dv}PusK&Hkc&WE?GDzcMdz*)aY$B{h;_hn&!1e>~)LS zdu-y_&y^I~Qcrtr?~ABK-}k|y*a?KW+5sh%L=qIT-D!J0T z`mbV#186)(fGX%rhb$B-sFU&RKKBjRlJNGP`0;~{>B911{R3k}YuIudVLr~cWIuBO z+3L9a`(y?G715mjG|#Z-FtTI#95YT^P_9#ZKapm`LkijoO6A`tF@qnraKVu~M{j+7 z+i+!OB6rH_?C%OlzE+-vil)0c;CHDfd&n5zSH0&R4Qa#?q`jm+W4{6nzbvSWN^$p= z>@r+%pM_y58gE#%9MDh*b32N0Qp9*s4Vko^Nj`0D_$3A6tjzlGD#@tG>DVrgk#ie! zeZkh&a?Di!n2jKV7z8kB#1J*^tH$((IF@PsYD7p(UKl(dV!oz%|hK|E^iXzv(Lc&_7VLE``tqHu-o* zjju5>Zs*MgC#Qa%YVXs7F5=XTSC%ux6tQ z;W6&gEq*9PRcW1AFD_itLOfBW!DE7WJrQSvaVc~IK19mPpM{tjbk2l)?U?dzQ02O* ze*ZoIa3eeL^2;jil;VDX(!crnKQ2YuA%1!G@x$=hIO>EA28oEc0z}ochZ*^@sz+`e zqed;??@VsR;5O$e7CK9AT{w`bzz6v%)-qFDN73 zJ)-fpxUP^^jow9IqIaT{N7U(>c1K`M>Y9;7J%USU(NuFlXu3oW0yFiUX%Nvkd<9x4 zbH<Ujef15+GBKyYe8-I_sKz{@ECp$6r6}BQH364k6@|KYE*1B^0zp^e#8y6|?eg z&dRX0%UPzoKArtVbO)*j@@0^YE`2@E%Wkywt4dCJ&Rn9yT?@$;8k4X>%W?SIfDCi( zbe(A+-h|`N_Y0DUozL+5Du6!RYd*D!#<&Q#KRT_#72ybKc+w)FG!?U1GkVjBu5zJJk#vC7j9djbQmQ?z zOwG&DNvWo+$0`t7@e1Iydy@Fb9b^y|`@BU<-Ea@Y!a{*?)~$v1z7yhHgiqvDeoZKO zPoBDeC~dkMy~|#p?%El&%k8;)z?n-KrQ!4za2H@T-lbV!htB=hs=kPQ)VSurn32Kh z#T!Wuf(D|U0XHN6-EV(VH|T;gOYUM5+Q-I{Q6=B~2cSQ`P{*H#8GQ2DU$QMaNw3sM zxRd)0aQ(StJFZo1mYGTCUhZx&{DL&|)KA{c!A-`hgnwyqy+*g^1shN8gSXeuD7miD z*?08zvoifU6(TcJMeg!H>1Z6#8C<5fj>yXFwerFIB^W@=_YUk^)SNcl5i=i>JoupWta&!O`i4jiRNfobRSuT zRckOCcXc0)#lE{6_s`q-E4(M!Fx#=uQaV06Hta?(P2!uLdj7jb(W!sGuI98p1_ZJP zIzz#l*3!9e0XpCQs`XcVBQC0UVW-R!TF4jWdc;IE4+UvXf03x9*L)-kK8S1Do+!Gi)qyu3%KFBIJb)Nt zB~KQ9NJ@e_+S9OZ>$&ZrJ)N{Yw!_|+=2$`}kpevNx3i$&!N;J)$zUW9t~!NO_6Vw;QSiquI( z!&eEBM`Vzr}347SNBmBA4 zOt4YIxK2OSpNrNk$~4MV^V%noF!#%S?!${{tf;gi4WomtosIsk-0yuOvc=%=_oAXM z{_A-_lFH^NlSeJb?S1pQScehP(}(o4is!GF=QDCUs791h@$=!zF1#*^Ke&^kde@Si z6V-s8W&`eON$#)hi*DE@QPNG)P@@V?yY(xa7Wg8}P$DsrtgTmorcX>`t{o0qsY+td zEO@cpadMwvW-REulUoK4Tw8FK%yH-)e@<8Oad1k7WvbFEJkpkul19sCoU=v~Lb6m> zsTP+l0lJ-|K(Xn}-bgmf)TdFV^%w;<%?=hRlPMnMWV~z&%aMw8O&S<6$x=)3FcOs) zkBoM5mF&r9EBOq>cx3TwM2gj*?W_llQpN92=K{+y_Cb3ljJBKVk9x7E9ep*XYvVqs zVgI(cCV9PDAyF?Ql;cs!u1{-rkZ++sk?C(6~f})hs++&hYh5c0HyYTaMy#EQZ&W3l~)S>bB}6>P*tbdqwo;_KhlTd6L{z2ZB(XK_G|SZJC)2a+x#%7I;2<5NDTBa zH#W(;VX}muDH0JJ9Jf@kqbRF6Wou^Nrz)fy!y}hm6K3SjXITYY|KcKL5$(1dMEu=XFM+7_dwP&3;JB*}w zkEAap^HRqgq0R*{W2FnUWY|YE*rCO|?Dg4}B#2oNZV{UJ>LNbw(T3 zJ8a{nF3wr6%nQG;@Q~Zvdx4f4-FS4^Ipjtr@-z3hb_IT0mCLLqhGOCHh+4&|xlCSV zO*ri%pIY@M+U$d>JG-vBBBN*E0c6gX6}OYnD{}+5Bf7EyjR+3+O3t51TC!&Ud%}`Y+Cvs#G=At?t>g#~kB%-{IH6lTxXhBugk7nqvYUu_^K? ztsO#QigNS8^!KZoVs&m0B1g9i-4Y-Crt4Wd`&s0p)H@5#sOJ0-8E~|N-hVdi2Zge# z7B1SlIkUw~4S@|F!1wB>?i*)3EKC5hM#m*>CC!1B2dQ)f@s zu-_Bd%y+bOsb`}&?j2>6F9ojRZakGLY$F7l*!#zi}lZ$X}8rhozB* z$Y>*#Wt1IpNjQ!&D4I8QpN&(Bz`2eEDk)DVAeeyvN(r?mM;k0Ih7?L=l{Y=)7o$|a zb%{85#WJp!id#bpgo_=E6jgDv)9)%=c42E^3Aw*)GQB&rBlBy_%fKko@j$W%h6Rw4 zs*n28-GW}k+yXJHtL>ijWxuSo=&92U>UAwYnF>o>^IF(YI?@i}zZIN?UKdWoi@-J;9zQA?vXf4tYODqO9B6 zecw1T9HLRqb{jU!)4%C9J|*t$wBF39yz7G;qa?0{+Nm2wp!yKSAYLvWaib4L*rn$l z`jZW!&)-xpxCK8}#8W*Q^-MH+OWDtycvAf_ySD zG<9CP+!7QdFTc^%qy-puVVS>BPMCgSo6LQQo879nWvloXRsqM7m$vUBA0a9UqE`ZZ zlIiJ-BlOg2pDF2L1VlaL`J?(0bvJ={KLJD>znlu~VfWP+S5i@HF8C31Vg?RBRX~J5zI#qh0?p zozq)jW53@GJa1k__GS|He}ORmt)xrYSV+waF&^b?kNd=4IY0Yzxp#UYdtW<-dAMS-$!?{2 z&qSea$Il;q%9+(`op#1II@yeXZ>ZVC^vrCRbj(dFhE=TP5o2f5uVnI3>lNvvH~d42 z$E5%@OiS51EQ>@MdOu|&ZW*Z#MqR@*Mcyw`vhh20SwZJ&9Q5@;$Q zQ)@c6amdV7jcZPAQ|OB%W*y>HZsw4|2Mahek`D7F#w#`J2f?{b#XQ3@Az|0pPWDP_ zoU;2Qya|VgI~qGd*-#b%(!5kSC1yYK){>f|YLr0T^NfsSU$&9D@aLM7bwU!YVam#W zl z-rWi7@ZMvdVoSS|_hCx$d)s@E3?~aLOc?Dsbd*B#X6n#7M_yb}hC@u9y3u&xiOAVS zf&BOM9=*J^n%So4d6eKYr5ZWD`odwo0?NA7jYn5(}lV=UKYofolsp< zORD!IB`Q+Me|vUAp$H&bG{qE#D(Z*Y@2{-qmE7Dg04ebV@-SwGW~QvW%z4#-&*@ty zDQ#J0d%x*Uv@h5y8je>g4ZHz8Z{CzXKOV?Of^LL8cSPx5O=nS7SI$1i$wTk4*a%LM09*Bx)x z9h`kkSaaq(7e~HU-(@H0C;kA|Nyv%RC$aGaS^*Vg+MOCLGe^Nb@{NZSL#Nr(tzr)wVnr94XA{MG!m%xhJk= z58hY;_HFE*>K@r6bWStS+YO(alU1~YO0lh>a{NEI>?sg`j|Q$gJq<{*Wj?^|cJVsm zn_qq=Ywio_sk5}KXcr^F#YWZtw3my`yl??QJ^M|U$>na9j!M$u`n2ZLkm6U(iT4!w zvz^f{L1VWQvBsV54W&kCb&85K#5k_qFMdb~dBTmf>Q z-}>06nGmWDL%nYpa!Tt~_LGEboD|P7w*OdzdbXuqH;ac#8d0}@eL|&*TOb8@Mv0O# z$r-H2HHzVva$_eU$u?Gzy2W4(=^72d?h9&Wtt_lobcRQEqk zO=8&D&4?W>hYAXXMqC+0V{=>Eaz0HNtLVCm%W|Sw>s_fS^_eH;=HA8aw^DWLvDWc5 zRlVKAH|)F(Qfw()El0w^Umhk0cTEuZl~iO!nA0#_Or1IR6htzWr{aG~THf=CS#J_P zmJJGKR24A~hXfzP{w0!mmbFW6!=`53!7pZrOz2lo49|wc1jmLCx?4*sD=Ws9SBOQ~ zL^P%|xtU=k!hWAwASicaf%Iwh9aKoi8}oqw7QyV1;xK!)oe8L2Q$$gz7qg$C`z}w| zv%XdOjX6ka$Ex3@rO=myStCPJ)R&QG)-+;N8&kqu)fMJ`j_5~nQtGSiFA6bl%oH8IKc#~xeQu} z^YX2lQDZ)Q`Pg4v$9|)#y`v5-We*K&0!6lfT0pK$51TErVD+GI^PiWvJh~I$VIw1Pp(Ei|Kt;l@Q4pT-?r}UG~i4vez@IB^^V@$cJp+ zCO_#|p2)MymTJDyC|K&98JbfTVruw7wmotA&~D`xoekBj9_K?^<>IuyNhNU5j$x5* z*OvF0vNc}}R%Z*M%k4@os*GOSvI+?JlTtrbzH&A`!Xy??3DCT!@-HcS5Bkij6 zqwcVEzpDs_*m_1gd{gf=%BUUd0^ED}eWIW31{@pT)C0ySnjz4kYrim+rHm{&rOKH} z7Orv9gV7WdR6_@$0AAjUM9P0?z{Y{~8EbNFpHn^O~>R z?GaPDK2u#dzkdiE8Zaf8=GglOq1NR#e-+Qvbs6OoO=xKRk;3QH2P-C%f!F6g*e)>T ztH>0M5$W4W*sxKJ8NS^7;IE9>uN?{ho+4ib+I7Dr+l8fJ?909TT+LC1#gmsIt+y?nzM@L*0%5B^=zb2xxLPpts)o8vS>8!EU`!*Mz{8)lyr!1y z69c*E>DPqmz+BUvFKKaIOl?>Q(vf|K%!de8(#mN$+mGC^|3e8w9#LuxgaZ}+Iy zoi9gu`T)f&{*4blQJzf6>g~Esm0`0nof7^nnu6G#A8SjNpxJ5xr-FG z80e)Vy3lh3LGMe^-RVuX;nfq_qm(KLxAO*Dw|Bgk(Awfa=WpbNB>Ad|-nSQJrHDJ= zg_0jg31?K~Mm7(%47mlx&qe?HnPE`PUfE!m_Fs`zL2zVwojhcUIgR;8ESW><$zoYF z_4VBNNY1r;RbKaKrw;uD$M^IJFkXQn9$43Vsm91b_*DD{@)?ffQe1S=FuE z4}c6mqZjsW%RF4`VR*Un7uXCNF6;-B7Y@8Jm(m2ZVep)Ju=;Ka@fG71c3JbTe3@D4 zJxLrdyu_oz=);o=`3yo(9C#tn_KeuG1-MSulQKz152`&A+#9^6%dZj2zry2Lbj;L| z`&OuVL1f-p(4a+#av+e=qgNcN2C`%1o+ zR#Q{xj@)~+#i6aoNl5+9lad*0ZjMlUik`TfUhBe6Ir%S_^FYoiVlRb0jC{oK7&@PI zs^2qjKK~&vZzK-Fl*U_eD-T(;s5s4ZT{$7;SK+r~&>`EBBEg_S_>uBeSaX6$hK?Z& zlAvy6lAyZXW}d;V&j?- zs*K;S2Ylh1AE7zI-^aDOHYCF6<5tQTIlWSNd{Km)o+OZWxNTBaq;Tnph+)8B|3U)& zonMObFh5_^Th^^+=5NOTzU_MET&?As224y?BuMGJCHdY5R7`t;LW#{&#sp6C%3BVv zSc=ZGNAEc}+nzj=3VqUKC$8n7X#wAn5Jq&C>W@YFTa2u%{ZtXwOYed0)aMV+wygh= z$RT-g<@vYvp1!UkIu;q;N!fh(m_dV{7TY3LxnB_<4&|WA>20&d;U-GOS`l%byo(_H zv6pYNJewF6V+-w*uPP;GK*zgCzgF#B)nz`w>YvQj2@SwwINTti8Cj2(S>lb|Yt}ZO zP)vJ<`n%@WD6d^j5S=5n1bMJh`too>wnO7RW%vQP_s`fkH{aPQ4kQ1ec8BZKXUhdp zV8T{W(Nn5V?G@!>fcJ(>pFb?$!B~Gx{|~JQJqO;CdHP~U$;P2I7uFLi=NO{)`8}^EZ@0+8Nfh@0n%v+}r*e+58 zM}(q-j(XeXWkiCB+hlLKyGrDbHDQ@?Di3 zDtm&m|K+pnq*B1Li`<$_*A7K%?zC5~?C><;ye2s(-?uRC=uGt!SQMsQw1^e6u~*4~ zXyD-*=b!YieeSTNqvKn#rPX95U@~aT*7Ix{j_`9v`cBIm2PDg0PDiA9xt}M@^1Ln1 z6xZBB-k==p`v&WsT&8unidmofa5%1naJ$4X6(%_-kvis&={y7O_)E(@)Z~292Uavg z=O$impxSEdtw4Lj*fX5Tsf(li_s^rmU?V-?NZGFZJv;Su_HBYPHgr7Bm};&^&obB8v%1KvBfsJ*C!!<<6)q7oo}2aR1KKr5Dp+NXcAf-R z3EfW64jjSc?O2DNW}hX@f!q26u@!%nUZgKrSKN+F^wC@e# z<}kB30vkF@ZbOvg!{ACyKCeAVyiX)!$S00ccSL(JM%^C*2$dQahcHL7%Ey;y_ZSCy zpyGxys1+p3dk$t+CBbGCb^Randwskv{AJC` z2Zwj#$WIAzUX%_bXGyJH*n9ha=bUH~seu2Be@37bWMja8Q}kC@NU~x=7ja~LU2eGt zfQ%H_89DEGdE%d$3N#tMYL48-O~-$0a5h@ByhlGVWjKNj?b1y6P?$fky17o6SapE* zDsqfDbu5>>IKXqv`cQP;{LRMRWQdr`0#Pv?342JDurRe-ML`j0Q;7Gj$>Khr$Mp*p ztgtzodx7KKBWh1ZwHFqystMo#yjNjZ0wn1ePt59yXg?;2rUyjbP#@6IDc!U|OizSm zr0H-c2iGIVh}rdLS@pSLW@jn0UG*sJMAqTyj+5^t>uOj*+;9amT2$9GpZCCMRGVs^ zN#9z_ptp!usTl1{o%>43<$-1gqeqHXdH|D8pRBE+3_Wi)7ai=Bj^l>C3_Id@SyE&I zmPjpQUgn`-g=4;M%kmYj79R;4bQTuD1xQDA<@<)&EzWbv3AV{;&wla!^IEN&c*~lv z1MEQbyu>?sx-Kv9oB}9m*|ag* zd(3OWY-`na^TwjbU6b9u?xbwELA@wO^uavrKnY6@37XhD*W-w3+`N?RZt>m~M=Zj$ zU(H!zDgA&T7S&1c(b%gpUdy-8wsEVqo9#SjjJe(!Ko`EDne2&uKO=F?+aImjlEYTd zwZOp+XUODYqo14mWa`G!7=>C}S1A#C@7`0G2^$d$Vd*kX^pN8v+Lor-G%tk1Jbh~3 zTmp31mA#BU&MB(H)&xIX__RZU)RZ}#4}48<-ew52`fD#a7HmD~utBUFtNv)OG$P|w zK@7_W*IPw7z8)K7vK1WQHsD+6Q~_AjsE`m!gTrW3~<2$+Vi)E1&gHgUQg5v-)sAFBZ|`QE5+`inIPBViMmO-db`4dPJm_uLoqYiJHV8P{dXVb~ zNU-Yb`=TVPDO5I~tGXQ&Mz&o%Pfi+~eBY>rK<7F*C^lW}=%Vd+fM#F)^qEiYdXxhL z$^Y28I_w3iBtp1GZ8Pd!g|SK@A#Yy*zfi5&^H zYd?dy5;@P;*4qiDE%@81ewn2=a_PsnITFowP_YTiWYGlr5;JSf|IA z2Uw8I1Tai?4h*MO4=UL6+Q}^nh z8!}ARH?hLewi9x<n=H)$0?VV;2%ZHV18bG{Q7$Hi+(}jSu1<&-&FTr$#nw5G=u#+Rl4SyAmA9$ zl>C?rxJXyLrl z3wPDCbD`N7sOSTgvaFv^c`^I04z_Y?0n>L{aOmB$(5}TGvnL0x0oN@ObVw2^?hM(#FO8yt-8DUQq zXsk9V>?^fUv6Sdaa*l&4m*Yb}wMLH?&6kYjR9LURyf_p|%~kdK^m!>s?1Bl~fNET| z&ymUk@{Wek-GRT1)gH6I0L9PR^C1GkfQe1zr;(UyOmg+CtNoJCqf}QUhDBWqw2 zRc?t@uE~Hb!4E)(#ap*84gDFmEOu~V6qiX=ZO?Fiq3~H z{-)D0xZ|Z^aOS3}{+#=ssGA_ZvkrfRY&V`y(g6jtE`|C915_V~YJ-KI_MK;jzg^$f z1WZCWk5GUHySb}^eqLVNZf8!zwk3UH8%aktt55yUo4FHE9^6m-tQE&f^*WHGzIpW; zmm0_lzH%vY!9Mwe{!i?cS}}_qtW+c8=;9(zj-@sR#DxE>t{ULwPE_8M>|2Q-5$x;ta%|>^_5|4S!Y@&t!xAiTm?Zn zH4#EZl&j5a$dGnmFzdOEB2-0%W=yrf%xdhcZndha+m_cXWFFZz)A0iX|5UA z_c+551)*j2mA`5E9qRg=>ZQ*i5Vp2_vmqCwae8@`Y|+(sUa>DJ)Ohc0#(YNPI%r{^ zNmU=yhlpJdeoVySz>7P>`bx!q!v7;NN?Uj*c)T|cuRA@!-(R9i@MeyWwz^(8m~Z(F z#1XMG*%rqS>V;KN4yo*X-n?JHpw8hrT3Qu@^oz==J=PYoHlzVq8aPRC9pIPc9qcVI z)>Sfp^tfY)d@SZ90CtE3%3o9%XhRy6yb?ugJJ*jU8;Xf37T;igO zxPlP-GYJe&XDf8~q$lUA_LPyZ$_q+}7cYGR2#8@l;HWq45E!1t&?< zLlqZ&t-GTxr~tJZo$pfN?9tDjOu~BoQ7|mZK5*TTeR?%|_OasB_)MYBkk{bf?HCii zu+ClTOGCIC*s$b!!}J%VE!=?KtX1tmPdU;`stexaVX6O%S}$*Jg5n!CX-lb(O^fX) zDk3&8GB;;o-hEv&Wf#f!sL^PJWgDxh&C%23*ewW6kzjiWcs4mXIbZtIq^Hk#h$p%2 zbB(ZwXoJE26x_6_vQ&q+-(uFV9E&_SdU)b(Va3eslA3YQR7UHjr*6Y_(fWSxX6~WI zZ#wGW#Z?d8>}(=@{n+bQ6RZ6-q1iz6r2gC3MxdS)Nd$XE-PaqRNlMn?-S_Nd|^pO3~aG!+Mu@VIpP+)?Lmr(OQ`#t3MiQ&BONs5#8OltfCAgu7N zD7|u+yR8s>e{}>>U~fi?SQ<>8sEb50HZwicspXbX6cYt1YUwfPq|eM4yW)d0VskpP zabEhe51r}=Y9`wVDLkpJiw-yO@8CTp5)PQx`D|5OcK!$ zK89k9Pbxw9c*E#KzSC6Mq$a3V*czPgvtIChQK7rv927)cE;~5wJ>MvtgX$g8DlkNJ z@%%Mmm>%bCy&&a&95|=f1SJ44L{likpFzhZPUeu#FRVgtWD6z5)}C<%-H9EMQui#v zdZ8;-vczYW8v-)IPtiPs%Kh0(+z&P>7?N0Ez>8r7W|-;LJNa?OU3x*uYUi7u@P4Zi zi+y0KG)zYVN(^gg-r!|la<36Nx}DuwkKY}udaJ*!f(1Cl`JxVg7rnfbj?WhMIg(4rM5jp^deTUUSI9< zChZdZJD;Q}M}PjP*1@Ft5*fA?9bwP^fPBJ$T(-4}P^&_wG&3}zgt%1#WMdaz#*7nV zLn`}!)A1}li)|1OC!6&eyMRo`??=mS7x!rlr_GZlfF`7YU72+o42WuYA5_60G}TF}d_+dfM82nhC%cje>+uEWgGv^XkM$&U(;SFOX8*^JDCCQmZHDpLJ(Z zE+p3$U%u5LpG1LQf{aVkG|Wr@;kPIcD)46%(F88V#}lqS5XPaPkfR;vL{WzVz60N# zsXlI&M7~pbBDA+|pqzDhhrrgN2QqHgn+`_s;q6^<*out$>l%Y~Ye}~2rVe^c>1K-u zyGzNlFTle?pMxZZcj^#v!XzR7^1Q)$o^lO(=W)f$?ibr-Kg&-Jc0AjqS)yc2$5uzW zUsY(iHNHv2wkxkt&FwxUJ1@gcUJzga>{}dcI>@u6s=(C%Rhw0RH`F@y4%9=tUZXB4 z98|VrVy!>5%`)dEJbrzq&w#ibcX+IL;-<^h(jTVjW-gvj-)j=Q1BsIEk^^;S2cBdR zAO%w_L5kHyGlryCO?yA z$FQUL5m%7gGvw{(=81Kahy&C;=MZznm&u80^$xpTT}h8YW#k_m)JPBRgzS$~MADt0!Hynq<+C`(e`%zvM;g{AVlOn`-wawT?@Kj?p3ZsO*IxC z-u#+?PsiLowFBhGJsHi&z71oL;m3?D%9Uf6rSLE2b_Q9mPiDK$vw!_vZPi*A=E2ob zq9AWAcTerW7#PSto{a@6D~XLeJvW~&L*^K?*$jD`@>Ff=>xy=UynG|{bOSRB-4nYH z`n0}?SE2+FLOu|#3!Kd4pYiI=%%$SNJ)mO6e7kH+Q|K9Uf)h!-44c}2j5ycTaM#WP zjUwc)Dy)`a8B;qk2Brt}D*2NHFx>A|`Ra}~#UnWEQgrvXr#+a-#pPw9Xxg8pZL5m9 zH3+?0w-1^qB|jR&lSDPwVXMNeb{|^i$mWTRHlfd2b`HE?9q1a?H@!RJj?75wWu2#> z1>f^j83u5iV@@4R0;Ul|joUg9_{LvywSl*6+;==5T07()VRN}IL6SB!l4Da8sXiJr zdqpQMN|kVEC%EL${*1<$TV&-i5{>8)t?In6K+RciB9hd8dEpbPBwy`$bRfS$oJ;$0 z@$6-`GQ)*x0g%sz8I$R1$PJSGVmYn8Q*rJzA#M06|3bXpBycbPB0v1i?m*&2Pwuya zTdCKhW14t)LVvvTz4WF+ugA(-#z)!`1aVM5I;qg-8(8& zpPGtX@h~lzhEiYGq3Az>V1r-hmlm}P(e(DQ;? z5J~7aU7X7=YkO;~y~RK{W6^a@Jy@#L{f=r!A9T#Nyk(B5gt$gaT5ZzvJ51-i>}Pu- zqN~CT*jD|1Rffc9>#TDA3iS3!+$#=v*v@q0Q|avP`do3Fx)Nt~9M!y5a=5QYPgc1{ zBhQQy{wQIj`5^CySlmbZSTU%hG0Qy&uGVEMH^bHA=0W_mLf;xM75B zr}@JTl*T=F?*LTHiq)+Lj}UQEq`N_-7iym#9OzD7&4jT7Zx4;%-1N4<)i%MfQHMeC=0eZ zQC$HII2g3y&BPX4ObK8mm}tAGGdFk`0zxtrLrCXgn(RUm6EdZRix887W8G?cwq>$E zR7Uyu835Oy_;Chb?2W&OdozGO5%U)u-u+csb*e~}o0_)Gz99@4H_vX`KE2JBlkMl4 zEUl=@{fV%-H@2}T6E^quFdtAE;=ctt8>^i54j}nV+AxHxqbCqDGs}bW`gAGl<7Q|r zng@5bsOH{>@S@{~Z`#F#!(4ls@bn?sXO;*!vWxmbxvDIM_$lF%B1u1JT3A;Lt8@sf;c`;hM5c=2rF; z6*G`^gA}1rGlvL|^%)kj(X7q|n@V`s?+aK1n-@Qae(f1_3*ZYEi(pB~3xQjF?-{iT zUj6mCScdrs?hu}HqYNV+q`he!$;z9Wi$+KYHKOiZ-vx?HqOk{#akq@L{r%@qE!d#k zx2>bqe>Q3`i_FYyuy1yLf&AK{$+(}(C_HYaZP>(ZJu$!LHZ%6A-CGKoW<~8XrpSfy zS7{@*?G^%x>oU=Cr?<9#lH)5;-4|?}IyW!ShLph+RZiDL_c2%BIx$koP^`Hn8yZNW zJXqLEhdT&aw5UO45h6$P-R^_@p-#|kx$ErPZ^w}m1236F|9eeY>Q(8e7W@K zTarc`FJpv_5J|Z67j|lVJN@oRkSESiUzKs@H{Dx8Mr-R8J}9wVvTLd?K>gM|QC=Oe zi&!!PNi@kN0FgtpoEaUJ#0^n)h*W5GE`Cl)s41BpH&$30rI*iFb>{D*q$4h1JYHwl_W`~Pne3N+1yux&G=UcZ=Mns|J6d}CK_IIRn$22gz(^{??(_Qw2t(22i6K!7%rnPt}TB>d)D<&rh@5 zs-C3Y5fhOzHj|7CqAZwD(Su zbd_2-l$UV0^ggCZUlgO?bPnA+PWLj%%;I3tlF&hi^CECIR+!h}P!Yro%ckPFut`By zGRv{C@y2;uJ+E>1^Bjbm`aSZVv5ByRa8T!3?NxSZnQ73+uDvLK?eXj;z%SEFpV+zt z>vxi{w~+bi3mKUt)6UWQ{4OWbaD=9qpXOOPYWVmx&9BnfL5y>AoLlvKU(Bd#woq(!VW2)tuz#bGiF0bdDtYlGV4em5Ka<0=k)h4H+-t!JFPg{d2*sW`nBxdqHPR6qbx>upIuWSW)C@pc8l)X<>{IJLJYe0)#(RqiR1wQ@I3e5qHSgEF_wRK4w@ucvN;0V5Cd*p>1`P z;KDX5)bI(LLuN^HS61u7`j)OER*@G&Ae({O_XQs+i1oWhB8G7yA)tiavm0|#CW5xk zh1kN(3irYCo}~Hd+WtTuzkBc{ydv>vCsZM!NwEsL<@y-UDe^fzX5Zd6)ZwEGv!C)! z7A&Ov3Gig_<))Z`qTQ*nVf%3{xTNI5A6-YUGd4Z@#@4WB1jPh6ucoo$C7wE&8CwFG zK}V`aaj^!l@m>CW4Xja_9IzCW0w{4uZ10p_K+!qmmGz+}h45ahch&tH)a~|a+~oM) zsqEunCEmt>x^sVA79s4atSbLLSHbROr==?<+oR%WmQJeUvn*g={~lo zS4a^i1{RHk#CzOa(uhTyu4^37&uv+qqelib$Uv_fQfIYoL#Nz#ul zGl=AADMFSgjk}Kq<+S`fkZ)kc#P>|1YYJ$oO9cFuHmF%Ep*j{|WnMs%U)w9jYHff>& zA`rHtU)8YZcX+6+QJJmXs_4g*23Z7+5cI9`zaFfI~uuFqKsI-G~%3w*yyj#8;nAOXfLDKR>AKRX^+aoxa$Y(uZ8NiSI!Xc~40sCHSaxgQF3Ec4rtWr16 zn$PneP5n)0X*&6?uaxoiJNb+p)*%n-vy!IK)vMyyF^!3BvQOqXipZ2OS~J0(Hib#F zqz4|Jd)zS#v3l@%$fI@Eq+{;u5`x^3E4|at|8s(lE&JDh84vz1q;Ln;Yr`Z$T7@nLdIIPJ!en}qM zk5efb+5VIZfT9T`a4m0t50Y$lu$tqft))Y*HG__xA=k1; zSl^x~l5r z%`FzQ(jC`HvJSS|Y<)F6q~Hu6S+D7|s0eZobSbGNS{}i^Qm^}~Ue66Rei!hs*+}yu z{*ML7-~X3q=l{vWy?S^Tr^1mnw7izOQQ~fb$unMP6dI5dvE(bW&*JQc@_2Wj1&VNl zmSPS1tWyfHwtEtYP0hTmEa40On9uuvWQz8o!qBfsl1$d-U0nzjySYt>zQ4us?ep=P zegU_Q+G$;Pxsz8ld)voJtf^~~Do}T)N#kI!SSn8`f7s%opK{0-4B@pG&Q|&%>ncuM z=g-5gZKJq;{atQa_!i+=@2n@aj9t{Teqhhdc5H6<&yBzS$7}y?9FlDqbi_f`+>6Xv zN_F79^`x_Sni}nx32?mjsBjY!m(V>+TCdMGAKVFMTO`(n1MjS-IwsTeeJllnih2!w zP6bg3IrHqAoO~NQr}y>^!d}$t*MbS&qQ_Q~z1pjNWce+$eF{)=;RDZlDNS;8cK0PL zYr9Lrw0!H7qbJxuX;MUOV#g{ZVciFDDx(6`&!|Hwd74^OrMrLd{aS24WKg#F0--Vx z630~BB%{8~j>)9tXb@fg6 z@zv)%m9ltQvD;Y!jkFq!d{}%T@3Co;p!CpQsivNa2Y>KA*GnHHaasrMN8-XJ<>$0C zO3QUK-kFOoxW3Ym;LzO`$%Z)eE@Ug2od;RsP#=O#XAe_kFYzLJex^&AjV{bm;jmqj z9y?z_T(*j1XATFN$phct$_gx*$1zj*XHLa z6{3z7jOp|F%KUz3LPIZ15@wDPjpIcfXzUcky`8`TtAl*p+WD4gN`4!m-6wMey``Pg zZXg?&iFsX_bgGy#COmxE|L<#0Xa2C+c(|5Q{_WScgpYJ@+=*Xs#e4Y2FBPlniH{&M zD$m5pE?!USro8=mJ1gqh2?DfM_*-?C%s-TyY@K+qVG*-UWecVS}RsGqs3 zb~If&hVN07v3=kYJc8nWq{55noL?2s_n`CFc?BQ*9?IV-k?R0TVt3 z{RMM0IjI@&;C{Y&GOM{jJ)dcoW8#1nV1LATdB*cfa7Aogzo#!7C@tS5=7W*W+koo! zP0X>7xC>-kzfk}Mmb@}A#?Zx5flGb3z(ra_#^jfID182GK5x4u#(izZ@&^_lA4ZDq z(P7r09{khm(|Ps=92F;a*F5sQ2{~+X=(k0M#W`Db;tpon%VktJ+V@|$r-edThFz1j{6?5y=nR~*MyJ3D*UxUi$=x+H9KNl0u$dWbGmchrTvhDju#QAonv1+j$t~Rvxf}g8I&C< zJDB`b)@J!hna0<$qmyXT&~T! zv{lxZWvW${#{?-!0#J{9Bn0M`b0;Jfl+{NjMqjM8GWpg|Fns%i@Y73HX<=)HttzXE zZPQk1ztC5N z3ne54NDW=$1A|AcvBw+7Sy?)rxwI`_ZbMl_s-Zp30%+9=w;BQuA3jG`QNsBl%o@rM zMJ_Nbn@5}$i29q|b_1e`E(RR?N9UCA$`{j7_Hm5t^`*Y9oek#~SJO9iZQr8+TVR2T zj%{1-l;3nF+D`}`V@=P+^=u6Ny*sxXXCy~szBP?4=&{96?G)?=gP5DIUFQe5(%sDX zKlxhvFMjL6h70= zJ;vd=_Ak8i)Q$W~&4krgh9l+kFEH#)w?o@|X&vZHQ}O|U@|q5&+1jgjiE-^@FWGfq zbqYUJ@?l>RfB(kkwS5=$#Eij7sG0_zn6qj%vX$1AR8m!BlA(U+y`T<~Y{kyaA^74R z8YJpF%JQi{lN8qis-V+>!UhJ3x}p1;8V@a>=qCM-wU}cYo^41Yj|WixXs=@DQQ$v+ z{JZ}6DELa`(gFJWVkmT-QjTg)a*Xo`=JycJqFHl^MwGy{=c*p%C>{JPg$F)|_WC{5u2V=6g!&aX}nT3PWk+b%(7uCsLEz3A-NiKu?lLHGU(`EQJZf~=0J~%Rae!NbA}h41bGfE6&_}9HRFv@ zc?o^Qx~*kz?ywK$h7lgycTH!4R*JKgKhpVdMwsKJbp72h8R@Z=X0hd}Cw1^dpZp4g zgvcvhwu3pNB20CjxeUD(7PkyAqG}|whHEH6m(iAmHPY-A;q8XS5gwuTb7@bi-D$4E z77!Kd!iS0(mA$C7IAki@s2A^!dpJ9stuRM)sM-%$92i7!fosOB2JZHXo2meSw0A9_tm{;x08i^ zw$kTz1hh#?q|#UlN_qfb2-DaRYrca`ii{y9_$Jy~xveE8uj0ZYu5SrPJxM~;&)eeT z&aV+`#@kdaqxwb$6~zYm!dZt>=Ejv{-fT*{FhC~3DtNCau~444HCO?)Wa~*r~9k zZ_|v-!p@xQ#~YmrN`brIF|t<|znP>3cun|=^IfQfMH$QXdRlDR3R)4QtJyC^gaikd zZCsf?SvWSP@@533z)lFBpM`CzlYU#Rj` z-EY@z_aSn#g}*pA$u&xl4*QfVXDgubom@pym(frfDGT+Ju39rluv)R@-7 zy(g_biXa+Sgb_WyWAgbMJSU>WP(MPoqRK5$h@MU0Yk9V{U*ch-N>qO54T}=LdX?kt z_Vx3`6stm6yI>)Y=nm0~@n~;q$m$3nM8V|gu!iBoxdFxPrEievenS6A4ptm;&T{XO z3JQ#8W*w0=8?)>Y3CqJUuqvqTqeO%%3aMgQZ=h^J+ME`HaMMq!ouJ#L{!7tGVa+2n z^tasd^5;|mV}aWJ{OdvysBc4rOGs_OmdlIwEvphz+HR74 z>JvAkxK6-P_$a!Ia@rsZlpZTGL0qvlz5Yq}wjxH+x95@4GTHX4aBggdCBlt=XK>Mz zh8tX0p`i)$3%hiZI(lWR7HC-K#R~0nhz{A4V9ju)GPANzk_cxOPq_7K5bC*$?!z{) z%7$dunlX}Fq%Y>dLK5H}?i&p|E2+IsUMhlFC=H12VG+OKe=kgc9gzzeAajAc zd2DtP0LAoSpC6CoYpwpO_+qOG9pC5@=m*(^;!NubA>s520y&+IqVnw*DbMMN1xE`H z>R7feXJnV|h+7e}Upbk2NyPLgq@$IRaH@WU%~s<9ElT8)G7WwCKnGZ>3bJ+>f0WSG z`nI3Yn=0hL^kE~S=g{w(*qwb(3}AC2`AK$>SSZ26CfrDvOaHN!DKPMNli2KUzf@7G zrt`mmdPh^u!{n;=%c=HCuy&v&b|$7#k-~Mf1W(yLGfT7KCJE}%)|)zT{kg<80o=rR z_Uh0rHRDCu$^oFy6fvN{mpmAR-Q;#9^hc1~7lf;{Z+>^TpPNO5&;2B8j-~8F zIiLNw>*XJZr}HkFAKM>CdI!NTl|6^$UqQa9*ROmpYl(n^F~7Sf6b6%Bis z8*bi#|NN>|V9&|FL`;G_HceYTjPJx*d0DF)J!;eeD6tBYa4Ny4$hS7>L*G+hN;19# zLxH-g5eR*cABIu>HJgaO$y;i$4b}$X8Y6hRtCs}ZLwF0e?vvuz9~(ifb_TU7Z(!-d z8oCddwNT4Gy)zjb^IGszG_RaMq*plo7HgdWMBfr6k8)<}{#;q*K$ufWZ#pxYa2c-U zg6X*7O=f0yrBE0jp7=;R+CP(BpBX5@%m2-r(jMm03LwJ$a|F-7+!8I^Q(B@tBgH=@1JdyPmV@ zfkKha-Mz*vvx-;F1$&8sK7T_SeY6@f)l`SgFoOV+iVW>{x$dEU^v39R3dQs!BjQ{*u}5VQZ58eInBb^+ht>wUkzS*XLAn zIF>ZE3E7&~X6SeqzRU-d(=T&z_C)PykcCumhiOj?76_OB=&lyyF)mA_3 z>zgSmdI#B=P4}M{|FCufYY3rLvFufodS{#rRL9d*nEH}qsWtb^%3~J_BG+{mIvmA3d+Y5O_wdT&b}m7wUN)USP+gT#atQ}!G)^W{ z<m{Z5Y71D%ZO@pDxTnSV%`c~+uXTtn5(-1%k-Sx=E^&;H`& zHtLyeb3d+J5;&}smjgAzf=$ZE8-dnRmCv(3dVH(~K}zjX4^G2U9{KyLr_5eE|r+kG?0lQkJ9)Q>}8@Sz>F+mPjAea4klz}#=Svc+dp?* zGVK&WkejO=?7O_lY^9C!wtM2^3bU&yh;nlqWv#>hmDFFFB72KRpJnXcB}3Q9m!ZEFDwhF$ucgZ<%?d&tB*F z#b{cz*&1UmuN5Ec!&6x&%cVXKg9Hub#qy5r$90IXC5B|mt!Yhv)Wvjn(INl%-`(8) z58f>@xN*30SxJ=LcUtSK@y6=06p8hK79X?Z())VKWn5;QpCD^+qz>mjvkO^ZgoVA` zcmSfra#xabs`p1zoXqUhBU=$xUZ-I2)}v!Wwvtt)g?SHexaxJaukug2AtQ3{V4Lfh z#=hqlnGk4}yCgmo)X8aDU<1s$E8~3umr4Bx_Z=aGv;yv@7GILwx;M)C!umXMRWc9Z zOMiqaJ;a_@3w4`*Bv!g8Y*dexUcD^SV>m}urbMD5Tb`+S@XaGK^&gGt)K~{bIm~Ej z0azv;ZZ_!r*=aC0$*Nu*p4O#5^tqNs+m?SMZt>JI^&)4gA7EE?{NwWIOZQ0kc{Gq} z<)&-g`!@3KPOQ*c!!vF7J4IhQx>?|{a&tZAQiqFQb5%1CE#v3XqV)h(#dDswe!;=s z!s!Ou(%J9~WjoQ$%j(}ox&r8}Z=zOAsh+UI>;ogcRHR3jz-|p>!!l=AT76sRgSSx?X zTjHl8y_%|4Wwdj}*tPY1OO8^$x$mTZmQAf*@jq*o{HbIQf~Q+&0}HHV15}-2((N$R zn_ARcoTLiD&Xq=)(&E`4`8|3tWnwrx0s&pGlaY7hUiw||m@K|3$^}(b`b3BJG-0XY%G3f+e^8qn*G@96 zAWh$iYu)x%kbZ4D1{g`4DeRcmmJ;ZzJAJ^GU+j@_9v_sRXd{X03d`j{e6kl#^amECM~E`#RbNt;in}hmhy7r~nV8roc)OnKSQ39ehLUJcgYQo) zN&7u=WKF>vZxRSmqqdKMGxfpL(y~df%XCh(uE2B$u+Uvh zlr(JW?!P6FGG6C#EPB-|8YMa^mM`?f{)BJ2mY2K@gA3`h zsL%es5vf~#`lyo1>6)p596xtD1~OZ)hFQhM>RV4hrbAvi^m+IKD^`8a{wF=M71BXw zU~jEZ+#eyxQjsU#h5uAJ&E#gx3R^mu?VQU-V%07~mU~#H2kU7?z927FJtzd7dTlgd zT2HcM0}1h97y_rjz+=$^t9)vQMbe|2dL$rv@5kCvC$QgjW7Oszy(}ghb+`)STxoO*B(di#EMOh=r$=PW<5^VE20(Pp?GPNz7ik+*MQ1^U+PB-x+_xA_nquoPRZ zZ5QQRROM7WFYd(i8>_vfzy07pSl1Ao?lyKP!~c48c-{!5>eldbB&Mg+QL=8L+uWx~ z(&sj*{$x}=ulviaw?0dRA39yA!WO8Ei9hj`7_*W9Ll>!TQv8F~5uk z+WfDry}Aq7@9gMwD=elNMW$7k;nhMQV*ZZo(t@o9cYgw0H7YIZi z91FKdSkz`5c zFaWnThupphOVCdzyA65QU594cHD<)hK|d_t&3n}bE)Hikoml6JFlFp}%t4eF!8$Ur zny*&;@9V$e`X*PNjKlg?2UP?E}uc5l9Q@R9ib00$!8jLvdcSw^fJ>D?XW#rTFB=$hn^NX;O?vzzOnJ)NXYg5 z>4aRcdIHxvpMWlVCZBoQ>Fu)Q>UNUEPdc`K-<|_~nIVPaSB*#W2i!)~+@EwCMQ7wU zgA`xxcLPSTt-5I`R&y&-!P@|{uc034bAs7lk8LA4Soz|as&N~%l%H=jOvwIFpuJRP zPTj)`26w5;i(Qm``cJyorTOpr{N%V;K3WZ*7qgc+%{B)z)E&Js1)(7ZOSqdT&!De3;-GI7QKj~(@PR}xRJNb_q6A)CC>=!kq*(c{>`#V9U(M(l` z>CK8~VO#|b%J0CzuP{B>=voJW`J`=6h;r5}0+ndBYlr}P>Q0eW#_aFx**n;eifad5 z1@UJWB%K-yIw%a1wJ0pdxlZtpF+fxzwy#_kpD=_68Q?A>7$xStN3VbVrupVT&Ai2N z>F-%9&ZLAELw@wk@>MhmIn!&~t|<`&7oPDC2{)vXwX;PDLPZvcn!0UZIUtfwjtm|jqcuGH}Csy*r`}`VT6UJ3Cg@8wT)rvOi?$Lr@UtwhwgSW za0VK)6bL!squx(yxbFSlR@1}EK3Z8`d}gD;swk*(4eEv=<^uoiTmriQ|6 z``@iNh{&z?fF0F&1Qm7om-MVPn633}hz5V(VE*&pPTjb%O?H}tuO?OhqyyS6_o3qQ zXez{cm+9aQOv`4wS$kX2}9{!DEh$Frd za7wv2kqgmW25t89c0L#)u2aVw)4AV;WdEf^mdR=`39{(|zNdv;!!7++%64mJgiDutJ1n?V(SuT2lU|GlYc*{G&~B{*<1ZMi3M+48H;6# zY2S3Cu5%@6&RRdSP9DXG3b-C+H5GAg$bau);G7JPR0}2s5d+V3c@<7`cDJ%DDW1L* zH+3D!+v9y>KziGFn%eDsOn-&wi|UE&6s`Ck!e+~pfn?{FSBH+$U-KxZ{Qb+~0h(ng z5y!OKZH8mPLcpi7u*m8O2>sv|Z(&;K$WOYMx1=edOZqaH#}v$=7;lo4h=Y>; zn&JGXRjuNWXn}%vOGy!VtG+S#ym9HucNYqqTJ6W?U2z}2H8U!#0)G2R_ps!8lC-CQ zUS6Ag@A6@WnKn>FthUybV;|?6C6enmTo0L2Q39W3bIJX>Z&uZ^?lu(@oJ(DsgK2S# zalTpBaQTMYAXAWX-3!JpZY03A2aZ2&6&g&Q93rsNg?fAbJ1zbz?S7YqC#VQMiItdC z^#mIn0?t&z!8Q$yM3f^(ZJ@c-Hdr()>v~zuxxoiHA3pB=cC#6%4Gcx>h(_k47L{{- zSYzOg%w1urf)N>wgZ#S}Vk+wPNx`ru_VQk1M;9ztCl({vSJT!e)pFod|K)9M6XKZE zkyLKqz2U<7#BdSHtK0-m3%5}x{BLdzZke%RfPl*vw=b% zBwd9H@9Ny2>B%66dDYD1p$l2Cg_-Xmh`P^?RjbNuq9d^)A(~GlU*Li&>2CASAf(Ay zRg6Oy1`uXCt0&~Y!KOW{-P!&4*K_$An?e0f>8mw6VVBUX3)8Xpo(63coKPc_Q@qYI zNa38!S!r;F=F6ENTCn*B4hE9jmCP|vRpvWxXVluxhzc0yrgXPOm200X2+3D zRL#Ab@Bl!QY~hW$ckP9WwjZ-RsLz~o)OAc6PM-~!HyjA=tqBomCfSu51KWSiY$otG(XmHwHF9^BOHVy*+!x*~b#uTmcKsw zm)?S}VR`jAnk#}hum1Z%@YvQCfTh(0QfZoQjxK+xWQdQ5)LHck3$J^8@U3kYYa4FaIg}NjF}uc@a$m;Q3}8pD@Lke&U1X z>sW^c8yn~z^v|zE?k7#wUb^VGm;4F=Hcj%v<6J|F74{^;15&OHVqRHb5^6H)mZQDK zjSi~rU+7=&x3ooNy}4d)o#M_rwUPN0;(b^iXat9a_mZEf)KymnH#2yKd%4=~ z({o1FeIL16jf|xK0Pg?DCETJAbTXp1JDS+kTVNa&y}fLBqDEDVbi(R=n$&;Qq|UK< zlvOCFG&N{yD*V~mpy2Vi@V+F|m4LCzPr6?SjnE$Fb9^=o1~yQ=!t9SyY$@T)70SkW zg-V)Fa;D0f)46BH)kyn-Hur1l!=+#$0z#b4N7LpDJuh_?gdPS+u+hS+{LRy7*uShz z?X`cp&Q|e?%U$6m^P0dwq>)d&T*P(LUU#car8{C%EZ0)cRMR~VR1#QGLfI?6a!H5S zc-HZN^GhMLXr52PKf zZU6|@EE>rap^}Y(Ko#!2i_wKOy_x2VC?U(RzoV<$C`R7l`OSGzrt6Xyl*69ne3vUQGaAq6foq7)uZ5g*-B5(xcK6YCP%lSmm02S1yOuOwleb~I!gFW8xcsm(6SB2q~iF%l2hT#5@{nzI3v_+@t-7_v({Q$si)sVj_ zn1&kU&=K&PB?TB|&`h(K6#Ooc9FM~uS z6l0Dy3J~C?tF5FSvo62R>H`!l?=CF)3nGbDb+7hq?ul)Vw}`lVyvJtKT0f1Z8wBFtUL8cy}Vm(yGTsW?KWVq@1%-G#p%=?$S0{c~J>gmi62~ z&tBZ)e%`uN%W$nIou2K|n9bQ}yS-fC5NeND+-i4+F@Ke*iIv+ndRnHaPE~hBgj#!B z$AwP{M^qUU@wR8$y_uzMup#$6)*uuTsaUn>;1zG#>7OmBD!C=r zM7{B-paNe#X6bSZz?yvgqf{A=oLRq?@a#Zm2Fd4nYX>UAKLvNnCFpw3B_CZF%Y5wB zQ)jhRnU|6+~trbPd>xeEG_rXDf;qONRf^?U{wCnObW+#m@+@)1{utV9DE;R?MH@`Gm>!w)g=1KiYXGCb!Hz%J5#^62f z1HaeJc41e$?cC1QB1???CF}g%9*LI3SD@xNdv>kWw8}5e%j$Wx%|-lw#2<{HARt(yE#kciQB%ba<>j#03BaF_sCh{SVMlvxh0W~|&|(p&Z{NMMP+ zG$Y*+k^|3Y=!Ocvg!;K-1j^bkO>4@=$x4mCHnyg#H(W?Af{0pW4lApFo%7914ht+8 zNA7oQ8YE`AkE1)NF5%F)c_=NN?aeA`YD-38uz1`I=i^xv*?{6|)KZMNzw{&8YcyBdqi2g{0?C?t z$FY&N?({V&`>X;#{-h(le+M2=0t=K-JXTB$TWdasRyl9hb(I8OXSyGsBl6k?0XoJQ zPLSf2_AUx#J&CbrN59J!Ielk)&n}Zol)$HqxPolW&&r%4-yGe)V(g9z(s?ko5U|OE zYk*#3BpL0CwA@3<29nyUjSQ&m`l|D;vvl^t3G4G_KFhX^?Au4|xFa?N6q;uy?-M3t(I1{QB4ZB0kh@KYy0&VKZ%e|!eq1u%66aFnbEY{KSpzTR%K!b+`zv*O z$0~D?Rz|?uU0*-8@2CHV?#+MYoK1rnC-xt_lP92Nai!RCFVstUcol7mz$jGC$1klFz1F+^OvOWre@O=Ie5{kA5==sWK>gPM7gyh)3s zSZYg%!&TeNZFOy9mYwTA{_WTQ1kxHPCrVM4yToG~bVN|Rh&mx_nw4o-t}`bXn=%%I zG3CpN#Qch9Eq^XrcCIy$4(#4Skq#6uNPr)c;sOoil}_v31lc=B=`240- zoXL{vmxrhf+UJ!r9%B`^OLY?MYWH492PsSzD2j8WXWSL5I^*WW=R;4zu*v>Ttc&%R zm$pFzo86MdyoyWgeQ{OnfRF6eMp@3W&AOHom1eu2lAqX)BMomj1psK&)#Ho09hr|@ zc`psBO>=9T+e=v4rZ%<^{@m=jqCVsryps*a&H@^L6!il`Yq$xZIul~xGt`Q>PN?HSnW~idQ27bk%hsk>h zCTLSackA*}G*Fn?2@C;_Rb{U*^4^}`MRVK&X1 zZ1RaPZFJ|_>e43_{MXYzCRTa{Vk=WMh?bq71pdq&mqaz3r0C`B&Cjq;U?6~8`w3b= zX!A&Frxa&r*?lgy*CLC#2GwvqDE!vYV9|26tK^rtUK|wW2{LA_K<@Ed4(o4IB54)g@4u`<3H9C=ZqAPu`aHSgmYG_cms}Hu;dTktXQMe44bKKbC3DdH&^%6 zh!q&k+MA8vgXj7rw$jGeN^`$oeD0M&QbXMLx{jh86&I9*&gIeSXwzXrZcU24hFuGS zzaHj&UTN(j_jR?=y~K)2J>LN}o-l^!>_*@2uJU4}S$pqaRYq+-8JG~(&S{${IxI~X z_wfni$}6H3`s3Vr&N69d^){7j!E5@G2e?PCBsvTG`quJi5>p|f=6m}}eCk`rTmx!r z)cD%MO7gf{^WA+h=#jSnm?|oVb0wW^lIzuG>S(G0e(iK*FnaZaHH(_!R2$H4bSYhp zMF?yXhQbE5X*T58MqZ?6tPX#jpu||z1g-URatxaA1I+QXKoTNfw_|nSwr+!SrL<5< zhR|MXGe!KLmm1rR$=J3`6k_d92?pC~k}~!Jrq{ojwIt66wDH zt}a;ZwAFuOvdQ`T$gE%QHK-E^YqHDpbTqEW+uL$ITKGwaPrh>cV|v~Y?R7Hg9$x!0 z2Tvs8%RmUKiRAT@il`Nvou72S@0>;p>sxy3Cpx6Y`xs0eFN8~rfjbTt`d15HBf&&A z%j)B*MS1;LY&4;ovGpLPI(g|4uiV|d|EaPV5w!(KE+5kgD zy=2PzzB#F9!+R(D0PQP6R$8DQf39v}IWCXz2jy~KVnZcDCHEHxKB!r~RTb6jy!nps8A<;e6;zv^ zpS`BC2*&Sh**{I7+-Y8|aTRx&#B63n+)MQISgz?5H#a~*~gnrP;tH{fPLLd59hSi_=xUt~W<#ksFN zQo$O~frI8r-YOZ*{}y;Y>UXpykIC)AIA=y=Wv-N+Vx5tivF)vRApueMBgA?r?*PEk z1O;@4g@cdrz=#wj4OOFB*DuD`#&wO3`>&-;bG{Upt%hcNFuw zg76TI09$X(wvt+lr$mw5yL>J;-iDz4Pb2!VuFzYT z>jhtj{TAK=RMX@!A7;zvFs()!H_eA7Y^8BPR@GCDKQ~AH0|S?_8C}u?`gl{aM=&7j z25I`CpKtwAEa%4|&q4*vc!wXnJ7r$SekOO-p(2HNuK)mg{6ep z*4~~S6fwe!Pe-)Z&OW05`|Dt}gup3@WxvzuP0Jy`p>w882A;`$<05~c(6jMY#8d~N z+WOpSNOR*H17H~xs0q6-@wA)JUXOOOCBs@m9&nCmt!L5+&mPdW_jboS(EjJqIatQ< zgEP-K(oH2r@oC|hiKnJLp6ULW`s-1>HRR;!zLr{aL2#o!Xl%UBdIwmStt8a7*8Cq> z6H-_Tf8MQ&t)KO%(6J?*1#mY}}vgw#Qa^>Gw?>VGKPO zq&im8F)VYBHX?1xE(;8<xOG9PFOR0W-m(m|I z`pId^pi;5E{*s|SUY6*MX!dkmx}DvyfH@qSB?&2TLrbx z#WZc}v$R5w+qObcFZ)xkXUeQl=cPt?^(xbegJ(;N-zaEhBR9cltIIXR$XCFr-_%|wNlmIrrxO53-QrQJAL|Q&?I`Okk3w$DEEP% z627-Q6{;vy903u&8$K9n&8&Lg(#=JhX)O6hR`vs1Yja z6&MD8FWfzS^4LAFm&c`-*M*n^pe%5GQAz$`Y3foGd$X?;_i7?<6yktjeDR->BT-gw z($GQL$Q@O;R%@S6=GYniI^Bhuia~K#{GJ+<)yjnkQ(JTIgEDTiiDDGhNzY2?`~3L9 z*ufD$4v6)5NNuN{<%4ex?HsTc?qpsqA5P1f2`(n?b`RY7LMJWD$Jw!@|GKkbY@)32 z6NN8c34C4RYBY)RQXDKF@|YM129ahTd~}^>>m?0iIj04JIo2pXBsjYPS3LuC{I2$b zOUi+qIyGwL8H5~mAevk}<3inhoK}cdncgwQO$C0%xTp7;V0l1|ti7v8Tm}kO6%=XU zdX0Tw+j?G-PWO!z?0nXa5R6y8~#dA19K=b?R1Y^ zW4L3_7{Iu6%8~E>&B;E!&DG63WBMtQ)B+y)Nn&e3<=2F_h+A6x$h{He0w$W z))&Y&ab)_8@F)x^Fy^zmX2~k3&sv<#u~M3(6Vy1XBwg?%L#f#FGl82Eo`DJzdE6cL zxmK~!?i(W^F=G06Ls?I4;465#lzXlr1Dt{FWeHJnZjR!V(3*XE32WcL*`me67<9CG zg9z-)k)YXqg+sMmzPJv{S7-{)B>Uqb-f)@&B?rE`b>6#se#-7we}K?aIcHB)GwPV= znJBT!C*w-W0hy#0M_=UWvgoF7uG zI?8fhCieRGl$SXHA}Kibb-ys)C`$%`#|A0UbKU2O^tFL_qT0P2lEu3%_Gznof>w-F zR{jjum)CQQ9Xq3mE)|td>05T$y)ErPm6`eW-%~ukzpNLj7?)yw>rJ{g}` z)jhvY_3 z^eBBG+Idr$@~~~;_6OYq{ZNly6R`Zqryyr7DtzlTMa-^q`v8>cv@nY~jcj4~Fj~v* zQzxq6k}akqc|SK<(!LOP{?|w{`%4w08t!+~D&$NxmL8xZ% zf`0MPbD*ZLV|ShXtoK0vFPa4Lg;@pd&Tb$bQJ0LrWjWq72;dY6`buEN?+-tc1K z$DvaMw=Z}gxN~+|F(bcz$}oGl_NyCT6S{sMf!>;T*Z<4ZSa)jIXv3U8WTAH@`_IED z(1f@R(JSaqE|)wHXLjebo%tYcye?8r0|j4}0la$G+~}w~zf~oHk`)>9mNnKWejOXs;~0$YmOHO+W;XYGpQ)E{6|f~9lA%5-KVfpuh(1Fc6Db` z@p5d_+Ric9*kF}>rqD}Vb@!~WK)`GFUXdg*St}wfD5JaF{A2d z!dcTJuH<)v_EcSO!DC{${L(u;+~d+*R!WI# zu8d{Tj$os%A=XhNU?M8+ej>*Y2)57O50_956$ZHbsiTA*=O8|$B)}9{PcbwwN2a$V zFMOH?)pI{WT>VOdi3Twgf#L-Whq!wM~web^aWj0RJ3 zC-7X3Bjx#TTtQNb07k9z#~8I(BY8&n3iw26V^E|#)BM({ZRnJ41XG^l*Rs>}OHLBf zHh{$KFOWehB-jo~MZ9c7U#>{1ig0cF2mIq<-9OsDTvUN-zwkIghK{3eSuk_#$t$KP zzQn8g`bn-U&%J0FgfN)6WzO!nis&rl*=XENNN&p@lt_5Zq$PPpRVX)qbM{!+|8AMB zHr4*bf^{+bbA^&Kb(D%!g})3IAV;A+#ll7dX{{6^E?Au8sA#UHQ8!PFJ5<08)d^^319b&ee0e3x%h zi&=C5g0hbO<~D4Eg6Zq0nlht!a(u!<~oI%-`75(fLyaaCO0vuF|t| z*Lz+9x0#o+tCuaIEmH*E-HF^8)SslzDw+r>zWchX-w17`-u^bLo+=(|Vb_*4bn2J3 zAeQ0>+iG$u9xbaDxzc$tDeqZpDw8-V*eeOxx0GkszQ?-nZi-| zmj#%QJ$$B55;1Q%;^OD#f`5#li`|dJq(dk4jQiRtSP#|W>;;>Y<&5$9w(OHa1uOj@ z@@ktl*vpyJvhC=e0%+&)^)>yxBzi$c!hs@{juBPw z>6#0cb9;B*&&g0w&Xy;mFuCoTCQ{<1bQnP|Tz}0|&Y6Ra%|+(!^pN?mL7W3_lG z#%bkv%=&S*sf^qAR~V{?)j&Ac{k`qts6}v8wOodF2H;hxUz4A))1cpk`(~Eg_GAhM zEC)=oUzO}CelkQoVk|IK3#94{6qHFUuZ~=5gm^3{M5sihk8Y^dfn+I`{NcP{L*yt{ zuSRq<9`~Ycq0&8AOC~snpfWtCAQ;e-(ZsE z5%bHAVkwqS?qR;ZwAEq!#Ym-Xt7#4-0zu3}rR9Rt4@F@jzw4u(+Vloq&cEKRJrA95 z3UdM0$wiS{uv87b@199z^e#Y4CX%K3ioYL6?R^Gb5_=*BxJkv;eXO<;*J18xh*JN> zT=;-wbh1KsOZUHf9;2hXJ@K?&UgGc7gCO(|@$b-wrT$C;u7&ic8Eh%`elg|}WS6|Y zh2TTZ&cdlDbI^irnnhVZ^IwayA(c~pL4xAQR5^iUaWuQO%)3bCHbJ~z?7~g6&V=KY z&bwKH?KIwXUbU4~L-uJ_#k$b&-h2P{_us-3H(xf?-(r&MNXtD8^?5co@*{VHqu*yc z%%NKrB|QwjfeI)82-uyG0Ehq-$NtBeO!}q$mSgnXyuZJfu=IoLzbfrrg+xgA1rmIo zn3U>@qop)CE|jQR+Tv}#mcb!U``yRV5=V3Oi*j^}I(bjbrKl#H+DgGNHbvYEcMzok zlTbHLvHSJA(!L8W1vij-<$^~~p{j+V&mOrsA!)wcqN$iD>Ksg|K)B3HS)k$j^skti zXk~F7+nRf~o0*(K72w>e&B~kUcnNZL_byE9HLkzPJwQK@&_wr?PSg(RHK`Ufr>^Rs zm6X%U7v&$ai^_vD#6D5uwwqmJWe#50aYqF&qf;#|>@vvzj8aFqA z(|FZIfL@Q%0u_J93`R{LSLP)IcCU45cvnEL&43MhcY#(XOVsFTj^y`wq#J2Jp78be z{!FD5muyD;-&Z08tU4QM4w}2OU#$hSOzObSU&na~uwR?+ z3(!^8dUXo+kJs`ro?cjr2z>GnIY;@*6B9xSwT1~}UMA7F?uq6`rKe@?tY^9Uv!w4e zHdVUUR#DsuUsxkc^pSfmMM2$Bk0g{d(mcf$dM|pPD=jFU$oiG$rxV}Nxvhwo-E+>> zzhYr+=U=yU!VJ~l)wx0P^qvvbhKGyBk%U+qEn7+=kHltIMIBixEs4+jb#vmUP1CQ!hmr?V)?0aYoBw-6=Ni3ouDSuj)XzaB%LQZ3tNF<3iMk;U5nPgLB@1C@@R%+ zzTf=SK8=;*>w9mW@am}b+A0E==yjjA_k7!-9+k=~-PeKW$sE zd=i7}65KZUhr`h(pg3B~=SWs@{566j-%Y?{akQgi(f^nH{ysrb1Mi9R;7s?HCuyd z$g;FzrYTiB1>@j9eeo(b%Bv~#4kRG#lQiCsY)j_K>OKQrZ(Z0fbfDGjfhe25!InM!js&^V#~WTs4_T5%ljrp8t1t zoBthyei#hjo82h*p@J#%8pQC9%`>F9EV@z=Z_lshBrqkTgcv4< zG=b}EBY0*R4&r(3o_a&^?k}T%Z3`xW{fb%sHu?yuHvLj%8;2tgg6-L_9PQ($zN+$T zq5JWdyG3-R*LFez1V6j?z231}9*Gx;SZvIwr-F?Z{S`uUtqOnKS$H=eXuh$YoTI(M zCdGYu!~p)m7hyqf-zt*!tu?u}$f(P+>7vdXaxX9m!$~vhM*Ym+{^_@R}J?P6?ZpFc}7a_xn>9=>XIcLAUqglYa zUOyPX#xzTQ*<1LOI&P>|+5Eh|FM7U#Fa8a8<*L=nHD$#??6=~E+e~iK z9qxHSc_SOeWZwd)&ttMhcBdhGAxCx3Y>yG zUmVf)`Ra#fDtvA{W9$Bp@;34!%A0g2H(?2s9@*ge5%X<9kUtt#7QB0iOP*``&BCN< z7xH#jDrd4OeIeEnspXio2<=0M+ArID41}=Z0x>kq7N#@N1RtCvPx~Gko(b9rEJ$?+ zsqUtP*=c1trQfZ#sHct=Wq2ZtRvKveJ3b}uT9!a_`!$P**~RDEnWcX2Yr;Gj0U$DI zkq5_AY*+Zrr%G6FFyKka%!vDUZY9H7@5YButag z*5vqMjW0tst*E{7xukURaxk-68{Q>r7SiejvqS`Ch5G7hv-(Y0V%7>#^~;J%S#ERn z*yN@`-yE83I#Wjjs;pIlT8xT!E%z0)hRT@WaDoYakMP*FQIMe|Ye;0Cx`e)D zwMh~bxsr!8Ba3UE&FU{#8F(h^QqrtA%wbO^QRU8v^jC5(KY2DDpDy&Jlah8oidJjf zh8npFRd_%3(4guzj+M~N2lQvnQkL=rUxQAXg$9(87e@ELrj7mRiE9o`F>M|2#HQnk zoAM^1-Rvf8+=g_`Odwy`84Le|OUZ*5cj<+Uw6cl5UEC+fP1&e_g!y*$Cd(7{ZjqM; zuqf}IBNWlVDs`0C9-O$3b+|yPb*8|rgub?7y0@XdYqu`M;g$F7aGJYrh6MzYEcAvK z6AQP#G4zgEH_|)lh#R7->wFz|k`&M|&s+wsf@cW_7T6l=en4-!CTIdoEt#j-c^Qu= z9#6FBvSYhGMCv1mjvF~marh@)G2HoH4krV+i6$FLqR0Rpdn6OeF4OC`dJqW#`pYEO zEj=e$i|G_&4%;NvYms4j^ycWKO+w5i8 zDO)aSXRxJk5g=Hw165}M3Fc&^p75UikYbf4SYhX~Y^vDd%d9*`JS-UukePQtA9(&; z1r5|R9@h0TQoS#`blML%yeHz?AoKtq6AS9*>gHZ1&F5vxgi7#9;k~|;_yy|JLFIVw z;z`Qe>eSn%_Op4MKv+>TP^5a-ES=z_@V+u`Xn7~&9sV)NCM8MPOqrldsMDyTYcnB| zbbQaT%Jy(p>W}QwgNjL*9wFaY+CkvbzDu$KS%&Bv3SE0X<|LW~MFcM6K4VTUyHlVm zxa>CD`d5PM|N(uFMWS-$&IdkVNODce_-jgv=u z*;Zyc@mqD+yCR5M$8%+dDj*F(qYJQF(+>q`@8c#zy(G^alF+hytO8_;J0R&FS+i#}FwN%haNs-y1c-dU~$v77&}FM}K#P8wsR-ye|B8CO>yE>dr7d}F+LZiDHV0GY)8}{dmL~6p@MWVmIM>B<3rfJ zt{N$>1r?J5h?+O;ZZ(ZJO~cq{Z~Dq5x1st1nt=`?+pE(&LHyx&@9iO0`v3ha`rCiU zBh&xYZ|M9eJ&KSRA35}6)>e=uCtG9JFrBpz)R=ftR37QyGf#t(b#(fD6FqoxxaH10 zi#gV}jgRTO3_Ic#0{r_Q6%||RADec#4|5TGR>WpuTy!&t9!?VTq%5QtnT8Ph4EHLAmU3kEgygS8`|aq#MH!H zW=Zb{&#qrBiAAl5y^w)U2(@uyzfGIj0< zk_q?W9FwUViVSpf3*jIOYnGCQiq=?KSzo}eehx18@SA}l@(SGLHWePYUOeB(9N@7f)aG} zCKe_JtLFM?m+$|%SpP#_f9(sh;(k@KrtZ$OfdaY2f`vjQoi@9sZ4LyAUVRTReod4~ zMFRlUeo3s4yYvatalJN#2M{+QqHW>~<)6hZ+V`C^b7#5bN}`14J`&c*8#PE*Fuy`By z?fH$_=n58MS+T3sM0RQM9D$!_&q7@4*YJ>HmVM&aXLeYoEruJegr^1>{;i>p3A1G4 zY{E2+A0XjW{V?!aw^fkP%dAuXoVQcF=Nvu)4>AMFnC0UAQ|_}o5L*TI5Q1nBVr$=g zj%pgNgELXIf4jK@ zgS(yRG4N&x5gYI$1Qqo)kWXP+lbDcqZq&fSueS}3y0bE&Z@0X&q+JzHukWw$FnJJP zXW~?uFxTYX=O7r&T@QbT!8vNAyx`jv4)T0_2tDGQhVVbfn{DM-;y9;w(tT7vq85Mk zFDp39cn0@fl@SHj^xu%`O)VlNr%b)v#7{lVqg+TS938GArGI7a)fBGf>Te!9l5M`V ziZ(ef%eRp+cMS%_r_pZ{J;yzs;`O}%R^P}3E{+;-8`Bu1n&P_^+UcYb3wJ9L)xQVU zX)2+HiDGcm{LzD>pvKWVGqD6aGU;5n&I|SgGcN~+r2XadeJWC< z5z0iPL-}CyP*N~}W*n~e(&3=fztGU(ae=KbK^THQ0L9{evsAn${hV>!0Ub#3lq|?4 zXmU*J5SYPv>>7Fz$8|ZUvTj}SQc0X!oN|DDOo3-Yw-gdal*XNu2|wS+MN<{}H~^1? z2-cn9&)_q598R}<&y`%blbU=ZkD*9KnOsss(%Zx=hNRB-lrt@yGke1nf`?ni=*0ecO} zNNPgI-mgnym76X;n!2lN38^$-$Qoc8$X2RZOjKchY229XR#xDW2a8Lv=iN?~QYEoH zDP1?~qN(6Ayt$>Wsdx`;Ei2d5Q1>2c3mR2j9A5ETSqme4T+$?7Z|z4H6s$~~V&mfL zH2^95uY>)-4hjlJTlX42`{w560^}q0Oh8jn|AuS3jjrH6`hJ$$~asyOuyl@!|wGy-99f}>Bhush0 zsob)FSq-^lm(Pf8=P_{^bnN`-wCjLE33fYosfSjfbh%qmy%R(vIsY15d7zPwBy5)n zELui4rpVC(iZf4y6CTBfv-+j(*J#nnXpXHNDs4(oz z)lO9@bj_lygS8~8Syv9l9w=OQzQZWFakj)+N+0q?yISx=P618Aft_l(}tOYNdWgeL)L@PJ(4!YRP*ya**WB*LU$Q zQ%tB8a7LDm^G6J!zh=|N>xflUWZ=bW`QF`n=N!XD2J&6!1Ngq;Yz?HI5K`W)?dNxJ6u&7IFjd0U*jEuX{BoGNjtVyxW2Q*^ zBKoa!FjFfwZ4~9<^Fzp3sr{HAJXiMayOxulePFFY8ZHd z9{jFEO31_6{V;c5rWtpVCIadHTBkW|d-*p@FjJ)_ngutRYcs?=xe0Q*B5p9!M(|9wfnoULP|M2>ySnGZE z>bDh7DSqwwCG^%BG+jggfl9C!K0(qZ4uxs|e7DZ+eBZUQN1m-iQF01smFuh04pIHH z#GOzZ?mVX=YYwXr+fbJbaPSHJ&e!d<8|rDa+Y%pOzgb?0!|3lwmrq;h4J%1i!4Kww z=V=$Y`h`48q3632#Y`zLKltoA=T#Z0vD(TBW$nbTPkG0y^snrgxz!U992SjEG)ue1 zIw!EPFa0gfVsR}ovaKM_)$xUwJeRt%y~W8IC|rkMXDsuY*iu!UCj$eVvip_b85|~V zvlJ&88L?6N6O+BOPqTQvjdyt~oa=|ParLJ+z*3jC7m`n`CdU-4_(_5OB@caF&gFR~ z!sITLY|?XHjW=&UvL;Wwo`ooQ+y&_t`4s`+d$32o#LS3g#gFuhi%JIARm71Hdh6Hm zrC6%a=PNOh_du!yulRH^ZLwCtF)Mv(L4eNXf+xfWq6D;y&2^QJ8a7ag}Jt z($@uT6+*98tPp+-AU7Qej)$q=CqcZgDQ3RaR<_C=ZGO^b6g&n$NDi>j0;wx)uE6a! zvR7-mCcWd6%fx0#eikWutK0ti4pM613yJfm+D=XsLJ^azg`gpQ+O?=FTy2ZBMB%fU4(E37#dZ?>nY7oc7 zgRxyJ^C_@~R@1p%u3H+1mG=YUFNDx4#~Pi}xC3g^+M8&$@SV;KI~+2GLCNrU)UzAs zE}q2i1xo*t|IGs3_{}1nULV>O=PqA7P{eBNtnu$T7MA}kU!vJQm3C?hE!%a1!R|h* zl+mVeJ>Ph|8%k;x@xC7&P8B-PDIRx~iqk)K!QUwa&m;iBn}?lZ>%A0skR0`1NX(2J zT1dJb1UAw5Cz5q)l}+dd%1?G{^4L?7sY290k(jH1^9G2g*#w~5mNeXy+j9c&3S&Fx zlpez!E%GgdpjU=wknv&94IYG``lic4cRmmjMxSdr=B{#yYGkeMpqh+E8k)LX{r6@V z*N~PX32$y@fK#>HJWwRAnX%zBAr|~;F=ahpH<&O9drR)>l_R#yeJOYR#{-LSbZ3`w zA{1u!KGN`NVa$2vljH=iP`F~4>r0okca#iwxPO00tPVhi&_8TAUu}qY^;SZthES7m z^0`$jC({o3?pC!I`320LrU?sHSkKP9J$^gOpI*nznQk8HD04WL+6HX47^kmkZHMY^ zJxj~n&aqj%Qw{aLN3$TW--h&r@-spc7i|yT=i8?VjD_fbydB~n0PJY90)$26e@HPd zqlMRO@9)=ikRnO@ayQH7^oO!Ay}vv>f{$`Q*Rq9j+ z>Vjw*lV*K?ut_#nEaKW7!oMyba6M9aJc}`{C=dB@;U&X=FF35Bqs7$ak|&q&A^ROX z>nAIfL^%J2#QOR!i$LosCJ5LB0O6(&#C0n7DHBv8)kEn5z|f%%%m| zMJuBiMc*qP=w9u!*juql-!iasA-49veCaXtTz)4>{a(s1i<&4y`o8COx|%FSOjegf zG>M--ZZ5y*d@?(r@BQxelPIAf%ntu$uco=rRUgJyoB%YkUA3u zG66W&;FkrV@r#6vk6Fz(V4bO|JqK|#5~WCBqWQyxdxiNqbLPhv;p%GHIMesI9=nDd zgv5I4(+E4NeCbBcH`K44QX0R@-eKnHN}OE4wSKiCjmgWe6#mKl_Dv&ShR5Tx0j1}7 z@wm0_Az_5X*0s;6k+WdpzMAS`RxtK|4me-digUe+#8GtHz*{1^frW0 z%h(!;zGcz1nDH&fUB!tMSND}om#tB?bPJu%KF|2yEJ;4Eng4xnOks23p;lita^2*> z=i1;^j_&f0M{ywcg480Z2E?s~rtKNuqOjTl<+eLNc$4fnsv1*hD>lC#5x=C&nYStl z>!c=hILRnIaJ6!n94c8cEJtc&8yFmq*DaF8h5*wAY#pn(cI|I%+0dfaxP@x+T%8p7 zBx(7eSGsnS%(peOoBWhjR9x9JU+5F@2@99>|C~`b)vPplLS-8%>NPCth?Xn*o2V9c z7H&G}WAg|#7UDlr>P`%Oj?8H)^5NyPA=F~3yen&KeKQ` z7XU-HE)Ke$I@5k@41 zUv7%C?z|mFcVmVNFCJ-k*h9K5in^(nfy`2F%}I=2^>Wf^GkdGfv9t{+BQQ;D|D(`N z>i9FF|NB3t+yCDif`uWxD=hkB1`JYMw9FyEkduGxK0(5aOBnRMZ*~H}pA6yOEEzPA zq0ny@qaC$~G|Q?;oOGu>n3}`!AfmCmq1WIWbp`jgoJ7mvCA(q&L?&!(l2XT=psFC# zuO3TR;#}C!jD;jQB_@W=bm?zE$xoe#UYc!KMScZz5Ljf`^UNI?X^vSyx!d=(z5dA# zhxDHK`1p4%;>?-!`eBUG+6n5EI07k?Hh3)Xr=$Oq=hy@Mmbl3F{{Q`S|HmA`{>4&s-iKbUn56_f=$+|swcKrg?1k)zZ?~V@ zeHlBO`3P2#gf+Z^`Nq&K5|!@&skMaW&c6(0eIFDO=O|RS>MmC$MHU}a$3o#*?!YO9{_J4-_v{ zj&$x@52^s!x!42u;?ixenp%h#1RZ=>&5}2i1%ub6^OIs%7`R_Wxo0tp=6HsUk@;asn~u#j{SMoH#7gTW6U*1o*+S+tHw=?pq_;Fr z(d99_=vzu2ZeN}n62N1kAGyNpb8loZ2z8xs6Oy9C-v_ae4_JNcOf23K{>HWSJ$m+s zv(h%sU~MjBxlkNU-Mg=MrlzdlePj8y&{3+^9bIWy)yIj!q7Dq@e4#cr@qWWHc(luR zQ(WMvPEF7ef2pm>jEO_65U*xliz{k|iC5%L;9Qx8_NZo4ajOEPu@%Tze`H23uao&=oQWk3Sk_0PJrHI430)DX3$OGt=I1 zmVy5?C70P0spl2GZf9GFWl*?n%w&dS#4dp80yi8{X8gL2UEe!m=gu3ZQJ2mZ@5t;v zAxNF&@4elNGh?yPpyGuoaZiY_zAZDYW|4Zsm5SF*kL)q3f1A_irWR0@)3np|I=^@4 z0#U`64uPj8w?~iRmBRd_xrl{GPpI0Ed64v*O=Y^T=DrCvSx>d_D- z>2Kg;P4HvL#R|7(qYI&VL+fse;s2;#ojY|y>~bI~%K~f60eG2QXa22)FIHAGrR4+^ z!{q;|Cdq~MzpnH9W9%ABzsJ(8uC$X0i*3vV_Y66)=wU+M0t?4q2{u<6$rx#$tz$PK zL7|G%m?pEPoqffHe5-45pEgpoa4Y)PaVIz!ER><~-hY5?6_IN@>d zeSA^cL4uY;pIe#`S-|y?Z|QrX+(QY;<8Ua&y2_g`+zBg<3U!$(*#o5ZiyIu^tI1F_ z7PQt+1Ii?LhyBzv{bHyc8fZQ+b-4(PG-pd_mvQ^UyQr|ao(kqZr zyL1UJJSm3+2h;PNa#WM;Bzmj>?ib7Q|7EfL`CmOXo!WBxirr;RB|zhjjJgVsz z)o}75e%O-bivFJ&4i@|>&DNVoD+-xC=AVnm_B6;d)do+UdtAxwG&beLZU-sHi0s4Q z^XuQH95TbTNo`JQ!vYdO8HPR1(J0?>II$@&V}f7hplp7wXlxB*ETxtzYNhT1J;#)L zSTOkaJ|?vcDBja4Iv1==IXCM+Fv>-ayxoMad*>~#i@7LOPpuP=7^f_%zBP63o4R-Z zv|}z2()>B*wpX+Fg~?LEZ3)f##J$hXS0)Ok+^CN1?nMeM4ANT=IFJtCltb!-3iXD) zb9+OHe3`I%*WZO1MLEv&qyEiusOJD07xq!+zf6DEym}OLH+PKQGxM88Ox2-&kf<&P zHo0dUC4zg>tdCn>7HPLC%>&yG6d?~|Oi{M!W@~gp7~y~~kS<;K!KvE+pG$WMEipEn$&=Z^~ znBK>HJ3axtccGEz$H!V7*7|0Kx}tuwASE2Fi`NMUAINQNx57N21&RmACQ6FO}b zehMk|K)x2NHca`g!?(5VWnmGUQ|Rd>hbaDGYN#Y1ri)C?R4k-C-{-wjC>s(Vgjx)W zD49Vrw)Rq3jh|;KzUVf5TcOPkTt{+7h`)(5@5|l6f-Rbwf7B)tkOoI`zbG&S3)|K( zpgwny;09~f)?allbKEF9GU6`+#oB$o26@ZS_=tmshoG@Ei>^1AKA`N+5&2=Bq5U=8 zi`+!K_yoK>J+6Ls2#t}rFcgcl9YCvh8DD+{pwo0J5?t_9n@~X*cX$& z{!7kt;ts+k?#KkQfoY-Owc`S8Z%j&0|6=2d1ZS+B403^+W#(-&vf!{`Fx?G}ag@;@WtAu4Sa2Zrp2@7ysk(qH7+1 zYR=UF0#=hByW3@8C=1WXI!MN(>>^Y9QJ9pWwf=TUtL5vOy~Kr(qVu~O_Mz|g*b^9# zjRK4JQMZa#AUH^#%$^L1XvG->$-Utte=_SNBW%xI;w{WAcA*Jl7s|$#_uk7Wx%3{7 z)jc!`iS!aq>sl76)ADMw%D_XAPKcq2b+y1v%E-X(4f^mIixm4RBmQHNcUiY)JPKSx zGrr;%KV zvNhV)RWh1*T7GxBq}y`wqm2830)oR?a@Y+u%85awt!c{wJQDzT1?~WyfsKBqlS+ZV zYT2l0jAlpXj_095z{_~YqrNIXbgy|s-|NO2RBQLu(a7Wv`~Zu!FgL-oPbd_wV5s@= z{NrY5#X`>krcu=bIiGmO?2+o}RC$O~L?9v$CcYw*PB_z3(P#6aux%f=4{3xHdN)O{ z?TNtf;cVy6>cQ43oNhs`rXz2e>y0X_FXV)atNxWreJVwX^Jg2Q<75oa^{pD$uK0Ed zCP&>#t$6=x^Pp23WR?(`s2LFxPxqXevfdMrBD$DbYj|ObN?IF#NqgD|KzJb{2Ip1s zMuxfg58|^}#XVGy0+*N`CkfGA=1EJm`JH4hj`)n>kjD9lO~MwvABOnMbb0bR)_>h_ ze+Rc91p%qSe=Rh}JE4@hFib;LxaT*sxAS&uE)Mw5D67i4y1f^o2+5YFlqH~b?TI+& zi{8zHwSY?p#$V<&8iWp#rRoKPMuwiYdLW#(xFn5W!0Sl|KH?vML4KW{L0NY5rlOjbODU2+SS5;cdO%PLCHPc#DHTxfv`gv^1J28J;TLweIO{ETg^0*@)p*Y5pf=6GDO_`Lh7}hG`oU zsGOB8VfGa`_b{aaDQD&z=X5i4J9)75B*+*XcpULft2!Qn2n?fktLO%8^Z^6MOtOIJ zaU5EyG+f?}UI^Eh#P{ZTVHj_krKip%%k-6+RFHDAdN@1TQ5>e2*NO|Vny${1s7 zEe?zR1#MNXWF-wQ%vxmq_?NDTc#cbUv2`6MvA?`pbg$l=5*@E&^S*pleq+-MToC>@ ze-FAuSKRe0%wTU+I7xM)OvZ&Ffwg!_bu2IMk|lGs->P%A5Wp4FP$I1YT)SG3?4 z7mF8ZlKaH)-r%CXDd2`>Rk9t~0;SxW`l08}Ql*105KpPUoXlG|x(z!%-wq*MeiVJtcm_UTets9t5ifNL*X;|RUTt4QWgWme%V43@sE!2Tsd#6$-Rcc?z%fmt3aZmho$!M;Q*ihR^Gv0a`Dblw(4fGnE)B5u;k;hq&Hh zt+HckCA{ij!b>HZtqJkCUbL={Lp7ye@VA<;Y+9P29VQv7y0z;^p@$tmEA~6g>8?eX z;m7@lrAuZu4*~jDREevJ1cT`yI!_o` z8T_8!9E~Y?>KXdi7C=4$CXKU@ zQwya5_szJ{;aFFRIoGc=`Vw{4@q~|?m6yJ13Cz^ca0el5`#kFxYOmCSY(xtKoJ1Oi zTeSs;lf{ZIxS`aBJ%kIaUxY7|`Ee)kr@pWAJ>)rnfO^rhm>>3Icdx%o3cbZ$lh_P8 zz0K6+xhilDrS)SKlr)C9IA8aW=f%6GWrgwAB-MGRnA}X0inPuH#mBRTrVgh1NtP38 z=u1ESkIbEnf3x_cxn_{BuF13&_yYTU%1tt|=ewke%-zKoxy&MFe%XW5GP(hW7|uN| zzbu!2j5f#D7_1I_W_0MQhfu-uq!55S=PrM(n)xjWEJwp>DyLk2jQ^?q%ea1hfj9bSX8}}%#nIXA2Q-`Yp((W9S0ZY3IQ-^C-Idh}ko-F@#{+I75 zo*Pn=#^-L7%X1&K(gNLEHLM%Jte*YgT?NnZjJFr|h z<%5~bB_jYwo2VWyFD(GxuK{rSvxNt4jcq`~v^|{fqUL{wtU=WR#5HA&^OOH-=~(&J zE*kS?)@^&1d7FboX2!|S5_AcClP+@7@Hq4QuZXjG%%%M&mKe{&6H@8$wgO{7GDPm& zgweQzXVc22^vCD{NG_aO^`>AWXeP1pWk|i^XEp=b%)a$g5!oY~_f(PSS@zbWJ&|Y(cW^Kc9m*bbgqPAiU^7=vNL{qO5y&WmF=mStbyYqp)f!wSPKLWVfky5 zuODP$68?``X}8e-?v1}z1bOC&K#wG|H8W}lhulSB_ORVQq@HtJ_z=QwPfq+3%U@ug zEF#k-ljW2kj$19bbpB8eVL>Qq%X*ii_~h~@@^a&E77xLLR_2GiV`ZSpoST9V5(i^X z1~hlxGs@h>0VU+F_y51|g?i$NfgU56U5T?_SXc!3r9JKW7=*B$UrLr^wTdg?!w;v1 zG^8?O8;I;-w*PxSM(gl9%l^a!a1Eppf>I9*Uv*;66)Xy;rh#QpiCOdgT-3F|q!4P? z&ihk0)$l9fL-0RMCmZovMCmm-)V2P#B48s8wdY|F!)UX6i%#wvi`Qf6;QN=K(kaZ0 zlrIeC{a{=MxBhdUbLhXe1vs7~1NEwJkpH_R> z^D{eZ=TWciptuYS5K8@PTkh=>44Fv7Ii*Ds(InWv76_NsC@IZZ>Nn!2S9Wt$xdb3X z^q^iqO;!du!;GP=AaU)gbRsOX>RS5_2j5VQIB@5Mxx(gerSjP&2ah5u1gLcX8~mO+`Q@;sZ_4S3@LB8weq)~zRVSt zzwiH_WB#k&HN~Fo4EbXd)@hHAN1hMc_jySBi=QLKTx&@w>KQOKyjnhhD{?PdbX_-| zE|R;`Jr2F)?vbpq0#{7~kW~o4V=c2Hv*GXS{)A#zzc?qyb$1MMjTW>QCm7*qZHPRi zbYk12`W?QHx0>SnSle#JRs{$9F6L?|Vuc7)%+{}F>l?vdl}?*G>s|hpI-o&pG}oHD zc-!QxU&Vn&v+gr|TF=U0BtlJuq({#RrBKdx%)k|()$_C(cB|TC921!9ci-O&Isg6e zXPocmR<8ppPiSs_uHToAP3->C%G9zHRiva0M`m7A!4oDHvTnSYeE2@#>JZBn%kctL zj|X?lVOV!qtvJARG!a}(?zjKK5@cOFxJ=lMg6>*TPt0^ zW^nGL2^uS3s}S1Q+mrb^1FfqmG?`AtAsxk8+( z7>?i7!nwppHKQe0u4?S*vNRFM;Pm(*+oO@8aXW{G{XOmhOlsrU_d+vH6OVof znsK0>FtZ^wehq1{^YD=0`mFp-2Q)snsEH^XDKWD>6CLNaW8J599EqCfdXsT|vl%PA z{}p!um;PA4HpOdI%#>-lT)2X;*Wg{FXv0clk~S~ofx|iGT1p?cG<-pqN_1LdnDI+~ zud#vUd%C)(AH#@25InoZSo#0QS=QxIWVuh{N30jdnWZ6}vco^1C3{tWy#Lp0BCz4` z&q7U%az!}Nn8;R`T|dPj@(U>TDltd;geX>51*Kl9e~79#BtNyrZ1w^eTYY4Yf92n0PK z`@l7r7`Pgdy=L5e zc|0@;)E+Fb8~&`tuHC9d;X>k?d1;d)I;?b zD430bQYz+okm%qu`}G$mB=0OYAzMG}^(p14GP zlCS`?M32r(3MsO>O30bRY-5;z-EqB}x&SY?R zR)`h9_J(z0b!~TUknx2`6tuwq_O<-B1xEHi+q5Gqq@AGV@cf$>-)2I39a2^Hp2rl@ zxUZ`R6@&$sHx3dOcC!A7d2fSvQRQ3PA1ezeKQd6|EH)p756n_m(nHA~hqP=V&U6ot3sx*3} zzLsegGX0oUTng)%4^|ra2iTXLD2W{T)%T^-!}R&FZfn9+YcyFS+{#CDMRh|{(=16o zJ0L<%&dK3aKNIRaKcC2#-XJCRd?vMT66<^SL)PsskpKs& zrDF!AEFxy!2*?_j(`>8{a*tGOkGg&wpG&=*|IP5@o_LxMMI;dfCK>%^If>S_@TfW8 zqyOu(e?YL22d`%Mfce&ZN*dNz(<+S@(p&1Ht_=z_1kLPagT8gUD(9yzfi0wjbO1{m0%m z!QP@~=CH$sOJde|W2CncF6){lXy>;nsgb|koiV3-o>e_cVQ!*gQGZ;uR(yQ6a@#%~ zJWyIWW)+uR1YlAy=-J~XpK97kP#JaG zx$^Y7SNrn;jTNrTtXW=1{k5Sw5RcxToL*4K@xt@A*tADu@;=MMu~wF=prrN`P`R+p z)~*@Cqp#R&99m^8c6ce8U_EQ;43X0alL#I1yD+ZY=_o$viWnGM;XvVRv zce5k>S4aif%dU{t#q0e^e6_i96E77}sZ;cC+XN_-DZCl0CCF})f3x)YdpDFVs#*yF zgl8Q?Y9+CS+ZHyh)5G3D^cPauRHoAmCxf3gdGPGd+L>^=AEIMZ*S zJXhJ8Yd<`jLTo$Omprz4KweqLL&XWs0BSvg7fRsV3E7ROnwk$uorHxvJbi z0I#*yQ5Oq$R71i5=05H_jPbHTno;EHHNv`>7XLHzmU89|qoaO6(D z1+Hqs?0Q1ZbO3AR3_aP#F+b7x=i}17CB!nL(T__j62p8eecL0 zaG~8hRlTWQ#nHQ)RAeQ>A;o){%}vlv<~_##8o_#msq*U&qmT8fK%@Gk>su6TaEQ#2 z`mfaOW11XZw}LVdGQD(XAf`bPy^~#=TLiF4SKF*Jjg>h)ARYgFG1O$Z*}SS3^~q_| z4|WaL-)cBS!wc0}M;`_XaQz^AkCh0yD~*sv)efD^_ciI9b(Ev19r7o9 z@K%y}k$%G)jVW&3yFMSTO5jcie>M|3R_azJTY(|i!CY3Y_SWLFLI$VS{G^v&{JXdl z(?5C;P=r;enqK2F&o7dAxi8*b(6%<7>SNZCaCy@P+WQ^1F*2Tzrwe`BNn3N8_L$_g zv379^L*oR1j|zI!@$!d$tIsN32@fmGx=}6`Kq_X_p-<=F1wa`!lFt{&2%08F%!T4N_@Dl*U7Kc)GM;6!kl+nW_r;MVkvXuv&Cdzbh6gC;wgA0eDD+vJ( z?L%`8cmTepFY1kH8cXZ=r2?LKHif?y^t7Q1_%p{K@ zabeZvO-tKb&i>Uyh66HYP5M0Q15yA&>pGvfgqFX$DZkEuY-bIMGV9s)EItI9?d+}y z)-cFV4DYlV@gGs4iIGn$J=Gs8uZqeIqycyLvg$I=iyM^9tWUe_V62cy>Z$xoI6z4k z-ytIIa>dIJU#m!oxF}p}rNf$rIhKyqIDxj!g}rL2cI$~AVCT?whrRR6u=K#TI(;r5 zz?dwq6nm#-xEtM(_MXmo%3}WCF8sV|A7Hh_T2n5=no-MTi;m`LLD$MHs~nt(84t39 z-xBtu%(wn@@ zuBP0&`!kY=)TCWGzWBt>U8*B}le)}VZ4Rj#=3-*P_i8F%y>E35ms+;SCC`G{%aDs* zGRCi5PUQ;pOy5f1Jim)Ncz)c7G-J}jipmD%!+Z&Hq96aj!PZbyD|R%q%==1l!gtQo zSI81IRIb<^mZ)$jALjg>o3iRHE;6OG6WNEx6@6xp0UbB%>Y6TTyXkawR=1r}^FQ!d zJv0QBnkl^zsu0pwW+K%&|3RwNEcjDm%6yT5BK2=|F35JDAM{<^M1*EFrC#5oCE~9~ z)6^+p4}r9TJAl@t&bbXT?#JU_UCNv(YJKw<^ZL^*{~@aNJ?nrI6=``HEp1jd99taH z9y|J|_%tI;NKtgPF_3I5d;IM2t_q2_(Vrx(w@! zp$Yn=*uK(Vg{yBFTWc(8)3chz2c8Ij`S*F5{O@v>bcIP7vkX(xo1)N%*`-Cu5sYOs znnAgsQ(OjZLm7T&znZ&!91B#o*V1UgBX~=yxX?B(=VubjfqYrHl7FWeE`4o>7!v#7 z+~ew^jN^il(`k3St%t$6`o6b<1rpit@9>vpLTmUtleHKY06D3{R*_@niDFtIzHEh1 z@7Tcsl)C4?H3 zDxr4>Z7V9$66sPS9TGyM6Y2(mKthogdQa$t8ajBh&z-sV+?jj+d1uaf-~5rutjtoE31(>r?a0vG`1#Mlfy>uA_T|i-Ig33Up7IqQ@J)jBd$E@ zPxsV^ictTUq)ktq&tqNbjXOmcUijcA($VUEu{3Z;)U~0M_4i4!$iWl?7;Nz2(^tYyZ<%>isM&>062jiy)Fr?|b zFP&IZ?XOw9P`zJt4_s>@!Q$}e*0O}bhW*LelhGC?lchGr>jft%Y8<>=J;GYKOvOkk zS+(vX>z<(4szx~HE>4K0P)Suw?>(ey76yeSY`e0@F44U5zlrGUnrw)77vggVl^@ys zHC#Ng{igW+4_;k4fHPmxmJoLbo*C+0gQ6vz_KmMjb}xznbG=74yJy*y!^T^sVFpjg zddGxIIZRQMwq%7~YmxF$Gf?THJ3}}ZVh;dX%h~7LZN7L`eOS|toE`8x33-sRif_Js zR%dV+J5`3gu$TW`RjVTb37`Q(xWC&dj-$!Bbxlrh@U>Nm+U#AZ5Uzc36~|zd2~3nx zY)_VfX=7I|I_j`g%W_=TkQeJx$aG}`_m56x0Ef^0(i#75;Eq|A^~-DA3)5Rvn{g7Ij*^3hO}mlMG5Xu_-H zE4)|-QXQmu%%Nq^D2(d@4mVggWT8?iR!L&phZP<|~65q8%mQB_% z%ZBp)xcoDw+1S5ly(ffvs@~#r|7Hd+-#&%Rn(Z{G-5=tVhV*RmTQ%X+tmQOTOQW$Rxjoni0sJM z#6ft4=0EjVZ?l63vhe6Exd~N?h8o5}`(T5JH!52a>eY`lboS*d>^T7gY!Q<0Y7ALi zYTR`DiQObJgD&pe+>kh{NIWM@t|5oFH;YSwU`lzW^$LTpcp z=1=mm<{QnA)_-pV(26}k?d&&~1u+#OdxeFCuWK`sm!sT!UnEi)tf;K$of7>v6=Lbe z&rj&NrXn93*-7uCWqlzE3ZqHzIo$UkjN2 z+D)A{uZXpT1Z3DqlM zj1Ta)kp-*wVYe4F*;AHKHecGa%OGB#o#;}xrbH5TztG*+{_iTB{#V;&Ivl83^v`J3 zCX65ClNpl@^Z{03|7fJ)>vA(6A=nVMZpnUKNdH-TbG)*~1VKM( z0d*QKBQIsVWYQc>i35o!@#s$rO}_*Rl2NGPZ#@NAP;u$hWSxpcS(mbu^Pm>yR=Y2$ z4dq#XCl7@CTwB?kvx=TaSKL8;o!bxGH_#DoV+SPkkV{wQW3&P|Hw0#OYilNZ%u-x} zlWKA@0BW1JZrr*g?>Cv@H zydSffNX5p?0wY50O4m$aT%q#do0?U-Ou2a10*7cS1IzYBu_4Q*#fzt23yA^fjk?So z%~#!12)Sr3{WBkgWsjZc3!B8+&CA#n!l4P=$Cds4{bAk$}!VXlq+GhK^{9qXx zu6P|Ng2K&PTh)#?TO*MP*&+xvbSutd7WM!v92x{Jl+4}%h-gc(WmMmz-MF<<`!8c zD;SWJ$rzKIZ>ZM{*wl1sxKw+QP_vD#m(zK2S}Vc%@skucDI`VVxltjhmh;0OTW~h6 zTM9dIKA6N$qg$S|kcj|Np+V#xIPIQR_&XA_uen7FDc&AMB-*>-kcw}or<*l$dxv7#>)tX`nxfbF#d^#SvSo(kgt*sRaJuAG;h%}5?XCB6N7y-j;r^zGtS2;e zVD~S&7-qSJ%l9O;L&D`^Vv@C*D{=Ce(RR+f;VGhH?uVQCbf;{UreEmeEL2+C{cb8k z4`-8FSQb0=)MLwsKlJ2JR(ARA0}S6?@qYJ|$WJI5z-wyFBLbN4sC`+g?;P2&nP??@ z48a1%u=@5a!p1uWP3|_Q41)RG&WmG((u-rYFFo4g{m&f;0#0XGllMZY8-nRE4X0_+ z5^lXm>dyRlh1JfO@6)cXwLJQ>kCxz$Cp_6tGC!gI9vAQYZqHvM>DyF`p-mm(zxyNx zk1)q%j^U$YTv?PyCv7<-F4RggC^L5EUI8;t6N-HkEO0mVKHoD4h_`>8;n_Fsx(+~- z@$0i`!e_U3%a(wJY+Yuv-&UMuo_hIZd-6$Z(1(qzVuLhn6P~+aY+6w%-qMDmZ{?VL zzm6_2^)1ai8fOs|DBC2Lg4cU`j^}yyw&)D~ST{7Y#)jzJc=XzN@O-LsK(FRKR>FxW zJ(Kf^mX`w>^?Jb}>?_h{Q+;7JHkho+&r&`FDvrwK-`xi*GFf+csuc6^Hfb6RaG|%t z^z5Qk*0x@D&o->WY}w>7Gbk4(+#v<2N_yDuYNG^~TM6<5m z%+Y=ySv9TQi-O5nTs-RY%jBwGbcrH?fqA}5Fx?!bjHWO-nBM(CJ$jBH^Fib#MJ4QV zB_!8h2%%%Y1D{L7)cU5%tx%1&ej@P}j?t(n~f#_S)EsjnnPiifQG?2jHN6 zp7Z`?^vI08bKQX(0H-gh;#D^Pj*7Y-gZ?^d+@e(GA~4GxAI*qWI8L4AyA@Z+!C(5k zTJo~mJ5QK(txf;rJl4@brPLp^uk_FLL*ugh*%%~yEjrOsF_Um7S>30CW8kBzE0^(T zfK@DrG0Y)dEn|7d^sGOG{_hPSisQQcWO$`3+={~q=iYdCD?Tfvv@wG){KI}O z@R3llO%6pEJ)^K*RGGDZ>c4-c(`u=WP>8-u>w3fr+@N&YR znXVn3pRDsYz4ZZeZFj&8Z%e42Wcj_=_RBc9wXemH$4ardTO81^egP7u^%G*B38vh2 zp+TfX6W=!;?LbDIbCicvS{f#_8#`|ikM<E};k}uz*J|eN+hU$E+Re^_PC>R!pj! zDe2e0xB+wUDcE92E0Lr6j9Vmz-PFk6L6y)s)54uKeVJ zTR+qSBc02(0q01t@!@FndSU(F}^Oc4PuA z*)=i7cM>+_(%`KE$`&kgK{Ml|&EurdaLb$*oM}iryd1qvIjbi{xhvIP`0+Ht@d|`KCXMX3C))ey#3uB4kGZkgnEqw*UE@8E3>+CV++9XKBX?AavWpxHK z!m?kdN0j9w?M@7THM5fm0eGd_NXsgMt#Fb1l>8c3%ULs0h#YS)iOStP_X1Sha2_NX z#;8{AvMZrIM<$R*h-LgzYIO;-v9Mqja&aam*49P zlZvE|>LF#O`|?(<%`O+x+H%FBJ0?@vCVV4PY6)xvE*o}C?1>s&b@tX_-*C34Lw#!H z2vH|Nfy{-Ai~x;1Iqgu*;jSx~YYr9^uVXXxYlx6z98Q0+9~uKV4$fcK)GRUxAa;3; zZ2LAc%$^skF=FeKIppkr`!F_G)ebXL)vgcZrV%e*Ro9~B>8mT^d(Eguv3Reh;3tqt z=BuETJv$LG!-y1MAiup{suY5JLL6Ha0tvqeXklsX*tT;;Te}Cb%*yfUf4`Nq9MBy@ z)}j0DTKZre7rgrGm{jeknkME@Dg5@-{iW~>>t-DM(h2l<@j#jOd15oe!oeVQm`?#b! zvyq_i3X4oJG)x}o8fKv)-#E~z=X)zM_oG8E?#Eg!s0_YOLHgEai{7f1Wt0LD7lL=1 zxF!HqQECi|2C}zA21VC)X%hK-{#nZ9b^TFvOpcxxaea8%G-go}IUsJ!b6tj7{9p=; z4x8Z5+za$Mg+~LKqF0u7#30%7M5LC{m!Sob))onyfjmX zv*We@V_fK!zWf-tq|rE&Rw;OE3T$v4o=REtt=w1S{@e_29-xqFcY{vrdzC`nW4uNRA}%b5>L`J}eB^7aq~LN&-vOO$BGEU$eCgX$7|(%NV7p{Y;5i(jH;=)_Ae za-zHVA4xBM(V<^P9noLz%_VHb$DDA+LxO>}4vJ4@n;dVKrL+GGm`Z3ak5FCpD>sA9 zScvv#4{B$Z8)k4$M=;(M6?5i#pc6`OA0<{WXExVS($My`i;(gI3PQD35N0|)H-(&~ z$~7nDd)}ZInR@TcZ!IFVip;s$Sq^ilE%vLj&sxC-1Gkl-T~Y6dK*DF_YRW7q%_m^j zTI;GRGiwFjdT>`4(Hkw?6r-1iNx!=q>SpFNTjm)t>|j7qIV&B=n}u$D(cFotp2BU5 zzvOO(wafY8UaavCSn#aO5GeL=i%wilxZ@Y^u+4)RA+;-xTQ5CT-Ky8U3->PQN!A2j z+w=*IWooY@rPPt}ZDL;#cf2;)0mT6fJ=aNPEIJiagc3_hqzZ_TFNck1>%c;f@?`a< z+%Tsb?Q+lPBsWQN8yMUxoUDCt4w5=RaPDG!tuZSfm7KQ)z)(_);WB-?NI${z>&lz6iHRy9xSYqORo#JQufJq1e zTDsW|VP|HpoJ<;1@j(w^K6TxNsZV=k-)YKB2ea90EPA4FOFe19g$0`mYgV3*XpE<0 zf0qng_=uolvnyLhr!rUg-BXw+q=E&0?U52w9&g^|%OqMmv06MmptjahfHEEz)(36$ zoYjQh+!(a0VwzsFd6tMDpAkVKYZRC8nOySN50O&d(v?5$&k*OWo~j%B;?tVUFg~6G zktYTIXCWcs6op6W9`S4GR+u_p&Xt$H==`;ItoSo~E5$*gU?{Pbw^S&;bIr#fb@oFm zLm>SdiiaRX(npA>yFMG?J^Co4Kf3JgoOWYufwY5yPEge|lpGQdv!d<;>1N z-sp`G%Jumx5*dkjs;0V`QUNE+)X^Bq*-%PQR!FIZd?6+!)?E1Mj6 zz0;V(w|X=_QNO?S zkLUAhO-!8qFioVuC<@Ktoo$-tr;d&<*RUrb&l$(Zlq~%BD-{CA@%Qr7lx^13pRCF5 zD=4DHi2=IHJu+FdfU!2816vok{b;^VKAVbxc~*zI=fv&+Pf7Yn$8ag^^frUHRaI3T zWhpWf?K18TvEc78JFwwJHV&vD&(chY-Vqf-H2f)nhk<2PXE|C@}fq> zb(oBN4~!ye!<=9FD{{s;L1VClc3!pVm}Ul>m`T#{`bALvCTc@kGPmv{0;agXuR_(e z2AnT9^*-nn>v7#c3m7mcTn2jnlkFBJH&VyZn!M+)nj|wBy)Jw1gSe_%It;Kkt3G3e z>OCwsV6vtxdar&fE|z>3OfoR=A`WS|w(?bQETbWdihnvFF$rNAIbkD7{=QC~bAxWr z;B|LU4+0K5=?D95M?M@m6Qx3AWl>)-8_!E|oI9FN!u}lINoS?dh~kc)FY%}oby0lf zi^`r#PtV^s%Un5$=8&~eBQAnbYMS1kZfot`$20B46;f*yxmfCW)+sQH5=In6(xd@e z$sHzmBi%IK?RQK}9LH?lBce+vekQhw2O*CfrgC&z`v`kgs+MuQt>WjaD_c@p%$Nj+ zm#*wzFgHgQZfa?*njm;&ib}y+UOBexBD4+mVl9>Z3oyzdc?rtah^J4#k6S9dO;uum zy4(7Z3Rom`^r`Wo!;*kEtmUvvQ}@~?rUmG;+upo+$M#08{}lRVnnTZQ2Jk~ecBi!Y zVL`z8<=(C-nTcgW_e^oDnKz@?UB60 z13hZi2+dTzBYFPG>i2{iEQg;Z+`vfCH?(*|_7I?Ur@|6tFKRWKTDi}NU5bQP_|=(> z+gzPNG z57NqdHLX4?u7?@*-zGP5>@3ZHaJ@0arFJ8%PU`qbI^awc(Zh##H^0r_1L8|YnVIE< z>2S60yyWy=+T2E;LK*m1WJRV{HdX`m#kzD`gm`2L9-5sG0u_Nl3bsp(M!)EAw4jIb zu#Dx3rdJhk$H}94Xh3&2Vns@;31);gFieSx#Af`t_M?4i~f0TDM|*y6ObSpLuet5xQZy^&bG0AvHiO4P?X zVUlw3hoMz|bO%*gUNy{EAl1)2Tc+N=xh4GJaq`C>Xi}O#@q>`Rx?jM$qc2(*{WHa zhqa+E#BIv(dnhAdJUHn7_KY7R1xOY6hxXZ53qN0eS>v46f}12oA*QC{rliLG+&uJN zf<#khO(NYCgmSFwM;konmE`C3-relVP55R_qS^t(F!Kts>&f2(*VC=>jvRG zg1_g>HdIz*B)RyhzAsuo1dpmL*Ku*c;uEK~5?HsZvqFR+puiJlYwB@GX;JuHbFU@* z+)`^&p2IqX+syIChg4bc15Mi9$K_gOt-|z*V#(*M6O+_*q3=c$t;Lkgi#SKOzBqUD zJgxkBpI}?H9kF;J%S>=N8X;vbfcKt}&Rz3X9f-OUuN$nqB}6d98=jE<(r~phg<~Rc-kk zxXsLmXSObKF|I9yjMn#ABRzntOF92x1Q2c8t(2N`+_G)c{syIyk}aqqC4o;ri|QC; z1%&As!M4E)8cRJ>o$ec726=K|g3$PQ+qL~A+;!8WuDt_;Xh=~-^Mus3tJdqc17%~` z;!tdsk1b{?qohw5G%WMHalc6=snMH-w;=M z>@>+OU@@>*%;kJcsDbgyUSwpEnY8f}+v4k|iNrc~ooh7k9?Qh54{8PMqSNI8twzA` z#ZXg@h*yWmOwO;(&Nr@8?a!FNR1Ikl5gmWW(Y-pT8z$2Fq4itO%W4LvWoMBmhU4Z9vmp{0q_o3zh9x(x=@m^} zATMvIo~)4%)acffj;llU2!07keoHVo7tg3Jojg>Ycva%OuDO&}$KL>MwiSrIgavA& zLE(8ek^Sz&uRSb!UoW7ca=s76p-4cuhC>=(a%!xN9;7I*uIfjFS{@dU!k7YW>(5xU z{oWS1PGCm0WQ~kyLC`{m@3Igs9 zS<(1l>2asWA@7z>OJ>q(N^a@ZH{~4;?gk8{J2Fh+3nQ*0o48ownnr};_*jp{M!PJN zYDD!uYO`4bn+Q`OV!(wOrj&$A5v0&2FH6G2gEE?wgZYc-%m$!w$z8UgzxDU$+@LhT zde$S``P0%7w;2?06$0c>EX&C%UB`^tj+@;>*bT+P$}X;saO))1MRvw`mC8FN12?6+_JEG=if9FmC}KWdj&AA~q&H(?P@c^R68I}d ze?qvXf{w--nH0JNm!92St|@SxB+Q-*O0&ZvCe4JfeAkm)?a)H?{~H>S|LHb=gVZPV zC@ZWfV}mKTDp5~zfoRe$B#QSjhkB4R1Hz7NYH$A8Kn%Q$A_Uob^4sMEfHNJ@Kx}M{ zhcL;n`}8NOo*Wvie%3bwJUZg)Iq5(N=yH7~Ryv8=;#qJ4iW+Ep%aaI|o4pw;K6AzC zZ#?}DMSinc_}2H{JZ>F40p=(_EzN4RHS+Kc%3?3}g66Ez;7fDzm` zF*-+GOPP1&`dJ=N@Gq25KX#9thq8H{_Pe`{O2&w%%if&R3SXD}X^#=nr{`BU%TLN- znYsNj1AWtgN=J96p`sE}RjC7z6A2Df@p{Ffnh;kt0{tQwFy^qjqGVVQ93QUTbS&Au z+L@T|RIpBhsV@Lg?UzG|;8c6}t;*B*Zkpv|x^Xm6t<==TQjRw~ zV8~`mPKumtrt{4I#6M5A>8%%}QLaWzQIts3dmEF=52E$FMl$`=+|S|6GVDjX_&`Os z?T<_j5L)Sy0njL%HdQMQr9$O+adJb7Wr+e>b-0dns>xMnV&@7(JxPWe#a|&Bk}`YQ zt-jKi_UW=_Uq?99zmT*!2m&nHCYP2u?gW(#QEoh{wCIsFsT94PG;G_^SkzX&UE02J zxHTM6Fedqp3^`-i3^et=r=6Q=+Po2>IQL?A;Iy#H(#*Vzze2sDR{Ja=%c~Sm%Q`%> ziXDI_8ghI{8qzPic&c3_vTS*Z$n*zinl(31;grP_;^Sf)M;wqa+X%S8FFMSI(VOqL zVqi1rk)UeLA_~qBt(6j||7zf(b)C!o4RADgemisK5_WS~#y zfXJ&E-8qgl{NSksqi`ok5?Us)PlJ@Aulh&5#tE43)*)Nu0z?MbYnX!0?=%ncyiM4wQEL|%^uCl-%>;y@~zebFg!fb zV;$a}5(a$NPzhQZD@84ZRc)$6hJFWpHhNP?@U-|sm7FwF$>_qMYNRy=Xp6YPXFd+G z3&?U~?~Lo~-qfMR6B*badoJ{dPl^r{dK^|I{`5bU53=vj+?P2Eg0J zUAygGS&t5mov}>;w3y%fUWL)S35tqZllBpiT&nYVl%85lx=~6d=yTFC(!;+c1qIp_ z1vgdZyLTbWAedYDyLB4@9vcZWIH?U4eM$magWQ9wi@f*ahizqE7k9CSe5bWOVH82_~IT!*1-45C%_?0GwPDty! z&0xN$DZ34CJ)yD>t;??W$)l->fnHgNJY58b0Rfs60DP|=?L_99Y+@}8)l{R&beLU) z%$+Hx`62q)k#wJmy0`i9F>p1DpRH*TSAsKt(aB7&Tz1l25y;F=|B?P&5HZX;^lMps zkKo5?)h6BLVqsjH>TZYb0%0W1E0hTHJO)JM9jYDqMx5dUpv{*qk!QL<0Oz{Q6VoI% z-`~=7oGVxOhHeDpDb6bHSORPkwKfvQKQ&bz@?y=qkd5PG@KN7`8mh)_^?sj3)94OA z^xmle>~eE(y-qD16m+!PX0gEqDUEF#Emp0|vf%ZEAVGmV|732l!TSwzEUJvNzmBfL zv~{@|=N25Gyt`-gt~`4386zv` zYOUMyg|1&quk2-sFgX>EP9FauS?Fxjr>fZqTmFl}a>NW{42~2ouK6u*@E$NBFUC+<=ze?XA=d?&P z^|KDFbPB+18q<50n@`w>dXDZJ9(%3hXF$@Me_y@2)<(ebM%wp3`8$D1$zGi!yT-vmWj*OO+^ zN?<)qM~i=N-q`Y7A3EL2Gs7tyHhz(59K(hdWq>@`Iemzs?B=+!T}Z4Rhu2}E4Ri< z)-W5RT~#Y>Hs$&eIEt-^hr+=xI>`$D8K)k-GJA_Et%rey(3-7SLfGd%xxT-{LT%oH zmmOR3f$YfW(@SogtN(zqOWXXm3C=pc@?~p&qO6uYu2Vs**`q8X!KLh{%&2{+Xhv3U zIsZtdu5Kg2kW213y$|`pta%I*S&15P4Z9a!OrH@C^@%-7b1|lsER^cv(!Xne;Z?@2 zj&2=2pA_WTlR8zqd`YV;WeOor|D^l#e_TQSp9XaQ&&z9$gB1kA*HPQ%duV&BL(Ayn zM+bDlen!|}Um7hVclS{|OLF|@)`=J6|FOz{Ft+n2XM-2i-t_F95CxEckktJD5- zMh#55>9_%`X|w;nN$l#nNR?H)2DsuLxhTs)Q|`XMOFZ(O%sM|-egE5TuWQS&QN%;i zUV`Q*xuSxF@?u=@AG-VZV6HZY8L`LT%<_u=_*{B~`0EC(;AX%+qJF~5&CHq-Y@R-F z_^O*ufg?4*#`o?{x`TZ57#+;dIJZ?qf~6z%fTqUTGm(TP`?0i&a@%G_z?FipLpKwG zwbL(=+@ok8FOr5~^Sy6Zd2;VvB-6x;TdX6r$q($H{c2CmE7aWrkXg7 zvoD8qw6ke7a5H+K=iWEElK*>!uNOBXHuHbc0dN0(b)cx9L7AgHMCeAr?k3%he&YVX zt$_jBe*7Qu;K`9@6NAx|0-0Q}IziPB24*eO5)0iV+C&1QH7vG4%zip`rzt};Xfxf& zNbL=16&jDu-z$*Y(lfve zS}t2izwsJR;#s18E4Xj-M4sq4#oAyb=_~Xuw3TAa@(Cf7?{Tmzx0mYU4Nj}zQabVE zksPev>Z@_|2J0a&;LWt`TxppJigtMUTe3vXIN-idObMU zcS;RW)gj9?c-lX21-6oraY=qR?qvS` zgwq3&CbGH9_Jx zYY}pnHUMq>i6g#sE_ZBz(r|gjQ%^GSQ+3wv4_aoVhXPmhwg(R%Q?bkzAImstdl`I^xGyxvs zmB9bArtkez=q_J41e!xQbX{6`yw9KLX_ht;Ez63PzKm3kNAM=|R^zNpSB4G4@1~zr z84)Nl9`3ch*XU^yq~YdJAyqwP|2Yr4;#iJP#az8Z`PQctFhfae#FmmmtDQqN0S5{A-`Q?SOaRR6}eaTTZy>jZXn)1a`QuIfaSwFp*0VklObg zLs%&2Qe?~-!wB3dbCx&TPTd?Gn@8|gc&%np7Z`g^Z-ARKYcK+FwSbgL8)QqQ4c_-S zC#@#vb|~}Xr8s+c@nH1SUUSoGr-N_z(4dg*=Ax(a_Hv6eo7QT0>o6ypvI3inIA+vk zR!uPwJ_`xcJo4TXj!$wK7@JsokuzE<9;o)&*_W1Zx%{ycp3dLdDPta|0mriEbbIZd z^R`7Y8tF7ox)kq>590UsF!z?^e|rg9&j}Q=+Y*!D<&d9G?{$Na)y?wG_5zr{ z-t0d$R<5g2y&->VgpbQ9$`Ym8gi%%Rma)KkaI%A4f{{}uDT;;+tj(ZnR@lBh!UqDN0 zx(IcvZNk* z@oWcqmApXpCbFr7pI5Iq9C6;26kwvCV9l+Q9FHfEwS}Hb{5UB-CiNok1@So6Telfc@voWk9N-dA0N?u1%4CT9^|z${^) zqC%6z@=XWXov7Z@|NJV4-6Ryc3W{oIRIuHWRU^GUkbH6?i$%@^GC#^N{G+u`V@Ee$ z*E@||)U0&=RJ70Q193oWW0+!CY4y7#2ZVjh9rtipxl*oihOnooNXdm9({q2a62I;e zyi~IedX-grQLC38N6uVbw@zcwXYE?D1rO8|lL4D`iGi@1l zM10Y~u8ZrJ*V{gMx-`q#qnQs`<&w; zKs8%|?^#}1Aso8G0=XH1g709xyTo_bZ{oYRrV{A2HtF zFXV`>OW$C#g6Pu8EF~8_zq5(OHCgmW^fN}`oal?r6}yPJjF zZS_rtj}LcV(@YD~@gWscbv742Q6wLc<6V4W3Mm=NKXdwU`EoL8rW!>gSOIF^JbCbg z+43BSkZELvU;3QGYLuT$m-lP{co>IMv8nmr8b~}yDRg04bBL?yPuZWoR$=R^IXc0^TKFzNhp4F`d6yHI2B|2d=jA*=~Ch~$(Qt2{9 zz#8n-9Q#Msp={`m89=qOE@X1=$QSO9^cNHJ9!nz79DaTWw2S9x9JeR}N@p*D+Xorr zCH~m+AA8O}?D1qRw-NNFa}ux2b-jMh8@+9wG{d;;Kya!!hHLG`r#@S6tjV5ZQd5)n z{sFOZY?gzx|9CK_nU^1Yl5?6p(&zlPE)o+}zgFlD12ScW-kvUJCEp1~UXT;Zl0F>h zUTUp=vU*1~{^6kU(IjX4T~~*P0%yx}OY_Y*lga2Acsz>CLeknFBO>%iE0kmJ(JD3j z#?8gi`u1*;kb}l7=&Oiy@3QucbYw* zYS2?WS^*A+*S&vJP{x%K-RL`hS~EZz#{1_Q2a;3-GpqvE$z z-}YNRZScSNq){*uA>X}DGGTN?#|l=@qA%V0J>esTdUa#(xqi`s^}UVas34+y#BJM% z@LQh-hRy|XNr}`oPdVqa0uyZM+5NS3B{?Cp?b9pzeA(w~bF(xscS5X=FhO^1@#UO< zm(pCc0A^;js&&ho)cxB%<5J^qbTn<_7zez%o>)N~RMUhX0v}s{M4$Gb+}<7eRy$8| zds}|m6n1& zCuvuQaqg7U?)V+{@uayg$DcRa5W59b`sdA}n~iF&h4HGI@re z{}{=)CW!q~%7dx~rwZ**aFb*fY9MnLAKUMIw^Ja^wv2oWG(Pj=&(FTC*4EwbOGt9S zLiVB$(!9*65S(SEsFZa@MRqiPugSZub4ykE^dl?oX;IQd0csvkQz_D#M}c!-#gRtVjkb+87YxGQ~<9u=Z4`#(4yxQURKCkrv zZ=#jRNrLLAKwuhj55L{1*P6v#ZfG+zSgFT#8R7DD`l*`%aeSD6!g5*i z@v6-@`5bsxvvnwo`5qtBq_3@C1;&Rzm6LQ4WqMIr`C3=8@b`S{Qo(9qYkJPhKq3C} zo=t{=CzWz1G*EfS%`73h6Q|8l5mRHX@EFDNMK&4sL-G1SqaM6uvY?em&4+(6MpC93 z2jxhZwiP~vt1s*nL%$p2=q0d8EDk=xFnO-Mk!xln!oECr46$cRy z=Q^qavmI6wZLjXPC_mox)I$@CN(eH~I<#|Ca;VTSP$XE>q-(JN^`_*~0U9V0c1iD& zE&Y#dO-5X1ZR}J7UqR@`PzfezVDwoFY)vg5Y663VX|Fcgnapg_TN!U74bP zTw>^t*w3O2y)qp?JK?2)i9&n{=9Jl>lY~U$%nzrddc)|@=$N?RrJ*fo0xa@pqP5cU zmP{;jf)OopzCG(BCLU3m#`qYIamFl-Z7m(8af|ZUvS=!$a7@vw@ZOKFD`+?z{9=W@ zUf(kslJX|qVui|>+W6LhzL5jG?!xrmlXK)KwdJhRFut(7?M*pOBi?}~_@Rwmj<_o8 ziApapt`=`AO`W@y-Zm#%N%%(CCEb#H$$!_JgdeicTre7zWun(X3xCMo${l+Qs~@a@ zPk5!Lc9oYAY=)3R0JOUJc7N8rODV03s)$8ss})PtqGS0QZJ&+FWR5jIrw5lEmma+@bO_%Yrn?L!iVAKx{fW!4}YzGQd@ z{f4WsjjzHqWka6@`^Hn{kO>?cE+%n9d^O)5blPht1Xm4Gdp4GPC)CwNGj_FBO<(0? z33fB_07v(o-zF&^ppo|DQlu%JWE?E?cyrj6`I87tq06cW(T?|g7Ks$^R3-9$Qi2c_ zJ^i*%@ra1X!rX9hel}t0FctKksMAf9777E0hJ^n(_+8=y>*Pxmu(?8J;_h8r?M_FT zk;+43(>kMzT^enFW!o^i3>!QRT5!SjqYSg}W3l3wqOGFMx~P0b^O~7r`OgH!KT|sk z{UjnjA$dbbnm~^XoB-daFno=m9}W=AE^kQj%kRqmU!A*agUHd%Xuo?0W7M6u8(h3& z)ZRp!e7R>s`M@TgT^bRP6H%9{Sb8ez2~5ZZ4HTP@^YT2i3`Uac;dyO z7hD&cTVR#1q}ZU{F6B3fj?g9K%?~Ll&@*Mu**=N2^Vu*gAz`O)+Aj@CPC_0;=Y-730_1GjvC+ zq897K0~&|P8s4izsXYP|ba;T~scY)XqPiOru7&SP8INt9d4mNULX1W#Cd=e_yP(Zg z-Ia|a5rHYc=yv%9(;eA#>eH8E9)?K??j^kT&lb;E}jDq*ccE!qe;eoB78OV+wwDd+M;m;$d3fHeMr-}Hgm$r zc7G^2!|3P1LVPz-e+CawwF8{^h<7wrEQc_g|9entc4`GmTJj7RkMMn4FT321&z1AE zRHvA_DPi@pou7gW3D-R%{$8DXCv@!vTfHh}=xcHj+OEQ8eSc4YwA`k0M;KY-Xqud< z_wBmvXx6e8Q^uHGuFDS2ZqDKJ+=>u)XSxM`)v_E6d^Ie8OH83+*;8k(XHYt{(rB;h z&l|YL8dzYDqN0xK`?LYefvu3~<2XS(H)|<%__lMhZQ~L1?`iJ|Z(f@@?n^sNm*RYf zBL^1&IrX8szTMai!!)b08BLEcifMUuxcWDyI%74Z2+4(Cbn+Jwd4ZTAfSQNOS?cfd zqo>z+v{#5*r_<-XGF~&Oj~$l{GxKJkX&!|HvQsx5ng2h&-bc#IyC-P7EL(NzWrB>| zN{#~ANb!OMmr6d*eqWJraCY(d!eAi%uFi|-+*OiPFHr*Q(+(+SNd(6^TK6L;40W_zdO{~c%mSLTv#}u3cxI_-HG_fx+@B5R07mLrE}T zOw*3K@>bzby@sSPoq9gy7GKd1MTrYLdyWFMLZ00YsJfvs3zPi*PMT>Nqp@KyDe%+f z-k&FAe4U_Ps!DIeZ~ydfJ$!O}4L^|*|8Yyh4teZ@3^F8|y`ly>C9KIWJFLOB7u=4H zX}MHZb7Yc`kN3{QY10Pj&1;aBDYMx^37^E;pmg@u8q_xKpE8JlETkJt=~!bH|0ici z>XJ$Atw+%=RbAYEVAyW|nx{@5S;mh?&YnR~!qjw89;1@@d@nZkU;Uxk-*ly~|KkVp zzxnB2PlkuRFxO^E++9HWOO#tPnhG>BYQhNj*so13YZAdP!GoGAVaqZjW>Ub=(3`1z zcIe^I8hm<&uOx=A$aVfBxJl%AFZw8b2a_2(E#`oH#;-v0coo3yDh*6>^qyN&R5FTM zcm{q;G07^-Z&v9q8g+92;S6UoHg(ta)WVl+*Nz?wcMtzx+`V;BTWkOJ%ieXN-4tul z7AO?o(Bih+;*?M%1gBUj!Gi?nso@Dlg3B&WLP(L|Qk)Q^xI=*i2ogL5OW*A0{ms0; z_dRp|I&t6S)@Atm1>vM@r^!PD9vZ!_7bL@qw+g`I7Qul_;C5}FQ zpk0`>?XO!pv?F@XtIuyuCW0KLVKKr1I>Gb!R#rms-Fe*g(?zrr)%O9mM{ZP?t`67; z%h1pO7zX|YUMAJ@YI2|x_GJYr`8iEUn&7Z=%O_FvUko4g`x3;CieUm~XGw4Zm4$7z zV5({?#!C?AZ7r>U6B6#Xg|K(H$nnQl0ryp9d$UBRnnc2`u+TDI`gkUkw z;Mjw^WT&Os6|(M?WvKGh2QqO3LP-i!h~1PrH8 zi!V2#ntwB)TSeU=@b<`HbJL$_VN z9(4dOoLJKZn5nFasH;b>h?8duq^pFSIgViEpqJ#9>l1W8|FcpS$j?HZNqS@WMUsow zK3770+*N>ZI9v`19q{zz65{3mI5TJZ3UF^LOCSes)yjBJLn`bsrt|~@{2?*7;6D5o z7xv%*JEVU>DRr@pz7jpT+PR5?r9QTwiyAj5(4j=J#ok75d_HcF%V)b=jW#iecD1SO z^Ltz&qF~M$oQhR2&YjKj51F=uH3Hcy7k>ioO9YP1<4e99LkE{kQ|;rzUWH-N~X?7-k%xEtH$v= z+n-j5hU^_@oEdyxE^b@Kr*NR>ACr7vWjSQ*6c6?d0ShZV*rl=Tq8?a5^KdqP=maDAfj7@IyyEoD3e}4QEei!&SJ>-P2LB&JR;pIsfqmr2Dl3@!GjUU? zCN%~B+>$#oQB)FoJGj)}t2O@W+>f62F8lViJJuG+hKWPE-pY!+dQxqzW;BT68=#XA zDg!GOFMct6`ZW2_$}w&IUhoZzLLT{wVohm$e)wTZyLeFMXSxt9dpfo>zE<~1Q^OwnM_+o zNQ@m?x3@#7jS89~UOInTU;g`CJn-@0>Z26xvs_L=hzvU=6RpurGEDL_B?X6M zG_uY87>v&xOF*`^9%b2-77kcKv0uL4#=y^S0GVJwbx^=s&obauv_3#BlJDg3EaA3i zidoJsl)Sljc2At+nw$0OekXy`BPO(2i*^api{h5k1K*G-cD-M>f3IxO90Mu75I7_Zz8|CXH5s zkjGFU3EXl$)1~pwMYt%JC0nfxOvV;1DgZRO=t|C6&|L#{qhQxH3O7B`k`>T+@p!@-G6DLXwCAQ#dsE0>GXAoD4`=HG zjaK!+5MA>(d97WOC==biXQCa*j?3OM{1$T}e8Cq+g{1b2YtH>EZvZp6+lgK|a~Pop z6>!%?N0CIARV4BL^kFz__UwEQ&w0pT>np#x&u)HOHKxzpGjE53g^oZ7gJtV3N)m1q zfjaP0x1}uIX~G-mRjKK!jd0~sn5ilG8E_3Pp(n*_p}{3-Xr*^JjTH13qD53JD^!8* z9QysosABr(SvOTKN01o>b8GXjRiPaw+Nv^G@fh?&m9R=I4!qDkD`Ctn4z@C%`6JJs zprzVZ{E2Mq0jSmXW_wy&I9>H;9-tiZawxZ?Ws$7Z9E?7M=UBVincL1SFmd)J!q`|o zn)P7$w=Qle(C_&j-bNU1V|m6#uQX(1%;J3Zq&i@FkDfh%o91j)k0rTU4;%%Y&UtS= zSG-2^Ox?9z_H9TXD^qRe?$@94RK+iuXvADoX)*3e76rhLM46&}T&z$DZuGq6a9nne zTKpAx=Rn7a!DlT`vPfm#%_m96#%eFz{H0mF*#tXH-BD;ysZQb&SK*CX0!6H>qOs(D z+Ba%SfbU+tRq0yKXYuCRk^q=Zq2+_?faWvqcaFFswLHS)Q1W^u-xg{;=f=1^{2Pu=5F1FT&gI) z>0QHdYYIaC%qkf2Qr9p?9D!a9Q6qP>_n<0_j@nHwNDWOLCyU3Dxq^QfWe!8AM(%MKI378 z02HD*NTgD}e*MR8b?aKxGF-q`ALgtI!paj4RNm1I3-=3XvrOU9$;=*G_c;M5!;+aF zd2)STox4tnvf5paajqFH>jWaB<+QGeV~kRY!{_}*Y!q>&K1|z#FR%DX)7Q5}iAkLA zz(uk#lES)`lE-wM_xnniW-YcPDpx@DL%BY=ZRuNQ4{DZ^!Q8V|3L_YQ$Hr#3YZB(N_ozDisr1Ub`alam zM3^gc_)o`(!T_}d%>6gv@4pyj_ZpU+ zn#2DUAjF@CvW6QtxxI@$XZ)9Law3X>!Q?*igD{ZIEI+6?nGBY^Rx48u#tvwJ&smju z|GLVXXSzo-xEt?Tl5@K^D!QF+`uP__*I|H)EoeA?oU%i|*1HUJ;5gemz69ewDBZ9= z$QExfd%T>}8(!@3mvx^2HqGMX8U&u5cK9;cr8!xV`M$#+>>5)EU`k>f> zEw5NtJz!m3S$)rrH-D?jwKx+Q{v(psr*`z3GJ!4au!zcquw}PY z#EZ3v<#n0f)nO$4hHG2WOL#YiHyMR4!}q|uz0q6o_L98S2aGqp6u236_v%%}U`*i< z&WHacuq$c3A`>q7noK@rwIK(tjd-ekpJm_y#+mwyTA)w7e@>jIKewK%1|J+8(goJ^ zGlw`>bmyCmxf)M1$*ZgW>)*5HKmY5uznpy1Lnnm=MXj)cs!!%hHY-lHO{n+ug+N0~ z;)+(?U9tcf&+9$KT#{QN1MHT4bg=lt2m-ZNHTmf1r!9I&L{~=3Nk(OW>Y9FIUncY! zL|^g3!=#D7cZ>~I-W>iy`Z%kgCLR|$z}W5{FWG9|wOlpo@D*kZA5tYWnvD9pnQ9~v zDD^w-<3xL(5RtGBOHUHSO`({uxr+Xg0bmVfdBOi8r2Botk8X3ES)XaEq-O|uztbRf zOSl7S^5!t9Rf)zoJt>0&C)(H)9^U<xGFRezQdp zByiRlDCH+t<_A6rnAJc-%$GuB76Tn?2EYMl#tU?0RE0t~JcKvbpYh|%+!7fv#p_`a zoe+alNoeTWkF!f3BbgNNf(kkUl*3ah3tr-ths{p3)Z}S;d{tw2;#%6q9WeGjYRP(6 z+-(6L-EIV5Fe3PEw!$YHrvsm;W)XdZl`i+4{(v4gj(8TYz(el2pn9s0jI2V56i&N0Em(yuHLEg#y*Jm3hnx4(IKPC7iXKx;aJEV>cbX=)$%jgUU`DB`dk1E%c ztn{*xtprM$VXxGIWowlKo02>UuI-;KMz zr_k59tj+NqPRF~2kllc~DX*z-GccV^P=4!67Yp2gO0wR~NFy2L&o$$vX&3=A#ag(Gb29i5WU1&n5Iuq1h6; zhbPmxZFqZ*YX3EoIRnTo4h#xN?#`;z!58H2u}bWyqOtDsgR+XdGsS$gNH`F`)>FG+ zS=TMi<;LhRyob%2$R@hmB6M!9myOWA#Y zGaoIpF9V%*9S{^K-Y3vqFZyI41=>45Nhy=<7$O7@TdbUZRvUoJ!v+*k%%1wSpkyHXvL@*;wqYiOeIZ^)JTm>W~*hj2ipC&J@rMo=G+Zoxz)@AbnK_ zu|jqs?!5Jy8tzP{@^0KyIR|79h7ojbGX9-BLkV+=WloIfk7^Q;(zSGK&cYoDiQCY- zr7*9C4c(wlc|8XH&?9;~5@f_Y=;tKUgqMdonQztbZVF zk`e#%@J}fd*IA2asoQyh(z$<*E7HR$5o%^WC(0Ug4pI|~mmIO2JTPh=67p%yxmLyf z#dey2DWF#=gK(@NVzB!q@BG7xXph~|+}SIz_K+{}_4rhfMiL4&TYWJpE^2-k(oL4P zt?R0xnl5DEjdcX-(k4Ir_|~A3)|}FQTF-em{i39)?!8ANTZf>{pdM>NhRA)Aitrof zs_`&q^d-p?%m_Xun-3@O2VY*}Jb>pK9ZH=+(dEjn)v{k1(UKco8@gIAkbIJl5wO3o z7FQ*{DHqpw5tdm`qVX+E?Kn!Tf0^wv4>3(B3tm_ZztQ(Kw@~R8MchejNGJrIFkBA| zv$>AZczQ(9cX)h>cVWnIE52SWvptW?ot-bEs4K0lm)!mGa!LaG4p9&1A1M9&$O=E- z+TA}2>3QH6TfDPzA-d{MQHc}^FY&gQl3ipL>4RsN(R@I;H@zrP6xc`qT<+*;p>7SX z=2k<6wPS9Hc;IYJ0y*hw0n{I%CMW%zzy4>cV&wE51`c}mL2%4|m z(VwiF&<_vN(=FU}QHxd>^Hr&3&WKnr_Nn-S9Kv48Y*#vF`w*bMhO;0w%eG>i9BLiF zILG^42P|{`rA|T>)!BumiPo#@thGSOrhLtKm)%)**yaTfMKY~rANORtHL9W5d?Gx_ zcR>5(Bo^!2LJA$Y9Z}n|8PJNak!^%pUJBJ3HCbsSQ)Hpd zYeKHYy!u@hiP@_a%^O|&nMER16Yo>dD080kRgt(FwCKu(24U!wu9Ih{o)u2g&-TmfJ#?(^=}n<_ zS90!H4SAF&OH0`F8T=gw#n%r=`F>DOWlc$F8FDN)n8ZOPLaI_PDqAm)Kj>(LNuK4~ zzz4VlnSEz>%yP=tz;VJve)Y9@wfFCQ&p<=2n|3~pEYsn}@WI2C+GEzM`J?#R$D5|E zZqv72K|{sYxP%gkKm2Z4H2KI*c&r-Q_S|xaN6Lr(*;CjRxbTU%1JDaQ*xz_{H(tYs zi#`vFueb8AKddm=nekX4)+hCN_=BIbfDhlJ_m&h+m~7Hr8(RiqN>ehS)xC2>@@GqO z^l2>K>lcG2#P$qIZ!XzscYiUgUs3Do_+7_<~1II194BC?w-Vbx+mBF(Ly$GnAvvzx~AEWa3ZWQQ(}&tmC{vUIth zm_>WreO`oQdOYgn6@{41F*ln9psmVT+)%6enw}wW%QiU6W*f#i#9OxsCTlNNfgm&l zqN#Y3KM17nxy7rEwFToGX2|TLk?=n%cZm9Q+Y3k7g^X}W-AwD?YS7Djn?H#8#P4BO46xod5_6tfQ z&0j&m&GHjkwr$fDAoR_omfoG_1sUFM)BOegjbpYO-^R`n9jP24m zknMVkFZ5}OWjYt24WefXMoI}J&EtReBuzmQj$D~xPWAVaOUTrgTg2-j*3T!=M?zc| zVWS1^^{x7NB|wX=CVrxfd8QTE4=LV$S;R=d$G8JaUDk8Y6e=Ib^Jo{>iU-fMrYmmH zOv(Hv?r|aH51!^QvS;hfVn(Wds@tUK0DRiH8{a2VUpl0!b}6_VnVarTqp2-JPrX-6 zKmKB%+fZRXV(3F~%iB>8QEtE0GZqh_8_kOg(sU2#+Ca?(W62JvcH8GPdT^GltBAyA zts3T9Gs_;0kTBzt2jJL6*=8>7U z3wff$&lBfG2*=N6*vfh<0aT{Jpflu`@>J*jK;;Xnr)9`+r85={ZDRs`cvR{eF9Zb^ zx@Q(yu<6`X;B)4ZBg=-j9dn)ASRA>y>$nVLlQwk7EhfVP)KZ}(@jH$)O9U{d}7ZR%ocV3 z3^9Rtq8Cm0P3aeSRdt&rFkER+ zGG>qw&eb`^E4;SG)YZ!V+?)Dd)q9N>wMoE3pvgn>dnd@Yml-wdKhsW@jp( zk0TMf_pzT_lp4?JHcLRISrX4!HB9eLd}MxTW1Z~#fiCaZsG^E)8Jb87L6fU|RCFE$ z>|LqN4Af(^2PR5PASH7`lA1nDxeKRc$V@P`8gg$Tov(&yv8wWceby7H%=b%bCPCr% zqUOAsUkwo+BE~9k+)k^i0>|ee%+1UP1K5<70gEg{tdhmIM#RsYOSNj)!pxiPdm4|i z;-LPrin;o-_lJ1%R!mQl$MZ6c96Zq(e6R!zkP!i!KRGRSm8bL^-ViN#*SrvTuq)hmy?FfTL%rn4xyy+d#1W%&UVg>`N0C6Su7_0MOEa}#=o=n*5()jKle={E#LLgcB3EC%+VwXx#;0V&Z`WpJ|!hgW^$-Hx*0>&YBxf{7px!B6Krpt`(NNoO^P3% z)bgt+PjZ&I0xQl#11`qOYX*FRifaav$3>0O6Ll6^8mSWBEcpYa#V~&1DmR}$dA>p? zGEIXvQ? zmMtM3A!gz}^A;mcR;~I9;NVh7l^M0YXEMh#=>!xMMJio+yDZC5N0mw}b{u&wG^u&9 zaEClUnkh}HSoSKJ?4uW2y-hwn3ziQvr!g!S@6ayR!kFkQQ-{Z^zGmLid5_bU!I0Q< zfCOOI8Z0ZpHA{-ce?iS?l?E(aJ$X0 zTMxLvQHfilvdI~gkw?+-LyFaZtFMflD%G#;?droly8DyUVj0_2<#$lw>LlirybFS+ zbruVlB%l|soH;X}{m^Kq$1k@z7!u&I7`Z-56GBpHl?8ic)5?lHbJ@KK#kD=l=Aw6B zj8B1ef^Yd(bBR@UuFBLSVK&A%k#5;hm+sWLNwXy-M9W;} zbErb%CWUKmSBE-%dxPaHPU?GxJJ<(#uyOHd&YKz_Vy*Yvcs7(jY#``XYS%@0z)7~E&ZstX5rY(6_=OjMm%r}BQuc)}F-xm5BF1qu%kgQ^n?N#ROWwMVxv6k!nGS?eM|GLLq#sPaBSv~+eW zqY2Fxc>>!{0;g?{ZfUwVd6t%~ly)S*kQGR&2Wxx$oIH`0I&7R$v5ulSg?H^MhL&Q8 zwvT6S7V2qD&`iu57u%b=?r#T|So(f>J%<{hGYT_~LS0mA#cf_Uc#o~*Yl`d%G17^0 z6^wtIH^z&InvRCbik96eO)MVkp8&tDS~pFb=q}k&&cl3PKQgvytk_H%?U6w}ok9bM zKQn%RykKasKiS)u1cB@U_wzrOI=DH=SeS_A3GBUygWg(6*-h5ZT}E49LnQaNz~YFt^0NwZmZ=w@9^5mhBmI@ ztH$@H+QU{Nr@)bnM})V&aP=n!{i*2cBmE>J3zgOK2jR!;w+FWvKctwJjnoHdR?Hz0 zVM`h3=(^c%f=4JjlW`<|p5o})b!Qb}SyV|#yKqXj_J*ILc$M?w^fEz{9T3Pdx8zjy zUj_{SVqoB=XH-OLuP)OCV}Jd}Zr=a%3x~ZWc{Ik>LIvmWnRcf5@rUWE7%oiG+v_e4 zin%IQ*O)ZF$))iF?&qABip(@v!ltCvUY+{&Nv?d>9Wv#+ps|oh89ZvH#2@-HrK!p0 z&NgddBX735jYd)d`GO;clbHk%>o7NY-HRye}%j)V&%%83lY)@+=|3N4J6DRWjgQ3!F zyFDk@KxLyCqXcyqFBYzx&fTvbSYGH*PMDe`uMDF>Q2m};$JdWXUH?vnY65;U-?Dzy z8r_Enh#Nn4kE5ihDp~o69HnSEZM<$SBM7(P8_h^S`9F5X{q9-ShTaOfj~qCR*~8DE zcK`vl?~_wXM;|HC^-drDmo1s&L1TORyVyaxEp(uLi0z3}%4ox}qM$*FuBxdc1C_W9t`DUHU+AjH?5QeC)o}k@Mie3Q zd4*=8=)wZQ$ggn4pDX0%e7q3%iTrLExHxHeXzRFR**I&wI#;6BVBS_59!dtHJqfzM zSsd{TR~Zd0Eq|{BnIvo^QEHP{hU(v}*ovNS`LU3- zYVd>ScRM|OJ#h$~G;BT{5iHC<+5ROn+bun1)rs5qF{IjKTaU?mhHw%w;ztZy<*QGX z-opg?{4Q6rU0q{kiJmxx+lK}q0!@)Z$;RE6JR+siGCp~!#KTyDeJw1Fu||a8@v|5o z2^)`8n|;7KAle%7FStv5`oXGt339roUOu%l&y*TXct!TCI3 zF%vsP*W&nsNfT3_eMXad9)d=xR<@hvLjrg@&?g|uV@MZl5Z)wxQIrjFVrPG)sjK_r z|1);8-%jL=ho(_Uy@V$Y-06MN9aG)d0Eir7*L=p54*GW%-12wksB0YXgytO)1E_zX zUDcvVs}|et5zo+KBQ2)dFd~pOB%ImvQt&}XiL{gVANduu3>h)+c4Tn_d-oWTmD_%@ z<78FSWRxy3B(0tAO9U3WNhxY!Zi6966P8)QwK0Xq39MlIB4R8VPKROaDP33%sc}a~ z@|s&8#v;FA=}TXv!;atU+#wBvF|`8rLFKl7woOIcj{D8|c}L;3{aM*lCE~Bk5uM=%(c;9(C1`0id2aoehH#(& zY{}T1ejw+ZnZ|?mp&l=V6xYtZf^tnbOIFB%zR#tU?RHP|dZ_uGP%qRi^G{_q*)Uc~ za(>Z_kv-G9;Wt}MHk>em31iccdXLqWg7*~yO+NT|%NXy0Ze1xbrNIC}?k9fgn6x%zOVht9vyFL`EdUs(2{E$I|n{^Kun zWy?G3;&&6oZjB8GOLx{JuM*VHB){OB#Ks8xka9DU^Y6n^7)t^j4a)OwFQ=~D{(1EHpT zmRy8Dl4z{Cc&NcZL;2T==>_*OOtrz4qAq-~<_RQlZ!7Hm_OYa`)5!XK2uDpVMbEDmKqZAZvkO4 ze9_otf&#wR=v<*lw3Ca?~s~7`IZ!HAU|?T1g8F zctVqpA1e+*i_&jb|FMJw=^^P0laZe_E{f20UF}^jZx>(VwlD;5T7$>cr0ZvWTu4i& zDcLTe?;Z$oLFt;oyK$P>s5k)K>L055Xy@_S6YMr?j0Yh06c4-S>;ZZm~-rkg~Kx2Vkfrd>qj_ z&55TKNh%Asb?l^ZYX#J$<0U_)NLDFOORYk24xf(AX2NP>9RXkn9F?u+$NTrt;H+%8 zOs1mlw7#Gu9j~6*rICmJhl|$Y!z0_&&tL z4hJ2x2T>oM8JPH4gO7hyv0JkYda9HRhOi|kCOdHpwAc&p<5Y|lPK$xw><%&I9@=~9 zKoielo>ogjM5Kj`YkiS}v{}jgTMMI8(k}lB!Xm5}7XQfrXnAE=R)Oh(8 zQB|$Fc88o6%6r#HC1rLwVG)!=AHtt0^*<|HwlD@$&zpRR@qsd!)KZ?Y2DDAJi-9*X zO_cGp%yDr4NHFtroutdCIf_r`HcU$fw^d?%p*w#Vif6P>VJ)l8NJq|)eRbhlp?&&) zPHomLAZo-uw2orik@~#3A`5q#=1*$5!-t0=>n|66x)yLl^$@_r&sQZi2fZ^zmY3g zT9s8j07t$JX8NJCEJKBSiZ7_>@SmT+^OiDa^NA=ZOCppmw7O0Hp(wtndIW<(uw@3< zi+Cd=d&2&}hyyFAl>{^yv|76E1DU%2G*l?Ml26wE`Kdyfm{B%qyOFbK(ehey&6;r! z^82^OKAoP<6zdtm=AtFPEX$l)2`!TLA%HcOFg{ZqSgn|Lk@2xWXQMk;TOFV@ha%I> z;`%S6bIil8(W%w*G@G4@IOEj2x4q8&!Zv0X0E(Ng`?4@b@JJ9-joEZxI4DP+KZv%M zIw_U#^5d8QHbz|w=MG;gLFSr=4o<8H1g`;p*22M4zLK#03S+oZ2xeE|=(HBuQKl0e zjpII+dZT?$X34sTw-cw}V9tE5v%TC9&Qz4n4^M?!hui|`O}lPU%{)O%^hf}IzBBH9 z?0SkcQ6(_R`n_mbRFh^-ues*5gV9V=lXBco@)6e4mUWros?&G+%l`lUpX-3Gu?vSA zQ;S8k*N8bur#sUD8f$%x$(|jvIU&VxWkf_UIuI3SwtKkgV1ZUY;%aG%BG>>8flN&z zURk1`m9<%TNESfeW5|`hzY|F%OPaN(#*Q9S`F=4pdSGu3RRwj*psL`cw?R@cVgLXb zB7{&^X?y1X5dKcU@mud$uz*9tfDceXL&Lz=gqjQYG4C((2nR`q4b<{ytrk>@U}K2H zV9Tws-5e$+Wue{+p<&O{s*dn;&tD8#`)Ts!Gakb4{DLiMJYoGy4jDf6awaL6aumVu zmQ{omie-#LBm!W;Qii5v&b%1|8+dYkXCVd&|uIQ-XQvb$#HLvh)=)&s%MQ06|| z_Dx3hv3TIN#!}ddk_8OF5f#1v@_*9B{!NQ>7Xi7&9Mb7OXN|SE(toss_cARnu?GDx z)p|_#?kEJ>jIAL4obMiK%CbV;CjDaAz7Lme6M-0{t31!=;pOHuOBgO6g9U;GT#i6w zS!WDmREqGjV*=*0Yf`fDKr8~K0IN{;uHWo198@QUttd(g_c06Wk7YVIB+vWYo`ecY zWJnH;ye#ULiPMxSnc(w^ivD?cxe^c_Jxgk^BWG> z-i+NUDx51!dz-GQsHnc{8Ad&G+M<%I)L>qTR}idfF{kT(XhsdV8l?@C`huQ zOxw-4>vaLLn$&hpm6pkLyT%iU=6_({X-F^4oG=hR%ui?6gn@t9+M$RWDX-AbOiVz5 zJ;tcn5jwmCm!J8Rod_fHOFxCo~zYYqfNtFQ4K}D{b+u}07F65 z0>s4)(HHCCC1`+}UF8+utIZZN;0}^0hQ%=0zoI1S9S&_LfN)G=)fo}lFE_L7E1kH6 zj_2q4v+K4FmmxMG&kF|jic}qJj>L-KoF5pOv(FDjvjYC++>rgTX4JO4-is-YM_rmc z8SaJ|y9iIZ;YFTv=%V`Q z;;njAktMY(>^YO9@rNFsg?y&Duu)&eHe94-dk4Q`B&$xmXR?nSScF@ygLC;Xm(x_u zW8C1{H#rmKK_zS)Go2RC7gHaCEEC`Nk+qs&e$g#ER-N*Mi#+CTreG6(`SDwYpAj9w z&M^v>`@x2|vtH0%b(T@H z*fk4JtXMq0nY;Cmv~Vk6Myi>cTVwzdENTxH30v;NGy&(|xhUDT&)M2oSu60+?W}9< zG03;2?>k46#!BI(x2P-i34D^*beKOasl4ZO1DvIa8lize*ETMzGm6X~$I48AF2~^- zO-viE?*YTrxPUlch_p5dtvk zX7gm()?cP1s%UYi4`<974S?>DRz!s;++9D>bAHoL*Fh!CK`cue(n48CKHzC_fR4 zf+{Q)4I7+#K3)tu5C6~8{$D=_z|DwjqrukgyG@cp-x!qf{CxH;S~6$@Kj6=k+rxvM zA(F0BEq&uehN`LmI(lWT#!ce4nEE&bcu+I{LP#l{71_j>&zvgaGn8!b;XJv_-=_8@ zOJYa4Lvxt2?0BJR1(2I)^lYE*SGrjaKH1MvCMGFM(FB8(c`E}3>rAc+I-#bDm({6@Ar=Z((Xub5R(YwvoX4QDxLqkgA zd<<-Vb#G-;gnDig%VkclKzD7KH|iv*atGdlD#I7H>sGUpmPIKFc9T*Ik*b{Fk^Gz} z^nNKvfEFL-Ge|)>&_Gp`i!zWg)C`hJta3sU!VA{CITV;bnb>=c*(mHs@7ZQ#d3h6t zlyjqVL2YM3AAhzIR&=Ojni#|Fcy-?VQ>_ZSC%(tb78D0giw+f=^`h!-m8QNUfFUS( zx1@ND!S&zRG=+UUV z;p5?#!&=YD^mgdrD*rDASUmltVNloblaEZl7`o}pZ2e(>T{=ApxO<-Zk%pr3AJNqi z|Lw{h2aWVu*-r;3$*R#D_8E95@!!J;tdo=OD! zr9OC%T6g3(G56>pTF_sAH;v53Yj3j3R$FCN;yT%#_GXX20=P#%AGL-TN7BvHs6;)- z<^|7_4VwhDF&JjaIC<@}3eQ7&jPhi66BgGeyp>vi>kY%hq_1%a3DTfmf~)bo35JqW zFp}T6@($GZJ$bGtXmco{aYyKON*Rk7U0Lk@wpbDr>=hO?b_h5^?Vt>7iZK%BA15D*9Gud97U;KRl_qJlH zZ=fQK@cPA$b8~=(n$qDu_wN&JBK65)E$2mZ%QxsqBZ=+shya*C@pQGc$*hdTyY zWn0ha@7<@c*(0=eJ3>zIG|Mgsa_&bnt{G*=hX?u@PoUOh-hG{M5!kO0AXc8U{;|9g zn%d#jl;jhF9tE+{^z**;5=GFz7%~w0sMGGHF(tJu^XuF&H{t32EFlQQ%EFY_vSY=x zyKXg<(egY`tzKS4MM-^9{OI1c=>0ld;Fn`r8H4LBdZX;`yO;M|;9r4XM%7nFJ!`KS z)IMGMWcQI}&7^t+btHUwEfHWXaIx^&r4`t@btWsKJIngSspN?K*{Z2=u?_6NuPycC zX)_PZnH#rNC^dFra3f~Qn{EAd4Cg%+;ErblCULPdJnapQutJH6UGnmWcqon+7PV-W zpSg#qnz{~Q-~0{R*H13%mYRnHp_S*bH~^GA^%sMzO~lZ#D^BYWuU}eW+i!r_uF$C| z08a!30Er=)4Wak33*Q!c9GD*d-B)t>xuq9{Yw>jS8s3&#$@KZqjPM;Db4<=7ELX?o z5%F*L>LO%Ll)g;3rhYPKhrhbtoXUtuFo*X}RvsQ}&*RiR%q>rBzB-cBe!uvT{3Mn; zEJSN(ZEi2JXU($OL7>B>@~5lJF9zZrdumW9O`m^@%k^f8&R9nCilsI1AS4Q(l%lWo z^;G>n5_-X*2Fjr+?>nj5A${LvqeS&l&bSr1ccdP^LOF_%Coij*XkvrnJ?*Zg-a$j% zOjIJxV9>a()tt>#h!@T1Hv<7uL=P;o$=znK2bXnQfvCNocy9b%Nz=7`NfG$l1>DQ! zfh_22^ss(LNES-T#p_#V4r^%Bqpsp>#x)%KP8GA4eM@ytwf|0h4B`*7AsEYbkmu4L z%(BGx7q1T(R2>-elJ=(8g?QiR#XsXZJvREqa0H;e_0EiIRAU$V#c&FaihKptGe^oI zotSW6%F6BQ7nBf9^fa5dBQ;!bEf=iO-2AQ-679(weP^tmu1TtCi9e4ll!WrkWtV4# z7afOx+gUEGz+;mICzn5lovAxo#TZ%(rZ&XB%dcsIZ>G!@ce@7G?d@p^c~076&hVY* z+f{F*PZshm;%{XnvGTuNvguq)x>oMyy}q+PP}3zxI#ORVnmCQrlDU0yk<&cGc;;0j zqXFG{)(~0moQTLlnnNIC>c;>z^U+aXSTQ34-finykyySMV6(s!?!8kI zs*q&YFqa~Dx&ra8#a2})KzaGyGTV==T{S_xt9xikhfIvCiq3~~V<*{$36cGn^^wOK zCKts9$i}i6!n5@;E!pk0Q>j-u{ZO8bmwzu%tnYxQ2I9F@W`+>_ui|3cB}IEK|6=eN z7x4_p7->_o%Z^>Vy`F{Q?rC63Bwp`R>^^<>iyo1$9sBYkQf)GoGbrk-!i^>=cGEX-+S!`m0YYeC*?>jUoFI z8QS0-zo_;yX-f8q$LkOk+D8Wy8=!(g^yuc!h1CLWREMXi$prx-0@;5tki?_+my??~ zZ3S$lS6_#TpO>KCEcy%|Jw7VV9_&`}8Phhn2dgBNY_AewK-e!PU*redZQa z;1ZHNTVu6C=(~O;K(f7115#u+s5!n*qPjl^eB)uQ5PeDX82l(EDL@L3G=#2rz8QDw zJ-13N6d#yRb)50`+j}r!30h`l)02{E2@W|2q>#o^ifYYeP7J5@yz^Ha*i(fz|uC`){3)TPfZ@I_{}F$qOw|UnA~4H8O(WA6H=> zlQ$_6EBNcrRc!m~j==Sb0a11Xv+j-PGYD2*Ly^E7;+R9F3fmqs02Gxg@Dn9FN zoLn~I5ZP7M=eLg@3fhGMbWJJaRh|z@OGqiH4_G8j6+7ulR!Hy}Tf`PAz1+gj&m<|H zi?xR;*CMx6xiPL0K59Ep-7gAQn$ZPS8-;T|!$}NrSu6nHs|d_a-FXJS(#^{jHQTP) zJI%g-HS?h-wQF zJk!x)96vfqy3$*iQrl?} zd7>_Rv16hm1@)>2AK1Y7KUT!9#a}OocdWYO>hR&tSg`G7*P(@y$B=*qXnm+lXs`Zr z{T=UCt#Estv{`g{B=?4=sdaWt92D2n0$ts~Prx(y{dUI;ctR^a~Fr=?%ggj7JbT)!#|EsL<(zUsW} zx~YVQxH ztLd0TO4C-N>;XQbh4~|(yDO@E%zXb3DfZ>^M=H|47}R%uF?iS>XKhP@iqjgMPE2L{ zxgfoBIUG$1%IQkLm>Xg2;-R1o`?_>xunu^h%|q!a90v{konTBkqev>>UmIFR6~xL= zACNG2hzosQyA9TEY%l2fd9v3XZA=A=;nx9G=;xW!`-}_)<3Ti?;xg_%%SFwo8PZ$ z)yRtG&`bS3WKPsI6Nta-WDMGz`(7_4uU=KR<@Jz+*5!I&4JoK9Bnd9BCs3n{v`@M_wV@!o;O*^T3I_~XJ_y4d4A60P|39` zet{g01UJV6#4f|UUplQE-gs7l+keuWu@VvodoXKg$ij1#WbFe_i`6&;qbRQEB zA4&dkZpVE7Sjhe}<%NS^4tt|b3A8jX4dv8d9SeUSunf!DWc1H}ua@%XI~Yx%w*=qq z1lfO@Nr2zFSy`TL$U9_L>oYs&q!NFBtPX$C#}9~4=c>W$HHDlfWIK)cjE%2OCh7|a z1{rcjT^(rf{@HC6RV8lk4%gIzL}vfgt30-{Fu3dp3+3Z|T{>$^_QB%Jb^m3u8FhLbc zc0L!SV_FIUNgth}$ry0B(YwFzRF{*Soqzm6kE}K_EuYC6m23KlbE`G`$hw14Yv}ZiD$4DKc#wgt3y@8&_?GL4>^bWI zZO2+m`DuU`ki8zMB8xHob=2(i)D+9-?%0g%zFx{hJT^9?YvaM;|CIVFdrAdr>maJS zxC}uo^drGo#OAL>^x6t`{mn^`yP-K9z4J5GZ%sDjT<))K{Z-58i<})2z}Jne%oQKj z-x$XpYSj{gTm(3DM1;NQ0e3CN`zeF<;dJBJJLTmQ_uOUK2w-C70j{LQ?%!_h=>9|dW3Ve=^FaBC`XH( z^Sz`fhWB!~AL~$;tA%Zymf%Byh{l<(sX#9~moi*4*bcLM^n7C+0^}^mjQ^wE^MO^7 zQDevUWG>~&ED28~pypTgsR&P;Fn(=cQaD|%V^zFga6WGAwETr733Bm*f?g zr?)1X+pqz{y!*zGyi3LJAETU|=A3rT#k^nXKed@9}YLWCLnRbvaWSVZr(JcfTXh}S++ zY?0k|$_fsB11`p+a@Wt}UGn^+3=wW8U!e|iyk-m(k^Z&;5GsbR*!7P+yleDhE~oo} z)Q*N2UeQOBJd-lig~Fk~5wPIz7FpLnR(z3@p{H+j)Z+F*T4ed{T-jE?0dEFWwb+T`C?);A=P zc*Z$t%=O1;pzOqV-0wa0f;w)4Ry)4|%PkK3OVtMqw2#i%A@HjnOhIR#5ym@-mVMz$2-jaIyxS~#Ix?kQ^hq`C7# zemBfuHuOoL76qjSo3M-N}Z!KhKUg9Fc-bER3AvoP!gP(f_W!C>{?7wGBF}}~$iGY%vv!OUs?0@1#Ebrx zK@WzEZknB8nsWe+ER}wb;D`uj%=kr8JC-lMFa_pw{9jvQUUCbXYWuUh_XLyRsa>?` z2S0c;(Uvwfc+j+I{x(&y=0y!ER9Ov9qn9$ci{I~U($@5laYxwVtwj^%JH%?Yv*@O2 z>`Uo8_%;XwsL6V7$NFl`rZV5n2{Wns(d8CG98Y7)LtH1H7U}E%l7k0emTr7MGz@R4`;Q0?ApW*7` zT-?MpG-xGNm0_8L9pYJUhVki7a7_oh}r()hQ916Rm@f`JtMdywchtz z=n7Yiz(xm?{Q!JALl`H4Vnjz_hOkD47I)B=9Z~-to4WgA+73lZ_tk(tH2n8Zb&`Gs z1*G+G{WyV79###wX7)9)-In^AwT56^uQh9tZ?k%N`!SHe^QU4^#Z#^o67SoUkaKI+ z81Y7N4}EL$&zVg}_a76+uN$o{!$-((9fk75Ow`I*LB(t%aJe zbh1dca7Nybni?B=bEsF7G(7uywG7QJWQRFR_~TVetwrg+N6c+@5h-GlF9c2T2EClf zA4kivf564-J6DYKlz)XSRuNYqEh#@bkZ%&z5WTLu@I^ACo3xKtN2%%TvZI#1s< zdp%&tcrPx0aBiqzMc$-UK=ZrzfxNh1D&s+r4NEnE8NF zaz*_tGEOw!_LwQP^_$ntW;X0aZ-wr1gciZnPvSR&p%DXYsu5q@vYoPn_yTxnc{EMm z1=Ev@j>GF7gi?&Cd3{=A1<*QhOFT*ZuNi61DSmRr%U2CPZDRsh_4+?Yq>a4NtL}b? z$7T?)OTR3Bx%P4m<65!`xa%oE7dyb)@c0qG(ZKZxBY_dwhNIPh-6}OLt))YbKObXE zs>mx^S5rE+Y+n$JEBZeqbLur=GKJz+H^H0}l<@XFC;`7#e~Lfgm9P|oZf_o;86dGM zY&E8W1&s%Sfv^!hh}Ml9+z_!fb$iUio<+tTKjWUkcBO*tz{yNt1UaJsf@T_0iB5|Nh47Dz4z$RMlSQfbP z@H1{O__Q2WDj{e+G$EnT*=Q71Gosv7>p!a?DUswR>0a)GGJ=0h1F8faiP}+AUH@fj zdp5JdcFC;sTPXT2WyI6rQM?m-;EF9zzfIgx5R1yV?X?xl@2lmx+M`fNoAK~p;hZh2 zpjDt)+|HqLxLTLjbgED06pSS;)7B!DVFw3mZ|DC$9z(SELbs|XtMIpnrg$@eBI#DJ z4e?@kb3Uo>bf19r?zHlMjtCS+`K+vo@AB*1hEwHp^TJ1^;#noJdcWyBn0@G%6c*(# zs(+4M{F6$P>nT>@=hy&haQ+@(;cH9v4Lkcfv#M^GD~JCBPwBP6$O%5)Fl0B`k^ExC z&=@H%wn$gn;Az5O`Wcc@$LQ?+TALn#?FW9xmAC~bP7E8c5x!`n34Z}q?> z*QU9^BJg_b3-u=lsDGJmwMEu|jyZyrb^KpyAZ@2IWMeJuIdudC@Z{ElG=nJ@ul|5c zNmq-1nJA_%n<+cQDa@wb_f$8|5R?dnV`Q&KK4K>oiv2)GW%xBQGV zUNY($#uGfg`C~{T0i%&U{H2()h?wjcUsf?cF*-PK3hTCX%QR@@yfqB);;TXh^6LlP zFV)Y&mp%SQv$GbyCN;lTJ^Hf9z_%@f7Us4uyV<$&gv`U1As(dpAENxou0q&hK*w>o zLOFp$c4=m`^6%sTL;W&rZroGH)a5Pui#AW^5sVQ0&HX=KGY3jyjaSGvtV#or`Y@Lz<_59_6=2YE0{Drl> zw&ucrZh}jSY6x=Qh#WS3HFJ$^woq=PAryN*(j51e01lKbT(j`1as4#u`O4wY1Fd{+OtLaQ~{ z7kR^5dL4R`*Kt4#BHSwqFx1jAxti0v^s5osrjg_a(kV{?GO98JeV?Qar~p5$^_m_*RJL`0aQT#{eDfS|{f3b)gD>u%wxlk! zcK!og9`-z-^K4LYGll404by64c_nLOZOrNPYSAeBI#@Yi#w7dEtuHik!+6*5*Q9C< zt0+v#nTVT$*~Jp@)sLBug{rE_1Y9a;x`Xj`cgYy(g`=zrwyxNihVgxvPfafiqkgG2 z|B3@IRi51ey5Z7Vjr2?9ua_Ko$Neb#%$Ffv?NAjg)|}uF89EB5b6bC3B(*(}*=V+H zg4^UsxQHtI9ceneYs^F0Cbc>g)|Sm+7&SlR#*x3Kr4%_wJy`%D$>z!#Sh#7!_siVF zTA8CJE{MtWBLG8I^7g>p*49U z?@m|(@VSAf2Fs__M-BUrcwO7JSdf)5Mbq84Bi= z0cTY2Lr2PXzuh*`i*~7VQ`Z)C$z=#amZBx@>9z5D218fz2UYolD4UIjKx{Gl=6s19 z_lk>EXX`{Fs4UU&PDFL7O_!5HV~vsh;q&Uj$TZ3SnDMGOsCgU>ek%pyxD+f5^{hP# z)->hq2c?p~&^sN(tGd;y*)g-h$E>-^%$3zo#;R%%A_b`7&4t?Eq<%bHu;kS7A9QY> z2j0Ae92~4Dy-4Jo_rnW0Frptpg4`Sei%;KVO(x?+vI+Si_kX!QEa|0onD_O<98A&} zmI!gLxsr$L4cae`UQMsCvRmcLO8;(!*N%40q<98|TQM}QU{po3TJ;EpXG(EIa-M^h z{g1HD=&aeb@bvI5&`Y=k%kA0?yj9M??8!HjsJt~hI46RNUGy;cK$2UKgJ5CANpJh% zgPdJY2?|{RCgosi3SPpS|FV7=9!qK~_t2Yga}x-YaGvlO9B!}#xd%$`H^hiwHmoa|BnXiJ_t$$`}zqr|; z7A@S?lnL-CTAK!k8(N#fM%Bsw6Ef?tLv3`c*ol;NviI1m)2%$o8rPN$eI6S4hBGaS zkV3V`m}{4Vr^_x)k?k~h53M6jL5@3))7sN@wm0&aC6csi%4!~GUMSWc9HY&_x^voP zVgRJ6;LhZ9zWHw0XN!TW7u>zmO@-lvL&-l~C0Gm^{f=yJ3%BX$FjEFFD%athR;ipA zswMx5dshbtvsvcczY~DNFL>0Sv77vOaxMOb;|6C8uwlLG$Af|lorvw1A<bD% zvEgn$+p&E?^cz3LGwzeE1`S8bWO7XBejPfBn^QIdB#IOhWx#00CF3CxY?}4=JET}h zT1V0klhlYWOu8ik6Nh%Yo>Djxg{({zx^OJ&P<`j_v(`>lfS3>zXWvvi1PgZi@eN}7 z?j$4zsNcBh?8Sy12OkN&Wo2OBW`C;=#O3jZ=RA19^x*{)6Rm5$)bW?QqL_chtC7H> z00H+T9q&>qOTtpLoqDj9OM_^1{XyzoSf4CqfuWdR>rB#|HDU$xQLr~Dga|d&di=|r z9Sy*oj@OM1e(|WlC{K0Jho9#yc`J~?So^MV_pVpNg*m5&2kh+TaAkJZ)#mQmvK(Mb z%RQ6BeiGG9!RCzp`NQ#H8;o{Hh1Y#ShG16*bw_h4|9T7iNhvAyZ_xJh)q3^gZlTa7 zQ(&Kx`iGghWYQPnVMLs1W^#sg)9Ic#aylBnnH+68%i5LOt7#bC&tTT0km7tXFUP#q z3ODT+5sk_tD~vUt{v)^W>9QF~FaC%sK=Kbmi5#^zp@odidu-b{1q9!ZxT|w^R-V9g z3-sR+WVR`XVgfOl*;-tCSWf9sxzSoCSqJ5YL{kLWRmWTI|NQuERje-pkkHop5~M;f z8$bT%KUQ{gI*fy`c}{(t{4dksqyOuX%w;z4I7j_>i_vXZ6Tn<8z7z@oooxzUl;>Ya z{qOr1a&|k9{{MU$YhmQK@qd{ZWmZNF{k$_DOA)kQzKrCmoZF)MK3Im1#|IV)r`TZJ z`YCbUY}D(JrLR96(gcQ(j~LM>cAt8MrcrtnBkxjI!o-K7{QbYz)W5MchF~}XCvgvM zopdcgAC@}#9OYq9up5(kK}pMVY2l}#>BfV#jkq5lqjWSYyEdn75@v%hG?#R~uZ-f; z`$~mix}zm!WaTC{_9?=#-5J|}O~T*>n?6BFM&Z<>{y$5tA<5eDic0cl&C#AW&cZL` z3+qKkcl_mhkHj_piX0H7LDilZ1(}tVM$xTQRi{N*DC4Kpp|H8pvjHN(%PUdxJ4Py$Gi7B=Czky)hNuB*qVVGK@LZMwn?qO6z z8d(A{kCqsz#lCn-&o2Ky2 zJVG`$k5n~fM!+?W@okzbUKUso;MEVTE@*L9i>J-Xk!*DXZW0OlpMskUx#Q8)@Af?? z(dPKLFjFVQz0RXX2_|#Gor2!0sH(hc^e(Grkp%ci_;MhQ$JA2AFJ0jM%5$|L-U~;& zl%S=LgRUE;Rn#PEHOM5?v2XbMPiwQ3J}8h6b7ZXeX;s(;(~jkkK4;9DsqT~kw#BCl zHsyBNs&07KJx)T%Z}=S48@CPA#=)@gn$O}g<6VRM2m$ZrTS4wrnF%7>ctc1|rb4s( zRF1G|hCU5Z-l-=6QDfxKx_Lb|O+mgOi%~asnSowy)pFCN7}kq3$2Vcp!?PJ;u%4NwW4{%7+oVudBTCZol-P{gX6*Y)(Wy@}Np1;b!xqRO`k zYvSOp5){i*l#d5)qRk3(GviaQ01CRdZl$GN2%goF1fYgIRsEr@?Iqf|0J}i9f!hmlN%8Zp0gPHDxszzIq~i zJQWa7oyi`{7;KdKWa!#=cXx!rT7AV(7AUlJUV={%aT0B8<78n68~QA(d9(>%TW&1t@N;Fx_ZPm9gIK*UMA)2%)Tki@-6w{hB*;h zCIQ&G6&>_#@9*Iw1*qtMP#!^OXD&tqSEK(;)#xW-&2%#<^I!B|Ww6hmYZB>}INmk` za!(?7i2;f%@0QsY*0QTe4BVEybxu)&E)<;SpWcm4doVPNGha>M<4mKgCYnjKS>_H4 zJ9?ZDg4iRM8G*#N>hEu?R@+A?q1}P^&`AEKonJn|dAB@WAv5wi;3KatWQ1);xasQVXWjXyD}yM9d;CF$90KCYah<(DiA7t;1g3_y(7tdO3~Gf-<8W@UDA= zBi+ZC!(H$~d(`&a(Jwt5jVcNO;;f0jS$UU15=#=^zFoE3LwS#6_LPge*GdQSB^k|j zlIr*lQFVN&Kr{7H&~`rGPFlVAx)ETs*7kYn5Uc*))opxJ{x_bn zgg6JcixY^xecA#6Wjc&3eOOJEXe@=Du5By1IRMDqn&*ocH+(~%oN&XM0)b}< z58mdx#w)6Lt@bxb`x^Q%Ff?{T-8BVw#U}HRm ze&8xpE8xI6Mp@7_0b)2&t077I$4ia*SKrcZg*4PWfWk({#u-U+K^esxoPT;)3SB7e zc7T$3y}>@WJ3S=rSAzf9tEXEm)}Xz9G)I5T2 z)l`7g&ivp+Ioe5O;LaY=_SVZ>`^U;%S0dS*`1cc5&F1HincGW7a(an8sR6 ziBljsSxYW9A~%}0Vp#1)b(k(~McYxM{_>Mdb*^_2?W9AN{@RmBjEg_vO@xM)VXudX z+inSaJy1XBEjl(pLyGi=ijMsSpNrE$%?NFZ zqnN}Ri)FMEC?F7^UO6TzQz&G%>@qQl00Hk~C!dRr(0aT}A_JSgoRO+Qvu~%|Ey>g{>8B zOQt^^wj6$tCyP`ao6PxY>bI)vy#f`#FK%z@n@#Nvem3BkG*L*LCJqZ}6K*$xHrx0Z zDXv^w-nAsJyKdds7$hy@3DeM)tcRoPP@o6;&-Sg<>DXXQ+E>>L4Cn@wP> z8nie$77+1U$`QH%tMpuJJf<$InlbJ(x?rNnJy_zl|7ByO$YFl(&~{SS5LxA7D5_^f zFmL>m>Du3av=0awsWN=$rIdfB#Q&OiuGOp0_D565LWsaafJ+|dmJ(tziUaS0OgRb_ z9D%>SCL-$FSloCQvYO((oH0uto|%K2y%=#=!~^q4+Ra?YIaG=HXh%2m{m?LY5FM5_ zel89QnOO`dU6*lhc091=*4(7|PPK{-J7oQL00d+Aq~y=hcupS43`cSOfHK|lj}g52 zK0)^VrLV3y8paXh+W0o}RFf)u`&4?q-4U=9nisaCE@jsI)=OO|>NNJ-0VBFo6xWj{ zb5bql=z`^w9wmHYonxP?0MSro3Rg0tiSHX%faSB5 zKL)g=9?eiccsfBi)eT+W9g{P{!}Aii z&P1h8jA3~O0z(BwwT^SWx9YkMnRr!W-X`2sRal4{kjzw-F}1VjMW9#Tjq8m~G7G9_ zC*O@loTm`h9YPyTCeQTcZ|8_hKZTOmvZvZIMq?17x^>5aVknNG5F)%%Jmx^8bhro46`DZ;c?{a!Lr4p{VRXZU!9 z8-Lb~zYE$hA)?o}mmDDW{;m^;UqddOv0V<`w<^An4j!JI0F7TU$;dG!Y$%64)O!7^ z;;c4!@0R{Sikge~?I9V0KYnYjeEw|YQ-hNs?>8grjqViHH!v4c(k?lbq{vMJLs+l# zgG&8GA&BZHwpGhh<4dnPU;>wI(|dIm9V21>K4u=WDnK22-o6INom>ID=^UV3tBnJrkN%Og zHpb$I&P#E7PA-PW{haW@EK7iB{k*yL%pQzTRWJJxojO`A#+bp%FBpsWR4-XDnacKG zt!wD%Z=cDY`q4FVU}M${KhOM~G}(lGx)8r5JE)rFDHUvCES%bU{%6jZ6C} z#OrCIcN(5>pQ|u4_82mPi(nwm3}n2e?4FNz0vZTGuh<90pC-9w`3 z&Zb{zbP4sr5I|S0drqY>3A3>%<-ACus&dZ^r4QFZ21C&XyqFW*Wd5Uo8ech1DvwiO zH9MJtoB_?9zt1EjhLmYdCdECN^+>Ty^^9LI416Y5;B96(kSmkZMOdhH(w8b^KLgWq$G^ zICqVLr_796-_b#sfOcuYsF3p{EQnIMXOFRC$JWSGo zh$VVxX+^71Z<4G0@gR+|+x6eNhN*>aXW}zYLHyKWLfK4FE1EZ_OhBLvHEzlnYfmv! zI6M-6bEHwEgFZM%^U`1f8vbSR!#niQ(FDrg_6F$Y)_iX_qQ#C6yf>aw?hqkX#Nt`p zL(WNYJ1Tn5M=G0E4m!!PY(aUV2rJu{GjkU?h)+6@yWs6%Vh1Y@n%V1%^Ho?uOPvRh zXLri5Du7V1_0$14Xem!6N8{j7*#RATSNJ%rkh{Xnm#%R1>dUBI>5^D^+Cgxp!$|<*SYa86W?1OP(rkw#bvTxw%G4GKkHVr zhNELK&?K@^Ggex=!|VjPwndtLQMPRED+)F6-^d=Ajfit1^R9F^Q`Mb0tmFSW4H z$F9#=y>9kXhNO`LJe8-p>zi)%i{=ECg0fJtus2z~ZCVRf#x2GzI{U@He882D&8=y#NN>- z6)$PV+PlL?;wPsl!y9urZnYacf}CT$kUtA7;Vmbg;MYZZ#2k#*lDBo1^;_pV53q(- z46bTbO0elekzJATG6kHEbk2#@WpKoPz+y^e=Mpgp8k&=Mr^D{K>gP3*U^w%kqD>xq z#Jo;qmr}+3cYg(PIC-%agqCI2ghBh;NJ4R^uH(s(b5i6!7^5bKYPsN9$Top1Y&9}E zXpXT=Q1|~`m1Erh?c~F^taNo*hbKL2nNVO6F#^7SHbQPmD%7!Eb*w*UspUrB3}&1_ zd^d}d->rl=RYkrbIeXY6P1d9v04y!fQANw_2L!WFPT{Ue(^;2HwYsY~3Z1K4&kD<$ z;wpqEHnrsGh`X#1(F99rt3%7t1QVatX1Nna6g+`uA{q_C<%3AHEoG_>yy(j*mQ5aBQ&X|W@&Vg^@ zJtBea2%3EdL=MYK&hsPR^Rze;fHvbG#Cooiek;V zcJuL5vYL)KH%>4m{J~P5)msEmX#P%iOCTtsQ$+*OITRQY7U)=g(@50eub7jrcCGUu zg^5M|Ws90P_?+(43SdoWZR1xI-8)mFb{JmGUB|~QyB?^v`LZ35j>GmGL|o5=@Y;5G zxcl$hnCt{SamWM@27|#z#_TlrODhHELJk3)@B3y&CC%(=P8FSn3^UCYg|llcD&1c# zoqX@BM*#@D5Jh^0j_FA2WoP&YICDJEDv}zkt6#a8?{@cQrF3Co0zPr+M006o61g?v zX+111IbKl~C-Dx~xC6LDduxN?K|d#yO?TEMvv@6S|8(|QGb4SpbMaaK2D&mVf08dR zs}7{`9@oD~$kYQ_jDQwn{*Zzu-4;iN3MT#B&JQ_Eu?^9|>K9umnp#XzP^(G@A&x1h zN%+rrXJ&x{EdhXAk99ehPZhnpe8+>XU&aY@Ef4 zRcD~^$0#dhP5dZkX#g6Y-#D7>%I$c%KG^H_pE_aW#VXxUC5tn}{p6{>S%^-Bl{PI5Zu$Nd*X||ksWM6O$LgXGh?0ik6b20E>~WU=tcIzFDYDyM6s}g7~*reRfcUNXny_!^5aTceYR2ewTM+5 znnIe7e%3KA!SER@)4UdQ)8>?Q6n3?TY_}GIr=TwbL)*2SWf&pJ-Gt-32K*I|?_j7b zD<)k=^91ljPjXFatb3sO?CycMtW_LoTy=wc!Sd7{E76z4eb|_e>dNaV_laK-mz3}{ zgkd|l#V?D6wnlu6Is{r1gx(Fpi z&iRsRhd9isBi?3O!OxYh0I1Fpfik z1Z0?FjOQh(8W}|Z)LIOI8WNu8OI?I=QwWW*Y=|?|xAi#n|B}}eUx`&++boRxc%1lD zrDnr*%OKk!PZz+YT@!Bjl=EBLYFh)pNZomK?JYEs5~v(VUF zldg3kZbB8`QLOCr_C>l{X`fys3dS3Eb3NHLJKfr}Gs&!c_j#hizs#trc*`%hl>XqC z-;sFghre3lyKE4rulDU za0ry1#0mKmZGeNx*{RfTV!|Wg-?R>pr)bpYb4$UK~Q+@Nv zZ!NX+U}BeW)r3h{FaxDqQa-AUw1@zN_*}2>SDDsmaVHdq~%lI4V+lot_)l1 zzwNFCYdT65BD;_O@o2?hP~vWa$#K)UoPko-jKKBfi9}-qZ-C@Pp7Ne%t@Zcd2B(nNxs|a`bbS6x zwz#!w+{ST1%56^TVq|rAri)yAMB~3qFaCSpf8M%cH0SGU7q#A;gEeosqgIyHcH!v~1ni2`fCEkACKt^$g?C?Kx-RmrIall4L|)voJlwJ_bG=R*;_7FI1@n2uB)Te~>F1 zed6lTD5yjdBv=F)&U~-1v2|0714fP_}cawSCkzeS!Alyks4`%CUl!_g-tE z3@2^lAw;jmPov=zCgZPG@i4qQ!-gn7CiMM6wA}vG{9~(z~Bq^wVSN?q`&m?hW<_v(#*#!yJcxV%i?Uu`` z?v<^eJ(?}ry@ccVc(uuB?X_n*PPp%}P3P>~UbFtt`gQq*74sD-F#%vmXiD&@lNcG; z|NO}9)d6_FaQ@@M;8R6m38)HraNjRul*)1I^FSA^;Tv(|qK8iq%Whe&^#^MTzHgRo z$M~n9l4mJD-qOJ%Q$i68hV1V)Aso=WHd3$d`XQ8pY&=;5$|n4nuEPJ(mhZ{;g~js-HEXPKX%!|yc5#YX^{ zZ}|fKrh^&r50_3^?jg&&~ArGbRo5 zFJkLn%cs#EkLDY^9tAryLPLcu+s2}`t`dFY@OI8`h0i&WVY+k!jI~Anbuy2Gxbv=J z@CEQY{RiBQ`K>TGreT^#;+elcBHT zC=t~-M%i!x+t8sx%rb!OF3)Ms8ft&cH~S3Utu32bN3#seC&~sFxP9HHDVtABl4&J^p1(7Eph@ny0svX@ zl_g@to|s#T@auD1D=3g{;sC6AX%*-VImB zoZ~U(<%keNZ2|mbDDb+L@?HbGpCyM)htoECJq6X1?NkYBjDx3fI+vAef{fK8?S=ZX zEG?~S<&^i@6S@l{c@@<(gkS-E7D!ub;>cI{8{_p~X`$qIgJl=GwFIQ63oB&JdTh0> zv2MYy_YL?uuBH(4yMR<&tG7pP75e8|`?oKIBZbCD^vV55jl50HJT)8E=9CN0y$HkU z8FN}>;06HEIp*NYAB%x`mlQ{)t&j$QYGD!fwCht_51z!v2%3-(#)%%f!Yg)|OrLwH zY0@vPlUCM7rnECo)Q^AE?Hj6s&@-g2v$CHUwUf_z7FjFyNOrhg3{GrVR`2*V%}yL+ zX*xUDm2dfG6a$k8fNUJTSyJn6M3&{<`>S*KG@q-L~S%zHNg>g*v`xXN}F{L}(7pmgEZ>@;`l;#($bk;;~#(gC`e< z4lN0K&9a++Jk>c%xIX8hbgpA+PoH2;h4y;1klL#&I^)Y5Cb0l_=2^JF32^lcYMi~m6 zk>hZ4Z1Aq0MubH;)2`24F!p0?;DIVEjLlJZHys#wCeiZyxr(Aw&%6PUN1D`Hud8k3 zWxKWhnkv1wqMjT<`?Y`P6UJx-Y1X*%FH>T+9cZ4m-xL_pd6l9VGc%jbzcut=z<9uk@njgz**`g>)_|?=xL`jDuNNTm7+WQy`xw@M1XX|KvTrlxraPf>X| zwrbI9U4-H^5|0UdT2 zXBhk8NjY6AnWTAqtj!3|8H5c7N;>%Ej`p}`KKx=DB8y(P2!$8&cXbL(Agad~Aj^Z4 z%mV`mUpQ}h?jU7hmKqXl{CRu9lf{tmG@l$+P6<=94jQZ{f1A!@K&#j><^&|&MgpNe{)cjRQb(pc-Q(}jCCwn#UCh6-YLy$uHRilCG z)RzfY(&o7?AMS+-wHUj6kZ_p_8!^~ui2PbChdB{v^B5RC$Xh~>(?L~vVSINo_1E0u zHx=g00b4?u+)0h#ZAHou%!k5lHO!&H!H}X07D0)2l#3<9C%bwPx3z%&m*1$&Pc8Ir zYV}4`v}lww$tcBdG4LSeyy}O1=enI5=Ogk*hL_CB!WA8%$|gc9IU^%ljOJ0aGFvNR zI83ZbFblJEz&n-G$edj9%_zar=JbIGF{*b871H?}C>hj0;Cs_#hJt{nPkmUf6SIgG zBx_R#h!KNLjEz^9w?%z=J&znHoLmCJ!unv#+w$sahBu8hSL$`NhqhgK?{}^$p|~SJ z`wAmBpOBs4tLC=i2Lej?2VG79?-b~LFoB5qBo~1*9zLjvtQFqK!HaQCJ8}@~eIh<0 zm^q*{NH8l4<(;hfV0`%Fno)H#fJBvm1_jOuN7;;KjlpJ+W-azrvsD2m^mB7yhzFz6 zCk{ub82-xymLzbK#j(h`d(n)nf}H+;qk!RzmnA z`3H;BNiS2sogP}i9h%?0i0nw)$fWds+Iws6y8_^A3WM`olJZ#OiZ(B;(z>}w(!Ezh zz(K+1y^=bE=b34zz(+b8850xv0Q2G+ajlAmb|2a5*YWVc4qXG)2#kvU%8S^cP;l8k zNSqRy6nK@N^I;le_sA-qQlh`cAf758nR>NC|ApraO*=2$ODO_eB4! zeM03_K{N*VpN3xAd#x&1_j1lxdprMUDT9b>OiszLSy>;|_dsT@Av$N4b4e_I4KbdW zFcy-%=2qm8OGjw^wrj@%^rot5!M>e9j+&^--8*2tx|19Z)ojB_+_8nLxFhtuTN0yP zAON`jk*(-hQEJr8vZk!oNlQnZcnpYn<8x^A=kY0#bcK#ktr@O5^<(;GO%a8@=Bta()iZ6}gVt!}f}!=9@iUJq zKcfJz+QN?yYoU8)=b zrVZF8$QHVWEN;%m&yCXx8s7bOYqa{vzK>Rz=&N|ZDxzf=Q7S^VbAHYzjD}cq!#1zO zUsHH57{oLIg?p#m^8G;F1&FbC`r#d#5bWt7na<1w(eWN-H~O6WeYk1_$J`Z)1I&YhpV#;Ycp%x zb>DZUN)0H*VesOE1PD6Q;*?M%xU>+U1W$0C3KR=8!M$jRK#ByHq9JHo+%>oc*Y3=> z_n&Y7$#LXIjwH`o&wAFn@9R3RWKal3jc)Btsv=23*L^on^)}zz8fg5}j>F8EH*sJn zFMN5$ho;#_^(;=wSppzE!?sLKMR`aNtgA-1ckq9{F!=^u#{Z1jtw>j)hl063-T0ET z@&i;BE9fCufhgb>c!>-a5L~RWx;W+`3+A6V%`2q4$CpVT1yz=BoXw4o7l@Gg{kRakVD(>rkuU*)40>Jtwd+n>bFFmw>g%iM*Su__Ct5&<@4Ck#-MBV6pKb6J z+DhuHX{SC1oVa7Q-&V6Lfqt65yYFU7lOjsEtko#}alnq;C$4WTYXI3*TkY&hQp8C7 zQO*7KutEr#!*C_D&^5?n;-)7zc)dFc-@ZJ;ytFQPdAEu+X1BBAuw;!79$cH)mPaSX zVV(GcWoc2067tn=;Ik^$!cn29>K#7GAv& z6U@p#e6Fks97IVPm)sGw!pM4`*x4#Fi~G?6A#RCgw3I&H*_h(Dx^EBy78~67n%Ra!mBh*hlJKiP+Ns{596;j zW5omnem{ajLpO}ML5udtw@QL{|pZIJ7jv)9|Me&T~m9*8B7*;awad* z=?CNW`A?>%eOp;c9#5#OsSdbynVd0EQ+1GKE}mTJp7d49Uj=26cs;<4-yH|9ypPEY zk~TF52nBoiyMId&B{S6ZYZ0w_L%;uH@N*+kceTt}a5n5N%>vc24ZX->znS`ii7t7B zF~`Y1Km5NYrsm$u7^0&jGb8sCv%5dBQ7x&Z90>Y(rz$;zk&=g}rJ;=n+pYI($XB zKi5wV7I|PBCWeTXu@|qZ0^$M%dYRp$o!URt&KN4)mX}KVz-&|bG9J#kJ?XaOA$|1> z-w_js1gaaW50^@0X2L}cH;&}~e!pFU8S@!xV(YrV5`Mquf%zWaUf?0a!)LiOXIPG{ z*@xC`wAg;Ni|R=Zbo zOFLiJ)6RZyx3e<9mJJ$nOtQts;!RvL5}-<-g7X5%`j)(`dGfu?n4}v;h`$s7)j^3X zjwC>WPJurZd%?N*6_sVOR4G!J=|X!*cmDJLKQjN<`}=-QZjTkUu2Rq<;O|cU_pdb< zX_iK&AgZ4vc1}>HzgI#%GfdM0hS!lF^OPRBE&t!XL}6YhZuYH^CD7w_cB00D#9Oq< zfA)9X+{{$EX*L4Fw+N^6=ohT+-=&LiF(V5$H0@Sy`F)sEq~fZtJv@$CHk;S&&TJ{M z{cFLfh$+sGz+G&QzKClu{b6SPj=%B=3X2tTbLlw~S4Ms`DO{H>@4wqQAgS)(+W*aQ zzW*A<$L;s15{&~G;I%IZlfP1L*VW7k-wjO@<*Q2%EF zV+@QEM^yZRtG-NG{YZSWU1_i;iDaLeI%?{@{U4}aZLM>*Ap{mUAIF;FD3}bk41?f% ztF|Wnd~Vz-{zgwXvH5xDy8}z7FVxhHmbGkp}GYy5T=t=3DiJi{K826MbJcs%S^)m^K2<`Jd z)IiBI*{I&Q@!+pp?9~jV7D90AL;HV+h}X!_v^DK9UFKG}K7M@s)Esv-A>xHQWw7yA zd+J^(_DY{Yb7vOfd1trjUOPW5jFBmqJyksWOCYkFmim3H4(2(1xqX>4s4NAHO>j^S zIGEX|8Yr%spO0M9EoXEkhT1Ux@gMv7|24s1z))jFnl2PKcN*k~$x!7~B>Nt&GJWbo zegBxqvX+tMeH^%;A5U7gvm6&5 zX%T94(Ne^y!bV!c9nyr(Is~iy%vpc&B)D0HES!yUVq*91+a&DdfZb10{AQqtNhxnL z02Y8$U2>3&CeXr4HrWL}5+V~nMneo}qJXehn=2Jna*fA~?3eU=+AlMY#;&5LZ8gNRHrL?Or9Y7d%%IBl~RRX^#vN?*AMA!$bfWC$uGIc2y=cF>l-6s$7zj)?7~V~i{> z8RltHCx@C#?GdEOynt;Q$j(DBq@418WDS|af@dkS0XS7B7)qyS29lLYie4ROBEq;4 zY&vO4FjP6t+hp7JG`ZRO9G5;O zJomlz3x5t7NahZ=Y8o!A3QHX5UtQZh=X0j7EOm2x)T_Rt&!#AMO!z34x=gh!#*R_k z1sWtwD^xp{YI5(Gd5*$e(%Ofu56gUz)Xt?d+107>G*5H42pcDETmP95m{iY^0Yro9 z$Q~)&WS>>DXQdY5;l1}G39`!4V7R|omxm(l)OZa|r2^PRf!JLg^Ty*nzaZ~ms_j21 zPPUZjGT8n;fSNg=IPjHN{!_ZYDxrKI5K=?pNb}W&&#h-JA+RXC$3m`}{pC!q+dj1F z;4EWlIZ#SRceW`!3BEjDF=3`SB3_n!$ByzPWvEmxCNu#) z`+ViZ$yNGvbix(<{!*tS2VIYGbouNm{3K!2>bA3*g~M5f*PeS7#oM*O^NK#wLI5Dd zpS|t5V8vwjYTrs--oa`jpxCw0)1J?4<804@%|q0=d~^iGgN23 za?rzC?}}?Il_&9xGI?J7}r&(RCtb?l?S>OfHkh1%gVyjXo87Q?tM|FXI(&c|9;!u zdwj}VItGpFnj-g!vmiJ}_R1hgL@Qhh)orOB zQU(J8PlM^}Rde+C(MW2Em8HX{l2IJ?rT?M$vr-I$!jdaJIBe(6hgWfsLz{fpA%nUyzv2U3wlag97N{8Z z|A`MGd@aErxJ^wE5Yr~Ja+TrfqTvT`ezY>ezKf2OdU9L_02Dtc`?)MpBD#+i4eous zc&;13&9}*oRpLouh&6OsyZ&_hZi{7n(&OUN!0u>L5J165r_QMS>xRT3pASP*$*#UJ z4Yd+W^O4AmUXyplQ;MSSo2;x;zw4jCx)g zNlsF``7}ZXL7Ep3AUKwN%k{RR13F$)C0-q_Qa2y9b)lM=QN-`(0j}gl--lja-;zkK zerd{PQ6|!=!*v2+o?u+PxNi!Y%jMF_x4Le23UJyRP*@P)zZPBizPynh?F%$!PwaYG z&bwEg6+Lm9k|HV^PX?HA+Or~6t^mip6YfJVyTKvMFhH?0hp2TSyg2E?PweAqWKaNF z<*DjmMJbI1nN<9>23lilD_}BuD@9mX@OYz14PL5urIK)=cfHsp5}e)`#vTy=GCAe1 z0dSxdEmn(haLG9@dTgCnhEev(^0fPv0Ct zSL@ClsN`Zq;85*&9ezw4`s+s0Wpre)T3lP#2zkoUCwyY(G&v=<_BGa#N+|yvjmQXF z5h2vmoMw+U;NbVf^djzkLm%QS3yvX1lfImU%d9gOcq;Y8K6mudHy=eFq= zVwJIvG~eXu4@2X{oV%zuYeXAg(Q>hRiIMP5;}7@$T#3|CsVj0NX=pfejVT4p64}Dp zdFpRIvkB$_Tbv7NMwMPcMBmmq8~0lkXnKM~X$c7A+^apEa$uBK!$bE26}Hiim@YzR zAP_$)wgcF8bi*Mbpz~?8O3S+xD^%AKLCj1(qcq;EOxS^RdREj+Yn&eoSvm=df&SxO z^GW|rbHQvbljx}H@@JyYhRbcc9xgXpz6%uugwC{a^xN^p z3|FKq^#}PnqqI~i)MgA#*2(+_7-1vtA6JbxF|XgpCmm74_-jn2-}FuTx|HZV_W=b9 zEHJ-+4K^v$`nvnDE*h$1Rn9o(T(Q3=ZhES&_@~a`6K4U!*x;<6*MWNvt-orw`j3cv z_Ex{|Z`{w@M7~9ptQ_nvSL+spqE#O`p>tvYp>GXCK`M=yc&CC?4)m$<+2L7YSMh1! zv$GJz%h>0{w{PAnOt2f`p}YaW3&7giVv$)L8v$D05=}x6>qE`+v>g9%D^sUrT}XDv z9m!2q5^#tvgZAX@@ZhjJje&g8-P1sC=<+(_mFBZ0xB=vKCIi0Jp~5;WMVM*VuC`q2 z?CtVcK?@&}1-}C}Y9tQLM5NVpHK-3nun(fA7Q%KN;_3!p*p!zRULB7Q>Zn4CVLkgK zK?MpZw2+Xjl&n)+6I+zn z+IrZ{E+Tccy*l3_6H!ML-5MuoC$4;96{db+;;@z%VJQh zW!H1R_IrO}rgw(}rs3mF*;UvD$M~(j^fH*t45lYgxz9jb_ADcq%b6hwjgs)munhQh zLpk~(74cHQ2hqK9Ikcw~6n+lWyZGJT7iu*6MJJWW5`)Fzg8XnbT9Fgg;4mufwJ(yi)k-~Mmkr!?iWw`S5tr?X`KKj)}CD6Di|8fe`cKNa^@pf zZ*w0+UM2vy<6R}R#Ci zSfGqx_t+JJuPzcUrct?}n2Nv8qfzHy9TsdIQR=Rfxg*9BydHm+>>O%Y7kyE8tr}OTC8V4gv?8qx5@9Rn<+IE>Rdl4j`S8B; zN4TmJhcep-_^f41_?pSMxX6*K=}I22X%z~-p#szjrJ(guBulx0!;q3;EugB1)6Kk_ zcc`V&o$c+6wI4Eb31R(0GR%&|)us07tn5FUJ0PEwt@Q^7(=I{7+tq!BPQ30_iJx@F z8%1aikQZ zENcM?_WFyNZDl~{Bc-QeUV{K(C8FhS{%KbBBPoBusa_cEF$!{)YF0rq>FcI%?r!{k zx~ku=*%7bly-(FT(of(nGw(L-9q2hwb#6k0A2bqfHRmPy*%rhP)8MY&w7e9O8Oa|_V8f+FujYV2 zrq^?2=gd@A&2gM)Moz3n8yc3qU2y%?>(`BO|9wvDUpJ)8uFusL!Ip--9%oG>^Tu-W z^0Lc^@j1;x;cA(voCeNXq!mBHp!5oCa>5g|;U0*V3u@4?;M1V|0AR6E`hvO459@AI z(3+Dy9U8mG$Iol}r^hykoW(17MGm>kc_)cGLSjiWWb))sRB#aCzv)H74j(huvGtzc z>q@kgX_QY-&vyf5rxnU$ag;o}f%ZBS#J=2a7f^<3kCLq%*-!>T zG)i!(eI3!=NXPT$XZL#uFjQLefO7YEQ2(TyQG;7$nud7$gH3ZReoTt$08gyQj_h9b zYYM@_=NB^LDtdqdIs%qsg!UH_BKis%^|1}%8oR^m(7>&t5d3M@R;+!8c5boy0teQ6 zd-YiFLjTfK&KH3Za^T;l@LlRRzT6$$u9h@L*lD#@I9(`A4Ydqe@18_oFG>loEL*T! zs)_2XU9T#6rWlgM#f{H5;9u(yvGmp8PG^sz;oM{`sYYJjrv+vy`IkNIH0TJvQH$0| zeN|a-t>5yl<$;ixlxJvI@u@K>BVfqgr5T;i-MAv*AYq>lvhC`Zcep+jycs&8x>nd} zX?h*W+AzC|@-kCC143p*6{YR?ao@If>h#RF?K|sHexOlU{KcTc0w=i(1v1`bn~ z4E>7>)fgS#4q73-F94>zD&c=mVwXXovAlQ1?e{8l60?OeMlcW~-)5(v#;*HCs7Y5pUb$@*g|ddg&iPUd@!OO4|@L!6RoZ}TBfP^Y^h!WTyz zDSdDZpRTyTIIMd?V=B}v+{28w#WYUUhY9HbTlu4Lns5XJ1?ebF&b3twwDz`x%_fvT z^dWW-+h_TC!^bMHrt#|gImXgks!j4g@KW?U>BdP*%Wp&FT}GvuS|sfB_CVJi+EXN# z2yuC%nbn%4MG+$zqM-jrO5mQGyAr1gs*`P;xq71-1Ti1mLiZiy$>rVu>@PP$z?LNi zPVg5gXXEQEC+t880|W8v#&5cpvYqLZ;)!68HAz0%gojh5eLJz9x>PCk*Jw{PuP9S+ zQg!L`jq}RIAg>it8?p=)8dr1j>&A{E&wHuGif1)CLM>Nw&(rshQLVx?9=moIVd@(n z;UrVJNhGbOAGIpfssGPIG-ka^nO3iVwOgOkRw16c-q#3D z9Tal#>ueBxUw+@EuPJsi`hZ7Ka4Dhn)g>|~J87jPs>6c0H~u9&P6o2-Gh>FfODA_U zTaQyD+X=KpmHeS?+UbTZ`jp4cR{LPevK*W6?sFYB_Z<1Kzm!DpN^jq#xCJjzmV{m~ zt(2lys5n<1V|nq1XEyDIKnn8_6Im!xQY1mvsAl7sLld&ZvNS?I+_OUMbRJ>OiwApbTJyMXplJcyV0W5fEYhahpf0`oLQq%iiAveF}g%a<|)0Jhp z+x=|$&GM4vA5=;mi5JPRGv%#R3!C5(jx6sB#MP}WR=1&I2b5;hG=^o0tn799WA((v zbs>+@1#X|^qSIMKagkXu8j=BLG-20Xdlv6*)ADKFNw5F(CIA>G_`P?fq6%I-a1=3v zygf2&NQk-Y2c!_rngA{#Ao{Uq5v$2BP1iu*6OUY@xqGJu`fFz zqyje*)oeAW`sC-BKfT(x97&0^zkThV>R zw<{WO;~B=p2FzAKNZF$`fTWf{{47)SPNcP*`fQk%`$*v0Kplm2^^y@aab?)w?F7%{ zvJJAFA>;`-`!#E!pDhi@h<<%7^Vx9R{R&ulro%EzU*h6A5p*8bj!KX_9*y+h=SaBr zE>G!guiEly;oXNe&>K=KC$O6G1{~!L9;HFM>srdIGzd*kab{8Y1H}nkolWJ#Gb3H8 zCTerbgY8o|DRFx<*rNvE3VfOA4o=^OYIb>*uG0ElJW#+=f_P1K8vIH&yU_~(JA{;! zpd>4qR|>5xW8Hei{9aFN3_fZYAC-Lev0_t-Wjjpdf^JEhN#RPUBDu@smUGR^Aaq(8T5oky`KntPwM%yWi*G)aNVSJ}A``k|pDvqJu|ab%_K!V=h7PGfhzb z&RnjBv%$-8X*yV!j5H->_#WaYV1c8>n==+z>WM6+S3 z=Qc82Gi$bL4AcB*+mU?h0&}#!t6=l&TGOumY9+KrGP%ReeAzvL%9_)(y)>_R?oj@IiP=)!kij{nUwiv{y3MZgs*s?^(x_A@ao9+Y9&`(7*TXezAHA+e$zU&Z!on@n(3TLtDD)*#Mf>}#N zw(+Gv&+ZgQGx&y-g61{-zZE@_$xdlql6l|?^U13iB|Jk3DYNV=?(jWcRboweU(qn*;K`Bw z>S^Zfvj6Ey_(-|$KuTgsYK&SpaqY1!PLqA>l=Q1Lf)-X<2I|p$ba_*sLaD`8=lz9(4c60mQbWoR<;6Th2g|p^;-6 zOuB#5!3IA@S#d-GvH*b`r`{vuCjns1i|l(;wT$6CCpZ$*n@q0?4T;y( zo^=Se&XptZ@F(*=;p0S-iTDNgzIC@HS2AB}GCY%_-{&Wt0*L7W6uiSx45LYc^Sn}q zmm;6|Ju`@a((gELL$_~aureCP{y^Q;uq2BnJo-fD>Yke6%NV9HjijV0&JDyA9@r&v ztq^O;>jUanI=yfD9E{q&BN+7S25@`1^%m~^dsFg5iAt`yXUm>RN)mAM5%@Gh{S>?R z?=Q^iI&M;Rx798ATS*(AcUK9e*-(DODGRH=C5A-b_vfUP)~azuU; z*Cz5Y;@Z|inKegZ-rJ#cf_Ki2v%kIgXjM(*X_Gej5km}swvFSu#+RU8 z2+s=Ezr=KPM6}XbCRj>?|BW$@ff{#wFD$bp+DF?As$h0J-V57ACQg6<^dLTR2;T`3 z9N6{G4>TUoyNe*#m9^-yjx_fiu71eBvy2e1{-LE+cY?KesWAve*eeYGOT?a(`JlLlfdhoT z_X&*?=@93ql{P*;9)~CyMOW~=zq(g<$5iyI^xLr+0_fGm?_}XHaXllff=-F+wuwmx ztrsAC1R{KQ4P{@uj#c4O*jj4+dS^KXY)Q|eDY00xAdyGFQfo6>HnMePMZQP#p?~AC z57@T%itHAYGMq4^<6x{p_O=l0J;@t3dA|>yH8rNa8S_dz5s&g7S%lM@)s<4C{5~K# zVq&uLX-k{{-sq*WS7LRPO?=TNQ<0C6H4GTrhJKT9=>nZQp&{@~bh$rvHubE2$77o} z%JWvKPia1$hq!C<{UrF2>%v94E^xPgBq(eJuZHx)BFD}7YVM)ME!aXl3jTpo(=tk0 zCX@i1?KV-}d=NJS2yI<@;h}9)XydSAH?7n1LXQgOI#ydNKao;^?r%k|-kq8vC3rmg zlA-rP9W}n%|FNs@MAg!(Zs0-}v*SKm`oP@kLBJG;K8U{b_{Fn(!fsk3ptbLx9wkIh zPQ({kaB@A)X~%h#2{Hf z7-&z+;lGzg=SwDcE~x-nT5hVo`UxGu{kh!k)YtA<+q3PsLU67#2i=&GXpvgu5L0_C(oT>IO+^j7h z9l`52Qc4mjv-}>RhGlEuD)k+s(y(WUjd=VjufQ0!<@~PV{Jw5unJSiW@|N*tjK+RE z?z*2g2YhLBAZrJ>t0Vbo$5n|ta-7!@gMH!1#P~_2X{7uGK=_CfiPVIL z*6p|&s){r+dBytuaCt6$soNiPC^AY|`};Rm<{GHbhm88-yN(vj%oY&v&JOJ|O}b_r zYPcf1Tb|fz1sl#Zk!Pr@WC`I0S0ma)0OTP=pMMq;W;YT5{kzP3+AwFXv)%%OVVA+6 z`G@q0)kJ|dabrssVPk^slbAxW7+G2+DnRBR^CXnX`?Kc?+m@_y%#MQDR1qQ@vQAlu zn?ds)6)hl965Xl~>wTT`_=fraB+aw2a;Pc^OdXyh4W_ndv-YIML&5+|&rD)|w-X)D zVxPyx#8$=BYBabSC&R5fY%)iP3GXe`@GECBBOR|Wk{HWE! z4W;_N1r|f+n{-d@Hocd}Z_s{GteLT`C7|dlc{w6JJ%{bc;F*MBDNNR}#6pxlP#wm8 z!)QE4vlQ>E=lhcmu!Q12c1Ua;NHG4^$!EtUQAyJ*FtKm>^|>hP9@*;-9A10EU|Reh zn?@BMZP$+2+1Y8HBR1M_soXHH2YGt(-B{P1V={iTvD;9`NE4rSj+$_c{=)(7JQ0LW zl1u#dACVu7x?3y~#sois_~Dl+fNR&p)~v@rQN=o4pUm2x$7`1p)8bDSnpgim6lo^> z$o}o=!+)2>iaQiAIM2LIYJx+pU+i|c|1!2|`e4vy{QaFT(R>jIh|A^hvGjjwjA8yK ze9SH!nf0?=TfKlr-#|w@e_*r8c-P`v2YT{z{42hu3&wc;d36VtYo-?{@dMK@H_Xdv z$rOg-*jf*JM#yiD#Z-lU)*PRpzIZ0UU(NGe6ymZh2^X8T7b|WFMUN?jU+);`q5bjlf(Pu9bi5Z%!iCOxyB(4 zAOw1yjr*pqols^CdpRX9fT4>|7?B<>tDKMOOXUzOKP;#m(V| zuDSKCaw+{cVNgrQs@`7}0 zyAWPs{?bFg-}n60Ki0IOcB(do65^MODPWJ9TX9%~qXkb@;nXp;p{K|cEORE&w< zIO160_$W)fZU&I$9w^}7kToab_a8HsCQDvJBa{9hADmGHFOH5E!T8bD_!~i!=-jmT zyql)9>lr>VetmjEMC=43OV6--R(;P3F?<%@N1X0rrGDZcLG+h_^JCqw%hQ=pW{d9c zoHYUEreL`2$*Dha&Dw`D$=-3vfIKEpt0N_M2$}mAezc#BMOt0`_Qrtk^%dv$ghoa=}%nnp)-sAP^|GaItzluUu zTKVHh-B~$&=0B7iO!wwEl-<9s{yv)fqCbpjYko zI(jV&N*5qqHYrR#I~qRH-h&CX9~=&?z#LgbL*tcC(Mw0XaQdEEw}4i!5_>#hFD z=u1d3`xdj>6bQb8Y(*v|OOl_`B7H9+>X z|JUCC8GBMt`C)oCt&yj#lx!Yv4?~=Wfc(&v9_x)d5d-7sH*pBAvUfRZF3ujn+CKwa z(AjGvFj4lNORzHi!_NyV=1%<(ZCn(1nG$@5T(N@~RWh{3gBTNu4S<%63BWcelUdtWi9m;h1!)-2-!P3=^mwbcaum3AkXFpKkiynmSMMXx^f^}ktl`GfmxtTmn zdr!C3PoxHsZBJ{0B+b6MYXJ2eF&(2!XES9lQ+=YJ+*=Ev7^+?DnQzjLf;_E5Qh1WR zWvQoY@uF6kh`U?*t)+6fHtr}Hi?|FB3~Br~&hZI+4?|W)&02nL>=+pEcv-|)s5um* z-GnWP(K()8R!{~+Ti6SNx~N@sr^bmZqr*&RuWt~%4RwL#b zSki=MQln7N#w|T z#oMI=*9#=AVrHy{opFELb$ILSAjCf@Q)}2pOFeC`eplFWDYBGb4c9$OSHyfZLuCqs z8<@wCB@{@GA&}}0tq*Is|HA?uW`V~U_6%2)9qewC88%c?Bl2KEre!Pm1W*6b6N)ja zd!(vQf}WR{P`0)b;?jewJAJaiJ6(iwv6C4qOGf8qEhS1aEGZPDEbS1R8*UyCBSSP| zT>S1GsKkuomNoZ^Q$gNv`+f14VDAZks1TfcI#Qfw4C;jJr|ek08_13`19a~w7#kNN z3(e!Z;FF_h4onzp%Z9YDh%dFuXSI2Xvs5wUZsYOhw?ns~E*dEdI1PK9AQ_J`04a@3 z|GKeJ7)`eJJz&ozw(@BUmV|JBWh@q^9uQrhXfwJw zIP5ftlBQ84D5loC$T;WVX@n;S6*vFG!+;fKDzj=VVj3tD3r0KkcYz zVqzD=t=(ea)FN@~QIBCWFj$$m-j?@FsSvZ~vp}9~)r}XNLzc&Nl*Tj$MJ*c$4}KWM zpb|x6+@r%L>kLD<{7##!#b^})F5L^(oH{$}h}tnxt|`%tkU&pWkTzwxH!*#EMsLn3 zkP3rD)|+IW7z$4wv#0fS-r<2WusUvs3-19fniA!c`g9UTY}mPfYk-85Qn22~Q`l-~tf^^zkD&kJyER-+(Q34_z^L@Z7U zx*OJgcGa;&7A$yr++DCy6?CaX7JjqsU3~aSnmQ92D{@}^%Hh#_=`l1 zY%QWKFw>tSE(lJ^JrD?Vn?66TPpO#Jd4m8QA(Ub2f2MIR41Wm;zW?A;!hdF_LUy-o_0jEq{=&1e8c#i*Bf+_f=);VsYtp!}l!A%X zgh_qji55g_bI9g|KnibNFGIk>9X@8qpAfV0;EI6bix+eOrs(!#hRa(XWlIrABY|k! zc>692^`pkL0EhTN;LfK<64ud9?s~0T-FQ|+0|a?YY+&LoY;mlV-(*xV61z0iIqL)j za$nBrDDW`6uIAKr%w={F=pqK5i@Bfo zo*dCV;@CWwO%FB*xYRDSL3=D^hm>P!E)z5r{{6=Vo7Sk2`>2|OPXO*EDG zEQBEO$!ui@gLT$*n|vAJ@2mD(zUT01lkO$Um(G3Ku=?7K>KG#iYCNx-_RH#g`C*7* z?K;6C92D;f=AwaX6bGizYjrES^tL%d3W~DE8(OtW+@VI);**hG(wCx{ zW8L^lu{8U#tizUvh1bgM+4zcc5ix8B?3&-U3^N$Q&A%@k^#`Rc}aEDf(OyLMG5mg z&jub}Ci)eYjd(5}Entp94hH)w*cyq7AkZ#jf4;il;=$$PsYv}d z7$vBY*_!KnSc=Q+2(#_eP|>ShKn@|RDE?dTeHduO*3na#{F=$YNZQE0=DtlDmh94R ze;u#pOLgcV3o!})Y>vEq;oT{iP%V9t)3~`{PB zxxht2T`{DX(AA0R5!WzPO;+iKQN=1V>QiB|L5}VC#OnJ%0|8fge8sFlzhk;Z?^E@? z*pp9K*DKOMbM16E1&3uF-pT5?Xk2fi3|DX0S_l&M%n^*(3%2QfYz~<%rdqS zZi7ZisLRbt#JeAb`b(8bJoQax?F6l$N00Pq9mT6>Xf19(rHkom9urfb73D!)W`8VW zsAX8v`o+L~R;mPNor;a@)yDO$oe_tS&Q9o-+}hPcH9TVbfV8dRD!p5Gs}&mTV~QK9 zGi0Z&D7uQVG&lP7R)0ZwLDjDt4S#>&1epn*xnjmrADu9)1kD*Y+*9Fk#+FogWlx6; zzUI_|ncR^#+{HB`Vxp}RYI=dt3q~vH>O0(`*S*HcqBEgogWD;k=Jt3n{|YTWbK}qM zhL^OAxvtaIrw`~v-S*Dpx@_iWH)J`+tdeN44;D`4(t*GX3|7AlO0dE-6=uv1 zJkZ7_8HcB%EqwNODYP)xM>X7hRd3(y1O7Y;OV9*BLU6U<)t<~%tC2O=Na;9+lwUU< zLuv5@B_%1PFBk|FDr=E}%ZK^!vH4dP$~YO;hW?%f2}g_j*zQrL1-4wiL^b*e^5349 zdwfxSU)$4<#+x?gFz&!odtqZ5L?5X&ggw7b_{n?Jf|<^`Zp-|c?ePGmuy1aawiQGS zo|4Ql`Mf*M{Y8(h&o zPAo6`X9K24|5iSTXFsmziQF5&8NtHxoOt0fNZoJQXxJ6VW+m%GmGr7h`4JTR+{_J!h{n%X7@8z{l>1NB72c@V5!9OLJ7EIB_qe24;-nWY}#X3 zbv=1JpFAh1@&xPo2GW1T$n#tAVg+BQX1Im&sfsi4ygsruF7-|<9e=nal%SmTbx~kC zX+#s$NDBn?ULHgOVOrX|7f+{0U%xXHOpXH|@7O*t=rtd>o}&d(9WM<(Z`oio2t8en zv;*nztu`EGGWd`fowg^sqtLMM`9L-1E!^+JU7*W=~) zy+oIjX_Cd|rKkx>kz5?gI*q0D&6Jk#xgS7buaT*ln@;a; z%Qzvyp&*(`S+q`Iy~{yApzvzY$GKD2s4c6YIF*p@r6mx9pCSA_DG#+2+&oN&vVDig6Wg1Mac%N*G3DFCuHYn=Z2vK z``i%#s~quX(|S|bZDoZzyAvjnaKY5+YS#3w?n4L3QTW&dgZlF9uBWFz%L4==z;Sa#e)%)H*WA7Zl zu^nqe*mgn>RzJLiCw*BJIeEHp8ts&9q_?^!x7zEl*srYFjG~20~Ol+&o0{gFwlq?zWYrp zinej*$0#101Z3;6x`p~58^9Vp&VXw%5L{SM%ei<|@pU^=H#N|&MZ(7F?B1wRm|4?z zwJib};_!`_%)1(8@Br6E#%tzqvf2!tO{+G7K`=O)<@}|J30~{V3x778lVa5 z9m6{zc3~)@?+w;B2iOBeuEMjcjG8%rrHKRmw{W7=0Os?Fq-dG zS9dI-F-r{)hu9#^;c4|}4J7adz&b+7wbSa)o|bd27^C5G%g|}-6d1hoOy}A*R)}uq zl))CUz)MT5NzmB#$1fuW?EKE=tM8-8@~mL~Y;9 zt-KnCp@*?g74Sxg zIZ1^jbyGAsU}+enyIJyh@N@6ac-Bw=N)DI0k^_|A@@ao^iZjrNWva&663j%XJemA; zg$0F>v7F@d)Et*Os)Jd6&{^VC3QtUZy~Y2b?yaNZYL|XNTmpgM9tiI49^BnESa56H z2@>4h-JuEY5Zv9}-CY{U^n2tx=UeCAnLBINtaWeqAA9fW+K+VauBYnvloUjjXA>Se z1VL-}%8l2aKkRK~BbrKbM5eST3!zAxWx{$#($MUUN8rI!5Mn4n&rf z(Xc$I>^Kpt@qG_l*>*CsxmzSLcB(+dW7V>uEJy8rqT$yh10AHlo$e6?nwx5<)XQ)=Uch(h1ClIkp?uE=mO0453!JUm_WJOvoIV>c%~nUI1xwpl+F(w>m+(rgaK<4g z2V>@itus12ldJiAvUuNaB&Q#^90;QV8Tpgl%!eF9295qjLn?_L+HN~UGy#x7L^sSy za<6`B7%dn#D}CoV2Lllis6|H1XG!(eJYiHT`)fCv0*W(N^<9bvZ5j00dL0`ln&F35 zEJgB#?|h#4huIcaw@KtPKHg0R=3c6^_wzanc|)=cgDjsbWobKo1$pQjIq(M>1md_w zh)RyR<>8` zJ8He!uE;~!SON=Dv=+{+?qklLw?_FXxaYWd_o~>#D-4%!Ty0kaGOGey62=nVV&;b( zrnQMwDALBg!{;uXe3GOZC!1ljgP%GqZ*Mc~wHHq)EG0;PoiI{G^;#9lM zcTZWfsEwjZLkCD5pT7Kp@%puAkgtF26BIzV0_q^jDCwX&SJ~BB-a15<(JW`PzO4}OhN4jhrlbC>SN#fCXjr7MhC4nFz zB2I^4>llQmz?W8ya&ZyzQGkP6SttJ4V9iSarW{^te@S4;-E>4QH1 z9|#lrDG#!doa(%+D5<3=MX(Q)W=7HBzSA#b+ME5b^SD><2+Vmq!2;W=Gzg~{cFVmJ~ZQWmhvzzAzL)=t&0<#`J6GcflZTw ztTBz7y_?Kr1f&po*|gQ=lN}LBsAaeSwb`7emY7*z5!6J%a$;2R9IVVjsDzer<(Oj#p+WYZ|S_5l+NDv z&_I643G0t&Btkt+jm^GkWBrQJ`NB?|mso*Iwv1>xcE=?e+d(of6^$~2sT*BJin9vA zCSEbH6G)uq+562F9QTtOatsw)Q;9tAXp$2?UPf&G5E^-ySkDswd3bxK>YZcR)TJt~FTdSHeV+k;7fA6vh4b4_p z#u&WdVdq>2R?1aVRv8;?elBtAx}?97G@Z*Vpp{?88~wT5KPyu?)4P(rk5JsCZ!NdC zKV5w*KlO3BT~#KdE+-oZ;vNQ@1_o6IXhKl+Qygc7hVtK4>f;73-uv7pCt(|r`LHGq zce-ZT#)Hiq?Qb?G^OU!*(zwiXbQXBdOYrj>)gM%i*Y!3EGV82SV^YXImH;ZvgN(6r zX;6scS(Fpx4LZ4i#rDAw2W}Ov?G?T2d0MIksjF(djr~R^b?Mv$c^kyC` z&W5(e5+x?SJAJU(utNnnY8S7=?^)c#(yQ?mH*`8)$KxwqsmYjJ?VMTb$s2;m}#jUeOewC=T40ZjFgyf1LI52<)ork6onu^*z;I4(B zjSIYfl0bnKD9hhA{YFUcXn? zWZHQl6X;iTeR~+-iEI))n69^eQ2vT+(%Wf9GdvPLqrYmU=A^1zb931C{@n)y(s5Z= zJ2R27iX(*V4ackLf?imGUoYXD{Cu8?lo(}S@79*VTBK}}(G8=%_Cn|*!_l<5Z+TWb z^`KMdJe_9({ptTV}Sp^cL=uyEq5q?X2cr=>$I^=5uz1J};fC3JAN&@1u*g^;1e` z<|ueOMsXR5Or}CWPlk0)7Bjs4p^OA(tLN7`Uwujo=lgy^uLKXD)bakTTFO$OeREq% z)r^Z45t%ld-o9c0AZUkuhco{*cF^{wwm$kt=(BQpmDQ_SwfPd)z{p;N-j6XwvwO_) zVM4mPk~S~*1P(%v&*q*p*Gn}+61@>ECNBLeKjC@XZPdJGm-#dMmfSA9Pr*szR=`P_ z4)DE_X;_|d31Cigv_spkigvYi(vKvq35R!!tA{gcz=63;L&5iKc=i-B2{a?5nW-_ zj*I=G`lC8;W2t)mgWwo)+?at5P|=K284V*y;nO4`k6z)UAH|j#y`47Z#<2IRFvQdx z1O)#`Up$9NLZV7Vda=FY*ir@tST4b)R7P9#llkr}z_Il^sYVo=r{Is``*7ZTS(zBk z9A3MtC3Zx z1!o{WQgxTr6{HN`A?;SE+^wO{f4}XRS>u!?;*`+KR5U40>A>1VAAobO0mx=6fS20? zJyLnSEGkPdFb3(9xS-4StN4b;JDIMOhijL`en?;lTzclZd#Xy4tMQOlXH+SL02Z9C zuxmsB5snSXm1vdBSE{*+P8s*YXE<*>5LN;`qxE>pksp1Sr+7v2K*V)TzN}UayAZ`& znJrlD$%B%8rLqD;FO!x7O=;xgb#L84_1NWJ%F?mcOb+i=^^cLI8yuFo4joK=fPwqn zN|6YtP3Ek2-;a~t$3?Mha`ZkWl_dvdKhE^PwQ*G>?W%ox|DaF=P-lAk;?p=D72i-s zc8&gQpim5zd1d`+F`2_=7@xGk*EAGg7TrqrHA0d=ffel4$s~8J=~%NN`-_(mgyQ7Y zNi&k3@y_%GPJzFXw&HwzRN2IQ7zq`A>~}#QpVV-q!E>GDR`(lK(g z@$7#fDBr6$e0t2fNDPA~X8kB@&B-+Ed=ehA_#aS(!q+IqzLhp!mf^ECTx_EzTiJSv zx7HjuMim&~Jkk}o@n@!D?kXU)Z#0&9oG$JF%mdGhSA5lguL3BYhoKqNE86Xntn!8_ zHIa{=>4{B5MFQMK^XA+9bn~0H^z=R&GbKde)Hz^p;_i)K4*+ofnI>mfe)KGbXEUAY zpx6vTX(cXt@ZOiSvVmXye z508pLTd9k%hzzvq#R{VlpnbP5Oel1*V%oBeRx&j;V@O!WCPBunNYRf~lxp8OOy*mI zpKdMh1>R&He;}?IrkwVA#~ICNk63rl$u#wC%A6}X9orI@=?hs4$YX*uy#-#;qY8}2 zP0m_B;J-HIJzQFW-fv8yd)K15d1asHCUAK$%M~_Nvb&8g_Zv$A03+g1XMmf4=47eD z!`Of-4w7zEzjUl7*GPl=Rs!VG0!27usqr>Q(A;yhO!Ab=HB&)BdcAVuF6pG=a5d>w zy7*9&EWLj>hlr|CV`8yW=%ggT9gd$cHk$KXq7*1d)IGAd{({z#oD{)Zf4?22&sLx& zQ8E@u;o+#yp=IA;HMHce=4ckz@%WL_-mp#wMMIPAXTG=GQz{4I2=A?OK~GziJ?2sA z^;KaktA@pw$hrrJ8RNemU#ybtE!IQ~N+;Z6G&ynfw{8t$i~ul_%!3ha#q z4BE@R-@;ISRITJ5+nY{n+ey;3;Y<>~!hcB5q4$GzQLmO~=U+ohPt@tOUX-T;)+?aK zfM|XGdN8xt7U&<)WCt@wjNSML_u9qMV4ZVx8+@V%Xn&fRFIDW-VHV|K`Rc@WO}bHe z>GbNC)a_SI;@DtxU_~FUBc}aCX3wK(t4jINyCh3qoMFXqzVr1#Prjw`L+#>^$>2ya zO{!Wi3=3ryY*J8xGOF+@CN}%b$?DVMkxQke{NymxkN)Kwx0(iBO1{sa8KyS;&VG57 zi+Mw%9IEFUBOl2}SEqB(=os#3h&}1(*tuB!uS=SZJPl*V<;!&4UT`v;o_;}OLJ3h$Yvdv-R@lzb5U>JlmYI41+@+~GI!E>& z*?CjKTjHznResErQ{74rQEELWsvgZg@lk982I-xWZYet{fs|b0krjktD-Q#6YR^n? zQ*c$Qby|Z-6k8B5*znL!V{B-l-r-%^r%Pc^PkaX*BkI7Kzv3b0!1>X<B&n15OfkOPC?-FfnY$R&XsuU4IRSdVq3(dLo zKGSw~s2;QSvbG#g5>mmf*d&qBbA!04n`}~@ao)@BFW*`*ZobUOiI1TwIxMYa8YHz| z6_}b2OMAfO{s$reBMwm0DUWcirS-}m*?h{*?@%#!?YDw&+gnCctE#>;*GZN>8#N&h z-`8x5P!M~Lea|_$-#QTp?oqT|TH3j)9Xl)mI1O{3sP6eG&ylmq=0IW^gV&ydIJ0QeOK8KfuHwZWwkKfYI;`0+ClM<`^Yz z{IBR9|NofU|2c%x){=TkB$S%3qi17#QMjAFM7uc~X2-6bsdCU7YH$1#+UmZCV2SAw z!Iuv-w+^JUJM^(gTfK8p{Lsm*VlxE#Vq*(-V&{MpJR|T6d&3?wU67$OyY*`lVQD+R z=NQSPeQDerH3S`p3RhH=?`^!$h5x4Uo}oM1;tuF_!?U z50`1N$)6xTp(KNSA`6`y!P$IC{?GXh{$r$M-zsfgN_4A?rAz}UHVKj{`ZZ|*KOY+A zqr8lU-=N}kZKHY4ldHx9SiB3w@|Dsr-`Ry2t0xJ2SN;tcXKHB;GYe7=n!)+}6RFX5qm0 zxlS;eA*P)tDF_hi&}vkxv%(R|ijz7ZcWtsQ6g{yC&|0qs_64PL^$0Wc zq%?h@olC_}CAhW4_#a>U|GoqfR*sr^D|!9~+7fH^wMzM$c3)V-*-9_YkDUwsN37I* z8rTh$63vMt*y(Fm=98A_nPd2K; z!?&Sq9)|Yf+3MXh-cDHx6}*g#VVn`HpHmI40=JMR`Wll&9_nVv#0-jlj)Cts2B6dJ z0xDWX0!78nRvcr;9>+6Otd)bFfesGsCF^1q9W8mgkGi38@EV=H z(>-MX#fYJdMBC9w)KwJdHKknK%G;;(NG^66;4qBEBc>AE5V+28`O%5(iXycwF8+b( zqhj3M=GAVbfpm*FIEg=cXLg2r+M%uSY(G<2hI~oK@~Us_s57?Kyw;=Z({7Fsx?kIc z2QI7a?`@!3SyD9TFnOc9)I63zLe7E+@7Ivks?9b_HWp5B$Q}=VrD0`zHLcgW1NY{2 z^7F$J5hc$QOBrulL&s*=={4@v!EPq&O{dgRe(Q0oi|BugVsGV3;RB>tfJm^WC?@eWc6&#dKwO3q_-&nCRv2n=MRWsRpB0#Sf<-u~R5kIRJ zflt0xE%a-A?x`TcZPp|TqlQ9F?5zaWA^WwVV0iz2Amp zYoLY)uVYv;?m8*UH%&5MgiJt@<4*UWD9j-&L54zoeZ{jW`OYpyRY^&N1kgaCXz%_s zd0|5!^>JYT%-Nf-E@p5~x)miEr#LB|ii7?NtX|o9YAL-yU?N z<5LJ25I679NW}qEJGze2b`vNxv=szqXZu*HgA}s!<2i^X453o2>KipYUQcezkMtd) zLgB-^bdn->7#)>j8Z~R>H2vqus@{x*lQ?vz%0-v#wvw!iB@-iL z`nl%!dH=VuUL1IfnsL>3%beQ4wfd&I z{ZWj!G&HQo3xZcu_}*2#&J(UKqZQ;Kr-n^0bS^Nwukf>@V*7rfquEM%Uh=Kbybtp8 zNg>6?+L=Fiiho;zPnlDn&RTovSSSHEz-NCQwnRUqT(ABeOXD;$3*jYQvZM=%S9M>? zkAVjLXISyb9a3j~5hEObAefQpmoY)&RO7pI44mA}?-?iVr*d_Qs0K8t9peD1MAZ&I zq?j(dh76Z9axjvS*?Df*3@v@_aU+}VWc%ExF3u2l$q-tQQh1Vvf0o_Wv2IV3%G5fvr0?1Vwdxi?_~9rlaUMi%n_Vf_ciBX zi)^lseH&7+?eX!SkZAV!q9Kjw4)*S729FE2%}D5k!b|wv1SG4M^VR(vS-qOvnVwbR z6hq(C_k8tjInQK2A>2S*;t(2Np)LjQ>xcWB8`_fUKj=6mVL#ycez0=_URZS!+tCZ} z+V9wWbj5|KZ@Z3-HT0)I^|+OlPev6Cd+96fz5utlma@frjT zsHZzCKH&9F4hmp+#IFy`nWGc8vR}U>?+?>*UH84VF?Z#o-ui~FU=U=9oicWXJTC9>Pua{?t&dF?RJ8yqpr`bPPr6ee_&vhf&20WBhiZ+!6oz}<< zCE8MqWu6yQF1CL6;r$LIlz*UeV+3ipx*BM~Z}_=Apgtd|B-xDOa}8e0q`6f%u9Le>N^8UGmZyZC zNDPLUSI4~S`fz3ybWf|q6dX~V4W~I5d;N0Dsu$5Qn}8YU`K~7goBfsb&6rbzl{#5% zVR_0pmS!LYz4bF)-Hh{!`CctU($4Qav3}3ud!C{T3Gx#Q^VV5rJSa`ym4)YES zS}nhF^2&|+^G*sP$a3g&F4-Bi=51$RT)TXBXyTImGR>kOXDcx9X&?JFRa#oqyzl_1 z4-)iW2ookAl-s4mz&$*Y+jY0gX6hO_p55H!nKA!t!p1Mb7C^KLto%j58{Ap|opA&K zYYT@TaDp;8iC8$LgXkg}BUOv8i+-L)9(%8%4wX=3otG3s2|1O+3{O4!Hheu!cgU-G zlog%w&186Z-PrwSj!UZ_YY332EwN!dc*fXmRzQ|ZE*AY{ti%qa)h=T6gGASbmQ|B` zH4Q5KbA`dJLdOjiR|Uj9Cg(7rTtt0;U5Mr1uq4uNT(c*Hl_+k(q~lpH~zN& z6ooARCJIIE?VQc*oSjHmS;15l5+->wQ%fTedv_9D@HI0DCkrbH7Y{3mJ_(bO5dh3d z!t)my%&21KWbXnnF>@mMOQedsJ4>oMgT?9Jt|XaBxc<&2CKuHx z1Pcil`#(;>v;G&e62RU>)eJl!U2u|JQ{6S0p|w2M_yyllUFFtKsA=Xg-(KrRKd>E?xdCYV&gEb@G8i zzaJQJ7q;&I1gef8(5R%ym9@ElqS$=A5?(gyg9XI~DT4k~qdhfIEdbKC$w?4NwSjyNM z7>M)zEU*Vk_}#Ke{N@6Z#UV{)H*CaCSTqJhmx22rHp;5jB)`VIa;nwTn8zk!!&gfF zx`&7N+YD;byMc;TP_=!xo#DnG4-ng7&-?zv`z2R*8ejmCN;X1@;U{7>re-JmkunYt zPJhp7>f3{K&^OxDEf34-UPeX^Ez02f34OPz-usiq(ou&S`?4?06dkeOjidMX@p;e@ z5l%s%=o;>RE!uIYCetYYiG{3^MXvK@KjETfI2(yN5jA|W97hUAXh$c|A00`fo;rJw zn++SlFQ?+ooM`KC>3vDi_Ybh?azHremr%^6s;>9i z)NFQi{cPrHh+-hRL;58od+-57X!)^SNP$pv*+P^V$Y>pN*~h{Tyi7_8BH@GT@$B$Q z!k=}NRA2Ru_utTrp(`HZ-+AQY_d1{4wcC*#xKtK#-Bf?2Mwx^|5Ojv`_qxxfj*qs;|4`RJ*9v@>`qc7So1}H*ESz4+Hp4SUn z1%DMPr+rSOQ|RBvTCZPWnh+4uJqekj#v^JAJE6H|hayrgS08>9z4fwGhSPsd33f8qCd?H*OF!6U4 zx~!rVjm?7i4L82vkCfNQBg=V33z6^iQmL=>RtP2a`_wokr@^dVKrJ)ym$f*V0wYkK zJ;;QddzW1I-brC$&bT-MSddoOLol$If84xnlcX63oH;w1da8r1`Aj7t1#QhneHL+z zf>x{YTi_;_;y11x1i20x@aqFn0bDi4Tm8yQ1T&KVeY~SlBiY~w_r@@r(sQ`>w=C~R z@lOpTY~m#Nt7PHYcuGgqeTy7V+D6$#OiJ3y*jH~Bw#2ndh?kBEBIZ9F^q4W`@|RzD z2RLkSIQ{YU0_T|hLXo84RrHi4zf62^mvI-9{`8H|+?kcQ73bNh2T||mu(aO%Yzjf;FF6da!fX1H?ob<4cE_K3Lm`yhE#&cVp=1Q{1H2S2 zGj`rPb?|C?NQo(Kq@5N)J)F=o4mq$Cj?z@^hEQtrkgOQrAm|xx47Ab1kkX#1F4ZfAUl=Ge*SArng{ zQkvzorSHkx0;SJQtCBn!YM5G_-Sh;x--8lIt%BN#Q28kBw@?z@bRWkt=@sFhi}sAR zQWM2Rwk6j0NHZAjR~<^OS*>u6uXB4}m?SW4F~wCiF{D${75%OC#P<~@aZMVV6HG+N zjwU~gdJe*r|Hd*|Tfd>F=5)u7)TwLFwZ35{ht5Mt{mx2FEl=5l=|9D4Ns>K8_#4VB zcI-&qw!vkJAxlu3Y&A$(w@1>-^m~g$@i*+@dW`{^fYo1(?7-}n`_>irU!YR6<}{=E zQdhV?=$(-+Y^2W!&8@AfrgHfsyd%+ss}E6OZK{ENY#>M6&$8W$AV$8gA?H90bd zf;mhP+m%{-zxb=LAT#br)%|>Ztz?!?h-rN47cB?H_SoTxoD?A90K*G$9a!nUMiXy| zF3uAABDDP$&_&R2+xVOfFgw6sCPHqqjMN@g3zCm?u}P1GMTbwMGPCO;npI3q!Yy`& zW35cn`yL@%%Qx6WiCyu+tt((Hld4KX4MX+$XA+_n1ta{0^-Lb~Jxs`|nwN+_vky#= zDB4%CJknl%x`sV^7^cDlCF8O(4o8><5-PPAKb z`M5SuF(XA|{IG0E#zAHgb&)@pZz#)@AYDl5MMvl>g%YNPkntV*19qkU9q+W5CQgW2 zKhL+9=^@ojsw4)9@5Tca{nJM$={K1?H6wpWj2>AAY!7dLpA|A@>j5jZ+}Kak?u0~n zxpLYMm82raT1*Vjhvhd%pS+m@icDr;u0!1-A#$&EeM9a8+oEogcbZc?-<;nuQAAd` z+O#8QqdVDQaGt*CLZJlv zK?M{Wi6~M_Otvx&xu-LILRF37*fy{gR)RGoXCb`<^5-8!8AF0==qP>u-4hkdzEXaW zgUB>^9H(Shb(%x#Z&0(3w2#jQ(q`TfZ=I)Cj?Hg*ZkF0TB~TqEdW?2?>S!h6XupPO zQ4(zzhua;~kq8<@`}Rio%hBh~*UDg395)>XCCEO|G=idmL|wIrM^-u8V{RJlYzI!5 z$V!vZY`>KpH?-`IHe?7s>2T+TW&LX?=*OKg?&V%3S;;8JT(J)}Ar(KH6_(blL-uc^ zmiEV9+AkxsphvOZ1F_{vS&)D~whC~`MTN6<6(eV+m*SYRa{d*Ox z`eL$9N9C+(U6LBE;6QaQzoJZcb_M^LD+rAkMEa2u_Kss=h#2l;;Z_*zYglfYlM6bW_ab%&}vpAtT5SnJ}WXpa(M=Mo8uzMz^9kD+V`C3unN3x(o zuBjlRjif-Oo;F56Y<{+G&H2+OLK@4j$_#J5A^Sy?DM_-Ugq(1hS4$xTL6AxFCd>o_2h_w80W*g|O zzewt$0{mrZY51if#%$}|=jmy+=MQ|;6+6yzqtRYfs0r=J1Lm~ zMD1-I?Ct)tBe+SJMD4*KtEz*M30Qj-c{os{xGcoW9!wY{6~(7hoeM zs`gK~M#{|6+`{=UGlNOh#n}087Qo+(gnya?{~S7#rllzu*I{L4`7exzotu;6-!%R| zOMkW?KFLT(OF%$ELO?)*-w=ORAw(hIU|`{3Vc_6k;o#xn5I%hR@BtC=111V8@+TZj zTwEMXY;1fY3SxW$GD2)@5_%FcN-7#!8a!eKW(I0z3ThhazZ!vrhll@w@B!n)2MlU_ zY<%kf*RManA*4FApi715I{gcL;m&p7yJbW4-10;1r7dC{1XHu zG&B?xECLKN9Q0o-kWkPt5U^-)= zv2n=R9Dj%!2X=#-!Tk5u|K87ERJ4EV^B>d|2xM?KP-xI-5JC_IGCQVAN3BBdUuG0W zBOFrDs`&AgvahUUqrO0Xz3~(;LL|G=8VR9yDknVGgu`l5n{X+ksN(CY3M%4DX=DSS zN>1jK?nv@G!7opwm>%hlWyntqoWHCe;N27nHqKgUYRee<*wfHBcdB3_1;O5V|3YCi zY^<1Cq-*2Nrl@^iZ-vXV39|*F%I#=q$-?CMkP1tSTEJ3}-*D4R2vb}6hF!#x8g~tXwpsnMX#po z*KQ6JDxH%3Roaa!+F6xwMK5=7;$)Lc&{kXvnNG_i%E{Dy@Um zFh||wQR`X^=Z_8Z>Doc$^)(&Z1|ri#U$lgzU}6>KC)7{YX~#>dxZn=-DY!^wQwS<( z4DcQl9UgU8s$|5Pt#Kp-zv4J`YFSxQUaw;U!Z)4<&uW!TSh^1+s4j;2S= zkPoW{EQ{z;XU?T$I?z}OHfd>fqF1#FNt|A4K{a6Mk!Z;z{`SUUs}dNCLSvaUU<@Y(c{zh(pf|TDROh;s%LU( zR0r19!#z>x!L|%~RVgk4d>SweUspvR*hCk+I*ztTG0I|@I@!Es`{@8E>R%;a;z(my z?i%eK4Y4MADRL65e@}GZbitK?zK|#>LZy?0*5KcZ!tkh3tlThDf^}j>W?zXGfTar` z>S@GmD(AY>Xu^!Il6uAVbz%4w)};j{U%HyqNNN&*Lz+^$HoImpRq4DDhsN_M^Vds z5?hc%>^dCCppAN0j*bDXnt`UlDNS+3+o+U7QFU@(z4ANx@mzMq)8Z zjc#3qag~`8mH41f*wHdd6Wfso5jI2;o1ZQ;wUulU>PN%-m>Vxp81C|thIDYIlc4~> zOsK4PAmT_HHE+HC$SKR)SCpqaoV}F`#L$$y0bK;g50SmU6KMt!NZKW59#BTiicpB# zzbno^!VF~gS*DnB59)=UsW%7pgfA*Of|8)X22Dk zY&8iy=gOGTZ}s6b3x!eg)`Q;hV)Q=gDw1NNDAI4mM8Oy4%r@}=vc$fx_#z?0t;F61 zQ}hid-v%{bXtduazVz+I0;O>=;SxGdtfT$w4D=#wTh=Zj>u8W`S}|Bw9dp|mWK_$! zc?jZJ0RqYa*70u@_M##ux>YTy*r3Locs~aA3y@86br}`xLOB4xpTH#Pm?O%K)?S z+-wWqF)+Htp<>dXdM`i6ze8>|#&BGRYzR=iLU-A!9pxr_R7VP4A2V$cfh=wfaea1Y z41e=I%qxV$C?K9#XID+J0GsBS%T8iJbo6A#D1(@BKN8L`A5|tPqfeIJ-p!+1%cijC zcNiWu{nD@*SPB`jj|5ziW-?t(jgLk!;owl`tV&eIMV}>(nF7Y%^MpN8A~qf@bCRpi z3&z?F9_!>@8~px0j{oNmD&Ir~vCkTjlBU;{i`VUt%}vV?8%wcZNJ@W9*6&n0xAb*h zxM=p6J<;ZZw)Yq0AHN=-*53p&I>V9kD`k~!)I&K41X8Bb2nBY`9{qs`>c2`*z=Rd4 zr+=qDwPss%$1fiLz@_WUi|4x9A(MvM;nz?yMyHKVdIgCB|O0wB}vtaSd=h z$hnjw#G2FmsNG9IbaBnrZe<{dhw6thPFw)BMH+;%axJ z#^vr_m#BFXt436x?PWZ#&*?FCrv}C~Zz?^cNSF576HPlRgJm zYugq^+VZd3?CnBMN-nR}X{*dN6s<;vV9{EaojKlTR>r(ZPAkqO7J5;my{7Y3m^?mb z^Pa?bG;>%s$TmxhRv6P+dHkN?sPQhh$F=2M)@TS<69 zfQxNF-6tsQL}Gghb|0B1Q|{Rz@6J=ZbrYrOYg~`5vW;uM5gt(6oNqS49rv^r=d1d> zOBt<+h8r-xI(G9AI=DbR;?WFWj+6O@5%ZLL$API<43m*h|G>@Z6<#&ke6reSz9CEP zsQ<}x=NN+i6N-*BJW;MW8A-5Cc*2@}%F>L9wtDGYZ|K}{J>$WdE3c%Me)F&t&FXaU zrH%@M6rKzKMT!^uT++#E+a{3mAWe>=jHrQ+L%uP)eo@I~FZdfwFnl9PV$i<)E;PB4 z3XM~k&)P|K(CC%Alv|4`2W4&0n$K5SdJFuTA(pkE(37LVwD3ue#$RfLs%3{ckC-g6 z0Vxv{k51*C7);&j@Hp^ZCDVT(5F@rJ+gupyYmOs|IBWW|TkF@6)Om-73?F+ zZ*vlQU$ssdsKi1DYhaDK0h7vv&s*8w-h7CKfE`$S(`~PH0+j3TfV4LI@1AC^O6nFx zc2rWHjA5ClOngKgXQZO%)J3)uszb7;Fix-xI4F|e+0H5{&t3W88fQOR!Ws7g+~gOv zehQ0Di_$82d;=(>{1nzcJdMl#9uOri&yb$(GAi#dUFUvem$C;l?pW9`QySrQ>L@J} zuM(dUA9&}001=6f@;N)sx&Ep*c-q*?5>0%0C~hqt#4@L4sYIw`)YbiC*tU?olt%kS zTr>$bJ3M2xfoQxUxE47h-Hdsm&~@%?o^!=>R{!f_JeEH?=I5mV6^taVNaQ$eod3mN zFt$qeRrzvG^QNpRLCEpN@WI~wLY>lZC&o9wD@ndR4HN^;j#lS22>1~gNi=6o93*p< zq|eWKu`2yaNfi)&unX^kKe&zFPNAuY+}1ebhZwe%|KrEenBXpo;HUx*k=cM+J(RAt zOuSmW7s@;h&*y%$bB;8?%!}_)NP<(%N-@Qu3MgMpVhx2mF|o*M4Mh!I3g#AKr;$2$ zr0IB+sCAxl*}hKKSl9I8c!ve+W9`LWPz3;@r#2RH=m3sRBb=HdTb^jX2J|{fe#pHnVDSrXfdL@?DtP^psIX%hAl^^vPcWOnfW zu=PiB8yBy~=4`!0VBA=#6W@IHtiGBO;|UR!UB^fh4<*0ID8@XmDx-wVEORPwu;+Ft zHU(oWaQK&Cr3GWRxqhk+j%8E%3>*v@9;`oGrnCF%>SS$wY3`sw^6Y6NkF9?AT!mAF zY(%(GqmD{^Y;1nyx7fr&=;*#5XF!Gj`q#0{9HN6-<_!^3w#ow|{y(IT-RqC6 zGbxL6!EM>mi+gB)W6&Czi<#tx@LYyIIn-+>y2z1yrDO_9cgTG*D_%1D$h<;e2|+cRCnK7Ht44ZCGU*huC1hO0aQUMDgW|IBxeB8Yy_9Fz97nOeJ3xaQ0QN zd#u-T+r7y(-;}qE4RD3Rl&6Bt(&~LxdrIHkyRNg1>$P0togJi1`uQW=kt$aI$+IK_ z&sjkg^h!^=c}sldkUoSc@ni2j)h=TwHfD*T!juaqVs;@X$s+PDr_|>> z5SS`JLjlSh97kQ7K9*)$I}o(+JqV|!5tK8N-6q7rhEm%rQ}{->%S62^^r&t{ol6Tp z$RJB6eyu5Yf)JaQsngimZMGPpy-_pyh4!VhoI1DvF22pH1pYu4R4zac+&J!jj(^#@+eMTons!94}psY`|87%|<}h z(oxGUPd}!TA-Bv->b7gVr70HaA|844gnV%Zb-sT!^-(tE#vK+=Jz5}rm80=s$eF(- z;w#@8?EtiSosd4J60@hU6|t+W5VO-o>7D9aI@gko z+2us;Jk)&B`^G^kegcUJ%bGTvtqWsuxqbl!yOO{92Q|@C{PQY4U$*4q6yn)Z;S+X0 z6LetmBz$ZJ68G!N;P$0xq1JD)rcN#QSD=}g}D{U0iMbsyG6hVIB%f74uhmptQvcao@b@T8iGvedabG>7|vk<^Dx~v|V;O|}3-u=hk zT?%uA7ra_VY9hH2yNLu&b=S>CU51ZTy|t1D*r1K@sO(q~>z}R(=e&7Co$}$15Y=aL zO`@qsa2d{l8u7UBCRDb`w9tVjWxVRVtQhvtn9ot@tQ(Ea#VW;!-Rcs^p3# z1sdc-B^k~>ymd}RKW9~BIoT1Y>JUwmW%T%1SjUx6NGHXxJs+?>2DT{28RnM1UrcnsSFkZ_k7}Yv4WadmJ%!ft|rIqZ2ZY zmy6L$3sXN)Wi7I5YY!|64P=cnx|87~WSc{4&4UOnTw+*sm-O@M(XOC$F@Tkbn3_Nn zr1&YTi!AA^3gZu1Z|y>|Y4lsvICcglK+OezB=g5&RPRm=85@JE(u8!~Cm>rSutD@Z zYnCjeX4hde^b)V8NroSTR1wv`0YIv4M&#c0OS&~Av}qPCis(0*B9qBVSU>Q3r%e5% zts6IpWVo@Jz3Qd56BTJ8sE<#4^mhpzKE1dyPePjmB8!nWaw!bzC_*w$^yEiwEGv}^ zE%AX*F%Wa>OrGvfr&z*E#v~gXncUK;*&+~x&~sXD>;6tzJxr^_niZjyuTijpN5ZrZ zrN+X#l$ID2_$~)fKVt$3S((rwbGkvmo!9Y$sJI%56~?TaNd&fuo`WbOoN33Um?Eo^ z08Ls(Ph6wSfCQkBqC$a{Jt9|zIGto??t< zI+wJ(>ol&@=?{w9yv-vfm;jP2_Wz5zvjB?gTeCeHT!UL6K%mj!?!g*ppz+2+a7g3s zPSD^a1P_h7H5%N5yN2Kr+yVje`hVx%xtTXpQ}f=`ysAf0)kijP`mp<)y}tE3Ylq{W zgrVJjdKF?HR24(SM;v?0kAfarD~eWtr*R4i@e+agyh2Mg(Ex)#y{-GdK2jDmmi0QM?9G5>&yRU)Yt!d5*pq= zK6$EuSpP;zMppOhHN(CL_8KNm*`5$CPE1VeYX-B9Nzx%CTR0|84wx;3u=o#{zKrISka=!5y78b9ziOO}0g6s_Zm7fYRE>G&F;1wo0_Xb`_r8dA^0M9EwVxDC zULG5fexM8Wi8YU$6c`(Tlz4?ijURd!xvHeOz2cM2qrh@bUrOr>2}hfw!v7kO6}+4N zda0IiNbJ_RCx*qErtCM${1ip?zqgkDa(Di5CH|+iB#hYl{{Ytd2cd<4wf@0v{kLGP z|J_geyNSe&@RN9j{`QvsQ$OjiCjU4W|5JVv?|;!x;ztn0|6qni`1t;0hW~%?la!DP z{*9kRgYc97<|zH?C!wKZqN4oeHi7@eP(nq);ez-s69Tpa+&cK zGf)}GrPS-HU^{nRj$euX2>hP8h}rUz|2WCPqAUz?+ao-W-I1#`a)+b5a`HwXN~oV= z3)}~QtA}`;C025CX}^f-K4hdekV^3E5;h%bYb%0fiNn!RsFYWmNRoWmDHvcgnbOHr zhb0NUBb&7Q&N0^U(}F@-mdJeyJ5n79E_=Jegh>^p$Y{*IQz~0oI<_^-M?=kH8Jm^; zDqSF1r$I0hrTfnETe4Qad~gsJBPs>euZWZ^#-3%`Sj1y-8ith>mcYH4fb+Ffx1R&; zMxB(jT1mXl?(`AT9+J2|LA?BT6#AAr@V1Pg#UOqxoJw5N;|Tcz)AxwXeB=F!yfWYfDNf)t-a zVV0;M-C*YjBn6I7oYItEEgC#2a%)1?b3h#{l5LIV*6el>92E=t&V*9x$=5+89 z7$q!nJ3N;JA8TL1=9x0 zEgMdG54gaSRqtvn?2lxIc4<>Fsuvy%%7)h1z)utWk{TlEVIam%t0X?8G}Z#gzt`wpePW$oZ0QvTcV>BQ95^3geSeYy-Q zco_;rmL_yg;0s}Qhg2BYoP`3{-mW~}oW`=`T{JpwUl3}xIw&}2ZZb+qpjc(jov6+V zE^9%ORSqmvc3l0irxKc?fY_liKRsn+G=QQLG=Du)|%Wo6p*rKRr z-8!U003e)$i8w7fKv0M%IX3YJCB*I6u`!!v6O^G&@zL7ljLO$ zW4d8>mQ^|>t+AwQOl=NOG|B5XNP8%t@08-R#A8o9i`Hki-z2#gFu0$XVXvEcE(AHq z)O%JZwpw$G!FK}_TOC$c`7&;&GZZ_&usza_ozkXyyuUN_{?)qtU6N<{Hxl&B=RRO9 z%k9W%7}sCBwchHjFHNQco8h%p)`xW9ZS*2jW{?hI@`JqWXbK7fvB$b(w|W)%2#K{N zs@58Nomn-WYVK}Md3Vn6)KubBj&QQ!02dO$xeHyjHht)v_4;TWL&0bywsk;1yARML zVT5|Ba3-uVuN^2UgSLrGulwbp$f|RaJ@T#XazV;B!&Vo_!qi--n`%Rz*xb{Uf?^bH zKKN*+ZjT;>n<`_{!QmUPKn{Uo#)VcMB?yDc9i9-|cn5x2cv?=1LLe)qMD_77jMKDW zCC)ABomOEb$vc|H7RJv#PL`BAc<9J*PZk9NunmSmE=b@OqM7TtSIbxVXgg-0md-ey zjU|ZLKBineITjEF3<7PWBF9f9VOTO99*KCSmbL+qR!t)wnxqZMj?dVYaUdz$%(+Ex zLOR8iB&7%SRNvMIeDs+u5j$2jugQ{fXslz{1s{G|G732W2BBpF@^u;*6sz6nF&eXH z;nWc^ji#^#S}iye|E0d}z^`pfI5mzkWJN_;<_Lqurt>^XxQczQF+eh|?Hi|Vy#2L< zZIg79(up1=Uc;ycwk$0$1*{>BVT&_%U^=-J;?l$bOV8Wn@o#ECp&?JEl4Cm&h#+b! z2lS#8xc!vqOv=l|O*|{J=&f~9(ak^pTE_p;sZgNh;)Rf;U+RG73J!>q8Q6u46oT@S zm>3=X4Wg&8=12e4VP@@or+oq@N{;)Ixxasik6?VeBfL45SAg8EtaP514U+S&~twl`gKP_ZX0Fr*)_9qk!*hFg}HQx0~z ze<^r;oVk%n)r~P?r^ukyVB4%~u=dh~cDCUg z+34tyXkA4U7!W{7{e~-QN}T!4eUpbaBvKkF=G-EdBbvzuiwrq{3-7UKMjF{KeC0MimEe z%0@HLj2*bd8I)ah$zV6AuE7`7+S_V8ttq(O$egxb^z=89wM1*QVMHoz5ijK$P7pwf zuyLK-f&YTgzQ1!iST*HHCGeuzIg+R7HsTF%5@JW}BO5xrd!@=~+Bwq!6SPy@vDTU_(S)(RoU}ql~0FtGSC$+c#5I>q8lP)}=h5<_Z&zs;(%8 z{!dnn!JwDR4#Gi)BWp4$!R`C!V8Pqj%s7d{(SXzvs+RHkQf%^)S!Yf*IeRdp7kxi4 zewHZPiWtlnqI{6UR{O%%uzZYa^~caXmG6ym(lYggXJc7R5^-ii!7VgFydXiyOs-x- zXkf-eS+LLO^BQO6a?-jj_)|(aKbbZ$u`WKZc0sJQ2)*~Ami?^NRq0n8V$QlBqjGkJ z^Dl~y$9abE!WzT!lubx!!inoQCBkCCE^cvSo6r`@iOTU-QTKwj*~LK-=i>7TIB0MP z_>y{c_Em`t{p;5#qhy;XEEEpaOsdgehdc}eeFh9mRNlY!an|ikPKDBf#L%D2NtOjO zLc|I`+5xv4C|$^Y0=?;T8=Bh}$4;Nw>i56Qo0njn(rcb~Uo&5Qtq>}>$S>zi1VfyO z5!^NslEP()_sDVWxmWxpu*(2gtvxm41((Nic#AlDh{ce@S|P3T{Azq%Q~GRbg%aD! z(*_1?(37o{qb6sUP|p^7+qsgOB3X~ic%ye?u(|nngk9Z9O2YK-$M8@qNHnEW`=NSb zubk%2ilJ%>K5r$}If=nALC>}@ny>_462FHg*l(oOj&tavPyB&YLYCSc_mP^8Zivn= z_@i3KxaPmS=;%gc=^cN&75t4Pq4@V#9SAFN6JP1BeE`+s72a&|*U^t-JI{Hw)A|R} zf`jta-zet5`47RB+v5pYe0O?Bpjq9Z;)t}F6}>s!l_Gt;{Dok;^?Rll=3u$Vv^I+) zCXY82S8T_w4|^t$9a(q7sHy$q`{ELaSWjb`O2I(o?|MoSMeBJ zDmm-pI^M#p#&kbiReR;kcU`- zL0#i!x$4`_b$99nfj#Mp>~T3$UcQesEnai!=^SLbyF!DMS=hWYH+?FOKwDT@{p+x% ze1g~X){HPq>5j!pqK}CvM~zEJ3n1r3SzqT#w z$M7@tc`qsfpJ5|~gg*_pAXMO6mXZ9|Lxy~sE8Iv+Y1wxz(fOR+xLTzNRUxEG990)k zWOAe@U}igDt@7YowB9fHkq_Uys?BsJrz!h zRvbTpCEF?KU$nzd{2PhJ3$|DDzMjLE-)pmvTRzr5&wQ~olvm$>VA*UZ(?zt$kr@ZA zu{NccS=xiP6j<#yj4{S;?A{J{Y*~g5MzI++_W^+vm_G#*G{_EyXA&Ejd#x!oS6G&o~^%ld;Mz7dUeP169=2d`)w$bw>*<~+s_J?f4(8%(O)OuBj-1->`E)p z$_D5FJ{;ypICP_Q|N7stE0g~(?Qs05Rq?{!Q0M!vtUSS}#*xo+@XZ%We&~%Uq_myL zOZlP}Zeu>v4ZtS!dqm*6(Xr|NgpN&qG!|3*^Fu%jTob}y86D&PW|VvP=Hxi%8n!uUfWI2JUz~hWl^7gan90<={M(G5w&3>cmvp(Gy`-kGQs^~9quYGQ- zu1hOOh^wf6mhH`9RAu}|vJ?N;Mx}qfk^V1icLKqOI~_~!|7cV?Df2Z0-U50kxI$}X zzIfIDW|Q1npnl~hxEa~JR72)mo3;3x`?Hb8!Uyte-QwJX%0I4OFyom(2GLKKrb`*6 z70B{xUO6QWRGvEes-!83iH@1+S#Bko`S<)UncBkcEph>JXO0KpBp5EIGWwq91NU3m zE8SePW&dui?r&Z^S>ByLR7GK~i=a*#eN5%fZ~ zw6e?#=FY>h4Y6obflg(2Wf=x*OgHNdw8$(8T6DC-X4fqi)yLFdS`E@ocI;}6C-{rb*}VpJU>!<$YPCcNGA2u&#^AZkxaL$Y z4f@Q|`L}Lg5+imDv=b}OvipwqhFgx$W+W=dL( z(s4wrSOrEb_^WYbHDM|Z!%-A4b}uyCC4jA&zma^%JF0dO^WZH98-X_L^~j)P6iM!{ zNM5rsWhM*3iaTv2IQ6?p1k z_{P8i+ga+`b-4-FWUIO4%8<3*gpz!QV4Nr)L;} zRY*Tf1ug-cOqYOxG(|0Ve&f_ta@?vz_4oa!&>5d zJuWHp16tv=y)4kvV<8LWuutjhoXqmY!;~teIA9;TCZ*wcd}3#5XN6hbtIx)f4neEk zG9R&yFWqfrY2{opoNYDrRH3qU%Rhr90Cs2g9%@zk-?)iLizq$#JsFw%8sP>3f>(vW zW;?JaDWE=xL>Vv0*IBy>{4onJ%9%!`<{Ol&e#4g}6*ojmSRk)awb3q%(xPLn;q?4T3G@o5pV^S$}?Wn2W{zAMA!qAFM1W*5;$VD=ZU41)1XGn9!E3@ z?___!8XoL+0F`MkZ^>D5Mf4_VY$PPqO)?liQMYoHF=$<-U(7AFoYT^L&a4c~b~}>A zey6lj*~u$Cv_DrnQQs6+(SXh%2LOX)o(UI^!DchY_KPZY5hV{SSRq>Rq3!wV0bejH zfIf4xP|S6w&*cQytE==9H*I5?sr0+uH+a`nZ9QE_?|}BRM;6MXC!rM_Io;~u2N~+C z2zWY9dxzQ?)u!MB&nGv^>*BXHY``8Upx-1#H*R+byJs{3YiMY|tN=u6hjFDy%`If0 z>pf?kGkpesm627+f}h85k|TQlyJLWPLow6v+MNbnMH#wjI4=|Ejt z{E}Ej3j^%@0=U#<%(zf#pCj_+BISoB4=10!8T(2|DijAF0ar6te^-=jd4tqq@6UVH z4;{TF{QQlPVGI$ShHe|Qa{glt@;@|2e9q?UPGDUyQ&FGsJKZ1JKemefFRx8oM z)DI!IzRBCoObTcJ*y>GT#zbHInd!2m@4`gwOtY*edxN{&AYWbG&txU)tFxw|yZk$7 zW5J*!(=nIZ*jY0@il{;~mQH))5hOCIf0X$~0GP7Xq(PT`m^t%7Guj9jV96}Lu0i&6 zD~J$N39AB>*k&@ z)WejTn!}KHJ2`)Xb^DR#?N|{XiD$}|8KVQ=MWT$W_YCjws<*A2jWRgpb5Me4lKl?f zk6|vP`yh+g zrF^?-x!(4|B6Mz71E9i|=%DX8my3cBdLwN2Sfp(L@7yVmj#&)OI?j^KW2fC96%nZDlG$XRJP+h#Zx4| zY!95nOE6gq3Hm6Q;+uwcAE^&ZsNNj*va0UWs`;v9G_K$HK{hZT%4|vt${ObpE1Nsd zLvst%VyIquFezCU6%eOsG=!yNQZmqAXS#QmNAF7V*)x{?^mPpui@aOH{;2L>Bk&VT zmQnPZ#&_MvP)fA>-kDF~s}qm`bt$S{uu7e zxCY&zuey5@vovFCqYpMII`yR`q(hi8slniy^JXobZz;`5etWX5B;? zhU{Cyg;9Pb%+@XwpSJ)M%Ctol(E5OKsjzfCPTyTw11CDdpqQ(c`4?TT;TO|eTAM!?| zWusVFmFT@w{JQ!OV=k^G#F%Rll8?}m=}?50{86DPGyCUQ4A@%yDC;h?*U=!L1HlzK zs(IGTBe5g9UE5QWPzyqJC~4pn{vpCCv?RVN266-0&`K8O2~P8E6cT##{2JS31|qy0USjYuQp1f;I> z_Yl)#qg$+LDOkYFk&ewv4i7_U$jS;12gQUL{LCPJK{ikdH2rg2ODlUx^U&v@R@n_ z#>aUf2~m-49S-OtTey4PGL2Wq5O0RvJuGc2zwM`?ghioTDnUY3!E7hU$!=8-=sd`k zwPJ7zq-YF64C5RCrizg8o1i%{*(^@1JKJ}#PF~Hg(J8yX_|zM=iTMaO>d2@$c__n} z8#8Q?S)o`ISW2{i8H>55)y9tF5@fW~YOT0=Viu~zAGKX%eIZzyPFtJ#39+a@t93ab z9$Uwm-)9^5tqc`GBeuk$$Gr6=oYLL}U*gI{l-Ri>Y3&L zMis_8oJuLfxoy^vDZDcP#ukO4(OA{w8z&cO6;wbfU*SN?$+v5ZXwuV&C`bHyXd-n} zERf_3=q=TQ|y*Aj6GtAVa9LZ+uBrVKNdFi+s4Uo-;oRyUVnVtq!6F?;q zn3+6@1_|N?{0}vW=wTgMQa5~vn81*NGbi5fW&o``me&T|$`=;v>w%VvmsQB+nkO#q zPwG7TRqo-b3{!W4{jxKzVGZ;29^S8FktcNGqp=hz4CO@2!Yg>g8ke|BfEtNG3Dm+! z-lbLGO1^+!Kh3UwK0r##q&s}45*+ECoupe7_2~946}ZeK))ZWv7Ff`*pN3zF&_11p z3)3i1vwvCO=IT_j(yG`IjcV4l6! zqT9I1^P)tLjrWnymKEsh#0#@jv>6gEcXVBN-^wu3uyf_kZO8;sN;~u-T3c*GikRN^ zqd0FxWMA(`0$F)Dd1yl&?f9e4EAbgcl34|5Oq3bL>tPbe1FzykD?!Q`r#QEYkIgF` z(}=V6hq&cA(^6KQr*hJ#X!a6BO9xwvhB>%HS*kcut1W_))TPDn?Jpwld8b;if;h-} zU+AuuA>?YeWJeCWMCcg{>X}v+32`N{-{&)}Lj@@<9Z2dQH-ia)QN6f*H>BK#C38KrskkZ9o|2YM@ncU-)y6XvE19V!> z@Pw@74hN#@?CI^IaVchIXeT?Lk^qeGm9%5ch2FeQ+*^KUQbM;%_k&o1+8Jk-aXCL4 zbu~osvjc-qfv=lywbCWDmm4ucLjb5ASafks;RlIFlgC|*lW@XzutW<2e_dem5!@gz zRfGeVmbF)|R_Eoq!}HwZ+GJ)X90&$;pq%v)2{3fxTo6wiUHeM{2y1SKraTFu?{Pzo zO~9Vv)~E_#u%^JkoPTPXcEFRBBhwp8cwaT(Cq9ioqS#ti@UTjvLHEbnpUeM~du;f1 zE9>kX_AwlM98{9>1PZ=dHWiZ1(L5#2e_2iNCiyqg5s8K|!Z5?!b)%hQjz8)dsTk@L zctU%aaS9n~Ie=ue_-pddAW95&<|H}45>gGmQauwa?rfzUL zzC(Eyb9f0lGqi#ez=DRti+PkEjeSL;DKowl_)auX&ROW)k)6=CqR~hUh;QWGVV*J` z5(u2U%fER1D_1fh=U|Zzfdtc?w4m-|Jys>@;4S#CGR_Kn+vUpZivJ#pAs zl@smAte!3!={?{D!cP2;Vh{fU#r}az{ih(WfPl!q19_>1aKD^XeQ*tC{TGn;hnnCn z8BYC8BbEj|XU1b-Zpy2;t(pNk^&}_`|CrZ6zS0@Qeu!)px@66hWB2b zyr=u~k9Uk(Ti*s9YOFrKFq*vZ%_MHv!XT|l8o$td5V|y@#W5q0yo)9ev zd~T8r5(<~@f1*UZ2;FK8)#YkiVxI zC}l2-KN+eM$yPEc{K){6P|HZTpcz@pe1TfqD->;=BzZoT2^$LZez)aWtp1tjE74jl zRRPoE7ek#64rNcLsE`PwCdWRda6OK;PTd%>Xrmg`HZ)IJtQwB4ZDuSd?uls_>ZuKHVvd0GiN z@*5f`)_t>^p)0cmPjd{3b(Cy+m)}3}-xc+Yzb11%tlfj%SGhH@fBkB`a~HS6c4$+X z(G5x#%~Y5(duBRz%T`&!Cc1lEWe6yDyd0O0c9h+d!h)hr85|_;f z>Y<0hLg%C42&7=%s%IJF#8fClwvI_$T;D*A_|rk(Y51jCKXrgO2wi$ZPOqxzgMJB6TX}RaR}Ev`qsSG zawZ@{vwrw!-7PrIKR3yjG2XPiBbb$UdDO8m3P2cr7b9d8^o!N;*$VXo^bom)6O$Y<%->o+a%XGC0DZN=|e z+Cy7lc~Lbq3lIyHpIr2@y7^N%yF?jxc!p4;cS9#n72U_Gm%pwK0>jxk-%pQBxs4#t>^y7P+;bij65Dc0 zPJI%YESeO#;?q(c|BPk{#fwH-Z3I5&u)1%;&=(1H{OX1WQ4WDi6pIjXrNV1>`z2_( ze{7o_6Z>c{eqwyOwU?cjAlxoiV7SlS{JOx*hptu0GJW8``qp6o{I}NsxYzzq;mQBixEmfpzJJA&`Gk0Q{b>{jdFh;>jdDn555zWZcOqcr~?j^_-JZ zQtRp&`GjQ=nK!kQ(_~D7!41rEA$k7|DES}*WD9zs)~qniU8S+lUOrM2n_fP*qaEdZ znC?&Ypmn*@O+j3ViMZ5c)mVJ1GZ)Nl13f}~8ySJfpHtU!|d zk+5PE3{}Rpd1FMS?Ov+gu#$JN(Ns4@%mGZP1(Ze5nyI8Dt|;9J!INgf>YiGL@EG*r zeI9aO`92T8)OsOPV}XKdI2sC!39k|j)=N%bDV$|p;;3@f z<8PV=G)`lyU^$}ub+=V~*)qrI$V1{nU=e?-u(T&vRuNSQiEYkN2fll)l1l6FVy|+l zp!#kRoHY5GsW@#2bH`!}cjtq4R%(w(Es@)6+f}BOAw4XYr5T28%CC_YO@|I>@76B} z$r3PxD3uQ5Q*i$c>V9;vU3~6QoBm#!w`%Aw)csrheYC*=h+a9)eP-~DrCCVWI@VB&M3oq7YE9EQ+s#eFS*P|2`N4-sIAGCfN7HNt?QVO9xulYCgs`(hqNjiQ~Dg#W!&7(;@69J03$ zmr(jNTA!Y_#V_X}(x%cFMA%Tmj`Ke2Tc!p8?Eiyko~N!ptd#}l>fs9?Ufb58&osXH z%gty8vVL<|HEHV8_SDywuR^j5l4UGsZhUvrC(e(@YM^au@Y)|GX6!~!W~PW6vLQ}q zt3in&P9Tt?yU(F->fA(Mt!2&LbDpMGQGky`X&WnY=MZboa^ZxKgpK#wRT5(DqAjCO zuN(=uG%jbXV$yA@dJwZsU#zET)N|I>hV$wrIESSaF;@E4l~lmg19~jNC6^8yrYa|B zIF>&JnB(P@{NS|H>M96BT3AgDyJ5xMphq>bb>sawu1?M7Z#$TLRiy^9~+*-nwS zlo6wah!RVPxjtSwT#L*}v88vE@F|Aee5l~LP`+2GpU&0wr8#_-s`72-$DYMnE(nGiDDxmY z{ly~XZl<2kTw#*-=ZhpY+cU>eliDl(@n&P|?r}j;xtY_)Z4$C*#G|kUiUeFny7N>( zy4=X(`b!07zzi%MdH_zY>0>OxcvhC-J5|>e`ZX)^CaHt?2zkSV+wbkPlvUN;;4(kkB!7NN5Xyx&Lf8DDph8q9c-g&^6=PfadJ3ngu(qC6`6)DkX@Nk#fi zJVZrepUaK@Bg6ok77U(r+VV7)j4t)!_Ku!@#-G#Ms=DYn5I?pbUq7t^p&BX0QU=cu zrd(Z?0I^V~l;|?B-QFRxkQN=_PyiGzv)cFRLgqEf)Ikdmy-z?7k}xKerJJOL>d&`~GgpP2pVbZCR*G+DPddPx z5La#;GF~dKfJr696XQPpf>|{(k)q=E61Cz6Q5tE>&W5tj& zo#SWC=z1@OsP63U$D~YEe(kX=qSy)vGkf+)->)FtK?5~E_&}&ZU|zH9%Rn_`=Nk)I z#cDmstkqLgc4niW20tya1{pBUN&j7r4Fg^E^=ixdG+*~~Ak=v#ZR7`YHV3M+VNsjzV5U`O8iR`I-TS7#z`wUsUn#1hnM4r zSk{P;Y7*@GR04pt2xumzl=F0%AYwyN$)AB6X-V-V+7Ys`Xi#>RKP@|mxp6>1x3yeJ zcM;nxap4936q%u|a_2S&eiT5e)Jf*1__-H+r^>)5!+NE%?z{CTT80C!K$qyAm;k%0 z^pZmV;eF>^4kHbdu<7_^fw+%NDvkYGxDxh5(Ap^=SepR+6@0RQ%%#1_Jx-0ZL(o9eUkiMO^hh zusr8Wnp{lAN>66|fII}+jD-%0+&rAKiZ&Dx9@;p=V9;`OW@QmIRlTj!Gx?=$h&h`< za#yoOj|vhxSG3cbyx$0`h#bdi$U(w-WY}+N3q*;~qp;&S zQgpega80{(i`*Lf0h*%Vpq@4@BEp83!{WR@6XKT`i?DhKqLhHLU?e39 zBp-kwqMLzwehryMd1SbipT53eF?-nhtILfgQ%0#pZ1YZ!!fc$Fd(n~VSpnExm*GsT z&t#D9*oT(ik{e`>RDb3ySv<1QQU)ZZpwYb^NKIh|9A*dMe>c?D(EYx5Xy_BM@BIm% zWO1sn(40Vm6yb@-kBDj1Ai2Dlz)=Jsk>#I?)C~Zs=1<4w(tp#+674ftG89?Wc zmE!Vq{`6k_?kQ`2h?K^n*HA#UQN>ec8xn;a%E8K#f)N}{2vAvBgtBXYVwzh4vR1SA zi?k5DZ1j$hB6{N!6AUP4tISAGW8piaDZ_&>_DBbfgf^MSWo>@?xVNGKir>MN{IyaR zb#JsgTt|fae|X*@{?hnSQmda<=ylR>qz1)C;L#a~U`gc>ktjj8$PVulma^skrR{4` z`Hf^9F{AYnVm$jtdxJfHPoa024pY;XhKz>E4lz9K6+>EmzRM>EVVl%}H}WL3EQsR> z{10l>f0Ne#)4CZE{`y~wi4{QP(*AuaAOV4w{QsZnW<`YX{WB((_OC?Szl8HYl`}#& zqat!*vHlXyz`qM;R5W}{w7)6me+id{Lu6j`y4KqVgNVs}`No;Wufo?7<)Wtt8h>c1i9!hon~<7#SIJ`KigX zocv<8CAG81x22e&OIa&x%L_N=!pmO|Gj|=0tYJXSz_t~!XOaVDX*+mZYo$P-i9N*YL2XBe-5*s1GyNblGl@8?z0wJ<=8SMn9!-r0pvS>2W_H z=HP*J*WaY`;BTZ&xVI!iI^S{pC7o}iR0`K-_ua?Fk+XxZeC84=_+Yh7dRRp3VIMCj zpy(gWq*-0DG&H-FG#66Mn4SjfL+vZ+;%w(?$`iPhv&=&oRGQA0e*6$+xLB6h-VR7o zK+y@^M@qtav~!@8X*&RrGrO&&ZoNfr z>4XdLvIeyo+%Jt3oeJ}~WScPRsIDO!noQ(Yy7Gjb=HYfjm_hwj;rhx*LE)CN%ci>} zdyg6bX}i%|nQi65mSQ)QqNOE}==gwl1#yUtgs!Y#n?#hk8JSWRb+vtsoU>IZ5+0s$`9R>udzH zLv`T?S+N$Eosd#8GYH2L>utU(*u=RLR&dik5foNd1h(+-Dd50^G1!9$)VidD zH{)D24nI747`&GG==qBH@yla^U6#uD4Gp~o;bqvUl9Xr`db7z2D(_m^j|Hg25>HfGfHFC2}nUc?dfR$ds>YwJ7w_3K%j3lY|sw2hbXB(2p;b(7}G%4Dya z@~Z-&O%Qa5{K*dQ!Ga~?LM1#BbRKx`_np54>!a?d_eg{PR4oL0?wM(~&Y%OZ(w zf?KzNLhQK%2j=GJt7~!_{8mFqQwZf5M-n+7@<3?gw83ft?cI$nQy)E zL!xg&3AfyfKz*RUg>047qXCj90=1i@Gh**PPOOM)sqeAGiEkw7Ca-hC_yFf6iW`<# z(eQA8thJ*lb1(fSx=nji8G$x%bUn}9`s}S73nmS$pg5fGuJpLX0)Hbqpq{JBZr5=} zsI1`jNbWu7b&nS3Vf0t44DY$=8WkuTWQGvC3mmNz_8lYdXZ^n6etUykYco`3K!fea zrgJ7FDNU`q7ZY8XQbSkt5)H+N?#RPpZ|EsM?QrjXiokREVYRLzh_fxK+tsiQDHF^* zPf1f5&AscCpHjd+OFTxr_0vV>dt$~4KE`@^_aZ8-XrSTBQW6-=D>P7BScK%9ScL<4Jq_ zmszTvgJ0~D0BD*HEhAdkF|)Vk0SE;wwj$;AHK*(tD^BFyG}oYW{36jpnKM>6X>D#K zIMv*RjPLy{KeayqNFa4uNlq-V7TRzi;4HHD!cpj6xVGQbYC!iJY+7V7hrk#b@W%Ps zuI+E6EuJrTzT^@cZsSv5{(=aZP5#*79n~9{RrDJvq5s!G84yeFL#E>GQs6DFzv7U+ll@^_+bONj>&r0jG1&WlKAJdg+0>aa zUm6ub`eBq7ld@fN`S$MT!2C;=uqzPPZw1ZbpUK4yjpdE|22^jvaX9J~=`<`iHsJK^ zA~Ic9_oP-OdRP)?KT96>2Ci*rljEc)ZA^=kK|}pHvGv?D%B2+ur1C%C3OONkCm?r2 zP#47xeEb&gs&9Rl--w4aI6AXZ459X!&+GZ5`m#Q3xC>1N%*>+erod2AU}ynH#R3nT z(W1$qeXKN!gd>hVPa(`>PT-RdsoU;rX}e%-epA# z52_?i|T7LsCC7RzAqYeBQE0Rq5WQ*zE#)^>)X>*AGVrF*CnPoGr6nL? zg%T$&MX=6hEw>=^LBxO?Xy%er;lGo4v!o0Yb0+p4r}o0Yb0 z+qP}nwpo>V^ZU-$>Ammi-4SlyF+drVZ#ep7_gM@ddIvrkUO z@C(F2oaI!u;MV)`pP=HJ3&M2b3~-ExLJG{}6qMirLENHH?~-=$qVR5_e@wcG`lt1W zID53=n+i#`HYm4_o5yHH`+JJr*nI3LzDv9R^u3;rFK>x?Ji_{7^tXsA-ln^xB_)rZ z#Z)-u)XpW+&a+O6ll1nNdsRuHh_{|@ZPHkcHWSf0n1-iBr?P8|Cq%w0*=F+UjD5nJd&D<8{rHe$Z)T)@&MI%IiE||GvMWJLFgQ zFkjnF84jDrJXi!&hYRdxW4#FP9Cs`X>YGJtgx4Wc^hUdumQ(gMgVU|*(b^X8eWlmJ zeR0?}E9w`}FvI35C+Ccs-(uc2J>4@Y#CG9KjR6}xDUhOjyWy`!IY}8_Oe<+|AR%X5mVdb25sj&BhE;T({^T+Xk;G z$`LH0g|wS)2P3#3Cxd>5igW{uj@fiTf_L?$T<`A&+>TkFBk+(?XoUf-fkDAh_D$>Dv2gD~Ek=u*iI%B9Q);ep{V%Rg?pEu-AqkQ3T z8?Y)Vbjzpm>zM~7>zg4M_SI3}YxY`EdTUMna1Ooz!R)SV3IZaBC{)N-Yn*7AY9$Yk zZ8z2>4Pq(b(Crh9D9wm#$UQRZwkUD6$q0c!8NOBi{?QVdc0s=#{fyiB>PO89qs+z& zhZ`>Cof_#^dsY-0E{SQ`1Kkr4-FFH#HY-~v`OMJN5DF$SjyN$nQmnLO=mMz?9eW<4 z#7K*5f$x?Q3cXXK>2wNDJI902lyx_{0L;@5@cz*fKbT5 zbhxy#mhIF?fK*tvH_m^6G%J1(NLeh^9gUo}!nND}G)?}h$H}#G#~bTLeR=2{C3CrQ zud8z)N7PAFKdtk$&uxt0+Y$eBP!j&sMjNiL4#4i9lt zwMJbdKe`IZ;6_U$`NNFRpnSV?;Nhgu0edW1u~Y4q38}oOypyqjkQ;l%U9(e|Wl1|K z2solHR6!v!W09b8T}@E8;-v)lt__!@>a9x2gSvHf&dNS}0jjx5@FeIWaR^?^rzjM!y!N@4|UCDu6igi%}~Ep!elTVc-@boHOCHL{f)TG@M_J+BFbEy3NEiL!eW9 zbsUV|vH^GkD0Tn+i!WEG)<5o$NqtjY%giZTs;y?yYS$D9wdralR%yzDYez_CH;c(V z2`q7Giir0W)x>_N%t}B%2aQ@Tt~~i^&^+XafD0pPiEpyYcFWuFSi1c;fni>*P=)BR zf2;U=Hu_>l*#gCCeyQCit{quhHEx$;8*UT1N)bFc!HL^PU|TVM^Y+Xku@EfYX$JN6 zEoh!Fq3CjEwWXvm)rR3Fp8QFR^6TQ9^G$N~8cqs;em5yOzrxBSgx#dr%+Kcx;Q zYM(EH4791B92}UC+sm!eKLPWA8$~Z*vbKb7Gc4SqsuL}i{AdiS$^rX}1xz83>@QbQ zumi0NsBTjiy+x|%h4u$2;UBJ;{K|#o{M8ndG)uMfQ)(nq@u(ny1!ETnplvJchk4$(2g4#vR?f+l_nke@8ZmvUn)iT6CefmOTFYbees=? zl}lB^zw*twL_YyUtv=Su%K0nZqKi9<*V}}<&oh>% za%R$8F7j2Egy0g8oi_RPfZpDR-n)< z78_qA6b{8Q&&1D~kqhx~Q@OzaP5`Pl$#^MFCFDFb0?+rN0%n#b*|M2 z75t8)k-IF=KXMIj=Kr4!U()eib3QI)lQ*c_HV9cJ+xW2HAE>rI-uQ7%6ys3_o?A%9 zdZv&7d2i`W+`qew^y0rbwrHEWeg)IEmX}lmqz-UwKin@NXZ*X)nKnLodu#Yeah+8E zmEG(2g|`to-_z(ymyC{&2VSbIWoG!n;q!CtYeFIL--noG=JQ$qTT&!mBat=U$3(=U&#<&2v#4?* z^I24*wG@JjYtF8W{&Ri=;DgHJbAt~f?pk;ri7oFY-XnzsxW5m18sK}SbbDL*1W1*T z`}-Kh^}oH5oPR%>h2|6BUG`(a>!I*pQi}g9GyAJ?{67{qGqL|8pV2jAP)#!WkK*Qc z)rnTVhVR6GP>L@$AG5HiX13Nz`1~47-#+~m5Sil+F+7IEX4vlIgu>ur-%0|-@2`Px zCPg#6-|b(HW7M&AtzW))#mRU@-7U&)V+P~*f;Tb2{R!T9+eLSGkN3N$(z4l~Ml=Ah z8^|v}(loVi4QpkRk_#LOMcJ>*;Xsh5>*9jaX+o*$`Sa4~nXU07)w zIcgE1v$EGZu(P+z@7MFu>Kf(DfV`bcYd1c{%vmpc&O0tUE-^gs69$KwEz|aR1Ui1( z(~-f%UH%dGMjO8_1EwXHhqx>?Q?g$Hq5)4Oe<4+Jqpl5#g>(6qI9?`qnCRJ}SdP3iC!C2R7*UgqC2&ANPCD|b=XfX*}&Z z6NWvi%1m2D10iCybT@HvYB1lVj-~bO$}zP;Lar;77xyroS@g&v=TXZ|`RE+j z@R~xLl5l*RG%a?BrE^(jun~quW8JN|qn6~tUKs#Wi+Ej0d!ne*Mtrjmra~Ek;Kgg4 zB*kugQ%Klgh}FRK1u=}7a4M=gb&8tS7jrB>|IS|`yqqS0EXpAns>pcOJ3lyi5;N6Q ziOItX-F^k=Oag4ynzX*@G979+F-zQHC5A767*k39dJin#44Y1|QFK4Q?zfZxgk0;I5qg=K9-dUuDBFk^fVp1E|hnvkzOHDZF z_~oqqT48`4Y*X2n*|BYKxtg-}1wUtA*A!ogIjkzR}H_frYs8OBEWNv9o3{Js1gtm9GRinD_P_(0I z5Dw9Us7wG9=@6V~bGdC2C|jh<>g)#kcdG7hfm! zk^Vpu3{SW#u|d#~oB@y(2X5j(n{qhuxT>F(s4g04RN}2kn9dP>nZ9EF=5Y#SPNcr@}Z;)MGNo!v!fP#gf_y?<ATiSVONvZw)lQ0>=j&z?8_+Kh-BQ{>x-e#=jH}|A&(~{}yon ze+r-cRek)gv+n;~(7*Fb_~noO_cotJbqx!uRs`?o>XhRi^TIhC0o@CSj_GefzkG?> z;l=RNKjCHzCCXHqixv%RbfYmmqOP1i%ZQxfPmjS9yIHCA=?`7)ARMCmTobH1!b$Cfx^r2E#To+VeCPxm{|JiJ?SIpu#jIZ zw*q*bCFaf3K88g$>Pj~WpxEZO>fY>(z=XsETptdV^1Ne&}z3yoRoY`2)wNykTex6M18<7BuqgIVG2 z<$wlU^bJlgSxNC8r`{*0$lm(B*2+tZL&n0-CGP9r5v#ak8#Oo@Zx{5^t*sY_XXsE+ z<~ptC{>V8|fy~+1hb2oKu{pV6Kwz`zB}G;Dd#PFo>zYOedc?Ir9H~0B#@1ManQF>H zei!5VG#61L_KSnna@cO(?CBAtCh z(G{LvINJ7bg(Fm-jYZ0_hE02pbq>QgFOsWYpLM=epSIw0hW;po)r6%chfyf9i5{>o zoFg88{iJnwpg~1Vfd~ryIR^BuQ2>O&%RSRfwY z?Ca!R#)XhdKJ@&`Yk@Cl^tMe`|(u6R)vjvOrZcxrM;N41~ zW)wKy%KDe?@*Fwma!p`)WXxLUl;|HP%ZNqW)Plq|5Gh`rO%31QdW$*O2(F+}i}snA z6V170q{=e3vAN&`)C^-taFRfVQk2GI%zsbmGMZ{fu3-jolDBOCK14|QLdEIg2C0S& zBnNqhMaS_&cbq@Osz9OYXMlbvHhvCf>?5KyB|ZRq0$=_OzZNB*+2L?nT9~mHW_j`9 z0;ymp(6u%_3Xmmh3f(*GCj{~Y)lbfWiU|tN#0*3uu8$!mFZ#qZwek8=JwUbsXU^cx z2?3Lz5UR7yDzjHFHtlOnaK^K}-#3aLFroL~vC8sR%MTHJ%($(2bTH`DeGdVh5aF@5 zhCHi4k&FfEcU*J%1TLKA!^?@aVaB5KDENQIGU;FFQ}hU#H)TaFdlW6kD^j5v{i-0nQmxW{ctR51VWdOJhwm8V*2e z1PRunHkk2@vrNEQj1+NbuBwsy14S0!uQRMJ#272**8h_ws#3LCMN;Rndco@-UoW^nBQv#0WM{+$6|Oro z^Cwgg@Z^^IC0-B% zqbnN6e)=xG<`Sm-%AP-tdTEKZ&VIV9N35Q2ALNNA01hO1=q&uqm5D|(n9n~=Q1;^q zLP+H0a68{l;}>yi2RM>E1xu_|U&3-(WD5XI_|M+)r9X`laLR zAXcQ>E_pXRpMl$2ujJtdQsH(mQ2Ybb)N|XxNy-ry=wkD7p24jZ)fP+vmIR#h&RE?5 z!~RMcd7TO7)gH8U?>6jWyW|n~;h0R4g8P!5 zG0wC2u%pBJ7U-e6GRHmp_ARrtp2}Fn%Fp$X^a0Q46Am<|L@W5wS5b?8H}H<^?zmJF zn37nMms5uZOV&@|u0>9ef0l*+m~Zs=wza<`ssFzx3)%jw!R!xRCueVCplIaifUog& zUr6Lj=oz^>;?w>aY5tXo{^zaWUv9P-fRZjUwm zx+{{`X??hV-y`GW8-o0LU!R}ew)7!PP(xZS>fVN=;SPAzhvL=gwmjY2=FRGQ?`!7$ z=r;(co3oPXA!+fmUAk5zlZBsdmCVV$DJ~GEGov9I#y(&xC0qdJE!o|TaP%`VEs!|j z3qhp7#!5nfp8yD<95i9O*}T@wk-~USltb2 z(^Fr)!WE@MN@l9>U(+D|F%3RCnt{4IK3wgTGDVf%H#@JLgcJ9#!wev=CT(cwX;HA0 z5n|O4B}1I(4M>7TS7AZ4)J3p!*oinXK8FD9rF(=nJN0X+tL+6#f?o!g z39V|5k}LRSVI)>_+N?xzplgOUM@PJQyj*;(9iz0O?c;+eTIn~^u&GV2r6!c|=d%b= zN|PU3NB8a{VH2ioRpf$$xS(IU%SPYPJqi%+^GIi{?$f`H#>NB%&X~1#>4a zokYj!@=uk}M01o*Z}{w{S)o<7*{_kFJfu7^O4dqy#P{%~aGpwa|3?brf#Af1(FPMcRR!iOJwkh*??bCr@u9pN+qZaA=INRs|(WbKVo>Nl9U2=%@p@s;m)2;|I zrgAJnAx{KFpS9?TvYVH@5}AEv=hc|GZ$J9a+@Q`mnh*;Y`evN6 zmMO7#ma+q9Lh6Y)W%+b2hLJkM@nx&Z{A*K((HtZwU8ZzxO=rk+tMo(72g=(5EOhaZc*jp8Ld+JwQ+Z2GV1M2~5vT zjGz|MlyK7r8GSUNqzAGN?b8IVEmh2ws4m|yk$Ky>z(DnuMH3zJMTHkRHzHO5Op112 zr;O(Z7qOQqy21tAn_;$ZUcgo>2Bg0u(1A=HaT#q4knG*%kmF=fpfe`7-8j2?0xzV<=4!~Caf?TtNUx%U=!uEV8vB~vNW><7Y8ksC${e+H}wUgnsS4=w2lGQAA) zoj!+#kj=A&1Bq#K^D|uq@mYUs>=#VS+<+gC6OBy}U>`hX@=audD6{RIND)=k6fP8dS zgU|q?E2EdVlS%#Qya23hrK}0&X0Ix7KK9++?@@1phG6~LA(A?N;CNe`0^2tqZ@SA( z=U;DcMi%(PpP-=!f!DtniM?KyW6j(uIukZBHGHE%Ag6j`*F@v@y*+SURzc@*pv!fZ?C&<->*kCUG`4 z%Kre`-?;5TLc}ZDw-u8o-sA|J|f$CP_8!Yf2-rarKQ1VQeodV<+*7dI&_A_`hEPet|(x1GJhLKci zNlQ;gw4zh(am;DYZXz5hM87=&-VXiKyg%O$x0BiQ`6q$5KRjPAgHQ1=QKlxocs$?$ zr(T|TMKAZ~$K+lwPmhQDCSO~X(IdXj+OoJ8Aag5X=i|0YMX~sWvVz?+vXf8{Mp+|K zBVNi5n(*z}uJmsYVud1dV#mSFqom0-&T_d_tf1oP*Goz!vN z>?k-Czg0qJj}xMFp17lbU%b8D-O2=9KD-@*O1L8EAQr3M$+?f5K1QF4lFN&m$w^$E znw^xMo}Renn`8jHgTF9Fmb1~gO=d2OdjnM$POtrD>il@TJ9Wy&K`E#iqNt}Mrl*zR z;5TEH=)Dn&G$l(nNZ3g$h)E%0XwEBilOnd7%%+yC41ciW@|iYJvk(?U@fx&{Y7CZb zICn8AU+GVCnuDn3(iN?TL#13i8&JZnxv?98`jLb+-CFq(CzUwSpzTxk)KM@E5Ukd` z1bM!>k{d?~NOlX$FG5@hQ)ek*|IJIhtmG#ob$HaT>_rEPl({AePJ|ATZZxTDieIa) z>aTqJ7DsMl^t}-Im3WlFI6oJj9VbCrzZ$@w)C2|Q>QR~8ynYqZt(r-79;*c@m~N!SEIG^OQpp^m<(?S_>^w@P?zEvb32u}Ju@zuKE95Z3W>7GS z%Zm7lCMaVDotu7hXw&j1uLp#HCUI3WesE$knBdwMqbs!}Yp)S>d0KX7V>H&4vT89V zE7k{-GcERS3QXzE&FIJQqFpDu4xfFfT*CuO2u)-r4)8OVJFW9UoQDJ*<7n;v4Im!q+yM!e;0A+mFW1@%V9KveylHukRDSA zZz|*6Mbu>Qt)1`0=o1>jbyMnDn?GFhhqb0-b;p%9{?#wX#0;2>*(!;&+>;ZwhHcpj zO9W9PHLwfJmtK9#dezFjK}!^lbY&wX$ZF2iL~*Uc?|Apx^d?HrdTZ2gHkyUScNYv4 z%T;ozHCJ6Zx*@-~_x;u~(aTfx6y3dV7g zHx3^D)5cQlW%Qe?>T@9P2iddcGNY-4<&)B969825wCUv@hvK-x}a?8eVUfZhCQbN z4!ug~R$}H{@v*ihFwo1;g_=7Ca*!2OAzIU>N*M4-XA`aX@*t|iJvMeCG}P?iCmBnO zu5C#h^r{wb5t@z3o`b}r4^uFlq%)gg))ctt9g__$P*aI*XxOpMl|L=?q;q_{3ow34 zv;g*Pk^0X7)v`X6*v|m(&?QVgl=REkHoGVaSnTC;Z1nX8v>D|duahu&*YP=a7Fj3S zNDc9f+56k=X_f@YN1ZaceUWL_$F3Q_oIC|jKgUSDTO@+TyG^s=lIm*ZC z4c?eJZKCx`#F2(v=eYQd(Q!jp$mUUILc(eaSJGc5GzDL#taof6g?tUvl79A1Lt}SrlxYO+5fBqhaZ>YGC0CcBgRW=Xez( zpxH&uiz@XSwz~4{CF+^BByYLZJP1C3v+kH3&jLM5MZrSFs$#c5A7+Z*^~~&#lR0Hm|rg z)-*~I(4uKzN63XffuKi`JZ5+?t;0ib~UriEe>#D8z=enR2FIY7D(FQ-QULAW*SW!f~PYx!05V z!6HxUOU=h?S;QHR6QT7Ejqkj|ao5CR(uT(?*pZN5bfl42f-46C?cY$>MjR**`pHM5 zcs9;f6d*r{t=U|mmzLvQ!3H!vox=H(j}_Qf#_19XA#4+Axk5mXrkdg2%#Qr z_}usHYpb-{U>Rgp+fT()cPa>fuZ4WoN#DJncyU7V zK;%fTLSz(N675nOFC5eAVVz}Uw_ata3wZ>&j}$aVp+AE8g3fHkb->acIClcT3bni@ zk6qy)rp7AQn&WgXx0^uR3hJYRJ(M=XC?}7Dkf?H*&s3z;A%94 zj5cZiFo!F>xRxz>_Xfnqo2n5t$FrG|W_=&()_TFiQvwwHXXW)Txll}h;VJzeHrW0> z<;C_FcTa@j?_suI%ImKpjOjlj!v0+Gzq2t*&(6yD-$dA^#(LCOiIUf|>Pssha%>y0 zFrWu(`WJrj0eJ1JLJ9e+LW$2Q*Vr(Ut*OIWoe65Y0D(L%m~|2)is7U4=gScguFtFe z%YBRpl`igoC82!JXbbOLUXMctn_PA0<<6a;X z)P^pRIwy$uCv-voM*m#v^yRznxlD25P%KDou5W8{jzfs_^FY9@GBTlUoaHbwmw!w@<6qU9p5Txp8JbTBNl`vNdHm=Ns1_mx+sT^kekNDtpk?mzxa>$78)-A0Jl9U{BeoU~_4a zORW$%e9j(UR0(hZ-}9iEKmr{rTjj=ZIWPHB=tO#__HsT6zETyNdOHZhu@E_Sxiz+% zQnLA}Zvia=))IX>)L$u6rg6>2ZF(*{aCNcD9K{@%meRBGUF@XqqVFf;$b$PW0(Woq zDW5%hZYiSE!{R5-m-uY)t`tYrcwj)2u_>~lv@Szny`KC?$+@+Fzo{5^ko4cWX^r2G zJ^W(pv3h}CqVmjQk?ze>sZ{9`<$EWOH+_|TtsmOTjzv!F{Mo_RjPMbP4A^|gxCfvO zIZ1Sz+LPmSy+&bm)&Z7b`N)?9gqXMP+EvuLrR3*T+d-r^{}_IVrF8u0F8m|hHpi{v zv_5Ykx__)Lm?GHb3EVOB+O$!7?y9?JYd*yo$U$4fX>Z({VH57*{S+)8mGTGPEVi@y z`mO$QaG@oQpm|cnSM-;%{SZQTTNe?0Q+OqFZ6&;{IrbHFN1%waE#s->~8X zTyojeb1-H0(VK8ovPhF6<5fD>x!Ki5-=p#6I>2}Qmr*`sme$=3A`Y-z$%+UEz9Z#g z1->Ky*(3$_&V&MbMMwqV?fD-xN})1igea5Ys>(LRvMj)|L55R|gH}@&W%9g-jS|;= z5&51q7F+4e7y9%0MfU-IJhB(1`aeG~`LbvcvSv6tx}@T!L~zhzZL@9uXWh*1;WSxZStVfJWLsr)RL` z^|eQG~&bQ?LhVv9H1CHGi^vd3b!&2tU_r)q(@hki#rzqC6ruKaQFZbQOBxs_ybcCno4R+ z+HpD3gVNzuY~$1pBtjAN_eK{>g5(dK$!(p1bmM%@BmesA|2O~XYuD{h-{=2c z1^pLul2*aU!N$qnz{ufGKS|itQB=`U&(Y}5N1|Wu(qB~7|KLCUWg?L;hw86-=Sv0s z6`%Q~g8r(F{zEG0j}`y*Jp4~vlJxA%tp67kv}wK0g5342c;e2dhWmkp4z?n`aSj9c z1fZdz%LiWJ;iFq1Cc#uFi;BZ~n#LC@eTIGaD}I3#)AhwmbT|4@|7CxCH(St>o@gkj z8V|1flj#?Zdg|hS=jkUW;!xD{JiL$3J6!>s4lmx8&rbib4=@(PRC;eLMu-KHo0oqj zSEK8cmiZg=uO$Zpk_VjP{NvLXd=tyZpy~SESkX6l*NiN<>*?FA-Pd_PS-%J1L5z^ySBpI%tPC;RBavK0P8r5@Dlt7m_mz>J zQ~KY@yChDK%YrF|;#Q9)T5noc^WxtR?@pu9Zo3rUDyDYp&O5$uirFwsJG2Fp z&{v0%RGJLMIV9Sm4V(ud;$l+Jh0MEMF#XsQn`5k;2)7JkS2jkP6+)(ApY~8{?<)$w z%s0cMbTH%Ng=c? z|6a~0NhN{4g@j zFf8bId;jnNd{&bq$UYN$+#%oxrfR~}a$-cBEf)-k10+s^hX5LXk8Mi6akTjGqY5+hKu1si(M^OJBM zG6C0+m6DCEft~5n%by#xtRaZKQ69B9m1-1%i+0JBE?u$uWkvm2(Jr|!uBHG-QKNiSn#8}^qlm`5b_LS~98>e0Y&$bew<*Y= zCt&rGb!9$BFjEd(e{mmomF4>eB124UGscg`^RMysBmKN$`afIw9II7oByt3MA)$$b zdxQ0%-;SQmdf$bl>{WMh9QtM>5%$**9cAgSPn^l*1s!@dL&;~<(Vb0+z%^IRTUvwG zgfXyb+ z_(3r{(zfLL$8L64iy+gP8K_j(c)AW6eBkQDeYL6;11mJG^Y*uwhDsX$UaHTwqQT@n zU*or0KYYR2KYgdNac#R9ff4~_J!r3y8;k^z_$a)-YJ+LG?uubN{(k0S{Y`amUc z+@$LJ_;92M1AlX}*w1ndSo{g-N%VDw3853JP%*x5-cxi@gxLr}JZAXXdl@fi5D{ZB zC_<`3IJwlI#&tQ{xt&Cn3Q6DUyDSZEbxl8zBE47ZDrLf>^<~Kp?M6;CPjJzc#+m#s8aF^2y?`~+iRQyg=`OUGbPS&$B9vpr%P=Zwy(*8j3Ir%T`)T50OAV9Js?IpD_uS-~KBk`lXMnf2{WGLgKzq;e5r zw--J#^UcVEcgF{Xc*-Px@mbbBgK{-WxxGBBYTT=M&C11M+f`rNGG}NxbTLn^!goVY zAJ*#^dHG!m>Jl3y&b$N+ zH91Xmw6u`ykU3v7cdh0)f622vT_xc-FG(OdtryI$r>RG}ENylp>ixzObL|#8Jjx=j zBXmLTg~!|O9^rKzW_Wb~f@DX^F57gkj4)#AE?H3WW4cO}!o#k86eZeoO(MBr?Wibj zyXa8<{LGkTw`D$ulU)H(=^M=CxKhd3eKuQf6Jxy>~k$rkKDaBOcp z!EmTh7{VYNx~iT%71${#Ee+0v)o=%fJTQfp+F*R-xjV*0S)?CL}*f@L%J z)?+^bpDH%3|5^3?%bI(pf4k=X|2L}Vj}`x0s)zLpI>y5T>ELK@q-O=`n(^iRSbuH6 zd2LtEIQY?J?Bb9?R_wD)Q$zoQ_akoSsAeAR+`7dfVl@&cHf789MUKaG{O}Tel@;Uq z_4Ii2oZH~KSG&887p&uh{xMcb(PC%W*-dEBNxg4I*4^!idDh=d8~mL8aC4X)5hP&G zC3FXDb_`WDU8B65RNz!0&3nAfOkJ?D8H>#tkJK1xU~%W3D}sjoNU-nf%G2R9X7Kyw z*DD{?G(!z*|NXMy-RtG+^R8&+q`bwGy2jVv%s1_^aD0shrO{Lz7kxh#rijEOWOnRmZ`yyGlC-&s0zJ1~$) zP7S@uFtSsa@{%D<)s(kSAwLx zOJlfn@XI+3O&FmlHat1o5eUW4{6Oc`*1XR5^+YMUS7tNNFdt$=aE)<6Xrb(jQvNpN zOxedH(T?gDAK|8cgnfI=^WM;Rj*40I0o0s2{LM0slBOZ*oa}*{rDbDaCS2-al=6wj zVo4>Fj_!0uon6^zx7a+fI8m5j+MprGkLxqvgJew$%19pxzBwH07oGB9$KcOPw_Q-yX zU60kLzwH}k{}_st5%s(z(ar8v9*Ux~#!%eS;I$IwCduaM4nD7tXwfsE8pWE4zrTB| z6we$}?dUNm&Y)DO<2Paonz*zdN|`7vHs4<)%2unwQ!zgI%85PT8rN;Ku7Fb=$ydlk zN?Q`uA&gsjD<_U{3Cq?0zC_W5FNe?c8JnAlE^gp>Y|GvZDIEvhY5`MBGZ|3e342>B zDJRl=<&$Z%sn6;kE2S{?mONq!J}+U}k^B>AHgg=t!^nA-`zSIrsJnb~`cO>?De zLS%8Q1$?yA>*u~y6z4p|*QM?~c~P=phmi8J)`SOc+zMn^vrRyilBJIQ+TLuKIJ0=L zNv)?-fedNwrJvFbC0fqWf$7s#YmEqfwEphc;R$CYKv6h`In^(MA!BSBEV~djyK2_VSt@6+h5boB;}; zMRCh2sWbjtsBTnTXQnLJ!9%rU`g?#}+O7m?@gfHR)E$IA=JZ{!9`5rnfKWSlZ^ z=;#>_z9jr`zqBXJyOwAcRb_p=h03a_Ru;C6S-Wk;z!<2&boP@$IuHpCyw zm)nEQ_wO0qTk^HB%AJ#5Z6cJP-E8%&W6lHR-fkUX%~wSdg#4Yex<1LaN(Q0f{Efx; zIAQ|n9)j(CLjZ+9l?N#PSwX=#o3k-H*fUi*oaYF(iIY(E$L`qD=MqE(yEVWbz@{#A zErO5!?}R7p?=GVdK$zUxujx|k+Ot;ArrGob=t{g=B73Eq0PdSG(rYC#)=%-?iY|+w zR_hI)Su8J@2pH@03#XiUf+nG!O8=7;j;kvn?c+bFAc44 z+HLSDujrMKI>J1JSyc%_RbD&u+P#Qy@xr<;99p-rn=#1)QzXzO2p)fw;TIY%dorL^ z98}hYIPKg&t9j}v4xUFfzT_pi%Npg+gM0Vi#p;A*v{GlJmw88*tLG@GYF8` z{|E7(82=6bi4E`t{{#U3JNy#>0375iHv<^r5BjIn-{_w(;7}mIe~HZi1w#Np1V}@Xtb^va-o5t2#P4f5m2?5whsj)-{kaD%v^t#l{u&%@HvR*fS|Le$9sb4~)^j zM0EV|EW$s2_@B>zt^q)Q9TE@%FaiKCfWv54IYKEj$NmDQPt1SiA(Z@!JcMKQRaF=o zDvpifL#t@v&Gp4``GZR%T3lZvopg2O&FLsEd#1WS0~3^VHJaibh?R)P&3EC*rVKfW zhc#@8M8Q*h8+_SY#zZw87dLk;H0uer65bHt^h#?_CnBv=Q z$%!6R=me4u_CQh=HBzCas_0iK=uL0ejDzkga@a~XhM(_XwXlzY5S1JG@B^yd#ka)U zN|`vk*qPbqHJw&QUCBpeFd+GWX*$-e{FkF$6LNsWdWJx~1Qs$0$JcQpIK6sh{ug8K z99&8C^?S#hWP(X1wmGqF+nR}O+qQjT+qP|6C$@QWt8P8d@2UINTetr?d)MCGU1xXK z>Q#HK_4$@HCQ;`ryrJKh7iW4d-Fm!=%hav5T@#;3 zsoXFeq|sswojC@VGmOA0dYGA#m}z6heq~tB108JcluH-Z_x1_E4BoPL;xP-s!>}7f z3O8VwTY(!3+ZwB3%oC7PlvwgFS~%?}V;Q$(T}{AjMQ&$NY2J0fauVN+EgGB2X_6OJ zSTLCpm=P)2R3WciqqR?1HTZKV$_;ycIIL6!$-&T4MT$r|5SU2Ox={Fc#}O}UDtWQY zVZlN$M92;WsC=lpC*x#C$h|LMT(FR`P)JHjn`5m3X=q43A5bLgr>57vUA&=2B39MT z8y&74$UH%nK*fkJ5jo!e1PjYfWha4Q`O=k8+1O|Y*S8k=&Vh6amVuJ@Mh6-k7;TCG z9JZIDh9+?5)1@+6dze*f!6{Nbk?yJBO+&1uiZ4YZ2)+2jug6145G-&SumHgI6iMSu zKM>JM>V;vGj*)O3jaXCNm$o^qBzJdi;fOdD^c%UnpZP}@ahlII&N9YBwaY-HS+Qt# zW-W!lJXXL$s13{jM*jtc#g64WbM{sSAfhN%)~?aiwf{=cfF0z()2DR#mmJ ztvE5N^B^=GsN-5|FEY--PsMepa)K_T61Q59`Y?4^8zr z73s<$r_kiQb_#eZCK?5722SB*yMMZZobH}DA%CPNgg*}D@;PUrJ`Zb(WVw`^B^%)( zY12$-iPBVEm6_&z5TRwoH_W}*ks2CT74EDN4^shH*1Be)LZNWwv)VO7Y!_NxGD z_27`#nX$sZs=zNws=gBHqBN#!zSg-NHZ(IdHUX_@+(yE&6h@*4Vw4zlEvY#Gj+d1*v}urfM!SZ&vY zmf$9kSD+X7kObKACpz#XDTg^TX<)Q=R@rAAq2Row5!Mc?Ie-dv3qiuJfPjKmj=@Y& z{C$ZrcOKVqf9_ExLL)(ZI4g=L zc-1Tf?We6I7k_`1gR)#fBYaRDX;TX~5T&k9ofQ6v z1R{~uS5Z+;$UpNyL%P93E}8GF=|!*+uKIn+%?nWXX)|@!UiY%e(A~3Nf?};&G9lP4VlBQPkpiu} zgq`CQ5sH&4S?jvR!(*;gQn-}GRhEbe#teBbDHK6O5Cnn%OauBGmKU|s1I`J5Vn+v) z_#9W7I8S29+RC|-ce?o!<}Rza%{Yt{A-L(L9v`Ds_XeZ6LcwEYwtx z2%#Yb652c^A6<#l@Uf$&W^Q<9qw+2vkv4ip1Rj^Aw9%aMdJJ0h9tK3!f*#hq{qL%zYp0b%0_ZjH{sU`1v z4<)Ds3CapI93E$$_gIR$bHT%`as=gQV)F@maW8{na`t*h))c#P)$y=4Vkc)7G%ux& ztX9*ZPRkDo`|<;`MVK*DVvB##n#y^~x!-a%6+aG0)kphOM9d^Jfk<&u-f>QYAu`2` zXI^b3>$&i5_RVddtJHKs_I>h*A3@}8ehsHyiUSo(1N+*o7_rUA38s~|lp6(2B=&VT zIE!c$_Q9h3JPggyoGS~_GK&focTdhO3c0t=1}3C7)z0S+(|j1iGF{|6;9S&U%p(mi zXwWAQ%1WqM!X@+Y;)jz`w55Yk?QeDRL6ls5g1#g;78R=IPVGZm(S2q26o?{e3`4l) ztS^4Wgn`y0cH)*H8xStPKh&}E<)C(IMS@;KIA%OqvhBzcn*K}iO2KMbeqzObQ~pi04vQ2| z$`mLjGkDsoG7W>cv0WPmm3`UXdtJE%l;$`!e}X{r#I&eT7on=(!ZWB!$s9=pLs){h ztqLBUIL{kOVJQS9WHCkAlJK(0IbW2T%96|zeJE88+9hIGS||U6VjDuT)-;fGc0}d) zauT3q2WDn|!Su~x^ z7l_!$UFICyJ(TQ}G-jG7rc7)KBNVCcTp$3NLHCNymm!*9eSzfc0$+|yALTqE)c6|1 z-la6nj?prwSiV36`ls(EW+(Rb?s2%kK)5HF?@j+>U_r7`DsrJsdGwap_CtEm$fknO zek@!uK0or+mU(Lt_vQ7cofj_gbyCjh?xwxSxPg4Rl9pL3(;ge)03(c`a&A171pDWQ zsZ;1qNGn?Iy#-%;WtTsxuH>$w@t7$|OFz65p)N!rN#ti$x}3)HPmIfUeSl7Je#oS7 z<~Bk53F8{+5xabYln6Fbi#s?zmRZFacyG@DGcw2pz5wK+X~*& zMp5v~m5wJDm!%Bzu;GLEVsA_=A{6MYHRlACeG^Ga2@d>WJU_L%@UXu?0x$5#UHbcd zuCt1=qoAMzQdF!@3znm%7FpVosOpIlyU7d9%(QbNOKeColc=j@Q;%7?=IVXDO^`lY zmAft6&5nr{v$from(x_2v5hPwhHM2Tuq3W80Rv}4V};uINr=Pi>2&ry)q@Tuu94Ow z(;+>~$JIV7r+lmqPqMXm!#;KvN=IYwBBlgyl6x*=+pp&I?+qUR-JGBOmSXzv?te7@ z=SU;eN|M{m^B~+>>o*L`63IwWCo6`G2~~e?NBoXau6X|BdOk#Qthh@vWEcx7 zI|_>#&YD!F&Df52y~!#g$q|aIH;xdf1Y63XWN45#e0GoP;vurfH#YwTVk`P^+}e4g zsyEBzW9~RVL(P+SgMau<6K)}PzyFU(C&l^v6^{`EK1s!&J5gt|7r(y|m(+3}z1Yj& z3k+7jMvwfd3V8Eps}^g}C4R5udxEghO?PL8{bu=WitYG3)JW2hWQyR=Egm* zartKJGFbn*&|Av8_`9kkDrUWDAuy>Cxy(dJ3h&B~Z~2{ExC8%t&W~zo!OL>L5VHqZ zIXJJsLry^O+CQgB(?(n%c7F-U!F`1HOQ5<+uBK-^B92e+11k;7>daL;sgg8`1uIA! zNtJ<=DjY{re#=<{F5iGR-}uvbf59oFlt| zVTIiS;1B8zv8euXt905l=?qz6C?OQwvcg98to%}0P9N12-7!iR8Nto`u@2gBE8HWJ zM3Dr%0z5mdgd}29JluuMR~UT6fW>9{<3qKh=+E6Hp_R8wCbReHkFn*<}%MBnk>c4OXEu)@CHc3KBWoGyK`cv1t zr>`!yzg<-m4K2F862&~;G-XFPqD#p@LUze_Aj4Y3sKBAs9a|;E)H|?h!)YlT7r2)0 z-$$Td_aWf;lyldeN}JhMSJ|nE-PhZ**;za9!oPexSC=&aS4g(tp6^^QZZ>RzQd+a2 zBF#FhNHQY3tXdSCJQK*|+jX0a8XubYYX6J*9C&|)dgRbkC4mRWC@B|}a< z;E!?#3kvbnTKdIiy$`U3FttNcp2Chb8Xhh)lq>vfl{aG{-Q<-LCj=F#rnYbOu-jk# zV4vbzoz?-z{!f$Bx(k7cbgV*5RLz=$rdEGDO$TY_AjizR<4^(uZ|sYQ1p=P;YuAJT>BbyfveJ?f9!!dbAo*9J z>ysY|5EEp4wh*$D%xctYJxR_IrC+=36dO4Xr|FJnVO0=0ewCEUk^lup6>YSR?_%-4Bqs~klogl`>6>G!AOW;DJGg*BS=}N2q=o;2twjiEL;d}LuU1q zss!eppqLCKmz>&7z6=lb@2fnEQ}^yDtZy$Qd-TfA9Qatv7iRH2^38tRTb#bo z_d!`ocZac=*Z&UXdrSn48-*AU8fHRmDw%8A?bvJD47hW;X3lc_T|YHPwPNC>`UjnW zU%PN9N=vv%C?zOmO%jN*_9uqf3Ikj-3k$AbhVoN9M%szdQ25``0dd2)6ObdS4NriM zR>Zt-F2P^C2fV+ijsCw3wyt^f`v-JOS9IL7(&AEYcC305_oKfer1ojUc>V?OmXuQy@K-R5yYo=8er8f& ztvX@T2{L-7S^4rZ6s}LTBJgrO(O-ar{4ih0$wkEYtaKht7QjOhIbnhx)G|*2f<}`o zDfsNE!EQei3u=w`yG@AA>kGImllKQcCe-PErC_0E%q! z@eDOP^pV}qvm~j<=1MQ)(Ofk;_N2B2k_FO!n-nw@j|+xnQVFr(J-da2CsBrq5RmsN z!VmjW@1^_s8G)+%T;*@CWa)qUL>4x>Um&#$-j=}2EPbBn&%LGM$)xA-nLl`u{g;3C z&l~pRmb8te_(>bT$-xrjJr{}zamNaH-@2(}z2}>NTG8|O%lWZGavQd^$s+@d&55ha zo6Y6nszTEl9w zPU~*uG&`oY_yxyeC0$l8QM~YLbX-*1kZYU|&ILT?a+#_TJxM)$!@QI6$Ma+fC4%HX z#9R_rq+c-5s#wfu=FO(%*2L!d^NAa56RD#N@U3ar-q zm8`3{{CT!0J1OF6mgRv*ZzziS9^S`Lgwe_%&?!}Uh)cM!iZOQUzSwzrUEwqj+LyE7 zy=IwLuGs4YdpTd!_dhzf{n{_QSx*Hvx=~o*|J^CS#G_O*Z-C3GM4iiXJ9cyy&`bC5WXZI*ixPb{`bFweFqIviV|%zS~5Gz{!rXaQ4qGj z#ibO=tpinr#YGf*GRyrwn?)gLv`Fe-hmBKGF30t#1h_;5UdrIQ;C#`{zq!ia`@NP; zA-KtphX?}?J;TMKQIJ=O?4viNX^+hxn%ucVa$z*njoqiS`TTA|kpL78fQ8Ru{uqwo zbNs}c)@LOaGxUE?KW?l%JF-F3*ZCc(iK9xagzF!uw5>Txr7llG;iLC`ZEy?GC@e@H z2uTIn=nB2`+@)Woc}mcG$1I=YHR97!^P@&6Ecu2 zvP{cr9@j~O`@RJh9{3+~kpRXmYxUP|uGf6+8d%D{kH^$_TdhsT> zXkY$F^}QBL3Gq{T#m9rR*rnV=PFfilSP4lA`O^c8coeu`C?agjDDIC-FB{SPK}$3H zH3#nfugDu8~vE%t!ZD)7_OHA1FILh~Q^8P~bNL*c7be zaC7(deIuW5)uC{ZN5DUTtmE--;rZO|>n&?9j{zPw@}LL(>xkGbtIU5qs|X(g&jdsY z#P<75z-UyoX5ZrYf~(7A&h3i)3jmkZAu`n{@yqHH`2N+w2RZf@4aSCTMfdfI#QZgT zSZaK1u6)&(dbjh*K}Rn_e>b(~TCNE%Hvwe}ub|sK+E|DovdX-1=u$iC0of7J!4Lc; zn}DXYHFZdpJ8V-ZpH%d_;+`*Nnc3`obAFELVhZ}=67)Q>rYO33u!VsL)3$Pqvw*~D zTFrj^V)SK2^W79Bv@gs{lXT66Pq0ld!gnt$PZZ}_kuhM(t`Jx2=3DMnvoE%(%9Mgr^;Bi? z>HCXvRze8SvqzFsZEilcKD4M6tOeC7>8V5B*eV{p>HVw$?%6G#T+17*1UwczoXklQ zSMrgPQ*KV%X2l|!cM$N#tq+g5DdOnK55|>_a`~G0ce%*grLn-8{5$!B-5d3CS!!lW z4vzp!SIjX_Z;t1qX4&S<=_1&AVEPL3lk-~YL@=e$UgP4?w+Wh~g69+Q4C52i0(Ywr zSNt=(5s*4&ywhs(T;qIpGaR->-%RMna_$Ne;@9ohj$iY2a8Ed)j?(FKpKF=fnL)Li zm_EHFo;8)t7w4!}EV&_5`f^#e!2C3UD&Z_=&R`=kc{Hx{atWVvo4tM!0I69Y2wEt!>f47q-UtozIK`c5dIG0Pb{|)&4JGh#Ym6chs zNH*SpF#58_Gg^ITM&9yhdMiak?iT3$)5+ptG_B??+u5xS!O6^!wx3$#<@#hT``}~^ zWN(!xF=zi<#lw9{LiSDEeF*_DJyrWa@Dr2A^5I%km8(PIP2`pU;FcF3wi|R_-v4AK zM*_c6DCE$H+7Gz~Kis~$-Y;}MbFHiG|9%v^1__SZkI@2oeTWREi-xt7FkWR9*#J~u(Ot!;0g#GYO3TffhIyA-xx!gbH@skhmp$ZLsFtyf zUb=hEn=6wi4jipuJhn4cPafZJ=WvI+k?NbZmfo)7>A?Ffz!vc0VWdq*~`y{i8X^es)M=;~U`tTb;rhs)uJO1H7<0MYQEiQl>_00_h> z*5A1Mr7foW$n%PLfDO9LziqyO#{Xr8=pFTF1zSp9TV=b_COS8N7S5M@pvEt|^Fp;V z|BvbC(gcC9eGi*&ijgG&X&ZDYt#9u@Qbq;JTM`{;`y!g*Sch9j?T{(|ISj!?RX}@9-^}U z6-vADK4@)hMShtII)PdSXiD8^={A_+&g>jZCdg7rBaQ7T#oHcMaqvEY$xjyJWfp`I zAXkYI#?vs!wBhnCiLDCjNIEAEQFSxG>2t7y_ zq$~fel*aK#ZHAeBlMm!8acjtlo3}4bDg4uKZI@XK_TTX>)knotb6RnE|DG4Ce>UkaAPg&6}5KIk0; z1`7Zl{Qfq6bg{YZRI9ebj8Dp6KBq^=%yE@?GM{vg?$e^(X4*eioCG0^d=Jb+B-6(+ z?~7tzdc1%crQaU7%g*n-jtM!_^SbVSifgT!^+guzjah4WkHn9RTqA(g2DkX#UA&m$ z5vJw(f%-nBGqdZ8C(DNhH_z-E;9Z{luP`(HHg>IvU-g4T3Z&*D+8gwEbQv5DrxQ#j zAIw49w>7mXT@v(tea4lz=vBc%_?+mhGPfSgG3!jLOp8q0^%D+$#as15^@H=LW>1dp zO%Y(~>^i?9Fa;^#smU7nR|;V^gJYUd9WVK|Rwu_yt<51@d%i~PY zmT#unX^$}ed6U^Wqmxy0bvl0cCMkMqN#y$v-HB<#EKg4QU8ZM^cT3$dNcw%I))YX$ z$<3-KB48YN^Wq6g4}^DvtUic%ZuMl)>r1&cs)&G09i=l-t06cuCPX(zb|#Ie!-%Md zIQ!RW$+h15x}sN8zOraZ{>FU<1l~+vA9_Mo>o3<>tU8^;pSwGQzY(nuS{s6&lQ}cB z2W^gZ4LH}+*YljyuUefuJ43f8Yz}tyb&YimO#`W4Am0U@+1{&7Z0h>YX&+hNY#u!x z5j|2q{1EDh&nY}&I;W#+_bo$7SO0MJDrU9}VFEV>H@QQAx7@s8%eS7oJv<$;a!18C zM7%+p!+1v9`snQduaplKo1L?ggfvpb;&Yo7-n`Q?85wN03cY4$8H4`82d74say1n_$6ZM3>1xf|cP1chd4;+t^lxP6Pz_!+JGnfoY-!EwF;uS?*+0 zHA{VF6Bc%^VO!Pp%tcJuO7V(A% zd$|=qzW1Kk<*8{Zbrv)pc>Mg@9yO2G)nfJbD;aKoC(n1igXKW>RJ3l5@LF94r3f2htEEw!!1*VVC#L(^B@7!wVlwM<$0C1*`iZQkk#>Jr^s%_$2VL%?RQ^Fzl7FC3R;4{- zTJy@_9(`W!Q-A&QtZ%P=oy!x{Z8-|m z#;P)_Ia#&54PCtPazL}$MuGJC!5QM;7_+5$BULA|MY>DlB#3`3%byIbq)=jGney6_ zO`y0&l2hXxy#m{et_2r`lN(#3Hz2tH@j{DAva3BXSux|j|J4y8oUz?HXK~vssVU`o z7Lb+KSTIp$E%dt9Q7M{H5#KzL?gDc(mMB6Rv@&E{oMv>;T7N4{O}%SXr%4d%uH8|t zrk@LQs2Ee1SFRSWS{XQJS+i#=ZkdS3eXYTQU>_zmn;slr*TndC2TGU3&f99D;il0R z&Oh>OxXw{(!P@L-nq9(VUXO!QxNyOKY?`qmN9M4L5iFcdV7m_(O7o1W_-0Kv#zPqm_=uX`CwR0KV8A0{z?sX+hLIbO%k)L zLBud)ikx1JWzgh#s+ge}<7NIgXN&q2dJX#iqx2K8n&KAmT&vxgKyjHa%TlE8sTi-j zbfB!eb&|^br>Tl!ck?XYj+M2}cdWU;fs=KVrShIRg@V=*E#;_fOtSh%rh@x}icz6) zPKD!@tkspu+Lmwfezwl3^CVr?ge?7GMMXorS)8p#X)%bYdO6KZ(M-eKR(9PSQ+P_E zs`WBeu|<-Jc@mGNQ7zeMaCe0=@t?Ot09Z{>rT2X#|;$qnY6O=}gKtuA`K^S;Xl zqc`57%BJVYI>yQLw&bO60ZZ9sTN_=g+H_S-i^`3TrSt_yi8EfA_Qp!X3vVkIR?zmo zst>G2^(vh=Olu{JCY`x9JuW3WUAUh5W&Iij zx>n6!0cr0A+?pOTni{?VJ>b<|^Vz=+@{7Xa6Yn;-8Xbiy8I2qWZ9c~3Q(v{7$H*PE)?vsiMJSLsJY102i%QJ4Y(}uLe%9i)C>slC{aDL zzwXPNZw$flWTYMQQv6&TVS$zV+-Szt&L4Hlz|91;aj}(cbR&dzF}i6nbKlBG%uW!Q z&VO;^bNap@?Nvzt&;l(X9jC*WZesgn2X8IuD=^@(fv9-E!zR-I8Ay+3AsQ|N zKrT=8URZ<5pY*e>{%LKqvNET>tzKVNXtxhlTdP}PQBk@+qfM@=)6rUG?X?+<9tYS) z;g3}GD86Je{H9ODnX>B(?{f*aC`qe>pp}FXjn{BGhvM!ACO!mtL{fms5?naz?~68Y zku4q*!SD$&!s{sXAG5}S%|g}sZUsO%k3UFv=AO*u3DeS7DAzmV7&DuV> zP8%}x>jdjx1Pz3CY)1~}8;cPkqS~_IFc!$o2^=O(|ItSs)Qppr7mc$dn$3qsbr+LI zXEq)nN8dn!!>Ub{j0{J*DO*U*b;Y34NA5Rq&I1k^i8zWp$ZH1^8##4vCngjY50`1j zUpOlwN7~VuI%hD7V<^xN#)XcA$fEL2=&;J&2j{B|?3rt-=uuhiZpDU@aQc%4!v+(Y zEf;BR6Cz=pVyzO^bHxwMCL3jAaf$ga3ULi2!4i{Ij#Tmc=M$0_n7aGKZq)L#Bi|d8 zA2UR4#koh0g&YX2A_(s^k5j!c3iQ*m#CAPD2gib*Mn7etmZwzdS^hPR{l^61XPuN$ z=E>n^FK=MKb$fS~OGRtR)`;ULEPchum=p$qAf0v0U_jOe7WasS3&uV%XcdGi=k8LY zh(e9~ffgSR=$<-f67<3i#*Yk>|IPX>)6nxC^5|213 zAjOkA7El_I5xBH8=C&U5H13$$4Z#%lpUVzZ5jyE5pdyBReeJ_v&iMIVERuM%Y!G*G z4+7h9MbqcPQS)FJACu>L76!^miKvNCLm{%D0zC+Uo(ES^kw?%4=BV_+!h=ZpVz^_y zvlUQ|pZQye&QB$)t+y3(;TuYIgA*iDN*lR|Tl0^<3t5|!U3#Ydx&!HtW&lRML3tgz z12<~J4^}k-q7PzIn}JQ}&&hBs->KMeM&Cvjs-K`nc65z~jtl-o`S*Tu#zuHa0d3#k zMfpz{^Wa2K8E@_3SL-sGld<_INdpQgm*QLY%fE_h+9!2959O~grq`tvVl{0@b5M+N z@|dOanKzMHi0a{`oG|2ETDD1=ePdiFt<$xo*Bc&k}E%-HJ zlYgK^$h#Yqkqbs2I?})%M%a=#9?BS~E})e~?A2(9Bt1Wt*+4R~wM8G5P^p%{wDo=s zOR$wrJ@rcgP7jTXBaE61g_F`e7ox-el%3)R(*hDM5K1iJiOQiD{>qYcAuDU#xN9#{ zy5mwzwv0)%Vc@EVT)B%_fzsk{qc3_fEJ8LN%Bo+N;uM`Yy9g&>syS#*7M$E(pG+Oxs-9`BhEfKd*V-aBu!;! zbX3^+TT-rg=~%1y?;IdptE@Y(|`nZ(=yy4wre0n29Nfr)3ORIE1Zt zB5+9A5`Q>vL(6|`T3vNGa$%l;hkLS;^fi$C>kOBjhPu{+G_~$!WpGY0bCA zs+EKC+Avee-ksXY5;ec>O@lAX8kkU?i#8ON66X>aTR%;wH_#{D*BkD!{DJyEL&Xo=3~j`EkAMMZLZvksi&a< zTKXaBWIe!GTkr(e9*}=}K3b)iIMl^g;559DO*QSxw`zlCPtLkCD|}~n`zd}_U%Y8+ zzJt$FY38+0ZDnF{5O`0Sh2JGqKwT0u`Y|y7A;6V8@j7_ADxZbtcr?^BleNgEvLg*} zJ3(bh=GZRCb{{UUO|Ex2y{9DbkW_nHe@+W4pw+f0o&1Ii3-#2TUCC^?MZn1$P>=55PO{^=QA+X= zEnR=go4a+yiHpl%LZ5)_qbh>qFon54jbfohwvF8AGrV9p%^~3v2@u&#i_39ndS1j# z<^3uw3XE@h$~eaz!yt9JEsZJ9PEsP~@Q)U5J;efNp3i+SBGETL+DDw6(p*TJ;xjRJ zI&^#OBR)w=lur6Em%OlM7 zc8aKS44=ple9f9vJ~J-j8wLux-2N*wy@-sNl3=$8nNxwDvNPUnnhCLamdnoI`)rQ3 zGOO^`>6Ebg!jH}FHTl15WBwCh`~L^dU}XHC^e~-R0rP=BKSZ8*gOZsddL@EGDf0mL1_`B_Dz{yg%Ifhs)Es;etc}m+r zfmWPt_UnVfg^+lUEW2~_zm(U(j$IU%2e>lvv@vcf?y0#9<(M*gs{`))(f8Tt#9^rx zopx;FCFsevCj4{Yolmlkc`ttd`^3Tb5H^+6`zosK-NlL$VP(!Yr!GZYGbxoNZ1s5+ zh)Vci)ZS=p$tZKDx!mV*c=36XcQ#1oHi9J;kKTd3@(3q1rUKv#zt~9p-^=v>h`MDU zU}0kW!~S2<8%7Q$cIN+4d3)aJ=J{(7ozK0j%>*!d?qRG~C;b=&0($}?fWB%d<;xEe zCxS%OvI9lu3xV{@MP6P2QdkfK0TiOTg@CApfQq6dv_*I(LO03q$fe8#C3M+i+Y9jY z`8GRQT2@t7RmJIant4@v3Cj<{4}RwxAb_^%fvD4cb27D7E2zI?@l zNI;qT$7^F^?1>K-GRGaZXTz&+vcB_dDe4WA07&C|o_%I4o4)0^_oM-`b*J9_RAA;% z)y~OjM$YfU(IcG7ZMV_*X58ZRJb)@LlE5J3#6=5AK-PgMo6Y;S6!X^sO;-(!qB@P$ zppX6buEGU0ycjf9RR-VXOnQ*yK}KCS@}ZM0GJ{v4ll05W7s_(G&ip6})kN2nvj`N% zp!L@1uR%Wk`*ROlAA&(6Y4;eKIzkLkFkraW)#F4}m2u1soSY_h{ z=F5k{h4L2LojTI(XiFo8Lgsx8&gKt6aZG?cR=Z>7Ne7+C2a}*K5~&fuheUcFI4`bn zOIk^mc8x|uj%-Qm`7rWfWKfkg@xBFl)cG*=l+MWVJ;g%E;s>P|1i#j zt!kh>41&$B36dxK=Y+12BK@o6Bjvmx(npCK0=Xld?p>z_A6FBC|4OAyMY-y|TS{hD zG&VUX?^zNC)c$tqVPq6KZyZ6dOGw;x__4BlvNGrDieW~wAOsP<1Nj_Z5dSA}&(ydN z^Aql?g|U*g^Vjh9G15}&@q?4DVA(52}j@(Vc6u7e+nnaSQEt}sJ-?$UZK6=uFk~l{@a}-?&v`kf#ANW~*x0 z6NCN*O+V&8W{B1i7!SfZZJb^4gJtKvz~S9L8+dQQ7=N-L5;s;wX#yWc%E|w7IE6{| zis;ZpDy<7#4k)T>aepek^5HuwYJtgF`Rfk7AntSaB=L{sB8y4bd6tKvzg2=5oC6YL zX;#9F5~T^1c8n4chVogb8to{jO1aig+!Hs?aYGx}1CawmbPd^Q zf-99H;uR5va_LKZy1FAi@cbOqLD}MzrFlXf6DURiEV90+q0k;pz1n(hlWO= ze{Ovdpv;p@8+_UH+C7Ho?)2B=H+^z%fD5$zzH$e-GJZ8=GY_iTnOhh}dDD(k9SV%Dx&*X9L)g$E_^B&DDwGMXehvjdd;&l#OY5{q5J&yXG2e|fnZ|du} zC6ig--?yTTp}gtvKd`Eq=_QFA9m~ z&L48;)LgdQd+Mw`lY0*&+WAjCOf_&UuqciDmigK}>@8Rv_BcjD0Vvlv_IX$x1ifyq zzo+xrv7huQJ;tciMY_nlP zed|gOAYAneFeXh5;o$}9tPGv8b z_ebKNr*qgX$N?2M^)BEV^92_OAD3*JFK?rdpWUO<9)m;Rq42XSEWSNJ*w$!e1Y<6t z9d!%&N>9c)!RY|OE=p{GNrl_s0?2#NbGV!`b*YYBy6OE{?bv$p%=HS@h*FPfN%CcL zT%EjcpH8qB&0fn}WAYy2A&N338hk{w0m5VTrYTgG@V=tto#UFL_;0pabBQZdTNS*lmoO*uXw%&;9C zUC-v=qMcNWNz0QP3tue$WXz%3b>IDfq| zJCbRmp!aR|v+Tm|p7kvQk}?+oEZL1&7w*~FYMIlm;`HwH=sGm5D;N4NgW12K^(xxf zKlZ+v+0A1{sCV*r4T(;};)9w4Pyc=1Qi4i>=;?Q@Xn@PKL-kErr)c%! z85&16@M2@?1{k}K&1vfyYLjT=#x?vfV%NT%wc{G~r5U%s_0@ADaDk(Tr-`~YGj-z< zw+|o~Zf|h#)OS7AAhO@^WWD0%m$f zV>+LwsSWy*h$>amTx)6P;g^D)Sl-EOgDDl6O}`2&c2S>GXq4plLUGL6w;b}1mnQ$z zLaa@vm21cWtk>loVsfiBOjxy6A7&?0(!S7^5O-HWJ)a716lA9RoW{|MWwl)`;Olj{ zo+c|*>rdGiv?;lGyUmZ5k^?i%Upehh{SxT2J?|sLx?LY520`?=r!Tq8KJp$TYF(4= zg04kAfA^wx$|`44aLm34&xXCDa*)r-KFhJorOL+c^WlE&KCkX?<9vm0I=xr!dqj6T z;{fd6C-={yZFqI_j~t0_q+D3hjqmw_Vf1ThEv*>)vZP?>VQUaqpG8-W7&zh z(A4Yn>xAnh9->WH^Q(2CG%7`jqJ`a(8HL*t-SOG+-h^IKuSNF=Cv+#WW(kfV_h={c zb1HL5bG&ob@!KR)q&;FUX41p4*qm6ZQ@F*5%cUE>k7p`A7BTCRzip%R-$%ETyMh8A zQ}ue5Z(_b06Tejuz8tUFnD%UBv?o7pKAy+3)b1`mfN!6COH(@$pYcqM2K1kNI5_(A zZ-06DVDW;OYCx>s^j+aTS{sjZ7j_*tB6tVgo-vd22D|V-LCJS;G%pcM%YFRdLv{27 z;os3M1uYmsFJ>E$#iWIQ)!ELw-i$6_mQeefQmZ zR8I9@GT~eUU?V9^^D{G}dWC6($`}*xwL;oGRJLRvjjY0|krjL_3Fj}a5IL=~=t-R*KA$2ljSPd3GK@+vyK(zQZf-s?MytMW}l=u^oU2v`ZhV}00$uoS;)vgVK@Bvm=R=CL2ZEKoH%D@u+4~q za02eq; z{zHOxycjqM{zn-S!u+pv$$3-GsF}ADB8hlmscAbGhbQ~H)}Rd{Ys%(GtzMo!o?f1y zk-xaj+3O=#d#nyxEf*Vz)@)ClPh`yiF7asxd|RvUnt$M zl{>~=+1q_=1YoN}HbA{yJ(2d702@K>x`^$`?xCyQr`zhgubu6kryHAFn;VyzdS_lxHX{EK*d;%fk~KYhn{*M0pZ9O;$b-Sai}HS`tnmGuSQ#1CFc3|WJ# z>&G_2b}V2c^zQSs0}&p1)Jy8=)`e)u8!X)pw<;iH=1fy`Y!;Cx)b%f-~aY4O{0#`DX2WywDJ?bBU^{5_&;Pw+BlEmsB2wI4(_E7M*NHbH^1c z)reI?=3}Qdk|@nWZM;Gc!J?YCIg+)l!lnu)yoHnqDhQ_YcU|X*NJm6cRjP|yqMJbOzl-RY0o0p5A&=Ku^|#dM;Ek?%Mi6gDWd~I(@#X%#3={ zV?tnjJp{VfYa?P6=pjC)UfQExCO*bHg^dOld$(llty|KlgYh*H^|gU($BnM6=f+jB zXXqpN+@AH;+fLgqU1H;g9+e9(FLiQt6}Bl}c3D@q&|AM|aOLHtJ{DG0VHxGYAf=ui;#EVa(^Q$WB$$WgImyLvtDn7o6feMyWGu2zK2y_ojuA5qeQ{$+shim5e z8XOK`N9+_hD!g?=D+9jzGH0M_T+ie!CaAk+&Q`nNwRbGZ%-EvS#~HgNNt;NhHJ2wQ zwwH-1u{uljyQZD9g!L%U2L+LXg2;NnHEzZc4dPR?# zI$al*&+f06gb>8m{fbJxCeZw2$DDDA9BD}RE3hP!lXg+V^0st+BvPNA&O}7k1LqX` z*iF1H%*?pCkxmKB)Oj&N_Q4?J?YOEg*~osMk4^C6Mghj-Mg6?NmGNsYjCVGGkR7S2 zr!}l(Z(E6Z7%Q3AR?>cZO#mf%o9ND(>*eA0e_EZzSTVUvJ+b_k;)(I{enSHN29K=t zR@Bubc-wDihpTvbaeG-JRd4K3$vJ5vMV*{jib6TMy)wI~RM+z%{3jKK`r1aB9Hmms zA>Ll~x|-hcuuAFk{f{>_#?G_5#OTs(iEh?+iFCZ~+TprG_tbS9c9;*-enUsr)hRoa z^+F9)SJx}x?NwJ(H?A=@Z+yV33)Jo4!d$p+W<^cgj5fxa7CY;EEvdpmOeS42cf|H` zdmD!33ym0c5u>e1!Mu4aR%yhzL6Kipp3UurnMj+F4k7U{7Q?xT91c7fmLaj+Wn%dn zZYR_u?L|6_#B!Q2rwMbKFsBJ~$`B?K?p5xUhM)%@y=|*Kn0Kz+!EJ>Y66GG`7K0Dl z9+Qa2CgNonr(?W45ijKyH+1!A%N2M{;2efAB#L8O)o|6oyd7eqQ;C>Z*_N|%E9Q90 z?Fi-Tk+2H(Y8CeC9EJp2U5WWCF@GiIuN3oF0uh_?r6rn5Bvv(OEr}dVlqcRbqTK=G!pthxH5?_vLzt*M0E1 zC&s<;n#EUfy&8IYa>{4o^;j&U_&k>16Z_B;`_vPe#B!D)twA~|=8VN~F47?+POM3| zo_O}avz#l(I|OV)z!CvCPQbGa&u&~dEGfmhr5Flai8#g*tW| zhD5xBl@CH%hO{S9<`;$8FAAq0+wx;?voS0aQ(6o?oWFr8w2jDL(nVX|3Hd${2@B~` zBSRg5D}uAF2{2jo)6%; z6wf7iF2>m~ZI0}T(6NOx3g;FsD_mW;xo}URY$qLuXAP|plwh%-;W6mtj&dF4VKivS zpJKR43~v-eK@6>eW3=Y7?2Dwh2Bv;Foa=Bb8=jBuma#LgMln`Ni%O)w?c?BuYLS9VkC=1y( zG+Js(wg;(Xe3HBVUj?1Qg7%7{f2h8)pv^YYm~*V zsV|Q7t5*yfRk?+b2deO@p5EU`U}$9{iLtEtPKFkD03jLkmpT)1RTaCZatlwEF0BH~ z&1JSSLpOcrUOoRNs7Zv8ONT9T`33gGRsU$eA(izTTvhdXED>{6^+V1vaJhpP)1r!= zJ7^~sRaNd#&ZET@*RXu$yq;B;>VX&Yd+q=qi^O{1W%a=OmwIm6iPa0SC|=Jk)^m5L zx24oq(Q}K>*H))gtW(;t&ZLfYCW&<>CF*eTI=;*5$WDPztmBiN`nNjn|DjIkZ|hvf z&57M3|K%V%pfCA&OOM+aGOr0#Ohl@wUwrdqTm8K8UhfX*K|W4^_HfPk36ohoZek<( zI54qieUCs-@0Px|{d;-+ZLGL&pyw92tzu~9mfM7hJsbK8eJcXvdRA?{YFzrJ4v$;Z z_P8zSP3&1$30H~F5~Uu+QV!j#5DJR%R;p5> z0M|HuRoyMRncYNb?&`DMgsbg zkrxw1I?UDwx`VA^N>BVZYgQuhKmMCFYu4;Bv&PI~vG{M+?3<9-G{G#GH5+gQ^uLqNi2*e4Sn{^Yx zTCCzt39*^QJ~YE-fORt72=Lz`Jp@jS-Q0Mz*AP3Ips%8L#ml3uu^2su>S<_#;>S=t z9}&Z$q<=hyYvBk?hX>&?%*!Y5!+H=vi}^=@Bkb1;C9nc+fuk@i_A}=C;5j%48PFLf z$D-nwyHRo{JV)YROc%pP>{~`!!bSKWP&KBL9Bw1I2Qsmhq3|eJ;Sjc%9#i7=R_dZ9 zc-K%kz>Sq>#ByT4kiGo=*m!uBl+cg)m*G8VCVn2G_r?~-R>oFA5?tV1t#8C~W7F}j zVNe4%!5!FxdGItGBvrJO?ujiDzl)!Uxv#_1TXHNpH`=a||ePZKdGoS(nz#y21r7jX8<#Z%BlH0@`YyCQUD(1$vhr-QpE8Gst z#NP}YgHPc&;i!@hrNg*Q;Dl1~YxW0`XHO$1_rpmdCk3Pn5y%4a61|z{TKA!S=fR8| z>@9NtL0E}AT?d|Ad4N1j){&RU%j5?tp`UOZcQ^kQ z|3mcSm@@WcY&|~L3CZ9^q?>_ra5c{7LHHiWmrgQB8TpV#Xa+}kb!#-5AG<0xH}+=i z7z7{%>y{#_t$_Y80((6N?uDK37T$Xh-iI^rFXR$Ol*E9%@R9(zh72J$iTkwYNGrAA z{1ww_w1FPsBHTfK1pjjDwx~JU5Iq--#Wu$3V{gRX6X&-GpVI?ppc-c40%J3_9iQ_i zoQChK((^I=L~O)Oa!4OCoK%t;GMUUEGf6GEo!o(3 zT~D@=o#bP3ocu(2Dy3%RQ-n^S_s|t|8{J1grl&dJhM)&i%iYec;I?sxxwE{E&){?T z{(KEThrdmNfJ|zUzt>`Inch0S^~u&ZqFK?N(d(m&qpwFlj(!zW#rDL$K_HrgeXN2> z*vC6@{A{;>HOj{Z?Bkd4E&PCU{tNPgBMRcc9(%-j>w*35k3AoOfay9sCzGkj|9NC1 zX&}4AUGDwl0Qr!dAm=E--e=+26<5J9dL548NxG5N(@*jImHvS~a0Zvh<)cqggQHo< z-H+pWj61=7!&BbO=ki1Nx%}G_PI9f}QOQclKFK?h@1;8FsDzFf+Tq2;d-Qd_8#fKs zpl`r&-_s9i3AvMABri}Gc^#kTLT_sj?LoUDGTMn!J{?T5l~SM7M@^uU)vz|`6Eu?> z!G}3D%*OQwbR=CsYv6gZ3og>$C}}ry2k9C*mRrd`#CIdd(7Sk@2dW{zK{=F@Za8-z zK`qWuCbyYq-|~V)&b3IUQ%!6k|E+{_AEF*CC6s%Yj3muu5Vat;y3z+AfY&MaQjP?>6Q4Dx4_4RQEG}oLfO}{ z)u;il20i_i+(D4zx`dQEM)Mhu}&0 z2U?T0Xtz?3k5?l%N2BhUf;J)t@}Lk$*A2R(R_cRggJ3x7(;C#0*TD@?i<ZE_>6m-6UcBl z!Y|_I!VvU;2NNScxf9Nk2k%=F`v{+w22Rxe1-MF4?qfg1K90TEdI;Nl9{c`~v^)GD z?a{szW_BbJyhPlsagwAb=o94i0swhW_VYX>TnCDWkxl_9mjI|yiZxhAi)&4fj)kEF z!1yG9`NKF_zmJm*pJPu>&`TZ3c^<&^BYDmi023aK z(?qyJSLg~|p(}KSuFw^_LRaVtU7;&#lFwS<#O1O9Ld z7cML)%FnZyO`I4?1DK0h^wlu6>J3&JqS=8!*2I)ZX}5G1@DH_)^g0|~`n*l$&&moY zTjZsYjFQsyO!jBm;B>5Veyr5i(6?!0b#WvXA&KU)A zdUu1T^qSpt1`LB|h!oqnc0O{e^+L1mLUS`tRR3mOE2c|y$TrBnP+iijJB>xzEayTq zGNv=5+?*bBgp#X% z2CnYkJGGYpY3aI>h_2*P5Fznb)OX)a`qit3^s5gI9$C5VDtA9q#cQ!s;EVkTE+lvC z$71oQg4$|`ki;CCEf#B0JY^DR7terSYBpIdyw$>HR~9cQEDWcZr12EH)oQ`w{Jf&V z0`Z;{Q3ASJjYezF$`WGJ8*MhD&caKJubEN1qCA&$Egm$m;RROyk8*OqF_4?KX$|PPfBs&kh&eH)KeLzpEo~>#!R)>Ho!Q z{7X49!>Dz**Seh=g{N@Ff~u}VoqBt?q-6HA4eVE`(b!2Y%Cq;KL zOWyNJx~31$nG~3meY@S7oy&3UDvI+O zX`_%^Shx}?FE_6^HxS6p4T8dih2=q#!z%)vxpZlJQp;tHN=XSf62~@ohM*1ZB+GDR z5l$jli$PhI!Ku;<9X))b)LTk2r1tJV@3J+L;C!~)`=gAo)edF-o6AZrIPA@~Y)3Pb z9VRu_&Lkc!%!(x4soQ4*xvsU;&^g;ibU$Zb*td{n?!!p8uY|4DYN+<5NaO3WQ#i3; zt?^YWmC3@1IW`t`if2g!QkgZenu!#PaB4eoLxqtK-1^Gx)B3s|o#OB5k0|x_By+i^ z++Q(ift#3HmWq;K5XIxcd;K6S4Ug8&HT6Egh4_|nmS!aCDtUP z(qNHFB|59cXzpf|^j9d1Ym$NhI-FvA^1Dq$g3Hh@@~^sotGM(~Z=s?@mBl#LnJKPn zQeZH2ijQ3;rDl`CDvr~i5~g8VU9urXon)}fZWuG>2ASQEqz=6(kY8pIO0Eg0YLVF67ECl;K+Lg)T%Z-1T@jYT*4)pqRd ze$spGI@0@H>@8~B=qpk2!#Ej7u(z3{K)BbGtP2RqzdC*oN_yBA8t0ifkJA&pI>@C5 zYc$syrw8A&{?l;5c|Iu5NcVG)sx&3ZO+G_LdWu#l;X{y_84LwYp-?c0x;PL_cAAot zolb`{*%34vOh%(YA(saYdXvGR&kO|v$r4C)7!7)bBuO3wgCdiMP$S0)2EEKMN-hUk zu)ou5*p1pcsgXP>Xyt;lzricRy8Iuh1R6=Hpc-yel&l#pv5 zO)uz1@h`}=qZA5x@(CCvw~o^5ZKHHLITQd zEUl-R711^0Q1x*&ulI>cBj49HXkT0_&?M1NK6=a}@4Mh2ix>&`%S zf7X!MSI8S%UZ8Vty%qa(F!mKk;AhZ4vY;dlauxrH%APcR2XTWfu8E-x?+SGUH^YL( zg9dkE!OsJWy9{82&p#6z!F?~8jtXhI&_$uJ5W9jahR%v!q>o~h;(Eo+{_*1@}f1#u2rD| z`Ub~+R>Hp3$tIh&8mKbR6#E6Z*oB5nd0M#w)2XowkP`bBSdh%If4!2Nq)3t{(Wcn% zpo{&|;7ZD5ccjOD5dvwF_y^@H6kRqFKJtSlgZ z^SvtTb`>$}WN~oDa8{vCG-e3DtQJ{801M zdmwsh?~YsEFZJ7l#J5*O>gdRv<$p)3x23@#cQ(d;7qogQ$Q4e(Imj@`$t$!?bUmoa zN4&R{`r?QKa5QWm5xNP9l@`LvztZRrY)L1`&e7pL=SfpmAol;TbeARJ;sp!wd= zZ28mBYT;AmZA?1xYJx|S-Q+atOci<`1U(mpLaBB%l0UYYO8pYpiQWjVXXep-sV@zc zYtSXh1S{scvA&8qY9pO|ZBB%*FxaUZMOOe}rA(Tzi3!almC8WY zO6N0^(Q<^qFSSEGFW-K{2D?$p zs%rEpZvD~tr!|(XXZLM4`ElO#jW~hHm`Iar zRgqLZmyI2->w}wme5veTQZYY%oN{i5W6qM#tE;+d~ z=jf8%gfoy#?|xNf@0>4@YJO}Y^WyV>3XhrL{-;k5(49fn_h&vKu*qmWjh6`WJ2OQn z3NwQtadntnP#6puO}r#j5DFf0%gZx8^)X}KE@jEbvki=nudSS)RRTmm%4 zU9@m~M)IxVl{ian(jT8B&N%zFUmK^L&C*(RI@8Kc54}0=m1?)cZtq>Y;>kNkJd~l+ ztMs-JbDmuN-gvsPVEg#Tz8#&TGw5vES+CCQw|od&C8TcDnB^q}CWTd(S~_gceM28b ztMf5iDTqB?;DZkY4O(h1b^9bPPqGEsdgc|E>otqkj81rsU`R@O&FuC0CQ;7Bewy#| zc#-k1avU%5xixO);X@Ld6|_XIWVQ+{pv63knQNr?3R)sbn&fhMK zv32w7k&?Dpo10The1#-m--Z<05(yQPuh$0%$F+V$KHA)ifxTX07=4F@Ph~_$kg?;q zl$Q4x@1no9=@~MXo^17@obO|Dj-1PYF9g5JsYv!K((GMqlFYQL)5fOVkoI`me*1CT z4>q}-39*F@gLqs%*iG0Uq$cb~Jmj>XaFz1B62c*4Bl%iTSWA_T zQk{&*n&^B;qtmuy%}JqPBl-MQojo(eE89f)63-AwB9EF|tK;I!T&?V8)W^+nxZPQl zV^Ml-wq%JSS%Q|?rog}{bqT~Sw_cK5T*8q^buH1isS4(k{Y7#Eepv#SCcM+ReeW-Q z`sn#>x7;v52-|de<6{jg_C7!F-g~_obddTo6~aFho#^p=vHhLj3qzfJ7K7cebpHzv zY^u=NEHsnpA=I7*B7c zE)5}rw<3SNiP$g3fr4OT?1-Rb+5_(n$~BF6=UkrWff3EvHC0J8MR@g z9N~;kZ}1vT9<$rxvf6bvjUR#TX0#t{u20AJ1TWjpN)BaseY{bp)oTq}PO8?ZG*p_wrwhbu^f!{11T%z{ zh|)sAR5@lwB$)#7X+5k&MM9bs0n%hCqF6A&(3OZ7jp?;o(cXwSC~kQoAYmVMAwAg0RYYb_nZ$$Ul!_Uo_xq8jS zaU)Bpan=nd*FO5kg2kIYeER+=t0(%kc7s)Eif;MV_rWWxHZQsNr6HYAdwq*2`dbl2 zhai_M6nYw7@V^T`!B1-5!Mn_n%n^}^RH91aZO$Zfd^cj8L)Q6dt|=1%K|^xD-5C44At#X46#E?E_wU>E^3>EI%S%u7H^qL0 zQ0)7L6u*z52SX%PkOxZB(xk3Zqa?djstGibPX%3Cnnf2b<-T;3mRSZ`sHKrK3#xo? zsqV{+QiVP5FF>4aT~>>Glby5Ah!f1_SDezE%v`5OZ|3E0gI9oL6RzJZ8KUSM37Q{| z9#^u{j6tS6TYy}I+?U`rGf4lAt)ZG!*FtR%_Vcqy?Ce&=$2gF)TM;(1Sja)tEV1F0 z#D*!tQp6_anbc)w8&)^7JTuEPv%C&qxvJgniThnC?K{*mX{UntUKf)I<7H{iIOY0N zYu22)e(LD-E=M1I>`0e1%`-R6erEN}x2(3lG;iKZo952lL>K43Q1i%VpFJ}6g@VG) zgU8n$I#f4)P?ztftz0#A{E8J(*^ISoZ@BTr7g3*xUL`jky-FwK3JPt5MI~HH2x>o^HRW#AJnPq07k9L+Wk>Vieu>_RpZ1@+*DZV_u?QMfLDGj>3$c7= z2Wg_0P)1NdE?kIj7&K!tzC+cadmK9H2`oW}hKdIc>V(1I(L^5o#%$Nyywc0M`d&20 zZ*ZH{Mz%*gk<{^1IJL;JP7SgkX{5gkPIFMJvO8S-Km);lT0^#>%)lA!$%&UD)o8BS zE@?JeZpODZG#>{s9j^G?77@>L53}&HG<}uX0C79xBeqc?ZdOqAJb>TBKLqLM&b}f< ziu7p7oZT`yWnN|I82 zh$c<1(dhIprQQ%oV?{~faDI9?oR;niq-Q8NF-t1Vr&1|LT?(3MH;P#n%W#9mVl=qy z2E9L-W%c%eXP#%dhdb;co;0V&gWj;;>2PGEr@NgFlhf%i==E-ziD)S^7zij8av<)A zHp`Pmv$7QS%#5(Z7Ivuv>d)z8dR~upw`NyNvo$7Mv07Y)%(sXqTScFYVJN0i zs>N4Uh@uusL;$rg%NAL9XUDDU>e_7d*E;TH|L>RL-7-XKjN%(c++QFVNdR9T`AY%E z1vu{Z)=z4m5qGTKVqrO%^}FZ+zCfNV7qj1HP;JeMvz{->!sx*^h{k=-MCRf@+9BIQ zI-&I`_Lgr1%1{-`P%@-I9=T4~y*Yhj|Nlk%X!4R&b!?!&yXX?jsUnUR4$1S z;*#fhlej=?Ql2-(l@_+7gyn9RJ2x-SBBvI4Af#1$)Yps&!(If1(K(B8aThj(tB!W;nr^KuVlnd z@>lblpcqaHw`Q71Hk83Y;3O8aWw>>s=~~N_teK`+mYKF~R%NH;qMW{#zD1*~qY9^5 zCl}67ej;0$pR4sc{RB99lEvC7&l_-S(O)vC0^1^nP$$)5-W`f`;&>WSB!%TQzHr#l z#TnM-dUCUK%X0Z#d*_9hO+tV1m1JuxW52l97U#aTbNq#F!qe<5Vs(hWI1CORiPkw8 zv54LTP4V}J+btGrvdxmP;#JIu<4SMy`!9QCC=(rj%mOs7?QdHcD$C*u3kwXG!+jFh zwt6d-44?h*xZy&$drC6VZJV}nklt*tM6NkFWz?A7V;1Gj|90VF-qV#$$#))y%{jEZ zD&ol;Ft%6aie1qk#*8&v^w#Xr)d6SkjSr64cn4vBV1@l36a3A%_FSmy)PnB;pA}F%k+R)Kd&sRWrf*e_G;lav;Ihgo zyDpTZi5oI5xjswlaa$}dw^bf-D-_f%r@^om4XM_vrCLW;hTBcNINKELnL9~mBEN*7 zFD(XU>~Rr@0mIP$ZPN>gY)IC?0tC@PD`PVGNs_T9gX?9Nt2-Rol>A5dB~D5DRq zhf17}Y@ClmVh|i-Ju{?prJP=s6fqcFDu1%4Fc5Gha|$WinXOuP8HYXIqj) z-?n+CZ{ICwo2A5?m_pyBI*A-Ij4ohoZyCpCq*l~n+$@&U`aBUmTbuTi@XCzbQ;xYT zxy(I4(nBqn1arUSfv$mWGyB^qxMI{r;zqAaVfTpF$wiQy>;acOzJgSeqQnZa8Q67- zxkzs|8}u%lCu}!_?KVooa&1_lkTd9_AE+ZbyLZV+Tl>mEJi!zfLlw>cak>1rg+!|V zedo6WObpNm|FZjgN;C~3YUI1MSUOt$#G5Uchtge%eDlFHp%}%wkcqX==`KWb>qN0W zo{-`~CdD+Yax%fxDu}`nz>yjacK^CLmwo1QrWyq+?h;&*opy=2WFv7f`u`+1i4BsY zG)vrTtziRr=N)lS-?R;e3~)Q_p6Hmr42Yn=0Q_DYPccmqx_sq2gv$^a6rqu{lt?5s#g)|rLRoCKWbtF=2)17gMdyp(w zhl@efJEGbtDPy`xyl9TU!__r2pp6K7p&XI61QB<{cG+U6?yxkfYyZbJ^zXN!5Z+i@ z4Yedd{(Z+Y(1yFof7}!e(5GvnyLBr?J@hUMuPS8W`=lG`{5}KR1@V2-1L)*x5{L-&W_g5`o;`nKg$-KU0+ zEyrx%>Ao|_96E==Y_Zt*w+(-4e=~AVDIQU;rRyc@6>HV+O5c^s@1;v5OXc&_2qer8 z)0Gl=Cut{nzM@3kMVD{Lw{)?|(`iJVtqU1KmTX&BD%+*qqiZlU7#qy>mOZv6yL^-O zW!*Z%v&QGlYb~2?8|?BC#=(|q+iKk-#ub)TwkPcJ3S))2!qV4vwSA;^r0yDnJk8cc zTV(8H?ra;N?W?OW$W>CM+$nX+)3hnZ6f@#1JK^OiHcrg6TzHzATF}iZQMVYKGGc?A2+lsNSG4}gb zgRRWMUh^fHoMjf9#Z_iwfdZk^Ry5UE^gW9ujj@m0uT=(i{SOu^60woR8hx3W-4~B9 z2uW&Pnc1r`bThg!AZ#KZDZ{1)9_~N4=s@%UDLk;~r$xhl+P&o>k*(YP6Yce4^vgA*iX;&& zsazBNYW+ddE4u&0_t9gdg2@)cGq0hB%!E$lnH}JZ?Gpxgecd7^tF7Cp!s~Kx%H?E{ zF1dYkM>;BVXM1O7+*-J_a9#R_+(Y4`o{zjI!$&jEh4pCcaw|N&e79!I_ta%P=y}$& zG28SJ>uI95K_*=zXaEP|*5!wiAxy%Jq@7)44oD#~hkpX0F;eBl_z%H*6ie zeopiNRYv=ER84Q+IdXMjw^hH0Z^W#x6%HLVt$66;XkmAtZZe^6>Iuh%^wRvRodff$ z^KY>%uq<>eaxUroM0aH$Z?AI7L}GpUi`|b}&scx8%A9PFMq3eky;Btt(n`BJY+8v4 zNT;N{oB)?qzIeJ zP(CAVZrZZ6)oGj4Bx&}Fr<#c8vOWLP&1g*G->Aj?$2JGDRWH7(jBowNU-nqzp9ixY zUm|`i^%vhTzT@hq;`gHQZThwkN(&O7G5qB#Qgjqo#DR&yN+i$Sw|H&V)iu{`EFV#I z=8fa`GPcG`c0T>|tGz069{*tU=#Mtl^WBo!?0oEI?&5-F>YYfSu-sIQfx=y7#g&{K>Gn_M$XSnXSEU@mC>@}UW zC~9;y`Wi!xkv~L<&Z4sl7QxEfsMG4UdtC0+G;0wpvgBHO(O#BvYZVz~skGj2ebKs~ zzGL~!YSM_CdwSgXuNJuGNbJ*i_;=cX=8U7dO;^<1hvbtj#J8r4cN1giyavk2Kpc&kNl6lyK!#5Wg} z+o%vOMD;hPLE<&<#>bg}!$WUq;s!a4~7$w0|6$sq|Z*^Q-XP(g;aeVmQ{ z8X}gT?7Gtkqav-f%sAN2*mbS74qLNmDr&1wW2sH|lelrov{XsL-9Q!A+$usU@hd?| z+vkETacMUb+v~6+`FA^%|2-pH)N}pn!>HxbQOmtb=TV2%VR0n%S-*Nm``!$V{n$X| z*2dWREf!syzGE9Q)z!WL+tKXk3IvSCe53I%dEBx4e){gdJ3OLhD`vWG-;A&C{%-o4 zVnz|m@Ni`m~W)F2?4tn2EtgF0X#UI`mnm(OUOVngUlu82~X^f zF4xClb}ec(rqa+_v6*lGL4_U_+2vou{N>XaWWTwc{o2?sTWC^on~`CViDRFDAyoQm zYa)Ktnp8$Pt*0dZUaH#XD9;s$rC3cXkpIlWFAI)Pwl5U&`~0Z}m(iM5#A0#npWw2E*UG(fY<92G?p^0k7WDGd;@)BeXD(&eS3T-eR7|p*t#so zCuQX`q^qTSq$j1k)ZQt5=Osi)BK=#>42ZuHinG4$(}C=2OqG?0Z=Bl^L}z{HzkadT zuil(eexIILP@LuE-aSCUkrERDqlVP*oITby4*i--n{W!yo&!*+qVElRh$dYoU`xu zo;~~C?4Et({n$J%4i;A@^_AgkqwxU1UCoSzo+X_kUH*?Nzb`zlX|L?zH=X_`OJ9B2f*L*Yc&0w-? z3|(Je{*C=ZL>FIz9ru2M%{_d1zPSre}<%?F)JuG!D+JF}g|~=^8&leZT)O zo0dgaT-Cd39T`281MgRX)Ot`64t<|^1^Z%JQlyh3{~iw}srdS@WV3@X z;WYKD zdY|*X5IC4`11oZNzt&U)Ui|mHHZi!c9dBBV&A=lBV>aS32B$gkIBO*zmpu53F|3&Q z+rf8tyqq;J`tR@Dci%hYEBnp(&tIAN_@$#0XJ2`YhH^I139@6~_|>nz0bdf&3EWu> znpuL*9`tKq$OJ>wPhw>NylQTG0yI&9%rTduKg%b3o1=v{NE4ZhC zEpV0|&Ehj?8(s8)uI`)|>CYdp8}!?}(DT``veU6G>*!HlS@7B-x1s^hT^tW7}nAs+oDr z3Z{#Bg?YvDBj-EZJI;6A|Htv6?^B!J=_&Cck?*G zAK{OKDU$I{f63k~5nXbIh6Ve2ZVeSa1zUW(2(+%a7@n%eTqDpu4SVw{E}g>C%@< zPn2rxDx+F=%w!6vBNeC$SB){UXAlZhfCDmyV=)&7$qf|+P=0%{KMx^Ja8{H%6l#?w z0J0d<%tB>Ya2=l;>?)mb}o2>%#KbHa4VsnPTi-5u6QT-9+Jb~kO+ zynWj8xuK-g4Gb;wp;C9T50e9pZ@X>g3dqzntrTiG6+fr2TGPuSVNC7lc!H#_KSR=I z_I_pbjvA|jS6RN+J2;B(q=r^MzA!xn!W<&C(j|*T4F_*+6Y%uofFS?o7ne-97AiD(AB-aTsc~3yW`~d z&Y%C@$va-Z`|cn8=9LOuUb?x_rf8J4<5v5V)6Yy{>hH} zfASO1g*MQI0nmkdyed|{%XMC0WY~(k6(fp!@cqng{4M4we1OqBrueq^b?Q9w6l?4s5(-4yppLL z!+$u?u&^T&r9_Mj)hNm2)7eS$B@O;%)<0%;44`!;ms_q>%TCv zc5b*odv%wpFE~HvS1nxd)n(&<%P1*(-A(1f==dKqTU(maI{E_e+$J|87W~w$v66tZ z+8J}MaCSLU&M!KZ7QN|O9=uhBPJOLh9?;o5&Yf29R@s-CF?|0s9)(_~LHICU2hTGw z*f7Xsa>2Tc$GkJ|b6cmzqo#4ni^k?p&P*GYW-WBKV{5S1GGpylq5yNxEnD%Gq~YTZ zI%K=@W3pN#H^2S%#OE&jHOn4>$3iUo5op;Ckmg$E{zIsE^2Gx-eRDC1J>Yfp8e7I` zo7Y>uZDEc^a0y?MUr}5VDXMJP+FE1-& zv{BBCR8h=mcrsK}CxSTmP=2Vb_Bp&8>Pi5Jy;Z24vkv1&&^B={E)y3=OdUY9=P6LUl;Tj_9WL%t+}*X@i@UqK6?ZKT7k9V9#l5(@yZiRN51W1a zvb$e*lKC>{%w&>(GC7%mY z7_4&y`^x}37Hn?ro+#vyNwY8R29PV2awN}uY(fm+<99-5+8u`B7zOVyb~%qK^Opyz zdJ;)NkluF-V;8D42i%4|7IWmU%iF?dwNfQ6i_f3wo%7nPA~s-hCK~%kw+QC5O`UoI zdRj%aSTf~COk(}$D726+Dhmo!r#u_|$le2S@Soh*5RW!V?X>i<^ldfgd z*9gkJF2*7Cx|ybvIkT9h_4v{$nwyu7=U>h--BJ=sC;A7tQ>-}bv!>B%_Fv4+!k~+x zFwF1Zpatzn{4|Qvw1MS6Ep`5Ia3pW_RLtWJM|Up->gr_b>KKm)T-WsJDk&Qz9Vi=_ zNb561>R?g&&hKf0wN2J4w4a_dV%A9(Z2*QgMK+l+wfZzeH%K9$ce{*qKdIXPMhpqr zr((qm%J{`jXlI<6g)G~3FogdAqqLmX8cy#Nlb)Ax%Zs|;&(yf>*V=BO410vCOhf0& z&B2?lmubjAfBUnwudMdPKE9(rjF2}~F?xsMh5yhr;NJC+b}a#We2!#%H#ZKYYh>6h zZ^avaYdE*Whn(S@L<#-n%rd_gXg^@T_EpoN-nxB&F2_|wU-#tiIfKKF?zxW!HJ|<` zzxG-`+mdcy_j{Lm?3uKdu+(|A+cBG>&ARgIIvz&$7a06LVUebK8+Q?_lfXlDE6CRw z45lt@-BuF8cPFHcl{&iW7Tu0?#}tvk7m+~C0N90{cda$)0ck8JH3zi;{_^GO#cE?N z+Gg5xCX?p!m4BuFeC2vqPx<_FO|@d}f?`FqAS?z`;?oCp&lS;)a~6%fS)Xj%CMjJh z;T-?|0RPPl7feOm%e+pv_?6n#r0(2NUT}x>N+1{li|e3!{mM%DXhdK(U&;}9B0%k$ z@T*5`t=fyuE$C&BqH96TjM>8=e={Z*hWsO)O#Z!fW1wBYFB;l@xx0>_k|*x!EnbmRKWyEx z2I&eloXr9G(tadg7i!chFPWKc%jwOR9M4)$J!I~r5VemSo5lEYfYs?;e8qNXv&U~O zYi6zF>?(bbeqxl1ars+uLRP;y+53t|i|In3sDE?kb60T}af9RNA(!y*1V%q*y4ai* z%pfaV-(opCt%RtJ9$D&og~M|B9~vUKF7FShg#4Laf?zzWm-sk}EvVN>l-JVcA(^Y= z{L*8f$Z_LaPAd;7HGHWg3P9o)1&_@bS`S8ep&!OOVHS7Pxa5!nhS|r> zhTq#dxuMV=cE&a4o-2s??UattiiP_iO^y<_SW3k`{+>9_T5Dc+nlGZTyD|J`C zX}Y$#;|sCV^eKE)DsZebIUOHiu5VxLtmxbSZFz)pz>}TR;V*w`(y&^a#bjbj!f;2W zWk|p&QJF)7P)>TfU>W)59wryzJ?$+XuucGinwT|4WklU2eedTZuW zjlDwAwhlH`kI-!^E?xswfz_!#mD^W=ohBPqEPnLi#7w?F-1F10e7r>O)q>6a8s~ut zM_BS_NXC}4zxW)nQuy)-9O}O8`Nm4fo6;iv3nPW``V<;f7mIr(#%ag3zknUolOKm6 zxoce|-gP@&s$KPh^9L1jiXhWTg{eysmg*igbW>5yS~EF$z4-)Fws}gp_ppCOQx8Um zn)=DQoKd)S`D5z0$F3-Wul*6NQw_9{oy@aKa=axx0I`zf^XJW{2#2xv&A~)U1xxo8gVG3+jS(xG(@4(s$bBoea8X-)YIehnLA;-~VPiv8m z-a^DZN#(L1v(|yAUm?<?Y=2HM|u6<;mB?q%(d8KiyT6fB@eqmop5EZzG>3tj%&1UzP`lTP^csZ>|iD zSDs8K^+MZ`DkXew9+13Fy0kxlqgFS*HXgJ0rnAfkZ@rGZ*DD@43xq}vrNSPhd z0+VL7%N6qH9&VpqB~ZUNf*GuiUyixN?8>`2Jk8#+rw1S3I`-+Og9P`T%4fEXMAWSn zfc<+c_(>Z2Fp+ASa3)yw(Qt%dk%}d}Y_>tW`(|^9{n>1VQoz461O}kk%g{|Mo^10k zs5L;p@AuTNRHqM`HUsdP&VXSwmHCD*n1{^;^6m5)}&R;IFSmfQYeXl>?(W?g*GAW z?H10;t!R_3S%|AiE}D7fa-_Z%TEeeEW4mvIS)k8lz5|4A%rQ+G>+id-zg&cT?&d1# z!0t?WvqY=OkMrk~m1*uSFY45;r$E^oVYQ2^HtPvU-*f29GK4I4dK+QgaR74B57W`R z_eL~S-PotOSf#I*^U<#`q&C^WF;Uk(V0ekb8_Aa%3%ih zO6VnI)?!Fy4ZF2+=v2y{iQ+d;g!QL;x3Mh$nx(VdFJTVF{JTGKx>B*(GD`@BaYvrH zY*4myM-^u9xKd2`V*YsdCm7F~diwk-m+`pb+wE@f_m2eT7?z(2(r)o+yaw>jdgHG7 zKiKhREkN)#a`9i<)g(9?>)UE%N>stn5)Q)(CkAwkOIXjtK0G|2JavSS*B^OkE72XB zvH3q@*1p|&bV?-iTC&o)3xTmec3cXS6*jN)}w5!NNNRg&62cem-!a5=OBA-LFgNyY_Guz|` zF;}}D7RPJB1L^7OMM55d=&zH`YW6n^x>bZfJCaV_suwRi5F+bSf|r%AKV+aAgWUBi zjuBsBn-}_!@I~n3DtX{~X?o1*BTrhFQix1DTVpSf1repZ81%-%hHZC!0AQjc`RAIP zIp(6wco=*(YS+jq9pZ@$M~avDhxoT4t0UiC|BT*kOklle7EmuE-I$#X7kPWw*Bgzr zx9+}y1{hH`l-&EJV)xJ6_sYJ9p5-* zzzl9SAZ_n!lWB_Vp7*T0S=2w1a)1M~I-RjGWW#1@2s}DY> z^?SE=?Pys*8fyTpap`fF){+uJK^$6S$YMS0GNC7VKWa$RzhYJGBf&q~%{MKDk@VJZ z=nYEN%irm=U2n=#%a(+|SBdPQ$&_Asf7{K+422_qel8muMV^J4_uq6rE&NoGs0k^b z{Z#RT%3pm5$q1_sTI(~d{~dzh=RXISQnR$I9N~%sfvgSaK-VHURouJw{6NZbO)(c= zk*O1x$Y2;g-@|^8MHAGSJ%r9GyEcC&oGrx=K{^Kqy#yJ(fM+`zVoTE}9(LtszI&_> zXs?WkQ0EZC4ID({r!r-gOar`Trx`G<8V$@7U)K?Ot0@$h&{+-d3Hyi!uct&dU*da) zpdVu8l>AFI)dOaY6U7f!H0tgdCbLmYCC7LB3keTsWv0^(s27`|p<KfTm?_FWcEs&j5txG0PcW|rLJ4VJ@hO;7=?O}*E(ci@`LsN*ii8Fjh z-u`~YtC7Ncvh?Izjy0yWrsUD0u|JV>%qjhb)J~Z59?L^PQB3^lB%PQ~<(V}i%@D9VV_jR&SBs@p| zan1lGpd20lK%Grz11$(E{7{(4_od-_BCj+5BOS$Qzvku7jNXjzAmaGuKc?P$xA3wS zBcCuztL?>VgULP~cpz_bSwjn_n8ALTHjF%(*0H&q0i9lQ2$Xn~!ZyfasY-t(Dc)}w zH?2;wsv?zS*GKf%2G(<>|F*KWOh4Jn07&Z`^Y5F=C8Y2+Ba%qzNX0QzMHnVhvx`T^ zsof~JB}TZ<%=Np3(o^f}La1ViSgt@C&*pMpg=@Z{3rRDznnbiLv@CPlxKNv^2_Uof zAO4QM1!fhXMv~Nj-_Yp!{?qwQlkC+^o*;u;j;}mI$V*>B_EVRQvEmSPx1ZE=rR^!i zV@*t5kfJ;Eauma`NYZK6Brh~VbAVQ+QyvjGPOo;0!`ggpW{uq_X{H)*f11^zeotbq z$l*(r1-H9N5TMezVGw0CK6(py@fa0?)@d}U-5U{RKIhmlZw1t>)d|=Sy$0^J_Rt3y z!lL8_>T#G=HHCLYX;yzV%ffc+X&;a3Y=<_mBiTfSl?4y+T8dK=o-F~Fk0T??kA*E7 z#Tnt^hWFb0F9949OgXNM_cDA6saHm}{m7R?&6U^?FbR zp0IuG?COfWT~ z8uw!dr}T6>hDQsLGi_FP?k@r}u!}ho4PoK0+}GLxGc@B5*cp&yca#MR$Px#Pg1;X! ztQhBeeIXSD0tNp@sh25={$g&e2HMx{lZYAsp)8`LZQ+X8ZQgkX84Tjq$WI>D^wN;< zxi<%Dl=Pm}l`79xNXL0_mQ)Ie{E~5v2FX`4#v7X`nsFks%VpcZQ+-iQ>XDIta`)fWLWua?6Zr6ql8oeX@8*}GbAn$@|GvJWpR`JK`&jHuP5&B=E zb}Mw?HNc)CIOmnR3_zQX0mumU!q)nU(8VTqc4)GpHrJKW4Y~t-@8<{&YG6tNR2S`K zLC*!uX%5tV(q5`0!LFDP43x(wDQ}8eRkKQdW6H4i-sGI7L--z9qPTb%9vX`n#|!io zbPAe)w%s&FnYEb{5l_~ z;2u0;G`&&^CMi`;r?h-2x3(K)3L7f4oCLyA%Q0aKkxDn-R7vcnzb$93ZlLuTO}=bi z`HUG8`IhE)89ea3Q&xeg??Zo3(hPQvis!aSUPH)inKnH z(28+_5gguSBl=iA2WC`H9Rq>mh+ix$eH{D-U9Zfo&1)PiSn1OZ5K)6X_BadH3b&e9 z{}=Y16+MMkm}kS0*J3zrhgG!dCjnLur|s+S_z(K`EG zsS+-k8fd&*TSSd~@ZA7<#SiQ^S@a4CxYBlXqss`QP|VZxuQE1>NF- zUrGaYkvV! zrG$`QO9hMn*TLO*geZRWpYf7p4F75Trj-!-3& zCddj{azpHj_QGoz={KZv8W(9!i@A-{J+!&I7`Vl*L@}9u+jE4B(#oymkCb=Qo#?k! zcXxuL?DMo|b|$!@b7tRrfZ;vh?qkQDYMMmcfUUa~O7lH5}OZ#k(7Bw_Jkp?v1->@=*r2bapJrNilpPvmrpv!5<}z{FWn_|P_2bI zK1$7)l`y{}p&npMqV~}YiZ7&N;7BDa=2#kxX?5W241;yHR-o0WFIk5u4>THocw&tk zLh)#d$~@Mgnb$+Tr%bITOMN}Zc}n2CRc0zO9Rl$hTJND1-NmW3Gvd*WS$EQiBASz0 zyrJG$DxBPq7V)#2>nw>XWKQVFpQNeZdI zM;py$1hJ=^CU*&bv(Wls><(Hi9nCvWgUwgqO0GzFV%AkD6YnWY1ujx5_DwBeB9%XCagY)@rio2VsC6C7Gb!cO8bG8hzF3m$G7k zCrV$uhgIv97;o=(Wo4*WWkkkJgEr9MJmb5O%m36g?(j}l;%ixt93{%43n^B(O`>Mi41@PS4TM)IJWxp#&CH}EY6U7s{0bIzvM|UM zThZ_ruQv19*I%+D$x+UlZQ;Aq@dUdVqzrr-W^wY%@`)>gX27!eOLVotH+$E2DJwtMnSI%W5jrTP&4F1B*17(e|12 zYK?jmKFewzb9j!Atatq+O)jPg*h&^1?nlFH4pAe$@yt^)_NfDwxw>Utv~Bt?7oa- zp4cCy22Dgr6zO(%ck424-3p~fAb0nrs$|mD+3n$5it8=1G@X$N1)sD9@`bE?wVL0C zFtG(%NAPwGRl@f$)qJ&EC`NNrV@xqnVSTqP(VRIRxGGYmMi39V0FndU(} zi73jm7=HoKBEHCuPF!4lB!d#z@I{7EO6IP3=uc-v{JSmM__)uNG93(CrsAc4;+3Eh zSv(Myc~+tnyMttIIyqw-V4)SJc9Ii?BMZ**$O8kF4x>wu10S3VO)-L-zz0ZsKa_n6 ztF%hN<;>O5Y8vHpHc_PYb>(#E0S#5f3ZFVu1&B)r$NRR6p6{!2ke>?;RGu$yR}&ySUVq|&QTHF9E5#dJBi(qCc<&E*puYW^je zs1j!P2P%6M>=ke8cLp`Eu0>RR>w~5X#!Ai8ZsFpXA|{gh;)>G$2j6f`q>d+!6Ur5y@TaS+ zk1?|^l3${@^DYa{W#UYQ6g&@o(mnLtNs{lJ;GLQk-4K|98wy}zuwt5+gLc$(3 zSuu#F9d5i1qbougHnEzo(5^DBg=Tf8!&8Zi=D^f~&*g*BT*X-y72I0*@Z3V^>|{e* zA@_By=6$+4Sg7Rn(4hZgIUsObpi0uXoiWH6{&Bcg9@`xGp~1S5JSfvNjchsk+`kOb z^yxU?)$sICt`^hTlc6yDRe|t_!?Y03t4?smTw}Q0uj0l2WCGE1$yCKSo6h|Cx`S>` z`N&v>G`rkJ@jN$;C;i1t!}zTs48{~|X41V)ek}X__1+8SH~sl8^i7GsjSZVnDd=GS z>%tpwPHY7Pw+Jb#HNZ&o8|c(Cf6v}$Ac6EsNz|JiWDKsDQj8wi+2{%xaPW}xjDl;G zo#N>}q3v)Cm0GM^E^>G=rG$4IG^j~6`PFh5xmxFL9C0ba%i~zsJlA*Z4uuFL`uP}N zODZZTz)!w^(9D+iQmy#_ToCm6Ymefj7n)2b_dX)DPNv702|83npyws+{j1=S=aqv-%==Ht zKeuKr1VKg$RpP`Sl73u1GMjqdIVJyLr@y^*yZKKC9RQW4mJIN z$fus5c|T9oH!ilLH--NW$mAhmA+a;IMB?WsVgA2yMA_K?H;!n+sBI7nn)rivNa_*U z_BT;{L{iErDTZgISzjoCXrx-S$xvW-b-FBiSxOHtn_H+A#Mc13$X0U8Z_yyz98(@_ zB`fOJ7}=lBRC(Vg^|ulqXS?~BZs)1$k^Kv~OOdT7vwX;E<2YXw+iyABI$`4kZO`&3~}+S9MhePzihSEpJ&?mHM=~=k7<}l`VA0fU+|m( zr%GFw+!dD!XKO+x(3b2`c;fd&SUwT+T*d%yRv?6pA4_x13#R2~vB^o#hf?!*q-q5& zi{+7^Haxgj|@|8#VAcQi3YVg+y_QBsO4N+A6Y?XIm3 literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_driver.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_driver.c new file mode 100644 index 000000000..5d44f2da8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_driver.c @@ -0,0 +1,1713 @@ +/* caam_driver.c + * + * Copyright (C) 2006-2020 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(__INTEGRITY) || defined(INTEGRITY) + +/* build into Integrity kernel */ +#include +#include "wolfssl/wolfcrypt/port/caam/caam_driver.h" + +#define CAAM_READ(reg) *(volatile unsigned int*)(reg) +#define CAAM_WRITE(reg, in) *(volatile unsigned int*)(reg) = (in); + +#define DESC_COUNT 1 +#define MAX_BUF 20 +#define BUFFER_COUNT (MAX_BUF * DESC_COUNT) + +/* CAAM descriptors can only be 64 unsigned ints */ +#define MAX_DESC_SZ 64 + +/* 64 byte buffer for when data crosses a page boundary */ +#define ALIGN_BUF 16 + +/* MAX_CTX is 64 bytes (sha512 digest) + 8 bytes (CAAM length value) */ +#define MAX_CTX 18 + +#define MIN_READ_REG 0xF2100000 +#define MAX_READ_REG 0XF2110000 + +struct JobRing { + Address JobIn; + Address JobOut; + Address Desc; + Value page; /* page allocation for descriptor to use */ +}; + +struct buffer { + Address data; + Address dataSz; +}; + +/* CAAM descriptor */ +struct DescStruct { + struct IORequestStruct TheIORequest; + struct CAAM_DEVICE* caam; + struct buffer buf[MAX_BUF]; /* buffers holding data input address */ + UINT4 desc[MAX_DESC_SZ]; /* max size of 64 word32 */ + UINT4 aadSzBuf[4]; /* Formatted AAD size for CCM */ + UINT4 alignBuf[ALIGN_BUF]; /* 64 byte buffer for non page + align */ + UINT4 iv[MAX_CTX]; /* AES IV and also hash state */ + UINT4 ctxBuf[MAX_CTX]; /* key */ + Address output; /* address to output buffer */ + Address ctxOut; /* address to update buffer holding state */ + Value alignIdx;/* index for align buffer */ + Value idx; /* index for descriptor buffer */ + Value headIdx; /* for first portion of descriptor buffer */ + Value lastIdx; /* for last portion of descriptor buffer */ + Value outputIdx; /* idx to output buffer in "buf" */ + Value inputSz; /* size of input buffer */ + Value ctxSz; /* size of CTX/Key buffer */ + Value aadSz; /* AAD size for CCM */ + Value lastFifo; + Value type; + Value state; + Value DescriptorCount; + Boolean running; /* True if building/running descriptor is + in process */ +}; + +struct CAAM_DEVICE { + struct IODeviceVectorStruct caamVector; + struct IODescriptorStruct IODescriptorArray[BUFFER_COUNT]; + struct DescStruct DescArray[DESC_COUNT]; + volatile Value InterruptStatus; + CALL HandleInterruptCall; + struct JobRing ring; +}; + +#define DRIVER_NAME "wolfSSL_CAAM_Driver" + +static struct CAAM_DEVICE caam; + +/****************************************************************************** + Internal CAAM Job Ring and partition functions + ****************************************************************************/ + +/* flush job ring and reset */ +static Error caamReset(void) +{ + int t = 100000; /* time out counter for flushing job ring */ + + /* make sure interrupts are masked in JRCFGR0_LS register */ + CAAM_WRITE(CAAM_BASE | 0x1054, CAAM_READ(CAAM_BASE | 0x1054) | 1); + + /* flush and reset job rings using JRCR0 register */ + CAAM_WRITE(CAAM_BASE | 0x106C, 1); + + /* check register JRINTR for if halt is in progress */ + while (t > 0 && ((CAAM_READ(CAAM_BASE | 0x104C) & 0x4) == 0x4)) t--; + if (t == 0) { + /*unrecoverable failure, the job ring is locked, up hard reset needed*/ + return NotRestartable; + } + + /* now that flush has been done restart the job ring */ + t = 100000; + CAAM_WRITE(CAAM_BASE | 0x106C, 1); + while (t > 0 && ((CAAM_READ(CAAM_BASE | 0x106C) & 1) == 1)) t--; + if (t == 0) { + /*unrecoverable failure, reset bit did not return to 0 */ + return NotRestartable; + } + + /* reset most registers and state machines in CAAM using MCFGR register + also reset DMA */ + CAAM_WRITE(CAAM_BASE | 0x0004, 0x90000000); + + return Success; +} + +/* returns MemoryMapMayNotBeEmpty if page/par is already owned + * returns Success on success + * all other returns is an error state + */ +static Error caamCreatePartition(unsigned char page, unsigned char par) +{ + /* check ownership of partition */ + if ((CAAM_READ(CAAM_BASE | 0x1FBC) & (0x3 << (par * 2))) > 0) { + return MemoryMapMayNotBeEmpty; + } + + /* set generic all access permissions, gets reset later */ + CAAM_WRITE(CAAM_BASE | (0x1108 + (par * 16)), 0xF); + CAAM_WRITE(CAAM_BASE | (0x110C + (par * 16)), 0xF); + CAAM_WRITE(CAAM_BASE | (0x1104 + (par * 16)), 0xFF); + + /* check ownership of page */ + CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x5); + /* wait for inquiry cmd to complete */ + while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && + (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) { + } + if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x000000C0) == 0xC0) { + /* owns the page can dealloc it */ + CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x2); + while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && + (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) {} + if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) { + /* error while deallocating page */ + return MemoryMapMayNotBeEmpty; /* PSP set on page or is unavailable */ + } + } + else { + /* check if owned by someone else */ + if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x000000C0) != 0) { + return MemoryMapMayNotBeEmpty; + } + } + + /* allocate page to partition */ + CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | (par << 8) | 0x1); + /* wait for alloc cmd to complete */ + while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && + (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) { + } + + if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) { + return MemoryOperationNotPerformed; + } + + /* double check ownership now of page */ + CAAM_WRITE(CAAM_BASE | 0x10F4, (page << 16) | 0x5); + /* wait for inquiry cmd to complete */ + while ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000C000) > 0 && + (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) == 0) { + } + if ((CAAM_READ(CAAM_BASE | 0x10FC) & 0x0000000F) == 0 || + (CAAM_READ(CAAM_BASE | 0x10FC) & 0x00003000) > 0) { + /* page not owned */ + return MemoryOperationNotPerformed; + } + + return Success; +} + + +/* Gets the status of a job. Returns Waiting if no output jobs ready to be + * read. + * If no jobs are done then return Waiting + * If jobs are done but does not match desc then return NoActivityReady + * Status holds the error values if any */ +static Error caamGetJob(struct CAAM_DEVICE* dev, UINT4* status) +{ + UINT4 reg = CAAM_READ(CAAM_BASE | 0x1044); /* JRSTAR0 status */ + if (status) { + *status = 0; + } + + /* check for DECO, CCB, and Job Ring error state JRSTAR0 register */ + if (((reg & 0xF0000000) == 0x20000000) || /* CCB error */ + ((reg & 0xF0000000) == 0x40000000)|| /* DECO error */ + ((reg & 0xF0000000) == 0x60000000)) { /* Job Ring error */ + + if ((reg & 0x0000000F) > 0) { + *status = reg; + return Failure; + } + } + + /* Check number of done jobs in output list */ + reg = CAAM_READ(CAAM_BASE | 0x103C); + if ((reg & 0x000003FF) > 0) { + UINT4* out = (UINT4*)(dev->ring.JobOut); + if (status) { + *status = out[1]; + } + + if ((dev->ring.Desc ^ 0xF0000000) != out[0]) { + db_printf("CAAM job completed vs expected mismatch"); + return NoActivityReady; + } + + if (out[1] > 0) { + return Failure; + } + + /* increment jobs removed */ + CAAM_WRITE(CAAM_BASE | 0x1034, 1); + } + else { + /* check if the CAAM is idle and not processing any descriptors */ + if ((CAAM_READ(CAAM_BASE | 0x0FD4) & 0x00000002) == 2 /* idle */ + && (CAAM_READ(CAAM_BASE | 0x0FD4) & 0x00000001) == 0) { + return NoActivityReady; + } + + return Waiting; + } + + return Success; +} + + +/* Initialize CAAM RNG + * returns 0 on success */ +static int caamInitRng(struct CAAM_DEVICE* dev) +{ + UINT4 reg, status; + int ret = 0; + + /* Set up use of the TRNG for seeding wolfSSL HASH-DRBG */ + CAAM_WRITE(CAAM_RTMCTL, CAAM_PRGM); + CAAM_WRITE(CAAM_RTMCTL, CAAM_READ(CAAM_RTMCTL) | 0x40); /* reset */ + + /* Set up reading from TRNG */ + CAAM_WRITE(CAAM_RTMCTL, CAAM_READ(CAAM_RTMCTL) | CAAM_TRNG); + + /* Set up delay for TRNG @TODO Optimizations? + * Shift left with RTSDCTL because 0-15 is for sample number + * Also setting the max and min frequencies */ + CAAM_WRITE(CAAM_RTSDCTL, (CAAM_ENT_DLY << 16) | 0x09C4); + CAAM_WRITE(CAAM_RTFRQMIN, CAAM_ENT_DLY >> 1); /* 1/2 */ + CAAM_WRITE(CAAM_RTFRQMAX, CAAM_ENT_DLY << 3); /* up to 8x */ + + /* Set back to run mode and clear RTMCL error bit */ + reg = CAAM_READ(CAAM_RTMCTL) ^ CAAM_PRGM; + + CAAM_WRITE(CAAM_RTMCTL, reg); + reg = CAAM_READ(CAAM_RTMCTL); + reg |= CAAM_CTLERR; + CAAM_WRITE(CAAM_RTMCTL, reg); + + /* check input slot is available and then add */ + if (CAAM_READ(CAAM_BASE | 0x1014) > 0) { + UINT4* in = (UINT4*)dev->ring.JobIn; + + memcpy((unsigned char*)dev->ring.Desc, (unsigned char*)wc_rng_start, + sizeof(wc_rng_start)); + + in[0] = dev->ring.Desc ^ 0xF0000000; /* physical address */ + CAAM_WRITE(CAAM_IRJAR0, 0x00000001); + } + else { + return Waiting; + } + + do { + ret = caamGetJob(dev, &status); + /* @TODO use a better way to chill out CPU. */ + } while (ret == Waiting); + + return ret; +} + + +static Error caamDoJob(struct DescStruct* desc) +{ + Error ret; + UINT4 status; + + /* clear and set desc size */ + desc->desc[0] &= 0xFFFFFF80; + desc->desc[0] += desc->idx; + + /* check input slot is available and then add */ + if (CAAM_READ(CAAM_BASE | 0x1014) > 0) { + UINT4* in = (UINT4*)desc->caam->ring.JobIn; + + memcpy((unsigned char*)desc->caam->ring.Desc, (unsigned char*)desc->desc, + (desc->idx + 1) * sizeof(UINT4)); + + in[0] = desc->caam->ring.Desc ^ 0xF0000000; /* physical address */ + CAAM_WRITE(CAAM_IRJAR0, 0x00000001); + } + else { + return Waiting; + } + + do { + ret = caamGetJob(desc->caam, &status); + /* @TODO use a better way to chill out CPU. */ + } while (ret == Waiting); + + if (status != 0 || ret != Success) { + #if 0 + /* Used during testing to print out descriptor */ + { + char msg[2048]; + char* pt = msg; + int z; + + memset(msg, 0, sizeof(msg)); + for (z = 0; z < desc->idx; z++) { + snprintf(pt, sizeof(msg) - (z * 21), "desc[%d] = 0x%8.8x, ", + z, desc->desc[z]); + pt += 21; + } + snprintf(pt, sizeof(msg) - (z * 21), "status = 0x%8.8x\n", status); + if (desc->buf[0].data != 0) { /* for testing */ + memcpy((char*)desc->buf[0].data, msg, sizeof(msg)); + } + } + #endif + + + /* try to reset after error */ + caamReset(); + return ret; + } + + return Success; +} + + +/* handle input or output buffers + * NOTES: if sz == 0 then read all the rest of the buffers available + * when align == 1 then there is no alignment constraints + * + * returns the data size in bytes on success. With failure a negative value is + * returned. + */ +static int caamAddIO(struct DescStruct* desc, UINT4 options, UINT4 sz, + UINT4 align, UINT4* idx) +{ + int i, outSz = 0; + + if (align == 0) { + return -1; /* programming error */ + } + + for (i = *idx; i < desc->DescriptorCount; i++) { + /* input must be a multiple of "align" bytes */ + struct buffer* buf = &desc->buf[i]; + int blocks = buf->dataSz / align; + Address data = buf->data; + Address dataSz = buf->dataSz; + + if (outSz >= sz && sz != 0) { + break; + } + + if (dataSz % align > 0) { + /* store potential overlap */ + int tmpSz = dataSz % align; + int add = (tmpSz < (align - desc->alignIdx)) ? tmpSz : + align - desc->alignIdx; + unsigned char* local = (unsigned char*)desc->alignBuf; + + /* if already something in the buffer then add from front */ + if (desc->alignIdx > 0) { + memcpy((unsigned char*)&local[desc->alignIdx], + (unsigned char*)data, add); + data += add; + } + else { + memcpy((unsigned char*)&local[desc->alignIdx], + (unsigned char*)data + (blocks * align), add); + } + dataSz -= add; + desc->alignIdx += add; + } + + if (desc->alignIdx == align) { + desc->lastFifo = desc->idx; + if (desc->idx + 2 > MAX_DESC_SZ) { + return -1; + } + desc->desc[desc->idx++] = options + desc->alignIdx; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->alignBuf); + ASP_FlushCaches((Address)desc->alignBuf, desc->alignIdx); + outSz += desc->alignIdx; + } + + if (blocks > 0) { + desc->lastFifo = desc->idx; + if (desc->idx + 2 > MAX_DESC_SZ) { + return -1; + } + desc->desc[desc->idx++] = options + (blocks * align); + desc->desc[desc->idx++] = BSP_VirtualToPhysical(data); + outSz += (blocks * align); + + /* only one buffer available for align cases so exit here and make + a new descriptor after running current one */ + if (desc->alignIdx == align) { + desc->alignIdx = 0; + i++; /* start at next buffer */ + break; + } + } + } + + *idx = i; + return outSz; +} + + +/****************************************************************************** + IODevice Register Read and Write + ****************************************************************************/ + +static Error caamReadRegister(IODeviceVector ioCaam, Value reg, Value *out) +{ + if (reg < MIN_READ_REG || reg > MAX_READ_REG) { + return IllegalRegisterNumber; + } + + switch (reg) { + case CAAM_STATUS: + case CAAM_VERSION_MS: + case CAAM_VERSION_LS: + case CAMM_SUPPORT_MS: + case CAMM_SUPPORT_LS: + case CAAM_RTMCTL: + *out = CAAM_READ(reg); + break; + + default: + return IllegalRegisterNumber; + } + + (void)ioCaam; + return Success; +} + + +static Error caamWriteRegister(IODeviceVector ioCaam, Value reg, Value in) +{ + /* Should be no need for writes */ + return OperationNotAllowedOnTheUniversalIODevice; +} + + +/****************************************************************************** + CAAM Blob Operations + ****************************************************************************/ + +/* limit on size due to size of job ring being 64 word32's */ +static Error caamBlob(struct DescStruct* desc) +{ + Error err; + UINT4 keyType = 0x00000C08; /* default red */ + UINT4 i = 0; + int sz = 0, ret; + + if (desc->idx + 3 > MAX_DESC_SZ) { + return Failure; + } + + /*default to Red Key type, with offset of 12 and 8 byte load to context 2*/ + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2 | CAAM_IMM | keyType); + + /* add key modifier */ + if (i < desc->DescriptorCount) { + UINT4* pt; + Address data = desc->buf[i].data; + Address dataSz = desc->buf[i].dataSz; + + pt = (UINT4*)data; + if (dataSz < 8) { /* expecting 8 bytes for key modifier*/ + return TooManyBuffers; + } + desc->desc[desc->idx++] = pt[0]; + desc->desc[desc->idx++] = pt[1]; + } + + /* add input */ + while (sz < desc->inputSz && i < desc->DescriptorCount) { + ret = caamAddIO(desc, CAAM_SEQI, desc->inputSz - sz, 1, &i); + if (ret < 0) { /* handle error case */ + return TooManyBuffers; + } + sz += ret; + } + desc->outputIdx = i; + + /* add output */ + if (caamAddIO(desc, CAAM_SEQO, 0, 1, &i) < 0) { + return TooManyBuffers; + } + + if (desc->idx + 1 > MAX_DESC_SZ) { + return Failure; + } + desc->desc[desc->idx++] = CAAM_OP | CAAM_OPID_BLOB | desc->type; + + if ((err = caamDoJob(desc)) != Success) { + return err; + } + + /* flush output buffers */ + for (i = desc->outputIdx; i < desc->DescriptorCount; i++) { + ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz); + } + + return Success; +} + + +/****************************************************************************** + CAAM AES Operations + ****************************************************************************/ + +/* returns amount written on success and negative value in error case. + * Is different from caamAddIO in that it only adds a single input buffer + * rather than multiple ones. + */ +static int caamAesInput(struct DescStruct* desc, UINT4* idx, int align, + UINT4 totalSz) +{ + int sz; + UINT4 i = *idx; + + /* handle alignment constraints on input */ + if (desc->alignIdx > 0) { + sz = desc->alignIdx; + + /* if there is more input buffers then add part of it */ + if (i < desc->outputIdx && i < desc->DescriptorCount) { + sz = align - desc->alignIdx; + sz = (sz <= desc->buf[i].dataSz) ? sz : desc->buf[i].dataSz; + memcpy((unsigned char*)(desc->alignBuf) + desc->alignIdx, + (unsigned char*)(desc->buf[i].data), sz); + + desc->buf[i].dataSz -= sz; + desc->buf[i].data += sz; + sz += desc->alignIdx; + } + + if (desc->idx + 2 > MAX_DESC_SZ) { + return -1; + } + ASP_FlushCaches((Address)desc->alignBuf, sz); + desc->desc[desc->idx++] = (CAAM_FIFO_L | FIFOL_TYPE_LC1 | + CAAM_CLASS1 | FIFOL_TYPE_MSG) + sz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->alignBuf); + desc->alignIdx = 0; + } + else { + sz = desc->buf[i].dataSz; + if ((totalSz + sz) == desc->inputSz) { /* not an issue on final */ + align = 1; + } + + desc->alignIdx = sz % align; + if (desc->alignIdx != 0) { + sz -= desc->alignIdx; + memcpy((unsigned char*)desc->alignBuf, + (unsigned char*)(desc->buf[i].data) + sz, + desc->alignIdx); + } + + if (desc->idx + 2 > MAX_DESC_SZ) { + return -1; + } + desc->desc[desc->idx++] = (CAAM_FIFO_L | FIFOL_TYPE_LC1 | + CAAM_CLASS1 | FIFOL_TYPE_MSG) + sz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->buf[i].data); + i++; + } + + *idx = i; + return sz; +} + + +/* returns enum Success on success, all other return values should be + * considered an error. + * + * ofst is the amount of leftover buffer from previous calls + * inputSz is the amount of input in bytes that is being matched to output + */ +static Error caamAesOutput(struct DescStruct* desc, int* ofst, UINT4 inputSz) +{ + int offset = *ofst; + + if (desc->output != 0 && offset > 0 && inputSz > 0) { + UINT4 addSz; + + /* handle potential leftovers */ + addSz = (inputSz >= offset) ? offset : inputSz; + + inputSz -= addSz; + desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + addSz; + if (inputSz > 0) { /* check if expecting more output */ + desc->desc[desc->idx - 1] |= CAAM_FIFOS_CONT; + } + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->output); + + if (addSz == offset) { + /* reset */ + desc->output = 0; + offset = 0; + } + else { + offset -= addSz; + desc->output += addSz; + + if (offset < 0) { + return TransferFailed; + } + } + } + + for (; desc->lastIdx < desc->DescriptorCount; desc->lastIdx++) { + struct buffer* buf = &desc->buf[desc->lastIdx]; + + if (inputSz > 0) { + int tmp; + + if (buf->dataSz <= inputSz) { + tmp = buf->dataSz; + } + else { + offset = buf->dataSz - inputSz; + tmp = inputSz; + desc->output = buf->data + tmp; + } + inputSz -= tmp; + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_FIFO_S | FIFOS_TYPE_MSG + tmp; + if (inputSz > 0) { /* check if expecting more output */ + desc->desc[desc->idx - 1] |= CAAM_FIFOS_CONT; + } + desc->desc[desc->idx++] = BSP_VirtualToPhysical(buf->data); + } + else { + break; + } + } + + *ofst = offset; + return Success; +} + + +/* check size of output and get starting buffer for it */ +static Error caamAesOutSz(struct DescStruct* desc, UINT4 i) +{ + int sz = 0; + + for (desc->outputIdx = i; desc->outputIdx < desc->DescriptorCount && + sz < desc->inputSz; desc->outputIdx++) { + sz += desc->buf[desc->outputIdx].dataSz; + } + desc->lastIdx = desc->outputIdx; + + /* make certain that output size is same as input */ + sz = 0; + for (; desc->lastIdx < desc->DescriptorCount; desc->lastIdx++) { + sz += desc->buf[desc->lastIdx].dataSz; + } + if (sz != desc->inputSz) { + return SizeIsTooLarge; + } + desc->lastIdx = desc->outputIdx; + + return Success; +} + + +/* AES operations follow the buffer sequence of KEY -> (IV) -> Input -> Output + */ +static Error caamAes(struct DescStruct* desc) +{ + struct buffer* ctx[3]; + struct buffer* iv[3]; + Value ofst = 0; + Error err; + UINT4 i, totalSz = 0; + int ctxIdx = 0; + int ivIdx = 0; + int offset = 0; + int align = 1; + int sz = 0; + + int ctxSz = desc->ctxSz; + + if (desc->state != CAAM_ENC && desc->state != CAAM_DEC) { + return IllegalStatusNumber; + } + + if (ctxSz != 16 && ctxSz != 24 && ctxSz != 32) { + return ArgumentError; + } + + /* get key */ + for (i = 0; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)desc->ctxBuf; + + if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) { + ctx[ctxIdx] = buf; + sz += buf->dataSz; + + memcpy((unsigned char*)&local[offset], + (unsigned char*)ctx[ctxIdx]->data, ctx[ctxIdx]->dataSz); + offset += ctx[ctxIdx]->dataSz; + ctxIdx++; + } + else { + break; + } + } + + /* sanity checks on size of key */ + if (sz > ctxSz) { + return SizeIsTooLarge; + } + if (ctxSz > (MAX_CTX * sizeof(UINT4)) - 16) { + return ArgumentError; + } + + /* Flush cache of ctx buffer then : + Add KEY Load command 0x0220000X + Add address to read key from 0xXXXXXXXX */ + ASP_FlushCaches((Address)desc->ctxBuf, ctxSz); + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + ctxSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->ctxBuf); + + /* get IV if needed by algorithm */ + switch (desc->type) { + case CAAM_AESECB: + break; + + case CAAM_AESCTR: + ofst = 0x00001000; + /* fall through because states are the same only the offset changes */ + + case CAAM_AESCBC: + { + int maxSz = 16; /* default to CBC/CTR max size */ + + sz = 0; + offset = 0; + for (; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)desc->iv; + + if (sz < maxSz) { + iv[ivIdx] = buf; + + if (buf->dataSz + sz > maxSz) { + return SizeIsTooLarge; + } + + sz += buf->dataSz; + memcpy((unsigned char*)&local[offset], + (unsigned char*)iv[ivIdx]->data, iv[ivIdx]->dataSz); + offset += iv[ivIdx]->dataSz; + ivIdx++; + } + else { + break; + } + } + + if (sz != maxSz) { + /* invalid IV size */ + return SizeIsTooLarge; + } + + ASP_FlushCaches((Address)desc->iv, maxSz); + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) + maxSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv); + } + break; + + default: + return OperationNotImplemented; + } + + /* write operation */ + if (desc->idx + 1 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS1 | desc->type | + CAAM_ALG_UPDATE | desc->state; + + /* find output buffers */ + if (caamAesOutSz(desc, i) != Success) { + return SizeIsTooLarge; + } + + /* set alignment constraints */ + if (desc->type == CAAM_AESCBC || desc->type == CAAM_AESECB) { + align = 16; + } + + /* indefinite loop for input/output buffers */ + desc->headIdx = desc->idx; + desc->output = 0; + offset = 0; /* store left over amount for output buffer */ + do { + desc->idx = desc->headIdx; /* reset for each loop */ + + /* add a single input buffer (multiple ones was giving deco watch dog + * time out errors on the FIFO load of 1c. + * @TODO this could be a place for optimization if more data could be + * loaded in at one time */ + if ((sz = caamAesInput(desc, &i, align, totalSz)) < 0) { + return TransferFailed; + } + totalSz += sz; + + if (caamAesOutput(desc, &offset, sz) != Success) { + return TransferFailed; + } + + /* store updated IV */ + if (ivIdx > 0) { + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | ofst | 16; + desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv); + } + + if ((err = caamDoJob(desc)) != Success) { + return err; + } + ASP_FlushCaches((Address)desc->iv, 16); + } while (desc->lastIdx < desc->DescriptorCount || offset > 0); + + /* flush output buffers */ + for (i = desc->outputIdx; i < desc->lastIdx; i++) { + ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz); + } + + /* handle case with IV */ + if (ivIdx > 0) { + unsigned char* pt = (unsigned char*)desc->iv; + ASP_FlushCaches((Address)pt, 16); + for (i = 0; i < ivIdx; i++) { + memcpy((unsigned char*)iv[i]->data, pt, iv[i]->dataSz); + pt += iv[i]->dataSz; + ASP_FlushCaches(iv[i]->data, iv[i]->dataSz); + } + } + + return Success; +} + + +/****************************************************************************** + CAAM AEAD Operations + ****************************************************************************/ + +/* AEAD operations follow the buffer sequence of KEY -> (IV or B0 | CTR0) -> (AD) + * -> Input -> Output + * + */ +static Error caamAead(struct DescStruct* desc) +{ + struct buffer* ctx[3]; + struct buffer* iv[3]; + Value ofst = 0; + UINT4 state = CAAM_ALG_INIT; + UINT4 totalSz = 0; + Error err; + UINT4 i; + int ctxIdx = 0; + int ivIdx = 0; + int offset = 0; + int sz = 0; + int ivSz = 32; /* size of B0 | CTR0 for CCM mode */ + int ctxSz = desc->ctxSz; + int align = 16; /* input should be multiples of 16 bytes unless is final */ + int opIdx; + + if (desc->state != CAAM_ENC && desc->state != CAAM_DEC) { + return IllegalStatusNumber; + } + + /* sanity check is valid AES key size */ + if (ctxSz != 16 && ctxSz != 24 && ctxSz != 32) { + return ArgumentError; + } + + /* get key */ + for (i = 0; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)desc->ctxBuf; + + if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) { + ctx[ctxIdx] = buf; + sz += buf->dataSz; + + memcpy((unsigned char*)&local[offset], + (unsigned char*)ctx[ctxIdx]->data, ctx[ctxIdx]->dataSz); + offset += ctx[ctxIdx]->dataSz; + ctxIdx++; + } + else { + break; + } + } + + /* sanity checks on size of key */ + if (sz > ctxSz) { + return SizeIsTooLarge; + } + + /* Flush cache of ctx buffer then : + Add KEY Load command 0x0220000X + Add address to read key from 0xXXXXXXXX */ + ASP_FlushCaches((Address)desc->ctxBuf, ctxSz); + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = (CAAM_KEY | CAAM_CLASS1 | CAAM_NWB) + ctxSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->ctxBuf); + + desc->headIdx = desc->idx; + desc->output = 0; + offset = 0; /* store left over amount for output buffer */ + do { + desc->idx = desc->headIdx; /* reset for each loop */ + + /* write operation */ + if (desc->idx + 1 > MAX_DESC_SZ) { + return TransferFailed; + } + opIdx = desc->idx; + desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS1 | state | desc->type | + desc->state; + + /* get IV if needed by algorithm */ + switch (desc->type) { + case CAAM_AESCCM: + if ((state & CAAM_ALG_INIT) == CAAM_ALG_INIT) { + sz = 0; + offset = 0; + for (; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)desc->iv; + + if (sz < ivSz) { + iv[ivIdx] = buf; + + if (buf->dataSz + sz > ivSz) { + return SizeIsTooLarge; + } + + sz += buf->dataSz; + memcpy((unsigned char*)&local[offset], + (unsigned char*)iv[ivIdx]->data, iv[ivIdx]->dataSz); + offset += iv[ivIdx]->dataSz; + ivIdx++; + } + else { + break; + } + } + + if (sz != ivSz) { + /* invalid IV size */ + return SizeIsTooLarge; + } + offset = 0; + } + + ASP_FlushCaches((Address)desc->iv, ivSz); + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS1 | ofst) + + ivSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv); + break; + + default: + return OperationNotImplemented; + } + + + /********* handle AAD -- is only done with Init **********************/ + if ((state & CAAM_ALG_INIT) == CAAM_ALG_INIT) { + if ((desc->type == CAAM_AESCCM) && (desc->aadSz > 0)) { + /* set formatted AAD buffer size for CCM */ + ASP_FlushCaches((Address)desc->aadSzBuf, sizeof(desc->aadSzBuf)); + desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS1 | + FIFOL_TYPE_AAD + desc->aadSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->aadSzBuf); + + /* now set aadSz to unformatted version for getting buffers */ + if (desc->aadSz == 2) { + unsigned char* pt = (unsigned char*)desc->aadSzBuf; + desc->aadSz = (((UINT4)pt[0] & 0xFF) << 8) | + ((UINT4)pt[1] & 0xFF); + } + else { + unsigned char* pt = (unsigned char*)desc->aadSzBuf; + desc->aadSz = (((UINT4)pt[2] & 0xFF) << 24) | + (((UINT4)pt[3] & 0xFF) << 16) | + (((UINT4)pt[4] & 0xFF) << 8) | + ((UINT4)pt[5] & 0xFF); + } + } + + /* get additional data buffers */ + if (desc->aadSz > 0) { + sz = 0; + for (; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + if (sz < desc->aadSz) { + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->lastFifo = desc->idx; + desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS1 | + FIFOL_TYPE_AAD + buf->dataSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(buf->data); + sz += buf->dataSz; + } + else { + break; + } + } + + /* flush AAD from FIFO and pad it to 16 byte block */ + desc->desc[desc->lastFifo] |= FIFOL_TYPE_FC1; + } + + /* find output buffers */ + if (caamAesOutSz(desc, i) != Success) { + return SizeIsTooLarge; + } + } + + /* handle alignment constraints on input */ + if ((sz = caamAesInput(desc, &i, align, totalSz)) < 0) { + return TransferFailed; + } + totalSz += sz; + + /* handle output buffers */ + if (caamAesOutput(desc, &offset, sz) != Success) { + return TransferFailed; + } + + /* store updated IV, if is last then set offset and final for MAC */ + if ((desc->lastIdx == desc->DescriptorCount) && (offset == 0)) { + ivSz = 16; + if (desc->state == CAAM_ENC) { + ofst = 32 << 8; /* offset is in 15-8 bits */ + } + else { + ofst = 0; + } + desc->desc[opIdx] |= CAAM_ALG_FINAL; + } + else { + /* if not final then store and use ctr and encrypted ctr from + context dword 2,3 and 4,5. Also store MAC and AAD info from + context dword 6. */ + ivSz = 56; + ofst = 0; + } + + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS1 | ofst | ivSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv); + + if ((err = caamDoJob(desc)) != Success) { + return err; + } + state = CAAM_ALG_UPDATE; + } while (desc->lastIdx < desc->DescriptorCount || offset > 0); + + /* flush output buffers */ + for (i = desc->outputIdx; i < desc->lastIdx; i++) { + ASP_FlushCaches(desc->buf[i].data, desc->buf[i].dataSz); + } + + /* handle case with IV (This is also the output of MAC with AES-CCM) */ + if (ivIdx > 0) { + unsigned char* pt = (unsigned char*)desc->iv; + ASP_FlushCaches((Address)pt, ivSz); + for (i = 0; i < ivIdx; i++) { + memcpy((unsigned char*)iv[i]->data, pt, iv[i]->dataSz); + pt += iv[i]->dataSz; + ASP_FlushCaches(iv[i]->data, iv[i]->dataSz); + } + } + + return Success; +} + + +/****************************************************************************** + CAAM SHA Operations + ****************************************************************************/ +static int shaSize(struct DescStruct* desc) +{ + /* sanity check on dataSz for context */ + switch (desc->type) { + case CAAM_MD5: + return CAAM_MD5_CTXSZ; + + case CAAM_SHA: + return CAAM_SHA_CTXSZ; + + case CAAM_SHA224: + return CAAM_SHA224_CTXSZ; + + case CAAM_SHA256: + return CAAM_SHA256_CTXSZ; + + case CAAM_SHA384: + return CAAM_SHA384_CTXSZ; + + case CAAM_SHA512: + return CAAM_SHA512_CTXSZ; + + default: + return 0; + } +} + +/* SHA operations + * start: the index to start traversing through buffers. It's needed to allow + * for HMAC to reuse this code. + * + * return Success on success. All other return values are considered a fail + * case. + */ +static Error caamSha(struct DescStruct* desc, int start) +{ + struct buffer* ctx[3]; + Error err; + UINT4 i; + int sz = 0; + int ctxIdx = 0; + int offset = 0; + + int ctxSz = shaSize(desc); + + /* get context */ + for (i = start; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)desc->iv; + + if (sz < ctxSz && sz < (MAX_CTX * sizeof(UINT4))) { + ctx[ctxIdx] = buf; + sz += buf->dataSz; + + if (ctx[ctxIdx]->dataSz + offset > (MAX_CTX * sizeof(UINT4))) { + return SizeIsTooLarge; + } + memcpy((unsigned char*)&local[offset], (unsigned char*)ctx[ctxIdx]->data, + ctx[ctxIdx]->dataSz); + offset += ctx[ctxIdx]->dataSz; + ctxIdx++; + } + else { + break; + } + } + if (sz > ctxSz || ctxSz > (MAX_CTX * sizeof(UINT4))) { + return SizeIsTooLarge; + } + + ASP_FlushCaches((Address)desc->iv, ctxSz); + /*Manage Context (current digest + 8 byte running message length)*/ + if ((desc->state & CAAM_ALG_INIT) != CAAM_ALG_INIT) { + /* don't load into the class 2 context register on inti. + Found that loading in caused context to not get set. */ + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = (CAAM_LOAD_CTX | CAAM_CLASS2) + ctxSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical((Address)desc->iv); + } + + /* add operation command */ + desc->desc[desc->idx++] = CAAM_OP | CAAM_CLASS2 | desc->state | + desc->type; + + /* Check case where there is no input. + In all cases the FIFO Load should be flushed. */ + if (i == desc->DescriptorCount) { + desc->lastFifo = desc->idx; + if (desc->idx + 1 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_FIFO_L | CAAM_CLASS2 | + FIFOL_TYPE_MSG | CAAM_IMM; + } + + /* save index for looping over input */ + desc->headIdx = desc->idx; + do { + desc->idx = desc->headIdx; /* reset for each loop */ + if (i < desc->DescriptorCount) { + /* input must be a multiple of 64 bytes unless in final call */ + if (((desc->state & CAAM_ALG_FINAL) == CAAM_ALG_FINAL)) { + if (caamAddIO(desc, (CAAM_FIFO_L | CAAM_CLASS2 | + FIFOL_TYPE_MSG), 0, 1, &i) < 0) { + return TooManyBuffers; + } + } + else { + if (caamAddIO(desc, (CAAM_FIFO_L | CAAM_CLASS2 | + FIFOL_TYPE_MSG), 0, 64, &i) < 0) { + return TooManyBuffers; + } + } + } + + desc->desc[desc->lastFifo] |= FIFOL_TYPE_LC2; + + /* set context out */ + if (desc->idx + 2 > MAX_DESC_SZ) { + return TransferFailed; + } + desc->desc[desc->idx++] = CAAM_STORE_CTX | CAAM_CLASS2 + ctxSz; + desc->desc[desc->idx++] = BSP_VirtualToPhysical(desc->iv); + + if ((err = caamDoJob(desc)) != Success) { + return err; + } + /* flush context output for each loop */ + ASP_FlushCaches((Address)desc->iv, ctxSz); + } while (i < desc->DescriptorCount); + + /* store context to buffers */ + { + unsigned char* pt = (unsigned char*)desc->iv; + for (i = 0; i < ctxIdx; i++) { + memcpy((unsigned char*)ctx[i]->data, pt, ctx[i]->dataSz); + pt += ctx[i]->dataSz; + ASP_FlushCaches(ctx[i]->data, ctx[i]->dataSz); + } + } + + return Success; +} + + +/****************************************************************************** + CAAM TRNG Operations + ****************************************************************************/ + +/* If Entropy is not ready then return Waiting */ +static Error caamRng(struct DescStruct* desc) +{ + int sz = 0; + int i; + + Address reg; /* RTENT reg to read */ + int ofst = sizeof(UINT4); + + + /* Check ENT_VAL bit to make sure entropy is ready */ + if ((CAAM_READ(CAAM_RTMCTL) & CAAM_ENTVAL) != + CAAM_ENTVAL) { + return Waiting; + } + + /* check state of TRNG */ + if ((CAAM_READ(CAAM_RTSTATUS) & 0x0000FFFF) > 0) { + return Failure; + } + + /* read entropy from RTENT registers */ + reg = CAAM_RTENT0; + + for (i = 0; i < desc->DescriptorCount; i++) { + struct buffer* buf = &desc->buf[i]; + unsigned char* local = (unsigned char*)buf->data; + sz = buf->dataSz; + + while (sz > 3 && reg <= CAAM_RTENT11) { + *((UINT4*)local) = CAAM_READ(reg); + reg += ofst; + local += ofst; + sz -= ofst; + } + + if (reg > CAAM_RTENT11 && sz > 0) { + return SizeIsTooLarge; + } + + /* handle non word32 size amount left over */ + if (sz > 0) { + UINT4 tmp = CAAM_READ(reg); + memcpy(local, (unsigned char*)&tmp, sz); + } + + ASP_FlushCaches(buf->data, buf->dataSz); + } + + + /* read RTENT11 to trigger new entropy generation */ + if (reg != CAAM_RTENT11) { + CAAM_READ(CAAM_RTENT11); + } + + return Success; +} + + +/****************************************************************************** + IODevice Start, Transfer and Finish Buffer + ****************************************************************************/ +/* args[0] holds the state such as encrypt/decrypt or init/update/final + * args[1] holds the ctx/key size + * args[2] holds the input size + * args[3] dependent on algo (such as AAD size with AES-CCM) */ +static Error caamTransferStart(IODeviceVector ioCaam, + Value type, const volatile Value args[4]) +{ + struct CAAM_DEVICE* local = (struct CAAM_DEVICE*)ioCaam; + struct DescStruct* desc; + + /* currently only one desc is available for use */ + desc = &local->DescArray[0]; + + /* check if the desc is idle before using */ + if (GetIORequestStatus((IORequest)desc) != IdleIORequest) { + return ResourceNotAvailable; + } + + desc->idx = 0; + desc->output = 0; + desc->ctxOut = 0; + desc->outputIdx = 0; + desc->alignIdx = 0; + desc->lastFifo = 0; + desc->state = args[0]; + desc->ctxSz = args[1]; + desc->inputSz = args[2]; + desc->aadSz = 0; + desc->desc[desc->idx++] = CAAM_HEAD; /* later will put size to header*/ + + switch (type) { + case CAAM_AESECB: + case CAAM_AESCBC: + if (desc->inputSz % 16 != 0) { + return ArgumentError; + } + /* fall through to break */ + case CAAM_AESCTR: + break; + + case CAAM_AESCCM: + memset((unsigned char*)desc->aadSzBuf, 0, sizeof(desc->aadSzBuf)); + if (args[3] > 0) { + /* encode the length in */ + if (args[3] <= 0xFEFF) { + unsigned char* pt = (unsigned char*)desc->aadSzBuf; + desc->aadSz = 2; + pt[0] = ((args[3] & 0xFF00) >> 8); + pt[1] = (args[3] & 0x00FF); + } + else if (args[3] <= 0xFFFFFFFF) { + unsigned char* pt = (unsigned char*)desc->aadSzBuf; + desc->aadSz = 6; + pt[0] = 0xFF; pt[1] = 0xFE; + pt[2] = ((args[3] & 0xFF000000) >> 24); + pt[3] = ((args[3] & 0x00FF0000) >> 16); + pt[4] = ((args[3] & 0x0000FF00) >> 8); + pt[5] = (args[3] & 0x000000FF); + } + } + break; + + case CAAM_MD5: + case CAAM_SHA: + case CAAM_SHA224: + case CAAM_SHA256: + case CAAM_SHA384: + case CAAM_SHA512: + break; + + case CAAM_BLOB_ENCAP: + case CAAM_BLOB_DECAP: + break; + + case CAAM_ENTROPY: + break; + + default: + /* unknown type */ + return UsageNotSupported; + } + + desc->DescriptorCount = 0; + desc->type = type; + desc->running = true; + StartIORequest((IORequest)desc); + + /* For now only require READ permissions */ + SetIORequestBufferPermissions((IORequest)desc, MEMORY_READ); + return Success; +} + + +static Error caamTransferBuffer(IODeviceVector TheIODeviceVector, + IORequest req, IODescriptor NewIODescriptor, + Address data, Address dataSz) +{ + struct DescStruct* desc = (struct DescStruct*)req; + Error err; + + switch (desc->type) { + case CAAM_AESECB: + case CAAM_AESCTR: + case CAAM_AESCBC: + case CAAM_AESCCM: + + case CAAM_MD5: + case CAAM_SHA: + case CAAM_SHA224: + case CAAM_SHA256: + case CAAM_SHA384: + case CAAM_SHA512: + + case CAAM_BLOB_ENCAP: + case CAAM_BLOB_DECAP: + case CAAM_ENTROPY: + { /* set buffer for transfer finish */ + struct buffer* buf; + if (desc->DescriptorCount >= MAX_BUF) { + return TooManyBuffers; + } + buf = &desc->buf[desc->DescriptorCount]; + buf->data = data; + buf->dataSz = dataSz; + } + err = Success; + break; + + default: + err = UsageNotSupported; + } + + if (err != Success) { + desc->running = false; + DismissIORequest(req); + return err; + } + + desc->DescriptorCount++; + return Success; +} + + +static Error caamTransferFinish(IODeviceVector ioCaam, IORequest req) +{ + struct DescStruct* desc = (struct DescStruct*)req; + Error ret; + + /* construct desc */ + switch (desc->type) { + case CAAM_AESECB: + case CAAM_AESCTR: + case CAAM_AESCBC: + ret = caamAes(desc); + break; + + case CAAM_AESCCM: + ret = caamAead(desc); + break; + + case CAAM_MD5: + case CAAM_SHA: + case CAAM_SHA224: + case CAAM_SHA256: + case CAAM_SHA384: + case CAAM_SHA512: + ret = caamSha(desc, 0); + break; + + case CAAM_ENTROPY: + ret = caamRng(desc); + break; + + case CAAM_BLOB_ENCAP: + case CAAM_BLOB_DECAP: + ret = caamBlob(desc); + break; + + default: + ret = UsageNotSupported; + } + + desc->running = false; + DismissIORequest(req); + return ret; +} + + +/****************************************************************************** + IODevice Interrupt and Init + ****************************************************************************/ + +static Error caamTransferWrite(IODeviceVector ioCaam, + IORequest req, Value dataSz, const volatile Value *data) +{ + DismissIORequest(req); + return UsageNotSupported; +} + + +static void caamTransferAbort(IODeviceVector ioCaam, IORequest req) +{ + DismissIORequest(req); +} + + +static void caamTransferRecall(IODeviceVector ioCaam, IODescriptor req) +{ + +} + + +static void HandleInterrupt(Address id) +{ + struct CAAM_DEVICE* local = (struct CAAM_DEVICE*)id; + Value InterruptStatus = INTERRUPT_AtomicWrite(&local->InterruptStatus, 0); + int i; + + /* Loop through descriptors and try to dismiss them */ + for (i = 0; i < DESC_COUNT; i++) { + struct DescStruct* desc = &local->DescArray[i]; + if (InterruptStatus & (1 << i)) { + desc->running = false; + if (GetIORequestStatus((IORequest)desc) == IORequestSuspended) { + ContinueIORequest((IORequest)desc); + } + else { + DismissIORequest((IORequest)desc); + } + } + } +} + + +static Error caamCreate(IODeviceVector ioCaam) +{ + return Success; +} + + +void InitCAAM(void) +{ + /* get IO vector and set it up */ + IODeviceVector ioCaam = &caam.caamVector; + unsigned int reg; + int i; + Error ret; + + + ioCaam->Create = &caamCreate; + ioCaam->ReadRegister = &caamReadRegister; + ioCaam->WriteRegister = &caamWriteRegister; + + ioCaam->TransferStart = &caamTransferStart; + ioCaam->TransferBuffer = &caamTransferBuffer; + ioCaam->TransferWrite = &caamTransferWrite; + ioCaam->TransferFinish = &caamTransferFinish; + ioCaam->TransferAbort = &caamTransferAbort; + ioCaam->TransferRecall = &caamTransferRecall; +#ifdef HARDWARE_CACHE_COHERENCY + ioCaam->IOSynchronizationNotRequired = 1; +#endif + + RegisterIODeviceVector(ioCaam, DRIVER_NAME); + RequestIOTerminationTask(ioCaam, 10); + + /* Initialize descriptors */ + for (i = 0; i < BUFFER_COUNT; i++) { + InitializeIODescriptor(ioCaam, &caam.IODescriptorArray[i]); + } + + /* Initialize Descriptors */ + for (i = 0; i < DESC_COUNT; i++) { + InitializeIORequest(ioCaam, &caam.DescArray[i].TheIORequest, + IOREQUEST_STANDARD); + caam.DescArray[i].running = false; + caam.DescArray[i].caam = &caam; + } + + + /* call interrupt to make IORequests available */ + caam.InterruptStatus = 0; + INTERRUPT_InitCall(&caam.HandleInterruptCall, + &HandleInterrupt, "Start up CAAM IORequest"); + + /* set clock speed for CAAM. Setting it here to allow for restricting + access */ + #define REGS_CCM_BASE (0xf20c4000) + #define HW_CCM_CCGR0_ADDR (0xf20c4068) + #define CG(x) (3 << (x*2)) + + reg = CG(6) | CG(5) | CG(4); + *(volatile unsigned int*)HW_CCM_CCGR0_ADDR = + *(volatile unsigned int*)HW_CCM_CCGR0_ADDR | reg; + + /* set up job ring */ + + /* @TODO create partition in physical memory for job rings + current partition security is set to the default */ + for (i = 1; i < CAAM_PAGE_MAX; i++) { + ret = caamCreatePartition(i, i); + if (ret == 0) { + break; + } + + if (ret != MemoryMapMayNotBeEmpty) { + INTERRUPT_Panic(); + } + } + + if (ret != 0) { + INTERRUPT_Panic(); + } + + caam.ring.page = i; + caam.ring.JobIn = (CAAM_PAGE + (i << 12)); + caam.ring.JobOut = caam.ring.JobIn + 16; + caam.ring.Desc = caam.ring.JobOut + 16; + + /* set physical address of job rings */ + CAAM_WRITE(CAAM_IRBAR0, caam.ring.JobIn ^ 0xF0000000); + CAAM_WRITE(CAAM_ORBAR0, caam.ring.JobOut ^ 0xF0000000); + + /* Initialize job ring sizes to 1 */ + CAAM_WRITE(CAAM_IRSR0, 1); + CAAM_WRITE(CAAM_ORSR0, 1); + + /* set DECO watchdog to time out and flush jobs that cause the DECO to hang */ + CAAM_WRITE((CAAM_BASE | 0x0004), CAAM_READ(CAAM_BASE | 0x0004) | 0x40000000); + + /* start up RNG if not already started */ + if (caamInitRng(&caam) != 0) { + INTERRUPT_Panic(); + } +} + +void (*__ghsentry_bspuserinit_InitCAAM)(void) = &InitCAAM; + +#endif /* INTEGRITY */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_init.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_init.c new file mode 100644 index 000000000..014341cd6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_init.c @@ -0,0 +1,289 @@ +/* caam_init.c + * + * Copyright (C) 2006-2020 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 + */ + + +#include + +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6_CAAM_BLOB) + +#include +#include +#include + +#define WC_CAAM_BLOB_SZ 48 + +#ifndef WC_CAAM_PASSWORD + #define WC_CAAM_PASSWORD "!systempassword" +#endif + +#if defined(__INTEGRITY) || defined(INTEGRITY) + #include + #include + static IODevice caam = NULLIODevice; +#endif + +#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG) +#include +#include + +static void wc_caamBanner(void) +{ + printf("********* wolfSSL Version %s : Printing Out CAAM Information ********\n", + LIBWOLFSSL_VERSION_STRING); + printf("CAAM Status [0x%8.8x] = 0x%8.8x\n", + CAAM_STATUS, WC_CAAM_READ(CAAM_STATUS)); + printf("CAAM Version MS Register [0x%8.8x] = 0x%8.8x\n", + CAAM_VERSION_MS, WC_CAAM_READ(CAAM_VERSION_MS)); + printf("CAAM Version LS Register [0x%8.8x] = 0x%8.8x\n", + CAAM_VERSION_LS, WC_CAAM_READ(CAAM_VERSION_LS)); + printf("CAAM Support MS Register [0x%8.8x] = 0x%8.8x\n", + CAMM_SUPPORT_MS, WC_CAAM_READ(CAMM_SUPPORT_MS)); + printf("CAAM Support LS [0x%8.8x] = 0x%8.8x\n", + CAMM_SUPPORT_LS, WC_CAAM_READ(CAMM_SUPPORT_LS)); + printf("********************************************************************\n\n"); +} +#endif + + +/* Allow runtime setting for CAAM IODevice in case user wants to use password + * at run time. + * + * returns 0 on success + * + * NOTE this is how IODevice is defined in INTEGRITY "typedef struct + * IODeviceStruct *IODevice;" + */ +int wc_caamSetResource(IODevice ioDev) +{ + WOLFSSL_MSG("Setting CAAM driver"); + caam = ioDev; + + return 0; +} + +/* Check hardware support + * + * returns 0 on success + */ +int wc_caamInit(void) +{ + int ret; + word32 reg; + + /* get the driver up */ + if (caam == NULLIODevice) { + WOLFSSL_MSG("Starting CAAM driver"); + if ((ret = (int)RequestResource((Object *)&caam, "wolfSSL_CAAM_Driver", + WC_CAAM_PASSWORD)) != (int)Success) { + WOLFSSL_MSG("Unable to get the CAAM IODevice, check password?"); + WOLFSSL_LEAVE("wc_caamInit: error from driver = ", ret); + ret = 0; /* not a hard failure because user can set resource */ + } + } + +#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG) + /* print out CAAM version/info and wolfSSL version */ + wc_caamBanner(); +#endif + + /* check that for implemented modules + * bits 0-3 AES, 4-7 DES, 12-15 Hashing , 16-19 RNG */ + reg = WC_CAAM_READ(CAMM_SUPPORT_LS); + + #ifndef WC_NO_RNG + if (((reg & 0x000F0000) >> 16) > 0) { + WOLFSSL_MSG("Found CAAM RNG hardware module"); + if ((WC_CAAM_READ(CAAM_RTMCTL) & 0x40000001) != 0x40000001) { + WOLFSSL_MSG("Error CAAM RNG has not been set up"); + } + } + #endif + + #ifndef NO_SHA256 + if ((reg & 0x0000F000) > 0) { + WOLFSSL_MSG("Found CAAM MDHA module"); + } + else { + WOLFSSL_MSG("Hashing not supported by CAAM"); + return WC_HW_E; + } + #endif + + #ifndef NO_AES + if ((reg & 0x0000000F) > 0) { + WOLFSSL_MSG("Found CAAM AES module"); + } + else { + WOLFSSL_MSG("AES not supported by CAAM"); + return WC_HW_E; + } + #endif + + (void)ret; + return 0; +} + + +int wc_caamFree(void) +{ + return 0; +} + + +word32 wc_caamReadRegister(word32 reg) +{ + Value out = 0; + + if (caam == NULLIODevice) { + WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?"); + return 0; + } + + if (ReadIODeviceRegister(caam, reg, &out) != Success) { + WOLFSSL_MSG("Error reading register\n"); + } + + return (word32)out; +} + +void wc_caamWriteRegister(word32 reg, word32 value) +{ + if (caam == NULLIODevice) { + WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?"); + return; + } + + if (WriteIODeviceRegister(caam, reg, value) != Success) { + WOLFSSL_MSG("Error writing to register\n"); + } +} + + +/* return 0 on success and WC_HW_E on failure. Can also return WC_HW_WAIT_E + * in the case that the driver is waiting for a resource or RAN_BLOCK_E if + * waiting for entropy. */ +int wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type) +{ + int ret; + if (caam == NULLIODevice) { + WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?"); + return WC_HW_E; + } + + if ((ret = SynchronousSendIORequest(caam, type, (const Value*)arg, buf)) + != Success) { + #if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG) + printf("ret of SynchronousSendIORequest = %d type = %d\n", ret, type); + #endif + + /* if waiting for resource or RNG return waiting */ + if (ret == Waiting) { + WOLFSSL_MSG("Waiting on entropy from driver"); + return RAN_BLOCK_E; + } + + if (ret == ResourceNotAvailable) { + WOLFSSL_MSG("Waiting on CAAM driver"); + return WC_HW_WAIT_E; + } + + return WC_HW_E; + } + + (void)ret; + return 0; +} + + +int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, word32* outSz) +{ + Buffer in[3]; + word32 arg[4]; + int ret; + word32 local[2] = {0,0}; + + if (data == NULL || out == NULL || outSz == NULL || + *outSz < dataSz + WC_CAAM_BLOB_SZ) { + return BAD_FUNC_ARG; + } + + in[0].BufferType = DataBuffer; + in[0].TheAddress = (Address)local; + in[0].Length = sizeof(local); + + in[1].BufferType = DataBuffer; + in[1].TheAddress = (Address)data; + in[1].Length = dataSz; + + in[2].BufferType = DataBuffer | LastBuffer; + in[2].TheAddress = (Address)out; + in[2].Length = dataSz + WC_CAAM_BLOB_SZ; + + arg[2] = dataSz; + + if ((ret = wc_caamAddAndWait(in, arg, CAAM_BLOB_ENCAP)) != 0) { + WOLFSSL_MSG("Error with CAAM blob create"); + return ret; + } + + *outSz = dataSz + WC_CAAM_BLOB_SZ; + return 0; +} + + +int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, word32* outSz) +{ + Buffer in[3]; + word32 arg[4]; + int ret; + word32 local[2] = {0,0}; + + if (data == NULL || out == NULL || outSz == NULL || + *outSz < dataSz - WC_CAAM_BLOB_SZ) { + return BAD_FUNC_ARG; + } + + in[0].BufferType = DataBuffer; + in[0].TheAddress = (Address)local; + in[0].Length = sizeof(local); + + in[0].BufferType = DataBuffer; + in[0].TheAddress = (Address)data; + in[0].Length = dataSz; + + in[1].BufferType = DataBuffer | LastBuffer; + in[1].TheAddress = (Address)out; + in[1].Length = dataSz - WC_CAAM_BLOB_SZ; + + arg[2] = dataSz; + + if ((ret = wc_caamAddAndWait(in, arg, CAAM_BLOB_DECAP)) != 0) { + WOLFSSL_MSG("Error with CAAM blob create"); + return ret; + } + + *outSz = dataSz - WC_CAAM_BLOB_SZ; + return 0; +} + +#endif /* WOLFSSL_IMX6_CAAM */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_sha.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_sha.c new file mode 100644 index 000000000..74d62fb97 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/caam/caam_sha.c @@ -0,0 +1,397 @@ +/* caam_sha.c + * + * Copyright (C) 2006-2020 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 + */ + + +#include + +#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#include +#include +#include + +#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT) +#include +#endif + +#ifndef NO_SHA +#include +#endif + +#if !defined(NO_SHA256) || defined(WOLFSSL_SHA224) +#include +#endif + +#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) +#include +#endif + +#ifndef NO_MD5 +#include +#endif + +/****************************************************************************** + Common Code Between SHA Functions + ****************************************************************************/ + +static int _InitSha(wc_Sha* sha, void* heap, int devId, word32 digestSz, + word32 type) +{ + Buffer buf[1]; + word32 arg[4]; + int ret; + + (void)heap; + (void)devId; + + if (sha == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(sha, 0, sizeof(Sha)); + + /* Set buffer for context */ + buf[0].BufferType = DataBuffer | LastBuffer; + buf[0].TheAddress = (Address)sha->ctx; + buf[0].Length = digestSz + WC_CAAM_CTXLEN; + buf[0].Transferred = 0; + + arg[0] = CAAM_ALG_INIT; + arg[1] = digestSz + WC_CAAM_CTXLEN; + + if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) { + WOLFSSL_MSG("Error with CAAM SHA init"); + return ret; + } + + return 0; +} + + +static int _ShaUpdate(wc_Sha* sha, const byte* data, word32 len, word32 digestSz, + word32 type) +{ + Buffer buf[2]; + word32 arg[4]; + int ret; + byte* local; + + if (sha == NULL ||(data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + if (len == 0) return 0; /* nothing to do */ + + local = (byte*)sha->buffer; + /* check for filling out existing buffer */ + if (sha->buffLen > 0) { + word32 add = min(len, WC_CAAM_HASH_BLOCK - sha->buffLen); + XMEMCPY(&local[sha->buffLen], data, add); + + sha->buffLen += add; + data += add; + len -= add; + + if (sha->buffLen == WC_CAAM_HASH_BLOCK) { + /* Set buffer for context */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)sha->ctx; + buf[0].Length = digestSz + WC_CAAM_CTXLEN; + buf[0].Transferred = 0; + + /* data to update with */ + buf[1].BufferType = DataBuffer | LastBuffer; + buf[1].TheAddress = (Address)sha->buffer; + buf[1].Length = sha->buffLen; + buf[1].Transferred = 0; + + arg[0] = CAAM_ALG_UPDATE; + arg[1] = digestSz + WC_CAAM_CTXLEN; + + if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) { + WOLFSSL_MSG("Error with CAAM SHA update"); + return ret; + } + sha->buffLen = 0; /* cleared out buffer */ + } + } + + /* check if multiple full blocks can be done */ + if (len >= WC_CAAM_HASH_BLOCK) { + word32 sz = len / WC_CAAM_HASH_BLOCK; + sz = sz * WC_CAAM_HASH_BLOCK; + + /* Set buffer for context */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)sha->ctx; + buf[0].Length = digestSz + WC_CAAM_CTXLEN; + buf[0].Transferred = 0; + + /* data to update with */ + buf[1].BufferType = DataBuffer | LastBuffer; + buf[1].TheAddress = (Address)data; + buf[1].Length = sz; + buf[1].Transferred = 0; + + arg[0] = CAAM_ALG_UPDATE; + arg[1] = digestSz + WC_CAAM_CTXLEN; + + if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) { + WOLFSSL_MSG("Error with CAAM SHA update"); + return ret; + } + + len -= sz; + data += sz; + } + + /* check for left overs */ + if (len > 0) { + word32 add = min(len, WC_CAAM_HASH_BLOCK - sha->buffLen); + XMEMCPY(&local[sha->buffLen], data, add); + sha->buffLen += add; + } + + return 0; +} + + +static int _ShaFinal(wc_Sha* sha, byte* out, word32 digestSz, + word32 type) +{ + Buffer buf[2]; + word32 arg[4]; + int ret; + + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + /* Set buffer for context */ + buf[0].BufferType = DataBuffer; + buf[0].TheAddress = (Address)sha->ctx; + buf[0].Length = digestSz + WC_CAAM_CTXLEN; + buf[0].Transferred = 0; + + /* add any potential left overs */ + buf[1].BufferType = DataBuffer | LastBuffer; + buf[1].TheAddress = (Address)sha->buffer; + buf[1].Length = sha->buffLen; + buf[1].Transferred = 0; + + arg[0] = CAAM_ALG_FINAL; + arg[1] = digestSz + WC_CAAM_CTXLEN; + + if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) { + WOLFSSL_MSG("Error with CAAM SHA init"); + return ret; + } + + return 0; +} + +/****************************************************************************** + MD5 + ****************************************************************************/ +#if !defined(NO_MD5) +int wc_InitMd5_ex(wc_Md5* sha, void* heap, int devId) +{ + return _InitSha(sha, heap, devId, MD5_DIGEST_SIZE, CAAM_MD5); +} + + +int wc_Md5Update(wc_Md5* sha, const byte* data, word32 len) +{ + return _ShaUpdate(sha, data, len, MD5_DIGEST_SIZE, CAAM_MD5); +} + + +int wc_Md5Final(wc_Md5* sha, byte* hash) +{ + int ret; + if ((ret = _ShaFinal(sha, hash, MD5_DIGEST_SIZE, CAAM_MD5)) != 0) { + return ret; + } + + XMEMCPY(hash, (byte*)sha->ctx, MD5_DIGEST_SIZE); + return _InitSha(sha, NULL, 0, MD5_DIGEST_SIZE, CAAM_MD5); +} +#endif /* !NO_MD5 */ + + +/****************************************************************************** + SHA 1 + ****************************************************************************/ +#if !defined(NO_SHA) +int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) +{ + return _InitSha(sha, heap, devId, SHA_DIGEST_SIZE, CAAM_SHA); +} + + +int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) +{ + return _ShaUpdate(sha, data, len, SHA_DIGEST_SIZE, CAAM_SHA); +} + + +int wc_ShaFinal(wc_Sha* sha, byte* out) +{ + int ret; + if ((ret = _ShaFinal(sha, out, SHA_DIGEST_SIZE, CAAM_SHA)) != 0) { + return ret; + } + + XMEMCPY(out, (byte*)sha->ctx, SHA_DIGEST_SIZE); + return _InitSha(sha, NULL, 0, SHA_DIGEST_SIZE, CAAM_SHA); +} +#endif /* !NO_SHA */ + + +/****************************************************************************** + SHA 224 + ****************************************************************************/ +#ifdef WOLFSSL_SHA224 +int wc_InitSha224_ex(wc_Sha224* sha, void* heap, int devId) +{ + return _InitSha(sha, heap, devId, SHA256_DIGEST_SIZE, CAAM_SHA224); +} + + +int wc_Sha224Update(wc_Sha224* sha, const byte* data, word32 len) +{ + return _ShaUpdate(sha, data, len, SHA256_DIGEST_SIZE, CAAM_SHA224); +} + + +int wc_Sha224Final(wc_Sha224* sha, byte* out) +{ + int ret; + if ((ret = _ShaFinal(sha, out, SHA256_DIGEST_SIZE, CAAM_SHA224)) != 0) { + return ret; + } + + XMEMCPY(out, (byte*)sha->ctx, SHA224_DIGEST_SIZE); + return _InitSha(sha, NULL, 0, SHA256_DIGEST_SIZE, CAAM_SHA224); +} +#endif /* WOLFSSL_SHA224 */ + + +/****************************************************************************** + SHA 256 + ****************************************************************************/ +#if !defined(NO_SHA256) +int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId) +{ + return _InitSha(sha, heap, devId, SHA256_DIGEST_SIZE, CAAM_SHA256); +} + + +int wc_Sha256Update(wc_Sha256* sha, const byte* data, word32 len) +{ + return _ShaUpdate(sha, data, len, SHA256_DIGEST_SIZE, CAAM_SHA256); +} + + +int wc_Sha256Final(wc_Sha256* sha, byte* out) +{ + int ret; + if ((ret = _ShaFinal(sha, out, SHA256_DIGEST_SIZE, CAAM_SHA256)) != 0) { + return ret; + } + + XMEMCPY(out, (byte*)sha->ctx, SHA256_DIGEST_SIZE); + return _InitSha(sha, NULL, 0, SHA256_DIGEST_SIZE, CAAM_SHA256); +} +#endif /* !NO_SHA256 */ + + +/****************************************************************************** + SHA 384 + ****************************************************************************/ +#ifdef WOLFSSL_SHA384 +int wc_InitSha384_ex(wc_Sha384* sha, void* heap, int devId) +{ + return _InitSha(sha, heap, devId, SHA512_DIGEST_SIZE, CAAM_SHA384); +} + + +int wc_Sha384Update(wc_Sha384* sha, const byte* data, word32 len) +{ + return _ShaUpdate(sha, data, len, SHA512_DIGEST_SIZE, CAAM_SHA384); +} + + +int wc_Sha384Final(wc_Sha384* sha, byte* out) +{ + int ret; + if ((ret = _ShaFinal(sha, out, SHA512_DIGEST_SIZE, CAAM_SHA384)) != 0) { + return ret; + } + + XMEMCPY(out, (byte*)sha->ctx, SHA384_DIGEST_SIZE); + return _InitSha(sha, NULL, 0, SHA512_DIGEST_SIZE, CAAM_SHA384); +} +#endif /* WOLFSSL_SHA384 */ + + + +/****************************************************************************** + SHA 512 + ****************************************************************************/ +#ifdef WOLFSSL_SHA512 +int wc_InitSha512_ex(wc_Sha512* sha, void* heap, int devId) +{ + return _InitSha(sha, heap, devId, SHA512_DIGEST_SIZE, CAAM_SHA512); +} + + +int wc_Sha512Update(wc_Sha512* sha, const byte* data, word32 len) +{ + return _ShaUpdate(sha, data, len, SHA512_DIGEST_SIZE, CAAM_SHA512); +} + + +int wc_Sha512Final(wc_Sha512* sha, byte* out) +{ + int ret; + if ((ret = _ShaFinal(sha, out, SHA512_DIGEST_SIZE, CAAM_SHA512)) != 0) { + return ret; + } + + XMEMCPY(out, (byte*)sha->ctx, SHA512_DIGEST_SIZE); + return _InitSha(sha, NULL, 0, SHA512_DIGEST_SIZE, CAAM_SHA512); +} +#endif /* WOLFSSL_SHA512 */ + +#endif /* WOLFSSL_IMX6_CAAM */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/README.md b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/README.md new file mode 100644 index 000000000..b98d866dd --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/README.md @@ -0,0 +1,3 @@ +# Cavium Nitrox III/V Support + +Please contact wolfSSL at info@wolfssl.com to request an evaluation. diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/README_Octeon.md b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/README_Octeon.md new file mode 100644 index 000000000..b2670d02e --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/README_Octeon.md @@ -0,0 +1,3 @@ +# Cavium Octeon III CN7300 + +Please contact wolfSSL at info@wolfssl.com to request an evaluation. diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/cavium_nitrox.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/cavium_nitrox.c new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/cavium_octeon_sync.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/cavium_octeon_sync.c new file mode 100644 index 000000000..078e8cb52 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/cavium/cavium_octeon_sync.c @@ -0,0 +1,879 @@ +/* cavium_octeon_sync.c + * + * Copyright(C) 2006-2020 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 +#include +#include + +#ifdef HAVE_CAVIUM_OCTEON_SYNC + +/* Setting NO_MAIN_DRIVER here because this file ends up building + * in the library sources which doesn't have NO_MAIN_DRIVER set, + * as the library expects main to be somewhere else. */ +#undef NO_MAIN_DRIVER +#define NO_MAIN_DRIVER + +#include +#include +#include +#include + +#include "cvmx.h" +#include "cvmx-asm.h" +#include "cvmx-key.h" +#include "cvmx-swap.h" + +#ifndef NO_DES3 + #include +#endif +#ifndef NO_AES + #include +#endif + +#define NOOPT __attribute__((optimize("O0"))) + +static int devId = 1234; + +#ifndef NO_DES3 +static int Octeon_Des3_CbcEncrypt(Des3* des3, + uint64_t *inp64, uint64_t *outp64, size_t inl) +{ + register uint64_t i0, r0; + uint64_t *key, *iv; + + if (des3 == NULL || inp64 == NULL || outp64 == NULL) + return BAD_FUNC_ARG; + + /* expects 64-bit aligned value */ + key = (uint64_t*)des3->devKey; + CVMX_MT_3DES_KEY(key[0], 0); + CVMX_MT_3DES_KEY(key[1], 1); + CVMX_MT_3DES_KEY(key[2], 2); + iv = (uint64_t*)des3->reg; + CVMX_MT_3DES_IV(iv[0]); + + CVMX_PREFETCH0(inp64); + + i0 = *inp64; + + /* DES3 assembly can handle 16-byte chunks */ + if (inl >= 16) { + CVMX_MT_3DES_ENC_CBC(i0); + inl -= 8; + inp64++; + outp64++; + + if (inl >= 8) { + i0 = inp64[0]; + CVMX_MF_3DES_RESULT(r0); + CVMX_MT_3DES_ENC_CBC(i0); + + for (;;) { + outp64[-1] = r0; + inl -= 8; + inp64++; + outp64++; + i0 = *inp64; + + if (inl < 8) + break; + + CVMX_PREFETCH(inp64, 64); + CVMX_MF_3DES_RESULT(r0); + CVMX_MT_3DES_ENC_CBC(i0); + } + } + CVMX_MF_3DES_RESULT(r0); + outp64[-1] = r0; + } + /* remainder */ + if (inl > 0) { + uint64_t r = 0; + if (inl <= 8) { + XMEMCPY(&r, inp64, inl); + CVMX_MT_3DES_ENC_CBC(r); + CVMX_MF_3DES_RESULT(*outp64); + } + else { + i0 = *inp64; + CVMX_MT_3DES_ENC_CBC(i0); + CVMX_MF_3DES_RESULT(*outp64); + inp64++, outp64++; + + XMEMCPY(&r, inp64, inl); + CVMX_MT_3DES_ENC_CBC(r); + CVMX_MF_3DES_RESULT(*outp64); + } + } + + CVMX_MT_3DES_IV(iv[0]); + + return 0; +} + +static int Octeon_Des3_CbcDecrypt(Des3* des3, + uint64_t *inp64, uint64_t *outp64, size_t inl) +{ + register uint64_t i0, r0; + uint64_t *key, *iv; + + if (des3 == NULL || inp64 == NULL || outp64 == NULL) + return BAD_FUNC_ARG; + + /* expects 64-bit aligned value */ + key = (uint64_t*)des3->devKey; + CVMX_MT_3DES_KEY(key[0], 0); + CVMX_MT_3DES_KEY(key[1], 1); + CVMX_MT_3DES_KEY(key[2], 2); + + iv = (uint64_t*)des3->reg; + CVMX_MT_3DES_IV(iv[0]); + + CVMX_PREFETCH0(inp64); + + i0 = *inp64; + + /* DES3 assembly can handle 16-byte chunks */ + if (inl >= 16) { + CVMX_MT_3DES_DEC_CBC(i0); + inl -= 8; + inp64++; + outp64++; + + if (inl >= 8) { + i0 = inp64[0]; + CVMX_MF_3DES_RESULT(r0); + CVMX_MT_3DES_DEC_CBC(i0); + + for (;;) { + outp64[-1] = r0; + inl -= 8; + inp64++; + outp64++; + i0 = *inp64; + + if (inl < 8) + break; + + CVMX_PREFETCH(inp64, 64); + CVMX_MF_3DES_RESULT(r0); + CVMX_MT_3DES_DEC_CBC(i0); + } + } + + CVMX_MF_3DES_RESULT(r0); + outp64[-1] = r0; + } + /* remainder */ + if (inl > 0) { + if (inl <= 8) { + uint64_t r = 0; + XMEMCPY(&r, inp64, inl); + CVMX_MT_3DES_DEC_CBC(r); + CVMX_MF_3DES_RESULT(*outp64); + } + else { + uint64_t r = 0; + i0 = *inp64; + CVMX_MT_3DES_DEC_CBC(i0); + CVMX_MF_3DES_RESULT(*outp64); + inp64++, outp64++; + + XMEMCPY(&r, inp64, inl); + CVMX_MT_3DES_DEC_CBC(r); + CVMX_MF_3DES_RESULT(*outp64); + } + } + + CVMX_MT_3DES_IV(iv[0]); + + return 0; +} +#endif /* !NO_DES3 */ + + +#ifndef NO_AES + +#ifdef HAVE_AES_CBC +static int Octeon_AesCbc_Encrypt(Aes *aes, + uint64_t *inp64, uint64_t *outp64, size_t inl) +{ + register uint64_t i0, i1, r0, r1; + uint64_t *key, *iv; + + if (aes == NULL || inp64 == NULL || outp64 == NULL) { + return BAD_FUNC_ARG; + } + + iv = (uint64_t*)aes->reg; + CVMX_MT_AES_IV(iv[0], 0); + CVMX_MT_AES_IV(iv[1], 1); + + key = (uint64_t*)aes->devKey; + CVMX_MT_AES_KEY(key[0], 0); + CVMX_MT_AES_KEY(key[1], 1); + CVMX_MT_AES_KEY(key[2], 2); + CVMX_MT_AES_KEY(key[3], 3); + + CVMX_MT_AES_KEYLENGTH(aes->keylen/8 - 1); + + CVMX_PREFETCH0(inp64); + + i0 = inp64[0]; + i1 = inp64[1]; + + /* AES assembly can handle 32-byte chunks */ + if (inl >= 32) { + CVMX_MT_AES_ENC_CBC0(i0); + CVMX_MT_AES_ENC_CBC1(i1); + inl -= 16; + inp64 += 2; + outp64 += 2; + + if (inl >= 16) { + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + i0 = inp64[0]; + i1 = inp64[1]; + CVMX_MT_AES_ENC_CBC0(i0); + CVMX_MT_AES_ENC_CBC1(i1); + + for (;;) { + outp64[-2] = r0; + outp64[-1] = r1; + outp64 += 2; + inp64 += 2; + inl -= 16; + i0 = inp64[0]; + i1 = inp64[1]; + + if (inl < 16) + break; + + CVMX_PREFETCH(inp64, 64); + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + CVMX_MT_AES_ENC_CBC0(i0); + CVMX_MT_AES_ENC_CBC1(i1); + } + } + + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + outp64[-2] = r0; + outp64[-1] = r1; + } + /* remainder */ + if (inl > 0) { + uint64_t in64[2] = { 0, 0 }; + if (inl <= 16) { + XMEMCPY(in64, inp64, inl); + CVMX_MT_AES_ENC_CBC0(in64[0]); + CVMX_MT_AES_ENC_CBC1(in64[1]); + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + outp64[0] = r0; + outp64[1] = r1; + } + else { + CVMX_MT_AES_ENC_CBC0(i0); + CVMX_MT_AES_ENC_CBC1(i1); + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + inl -= 16; + outp64[0] = r0; + outp64[1] = r1; + inp64 += 2; + outp64 += 2; + XMEMCPY(in64, inp64, inl); + CVMX_MT_AES_ENC_CBC0(in64[0]); + CVMX_MT_AES_ENC_CBC1(in64[1]); + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + outp64[0] = r0; + outp64[1] = r1; + } + } + + CVMX_MF_AES_IV(iv[0], 0); + CVMX_MF_AES_IV(iv[1], 1); + + return 0; +} + +static int Octeon_AesCbc_Decrypt(Aes *aes, + uint64_t *inp64, uint64_t *outp64, size_t inl) +{ + register uint64_t i0, i1, r0, r1; + uint64_t *key, *iv; + + if (aes == NULL || inp64 == NULL || outp64 == NULL) { + return BAD_FUNC_ARG; + } + + iv = (uint64_t*)aes->reg; + key = (uint64_t*)aes->devKey; + + CVMX_MT_AES_IV(iv[0], 0); + CVMX_MT_AES_IV(iv[1], 1); + + CVMX_MT_AES_KEY(key[0], 0); + CVMX_MT_AES_KEY(key[1], 1); + CVMX_MT_AES_KEY(key[2], 2); + CVMX_MT_AES_KEY(key[3], 3); + CVMX_MT_AES_KEYLENGTH(aes->keylen/8 - 1); + + CVMX_PREFETCH0(inp64); + + i0 = inp64[0]; + i1 = inp64[1]; + + /* AES assembly can handle 32-byte chunks */ + if (inl >= 32) { + CVMX_MT_AES_DEC_CBC0(i0); + CVMX_MT_AES_DEC_CBC1(i1); + inp64 += 2; + outp64 += 2; + inl -= 16; + + if (inl >= 16) { + i0 = inp64[0]; + i1 = inp64[1]; + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + CVMX_MT_AES_DEC_CBC0(i0); + CVMX_MT_AES_DEC_CBC1(i1); + + for (;;) { + outp64[-2] = r0; + outp64[-1] = r1; + outp64 += 2; + inp64 += 2; + inl -= 16; + i0 = inp64[0]; + i1 = inp64[1]; + + if (inl < 16) + break; + + CVMX_PREFETCH(inp64, 64); + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + CVMX_MT_AES_DEC_CBC0(i0); + CVMX_MT_AES_DEC_CBC1(i1); + } + } + + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + outp64[-2] = r0; + outp64[-1] = r1; + } + /* remainder */ + if (inl > 0) { + uint64_t in64[2] = { 0, 0 }; + XMEMCPY(in64, inp64, inl); + CVMX_MT_AES_DEC_CBC0(in64[0]); + CVMX_MT_AES_DEC_CBC1(in64[1]); + CVMX_MF_AES_RESULT(r0, 0); + CVMX_MF_AES_RESULT(r1, 1); + outp64[0] = r0; + outp64[1] = r1; + } + + CVMX_MF_AES_IV(iv[0], 0); + CVMX_MF_AES_IV(iv[1], 1); + + return 0; +} +#endif /* HAVE_AES_CBC */ + + +#ifdef HAVE_AESGCM + +#define CVM_AES_RD_RESULT_WR_DATA(in1, in2, out1, out2) \ + asm volatile(\ + ".set noreorder \n" \ + "dmfc2 %[r1],0x0100\n" \ + "dmfc2 %[r2],0x0101\n" \ + "dmtc2 %[r3],0x010a\n" \ + "dmtc2 %[r4],0x310b\n" \ + ".set reorder \n" \ + : [r1] "=&d"(in1) , [r2] "=&d"(in2) \ + : [r3] "d"(out1), [r4] "d"(out2)) + +static NOOPT void Octeon_GHASH_Restore(word16 poly, byte* h) +{ + word64* bigH = (word64*)h; + CVMX_MT_GFM_POLY((word64)poly); + CVMX_MT_GFM_MUL(bigH[0], 0); + CVMX_MT_GFM_MUL(bigH[1], 1); +} + + +static NOOPT void Octeon_GHASH_Init(word16 poly, byte* h) +{ + Octeon_GHASH_Restore(poly, h); + CVMX_MT_GFM_RESINP(0, 0); + CVMX_MT_GFM_RESINP(0, 1); +} + + +static NOOPT void Octeon_GHASH_Update(byte* in) +{ + word64* bigIn = (word64*)in; + CVMX_MT_GFM_XOR0(bigIn[0]); + CVMX_MT_GFM_XORMUL1(bigIn[1]); +} + + +static NOOPT void Octeon_GHASH_Final(byte* out, word64 authInSz, word64 inSz) +{ + word64* bigOut = (word64*)out; + + CVMX_MT_GFM_XOR0(authInSz * 8); + CVMX_MT_GFM_XORMUL1(inSz * 8); + CVMX_MF_GFM_RESINP(bigOut[0], 0); + CVMX_MF_GFM_RESINP(bigOut[1], 1); +} + + +/* Sets the Octeon key with the key found in the Aes record. */ +static NOOPT int Octeon_AesGcm_SetKey(Aes* aes) +{ + int ret = 0; + + if (aes == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + uint64_t* key = (uint64_t*)aes->devKey; + + CVMX_MT_AES_KEY(key[0], 0); + CVMX_MT_AES_KEY(key[1], 1); + CVMX_MT_AES_KEY(key[2], 2); + CVMX_MT_AES_KEY(key[3], 3); + CVMX_MT_AES_KEYLENGTH((aes->keylen / 8) - 1); + + if (!aes->keySet) { + uint64_t* bigH = (uint64_t*)aes->H; + CVMX_MT_AES_ENC0(0); + CVMX_MT_AES_ENC1(0); + CVMX_MF_AES_RESULT(bigH[0], 0); + CVMX_MF_AES_RESULT(bigH[1], 1); + aes->keySet = 1; + } + } + + return ret; +} + + +static NOOPT int Octeon_AesGcm_SetIV(Aes* aes, byte* iv, word32 ivSz) +{ + int ret = 0; + + if (aes == NULL || iv == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMSET((byte*)aes->reg, 0, sizeof(aes->reg)); + XMEMCPY((byte*)aes->reg, iv, ivSz); + aes->reg[3] = 1; + } + else { + int blocks, remainder, i; + byte aesBlock[AES_BLOCK_SIZE]; + + blocks = ivSz / AES_BLOCK_SIZE; + remainder = ivSz % AES_BLOCK_SIZE; + + for (i = 0; i < blocks; i++, iv += AES_BLOCK_SIZE) + Octeon_GHASH_Update(iv); + + XMEMSET(aesBlock, 0, sizeof(aesBlock)); + for (i = 0; i < remainder; i++) + aesBlock[i] = iv[i]; + Octeon_GHASH_Update(aesBlock); + + Octeon_GHASH_Final((byte*)aes->reg, 0, ivSz); + } + + aes->y0 = aes->reg[3]; + aes->reg[3]++; + + Octeon_GHASH_Init(0xe100, aes->H); + } + + return ret; +} + + +static NOOPT int Octeon_AesGcm_SetAAD(Aes* aes, byte* aad, word32 aadSz) +{ + word64* p; + ALIGN16 byte aesBlock[AES_BLOCK_SIZE]; + int blocks, remainder, i; + + if (aes == NULL || (aadSz != 0 && aad == NULL)) + return BAD_FUNC_ARG; + + if (aadSz == 0) + return 0; + + blocks = aadSz / AES_BLOCK_SIZE; + remainder = aadSz % AES_BLOCK_SIZE; + + Octeon_GHASH_Restore(0xe100, aes->H); + + p = (word64*)aesBlock; + + for (i = 0; i < blocks; i++, aad += AES_BLOCK_SIZE) { + CVMX_LOADUNA_INT64(p[0], aad, 0); + CVMX_LOADUNA_INT64(p[1], aad, 8); + CVMX_MT_GFM_XOR0(p[0]); + CVMX_MT_GFM_XORMUL1(p[1]); + } + + XMEMSET(aesBlock, 0, sizeof(aesBlock)); + + for (i = 0; i < remainder; i++) + aesBlock[i] = aad[i]; + + CVMX_MT_GFM_XOR0(p[0]); + CVMX_MT_GFM_XORMUL1(p[1]); + + return 0; +} + + +static int Octeon_AesGcm_SetEncrypt(Aes* aes, byte* in, byte* out, word32 inSz, + int encrypt) +{ + word32 i, blocks, remainder; + ALIGN16 byte aesBlockIn[AES_BLOCK_SIZE]; + ALIGN16 byte aesBlockOut[AES_BLOCK_SIZE]; + word64* pIn; + word64* pOut; + word64* pIv; + + if (aes == NULL || in == NULL || out == NULL) + return BAD_FUNC_ARG; + + pIn = (word64*)aesBlockIn; + pOut = (word64*)aesBlockOut; + pIv = (word64*)aes->reg; + + CVMX_PREFETCH0(in); + + CVMX_MT_AES_ENC0(pIv[0]); + CVMX_MT_AES_ENC1(pIv[1]); + + blocks = inSz / AES_BLOCK_SIZE; + remainder = inSz % AES_BLOCK_SIZE; + + for (i = 0; i < blocks; + i++, in += AES_BLOCK_SIZE, out += AES_BLOCK_SIZE) { + CVMX_PREFETCH128(in); + aes->reg[3]++; + + CVMX_LOADUNA_INT64(pIn[0], in, 0); + CVMX_LOADUNA_INT64(pIn[1], in, 8); + + CVM_AES_RD_RESULT_WR_DATA(pOut[0], pOut[1], pIv[0], pIv[1]); + + if (encrypt) { + pOut[0] ^= pIn[0]; + pOut[1] ^= pIn[1]; + CVMX_MT_GFM_XOR0(pOut[0]); + CVMX_MT_GFM_XORMUL1(pOut[1]); + } + else { + CVMX_MT_GFM_XOR0(pIn[0]); + CVMX_MT_GFM_XORMUL1(pIn[1]); + pOut[0] ^= pIn[0]; + pOut[1] ^= pIn[1]; + } + + CVMX_STOREUNA_INT64(pOut[0], out, 0); + CVMX_STOREUNA_INT64(pOut[1], out, 8); + } + + if (remainder > 0) { + ALIGN16 byte aesBlockMask[AES_BLOCK_SIZE]; + word64* pMask = (word64*)aesBlockMask; + + XMEMSET(aesBlockOut, 0, sizeof(aesBlockOut)); + XMEMSET(aesBlockMask, 0, sizeof(aesBlockMask)); + for (i = 0; i < remainder; i++) { + aesBlockIn[i] = in[i]; + aesBlockMask[i] = 0xFF; + } + + if (encrypt) { + CVMX_MF_AES_RESULT(pOut[0], 0); + CVMX_MF_AES_RESULT(pOut[1], 1); + + pOut[0] ^= pIn[0]; + pOut[1] ^= pIn[1]; + + pOut[0] &= pMask[0]; + pOut[1] &= pMask[1]; + + CVMX_MT_GFM_XOR0(pOut[0]); + CVMX_MT_GFM_XORMUL1(pOut[1]); + } + else { + CVMX_MT_GFM_XOR0(pIn[0]); + CVMX_MT_GFM_XORMUL1(pIn[1]); + + CVMX_MF_AES_RESULT(pOut[0], 0); + CVMX_MF_AES_RESULT(pOut[1], 1); + + pOut[0] ^= pIn[0]; + pOut[1] ^= pIn[1]; + + pOut[0] &= pMask[0]; + pOut[1] &= pMask[1]; + } + + for (i = 0; i < remainder; i++) + out[i] = aesBlockOut[i]; + } + + return 0; +} + + +static NOOPT int Octeon_AesGcm_Finalize(Aes* aes, word32 inSz, word32 aadSz, + byte* tag) +{ + word64 bigSz; + word64* pIv; + word64* pIn; + word64* pOut; + uint32_t countSave; + ALIGN16 byte aesBlockIn[AES_BLOCK_SIZE]; + ALIGN16 byte aesBlockOut[AES_BLOCK_SIZE]; + + countSave = aes->reg[3]; + aes->reg[3] = aes->y0; + + pIv = (word64*)aes->reg; + CVMX_MT_AES_ENC0(pIv[0]); + CVMX_MT_AES_ENC1(pIv[1]); + + bigSz = (word64)aadSz * 8; + CVMX_MT_GFM_XOR0(bigSz); + bigSz = (word64)inSz * 8; + CVMX_MT_GFM_XORMUL1(bigSz); + + aes->reg[3] = countSave; + + pIn = (word64*)aesBlockIn; + CVMX_MF_AES_RESULT(pIn[0], 0); + CVMX_MF_AES_RESULT(pIn[1], 1); + + pOut = (word64*)aesBlockOut; + CVMX_MF_GFM_RESINP(pOut[0], 0); + CVMX_MF_GFM_RESINP(pOut[1], 1); + + pOut[0] ^= pIn[0]; + pOut[1] ^= pIn[1]; + + CVMX_STOREUNA_INT64(pOut[0], tag, 0); + CVMX_STOREUNA_INT64(pOut[1], tag, 8); + + return 0; +} + + +static int Octeon_AesGcm_Encrypt(Aes* aes, byte* in, byte* out, word32 inSz, + byte* iv, word32 ivSz, byte* aad, word32 aadSz, byte* tag) +{ + int ret = 0; + + if (aes == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) + ret = Octeon_AesGcm_SetKey(aes); + + if (ret == 0) + ret = Octeon_AesGcm_SetIV(aes, iv, ivSz); + + if (ret == 0) + ret = Octeon_AesGcm_SetAAD(aes, aad, aadSz); + + if (ret == 0) + ret = Octeon_AesGcm_SetEncrypt(aes, in, out, inSz, 1); + + if (ret == 0) + ret = Octeon_AesGcm_Finalize(aes, inSz, aadSz, tag); + + return ret; +} + + +static int Octeon_AesGcm_Decrypt(Aes* aes, byte* in, byte* out, word32 inSz, + byte* iv, word32 ivSz, byte* aad, word32 aadSz, byte* tag) +{ + int ret = 0; + + if (aes == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) + ret = Octeon_AesGcm_SetKey(aes); + + if (ret == 0) + ret = Octeon_AesGcm_SetIV(aes, iv, ivSz); + + if (ret == 0) + ret = Octeon_AesGcm_SetAAD(aes, aad, aadSz); + + if (ret == 0) + ret = Octeon_AesGcm_SetEncrypt(aes, in, out, inSz, 0); + + if (ret == 0) + ret = Octeon_AesGcm_Finalize(aes, inSz, aadSz, tag); + + return ret; +} + +#endif /* HAVE_AESGCM */ + +#endif /* !NO_AES */ + +#ifdef WOLF_CRYPTO_CB + +#include + + +static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) +{ + int ret = NOT_COMPILED_IN; /* return this to bypass HW and use SW */ + + if (info == NULL) + return BAD_FUNC_ARG; + +#ifdef DEBUG_WOLFSSL + printf("CryptoDevCb: Algo Type %d\n", info->algo_type); +#endif + + if (info->algo_type == WC_ALGO_TYPE_CIPHER) { +#if !defined(NO_AES) || !defined(NO_DES3) + #ifdef HAVE_AESGCM + if (info->cipher.type == WC_CIPHER_AES_GCM) { + if (info->cipher.enc) { + ret = Octeon_AesGcm_Encrypt( + info->cipher.aesgcm_enc.aes, + (byte*)info->cipher.aesgcm_enc.in, + (byte*)info->cipher.aesgcm_enc.out, + info->cipher.aesgcm_enc.sz, + (byte*)info->cipher.aesgcm_enc.iv, + info->cipher.aesgcm_enc.ivSz, + (byte*)info->cipher.aesgcm_enc.authIn, + info->cipher.aesgcm_enc.authInSz, + (byte*)info->cipher.aesgcm_enc.authTag); + } + else { + ret = Octeon_AesGcm_Decrypt( + info->cipher.aesgcm_dec.aes, + (byte*)info->cipher.aesgcm_dec.in, + (byte*)info->cipher.aesgcm_dec.out, + info->cipher.aesgcm_dec.sz, + (byte*)info->cipher.aesgcm_dec.iv, + info->cipher.aesgcm_dec.ivSz, + (byte*)info->cipher.aesgcm_dec.authIn, + info->cipher.aesgcm_dec.authInSz, + (byte*)info->cipher.aesgcm_dec.authTag); + } + } + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AES_CBC + if (info->cipher.type == WC_CIPHER_AES_CBC) { + if (info->cipher.enc) { + ret = Octeon_AesCbc_Encrypt( + info->cipher.aescbc.aes, + (word64*)info->cipher.aescbc.in, + (word64*)info->cipher.aescbc.out, + info->cipher.aescbc.sz); + } + else { + ret = Octeon_AesCbc_Decrypt( + info->cipher.aescbc.aes, + (word64*)info->cipher.aescbc.in, + (word64*)info->cipher.aescbc.out, + info->cipher.aescbc.sz); + } + } + #endif /* HAVE_AES_CBC */ + #ifndef NO_DES3 + if (info->cipher.type == WC_CIPHER_DES3) { + if (info->cipher.enc) { + ret = Octeon_Des3_CbcEncrypt( + info->cipher.des3.des, + (word64*)info->cipher.des3.in, + (word64*)info->cipher.des3.out, + info->cipher.des3.sz); + } + else { + ret = Octeon_Des3_CbcDecrypt( + info->cipher.des3.des, + (word64*)info->cipher.des3.in, + (word64*)info->cipher.des3.out, + info->cipher.des3.sz); + } + } + #endif /* !NO_DES3 */ +#endif /* !NO_AES || !NO_DES3 */ + } + + (void)devIdArg; + (void)ctx; + + return ret; +} + +int wc_CryptoCb_InitOcteon(void) +{ + if (wc_CryptoCb_RegisterDevice(devId, myCryptoDevCb, NULL) < 0) { + return INVALID_DEVID; + } + + return devId; +} + +void wc_CryptoCb_CleanupOcteon(int* id) +{ + wc_CryptoCb_UnRegisterDevice(*id); + *id = INVALID_DEVID; +} + +#endif /* WOLF_CRYPTO_CB */ + +#endif /* HAVE_CAVIUM_OCTEON_SYNC */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/README.md b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/README.md new file mode 100644 index 000000000..7844dca86 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/README.md @@ -0,0 +1,43 @@ +# Description + +Used to build with cryptodev-linux library with Linux OS. + +# Quick Start + +## Installing cryptodev module + +If not already installed then the cryptodev-linux module will need installed. + +``` +git clone https://github.com/cryptodev-linux/cryptodev-linux.git +cd cryptodev-linux +make +sudo make install +modprobe cryptodev +``` + + +## Options for building wolfSSL + +For default build with all supported features use: + +``` +./configure --enable-cryptodev +``` + +Or for more control over features used: + +``` +./configure --enable-devcrypto=cbc +./configure --enable-devcrypto=hash +./configure --enable-devcrypto=aes +./configure --enable-devcrypto=all +``` + +Then build the wolfSSL library with: + +``` +make +sudo make install +./wolfcrypt/test/testwolfcrypt +``` diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/devcrypto_aes.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/devcrypto_aes.c new file mode 100644 index 000000000..1f6d09d72 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/devcrypto_aes.c @@ -0,0 +1,384 @@ +/* devcrypto_aes.c + * + * Copyright (C) 2006-2020 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(NO_AES) && defined(WOLFSSL_DEVCRYPTO) + +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#if defined(HAVE_AES_CBC) && defined(WOLFSSL_DEVCRYPTO_CBC) +int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + struct crypt_op crt; + int ret; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + /* encrypt only up to AES block size of date */ + sz = sz - (sz % AES_BLOCK_SIZE); + if (aes->ctx.cfd == -1) { + ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_CBC, + (byte*)aes->devKey, aes->keylen); + if (ret != 0) + return ret; + } + wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)aes->reg, + COP_ENCRYPT); + ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt); + if (ret != 0) { + return WC_DEVCRYPTO_E; + } + + /* store iv for next call */ + XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + return 0; +} + +#ifdef HAVE_AES_DECRYPT +int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + struct crypt_op crt; + int ret; + + if (aes == NULL || out == NULL || in == NULL || sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + if (aes->ctx.cfd == -1) { + ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_CBC, + (byte*)aes->devKey, aes->keylen); + if (ret != 0) + return ret; + } + wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)aes->reg, + COP_DECRYPT); + ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt); + if (ret != 0) { + return WC_DEVCRYPTO_E; + } + + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + return 0; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_CBC && WOLFSSL_DEVCRYPTO_CBC */ + + +#ifdef WOLFSSL_DEVCRYPTO_AES /* all AES algorithms supported */ +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 || + !((keylen == 16) || (keylen == 24) || (keylen == 32))) { + return BAD_FUNC_ARG; + } + +#if defined(AES_MAX_KEY_SIZE) + /* Check key length */ + if (keylen > max_key_len) { + return BAD_FUNC_ARG; + } +#endif + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + +#ifdef WOLFSSL_AES_COUNTER + aes->left = 0; +#endif + aes->ctx.cfd = -1; + XMEMCPY(aes->devKey, userKey, keylen); + + (void)dir; + return wc_AesSetIV(aes, iv); +} + + +/* AES-DIRECT */ +#if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AES_ECB) + +/* common code between ECB encrypt and decrypt + * returns 0 on success */ +static int wc_DevCrypto_AesDirect(Aes* aes, byte* out, const byte* in, + word32 sz, int dir) +{ + int ret; + struct crypt_op crt; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + if (aes->ctx.cfd == -1) { + ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_ECB, (byte*)aes->devKey, + aes->keylen); + if (ret != 0) + return ret; + } + + wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, NULL, dir); + ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt); + if (ret != 0) { + return WC_DEVCRYPTO_E; + } + return 0; +} +#endif + + +#if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESCCM) +void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) +{ + wc_DevCrypto_AesDirect(aes, out, in, AES_BLOCK_SIZE, COP_ENCRYPT); +} + + +void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) +{ + wc_DevCrypto_AesDirect(aes, out, in, AES_BLOCK_SIZE, COP_DECRYPT); +} + + +int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) +{ + return wc_AesSetKey(aes, userKey, keylen, iv, dir); +} +#endif + + +/* AES-CTR */ +#if defined(WOLFSSL_AES_COUNTER) + +/* Increment AES counter */ +static WC_INLINE void IncrementAesCounter(byte* inOutCtr) +{ + /* 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; + } +} + +int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int ret; + struct crypt_op crt; + 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--; + sz--; + } + + if (aes->ctx.cfd == -1) { + ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_CTR, (byte*)aes->devKey, + aes->keylen); + if (ret != 0) + return ret; + } + + if (sz > 0) { + /* clear previously leftover data */ + tmp = (byte*)aes->tmp; + XMEMSET(tmp, 0, AES_BLOCK_SIZE); + + /* update IV */ + wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)aes->reg, + COP_ENCRYPT); + ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt); + if (ret != 0) { + return WC_DEVCRYPTO_E; + } + + /* adjust counter after call to hardware */ + while (sz >= AES_BLOCK_SIZE) { + IncrementAesCounter((byte*)aes->reg); + sz -= AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + } + } + + /* create key stream for later if needed */ + if (sz > 0) { + Aes tmpAes; + wc_AesSetKey(&tmpAes, (byte*)aes->devKey, aes->keylen, (byte*)aes->reg, + AES_ENCRYPTION); + wc_AesEncryptDirect(&tmpAes, (byte*)aes->tmp, (const byte*)aes->reg); + wc_AesFree(&tmpAes); + IncrementAesCounter((byte*)aes->reg); + + aes->left = AES_BLOCK_SIZE - (sz % AES_BLOCK_SIZE); + } + + return 0; +} +#endif /* WOLFSSL_AES_COUNTER */ + + +#ifdef HAVE_AESGCM + +int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) +{ + return wc_AesSetKey(aes, key, len, NULL, AES_ENCRYPTION); +} + + + +/* common code for AES-GCM encrypt/decrypt */ +static int wc_DevCrypto_AesGcm(Aes* aes, byte* out, byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz, + int dir) +{ + struct crypt_auth_op crt = {0}; + int ret; + byte scratch[AES_BLOCK_SIZE]; + + /* argument checks */ + if (aes == NULL || authTagSz > AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + /* Account for NULL in/out buffers. Up to tag size is still written into + * in/out buffers */ + if (out == NULL) + out = scratch; + if (in == NULL) + in = scratch; + + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + if (aes->ctx.cfd == -1) { + ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_GCM, (byte*)aes->devKey, + aes->keylen); + if (ret != 0) + return ret; + } + + /* if decrypting then the tag is expected to be at the end of "in" buffer */ + if (dir == COP_DECRYPT) { + XMEMCPY(in + sz, authTag, authTagSz); + sz += authTagSz; + } + else{ + /* get full tag from hardware */ + authTagSz = AES_BLOCK_SIZE; + } + wc_SetupCryptAead(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)iv, ivSz, + dir, (byte*)authIn, authInSz, authTag, authTagSz); + ret = ioctl(aes->ctx.cfd, CIOCAUTHCRYPT, &crt); + if (ret != 0) { + if (dir == COP_DECRYPT) { + return AES_GCM_AUTH_E; + } + else { + return WC_DEVCRYPTO_E; + } + } + + /* after encryption the tag has been placed at the end of "out" buffer */ + if (dir == COP_ENCRYPT) { + XMEMCPY(authTag, out + sz, authTagSz); + } + return 0; +} + + +/* it is assumed that "out" buffer has enough room for cipher text + tag */ +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 (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + + return wc_DevCrypto_AesGcm(aes, out, (byte*)in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz, + COP_ENCRYPT); +} + +#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT) +/* it is assumed that "in" buffer has enough room for cipher text + tag */ +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 wc_DevCrypto_AesGcm(aes, out, (byte*)in, sz, iv, ivSz, + (byte*)authTag, authTagSz, authIn, authInSz, + COP_DECRYPT); +} +#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */ +#endif /* HAVE_AESGCM */ + + +#ifdef HAVE_AES_ECB +int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_DevCrypto_AesDirect(aes, out, in, sz, COP_ENCRYPT); +} + + +int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_DevCrypto_AesDirect(aes, out, in, sz, COP_DECRYPT); +} +#endif /* HAVE_AES_ECB */ +#endif /* WOLFSSL_DEVCRYPTO_AES */ +#endif /* !NO_AES && WOLFSSL_DEVCRYPTO */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/devcrypto_hash.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/devcrypto_hash.c new file mode 100644 index 000000000..f73224dd8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/devcrypto_hash.c @@ -0,0 +1,248 @@ +/* devcrypto_hash.c + * + * Copyright (C) 2006-2020 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_DEVCRYPTO_HASH) + +#include +#include +#include + +#if !defined(NO_SHA256) +#include +#endif + +/* dereference structure based on type to get cryptodev context pointer + * can return NULL on fail case */ +static WC_CRYPTODEV* GetHashContext(void* ctx, int type) +{ + switch (type) { + case CRYPTO_SHA2_256: + return &((wc_Sha256*)ctx)->ctx; + + default: + return NULL; + } + + return NULL; +} + + +/* generic hash initialization + * key is for hmac algorithms and keySz is for the size of key buffer + * key should be null in the case of non hmac algorithms + * return 0 on success */ +static int HashInit(void* ctx, int type, byte* key, word32 keySz) +{ + WC_CRYPTODEV* cdev; + + if ((cdev = GetHashContext(ctx, type)) == NULL) { + WOLFSSL_MSG("Unsupported hash type"); + return BAD_FUNC_ARG; + } + + return wc_DevCryptoCreate(cdev, type, key, keySz); +} + + +/* generic function for updated hash structure + * returns 0 on success */ +static int HashUpdate(void* ctx, int type, const byte* input, word32 inputSz) +{ + WC_CRYPTODEV* dev; + struct crypt_op crt; + byte digest[64]; + + if (inputSz == 0) { + return 0; + } + + if ((dev = GetHashContext(ctx, type)) == NULL) { + WOLFSSL_MSG("Unsupported hash type"); + return BAD_FUNC_ARG; + } + + wc_SetupCrypt(&crt, dev, (byte*)input, inputSz, NULL, digest, COP_FLAG_UPDATE); + if (ioctl(dev->cfd, CIOCCRYPT, &crt)) { + WOLFSSL_MSG("Error with call to ioctl"); + return WC_DEVCRYPTO_E; + } + + return 0; +} + + +/* generic function for getting final digest value */ +static int GetDigest(void* ctx, int type, byte* out) +{ + WC_CRYPTODEV* dev; + struct crypt_op crt; + + if ((dev = GetHashContext(ctx, type)) == NULL) { + WOLFSSL_MSG("Unsupported hash type"); + return BAD_FUNC_ARG; + } + + wc_SetupCrypt(&crt, dev, NULL, 0, NULL, out, COP_FLAG_FINAL); + if (ioctl(dev->cfd, CIOCCRYPT, &crt)) { + WOLFSSL_MSG("Error with call to ioctl"); + return WC_DEVCRYPTO_E; + } + + return 0; +} + +#if !defined(NO_SHA256) + +int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId) +{ + if (sha == NULL) { + return BAD_FUNC_ARG; + } + + (void)devId; /* no async for now */ + XMEMSET(sha, 0, sizeof(wc_Sha256)); + sha->heap = heap; + + return HashInit((void*)sha, CRYPTO_SHA2_256, NULL, 0); +} + + +int wc_Sha256Update(wc_Sha256* sha, const byte* in, word32 sz) +{ + if (sha == NULL || (sz > 0 && in == NULL)) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_DEVCRYPTO_HASH_KEEP + /* keep full message to hash at end instead of incremental updates */ + if (sha->len < sha->used + sz) { + if (sha->msg == NULL) { + sha->msg = (byte*)XMALLOC(sha->used + sz, sha->heap, + DYNAMIC_TYPE_TMP_BUFFER); + } else { + byte* pt = (byte*)XREALLOC(sha->msg, sha->used + sz, sha->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (pt == NULL) { + return MEMORY_E; + } + sha->msg = pt; + } + if (sha->msg == NULL) { + return MEMORY_E; + } + sha->len = sha->used + sz; + } + XMEMCPY(sha->msg + sha->used, in, sz); + sha->used += sz; + return 0; +#else + return HashUpdate(sha, CRYPTO_SHA2_256, in, sz); +#endif +} + + +int wc_Sha256Final(wc_Sha256* sha, byte* hash) +{ + int ret; + + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + /* help static analysis tools out */ + XMEMSET(hash, 0, WC_SHA256_DIGEST_SIZE); +#ifdef WOLFSSL_DEVCRYPTO_HASH_KEEP + /* keep full message to hash at end instead of incremental updates */ + if ((ret = HashUpdate(sha, CRYPTO_SHA2_256, sha->msg, sha->used)) < 0) { + return ret; + } + XFREE(sha->msg, sha->heap, DYNAMIC_TYPE_TMP_BUFFER); + sha->msg = NULL; +#endif + ret = GetDigest(sha, CRYPTO_SHA2_256, hash); + if (ret != 0) { + return ret; + } + + wc_Sha256Free(sha); + return wc_InitSha256_ex(sha, sha->heap, 0); +} + + +int wc_Sha256GetHash(wc_Sha256* sha, byte* hash) +{ + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_DEVCRYPTO_HASH_KEEP + { + int ret; + wc_Sha256 cpy; + wc_Sha256Copy(sha, &cpy); + + if ((ret = HashUpdate(&cpy, CRYPTO_SHA2_256, cpy.msg, cpy.used)) == 0) { + /* help static analysis tools out */ + XMEMSET(hash, 0, WC_SHA256_DIGEST_SIZE); + ret = GetDigest(&cpy, CRYPTO_SHA2_256, hash); + } + wc_Sha256Free(&cpy); + return ret; + } +#else + (void)sha; + (void)hash; + + WOLFSSL_MSG("Compile with WOLFSSL_DEVCRYPTO_HASH_KEEP for this feature"); + return NOT_COMPILED_IN; +#endif +} + +int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + + wc_InitSha256_ex(dst, src->heap, 0); +#ifdef WOLFSSL_DEVCRYPTO_HASH_KEEP + dst->len = src->len; + dst->used = src->used; + dst->msg = (byte*)XMALLOC(src->len, dst->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (dst->msg == NULL) { + return MEMORY_E; + } + XMEMCPY(dst->msg, src->msg, src->len); +#endif + + return 0; +} + +#endif /* !NO_SHA256 */ + +#endif /* WOLFSSL_DEVCRYPTO */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/wc_devcrypto.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/wc_devcrypto.c new file mode 100644 index 000000000..2c80518a3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/devcrypto/wc_devcrypto.c @@ -0,0 +1,167 @@ +/* wc_devcrypto.c + * + * Copyright (C) 2006-2020 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_DEVCRYPTO) + +#include +#include +#include + +/* sets up a context for talking to /dev/crypto + * return 0 on success */ +int wc_DevCryptoCreate(WC_CRYPTODEV* ctx, int type, byte* key, word32 keySz) +{ + int fd; + int isHash = 0; /* flag for if hashing algorithm */ + + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + /* sanity check on session type before creating descriptor */ + XMEMSET(ctx, 0, sizeof(WC_CRYPTODEV)); + switch (type) { + case CRYPTO_SHA1: + case CRYPTO_SHA2_256: + isHash = 1; + break; + + #ifndef NO_AES + case CRYPTO_AES_CTR: + case CRYPTO_AES_ECB: + case CRYPTO_AES_GCM: + case CRYPTO_AES_CBC: + isHash = 0; + break; + #endif + + default: + WOLFSSL_MSG("Unknown / Unimplemented algorithm type"); + return BAD_FUNC_ARG; + } + + /* create descriptor */ + if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) { + WOLFSSL_MSG("Error opening /dev/crypto is cryptodev module loaded?"); + return WC_DEVCRYPTO_E; + } + if (fcntl(fd, F_SETFD, 1) == -1) { + WOLFSSL_MSG("Error setting F_SETFD with fcntl"); + close(fd); + return WC_DEVCRYPTO_E; + } + + /* set up session */ + ctx->cfd = fd; + + if (isHash) { + ctx->sess.mac = type; + } + else { + ctx->sess.cipher = type; + ctx->sess.key = (void*)key; + ctx->sess.keylen = keySz; + } + + if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) { + close(fd); + WOLFSSL_MSG("Error starting cryptodev session"); + return WC_DEVCRYPTO_E; + } + + (void)key; + (void)keySz; + + return 0; +} + + +/* free up descriptor and session used with ctx */ +void wc_DevCryptoFree(WC_CRYPTODEV* ctx) +{ + if (ctx != NULL && ctx->cfd >= 0) { + if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) { + WOLFSSL_MSG("Error stopping cryptodev session"); + } + close(ctx->cfd); + } +} + + +/* setup crypt_op structure */ +void wc_SetupCrypt(struct crypt_op* crt, WC_CRYPTODEV* dev, + byte* src, int srcSz, byte* dst, byte* dig, int flag) + +{ + XMEMSET(crt, 0, sizeof(struct crypt_op)); + crt->ses = dev->sess.ses; + crt->src = src; + crt->len = srcSz; + crt->dst = dst; + crt->mac = dig; + crt->flags = flag; +} + + +/* setup crypt_op structure for symmetric key operations */ +void wc_SetupCryptSym(struct crypt_op* crt, WC_CRYPTODEV* dev, + byte* src, word32 srcSz, byte* dst, byte* iv, int flag) + +{ + XMEMSET(crt, 0, sizeof(struct crypt_op)); + crt->ses = dev->sess.ses; + crt->src = src; + crt->len = srcSz; + crt->dst = dst; + crt->iv = iv; + crt->op = flag; +} + + +/* setup crypt_auth_op structure for aead operations */ +void wc_SetupCryptAead(struct crypt_auth_op* crt, WC_CRYPTODEV* dev, + byte* src, word32 srcSz, byte* dst, byte* iv, word32 ivSz, int flag, + byte* authIn, word32 authInSz, byte* authTag, word32 authTagSz) +{ + XMEMSET(crt, 0, sizeof(struct crypt_op)); + crt->ses = dev->sess.ses; + crt->src = src; + crt->len = srcSz; + crt->dst = dst; + crt->iv = iv; + crt->iv_len = ivSz; + crt->op = flag; + + /* also set auth in and tag */ + crt->auth_src = authIn; + crt->auth_len = authInSz; + crt->tag = authTag; + crt->tag_len = authTagSz; +} +#endif /* WOLFSSL_DEVCRYPTO */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/README.md b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/README.md new file mode 100644 index 000000000..4b5d971ba --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/quickassist.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/quickassist.c new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/quickassist_mem.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/quickassist_mem.c new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/quickassist_sync.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/quickassist_sync.c new file mode 100644 index 000000000..e03bca91f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/intel/quickassist_sync.c @@ -0,0 +1,2004 @@ +/* quickassist_sync.c + * + * Copyright (C) 2006-2020 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_INTEL_QA_SYNC + +#ifdef QAT_DEMO_MAIN + #define QAT_DEBUG +#endif + + +#include +#include +#include +#ifndef NO_AES + #include +#endif + +#include +#include + +#include "cpa.h" +#include "cpa_cy_im.h" +#include "cpa_cy_sym.h" +#include "cpa_cy_rsa.h" +#include "cpa_cy_ln.h" +#include "cpa_cy_ecdh.h" +#include "cpa_cy_ecdsa.h" +#include "cpa_cy_dh.h" +#include "cpa_cy_drbg.h" +#include "cpa_cy_nrbg.h" +#include "cpa_cy_prime.h" + +#include "icp_sal_user.h" +#include "icp_sal_poll.h" + + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* User space utils */ +#include +#include +#include +#include + +#if 0 + /* Optional feature for partial QAT hashing support */ + /* This will process updates through hardware instead of caching them */ + #define QAT_HASH_ENABLE_PARTIAL +#endif +#ifdef QAT_HASH_ENABLE_PARTIAL + #define MAX_QAT_HASH_BUFFERS 2 +#endif + +/* Detect QAT driver version */ +#if defined(CPA_CY_API_VERSION_NUM_MAJOR) && CPA_CY_API_VERSION_NUM_MAJOR > 1 + #define QAT_V2 +#endif + +#ifdef QAT_V2 + /* quickassist/utilities/libusdm_drv/qae_mem.h */ + /* Provides user-space API's for accessing NUMA allocated memory through usdm_drv */ + #include "qae_mem.h" +#include "linux/include/qae_mem_utils.h" +#endif + +#ifdef QAT_USE_POLLING_THREAD + #include +#endif + +/* Tunable parameters */ +#ifndef QAT_PROCESS_NAME + #define QAT_PROCESS_NAME "SSL" +#endif +#ifndef QAT_LIMIT_DEV_ACCESS + #define QAT_LIMIT_DEV_ACCESS CPA_FALSE +#endif +#ifndef QAT_MAX_DEVICES + #define QAT_MAX_DEVICES (1) /* maximum number of QAT cards */ +#endif + +#ifndef QAT_RETRY_LIMIT + #define QAT_RETRY_LIMIT (100) +#endif +#ifndef QAT_POLL_RESP_QUOTA + #define QAT_POLL_RESP_QUOTA (0) /* all pending */ +#endif + +#if !defined(NO_AES) || !defined(NO_DES3) + #define QAT_ENABLE_CRYPTO +#endif + +/* Pre-declarations */ +struct IntelQaDev; +struct wc_CryptoInfo; +struct WC_BIGINT; +struct WC_RNG; + + +#if defined(QAT_ENABLE_HASH) || defined(QAT_ENABLE_CRYPTO) +/* symmetric context */ +typedef struct IntelQaSymCtx { + CpaCySymOpData opData; + CpaCySymSessionCtx symCtxSrc; + CpaCySymSessionCtx symCtx; + word32 symCtxSize; + + /* flags */ + word32 isOpen:1; + word32 isCopy:1; +} IntelQaSymCtx; +#endif + +typedef void (*IntelQaFreeFunc)(struct IntelQaDev*); + + +/* QuickAssist device */ +typedef struct IntelQaDev { + CpaInstanceHandle handle; + int devId; + void* heap; + + /* callback return info */ + int ret; + byte* out; + union { + word32* outLenPtr; + word32 outLen; + }; + + /* operations */ + IntelQaFreeFunc freeFunc; + union { + #ifdef QAT_ENABLE_CRYPTO + struct { + IntelQaSymCtx ctx; + CpaBufferList bufferList; + CpaFlatBuffer flatBuffer; + byte* authTag; + word32 authTagSz; + } cipher; + #endif + } op; + +#ifdef QAT_USE_POLLING_THREAD + pthread_t pollingThread; + byte pollingCy; +#endif +} IntelQaDev; + + +/* Interface */ +static int IntelQaHardwareStart(const char*, int); +static void IntelQaHardwareStop(void); +static int IntelQaInit(void*); +static void IntelQaDeInit(int); +static int IntelQaNumInstances(void); +static int IntelQaOpen(IntelQaDev*, int); +static void IntelQaClose(IntelQaDev*); +static int IntelQaDevCopy(IntelQaDev*, IntelQaDev*); +static int IntelQaPoll(IntelQaDev*); +static int IntelQaGetCyInstanceCount(void); + +#ifndef NO_AES + #ifdef HAVE_AES_CBC + static int IntelQaSymAesCbcEncrypt(IntelQaDev*, byte*, + const byte*, word32, const byte*, word32, const byte*, word32); + #ifdef HAVE_AES_DECRYPT + static int IntelQaSymAesCbcDecrypt(IntelQaDev*, byte*, + const byte*, word32, const byte*, word32, const byte*, word32); + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AES_CBC */ + + #ifdef HAVE_AESGCM + static int IntelQaSymAesGcmEncrypt(IntelQaDev*, byte*, + const byte*, word32, const byte*, word32, const byte*, word32, + byte*, word32, const byte*, word32); + #ifdef HAVE_AES_DECRYPT + static int IntelQaSymAesGcmDecrypt(IntelQaDev*, byte*, + const byte*, word32, const byte*, word32, const byte*, word32, + const byte*, word32, const byte*, word32); + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AESGCM */ +#endif /* !NO_AES */ + +#ifndef NO_DES3 + static int IntelQaSymDes3CbcEncrypt(IntelQaDev*, byte*, + const byte*, word32, const byte*, word32, const byte* iv, word32); + static int IntelQaSymDes3CbcDecrypt(IntelQaDev* dev, byte*, + const byte*, word32, const byte*, word32, const byte* iv, word32); +#endif /*! NO_DES3 */ + +#ifdef WOLF_CRYPTO_CB + static int IntelQaSymSync_CryptoDevCb(int, struct wc_CryptoInfo*, + void*); +#endif /* WOLF_CRYPTO_CB */ + + +#ifdef QAT_DEBUG + #define QLOG(...) do { printf(__VA_ARGS__); } while (0) +#else + #define QLOG(...) +#endif + + +#define OS_HOST_TO_NW_32(uData) ByteReverseWord32(uData) + + +static CpaInstanceHandle* g_cyInstances = NULL; +static CpaInstanceInfo2* g_cyInstanceInfo = NULL; +static Cpa32U* g_cyInstMap = NULL; +static Cpa16U g_numInstances = 0; +static Cpa16U g_instCounter = 0; +static CpaBoolean g_cyServiceStarted = CPA_FALSE; +#ifdef QAT_USE_POLLING_CHECK + static CpaBoolean* g_cyPolling = NULL; + static pthread_mutex_t* g_PollLock; +#endif +static volatile int g_initCount = 0; +static pthread_mutex_t g_Hwlock = PTHREAD_MUTEX_INITIALIZER; + + +typedef struct qatCapabilities { + /* capabilities */ + word32 supPartial:1; + word32 supSha3:1; +} qatCapabilities_t; +static qatCapabilities_t g_qatCapabilities = {0}; + + +#if defined(QAT_ENABLE_CRYPTO) + static int IntelQaSymClose(IntelQaDev* dev, int doFree); +#endif + + +extern Cpa32U osalLogLevelSet(Cpa32U level); + + +static IntelQaDev qaDev; + + +/* -------------------------------------------------------------------------- */ +/* Polling */ +/* -------------------------------------------------------------------------- */ + +static WC_INLINE int SyncSleep(word32 ms) +{ + int ret = 0; + struct timespec resTime, remTime; + resTime.tv_sec = ms/1000; + resTime.tv_nsec = (ms%1000)*1000000; + do { + ret = nanosleep(&resTime, &remTime); + resTime = remTime; + } while ((ret!=0) && (errno == EINTR)); + + if (ret != 0) { + QLOG("nanoSleep failed with code %d\n", ret); + return BAD_FUNC_ARG; + } + + return ret; +} + +#ifdef QAT_USE_POLLING_THREAD +static void* IntelQaPollingThread(void* context) +{ + IntelQaDev* dev = (IntelQaDev*)context; + + QLOG("Polling Thread Start\n"); + while (dev->pollingCy) { + icp_sal_CyPollInstance(dev->handle, QAT_POLL_RESP_QUOTA); + SyncSleep(10); + } + QLOG("Polling Thread Exit\n"); + pthread_exit(NULL); +} + +static CpaStatus IntelQaStartPollingThread(IntelQaDev* dev) +{ + if (dev->pollingCy == 0) { + dev->pollingCy = 1; + + QLOG("Polling Thread Created\n"); + + if (pthread_create(&dev->pollingThread, NULL, IntelQaPollingThread, + (void*)dev) != 0) { + QLOG("Failed create polling thread!\n"); + return CPA_STATUS_FAIL; + } + } + return CPA_STATUS_SUCCESS; +} + +static void IntelQaStopPollingThread(IntelQaDev* dev) +{ + dev->pollingCy = 0; + pthread_join(dev->pollingThread, 0); +} +#endif /* QAT_USE_POLLING_THREAD */ + + +/* -------------------------------------------------------------------------- */ +/* Device */ +/* -------------------------------------------------------------------------- */ +void IntelQaHardwareStop(void) +{ + int i; + CpaStatus status; + + g_initCount--; /* track de-init count */ + if (g_initCount != 0) { + return; + } + + if (g_cyServiceStarted == CPA_TRUE) { + g_cyServiceStarted = CPA_FALSE; + for (i=0; i 1) { + return 0; + } + + status = qaeMemInit(); + if (status != CPA_STATUS_SUCCESS) { + QLOG("IntelQA: Could not start qae mem for user space (status %d)\n" + "\tHas the qaeMemDrv.ko module been loaded?\n", + status); + return ASYNC_INIT_E; + } + + status = icp_sal_userStartMultiProcess(process_name, + limitDevAccess ? CPA_TRUE : CPA_FALSE); + if (status != CPA_STATUS_SUCCESS) { + QLOG("IntelQA: Could not start sal for user space! status %d\n", + status); + ret = ASYNC_INIT_E; goto error; + } + +#ifdef QAT_DEBUG + /* optionally enable debugging */ + //osalLogLevelSet(8); +#endif + + status = cpaCyGetNumInstances(&g_numInstances); + if (status != CPA_STATUS_SUCCESS || g_numInstances == 0) { + QLOG("IntelQA: Failed to get num of instances! status %d\n", status); + ret = INVALID_DEVID; goto error; + } + + /* Get handles / info */ + g_cyInstances = (CpaInstanceHandle*)XMALLOC( + sizeof(CpaInstanceHandle) * g_numInstances, NULL, DYNAMIC_TYPE_ASYNC); + if (g_cyInstances == NULL) { + QLOG("IntelQA: Failed to allocate instances\n"); + ret = INVALID_DEVID; goto error; + } + +#ifdef QAT_USE_POLLING_CHECK + g_cyPolling = (CpaBoolean*)XMALLOC(sizeof(CpaBoolean) * g_numInstances, NULL, + DYNAMIC_TYPE_ASYNC); + if (g_cyPolling == NULL) { + QLOG("IntelQA: Failed to allocate polling status\n"); + ret = INVALID_DEVID; goto error; + } + g_PollLock = (pthread_mutex_t*)XMALLOC(sizeof(pthread_mutex_t) * + g_numInstances, NULL, DYNAMIC_TYPE_ASYNC); + if (g_PollLock == NULL) { + QLOG("IntelQA: Failed to allocate polling locks\n"); + ret = INVALID_DEVID; goto error; + } + for (i=0; i> 8), + (Cpa8U)((g_cyInstanceInfo[i].physInstId.busAddress) + & 0xFF) >> 3, + (Cpa8U)((g_cyInstanceInfo[i].physInstId.busAddress) & 3), + g_cyInstanceInfo[i].isPolled); + + status = cpaCySetAddressTranslation(g_cyInstances[i], + qaeVirtToPhysNUMA); + if (status != CPA_STATUS_SUCCESS) { + QLOG("IntelQA: Error setting memory config for inst %d\n", i); + ret = INVALID_DEVID; goto error; + } + + status = cpaCyStartInstance(g_cyInstances[i]); + if (status != CPA_STATUS_SUCCESS) { + QLOG("IntelQA: Error starting crypto instance %d\n", i); + ret = INVALID_DEVID; goto error; + } + } + + QLOG("IntelQA: Instances %d\n", g_numInstances); + return ret; + +error: + IntelQaHardwareStop(); + return ret; +} + + +int IntelQaInit(void* threadId) +{ + int ret; + int devId; + (void)threadId; + + ret = pthread_mutex_lock(&g_Hwlock); + if (ret != 0) { + QLOG("IntelQaInit: mutex lock failed! %d\n", ret); + return BAD_MUTEX_E; + } + + ret = IntelQaHardwareStart(QAT_PROCESS_NAME, QAT_LIMIT_DEV_ACCESS); + if (ret != 0) { + pthread_mutex_unlock(&g_Hwlock); + return ret; + } + + if (g_numInstances <= 0) { + pthread_mutex_unlock(&g_Hwlock); + return ASYNC_INIT_E; + } + + /* assign device id */ + devId = (g_instCounter % g_numInstances); + g_instCounter++; + + pthread_mutex_unlock(&g_Hwlock); + + return devId; +} + + +int IntelQaNumInstances(void) +{ + return g_numInstances; +} + + +int IntelQaOpen(IntelQaDev* dev, int devId) +{ + if (dev == NULL) { + return BAD_FUNC_ARG; + } + + /* clear device info */ + XMEMSET(dev, 0, sizeof(IntelQaDev)); + + if (g_cyInstances == NULL) { + QLOG("IntelQA not initialized\n"); + return ASYNC_INIT_E; + } + + dev->devId = devId; + dev->handle = g_cyInstances[devId]; + +#ifdef QAT_USE_POLLING_THREAD + /* start polling thread */ + IntelQaStartPollingThread(dev); +#endif + + return 0; +} + + +#if defined(QAT_ENABLE_CRYPTO) + +static IntelQaSymCtx* IntelQaGetSymCtx(IntelQaDev* dev) +{ + return &dev->op.cipher.ctx; +} + +#endif + + +void IntelQaClose(IntelQaDev* dev) +{ + if (dev) { + QLOG("IntelQaClose %p\n", dev); + /* close any active session */ + IntelQaSymClose(dev, 1); + + #ifdef QAT_USE_POLLING_THREAD + IntelQaStopPollingThread(dev); + #endif + + dev->handle = NULL; + } +} + +void IntelQaDeInit(int devId) +{ + (void)devId; + + if (pthread_mutex_lock(&g_Hwlock) == 0) { + IntelQaHardwareStop(); + pthread_mutex_unlock(&g_Hwlock); + } +} + +int IntelQaPoll(IntelQaDev* dev) +{ + int ret = 0; + CpaStatus status; + +#ifdef QAT_USE_POLLING_CHECK + pthread_mutex_t* lock = &g_PollLock[dev->qat.devId]; + if (pthread_mutex_lock(lock) == 0) { + /* test if any other threads are polling */ + if (g_cyPolling[dev->qat.devId]) { + pthread_mutex_unlock(lock); + + /* return success even though its busy, caller will treat as WC_PENDING_E */ + return 0; + } + + g_cyPolling[dev->qat.devId] = 1; + pthread_mutex_unlock(lock); + } +#endif + + status = icp_sal_CyPollInstance(dev->handle, QAT_POLL_RESP_QUOTA); + if (status != CPA_STATUS_SUCCESS && status != CPA_STATUS_RETRY) { + QLOG("IntelQa: Poll failure %d\n", status); + ret = -1; + } + + { + if (dev->ret != WC_PENDING_E) { + /* perform cleanup */ + IntelQaFreeFunc freeFunc = dev->freeFunc; + QLOG("IntelQaOpFree: Dev %p, FreeFunc %p\n", dev, freeFunc); + if (freeFunc) { + dev->freeFunc = NULL; + freeFunc(dev); + } + } + } + +#ifdef QAT_USE_POLLING_CHECK + /* indicate we are done polling */ + if (pthread_mutex_lock(lock) == 0) { + g_cyPolling[dev->qat.devId] = 0; + pthread_mutex_unlock(lock); + } +#endif + + return ret; +} + +static int IntelQaPollBlockRet(IntelQaDev* dev, int ret_wait) +{ + int ret; + + do { + ret = IntelQaPoll(dev); + + if (dev->ret != ret_wait) { + break; + } + } while (1); + ret = dev->ret; + + return ret; +} + +int IntelQaGetCyInstanceCount(void) +{ + return g_numInstances; +} + +static WC_INLINE int IntelQaHandleCpaStatus(IntelQaDev* dev, CpaStatus status, + int* ret, byte isAsync, void* callback, int* retryCount) +{ + int retry = 0; + + if (status == CPA_STATUS_SUCCESS) { + if (isAsync && callback) { + *ret = WC_PENDING_E; + } + else { + *ret = IntelQaPollBlockRet(dev, WC_PENDING_E); + } + } + else if (status == CPA_STATUS_RETRY) { + (*retryCount)++; + if ((*retryCount % (QAT_RETRY_LIMIT + 1)) == QAT_RETRY_LIMIT) { + SyncSleep(10); + } + retry = 1; + } + else { + *ret = ASYNC_OP_E; + } + + return retry; +} + +static WC_INLINE void IntelQaOpInit(IntelQaDev* dev, IntelQaFreeFunc freeFunc) +{ + dev->ret = WC_PENDING_E; + dev->freeFunc = freeFunc; +} + + +/* -------------------------------------------------------------------------- */ +/* Symmetric Algos */ +/* -------------------------------------------------------------------------- */ + +#if defined(QAT_ENABLE_CRYPTO) + +static int IntelQaSymOpen(IntelQaDev* dev, CpaCySymSessionSetupData* setup, + CpaCySymCbFunc callback) +{ + int ret = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U sessionCtxSize = 0; + IntelQaSymCtx* ctx; + + /* arg check */ + if (dev == NULL || setup == NULL) { + return BAD_FUNC_ARG; + } + + ctx = IntelQaGetSymCtx(dev); + + /* Determine size of session context to allocate - use max size */ + status = cpaCySymSessionCtxGetSize(dev->handle, setup, &sessionCtxSize); + + if (ctx->symCtxSize > 0 && ctx->symCtxSize > sessionCtxSize) { + QLOG("Symmetric context size error! Buf %d, Exp %d\n", + ctx->symCtxSize, sessionCtxSize); + return ASYNC_OP_E; + } + + /* make sure session context is allocated */ + if (ctx->symCtx == NULL) { + /* Allocate session context */ + ctx->symCtx = XMALLOC(sessionCtxSize, dev->heap, DYNAMIC_TYPE_ASYNC_NUMA64); + if (ctx->symCtx == NULL) { + return MEMORY_E; + } + } + ctx->symCtxSize = sessionCtxSize; + + if (!ctx->isOpen) { + ctx->isOpen = 1; + + QLOG("IntelQaSymOpen: InitSession dev %p, symCtx %p\n", + dev, ctx->symCtx); + + /* open symmetric session */ + status = cpaCySymInitSession(dev->handle, callback, setup, ctx->symCtx); + if (status != CPA_STATUS_SUCCESS) { + QLOG("cpaCySymInitSession failed! dev %p, status %d\n", + dev, status); + XFREE(ctx->symCtx, dev->heap, DYNAMIC_TYPE_ASYNC_NUMA64); + ctx->symCtx = NULL; + return ASYNC_INIT_E; + } + } + + if (ctx->symCtxSrc == NULL) { + ctx->symCtxSrc = ctx->symCtx; + } + + QLOG("IntelQaSymOpen: dev %p, symCtx %p (src %p), " + "symCtxSize %d, isCopy %d, isOpen %d\n", + dev, ctx->symCtx, ctx->symCtxSrc, ctx->symCtxSize, + ctx->isCopy, ctx->isOpen); + + return ret; +} + +static int IntelQaSymClose(IntelQaDev* dev, int doFree) +{ + int ret = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + IntelQaSymCtx* ctx; + + if (dev == NULL) { + return BAD_FUNC_ARG; + } + + ctx = IntelQaGetSymCtx(dev); + + QLOG("IntelQaSymClose: dev %p, ctx %p, symCtx %p (src %p), " + "symCtxSize %d, isCopy %d, isOpen %d, doFree %d\n", + dev, ctx, ctx->symCtx, ctx->symCtxSrc, ctx->symCtxSize, + ctx->isCopy, ctx->isOpen, doFree); + + if (ctx->symCtx == ctx->symCtxSrc && ctx->symCtx != NULL) { + if (ctx->isOpen) { + ctx->isOpen = 0; + QLOG("IntelQaSymClose: RemoveSession dev %p, symCtx %p\n", + dev, ctx->symCtx); + status = cpaCySymRemoveSession(dev->handle, ctx->symCtx); + if (status == CPA_STATUS_RETRY) { + QLOG("cpaCySymRemoveSession retry!\n"); + /* treat this as error, since session should not be active */ + ret = ASYNC_OP_E; + } + else if (status != CPA_STATUS_SUCCESS) { + QLOG("cpaCySymRemoveSession failed! status %d\n", status); + ret = ASYNC_OP_E; + } + } + } + + if (doFree) { + XFREE(ctx->symCtx, dev->heap, DYNAMIC_TYPE_ASYNC_NUMA64); + ctx->symCtx = NULL; + ctx->symCtxSrc = NULL; + ctx->symCtxSize = 0; + } + + return ret; +} + +#endif /* QAT_ENABLE_CRYPTO */ + + +/* -------------------------------------------------------------------------- */ +/* AES/DES Algo */ +/* -------------------------------------------------------------------------- */ + +#ifdef QAT_ENABLE_CRYPTO + +static void IntelQaSymCipherFree(IntelQaDev* dev) +{ + IntelQaSymCtx* ctx = &dev->op.cipher.ctx; + CpaCySymOpData* opData = &ctx->opData; + CpaBufferList* pDstBuffer = &dev->op.cipher.bufferList; + + if (opData) { + if (opData->pAdditionalAuthData) { + XFREE(opData->pAdditionalAuthData, dev->heap, + DYNAMIC_TYPE_ASYNC_NUMA); + opData->pAdditionalAuthData = NULL; + } + if (opData->pIv) { + XFREE(opData->pIv, dev->heap, DYNAMIC_TYPE_ASYNC_NUMA); + opData->pIv = NULL; + } + XMEMSET(opData, 0, sizeof(CpaCySymOpData)); + } + if (pDstBuffer) { + if (pDstBuffer->pBuffers) { + if (pDstBuffer->pBuffers->pData) { + XFREE(pDstBuffer->pBuffers->pData, dev->heap, + DYNAMIC_TYPE_ASYNC_NUMA); + pDstBuffer->pBuffers->pData = NULL; + } + XMEMSET(pDstBuffer->pBuffers, 0, sizeof(CpaFlatBuffer)); + } + if (pDstBuffer->pPrivateMetaData) { + XFREE(pDstBuffer->pPrivateMetaData, dev->heap, + DYNAMIC_TYPE_ASYNC_NUMA); + pDstBuffer->pPrivateMetaData = NULL; + } + XMEMSET(pDstBuffer, 0, sizeof(CpaBufferList)); + } + + /* close and free sym context */ + IntelQaSymClose(dev, 1); + + /* clear temp pointers */ + dev->out = NULL; + dev->outLen = 0; +#ifndef NO_AES + if (dev->op.cipher.authTag != NULL) { + XMEMSET(dev->op.cipher.authTag, 0, dev->op.cipher.authTagSz); + XFREE(dev->op.cipher.authTag, dev->heap, DYNAMIC_TYPE_ASYNC_NUMA); + dev->op.cipher.authTag = NULL; + } + dev->op.cipher.authTagSz = 0; +#endif +} + +static int IntelQaSymCipher(IntelQaDev* dev, byte* out, const byte* in, + word32 inOutSz, const byte* key, word32 keySz, const byte* iv, word32 ivSz, + CpaCySymOp symOperation, CpaCySymCipherAlgorithm cipherAlgorithm, + CpaCySymCipherDirection cipherDirection, + + /* for auth ciphers (CCM or GCM) */ + CpaCySymHashAlgorithm hashAlgorithm, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret; + CpaStatus status = CPA_STATUS_SUCCESS; + CpaCySymOpData* opData = NULL; + CpaCySymSessionSetupData setup; + const Cpa32U numBuffers = 1; + CpaBufferList* bufferList = NULL; + CpaFlatBuffer* flatBuffer = NULL; + Cpa8U* ivBuf = NULL; + Cpa8U* dataBuf = NULL; + Cpa32U dataLen = inOutSz; + Cpa8U* metaBuf = NULL; + Cpa32U metaSize = 0; + Cpa8U* authInBuf = NULL; + Cpa32U authInSzAligned = authInSz; + Cpa8U* authTagBuf = NULL; + IntelQaSymCtx* ctx; + CpaBoolean verifyResult = CPA_FALSE; + + QLOG("IntelQaSymCipher: dev %p, out %p, in %p, inOutSz %d, op %d, " + "algo %d, dir %d, hash %d\n", + dev, out, in, inOutSz, symOperation, cipherAlgorithm, + cipherDirection, hashAlgorithm); + + /* check args */ + if (out == NULL || in == NULL || inOutSz == 0 || + key == NULL || keySz == 0 || iv == NULL || ivSz == 0) { + return BAD_FUNC_ARG; + } + if (hashAlgorithm != CPA_CY_SYM_HASH_NONE && + (authTag == NULL || authTagSz == 0)) { + return BAD_FUNC_ARG; + } + + /* get meta size */ + status = cpaCyBufferListGetMetaSize(dev->handle, numBuffers, &metaSize); + if (status != CPA_STATUS_SUCCESS && metaSize <= 0) { + ret = BUFFER_E; goto exit; + } + + /* if authtag provided then it will be appended to end of input */ + if (authTag && authTagSz > 0) { + dataLen += authTagSz; + } + + /* allocate buffers */ + ctx = &dev->op.cipher.ctx; + opData = &ctx->opData; + bufferList = &dev->op.cipher.bufferList; + flatBuffer = &dev->op.cipher.flatBuffer; + metaBuf = XMALLOC(metaSize, dev->heap, DYNAMIC_TYPE_ASYNC_NUMA); + dataBuf = XMALLOC(dataLen, dev->heap, DYNAMIC_TYPE_ASYNC_NUMA); + XMEMCPY(dataBuf, in, inOutSz); + ivBuf = XMALLOC(AES_BLOCK_SIZE, dev->heap, DYNAMIC_TYPE_ASYNC_NUMA); + XMEMCPY(ivBuf, iv, ivSz); + authTagBuf = XMALLOC(authTagSz, dev->heap, DYNAMIC_TYPE_ASYNC_NUMA); + + /* check allocations */ + if (ivBuf == NULL || metaBuf == NULL || dataBuf == NULL || + authTagBuf == NULL) { + ret = MEMORY_E; goto exit; + } + + /* AAD */ + if (authIn && authInSz > 0) { + /* make sure AAD is block aligned */ + if (authInSzAligned % AES_BLOCK_SIZE) { + authInSzAligned += AES_BLOCK_SIZE - + (authInSzAligned % AES_BLOCK_SIZE); + } + + authInBuf = XMALLOC(authInSzAligned, dev->heap, + DYNAMIC_TYPE_ASYNC_NUMA); + XMEMCPY(authInBuf, authIn, authInSz); + if (authInBuf == NULL) { + ret = MEMORY_E; goto exit; + } + /* clear remainder */ + XMEMSET(authInBuf + authInSz, 0, authInSzAligned - authInSz); + } + + /* init buffers */ + XMEMSET(&setup, 0, sizeof(CpaCySymSessionSetupData)); + XMEMSET(opData, 0, sizeof(CpaCySymOpData)); + XMEMSET(bufferList, 0, sizeof(CpaBufferList)); + XMEMSET(flatBuffer, 0, sizeof(CpaFlatBuffer)); + XMEMSET(metaBuf, 0, metaSize); + + bufferList->pBuffers = flatBuffer; + bufferList->numBuffers = numBuffers; + bufferList->pPrivateMetaData = metaBuf; + flatBuffer->dataLenInBytes = dataLen; + flatBuffer->pData = dataBuf; + + /* setup */ + setup.sessionPriority = CPA_CY_PRIORITY_NORMAL; + setup.symOperation = symOperation; + setup.cipherSetupData.cipherAlgorithm = cipherAlgorithm; + setup.cipherSetupData.cipherKeyLenInBytes = keySz; + setup.cipherSetupData.pCipherKey = (byte*)key; + setup.cipherSetupData.cipherDirection = cipherDirection; + + /* setup auth ciphers */ + if (hashAlgorithm != CPA_CY_SYM_HASH_NONE) { + setup.algChainOrder = + (cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT) ? + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH : + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; + + setup.hashSetupData.hashAlgorithm = hashAlgorithm; + setup.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; + setup.hashSetupData.digestResultLenInBytes = authTagSz; + setup.hashSetupData.authModeSetupData.aadLenInBytes = authInSz; + + if (cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT) + setup.digestIsAppended = CPA_TRUE; + else + setup.digestIsAppended = CPA_FALSE; + } + + /* open session */ + ret = IntelQaSymOpen(dev, &setup, NULL); + if (ret != 0) { + goto exit; + } + + /* operation data */ + opData->sessionCtx = ctx->symCtx; + opData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; + opData->pIv = ivBuf; + opData->ivLenInBytes = ivSz; + opData->cryptoStartSrcOffsetInBytes = 0; + opData->messageLenToCipherInBytes = inOutSz; + if (authIn && authInSz > 0) { + opData->pAdditionalAuthData = authInBuf; + } + if (cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT) { + if (authTag && authTagSz > 0) { + /* append digest to end of data buffer */ + XMEMCPY(flatBuffer->pData + inOutSz, authTag, authTagSz); + } + } + else { + if (authTag && authTagSz > 0) { + XMEMCPY(authTagBuf, authTag, authTagSz); + } + } + + /* store info needed for output */ + dev->out = out; + dev->outLen = inOutSz; + if (cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT) { + dev->op.cipher.authTag = authTagBuf; + dev->op.cipher.authTagSz = authTagSz; + opData->pDigestResult = authTagBuf; + } + else { + dev->op.cipher.authTag = NULL; + dev->op.cipher.authTagSz = 0; + } + IntelQaOpInit(dev, IntelQaSymCipherFree); + + /* perform symmetric AES operation async */ + /* use same buffer list for in-place operation */ + status = cpaCySymPerformOp(dev->handle, dev, opData, + bufferList, bufferList, &verifyResult); + + if (symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING && + cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM && + cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT && + hashAlgorithm == CPA_CY_SYM_HASH_AES_GCM) { + if (verifyResult == CPA_FALSE) { + ret = AES_GCM_AUTH_E; + } + } +exit: + + if (ret != 0) { + QLOG("cpaCySymPerformOp Cipher failed! dev %p, status %d, ret %d\n", + dev, status, ret); + } + + /* Capture the inline decrypt into the output. */ + XMEMCPY(out, dataBuf, inOutSz); + if (cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT) { + if (authTag != NULL && authTagSz > 0) { + XMEMCPY(authTag, authTagBuf, authTagSz); + } + } + + /* handle cleanup */ + IntelQaSymCipherFree(dev); + + return ret; +} + +#ifdef HAVE_AES_CBC +int IntelQaSymAesCbcEncrypt(IntelQaDev* dev, + byte* out, const byte* in, word32 sz, + const byte* key, word32 keySz, + const byte* iv, word32 ivSz) +{ + int ret = IntelQaSymCipher(dev, out, in, sz, + key, keySz, iv, ivSz, + CPA_CY_SYM_OP_CIPHER, CPA_CY_SYM_CIPHER_AES_CBC, + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT, + CPA_CY_SYM_HASH_NONE, NULL, 0, NULL, 0); + + XMEMCPY((byte*)iv, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + return ret; +} + +#ifdef HAVE_AES_DECRYPT +int IntelQaSymAesCbcDecrypt(IntelQaDev* dev, + byte* out, const byte* in, word32 sz, + const byte* key, word32 keySz, + const byte* iv, word32 ivSz) +{ + byte nextIv[AES_BLOCK_SIZE]; + int ret; + + XMEMCPY(nextIv, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + ret = IntelQaSymCipher(dev, out, in, sz, + key, keySz, iv, ivSz, + CPA_CY_SYM_OP_CIPHER, CPA_CY_SYM_CIPHER_AES_CBC, + CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT, + CPA_CY_SYM_HASH_NONE, NULL, 0, NULL, 0); + + XMEMCPY((byte*)iv, nextIv, AES_BLOCK_SIZE); + return ret; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_CBC */ + + +#ifdef HAVE_AESGCM +int IntelQaSymAesGcmEncrypt(IntelQaDev* dev, + byte* out, const byte* in, word32 sz, + const byte* key, word32 keySz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + return IntelQaSymCipher(dev, out, in, sz, + key, keySz, iv, ivSz, + CPA_CY_SYM_OP_ALGORITHM_CHAINING, CPA_CY_SYM_CIPHER_AES_GCM, + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT, + CPA_CY_SYM_HASH_AES_GCM, authTag, authTagSz, authIn, authInSz); +} +#ifdef HAVE_AES_DECRYPT +int IntelQaSymAesGcmDecrypt(IntelQaDev* dev, + byte* out, const byte* in, word32 sz, + const byte* key, word32 keySz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + return IntelQaSymCipher(dev, out, in, sz, + key, keySz, iv, ivSz, + CPA_CY_SYM_OP_ALGORITHM_CHAINING, CPA_CY_SYM_CIPHER_AES_GCM, + CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT, + CPA_CY_SYM_HASH_AES_GCM, (byte*)authTag, authTagSz, authIn, authInSz); +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AESGCM */ + +#ifndef NO_DES3 +int IntelQaSymDes3CbcEncrypt(IntelQaDev* dev, + byte* out, const byte* in, word32 sz, + const byte* key, word32 keySz, + const byte* iv, word32 ivSz) +{ + return IntelQaSymCipher(dev, out, in, sz, + key, keySz, iv, ivSz, + CPA_CY_SYM_OP_CIPHER, CPA_CY_SYM_CIPHER_3DES_CBC, + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT, + CPA_CY_SYM_HASH_NONE, NULL, 0, NULL, 0); +} + +int IntelQaSymDes3CbcDecrypt(IntelQaDev* dev, + byte* out, const byte* in, word32 sz, + const byte* key, word32 keySz, + const byte* iv, word32 ivSz) +{ + return IntelQaSymCipher(dev, out, in, sz, + key, keySz, iv, ivSz, + CPA_CY_SYM_OP_CIPHER, CPA_CY_SYM_CIPHER_3DES_CBC, + CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT, + CPA_CY_SYM_HASH_NONE, NULL, 0, NULL, 0); +} +#endif /* !NO_DES3 */ + +#endif /* QAT_ENABLE_CRYPTO */ + + +#ifdef WOLF_CRYPTO_CB + +int IntelQaSymSync_CryptoDevCb(int devId, struct wc_CryptoInfo* info, void* ctx) +{ + int rc = NOT_COMPILED_IN; /* return this to bypass HW and use SW */ + IntelQaDev* dev; + + if (info == NULL || ctx == NULL) + return BAD_FUNC_ARG; + + (void)devId; + dev = (IntelQaDev*)ctx; + + #ifdef QAT_ENABLE_CRYPTO + if (info->algo_type == WC_ALGO_TYPE_CIPHER) { + QLOG("CryptoDevCb Cipher: Type %d\n", info->cipher.type); + + #ifndef NO_AES + if (info->cipher.type == WC_CIPHER_AES_CBC) { + Aes* aes = info->cipher.aescbc.aes; + if (aes == NULL) + return BAD_FUNC_ARG; + + if (info->cipher.enc) { + rc = IntelQaSymAesCbcEncrypt(dev, + info->cipher.aescbc.out, + info->cipher.aescbc.in, + info->cipher.aescbc.sz, + (byte*)aes->devKey, aes->keylen, + (byte*)aes->reg, AES_BLOCK_SIZE); + } + else { + rc = IntelQaSymAesCbcDecrypt(dev, + info->cipher.aescbc.out, + info->cipher.aescbc.in, + info->cipher.aescbc.sz, + (byte*)aes->devKey, aes->keylen, + (byte*)aes->reg, AES_BLOCK_SIZE); + } + } + #endif /* !NO_AES */ + + #ifdef HAVE_AESGCM + if (info->cipher.type == WC_CIPHER_AES_GCM) { + if (info->cipher.enc) { + Aes* aes = info->cipher.aesgcm_enc.aes; + if (aes == NULL) + return BAD_FUNC_ARG; + + rc = IntelQaSymAesGcmEncrypt(dev, + info->cipher.aesgcm_enc.out, + info->cipher.aesgcm_enc.in, + info->cipher.aesgcm_enc.sz, + (const byte*)aes->devKey, aes->keylen, + info->cipher.aesgcm_enc.iv, + info->cipher.aesgcm_enc.ivSz, + info->cipher.aesgcm_enc.authTag, + info->cipher.aesgcm_enc.authTagSz, + info->cipher.aesgcm_enc.authIn, + info->cipher.aesgcm_enc.authInSz); + } + else { + Aes* aes = info->cipher.aesgcm_dec.aes; + if (aes == NULL) + return BAD_FUNC_ARG; + + rc = IntelQaSymAesGcmDecrypt(dev, + info->cipher.aesgcm_dec.out, + info->cipher.aesgcm_dec.in, + info->cipher.aesgcm_dec.sz, + (const byte*)aes->devKey, aes->keylen, + info->cipher.aesgcm_dec.iv, + info->cipher.aesgcm_dec.ivSz, + info->cipher.aesgcm_dec.authTag, + info->cipher.aesgcm_dec.authTagSz, + info->cipher.aesgcm_dec.authIn, + info->cipher.aesgcm_dec.authInSz); + } + } + #endif /* HAVE_AESGCM */ + + #ifndef NO_DES3 + if (info->cipher.type == WC_CIPHER_DES3) { + Des3* des = info->cipher.des3.des; + if (des == NULL) + return BAD_FUNC_ARG; + + if (info->cipher.enc) { + rc = IntelQaSymDes3CbcEncrypt(dev, + info->cipher.des3.out, + info->cipher.des3.in, + info->cipher.des3.sz, + (byte*)des->devKey, DES3_KEYLEN, + (byte*)des->reg, DES_BLOCK_SIZE); + } + else { + rc = IntelQaSymDes3CbcDecrypt(dev, + info->cipher.des3.out, + info->cipher.des3.in, + info->cipher.des3.sz, + (byte*)des->devKey, DES3_KEYLEN, + (byte*)des->reg, DES_BLOCK_SIZE); + } + } + #endif /* !NO_DES3 */ + } + #endif /* QAT_ENABLE_CRYPTO */ + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* Public API */ +/* -------------------------------------------------------------------------- */ + +int wc_CryptoCb_InitIntelQa(void) +{ + int devId, rc; + + devId = IntelQaInit(NULL); + if (devId < 0) { + QLOG("Couldn't init the Intel QA\n"); + devId = INVALID_DEVID; + } + else { + rc = IntelQaOpen(&qaDev, devId); + if (rc != 0) { + QLOG("Couldn't open the device\n"); + IntelQaDeInit(devId); + devId = INVALID_DEVID; + } + else { + rc = wc_CryptoCb_RegisterDevice(devId, + IntelQaSymSync_CryptoDevCb, &qaDev); + if (rc != 0) { + QLOG("Couldn't register the device\n"); + IntelQaClose(&qaDev); + IntelQaDeInit(devId); + devId = INVALID_DEVID; + } + } + } + + return devId; +} + + +void wc_CryptoCb_CleanupIntelQa(int* id) +{ + if (INVALID_DEVID != *id) { + wc_CryptoCb_UnRegisterDevice(*id); + IntelQaClose(&qaDev); + IntelQaDeInit(*id); + *id = INVALID_DEVID; + } +} + +#endif /* WOLF_CRYPTO_CB */ + + +/* -------------------------------------------------------------------------- */ +/* Memory allocator and deallocator */ +/* -------------------------------------------------------------------------- */ +#include +#include +#include + +/* use thread local for QAE variables (removing mutex requirement) */ +#ifdef USE_QAE_THREAD_LS + #include /* for threadId tracking */ + #define QAE_THREAD_LS THREAD_LS_T +#else + #define QAE_THREAD_LS +#endif + +/* these are used to align memory to a byte boundary */ +#define ALIGNMENT_BASE (16ul) +#define ALIGNMENT_HW (64ul) +#define WOLF_MAGIC_NUM 0xA576F6C6641736EBUL /* (0xA)WolfAsyn(0xB) */ +#define WOLF_HEADER_ALIGN ALIGNMENT_BASE + +#define QAE_NOT_NUMA_PAGE 0xFFFF +typedef struct qaeMemHeader { +#ifdef WOLFSSL_TRACK_MEMORY + struct qaeMemHeader* next; + struct qaeMemHeader* prev; + #ifdef WOLFSSL_DEBUG_MEMORY + const char* func; + unsigned int line; + #endif +#endif + uint64_t magic; + void* heap; +#ifdef USE_QAE_THREAD_LS + pthread_t threadId; +#endif + size_t size; + word16 count; + word16 isNuma:1; + word16 reservedBits:15; /* use for future bits */ + word16 type; + word16 numa_page_offset; /* use QAE_NOT_NUMA_PAGE if not NUMA */ +} ALIGN16 qaeMemHeader; + +#ifdef WOLFSSL_TRACK_MEMORY + typedef struct qaeMemStats { + long totalAllocs; /* number of allocations */ + long totalDeallocs; /* number of deallocations */ + long totalBytes; /* total number of bytes allocated */ + long peakBytes; /* concurrent max bytes */ + long currentBytes; /* total current bytes in use */ + } qaeMemStats; + + /* track allocations and report at end */ + typedef struct qaeMemList { + qaeMemHeader* head; + qaeMemHeader* tail; + uint32_t count; + } qaeMemList; +#endif /* WOLFSSL_TRACK_MEMORY */ + + +/* local variables */ +#ifndef USE_QAE_THREAD_LS + static pthread_mutex_t g_memLock = PTHREAD_MUTEX_INITIALIZER; +#endif + + +#ifdef WOLFSSL_TRACK_MEMORY + static qaeMemStats g_memStats; + static qaeMemList g_memList; + static pthread_mutex_t g_memStatLock = PTHREAD_MUTEX_INITIALIZER; +#endif + +static WC_INLINE int qaeMemTypeIsNuma(int type) +{ + int isNuma = 0; + + switch (type) { + case DYNAMIC_TYPE_ASYNC_NUMA: + case DYNAMIC_TYPE_ASYNC_NUMA64: + case DYNAMIC_TYPE_WOLF_BIGINT: + case DYNAMIC_TYPE_PRIVATE_KEY: + case DYNAMIC_TYPE_PUBLIC_KEY: + case DYNAMIC_TYPE_AES_BUFFER: + case DYNAMIC_TYPE_RSA_BUFFER: + case DYNAMIC_TYPE_ECC_BUFFER: + case DYNAMIC_TYPE_SIGNATURE: + case DYNAMIC_TYPE_DIGEST: + case DYNAMIC_TYPE_SECRET: + case DYNAMIC_TYPE_SEED: + case DYNAMIC_TYPE_SALT: + { + isNuma = 1; + break; + } + case DYNAMIC_TYPE_OUT_BUFFER: + case DYNAMIC_TYPE_IN_BUFFER: + { + #if !defined(WC_ASYNC_NO_CRYPT) && !defined(WC_ASYNC_NO_HASH) + isNuma = 1; + #else + isNuma = 0; + #endif + break; + } + default: + isNuma = 0; + break; + } + return isNuma; +} + + +static void _qaeMemFree(void *ptr, void* heap, int type +#ifdef WOLFSSL_DEBUG_MEMORY + , const char* func, unsigned int line +#endif +) +{ + qaeMemHeader* header = NULL; + size_t size; + void* origPtr = ptr; + + if (ptr == NULL) + return; + + /* adjust for header and align */ + ptr = (byte*)(((size_t)ptr - ((size_t)ptr % WOLF_HEADER_ALIGN)) - + sizeof(qaeMemHeader)); + header = (qaeMemHeader*)ptr; + + /* check for header magic */ + if (header->magic != WOLF_MAGIC_NUM) { + printf("Free: Header magic not found! %p\n", ptr); + return; + } + + /* cache values for later */ + size = header->size; + +#ifdef WOLFSSL_DEBUG_MEMORY +#ifdef WOLFSSL_DEBUG_MEMORY_PRINT + printf("Free: %p (%u) at %s:%u, heap %p, type %d, count %d\n", + origPtr, (unsigned int)size, func, line, heap, type, header->count); +#else + (void)func; + (void)line; +#endif +#endif + (void)type; + + /* adjust free count */ + header->count--; + + /* check header count */ + if (header->count > 0) { + /* go ahead and return if still in use */ + return; + } + +#ifdef WOLFSSL_TRACK_MEMORY + if (pthread_mutex_lock(&g_memStatLock) == 0) { + g_memStats.currentBytes -= size; + g_memStats.totalDeallocs++; + + if (header == g_memList.head && header == g_memList.tail) { + g_memList.head = NULL; + g_memList.tail = NULL; + } + else if (header == g_memList.head) { + g_memList.head = header->next; + g_memList.head->prev = NULL; + } + else if (header == g_memList.tail) { + g_memList.tail = header->prev; + g_memList.tail->next = NULL; + } + else { + qaeMemHeader* next = header->next; + qaeMemHeader* prev = header->prev; + if (next) + next->prev = prev; + if (prev) + prev->next = next; + } + g_memList.count--; + + pthread_mutex_unlock(&g_memStatLock); + } +#endif + + (void)heap; + (void)size; + (void)origPtr; + +#ifdef WOLFSSL_DEBUG_MEMORY + /* make sure magic is gone */ + header->magic = 0; +#endif + + /* free type */ + if (header->isNuma && header->numa_page_offset != QAE_NOT_NUMA_PAGE) { + qaeMemFreeNUMA(&ptr); + } + else { + free(ptr); + } +} + + +static void* _qaeMemAlloc(size_t size, void* heap, int type +#ifdef WOLFSSL_DEBUG_MEMORY + , const char* func, unsigned int line +#endif +) +{ + void* ptr = NULL; + qaeMemHeader* header = NULL; + int isNuma; + int alignment = ALIGNMENT_BASE; + word16 page_offset = QAE_NOT_NUMA_PAGE; + + /* make sure all allocations are aligned */ + if ((size % WOLF_HEADER_ALIGN) != 0) { + size += (WOLF_HEADER_ALIGN - (size % WOLF_HEADER_ALIGN)); + } + + isNuma = qaeMemTypeIsNuma(type); + if (type == DYNAMIC_TYPE_ASYNC_NUMA64) + alignment = ALIGNMENT_HW; + + /* allocate type */ + if (isNuma) { + /* Node is typically 0 */ + page_offset = 0; + ptr = qaeMemAllocNUMA((Cpa32U)(size + sizeof(qaeMemHeader)), 0, + alignment); + } + else { + isNuma = 0; + ptr = malloc(size + sizeof(qaeMemHeader)); + } + + /* add header */ + if (ptr) { + header = (qaeMemHeader*)ptr; + ptr = (byte*)ptr + sizeof(qaeMemHeader); + header->magic = WOLF_MAGIC_NUM; + header->heap = heap; + header->size = size; + header->type = type; + header->count = 1; + header->isNuma = isNuma; + header->numa_page_offset = page_offset; + #ifdef USE_QAE_THREAD_LS + header->threadId = pthread_self(); + #endif + + #ifdef WOLFSSL_TRACK_MEMORY + if (pthread_mutex_lock(&g_memStatLock) == 0) { + g_memStats.totalAllocs++; + g_memStats.totalBytes += size; + g_memStats.currentBytes += size; + if (g_memStats.currentBytes > g_memStats.peakBytes) + g_memStats.peakBytes = g_memStats.currentBytes; + + #ifdef WOLFSSL_DEBUG_MEMORY + header->func = func; + header->line = line; + #endif + + /* Setup event */ + header->next = NULL; + if (g_memList.tail == NULL) { + g_memList.head = header; + } + else { + g_memList.tail->next = header; + header->prev = g_memList.tail; + } + g_memList.tail = header; /* add to the end either way */ + g_memList.count++; + + pthread_mutex_unlock(&g_memStatLock); + } + #endif + } + +#ifdef WOLFSSL_DEBUG_MEMORY +#ifdef WOLFSSL_DEBUG_MEMORY_PRINT + printf("Alloc: %p (%u) at %s:%u, heap %p, type %d\n", + ptr, (unsigned int)size, func, line, heap, type); +#else + (void)func; + (void)line; +#endif +#endif + + (void)heap; + + return ptr; +} + +/* Public Functions */ +void* wc_CryptoCb_IntelQaMalloc(size_t size, void* heap, int type +#ifdef WOLFSSL_DEBUG_MEMORY + , const char* func, unsigned int line +#endif +) +{ + void* ptr; + +#ifndef USE_QAE_THREAD_LS + int ret = pthread_mutex_lock(&g_memLock); + if (ret != 0) { + printf("Alloc: Error(%d) on mutex lock\n", ret); + return NULL; + } +#endif + + ptr = _qaeMemAlloc(size, heap, type + #ifdef WOLFSSL_DEBUG_MEMORY + , func, line + #endif + ); + +#ifndef USE_QAE_THREAD_LS + pthread_mutex_unlock(&g_memLock); +#endif + + return ptr; +} + +void wc_CryptoCb_IntelQaFree(void *ptr, void* heap, int type +#ifdef WOLFSSL_DEBUG_MEMORY + , const char* func, unsigned int line +#endif +) +{ +#ifndef USE_QAE_THREAD_LS + int ret = pthread_mutex_lock(&g_memLock); + if (ret != 0) { + printf("Free: Error(%d) on mutex lock\n", ret); + return; + } +#endif + + _qaeMemFree(ptr, heap, type + #ifdef WOLFSSL_DEBUG_MEMORY + , func, line + #endif + ); + +#ifndef USE_QAE_THREAD_LS + pthread_mutex_unlock(&g_memLock); +#endif +} + +void* wc_CryptoCb_IntelQaRealloc(void *ptr, size_t size, void* heap, int type +#ifdef WOLFSSL_DEBUG_MEMORY + , const char* func, unsigned int line +#endif +) +{ + void* newPtr = NULL; + void* origPtr = ptr; + qaeMemHeader* header = NULL; + byte allocNew = 1; + int newIsNuma = -1, ptrIsNuma = -1; + size_t copySize = 0; + +#ifndef USE_QAE_THREAD_LS + int ret = pthread_mutex_lock(&g_memLock); + if (ret != 0) { + printf("Realloc: Error(%d) on mutex lock\n", ret); + return NULL; + } +#endif + + (void)heap; + + if (ptr) { + /* get header pointer and align */ + header = (qaeMemHeader*)(((size_t)ptr - + ((size_t)ptr % WOLF_HEADER_ALIGN)) - sizeof(qaeMemHeader)); + if (header->magic == WOLF_MAGIC_NUM) { + newIsNuma = qaeMemTypeIsNuma(type); + ptrIsNuma = (header->numa_page_offset != QAE_NOT_NUMA_PAGE) ? 1 : 0; + + /* for non-NUMA, treat as normal REALLOC */ + if (newIsNuma == 0 && ptrIsNuma == 0) { + allocNew = 1; + } + /* if matching NUMA type and size fits, use existing */ + else if (newIsNuma == ptrIsNuma && header->size >= size) { + + #ifdef USE_QAE_THREAD_LS + if (header->threadId != pthread_self()) { + allocNew = 1; + #if 0 + printf("Realloc %p from different thread! orig %lx this %lx\n", + origPtr, header->threadId, pthread_self()); + #endif + } + else + #endif + { + /* use existing pointer and increment counter */ + header->count++; + newPtr = origPtr; + allocNew = 0; + } + } + + copySize = header->size; + } + else { + copySize = size; + } + } + + if (allocNew) { + newPtr = _qaeMemAlloc(size, heap, type + #ifdef WOLFSSL_DEBUG_MEMORY + , func, line + #endif + ); + if (newPtr && ptr) { + /* only copy min of new and old size to new pointer */ + if (copySize > size) + copySize = size; + XMEMCPY(newPtr, ptr, copySize); + + if (newIsNuma == 0 && ptrIsNuma == 0) { + /* for non-NUMA, treat as normal REALLOC and free old pointer */ + _qaeMemFree(ptr, heap, type + #ifdef WOLFSSL_DEBUG_MEMORY + , func, line + #endif + ); + } + } + } + +#ifndef USE_QAE_THREAD_LS + pthread_mutex_unlock(&g_memLock); +#endif + +#ifdef WOLFSSL_DEBUG_MEMORY +#ifdef WOLFSSL_DEBUG_MEMORY_PRINT + if (allocNew) { + printf("Realloc: New %p -> %p (%u) at %s:%u, heap %p, type %d\n", + origPtr, newPtr, (unsigned int)size, func, line, heap, type); + } + else { + printf("Realloc: Reuse %p (%u) at %s:%u, heap %p, type %d, count %d\n", + origPtr, (unsigned int)size, func, line, header->heap, header->type, header->count); + } +#else + (void)func; + (void)line; +#endif +#endif + + return newPtr; +} + + +#ifdef WOLFSSL_TRACK_MEMORY +int InitMemoryTracker(void) +{ + if (pthread_mutex_lock(&g_memStatLock) == 0) { + g_memStats.totalAllocs = 0; + g_memStats.totalDeallocs= 0; + g_memStats.totalBytes = 0; + g_memStats.peakBytes = 0; + g_memStats.currentBytes = 0; + + XMEMSET(&g_memList, 0, sizeof(g_memList)); + + pthread_mutex_unlock(&g_memStatLock); + } + + return 0; +} + +void ShowMemoryTracker(void) +{ + if (pthread_mutex_lock(&g_memStatLock) == 0) { + printf("total Allocs = %9ld\n", g_memStats.totalAllocs); + printf("total Deallocs = %9ld\n", g_memStats.totalDeallocs); + printf("total Bytes = %9ld\n", g_memStats.totalBytes); + printf("peak Bytes = %9ld\n", g_memStats.peakBytes); + printf("current Bytes = %9ld\n", g_memStats.currentBytes); + + if (g_memList.count > 0) { + + /* print list of allocations */ + qaeMemHeader* header; + for (header = g_memList.head; header != NULL; header = header->next) { + printf("Leak: Ptr %p, Size %u, Type %d, Heap %p" + #ifdef WOLFSSL_DEBUG_MEMORY + ", Func %s, Line %d" + #endif + "\n", + (byte*)header + sizeof(qaeMemHeader), (unsigned int)header->size, + header->type, header->heap + #ifdef WOLFSSL_DEBUG_MEMORY + , header->func, header->line + #endif + ); + } + } + + pthread_mutex_unlock(&g_memStatLock); + + /* cleanup lock */ + pthread_mutex_destroy(&g_memStatLock); + } +} +#endif /* WOLFSSL_TRACK_MEMORY */ + +#ifdef QAT_DEMO_MAIN + +/* AES GCM */ +static const byte aesgcm_k[] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, + 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22 +}; + +static const byte aesgcm_iv[] = { + 0xca, 0xfe, 0xca, 0xfe, 0xca, 0xfe, 0xca, 0xfe, + 0xca, 0xfe, 0xca, 0xfe +}; + +static const byte aesgcm_a[] = { + 0xde, 0xad, 0xde, 0xad, 0xde, 0xad, 0xde, 0xad, + 0xde, 0xad, 0xde, 0xad, 0xde, 0xad, 0xde, 0xad, + 0xde, 0xad, 0xde, 0xad +}; + +static const byte aesgcm_p[] = { + 0x79, 0x84, 0x86, 0x44, 0x68, 0x45, 0x15, 0x61, + 0x86, 0x54, 0x66, 0x56, 0x54, 0x54, 0x31, 0x54, + 0x64, 0x64, 0x68, 0x45, 0x15, 0x15, 0x61, 0x61, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x56, 0x14, 0x11, + 0x72, 0x13, 0x51, 0x82, 0x84, 0x56, 0x74, 0x53, + 0x45, 0x34, 0x65, 0x15, 0x46, 0x14, 0x67, 0x55, + 0x16, 0x14, 0x67, 0x54, 0x65, 0x47, 0x14, 0x67, + 0x46, 0x74, 0x65, 0x46 +}; + +static const byte aesgcm_c[] = { + 0x59, 0x85, 0x02, 0x97, 0xE0, 0x4D, 0xFC, 0x5C, + 0x03, 0xCC, 0x83, 0x64, 0xCE, 0x28, 0x0B, 0x95, + 0x78, 0xEC, 0x93, 0x40, 0xA1, 0x8D, 0x21, 0xC5, + 0x48, 0x6A, 0x39, 0xBA, 0x4F, 0x4B, 0x8C, 0x95, + 0x6F, 0x8C, 0xF6, 0x9C, 0xD0, 0xA5, 0x8D, 0x67, + 0xA1, 0x32, 0x11, 0xE7, 0x2E, 0xF6, 0x63, 0xAF, + 0xDE, 0xD4, 0x7D, 0xEC, 0x15, 0x01, 0x58, 0xCB, + 0xE3, 0x7B, 0xC6, 0x94, +}; + +static byte aesgcm_t[] = { + 0x5D, 0x10, 0x3F, 0xC7, 0x22, 0xC7, 0x21, 0x29 +}; + + +/* simple example of using AES-GCM encrypt with Intel QA */ +int main(int argc, char** argv) +{ +#if !defined(NO_AES) && defined(HAVE_AESGCM) + int ret; + IntelQaDev dev; + byte out[256]; + byte tmp[256]; + word32 tmpLen; +#endif + +#ifdef QAT_DEBUG + wolfSSL_Debugging_ON(); +#endif + + IntelQaInit(NULL); + +#ifndef NO_AES +#ifdef HAVE_AESGCM + /* AES Test */ + IntelQaOpen(&dev, 0); + dev.event.ret = WC_PENDING_E; + tmpLen = sizeof(aesgcm_t); + XMEMSET(out, 0, sizeof(out)); + XMEMSET(tmp, 0, sizeof(tmp)); + + ret = IntelQaSymAesGcmEncrypt(&dev, out, aesgcm_p, sizeof(aesgcm_p), + aesgcm_k, sizeof(aesgcm_k), aesgcm_iv, sizeof(aesgcm_iv), + tmp, tmpLen, aesgcm_a, sizeof(aesgcm_a)); + printf("AES GCM Encrypt: Ret=%d, Tag Len=%d\n", ret, tmpLen); + IntelQaClose(&dev); +#endif /* HAVE_AESGCM */ +#endif /* NO_AES */ + + IntelQaDeInit(0); + + return 0; +} + +#endif + +#endif /* HAVE_INTEL_QA_SYNC */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/mynewt/mynewt_port.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/mynewt/mynewt_port.c new file mode 100644 index 000000000..8a4e903fb --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/mynewt/mynewt_port.c @@ -0,0 +1,146 @@ +/* mynewt_port.c + * + * Copyright (C) 2006-2020 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(WOLFSSL_APACHE_MYNEWT) +#ifndef NO_FILESYSTEM +#include "fs/fs.h" +#define FILE struct fs_file + +FILE* mynewt_fopen(const char * restrict path, const char * restrict mode) +{ + FILE *file; + uint8_t access_flags = 0; + const char *p = mode; + while(*p != '\0') { + switch(*p) { + case 'r': + { + access_flags |= FS_ACCESS_READ; + if(*(p+1) == '+') { + access_flags |= FS_ACCESS_WRITE; + } + } + break; + + case 'w': + { + access_flags |= (FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE); + if(*(p+1) == '+') { + access_flags |= FS_ACCESS_READ; + } + } + break; + + case 'a': + { + access_flags |= (FS_ACCESS_WRITE | FS_ACCESS_APPEND); + if(*(p+1) == '+') { + access_flags |= FS_ACCESS_READ; + } + } + break; + } + p++; + } + + /* Open the file for reading. */ + int rc = fs_open(path, access_flags, &file); + if (rc != 0) { + return NULL; + } + return file; +} + +int mynewt_fseek(FILE *stream, long offset, int whence) +{ + uint32_t fs_offset; + + switch(whence) { + case 0: /* SEEK_SET */ + { + fs_offset += offset; + } + break; + + case 1: /* SEEK_CUR */ + { + fs_offset = fs_getpos(stream); + fs_offset += offset; + } + break; + + case 2: /* SEEK_END */ + { + fs_filelen(stream, &fs_offset); + fs_offset += offset; + } + break; + } + + fs_seek(stream, fs_offset); + + return 0; +} + +long mynewt_ftell(FILE *stream) +{ + uint32_t fs_offset; + fs_filelen(stream, &fs_offset); + fs_seek(stream, fs_offset); + return (long)fs_offset; +} + +void mynewt_rewind(FILE *stream) +{ + fs_seek(stream, 0); +} + +size_t mynewt_fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream) +{ + size_t to_read = size * nitems; + uint32_t read_size; + int rc = fs_read(stream, to_read, ptr, &read_size); + if(rc != 0) { + return 0; + } + + return (size_t)read_size; +} + +size_t mynewt_fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream) +{ + size_t to_write = size * nitems; + int rc = fs_write(stream, ptr, to_write); + if(rc != 0) { + return 0; + } + + return to_write; +} + +int mynewt_fclose(FILE *stream) +{ + fs_close(stream); + return 0; +} + +#endif /* NO_FILESYSTEM*/ +#endif /* if defined(WOLFSSL_APACHE_MYNEWT) */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/nrf51.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/nrf51.c new file mode 100644 index 000000000..c7db4b067 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/nrf51.c @@ -0,0 +1,220 @@ +/* nrf51.c + * + * Copyright (C) 2006-2020 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_NRF51 + +#include "bsp.h" +#include "nrf_delay.h" +#include "app_uart.h" +#include "app_error.h" +#include "nrf_drv_rng.h" +#include "nrf_drv_rtc.h" +#include "nrf_drv_clock.h" +#include "nrf_ecb.h" + +#ifdef SOFTDEVICE_PRESENT + #include "softdevice_handler.h" + #include "nrf_soc.h" +#endif /* SOFTDEVICE_PRESENT */ + +/* RTC */ +#ifndef NO_CRYPT_BENCHMARK +static byte mRtcInitDone = 0; +static int mRtcSec = 0; +const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(0); /**< Declaring an instance of nrf_drv_rtc for RTC0. */ +#endif /* !NO_CRYPT_BENCHMARK */ + +/* AES */ +#if !defined(NO_AES) && !defined(SOFTDEVICE_PRESENT) + static byte mAesInitDone = 0; +#endif + +/** @brief Function for getting vector of random numbers. + * + * @param[out] p_buff Pointer to unit8_t buffer for storing the bytes. + * @param[in] length Number of bytes to take from pool and place in p_buff. + * + * @retval 0 = Success, else error + */ +int nrf51_random_generate(byte* output, word32 size) +{ + int remaining = size, length, pos = 0; + uint8_t available; + uint32_t err_code; + + /* Make sure RNG is running */ + err_code = nrf_drv_rng_init(NULL); + if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) { + return -1; + } + + while (remaining > 0) { + err_code = nrf_drv_rng_bytes_available(&available); + if (err_code == NRF_SUCCESS) { + length = (remaining < available) ? remaining : available; + if (length > 0) { + err_code = nrf_drv_rng_rand(&output[pos], length); + remaining -= length; + pos += length; + } + } + + if (err_code != NRF_SUCCESS) { + break; + } + } + + return (err_code == NRF_SUCCESS) ? 0 : -1; +} + +#if !defined(NO_AES) && defined(WOLFSSL_NRF51_AES) + +#ifdef SOFTDEVICE_PRESENT +static const byte* nRF51AesKey = NULL; +#endif +int nrf51_aes_set_key(const byte* key) +{ +#ifdef SOFTDEVICE_PRESENT + nRF51AesKey = key; +#else + if (!mAesInitDone) { + nrf_ecb_init(); + mAesInitDone = 1; + } + nrf_ecb_set_key(key); +#endif + return 0; +} + + +int nrf51_aes_encrypt(const byte* in, const byte* key, word32 rounds, byte* out) +{ + int ret; + uint32_t err_code = 0; +#ifdef SOFTDEVICE_PRESENT + nrf_ecb_hal_data_t ecb_hal_data; +#endif + + /* Set key */ + ret = nrf51_aes_set_key(key); + if (ret != 0) { + return ret; + } + +#ifdef SOFTDEVICE_PRESENT + /* Define ECB record */ + XMEMCPY(ecb_hal_data.key, nRF51AesKey, SOC_ECB_KEY_LENGTH); + XMEMCPY(ecb_hal_data.cleartext, in, SOC_ECB_CLEARTEXT_LENGTH); + XMEMSET(ecb_hal_data.ciphertext, 0, SOC_ECB_CIPHERTEXT_LENGTH); + + /* Perform block encrypt */ + err_code = sd_ecb_block_encrypt(&ecb_hal_data); + if (err_code != NRF_SUCCESS) { + return -1; + } + + /* Grab result */ + XMEMCPY(out, ecb_hal_data.ciphertext, SOC_ECB_CIPHERTEXT_LENGTH); +#else + err_code = nrf_ecb_crypt(out, in); + err_code = err_code ? 0 : -1; +#endif + + return err_code; +} + +#endif /* !NO_AES && WOLFSSL_NRF51_AES */ + + +#ifndef NO_CRYPT_BENCHMARK +static void rtc_handler(nrf_drv_rtc_int_type_t int_type) +{ + if (int_type == NRF_DRV_RTC_INT_COMPARE0) + { + mRtcSec++; + nrf_drv_rtc_counter_clear(&rtc); + nrf_drv_rtc_int_enable(&rtc, RTC_CHANNEL_INT_MASK(0)); + +#ifdef BSP_LED_0 + nrf_gpio_pin_toggle(BSP_LED_0); +#endif + } +} + +static void rtc_config(void) +{ + uint32_t err_code; + + // Start the internal LFCLK XTAL oscillator + err_code = nrf_drv_clock_init(NULL); + APP_ERROR_CHECK(err_code); + + nrf_drv_clock_lfclk_request(); + + // Initialize RTC instance + err_code = nrf_drv_rtc_init(&rtc, NULL, rtc_handler); + APP_ERROR_CHECK(err_code); + + // Enable tick event + nrf_drv_rtc_tick_enable(&rtc, false); + + // Set compare channel to trigger interrupt after 1 seconds + err_code = nrf_drv_rtc_cc_set(&rtc, 0, RTC0_CONFIG_FREQUENCY, true); + APP_ERROR_CHECK(err_code); + + // Power on RTC instance + nrf_drv_rtc_enable(&rtc); +} + +static int rtc_get_ms(void) +{ + /* Prescaler is 12-bit for COUNTER: frequency = (32768/(PRESCALER+1)) */ + int frequency = (32768 / (rtc_prescaler_get(rtc.p_reg) + 1)); + int counter = nrf_drv_rtc_counter_get(&rtc); + + /* Convert with rounding frequency to milliseconds */ + return ((counter * 1000) + (frequency / 2) ) / frequency; +} + +double current_time(int reset) +{ + double time; + + if (!mRtcInitDone) { + rtc_config(); + mRtcInitDone = 1; + } + + time = mRtcSec; + time += (double)rtc_get_ms() / 1000; + + return time; +} +#endif /* !NO_CRYPT_BENCHMARK */ + +#endif /* WOLFSSL_NRF51 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/nxp/ksdk_port.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/nxp/ksdk_port.c new file mode 100644 index 000000000..a5cc737d7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/nxp/ksdk_port.c @@ -0,0 +1,1731 @@ +/* ksdk_port.c + * + * Copyright (C) 2006-2020 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 NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* If FREESCALE_LTC_TFM or FREESCALE_LTC_ECC */ +#if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC) + +#include +#include +#include +#include +#include + +#define ERROR_OUT(res) { ret = (res); goto done; } + + +int ksdk_port_init(void) +{ +#if defined(FREESCALE_LTC_TFM) + LTC_Init(LTC0); +#endif + + return 0; +} + +/* Reverse array in memory (in place) */ +static void ltc_reverse_array(uint8_t *src, size_t src_len) +{ + unsigned int i; + + for (i = 0; i < src_len / 2; i++) { + uint8_t tmp; + + tmp = src[i]; + src[i] = src[src_len - 1 - i]; + src[src_len - 1 - i] = tmp; + } +} + + +#ifndef WOLFSSL_SP_MATH +/* same as mp_to_unsigned_bin() with mp_reverse() skipped */ +static int mp_to_unsigned_lsb_bin(mp_int *a, unsigned char *b) +{ + int res; + mp_int t; + + 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 + } + + return res; +} +#endif + +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); +#ifndef WOLFSSL_SP_MATH + res = mp_to_unsigned_lsb_bin(A, dst); /* result is lsbyte at lowest addr as required by LTC */ +#else + res = mp_to_unsigned_bin(A, dst); + if (res == MP_OKAY) { + ltc_reverse_array(dst, sz); + } +#endif + *psz = sz; + return res; +} + +/* LTC TFM */ +#if defined(FREESCALE_LTC_TFM) + + +/* these function are used by wolfSSL upper layers (like RSA) */ + +/* c = a * b */ +int mp_mul(mp_int *A, mp_int *B, mp_int *C) +{ + int res = MP_OKAY; + int szA, szB; + 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 = 0; + +#ifndef WOLFSSL_SP_MATH + neg = (A->sign == B->sign) ? MP_ZPOS : MP_NEG; +#endif + + /* unsigned multiply */ + 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); + + if (ptrA && ptrB && ptrC) { + uint16_t sizeA, sizeB; + + 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_reverse_array(ptrB, sizeB); + res = mp_read_unsigned_bin(C, ptrB, sizeB); + } + } + +#ifndef WOLFSSL_SP_MATH + /* fix sign */ + C->sign = neg; +#endif + if (ptrA) { + XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrB) { + XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrC) { + XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); + } + } + else { +#ifdef WOLFSSL_SP_MATH + res = sp_mul(A, B, C); +#else + res = wolfcrypt_mp_mul(A, B, C); +#endif + } + return res; +} + +/* c = a mod b, 0 <= c < b */ +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 = 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 neg = 0; + 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); + +#ifndef WOLFSSL_SP_MATH + /* get sign for the result */ + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; +#endif + + /* get remainder of unsigned a divided by unsigned b */ + if (ptrA && ptrB && ptrC) { + uint16_t sizeA, sizeB, 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) { + 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 = MP_MEM; + } + +#ifndef WOLFSSL_SP_MATH + /* fix sign */ + c->sign = neg; +#endif + + if (ptrA) { + XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrB) { + XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrC) { + XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); + } +#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) + } + else { + 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 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 = mp_unsigned_bin_size(a); + szB = mp_unsigned_bin_size(b); + if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) { +#endif + 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); + + if (ptrA && ptrB && ptrC) { + uint16_t sizeA, sizeB, 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) { + 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 = MP_MEM; + } + +#ifndef WOLFSSL_SP_MATH + c->sign = a->sign; +#endif + if (ptrA) { + XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrB) { + XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrC) { + XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); + } +#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) + } + else { + res = wolfcrypt_mp_invmod(a, b, c); + } +#endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; +} + +/* d = a * b (mod c) */ +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 = 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 */ + 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, subtract abs(A) or abs(B) from modulus to get positive integer representation of the + * same number */ + res = mp_init(&t); +#ifndef WOLFSSL_SP_MATH + if (a->sign) { + if (res == MP_OKAY) + res = mp_add(a, c, &t); + if (res == MP_OKAY) + res = mp_copy(&t, a); + } + if (b->sign) { + if (res == MP_OKAY) + res = mp_add(b, c, &t); + if (res == MP_OKAY) + res = mp_copy(&t, b); + } +#endif + + if (res == MP_OKAY && ptrA && ptrB && ptrC && ptrD) { + uint16_t sizeA, sizeB, sizeC, sizeD; + + 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 (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 = MP_VAL; + } + } + 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 = MP_VAL; + } + } + + 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 = MP_VAL; + } + } + + if (res == MP_OKAY) { + ltc_reverse_array(ptrD, sizeD); + res = mp_read_unsigned_bin(d, ptrD, sizeD); + } + } + else { + res = MP_MEM; + } + + if (ptrA) { + XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrB) { + XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrC) { + XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrD) { + XFREE(ptrD, NULL, DYNAMIC_TYPE_BIGINT); + } + #ifndef USE_FAST_MATH + mp_clear(&t); + #endif +#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) + } + else { + res = wolfcrypt_mp_mulmod(a, b, c, d); + } +#endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; +} + +/* Y = G^X mod P */ +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; + mp_int tmp; + + /* if G cannot fit into LTC_PKHA, reduce it */ + szA = mp_unsigned_bin_size(G); + if (szA > LTC_MAX_INT_BYTES) { + res = mp_init(&tmp); + if (res != MP_OKAY) + return res; + if ((res = mp_mod(G, P, &tmp)) != MP_OKAY) { + return res; + } + G = &tmp; + szA = mp_unsigned_bin_size(G); + } + + 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 */ + mp_int t; + + uint16_t sizeG, sizeX, sizeP; + uint8_t *ptrG = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); + uint8_t *ptrX = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); + 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 */ + res = mp_init(&t); +#ifndef WOLFSSL_SP_MATH + if (G->sign) { + if (res == MP_OKAY) + res = mp_add(G, P, &t); + if (res == MP_OKAY) + res = mp_copy(&t, G); + } +#endif + + 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. */ + /* we can take advantage of modular arithmetic rule that: A^B mod C = ( (A mod C)^B ) mod C + and so we do first (A mod N) : LTC does not give size requirement on A versus N, + and then the modular exponentiation. + */ + /* if G >= P then */ + 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 = MP_VAL; + } + } + + 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 = MP_VAL; + } + else { + ltc_reverse_array(ptrP, sizeP); + res = mp_read_unsigned_bin(Y, ptrP, sizeP); + } + } + } + else { + res = MP_MEM; + } + + if (ptrG) { + XFREE(ptrG, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrX) { + XFREE(ptrX, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrP) { + XFREE(ptrP, NULL, DYNAMIC_TYPE_BIGINT); + } + #ifndef USE_FAST_MATH + mp_clear(&t); + #endif +#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) + } + else { + 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 /* FREESCALE_LTC_TFM */ + + +/* ECC */ +#if defined(HAVE_ECC) && defined(FREESCALE_LTC_ECC) + +/* 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 zeros + * so that result array has 32 bytes, same as modulus (sz). + */ +static int ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) +{ + int res; + int szbin; + int offset; + + /* check how many bytes are in the mp_int */ + szbin = mp_unsigned_bin_size(a); + + /* compute offset from dst */ + offset = sz - szbin; + if (offset < 0) + offset = 0; + if (offset > sz) + offset = sz; + + /* add leading zeroes */ + if (offset) + XMEMSET(dst, 0, offset); + + /* convert mp_int to array of bytes */ + res = mp_to_unsigned_bin(a, dst + offset); + + 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 */ +#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) +#define ECC192 +#endif +#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) +#define ECC224 +#endif +#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) +#define ECC256 +#endif +#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) +#define ECC384 +#endif + +/* P-256 */ +#ifdef ECC256 +static const uint8_t ltc_ecc256_modulus[32] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; +static const uint8_t ltc_ecc256_r2modn[32] = { + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00}; +static const uint8_t ltc_ecc256_aCurveParam[32] = { + 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; +static const uint8_t ltc_ecc256_bCurveParam[32] = { + 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B, 0xF6, 0xB0, 0x53, + 0xCC, 0xB0, 0x06, 0x1D, 0x65, 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, + 0xEB, 0xB3, 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A}; +#endif + +#ifdef ECC192 +static const uint8_t ltc_ecc192_modulus[24] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +static const uint8_t ltc_ecc192_r2modn[24] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ltc_ecc192_aCurveParam[24] = { + 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +static const uint8_t ltc_ecc192_bCurveParam[24] = { + 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE, 0x49, 0x30, 0x24, 0x72, + 0xAB, 0xE9, 0xA7, 0x0F, 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64}; +#endif + +#ifdef ECC224 +static const uint8_t ltc_ecc224_modulus[28] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +static const uint8_t ltc_ecc224_r2modn[28] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ltc_ecc224_aCurveParam[28] = { + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +static const uint8_t ltc_ecc224_bCurveParam[28] = { + 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27, 0xBA, 0xD8, + 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50, 0x56, 0x32, 0x41, 0xF5, + 0xAB, 0xB3, 0x04, 0x0C, 0x85, 0x0A, 0x05, 0xB4}; +#endif + +#ifdef ECC384 +static const uint8_t ltc_ecc384_modulus[48] = { + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +static const uint8_t ltc_ecc384_r2modn[48] = { + 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t ltc_ecc384_aCurveParam[48] = { + 0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +static const uint8_t ltc_ecc384_bCurveParam[48] = { + 0xef, 0x2a, 0xec, 0xd3, 0xed, 0xc8, 0x85, 0x2a, 0x9d, 0xd1, 0x2e, 0x8a, + 0x8d, 0x39, 0x56, 0xc6, 0x5a, 0x87, 0x13, 0x50, 0x8f, 0x08, 0x14, 0x03, + 0x12, 0x41, 0x81, 0xfe, 0x6e, 0x9c, 0x1d, 0x18, 0x19, 0x2d, 0xf8, 0xe3, + 0x6b, 0x05, 0x8e, 0x98, 0xe4, 0xe7, 0x3e, 0xe2, 0xa7, 0x2f, 0x31, 0xb3}; +#endif + +static int ltc_get_ecc_specs(const uint8_t **modulus, const uint8_t **r2modn, + const uint8_t **aCurveParam, const uint8_t **bCurveParam, int size) +{ + switch(size) { + case 32: + *modulus = ltc_ecc256_modulus; + *r2modn = ltc_ecc256_r2modn; + *aCurveParam = ltc_ecc256_aCurveParam; + *bCurveParam = ltc_ecc256_bCurveParam; + break; +#ifdef ECC224 + case 28: + *modulus = ltc_ecc224_modulus; + *r2modn = ltc_ecc224_r2modn; + *aCurveParam = ltc_ecc224_aCurveParam; + *bCurveParam = ltc_ecc224_bCurveParam; + break; +#endif +#ifdef ECC192 + case 24: + *modulus = ltc_ecc192_modulus; + *r2modn = ltc_ecc192_r2modn; + *aCurveParam = ltc_ecc192_aCurveParam; + *bCurveParam = ltc_ecc192_bCurveParam; + break; +#endif +#ifdef HAVE_ECC384 + case 48: + *modulus = ltc_ecc384_modulus; + *r2modn = ltc_ecc384_r2modn; + *aCurveParam = ltc_ecc384_aCurveParam; + *bCurveParam = ltc_ecc384_bCurveParam; + break; +#endif + default: + return -1; + } + return 0; +} + +/** + Perform a point multiplication (timing resistant) + k The scalar to multiply by + G The base point + R [out] Destination for kG + modulus The modulus of the field the ECC curve is in + map Boolean whether to map back to affine or not + (1==map, 0 == leave in projective) + return MP_OKAY on success +*/ +int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int *modulus, int map, void* heap) +{ + ltc_pkha_ecc_point_t B; + uint8_t size; + int szModulus; + 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]; + uint8_t kbin[LTC_MAX_INT_BYTES]; + + const uint8_t *modbin; + const uint8_t *aCurveParam; + const uint8_t *bCurveParam; + const uint8_t *r2modn; + + if (k == NULL || G == NULL || R == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + szModulus = mp_unsigned_bin_size(modulus); + szkbin = mp_unsigned_bin_size(k); + + 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 */ + if (0 != ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam, size)) { + return ECC_BAD_ARG_E; + } + + B.X = &Gxbin[0]; + B.Y = &Gybin[0]; + + 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 MP_VAL; + } + + ltc_reverse_array(Gxbin, size); + ltc_reverse_array(Gybin, size); + 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) + */ +#ifndef WOLFSSL_SP_MATH + R->y->sign = k->sign; +#endif + } + if (res == MP_OKAY) + res = mp_set(R->z, 1); + + return res; +} + +int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) +{ + int res; + ltc_pkha_ecc_point_t A, B; + int size; + status_t status; + + uint8_t Gxbin[LTC_MAX_ECC_BITS / 8]; + uint8_t Gybin[LTC_MAX_ECC_BITS / 8]; + uint8_t Qxbin[LTC_MAX_ECC_BITS / 8]; + uint8_t Qybin[LTC_MAX_ECC_BITS / 8]; + const uint8_t *modbin; + const uint8_t *aCurveParam; + const uint8_t *bCurveParam; + const uint8_t *r2modn; + + size = mp_unsigned_bin_size(m); + + /* find LTC friendly parameters for the selected curve */ + if (ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam, size) != 0) { + res = ECC_BAD_ARG_E; + } + else { + 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; + + B.X = Qxbin; + B.Y = Qybin; + + status = LTC_PKHA_ECC_PointAdd(LTC_BASE, &A, &B, modbin, r2modn, aCurveParam, bCurveParam, size, + kLTC_PKHA_IntegerArith, &A); + if (status != kStatus_Success) { + res = MP_VAL; + } + else { + ltc_reverse_array(Gxbin, size); + ltc_reverse_array(Gybin, size); + 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 res; +} + +#if defined(HAVE_ED25519) || defined(HAVE_CURVE25519) +/* Weierstrass parameters of prime 2^255 - 19 */ +static const uint8_t curve25519_modbin[32] = { + 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; +/* precomputed R2modN for the curve25519 */ +static const uint8_t r2mod[32] = { + 0xa4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/* invThree = ModInv(3,curve25519_modbin) in LSB first */ +static const uint8_t invThree[32] = { + 0x49, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}; + +/* + * + * finds square root in finite field when modulus congruent to 5 modulo 8 + * this is fixed to curve25519 modulus 2^255 - 19 which is congruent to 5 modulo 8 + * + * This function solves equation: res^2 = a mod (2^255 - 19) + * +p = prime +p % 8 must be 5 + +v = ModularArithmetic.powmod(2*a, (p-5)/8, p) +i = (2*a*v**2) % p +r1 = 1*a*v*(i - 1) % p +r2 = -1*a*v*(i - 1) % p +puts "Gy=0x#{r2.to_s(16)}" + */ +status_t LTC_PKHA_Prime25519SquareRootMod(const uint8_t *A, size_t sizeA, + uint8_t *res, size_t *szRes, int sign) +{ + status_t status; + const uint8_t curve25519_param[] = { + 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f}; + uint8_t twoA[sizeof(curve25519_modbin)] = {0}; + uint8_t V[sizeof(curve25519_modbin)] = {0}; + uint8_t I[sizeof(curve25519_modbin)] = {0}; + uint8_t VV[sizeof(curve25519_modbin)] = {0}; + uint16_t szTwoA = 0; + uint16_t szV = 0; + uint16_t szVV = 0; + uint16_t szI = 0; + uint16_t szRes16 = 0; + uint8_t one = 1; + + /* twoA = 2*A % p */ + status = LTC_PKHA_ModAdd(LTC_BASE, A, sizeA, A, sizeA, curve25519_modbin, + sizeof(curve25519_modbin), twoA, &szTwoA, kLTC_PKHA_IntegerArith); + + /* V = ModularArithmetic.powmod(twoA, (p-5)/8, p) */ + if (status == kStatus_Success) { + status = + LTC_PKHA_ModExp(LTC_BASE, twoA, szTwoA, curve25519_modbin, + sizeof(curve25519_modbin), curve25519_param, + sizeof(curve25519_param), V, &szV, kLTC_PKHA_IntegerArith, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + + /* VV = V*V % p */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, V, szV, V, szV, curve25519_modbin, + sizeof(curve25519_modbin), VV, &szVV, kLTC_PKHA_IntegerArith, + kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); + } + + /* I = twoA * VV = 2*A*V*V % p */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, twoA, szTwoA, VV, szVV, + curve25519_modbin, sizeof(curve25519_modbin), I, &szI, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + + /* I = I - 1 */ + XMEMSET(VV, 0xff, sizeof(VV)); /* just temp for maximum integer - for non-modular subtract */ + if (0 <= LTC_PKHA_CompareBigNum(I, szI, &one, sizeof(one))) { + if (status == kStatus_Success) { + status = LTC_PKHA_ModSub1(LTC_BASE, I, szI, &one, sizeof(one), + VV, sizeof(VV), I, &szI); + } + } + else { + if (status == kStatus_Success) { + status = LTC_PKHA_ModSub1(LTC_BASE, curve25519_modbin, + sizeof(curve25519_modbin), &one, sizeof(one), VV, sizeof(VV), I, + &szI); + } + } + + /* res = a*v mod p */ + status = LTC_PKHA_ModMul(LTC_BASE, A, sizeA, V, szV, curve25519_modbin, + sizeof(curve25519_modbin), res, &szRes16, kLTC_PKHA_IntegerArith, + kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); + + /* res = res * (i-1) mod p */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, res, szRes16, I, szI, + curve25519_modbin, sizeof(curve25519_modbin), res, &szRes16, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + + /* if X mod 2 != X_0 then we need the -X + * + * X mod 2 get from LSB bit0 + */ + if ((status == kStatus_Success) && + ((bool)sign != (bool)(res[0] & 0x01u))) + { + status = LTC_PKHA_ModSub1(LTC_BASE, curve25519_modbin, + sizeof(curve25519_modbin), res, szRes16, VV, sizeof(VV), res, + &szRes16); /* -a = p - a */ + } + + if (status == kStatus_Success) { + *szRes = szRes16; + } + + return status; +} +#endif /* HAVE_ED25519 || HAVE_CURVE25519 */ + + +#ifdef HAVE_CURVE25519 + +/* for LTC we need Weierstrass format of curve25519 parameters + * these two are base point X and Y. + * in LSB first format (native for LTC) + */ +static const ECPoint ecBasePoint = { + {0x5a, 0x24, 0xad, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a}, + {0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, + 0x6d, 0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, + 0x1e, 0xe0, 0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20}, +}; + +const ECPoint *wc_curve25519_GetBasePoint(void) +{ + return &ecBasePoint; +} + +static const uint8_t curve25519_aCurveParam[CURVE25519_KEYSIZE] = { + 0x44, 0xa1, 0x14, 0x49, 0x98, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0x2a}; + +static const uint8_t curve_bCurveParam[CURVE25519_KEYSIZE] = { + 0x64, 0xc8, 0x10, 0x77, 0x9c, 0x5e, 0x0b, 0x26, 0xb4, 0x97, 0xd0, + 0x5e, 0x42, 0x7b, 0x09, 0xed, + 0x25, 0xb4, 0x97, 0xd0, 0x5e, 0x42, 0x7b, 0x09, 0xed, 0x25, 0xb4, + 0x97, 0xd0, 0x5e, 0x42, 0x7b}; + +/* transform a point on Montgomery curve to a point on Weierstrass curve */ +status_t LTC_PKHA_Curve25519ToWeierstrass( + const ltc_pkha_ecc_point_t *ltcPointIn,ltc_pkha_ecc_point_t *ltcPointOut) +{ + /* offset X point (in Montgomery) so that it becomes Weierstrass */ + const uint8_t offset[] = { + 0x51, 0x24, 0xad, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a}; + uint16_t sizeRes = 0; + status_t status; + status = LTC_PKHA_ModAdd(LTC_BASE, ltcPointIn->X, CURVE25519_KEYSIZE, + offset, sizeof(offset), curve25519_modbin, CURVE25519_KEYSIZE, + ltcPointOut->X, &sizeRes, kLTC_PKHA_IntegerArith); + + if (status == kStatus_Success) { + if (ltcPointOut->Y != ltcPointIn->Y) { + XMEMCPY(ltcPointOut->Y, ltcPointIn->Y, CURVE25519_KEYSIZE); + } + } + + return status; +} + +/* transform a point on Weierstrass curve to a point on Montgomery curve */ +status_t LTC_PKHA_WeierstrassToCurve25519( + const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut) +{ + status_t status; + uint16_t resultSize = 0; + const uint8_t three = 0x03; + + status = LTC_PKHA_ModMul(LTC_BASE, &three, sizeof(three), ltcPointIn->X, + CURVE25519_KEYSIZE, curve25519_modbin, CURVE25519_KEYSIZE, + ltcPointOut->X, &resultSize, kLTC_PKHA_IntegerArith, + kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); + + if (status == kStatus_Success) { + const uint8_t A[] = {0x06, 0x6d, 0x07}; + if (LTC_PKHA_CompareBigNum(ltcPointOut->X, resultSize, A, sizeof(A))) { + status = LTC_PKHA_ModSub1(LTC_BASE, ltcPointOut->X, resultSize, A, + sizeof(A), curve25519_modbin, CURVE25519_KEYSIZE, + ltcPointOut->X, &resultSize); + } + else { + status = LTC_PKHA_ModSub2(LTC_BASE, ltcPointOut->X, resultSize, A, + sizeof(A), curve25519_modbin, CURVE25519_KEYSIZE, + ltcPointOut->X, &resultSize); + } + } + + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, invThree, CURVE25519_KEYSIZE, + ltcPointOut->X, resultSize, curve25519_modbin, CURVE25519_KEYSIZE, + ltcPointOut->X, &resultSize, kLTC_PKHA_IntegerArith, + kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); + } + + if (status == kStatus_Success) { + if (ltcPointOut->Y != ltcPointIn->Y) { + XMEMCPY(ltcPointOut->Y, ltcPointIn->Y, CURVE25519_KEYSIZE); + } + } + + return status; +} + +/* Y = square root (X^3 + 486662*X^2 + X) */ +status_t LTC_PKHA_Curve25519ComputeY(ltc_pkha_ecc_point_t *ltcPoint) +{ + uint8_t three = 3; + const uint8_t A[] = {0x06, 0x6d, 0x07}; + uint8_t U[CURVE25519_KEYSIZE] = {0}; + uint8_t X2[CURVE25519_KEYSIZE] = {0}; + uint16_t sizeU = 0; + uint16_t sizeX2 = 0; + size_t szRes = 0; + status_t status; + + /* X^3 */ + status = LTC_PKHA_ModExp(LTC_BASE, ltcPoint->X, CURVE25519_KEYSIZE, + curve25519_modbin, CURVE25519_KEYSIZE, &three, 1, U, &sizeU, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); + + /* X^2 */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, ltcPoint->X, CURVE25519_KEYSIZE, + ltcPoint->X, CURVE25519_KEYSIZE, curve25519_modbin, + CURVE25519_KEYSIZE, X2, &sizeX2, kLTC_PKHA_IntegerArith, + kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); + } + + /* 486662*X^2 */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, A, sizeof(A), X2, sizeX2, + curve25519_modbin, CURVE25519_KEYSIZE, X2, &sizeX2, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + + /* X^3 + 486662*X^2 */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModAdd(LTC_BASE, U, sizeU, X2, sizeX2, + curve25519_modbin, CURVE25519_KEYSIZE, U, &sizeU, + kLTC_PKHA_IntegerArith); + } + + /* U = X^3 + 486662*X^2 + X */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModAdd(LTC_BASE, U, sizeU, ltcPoint->X, + CURVE25519_KEYSIZE, curve25519_modbin, CURVE25519_KEYSIZE, U, + &sizeU, kLTC_PKHA_IntegerArith); + } + + /* Y = modular square root of U (U is Y^2) */ + if (status == kStatus_Success) { + status = LTC_PKHA_Prime25519SquareRootMod(U, sizeU, ltcPoint->Y, + &szRes, 1); + } + + return status; +} + +/* Q = n*P */ +/* if type is set, the input point p is in Montgomery curve coordinates, + so there is a map to Weierstrass curve */ +/* q output point is always in Montgomery curve coordinates */ +int wc_curve25519(ECPoint *q, byte *n, const ECPoint *p, fsl_ltc_ecc_coordinate_system_t type) +{ + status_t status; + ltc_pkha_ecc_point_t ltcPoint; + ltc_pkha_ecc_point_t ltcPointOut; + ECPoint pIn = {{0}}; + + XMEMCPY(&pIn, p, sizeof(*p)); + ltcPoint.X = &pIn.point[0]; + ltcPoint.Y = &pIn.pointY[0]; + + /* if input point P is on Curve25519 Montgomery curve, transform + it to Weierstrass equivalent */ + if (type == kLTC_Curve25519) { + LTC_PKHA_Curve25519ToWeierstrass(<cPoint, <cPoint); + } + + ltcPointOut.X = &q->point[0]; + ltcPointOut.Y = &q->pointY[0]; + /* curve25519_modbin, r2mod, curve25519_aCurveParam, curve25519_bCurveParam + * are Weierstrass equivalent with Curve25519 */ + status = LTC_PKHA_ECC_PointMul(LTC_BASE, <cPoint, n, CURVE25519_KEYSIZE, + curve25519_modbin, r2mod, curve25519_aCurveParam, + curve25519_bCurveParam, CURVE25519_KEYSIZE, kLTC_PKHA_TimingEqualized, + kLTC_PKHA_IntegerArith, <cPointOut, NULL); + + /* now need to map from Weierstrass form to Montgomery form */ + if (status == kStatus_Success) { + status = LTC_PKHA_WeierstrassToCurve25519(<cPointOut, <cPointOut); + } + + return (status == kStatus_Success) ? 0 : IS_POINT_E; +} + +#endif /* HAVE_CURVE25519 */ + + +#ifdef HAVE_ED25519 +/* a and d are Edwards curve parameters -1 and -121665/121666 prime is 2^255 - 19. + * + * https://en.wikipedia.org/wiki/Montgomery_curve#Equivalence_with_Edward_curves + */ + +/* d parameter of ed25519 */ +static const uint8_t d_coefEd25519[] = { + 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, 0xab, 0xd8, 0x41, + 0x41, 0x4d, 0x0a, 0x70, 0x00, 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, + 0xc7, 0x8c, 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52}; + +/* Montgomery curve parameter A for a Montgomery curve equivalent with ed25519 */ +static const uint8_t A_coefEd25519[] = { + 0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/* Montgomery curve parameter B for a Montgomery curve equivalent with ed25519 */ +static const uint8_t B_coefEd25519[] = { + 0xe5, 0x92, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + +/* these are pre-computed constants used in computations */ + +/* = 3*B */ +static const uint8_t threeB_coefEd25519[] = { + 0xd5, 0xb8, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + +/* = -A */ +static const uint8_t minus_A_coefEd25519[] = { + 0xe7, 0x92, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + +/* = 1/B */ +static const uint8_t invB_coefEd25519[] = { +0xc4, 0xa1, 0x29, 0x7b, 0x8d, 0x2c, 0x85, 0x22, 0xd5, 0x89, 0xaf, + 0xaf, 0x6c, 0xfd, 0xe3, 0xff, 0xd9, 0x85, 0x21, 0xa2, 0xe1, 0x2f, + 0xce, 0x1c, 0x63, 0x00, 0x24, 0x75, 0xc4, 0x24, 0x7f, 0x6b}; + +/* = 1/(3*B) */ +static const uint8_t A_mul_invThreeB_coefEd25519[] = { + 0xb9, 0x3e, 0xe4, 0xad, 0xa1, 0x37, 0xa7, 0x93, 0x1c, 0xa4, 0x35, + 0xe0, 0x0c, 0x57, 0xbd, 0xaa, 0x6e, 0x51, 0x94, 0x3e, 0x14, 0xe0, + 0xcb, 0xec, 0xbd, 0xff, 0xe7, 0xb1, 0x27, 0x92, 0x00, 0x63}; + +/* Weierstrass curve parameter a for a Weierstrass curve equivalent with ed25519 */ +static const uint8_t a_coefEd25519[] = { + 0x2d, 0x17, 0xbc, 0xf8, 0x8e, 0xe1, 0x71, 0xac, 0xf7, 0x2a, 0xa5, + 0x0c, 0x5d, 0xb6, 0xb8, 0x6b, 0xd6, 0x3d, 0x7b, 0x61, 0x0d, 0xe1, + 0x97, 0x31, 0xe6, 0xbe, 0xb9, 0xa5, 0xd3, 0xac, 0x4e, 0x5d}; + +/* Weierstrass curve parameter b for a Weierstrass curve equivalent with ed25519 */ +static const uint8_t b_coefEd25519[] = { + 0xa4, 0xb2, 0x64, 0xf3, 0xc1, 0xeb, 0x04, 0x90, 0x32, 0xbc, 0x9f, + 0x6b, 0x97, 0x31, 0x48, 0xf5, 0xd5, 0x80, 0x57, 0x10, 0x06, 0xdb, + 0x0d, 0x55, 0xe0, 0xb3, 0xd0, 0xcf, 0x9b, 0xb2, 0x11, 0x1d}; + +/* Ed25519 basepoint B mapped to Weierstrass equivalent */ +static uint8_t Wx_Ed25519[ED25519_KEY_SIZE] = { + 0x35, 0xef, 0x5a, 0x02, 0x9b, 0xc8, 0x55, 0xca, 0x9a, 0x7c, 0x61, + 0x0d, 0xdf, 0x3f, 0xc1, 0xa9, 0x18, 0x06, 0xc2, 0xf1, 0x02, 0x8f, + 0x0b, 0xf0, 0x39, 0x03, 0x2c, 0xd0, 0x0f, 0xdd, 0x78, 0x2a}; +static uint8_t Wy_Ed25519[ED25519_KEY_SIZE] = { + 0x14, 0x1d, 0x2c, 0xf6, 0xf3, 0x30, 0x78, 0x9b, 0x65, 0x31, 0x71, + 0x80, 0x61, 0xd0, 0x6f, 0xcf, 0x23, 0x83, 0x79, 0x63, 0xa5, 0x3b, + 0x48, 0xbe, 0x2e, 0xa2, 0x1d, 0xc7, 0xa5, 0x44, 0xc6, 0x29}; + +static const ltc_pkha_ecc_point_t basepointEd25519 = { + Wx_Ed25519, Wy_Ed25519, +}; + +const ltc_pkha_ecc_point_t *LTC_PKHA_Ed25519_BasePoint(void) +{ + return &basepointEd25519; +} + +/* input point is on Weierstrass curve, typeOut determines the coordinates + system of output point (either Weierstrass or Ed25519) */ +status_t LTC_PKHA_Ed25519_PointMul(const ltc_pkha_ecc_point_t *ltcPointIn, + const uint8_t *N, + size_t sizeN, + ltc_pkha_ecc_point_t *ltcPointOut, + fsl_ltc_ecc_coordinate_system_t typeOut) +{ + uint16_t szN = (uint16_t)sizeN; + status_t status; + /* input on W, output in W, W parameters of ECC curve are Ed25519 curve + parameters mapped to Weierstrass curve */ + status = LTC_PKHA_ECC_PointMul(LTC_BASE, ltcPointIn, N, szN, + curve25519_modbin, r2mod, a_coefEd25519, b_coefEd25519, + ED25519_KEY_SIZE, kLTC_PKHA_TimingEqualized, kLTC_PKHA_IntegerArith, + ltcPointOut, NULL); + + /* Weierstrass coordinates to Ed25519 coordinates */ + if ((status == kStatus_Success) && (typeOut == kLTC_Ed25519)) { + status = LTC_PKHA_WeierstrassToEd25519(ltcPointOut, ltcPointOut); + } + return status; +} + +status_t LTC_PKHA_Ed25519ToWeierstrass(const ltc_pkha_ecc_point_t *ltcPointIn, + ltc_pkha_ecc_point_t *ltcPointOut) +{ + status_t status; + uint8_t Mx[ED25519_KEY_SIZE] = {0}; + uint8_t My[ED25519_KEY_SIZE] = {0}; + uint8_t temp[ED25519_KEY_SIZE] = {0}; + uint8_t temp2[ED25519_KEY_SIZE] = {0}; + const uint8_t max[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + const uint8_t *Ex; + const uint8_t *Ey; + uint8_t *Gx; + uint8_t *Gy; + uint16_t szMx = 0; + uint16_t szGx = 0; + uint16_t szMy = 0; + uint16_t szGy = 0; + uint16_t szTemp = 0; + uint16_t szTemp2 = 0; + uint8_t one = 1; + + Ex = ltcPointIn->X; + Ey = ltcPointIn->Y; + Gx = ltcPointOut->X; + Gy = ltcPointOut->Y; + /* # (Ex, Ey) on Ed (a_ed, d) to (x, y) on M (A,B) + 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)) + + (A * ModularArithmetic.invert(3*B, prime))) % prime + Gy = (My * ModularArithmetic.invert(B, prime)) % prime */ + + /* temp = 1 + Ey */ + status = LTC_PKHA_ModAdd(LTC_BASE, Ey, ED25519_KEY_SIZE, &one, sizeof(one), + curve25519_modbin, sizeof(curve25519_modbin), temp, &szTemp, + kLTC_PKHA_IntegerArith); + + /* temp2 = 1 - Ey = 1 + (p - Ey) */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModSub1(LTC_BASE, curve25519_modbin, + sizeof(curve25519_modbin), Ey, ED25519_KEY_SIZE, max, sizeof(max), + temp2, &szTemp2); + } + if (status == kStatus_Success) { + status = LTC_PKHA_ModAdd(LTC_BASE, temp2, szTemp2, &one, sizeof(one), + curve25519_modbin, sizeof(curve25519_modbin), temp2, &szTemp2, + kLTC_PKHA_IntegerArith); + } + + /* Mx = ModInv(temp2,prime) */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModInv(LTC_BASE, temp2, szTemp2, curve25519_modbin, + sizeof(curve25519_modbin), Mx, &szMx, kLTC_PKHA_IntegerArith); + } + + /* Mx = Mx * temp */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, Mx, szMx, temp, szTemp, + curve25519_modbin, ED25519_KEY_SIZE, Mx, &szMx, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + + /* My = temp2 * Ex */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, Ex, ED25519_KEY_SIZE, temp2, + szTemp2, curve25519_modbin, ED25519_KEY_SIZE, My, &szMy, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + + /* My = ModInv(My, prime) */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModInv(LTC_BASE, My, szMy, curve25519_modbin, + sizeof(curve25519_modbin), My, &szMy, kLTC_PKHA_IntegerArith); + } + /* My = My * temp */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, My, szMy, temp, szTemp, + curve25519_modbin, ED25519_KEY_SIZE, My, &szMy, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + + /* Gx = Mx * invB_coefEd25519 + A_mul_invThreeB_coefEd25519 */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, Mx, szMx, invB_coefEd25519, + sizeof(invB_coefEd25519), curve25519_modbin, ED25519_KEY_SIZE, Gx, + &szGx, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + if (status == kStatus_Success) { + status = LTC_PKHA_ModAdd(LTC_BASE, Gx, szGx, + A_mul_invThreeB_coefEd25519, sizeof(A_mul_invThreeB_coefEd25519), + curve25519_modbin, sizeof(curve25519_modbin), Gx, &szGx, + kLTC_PKHA_IntegerArith); + } + + /* Gy = My * invB_coefEd25519 */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, My, szMy, invB_coefEd25519, + sizeof(invB_coefEd25519), curve25519_modbin, ED25519_KEY_SIZE, Gy, + &szGy, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + + return status; +} + +/* +# (Gx, Gy) on W to (Ex, Ey) on E +My = (B*Gy) % prime +Mx = ((3*B*Gx-A)*ModularArithmetic.invert(3, prime)) % prime +Ex = Mx*ModularArithmetic.invert(My, prime) % prime +Ey = (Mx - 1)*ModularArithmetic.invert(Mx + 1, prime) % prime +*/ +status_t LTC_PKHA_WeierstrassToEd25519(const ltc_pkha_ecc_point_t *ltcPointIn, + ltc_pkha_ecc_point_t *ltcPointOut) +{ + status_t status; + uint8_t Mx[ED25519_KEY_SIZE] = {0}; + uint8_t My[ED25519_KEY_SIZE] = {0}; + uint8_t temp[ED25519_KEY_SIZE] = {0}; + const uint8_t *Gx; + const uint8_t *Gy; + uint8_t *Ex; + uint8_t *Ey; + uint16_t szMx = 0; + uint16_t szEx = 0; + uint16_t szMy = 0; + uint16_t szEy = 0; + uint16_t szTemp = 0; + uint8_t one = 1; + + Gx = ltcPointIn->X; + Gy = ltcPointIn->Y; + Ex = ltcPointOut->X; + Ey = ltcPointOut->Y; + + /* My = (B*Gy) % prime */ + status = LTC_PKHA_ModMul(LTC_BASE, B_coefEd25519, sizeof(B_coefEd25519), + Gy, ED25519_KEY_SIZE, curve25519_modbin, ED25519_KEY_SIZE, My, &szMy, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); + + /* temp = 3*B*Gx mod p */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, threeB_coefEd25519, + sizeof(threeB_coefEd25519), Gx, ED25519_KEY_SIZE, curve25519_modbin, + ED25519_KEY_SIZE, temp, &szTemp, kLTC_PKHA_IntegerArith, + kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); + } + /* temp = (temp - A) mod p */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModAdd(LTC_BASE, temp, szTemp, minus_A_coefEd25519, + sizeof(minus_A_coefEd25519), curve25519_modbin, + sizeof(curve25519_modbin), temp, &szTemp, kLTC_PKHA_IntegerArith); + } + /* Mx = (temp/3) mod p */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, temp, szTemp, invThree, + sizeof(invThree), curve25519_modbin, sizeof(curve25519_modbin), Mx, + &szMx, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + /* temp = 1/My mod p */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModInv(LTC_BASE, My, szMy, curve25519_modbin, + sizeof(curve25519_modbin), temp, &szTemp, kLTC_PKHA_IntegerArith); + } + /* Ex = Mx * temp mod p */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, temp, szTemp, Mx, szMx, + curve25519_modbin, sizeof(curve25519_modbin), Ex, &szEx, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + + /* temp = Mx + 1 mod p */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModAdd(LTC_BASE, Mx, szMx, &one, sizeof(one), + curve25519_modbin, sizeof(curve25519_modbin), temp, &szTemp, + kLTC_PKHA_IntegerArith); + } + /* temp = 1/temp mod p */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModInv(LTC_BASE, temp, szTemp, curve25519_modbin, + sizeof(curve25519_modbin), temp, &szTemp, kLTC_PKHA_IntegerArith); + } + /* Mx = (Mx - 1) mod p */ + if (status == kStatus_Success) { + if (LTC_PKHA_CompareBigNum(Mx, szMx, &one, sizeof(one)) >= 0) { + status = LTC_PKHA_ModSub1(LTC_BASE, Mx, szMx, &one, sizeof(one), + curve25519_modbin, sizeof(curve25519_modbin), Mx, &szMx); + } + else { + /* Mx is zero, so it is modulus, thus we do modulus - 1 */ + XMEMCPY(Mx, curve25519_modbin, sizeof(curve25519_modbin)); + Mx[0]--; + } + } + /* Ey = Mx * temp mod p */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, temp, szTemp, Mx, szMx, + curve25519_modbin, sizeof(curve25519_modbin), Ey, &szEy, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + + return status; +} + +status_t LTC_PKHA_Ed25519_PointDecompress(const uint8_t *pubkey, + size_t pubKeySize, ltc_pkha_ecc_point_t *ltcPointOut) +{ + status_t status; + const uint8_t one = 1; + + /* pubkey contains the Y coordinate and a sign of X + */ + + /* x^2 = ((y^2 - 1) / (d*y^2 +1)) mod p */ + + /* decode Y from pubkey */ + XMEMCPY(ltcPointOut->Y, pubkey, pubKeySize); + ltcPointOut->Y[pubKeySize - 1] &= ~0x80u; + int sign = (int)(bool)(pubkey[pubKeySize - 1] & 0x80u); + + uint8_t U[ED25519_KEY_SIZE] = {0}; + uint8_t V[ED25519_KEY_SIZE] = {0}; + uint8_t *X = ltcPointOut->X; + uint8_t *Y = ltcPointOut->Y; + uint16_t szU = 0; + uint16_t szV = 0; + size_t szRes = 0; + + /* decode X from pubkey */ + + /* U = y * y mod p */ + status = LTC_PKHA_ModMul(LTC_BASE, Y, ED25519_KEY_SIZE, Y, + ED25519_KEY_SIZE, curve25519_modbin, ED25519_KEY_SIZE, U, &szU, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); + XMEMCPY(V, U, szU); + szV = szU; + + /* U = U - 1 = y^2 - 1 */ + if (status == kStatus_Success) { + if (LTC_PKHA_CompareBigNum(U, szU, &one, sizeof(one)) >= 0) { + status = LTC_PKHA_ModSub1(LTC_BASE, U, szU, &one, sizeof(one), + curve25519_modbin, sizeof(curve25519_modbin), U, &szU); + } + else { + /* U is zero, so it is modulus, thus we do modulus - 1 */ + XMEMCPY(U, curve25519_modbin, sizeof(curve25519_modbin)); + U[0]--; + } + } + + /* V = d*y*y + 1 */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, V, szV, d_coefEd25519, + ED25519_KEY_SIZE, curve25519_modbin, ED25519_KEY_SIZE, V, &szV, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); + } + + if (status == kStatus_Success) { + status = LTC_PKHA_ModAdd(LTC_BASE, V, szV, &one, sizeof(one), + curve25519_modbin, sizeof(curve25519_modbin), V, &szV, + kLTC_PKHA_IntegerArith); + } + + /* U = U / V (mod p) */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModInv(LTC_BASE, V, szV, curve25519_modbin, + sizeof(curve25519_modbin), V, &szV, kLTC_PKHA_IntegerArith); + } + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, V, szV, U, szU, curve25519_modbin, + ED25519_KEY_SIZE, U, &szU, kLTC_PKHA_IntegerArith, + kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); + } + + /* get square root */ + if (status == kStatus_Success) { + status = LTC_PKHA_Prime25519SquareRootMod(U, szU, X, &szRes, sign); + } + + return status; +} + +/* LSByte first of Ed25519 parameter l = 2^252 + 27742317777372353535851937790883648493 */ +static const uint8_t l_coefEdDSA[] = { + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, + 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; + +/* +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. +*/ +status_t LTC_PKHA_sc_reduce(uint8_t *a) +{ + uint16_t szA = 0; + return LTC_PKHA_ModRed(LTC_BASE, a, 64, l_coefEdDSA, sizeof(l_coefEdDSA), + a, &szA, kLTC_PKHA_IntegerArith); +} + +/* +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. +*/ +status_t LTC_PKHA_sc_muladd(uint8_t *s, const uint8_t *a, + const uint8_t *b, const uint8_t *c) +{ + uint16_t szS = 0; + uint16_t szB = 0; + uint8_t tempB[32] = {0}; + status_t status; + + /* 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. + */ + status = LTC_PKHA_ModRed(LTC_BASE, b, 32, l_coefEdDSA, sizeof(l_coefEdDSA), + tempB, &szB, kLTC_PKHA_IntegerArith); + + if (status == kStatus_Success) { + status = LTC_PKHA_ModMul(LTC_BASE, a, 32, tempB, szB, l_coefEdDSA, + sizeof(l_coefEdDSA), s, &szS, kLTC_PKHA_IntegerArith, + kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); + } + + if (status == kStatus_Success) { + status = LTC_PKHA_ModAdd(LTC_BASE, s, szS, c, 32, l_coefEdDSA, 32, s, + &szS, kLTC_PKHA_IntegerArith); + } + + return status; +} + +/* +r = a * A + b * B +where A is public key point, B is basepoint +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. +*/ +status_t LTC_PKHA_SignatureForVerify(uint8_t *rcheck, const unsigned char *a, + const unsigned char *b, ed25519_key *key) +{ + /* To verify a signature on a message M, first split the signature + into two 32-octet halves. Decode the first half as a point R, + and the second half as an integer s, in the range 0 <= s < q. If + the decoding fails, the signature is invalid. */ + + /* Check the group equation 8s B = 8 R + 8k A. */ + + /* + Uses a fast single-signature verification SB = R + H(R,A,M)A becomes + SB - H(R,A,M)A saving decompression of R + */ + uint8_t X0[ED25519_PUB_KEY_SIZE] = {0}; + uint8_t X1[ED25519_PUB_KEY_SIZE] = {0}; + uint8_t Y0[ED25519_PUB_KEY_SIZE] = {0}; + uint8_t Y1[ED25519_PUB_KEY_SIZE] = {0}; + const uint8_t max[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + ltc_pkha_ecc_point_t ltc0; + ltc_pkha_ecc_point_t ltc1; + ltc_pkha_ecc_point_t pubKey; + status_t status; + + /* The equality for the negative of a point P, in affine coordinates, + is -P = -(x,y) = (x, -y) */ + uint16_t szY = 32; + + ltc0.X = X0; + ltc1.X = X1; + ltc0.Y = Y0; + ltc1.Y = Y1; + pubKey.X = key->pointX; + pubKey.Y = key->pointY; + + /* ltc0 = b*B */ + status = LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), b, + ED25519_KEY_SIZE, <c0, kLTC_Weierstrass /* result in W */); + + /* ltc1 = a*A */ + if (status == kStatus_Success) { + status = LTC_PKHA_Ed25519ToWeierstrass(&pubKey, <c1); + } + if (status == kStatus_Success) { + status = LTC_PKHA_Ed25519_PointMul(<c1, a, ED25519_KEY_SIZE, <c1, + kLTC_Weierstrass /* result in W */); + } + + /* R = b*B - a*A */ + if (status == kStatus_Success) { + status = LTC_PKHA_ModSub1(LTC_BASE, curve25519_modbin, + sizeof(curve25519_modbin), ltc1.Y, szY, max, sizeof(max), ltc1.Y, + &szY); + } + if (status == kStatus_Success) { + status = LTC_PKHA_ECC_PointAdd(LTC_BASE, <c0, <c1, + curve25519_modbin, r2mod, a_coefEd25519, b_coefEd25519, + ED25519_KEY_SIZE, kLTC_PKHA_IntegerArith, <c0); + } + /* map to Ed25519 */ + if (status == kStatus_Success) { + status = LTC_PKHA_WeierstrassToEd25519(<c0, <c0); + } + if (((uint32_t)ltc0.X[0]) & 0x01u) { + ltc0.Y[ED25519_KEY_SIZE - 1] |= 0x80u; + } + + XMEMCPY(rcheck, ltc0.Y, ED25519_KEY_SIZE); + return status; +} + +status_t LTC_PKHA_Ed25519_Compress(const ltc_pkha_ecc_point_t *ltcPointIn, + uint8_t *p) +{ + /* compress */ + /* get sign of X per https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-02 + * To form the encoding of the point, copy the least + significant bit of the x-coordinate to the most significant bit of + the final octet + */ + XMEMCPY(p, ltcPointIn->Y, ED25519_KEY_SIZE); + if (((uint32_t)ltcPointIn->X[0]) & 0x01u) { + p[ED25519_KEY_SIZE - 1] |= 0x80u; + } + return kStatus_Success; +} + +#endif /* HAVE_ED25519 */ +#endif /* FREESCALE_LTC_ECC */ + + +#undef ERROR_OUT + +#endif /* FREESCALE_LTC_TFM || FREESCALE_LTC_ECC */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/pic32/pic32mz-crypt.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/pic32/pic32mz-crypt.c new file mode 100644 index 000000000..1e618c194 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/pic32/pic32mz-crypt.c @@ -0,0 +1,804 @@ +/* pic32mz-crypt.c + * + * Copyright (C) 2006-2020 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* pIn, int inLen, word32* pOut, 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; + word32* in = (word32*)pIn; + word32* out = pOut; + int isDynamic = 0; + + /* 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))) { + /* dynamically allocate aligned pointers */ + isDynamic = 1; + in = (word32*)XMALLOC(inLen, NULL, DYNAMIC_TYPE_AES_BUFFER); + if (in == NULL) + return MEMORY_E; + if ((word32*)pIn == pOut) /* inline */ + out = (word32*)in; + else { + out = (word32*)XMALLOC(outLen, NULL, DYNAMIC_TYPE_AES_BUFFER); + if (out == NULL) { + XFREE(in, NULL, DYNAMIC_TYPE_AES_BUFFER); + return MEMORY_E; + } + } + XMEMCPY(in, pIn, inLen); + } + + /* 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 != 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(); + + /* 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 + } + + /* handle unaligned */ + if (isDynamic) { + /* return result */ + XMEMCPY(pOut, out, outLen); + + /* free dynamic buffers */ + XFREE(in, NULL, DYNAMIC_TYPE_AES_BUFFER); + if ((word32*)pIn != pOut) + XFREE(out, NULL, DYNAMIC_TYPE_AES_BUFFER); + } + + 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); + /* initialize the MSGLEN on engine startup to avoid infinite loop when + * length is less than 257 (size of PIC32_BLOCK_SIZE) */ + uc_desc->bd[desc->currBd].MSGLEN = desc->msgSize; + 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); + cache->buf = NULL; + } + } + 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->buf = NULL; + cache->bufLen = cache->updLen = 0; + + return ret; +} + +static void wc_Pic32HashFree(hashUpdCache* cache, void* heap) +{ + if (cache && cache->buf && !cache->isCopy) { + XFREE(cache->buf, heap, DYNAMIC_TYPE_HASH_TMP); + cache->buf = NULL; + } +} + +/* API's for compatibility with Harmony wrappers - not used */ +#ifndef NO_MD5 + int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId) + { + if (md5 == NULL) + return BAD_FUNC_ARG; + + XMEMSET(md5, 0, sizeof(wc_Md5)); + md5->heap = heap; + (void)devId; + return 0; + } + int wc_Md5Update(wc_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(wc_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(wc_Md5* md5, word32 len) + { + if (md5) { + #ifdef WOLFSSL_PIC32MZ_LARGE_HASH + md5->cache.finalLen = len; + #else + (void)len; + #endif + } + } + void wc_Md5Pic32Free(wc_Md5* md5) + { + if (md5) { + wc_Pic32HashFree(&md5->cache, md5->heap); + } + } +#endif /* !NO_MD5 */ +#ifndef NO_SHA + int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) + { + if (sha == NULL) + return BAD_FUNC_ARG; + + XMEMSET(sha, 0, sizeof(wc_Sha)); + sha->heap = heap; + (void)devId; + return 0; + } + int wc_ShaUpdate(wc_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(wc_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(wc_Sha* sha, word32 len) + { + if (sha) { + #ifdef WOLFSSL_PIC32MZ_LARGE_HASH + sha->cache.finalLen = len; + #else + (void)len; + #endif + } + } + void wc_ShaPic32Free(wc_Sha* sha) + { + if (sha) { + wc_Pic32HashFree(&sha->cache, sha->heap); + } + } +#endif /* !NO_SHA */ +#ifndef NO_SHA256 + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + if (sha256 == NULL) + return BAD_FUNC_ARG; + + XMEMSET(sha256, 0, sizeof(wc_Sha256)); + sha256->heap = heap; + (void)devId; + return 0; + } + int wc_Sha256Update(wc_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(wc_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(wc_Sha256* sha256, word32 len) + { + if (sha256) { + #ifdef WOLFSSL_PIC32MZ_LARGE_HASH + sha256->cache.finalLen = len; + #else + (void)len; + #endif + } + } + void wc_Sha256Pic32Free(wc_Sha256* sha256) + { + if (sha256) { + wc_Pic32HashFree(&sha256->cache, sha256->heap); + } + } +#endif /* !NO_SHA256 */ +#endif /* WOLFSSL_PIC32MZ_HASH */ + + +#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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/pic32/pic32mz-hash.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/pic32/pic32mz-hash.c deleted file mode 100644 index c293afacd..000000000 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/pic32/pic32mz-hash.c +++ /dev/null @@ -1,371 +0,0 @@ -/* pic32mz-hash.c - * - * Copyright (C) 2006-2015 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 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_data_size(pic32mz_desc *desc, word32 msgSize) -{ - desc->msgSize = msgSize; -} - -static void update_engine(pic32mz_desc *desc, const char *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); - } -} - -static int fillBuff(char *buff, int *bufflen, const char *data, int len, int blocksz) -{ - int room, copysz ; - - room = blocksz - *bufflen ; - copysz = (len <= room) ? len : room ; - XMEMCPY(buff, data, copysz) ; - *bufflen += copysz ; - return (*bufflen == blocksz) ? 1 : 0 ; -} - -#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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/st/README.md b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/st/README.md new file mode 100644 index 000000000..011dd909b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/st/README.md @@ -0,0 +1,132 @@ +# ST Ports + +Support for the STM32 L4, F1, F2, F4 and F7 on-board crypto hardware acceleration for symmetric AES (ECB/CBC/CTR/GCM) and MD5/SHA1/SHA224/SHA256. + +Support for the STSAFE-A100 crypto hardware accelerator co-processor via I2C for ECC supporting NIST or Brainpool 256-bit and 384-bit curves. It requires the ST-Safe SDK including wolf stsafe_interface.c/.h files. Please contact ST for these. + + +For details see our [wolfSSL ST](https://www.wolfssl.com/docs/stm32/) page. + + +## STM32 Symmetric Acceleration + +We support using the STM32 CubeMX and Standard Peripheral Library. + +### Building + +To enable support define one of the following: + +``` +#define WOLFSSL_STM32L4 +#define WOLFSSL_STM32F1 +#define WOLFSSL_STM32F2 +#define WOLFSSL_STM32F4 +#define WOLFSSL_STM32F7 +``` + +To use CubeMX define `WOLFSSL_STM32_CUBEMX` otherwise StdPeriLib is used. + +To disable portions of the hardware acceleration you can optionally define: + +``` +#define NO_STM32_RNG +#define NO_STM32_CRYPTO +#define NO_STM32_HASH +``` + +### Coding + +In your application you must include before any other wolfSSL headers. If building the sources directly we recommend defining `WOLFSSL_USER_SETTINGS` and adding your own `user_settings.h` file. You can find a good reference for this in `IDE/GCC-ARM/Header/user_settings.h`. + + +### Benchmarks + +See our [benchmarks](https://www.wolfssl.com/docs/benchmarks/) on the wolfSSL website. + + + +## STSAFE-A100 ECC Acceleration + +Using the wolfSSL PK callbacks and the reference ST Safe reference API's we support an ECC only cipher suite such as ECDHE-ECDSA-AES128-SHA256 for TLS client or server. + +At the wolfCrypt level we also support ECC native API's for `wc_ecc_*` using the ST-Safe. + +### Building + +`./configure --enable-pkcallbacks CFLAGS="-DWOLFSSL_STSAFEA100"` + +or + +`#define HAVE_PK_CALLBACKS` +`#define WOLFSSL_STSAFEA100` + + +### Coding + +Setup the PK callbacks for TLS using: + +``` +/* Setup PK Callbacks for STSAFE-A100 */ +WOLFSSL_CTX* ctx; +wolfSSL_CTX_SetEccKeyGenCb(ctx, SSL_STSAFE_CreateKeyCb); +wolfSSL_CTX_SetEccSignCb(ctx, SSL_STSAFE_SignCertificateCb); +wolfSSL_CTX_SetEccVerifyCb(ctx, SSL_STSAFE_VerifyPeerCertCb); +wolfSSL_CTX_SetEccSharedSecretCb(ctx, SSL_STSAFE_SharedSecretCb); +wolfSSL_CTX_SetDevId(ctx, 0); /* enables wolfCrypt `wc_ecc_*` ST-Safe use */ +``` + +The reference STSAFE-A100 PK callback functions are located in the `wolfcrypt/src/port/st/stsafe.c` file. + +Adding a custom context to the callbacks: + +``` +/* Setup PK Callbacks context */ +WOLFSSL* ssl; +void* myOwnCtx; +wolfSSL_SetEccKeyGenCtx(ssl, myOwnCtx); +wolfSSL_SetEccVerifyCtx(ssl, myOwnCtx); +wolfSSL_SetEccSignCtx(ssl, myOwnCtx); +wolfSSL_SetEccSharedSecretCtx(ssl, myOwnCtx); +``` + +### Benchmarks and Memory Use + +Software only implementation (STM32L4 120Mhz, Cortex-M4, Fast Math): + +``` +ECDHE 256 key gen SW 4 ops took 1.278 sec, avg 319.500 ms, 3.130 ops/sec +ECDHE 256 agree SW 4 ops took 1.306 sec, avg 326.500 ms, 3.063 ops/sec +ECDSA 256 sign SW 4 ops took 1.298 sec, avg 324.500 ms, 3.082 ops/sec +ECDSA 256 verify SW 2 ops took 1.283 sec, avg 641.500 ms, 1.559 ops/sec +``` + +Memory Use: + +``` +Peak Stack: 18456 +Peak Heap: 2640 +Total: 21096 +``` + + +STSAFE-A100 acceleration: + +``` +ECDHE 256 key gen HW 8 ops took 1.008 sec, avg 126.000 ms, 7.937 ops/sec +ECDHE 256 agree HW 6 ops took 1.051 sec, avg 175.167 ms, 5.709 ops/sec +ECDSA 256 sign HW 14 ops took 1.161 sec, avg 82.929 ms, 12.059 ops/sec +ECDSA 256 verify HW 8 ops took 1.184 sec, avg 148.000 ms, 6.757 ops/sec +``` + +Memory Use: + +``` +Peak Stack: 9592 +Peak Heap: 170 +Total: 9762 +``` + + +## Support + +Email us at [support@wolfssl.com](mailto:support@wolfssl.com). diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/st/stm32.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/st/stm32.c new file mode 100644 index 000000000..b37dbd845 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/st/stm32.c @@ -0,0 +1,879 @@ +/* stm32.c + * + * Copyright (C) 2006-2020 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 + */ + +/* Generic STM32 Hashing Function */ +/* Supports CubeMX HAL or Standard Peripheral Library */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifndef NO_AES + #include +#endif + + +#ifdef STM32_HASH + +#ifdef WOLFSSL_STM32L4 + #define HASH_STR_NBW HASH_STR_NBLW +#endif + +/* User can override STM32_HASH_CLOCK_ENABLE and STM32_HASH_CLOCK_DISABLE */ +#ifndef STM32_HASH_CLOCK_ENABLE + static WC_INLINE void wc_Stm32_Hash_Clock_Enable(STM32_HASH_Context* stmCtx) + { + #ifdef WOLFSSL_STM32_CUBEMX + __HAL_RCC_HASH_CLK_ENABLE(); + #else + RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, ENABLE); + #endif + (void)stmCtx; + } + #define STM32_HASH_CLOCK_ENABLE(ctx) wc_Stm32_Hash_Clock_Enable(ctx) +#endif + +#ifndef STM32_HASH_CLOCK_DISABLE + static WC_INLINE void wc_Stm32_Hash_Clock_Disable(STM32_HASH_Context* stmCtx) + { + #ifdef WOLFSSL_STM32_CUBEMX + __HAL_RCC_HASH_CLK_DISABLE(); + #else + RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, DISABLE); + #endif + (void)stmCtx; + } + #define STM32_HASH_CLOCK_DISABLE(ctx) wc_Stm32_Hash_Clock_Disable(ctx) +#endif + +/* STM32 Port Internal Functions */ +static WC_INLINE void wc_Stm32_Hash_SaveContext(STM32_HASH_Context* ctx) +{ + int i; + + /* save context registers */ + ctx->HASH_IMR = HASH->IMR; + ctx->HASH_STR = HASH->STR; + ctx->HASH_CR = HASH->CR; + for (i=0; iHASH_CSR[i] = HASH->CSR[i]; + } +} + +static WC_INLINE int wc_Stm32_Hash_RestoreContext(STM32_HASH_Context* ctx) +{ + int i; + + if (ctx->HASH_CR != 0) { + /* restore context registers */ + HASH->IMR = ctx->HASH_IMR; + HASH->STR = ctx->HASH_STR; + HASH->CR = ctx->HASH_CR; + + /* Initialize the hash processor */ + HASH->CR |= HASH_CR_INIT; + + /* continue restoring context registers */ + for (i=0; iCSR[i] = ctx->HASH_CSR[i]; + } + return 1; + } + return 0; +} + +static WC_INLINE void wc_Stm32_Hash_GetDigest(byte* hash, int digestSize) +{ + word32 digest[HASH_MAX_DIGEST/sizeof(word32)]; + + /* get digest result */ + digest[0] = HASH->HR[0]; + digest[1] = HASH->HR[1]; + digest[2] = HASH->HR[2]; + digest[3] = HASH->HR[3]; + if (digestSize >= 20) { + digest[4] = HASH->HR[4]; + #ifdef HASH_DIGEST + if (digestSize >= 28) { + digest[5] = HASH_DIGEST->HR[5]; + digest[6] = HASH_DIGEST->HR[6]; + if (digestSize == 32) + digest[7] = HASH_DIGEST->HR[7]; + } + #endif + } + + ByteReverseWords(digest, digest, digestSize); + + XMEMCPY(hash, digest, digestSize); +} + + +/* STM32 Port Exposed Functions */ +static WC_INLINE int wc_Stm32_Hash_WaitDone(void) +{ + /* wait until hash hardware is not busy */ + int timeout = 0; + while ((HASH->SR & HASH_SR_BUSY) && ++timeout < STM32_HASH_TIMEOUT) { + + } + /* verify timeout did not occur */ + if (timeout >= STM32_HASH_TIMEOUT) { + return WC_TIMEOUT_E; + } + return 0; +} + + +void wc_Stm32_Hash_Init(STM32_HASH_Context* stmCtx) +{ + /* clear context */ + XMEMSET(stmCtx, 0, sizeof(STM32_HASH_Context)); +} + +int wc_Stm32_Hash_Update(STM32_HASH_Context* stmCtx, word32 algo, + const byte* data, int len) +{ + int ret = 0; + byte* local = (byte*)stmCtx->buffer; + int wroteToFifo = 0; + + /* check that internal buffLen is valid */ + if (stmCtx->buffLen >= STM32_HASH_REG_SIZE) { + return BUFFER_E; + } + + /* turn on hash clock */ + STM32_HASH_CLOCK_ENABLE(stmCtx); + + /* restore hash context or init as new hash */ + if (wc_Stm32_Hash_RestoreContext(stmCtx) == 0) { + /* reset the control register */ + HASH->CR &= ~(HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); + + /* configure algorithm, mode and data type */ + HASH->CR |= (algo | HASH_ALGOMODE_HASH | HASH_DATATYPE_8B); + + /* reset HASH processor */ + HASH->CR |= HASH_CR_INIT; + } + + /* write 4-bytes at a time into FIFO */ + while (len) { + word32 add = min(len, STM32_HASH_REG_SIZE - stmCtx->buffLen); + XMEMCPY(&local[stmCtx->buffLen], data, add); + + stmCtx->buffLen += add; + data += add; + len -= add; + + if (stmCtx->buffLen == STM32_HASH_REG_SIZE) { + wroteToFifo = 1; + HASH->DIN = *(word32*)stmCtx->buffer; + + stmCtx->loLen += STM32_HASH_REG_SIZE; + stmCtx->buffLen = 0; + } + } + + if (wroteToFifo) { + /* save hash state for next operation */ + wc_Stm32_Hash_SaveContext(stmCtx); + } + + /* turn off hash clock */ + STM32_HASH_CLOCK_DISABLE(stmCtx); + + return ret; +} + +int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo, + byte* hash, int digestSize) +{ + int ret = 0; + word32 nbvalidbitsdata = 0; + + /* turn on hash clock */ + STM32_HASH_CLOCK_ENABLE(stmCtx); + + /* restore hash state */ + wc_Stm32_Hash_RestoreContext(stmCtx); + + /* finish reading any trailing bytes into FIFO */ + if (stmCtx->buffLen > 0) { + HASH->DIN = *(word32*)stmCtx->buffer; + stmCtx->loLen += stmCtx->buffLen; + } + + /* calculate number of valid bits in last word */ + nbvalidbitsdata = 8 * (stmCtx->loLen % STM32_HASH_REG_SIZE); + HASH->STR &= ~HASH_STR_NBW; + HASH->STR |= nbvalidbitsdata; + + /* start hash processor */ + HASH->STR |= HASH_STR_DCAL; + + /* wait for hash done */ + ret = wc_Stm32_Hash_WaitDone(); + if (ret == 0) { + /* read message digest */ + wc_Stm32_Hash_GetDigest(hash, digestSize); + } + + /* turn off hash clock */ + STM32_HASH_CLOCK_DISABLE(stmCtx); + + return ret; +} + +#endif /* STM32_HASH */ + + +#ifdef STM32_CRYPTO + +#ifndef NO_AES +#ifdef WOLFSSL_STM32_CUBEMX +int wc_Stm32_Aes_Init(Aes* aes, CRYP_HandleTypeDef* hcryp) +{ + int ret; + word32 keySize; + + ret = wc_AesGetKeySize(aes, &keySize); + if (ret != 0) + return ret; + + XMEMSET(hcryp, 0, sizeof(CRYP_HandleTypeDef)); + switch (keySize) { + case 16: /* 128-bit key */ + hcryp->Init.KeySize = CRYP_KEYSIZE_128B; + break; + #ifdef CRYP_KEYSIZE_192B + case 24: /* 192-bit key */ + hcryp->Init.KeySize = CRYP_KEYSIZE_192B; + break; + #endif + 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 = (STM_CRYPT_TYPE*)aes->key; +#ifdef STM32_HAL_V2 + hcryp->Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE; +#endif + + return 0; +} + +#else /* STD_PERI_LIB */ + +int wc_Stm32_Aes_Init(Aes* aes, CRYP_InitTypeDef* cryptInit, + CRYP_KeyInitTypeDef* keyInit) +{ + int ret; + word32 keySize; + word32* aes_key; + + ret = wc_AesGetKeySize(aes, &keySize); + if (ret != 0) + return ret; + + aes_key = aes->key; + + /* crypto structure initialization */ + CRYP_KeyStructInit(keyInit); + CRYP_StructInit(cryptInit); + + /* load key into correct registers */ + switch (keySize) { + case 16: /* 128-bit key */ + cryptInit->CRYP_KeySize = CRYP_KeySize_128b; + keyInit->CRYP_Key2Left = aes_key[0]; + keyInit->CRYP_Key2Right = aes_key[1]; + keyInit->CRYP_Key3Left = aes_key[2]; + keyInit->CRYP_Key3Right = aes_key[3]; + break; + + case 24: /* 192-bit key */ + cryptInit->CRYP_KeySize = CRYP_KeySize_192b; + keyInit->CRYP_Key1Left = aes_key[0]; + keyInit->CRYP_Key1Right = aes_key[1]; + keyInit->CRYP_Key2Left = aes_key[2]; + keyInit->CRYP_Key2Right = aes_key[3]; + keyInit->CRYP_Key3Left = aes_key[4]; + keyInit->CRYP_Key3Right = aes_key[5]; + break; + + case 32: /* 256-bit key */ + cryptInit->CRYP_KeySize = CRYP_KeySize_256b; + keyInit->CRYP_Key0Left = aes_key[0]; + keyInit->CRYP_Key0Right = aes_key[1]; + keyInit->CRYP_Key1Left = aes_key[2]; + keyInit->CRYP_Key1Right = aes_key[3]; + keyInit->CRYP_Key2Left = aes_key[4]; + keyInit->CRYP_Key2Right = aes_key[5]; + keyInit->CRYP_Key3Left = aes_key[6]; + keyInit->CRYP_Key3Right = aes_key[7]; + break; + + default: + break; + } + cryptInit->CRYP_DataType = CRYP_DataType_8b; + + return 0; +} +#endif /* WOLFSSL_STM32_CUBEMX */ +#endif /* !NO_AES */ +#endif /* STM32_CRYPTO */ + +#ifdef WOLFSSL_STM32_PKA +#include +#include +#include + +extern PKA_HandleTypeDef hpka; + +/* Reverse array in memory (in place) */ +#ifdef HAVE_ECC +#include + +/* convert from mp_int to STM32 PKA HAL 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 zeros + * so that result array has 32 bytes, same as modulus (sz). + */ +static int stm32_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) +{ + int res; + int szbin; + int offset; + + if (!a || !dst || (sz < 0)) + return -1; + + /* check how many bytes are in the mp_int */ + szbin = mp_unsigned_bin_size(a); + if ((szbin < 0) || (szbin > sz)) + return -1; + + /* compute offset from dst */ + offset = sz - szbin; + if (offset < 0) + offset = 0; + if (offset > sz) + offset = sz; + + /* add leading zeroes */ + if (offset) + XMEMSET(dst, 0, offset); + + /* convert mp_int to array of bytes */ + res = mp_to_unsigned_bin(a, dst + offset); + return res; +} + +/* ECC specs in lsbyte at lowest address format for direct use by STM32_PKA PKHA driver functions */ +#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) +#define ECC192 +#endif +#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) +#define ECC224 +#endif +#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) +#define ECC256 +#endif +#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) +#define ECC384 +#endif + +/* STM32 PKA supports up to 640bit numbers */ +#define STM32_MAX_ECC_SIZE (80) + + +/* P-192 */ +#ifdef ECC192 +#define ECC192_KEYSIZE (24) +static const uint8_t stm32_ecc192_prime[ECC192_KEYSIZE] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; +static const uint32_t stm32_ecc192_coef_sign = 1U; + +static const uint8_t stm32_ecc192_coef[ECC192_KEYSIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 +}; + +static const uint8_t stm32_ecc192_pointX[ECC192_KEYSIZE] = { + 0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, + 0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00, + 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12 +}; + +const uint8_t stm32_ecc192_pointY[ECC192_KEYSIZE] = { + 0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78, + 0x63, 0x10, 0x11, 0xED, 0x6B, 0x24, 0xCD, 0xD5, + 0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11 +}; + +const uint8_t stm32_ecc192_order[ECC192_KEYSIZE] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36, + 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31 +}; +const uint32_t stm32_ecc192_cofactor = 1U; + +#endif /* ECC192 */ + +/* P-224 */ +#ifdef ECC224 +#define ECC224_KEYSIZE (28) +static const uint8_t stm32_ecc224_prime[ECC224_KEYSIZE] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 +}; +static const uint32_t stm32_ecc224_coef_sign = 1U; + +static const uint8_t stm32_ecc224_coef[ECC224_KEYSIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03 +}; + +static const uint8_t stm32_ecc224_pointX[ECC224_KEYSIZE] = { + 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, + 0x32, 0x13, 0x90, 0xB9, 0x4A, 0x03, 0xC1, 0xD3, + 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6, + 0x11, 0x5C, 0x1D, 0x21 +}; + +const uint8_t stm32_ecc224_pointY[ECC224_KEYSIZE] = { + 0xBD, 0x37, 0x63, 0x88, 0xB5, 0xF7, 0x23, 0xFB, + 0x4C, 0x22, 0xDF, 0xE6, 0xCD, 0x43, 0x75, 0xA0, + 0x5A, 0x07, 0x47, 0x64, 0x44, 0xD5, 0x81, 0x99, + 0x85, 0x00, 0x7E, 0x34 +}; + +const uint8_t stm32_ecc224_order[ECC224_KEYSIZE] = { +}; +const uint32_t stm32_ecc224_cofactor = 1U; + +#endif /* ECC224 */ + +/* P-256 */ +#ifdef ECC256 +#define ECC256_KEYSIZE (32) + +static const uint8_t stm32_ecc256_prime[ECC256_KEYSIZE] = { + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; +static const uint32_t stm32_ecc256_coef_sign = 1U; + +static const uint8_t stm32_ecc256_coef[ECC256_KEYSIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 +}; + +static const uint8_t stm32_ecc256_pointX[ECC256_KEYSIZE] = { + 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 uint8_t stm32_ecc256_pointY[ECC256_KEYSIZE] = { + 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 +}; + +const uint8_t stm32_ecc256_order[ECC256_KEYSIZE] = { + 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 uint32_t stm32_ecc256_cofactor = 1U; + +#endif /* ECC256 */ + +/* P-384 */ +#ifdef ECC384 +#define ECC384_KEYSIZE (48) + +static const uint8_t stm32_ecc384_prime[ECC384_KEYSIZE] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const uint32_t stm32_ecc384_coef_sign = 1U; + +static const uint8_t stm32_ecc384_coef[ECC384_KEYSIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 +}; + +static const uint8_t stm32_ecc384_pointX[ECC384_KEYSIZE] = { + 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, + 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74, + 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98, + 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, + 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C, + 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7, +}; + +const uint8_t stm32_ecc384_pointY[ECC384_KEYSIZE] = { + 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, + 0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29, + 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C, + 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, + 0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D, + 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F, +}; + +const uint8_t stm32_ecc384_order[ECC384_KEYSIZE] = { +}; +const uint32_t stm32_ecc384_cofactor = 1U; + +#endif /* ECC384 */ +static int stm32_get_ecc_specs(const uint8_t **prime, const uint8_t **coef, + const uint32_t **coef_sign, const uint8_t **GenPointX, const uint8_t **GenPointY, + const uint8_t **order, int size) +{ + switch(size) { + case 32: + *prime = stm32_ecc256_prime; + *coef = stm32_ecc256_coef; + *GenPointX = stm32_ecc256_pointX; + *GenPointY = stm32_ecc256_pointY; + *coef_sign = &stm32_ecc256_coef_sign; + *order = stm32_ecc256_order; + break; +#ifdef ECC224 + case 28: + *prime = stm32_ecc224_prime; + *coef = stm32_ecc224_coef; + *GenPointX = stm32_ecc224_pointX; + *GenPointY = stm32_ecc224_pointY; + *coef_sign = &stm32_ecc224_coef; + break; +#endif +#ifdef ECC192 + case 24: + *prime = stm32_ecc192_prime; + *coef = stm32_ecc192_coef; + *GenPointX = stm32_ecc192_pointX; + *GenPointY = stm32_ecc192_pointY; + *coef_sign = &stm32_ecc192_coef; + break; +#endif +#ifdef ECC384 + case 48: + *prime = stm32_ecc384_prime; + *coef = stm32_ecc384_coef; + *GenPointX = stm32_ecc384_pointX; + *GenPointY = stm32_ecc384_pointY; + *coef_sign = &stm32_ecc384_coef; + break; +#endif + default: + return -1; + } + return 0; +} + + +/** + Perform a point multiplication (timing resistant) + k The scalar to multiply by + G The base point + R [out] Destination for kG + modulus The modulus of the field the ECC curve is in + map Boolean whether to map back to affine or not + (1==map, 0 == leave in projective) + return MP_OKAY on success +*/ +int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int *modulus, int map, void* heap) +{ + PKA_ECCMulInTypeDef pka_mul; + PKA_ECCMulOutTypeDef pka_mul_res; + uint8_t size; + int szModulus; + int szkbin; + int status; + int res; + uint8_t Gxbin[STM32_MAX_ECC_SIZE]; + uint8_t Gybin[STM32_MAX_ECC_SIZE]; + uint8_t kbin[STM32_MAX_ECC_SIZE]; + uint8_t PtXbin[STM32_MAX_ECC_SIZE]; + uint8_t PtYbin[STM32_MAX_ECC_SIZE]; + const uint8_t *prime, *coef, *gen_x, *gen_y, *order; + const uint32_t *coef_sign; + (void)a; + (void)heap; + XMEMSET(&pka_mul, 0x00, sizeof(PKA_ECCMulInTypeDef)); + XMEMSET(&pka_mul_res, 0x00, sizeof(PKA_ECCMulOutTypeDef)); + pka_mul_res.ptX = PtXbin; + pka_mul_res.ptY = PtYbin; + + if (k == NULL || G == NULL || R == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + szModulus = mp_unsigned_bin_size(modulus); + szkbin = mp_unsigned_bin_size(k); + + res = stm32_get_from_mp_int(kbin, k, szkbin); + if (res == MP_OKAY) + res = stm32_get_from_mp_int(Gxbin, G->x, szModulus); + if (res == MP_OKAY) + res = stm32_get_from_mp_int(Gybin, G->y, szModulus); + + if (res != MP_OKAY) + return res; + + size = (uint8_t)szModulus; + /* find STM32_PKA friendly parameters for the selected curve */ + if (0 != stm32_get_ecc_specs(&prime, &coef, &coef_sign, &gen_x, &gen_y, &order, size)) { + return ECC_BAD_ARG_E; + } + (void)order; + + pka_mul.modulusSize = szModulus; + pka_mul.coefSign = *coef_sign; + pka_mul.coefA = coef; + pka_mul.modulus = prime; + pka_mul.pointX = Gxbin; + pka_mul.pointY = Gybin; + pka_mul.scalarMulSize = size; + pka_mul.scalarMul = kbin; + + status = HAL_PKA_ECCMul(&hpka, &pka_mul, HAL_MAX_DELAY); + if (status != HAL_OK) { + return WC_HW_E; + } + pka_mul_res.ptX = Gxbin; + pka_mul_res.ptY = Gybin; + HAL_PKA_ECCMul_GetResult(&hpka, &pka_mul_res); + res = mp_read_unsigned_bin(R->x, Gxbin, size); + if (res == MP_OKAY) { + res = mp_read_unsigned_bin(R->y, Gybin, size); +#ifndef WOLFSSL_SP_MATH + /* 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; +#endif + } + if (res == MP_OKAY) + res = mp_set(R->z, 1); + HAL_PKA_RAMReset(&hpka); + return res; +} + +int stm32_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, + word32 hashlen, int* res, ecc_key* key) +{ + PKA_ECDSAVerifInTypeDef pka_ecc; + uint8_t size; + int szModulus; + int szrbin; + int status; + uint8_t Rbin[STM32_MAX_ECC_SIZE]; + uint8_t Sbin[STM32_MAX_ECC_SIZE]; + uint8_t Qxbin[STM32_MAX_ECC_SIZE]; + uint8_t Qybin[STM32_MAX_ECC_SIZE]; + uint8_t Hashbin[STM32_MAX_ECC_SIZE]; + uint8_t privKeybin[STM32_MAX_ECC_SIZE]; + const uint8_t *prime, *coef, *gen_x, *gen_y, *order; + const uint32_t *coef_sign; + XMEMSET(&pka_ecc, 0x00, sizeof(PKA_ECDSAVerifInTypeDef)); + + if (r == NULL || s == NULL || hash == NULL || res == NULL || key == NULL) { + return ECC_BAD_ARG_E; + } + *res = 0; + + szModulus = mp_unsigned_bin_size(key->pubkey.x); + szrbin = mp_unsigned_bin_size(r); + + status = stm32_get_from_mp_int(Rbin, r, szrbin); + if (status == MP_OKAY) + status = stm32_get_from_mp_int(Sbin, s, szrbin); + if (status == MP_OKAY) + status = stm32_get_from_mp_int(Qxbin, key->pubkey.x, szModulus); + if (status == MP_OKAY) + status = stm32_get_from_mp_int(Qybin, key->pubkey.y, szModulus); + if (status == MP_OKAY) + status = stm32_get_from_mp_int(privKeybin, &key->k, szModulus); + if (status != MP_OKAY) + return status; + + size = (uint8_t)szModulus; + /* find parameters for the selected curve */ + if (0 != stm32_get_ecc_specs(&prime, &coef, &coef_sign, &gen_x, &gen_y, &order, size)) { + return ECC_BAD_ARG_E; + } + + + pka_ecc.primeOrderSize = size; + pka_ecc.modulusSize = size; + pka_ecc.coefSign = *coef_sign; + pka_ecc.coef = coef; + pka_ecc.modulus = prime; + pka_ecc.basePointX = gen_x; + pka_ecc.basePointY = gen_y; + pka_ecc.primeOrder = order; + + pka_ecc.pPubKeyCurvePtX = Qxbin; + pka_ecc.pPubKeyCurvePtY = Qybin; + pka_ecc.RSign = Rbin; + pka_ecc.SSign = Sbin; + XMEMSET(Hashbin, 0, STM32_MAX_ECC_SIZE); + XMEMCPY(Hashbin + (size - hashlen), hash, hashlen); + pka_ecc.hash = Hashbin; + + status = HAL_PKA_ECDSAVerif(&hpka, &pka_ecc, HAL_MAX_DELAY); + if (status != HAL_OK) { + HAL_PKA_RAMReset(&hpka); + return WC_HW_E; + } + *res = HAL_PKA_ECDSAVerif_IsValidSignature(&hpka); + HAL_PKA_RAMReset(&hpka); + return status; +} + +int stm32_ecc_sign_hash_ex(const byte* hash, word32 hashlen, WC_RNG* rng, + ecc_key* key, mp_int *r, mp_int *s) +{ + PKA_ECDSASignInTypeDef pka_ecc; + PKA_ECDSASignOutTypeDef pka_ecc_out; + int size; + int status; + mp_int gen_k; + mp_int order_mp; + uint8_t Keybin[STM32_MAX_ECC_SIZE]; + uint8_t Intbin[STM32_MAX_ECC_SIZE]; + uint8_t Rbin[STM32_MAX_ECC_SIZE]; + uint8_t Sbin[STM32_MAX_ECC_SIZE]; + uint8_t Hashbin[STM32_MAX_ECC_SIZE]; + const uint8_t *prime, *coef, *gen_x, *gen_y, *order; + const uint32_t *coef_sign; + XMEMSET(&pka_ecc, 0x00, sizeof(PKA_ECDSASignInTypeDef)); + XMEMSET(&pka_ecc, 0x00, sizeof(PKA_ECDSASignOutTypeDef)); + + if (r == NULL || s == NULL || hash == NULL || key == NULL) { + return ECC_BAD_ARG_E; + } + + mp_init(&gen_k); + mp_init(&order_mp); + + size = mp_unsigned_bin_size(key->pubkey.x); + + status = stm32_get_from_mp_int(Keybin, &key->k, size); + if (status != MP_OKAY) + return status; + + /* find parameters for the selected curve */ + if (0 != stm32_get_ecc_specs(&prime, &coef, &coef_sign, &gen_x, &gen_y, &order, size)) { + return ECC_BAD_ARG_E; + } + + status = mp_read_unsigned_bin(&order_mp, order, size); + if (status == MP_OKAY) + status = wc_ecc_gen_k(rng, size, &gen_k, &order_mp); + if (status == MP_OKAY) + status = stm32_get_from_mp_int(Intbin, &gen_k, size); + if (status != MP_OKAY) + return status; + + pka_ecc.primeOrderSize = size; + pka_ecc.modulusSize = size; + pka_ecc.coefSign = *coef_sign; + pka_ecc.coef = coef; + pka_ecc.modulus = prime; + pka_ecc.basePointX = gen_x; + pka_ecc.basePointY = gen_y; + pka_ecc.primeOrder = order; + + XMEMSET(Hashbin, 0, STM32_MAX_ECC_SIZE); + XMEMCPY(Hashbin + (size - hashlen), hash, hashlen); + pka_ecc.hash = Hashbin; + pka_ecc.integer = Intbin; + pka_ecc.privateKey = Keybin; + + /* Assign R, S static buffers */ + pka_ecc_out.RSign = Rbin; + pka_ecc_out.SSign = Sbin; + + status = HAL_PKA_ECDSASign(&hpka, &pka_ecc, HAL_MAX_DELAY); + if (status != HAL_OK) { + HAL_PKA_RAMReset(&hpka); + return WC_HW_E; + } + HAL_PKA_ECDSASign_GetResult(&hpka, &pka_ecc_out, NULL); + status = mp_read_unsigned_bin(r, pka_ecc_out.RSign, size); + if (status == MP_OKAY) + status = mp_read_unsigned_bin(s, pka_ecc_out.SSign, size); + HAL_PKA_RAMReset(&hpka); + return status; +} + +#endif /* HAVE_ECC */ +#endif /* WOLFSSL_STM32_PKA */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/st/stsafe.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/st/stsafe.c new file mode 100644 index 000000000..239b159ae --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/st/stsafe.c @@ -0,0 +1,566 @@ +/* stsafe.c + * + * Copyright (C) 2006-2020 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 + */ + +#include +#include + +#ifndef STSAFE_INTERFACE_PRINTF +#define STSAFE_INTERFACE_PRINTF(...) +#endif + +#ifdef WOLFSSL_STSAFEA100 + +int SSL_STSAFE_LoadDeviceCertificate(byte** pRawCertificate, + word32* pRawCertificateLen) +{ + int err; + + if (pRawCertificate == NULL || pRawCertificateLen == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef USE_STSAFE_VERBOSE + WOLFSSL_MSG("SSL_STSAFE_LoadDeviceCertificate"); +#endif + + /* Try reading device certificate from ST-SAFE Zone 0 */ + err = stsafe_interface_read_device_certificate_raw( + pRawCertificate, (uint32_t*)pRawCertificateLen); + if (err == STSAFE_A_OK) { + #if 0 + /* example for loading into WOLFSSL_CTX */ + err = wolfSSL_CTX_use_certificate_buffer(ctx, + *pRawCertificate, *pRawCertificateLen, SSL_FILETYPE_ASN1); + if (err != WOLFSSL_SUCCESS) { + /* failed */ + } + /* can free now */ + XFREE(*pRawCertificate, NULL, DYNAMIC_TEMP_BUFFER); + *pRawCertificate = NULL; + #endif + } + else { + err = WC_HW_E; + } + + return err; +} + +#ifdef HAVE_PK_CALLBACKS + +/** + * \brief Key Gen Callback (used by TLS server) + */ +int SSL_STSAFE_CreateKeyCb(WOLFSSL* ssl, ecc_key* key, word32 keySz, + int ecc_curve, void* ctx) +{ + int err; + byte pubKeyRaw[STSAFE_MAX_PUBKEY_RAW_LEN]; + StSafeA_KeySlotNumber slot; + StSafeA_CurveId curve_id; + + (void)ssl; + (void)ctx; + +#ifdef USE_STSAFE_VERBOSE + WOLFSSL_MSG("CreateKeyCb: STSAFE"); +#endif + + /* get curve */ + curve_id = stsafe_get_ecc_curve_id(ecc_curve); + + /* generate new ephemeral key on device */ + err = stsafe_interface_create_key(&slot, curve_id, (uint8_t*)&pubKeyRaw[0]); + if (err != STSAFE_A_OK) { + #ifdef USE_STSAFE_VERBOSE + STSAFE_INTERFACE_PRINTF("stsafe_interface_create_key error: %d\n", err); + #endif + err = WC_HW_E; + return err; + } + + /* load generated public key into key, used by wolfSSL */ + err = wc_ecc_import_unsigned(key, &pubKeyRaw[0], &pubKeyRaw[keySz], + NULL, ecc_curve); + + return err; +} + +/** + * \brief Verify Peer Cert Callback. + */ +int SSL_STSAFE_VerifyPeerCertCb(WOLFSSL* ssl, + const unsigned char* sig, unsigned int sigSz, + const unsigned char* hash, unsigned int hashSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx) +{ + int err; + byte sigRS[STSAFE_MAX_SIG_LEN]; + byte *r, *s; + word32 r_len = STSAFE_MAX_SIG_LEN/2, s_len = STSAFE_MAX_SIG_LEN/2; + byte pubKeyX[STSAFE_MAX_PUBKEY_RAW_LEN/2]; + byte pubKeyY[STSAFE_MAX_PUBKEY_RAW_LEN/2]; + word32 pubKeyX_len = sizeof(pubKeyX); + word32 pubKeyY_len = sizeof(pubKeyY); + ecc_key key; + word32 inOutIdx = 0; + StSafeA_CurveId curve_id; + int ecc_curve; + + (void)ssl; + (void)ctx; + +#ifdef USE_STSAFE_VERBOSE + WOLFSSL_MSG("VerifyPeerCertCB: STSAFE"); +#endif + + err = wc_ecc_init(&key); + if (err != 0) { + return err; + } + + /* Decode the public key */ + err = wc_EccPublicKeyDecode(keyDer, &inOutIdx, &key, keySz); + if (err == 0) { + /* Extract Raw X and Y coordinates of the public key */ + err = wc_ecc_export_public_raw(&key, pubKeyX, &pubKeyX_len, + pubKeyY, &pubKeyY_len); + } + if (err == 0) { + int key_sz; + + /* determine curve */ + ecc_curve = key.dp->id; + curve_id = stsafe_get_ecc_curve_id(ecc_curve); + key_sz = stsafe_get_key_size(curve_id); + + /* Extract R and S from signature */ + XMEMSET(sigRS, 0, sizeof(sigRS)); + r = &sigRS[0]; + s = &sigRS[key_sz]; + err = wc_ecc_sig_to_rs(sig, sigSz, r, &r_len, s, &s_len); + (void)r_len; + (void)s_len; + } + + if (err == 0) { + /* Verify signature */ + err = stsafe_interface_verify(curve_id, (uint8_t*)hash, sigRS, + pubKeyX, pubKeyY, (int32_t*)result); + if (err != STSAFE_A_OK) { + #ifdef USE_STSAFE_VERBOSE + STSAFE_INTERFACE_PRINTF("stsafe_interface_verify error: %d\n", err); + #endif + err = WC_HW_E; + } + } + + wc_ecc_free(&key); + return err; +} + +/** + * \brief Sign Certificate Callback. + */ +int SSL_STSAFE_SignCertificateCb(WOLFSSL* ssl, const byte* in, + word32 inSz, byte* out, word32* outSz, + const byte* key, word32 keySz, void* ctx) +{ + int err; + byte digest[STSAFE_MAX_KEY_LEN]; + byte sigRS[STSAFE_MAX_SIG_LEN]; + byte *r, *s; + StSafeA_CurveId curve_id; + int key_sz; + + (void)ssl; + (void)ctx; + +#ifdef USE_STSAFE_VERBOSE + WOLFSSL_MSG("SignCertificateCb: STSAFE"); +#endif + + curve_id = stsafe_get_curve_mode(); + key_sz = stsafe_get_key_size(curve_id); + + /* Build input digest */ + if (inSz > key_sz) + inSz = key_sz; + XMEMSET(&digest[0], 0, sizeof(digest)); + XMEMCPY(&digest[key_sz - inSz], in, inSz); + + /* Sign using slot 0: Result is R then S */ + /* Sign will always use the curve type in slot 0 (the TLS curve needs to match) */ + XMEMSET(sigRS, 0, sizeof(sigRS)); + err = stsafe_interface_sign(STSAFE_A_SLOT_0, curve_id, digest, sigRS); + if (err != STSAFE_A_OK) { + #ifdef USE_STSAFE_VERBOSE + STSAFE_INTERFACE_PRINTF("stsafe_interface_sign error: %d\n", err); + #endif + err = WC_HW_E; + return err; + } + + /* Convert R and S to signature */ + r = &sigRS[0]; + s = &sigRS[key_sz]; + err = wc_ecc_rs_raw_to_sig((const byte*)r, key_sz, (const byte*)s, key_sz, + out, outSz); + if (err != 0) { + #ifdef USE_STSAFE_VERBOSE + WOLFSSL_MSG("Error converting RS to Signature"); + #endif + } + + return err; +} + + +/** + * \brief Create pre master secret using peer's public key and self private key. + */ +int SSL_STSAFE_SharedSecretCb(WOLFSSL* ssl, ecc_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx) +{ + int err; + byte otherKeyX[STSAFE_MAX_KEY_LEN]; + byte otherKeyY[STSAFE_MAX_KEY_LEN]; + word32 otherKeyX_len = sizeof(otherKeyX); + word32 otherKeyY_len = sizeof(otherKeyY); + byte pubKeyRaw[STSAFE_MAX_PUBKEY_RAW_LEN]; + StSafeA_KeySlotNumber slot; + StSafeA_CurveId curve_id; + ecc_key tmpKey; + int ecc_curve; + int key_sz; + + (void)ssl; + (void)ctx; + +#ifdef USE_STSAFE_VERBOSE + WOLFSSL_MSG("SharedSecretCb: STSAFE"); +#endif + + err = wc_ecc_init(&tmpKey); + if (err != 0) { + return err; + } + + /* set curve */ + ecc_curve = otherKey->dp->id; + curve_id = stsafe_get_ecc_curve_id(ecc_curve); + key_sz = stsafe_get_key_size(curve_id); + + /* for client: create and export public key */ + if (side == WOLFSSL_CLIENT_END) { + /* Export otherKey raw X and Y */ + err = wc_ecc_export_public_raw(otherKey, + &otherKeyX[0], (word32*)&otherKeyX_len, + &otherKeyY[0], (word32*)&otherKeyY_len); + if (err != 0) { + return err; + } + + err = stsafe_interface_create_key(&slot, curve_id, (uint8_t*)&pubKeyRaw[0]); + if (err != STSAFE_A_OK) { + #ifdef USE_STSAFE_VERBOSE + STSAFE_INTERFACE_PRINTF("stsafe_interface_create_key error: %d\n", err); + #endif + err = WC_HW_E; + return err; + } + + /* convert raw unsigned public key to X.963 format for TLS */ + err = wc_ecc_init(&tmpKey); + if (err == 0) { + err = wc_ecc_import_unsigned(&tmpKey, &pubKeyRaw[0], &pubKeyRaw[key_sz], + NULL, ecc_curve); + if (err == 0) { + err = wc_ecc_export_x963(&tmpKey, pubKeyDer, pubKeySz); + } + wc_ecc_free(&tmpKey); + } + } + /* for server: import public key */ + else if (side == WOLFSSL_SERVER_END) { + /* import peer's key and export as raw unsigned for hardware */ + err = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, &tmpKey, ecc_curve); + if (err == 0) { + err = wc_ecc_export_public_raw(&tmpKey, otherKeyX, &otherKeyX_len, + otherKeyY, &otherKeyY_len); + } + } + else { + err = BAD_FUNC_ARG; + } + + wc_ecc_free(&tmpKey); + + if (err != 0) { + return err; + } + + /* Compute shared secret */ + err = stsafe_interface_shared_secret(curve_id, &otherKeyX[0], &otherKeyY[0], + out, (int32_t*)outlen); + if (err != STSAFE_A_OK) { + #ifdef USE_STSAFE_VERBOSE + STSAFE_INTERFACE_PRINTF("stsafe_interface_shared_secret error: %d\n", err); + #endif + err = WC_HW_E; + } + + return err; +} + +int SSL_STSAFE_SetupPkCallbacks(WOLFSSL_CTX* ctx) +{ + wolfSSL_CTX_SetEccKeyGenCb(ctx, SSL_STSAFE_CreateKeyCb); + wolfSSL_CTX_SetEccSignCb(ctx, SSL_STSAFE_SignCertificateCb); + wolfSSL_CTX_SetEccVerifyCb(ctx, SSL_STSAFE_VerifyPeerCertCb); + wolfSSL_CTX_SetEccSharedSecretCb(ctx, SSL_STSAFE_SharedSecretCb); + wolfSSL_CTX_SetDevId(ctx, 0); /* enables wolfCrypt `wc_ecc_*` ST-Safe use */ + return 0; +} + +int SSL_STSAFE_SetupPkCallbackCtx(WOLFSSL* ssl, void* user_ctx) +{ + wolfSSL_SetEccKeyGenCtx(ssl, user_ctx); + wolfSSL_SetEccSharedSecretCtx(ssl, user_ctx); + wolfSSL_SetEccSignCtx(ssl, user_ctx); + wolfSSL_SetEccVerifyCtx(ssl, user_ctx); + return 0; +} + + +#endif /* HAVE_PK_CALLBACKS */ + +#ifdef WOLF_CRYPTO_CB + +int wolfSSL_STSAFE_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) +{ + int rc = CRYPTOCB_UNAVAILABLE; + wolfSTSAFE_CryptoCb_Ctx* stsCtx = (wolfSTSAFE_CryptoCb_Ctx*)ctx; + + if (info == NULL || ctx == NULL) + return BAD_FUNC_ARG; + + (void)devId; + (void)stsCtx; + + if (info->algo_type == WC_ALGO_TYPE_SEED) { + /* use the STSAFE hardware for RNG seed */ + #if !defined(WC_NO_RNG) && defined(USE_STSAFE_RNG_SEED) + while (info->seed.sz > 0) { + rc = stsafe_interface_getrandom(info->seed.seed, info->seed.sz); + if (rc < 0) { + return rc; + } + info->seed.seed += rc; + info->seed.sz -= rc; + } + rc = 0; + #else + rc = CRYPTOCB_UNAVAILABLE; + #endif + } +#ifdef HAVE_ECC + else if (info->algo_type == WC_ALGO_TYPE_PK) { + #ifdef USE_STSAFE_VERBOSE + STSAFE_INTERFACE_PRINTF("STSAFE Pk: Type %d\n", info->pk.type); + #endif + + if (info->pk.type == WC_PK_TYPE_EC_KEYGEN) { + byte pubKeyRaw[STSAFE_MAX_PUBKEY_RAW_LEN]; + StSafeA_KeySlotNumber slot; + StSafeA_CurveId curve_id; + int ecc_curve, key_sz; + + WOLFSSL_MSG("STSAFE: ECC KeyGen"); + + /* get curve */ + ecc_curve = info->pk.eckg.curveId; + curve_id = stsafe_get_ecc_curve_id(ecc_curve); + key_sz = stsafe_get_key_size(curve_id); + + /* generate new ephemeral key on device */ + rc = stsafe_interface_create_key(&slot, curve_id, + (uint8_t*)pubKeyRaw); + if (rc != STSAFE_A_OK) { + #ifdef USE_STSAFE_VERBOSE + STSAFE_INTERFACE_PRINTF("stsafe_interface_create_key error: %d\n", rc); + #endif + rc = WC_HW_E; + return rc; + } + + /* load generated public key into key, used by wolfSSL */ + rc = wc_ecc_import_unsigned(info->pk.eckg.key, pubKeyRaw, + &pubKeyRaw[key_sz], NULL, ecc_curve); + } + else if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) { + byte digest[STSAFE_MAX_KEY_LEN]; + byte sigRS[STSAFE_MAX_SIG_LEN]; + byte *r, *s; + StSafeA_CurveId curve_id; + word32 inSz = info->pk.eccsign.inlen; + int key_sz; + + WOLFSSL_MSG("STSAFE: ECC Sign"); + + curve_id = stsafe_get_curve_mode(); + key_sz = stsafe_get_key_size(curve_id); + + /* truncate input to match key size */ + if (inSz > key_sz) + inSz = key_sz; + + /* Build input digest */ + XMEMSET(&digest[0], 0, sizeof(digest)); + XMEMCPY(&digest[key_sz - inSz], info->pk.eccsign.in, inSz); + + /* Sign using slot 0: Result is R then S */ + /* Sign will always use the curve type in slot 0 + (the TLS curve needs to match) */ + XMEMSET(sigRS, 0, sizeof(sigRS)); + rc = stsafe_interface_sign(STSAFE_A_SLOT_0, curve_id, + (uint8_t*)info->pk.eccsign.in, sigRS); + if (rc != STSAFE_A_OK) { + #ifdef USE_STSAFE_VERBOSE + STSAFE_INTERFACE_PRINTF("stsafe_interface_sign error: %d\n", rc); + #endif + rc = WC_HW_E; + return rc; + } + + /* Convert R and S to signature */ + r = &sigRS[0]; + s = &sigRS[key_sz]; + rc = wc_ecc_rs_raw_to_sig((const byte*)r, key_sz, (const byte*)s, + key_sz, info->pk.eccsign.out, info->pk.eccsign.outlen); + if (rc != 0) { + WOLFSSL_MSG("Error converting RS to Signature"); + } + } + else if (info->pk.type == WC_PK_TYPE_ECDSA_VERIFY) { + byte sigRS[STSAFE_MAX_SIG_LEN]; + byte *r, *s; + word32 r_len = STSAFE_MAX_SIG_LEN/2, s_len = STSAFE_MAX_SIG_LEN/2; + byte pubKeyX[STSAFE_MAX_PUBKEY_RAW_LEN/2]; + byte pubKeyY[STSAFE_MAX_PUBKEY_RAW_LEN/2]; + word32 pubKeyX_len = sizeof(pubKeyX); + word32 pubKeyY_len = sizeof(pubKeyY); + StSafeA_CurveId curve_id; + int ecc_curve, key_sz; + + WOLFSSL_MSG("STSAFE: ECC Verify"); + + if (info->pk.eccverify.key == NULL) + return BAD_FUNC_ARG; + + /* determine curve */ + ecc_curve = info->pk.eccverify.key->dp->id; + curve_id = stsafe_get_ecc_curve_id(ecc_curve); + key_sz = stsafe_get_key_size(curve_id); + + /* Extract Raw X and Y coordinates of the public key */ + rc = wc_ecc_export_public_raw(info->pk.eccverify.key, + pubKeyX, &pubKeyX_len, + pubKeyY, &pubKeyY_len); + if (rc == 0) { + /* Extract R and S from signature */ + XMEMSET(sigRS, 0, sizeof(sigRS)); + r = &sigRS[0]; + s = &sigRS[key_sz]; + rc = wc_ecc_sig_to_rs(info->pk.eccverify.sig, + info->pk.eccverify.siglen, r, &r_len, s, &s_len); + (void)r_len; + (void)s_len; + } + if (rc == 0) { + /* Verify signature */ + rc = stsafe_interface_verify(curve_id, + (uint8_t*)info->pk.eccverify.hash, sigRS, pubKeyX, pubKeyY, + (int32_t*)info->pk.eccverify.res); + if (rc != STSAFE_A_OK) { + #ifdef USE_STSAFE_VERBOSE + STSAFE_INTERFACE_PRINTF("stsafe_interface_verify error: %d\n", rc); + #endif + rc = WC_HW_E; + } + } + } + else if (info->pk.type == WC_PK_TYPE_ECDH) { + byte otherKeyX[STSAFE_MAX_KEY_LEN]; + byte otherKeyY[STSAFE_MAX_KEY_LEN]; + word32 otherKeyX_len = sizeof(otherKeyX); + word32 otherKeyY_len = sizeof(otherKeyY); + StSafeA_CurveId curve_id; + int ecc_curve; + + WOLFSSL_MSG("STSAFE: PMS"); + + if (info->pk.ecdh.public_key == NULL) + return BAD_FUNC_ARG; + + /* get curve */ + ecc_curve = info->pk.ecdh.public_key->dp->id; + curve_id = stsafe_get_ecc_curve_id(ecc_curve); + + /* Export otherKey raw X and Y */ + rc = wc_ecc_export_public_raw(info->pk.ecdh.public_key, + &otherKeyX[0], (word32*)&otherKeyX_len, + &otherKeyY[0], (word32*)&otherKeyY_len); + if (rc == 0) { + /* Compute shared secret */ + *info->pk.ecdh.outlen = 0; + rc = stsafe_interface_shared_secret(curve_id, + otherKeyX, otherKeyY, + info->pk.ecdh.out, (int32_t*)info->pk.ecdh.outlen); + if (rc != STSAFE_A_OK) { + #ifdef USE_STSAFE_VERBOSE + STSAFE_INTERFACE_PRINTF("stsafe_interface_shared_secret error: %d\n", rc); + #endif + rc = WC_HW_E; + } + } + } + } +#endif /* HAVE_ECC */ + + /* need to return negative here for error */ + if (rc != 0 && rc != CRYPTOCB_UNAVAILABLE) { + WOLFSSL_MSG("STSAFE: CryptoCb failed"); + #ifdef USE_STSAFE_VERBOSE + STSAFE_INTERFACE_PRINTF("STSAFE: CryptoCb failed %d\n", rc); + #endif + rc = WC_HW_E; + } + + return rc; +} + +#endif /* WOLF_CRYPTO_CB */ + +#endif /* WOLFSSL_STSAFEA100 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/ti/ti-aes.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/ti/ti-aes.c index d38e7a3cb..52f2ceb97 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/ti/ti-aes.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/ti/ti-aes.c @@ -1,8 +1,8 @@ /* port/ti/ti-aes.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ - + + #ifdef HAVE_CONFIG_H #include #endif @@ -65,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; @@ -84,19 +85,19 @@ 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, aes->reg); - ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen); + ROM_AESIVSet(AES_BASE, (uint32_t *)aes->reg); + ROM_AESKey1Set(AES_BASE, (uint32_t *)aes->key, aes->keylen); if((dir == AES_CFG_DIR_DECRYPT)&& (mode == AES_CFG_MODE_CBC)) /* if input and output same will overwrite input iv */ 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) @@ -106,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]) @@ -120,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) @@ -135,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) ; } @@ -155,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 ; @@ -181,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 ; @@ -201,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) ; @@ -250,11 +251,12 @@ static int AesAuthArgCheck(Aes* aes, byte* out, const byte* in, word32 inSz, const byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz, word32 *M, word32 *L) { + (void) authInSz ; if((aes == NULL)||(nonce == NULL)||(authTag== NULL)||(authIn == NULL)) 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 ; @@ -302,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); @@ -342,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 ; @@ -353,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) ; } @@ -380,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) ; } @@ -403,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 ; } @@ -411,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 ; @@ -422,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) ; } @@ -449,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) ; } @@ -468,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 ; @@ -488,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) ; } @@ -495,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) ; } @@ -516,17 +521,17 @@ WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, #endif /* HAVE_AESGCM */ #ifdef HAVE_AESCCM -WOLFSSL_API void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) +WOLFSSL_API int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) { - AesAuthSetKey(aes, key, keySz) ; + return AesAuthSetKey(aes, key, keySz) ; } -WOLFSSL_API void wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, +WOLFSSL_API 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) -{ - AesAuthEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, +{ + return AesAuthEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, AES_CFG_MODE_CCM) ; } @@ -534,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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/ti/ti-ccm.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/ti/ti-ccm.c index 09705cfb8..5c0051e03 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/ti/ti-ccm.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/ti/ti-ccm.c @@ -1,8 +1,8 @@ /* port/ti/ti_ccm.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -27,56 +28,67 @@ #if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) - +#include "wolfssl/wolfcrypt/port/ti/ti-ccm.h" #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; i #endif @@ -63,39 +64,39 @@ static int DesSetKey(Des* des, const byte* key, const byte* iv,int dir, int tri return BAD_FUNC_ARG; if(!((dir == DES_ENCRYPTION) || (dir == DES_DECRYPTION))) return BAD_FUNC_ARG; - + XMEMCPY(des->key, 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); ROM_DESConfigSet(DES_BASE, (dir | DES_CFG_MODE_CBC | tri)); - ROM_DESIVSet(DES_BASE, des->reg); - ROM_DESKeySet(DES_BASE, des->key); + ROM_DESIVSet(DES_BASE, (uint32_t*)des->reg); + ROM_DESKeySet(DES_BASE,(uint32_t*)des->key); if(dir == DES_CFG_DIR_DECRYPT) /* if input and output same will overwrite input iv */ 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] ; @@ -103,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) ; } @@ -148,32 +149,54 @@ 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) -{ return 0 ;} +{ + (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) -{ return 0 ; } +{ + (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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/ti/ti-hash.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/ti/ti-hash.c index c60f86423..ab8f2cc22 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/ti/ti-hash.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/ti/ti-hash.c @@ -1,8 +1,8 @@ /* port/ti/ti-hash.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -38,12 +39,13 @@ #include #include -#include -#include -#include +#include +#include +#include #include #include #include +#include #ifndef TI_DUMMY_BUILD #include "inc/hw_memmap.h" @@ -57,66 +59,70 @@ #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) { - 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 ; -#endif - XMEMCPY(result, h, hsize) ; + (void) hash; + (void) algo; - return 0 ; + XMEMSET(h, 0, sizeof(h)); +#endif + XMEMCPY(result, h, hsize); + + 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) @@ -143,149 +149,190 @@ static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word3 } #ifdef WOLFSSL_SMALL_STACK - XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hash_desc, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } +static int hashFree(wolfssl_TI_Hash *hash) +{ + XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER); + 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 ; - if(!wolfSSL_TI_CCMInit())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); } -#endif /* NO_MD5 */ +WOLFSSL_API void wc_Md5Free(Md5* md5) +{ + hashFree((wolfssl_TI_Hash *)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 ; - if(!wolfSSL_TI_CCMInit())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); } -#endif /* NO_SHA */ +WOLFSSL_API void wc_ShaFree(Sha* sha) +{ + hashFree((wolfssl_TI_Hash *)sha); +} -#if defined(HAVE_SHA224) -WOLFSSL_API int wc_InitSha224(Sha224* sha224) +#endif /* !NO_SHA */ + +#if defined(WOLFSSL_SHA224) +WOLFSSL_API int wc_InitSha224_ex(Sha224* sha224, void* heap, int devId) { if (sha224 == NULL) - return 1 ; - if(!wolfSSL_TI_CCMInit())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); } -#endif /* HAVE_SHA224 */ +WOLFSSL_API void wc_Sha224Free(Sha224* sha224) +{ + hashFree((wolfssl_TI_Hash *)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 ; - if(!wolfSSL_TI_CCMInit())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); } -#endif + +WOLFSSL_API void wc_Sha256Free(Sha256* sha256) +{ + hashFree((wolfssl_TI_Hash *)sha256); +} + +#endif /* !NO_SHA256 */ #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/xilinx/xil-aesgcm.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/xilinx/xil-aesgcm.c new file mode 100644 index 000000000..6af4b3177 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/xilinx/xil-aesgcm.c @@ -0,0 +1,202 @@ +/* xil-aesgcm.c + * + * Copyright (C) 2006-2020 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("Failed 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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/xilinx/xil-sha3.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/xilinx/xil-sha3.c new file mode 100644 index 000000000..a9db6b955 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/port/xilinx/xil-sha3.c @@ -0,0 +1,158 @@ +/* xil-sha3.c + * + * Copyright (C) 2006-2020 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(wc_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(wc_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(wc_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(wc_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(wc_Sha3* sha, byte* out) +{ + wc_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(wc_Sha3* src, wc_Sha3* dst) +{ + if (src == NULL || dst== NULL) { + return BAD_FUNC_ARG; + } + + XMEMCPY((byte*)dst, (byte*)src, sizeof(wc_Sha3)); + return 0; +} + +#endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/pwdbased.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/pwdbased.c index b9764d8d0..c672c2285 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/pwdbased.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/pwdbased.c @@ -1,8 +1,8 @@ /* pwdbased.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -27,176 +28,196 @@ #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 #include #include -#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) - #include -#endif #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; +#ifdef HAVE_PBKDF1 + +/* PKCS#5 v1.5 with non standard extension to optionally derive the extra data (IV) */ +int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen, + const byte* passwd, int passwdLen, const byte* salt, int saltLen, + int iterations, int hashType, void* heap) +{ + int err; + int keyLeft, ivLeft, i; + int digestLeft, store; + int keyOutput = 0; + int diestLen; + byte digest[WC_MAX_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + wc_HashAlg* hash = NULL; +#else + wc_HashAlg hash[1]; +#endif + enum wc_HashType hashT; + + (void)heap; + + if (key == NULL || keyLen < 0 || passwdLen < 0 || saltLen < 0 || ivLen < 0){ + return BAD_FUNC_ARG; } -#endif /* WOLFSSL_HAVE_MIN */ + if (iterations <= 0) + iterations = 1; + hashT = wc_HashTypeConvert(hashType); + err = wc_HashGetDigestSize(hashT); + if (err < 0) + return err; + diestLen = err; -#ifndef NO_SHA -/* PBKDF1 needs at least SHA available */ + /* initialize hash */ +#ifdef WOLFSSL_SMALL_STACK + hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), heap, + DYNAMIC_TYPE_HASHCTX); + if (hash == NULL) + return MEMORY_E; +#endif + + err = wc_HashInit_ex(hash, hashT, heap, INVALID_DEVID); + if (err != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(hash, heap, DYNAMIC_TYPE_HASHCTX); + #endif + return err; + } + + keyLeft = keyLen; + ivLeft = ivLen; + while (keyOutput < (keyLen + ivLen)) { + digestLeft = diestLen; + /* D_(i - 1) */ + if (keyOutput) { /* first time D_0 is empty */ + err = wc_HashUpdate(hash, hashT, digest, diestLen); + if (err != 0) break; + } + + /* data */ + err = wc_HashUpdate(hash, hashT, passwd, passwdLen); + if (err != 0) break; + + /* salt */ + if (salt) { + err = wc_HashUpdate(hash, hashT, salt, saltLen); + if (err != 0) break; + } + + err = wc_HashFinal(hash, hashT, digest); + if (err != 0) break; + + /* count */ + for (i = 1; i < iterations; i++) { + err = wc_HashUpdate(hash, hashT, digest, diestLen); + if (err != 0) break; + + err = wc_HashFinal(hash, hashT, digest); + if (err != 0) break; + } + + if (keyLeft) { + store = min(keyLeft, diestLen); + XMEMCPY(&key[keyLen - keyLeft], digest, store); + + keyOutput += store; + keyLeft -= store; + digestLeft -= store; + } + + if (ivLeft && digestLeft) { + store = min(ivLeft, digestLeft); + if (iv != NULL) + XMEMCPY(&iv[ivLen - ivLeft], + &digest[diestLen - digestLeft], store); + keyOutput += store; + ivLeft -= store; + } + } + + wc_HashFree(hash, hashT); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash, heap, DYNAMIC_TYPE_HASHCTX); +#endif + + if (err != 0) + return err; + + if (keyOutput != (keyLen + ivLen)) + return BUFFER_E; + + return err; +} + +/* PKCS#5 v1.5 */ int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, int sLen, int iterations, int kLen, int hashType) { - Sha sha; -#ifndef NO_MD5 - Md5 md5; -#endif - int hLen = (int)SHA_DIGEST_SIZE; - int i, ret = 0; - byte buffer[SHA_DIGEST_SIZE]; /* max size */ - - if (hashType != MD5 && hashType != SHA) - return BAD_FUNC_ARG; - -#ifndef NO_MD5 - if (hashType == MD5) - hLen = (int)MD5_DIGEST_SIZE; -#endif - - if (kLen > hLen) - return BAD_FUNC_ARG; - - if (iterations < 1) - return BAD_FUNC_ARG; - - switch (hashType) { -#ifndef NO_MD5 - case MD5: - wc_InitMd5(&md5); - wc_Md5Update(&md5, passwd, pLen); - wc_Md5Update(&md5, salt, sLen); - wc_Md5Final(&md5, buffer); - break; -#endif /* NO_MD5 */ - case SHA: - default: - ret = wc_InitSha(&sha); - if (ret != 0) - return ret; - wc_ShaUpdate(&sha, passwd, pLen); - wc_ShaUpdate(&sha, salt, sLen); - wc_ShaFinal(&sha, buffer); - break; - } - - for (i = 1; i < iterations; i++) { - if (hashType == SHA) { - wc_ShaUpdate(&sha, buffer, hLen); - wc_ShaFinal(&sha, buffer); - } -#ifndef NO_MD5 - else { - wc_Md5Update(&md5, buffer, hLen); - wc_Md5Final(&md5, buffer); - } -#endif - } - XMEMCPY(output, buffer, kLen); - - return 0; -} -#endif /* NO_SHA */ - - -int GetDigestSize(int hashType) -{ - int hLen; - - switch (hashType) { -#ifndef NO_MD5 - case MD5: - hLen = MD5_DIGEST_SIZE; - break; -#endif -#ifndef NO_SHA - case SHA: - hLen = SHA_DIGEST_SIZE; - break; -#endif -#ifndef NO_SHA256 - case SHA256: - hLen = SHA256_DIGEST_SIZE; - break; -#endif -#ifdef WOLFSSL_SHA512 - case SHA512: - hLen = SHA512_DIGEST_SIZE; - break; -#endif - default: - return BAD_FUNC_ARG; - } - - return hLen; + return wc_PBKDF1_ex(output, kLen, NULL, 0, + passwd, pLen, salt, sLen, iterations, hashType, NULL); } +#endif /* HAVE_PKCS5 */ -int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, - int sLen, int iterations, int kLen, int hashType) +#ifdef HAVE_PBKDF2 + +int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen, const byte* salt, + int sLen, int iterations, int kLen, int hashType, void* heap, int devId) { word32 i = 1; int hLen; int j, ret; - Hmac hmac; #ifdef WOLFSSL_SMALL_STACK byte* buffer; + Hmac* hmac; #else - byte buffer[MAX_DIGEST_SIZE]; + byte buffer[WC_MAX_DIGEST_SIZE]; + Hmac hmac[1]; #endif + enum wc_HashType hashT; - hLen = GetDigestSize(hashType); + if (output == NULL || pLen < 0 || sLen < 0 || kLen < 0) { + return BAD_FUNC_ARG; + } + + if (iterations <= 0) + iterations = 1; + + hashT = wc_HashTypeConvert(hashType); + hLen = wc_HashGetDigestSize(hashT); if (hLen < 0) return BAD_FUNC_ARG; #ifdef WOLFSSL_SMALL_STACK - buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + buffer = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); if (buffer == NULL) return MEMORY_E; + hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC); + if (hmac == NULL) { + XFREE(buffer, heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } #endif - ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen); - + ret = wc_HmacInit(hmac, heap, devId); if (ret == 0) { - while (kLen) { + /* use int hashType here, since HMAC FIPS uses the old unique value */ + ret = wc_HmacSetKey(hmac, hashType, passwd, pLen); + + while (ret == 0 && kLen) { int currentLen; - ret = wc_HmacUpdate(&hmac, salt, sLen); + ret = wc_HmacUpdate(hmac, salt, sLen); if (ret != 0) break; @@ -204,7 +225,7 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, for (j = 0; j < 4; j++) { byte b = (byte)(i >> ((3-j) * 8)); - ret = wc_HmacUpdate(&hmac, &b, 1); + ret = wc_HmacUpdate(hmac, &b, 1); if (ret != 0) break; } @@ -213,7 +234,7 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, if (ret != 0) break; - ret = wc_HmacFinal(&hmac, buffer); + ret = wc_HmacFinal(hmac, buffer); if (ret != 0) break; @@ -221,10 +242,10 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, XMEMCPY(output, buffer, currentLen); for (j = 1; j < iterations; j++) { - ret = wc_HmacUpdate(&hmac, buffer, hLen); + ret = wc_HmacUpdate(hmac, buffer, hLen); if (ret != 0) break; - ret = wc_HmacFinal(&hmac, buffer); + ret = wc_HmacFinal(hmac, buffer); if (ret != 0) break; xorbuf(output, buffer, currentLen); @@ -238,171 +259,98 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, kLen -= currentLen; i++; } + wc_HmacFree(hmac); } #ifdef WOLFSSL_SMALL_STACK - XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(buffer, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); #endif return ret; } -#ifdef WOLFSSL_SHA512 - #define PBKDF_DIGEST_SIZE SHA512_BLOCK_SIZE -#elif !defined(NO_SHA256) - #define PBKDF_DIGEST_SIZE SHA256_BLOCK_SIZE -#else - #define PBKDF_DIGEST_SIZE SHA_DIGEST_SIZE -#endif - -/* helper for wc_PKCS12_PBKDF(), sets block and digest sizes */ -int GetPKCS12HashSizes(int hashType, word32* v, word32* u) +int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, + int sLen, int iterations, int kLen, int hashType) { - if (!v || !u) - return BAD_FUNC_ARG; - - switch (hashType) { -#ifndef NO_MD5 - case MD5: - *v = MD5_BLOCK_SIZE; - *u = MD5_DIGEST_SIZE; - break; -#endif -#ifndef NO_SHA - case SHA: - *v = SHA_BLOCK_SIZE; - *u = SHA_DIGEST_SIZE; - break; -#endif -#ifndef NO_SHA256 - case SHA256: - *v = SHA256_BLOCK_SIZE; - *u = SHA256_DIGEST_SIZE; - break; -#endif -#ifdef WOLFSSL_SHA512 - case SHA512: - *v = SHA512_BLOCK_SIZE; - *u = SHA512_DIGEST_SIZE; - break; -#endif - default: - return BAD_FUNC_ARG; - } - - return 0; + return wc_PBKDF2_ex(output, passwd, pLen, salt, sLen, iterations, kLen, + hashType, NULL, INVALID_DEVID); } +#endif /* HAVE_PBKDF2 */ + +#ifdef HAVE_PKCS12 + /* helper for PKCS12_PBKDF(), does hash operation */ -int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, +static int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, byte* Ai, word32 u, int iterations) { int i; int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + wc_HashAlg* hash = NULL; +#else + wc_HashAlg hash[1]; +#endif + enum wc_HashType hashT; - if (buffer == NULL || Ai == NULL) + if (buffer == NULL || Ai == NULL) { return BAD_FUNC_ARG; - - switch (hashType) { -#ifndef NO_MD5 - case MD5: - { - Md5 md5; - wc_InitMd5(&md5); - wc_Md5Update(&md5, buffer, totalLen); - wc_Md5Final(&md5, Ai); - - for (i = 1; i < iterations; i++) { - wc_Md5Update(&md5, Ai, u); - wc_Md5Final(&md5, Ai); - } - } - break; -#endif /* NO_MD5 */ -#ifndef NO_SHA - case SHA: - { - Sha sha; - ret = wc_InitSha(&sha); - if (ret != 0) - break; - wc_ShaUpdate(&sha, buffer, totalLen); - wc_ShaFinal(&sha, Ai); - - for (i = 1; i < iterations; i++) { - wc_ShaUpdate(&sha, Ai, u); - wc_ShaFinal(&sha, Ai); - } - } - break; -#endif /* NO_SHA */ -#ifndef NO_SHA256 - case SHA256: - { - Sha256 sha256; - ret = wc_InitSha256(&sha256); - if (ret != 0) - break; - - ret = wc_Sha256Update(&sha256, buffer, totalLen); - if (ret != 0) - break; - - ret = wc_Sha256Final(&sha256, Ai); - if (ret != 0) - break; - - for (i = 1; i < iterations; i++) { - ret = wc_Sha256Update(&sha256, Ai, u); - if (ret != 0) - break; - - ret = wc_Sha256Final(&sha256, Ai); - if (ret != 0) - break; - } - } - break; -#endif /* NO_SHA256 */ -#ifdef WOLFSSL_SHA512 - case SHA512: - { - Sha512 sha512; - ret = wc_InitSha512(&sha512); - if (ret != 0) - break; - - ret = wc_Sha512Update(&sha512, buffer, totalLen); - if (ret != 0) - break; - - ret = wc_Sha512Final(&sha512, Ai); - if (ret != 0) - break; - - for (i = 1; i < iterations; i++) { - ret = wc_Sha512Update(&sha512, Ai, u); - if (ret != 0) - break; - - ret = wc_Sha512Final(&sha512, Ai); - if (ret != 0) - break; - } - } - break; -#endif /* WOLFSSL_SHA512 */ - - default: - ret = BAD_FUNC_ARG; - break; } + hashT = wc_HashTypeConvert(hashType); + + /* initialize hash */ +#ifdef WOLFSSL_SMALL_STACK + hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), NULL, + DYNAMIC_TYPE_HASHCTX); + if (hash == NULL) + return MEMORY_E; +#endif + + ret = wc_HashInit(hash, hashT); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(hash, NULL, DYNAMIC_TYPE_HASHCTX); + #endif + return ret; + } + + ret = wc_HashUpdate(hash, hashT, buffer, totalLen); + + if (ret == 0) + ret = wc_HashFinal(hash, hashT, Ai); + + for (i = 1; i < iterations; i++) { + if (ret == 0) + ret = wc_HashUpdate(hash, hashT, Ai, u); + if (ret == 0) + ret = wc_HashFinal(hash, hashT, Ai); + } + + wc_HashFree(hash, hashT); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash, NULL, DYNAMIC_TYPE_HASHCTX); +#endif + return ret; } -int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt, - int saltLen, int iterations, int kLen, int hashType, int id) + +int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen, + const byte* salt, int saltLen, int iterations, int kLen, int hashType, + int id) +{ + return wc_PKCS12_PBKDF_ex(output, passwd, passLen, salt, saltLen, + iterations, kLen, hashType, id, NULL); +} + + +/* extended API that allows a heap hint to be used */ +int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, + const byte* salt, int saltLen, int iterations, int kLen, + int hashType, int id, void* heap) { /* all in bytes instead of bits */ word32 u, v, dLen, pLen, iLen, sLen, totalLen; @@ -421,34 +369,48 @@ int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* sa byte* Ai; byte* B; #else - byte Ai[PBKDF_DIGEST_SIZE]; - byte B[PBKDF_DIGEST_SIZE]; + byte Ai[WC_MAX_DIGEST_SIZE]; + byte B[WC_MAX_BLOCK_SIZE]; #endif + enum wc_HashType hashT; - if (!iterations) + (void)heap; + + if (output == NULL || passLen < 0 || saltLen < 0 || kLen < 0) { + return BAD_FUNC_ARG; + } + + if (iterations <= 0) iterations = 1; - ret = GetPKCS12HashSizes(hashType, &v, &u); + hashT = wc_HashTypeConvert(hashType); + ret = wc_HashGetDigestSize(hashT); if (ret < 0) - return BAD_FUNC_ARG; + return ret; + u = ret; + + ret = wc_HashGetBlockSize(hashT); + if (ret < 0) + return ret; + v = ret; #ifdef WOLFSSL_SMALL_STACK - Ai = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + Ai = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); if (Ai == NULL) return MEMORY_E; - B = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + B = (byte*)XMALLOC(WC_MAX_BLOCK_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); if (B == NULL) { - XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } #endif - XMEMSET(Ai, 0, PBKDF_DIGEST_SIZE); - XMEMSET(B, 0, PBKDF_DIGEST_SIZE); + XMEMSET(Ai, 0, WC_MAX_DIGEST_SIZE); + XMEMSET(B, 0, WC_MAX_BLOCK_SIZE); dLen = v; - sLen = v * ((saltLen + v - 1) / v); + sLen = v * ((saltLen + v - 1) / v); if (passLen) pLen = v * ((passLen + v - 1) / v); else @@ -458,11 +420,11 @@ int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* sa totalLen = dLen + sLen + pLen; if (totalLen > sizeof(staticBuffer)) { - buffer = (byte*)XMALLOC(totalLen, 0, DYNAMIC_TYPE_KEY); + buffer = (byte*)XMALLOC(totalLen, heap, DYNAMIC_TYPE_KEY); if (buffer == NULL) { #ifdef WOLFSSL_SMALL_STACK - XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(B, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return MEMORY_E; } @@ -522,7 +484,7 @@ int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* sa else { if (outSz > (int)v) { /* take off MSB */ - byte tmp[129]; + byte tmp[WC_MAX_BLOCK_SIZE + 1]; ret = mp_to_unsigned_bin(&res, tmp); XMEMCPY(I + i, tmp + 1, v); } @@ -546,17 +508,288 @@ int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* sa mp_clear(&B1); } - if (dynamic) XFREE(buffer, 0, DYNAMIC_TYPE_KEY); + if (dynamic) XFREE(buffer, heap, DYNAMIC_TYPE_KEY); #ifdef WOLFSSL_SMALL_STACK - XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(B, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } -#undef PBKDF_DIGEST_SIZE +#endif /* HAVE_PKCS12 */ + +#ifdef HAVE_SCRYPT +/* Rotate the 32-bit value a by b bits to the left. + * + * a 32-bit value. + * b Number of bits to rotate. + * returns rotated value. + */ +#define R(a, b) rotlFixed(a, b) + +/* One round of Salsa20/8. + * Code taken from RFC 7914: scrypt PBKDF. + * + * out Output buffer. + * in Input data to hash. + */ +static void scryptSalsa(word32* out, word32* in) +{ + int i; + word32 x[16]; + +#ifdef LITTLE_ENDIAN_ORDER + for (i = 0; i < 16; ++i) + x[i] = in[i]; +#else + for (i = 0; i < 16; i++) + x[i] = ByteReverseWord32(in[i]); +#endif + for (i = 8; i > 0; i -= 2) { + x[ 4] ^= R(x[ 0] + x[12], 7); x[ 8] ^= R(x[ 4] + x[ 0], 9); + x[12] ^= R(x[ 8] + x[ 4], 13); x[ 0] ^= R(x[12] + x[ 8], 18); + x[ 9] ^= R(x[ 5] + x[ 1], 7); x[13] ^= R(x[ 9] + x[ 5], 9); + x[ 1] ^= R(x[13] + x[ 9], 13); x[ 5] ^= R(x[ 1] + x[13], 18); + x[14] ^= R(x[10] + x[ 6], 7); x[ 2] ^= R(x[14] + x[10], 9); + x[ 6] ^= R(x[ 2] + x[14], 13); x[10] ^= R(x[ 6] + x[ 2], 18); + x[ 3] ^= R(x[15] + x[11], 7); x[ 7] ^= R(x[ 3] + x[15], 9); + x[11] ^= R(x[ 7] + x[ 3], 13); x[15] ^= R(x[11] + x[ 7], 18); + x[ 1] ^= R(x[ 0] + x[ 3], 7); x[ 2] ^= R(x[ 1] + x[ 0], 9); + x[ 3] ^= R(x[ 2] + x[ 1], 13); x[ 0] ^= R(x[ 3] + x[ 2], 18); + x[ 6] ^= R(x[ 5] + x[ 4], 7); x[ 7] ^= R(x[ 6] + x[ 5], 9); + x[ 4] ^= R(x[ 7] + x[ 6], 13); x[ 5] ^= R(x[ 4] + x[ 7], 18); + x[11] ^= R(x[10] + x[ 9], 7); x[ 8] ^= R(x[11] + x[10], 9); + x[ 9] ^= R(x[ 8] + x[11], 13); x[10] ^= R(x[ 9] + x[ 8], 18); + x[12] ^= R(x[15] + x[14], 7); x[13] ^= R(x[12] + x[15], 9); + x[14] ^= R(x[13] + x[12], 13); x[15] ^= R(x[14] + x[13], 18); + } +#ifdef LITTLE_ENDIAN_ORDER + for (i = 0; i < 16; ++i) + out[i] = in[i] + x[i]; +#else + for (i = 0; i < 16; i++) + out[i] = ByteReverseWord32(ByteReverseWord32(in[i]) + x[i]); +#endif +} + +/* Mix a block using Salsa20/8. + * Based on RFC 7914: scrypt PBKDF. + * + * b Blocks to mix. + * y Temporary storage. + * r Size of the block. + */ +static void scryptBlockMix(byte* b, byte* y, int r) +{ + byte x[64]; +#ifdef WORD64_AVAILABLE + word64* b64 = (word64*)b; + word64* y64 = (word64*)y; + word64* x64 = (word64*)x; +#else + word32* b32 = (word32*)b; + word32* y32 = (word32*)y; + word32* x32 = (word32*)x; +#endif + int i; + int j; + + /* Step 1. */ + XMEMCPY(x, b + (2 * r - 1) * 64, sizeof(x)); + /* Step 2. */ + for (i = 0; i < 2 * r; i++) + { +#ifdef WORD64_AVAILABLE + for (j = 0; j < 8; j++) + x64[j] ^= b64[i * 8 + j]; +#else + for (j = 0; j < 16; j++) + x32[j] ^= b32[i * 16 + j]; +#endif + scryptSalsa((word32*)x, (word32*)x); + XMEMCPY(y + i * 64, x, sizeof(x)); + } + /* Step 3. */ + for (i = 0; i < r; i++) { +#ifdef WORD64_AVAILABLE + for (j = 0; j < 8; j++) { + b64[i * 8 + j] = y64[2 * i * 8 + j]; + b64[(r + i) * 8 + j] = y64[(2 * i + 1) * 8 + j]; + } +#else + for (j = 0; j < 16; j++) { + b32[i * 16 + j] = y32[2 * i * 16 + j]; + b32[(r + i) * 16 + j] = y32[(2 * i + 1) * 16 + j]; + } +#endif + } +} + +/* Random oracles mix. + * Based on RFC 7914: scrypt PBKDF. + * + * x Data to mix. + * v Temporary buffer. + * y Temporary buffer for the block mix. + * r Block size parameter. + * n CPU/Memory cost parameter. + */ +static void scryptROMix(byte* x, byte* v, byte* y, int r, word32 n) +{ + word32 i; + word32 j; + word32 k; + word32 bSz = 128 * r; +#ifdef WORD64_AVAILABLE + word64* x64 = (word64*)x; + word64* v64 = (word64*)v; +#else + word32* x32 = (word32*)x; + word32* v32 = (word32*)v; +#endif + + /* Step 1. X = B (B not needed therefore not implemented) */ + /* Step 2. */ + for (i = 0; i < n; i++) + { + XMEMCPY(v + i * bSz, x, bSz); + scryptBlockMix(x, y, r); + } + + /* Step 3. */ + for (i = 0; i < n; i++) + { +#ifdef LITTLE_ENDIAN_ORDER +#ifdef WORD64_AVAILABLE + j = *(word64*)(x + (2*r - 1) * 64) & (n-1); +#else + j = *(word32*)(x + (2*r - 1) * 64) & (n-1); +#endif +#else + byte* t = x + (2*r - 1) * 64; + j = (t[0] | (t[1] << 8) | (t[2] << 16) | ((word32)t[3] << 24)) & (n-1); +#endif +#ifdef WORD64_AVAILABLE + for (k = 0; k < bSz / 8; k++) + x64[k] ^= v64[j * bSz / 8 + k]; +#else + for (k = 0; k < bSz / 4; k++) + x32[k] ^= v32[j * bSz / 4 + k]; +#endif + scryptBlockMix(x, y, r); + } + /* Step 4. B' = X (B = X = B' so not needed, therefore not implemented) */ +} + +/* Generates an key derived from a password and salt using a memory hard + * algorithm. + * Implements RFC 7914: scrypt PBKDF. + * + * output The derived key. + * passwd The password to derive key from. + * passLen The length of the password. + * salt The key specific data. + * saltLen The length of the salt data. + * cost The CPU/memory cost parameter. Range: 1..(128*r/8-1) + * (Iterations = 2^cost) + * blockSize The number of 128 byte octets in a working block. + * parallel The number of parallel mix operations to perform. + * (Note: this implementation does not use threads.) + * dkLen The length of the derived key in bytes. + * returns BAD_FUNC_ARG when: blockSize is too large for cost. + */ +int wc_scrypt(byte* output, const byte* passwd, int passLen, + const byte* salt, int saltLen, int cost, int blockSize, + int parallel, int dkLen) +{ + int ret = 0; + int i; + byte* v = NULL; + byte* y = NULL; + byte* blocks = NULL; + word32 blocksSz; + word32 bSz; + + if (blockSize > 8) + return BAD_FUNC_ARG; + + if (cost < 1 || cost >= 128 * blockSize / 8 || parallel < 1 || dkLen < 1) + return BAD_FUNC_ARG; + + bSz = 128 * blockSize; + blocksSz = bSz * parallel; + blocks = (byte*)XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (blocks == NULL) + goto end; + /* Temporary for scryptROMix. */ + v = (byte*)XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (v == NULL) + goto end; + /* Temporary for scryptBlockMix. */ + 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, + WC_SHA256); + if (ret != 0) + goto end; + + /* Step 2. */ + for (i = 0; i < parallel; i++) + scryptROMix(blocks + i * bSz, v, y, blockSize, 1 << cost); + + /* Step 3. */ + ret = wc_PBKDF2(output, passwd, passLen, blocks, blocksSz, 1, dkLen, + WC_SHA256); +end: + if (blocks != NULL) + XFREE(blocks, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (v != NULL) + XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (y != NULL) + XFREE(y, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +/* Generates an key derived from a password and salt using a memory hard + * algorithm. + * Implements RFC 7914: scrypt PBKDF. + * + * output Derived key. + * passwd Password to derive key from. + * passLen Length of the password. + * salt Key specific data. + * saltLen Length of the salt data. + * iterations Number of iterations to perform. Range: 1 << (1..(128*r/8-1)) + * blockSize Number of 128 byte octets in a working block. + * parallel Number of parallel mix operations to perform. + * (Note: this implementation does not use threads.) + * dkLen Length of the derived key in bytes. + * returns BAD_FUNC_ARG when: iterations is not a power of 2 or blockSize is too + * large for iterations. + */ +int wc_scrypt_ex(byte* output, const byte* passwd, int passLen, + const byte* salt, int saltLen, word32 iterations, + int blockSize, int parallel, int dkLen) +{ + int cost; + + /* Iterations must be a power of 2. */ + if ((iterations & (iterations - 1)) != 0) + return BAD_FUNC_ARG; + + for (cost = -1; iterations != 0; cost++) { + iterations >>= 1; + } + + return wc_scrypt(output, passwd, passLen, salt, saltLen, cost, blockSize, + parallel, dkLen); +} +#endif /* HAVE_SCRYPT */ #endif /* NO_PWDBASED */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/rabbit.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/rabbit.c index fc7861115..820fd0ac3 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/rabbit.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/rabbit.c @@ -1,8 +1,8 @@ /* rabbit.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -33,6 +34,7 @@ #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif @@ -86,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])); @@ -114,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]); @@ -143,7 +145,7 @@ static void wc_RabbitSetIV(Rabbit* ctx, const byte* inIv) /* Key setup */ -static INLINE int DoKey(Rabbit* ctx, const byte* key, const byte* iv) +static WC_INLINE int DoKey(Rabbit* ctx, const byte* key, const byte* iv) { /* Temporary variables */ word32 k0, k1, k2, k3, i; @@ -198,10 +200,36 @@ static INLINE int DoKey(Rabbit* ctx, const byte* key, const byte* iv) } +int wc_Rabbit_SetHeap(Rabbit* ctx, void* heap) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef XSTREAM_ALIGN + ctx->heap = heap; +#endif + + (void)heap; + return 0; +} + + /* 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 + ctx->heap = (void*)WOLFSSL_HEAP_TEST; + #else + ctx->heap = NULL; + #endif /* WOLFSSL_HEAP_TEST */ + if ((wolfssl_word)key % 4) { int alignKey[4]; @@ -219,7 +247,7 @@ int wc_RabbitSetKey(Rabbit* ctx, const byte* key, const byte* iv) /* Encrypt/decrypt a message of any size */ -static INLINE int DoProcess(Rabbit* ctx, byte* output, const byte* input, +static WC_INLINE int DoProcess(Rabbit* ctx, byte* output, const byte* input, word32 msglen) { /* Encrypt/decrypt all full blocks */ @@ -262,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 */ @@ -281,20 +309,24 @@ 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 byte* tmp; WOLFSSL_MSG("wc_RabbitProcess unaligned"); - tmp = (byte*)XMALLOC(msglen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmp = (byte*)XMALLOC(msglen, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) return MEMORY_E; XMEMCPY(tmp, input, msglen); DoProcess(ctx, tmp, tmp, msglen); XMEMCPY(output, tmp, msglen); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); return 0; #else diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/random.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/random.c index 4a1f7ea5b..53041d164 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/random.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/random.c @@ -1,8 +1,8 @@ /* random.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,135 +16,247 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif - + #include +#include /* on HPUX 11 you may need to install /dev/random see http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I */ -#include +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$c") + #pragma const_seg(".fipsB$c") + #endif +#endif + + +#include +#include + + +/* If building for old FIPS. */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) -#ifdef HAVE_FIPS int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz) { return GenerateSeed(os, seed, sz); } -#ifdef HAVE_CAVIUM - int wc_InitRngCavium(RNG* rng, int i) - { - return InitRngCavium(rng, i); - } -#endif +int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId) +{ + (void)heap; + (void)devId; + return InitRng_fips(rng); +} - -int wc_InitRng(RNG* rng) +int wc_InitRng(WC_RNG* rng) { return InitRng_fips(rng); } -int wc_RNG_GenerateBlock(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(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(RNG* rng) + 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, - byte* output, word32 outputSz) + int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + byte* output, word32 outputSz) { - return RNG_HealthTest_fips(reseed, entropyA, entropyASz, - entropyB, entropyBSz, output, outputSz); - } -#endif /* HAVE_HASHDRBG || NO_RC4 */ -#else /* else build without fips */ -#include + return RNG_HealthTest_fips(reseed, seedA, seedASz, + seedB, seedBSz, output, outputSz); + } +#endif /* HAVE_HASHDRBG */ -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#else /* else build without fips, or for new fips */ - #include +#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */ - #ifdef NO_INLINE - #include - #else - #include - #endif -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#include -#if defined(USE_WINDOWS_API) +#ifdef WOLF_CRYPTO_CB + #include +#endif + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_SGX) + #include +#elif defined(USE_WINDOWS_API) #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #endif #include #include +#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" +#elif defined(WOLFSSL_WICED) + #include "wiced_crypto.h" +#elif defined(WOLFSSL_NETBURNER) + #include + #include + #include +#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(WOLFSSL_DEOS) +#elif defined(MICRIUM) +#elif defined(WOLFSSL_NUCLEUS) +#elif defined(WOLFSSL_PB) +#elif defined(WOLFSSL_ZEPHYR) +#elif defined(WOLFSSL_TELIT_M2MB) +#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG) #else - #if !defined(NO_DEV_RANDOM) && !defined(CUSTOM_RAND_GENERATE) && \ - !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM) - #include - #ifndef EBSNET - #include - #endif - #else - /* include headers that may be needed to get good seed */ + /* include headers that may be needed to get good seed */ + #include + #ifndef EBSNET + #include #endif -#endif /* USE_WINDOWS_API */ - -#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) ; - #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 + +#ifdef USE_WINDOWS_API + #include +#endif /* USE_WINDOWS_API */ +#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 SECURITY_STRENGTH (256) -#define ENTROPY_SZ (SECURITY_STRENGTH/8) -#define NONCE_SZ (ENTROPY_SZ/2) -#define ENTROPY_NONCE_SZ (ENTROPY_SZ+NONCE_SZ) +#define RESEED_INTERVAL WC_RESEED_INTERVAL + + +/* For FIPS builds, the user should not be adjusting the values. */ +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #if defined(RNG_SECURITY_STRENGTH) \ + || defined(ENTROPY_SCALE_FACTOR) \ + || defined(SEED_BLOCK_SZ) + + #error "Do not change the RNG parameters for FIPS builds." + #endif +#endif + + +/* The security strength for the RNG is the target number of bits of + * entropy you are looking for in a seed. */ +#ifndef RNG_SECURITY_STRENGTH + #if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + /* SHA-256 requires a minimum of 256-bits of entropy. The goal + * of 1024 will provide 4 times that. */ + #define RNG_SECURITY_STRENGTH (1024) + #else + /* If not using FIPS or using old FIPS, set the number down a bit. + * More is better, but more is also slower. */ + #define RNG_SECURITY_STRENGTH (256) + #endif +#endif + +#ifndef ENTROPY_SCALE_FACTOR + /* The entropy scale factor should be the whole number inverse of the + * minimum bits of entropy per bit of NDRNG output. */ + #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) + /* The value of 2 applies to Intel's RDSEED which provides about + * 0.5 bits minimum of entropy per bit. */ + #define ENTROPY_SCALE_FACTOR 2 + #else + /* Setting the default to 1. */ + #define ENTROPY_SCALE_FACTOR 1 + #endif +#endif + +#ifndef SEED_BLOCK_SZ + /* The seed block size, is the size of the output of the underlying NDRNG. + * This value is used for testing the output of the NDRNG. */ + #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) + /* RDSEED outputs in blocks of 64-bits. */ + #define SEED_BLOCK_SZ sizeof(word64) + #else + /* Setting the default to 4. */ + #define SEED_BLOCK_SZ 4 + #endif +#endif + +#define SEED_SZ (RNG_SECURITY_STRENGTH*ENTROPY_SCALE_FACTOR/8) + +/* The maximum seed size will be the seed size plus a seed block for the + * test, and an additional half of the seed size. This additional half + * is in case the user does not supply a nonce. A nonce will be obtained + * from the NDRNG. */ +#define MAX_SEED_SZ (SEED_SZ + SEED_SZ/2 + SEED_BLOCK_SZ) + /* Internal return codes */ #define DRBG_SUCCESS 0 -#define DRBG_ERROR 1 -#define DRBG_FAILURE 2 -#define DRBG_NEED_RESEED 3 -#define DRBG_CONT_FAILURE 4 +#define DRBG_FAILURE 1 +#define DRBG_NEED_RESEED 2 +#define DRBG_CONT_FAILURE 3 /* RNG health states */ #define DRBG_NOT_INIT 0 @@ -152,6 +264,12 @@ int wc_RNG_GenerateByte(RNG* rng, byte* b) #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, @@ -161,13 +279,20 @@ enum { drbgInitV }; - +/* NOTE: if DRBG struct is changed please update random.h drbg_data size */ typedef struct DRBG { word32 reseedCtr; word32 lastBlock; byte V[DRBG_SEED_LEN]; byte C[DRBG_SEED_LEN]; +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + void* heap; + int devId; +#endif byte matchCount; +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256 sha256; +#endif } DRBG; @@ -179,73 +304,104 @@ 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]; +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256* sha = &drbg->sha256; +#else + wc_Sha256 sha[1]; +#endif +#ifdef WC_ASYNC_ENABLE_SHA256 + DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap); + if (digest == NULL) + return MEMORY_E; +#else + byte digest[WC_SHA256_DIGEST_SIZE]; +#endif (void)drbg; - #ifdef LITTLE_ENDIAN_ORDER - bits = ByteReverseWord32(bits); - #endif +#ifdef WC_ASYNC_ENABLE_SHA256 + 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++) { +#ifndef WOLFSSL_SMALL_STACK_CACHE + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + 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) +#endif + 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); + +#ifndef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256Free(sha); +#endif + 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); + +#ifdef WC_ASYNC_ENABLE_SHA256 + FREE_VAR(digest, drbg->heap); +#endif + + 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) +static int Hash_DRBG_Reseed(DRBG* drbg, const byte* seed, word32 seedSz) { - byte seed[DRBG_SEED_LEN]; + byte newV[DRBG_SEED_LEN]; - if (Hash_df(drbg, seed, sizeof(seed), drbgReseed, drbg->V, sizeof(drbg->V), - entropy, entropySz) != DRBG_SUCCESS) { + XMEMSET(newV, 0, DRBG_SEED_LEN); + + if (Hash_df(drbg, newV, sizeof(newV), drbgReseed, + drbg->V, sizeof(drbg->V), seed, seedSz) != DRBG_SUCCESS) { return DRBG_FAILURE; } - XMEMCPY(drbg->V, seed, sizeof(drbg->V)); - ForceZero(seed, sizeof(seed)); + XMEMCPY(drbg->V, newV, sizeof(drbg->V)); + ForceZero(newV, sizeof(newV)); if (Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V, sizeof(drbg->V), NULL, 0) != DRBG_SUCCESS) { @@ -258,7 +414,17 @@ static int Hash_DRBG_Reseed(DRBG* drbg, const byte* entropy, word32 entropySz) return DRBG_SUCCESS; } -static INLINE void array_add_one(byte* data, word32 dataSz) +/* Returns: DRBG_SUCCESS and DRBG_FAILURE or BAD_FUNC_ARG on fail */ +int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz) +{ + if (rng == NULL || seed == NULL) { + return BAD_FUNC_ARG; + } + + return Hash_DRBG_Reseed(rng->drbg, seed, seedSz); +} + +static WC_INLINE void array_add_one(byte* data, word32 dataSz) { int i; @@ -269,16 +435,26 @@ 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]; +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256* sha = &drbg->sha256; +#else + wc_Sha256 sha[1]; +#endif +#ifdef WC_ASYNC_ENABLE_SHA256 + DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap); + if (digest == NULL) + return MEMORY_E; +#else + byte digest[WC_SHA256_DIGEST_SIZE]; +#endif /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for * the continuous test. */ @@ -289,48 +465,63 @@ 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) { +#ifndef WOLFSSL_SMALL_STACK_CACHE + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(sha); + #endif + if (ret == 0) +#endif + ret = wc_Sha256Update(sha, data, sizeof(data)); + if (ret == 0) + ret = wc_Sha256Final(sha, digest); +#ifndef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256Free(sha); +#endif - 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 (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; +#ifdef WC_ASYNC_ENABLE_SHA256 + FREE_VAR(digest, drbg->heap); +#endif + + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; } - -static INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen) +static WC_INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen) { word16 carry = 0; @@ -352,53 +543,97 @@ 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; +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256* sha = &drbg->sha256; +#else + wc_Sha256 sha[1]; +#endif + 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 { + #ifdef WC_ASYNC_ENABLE_SHA256 + DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap); + if (digest == NULL) + return MEMORY_E; + #else + byte digest[WC_SHA256_DIGEST_SIZE]; + #endif + 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) { +#ifndef WOLFSSL_SMALL_STACK_CACHE + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(sha); + #endif + if (ret == 0) +#endif + 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)); +#ifndef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256Free(sha); +#endif + + 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); + #ifdef WC_ASYNC_ENABLE_SHA256 + FREE_VAR(digest, drbg->heap); + #endif } - 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; + int ret; XMEMSET(drbg, 0, sizeof(DRBG)); +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + drbg->heap = heap; + drbg->devId = devId; +#else + (void)heap; + (void)devId; +#endif + +#ifdef WOLFSSL_SMALL_STACK_CACHE + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + ret = wc_InitSha256_ex(&drbg->sha256, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(&drbg->sha256); + #endif + if (ret != 0) + return ret; +#endif if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz, nonce, nonceSz) == DRBG_SUCCESS && @@ -410,11 +645,13 @@ static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz, drbg->matchCount = 0; ret = DRBG_SUCCESS; } + else { + ret = DRBG_FAILURE; + } return ret; } - /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_DRBG_Uninstantiate(DRBG* drbg) { @@ -422,6 +659,10 @@ static int Hash_DRBG_Uninstantiate(DRBG* drbg) int compareSum = 0; byte* compareDrbg = (byte*)drbg; +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256Free(&drbg->sha256); +#endif + ForceZero(drbg, sizeof(DRBG)); for (i = 0; i < sizeof(DRBG); i++) @@ -430,91 +671,293 @@ static int Hash_DRBG_Uninstantiate(DRBG* drbg) return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE; } + +int wc_RNG_TestSeed(const byte* seed, word32 seedSz) +{ + int ret = DRBG_SUCCESS; + + /* Check the seed for duplicate words. */ + word32 seedIdx = 0; + word32 scratchSz = min(SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ); + + while (seedIdx < seedSz - SEED_BLOCK_SZ) { + if (ConstantCompare(seed + seedIdx, + seed + seedIdx + scratchSz, + scratchSz) == 0) { + + ret = DRBG_CONT_FAILURE; + } + seedIdx += SEED_BLOCK_SZ; + scratchSz = min(SEED_BLOCK_SZ, (seedSz - seedIdx)); + } + + return ret; +} +#endif /* HAVE_HASHDRBG */ /* End NIST DRBG Code */ -/* Get seed and key cipher */ -int wc_InitRng(RNG* rng) +static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, + void* heap, int devId) { - int ret = BAD_FUNC_ARG; + int ret = RNG_FAILURE_E; +#ifdef HAVE_HASHDRBG + word32 seedSz = SEED_SZ + SEED_BLOCK_SZ; +#endif - if (rng != NULL) { - if (wc_RNG_HealthTestLocal(0) == 0) { - byte entropy[ENTROPY_NONCE_SZ]; + (void)nonce; + (void)nonceSz; - rng->drbg = - (struct DRBG*)XMALLOC(sizeof(DRBG), NULL, 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) { + if (rng == NULL) + return BAD_FUNC_ARG; + if (nonce == NULL && nonceSz != 0) + return BAD_FUNC_ARG; - ret = Hash_DRBG_Generate(rng->drbg, NULL, 0); - } - else - ret = DRBG_FAILURE; +#ifdef WOLFSSL_HEAP_TEST + rng->heap = (void*)WOLFSSL_HEAP_TEST; + (void)heap; +#else + rng->heap = heap; +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + rng->devId = devId; + #if defined(WOLF_CRYPTO_CB) + rng->seed.devId = devId; + #endif +#else + (void)devId; +#endif - ForceZero(entropy, ENTROPY_NONCE_SZ); - } - else - ret = DRBG_CONT_FAILURE; +#ifdef HAVE_HASHDRBG + /* init the DBRG to known values */ + rng->drbg = NULL; + rng->status = DRBG_NOT_INIT; +#endif - 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; +#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) + /* init the intel RD seed and/or rand */ + wc_InitRng_IntelRD(); +#endif + + /* 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 (nonceSz == 0) + seedSz = MAX_SEED_SZ; + + if (wc_RNG_HealthTestLocal(0) == 0) { + #ifdef WC_ASYNC_ENABLE_SHA256 + DECLARE_VAR(seed, byte, MAX_SEED_SZ, rng->heap); + if (seed == NULL) + return MEMORY_E; + #else + byte seed[MAX_SEED_SZ]; + #endif + +#if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + rng->drbg = + (struct DRBG*)XMALLOC(sizeof(DRBG), rng->heap, + DYNAMIC_TYPE_RNG); +#else + /* compile-time validation of drbg_data size */ + typedef char drbg_data_test[sizeof(rng->drbg_data) >= + sizeof(struct DRBG) ? 1 : -1]; + (void)sizeof(drbg_data_test); + rng->drbg = (struct DRBG*)rng->drbg_data; +#endif + + if (rng->drbg == NULL) { + ret = MEMORY_E; } else { - rng->status = DRBG_FAILED; + ret = wc_GenerateSeed(&rng->seed, seed, seedSz); + if (ret != 0) + ret = DRBG_FAILURE; + else + ret = wc_RNG_TestSeed(seed, seedSz); + + if (ret == DRBG_SUCCESS) + ret = Hash_DRBG_Instantiate(rng->drbg, + seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ, + nonce, nonceSz, rng->heap, devId); + + if (ret != DRBG_SUCCESS) { + #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG); + #endif + rng->drbg = NULL; + } } + + ForceZero(seed, seedSz); + #ifdef WC_ASYNC_ENABLE_SHA256 + FREE_VAR(seed, rng->heap); + #endif } + 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; } +WOLFSSL_ABI +WC_RNG* wc_rng_new(byte* nonce, word32 nonceSz, void* heap) +{ + WC_RNG* rng; + + rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), heap, DYNAMIC_TYPE_RNG); + if (rng) { + int error = _InitRng(rng, nonce, nonceSz, heap, INVALID_DEVID) != 0; + if (error) { + XFREE(rng, heap, DYNAMIC_TYPE_RNG); + rng = NULL; + } + } + + return rng; +} + + +WOLFSSL_ABI +void wc_rng_free(WC_RNG* rng) +{ + if (rng) { + void* heap = rng->heap; + + wc_FreeRng(rng); + ForceZero(rng, sizeof(WC_RNG)); + XFREE(rng, heap, DYNAMIC_TYPE_RNG); + (void)heap; + } +} + + +int wc_InitRng(WC_RNG* rng) +{ + return _InitRng(rng, NULL, 0, NULL, INVALID_DEVID); +} + + +int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId) +{ + return _InitRng(rng, NULL, 0, heap, devId); +} + + +int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz) +{ + return _InitRng(rng, nonce, nonceSz, NULL, INVALID_DEVID); +} + + +int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz, + void* heap, int devId) +{ + return _InitRng(rng, nonce, nonceSz, heap, devId); +} + + /* place a generated block in output */ -int wc_RNG_GenerateBlock(RNG* rng, byte* output, word32 sz) +WOLFSSL_ABI +int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) { int ret; - if (rng == NULL || output == NULL || sz > MAX_REQUEST_LEN) + if (rng == NULL || output == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLF_CRYPTO_CB + if (rng->devId != INVALID_DEVID) { + ret = wc_CryptoCb_RandomBlock(rng, output, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif + +#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) && defined(QAT_ENABLE_RNG) + 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]; + byte newSeed[SEED_SZ + SEED_BLOCK_SZ]; - if (wc_GenerateSeed(&rng->seed, entropy, ENTROPY_SZ) == 0 && - Hash_DRBG_Reseed(rng->drbg, entropy, ENTROPY_SZ) - == DRBG_SUCCESS) { - - ret = Hash_DRBG_Generate(rng->drbg, NULL, 0); - if (ret == DRBG_SUCCESS) - ret = Hash_DRBG_Generate(rng->drbg, output, sz); - } - else + ret = wc_GenerateSeed(&rng->seed, newSeed, + SEED_SZ + SEED_BLOCK_SZ); + if (ret != 0) ret = DRBG_FAILURE; + else + ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ); - ForceZero(entropy, ENTROPY_SZ); + if (ret == DRBG_SUCCESS) + ret = Hash_DRBG_Reseed(rng->drbg, newSeed + SEED_BLOCK_SZ, + SEED_SZ); + if (ret == DRBG_SUCCESS) + ret = Hash_DRBG_Generate(rng->drbg, output, sz); + + ForceZero(newSeed, sizeof(newSeed)); } else ret = DRBG_CONT_FAILURE; @@ -531,90 +974,147 @@ int wc_RNG_GenerateBlock(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; } -int wc_RNG_GenerateByte(RNG* rng, byte* b) +int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) { return wc_RNG_GenerateBlock(rng, b, 1); } -int wc_FreeRng(RNG* rng) +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, NULL, 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; + + #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG); + #endif + rng->drbg = NULL; } + rng->status = DRBG_NOT_INIT; +#endif /* HAVE_HASHDRBG */ + + return ret; +} + +#ifdef HAVE_HASHDRBG +int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + byte* output, word32 outputSz) +{ + return wc_RNG_HealthTest_ex(reseed, NULL, 0, + seedA, seedASz, seedB, seedBSz, + output, outputSz, + NULL, INVALID_DEVID); +} + + +int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz, + const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + byte* output, word32 outputSz, + void* heap, int devId) +{ + int ret = -1; + DRBG* drbg; +#ifndef WOLFSSL_SMALL_STACK + DRBG drbg_var; +#endif + + if (seedA == NULL || output == NULL) { + return BAD_FUNC_ARG; + } + + if (reseed != 0 && seedB == NULL) { + return BAD_FUNC_ARG; + } + + if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE) { + return ret; + } + +#ifdef WOLFSSL_SMALL_STACK + drbg = (DRBG*)XMALLOC(sizeof(DRBG), NULL, DYNAMIC_TYPE_RNG); + if (drbg == NULL) { + return MEMORY_E; + } +#else + drbg = &drbg_var; +#endif + + if (Hash_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz, + heap, devId) != 0) { + goto exit_rng_ht; + } + + if (reseed) { + if (Hash_DRBG_Reseed(drbg, seedB, seedBSz) != 0) { + goto exit_rng_ht; + } + } + + /* This call to generate is prescribed by the NIST DRBGVS + * procedure. The results are thrown away. The known + * answer test checks the second block of DRBG out of + * the generator to ensure the internal state is updated + * as expected. */ + if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) { + goto exit_rng_ht; + } + + if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) { + goto exit_rng_ht; + } + + /* Mark success */ + ret = 0; + +exit_rng_ht: + + /* This is safe to call even if Hash_DRBG_Instantiate fails */ + if (Hash_DRBG_Uninstantiate(drbg) != 0) { + ret = -1; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(drbg, NULL, DYNAMIC_TYPE_RNG); +#endif + return ret; } -int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, - const byte* entropyB, word32 entropyBSz, - byte* output, word32 outputSz) -{ - DRBG drbg; - - if (entropyA == NULL || output == NULL) - return BAD_FUNC_ARG; - - if (reseed != 0 && entropyB == NULL) - return BAD_FUNC_ARG; - - if (outputSz != (SHA256_DIGEST_SIZE * 4)) - return -1; - - if (Hash_DRBG_Instantiate(&drbg, entropyA, entropyASz, NULL, 0) != 0) - return -1; - - if (reseed) { - if (Hash_DRBG_Reseed(&drbg, entropyB, entropyBSz) != 0) { - Hash_DRBG_Uninstantiate(&drbg); - return -1; - } - } - - if (Hash_DRBG_Generate(&drbg, output, outputSz) != 0) { - Hash_DRBG_Uninstantiate(&drbg); - return -1; - } - - if (Hash_DRBG_Generate(&drbg, output, outputSz) != 0) { - Hash_DRBG_Uninstantiate(&drbg); - return -1; - } - - if (Hash_DRBG_Uninstantiate(&drbg) != 0) { - return -1; - } - - return 0; -} - - -const byte entropyA[] = { +const byte seedA[] = { 0x63, 0x36, 0x33, 0x77, 0xe4, 0x1e, 0x86, 0x46, 0x8d, 0xeb, 0x0a, 0xb4, 0xa8, 0xed, 0x68, 0x3f, 0x6a, 0x13, 0x4e, 0x47, 0xe0, 0x14, 0xc7, 0x00, 0x45, 0x4e, 0x81, 0xe9, 0x53, 0x58, 0xa5, 0x69, 0x80, 0x8a, 0xa3, 0x8f, 0x2a, 0x72, 0xa6, 0x23, 0x59, 0x91, 0x5a, 0x9f, 0x8a, 0x04, 0xca, 0x68 }; -const byte reseedEntropyA[] = { +const byte reseedSeedA[] = { 0xe6, 0x2b, 0x8a, 0x8e, 0xe8, 0xf1, 0x41, 0xb6, 0x98, 0x05, 0x66, 0xe3, 0xbf, 0xe3, 0xc0, 0x49, 0x03, 0xda, 0xd4, 0xac, 0x2c, 0xdf, 0x9f, 0x22, 0x80, 0x01, 0x0a, 0x67, 0x39, 0xbc, 0x83, 0xd3 @@ -634,11 +1134,12 @@ const byte outputA[] = { 0xa1, 0x80, 0x18, 0x3a, 0x07, 0xdf, 0xae, 0x17 }; -const byte entropyB[] = { +const byte seedB[] = { 0xa6, 0x5a, 0xd0, 0xf3, 0x45, 0xdb, 0x4e, 0x0e, 0xff, 0xe8, 0x75, 0xc3, 0xa2, 0xe7, 0x1f, 0x42, 0xc7, 0x12, 0x9d, 0x62, 0x0f, 0xf5, 0xc1, 0x19, - 0xa9, 0xef, 0x55, 0xf0, 0x51, 0x85, 0xe0, 0xfb, 0x85, 0x81, 0xf9, 0x31, - 0x75, 0x17, 0x27, 0x6e, 0x06, 0xe9, 0x60, 0x7d, 0xdb, 0xcb, 0xcc, 0x2e + 0xa9, 0xef, 0x55, 0xf0, 0x51, 0x85, 0xe0, 0xfb, /* nonce next */ + 0x85, 0x81, 0xf9, 0x31, 0x75, 0x17, 0x27, 0x6e, 0x06, 0xe9, 0x60, 0x7d, + 0xdb, 0xcb, 0xcc, 0x2e }; const byte outputB[] = { @@ -659,320 +1160,423 @@ const byte outputB[] = { static int wc_RNG_HealthTestLocal(int reseed) { int ret = 0; - byte check[SHA256_DIGEST_SIZE * 4]; +#ifdef WOLFSSL_SMALL_STACK + byte* check; +#else + byte check[RNG_HEALTH_TEST_CHECK_SIZE]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + check = (byte*)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (check == NULL) { + return MEMORY_E; + } +#endif if (reseed) { - ret = wc_RNG_HealthTest(1, entropyA, sizeof(entropyA), - reseedEntropyA, sizeof(reseedEntropyA), - check, sizeof(check)); + ret = wc_RNG_HealthTest(1, seedA, sizeof(seedA), + reseedSeedA, sizeof(reseedSeedA), + check, RNG_HEALTH_TEST_CHECK_SIZE); if (ret == 0) { - if (ConstantCompare(check, outputA, sizeof(check)) != 0) + if (ConstantCompare(check, outputA, + RNG_HEALTH_TEST_CHECK_SIZE) != 0) ret = -1; } } else { - ret = wc_RNG_HealthTest(0, entropyB, sizeof(entropyB), + ret = wc_RNG_HealthTest(0, seedB, sizeof(seedB), NULL, 0, - check, sizeof(check)); + check, RNG_HEALTH_TEST_CHECK_SIZE); if (ret == 0) { - if (ConstantCompare(check, outputB, sizeof(check)) != 0) + if (ConstantCompare(check, outputB, + RNG_HEALTH_TEST_CHECK_SIZE) != 0) ret = -1; } + + /* The previous test cases use a large seed instead of a seed and nonce. + * seedB is actually from a test case with a seed and nonce, and + * just concatenates them. The pivot point between seed and nonce is + * byte 32, feed them into the health test separately. */ + if (ret == 0) { + ret = wc_RNG_HealthTest_ex(0, + seedB + 32, sizeof(seedB) - 32, + seedB, 32, + NULL, 0, + check, RNG_HEALTH_TEST_CHECK_SIZE, + NULL, INVALID_DEVID); + if (ret == 0) { + if (ConstantCompare(check, outputB, sizeof(outputB)) != 0) + ret = -1; + } + } } +#ifdef WOLFSSL_SMALL_STACK + XFREE(check, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; } +#endif /* HAVE_HASHDRBG */ -#else /* HAVE_HASHDRBG || NO_RC4 */ -/* Get seed and key cipher */ -int wc_InitRng(RNG* rng) +#ifdef HAVE_WNR + +/* + * Init global Whitewood netRandom context + * Returns 0 on success, negative on error + */ +int wc_InitNetRandom(const char* configFile, wnr_hmac_key hmac_cb, int timeout) { - int ret; -#ifdef WOLFSSL_SMALL_STACK - byte* key; - byte* junk; -#else - byte key[32]; - byte junk[256]; -#endif + if (configFile == NULL || timeout < 0) + return BAD_FUNC_ARG; -#ifdef HAVE_INTEL_RDGEN - wc_InitRng_IntelRD() ; - if(IS_INTEL_RDRAND)return 0 ; -#endif -#ifdef HAVE_CAVIUM - if (rng->magic == WOLFSSL_RNG_CAVIUM_MAGIC) + if (wnr_mutex_init > 0) { + WOLFSSL_MSG("netRandom context already created, skipping"); return 0; -#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); - 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 + if (wc_InitMutex(&wnr_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex wnr_mutex"); + return BAD_MUTEX_E; + } + wnr_mutex_init = 1; - return ret; -} + if (wc_LockMutex(&wnr_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex wnr_mutex"); + return BAD_MUTEX_E; + } -#ifdef HAVE_CAVIUM - static void CaviumRNG_GenerateBlock(RNG* rng, byte* output, word32 sz); -#endif + /* store entropy timeout */ + wnr_timeout = timeout; -/* place a generated block in output */ -int wc_RNG_GenerateBlock(RNG* rng, byte* output, word32 sz) -{ -#ifdef HAVE_INTEL_RDGEN - if(IS_INTEL_RDRAND) - return wc_GenerateRand_IntelRD(NULL, output, sz) ; -#endif -#ifdef HAVE_CAVIUM - if (rng->magic == WOLFSSL_RNG_CAVIUM_MAGIC) - return CaviumRNG_GenerateBlock(rng, output, sz); -#endif - XMEMSET(output, 0, sz); - wc_Arc4Process(&rng->cipher, output, output, sz); + /* create global wnr_context struct */ + if (wnr_create(&wnr_ctx) != WNR_ERROR_NONE) { + WOLFSSL_MSG("Error creating global netRandom context"); + return RNG_FAILURE_E; + } + + /* load config file */ + if (wnr_config_loadf(wnr_ctx, (char*)configFile) != WNR_ERROR_NONE) { + WOLFSSL_MSG("Error loading config file into netRandom context"); + wnr_destroy(wnr_ctx); + wnr_ctx = NULL; + return RNG_FAILURE_E; + } + + /* create/init polling mechanism */ + if (wnr_poll_create() != WNR_ERROR_NONE) { + printf("ERROR: wnr_poll_create() failed\n"); + WOLFSSL_MSG("Error initializing netRandom polling mechanism"); + wnr_destroy(wnr_ctx); + wnr_ctx = NULL; + return RNG_FAILURE_E; + } + + /* validate config, set HMAC callback (optional) */ + if (wnr_setup(wnr_ctx, hmac_cb) != WNR_ERROR_NONE) { + WOLFSSL_MSG("Error setting up netRandom context"); + wnr_destroy(wnr_ctx); + wnr_ctx = NULL; + wnr_poll_destroy(); + return RNG_FAILURE_E; + } + + wc_UnLockMutex(&wnr_mutex); return 0; } - -int wc_RNG_GenerateByte(RNG* rng, byte* b) +/* + * Free global Whitewood netRandom context + * Returns 0 on success, negative on error + */ +int wc_FreeNetRandom(void) { - return wc_RNG_GenerateBlock(rng, b, 1); -} + if (wnr_mutex_init > 0) { - -int wc_FreeRng(RNG* rng) -{ - (void)rng; - return 0; -} - - -#ifdef HAVE_CAVIUM - -#include -#include "cavium_common.h" - -/* Initiliaze RNG for use with Nitrox device */ -int wc_InitRngCavium(RNG* rng, int devId) -{ - if (rng == NULL) - return -1; - - rng->devId = devId; - rng->magic = WOLFSSL_RNG_CAVIUM_MAGIC; - - return 0; -} - - -static void CaviumRNG_GenerateBlock(RNG* rng, byte* output, word32 sz) -{ - wolfssl_word offset = 0; - word32 requestId; - - while (sz > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - if (CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId, - rng->devId) != 0) { - WOLFSSL_MSG("Cavium RNG failed"); + if (wc_LockMutex(&wnr_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex wnr_mutex"); + return BAD_MUTEX_E; } - sz -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - } - if (sz) { - word16 slen = (word16)sz; - if (CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId, - rng->devId) != 0) { - WOLFSSL_MSG("Cavium RNG failed"); + + if (wnr_ctx != NULL) { + wnr_destroy(wnr_ctx); + wnr_ctx = NULL; } + wnr_poll_destroy(); + + wc_UnLockMutex(&wnr_mutex); + + wc_FreeMutex(&wnr_mutex); + wnr_mutex_init = 0; } + + return 0; } -#endif /* HAVE_CAVIUM */ - -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#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) +#ifdef HAVE_INTEL_RDSEED - #define XASM_LINK(f) +#ifndef USE_WINDOWS_API -#endif /* _MSC_VER */ + /* return 0 on success */ + static WC_INLINE int IntelRDseed64(word64* seed) + { + unsigned char ok; -#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(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) ; + __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok)); + return (ok) ? 0 : -1; } - return 0 ; -} -static int wc_InitRng_IntelRD() +#else /* USE_WINDOWS_API */ + /* The compiler Visual Studio uses does not allow inline assembly. + * It does allow for Intel intrinsic functions. */ + + /* return 0 on success */ + static WC_INLINE int IntelRDseed64(word64* seed) + { + int ok; + + ok = _rdseed64_step(seed); + return (ok) ? 0 : -1; + } + +#endif /* USE_WINDOWS_API */ + +/* return 0 on success */ +static WC_INLINE int IntelRDseed64_r(word64* rnd) { - 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 ; + int i; + for (i = 0; i < INTELRD_RETRY; i++) { + if (IntelRDseed64(rnd) == 0) + return 0; } - return 1 ; -} - -#define INTELRD_RETRY 10 - -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) - -/* return 0 on success */ -static inline int IntelRDseed32(unsigned int *seed) -{ - int rdseed; unsigned char ok ; - - __asm__ volatile("rdseed %0; setc %1":"=r"(rdseed), "=qm"(ok)); - if(ok){ - *seed = rdseed ; - return 0 ; - } else - return 1; -} - -/* return 0 on success */ -static inline int IntelRDseed32_r(unsigned int *rnd) -{ - int i ; - for(i=0; i 0; sz-=4, output+=4) { - if(IS_INTEL_RDSEED)ret = IntelRDseed32_r((word32 *)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); + ForceZero(&rndTmp, sizeof(rndTmp)); - if(IS_INTEL_RDSEED)ret = IntelRDseed32_r(&rndTmp) ; - else return 1 ; - if(ret) - return 1 ; - XMEMCPY(output, &rndTmp, sz) ; return 0; } -#else +#endif /* HAVE_INTEL_RDSEED */ + +#ifdef HAVE_INTEL_RDRAND + +#ifndef USE_WINDOWS_API /* return 0 on success */ -static inline int IntelRDrand32(unsigned int *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; +static WC_INLINE int IntelRDrand64(word64 *rnd) +{ + unsigned char ok; + + __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok)); + + return (ok) ? 0 : -1; } +#else /* USE_WINDOWS_API */ + /* The compiler Visual Studio uses does not allow inline assembly. + * It does allow for Intel intrinsic functions. */ + /* return 0 on success */ -static inline int IntelRDrand32_r(unsigned int *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 */ -#if defined(USE_WINDOWS_API) +/* Begin wc_GenerateSeed Implementations */ +#if defined(CUSTOM_RAND_GENERATE_SEED) + /* Implement your own random generation function + * Return 0 to indicate success + * int rand_gen_seed(byte* output, word32 sz); + * #define CUSTOM_RAND_GENERATE_SEED rand_gen_seed */ + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + (void)os; /* Suppress unused arg warning */ + return CUSTOM_RAND_GENERATE_SEED(output, sz); + } + +#elif defined(CUSTOM_RAND_GENERATE_SEED_OS) + + /* Implement your own random generation function, + * which includes OS_Seed. + * Return 0 to indicate success + * int rand_gen_seed(OS_Seed* os, byte* output, word32 sz); + * #define CUSTOM_RAND_GENERATE_SEED_OS rand_gen_seed */ + + int wc_GenerateSeed(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) { + int ret = !SGX_SUCCESS; + int i, read_max = 10; + + for (i = 0; i < read_max && ret != SGX_SUCCESS; i++) { + ret = sgx_read_rand(output, sz); + } + + (void)os; + return (ret == SGX_SUCCESS) ? 0 : 1; +} + +#elif defined(USE_WINDOWS_API) + +int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) +{ +#ifdef WOLF_CRYPTO_CB + int ret; + + if (os != NULL && os->devId != INVALID_DEVID) { + ret = wc_CryptoCb_RandomSeed(os, output, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif + + #ifdef HAVE_INTEL_RDSEED + if (IS_INTEL_RDSEED(intel_flags)) { + if (!wc_GenerateSeed_IntelRD(NULL, output, sz)) { + /* success, we're done */ + return 0; + } + #ifdef FORCE_FAILURE_RDSEED + /* don't fall back to CryptoAPI */ + return READ_RAN_E; + #endif + } + #endif /* HAVE_INTEL_RDSEED */ + if(!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) return WINCRYPT_E; @@ -991,92 +1595,85 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #include "rtprand.h" /* rtp_rand () */ #include "rtptime.h" /* rtp_get_system_msec() */ - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { - int i; - rtp_srand(rtp_get_system_msec()); + word32 i; + rtp_srand(rtp_get_system_msec()); for (i = 0; i < sz; i++ ) { output[i] = rtp_rand() % 256; - if ( (i % 8) == 7) - rtp_srand(rtp_get_system_msec()); } return 0; } -#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(MBED) - -/* write a real one !!!, just for testing board */ -int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - int i; - for (i = 0; i < sz; i++ ) - output[i] = i; - - 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 + #ifdef MICROCHIP_MPLAB_HARMONY_3 + #include "system/time/sys_time.h" + #define PIC32_SEED_COUNT SYS_TIME_CounterGet + #else + #define PIC32_SEED_COUNT _CP0_GET_COUNT + #endif + #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, y; + x = RNGNUMGEN1; + y = RNGNUMGEN2; + (void)x; + (void)y; } 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) { @@ -1090,11 +1687,12 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) } return 0; } - #endif /* WOLFSSL_MIC32MZ_RNG */ + #endif /* WOLFSSL_PIC32MZ_RNG */ -#elif defined(FREESCALE_MQX) +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) || \ + defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) - #ifdef FREESCALE_K70_RNGA + #if defined(FREESCALE_K70_RNGA) || defined(FREESCALE_RNGA) /* * wc_Generates a RNG seed using the Random Number Generator Accelerator * on the Kinetis K70. Documentation located in Chapter 37 of @@ -1102,10 +1700,16 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) */ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { - int i; + word32 i; /* turn on RNGA module */ - SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK; + #if defined(SIM_SCGC3_RNGA_MASK) + SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK; + #endif + #if defined(SIM_SCGC6_RNGA_MASK) + /* additionally needed for at least K64F */ + SIM_SCGC6 |= SIM_SCGC6_RNGA_MASK; + #endif /* set SLP bit to 0 - "RNGA is not in sleep mode" */ RNG_CR &= ~RNG_CR_SLP_MASK; @@ -1128,7 +1732,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } - #elif defined(FREESCALE_K53_RNGB) + #elif defined(FREESCALE_K53_RNGB) || defined(FREESCALE_RNGB) /* * wc_Generates a RNG seed using the Random Number Generator (RNGB) * on the Kinetis K53. Documentation located in Chapter 33 of @@ -1166,78 +1770,191 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } - #else - #warning "write a real random seed!!!!, just for testing now" + #elif defined(FREESCALE_KSDK_2_0_TRNG) int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { - int i; - for (i = 0; i < sz; i++ ) - output[i] = i; + status_t status; + status = TRNG_GetRandomData(TRNG0, output, sz); + if (status == kStatus_Success) + { + return(0); + } + else + { + return RAN_BLOCK_E; + } + } + #elif defined(FREESCALE_KSDK_2_0_RNGA) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + status_t status; + status = RNGA_GetRandomData(RNG, output, sz); + if (status == kStatus_Success) + { + return(0); + } + else + { + return RAN_BLOCK_E; + } + } + + + #elif defined(FREESCALE_RNGA) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + RNGA_DRV_GetRandomData(RNGA_INSTANCE, output, sz); return 0; } + + #else + #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) +#elif defined(STM32_RNG) + /* Generate a RNG seed using the hardware random number generator + * on the STM32F2/F4/F7/L4. */ -#warning "write a real random seed!!!!, just for testing now" - -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) - #undef RNG - #include "stm32f2xx_rng.h" - #include "stm32f2xx_rcc.h" - /* - * wc_Generate a RNG seed using the hardware random number generator - * on the STM32F2. Documentation located in STM32F2xx Standard Peripheral - * Library document (See note in README). - */ + #ifdef WOLFSSL_STM32_CUBEMX int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { - int i; + int ret; + RNG_HandleTypeDef hrng; + word32 i = 0; + (void)os; + + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + /* enable RNG clock source */ + __HAL_RCC_RNG_CLK_ENABLE(); + + /* enable RNG peripheral */ + XMEMSET(&hrng, 0, sizeof(hrng)); + hrng.Instance = RNG; + HAL_RNG_Init(&hrng); + + while (i < sz) { + /* If not aligned or there is odd/remainder */ + if( (i + sizeof(word32)) > sz || + ((wolfssl_word)&output[i] % sizeof(word32)) != 0 + ) { + /* Single byte at a time */ + uint32_t tmpRng = 0; + if (HAL_RNG_GenerateRandomNumber(&hrng, &tmpRng) != HAL_OK) { + wolfSSL_CryptHwMutexUnLock(); + return RAN_BLOCK_E; + } + output[i++] = (byte)tmpRng; + } + else { + /* Use native 32 instruction */ + if (HAL_RNG_GenerateRandomNumber(&hrng, (uint32_t*)&output[i]) != HAL_OK) { + wolfSSL_CryptHwMutexUnLock(); + return RAN_BLOCK_E; + } + i += sizeof(word32); + } + } + + wolfSSL_CryptHwMutexUnLock(); + + return 0; + } + #elif defined(WOLFSSL_STM32F427_RNG) || defined(WOLFSSL_STM32_RNG_NOLIB) + + /* Generate a RNG seed using the hardware RNG on the STM32F427 + * directly, following steps outlined in STM32F4 Reference + * Manual (Chapter 24) for STM32F4xx family. */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret; + word32 i; + (void)os; + + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + /* enable RNG peripheral clock */ + RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN; + + /* enable RNG interrupt, set IE bit in RNG->CR register */ + RNG->CR |= RNG_CR_IE; + + /* enable RNG, set RNGEN bit in RNG->CR. Activates RNG, + * RNG_LFSR, and error detector */ + RNG->CR |= RNG_CR_RNGEN; + + /* verify no errors, make sure SEIS and CEIS bits are 0 + * in RNG->SR register */ + if (RNG->SR & (RNG_SR_SECS | RNG_SR_CECS)) { + wolfSSL_CryptHwMutexUnLock(); + return RNG_FAILURE_E; + } + + for (i = 0; i < sz; i++) { + /* wait until RNG number is ready */ + while ((RNG->SR & RNG_SR_DRDY) == 0) { } + + /* get value */ + output[i] = RNG->DR; + } + + wolfSSL_CryptHwMutexUnLock(); + + return 0; + } + + #else + + /* Generate a RNG seed using the STM32 Standard Peripheral Library */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret; + word32 i; + (void)os; + + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } /* 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) { + wolfSSL_CryptHwMutexUnLock(); + return RNG_FAILURE_E; + } + for (i = 0; i < 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(); } - return 0; - } -#elif defined(WOLFSSL_LPC43xx) || defined(WOLFSSL_STM32F2xx) - - #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; + wolfSSL_CryptHwMutexUnLock(); return 0; } + #endif /* WOLFSSL_STM32_CUBEMX */ #elif defined(WOLFSSL_TIRTOS) @@ -1258,82 +1975,578 @@ 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 */ +#elif defined(WOLFSSL_PB) int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { word32 i; + for (i = 0; i < sz; i++) + output[i] = UTL_Rand(); (void)os; - for (i = 0; i < sz; i++ ) - output[i] = CUSTOM_RAND_GENERATE(); - return 0; } -#elif defined(NO_DEV_RANDOM) +#elif defined(WOLFSSL_NUCLEUS) +#include "nucleus.h" +#include "kernel/plus_common.h" -#error "you need to write an os specific wc_GenerateSeed() here" - -/* +#warning "potential for not enough entropy, currently being used for testing" int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { + int i; + srand(NU_Get_Time_Stamp()); + + for (i = 0; i < sz; i++ ) { + output[i] = rand() % 256; + if ((i % 8) == 7) { + srand(NU_Get_Time_Stamp()); + } + } + return 0; } -*/ +#elif defined(WOLFSSL_DEOS) && !defined(CUSTOM_RAND_GENERATE) + #include "stdlib.h" + #warning "potential for not enough entropy, currently being used for testing Deos" + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + int seed = XTIME(0); + (void)os; -#else /* !USE_WINDOWS_API && !HAVE_RPT_SYS && !MICRIUM && !NO_DEV_RANDOM */ - -/* may block */ -int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - int ret = 0; - - -#if defined(HAVE_INTEL_RDGEN) && (defined(HAVE_HASHDRBG) || defined(NO_RC4)) - wc_InitRng_IntelRD() ; /* set cpuid_flags if not yet */ - if(IS_INTEL_RDSEED) - return wc_GenerateSeed_IntelRD(NULL, output, sz) ; -#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; + for (i = 0; i < sz; i++ ) { + output[i] = rand_r(&seed) % 256; + if ((i % 8) == 7) { + seed = XTIME(0); + rand_r(&seed); + } } - sz -= len; - output += len; + return 0; + } +#elif defined(WOLFSSL_VXWORKS) + + #include + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { + STATUS status; + + #ifdef VXWORKS_SIM + /* cannot generate true entropy with VxWorks simulator */ + #warning "not enough entropy, simulator for testing only" + int i = 0; + + for (i = 0; i < 1000; i++) { + randomAddTimeStamp(); + } + #endif + + status = randBytes (output, sz); + if (status == ERROR) { + return RNG_FAILURE_E; + } + + return 0; + } + +#elif defined(WOLFSSL_NRF51) + #include "app_error.h" + #include "nrf_drv_rng.h" + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int remaining = sz, length, pos = 0; + uint8_t available; + uint32_t err_code; + + (void)os; + + /* Make sure RNG is running */ + err_code = nrf_drv_rng_init(NULL); + if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) { + return -1; + } + + while (remaining > 0) { + err_code = nrf_drv_rng_bytes_available(&available); + if (err_code == NRF_SUCCESS) { + length = (remaining < available) ? remaining : available; + if (length > 0) { + err_code = nrf_drv_rng_rand(&output[pos], length); + remaining -= length; + pos += length; + } + } + + if (err_code != NRF_SUCCESS) { + break; + } + } + + return (err_code == NRF_SUCCESS) ? 0 : -1; + } + +#elif defined(HAVE_WNR) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + if (os == NULL || output == NULL || wnr_ctx == NULL || + wnr_timeout < 0) { + return BAD_FUNC_ARG; + } + + if (wnr_mutex_init == 0) { + WOLFSSL_MSG("netRandom context must be created before use"); + return RNG_FAILURE_E; + } + + if (wc_LockMutex(&wnr_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex wnr_mutex\n"); + return BAD_MUTEX_E; + } + + if (wnr_get_entropy(wnr_ctx, wnr_timeout, output, sz, sz) != + WNR_ERROR_NONE) + return RNG_FAILURE_E; + + wc_UnLockMutex(&wnr_mutex); + + return 0; + } + +#elif defined(WOLFSSL_ATMEL) + #include + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; + + (void)os; + if (output == NULL) { + return BUFFER_E; + } + + ret = atmel_get_random_number(sz, output); + + return ret; + } + +#elif defined(INTIME_RTOS) + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; + + (void)os; + + if (output == NULL) { + return BUFFER_E; + } + + /* Note: Investigate better solution */ + /* no return to check */ + arc4random_buf(output, sz); + + return ret; + } + +#elif defined(WOLFSSL_WICED) + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret; + (void)os; + + if (output == NULL || UINT16_MAX < sz) { + return BUFFER_E; + } + + if ((ret = wiced_crypto_get_random((void*) output, sz) ) + != WICED_SUCCESS) { + return ret; + } + + return ret; + } + +#elif defined(WOLFSSL_NETBURNER) + #warning using NetBurner pseudo random GetRandomByte for seed + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 i; + (void)os; + + if (output == NULL) { + return BUFFER_E; + } + + for (i = 0; i < sz; i++) { + output[i] = GetRandomByte(); + + /* check if was a valid random number */ + if (!RandomValid()) + return RNG_FAILURE_E; + } + + return 0; + } +#elif defined(IDIRECT_DEV_RANDOM) + + extern int getRandom( int sz, unsigned char *output ); + + int GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int num_bytes_returned = 0; + + num_bytes_returned = getRandom( (int) sz, (unsigned char *) output ); + + return 0; + } + +#elif (defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG)) + + #include + #include + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + Buffer buf[1]; + int ret = 0; + int times = 1000, i; + + (void)os; + + if (output == NULL) { + return BUFFER_E; + } + + buf[0].BufferType = DataBuffer | LastBuffer; + buf[0].TheAddress = (Address)output; + buf[0].Length = sz; + + /* Check Waiting to make sure entropy is ready */ + for (i = 0; i < times; i++) { + ret = wc_caamAddAndWait(buf, NULL, CAAM_ENTROPY); + if (ret == Success) { + break; + } + + /* driver could be waiting for entropy */ + if (ret != RAN_BLOCK_E) { + return ret; + } + usleep(100); + } + + if (i == times && ret != Success) { + return RNG_FAILURE_E; + } + else { /* Success case */ + ret = 0; + } + + return ret; + } + +#elif defined(WOLFSSL_APACHE_MYNEWT) + + #include + #include "os/os_time.h" + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + srand(os_time_get()); + + for (i = 0; i < sz; i++ ) { + output[i] = rand() % 256; + if ((i % 8) == 7) { + srand(os_time_get()); + } + } + + return 0; + } + +#elif defined(WOLFSSL_ESPIDF) + #if defined(WOLFSSL_ESPWROOM32) || defined(WOLFSSL_ESPWROOM32SE) + #include + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 rand; + while (sz > 0) { + word32 len = sizeof(rand); + if (sz < len) + len = sz; + /* Get one random 32-bit word from hw RNG */ + rand = esp_random( ); + XMEMCPY(output, &rand, len); + output += len; + sz -= len; + } + + return 0; + } + #endif /* end WOLFSSL_ESPWROOM32 */ + +#elif defined(WOLFSSL_RENESAS_TSIP) +#if defined(WOLFSSL_RENESA_TSIP_IAREWRX) + #include "r_bsp/mcu/all/r_rx_compiler.h" +#endif + #include "r_bsp/platform.h" + #include "r_tsip_rx_if.h" + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret; + uint32_t buffer[4]; + + while (sz > 0) { + uint32_t len = sizeof(buffer); + + if (sz < len) { + len = sz; + } + /* return 4 words random number*/ + ret = R_TSIP_GenerateRandomNumber(buffer); + if(ret == TSIP_SUCCESS) { + XMEMCPY(output, &buffer, len); + output += len; + sz -= len; + } else + return ret; + } + return ret; + } + +#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG) + #include "hal_data.h" + + #ifndef WOLFSSL_SCE_TRNG_HANDLE + #define WOLFSSL_SCE_TRNG_HANDLE g_sce_trng + #endif + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + uint32_t ret; + uint32_t blocks; + word32 len = sz; + + ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->open(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl, + WOLFSSL_SCE_TRNG_HANDLE.p_cfg); + if (ret != SSP_SUCCESS && ret != SSP_ERR_CRYPTO_ALREADY_OPEN) { + /* error opening TRNG driver */ + return -1; + } + + blocks = sz / sizeof(uint32_t); + if (blocks > 0) { + ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->read(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl, + (uint32_t*)output, blocks); + if (ret != SSP_SUCCESS) { + return -1; + } + } + + len = len - (blocks * sizeof(uint32_t)); + if (len > 0) { + uint32_t tmp; + + if (len > sizeof(uint32_t)) { + return -1; + } + ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->read(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl, + (uint32_t*)tmp, 1); + if (ret != SSP_SUCCESS) { + return -1; + } + XMEMCPY(output + (blocks * sizeof(uint32_t)), (byte*)&tmp, len); + } + + ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->close(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl); + if (ret != SSP_SUCCESS) { + /* error opening TRNG driver */ + return -1; + } + return 0; + } +#elif defined(CUSTOM_RAND_GENERATE_BLOCK) + /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc + * extern int myRngFunc(byte* output, word32 sz); + */ + +#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) || \ + defined(WOLFSSL_CONTIKI) || defined(WOLFSSL_AZSPHERE) + + /* 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 + +#elif defined(WOLFSSL_ZEPHYR) + + #include + #ifndef _POSIX_C_SOURCE + #include + #else + #include + #endif + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; + word32 rand; + while (sz > 0) { + word32 len = sizeof(rand); + if (sz < len) + len = sz; + rand = sys_rand32_get(); + XMEMCPY(output, &rand, len); + output += len; + sz -= len; + } + + return ret; + } + +#elif defined(WOLFSSL_TELIT_M2MB) + + #include "stdlib.h" + static long get_timestamp(void) { + long myTime = 0; + INT32 fd = m2mb_rtc_open("/dev/rtc0", 0); + if (fd >= 0) { + M2MB_RTC_TIMEVAL_T timeval; + m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval); + myTime = timeval.msec; + m2mb_rtc_close(fd); + } + return myTime; + } + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + srand(get_timestamp()); + for (i = 0; i < sz; i++ ) { + output[i] = rand() % 256; + if ((i % 8) == 7) { + srand(get_timestamp()); + } + } + return 0; + } + +#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; + } + */ - if (sz) { -#ifdef BLOCKING - sleep(0); /* context switch */ #else - ret = RAN_BLOCK_E; - break; -#endif + + /* may block */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; + + if (os == NULL) { + return BAD_FUNC_ARG; } + + #ifdef WOLF_CRYPTO_CB + if (os->devId != INVALID_DEVID) { + ret = wc_CryptoCb_RandomSeed(os, output, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; /* reset error code */ + } + #endif + + #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; + #else + /* reset error and fallback to using /dev/urandom */ + ret = 0; + #endif + } + #endif /* HAVE_INTEL_RDSEED */ + + #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */ + os->fd = open("/dev/urandom", O_RDONLY); + if (os->fd == -1) + #endif + { + /* 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) { + #if defined(BLOCKING) || defined(WC_RNG_BLOCKING) + sleep(0); /* context switch */ + #else + ret = RAN_BLOCK_E; + break; + #endif + } + } + close(os->fd); + + return ret; } - close(os->fd); - return ret; -} +#endif -#endif /* USE_WINDOWS_API */ +#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 /* WC_NO_RNG */ #endif /* HAVE_FIPS */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ripemd.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ripemd.c index 639a42d07..484c62fe4 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ripemd.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/ripemd.c @@ -1,8 +1,8 @@ /* ripemd.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -32,22 +33,18 @@ #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif +#include -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; +int wc_InitRipeMd(RipeMd* ripemd) +{ + if (ripemd == NULL) { + return BAD_FUNC_ARG; } -#endif /* WOLFSSL_HAVE_MIN */ - -void wc_InitRipeMd(RipeMd* ripemd) -{ ripemd->digest[0] = 0x67452301L; ripemd->digest[1] = 0xEFCDAB89L; ripemd->digest[2] = 0x98BADCFEL; @@ -57,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))) @@ -195,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); @@ -272,7 +271,7 @@ static void Transform(RipeMd* ripemd) } -static INLINE void AddLength(RipeMd* ripemd, word32 len) +static WC_INLINE void AddLength(RipeMd* ripemd, word32 len) { word32 tmp = ripemd->loLen; if ( (ripemd->loLen += len) < tmp) @@ -280,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); @@ -303,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 */ @@ -326,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 */ @@ -338,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); @@ -347,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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/rsa.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/rsa.c index 1a5021783..69ab7b21b 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/rsa.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/rsa.c @@ -1,8 +1,8 @@ /* rsa.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,22 +16,82 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include +#include #ifndef NO_RSA +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$e") + #pragma const_seg(".fipsB$e") + #endif +#endif + #include -#ifdef HAVE_FIPS +#ifdef WOLFSSL_AFALG_XILINX_RSA +#include +#endif + +#ifdef WOLFSSL_HAVE_SP_RSA +#include +#endif + +/* +Possible RSA enable options: + * NO_RSA: Overall control of RSA default: on (not defined) + * WC_RSA_BLINDING: Uses Blinding w/ Private Ops default: off + Note: slower by ~20% + * WOLFSSL_KEY_GEN: Allows Private Key Generation default: off + * RSA_LOW_MEM: NON CRT Private Operations, less memory default: off + * WC_NO_RSA_OAEP: Disables RSA OAEP padding default: on (not defined) + * WC_RSA_NONBLOCK: Enables support for RSA non-blocking default: off + * WC_RSA_NONBLOCK_TIME:Enables support for time based blocking default: off + * time calculation. +*/ + +/* +RSA Key Size Configuration: + * FP_MAX_BITS: With USE_FAST_MATH only default: 4096 + If USE_FAST_MATH then use this to override default. + Value is key size * 2. Example: RSA 3072 = 6144 +*/ + + +/* If building for old FIPS. */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + 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); } @@ -42,16 +102,25 @@ int wc_FreeRsaKey(RsaKey* key) } +#ifndef WOLFSSL_RSA_VERIFY_ONLY int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key, RNG* rng) + 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); } +#endif +#ifndef WOLFSSL_RSA_PUBLIC_ONLY 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); } @@ -59,19 +128,29 @@ 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); } int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key, RNG* rng) + 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); } +#endif 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); } @@ -79,177 +158,1123 @@ 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); } +#ifndef WOLFSSL_RSA_VERIFY_ONLY 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); } +#endif + + #ifdef WOLFSSL_KEY_GEN - int wc_MakeRsaKey(RsaKey* key, int size, long e, RNG* rng) + int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) { return MakeRsaKey(key, size, e, rng); } #endif -#ifdef HAVE_CAVIUM - int wc_RsaInitCavium(RsaKey* key, int i) - { - return RsaInitCavium(key, i); - } - - - void wc_RsaFreeCavium(RsaKey* key) - { - RsaFreeCavium(key); - } -#endif - /* these are functions in asn and are routed to wolfssl/wolfcrypt/asn.c * wc_RsaPrivateKeyDecode * wc_RsaPublicKeyDecode */ -#else /* else build without fips */ +#else /* else build without fips, or for new fips */ + #include -#include #include +#ifdef WOLF_CRYPTO_CB + #include +#endif #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif -#ifdef SHOW_GEN - #ifdef FREESCALE_MQX - #include - #else - #include - #endif -#endif - -#ifdef HAVE_CAVIUM - static int InitCaviumRsaKey(RsaKey* key, void* heap); - static int FreeCaviumRsaKey(RsaKey* key); - static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key); - static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key); - static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key); - static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key); -#endif enum { - RSA_PUBLIC_ENCRYPT = 0, - RSA_PUBLIC_DECRYPT = 1, - RSA_PRIVATE_ENCRYPT = 2, - RSA_PRIVATE_DECRYPT = 3, + RSA_STATE_NONE = 0, - RSA_BLOCK_TYPE_1 = 1, - RSA_BLOCK_TYPE_2 = 2, + RSA_STATE_ENCRYPT_PAD, + RSA_STATE_ENCRYPT_EXPTMOD, + RSA_STATE_ENCRYPT_RES, - RSA_MIN_SIZE = 512, - RSA_MAX_SIZE = 4096, - - RSA_MIN_PAD_SZ = 11 /* seperator + 0 + pad value + 8 pads */ + RSA_STATE_DECRYPT_EXPTMOD, + RSA_STATE_DECRYPT_UNPAD, + RSA_STATE_DECRYPT_RES, }; -int wc_InitRsaKey(RsaKey* key, void* heap) +static void wc_RsaCleanup(RsaKey* key) { -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return InitCaviumRsaKey(key, heap); -#endif - - key->type = -1; /* haven't decided yet */ - key->heap = heap; - -/* TomsFastMath doesn't use memory allocation */ -#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; +#ifndef WOLFSSL_RSA_VERIFY_INLINE + if (key && key->data) { + /* make sure any allocated memory is free'd */ + if (key->dataIsAlloc) { + #ifndef WOLFSSL_RSA_PUBLIC_ONLY + if (key->type == RSA_PRIVATE_DECRYPT || + key->type == RSA_PRIVATE_ENCRYPT) { + ForceZero(key->data, key->dataLen); + } + #endif + XFREE(key->data, key->heap, DYNAMIC_TYPE_WOLF_BIGINT); + key->dataIsAlloc = 0; + } + key->data = NULL; + key->dataLen = 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); + (void)key; #endif - - return 0; } +int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) +{ + int ret = 0; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(key, 0, sizeof(RsaKey)); + + key->type = RSA_TYPE_UNKNOWN; + key->state = RSA_STATE_NONE; + key->heap = heap; +#ifndef WOLFSSL_RSA_VERIFY_INLINE + key->dataIsAlloc = 0; + key->data = NULL; +#endif + key->dataLen = 0; +#ifdef WC_RSA_BLINDING + key->rng = NULL; +#endif + +#ifdef WOLF_CRYPTO_CB + key->devId = devId; +#else + (void)devId; +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + #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, + key->heap, devId); + if (ret != 0) + return ret; + #endif /* WC_ASYNC_ENABLE_RSA */ +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + ret = mp_init_multi(&key->n, &key->e, NULL, NULL, NULL, NULL); + if (ret != MP_OKAY) + return ret; + +#if !defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM) + ret = mp_init_multi(&key->d, &key->p, &key->q, NULL, NULL, NULL); +#else + ret = mp_init_multi(&key->d, &key->p, &key->q, &key->dP, &key->dQ, &key->u); +#endif + if (ret != MP_OKAY) { + mp_clear(&key->n); + mp_clear(&key->e); + return ret; + } +#else + ret = mp_init(&key->n); + if (ret != MP_OKAY) + return ret; + ret = mp_init(&key->e); + if (ret != MP_OKAY) { + mp_clear(&key->n); + return ret; + } +#endif + +#ifdef WOLFSSL_XILINX_CRYPT + key->pubExp = 0; + key->mod = NULL; +#endif + +#ifdef WOLFSSL_AFALG_XILINX_RSA + key->alFd = WC_SOCK_NOTSET; + key->rdFd = WC_SOCK_NOTSET; +#endif + + return ret; +} + +int wc_InitRsaKey(RsaKey* key, void* heap) +{ + return wc_InitRsaKey_ex(key, heap, INVALID_DEVID); +} + +#ifdef HAVE_PKCS11 +int wc_InitRsaKey_Id(RsaKey* key, unsigned char* id, int len, void* heap, + int devId) +{ + int ret = 0; + + if (key == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0 && (len < 0 || len > RSA_MAX_ID_LEN)) + ret = BUFFER_E; + + if (ret == 0) + ret = wc_InitRsaKey_ex(key, heap, devId); + + if (ret == 0 && id != NULL && len != 0) { + XMEMCPY(key->id, id, len); + key->idLen = len; + } + + return ret; +} +#endif + + +#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; +} /* WOLFSSL_XILINX_CRYPT*/ + +#elif defined(WOLFSSL_CRYPTOCELL) + +int wc_InitRsaHw(RsaKey* key) +{ + CRYSError_t ret = 0; + byte e[3]; + word32 eSz = sizeof(e); + byte n[256]; + word32 nSz = sizeof(n); + byte d[256]; + word32 dSz = sizeof(d); + byte p[128]; + word32 pSz = sizeof(p); + byte q[128]; + word32 qSz = sizeof(q); + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, d, &dSz, p, &pSz, q, &qSz); + if (ret != 0) + return MP_READ_E; + + ret = CRYS_RSA_Build_PubKey(&key->ctx.pubKey, e, eSz, n, nSz); + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_Build_PubKey failed"); + return ret; + } + + ret = CRYS_RSA_Build_PrivKey(&key->ctx.privKey, d, dSz, e, eSz, n, nSz); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_Build_PrivKey failed"); + return ret; + } + key->type = RSA_PRIVATE; + return 0; +} +static int cc310_RSA_GenerateKeyPair(RsaKey* key, int size, long e) +{ + CRYSError_t ret = 0; + CRYS_RSAKGData_t KeyGenData; + CRYS_RSAKGFipsContext_t FipsCtx; + byte ex[3]; + uint16_t eSz = sizeof(ex); + byte n[256]; + uint16_t nSz = sizeof(n); + + ret = CRYS_RSA_KG_GenerateKeyPair(&wc_rndState, + wc_rndGenVectFunc, + (byte*)&e, + 3*sizeof(uint8_t), + size, + &key->ctx.privKey, + &key->ctx.pubKey, + &KeyGenData, + &FipsCtx); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_KG_GenerateKeyPair failed"); + return ret; + } + + ret = CRYS_RSA_Get_PubKey(&key->ctx.pubKey, ex, &eSz, n, &nSz); + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_Get_PubKey failed"); + return ret; + } + ret = wc_RsaPublicKeyDecodeRaw(n, nSz, ex, eSz, key); + + key->type = RSA_PRIVATE; + + return ret; +} +#endif /* WOLFSSL_CRYPTOCELL */ int wc_FreeRsaKey(RsaKey* key) { - (void)key; + int ret = 0; -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return FreeCaviumRsaKey(key); + if (key == NULL) { + return BAD_FUNC_ARG; + } + + wc_RsaCleanup(key); + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_RSA); #endif -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH +#ifndef WOLFSSL_RSA_PUBLIC_ONLY if (key->type == RSA_PRIVATE) { - mp_clear(&key->u); - mp_clear(&key->dQ); - mp_clear(&key->dP); - mp_clear(&key->q); - mp_clear(&key->p); - mp_clear(&key->d); +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + mp_forcezero(&key->u); + mp_forcezero(&key->dQ); + mp_forcezero(&key->dP); +#endif + mp_forcezero(&key->q); + mp_forcezero(&key->p); + mp_forcezero(&key->d); } + /* private part */ +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + mp_clear(&key->u); + mp_clear(&key->dQ); + mp_clear(&key->dP); +#endif + mp_clear(&key->q); + mp_clear(&key->p); + mp_clear(&key->d); +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + + /* 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 +#ifdef WOLFSSL_AFALG_XILINX_RSA + /* make sure that sockets are closed on cleanup */ + if (key->alFd > 0) { + close(key->alFd); + key->alFd = WC_SOCK_NOTSET; + } + if (key->rdFd > 0) { + close(key->rdFd); + key->rdFd = WC_SOCK_NOTSET; + } +#endif + + return ret; +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +#if defined(WOLFSSL_KEY_GEN) && !defined(WOLFSSL_NO_RSA_KEY_CHECK) +/* Check the pair-wise consistency of the RSA key. + * From NIST SP 800-56B, section 6.4.1.1. + * Verify that k = (k^e)^d, for some k: 1 < k < n-1. */ +int wc_CheckRsaKey(RsaKey* key) +{ +#if defined(WOLFSSL_CRYPTOCELL) + return 0; +#endif +#ifdef WOLFSSL_SMALL_STACK + mp_int *k = NULL, *tmp = NULL; +#else + mp_int k[1], tmp[1]; +#endif + int ret = 0; + +#ifdef WOLFSSL_SMALL_STACK + k = (mp_int*)XMALLOC(sizeof(mp_int) * 2, NULL, DYNAMIC_TYPE_RSA); + if (k == NULL) + return MEMORY_E; + tmp = k + 1; +#endif + + if (mp_init_multi(k, tmp, NULL, NULL, NULL, NULL) != MP_OKAY) + ret = MP_INIT_E; + + if (ret == 0) { + if (key == NULL) + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if (mp_set_int(k, 0x2342) != MP_OKAY) + ret = MP_READ_E; + } + +#ifdef WOLFSSL_HAVE_SP_RSA +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->n) == 2048) { + ret = sp_ModExp_2048(k, &key->e, &key->n, tmp); + if (ret != 0) + ret = MP_EXPTMOD_E; + ret = sp_ModExp_2048(tmp, &key->d, &key->n, tmp); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->n) == 3072) { + ret = sp_ModExp_3072(k, &key->e, &key->n, tmp); + if (ret != 0) + ret = MP_EXPTMOD_E; + ret = sp_ModExp_3072(tmp, &key->d, &key->n, tmp); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#ifdef WOLFSSL_SP_4096 + if (mp_count_bits(&key->n) == 4096) { + ret = sp_ModExp_4096(k, &key->e, &key->n, tmp); + if (ret != 0) + ret = MP_EXPTMOD_E; + ret = sp_ModExp_4096(tmp, &key->d, &key->n, tmp); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#endif +#ifdef WOLFSSL_SP_MATH + { + ret = WC_KEY_SIZE_E; + } +#else + { + if (ret == 0) { + if (mp_exptmod(k, &key->e, &key->n, tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + } + + if (ret == 0) { + if (mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + } + } +#endif + + if (ret == 0) { + if (mp_cmp(k, tmp) != MP_EQ) + ret = RSA_KEY_PAIR_E; + } + + /* Check d is less than n. */ + if (ret == 0 ) { + if (mp_cmp(&key->d, &key->n) != MP_LT) { + ret = MP_EXPTMOD_E; + } + } + /* Check p*q = n. */ + if (ret == 0 ) { + if (mp_mul(&key->p, &key->q, tmp) != MP_OKAY) { + ret = MP_EXPTMOD_E; + } + } + if (ret == 0 ) { + if (mp_cmp(&key->n, tmp) != MP_EQ) { + ret = MP_EXPTMOD_E; + } + } + + /* Check dP, dQ and u if they exist */ + if (ret == 0 && !mp_iszero(&key->dP)) { + if (mp_sub_d(&key->p, 1, tmp) != MP_OKAY) { + ret = MP_EXPTMOD_E; + } + /* Check dP <= p-1. */ + if (ret == 0) { + if (mp_cmp(&key->dP, tmp) != MP_LT) { + ret = MP_EXPTMOD_E; + } + } + /* Check e*dP mod p-1 = 1. (dP = 1/e mod p-1) */ + if (ret == 0) { + if (mp_mulmod(&key->dP, &key->e, tmp, tmp) != MP_OKAY) { + ret = MP_EXPTMOD_E; + } + } + if (ret == 0 ) { + if (!mp_isone(tmp)) { + ret = MP_EXPTMOD_E; + } + } + + if (ret == 0) { + if (mp_sub_d(&key->q, 1, tmp) != MP_OKAY) { + ret = MP_EXPTMOD_E; + } + } + /* Check dQ <= q-1. */ + if (ret == 0) { + if (mp_cmp(&key->dQ, tmp) != MP_LT) { + ret = MP_EXPTMOD_E; + } + } + /* Check e*dP mod p-1 = 1. (dQ = 1/e mod q-1) */ + if (ret == 0) { + if (mp_mulmod(&key->dQ, &key->e, tmp, tmp) != MP_OKAY) { + ret = MP_EXPTMOD_E; + } + } + if (ret == 0 ) { + if (!mp_isone(tmp)) { + ret = MP_EXPTMOD_E; + } + } + + /* Check u <= p. */ + if (ret == 0) { + if (mp_cmp(&key->u, &key->p) != MP_LT) { + ret = MP_EXPTMOD_E; + } + } + /* Check u*q mod p = 1. (u = 1/q mod p) */ + if (ret == 0) { + if (mp_mulmod(&key->u, &key->q, &key->p, tmp) != MP_OKAY) { + ret = MP_EXPTMOD_E; + } + } + if (ret == 0 ) { + if (!mp_isone(tmp)) { + ret = MP_EXPTMOD_E; + } + } + } + + mp_forcezero(tmp); + mp_clear(tmp); + mp_clear(k); +#ifdef WOLFSSL_SMALL_STACK + XFREE(k, NULL, DYNAMIC_TYPE_RSA); +#endif + + return ret; +} +#endif +#endif + + +#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 + seedSz: size of seed buffer + out: mask output after generation + outSz: size of output buffer + */ +#if !defined(NO_SHA) || !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) +static int RsaMGF1(enum wc_HashType hType, byte* seed, word32 seedSz, + byte* out, word32 outSz, void* heap) +{ + byte* tmp; + /* needs to be large enough for seed size plus counter(4) */ + byte tmpA[WC_MAX_DIGEST_SIZE + 4]; + byte tmpF; /* 1 if dynamic memory needs freed */ + word32 tmpSz; + int hLen; + int ret; + word32 counter; + word32 idx; + hLen = wc_HashGetDigestSize(hType); + counter = 0; + idx = 0; + + (void)heap; + + /* check error return of wc_HashGetDigestSize */ + if (hLen < 0) { + return hLen; + } + + /* if tmp is not large enough than use some dynamic memory */ + if ((seedSz + 4) > sizeof(tmpA) || (word32)hLen > sizeof(tmpA)) { + /* 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_RSA_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + tmpF = 1; /* make sure to free memory when done */ + } + else { + /* use array on the stack */ + tmpSz = sizeof(tmpA); + tmp = tmpA; + tmpF = 0; /* no need to free memory at end */ + } + + do { + int i = 0; + XMEMCPY(tmp, seed, seedSz); + + /* counter to byte array appended to tmp */ + tmp[seedSz] = (counter >> 24) & 0xFF; + tmp[seedSz + 1] = (counter >> 16) & 0xFF; + tmp[seedSz + 2] = (counter >> 8) & 0xFF; + tmp[seedSz + 3] = (counter) & 0xFF; + + /* hash and append to existing output */ + 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_RSA_BUFFER); + } + return ret; + } + + for (i = 0; i < hLen && idx < outSz; i++) { + out[idx++] = tmp[i]; + } + counter++; + } while (idx < outSz); + + /* check for if dynamic memory was needed, then free */ + if (tmpF) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + } + return 0; } +#endif /* SHA2 Hashes */ -static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, - word32 pkcsBlockLen, byte padValue, RNG* rng) +/* helper function to direct which mask generation function is used + switched on type input + */ +static int RsaMGF(int type, byte* seed, word32 seedSz, byte* out, + word32 outSz, void* heap) { - if (inputLen == 0) - return 0; + int ret; + + switch(type) { + #ifndef NO_SHA + case WC_MGF1SHA1: + ret = RsaMGF1(WC_HASH_TYPE_SHA, seed, seedSz, out, outSz, heap); + break; + #endif + #ifndef NO_SHA256 + #ifdef WOLFSSL_SHA224 + case WC_MGF1SHA224: + ret = RsaMGF1(WC_HASH_TYPE_SHA224, seed, seedSz, out, outSz, heap); + break; + #endif + case WC_MGF1SHA256: + ret = RsaMGF1(WC_HASH_TYPE_SHA256, seed, seedSz, out, outSz, heap); + break; + #endif + #ifdef WOLFSSL_SHA384 + case WC_MGF1SHA384: + ret = RsaMGF1(WC_HASH_TYPE_SHA384, seed, seedSz, out, outSz, heap); + break; + #endif + #ifdef WOLFSSL_SHA512 + case WC_MGF1SHA512: + ret = RsaMGF1(WC_HASH_TYPE_SHA512, seed, seedSz, out, outSz, heap); + break; + #endif + default: + WOLFSSL_MSG("Unknown MGF type: check build options"); + ret = BAD_FUNC_ARG; + } + + /* in case of default avoid unused warning */ + (void)seed; + (void)seedSz; + (void)out; + (void)outSz; + (void)heap; + + return ret; +} +#endif /* !WC_NO_RSA_OAEP || WC_RSA_PSS */ + + +/* Padding */ +#ifndef WOLFSSL_RSA_VERIFY_ONLY +#ifndef WC_NO_RNG +#ifndef WC_NO_RSA_OAEP +static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, byte padValue, WC_RNG* rng, + enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen, + void* heap) +{ + int ret; + int hLen; + int psLen; + int i; + word32 idx; + + byte* dbMask; + + #ifdef WOLFSSL_SMALL_STACK + byte* lHash = NULL; + byte* seed = NULL; + #else + /* must be large enough to contain largest hash */ + byte lHash[WC_MAX_DIGEST_SIZE]; + byte seed[ WC_MAX_DIGEST_SIZE]; + #endif + + /* no label is allowed, but catch if no label provided and length > 0 */ + if (optLabel == NULL && labelLen > 0) { + return BUFFER_E; + } + + /* limit of label is the same as limit of hash function which is massive */ + hLen = wc_HashGetDigestSize(hType); + if (hLen < 0) { + return hLen; + } + + #ifdef WOLFSSL_SMALL_STACK + lHash = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_RSA_BUFFER); + if (lHash == NULL) { + return MEMORY_E; + } + seed = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_RSA_BUFFER); + if (seed == NULL) { + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + return MEMORY_E; + } + #else + /* hLen should never be larger than lHash since size is max digest size, + but check before blindly calling wc_Hash */ + if ((word32)hLen > sizeof(lHash)) { + WOLFSSL_MSG("OAEP lHash to small for digest!!"); + return MEMORY_E; + } + #endif + + 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_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return ret; + } + + /* 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 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 + */ + 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_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return BAD_FUNC_ARG; + } + + if (inputLen > (pkcsBlockLen - 2 * hLen - 2)) { + WOLFSSL_MSG("OAEP pad error message too long"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return BAD_FUNC_ARG; + } + + /* concatenate lHash || PS || 0x01 || msg */ + idx = pkcsBlockLen - 1 - inputLen; + 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_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return BUFFER_E; + } + XMEMCPY(pkcsBlock + (pkcsBlockLen - inputLen), input, inputLen); + pkcsBlock[idx--] = 0x01; /* PS and M separator */ + while (psLen > 0 && idx > 0) { + pkcsBlock[idx--] = 0x00; + psLen--; + } + + idx = idx - hLen + 1; + XMEMCPY(pkcsBlock + idx, lHash, hLen); + + /* generate random seed */ + if ((ret = wc_RNG_GenerateBlock(rng, seed, hLen)) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return ret; + } + + /* create maskedDB from dbMask */ + dbMask = (byte*)XMALLOC(pkcsBlockLen - hLen - 1, heap, DYNAMIC_TYPE_RSA); + if (dbMask == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return MEMORY_E; + } + XMEMSET(dbMask, 0, pkcsBlockLen - hLen - 1); /* help static analyzer */ + + ret = RsaMGF(mgf, seed, hLen, dbMask, pkcsBlockLen - hLen - 1, heap); + if (ret != 0) { + XFREE(dbMask, heap, DYNAMIC_TYPE_RSA); + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return ret; + } + + i = 0; + idx = hLen + 1; + while (idx < pkcsBlockLen && (word32)i < (pkcsBlockLen - hLen -1)) { + pkcsBlock[idx] = dbMask[i++] ^ pkcsBlock[idx]; + idx++; + } + XFREE(dbMask, heap, DYNAMIC_TYPE_RSA); + + + /* create maskedSeed from seedMask */ + idx = 0; + pkcsBlock[idx++] = 0x00; + /* create seedMask inline */ + if ((ret = RsaMGF(mgf, pkcsBlock + hLen + 1, pkcsBlockLen - hLen - 1, + pkcsBlock + 1, hLen, heap)) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return ret; + } + + /* xor created seedMask with seed to make maskedSeed */ + i = 0; + while (idx < (word32)(hLen + 1) && i < hLen) { + pkcsBlock[idx] = pkcsBlock[idx] ^ seed[i++]; + idx++; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + (void)padValue; + + return 0; +} +#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) + * + * input Digest of the message. + * inputLen Length of digest. + * pkcsBlock Buffer to write to. + * pkcsBlockLen Length of buffer to write to. + * rng Random number generator (for salt). + * htype Hash function to use. + * mgf Mask generation function. + * saltLen Length of salt to put in padding. + * bits Length of key in bits. + * heap Used for dynamic memory allocation. + * returns 0 on success, PSS_SALTLEN_E when the salt length is invalid + * and other negative values on error. + */ +static int RsaPad_PSS(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, WC_RNG* rng, enum wc_HashType hType, int mgf, + int saltLen, int bits, void* heap) +{ + int ret = 0; + int hLen, i, o, maskLen, hiBits; + byte* m; + byte* s; +#if defined(WOLFSSL_PSS_LONG_SALT) || defined(WOLFSSL_PSS_SALT_LEN_DISCOVER) + #if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY) + byte salt[RSA_MAX_SIZE/8 + RSA_PSS_PAD_SZ]; + #else + byte* salt = NULL; + #endif +#else + byte salt[WC_MAX_DIGEST_SIZE]; +#endif + +#if defined(WOLFSSL_PSS_LONG_SALT) || defined(WOLFSSL_PSS_SALT_LEN_DISCOVER) + if (pkcsBlockLen > RSA_MAX_SIZE/8) { + return MEMORY_E; + } +#endif + + hLen = wc_HashGetDigestSize(hType); + if (hLen < 0) + return hLen; + + hiBits = (bits - 1) & 0x7; + if (hiBits == 0) { + *(pkcsBlock++) = 0; + pkcsBlockLen--; + } + + if (saltLen == RSA_PSS_SALT_LEN_DEFAULT) { + saltLen = hLen; + #ifdef WOLFSSL_SHA512 + /* See FIPS 186-4 section 5.5 item (e). */ + if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE) { + saltLen = RSA_PSS_SALT_MAX_SZ; + } + #endif + } +#ifndef WOLFSSL_PSS_LONG_SALT + else if (saltLen > hLen) { + return PSS_SALTLEN_E; + } +#endif +#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER + else if (saltLen < RSA_PSS_SALT_LEN_DEFAULT) { + return PSS_SALTLEN_E; + } +#else + else if (saltLen == RSA_PSS_SALT_LEN_DISCOVER) { + saltLen = (int)pkcsBlockLen - hLen - 2; + if (saltLen < 0) { + return PSS_SALTLEN_E; + } + } + else if (saltLen < RSA_PSS_SALT_LEN_DISCOVER) { + return PSS_SALTLEN_E; + } +#endif + if ((int)pkcsBlockLen - hLen < saltLen + 2) { + return PSS_SALTLEN_E; + } + + maskLen = pkcsBlockLen - 1 - hLen; + +#if defined(WOLFSSL_PSS_LONG_SALT) || defined(WOLFSSL_PSS_SALT_LEN_DISCOVER) + #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + salt = (byte*)XMALLOC(RSA_PSS_PAD_SZ + inputLen + saltLen, heap, + DYNAMIC_TYPE_RSA_BUFFER); + if (salt == NULL) { + return MEMORY_E; + } + #endif + s = m = salt; + XMEMSET(m, 0, RSA_PSS_PAD_SZ); + m += RSA_PSS_PAD_SZ; + XMEMCPY(m, input, inputLen); + m += inputLen; + o = (int)(m - s); + if (saltLen > 0) { + ret = wc_RNG_GenerateBlock(rng, m, saltLen); + if (ret == 0) { + m += saltLen; + } + } +#else + s = m = pkcsBlock; + XMEMSET(m, 0, RSA_PSS_PAD_SZ); + m += RSA_PSS_PAD_SZ; + XMEMCPY(m, input, inputLen); + m += inputLen; + o = 0; + if (saltLen > 0) { + ret = wc_RNG_GenerateBlock(rng, salt, saltLen); + if (ret == 0) { + XMEMCPY(m, salt, saltLen); + m += saltLen; + } + } +#endif + if (ret == 0) { + /* Put Hash at end of pkcsBlock - 1 */ + ret = wc_Hash(hType, s, (word32)(m - s), pkcsBlock + maskLen, hLen); + } + if (ret == 0) { + pkcsBlock[pkcsBlockLen - 1] = RSA_PSS_PAD_TERM; + + ret = RsaMGF(mgf, pkcsBlock + maskLen, hLen, pkcsBlock, maskLen, heap); + } + if (ret == 0) { + pkcsBlock[0] &= (1 << hiBits) - 1; + + m = pkcsBlock + maskLen - saltLen - 1; + *(m++) ^= 0x01; + for (i = 0; i < saltLen; i++) { + m[i] ^= salt[o + i]; + } + } + +#if defined(WOLFSSL_PSS_LONG_SALT) || defined(WOLFSSL_PSS_SALT_LEN_DISCOVER) + #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + if (salt != NULL) { + XFREE(salt, heap, DYNAMIC_TYPE_RSA_BUFFER); + } + #endif +#endif + return ret; +} +#endif /* WC_RSA_PSS */ +#endif /* !WC_NO_RNG */ + +static int RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, byte padValue, WC_RNG* rng) +{ + if (input == NULL || inputLen == 0 || pkcsBlock == NULL || + pkcsBlockLen == 0) { + return BAD_FUNC_ARG; + } pkcsBlock[0] = 0x0; /* set first byte to zero and advance */ pkcsBlock++; pkcsBlockLen--; pkcsBlock[0] = padValue; /* insert padValue */ - if (padValue == RSA_BLOCK_TYPE_1) + if (padValue == RSA_BLOCK_TYPE_1) { + if (pkcsBlockLen < inputLen + 2) { + WOLFSSL_MSG("RsaPad error, invalid length"); + return RSA_PAD_E; + } + /* pad with 0xff bytes */ XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2); + } else { +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WC_NO_RNG) /* pad with non-zero random bytes */ - word32 padLen = pkcsBlockLen - inputLen - 1, i; - int ret = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen); + word32 padLen, i; + int ret; - if (ret != 0) + if (pkcsBlockLen < inputLen + 1) { + WOLFSSL_MSG("RsaPad error, invalid length"); + return RSA_PAD_E; + } + + padLen = pkcsBlockLen - inputLen - 1; + ret = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen); + if (ret != 0) { return ret; + } /* remove zeros */ - for (i = 1; i < padLen; i++) + for (i = 1; i < padLen; i++) { if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01; + } +#else + (void)rng; + return RSA_WRONG_TYPE_E; +#endif } pkcsBlock[pkcsBlockLen-inputLen-1] = 0; /* separator */ @@ -258,348 +1283,2300 @@ static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, return 0; } +/* helper function to direct which padding is used */ +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, + int saltLen, int bits, void* heap) +{ + int ret; + + switch (padType) + { + case WC_RSA_PKCSV15_PAD: + /*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding");*/ + ret = RsaPad(input, inputLen, pkcsBlock, pkcsBlockLen, + padValue, rng); + break; + +#ifndef WC_NO_RNG + #ifndef WC_NO_RSA_OAEP + case WC_RSA_OAEP_PAD: + WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); + ret = RsaPad_OAEP(input, inputLen, pkcsBlock, pkcsBlockLen, + 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, saltLen, bits, heap); + break; + #endif +#endif /* !WC_NO_RNG */ + + #ifdef WC_RSA_NO_PADDING + case WC_RSA_NO_PAD: + WOLFSSL_MSG("wolfSSL Using NO padding"); + + /* In the case of no padding being used check that input is exactly + * the RSA key length */ + if (bits <= 0 || inputLen != ((word32)bits/WOLFSSL_BIT_SIZE)) { + WOLFSSL_MSG("Bad input size"); + ret = RSA_PAD_E; + } + else { + XMEMCPY(pkcsBlock, input, inputLen); + ret = 0; + } + break; + #endif + + default: + WOLFSSL_MSG("Unknown RSA Pad Type"); + ret = RSA_PAD_E; + } + + /* silence warning if not used with padding scheme */ + (void)input; + (void)inputLen; + (void)pkcsBlock; + (void)pkcsBlockLen; + (void)padValue; + (void)rng; + (void)padType; + (void)hType; + (void)mgf; + (void)optLabel; + (void)labelLen; + (void)saltLen; + (void)bits; + (void)heap; + + return ret; +} +#endif /* WOLFSSL_RSA_VERIFY_ONLY */ + + +/* UnPadding */ +#ifndef WC_NO_RSA_OAEP +/* UnPad plaintext, set start to *output, return length of plaintext, + * < 0 on error */ +static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, + byte **output, enum wc_HashType hType, int mgf, + byte* optLabel, word32 labelLen, void* heap) +{ + int hLen; + int ret; + byte h[WC_MAX_DIGEST_SIZE]; /* max digest size */ + byte* tmp; + word32 idx; + + /* no label is allowed, but catch if no label provided and length > 0 */ + if (optLabel == NULL && labelLen > 0) { + return BUFFER_E; + } + + hLen = wc_HashGetDigestSize(hType); + if ((hLen < 0) || (pkcsBlockLen < (2 * (word32)hLen + 2))) { + return BAD_FUNC_ARG; + } + + tmp = (byte*)XMALLOC(pkcsBlockLen, heap, DYNAMIC_TYPE_RSA_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + XMEMSET(tmp, 0, pkcsBlockLen); + + /* find seedMask value */ + if ((ret = RsaMGF(mgf, (byte*)(pkcsBlock + (hLen + 1)), + pkcsBlockLen - hLen - 1, tmp, hLen, heap)) != 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + return ret; + } + + /* xor seedMask value with maskedSeed to get seed value */ + for (idx = 0; idx < (word32)hLen; idx++) { + tmp[idx] = tmp[idx] ^ pkcsBlock[1 + idx]; + } + + /* get dbMask value */ + if ((ret = RsaMGF(mgf, tmp, hLen, tmp + hLen, + pkcsBlockLen - hLen - 1, heap)) != 0) { + XFREE(tmp, NULL, DYNAMIC_TYPE_RSA_BUFFER); + return ret; + } + + /* get DB value by doing maskedDB xor dbMask */ + for (idx = 0; idx < (pkcsBlockLen - hLen - 1); idx++) { + pkcsBlock[hLen + 1 + idx] = pkcsBlock[hLen + 1 + idx] ^ tmp[idx + hLen]; + } + + /* done with use of 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 comparison with hash sent */ + if ((ret = wc_Hash(hType, optLabel, labelLen, h, hLen)) != 0) { + return ret; + } + + /* say no to chosen ciphertext attack. + Comparison of lHash, Y, and separator value needs to all happen in + constant time. + Attackers should not be able to get error condition from the timing of + these checks. + */ + ret = 0; + ret |= ConstantCompare(pkcsBlock + hLen + 1, h, hLen); + ret += pkcsBlock[idx++] ^ 0x01; /* separator value is 0x01 */ + ret += pkcsBlock[0] ^ 0x00; /* Y, the first value, should be 0 */ + + /* Return 0 data length on error. */ + idx = ctMaskSelInt(ctMaskEq(ret, 0), idx, pkcsBlockLen); + + /* adjust pointer to correct location in array and return size of M */ + *output = (byte*)(pkcsBlock + idx); + return pkcsBlockLen - idx; +} +#endif /* WC_NO_RSA_OAEP */ + +#ifdef WC_RSA_PSS +/* 0x00 .. 0x00 0x01 | Salt | Gen Hash | 0xbc + * MGF over all bytes down to end of Salt + * + * pkcsBlock Buffer holding decrypted data. + * pkcsBlockLen Length of buffer. + * htype Hash function to use. + * mgf Mask generation function. + * saltLen Length of salt to put in padding. + * bits Length of key in bits. + * heap Used for dynamic memory allocation. + * returns 0 on success, PSS_SALTLEN_E when the salt length is invalid, + * BAD_PADDING_E when the padding is not valid, MEMORY_E when allocation fails + * and other negative values on error. + */ +static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen, + byte **output, enum wc_HashType hType, int mgf, + int saltLen, int bits, void* heap) +{ + int ret; + byte* tmp; + int hLen, i, maskLen; +#ifdef WOLFSSL_SHA512 + int orig_bits = bits; +#endif +#if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY) + byte tmp_buf[RSA_MAX_SIZE/8]; + tmp = tmp_buf; + + if (pkcsBlockLen > RSA_MAX_SIZE/8) { + return MEMORY_E; + } +#endif + + hLen = wc_HashGetDigestSize(hType); + if (hLen < 0) + return hLen; + bits = (bits - 1) & 0x7; + if ((pkcsBlock[0] & (0xff << bits)) != 0) { + return BAD_PADDING_E; + } + if (bits == 0) { + pkcsBlock++; + pkcsBlockLen--; + } + maskLen = (int)pkcsBlockLen - 1 - hLen; + if (maskLen < 0) { + WOLFSSL_MSG("RsaUnPad_PSS: Hash too large"); + return WC_KEY_SIZE_E; + } + + if (saltLen == RSA_PSS_SALT_LEN_DEFAULT) { + saltLen = hLen; + #ifdef WOLFSSL_SHA512 + /* See FIPS 186-4 section 5.5 item (e). */ + if (orig_bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE) + saltLen = RSA_PSS_SALT_MAX_SZ; + #endif + } +#ifndef WOLFSSL_PSS_LONG_SALT + else if (saltLen > hLen) + return PSS_SALTLEN_E; +#endif +#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER + else if (saltLen < RSA_PSS_SALT_LEN_DEFAULT) + return PSS_SALTLEN_E; + if (maskLen < saltLen + 1) { + return PSS_SALTLEN_E; + } +#else + else if (saltLen < RSA_PSS_SALT_LEN_DISCOVER) + return PSS_SALTLEN_E; + if (saltLen != RSA_PSS_SALT_LEN_DISCOVER && maskLen < saltLen + 1) { + return WC_KEY_SIZE_E; + } +#endif + + if (pkcsBlock[pkcsBlockLen - 1] != RSA_PSS_PAD_TERM) { + WOLFSSL_MSG("RsaUnPad_PSS: Padding Term Error"); + return BAD_PADDING_E; + } + +#if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + tmp = (byte*)XMALLOC(maskLen, heap, DYNAMIC_TYPE_RSA_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } +#endif + + if ((ret = RsaMGF(mgf, pkcsBlock + maskLen, hLen, tmp, maskLen, + heap)) != 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + return ret; + } + + tmp[0] &= (1 << bits) - 1; + pkcsBlock[0] &= (1 << bits) - 1; +#ifdef WOLFSSL_PSS_SALT_LEN_DISCOVER + if (saltLen == RSA_PSS_SALT_LEN_DISCOVER) { + for (i = 0; i < maskLen - 1; i++) { + if (tmp[i] != pkcsBlock[i]) { + break; + } + } + if (tmp[i] != (pkcsBlock[i] ^ 0x01)) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + WOLFSSL_MSG("RsaUnPad_PSS: Padding Error Match"); + return PSS_SALTLEN_RECOVER_E; + } + saltLen = maskLen - (i + 1); + } + else +#endif + { + for (i = 0; i < maskLen - 1 - saltLen; i++) { + if (tmp[i] != pkcsBlock[i]) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + WOLFSSL_MSG("RsaUnPad_PSS: Padding Error Match"); + return PSS_SALTLEN_E; + } + } + if (tmp[i] != (pkcsBlock[i] ^ 0x01)) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + WOLFSSL_MSG("RsaUnPad_PSS: Padding Error End"); + return PSS_SALTLEN_E; + } + } + for (i++; i < maskLen; i++) + pkcsBlock[i] ^= tmp[i]; + +#if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); +#endif + + *output = pkcsBlock + maskLen - saltLen; + return saltLen + hLen; +} +#endif /* UnPad plaintext, set start to *output, return length of plaintext, * < 0 on error */ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, - byte **output, byte padValue) + byte **output, byte padValue) { - word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0, - invalid = 0, - i = 1, - outputLen; + int ret = BAD_FUNC_ARG; + word16 i; +#ifndef WOLFSSL_RSA_VERIFY_ONLY + byte invalid = 0; +#endif - if (pkcsBlock[0] != 0x0) /* skip past zero */ - invalid = 1; - pkcsBlock++; pkcsBlockLen--; + if (output == NULL || pkcsBlockLen == 0 || pkcsBlockLen > 0xFFFF) { + return BAD_FUNC_ARG; + } - /* Require block type padValue */ - invalid = (pkcsBlock[0] != padValue) || invalid; - - /* verify the padding until we find the separator */ if (padValue == RSA_BLOCK_TYPE_1) { - while (i maxOutputLen) || invalid; - - if (invalid) { - WOLFSSL_MSG("RsaUnPad error, bad formatting"); - return RSA_PAD_E; - } - - *output = (byte *)(pkcsBlock + i); - return outputLen; + return ret; } - -static int wc_RsaFunction(const byte* in, word32 inLen, byte* out, - word32* outLen, int type, RsaKey* key) +/* helper function to direct unpadding + * + * bits is the key modulus size in bits + */ +int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, + byte padValue, int padType, enum wc_HashType hType, + int mgf, byte* optLabel, word32 labelLen, int saltLen, + int bits, void* heap) { - #define ERROR_OUT(x) { ret = (x); goto done;} + int ret; - mp_int tmp; - int ret = 0; - word32 keyLen, len; + switch (padType) { + case WC_RSA_PKCSV15_PAD: + /*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 un-padding");*/ + ret = RsaUnPad(pkcsBlock, pkcsBlockLen, out, padValue); + break; - if (mp_init(&tmp) != MP_OKAY) - return MP_INIT_E; + #ifndef WC_NO_RSA_OAEP + case WC_RSA_OAEP_PAD: + WOLFSSL_MSG("wolfSSL Using RSA OAEP un-padding"); + ret = RsaUnPad_OAEP((byte*)pkcsBlock, pkcsBlockLen, out, + hType, mgf, optLabel, labelLen, heap); + break; + #endif - if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY) - ERROR_OUT(MP_READ_E); + #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, + saltLen, bits, heap); + break; + #endif - if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { - #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */ - if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY) - ERROR_OUT(MP_EXPTMOD_E); - #else - #define INNER_ERROR_OUT(x) { ret = (x); goto inner_done; } + #ifdef WC_RSA_NO_PADDING + case WC_RSA_NO_PAD: + WOLFSSL_MSG("wolfSSL Using NO un-padding"); - mp_int tmpa, tmpb; - - if (mp_init(&tmpa) != MP_OKAY) - ERROR_OUT(MP_INIT_E); - - if (mp_init(&tmpb) != MP_OKAY) { - mp_clear(&tmpa); - ERROR_OUT(MP_INIT_E); + /* In the case of no padding being used check that input is exactly + * the RSA key length */ + if (bits <= 0 || pkcsBlockLen != + ((word32)(bits+WOLFSSL_BIT_SIZE-1)/WOLFSSL_BIT_SIZE)) { + WOLFSSL_MSG("Bad input size"); + ret = RSA_PAD_E; } + else { + if (out != NULL) { + *out = pkcsBlock; + } + ret = pkcsBlockLen; + } + break; + #endif /* WC_RSA_NO_PADDING */ - /* tmpa = tmp^dP mod p */ - if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY) - INNER_ERROR_OUT(MP_EXPTMOD_E); - - /* tmpb = tmp^dQ mod q */ - if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY) - INNER_ERROR_OUT(MP_EXPTMOD_E); - - /* tmp = (tmpa - tmpb) * qInv (mod p) */ - if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY) - INNER_ERROR_OUT(MP_SUB_E); - - if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY) - INNER_ERROR_OUT(MP_MULMOD_E); - - /* tmp = tmpb + q * tmp */ - if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY) - INNER_ERROR_OUT(MP_MUL_E); - - if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY) - INNER_ERROR_OUT(MP_ADD_E); - - inner_done: - mp_clear(&tmpa); - mp_clear(&tmpb); - - if (ret != 0) return ret; - - #endif /* RSA_LOW_MEM */ + default: + WOLFSSL_MSG("Unknown RSA UnPad Type"); + ret = RSA_PAD_E; } - else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) { - if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY) - ERROR_OUT(MP_EXPTMOD_E); + + /* silence warning if not used with padding scheme */ + (void)hType; + (void)mgf; + (void)optLabel; + (void)labelLen; + (void)saltLen; + (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; + (void)rng; + + keyLen = wc_RsaEncryptSize(key); + if (keyLen > *outLen) { + WOLFSSL_MSG("Output buffer is not big enough"); + return BAD_FUNC_ARG; } - else - ERROR_OUT(RSA_WRONG_TYPE_E); - keyLen = mp_unsigned_bin_size(&key->n); - if (keyLen > *outLen) - ERROR_OUT(RSA_BUFFER_E); + if (inLen != keyLen) { + WOLFSSL_MSG("Expected that inLen equals RSA key length"); + return BAD_FUNC_ARG; + } - len = mp_unsigned_bin_size(&tmp); - - /* pad front w/ zeros to match key length */ - while (len < keyLen) { - *out++ = 0x00; - len++; + 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; - /* convert */ - if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY) + return ret; +} +#endif /* WOLFSSL_XILINX_CRYPT */ + +#ifdef WC_RSA_NONBLOCK +static int wc_RsaFunctionNonBlock(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key) +{ + int ret = 0; + word32 keyLen, len; + + if (key == NULL || key->nb == NULL) { + return BAD_FUNC_ARG; + } + + if (key->nb->exptmod.state == TFM_EXPTMOD_NB_INIT) { + if (mp_init(&key->nb->tmp) != MP_OKAY) { + ret = MP_INIT_E; + } + + if (ret == 0) { + if (mp_read_unsigned_bin(&key->nb->tmp, (byte*)in, inLen) != MP_OKAY) { + ret = MP_READ_E; + } + } + } + + if (ret == 0) { + switch(type) { + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + ret = fp_exptmod_nb(&key->nb->exptmod, &key->nb->tmp, &key->d, + &key->n, &key->nb->tmp); + if (ret == FP_WOULDBLOCK) + return ret; + if (ret != MP_OKAY) + ret = MP_EXPTMOD_E; + break; + + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + ret = fp_exptmod_nb(&key->nb->exptmod, &key->nb->tmp, &key->e, + &key->n, &key->nb->tmp); + if (ret == FP_WOULDBLOCK) + return ret; + if (ret != MP_OKAY) + ret = MP_EXPTMOD_E; + break; + default: + ret = RSA_WRONG_TYPE_E; + break; + } + } + + if (ret == 0) { + keyLen = wc_RsaEncryptSize(key); + if (keyLen > *outLen) + ret = RSA_BUFFER_E; + } + if (ret == 0) { + len = mp_unsigned_bin_size(&key->nb->tmp); + + /* pad front w/ zeros to match key length */ + while (len < keyLen) { + *out++ = 0x00; + len++; + } + + *outLen = keyLen; + + /* convert */ + if (mp_to_unsigned_bin(&key->nb->tmp, out) != MP_OKAY) { + ret = MP_TO_E; + } + } + + mp_clear(&key->nb->tmp); + + return ret; +} +#endif /* WC_RSA_NONBLOCK */ + +#ifdef WOLFSSL_AFALG_XILINX_RSA +#ifndef ERROR_OUT +#define ERROR_OUT(x) ret = (x); goto done +#endif + +static const char WC_TYPE_ASYMKEY[] = "skcipher"; +static const char WC_NAME_RSA[] = "xilinx-zynqmp-rsa"; +#ifndef MAX_XILINX_RSA_KEY + /* max key size of 4096 bits / 512 bytes */ + #define MAX_XILINX_RSA_KEY 512 +#endif +static const byte XILINX_RSA_FLAG[] = {0x1}; + + +/* AF_ALG implementation of RSA */ +static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + struct msghdr msg; + struct cmsghdr* cmsg; + struct iovec iov; + byte* keyBuf = NULL; + word32 keyBufSz = 0; + char cbuf[CMSG_SPACE(4) + CMSG_SPACE(sizeof(struct af_alg_iv) + 1)] = {0}; + int ret = 0; + int op = 0; /* decryption vs encryption flag */ + word32 keyLen; + + /* input and output buffer need to be aligned */ + ALIGN64 byte outBuf[MAX_XILINX_RSA_KEY]; + ALIGN64 byte inBuf[MAX_XILINX_RSA_KEY]; + + XMEMSET(&msg, 0, sizeof(struct msghdr)); + (void)rng; + + keyLen = wc_RsaEncryptSize(key); + if (keyLen > *outLen) { + ERROR_OUT(RSA_BUFFER_E); + } + + if (keyLen > MAX_XILINX_RSA_KEY) { + WOLFSSL_MSG("RSA key size larger than supported"); + ERROR_OUT(BAD_FUNC_ARG); + } + + if ((keyBuf = (byte*)XMALLOC(keyLen * 2, key->heap, DYNAMIC_TYPE_KEY)) + == NULL) { + ERROR_OUT(MEMORY_E); + } + + if ((ret = mp_to_unsigned_bin(&(key->n), keyBuf)) != MP_OKAY) { ERROR_OUT(MP_TO_E); + } + + switch(type) { + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + op = 1; /* set as decrypt */ + { + keyBufSz = mp_unsigned_bin_size(&(key->d)); + if ((mp_to_unsigned_bin(&(key->d), keyBuf + keyLen)) + != MP_OKAY) { + ERROR_OUT(MP_TO_E); + } + } + break; + + case RSA_PUBLIC_DECRYPT: + case RSA_PUBLIC_ENCRYPT: { + word32 exp = 0; + word32 eSz = mp_unsigned_bin_size(&(key->e)); + if ((mp_to_unsigned_bin(&(key->e), (byte*)&exp + + (sizeof(word32) - eSz))) != MP_OKAY) { + ERROR_OUT(MP_TO_E); + } + keyBufSz = sizeof(word32); + XMEMCPY(keyBuf + keyLen, (byte*)&exp, keyBufSz); + break; + } + + default: + ERROR_OUT(RSA_WRONG_TYPE_E); + } + keyBufSz += keyLen; /* add size of modulus */ + + /* check for existing sockets before creating new ones */ + if (key->alFd > 0) { + close(key->alFd); + key->alFd = WC_SOCK_NOTSET; + } + if (key->rdFd > 0) { + close(key->rdFd); + key->rdFd = WC_SOCK_NOTSET; + } + + /* create new sockets and set the key to use */ + if ((key->alFd = wc_Afalg_Socket()) < 0) { + WOLFSSL_MSG("Unable to create socket"); + ERROR_OUT(key->alFd); + } + if ((key->rdFd = wc_Afalg_CreateRead(key->alFd, WC_TYPE_ASYMKEY, + WC_NAME_RSA)) < 0) { + WOLFSSL_MSG("Unable to bind and create read/send socket"); + ERROR_OUT(key->rdFd); + } + if ((ret = setsockopt(key->alFd, SOL_ALG, ALG_SET_KEY, keyBuf, + keyBufSz)) < 0) { + WOLFSSL_MSG("Error setting RSA key"); + ERROR_OUT(ret); + } + + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); + cmsg = CMSG_FIRSTHDR(&msg); + if ((ret = wc_Afalg_SetOp(cmsg, op)) < 0) { + ERROR_OUT(ret); + } + + /* set flag in IV spot, needed for Xilinx hardware acceleration use */ + cmsg = CMSG_NXTHDR(&msg, cmsg); + if ((ret = wc_Afalg_SetIv(cmsg, (byte*)XILINX_RSA_FLAG, + sizeof(XILINX_RSA_FLAG))) != 0) { + ERROR_OUT(ret); + } + + /* compose and send msg */ + XMEMCPY(inBuf, (byte*)in, inLen); /* for alignment */ + iov.iov_base = inBuf; + iov.iov_len = inLen; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + if ((ret = sendmsg(key->rdFd, &msg, 0)) <= 0) { + ERROR_OUT(WC_AFALG_SOCK_E); + } + + if ((ret = read(key->rdFd, outBuf, inLen)) <= 0) { + ERROR_OUT(WC_AFALG_SOCK_E); + } + XMEMCPY(out, outBuf, ret); + *outLen = keyLen; done: - mp_clear(&tmp); - if (ret == MP_EXPTMOD_E) { - WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem"); + /* clear key data and free buffer */ + if (keyBuf != NULL) { + ForceZero(keyBuf, keyBufSz); } + XFREE(keyBuf, key->heap, DYNAMIC_TYPE_KEY); + + if (key->alFd > 0) { + close(key->alFd); + key->alFd = WC_SOCK_NOTSET; + } + if (key->rdFd > 0) { + close(key->rdFd); + key->rdFd = WC_SOCK_NOTSET; + } + + return ret; +} + +#else +static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ +#ifndef WOLFSSL_SP_MATH +#ifdef WOLFSSL_SMALL_STACK + mp_int* tmp; +#ifdef WC_RSA_BLINDING + mp_int* rnd; + mp_int* rndi; +#endif +#else + mp_int tmp[1]; +#ifdef WC_RSA_BLINDING + mp_int rnd[1], rndi[1]; +#endif +#endif + int ret = 0; + word32 keyLen = 0; +#endif + +#ifdef WOLFSSL_HAVE_SP_RSA +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->n) == 2048) { + switch(type) { +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + #ifdef WC_RSA_BLINDING + if (rng == NULL) + return MISSING_RNG_E; + #endif + #ifndef RSA_LOW_MEM + return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q, + &key->dP, &key->dQ, &key->u, &key->n, + out, outLen); + #else + return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q, + NULL, NULL, NULL, &key->n, out, outLen); + #endif +#endif + 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) { +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + #ifdef WC_RSA_BLINDING + if (rng == NULL) + return MISSING_RNG_E; + #endif + #ifndef RSA_LOW_MEM + return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q, + &key->dP, &key->dQ, &key->u, &key->n, + out, outLen); + #else + return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q, + NULL, NULL, NULL, &key->n, out, outLen); + #endif +#endif + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + return sp_RsaPublic_3072(in, inLen, &key->e, &key->n, out, outLen); + } + } +#endif +#ifdef WOLFSSL_SP_4096 + if (mp_count_bits(&key->n) == 4096) { + switch(type) { +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + #ifdef WC_RSA_BLINDING + if (rng == NULL) + return MISSING_RNG_E; + #endif + #ifndef RSA_LOW_MEM + return sp_RsaPrivate_4096(in, inLen, &key->d, &key->p, &key->q, + &key->dP, &key->dQ, &key->u, &key->n, + out, outLen); + #else + return sp_RsaPrivate_4096(in, inLen, &key->d, &key->p, &key->q, + NULL, NULL, NULL, &key->n, out, outLen); + #endif +#endif + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + return sp_RsaPublic_4096(in, inLen, &key->e, &key->n, out, outLen); + } + } +#endif +#endif /* WOLFSSL_HAVE_SP_RSA */ + +#ifdef WOLFSSL_SP_MATH + (void)rng; + WOLFSSL_MSG("SP Key Size Error"); + return WC_KEY_SIZE_E; +#else + (void)rng; + +#ifdef WOLFSSL_SMALL_STACK + tmp = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA); + if (tmp == NULL) + return MEMORY_E; +#ifdef WC_RSA_BLINDING + rnd = (mp_int*)XMALLOC(sizeof(mp_int) * 2, key->heap, DYNAMIC_TYPE_RSA); + if (rnd == NULL) { + XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); + return MEMORY_E; + } + rndi = rnd + 1; +#endif /* WC_RSA_BLINDING */ +#endif /* WOLFSSL_SMALL_STACK */ + + if (mp_init(tmp) != MP_OKAY) + ret = MP_INIT_E; + +#ifdef WC_RSA_BLINDING + if (ret == 0) { + if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { + if (mp_init_multi(rnd, rndi, NULL, NULL, NULL, NULL) != MP_OKAY) { + mp_clear(tmp); + ret = MP_INIT_E; + } + } + } +#endif + +#ifndef TEST_UNPAD_CONSTANT_TIME + if (ret == 0 && mp_read_unsigned_bin(tmp, (byte*)in, inLen) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0) { + switch(type) { + #ifndef WOLFSSL_RSA_PUBLIC_ONLY + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + { + #if defined(WC_RSA_BLINDING) && !defined(WC_NO_RNG) + /* blind */ + ret = mp_rand(rnd, get_digit_count(&key->n), rng); + + /* rndi = 1/rnd mod n */ + if (ret == 0 && mp_invmod(rnd, &key->n, rndi) != MP_OKAY) + ret = MP_INVMOD_E; + + /* rnd = rnd^e */ + if (ret == 0 && mp_exptmod(rnd, &key->e, &key->n, rnd) != MP_OKAY) + ret = MP_EXPTMOD_E; + + /* tmp = tmp*rnd mod n */ + if (ret == 0 && mp_mulmod(tmp, rnd, &key->n, tmp) != MP_OKAY) + ret = MP_MULMOD_E; + #endif /* WC_RSA_BLINDING && !WC_NO_RNG */ + + #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */ + if (ret == 0 && mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + #else + if (ret == 0) { + #ifdef WOLFSSL_SMALL_STACK + mp_int* tmpa; + mp_int* tmpb = NULL; + #else + mp_int tmpa[1], tmpb[1]; + #endif + int cleara = 0, clearb = 0; + + #ifdef WOLFSSL_SMALL_STACK + tmpa = (mp_int*)XMALLOC(sizeof(mp_int) * 2, + key->heap, DYNAMIC_TYPE_RSA); + if (tmpa != NULL) + tmpb = tmpa + 1; + else + ret = MEMORY_E; + #endif + + if (ret == 0) { + if (mp_init(tmpa) != MP_OKAY) + ret = MP_INIT_E; + else + cleara = 1; + } + + if (ret == 0) { + if (mp_init(tmpb) != MP_OKAY) + ret = MP_INIT_E; + else + clearb = 1; + } + + /* tmpa = tmp^dP mod p */ + if (ret == 0 && mp_exptmod(tmp, &key->dP, &key->p, + tmpa) != MP_OKAY) + ret = MP_EXPTMOD_E; + + /* tmpb = tmp^dQ mod q */ + if (ret == 0 && mp_exptmod(tmp, &key->dQ, &key->q, + tmpb) != MP_OKAY) + ret = MP_EXPTMOD_E; + + /* tmp = (tmpa - tmpb) * qInv (mod p) */ + if (ret == 0 && mp_sub(tmpa, tmpb, tmp) != MP_OKAY) + ret = MP_SUB_E; + + if (ret == 0 && mp_mulmod(tmp, &key->u, &key->p, + tmp) != MP_OKAY) + ret = MP_MULMOD_E; + + /* tmp = tmpb + q * tmp */ + if (ret == 0 && mp_mul(tmp, &key->q, tmp) != MP_OKAY) + ret = MP_MUL_E; + + if (ret == 0 && mp_add(tmp, tmpb, tmp) != MP_OKAY) + ret = MP_ADD_E; + + #ifdef WOLFSSL_SMALL_STACK + if (tmpa != NULL) + #endif + { + if (cleara) + mp_clear(tmpa); + if (clearb) + mp_clear(tmpb); + #ifdef WOLFSSL_SMALL_STACK + XFREE(tmpa, key->heap, DYNAMIC_TYPE_RSA); + #endif + } + } /* tmpa/b scope */ + #endif /* RSA_LOW_MEM */ + + #ifdef WC_RSA_BLINDING + /* unblind */ + if (ret == 0 && mp_mulmod(tmp, rndi, &key->n, tmp) != MP_OKAY) + ret = MP_MULMOD_E; + #endif /* WC_RSA_BLINDING */ + + break; + } + #endif + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + #ifdef WOLFSSL_XILINX_CRYPT + ret = wc_RsaFunctionXil(in, inLen, out, outLen, type, key, rng); + #else + if (mp_exptmod_nct(tmp, &key->e, &key->n, tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + #endif + break; + default: + ret = RSA_WRONG_TYPE_E; + break; + } + } + + if (ret == 0) { + keyLen = wc_RsaEncryptSize(key); + if (keyLen > *outLen) + ret = RSA_BUFFER_E; + } + if (ret == 0) { + *outLen = keyLen; + if (mp_to_unsigned_bin_len(tmp, out, keyLen) != MP_OKAY) + ret = MP_TO_E; + } +#else + (void)type; + (void)key; + (void)keyLen; + XMEMCPY(out, in, inLen); + *outLen = inLen; +#endif + + mp_clear(tmp); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); +#endif +#ifdef WC_RSA_BLINDING + if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { + mp_clear(rndi); + mp_clear(rnd); + } +#ifdef WOLFSSL_SMALL_STACK + XFREE(rnd, key->heap, DYNAMIC_TYPE_RSA); +#endif +#endif /* WC_RSA_BLINDING */ + return ret; +#endif /* WOLFSSL_SP_MATH */ +} +#endif + +#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 + 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; + testDev->rsaFunc.outSz = outLen; + testDev->rsaFunc.type = type; + testDev->rsaFunc.key = key; + testDev->rsaFunc.rng = rng; + return WC_PENDING_E; + } +#endif /* WOLFSSL_ASYNC_CRYPT_TEST */ + + switch(type) { +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + #ifdef HAVE_CAVIUM + key->dataLen = key->n.raw.len; + 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) + #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 + break; +#endif + + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + #ifdef HAVE_CAVIUM + key->dataLen = key->n.raw.len; + 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) + 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 + break; + + default: + ret = RSA_WRONG_TYPE_E; + } + + return ret; +} +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_RSA */ + +#if defined(WC_RSA_DIRECT) || defined(WC_RSA_NO_PADDING) +/* Function that does the RSA operation directly with no padding. + * + * in buffer to do operation on + * inLen length of input buffer + * out buffer to hold results + * outSz gets set to size of result buffer. Should be passed in as length + * of out buffer. If the pointer "out" is null then outSz gets set to + * the expected buffer size needed and LENGTH_ONLY_E gets returned. + * key RSA key to use for encrypt/decrypt + * type if using private or public key {RSA_PUBLIC_ENCRYPT, + * RSA_PUBLIC_DECRYPT, RSA_PRIVATE_ENCRYPT, RSA_PRIVATE_DECRYPT} + * rng wolfSSL RNG to use if needed + * + * returns size of result on success + */ +int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz, + RsaKey* key, int type, WC_RNG* rng) +{ + int ret; + + if (in == NULL || outSz == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + /* sanity check on type of RSA operation */ + switch (type) { + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + case RSA_PRIVATE_DECRYPT: + break; + default: + WOLFSSL_MSG("Bad RSA type"); + return BAD_FUNC_ARG; + } + + if ((ret = wc_RsaEncryptSize(key)) < 0) { + return BAD_FUNC_ARG; + } + + if (inLen != (word32)ret) { + WOLFSSL_MSG("Bad input length. Should be RSA key size"); + return BAD_FUNC_ARG; + } + + if (out == NULL) { + *outSz = inLen; + return LENGTH_ONLY_E; + } + + switch (key->state) { + case RSA_STATE_NONE: + case RSA_STATE_ENCRYPT_PAD: + case RSA_STATE_ENCRYPT_EXPTMOD: + case RSA_STATE_DECRYPT_EXPTMOD: + case RSA_STATE_DECRYPT_UNPAD: + key->state = (type == RSA_PRIVATE_ENCRYPT || + type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_EXPTMOD: + RSA_STATE_DECRYPT_EXPTMOD; + + key->dataLen = *outSz; + + ret = wc_RsaFunction(in, inLen, out, &key->dataLen, type, key, rng); + if (ret >= 0 || ret == WC_PENDING_E) { + key->state = (type == RSA_PRIVATE_ENCRYPT || + type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_RES: + RSA_STATE_DECRYPT_RES; + } + if (ret < 0) { + break; + } + + FALL_THROUGH; + + case RSA_STATE_ENCRYPT_RES: + case RSA_STATE_DECRYPT_RES: + ret = key->dataLen; + break; + + default: + ret = BAD_STATE_E; + } + + /* if async pending then skip cleanup*/ + if (ret == WC_PENDING_E + #ifdef WC_RSA_NONBLOCK + || ret == FP_WOULDBLOCK + #endif + ) { + return ret; + } + + key->state = RSA_STATE_NONE; + wc_RsaCleanup(key); + + return ret; +} +#endif /* WC_RSA_DIRECT || WC_RSA_NO_PADDING */ + +#if defined(WOLFSSL_CRYPTOCELL) +static int cc310_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + CRYSError_t ret = 0; + CRYS_RSAPrimeData_t primeData; + int modulusSize = wc_RsaEncryptSize(key); + + /* The out buffer must be at least modulus size bytes long. */ + if (outLen < modulusSize) + return BAD_FUNC_ARG; + + ret = CRYS_RSA_PKCS1v15_Encrypt(&wc_rndState, + wc_rndGenVectFunc, + &key->ctx.pubKey, + &primeData, + (byte*)in, + inLen, + out); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_PKCS1v15_Encrypt failed"); + return -1; + } + + return modulusSize; +} +static int cc310_RsaPublicDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + CRYSError_t ret = 0; + CRYS_RSAPrimeData_t primeData; + uint16_t actualOutLen = outLen; + + ret = CRYS_RSA_PKCS1v15_Decrypt(&key->ctx.privKey, + &primeData, + (byte*)in, + inLen, + out, + &actualOutLen); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_PKCS1v15_Decrypt failed"); + return -1; + } + return actualOutLen; +} + +int cc310_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, CRYS_RSA_HASH_OpMode_t mode) +{ + CRYSError_t ret = 0; + uint16_t actualOutLen = outLen*sizeof(byte); + CRYS_RSAPrivUserContext_t contextPrivate; + + ret = CRYS_RSA_PKCS1v15_Sign(&wc_rndState, + wc_rndGenVectFunc, + &contextPrivate, + &key->ctx.privKey, + mode, + (byte*)in, + inLen, + out, + &actualOutLen); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_PKCS1v15_Sign failed"); + return -1; + } + return actualOutLen; +} + +int cc310_RsaSSL_Verify(const byte* in, word32 inLen, byte* sig, + RsaKey* key, CRYS_RSA_HASH_OpMode_t mode) +{ + CRYSError_t ret = 0; + CRYS_RSAPubUserContext_t contextPub; + + /* verify the signature in the sig pointer */ + ret = CRYS_RSA_PKCS1v15_Verify(&contextPub, + &key->ctx.pubKey, + mode, + (byte*)in, + inLen, + sig); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_PKCS1v15_Verify failed"); + return -1; + } + + return ret; +} +#endif /* WOLFSSL_CRYPTOCELL */ + +int wc_RsaFunction(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + int ret = 0; + + if (key == NULL || in == NULL || inLen == 0 || out == NULL || + outLen == NULL || *outLen == 0 || type == RSA_TYPE_UNKNOWN) { + return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + ret = wc_CryptoCb_Rsa(in, inLen, out, outLen, type, key, rng); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; /* reset error code and try using software */ + } +#endif + +#ifndef TEST_UNPAD_CONSTANT_TIME +#ifndef NO_RSA_BOUNDS_CHECK + if (type == RSA_PRIVATE_DECRYPT && + key->state == RSA_STATE_DECRYPT_EXPTMOD) { + + /* Check that 1 < in < n-1. (Requirement of 800-56B.) */ +#ifdef WOLFSSL_SMALL_STACK + mp_int* c; +#else + mp_int c[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + c = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA); + if (c == NULL) + ret = MEMORY_E; +#endif + + if (mp_init(c) != MP_OKAY) + ret = MEMORY_E; + if (ret == 0) { + if (mp_read_unsigned_bin(c, in, inLen) != 0) + ret = MP_READ_E; + } + if (ret == 0) { + /* check c > 1 */ + if (mp_cmp_d(c, 1) != MP_GT) + ret = RSA_OUT_OF_RANGE_E; + } + if (ret == 0) { + /* add c+1 */ + if (mp_add_d(c, 1, c) != MP_OKAY) + ret = MP_ADD_E; + } + if (ret == 0) { + /* check c+1 < n */ + if (mp_cmp(c, &key->n) != MP_LT) + ret = RSA_OUT_OF_RANGE_E; + } + mp_clear(c); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(c, key->heap, DYNAMIC_TYPE_RSA); +#endif + + if (ret != 0) + return ret; + } +#endif /* NO_RSA_BOUNDS_CHECK */ +#endif + +#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 +#endif +#ifdef WC_RSA_NONBLOCK + if (key->nb) { + ret = wc_RsaFunctionNonBlock(in, inLen, out, outLen, type, key); + } + else +#endif + { + ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); + } + + /* handle error */ + if (ret < 0 && ret != WC_PENDING_E + #ifdef WC_RSA_NONBLOCK + && ret != FP_WOULDBLOCK + #endif + ) { + 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; } -int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, - RsaKey* key, RNG* rng) +#ifndef WOLFSSL_RSA_VERIFY_ONLY +/* Internal Wrappers */ +/* Gives the option of choosing padding type + in : input to be encrypted + inLen: length of input buffer + out: encrypted output + outLen: length of encrypted output buffer + key : wolfSSL initialized RSA key struct + rng : wolfSSL initialized random number struct + 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, WC_RSA_OAEP_PAD, + WC_RSA_NO_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 + labelSz : size of optional label buffer + saltLen : Length of salt used in PSS + rng : random number generator */ +static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, int rsa_type, + byte pad_value, int pad_type, + enum wc_HashType hash, int mgf, + byte* label, word32 labelSz, int saltLen, + WC_RNG* rng) { - int sz, ret; + int ret, sz; + + if (in == NULL || inLen == 0 || out == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + sz = wc_RsaEncryptSize(key); + if (sz > (int)outLen) { + return RSA_BUFFER_E; + } + + if (sz < RSA_MIN_PAD_SZ) { + return WC_KEY_SIZE_E; + } + + if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) { +#ifdef WC_RSA_NO_PADDING + /* In the case that no padding is used the input length can and should + * be the same size as the RSA key. */ + if (pad_type != WC_RSA_NO_PAD) +#endif + return RSA_BUFFER_E; + } + + switch (key->state) { + case RSA_STATE_NONE: + case RSA_STATE_ENCRYPT_PAD: + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(HAVE_CAVIUM) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA && + pad_type != WC_RSA_PSS_PAD && 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->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) { + key->state = RSA_STATE_ENCRYPT_RES; + key->dataLen = key->n.raw.len; + return NitroxRsaSSL_Sign(in, inLen, out, outLen, key); + } + } + #elif defined(WOLFSSL_CRYPTOCELL) + if (rsa_type == RSA_PUBLIC_ENCRYPT && + pad_value == RSA_BLOCK_TYPE_2) { + + return cc310_RsaPublicEncrypt(in, inLen, out, outLen, key); + } + else if (rsa_type == RSA_PRIVATE_ENCRYPT && + pad_value == RSA_BLOCK_TYPE_1) { + return cc310_RsaSSL_Sign(in, inLen, out, outLen, key, + cc310_hashModeRSA(hash, 0)); + } + #endif /* WOLFSSL_CRYPTOCELL */ + + key->state = RSA_STATE_ENCRYPT_PAD; + ret = wc_RsaPad_ex(in, inLen, out, sz, pad_value, rng, pad_type, hash, + mgf, label, labelSz, saltLen, mp_count_bits(&key->n), + key->heap); + if (ret < 0) { + break; + } + + key->state = RSA_STATE_ENCRYPT_EXPTMOD; + FALL_THROUGH; + + 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; + + case RSA_STATE_ENCRYPT_RES: + ret = key->dataLen; + break; + + default: + ret = BAD_STATE_E; + break; + } + + /* if async pending then return and skip done cleanup below */ + if (ret == WC_PENDING_E + #ifdef WC_RSA_NONBLOCK + || ret == FP_WOULDBLOCK + #endif + ) { + return ret; + } + + key->state = RSA_STATE_NONE; + wc_RsaCleanup(key); + + return ret; +} -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return CaviumRsaPublicEncrypt(in, inLen, out, outLen, key); #endif - sz = mp_unsigned_bin_size(&key->n); - if (sz > (int)outLen) - return RSA_BUFFER_E; +/* Gives the option of choosing padding type + in : input to be decrypted + inLen: length of input buffer + out: decrypted message + outLen: length of decrypted message in bytes + outPtr: optional inline output pointer (if provided doing inline) + key : wolfSSL initialized RSA key struct + 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, WC_RSA_OAEP_PAD, + WC_RSA_NO_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 + labelSz : size of optional label buffer + saltLen : Length of salt used in PSS + rng : random number generator */ +static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, + word32 outLen, byte** outPtr, RsaKey* key, + int rsa_type, byte pad_value, int pad_type, + enum wc_HashType hash, int mgf, + byte* label, word32 labelSz, int saltLen, + WC_RNG* rng) +{ + int ret = RSA_WRONG_TYPE_E; + byte* pad = NULL; - if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) - return RSA_BUFFER_E; + if (in == NULL || inLen == 0 || out == NULL || key == NULL) { + return BAD_FUNC_ARG; + } - ret = wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng); - if (ret != 0) + switch (key->state) { + case RSA_STATE_NONE: + 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 && + pad_type != WC_RSA_PSS_PAD) { +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + if (rsa_type == RSA_PRIVATE_DECRYPT && + pad_value == RSA_BLOCK_TYPE_2) { + key->state = RSA_STATE_DECRYPT_RES; + key->data = NULL; + return NitroxRsaPrivateDecrypt(in, inLen, out, &key->dataLen, + key); +#endif + } + else if (rsa_type == RSA_PUBLIC_DECRYPT && + pad_value == RSA_BLOCK_TYPE_1) { + key->state = RSA_STATE_DECRYPT_RES; + key->data = NULL; + return NitroxRsaSSL_Verify(in, inLen, out, &key->dataLen, key); + } + } + #elif defined(WOLFSSL_CRYPTOCELL) + if (rsa_type == RSA_PRIVATE_DECRYPT && + pad_value == RSA_BLOCK_TYPE_2) { + ret = cc310_RsaPublicDecrypt(in, inLen, out, outLen, key); + if (outPtr != NULL) + *outPtr = out; /* for inline */ + return ret; + } + else if (rsa_type == RSA_PUBLIC_DECRYPT && + pad_value == RSA_BLOCK_TYPE_1) { + return cc310_RsaSSL_Verify(in, inLen, out, key, + cc310_hashModeRSA(hash, 0)); + } + #endif /* WOLFSSL_CRYPTOCELL */ + + +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE) + /* verify the tmp ptr is NULL, otherwise indicates bad state */ + if (key->data != NULL) { + ret = BAD_STATE_E; + break; + } + + /* if not doing this inline then allocate a buffer for it */ + if (outPtr == NULL) { + key->data = (byte*)XMALLOC(inLen, key->heap, + DYNAMIC_TYPE_WOLF_BIGINT); + key->dataIsAlloc = 1; + if (key->data == NULL) { + ret = MEMORY_E; + break; + } + XMEMCPY(key->data, in, inLen); + } + else { + key->data = out; + } +#endif + + key->state = RSA_STATE_DECRYPT_EXPTMOD; + FALL_THROUGH; + + case RSA_STATE_DECRYPT_EXPTMOD: +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE) + ret = wc_RsaFunction(key->data, inLen, key->data, &key->dataLen, + rsa_type, key, rng); +#else + ret = wc_RsaFunction(in, inLen, out, &key->dataLen, rsa_type, key, rng); +#endif + + if (ret >= 0 || ret == WC_PENDING_E) { + key->state = RSA_STATE_DECRYPT_UNPAD; + } + if (ret < 0) { + break; + } + + FALL_THROUGH; + + case RSA_STATE_DECRYPT_UNPAD: +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE) + ret = wc_RsaUnPad_ex(key->data, key->dataLen, &pad, pad_value, pad_type, + hash, mgf, label, labelSz, saltLen, + mp_count_bits(&key->n), key->heap); +#else + ret = wc_RsaUnPad_ex(out, key->dataLen, &pad, pad_value, pad_type, hash, + mgf, label, labelSz, saltLen, + mp_count_bits(&key->n), key->heap); +#endif + if (rsa_type == RSA_PUBLIC_DECRYPT && ret > (int)outLen) + ret = RSA_BUFFER_E; + else if (ret >= 0 && pad != NULL) { +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE) + signed char c; +#endif + + /* only copy output if not inline */ + if (outPtr == NULL) { +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE) + if (rsa_type == RSA_PRIVATE_DECRYPT) { + word32 i, j; + int start = (int)((size_t)pad - (size_t)key->data); + + for (i = 0, j = 0; j < key->dataLen; j++) { + out[i] = key->data[j]; + c = ctMaskGTE(j, start); + c &= ctMaskLT(i, outLen); + /* 0 - no add, -1 add */ + i += (word32)((byte)(-c)); + } + } + else +#endif + { + XMEMCPY(out, pad, ret); + } + } + else + *outPtr = pad; + +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) + ret = ctMaskSelInt(ctMaskLTE(ret, outLen), ret, RSA_BUFFER_E); + ret = ctMaskSelInt(ctMaskNotEq(ret, 0), ret, RSA_BUFFER_E); +#else + if (outLen < (word32)ret) + ret = RSA_BUFFER_E; +#endif + } + + key->state = RSA_STATE_DECRYPT_RES; + FALL_THROUGH; + + case RSA_STATE_DECRYPT_RES: + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(HAVE_CAVIUM) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA && + pad_type != WC_RSA_PSS_PAD) { + if (ret > 0) { + /* convert result */ + byte* dataLen = (byte*)&key->dataLen; + ret = (dataLen[0] << 8) | (dataLen[1]); + + if (outPtr) + *outPtr = in; + } + } + #endif + break; + + default: + ret = BAD_STATE_E; + break; + } + + /* if async pending then return and skip done cleanup below */ + if (ret == WC_PENDING_E + #ifdef WC_RSA_NONBLOCK + || ret == FP_WOULDBLOCK + #endif + ) { return ret; + } - if ((ret = wc_RsaFunction(out, sz, out, &outLen, - RSA_PUBLIC_ENCRYPT, key)) < 0) - sz = ret; + key->state = RSA_STATE_NONE; + wc_RsaCleanup(key); - return sz; + return ret; } +#ifndef WOLFSSL_RSA_VERIFY_ONLY +/* Public RSA Functions */ +int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, WC_RNG* rng) +{ + return RsaPublicEncryptEx(in, inLen, out, outLen, key, + RSA_PUBLIC_ENCRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); +} + + +#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING) +int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng, int type, + enum wc_HashType hash, int mgf, byte* label, + word32 labelSz) +{ + return RsaPublicEncryptEx(in, inLen, out, outLen, key, RSA_PUBLIC_ENCRYPT, + RSA_BLOCK_TYPE_2, type, hash, mgf, label, labelSz, 0, rng); +} +#endif /* WC_NO_RSA_OAEP */ +#endif + + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key) { - int ret; - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) { - ret = CaviumRsaPrivateDecrypt(in, inLen, in, inLen, key); - if (ret > 0) - *out = in; - return ret; - } + WC_RNG* rng; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#else + rng = NULL; #endif - - if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key)) - < 0) { - return ret; - } - - return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_2); + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); } -int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, - RsaKey* key) +#ifndef WC_NO_RSA_OAEP +int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, byte** out, + RsaKey* key, int type, enum wc_HashType hash, + int mgf, byte* label, word32 labelSz) { - int plainLen; - byte* tmp; - byte* pad = 0; - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key); + WC_RNG* rng; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#else + rng = NULL; #endif + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash, + mgf, label, labelSz, 0, rng); +} +#endif /* WC_NO_RSA_OAEP */ - tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); - if (tmp == NULL) { - return MEMORY_E; - } - XMEMCPY(tmp, in, inLen); - - if ( (plainLen = wc_RsaPrivateDecryptInline(tmp, inLen, &pad, key) ) < 0) { - XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); - return plainLen; - } - if (plainLen > (int)outLen) - plainLen = BAD_FUNC_ARG; - else - XMEMCPY(out, pad, plainLen); - - ForceZero(tmp, inLen); - XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); - - return plainLen; +int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + WC_RNG* rng; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#else + rng = NULL; +#endif + return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); } +#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING) +int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, int type, + enum wc_HashType hash, int mgf, byte* label, + word32 labelSz) +{ + WC_RNG* rng; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#else + rng = NULL; +#endif + return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash, mgf, label, + labelSz, 0, rng); +} +#endif /* WC_NO_RSA_OAEP || WC_RSA_NO_PADDING */ +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ -/* for Rsa Verify */ +#if !defined(WOLFSSL_CRYPTOCELL) int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) { - int ret; - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) { - ret = CaviumRsaSSL_Verify(in, inLen, in, inLen, key); - if (ret > 0) - *out = in; - return ret; - } + WC_RNG* rng; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#else + rng = NULL; +#endif + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); +} #endif - if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key)) - < 0) { - return ret; - } - - return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1); -} - - +#ifndef WOLFSSL_RSA_VERIFY_ONLY int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, - RsaKey* key) + RsaKey* key) { - int plainLen; - byte* tmp; - byte* pad = 0; + return wc_RsaSSL_Verify_ex(in, inLen, out, outLen, key , WC_RSA_PKCSV15_PAD); +} -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return CaviumRsaSSL_Verify(in, inLen, out, outLen, key); +int wc_RsaSSL_Verify_ex(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, int pad_type) +{ + WC_RNG* rng; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WC_RSA_BLINDING + rng = key->rng; +#else + rng = NULL; #endif - tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); - if (tmp == NULL) { - return MEMORY_E; - } + return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, pad_type, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); +} +#endif - XMEMCPY(tmp, in, inLen); +#ifdef WC_RSA_PSS +/* Verify the message signed with RSA-PSS. + * The input buffer is reused for the output buffer. + * Salt length is equal to hash length. + * + * in Buffer holding encrypted data. + * inLen Length of data in buffer. + * out Pointer to address containing the PSS data. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * returns the length of the PSS data on success and negative indicates failure. + */ +int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out, + enum wc_HashType hash, int mgf, RsaKey* key) +{ +#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER + return wc_RsaPSS_VerifyInline_ex(in, inLen, out, hash, mgf, + RSA_PSS_SALT_LEN_DEFAULT, key); +#else + return wc_RsaPSS_VerifyInline_ex(in, inLen, out, hash, mgf, + RSA_PSS_SALT_LEN_DISCOVER, key); +#endif +} - if ( (plainLen = wc_RsaSSL_VerifyInline(tmp, inLen, &pad, key) ) < 0) { - XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); - return plainLen; - } +/* Verify the message signed with RSA-PSS. + * The input buffer is reused for the output buffer. + * + * in Buffer holding encrypted data. + * inLen Length of data in buffer. + * out Pointer to address containing the PSS data. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * saltLen Length of salt used. RSA_PSS_SALT_LEN_DEFAULT (-1) indicates salt + * length is the same as the hash length. RSA_PSS_SALT_LEN_DISCOVER + * indicates salt length is determined from the data. + * returns the length of the PSS data on success and negative indicates failure. + */ +int wc_RsaPSS_VerifyInline_ex(byte* in, word32 inLen, byte** out, + enum wc_HashType hash, int mgf, int saltLen, + RsaKey* key) +{ + WC_RNG* rng; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#else + rng = NULL; +#endif + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, + hash, mgf, NULL, 0, saltLen, rng); +} - if (plainLen > (int)outLen) - plainLen = BAD_FUNC_ARG; - else - XMEMCPY(out, pad, plainLen); +/* Verify the message signed with RSA-PSS. + * Salt length is equal to hash length. + * + * in Buffer holding encrypted data. + * inLen Length of data in buffer. + * out Pointer to address containing the PSS data. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * returns the length of the PSS data on success and negative indicates failure. + */ +int wc_RsaPSS_Verify(byte* in, word32 inLen, byte* out, word32 outLen, + enum wc_HashType hash, int mgf, RsaKey* key) +{ +#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER + return wc_RsaPSS_Verify_ex(in, inLen, out, outLen, hash, mgf, + RSA_PSS_SALT_LEN_DEFAULT, key); +#else + return wc_RsaPSS_Verify_ex(in, inLen, out, outLen, hash, mgf, + RSA_PSS_SALT_LEN_DISCOVER, key); +#endif +} - ForceZero(tmp, inLen); - XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); - - return plainLen; +/* Verify the message signed with RSA-PSS. + * + * in Buffer holding encrypted data. + * inLen Length of data in buffer. + * out Pointer to address containing the PSS data. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * saltLen Length of salt used. RSA_PSS_SALT_LEN_DEFAULT (-1) indicates salt + * length is the same as the hash length. RSA_PSS_SALT_LEN_DISCOVER + * indicates salt length is determined from the data. + * returns the length of the PSS data on success and negative indicates failure. + */ +int wc_RsaPSS_Verify_ex(byte* in, word32 inLen, byte* out, word32 outLen, + enum wc_HashType hash, int mgf, int saltLen, + RsaKey* key) +{ + WC_RNG* rng; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#else + rng = NULL; +#endif + return RsaPrivateDecryptEx(in, inLen, out, outLen, NULL, key, + RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, + hash, mgf, NULL, 0, saltLen, rng); } -/* for Rsa Sign */ +/* Checks the PSS data to ensure that the signature matches. + * Salt length is equal to hash length. + * + * in Hash of the data that is being verified. + * inSz Length of hash. + * sig Buffer holding PSS data. + * sigSz Size of PSS data. + * hashType Hash algorithm. + * returns BAD_PADDING_E when the PSS data is invalid, BAD_FUNC_ARG when + * NULL is passed in to in or sig or inSz is not the same as the hash + * algorithm length and 0 on success. + */ +int wc_RsaPSS_CheckPadding(const byte* in, word32 inSz, byte* sig, + word32 sigSz, enum wc_HashType hashType) +{ + return wc_RsaPSS_CheckPadding_ex(in, inSz, sig, sigSz, hashType, inSz, 0); +} + +/* Checks the PSS data to ensure that the signature matches. + * + * in Hash of the data that is being verified. + * inSz Length of hash. + * sig Buffer holding PSS data. + * sigSz Size of PSS data. + * hashType Hash algorithm. + * saltLen Length of salt used. RSA_PSS_SALT_LEN_DEFAULT (-1) indicates salt + * length is the same as the hash length. RSA_PSS_SALT_LEN_DISCOVER + * indicates salt length is determined from the data. + * returns BAD_PADDING_E when the PSS data is invalid, BAD_FUNC_ARG when + * NULL is passed in to in or sig or inSz is not the same as the hash + * algorithm length and 0 on success. + */ +int wc_RsaPSS_CheckPadding_ex(const byte* in, word32 inSz, byte* sig, + word32 sigSz, enum wc_HashType hashType, + int saltLen, int bits) +{ + int ret = 0; +#ifndef WOLFSSL_PSS_LONG_SALT + byte sigCheck[WC_MAX_DIGEST_SIZE*2 + RSA_PSS_PAD_SZ]; +#else + byte *sigCheck = NULL; +#endif + + (void)bits; + + if (in == NULL || sig == NULL || + inSz != (word32)wc_HashGetDigestSize(hashType)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if (saltLen == RSA_PSS_SALT_LEN_DEFAULT) { + saltLen = inSz; + #ifdef WOLFSSL_SHA512 + /* See FIPS 186-4 section 5.5 item (e). */ + if (bits == 1024 && inSz == WC_SHA512_DIGEST_SIZE) { + saltLen = RSA_PSS_SALT_MAX_SZ; + } + #endif + } +#ifndef WOLFSSL_PSS_LONG_SALT + else if ((word32)saltLen > inSz) { + ret = PSS_SALTLEN_E; + } +#endif +#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER + else if (saltLen < RSA_PSS_SALT_LEN_DEFAULT) { + ret = PSS_SALTLEN_E; + } +#else + else if (saltLen == RSA_PSS_SALT_LEN_DISCOVER) { + saltLen = sigSz - inSz; + if (saltLen < 0) { + ret = PSS_SALTLEN_E; + } + } + else if (saltLen < RSA_PSS_SALT_LEN_DISCOVER) { + ret = PSS_SALTLEN_E; + } +#endif + } + + /* Sig = Salt | Exp Hash */ + if (ret == 0) { + if (sigSz != inSz + saltLen) { + ret = PSS_SALTLEN_E; + } + } + +#ifdef WOLFSSL_PSS_LONG_SALT + if (ret == 0) { + sigCheck = (byte*)XMALLOC(RSA_PSS_PAD_SZ + inSz + saltLen, NULL, + DYNAMIC_TYPE_RSA_BUFFER); + if (sigCheck == NULL) { + ret = MEMORY_E; + } + } +#endif + + /* Exp Hash = HASH(8 * 0x00 | Message Hash | Salt) */ + if (ret == 0) { + XMEMSET(sigCheck, 0, RSA_PSS_PAD_SZ); + XMEMCPY(sigCheck + RSA_PSS_PAD_SZ, in, inSz); + XMEMCPY(sigCheck + RSA_PSS_PAD_SZ + inSz, sig, saltLen); + ret = wc_Hash(hashType, sigCheck, RSA_PSS_PAD_SZ + inSz + saltLen, + sigCheck, inSz); + } + if (ret == 0) { + if (XMEMCMP(sigCheck, sig + saltLen, inSz) != 0) { + WOLFSSL_MSG("RsaPSS_CheckPadding: Padding Error"); + ret = BAD_PADDING_E; + } + } + +#ifdef WOLFSSL_PSS_LONG_SALT + if (sigCheck != NULL) { + XFREE(sigCheck, NULL, DYNAMIC_TYPE_RSA_BUFFER); + } +#endif + return ret; +} + + +/* Verify the message signed with RSA-PSS. + * The input buffer is reused for the output buffer. + * Salt length is equal to hash length. + * + * in Buffer holding encrypted data. + * inLen Length of data in buffer. + * out Pointer to address containing the PSS data. + * digest Hash of the data that is being verified. + * digestLen Length of hash. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * returns the length of the PSS data on success and negative indicates failure. + */ +int wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out, + const byte* digest, word32 digestLen, + enum wc_HashType hash, int mgf, RsaKey* key) +{ + int ret = 0, verify, saltLen, hLen, bits = 0; + + hLen = wc_HashGetDigestSize(hash); + if (hLen < 0) + return hLen; + if ((word32)hLen != digestLen) + return BAD_FUNC_ARG; + + saltLen = hLen; + #ifdef WOLFSSL_SHA512 + /* See FIPS 186-4 section 5.5 item (e). */ + bits = mp_count_bits(&key->n); + if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE) + saltLen = RSA_PSS_SALT_MAX_SZ; + #endif + + verify = wc_RsaPSS_VerifyInline_ex(in, inLen, out, hash, mgf, saltLen, key); + if (verify > 0) + ret = wc_RsaPSS_CheckPadding_ex(digest, digestLen, *out, verify, + hash, saltLen, bits); + if (ret == 0) + ret = verify; + + return ret; +} + + +/* Verify the message signed with RSA-PSS. + * Salt length is equal to hash length. + * + * in Buffer holding encrypted data. + * inLen Length of data in buffer. + * out Pointer to address containing the PSS data. + * outLen Length of the output. + * digest Hash of the data that is being verified. + * digestLen Length of hash. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * returns the length of the PSS data on success and negative indicates failure. + */ +int wc_RsaPSS_VerifyCheck(byte* in, word32 inLen, byte* out, word32 outLen, + const byte* digest, word32 digestLen, + enum wc_HashType hash, int mgf, + RsaKey* key) +{ + int ret = 0, verify, saltLen, hLen, bits = 0; + + hLen = wc_HashGetDigestSize(hash); + if (hLen < 0) + return hLen; + if ((word32)hLen != digestLen) + return BAD_FUNC_ARG; + + saltLen = hLen; + #ifdef WOLFSSL_SHA512 + /* See FIPS 186-4 section 5.5 item (e). */ + bits = mp_count_bits(&key->n); + if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE) + saltLen = RSA_PSS_SALT_MAX_SZ; + #endif + + verify = wc_RsaPSS_Verify_ex(in, inLen, out, outLen, hash, + mgf, saltLen, key); + if (verify > 0) + ret = wc_RsaPSS_CheckPadding_ex(digest, digestLen, out, verify, + hash, saltLen, bits); + if (ret == 0) + ret = verify; + + return ret; +} + +#endif + +#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY) int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, - RsaKey* key, RNG* rng) + RsaKey* key, WC_RNG* rng) { - int sz, ret; - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return CaviumRsaSSL_Sign(in, inLen, out, outLen, key); -#endif - - sz = mp_unsigned_bin_size(&key->n); - if (sz > (int)outLen) - return RSA_BUFFER_E; - - if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) - return RSA_BUFFER_E; - - ret = wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng); - if (ret != 0) - return ret; - - if ((ret = wc_RsaFunction(out, sz, out, &outLen, - RSA_PRIVATE_ENCRYPT,key)) < 0) - sz = ret; - - return sz; + return RsaPublicEncryptEx(in, inLen, out, outLen, key, + RSA_PRIVATE_ENCRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); } +#ifdef WC_RSA_PSS +/* Sign the hash of a message using RSA-PSS. + * Salt length is equal to hash length. + * + * in Buffer holding hash of message. + * inLen Length of data in buffer (hash length). + * out Buffer to write encrypted signature into. + * outLen Size of buffer to write to. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * rng Random number generator. + * returns the length of the encrypted signature on success, a negative value + * indicates failure. + */ +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 wc_RsaPSS_Sign_ex(in, inLen, out, outLen, hash, mgf, + RSA_PSS_SALT_LEN_DEFAULT, key, rng); +} +/* Sign the hash of a message using RSA-PSS. + * + * in Buffer holding hash of message. + * inLen Length of data in buffer (hash length). + * out Buffer to write encrypted signature into. + * outLen Size of buffer to write to. + * hash Hash algorithm. + * mgf Mask generation function. + * saltLen Length of salt used. RSA_PSS_SALT_LEN_DEFAULT (-1) indicates salt + * length is the same as the hash length. RSA_PSS_SALT_LEN_DISCOVER + * indicates salt length is determined from the data. + * key Public RSA key. + * rng Random number generator. + * returns the length of the encrypted signature on success, a negative value + * indicates failure. + */ +int wc_RsaPSS_Sign_ex(const byte* in, word32 inLen, byte* out, word32 outLen, + enum wc_HashType hash, int mgf, int saltLen, 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, saltLen, rng); +} +#endif +#endif + +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) || !defined(WOLFSSL_SP_MATH) || \ + defined(WC_RSA_PSS) int wc_RsaEncryptSize(RsaKey* key) { -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return key->c_nSz; -#endif - return mp_unsigned_bin_size(&key->n); -} + int ret; + if (key == NULL) { + return BAD_FUNC_ARG; + } + + ret = mp_unsigned_bin_size(&key->n); + +#ifdef WOLF_CRYPTO_CB + if (ret == 0 && key->devId != INVALID_DEVID) { + ret = 2048/8; /* hardware handles, use 2048-bit as default */ + } +#endif + + return ret; +} +#endif + +#ifndef WOLFSSL_RSA_VERIFY_ONLY /* flatten RsaKey structure into individual elements (e, n) */ int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, - word32* nSz) + word32* nSz) { int sz, ret; - if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) - return BAD_FUNC_ARG; + if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) { + return BAD_FUNC_ARG; + } sz = mp_unsigned_bin_size(&key->e); - if ((word32)sz > *nSz) + if ((word32)sz > *eSz) return RSA_BUFFER_E; ret = mp_to_unsigned_bin(&key->e, e); if (ret != MP_OKAY) return ret; *eSz = (word32)sz; - sz = mp_unsigned_bin_size(&key->n); + sz = wc_RsaEncryptSize(key); if ((word32)sz > *nSz) return RSA_BUFFER_E; ret = mp_to_unsigned_bin(&key->n, n); @@ -609,364 +3586,616 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, return 0; } +#endif + +#endif /* HAVE_FIPS */ + + +#ifndef WOLFSSL_RSA_VERIFY_ONLY +static int RsaGetValue(mp_int* in, byte* out, word32* outSz) +{ + word32 sz; + int ret = 0; + + /* Parameters ensured by calling function. */ + + sz = (word32)mp_unsigned_bin_size(in); + if (sz > *outSz) + ret = RSA_BUFFER_E; + + if (ret == 0) + ret = mp_to_unsigned_bin(in, out); + + if (ret == MP_OKAY) + *outSz = sz; + + return ret; +} + + +int wc_RsaExportKey(RsaKey* key, + byte* e, word32* eSz, byte* n, word32* nSz, + byte* d, word32* dSz, byte* p, word32* pSz, + byte* q, word32* qSz) +{ + int ret = BAD_FUNC_ARG; + + if (key && e && eSz && n && nSz && d && dSz && p && pSz && q && qSz) + ret = 0; + + if (ret == 0) + ret = RsaGetValue(&key->e, e, eSz); + if (ret == 0) + ret = RsaGetValue(&key->n, n, nSz); +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + if (ret == 0) + ret = RsaGetValue(&key->d, d, dSz); + if (ret == 0) + ret = RsaGetValue(&key->p, p, pSz); + if (ret == 0) + ret = RsaGetValue(&key->q, q, qSz); +#else + /* no private parts to key */ + if (d == NULL || p == NULL || q == NULL || dSz == NULL || pSz == NULL + || qSz == NULL) { + ret = BAD_FUNC_ARG; + } + else { + *dSz = 0; + *pSz = 0; + *qSz = 0; + } +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + + return ret; +} +#endif #ifdef WOLFSSL_KEY_GEN -static const int USE_BBS = 1; - -static int rand_prime(mp_int* N, int len, RNG* rng, void* heap) +/* Check that |p-q| > 2^((size/2)-100) */ +static int wc_CompareDiffPQ(mp_int* p, mp_int* q, int size) { - int err, res, type; - byte* buf; + mp_int c, d; + int ret; - (void)heap; - if (N == NULL || rng == NULL) - return BAD_FUNC_ARG; - - /* get type */ - if (len < 0) { - type = USE_BBS; - len = -len; - } else { - type = 0; - } - - /* allow sizes between 2 and 512 bytes for a prime size */ - if (len < 2 || len > 512) { + if (p == NULL || q == NULL) return BAD_FUNC_ARG; - } - - /* allocate buffer to work with */ - buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_RSA); - if (buf == NULL) { - return MEMORY_E; - } - XMEMSET(buf, 0, len); - do { -#ifdef SHOW_GEN - printf("."); - fflush(stdout); -#endif - /* generate value */ - err = wc_RNG_GenerateBlock(rng, buf, len); - if (err != 0) { - XFREE(buf, heap, DYNAMIC_TYPE_RSA); - return err; - } + ret = mp_init_multi(&c, &d, NULL, NULL, NULL, NULL); - /* munge bits */ - buf[0] |= 0x80 | 0x40; - buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); - - /* load value */ - if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) { - XFREE(buf, heap, DYNAMIC_TYPE_RSA); - return err; - } + /* c = 2^((size/2)-100) */ + if (ret == 0) + ret = mp_2expt(&c, (size/2)-100); - /* test */ - if ((err = mp_prime_is_prime(N, 8, &res)) != MP_OKAY) { - XFREE(buf, heap, DYNAMIC_TYPE_RSA); - return err; - } - } while (res == MP_NO); + /* d = |p-q| */ + if (ret == 0) + ret = mp_sub(p, q, &d); - ForceZero(buf, len); - XFREE(buf, heap, DYNAMIC_TYPE_RSA); + if (ret == 0) + ret = mp_abs(&d, &d); - return 0; + /* compare */ + if (ret == 0) + ret = mp_cmp(&d, &c); + + if (ret == MP_GT) + ret = MP_OKAY; + + mp_clear(&d); + mp_clear(&c); + + return ret; } -/* Make an RSA key for size bits, with e specified, 65537 is a good e */ -int wc_MakeRsaKey(RsaKey* key, int size, long e, RNG* rng) +/* The lower_bound value is floor(2^(0.5) * 2^((nlen/2)-1)) where nlen is 4096. + * This number was calculated using a small test tool written with a common + * large number math library. Other values of nlen may be checked with a subset + * of lower_bound. */ +static const byte lower_bound[] = { + 0xB5, 0x04, 0xF3, 0x33, 0xF9, 0xDE, 0x64, 0x84, + 0x59, 0x7D, 0x89, 0xB3, 0x75, 0x4A, 0xBE, 0x9F, + 0x1D, 0x6F, 0x60, 0xBA, 0x89, 0x3B, 0xA8, 0x4C, + 0xED, 0x17, 0xAC, 0x85, 0x83, 0x33, 0x99, 0x15, +/* 512 */ + 0x4A, 0xFC, 0x83, 0x04, 0x3A, 0xB8, 0xA2, 0xC3, + 0xA8, 0xB1, 0xFE, 0x6F, 0xDC, 0x83, 0xDB, 0x39, + 0x0F, 0x74, 0xA8, 0x5E, 0x43, 0x9C, 0x7B, 0x4A, + 0x78, 0x04, 0x87, 0x36, 0x3D, 0xFA, 0x27, 0x68, +/* 1024 */ + 0xD2, 0x20, 0x2E, 0x87, 0x42, 0xAF, 0x1F, 0x4E, + 0x53, 0x05, 0x9C, 0x60, 0x11, 0xBC, 0x33, 0x7B, + 0xCA, 0xB1, 0xBC, 0x91, 0x16, 0x88, 0x45, 0x8A, + 0x46, 0x0A, 0xBC, 0x72, 0x2F, 0x7C, 0x4E, 0x33, + 0xC6, 0xD5, 0xA8, 0xA3, 0x8B, 0xB7, 0xE9, 0xDC, + 0xCB, 0x2A, 0x63, 0x43, 0x31, 0xF3, 0xC8, 0x4D, + 0xF5, 0x2F, 0x12, 0x0F, 0x83, 0x6E, 0x58, 0x2E, + 0xEA, 0xA4, 0xA0, 0x89, 0x90, 0x40, 0xCA, 0x4A, +/* 2048 */ + 0x81, 0x39, 0x4A, 0xB6, 0xD8, 0xFD, 0x0E, 0xFD, + 0xF4, 0xD3, 0xA0, 0x2C, 0xEB, 0xC9, 0x3E, 0x0C, + 0x42, 0x64, 0xDA, 0xBC, 0xD5, 0x28, 0xB6, 0x51, + 0xB8, 0xCF, 0x34, 0x1B, 0x6F, 0x82, 0x36, 0xC7, + 0x01, 0x04, 0xDC, 0x01, 0xFE, 0x32, 0x35, 0x2F, + 0x33, 0x2A, 0x5E, 0x9F, 0x7B, 0xDA, 0x1E, 0xBF, + 0xF6, 0xA1, 0xBE, 0x3F, 0xCA, 0x22, 0x13, 0x07, + 0xDE, 0xA0, 0x62, 0x41, 0xF7, 0xAA, 0x81, 0xC2, +/* 3072 */ + 0xC1, 0xFC, 0xBD, 0xDE, 0xA2, 0xF7, 0xDC, 0x33, + 0x18, 0x83, 0x8A, 0x2E, 0xAF, 0xF5, 0xF3, 0xB2, + 0xD2, 0x4F, 0x4A, 0x76, 0x3F, 0xAC, 0xB8, 0x82, + 0xFD, 0xFE, 0x17, 0x0F, 0xD3, 0xB1, 0xF7, 0x80, + 0xF9, 0xAC, 0xCE, 0x41, 0x79, 0x7F, 0x28, 0x05, + 0xC2, 0x46, 0x78, 0x5E, 0x92, 0x95, 0x70, 0x23, + 0x5F, 0xCF, 0x8F, 0x7B, 0xCA, 0x3E, 0xA3, 0x3B, + 0x4D, 0x7C, 0x60, 0xA5, 0xE6, 0x33, 0xE3, 0xE1 +/* 4096 */ +}; + + +/* returns 1 on key size ok and 0 if not ok */ +static WC_INLINE int RsaSizeCheck(int size) { + if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE) { + return 0; + } + +#ifdef HAVE_FIPS + /* Key size requirements for CAVP */ + switch (size) { + case 1024: + case 2048: + case 3072: + case 4096: + return 1; + } + + return 0; +#else + return 1; /* allow unusual key sizes in non FIPS mode */ +#endif /* HAVE_FIPS */ +} + + +static int _CheckProbablePrime(mp_int* p, mp_int* q, mp_int* e, int nlen, + int* isPrime, WC_RNG* rng) +{ + int ret; + mp_int tmp1, tmp2; + mp_int* prime; + + if (p == NULL || e == NULL || isPrime == NULL) + return BAD_FUNC_ARG; + + if (!RsaSizeCheck(nlen)) + return BAD_FUNC_ARG; + + *isPrime = MP_NO; + + if (q != NULL) { + /* 5.4 - check that |p-q| <= (2^(1/2))(2^((nlen/2)-1)) */ + ret = wc_CompareDiffPQ(p, q, nlen); + if (ret != MP_OKAY) goto notOkay; + prime = q; + } + else + prime = p; + + ret = mp_init_multi(&tmp1, &tmp2, NULL, NULL, NULL, NULL); + if (ret != MP_OKAY) goto notOkay; + + /* 4.4,5.5 - Check that prime >= (2^(1/2))(2^((nlen/2)-1)) + * This is a comparison against lowerBound */ + ret = mp_read_unsigned_bin(&tmp1, lower_bound, nlen/16); + if (ret != MP_OKAY) goto notOkay; + ret = mp_cmp(prime, &tmp1); + if (ret == MP_LT) goto exit; + + /* 4.5,5.6 - Check that GCD(p-1, e) == 1 */ + ret = mp_sub_d(prime, 1, &tmp1); /* tmp1 = prime-1 */ + if (ret != MP_OKAY) goto notOkay; + ret = mp_gcd(&tmp1, e, &tmp2); /* tmp2 = gcd(prime-1, e) */ + if (ret != MP_OKAY) goto notOkay; + ret = mp_cmp_d(&tmp2, 1); + if (ret != MP_EQ) goto exit; /* e divides p-1 */ + + /* 4.5.1,5.6.1 - Check primality of p with 8 rounds of M-R. + * mp_prime_is_prime_ex() performs test divisions against the first 256 + * prime numbers. After that it performs 8 rounds of M-R using random + * bases between 2 and n-2. + * mp_prime_is_prime() performs the same test divisions and then does + * M-R with the first 8 primes. Both functions set isPrime as a + * side-effect. */ + if (rng != NULL) + ret = mp_prime_is_prime_ex(prime, 8, isPrime, rng); + else + ret = mp_prime_is_prime(prime, 8, isPrime); + if (ret != MP_OKAY) goto notOkay; + +exit: + ret = MP_OKAY; +notOkay: + mp_clear(&tmp1); + mp_clear(&tmp2); + return ret; +} + + +int wc_CheckProbablePrime_ex(const byte* pRaw, word32 pRawSz, + const byte* qRaw, word32 qRawSz, + const byte* eRaw, word32 eRawSz, + int nlen, int* isPrime, WC_RNG* rng) +{ + mp_int p, q, e; + mp_int* Q = NULL; + int ret; + + if (pRaw == NULL || pRawSz == 0 || + eRaw == NULL || eRawSz == 0 || + isPrime == NULL) { + + return BAD_FUNC_ARG; + } + + if ((qRaw != NULL && qRawSz == 0) || (qRaw == NULL && qRawSz != 0)) + return BAD_FUNC_ARG; + + ret = mp_init_multi(&p, &q, &e, NULL, NULL, NULL); + + if (ret == MP_OKAY) + ret = mp_read_unsigned_bin(&p, pRaw, pRawSz); + + if (ret == MP_OKAY) { + if (qRaw != NULL) { + ret = mp_read_unsigned_bin(&q, qRaw, qRawSz); + if (ret == MP_OKAY) + Q = &q; + } + } + + if (ret == MP_OKAY) + ret = mp_read_unsigned_bin(&e, eRaw, eRawSz); + + if (ret == MP_OKAY) + ret = _CheckProbablePrime(&p, Q, &e, nlen, isPrime, rng); + + ret = (ret == MP_OKAY) ? 0 : PRIME_GEN_E; + + mp_clear(&p); + mp_clear(&q); + mp_clear(&e); + + return ret; +} + + +int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz, + const byte* qRaw, word32 qRawSz, + const byte* eRaw, word32 eRawSz, + int nlen, int* isPrime) +{ + return wc_CheckProbablePrime_ex(pRaw, pRawSz, qRaw, qRawSz, + eRaw, eRawSz, nlen, isPrime, NULL); +} + +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) +/* Make an RSA key for size bits, with e specified, 65537 is a good e */ +int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) +{ +#ifndef WC_NO_RNG mp_int p, q, tmp1, tmp2, tmp3; - int err; + int err, i, failCount, primeSz, isPrime = 0; + byte* buf = NULL; if (key == NULL || rng == NULL) return BAD_FUNC_ARG; - if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE) + if (!RsaSizeCheck(size)) return BAD_FUNC_ARG; if (e < 3 || (e & 1) == 0) return BAD_FUNC_ARG; - if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY) - return err; +#if defined(WOLFSSL_CRYPTOCELL) - err = mp_set_int(&tmp3, e); + return cc310_RSA_GenerateKeyPair(key, size, e); + +#endif /*WOLFSSL_CRYPTOCELL*/ + +#ifdef WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_MakeRsaKey(key, size, e, rng); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(WC_ASYNC_ENABLE_RSA_KEYGEN) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + return IntelQaRsaKeyGen(&key->asyncDev, key, size, e, rng); + #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 + + err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL); + + if (err == MP_OKAY) + err = mp_set_int(&tmp3, e); + + /* The failCount value comes from NIST FIPS 186-4, section B.3.3, + * process steps 4.7 and 5.8. */ + failCount = 5 * (size / 2); + primeSz = size / 16; /* size is the size of n in bits. + primeSz is in bytes. */ + + /* allocate buffer to work with */ + if (err == MP_OKAY) { + buf = (byte*)XMALLOC(primeSz, key->heap, DYNAMIC_TYPE_RSA); + if (buf == NULL) + err = MEMORY_E; + } /* make p */ if (err == MP_OKAY) { + isPrime = 0; + i = 0; do { - err = rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */ +#ifdef SHOW_GEN + printf("."); + fflush(stdout); +#endif + /* generate value */ + err = wc_RNG_GenerateBlock(rng, buf, primeSz); + if (err == 0) { + /* prime lower bound has the MSB set, set it in candidate */ + buf[0] |= 0x80; + /* make candidate odd */ + buf[primeSz-1] |= 0x01; + /* load value */ + err = mp_read_unsigned_bin(&p, buf, primeSz); + } if (err == MP_OKAY) - err = mp_sub_d(&p, 1, &tmp1); /* tmp1 = p-1 */ + err = _CheckProbablePrime(&p, NULL, &tmp3, size, &isPrime, rng); - if (err == MP_OKAY) - err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(p-1, e) */ - } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divdes p-1 */ +#ifdef HAVE_FIPS + i++; +#else + /* Keep the old retry behavior in non-FIPS build. */ + (void)i; +#endif + } while (err == MP_OKAY && !isPrime && i < failCount); } + if (err == MP_OKAY && !isPrime) + err = PRIME_GEN_E; + /* make q */ if (err == MP_OKAY) { + isPrime = 0; + i = 0; do { - err = rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */ +#ifdef SHOW_GEN + printf("."); + fflush(stdout); +#endif + /* generate value */ + err = wc_RNG_GenerateBlock(rng, buf, primeSz); + if (err == 0) { + /* prime lower bound has the MSB set, set it in candidate */ + buf[0] |= 0x80; + /* make candidate odd */ + buf[primeSz-1] |= 0x01; + /* load value */ + err = mp_read_unsigned_bin(&q, buf, primeSz); + } if (err == MP_OKAY) - err = mp_sub_d(&q, 1, &tmp1); /* tmp1 = q-1 */ + err = _CheckProbablePrime(&p, &q, &tmp3, size, &isPrime, rng); - if (err == MP_OKAY) - err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(q-1, e) */ - } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divdes q-1 */ +#ifdef HAVE_FIPS + i++; +#else + /* Keep the old retry behavior in non-FIPS build. */ + (void)i; +#endif + } while (err == MP_OKAY && !isPrime && i < failCount); } + if (err == MP_OKAY && !isPrime) + err = PRIME_GEN_E; + + if (buf) { + ForceZero(buf, primeSz); + XFREE(buf, key->heap, DYNAMIC_TYPE_RSA); + } + + if (err == MP_OKAY && mp_cmp(&p, &q) < 0) { + err = mp_copy(&p, &tmp1); + if (err == MP_OKAY) + err = mp_copy(&q, &p); + if (err == MP_OKAY) + mp_copy(&tmp1, &q); + } + + /* Setup RsaKey buffers */ if (err == MP_OKAY) err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL); - if (err == MP_OKAY) err = mp_init_multi(&key->dP, &key->dQ, &key->u, NULL, NULL, NULL); - if (err == MP_OKAY) - err = mp_sub_d(&p, 1, &tmp2); /* tmp2 = p-1 */ - - if (err == MP_OKAY) - err = mp_lcm(&tmp1, &tmp2, &tmp1); /* tmp1 = lcm(p-1, q-1),last loop */ - - /* make key */ - if (err == MP_OKAY) - err = mp_set_int(&key->e, e); /* key->e = e */ - - if (err == MP_OKAY) /* key->d = 1/e mod lcm(p-1, q-1) */ - err = mp_invmod(&key->e, &tmp1, &key->d); - - if (err == MP_OKAY) - err = mp_mul(&p, &q, &key->n); /* key->n = pq */ - - if (err == MP_OKAY) + /* Software Key Calculation */ + if (err == MP_OKAY) /* tmp1 = p-1 */ err = mp_sub_d(&p, 1, &tmp1); - - if (err == MP_OKAY) + if (err == MP_OKAY) /* tmp2 = q-1 */ err = mp_sub_d(&q, 1, &tmp2); - +#ifdef WC_RSA_BLINDING + if (err == MP_OKAY) /* tmp3 = order of n */ + err = mp_mul(&tmp1, &tmp2, &tmp3); +#else + if (err == MP_OKAY) /* tmp3 = lcm(p-1, q-1), last loop */ + err = mp_lcm(&tmp1, &tmp2, &tmp3); +#endif + /* make key */ + if (err == MP_OKAY) /* key->e = e */ + err = mp_set_int(&key->e, (mp_digit)e); +#ifdef WC_RSA_BLINDING + /* Blind the inverse operation with a value that is invertable */ + if (err == MP_OKAY) { + do { + err = mp_rand(&key->p, get_digit_count(&tmp3), rng); + if (err == MP_OKAY) + err = mp_set_bit(&key->p, 0); + if (err == MP_OKAY) + err = mp_set_bit(&key->p, size - 1); + if (err == MP_OKAY) + err = mp_gcd(&key->p, &tmp3, &key->q); + } + while ((err == MP_OKAY) && !mp_isone(&key->q)); + } if (err == MP_OKAY) + err = mp_mul_d(&key->p, (mp_digit)e, &key->e); +#endif + if (err == MP_OKAY) /* key->d = 1/e mod lcm(p-1, q-1) */ + err = mp_invmod(&key->e, &tmp3, &key->d); +#ifdef WC_RSA_BLINDING + /* Take off blinding from d and reset e */ + if (err == MP_OKAY) + err = mp_mulmod(&key->d, &key->p, &tmp3, &key->d); + if (err == MP_OKAY) + err = mp_set_int(&key->e, (mp_digit)e); +#endif + if (err == MP_OKAY) /* key->n = pq */ + err = mp_mul(&p, &q, &key->n); + if (err == MP_OKAY) /* key->dP = d mod(p-1) */ err = mp_mod(&key->d, &tmp1, &key->dP); - - if (err == MP_OKAY) + if (err == MP_OKAY) /* key->dQ = d mod(q-1) */ err = mp_mod(&key->d, &tmp2, &key->dQ); - - if (err == MP_OKAY) +#ifdef WOLFSSL_MP_INVMOD_CONSTANT_TIME + if (err == MP_OKAY) /* key->u = 1/q mod p */ err = mp_invmod(&q, &p, &key->u); - +#else + if (err == MP_OKAY) + err = mp_sub_d(&p, 2, &tmp3); + if (err == MP_OKAY) /* key->u = 1/q mod p = q^p-2 mod p */ + err = mp_exptmod(&q, &tmp3 , &p, &key->u); +#endif if (err == MP_OKAY) err = mp_copy(&p, &key->p); - if (err == MP_OKAY) err = mp_copy(&q, &key->q); +#ifdef HAVE_WOLF_BIGINT + /* make sure raw unsigned bin version is available */ if (err == MP_OKAY) - key->type = RSA_PRIVATE; + err = wc_mp_to_bigint(&key->n, &key->n.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->e, &key->e.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->d, &key->d.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->p, &key->p.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->q, &key->q.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->dP, &key->dP.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->dQ, &key->dQ.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->u, &key->u.raw); +#endif - mp_clear(&tmp3); - mp_clear(&tmp2); - mp_clear(&tmp1); - mp_clear(&q); + if (err == MP_OKAY) + key->type = RSA_PRIVATE; + + mp_clear(&tmp1); + mp_clear(&tmp2); + mp_clear(&tmp3); mp_clear(&p); + mp_clear(&q); - if (err != MP_OKAY) { - wc_FreeRsaKey(key); +#if defined(WOLFSSL_KEY_GEN) && !defined(WOLFSSL_NO_RSA_KEY_CHECK) + /* Perform the pair-wise consistency test on the new key. */ + if (err == 0) + err = wc_CheckRsaKey(key); +#endif + + if (err != 0) { + wc_FreeRsaKey(key); return err; } +#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL) + if (wc_InitRsaHw(key) != 0) { + return BAD_STATE_E; + } +#endif return 0; +#else + return NOT_COMPILED_IN; +#endif } - - +#endif /* !FIPS || FIPS_VER >= 2 */ #endif /* WOLFSSL_KEY_GEN */ -#ifdef HAVE_CAVIUM - -#include -#include "cavium_common.h" - -/* Initiliaze RSA for use with Nitrox device */ -int RsaInitCavium(RsaKey* rsa, int devId) -{ - if (rsa == NULL) - return -1; - - if (CspAllocContext(CONTEXT_SSL, &rsa->contextHandle, devId) != 0) - return -1; - - rsa->devId = devId; - rsa->magic = WOLFSSL_RSA_CAVIUM_MAGIC; - - return 0; -} - - -/* Free RSA from use with Nitrox device */ -void wc_RsaFreeCavium(RsaKey* rsa) -{ - if (rsa == NULL) - return; - - CspFreeContext(CONTEXT_SSL, rsa->contextHandle, rsa->devId); - rsa->magic = 0; -} - - -/* Initialize cavium RSA key */ -static int InitCaviumRsaKey(RsaKey* key, void* heap) +#ifdef WC_RSA_BLINDING +int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng) { if (key == NULL) return BAD_FUNC_ARG; - key->heap = heap; - key->type = -1; /* don't know yet */ + key->rng = rng; - key->c_n = NULL; - key->c_e = NULL; - key->c_d = NULL; - key->c_p = NULL; - key->c_q = NULL; - key->c_dP = NULL; - key->c_dQ = NULL; - key->c_u = NULL; - - key->c_nSz = 0; - key->c_eSz = 0; - key->c_dSz = 0; - key->c_pSz = 0; - key->c_qSz = 0; - key->c_dP_Sz = 0; - key->c_dQ_Sz = 0; - key->c_uSz = 0; - return 0; } +#endif /* WC_RSA_BLINDING */ - -/* Free cavium RSA key */ -static int FreeCaviumRsaKey(RsaKey* key) +#ifdef WC_RSA_NONBLOCK +int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb) { if (key == NULL) return BAD_FUNC_ARG; - XFREE(key->c_n, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_e, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_d, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_p, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_q, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_dP, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_dQ, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_u, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - - return InitCaviumRsaKey(key, key->heap); /* reset pointers */ -} - - -static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 requestId; - word32 ret; - - if (key == NULL || in == NULL || out == NULL || outLen < (word32)key->c_nSz) - return -1; - - ret = CspPkcs1v15Enc(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_eSz, - (word16)inLen, key->c_n, key->c_e, (byte*)in, out, - &requestId, key->devId); - if (ret != 0) { - WOLFSSL_MSG("Cavium Enc BT2 failed"); - return -1; + if (nb) { + XMEMSET(nb, 0, sizeof(RsaNb)); } - return key->c_nSz; + + /* Allow nb == NULL to clear non-block mode */ + key->nb = nb; + + return 0; } - - -static INLINE void ato16(const byte* c, word16* u16) +#ifdef WC_RSA_NONBLOCK_TIME +int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs, word32 cpuMHz) { - *u16 = (c[0] << 8) | (c[1]); -} - - -static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 requestId; - word32 ret; - word16 outSz = (word16)outLen; - - if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz) - return -1; - - ret = CspPkcs1v15CrtDec(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_q, - key->c_dQ, key->c_p, key->c_dP, key->c_u, - (byte*)in, &outSz, out, &requestId, key->devId); - if (ret != 0) { - WOLFSSL_MSG("Cavium CRT Dec BT2 failed"); - return -1; + if (key == NULL || key->nb == NULL) { + return BAD_FUNC_ARG; } - ato16((const byte*)&outSz, &outSz); - return outSz; + /* calculate maximum number of instructions to block */ + key->nb->exptmod.maxBlockInst = cpuMHz * maxBlockUs; + + return 0; } +#endif /* WC_RSA_NONBLOCK_TIME */ +#endif /* WC_RSA_NONBLOCK */ - -static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 requestId; - word32 ret; - - if (key == NULL || in == NULL || out == NULL || inLen == 0 || outLen < - (word32)key->c_nSz) - return -1; - - ret = CspPkcs1v15CrtEnc(CAVIUM_BLOCKING, BT1, key->c_nSz, (word16)inLen, - key->c_q, key->c_dQ, key->c_p, key->c_dP, key->c_u, - (byte*)in, out, &requestId, key->devId); - if (ret != 0) { - WOLFSSL_MSG("Cavium CRT Enc BT1 failed"); - return -1; - } - return key->c_nSz; -} - - -static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 requestId; - word32 ret; - word16 outSz = (word16)outLen; - - if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz) - return -1; - - ret = CspPkcs1v15Dec(CAVIUM_BLOCKING, BT1, key->c_nSz, key->c_eSz, - key->c_n, key->c_e, (byte*)in, &outSz, out, - &requestId, key->devId); - if (ret != 0) { - WOLFSSL_MSG("Cavium Dec BT1 failed"); - return -1; - } - outSz = ntohs(outSz); - - return outSz; -} - - -#endif /* HAVE_CAVIUM */ - -#endif /* HAVE_FIPS */ #endif /* NO_RSA */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/selftest.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/selftest.c new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha.c index be8cf17af..5c80563e1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha.c @@ -1,8 +1,8 @@ /* sha.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,7 +16,7 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ @@ -28,431 +28,855 @@ #if !defined(NO_SHA) -#include -#include -#include +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) -#ifdef NO_INLINE - #include -#else - #include + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$j") + #pragma const_seg(".fipsB$j") + #endif +#endif + +#include +#include +#include + +#ifdef WOLF_CRYPTO_CB + #include #endif /* fips wrapper calls, user can call direct */ -#ifdef HAVE_FIPS - int wc_InitSha(Sha* sha) - { - return InitSha_fips(sha); - } +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) - - int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) - { - return ShaUpdate_fips(sha, data, len); - } - - - int wc_ShaFinal(Sha* sha, byte* out) - { - return ShaFinal_fips(sha,out); - } - - int wc_ShaHash(const byte* data, word32 sz, byte* out) + int wc_InitSha(wc_Sha* sha) { - return ShaHash(data, sz, out); + 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); } -#else /* else build without fips */ + 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(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, or for FIPS v2 */ + #if defined(WOLFSSL_TI_HASH) /* #include included by wc_port.c */ + #else -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitSha wc_InitSha_sw -#define wc_ShaUpdate wc_ShaUpdate_sw -#define wc_ShaFinal wc_ShaFinal_sw +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include #endif -#ifdef FREESCALE_MMCAU - #include "cau_api.h" - #define XTRANSFORM(S,B) cau_sha1_hash_n((B), 1, ((S))->digest) -#else - #define XTRANSFORM(S,B) Transform((S)) -#endif +/* Hardware Acceleration */ +#if defined(WOLFSSL_PIC32MZ_HASH) + #include -#ifdef STM32F2_HASH -/* - * STM32F2 hardware SHA1 support through the STM32F2 standard peripheral - * library. Documentation located in STM32F2xx Standard Peripheral Library - * document (See note in README). - */ -#include "stm32f2xx.h" -#include "stm32f2xx_hash.h" +#elif defined(STM32_HASH) -int wc_InitSha(Sha* sha) -{ - /* STM32F2 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); - sha->buffLen = 0; - sha->loLen = 0; - - /* initialize HASH peripheral */ - HASH_DeInit(); - - /* configure algo used, algo mode, datatype */ - HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); - HASH->CR |= (HASH_AlgoSelection_SHA1 | HASH_AlgoMode_HASH - | HASH_DataType_8b); - - /* reset HASH processor */ - HASH->CR |= HASH_CR_INIT; - - return 0; -} - -int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) -{ - word32 i = 0; - word32 fill = 0; - word32 diff = 0; - - /* if saved partial block is available */ - if (sha->buffLen) { - fill = 4 - sha->buffLen; - - /* 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); - - data += fill; - len -= fill; - sha->loLen += 4; - sha->buffLen = 0; - } else { - /* append partial to existing stored block */ - XMEMCPY((byte*)sha->buffer + sha->buffLen, data, len); - sha->buffLen += len; - return; - } - } - - /* write input block in the IN FIFO */ - for(i = 0; i < len; i += 4) + /* Supports CubeMX HAL or Standard Peripheral Library */ + int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) { - 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; + if (sha == NULL) { + return BAD_FUNC_ARG; } + + (void)devId; + (void)heap; + + wc_Stm32_Hash_Init(&sha->stmCtx); + + return 0; } - /* keep track of total data length thus far */ - sha->loLen += (len - sha->buffLen); - - return 0; -} - -int wc_ShaFinal(Sha* sha, byte* hash) -{ - __IO uint16_t nbvalidbitsdata = 0; - - /* finish reading any trailing bytes into FIFO */ - if (sha->buffLen) { - HASH_DataIn(*(uint32_t*)sha->buffer); - sha->loLen += sha->buffLen; - } - - /* calculate number of valid bits in last word of input data */ - nbvalidbitsdata = 8 * (sha->loLen % SHA_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 */ - sha->digest[0] = HASH->HR[0]; - sha->digest[1] = HASH->HR[1]; - sha->digest[2] = HASH->HR[2]; - sha->digest[3] = HASH->HR[3]; - sha->digest[4] = HASH->HR[4]; - - ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); - - XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); - - return wc_InitSha(sha); /* reset state */ -} - -#else /* wc_ software implementation */ - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) + int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) { - return a > b ? b : a; + int ret; + + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Update(&sha->stmCtx, HASH_AlgoSelection_SHA1, + data, len); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; } -#endif /* WOLFSSL_HAVE_MIN */ + int wc_ShaFinal(wc_Sha* sha, byte* hash) + { + int ret; + + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Final(&sha->stmCtx, HASH_AlgoSelection_SHA1, + hash, WC_SHA_DIGEST_SIZE); + wolfSSL_CryptHwMutexUnLock(); + } + + (void)wc_InitSha(sha); /* reset state */ + + return ret; + } -int wc_InitSha(Sha* sha) -{ -#ifdef FREESCALE_MMCAU - cau_sha1_initialize_output(sha->digest); +#elif defined(FREESCALE_LTC_SHA) + + #include "fsl_ltc.h" + int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + + (void)devId; + (void)heap; + + LTC_HASH_Init(LTC_BASE, &sha->ctx, kLTC_Sha1, NULL, 0); + return 0; + } + + int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) + { + LTC_HASH_Update(&sha->ctx, data, len); + return 0; + } + + int wc_ShaFinal(wc_Sha* sha, byte* hash) + { + uint32_t hashlen = WC_SHA_DIGEST_SIZE; + LTC_HASH_Finish(&sha->ctx, hash, &hashlen); + return wc_InitSha(sha); /* reset state */ + } + + +#elif defined(FREESCALE_MMCAU_SHA) + + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + #include "cau_api.h" + #else + #include "fsl_mmcau.h" + #endif + + #define USE_SHA_SOFTWARE_IMPL /* Only for API's, actual transform is here */ + + #define XTRANSFORM(S,B) Transform((S),(B)) + #define XTRANSFORM_LEN(S,B,L) Transform_Len((S),(B),(L)) + + #ifndef WC_HASH_DATA_ALIGNMENT + /* these hardware API's require 4 byte (word32) alignment */ + #define WC_HASH_DATA_ALIGNMENT 4 + #endif + + static int InitSha(wc_Sha* sha) + { + int ret = 0; + ret = wolfSSL_CryptHwMutexLock(); + 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; + sha->loLen = 0; + sha->hiLen = 0; + + return ret; + } + + static int Transform(wc_Sha* sha, const byte* data) + { + int ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha1_hash_n((byte*)data, 1, sha->digest); + #else + MMCAU_SHA1_HashN((byte*)data, 1, (uint32_t*)sha->digest); + #endif + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + + static int Transform_Len(wc_Sha* sha, const byte* data, word32 len) + { + int ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + #if defined(WC_HASH_DATA_ALIGNMENT) && WC_HASH_DATA_ALIGNMENT > 0 + if ((size_t)data % WC_HASH_DATA_ALIGNMENT) { + /* data pointer is NOT aligned, + * so copy and perform one block at a time */ + byte* local = (byte*)sha->buffer; + while (len >= WC_SHA_BLOCK_SIZE) { + XMEMCPY(local, data, WC_SHA_BLOCK_SIZE); + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha1_hash_n(local, 1, sha->digest); + #else + MMCAU_SHA1_HashN(local, 1, sha->digest); + #endif + data += WC_SHA_BLOCK_SIZE; + len -= WC_SHA_BLOCK_SIZE; + } + } + else + #endif + { + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha1_hash_n((byte*)data, len/WC_SHA_BLOCK_SIZE, sha->digest); + #else + MMCAU_SHA1_HashN((byte*)data, len/WC_SHA_BLOCK_SIZE, + (uint32_t*)sha->digest); + #endif + } + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) + /* wolfcrypt/src/port/caam/caam_sha.c */ + +#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + + #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h" + + #define USE_SHA_SOFTWARE_IMPL + + static int InitSha(wc_Sha* sha) + { + int ret = 0; + + sha->digest[0] = 0x67452301L; + sha->digest[1] = 0xEFCDAB89L; + sha->digest[2] = 0x98BADCFEL; + sha->digest[3] = 0x10325476L; + sha->digest[4] = 0xC3D2E1F0L; + + sha->buffLen = 0; + sha->loLen = 0; + sha->hiLen = 0; + + /* always start firstblock = 1 when using hw engine */ + sha->ctx.isfirstblock = 1; + sha->ctx.sha_type = SHA1; + if(sha->ctx.mode == ESP32_SHA_HW){ + /* release hw engine */ + esp_sha_hw_unlock(); + } + /* always set mode as INIT + * whether using HW or SW is determined at first call of update() + */ + sha->ctx.mode = ESP32_SHA_INIT; + + return ret; + } + +#elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH) + + /* implemented in wolfcrypt/src/port/Renesas/renesas_tsip_sha.c */ + #else - sha->digest[0] = 0x67452301L; - sha->digest[1] = 0xEFCDAB89L; - sha->digest[2] = 0x98BADCFEL; - sha->digest[3] = 0x10325476L; - sha->digest[4] = 0xC3D2E1F0L; -#endif + /* Software implementation */ + #define USE_SHA_SOFTWARE_IMPL - sha->buffLen = 0; - sha->loLen = 0; - sha->hiLen = 0; + static int InitSha(wc_Sha* sha) + { + int ret = 0; - return 0; -} + sha->digest[0] = 0x67452301L; + sha->digest[1] = 0xEFCDAB89L; + sha->digest[2] = 0x98BADCFEL; + sha->digest[3] = 0x10325476L; + sha->digest[4] = 0xC3D2E1F0L; -#ifndef FREESCALE_MMCAU + sha->buffLen = 0; + sha->loLen = 0; + sha->hiLen = 0; + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + sha->flags = 0; + #endif -#define blk0(i) (W[i] = sha->buffer[i]) -#define blk1(i) (W[(i)&15] = \ -rotlFixed(W[((i)+13)&15]^W[((i)+8)&15]^W[((i)+2)&15]^W[(i)&15],1)) - -#define f1(x,y,z) ((z)^((x) &((y)^(z)))) -#define f2(x,y,z) ((x)^(y)^(z)) -#define f3(x,y,z) (((x)&(y))|((z)&((x)|(y)))) -#define f4(x,y,z) ((x)^(y)^(z)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk0((i)) + 0x5A827999+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); -#define R1(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk1((i)) + 0x5A827999+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); -#define R2(v,w,x,y,z,i) (z)+= f2((w),(x),(y)) + blk1((i)) + 0x6ED9EBA1+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); -#define R3(v,w,x,y,z,i) (z)+= f3((w),(x),(y)) + blk1((i)) + 0x8F1BBCDC+ \ -rotlFixed((v),5); (w) = rotlFixed((w),30); -#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 Transform(Sha* sha) -{ - word32 W[SHA_BLOCK_SIZE / sizeof(word32)]; - - /* Copy context->state[] to working vars */ - word32 a = sha->digest[0]; - word32 b = sha->digest[1]; - word32 c = sha->digest[2]; - word32 d = sha->digest[3]; - word32 e = sha->digest[4]; - -#ifdef USE_SLOW_SHA - word32 t, i; - - for (i = 0; i < 16; i++) { - R0(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; + return ret; } +#endif /* End Hardware Acceleration */ - for (; i < 20; i++) { - R1(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } +/* Software implementation */ +#ifdef USE_SHA_SOFTWARE_IMPL - for (; i < 40; i++) { - R2(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 60; i++) { - R3(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } - - for (; i < 80; i++) { - R4(a, b, c, d, e, i); - t = e; e = d; d = c; c = b; b = a; a = t; - } -#else - /* 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); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); -#endif - - /* Add the working vars back into digest state[] */ - sha->digest[0] += a; - sha->digest[1] += b; - sha->digest[2] += c; - sha->digest[3] += d; - sha->digest[4] += e; -} - -#endif /* FREESCALE_MMCAU */ - - -static INLINE void AddLength(Sha* sha, word32 len) +static WC_INLINE void AddLength(wc_Sha* sha, word32 len) { word32 tmp = sha->loLen; - if ( (sha->loLen += len) < tmp) + if ((sha->loLen += len) < tmp) sha->hiLen++; /* carry low to high */ } +/* Check if custom wc_Sha transform is used */ +#ifndef XTRANSFORM + #define XTRANSFORM(S,B) Transform((S),(B)) -int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) + #define blk0(i) (W[i] = *((word32*)&data[i*sizeof(word32)])) + #define blk1(i) (W[(i)&15] = \ + rotlFixed(W[((i)+13)&15]^W[((i)+8)&15]^W[((i)+2)&15]^W[(i)&15],1)) + + #define f1(x,y,z) ((z)^((x) &((y)^(z)))) + #define f2(x,y,z) ((x)^(y)^(z)) + #define f3(x,y,z) (((x)&(y))|((z)&((x)|(y)))) + #define f4(x,y,z) ((x)^(y)^(z)) + + #ifdef WOLFSSL_NUCLEUS_1_2 + /* nucleus.h also defines R1-R4 */ + #undef R1 + #undef R2 + #undef R3 + #undef R4 + #endif + + /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ + #define R0(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk0((i)) + 0x5A827999+ \ + rotlFixed((v),5); (w) = rotlFixed((w),30); + #define R1(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk1((i)) + 0x5A827999+ \ + rotlFixed((v),5); (w) = rotlFixed((w),30); + #define R2(v,w,x,y,z,i) (z)+= f2((w),(x),(y)) + blk1((i)) + 0x6ED9EBA1+ \ + rotlFixed((v),5); (w) = rotlFixed((w),30); + #define R3(v,w,x,y,z,i) (z)+= f3((w),(x),(y)) + blk1((i)) + 0x8F1BBCDC+ \ + rotlFixed((v),5); (w) = rotlFixed((w),30); + #define R4(v,w,x,y,z,i) (z)+= f4((w),(x),(y)) + blk1((i)) + 0xCA62C1D6+ \ + rotlFixed((v),5); (w) = rotlFixed((w),30); + + static int Transform(wc_Sha* sha, const byte* data) + { + word32 W[WC_SHA_BLOCK_SIZE / sizeof(word32)]; + + /* Copy context->state[] to working vars */ + word32 a = sha->digest[0]; + word32 b = sha->digest[1]; + word32 c = sha->digest[2]; + word32 d = sha->digest[3]; + word32 e = sha->digest[4]; + + #ifdef USE_SLOW_SHA + word32 t, i; + + for (i = 0; i < 16; i++) { + R0(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 20; i++) { + R1(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 40; i++) { + R2(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 60; i++) { + R3(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 80; i++) { + R4(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + #else + /* 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); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + #endif + + /* Add the working vars back into digest state[] */ + sha->digest[0] += a; + sha->digest[1] += b; + sha->digest[2] += c; + sha->digest[3] += d; + sha->digest[4] += e; + + (void)data; /* Not used */ + + return 0; + } +#endif /* !USE_CUSTOM_SHA_TRANSFORM */ + + +int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) { - /* do block size increments */ - byte* local = (byte*)sha->buffer; + int ret = 0; - while (len) { - word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen); - XMEMCPY(&local[sha->buffLen], data, add); + if (sha == NULL) + return BAD_FUNC_ARG; - sha->buffLen += add; - data += add; - len -= add; - - if (sha->buffLen == SHA_BLOCK_SIZE) { -#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); + sha->heap = heap; +#ifdef WOLF_CRYPTO_CB + sha->devId = devId; #endif - XTRANSFORM(sha, local); - AddLength(sha, SHA_BLOCK_SIZE); + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha->ctx.mode = ESP32_SHA_INIT; + sha->ctx.isfirstblock = 1; +#endif + 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; +} + +/* do block size increments/updates */ +int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) +{ + int ret = 0; + word32 blocksLen; + byte* local; + + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (sha->devId != INVALID_DEVID) { + ret = wc_CryptoCb_ShaHash(sha, data, len, NULL); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + ret = 0; /* reset ret */ + /* fall-through when unavailable */ + } +#endif +#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; + + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + + /* add length for final */ + AddLength(sha, len); + + local = (byte*)sha->buffer; + + /* process any remainder from previous operation */ + if (sha->buffLen > 0) { + blocksLen = min(len, WC_SHA_BLOCK_SIZE - sha->buffLen); + XMEMCPY(&local[sha->buffLen], data, blocksLen); + + sha->buffLen += blocksLen; + data += blocksLen; + len -= blocksLen; + + if (sha->buffLen == WC_SHA_BLOCK_SIZE) { + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); + #endif + + #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if (sha->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha->ctx); + } + if (sha->ctx.mode == ESP32_SHA_SW) { + ret = XTRANSFORM(sha, (const byte*)local); + } else { + esp_sha_process(sha, (const byte*)local); + } + #else + ret = XTRANSFORM(sha, (const byte*)local); + #endif + if (ret != 0) + return ret; + sha->buffLen = 0; } } + /* process blocks */ +#ifdef XTRANSFORM_LEN + /* get number of blocks */ + /* 64-1 = 0x3F (~ Inverted = 0xFFFFFFC0) */ + /* len (masked by 0xFFFFFFC0) returns block aligned length */ + blocksLen = len & ~(WC_SHA_BLOCK_SIZE-1); + if (blocksLen > 0) { + /* Byte reversal performed in function if required. */ + XTRANSFORM_LEN(sha, data, blocksLen); + data += blocksLen; + len -= blocksLen; + } +#else + while (len >= WC_SHA_BLOCK_SIZE) { + word32* local32 = sha->buffer; + /* optimization to avoid memcpy if data pointer is properly aligned */ + /* Little Endian requires byte swap, so can't use data directly */ + #if defined(WC_HASH_DATA_ALIGNMENT) && !defined(LITTLE_ENDIAN_ORDER) + if (((size_t)data % WC_HASH_DATA_ALIGNMENT) == 0) { + local32 = (word32*)data; + } + else + #endif + { + XMEMCPY(local32, data, WC_SHA_BLOCK_SIZE); + } + + data += WC_SHA_BLOCK_SIZE; + len -= WC_SHA_BLOCK_SIZE; + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(local32, local32, WC_SHA_BLOCK_SIZE); + #endif + + #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if (sha->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha->ctx); + } + if (sha->ctx.mode == ESP32_SHA_SW){ + ret = XTRANSFORM(sha, (const byte*)local32); + } else { + esp_sha_process(sha, (const byte*)local32); + } + #else + ret = XTRANSFORM(sha, (const byte*)local32); + #endif + } +#endif /* XTRANSFORM_LEN */ + + /* save remainder */ + if (len > 0) { + XMEMCPY(local, data, len); + sha->buffLen = len; + } + + return ret; +} + +int wc_ShaFinalRaw(wc_Sha* sha, byte* hash) +{ +#ifdef LITTLE_ENDIAN_ORDER + word32 digest[WC_SHA_DIGEST_SIZE / sizeof(word32)]; +#endif + + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords((word32*)digest, (word32*)sha->digest, WC_SHA_DIGEST_SIZE); + XMEMCPY(hash, digest, WC_SHA_DIGEST_SIZE); +#else + XMEMCPY(hash, sha->digest, WC_SHA_DIGEST_SIZE); +#endif + return 0; } - -int wc_ShaFinal(Sha* sha, byte* hash) +int wc_ShaFinal(wc_Sha* sha, byte* hash) { - byte* local = (byte*)sha->buffer; + int ret; + byte* local; - AddLength(sha, sha->buffLen); /* before adding pads */ + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + local = (byte*)sha->buffer; + +#ifdef WOLF_CRYPTO_CB + if (sha->devId != INVALID_DEVID) { + ret = wc_CryptoCb_ShaHash(sha, NULL, 0, hash); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + ret = 0; /* reset ret */ + /* fall-through when unavailable */ + } +#endif +#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 */ 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, WC_SHA_BLOCK_SIZE); + #endif + + #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if (sha->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha->ctx); + } + if (sha->ctx.mode == ESP32_SHA_SW) { + ret = XTRANSFORM(sha, (const byte*)local); + } else { + ret = esp_sha_process(sha, (const byte*)local); + } + #else + ret = XTRANSFORM(sha, (const byte*)local); + #endif + if (ret != 0) + return ret; -#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - ByteReverseWords(sha->buffer, sha->buffer, SHA_BLOCK_SIZE); -#endif - 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) - 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 + /* ! 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 - XTRANSFORM(sha, local); -#ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); -#endif - XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); - - return wc_InitSha(sha); /* reset state */ -} - -#endif /* STM32F2_HASH */ - - -int wc_ShaHash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha* sha; +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if (sha->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha->ctx); + } + if (sha->ctx.mode == ESP32_SHA_SW) { + ret = XTRANSFORM(sha, (const byte*)local); + } else { + ret = esp_sha_digest_process(sha, 1); + } #else - Sha sha[1]; + ret = XTRANSFORM(sha, (const byte*)local); #endif -#ifdef WOLFSSL_SMALL_STACK - sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha == NULL) - return MEMORY_E; +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(sha->digest, sha->digest, WC_SHA_DIGEST_SIZE); #endif - if ((ret = wc_InitSha(sha)) != 0) { - WOLFSSL_MSG("wc_InitSha failed"); - } - else { - wc_ShaUpdate(sha, data, len); - wc_ShaFinal(sha, hash); - } + XMEMCPY(hash, sha->digest, WC_SHA_DIGEST_SIZE); -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + (void)InitSha(sha); /* reset state */ return ret; - } -#endif /* HAVE_FIPS */ -#endif /* WOLFSSL_TI_HASH */ -#endif /* NO_SHA */ +#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 */ + +#ifdef WOLFSSL_PIC32MZ_HASH + wc_ShaPic32Free(sha); +#endif +#if (defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)) + if (sha->msg != NULL) { + XFREE(sha->msg, sha->heap, DYNAMIC_TYPE_TMP_BUFFER); + sha->msg = NULL; + } +#endif +} + +#endif /* !WOLFSSL_TI_HASH */ +#endif /* HAVE_FIPS */ + +#ifndef WOLFSSL_TI_HASH +#if !defined(WOLFSSL_RENESAS_TSIP_CRYPT) || \ + defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH) +int wc_ShaGetHash(wc_Sha* sha, byte* hash) +{ + int ret; + wc_Sha tmpSha; + + if (sha == NULL || hash == NULL) + return BAD_FUNC_ARG; + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if(sha->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha->ctx); + } + if(sha->ctx.mode != ESP32_SHA_SW) + esp_sha_digest_process(sha, 0); +#endif + + ret = wc_ShaCopy(sha, &tmpSha); + if (ret == 0) { + ret = wc_ShaFinal(&tmpSha, hash); +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha->ctx.mode = ESP32_SHA_SW; +#endif + + + } + 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 +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + dst->ctx.mode = src->ctx.mode; + dst->ctx.isfirstblock = src->ctx.isfirstblock; + dst->ctx.sha_type = src->ctx.sha_type; +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + return ret; +} +#endif /* defined(WOLFSSL_RENESAS_TSIP_CRYPT) ... */ +#endif /* !WOLFSSL_TI_HASH */ + + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_ShaSetFlags(wc_Sha* sha, word32 flags) +{ + if (sha) { + sha->flags = flags; + } + return 0; +} +int wc_ShaGetFlags(wc_Sha* sha, word32* flags) +{ + if (sha && flags) { + *flags = sha->flags; + } + return 0; +} +#endif + +#endif /* !NO_SHA */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha256.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha256.c index f9f02b003..eb0911b01 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha256.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha256.c @@ -1,8 +1,8 @@ /* sha256.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,299 +16,604 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* code submitted by raphael.huck@efixo.com */ - #ifdef HAVE_CONFIG_H #include #endif #include -#include -#if !defined(NO_SHA256) -#ifdef HAVE_FIPS - -int wc_InitSha256(Sha256* sha) -{ - return InitSha256_fips(sha); -} - - -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); -} - - -int wc_Sha256Hash(const byte* data, word32 len, byte* out) -{ - return Sha256Hash(data, len, out); -} - -#else /* else build without fips */ - -#if !defined(NO_SHA256) && 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 - -#if defined(DEBUG_XMM) -#include "stdio.h" -#endif - -#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 +/* + * SHA256 Build Options: + * USE_SLOW_SHA256: Reduces code size by not partially unrolling + (~2KB smaller and ~25% slower) (default OFF) + * WOLFSSL_SHA256_BY_SPEC: Uses the Ch/Maj based on SHA256 specification + (default ON) + * WOLFSSL_SHA256_ALT_CH_MAJ: Alternate Ch/Maj that is easier for compilers to + optimize and recognize as SHA256 (default OFF) + * SHA256_MANY_REGISTERS: A SHA256 version that keeps all data in registers + and partial unrolled (default OFF) */ -#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)); +/* Default SHA256 to use Ch/Maj based on specification */ +#if !defined(WOLFSSL_SHA256_BY_SPEC) && !defined(WOLFSSL_SHA256_ALT_CH_MAJ) + #define WOLFSSL_SHA256_BY_SPEC +#endif - #define XASM_LINK(f) asm(f) -#else - #include - #define cpuid(a,b) __cpuid((int*)a,b) +#if !defined(NO_SHA256) && !defined(WOLFSSL_ARMASM) - #define XASM_LINK(f) +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) -#endif /* _MSC_VER */ + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS -#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 */ + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$d") + #pragma const_seg(".fipsB$d") + #endif +#endif -#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) +#include +#include +#include +#include -static word32 cpuid_check = 0 ; -static word32 cpuid_flags = 0 ; +#ifdef WOLF_CRYPTO_CB + #include +#endif -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(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) ; +/* fips wrapper calls, user can call direct */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + + int wc_InitSha256(wc_Sha256* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha256_fips(sha); } - 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 ; + 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); } - return 1 ; -} + 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; + } + + 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, or for FIPS v2 */ -/* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha512 */ -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 ; -} - +#if defined(WOLFSSL_TI_HASH) + /* #include included by wc_port.c */ +#elif defined(WOLFSSL_CRYPTOCELL) + /* wc_port.c includes wolfcrypt/src/port/arm/cryptoCellHash.c */ #else - #if defined(FREESCALE_MMCAU) - #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 #else + #define WOLFSSL_MISC_INCLUDED #include #endif -#ifdef FREESCALE_MMCAU - #include "cau_api.h" +#ifdef WOLFSSL_DEVCRYPTO_HASH + #include #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; + +#if defined(USE_INTEL_SPEEDUP) + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #undef NO_AVX2_SUPPORT + #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 + + +#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH_SHA2) && \ + (!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH)) && \ + !defined(WOLFSSL_AFALG_HASH) && !defined(WOLFSSL_DEVCRYPTO_HASH) && \ + (!defined(WOLFSSL_ESP32WROOM32_CRYPT) || defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)) && \ + (!defined(WOLFSSL_RENESAS_TSIP_CRYPT) || defined(NO_WOLFSSL_RENESAS_TSIP_HASH)) + +static int InitSha256(wc_Sha256* sha256) +{ + int ret = 0; + + 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(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + sha256->flags = 0; +#endif + + return ret; +} +#endif + + +/* Hardware Acceleration */ +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + + /* in case intel instructions aren't available, plus we need the K[] global */ + #define NEED_SOFT_SHA256 + + /***** + Intel AVX1/AVX2 Macro Control Structure + + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 + + #define HAVE_INTEL_RORX + + + int InitSha256(wc_Sha256* sha256) { + Save/Recover XMM, YMM + ... } -#endif /* WOLFSSL_HAVE_MIN */ + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + Transform_Sha256(); Function prototype + #else + Transform_Sha256() { } + 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 instruction + #else + #define RND + #endif + #endif -int wc_InitSha256(Sha256* sha256) -{ - #ifdef FREESCALE_MMCAU + #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 granular 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, const byte* data); + +#ifdef __cplusplus + extern "C" { +#endif + + #if defined(HAVE_INTEL_AVX1) + extern int Transform_Sha256_AVX1(wc_Sha256 *sha256, const byte* data); + extern int Transform_Sha256_AVX1_Len(wc_Sha256* sha256, + const byte* data, word32 len); + #endif + #if defined(HAVE_INTEL_AVX2) + extern int Transform_Sha256_AVX2(wc_Sha256 *sha256, const byte* data); + extern int Transform_Sha256_AVX2_Len(wc_Sha256* sha256, + const byte* data, word32 len); + #ifdef HAVE_INTEL_RORX + extern int Transform_Sha256_AVX1_RORX(wc_Sha256 *sha256, const byte* data); + extern int Transform_Sha256_AVX1_RORX_Len(wc_Sha256* sha256, + const byte* data, word32 len); + extern int Transform_Sha256_AVX2_RORX(wc_Sha256 *sha256, const byte* data); + extern int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256, + const byte* data, word32 len); + #endif /* HAVE_INTEL_RORX */ + #endif /* HAVE_INTEL_AVX2 */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + static int (*Transform_Sha256_p)(wc_Sha256* sha256, const byte* data); + /* = _Transform_Sha256 */ + static int (*Transform_Sha256_Len_p)(wc_Sha256* sha256, const byte* data, + word32 len); + /* = NULL */ + static int transform_check = 0; + static word32 intel_flags; + + #define XTRANSFORM(S, D) (*Transform_Sha256_p)((S),(D)) + #define XTRANSFORM_LEN(S, D, L) (*Transform_Sha256_Len_p)((S),(D),(L)) + + static void Sha256_SetTransform(void) + { + + if (transform_check) + return; + + intel_flags = cpuid_get_flags(); + + #ifdef HAVE_INTEL_AVX2 + if (1 && 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; + #ifdef WOLF_CRYPTO_CB + sha256->devId = devId; + #endif + + ret = InitSha256(sha256); + if (ret != 0) + return ret; + + /* 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; + } + +#elif defined(FREESCALE_LTC_SHA) + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + (void)heap; + (void)devId; + + 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, D) Transform_Sha256((S),(D)) + #define XTRANSFORM_LEN(S, D, L) Transform_Sha256_Len((S),(D),(L)) + + #ifndef WC_HASH_DATA_ALIGNMENT + /* these hardware API's require 4 byte (word32) alignment */ + #define WC_HASH_DATA_ALIGNMENT 4 + #endif + + 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; + #ifdef WOLFSSL_SMALL_STACK_CACHE + sha256->W = NULL; + #endif + + return ret; + } + + static int Transform_Sha256(wc_Sha256* sha256, const byte* data) + { + int ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha256_hash_n((byte*)data, 1, sha256->digest); + #else + MMCAU_SHA256_HashN((byte*)data, 1, sha256->digest); + #endif + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + + static int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, + word32 len) + { + int ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + #if defined(WC_HASH_DATA_ALIGNMENT) && WC_HASH_DATA_ALIGNMENT > 0 + if ((size_t)data % WC_HASH_DATA_ALIGNMENT) { + /* data pointer is NOT aligned, + * so copy and perform one block at a time */ + byte* local = (byte*)sha256->buffer; + while (len >= WC_SHA256_BLOCK_SIZE) { + XMEMCPY(local, data, WC_SHA256_BLOCK_SIZE); + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha256_hash_n(local, 1, sha256->digest); + #else + MMCAU_SHA256_HashN(local, 1, sha256->digest); + #endif + data += WC_SHA256_BLOCK_SIZE; + len -= WC_SHA256_BLOCK_SIZE; + } + } + else + #endif + { + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha256_hash_n((byte*)data, len/WC_SHA256_BLOCK_SIZE, + sha256->digest); + #else + MMCAU_SHA256_HashN((byte*)data, len/WC_SHA256_BLOCK_SIZE, + sha256->digest); + #endif + } + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + +#elif defined(WOLFSSL_PIC32MZ_HASH) + #include + +#elif defined(STM32_HASH_SHA2) + + /* Supports CubeMX HAL or Standard Peripheral Library */ + + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + if (sha256 == NULL) + return BAD_FUNC_ARG; + + (void)devId; + (void)heap; + + wc_Stm32_Hash_Init(&sha256->stmCtx); + return 0; + } + + int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) + { + int ret = 0; + + if (sha256 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Update(&sha256->stmCtx, + HASH_AlgoSelection_SHA256, data, len); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + + int wc_Sha256Final(wc_Sha256* sha256, byte* hash) + { + int ret = 0; + + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Final(&sha256->stmCtx, + HASH_AlgoSelection_SHA256, hash, WC_SHA256_DIGEST_SIZE); + wolfSSL_CryptHwMutexUnLock(); + } + + (void)wc_InitSha256(sha256); /* reset state */ + + return ret; + } + +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) + /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */ + +#elif defined(WOLFSSL_AFALG_HASH) + /* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */ + +#elif defined(WOLFSSL_DEVCRYPTO_HASH) + /* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */ + +#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_HASH) + #include "hal_data.h" + + #ifndef WOLFSSL_SCE_SHA256_HANDLE + #define WOLFSSL_SCE_SHA256_HANDLE g_sce_hash_0 + #endif + + #define WC_SHA256_DIGEST_WORD_SIZE 16 + #define XTRANSFORM(S, D) wc_Sha256SCE_XTRANSFORM((S), (D)) + static int wc_Sha256SCE_XTRANSFORM(wc_Sha256* sha256, const byte* data) + { + if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == + CRYPTO_WORD_ENDIAN_LITTLE) + { + ByteReverseWords((word32*)data, (word32*)data, + WC_SHA256_BLOCK_SIZE); + ByteReverseWords(sha256->digest, sha256->digest, + WC_SHA256_DIGEST_SIZE); + } + + if (WOLFSSL_SCE_SHA256_HANDLE.p_api->hashUpdate( + WOLFSSL_SCE_SHA256_HANDLE.p_ctrl, (word32*)data, + WC_SHA256_DIGEST_WORD_SIZE, sha256->digest) != SSP_SUCCESS){ + WOLFSSL_MSG("Unexpected hardware return value"); + return WC_HW_E; + } + + if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == + CRYPTO_WORD_ENDIAN_LITTLE) + { + ByteReverseWords((word32*)data, (word32*)data, + WC_SHA256_BLOCK_SIZE); + ByteReverseWords(sha256->digest, sha256->digest, + WC_SHA256_DIGEST_SIZE); + } + + return 0; + } + + + 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; + + (void)devId; + + return ret; + } + +#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + + #define NEED_SOFT_SHA256 + + static int InitSha256(wc_Sha256* sha256) + { + int ret = 0; + + 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; @@ -317,1450 +622,1023 @@ int wc_InitSha256(Sha256* sha256) sha256->digest[5] = 0x9B05688CL; sha256->digest[6] = 0x1F83D9ABL; sha256->digest[7] = 0x5BE0CD19L; + + sha256->buffLen = 0; + sha256->loLen = 0; + sha256->hiLen = 0; + + /* always start firstblock = 1 when using hw engine */ + sha256->ctx.isfirstblock = 1; + sha256->ctx.sha_type = SHA2_256; + if(sha256->ctx.mode == ESP32_SHA_HW) { + /* release hw */ + esp_sha_hw_unlock(); + } + /* always set mode as INIT + * whether using HW or SW is determined at first call of update() + */ + sha256->ctx.mode = ESP32_SHA_INIT; + + return ret; + } + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + int ret = 0; + + if (sha256 == NULL) + return BAD_FUNC_ARG; + + XMEMSET(sha256, 0, sizeof(wc_Sha256)); + sha256->ctx.mode = ESP32_SHA_INIT; + sha256->ctx.isfirstblock = 1; + (void)devId; + + ret = InitSha256(sha256); + + return ret; + } + +#elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH) + + /* implemented in wolfcrypt/src/port/Renesas/renesas_tsip_sha.c */ + +#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; + #ifdef WOLF_CRYPTO_CB + sha256->devId = devId; + sha256->devCtx = NULL; #endif - 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 0; -} - - -#if !defined(FREESCALE_MMCAU) -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) - -static int Transform(Sha256* sha256, byte* buf) -{ - cau_sha256_hash_n(buf, 1, sha256->digest); - - return 0; -} - -#endif /* FREESCALE_MMCAU */ - -#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 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; - -#if !defined(FREESCALE_MMCAU) -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); - } - - /* 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 /* #if !defined(FREESCALE_MMCAU) */ - -static INLINE void AddLength(Sha256* sha256, word32 len) -{ - word32 tmp = sha256->loLen; - if ( (sha256->loLen += len) < tmp) - sha256->hiLen++; /* carry low to high */ -} - -int wc_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) - #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_Sha256Final(Sha256* sha256, byte* hash) -{ - 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) - #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); + ret = InitSha256(sha256); if (ret != 0) return ret; - sha256->buffLen = 0; - } - 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; - - /* store lengths */ - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU) - #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); + #ifdef WOLFSSL_SMALL_STACK_CACHE + sha256->W = NULL; #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)); - #if defined(FREESCALE_MMCAU) || defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + #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 + }; + +/* Both versions of Ch and Maj are logically the same, but with the second set + the compilers can recognize them better for optimization */ +#ifdef WOLFSSL_SHA256_BY_SPEC + /* SHA256 math based on specification */ + #define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + #define Maj(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y))) +#else + /* SHA256 math reworked for easier compiler optimization */ + #define Ch(x,y,z) ((((y) ^ (z)) & (x)) ^ (z)) + #define Maj(x,y,z) ((((x) ^ (y)) & ((y) ^ (z))) ^ (y)) +#endif + #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] + + #ifndef XTRANSFORM + #define XTRANSFORM(S, D) Transform_Sha256((S),(D)) + #endif + +#ifndef SHA256_MANY_REGISTERS + #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 + + static int Transform_Sha256(wc_Sha256* sha256, const byte* data) + { + word32 S[8], t0, t1; + int i; + + #ifdef WOLFSSL_SMALL_STACK_CACHE + word32* W = sha256->W; + if (W == NULL) { + W = (word32*)XMALLOC(sizeof(word32) * WC_SHA256_BLOCK_SIZE, NULL, + DYNAMIC_TYPE_DIGEST); + if (W == NULL) + return MEMORY_E; + sha256->W = W; + } + #elif defined(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] = *((word32*)&data[i*sizeof(word32)]); + + 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]; + } + + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE) + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return 0; + } +#else + /* SHA256 version that keeps all data in registers */ + #define SCHED1(j) (W[j] = *((word32*)&data[j*sizeof(word32)])) + #define SCHED(j) ( \ + W[ j & 15] += \ + Gamma1(W[(j-2) & 15])+ \ + W[(j-7) & 15] + \ + Gamma0(W[(j-15) & 15]) \ + ) + + #define RND1(j) \ + t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+j] + SCHED1(j); \ + t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \ + d(j) += t0; \ + h(j) = t0 + t1 + #define RNDN(j) \ + t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+j] + SCHED(j); \ + t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \ + d(j) += t0; \ + h(j) = t0 + t1 + + static int Transform_Sha256(wc_Sha256* sha256, const byte* data) + { + word32 S[8], t0, t1; + int i; + word32 W[WC_SHA256_BLOCK_SIZE/sizeof(word32)]; + + /* Copy digest to working vars */ + S[0] = sha256->digest[0]; + S[1] = sha256->digest[1]; + S[2] = sha256->digest[2]; + S[3] = sha256->digest[3]; + S[4] = sha256->digest[4]; + S[5] = sha256->digest[5]; + S[6] = sha256->digest[6]; + S[7] = sha256->digest[7]; + + i = 0; + RND1( 0); RND1( 1); RND1( 2); RND1( 3); + RND1( 4); RND1( 5); RND1( 6); RND1( 7); + RND1( 8); RND1( 9); RND1(10); RND1(11); + RND1(12); RND1(13); RND1(14); RND1(15); + /* 64 operations, partially loop unrolled */ + for (i = 16; i < 64; i += 16) { + RNDN( 0); RNDN( 1); RNDN( 2); RNDN( 3); + RNDN( 4); RNDN( 5); RNDN( 6); RNDN( 7); + RNDN( 8); RNDN( 9); RNDN(10); RNDN(11); + RNDN(12); RNDN(13); RNDN(14); RNDN(15); + } + + /* Add the working vars back into digest */ + sha256->digest[0] += S[0]; + sha256->digest[1] += S[1]; + sha256->digest[2] += S[2]; + sha256->digest[3] += S[3]; + sha256->digest[4] += S[4]; + sha256->digest[5] += S[5]; + sha256->digest[6] += S[6]; + sha256->digest[7] += S[7]; + + return 0; + } +#endif /* SHA256_MANY_REGISTERS */ +#endif +/* End wc_ software implementation */ + + +#ifdef XTRANSFORM + + static WC_INLINE void AddLength(wc_Sha256* sha256, word32 len) + { + word32 tmp = sha256->loLen; + if ((sha256->loLen += len) < tmp) { + sha256->hiLen++; /* carry low to high */ + } + } + + /* do block size increments/updates */ + static WC_INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) + { + int ret = 0; + word32 blocksLen; + byte* local; + + if (sha256 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + + /* check that internal buffLen is valid */ + if (sha256->buffLen >= WC_SHA256_BLOCK_SIZE) { + return BUFFER_E; + } + + /* add length for final */ + AddLength(sha256, len); + + local = (byte*)sha256->buffer; + + /* process any remainder from previous operation */ + if (sha256->buffLen > 0) { + blocksLen = min(len, WC_SHA256_BLOCK_SIZE - sha256->buffLen); + XMEMCPY(&local[sha256->buffLen], data, blocksLen); + + sha256->buffLen += blocksLen; + data += blocksLen; + len -= blocksLen; + + 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 + + #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if (sha256->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha256->ctx); + } + if (sha256->ctx.mode == ESP32_SHA_SW){ + ret = XTRANSFORM(sha256, (const byte*)local); + } else { + esp_sha256_process(sha256, (const byte*)local); + } + #else + ret = XTRANSFORM(sha256, (const byte*)local); + #endif + + if (ret == 0) + sha256->buffLen = 0; + else + len = 0; /* error */ + } + } + + /* process blocks */ + #ifdef XTRANSFORM_LEN + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (Transform_Sha256_Len_p != NULL) + #endif + { + /* get number of blocks */ + /* 64-1 = 0x3F (~ Inverted = 0xFFFFFFC0) */ + /* len (masked by 0xFFFFFFC0) returns block aligned length */ + blocksLen = len & ~(WC_SHA256_BLOCK_SIZE-1); + if (blocksLen > 0) { + /* Byte reversal and alignment handled in function if required */ + XTRANSFORM_LEN(sha256, data, blocksLen); + data += blocksLen; + len -= blocksLen; + } + } + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + else + #endif + #endif /* XTRANSFORM_LEN */ + #if !defined(XTRANSFORM_LEN) || defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + { + while (len >= WC_SHA256_BLOCK_SIZE) { + word32* local32 = sha256->buffer; + /* optimization to avoid memcpy if data pointer is properly aligned */ + /* Intel transform function requires use of sha256->buffer */ + /* Little Endian requires byte swap, so can't use data directly */ + #if defined(WC_HASH_DATA_ALIGNMENT) && !defined(LITTLE_ENDIAN_ORDER) && \ + !defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2) + if (((size_t)data % WC_HASH_DATA_ALIGNMENT) == 0) { + local32 = (word32*)data; + } + else + #endif + { + XMEMCPY(local32, data, WC_SHA256_BLOCK_SIZE); + } + + data += WC_SHA256_BLOCK_SIZE; + len -= 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(local32, local32, WC_SHA256_BLOCK_SIZE); + } + #endif + + #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if (sha256->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha256->ctx); + } + if (sha256->ctx.mode == ESP32_SHA_SW){ + ret = XTRANSFORM(sha256, (const byte*)local32); + } else { + esp_sha256_process(sha256, (const byte*)local32); + } + #else + ret = XTRANSFORM(sha256, (const byte*)local32); + #endif + + if (ret != 0) + break; + } + } + #endif + + /* save remainder */ + if (len > 0) { + XMEMCPY(local, data, len); + sha256->buffLen = len; + } + + return ret; + } + + int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) + { + if (sha256 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + + #ifdef WOLF_CRYPTO_CB + if (sha256->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_Sha256Hash(sha256, data, len, NULL); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } + #endif + #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 */ + + return Sha256Update(sha256, data, len); + } + + static WC_INLINE int Sha256Final(wc_Sha256* sha256) + { + + int ret; + byte* local; + + if (sha256 == NULL) { + return BAD_FUNC_ARG; + } + + local = (byte*)sha256->buffer; + 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 + + #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if (sha256->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha256->ctx); + } + if (sha256->ctx.mode == ESP32_SHA_SW) { + ret = XTRANSFORM(sha256, (const byte*)local); + } else { + ret = esp_sha256_process(sha256, (const byte*)local); + } + #else + ret = XTRANSFORM(sha256, (const byte*)local); + #endif + 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(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif + { + ByteReverseWords(sha256->buffer, sha256->buffer, + WC_SHA256_BLOCK_SIZE); + } + #endif + /* ! 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) /* 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 + + #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if (sha256->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha256->ctx); + } + if (sha256->ctx.mode == ESP32_SHA_SW) { + ret = XTRANSFORM(sha256, (const byte*)local); + } else { + ret = esp_sha256_digest_process(sha256, 1); + } + #else + ret = XTRANSFORM(sha256, (const byte*)local); #endif - ret = XTRANSFORM(sha256, local); - if (ret != 0) return ret; + } + + int wc_Sha256FinalRaw(wc_Sha256* sha256, byte* hash) + { + #ifdef LITTLE_ENDIAN_ORDER + word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)]; + #endif + + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords((word32*)digest, (word32*)sha256->digest, + WC_SHA256_DIGEST_SIZE); + XMEMCPY(hash, digest, WC_SHA256_DIGEST_SIZE); + #else + XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE); + #endif + + return 0; + } + + int wc_Sha256Final(wc_Sha256* sha256, byte* hash) + { + int ret; + + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + #ifdef WOLF_CRYPTO_CB + if (sha256->devId != INVALID_DEVID) { + ret = wc_CryptoCb_Sha256Hash(sha256, NULL, 0, hash); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } + #endif + + #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 */ + return InitSha256(sha256); /* reset state */ + } + +#endif /* XTRANSFORM */ + +#ifdef WOLFSSL_SHA224 + +#ifdef STM32_HASH_SHA2 + + /* Supports CubeMX HAL or Standard Peripheral Library */ + + int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId) + { + if (sha224 == NULL) + return BAD_FUNC_ARG; + + (void)devId; + (void)heap; + + wc_Stm32_Hash_Init(&sha224->stmCtx); + return 0; + } + + int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len) + { + int ret = 0; + + if (sha224 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Update(&sha224->stmCtx, + HASH_AlgoSelection_SHA224, data, len); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + + int wc_Sha224Final(wc_Sha224* sha224, byte* hash) + { + int ret = 0; + + if (sha224 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Final(&sha224->stmCtx, + HASH_AlgoSelection_SHA224, hash, WC_SHA224_DIGEST_SIZE); + wolfSSL_CryptHwMutexUnLock(); + } + + (void)wc_InitSha224(sha224); /* reset state */ + + return ret; + } + +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) + /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */ + +#elif defined(WOLFSSL_AFALG_HASH) + #error SHA224 currently not supported with AF_ALG enabled + +#elif defined(WOLFSSL_DEVCRYPTO_HASH) + /* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */ + +#else + + #define NEED_SOFT_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; + + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + /* choose best Transform function under this runtime environment */ + Sha256_SetTransform(); + #endif + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + sha224->flags = 0; + #endif + + return ret; + } + +#endif + +#ifdef NEED_SOFT_SHA224 + 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; + + #ifdef WOLFSSL_SMALL_STACK_CACHE + sha224->W = NULL; + #endif + + #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_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) + ByteReverseWords(sha224->digest, sha224->digest, WC_SHA224_DIGEST_SIZE); + #endif + XMEMCPY(hash, sha224->digest, WC_SHA224_DIGEST_SIZE); + + return InitSha224(sha224); /* reset state */ + } +#endif /* end of SHA224 software implementation */ + + int wc_InitSha224(wc_Sha224* sha224) + { + return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID); + } + + void wc_Sha224Free(wc_Sha224* sha224) + { + if (sha224 == NULL) + return; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (sha224->W != NULL) { + XFREE(sha224->W, NULL, DYNAMIC_TYPE_DIGEST); + sha224->W = NULL; + } +#endif + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + wolfAsync_DevCtxFree(&sha224->asyncDev, WOLFSSL_ASYNC_MARKER_SHA224); + #endif /* WOLFSSL_ASYNC_CRYPT */ + + #ifdef WOLFSSL_PIC32MZ_HASH + wc_Sha256Pic32Free(sha224); + #endif + } +#endif /* WOLFSSL_SHA224 */ + + +int wc_InitSha256(wc_Sha256* sha256) +{ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); } +void wc_Sha256Free(wc_Sha256* sha256) +{ + if (sha256 == NULL) + return; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (sha256->W != NULL) { + XFREE(sha256->W, NULL, DYNAMIC_TYPE_DIGEST); + sha256->W = NULL; + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + wolfAsync_DevCtxFree(&sha256->asyncDev, WOLFSSL_ASYNC_MARKER_SHA256); +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_PIC32MZ_HASH + wc_Sha256Pic32Free(sha256); +#endif +#if defined(WOLFSSL_AFALG_HASH) + if (sha256->alFd > 0) { + close(sha256->alFd); + sha256->alFd = -1; /* avoid possible double close on socket */ + } + if (sha256->rdFd > 0) { + close(sha256->rdFd); + sha256->rdFd = -1; /* avoid possible double close on socket */ + } +#endif /* WOLFSSL_AFALG_HASH */ +#ifdef WOLFSSL_DEVCRYPTO_HASH + wc_DevCryptoFree(&sha256->ctx); +#endif /* WOLFSSL_DEVCRYPTO */ +#if (defined(WOLFSSL_AFALG_HASH) && defined(WOLFSSL_AFALG_HASH_KEEP)) || \ + (defined(WOLFSSL_DEVCRYPTO_HASH) && defined(WOLFSSL_DEVCRYPTO_HASH_KEEP)) || \ + (defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)) + if (sha256->msg != NULL) { + XFREE(sha256->msg, sha256->heap, DYNAMIC_TYPE_TMP_BUFFER); + sha256->msg = NULL; + } +#endif +} + +#endif /* !WOLFSSL_TI_HASH */ +#endif /* HAVE_FIPS */ -int wc_Sha256Hash(const byte* data, word32 len, byte* hash) +#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); + wc_Sha224Free(&tmpSha224); + } + 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_SMALL_STACK_CACHE + dst->W = NULL; + #endif + + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); + #endif + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; + #endif + + return ret; + } + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + int wc_Sha224SetFlags(wc_Sha224* sha224, word32 flags) + { + if (sha224) { + sha224->flags = flags; + } + return 0; + } + int wc_Sha224GetFlags(wc_Sha224* sha224, word32* flags) + { + if (sha224 && flags) { + *flags = sha224->flags; + } + return 0; + } +#endif + +#endif /* WOLFSSL_SHA224 */ + +#ifdef WOLFSSL_AFALG_HASH + /* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */ + +#elif defined(WOLFSSL_DEVCRYPTO_HASH) + /* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */ + +#elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH) + + /* implemented in wolfcrypt/src/port/Renesas/renesas_tsip_sha.c */ +#else + +int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash) +{ + int ret; + wc_Sha256 tmpSha256; + + if (sha256 == NULL || hash == NULL) + return BAD_FUNC_ARG; + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if(sha256->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha256->ctx); + } + if(sha256->ctx.mode == ESP32_SHA_HW) + { + esp_sha256_digest_process(sha256, 0); + } +#endif + ret = wc_Sha256Copy(sha256, &tmpSha256); + if (ret == 0) { + ret = wc_Sha256Final(&tmpSha256, hash); +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha256->ctx.mode = ESP32_SHA_SW; +#endif + + wc_Sha256Free(&tmpSha256); + } + return ret; +} +int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) { int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha256* sha256; -#else - Sha256 sha256[1]; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha256)); +#ifdef WOLFSSL_SMALL_STACK_CACHE + dst->W = NULL; #endif -#ifdef WOLFSSL_SMALL_STACK - sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha256 == NULL) - return MEMORY_E; +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); #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 - XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_PIC32MZ_HASH + ret = wc_Pic32HashCopy(&src->cache, &dst->cache); +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + dst->ctx.mode = src->ctx.mode; + dst->ctx.isfirstblock = src->ctx.isfirstblock; + dst->ctx.sha_type = src->ctx.sha_type; +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; #endif return ret; } - -#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 _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 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 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" - -#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_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_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_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_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_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_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"); - #endif -#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_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_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_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_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_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_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_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_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_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_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); \ +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Sha256SetFlags(wc_Sha256* sha256, word32 flags) +{ + if (sha256) { + sha256->flags = flags; + } + return 0; } - -#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); \ +int wc_Sha256GetFlags(wc_Sha256* sha256, word32* flags) +{ + if (sha256 && flags) { + *flags = sha256->flags; + } + return 0; } - -#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); \ -} - -#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_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_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)::) ; - -#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 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]} */\ - -#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]} */\ - #endif - - -#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 _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 _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 Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)\ - _Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) - -#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 -#define XTMP4 %xmm8 -#define XTMP5 %xmm9 -#define XFER %xmm10 - -#define SHUF_00BA %xmm11 /* shuffle xBxA -> 00BA */ -#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) -{ - - word32 W_K[64] ; /* temp for W+K */ - - #if defined(DEBUG_XMM) - int i, j ; - word32 xmm[29][4*15] ; - #endif - - Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; - W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ - - 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) ; - - 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) ; - - 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) ; - - 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) ; - - #if defined(DEBUG_XMM) - for(i=0; i<29; i++) { - for(j=0; j<4*14; j+=4) - printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, - xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; - printf("\n") ; - } - - for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; - #endif - - return 0; -} - -#if defined(HAVE_INTEL_RORX) -static int Transform_AVX1_RORX(Sha256* sha256) -{ - - word32 W_K[64] ; /* temp for W+K */ - - #if defined(DEBUG_XMM) - int i, j ; - word32 xmm[29][4*15] ; - #endif - - Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; - W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ - - 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) ; - - 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) ; - - 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) ; - - 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) ; - - #if defined(DEBUG_XMM) - for(i=0; i<29; i++) { - for(j=0; j<4*14; j+=4) - printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, - xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; - printf("\n") ; - } - - for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; - #endif - - return 0; -} -#endif /* HAVE_INTEL_RORX */ - -#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, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - return 0; -} - -#endif /* HAVE_INTEL_AVX2 */ - -#endif /* HAVE_FIPS */ - -#endif /* WOLFSSL_TI_HAHS */ +#endif /* !WOLFSSL_TI_HASH */ #endif /* NO_SHA256 */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha256_asm.S b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha256_asm.S new file mode 100644 index 000000000..c433d341c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha256_asm.S @@ -0,0 +1,22653 @@ +/* sha256_asm + * + * Copyright (C) 2006-2020 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 HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX1 +#endif /* HAVE_INTEL_AVX1 */ +#ifndef NO_AVX2_SUPPORT +#define HAVE_INTEL_AVX2 +#endif /* NO_AVX2_SUPPORT */ + +#ifdef HAVE_INTEL_AVX1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +L_avx1_sha256_k: +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0xe49b69c1,0xefbe4786,0xfc19dc6,0x240ca1cc +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0xc6e00bf3,0xd5a79147,0x6ca6351,0x14292967 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_sha256_shuf_00BA: +.quad 0xb0a090803020100, 0xffffffffffffffff +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_sha256_shuf_DC00: +.quad 0xffffffffffffffff, 0xb0a090803020100 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_sha256_flip_mask: +.quad 0x405060700010203, 0xc0d0e0f08090a0b +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX1 +.type Transform_Sha256_AVX1,@function +.align 4 +Transform_Sha256_AVX1: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX1 +.p2align 2 +_Transform_Sha256_AVX1: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x40, %rsp + leaq 32(%rdi), %rax + vmovdqa L_avx1_sha256_flip_mask(%rip), %xmm13 + vmovdqa L_avx1_sha256_shuf_00BA(%rip), %xmm11 + vmovdqa L_avx1_sha256_shuf_DC00(%rip), %xmm12 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vpshufb %xmm13, %xmm0, %xmm0 + vpshufb %xmm13, %xmm1, %xmm1 + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vpshufb %xmm13, %xmm2, %xmm2 + vpshufb %xmm13, %xmm3, %xmm3 + movl %r9d, %ebx + movl %r12d, %edx + xorl %r10d, %ebx + # set_w_k_xfer_4: 0 + vpaddd 0+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 16+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 32+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 48+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm0, %xmm1, %xmm5 + vpalignr $4, %xmm2, %xmm3, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm1, %xmm2, %xmm5 + vpalignr $4, %xmm3, %xmm0, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 16(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 20(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 24(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 28(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm2, %xmm3, %xmm5 + vpalignr $4, %xmm0, %xmm1, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 32(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 36(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 40(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 44(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm3, %xmm0, %xmm5 + vpalignr $4, %xmm1, %xmm2, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 48(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 52(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 56(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 60(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 4 + vpaddd 64+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 80+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 96+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 112+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm0, %xmm1, %xmm5 + vpalignr $4, %xmm2, %xmm3, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm1, %xmm2, %xmm5 + vpalignr $4, %xmm3, %xmm0, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 16(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 20(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 24(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 28(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm2, %xmm3, %xmm5 + vpalignr $4, %xmm0, %xmm1, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 32(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 36(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 40(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 44(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm3, %xmm0, %xmm5 + vpalignr $4, %xmm1, %xmm2, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 48(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 52(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 56(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 60(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 8 + vpaddd 128+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 144+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 160+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 176+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm0, %xmm1, %xmm5 + vpalignr $4, %xmm2, %xmm3, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm1, %xmm2, %xmm5 + vpalignr $4, %xmm3, %xmm0, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 16(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 20(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 24(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 28(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm2, %xmm3, %xmm5 + vpalignr $4, %xmm0, %xmm1, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 32(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 36(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 40(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 44(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm3, %xmm0, %xmm5 + vpalignr $4, %xmm1, %xmm2, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 48(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 52(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 56(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 60(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 12 + vpaddd 192+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 208+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 224+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 240+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # rnd_all_4: 0-3 + addl (%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 4(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 8(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 12(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 1-4 + addl 16(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 20(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 24(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 28(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 2-5 + addl 32(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 36(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 40(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 44(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 3-6 + addl 48(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 52(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 56(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 60(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + addl %r8d, (%rdi) + addl %r9d, 4(%rdi) + addl %r10d, 8(%rdi) + addl %r11d, 12(%rdi) + addl %r12d, 16(%rdi) + addl %r13d, 20(%rdi) + addl %r14d, 24(%rdi) + addl %r15d, 28(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX1,.-Transform_Sha256_AVX1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX1_Len +.type Transform_Sha256_AVX1_Len,@function +.align 4 +Transform_Sha256_AVX1_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX1_Len +.p2align 2 +_Transform_Sha256_AVX1_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + movq %rdx, %rsi + subq $0x40, %rsp + vmovdqa L_avx1_sha256_flip_mask(%rip), %xmm13 + vmovdqa L_avx1_sha256_shuf_00BA(%rip), %xmm11 + vmovdqa L_avx1_sha256_shuf_DC00(%rip), %xmm12 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # Start of loop processing a block +L_sha256_len_avx1_start: + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rbp), %xmm0 + vmovdqu 16(%rbp), %xmm1 + vpshufb %xmm13, %xmm0, %xmm0 + vpshufb %xmm13, %xmm1, %xmm1 + vmovdqu 32(%rbp), %xmm2 + vmovdqu 48(%rbp), %xmm3 + vpshufb %xmm13, %xmm2, %xmm2 + vpshufb %xmm13, %xmm3, %xmm3 + movl %r9d, %ebx + movl %r12d, %edx + xorl %r10d, %ebx + # set_w_k_xfer_4: 0 + vpaddd 0+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 16+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 32+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 48+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm0, %xmm1, %xmm5 + vpalignr $4, %xmm2, %xmm3, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm1, %xmm2, %xmm5 + vpalignr $4, %xmm3, %xmm0, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 16(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 20(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 24(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 28(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm2, %xmm3, %xmm5 + vpalignr $4, %xmm0, %xmm1, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 32(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 36(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 40(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 44(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm3, %xmm0, %xmm5 + vpalignr $4, %xmm1, %xmm2, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 48(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 52(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 56(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 60(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 4 + vpaddd 64+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 80+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 96+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 112+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm0, %xmm1, %xmm5 + vpalignr $4, %xmm2, %xmm3, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm1, %xmm2, %xmm5 + vpalignr $4, %xmm3, %xmm0, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 16(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 20(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 24(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 28(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm2, %xmm3, %xmm5 + vpalignr $4, %xmm0, %xmm1, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 32(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 36(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 40(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 44(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm3, %xmm0, %xmm5 + vpalignr $4, %xmm1, %xmm2, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 48(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 52(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 56(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 60(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 8 + vpaddd 128+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 144+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 160+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 176+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm0, %xmm1, %xmm5 + vpalignr $4, %xmm2, %xmm3, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm1, %xmm2, %xmm5 + vpalignr $4, %xmm3, %xmm0, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 16(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 20(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 24(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 28(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm2, %xmm3, %xmm5 + vpalignr $4, %xmm0, %xmm1, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 32(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 36(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 40(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 44(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm3, %xmm0, %xmm5 + vpalignr $4, %xmm1, %xmm2, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 48(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 52(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 56(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 60(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 12 + vpaddd 192+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 208+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 224+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 240+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # rnd_all_4: 0-3 + addl (%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 4(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 8(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 12(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 1-4 + addl 16(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 20(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 24(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 28(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 2-5 + addl 32(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 36(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 40(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 44(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 3-6 + addl 48(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 52(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 56(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 60(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + addl (%rdi), %r8d + addl 4(%rdi), %r9d + addl 8(%rdi), %r10d + addl 12(%rdi), %r11d + addl 16(%rdi), %r12d + addl 20(%rdi), %r13d + addl 24(%rdi), %r14d + addl 28(%rdi), %r15d + addq $0x40, %rbp + subl $0x40, %esi + movl %r8d, (%rdi) + movl %r9d, 4(%rdi) + movl %r10d, 8(%rdi) + movl %r11d, 12(%rdi) + movl %r12d, 16(%rdi) + movl %r13d, 20(%rdi) + movl %r14d, 24(%rdi) + movl %r15d, 28(%rdi) + jnz L_sha256_len_avx1_start + xorq %rax, %rax + vzeroupper + addq $0x40, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX1_Len,.-Transform_Sha256_AVX1_Len +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +L_avx1_rorx_sha256_k: +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0xe49b69c1,0xefbe4786,0xfc19dc6,0x240ca1cc +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0xc6e00bf3,0xd5a79147,0x6ca6351,0x14292967 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_rorx_sha256_shuf_00BA: +.quad 0xb0a090803020100, 0xffffffffffffffff +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_rorx_sha256_shuf_DC00: +.quad 0xffffffffffffffff, 0xb0a090803020100 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_rorx_sha256_flip_mask: +.quad 0x405060700010203, 0xc0d0e0f08090a0b +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX1_RORX +.type Transform_Sha256_AVX1_RORX,@function +.align 4 +Transform_Sha256_AVX1_RORX: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX1_RORX +.p2align 2 +_Transform_Sha256_AVX1_RORX: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x40, %rsp + vmovdqa L_avx1_rorx_sha256_flip_mask(%rip), %xmm13 + vmovdqa L_avx1_rorx_sha256_shuf_00BA(%rip), %xmm11 + vmovdqa L_avx1_rorx_sha256_shuf_DC00(%rip), %xmm12 + leaq 32(%rdi), %rax + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vpshufb %xmm13, %xmm0, %xmm0 + vpshufb %xmm13, %xmm1, %xmm1 + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vpshufb %xmm13, %xmm2, %xmm2 + vpshufb %xmm13, %xmm3, %xmm3 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # set_w_k_xfer_4: 0 + vpaddd 0+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 16+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 32+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 48+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + movl %r9d, %ebx + rorxl $6, %r12d, %edx + xorl %r10d, %ebx + # msg_sched: 0-3 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %xmm2, %xmm3, %xmm4 + vpalignr $4, %xmm0, %xmm1, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 16(%rsp), %r11d + vpalignr $4, %xmm3, %xmm0, %xmm4 + vpalignr $4, %xmm1, %xmm2, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 20(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 24(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 28(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 32(%rsp), %r15d + vpalignr $4, %xmm0, %xmm1, %xmm4 + vpalignr $4, %xmm2, %xmm3, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 36(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 40(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 44(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 48(%rsp), %r11d + vpalignr $4, %xmm1, %xmm2, %xmm4 + vpalignr $4, %xmm3, %xmm0, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 52(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 56(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 60(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 4 + vpaddd 64+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 80+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 96+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 112+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %xmm2, %xmm3, %xmm4 + vpalignr $4, %xmm0, %xmm1, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 16(%rsp), %r11d + vpalignr $4, %xmm3, %xmm0, %xmm4 + vpalignr $4, %xmm1, %xmm2, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 20(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 24(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 28(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 32(%rsp), %r15d + vpalignr $4, %xmm0, %xmm1, %xmm4 + vpalignr $4, %xmm2, %xmm3, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 36(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 40(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 44(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 48(%rsp), %r11d + vpalignr $4, %xmm1, %xmm2, %xmm4 + vpalignr $4, %xmm3, %xmm0, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 52(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 56(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 60(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 8 + vpaddd 128+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 144+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 160+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 176+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %xmm2, %xmm3, %xmm4 + vpalignr $4, %xmm0, %xmm1, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 16(%rsp), %r11d + vpalignr $4, %xmm3, %xmm0, %xmm4 + vpalignr $4, %xmm1, %xmm2, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 20(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 24(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 28(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 32(%rsp), %r15d + vpalignr $4, %xmm0, %xmm1, %xmm4 + vpalignr $4, %xmm2, %xmm3, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 36(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 40(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 44(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 48(%rsp), %r11d + vpalignr $4, %xmm1, %xmm2, %xmm4 + vpalignr $4, %xmm3, %xmm0, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 52(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 56(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 60(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 12 + vpaddd 192+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 208+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 224+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 240+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + xorl %eax, %eax + # rnd_all_4: 0-3 + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + addl %eax, %r8d + addl (%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 4(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + addl %eax, %r14d + addl 8(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 12(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + # rnd_all_4: 1-4 + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + addl %eax, %r12d + addl 16(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 20(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + addl %eax, %r10d + addl 24(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 28(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + # rnd_all_4: 2-5 + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + addl %eax, %r8d + addl 32(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 36(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + addl %eax, %r14d + addl 40(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 44(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + # rnd_all_4: 3-6 + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + addl %eax, %r12d + addl 48(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 52(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + addl %eax, %r10d + addl 56(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 60(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + addl %eax, %r8d + addl %r8d, (%rdi) + addl %r9d, 4(%rdi) + addl %r10d, 8(%rdi) + addl %r11d, 12(%rdi) + addl %r12d, 16(%rdi) + addl %r13d, 20(%rdi) + addl %r14d, 24(%rdi) + addl %r15d, 28(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX1_RORX,.-Transform_Sha256_AVX1_RORX +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX1_RORX_Len +.type Transform_Sha256_AVX1_RORX_Len,@function +.align 4 +Transform_Sha256_AVX1_RORX_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX1_RORX_Len +.p2align 2 +_Transform_Sha256_AVX1_RORX_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + movq %rdx, %rsi + subq $0x40, %rsp + vmovdqa L_avx1_rorx_sha256_flip_mask(%rip), %xmm13 + vmovdqa L_avx1_rorx_sha256_shuf_00BA(%rip), %xmm11 + vmovdqa L_avx1_rorx_sha256_shuf_DC00(%rip), %xmm12 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # Start of loop processing a block +L_sha256_len_avx1_len_rorx_start: + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rbp), %xmm0 + vmovdqu 16(%rbp), %xmm1 + vpshufb %xmm13, %xmm0, %xmm0 + vpshufb %xmm13, %xmm1, %xmm1 + vmovdqu 32(%rbp), %xmm2 + vmovdqu 48(%rbp), %xmm3 + vpshufb %xmm13, %xmm2, %xmm2 + vpshufb %xmm13, %xmm3, %xmm3 + # set_w_k_xfer_4: 0 + vpaddd 0+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 16+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 32+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 48+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + movl %r9d, %ebx + rorxl $6, %r12d, %edx + xorl %r10d, %ebx + # msg_sched: 0-3 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %xmm2, %xmm3, %xmm4 + vpalignr $4, %xmm0, %xmm1, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 16(%rsp), %r11d + vpalignr $4, %xmm3, %xmm0, %xmm4 + vpalignr $4, %xmm1, %xmm2, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 20(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 24(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 28(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 32(%rsp), %r15d + vpalignr $4, %xmm0, %xmm1, %xmm4 + vpalignr $4, %xmm2, %xmm3, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 36(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 40(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 44(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 48(%rsp), %r11d + vpalignr $4, %xmm1, %xmm2, %xmm4 + vpalignr $4, %xmm3, %xmm0, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 52(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 56(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 60(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 4 + vpaddd 64+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 80+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 96+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 112+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %xmm2, %xmm3, %xmm4 + vpalignr $4, %xmm0, %xmm1, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 16(%rsp), %r11d + vpalignr $4, %xmm3, %xmm0, %xmm4 + vpalignr $4, %xmm1, %xmm2, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 20(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 24(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 28(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 32(%rsp), %r15d + vpalignr $4, %xmm0, %xmm1, %xmm4 + vpalignr $4, %xmm2, %xmm3, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 36(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 40(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 44(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 48(%rsp), %r11d + vpalignr $4, %xmm1, %xmm2, %xmm4 + vpalignr $4, %xmm3, %xmm0, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 52(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 56(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 60(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 8 + vpaddd 128+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 144+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 160+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 176+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %xmm2, %xmm3, %xmm4 + vpalignr $4, %xmm0, %xmm1, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 16(%rsp), %r11d + vpalignr $4, %xmm3, %xmm0, %xmm4 + vpalignr $4, %xmm1, %xmm2, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 20(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 24(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 28(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 32(%rsp), %r15d + vpalignr $4, %xmm0, %xmm1, %xmm4 + vpalignr $4, %xmm2, %xmm3, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 36(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 40(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 44(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 48(%rsp), %r11d + vpalignr $4, %xmm1, %xmm2, %xmm4 + vpalignr $4, %xmm3, %xmm0, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 52(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 56(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 60(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 12 + vpaddd 192+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 208+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 224+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 240+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + xorl %eax, %eax + xorl %ecx, %ecx + # rnd_all_4: 0-3 + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + addl %eax, %r8d + addl (%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 4(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + addl %eax, %r14d + addl 8(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 12(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + # rnd_all_4: 1-4 + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + addl %eax, %r12d + addl 16(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 20(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + addl %eax, %r10d + addl 24(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 28(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + # rnd_all_4: 2-5 + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + addl %eax, %r8d + addl 32(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 36(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + addl %eax, %r14d + addl 40(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 44(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + # rnd_all_4: 3-6 + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + addl %eax, %r12d + addl 48(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 52(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + addl %eax, %r10d + addl 56(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 60(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + addl %eax, %r8d + addl (%rdi), %r8d + addl 4(%rdi), %r9d + addl 8(%rdi), %r10d + addl 12(%rdi), %r11d + addl 16(%rdi), %r12d + addl 20(%rdi), %r13d + addl 24(%rdi), %r14d + addl 28(%rdi), %r15d + addq $0x40, %rbp + subl $0x40, %esi + movl %r8d, (%rdi) + movl %r9d, 4(%rdi) + movl %r10d, 8(%rdi) + movl %r11d, 12(%rdi) + movl %r12d, 16(%rdi) + movl %r13d, 20(%rdi) + movl %r14d, 24(%rdi) + movl %r15d, 28(%rdi) + jnz L_sha256_len_avx1_len_rorx_start + xorq %rax, %rax + vzeroupper + addq $0x40, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX1_RORX_Len,.-Transform_Sha256_AVX1_RORX_Len +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX1 */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +L_avx2_sha256_k: +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0xe49b69c1,0xefbe4786,0xfc19dc6,0x240ca1cc +.long 0xe49b69c1,0xefbe4786,0xfc19dc6,0x240ca1cc +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0xc6e00bf3,0xd5a79147,0x6ca6351,0x14292967 +.long 0xc6e00bf3,0xd5a79147,0x6ca6351,0x14292967 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_sha256_shuf_00BA: +.quad 0xb0a090803020100, 0xffffffffffffffff +.quad 0xb0a090803020100, 0xffffffffffffffff +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_sha256_shuf_DC00: +.quad 0xffffffffffffffff, 0xb0a090803020100 +.quad 0xffffffffffffffff, 0xb0a090803020100 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_sha256_flip_mask: +.quad 0x405060700010203, 0xc0d0e0f08090a0b +.quad 0x405060700010203, 0xc0d0e0f08090a0b +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX2 +.type Transform_Sha256_AVX2,@function +.align 4 +Transform_Sha256_AVX2: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX2 +.p2align 2 +_Transform_Sha256_AVX2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x200, %rsp + leaq 32(%rdi), %rax + vmovdqa L_avx2_sha256_flip_mask(%rip), %xmm13 + vmovdqa L_avx2_sha256_shuf_00BA(%rip), %ymm11 + vmovdqa L_avx2_sha256_shuf_DC00(%rip), %ymm12 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vpshufb %xmm13, %xmm0, %xmm0 + vpshufb %xmm13, %xmm1, %xmm1 + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vpshufb %xmm13, %xmm2, %xmm2 + vpshufb %xmm13, %xmm3, %xmm3 + movl %r9d, %ebx + movl %r12d, %edx + xorl %r10d, %ebx + # set_w_k_xfer_4: 0 + vpaddd 0+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 32+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, (%rsp) + vmovdqu %ymm5, 32(%rsp) + vpaddd 64+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 96+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 64(%rsp) + vmovdqu %ymm5, 96(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm0, %ymm1, %ymm5 + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm3, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # msg_sched done: 0-3 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm1, %ymm2, %ymm5 + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 32(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 36(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm0, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 40(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 44(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # msg_sched done: 8-11 + # msg_sched: 16-19 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm2, %ymm3, %ymm5 + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 64(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 68(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm1, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 72(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 76(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # msg_sched done: 16-19 + # msg_sched: 24-27 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm3, %ymm0, %ymm5 + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 96(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 100(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm2, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 104(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 108(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # msg_sched done: 24-27 + # set_w_k_xfer_4: 4 + vpaddd 128+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 160+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, 128(%rsp) + vmovdqu %ymm5, 160(%rsp) + vpaddd 192+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 224+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 192(%rsp) + vmovdqu %ymm5, 224(%rsp) + # msg_sched: 32-35 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm0, %ymm1, %ymm5 + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 128(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 132(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm3, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 136(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 140(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # msg_sched done: 32-35 + # msg_sched: 40-43 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm1, %ymm2, %ymm5 + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 160(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 164(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm0, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 168(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 172(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # msg_sched done: 40-43 + # msg_sched: 48-51 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm2, %ymm3, %ymm5 + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 192(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 196(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm1, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 200(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 204(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # msg_sched done: 48-51 + # msg_sched: 56-59 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm3, %ymm0, %ymm5 + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 224(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 228(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm2, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 232(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 236(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # msg_sched done: 56-59 + # set_w_k_xfer_4: 8 + vpaddd 256+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 288+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, 256(%rsp) + vmovdqu %ymm5, 288(%rsp) + vpaddd 320+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 352+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 320(%rsp) + vmovdqu %ymm5, 352(%rsp) + # msg_sched: 64-67 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm0, %ymm1, %ymm5 + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 256(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 260(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm3, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 264(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 268(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # msg_sched done: 64-67 + # msg_sched: 72-75 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm1, %ymm2, %ymm5 + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 288(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 292(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm0, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 296(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 300(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # msg_sched done: 72-75 + # msg_sched: 80-83 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm2, %ymm3, %ymm5 + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 320(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 324(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm1, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 328(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 332(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # msg_sched done: 80-83 + # msg_sched: 88-91 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm3, %ymm0, %ymm5 + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 352(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 356(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm2, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 360(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 364(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # msg_sched done: 88-91 + # set_w_k_xfer_4: 12 + vpaddd 384+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 416+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, 384(%rsp) + vmovdqu %ymm5, 416(%rsp) + vpaddd 448+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 480+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 448(%rsp) + vmovdqu %ymm5, 480(%rsp) + # rnd_all_4: 24-27 + addl 384(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 388(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 392(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 396(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 26-29 + addl 416(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 420(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 424(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 428(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 28-31 + addl 448(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 452(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 456(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 460(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 30-33 + addl 480(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 484(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 488(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 492(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + addl %r8d, (%rdi) + addl %r9d, 4(%rdi) + addl %r10d, 8(%rdi) + addl %r11d, 12(%rdi) + addl %r12d, 16(%rdi) + addl %r13d, 20(%rdi) + addl %r14d, 24(%rdi) + addl %r15d, 28(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x200, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX2,.-Transform_Sha256_AVX2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX2_Len +.type Transform_Sha256_AVX2_Len,@function +.align 4 +Transform_Sha256_AVX2_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX2_Len +.p2align 2 +_Transform_Sha256_AVX2_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + movq %rdx, %rsi + subq $0x200, %rsp + testb $0x40, %sil + je L_sha256_len_avx2_block + vmovdqu (%rbp), %ymm0 + vmovdqu 32(%rbp), %ymm1 + vmovups %ymm0, 32(%rdi) + vmovups %ymm1, 64(%rdi) +#ifndef __APPLE__ + call Transform_Sha256_AVX2@plt +#else + call _Transform_Sha256_AVX2 +#endif /* __APPLE__ */ + addq $0x40, %rbp + subl $0x40, %esi + jz L_sha256_len_avx2_done +L_sha256_len_avx2_block: + vmovdqa L_avx2_sha256_flip_mask(%rip), %ymm13 + vmovdqa L_avx2_sha256_shuf_00BA(%rip), %ymm11 + vmovdqa L_avx2_sha256_shuf_DC00(%rip), %ymm12 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # Start of loop processing two blocks +L_sha256_len_avx2_start: + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rbp), %xmm0 + vmovdqu 16(%rbp), %xmm1 + vmovdqu 64(%rbp), %xmm4 + vmovdqu 80(%rbp), %xmm5 + vinserti128 $0x01, %xmm4, %ymm0, %ymm0 + vinserti128 $0x01, %xmm5, %ymm1, %ymm1 + vpshufb %ymm13, %ymm0, %ymm0 + vpshufb %ymm13, %ymm1, %ymm1 + vmovdqu 32(%rbp), %xmm2 + vmovdqu 48(%rbp), %xmm3 + vmovdqu 96(%rbp), %xmm6 + vmovdqu 112(%rbp), %xmm7 + vinserti128 $0x01, %xmm6, %ymm2, %ymm2 + vinserti128 $0x01, %xmm7, %ymm3, %ymm3 + vpshufb %ymm13, %ymm2, %ymm2 + vpshufb %ymm13, %ymm3, %ymm3 + movl %r9d, %ebx + movl %r12d, %edx + xorl %r10d, %ebx + # set_w_k_xfer_4: 0 + vpaddd 0+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 32+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, (%rsp) + vmovdqu %ymm5, 32(%rsp) + vpaddd 64+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 96+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 64(%rsp) + vmovdqu %ymm5, 96(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm0, %ymm1, %ymm5 + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm3, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # msg_sched done: 0-3 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm1, %ymm2, %ymm5 + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 32(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 36(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm0, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 40(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 44(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # msg_sched done: 8-11 + # msg_sched: 16-19 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm2, %ymm3, %ymm5 + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 64(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 68(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm1, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 72(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 76(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # msg_sched done: 16-19 + # msg_sched: 24-27 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm3, %ymm0, %ymm5 + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 96(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 100(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm2, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 104(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 108(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # msg_sched done: 24-27 + # set_w_k_xfer_4: 4 + vpaddd 128+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 160+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, 128(%rsp) + vmovdqu %ymm5, 160(%rsp) + vpaddd 192+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 224+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 192(%rsp) + vmovdqu %ymm5, 224(%rsp) + # msg_sched: 32-35 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm0, %ymm1, %ymm5 + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 128(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 132(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm3, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 136(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 140(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # msg_sched done: 32-35 + # msg_sched: 40-43 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm1, %ymm2, %ymm5 + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 160(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 164(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm0, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 168(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 172(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # msg_sched done: 40-43 + # msg_sched: 48-51 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm2, %ymm3, %ymm5 + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 192(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 196(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm1, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 200(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 204(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # msg_sched done: 48-51 + # msg_sched: 56-59 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm3, %ymm0, %ymm5 + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 224(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 228(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm2, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 232(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 236(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # msg_sched done: 56-59 + # set_w_k_xfer_4: 8 + vpaddd 256+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 288+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, 256(%rsp) + vmovdqu %ymm5, 288(%rsp) + vpaddd 320+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 352+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 320(%rsp) + vmovdqu %ymm5, 352(%rsp) + # msg_sched: 64-67 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm0, %ymm1, %ymm5 + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 256(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 260(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm3, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 264(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 268(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # msg_sched done: 64-67 + # msg_sched: 72-75 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm1, %ymm2, %ymm5 + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 288(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 292(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm0, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 296(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 300(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # msg_sched done: 72-75 + # msg_sched: 80-83 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm2, %ymm3, %ymm5 + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 320(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 324(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm1, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 328(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 332(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # msg_sched done: 80-83 + # msg_sched: 88-91 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm3, %ymm0, %ymm5 + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 352(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 356(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm2, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 360(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 364(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # msg_sched done: 88-91 + # set_w_k_xfer_4: 12 + vpaddd 384+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 416+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, 384(%rsp) + vmovdqu %ymm5, 416(%rsp) + vpaddd 448+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 480+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 448(%rsp) + vmovdqu %ymm5, 480(%rsp) + # rnd_all_4: 24-27 + addl 384(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 388(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 392(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 396(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 26-29 + addl 416(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 420(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 424(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 428(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 28-31 + addl 448(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 452(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 456(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 460(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 30-33 + addl 480(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 484(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 488(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 492(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + addl (%rdi), %r8d + addl 4(%rdi), %r9d + addl 8(%rdi), %r10d + addl 12(%rdi), %r11d + addl 16(%rdi), %r12d + addl 20(%rdi), %r13d + addl 24(%rdi), %r14d + addl 28(%rdi), %r15d + movl %r8d, (%rdi) + movl %r9d, 4(%rdi) + movl %r10d, 8(%rdi) + movl %r11d, 12(%rdi) + movl %r12d, 16(%rdi) + movl %r13d, 20(%rdi) + movl %r14d, 24(%rdi) + movl %r15d, 28(%rdi) + movl %r9d, %ebx + movl %r12d, %edx + xorl %r10d, %ebx + # rnd_all_4: 1-4 + addl 16(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 20(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 24(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 28(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 3-6 + addl 48(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 52(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 56(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 60(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 5-8 + addl 80(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 84(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 88(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 92(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 7-10 + addl 112(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 116(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 120(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 124(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 9-12 + addl 144(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 148(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 152(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 156(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 11-14 + addl 176(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 180(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 184(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 188(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 13-16 + addl 208(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 212(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 216(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 220(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 15-18 + addl 240(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 244(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 248(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 252(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 17-20 + addl 272(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 276(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 280(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 284(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 19-22 + addl 304(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 308(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 312(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 316(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 21-24 + addl 336(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 340(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 344(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 348(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 23-26 + addl 368(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 372(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 376(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 380(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 25-28 + addl 400(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 404(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 408(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 412(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 27-30 + addl 432(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 436(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 440(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 444(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 29-32 + addl 464(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 468(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 472(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 476(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 31-34 + addl 496(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 500(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 504(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 508(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + addl (%rdi), %r8d + addl 4(%rdi), %r9d + addl 8(%rdi), %r10d + addl 12(%rdi), %r11d + addl 16(%rdi), %r12d + addl 20(%rdi), %r13d + addl 24(%rdi), %r14d + addl 28(%rdi), %r15d + addq $0x80, %rbp + subl $0x80, %esi + movl %r8d, (%rdi) + movl %r9d, 4(%rdi) + movl %r10d, 8(%rdi) + movl %r11d, 12(%rdi) + movl %r12d, 16(%rdi) + movl %r13d, 20(%rdi) + movl %r14d, 24(%rdi) + movl %r15d, 28(%rdi) + jnz L_sha256_len_avx2_start +L_sha256_len_avx2_done: + xorq %rax, %rax + vzeroupper + addq $0x200, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX2_Len,.-Transform_Sha256_AVX2_Len +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +L_avx2_rorx_sha256_k: +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0xe49b69c1,0xefbe4786,0xfc19dc6,0x240ca1cc +.long 0xe49b69c1,0xefbe4786,0xfc19dc6,0x240ca1cc +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0xc6e00bf3,0xd5a79147,0x6ca6351,0x14292967 +.long 0xc6e00bf3,0xd5a79147,0x6ca6351,0x14292967 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_rorx_sha256_flip_mask: +.quad 0x405060700010203, 0xc0d0e0f08090a0b +.quad 0x405060700010203, 0xc0d0e0f08090a0b +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_rorx_sha256_shuf_00BA: +.quad 0xb0a090803020100, 0xffffffffffffffff +.quad 0xb0a090803020100, 0xffffffffffffffff +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_rorx_sha256_shuf_DC00: +.quad 0xffffffffffffffff, 0xb0a090803020100 +.quad 0xffffffffffffffff, 0xb0a090803020100 +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX2_RORX +.type Transform_Sha256_AVX2_RORX,@function +.align 4 +Transform_Sha256_AVX2_RORX: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX2_RORX +.p2align 2 +_Transform_Sha256_AVX2_RORX: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x200, %rsp + leaq 32(%rdi), %rax + vmovdqa L_avx2_rorx_sha256_flip_mask(%rip), %xmm13 + vmovdqa L_avx2_rorx_sha256_shuf_00BA(%rip), %ymm11 + vmovdqa L_avx2_rorx_sha256_shuf_DC00(%rip), %ymm12 + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vpshufb %xmm13, %xmm0, %xmm0 + vpshufb %xmm13, %xmm1, %xmm1 + vpaddd 0+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 32+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, (%rsp) + vmovdqu %ymm5, 32(%rsp) + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vpshufb %xmm13, %xmm2, %xmm2 + vpshufb %xmm13, %xmm3, %xmm3 + vpaddd 64+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 96+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 64(%rsp) + vmovdqu %ymm5, 96(%rsp) + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + movl %r9d, %ebx + rorxl $6, %r12d, %edx + xorl %r10d, %ebx + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %ymm0, %ymm1, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm3, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 128+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 128(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 32(%rsp), %r11d + vpalignr $4, %ymm1, %ymm2, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 36(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm0, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 40(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 44(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 160+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 160(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 64(%rsp), %r15d + vpalignr $4, %ymm2, %ymm3, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 68(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm1, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 72(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 76(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 192+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 192(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 96(%rsp), %r11d + vpalignr $4, %ymm3, %ymm0, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 100(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm2, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 104(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 108(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 224+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 224(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 128(%rsp), %r15d + vpalignr $4, %ymm0, %ymm1, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 132(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm3, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 136(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 140(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 256+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 256(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 160(%rsp), %r11d + vpalignr $4, %ymm1, %ymm2, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 164(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm0, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 168(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 172(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 288+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 288(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 192(%rsp), %r15d + vpalignr $4, %ymm2, %ymm3, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 196(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm1, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 200(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 204(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 320+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 320(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 224(%rsp), %r11d + vpalignr $4, %ymm3, %ymm0, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 228(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm2, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 232(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 236(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 352+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 352(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 256(%rsp), %r15d + vpalignr $4, %ymm0, %ymm1, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 260(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm3, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 264(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 268(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 384+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 384(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 288(%rsp), %r11d + vpalignr $4, %ymm1, %ymm2, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 292(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm0, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 296(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 300(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 416+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 416(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 320(%rsp), %r15d + vpalignr $4, %ymm2, %ymm3, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 324(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm1, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 328(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 332(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 448+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 448(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 352(%rsp), %r11d + vpalignr $4, %ymm3, %ymm0, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 356(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm2, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 360(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 364(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 480+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 480(%rsp) + xorl %eax, %eax + xorl %ecx, %ecx + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 384(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 388(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 392(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 396(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 416(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 420(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 424(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 428(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 448(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 452(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 456(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 460(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 480(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 484(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 488(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 492(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + addl %eax, %r8d + addl %r8d, (%rdi) + addl %r9d, 4(%rdi) + addl %r10d, 8(%rdi) + addl %r11d, 12(%rdi) + addl %r12d, 16(%rdi) + addl %r13d, 20(%rdi) + addl %r14d, 24(%rdi) + addl %r15d, 28(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x200, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX2_RORX,.-Transform_Sha256_AVX2_RORX +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX2_RORX_Len +.type Transform_Sha256_AVX2_RORX_Len,@function +.align 4 +Transform_Sha256_AVX2_RORX_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX2_RORX_Len +.p2align 2 +_Transform_Sha256_AVX2_RORX_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + movq %rdx, %rsi + subq $0x200, %rsp + testb $0x40, %sil + je L_sha256_len_avx2_rorx_block + vmovdqu (%rbp), %ymm0 + vmovdqu 32(%rbp), %ymm1 + vmovups %ymm0, 32(%rdi) + vmovups %ymm1, 64(%rdi) +#ifndef __APPLE__ + call Transform_Sha256_AVX2_RORX@plt +#else + call _Transform_Sha256_AVX2_RORX +#endif /* __APPLE__ */ + addq $0x40, %rbp + subl $0x40, %esi + jz L_sha256_len_avx2_rorx_done +L_sha256_len_avx2_rorx_block: + vmovdqa L_avx2_rorx_sha256_flip_mask(%rip), %ymm13 + vmovdqa L_avx2_rorx_sha256_shuf_00BA(%rip), %ymm11 + vmovdqa L_avx2_rorx_sha256_shuf_DC00(%rip), %ymm12 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # Start of loop processing two blocks +L_sha256_len_avx2_rorx_start: + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rbp), %xmm0 + vmovdqu 16(%rbp), %xmm1 + vinserti128 $0x01, 64(%rbp), %ymm0, %ymm0 + vinserti128 $0x01, 80(%rbp), %ymm1, %ymm1 + vpshufb %ymm13, %ymm0, %ymm0 + vpshufb %ymm13, %ymm1, %ymm1 + vpaddd 0+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 32+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, (%rsp) + vmovdqu %ymm5, 32(%rsp) + vmovdqu 32(%rbp), %xmm2 + vmovdqu 48(%rbp), %xmm3 + vinserti128 $0x01, 96(%rbp), %ymm2, %ymm2 + vinserti128 $0x01, 112(%rbp), %ymm3, %ymm3 + vpshufb %ymm13, %ymm2, %ymm2 + vpshufb %ymm13, %ymm3, %ymm3 + vpaddd 64+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 96+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 64(%rsp) + vmovdqu %ymm5, 96(%rsp) + movl %r9d, %ebx + rorxl $6, %r12d, %edx + xorl %r10d, %ebx + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %ymm0, %ymm1, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm3, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 128+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 128(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 32(%rsp), %r11d + vpalignr $4, %ymm1, %ymm2, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 36(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm0, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 40(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 44(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 160+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 160(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 64(%rsp), %r15d + vpalignr $4, %ymm2, %ymm3, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 68(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm1, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 72(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 76(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 192+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 192(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 96(%rsp), %r11d + vpalignr $4, %ymm3, %ymm0, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 100(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm2, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 104(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 108(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 224+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 224(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 128(%rsp), %r15d + vpalignr $4, %ymm0, %ymm1, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 132(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm3, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 136(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 140(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 256+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 256(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 160(%rsp), %r11d + vpalignr $4, %ymm1, %ymm2, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 164(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm0, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 168(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 172(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 288+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 288(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 192(%rsp), %r15d + vpalignr $4, %ymm2, %ymm3, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 196(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm1, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 200(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 204(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 320+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 320(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 224(%rsp), %r11d + vpalignr $4, %ymm3, %ymm0, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 228(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm2, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 232(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 236(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 352+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 352(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 256(%rsp), %r15d + vpalignr $4, %ymm0, %ymm1, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 260(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm3, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 264(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 268(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 384+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 384(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 288(%rsp), %r11d + vpalignr $4, %ymm1, %ymm2, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 292(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm0, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 296(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 300(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 416+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 416(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 320(%rsp), %r15d + vpalignr $4, %ymm2, %ymm3, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 324(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm1, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 328(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 332(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 448+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 448(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 352(%rsp), %r11d + vpalignr $4, %ymm3, %ymm0, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 356(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm2, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 360(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 364(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 480+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 480(%rsp) + xorl %eax, %eax + xorl %ecx, %ecx + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 384(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 388(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 392(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 396(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 416(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 420(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 424(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 428(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 448(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 452(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 456(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 460(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 480(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 484(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 488(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 492(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + addl %eax, %r8d + xorl %ecx, %ecx + addl (%rdi), %r8d + addl 4(%rdi), %r9d + addl 8(%rdi), %r10d + addl 12(%rdi), %r11d + addl 16(%rdi), %r12d + addl 20(%rdi), %r13d + addl 24(%rdi), %r14d + addl 28(%rdi), %r15d + movl %r8d, (%rdi) + movl %r9d, 4(%rdi) + movl %r10d, 8(%rdi) + movl %r11d, 12(%rdi) + movl %r12d, 16(%rdi) + movl %r13d, 20(%rdi) + movl %r14d, 24(%rdi) + movl %r15d, 28(%rdi) + movl %r9d, %ebx + xorl %eax, %eax + xorl %r10d, %ebx + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 16(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 20(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 24(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 28(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 48(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 52(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 56(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 60(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 80(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 84(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 88(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 92(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 112(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 116(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 120(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 124(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 144(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 148(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 152(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 156(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 176(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 180(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 184(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 188(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 208(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 212(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 216(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 220(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 240(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 244(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 248(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 252(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 272(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 276(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 280(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 284(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 304(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 308(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 312(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 316(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 336(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 340(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 344(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 348(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 368(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 372(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 376(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 380(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 400(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 404(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 408(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 412(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 432(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 436(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 440(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 444(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 464(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 468(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 472(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 476(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 496(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 500(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 504(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 508(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + addl %eax, %r8d + addq $0x80, %rbp + addl (%rdi), %r8d + addl 4(%rdi), %r9d + addl 8(%rdi), %r10d + addl 12(%rdi), %r11d + addl 16(%rdi), %r12d + addl 20(%rdi), %r13d + addl 24(%rdi), %r14d + addl 28(%rdi), %r15d + subl $0x80, %esi + movl %r8d, (%rdi) + movl %r9d, 4(%rdi) + movl %r10d, 8(%rdi) + movl %r11d, 12(%rdi) + movl %r12d, 16(%rdi) + movl %r13d, 20(%rdi) + movl %r14d, 24(%rdi) + movl %r15d, 28(%rdi) + jnz L_sha256_len_avx2_rorx_start +L_sha256_len_avx2_rorx_done: + xorq %rax, %rax + vzeroupper + addq $0x200, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX2_RORX_Len,.-Transform_Sha256_AVX2_RORX_Len +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha3.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha3.c new file mode 100644 index 000000000..3a0c8ddbb --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha3.c @@ -0,0 +1,1216 @@ +/* sha3.c + * + * Copyright (C) 2006-2020 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) && \ + !defined(WOLFSSL_AFALG_XILINX_SHA3) + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$l") + #pragma const_seg(".fipsB$l") + #endif +#endif + +#include +#include +#include + +#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 +}; + +/* Indices 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 +}; + +/* Indices 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 wc_Sha3 object holding state. + * returns 0 on success. + */ +static int InitSha3(wc_Sha3* sha3) +{ + int i; + + for (i = 0; i < 25; i++) + sha3->s[i] = 0; + sha3->i = 0; +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + sha3->flags = 0; +#endif + + return 0; +} + +/* Update the SHA-3 hash state with message data. + * + * sha3 wc_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(wc_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 wc_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(wc_Sha3* sha3, byte padChar, byte* hash, byte p, byte l) +{ + byte i; + byte *s8 = (byte *)sha3->s; + + sha3->t[p * 8 - 1] = 0x00; +#ifdef WOLFSSL_HASH_FLAGS + if (p == WC_SHA3_256_COUNT && sha3->flags & WC_HASH_SHA3_KECCAK256) { + padChar = 0x01; + } +#endif + sha3->t[ sha3->i] = padChar; + 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 wc_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(wc_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 wc_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(wc_Sha3* sha3, const byte* data, word32 len, byte p) +{ + int ret; + + 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) && defined(QAT_V2) + /* QAT only supports SHA3_256 */ + if (p == WC_SHA3_256_COUNT) { + ret = IntelQaSymSha3(&sha3->asyncDev, NULL, data, len); + if (ret != NOT_COMPILED_IN) + return ret; + /* fall-through when unavailable */ + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha3Update(sha3, data, len, p); + + return ret; +} + +/* Calculate the SHA-3 hash based on all the message data seen. + * + * sha3 wc_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(wc_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) && defined(QAT_V2) + /* QAT only supports SHA3_256 */ + /* QAT SHA-3 only supported on v2 (8970 or later cards) */ + if (len == WC_SHA3_256_DIGEST_SIZE) { + ret = IntelQaSymSha3(&sha3->asyncDev, hash, NULL, len); + if (ret != NOT_COMPILED_IN) + return ret; + /* fall-through when unavailable */ + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha3Final(sha3, 0x06, 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 wc_Sha3 object holding state. + * returns 0 on success. + */ +static void wc_Sha3Free(wc_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 */ +} + + +/* Copy the state of the SHA3 operation. + * + * src wc_Sha3 object holding state top copy. + * dst wc_Sha3 object to copy into. + * returns 0 on success. + */ +static int wc_Sha3Copy(wc_Sha3* src, wc_Sha3* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha3)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; +#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 wc_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(wc_Sha3* sha3, byte* hash, byte p, byte len) +{ + int ret; + wc_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 wc_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. + */ +int wc_InitSha3_224(wc_Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +/* Update the SHA3-224 hash state with message data. + * + * sha3 wc_Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +int wc_Sha3_224_Update(wc_Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, WC_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 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 28 bytes. + * returns 0 on success. + */ +int wc_Sha3_224_Final(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, WC_SHA3_224_COUNT, WC_SHA3_224_DIGEST_SIZE); +} + +/* Dispose of any dynamically allocated data from the SHA3-224 operation. + * (Required for async ops.) + * + * sha3 wc_Sha3 object holding state. + * returns 0 on success. + */ +void wc_Sha3_224_Free(wc_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 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 28 bytes. + * returns 0 on success. + */ +int wc_Sha3_224_GetHash(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, WC_SHA3_224_COUNT, WC_SHA3_224_DIGEST_SIZE); +} + +/* Copy the state of the SHA3-224 operation. + * + * src wc_Sha3 object holding state top copy. + * dst wc_Sha3 object to copy into. + * returns 0 on success. + */ +int wc_Sha3_224_Copy(wc_Sha3* src, wc_Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +/* Initialize the state for a SHA3-256 hash operation. + * + * sha3 wc_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. + */ +int wc_InitSha3_256(wc_Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +/* Update the SHA3-256 hash state with message data. + * + * sha3 wc_Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +int wc_Sha3_256_Update(wc_Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, WC_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 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 32 bytes. + * returns 0 on success. + */ +int wc_Sha3_256_Final(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, WC_SHA3_256_COUNT, WC_SHA3_256_DIGEST_SIZE); +} + +/* Dispose of any dynamically allocated data from the SHA3-256 operation. + * (Required for async ops.) + * + * sha3 wc_Sha3 object holding state. + * returns 0 on success. + */ +void wc_Sha3_256_Free(wc_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 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 32 bytes. + * returns 0 on success. + */ +int wc_Sha3_256_GetHash(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, WC_SHA3_256_COUNT, WC_SHA3_256_DIGEST_SIZE); +} + +/* Copy the state of the SHA3-256 operation. + * + * src wc_Sha3 object holding state top copy. + * dst wc_Sha3 object to copy into. + * returns 0 on success. + */ +int wc_Sha3_256_Copy(wc_Sha3* src, wc_Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +/* Initialize the state for a SHA3-384 hash operation. + * + * sha3 wc_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. + */ +int wc_InitSha3_384(wc_Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +/* Update the SHA3-384 hash state with message data. + * + * sha3 wc_Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +int wc_Sha3_384_Update(wc_Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, WC_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 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 48 bytes. + * returns 0 on success. + */ +int wc_Sha3_384_Final(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, WC_SHA3_384_COUNT, WC_SHA3_384_DIGEST_SIZE); +} + +/* Dispose of any dynamically allocated data from the SHA3-384 operation. + * (Required for async ops.) + * + * sha3 wc_Sha3 object holding state. + * returns 0 on success. + */ +void wc_Sha3_384_Free(wc_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 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 48 bytes. + * returns 0 on success. + */ +int wc_Sha3_384_GetHash(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, WC_SHA3_384_COUNT, WC_SHA3_384_DIGEST_SIZE); +} + +/* Copy the state of the SHA3-384 operation. + * + * src wc_Sha3 object holding state top copy. + * dst wc_Sha3 object to copy into. + * returns 0 on success. + */ +int wc_Sha3_384_Copy(wc_Sha3* src, wc_Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +/* Initialize the state for a SHA3-512 hash operation. + * + * sha3 wc_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. + */ +int wc_InitSha3_512(wc_Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +/* Update the SHA3-512 hash state with message data. + * + * sha3 wc_Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +int wc_Sha3_512_Update(wc_Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, WC_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 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 64 bytes. + * returns 0 on success. + */ +int wc_Sha3_512_Final(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, WC_SHA3_512_COUNT, WC_SHA3_512_DIGEST_SIZE); +} + +/* Dispose of any dynamically allocated data from the SHA3-512 operation. + * (Required for async ops.) + * + * sha3 wc_Sha3 object holding state. + * returns 0 on success. + */ +void wc_Sha3_512_Free(wc_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 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 64 bytes. + * returns 0 on success. + */ +int wc_Sha3_512_GetHash(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, WC_SHA3_512_COUNT, WC_SHA3_512_DIGEST_SIZE); +} + +/* Copy the state of the SHA3-512 operation. + * + * src wc_Sha3 object holding state top copy. + * dst wc_Sha3 object to copy into. + * returns 0 on success. + */ +int wc_Sha3_512_Copy(wc_Sha3* src, wc_Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Sha3_SetFlags(wc_Sha3* sha3, word32 flags) +{ + if (sha3) { + sha3->flags = flags; + } + return 0; +} +int wc_Sha3_GetFlags(wc_Sha3* sha3, word32* flags) +{ + if (sha3 && flags) { + *flags = sha3->flags; + } + return 0; +} +#endif + +#if defined(WOLFSSL_SHAKE256) +/* Initialize the state for a Shake256 hash operation. + * + * shake wc_Shake object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ +int wc_InitShake256(wc_Shake* shake, void* heap, int devId) +{ + return wc_InitSha3(shake, heap, devId); +} + +/* Update the SHAKE256 hash state with message data. + * + * shake wc_Shake object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +int wc_Shake256_Update(wc_Shake* shake, const byte* data, word32 len) +{ + if (shake == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + return Sha3Update(shake, data, len, WC_SHA3_256_COUNT); +} + +/* Calculate the SHAKE256 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * shake wc_Shake object holding state. + * hash Buffer to hold the hash result. Must be at least 64 bytes. + * returns 0 on success. + */ +int wc_Shake256_Final(wc_Shake* shake, byte* hash, word32 hashLen) +{ + int ret; + + if (shake == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = Sha3Final(shake, 0x1f, hash, WC_SHA3_256_COUNT, hashLen); + if (ret != 0) + return ret; + + return InitSha3(shake); /* reset state */ +} + +/* Dispose of any dynamically allocated data from the SHAKE256 operation. + * (Required for async ops.) + * + * shake wc_Shake object holding state. + * returns 0 on success. + */ +void wc_Shake256_Free(wc_Shake* shake) +{ + wc_Sha3Free(shake); +} + +/* Copy the state of the SHA3-512 operation. + * + * src wc_Shake object holding state top copy. + * dst wc_Shake object to copy into. + * returns 0 on success. + */ +int wc_Shake256_Copy(wc_Shake* src, wc_Shake* dst) +{ + return wc_Sha3Copy(src, dst); +} +#endif + +#endif /* WOLFSSL_SHA3 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha512.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha512.c index 8e52da909..0a648bf4a 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha512.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha512.c @@ -1,8 +1,8 @@ /* sha512.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,337 +16,187 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif #include + +#if (defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)) && !defined(WOLFSSL_ARMASM) + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$k") + #pragma const_seg(".fipsB$k") + #endif +#endif + #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); -} - - -int wc_Sha512Hash(const byte* data, word32 len, byte* out) -{ - return Sha512Hash(data, len, 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); -} - - -int wc_Sha384Hash(const byte* data, word32 len, byte* out) -{ - return Sha384Hash(data, len, 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 */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + + #ifdef WOLFSSL_SHA512 + + 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 */ + } + #endif + + #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 fips, or for FIPS v2 */ + +#include #ifdef NO_INLINE #include #else + #define WOLFSSL_MISC_INCLUDED #include #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - #if defined(USE_INTEL_SPEEDUP) - #define HAVE_INTEL_AVX1 - #define HAVE_INTEL_AVX2 -#endif + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #undef NO_AVX2_SUPPORT + #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 -#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 + #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 - + #define HAVE_INTEL_RORX + /* #define DEBUG_YMM */ #endif -#if defnied(HAVE_INTEL_AVX1) - - int Transform_AVX1() { - Stitched Message Sched/Round - } - +#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 defnied(HAVE_INTEL_AVX2) - - int Transform_AVX2() { - Stitched Message Sched/Round - } -#endif +#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) + /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */ - -*/ - -#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) +#ifdef WOLFSSL_SHA512 - #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(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) ; - } - return 0 ; -} - -#define CHECK_SHA512 0x1 -#define CHECK_SHA384 0x2 - -static int set_cpuid_flags(int sha) { - if((cpuid_check & sha) ==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 |= sha ; - 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) ; -#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(CHECK_SHA512)) 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); @@ -359,98 +209,311 @@ 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 */ + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + + sha512->ctx.sha_type = SHA2_512; + /* always start firstblock = 1 when using hw engine */ + sha512->ctx.isfirstblock = 1; + if(sha512->ctx.mode == ESP32_SHA_HW) { + /* release hw */ + esp_sha_hw_unlock(); + } + /* always set mode as INIT + * whether using HW or SW is determined at first call of update() + */ + sha512->ctx.mode = ESP32_SHA_INIT; #endif - - return 0 ; +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + sha512->flags = 0; +#endif + return 0; } +#endif /* WOLFSSL_SHA512 */ + +/* Hardware Acceleration */ +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + +#ifdef WOLFSSL_SHA512 + + /***** + 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 + */ + +#ifdef __cplusplus + extern "C" { +#endif + + #if defined(HAVE_INTEL_AVX1) + extern int Transform_Sha512_AVX1(wc_Sha512 *sha512); + extern int Transform_Sha512_AVX1_Len(wc_Sha512 *sha512, word32 len); + #endif + #if defined(HAVE_INTEL_AVX2) + extern int Transform_Sha512_AVX2(wc_Sha512 *sha512); + extern int Transform_Sha512_AVX2_Len(wc_Sha512 *sha512, word32 len); + #if defined(HAVE_INTEL_RORX) + extern int Transform_Sha512_AVX1_RORX(wc_Sha512 *sha512); + extern int Transform_Sha512_AVX1_RORX_Len(wc_Sha512 *sha512, + word32 len); + extern int Transform_Sha512_AVX2_RORX(wc_Sha512 *sha512); + extern int Transform_Sha512_AVX2_RORX_Len(wc_Sha512 *sha512, + word32 len); + #endif + #endif + +#ifdef __cplusplus + } /* extern "C" */ +#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; + } +#endif /* WOLFSSL_SHA512 */ + +#else + #define Transform_Sha512(sha512) _Transform_Sha512(sha512) + +#endif + +#ifdef WOLFSSL_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(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + Sha512_SetTransform(); +#endif + +#ifdef WOLFSSL_SMALL_STACK_CACHE + sha512->W = NULL; +#endif + +#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 /* WOLFSSL_SHA512 */ + 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)) -#define blk384(i) (W[i] = sha384->buffer[i]) - -#define R2(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk384(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 +#ifdef WOLFSSL_SMALL_STACK_CACHE + word64* W = sha512->W; + if (W == NULL) { + W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (W == NULL) + return MEMORY_E; + sha512->W = W; + } +#elif defined(WOLFSSL_SMALL_STACK) word64* W; W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (W == NULL) @@ -462,11 +525,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); } @@ -479,10 +542,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); @@ -496,7 +558,7 @@ static int _Transform(Sha512* sha512) ForceZero(W, sizeof(word64) * 16); ForceZero(T, sizeof(T)); -#ifdef WOLFSSL_SMALL_STACK +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE) XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -504,875 +566,350 @@ static int _Transform(Sha512* sha512) } -static INLINE void AddLength(Sha512* sha512, word32 len) +static WC_INLINE void AddLength(wc_Sha512* sha512, word32 len) { - word32 tmp = sha512->loLen; + word64 tmp = sha512->loLen; if ( (sha512->loLen += len) < tmp) sha512->hiLen++; /* carry low to high */ } -int wc_Sha512Update(Sha512* sha512, const byte* data, word32 len) +static WC_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); - XMEMCPY(&local[sha512->buffLen], data, add); + /* check that internal buffLen is valid */ + if (sha512->buffLen >= WC_SHA512_BLOCK_SIZE) + return BUFFER_E; - sha512->buffLen += add; - data += add; - len -= add; + AddLength(sha512, len); - 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; + if (sha512->buffLen > 0) { + word32 add = min(len, WC_SHA512_BLOCK_SIZE - sha512->buffLen); + if (add > 0) { + XMEMCPY(&local[sha512->buffLen], data, add); - AddLength(sha512, SHA512_BLOCK_SIZE); - sha512->buffLen = 0; + sha512->buffLen += add; + data += add; + len -= add; + } + + 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 + { + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ByteReverseWords64(sha512->buffer, sha512->buffer, + WC_SHA512_BLOCK_SIZE); + #endif + } + #endif + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ret = Transform_Sha512(sha512); + #else + if(sha512->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha512->ctx); + } + ret = esp_sha512_process(sha512); + if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){ + ret = Transform_Sha512(sha512); + } + #endif + if (ret == 0) + 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) { + 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(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + { + while (len >= WC_SHA512_BLOCK_SIZE) { + XMEMCPY(local, data, WC_SHA512_BLOCK_SIZE); + + data += WC_SHA512_BLOCK_SIZE; + len -= WC_SHA512_BLOCK_SIZE; + + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + { + ByteReverseWords64(sha512->buffer, sha512->buffer, + WC_SHA512_BLOCK_SIZE); + } + #endif + /* Byte reversal performed in function if required. */ + ret = Transform_Sha512(sha512); + if (ret != 0) + break; + } + } +#else + { + while (len >= WC_SHA512_BLOCK_SIZE) { + XMEMCPY(local, data, WC_SHA512_BLOCK_SIZE); + + data += WC_SHA512_BLOCK_SIZE; + len -= WC_SHA512_BLOCK_SIZE; + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ByteReverseWords64(sha512->buffer, sha512->buffer, + WC_SHA512_BLOCK_SIZE); + #endif + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ret = Transform_Sha512(sha512); + #else + if(sha512->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha512->ctx); + } + ret = esp_sha512_process(sha512); + if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){ + ret = Transform_Sha512(sha512); + } + #endif + if (ret != 0) + break; + } + } +#endif + + if (len > 0) { + XMEMCPY(local, data, len); + sha512->buffLen = len; + } + + return ret; } +#ifdef WOLFSSL_SHA512 -int wc_Sha512Final(Sha512* sha512, byte* hash) +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); +} + +#endif /* WOLFSSL_SHA512 */ + +#endif /* WOLFSSL_IMX6_CAAM */ + +static WC_INLINE int Sha512Final(wc_Sha512* sha512) { byte* local = (byte*)sha512->buffer; int ret; - SAVE_XMM_YMM ; /* for Intel AVX */ - AddLength(sha512, sha512->buffLen); /* before adding pads */ + if (sha512 == NULL) { + return BAD_FUNC_ARG; + } 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 + { + + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ByteReverseWords64(sha512->buffer,sha512->buffer, + WC_SHA512_BLOCK_SIZE); + #endif + } +#endif /* LITTLE_ENDIAN_ORDER */ +#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ret = Transform_Sha512(sha512); +#else + if(sha512->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha512->ctx); + } + ret = esp_sha512_process(sha512); + if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){ + ret = Transform_Sha512(sha512); + } +#endif 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 + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ByteReverseWords64(sha512->buffer, sha512->buffer, WC_SHA512_PAD_SIZE); + #endif +#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); +#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen; + sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen; +#endif + +#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 +#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ret = Transform_Sha512(sha512); +#else + if(sha512->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha512->ctx); + } + ret = esp_sha512_digest_process(sha512, 1); + if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW) { + ret = Transform_Sha512(sha512); + } +#endif 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 - XMEMCPY(hash, sha512->digest, SHA512_DIGEST_SIZE); - return wc_InitSha512(sha512); /* reset state */ + return 0; } +#ifdef WOLFSSL_SHA512 -int wc_Sha512Hash(const byte* data, word32 len, byte* hash) +int wc_Sha512FinalRaw(wc_Sha512* sha512, byte* hash) { - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha512* sha512; -#else - Sha512 sha512[1]; +#ifdef LITTLE_ENDIAN_ORDER + word64 digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)]; #endif -#ifdef WOLFSSL_SMALL_STACK - sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha512 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64((word64*)digest, (word64*)sha512->digest, + WC_SHA512_DIGEST_SIZE); + XMEMCPY(hash, digest, WC_SHA512_DIGEST_SIZE); +#else + XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE); +#endif + + return 0; +} + +int wc_Sha512Final(wc_Sha512* sha512, byte* hash) +{ + 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, WC_SHA512_DIGEST_SIZE); + + 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 MEMORY_E; + return; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (sha512->W != NULL) { + XFREE(sha512->W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha512->W = NULL; + } #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"); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; + +#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)); - -#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 - -#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 - -#if defined(HAVE_INTEL_AVX1) /* inline Assember for Intel AVX1 instructions */ -#if defined(DEBUG_XMM) - -#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 _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 DUMP_REG(REG) _DUMP_REG(REG, #REG) -#define PRINTF(fmt, ...) - -#else - -#define DUMP_REG(REG) -#define PRINTF(fmt, ...) - -#endif - -#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 _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 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 - - -/*** Transform Body ***/ -#if defined(HAVE_INTEL_AVX1) - -static int Transform_AVX1(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)); - - 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); - } - - /* Add the working vars back into 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); - - /* Wipe variables */ - #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) - XMEMSET(W_X, 0, sizeof(word64) * 16); - #endif - XMEMSET(T, 0, sizeof(T)); - - return 0; -} - -#endif - -#if defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_RORX) - -static int Transform_AVX1_RORX(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)); - - 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 */ - - 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); - - /* Wipe variables */ - #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) - XMEMSET(W_X, 0, sizeof(word64) * 16); - #endif - XMEMSET(T, 0, sizeof(T)); - - return 0; -} -#endif - -#if defined(HAVE_INTEL_AVX2) - -#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 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 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 blk384(i) (W[i] = sha384->buffer[i]) - - -#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 Block_Y_xx_2(i, w_0, w_4, w_8, w_12)\ - s0_1y (YMM_TEMP0, W_I_15y) ;\ - -#define Block_Y_xx_3(i, w_0, w_4, w_8, w_12)\ - s0_2y (YMM_TEMP0, W_I_15y) ;\ - -#define Block_Y_xx_4(i, w_0, w_4, w_8, w_12)\ - s0_3y (YMM_TEMP0, W_I_15y) ;\ - -#define Block_Y_xx_5(i, w_0, w_4, w_8, w_12)\ - ADDy(W_I_TEMPy, w_0, YMM_TEMP0) ;\ - -#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 Block_Y_xx_7(i, w_0, w_4, w_8, w_12)\ - s1_2y (YMM_TEMP0, W_I_2y) ;\ - -#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) ;\ - -#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 Block_Y_xx_10(i, w_0, w_4, w_8, w_12) \ - s1_1y (YMM_TEMP0, W_I_2y) ;\ - -#define Block_Y_xx_11(i, w_0, w_4, w_8, w_12) \ - s1_2y (YMM_TEMP0, W_I_2y) ;\ - -#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 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) -{ - const word64* K = K512; - word64 w[4] ; - word32 j /*, k*/; - word64 T[8]; - /* Copy digest to working vars */ - XMEMCPY(T, sha512->digest, sizeof(T)); - - 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 */ - - 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); - - /* Wipe variables */ - #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) - XMEMSET(W, 0, sizeof(word64) * 16); - #endif - XMEMSET(T, 0, sizeof(T)); - - return 0; -} - -#endif - +#endif /* WOLFSSL_SHA512 */ +/* -------------------------------------------------------------------------- */ +/* SHA384 */ +/* -------------------------------------------------------------------------- */ #ifdef WOLFSSL_SHA384 -#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - -#if defined(HAVE_INTEL_AVX1) -static int Transform384_AVX1(Sha384 *sha384) ; -#endif -#if defined(HAVE_INTEL_AVX2) -static int Transform384_AVX2(Sha384 *sha384) ; -#endif - -#if defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_AVX2) &&defined(HAVE_INTEL_RORX) -static int Transform384_AVX1_RORX(Sha384 *sha384) ; -#endif - -static int _Transform384(Sha384 *sha384) ; -static int (*Transform384_p)(Sha384* sha384) = _Transform384 ; - -#define Transform384(sha384) (*Transform384_p)(sha384) -static void set_Transform384(void) { - if(set_cpuid_flags(CHECK_SHA384))return ; - -#if defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2) - Transform384_p = ((IS_INTEL_AVX1) ? Transform384_AVX1 : _Transform384) ; -#elif defined(HAVE_INTEL_AVX2) - #if defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_RORX) - if(IS_INTEL_AVX2 && IS_INTEL_BMI2) { Transform384_p = Transform384_AVX1_RORX ; return ; } - #endif - if(IS_INTEL_AVX2) { Transform384_p = Transform384_AVX2 ; return ; } - #if defined(HAVE_INTEL_AVX1) - Transform384_p = ((IS_INTEL_AVX1) ? Transform384_AVX1 : _Transform384) ; - #endif -#else - Transform384_p = ((IS_INTEL_AVX1) ? Transform384_AVX1 : _Transform384) ; -#endif -} +#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) + /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */ #else - #define Transform384(sha512) _Transform384(sha512) -#endif -int wc_InitSha384(Sha384* 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); @@ -1386,420 +923,303 @@ int wc_InitSha384(Sha384* sha384) sha384->loLen = 0; sha384->hiLen = 0; -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - set_Transform384() ; +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha384->ctx.sha_type = SHA2_384; + /* always start firstblock = 1 when using hw engine */ + sha384->ctx.isfirstblock = 1; + if(sha384->ctx.mode == ESP32_SHA_HW) { + /* release hw */ + esp_sha_hw_unlock(); + } + /* always set mode as INIT + * whether using HW or SW is determined at first call of update() + */ + sha384->ctx.mode = ESP32_SHA_INIT; + #endif - +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + sha384->flags = 0; +#endif + return 0; } -static int _Transform384(Sha384* sha384) +int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len) { - const word64* K = K512; + if (sha384 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } - word32 j; - word64 T[8]; +#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 */ -#ifdef WOLFSSL_SMALL_STACK - word64* W; + return Sha512Update((wc_Sha512*)sha384, data, len); +} - W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (W == NULL) - return MEMORY_E; + +int wc_Sha384FinalRaw(wc_Sha384* sha384, byte* hash) +{ +#ifdef LITTLE_ENDIAN_ORDER + word64 digest[WC_SHA384_DIGEST_SIZE / sizeof(word64)]; +#endif + + if (sha384 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64((word64*)digest, (word64*)sha384->digest, + WC_SHA384_DIGEST_SIZE); + XMEMCPY(hash, digest, WC_SHA384_DIGEST_SIZE); #else - word64 W[16]; -#endif - - /* Copy digest to working vars */ - XMEMCPY(T, sha384->digest, sizeof(T)); - -#ifdef USE_SLOW_SHA2 - /* over twice as small, but 50% slower */ - /* 80 operations, not unrolled */ - for (j = 0; j < 80; j += 16) { - int m; - for (m = 0; m < 16; m++) { /* braces needed for macros {} */ - R2(m); - } - } -#else - /* 80 operations, partially loop unrolled */ - for (j = 0; j < 80; j += 16) { - R2( 0); R2( 1); R2( 2); R2( 3); - R2( 4); R2( 5); R2( 6); R2( 7); - R2( 8); R2( 9); R2(10); R2(11); - R2(12); R2(13); R2(14); R2(15); - } -#endif /* USE_SLOW_SHA2 */ - - /* Add the working vars back into digest */ - - sha384->digest[0] += a(0); - sha384->digest[1] += b(0); - sha384->digest[2] += c(0); - sha384->digest[3] += d(0); - sha384->digest[4] += e(0); - sha384->digest[5] += f(0); - sha384->digest[6] += g(0); - sha384->digest[7] += h(0); - - /* Wipe variables */ - XMEMSET(W, 0, sizeof(word64) * 16); - XMEMSET(T, 0, sizeof(T)); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE); #endif return 0; } -static INLINE void AddLength384(Sha384* sha384, word32 len) +int wc_Sha384Final(wc_Sha384* sha384, byte* hash) { - word32 tmp = sha384->loLen; - if ( (sha384->loLen += len) < tmp) - sha384->hiLen++; /* carry low to high */ -} - -int wc_Sha384Update(Sha384* sha384, const byte* data, word32 len) -{ - /* do block size increments */ - byte* local = (byte*)sha384->buffer; - - SAVE_XMM_YMM ; /* for Intel AVX */ - - while (len) { - word32 add = min(len, SHA384_BLOCK_SIZE - sha384->buffLen); - XMEMCPY(&local[sha384->buffLen], data, add); - - sha384->buffLen += add; - data += add; - len -= add; - - if (sha384->buffLen == SHA384_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(sha384->buffer, sha384->buffer, - SHA384_BLOCK_SIZE); - #endif - ret = Transform384(sha384); - if (ret != 0) - return ret; - - AddLength384(sha384, SHA384_BLOCK_SIZE); - sha384->buffLen = 0; - } - } - return 0; -} - - -int wc_Sha384Final(Sha384* sha384, byte* hash) -{ - byte* local = (byte*)sha384->buffer; int ret; - SAVE_XMM_YMM ; /* for Intel AVX */ - AddLength384(sha384, sha384->buffLen); /* before adding pads */ - - local[sha384->buffLen++] = 0x80; /* add 1 */ - - /* pad with zeros */ - if (sha384->buffLen > SHA384_PAD_SIZE) { - XMEMSET(&local[sha384->buffLen], 0, SHA384_BLOCK_SIZE -sha384->buffLen); - sha384->buffLen += SHA384_BLOCK_SIZE - sha384->buffLen; - - #if defined(LITTLE_ENDIAN_ORDER) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords64(sha384->buffer, sha384->buffer, - SHA384_BLOCK_SIZE); - #endif - ret = Transform384(sha384); - if (ret != 0) - return ret; - - sha384->buffLen = 0; + if (sha384 == NULL || hash == NULL) { + return BAD_FUNC_ARG; } - XMEMSET(&local[sha384->buffLen], 0, SHA384_PAD_SIZE - sha384->buffLen); - - /* put lengths in bits */ - sha384->hiLen = (sha384->loLen >> (8*sizeof(sha384->loLen) - 3)) + - (sha384->hiLen << 3); - sha384->loLen = sha384->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(sha384->buffer, sha384->buffer, - SHA384_BLOCK_SIZE); +#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 - /* ! length ordering dependent on digest endian type ! */ - sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2] = sha384->hiLen; - sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 1] = sha384->loLen; - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX1 || IS_INTEL_AVX2) - ByteReverseWords64(&(sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2]), - &(sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2]), - SHA384_BLOCK_SIZE - SHA384_PAD_SIZE); - #endif - ret = Transform384(sha384); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha512Final((wc_Sha512*)sha384); if (ret != 0) return ret; - #ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords64(sha384->digest, sha384->digest, SHA384_DIGEST_SIZE); - #endif - 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 */ } - -int wc_Sha384Hash(const byte* data, word32 len, byte* hash) +int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId) { - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha384* sha384; + int ret; + + if (sha384 == NULL) { + return BAD_FUNC_ARG; + } + + sha384->heap = heap; + ret = InitSha384(sha384); + if (ret != 0) + return ret; + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + Sha512_SetTransform(); +#endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + sha384->W = NULL; +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + ret = wolfAsync_DevCtxInit(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384, + sha384->heap, devId); #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 + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ return ret; } -#if defined(HAVE_INTEL_AVX1) - -static int Transform384_AVX1(Sha384* sha384) +#endif /* WOLFSSL_IMX6_CAAM */ + +int wc_InitSha384(wc_Sha384* sha384) { - const word64* K = K512; - word64 W_X[16+4]; - word32 j; - word64 T[8]; - - /* Copy digest to working vars */ - XMEMCPY(T, sha384->digest, sizeof(T)); - W_from_buff(W_X, sha384->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); - } - - /* Add the working vars back into digest */ - - sha384->digest[0] += a(0); - sha384->digest[1] += b(0); - sha384->digest[2] += c(0); - sha384->digest[3] += d(0); - sha384->digest[4] += e(0); - sha384->digest[5] += f(0); - sha384->digest[6] += g(0); - sha384->digest[7] += h(0); - - /* Wipe variables */ - #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) - XMEMSET(W, 0, sizeof(word64) * 16); - #endif - XMEMSET(T, 0, sizeof(T)); - - return 0; + return wc_InitSha384_ex(sha384, NULL, INVALID_DEVID); } -#endif - -#if defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_RORX) -static int Transform384_AVX1_RORX(Sha384* sha384) +void wc_Sha384Free(wc_Sha384* sha384) { - const word64* K = K512; - word64 W_X[16+4]; - word32 j; - word64 T[8]; + if (sha384 == NULL) + return; - /* Copy digest to working vars */ - XMEMCPY(T, sha384->digest, sizeof(T)); - - W_from_buff(W_X, sha384->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); +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (sha384->W != NULL) { + XFREE(sha384->W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha384->W = NULL; } - - /* Add the working vars back into digest */ - - sha384->digest[0] += a(0); - sha384->digest[1] += b(0); - sha384->digest[2] += c(0); - sha384->digest[3] += d(0); - sha384->digest[4] += e(0); - sha384->digest[5] += f(0); - sha384->digest[6] += g(0); - sha384->digest[7] += h(0); - - /* Wipe variables */ - #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) - XMEMSET(W, 0, sizeof(word64) * 16); - #endif - XMEMSET(T, 0, sizeof(T)); - - return 0; -} #endif -#if defined(HAVE_INTEL_AVX2) - -static int Transform384_AVX2(Sha384* sha384) -{ - const word64* K = K512; - word64 w[4] ; - word32 j; - word64 T[8]; - - /* Copy digest to working vars */ - XMEMCPY(T, sha384->digest, sizeof(T)); - - /* over twice as small, but 50% slower */ - /* 80 operations, not unrolled */ - - W_from_buff_Y(sha384->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 */ - - sha384->digest[0] += a(0); - sha384->digest[1] += b(0); - sha384->digest[2] += c(0); - sha384->digest[3] += d(0); - sha384->digest[4] += e(0); - sha384->digest[5] += f(0); - sha384->digest[6] += g(0); - sha384->digest[7] += h(0); - - /* Wipe variables */ - XMEMSET(T, 0, sizeof(T)); - - return 0; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + wolfAsync_DevCtxFree(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384); +#endif /* WOLFSSL_ASYNC_CRYPT */ } -#endif - #endif /* WOLFSSL_SHA384 */ #endif /* HAVE_FIPS */ +#ifdef WOLFSSL_SHA512 + +int wc_Sha512GetHash(wc_Sha512* sha512, byte* hash) +{ + int ret; + wc_Sha512 tmpSha512; + + if (sha512 == NULL || hash == NULL) + return BAD_FUNC_ARG; + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if(sha512->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha512->ctx); + } + if(sha512->ctx.mode != ESP32_SHA_SW) + esp_sha512_digest_process(sha512, 0); +#endif + + ret = wc_Sha512Copy(sha512, &tmpSha512); + if (ret == 0) { + ret = wc_Sha512Final(&tmpSha512, hash); +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha512->ctx.mode = ESP32_SHA_SW;; +#endif + wc_Sha512Free(&tmpSha512); + } + 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_SMALL_STACK_CACHE + dst->W = NULL; +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + dst->ctx.mode = src->ctx.mode; + dst->ctx.isfirstblock = src->ctx.isfirstblock; + dst->ctx.sha_type = src->ctx.sha_type; +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + + return ret; +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Sha512SetFlags(wc_Sha512* sha512, word32 flags) +{ + if (sha512) { + sha512->flags = flags; + } + return 0; +} +int wc_Sha512GetFlags(wc_Sha512* sha512, word32* flags) +{ + if (sha512 && flags) { + *flags = sha512->flags; + } + return 0; +} +#endif + #endif /* WOLFSSL_SHA512 */ +#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; +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if(sha384->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha384->ctx); + } + if(sha384->ctx.mode != ESP32_SHA_SW) { + esp_sha512_digest_process(sha384, 0); + } +#endif + ret = wc_Sha384Copy(sha384, &tmpSha384); + if (ret == 0) { + ret = wc_Sha384Final(&tmpSha384, hash); +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha384->ctx.mode = ESP32_SHA_SW; +#endif + wc_Sha384Free(&tmpSha384); + } + 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_SMALL_STACK_CACHE + dst->W = NULL; +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + dst->ctx.mode = src->ctx.mode; + dst->ctx.isfirstblock = src->ctx.isfirstblock; + dst->ctx.sha_type = src->ctx.sha_type; +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + + return ret; +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Sha384SetFlags(wc_Sha384* sha384, word32 flags) +{ + if (sha384) { + sha384->flags = flags; + } + return 0; +} +int wc_Sha384GetFlags(wc_Sha384* sha384, word32* flags) +{ + if (sha384 && flags) { + *flags = sha384->flags; + } + return 0; +} +#endif + +#endif /* WOLFSSL_SHA384 */ + +#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha512_asm.S b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha512_asm.S new file mode 100644 index 000000000..6a27ce42a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sha512_asm.S @@ -0,0 +1,10741 @@ +/* sha512_asm + * + * Copyright (C) 2006-2020 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 HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX1 +#endif /* HAVE_INTEL_AVX1 */ +#ifndef NO_AVX2_SUPPORT +#define HAVE_INTEL_AVX2 +#endif /* NO_AVX2_SUPPORT */ + +#ifdef HAVE_INTEL_AVX1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_sha512_k: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_sha512_flip_mask: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX1 +.type Transform_Sha512_AVX1,@function +.align 4 +Transform_Sha512_AVX1: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX1 +.p2align 2 +_Transform_Sha512_AVX1: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x88, %rsp + leaq 64(%rdi), %rax + vmovdqa L_avx1_sha512_flip_mask(%rip), %xmm14 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vpshufb %xmm14, %xmm0, %xmm0 + vpshufb %xmm14, %xmm1, %xmm1 + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vpshufb %xmm14, %xmm2, %xmm2 + vpshufb %xmm14, %xmm3, %xmm3 + vmovdqu 64(%rax), %xmm4 + vmovdqu 80(%rax), %xmm5 + vpshufb %xmm14, %xmm4, %xmm4 + vpshufb %xmm14, %xmm5, %xmm5 + vmovdqu 96(%rax), %xmm6 + vmovdqu 112(%rax), %xmm7 + vpshufb %xmm14, %xmm6, %xmm6 + vpshufb %xmm14, %xmm7, %xmm7 + movl $4, 128(%rsp) + leaq L_avx1_sha512_k(%rip), %rsi + movq %r9, %rbx + movq %r12, %rax + xorq %r10, %rbx + # Start of 16 rounds +L_sha256_len_avx1_start: + vpaddq (%rsi), %xmm0, %xmm8 + vpaddq 16(%rsi), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rsi), %xmm2, %xmm8 + vpaddq 48(%rsi), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rsi), %xmm4, %xmm8 + vpaddq 80(%rsi), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rsi), %xmm6, %xmm8 + vpaddq 112(%rsi), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + addq $0x80, %rsi + # msg_sched: 0-1 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm0, %xmm1, %xmm12 + vpalignr $8, %xmm4, %xmm5, %xmm13 + # rnd_0: 1 - 1 + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm0, %xmm13, %xmm0 + # rnd_0: 10 - 11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm0, %xmm8, %xmm0 + # rnd_1: 1 - 1 + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + vpsrlq $19, %xmm7, %xmm8 + vpsllq $45, %xmm7, %xmm9 + # rnd_1: 2 - 3 + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + vpsrlq $61, %xmm7, %xmm10 + vpsllq $3, %xmm7, %xmm11 + # rnd_1: 4 - 6 + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm7, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + vpaddq %xmm0, %xmm8, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 2-3 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm1, %xmm2, %xmm12 + vpalignr $8, %xmm5, %xmm6, %xmm13 + # rnd_0: 1 - 1 + movq %r14, %rdx + movq %r11, %rcx + addq 16(%rsp), %r13 + xorq %r12, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm1, %xmm13, %xmm1 + # rnd_0: 10 - 11 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm1, %xmm8, %xmm1 + # rnd_1: 1 - 1 + movq %r13, %rbx + movq %r10, %rcx + addq 24(%rsp), %r12 + xorq %r11, %rcx + vpsrlq $19, %xmm0, %xmm8 + vpsllq $45, %xmm0, %xmm9 + # rnd_1: 2 - 3 + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + vpsrlq $61, %xmm0, %xmm10 + vpsllq $3, %xmm0, %xmm11 + # rnd_1: 4 - 6 + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm0, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + vpaddq %xmm1, %xmm8, %xmm1 + # msg_sched done: 2-5 + # msg_sched: 4-5 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm2, %xmm3, %xmm12 + vpalignr $8, %xmm6, %xmm7, %xmm13 + # rnd_0: 1 - 1 + movq %r12, %rdx + movq %r9, %rcx + addq 32(%rsp), %r11 + xorq %r10, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm2, %xmm13, %xmm2 + # rnd_0: 10 - 11 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm2, %xmm8, %xmm2 + # rnd_1: 1 - 1 + movq %r11, %rbx + movq %r8, %rcx + addq 40(%rsp), %r10 + xorq %r9, %rcx + vpsrlq $19, %xmm1, %xmm8 + vpsllq $45, %xmm1, %xmm9 + # rnd_1: 2 - 3 + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + vpsrlq $61, %xmm1, %xmm10 + vpsllq $3, %xmm1, %xmm11 + # rnd_1: 4 - 6 + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm1, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + vpaddq %xmm2, %xmm8, %xmm2 + # msg_sched done: 4-7 + # msg_sched: 6-7 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm3, %xmm4, %xmm12 + vpalignr $8, %xmm7, %xmm0, %xmm13 + # rnd_0: 1 - 1 + movq %r10, %rdx + movq %r15, %rcx + addq 48(%rsp), %r9 + xorq %r8, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm3, %xmm13, %xmm3 + # rnd_0: 10 - 11 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm3, %xmm8, %xmm3 + # rnd_1: 1 - 1 + movq %r9, %rbx + movq %r14, %rcx + addq 56(%rsp), %r8 + xorq %r15, %rcx + vpsrlq $19, %xmm2, %xmm8 + vpsllq $45, %xmm2, %xmm9 + # rnd_1: 2 - 3 + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + vpsrlq $61, %xmm2, %xmm10 + vpsllq $3, %xmm2, %xmm11 + # rnd_1: 4 - 6 + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm2, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq %xmm3, %xmm8, %xmm3 + # msg_sched done: 6-9 + # msg_sched: 8-9 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm4, %xmm5, %xmm12 + vpalignr $8, %xmm0, %xmm1, %xmm13 + # rnd_0: 1 - 1 + movq %r8, %rdx + movq %r13, %rcx + addq 64(%rsp), %r15 + xorq %r14, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm4, %xmm13, %xmm4 + # rnd_0: 10 - 11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm4, %xmm8, %xmm4 + # rnd_1: 1 - 1 + movq %r15, %rbx + movq %r12, %rcx + addq 72(%rsp), %r14 + xorq %r13, %rcx + vpsrlq $19, %xmm3, %xmm8 + vpsllq $45, %xmm3, %xmm9 + # rnd_1: 2 - 3 + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + vpsrlq $61, %xmm3, %xmm10 + vpsllq $3, %xmm3, %xmm11 + # rnd_1: 4 - 6 + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm3, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + vpaddq %xmm4, %xmm8, %xmm4 + # msg_sched done: 8-11 + # msg_sched: 10-11 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm5, %xmm6, %xmm12 + vpalignr $8, %xmm1, %xmm2, %xmm13 + # rnd_0: 1 - 1 + movq %r14, %rdx + movq %r11, %rcx + addq 80(%rsp), %r13 + xorq %r12, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm5, %xmm13, %xmm5 + # rnd_0: 10 - 11 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm5, %xmm8, %xmm5 + # rnd_1: 1 - 1 + movq %r13, %rbx + movq %r10, %rcx + addq 88(%rsp), %r12 + xorq %r11, %rcx + vpsrlq $19, %xmm4, %xmm8 + vpsllq $45, %xmm4, %xmm9 + # rnd_1: 2 - 3 + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + vpsrlq $61, %xmm4, %xmm10 + vpsllq $3, %xmm4, %xmm11 + # rnd_1: 4 - 6 + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm4, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + vpaddq %xmm5, %xmm8, %xmm5 + # msg_sched done: 10-13 + # msg_sched: 12-13 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm6, %xmm7, %xmm12 + vpalignr $8, %xmm2, %xmm3, %xmm13 + # rnd_0: 1 - 1 + movq %r12, %rdx + movq %r9, %rcx + addq 96(%rsp), %r11 + xorq %r10, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm6, %xmm13, %xmm6 + # rnd_0: 10 - 11 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm6, %xmm8, %xmm6 + # rnd_1: 1 - 1 + movq %r11, %rbx + movq %r8, %rcx + addq 104(%rsp), %r10 + xorq %r9, %rcx + vpsrlq $19, %xmm5, %xmm8 + vpsllq $45, %xmm5, %xmm9 + # rnd_1: 2 - 3 + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + vpsrlq $61, %xmm5, %xmm10 + vpsllq $3, %xmm5, %xmm11 + # rnd_1: 4 - 6 + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm5, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + vpaddq %xmm6, %xmm8, %xmm6 + # msg_sched done: 12-15 + # msg_sched: 14-15 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm7, %xmm0, %xmm12 + vpalignr $8, %xmm3, %xmm4, %xmm13 + # rnd_0: 1 - 1 + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm7, %xmm13, %xmm7 + # rnd_0: 10 - 11 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm7, %xmm8, %xmm7 + # rnd_1: 1 - 1 + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + vpsrlq $19, %xmm6, %xmm8 + vpsllq $45, %xmm6, %xmm9 + # rnd_1: 2 - 3 + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + vpsrlq $61, %xmm6, %xmm10 + vpsllq $3, %xmm6, %xmm11 + # rnd_1: 4 - 6 + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm6, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq %xmm7, %xmm8, %xmm7 + # msg_sched done: 14-17 + subl $0x01, 128(%rsp) + jne L_sha256_len_avx1_start + vpaddq (%rsi), %xmm0, %xmm8 + vpaddq 16(%rsi), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rsi), %xmm2, %xmm8 + vpaddq 48(%rsi), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rsi), %xmm4, %xmm8 + vpaddq 80(%rsi), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rsi), %xmm6, %xmm8 + vpaddq 112(%rsi), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + # rnd_all_2: 0-1 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + # rnd_all_2: 2-3 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 16(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 24(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + # rnd_all_2: 4-5 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 32(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 40(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + # rnd_all_2: 6-7 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 48(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 56(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + # rnd_all_2: 8-9 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq 64(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 72(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + # rnd_all_2: 10-11 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 80(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 88(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + # rnd_all_2: 12-13 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 96(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 104(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + # rnd_all_2: 14-15 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + addq %r8, (%rdi) + addq %r9, 8(%rdi) + addq %r10, 16(%rdi) + addq %r11, 24(%rdi) + addq %r12, 32(%rdi) + addq %r13, 40(%rdi) + addq %r14, 48(%rdi) + addq %r15, 56(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x88, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX1,.-Transform_Sha512_AVX1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX1_Len +.type Transform_Sha512_AVX1_Len,@function +.align 4 +Transform_Sha512_AVX1_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX1_Len +.p2align 2 +_Transform_Sha512_AVX1_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + subq $0x90, %rsp + movq 224(%rdi), %rsi + leaq L_avx1_sha512_k(%rip), %rdx + vmovdqa L_avx1_sha512_flip_mask(%rip), %xmm14 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + # Start of loop processing a block +L_sha512_len_avx1_begin: + vmovdqu (%rsi), %xmm0 + vmovdqu 16(%rsi), %xmm1 + vpshufb %xmm14, %xmm0, %xmm0 + vpshufb %xmm14, %xmm1, %xmm1 + vmovdqu 32(%rsi), %xmm2 + vmovdqu 48(%rsi), %xmm3 + vpshufb %xmm14, %xmm2, %xmm2 + vpshufb %xmm14, %xmm3, %xmm3 + vmovdqu 64(%rsi), %xmm4 + vmovdqu 80(%rsi), %xmm5 + vpshufb %xmm14, %xmm4, %xmm4 + vpshufb %xmm14, %xmm5, %xmm5 + vmovdqu 96(%rsi), %xmm6 + vmovdqu 112(%rsi), %xmm7 + vpshufb %xmm14, %xmm6, %xmm6 + vpshufb %xmm14, %xmm7, %xmm7 + movl $4, 128(%rsp) + movq %r9, %rbx + movq %r12, %rax + xorq %r10, %rbx + vpaddq (%rdx), %xmm0, %xmm8 + vpaddq 16(%rdx), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rdx), %xmm2, %xmm8 + vpaddq 48(%rdx), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rdx), %xmm4, %xmm8 + vpaddq 80(%rdx), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rdx), %xmm6, %xmm8 + vpaddq 112(%rdx), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + # Start of 16 rounds +L_sha512_len_avx1_start: + addq $0x80, %rdx + movq %rdx, 136(%rsp) + # msg_sched: 0-1 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm0, %xmm1, %xmm12 + vpalignr $8, %xmm4, %xmm5, %xmm13 + # rnd_0: 1 - 1 + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm0, %xmm13, %xmm0 + # rnd_0: 10 - 11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm0, %xmm8, %xmm0 + # rnd_1: 1 - 1 + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + vpsrlq $19, %xmm7, %xmm8 + vpsllq $45, %xmm7, %xmm9 + # rnd_1: 2 - 3 + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + vpsrlq $61, %xmm7, %xmm10 + vpsllq $3, %xmm7, %xmm11 + # rnd_1: 4 - 6 + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm7, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + vpaddq %xmm0, %xmm8, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 2-3 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm1, %xmm2, %xmm12 + vpalignr $8, %xmm5, %xmm6, %xmm13 + # rnd_0: 1 - 1 + movq %r14, %rdx + movq %r11, %rcx + addq 16(%rsp), %r13 + xorq %r12, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm1, %xmm13, %xmm1 + # rnd_0: 10 - 11 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm1, %xmm8, %xmm1 + # rnd_1: 1 - 1 + movq %r13, %rbx + movq %r10, %rcx + addq 24(%rsp), %r12 + xorq %r11, %rcx + vpsrlq $19, %xmm0, %xmm8 + vpsllq $45, %xmm0, %xmm9 + # rnd_1: 2 - 3 + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + vpsrlq $61, %xmm0, %xmm10 + vpsllq $3, %xmm0, %xmm11 + # rnd_1: 4 - 6 + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm0, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + vpaddq %xmm1, %xmm8, %xmm1 + # msg_sched done: 2-5 + # msg_sched: 4-5 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm2, %xmm3, %xmm12 + vpalignr $8, %xmm6, %xmm7, %xmm13 + # rnd_0: 1 - 1 + movq %r12, %rdx + movq %r9, %rcx + addq 32(%rsp), %r11 + xorq %r10, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm2, %xmm13, %xmm2 + # rnd_0: 10 - 11 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm2, %xmm8, %xmm2 + # rnd_1: 1 - 1 + movq %r11, %rbx + movq %r8, %rcx + addq 40(%rsp), %r10 + xorq %r9, %rcx + vpsrlq $19, %xmm1, %xmm8 + vpsllq $45, %xmm1, %xmm9 + # rnd_1: 2 - 3 + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + vpsrlq $61, %xmm1, %xmm10 + vpsllq $3, %xmm1, %xmm11 + # rnd_1: 4 - 6 + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm1, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + vpaddq %xmm2, %xmm8, %xmm2 + # msg_sched done: 4-7 + # msg_sched: 6-7 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm3, %xmm4, %xmm12 + vpalignr $8, %xmm7, %xmm0, %xmm13 + # rnd_0: 1 - 1 + movq %r10, %rdx + movq %r15, %rcx + addq 48(%rsp), %r9 + xorq %r8, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm3, %xmm13, %xmm3 + # rnd_0: 10 - 11 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm3, %xmm8, %xmm3 + # rnd_1: 1 - 1 + movq %r9, %rbx + movq %r14, %rcx + addq 56(%rsp), %r8 + xorq %r15, %rcx + vpsrlq $19, %xmm2, %xmm8 + vpsllq $45, %xmm2, %xmm9 + # rnd_1: 2 - 3 + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + vpsrlq $61, %xmm2, %xmm10 + vpsllq $3, %xmm2, %xmm11 + # rnd_1: 4 - 6 + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm2, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq %xmm3, %xmm8, %xmm3 + # msg_sched done: 6-9 + # msg_sched: 8-9 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm4, %xmm5, %xmm12 + vpalignr $8, %xmm0, %xmm1, %xmm13 + # rnd_0: 1 - 1 + movq %r8, %rdx + movq %r13, %rcx + addq 64(%rsp), %r15 + xorq %r14, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm4, %xmm13, %xmm4 + # rnd_0: 10 - 11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm4, %xmm8, %xmm4 + # rnd_1: 1 - 1 + movq %r15, %rbx + movq %r12, %rcx + addq 72(%rsp), %r14 + xorq %r13, %rcx + vpsrlq $19, %xmm3, %xmm8 + vpsllq $45, %xmm3, %xmm9 + # rnd_1: 2 - 3 + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + vpsrlq $61, %xmm3, %xmm10 + vpsllq $3, %xmm3, %xmm11 + # rnd_1: 4 - 6 + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm3, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + vpaddq %xmm4, %xmm8, %xmm4 + # msg_sched done: 8-11 + # msg_sched: 10-11 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm5, %xmm6, %xmm12 + vpalignr $8, %xmm1, %xmm2, %xmm13 + # rnd_0: 1 - 1 + movq %r14, %rdx + movq %r11, %rcx + addq 80(%rsp), %r13 + xorq %r12, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm5, %xmm13, %xmm5 + # rnd_0: 10 - 11 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm5, %xmm8, %xmm5 + # rnd_1: 1 - 1 + movq %r13, %rbx + movq %r10, %rcx + addq 88(%rsp), %r12 + xorq %r11, %rcx + vpsrlq $19, %xmm4, %xmm8 + vpsllq $45, %xmm4, %xmm9 + # rnd_1: 2 - 3 + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + vpsrlq $61, %xmm4, %xmm10 + vpsllq $3, %xmm4, %xmm11 + # rnd_1: 4 - 6 + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm4, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + vpaddq %xmm5, %xmm8, %xmm5 + # msg_sched done: 10-13 + # msg_sched: 12-13 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm6, %xmm7, %xmm12 + vpalignr $8, %xmm2, %xmm3, %xmm13 + # rnd_0: 1 - 1 + movq %r12, %rdx + movq %r9, %rcx + addq 96(%rsp), %r11 + xorq %r10, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm6, %xmm13, %xmm6 + # rnd_0: 10 - 11 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm6, %xmm8, %xmm6 + # rnd_1: 1 - 1 + movq %r11, %rbx + movq %r8, %rcx + addq 104(%rsp), %r10 + xorq %r9, %rcx + vpsrlq $19, %xmm5, %xmm8 + vpsllq $45, %xmm5, %xmm9 + # rnd_1: 2 - 3 + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + vpsrlq $61, %xmm5, %xmm10 + vpsllq $3, %xmm5, %xmm11 + # rnd_1: 4 - 6 + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm5, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + vpaddq %xmm6, %xmm8, %xmm6 + # msg_sched done: 12-15 + # msg_sched: 14-15 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm7, %xmm0, %xmm12 + vpalignr $8, %xmm3, %xmm4, %xmm13 + # rnd_0: 1 - 1 + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm7, %xmm13, %xmm7 + # rnd_0: 10 - 11 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm7, %xmm8, %xmm7 + # rnd_1: 1 - 1 + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + vpsrlq $19, %xmm6, %xmm8 + vpsllq $45, %xmm6, %xmm9 + # rnd_1: 2 - 3 + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + vpsrlq $61, %xmm6, %xmm10 + vpsllq $3, %xmm6, %xmm11 + # rnd_1: 4 - 6 + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm6, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq %xmm7, %xmm8, %xmm7 + # msg_sched done: 14-17 + movq 136(%rsp), %rdx + vpaddq (%rdx), %xmm0, %xmm8 + vpaddq 16(%rdx), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rdx), %xmm2, %xmm8 + vpaddq 48(%rdx), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rdx), %xmm4, %xmm8 + vpaddq 80(%rdx), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rdx), %xmm6, %xmm8 + vpaddq 112(%rdx), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + subl $0x01, 128(%rsp) + jne L_sha512_len_avx1_start + # rnd_all_2: 0-1 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + # rnd_all_2: 2-3 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 16(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 24(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + # rnd_all_2: 4-5 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 32(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 40(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + # rnd_all_2: 6-7 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 48(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 56(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + # rnd_all_2: 8-9 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq 64(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 72(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + # rnd_all_2: 10-11 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 80(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 88(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + # rnd_all_2: 12-13 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 96(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 104(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + # rnd_all_2: 14-15 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + addq (%rdi), %r8 + addq 8(%rdi), %r9 + addq 16(%rdi), %r10 + addq 24(%rdi), %r11 + addq 32(%rdi), %r12 + addq 40(%rdi), %r13 + addq 48(%rdi), %r14 + addq 56(%rdi), %r15 + leaq L_avx1_sha512_k(%rip), %rdx + addq $0x80, %rsi + subl $0x80, %ebp + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + jnz L_sha512_len_avx1_begin + xorq %rax, %rax + vzeroupper + addq $0x90, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX1_Len,.-Transform_Sha512_AVX1_Len +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_rorx_sha512_k: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_rorx_sha512_flip_mask: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX1_RORX +.type Transform_Sha512_AVX1_RORX,@function +.align 4 +Transform_Sha512_AVX1_RORX: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX1_RORX +.p2align 2 +_Transform_Sha512_AVX1_RORX: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x88, %rsp + leaq 64(%rdi), %rax + vmovdqa L_avx1_rorx_sha512_flip_mask(%rip), %xmm14 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vpshufb %xmm14, %xmm0, %xmm0 + vpshufb %xmm14, %xmm1, %xmm1 + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vpshufb %xmm14, %xmm2, %xmm2 + vpshufb %xmm14, %xmm3, %xmm3 + vmovdqu 64(%rax), %xmm4 + vmovdqu 80(%rax), %xmm5 + vpshufb %xmm14, %xmm4, %xmm4 + vpshufb %xmm14, %xmm5, %xmm5 + vmovdqu 96(%rax), %xmm6 + vmovdqu 112(%rax), %xmm7 + vpshufb %xmm14, %xmm6, %xmm6 + vpshufb %xmm14, %xmm7, %xmm7 + movl $4, 128(%rsp) + leaq L_avx1_rorx_sha512_k(%rip), %rsi + movq %r9, %rbx + xorq %rdx, %rdx + xorq %r10, %rbx + vpaddq (%rsi), %xmm0, %xmm8 + vpaddq 16(%rsi), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rsi), %xmm2, %xmm8 + vpaddq 48(%rsi), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rsi), %xmm4, %xmm8 + vpaddq 80(%rsi), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rsi), %xmm6, %xmm8 + vpaddq 112(%rsi), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + # Start of 16 rounds +L_sha256_len_avx1_rorx_start: + addq $0x80, %rsi + # msg_sched: 0-1 + # rnd_0: 0 - 0 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpalignr $8, %xmm0, %xmm1, %xmm12 + vpalignr $8, %xmm4, %xmm5, %xmm13 + # rnd_0: 1 - 1 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm0, %xmm13, %xmm0 + # rnd_0: 6 - 7 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + vpaddq %xmm0, %xmm8, %xmm0 + # rnd_1: 0 - 0 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpsrlq $19, %xmm7, %xmm8 + vpsllq $45, %xmm7, %xmm9 + # rnd_1: 1 - 1 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm7, %xmm10 + vpsllq $3, %xmm7, %xmm11 + # rnd_1: 2 - 2 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm7, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpaddq %xmm0, %xmm8, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 2-3 + # rnd_0: 0 - 0 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpalignr $8, %xmm1, %xmm2, %xmm12 + vpalignr $8, %xmm5, %xmm6, %xmm13 + # rnd_0: 1 - 1 + addq 16(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm1, %xmm13, %xmm1 + # rnd_0: 6 - 7 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpaddq %xmm1, %xmm8, %xmm1 + # rnd_1: 0 - 0 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $19, %xmm0, %xmm8 + vpsllq $45, %xmm0, %xmm9 + # rnd_1: 1 - 1 + addq 24(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm0, %xmm10 + vpsllq $3, %xmm0, %xmm11 + # rnd_1: 2 - 2 + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm0, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vpaddq %xmm1, %xmm8, %xmm1 + # msg_sched done: 2-5 + # msg_sched: 4-5 + # rnd_0: 0 - 0 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpalignr $8, %xmm2, %xmm3, %xmm12 + vpalignr $8, %xmm6, %xmm7, %xmm13 + # rnd_0: 1 - 1 + addq 32(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm2, %xmm13, %xmm2 + # rnd_0: 6 - 7 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + vpaddq %xmm2, %xmm8, %xmm2 + # rnd_1: 0 - 0 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpsrlq $19, %xmm1, %xmm8 + vpsllq $45, %xmm1, %xmm9 + # rnd_1: 1 - 1 + addq 40(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm1, %xmm10 + vpsllq $3, %xmm1, %xmm11 + # rnd_1: 2 - 2 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm1, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpaddq %xmm2, %xmm8, %xmm2 + # msg_sched done: 4-7 + # msg_sched: 6-7 + # rnd_0: 0 - 0 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpalignr $8, %xmm3, %xmm4, %xmm12 + vpalignr $8, %xmm7, %xmm0, %xmm13 + # rnd_0: 1 - 1 + addq 48(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm3, %xmm13, %xmm3 + # rnd_0: 6 - 7 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpaddq %xmm3, %xmm8, %xmm3 + # rnd_1: 0 - 0 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $19, %xmm2, %xmm8 + vpsllq $45, %xmm2, %xmm9 + # rnd_1: 1 - 1 + addq 56(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm2, %xmm10 + vpsllq $3, %xmm2, %xmm11 + # rnd_1: 2 - 2 + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm2, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vpaddq %xmm3, %xmm8, %xmm3 + # msg_sched done: 6-9 + # msg_sched: 8-9 + # rnd_0: 0 - 0 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpalignr $8, %xmm4, %xmm5, %xmm12 + vpalignr $8, %xmm0, %xmm1, %xmm13 + # rnd_0: 1 - 1 + addq 64(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm4, %xmm13, %xmm4 + # rnd_0: 6 - 7 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + vpaddq %xmm4, %xmm8, %xmm4 + # rnd_1: 0 - 0 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpsrlq $19, %xmm3, %xmm8 + vpsllq $45, %xmm3, %xmm9 + # rnd_1: 1 - 1 + addq 72(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm3, %xmm10 + vpsllq $3, %xmm3, %xmm11 + # rnd_1: 2 - 2 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm3, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpaddq %xmm4, %xmm8, %xmm4 + # msg_sched done: 8-11 + # msg_sched: 10-11 + # rnd_0: 0 - 0 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpalignr $8, %xmm5, %xmm6, %xmm12 + vpalignr $8, %xmm1, %xmm2, %xmm13 + # rnd_0: 1 - 1 + addq 80(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm5, %xmm13, %xmm5 + # rnd_0: 6 - 7 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpaddq %xmm5, %xmm8, %xmm5 + # rnd_1: 0 - 0 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $19, %xmm4, %xmm8 + vpsllq $45, %xmm4, %xmm9 + # rnd_1: 1 - 1 + addq 88(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm4, %xmm10 + vpsllq $3, %xmm4, %xmm11 + # rnd_1: 2 - 2 + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm4, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vpaddq %xmm5, %xmm8, %xmm5 + # msg_sched done: 10-13 + # msg_sched: 12-13 + # rnd_0: 0 - 0 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpalignr $8, %xmm6, %xmm7, %xmm12 + vpalignr $8, %xmm2, %xmm3, %xmm13 + # rnd_0: 1 - 1 + addq 96(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm6, %xmm13, %xmm6 + # rnd_0: 6 - 7 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + vpaddq %xmm6, %xmm8, %xmm6 + # rnd_1: 0 - 0 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpsrlq $19, %xmm5, %xmm8 + vpsllq $45, %xmm5, %xmm9 + # rnd_1: 1 - 1 + addq 104(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm5, %xmm10 + vpsllq $3, %xmm5, %xmm11 + # rnd_1: 2 - 2 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm5, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpaddq %xmm6, %xmm8, %xmm6 + # msg_sched done: 12-15 + # msg_sched: 14-15 + # rnd_0: 0 - 0 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpalignr $8, %xmm7, %xmm0, %xmm12 + vpalignr $8, %xmm3, %xmm4, %xmm13 + # rnd_0: 1 - 1 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm7, %xmm13, %xmm7 + # rnd_0: 6 - 7 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpaddq %xmm7, %xmm8, %xmm7 + # rnd_1: 0 - 0 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $19, %xmm6, %xmm8 + vpsllq $45, %xmm6, %xmm9 + # rnd_1: 1 - 1 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm6, %xmm10 + vpsllq $3, %xmm6, %xmm11 + # rnd_1: 2 - 2 + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm6, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vpaddq %xmm7, %xmm8, %xmm7 + # msg_sched done: 14-17 + vpaddq (%rsi), %xmm0, %xmm8 + vpaddq 16(%rsi), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rsi), %xmm2, %xmm8 + vpaddq 48(%rsi), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rsi), %xmm4, %xmm8 + vpaddq 80(%rsi), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rsi), %xmm6, %xmm8 + vpaddq 112(%rsi), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + subl $0x01, 128(%rsp) + jne L_sha256_len_avx1_rorx_start + # rnd_all_2: 0-1 + # rnd_0: 0 - 7 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 2-3 + # rnd_0: 0 - 7 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 16(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 24(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 4-5 + # rnd_0: 0 - 7 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 32(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 40(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 6-7 + # rnd_0: 0 - 7 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 48(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 56(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + # rnd_all_2: 8-9 + # rnd_0: 0 - 7 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq 64(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 72(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 10-11 + # rnd_0: 0 - 7 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 80(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 88(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 12-13 + # rnd_0: 0 - 7 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 96(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 104(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 14-15 + # rnd_0: 0 - 7 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + addq %rdx, %r8 + addq %r8, (%rdi) + addq %r9, 8(%rdi) + addq %r10, 16(%rdi) + addq %r11, 24(%rdi) + addq %r12, 32(%rdi) + addq %r13, 40(%rdi) + addq %r14, 48(%rdi) + addq %r15, 56(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x88, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX1_RORX,.-Transform_Sha512_AVX1_RORX +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX1_RORX_Len +.type Transform_Sha512_AVX1_RORX_Len,@function +.align 4 +Transform_Sha512_AVX1_RORX_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX1_RORX_Len +.p2align 2 +_Transform_Sha512_AVX1_RORX_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + subq $0x90, %rsp + movq 224(%rdi), %rsi + leaq L_avx1_rorx_sha512_k(%rip), %rcx + vmovdqa L_avx1_rorx_sha512_flip_mask(%rip), %xmm14 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + # Start of loop processing a block +L_sha512_len_avx1_rorx_begin: + vmovdqu (%rsi), %xmm0 + vmovdqu 16(%rsi), %xmm1 + vpshufb %xmm14, %xmm0, %xmm0 + vpshufb %xmm14, %xmm1, %xmm1 + vmovdqu 32(%rsi), %xmm2 + vmovdqu 48(%rsi), %xmm3 + vpshufb %xmm14, %xmm2, %xmm2 + vpshufb %xmm14, %xmm3, %xmm3 + vmovdqu 64(%rsi), %xmm4 + vmovdqu 80(%rsi), %xmm5 + vpshufb %xmm14, %xmm4, %xmm4 + vpshufb %xmm14, %xmm5, %xmm5 + vmovdqu 96(%rsi), %xmm6 + vmovdqu 112(%rsi), %xmm7 + vpshufb %xmm14, %xmm6, %xmm6 + vpshufb %xmm14, %xmm7, %xmm7 + movl $4, 128(%rsp) + movq %r9, %rbx + xorq %rdx, %rdx + xorq %r10, %rbx + vpaddq (%rcx), %xmm0, %xmm8 + vpaddq 16(%rcx), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rcx), %xmm2, %xmm8 + vpaddq 48(%rcx), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rcx), %xmm4, %xmm8 + vpaddq 80(%rcx), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rcx), %xmm6, %xmm8 + vpaddq 112(%rcx), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + # Start of 16 rounds +L_sha512_len_avx1_rorx_start: + addq $0x80, %rcx + movq %rcx, 136(%rsp) + # msg_sched: 0-1 + # rnd_0: 0 - 0 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpalignr $8, %xmm0, %xmm1, %xmm12 + vpalignr $8, %xmm4, %xmm5, %xmm13 + # rnd_0: 1 - 1 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm0, %xmm13, %xmm0 + # rnd_0: 6 - 7 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + vpaddq %xmm0, %xmm8, %xmm0 + # rnd_1: 0 - 0 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpsrlq $19, %xmm7, %xmm8 + vpsllq $45, %xmm7, %xmm9 + # rnd_1: 1 - 1 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm7, %xmm10 + vpsllq $3, %xmm7, %xmm11 + # rnd_1: 2 - 2 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm7, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpaddq %xmm0, %xmm8, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 2-3 + # rnd_0: 0 - 0 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpalignr $8, %xmm1, %xmm2, %xmm12 + vpalignr $8, %xmm5, %xmm6, %xmm13 + # rnd_0: 1 - 1 + addq 16(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm1, %xmm13, %xmm1 + # rnd_0: 6 - 7 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpaddq %xmm1, %xmm8, %xmm1 + # rnd_1: 0 - 0 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $19, %xmm0, %xmm8 + vpsllq $45, %xmm0, %xmm9 + # rnd_1: 1 - 1 + addq 24(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm0, %xmm10 + vpsllq $3, %xmm0, %xmm11 + # rnd_1: 2 - 2 + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm0, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vpaddq %xmm1, %xmm8, %xmm1 + # msg_sched done: 2-5 + # msg_sched: 4-5 + # rnd_0: 0 - 0 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpalignr $8, %xmm2, %xmm3, %xmm12 + vpalignr $8, %xmm6, %xmm7, %xmm13 + # rnd_0: 1 - 1 + addq 32(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm2, %xmm13, %xmm2 + # rnd_0: 6 - 7 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + vpaddq %xmm2, %xmm8, %xmm2 + # rnd_1: 0 - 0 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpsrlq $19, %xmm1, %xmm8 + vpsllq $45, %xmm1, %xmm9 + # rnd_1: 1 - 1 + addq 40(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm1, %xmm10 + vpsllq $3, %xmm1, %xmm11 + # rnd_1: 2 - 2 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm1, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpaddq %xmm2, %xmm8, %xmm2 + # msg_sched done: 4-7 + # msg_sched: 6-7 + # rnd_0: 0 - 0 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpalignr $8, %xmm3, %xmm4, %xmm12 + vpalignr $8, %xmm7, %xmm0, %xmm13 + # rnd_0: 1 - 1 + addq 48(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm3, %xmm13, %xmm3 + # rnd_0: 6 - 7 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpaddq %xmm3, %xmm8, %xmm3 + # rnd_1: 0 - 0 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $19, %xmm2, %xmm8 + vpsllq $45, %xmm2, %xmm9 + # rnd_1: 1 - 1 + addq 56(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm2, %xmm10 + vpsllq $3, %xmm2, %xmm11 + # rnd_1: 2 - 2 + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm2, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vpaddq %xmm3, %xmm8, %xmm3 + # msg_sched done: 6-9 + # msg_sched: 8-9 + # rnd_0: 0 - 0 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpalignr $8, %xmm4, %xmm5, %xmm12 + vpalignr $8, %xmm0, %xmm1, %xmm13 + # rnd_0: 1 - 1 + addq 64(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm4, %xmm13, %xmm4 + # rnd_0: 6 - 7 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + vpaddq %xmm4, %xmm8, %xmm4 + # rnd_1: 0 - 0 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpsrlq $19, %xmm3, %xmm8 + vpsllq $45, %xmm3, %xmm9 + # rnd_1: 1 - 1 + addq 72(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm3, %xmm10 + vpsllq $3, %xmm3, %xmm11 + # rnd_1: 2 - 2 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm3, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpaddq %xmm4, %xmm8, %xmm4 + # msg_sched done: 8-11 + # msg_sched: 10-11 + # rnd_0: 0 - 0 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpalignr $8, %xmm5, %xmm6, %xmm12 + vpalignr $8, %xmm1, %xmm2, %xmm13 + # rnd_0: 1 - 1 + addq 80(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm5, %xmm13, %xmm5 + # rnd_0: 6 - 7 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpaddq %xmm5, %xmm8, %xmm5 + # rnd_1: 0 - 0 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $19, %xmm4, %xmm8 + vpsllq $45, %xmm4, %xmm9 + # rnd_1: 1 - 1 + addq 88(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm4, %xmm10 + vpsllq $3, %xmm4, %xmm11 + # rnd_1: 2 - 2 + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm4, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vpaddq %xmm5, %xmm8, %xmm5 + # msg_sched done: 10-13 + # msg_sched: 12-13 + # rnd_0: 0 - 0 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpalignr $8, %xmm6, %xmm7, %xmm12 + vpalignr $8, %xmm2, %xmm3, %xmm13 + # rnd_0: 1 - 1 + addq 96(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm6, %xmm13, %xmm6 + # rnd_0: 6 - 7 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + vpaddq %xmm6, %xmm8, %xmm6 + # rnd_1: 0 - 0 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpsrlq $19, %xmm5, %xmm8 + vpsllq $45, %xmm5, %xmm9 + # rnd_1: 1 - 1 + addq 104(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm5, %xmm10 + vpsllq $3, %xmm5, %xmm11 + # rnd_1: 2 - 2 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm5, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpaddq %xmm6, %xmm8, %xmm6 + # msg_sched done: 12-15 + # msg_sched: 14-15 + # rnd_0: 0 - 0 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpalignr $8, %xmm7, %xmm0, %xmm12 + vpalignr $8, %xmm3, %xmm4, %xmm13 + # rnd_0: 1 - 1 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm7, %xmm13, %xmm7 + # rnd_0: 6 - 7 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpaddq %xmm7, %xmm8, %xmm7 + # rnd_1: 0 - 0 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $19, %xmm6, %xmm8 + vpsllq $45, %xmm6, %xmm9 + # rnd_1: 1 - 1 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm6, %xmm10 + vpsllq $3, %xmm6, %xmm11 + # rnd_1: 2 - 2 + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm6, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vpaddq %xmm7, %xmm8, %xmm7 + # msg_sched done: 14-17 + movq 136(%rsp), %rcx + vpaddq (%rcx), %xmm0, %xmm8 + vpaddq 16(%rcx), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rcx), %xmm2, %xmm8 + vpaddq 48(%rcx), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rcx), %xmm4, %xmm8 + vpaddq 80(%rcx), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rcx), %xmm6, %xmm8 + vpaddq 112(%rcx), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + subl $0x01, 128(%rsp) + jne L_sha512_len_avx1_rorx_start + vpaddq (%rcx), %xmm0, %xmm8 + vpaddq 16(%rcx), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rcx), %xmm2, %xmm8 + vpaddq 48(%rcx), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rcx), %xmm4, %xmm8 + vpaddq 80(%rcx), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rcx), %xmm6, %xmm8 + vpaddq 112(%rcx), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + # rnd_all_2: 0-1 + # rnd_0: 0 - 7 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 2-3 + # rnd_0: 0 - 7 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 16(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 24(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 4-5 + # rnd_0: 0 - 7 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 32(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 40(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 6-7 + # rnd_0: 0 - 7 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 48(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 56(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + # rnd_all_2: 8-9 + # rnd_0: 0 - 7 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq 64(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 72(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 10-11 + # rnd_0: 0 - 7 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 80(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 88(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 12-13 + # rnd_0: 0 - 7 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 96(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 104(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 14-15 + # rnd_0: 0 - 7 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + addq %rdx, %r8 + addq (%rdi), %r8 + addq 8(%rdi), %r9 + addq 16(%rdi), %r10 + addq 24(%rdi), %r11 + addq 32(%rdi), %r12 + addq 40(%rdi), %r13 + addq 48(%rdi), %r14 + addq 56(%rdi), %r15 + leaq L_avx1_rorx_sha512_k(%rip), %rcx + addq $0x80, %rsi + subl $0x80, %ebp + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + jnz L_sha512_len_avx1_rorx_begin + xorq %rax, %rax + vzeroupper + addq $0x90, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX1_RORX_Len,.-Transform_Sha512_AVX1_RORX_Len +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX1 */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_sha512_k: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_sha512_k_2: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 8 +#else +.p2align 3 +#endif /* __APPLE__ */ +L_avx2_sha512_k_2_end: +.quad 1024+L_avx2_sha512_k_2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_sha512_flip_mask: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX2 +.type Transform_Sha512_AVX2,@function +.align 4 +Transform_Sha512_AVX2: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX2 +.p2align 2 +_Transform_Sha512_AVX2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x88, %rsp + leaq 64(%rdi), %rax + vmovdqa L_avx2_sha512_flip_mask(%rip), %ymm15 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + vmovdqu (%rax), %ymm0 + vmovdqu 32(%rax), %ymm1 + vpshufb %ymm15, %ymm0, %ymm0 + vpshufb %ymm15, %ymm1, %ymm1 + vmovdqu 64(%rax), %ymm2 + vmovdqu 96(%rax), %ymm3 + vpshufb %ymm15, %ymm2, %ymm2 + vpshufb %ymm15, %ymm3, %ymm3 + movl $4, 128(%rsp) + leaq L_avx2_sha512_k(%rip), %rsi + movq %r9, %rbx + movq %r12, %rax + xorq %r10, %rbx + vpaddq (%rsi), %ymm0, %ymm8 + vpaddq 32(%rsi), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rsi), %ymm2, %ymm8 + vpaddq 96(%rsi), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + # Start of 16 rounds +L_sha256_avx2_start: + addq $0x80, %rsi + rorq $23, %rax + vpblendd $3, %ymm1, %ymm0, %ymm12 + vpblendd $3, %ymm3, %ymm2, %ymm13 + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + vpermq $57, %ymm12, %ymm12 + rorq $4, %rax + xorq %r14, %rcx + vpermq $57, %ymm13, %ymm13 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpsrlq $0x01, %ymm12, %ymm8 + addq %rax, %r15 + movq %r8, %rcx + vpsllq $63, %ymm12, %ymm9 + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $8, %ymm12, %ymm10 + xorq %r8, %rcx + xorq %r9, %rbx + vpsllq $56, %ymm12, %ymm11 + rorq $6, %rcx + addq %r15, %r11 + vpor %ymm9, %ymm8, %ymm8 + xorq %r8, %rcx + addq %rbx, %r15 + vpor %ymm11, %ymm10, %ymm10 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r15, %rbx + movq %r12, %rcx + vpxor %ymm10, %ymm8, %ymm8 + addq 8(%rsp), %r14 + xorq %r13, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r11, %rax + andq %r11, %rcx + vpaddq %ymm0, %ymm13, %ymm0 + rorq $4, %rax + xorq %r13, %rcx + vpaddq %ymm0, %ymm8, %ymm0 + xorq %r11, %rax + addq %rcx, %r14 + vperm2I128 $0x81, %ymm3, %ymm3, %ymm14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + vpsrlq $19, %ymm14, %ymm8 + xorq %r15, %rcx + xorq %r8, %rdx + vpsllq $45, %ymm14, %ymm9 + rorq $6, %rcx + addq %r14, %r10 + vpsrlq $61, %ymm14, %ymm10 + xorq %r15, %rcx + addq %rdx, %r14 + vpsllq $3, %ymm14, %ymm11 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + vpor %ymm9, %ymm8, %ymm8 + movq %r14, %rdx + movq %r11, %rcx + addq 16(%rsp), %r13 + xorq %r12, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r10, %rax + andq %r10, %rcx + vpxor %ymm10, %ymm8, %ymm8 + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $6, %ymm14, %ymm11 + xorq %r10, %rax + addq %rcx, %r13 + vpxor %ymm11, %ymm8, %ymm8 + rorq $14, %rax + xorq %r15, %rdx + vpaddq %ymm0, %ymm8, %ymm0 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vperm2I128 $8, %ymm0, %ymm0, %ymm14 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpsrlq $19, %ymm14, %ymm8 + xorq %r14, %rcx + addq %rbx, %r13 + vpsllq $45, %ymm14, %ymm9 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + vpsrlq $61, %ymm14, %ymm10 + movq %r13, %rbx + movq %r10, %rcx + addq 24(%rsp), %r12 + xorq %r11, %rcx + vpsllq $3, %ymm14, %ymm11 + xorq %r9, %rax + andq %r9, %rcx + vpor %ymm9, %ymm8, %ymm8 + rorq $4, %rax + xorq %r11, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r9, %rax + addq %rcx, %r12 + vpxor %ymm10, %ymm8, %ymm8 + rorq $14, %rax + xorq %r14, %rbx + vpsrlq $6, %ymm14, %ymm11 + addq %rax, %r12 + movq %r13, %rcx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + rorq $5, %rcx + vpaddq %ymm0, %ymm8, %ymm0 + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + vpblendd $3, %ymm2, %ymm1, %ymm12 + vpblendd $3, %ymm0, %ymm3, %ymm13 + movq %r12, %rdx + movq %r9, %rcx + addq 32(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + vpermq $57, %ymm12, %ymm12 + rorq $4, %rax + xorq %r10, %rcx + vpermq $57, %ymm13, %ymm13 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpsrlq $0x01, %ymm12, %ymm8 + addq %rax, %r11 + movq %r12, %rcx + vpsllq $63, %ymm12, %ymm9 + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $8, %ymm12, %ymm10 + xorq %r12, %rcx + xorq %r13, %rbx + vpsllq $56, %ymm12, %ymm11 + rorq $6, %rcx + addq %r11, %r15 + vpor %ymm9, %ymm8, %ymm8 + xorq %r12, %rcx + addq %rbx, %r11 + vpor %ymm11, %ymm10, %ymm10 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r11, %rbx + movq %r8, %rcx + vpxor %ymm10, %ymm8, %ymm8 + addq 40(%rsp), %r10 + xorq %r9, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r15, %rax + andq %r15, %rcx + vpaddq %ymm1, %ymm13, %ymm1 + rorq $4, %rax + xorq %r9, %rcx + vpaddq %ymm1, %ymm8, %ymm1 + xorq %r15, %rax + addq %rcx, %r10 + vperm2I128 $0x81, %ymm0, %ymm0, %ymm14 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + vpsrlq $19, %ymm14, %ymm8 + xorq %r11, %rcx + xorq %r12, %rdx + vpsllq $45, %ymm14, %ymm9 + rorq $6, %rcx + addq %r10, %r14 + vpsrlq $61, %ymm14, %ymm10 + xorq %r11, %rcx + addq %rdx, %r10 + vpsllq $3, %ymm14, %ymm11 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + vpor %ymm9, %ymm8, %ymm8 + movq %r10, %rdx + movq %r15, %rcx + addq 48(%rsp), %r9 + xorq %r8, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r14, %rax + andq %r14, %rcx + vpxor %ymm10, %ymm8, %ymm8 + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $6, %ymm14, %ymm11 + xorq %r14, %rax + addq %rcx, %r9 + vpxor %ymm11, %ymm8, %ymm8 + rorq $14, %rax + xorq %r11, %rdx + vpaddq %ymm1, %ymm8, %ymm1 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vperm2I128 $8, %ymm1, %ymm1, %ymm14 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpsrlq $19, %ymm14, %ymm8 + xorq %r10, %rcx + addq %rbx, %r9 + vpsllq $45, %ymm14, %ymm9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + vpsrlq $61, %ymm14, %ymm10 + movq %r9, %rbx + movq %r14, %rcx + addq 56(%rsp), %r8 + xorq %r15, %rcx + vpsllq $3, %ymm14, %ymm11 + xorq %r13, %rax + andq %r13, %rcx + vpor %ymm9, %ymm8, %ymm8 + rorq $4, %rax + xorq %r15, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r13, %rax + addq %rcx, %r8 + vpxor %ymm10, %ymm8, %ymm8 + rorq $14, %rax + xorq %r10, %rbx + vpsrlq $6, %ymm14, %ymm11 + addq %rax, %r8 + movq %r9, %rcx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + rorq $5, %rcx + vpaddq %ymm1, %ymm8, %ymm1 + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + rorq $23, %rax + vpblendd $3, %ymm3, %ymm2, %ymm12 + vpblendd $3, %ymm1, %ymm0, %ymm13 + movq %r8, %rdx + movq %r13, %rcx + addq 64(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + vpermq $57, %ymm12, %ymm12 + rorq $4, %rax + xorq %r14, %rcx + vpermq $57, %ymm13, %ymm13 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpsrlq $0x01, %ymm12, %ymm8 + addq %rax, %r15 + movq %r8, %rcx + vpsllq $63, %ymm12, %ymm9 + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $8, %ymm12, %ymm10 + xorq %r8, %rcx + xorq %r9, %rbx + vpsllq $56, %ymm12, %ymm11 + rorq $6, %rcx + addq %r15, %r11 + vpor %ymm9, %ymm8, %ymm8 + xorq %r8, %rcx + addq %rbx, %r15 + vpor %ymm11, %ymm10, %ymm10 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r15, %rbx + movq %r12, %rcx + vpxor %ymm10, %ymm8, %ymm8 + addq 72(%rsp), %r14 + xorq %r13, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r11, %rax + andq %r11, %rcx + vpaddq %ymm2, %ymm13, %ymm2 + rorq $4, %rax + xorq %r13, %rcx + vpaddq %ymm2, %ymm8, %ymm2 + xorq %r11, %rax + addq %rcx, %r14 + vperm2I128 $0x81, %ymm1, %ymm1, %ymm14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + vpsrlq $19, %ymm14, %ymm8 + xorq %r15, %rcx + xorq %r8, %rdx + vpsllq $45, %ymm14, %ymm9 + rorq $6, %rcx + addq %r14, %r10 + vpsrlq $61, %ymm14, %ymm10 + xorq %r15, %rcx + addq %rdx, %r14 + vpsllq $3, %ymm14, %ymm11 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + vpor %ymm9, %ymm8, %ymm8 + movq %r14, %rdx + movq %r11, %rcx + addq 80(%rsp), %r13 + xorq %r12, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r10, %rax + andq %r10, %rcx + vpxor %ymm10, %ymm8, %ymm8 + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $6, %ymm14, %ymm11 + xorq %r10, %rax + addq %rcx, %r13 + vpxor %ymm11, %ymm8, %ymm8 + rorq $14, %rax + xorq %r15, %rdx + vpaddq %ymm2, %ymm8, %ymm2 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vperm2I128 $8, %ymm2, %ymm2, %ymm14 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpsrlq $19, %ymm14, %ymm8 + xorq %r14, %rcx + addq %rbx, %r13 + vpsllq $45, %ymm14, %ymm9 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + vpsrlq $61, %ymm14, %ymm10 + movq %r13, %rbx + movq %r10, %rcx + addq 88(%rsp), %r12 + xorq %r11, %rcx + vpsllq $3, %ymm14, %ymm11 + xorq %r9, %rax + andq %r9, %rcx + vpor %ymm9, %ymm8, %ymm8 + rorq $4, %rax + xorq %r11, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r9, %rax + addq %rcx, %r12 + vpxor %ymm10, %ymm8, %ymm8 + rorq $14, %rax + xorq %r14, %rbx + vpsrlq $6, %ymm14, %ymm11 + addq %rax, %r12 + movq %r13, %rcx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + rorq $5, %rcx + vpaddq %ymm2, %ymm8, %ymm2 + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + vpblendd $3, %ymm0, %ymm3, %ymm12 + vpblendd $3, %ymm2, %ymm1, %ymm13 + movq %r12, %rdx + movq %r9, %rcx + addq 96(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + vpermq $57, %ymm12, %ymm12 + rorq $4, %rax + xorq %r10, %rcx + vpermq $57, %ymm13, %ymm13 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpsrlq $0x01, %ymm12, %ymm8 + addq %rax, %r11 + movq %r12, %rcx + vpsllq $63, %ymm12, %ymm9 + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $8, %ymm12, %ymm10 + xorq %r12, %rcx + xorq %r13, %rbx + vpsllq $56, %ymm12, %ymm11 + rorq $6, %rcx + addq %r11, %r15 + vpor %ymm9, %ymm8, %ymm8 + xorq %r12, %rcx + addq %rbx, %r11 + vpor %ymm11, %ymm10, %ymm10 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r11, %rbx + movq %r8, %rcx + vpxor %ymm10, %ymm8, %ymm8 + addq 104(%rsp), %r10 + xorq %r9, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r15, %rax + andq %r15, %rcx + vpaddq %ymm3, %ymm13, %ymm3 + rorq $4, %rax + xorq %r9, %rcx + vpaddq %ymm3, %ymm8, %ymm3 + xorq %r15, %rax + addq %rcx, %r10 + vperm2I128 $0x81, %ymm2, %ymm2, %ymm14 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + vpsrlq $19, %ymm14, %ymm8 + xorq %r11, %rcx + xorq %r12, %rdx + vpsllq $45, %ymm14, %ymm9 + rorq $6, %rcx + addq %r10, %r14 + vpsrlq $61, %ymm14, %ymm10 + xorq %r11, %rcx + addq %rdx, %r10 + vpsllq $3, %ymm14, %ymm11 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + vpor %ymm9, %ymm8, %ymm8 + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r14, %rax + andq %r14, %rcx + vpxor %ymm10, %ymm8, %ymm8 + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $6, %ymm14, %ymm11 + xorq %r14, %rax + addq %rcx, %r9 + vpxor %ymm11, %ymm8, %ymm8 + rorq $14, %rax + xorq %r11, %rdx + vpaddq %ymm3, %ymm8, %ymm3 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vperm2I128 $8, %ymm3, %ymm3, %ymm14 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpsrlq $19, %ymm14, %ymm8 + xorq %r10, %rcx + addq %rbx, %r9 + vpsllq $45, %ymm14, %ymm9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + vpsrlq $61, %ymm14, %ymm10 + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + vpsllq $3, %ymm14, %ymm11 + xorq %r13, %rax + andq %r13, %rcx + vpor %ymm9, %ymm8, %ymm8 + rorq $4, %rax + xorq %r15, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r13, %rax + addq %rcx, %r8 + vpxor %ymm10, %ymm8, %ymm8 + rorq $14, %rax + xorq %r10, %rbx + vpsrlq $6, %ymm14, %ymm11 + addq %rax, %r8 + movq %r9, %rcx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + rorq $5, %rcx + vpaddq %ymm3, %ymm8, %ymm3 + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq (%rsi), %ymm0, %ymm8 + vpaddq 32(%rsi), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rsi), %ymm2, %ymm8 + vpaddq 96(%rsi), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + subl $0x01, 128(%rsp) + jne L_sha256_avx2_start + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 16(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 24(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 32(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 40(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 48(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 56(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq 64(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 72(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 80(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 88(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 96(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 104(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + addq %r8, (%rdi) + addq %r9, 8(%rdi) + addq %r10, 16(%rdi) + addq %r11, 24(%rdi) + addq %r12, 32(%rdi) + addq %r13, 40(%rdi) + addq %r14, 48(%rdi) + addq %r15, 56(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x88, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX2,.-Transform_Sha512_AVX2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX2_Len +.type Transform_Sha512_AVX2_Len,@function +.align 4 +Transform_Sha512_AVX2_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX2_Len +.p2align 2 +_Transform_Sha512_AVX2_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + testb $0x80, %bpl + je L_sha512_len_avx2_block + movq 224(%rdi), %rcx + vmovdqu (%rcx), %ymm0 + vmovdqu 32(%rcx), %ymm1 + vmovdqu 64(%rcx), %ymm2 + vmovdqu 96(%rcx), %ymm3 + vmovups %ymm0, 64(%rdi) + vmovups %ymm1, 96(%rdi) + vmovups %ymm2, 128(%rdi) + vmovups %ymm3, 160(%rdi) +#ifndef __APPLE__ + call Transform_Sha512_AVX2@plt +#else + call _Transform_Sha512_AVX2 +#endif /* __APPLE__ */ + addq $0x80, 224(%rdi) + subl $0x80, %ebp + jz L_sha512_len_avx2_done +L_sha512_len_avx2_block: + movq 224(%rdi), %rcx + vmovdqa L_avx2_sha512_flip_mask(%rip), %ymm15 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + # Start of loop processing two blocks +L_sha512_len_avx2_begin: + subq $0x540, %rsp + leaq L_avx2_sha512_k_2(%rip), %rsi + movq %r9, %rbx + movq %r12, %rax + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vinserti128 $0x01, 128(%rcx), %ymm0, %ymm0 + vinserti128 $0x01, 144(%rcx), %ymm1, %ymm1 + vpshufb %ymm15, %ymm0, %ymm0 + vpshufb %ymm15, %ymm1, %ymm1 + vmovdqu 32(%rcx), %xmm2 + vmovdqu 48(%rcx), %xmm3 + vinserti128 $0x01, 160(%rcx), %ymm2, %ymm2 + vinserti128 $0x01, 176(%rcx), %ymm3, %ymm3 + vpshufb %ymm15, %ymm2, %ymm2 + vpshufb %ymm15, %ymm3, %ymm3 + vmovdqu 64(%rcx), %xmm4 + vmovdqu 80(%rcx), %xmm5 + vinserti128 $0x01, 192(%rcx), %ymm4, %ymm4 + vinserti128 $0x01, 208(%rcx), %ymm5, %ymm5 + vpshufb %ymm15, %ymm4, %ymm4 + vpshufb %ymm15, %ymm5, %ymm5 + vmovdqu 96(%rcx), %xmm6 + vmovdqu 112(%rcx), %xmm7 + vinserti128 $0x01, 224(%rcx), %ymm6, %ymm6 + vinserti128 $0x01, 240(%rcx), %ymm7, %ymm7 + vpshufb %ymm15, %ymm6, %ymm6 + vpshufb %ymm15, %ymm7, %ymm7 + xorq %r10, %rbx + # Start of 16 rounds +L_sha512_len_avx2_start: + vpaddq (%rsi), %ymm0, %ymm8 + vpaddq 32(%rsi), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rsi), %ymm2, %ymm8 + vpaddq 96(%rsi), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + vpaddq 128(%rsi), %ymm4, %ymm8 + vpaddq 160(%rsi), %ymm5, %ymm9 + vmovdqu %ymm8, 128(%rsp) + vmovdqu %ymm9, 160(%rsp) + vpaddq 192(%rsi), %ymm6, %ymm8 + vpaddq 224(%rsi), %ymm7, %ymm9 + vmovdqu %ymm8, 192(%rsp) + vmovdqu %ymm9, 224(%rsp) + # msg_sched: 0-1 + rorq $23, %rax + vpalignr $8, %ymm0, %ymm1, %ymm12 + vpalignr $8, %ymm4, %ymm5, %ymm13 + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm0, %ymm13, %ymm0 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + vpaddq %ymm0, %ymm8, %ymm0 + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + vpsrlq $19, %ymm7, %ymm8 + vpsllq $45, %ymm7, %ymm9 + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + vpsrlq $61, %ymm7, %ymm10 + vpsllq $3, %ymm7, %ymm11 + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm7, %ymm11 + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + vpaddq %ymm0, %ymm8, %ymm0 + # msg_sched done: 0-3 + # msg_sched: 4-5 + rorq $23, %rax + vpalignr $8, %ymm1, %ymm2, %ymm12 + vpalignr $8, %ymm5, %ymm6, %ymm13 + movq %r14, %rdx + movq %r11, %rcx + addq 32(%rsp), %r13 + xorq %r12, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm1, %ymm13, %ymm1 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + vpaddq %ymm1, %ymm8, %ymm1 + movq %r13, %rbx + movq %r10, %rcx + addq 40(%rsp), %r12 + xorq %r11, %rcx + vpsrlq $19, %ymm0, %ymm8 + vpsllq $45, %ymm0, %ymm9 + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + vpsrlq $61, %ymm0, %ymm10 + vpsllq $3, %ymm0, %ymm11 + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm0, %ymm11 + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + vpaddq %ymm1, %ymm8, %ymm1 + # msg_sched done: 4-7 + # msg_sched: 8-9 + rorq $23, %rax + vpalignr $8, %ymm2, %ymm3, %ymm12 + vpalignr $8, %ymm6, %ymm7, %ymm13 + movq %r12, %rdx + movq %r9, %rcx + addq 64(%rsp), %r11 + xorq %r10, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm2, %ymm13, %ymm2 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + vpaddq %ymm2, %ymm8, %ymm2 + movq %r11, %rbx + movq %r8, %rcx + addq 72(%rsp), %r10 + xorq %r9, %rcx + vpsrlq $19, %ymm1, %ymm8 + vpsllq $45, %ymm1, %ymm9 + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + vpsrlq $61, %ymm1, %ymm10 + vpsllq $3, %ymm1, %ymm11 + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm1, %ymm11 + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + vpaddq %ymm2, %ymm8, %ymm2 + # msg_sched done: 8-11 + # msg_sched: 12-13 + rorq $23, %rax + vpalignr $8, %ymm3, %ymm4, %ymm12 + vpalignr $8, %ymm7, %ymm0, %ymm13 + movq %r10, %rdx + movq %r15, %rcx + addq 96(%rsp), %r9 + xorq %r8, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm3, %ymm13, %ymm3 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + vpaddq %ymm3, %ymm8, %ymm3 + movq %r9, %rbx + movq %r14, %rcx + addq 104(%rsp), %r8 + xorq %r15, %rcx + vpsrlq $19, %ymm2, %ymm8 + vpsllq $45, %ymm2, %ymm9 + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + vpsrlq $61, %ymm2, %ymm10 + vpsllq $3, %ymm2, %ymm11 + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm2, %ymm11 + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq %ymm3, %ymm8, %ymm3 + # msg_sched done: 12-15 + # msg_sched: 16-17 + rorq $23, %rax + vpalignr $8, %ymm4, %ymm5, %ymm12 + vpalignr $8, %ymm0, %ymm1, %ymm13 + movq %r8, %rdx + movq %r13, %rcx + addq 128(%rsp), %r15 + xorq %r14, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm4, %ymm13, %ymm4 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + vpaddq %ymm4, %ymm8, %ymm4 + movq %r15, %rbx + movq %r12, %rcx + addq 136(%rsp), %r14 + xorq %r13, %rcx + vpsrlq $19, %ymm3, %ymm8 + vpsllq $45, %ymm3, %ymm9 + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + vpsrlq $61, %ymm3, %ymm10 + vpsllq $3, %ymm3, %ymm11 + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm3, %ymm11 + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + vpaddq %ymm4, %ymm8, %ymm4 + # msg_sched done: 16-19 + # msg_sched: 20-21 + rorq $23, %rax + vpalignr $8, %ymm5, %ymm6, %ymm12 + vpalignr $8, %ymm1, %ymm2, %ymm13 + movq %r14, %rdx + movq %r11, %rcx + addq 160(%rsp), %r13 + xorq %r12, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm5, %ymm13, %ymm5 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + vpaddq %ymm5, %ymm8, %ymm5 + movq %r13, %rbx + movq %r10, %rcx + addq 168(%rsp), %r12 + xorq %r11, %rcx + vpsrlq $19, %ymm4, %ymm8 + vpsllq $45, %ymm4, %ymm9 + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + vpsrlq $61, %ymm4, %ymm10 + vpsllq $3, %ymm4, %ymm11 + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm4, %ymm11 + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + vpaddq %ymm5, %ymm8, %ymm5 + # msg_sched done: 20-23 + # msg_sched: 24-25 + rorq $23, %rax + vpalignr $8, %ymm6, %ymm7, %ymm12 + vpalignr $8, %ymm2, %ymm3, %ymm13 + movq %r12, %rdx + movq %r9, %rcx + addq 192(%rsp), %r11 + xorq %r10, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm6, %ymm13, %ymm6 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + vpaddq %ymm6, %ymm8, %ymm6 + movq %r11, %rbx + movq %r8, %rcx + addq 200(%rsp), %r10 + xorq %r9, %rcx + vpsrlq $19, %ymm5, %ymm8 + vpsllq $45, %ymm5, %ymm9 + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + vpsrlq $61, %ymm5, %ymm10 + vpsllq $3, %ymm5, %ymm11 + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm5, %ymm11 + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + vpaddq %ymm6, %ymm8, %ymm6 + # msg_sched done: 24-27 + # msg_sched: 28-29 + rorq $23, %rax + vpalignr $8, %ymm7, %ymm0, %ymm12 + vpalignr $8, %ymm3, %ymm4, %ymm13 + movq %r10, %rdx + movq %r15, %rcx + addq 224(%rsp), %r9 + xorq %r8, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm7, %ymm13, %ymm7 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + vpaddq %ymm7, %ymm8, %ymm7 + movq %r9, %rbx + movq %r14, %rcx + addq 232(%rsp), %r8 + xorq %r15, %rcx + vpsrlq $19, %ymm6, %ymm8 + vpsllq $45, %ymm6, %ymm9 + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + vpsrlq $61, %ymm6, %ymm10 + vpsllq $3, %ymm6, %ymm11 + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm6, %ymm11 + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq %ymm7, %ymm8, %ymm7 + # msg_sched done: 28-31 + addq $0x100, %rsi + addq $0x100, %rsp + cmpq L_avx2_sha512_k_2_end(%rip), %rsi + jne L_sha512_len_avx2_start + vpaddq (%rsi), %ymm0, %ymm8 + vpaddq 32(%rsi), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rsi), %ymm2, %ymm8 + vpaddq 96(%rsi), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + vpaddq 128(%rsi), %ymm4, %ymm8 + vpaddq 160(%rsi), %ymm5, %ymm9 + vmovdqu %ymm8, 128(%rsp) + vmovdqu %ymm9, 160(%rsp) + vpaddq 192(%rsi), %ymm6, %ymm8 + vpaddq 224(%rsi), %ymm7, %ymm9 + vmovdqu %ymm8, 192(%rsp) + vmovdqu %ymm9, 224(%rsp) + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 32(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 40(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 64(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 72(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 96(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 104(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq 128(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 136(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 160(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 168(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 192(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 200(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 224(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 232(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + subq $0x400, %rsp + addq (%rdi), %r8 + addq 8(%rdi), %r9 + addq 16(%rdi), %r10 + addq 24(%rdi), %r11 + addq 32(%rdi), %r12 + addq 40(%rdi), %r13 + addq 48(%rdi), %r14 + addq 56(%rdi), %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + movq %r9, %rbx + movq %r12, %rax + xorq %r10, %rbx + movq $5, %rsi +L_sha512_len_avx2_tail: + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq 16(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 24(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 48(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 56(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 80(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 88(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq 144(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 152(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 176(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 184(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 208(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 216(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 240(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 248(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + addq $0x100, %rsp + subq $0x01, %rsi + jnz L_sha512_len_avx2_tail + addq (%rdi), %r8 + addq 8(%rdi), %r9 + addq 16(%rdi), %r10 + addq 24(%rdi), %r11 + addq 32(%rdi), %r12 + addq 40(%rdi), %r13 + addq 48(%rdi), %r14 + addq 56(%rdi), %r15 + movq 224(%rdi), %rcx + addq $0x40, %rsp + addq $0x100, %rcx + subl $0x100, %ebp + movq %rcx, 224(%rdi) + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + jnz L_sha512_len_avx2_begin +L_sha512_len_avx2_done: + xorq %rax, %rax + vzeroupper + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX2_Len,.-Transform_Sha512_AVX2_Len +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_rorx_sha512_k: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_rorx_sha512_k_2: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 8 +#else +.p2align 3 +#endif /* __APPLE__ */ +L_avx2_rorx_sha512_k_2_end: +.quad 1024+L_avx2_rorx_sha512_k_2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_rorx_sha512_flip_mask: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX2_RORX +.type Transform_Sha512_AVX2_RORX,@function +.align 4 +Transform_Sha512_AVX2_RORX: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX2_RORX +.p2align 2 +_Transform_Sha512_AVX2_RORX: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x88, %rsp + leaq 64(%rdi), %rcx + vmovdqa L_avx2_rorx_sha512_flip_mask(%rip), %ymm15 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + vmovdqu (%rcx), %ymm0 + vmovdqu 32(%rcx), %ymm1 + vpshufb %ymm15, %ymm0, %ymm0 + vpshufb %ymm15, %ymm1, %ymm1 + vmovdqu 64(%rcx), %ymm2 + vmovdqu 96(%rcx), %ymm3 + vpshufb %ymm15, %ymm2, %ymm2 + vpshufb %ymm15, %ymm3, %ymm3 + movl $4, 128(%rsp) + leaq L_avx2_rorx_sha512_k(%rip), %rsi + movq %r9, %rbx + xorq %rdx, %rdx + xorq %r10, %rbx + # set_w_k: 0 + vpaddq (%rsi), %ymm0, %ymm8 + vpaddq 32(%rsi), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rsi), %ymm2, %ymm8 + vpaddq 96(%rsi), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + # Start of 16 rounds +L_sha256_len_avx2_rorx_start: + addq $0x80, %rsi + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpblendd $3, %ymm1, %ymm0, %ymm12 + vpblendd $3, %ymm3, %ymm2, %ymm13 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpermq $57, %ymm12, %ymm12 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpermq $57, %ymm13, %ymm13 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + vperm2I128 $0x81, %ymm3, %ymm3, %ymm14 + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpxor %ymm10, %ymm8, %ymm8 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpaddq %ymm0, %ymm13, %ymm0 + vpaddq %ymm0, %ymm8, %ymm0 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + vpor %ymm11, %ymm10, %ymm10 + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + vpxor %ymm10, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpsrlq $6, %ymm14, %ymm11 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpxor %ymm11, %ymm8, %ymm8 + addq 16(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpaddq %ymm0, %ymm8, %ymm0 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vperm2I128 $8, %ymm0, %ymm0, %ymm14 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + vpor %ymm11, %ymm10, %ymm10 + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpxor %ymm10, %ymm8, %ymm8 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $6, %ymm14, %ymm11 + addq 24(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpxor %ymm11, %ymm8, %ymm8 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpaddq %ymm0, %ymm8, %ymm0 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + vpaddq (%rsi), %ymm0, %ymm8 + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vmovdqu %ymm8, (%rsp) + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpblendd $3, %ymm2, %ymm1, %ymm12 + vpblendd $3, %ymm0, %ymm3, %ymm13 + addq 32(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpermq $57, %ymm12, %ymm12 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpermq $57, %ymm13, %ymm13 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + vperm2I128 $0x81, %ymm0, %ymm0, %ymm14 + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpxor %ymm10, %ymm8, %ymm8 + addq 40(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpaddq %ymm1, %ymm13, %ymm1 + vpaddq %ymm1, %ymm8, %ymm1 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + vpor %ymm11, %ymm10, %ymm10 + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + vpxor %ymm10, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpsrlq $6, %ymm14, %ymm11 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpxor %ymm11, %ymm8, %ymm8 + addq 48(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpaddq %ymm1, %ymm8, %ymm1 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vperm2I128 $8, %ymm1, %ymm1, %ymm14 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + vpor %ymm11, %ymm10, %ymm10 + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpxor %ymm10, %ymm8, %ymm8 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $6, %ymm14, %ymm11 + addq 56(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpxor %ymm11, %ymm8, %ymm8 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpaddq %ymm1, %ymm8, %ymm1 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + vpaddq 32(%rsi), %ymm1, %ymm8 + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vmovdqu %ymm8, 32(%rsp) + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpblendd $3, %ymm3, %ymm2, %ymm12 + vpblendd $3, %ymm1, %ymm0, %ymm13 + addq 64(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpermq $57, %ymm12, %ymm12 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpermq $57, %ymm13, %ymm13 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + vperm2I128 $0x81, %ymm1, %ymm1, %ymm14 + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpxor %ymm10, %ymm8, %ymm8 + addq 72(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpaddq %ymm2, %ymm13, %ymm2 + vpaddq %ymm2, %ymm8, %ymm2 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + vpor %ymm11, %ymm10, %ymm10 + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + vpxor %ymm10, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpsrlq $6, %ymm14, %ymm11 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpxor %ymm11, %ymm8, %ymm8 + addq 80(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpaddq %ymm2, %ymm8, %ymm2 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vperm2I128 $8, %ymm2, %ymm2, %ymm14 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + vpor %ymm11, %ymm10, %ymm10 + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpxor %ymm10, %ymm8, %ymm8 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $6, %ymm14, %ymm11 + addq 88(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpxor %ymm11, %ymm8, %ymm8 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpaddq %ymm2, %ymm8, %ymm2 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + vpaddq 64(%rsi), %ymm2, %ymm8 + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vmovdqu %ymm8, 64(%rsp) + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpblendd $3, %ymm0, %ymm3, %ymm12 + vpblendd $3, %ymm2, %ymm1, %ymm13 + addq 96(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpermq $57, %ymm12, %ymm12 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpermq $57, %ymm13, %ymm13 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + vperm2I128 $0x81, %ymm2, %ymm2, %ymm14 + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpxor %ymm10, %ymm8, %ymm8 + addq 104(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpaddq %ymm3, %ymm13, %ymm3 + vpaddq %ymm3, %ymm8, %ymm3 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + vpor %ymm11, %ymm10, %ymm10 + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + vpxor %ymm10, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpsrlq $6, %ymm14, %ymm11 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpxor %ymm11, %ymm8, %ymm8 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpaddq %ymm3, %ymm8, %ymm3 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vperm2I128 $8, %ymm3, %ymm3, %ymm14 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + vpor %ymm11, %ymm10, %ymm10 + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpxor %ymm10, %ymm8, %ymm8 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $6, %ymm14, %ymm11 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpxor %ymm11, %ymm8, %ymm8 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpaddq %ymm3, %ymm8, %ymm3 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + vpaddq 96(%rsi), %ymm3, %ymm8 + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vmovdqu %ymm8, 96(%rsp) + subl $0x01, 128(%rsp) + jne L_sha256_len_avx2_rorx_start + # rnd_all_4: 0-3 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 16(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 24(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_4: 4-7 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 32(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 40(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 48(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 56(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + # rnd_all_4: 8-11 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq 64(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 72(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 80(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 88(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_4: 12-15 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 96(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 104(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + addq %rdx, %r8 + addq %r8, (%rdi) + addq %r9, 8(%rdi) + addq %r10, 16(%rdi) + addq %r11, 24(%rdi) + addq %r12, 32(%rdi) + addq %r13, 40(%rdi) + addq %r14, 48(%rdi) + addq %r15, 56(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x88, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX2_RORX,.-Transform_Sha512_AVX2_RORX +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX2_RORX_Len +.type Transform_Sha512_AVX2_RORX_Len,@function +.align 4 +Transform_Sha512_AVX2_RORX_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX2_RORX_Len +.p2align 2 +_Transform_Sha512_AVX2_RORX_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + testb $0x80, %sil + je L_sha512_len_avx2_rorx_block + movq 224(%rdi), %rax + push %rsi + vmovdqu (%rax), %ymm0 + vmovdqu 32(%rax), %ymm1 + vmovdqu 64(%rax), %ymm2 + vmovdqu 96(%rax), %ymm3 + vmovups %ymm0, 64(%rdi) + vmovups %ymm1, 96(%rdi) + vmovups %ymm2, 128(%rdi) + vmovups %ymm3, 160(%rdi) +#ifndef __APPLE__ + call Transform_Sha512_AVX2_RORX@plt +#else + call _Transform_Sha512_AVX2_RORX +#endif /* __APPLE__ */ + pop %rsi + addq $0x80, 224(%rdi) + subl $0x80, %esi + jz L_sha512_len_avx2_rorx_done +L_sha512_len_avx2_rorx_block: + movq 224(%rdi), %rax + vmovdqa L_avx2_rorx_sha512_flip_mask(%rip), %ymm15 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + # Start of loop processing two blocks +L_sha512_len_avx2_rorx_begin: + subq $0x540, %rsp + leaq L_avx2_rorx_sha512_k_2(%rip), %rbp + movq %r9, %rbx + xorq %rdx, %rdx + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vinserti128 $0x01, 128(%rax), %ymm0, %ymm0 + vinserti128 $0x01, 144(%rax), %ymm1, %ymm1 + vpshufb %ymm15, %ymm0, %ymm0 + vpshufb %ymm15, %ymm1, %ymm1 + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vinserti128 $0x01, 160(%rax), %ymm2, %ymm2 + vinserti128 $0x01, 176(%rax), %ymm3, %ymm3 + vpshufb %ymm15, %ymm2, %ymm2 + vpshufb %ymm15, %ymm3, %ymm3 + vmovdqu 64(%rax), %xmm4 + vmovdqu 80(%rax), %xmm5 + vinserti128 $0x01, 192(%rax), %ymm4, %ymm4 + vinserti128 $0x01, 208(%rax), %ymm5, %ymm5 + vpshufb %ymm15, %ymm4, %ymm4 + vpshufb %ymm15, %ymm5, %ymm5 + vmovdqu 96(%rax), %xmm6 + vmovdqu 112(%rax), %xmm7 + vinserti128 $0x01, 224(%rax), %ymm6, %ymm6 + vinserti128 $0x01, 240(%rax), %ymm7, %ymm7 + vpshufb %ymm15, %ymm6, %ymm6 + vpshufb %ymm15, %ymm7, %ymm7 + xorq %r10, %rbx + # Start of 16 rounds +L_sha512_len_avx2_rorx_start: + vpaddq (%rbp), %ymm0, %ymm8 + vpaddq 32(%rbp), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rbp), %ymm2, %ymm8 + vpaddq 96(%rbp), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + vpaddq 128(%rbp), %ymm4, %ymm8 + vpaddq 160(%rbp), %ymm5, %ymm9 + vmovdqu %ymm8, 128(%rsp) + vmovdqu %ymm9, 160(%rsp) + vpaddq 192(%rbp), %ymm6, %ymm8 + vpaddq 224(%rbp), %ymm7, %ymm9 + vmovdqu %ymm8, 192(%rsp) + vmovdqu %ymm9, 224(%rsp) + # msg_sched: 0-1 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpalignr $8, %ymm0, %ymm1, %ymm12 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm4, %ymm5, %ymm13 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm0, %ymm13, %ymm0 + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + vpaddq %ymm0, %ymm8, %ymm0 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpsrlq $19, %ymm7, %ymm8 + vpsllq $45, %ymm7, %ymm9 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm7, %ymm10 + vpsllq $3, %ymm7, %ymm11 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm7, %ymm11 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpaddq %ymm0, %ymm8, %ymm0 + # msg_sched done: 0-3 + # msg_sched: 4-5 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpalignr $8, %ymm1, %ymm2, %ymm12 + addq 32(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm5, %ymm6, %ymm13 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm1, %ymm13, %ymm1 + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpaddq %ymm1, %ymm8, %ymm1 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $19, %ymm0, %ymm8 + vpsllq $45, %ymm0, %ymm9 + addq 40(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm0, %ymm10 + vpsllq $3, %ymm0, %ymm11 + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm0, %ymm11 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vpaddq %ymm1, %ymm8, %ymm1 + # msg_sched done: 4-7 + # msg_sched: 8-9 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpalignr $8, %ymm2, %ymm3, %ymm12 + addq 64(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm6, %ymm7, %ymm13 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm2, %ymm13, %ymm2 + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + vpaddq %ymm2, %ymm8, %ymm2 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpsrlq $19, %ymm1, %ymm8 + vpsllq $45, %ymm1, %ymm9 + addq 72(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm1, %ymm10 + vpsllq $3, %ymm1, %ymm11 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm1, %ymm11 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpaddq %ymm2, %ymm8, %ymm2 + # msg_sched done: 8-11 + # msg_sched: 12-13 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpalignr $8, %ymm3, %ymm4, %ymm12 + addq 96(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm7, %ymm0, %ymm13 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm3, %ymm13, %ymm3 + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpaddq %ymm3, %ymm8, %ymm3 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $19, %ymm2, %ymm8 + vpsllq $45, %ymm2, %ymm9 + addq 104(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm2, %ymm10 + vpsllq $3, %ymm2, %ymm11 + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm2, %ymm11 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vpaddq %ymm3, %ymm8, %ymm3 + # msg_sched done: 12-15 + # msg_sched: 16-17 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpalignr $8, %ymm4, %ymm5, %ymm12 + addq 128(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm0, %ymm1, %ymm13 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm4, %ymm13, %ymm4 + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + vpaddq %ymm4, %ymm8, %ymm4 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpsrlq $19, %ymm3, %ymm8 + vpsllq $45, %ymm3, %ymm9 + addq 136(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm3, %ymm10 + vpsllq $3, %ymm3, %ymm11 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm3, %ymm11 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpaddq %ymm4, %ymm8, %ymm4 + # msg_sched done: 16-19 + # msg_sched: 20-21 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpalignr $8, %ymm5, %ymm6, %ymm12 + addq 160(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm1, %ymm2, %ymm13 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm5, %ymm13, %ymm5 + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpaddq %ymm5, %ymm8, %ymm5 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $19, %ymm4, %ymm8 + vpsllq $45, %ymm4, %ymm9 + addq 168(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm4, %ymm10 + vpsllq $3, %ymm4, %ymm11 + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm4, %ymm11 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vpaddq %ymm5, %ymm8, %ymm5 + # msg_sched done: 20-23 + # msg_sched: 24-25 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpalignr $8, %ymm6, %ymm7, %ymm12 + addq 192(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm2, %ymm3, %ymm13 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm6, %ymm13, %ymm6 + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + vpaddq %ymm6, %ymm8, %ymm6 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpsrlq $19, %ymm5, %ymm8 + vpsllq $45, %ymm5, %ymm9 + addq 200(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm5, %ymm10 + vpsllq $3, %ymm5, %ymm11 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm5, %ymm11 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpaddq %ymm6, %ymm8, %ymm6 + # msg_sched done: 24-27 + # msg_sched: 28-29 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpalignr $8, %ymm7, %ymm0, %ymm12 + addq 224(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm3, %ymm4, %ymm13 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm7, %ymm13, %ymm7 + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpaddq %ymm7, %ymm8, %ymm7 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $19, %ymm6, %ymm8 + vpsllq $45, %ymm6, %ymm9 + addq 232(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm6, %ymm10 + vpsllq $3, %ymm6, %ymm11 + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm6, %ymm11 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vpaddq %ymm7, %ymm8, %ymm7 + # msg_sched done: 28-31 + addq $0x100, %rbp + addq $0x100, %rsp + cmpq L_avx2_rorx_sha512_k_2_end(%rip), %rbp + jne L_sha512_len_avx2_rorx_start + vpaddq (%rbp), %ymm0, %ymm8 + vpaddq 32(%rbp), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rbp), %ymm2, %ymm8 + vpaddq 96(%rbp), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + vpaddq 128(%rbp), %ymm4, %ymm8 + vpaddq 160(%rbp), %ymm5, %ymm9 + vmovdqu %ymm8, 128(%rsp) + vmovdqu %ymm9, 160(%rsp) + vpaddq 192(%rbp), %ymm6, %ymm8 + vpaddq 224(%rbp), %ymm7, %ymm9 + vmovdqu %ymm8, 192(%rsp) + vmovdqu %ymm9, 224(%rsp) + # rnd_all_2: 0-1 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 4-5 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 32(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 40(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 8-9 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 64(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 72(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 12-13 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 96(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 104(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + # rnd_all_2: 16-17 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq 128(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 136(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 20-21 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 160(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 168(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 24-25 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 192(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 200(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 28-29 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 224(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 232(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + addq %rdx, %r8 + subq $0x400, %rsp + addq (%rdi), %r8 + addq 8(%rdi), %r9 + addq 16(%rdi), %r10 + addq 24(%rdi), %r11 + addq 32(%rdi), %r12 + addq 40(%rdi), %r13 + addq 48(%rdi), %r14 + addq 56(%rdi), %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + movq %r9, %rbx + xorq %rdx, %rdx + xorq %r10, %rbx + movq $5, %rbp +L_sha512_len_avx2_rorx_tail: + # rnd_all_2: 2-3 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq 16(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 24(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 6-7 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 48(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 56(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 10-11 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 80(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 88(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 14-15 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + # rnd_all_2: 18-19 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq 144(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 152(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 22-23 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 176(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 184(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 26-27 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 208(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 216(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 30-31 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 240(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 248(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + addq $0x100, %rsp + subq $0x01, %rbp + jnz L_sha512_len_avx2_rorx_tail + addq %rdx, %r8 + addq (%rdi), %r8 + addq 8(%rdi), %r9 + addq 16(%rdi), %r10 + addq 24(%rdi), %r11 + addq 32(%rdi), %r12 + addq 40(%rdi), %r13 + addq 48(%rdi), %r14 + addq 56(%rdi), %r15 + movq 224(%rdi), %rax + addq $0x40, %rsp + addq $0x100, %rax + subl $0x100, %esi + movq %rax, 224(%rdi) + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + jnz L_sha512_len_avx2_rorx_begin +L_sha512_len_avx2_rorx_done: + xorq %rax, %rax + vzeroupper + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX2_RORX_Len,.-Transform_Sha512_AVX2_RORX_Len +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/signature.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/signature.c new file mode 100644 index 000000000..5d503338a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/signature.c @@ -0,0 +1,559 @@ +/* signature.c + * + * Copyright (C) 2006-2020 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 +#include +#include +#ifndef NO_ASN +#include +#endif +#ifdef HAVE_ECC +#include +#endif +#ifndef NO_RSA +#include +#endif + +/* If ECC and RSA are disabled then disable signature wrapper */ +#if (!defined(HAVE_ECC) || (defined(HAVE_ECC) && !defined(HAVE_ECC_SIGN) \ + && !defined(HAVE_ECC_VERIFY))) && defined(NO_RSA) + #undef NO_SIG_WRAPPER + #define NO_SIG_WRAPPER +#endif + +/* Signature wrapper disabled check */ +#ifndef NO_SIG_WRAPPER + +#if !defined(NO_RSA) && !defined(NO_ASN) +static int wc_SignatureDerEncode(enum wc_HashType hash_type, byte* hash_data, + word32 hash_len, word32* hash_enc_len) +{ + int ret, oid; + + ret = wc_HashGetOID(hash_type); + if (ret < 0) { + return ret; + } + oid = ret; + + ret = wc_EncodeSignature(hash_data, hash_data, hash_len, oid); + if (ret > 0) { + *hash_enc_len = ret; + ret = 0; + } + + return ret; +} +#endif /* !NO_RSA && !NO_ASN */ + +int wc_SignatureGetSize(enum wc_SignatureType sig_type, + const void* key, word32 key_len) +{ + int sig_len = BAD_FUNC_ARG; + + /* Suppress possible unused args if all signature types are disabled */ + (void)key; + (void)key_len; + + switch(sig_type) { + case WC_SIGNATURE_TYPE_ECC: +#ifdef HAVE_ECC + /* Sanity check that void* key is at least ecc_key in size */ + if (key_len >= sizeof(ecc_key)) { + sig_len = wc_ecc_sig_size((ecc_key*)key); + } + else { + WOLFSSL_MSG("wc_SignatureGetSize: Invalid ECC key size"); + } +#else + sig_len = SIG_TYPE_E; +#endif + break; + + case WC_SIGNATURE_TYPE_RSA_W_ENC: + case WC_SIGNATURE_TYPE_RSA: +#ifndef NO_RSA + /* Sanity check that void* key is at least RsaKey in size */ + if (key_len >= sizeof(RsaKey)) { + sig_len = wc_RsaEncryptSize((RsaKey*)key); + } + else { + WOLFSSL_MSG("wc_SignatureGetSize: Invalid RsaKey key size"); + } +#else + sig_len = SIG_TYPE_E; +#endif + break; + + case WC_SIGNATURE_TYPE_NONE: + default: + sig_len = BAD_FUNC_ARG; + break; + } + return sig_len; +} + +int wc_SignatureVerifyHash( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* hash_data, word32 hash_len, + const byte* sig, word32 sig_len, + const void* key, word32 key_len) +{ + int ret; + + /* Check arguments */ + if (hash_data == NULL || hash_len == 0 || + sig == NULL || sig_len == 0 || + key == NULL || key_len == 0) { + return BAD_FUNC_ARG; + } + + /* Validate signature len (1 to max is okay) */ + if ((int)sig_len > wc_SignatureGetSize(sig_type, key, key_len)) { + WOLFSSL_MSG("wc_SignatureVerify: Invalid sig type/len"); + return BAD_FUNC_ARG; + } + + /* Validate hash size */ + ret = wc_HashGetDigestSize(hash_type); + if (ret < 0) { + WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len"); + return ret; + } + ret = 0; + + /* Verify signature using hash */ + switch (sig_type) { + case WC_SIGNATURE_TYPE_ECC: + { +#if defined(HAVE_ECC) && defined(HAVE_ECC_VERIFY) + int is_valid_sig = 0; + + /* Perform verification of signature using provided ECC 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; + } +#else + ret = SIG_TYPE_E; +#endif + break; + } + + case WC_SIGNATURE_TYPE_RSA_W_ENC: + case WC_SIGNATURE_TYPE_RSA: + { +#ifndef NO_RSA +#if defined(WOLFSSL_CRYPTOCELL) + /* the signature must propagate to the cryptocell to get verfied */ + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + ret = cc310_RsaSSL_Verify(hash_data, hash_len,(byte*)sig, key, + CRYS_RSA_HASH_SHA256_mode); + } + else { + ret = cc310_RsaSSL_Verify(hash_data, hash_len,(byte*)sig, key, + CRYS_RSA_After_SHA256_mode); + } + + if (ret != 0) { + WOLFSSL_MSG("RSA Signature Verify difference!"); + ret = SIG_VERIFY_E; + } + +#else /* WOLFSSL_CRYPTOCELL */ + + word32 plain_len = hash_len; + byte *plain_data; + + /* Make sure the plain text output is at least key size */ + if (plain_len < sig_len) { + plain_len = sig_len; + } + plain_data = (byte*)XMALLOC(plain_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (plain_data) { + /* Perform verification of signature using provided RSA 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) { + ret = 0; /* Success */ + } + else { + WOLFSSL_MSG("RSA Signature Verify difference!"); + ret = SIG_VERIFY_E; + } + } + XFREE(plain_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + else { + ret = MEMORY_E; + } +#endif /* !WOLFSSL_CRYPTOCELL */ +#else + ret = SIG_TYPE_E; +#endif + break; + } + + case WC_SIGNATURE_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + break; + } + + return ret; +} + +int wc_SignatureVerify( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + const byte* sig, word32 sig_len, + const void* key, word32 key_len) +{ + int ret; + word32 hash_len, hash_enc_len; +#if defined(WOLFSSL_SMALL_STACK) || defined(NO_ASN) + byte *hash_data; +#else + byte hash_data[MAX_DER_DIGEST_SZ]; +#endif + + /* Check arguments */ + if (data == NULL || data_len == 0 || + sig == NULL || sig_len == 0 || + key == NULL || key_len == 0) { + return BAD_FUNC_ARG; + } + + /* Validate signature len (1 to max is okay) */ + if ((int)sig_len > wc_SignatureGetSize(sig_type, key, key_len)) { + WOLFSSL_MSG("wc_SignatureVerify: Invalid sig type/len"); + return BAD_FUNC_ARG; + } + + /* Validate hash size */ + ret = wc_HashGetDigestSize(hash_type); + if (ret < 0) { + WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len"); + return ret; + } + hash_enc_len = hash_len = ret; + +#ifndef NO_RSA + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + /* For RSA with ASN.1 encoding include room */ + hash_enc_len += MAX_DER_DIGEST_ASN_SZ; + } +#endif + +#if defined(WOLFSSL_SMALL_STACK) || defined(NO_ASN) + /* Allocate temporary buffer for hash data */ + hash_data = (byte*)XMALLOC(hash_enc_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (hash_data == NULL) { + return MEMORY_E; + } +#endif + + /* Perform hash of data */ + ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); + if (ret == 0) { + /* Handle RSA with DER encoding */ + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + #if defined(NO_RSA) || defined(NO_ASN) + ret = SIG_TYPE_E; + #else + ret = wc_SignatureDerEncode(hash_type, hash_data, hash_len, + &hash_enc_len); + #endif + } + + if (ret == 0) { +#if defined(WOLFSSL_CRYPTOCELL) + if ((sig_type == WC_SIGNATURE_TYPE_RSA) + || (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC)) { + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + ret = cc310_RsaSSL_Verify(hash_data, hash_len, sig, key, + cc310_hashModeRSA(hash_type, 0)); + } + else { + ret = cc310_RsaSSL_Verify(hash_data, hash_len, sig, key, + cc310_hashModeRSA(hash_type, 1)); + } + } +#else + /* Verify signature using hash */ + ret = wc_SignatureVerifyHash(hash_type, sig_type, + hash_data, hash_enc_len, sig, sig_len, key, key_len); +#endif /* WOLFSSL_CRYPTOCELL */ + } + } + +#if defined(WOLFSSL_SMALL_STACK) || defined(NO_ASN) + XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +int wc_SignatureGenerateHash( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* hash_data, word32 hash_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, WC_RNG* rng) +{ + return wc_SignatureGenerateHash_ex(hash_type, sig_type, hash_data, hash_len, + sig, sig_len, key, key_len, rng, 1); +} + +int wc_SignatureGenerateHash_ex( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* hash_data, word32 hash_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, WC_RNG* rng, int verify) +{ + int ret; + + /* Suppress possible unused arg if all signature types are disabled */ + (void)rng; + + /* Check arguments */ + if (hash_data == NULL || hash_len == 0 || + sig == NULL || sig_len == NULL || *sig_len == 0 || + key == NULL || key_len == 0) { + return BAD_FUNC_ARG; + } + + /* Validate signature len (needs to be at least max) */ + if ((int)*sig_len < wc_SignatureGetSize(sig_type, key, key_len)) { + WOLFSSL_MSG("wc_SignatureGenerate: Invalid sig type/len"); + return BAD_FUNC_ARG; + } + + /* Validate hash size */ + ret = wc_HashGetDigestSize(hash_type); + if (ret < 0) { + WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len"); + return ret; + } + ret = 0; + + /* Create signature using hash as data */ + switch (sig_type) { + case WC_SIGNATURE_TYPE_ECC: +#if defined(HAVE_ECC) && defined(HAVE_ECC_SIGN) + /* Create signature using provided ECC 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 + break; + + case WC_SIGNATURE_TYPE_RSA_W_ENC: + case WC_SIGNATURE_TYPE_RSA: +#if !defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) + #if defined(WOLFSSL_CRYPTOCELL) + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + ret = cc310_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, key, + cc310_hashModeRSA(hash_type, 0)); + } + else { + ret = cc310_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, key, + cc310_hashModeRSA(hash_type, 1)); + } + #else + /* Create signature using provided RSA 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_Sign(hash_data, hash_len, sig, *sig_len, + (RsaKey*)key, rng); + } while (ret == WC_PENDING_E); + #endif /* WOLFSSL_CRYPTOCELL */ + if (ret >= 0) { + *sig_len = ret; + ret = 0; /* Success */ + } +#else + ret = SIG_TYPE_E; +#endif + break; + + case WC_SIGNATURE_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + break; + } + + if (ret == 0 && verify) { + ret = wc_SignatureVerifyHash(hash_type, sig_type, hash_data, hash_len, + sig, *sig_len, key, key_len); + } + + return ret; +} + +int wc_SignatureGenerate( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, WC_RNG* rng) +{ + return wc_SignatureGenerate_ex(hash_type, sig_type, data, data_len, sig, + sig_len, key, key_len, rng, 1); +} + +int wc_SignatureGenerate_ex( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, WC_RNG* rng, int verify) +{ + int ret; + word32 hash_len, hash_enc_len; +#if defined(WOLFSSL_SMALL_STACK) || defined(NO_ASN) + byte *hash_data; +#else + byte hash_data[MAX_DER_DIGEST_SZ]; +#endif + + /* Check arguments */ + if (data == NULL || data_len == 0 || + sig == NULL || sig_len == NULL || *sig_len == 0 || + key == NULL || key_len == 0) { + return BAD_FUNC_ARG; + } + + /* Validate signature len (needs to be at least max) */ + if ((int)*sig_len < wc_SignatureGetSize(sig_type, key, key_len)) { + WOLFSSL_MSG("wc_SignatureGenerate: Invalid sig type/len"); + return BAD_FUNC_ARG; + } + + /* Validate hash size */ + ret = wc_HashGetDigestSize(hash_type); + if (ret < 0) { + WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len"); + return ret; + } + hash_enc_len = hash_len = ret; + +#if !defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + /* For RSA with ASN.1 encoding include room */ + hash_enc_len += MAX_DER_DIGEST_ASN_SZ; + } +#endif + +#if defined(WOLFSSL_SMALL_STACK) || defined(NO_ASN) + /* Allocate temporary buffer for hash data */ + hash_data = (byte*)XMALLOC(hash_enc_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (hash_data == NULL) { + return MEMORY_E; + } +#endif + + /* Perform hash of data */ + ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); + if (ret == 0) { + /* Handle RSA with DER encoding */ + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + #if defined(NO_RSA) || defined(NO_ASN) || \ + defined(WOLFSSL_RSA_PUBLIC_ONLY) + ret = SIG_TYPE_E; + #else + ret = wc_SignatureDerEncode(hash_type, hash_data, hash_len, + &hash_enc_len); + #endif + } + if (ret == 0) { +#if defined(WOLFSSL_CRYPTOCELL) + if ((sig_type == WC_SIGNATURE_TYPE_RSA) + || (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC)) { + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + ret = cc310_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, + key, cc310_hashModeRSA(hash_type, 0)); + } + else { + ret = cc310_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, + key, cc310_hashModeRSA(hash_type, 1)); + } + + if (ret == *sig_len) { + ret = 0; + } + } + } + } +#else + /* Generate signature using hash */ + ret = wc_SignatureGenerateHash(hash_type, sig_type, + hash_data, hash_enc_len, sig, sig_len, key, key_len, rng); + } + } + + if (ret == 0 && verify) { + ret = wc_SignatureVerifyHash(hash_type, sig_type, hash_data, + hash_enc_len, sig, *sig_len, key, key_len); + } +#endif /* WOLFSSL_CRYPTOCELL */ + +#if defined(WOLFSSL_SMALL_STACK) || defined(NO_ASN) + XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* NO_SIG_WRAPPER */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_arm32.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_arm32.c new file mode 100644 index 000000000..4540dde65 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_arm32.c @@ -0,0 +1,89057 @@ +/* sp.c + * + * Copyright (C) 2006-2020 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 +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifdef WOLFSSL_SP_ARM32_ASM +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * 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<64 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + 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_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "mov r10, #0\n\t" + "# A[0] * B[0]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r3, r4, r8, r9\n\t" + "mov r5, #0\n\t" + "str r3, [sp]\n\t" + "# A[0] * B[1]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[0]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #4]\n\t" + "# A[0] * B[2]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #8]\n\t" + "# A[0] * B[3]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[2]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[1]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #12]\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[3]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #16]\n\t" + "# A[0] * B[5]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[4]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[3]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[2]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[1]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #20]\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #24]\n\t" + "# A[0] * B[7]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[6]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[5]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[4]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[3]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[2]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[1]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #28]\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[2]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[1]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[2] * B[7]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[3] * B[6]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[5]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[3]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[2]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[4] * B[6]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[3]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[4] * B[7]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[5] * B[6]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[5]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[5] * B[7]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[5]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[6] * B[7]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[7] * B[6]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[7] * B[7]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r7\n\t" + "str r5, [%[r], #56]\n\t" + "str r3, [%[r], #60]\n\t" + "ldr r3, [sp, #0]\n\t" + "ldr r4, [sp, #4]\n\t" + "ldr r5, [sp, #8]\n\t" + "ldr r6, [sp, #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [sp, #16]\n\t" + "ldr r4, [sp, #20]\n\t" + "ldr r5, [sp, #24]\n\t" + "ldr r6, [sp, #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "add sp, sp, #32\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +} + +/* 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_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "mov r14, #0\n\t" + "# A[0] * A[0]\n\t" + "ldr r10, [%[a], #0]\n\t" + "umull r8, r3, r10, r10\n\t" + "mov r4, #0\n\t" + "str r8, [sp]\n\t" + "# A[0] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[1] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[1] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[1] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[2] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #28]\n\t" + "# A[1] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[2] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #32]\n\t" + "# A[2] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[3] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #36]\n\t" + "# A[3] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[4] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[5] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #40]\n\t" + "# A[4] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[5] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [%[r], #44]\n\t" + "# A[5] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[6] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [%[r], #48]\n\t" + "# A[6] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #52]\n\t" + "# A[7] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adc r2, r2, r9\n\t" + "str r4, [%[r], #56]\n\t" + "str r2, [%[r], #60]\n\t" + "ldr r2, [sp, #0]\n\t" + "ldr r3, [sp, #4]\n\t" + "ldr r4, [sp, #8]\n\t" + "ldr r8, [sp, #12]\n\t" + "str r2, [%[r], #0]\n\t" + "str r3, [%[r], #4]\n\t" + "str r4, [%[r], #8]\n\t" + "str r8, [%[r], #12]\n\t" + "ldr r2, [sp, #16]\n\t" + "ldr r3, [sp, #20]\n\t" + "ldr r4, [sp, #24]\n\t" + "ldr r8, [sp, #28]\n\t" + "str r2, [%[r], #16]\n\t" + "str r3, [%[r], #20]\n\t" + "str r4, [%[r], #24]\n\t" + "str r8, [%[r], #28]\n\t" + "add sp, sp, #32\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14" + ); +} + +/* 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_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + 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_16(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "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_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + 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_8(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[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. + */ +SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit b1[8]; + sp_digit z2[16]; + sp_digit u, ca, cb; + + ca = sp_2048_add_8(a1, a, &a[8]); + cb = sp_2048_add_8(b1, b, &b[8]); + u = ca & cb; + sp_2048_mul_8(z1, a1, b1); + sp_2048_mul_8(z2, &a[8], &b[8]); + sp_2048_mul_8(z0, a, b); + sp_2048_mask_8(r + 16, a1, 0 - cb); + sp_2048_mask_8(b1, b1, 0 - ca); + u += sp_2048_add_8(r + 16, r + 16, b1); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + (void)sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[16]; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit u; + + u = sp_2048_add_8(a1, a, &a[8]); + sp_2048_sqr_8(z1, a1); + sp_2048_sqr_8(z2, &a[8]); + sp_2048_sqr_8(z0, a); + sp_2048_mask_8(r + 16, a1, 0 - u); + u += sp_2048_add_8(r + 16, r + 16, r + 16); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + (void)sp_2048_add_16(r + 16, r + 16, z2); +} + +/* 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__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "ldr r2, [%[a], #64]\n\t" + "ldr r3, [%[a], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "ldr r8, [%[b], #72]\n\t" + "ldr r9, [%[b], #76]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #64]\n\t" + "str r3, [%[a], #68]\n\t" + "str r4, [%[a], #72]\n\t" + "str r5, [%[a], #76]\n\t" + "ldr r2, [%[a], #80]\n\t" + "ldr r3, [%[a], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "ldr r8, [%[b], #88]\n\t" + "ldr r9, [%[b], #92]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #80]\n\t" + "str r3, [%[a], #84]\n\t" + "str r4, [%[a], #88]\n\t" + "str r5, [%[a], #92]\n\t" + "ldr r2, [%[a], #96]\n\t" + "ldr r3, [%[a], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "ldr r8, [%[b], #104]\n\t" + "ldr r9, [%[b], #108]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #96]\n\t" + "str r3, [%[a], #100]\n\t" + "str r4, [%[a], #104]\n\t" + "str r5, [%[a], #108]\n\t" + "ldr r2, [%[a], #112]\n\t" + "ldr r3, [%[a], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "ldr r8, [%[b], #120]\n\t" + "ldr r9, [%[b], #124]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #112]\n\t" + "str r3, [%[a], #116]\n\t" + "str r4, [%[a], #120]\n\t" + "str r5, [%[a], #124]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "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__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "ldr r8, [%[b], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "ldr r10, [%[b], #104]\n\t" + "ldr r14, [%[b], #108]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "ldr r8, [%[b], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "ldr r10, [%[b], #120]\n\t" + "ldr r14, [%[b], #124]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + 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, const 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. + */ +SP_NOINLINE 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)); + (void)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. + */ +SP_NOINLINE 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)); + (void)sp_2048_add_32(r + 32, r + 32, z2); +} + +/* 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_64(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "ldr r2, [%[a], #64]\n\t" + "ldr r3, [%[a], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "ldr r8, [%[b], #72]\n\t" + "ldr r9, [%[b], #76]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #64]\n\t" + "str r3, [%[a], #68]\n\t" + "str r4, [%[a], #72]\n\t" + "str r5, [%[a], #76]\n\t" + "ldr r2, [%[a], #80]\n\t" + "ldr r3, [%[a], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "ldr r8, [%[b], #88]\n\t" + "ldr r9, [%[b], #92]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #80]\n\t" + "str r3, [%[a], #84]\n\t" + "str r4, [%[a], #88]\n\t" + "str r5, [%[a], #92]\n\t" + "ldr r2, [%[a], #96]\n\t" + "ldr r3, [%[a], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "ldr r8, [%[b], #104]\n\t" + "ldr r9, [%[b], #108]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #96]\n\t" + "str r3, [%[a], #100]\n\t" + "str r4, [%[a], #104]\n\t" + "str r5, [%[a], #108]\n\t" + "ldr r2, [%[a], #112]\n\t" + "ldr r3, [%[a], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "ldr r8, [%[b], #120]\n\t" + "ldr r9, [%[b], #124]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #112]\n\t" + "str r3, [%[a], #116]\n\t" + "str r4, [%[a], #120]\n\t" + "str r5, [%[a], #124]\n\t" + "ldr r2, [%[a], #128]\n\t" + "ldr r3, [%[a], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[a], #140]\n\t" + "ldr r6, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "ldr r8, [%[b], #136]\n\t" + "ldr r9, [%[b], #140]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #128]\n\t" + "str r3, [%[a], #132]\n\t" + "str r4, [%[a], #136]\n\t" + "str r5, [%[a], #140]\n\t" + "ldr r2, [%[a], #144]\n\t" + "ldr r3, [%[a], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[a], #156]\n\t" + "ldr r6, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "ldr r8, [%[b], #152]\n\t" + "ldr r9, [%[b], #156]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #144]\n\t" + "str r3, [%[a], #148]\n\t" + "str r4, [%[a], #152]\n\t" + "str r5, [%[a], #156]\n\t" + "ldr r2, [%[a], #160]\n\t" + "ldr r3, [%[a], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[a], #172]\n\t" + "ldr r6, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "ldr r8, [%[b], #168]\n\t" + "ldr r9, [%[b], #172]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #160]\n\t" + "str r3, [%[a], #164]\n\t" + "str r4, [%[a], #168]\n\t" + "str r5, [%[a], #172]\n\t" + "ldr r2, [%[a], #176]\n\t" + "ldr r3, [%[a], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[a], #188]\n\t" + "ldr r6, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "ldr r8, [%[b], #184]\n\t" + "ldr r9, [%[b], #188]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #176]\n\t" + "str r3, [%[a], #180]\n\t" + "str r4, [%[a], #184]\n\t" + "str r5, [%[a], #188]\n\t" + "ldr r2, [%[a], #192]\n\t" + "ldr r3, [%[a], #196]\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r5, [%[a], #204]\n\t" + "ldr r6, [%[b], #192]\n\t" + "ldr r7, [%[b], #196]\n\t" + "ldr r8, [%[b], #200]\n\t" + "ldr r9, [%[b], #204]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #192]\n\t" + "str r3, [%[a], #196]\n\t" + "str r4, [%[a], #200]\n\t" + "str r5, [%[a], #204]\n\t" + "ldr r2, [%[a], #208]\n\t" + "ldr r3, [%[a], #212]\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r5, [%[a], #220]\n\t" + "ldr r6, [%[b], #208]\n\t" + "ldr r7, [%[b], #212]\n\t" + "ldr r8, [%[b], #216]\n\t" + "ldr r9, [%[b], #220]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #208]\n\t" + "str r3, [%[a], #212]\n\t" + "str r4, [%[a], #216]\n\t" + "str r5, [%[a], #220]\n\t" + "ldr r2, [%[a], #224]\n\t" + "ldr r3, [%[a], #228]\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r5, [%[a], #236]\n\t" + "ldr r6, [%[b], #224]\n\t" + "ldr r7, [%[b], #228]\n\t" + "ldr r8, [%[b], #232]\n\t" + "ldr r9, [%[b], #236]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #224]\n\t" + "str r3, [%[a], #228]\n\t" + "str r4, [%[a], #232]\n\t" + "str r5, [%[a], #236]\n\t" + "ldr r2, [%[a], #240]\n\t" + "ldr r3, [%[a], #244]\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r5, [%[a], #252]\n\t" + "ldr r6, [%[b], #240]\n\t" + "ldr r7, [%[b], #244]\n\t" + "ldr r8, [%[b], #248]\n\t" + "ldr r9, [%[b], #252]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #240]\n\t" + "str r3, [%[a], #244]\n\t" + "str r4, [%[a], #248]\n\t" + "str r5, [%[a], #252]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "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_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "ldr r8, [%[b], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "ldr r10, [%[b], #104]\n\t" + "ldr r14, [%[b], #108]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "ldr r8, [%[b], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "ldr r10, [%[b], #120]\n\t" + "ldr r14, [%[b], #124]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[a], #132]\n\t" + "ldr r6, [%[a], #136]\n\t" + "ldr r7, [%[a], #140]\n\t" + "ldr r8, [%[b], #128]\n\t" + "ldr r9, [%[b], #132]\n\t" + "ldr r10, [%[b], #136]\n\t" + "ldr r14, [%[b], #140]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #128]\n\t" + "str r5, [%[r], #132]\n\t" + "str r6, [%[r], #136]\n\t" + "str r7, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[a], #148]\n\t" + "ldr r6, [%[a], #152]\n\t" + "ldr r7, [%[a], #156]\n\t" + "ldr r8, [%[b], #144]\n\t" + "ldr r9, [%[b], #148]\n\t" + "ldr r10, [%[b], #152]\n\t" + "ldr r14, [%[b], #156]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #144]\n\t" + "str r5, [%[r], #148]\n\t" + "str r6, [%[r], #152]\n\t" + "str r7, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[a], #164]\n\t" + "ldr r6, [%[a], #168]\n\t" + "ldr r7, [%[a], #172]\n\t" + "ldr r8, [%[b], #160]\n\t" + "ldr r9, [%[b], #164]\n\t" + "ldr r10, [%[b], #168]\n\t" + "ldr r14, [%[b], #172]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #160]\n\t" + "str r5, [%[r], #164]\n\t" + "str r6, [%[r], #168]\n\t" + "str r7, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[a], #180]\n\t" + "ldr r6, [%[a], #184]\n\t" + "ldr r7, [%[a], #188]\n\t" + "ldr r8, [%[b], #176]\n\t" + "ldr r9, [%[b], #180]\n\t" + "ldr r10, [%[b], #184]\n\t" + "ldr r14, [%[b], #188]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #176]\n\t" + "str r5, [%[r], #180]\n\t" + "str r6, [%[r], #184]\n\t" + "str r7, [%[r], #188]\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r5, [%[a], #196]\n\t" + "ldr r6, [%[a], #200]\n\t" + "ldr r7, [%[a], #204]\n\t" + "ldr r8, [%[b], #192]\n\t" + "ldr r9, [%[b], #196]\n\t" + "ldr r10, [%[b], #200]\n\t" + "ldr r14, [%[b], #204]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #192]\n\t" + "str r5, [%[r], #196]\n\t" + "str r6, [%[r], #200]\n\t" + "str r7, [%[r], #204]\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r5, [%[a], #212]\n\t" + "ldr r6, [%[a], #216]\n\t" + "ldr r7, [%[a], #220]\n\t" + "ldr r8, [%[b], #208]\n\t" + "ldr r9, [%[b], #212]\n\t" + "ldr r10, [%[b], #216]\n\t" + "ldr r14, [%[b], #220]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #208]\n\t" + "str r5, [%[r], #212]\n\t" + "str r6, [%[r], #216]\n\t" + "str r7, [%[r], #220]\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r5, [%[a], #228]\n\t" + "ldr r6, [%[a], #232]\n\t" + "ldr r7, [%[a], #236]\n\t" + "ldr r8, [%[b], #224]\n\t" + "ldr r9, [%[b], #228]\n\t" + "ldr r10, [%[b], #232]\n\t" + "ldr r14, [%[b], #236]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #224]\n\t" + "str r5, [%[r], #228]\n\t" + "str r6, [%[r], #232]\n\t" + "str r7, [%[r], #236]\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r5, [%[a], #244]\n\t" + "ldr r6, [%[a], #248]\n\t" + "ldr r7, [%[a], #252]\n\t" + "ldr r8, [%[b], #240]\n\t" + "ldr r9, [%[b], #244]\n\t" + "ldr r10, [%[b], #248]\n\t" + "ldr r14, [%[b], #252]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #240]\n\t" + "str r5, [%[r], #244]\n\t" + "str r6, [%[r], #248]\n\t" + "str r7, [%[r], #252]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + 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_32(sp_digit* r, const 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 +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit b1[32]; + sp_digit z2[64]; + sp_digit u, ca, cb; + + ca = sp_2048_add_32(a1, a, &a[32]); + cb = sp_2048_add_32(b1, b, &b[32]); + u = ca & cb; + sp_2048_mul_32(z1, a1, b1); + sp_2048_mul_32(z2, &a[32], &b[32]); + sp_2048_mul_32(z0, a, b); + sp_2048_mask_32(r + 64, a1, 0 - cb); + sp_2048_mask_32(b1, b1, 0 - ca); + u += sp_2048_add_32(r + 64, r + 64, b1); + u += sp_2048_sub_in_place_64(z1, z2); + u += sp_2048_sub_in_place_64(z1, z0); + u += sp_2048_add_64(r + 32, r + 32, z1); + r[96] = u; + XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1)); + (void)sp_2048_add_64(r + 64, r + 64, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[64]; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit u; + + u = sp_2048_add_32(a1, a, &a[32]); + sp_2048_sqr_32(z1, a1); + sp_2048_sqr_32(z2, &a[32]); + sp_2048_sqr_32(z0, a); + sp_2048_mask_32(r + 64, a1, 0 - u); + u += sp_2048_add_32(r + 64, r + 64, r + 64); + u += sp_2048_sub_in_place_64(z1, z2); + u += sp_2048_sub_in_place_64(z1, z0); + u += sp_2048_add_64(r + 32, r + 32, z1); + r[96] = u; + XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1)); + (void)sp_2048_add_64(r + 64, r + 64, z2); +} + +#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 sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #256\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_sub_in_place_64(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r14, #0\n\t" + "add r12, %[a], #256\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#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_64(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #512\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #252\n\t" + "it cc\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #256\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #504\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* 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_64(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #512\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #252\n\t" + "it cc\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #256\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #504\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<32; i++) { + r[i] = a[i] & m; + } +} + +#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 sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #128\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * 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__ ( + "mov r14, #0\n\t" + "add r12, %[a], #128\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#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_32(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #256\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #124\n\t" + "it cc\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #128\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #248\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* 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) +{ + __asm__ __volatile__ ( + "sub sp, sp, #256\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #124\n\t" + "it cc\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #128\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #248\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* 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_64(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #256\n\t" + "blt 1b\n\t" + "str r3, [%[r], #256]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #28]\n\t" + "# A[8] * B\n\t" + "ldr r8, [%[a], #32]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[9] * B\n\t" + "ldr r8, [%[a], #36]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[10] * B\n\t" + "ldr r8, [%[a], #40]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[11] * B\n\t" + "ldr r8, [%[a], #44]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[12] * B\n\t" + "ldr r8, [%[a], #48]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[13] * B\n\t" + "ldr r8, [%[a], #52]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[14] * B\n\t" + "ldr r8, [%[a], #56]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #56]\n\t" + "# A[15] * B\n\t" + "ldr r8, [%[a], #60]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #60]\n\t" + "# A[16] * B\n\t" + "ldr r8, [%[a], #64]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[17] * B\n\t" + "ldr r8, [%[a], #68]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[18] * B\n\t" + "ldr r8, [%[a], #72]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[19] * B\n\t" + "ldr r8, [%[a], #76]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[20] * B\n\t" + "ldr r8, [%[a], #80]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[21] * B\n\t" + "ldr r8, [%[a], #84]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[22] * B\n\t" + "ldr r8, [%[a], #88]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #88]\n\t" + "# A[23] * B\n\t" + "ldr r8, [%[a], #92]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #92]\n\t" + "# A[24] * B\n\t" + "ldr r8, [%[a], #96]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #96]\n\t" + "# A[25] * B\n\t" + "ldr r8, [%[a], #100]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #100]\n\t" + "# A[26] * B\n\t" + "ldr r8, [%[a], #104]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #104]\n\t" + "# A[27] * B\n\t" + "ldr r8, [%[a], #108]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #108]\n\t" + "# A[28] * B\n\t" + "ldr r8, [%[a], #112]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #112]\n\t" + "# A[29] * B\n\t" + "ldr r8, [%[a], #116]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #116]\n\t" + "# A[30] * B\n\t" + "ldr r8, [%[a], #120]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #120]\n\t" + "# A[31] * B\n\t" + "ldr r8, [%[a], #124]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #124]\n\t" + "# A[32] * B\n\t" + "ldr r8, [%[a], #128]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #128]\n\t" + "# A[33] * B\n\t" + "ldr r8, [%[a], #132]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #132]\n\t" + "# A[34] * B\n\t" + "ldr r8, [%[a], #136]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #136]\n\t" + "# A[35] * B\n\t" + "ldr r8, [%[a], #140]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #140]\n\t" + "# A[36] * B\n\t" + "ldr r8, [%[a], #144]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #144]\n\t" + "# A[37] * B\n\t" + "ldr r8, [%[a], #148]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #148]\n\t" + "# A[38] * B\n\t" + "ldr r8, [%[a], #152]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #152]\n\t" + "# A[39] * B\n\t" + "ldr r8, [%[a], #156]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #156]\n\t" + "# A[40] * B\n\t" + "ldr r8, [%[a], #160]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #160]\n\t" + "# A[41] * B\n\t" + "ldr r8, [%[a], #164]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #164]\n\t" + "# A[42] * B\n\t" + "ldr r8, [%[a], #168]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #168]\n\t" + "# A[43] * B\n\t" + "ldr r8, [%[a], #172]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #172]\n\t" + "# A[44] * B\n\t" + "ldr r8, [%[a], #176]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #176]\n\t" + "# A[45] * B\n\t" + "ldr r8, [%[a], #180]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #180]\n\t" + "# A[46] * B\n\t" + "ldr r8, [%[a], #184]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #184]\n\t" + "# A[47] * B\n\t" + "ldr r8, [%[a], #188]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #188]\n\t" + "# A[48] * B\n\t" + "ldr r8, [%[a], #192]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #192]\n\t" + "# A[49] * B\n\t" + "ldr r8, [%[a], #196]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #196]\n\t" + "# A[50] * B\n\t" + "ldr r8, [%[a], #200]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #200]\n\t" + "# A[51] * B\n\t" + "ldr r8, [%[a], #204]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #204]\n\t" + "# A[52] * B\n\t" + "ldr r8, [%[a], #208]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #208]\n\t" + "# A[53] * B\n\t" + "ldr r8, [%[a], #212]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #212]\n\t" + "# A[54] * B\n\t" + "ldr r8, [%[a], #216]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #216]\n\t" + "# A[55] * B\n\t" + "ldr r8, [%[a], #220]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #220]\n\t" + "# A[56] * B\n\t" + "ldr r8, [%[a], #224]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #224]\n\t" + "# A[57] * B\n\t" + "ldr r8, [%[a], #228]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #228]\n\t" + "# A[58] * B\n\t" + "ldr r8, [%[a], #232]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #232]\n\t" + "# A[59] * B\n\t" + "ldr r8, [%[a], #236]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #236]\n\t" + "# A[60] * B\n\t" + "ldr r8, [%[a], #240]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #240]\n\t" + "# A[61] * B\n\t" + "ldr r8, [%[a], #244]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #244]\n\t" + "# A[62] * B\n\t" + "ldr r8, [%[a], #248]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #248]\n\t" + "# A[63] * B\n\t" + "ldr r8, [%[a], #252]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r3, [%[r], #252]\n\t" + "str r4, [%[r], #256]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_2048_mont_norm_32(sp_digit* r, const 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, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #128\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + 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, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r7, [%[m], #0]\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr r7, [%[m], #32]\n\t" + "ldr r9, [%[a], #32]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #32]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr r7, [%[m], #36]\n\t" + "ldr r9, [%[a], #36]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #36]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr r7, [%[m], #40]\n\t" + "ldr r9, [%[a], #40]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #40]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr r7, [%[m], #44]\n\t" + "ldr r9, [%[a], #44]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #44]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr r7, [%[m], #48]\n\t" + "ldr r9, [%[a], #48]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #48]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr r7, [%[m], #52]\n\t" + "ldr r9, [%[a], #52]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #52]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr r7, [%[m], #56]\n\t" + "ldr r9, [%[a], #56]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #56]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr r7, [%[m], #60]\n\t" + "ldr r9, [%[a], #60]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #60]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr r7, [%[m], #64]\n\t" + "ldr r9, [%[a], #64]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #64]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr r7, [%[m], #68]\n\t" + "ldr r9, [%[a], #68]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #68]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr r7, [%[m], #72]\n\t" + "ldr r9, [%[a], #72]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #72]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr r7, [%[m], #76]\n\t" + "ldr r9, [%[a], #76]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #76]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr r7, [%[m], #80]\n\t" + "ldr r9, [%[a], #80]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #80]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr r7, [%[m], #84]\n\t" + "ldr r9, [%[a], #84]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #84]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr r7, [%[m], #88]\n\t" + "ldr r9, [%[a], #88]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #88]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr r7, [%[m], #92]\n\t" + "ldr r9, [%[a], #92]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #92]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr r7, [%[m], #96]\n\t" + "ldr r9, [%[a], #96]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #96]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr r7, [%[m], #100]\n\t" + "ldr r9, [%[a], #100]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #100]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr r7, [%[m], #104]\n\t" + "ldr r9, [%[a], #104]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #104]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr r7, [%[m], #108]\n\t" + "ldr r9, [%[a], #108]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #108]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr r7, [%[m], #112]\n\t" + "ldr r9, [%[a], #112]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #112]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr r7, [%[m], #116]\n\t" + "ldr r9, [%[a], #116]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #116]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr r7, [%[m], #120]\n\t" + "ldr r9, [%[a], #120]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #120]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr r7, [%[m], #124]\n\t" + "ldr r9, [%[a], #124]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #124]\n\t" + "ldr r9, [%[a], #128]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #128]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #128\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "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_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const 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, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #128\n\t" + "blt 1b\n\t" + "str r3, [%[r], #128]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #28]\n\t" + "# A[8] * B\n\t" + "ldr r8, [%[a], #32]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[9] * B\n\t" + "ldr r8, [%[a], #36]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[10] * B\n\t" + "ldr r8, [%[a], #40]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[11] * B\n\t" + "ldr r8, [%[a], #44]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[12] * B\n\t" + "ldr r8, [%[a], #48]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[13] * B\n\t" + "ldr r8, [%[a], #52]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[14] * B\n\t" + "ldr r8, [%[a], #56]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #56]\n\t" + "# A[15] * B\n\t" + "ldr r8, [%[a], #60]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #60]\n\t" + "# A[16] * B\n\t" + "ldr r8, [%[a], #64]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[17] * B\n\t" + "ldr r8, [%[a], #68]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[18] * B\n\t" + "ldr r8, [%[a], #72]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[19] * B\n\t" + "ldr r8, [%[a], #76]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[20] * B\n\t" + "ldr r8, [%[a], #80]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[21] * B\n\t" + "ldr r8, [%[a], #84]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[22] * B\n\t" + "ldr r8, [%[a], #88]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #88]\n\t" + "# A[23] * B\n\t" + "ldr r8, [%[a], #92]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #92]\n\t" + "# A[24] * B\n\t" + "ldr r8, [%[a], #96]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #96]\n\t" + "# A[25] * B\n\t" + "ldr r8, [%[a], #100]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #100]\n\t" + "# A[26] * B\n\t" + "ldr r8, [%[a], #104]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #104]\n\t" + "# A[27] * B\n\t" + "ldr r8, [%[a], #108]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #108]\n\t" + "# A[28] * B\n\t" + "ldr r8, [%[a], #112]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #112]\n\t" + "# A[29] * B\n\t" + "ldr r8, [%[a], #116]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #116]\n\t" + "# A[30] * B\n\t" + "ldr r8, [%[a], #120]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #120]\n\t" + "# A[31] * B\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r7\n\t" + "str r4, [%[r], #124]\n\t" + "str r5, [%[r], #128]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + 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 int32_t sp_2048_cmp_32(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #124\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "subs r6, r6, #4\n\t" + "bcs 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + 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 WC_INLINE int sp_2048_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (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); + + 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, d, (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 WC_INLINE int sp_2048_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_32(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][64]; +#else + sp_digit* t[16]; + 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) * 16 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 64; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32U); + if (reduceA != 0) { + 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); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + 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); + } + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U); + 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; +} +#else +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const 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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 64; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32U); + if (reduceA != 0) { + 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) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 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); + } + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U); + 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 /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* 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 single precision number. + */ +static void sp_2048_mont_norm_64(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 64); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_64(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* 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_64(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #256\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r6, [%[a], #132]\n\t" + "ldr r5, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #128]\n\t" + "str r6, [%[r], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r6, [%[a], #140]\n\t" + "ldr r5, [%[b], #136]\n\t" + "ldr r7, [%[b], #140]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #136]\n\t" + "str r6, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r6, [%[a], #148]\n\t" + "ldr r5, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #144]\n\t" + "str r6, [%[r], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r6, [%[a], #156]\n\t" + "ldr r5, [%[b], #152]\n\t" + "ldr r7, [%[b], #156]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #152]\n\t" + "str r6, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r6, [%[a], #164]\n\t" + "ldr r5, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #160]\n\t" + "str r6, [%[r], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r6, [%[a], #172]\n\t" + "ldr r5, [%[b], #168]\n\t" + "ldr r7, [%[b], #172]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #168]\n\t" + "str r6, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r6, [%[a], #180]\n\t" + "ldr r5, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #176]\n\t" + "str r6, [%[r], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r6, [%[a], #188]\n\t" + "ldr r5, [%[b], #184]\n\t" + "ldr r7, [%[b], #188]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #184]\n\t" + "str r6, [%[r], #188]\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r6, [%[a], #196]\n\t" + "ldr r5, [%[b], #192]\n\t" + "ldr r7, [%[b], #196]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #192]\n\t" + "str r6, [%[r], #196]\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r6, [%[a], #204]\n\t" + "ldr r5, [%[b], #200]\n\t" + "ldr r7, [%[b], #204]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #200]\n\t" + "str r6, [%[r], #204]\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r6, [%[a], #212]\n\t" + "ldr r5, [%[b], #208]\n\t" + "ldr r7, [%[b], #212]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #208]\n\t" + "str r6, [%[r], #212]\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r6, [%[a], #220]\n\t" + "ldr r5, [%[b], #216]\n\t" + "ldr r7, [%[b], #220]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #216]\n\t" + "str r6, [%[r], #220]\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r6, [%[a], #228]\n\t" + "ldr r5, [%[b], #224]\n\t" + "ldr r7, [%[b], #228]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #224]\n\t" + "str r6, [%[r], #228]\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r6, [%[a], #236]\n\t" + "ldr r5, [%[b], #232]\n\t" + "ldr r7, [%[b], #236]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #232]\n\t" + "str r6, [%[r], #236]\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r6, [%[a], #244]\n\t" + "ldr r5, [%[b], #240]\n\t" + "ldr r7, [%[b], #244]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #240]\n\t" + "str r6, [%[r], #244]\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r6, [%[a], #252]\n\t" + "ldr r5, [%[b], #248]\n\t" + "ldr r7, [%[b], #252]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #248]\n\t" + "str r6, [%[r], #252]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + 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_64(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r7, [%[m], #0]\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr r7, [%[m], #32]\n\t" + "ldr r9, [%[a], #32]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #32]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr r7, [%[m], #36]\n\t" + "ldr r9, [%[a], #36]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #36]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr r7, [%[m], #40]\n\t" + "ldr r9, [%[a], #40]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #40]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr r7, [%[m], #44]\n\t" + "ldr r9, [%[a], #44]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #44]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr r7, [%[m], #48]\n\t" + "ldr r9, [%[a], #48]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #48]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr r7, [%[m], #52]\n\t" + "ldr r9, [%[a], #52]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #52]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr r7, [%[m], #56]\n\t" + "ldr r9, [%[a], #56]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #56]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr r7, [%[m], #60]\n\t" + "ldr r9, [%[a], #60]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #60]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr r7, [%[m], #64]\n\t" + "ldr r9, [%[a], #64]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #64]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr r7, [%[m], #68]\n\t" + "ldr r9, [%[a], #68]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #68]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr r7, [%[m], #72]\n\t" + "ldr r9, [%[a], #72]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #72]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr r7, [%[m], #76]\n\t" + "ldr r9, [%[a], #76]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #76]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr r7, [%[m], #80]\n\t" + "ldr r9, [%[a], #80]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #80]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr r7, [%[m], #84]\n\t" + "ldr r9, [%[a], #84]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #84]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr r7, [%[m], #88]\n\t" + "ldr r9, [%[a], #88]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #88]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr r7, [%[m], #92]\n\t" + "ldr r9, [%[a], #92]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #92]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr r7, [%[m], #96]\n\t" + "ldr r9, [%[a], #96]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #96]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr r7, [%[m], #100]\n\t" + "ldr r9, [%[a], #100]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #100]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr r7, [%[m], #104]\n\t" + "ldr r9, [%[a], #104]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #104]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr r7, [%[m], #108]\n\t" + "ldr r9, [%[a], #108]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #108]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr r7, [%[m], #112]\n\t" + "ldr r9, [%[a], #112]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #112]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr r7, [%[m], #116]\n\t" + "ldr r9, [%[a], #116]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #116]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr r7, [%[m], #120]\n\t" + "ldr r9, [%[a], #120]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #120]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr r7, [%[m], #124]\n\t" + "ldr r9, [%[a], #124]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #124]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+32] += m[32] * mu\n\t" + "ldr r7, [%[m], #128]\n\t" + "ldr r9, [%[a], #128]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #128]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+33] += m[33] * mu\n\t" + "ldr r7, [%[m], #132]\n\t" + "ldr r9, [%[a], #132]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #132]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+34] += m[34] * mu\n\t" + "ldr r7, [%[m], #136]\n\t" + "ldr r9, [%[a], #136]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #136]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+35] += m[35] * mu\n\t" + "ldr r7, [%[m], #140]\n\t" + "ldr r9, [%[a], #140]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #140]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+36] += m[36] * mu\n\t" + "ldr r7, [%[m], #144]\n\t" + "ldr r9, [%[a], #144]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #144]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+37] += m[37] * mu\n\t" + "ldr r7, [%[m], #148]\n\t" + "ldr r9, [%[a], #148]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #148]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+38] += m[38] * mu\n\t" + "ldr r7, [%[m], #152]\n\t" + "ldr r9, [%[a], #152]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #152]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+39] += m[39] * mu\n\t" + "ldr r7, [%[m], #156]\n\t" + "ldr r9, [%[a], #156]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #156]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+40] += m[40] * mu\n\t" + "ldr r7, [%[m], #160]\n\t" + "ldr r9, [%[a], #160]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #160]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+41] += m[41] * mu\n\t" + "ldr r7, [%[m], #164]\n\t" + "ldr r9, [%[a], #164]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #164]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+42] += m[42] * mu\n\t" + "ldr r7, [%[m], #168]\n\t" + "ldr r9, [%[a], #168]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #168]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+43] += m[43] * mu\n\t" + "ldr r7, [%[m], #172]\n\t" + "ldr r9, [%[a], #172]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #172]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+44] += m[44] * mu\n\t" + "ldr r7, [%[m], #176]\n\t" + "ldr r9, [%[a], #176]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #176]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+45] += m[45] * mu\n\t" + "ldr r7, [%[m], #180]\n\t" + "ldr r9, [%[a], #180]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #180]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+46] += m[46] * mu\n\t" + "ldr r7, [%[m], #184]\n\t" + "ldr r9, [%[a], #184]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #184]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+47] += m[47] * mu\n\t" + "ldr r7, [%[m], #188]\n\t" + "ldr r9, [%[a], #188]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #188]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+48] += m[48] * mu\n\t" + "ldr r7, [%[m], #192]\n\t" + "ldr r9, [%[a], #192]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #192]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+49] += m[49] * mu\n\t" + "ldr r7, [%[m], #196]\n\t" + "ldr r9, [%[a], #196]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #196]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+50] += m[50] * mu\n\t" + "ldr r7, [%[m], #200]\n\t" + "ldr r9, [%[a], #200]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #200]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+51] += m[51] * mu\n\t" + "ldr r7, [%[m], #204]\n\t" + "ldr r9, [%[a], #204]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #204]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+52] += m[52] * mu\n\t" + "ldr r7, [%[m], #208]\n\t" + "ldr r9, [%[a], #208]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #208]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+53] += m[53] * mu\n\t" + "ldr r7, [%[m], #212]\n\t" + "ldr r9, [%[a], #212]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #212]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+54] += m[54] * mu\n\t" + "ldr r7, [%[m], #216]\n\t" + "ldr r9, [%[a], #216]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #216]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+55] += m[55] * mu\n\t" + "ldr r7, [%[m], #220]\n\t" + "ldr r9, [%[a], #220]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #220]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+56] += m[56] * mu\n\t" + "ldr r7, [%[m], #224]\n\t" + "ldr r9, [%[a], #224]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #224]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+57] += m[57] * mu\n\t" + "ldr r7, [%[m], #228]\n\t" + "ldr r9, [%[a], #228]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #228]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+58] += m[58] * mu\n\t" + "ldr r7, [%[m], #232]\n\t" + "ldr r9, [%[a], #232]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #232]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+59] += m[59] * mu\n\t" + "ldr r7, [%[m], #236]\n\t" + "ldr r9, [%[a], #236]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #236]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+60] += m[60] * mu\n\t" + "ldr r7, [%[m], #240]\n\t" + "ldr r9, [%[a], #240]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #240]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+61] += m[61] * mu\n\t" + "ldr r7, [%[m], #244]\n\t" + "ldr r9, [%[a], #244]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #244]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+62] += m[62] * mu\n\t" + "ldr r7, [%[m], #248]\n\t" + "ldr r9, [%[a], #248]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #248]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+63] += m[63] * mu\n\t" + "ldr r7, [%[m], #252]\n\t" + "ldr r9, [%[a], #252]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #252]\n\t" + "ldr r9, [%[a], #256]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #256]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #256\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + sp_2048_cond_sub_64(a - 64, 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_64(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_2048_mul_64(r, a, b); + sp_2048_mont_reduce_64(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_64(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_64(r, a); + sp_2048_mont_reduce_64(r, m, mp); +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_2048_word_64(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + 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_64(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<64; 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; + } +#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 int32_t sp_2048_cmp_64(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #252\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "subs r6, r6, #4\n\t" + "bcs 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #252]\n\t" + "ldr r5, [%[b], #252]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r5, [%[b], #248]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #244]\n\t" + "ldr r5, [%[b], #244]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r5, [%[b], #240]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #236]\n\t" + "ldr r5, [%[b], #236]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r5, [%[b], #232]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #228]\n\t" + "ldr r5, [%[b], #228]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r5, [%[b], #224]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #220]\n\t" + "ldr r5, [%[b], #220]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r5, [%[b], #216]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #212]\n\t" + "ldr r5, [%[b], #212]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r5, [%[b], #208]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #204]\n\t" + "ldr r5, [%[b], #204]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r5, [%[b], #200]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #196]\n\t" + "ldr r5, [%[b], #196]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r5, [%[b], #192]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #188]\n\t" + "ldr r5, [%[b], #188]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[b], #184]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #180]\n\t" + "ldr r5, [%[b], #180]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[b], #176]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #172]\n\t" + "ldr r5, [%[b], #172]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[b], #168]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #164]\n\t" + "ldr r5, [%[b], #164]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[b], #160]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #156]\n\t" + "ldr r5, [%[b], #156]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[b], #152]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #148]\n\t" + "ldr r5, [%[b], #148]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[b], #144]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #140]\n\t" + "ldr r5, [%[b], #140]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[b], #136]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #132]\n\t" + "ldr r5, [%[b], #132]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[b], #128]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + 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 WC_INLINE int sp_2048_div_64(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_2048_mul_d_64(t2, d, r1); + t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + sp_2048_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2); + sp_2048_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_64(t1, d) >= 0; + sp_2048_cond_sub_64(r, t1, d, (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 WC_INLINE int sp_2048_mod_64(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_64(a, m, NULL, r); +} + +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +/* 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 WC_INLINE int sp_2048_div_64_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_2048_mul_d_64(t2, d, r1); + t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + if (t1[64 + i] != 0) { + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d); + if (t1[64 + i] != 0) + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d); + } + } + + r1 = sp_2048_cmp_64(t1, d) >= 0; + sp_2048_cond_sub_64(r, t1, d, (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 WC_INLINE int sp_2048_mod_64_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_64_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* 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_64(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][128]; +#else + sp_digit* t[16]; + 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) * 16 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 128; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64U); + if (reduceA != 0) { + err = sp_2048_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) { + err = sp_2048_mod_64(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_2048_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_64(t[10], t[ 5], m, mp); + sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_64(t[12], t[ 6], m, mp); + sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_64(t[14], t[ 7], m, mp); + sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_mont_mul_64(r, r, t[y], m, mp); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#else +/* 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_64(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][128]; +#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 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 128; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64U); + if (reduceA != 0) { + err = sp_2048_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) { + err = sp_2048_mod_64(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_2048_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_64(t[10], t[ 5], m, mp); + sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_64(t[12], t[ 6], m, mp); + sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_64(t[14], t[ 7], m, mp); + sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_64(t[16], t[ 8], m, mp); + sp_2048_mont_mul_64(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_64(t[18], t[ 9], m, mp); + sp_2048_mont_mul_64(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_64(t[20], t[10], m, mp); + sp_2048_mont_mul_64(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_64(t[22], t[11], m, mp); + sp_2048_mont_mul_64(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_64(t[24], t[12], m, mp); + sp_2048_mont_mul_64(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_64(t[26], t[13], m, mp); + sp_2048_mont_mul_64(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_64(t[28], t[14], m, mp); + sp_2048_mont_mul_64(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_64(t[30], t[15], m, mp); + sp_2048_mont_mul_64(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_mont_mul_64(r, r, t[y], m, mp); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[128], m[64], r[128]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; +#endif + sp_digit *ah; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 64 * 2; + m = r + 64 * 2; + } +#endif + + if (err == MP_OKAY) { + ah = a + 64; + + sp_2048_from_bin(ah, 64, in, inLen); +#if DIGIT_BIT >= 32 + 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, 64, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_2048_sqr_64(r, ah); + err = sp_2048_mod_64_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_64(r, ah, r); + err = sp_2048_mod_64_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) * 64); + err = sp_2048_mod_64_cond(a, a, m); + + if (err == MP_OKAY) { + for (i = 31; i >= 0; i--) { + if (e[0] >> i) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 64); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_64(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) { + sp_2048_mont_mul_64(r, r, a, m, mp); + } + } + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_2048_mont_reduce_64(r, m, mp); + + for (i = 63; i > 0; i--) { + if (r[i] != m[i]) { + break; + } + } + if (r[i] >= m[i]) { + sp_2048_sub_in_place_64(r, m); + } + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) + 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 < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 2048) { + err = MP_READ_E; + } + if (inLen > 256) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 64; + m = a + 128; + r = a; + + sp_2048_from_bin(a, 64, in, inLen); + sp_2048_from_mp(d, 64, dm); + sp_2048_from_mp(m, 64, mm); + err = sp_2048_mod_exp_64(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) * 64); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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 sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #128\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adds r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "adc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[64 * 2]; + sp_digit p[32], q[32], dp[32]; + sp_digit tmpa[64], tmpb[64]; +#else + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* tmpa; + sp_digit* tmpb; +#endif + sp_digit* r; + sp_digit* qi; + sp_digit* dq; + sp_digit c; + 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 (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 64 * 2; + q = p + 32; + qi = dq = dp = q + 32; + tmpa = qi + 32; + tmpb = tmpa + 64; + + r = t + 64; + } +#else +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + r = a; + qi = dq = dp; +#endif + sp_2048_from_bin(a, 64, in, inLen); + sp_2048_from_mp(p, 32, pm); + sp_2048_from_mp(q, 32, qm); + sp_2048_from_mp(dp, 32, dpm); + + err = sp_2048_mod_exp_32(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 32, dqm); + err = sp_2048_mod_exp_32(tmpb, a, dq, 1024, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_32(tmpa, tmpb); + c += sp_2048_cond_add_32(tmpa, tmpa, p, c); + sp_2048_cond_add_32(tmpa, tmpa, p, c); + + sp_2048_from_mp(qi, 32, qim); + sp_2048_mul_32(tmpa, tmpa, qi); + err = sp_2048_mod_32(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_32(tmpa, q, tmpa); + XMEMSET(&tmpb[32], 0, sizeof(sp_digit) * 32); + sp_2048_add_64(r, tmpb, tmpa); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + 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)); +#endif + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 64); + r->used = 64; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 64, base); + sp_2048_from_mp(e, 64, exp); + sp_2048_from_mp(m, 64, mod); + + err = sp_2048_mod_exp_64(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_2048 +static void sp_2048_lshift_64(sp_digit* r, sp_digit* a, byte n) +{ + __asm__ __volatile__ ( + "mov r6, #31\n\t" + "sub r6, r6, %[n]\n\t" + "ldr r3, [%[a], #252]\n\t" + "lsr r4, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r4, r4, r6\n\t" + "ldr r2, [%[a], #248]\n\t" + "str r4, [%[r], #256]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #244]\n\t" + "str r3, [%[r], #252]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #240]\n\t" + "str r2, [%[r], #248]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #236]\n\t" + "str r4, [%[r], #244]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #232]\n\t" + "str r3, [%[r], #240]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #228]\n\t" + "str r2, [%[r], #236]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #224]\n\t" + "str r4, [%[r], #232]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #220]\n\t" + "str r3, [%[r], #228]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #216]\n\t" + "str r2, [%[r], #224]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #212]\n\t" + "str r4, [%[r], #220]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #208]\n\t" + "str r3, [%[r], #216]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #204]\n\t" + "str r2, [%[r], #212]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #200]\n\t" + "str r4, [%[r], #208]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #196]\n\t" + "str r3, [%[r], #204]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #192]\n\t" + "str r2, [%[r], #200]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #188]\n\t" + "str r4, [%[r], #196]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #184]\n\t" + "str r3, [%[r], #192]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #180]\n\t" + "str r2, [%[r], #188]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #176]\n\t" + "str r4, [%[r], #184]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #172]\n\t" + "str r3, [%[r], #180]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #168]\n\t" + "str r2, [%[r], #176]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #164]\n\t" + "str r4, [%[r], #172]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #160]\n\t" + "str r3, [%[r], #168]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #156]\n\t" + "str r2, [%[r], #164]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #152]\n\t" + "str r4, [%[r], #160]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #148]\n\t" + "str r3, [%[r], #156]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #144]\n\t" + "str r2, [%[r], #152]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #140]\n\t" + "str r4, [%[r], #148]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #136]\n\t" + "str r3, [%[r], #144]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #132]\n\t" + "str r2, [%[r], #140]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #128]\n\t" + "str r4, [%[r], #136]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #124]\n\t" + "str r3, [%[r], #132]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #120]\n\t" + "str r2, [%[r], #128]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #116]\n\t" + "str r4, [%[r], #124]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #112]\n\t" + "str r3, [%[r], #120]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #108]\n\t" + "str r2, [%[r], #116]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #104]\n\t" + "str r4, [%[r], #112]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #100]\n\t" + "str r3, [%[r], #108]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #96]\n\t" + "str r2, [%[r], #104]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #92]\n\t" + "str r4, [%[r], #100]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #88]\n\t" + "str r3, [%[r], #96]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #84]\n\t" + "str r2, [%[r], #92]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #80]\n\t" + "str r4, [%[r], #88]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #76]\n\t" + "str r3, [%[r], #84]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #72]\n\t" + "str r2, [%[r], #80]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #68]\n\t" + "str r4, [%[r], #76]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #64]\n\t" + "str r3, [%[r], #72]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #60]\n\t" + "str r2, [%[r], #68]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "str r3, [%[r]]\n\t" + "str r4, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [n] "r" (n) + : "memory", "r2", "r3", "r4", "r5", "r6" + ); +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_64(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[128]; + sp_digit td[65]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 193, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 128; +#else + norm = nd; + tmp = td; +#endif + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + sp_2048_lshift_64(r, norm, y); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_lshift_64(r, r, y); + sp_2048_mul_d_64(tmp, norm, r[64]); + r[64] = 0; + o = sp_2048_add_64(r, r, tmp); + sp_2048_cond_sub_64(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* HAVE_FFDHE_2048 */ + +/* 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. + * returns 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[128], e[64], m[64]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 256) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 64, base); + sp_2048_from_bin(e, 64, exp, expLen); + sp_2048_from_mp(m, 64, mod); + + #ifdef HAVE_FFDHE_2048 + if (base->used == 1 && base->dp[0] == 2 && m[63] == (sp_digit)-1) + err = sp_2048_mod_exp_2_64(r, e, expLen * 8, m); + else + #endif + err = sp_2048_mod_exp_64(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 */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_mp(e, 32, exp); + sp_2048_from_mp(m, 32, mod); + + err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 32, 0, sizeof(*r) * 32U); + err = sp_2048_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * 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<96 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + 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_12(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #48\n\t" + "mov r10, #0\n\t" + "# A[0] * B[0]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r3, r4, r8, r9\n\t" + "mov r5, #0\n\t" + "str r3, [sp]\n\t" + "# A[0] * B[1]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[0]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #4]\n\t" + "# A[0] * B[2]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #8]\n\t" + "# A[0] * B[3]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[2]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[1]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #12]\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[3]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #16]\n\t" + "# A[0] * B[5]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[4]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[3]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[2]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[1]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #20]\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #24]\n\t" + "# A[0] * B[7]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[6]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[5]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[4]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[3]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[2]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[1]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #28]\n\t" + "# A[0] * B[8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[2]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[1]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[0]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #32]\n\t" + "# A[0] * B[9]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[7]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[6]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[5]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[3]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[2]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[1]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[0]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #36]\n\t" + "# A[0] * B[10]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[9]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[8]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[6]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[3]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[2]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[1]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[0]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #40]\n\t" + "# A[0] * B[11]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[10]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[9]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[8]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[7]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[6]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[5]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[3]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[2]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[1]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[0]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #44]\n\t" + "# A[1] * B[11]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[2] * B[10]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[9]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[8]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[7]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[5]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[4]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[3]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[2]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[1]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[2] * B[11]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[3] * B[10]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[9]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[8]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[7]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[6]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[5]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[4]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[3]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[2]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[3] * B[11]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[4] * B[10]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[9]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[8]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[7]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[6]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[5]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[4]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[3]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #56]\n\t" + "# A[4] * B[11]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[5] * B[10]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[9]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[8]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[7]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[6]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[5]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[4]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #60]\n\t" + "# A[5] * B[11]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[6] * B[10]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[9]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[8]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[7]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[6]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[5]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[6] * B[11]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[7] * B[10]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[9]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[8]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[7]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[6]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[7] * B[11]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[8] * B[10]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[9]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[8]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[7]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[8] * B[11]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[9] * B[10]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[9]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[8]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[9] * B[11]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[10] * B[10]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[9]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[10] * B[11]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[11] * B[10]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[11] * B[11]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r3, [sp, #0]\n\t" + "ldr r4, [sp, #4]\n\t" + "ldr r5, [sp, #8]\n\t" + "ldr r6, [sp, #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [sp, #16]\n\t" + "ldr r4, [sp, #20]\n\t" + "ldr r5, [sp, #24]\n\t" + "ldr r6, [sp, #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r3, [sp, #32]\n\t" + "ldr r4, [sp, #36]\n\t" + "ldr r5, [sp, #40]\n\t" + "ldr r6, [sp, #44]\n\t" + "str r3, [%[r], #32]\n\t" + "str r4, [%[r], #36]\n\t" + "str r5, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "add sp, sp, #48\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +} + +/* 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_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #48\n\t" + "mov r14, #0\n\t" + "# A[0] * A[0]\n\t" + "ldr r10, [%[a], #0]\n\t" + "umull r8, r3, r10, r10\n\t" + "mov r4, #0\n\t" + "str r8, [sp]\n\t" + "# A[0] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[1] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[1] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[1] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[2] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #28]\n\t" + "# A[0] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #32]\n\t" + "# A[0] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #36]\n\t" + "# A[0] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #40]\n\t" + "# A[0] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #44]\n\t" + "# A[1] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[2] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #48]\n\t" + "# A[2] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[3] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #52]\n\t" + "# A[3] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[4] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #56]\n\t" + "# A[4] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[5] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #60]\n\t" + "# A[5] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[6] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #64]\n\t" + "# A[6] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[7] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #68]\n\t" + "# A[7] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[8] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[9] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [%[r], #72]\n\t" + "# A[8] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[9] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #76]\n\t" + "# A[9] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[10] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [%[r], #80]\n\t" + "# A[10] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [%[r], #84]\n\t" + "# A[11] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adc r4, r4, r9\n\t" + "str r3, [%[r], #88]\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r2, [sp, #0]\n\t" + "ldr r3, [sp, #4]\n\t" + "ldr r4, [sp, #8]\n\t" + "ldr r8, [sp, #12]\n\t" + "str r2, [%[r], #0]\n\t" + "str r3, [%[r], #4]\n\t" + "str r4, [%[r], #8]\n\t" + "str r8, [%[r], #12]\n\t" + "ldr r2, [sp, #16]\n\t" + "ldr r3, [sp, #20]\n\t" + "ldr r4, [sp, #24]\n\t" + "ldr r8, [sp, #28]\n\t" + "str r2, [%[r], #16]\n\t" + "str r3, [%[r], #20]\n\t" + "str r4, [%[r], #24]\n\t" + "str r8, [%[r], #28]\n\t" + "ldr r2, [sp, #32]\n\t" + "ldr r3, [sp, #36]\n\t" + "ldr r4, [sp, #40]\n\t" + "ldr r8, [sp, #44]\n\t" + "str r2, [%[r], #32]\n\t" + "str r3, [%[r], #36]\n\t" + "str r4, [%[r], #40]\n\t" + "str r8, [%[r], #44]\n\t" + "add sp, sp, #48\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14" + ); +} + +/* 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_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + 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_24(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "ldr r2, [%[a], #64]\n\t" + "ldr r3, [%[a], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "ldr r8, [%[b], #72]\n\t" + "ldr r9, [%[b], #76]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #64]\n\t" + "str r3, [%[a], #68]\n\t" + "str r4, [%[a], #72]\n\t" + "str r5, [%[a], #76]\n\t" + "ldr r2, [%[a], #80]\n\t" + "ldr r3, [%[a], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "ldr r8, [%[b], #88]\n\t" + "ldr r9, [%[b], #92]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #80]\n\t" + "str r3, [%[a], #84]\n\t" + "str r4, [%[a], #88]\n\t" + "str r5, [%[a], #92]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "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_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + 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_12(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<12; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; + r[8] = a[8] & m; + r[9] = a[9] & m; + r[10] = a[10] & m; + r[11] = a[11] & 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. + */ +SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[24]; + sp_digit a1[12]; + sp_digit b1[12]; + sp_digit z2[24]; + sp_digit u, ca, cb; + + ca = sp_3072_add_12(a1, a, &a[12]); + cb = sp_3072_add_12(b1, b, &b[12]); + u = ca & cb; + sp_3072_mul_12(z1, a1, b1); + sp_3072_mul_12(z2, &a[12], &b[12]); + sp_3072_mul_12(z0, a, b); + sp_3072_mask_12(r + 24, a1, 0 - cb); + sp_3072_mask_12(b1, b1, 0 - ca); + u += sp_3072_add_12(r + 24, r + 24, b1); + u += sp_3072_sub_in_place_24(z1, z2); + u += sp_3072_sub_in_place_24(z1, z0); + u += sp_3072_add_24(r + 12, r + 12, z1); + r[36] = u; + XMEMSET(r + 36 + 1, 0, sizeof(sp_digit) * (12 - 1)); + (void)sp_3072_add_24(r + 24, r + 24, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[24]; + sp_digit z1[24]; + sp_digit a1[12]; + sp_digit u; + + u = sp_3072_add_12(a1, a, &a[12]); + sp_3072_sqr_12(z1, a1); + sp_3072_sqr_12(z2, &a[12]); + sp_3072_sqr_12(z0, a); + sp_3072_mask_12(r + 24, a1, 0 - u); + u += sp_3072_add_12(r + 24, r + 24, r + 24); + u += sp_3072_sub_in_place_24(z1, z2); + u += sp_3072_sub_in_place_24(z1, z0); + u += sp_3072_add_24(r + 12, r + 12, z1); + r[36] = u; + XMEMSET(r + 36 + 1, 0, sizeof(sp_digit) * (12 - 1)); + (void)sp_3072_add_24(r + 24, r + 24, z2); +} + +/* 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__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "ldr r2, [%[a], #64]\n\t" + "ldr r3, [%[a], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "ldr r8, [%[b], #72]\n\t" + "ldr r9, [%[b], #76]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #64]\n\t" + "str r3, [%[a], #68]\n\t" + "str r4, [%[a], #72]\n\t" + "str r5, [%[a], #76]\n\t" + "ldr r2, [%[a], #80]\n\t" + "ldr r3, [%[a], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "ldr r8, [%[b], #88]\n\t" + "ldr r9, [%[b], #92]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #80]\n\t" + "str r3, [%[a], #84]\n\t" + "str r4, [%[a], #88]\n\t" + "str r5, [%[a], #92]\n\t" + "ldr r2, [%[a], #96]\n\t" + "ldr r3, [%[a], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "ldr r8, [%[b], #104]\n\t" + "ldr r9, [%[b], #108]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #96]\n\t" + "str r3, [%[a], #100]\n\t" + "str r4, [%[a], #104]\n\t" + "str r5, [%[a], #108]\n\t" + "ldr r2, [%[a], #112]\n\t" + "ldr r3, [%[a], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "ldr r8, [%[b], #120]\n\t" + "ldr r9, [%[b], #124]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #112]\n\t" + "str r3, [%[a], #116]\n\t" + "str r4, [%[a], #120]\n\t" + "str r5, [%[a], #124]\n\t" + "ldr r2, [%[a], #128]\n\t" + "ldr r3, [%[a], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[a], #140]\n\t" + "ldr r6, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "ldr r8, [%[b], #136]\n\t" + "ldr r9, [%[b], #140]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #128]\n\t" + "str r3, [%[a], #132]\n\t" + "str r4, [%[a], #136]\n\t" + "str r5, [%[a], #140]\n\t" + "ldr r2, [%[a], #144]\n\t" + "ldr r3, [%[a], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[a], #156]\n\t" + "ldr r6, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "ldr r8, [%[b], #152]\n\t" + "ldr r9, [%[b], #156]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #144]\n\t" + "str r3, [%[a], #148]\n\t" + "str r4, [%[a], #152]\n\t" + "str r5, [%[a], #156]\n\t" + "ldr r2, [%[a], #160]\n\t" + "ldr r3, [%[a], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[a], #172]\n\t" + "ldr r6, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "ldr r8, [%[b], #168]\n\t" + "ldr r9, [%[b], #172]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #160]\n\t" + "str r3, [%[a], #164]\n\t" + "str r4, [%[a], #168]\n\t" + "str r5, [%[a], #172]\n\t" + "ldr r2, [%[a], #176]\n\t" + "ldr r3, [%[a], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[a], #188]\n\t" + "ldr r6, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "ldr r8, [%[b], #184]\n\t" + "ldr r9, [%[b], #188]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #176]\n\t" + "str r3, [%[a], #180]\n\t" + "str r4, [%[a], #184]\n\t" + "str r5, [%[a], #188]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "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__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "ldr r8, [%[b], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "ldr r10, [%[b], #104]\n\t" + "ldr r14, [%[b], #108]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "ldr r8, [%[b], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "ldr r10, [%[b], #120]\n\t" + "ldr r14, [%[b], #124]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[a], #132]\n\t" + "ldr r6, [%[a], #136]\n\t" + "ldr r7, [%[a], #140]\n\t" + "ldr r8, [%[b], #128]\n\t" + "ldr r9, [%[b], #132]\n\t" + "ldr r10, [%[b], #136]\n\t" + "ldr r14, [%[b], #140]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #128]\n\t" + "str r5, [%[r], #132]\n\t" + "str r6, [%[r], #136]\n\t" + "str r7, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[a], #148]\n\t" + "ldr r6, [%[a], #152]\n\t" + "ldr r7, [%[a], #156]\n\t" + "ldr r8, [%[b], #144]\n\t" + "ldr r9, [%[b], #148]\n\t" + "ldr r10, [%[b], #152]\n\t" + "ldr r14, [%[b], #156]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #144]\n\t" + "str r5, [%[r], #148]\n\t" + "str r6, [%[r], #152]\n\t" + "str r7, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[a], #164]\n\t" + "ldr r6, [%[a], #168]\n\t" + "ldr r7, [%[a], #172]\n\t" + "ldr r8, [%[b], #160]\n\t" + "ldr r9, [%[b], #164]\n\t" + "ldr r10, [%[b], #168]\n\t" + "ldr r14, [%[b], #172]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #160]\n\t" + "str r5, [%[r], #164]\n\t" + "str r6, [%[r], #168]\n\t" + "str r7, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[a], #180]\n\t" + "ldr r6, [%[a], #184]\n\t" + "ldr r7, [%[a], #188]\n\t" + "ldr r8, [%[b], #176]\n\t" + "ldr r9, [%[b], #180]\n\t" + "ldr r10, [%[b], #184]\n\t" + "ldr r14, [%[b], #188]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #176]\n\t" + "str r5, [%[r], #180]\n\t" + "str r6, [%[r], #184]\n\t" + "str r7, [%[r], #188]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + 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, const 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. + */ +SP_NOINLINE 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)); + (void)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. + */ +SP_NOINLINE 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)); + (void)sp_3072_add_48(r + 48, r + 48, z2); +} + +/* 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_96(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "ldr r2, [%[a], #64]\n\t" + "ldr r3, [%[a], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "ldr r8, [%[b], #72]\n\t" + "ldr r9, [%[b], #76]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #64]\n\t" + "str r3, [%[a], #68]\n\t" + "str r4, [%[a], #72]\n\t" + "str r5, [%[a], #76]\n\t" + "ldr r2, [%[a], #80]\n\t" + "ldr r3, [%[a], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "ldr r8, [%[b], #88]\n\t" + "ldr r9, [%[b], #92]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #80]\n\t" + "str r3, [%[a], #84]\n\t" + "str r4, [%[a], #88]\n\t" + "str r5, [%[a], #92]\n\t" + "ldr r2, [%[a], #96]\n\t" + "ldr r3, [%[a], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "ldr r8, [%[b], #104]\n\t" + "ldr r9, [%[b], #108]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #96]\n\t" + "str r3, [%[a], #100]\n\t" + "str r4, [%[a], #104]\n\t" + "str r5, [%[a], #108]\n\t" + "ldr r2, [%[a], #112]\n\t" + "ldr r3, [%[a], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "ldr r8, [%[b], #120]\n\t" + "ldr r9, [%[b], #124]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #112]\n\t" + "str r3, [%[a], #116]\n\t" + "str r4, [%[a], #120]\n\t" + "str r5, [%[a], #124]\n\t" + "ldr r2, [%[a], #128]\n\t" + "ldr r3, [%[a], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[a], #140]\n\t" + "ldr r6, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "ldr r8, [%[b], #136]\n\t" + "ldr r9, [%[b], #140]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #128]\n\t" + "str r3, [%[a], #132]\n\t" + "str r4, [%[a], #136]\n\t" + "str r5, [%[a], #140]\n\t" + "ldr r2, [%[a], #144]\n\t" + "ldr r3, [%[a], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[a], #156]\n\t" + "ldr r6, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "ldr r8, [%[b], #152]\n\t" + "ldr r9, [%[b], #156]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #144]\n\t" + "str r3, [%[a], #148]\n\t" + "str r4, [%[a], #152]\n\t" + "str r5, [%[a], #156]\n\t" + "ldr r2, [%[a], #160]\n\t" + "ldr r3, [%[a], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[a], #172]\n\t" + "ldr r6, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "ldr r8, [%[b], #168]\n\t" + "ldr r9, [%[b], #172]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #160]\n\t" + "str r3, [%[a], #164]\n\t" + "str r4, [%[a], #168]\n\t" + "str r5, [%[a], #172]\n\t" + "ldr r2, [%[a], #176]\n\t" + "ldr r3, [%[a], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[a], #188]\n\t" + "ldr r6, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "ldr r8, [%[b], #184]\n\t" + "ldr r9, [%[b], #188]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #176]\n\t" + "str r3, [%[a], #180]\n\t" + "str r4, [%[a], #184]\n\t" + "str r5, [%[a], #188]\n\t" + "ldr r2, [%[a], #192]\n\t" + "ldr r3, [%[a], #196]\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r5, [%[a], #204]\n\t" + "ldr r6, [%[b], #192]\n\t" + "ldr r7, [%[b], #196]\n\t" + "ldr r8, [%[b], #200]\n\t" + "ldr r9, [%[b], #204]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #192]\n\t" + "str r3, [%[a], #196]\n\t" + "str r4, [%[a], #200]\n\t" + "str r5, [%[a], #204]\n\t" + "ldr r2, [%[a], #208]\n\t" + "ldr r3, [%[a], #212]\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r5, [%[a], #220]\n\t" + "ldr r6, [%[b], #208]\n\t" + "ldr r7, [%[b], #212]\n\t" + "ldr r8, [%[b], #216]\n\t" + "ldr r9, [%[b], #220]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #208]\n\t" + "str r3, [%[a], #212]\n\t" + "str r4, [%[a], #216]\n\t" + "str r5, [%[a], #220]\n\t" + "ldr r2, [%[a], #224]\n\t" + "ldr r3, [%[a], #228]\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r5, [%[a], #236]\n\t" + "ldr r6, [%[b], #224]\n\t" + "ldr r7, [%[b], #228]\n\t" + "ldr r8, [%[b], #232]\n\t" + "ldr r9, [%[b], #236]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #224]\n\t" + "str r3, [%[a], #228]\n\t" + "str r4, [%[a], #232]\n\t" + "str r5, [%[a], #236]\n\t" + "ldr r2, [%[a], #240]\n\t" + "ldr r3, [%[a], #244]\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r5, [%[a], #252]\n\t" + "ldr r6, [%[b], #240]\n\t" + "ldr r7, [%[b], #244]\n\t" + "ldr r8, [%[b], #248]\n\t" + "ldr r9, [%[b], #252]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #240]\n\t" + "str r3, [%[a], #244]\n\t" + "str r4, [%[a], #248]\n\t" + "str r5, [%[a], #252]\n\t" + "ldr r2, [%[a], #256]\n\t" + "ldr r3, [%[a], #260]\n\t" + "ldr r4, [%[a], #264]\n\t" + "ldr r5, [%[a], #268]\n\t" + "ldr r6, [%[b], #256]\n\t" + "ldr r7, [%[b], #260]\n\t" + "ldr r8, [%[b], #264]\n\t" + "ldr r9, [%[b], #268]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #256]\n\t" + "str r3, [%[a], #260]\n\t" + "str r4, [%[a], #264]\n\t" + "str r5, [%[a], #268]\n\t" + "ldr r2, [%[a], #272]\n\t" + "ldr r3, [%[a], #276]\n\t" + "ldr r4, [%[a], #280]\n\t" + "ldr r5, [%[a], #284]\n\t" + "ldr r6, [%[b], #272]\n\t" + "ldr r7, [%[b], #276]\n\t" + "ldr r8, [%[b], #280]\n\t" + "ldr r9, [%[b], #284]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #272]\n\t" + "str r3, [%[a], #276]\n\t" + "str r4, [%[a], #280]\n\t" + "str r5, [%[a], #284]\n\t" + "ldr r2, [%[a], #288]\n\t" + "ldr r3, [%[a], #292]\n\t" + "ldr r4, [%[a], #296]\n\t" + "ldr r5, [%[a], #300]\n\t" + "ldr r6, [%[b], #288]\n\t" + "ldr r7, [%[b], #292]\n\t" + "ldr r8, [%[b], #296]\n\t" + "ldr r9, [%[b], #300]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #288]\n\t" + "str r3, [%[a], #292]\n\t" + "str r4, [%[a], #296]\n\t" + "str r5, [%[a], #300]\n\t" + "ldr r2, [%[a], #304]\n\t" + "ldr r3, [%[a], #308]\n\t" + "ldr r4, [%[a], #312]\n\t" + "ldr r5, [%[a], #316]\n\t" + "ldr r6, [%[b], #304]\n\t" + "ldr r7, [%[b], #308]\n\t" + "ldr r8, [%[b], #312]\n\t" + "ldr r9, [%[b], #316]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #304]\n\t" + "str r3, [%[a], #308]\n\t" + "str r4, [%[a], #312]\n\t" + "str r5, [%[a], #316]\n\t" + "ldr r2, [%[a], #320]\n\t" + "ldr r3, [%[a], #324]\n\t" + "ldr r4, [%[a], #328]\n\t" + "ldr r5, [%[a], #332]\n\t" + "ldr r6, [%[b], #320]\n\t" + "ldr r7, [%[b], #324]\n\t" + "ldr r8, [%[b], #328]\n\t" + "ldr r9, [%[b], #332]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #320]\n\t" + "str r3, [%[a], #324]\n\t" + "str r4, [%[a], #328]\n\t" + "str r5, [%[a], #332]\n\t" + "ldr r2, [%[a], #336]\n\t" + "ldr r3, [%[a], #340]\n\t" + "ldr r4, [%[a], #344]\n\t" + "ldr r5, [%[a], #348]\n\t" + "ldr r6, [%[b], #336]\n\t" + "ldr r7, [%[b], #340]\n\t" + "ldr r8, [%[b], #344]\n\t" + "ldr r9, [%[b], #348]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #336]\n\t" + "str r3, [%[a], #340]\n\t" + "str r4, [%[a], #344]\n\t" + "str r5, [%[a], #348]\n\t" + "ldr r2, [%[a], #352]\n\t" + "ldr r3, [%[a], #356]\n\t" + "ldr r4, [%[a], #360]\n\t" + "ldr r5, [%[a], #364]\n\t" + "ldr r6, [%[b], #352]\n\t" + "ldr r7, [%[b], #356]\n\t" + "ldr r8, [%[b], #360]\n\t" + "ldr r9, [%[b], #364]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #352]\n\t" + "str r3, [%[a], #356]\n\t" + "str r4, [%[a], #360]\n\t" + "str r5, [%[a], #364]\n\t" + "ldr r2, [%[a], #368]\n\t" + "ldr r3, [%[a], #372]\n\t" + "ldr r4, [%[a], #376]\n\t" + "ldr r5, [%[a], #380]\n\t" + "ldr r6, [%[b], #368]\n\t" + "ldr r7, [%[b], #372]\n\t" + "ldr r8, [%[b], #376]\n\t" + "ldr r9, [%[b], #380]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #368]\n\t" + "str r3, [%[a], #372]\n\t" + "str r4, [%[a], #376]\n\t" + "str r5, [%[a], #380]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "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_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "ldr r8, [%[b], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "ldr r10, [%[b], #104]\n\t" + "ldr r14, [%[b], #108]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "ldr r8, [%[b], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "ldr r10, [%[b], #120]\n\t" + "ldr r14, [%[b], #124]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[a], #132]\n\t" + "ldr r6, [%[a], #136]\n\t" + "ldr r7, [%[a], #140]\n\t" + "ldr r8, [%[b], #128]\n\t" + "ldr r9, [%[b], #132]\n\t" + "ldr r10, [%[b], #136]\n\t" + "ldr r14, [%[b], #140]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #128]\n\t" + "str r5, [%[r], #132]\n\t" + "str r6, [%[r], #136]\n\t" + "str r7, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[a], #148]\n\t" + "ldr r6, [%[a], #152]\n\t" + "ldr r7, [%[a], #156]\n\t" + "ldr r8, [%[b], #144]\n\t" + "ldr r9, [%[b], #148]\n\t" + "ldr r10, [%[b], #152]\n\t" + "ldr r14, [%[b], #156]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #144]\n\t" + "str r5, [%[r], #148]\n\t" + "str r6, [%[r], #152]\n\t" + "str r7, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[a], #164]\n\t" + "ldr r6, [%[a], #168]\n\t" + "ldr r7, [%[a], #172]\n\t" + "ldr r8, [%[b], #160]\n\t" + "ldr r9, [%[b], #164]\n\t" + "ldr r10, [%[b], #168]\n\t" + "ldr r14, [%[b], #172]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #160]\n\t" + "str r5, [%[r], #164]\n\t" + "str r6, [%[r], #168]\n\t" + "str r7, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[a], #180]\n\t" + "ldr r6, [%[a], #184]\n\t" + "ldr r7, [%[a], #188]\n\t" + "ldr r8, [%[b], #176]\n\t" + "ldr r9, [%[b], #180]\n\t" + "ldr r10, [%[b], #184]\n\t" + "ldr r14, [%[b], #188]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #176]\n\t" + "str r5, [%[r], #180]\n\t" + "str r6, [%[r], #184]\n\t" + "str r7, [%[r], #188]\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r5, [%[a], #196]\n\t" + "ldr r6, [%[a], #200]\n\t" + "ldr r7, [%[a], #204]\n\t" + "ldr r8, [%[b], #192]\n\t" + "ldr r9, [%[b], #196]\n\t" + "ldr r10, [%[b], #200]\n\t" + "ldr r14, [%[b], #204]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #192]\n\t" + "str r5, [%[r], #196]\n\t" + "str r6, [%[r], #200]\n\t" + "str r7, [%[r], #204]\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r5, [%[a], #212]\n\t" + "ldr r6, [%[a], #216]\n\t" + "ldr r7, [%[a], #220]\n\t" + "ldr r8, [%[b], #208]\n\t" + "ldr r9, [%[b], #212]\n\t" + "ldr r10, [%[b], #216]\n\t" + "ldr r14, [%[b], #220]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #208]\n\t" + "str r5, [%[r], #212]\n\t" + "str r6, [%[r], #216]\n\t" + "str r7, [%[r], #220]\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r5, [%[a], #228]\n\t" + "ldr r6, [%[a], #232]\n\t" + "ldr r7, [%[a], #236]\n\t" + "ldr r8, [%[b], #224]\n\t" + "ldr r9, [%[b], #228]\n\t" + "ldr r10, [%[b], #232]\n\t" + "ldr r14, [%[b], #236]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #224]\n\t" + "str r5, [%[r], #228]\n\t" + "str r6, [%[r], #232]\n\t" + "str r7, [%[r], #236]\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r5, [%[a], #244]\n\t" + "ldr r6, [%[a], #248]\n\t" + "ldr r7, [%[a], #252]\n\t" + "ldr r8, [%[b], #240]\n\t" + "ldr r9, [%[b], #244]\n\t" + "ldr r10, [%[b], #248]\n\t" + "ldr r14, [%[b], #252]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #240]\n\t" + "str r5, [%[r], #244]\n\t" + "str r6, [%[r], #248]\n\t" + "str r7, [%[r], #252]\n\t" + "ldr r4, [%[a], #256]\n\t" + "ldr r5, [%[a], #260]\n\t" + "ldr r6, [%[a], #264]\n\t" + "ldr r7, [%[a], #268]\n\t" + "ldr r8, [%[b], #256]\n\t" + "ldr r9, [%[b], #260]\n\t" + "ldr r10, [%[b], #264]\n\t" + "ldr r14, [%[b], #268]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #256]\n\t" + "str r5, [%[r], #260]\n\t" + "str r6, [%[r], #264]\n\t" + "str r7, [%[r], #268]\n\t" + "ldr r4, [%[a], #272]\n\t" + "ldr r5, [%[a], #276]\n\t" + "ldr r6, [%[a], #280]\n\t" + "ldr r7, [%[a], #284]\n\t" + "ldr r8, [%[b], #272]\n\t" + "ldr r9, [%[b], #276]\n\t" + "ldr r10, [%[b], #280]\n\t" + "ldr r14, [%[b], #284]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #272]\n\t" + "str r5, [%[r], #276]\n\t" + "str r6, [%[r], #280]\n\t" + "str r7, [%[r], #284]\n\t" + "ldr r4, [%[a], #288]\n\t" + "ldr r5, [%[a], #292]\n\t" + "ldr r6, [%[a], #296]\n\t" + "ldr r7, [%[a], #300]\n\t" + "ldr r8, [%[b], #288]\n\t" + "ldr r9, [%[b], #292]\n\t" + "ldr r10, [%[b], #296]\n\t" + "ldr r14, [%[b], #300]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #288]\n\t" + "str r5, [%[r], #292]\n\t" + "str r6, [%[r], #296]\n\t" + "str r7, [%[r], #300]\n\t" + "ldr r4, [%[a], #304]\n\t" + "ldr r5, [%[a], #308]\n\t" + "ldr r6, [%[a], #312]\n\t" + "ldr r7, [%[a], #316]\n\t" + "ldr r8, [%[b], #304]\n\t" + "ldr r9, [%[b], #308]\n\t" + "ldr r10, [%[b], #312]\n\t" + "ldr r14, [%[b], #316]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #304]\n\t" + "str r5, [%[r], #308]\n\t" + "str r6, [%[r], #312]\n\t" + "str r7, [%[r], #316]\n\t" + "ldr r4, [%[a], #320]\n\t" + "ldr r5, [%[a], #324]\n\t" + "ldr r6, [%[a], #328]\n\t" + "ldr r7, [%[a], #332]\n\t" + "ldr r8, [%[b], #320]\n\t" + "ldr r9, [%[b], #324]\n\t" + "ldr r10, [%[b], #328]\n\t" + "ldr r14, [%[b], #332]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #320]\n\t" + "str r5, [%[r], #324]\n\t" + "str r6, [%[r], #328]\n\t" + "str r7, [%[r], #332]\n\t" + "ldr r4, [%[a], #336]\n\t" + "ldr r5, [%[a], #340]\n\t" + "ldr r6, [%[a], #344]\n\t" + "ldr r7, [%[a], #348]\n\t" + "ldr r8, [%[b], #336]\n\t" + "ldr r9, [%[b], #340]\n\t" + "ldr r10, [%[b], #344]\n\t" + "ldr r14, [%[b], #348]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #336]\n\t" + "str r5, [%[r], #340]\n\t" + "str r6, [%[r], #344]\n\t" + "str r7, [%[r], #348]\n\t" + "ldr r4, [%[a], #352]\n\t" + "ldr r5, [%[a], #356]\n\t" + "ldr r6, [%[a], #360]\n\t" + "ldr r7, [%[a], #364]\n\t" + "ldr r8, [%[b], #352]\n\t" + "ldr r9, [%[b], #356]\n\t" + "ldr r10, [%[b], #360]\n\t" + "ldr r14, [%[b], #364]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #352]\n\t" + "str r5, [%[r], #356]\n\t" + "str r6, [%[r], #360]\n\t" + "str r7, [%[r], #364]\n\t" + "ldr r4, [%[a], #368]\n\t" + "ldr r5, [%[a], #372]\n\t" + "ldr r6, [%[a], #376]\n\t" + "ldr r7, [%[a], #380]\n\t" + "ldr r8, [%[b], #368]\n\t" + "ldr r9, [%[b], #372]\n\t" + "ldr r10, [%[b], #376]\n\t" + "ldr r14, [%[b], #380]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #368]\n\t" + "str r5, [%[r], #372]\n\t" + "str r6, [%[r], #376]\n\t" + "str r7, [%[r], #380]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + 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_48(sp_digit* r, const 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 +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[96]; + sp_digit a1[48]; + sp_digit b1[48]; + sp_digit z2[96]; + sp_digit u, ca, cb; + + ca = sp_3072_add_48(a1, a, &a[48]); + cb = sp_3072_add_48(b1, b, &b[48]); + u = ca & cb; + sp_3072_mul_48(z1, a1, b1); + sp_3072_mul_48(z2, &a[48], &b[48]); + sp_3072_mul_48(z0, a, b); + sp_3072_mask_48(r + 96, a1, 0 - cb); + sp_3072_mask_48(b1, b1, 0 - ca); + u += sp_3072_add_48(r + 96, r + 96, b1); + u += sp_3072_sub_in_place_96(z1, z2); + u += sp_3072_sub_in_place_96(z1, z0); + u += sp_3072_add_96(r + 48, r + 48, z1); + r[144] = u; + XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1)); + (void)sp_3072_add_96(r + 96, r + 96, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[96]; + sp_digit z1[96]; + sp_digit a1[48]; + sp_digit u; + + u = sp_3072_add_48(a1, a, &a[48]); + sp_3072_sqr_48(z1, a1); + sp_3072_sqr_48(z2, &a[48]); + sp_3072_sqr_48(z0, a); + sp_3072_mask_48(r + 96, a1, 0 - u); + u += sp_3072_add_48(r + 96, r + 96, r + 96); + u += sp_3072_sub_in_place_96(z1, z2); + u += sp_3072_sub_in_place_96(z1, z0); + u += sp_3072_add_96(r + 48, r + 48, z1); + r[144] = u; + XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1)); + (void)sp_3072_add_96(r + 96, r + 96, z2); +} + +#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 sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #384\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_in_place_96(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r14, #0\n\t" + "add r12, %[a], #384\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#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_96(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #768\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #380\n\t" + "it cc\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #384\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #760\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* 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_96(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #768\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #380\n\t" + "it cc\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #384\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #760\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<48; i++) { + r[i] = a[i] & m; + } +} + +#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 sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #192\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * 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__ ( + "mov r14, #0\n\t" + "add r12, %[a], #192\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#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_48(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #384\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #188\n\t" + "it cc\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #192\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #376\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* 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) +{ + __asm__ __volatile__ ( + "sub sp, sp, #384\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #188\n\t" + "it cc\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #192\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #376\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* 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_96(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #384\n\t" + "blt 1b\n\t" + "str r3, [%[r], #384]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #28]\n\t" + "# A[8] * B\n\t" + "ldr r8, [%[a], #32]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[9] * B\n\t" + "ldr r8, [%[a], #36]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[10] * B\n\t" + "ldr r8, [%[a], #40]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[11] * B\n\t" + "ldr r8, [%[a], #44]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[12] * B\n\t" + "ldr r8, [%[a], #48]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[13] * B\n\t" + "ldr r8, [%[a], #52]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[14] * B\n\t" + "ldr r8, [%[a], #56]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #56]\n\t" + "# A[15] * B\n\t" + "ldr r8, [%[a], #60]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #60]\n\t" + "# A[16] * B\n\t" + "ldr r8, [%[a], #64]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[17] * B\n\t" + "ldr r8, [%[a], #68]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[18] * B\n\t" + "ldr r8, [%[a], #72]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[19] * B\n\t" + "ldr r8, [%[a], #76]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[20] * B\n\t" + "ldr r8, [%[a], #80]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[21] * B\n\t" + "ldr r8, [%[a], #84]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[22] * B\n\t" + "ldr r8, [%[a], #88]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #88]\n\t" + "# A[23] * B\n\t" + "ldr r8, [%[a], #92]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #92]\n\t" + "# A[24] * B\n\t" + "ldr r8, [%[a], #96]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #96]\n\t" + "# A[25] * B\n\t" + "ldr r8, [%[a], #100]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #100]\n\t" + "# A[26] * B\n\t" + "ldr r8, [%[a], #104]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #104]\n\t" + "# A[27] * B\n\t" + "ldr r8, [%[a], #108]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #108]\n\t" + "# A[28] * B\n\t" + "ldr r8, [%[a], #112]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #112]\n\t" + "# A[29] * B\n\t" + "ldr r8, [%[a], #116]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #116]\n\t" + "# A[30] * B\n\t" + "ldr r8, [%[a], #120]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #120]\n\t" + "# A[31] * B\n\t" + "ldr r8, [%[a], #124]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #124]\n\t" + "# A[32] * B\n\t" + "ldr r8, [%[a], #128]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #128]\n\t" + "# A[33] * B\n\t" + "ldr r8, [%[a], #132]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #132]\n\t" + "# A[34] * B\n\t" + "ldr r8, [%[a], #136]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #136]\n\t" + "# A[35] * B\n\t" + "ldr r8, [%[a], #140]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #140]\n\t" + "# A[36] * B\n\t" + "ldr r8, [%[a], #144]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #144]\n\t" + "# A[37] * B\n\t" + "ldr r8, [%[a], #148]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #148]\n\t" + "# A[38] * B\n\t" + "ldr r8, [%[a], #152]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #152]\n\t" + "# A[39] * B\n\t" + "ldr r8, [%[a], #156]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #156]\n\t" + "# A[40] * B\n\t" + "ldr r8, [%[a], #160]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #160]\n\t" + "# A[41] * B\n\t" + "ldr r8, [%[a], #164]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #164]\n\t" + "# A[42] * B\n\t" + "ldr r8, [%[a], #168]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #168]\n\t" + "# A[43] * B\n\t" + "ldr r8, [%[a], #172]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #172]\n\t" + "# A[44] * B\n\t" + "ldr r8, [%[a], #176]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #176]\n\t" + "# A[45] * B\n\t" + "ldr r8, [%[a], #180]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #180]\n\t" + "# A[46] * B\n\t" + "ldr r8, [%[a], #184]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #184]\n\t" + "# A[47] * B\n\t" + "ldr r8, [%[a], #188]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #188]\n\t" + "# A[48] * B\n\t" + "ldr r8, [%[a], #192]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #192]\n\t" + "# A[49] * B\n\t" + "ldr r8, [%[a], #196]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #196]\n\t" + "# A[50] * B\n\t" + "ldr r8, [%[a], #200]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #200]\n\t" + "# A[51] * B\n\t" + "ldr r8, [%[a], #204]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #204]\n\t" + "# A[52] * B\n\t" + "ldr r8, [%[a], #208]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #208]\n\t" + "# A[53] * B\n\t" + "ldr r8, [%[a], #212]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #212]\n\t" + "# A[54] * B\n\t" + "ldr r8, [%[a], #216]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #216]\n\t" + "# A[55] * B\n\t" + "ldr r8, [%[a], #220]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #220]\n\t" + "# A[56] * B\n\t" + "ldr r8, [%[a], #224]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #224]\n\t" + "# A[57] * B\n\t" + "ldr r8, [%[a], #228]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #228]\n\t" + "# A[58] * B\n\t" + "ldr r8, [%[a], #232]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #232]\n\t" + "# A[59] * B\n\t" + "ldr r8, [%[a], #236]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #236]\n\t" + "# A[60] * B\n\t" + "ldr r8, [%[a], #240]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #240]\n\t" + "# A[61] * B\n\t" + "ldr r8, [%[a], #244]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #244]\n\t" + "# A[62] * B\n\t" + "ldr r8, [%[a], #248]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #248]\n\t" + "# A[63] * B\n\t" + "ldr r8, [%[a], #252]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #252]\n\t" + "# A[64] * B\n\t" + "ldr r8, [%[a], #256]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #256]\n\t" + "# A[65] * B\n\t" + "ldr r8, [%[a], #260]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #260]\n\t" + "# A[66] * B\n\t" + "ldr r8, [%[a], #264]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #264]\n\t" + "# A[67] * B\n\t" + "ldr r8, [%[a], #268]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #268]\n\t" + "# A[68] * B\n\t" + "ldr r8, [%[a], #272]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #272]\n\t" + "# A[69] * B\n\t" + "ldr r8, [%[a], #276]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #276]\n\t" + "# A[70] * B\n\t" + "ldr r8, [%[a], #280]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #280]\n\t" + "# A[71] * B\n\t" + "ldr r8, [%[a], #284]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #284]\n\t" + "# A[72] * B\n\t" + "ldr r8, [%[a], #288]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #288]\n\t" + "# A[73] * B\n\t" + "ldr r8, [%[a], #292]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #292]\n\t" + "# A[74] * B\n\t" + "ldr r8, [%[a], #296]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #296]\n\t" + "# A[75] * B\n\t" + "ldr r8, [%[a], #300]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #300]\n\t" + "# A[76] * B\n\t" + "ldr r8, [%[a], #304]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #304]\n\t" + "# A[77] * B\n\t" + "ldr r8, [%[a], #308]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #308]\n\t" + "# A[78] * B\n\t" + "ldr r8, [%[a], #312]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #312]\n\t" + "# A[79] * B\n\t" + "ldr r8, [%[a], #316]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #316]\n\t" + "# A[80] * B\n\t" + "ldr r8, [%[a], #320]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #320]\n\t" + "# A[81] * B\n\t" + "ldr r8, [%[a], #324]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #324]\n\t" + "# A[82] * B\n\t" + "ldr r8, [%[a], #328]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #328]\n\t" + "# A[83] * B\n\t" + "ldr r8, [%[a], #332]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #332]\n\t" + "# A[84] * B\n\t" + "ldr r8, [%[a], #336]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #336]\n\t" + "# A[85] * B\n\t" + "ldr r8, [%[a], #340]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #340]\n\t" + "# A[86] * B\n\t" + "ldr r8, [%[a], #344]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #344]\n\t" + "# A[87] * B\n\t" + "ldr r8, [%[a], #348]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #348]\n\t" + "# A[88] * B\n\t" + "ldr r8, [%[a], #352]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #352]\n\t" + "# A[89] * B\n\t" + "ldr r8, [%[a], #356]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #356]\n\t" + "# A[90] * B\n\t" + "ldr r8, [%[a], #360]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #360]\n\t" + "# A[91] * B\n\t" + "ldr r8, [%[a], #364]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #364]\n\t" + "# A[92] * B\n\t" + "ldr r8, [%[a], #368]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #368]\n\t" + "# A[93] * B\n\t" + "ldr r8, [%[a], #372]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #372]\n\t" + "# A[94] * B\n\t" + "ldr r8, [%[a], #376]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #376]\n\t" + "# A[95] * B\n\t" + "ldr r8, [%[a], #380]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r7\n\t" + "str r5, [%[r], #380]\n\t" + "str r3, [%[r], #384]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_3072_mont_norm_48(sp_digit* r, const 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, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #192\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r6, [%[a], #132]\n\t" + "ldr r5, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #128]\n\t" + "str r6, [%[r], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r6, [%[a], #140]\n\t" + "ldr r5, [%[b], #136]\n\t" + "ldr r7, [%[b], #140]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #136]\n\t" + "str r6, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r6, [%[a], #148]\n\t" + "ldr r5, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #144]\n\t" + "str r6, [%[r], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r6, [%[a], #156]\n\t" + "ldr r5, [%[b], #152]\n\t" + "ldr r7, [%[b], #156]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #152]\n\t" + "str r6, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r6, [%[a], #164]\n\t" + "ldr r5, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #160]\n\t" + "str r6, [%[r], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r6, [%[a], #172]\n\t" + "ldr r5, [%[b], #168]\n\t" + "ldr r7, [%[b], #172]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #168]\n\t" + "str r6, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r6, [%[a], #180]\n\t" + "ldr r5, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #176]\n\t" + "str r6, [%[r], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r6, [%[a], #188]\n\t" + "ldr r5, [%[b], #184]\n\t" + "ldr r7, [%[b], #188]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #184]\n\t" + "str r6, [%[r], #188]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + 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, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r7, [%[m], #0]\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr r7, [%[m], #32]\n\t" + "ldr r9, [%[a], #32]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #32]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr r7, [%[m], #36]\n\t" + "ldr r9, [%[a], #36]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #36]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr r7, [%[m], #40]\n\t" + "ldr r9, [%[a], #40]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #40]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr r7, [%[m], #44]\n\t" + "ldr r9, [%[a], #44]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #44]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr r7, [%[m], #48]\n\t" + "ldr r9, [%[a], #48]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #48]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr r7, [%[m], #52]\n\t" + "ldr r9, [%[a], #52]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #52]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr r7, [%[m], #56]\n\t" + "ldr r9, [%[a], #56]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #56]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr r7, [%[m], #60]\n\t" + "ldr r9, [%[a], #60]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #60]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr r7, [%[m], #64]\n\t" + "ldr r9, [%[a], #64]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #64]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr r7, [%[m], #68]\n\t" + "ldr r9, [%[a], #68]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #68]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr r7, [%[m], #72]\n\t" + "ldr r9, [%[a], #72]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #72]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr r7, [%[m], #76]\n\t" + "ldr r9, [%[a], #76]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #76]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr r7, [%[m], #80]\n\t" + "ldr r9, [%[a], #80]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #80]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr r7, [%[m], #84]\n\t" + "ldr r9, [%[a], #84]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #84]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr r7, [%[m], #88]\n\t" + "ldr r9, [%[a], #88]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #88]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr r7, [%[m], #92]\n\t" + "ldr r9, [%[a], #92]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #92]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr r7, [%[m], #96]\n\t" + "ldr r9, [%[a], #96]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #96]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr r7, [%[m], #100]\n\t" + "ldr r9, [%[a], #100]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #100]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr r7, [%[m], #104]\n\t" + "ldr r9, [%[a], #104]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #104]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr r7, [%[m], #108]\n\t" + "ldr r9, [%[a], #108]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #108]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr r7, [%[m], #112]\n\t" + "ldr r9, [%[a], #112]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #112]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr r7, [%[m], #116]\n\t" + "ldr r9, [%[a], #116]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #116]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr r7, [%[m], #120]\n\t" + "ldr r9, [%[a], #120]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #120]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr r7, [%[m], #124]\n\t" + "ldr r9, [%[a], #124]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #124]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+32] += m[32] * mu\n\t" + "ldr r7, [%[m], #128]\n\t" + "ldr r9, [%[a], #128]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #128]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+33] += m[33] * mu\n\t" + "ldr r7, [%[m], #132]\n\t" + "ldr r9, [%[a], #132]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #132]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+34] += m[34] * mu\n\t" + "ldr r7, [%[m], #136]\n\t" + "ldr r9, [%[a], #136]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #136]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+35] += m[35] * mu\n\t" + "ldr r7, [%[m], #140]\n\t" + "ldr r9, [%[a], #140]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #140]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+36] += m[36] * mu\n\t" + "ldr r7, [%[m], #144]\n\t" + "ldr r9, [%[a], #144]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #144]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+37] += m[37] * mu\n\t" + "ldr r7, [%[m], #148]\n\t" + "ldr r9, [%[a], #148]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #148]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+38] += m[38] * mu\n\t" + "ldr r7, [%[m], #152]\n\t" + "ldr r9, [%[a], #152]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #152]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+39] += m[39] * mu\n\t" + "ldr r7, [%[m], #156]\n\t" + "ldr r9, [%[a], #156]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #156]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+40] += m[40] * mu\n\t" + "ldr r7, [%[m], #160]\n\t" + "ldr r9, [%[a], #160]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #160]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+41] += m[41] * mu\n\t" + "ldr r7, [%[m], #164]\n\t" + "ldr r9, [%[a], #164]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #164]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+42] += m[42] * mu\n\t" + "ldr r7, [%[m], #168]\n\t" + "ldr r9, [%[a], #168]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #168]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+43] += m[43] * mu\n\t" + "ldr r7, [%[m], #172]\n\t" + "ldr r9, [%[a], #172]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #172]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+44] += m[44] * mu\n\t" + "ldr r7, [%[m], #176]\n\t" + "ldr r9, [%[a], #176]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #176]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+45] += m[45] * mu\n\t" + "ldr r7, [%[m], #180]\n\t" + "ldr r9, [%[a], #180]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #180]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+46] += m[46] * mu\n\t" + "ldr r7, [%[m], #184]\n\t" + "ldr r9, [%[a], #184]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #184]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+47] += m[47] * mu\n\t" + "ldr r7, [%[m], #188]\n\t" + "ldr r9, [%[a], #188]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #188]\n\t" + "ldr r9, [%[a], #192]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #192]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #192\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "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_48(sp_digit* r, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const 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, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #192\n\t" + "blt 1b\n\t" + "str r3, [%[r], #192]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #28]\n\t" + "# A[8] * B\n\t" + "ldr r8, [%[a], #32]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[9] * B\n\t" + "ldr r8, [%[a], #36]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[10] * B\n\t" + "ldr r8, [%[a], #40]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[11] * B\n\t" + "ldr r8, [%[a], #44]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[12] * B\n\t" + "ldr r8, [%[a], #48]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[13] * B\n\t" + "ldr r8, [%[a], #52]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[14] * B\n\t" + "ldr r8, [%[a], #56]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #56]\n\t" + "# A[15] * B\n\t" + "ldr r8, [%[a], #60]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #60]\n\t" + "# A[16] * B\n\t" + "ldr r8, [%[a], #64]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[17] * B\n\t" + "ldr r8, [%[a], #68]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[18] * B\n\t" + "ldr r8, [%[a], #72]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[19] * B\n\t" + "ldr r8, [%[a], #76]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[20] * B\n\t" + "ldr r8, [%[a], #80]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[21] * B\n\t" + "ldr r8, [%[a], #84]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[22] * B\n\t" + "ldr r8, [%[a], #88]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #88]\n\t" + "# A[23] * B\n\t" + "ldr r8, [%[a], #92]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #92]\n\t" + "# A[24] * B\n\t" + "ldr r8, [%[a], #96]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #96]\n\t" + "# A[25] * B\n\t" + "ldr r8, [%[a], #100]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #100]\n\t" + "# A[26] * B\n\t" + "ldr r8, [%[a], #104]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #104]\n\t" + "# A[27] * B\n\t" + "ldr r8, [%[a], #108]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #108]\n\t" + "# A[28] * B\n\t" + "ldr r8, [%[a], #112]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #112]\n\t" + "# A[29] * B\n\t" + "ldr r8, [%[a], #116]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #116]\n\t" + "# A[30] * B\n\t" + "ldr r8, [%[a], #120]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #120]\n\t" + "# A[31] * B\n\t" + "ldr r8, [%[a], #124]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #124]\n\t" + "# A[32] * B\n\t" + "ldr r8, [%[a], #128]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #128]\n\t" + "# A[33] * B\n\t" + "ldr r8, [%[a], #132]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #132]\n\t" + "# A[34] * B\n\t" + "ldr r8, [%[a], #136]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #136]\n\t" + "# A[35] * B\n\t" + "ldr r8, [%[a], #140]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #140]\n\t" + "# A[36] * B\n\t" + "ldr r8, [%[a], #144]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #144]\n\t" + "# A[37] * B\n\t" + "ldr r8, [%[a], #148]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #148]\n\t" + "# A[38] * B\n\t" + "ldr r8, [%[a], #152]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #152]\n\t" + "# A[39] * B\n\t" + "ldr r8, [%[a], #156]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #156]\n\t" + "# A[40] * B\n\t" + "ldr r8, [%[a], #160]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #160]\n\t" + "# A[41] * B\n\t" + "ldr r8, [%[a], #164]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #164]\n\t" + "# A[42] * B\n\t" + "ldr r8, [%[a], #168]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #168]\n\t" + "# A[43] * B\n\t" + "ldr r8, [%[a], #172]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #172]\n\t" + "# A[44] * B\n\t" + "ldr r8, [%[a], #176]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #176]\n\t" + "# A[45] * B\n\t" + "ldr r8, [%[a], #180]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #180]\n\t" + "# A[46] * B\n\t" + "ldr r8, [%[a], #184]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #184]\n\t" + "# A[47] * B\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r7\n\t" + "str r5, [%[r], #188]\n\t" + "str r3, [%[r], #192]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + 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 int32_t sp_3072_cmp_48(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #188\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "subs r6, r6, #4\n\t" + "bcs 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #188]\n\t" + "ldr r5, [%[b], #188]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[b], #184]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #180]\n\t" + "ldr r5, [%[b], #180]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[b], #176]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #172]\n\t" + "ldr r5, [%[b], #172]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[b], #168]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #164]\n\t" + "ldr r5, [%[b], #164]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[b], #160]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #156]\n\t" + "ldr r5, [%[b], #156]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[b], #152]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #148]\n\t" + "ldr r5, [%[b], #148]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[b], #144]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #140]\n\t" + "ldr r5, [%[b], #140]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[b], #136]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #132]\n\t" + "ldr r5, [%[b], #132]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[b], #128]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + 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 WC_INLINE int sp_3072_div_48(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; + + (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); + + 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, d, (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 WC_INLINE int sp_3072_mod_48(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_48(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][96]; +#else + sp_digit* t[16]; + 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) * 16 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 96; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48U); + if (reduceA != 0) { + 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); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + 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); + } + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U); + 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; +} +#else +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const 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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 96; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48U); + if (reduceA != 0) { + 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) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 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); + } + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U); + 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 /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* 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 single precision number. + */ +static void sp_3072_mont_norm_96(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 96); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_96(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* 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_96(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #384\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r6, [%[a], #132]\n\t" + "ldr r5, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #128]\n\t" + "str r6, [%[r], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r6, [%[a], #140]\n\t" + "ldr r5, [%[b], #136]\n\t" + "ldr r7, [%[b], #140]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #136]\n\t" + "str r6, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r6, [%[a], #148]\n\t" + "ldr r5, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #144]\n\t" + "str r6, [%[r], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r6, [%[a], #156]\n\t" + "ldr r5, [%[b], #152]\n\t" + "ldr r7, [%[b], #156]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #152]\n\t" + "str r6, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r6, [%[a], #164]\n\t" + "ldr r5, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #160]\n\t" + "str r6, [%[r], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r6, [%[a], #172]\n\t" + "ldr r5, [%[b], #168]\n\t" + "ldr r7, [%[b], #172]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #168]\n\t" + "str r6, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r6, [%[a], #180]\n\t" + "ldr r5, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #176]\n\t" + "str r6, [%[r], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r6, [%[a], #188]\n\t" + "ldr r5, [%[b], #184]\n\t" + "ldr r7, [%[b], #188]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #184]\n\t" + "str r6, [%[r], #188]\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r6, [%[a], #196]\n\t" + "ldr r5, [%[b], #192]\n\t" + "ldr r7, [%[b], #196]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #192]\n\t" + "str r6, [%[r], #196]\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r6, [%[a], #204]\n\t" + "ldr r5, [%[b], #200]\n\t" + "ldr r7, [%[b], #204]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #200]\n\t" + "str r6, [%[r], #204]\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r6, [%[a], #212]\n\t" + "ldr r5, [%[b], #208]\n\t" + "ldr r7, [%[b], #212]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #208]\n\t" + "str r6, [%[r], #212]\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r6, [%[a], #220]\n\t" + "ldr r5, [%[b], #216]\n\t" + "ldr r7, [%[b], #220]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #216]\n\t" + "str r6, [%[r], #220]\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r6, [%[a], #228]\n\t" + "ldr r5, [%[b], #224]\n\t" + "ldr r7, [%[b], #228]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #224]\n\t" + "str r6, [%[r], #228]\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r6, [%[a], #236]\n\t" + "ldr r5, [%[b], #232]\n\t" + "ldr r7, [%[b], #236]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #232]\n\t" + "str r6, [%[r], #236]\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r6, [%[a], #244]\n\t" + "ldr r5, [%[b], #240]\n\t" + "ldr r7, [%[b], #244]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #240]\n\t" + "str r6, [%[r], #244]\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r6, [%[a], #252]\n\t" + "ldr r5, [%[b], #248]\n\t" + "ldr r7, [%[b], #252]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #248]\n\t" + "str r6, [%[r], #252]\n\t" + "ldr r4, [%[a], #256]\n\t" + "ldr r6, [%[a], #260]\n\t" + "ldr r5, [%[b], #256]\n\t" + "ldr r7, [%[b], #260]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #256]\n\t" + "str r6, [%[r], #260]\n\t" + "ldr r4, [%[a], #264]\n\t" + "ldr r6, [%[a], #268]\n\t" + "ldr r5, [%[b], #264]\n\t" + "ldr r7, [%[b], #268]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #264]\n\t" + "str r6, [%[r], #268]\n\t" + "ldr r4, [%[a], #272]\n\t" + "ldr r6, [%[a], #276]\n\t" + "ldr r5, [%[b], #272]\n\t" + "ldr r7, [%[b], #276]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #272]\n\t" + "str r6, [%[r], #276]\n\t" + "ldr r4, [%[a], #280]\n\t" + "ldr r6, [%[a], #284]\n\t" + "ldr r5, [%[b], #280]\n\t" + "ldr r7, [%[b], #284]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #280]\n\t" + "str r6, [%[r], #284]\n\t" + "ldr r4, [%[a], #288]\n\t" + "ldr r6, [%[a], #292]\n\t" + "ldr r5, [%[b], #288]\n\t" + "ldr r7, [%[b], #292]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #288]\n\t" + "str r6, [%[r], #292]\n\t" + "ldr r4, [%[a], #296]\n\t" + "ldr r6, [%[a], #300]\n\t" + "ldr r5, [%[b], #296]\n\t" + "ldr r7, [%[b], #300]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #296]\n\t" + "str r6, [%[r], #300]\n\t" + "ldr r4, [%[a], #304]\n\t" + "ldr r6, [%[a], #308]\n\t" + "ldr r5, [%[b], #304]\n\t" + "ldr r7, [%[b], #308]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #304]\n\t" + "str r6, [%[r], #308]\n\t" + "ldr r4, [%[a], #312]\n\t" + "ldr r6, [%[a], #316]\n\t" + "ldr r5, [%[b], #312]\n\t" + "ldr r7, [%[b], #316]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #312]\n\t" + "str r6, [%[r], #316]\n\t" + "ldr r4, [%[a], #320]\n\t" + "ldr r6, [%[a], #324]\n\t" + "ldr r5, [%[b], #320]\n\t" + "ldr r7, [%[b], #324]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #320]\n\t" + "str r6, [%[r], #324]\n\t" + "ldr r4, [%[a], #328]\n\t" + "ldr r6, [%[a], #332]\n\t" + "ldr r5, [%[b], #328]\n\t" + "ldr r7, [%[b], #332]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #328]\n\t" + "str r6, [%[r], #332]\n\t" + "ldr r4, [%[a], #336]\n\t" + "ldr r6, [%[a], #340]\n\t" + "ldr r5, [%[b], #336]\n\t" + "ldr r7, [%[b], #340]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #336]\n\t" + "str r6, [%[r], #340]\n\t" + "ldr r4, [%[a], #344]\n\t" + "ldr r6, [%[a], #348]\n\t" + "ldr r5, [%[b], #344]\n\t" + "ldr r7, [%[b], #348]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #344]\n\t" + "str r6, [%[r], #348]\n\t" + "ldr r4, [%[a], #352]\n\t" + "ldr r6, [%[a], #356]\n\t" + "ldr r5, [%[b], #352]\n\t" + "ldr r7, [%[b], #356]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #352]\n\t" + "str r6, [%[r], #356]\n\t" + "ldr r4, [%[a], #360]\n\t" + "ldr r6, [%[a], #364]\n\t" + "ldr r5, [%[b], #360]\n\t" + "ldr r7, [%[b], #364]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #360]\n\t" + "str r6, [%[r], #364]\n\t" + "ldr r4, [%[a], #368]\n\t" + "ldr r6, [%[a], #372]\n\t" + "ldr r5, [%[b], #368]\n\t" + "ldr r7, [%[b], #372]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #368]\n\t" + "str r6, [%[r], #372]\n\t" + "ldr r4, [%[a], #376]\n\t" + "ldr r6, [%[a], #380]\n\t" + "ldr r5, [%[b], #376]\n\t" + "ldr r7, [%[b], #380]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #376]\n\t" + "str r6, [%[r], #380]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + 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_96(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r7, [%[m], #0]\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr r7, [%[m], #32]\n\t" + "ldr r9, [%[a], #32]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #32]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr r7, [%[m], #36]\n\t" + "ldr r9, [%[a], #36]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #36]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr r7, [%[m], #40]\n\t" + "ldr r9, [%[a], #40]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #40]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr r7, [%[m], #44]\n\t" + "ldr r9, [%[a], #44]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #44]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr r7, [%[m], #48]\n\t" + "ldr r9, [%[a], #48]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #48]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr r7, [%[m], #52]\n\t" + "ldr r9, [%[a], #52]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #52]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr r7, [%[m], #56]\n\t" + "ldr r9, [%[a], #56]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #56]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr r7, [%[m], #60]\n\t" + "ldr r9, [%[a], #60]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #60]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr r7, [%[m], #64]\n\t" + "ldr r9, [%[a], #64]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #64]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr r7, [%[m], #68]\n\t" + "ldr r9, [%[a], #68]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #68]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr r7, [%[m], #72]\n\t" + "ldr r9, [%[a], #72]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #72]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr r7, [%[m], #76]\n\t" + "ldr r9, [%[a], #76]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #76]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr r7, [%[m], #80]\n\t" + "ldr r9, [%[a], #80]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #80]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr r7, [%[m], #84]\n\t" + "ldr r9, [%[a], #84]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #84]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr r7, [%[m], #88]\n\t" + "ldr r9, [%[a], #88]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #88]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr r7, [%[m], #92]\n\t" + "ldr r9, [%[a], #92]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #92]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr r7, [%[m], #96]\n\t" + "ldr r9, [%[a], #96]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #96]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr r7, [%[m], #100]\n\t" + "ldr r9, [%[a], #100]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #100]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr r7, [%[m], #104]\n\t" + "ldr r9, [%[a], #104]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #104]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr r7, [%[m], #108]\n\t" + "ldr r9, [%[a], #108]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #108]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr r7, [%[m], #112]\n\t" + "ldr r9, [%[a], #112]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #112]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr r7, [%[m], #116]\n\t" + "ldr r9, [%[a], #116]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #116]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr r7, [%[m], #120]\n\t" + "ldr r9, [%[a], #120]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #120]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr r7, [%[m], #124]\n\t" + "ldr r9, [%[a], #124]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #124]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+32] += m[32] * mu\n\t" + "ldr r7, [%[m], #128]\n\t" + "ldr r9, [%[a], #128]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #128]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+33] += m[33] * mu\n\t" + "ldr r7, [%[m], #132]\n\t" + "ldr r9, [%[a], #132]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #132]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+34] += m[34] * mu\n\t" + "ldr r7, [%[m], #136]\n\t" + "ldr r9, [%[a], #136]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #136]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+35] += m[35] * mu\n\t" + "ldr r7, [%[m], #140]\n\t" + "ldr r9, [%[a], #140]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #140]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+36] += m[36] * mu\n\t" + "ldr r7, [%[m], #144]\n\t" + "ldr r9, [%[a], #144]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #144]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+37] += m[37] * mu\n\t" + "ldr r7, [%[m], #148]\n\t" + "ldr r9, [%[a], #148]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #148]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+38] += m[38] * mu\n\t" + "ldr r7, [%[m], #152]\n\t" + "ldr r9, [%[a], #152]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #152]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+39] += m[39] * mu\n\t" + "ldr r7, [%[m], #156]\n\t" + "ldr r9, [%[a], #156]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #156]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+40] += m[40] * mu\n\t" + "ldr r7, [%[m], #160]\n\t" + "ldr r9, [%[a], #160]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #160]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+41] += m[41] * mu\n\t" + "ldr r7, [%[m], #164]\n\t" + "ldr r9, [%[a], #164]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #164]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+42] += m[42] * mu\n\t" + "ldr r7, [%[m], #168]\n\t" + "ldr r9, [%[a], #168]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #168]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+43] += m[43] * mu\n\t" + "ldr r7, [%[m], #172]\n\t" + "ldr r9, [%[a], #172]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #172]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+44] += m[44] * mu\n\t" + "ldr r7, [%[m], #176]\n\t" + "ldr r9, [%[a], #176]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #176]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+45] += m[45] * mu\n\t" + "ldr r7, [%[m], #180]\n\t" + "ldr r9, [%[a], #180]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #180]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+46] += m[46] * mu\n\t" + "ldr r7, [%[m], #184]\n\t" + "ldr r9, [%[a], #184]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #184]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+47] += m[47] * mu\n\t" + "ldr r7, [%[m], #188]\n\t" + "ldr r9, [%[a], #188]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #188]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+48] += m[48] * mu\n\t" + "ldr r7, [%[m], #192]\n\t" + "ldr r9, [%[a], #192]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #192]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+49] += m[49] * mu\n\t" + "ldr r7, [%[m], #196]\n\t" + "ldr r9, [%[a], #196]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #196]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+50] += m[50] * mu\n\t" + "ldr r7, [%[m], #200]\n\t" + "ldr r9, [%[a], #200]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #200]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+51] += m[51] * mu\n\t" + "ldr r7, [%[m], #204]\n\t" + "ldr r9, [%[a], #204]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #204]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+52] += m[52] * mu\n\t" + "ldr r7, [%[m], #208]\n\t" + "ldr r9, [%[a], #208]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #208]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+53] += m[53] * mu\n\t" + "ldr r7, [%[m], #212]\n\t" + "ldr r9, [%[a], #212]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #212]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+54] += m[54] * mu\n\t" + "ldr r7, [%[m], #216]\n\t" + "ldr r9, [%[a], #216]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #216]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+55] += m[55] * mu\n\t" + "ldr r7, [%[m], #220]\n\t" + "ldr r9, [%[a], #220]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #220]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+56] += m[56] * mu\n\t" + "ldr r7, [%[m], #224]\n\t" + "ldr r9, [%[a], #224]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #224]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+57] += m[57] * mu\n\t" + "ldr r7, [%[m], #228]\n\t" + "ldr r9, [%[a], #228]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #228]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+58] += m[58] * mu\n\t" + "ldr r7, [%[m], #232]\n\t" + "ldr r9, [%[a], #232]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #232]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+59] += m[59] * mu\n\t" + "ldr r7, [%[m], #236]\n\t" + "ldr r9, [%[a], #236]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #236]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+60] += m[60] * mu\n\t" + "ldr r7, [%[m], #240]\n\t" + "ldr r9, [%[a], #240]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #240]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+61] += m[61] * mu\n\t" + "ldr r7, [%[m], #244]\n\t" + "ldr r9, [%[a], #244]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #244]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+62] += m[62] * mu\n\t" + "ldr r7, [%[m], #248]\n\t" + "ldr r9, [%[a], #248]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #248]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+63] += m[63] * mu\n\t" + "ldr r7, [%[m], #252]\n\t" + "ldr r9, [%[a], #252]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #252]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+64] += m[64] * mu\n\t" + "ldr r7, [%[m], #256]\n\t" + "ldr r9, [%[a], #256]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #256]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+65] += m[65] * mu\n\t" + "ldr r7, [%[m], #260]\n\t" + "ldr r9, [%[a], #260]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #260]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+66] += m[66] * mu\n\t" + "ldr r7, [%[m], #264]\n\t" + "ldr r9, [%[a], #264]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #264]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+67] += m[67] * mu\n\t" + "ldr r7, [%[m], #268]\n\t" + "ldr r9, [%[a], #268]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #268]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+68] += m[68] * mu\n\t" + "ldr r7, [%[m], #272]\n\t" + "ldr r9, [%[a], #272]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #272]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+69] += m[69] * mu\n\t" + "ldr r7, [%[m], #276]\n\t" + "ldr r9, [%[a], #276]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #276]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+70] += m[70] * mu\n\t" + "ldr r7, [%[m], #280]\n\t" + "ldr r9, [%[a], #280]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #280]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+71] += m[71] * mu\n\t" + "ldr r7, [%[m], #284]\n\t" + "ldr r9, [%[a], #284]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #284]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+72] += m[72] * mu\n\t" + "ldr r7, [%[m], #288]\n\t" + "ldr r9, [%[a], #288]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #288]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+73] += m[73] * mu\n\t" + "ldr r7, [%[m], #292]\n\t" + "ldr r9, [%[a], #292]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #292]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+74] += m[74] * mu\n\t" + "ldr r7, [%[m], #296]\n\t" + "ldr r9, [%[a], #296]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #296]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+75] += m[75] * mu\n\t" + "ldr r7, [%[m], #300]\n\t" + "ldr r9, [%[a], #300]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #300]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+76] += m[76] * mu\n\t" + "ldr r7, [%[m], #304]\n\t" + "ldr r9, [%[a], #304]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #304]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+77] += m[77] * mu\n\t" + "ldr r7, [%[m], #308]\n\t" + "ldr r9, [%[a], #308]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #308]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+78] += m[78] * mu\n\t" + "ldr r7, [%[m], #312]\n\t" + "ldr r9, [%[a], #312]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #312]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+79] += m[79] * mu\n\t" + "ldr r7, [%[m], #316]\n\t" + "ldr r9, [%[a], #316]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #316]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+80] += m[80] * mu\n\t" + "ldr r7, [%[m], #320]\n\t" + "ldr r9, [%[a], #320]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #320]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+81] += m[81] * mu\n\t" + "ldr r7, [%[m], #324]\n\t" + "ldr r9, [%[a], #324]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #324]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+82] += m[82] * mu\n\t" + "ldr r7, [%[m], #328]\n\t" + "ldr r9, [%[a], #328]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #328]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+83] += m[83] * mu\n\t" + "ldr r7, [%[m], #332]\n\t" + "ldr r9, [%[a], #332]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #332]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+84] += m[84] * mu\n\t" + "ldr r7, [%[m], #336]\n\t" + "ldr r9, [%[a], #336]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #336]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+85] += m[85] * mu\n\t" + "ldr r7, [%[m], #340]\n\t" + "ldr r9, [%[a], #340]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #340]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+86] += m[86] * mu\n\t" + "ldr r7, [%[m], #344]\n\t" + "ldr r9, [%[a], #344]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #344]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+87] += m[87] * mu\n\t" + "ldr r7, [%[m], #348]\n\t" + "ldr r9, [%[a], #348]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #348]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+88] += m[88] * mu\n\t" + "ldr r7, [%[m], #352]\n\t" + "ldr r9, [%[a], #352]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #352]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+89] += m[89] * mu\n\t" + "ldr r7, [%[m], #356]\n\t" + "ldr r9, [%[a], #356]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #356]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+90] += m[90] * mu\n\t" + "ldr r7, [%[m], #360]\n\t" + "ldr r9, [%[a], #360]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #360]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+91] += m[91] * mu\n\t" + "ldr r7, [%[m], #364]\n\t" + "ldr r9, [%[a], #364]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #364]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+92] += m[92] * mu\n\t" + "ldr r7, [%[m], #368]\n\t" + "ldr r9, [%[a], #368]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #368]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+93] += m[93] * mu\n\t" + "ldr r7, [%[m], #372]\n\t" + "ldr r9, [%[a], #372]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #372]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+94] += m[94] * mu\n\t" + "ldr r7, [%[m], #376]\n\t" + "ldr r9, [%[a], #376]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #376]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+95] += m[95] * mu\n\t" + "ldr r7, [%[m], #380]\n\t" + "ldr r9, [%[a], #380]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #380]\n\t" + "ldr r9, [%[a], #384]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #384]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #384\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + sp_3072_cond_sub_96(a - 96, 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_96(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_3072_mul_96(r, a, b); + sp_3072_mont_reduce_96(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_96(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_96(r, a); + sp_3072_mont_reduce_96(r, m, mp); +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_3072_word_96(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + 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_96(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<96; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 96; 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 int32_t sp_3072_cmp_96(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #380\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "subs r6, r6, #4\n\t" + "bcs 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #380]\n\t" + "ldr r5, [%[b], #380]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #376]\n\t" + "ldr r5, [%[b], #376]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #372]\n\t" + "ldr r5, [%[b], #372]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #368]\n\t" + "ldr r5, [%[b], #368]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #364]\n\t" + "ldr r5, [%[b], #364]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #360]\n\t" + "ldr r5, [%[b], #360]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #356]\n\t" + "ldr r5, [%[b], #356]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #352]\n\t" + "ldr r5, [%[b], #352]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #348]\n\t" + "ldr r5, [%[b], #348]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #344]\n\t" + "ldr r5, [%[b], #344]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #340]\n\t" + "ldr r5, [%[b], #340]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #336]\n\t" + "ldr r5, [%[b], #336]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #332]\n\t" + "ldr r5, [%[b], #332]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #328]\n\t" + "ldr r5, [%[b], #328]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #324]\n\t" + "ldr r5, [%[b], #324]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #320]\n\t" + "ldr r5, [%[b], #320]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #316]\n\t" + "ldr r5, [%[b], #316]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #312]\n\t" + "ldr r5, [%[b], #312]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #308]\n\t" + "ldr r5, [%[b], #308]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #304]\n\t" + "ldr r5, [%[b], #304]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #300]\n\t" + "ldr r5, [%[b], #300]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #296]\n\t" + "ldr r5, [%[b], #296]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #292]\n\t" + "ldr r5, [%[b], #292]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #288]\n\t" + "ldr r5, [%[b], #288]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #284]\n\t" + "ldr r5, [%[b], #284]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #280]\n\t" + "ldr r5, [%[b], #280]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #276]\n\t" + "ldr r5, [%[b], #276]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #272]\n\t" + "ldr r5, [%[b], #272]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #268]\n\t" + "ldr r5, [%[b], #268]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #264]\n\t" + "ldr r5, [%[b], #264]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #260]\n\t" + "ldr r5, [%[b], #260]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #256]\n\t" + "ldr r5, [%[b], #256]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #252]\n\t" + "ldr r5, [%[b], #252]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r5, [%[b], #248]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #244]\n\t" + "ldr r5, [%[b], #244]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r5, [%[b], #240]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #236]\n\t" + "ldr r5, [%[b], #236]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r5, [%[b], #232]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #228]\n\t" + "ldr r5, [%[b], #228]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r5, [%[b], #224]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #220]\n\t" + "ldr r5, [%[b], #220]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r5, [%[b], #216]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #212]\n\t" + "ldr r5, [%[b], #212]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r5, [%[b], #208]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #204]\n\t" + "ldr r5, [%[b], #204]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r5, [%[b], #200]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #196]\n\t" + "ldr r5, [%[b], #196]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r5, [%[b], #192]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #188]\n\t" + "ldr r5, [%[b], #188]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[b], #184]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #180]\n\t" + "ldr r5, [%[b], #180]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[b], #176]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #172]\n\t" + "ldr r5, [%[b], #172]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[b], #168]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #164]\n\t" + "ldr r5, [%[b], #164]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[b], #160]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #156]\n\t" + "ldr r5, [%[b], #156]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[b], #152]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #148]\n\t" + "ldr r5, [%[b], #148]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[b], #144]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #140]\n\t" + "ldr r5, [%[b], #140]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[b], #136]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #132]\n\t" + "ldr r5, [%[b], #132]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[b], #128]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + 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 WC_INLINE int sp_3072_div_96(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[192], t2[97]; + sp_digit div, r1; + int i; + + (void)m; + + + div = d[95]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 96); + for (i=95; i>=0; i--) { + r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div); + + sp_3072_mul_d_96(t2, d, r1); + t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2); + t1[96 + i] -= t2[96]; + sp_3072_mask_96(t2, d, t1[96 + i]); + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2); + sp_3072_mask_96(t2, d, t1[96 + i]); + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_96(t1, d) >= 0; + sp_3072_cond_sub_96(r, t1, d, (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 WC_INLINE int sp_3072_mod_96(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_96(a, m, NULL, r); +} + +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +/* 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 WC_INLINE int sp_3072_div_96_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[192], t2[97]; + sp_digit div, r1; + int i; + + (void)m; + + + div = d[95]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 96); + for (i=95; i>=0; i--) { + r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div); + + sp_3072_mul_d_96(t2, d, r1); + t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2); + t1[96 + i] -= t2[96]; + if (t1[96 + i] != 0) { + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d); + if (t1[96 + i] != 0) + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d); + } + } + + r1 = sp_3072_cmp_96(t1, d) >= 0; + sp_3072_cond_sub_96(r, t1, d, (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 WC_INLINE int sp_3072_mod_96_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_96_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* 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_96(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][192]; +#else + sp_digit* t[16]; + 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) * 16 * 192, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 192; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 96U); + if (reduceA != 0) { + err = sp_3072_mod_96(t[1] + 96, a, m); + if (err == MP_OKAY) { + err = sp_3072_mod_96(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96); + err = sp_3072_mod_96(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_96(t[10], t[ 5], m, mp); + sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_96(t[12], t[ 6], m, mp); + sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_96(t[14], t[ 7], m, mp); + sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 96); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_mont_mul_96(r, r, t[y], m, mp); + } + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#else +/* 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_96(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][192]; +#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 * 192, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 192; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 96U); + if (reduceA != 0) { + err = sp_3072_mod_96(t[1] + 96, a, m); + if (err == MP_OKAY) { + err = sp_3072_mod_96(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96); + err = sp_3072_mod_96(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_96(t[10], t[ 5], m, mp); + sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_96(t[12], t[ 6], m, mp); + sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_96(t[14], t[ 7], m, mp); + sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_96(t[16], t[ 8], m, mp); + sp_3072_mont_mul_96(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_96(t[18], t[ 9], m, mp); + sp_3072_mont_mul_96(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_96(t[20], t[10], m, mp); + sp_3072_mont_mul_96(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_96(t[22], t[11], m, mp); + sp_3072_mont_mul_96(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_96(t[24], t[12], m, mp); + sp_3072_mont_mul_96(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_96(t[26], t[13], m, mp); + sp_3072_mont_mul_96(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_96(t[28], t[14], m, mp); + sp_3072_mont_mul_96(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_96(t[30], t[15], m, mp); + sp_3072_mont_mul_96(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 96); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_mont_mul_96(r, r, t[y], m, mp); + } + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[192], m[96], r[192]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; +#endif + sp_digit *ah; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 96 * 2; + m = r + 96 * 2; + } +#endif + + if (err == MP_OKAY) { + ah = a + 96; + + sp_3072_from_bin(ah, 96, in, inLen); +#if DIGIT_BIT >= 32 + 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, 96, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_3072_sqr_96(r, ah); + err = sp_3072_mod_96_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_96(r, ah, r); + err = sp_3072_mod_96_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) * 96); + err = sp_3072_mod_96_cond(a, a, m); + + if (err == MP_OKAY) { + for (i = 31; i >= 0; i--) { + if (e[0] >> i) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 96); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_96(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) { + sp_3072_mont_mul_96(r, r, a, m, mp); + } + } + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96); + sp_3072_mont_reduce_96(r, m, mp); + + for (i = 95; i > 0; i--) { + if (r[i] != m[i]) { + break; + } + } + if (r[i] >= m[i]) { + sp_3072_sub_in_place_96(r, m); + } + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) + 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 < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 3072) { + err = MP_READ_E; + } + if (inLen > 384) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 96; + m = a + 192; + r = a; + + sp_3072_from_bin(a, 96, in, inLen); + sp_3072_from_mp(d, 96, dm); + sp_3072_from_mp(m, 96, mm); + err = sp_3072_mod_exp_96(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) * 96); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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 sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #192\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adds r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r6, [%[a], #132]\n\t" + "ldr r5, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #128]\n\t" + "str r6, [%[r], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r6, [%[a], #140]\n\t" + "ldr r5, [%[b], #136]\n\t" + "ldr r7, [%[b], #140]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #136]\n\t" + "str r6, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r6, [%[a], #148]\n\t" + "ldr r5, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #144]\n\t" + "str r6, [%[r], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r6, [%[a], #156]\n\t" + "ldr r5, [%[b], #152]\n\t" + "ldr r7, [%[b], #156]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #152]\n\t" + "str r6, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r6, [%[a], #164]\n\t" + "ldr r5, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #160]\n\t" + "str r6, [%[r], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r6, [%[a], #172]\n\t" + "ldr r5, [%[b], #168]\n\t" + "ldr r7, [%[b], #172]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #168]\n\t" + "str r6, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r6, [%[a], #180]\n\t" + "ldr r5, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #176]\n\t" + "str r6, [%[r], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r6, [%[a], #188]\n\t" + "ldr r5, [%[b], #184]\n\t" + "ldr r7, [%[b], #188]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #184]\n\t" + "str r6, [%[r], #188]\n\t" + "adc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[96 * 2]; + sp_digit p[48], q[48], dp[48]; + sp_digit tmpa[96], tmpb[96]; +#else + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* tmpa; + sp_digit* tmpb; +#endif + sp_digit* r; + sp_digit* qi; + sp_digit* dq; + sp_digit c; + 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 (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 96 * 2; + q = p + 48; + qi = dq = dp = q + 48; + tmpa = qi + 48; + tmpb = tmpa + 96; + + r = t + 96; + } +#else +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + r = a; + qi = dq = dp; +#endif + sp_3072_from_bin(a, 96, in, inLen); + sp_3072_from_mp(p, 48, pm); + sp_3072_from_mp(q, 48, qm); + sp_3072_from_mp(dp, 48, dpm); + + err = sp_3072_mod_exp_48(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 48, dqm); + err = sp_3072_mod_exp_48(tmpb, a, dq, 1536, q, 1); + } + + if (err == MP_OKAY) { + c = sp_3072_sub_in_place_48(tmpa, tmpb); + c += sp_3072_cond_add_48(tmpa, tmpa, p, c); + sp_3072_cond_add_48(tmpa, tmpa, p, c); + + sp_3072_from_mp(qi, 48, qim); + sp_3072_mul_48(tmpa, tmpa, qi); + err = sp_3072_mod_48(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_48(tmpa, q, tmpa); + XMEMSET(&tmpb[48], 0, sizeof(sp_digit) * 48); + sp_3072_add_96(r, tmpb, tmpa); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 48 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + 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)); +#endif + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 96); + r->used = 96; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 96; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 96; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[192], e[96], m[96]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 96, base); + sp_3072_from_mp(e, 96, exp); + sp_3072_from_mp(m, 96, mod); + + err = sp_3072_mod_exp_96(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_3072 +static void sp_3072_lshift_96(sp_digit* r, sp_digit* a, byte n) +{ + __asm__ __volatile__ ( + "mov r6, #31\n\t" + "sub r6, r6, %[n]\n\t" + "ldr r3, [%[a], #380]\n\t" + "lsr r4, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r4, r4, r6\n\t" + "ldr r2, [%[a], #376]\n\t" + "str r4, [%[r], #384]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #372]\n\t" + "str r3, [%[r], #380]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #368]\n\t" + "str r2, [%[r], #376]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #364]\n\t" + "str r4, [%[r], #372]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #360]\n\t" + "str r3, [%[r], #368]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #356]\n\t" + "str r2, [%[r], #364]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #352]\n\t" + "str r4, [%[r], #360]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #348]\n\t" + "str r3, [%[r], #356]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #344]\n\t" + "str r2, [%[r], #352]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #340]\n\t" + "str r4, [%[r], #348]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #336]\n\t" + "str r3, [%[r], #344]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #332]\n\t" + "str r2, [%[r], #340]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #328]\n\t" + "str r4, [%[r], #336]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #324]\n\t" + "str r3, [%[r], #332]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #320]\n\t" + "str r2, [%[r], #328]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #316]\n\t" + "str r4, [%[r], #324]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #312]\n\t" + "str r3, [%[r], #320]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #308]\n\t" + "str r2, [%[r], #316]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #304]\n\t" + "str r4, [%[r], #312]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #300]\n\t" + "str r3, [%[r], #308]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #296]\n\t" + "str r2, [%[r], #304]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #292]\n\t" + "str r4, [%[r], #300]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #288]\n\t" + "str r3, [%[r], #296]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #284]\n\t" + "str r2, [%[r], #292]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #280]\n\t" + "str r4, [%[r], #288]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #276]\n\t" + "str r3, [%[r], #284]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #272]\n\t" + "str r2, [%[r], #280]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #268]\n\t" + "str r4, [%[r], #276]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #264]\n\t" + "str r3, [%[r], #272]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #260]\n\t" + "str r2, [%[r], #268]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #256]\n\t" + "str r4, [%[r], #264]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #252]\n\t" + "str r3, [%[r], #260]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #248]\n\t" + "str r2, [%[r], #256]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #244]\n\t" + "str r4, [%[r], #252]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #240]\n\t" + "str r3, [%[r], #248]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #236]\n\t" + "str r2, [%[r], #244]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #232]\n\t" + "str r4, [%[r], #240]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #228]\n\t" + "str r3, [%[r], #236]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #224]\n\t" + "str r2, [%[r], #232]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #220]\n\t" + "str r4, [%[r], #228]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #216]\n\t" + "str r3, [%[r], #224]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #212]\n\t" + "str r2, [%[r], #220]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #208]\n\t" + "str r4, [%[r], #216]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #204]\n\t" + "str r3, [%[r], #212]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #200]\n\t" + "str r2, [%[r], #208]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #196]\n\t" + "str r4, [%[r], #204]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #192]\n\t" + "str r3, [%[r], #200]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #188]\n\t" + "str r2, [%[r], #196]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #184]\n\t" + "str r4, [%[r], #192]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #180]\n\t" + "str r3, [%[r], #188]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #176]\n\t" + "str r2, [%[r], #184]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #172]\n\t" + "str r4, [%[r], #180]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #168]\n\t" + "str r3, [%[r], #176]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #164]\n\t" + "str r2, [%[r], #172]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #160]\n\t" + "str r4, [%[r], #168]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #156]\n\t" + "str r3, [%[r], #164]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #152]\n\t" + "str r2, [%[r], #160]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #148]\n\t" + "str r4, [%[r], #156]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #144]\n\t" + "str r3, [%[r], #152]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #140]\n\t" + "str r2, [%[r], #148]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #136]\n\t" + "str r4, [%[r], #144]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #132]\n\t" + "str r3, [%[r], #140]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #128]\n\t" + "str r2, [%[r], #136]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #124]\n\t" + "str r4, [%[r], #132]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #120]\n\t" + "str r3, [%[r], #128]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #116]\n\t" + "str r2, [%[r], #124]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #112]\n\t" + "str r4, [%[r], #120]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #108]\n\t" + "str r3, [%[r], #116]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #104]\n\t" + "str r2, [%[r], #112]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #100]\n\t" + "str r4, [%[r], #108]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #96]\n\t" + "str r3, [%[r], #104]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #92]\n\t" + "str r2, [%[r], #100]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #88]\n\t" + "str r4, [%[r], #96]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #84]\n\t" + "str r3, [%[r], #92]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #80]\n\t" + "str r2, [%[r], #88]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #76]\n\t" + "str r4, [%[r], #84]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #72]\n\t" + "str r3, [%[r], #80]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #68]\n\t" + "str r2, [%[r], #76]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #64]\n\t" + "str r4, [%[r], #72]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #60]\n\t" + "str r3, [%[r], #68]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #56]\n\t" + "str r2, [%[r], #64]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #52]\n\t" + "str r4, [%[r], #60]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #48]\n\t" + "str r3, [%[r], #56]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #44]\n\t" + "str r2, [%[r], #52]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #40]\n\t" + "str r4, [%[r], #48]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #36]\n\t" + "str r3, [%[r], #44]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #32]\n\t" + "str r2, [%[r], #40]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #28]\n\t" + "str r4, [%[r], #36]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #24]\n\t" + "str r3, [%[r], #32]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #20]\n\t" + "str r2, [%[r], #28]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #16]\n\t" + "str r4, [%[r], #24]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #12]\n\t" + "str r3, [%[r], #20]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #8]\n\t" + "str r2, [%[r], #16]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #4]\n\t" + "str r4, [%[r], #12]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #0]\n\t" + "str r3, [%[r], #8]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "str r4, [%[r]]\n\t" + "str r2, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [n] "r" (n) + : "memory", "r2", "r3", "r4", "r5", "r6" + ); +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_96(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[192]; + sp_digit td[97]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 289, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 192; +#else + norm = nd; + tmp = td; +#endif + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + sp_3072_lshift_96(r, norm, y); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_lshift_96(r, r, y); + sp_3072_mul_d_96(tmp, norm, r[96]); + r[96] = 0; + o = sp_3072_add_96(r, r, tmp); + sp_3072_cond_sub_96(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* HAVE_FFDHE_3072 */ + +/* 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. + * returns 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[192], e[96], m[96]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 384) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 96, base); + sp_3072_from_bin(e, 96, exp, expLen); + sp_3072_from_mp(m, 96, mod); + + #ifdef HAVE_FFDHE_3072 + if (base->used == 1 && base->dp[0] == 2 && m[95] == (sp_digit)-1) + err = sp_3072_mod_exp_2_96(r, e, expLen * 8, m); + else + #endif + err = sp_3072_mod_exp_96(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 */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_mp(e, 48, exp); + sp_3072_from_mp(m, 48, mod); + + err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 48, 0, sizeof(*r) * 48U); + err = sp_3072_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#ifdef WOLFSSL_SP_4096 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 512 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_4096_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 4096 / 8 - 1; + a[j] = 0; + for (i=0; i<128 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + a[j] = 0; + } + if (s != 0) { + j++; + } + } +} + +#ifndef 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 sp_digit sp_4096_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "ldr r8, [%[b], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "ldr r10, [%[b], #104]\n\t" + "ldr r14, [%[b], #108]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "ldr r8, [%[b], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "ldr r10, [%[b], #120]\n\t" + "ldr r14, [%[b], #124]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[a], #132]\n\t" + "ldr r6, [%[a], #136]\n\t" + "ldr r7, [%[a], #140]\n\t" + "ldr r8, [%[b], #128]\n\t" + "ldr r9, [%[b], #132]\n\t" + "ldr r10, [%[b], #136]\n\t" + "ldr r14, [%[b], #140]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #128]\n\t" + "str r5, [%[r], #132]\n\t" + "str r6, [%[r], #136]\n\t" + "str r7, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[a], #148]\n\t" + "ldr r6, [%[a], #152]\n\t" + "ldr r7, [%[a], #156]\n\t" + "ldr r8, [%[b], #144]\n\t" + "ldr r9, [%[b], #148]\n\t" + "ldr r10, [%[b], #152]\n\t" + "ldr r14, [%[b], #156]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #144]\n\t" + "str r5, [%[r], #148]\n\t" + "str r6, [%[r], #152]\n\t" + "str r7, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[a], #164]\n\t" + "ldr r6, [%[a], #168]\n\t" + "ldr r7, [%[a], #172]\n\t" + "ldr r8, [%[b], #160]\n\t" + "ldr r9, [%[b], #164]\n\t" + "ldr r10, [%[b], #168]\n\t" + "ldr r14, [%[b], #172]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #160]\n\t" + "str r5, [%[r], #164]\n\t" + "str r6, [%[r], #168]\n\t" + "str r7, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[a], #180]\n\t" + "ldr r6, [%[a], #184]\n\t" + "ldr r7, [%[a], #188]\n\t" + "ldr r8, [%[b], #176]\n\t" + "ldr r9, [%[b], #180]\n\t" + "ldr r10, [%[b], #184]\n\t" + "ldr r14, [%[b], #188]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #176]\n\t" + "str r5, [%[r], #180]\n\t" + "str r6, [%[r], #184]\n\t" + "str r7, [%[r], #188]\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r5, [%[a], #196]\n\t" + "ldr r6, [%[a], #200]\n\t" + "ldr r7, [%[a], #204]\n\t" + "ldr r8, [%[b], #192]\n\t" + "ldr r9, [%[b], #196]\n\t" + "ldr r10, [%[b], #200]\n\t" + "ldr r14, [%[b], #204]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #192]\n\t" + "str r5, [%[r], #196]\n\t" + "str r6, [%[r], #200]\n\t" + "str r7, [%[r], #204]\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r5, [%[a], #212]\n\t" + "ldr r6, [%[a], #216]\n\t" + "ldr r7, [%[a], #220]\n\t" + "ldr r8, [%[b], #208]\n\t" + "ldr r9, [%[b], #212]\n\t" + "ldr r10, [%[b], #216]\n\t" + "ldr r14, [%[b], #220]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #208]\n\t" + "str r5, [%[r], #212]\n\t" + "str r6, [%[r], #216]\n\t" + "str r7, [%[r], #220]\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r5, [%[a], #228]\n\t" + "ldr r6, [%[a], #232]\n\t" + "ldr r7, [%[a], #236]\n\t" + "ldr r8, [%[b], #224]\n\t" + "ldr r9, [%[b], #228]\n\t" + "ldr r10, [%[b], #232]\n\t" + "ldr r14, [%[b], #236]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #224]\n\t" + "str r5, [%[r], #228]\n\t" + "str r6, [%[r], #232]\n\t" + "str r7, [%[r], #236]\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r5, [%[a], #244]\n\t" + "ldr r6, [%[a], #248]\n\t" + "ldr r7, [%[a], #252]\n\t" + "ldr r8, [%[b], #240]\n\t" + "ldr r9, [%[b], #244]\n\t" + "ldr r10, [%[b], #248]\n\t" + "ldr r14, [%[b], #252]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #240]\n\t" + "str r5, [%[r], #244]\n\t" + "str r6, [%[r], #248]\n\t" + "str r7, [%[r], #252]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + 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_4096_sub_in_place_128(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "ldr r2, [%[a], #64]\n\t" + "ldr r3, [%[a], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "ldr r8, [%[b], #72]\n\t" + "ldr r9, [%[b], #76]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #64]\n\t" + "str r3, [%[a], #68]\n\t" + "str r4, [%[a], #72]\n\t" + "str r5, [%[a], #76]\n\t" + "ldr r2, [%[a], #80]\n\t" + "ldr r3, [%[a], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "ldr r8, [%[b], #88]\n\t" + "ldr r9, [%[b], #92]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #80]\n\t" + "str r3, [%[a], #84]\n\t" + "str r4, [%[a], #88]\n\t" + "str r5, [%[a], #92]\n\t" + "ldr r2, [%[a], #96]\n\t" + "ldr r3, [%[a], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "ldr r8, [%[b], #104]\n\t" + "ldr r9, [%[b], #108]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #96]\n\t" + "str r3, [%[a], #100]\n\t" + "str r4, [%[a], #104]\n\t" + "str r5, [%[a], #108]\n\t" + "ldr r2, [%[a], #112]\n\t" + "ldr r3, [%[a], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "ldr r8, [%[b], #120]\n\t" + "ldr r9, [%[b], #124]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #112]\n\t" + "str r3, [%[a], #116]\n\t" + "str r4, [%[a], #120]\n\t" + "str r5, [%[a], #124]\n\t" + "ldr r2, [%[a], #128]\n\t" + "ldr r3, [%[a], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[a], #140]\n\t" + "ldr r6, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "ldr r8, [%[b], #136]\n\t" + "ldr r9, [%[b], #140]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #128]\n\t" + "str r3, [%[a], #132]\n\t" + "str r4, [%[a], #136]\n\t" + "str r5, [%[a], #140]\n\t" + "ldr r2, [%[a], #144]\n\t" + "ldr r3, [%[a], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[a], #156]\n\t" + "ldr r6, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "ldr r8, [%[b], #152]\n\t" + "ldr r9, [%[b], #156]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #144]\n\t" + "str r3, [%[a], #148]\n\t" + "str r4, [%[a], #152]\n\t" + "str r5, [%[a], #156]\n\t" + "ldr r2, [%[a], #160]\n\t" + "ldr r3, [%[a], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[a], #172]\n\t" + "ldr r6, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "ldr r8, [%[b], #168]\n\t" + "ldr r9, [%[b], #172]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #160]\n\t" + "str r3, [%[a], #164]\n\t" + "str r4, [%[a], #168]\n\t" + "str r5, [%[a], #172]\n\t" + "ldr r2, [%[a], #176]\n\t" + "ldr r3, [%[a], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[a], #188]\n\t" + "ldr r6, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "ldr r8, [%[b], #184]\n\t" + "ldr r9, [%[b], #188]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #176]\n\t" + "str r3, [%[a], #180]\n\t" + "str r4, [%[a], #184]\n\t" + "str r5, [%[a], #188]\n\t" + "ldr r2, [%[a], #192]\n\t" + "ldr r3, [%[a], #196]\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r5, [%[a], #204]\n\t" + "ldr r6, [%[b], #192]\n\t" + "ldr r7, [%[b], #196]\n\t" + "ldr r8, [%[b], #200]\n\t" + "ldr r9, [%[b], #204]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #192]\n\t" + "str r3, [%[a], #196]\n\t" + "str r4, [%[a], #200]\n\t" + "str r5, [%[a], #204]\n\t" + "ldr r2, [%[a], #208]\n\t" + "ldr r3, [%[a], #212]\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r5, [%[a], #220]\n\t" + "ldr r6, [%[b], #208]\n\t" + "ldr r7, [%[b], #212]\n\t" + "ldr r8, [%[b], #216]\n\t" + "ldr r9, [%[b], #220]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #208]\n\t" + "str r3, [%[a], #212]\n\t" + "str r4, [%[a], #216]\n\t" + "str r5, [%[a], #220]\n\t" + "ldr r2, [%[a], #224]\n\t" + "ldr r3, [%[a], #228]\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r5, [%[a], #236]\n\t" + "ldr r6, [%[b], #224]\n\t" + "ldr r7, [%[b], #228]\n\t" + "ldr r8, [%[b], #232]\n\t" + "ldr r9, [%[b], #236]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #224]\n\t" + "str r3, [%[a], #228]\n\t" + "str r4, [%[a], #232]\n\t" + "str r5, [%[a], #236]\n\t" + "ldr r2, [%[a], #240]\n\t" + "ldr r3, [%[a], #244]\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r5, [%[a], #252]\n\t" + "ldr r6, [%[b], #240]\n\t" + "ldr r7, [%[b], #244]\n\t" + "ldr r8, [%[b], #248]\n\t" + "ldr r9, [%[b], #252]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #240]\n\t" + "str r3, [%[a], #244]\n\t" + "str r4, [%[a], #248]\n\t" + "str r5, [%[a], #252]\n\t" + "ldr r2, [%[a], #256]\n\t" + "ldr r3, [%[a], #260]\n\t" + "ldr r4, [%[a], #264]\n\t" + "ldr r5, [%[a], #268]\n\t" + "ldr r6, [%[b], #256]\n\t" + "ldr r7, [%[b], #260]\n\t" + "ldr r8, [%[b], #264]\n\t" + "ldr r9, [%[b], #268]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #256]\n\t" + "str r3, [%[a], #260]\n\t" + "str r4, [%[a], #264]\n\t" + "str r5, [%[a], #268]\n\t" + "ldr r2, [%[a], #272]\n\t" + "ldr r3, [%[a], #276]\n\t" + "ldr r4, [%[a], #280]\n\t" + "ldr r5, [%[a], #284]\n\t" + "ldr r6, [%[b], #272]\n\t" + "ldr r7, [%[b], #276]\n\t" + "ldr r8, [%[b], #280]\n\t" + "ldr r9, [%[b], #284]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #272]\n\t" + "str r3, [%[a], #276]\n\t" + "str r4, [%[a], #280]\n\t" + "str r5, [%[a], #284]\n\t" + "ldr r2, [%[a], #288]\n\t" + "ldr r3, [%[a], #292]\n\t" + "ldr r4, [%[a], #296]\n\t" + "ldr r5, [%[a], #300]\n\t" + "ldr r6, [%[b], #288]\n\t" + "ldr r7, [%[b], #292]\n\t" + "ldr r8, [%[b], #296]\n\t" + "ldr r9, [%[b], #300]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #288]\n\t" + "str r3, [%[a], #292]\n\t" + "str r4, [%[a], #296]\n\t" + "str r5, [%[a], #300]\n\t" + "ldr r2, [%[a], #304]\n\t" + "ldr r3, [%[a], #308]\n\t" + "ldr r4, [%[a], #312]\n\t" + "ldr r5, [%[a], #316]\n\t" + "ldr r6, [%[b], #304]\n\t" + "ldr r7, [%[b], #308]\n\t" + "ldr r8, [%[b], #312]\n\t" + "ldr r9, [%[b], #316]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #304]\n\t" + "str r3, [%[a], #308]\n\t" + "str r4, [%[a], #312]\n\t" + "str r5, [%[a], #316]\n\t" + "ldr r2, [%[a], #320]\n\t" + "ldr r3, [%[a], #324]\n\t" + "ldr r4, [%[a], #328]\n\t" + "ldr r5, [%[a], #332]\n\t" + "ldr r6, [%[b], #320]\n\t" + "ldr r7, [%[b], #324]\n\t" + "ldr r8, [%[b], #328]\n\t" + "ldr r9, [%[b], #332]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #320]\n\t" + "str r3, [%[a], #324]\n\t" + "str r4, [%[a], #328]\n\t" + "str r5, [%[a], #332]\n\t" + "ldr r2, [%[a], #336]\n\t" + "ldr r3, [%[a], #340]\n\t" + "ldr r4, [%[a], #344]\n\t" + "ldr r5, [%[a], #348]\n\t" + "ldr r6, [%[b], #336]\n\t" + "ldr r7, [%[b], #340]\n\t" + "ldr r8, [%[b], #344]\n\t" + "ldr r9, [%[b], #348]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #336]\n\t" + "str r3, [%[a], #340]\n\t" + "str r4, [%[a], #344]\n\t" + "str r5, [%[a], #348]\n\t" + "ldr r2, [%[a], #352]\n\t" + "ldr r3, [%[a], #356]\n\t" + "ldr r4, [%[a], #360]\n\t" + "ldr r5, [%[a], #364]\n\t" + "ldr r6, [%[b], #352]\n\t" + "ldr r7, [%[b], #356]\n\t" + "ldr r8, [%[b], #360]\n\t" + "ldr r9, [%[b], #364]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #352]\n\t" + "str r3, [%[a], #356]\n\t" + "str r4, [%[a], #360]\n\t" + "str r5, [%[a], #364]\n\t" + "ldr r2, [%[a], #368]\n\t" + "ldr r3, [%[a], #372]\n\t" + "ldr r4, [%[a], #376]\n\t" + "ldr r5, [%[a], #380]\n\t" + "ldr r6, [%[b], #368]\n\t" + "ldr r7, [%[b], #372]\n\t" + "ldr r8, [%[b], #376]\n\t" + "ldr r9, [%[b], #380]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #368]\n\t" + "str r3, [%[a], #372]\n\t" + "str r4, [%[a], #376]\n\t" + "str r5, [%[a], #380]\n\t" + "ldr r2, [%[a], #384]\n\t" + "ldr r3, [%[a], #388]\n\t" + "ldr r4, [%[a], #392]\n\t" + "ldr r5, [%[a], #396]\n\t" + "ldr r6, [%[b], #384]\n\t" + "ldr r7, [%[b], #388]\n\t" + "ldr r8, [%[b], #392]\n\t" + "ldr r9, [%[b], #396]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #384]\n\t" + "str r3, [%[a], #388]\n\t" + "str r4, [%[a], #392]\n\t" + "str r5, [%[a], #396]\n\t" + "ldr r2, [%[a], #400]\n\t" + "ldr r3, [%[a], #404]\n\t" + "ldr r4, [%[a], #408]\n\t" + "ldr r5, [%[a], #412]\n\t" + "ldr r6, [%[b], #400]\n\t" + "ldr r7, [%[b], #404]\n\t" + "ldr r8, [%[b], #408]\n\t" + "ldr r9, [%[b], #412]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #400]\n\t" + "str r3, [%[a], #404]\n\t" + "str r4, [%[a], #408]\n\t" + "str r5, [%[a], #412]\n\t" + "ldr r2, [%[a], #416]\n\t" + "ldr r3, [%[a], #420]\n\t" + "ldr r4, [%[a], #424]\n\t" + "ldr r5, [%[a], #428]\n\t" + "ldr r6, [%[b], #416]\n\t" + "ldr r7, [%[b], #420]\n\t" + "ldr r8, [%[b], #424]\n\t" + "ldr r9, [%[b], #428]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #416]\n\t" + "str r3, [%[a], #420]\n\t" + "str r4, [%[a], #424]\n\t" + "str r5, [%[a], #428]\n\t" + "ldr r2, [%[a], #432]\n\t" + "ldr r3, [%[a], #436]\n\t" + "ldr r4, [%[a], #440]\n\t" + "ldr r5, [%[a], #444]\n\t" + "ldr r6, [%[b], #432]\n\t" + "ldr r7, [%[b], #436]\n\t" + "ldr r8, [%[b], #440]\n\t" + "ldr r9, [%[b], #444]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #432]\n\t" + "str r3, [%[a], #436]\n\t" + "str r4, [%[a], #440]\n\t" + "str r5, [%[a], #444]\n\t" + "ldr r2, [%[a], #448]\n\t" + "ldr r3, [%[a], #452]\n\t" + "ldr r4, [%[a], #456]\n\t" + "ldr r5, [%[a], #460]\n\t" + "ldr r6, [%[b], #448]\n\t" + "ldr r7, [%[b], #452]\n\t" + "ldr r8, [%[b], #456]\n\t" + "ldr r9, [%[b], #460]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #448]\n\t" + "str r3, [%[a], #452]\n\t" + "str r4, [%[a], #456]\n\t" + "str r5, [%[a], #460]\n\t" + "ldr r2, [%[a], #464]\n\t" + "ldr r3, [%[a], #468]\n\t" + "ldr r4, [%[a], #472]\n\t" + "ldr r5, [%[a], #476]\n\t" + "ldr r6, [%[b], #464]\n\t" + "ldr r7, [%[b], #468]\n\t" + "ldr r8, [%[b], #472]\n\t" + "ldr r9, [%[b], #476]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #464]\n\t" + "str r3, [%[a], #468]\n\t" + "str r4, [%[a], #472]\n\t" + "str r5, [%[a], #476]\n\t" + "ldr r2, [%[a], #480]\n\t" + "ldr r3, [%[a], #484]\n\t" + "ldr r4, [%[a], #488]\n\t" + "ldr r5, [%[a], #492]\n\t" + "ldr r6, [%[b], #480]\n\t" + "ldr r7, [%[b], #484]\n\t" + "ldr r8, [%[b], #488]\n\t" + "ldr r9, [%[b], #492]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #480]\n\t" + "str r3, [%[a], #484]\n\t" + "str r4, [%[a], #488]\n\t" + "str r5, [%[a], #492]\n\t" + "ldr r2, [%[a], #496]\n\t" + "ldr r3, [%[a], #500]\n\t" + "ldr r4, [%[a], #504]\n\t" + "ldr r5, [%[a], #508]\n\t" + "ldr r6, [%[b], #496]\n\t" + "ldr r7, [%[b], #500]\n\t" + "ldr r8, [%[b], #504]\n\t" + "ldr r9, [%[b], #508]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #496]\n\t" + "str r3, [%[a], #500]\n\t" + "str r4, [%[a], #504]\n\t" + "str r5, [%[a], #508]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "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_4096_add_128(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "ldr r8, [%[b], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "ldr r10, [%[b], #104]\n\t" + "ldr r14, [%[b], #108]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "ldr r8, [%[b], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "ldr r10, [%[b], #120]\n\t" + "ldr r14, [%[b], #124]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[a], #132]\n\t" + "ldr r6, [%[a], #136]\n\t" + "ldr r7, [%[a], #140]\n\t" + "ldr r8, [%[b], #128]\n\t" + "ldr r9, [%[b], #132]\n\t" + "ldr r10, [%[b], #136]\n\t" + "ldr r14, [%[b], #140]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #128]\n\t" + "str r5, [%[r], #132]\n\t" + "str r6, [%[r], #136]\n\t" + "str r7, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[a], #148]\n\t" + "ldr r6, [%[a], #152]\n\t" + "ldr r7, [%[a], #156]\n\t" + "ldr r8, [%[b], #144]\n\t" + "ldr r9, [%[b], #148]\n\t" + "ldr r10, [%[b], #152]\n\t" + "ldr r14, [%[b], #156]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #144]\n\t" + "str r5, [%[r], #148]\n\t" + "str r6, [%[r], #152]\n\t" + "str r7, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[a], #164]\n\t" + "ldr r6, [%[a], #168]\n\t" + "ldr r7, [%[a], #172]\n\t" + "ldr r8, [%[b], #160]\n\t" + "ldr r9, [%[b], #164]\n\t" + "ldr r10, [%[b], #168]\n\t" + "ldr r14, [%[b], #172]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #160]\n\t" + "str r5, [%[r], #164]\n\t" + "str r6, [%[r], #168]\n\t" + "str r7, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[a], #180]\n\t" + "ldr r6, [%[a], #184]\n\t" + "ldr r7, [%[a], #188]\n\t" + "ldr r8, [%[b], #176]\n\t" + "ldr r9, [%[b], #180]\n\t" + "ldr r10, [%[b], #184]\n\t" + "ldr r14, [%[b], #188]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #176]\n\t" + "str r5, [%[r], #180]\n\t" + "str r6, [%[r], #184]\n\t" + "str r7, [%[r], #188]\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r5, [%[a], #196]\n\t" + "ldr r6, [%[a], #200]\n\t" + "ldr r7, [%[a], #204]\n\t" + "ldr r8, [%[b], #192]\n\t" + "ldr r9, [%[b], #196]\n\t" + "ldr r10, [%[b], #200]\n\t" + "ldr r14, [%[b], #204]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #192]\n\t" + "str r5, [%[r], #196]\n\t" + "str r6, [%[r], #200]\n\t" + "str r7, [%[r], #204]\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r5, [%[a], #212]\n\t" + "ldr r6, [%[a], #216]\n\t" + "ldr r7, [%[a], #220]\n\t" + "ldr r8, [%[b], #208]\n\t" + "ldr r9, [%[b], #212]\n\t" + "ldr r10, [%[b], #216]\n\t" + "ldr r14, [%[b], #220]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #208]\n\t" + "str r5, [%[r], #212]\n\t" + "str r6, [%[r], #216]\n\t" + "str r7, [%[r], #220]\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r5, [%[a], #228]\n\t" + "ldr r6, [%[a], #232]\n\t" + "ldr r7, [%[a], #236]\n\t" + "ldr r8, [%[b], #224]\n\t" + "ldr r9, [%[b], #228]\n\t" + "ldr r10, [%[b], #232]\n\t" + "ldr r14, [%[b], #236]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #224]\n\t" + "str r5, [%[r], #228]\n\t" + "str r6, [%[r], #232]\n\t" + "str r7, [%[r], #236]\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r5, [%[a], #244]\n\t" + "ldr r6, [%[a], #248]\n\t" + "ldr r7, [%[a], #252]\n\t" + "ldr r8, [%[b], #240]\n\t" + "ldr r9, [%[b], #244]\n\t" + "ldr r10, [%[b], #248]\n\t" + "ldr r14, [%[b], #252]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #240]\n\t" + "str r5, [%[r], #244]\n\t" + "str r6, [%[r], #248]\n\t" + "str r7, [%[r], #252]\n\t" + "ldr r4, [%[a], #256]\n\t" + "ldr r5, [%[a], #260]\n\t" + "ldr r6, [%[a], #264]\n\t" + "ldr r7, [%[a], #268]\n\t" + "ldr r8, [%[b], #256]\n\t" + "ldr r9, [%[b], #260]\n\t" + "ldr r10, [%[b], #264]\n\t" + "ldr r14, [%[b], #268]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #256]\n\t" + "str r5, [%[r], #260]\n\t" + "str r6, [%[r], #264]\n\t" + "str r7, [%[r], #268]\n\t" + "ldr r4, [%[a], #272]\n\t" + "ldr r5, [%[a], #276]\n\t" + "ldr r6, [%[a], #280]\n\t" + "ldr r7, [%[a], #284]\n\t" + "ldr r8, [%[b], #272]\n\t" + "ldr r9, [%[b], #276]\n\t" + "ldr r10, [%[b], #280]\n\t" + "ldr r14, [%[b], #284]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #272]\n\t" + "str r5, [%[r], #276]\n\t" + "str r6, [%[r], #280]\n\t" + "str r7, [%[r], #284]\n\t" + "ldr r4, [%[a], #288]\n\t" + "ldr r5, [%[a], #292]\n\t" + "ldr r6, [%[a], #296]\n\t" + "ldr r7, [%[a], #300]\n\t" + "ldr r8, [%[b], #288]\n\t" + "ldr r9, [%[b], #292]\n\t" + "ldr r10, [%[b], #296]\n\t" + "ldr r14, [%[b], #300]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #288]\n\t" + "str r5, [%[r], #292]\n\t" + "str r6, [%[r], #296]\n\t" + "str r7, [%[r], #300]\n\t" + "ldr r4, [%[a], #304]\n\t" + "ldr r5, [%[a], #308]\n\t" + "ldr r6, [%[a], #312]\n\t" + "ldr r7, [%[a], #316]\n\t" + "ldr r8, [%[b], #304]\n\t" + "ldr r9, [%[b], #308]\n\t" + "ldr r10, [%[b], #312]\n\t" + "ldr r14, [%[b], #316]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #304]\n\t" + "str r5, [%[r], #308]\n\t" + "str r6, [%[r], #312]\n\t" + "str r7, [%[r], #316]\n\t" + "ldr r4, [%[a], #320]\n\t" + "ldr r5, [%[a], #324]\n\t" + "ldr r6, [%[a], #328]\n\t" + "ldr r7, [%[a], #332]\n\t" + "ldr r8, [%[b], #320]\n\t" + "ldr r9, [%[b], #324]\n\t" + "ldr r10, [%[b], #328]\n\t" + "ldr r14, [%[b], #332]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #320]\n\t" + "str r5, [%[r], #324]\n\t" + "str r6, [%[r], #328]\n\t" + "str r7, [%[r], #332]\n\t" + "ldr r4, [%[a], #336]\n\t" + "ldr r5, [%[a], #340]\n\t" + "ldr r6, [%[a], #344]\n\t" + "ldr r7, [%[a], #348]\n\t" + "ldr r8, [%[b], #336]\n\t" + "ldr r9, [%[b], #340]\n\t" + "ldr r10, [%[b], #344]\n\t" + "ldr r14, [%[b], #348]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #336]\n\t" + "str r5, [%[r], #340]\n\t" + "str r6, [%[r], #344]\n\t" + "str r7, [%[r], #348]\n\t" + "ldr r4, [%[a], #352]\n\t" + "ldr r5, [%[a], #356]\n\t" + "ldr r6, [%[a], #360]\n\t" + "ldr r7, [%[a], #364]\n\t" + "ldr r8, [%[b], #352]\n\t" + "ldr r9, [%[b], #356]\n\t" + "ldr r10, [%[b], #360]\n\t" + "ldr r14, [%[b], #364]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #352]\n\t" + "str r5, [%[r], #356]\n\t" + "str r6, [%[r], #360]\n\t" + "str r7, [%[r], #364]\n\t" + "ldr r4, [%[a], #368]\n\t" + "ldr r5, [%[a], #372]\n\t" + "ldr r6, [%[a], #376]\n\t" + "ldr r7, [%[a], #380]\n\t" + "ldr r8, [%[b], #368]\n\t" + "ldr r9, [%[b], #372]\n\t" + "ldr r10, [%[b], #376]\n\t" + "ldr r14, [%[b], #380]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #368]\n\t" + "str r5, [%[r], #372]\n\t" + "str r6, [%[r], #376]\n\t" + "str r7, [%[r], #380]\n\t" + "ldr r4, [%[a], #384]\n\t" + "ldr r5, [%[a], #388]\n\t" + "ldr r6, [%[a], #392]\n\t" + "ldr r7, [%[a], #396]\n\t" + "ldr r8, [%[b], #384]\n\t" + "ldr r9, [%[b], #388]\n\t" + "ldr r10, [%[b], #392]\n\t" + "ldr r14, [%[b], #396]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #384]\n\t" + "str r5, [%[r], #388]\n\t" + "str r6, [%[r], #392]\n\t" + "str r7, [%[r], #396]\n\t" + "ldr r4, [%[a], #400]\n\t" + "ldr r5, [%[a], #404]\n\t" + "ldr r6, [%[a], #408]\n\t" + "ldr r7, [%[a], #412]\n\t" + "ldr r8, [%[b], #400]\n\t" + "ldr r9, [%[b], #404]\n\t" + "ldr r10, [%[b], #408]\n\t" + "ldr r14, [%[b], #412]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #400]\n\t" + "str r5, [%[r], #404]\n\t" + "str r6, [%[r], #408]\n\t" + "str r7, [%[r], #412]\n\t" + "ldr r4, [%[a], #416]\n\t" + "ldr r5, [%[a], #420]\n\t" + "ldr r6, [%[a], #424]\n\t" + "ldr r7, [%[a], #428]\n\t" + "ldr r8, [%[b], #416]\n\t" + "ldr r9, [%[b], #420]\n\t" + "ldr r10, [%[b], #424]\n\t" + "ldr r14, [%[b], #428]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #416]\n\t" + "str r5, [%[r], #420]\n\t" + "str r6, [%[r], #424]\n\t" + "str r7, [%[r], #428]\n\t" + "ldr r4, [%[a], #432]\n\t" + "ldr r5, [%[a], #436]\n\t" + "ldr r6, [%[a], #440]\n\t" + "ldr r7, [%[a], #444]\n\t" + "ldr r8, [%[b], #432]\n\t" + "ldr r9, [%[b], #436]\n\t" + "ldr r10, [%[b], #440]\n\t" + "ldr r14, [%[b], #444]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #432]\n\t" + "str r5, [%[r], #436]\n\t" + "str r6, [%[r], #440]\n\t" + "str r7, [%[r], #444]\n\t" + "ldr r4, [%[a], #448]\n\t" + "ldr r5, [%[a], #452]\n\t" + "ldr r6, [%[a], #456]\n\t" + "ldr r7, [%[a], #460]\n\t" + "ldr r8, [%[b], #448]\n\t" + "ldr r9, [%[b], #452]\n\t" + "ldr r10, [%[b], #456]\n\t" + "ldr r14, [%[b], #460]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #448]\n\t" + "str r5, [%[r], #452]\n\t" + "str r6, [%[r], #456]\n\t" + "str r7, [%[r], #460]\n\t" + "ldr r4, [%[a], #464]\n\t" + "ldr r5, [%[a], #468]\n\t" + "ldr r6, [%[a], #472]\n\t" + "ldr r7, [%[a], #476]\n\t" + "ldr r8, [%[b], #464]\n\t" + "ldr r9, [%[b], #468]\n\t" + "ldr r10, [%[b], #472]\n\t" + "ldr r14, [%[b], #476]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #464]\n\t" + "str r5, [%[r], #468]\n\t" + "str r6, [%[r], #472]\n\t" + "str r7, [%[r], #476]\n\t" + "ldr r4, [%[a], #480]\n\t" + "ldr r5, [%[a], #484]\n\t" + "ldr r6, [%[a], #488]\n\t" + "ldr r7, [%[a], #492]\n\t" + "ldr r8, [%[b], #480]\n\t" + "ldr r9, [%[b], #484]\n\t" + "ldr r10, [%[b], #488]\n\t" + "ldr r14, [%[b], #492]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #480]\n\t" + "str r5, [%[r], #484]\n\t" + "str r6, [%[r], #488]\n\t" + "str r7, [%[r], #492]\n\t" + "ldr r4, [%[a], #496]\n\t" + "ldr r5, [%[a], #500]\n\t" + "ldr r6, [%[a], #504]\n\t" + "ldr r7, [%[a], #508]\n\t" + "ldr r8, [%[b], #496]\n\t" + "ldr r9, [%[b], #500]\n\t" + "ldr r10, [%[b], #504]\n\t" + "ldr r14, [%[b], #508]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #496]\n\t" + "str r5, [%[r], #500]\n\t" + "str r6, [%[r], #504]\n\t" + "str r7, [%[r], #508]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +/* 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_4096_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #256\n\t" + "mov r10, #0\n\t" + "# A[0] * B[0]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r3, r4, r8, r9\n\t" + "mov r5, #0\n\t" + "str r3, [sp]\n\t" + "# A[0] * B[1]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[0]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #4]\n\t" + "# A[0] * B[2]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #8]\n\t" + "# A[0] * B[3]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[2]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[1]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #12]\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[3]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #16]\n\t" + "# A[0] * B[5]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[4]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[3]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[2]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[1]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #20]\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #24]\n\t" + "# A[0] * B[7]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[6]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[5]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[4]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[3]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[2]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[1]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #28]\n\t" + "# A[0] * B[8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[2]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[1]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[0]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #32]\n\t" + "# A[0] * B[9]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[7]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[6]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[5]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[3]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[2]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[1]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[0]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #36]\n\t" + "# A[0] * B[10]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[9]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[8]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[6]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[3]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[2]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[1]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[0]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #40]\n\t" + "# A[0] * B[11]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[10]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[9]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[8]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[7]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[6]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[5]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[3]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[2]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[1]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[0]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #44]\n\t" + "# A[0] * B[12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[11]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[10]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[9]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[8]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[7]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[5]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[4]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[3]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[2]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[1]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[0]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #48]\n\t" + "# A[0] * B[13]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[11]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[10]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[9]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[8]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[7]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[6]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[5]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[4]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[3]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[2]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[1]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[0]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #52]\n\t" + "# A[0] * B[14]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[13]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[11]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[10]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[9]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[8]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[7]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[6]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[5]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[4]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[3]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[2]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[1]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[0]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #56]\n\t" + "# A[0] * B[15]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[14]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[13]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[12]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[11]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[10]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[9]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[8]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[7]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[6]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[5]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[4]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[3]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[2]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[1]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[0]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #60]\n\t" + "# A[0] * B[16]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[15]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[14]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[13]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[12]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[11]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[10]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[9]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[8]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[7]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[6]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[5]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[4]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[3]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[2]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[1]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[0]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #64]\n\t" + "# A[0] * B[17]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[16]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[15]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[14]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[13]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[12]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[11]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[10]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[9]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[8]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[7]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[6]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[5]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[4]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[3]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[2]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[1]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[0]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #68]\n\t" + "# A[0] * B[18]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[17]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[16]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[15]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[14]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[13]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[12]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[11]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[10]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[9]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[8]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[7]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[6]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[5]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[4]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[3]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[2]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[1]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[0]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #72]\n\t" + "# A[0] * B[19]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[18]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[17]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[16]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[15]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[14]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[13]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[12]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[11]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[10]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[9]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[8]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[7]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[6]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[5]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[4]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[3]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[2]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[1]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[0]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #76]\n\t" + "# A[0] * B[20]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[19]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[18]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[17]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[16]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[15]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[14]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[13]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[12]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[11]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[10]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[9]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[8]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[7]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[6]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[5]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[4]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[3]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[2]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[1]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[0]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #80]\n\t" + "# A[0] * B[21]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[20]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[19]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[18]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[17]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[16]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[15]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[14]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[13]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[12]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[11]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[10]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[9]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[8]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[7]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[6]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[5]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[4]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[3]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[2]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[1]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[0]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #84]\n\t" + "# A[0] * B[22]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[21]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[20]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[19]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[18]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[17]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[16]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[15]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[14]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[13]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[12]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[11]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[10]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[9]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[8]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[7]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[6]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[5]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[4]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[3]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[2]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[1]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[0]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #88]\n\t" + "# A[0] * B[23]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[22]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[21]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[20]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[19]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[18]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[17]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[16]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[15]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[14]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[13]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[12]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[11]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[10]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[9]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[8]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[7]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[6]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[5]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[4]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[3]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[2]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[1]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[0]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #92]\n\t" + "# A[0] * B[24]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[23]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[22]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[21]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[20]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[19]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[18]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[17]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[16]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[15]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[14]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[13]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[12]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[11]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[10]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[9]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[8]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[7]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[6]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[5]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[4]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[3]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[2]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[1]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[0]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #96]\n\t" + "# A[0] * B[25]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[24]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[23]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[22]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[21]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[20]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[19]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[18]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[17]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[16]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[15]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[14]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[13]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[12]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[11]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[10]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[9]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[8]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[7]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[6]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[5]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[4]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[3]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[2]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[1]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[0]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #100]\n\t" + "# A[0] * B[26]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[25]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[24]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[23]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[22]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[21]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[20]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[19]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[18]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[17]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[16]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[15]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[14]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[13]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[12]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[11]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[10]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[9]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[8]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[7]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[6]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[5]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[4]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[3]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[2]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[1]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[0]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #104]\n\t" + "# A[0] * B[27]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[26]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[25]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[24]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[23]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[22]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[21]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[20]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[19]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[18]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[17]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[16]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[15]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[14]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[13]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[12]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[11]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[10]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[9]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[8]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[7]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[6]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[5]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[4]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[3]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[2]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[1]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[0]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #108]\n\t" + "# A[0] * B[28]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[27]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[26]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[25]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[24]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[23]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[22]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[21]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[20]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[19]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[18]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[17]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[16]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[15]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[14]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[13]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[12]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[11]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[10]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[9]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[8]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[7]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[6]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[5]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[4]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[3]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[2]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[1]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[0]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #112]\n\t" + "# A[0] * B[29]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[28]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[27]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[26]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[25]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[24]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[23]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[22]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[21]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[20]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[19]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[18]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[17]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[16]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[15]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[14]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[13]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[12]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[11]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[10]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[9]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[8]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[7]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[6]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[5]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[4]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[3]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[2]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[1]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[0]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #116]\n\t" + "# A[0] * B[30]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[29]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[28]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[27]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[26]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[25]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[24]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[23]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[22]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[21]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[20]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[19]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[18]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[17]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[16]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[15]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[14]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[13]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[12]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[11]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[10]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[9]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[8]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[7]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[6]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[5]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[4]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[3]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[2]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[1]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[0]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #120]\n\t" + "# A[0] * B[31]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[30]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[29]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[28]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[27]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[26]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[25]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[24]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[23]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[22]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[21]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[20]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[19]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[18]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[17]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[16]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[15]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[14]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[13]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[12]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[11]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[10]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[9]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[8]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[7]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[6]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[5]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[4]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[3]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[2]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[1]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[0]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #124]\n\t" + "# A[0] * B[32]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[31]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[30]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[29]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[28]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[27]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[26]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[25]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[24]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[23]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[22]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[21]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[20]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[19]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[18]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[17]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[16]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[15]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[14]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[13]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[12]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[11]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[10]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[9]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[8]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[7]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[6]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[5]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[4]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[3]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[2]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[1]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[0]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #128]\n\t" + "# A[0] * B[33]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[32]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[31]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[30]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[29]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[28]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[27]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[26]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[25]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[24]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[23]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[22]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[21]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[20]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[19]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[18]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[17]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[16]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[15]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[14]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[13]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[12]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[11]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[10]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[9]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[8]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[7]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[6]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[5]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[4]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[3]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[2]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[1]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[0]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #132]\n\t" + "# A[0] * B[34]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[33]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[32]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[31]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[30]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[29]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[28]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[27]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[26]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[25]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[24]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[23]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[22]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[21]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[20]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[19]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[18]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[17]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[16]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[15]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[14]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[13]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[12]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[11]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[10]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[9]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[8]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[7]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[6]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[5]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[4]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[3]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[2]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[1]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[0]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #136]\n\t" + "# A[0] * B[35]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[34]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[33]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[32]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[31]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[30]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[29]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[28]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[27]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[26]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[25]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[24]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[23]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[22]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[21]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[20]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[19]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[18]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[17]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[16]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[15]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[14]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[13]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[12]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[11]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[10]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[9]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[8]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[7]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[6]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[5]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[4]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[3]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[2]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[1]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[0]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #140]\n\t" + "# A[0] * B[36]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[35]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[34]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[33]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[32]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[31]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[30]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[29]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[28]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[27]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[26]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[25]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[24]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[23]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[22]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[21]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[20]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[19]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[18]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[17]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[16]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[15]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[14]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[13]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[12]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[11]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[10]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[9]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[8]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[7]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[6]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[5]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[4]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[3]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[2]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[1]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[0]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #144]\n\t" + "# A[0] * B[37]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[36]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[35]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[34]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[33]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[32]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[31]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[30]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[29]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[28]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[27]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[26]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[25]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[24]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[23]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[22]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[21]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[20]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[19]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[18]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[17]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[16]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[15]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[14]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[13]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[12]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[11]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[10]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[9]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[8]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[7]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[6]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[5]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[4]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[3]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[2]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[1]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[0]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #148]\n\t" + "# A[0] * B[38]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[37]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[36]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[35]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[34]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[33]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[32]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[31]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[30]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[29]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[28]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[27]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[26]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[25]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[24]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[23]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[22]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[21]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[20]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[19]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[18]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[17]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[16]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[15]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[14]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[13]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[12]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[11]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[10]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[9]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[8]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[7]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[6]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[5]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[4]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[3]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[2]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[1]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[0]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #152]\n\t" + "# A[0] * B[39]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[38]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[37]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[36]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[35]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[34]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[33]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[32]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[31]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[30]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[29]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[28]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[27]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[26]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[25]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[24]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[23]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[22]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[21]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[20]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[19]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[18]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[17]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[16]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[15]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[14]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[13]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[12]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[11]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[10]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[9]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[8]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[7]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[6]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[5]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[4]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[3]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[2]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[1]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[0]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #156]\n\t" + "# A[0] * B[40]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[39]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[38]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[37]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[36]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[35]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[34]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[33]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[32]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[31]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[30]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[29]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[28]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[27]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[26]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[25]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[24]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[23]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[22]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[21]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[20]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[19]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[18]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[17]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[16]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[15]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[14]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[13]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[12]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[11]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[10]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[9]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[8]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[7]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[6]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[5]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[4]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[3]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[2]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[1]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[0]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #160]\n\t" + "# A[0] * B[41]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[40]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[39]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[38]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[37]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[36]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[35]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[34]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[33]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[32]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[31]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[30]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[29]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[28]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[27]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[26]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[25]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[24]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[23]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[22]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[21]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[20]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[19]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[18]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[17]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[16]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[15]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[14]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[13]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[12]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[11]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[10]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[9]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[8]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[7]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[6]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[5]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[4]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[3]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[2]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[1]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[0]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #164]\n\t" + "# A[0] * B[42]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[41]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[40]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[39]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[38]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[37]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[36]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[35]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[34]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[33]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[32]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[31]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[30]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[29]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[28]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[27]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[26]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[25]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[24]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[23]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[22]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[21]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[20]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[19]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[18]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[17]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[16]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[15]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[14]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[13]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[12]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[11]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[10]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[9]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[8]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[7]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[6]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[5]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[4]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[3]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[2]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[1]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[0]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #168]\n\t" + "# A[0] * B[43]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[42]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[41]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[40]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[39]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[38]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[37]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[36]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[35]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[34]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[33]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[32]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[31]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[30]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[29]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[28]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[27]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[26]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[25]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[24]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[23]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[22]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[21]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[20]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[19]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[18]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[17]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[16]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[15]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[14]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[13]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[12]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[11]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[10]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[9]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[8]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[7]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[6]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[5]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[4]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[3]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[2]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[1]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[0]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #172]\n\t" + "# A[0] * B[44]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[43]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[42]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[41]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[40]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[39]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[38]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[37]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[36]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[35]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[34]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[33]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[32]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[31]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[30]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[29]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[28]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[27]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[26]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[25]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[24]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[23]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[22]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[21]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[20]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[19]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[18]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[17]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[16]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[15]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[14]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[13]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[12]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[11]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[10]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[9]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[8]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[7]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[6]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[5]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[4]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[3]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[2]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[1]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[0]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #176]\n\t" + "# A[0] * B[45]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[44]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[43]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[42]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[41]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[40]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[39]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[38]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[37]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[36]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[35]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[34]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[33]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[32]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[31]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[30]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[29]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[28]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[27]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[26]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[25]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[24]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[23]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[22]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[21]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[20]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[19]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[18]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[17]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[16]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[15]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[14]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[13]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[12]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[11]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[10]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[9]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[8]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[7]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[6]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[5]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[4]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[3]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[2]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[1]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[0]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #180]\n\t" + "# A[0] * B[46]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[45]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[44]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[43]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[42]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[41]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[40]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[39]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[38]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[37]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[36]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[35]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[34]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[33]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[32]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[31]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[30]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[29]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[28]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[27]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[26]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[25]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[24]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[23]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[22]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[21]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[20]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[19]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[18]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[17]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[16]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[15]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[14]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[13]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[12]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[11]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[10]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[9]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[8]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[7]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[6]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[5]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[4]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[3]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[2]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[1]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[0]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #184]\n\t" + "# A[0] * B[47]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[46]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[45]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[44]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[43]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[42]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[41]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[40]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[39]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[38]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[37]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[36]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[35]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[34]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[33]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[32]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[31]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[30]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[29]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[28]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[27]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[26]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[25]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[24]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[23]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[22]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[21]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[20]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[19]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[18]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[17]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[16]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[15]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[14]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[13]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[12]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[11]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[10]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[9]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[8]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[7]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[6]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[5]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[4]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[3]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[2]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[1]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[0]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #188]\n\t" + "# A[0] * B[48]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[47]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[46]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[45]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[44]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[43]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[42]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[41]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[40]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[39]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[38]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[37]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[36]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[35]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[34]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[33]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[32]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[31]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[30]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[29]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[28]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[27]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[26]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[25]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[24]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[23]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[22]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[21]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[20]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[19]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[18]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[17]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[16]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[15]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[14]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[13]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[12]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[11]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[10]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[9]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[8]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[7]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[6]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[5]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[4]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[3]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[2]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[1]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[0]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #192]\n\t" + "# A[0] * B[49]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[48]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[47]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[46]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[45]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[44]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[43]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[42]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[41]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[40]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[39]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[38]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[37]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[36]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[35]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[34]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[33]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[32]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[31]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[30]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[29]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[28]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[27]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[26]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[25]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[24]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[23]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[22]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[21]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[20]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[19]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[18]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[17]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[16]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[15]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[14]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[13]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[12]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[11]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[10]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[9]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[8]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[7]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[6]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[5]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[4]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[3]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[2]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[1]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[0]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #196]\n\t" + "# A[0] * B[50]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[49]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[48]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[47]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[46]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[45]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[44]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[43]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[42]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[41]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[40]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[39]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[38]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[37]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[36]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[35]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[34]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[33]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[32]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[31]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[30]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[29]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[28]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[27]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[26]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[25]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[24]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[23]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[22]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[21]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[20]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[19]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[18]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[17]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[16]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[15]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[14]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[13]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[12]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[11]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[10]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[9]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[8]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[7]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[6]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[5]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[4]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[3]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[2]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[1]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[0]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #200]\n\t" + "# A[0] * B[51]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[50]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[49]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[48]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[47]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[46]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[45]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[44]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[43]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[42]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[41]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[40]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[39]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[38]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[37]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[36]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[35]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[34]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[33]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[32]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[31]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[30]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[29]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[28]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[27]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[26]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[25]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[24]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[23]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[22]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[21]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[20]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[19]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[18]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[17]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[16]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[15]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[14]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[13]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[12]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[11]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[10]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[9]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[8]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[7]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[6]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[5]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[4]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[3]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[2]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[1]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[0]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #204]\n\t" + "# A[0] * B[52]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[51]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[50]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[49]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[48]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[47]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[46]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[45]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[44]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[43]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[42]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[41]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[40]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[39]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[38]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[37]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[36]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[35]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[34]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[33]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[32]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[31]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[30]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[29]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[28]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[27]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[26]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[25]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[24]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[23]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[22]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[21]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[20]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[19]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[18]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[17]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[16]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[15]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[14]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[13]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[12]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[11]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[10]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[9]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[8]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[7]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[6]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[5]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[4]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[3]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[2]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[1]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[0]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #208]\n\t" + "# A[0] * B[53]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[52]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[51]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[50]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[49]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[48]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[47]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[46]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[45]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[44]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[43]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[42]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[41]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[40]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[39]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[38]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[37]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[36]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[35]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[34]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[33]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[32]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[31]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[30]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[29]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[28]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[27]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[26]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[25]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[24]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[23]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[22]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[21]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[20]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[19]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[18]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[17]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[16]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[15]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[14]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[13]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[12]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[11]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[10]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[9]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[8]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[7]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[6]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[5]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[4]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[3]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[2]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[1]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[0]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #212]\n\t" + "# A[0] * B[54]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[53]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[52]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[51]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[50]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[49]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[48]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[47]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[46]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[45]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[44]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[43]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[42]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[41]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[40]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[39]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[38]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[37]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[36]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[35]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[34]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[33]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[32]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[31]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[30]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[29]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[28]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[27]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[26]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[25]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[24]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[23]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[22]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[21]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[20]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[19]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[18]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[17]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[16]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[15]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[14]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[13]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[12]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[11]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[10]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[9]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[8]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[7]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[6]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[5]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[4]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[3]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[2]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[1]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[0]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #216]\n\t" + "# A[0] * B[55]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[54]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[53]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[52]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[51]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[50]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[49]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[48]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[47]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[46]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[45]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[44]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[43]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[42]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[41]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[40]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[39]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[38]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[37]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[36]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[35]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[34]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[33]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[32]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[31]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[30]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[29]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[28]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[27]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[26]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[25]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[24]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[23]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[22]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[21]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[20]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[19]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[18]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[17]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[16]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[15]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[14]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[13]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[12]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[11]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[10]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[9]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[8]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[7]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[6]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[5]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[4]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[3]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[2]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[1]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[0]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #220]\n\t" + "# A[0] * B[56]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[55]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[54]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[53]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[52]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[51]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[50]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[49]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[48]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[47]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[46]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[45]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[44]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[43]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[42]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[41]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[40]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[39]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[38]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[37]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[36]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[35]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[34]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[33]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[32]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[31]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[30]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[29]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[28]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[27]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[26]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[25]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[24]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[23]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[22]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[21]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[20]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[19]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[18]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[17]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[16]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[15]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[14]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[13]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[12]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[11]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[10]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[9]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[8]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[7]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[6]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[5]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[4]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[3]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[2]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[1]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[0]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #224]\n\t" + "# A[0] * B[57]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[56]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[55]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[54]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[53]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[52]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[51]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[50]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[49]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[48]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[47]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[46]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[45]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[44]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[43]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[42]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[41]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[40]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[39]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[38]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[37]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[36]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[35]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[34]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[33]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[32]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[31]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[30]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[29]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[28]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[27]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[26]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[25]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[24]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[23]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[22]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[21]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[20]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[19]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[18]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[17]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[16]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[15]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[14]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[13]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[12]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[11]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[10]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[9]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[8]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[7]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[6]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[5]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[4]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[3]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[2]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[1]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[0]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #228]\n\t" + "# A[0] * B[58]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[57]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[56]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[55]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[54]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[53]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[52]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[51]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[50]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[49]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[48]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[47]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[46]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[45]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[44]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[43]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[42]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[41]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[40]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[39]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[38]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[37]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[36]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[35]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[34]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[33]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[32]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[31]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[30]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[29]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[28]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[27]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[26]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[25]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[24]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[23]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[22]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[21]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[20]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[19]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[18]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[17]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[16]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[15]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[14]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[13]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[12]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[11]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[10]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[9]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[8]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[7]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[6]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[5]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[4]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[3]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[2]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[1]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[0]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #232]\n\t" + "# A[0] * B[59]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[58]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[57]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[56]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[55]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[54]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[53]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[52]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[51]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[50]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[49]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[48]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[47]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[46]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[45]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[44]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[43]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[42]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[41]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[40]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[39]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[38]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[37]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[36]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[35]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[34]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[33]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[32]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[31]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[30]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[29]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[28]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[27]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[26]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[25]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[24]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[23]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[22]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[21]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[20]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[19]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[18]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[17]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[16]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[15]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[14]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[13]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[12]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[11]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[10]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[9]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[8]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[7]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[6]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[5]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[4]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[3]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[2]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[1]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[0]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #236]\n\t" + "# A[0] * B[60]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[59]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[58]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[57]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[56]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[55]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[54]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[53]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[52]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[51]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[50]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[49]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[48]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[47]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[46]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[45]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[44]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[43]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[42]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[41]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[40]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[39]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[38]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[37]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[36]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[35]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[34]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[33]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[32]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[31]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[30]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[29]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[28]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[27]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[26]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[25]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[24]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[23]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[22]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[21]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[20]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[19]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[18]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[17]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[16]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[15]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[14]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[13]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[12]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[11]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[10]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[9]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[8]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[7]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[6]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[5]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[4]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[3]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[2]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[1]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[0]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #240]\n\t" + "# A[0] * B[61]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[60]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[59]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[58]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[57]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[56]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[55]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[54]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[53]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[52]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[51]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[50]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[49]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[48]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[47]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[46]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[45]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[44]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[43]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[42]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[41]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[40]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[39]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[38]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[37]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[36]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[35]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[34]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[33]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[32]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[31]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[30]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[29]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[28]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[27]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[26]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[25]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[24]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[23]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[22]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[21]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[20]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[19]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[18]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[17]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[16]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[15]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[14]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[13]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[12]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[11]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[10]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[9]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[8]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[7]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[6]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[5]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[4]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[3]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[2]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[1]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[0]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #244]\n\t" + "# A[0] * B[62]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[61]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[60]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[59]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[58]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[57]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[56]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[55]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[54]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[53]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[52]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[51]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[50]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[49]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[48]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[47]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[46]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[45]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[44]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[43]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[42]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[41]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[40]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[39]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[38]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[37]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[36]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[35]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[34]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[33]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[32]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[31]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[30]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[29]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[28]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[27]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[26]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[25]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[24]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[23]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[22]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[21]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[20]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[19]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[18]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[17]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[16]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[15]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[14]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[13]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[12]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[11]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[10]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[9]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[8]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[7]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[6]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[5]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[4]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[3]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[2]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[1]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[0]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #248]\n\t" + "# A[0] * B[63]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[62]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[61]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[60]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[59]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[58]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[57]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[56]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[55]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[54]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[53]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[52]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[51]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[50]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[49]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[48]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[47]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[46]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[45]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[44]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[43]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[42]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[41]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[40]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[39]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[38]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[37]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[36]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[35]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[34]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[33]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[32]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[31]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[30]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[29]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[28]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[27]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[26]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[25]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[24]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[23]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[22]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[21]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[20]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[19]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[18]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[17]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[16]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[15]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[14]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[13]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[12]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[11]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[10]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[9]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[8]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[7]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[6]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[5]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[4]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[3]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[2]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[1]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[0]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #252]\n\t" + "# A[1] * B[63]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[2] * B[62]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[61]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[60]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[59]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[58]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[57]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[56]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[55]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[54]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[53]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[52]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[51]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[50]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[49]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[48]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[47]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[46]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[45]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[44]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[43]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[42]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[41]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[40]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[39]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[38]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[37]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[36]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[35]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[34]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[33]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[32]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[31]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[30]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[29]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[28]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[27]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[26]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[25]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[24]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[23]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[22]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[21]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[20]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[19]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[18]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[17]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[16]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[15]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[14]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[13]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[12]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[11]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[10]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[9]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[8]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[7]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[6]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[5]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[4]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[3]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[2]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[1]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #256]\n\t" + "# A[2] * B[63]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[3] * B[62]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[61]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[60]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[59]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[58]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[57]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[56]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[55]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[54]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[53]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[52]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[51]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[50]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[49]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[48]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[47]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[46]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[45]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[44]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[43]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[42]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[41]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[40]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[39]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[38]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[37]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[36]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[35]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[34]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[33]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[32]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[31]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[30]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[29]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[28]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[27]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[26]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[25]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[24]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[23]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[22]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[21]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[20]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[19]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[18]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[17]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[16]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[15]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[14]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[13]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[12]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[11]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[10]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[9]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[8]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[7]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[6]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[5]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[4]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[3]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[2]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #260]\n\t" + "# A[3] * B[63]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[4] * B[62]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[61]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[60]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[59]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[58]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[57]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[56]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[55]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[54]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[53]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[52]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[51]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[50]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[49]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[48]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[47]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[46]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[45]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[44]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[43]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[42]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[41]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[40]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[39]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[38]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[37]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[36]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[35]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[34]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[33]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[32]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[31]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[30]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[29]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[28]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[27]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[26]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[25]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[24]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[23]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[22]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[21]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[20]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[19]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[18]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[17]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[16]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[15]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[14]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[13]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[12]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[11]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[10]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[9]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[8]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[7]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[6]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[5]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[4]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[3]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #264]\n\t" + "# A[4] * B[63]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[5] * B[62]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[61]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[60]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[59]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[58]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[57]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[56]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[55]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[54]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[53]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[52]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[51]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[50]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[49]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[48]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[47]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[46]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[45]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[44]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[43]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[42]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[41]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[40]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[39]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[38]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[37]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[36]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[35]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[34]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[33]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[32]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[31]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[30]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[29]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[28]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[27]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[26]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[25]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[24]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[23]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[22]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[21]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[20]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[19]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[18]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[17]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[16]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[15]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[14]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[13]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[12]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[11]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[10]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[9]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[8]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[7]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[6]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[5]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[4]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #268]\n\t" + "# A[5] * B[63]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[6] * B[62]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[61]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[60]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[59]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[58]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[57]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[56]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[55]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[54]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[53]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[52]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[51]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[50]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[49]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[48]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[47]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[46]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[45]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[44]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[43]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[42]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[41]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[40]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[39]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[38]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[37]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[36]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[35]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[34]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[33]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[32]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[31]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[30]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[29]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[28]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[27]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[26]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[25]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[24]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[23]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[22]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[21]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[20]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[19]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[18]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[17]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[16]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[15]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[14]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[13]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[12]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[11]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[10]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[9]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[8]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[7]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[6]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[5]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #272]\n\t" + "# A[6] * B[63]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[7] * B[62]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[61]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[60]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[59]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[58]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[57]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[56]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[55]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[54]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[53]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[52]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[51]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[50]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[49]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[48]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[47]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[46]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[45]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[44]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[43]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[42]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[41]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[40]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[39]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[38]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[37]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[36]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[35]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[34]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[33]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[32]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[31]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[30]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[29]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[28]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[27]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[26]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[25]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[24]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[23]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[22]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[21]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[20]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[19]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[18]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[17]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[16]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[15]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[14]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[13]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[12]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[11]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[10]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[9]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[8]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[7]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[6]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #276]\n\t" + "# A[7] * B[63]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[8] * B[62]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[61]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[60]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[59]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[58]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[57]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[56]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[55]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[54]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[53]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[52]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[51]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[50]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[49]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[48]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[47]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[46]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[45]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[44]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[43]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[42]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[41]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[40]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[39]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[38]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[37]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[36]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[35]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[34]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[33]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[32]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[31]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[30]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[29]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[28]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[27]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[26]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[25]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[24]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[23]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[22]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[21]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[20]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[19]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[18]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[17]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[16]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[15]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[14]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[13]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[12]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[11]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[10]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[9]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[8]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[7]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #280]\n\t" + "# A[8] * B[63]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[9] * B[62]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[61]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[60]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[12] * B[59]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[58]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[57]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[56]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[55]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[54]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[53]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[52]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[51]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[50]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[49]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[48]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[47]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[46]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[45]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[44]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[43]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[42]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[41]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[40]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[39]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[38]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[37]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[36]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[35]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[34]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[33]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[32]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[31]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[30]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[29]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[28]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[27]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[26]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[25]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[24]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[23]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[22]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[21]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[20]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[19]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[18]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[17]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[16]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[15]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[14]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[13]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[12]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[11]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[10]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[9]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[8]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #284]\n\t" + "# A[9] * B[63]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[10] * B[62]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[61]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[12] * B[60]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[13] * B[59]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[58]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[57]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[56]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[55]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[54]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[53]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[52]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[51]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[50]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[49]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[48]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[47]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[46]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[45]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[44]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[43]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[42]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[41]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[40]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[39]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[38]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[37]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[36]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[35]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[34]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[33]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[32]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[31]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[30]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[29]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[28]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[27]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[26]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[25]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[24]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[23]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[22]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[21]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[20]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[19]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[18]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[17]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[16]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[15]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[14]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[13]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[12]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[11]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[10]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[9]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #288]\n\t" + "# A[10] * B[63]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[11] * B[62]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[12] * B[61]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[13] * B[60]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[14] * B[59]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[58]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[57]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[56]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[55]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[54]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[53]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[52]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[51]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[50]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[49]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[48]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[47]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[46]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[45]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[44]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[43]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[42]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[41]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[40]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[39]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[38]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[37]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[36]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[35]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[34]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[33]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[32]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[31]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[30]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[29]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[28]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[27]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[26]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[25]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[24]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[23]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[22]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[21]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[20]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[19]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[18]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[17]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[16]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[15]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[14]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[13]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[12]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[11]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[10]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #292]\n\t" + "# A[11] * B[63]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[12] * B[62]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[13] * B[61]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[14] * B[60]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[15] * B[59]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[58]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[57]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[56]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[55]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[54]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[53]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[52]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[51]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[50]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[49]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[48]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[47]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[46]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[45]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[44]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[43]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[42]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[41]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[40]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[39]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[38]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[37]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[36]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[35]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[34]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[33]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[32]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[31]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[30]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[29]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[28]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[27]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[26]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[25]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[24]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[23]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[22]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[21]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[20]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[19]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[18]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[17]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[16]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[15]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[14]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[13]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[12]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[11]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #296]\n\t" + "# A[12] * B[63]\n\t" + "ldr r8, [%[a], #48]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[13] * B[62]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[14] * B[61]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[15] * B[60]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[16] * B[59]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[58]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[57]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[56]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[55]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[54]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[53]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[52]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[51]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[50]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[49]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[48]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[47]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[46]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[45]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[44]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[43]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[42]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[41]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[40]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[39]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[38]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[37]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[36]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[35]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[34]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[33]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[32]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[31]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[30]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[29]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[28]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[27]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[26]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[25]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[24]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[23]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[22]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[21]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[20]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[19]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[18]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[17]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[16]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[15]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[14]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[13]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[12]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #48]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #300]\n\t" + "# A[13] * B[63]\n\t" + "ldr r8, [%[a], #52]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[14] * B[62]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[15] * B[61]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[16] * B[60]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[17] * B[59]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[58]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[57]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[56]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[55]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[54]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[53]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[52]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[51]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[50]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[49]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[48]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[47]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[46]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[45]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[44]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[43]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[42]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[41]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[40]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[39]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[38]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[37]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[36]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[35]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[34]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[33]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[32]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[31]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[30]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[29]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[28]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[27]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[26]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[25]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[24]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[23]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[22]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[21]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[20]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[19]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[18]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[17]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[16]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[15]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[14]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[13]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #52]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #304]\n\t" + "# A[14] * B[63]\n\t" + "ldr r8, [%[a], #56]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[15] * B[62]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[16] * B[61]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[17] * B[60]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[18] * B[59]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[58]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[57]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[56]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[55]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[54]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[53]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[52]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[51]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[50]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[49]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[48]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[47]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[46]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[45]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[44]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[43]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[42]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[41]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[40]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[39]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[38]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[37]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[36]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[35]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[34]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[33]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[32]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[31]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[30]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[29]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[28]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[27]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[26]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[25]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[24]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[23]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[22]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[21]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[20]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[19]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[18]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[17]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[16]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[15]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[14]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #56]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #308]\n\t" + "# A[15] * B[63]\n\t" + "ldr r8, [%[a], #60]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[16] * B[62]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[17] * B[61]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[18] * B[60]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[19] * B[59]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[58]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[57]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[56]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[55]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[54]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[53]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[52]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[51]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[50]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[49]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[48]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[47]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[46]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[45]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[44]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[43]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[42]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[41]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[40]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[39]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[38]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[37]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[36]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[35]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[34]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[33]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[32]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[31]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[30]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[29]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[28]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[27]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[26]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[25]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[24]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[23]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[22]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[21]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[20]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[19]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[18]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[17]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[16]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[15]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #60]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #312]\n\t" + "# A[16] * B[63]\n\t" + "ldr r8, [%[a], #64]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[17] * B[62]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[18] * B[61]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[19] * B[60]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[20] * B[59]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[58]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[57]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[56]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[55]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[54]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[53]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[52]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[51]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[50]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[49]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[48]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[47]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[46]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[45]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[44]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[43]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[42]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[41]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[40]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[39]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[38]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[37]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[36]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[35]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[34]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[33]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[32]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[31]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[30]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[29]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[28]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[27]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[26]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[25]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[24]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[23]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[22]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[21]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[20]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[19]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[18]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[17]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[16]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #64]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #316]\n\t" + "# A[17] * B[63]\n\t" + "ldr r8, [%[a], #68]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[18] * B[62]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[19] * B[61]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[20] * B[60]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[21] * B[59]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[58]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[57]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[56]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[55]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[54]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[53]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[52]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[51]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[50]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[49]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[48]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[47]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[46]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[45]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[44]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[43]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[42]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[41]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[40]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[39]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[38]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[37]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[36]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[35]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[34]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[33]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[32]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[31]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[30]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[29]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[28]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[27]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[26]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[25]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[24]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[23]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[22]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[21]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[20]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[19]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[18]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[17]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #68]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #320]\n\t" + "# A[18] * B[63]\n\t" + "ldr r8, [%[a], #72]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[19] * B[62]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[20] * B[61]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[21] * B[60]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[22] * B[59]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[58]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[57]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[56]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[55]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[54]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[53]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[52]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[51]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[50]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[49]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[48]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[47]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[46]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[45]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[44]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[43]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[42]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[41]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[40]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[39]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[38]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[37]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[36]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[35]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[34]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[33]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[32]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[31]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[30]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[29]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[28]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[27]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[26]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[25]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[24]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[23]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[22]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[21]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[20]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[19]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[18]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #72]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #324]\n\t" + "# A[19] * B[63]\n\t" + "ldr r8, [%[a], #76]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[20] * B[62]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[21] * B[61]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[22] * B[60]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[23] * B[59]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[58]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[57]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[56]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[55]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[54]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[53]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[52]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[51]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[50]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[49]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[48]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[47]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[46]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[45]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[44]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[43]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[42]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[41]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[40]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[39]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[38]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[37]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[36]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[35]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[34]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[33]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[32]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[31]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[30]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[29]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[28]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[27]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[26]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[25]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[24]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[23]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[22]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[21]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[20]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[19]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #76]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #328]\n\t" + "# A[20] * B[63]\n\t" + "ldr r8, [%[a], #80]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[21] * B[62]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[22] * B[61]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[23] * B[60]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[24] * B[59]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[58]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[57]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[56]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[55]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[54]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[53]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[52]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[51]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[50]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[49]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[48]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[47]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[46]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[45]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[44]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[43]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[42]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[41]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[40]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[39]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[38]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[37]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[36]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[35]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[34]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[33]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[32]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[31]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[30]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[29]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[28]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[27]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[26]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[25]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[24]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[23]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[22]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[21]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[20]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #80]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #332]\n\t" + "# A[21] * B[63]\n\t" + "ldr r8, [%[a], #84]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[22] * B[62]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[23] * B[61]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[24] * B[60]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[25] * B[59]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[58]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[57]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[56]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[55]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[54]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[53]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[52]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[51]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[50]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[49]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[48]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[47]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[46]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[45]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[44]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[43]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[42]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[41]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[40]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[39]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[38]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[37]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[36]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[35]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[34]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[33]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[32]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[31]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[30]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[29]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[28]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[27]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[26]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[25]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[24]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[23]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[22]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[21]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #84]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #336]\n\t" + "# A[22] * B[63]\n\t" + "ldr r8, [%[a], #88]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[23] * B[62]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[24] * B[61]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[25] * B[60]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[26] * B[59]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[58]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[57]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[56]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[55]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[54]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[53]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[52]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[51]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[50]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[49]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[48]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[47]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[46]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[45]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[44]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[43]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[42]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[41]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[40]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[39]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[38]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[37]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[36]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[35]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[34]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[33]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[32]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[31]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[30]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[29]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[28]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[27]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[26]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[25]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[24]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[23]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[22]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #88]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #340]\n\t" + "# A[23] * B[63]\n\t" + "ldr r8, [%[a], #92]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[24] * B[62]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[25] * B[61]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[26] * B[60]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[27] * B[59]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[58]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[57]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[56]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[55]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[54]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[53]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[52]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[51]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[50]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[49]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[48]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[47]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[46]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[45]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[44]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[43]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[42]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[41]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[40]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[39]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[38]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[37]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[36]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[35]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[34]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[33]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[32]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[31]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[30]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[29]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[28]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[27]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[26]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[25]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[24]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[23]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #92]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #344]\n\t" + "# A[24] * B[63]\n\t" + "ldr r8, [%[a], #96]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[25] * B[62]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[26] * B[61]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[27] * B[60]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[28] * B[59]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[58]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[57]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[56]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[55]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[54]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[53]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[52]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[51]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[50]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[49]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[48]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[47]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[46]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[45]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[44]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[43]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[42]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[41]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[40]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[39]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[38]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[37]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[36]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[35]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[34]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[33]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[32]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[31]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[30]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[29]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[28]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[27]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[26]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[25]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[24]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #96]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #348]\n\t" + "# A[25] * B[63]\n\t" + "ldr r8, [%[a], #100]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[26] * B[62]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[27] * B[61]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[28] * B[60]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[29] * B[59]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[58]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[57]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[56]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[55]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[54]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[53]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[52]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[51]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[50]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[49]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[48]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[47]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[46]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[45]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[44]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[43]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[42]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[41]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[40]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[39]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[38]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[37]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[36]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[35]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[34]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[33]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[32]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[31]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[30]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[29]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[28]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[27]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[26]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[25]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #100]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #352]\n\t" + "# A[26] * B[63]\n\t" + "ldr r8, [%[a], #104]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[27] * B[62]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[28] * B[61]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[29] * B[60]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[30] * B[59]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[58]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[57]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[56]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[55]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[54]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[53]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[52]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[51]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[50]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[49]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[48]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[47]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[46]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[45]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[44]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[43]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[42]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[41]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[40]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[39]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[38]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[37]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[36]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[35]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[34]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[33]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[32]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[31]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[30]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[29]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[28]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[27]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[26]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #104]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #356]\n\t" + "# A[27] * B[63]\n\t" + "ldr r8, [%[a], #108]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[28] * B[62]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[29] * B[61]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[30] * B[60]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[31] * B[59]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[58]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[57]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[56]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[55]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[54]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[53]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[52]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[51]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[50]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[49]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[48]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[47]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[46]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[45]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[44]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[43]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[42]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[41]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[40]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[39]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[38]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[37]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[36]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[35]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[34]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[33]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[32]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[31]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[30]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[29]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[28]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[27]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #108]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #360]\n\t" + "# A[28] * B[63]\n\t" + "ldr r8, [%[a], #112]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[29] * B[62]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[30] * B[61]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[31] * B[60]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[32] * B[59]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[58]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[57]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[56]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[55]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[54]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[53]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[52]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[51]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[50]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[49]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[48]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[47]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[46]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[45]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[44]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[43]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[42]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[41]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[40]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[39]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[38]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[37]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[36]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[35]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[34]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[33]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[32]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[31]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[30]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[29]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[28]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #112]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #364]\n\t" + "# A[29] * B[63]\n\t" + "ldr r8, [%[a], #116]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[30] * B[62]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[31] * B[61]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[32] * B[60]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[33] * B[59]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[58]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[57]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[56]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[55]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[54]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[53]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[52]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[51]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[50]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[49]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[48]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[47]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[46]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[45]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[44]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[43]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[42]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[41]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[40]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[39]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[38]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[37]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[36]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[35]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[34]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[33]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[32]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[31]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[30]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[29]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #116]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #368]\n\t" + "# A[30] * B[63]\n\t" + "ldr r8, [%[a], #120]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[31] * B[62]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[32] * B[61]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[33] * B[60]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[34] * B[59]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[58]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[57]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[56]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[55]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[54]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[53]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[52]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[51]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[50]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[49]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[48]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[47]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[46]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[45]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[44]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[43]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[42]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[41]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[40]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[39]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[38]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[37]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[36]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[35]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[34]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[33]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[32]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[31]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[30]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #120]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #372]\n\t" + "# A[31] * B[63]\n\t" + "ldr r8, [%[a], #124]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[32] * B[62]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[33] * B[61]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[34] * B[60]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[35] * B[59]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[58]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[57]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[56]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[55]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[54]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[53]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[52]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[51]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[50]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[49]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[48]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[47]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[46]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[45]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[44]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[43]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[42]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[41]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[40]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[39]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[38]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[37]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[36]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[35]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[34]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[33]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[32]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[31]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #124]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #376]\n\t" + "# A[32] * B[63]\n\t" + "ldr r8, [%[a], #128]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[33] * B[62]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[34] * B[61]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[35] * B[60]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[36] * B[59]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[58]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[57]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[56]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[55]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[54]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[53]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[52]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[51]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[50]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[49]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[48]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[47]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[46]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[45]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[44]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[43]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[42]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[41]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[40]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[39]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[38]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[37]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[36]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[35]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[34]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[33]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[32]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #128]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #380]\n\t" + "# A[33] * B[63]\n\t" + "ldr r8, [%[a], #132]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[34] * B[62]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[35] * B[61]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[36] * B[60]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[37] * B[59]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[58]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[57]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[56]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[55]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[54]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[53]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[52]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[51]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[50]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[49]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[48]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[47]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[46]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[45]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[44]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[43]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[42]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[41]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[40]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[39]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[38]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[37]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[36]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[35]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[34]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[33]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #132]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #384]\n\t" + "# A[34] * B[63]\n\t" + "ldr r8, [%[a], #136]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[35] * B[62]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[36] * B[61]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[37] * B[60]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[38] * B[59]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[58]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[57]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[56]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[55]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[54]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[53]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[52]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[51]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[50]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[49]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[48]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[47]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[46]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[45]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[44]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[43]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[42]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[41]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[40]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[39]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[38]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[37]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[36]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[35]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[34]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #136]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #388]\n\t" + "# A[35] * B[63]\n\t" + "ldr r8, [%[a], #140]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[36] * B[62]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[37] * B[61]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[38] * B[60]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[39] * B[59]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[58]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[57]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[56]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[55]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[54]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[53]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[52]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[51]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[50]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[49]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[48]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[47]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[46]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[45]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[44]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[43]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[42]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[41]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[40]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[39]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[38]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[37]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[36]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[35]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #140]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #392]\n\t" + "# A[36] * B[63]\n\t" + "ldr r8, [%[a], #144]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[37] * B[62]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[38] * B[61]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[39] * B[60]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[40] * B[59]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[58]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[57]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[56]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[55]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[54]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[53]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[52]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[51]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[50]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[49]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[48]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[47]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[46]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[45]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[44]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[43]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[42]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[41]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[40]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[39]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[38]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[37]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[36]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #144]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #396]\n\t" + "# A[37] * B[63]\n\t" + "ldr r8, [%[a], #148]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[38] * B[62]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[39] * B[61]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[40] * B[60]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[41] * B[59]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[58]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[57]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[56]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[55]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[54]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[53]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[52]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[51]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[50]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[49]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[48]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[47]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[46]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[45]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[44]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[43]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[42]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[41]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[40]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[39]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[38]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[37]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #148]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #400]\n\t" + "# A[38] * B[63]\n\t" + "ldr r8, [%[a], #152]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[39] * B[62]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[40] * B[61]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[41] * B[60]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[42] * B[59]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[58]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[57]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[56]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[55]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[54]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[53]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[52]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[51]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[50]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[49]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[48]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[47]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[46]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[45]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[44]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[43]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[42]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[41]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[40]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[39]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[38]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #152]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #404]\n\t" + "# A[39] * B[63]\n\t" + "ldr r8, [%[a], #156]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[40] * B[62]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[41] * B[61]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[42] * B[60]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[43] * B[59]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[58]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[57]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[56]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[55]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[54]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[53]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[52]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[51]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[50]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[49]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[48]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[47]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[46]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[45]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[44]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[43]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[42]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[41]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[40]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[39]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #156]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #408]\n\t" + "# A[40] * B[63]\n\t" + "ldr r8, [%[a], #160]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[41] * B[62]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[42] * B[61]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[43] * B[60]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[44] * B[59]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[58]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[57]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[56]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[55]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[54]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[53]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[52]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[51]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[50]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[49]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[48]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[47]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[46]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[45]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[44]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[43]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[42]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[41]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[40]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #160]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #412]\n\t" + "# A[41] * B[63]\n\t" + "ldr r8, [%[a], #164]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[42] * B[62]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[43] * B[61]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[44] * B[60]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[45] * B[59]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[58]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[57]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[56]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[55]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[54]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[53]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[52]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[51]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[50]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[49]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[48]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[47]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[46]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[45]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[44]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[43]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[42]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[41]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #164]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #416]\n\t" + "# A[42] * B[63]\n\t" + "ldr r8, [%[a], #168]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[43] * B[62]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[44] * B[61]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[45] * B[60]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[46] * B[59]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[58]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[57]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[56]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[55]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[54]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[53]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[52]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[51]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[50]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[49]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[48]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[47]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[46]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[45]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[44]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[43]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[42]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #168]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #420]\n\t" + "# A[43] * B[63]\n\t" + "ldr r8, [%[a], #172]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[44] * B[62]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[45] * B[61]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[46] * B[60]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[47] * B[59]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[58]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[57]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[56]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[55]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[54]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[53]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[52]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[51]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[50]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[49]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[48]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[47]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[46]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[45]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[44]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[43]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #172]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #424]\n\t" + "# A[44] * B[63]\n\t" + "ldr r8, [%[a], #176]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[45] * B[62]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[46] * B[61]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[47] * B[60]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[48] * B[59]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[58]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[57]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[56]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[55]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[54]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[53]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[52]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[51]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[50]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[49]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[48]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[47]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[46]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[45]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[44]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #176]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #428]\n\t" + "# A[45] * B[63]\n\t" + "ldr r8, [%[a], #180]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[46] * B[62]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[47] * B[61]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[48] * B[60]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[49] * B[59]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[58]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[57]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[56]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[55]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[54]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[53]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[52]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[51]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[50]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[49]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[48]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[47]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[46]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[45]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #180]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #432]\n\t" + "# A[46] * B[63]\n\t" + "ldr r8, [%[a], #184]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[47] * B[62]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[48] * B[61]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[49] * B[60]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[50] * B[59]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[58]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[57]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[56]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[55]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[54]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[53]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[52]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[51]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[50]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[49]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[48]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[47]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[46]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #184]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #436]\n\t" + "# A[47] * B[63]\n\t" + "ldr r8, [%[a], #188]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[48] * B[62]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[49] * B[61]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[50] * B[60]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[51] * B[59]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[58]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[57]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[56]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[55]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[54]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[53]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[52]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[51]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[50]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[49]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[48]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[47]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #188]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #440]\n\t" + "# A[48] * B[63]\n\t" + "ldr r8, [%[a], #192]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[49] * B[62]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[50] * B[61]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[51] * B[60]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[52] * B[59]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[58]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[57]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[56]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[55]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[54]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[53]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[52]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[51]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[50]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[49]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[48]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #192]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #444]\n\t" + "# A[49] * B[63]\n\t" + "ldr r8, [%[a], #196]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[50] * B[62]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[51] * B[61]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[52] * B[60]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[53] * B[59]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[58]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[57]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[56]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[55]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[54]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[53]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[52]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[51]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[50]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[49]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #196]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #448]\n\t" + "# A[50] * B[63]\n\t" + "ldr r8, [%[a], #200]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[51] * B[62]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[52] * B[61]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[53] * B[60]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[54] * B[59]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[58]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[57]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[56]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[55]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[54]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[53]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[52]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[51]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[50]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #200]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #452]\n\t" + "# A[51] * B[63]\n\t" + "ldr r8, [%[a], #204]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[52] * B[62]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[53] * B[61]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[54] * B[60]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[55] * B[59]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[58]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[57]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[56]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[55]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[54]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[53]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[52]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[51]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #204]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #456]\n\t" + "# A[52] * B[63]\n\t" + "ldr r8, [%[a], #208]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[53] * B[62]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[54] * B[61]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[55] * B[60]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[56] * B[59]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[58]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[57]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[56]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[55]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[54]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[53]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[52]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #208]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #460]\n\t" + "# A[53] * B[63]\n\t" + "ldr r8, [%[a], #212]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[54] * B[62]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[55] * B[61]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[56] * B[60]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[57] * B[59]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[58]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[57]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[56]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[55]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[54]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[53]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #212]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #464]\n\t" + "# A[54] * B[63]\n\t" + "ldr r8, [%[a], #216]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[55] * B[62]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[56] * B[61]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[57] * B[60]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[58] * B[59]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[58]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[57]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[56]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[55]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[54]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #216]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #468]\n\t" + "# A[55] * B[63]\n\t" + "ldr r8, [%[a], #220]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[56] * B[62]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[57] * B[61]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[58] * B[60]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[59] * B[59]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[58]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[57]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[56]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[55]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #220]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #472]\n\t" + "# A[56] * B[63]\n\t" + "ldr r8, [%[a], #224]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[57] * B[62]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[58] * B[61]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[59] * B[60]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[60] * B[59]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[58]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[57]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[56]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #224]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #476]\n\t" + "# A[57] * B[63]\n\t" + "ldr r8, [%[a], #228]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[58] * B[62]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[59] * B[61]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[60] * B[60]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[61] * B[59]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[58]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[57]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #228]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #480]\n\t" + "# A[58] * B[63]\n\t" + "ldr r8, [%[a], #232]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[59] * B[62]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[60] * B[61]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[61] * B[60]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[62] * B[59]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[58]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #232]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #484]\n\t" + "# A[59] * B[63]\n\t" + "ldr r8, [%[a], #236]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[60] * B[62]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[61] * B[61]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[62] * B[60]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[63] * B[59]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #236]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #488]\n\t" + "# A[60] * B[63]\n\t" + "ldr r8, [%[a], #240]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[61] * B[62]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[62] * B[61]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[63] * B[60]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #240]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #492]\n\t" + "# A[61] * B[63]\n\t" + "ldr r8, [%[a], #244]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[62] * B[62]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[63] * B[61]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #244]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #496]\n\t" + "# A[62] * B[63]\n\t" + "ldr r8, [%[a], #248]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[63] * B[62]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #248]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #500]\n\t" + "# A[63] * B[63]\n\t" + "ldr r8, [%[a], #252]\n\t" + "ldr r9, [%[b], #252]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r3, [%[r], #504]\n\t" + "str r4, [%[r], #508]\n\t" + "ldr r3, [sp, #0]\n\t" + "ldr r4, [sp, #4]\n\t" + "ldr r5, [sp, #8]\n\t" + "ldr r6, [sp, #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [sp, #16]\n\t" + "ldr r4, [sp, #20]\n\t" + "ldr r5, [sp, #24]\n\t" + "ldr r6, [sp, #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r3, [sp, #32]\n\t" + "ldr r4, [sp, #36]\n\t" + "ldr r5, [sp, #40]\n\t" + "ldr r6, [sp, #44]\n\t" + "str r3, [%[r], #32]\n\t" + "str r4, [%[r], #36]\n\t" + "str r5, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r3, [sp, #48]\n\t" + "ldr r4, [sp, #52]\n\t" + "ldr r5, [sp, #56]\n\t" + "ldr r6, [sp, #60]\n\t" + "str r3, [%[r], #48]\n\t" + "str r4, [%[r], #52]\n\t" + "str r5, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r3, [sp, #64]\n\t" + "ldr r4, [sp, #68]\n\t" + "ldr r5, [sp, #72]\n\t" + "ldr r6, [sp, #76]\n\t" + "str r3, [%[r], #64]\n\t" + "str r4, [%[r], #68]\n\t" + "str r5, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r3, [sp, #80]\n\t" + "ldr r4, [sp, #84]\n\t" + "ldr r5, [sp, #88]\n\t" + "ldr r6, [sp, #92]\n\t" + "str r3, [%[r], #80]\n\t" + "str r4, [%[r], #84]\n\t" + "str r5, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r3, [sp, #96]\n\t" + "ldr r4, [sp, #100]\n\t" + "ldr r5, [sp, #104]\n\t" + "ldr r6, [sp, #108]\n\t" + "str r3, [%[r], #96]\n\t" + "str r4, [%[r], #100]\n\t" + "str r5, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r3, [sp, #112]\n\t" + "ldr r4, [sp, #116]\n\t" + "ldr r5, [sp, #120]\n\t" + "ldr r6, [sp, #124]\n\t" + "str r3, [%[r], #112]\n\t" + "str r4, [%[r], #116]\n\t" + "str r5, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "ldr r3, [sp, #128]\n\t" + "ldr r4, [sp, #132]\n\t" + "ldr r5, [sp, #136]\n\t" + "ldr r6, [sp, #140]\n\t" + "str r3, [%[r], #128]\n\t" + "str r4, [%[r], #132]\n\t" + "str r5, [%[r], #136]\n\t" + "str r6, [%[r], #140]\n\t" + "ldr r3, [sp, #144]\n\t" + "ldr r4, [sp, #148]\n\t" + "ldr r5, [sp, #152]\n\t" + "ldr r6, [sp, #156]\n\t" + "str r3, [%[r], #144]\n\t" + "str r4, [%[r], #148]\n\t" + "str r5, [%[r], #152]\n\t" + "str r6, [%[r], #156]\n\t" + "ldr r3, [sp, #160]\n\t" + "ldr r4, [sp, #164]\n\t" + "ldr r5, [sp, #168]\n\t" + "ldr r6, [sp, #172]\n\t" + "str r3, [%[r], #160]\n\t" + "str r4, [%[r], #164]\n\t" + "str r5, [%[r], #168]\n\t" + "str r6, [%[r], #172]\n\t" + "ldr r3, [sp, #176]\n\t" + "ldr r4, [sp, #180]\n\t" + "ldr r5, [sp, #184]\n\t" + "ldr r6, [sp, #188]\n\t" + "str r3, [%[r], #176]\n\t" + "str r4, [%[r], #180]\n\t" + "str r5, [%[r], #184]\n\t" + "str r6, [%[r], #188]\n\t" + "ldr r3, [sp, #192]\n\t" + "ldr r4, [sp, #196]\n\t" + "ldr r5, [sp, #200]\n\t" + "ldr r6, [sp, #204]\n\t" + "str r3, [%[r], #192]\n\t" + "str r4, [%[r], #196]\n\t" + "str r5, [%[r], #200]\n\t" + "str r6, [%[r], #204]\n\t" + "ldr r3, [sp, #208]\n\t" + "ldr r4, [sp, #212]\n\t" + "ldr r5, [sp, #216]\n\t" + "ldr r6, [sp, #220]\n\t" + "str r3, [%[r], #208]\n\t" + "str r4, [%[r], #212]\n\t" + "str r5, [%[r], #216]\n\t" + "str r6, [%[r], #220]\n\t" + "ldr r3, [sp, #224]\n\t" + "ldr r4, [sp, #228]\n\t" + "ldr r5, [sp, #232]\n\t" + "ldr r6, [sp, #236]\n\t" + "str r3, [%[r], #224]\n\t" + "str r4, [%[r], #228]\n\t" + "str r5, [%[r], #232]\n\t" + "str r6, [%[r], #236]\n\t" + "ldr r3, [sp, #240]\n\t" + "ldr r4, [sp, #244]\n\t" + "ldr r5, [sp, #248]\n\t" + "ldr r6, [sp, #252]\n\t" + "str r3, [%[r], #240]\n\t" + "str r4, [%[r], #244]\n\t" + "str r5, [%[r], #248]\n\t" + "str r6, [%[r], #252]\n\t" + "add sp, sp, #256\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +} + +/* 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_4096_mask_64(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<64; 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; + } +#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. + */ +SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[128]; + sp_digit a1[64]; + sp_digit b1[64]; + sp_digit z2[128]; + sp_digit u, ca, cb; + + ca = sp_2048_add_64(a1, a, &a[64]); + cb = sp_2048_add_64(b1, b, &b[64]); + u = ca & cb; + sp_2048_mul_64(z1, a1, b1); + sp_2048_mul_64(z2, &a[64], &b[64]); + sp_2048_mul_64(z0, a, b); + sp_2048_mask_64(r + 128, a1, 0 - cb); + sp_2048_mask_64(b1, b1, 0 - ca); + u += sp_2048_add_64(r + 128, r + 128, b1); + u += sp_4096_sub_in_place_128(z1, z2); + u += sp_4096_sub_in_place_128(z1, z0); + u += sp_4096_add_128(r + 64, r + 64, z1); + r[192] = u; + XMEMSET(r + 192 + 1, 0, sizeof(sp_digit) * (64 - 1)); + (void)sp_4096_add_128(r + 128, r + 128, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_4096_sqr_64(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #256\n\t" + "mov r14, #0\n\t" + "# A[0] * A[0]\n\t" + "ldr r10, [%[a], #0]\n\t" + "umull r8, r3, r10, r10\n\t" + "mov r4, #0\n\t" + "str r8, [sp]\n\t" + "# A[0] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[1] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[1] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[1] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[2] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #28]\n\t" + "# A[0] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #32]\n\t" + "# A[0] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #36]\n\t" + "# A[0] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #40]\n\t" + "# A[0] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #44]\n\t" + "# A[0] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #48]\n\t" + "# A[0] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #52]\n\t" + "# A[0] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #56]\n\t" + "# A[0] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #60]\n\t" + "# A[0] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #64]\n\t" + "# A[0] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #68]\n\t" + "# A[0] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #72]\n\t" + "# A[0] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #76]\n\t" + "# A[0] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #80]\n\t" + "# A[0] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #84]\n\t" + "# A[0] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #88]\n\t" + "# A[0] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #92]\n\t" + "# A[0] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[12]\n\t" + "ldr r10, [%[a], #48]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #96]\n\t" + "# A[0] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #100]\n\t" + "# A[0] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[13]\n\t" + "ldr r10, [%[a], #52]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #104]\n\t" + "# A[0] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #108]\n\t" + "# A[0] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[14]\n\t" + "ldr r10, [%[a], #56]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #112]\n\t" + "# A[0] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #116]\n\t" + "# A[0] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[15]\n\t" + "ldr r10, [%[a], #60]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #120]\n\t" + "# A[0] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #124]\n\t" + "# A[0] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[16]\n\t" + "ldr r10, [%[a], #64]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #128]\n\t" + "# A[0] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #132]\n\t" + "# A[0] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[17]\n\t" + "ldr r10, [%[a], #68]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #136]\n\t" + "# A[0] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #140]\n\t" + "# A[0] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[18]\n\t" + "ldr r10, [%[a], #72]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #144]\n\t" + "# A[0] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #148]\n\t" + "# A[0] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[19]\n\t" + "ldr r10, [%[a], #76]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #152]\n\t" + "# A[0] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #156]\n\t" + "# A[0] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[20]\n\t" + "ldr r10, [%[a], #80]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #160]\n\t" + "# A[0] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #164]\n\t" + "# A[0] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[21]\n\t" + "ldr r10, [%[a], #84]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #168]\n\t" + "# A[0] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #172]\n\t" + "# A[0] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[22]\n\t" + "ldr r10, [%[a], #88]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #176]\n\t" + "# A[0] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #180]\n\t" + "# A[0] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[23]\n\t" + "ldr r10, [%[a], #92]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #184]\n\t" + "# A[0] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #188]\n\t" + "# A[0] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[24]\n\t" + "ldr r10, [%[a], #96]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #192]\n\t" + "# A[0] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #196]\n\t" + "# A[0] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[25]\n\t" + "ldr r10, [%[a], #100]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #200]\n\t" + "# A[0] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #204]\n\t" + "# A[0] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[26]\n\t" + "ldr r10, [%[a], #104]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #208]\n\t" + "# A[0] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #212]\n\t" + "# A[0] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[27]\n\t" + "ldr r10, [%[a], #108]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #216]\n\t" + "# A[0] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #220]\n\t" + "# A[0] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[28]\n\t" + "ldr r10, [%[a], #112]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #224]\n\t" + "# A[0] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #228]\n\t" + "# A[0] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[29]\n\t" + "ldr r10, [%[a], #116]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #232]\n\t" + "# A[0] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #236]\n\t" + "# A[0] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[30]\n\t" + "ldr r10, [%[a], #120]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #240]\n\t" + "# A[0] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #244]\n\t" + "# A[0] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[31]\n\t" + "ldr r10, [%[a], #124]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #248]\n\t" + "# A[0] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #252]\n\t" + "# A[1] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[2] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[32]\n\t" + "ldr r10, [%[a], #128]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #256]\n\t" + "# A[2] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[3] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #260]\n\t" + "# A[3] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[4] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[33]\n\t" + "ldr r10, [%[a], #132]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #264]\n\t" + "# A[4] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[5] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #268]\n\t" + "# A[5] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[6] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[34]\n\t" + "ldr r10, [%[a], #136]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #272]\n\t" + "# A[6] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[7] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #276]\n\t" + "# A[7] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[8] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[9] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[35]\n\t" + "ldr r10, [%[a], #140]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #280]\n\t" + "# A[8] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[9] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[10] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #284]\n\t" + "# A[9] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[10] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[11] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[36]\n\t" + "ldr r10, [%[a], #144]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #288]\n\t" + "# A[10] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[11] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[12] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #292]\n\t" + "# A[11] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[12] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[13] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[37]\n\t" + "ldr r10, [%[a], #148]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #296]\n\t" + "# A[12] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #48]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[13] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[14] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #300]\n\t" + "# A[13] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #52]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[14] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[15] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[38]\n\t" + "ldr r10, [%[a], #152]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #304]\n\t" + "# A[14] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #56]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[15] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[16] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #308]\n\t" + "# A[15] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #60]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[16] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[17] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[39]\n\t" + "ldr r10, [%[a], #156]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #312]\n\t" + "# A[16] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #64]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[17] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[18] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #316]\n\t" + "# A[17] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #68]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[18] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[19] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[40]\n\t" + "ldr r10, [%[a], #160]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #320]\n\t" + "# A[18] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #72]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[19] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[20] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #324]\n\t" + "# A[19] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #76]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[20] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[21] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[41]\n\t" + "ldr r10, [%[a], #164]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #328]\n\t" + "# A[20] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #80]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[21] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[22] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #332]\n\t" + "# A[21] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #84]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[22] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[23] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[42]\n\t" + "ldr r10, [%[a], #168]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #336]\n\t" + "# A[22] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #88]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[23] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[24] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #340]\n\t" + "# A[23] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #92]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[24] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[25] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[43]\n\t" + "ldr r10, [%[a], #172]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #344]\n\t" + "# A[24] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #96]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[25] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[26] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #348]\n\t" + "# A[25] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #100]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[26] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[27] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[44]\n\t" + "ldr r10, [%[a], #176]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #352]\n\t" + "# A[26] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #104]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[27] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[28] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #356]\n\t" + "# A[27] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #108]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[28] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[29] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[45]\n\t" + "ldr r10, [%[a], #180]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #360]\n\t" + "# A[28] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #112]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[29] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[30] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #364]\n\t" + "# A[29] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #116]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[30] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[31] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[46]\n\t" + "ldr r10, [%[a], #184]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #368]\n\t" + "# A[30] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #120]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[31] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[32] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #372]\n\t" + "# A[31] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[32] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[33] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[47]\n\t" + "ldr r10, [%[a], #188]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #376]\n\t" + "# A[32] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #128]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[33] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[34] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #380]\n\t" + "# A[33] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #132]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[34] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[35] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[48]\n\t" + "ldr r10, [%[a], #192]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #384]\n\t" + "# A[34] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #136]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[35] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[36] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #388]\n\t" + "# A[35] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #140]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[36] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[37] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[49]\n\t" + "ldr r10, [%[a], #196]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #392]\n\t" + "# A[36] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #144]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[37] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[38] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #396]\n\t" + "# A[37] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #148]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[38] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[39] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[50] * A[50]\n\t" + "ldr r10, [%[a], #200]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #400]\n\t" + "# A[38] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #152]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[39] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[40] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[50] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #404]\n\t" + "# A[39] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #156]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[40] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[41] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[50] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[51] * A[51]\n\t" + "ldr r10, [%[a], #204]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #408]\n\t" + "# A[40] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #160]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[41] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[42] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[50] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[51] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "ldr r8, [%[a], #204]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #412]\n\t" + "# A[41] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #164]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[42] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[43] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[50] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[51] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #204]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[52] * A[52]\n\t" + "ldr r10, [%[a], #208]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #416]\n\t" + "# A[42] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #168]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[43] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[44] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[50] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[51] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #204]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[52] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "ldr r8, [%[a], #208]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #420]\n\t" + "# A[43] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #172]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[44] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[45] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[50] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[51] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #204]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[52] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #208]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[53] * A[53]\n\t" + "ldr r10, [%[a], #212]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #424]\n\t" + "# A[44] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #176]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[45] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[46] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[50] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[51] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #204]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[52] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #208]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[53] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "ldr r8, [%[a], #212]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #428]\n\t" + "# A[45] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #180]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[46] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[47] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[50] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[51] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #204]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[52] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #208]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[53] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #212]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[54] * A[54]\n\t" + "ldr r10, [%[a], #216]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #432]\n\t" + "# A[46] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #184]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[47] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[48] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[50] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[51] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #204]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[52] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #208]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[53] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #212]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[54] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "ldr r8, [%[a], #216]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #436]\n\t" + "# A[47] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[48] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[49] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[50] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[51] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #204]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[52] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #208]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[53] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #212]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[54] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #216]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[55] * A[55]\n\t" + "ldr r10, [%[a], #220]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #440]\n\t" + "# A[48] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #192]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[49] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[50] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[51] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #204]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[52] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #208]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[53] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #212]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[54] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #216]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[55] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "ldr r8, [%[a], #220]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #444]\n\t" + "# A[49] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #196]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[50] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[51] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #204]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[52] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #208]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[53] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #212]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[54] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #216]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[55] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #220]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[56] * A[56]\n\t" + "ldr r10, [%[a], #224]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #448]\n\t" + "# A[50] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #200]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[51] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #204]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[52] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #208]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[53] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #212]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[54] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #216]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[55] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #220]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[56] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "ldr r8, [%[a], #224]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #452]\n\t" + "# A[51] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #204]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[52] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #208]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[53] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #212]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[54] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #216]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[55] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #220]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[56] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #224]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[57] * A[57]\n\t" + "ldr r10, [%[a], #228]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #456]\n\t" + "# A[52] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #208]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[53] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #212]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[54] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #216]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[55] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #220]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[56] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #224]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[57] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "ldr r8, [%[a], #228]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #460]\n\t" + "# A[53] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #212]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[54] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #216]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[55] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #220]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[56] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #224]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[57] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #228]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[58] * A[58]\n\t" + "ldr r10, [%[a], #232]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #464]\n\t" + "# A[54] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #216]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[55] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #220]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[56] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #224]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[57] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #228]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[58] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "ldr r8, [%[a], #232]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #468]\n\t" + "# A[55] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #220]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[56] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #224]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[57] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #228]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[58] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #232]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[59] * A[59]\n\t" + "ldr r10, [%[a], #236]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #472]\n\t" + "# A[56] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #224]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[57] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #228]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[58] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #232]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[59] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "ldr r8, [%[a], #236]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #476]\n\t" + "# A[57] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #228]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[58] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #232]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[59] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #236]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[60] * A[60]\n\t" + "ldr r10, [%[a], #240]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #480]\n\t" + "# A[58] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #232]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[59] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #236]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[60] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "ldr r8, [%[a], #240]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #484]\n\t" + "# A[59] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #236]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[60] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #240]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[61] * A[61]\n\t" + "ldr r10, [%[a], #244]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [%[r], #488]\n\t" + "# A[60] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #240]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[61] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "ldr r8, [%[a], #244]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [%[r], #492]\n\t" + "# A[61] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #244]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[62] * A[62]\n\t" + "ldr r10, [%[a], #248]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #496]\n\t" + "# A[62] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "ldr r8, [%[a], #248]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [%[r], #500]\n\t" + "# A[63] * A[63]\n\t" + "ldr r10, [%[a], #252]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r2, r2, r8\n\t" + "adc r3, r3, r9\n\t" + "str r2, [%[r], #504]\n\t" + "str r3, [%[r], #508]\n\t" + "ldr r2, [sp, #0]\n\t" + "ldr r3, [sp, #4]\n\t" + "ldr r4, [sp, #8]\n\t" + "ldr r8, [sp, #12]\n\t" + "str r2, [%[r], #0]\n\t" + "str r3, [%[r], #4]\n\t" + "str r4, [%[r], #8]\n\t" + "str r8, [%[r], #12]\n\t" + "ldr r2, [sp, #16]\n\t" + "ldr r3, [sp, #20]\n\t" + "ldr r4, [sp, #24]\n\t" + "ldr r8, [sp, #28]\n\t" + "str r2, [%[r], #16]\n\t" + "str r3, [%[r], #20]\n\t" + "str r4, [%[r], #24]\n\t" + "str r8, [%[r], #28]\n\t" + "ldr r2, [sp, #32]\n\t" + "ldr r3, [sp, #36]\n\t" + "ldr r4, [sp, #40]\n\t" + "ldr r8, [sp, #44]\n\t" + "str r2, [%[r], #32]\n\t" + "str r3, [%[r], #36]\n\t" + "str r4, [%[r], #40]\n\t" + "str r8, [%[r], #44]\n\t" + "ldr r2, [sp, #48]\n\t" + "ldr r3, [sp, #52]\n\t" + "ldr r4, [sp, #56]\n\t" + "ldr r8, [sp, #60]\n\t" + "str r2, [%[r], #48]\n\t" + "str r3, [%[r], #52]\n\t" + "str r4, [%[r], #56]\n\t" + "str r8, [%[r], #60]\n\t" + "ldr r2, [sp, #64]\n\t" + "ldr r3, [sp, #68]\n\t" + "ldr r4, [sp, #72]\n\t" + "ldr r8, [sp, #76]\n\t" + "str r2, [%[r], #64]\n\t" + "str r3, [%[r], #68]\n\t" + "str r4, [%[r], #72]\n\t" + "str r8, [%[r], #76]\n\t" + "ldr r2, [sp, #80]\n\t" + "ldr r3, [sp, #84]\n\t" + "ldr r4, [sp, #88]\n\t" + "ldr r8, [sp, #92]\n\t" + "str r2, [%[r], #80]\n\t" + "str r3, [%[r], #84]\n\t" + "str r4, [%[r], #88]\n\t" + "str r8, [%[r], #92]\n\t" + "ldr r2, [sp, #96]\n\t" + "ldr r3, [sp, #100]\n\t" + "ldr r4, [sp, #104]\n\t" + "ldr r8, [sp, #108]\n\t" + "str r2, [%[r], #96]\n\t" + "str r3, [%[r], #100]\n\t" + "str r4, [%[r], #104]\n\t" + "str r8, [%[r], #108]\n\t" + "ldr r2, [sp, #112]\n\t" + "ldr r3, [sp, #116]\n\t" + "ldr r4, [sp, #120]\n\t" + "ldr r8, [sp, #124]\n\t" + "str r2, [%[r], #112]\n\t" + "str r3, [%[r], #116]\n\t" + "str r4, [%[r], #120]\n\t" + "str r8, [%[r], #124]\n\t" + "ldr r2, [sp, #128]\n\t" + "ldr r3, [sp, #132]\n\t" + "ldr r4, [sp, #136]\n\t" + "ldr r8, [sp, #140]\n\t" + "str r2, [%[r], #128]\n\t" + "str r3, [%[r], #132]\n\t" + "str r4, [%[r], #136]\n\t" + "str r8, [%[r], #140]\n\t" + "ldr r2, [sp, #144]\n\t" + "ldr r3, [sp, #148]\n\t" + "ldr r4, [sp, #152]\n\t" + "ldr r8, [sp, #156]\n\t" + "str r2, [%[r], #144]\n\t" + "str r3, [%[r], #148]\n\t" + "str r4, [%[r], #152]\n\t" + "str r8, [%[r], #156]\n\t" + "ldr r2, [sp, #160]\n\t" + "ldr r3, [sp, #164]\n\t" + "ldr r4, [sp, #168]\n\t" + "ldr r8, [sp, #172]\n\t" + "str r2, [%[r], #160]\n\t" + "str r3, [%[r], #164]\n\t" + "str r4, [%[r], #168]\n\t" + "str r8, [%[r], #172]\n\t" + "ldr r2, [sp, #176]\n\t" + "ldr r3, [sp, #180]\n\t" + "ldr r4, [sp, #184]\n\t" + "ldr r8, [sp, #188]\n\t" + "str r2, [%[r], #176]\n\t" + "str r3, [%[r], #180]\n\t" + "str r4, [%[r], #184]\n\t" + "str r8, [%[r], #188]\n\t" + "ldr r2, [sp, #192]\n\t" + "ldr r3, [sp, #196]\n\t" + "ldr r4, [sp, #200]\n\t" + "ldr r8, [sp, #204]\n\t" + "str r2, [%[r], #192]\n\t" + "str r3, [%[r], #196]\n\t" + "str r4, [%[r], #200]\n\t" + "str r8, [%[r], #204]\n\t" + "ldr r2, [sp, #208]\n\t" + "ldr r3, [sp, #212]\n\t" + "ldr r4, [sp, #216]\n\t" + "ldr r8, [sp, #220]\n\t" + "str r2, [%[r], #208]\n\t" + "str r3, [%[r], #212]\n\t" + "str r4, [%[r], #216]\n\t" + "str r8, [%[r], #220]\n\t" + "ldr r2, [sp, #224]\n\t" + "ldr r3, [sp, #228]\n\t" + "ldr r4, [sp, #232]\n\t" + "ldr r8, [sp, #236]\n\t" + "str r2, [%[r], #224]\n\t" + "str r3, [%[r], #228]\n\t" + "str r4, [%[r], #232]\n\t" + "str r8, [%[r], #236]\n\t" + "ldr r2, [sp, #240]\n\t" + "ldr r3, [sp, #244]\n\t" + "ldr r4, [sp, #248]\n\t" + "ldr r8, [sp, #252]\n\t" + "str r2, [%[r], #240]\n\t" + "str r3, [%[r], #244]\n\t" + "str r4, [%[r], #248]\n\t" + "str r8, [%[r], #252]\n\t" + "add sp, sp, #256\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[128]; + sp_digit z1[128]; + sp_digit a1[64]; + sp_digit u; + + u = sp_2048_add_64(a1, a, &a[64]); + sp_2048_sqr_64(z1, a1); + sp_2048_sqr_64(z2, &a[64]); + sp_2048_sqr_64(z0, a); + sp_2048_mask_64(r + 128, a1, 0 - u); + u += sp_2048_add_64(r + 128, r + 128, r + 128); + u += sp_4096_sub_in_place_128(z1, z2); + u += sp_4096_sub_in_place_128(z1, z0); + u += sp_4096_add_128(r + 64, r + 64, z1); + r[192] = u; + XMEMSET(r + 192 + 1, 0, sizeof(sp_digit) * (64 - 1)); + (void)sp_4096_add_128(r + 128, r + 128, z2); +} + +#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 sp_digit sp_4096_add_128(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #512\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_4096_sub_in_place_128(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r14, #0\n\t" + "add r12, %[a], #512\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#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_4096_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #1024\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #508\n\t" + "it cc\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #512\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #1016\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #1024\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #508\n\t" + "it cc\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #512\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #1016\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_4096_mont_setup(const 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 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* 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_4096_mul_d_128(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #512\n\t" + "blt 1b\n\t" + "str r3, [%[r], #512]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #28]\n\t" + "# A[8] * B\n\t" + "ldr r8, [%[a], #32]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[9] * B\n\t" + "ldr r8, [%[a], #36]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[10] * B\n\t" + "ldr r8, [%[a], #40]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[11] * B\n\t" + "ldr r8, [%[a], #44]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[12] * B\n\t" + "ldr r8, [%[a], #48]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[13] * B\n\t" + "ldr r8, [%[a], #52]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[14] * B\n\t" + "ldr r8, [%[a], #56]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #56]\n\t" + "# A[15] * B\n\t" + "ldr r8, [%[a], #60]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #60]\n\t" + "# A[16] * B\n\t" + "ldr r8, [%[a], #64]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[17] * B\n\t" + "ldr r8, [%[a], #68]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[18] * B\n\t" + "ldr r8, [%[a], #72]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[19] * B\n\t" + "ldr r8, [%[a], #76]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[20] * B\n\t" + "ldr r8, [%[a], #80]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[21] * B\n\t" + "ldr r8, [%[a], #84]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[22] * B\n\t" + "ldr r8, [%[a], #88]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #88]\n\t" + "# A[23] * B\n\t" + "ldr r8, [%[a], #92]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #92]\n\t" + "# A[24] * B\n\t" + "ldr r8, [%[a], #96]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #96]\n\t" + "# A[25] * B\n\t" + "ldr r8, [%[a], #100]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #100]\n\t" + "# A[26] * B\n\t" + "ldr r8, [%[a], #104]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #104]\n\t" + "# A[27] * B\n\t" + "ldr r8, [%[a], #108]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #108]\n\t" + "# A[28] * B\n\t" + "ldr r8, [%[a], #112]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #112]\n\t" + "# A[29] * B\n\t" + "ldr r8, [%[a], #116]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #116]\n\t" + "# A[30] * B\n\t" + "ldr r8, [%[a], #120]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #120]\n\t" + "# A[31] * B\n\t" + "ldr r8, [%[a], #124]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #124]\n\t" + "# A[32] * B\n\t" + "ldr r8, [%[a], #128]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #128]\n\t" + "# A[33] * B\n\t" + "ldr r8, [%[a], #132]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #132]\n\t" + "# A[34] * B\n\t" + "ldr r8, [%[a], #136]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #136]\n\t" + "# A[35] * B\n\t" + "ldr r8, [%[a], #140]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #140]\n\t" + "# A[36] * B\n\t" + "ldr r8, [%[a], #144]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #144]\n\t" + "# A[37] * B\n\t" + "ldr r8, [%[a], #148]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #148]\n\t" + "# A[38] * B\n\t" + "ldr r8, [%[a], #152]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #152]\n\t" + "# A[39] * B\n\t" + "ldr r8, [%[a], #156]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #156]\n\t" + "# A[40] * B\n\t" + "ldr r8, [%[a], #160]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #160]\n\t" + "# A[41] * B\n\t" + "ldr r8, [%[a], #164]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #164]\n\t" + "# A[42] * B\n\t" + "ldr r8, [%[a], #168]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #168]\n\t" + "# A[43] * B\n\t" + "ldr r8, [%[a], #172]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #172]\n\t" + "# A[44] * B\n\t" + "ldr r8, [%[a], #176]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #176]\n\t" + "# A[45] * B\n\t" + "ldr r8, [%[a], #180]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #180]\n\t" + "# A[46] * B\n\t" + "ldr r8, [%[a], #184]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #184]\n\t" + "# A[47] * B\n\t" + "ldr r8, [%[a], #188]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #188]\n\t" + "# A[48] * B\n\t" + "ldr r8, [%[a], #192]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #192]\n\t" + "# A[49] * B\n\t" + "ldr r8, [%[a], #196]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #196]\n\t" + "# A[50] * B\n\t" + "ldr r8, [%[a], #200]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #200]\n\t" + "# A[51] * B\n\t" + "ldr r8, [%[a], #204]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #204]\n\t" + "# A[52] * B\n\t" + "ldr r8, [%[a], #208]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #208]\n\t" + "# A[53] * B\n\t" + "ldr r8, [%[a], #212]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #212]\n\t" + "# A[54] * B\n\t" + "ldr r8, [%[a], #216]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #216]\n\t" + "# A[55] * B\n\t" + "ldr r8, [%[a], #220]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #220]\n\t" + "# A[56] * B\n\t" + "ldr r8, [%[a], #224]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #224]\n\t" + "# A[57] * B\n\t" + "ldr r8, [%[a], #228]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #228]\n\t" + "# A[58] * B\n\t" + "ldr r8, [%[a], #232]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #232]\n\t" + "# A[59] * B\n\t" + "ldr r8, [%[a], #236]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #236]\n\t" + "# A[60] * B\n\t" + "ldr r8, [%[a], #240]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #240]\n\t" + "# A[61] * B\n\t" + "ldr r8, [%[a], #244]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #244]\n\t" + "# A[62] * B\n\t" + "ldr r8, [%[a], #248]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #248]\n\t" + "# A[63] * B\n\t" + "ldr r8, [%[a], #252]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #252]\n\t" + "# A[64] * B\n\t" + "ldr r8, [%[a], #256]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #256]\n\t" + "# A[65] * B\n\t" + "ldr r8, [%[a], #260]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #260]\n\t" + "# A[66] * B\n\t" + "ldr r8, [%[a], #264]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #264]\n\t" + "# A[67] * B\n\t" + "ldr r8, [%[a], #268]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #268]\n\t" + "# A[68] * B\n\t" + "ldr r8, [%[a], #272]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #272]\n\t" + "# A[69] * B\n\t" + "ldr r8, [%[a], #276]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #276]\n\t" + "# A[70] * B\n\t" + "ldr r8, [%[a], #280]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #280]\n\t" + "# A[71] * B\n\t" + "ldr r8, [%[a], #284]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #284]\n\t" + "# A[72] * B\n\t" + "ldr r8, [%[a], #288]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #288]\n\t" + "# A[73] * B\n\t" + "ldr r8, [%[a], #292]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #292]\n\t" + "# A[74] * B\n\t" + "ldr r8, [%[a], #296]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #296]\n\t" + "# A[75] * B\n\t" + "ldr r8, [%[a], #300]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #300]\n\t" + "# A[76] * B\n\t" + "ldr r8, [%[a], #304]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #304]\n\t" + "# A[77] * B\n\t" + "ldr r8, [%[a], #308]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #308]\n\t" + "# A[78] * B\n\t" + "ldr r8, [%[a], #312]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #312]\n\t" + "# A[79] * B\n\t" + "ldr r8, [%[a], #316]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #316]\n\t" + "# A[80] * B\n\t" + "ldr r8, [%[a], #320]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #320]\n\t" + "# A[81] * B\n\t" + "ldr r8, [%[a], #324]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #324]\n\t" + "# A[82] * B\n\t" + "ldr r8, [%[a], #328]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #328]\n\t" + "# A[83] * B\n\t" + "ldr r8, [%[a], #332]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #332]\n\t" + "# A[84] * B\n\t" + "ldr r8, [%[a], #336]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #336]\n\t" + "# A[85] * B\n\t" + "ldr r8, [%[a], #340]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #340]\n\t" + "# A[86] * B\n\t" + "ldr r8, [%[a], #344]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #344]\n\t" + "# A[87] * B\n\t" + "ldr r8, [%[a], #348]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #348]\n\t" + "# A[88] * B\n\t" + "ldr r8, [%[a], #352]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #352]\n\t" + "# A[89] * B\n\t" + "ldr r8, [%[a], #356]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #356]\n\t" + "# A[90] * B\n\t" + "ldr r8, [%[a], #360]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #360]\n\t" + "# A[91] * B\n\t" + "ldr r8, [%[a], #364]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #364]\n\t" + "# A[92] * B\n\t" + "ldr r8, [%[a], #368]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #368]\n\t" + "# A[93] * B\n\t" + "ldr r8, [%[a], #372]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #372]\n\t" + "# A[94] * B\n\t" + "ldr r8, [%[a], #376]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #376]\n\t" + "# A[95] * B\n\t" + "ldr r8, [%[a], #380]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #380]\n\t" + "# A[96] * B\n\t" + "ldr r8, [%[a], #384]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #384]\n\t" + "# A[97] * B\n\t" + "ldr r8, [%[a], #388]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #388]\n\t" + "# A[98] * B\n\t" + "ldr r8, [%[a], #392]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #392]\n\t" + "# A[99] * B\n\t" + "ldr r8, [%[a], #396]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #396]\n\t" + "# A[100] * B\n\t" + "ldr r8, [%[a], #400]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #400]\n\t" + "# A[101] * B\n\t" + "ldr r8, [%[a], #404]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #404]\n\t" + "# A[102] * B\n\t" + "ldr r8, [%[a], #408]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #408]\n\t" + "# A[103] * B\n\t" + "ldr r8, [%[a], #412]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #412]\n\t" + "# A[104] * B\n\t" + "ldr r8, [%[a], #416]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #416]\n\t" + "# A[105] * B\n\t" + "ldr r8, [%[a], #420]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #420]\n\t" + "# A[106] * B\n\t" + "ldr r8, [%[a], #424]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #424]\n\t" + "# A[107] * B\n\t" + "ldr r8, [%[a], #428]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #428]\n\t" + "# A[108] * B\n\t" + "ldr r8, [%[a], #432]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #432]\n\t" + "# A[109] * B\n\t" + "ldr r8, [%[a], #436]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #436]\n\t" + "# A[110] * B\n\t" + "ldr r8, [%[a], #440]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #440]\n\t" + "# A[111] * B\n\t" + "ldr r8, [%[a], #444]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #444]\n\t" + "# A[112] * B\n\t" + "ldr r8, [%[a], #448]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #448]\n\t" + "# A[113] * B\n\t" + "ldr r8, [%[a], #452]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #452]\n\t" + "# A[114] * B\n\t" + "ldr r8, [%[a], #456]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #456]\n\t" + "# A[115] * B\n\t" + "ldr r8, [%[a], #460]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #460]\n\t" + "# A[116] * B\n\t" + "ldr r8, [%[a], #464]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #464]\n\t" + "# A[117] * B\n\t" + "ldr r8, [%[a], #468]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #468]\n\t" + "# A[118] * B\n\t" + "ldr r8, [%[a], #472]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #472]\n\t" + "# A[119] * B\n\t" + "ldr r8, [%[a], #476]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #476]\n\t" + "# A[120] * B\n\t" + "ldr r8, [%[a], #480]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #480]\n\t" + "# A[121] * B\n\t" + "ldr r8, [%[a], #484]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #484]\n\t" + "# A[122] * B\n\t" + "ldr r8, [%[a], #488]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #488]\n\t" + "# A[123] * B\n\t" + "ldr r8, [%[a], #492]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #492]\n\t" + "# A[124] * B\n\t" + "ldr r8, [%[a], #496]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #496]\n\t" + "# A[125] * B\n\t" + "ldr r8, [%[a], #500]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #500]\n\t" + "# A[126] * B\n\t" + "ldr r8, [%[a], #504]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #504]\n\t" + "# A[127] * B\n\t" + "ldr r8, [%[a], #508]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r7\n\t" + "str r4, [%[r], #508]\n\t" + "str r5, [%[r], #512]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 4096 bits, just need to subtract. + * + * r A single precision number. + * m A single precision number. + */ +static void sp_4096_mont_norm_128(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 128); + + /* r = 2^n mod m */ + sp_4096_sub_in_place_128(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* 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_4096_cond_sub_128(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #512\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r6, [%[a], #132]\n\t" + "ldr r5, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #128]\n\t" + "str r6, [%[r], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r6, [%[a], #140]\n\t" + "ldr r5, [%[b], #136]\n\t" + "ldr r7, [%[b], #140]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #136]\n\t" + "str r6, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r6, [%[a], #148]\n\t" + "ldr r5, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #144]\n\t" + "str r6, [%[r], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r6, [%[a], #156]\n\t" + "ldr r5, [%[b], #152]\n\t" + "ldr r7, [%[b], #156]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #152]\n\t" + "str r6, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r6, [%[a], #164]\n\t" + "ldr r5, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #160]\n\t" + "str r6, [%[r], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r6, [%[a], #172]\n\t" + "ldr r5, [%[b], #168]\n\t" + "ldr r7, [%[b], #172]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #168]\n\t" + "str r6, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r6, [%[a], #180]\n\t" + "ldr r5, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #176]\n\t" + "str r6, [%[r], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r6, [%[a], #188]\n\t" + "ldr r5, [%[b], #184]\n\t" + "ldr r7, [%[b], #188]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #184]\n\t" + "str r6, [%[r], #188]\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r6, [%[a], #196]\n\t" + "ldr r5, [%[b], #192]\n\t" + "ldr r7, [%[b], #196]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #192]\n\t" + "str r6, [%[r], #196]\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r6, [%[a], #204]\n\t" + "ldr r5, [%[b], #200]\n\t" + "ldr r7, [%[b], #204]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #200]\n\t" + "str r6, [%[r], #204]\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r6, [%[a], #212]\n\t" + "ldr r5, [%[b], #208]\n\t" + "ldr r7, [%[b], #212]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #208]\n\t" + "str r6, [%[r], #212]\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r6, [%[a], #220]\n\t" + "ldr r5, [%[b], #216]\n\t" + "ldr r7, [%[b], #220]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #216]\n\t" + "str r6, [%[r], #220]\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r6, [%[a], #228]\n\t" + "ldr r5, [%[b], #224]\n\t" + "ldr r7, [%[b], #228]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #224]\n\t" + "str r6, [%[r], #228]\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r6, [%[a], #236]\n\t" + "ldr r5, [%[b], #232]\n\t" + "ldr r7, [%[b], #236]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #232]\n\t" + "str r6, [%[r], #236]\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r6, [%[a], #244]\n\t" + "ldr r5, [%[b], #240]\n\t" + "ldr r7, [%[b], #244]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #240]\n\t" + "str r6, [%[r], #244]\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r6, [%[a], #252]\n\t" + "ldr r5, [%[b], #248]\n\t" + "ldr r7, [%[b], #252]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #248]\n\t" + "str r6, [%[r], #252]\n\t" + "ldr r4, [%[a], #256]\n\t" + "ldr r6, [%[a], #260]\n\t" + "ldr r5, [%[b], #256]\n\t" + "ldr r7, [%[b], #260]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #256]\n\t" + "str r6, [%[r], #260]\n\t" + "ldr r4, [%[a], #264]\n\t" + "ldr r6, [%[a], #268]\n\t" + "ldr r5, [%[b], #264]\n\t" + "ldr r7, [%[b], #268]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #264]\n\t" + "str r6, [%[r], #268]\n\t" + "ldr r4, [%[a], #272]\n\t" + "ldr r6, [%[a], #276]\n\t" + "ldr r5, [%[b], #272]\n\t" + "ldr r7, [%[b], #276]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #272]\n\t" + "str r6, [%[r], #276]\n\t" + "ldr r4, [%[a], #280]\n\t" + "ldr r6, [%[a], #284]\n\t" + "ldr r5, [%[b], #280]\n\t" + "ldr r7, [%[b], #284]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #280]\n\t" + "str r6, [%[r], #284]\n\t" + "ldr r4, [%[a], #288]\n\t" + "ldr r6, [%[a], #292]\n\t" + "ldr r5, [%[b], #288]\n\t" + "ldr r7, [%[b], #292]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #288]\n\t" + "str r6, [%[r], #292]\n\t" + "ldr r4, [%[a], #296]\n\t" + "ldr r6, [%[a], #300]\n\t" + "ldr r5, [%[b], #296]\n\t" + "ldr r7, [%[b], #300]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #296]\n\t" + "str r6, [%[r], #300]\n\t" + "ldr r4, [%[a], #304]\n\t" + "ldr r6, [%[a], #308]\n\t" + "ldr r5, [%[b], #304]\n\t" + "ldr r7, [%[b], #308]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #304]\n\t" + "str r6, [%[r], #308]\n\t" + "ldr r4, [%[a], #312]\n\t" + "ldr r6, [%[a], #316]\n\t" + "ldr r5, [%[b], #312]\n\t" + "ldr r7, [%[b], #316]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #312]\n\t" + "str r6, [%[r], #316]\n\t" + "ldr r4, [%[a], #320]\n\t" + "ldr r6, [%[a], #324]\n\t" + "ldr r5, [%[b], #320]\n\t" + "ldr r7, [%[b], #324]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #320]\n\t" + "str r6, [%[r], #324]\n\t" + "ldr r4, [%[a], #328]\n\t" + "ldr r6, [%[a], #332]\n\t" + "ldr r5, [%[b], #328]\n\t" + "ldr r7, [%[b], #332]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #328]\n\t" + "str r6, [%[r], #332]\n\t" + "ldr r4, [%[a], #336]\n\t" + "ldr r6, [%[a], #340]\n\t" + "ldr r5, [%[b], #336]\n\t" + "ldr r7, [%[b], #340]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #336]\n\t" + "str r6, [%[r], #340]\n\t" + "ldr r4, [%[a], #344]\n\t" + "ldr r6, [%[a], #348]\n\t" + "ldr r5, [%[b], #344]\n\t" + "ldr r7, [%[b], #348]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #344]\n\t" + "str r6, [%[r], #348]\n\t" + "ldr r4, [%[a], #352]\n\t" + "ldr r6, [%[a], #356]\n\t" + "ldr r5, [%[b], #352]\n\t" + "ldr r7, [%[b], #356]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #352]\n\t" + "str r6, [%[r], #356]\n\t" + "ldr r4, [%[a], #360]\n\t" + "ldr r6, [%[a], #364]\n\t" + "ldr r5, [%[b], #360]\n\t" + "ldr r7, [%[b], #364]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #360]\n\t" + "str r6, [%[r], #364]\n\t" + "ldr r4, [%[a], #368]\n\t" + "ldr r6, [%[a], #372]\n\t" + "ldr r5, [%[b], #368]\n\t" + "ldr r7, [%[b], #372]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #368]\n\t" + "str r6, [%[r], #372]\n\t" + "ldr r4, [%[a], #376]\n\t" + "ldr r6, [%[a], #380]\n\t" + "ldr r5, [%[b], #376]\n\t" + "ldr r7, [%[b], #380]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #376]\n\t" + "str r6, [%[r], #380]\n\t" + "ldr r4, [%[a], #384]\n\t" + "ldr r6, [%[a], #388]\n\t" + "ldr r5, [%[b], #384]\n\t" + "ldr r7, [%[b], #388]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #384]\n\t" + "str r6, [%[r], #388]\n\t" + "ldr r4, [%[a], #392]\n\t" + "ldr r6, [%[a], #396]\n\t" + "ldr r5, [%[b], #392]\n\t" + "ldr r7, [%[b], #396]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #392]\n\t" + "str r6, [%[r], #396]\n\t" + "ldr r4, [%[a], #400]\n\t" + "ldr r6, [%[a], #404]\n\t" + "ldr r5, [%[b], #400]\n\t" + "ldr r7, [%[b], #404]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #400]\n\t" + "str r6, [%[r], #404]\n\t" + "ldr r4, [%[a], #408]\n\t" + "ldr r6, [%[a], #412]\n\t" + "ldr r5, [%[b], #408]\n\t" + "ldr r7, [%[b], #412]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #408]\n\t" + "str r6, [%[r], #412]\n\t" + "ldr r4, [%[a], #416]\n\t" + "ldr r6, [%[a], #420]\n\t" + "ldr r5, [%[b], #416]\n\t" + "ldr r7, [%[b], #420]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #416]\n\t" + "str r6, [%[r], #420]\n\t" + "ldr r4, [%[a], #424]\n\t" + "ldr r6, [%[a], #428]\n\t" + "ldr r5, [%[b], #424]\n\t" + "ldr r7, [%[b], #428]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #424]\n\t" + "str r6, [%[r], #428]\n\t" + "ldr r4, [%[a], #432]\n\t" + "ldr r6, [%[a], #436]\n\t" + "ldr r5, [%[b], #432]\n\t" + "ldr r7, [%[b], #436]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #432]\n\t" + "str r6, [%[r], #436]\n\t" + "ldr r4, [%[a], #440]\n\t" + "ldr r6, [%[a], #444]\n\t" + "ldr r5, [%[b], #440]\n\t" + "ldr r7, [%[b], #444]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #440]\n\t" + "str r6, [%[r], #444]\n\t" + "ldr r4, [%[a], #448]\n\t" + "ldr r6, [%[a], #452]\n\t" + "ldr r5, [%[b], #448]\n\t" + "ldr r7, [%[b], #452]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #448]\n\t" + "str r6, [%[r], #452]\n\t" + "ldr r4, [%[a], #456]\n\t" + "ldr r6, [%[a], #460]\n\t" + "ldr r5, [%[b], #456]\n\t" + "ldr r7, [%[b], #460]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #456]\n\t" + "str r6, [%[r], #460]\n\t" + "ldr r4, [%[a], #464]\n\t" + "ldr r6, [%[a], #468]\n\t" + "ldr r5, [%[b], #464]\n\t" + "ldr r7, [%[b], #468]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #464]\n\t" + "str r6, [%[r], #468]\n\t" + "ldr r4, [%[a], #472]\n\t" + "ldr r6, [%[a], #476]\n\t" + "ldr r5, [%[b], #472]\n\t" + "ldr r7, [%[b], #476]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #472]\n\t" + "str r6, [%[r], #476]\n\t" + "ldr r4, [%[a], #480]\n\t" + "ldr r6, [%[a], #484]\n\t" + "ldr r5, [%[b], #480]\n\t" + "ldr r7, [%[b], #484]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #480]\n\t" + "str r6, [%[r], #484]\n\t" + "ldr r4, [%[a], #488]\n\t" + "ldr r6, [%[a], #492]\n\t" + "ldr r5, [%[b], #488]\n\t" + "ldr r7, [%[b], #492]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #488]\n\t" + "str r6, [%[r], #492]\n\t" + "ldr r4, [%[a], #496]\n\t" + "ldr r6, [%[a], #500]\n\t" + "ldr r5, [%[b], #496]\n\t" + "ldr r7, [%[b], #500]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #496]\n\t" + "str r6, [%[r], #500]\n\t" + "ldr r4, [%[a], #504]\n\t" + "ldr r6, [%[a], #508]\n\t" + "ldr r5, [%[b], #504]\n\t" + "ldr r7, [%[b], #508]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #504]\n\t" + "str r6, [%[r], #508]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* Reduce the number back to 4096 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_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r7, [%[m], #0]\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr r7, [%[m], #32]\n\t" + "ldr r9, [%[a], #32]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #32]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr r7, [%[m], #36]\n\t" + "ldr r9, [%[a], #36]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #36]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr r7, [%[m], #40]\n\t" + "ldr r9, [%[a], #40]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #40]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr r7, [%[m], #44]\n\t" + "ldr r9, [%[a], #44]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #44]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr r7, [%[m], #48]\n\t" + "ldr r9, [%[a], #48]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #48]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr r7, [%[m], #52]\n\t" + "ldr r9, [%[a], #52]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #52]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr r7, [%[m], #56]\n\t" + "ldr r9, [%[a], #56]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #56]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr r7, [%[m], #60]\n\t" + "ldr r9, [%[a], #60]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #60]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr r7, [%[m], #64]\n\t" + "ldr r9, [%[a], #64]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #64]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr r7, [%[m], #68]\n\t" + "ldr r9, [%[a], #68]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #68]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr r7, [%[m], #72]\n\t" + "ldr r9, [%[a], #72]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #72]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr r7, [%[m], #76]\n\t" + "ldr r9, [%[a], #76]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #76]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr r7, [%[m], #80]\n\t" + "ldr r9, [%[a], #80]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #80]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr r7, [%[m], #84]\n\t" + "ldr r9, [%[a], #84]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #84]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr r7, [%[m], #88]\n\t" + "ldr r9, [%[a], #88]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #88]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr r7, [%[m], #92]\n\t" + "ldr r9, [%[a], #92]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #92]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr r7, [%[m], #96]\n\t" + "ldr r9, [%[a], #96]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #96]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr r7, [%[m], #100]\n\t" + "ldr r9, [%[a], #100]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #100]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr r7, [%[m], #104]\n\t" + "ldr r9, [%[a], #104]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #104]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr r7, [%[m], #108]\n\t" + "ldr r9, [%[a], #108]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #108]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr r7, [%[m], #112]\n\t" + "ldr r9, [%[a], #112]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #112]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr r7, [%[m], #116]\n\t" + "ldr r9, [%[a], #116]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #116]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr r7, [%[m], #120]\n\t" + "ldr r9, [%[a], #120]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #120]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr r7, [%[m], #124]\n\t" + "ldr r9, [%[a], #124]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #124]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+32] += m[32] * mu\n\t" + "ldr r7, [%[m], #128]\n\t" + "ldr r9, [%[a], #128]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #128]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+33] += m[33] * mu\n\t" + "ldr r7, [%[m], #132]\n\t" + "ldr r9, [%[a], #132]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #132]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+34] += m[34] * mu\n\t" + "ldr r7, [%[m], #136]\n\t" + "ldr r9, [%[a], #136]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #136]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+35] += m[35] * mu\n\t" + "ldr r7, [%[m], #140]\n\t" + "ldr r9, [%[a], #140]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #140]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+36] += m[36] * mu\n\t" + "ldr r7, [%[m], #144]\n\t" + "ldr r9, [%[a], #144]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #144]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+37] += m[37] * mu\n\t" + "ldr r7, [%[m], #148]\n\t" + "ldr r9, [%[a], #148]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #148]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+38] += m[38] * mu\n\t" + "ldr r7, [%[m], #152]\n\t" + "ldr r9, [%[a], #152]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #152]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+39] += m[39] * mu\n\t" + "ldr r7, [%[m], #156]\n\t" + "ldr r9, [%[a], #156]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #156]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+40] += m[40] * mu\n\t" + "ldr r7, [%[m], #160]\n\t" + "ldr r9, [%[a], #160]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #160]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+41] += m[41] * mu\n\t" + "ldr r7, [%[m], #164]\n\t" + "ldr r9, [%[a], #164]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #164]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+42] += m[42] * mu\n\t" + "ldr r7, [%[m], #168]\n\t" + "ldr r9, [%[a], #168]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #168]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+43] += m[43] * mu\n\t" + "ldr r7, [%[m], #172]\n\t" + "ldr r9, [%[a], #172]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #172]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+44] += m[44] * mu\n\t" + "ldr r7, [%[m], #176]\n\t" + "ldr r9, [%[a], #176]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #176]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+45] += m[45] * mu\n\t" + "ldr r7, [%[m], #180]\n\t" + "ldr r9, [%[a], #180]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #180]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+46] += m[46] * mu\n\t" + "ldr r7, [%[m], #184]\n\t" + "ldr r9, [%[a], #184]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #184]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+47] += m[47] * mu\n\t" + "ldr r7, [%[m], #188]\n\t" + "ldr r9, [%[a], #188]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #188]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+48] += m[48] * mu\n\t" + "ldr r7, [%[m], #192]\n\t" + "ldr r9, [%[a], #192]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #192]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+49] += m[49] * mu\n\t" + "ldr r7, [%[m], #196]\n\t" + "ldr r9, [%[a], #196]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #196]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+50] += m[50] * mu\n\t" + "ldr r7, [%[m], #200]\n\t" + "ldr r9, [%[a], #200]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #200]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+51] += m[51] * mu\n\t" + "ldr r7, [%[m], #204]\n\t" + "ldr r9, [%[a], #204]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #204]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+52] += m[52] * mu\n\t" + "ldr r7, [%[m], #208]\n\t" + "ldr r9, [%[a], #208]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #208]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+53] += m[53] * mu\n\t" + "ldr r7, [%[m], #212]\n\t" + "ldr r9, [%[a], #212]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #212]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+54] += m[54] * mu\n\t" + "ldr r7, [%[m], #216]\n\t" + "ldr r9, [%[a], #216]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #216]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+55] += m[55] * mu\n\t" + "ldr r7, [%[m], #220]\n\t" + "ldr r9, [%[a], #220]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #220]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+56] += m[56] * mu\n\t" + "ldr r7, [%[m], #224]\n\t" + "ldr r9, [%[a], #224]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #224]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+57] += m[57] * mu\n\t" + "ldr r7, [%[m], #228]\n\t" + "ldr r9, [%[a], #228]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #228]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+58] += m[58] * mu\n\t" + "ldr r7, [%[m], #232]\n\t" + "ldr r9, [%[a], #232]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #232]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+59] += m[59] * mu\n\t" + "ldr r7, [%[m], #236]\n\t" + "ldr r9, [%[a], #236]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #236]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+60] += m[60] * mu\n\t" + "ldr r7, [%[m], #240]\n\t" + "ldr r9, [%[a], #240]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #240]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+61] += m[61] * mu\n\t" + "ldr r7, [%[m], #244]\n\t" + "ldr r9, [%[a], #244]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #244]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+62] += m[62] * mu\n\t" + "ldr r7, [%[m], #248]\n\t" + "ldr r9, [%[a], #248]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #248]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+63] += m[63] * mu\n\t" + "ldr r7, [%[m], #252]\n\t" + "ldr r9, [%[a], #252]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #252]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+64] += m[64] * mu\n\t" + "ldr r7, [%[m], #256]\n\t" + "ldr r9, [%[a], #256]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #256]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+65] += m[65] * mu\n\t" + "ldr r7, [%[m], #260]\n\t" + "ldr r9, [%[a], #260]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #260]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+66] += m[66] * mu\n\t" + "ldr r7, [%[m], #264]\n\t" + "ldr r9, [%[a], #264]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #264]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+67] += m[67] * mu\n\t" + "ldr r7, [%[m], #268]\n\t" + "ldr r9, [%[a], #268]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #268]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+68] += m[68] * mu\n\t" + "ldr r7, [%[m], #272]\n\t" + "ldr r9, [%[a], #272]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #272]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+69] += m[69] * mu\n\t" + "ldr r7, [%[m], #276]\n\t" + "ldr r9, [%[a], #276]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #276]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+70] += m[70] * mu\n\t" + "ldr r7, [%[m], #280]\n\t" + "ldr r9, [%[a], #280]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #280]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+71] += m[71] * mu\n\t" + "ldr r7, [%[m], #284]\n\t" + "ldr r9, [%[a], #284]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #284]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+72] += m[72] * mu\n\t" + "ldr r7, [%[m], #288]\n\t" + "ldr r9, [%[a], #288]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #288]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+73] += m[73] * mu\n\t" + "ldr r7, [%[m], #292]\n\t" + "ldr r9, [%[a], #292]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #292]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+74] += m[74] * mu\n\t" + "ldr r7, [%[m], #296]\n\t" + "ldr r9, [%[a], #296]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #296]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+75] += m[75] * mu\n\t" + "ldr r7, [%[m], #300]\n\t" + "ldr r9, [%[a], #300]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #300]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+76] += m[76] * mu\n\t" + "ldr r7, [%[m], #304]\n\t" + "ldr r9, [%[a], #304]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #304]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+77] += m[77] * mu\n\t" + "ldr r7, [%[m], #308]\n\t" + "ldr r9, [%[a], #308]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #308]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+78] += m[78] * mu\n\t" + "ldr r7, [%[m], #312]\n\t" + "ldr r9, [%[a], #312]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #312]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+79] += m[79] * mu\n\t" + "ldr r7, [%[m], #316]\n\t" + "ldr r9, [%[a], #316]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #316]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+80] += m[80] * mu\n\t" + "ldr r7, [%[m], #320]\n\t" + "ldr r9, [%[a], #320]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #320]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+81] += m[81] * mu\n\t" + "ldr r7, [%[m], #324]\n\t" + "ldr r9, [%[a], #324]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #324]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+82] += m[82] * mu\n\t" + "ldr r7, [%[m], #328]\n\t" + "ldr r9, [%[a], #328]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #328]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+83] += m[83] * mu\n\t" + "ldr r7, [%[m], #332]\n\t" + "ldr r9, [%[a], #332]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #332]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+84] += m[84] * mu\n\t" + "ldr r7, [%[m], #336]\n\t" + "ldr r9, [%[a], #336]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #336]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+85] += m[85] * mu\n\t" + "ldr r7, [%[m], #340]\n\t" + "ldr r9, [%[a], #340]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #340]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+86] += m[86] * mu\n\t" + "ldr r7, [%[m], #344]\n\t" + "ldr r9, [%[a], #344]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #344]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+87] += m[87] * mu\n\t" + "ldr r7, [%[m], #348]\n\t" + "ldr r9, [%[a], #348]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #348]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+88] += m[88] * mu\n\t" + "ldr r7, [%[m], #352]\n\t" + "ldr r9, [%[a], #352]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #352]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+89] += m[89] * mu\n\t" + "ldr r7, [%[m], #356]\n\t" + "ldr r9, [%[a], #356]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #356]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+90] += m[90] * mu\n\t" + "ldr r7, [%[m], #360]\n\t" + "ldr r9, [%[a], #360]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #360]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+91] += m[91] * mu\n\t" + "ldr r7, [%[m], #364]\n\t" + "ldr r9, [%[a], #364]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #364]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+92] += m[92] * mu\n\t" + "ldr r7, [%[m], #368]\n\t" + "ldr r9, [%[a], #368]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #368]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+93] += m[93] * mu\n\t" + "ldr r7, [%[m], #372]\n\t" + "ldr r9, [%[a], #372]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #372]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+94] += m[94] * mu\n\t" + "ldr r7, [%[m], #376]\n\t" + "ldr r9, [%[a], #376]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #376]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+95] += m[95] * mu\n\t" + "ldr r7, [%[m], #380]\n\t" + "ldr r9, [%[a], #380]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #380]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+96] += m[96] * mu\n\t" + "ldr r7, [%[m], #384]\n\t" + "ldr r9, [%[a], #384]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #384]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+97] += m[97] * mu\n\t" + "ldr r7, [%[m], #388]\n\t" + "ldr r9, [%[a], #388]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #388]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+98] += m[98] * mu\n\t" + "ldr r7, [%[m], #392]\n\t" + "ldr r9, [%[a], #392]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #392]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+99] += m[99] * mu\n\t" + "ldr r7, [%[m], #396]\n\t" + "ldr r9, [%[a], #396]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #396]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+100] += m[100] * mu\n\t" + "ldr r7, [%[m], #400]\n\t" + "ldr r9, [%[a], #400]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #400]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+101] += m[101] * mu\n\t" + "ldr r7, [%[m], #404]\n\t" + "ldr r9, [%[a], #404]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #404]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+102] += m[102] * mu\n\t" + "ldr r7, [%[m], #408]\n\t" + "ldr r9, [%[a], #408]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #408]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+103] += m[103] * mu\n\t" + "ldr r7, [%[m], #412]\n\t" + "ldr r9, [%[a], #412]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #412]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+104] += m[104] * mu\n\t" + "ldr r7, [%[m], #416]\n\t" + "ldr r9, [%[a], #416]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #416]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+105] += m[105] * mu\n\t" + "ldr r7, [%[m], #420]\n\t" + "ldr r9, [%[a], #420]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #420]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+106] += m[106] * mu\n\t" + "ldr r7, [%[m], #424]\n\t" + "ldr r9, [%[a], #424]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #424]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+107] += m[107] * mu\n\t" + "ldr r7, [%[m], #428]\n\t" + "ldr r9, [%[a], #428]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #428]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+108] += m[108] * mu\n\t" + "ldr r7, [%[m], #432]\n\t" + "ldr r9, [%[a], #432]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #432]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+109] += m[109] * mu\n\t" + "ldr r7, [%[m], #436]\n\t" + "ldr r9, [%[a], #436]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #436]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+110] += m[110] * mu\n\t" + "ldr r7, [%[m], #440]\n\t" + "ldr r9, [%[a], #440]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #440]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+111] += m[111] * mu\n\t" + "ldr r7, [%[m], #444]\n\t" + "ldr r9, [%[a], #444]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #444]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+112] += m[112] * mu\n\t" + "ldr r7, [%[m], #448]\n\t" + "ldr r9, [%[a], #448]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #448]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+113] += m[113] * mu\n\t" + "ldr r7, [%[m], #452]\n\t" + "ldr r9, [%[a], #452]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #452]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+114] += m[114] * mu\n\t" + "ldr r7, [%[m], #456]\n\t" + "ldr r9, [%[a], #456]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #456]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+115] += m[115] * mu\n\t" + "ldr r7, [%[m], #460]\n\t" + "ldr r9, [%[a], #460]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #460]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+116] += m[116] * mu\n\t" + "ldr r7, [%[m], #464]\n\t" + "ldr r9, [%[a], #464]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #464]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+117] += m[117] * mu\n\t" + "ldr r7, [%[m], #468]\n\t" + "ldr r9, [%[a], #468]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #468]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+118] += m[118] * mu\n\t" + "ldr r7, [%[m], #472]\n\t" + "ldr r9, [%[a], #472]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #472]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+119] += m[119] * mu\n\t" + "ldr r7, [%[m], #476]\n\t" + "ldr r9, [%[a], #476]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #476]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+120] += m[120] * mu\n\t" + "ldr r7, [%[m], #480]\n\t" + "ldr r9, [%[a], #480]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #480]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+121] += m[121] * mu\n\t" + "ldr r7, [%[m], #484]\n\t" + "ldr r9, [%[a], #484]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #484]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+122] += m[122] * mu\n\t" + "ldr r7, [%[m], #488]\n\t" + "ldr r9, [%[a], #488]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #488]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+123] += m[123] * mu\n\t" + "ldr r7, [%[m], #492]\n\t" + "ldr r9, [%[a], #492]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #492]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+124] += m[124] * mu\n\t" + "ldr r7, [%[m], #496]\n\t" + "ldr r9, [%[a], #496]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #496]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+125] += m[125] * mu\n\t" + "ldr r7, [%[m], #500]\n\t" + "ldr r9, [%[a], #500]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #500]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+126] += m[126] * mu\n\t" + "ldr r7, [%[m], #504]\n\t" + "ldr r9, [%[a], #504]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #504]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+127] += m[127] * mu\n\t" + "ldr r7, [%[m], #508]\n\t" + "ldr r9, [%[a], #508]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #508]\n\t" + "ldr r9, [%[a], #512]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #512]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #512\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + sp_4096_cond_sub_128(a - 128, 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_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_4096_mul_128(r, a, b); + sp_4096_mont_reduce_128(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_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_4096_sqr_128(r, a); + sp_4096_mont_reduce_128(r, m, mp); +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_4096_word_128(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + 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_4096_mask_128(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<128; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 128; 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 int32_t sp_4096_cmp_128(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #508\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "subs r6, r6, #4\n\t" + "bcs 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #508]\n\t" + "ldr r5, [%[b], #508]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #504]\n\t" + "ldr r5, [%[b], #504]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #500]\n\t" + "ldr r5, [%[b], #500]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #496]\n\t" + "ldr r5, [%[b], #496]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #492]\n\t" + "ldr r5, [%[b], #492]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #488]\n\t" + "ldr r5, [%[b], #488]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #484]\n\t" + "ldr r5, [%[b], #484]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #480]\n\t" + "ldr r5, [%[b], #480]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #476]\n\t" + "ldr r5, [%[b], #476]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #472]\n\t" + "ldr r5, [%[b], #472]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #468]\n\t" + "ldr r5, [%[b], #468]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #464]\n\t" + "ldr r5, [%[b], #464]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #460]\n\t" + "ldr r5, [%[b], #460]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #456]\n\t" + "ldr r5, [%[b], #456]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #452]\n\t" + "ldr r5, [%[b], #452]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #448]\n\t" + "ldr r5, [%[b], #448]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #444]\n\t" + "ldr r5, [%[b], #444]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #440]\n\t" + "ldr r5, [%[b], #440]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #436]\n\t" + "ldr r5, [%[b], #436]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #432]\n\t" + "ldr r5, [%[b], #432]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #428]\n\t" + "ldr r5, [%[b], #428]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #424]\n\t" + "ldr r5, [%[b], #424]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #420]\n\t" + "ldr r5, [%[b], #420]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #416]\n\t" + "ldr r5, [%[b], #416]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #412]\n\t" + "ldr r5, [%[b], #412]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #408]\n\t" + "ldr r5, [%[b], #408]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #404]\n\t" + "ldr r5, [%[b], #404]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #400]\n\t" + "ldr r5, [%[b], #400]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #396]\n\t" + "ldr r5, [%[b], #396]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #392]\n\t" + "ldr r5, [%[b], #392]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #388]\n\t" + "ldr r5, [%[b], #388]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #384]\n\t" + "ldr r5, [%[b], #384]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #380]\n\t" + "ldr r5, [%[b], #380]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #376]\n\t" + "ldr r5, [%[b], #376]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #372]\n\t" + "ldr r5, [%[b], #372]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #368]\n\t" + "ldr r5, [%[b], #368]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #364]\n\t" + "ldr r5, [%[b], #364]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #360]\n\t" + "ldr r5, [%[b], #360]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #356]\n\t" + "ldr r5, [%[b], #356]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #352]\n\t" + "ldr r5, [%[b], #352]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #348]\n\t" + "ldr r5, [%[b], #348]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #344]\n\t" + "ldr r5, [%[b], #344]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #340]\n\t" + "ldr r5, [%[b], #340]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #336]\n\t" + "ldr r5, [%[b], #336]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #332]\n\t" + "ldr r5, [%[b], #332]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #328]\n\t" + "ldr r5, [%[b], #328]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #324]\n\t" + "ldr r5, [%[b], #324]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #320]\n\t" + "ldr r5, [%[b], #320]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #316]\n\t" + "ldr r5, [%[b], #316]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #312]\n\t" + "ldr r5, [%[b], #312]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #308]\n\t" + "ldr r5, [%[b], #308]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #304]\n\t" + "ldr r5, [%[b], #304]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #300]\n\t" + "ldr r5, [%[b], #300]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #296]\n\t" + "ldr r5, [%[b], #296]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #292]\n\t" + "ldr r5, [%[b], #292]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #288]\n\t" + "ldr r5, [%[b], #288]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #284]\n\t" + "ldr r5, [%[b], #284]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #280]\n\t" + "ldr r5, [%[b], #280]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #276]\n\t" + "ldr r5, [%[b], #276]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #272]\n\t" + "ldr r5, [%[b], #272]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #268]\n\t" + "ldr r5, [%[b], #268]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #264]\n\t" + "ldr r5, [%[b], #264]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #260]\n\t" + "ldr r5, [%[b], #260]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #256]\n\t" + "ldr r5, [%[b], #256]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #252]\n\t" + "ldr r5, [%[b], #252]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r5, [%[b], #248]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #244]\n\t" + "ldr r5, [%[b], #244]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r5, [%[b], #240]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #236]\n\t" + "ldr r5, [%[b], #236]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r5, [%[b], #232]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #228]\n\t" + "ldr r5, [%[b], #228]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r5, [%[b], #224]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #220]\n\t" + "ldr r5, [%[b], #220]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r5, [%[b], #216]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #212]\n\t" + "ldr r5, [%[b], #212]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r5, [%[b], #208]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #204]\n\t" + "ldr r5, [%[b], #204]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r5, [%[b], #200]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #196]\n\t" + "ldr r5, [%[b], #196]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r5, [%[b], #192]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #188]\n\t" + "ldr r5, [%[b], #188]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[b], #184]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #180]\n\t" + "ldr r5, [%[b], #180]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[b], #176]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #172]\n\t" + "ldr r5, [%[b], #172]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[b], #168]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #164]\n\t" + "ldr r5, [%[b], #164]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[b], #160]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #156]\n\t" + "ldr r5, [%[b], #156]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[b], #152]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #148]\n\t" + "ldr r5, [%[b], #148]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[b], #144]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #140]\n\t" + "ldr r5, [%[b], #140]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[b], #136]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #132]\n\t" + "ldr r5, [%[b], #132]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[b], #128]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + 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 WC_INLINE int sp_4096_div_128(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[256], t2[129]; + sp_digit div, r1; + int i; + + (void)m; + + + div = d[127]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 128); + for (i=127; i>=0; i--) { + r1 = div_4096_word_128(t1[128 + i], t1[128 + i - 1], div); + + sp_4096_mul_d_128(t2, d, r1); + t1[128 + i] += sp_4096_sub_in_place_128(&t1[i], t2); + t1[128 + i] -= t2[128]; + sp_4096_mask_128(t2, d, t1[128 + i]); + t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], t2); + sp_4096_mask_128(t2, d, t1[128 + i]); + t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], t2); + } + + r1 = sp_4096_cmp_128(t1, d) >= 0; + sp_4096_cond_sub_128(r, t1, d, (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 WC_INLINE int sp_4096_mod_128(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_128(a, m, NULL, r); +} + +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +/* 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 WC_INLINE int sp_4096_div_128_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[256], t2[129]; + sp_digit div, r1; + int i; + + (void)m; + + + div = d[127]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 128); + for (i=127; i>=0; i--) { + r1 = div_4096_word_128(t1[128 + i], t1[128 + i - 1], div); + + sp_4096_mul_d_128(t2, d, r1); + t1[128 + i] += sp_4096_sub_in_place_128(&t1[i], t2); + t1[128 + i] -= t2[128]; + if (t1[128 + i] != 0) { + t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], d); + if (t1[128 + i] != 0) + t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], d); + } + } + + r1 = sp_4096_cmp_128(t1, d) >= 0; + sp_4096_cond_sub_128(r, t1, d, (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 WC_INLINE int sp_4096_mod_128_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_128_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* 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_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][256]; +#else + sp_digit* t[16]; + 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) * 16 * 256, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 256; + } +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_128(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 128U); + if (reduceA != 0) { + err = sp_4096_mod_128(t[1] + 128, a, m); + if (err == MP_OKAY) { + err = sp_4096_mod_128(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 128, a, sizeof(sp_digit) * 128); + err = sp_4096_mod_128(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_128(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_128(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_128(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_128(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_128(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_128(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_128(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_128(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_128(t[10], t[ 5], m, mp); + sp_4096_mont_mul_128(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_128(t[12], t[ 6], m, mp); + sp_4096_mont_mul_128(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_128(t[14], t[ 7], m, mp); + sp_4096_mont_mul_128(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 128); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + + sp_4096_mont_mul_128(r, r, t[y], m, mp); + } + + XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U); + sp_4096_mont_reduce_128(r, m, mp); + + mask = 0 - (sp_4096_cmp_128(r, m) >= 0); + sp_4096_cond_sub_128(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#else +/* 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_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][256]; +#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 * 256, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 256; + } +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_128(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 128U); + if (reduceA != 0) { + err = sp_4096_mod_128(t[1] + 128, a, m); + if (err == MP_OKAY) { + err = sp_4096_mod_128(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 128, a, sizeof(sp_digit) * 128); + err = sp_4096_mod_128(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_128(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_128(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_128(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_128(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_128(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_128(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_128(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_128(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_128(t[10], t[ 5], m, mp); + sp_4096_mont_mul_128(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_128(t[12], t[ 6], m, mp); + sp_4096_mont_mul_128(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_128(t[14], t[ 7], m, mp); + sp_4096_mont_mul_128(t[15], t[ 8], t[ 7], m, mp); + sp_4096_mont_sqr_128(t[16], t[ 8], m, mp); + sp_4096_mont_mul_128(t[17], t[ 9], t[ 8], m, mp); + sp_4096_mont_sqr_128(t[18], t[ 9], m, mp); + sp_4096_mont_mul_128(t[19], t[10], t[ 9], m, mp); + sp_4096_mont_sqr_128(t[20], t[10], m, mp); + sp_4096_mont_mul_128(t[21], t[11], t[10], m, mp); + sp_4096_mont_sqr_128(t[22], t[11], m, mp); + sp_4096_mont_mul_128(t[23], t[12], t[11], m, mp); + sp_4096_mont_sqr_128(t[24], t[12], m, mp); + sp_4096_mont_mul_128(t[25], t[13], t[12], m, mp); + sp_4096_mont_sqr_128(t[26], t[13], m, mp); + sp_4096_mont_mul_128(t[27], t[14], t[13], m, mp); + sp_4096_mont_sqr_128(t[28], t[14], m, mp); + sp_4096_mont_mul_128(t[29], t[15], t[14], m, mp); + sp_4096_mont_sqr_128(t[30], t[15], m, mp); + sp_4096_mont_mul_128(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 128); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + + sp_4096_mont_mul_128(r, r, t[y], m, mp); + } + + XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U); + sp_4096_mont_reduce_128(r, m, mp); + + mask = 0 - (sp_4096_cmp_128(r, m) >= 0); + sp_4096_cond_sub_128(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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 512 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_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[256], m[128], r[256]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; +#endif + sp_digit *ah; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 512) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 512 || + mp_count_bits(mm) != 4096)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 128 * 2; + m = r + 128 * 2; + } +#endif + + if (err == MP_OKAY) { + ah = a + 128; + + sp_4096_from_bin(ah, 128, in, inLen); +#if DIGIT_BIT >= 32 + 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_4096_from_mp(m, 128, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_4096_sqr_128(r, ah); + err = sp_4096_mod_128_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_4096_mul_128(r, ah, r); + err = sp_4096_mod_128_cond(r, r, m); + } + } + else { + int i; + sp_digit mp; + + sp_4096_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 128); + err = sp_4096_mod_128_cond(a, a, m); + + if (err == MP_OKAY) { + for (i = 31; i >= 0; i--) { + if (e[0] >> i) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 128); + for (i--; i>=0; i--) { + sp_4096_mont_sqr_128(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) { + sp_4096_mont_mul_128(r, r, a, m, mp); + } + } + XMEMSET(&r[128], 0, sizeof(sp_digit) * 128); + sp_4096_mont_reduce_128(r, m, mp); + + for (i = 127; i > 0; i--) { + if (r[i] != m[i]) { + break; + } + } + if (r[i] >= m[i]) { + sp_4096_sub_in_place_128(r, m); + } + } + } + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) + 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 < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 4096) { + err = MP_READ_E; + } + if (inLen > 512) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 128; + m = a + 256; + r = a; + + sp_4096_from_bin(a, 128, in, inLen); + sp_4096_from_mp(d, 128, dm); + sp_4096_from_mp(m, 128, mm); + err = sp_4096_mod_exp_128(r, a, d, 4096, m, 0); + } + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 128); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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 sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #256\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adds r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r6, [%[a], #132]\n\t" + "ldr r5, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #128]\n\t" + "str r6, [%[r], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r6, [%[a], #140]\n\t" + "ldr r5, [%[b], #136]\n\t" + "ldr r7, [%[b], #140]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #136]\n\t" + "str r6, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r6, [%[a], #148]\n\t" + "ldr r5, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #144]\n\t" + "str r6, [%[r], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r6, [%[a], #156]\n\t" + "ldr r5, [%[b], #152]\n\t" + "ldr r7, [%[b], #156]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #152]\n\t" + "str r6, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r6, [%[a], #164]\n\t" + "ldr r5, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #160]\n\t" + "str r6, [%[r], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r6, [%[a], #172]\n\t" + "ldr r5, [%[b], #168]\n\t" + "ldr r7, [%[b], #172]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #168]\n\t" + "str r6, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r6, [%[a], #180]\n\t" + "ldr r5, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #176]\n\t" + "str r6, [%[r], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r6, [%[a], #188]\n\t" + "ldr r5, [%[b], #184]\n\t" + "ldr r7, [%[b], #188]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #184]\n\t" + "str r6, [%[r], #188]\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r6, [%[a], #196]\n\t" + "ldr r5, [%[b], #192]\n\t" + "ldr r7, [%[b], #196]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #192]\n\t" + "str r6, [%[r], #196]\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r6, [%[a], #204]\n\t" + "ldr r5, [%[b], #200]\n\t" + "ldr r7, [%[b], #204]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #200]\n\t" + "str r6, [%[r], #204]\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r6, [%[a], #212]\n\t" + "ldr r5, [%[b], #208]\n\t" + "ldr r7, [%[b], #212]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #208]\n\t" + "str r6, [%[r], #212]\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r6, [%[a], #220]\n\t" + "ldr r5, [%[b], #216]\n\t" + "ldr r7, [%[b], #220]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #216]\n\t" + "str r6, [%[r], #220]\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r6, [%[a], #228]\n\t" + "ldr r5, [%[b], #224]\n\t" + "ldr r7, [%[b], #228]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #224]\n\t" + "str r6, [%[r], #228]\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r6, [%[a], #236]\n\t" + "ldr r5, [%[b], #232]\n\t" + "ldr r7, [%[b], #236]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #232]\n\t" + "str r6, [%[r], #236]\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r6, [%[a], #244]\n\t" + "ldr r5, [%[b], #240]\n\t" + "ldr r7, [%[b], #244]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #240]\n\t" + "str r6, [%[r], #244]\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r6, [%[a], #252]\n\t" + "ldr r5, [%[b], #248]\n\t" + "ldr r7, [%[b], #252]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #248]\n\t" + "str r6, [%[r], #252]\n\t" + "adc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* 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 512 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_4096(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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[128 * 2]; + sp_digit p[64], q[64], dp[64]; + sp_digit tmpa[128], tmpb[128]; +#else + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* tmpa; + sp_digit* tmpb; +#endif + sp_digit* r; + sp_digit* qi; + sp_digit* dq; + sp_digit c; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 512) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 512 || mp_count_bits(mm) != 4096)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 128 * 2; + q = p + 64; + qi = dq = dp = q + 64; + tmpa = qi + 64; + tmpb = tmpa + 128; + + r = t + 128; + } +#else +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + r = a; + qi = dq = dp; +#endif + sp_4096_from_bin(a, 128, in, inLen); + sp_4096_from_mp(p, 64, pm); + sp_4096_from_mp(q, 64, qm); + sp_4096_from_mp(dp, 64, dpm); + + err = sp_2048_mod_exp_64(tmpa, a, dp, 2048, p, 1); + } + if (err == MP_OKAY) { + sp_4096_from_mp(dq, 64, dqm); + err = sp_2048_mod_exp_64(tmpb, a, dq, 2048, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_64(tmpa, tmpb); + c += sp_4096_cond_add_64(tmpa, tmpa, p, c); + sp_4096_cond_add_64(tmpa, tmpa, p, c); + + sp_2048_from_mp(qi, 64, qim); + sp_2048_mul_64(tmpa, tmpa, qi); + err = sp_2048_mod_64(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_64(tmpa, q, tmpa); + XMEMSET(&tmpb[64], 0, sizeof(sp_digit) * 64); + sp_4096_add_128(r, tmpb, tmpa); + + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 64 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + 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)); +#endif + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_4096_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 128); + r->used = 128; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 128; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 128; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[256], e[128], m[128]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 128, base); + sp_4096_from_mp(e, 128, exp); + sp_4096_from_mp(m, 128, mod); + + err = sp_4096_mod_exp_128(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_4096_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_4096 +static void sp_4096_lshift_128(sp_digit* r, sp_digit* a, byte n) +{ + __asm__ __volatile__ ( + "mov r6, #31\n\t" + "sub r6, r6, %[n]\n\t" + "ldr r3, [%[a], #508]\n\t" + "lsr r4, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r4, r4, r6\n\t" + "ldr r2, [%[a], #504]\n\t" + "str r4, [%[r], #512]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #500]\n\t" + "str r3, [%[r], #508]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #496]\n\t" + "str r2, [%[r], #504]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #492]\n\t" + "str r4, [%[r], #500]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #488]\n\t" + "str r3, [%[r], #496]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #484]\n\t" + "str r2, [%[r], #492]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #480]\n\t" + "str r4, [%[r], #488]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #476]\n\t" + "str r3, [%[r], #484]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #472]\n\t" + "str r2, [%[r], #480]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #468]\n\t" + "str r4, [%[r], #476]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #464]\n\t" + "str r3, [%[r], #472]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #460]\n\t" + "str r2, [%[r], #468]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #456]\n\t" + "str r4, [%[r], #464]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #452]\n\t" + "str r3, [%[r], #460]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #448]\n\t" + "str r2, [%[r], #456]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #444]\n\t" + "str r4, [%[r], #452]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #440]\n\t" + "str r3, [%[r], #448]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #436]\n\t" + "str r2, [%[r], #444]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #432]\n\t" + "str r4, [%[r], #440]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #428]\n\t" + "str r3, [%[r], #436]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #424]\n\t" + "str r2, [%[r], #432]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #420]\n\t" + "str r4, [%[r], #428]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #416]\n\t" + "str r3, [%[r], #424]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #412]\n\t" + "str r2, [%[r], #420]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #408]\n\t" + "str r4, [%[r], #416]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #404]\n\t" + "str r3, [%[r], #412]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #400]\n\t" + "str r2, [%[r], #408]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #396]\n\t" + "str r4, [%[r], #404]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #392]\n\t" + "str r3, [%[r], #400]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #388]\n\t" + "str r2, [%[r], #396]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #384]\n\t" + "str r4, [%[r], #392]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #380]\n\t" + "str r3, [%[r], #388]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #376]\n\t" + "str r2, [%[r], #384]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #372]\n\t" + "str r4, [%[r], #380]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #368]\n\t" + "str r3, [%[r], #376]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #364]\n\t" + "str r2, [%[r], #372]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #360]\n\t" + "str r4, [%[r], #368]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #356]\n\t" + "str r3, [%[r], #364]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #352]\n\t" + "str r2, [%[r], #360]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #348]\n\t" + "str r4, [%[r], #356]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #344]\n\t" + "str r3, [%[r], #352]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #340]\n\t" + "str r2, [%[r], #348]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #336]\n\t" + "str r4, [%[r], #344]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #332]\n\t" + "str r3, [%[r], #340]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #328]\n\t" + "str r2, [%[r], #336]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #324]\n\t" + "str r4, [%[r], #332]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #320]\n\t" + "str r3, [%[r], #328]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #316]\n\t" + "str r2, [%[r], #324]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #312]\n\t" + "str r4, [%[r], #320]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #308]\n\t" + "str r3, [%[r], #316]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #304]\n\t" + "str r2, [%[r], #312]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #300]\n\t" + "str r4, [%[r], #308]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #296]\n\t" + "str r3, [%[r], #304]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #292]\n\t" + "str r2, [%[r], #300]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #288]\n\t" + "str r4, [%[r], #296]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #284]\n\t" + "str r3, [%[r], #292]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #280]\n\t" + "str r2, [%[r], #288]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #276]\n\t" + "str r4, [%[r], #284]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #272]\n\t" + "str r3, [%[r], #280]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #268]\n\t" + "str r2, [%[r], #276]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #264]\n\t" + "str r4, [%[r], #272]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #260]\n\t" + "str r3, [%[r], #268]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #256]\n\t" + "str r2, [%[r], #264]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #252]\n\t" + "str r4, [%[r], #260]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #248]\n\t" + "str r3, [%[r], #256]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #244]\n\t" + "str r2, [%[r], #252]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #240]\n\t" + "str r4, [%[r], #248]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #236]\n\t" + "str r3, [%[r], #244]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #232]\n\t" + "str r2, [%[r], #240]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #228]\n\t" + "str r4, [%[r], #236]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #224]\n\t" + "str r3, [%[r], #232]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #220]\n\t" + "str r2, [%[r], #228]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #216]\n\t" + "str r4, [%[r], #224]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #212]\n\t" + "str r3, [%[r], #220]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #208]\n\t" + "str r2, [%[r], #216]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #204]\n\t" + "str r4, [%[r], #212]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #200]\n\t" + "str r3, [%[r], #208]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #196]\n\t" + "str r2, [%[r], #204]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #192]\n\t" + "str r4, [%[r], #200]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #188]\n\t" + "str r3, [%[r], #196]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #184]\n\t" + "str r2, [%[r], #192]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #180]\n\t" + "str r4, [%[r], #188]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #176]\n\t" + "str r3, [%[r], #184]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #172]\n\t" + "str r2, [%[r], #180]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #168]\n\t" + "str r4, [%[r], #176]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #164]\n\t" + "str r3, [%[r], #172]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #160]\n\t" + "str r2, [%[r], #168]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #156]\n\t" + "str r4, [%[r], #164]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #152]\n\t" + "str r3, [%[r], #160]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #148]\n\t" + "str r2, [%[r], #156]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #144]\n\t" + "str r4, [%[r], #152]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #140]\n\t" + "str r3, [%[r], #148]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #136]\n\t" + "str r2, [%[r], #144]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #132]\n\t" + "str r4, [%[r], #140]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #128]\n\t" + "str r3, [%[r], #136]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #124]\n\t" + "str r2, [%[r], #132]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #120]\n\t" + "str r4, [%[r], #128]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #116]\n\t" + "str r3, [%[r], #124]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #112]\n\t" + "str r2, [%[r], #120]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #108]\n\t" + "str r4, [%[r], #116]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #104]\n\t" + "str r3, [%[r], #112]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #100]\n\t" + "str r2, [%[r], #108]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #96]\n\t" + "str r4, [%[r], #104]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #92]\n\t" + "str r3, [%[r], #100]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #88]\n\t" + "str r2, [%[r], #96]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #84]\n\t" + "str r4, [%[r], #92]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #80]\n\t" + "str r3, [%[r], #88]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #76]\n\t" + "str r2, [%[r], #84]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #72]\n\t" + "str r4, [%[r], #80]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #68]\n\t" + "str r3, [%[r], #76]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #64]\n\t" + "str r2, [%[r], #72]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "str r2, [%[r]]\n\t" + "str r3, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [n] "r" (n) + : "memory", "r2", "r3", "r4", "r5", "r6" + ); +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[256]; + sp_digit td[129]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 385, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 256; +#else + norm = nd; + tmp = td; +#endif + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_128(norm, m); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + sp_4096_lshift_128(r, norm, y); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + + sp_4096_lshift_128(r, r, y); + sp_4096_mul_d_128(tmp, norm, r[128]); + r[128] = 0; + o = sp_4096_add_128(r, r, tmp); + sp_4096_cond_sub_128(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U); + sp_4096_mont_reduce_128(r, m, mp); + + mask = 0 - (sp_4096_cmp_128(r, m) >= 0); + sp_4096_cond_sub_128(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* HAVE_FFDHE_4096 */ + +/* 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 512 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returns 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_4096(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[256], e[128], m[128]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 512) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 128, base); + sp_4096_from_bin(e, 128, exp, expLen); + sp_4096_from_mp(m, 128, mod); + + #ifdef HAVE_FFDHE_4096 + if (base->used == 1 && base->dp[0] == 2 && m[127] == (sp_digit)-1) + err = sp_4096_mod_exp_2_128(r, e, expLen * 8, m); + else + #endif + err = sp_4096_mod_exp_128(r, b, e, expLen * 8, m, 0); + + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + for (i=0; i<512 && 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_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* WOLFSSL_SP_4096 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point_256 { + sp_digit x[2 * 8]; + sp_digit y[2 * 8]; + sp_digit z[2 * 8]; + int infinity; +} sp_point_256; + +/* The modulus (prime) of the curve P256. */ +static const sp_digit p256_mod[8] = { + 0xffffffff,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000, + 0x00000001,0xffffffff +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static const sp_digit p256_norm_mod[8] = { + 0x00000001,0x00000000,0x00000000,0xffffffff,0xffffffff,0xffffffff, + 0xfffffffe,0x00000000 +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static const sp_digit p256_mp_mod = 0x00000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static const sp_digit p256_order[8] = { + 0xfc632551,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#endif +/* The order of the curve P256 minus 2. */ +static const sp_digit p256_order2[8] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static const sp_digit p256_norm_order[8] = { + 0x039cdaaf,0x0c46353d,0x58e8617b,0x43190552,0x00000000,0x00000000, + 0xffffffff,0x00000000 +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static const sp_digit p256_mp_order = 0xee00bc4f; +#endif +/* The base point of curve P256. */ +static const sp_point_256 p256_base = { + /* X ordinate */ + { + 0xd898c296,0xf4a13945,0x2deb33a0,0x77037d81,0x63a440f2,0xf8bce6e5, + 0xe12c4247,0x6b17d1f2, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x37bf51f5,0xcbb64068,0x6b315ece,0x2bce3357,0x7c0f9e16,0x8ee7eb4a, + 0xfe1a7f9b,0x4fe342e2, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p256_b[8] = { + 0x27d2604b,0x3bce3c3e,0xcc53b0f6,0x651d06b0,0x769886bc,0xb3ebbd55, + 0xaa3a93e7,0x5ac635d8 +}; +#endif + +static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp, sp_point_256** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), &(sp), &(p)) +#endif + + +static void sp_256_point_free_8(sp_point_256* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "sub sp, sp, #24\n\t" + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #20]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[a], #28]\n\t" + "# Clear overflow and underflow\n\t" + "mov r14, #0\n\t" + "mov r12, #0\n\t" + "# t[0] = 1 1 0 -1 -1 -1 -1 0\n\t" + "adds r10, r2, r3\n\t" + "adc r14, r14, #0\n\t" + "subs r10, r10, r5\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r6\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r7\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r8\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[0]\n\t" + "str r10, [sp, #0]\n\t" + "neg r12, r12\n\t" + "mov r10, #0\n\t" + "# t[1] = 0 1 1 0 -1 -1 -1 -1\n\t" + "adds r14, r14, r3\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r10, r10, #0\n\t" + "subs r14, r14, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r6\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r7\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r8\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r9\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[1]\n\t" + "str r14, [sp, #4]\n\t" + "neg r12, r12\n\t" + "mov r14, #0\n\t" + "# t[2] = 0 0 1 1 0 -1 -1 -1\n\t" + "adds r10, r10, r4\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r14, r14, #0\n\t" + "subs r10, r10, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r7\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r8\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r9\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[2]\n\t" + "str r10, [sp, #8]\n\t" + "neg r12, r12\n\t" + "mov r10, #0\n\t" + "# t[3] = -1 -1 0 2 2 1 0 -1\n\t" + "adds r14, r14, r5\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r5\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r6\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r6\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r7\n\t" + "adc r10, r10, #0\n\t" + "subs r14, r14, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r2\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r3\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r9\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[3]\n\t" + "str r14, [sp, #12]\n\t" + "neg r12, r12\n\t" + "mov r14, #0\n\t" + "# t[4] = 0 -1 -1 0 2 2 1 0\n\t" + "adds r10, r10, r6\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r6\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r7\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r7\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r8\n\t" + "adc r14, r14, #0\n\t" + "subs r10, r10, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r3\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r4\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[4]\n\t" + "str r10, [sp, #16]\n\t" + "neg r12, r12\n\t" + "mov r10, #0\n\t" + "# t[5] = 0 0 -1 -1 0 2 2 1\n\t" + "adds r14, r14, r7\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r7\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r8\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r8\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r9\n\t" + "adc r10, r10, #0\n\t" + "subs r14, r14, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r4\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r5\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[5]\n\t" + "str r14, [sp, #20]\n\t" + "neg r12, r12\n\t" + "mov r14, #0\n\t" + "# t[6] = -1 -1 0 0 0 1 3 2\n\t" + "adds r10, r10, r7\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r8\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r8\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r8\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r9\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r9\n\t" + "adc r14, r14, #0\n\t" + "subs r10, r10, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r2\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r3\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[6]\n\t" + "mov r8, r10\n\t" + "neg r12, r12\n\t" + "mov r10, #0\n\t" + "# t[7] = 1 0 -1 -1 -1 -1 0 3\n\t" + "adds r14, r14, r2\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r9\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r9\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r9\n\t" + "adc r10, r10, #0\n\t" + "subs r14, r14, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r4\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r5\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r6\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r7\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[7]\n\t" + "# Load intermediate\n\t" + "ldr r2, [sp, #0]\n\t" + "ldr r3, [sp, #4]\n\t" + "ldr r4, [sp, #8]\n\t" + "ldr r5, [sp, #12]\n\t" + "ldr r6, [sp, #16]\n\t" + "ldr r7, [sp, #20]\n\t" + "neg r12, r12\n\t" + "# Add overflow\n\t" + "# Subtract underflow - add neg underflow\n\t" + "adds r2, r2, r10\n\t" + "adcs r3, r3, #0\n\t" + "adcs r4, r4, #0\n\t" + "adds r5, r5, r12\n\t" + "adcs r6, r6, #0\n\t" + "adcs r7, r7, #0\n\t" + "adcs r8, r8, r12\n\t" + "adc r14, r14, r10\n\t" + "# Subtract overflow\n\t" + "# Add underflow - subtract neg underflow\n\t" + "subs r2, r2, r12\n\t" + "sbcs r3, r3, #0\n\t" + "sbcs r4, r4, #0\n\t" + "subs r5, r5, r10\n\t" + "sbcs r6, r6, #0\n\t" + "sbcs r7, r7, #0\n\t" + "sbcs r8, r8, r10\n\t" + "sbc r14, r14, r12\n\t" + "# Store result\n\t" + "str r2, [%[r], #0]\n\t" + "str r3, [%[r], #4]\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "str r6, [%[r], #16]\n\t" + "str r7, [%[r], #20]\n\t" + "str r8, [%[r], #24]\n\t" + "str r14, [%[r], #28]\n\t" + "add sp, sp, #24\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return MP_OKAY; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_256. + * + * p Point of type sp_point_256 (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_8(sp_point_256* p, const 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, 8, pm->x); + sp_256_from_mp(p->y, 8, pm->y); + sp_256_from_mp(p->z, 8, 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(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 8); + r->used = 8; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 8; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - 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 < 8; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_256 to type ecc_point. + * + * p Point of type sp_point_256. + * 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_8(const sp_point_256* 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; +} + +/* 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_8(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + (void)mp; + (void)m; + + __asm__ __volatile__ ( + "sub sp, sp, #68\n\t" + "mov r5, #0\n\t" + "# A[0] * B[0]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r8, r9, r6, r7\n\t" + "str r8, [sp, #0]\n\t" + "# A[0] * B[1]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adc r10, r4, #0\n\t" + "# A[1] * B[0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, #0\n\t" + "str r9, [sp, #4]\n\t" + "# A[0] * B[2]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adc r14, r4, r14\n\t" + "# A[1] * B[1]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, #0\n\t" + "# A[2] * B[0]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "str r10, [sp, #8]\n\t" + "# A[0] * B[3]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, #0\n\t" + "# A[1] * B[2]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[2] * B[1]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[3] * B[0]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "str r14, [sp, #12]\n\t" + "# A[0] * B[4]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, #0\n\t" + "# A[1] * B[3]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[4] * B[0]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "str r8, [sp, #16]\n\t" + "# A[0] * B[5]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, #0\n\t" + "# A[1] * B[4]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[2] * B[3]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[3] * B[2]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[4] * B[1]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[5] * B[0]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "str r9, [sp, #20]\n\t" + "# A[0] * B[6]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, #0\n\t" + "# A[1] * B[5]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[2] * B[4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[3] * B[3]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[4] * B[2]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[5] * B[1]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[6] * B[0]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "str r10, [sp, #24]\n\t" + "# A[0] * B[7]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, #0\n\t" + "# A[1] * B[6]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[2] * B[5]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[3] * B[4]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[4] * B[3]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[5] * B[2]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[6] * B[1]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[7] * B[0]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "str r14, [sp, #28]\n\t" + "# A[1] * B[7]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, #0\n\t" + "# A[2] * B[6]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[6] * B[2]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[7] * B[1]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "str r8, [sp, #32]\n\t" + "# A[2] * B[7]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, #0\n\t" + "# A[3] * B[6]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[4] * B[5]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[5] * B[4]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[6] * B[3]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[7] * B[2]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "str r9, [sp, #36]\n\t" + "# A[3] * B[7]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, #0\n\t" + "# A[4] * B[6]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[5] * B[5]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[6] * B[4]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[7] * B[3]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "str r10, [sp, #40]\n\t" + "# A[4] * B[7]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, #0\n\t" + "# A[5] * B[6]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[6] * B[5]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[7] * B[4]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "str r14, [sp, #44]\n\t" + "# A[5] * B[7]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, #0\n\t" + "# A[6] * B[6]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[7] * B[5]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[6] * B[7]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, #0\n\t" + "# A[7] * B[6]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[7] * B[7]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adc r14, r4, r14\n\t" + "str r8, [sp, #48]\n\t" + "str r9, [sp, #52]\n\t" + "str r10, [sp, #56]\n\t" + "str r14, [sp, #60]\n\t" + "# Start Reduction\n\t" + "ldr r4, [sp, #0]\n\t" + "ldr r5, [sp, #4]\n\t" + "ldr r6, [sp, #8]\n\t" + "ldr r7, [sp, #12]\n\t" + "ldr r8, [sp, #16]\n\t" + "ldr r9, [sp, #20]\n\t" + "ldr r10, [sp, #24]\n\t" + "ldr r14, [sp, #28]\n\t" + "# mu = a[0]-a[7] + a[0]-a[4] << 96 + (a[0]-a[1] * 2) << 192\n\t" + "# - a[0] << 224\n\t" + "# + (a[0]-a[1] * 2) << (6 * 32)\n\t" + "adds r10, r10, r4\n\t" + "adc r14, r14, r5\n\t" + "adds r10, r10, r4\n\t" + "adc r14, r14, r5\n\t" + "# - a[0] << (7 * 32)\n\t" + "sub r14, r14, r4\n\t" + "# + a[0]-a[4] << (3 * 32)\n\t" + "mov %[a], r7\n\t" + "mov %[b], r8\n\t" + "adds r7, r7, r4\n\t" + "adcs r8, r8, r5\n\t" + "adcs r9, r9, r6\n\t" + "adcs r10, r10, %[a]\n\t" + "adc r14, r14, %[b]\n\t" + "str r4, [sp, #0]\n\t" + "str r5, [sp, #4]\n\t" + "str r6, [sp, #8]\n\t" + "str r7, [sp, #12]\n\t" + "str r8, [sp, #16]\n\t" + "str r9, [sp, #20]\n\t" + "# a += mu * m\n\t" + "# += mu * ((1 << 256) - (1 << 224) + (1 << 192) + (1 << 96) - 1)\n\t" + "mov %[a], #0\n\t" + "# a[6] += t[0] + t[3]\n\t" + "ldr r3, [sp, #24]\n\t" + "adds r3, r3, r4\n\t" + "adc %[b], %[a], #0\n\t" + "adds r3, r3, r7\n\t" + "adc %[b], %[b], #0\n\t" + "str r10, [sp, #24]\n\t" + "# a[7] += t[1] + t[4]\n\t" + "ldr r3, [sp, #28]\n\t" + "adds r3, r3, %[b]\n\t" + "adc %[b], %[a], #0\n\t" + "adds r3, r3, r5\n\t" + "adc %[b], %[b], #0\n\t" + "adds r3, r3, r8\n\t" + "adc %[b], %[b], #0\n\t" + "str r14, [sp, #28]\n\t" + "str r3, [sp, #64]\n\t" + "# a[8] += t[0] + t[2] + t[5]\n\t" + "ldr r3, [sp, #32]\n\t" + "adds r3, r3, %[b]\n\t" + "adc %[b], %[a], #0\n\t" + "adds r3, r3, r4\n\t" + "adc %[b], %[b], #0\n\t" + "adds r3, r3, r6\n\t" + "adc %[b], %[b], #0\n\t" + "adds r3, r3, r9\n\t" + "adc %[b], %[b], #0\n\t" + "str r3, [sp, #32]\n\t" + "# a[9] += t[1] + t[3] + t[6]\n\t" + "# a[10] += t[2] + t[4] + t[7]\n\t" + "ldr r3, [sp, #36]\n\t" + "ldr r4, [sp, #40]\n\t" + "adds r3, r3, %[b]\n\t" + "adcs r4, r4, #0\n\t" + "adc %[b], %[a], #0\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc %[b], %[b], #0\n\t" + "adds r3, r3, r7\n\t" + "adcs r4, r4, r8\n\t" + "adc %[b], %[b], #0\n\t" + "adds r3, r3, r10\n\t" + "adcs r4, r4, r14\n\t" + "adc %[b], %[b], #0\n\t" + "str r3, [sp, #36]\n\t" + "str r4, [sp, #40]\n\t" + "# a[11] += t[3] + t[5]\n\t" + "# a[12] += t[4] + t[6]\n\t" + "# a[13] += t[5] + t[7]\n\t" + "# a[14] += t[6]\n\t" + "ldr r3, [sp, #44]\n\t" + "ldr r4, [sp, #48]\n\t" + "ldr r5, [sp, #52]\n\t" + "ldr r6, [sp, #56]\n\t" + "adds r3, r3, %[b]\n\t" + "adcs r4, r4, #0\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adc %[b], %[a], #0\n\t" + "adds r3, r3, r7\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adc %[b], %[b], #0\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adcs r5, r5, r14\n\t" + "adcs r6, r6, #0\n\t" + "adc %[b], %[b], #0\n\t" + "str r3, [sp, #44]\n\t" + "str r4, [sp, #48]\n\t" + "str r5, [sp, #52]\n\t" + "str r6, [sp, #56]\n\t" + "# a[15] += t[7]\n\t" + "ldr r3, [sp, #60]\n\t" + "adds r3, r3, %[b]\n\t" + "adc %[b], %[a], #0\n\t" + "adds r3, r3, r14\n\t" + "adc %[b], %[b], #0\n\t" + "str r3, [sp, #60]\n\t" + "ldr r3, [sp, #64]\n\t" + "ldr r4, [sp, #32]\n\t" + "ldr r5, [sp, #36]\n\t" + "ldr r6, [sp, #40]\n\t" + "ldr r8, [sp, #0]\n\t" + "ldr r9, [sp, #4]\n\t" + "ldr r10, [sp, #8]\n\t" + "ldr r14, [sp, #12]\n\t" + "subs r3, r3, r8\n\t" + "sbcs r4, r4, r9\n\t" + "sbcs r5, r5, r10\n\t" + "sbcs r6, r6, r14\n\t" + "str r4, [sp, #32]\n\t" + "str r5, [sp, #36]\n\t" + "str r6, [sp, #40]\n\t" + "ldr r3, [sp, #44]\n\t" + "ldr r4, [sp, #48]\n\t" + "ldr r5, [sp, #52]\n\t" + "ldr r6, [sp, #56]\n\t" + "ldr r7, [sp, #60]\n\t" + "ldr r8, [sp, #16]\n\t" + "ldr r9, [sp, #20]\n\t" + "ldr r10, [sp, #24]\n\t" + "ldr r14, [sp, #28]\n\t" + "sbcs r3, r3, r8\n\t" + "sbcs r4, r4, r9\n\t" + "sbcs r5, r5, r10\n\t" + "sbcs r6, r6, r14\n\t" + "sbc r7, r7, #0\n\t" + "str r3, [sp, #44]\n\t" + "str r4, [sp, #48]\n\t" + "str r5, [sp, #52]\n\t" + "str r6, [sp, #56]\n\t" + "str r7, [sp, #60]\n\t" + "# mask m and sub from result if overflow\n\t" + "sub %[b], %[a], %[b]\n\t" + "and %[a], %[b], #1\n\t" + "ldr r3, [sp, #32]\n\t" + "ldr r4, [sp, #36]\n\t" + "ldr r5, [sp, #40]\n\t" + "ldr r6, [sp, #44]\n\t" + "ldr r7, [sp, #48]\n\t" + "ldr r8, [sp, #52]\n\t" + "ldr r9, [sp, #56]\n\t" + "ldr r10, [sp, #60]\n\t" + "subs r3, r3, %[b]\n\t" + "sbcs r4, r4, %[b]\n\t" + "sbcs r5, r5, %[b]\n\t" + "sbcs r6, r6, #0\n\t" + "sbcs r7, r7, #0\n\t" + "sbcs r8, r8, #0\n\t" + "sbcs r9, r9, %[a]\n\t" + "sbc r10, r10, %[b]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "str r7, [%[r], #16]\n\t" + "str r8, [%[r], #20]\n\t" + "str r9, [%[r], #24]\n\t" + "str r10, [%[r], #28]\n\t" + "add sp, sp, #68\n\t" + : [a] "+r" (a), [b] "+r" (b) + : [r] "r" (r) + : "memory", "r8", "r9", "r10", "r14", "r3", "r4", "r5", "r6", "r7" + ); +} + +/* 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_8(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + (void)mp; + (void)m; + + __asm__ __volatile__ ( + "sub sp, sp, #68\n\t" + "mov r5, #0\n\t" + "# A[0] * A[1]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #4]\n\t" + "umull r9, r10, r6, r7\n\t" + "str r9, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adc r14, r4, #0\n\t" + "str r10, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adc r8, r4, #0\n\t" + "# A[1] * A[2]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, #0\n\t" + "str r14, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adc r9, r4, r9\n\t" + "# A[1] * A[3]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, #0\n\t" + "str r8, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adc r10, r4, r10\n\t" + "# A[1] * A[4]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, #0\n\t" + "# A[2] * A[3]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "str r9, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[2] * A[4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "str r10, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[2] * A[5]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[3] * A[4]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "str r14, [sp, #28]\n\t" + "# A[1] * A[7]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, #0\n\t" + "# A[2] * A[6]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[3] * A[5]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "str r8, [sp, #32]\n\t" + "# A[2] * A[7]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, #0\n\t" + "# A[3] * A[6]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[4] * A[5]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "str r9, [sp, #36]\n\t" + "# A[3] * A[7]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, #0\n\t" + "# A[4] * A[6]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "str r10, [sp, #40]\n\t" + "# A[4] * A[7]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, #0\n\t" + "# A[5] * A[6]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "str r14, [sp, #44]\n\t" + "# A[5] * A[7]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, #0\n\t" + "str r8, [sp, #48]\n\t" + "# A[6] * A[7]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adc r10, r4, r10\n\t" + "str r9, [sp, #52]\n\t" + "str r10, [sp, #56]\n\t" + "# Double\n\t" + "ldr r4, [sp, #4]\n\t" + "ldr r6, [sp, #8]\n\t" + "ldr r7, [sp, #12]\n\t" + "ldr r8, [sp, #16]\n\t" + "ldr r9, [sp, #20]\n\t" + "ldr r10, [sp, #24]\n\t" + "ldr r14, [sp, #28]\n\t" + "ldr r12, [sp, #32]\n\t" + "ldr r3, [sp, #36]\n\t" + "adds r4, r4, r4\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "adcs r12, r12, r12\n\t" + "adcs r3, r3, r3\n\t" + "str r4, [sp, #4]\n\t" + "str r6, [sp, #8]\n\t" + "str r7, [sp, #12]\n\t" + "str r8, [sp, #16]\n\t" + "str r9, [sp, #20]\n\t" + "str r10, [sp, #24]\n\t" + "str r14, [sp, #28]\n\t" + "str r12, [sp, #32]\n\t" + "str r3, [sp, #36]\n\t" + "ldr r4, [sp, #40]\n\t" + "ldr r6, [sp, #44]\n\t" + "ldr r7, [sp, #48]\n\t" + "ldr r8, [sp, #52]\n\t" + "ldr r9, [sp, #56]\n\t" + "adcs r4, r4, r4\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "str r4, [sp, #40]\n\t" + "str r6, [sp, #44]\n\t" + "str r7, [sp, #48]\n\t" + "str r8, [sp, #52]\n\t" + "str r9, [sp, #56]\n\t" + "adc r10, r5, #0\n\t" + "str r10, [sp, #60]\n\t" + "ldr r4, [sp, #4]\n\t" + "ldr r5, [sp, #8]\n\t" + "ldr r12, [sp, #12]\n\t" + "# A[0] * A[0]\n\t" + "ldr r6, [%[a], #0]\n\t" + "umull r8, r9, r6, r6\n\t" + "# A[1] * A[1]\n\t" + "ldr r6, [%[a], #4]\n\t" + "umull r10, r14, r6, r6\n\t" + "adds r9, r9, r4\n\t" + "adcs r10, r10, r5\n\t" + "adcs r14, r14, r12\n\t" + "str r8, [sp, #0]\n\t" + "str r9, [sp, #4]\n\t" + "str r10, [sp, #8]\n\t" + "str r14, [sp, #12]\n\t" + "ldr r3, [sp, #16]\n\t" + "ldr r4, [sp, #20]\n\t" + "ldr r5, [sp, #24]\n\t" + "ldr r12, [sp, #28]\n\t" + "# A[2] * A[2]\n\t" + "ldr r6, [%[a], #8]\n\t" + "umull r8, r9, r6, r6\n\t" + "# A[3] * A[3]\n\t" + "ldr r6, [%[a], #12]\n\t" + "umull r10, r14, r6, r6\n\t" + "adcs r8, r8, r3\n\t" + "adcs r9, r9, r4\n\t" + "adcs r10, r10, r5\n\t" + "adcs r14, r14, r12\n\t" + "str r8, [sp, #16]\n\t" + "str r9, [sp, #20]\n\t" + "str r10, [sp, #24]\n\t" + "str r14, [sp, #28]\n\t" + "ldr r3, [sp, #32]\n\t" + "ldr r4, [sp, #36]\n\t" + "ldr r5, [sp, #40]\n\t" + "ldr r12, [sp, #44]\n\t" + "# A[4] * A[4]\n\t" + "ldr r6, [%[a], #16]\n\t" + "umull r8, r9, r6, r6\n\t" + "# A[5] * A[5]\n\t" + "ldr r6, [%[a], #20]\n\t" + "umull r10, r14, r6, r6\n\t" + "adcs r8, r8, r3\n\t" + "adcs r9, r9, r4\n\t" + "adcs r10, r10, r5\n\t" + "adcs r14, r14, r12\n\t" + "str r8, [sp, #32]\n\t" + "str r9, [sp, #36]\n\t" + "str r10, [sp, #40]\n\t" + "str r14, [sp, #44]\n\t" + "ldr r3, [sp, #48]\n\t" + "ldr r4, [sp, #52]\n\t" + "ldr r5, [sp, #56]\n\t" + "ldr r12, [sp, #60]\n\t" + "# A[6] * A[6]\n\t" + "ldr r6, [%[a], #24]\n\t" + "umull r8, r9, r6, r6\n\t" + "# A[7] * A[7]\n\t" + "ldr r6, [%[a], #28]\n\t" + "umull r10, r14, r6, r6\n\t" + "adcs r8, r8, r3\n\t" + "adcs r9, r9, r4\n\t" + "adcs r10, r10, r5\n\t" + "adc r14, r14, r12\n\t" + "str r8, [sp, #48]\n\t" + "str r9, [sp, #52]\n\t" + "str r10, [sp, #56]\n\t" + "str r14, [sp, #60]\n\t" + "# Start Reduction\n\t" + "ldr r4, [sp, #0]\n\t" + "ldr r5, [sp, #4]\n\t" + "ldr r6, [sp, #8]\n\t" + "ldr r7, [sp, #12]\n\t" + "ldr r8, [sp, #16]\n\t" + "ldr r9, [sp, #20]\n\t" + "ldr r10, [sp, #24]\n\t" + "ldr r14, [sp, #28]\n\t" + "# mu = a[0]-a[7] + a[0]-a[4] << 96 + (a[0]-a[1] * 2) << 192\n\t" + "# - a[0] << 224\n\t" + "# + (a[0]-a[1] * 2) << (6 * 32)\n\t" + "adds r10, r10, r4\n\t" + "adc r14, r14, r5\n\t" + "adds r10, r10, r4\n\t" + "adc r14, r14, r5\n\t" + "# - a[0] << (7 * 32)\n\t" + "sub r14, r14, r4\n\t" + "# + a[0]-a[4] << (3 * 32)\n\t" + "mov %[a], r7\n\t" + "mov r12, r8\n\t" + "adds r7, r7, r4\n\t" + "adcs r8, r8, r5\n\t" + "adcs r9, r9, r6\n\t" + "adcs r10, r10, %[a]\n\t" + "adc r14, r14, r12\n\t" + "str r4, [sp, #0]\n\t" + "str r5, [sp, #4]\n\t" + "str r6, [sp, #8]\n\t" + "str r7, [sp, #12]\n\t" + "str r8, [sp, #16]\n\t" + "str r9, [sp, #20]\n\t" + "# a += mu * m\n\t" + "# += mu * ((1 << 256) - (1 << 224) + (1 << 192) + (1 << 96) - 1)\n\t" + "mov %[a], #0\n\t" + "# a[6] += t[0] + t[3]\n\t" + "ldr r3, [sp, #24]\n\t" + "adds r3, r3, r4\n\t" + "adc r12, %[a], #0\n\t" + "adds r3, r3, r7\n\t" + "adc r12, r12, #0\n\t" + "str r10, [sp, #24]\n\t" + "# a[7] += t[1] + t[4]\n\t" + "ldr r3, [sp, #28]\n\t" + "adds r3, r3, r12\n\t" + "adc r12, %[a], #0\n\t" + "adds r3, r3, r5\n\t" + "adc r12, r12, #0\n\t" + "adds r3, r3, r8\n\t" + "adc r12, r12, #0\n\t" + "str r14, [sp, #28]\n\t" + "str r3, [sp, #64]\n\t" + "# a[8] += t[0] + t[2] + t[5]\n\t" + "ldr r3, [sp, #32]\n\t" + "adds r3, r3, r12\n\t" + "adc r12, %[a], #0\n\t" + "adds r3, r3, r4\n\t" + "adc r12, r12, #0\n\t" + "adds r3, r3, r6\n\t" + "adc r12, r12, #0\n\t" + "adds r3, r3, r9\n\t" + "adc r12, r12, #0\n\t" + "str r3, [sp, #32]\n\t" + "# a[9] += t[1] + t[3] + t[6]\n\t" + "# a[10] += t[2] + t[4] + t[7]\n\t" + "ldr r3, [sp, #36]\n\t" + "ldr r4, [sp, #40]\n\t" + "adds r3, r3, r12\n\t" + "adcs r4, r4, #0\n\t" + "adc r12, %[a], #0\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "adds r3, r3, r7\n\t" + "adcs r4, r4, r8\n\t" + "adc r12, r12, #0\n\t" + "adds r3, r3, r10\n\t" + "adcs r4, r4, r14\n\t" + "adc r12, r12, #0\n\t" + "str r3, [sp, #36]\n\t" + "str r4, [sp, #40]\n\t" + "# a[11] += t[3] + t[5]\n\t" + "# a[12] += t[4] + t[6]\n\t" + "# a[13] += t[5] + t[7]\n\t" + "# a[14] += t[6]\n\t" + "ldr r3, [sp, #44]\n\t" + "ldr r4, [sp, #48]\n\t" + "ldr r5, [sp, #52]\n\t" + "ldr r6, [sp, #56]\n\t" + "adds r3, r3, r12\n\t" + "adcs r4, r4, #0\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adc r12, %[a], #0\n\t" + "adds r3, r3, r7\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adc r12, r12, #0\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adcs r5, r5, r14\n\t" + "adcs r6, r6, #0\n\t" + "adc r12, r12, #0\n\t" + "str r3, [sp, #44]\n\t" + "str r4, [sp, #48]\n\t" + "str r5, [sp, #52]\n\t" + "str r6, [sp, #56]\n\t" + "# a[15] += t[7]\n\t" + "ldr r3, [sp, #60]\n\t" + "adds r3, r3, r12\n\t" + "adc r12, %[a], #0\n\t" + "adds r3, r3, r14\n\t" + "adc r12, r12, #0\n\t" + "str r3, [sp, #60]\n\t" + "ldr r3, [sp, #64]\n\t" + "ldr r4, [sp, #32]\n\t" + "ldr r5, [sp, #36]\n\t" + "ldr r6, [sp, #40]\n\t" + "ldr r8, [sp, #0]\n\t" + "ldr r9, [sp, #4]\n\t" + "ldr r10, [sp, #8]\n\t" + "ldr r14, [sp, #12]\n\t" + "subs r3, r3, r8\n\t" + "sbcs r4, r4, r9\n\t" + "sbcs r5, r5, r10\n\t" + "sbcs r6, r6, r14\n\t" + "str r4, [sp, #32]\n\t" + "str r5, [sp, #36]\n\t" + "str r6, [sp, #40]\n\t" + "ldr r3, [sp, #44]\n\t" + "ldr r4, [sp, #48]\n\t" + "ldr r5, [sp, #52]\n\t" + "ldr r6, [sp, #56]\n\t" + "ldr r7, [sp, #60]\n\t" + "ldr r8, [sp, #16]\n\t" + "ldr r9, [sp, #20]\n\t" + "ldr r10, [sp, #24]\n\t" + "ldr r14, [sp, #28]\n\t" + "sbcs r3, r3, r8\n\t" + "sbcs r4, r4, r9\n\t" + "sbcs r5, r5, r10\n\t" + "sbcs r6, r6, r14\n\t" + "sbc r7, r7, #0\n\t" + "str r3, [sp, #44]\n\t" + "str r4, [sp, #48]\n\t" + "str r5, [sp, #52]\n\t" + "str r6, [sp, #56]\n\t" + "str r7, [sp, #60]\n\t" + "# mask m and sub from result if overflow\n\t" + "sub r12, %[a], r12\n\t" + "and %[a], r12, #1\n\t" + "ldr r3, [sp, #32]\n\t" + "ldr r4, [sp, #36]\n\t" + "ldr r5, [sp, #40]\n\t" + "ldr r6, [sp, #44]\n\t" + "ldr r7, [sp, #48]\n\t" + "ldr r8, [sp, #52]\n\t" + "ldr r9, [sp, #56]\n\t" + "ldr r10, [sp, #60]\n\t" + "subs r3, r3, r12\n\t" + "sbcs r4, r4, r12\n\t" + "sbcs r5, r5, r12\n\t" + "sbcs r6, r6, #0\n\t" + "sbcs r7, r7, #0\n\t" + "sbcs r8, r8, #0\n\t" + "sbcs r9, r9, %[a]\n\t" + "sbc r10, r10, r12\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "str r7, [%[r], #16]\n\t" + "str r8, [%[r], #20]\n\t" + "str r9, [%[r], #24]\n\t" + "str r10, [%[r], #28]\n\t" + "add sp, sp, #68\n\t" + : [a] "+r" (a) + : [r] "r" (r) + : "memory", "r8", "r9", "r10", "r14", "r3", "r4", "r5", "r6", "r7", "r12" + ); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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_8(sp_digit* r, const sp_digit* a, int n, + const sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_8(r, a, m, mp); + for (; n > 1; n--) { + sp_256_mont_sqr_8(r, r, m, mp); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint32_t p256_mod_minus_2[8] = { + 0xfffffffdU,0xffffffffU,0xffffffffU,0x00000000U,0x00000000U,0x00000000U, + 0x00000001U,0xffffffffU +}; +#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_8(sp_digit* r, const sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 8); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_8(t, t, p256_mod, p256_mp_mod); + if (p256_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 8); +#else + sp_digit* t1 = td; + sp_digit* t2 = td + 2 * 8; + sp_digit* t3 = td + 4 * 8; + /* 0x2 */ + sp_256_mont_sqr_8(t1, a, p256_mod, p256_mp_mod); + /* 0x3 */ + sp_256_mont_mul_8(t2, t1, a, p256_mod, p256_mp_mod); + /* 0xc */ + sp_256_mont_sqr_n_8(t1, t2, 2, p256_mod, p256_mp_mod); + /* 0xd */ + sp_256_mont_mul_8(t3, t1, a, p256_mod, p256_mp_mod); + /* 0xf */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xf0 */ + sp_256_mont_sqr_n_8(t1, t2, 4, p256_mod, p256_mp_mod); + /* 0xfd */ + sp_256_mont_mul_8(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xff */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xff00 */ + sp_256_mont_sqr_n_8(t1, t2, 8, p256_mod, p256_mp_mod); + /* 0xfffd */ + sp_256_mont_mul_8(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffff */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffff0000 */ + sp_256_mont_sqr_n_8(t1, t2, 16, p256_mod, p256_mp_mod); + /* 0xfffffffd */ + sp_256_mont_mul_8(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffffffff */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000000 */ + sp_256_mont_sqr_n_8(t1, t2, 32, p256_mod, p256_mp_mod); + /* 0xffffffffffffffff */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000001 */ + sp_256_mont_mul_8(r, t1, a, p256_mod, p256_mp_mod); + /* 0xffffffff000000010000000000000000000000000000000000000000 */ + sp_256_mont_sqr_n_8(r, r, 160, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff */ + sp_256_mont_mul_8(r, r, t2, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */ + sp_256_mont_sqr_n_8(r, r, 32, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */ + sp_256_mont_mul_8(r, r, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* 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 int32_t sp_256_cmp_8(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #28\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "subs r6, r6, #4\n\t" + "bcs 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + return r; +} + +/* Normalize the values in each word to 32. + * + * a Array of sp_digit to normalize. + */ +#define sp_256_norm_8(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_8(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #32\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +#define sp_256_mont_reduce_order_8 sp_256_mont_reduce_8 + +/* 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_8(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r7, [%[m], #0]\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "ldr r9, [%[a], #32]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #32]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #32\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + sp_256_cond_sub_8(a - 8, a, m, (sp_digit)0 - ca); +} + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + int32_t n; + + sp_256_mont_inv_8(t1, p->z, t + 2*8); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_8(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 8, 0, sizeof(r->x) / 2U); + sp_256_mont_reduce_8(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_8(r->x, p256_mod); + sp_256_cond_sub_8(r->x, r->x, p256_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_256_norm_8(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_8(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 8, 0, sizeof(r->y) / 2U); + sp_256_mont_reduce_8(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_8(r->y, p256_mod); + sp_256_cond_sub_8(r->y, r->y, p256_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_256_norm_8(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 sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #32\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#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 sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#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_8(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[a],#8]\n\t" + "ldr r7, [%[a],#12]\n\t" + "ldr r8, [%[b],#0]\n\t" + "ldr r9, [%[b],#4]\n\t" + "ldr r10, [%[b],#8]\n\t" + "ldr r14, [%[b],#12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "str r7, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[a],#24]\n\t" + "ldr r7, [%[a],#28]\n\t" + "ldr r8, [%[b],#16]\n\t" + "ldr r9, [%[b],#20]\n\t" + "ldr r10, [%[b],#24]\n\t" + "ldr r14, [%[b],#28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "adc r3, r12, #0\n\t" + "sub r3, r12, r3\n\t" + "and r12, r3, #1\n\t" + "ldr r8, [%[r],#0]\n\t" + "ldr r9, [%[r],#4]\n\t" + "ldr r10, [%[r],#8]\n\t" + "ldr r14, [%[r],#12]\n\t" + "subs r8, r8, r3\n\t" + "sbcs r9, r9, r3\n\t" + "sbcs r10, r10, r3\n\t" + "sbcs r14, r14, #0\n\t" + "sbcs r4, r4, #0\n\t" + "sbcs r5, r5, #0\n\t" + "sbcs r6, r6, r12\n\t" + "sbc r7, r7, r3\n\t" + "str r8, [%[r],#0]\n\t" + "str r9, [%[r],#4]\n\t" + "str r10, [%[r],#8]\n\t" + "str r14, [%[r],#12]\n\t" + "str r4, [%[r],#16]\n\t" + "str r5, [%[r],#20]\n\t" + "str r6, [%[r],#24]\n\t" + "str r7, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r3", "r12" + ); +} + +/* 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_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[a],#8]\n\t" + "ldr r7, [%[a],#12]\n\t" + "ldr r8, [%[a],#16]\n\t" + "ldr r9, [%[a],#20]\n\t" + "ldr r10, [%[a],#24]\n\t" + "ldr r14, [%[a],#28]\n\t" + "adds r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "adc r3, r12, #0\n\t" + "sub r3, r12, r3\n\t" + "and r12, r3, #1\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, r3\n\t" + "sbcs r6, r6, r3\n\t" + "sbcs r7, r7, #0\n\t" + "sbcs r8, r8, #0\n\t" + "sbcs r9, r9, #0\n\t" + "sbcs r10, r10, r12\n\t" + "sbc r14, r14, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "str r7, [%[r],#12]\n\t" + "str r8, [%[r],#16]\n\t" + "str r9, [%[r],#20]\n\t" + "str r10, [%[r],#24]\n\t" + "str r14, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r3", "r12" + ); +} + +/* 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_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[a],#8]\n\t" + "ldr r7, [%[a],#12]\n\t" + "ldr r8, [%[a],#16]\n\t" + "ldr r9, [%[a],#20]\n\t" + "ldr r10, [%[a],#24]\n\t" + "ldr r14, [%[a],#28]\n\t" + "adds r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "adc r3, r12, #0\n\t" + "sub r3, r12, r3\n\t" + "and r12, r3, #1\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, r3\n\t" + "sbcs r6, r6, r3\n\t" + "sbcs r7, r7, #0\n\t" + "sbcs r8, r8, #0\n\t" + "sbcs r9, r9, #0\n\t" + "sbcs r10, r10, r12\n\t" + "sbc r14, r14, r3\n\t" + "str r8, [%[r],#16]\n\t" + "str r9, [%[r],#20]\n\t" + "str r10, [%[r],#24]\n\t" + "str r14, [%[r],#28]\n\t" + "mov r12, #0\n\t" + "ldr r8, [%[a],#0]\n\t" + "ldr r9, [%[a],#4]\n\t" + "ldr r10, [%[a],#8]\n\t" + "ldr r14, [%[a],#12]\n\t" + "adds r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "str r8, [%[r],#0]\n\t" + "str r9, [%[r],#4]\n\t" + "str r10, [%[r],#8]\n\t" + "str r14, [%[r],#12]\n\t" + "ldr r8, [%[a],#16]\n\t" + "ldr r9, [%[a],#20]\n\t" + "ldr r10, [%[a],#24]\n\t" + "ldr r14, [%[a],#28]\n\t" + "ldr r4, [%[r],#16]\n\t" + "ldr r5, [%[r],#20]\n\t" + "ldr r6, [%[r],#24]\n\t" + "ldr r7, [%[r],#28]\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "adc r3, r12, #0\n\t" + "sub r3, r12, r3\n\t" + "and r12, r3, #1\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "ldr r6, [%[r],#8]\n\t" + "ldr r7, [%[r],#12]\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, r3\n\t" + "sbcs r6, r6, r3\n\t" + "sbcs r7, r7, #0\n\t" + "sbcs r8, r8, #0\n\t" + "sbcs r9, r9, #0\n\t" + "sbcs r10, r10, r12\n\t" + "sbc r14, r14, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "str r7, [%[r],#12]\n\t" + "str r8, [%[r],#16]\n\t" + "str r9, [%[r],#20]\n\t" + "str r10, [%[r],#24]\n\t" + "str r14, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r3", "r12" + ); +} + +/* 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_8(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[a],#8]\n\t" + "ldr r7, [%[a],#12]\n\t" + "ldr r8, [%[b],#0]\n\t" + "ldr r9, [%[b],#4]\n\t" + "ldr r10, [%[b],#8]\n\t" + "ldr r14, [%[b],#12]\n\t" + "subs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "str r7, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[a],#24]\n\t" + "ldr r7, [%[a],#28]\n\t" + "ldr r8, [%[b],#16]\n\t" + "ldr r9, [%[b],#20]\n\t" + "ldr r10, [%[b],#24]\n\t" + "ldr r14, [%[b],#28]\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "sbc r3, r12, #0\n\t" + "and r12, r3, #1\n\t" + "ldr r8, [%[r],#0]\n\t" + "ldr r9, [%[r],#4]\n\t" + "ldr r10, [%[r],#8]\n\t" + "ldr r14, [%[r],#12]\n\t" + "adds r8, r8, r3\n\t" + "adcs r9, r9, r3\n\t" + "adcs r10, r10, r3\n\t" + "adcs r14, r14, #0\n\t" + "adcs r4, r4, #0\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, r12\n\t" + "adc r7, r7, r3\n\t" + "str r8, [%[r],#0]\n\t" + "str r9, [%[r],#4]\n\t" + "str r10, [%[r],#8]\n\t" + "str r14, [%[r],#12]\n\t" + "str r4, [%[r],#16]\n\t" + "str r5, [%[r],#20]\n\t" + "str r6, [%[r],#24]\n\t" + "str r7, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r3", "r12" + ); +} + +/* 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_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "and r9, r3, #1\n\t" + "sub r7, r10, r9\n\t" + "and r8, r7, #1\n\t" + "adds r3, r3, r7\n\t" + "adcs r4, r4, r7\n\t" + "adcs r5, r5, r7\n\t" + "adcs r6, r6, r10\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "adcs r3, r3, r10\n\t" + "adcs r4, r4, r10\n\t" + "adcs r5, r5, r8\n\t" + "adcs r6, r6, r7\n\t" + "adc r9, r10, r10\n\t" + "lsr r7, r3, #1\n\t" + "and r3, r3, #1\n\t" + "lsr r8, r4, #1\n\t" + "lsr r10, r5, #1\n\t" + "lsr r14, r6, #1\n\t" + "orr r7, r7, r4, lsl #31\n\t" + "orr r8, r8, r5, lsl #31\n\t" + "orr r10, r10, r6, lsl #31\n\t" + "orr r14, r14, r9, lsl #31\n\t" + "mov r9, r3\n\t" + "str r7, [%[r], #16]\n\t" + "str r8, [%[r], #20]\n\t" + "str r10, [%[r], #24]\n\t" + "str r14, [%[r], #28]\n\t" + "ldr r3, [%[r], #0]\n\t" + "ldr r4, [%[r], #4]\n\t" + "ldr r5, [%[r], #8]\n\t" + "ldr r6, [%[r], #12]\n\t" + "lsr r7, r3, #1\n\t" + "lsr r8, r4, #1\n\t" + "lsr r10, r5, #1\n\t" + "lsr r14, r6, #1\n\t" + "orr r7, r7, r4, lsl #31\n\t" + "orr r8, r8, r5, lsl #31\n\t" + "orr r10, r10, r6, lsl #31\n\t" + "orr r14, r14, r9, lsl #31\n\t" + "str r7, [%[r], #0]\n\t" + "str r8, [%[r], #4]\n\t" + "str r10, [%[r], #8]\n\t" + "str r14, [%[r], #12]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r10", "r14", "r9" + ); + +} + +/* 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_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_8(t1, p->z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_8(z, p->y, p->z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_8(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_8(t2, p->x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_8(t1, p->x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_8(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_8(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_8(y, p->y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_8(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_8(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_8(y, y, p->x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_sqr_8(x, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_8(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_8(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_8(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_8(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_8(y, y, t2, p256_mod); +} + +#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 sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #32\n\t" + "\n1:\n\t" + "rsbs %[c], %[c], #0\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "sbc %[c], r4, r4\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#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 sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #0]\n\t" + "ldr r8, [%[b], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "ldr r10, [%[b], #12]\n\t" + "subs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "ldr r10, [%[b], #28]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "sbc %[c], %[c], #0\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* 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_8(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])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, + sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* t3 = t + 4*8; + sp_digit* t4 = t + 6*8; + sp_digit* t5 = t + 8*8; + 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) { + const sp_point_256* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_256_sub_8(t1, p256_mod, q->y); + sp_256_norm_8(t1); + if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) != 0) { + sp_256_proj_point_dbl_8(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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<8; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<8; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<8; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_8(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_8(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_8(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_8(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_8(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_8(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(x, x, t5, p256_mod); + sp_256_mont_dbl_8(t1, y, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_mul_8(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(y, y, t5, p256_mod); + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td[16]; + sp_point_256 rtd; + sp_digit tmpd[2 * 8 * 5]; +#endif + sp_point_256* t; + sp_point_256* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_256_point_new_8(heap, rtd, rt); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 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 */ + (void)sp_256_mod_mul_norm_8(t[1].x, g->x, p256_mod); + (void)sp_256_mod_mul_norm_8(t[1].y, g->y, p256_mod); + (void)sp_256_mod_mul_norm_8(t[1].z, g->z, p256_mod); + t[1].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_256_proj_point_add_8(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_256_proj_point_add_8(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_256_proj_point_add_8(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_256_proj_point_add_8(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_256_proj_point_dbl_8(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_256_proj_point_add_8(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_256_proj_point_dbl_8(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_256_proj_point_add_8(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_256_proj_point_dbl_8(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_256_proj_point_add_8(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 6; + n = k[i+1] << 0; + c = 28; + y = n >> 28; + XMEMCPY(rt, &t[y], sizeof(sp_point_256)); + n <<= 4; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--]; + c += 32; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + + sp_256_proj_point_add_8(rt, rt, &t[y], tmp); + } + + if (map != 0) { + sp_256_map_8(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 8 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_256) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_256_point_free_8(rt, 1, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_256 { + sp_digit x[8]; + sp_digit y[8]; +} sp_table_entry_256; + +#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_8(sp_point_256* p, int n, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*8; + sp_digit* b = t + 4*8; + sp_digit* t1 = t + 6*8; + sp_digit* t2 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_256_mont_dbl_8(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_8(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(w, w, p256_mod, p256_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(t1, t1, w, p256_mod); + sp_256_mont_tpl_8(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_8(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(b, t1, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(t2, b, p256_mod); + sp_256_mont_sub_8(x, x, t2, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_8(t1, t1, p256_mod, p256_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_256_mont_mul_8(w, w, t1, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_8(y, b, x, p256_mod); + sp_256_mont_mul_8(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(y, y, p256_mod); + sp_256_mont_sub_8(y, y, t1, p256_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(t1, t1, w, p256_mod); + sp_256_mont_tpl_8(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_8(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(b, t1, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(t2, b, p256_mod); + sp_256_mont_sub_8(x, x, t2, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_8(t1, t1, p256_mod, p256_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_8(y, b, x, p256_mod); + sp_256_mont_mul_8(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(y, y, p256_mod); + sp_256_mont_sub_8(y, y, t1, p256_mod); +#endif + /* Y = Y/2 */ + sp_256_div2_8(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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_8(sp_point_256* r, const sp_point_256* p, + const sp_point_256* q, sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* t3 = t + 4*8; + sp_digit* t4 = t + 6*8; + sp_digit* t5 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_256_sub_8(t1, p256_mod, q->y); + sp_256_norm_8(t1); + if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) != 0) { + sp_256_proj_point_dbl_8(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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<8; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<8; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<8; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_8(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_8(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_8(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(x, t1, t5, p256_mod); + sp_256_mont_dbl_8(t1, t3, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_8(t3, t3, x, p256_mod); + sp_256_mont_mul_8(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(y, t3, t5, p256_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 8; + sp_digit* tmp = t + 4 * 8; + + sp_256_mont_inv_8(t1, a->z, tmp); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_8(const sp_point_256* a, + sp_table_entry_256* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td, s1d, s2d; +#endif + sp_point_256* t; + sp_point_256* s1 = NULL; + sp_point_256* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_256_point_new_8(heap, td, t); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_8(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_256)); + /* 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)); + + for (i=1; i<4; i++) { + sp_256_proj_point_dbl_n_8(t, 64, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<4; i++) { + XMEMCPY(s1->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_8(t, s1, s2, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_256_point_free_8(s2, 0, heap); + sp_256_point_free_8(s1, 0, heap); + sp_256_point_free_8( 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 coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit td[2 * 8 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_256_point_new_8(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 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=63; j<4; j++,x+=64) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=62; i>=0; i--) { + y = 0; + for (j=0,x=i; j<4; j++,x+=64) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + + sp_256_proj_point_dbl_8(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 = !y; + sp_256_proj_point_add_qz1_8(rt, rt, p, t); + } + + if (map != 0) { + sp_256_map_8(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, heap); + sp_256_point_free_8(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_256_t { + sp_digit x[8]; + sp_digit y[8]; + sp_table_entry_256 table[16]; + uint32_t cnt; + int set; +} sp_cache_256_t; + +static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_256_last = -1; +static THREAD_LS_T int sp_cache_256_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_256 = 0; + static wolfSSL_Mutex sp_cache_256_lock; +#endif + +static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_256_inited == 0) { + for (i=0; ix, sp_cache_256[i].x) & + sp_256_cmp_equal_8(g->y, sp_cache_256[i].y)) { + sp_cache_256[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_256_last + 1) % FP_ENTRIES; + for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_256[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_256_last) { + least = sp_cache_256[0].cnt; + for (j=1; jx, sizeof(sp_cache_256[i].x)); + XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y)); + sp_cache_256[i].set = 1; + sp_cache_256[i].cnt = 1; + } + + *cache = &sp_cache_256[i]; + sp_cache_256_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 coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); +#else + sp_digit tmp[2 * 8 * 5]; + sp_cache_256_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_256 == 0) { + wc_InitMutex(&sp_cache_256_lock); + initCacheMutex_256 = 1; + } + if (wc_LockMutex(&sp_cache_256_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_256(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_8(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_256_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#else +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_8(const sp_point_256* a, + sp_table_entry_256* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td, s1d, s2d; +#endif + sp_point_256* t; + sp_point_256* s1 = NULL; + sp_point_256* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_256_point_new_8(heap, td, t); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_8(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_256)); + /* 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)); + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_8(t, 32, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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_8(t, s1, s2, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_256_point_free_8(s2, 0, heap); + sp_256_point_free_8(s1, 0, heap); + sp_256_point_free_8( 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 coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit td[2 * 8 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_256_point_new_8(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 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 / 32] >> (x % 32)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + + sp_256_proj_point_dbl_8(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 = !y; + sp_256_proj_point_add_qz1_8(rt, rt, p, t); + } + + if (map != 0) { + sp_256_map_8(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, heap); + sp_256_point_free_8(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_256_t { + sp_digit x[8]; + sp_digit y[8]; + sp_table_entry_256 table[256]; + uint32_t cnt; + int set; +} sp_cache_256_t; + +static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_256_last = -1; +static THREAD_LS_T int sp_cache_256_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_256 = 0; + static wolfSSL_Mutex sp_cache_256_lock; +#endif + +static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_256_inited == 0) { + for (i=0; ix, sp_cache_256[i].x) & + sp_256_cmp_equal_8(g->y, sp_cache_256[i].y)) { + sp_cache_256[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_256_last + 1) % FP_ENTRIES; + for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_256[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_256_last) { + least = sp_cache_256[0].cnt; + for (j=1; jx, sizeof(sp_cache_256[i].x)); + XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y)); + sp_cache_256[i].set = 1; + sp_cache_256[i].cnt = 1; + } + + *cache = &sp_cache_256[i]; + sp_cache_256_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 coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); +#else + sp_digit tmp[2 * 8 * 5]; + sp_cache_256_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_256 == 0) { + wc_InitMutex(&sp_cache_256_lock); + initCacheMutex_256 = 1; + } + if (wc_LockMutex(&sp_cache_256_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_256(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_8(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_256_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[8]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_256_point_new_8(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, km); + sp_256_point_from_ecc_point_8(point, gm); + + err = sp_256_ecc_mulmod_8(point, point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_8(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static const sp_table_entry_256 p256_table[16] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76 }, + { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18 } }, + /* 2 */ + { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961 }, + { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37, + 0x8d6f0f7b,0xf648f916 } }, + /* 3 */ + { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285 }, + { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562, + 0x6b6f7383,0x94bb725b } }, + /* 4 */ + { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4 }, + { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12 } }, + /* 5 */ + { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c }, + { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08 } }, + /* 6 */ + { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651 }, + { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a } }, + /* 7 */ + { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014, + 0xaeebffcd,0x9d0f27b2 }, + { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0, + 0x356ec48d,0x244a566d } }, + /* 8 */ + { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e, + 0xcd42ab1b,0x803f3e02 }, + { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e } }, + /* 9 */ + { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5 }, + { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418, + 0xe2d41c8b,0x23d0f130 } }, + /* 10 */ + { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9 }, + { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b, + 0x01fe49c3,0x2b100118 } }, + /* 11 */ + { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999 }, + { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551 } }, + /* 12 */ + { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148 }, + { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875, + 0x9f0e1a84,0x77387de3 } }, + /* 13 */ + { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0 }, + { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8 } }, + /* 14 */ + { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb }, + { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f } }, + /* 15 */ + { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52 }, + { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f } }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_8(sp_point_256* r, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table, + k, map, heap); +} + +#else +static const sp_table_entry_256 p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76 }, + { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18 } }, + /* 2 */ + { { 0x4147519a,0x20288602,0x26b372f0,0xd0981eac,0xa785ebc8,0xa9d4a7ca, + 0xdbdf58e9,0xd953c50d }, + { 0xfd590f8f,0x9d6361cc,0x44e6c917,0x72e9626b,0x22eb64cf,0x7fd96110, + 0x9eb288f3,0x863ebb7e } }, + /* 3 */ + { { 0x5cdb6485,0x7856b623,0x2f0a2f97,0x808f0ea2,0x4f7e300b,0x3e68d954, + 0xb5ff80a0,0x00076055 }, + { 0x838d2010,0x7634eb9b,0x3243708a,0x54014fbb,0x842a6606,0xe0e47d39, + 0x34373ee0,0x83087761 } }, + /* 4 */ + { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961 }, + { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37, + 0x8d6f0f7b,0xf648f916 } }, + /* 5 */ + { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285 }, + { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562, + 0x6b6f7383,0x94bb725b } }, + /* 6 */ + { { 0x720f141c,0xbbf9b48f,0x2df5bc74,0x6199b3cd,0x411045c4,0xdc3f6129, + 0x2f7dc4ef,0xcdd6bbcb }, + { 0xeaf436fd,0xcca6700b,0xb99326be,0x6f647f6d,0x014f2522,0x0c0fa792, + 0x4bdae5f6,0xa361bebd } }, + /* 7 */ + { { 0x597c13c7,0x28aa2558,0x50b7c3e1,0xc38d635f,0xf3c09d1d,0x07039aec, + 0xc4b5292c,0xba12ca09 }, + { 0x59f91dfd,0x9e408fa4,0xceea07fb,0x3af43b66,0x9d780b29,0x1eceb089, + 0x701fef4b,0x53ebb99d } }, + /* 8 */ + { { 0xb0e63d34,0x4fe7ee31,0xa9e54fab,0xf4600572,0xd5e7b5a4,0xc0493334, + 0x06d54831,0x8589fb92 }, + { 0x6583553a,0xaa70f5cc,0xe25649e5,0x0879094a,0x10044652,0xcc904507, + 0x02541c4f,0xebb0696d } }, + /* 9 */ + { { 0xac1647c5,0x4616ca15,0xc4cf5799,0xb8127d47,0x764dfbac,0xdc666aa3, + 0xd1b27da3,0xeb2820cb }, + { 0x6a87e008,0x9406f8d8,0x922378f3,0xd87dfa9d,0x80ccecb2,0x56ed2e42, + 0x55a7da1d,0x1f28289b } }, + /* 10 */ + { { 0x3b89da99,0xabbaa0c0,0xb8284022,0xa6f2d79e,0xb81c05e8,0x27847862, + 0x05e54d63,0x337a4b59 }, + { 0x21f7794a,0x3c67500d,0x7d6d7f61,0x207005b7,0x04cfd6e8,0x0a5a3781, + 0xf4c2fbd6,0x0d65e0d5 } }, + /* 11 */ + { { 0xb5275d38,0xd9d09bbe,0x0be0a358,0x4268a745,0x973eb265,0xf0762ff4, + 0x52f4a232,0xc23da242 }, + { 0x0b94520c,0x5da1b84f,0xb05bd78e,0x09666763,0x94d29ea1,0x3a4dcb86, + 0xc790cff1,0x19de3b8c } }, + /* 12 */ + { { 0x26c5fe04,0x183a716c,0x3bba1bdb,0x3b28de0b,0xa4cb712c,0x7432c586, + 0x91fccbfd,0xe34dcbd4 }, + { 0xaaa58403,0xb408d46b,0x82e97a53,0x9a697486,0x36aaa8af,0x9e390127, + 0x7b4e0f7f,0xe7641f44 } }, + /* 13 */ + { { 0xdf64ba59,0x7d753941,0x0b0242fc,0xd33f10ec,0xa1581859,0x4f06dfc6, + 0x052a57bf,0x4a12df57 }, + { 0x9439dbd0,0xbfa6338f,0xbde53e1f,0xd3c24bd4,0x21f1b314,0xfd5e4ffa, + 0xbb5bea46,0x6af5aa93 } }, + /* 14 */ + { { 0x10c91999,0xda10b699,0x2a580491,0x0a24b440,0xb8cc2090,0x3e0094b4, + 0x66a44013,0x5fe3475a }, + { 0xf93e7b4b,0xb0f8cabd,0x7c23f91a,0x292b501a,0xcd1e6263,0x42e889ae, + 0xecfea916,0xb544e308 } }, + /* 15 */ + { { 0x16ddfdce,0x6478c6e9,0xf89179e6,0x2c329166,0x4d4e67e1,0x4e8d6e76, + 0xa6b0c20b,0xe0b6b2bd }, + { 0xbb7efb57,0x0d312df2,0x790c4007,0x1aac0dde,0x679bc944,0xf90336ad, + 0x25a63774,0x71c023de } }, + /* 16 */ + { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4 }, + { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12 } }, + /* 17 */ + { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c }, + { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08 } }, + /* 18 */ + { { 0x309a4e1f,0x1e99f581,0xe9270074,0xab7de71b,0xefd28d20,0x26a5ef0b, + 0x7f9c563f,0xe7c0073f }, + { 0x0ef59f76,0x1f6d663a,0x20fcb050,0x669b3b54,0x7a6602d4,0xc08c1f7a, + 0xc65b3c0a,0xe08504fe } }, + /* 19 */ + { { 0xa031b3ca,0xf098f68d,0xe6da6d66,0x6d1cab9e,0x94f246e8,0x5bfd81fa, + 0x5b0996b4,0x78f01882 }, + { 0x3a25787f,0xb7eefde4,0x1dccac9b,0x8016f80d,0xb35bfc36,0x0cea4877, + 0x7e94747a,0x43a773b8 } }, + /* 20 */ + { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651 }, + { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a } }, + /* 21 */ + { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014, + 0xaeebffcd,0x9d0f27b2 }, + { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0, + 0x356ec48d,0x244a566d } }, + /* 22 */ + { { 0xeacf1f96,0x6db0394a,0x024c271c,0x9f2122a9,0x82cbd3b9,0x2626ac1b, + 0x3581ef69,0x45e58c87 }, + { 0xa38f9dbc,0xd3ff479d,0xe888a040,0xa8aaf146,0x46e0bed7,0x945adfb2, + 0xc1e4b7a4,0xc040e21c } }, + /* 23 */ + { { 0x6f8117b6,0x847af000,0x73a35433,0x651969ff,0x1d9475eb,0x482b3576, + 0x682c6ec7,0x1cdf5c97 }, + { 0x11f04839,0x7db775b4,0x48de1698,0x7dbeacf4,0xb70b3219,0xb2921dd1, + 0xa92dff3d,0x046755f8 } }, + /* 24 */ + { { 0xbce8ffcd,0xcc8ac5d2,0x2fe61a82,0x0d53c48b,0x7202d6c7,0xf6f16172, + 0x3b83a5f3,0x046e5e11 }, + { 0xd8007f01,0xe7b8ff64,0x5af43183,0x7fb1ef12,0x35e1a03c,0x045c5ea6, + 0x303d005b,0x6e0106c3 } }, + /* 25 */ + { { 0x88dd73b1,0x48c73584,0x995ed0d9,0x7670708f,0xc56a2ab7,0x38385ea8, + 0xe901cf1f,0x442594ed }, + { 0x12d4b65b,0xf8faa2c9,0x96c90c37,0x94c2343b,0x5e978d1f,0xd326e4a1, + 0x4c2ee68e,0xa796fa51 } }, + /* 26 */ + { { 0x823addd7,0x359fb604,0xe56693b3,0x9e2a6183,0x3cbf3c80,0xf885b78e, + 0xc69766e9,0xe4ad2da9 }, + { 0x8e048a61,0x357f7f42,0xc092d9a0,0x082d198c,0xc03ed8ef,0xfc3a1af4, + 0xc37b5143,0xc5e94046 } }, + /* 27 */ + { { 0x2be75f9e,0x476a538c,0xcb123a78,0x6fd1a9e8,0xb109c04b,0xd85e4df0, + 0xdb464747,0x63283daf }, + { 0xbaf2df15,0xce728cf7,0x0ad9a7f4,0xe592c455,0xe834bcc3,0xfab226ad, + 0x1981a938,0x68bd19ab } }, + /* 28 */ + { { 0x1887d659,0xc08ead51,0xb359305a,0x3374d5f4,0xcfe74fe3,0x96986981, + 0x3c6fdfd6,0x495292f5 }, + { 0x1acec896,0x4a878c9e,0xec5b4484,0xd964b210,0x664d60a7,0x6696f7e2, + 0x26036837,0x0ec7530d } }, + /* 29 */ + { { 0xad2687bb,0x2da13a05,0xf32e21fa,0xa1f83b6a,0x1dd4607b,0x390f5ef5, + 0x64863f0b,0x0f6207a6 }, + { 0x0f138233,0xbd67e3bb,0x272aa718,0xdd66b96c,0x26ec88ae,0x8ed00407, + 0x08ed6dcf,0xff0db072 } }, + /* 30 */ + { { 0x4c95d553,0x749fa101,0x5d680a8a,0xa44052fd,0xff3b566f,0x183b4317, + 0x88740ea3,0x313b513c }, + { 0x08d11549,0xb402e2ac,0xb4dee21c,0x071ee10b,0x47f2320e,0x26b987dd, + 0x86f19f81,0x2d3abcf9 } }, + /* 31 */ + { { 0x815581a2,0x4c288501,0x632211af,0x9a0a6d56,0x0cab2e99,0x19ba7a0f, + 0xded98cdf,0xc036fa10 }, + { 0xc1fbd009,0x29ae08ba,0x06d15816,0x0b68b190,0x9b9e0d8f,0xc2eb3277, + 0xb6d40194,0xa6b2a2c4 } }, + /* 32 */ + { { 0x6d3549cf,0xd433e50f,0xfacd665e,0x6f33696f,0xce11fcb4,0x695bfdac, + 0xaf7c9860,0x810ee252 }, + { 0x7159bb2c,0x65450fe1,0x758b357b,0xf7dfbebe,0xd69fea72,0x2b057e74, + 0x92731745,0xd485717a } }, + /* 33 */ + { { 0xf0cb5a98,0x11741a8a,0x1f3110bf,0xd3da8f93,0xab382adf,0x1994e2cb, + 0x2f9a604e,0x6a6045a7 }, + { 0xa2b2411d,0x170c0d3f,0x510e96e0,0xbe0eb83e,0x8865b3cc,0x3bcc9f73, + 0xf9e15790,0xd3e45cfa } }, + /* 34 */ + { { 0xe83f7669,0xce1f69bb,0x72877d6b,0x09f8ae82,0x3244278d,0x9548ae54, + 0xe3c2c19c,0x207755de }, + { 0x6fef1945,0x87bd61d9,0xb12d28c3,0x18813cef,0x72df64aa,0x9fbcd1d6, + 0x7154b00d,0x48dc5ee5 } }, + /* 35 */ + { { 0xf7e5a199,0x123790bf,0x989ccbb7,0xe0efb8cf,0x0a519c79,0xc27a2bfe, + 0xdff6f445,0xf2fb0aed }, + { 0xf0b5025f,0x41c09575,0x40fa9f22,0x550543d7,0x380bfbd0,0x8fa3c8ad, + 0xdb28d525,0xa13e9015 } }, + /* 36 */ + { { 0xa2b65cbc,0xf9f7a350,0x2a464226,0x0b04b972,0xe23f07a1,0x265ce241, + 0x1497526f,0x2bf0d6b0 }, + { 0x4b216fb7,0xd3d4dd3f,0xfbdda26a,0xf7d7b867,0x6708505c,0xaeb7b83f, + 0x162fe89f,0x42a94a5a } }, + /* 37 */ + { { 0xeaadf191,0x5846ad0b,0x25a268d7,0x0f8a4890,0x494dc1f6,0xe8603050, + 0xc65ede3d,0x2c2dd969 }, + { 0x93849c17,0x6d02171d,0x1da250dd,0x460488ba,0x3c3a5485,0x4810c706, + 0x42c56dbc,0xf437fa1f } }, + /* 38 */ + { { 0x4a0f7dab,0x6aa0d714,0x1776e9ac,0x0f049793,0xf5f39786,0x52c0a050, + 0x54707aa8,0xaaf45b33 }, + { 0xc18d364a,0x85e37c33,0x3e497165,0xd40b9b06,0x15ec5444,0xf4171681, + 0xf4f272bc,0xcdf6310d } }, + /* 39 */ + { { 0x8ea8b7ef,0x7473c623,0x85bc2287,0x08e93518,0x2bda8e34,0x41956772, + 0xda9e2ff2,0xf0d008ba }, + { 0x2414d3b1,0x2912671d,0xb019ea76,0xb3754985,0x453bcbdb,0x5c61b96d, + 0xca887b8b,0x5bd5c2f5 } }, + /* 40 */ + { { 0xf49a3154,0xef0f469e,0x6e2b2e9a,0x3e85a595,0xaa924a9c,0x45aaec1e, + 0xa09e4719,0xaa12dfc8 }, + { 0x4df69f1d,0x26f27227,0xa2ff5e73,0xe0e4c82c,0xb7a9dd44,0xb9d8ce73, + 0xe48ca901,0x6c036e73 } }, + /* 41 */ + { { 0x0f6e3138,0x5cfae12a,0x25ad345a,0x6966ef00,0x45672bc5,0x8993c64b, + 0x96afbe24,0x292ff658 }, + { 0x5e213402,0xd5250d44,0x4392c9fe,0xf6580e27,0xda1c72e8,0x097b397f, + 0x311b7276,0x644e0c90 } }, + /* 42 */ + { { 0xa47153f0,0xe1e421e1,0x920418c9,0xb86c3b79,0x705d7672,0x93bdce87, + 0xcab79a77,0xf25ae793 }, + { 0x6d869d0c,0x1f3194a3,0x4986c264,0x9d55c882,0x096e945e,0x49fb5ea3, + 0x13db0a3e,0x39b8e653 } }, + /* 43 */ + { { 0xb6fd2e59,0x37754200,0x9255c98f,0x35e2c066,0x0e2a5739,0xd9dab21a, + 0x0f19db06,0x39122f2f }, + { 0x03cad53c,0xcfbce1e0,0xe65c17e3,0x225b2c0f,0x9aa13877,0x72baf1d2, + 0xce80ff8d,0x8de80af8 } }, + /* 44 */ + { { 0x207bbb76,0xafbea8d9,0x21782758,0x921c7e7c,0x1c0436b1,0xdfa2b74b, + 0x2e368c04,0x87194906 }, + { 0xa3993df5,0xb5f928bb,0xf3b3d26a,0x639d75b5,0x85b55050,0x011aa78a, + 0x5b74fde1,0xfc315e6a } }, + /* 45 */ + { { 0xe8d6ecfa,0x561fd41a,0x1aec7f86,0x5f8c44f6,0x4924741d,0x98452a7b, + 0xee389088,0xe6d4a7ad }, + { 0x4593c75d,0x60552ed1,0xdd271162,0x70a70da4,0x7ba2c7db,0xd2aede93, + 0x9be2ae57,0x35dfaf9a } }, + /* 46 */ + { { 0xaa736636,0x6b956fcd,0xae2cab7e,0x09f51d97,0x0f349966,0xfb10bf41, + 0x1c830d2b,0x1da5c7d7 }, + { 0x3cce6825,0x5c41e483,0xf9573c3b,0x15ad118f,0xf23036b8,0xa28552c7, + 0xdbf4b9d6,0x7077c0fd } }, + /* 47 */ + { { 0x46b9661c,0xbf63ff8d,0x0d2cfd71,0xa1dfd36b,0xa847f8f7,0x0373e140, + 0xe50efe44,0x53a8632e }, + { 0x696d8051,0x0976ff68,0xc74f468a,0xdaec0c95,0x5e4e26bd,0x62994dc3, + 0x34e1fcc1,0x028ca76d } }, + /* 48 */ + { { 0xfc9877ee,0xd11d47dc,0x801d0002,0xc8b36210,0x54c260b6,0xd002c117, + 0x6962f046,0x04c17cd8 }, + { 0xb0daddf5,0x6d9bd094,0x24ce55c0,0xbea23575,0x72da03b5,0x663356e6, + 0xfed97474,0xf7ba4de9 } }, + /* 49 */ + { { 0xebe1263f,0xd0dbfa34,0x71ae7ce6,0x55763735,0x82a6f523,0xd2440553, + 0x52131c41,0xe31f9600 }, + { 0xea6b6ec6,0xd1bb9216,0x73c2fc44,0x37a1d12e,0x89d0a294,0xc10e7eac, + 0xce34d47b,0xaa3a6259 } }, + /* 50 */ + { { 0x36f3dcd3,0xfbcf9df5,0xd2bf7360,0x6ceded50,0xdf504f5b,0x491710fa, + 0x7e79daee,0x2398dd62 }, + { 0x6d09569e,0xcf4705a3,0x5149f769,0xea0619bb,0x35f6034c,0xff9c0377, + 0x1c046210,0x5717f5b2 } }, + /* 51 */ + { { 0x21dd895e,0x9fe229c9,0x40c28451,0x8e518500,0x1d637ecd,0xfa13d239, + 0x0e3c28de,0x660a2c56 }, + { 0xd67fcbd0,0x9cca88ae,0x0ea9f096,0xc8472478,0x72e92b4d,0x32b2f481, + 0x4f522453,0x624ee54c } }, + /* 52 */ + { { 0xd897eccc,0x09549ce4,0x3f9880aa,0x4d49d1d9,0x043a7c20,0x723c2423, + 0x92bdfbc0,0x4f392afb }, + { 0x7de44fd9,0x6969f8fa,0x57b32156,0xb66cfbe4,0x368ebc3c,0xdb2fa803, + 0xccdb399c,0x8a3e7977 } }, + /* 53 */ + { { 0x06c4b125,0xdde1881f,0xf6e3ca8c,0xae34e300,0x5c7a13e9,0xef6999de, + 0x70c24404,0x3888d023 }, + { 0x44f91081,0x76280356,0x5f015504,0x3d9fcf61,0x632cd36e,0x1827edc8, + 0x18102336,0xa5e62e47 } }, + /* 54 */ + { { 0x2facd6c8,0x1a825ee3,0x54bcbc66,0x699c6354,0x98df9931,0x0ce3edf7, + 0x466a5adc,0x2c4768e6 }, + { 0x90a64bc9,0xb346ff8c,0xe4779f5c,0x630a6020,0xbc05e884,0xd949d064, + 0xf9e652a0,0x7b5e6441 } }, + /* 55 */ + { { 0x1d28444a,0x2169422c,0xbe136a39,0xe996c5d8,0xfb0c7fce,0x2387afe5, + 0x0c8d744a,0xb8af73cb }, + { 0x338b86fd,0x5fde83aa,0xa58a5cff,0xfee3f158,0x20ac9433,0xc9ee8f6f, + 0x7f3f0895,0xa036395f } }, + /* 56 */ + { { 0xa10f7770,0x8c73c6bb,0xa12a0e24,0xa6f16d81,0x51bc2b9f,0x100df682, + 0x875fb533,0x4be36b01 }, + { 0x9fb56dbb,0x9226086e,0x07e7a4f8,0x306fef8b,0x66d52f20,0xeeaccc05, + 0x1bdc00c0,0x8cbc9a87 } }, + /* 57 */ + { { 0xc0dac4ab,0xe131895c,0x712ff112,0xa874a440,0x6a1cee57,0x6332ae7c, + 0x0c0835f8,0x44e7553e }, + { 0x7734002d,0x6d503fff,0x0b34425c,0x9d35cb8b,0x0e8738b5,0x95f70276, + 0x5eb8fc18,0x470a683a } }, + /* 58 */ + { { 0x90513482,0x81b761dc,0x01e9276a,0x0287202a,0x0ce73083,0xcda441ee, + 0xc63dc6ef,0x16410690 }, + { 0x6d06a2ed,0xf5034a06,0x189b100b,0xdd4d7745,0xab8218c9,0xd914ae72, + 0x7abcbb4f,0xd73479fd } }, + /* 59 */ + { { 0x5ad4c6e5,0x7edefb16,0x5b06d04d,0x262cf08f,0x8575cb14,0x12ed5bb1, + 0x0771666b,0x816469e3 }, + { 0x561e291e,0xd7ab9d79,0xc1de1661,0xeb9daf22,0x135e0513,0xf49827eb, + 0xf0dd3f9c,0x0a36dd23 } }, + /* 60 */ + { { 0x41d5533c,0x098d32c7,0x8684628f,0x7c5f5a9e,0xe349bd11,0x39a228ad, + 0xfdbab118,0xe331dfd6 }, + { 0x6bcc6ed8,0x5100ab68,0xef7a260e,0x7160c3bd,0xbce850d7,0x9063d9a7, + 0x492e3389,0xd3b4782a } }, + /* 61 */ + { { 0xf3821f90,0xa149b6e8,0x66eb7aad,0x92edd9ed,0x1a013116,0x0bb66953, + 0x4c86a5bd,0x7281275a }, + { 0xd3ff47e5,0x503858f7,0x61016441,0x5e1616bc,0x7dfd9bb1,0x62b0f11a, + 0xce145059,0x2c062e7e } }, + /* 62 */ + { { 0x0159ac2e,0xa76f996f,0xcbdb2713,0x281e7736,0x08e46047,0x2ad6d288, + 0x2c4e7ef1,0x282a35f9 }, + { 0xc0ce5cd2,0x9c354b1e,0x1379c229,0xcf99efc9,0x3e82c11e,0x992caf38, + 0x554d2abd,0xc71cd513 } }, + /* 63 */ + { { 0x09b578f4,0x4885de9c,0xe3affa7a,0x1884e258,0x59182f1f,0x8f76b1b7, + 0xcf47f3a3,0xc50f6740 }, + { 0x374b68ea,0xa9c4adf3,0x69965fe2,0xa406f323,0x85a53050,0x2f86a222, + 0x212958dc,0xb9ecb3a7 } }, + /* 64 */ + { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e, + 0xcd42ab1b,0x803f3e02 }, + { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e } }, + /* 65 */ + { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5 }, + { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418, + 0xe2d41c8b,0x23d0f130 } }, + /* 66 */ + { { 0xf41500d9,0x857ab6ed,0xfcbeada8,0x0d890ae5,0x89725951,0x52fe8648, + 0xc0a3fadd,0xb0288dd6 }, + { 0x650bcb08,0x85320f30,0x695d6e16,0x71af6313,0xb989aa76,0x31f520a7, + 0xf408c8d2,0xffd3724f } }, + /* 67 */ + { { 0xb458e6cb,0x53968e64,0x317a5d28,0x992dad20,0x7aa75f56,0x3814ae0b, + 0xd78c26df,0xf5590f4a }, + { 0xcf0ba55a,0x0fc24bd3,0x0c778bae,0x0fc4724a,0x683b674a,0x1ce9864f, + 0xf6f74a20,0x18d6da54 } }, + /* 68 */ + { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9 }, + { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b, + 0x01fe49c3,0x2b100118 } }, + /* 69 */ + { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999 }, + { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551 } }, + /* 70 */ + { { 0x1e9af288,0x55f655bb,0xf7ada931,0x647e1a64,0xcb2820e5,0x43697e4b, + 0x07ed56ff,0x51e00db1 }, + { 0x771c327e,0x43d169b8,0x4a96c2ad,0x29cdb20b,0x3deb4779,0xc07d51f5, + 0x49829177,0xe22f4241 } }, + /* 71 */ + { { 0x635f1abb,0xcd45e8f4,0x68538874,0x7edc0cb5,0xb5a8034d,0xc9472c1f, + 0x52dc48c9,0xf709373d }, + { 0xa8af30d6,0x401966bb,0xf137b69c,0x95bf5f4a,0x9361c47e,0x3966162a, + 0xe7275b11,0xbd52d288 } }, + /* 72 */ + { { 0x9c5fa877,0xab155c7a,0x7d3a3d48,0x17dad672,0x73d189d8,0x43f43f9e, + 0xc8aa77a6,0xa0d0f8e4 }, + { 0xcc94f92d,0x0bbeafd8,0x0c4ddb3a,0xd818c8be,0xb82eba14,0x22cc65f8, + 0x946d6a00,0xa56c78c7 } }, + /* 73 */ + { { 0x0dd09529,0x2962391b,0x3daddfcf,0x803e0ea6,0x5b5bf481,0x2c77351f, + 0x731a367a,0xd8befdf8 }, + { 0xfc0157f4,0xab919d42,0xfec8e650,0xf51caed7,0x02d48b0a,0xcdf9cb40, + 0xce9f6478,0x854a68a5 } }, + /* 74 */ + { { 0x63506ea5,0xdc35f67b,0xa4fe0d66,0x9286c489,0xfe95cd4d,0x3f101d3b, + 0x98846a95,0x5cacea0b }, + { 0x9ceac44d,0xa90df60c,0x354d1c3a,0x3db29af4,0xad5dbabe,0x08dd3de8, + 0x35e4efa9,0xe4982d12 } }, + /* 75 */ + { { 0xc34cd55e,0x23104a22,0x2680d132,0x58695bb3,0x1fa1d943,0xfb345afa, + 0x16b20499,0x8046b7f6 }, + { 0x38e7d098,0xb533581e,0xf46f0b70,0xd7f61e8d,0x44cb78c4,0x30dea9ea, + 0x9082af55,0xeb17ca7b } }, + /* 76 */ + { { 0x76a145b9,0x1751b598,0xc1bc71ec,0xa5cf6b0f,0x392715bb,0xd3e03565, + 0xfab5e131,0x097b00ba }, + { 0x565f69e1,0xaa66c8e9,0xb5be5199,0x77e8f75a,0xda4fd984,0x6033ba11, + 0xafdbcc9e,0xf95c747b } }, + /* 77 */ + { { 0xbebae45e,0x558f01d3,0xc4bc6955,0xa8ebe9f0,0xdbc64fc6,0xaeb705b1, + 0x566ed837,0x3512601e }, + { 0xfa1161cd,0x9336f1e1,0x4c65ef87,0x328ab8d5,0x724f21e5,0x4757eee2, + 0x6068ab6b,0x0ef97123 } }, + /* 78 */ + { { 0x54ca4226,0x02598cf7,0xf8642c8e,0x5eede138,0x468e1790,0x48963f74, + 0x3b4fbc95,0xfc16d933 }, + { 0xe7c800ca,0xbe96fb31,0x2678adaa,0x13806331,0x6ff3e8b5,0x3d624497, + 0xb95d7a17,0x14ca4af1 } }, + /* 79 */ + { { 0xbd2f81d5,0x7a4771ba,0x01f7d196,0x1a5f9d69,0xcad9c907,0xd898bef7, + 0xf59c231d,0x4057b063 }, + { 0x89c05c0a,0xbffd82fe,0x1dc0df85,0xe4911c6f,0xa35a16db,0x3befccae, + 0xf1330b13,0x1c3b5d64 } }, + /* 80 */ + { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148 }, + { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875, + 0x9f0e1a84,0x77387de3 } }, + /* 81 */ + { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0 }, + { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8 } }, + /* 82 */ + { { 0x84e35743,0x32aa3202,0x85a3cdef,0x320d6ab1,0x1df19819,0xb821b176, + 0xc433851f,0x5721361f }, + { 0x71fc9168,0x1f0db36a,0x5e5c403c,0x5f98ba73,0x37bcd8f5,0xf64ca87e, + 0xe6bb11bd,0xdcbac3c9 } }, + /* 83 */ + { { 0x4518cbe2,0xf01d9968,0x9c9eb04e,0xd242fc18,0xe47feebf,0x727663c7, + 0x2d626862,0xb8c1c89e }, + { 0xc8e1d569,0x51a58bdd,0xb7d88cd0,0x563809c8,0xf11f31eb,0x26c27fd9, + 0x2f9422d4,0x5d23bbda } }, + /* 84 */ + { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb }, + { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f } }, + /* 85 */ + { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52 }, + { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f } }, + /* 86 */ + { { 0x562976cc,0xbda5f14e,0x0ef12c38,0x22bca3e6,0x6cca9852,0xbbfa3064, + 0x08e2987a,0xbdb79dc8 }, + { 0xcb06a772,0xfd2cb5c9,0xfe536dce,0x38f475aa,0x7c2b5db8,0xc2a3e022, + 0xadd3c14a,0x8ee86001 } }, + /* 87 */ + { { 0xa4ade873,0xcbe96981,0xc4fba48c,0x7ee9aa4d,0x5a054ba5,0x2cee2899, + 0x6f77aa4b,0x92e51d7a }, + { 0x7190a34d,0x948bafa8,0xf6bd1ed1,0xd698f75b,0x0caf1144,0xd00ee6e3, + 0x0a56aaaa,0x5182f86f } }, + /* 88 */ + { { 0x7a4cc99c,0xfba6212c,0x3e6d9ca1,0xff609b68,0x5ac98c5a,0x5dbb27cb, + 0x4073a6f2,0x91dcab5d }, + { 0x5f575a70,0x01b6cc3d,0x6f8d87fa,0x0cb36139,0x89981736,0x165d4e8c, + 0x97974f2b,0x17a0cedb } }, + /* 89 */ + { { 0x076c8d3a,0x38861e2a,0x210f924b,0x701aad39,0x13a835d9,0x94d0eae4, + 0x7f4cdf41,0x2e8ce36c }, + { 0x037a862b,0x91273dab,0x60e4c8fa,0x01ba9bb7,0x33baf2dd,0xf9645388, + 0x34f668f3,0xf4ccc6cb } }, + /* 90 */ + { { 0xf1f79687,0x44ef525c,0x92efa815,0x7c595495,0xa5c78d29,0xe1231741, + 0x9a0df3c9,0xac0db488 }, + { 0xdf01747f,0x86bfc711,0xef17df13,0x592b9358,0x5ccb6bb5,0xe5880e4f, + 0x94c974a2,0x95a64a61 } }, + /* 91 */ + { { 0xc15a4c93,0x72c1efda,0x82585141,0x40269b73,0x16cb0bad,0x6a8dfb1c, + 0x29210677,0x231e54ba }, + { 0x8ae6d2dc,0xa70df917,0x39112918,0x4d6aa63f,0x5e5b7223,0xf627726b, + 0xd8a731e1,0xab0be032 } }, + /* 92 */ + { { 0x8d131f2d,0x097ad0e9,0x3b04f101,0x637f09e3,0xd5e9a748,0x1ac86196, + 0x2cf6a679,0xf1bcc880 }, + { 0xe8daacb4,0x25c69140,0x60f65009,0x3c4e4055,0x477937a6,0x591cc8fc, + 0x5aebb271,0x85169469 } }, + /* 93 */ + { { 0xf1dcf593,0xde35c143,0xb018be3b,0x78202b29,0x9bdd9d3d,0xe9cdadc2, + 0xdaad55d8,0x8f67d9d2 }, + { 0x7481ea5f,0x84111656,0xe34c590c,0xe7d2dde9,0x05053fa8,0xffdd43f4, + 0xc0728b5d,0xf84572b9 } }, + /* 94 */ + { { 0x97af71c9,0x5e1a7a71,0x7a736565,0xa1449444,0x0e1d5063,0xa1b4ae07, + 0x616b2c19,0xedee2710 }, + { 0x11734121,0xb2f034f5,0x4a25e9f0,0x1cac6e55,0xa40c2ecf,0x8dc148f3, + 0x44ebd7f4,0x9fd27e9b } }, + /* 95 */ + { { 0xf6e2cb16,0x3cc7658a,0xfe5919b6,0xe3eb7d2c,0x168d5583,0x5a8c5816, + 0x958ff387,0xa40c2fb6 }, + { 0xfedcc158,0x8c9ec560,0x55f23056,0x7ad804c6,0x9a307e12,0xd9396704, + 0x7dc6decf,0x99bc9bb8 } }, + /* 96 */ + { { 0x927dafc6,0x84a9521d,0x5c09cd19,0x52c1fb69,0xf9366dde,0x9d9581a0, + 0xa16d7e64,0x9abe210b }, + { 0x48915220,0x480af84a,0x4dd816c6,0xfa73176a,0x1681ca5a,0xc7d53987, + 0x87f344b0,0x7881c257 } }, + /* 97 */ + { { 0xe0bcf3ff,0x93399b51,0x127f74f6,0x0d02cbc5,0xdd01d968,0x8fb465a2, + 0xa30e8940,0x15e6e319 }, + { 0x3e0e05f4,0x646d6e0d,0x43588404,0xfad7bddc,0xc4f850d3,0xbe61c7d1, + 0x191172ce,0x0e55facf } }, + /* 98 */ + { { 0xf8787564,0x7e9d9806,0x31e85ce6,0x1a331721,0xb819e8d6,0x6b0158ca, + 0x6fe96577,0xd73d0976 }, + { 0x1eb7206e,0x42483425,0xc618bb42,0xa519290f,0x5e30a520,0x5dcbb859, + 0x8f15a50b,0x9250a374 } }, + /* 99 */ + { { 0xbe577410,0xcaff08f8,0x5077a8c6,0xfd408a03,0xec0a63a4,0xf1f63289, + 0xc1cc8c0b,0x77414082 }, + { 0xeb0991cd,0x05a40fa6,0x49fdc296,0xc1ca0866,0xb324fd40,0x3a68a3c7, + 0x12eb20b9,0x8cb04f4d } }, + /* 100 */ + { { 0x6906171c,0xb1c2d055,0xb0240c3f,0x9073e9cd,0xd8906841,0xdb8e6b4f, + 0x47123b51,0xe4e429ef }, + { 0x38ec36f4,0x0b8dd53c,0xff4b6a27,0xf9d2dc01,0x879a9a48,0x5d066e07, + 0x3c6e6552,0x37bca2ff } }, + /* 101 */ + { { 0xdf562470,0x4cd2e3c7,0xc0964ac9,0x44f272a2,0x80c793be,0x7c6d5df9, + 0x3002b22a,0x59913edc }, + { 0x5750592a,0x7a139a83,0xe783de02,0x99e01d80,0xea05d64f,0xcf8c0375, + 0xb013e226,0x43786e4a } }, + /* 102 */ + { { 0x9e56b5a6,0xff32b0ed,0xd9fc68f9,0x0750d9a6,0x597846a7,0xec15e845, + 0xb7e79e7a,0x8638ca98 }, + { 0x0afc24b2,0x2f5ae096,0x4dace8f2,0x05398eaf,0xaecba78f,0x3b765dd0, + 0x7b3aa6f0,0x1ecdd36a } }, + /* 103 */ + { { 0x6c5ff2f3,0x5d3acd62,0x2873a978,0xa2d516c0,0xd2110d54,0xad94c9fa, + 0xd459f32d,0xd85d0f85 }, + { 0x10b11da3,0x9f700b8d,0xa78318c4,0xd2c22c30,0x9208decd,0x556988f4, + 0xb4ed3c62,0xa04f19c3 } }, + /* 104 */ + { { 0xed7f93bd,0x087924c8,0x392f51f6,0xcb64ac5d,0x821b71af,0x7cae330a, + 0x5c0950b0,0x92b2eeea }, + { 0x85b6e235,0x85ac4c94,0x2936c0f0,0xab2ca4a9,0xe0508891,0x80faa6b3, + 0x5834276c,0x1ee78221 } }, + /* 105 */ + { { 0xe63e79f7,0xa60a2e00,0xf399d906,0xf590e7b2,0x6607c09d,0x9021054a, + 0x57a6e150,0xf3f2ced8 }, + { 0xf10d9b55,0x200510f3,0xd8642648,0x9d2fcfac,0xe8bd0e7c,0xe5631aa7, + 0x3da3e210,0x0f56a454 } }, + /* 106 */ + { { 0x1043e0df,0x5b21bffa,0x9c007e6d,0x6c74b6cc,0xd4a8517a,0x1a656ec0, + 0x1969e263,0xbd8f1741 }, + { 0xbeb7494a,0x8a9bbb86,0x45f3b838,0x1567d46f,0xa4e5a79a,0xdf7a12a7, + 0x30ccfa09,0x2d1a1c35 } }, + /* 107 */ + { { 0x506508da,0x192e3813,0xa1d795a7,0x336180c4,0x7a9944b3,0xcddb5949, + 0xb91fba46,0xa107a65e }, + { 0x0f94d639,0xe6d1d1c5,0x8a58b7d7,0x8b4af375,0xbd37ca1c,0x1a7c5584, + 0xf87a9af2,0x183d760a } }, + /* 108 */ + { { 0x0dde59a4,0x29d69711,0x0e8bef87,0xf1ad8d07,0x4f2ebe78,0x229b4963, + 0xc269d754,0x1d44179d }, + { 0x8390d30e,0xb32dc0cf,0x0de8110c,0x0a3b2753,0x2bc0339a,0x31af1dc5, + 0x9606d262,0x771f9cc2 } }, + /* 109 */ + { { 0x85040739,0x99993e77,0x8026a939,0x44539db9,0xf5f8fc26,0xcf40f6f2, + 0x0362718e,0x64427a31 }, + { 0x85428aa8,0x4f4f2d87,0xebfb49a8,0x7b7adc3f,0xf23d01ac,0x201b2c6d, + 0x6ae90d6d,0x49d9b749 } }, + /* 110 */ + { { 0x435d1099,0xcc78d8bc,0x8e8d1a08,0x2adbcd4e,0x2cb68a41,0x02c2e2a0, + 0x3f605445,0x9037d81b }, + { 0x074c7b61,0x7cdbac27,0x57bfd72e,0xfe2031ab,0x596d5352,0x61ccec96, + 0x7cc0639c,0x08c3de6a } }, + /* 111 */ + { { 0xf6d552ab,0x20fdd020,0x05cd81f1,0x56baff98,0x91351291,0x06fb7c3e, + 0x45796b2f,0xc6909442 }, + { 0x41231bd1,0x17b3ae9c,0x5cc58205,0x1eac6e87,0xf9d6a122,0x208837ab, + 0xcafe3ac0,0x3fa3db02 } }, + /* 112 */ + { { 0x05058880,0xd75a3e65,0x643943f2,0x7da365ef,0xfab24925,0x4147861c, + 0xfdb808ff,0xc5c4bdb0 }, + { 0xb272b56b,0x73513e34,0x11b9043a,0xc8327e95,0xf8844969,0xfd8ce37d, + 0x46c2b6b5,0x2d56db94 } }, + /* 113 */ + { { 0xff46ac6b,0x2461782f,0x07a2e425,0xd19f7926,0x09a48de1,0xfafea3c4, + 0xe503ba42,0x0f56bd9d }, + { 0x345cda49,0x137d4ed1,0x816f299d,0x821158fc,0xaeb43402,0xe7c6a54a, + 0x1173b5f1,0x4003bb9d } }, + /* 114 */ + { { 0xa0803387,0x3b8e8189,0x39cbd404,0xece115f5,0xd2877f21,0x4297208d, + 0xa07f2f9e,0x53765522 }, + { 0xa8a4182d,0xa4980a21,0x3219df79,0xa2bbd07a,0x1a19a2d4,0x674d0a2e, + 0x6c5d4549,0x7a056f58 } }, + /* 115 */ + { { 0x9d8a2a47,0x646b2558,0xc3df2773,0x5b582948,0xabf0d539,0x51ec000e, + 0x7a1a2675,0x77d482f1 }, + { 0x87853948,0xb8a1bd95,0x6cfbffee,0xa6f817bd,0x80681e47,0xab6ec057, + 0x2b38b0e4,0x4115012b } }, + /* 116 */ + { { 0x6de28ced,0x3c73f0f4,0x9b13ec47,0x1d5da760,0x6e5c6392,0x61b8ce9e, + 0xfbea0946,0xcdf04572 }, + { 0x6c53c3b0,0x1cb3c58b,0x447b843c,0x97fe3c10,0x2cb9780e,0xfb2b8ae1, + 0x97383109,0xee703dda } }, + /* 117 */ + { { 0xff57e43a,0x34515140,0xb1b811b8,0xd44660d3,0x8f42b986,0x2b3b5dff, + 0xa162ce21,0x2a0ad89d }, + { 0x6bc277ba,0x64e4a694,0xc141c276,0xc788c954,0xcabf6274,0x141aa64c, + 0xac2b4659,0xd62d0b67 } }, + /* 118 */ + { { 0x2c054ac4,0x39c5d87b,0xf27df788,0x57005859,0xb18128d6,0xedf7cbf3, + 0x991c2426,0xb39a23f2 }, + { 0xf0b16ae5,0x95284a15,0xa136f51b,0x0c6a05b1,0xf2700783,0x1d63c137, + 0xc0674cc5,0x04ed0092 } }, + /* 119 */ + { { 0x9ae90393,0x1f4185d1,0x4a3d64e6,0x3047b429,0x9854fc14,0xae0001a6, + 0x0177c387,0xa0a91fc1 }, + { 0xae2c831e,0xff0a3f01,0x2b727e16,0xbb76ae82,0x5a3075b4,0x8f12c8a1, + 0x9ed20c41,0x084cf988 } }, + /* 120 */ + { { 0xfca6becf,0xd98509de,0x7dffb328,0x2fceae80,0x4778e8b9,0x5d8a15c4, + 0x73abf77e,0xd57955b2 }, + { 0x31b5d4f1,0x210da79e,0x3cfa7a1c,0xaa52f04b,0xdc27c20b,0xd4d12089, + 0x02d141f1,0x8e14ea42 } }, + /* 121 */ + { { 0xf2897042,0xeed50345,0x43402c4a,0x8d05331f,0xc8bdfb21,0xc8d9c194, + 0x2aa4d158,0x597e1a37 }, + { 0xcf0bd68c,0x0327ec1a,0xab024945,0x6d4be0dc,0xc9fe3e84,0x5b9c8d7a, + 0x199b4dea,0xca3f0236 } }, + /* 122 */ + { { 0x6170bd20,0x592a10b5,0x6d3f5de7,0x0ea897f1,0x44b2ade2,0xa3363ff1, + 0x309c07e4,0xbde7fd7e }, + { 0xb8f5432c,0x516bb6d2,0xe043444b,0x210dc1cb,0xf8f95b5a,0x3db01e6f, + 0x0a7dd198,0xb623ad0e } }, + /* 123 */ + { { 0x60c7b65b,0xa75bd675,0x23a4a289,0xab8c5590,0xd7b26795,0xf8220fd0, + 0x58ec137b,0xd6aa2e46 }, + { 0x5138bb85,0x10abc00b,0xd833a95c,0x8c31d121,0x1702a32e,0xb24ff00b, + 0x2dcc513a,0x111662e0 } }, + /* 124 */ + { { 0xefb42b87,0x78114015,0x1b6c4dff,0xbd9f5d70,0xa7d7c129,0x66ecccd7, + 0x94b750f8,0xdb3ee1cb }, + { 0xf34837cf,0xb26f3db0,0xb9578d4f,0xe7eed18b,0x7c56657d,0x5d2cdf93, + 0x52206a59,0x886a6442 } }, + /* 125 */ + { { 0x65b569ea,0x3c234cfb,0xf72119c1,0x20011141,0xa15a619e,0x8badc85d, + 0x018a17bc,0xa70cf4eb }, + { 0x8c4a6a65,0x224f97ae,0x0134378f,0x36e5cf27,0x4f7e0960,0xbe3a609e, + 0xd1747b77,0xaa4772ab } }, + /* 126 */ + { { 0x7aa60cc0,0x67676131,0x0368115f,0xc7916361,0xbbc1bb5a,0xded98bb4, + 0x30faf974,0x611a6ddc }, + { 0xc15ee47a,0x30e78cbc,0x4e0d96a5,0x2e896282,0x3dd9ed88,0x36f35adf, + 0x16429c88,0x5cfffaf8 } }, + /* 127 */ + { { 0x9b7a99cd,0xc0d54cff,0x843c45a1,0x7bf3b99d,0x62c739e1,0x038a908f, + 0x7dc1994c,0x6e5a6b23 }, + { 0x0ba5db77,0xef8b454e,0xacf60d63,0xb7b8807f,0x76608378,0xe591c0c6, + 0x242dabcc,0x481a238d } }, + /* 128 */ + { { 0x35d0b34a,0xe3417bc0,0x8327c0a7,0x440b386b,0xac0362d1,0x8fb7262d, + 0xe0cdf943,0x2c41114c }, + { 0xad95a0b1,0x2ba5cef1,0x67d54362,0xc09b37a8,0x01e486c9,0x26d6cdd2, + 0x42ff9297,0x20477abf } }, + /* 129 */ + { { 0x18d65dbf,0x2f75173c,0x339edad8,0x77bf940e,0xdcf1001c,0x7022d26b, + 0xc77396b6,0xac66409a }, + { 0xc6261cc3,0x8b0bb36f,0x190e7e90,0x213f7bc9,0xa45e6c10,0x6541ceba, + 0xcc122f85,0xce8e6975 } }, + /* 130 */ + { { 0xbc0a67d2,0x0f121b41,0x444d248a,0x62d4760a,0x659b4737,0x0e044f1d, + 0x250bb4a8,0x08fde365 }, + { 0x848bf287,0xaceec3da,0xd3369d6e,0xc2a62182,0x92449482,0x3582dfdc, + 0x565d6cd7,0x2f7e2fd2 } }, + /* 131 */ + { { 0xc3770fa7,0xae4b92db,0x379043f9,0x095e8d5c,0x17761171,0x54f34e9d, + 0x907702ae,0xc65be92e }, + { 0xf6fd0a40,0x2758a303,0xbcce784b,0xe7d822e3,0x4f9767bf,0x7ae4f585, + 0xd1193b3a,0x4bff8e47 } }, + /* 132 */ + { { 0x00ff1480,0xcd41d21f,0x0754db16,0x2ab8fb7d,0xbbe0f3ea,0xac81d2ef, + 0x5772967d,0x3e4e4ae6 }, + { 0x3c5303e6,0x7e18f36d,0x92262397,0x3bd9994b,0x1324c3c0,0x9ed70e26, + 0x58ec6028,0x5388aefd } }, + /* 133 */ + { { 0x5e5d7713,0xad1317eb,0x75de49da,0x09b985ee,0xc74fb261,0x32f5bc4f, + 0x4f75be0e,0x5cf908d1 }, + { 0x8e657b12,0x76043510,0xb96ed9e6,0xbfd421a5,0x8970ccc2,0x0e29f51f, + 0x60f00ce2,0xa698ba40 } }, + /* 134 */ + { { 0xef748fec,0x73db1686,0x7e9d2cf9,0xe6e755a2,0xce265eff,0x630b6544, + 0x7aebad8d,0xb142ef8a }, + { 0x17d5770a,0xad31af9f,0x2cb3412f,0x66af3b67,0xdf3359de,0x6bd60d1b, + 0x58515075,0xd1896a96 } }, + /* 135 */ + { { 0x33c41c08,0xec5957ab,0x5468e2e1,0x87de94ac,0xac472f6c,0x18816b73, + 0x7981da39,0x267b0e0b }, + { 0x8e62b988,0x6e554e5d,0x116d21e7,0xd8ddc755,0x3d2a6f99,0x4610faf0, + 0xa1119393,0xb54e287a } }, + /* 136 */ + { { 0x178a876b,0x0a0122b5,0x085104b4,0x51ff96ff,0x14f29f76,0x050b31ab, + 0x5f87d4e6,0x84abb28b }, + { 0x8270790a,0xd5ed439f,0x85e3f46b,0x2d6cb59d,0x6c1e2212,0x75f55c1b, + 0x17655640,0xe5436f67 } }, + /* 137 */ + { { 0x2286e8d5,0x53f9025e,0x864453be,0x353c95b4,0xe408e3a0,0xd832f5bd, + 0x5b9ce99e,0x0404f68b }, + { 0xa781e8e5,0xcad33bde,0x163c2f5b,0x3cdf5018,0x0119caa3,0x57576960, + 0x0ac1c701,0x3a4263df } }, + /* 138 */ + { { 0x9aeb596d,0xc2965ecc,0x023c92b4,0x01ea03e7,0x2e013961,0x4704b4b6, + 0x905ea367,0x0ca8fd3f }, + { 0x551b2b61,0x92523a42,0x390fcd06,0x1eb7a89c,0x0392a63e,0xe7f1d2be, + 0x4ddb0c33,0x96dca264 } }, + /* 139 */ + { { 0x387510af,0x203bb43a,0xa9a36a01,0x846feaa8,0x2f950378,0xd23a5770, + 0x3aad59dc,0x4363e212 }, + { 0x40246a47,0xca43a1c7,0xe55dd24d,0xb362b8d2,0x5d8faf96,0xf9b08604, + 0xd8bb98c4,0x840e115c } }, + /* 140 */ + { { 0x1023e8a7,0xf12205e2,0xd8dc7a0b,0xc808a8cd,0x163a5ddf,0xe292a272, + 0x30ded6d4,0x5e0d6abd }, + { 0x7cfc0f64,0x07a721c2,0x0e55ed88,0x42eec01d,0x1d1f9db2,0x26a7bef9, + 0x2945a25a,0x7dea48f4 } }, + /* 141 */ + { { 0xe5060a81,0xabdf6f1c,0xf8f95615,0xe79f9c72,0x06ac268b,0xcfd36c54, + 0xebfd16d1,0xabc2a2be }, + { 0xd3e2eac7,0x8ac66f91,0xd2dd0466,0x6f10ba63,0x0282d31b,0x6790e377, + 0x6c7eefc1,0x4ea35394 } }, + /* 142 */ + { { 0x5266309d,0xed8a2f8d,0x81945a3e,0x0a51c6c0,0x578c5dc1,0xcecaf45a, + 0x1c94ffc3,0x3a76e689 }, + { 0x7d7b0d0f,0x9aace8a4,0x8f584a5f,0x963ace96,0x4e697fbe,0x51a30c72, + 0x465e6464,0x8212a10a } }, + /* 143 */ + { { 0xcfab8caa,0xef7c61c3,0x0e142390,0x18eb8e84,0x7e9733ca,0xcd1dff67, + 0x599cb164,0xaa7cab71 }, + { 0xbc837bd1,0x02fc9273,0xc36af5d7,0xc06407d0,0xf423da49,0x17621292, + 0xfe0617c3,0x40e38073 } }, + /* 144 */ + { { 0xa7bf9b7c,0xf4f80824,0x3fbe30d0,0x365d2320,0x97cf9ce3,0xbfbe5320, + 0xb3055526,0xe3604700 }, + { 0x6cc6c2c7,0x4dcb9911,0xba4cbee6,0x72683708,0x637ad9ec,0xdcded434, + 0xa3dee15f,0x6542d677 } }, + /* 145 */ + { { 0x7b6c377a,0x3f32b6d0,0x903448be,0x6cb03847,0x20da8af7,0xd6fdd3a8, + 0x09bb6f21,0xa6534aee }, + { 0x1035facf,0x30a1780d,0x9dcb47e6,0x35e55a33,0xc447f393,0x6ea50fe1, + 0xdc9aef22,0xf3cb672f } }, + /* 146 */ + { { 0x3b55fd83,0xeb3719fe,0x875ddd10,0xe0d7a46c,0x05cea784,0x33ac9fa9, + 0xaae870e7,0x7cafaa2e }, + { 0x1d53b338,0x9b814d04,0xef87e6c6,0xe0acc0a0,0x11672b0f,0xfb93d108, + 0xb9bd522e,0x0aab13c1 } }, + /* 147 */ + { { 0xd2681297,0xddcce278,0xb509546a,0xcb350eb1,0x7661aaf2,0x2dc43173, + 0x847012e9,0x4b91a602 }, + { 0x72f8ddcf,0xdcff1095,0x9a911af4,0x08ebf61e,0xc372430e,0x48f4360a, + 0x72321cab,0x49534c53 } }, + /* 148 */ + { { 0xf07b7e9d,0x83df7d71,0x13cd516f,0xa478efa3,0x6c047ee3,0x78ef264b, + 0xd65ac5ee,0xcaf46c4f }, + { 0x92aa8266,0xa04d0c77,0x913684bb,0xedf45466,0xae4b16b0,0x56e65168, + 0x04c6770f,0x14ce9e57 } }, + /* 149 */ + { { 0x965e8f91,0x99445e3e,0xcb0f2492,0xd3aca1ba,0x90c8a0a0,0xd31cc70f, + 0x3e4c9a71,0x1bb708a5 }, + { 0x558bdd7a,0xd5ca9e69,0x018a26b1,0x734a0508,0x4c9cf1ec,0xb093aa71, + 0xda300102,0xf9d126f2 } }, + /* 150 */ + { { 0xaff9563e,0x749bca7a,0xb49914a0,0xdd077afe,0xbf5f1671,0xe27a0311, + 0x729ecc69,0x807afcb9 }, + { 0xc9b08b77,0x7f8a9337,0x443c7e38,0x86c3a785,0x476fd8ba,0x85fafa59, + 0x6568cd8c,0x751adcd1 } }, + /* 151 */ + { { 0x10715c0d,0x8aea38b4,0x8f7697f7,0xd113ea71,0x93fbf06d,0x665eab14, + 0x2537743f,0x29ec4468 }, + { 0xb50bebbc,0x3d94719c,0xe4505422,0x399ee5bf,0x8d2dedb1,0x90cd5b3a, + 0x92a4077d,0xff9370e3 } }, + /* 152 */ + { { 0xc6b75b65,0x59a2d69b,0x266651c5,0x4188f8d5,0x3de9d7d2,0x28a9f33e, + 0xa2a9d01a,0x9776478b }, + { 0x929af2c7,0x8852622d,0x4e690923,0x334f5d6d,0xa89a51e9,0xce6cc7e5, + 0xac2f82fa,0x74a6313f } }, + /* 153 */ + { { 0xb75f079c,0xb2f4dfdd,0x18e36fbb,0x85b07c95,0xe7cd36dd,0x1b6cfcf0, + 0x0ff4863d,0xab75be15 }, + { 0x173fc9b7,0x81b367c0,0xd2594fd0,0xb90a7420,0xc4091236,0x15fdbf03, + 0x0b4459f6,0x4ebeac2e } }, + /* 154 */ + { { 0x5c9f2c53,0xeb6c5fe7,0x8eae9411,0xd2522011,0xf95ac5d8,0xc8887633, + 0x2c1baffc,0xdf99887b }, + { 0x850aaecb,0xbb78eed2,0x01d6a272,0x9d49181b,0xb1cdbcac,0x978dd511, + 0x779f4058,0x27b040a7 } }, + /* 155 */ + { { 0xf73b2eb2,0x90405db7,0x8e1b2118,0xe0df8508,0x5962327e,0x501b7152, + 0xe4cfa3f5,0xb393dd37 }, + { 0x3fd75165,0xa1230e7b,0xbcd33554,0xd66344c2,0x0f7b5022,0x6c36f1be, + 0xd0463419,0x09588c12 } }, + /* 156 */ + { { 0x02601c3b,0xe086093f,0xcf5c335f,0xfb0252f8,0x894aff28,0x955cf280, + 0xdb9f648b,0x81c879a9 }, + { 0xc6f56c51,0x040e687c,0x3f17618c,0xfed47169,0x9059353b,0x44f88a41, + 0x5fc11bc4,0xfa0d48f5 } }, + /* 157 */ + { { 0xe1608e4d,0xbc6e1c9d,0x3582822c,0x010dda11,0x157ec2d7,0xf6b7ddc1, + 0xb6a367d6,0x8ea0e156 }, + { 0x2383b3b4,0xa354e02f,0x3f01f53c,0x69966b94,0x2de03ca5,0x4ff6632b, + 0xfa00b5ac,0x3f5ab924 } }, + /* 158 */ + { { 0x59739efb,0x337bb0d9,0xe7ebec0d,0xc751b0f4,0x411a67d1,0x2da52dd6, + 0x2b74256e,0x8bc76887 }, + { 0x82d3d253,0xa5be3b72,0xf58d779f,0xa9f679a1,0xe16767bb,0xa1cac168, + 0x60fcf34f,0xb386f190 } }, + /* 159 */ + { { 0x2fedcfc2,0x31f3c135,0x62f8af0d,0x5396bf62,0xe57288c2,0x9a02b4ea, + 0x1b069c4d,0x4cb460f7 }, + { 0x5b8095ea,0xae67b4d3,0x6fc07603,0x92bbf859,0xb614a165,0xe1475f66, + 0x95ef5223,0x52c0d508 } }, + /* 160 */ + { { 0x15339848,0x231c210e,0x70778c8d,0xe87a28e8,0x6956e170,0x9d1de661, + 0x2bb09c0b,0x4ac3c938 }, + { 0x6998987d,0x19be0551,0xae09f4d6,0x8b2376c4,0x1a3f933d,0x1de0b765, + 0xe39705f4,0x380d94c7 } }, + /* 161 */ + { { 0x81542e75,0x01a355aa,0xee01b9b7,0x96c724a1,0x624d7087,0x6b3a2977, + 0xde2637af,0x2ce3e171 }, + { 0xf5d5bc1a,0xcfefeb49,0x2777e2b5,0xa655607e,0x9513756c,0x4feaac2f, + 0x0b624e4d,0x2e6cd852 } }, + /* 162 */ + { { 0x8c31c31d,0x3685954b,0x5bf21a0c,0x68533d00,0x75c79ec9,0x0bd7626e, + 0x42c69d54,0xca177547 }, + { 0xf6d2dbb2,0xcc6edaff,0x174a9d18,0xfd0d8cbd,0xaa4578e8,0x875e8793, + 0x9cab2ce6,0xa976a713 } }, + /* 163 */ + { { 0x93fb353d,0x0a651f1b,0x57fcfa72,0xd75cab8b,0x31b15281,0xaa88cfa7, + 0x0a1f4999,0x8720a717 }, + { 0x693e1b90,0x8c3e8d37,0x16f6dfc3,0xd345dc0b,0xb52a8742,0x8ea8d00a, + 0xc769893c,0x9719ef29 } }, + /* 164 */ + { { 0x58e35909,0x820eed8d,0x33ddc116,0x9366d8dc,0x6e205026,0xd7f999d0, + 0xe15704c1,0xa5072976 }, + { 0xc4e70b2e,0x002a37ea,0x6890aa8a,0x84dcf657,0x645b2a5c,0xcd71bf18, + 0xf7b77725,0x99389c9d } }, + /* 165 */ + { { 0x7ada7a4b,0x238c08f2,0xfd389366,0x3abe9d03,0x766f512c,0x6b672e89, + 0x202c82e4,0xa88806aa }, + { 0xd380184e,0x6602044a,0x126a8b85,0xa8cb78c4,0xad844f17,0x79d670c0, + 0x4738dcfe,0x0043bffb } }, + /* 166 */ + { { 0x36d5192e,0x8d59b5dc,0x4590b2af,0xacf885d3,0x11601781,0x83566d0a, + 0xba6c4866,0x52f3ef01 }, + { 0x0edcb64d,0x3986732a,0x8068379f,0x0a482c23,0x7040f309,0x16cbe5fa, + 0x9ef27e75,0x3296bd89 } }, + /* 167 */ + { { 0x454d81d7,0x476aba89,0x51eb9b3c,0x9eade7ef,0x81c57986,0x619a21cd, + 0xaee571e9,0x3b90febf }, + { 0x5496f7cb,0x9393023e,0x7fb51bc4,0x55be41d8,0x99beb5ce,0x03f1dd48, + 0x9f810b18,0x6e88069d } }, + /* 168 */ + { { 0xb43ea1db,0xce37ab11,0x5259d292,0x0a7ff1a9,0x8f84f186,0x851b0221, + 0xdefaad13,0xa7222bea }, + { 0x2b0a9144,0xa2ac78ec,0xf2fa59c5,0x5a024051,0x6147ce38,0x91d1eca5, + 0xbc2ac690,0xbe94d523 } }, + /* 169 */ + { { 0x0b226ce7,0x72f4945e,0x967e8b70,0xb8afd747,0x85a6c63e,0xedea46f1, + 0x9be8c766,0x7782defe }, + { 0x3db38626,0x760d2aa4,0x76f67ad1,0x460ae787,0x54499cdb,0x341b86fc, + 0xa2892e4b,0x03838567 } }, + /* 170 */ + { { 0x79ec1a0f,0x2d8daefd,0xceb39c97,0x3bbcd6fd,0x58f61a95,0xf5575ffc, + 0xadf7b420,0xdbd986c4 }, + { 0x15f39eb7,0x81aa8814,0xb98d976c,0x6ee2fcf5,0xcf2f717d,0x5465475d, + 0x6860bbd0,0x8e24d3c4 } }, + /* 171 */ + { { 0x9a587390,0x749d8e54,0x0cbec588,0x12bb194f,0xb25983c6,0x46e07da4, + 0x407bafc8,0x541a99c4 }, + { 0x624c8842,0xdb241692,0xd86c05ff,0x6044c12a,0x4f7fcf62,0xc59d14b4, + 0xf57d35d1,0xc0092c49 } }, + /* 172 */ + { { 0xdf2e61ef,0xd3cc75c3,0x2e1b35ca,0x7e8841c8,0x909f29f4,0xc62d30d1, + 0x7286944d,0x75e40634 }, + { 0xbbc237d0,0xe7d41fc5,0xec4f01c9,0xc9537bf0,0x282bd534,0x91c51a16, + 0xc7848586,0x5b7cb658 } }, + /* 173 */ + { { 0x8a28ead1,0x964a7084,0xfd3b47f6,0x802dc508,0x767e5b39,0x9ae4bfd1, + 0x8df097a1,0x7ae13eba }, + { 0xeadd384e,0xfd216ef8,0xb6b2ff06,0x0361a2d9,0x4bcdb5f3,0x204b9878, + 0xe2a8e3fd,0x787d8074 } }, + /* 174 */ + { { 0x757fbb1c,0xc5e25d6b,0xca201deb,0xe47bddb2,0x6d2233ff,0x4a55e9a3, + 0x9ef28484,0x5c222819 }, + { 0x88315250,0x773d4a85,0x827097c1,0x21b21a2b,0xdef5d33f,0xab7c4ea1, + 0xbaf0f2b0,0xe45d37ab } }, + /* 175 */ + { { 0x28511c8a,0xd2df1e34,0xbdca6cd3,0xebb229c8,0x627c39a7,0x578a71a7, + 0x84dfb9d3,0xed7bc122 }, + { 0x93dea561,0xcf22a6df,0xd48f0ed1,0x5443f18d,0x5bad23e8,0xd8b86140, + 0x45ca6d27,0xaac97cc9 } }, + /* 176 */ + { { 0xa16bd00a,0xeb54ea74,0xf5c0bcc1,0xd839e9ad,0x1f9bfc06,0x092bb7f1, + 0x1163dc4e,0x318f97b3 }, + { 0xc30d7138,0xecc0c5be,0xabc30220,0x44e8df23,0xb0223606,0x2bb7972f, + 0x9a84ff4d,0xfa41faa1 } }, + /* 177 */ + { { 0xa6642269,0x4402d974,0x9bb783bd,0xc81814ce,0x7941e60b,0x398d38e4, + 0x1d26e9e2,0x38bb6b2c }, + { 0x6a577f87,0xc64e4a25,0xdc11fe1c,0x8b52d253,0x62280728,0xff336abf, + 0xce7601a5,0x94dd0905 } }, + /* 178 */ + { { 0xde93f92a,0x156cf7dc,0x89b5f315,0xa01333cb,0xc995e750,0x02404df9, + 0xd25c2ae9,0x92077867 }, + { 0x0bf39d44,0xe2471e01,0x96bb53d7,0x5f2c9020,0x5c9c3d8f,0x4c44b7b3, + 0xd29beb51,0x81e8428b } }, + /* 179 */ + { { 0xc477199f,0x6dd9c2ba,0x6b5ecdd9,0x8cb8eeee,0xee40fd0e,0x8af7db3f, + 0xdbbfa4b1,0x1b94ab62 }, + { 0xce47f143,0x44f0d8b3,0x63f46163,0x51e623fc,0xcc599383,0xf18f270f, + 0x055590ee,0x06a38e28 } }, + /* 180 */ + { { 0xb3355b49,0x2e5b0139,0xb4ebf99b,0x20e26560,0xd269f3dc,0xc08ffa6b, + 0x83d9d4f8,0xa7b36c20 }, + { 0x1b3e8830,0x64d15c3a,0xa89f9c0b,0xd5fceae1,0xe2d16930,0xcfeee4a2, + 0xa2822a20,0xbe54c6b4 } }, + /* 181 */ + { { 0x8d91167c,0xd6cdb3df,0xe7a6625e,0x517c3f79,0x346ac7f4,0x7105648f, + 0xeae022bb,0xbf30a5ab }, + { 0x93828a68,0x8e7785be,0x7f3ef036,0x5161c332,0x592146b2,0xe11b5feb, + 0x2732d13a,0xd1c820de } }, + /* 182 */ + { { 0x9038b363,0x043e1347,0x6b05e519,0x58c11f54,0x6026cad1,0x4fe57abe, + 0x68a18da3,0xb7d17bed }, + { 0xe29c2559,0x44ca5891,0x5bfffd84,0x4f7a0376,0x74e46948,0x498de4af, + 0x6412cc64,0x3997fd5e } }, + /* 183 */ + { { 0x8bd61507,0xf2074682,0x34a64d2a,0x29e132d5,0x8a8a15e3,0xffeddfb0, + 0x3c6c13e8,0x0eeb8929 }, + { 0xa7e259f8,0xe9b69a3e,0xd13e7e67,0xce1db7e6,0xad1fa685,0x277318f6, + 0xc922b6ef,0x228916f8 } }, + /* 184 */ + { { 0x0a12ab5b,0x959ae25b,0x957bc136,0xcc11171f,0xd16e2b0c,0x8058429e, + 0x6e93097e,0xec05ad1d }, + { 0xac3f3708,0x157ba5be,0x30b59d77,0x31baf935,0x118234e5,0x47b55237, + 0x7ff11b37,0x7d314156 } }, + /* 185 */ + { { 0xf6dfefab,0x7bd9c05c,0xdcb37707,0xbe2f2268,0x3a38bb95,0xe53ead97, + 0x9bc1d7a3,0xe9ce66fc }, + { 0x6f6a02a1,0x75aa1576,0x60e600ed,0x38c087df,0x68cdc1b9,0xf8947f34, + 0x72280651,0xd9650b01 } }, + /* 186 */ + { { 0x5a057e60,0x504b4c4a,0x8def25e4,0xcbccc3be,0x17c1ccbd,0xa6353208, + 0x804eb7a2,0x14d6699a }, + { 0xdb1f411a,0x2c8a8415,0xf80d769c,0x09fbaf0b,0x1c2f77ad,0xb4deef90, + 0x0d43598a,0x6f4c6841 } }, + /* 187 */ + { { 0x96c24a96,0x8726df4e,0xfcbd99a3,0x534dbc85,0x8b2ae30a,0x3c466ef2, + 0x61189abb,0x4c4350fd }, + { 0xf855b8da,0x2967f716,0x463c38a1,0x41a42394,0xeae93343,0xc37e1413, + 0x5a3118b5,0xa726d242 } }, + /* 188 */ + { { 0x948c1086,0xdae6b3ee,0xcbd3a2e1,0xf1de503d,0x03d022f3,0x3f35ed3f, + 0xcc6cf392,0x13639e82 }, + { 0xcdafaa86,0x9ac938fb,0x2654a258,0xf45bc5fb,0x45051329,0x1963b26e, + 0xc1a335a3,0xca9365e1 } }, + /* 189 */ + { { 0x4c3b2d20,0x3615ac75,0x904e241b,0x742a5417,0xcc9d071d,0xb08521c4, + 0x970b72a5,0x9ce29c34 }, + { 0x6d3e0ad6,0x8cc81f73,0xf2f8434c,0x8060da9e,0x6ce862d9,0x35ed1d1a, + 0xab42af98,0x48c4abd7 } }, + /* 190 */ + { { 0x40c7485a,0xd221b0cc,0xe5274dbf,0xead455bb,0x9263d2e8,0x493c7698, + 0xf67b33cb,0x78017c32 }, + { 0x930cb5ee,0xb9d35769,0x0c408ed2,0xc0d14e94,0x272f1a4d,0xf8b7bf55, + 0xde5c1c04,0x53cd0454 } }, + /* 191 */ + { { 0x5d28ccac,0xbcd585fa,0x005b746e,0x5f823e56,0xcd0123aa,0x7c79f0a1, + 0xd3d7fa8f,0xeea465c1 }, + { 0x0551803b,0x7810659f,0x7ce6af70,0x6c0b599f,0x29288e70,0x4195a770, + 0x7ae69193,0x1b6e42a4 } }, + /* 192 */ + { { 0xf67d04c3,0x2e80937c,0x89eeb811,0x1e312be2,0x92594d60,0x56b5d887, + 0x187fbd3d,0x0224da14 }, + { 0x0c5fe36f,0x87abb863,0x4ef51f5f,0x580f3c60,0xb3b429ec,0x964fb1bf, + 0x42bfff33,0x60838ef0 } }, + /* 193 */ + { { 0x7e0bbe99,0x432cb2f2,0x04aa39ee,0x7bda44f3,0x9fa93903,0x5f497c7a, + 0x2d331643,0x636eb202 }, + { 0x93ae00aa,0xfcfd0e61,0x31ae6d2f,0x875a00fe,0x9f93901c,0xf43658a2, + 0x39218bac,0x8844eeb6 } }, + /* 194 */ + { { 0x6b3bae58,0x114171d2,0x17e39f3e,0x7db3df71,0x81a8eada,0xcd37bc7f, + 0x51fb789e,0x27ba83dc }, + { 0xfbf54de5,0xa7df439f,0xb5fe1a71,0x7277030b,0xdb297a48,0x42ee8e35, + 0x87f3a4ab,0xadb62d34 } }, + /* 195 */ + { { 0xa175df2a,0x9b1168a2,0x618c32e9,0x082aa04f,0x146b0916,0xc9e4f2e7, + 0x75e7c8b2,0xb990fd76 }, + { 0x4df37313,0x0829d96b,0xd0b40789,0x1c205579,0x78087711,0x66c9ae4a, + 0x4d10d18d,0x81707ef9 } }, + /* 196 */ + { { 0x03d6ff96,0x97d7cab2,0x0d843360,0x5b851bfc,0xd042db4b,0x268823c4, + 0xd5a8aa5c,0x3792daea }, + { 0x941afa0b,0x52818865,0x42d83671,0xf3e9e741,0x5be4e0a7,0x17c82527, + 0x94b001ba,0x5abd635e } }, + /* 197 */ + { { 0x0ac4927c,0x727fa84e,0xa7c8cf23,0xe3886035,0x4adca0df,0xa4bcd5ea, + 0x846ab610,0x5995bf21 }, + { 0x829dfa33,0xe90f860b,0x958fc18b,0xcaafe2ae,0x78630366,0x9b3baf44, + 0xd483411e,0x44c32ca2 } }, + /* 198 */ + { { 0xe40ed80c,0xa74a97f1,0x31d2ca82,0x5f938cb1,0x7c2d6ad9,0x53f2124b, + 0x8082a54c,0x1f2162fb }, + { 0x720b173e,0x7e467cc5,0x085f12f9,0x40e8a666,0x4c9d65dc,0x8cebc20e, + 0xc3e907c9,0x8f1d402b } }, + /* 199 */ + { { 0xfbc4058a,0x4f592f9c,0x292f5670,0xb15e14b6,0xbc1d8c57,0xc55cfe37, + 0x926edbf9,0xb1980f43 }, + { 0x32c76b09,0x98c33e09,0x33b07f78,0x1df5279d,0x863bb461,0x6f08ead4, + 0x37448e45,0x2828ad9b } }, + /* 200 */ + { { 0xc4cf4ac5,0x696722c4,0xdde64afb,0xf5ac1a3f,0xe0890832,0x0551baa2, + 0x5a14b390,0x4973f127 }, + { 0x322eac5d,0xe59d8335,0x0bd9b568,0x5e07eef5,0xa2588393,0xab36720f, + 0xdb168ac7,0x6dac8ed0 } }, + /* 201 */ + { { 0xeda835ef,0xf7b545ae,0x1d10ed51,0x4aa113d2,0x13741b09,0x035a65e0, + 0x20b9de4c,0x4b23ef59 }, + { 0x3c4c7341,0xe82bb680,0x3f58bc37,0xd457706d,0xa51e3ee8,0x73527863, + 0xddf49a4e,0x4dd71534 } }, + /* 202 */ + { { 0x95476cd9,0xbf944672,0xe31a725b,0x648d072f,0xfc4b67e0,0x1441c8b8, + 0x2f4a4dbb,0xfd317000 }, + { 0x8995d0e1,0x1cb43ff4,0x0ef729aa,0x76e695d1,0x41798982,0xe0d5f976, + 0x9569f365,0x14fac58c } }, + /* 203 */ + { { 0xf312ae18,0xad9a0065,0xfcc93fc9,0x51958dc0,0x8a7d2846,0xd9a14240, + 0x36abda50,0xed7c7651 }, + { 0x25d4abbc,0x46270f1a,0xf1a113ea,0x9b5dd8f3,0x5b51952f,0xc609b075, + 0x4d2e9f53,0xfefcb7f7 } }, + /* 204 */ + { { 0xba119185,0xbd09497a,0xaac45ba4,0xd54e8c30,0xaa521179,0x492479de, + 0x87e0d80b,0x1801a57e }, + { 0xfcafffb0,0x073d3f8d,0xae255240,0x6cf33c0b,0x5b5fdfbc,0x781d763b, + 0x1ead1064,0x9f8fc11e } }, + /* 205 */ + { { 0x5e69544c,0x1583a171,0xf04b7813,0x0eaf8567,0x278a4c32,0x1e22a8fd, + 0x3d3a69a9,0xa9d3809d }, + { 0x59a2da3b,0x936c2c2c,0x1895c847,0x38ccbcf6,0x63d50869,0x5e65244e, + 0xe1178ef7,0x3006b9ae } }, + /* 206 */ + { { 0xc9eead28,0x0bb1f2b0,0x89f4dfbc,0x7eef635d,0xb2ce8939,0x074757fd, + 0x45f8f761,0x0ab85fd7 }, + { 0x3e5b4549,0xecda7c93,0x97922f21,0x4be2bb5c,0xb43b8040,0x261a1274, + 0x11e942c2,0xb122d675 } }, + /* 207 */ + { { 0x66a5ae7a,0x3be607be,0x76adcbe3,0x01e703fa,0x4eb6e5c5,0xaf904301, + 0x097dbaec,0x9f599dc1 }, + { 0x0ff250ed,0x6d75b718,0x349a20dc,0x8eb91574,0x10b227a3,0x425605a4, + 0x8a294b78,0x7d5528e0 } }, + /* 208 */ + { { 0x20c26def,0xf0f58f66,0x582b2d1e,0x025585ea,0x01ce3881,0xfbe7d79b, + 0x303f1730,0x28ccea01 }, + { 0x79644ba5,0xd1dabcd1,0x06fff0b8,0x1fc643e8,0x66b3e17b,0xa60a76fc, + 0xa1d013bf,0xc18baf48 } }, + /* 209 */ + { { 0x5dc4216d,0x34e638c8,0x206142ac,0x00c01067,0x95f5064a,0xd453a171, + 0xb7a9596b,0x9def809d }, + { 0x67ab8d2c,0x41e8642e,0x6237a2b6,0xb4240433,0x64c4218b,0x7d506a6d, + 0x68808ce5,0x0357f8b0 } }, + /* 210 */ + { { 0x4cd2cc88,0x8e9dbe64,0xf0b8f39d,0xcc61c28d,0xcd30a0c8,0x4a309874, + 0x1b489887,0xe4a01add }, + { 0xf57cd8f9,0x2ed1eeac,0xbd594c48,0x1b767d3e,0x7bd2f787,0xa7295c71, + 0xce10cc30,0x466d7d79 } }, + /* 211 */ + { { 0x9dada2c7,0x47d31892,0x8f9aa27d,0x4fa0a6c3,0x820a59e1,0x90e4fd28, + 0x451ead1a,0xc672a522 }, + { 0x5d86b655,0x30607cc8,0xf9ad4af1,0xf0235d3b,0x571172a6,0x99a08680, + 0xf2a67513,0x5e3d64fa } }, + /* 212 */ + { { 0x9b3b4416,0xaa6410c7,0xeab26d99,0xcd8fcf85,0xdb656a74,0x5ebff74a, + 0xeb8e42fc,0x6c8a7a95 }, + { 0xb02a63bd,0x10c60ba7,0x8b8f0047,0x6b2f2303,0x312d90b0,0x8c6c3738, + 0xad82ca91,0x348ae422 } }, + /* 213 */ + { { 0x5ccda2fb,0x7f474663,0x8e0726d2,0x22accaa1,0x492b1f20,0x85adf782, + 0xd9ef2d2e,0xc1074de0 }, + { 0xae9a65b3,0xfcf3ce44,0x05d7151b,0xfd71e4ac,0xce6a9788,0xd4711f50, + 0xc9e54ffc,0xfbadfbdb } }, + /* 214 */ + { { 0x20a99363,0x1713f1cd,0x6cf22775,0xb915658f,0x24d359b2,0x968175cd, + 0x83716fcd,0xb7f976b4 }, + { 0x5d6dbf74,0x5758e24d,0x71c3af36,0x8d23bafd,0x0243dfe3,0x48f47760, + 0xcafcc805,0xf4d41b2e } }, + /* 215 */ + { { 0xfdabd48d,0x51f1cf28,0x32c078a4,0xce81be36,0x117146e9,0x6ace2974, + 0xe0160f10,0x180824ea }, + { 0x66e58358,0x0387698b,0xce6ca358,0x63568752,0x5e41e6c5,0x82380e34, + 0x83cf6d25,0x67e5f639 } }, + /* 216 */ + { { 0xcf4899ef,0xf89ccb8d,0x9ebb44c0,0x949015f0,0xb2598ec9,0x546f9276, + 0x04c11fc6,0x9fef789a }, + { 0x53d2a071,0x6d367ecf,0xa4519b09,0xb10e1a7f,0x611e2eef,0xca6b3fb0, + 0xa99c4e20,0xbc80c181 } }, + /* 217 */ + { { 0xe5eb82e6,0x972536f8,0xf56cb920,0x1a484fc7,0x50b5da5e,0xc78e2171, + 0x9f8cdf10,0x49270e62 }, + { 0xea6b50ad,0x1a39b7bb,0xa2388ffc,0x9a0284c1,0x8107197b,0x5403eb17, + 0x61372f7f,0xd2ee52f9 } }, + /* 218 */ + { { 0x88e0362a,0xd37cd285,0x8fa5d94d,0x442fa8a7,0xa434a526,0xaff836e5, + 0xe5abb733,0xdfb478be }, + { 0x673eede6,0xa91f1ce7,0x2b5b2f04,0xa5390ad4,0x5530da2f,0x5e66f7bf, + 0x08df473a,0xd9a140b4 } }, + /* 219 */ + { { 0x6e8ea498,0x0e0221b5,0x3563ee09,0x62347829,0x335d2ade,0xe06b8391, + 0x623f4b1a,0x760c058d }, + { 0xc198aa79,0x0b89b58c,0xf07aba7f,0xf74890d2,0xfde2556a,0x4e204110, + 0x8f190409,0x7141982d } }, + /* 220 */ + { { 0x4d4b0f45,0x6f0a0e33,0x392a94e1,0xd9280b38,0xb3c61d5e,0x3af324c6, + 0x89d54e47,0x3af9d1ce }, + { 0x20930371,0xfd8f7981,0x21c17097,0xeda2664c,0xdc42309b,0x0e9545dc, + 0x73957dd6,0xb1f815c3 } }, + /* 221 */ + { { 0x89fec44a,0x84faa78e,0x3caa4caf,0xc8c2ae47,0xc1b6a624,0x691c807d, + 0x1543f052,0xa41aed14 }, + { 0x7d5ffe04,0x42435399,0x625b6e20,0x8bacb2df,0x87817775,0x85d660be, + 0x86fb60ef,0xd6e9c1dd } }, + /* 222 */ + { { 0xc6853264,0x3aa2e97e,0xe2304a0b,0x771533b7,0xb8eae9be,0x1b912bb7, + 0xae9bf8c2,0x9c9c6e10 }, + { 0xe030b74c,0xa2309a59,0x6a631e90,0x4ed7494d,0xa49b79f2,0x89f44b23, + 0x40fa61b6,0x566bd596 } }, + /* 223 */ + { { 0xc18061f3,0x066c0118,0x7c83fc70,0x190b25d3,0x27273245,0xf05fc8e0, + 0xf525345e,0xcf2c7390 }, + { 0x10eb30cf,0xa09bceb4,0x0d77703a,0xcfd2ebba,0x150ff255,0xe842c43a, + 0x8aa20979,0x02f51755 } }, + /* 224 */ + { { 0xaddb7d07,0x396ef794,0x24455500,0x0b4fc742,0xc78aa3ce,0xfaff8eac, + 0xe8d4d97d,0x14e9ada5 }, + { 0x2f7079e2,0xdaa480a1,0xe4b0800e,0x45baa3cd,0x7838157d,0x01765e2d, + 0x8e9d9ae8,0xa0ad4fab } }, + /* 225 */ + { { 0x4a653618,0x0bfb7621,0x31eaaa5f,0x1872813c,0x44949d5e,0x1553e737, + 0x6e56ed1e,0xbcd530b8 }, + { 0x32e9c47b,0x169be853,0xb50059ab,0xdc2776fe,0x192bfbb4,0xcdba9761, + 0x6979341d,0x909283cf } }, + /* 226 */ + { { 0x76e81a13,0x67b00324,0x62171239,0x9bee1a99,0xd32e19d6,0x08ed361b, + 0xace1549a,0x35eeb7c9 }, + { 0x7e4e5bdc,0x1280ae5a,0xb6ceec6e,0x2dcd2cd3,0x6e266bc1,0x52e4224c, + 0x448ae864,0x9a8b2cf4 } }, + /* 227 */ + { { 0x09d03b59,0xf6471bf2,0xb65af2ab,0xc90e62a3,0xebd5eec9,0xff7ff168, + 0xd4491379,0x6bdb60f4 }, + { 0x8a55bc30,0xdadafebc,0x10097fe0,0xc79ead16,0x4c1e3bdd,0x42e19741, + 0x94ba08a9,0x01ec3cfd } }, + /* 228 */ + { { 0xdc9485c2,0xba6277eb,0x22fb10c7,0x48cc9a79,0x70a28d8a,0x4f61d60f, + 0x475464f6,0xd1acb1c0 }, + { 0x26f36612,0xd26902b1,0xe0618d8b,0x59c3a44e,0x308357ee,0x4df8a813, + 0x405626c2,0x7dcd079d } }, + /* 229 */ + { { 0xf05a4b48,0x5ce7d4d3,0x37230772,0xadcd2952,0x812a915a,0xd18f7971, + 0x377d19b8,0x0bf53589 }, + { 0x6c68ea73,0x35ecd95a,0x823a584d,0xc7f3bbca,0xf473a723,0x9fb674c6, + 0xe16686fc,0xd28be4d9 } }, + /* 230 */ + { { 0x38fa8e4b,0x5d2b9906,0x893fd8fc,0x559f186e,0x436fb6fc,0x3a6de2aa, + 0x510f88ce,0xd76007aa }, + { 0x523a4988,0x2d10aab6,0x74dd0273,0xb455cf44,0xa3407278,0x7f467082, + 0xb303bb01,0xf2b52f68 } }, + /* 231 */ + { { 0x9835b4ca,0x0d57eafa,0xbb669cbc,0x2d2232fc,0xc6643198,0x8eeeb680, + 0xcc5aed3a,0xd8dbe98e }, + { 0xc5a02709,0xcba9be3f,0xf5ba1fa8,0x30be68e5,0xf10ea852,0xfebd43cd, + 0xee559705,0xe01593a3 } }, + /* 232 */ + { { 0xea75a0a6,0xd3e5af50,0x57858033,0x512226ac,0xd0176406,0x6fe6d50f, + 0xaeb8ef06,0xafec07b1 }, + { 0x80bb0a31,0x7fb99567,0x37309aae,0x6f1af3cc,0x01abf389,0x9153a15a, + 0x6e2dbfdd,0xa71b9354 } }, + /* 233 */ + { { 0x18f593d2,0xbf8e12e0,0xa078122b,0xd1a90428,0x0ba4f2ad,0x150505db, + 0x628523d9,0x53a2005c }, + { 0xe7f2b935,0x07c8b639,0xc182961a,0x2bff975a,0x7518ca2c,0x86bceea7, + 0x3d588e3d,0xbf47d19b } }, + /* 234 */ + { { 0xdd7665d5,0x672967a7,0x2f2f4de5,0x4e303057,0x80d4903f,0x144005ae, + 0x39c9a1b6,0x001c2c7f }, + { 0x69efc6d6,0x143a8014,0x7bc7a724,0xc810bdaa,0xa78150a4,0x5f65670b, + 0x86ffb99b,0xfdadf8e7 } }, + /* 235 */ + { { 0xffc00785,0xfd38cb88,0x3b48eb67,0x77fa7591,0xbf368fbc,0x0454d055, + 0x5aa43c94,0x3a838e4d }, + { 0x3e97bb9a,0x56166329,0x441d94d9,0x9eb93363,0x0adb2a83,0x515591a6, + 0x873e1da3,0x3cdb8257 } }, + /* 236 */ + { { 0x7de77eab,0x137140a9,0x41648109,0xf7e1c50d,0xceb1d0df,0x762dcad2, + 0xf1f57fba,0x5a60cc89 }, + { 0x40d45673,0x80b36382,0x5913c655,0x1b82be19,0xdd64b741,0x057284b8, + 0xdbfd8fc0,0x922ff56f } }, + /* 237 */ + { { 0xc9a129a1,0x1b265dee,0xcc284e04,0xa5b1ce57,0xcebfbe3c,0x04380c46, + 0xf6c5cd62,0x72919a7d }, + { 0x8fb90f9a,0x298f453a,0x88e4031b,0xd719c00b,0x796f1856,0xe32c0e77, + 0x3624089a,0x5e791780 } }, + /* 238 */ + { { 0x7f63cdfb,0x5c16ec55,0xf1cae4fd,0x8e6a3571,0x560597ca,0xfce26bea, + 0xe24c2fab,0x4e0a5371 }, + { 0xa5765357,0x276a40d3,0x0d73a2b4,0x3c89af44,0x41d11a32,0xb8f370ae, + 0xd56604ee,0xf5ff7818 } }, + /* 239 */ + { { 0x1a09df21,0xfbf3e3fe,0xe66e8e47,0x26d5d28e,0x29c89015,0x2096bd0a, + 0x533f5e64,0xe41df0e9 }, + { 0xb3ba9e3f,0x305fda40,0x2604d895,0xf2340ceb,0x7f0367c7,0x0866e192, + 0xac4f155f,0x8edd7d6e } }, + /* 240 */ + { { 0x0bfc8ff3,0xc9a1dc0e,0xe936f42f,0x14efd82b,0xcca381ef,0x67016f7c, + 0xed8aee96,0x1432c1ca }, + { 0x70b23c26,0xec684829,0x0735b273,0xa64fe873,0xeaef0f5a,0xe389f6e5, + 0x5ac8d2c6,0xcaef480b } }, + /* 241 */ + { { 0x75315922,0x5245c978,0x3063cca5,0xd8295171,0xb64ef2cb,0xf3ce60d0, + 0x8efae236,0xd0ba177e }, + { 0xb1b3af60,0x53a9ae8f,0x3d2da20e,0x1a796ae5,0xdf9eef28,0x01d63605, + 0x1c54ae16,0xf31c957c } }, + /* 242 */ + { { 0x49cc4597,0xc0f58d52,0xbae0a028,0xdc5015b0,0x734a814a,0xefc5fc55, + 0x96e17c3a,0x013404cb }, + { 0xc9a824bf,0xb29e2585,0x001eaed7,0xd593185e,0x61ef68ac,0x8d6ee682, + 0x91933e6c,0x6f377c4b } }, + /* 243 */ + { { 0xa8333fd2,0x9f93bad1,0x5a2a95b8,0xa8930202,0xeaf75ace,0x211e5037, + 0xd2d09506,0x6dba3e4e }, + { 0xd04399cd,0xa48ef98c,0xe6b73ade,0x1811c66e,0xc17ecaf3,0x72f60752, + 0x3becf4a7,0xf13cf342 } }, + /* 244 */ + { { 0xa919e2eb,0xceeb9ec0,0xf62c0f68,0x83a9a195,0x7aba2299,0xcfba3bb6, + 0x274bbad3,0xc83fa9a9 }, + { 0x62fa1ce0,0x0d7d1b0b,0x3418efbf,0xe58b60f5,0x52706f04,0xbfa8ef9e, + 0x5d702683,0xb49d70f4 } }, + /* 245 */ + { { 0xfad5513b,0x914c7510,0xb1751e2d,0x05f32eec,0xd9fb9d59,0x6d850418, + 0x0c30f1cf,0x59cfadbb }, + { 0x55cb7fd6,0xe167ac23,0x820426a3,0x249367b8,0x90a78864,0xeaeec58c, + 0x354a4b67,0x5babf362 } }, + /* 246 */ + { { 0xee424865,0x37c981d1,0xf2e5577f,0x8b002878,0xb9e0c058,0x702970f1, + 0x9026c8f0,0x6188c6a7 }, + { 0xd0f244da,0x06f9a19b,0xfb080873,0x1ecced5c,0x9f213637,0x35470f9b, + 0xdf50b9d9,0x993fe475 } }, + /* 247 */ + { { 0x9b2c3609,0x68e31cdf,0x2c46d4ea,0x84eb19c0,0x9a775101,0x7ac9ec1a, + 0x4c80616b,0x81f76466 }, + { 0x75fbe978,0x1d7c2a5a,0xf183b356,0x6743fed3,0x501dd2bf,0x838d1f04, + 0x5fe9060d,0x564a812a } }, + /* 248 */ + { { 0xfa817d1d,0x7a5a64f4,0xbea82e0f,0x55f96844,0xcd57f9aa,0xb5ff5a0f, + 0x00e51d6c,0x226bf3cf }, + { 0x2f2833cf,0xd6d1a9f9,0x4f4f89a8,0x20a0a35a,0x8f3f7f77,0x11536c49, + 0xff257836,0x68779f47 } }, + /* 249 */ + { { 0x73043d08,0x79b0c1c1,0x1fc020fa,0xa5446774,0x9a6d26d0,0xd3767e28, + 0xeb092e0b,0x97bcb0d1 }, + { 0xf32ed3c3,0x2ab6eaa8,0xb281bc48,0xc8a4f151,0xbfa178f3,0x4d1bf4f3, + 0x0a784655,0xa872ffe8 } }, + /* 250 */ + { { 0xa32b2086,0xb1ab7935,0x8160f486,0xe1eb710e,0x3b6ae6be,0x9bd0cd91, + 0xb732a36a,0x02812bfc }, + { 0xcf605318,0xa63fd7ca,0xfdfd6d1d,0x646e5d50,0x2102d619,0xa1d68398, + 0xfe5396af,0x07391cc9 } }, + /* 251 */ + { { 0x8b80d02b,0xc50157f0,0x62877f7f,0x6b8333d1,0x78d542ae,0x7aca1af8, + 0x7e6d2a08,0x355d2adc }, + { 0x287386e1,0xb41f335a,0xf8e43275,0xfd272a94,0xe79989ea,0x286ca2cd, + 0x7c2a3a79,0x3dc2b1e3 } }, + /* 252 */ + { { 0x04581352,0xd689d21c,0x376782be,0x0a00c825,0x9fed701f,0x203bd590, + 0x3ccd846b,0xc4786910 }, + { 0x24c768ed,0x5dba7708,0x6841f657,0x72feea02,0x6accce0e,0x73313ed5, + 0xd5bb4d32,0xccc42968 } }, + /* 253 */ + { { 0x3d7620b9,0x94e50de1,0x5992a56a,0xd89a5c8a,0x675487c9,0xdc007640, + 0xaa4871cf,0xe147eb42 }, + { 0xacf3ae46,0x274ab4ee,0x50350fbe,0xfd4936fb,0x48c840ea,0xdf2afe47, + 0x080e96e3,0x239ac047 } }, + /* 254 */ + { { 0x2bfee8d4,0x481d1f35,0xfa7b0fec,0xce80b5cf,0x2ce9af3c,0x105c4c9e, + 0xf5f7e59d,0xc55fa1a3 }, + { 0x8257c227,0x3186f14e,0x342be00b,0xc5b1653f,0xaa904fb2,0x09afc998, + 0xd4f4b699,0x094cd99c } }, + /* 255 */ + { { 0xd703beba,0x8a981c84,0x32ceb291,0x8631d150,0xe3bd49ec,0xa445f2c9, + 0x42abad33,0xb90a30b6 }, + { 0xb4a5abf9,0xb465404f,0x75db7603,0x004750c3,0xca35d89f,0x6f9a42cc, + 0x1b7924f7,0x019f8b9a } }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_8(sp_point_256* r, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_8(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 coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[8]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_256_point_new_8(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, km); + + err = sp_256_ecc_mulmod_base_8(point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_8(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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_8(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +static void sp_256_add_one_8(sp_digit* a) +{ + __asm__ __volatile__ ( + "ldr r1, [%[a], #0]\n\t" + "ldr r2, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "adds r1, r1, #1\n\t" + "adcs r2, r2, #0\n\t" + "adcs r3, r3, #0\n\t" + "adcs r4, r4, #0\n\t" + "str r1, [%[a], #0]\n\t" + "str r2, [%[a], #4]\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r1, [%[a], #16]\n\t" + "ldr r2, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "adcs r1, r1, #0\n\t" + "adcs r2, r2, #0\n\t" + "adcs r3, r3, #0\n\t" + "adcs r4, r4, #0\n\t" + "str r1, [%[a], #16]\n\t" + "str r2, [%[a], #20]\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + : + : [a] "r" (a) + : "memory", "r1", "r2", "r3", "r4" + ); +} + +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; 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_8(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, 8, buf, (int)sizeof(buf)); + if (sp_256_cmp_8(k, p256_order2) < 0) { + sp_256_add_one_8(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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[8]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 inf; +#endif +#endif + sp_point_256* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity; +#endif + int err; + + (void)heap; + + err = sp_256_point_new_8(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + err = sp_256_ecc_gen_k_8(rng, k); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_256_iszero_8(point->x) == 0) || (sp_256_iszero_8(point->y) == 0)) { + 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_8(point, pub); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_256_point_free_8(infinity, 1, heap); +#endif + sp_256_point_free_8(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte array. + * 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<8 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[8]; +#endif + sp_point_256* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 32U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, priv); + sp_256_point_from_ecc_point_8(point, pub); + err = sp_256_ecc_mulmod_8(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#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_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #64\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #28\n\t" + "it cc\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #32\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #56\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +#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_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "mov r10, #0\n\t" + "# A[0] * B[0]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r3, r4, r8, r9\n\t" + "mov r5, #0\n\t" + "str r3, [sp]\n\t" + "# A[0] * B[1]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[0]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #4]\n\t" + "# A[0] * B[2]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #8]\n\t" + "# A[0] * B[3]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[2]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[1]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #12]\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[3]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #16]\n\t" + "# A[0] * B[5]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[4]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[3]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[2]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[1]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #20]\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #24]\n\t" + "# A[0] * B[7]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[6]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[5]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[4]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[3]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[2]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[1]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #28]\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[2]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[1]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[2] * B[7]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[3] * B[6]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[5]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[3]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[2]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[4] * B[6]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[3]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[4] * B[7]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[5] * B[6]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[5]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[5] * B[7]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[5]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[6] * B[7]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[7] * B[6]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[7] * B[7]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r7\n\t" + "str r5, [%[r], #56]\n\t" + "str r3, [%[r], #60]\n\t" + "ldr r3, [sp, #0]\n\t" + "ldr r4, [sp, #4]\n\t" + "ldr r5, [sp, #8]\n\t" + "ldr r6, [sp, #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [sp, #16]\n\t" + "ldr r4, [sp, #20]\n\t" + "ldr r5, [sp, #24]\n\t" + "ldr r6, [sp, #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "add sp, sp, #32\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_sub_in_place_8(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r14, #0\n\t" + "add r12, %[a], #32\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#else +/* 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_8(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* 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_8(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #32\n\t" + "blt 1b\n\t" + "str r3, [%[r], #32]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r7\n\t" + "str r4, [%[r], #28]\n\t" + "str r5, [%[r], #32]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_256_word_8(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + 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_8(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & 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 WC_INLINE int sp_256_div_8(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[16], t2[9]; + sp_digit div, r1; + int i; + + (void)m; + + + div = d[7]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 8); + for (i=7; i>=0; i--) { + r1 = div_256_word_8(t1[8 + i], t1[8 + i - 1], div); + + sp_256_mul_d_8(t2, d, r1); + t1[8 + i] += sp_256_sub_in_place_8(&t1[i], t2); + t1[8 + i] -= t2[8]; + sp_256_mask_8(t2, d, t1[8 + i]); + t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2); + sp_256_mask_8(t2, d, t1[8 + i]); + t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2); + } + + r1 = sp_256_cmp_8(t1, d) >= 0; + sp_256_cond_sub_8(r, t1, d, (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 WC_INLINE int sp_256_mod_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_256_div_8(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#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_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #64\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #28\n\t" + "it cc\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #32\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #56\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#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_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "mov r14, #0\n\t" + "# A[0] * A[0]\n\t" + "ldr r10, [%[a], #0]\n\t" + "umull r8, r3, r10, r10\n\t" + "mov r4, #0\n\t" + "str r8, [sp]\n\t" + "# A[0] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[1] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[1] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[1] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[2] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #28]\n\t" + "# A[1] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[2] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #32]\n\t" + "# A[2] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[3] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #36]\n\t" + "# A[3] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[4] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[5] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #40]\n\t" + "# A[4] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[5] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [%[r], #44]\n\t" + "# A[5] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[6] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [%[r], #48]\n\t" + "# A[6] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #52]\n\t" + "# A[7] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adc r2, r2, r9\n\t" + "str r4, [%[r], #56]\n\t" + "str r2, [%[r], #60]\n\t" + "ldr r2, [sp, #0]\n\t" + "ldr r3, [sp, #4]\n\t" + "ldr r4, [sp, #8]\n\t" + "ldr r8, [sp, #12]\n\t" + "str r2, [%[r], #0]\n\t" + "str r3, [%[r], #4]\n\t" + "str r4, [%[r], #8]\n\t" + "str r8, [%[r], #12]\n\t" + "ldr r2, [sp, #16]\n\t" + "ldr r3, [sp, #20]\n\t" + "ldr r4, [sp, #24]\n\t" + "ldr r8, [sp, #28]\n\t" + "str r2, [%[r], #16]\n\t" + "str r3, [%[r], #20]\n\t" + "str r4, [%[r], #24]\n\t" + "str r8, [%[r], #28]\n\t" + "add sp, sp, #32\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint32_t p256_order_minus_2[8] = { + 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU,0xffffffffU,0xffffffffU, + 0x00000000U,0xffffffffU +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint32_t p256_order_low[4] = { + 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU +}; +#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_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_256_mul_8(r, a, b); + sp_256_mont_reduce_order_8(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_8(sp_digit* r, const sp_digit* a) +{ + sp_256_sqr_8(r, a); + sp_256_mont_reduce_order_8(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_8(sp_digit* r, const sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_8(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_8(t, t); + if ((p256_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 8U); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 8; + sp_digit* t3 = td + 4 * 8; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_8(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_8(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_8(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_8(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_8(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_8(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_8(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_8(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_8(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_8(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_8(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_8(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_8(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_8(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t2, t2, a); + } + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t2, t2, a); + } + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t2, t2, a); + } + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t2, t2, a); + } + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_8(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#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, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit ed[2*8]; + sp_digit xd[2*8]; + sp_digit kd[2*8]; + sp_digit rd[2*8]; + sp_digit td[3 * 2*8]; + sp_point_256 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_256* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int32_t c; + int i; + + (void)heap; + + err = sp_256_point_new_8(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 8; + x = d + 2 * 8; + k = d + 4 * 8; + r = d + 6 * 8; + tmp = d + 8 * 8; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(e, 8, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 8, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_8(rng, k); + } + else { + sp_256_from_mp(k, 8, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 8U); + sp_256_norm_8(r); + c = sp_256_cmp_8(r, p256_order); + sp_256_cond_sub_8(r, r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(r); + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(k, k, p256_norm_order); + err = sp_256_mod_8(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(k); + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_8(kInv, k, tmp); + sp_256_norm_8(kInv); + + /* s = r * x + e */ + sp_256_mul_8(x, x, r); + err = sp_256_mod_8(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(x); + carry = sp_256_add_8(s, e, x); + sp_256_cond_sub_8(s, s, p256_order, 0 - carry); + sp_256_norm_8(s); + c = sp_256_cmp_8(s, p256_order); + sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(s, s, kInv); + sp_256_norm_8(s); + + /* Check that signature is usable. */ + if (sp_256_iszero_8(s) == 0) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 8); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U); +#endif + sp_256_point_free_8(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit u1d[2*8]; + sp_digit u2d[2*8]; + sp_digit sd[2*8]; + sp_digit tmpd[2*8 * 5]; + sp_point_256 p1d; + sp_point_256 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p1; + sp_point_256* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + + err = sp_256_point_new_8(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 8; + u2 = d + 2 * 8; + s = d + 4 * 8; + tmp = d + 6 * 8; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 8, hash, (int)hashLen); + sp_256_from_mp(u2, 8, r); + sp_256_from_mp(s, 8, sm); + sp_256_from_mp(p2->x, 8, pX); + sp_256_from_mp(p2->y, 8, pY); + sp_256_from_mp(p2->z, 8, pZ); + + { + sp_256_mul_8(s, s, p256_norm_order); + } + err = sp_256_mod_8(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(s); + { + sp_256_mont_inv_order_8(s, s, tmp); + sp_256_mont_mul_order_8(u1, u1, s); + sp_256_mont_mul_order_8(u2, u2, s); + } + + err = sp_256_ecc_mulmod_base_8(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + { + sp_256_proj_point_add_8(p1, p1, p2, tmp); + if (sp_256_iszero_8(p1->z)) { + if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) { + sp_256_proj_point_dbl_8(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + } + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 8, r); + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 8, r); + carry = sp_256_add_8(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_8(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_256_point_free_8(p1, 0, heap); + sp_256_point_free_8(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*8]; + sp_digit t2d[2*8]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 8; + t2 = d + 2 * 8; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_256_sqr_8(t1, point->y); + (void)sp_256_mod_8(t1, t1, p256_mod); + sp_256_sqr_8(t2, point->x); + (void)sp_256_mod_8(t2, t2, p256_mod); + sp_256_mul_8(t2, t2, point->x); + (void)sp_256_mod_8(t2, t2, p256_mod); + (void)sp_256_sub_8(t2, p256_mod, t2); + sp_256_mont_add_8(t1, t1, t2, p256_mod); + + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_8(t1, p256_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 pubd; +#endif + sp_point_256* pub; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_8(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 8, pX); + sp_256_from_mp(pub->y, 8, pY); + sp_256_from_bin(pub->z, 8, one, (int)sizeof(one)); + + err = sp_256_ecc_is_point_8(pub, NULL); + } + + sp_256_point_free_8(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[8]; + sp_point_256 pubd; + sp_point_256 pd; +#endif + sp_digit* priv = NULL; + sp_point_256* pub; + sp_point_256* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_8(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_256_from_mp(pub->x, 8, pX); + sp_256_from_mp(pub->y, 8, pY); + sp_256_from_bin(pub->z, 8, one, (int)sizeof(one)); + sp_256_from_mp(priv, 8, privm); + + /* Check point at infinitiy. */ + if ((sp_256_iszero_8(pub->x) != 0) && + (sp_256_iszero_8(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_8(pub->x, p256_mod) >= 0 || + sp_256_cmp_8(pub->y, p256_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_8(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_256_iszero_8(p->x) == 0) || + (sp_256_iszero_8(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_256_ecc_mulmod_base_8(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_8(p->x, pub->x) != 0 || + sp_256_cmp_8(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, heap); + sp_256_point_free_8(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 8 * 5]; + sp_point_256 pd; + sp_point_256 qd; +#endif + sp_digit* tmp; + sp_point_256* p; + sp_point_256* q = NULL; + int err; + + err = sp_256_point_new_8(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_256_point_new_8(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + sp_256_from_mp(q->x, 8, qX); + sp_256_from_mp(q->y, 8, qY); + sp_256_from_mp(q->z, 8, qZ); + + sp_256_proj_point_add_8(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(q, 0, NULL); + sp_256_point_free_8(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 8 * 2]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_8(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + + sp_256_proj_point_dbl_8(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 8 * 4]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_8(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + + sp_256_map_8(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_8(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 8]; + sp_digit t2d[2 * 8]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 8; + t2 = d + 2 * 8; +#else + t1 = t1d; + t2 = t2d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_8(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_8(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_8(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_8(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_8(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_8(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_8(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_8(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 8]; + sp_digit yd[2 * 8]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 8; + y = d + 2 * 8; +#else + x = xd; + y = yd; +#endif + + sp_256_from_mp(x, 8, xm); + err = sp_256_mod_mul_norm_8(x, x, p256_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_8(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_sub_8(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_8(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_8(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_8(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 8, 0, 8U * sizeof(sp_digit)); + sp_256_mont_reduce_8(y, p256_mod, p256_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_256_mont_sub_8(y, p256_mod, y, p256_mod); + } + + err = sp_256_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#ifdef WOLFSSL_SP_384 + +/* Point structure to use. */ +typedef struct sp_point_384 { + sp_digit x[2 * 12]; + sp_digit y[2 * 12]; + sp_digit z[2 * 12]; + int infinity; +} sp_point_384; + +/* The modulus (prime) of the curve P384. */ +static const sp_digit p384_mod[12] = { + 0xffffffff,0x00000000,0x00000000,0xffffffff,0xfffffffe,0xffffffff, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +}; +/* The Montogmery normalizer for modulus of the curve P384. */ +static const sp_digit p384_norm_mod[12] = { + 0x00000001,0xffffffff,0xffffffff,0x00000000,0x00000001,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 +}; +/* The Montogmery multiplier for modulus of the curve P384. */ +static sp_digit p384_mp_mod = 0x00000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P384. */ +static const sp_digit p384_order[12] = { + 0xccc52973,0xecec196a,0x48b0a77a,0x581a0db2,0xf4372ddf,0xc7634d81, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +}; +#endif +/* The order of the curve P384 minus 2. */ +static const sp_digit p384_order2[12] = { + 0xccc52971,0xecec196a,0x48b0a77a,0x581a0db2,0xf4372ddf,0xc7634d81, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P384. */ +static const sp_digit p384_norm_order[12] = { + 0x333ad68d,0x1313e695,0xb74f5885,0xa7e5f24d,0x0bc8d220,0x389cb27e, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P384. */ +static sp_digit p384_mp_order = 0xe88fdc45; +#endif +/* The base point of curve P384. */ +static const sp_point_384 p384_base = { + /* X ordinate */ + { + 0x72760ab7,0x3a545e38,0xbf55296c,0x5502f25d,0x82542a38,0x59f741e0, + 0x8ba79b98,0x6e1d3b62,0xf320ad74,0x8eb1c71e,0xbe8b0537,0xaa87ca22, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x90ea0e5f,0x7a431d7c,0x1d7e819d,0x0a60b1ce,0xb5f0b8c0,0xe9da3113, + 0x289a147c,0xf8f41dbd,0x9292dc29,0x5d9e98bf,0x96262c6f,0x3617de4a, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p384_b[12] = { + 0xd3ec2aef,0x2a85c8ed,0x8a2ed19d,0xc656398d,0x5013875a,0x0314088f, + 0xfe814112,0x181d9c6e,0xe3f82d19,0x988e056b,0xe23ee7e4,0xb3312fa7 +}; +#endif + +static int sp_384_point_new_ex_12(void* heap, sp_point_384* sp, sp_point_384** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), &(sp), &(p)) +#endif + + +static void sp_384_point_free_12(sp_point_384* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* t; +#else + int64_t t[12]; +#endif + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + (uint64_t)a[0] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[8] + (uint64_t)a[10] + (uint64_t)a[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[9] + (uint64_t)a[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + (uint64_t)a[0] - (uint64_t)a[2] + (uint64_t)a[3] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[10] - (uint64_t)a[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[3] + (uint64_t)a[4] + (uint64_t)a[8] + 2 * (uint64_t)a[9] + (uint64_t)a[10] - 2 * (uint64_t)a[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[4] + (uint64_t)a[5] + (uint64_t)a[9] + 2 * (uint64_t)a[10] + (uint64_t)a[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + (uint64_t)a[2] + (uint64_t)a[3] - (uint64_t)a[5] + (uint64_t)a[6] + (uint64_t)a[10] + 2 * (uint64_t)a[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + (uint64_t)a[3] + (uint64_t)a[4] - (uint64_t)a[6] + (uint64_t)a[7] + (uint64_t)a[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + (uint64_t)a[4] + (uint64_t)a[5] - (uint64_t)a[7] + (uint64_t)a[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + (uint64_t)a[5] + (uint64_t)a[6] - (uint64_t)a[8] + (uint64_t)a[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + (uint64_t)a[6] + (uint64_t)a[7] - (uint64_t)a[9] + (uint64_t)a[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + (uint64_t)a[7] + (uint64_t)a[8] - (uint64_t)a[10] + (uint64_t)a[11]; + + 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + + r[0] = t[0]; + r[1] = t[1]; + r[2] = t[2]; + r[3] = t[3]; + r[4] = t[4]; + r[5] = t[5]; + r[6] = t[6]; + r[7] = t[7]; + r[8] = t[8]; + r[9] = t[9]; + r[10] = t[10]; + r[11] = t[11]; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_12(sp_point_384* p, const 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_384_from_mp(p->x, 12, pm->x); + sp_384_from_mp(p->y, 12, pm->y); + sp_384_from_mp(p->z, 12, 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_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 12); + r->used = 12; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 12; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 12; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + +#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_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #96\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #44\n\t" + "it cc\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #48\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #88\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +#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_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #48\n\t" + "mov r10, #0\n\t" + "# A[0] * B[0]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r3, r4, r8, r9\n\t" + "mov r5, #0\n\t" + "str r3, [sp]\n\t" + "# A[0] * B[1]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[0]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #4]\n\t" + "# A[0] * B[2]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #8]\n\t" + "# A[0] * B[3]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[2]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[1]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #12]\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[3]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #16]\n\t" + "# A[0] * B[5]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[4]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[3]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[2]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[1]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #20]\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #24]\n\t" + "# A[0] * B[7]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[6]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[5]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[4]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[3]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[2]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[1]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #28]\n\t" + "# A[0] * B[8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[2]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[1]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[0]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #32]\n\t" + "# A[0] * B[9]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[7]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[6]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[5]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[3]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[2]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[1]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[0]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #36]\n\t" + "# A[0] * B[10]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[9]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[8]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[6]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[3]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[2]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[1]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[0]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #40]\n\t" + "# A[0] * B[11]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[10]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[9]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[8]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[7]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[6]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[5]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[3]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[2]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[1]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[0]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #44]\n\t" + "# A[1] * B[11]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[2] * B[10]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[9]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[8]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[7]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[5]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[4]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[3]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[2]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[1]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[2] * B[11]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[3] * B[10]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[9]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[8]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[7]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[6]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[5]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[4]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[3]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[2]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[3] * B[11]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[4] * B[10]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[9]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[8]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[7]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[6]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[5]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[4]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[3]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #56]\n\t" + "# A[4] * B[11]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[5] * B[10]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[9]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[8]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[8] * B[7]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[6]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[5]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[4]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #60]\n\t" + "# A[5] * B[11]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[6] * B[10]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[9]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[8] * B[8]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[9] * B[7]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[6]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[5]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[6] * B[11]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[7] * B[10]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[8] * B[9]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[9] * B[8]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[10] * B[7]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[6]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[7] * B[11]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[8] * B[10]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[9] * B[9]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[10] * B[8]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[11] * B[7]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[8] * B[11]\n\t" + "ldr r8, [%[a], #32]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[9] * B[10]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[10] * B[9]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[11] * B[8]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #32]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[9] * B[11]\n\t" + "ldr r8, [%[a], #36]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[10] * B[10]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[11] * B[9]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #36]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[10] * B[11]\n\t" + "ldr r8, [%[a], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[11] * B[10]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #40]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[11] * B[11]\n\t" + "ldr r8, [%[a], #44]\n\t" + "ldr r9, [%[b], #44]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r3, [sp, #0]\n\t" + "ldr r4, [sp, #4]\n\t" + "ldr r5, [sp, #8]\n\t" + "ldr r6, [sp, #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [sp, #16]\n\t" + "ldr r4, [sp, #20]\n\t" + "ldr r5, [sp, #24]\n\t" + "ldr r6, [sp, #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r3, [sp, #32]\n\t" + "ldr r4, [sp, #36]\n\t" + "ldr r5, [sp, #40]\n\t" + "ldr r6, [sp, #44]\n\t" + "str r3, [%[r], #32]\n\t" + "str r4, [%[r], #36]\n\t" + "str r5, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "add sp, sp, #48\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* 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_384_cond_sub_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #48\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +#define sp_384_mont_reduce_order_12 sp_384_mont_reduce_12 + +/* Reduce the number back to 384 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_384_mont_reduce_12(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r7, [%[m], #0]\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr r7, [%[m], #32]\n\t" + "ldr r9, [%[a], #32]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #32]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr r7, [%[m], #36]\n\t" + "ldr r9, [%[a], #36]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #36]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr r7, [%[m], #40]\n\t" + "ldr r9, [%[a], #40]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #40]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr r7, [%[m], #44]\n\t" + "ldr r9, [%[a], #44]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #44]\n\t" + "ldr r9, [%[a], #48]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #48]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #48\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + sp_384_cond_sub_12(a - 12, 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_384_mont_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_384_mul_12(r, a, b); + sp_384_mont_reduce_12(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_384_sqr_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #96\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #44\n\t" + "it cc\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #48\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #88\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #48\n\t" + "mov r14, #0\n\t" + "# A[0] * A[0]\n\t" + "ldr r10, [%[a], #0]\n\t" + "umull r8, r3, r10, r10\n\t" + "mov r4, #0\n\t" + "str r8, [sp]\n\t" + "# A[0] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[1] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[1] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[1] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[2] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #28]\n\t" + "# A[0] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #32]\n\t" + "# A[0] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #36]\n\t" + "# A[0] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #40]\n\t" + "# A[0] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #44]\n\t" + "# A[1] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[2] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #48]\n\t" + "# A[2] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[3] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #52]\n\t" + "# A[3] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[4] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[5] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #56]\n\t" + "# A[4] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[5] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[6] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #60]\n\t" + "# A[5] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[6] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[7] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[8]\n\t" + "ldr r10, [%[a], #32]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [%[r], #64]\n\t" + "# A[6] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[7] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[8] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #68]\n\t" + "# A[7] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[8] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[9] * A[9]\n\t" + "ldr r10, [%[a], #36]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [%[r], #72]\n\t" + "# A[8] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #32]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[9] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #76]\n\t" + "# A[9] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #36]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[10] * A[10]\n\t" + "ldr r10, [%[a], #40]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [%[r], #80]\n\t" + "# A[10] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "ldr r8, [%[a], #40]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [%[r], #84]\n\t" + "# A[11] * A[11]\n\t" + "ldr r10, [%[a], #44]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adc r4, r4, r9\n\t" + "str r3, [%[r], #88]\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r2, [sp, #0]\n\t" + "ldr r3, [sp, #4]\n\t" + "ldr r4, [sp, #8]\n\t" + "ldr r8, [sp, #12]\n\t" + "str r2, [%[r], #0]\n\t" + "str r3, [%[r], #4]\n\t" + "str r4, [%[r], #8]\n\t" + "str r8, [%[r], #12]\n\t" + "ldr r2, [sp, #16]\n\t" + "ldr r3, [sp, #20]\n\t" + "ldr r4, [sp, #24]\n\t" + "ldr r8, [sp, #28]\n\t" + "str r2, [%[r], #16]\n\t" + "str r3, [%[r], #20]\n\t" + "str r4, [%[r], #24]\n\t" + "str r8, [%[r], #28]\n\t" + "ldr r2, [sp, #32]\n\t" + "ldr r3, [sp, #36]\n\t" + "ldr r4, [sp, #40]\n\t" + "ldr r8, [sp, #44]\n\t" + "str r2, [%[r], #32]\n\t" + "str r3, [%[r], #36]\n\t" + "str r4, [%[r], #40]\n\t" + "str r8, [%[r], #44]\n\t" + "add sp, sp, #48\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14" + ); +} + +#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_384_mont_sqr_12(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_384_sqr_12(r, a); + sp_384_mont_reduce_12(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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_384_mont_sqr_n_12(sp_digit* r, const sp_digit* a, int n, + const sp_digit* m, sp_digit mp) +{ + sp_384_mont_sqr_12(r, a, m, mp); + for (; n > 1; n--) { + sp_384_mont_sqr_12(r, r, m, mp); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P384 curve. */ +static const uint32_t p384_mod_minus_2[12] = { + 0xfffffffdU,0x00000000U,0x00000000U,0xffffffffU,0xfffffffeU,0xffffffffU, + 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P384 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_384_mont_inv_12(sp_digit* r, const sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 12); + for (i=382; i>=0; i--) { + sp_384_mont_sqr_12(t, t, p384_mod, p384_mp_mod); + if (p384_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_384_mont_mul_12(t, t, a, p384_mod, p384_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 12); +#else + sp_digit* t1 = td; + sp_digit* t2 = td + 2 * 12; + sp_digit* t3 = td + 4 * 12; + sp_digit* t4 = td + 6 * 12; + sp_digit* t5 = td + 8 * 12; + + /* 0x2 */ + sp_384_mont_sqr_12(t1, a, p384_mod, p384_mp_mod); + /* 0x3 */ + sp_384_mont_mul_12(t5, t1, a, p384_mod, p384_mp_mod); + /* 0xc */ + sp_384_mont_sqr_n_12(t1, t5, 2, p384_mod, p384_mp_mod); + /* 0xf */ + sp_384_mont_mul_12(t2, t5, t1, p384_mod, p384_mp_mod); + /* 0x1e */ + sp_384_mont_sqr_12(t1, t2, p384_mod, p384_mp_mod); + /* 0x1f */ + sp_384_mont_mul_12(t4, t1, a, p384_mod, p384_mp_mod); + /* 0x3e0 */ + sp_384_mont_sqr_n_12(t1, t4, 5, p384_mod, p384_mp_mod); + /* 0x3ff */ + sp_384_mont_mul_12(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0x7fe0 */ + sp_384_mont_sqr_n_12(t1, t2, 5, p384_mod, p384_mp_mod); + /* 0x7fff */ + sp_384_mont_mul_12(t4, t4, t1, p384_mod, p384_mp_mod); + /* 0x3fff8000 */ + sp_384_mont_sqr_n_12(t1, t4, 15, p384_mod, p384_mp_mod); + /* 0x3fffffff */ + sp_384_mont_mul_12(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffc */ + sp_384_mont_sqr_n_12(t3, t2, 2, p384_mod, p384_mp_mod); + /* 0xfffffffd */ + sp_384_mont_mul_12(r, t3, a, p384_mod, p384_mp_mod); + /* 0xffffffff */ + sp_384_mont_mul_12(t3, t5, t3, p384_mod, p384_mp_mod); + /* 0xfffffffc0000000 */ + sp_384_mont_sqr_n_12(t1, t2, 30, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff */ + sp_384_mont_mul_12(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_12(t1, t2, 60, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_12(t1, t2, 120, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_12(t1, t2, 15, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */ + sp_384_mont_sqr_n_12(t1, t2, 33, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */ + sp_384_mont_mul_12(t2, t3, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_12(t1, t2, 96, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */ + sp_384_mont_mul_12(r, r, t1, p384_mod, p384_mp_mod); + +#endif /* WOLFSSL_SP_SMALL */ +} + +/* 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 int32_t sp_384_cmp_12(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #44\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "subs r6, r6, #4\n\t" + "bcs 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "it hi\n\t" + "movhi %[r], %[one]\n\t" + "it lo\n\t" + "movlo %[r], r3\n\t" + "it ne\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + return r; +} + +/* Normalize the values in each word to 32. + * + * a Array of sp_digit to normalize. + */ +#define sp_384_norm_12(a) + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*12; + int32_t n; + + sp_384_mont_inv_12(t1, p->z, t + 2*12); + + sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod); + + /* x /= z^2 */ + sp_384_mont_mul_12(r->x, p->x, t2, p384_mod, p384_mp_mod); + XMEMSET(r->x + 12, 0, sizeof(r->x) / 2U); + sp_384_mont_reduce_12(r->x, p384_mod, p384_mp_mod); + /* Reduce x to less than modulus */ + n = sp_384_cmp_12(r->x, p384_mod); + sp_384_cond_sub_12(r->x, r->x, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_12(r->x); + + /* y /= z^3 */ + sp_384_mont_mul_12(r->y, p->y, t1, p384_mod, p384_mp_mod); + XMEMSET(r->y + 12, 0, sizeof(r->y) / 2U); + sp_384_mont_reduce_12(r->y, p384_mod, p384_mp_mod); + /* Reduce y to less than modulus */ + n = sp_384_cmp_12(r->y, p384_mod); + sp_384_cond_sub_12(r->y, r->y, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_12(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 sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #48\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#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 sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#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_384_mont_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_12(r, a, b); + sp_384_cond_sub_12(r, r, m, 0 - o); +} + +/* 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_384_mont_dbl_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_12(r, a, a); + sp_384_cond_sub_12(r, r, m, 0 - o); +} + +/* 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_384_mont_tpl_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_12(r, a, a); + sp_384_cond_sub_12(r, r, m, 0 - o); + o = sp_384_add_12(r, r, a); + sp_384_cond_sub_12(r, r, m, 0 - o); +} + +#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 sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #48\n\t" + "\n1:\n\t" + "rsbs %[c], %[c], #0\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "sbc %[c], r4, r4\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#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 sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #0]\n\t" + "ldr r8, [%[b], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "ldr r10, [%[b], #12]\n\t" + "subs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "ldr r10, [%[b], #28]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r7, [%[b], #32]\n\t" + "ldr r8, [%[b], #36]\n\t" + "ldr r9, [%[b], #40]\n\t" + "ldr r10, [%[b], #44]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #32]\n\t" + "str r4, [%[r], #36]\n\t" + "str r5, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "sbc %[c], %[c], #0\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); + + return c; +} + +#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 sp_digit sp_384_cond_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #48\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adds r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "adcs r4, r4, r5\n\t" + "adcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "adc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* 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_384_mont_sub_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + sp_digit o; + + o = sp_384_sub_12(r, a, b); + sp_384_cond_add_12(r, r, m, o); +} + +static void sp_384_rshift1_12(sp_digit* r, sp_digit* a) +{ + __asm__ __volatile__ ( + "ldr r2, [%[a]]\n\t" + "ldr r3, [%[a], #4]\n\t" + "lsr r2, r2, #1\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r2, [%[r], #0]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r3, [%[r], #4]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r4, [%[r], #8]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r2, [%[r], #12]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r3, [%[r], #16]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r4, [%[r], #20]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r2, [%[r], #24]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r3, [%[r], #28]\n\t" + "orr r4, r4, r2, lsl #31\n\t" + "lsr r2, r2, #1\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r4, [%[r], #32]\n\t" + "orr r2, r2, r3, lsl #31\n\t" + "lsr r3, r3, #1\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r2, [%[r], #36]\n\t" + "orr r3, r3, r4, lsl #31\n\t" + "lsr r4, r4, #1\n\t" + "str r3, [%[r], #40]\n\t" + "str r4, [%[r], #44]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4" + ); +} + +/* 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_384_div2_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_cond_add_12(r, a, m, 0 - (a[0] & 1)); + sp_384_rshift1_12(r, r); + r[11] |= o << 31; +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_dbl_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*12; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_384_mont_sqr_12(t1, p->z, p384_mod, p384_mp_mod); + /* Z = Y * Z */ + sp_384_mont_mul_12(z, p->y, p->z, p384_mod, p384_mp_mod); + /* Z = 2Z */ + sp_384_mont_dbl_12(z, z, p384_mod); + /* T2 = X - T1 */ + sp_384_mont_sub_12(t2, p->x, t1, p384_mod); + /* T1 = X + T1 */ + sp_384_mont_add_12(t1, p->x, t1, p384_mod); + /* T2 = T1 * T2 */ + sp_384_mont_mul_12(t2, t1, t2, p384_mod, p384_mp_mod); + /* T1 = 3T2 */ + sp_384_mont_tpl_12(t1, t2, p384_mod); + /* Y = 2Y */ + sp_384_mont_dbl_12(y, p->y, p384_mod); + /* Y = Y * Y */ + sp_384_mont_sqr_12(y, y, p384_mod, p384_mp_mod); + /* T2 = Y * Y */ + sp_384_mont_sqr_12(t2, y, p384_mod, p384_mp_mod); + /* T2 = T2/2 */ + sp_384_div2_12(t2, t2, p384_mod); + /* Y = Y * X */ + sp_384_mont_mul_12(y, y, p->x, p384_mod, p384_mp_mod); + /* X = T1 * T1 */ + sp_384_mont_sqr_12(x, t1, p384_mod, p384_mp_mod); + /* X = X - Y */ + sp_384_mont_sub_12(x, x, y, p384_mod); + /* X = X - Y */ + sp_384_mont_sub_12(x, x, y, p384_mod); + /* Y = Y - X */ + sp_384_mont_sub_12(y, y, x, p384_mod); + /* Y = Y * T1 */ + sp_384_mont_mul_12(y, y, t1, p384_mod, p384_mp_mod); + /* Y = Y - T2 */ + sp_384_mont_sub_12(y, y, t2, p384_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_384_cmp_equal_12(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]) | (a[10] ^ b[10]) | (a[11] ^ b[11])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, + sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*12; + sp_digit* t3 = t + 4*12; + sp_digit* t4 = t + 6*12; + sp_digit* t5 = t + 8*12; + 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) { + const sp_point_384* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_384_sub_12(t1, p384_mod, q->y); + sp_384_norm_12(t1); + if ((sp_384_cmp_equal_12(p->x, q->x) & sp_384_cmp_equal_12(p->z, q->z) & + (sp_384_cmp_equal_12(p->y, q->y) | sp_384_cmp_equal_12(p->y, t1))) != 0) { + sp_384_proj_point_dbl_12(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<12; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<12; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<12; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_12(t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t3, t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t1, t1, x, p384_mod, p384_mp_mod); + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_12(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_12(t3, t3, y, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_12(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - U1 */ + sp_384_mont_sub_12(t2, t2, t1, p384_mod); + /* R = S2 - S1 */ + sp_384_mont_sub_12(t4, t4, t3, p384_mod); + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_12(z, z, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_12(x, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_12(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(y, t1, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(x, x, t5, p384_mod); + sp_384_mont_dbl_12(t1, y, p384_mod); + sp_384_mont_sub_12(x, x, t1, p384_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_12(y, y, x, p384_mod); + sp_384_mont_mul_12(y, y, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t5, t5, t3, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(y, y, t5, p384_mod); + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td[16]; + sp_point_384 rtd; + sp_digit tmpd[2 * 12 * 6]; +#endif + sp_point_384* t; + sp_point_384* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_384_point_new_12(heap, rtd, rt); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 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 */ + (void)sp_384_mod_mul_norm_12(t[1].x, g->x, p384_mod); + (void)sp_384_mod_mul_norm_12(t[1].y, g->y, p384_mod); + (void)sp_384_mod_mul_norm_12(t[1].z, g->z, p384_mod); + t[1].infinity = 0; + sp_384_proj_point_dbl_12(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_384_proj_point_add_12(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_384_proj_point_dbl_12(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_384_proj_point_add_12(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_384_proj_point_dbl_12(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_384_proj_point_add_12(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_384_proj_point_dbl_12(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_384_proj_point_add_12(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_384_proj_point_dbl_12(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_384_proj_point_add_12(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_384_proj_point_dbl_12(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_384_proj_point_add_12(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_384_proj_point_dbl_12(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_384_proj_point_add_12(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 10; + n = k[i+1] << 0; + c = 28; + y = n >> 28; + XMEMCPY(rt, &t[y], sizeof(sp_point_384)); + n <<= 4; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--]; + c += 32; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_384_proj_point_dbl_12(rt, rt, tmp); + sp_384_proj_point_dbl_12(rt, rt, tmp); + sp_384_proj_point_dbl_12(rt, rt, tmp); + sp_384_proj_point_dbl_12(rt, rt, tmp); + + sp_384_proj_point_add_12(rt, rt, &t[y], tmp); + } + + if (map != 0) { + sp_384_map_12(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 12 * 6); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_384) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_384_point_free_12(rt, 1, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_384 { + sp_digit x[12]; + sp_digit y[12]; +} sp_table_entry_384; + +#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_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*12; + sp_digit* b = t + 4*12; + sp_digit* t1 = t + 6*12; + sp_digit* t2 = t + 8*12; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_384_mont_dbl_12(y, y, p384_mod); + /* W = Z^4 */ + sp_384_mont_sqr_12(w, z, p384_mod, p384_mp_mod); + sp_384_mont_sqr_12(w, w, p384_mod, p384_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_12(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(t1, t1, w, p384_mod); + sp_384_mont_tpl_12(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_12(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_12(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_12(t2, b, p384_mod); + sp_384_mont_sub_12(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_12(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_12(t1, t1, p384_mod, p384_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_384_mont_mul_12(w, w, t1, p384_mod, p384_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_12(y, b, x, p384_mod); + sp_384_mont_mul_12(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_12(y, y, p384_mod); + sp_384_mont_sub_12(y, y, t1, p384_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_12(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(t1, t1, w, p384_mod); + sp_384_mont_tpl_12(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_12(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_12(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_12(t2, b, p384_mod); + sp_384_mont_sub_12(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_12(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_12(t1, t1, p384_mod, p384_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_12(y, b, x, p384_mod); + sp_384_mont_mul_12(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_12(y, y, p384_mod); + sp_384_mont_sub_12(y, y, t1, p384_mod); +#endif + /* Y = Y/2 */ + sp_384_div2_12(y, y, p384_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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_qz1_12(sp_point_384* r, const sp_point_384* p, + const sp_point_384* q, sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*12; + sp_digit* t3 = t + 4*12; + sp_digit* t4 = t + 6*12; + sp_digit* t5 = t + 8*12; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_384_sub_12(t1, p384_mod, q->y); + sp_384_norm_12(t1); + if ((sp_384_cmp_equal_12(p->x, q->x) & sp_384_cmp_equal_12(p->z, q->z) & + (sp_384_cmp_equal_12(p->y, q->y) | sp_384_cmp_equal_12(p->y, t1))) != 0) { + sp_384_proj_point_dbl_12(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<12; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<12; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<12; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_12(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_12(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - X1 */ + sp_384_mont_sub_12(t2, t2, x, p384_mod); + /* R = S2 - Y1 */ + sp_384_mont_sub_12(t4, t4, y, p384_mod); + /* Z3 = H*Z1 */ + sp_384_mont_mul_12(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_384_mont_sqr_12(t1, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_12(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t3, x, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(x, t1, t5, p384_mod); + sp_384_mont_dbl_12(t1, t3, p384_mod); + sp_384_mont_sub_12(x, x, t1, p384_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_384_mont_sub_12(t3, t3, x, p384_mod); + sp_384_mont_mul_12(t3, t3, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t5, t5, y, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(y, t3, t5, p384_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 12; + sp_digit* tmp = t + 4 * 12; + + sp_384_mont_inv_12(t1, a->z, tmp); + + sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod); + + sp_384_mont_mul_12(a->x, a->x, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(a->y, a->y, t1, p384_mod, p384_mp_mod); + XMEMCPY(a->z, p384_norm_mod, sizeof(p384_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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_384_gen_stripe_table_12(const sp_point_384* a, + sp_table_entry_384* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td, s1d, s2d; +#endif + sp_point_384* t; + sp_point_384* s1 = NULL; + sp_point_384* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_384_point_new_12(heap, td, t); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->y, a->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->z, a->z, p384_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_384_proj_to_affine_12(t, tmp); + + XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_384)); + /* 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)); + + for (i=1; i<4; i++) { + sp_384_proj_point_dbl_n_12(t, 96, tmp); + sp_384_proj_to_affine_12(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<4; i++) { + XMEMCPY(s1->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_384_proj_point_add_qz1_12(t, s1, s2, tmp); + sp_384_proj_to_affine_12(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_384_point_free_12(s2, 0, heap); + sp_384_point_free_12(s1, 0, heap); + sp_384_point_free_12( 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 coordinates. + * + * 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_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 rtd; + sp_point_384 pd; + sp_digit td[2 * 12 * 6]; +#endif + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_384_point_new_12(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + y = 0; + for (j=0,x=95; j<4; j++,x+=96) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=94; i>=0; i--) { + y = 0; + for (j=0,x=i; j<4; j++,x+=96) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + + sp_384_proj_point_dbl_12(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 = !y; + sp_384_proj_point_add_qz1_12(rt, rt, p, t); + } + + if (map != 0) { + sp_384_map_12(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, heap); + sp_384_point_free_12(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_384_t { + sp_digit x[12]; + sp_digit y[12]; + sp_table_entry_384 table[16]; + uint32_t cnt; + int set; +} sp_cache_384_t; + +static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_384_last = -1; +static THREAD_LS_T int sp_cache_384_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_384 = 0; + static wolfSSL_Mutex sp_cache_384_lock; +#endif + +static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_384_inited == 0) { + for (i=0; ix, sp_cache_384[i].x) & + sp_384_cmp_equal_12(g->y, sp_cache_384[i].y)) { + sp_cache_384[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_384_last + 1) % FP_ENTRIES; + for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_384[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_384_last) { + least = sp_cache_384[0].cnt; + for (j=1; jx, sizeof(sp_cache_384[i].x)); + XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y)); + sp_cache_384[i].set = 1; + sp_cache_384[i].cnt = 1; + } + + *cache = &sp_cache_384[i]; + sp_cache_384_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_384_ecc_mulmod_fast_12(r, g, k, map, heap); +#else + sp_digit tmp[2 * 12 * 7]; + sp_cache_384_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_384 == 0) { + wc_InitMutex(&sp_cache_384_lock); + initCacheMutex_384 = 1; + } + if (wc_LockMutex(&sp_cache_384_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_384(g, &cache); + if (cache->cnt == 2) + sp_384_gen_stripe_table_12(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_384_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_384_ecc_mulmod_fast_12(r, g, k, map, heap); + } + else { + err = sp_384_ecc_mulmod_stripe_12(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#else +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_384_gen_stripe_table_12(const sp_point_384* a, + sp_table_entry_384* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td, s1d, s2d; +#endif + sp_point_384* t; + sp_point_384* s1 = NULL; + sp_point_384* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_384_point_new_12(heap, td, t); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->y, a->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->z, a->z, p384_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_384_proj_to_affine_12(t, tmp); + + XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_384)); + /* 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)); + + for (i=1; i<8; i++) { + sp_384_proj_point_dbl_n_12(t, 48, tmp); + sp_384_proj_to_affine_12(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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_384_proj_point_add_qz1_12(t, s1, s2, tmp); + sp_384_proj_to_affine_12(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_384_point_free_12(s2, 0, heap); + sp_384_point_free_12(s1, 0, heap); + sp_384_point_free_12( 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 coordinates. + * + * 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_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 rtd; + sp_point_384 pd; + sp_digit td[2 * 12 * 6]; +#endif + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_384_point_new_12(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + y = 0; + for (j=0,x=47; j<8; j++,x+=48) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=46; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=48) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + + sp_384_proj_point_dbl_12(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 = !y; + sp_384_proj_point_add_qz1_12(rt, rt, p, t); + } + + if (map != 0) { + sp_384_map_12(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, heap); + sp_384_point_free_12(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_384_t { + sp_digit x[12]; + sp_digit y[12]; + sp_table_entry_384 table[256]; + uint32_t cnt; + int set; +} sp_cache_384_t; + +static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_384_last = -1; +static THREAD_LS_T int sp_cache_384_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_384 = 0; + static wolfSSL_Mutex sp_cache_384_lock; +#endif + +static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_384_inited == 0) { + for (i=0; ix, sp_cache_384[i].x) & + sp_384_cmp_equal_12(g->y, sp_cache_384[i].y)) { + sp_cache_384[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_384_last + 1) % FP_ENTRIES; + for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_384[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_384_last) { + least = sp_cache_384[0].cnt; + for (j=1; jx, sizeof(sp_cache_384[i].x)); + XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y)); + sp_cache_384[i].set = 1; + sp_cache_384[i].cnt = 1; + } + + *cache = &sp_cache_384[i]; + sp_cache_384_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_384_ecc_mulmod_fast_12(r, g, k, map, heap); +#else + sp_digit tmp[2 * 12 * 7]; + sp_cache_384_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_384 == 0) { + wc_InitMutex(&sp_cache_384_lock); + initCacheMutex_384 = 1; + } + if (wc_LockMutex(&sp_cache_384_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_384(g, &cache); + if (cache->cnt == 2) + sp_384_gen_stripe_table_12(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_384_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_384_ecc_mulmod_fast_12(r, g, k, map, heap); + } + else { + err = sp_384_ecc_mulmod_stripe_12(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[12]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_384_point_new_12(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 12, km); + sp_384_point_from_ecc_point_12(point, gm); + + err = sp_384_ecc_mulmod_12(point, point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_12(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static const sp_table_entry_384 p384_table[16] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x49c0b528,0x3dd07566,0xa0d6ce38,0x20e378e2,0x541b4d6e,0x879c3afc, + 0x59a30eff,0x64548684,0x614ede2b,0x812ff723,0x299e1513,0x4d3aadc2 }, + { 0x4b03a4fe,0x23043dad,0x7bb4a9ac,0xa1bfa8bf,0x2e83b050,0x8bade756, + 0x68f4ffd9,0xc6c35219,0x3969a840,0xdd800226,0x5a15c5e9,0x2b78abc2 } }, + /* 2 */ + { { 0xf26feef9,0x24480c57,0x3a0e1240,0xc31a2694,0x273e2bc7,0x735002c3, + 0x3ef1ed4c,0x8c42e9c5,0x7f4948e8,0x028babf6,0x8a978632,0x6a502f43 }, + { 0xb74536fe,0xf5f13a46,0xd8a9f0eb,0x1d218bab,0x37232768,0x30f36bcc, + 0x576e8c18,0xc5317b31,0x9bbcb766,0xef1d57a6,0xb3e3d4dc,0x917c4930 } }, + /* 3 */ + { { 0xe349ddd0,0x11426e2e,0x9b2fc250,0x9f117ef9,0xec0174a6,0xff36b480, + 0x18458466,0x4f4bde76,0x05806049,0x2f2edb6d,0x19dfca92,0x8adc75d1 }, + { 0xb7d5a7ce,0xa619d097,0xa34411e9,0x874275e5,0x0da4b4ef,0x5403e047, + 0x77901d8f,0x2ebaafd9,0xa747170f,0x5e63ebce,0x7f9d8036,0x12a36944 } }, + /* 4 */ + { { 0x2f9fbe67,0x378205de,0x7f728e44,0xc4afcb83,0x682e00f1,0xdbcec06c, + 0x114d5423,0xf2a145c3,0x7a52463e,0xa01d9874,0x7d717b0a,0xfc0935b1 }, + { 0xd4d01f95,0x9653bc4f,0x9560ad34,0x9aa83ea8,0xaf8e3f3f,0xf77943dc, + 0xe86fe16e,0x70774a10,0xbf9ffdcf,0x6b62e6f1,0x588745c9,0x8a72f39e } }, + /* 5 */ + { { 0x2341c342,0x73ade4da,0xea704422,0xdd326e54,0x3741cef3,0x336c7d98, + 0x59e61549,0x1eafa00d,0xbd9a3efd,0xcd3ed892,0xc5c6c7e4,0x03faf26c }, + { 0x3045f8ac,0x087e2fcf,0x174f1e73,0x14a65532,0xfe0af9a7,0x2cf84f28, + 0x2cdc935b,0xddfd7a84,0x6929c895,0x4c0f117b,0x4c8bcfcc,0x356572d6 } }, + /* 6 */ + { { 0x3f3b236f,0xfab08607,0x81e221da,0x19e9d41d,0x3927b428,0xf3f6571e, + 0x7550f1f6,0x4348a933,0xa85e62f0,0x7167b996,0x7f5452bf,0x62d43759 }, + { 0xf2955926,0xd85feb9e,0x6df78353,0x440a561f,0x9ca36b59,0x389668ec, + 0xa22da016,0x052bf1a1,0xf6093254,0xbdfbff72,0xe22209f3,0x94e50f28 } }, + /* 7 */ + { { 0x3062e8af,0x90b2e5b3,0xe8a3d369,0xa8572375,0x201db7b1,0x3fe1b00b, + 0xee651aa2,0xe926def0,0xb9b10ad7,0x6542c9be,0xa2fcbe74,0x098e309b }, + { 0xfff1d63f,0x779deeb3,0x20bfd374,0x23d0e80a,0x8768f797,0x8452bb3b, + 0x1f952856,0xcf75bb4d,0x29ea3faa,0x8fe6b400,0x81373a53,0x12bd3e40 } }, + /* 8 */ + { { 0x16973cf4,0x070d34e1,0x7e4f34f7,0x20aee08b,0x5eb8ad29,0x269af9b9, + 0xa6a45dda,0xdde0a036,0x63df41e0,0xa18b528e,0xa260df2a,0x03cc71b2 }, + { 0xa06b1dd7,0x24a6770a,0x9d2675d3,0x5bfa9c11,0x96844432,0x73c1e2a1, + 0x131a6cf0,0x3660558d,0x2ee79454,0xb0289c83,0xc6d8ddcd,0xa6aefb01 } }, + /* 9 */ + { { 0x01ab5245,0xba1464b4,0xc48d93ff,0x9b8d0b6d,0x93ad272c,0x939867dc, + 0xae9fdc77,0xbebe085e,0x894ea8bd,0x73ae5103,0x39ac22e1,0x740fc89a }, + { 0x28e23b23,0x5e28b0a3,0xe13104d0,0x2352722e,0xb0a2640d,0xf4667a18, + 0x49bb37c3,0xac74a72e,0xe81e183a,0x79f734f0,0x3fd9c0eb,0xbffe5b6c } }, + /* 10 */ + { { 0x00623f3b,0x03cf2922,0x5f29ebff,0x095c7111,0x80aa6823,0x42d72247, + 0x7458c0b0,0x044c7ba1,0x0959ec20,0xca62f7ef,0xf8ca929f,0x40ae2ab7 }, + { 0xa927b102,0xb8c5377a,0xdc031771,0x398a86a0,0xc216a406,0x04908f9d, + 0x918d3300,0xb423a73a,0xe0b94739,0x634b0ff1,0x2d69f697,0xe29de725 } }, + /* 11 */ + { { 0x8435af04,0x744d1400,0xfec192da,0x5f255b1d,0x336dc542,0x1f17dc12, + 0x636a68a8,0x5c90c2a7,0x7704ca1e,0x960c9eb7,0x6fb3d65a,0x9de8cf1e }, + { 0x511d3d06,0xc60fee0d,0xf9eb52c7,0x466e2313,0x206b0914,0x743c0f5f, + 0x2191aa4d,0x42f55bac,0xffebdbc2,0xcefc7c8f,0xe6e8ed1c,0xd4fa6081 } }, + /* 12 */ + { { 0x98683186,0x867db639,0xddcc4ea9,0xfb5cf424,0xd4f0e7bd,0xcc9a7ffe, + 0x7a779f7e,0x7c57f71c,0xd6b25ef2,0x90774079,0xb4081680,0x90eae903 }, + { 0x0ee1fceb,0xdf2aae5e,0xe86c1a1f,0x3ff1da24,0xca193edf,0x80f587d6, + 0xdc9b9d6a,0xa5695523,0x85920303,0x7b840900,0xba6dbdef,0x1efa4dfc } }, + /* 13 */ + { { 0xe0540015,0xfbd838f9,0xc39077dc,0x2c323946,0xad619124,0x8b1fb9e6, + 0x0ca62ea8,0x9612440c,0x2dbe00ff,0x9ad9b52c,0xae197643,0xf52abaa1 }, + { 0x2cac32ad,0xd0e89894,0x62a98f91,0xdfb79e42,0x276f55cb,0x65452ecf, + 0x7ad23e12,0xdb1ac0d2,0xde4986f0,0xf68c5f6a,0x82ce327d,0x389ac37b } }, + /* 14 */ + { { 0xb8a9e8c9,0xcd96866d,0x5bb8091e,0xa11963b8,0x045b3cd2,0xc7f90d53, + 0x80f36504,0x755a72b5,0x21d3751c,0x46f8b399,0x53c193de,0x4bffdc91 }, + { 0xb89554e7,0xcd15c049,0xf7a26be6,0x353c6754,0xbd41d970,0x79602370, + 0x12b176c0,0xde16470b,0x40c8809d,0x56ba1175,0xe435fb1e,0xe2db35c3 } }, + /* 15 */ + { { 0x6328e33f,0xd71e4aab,0xaf8136d1,0x5486782b,0x86d57231,0x07a4995f, + 0x1651a968,0xf1f0a5bd,0x76803b6d,0xa5dc5b24,0x42dda935,0x5c587cbc }, + { 0xbae8b4c0,0x2b6cdb32,0xb1331138,0x66d1598b,0x5d7e9614,0x4a23b2d2, + 0x74a8c05d,0x93e402a6,0xda7ce82e,0x45ac94e6,0xe463d465,0xeb9f8281 } }, +}; + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + return sp_384_ecc_mulmod_stripe_12(r, &p384_base, p384_table, + k, map, heap); +} + +#else +static const sp_table_entry_384 p384_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x49c0b528,0x3dd07566,0xa0d6ce38,0x20e378e2,0x541b4d6e,0x879c3afc, + 0x59a30eff,0x64548684,0x614ede2b,0x812ff723,0x299e1513,0x4d3aadc2 }, + { 0x4b03a4fe,0x23043dad,0x7bb4a9ac,0xa1bfa8bf,0x2e83b050,0x8bade756, + 0x68f4ffd9,0xc6c35219,0x3969a840,0xdd800226,0x5a15c5e9,0x2b78abc2 } }, + /* 2 */ + { { 0x2b0c535b,0x29864753,0x70506296,0x90dd6953,0x216ab9ac,0x038cd6b4, + 0xbe12d76a,0x3df9b7b7,0x5f347bdb,0x13f4d978,0x13e94489,0x222c5c9c }, + { 0x2680dc64,0x5f8e796f,0x58352417,0x120e7cb7,0xd10740b8,0x254b5d8a, + 0x5337dee6,0xc38b8efb,0x94f02247,0xf688c2e1,0x6c25bc4c,0x7b5c75f3 } }, + /* 3 */ + { { 0x9edffea5,0xe26a3cc3,0x37d7e9fc,0x35bbfd1c,0x9bde3ef6,0xf0e7700d, + 0x1a538f5a,0x0380eb47,0x05bf9eb3,0x2e9da8bb,0x1a460c3e,0xdbb93c73 }, + { 0xf526b605,0x37dba260,0xfd785537,0x95d4978e,0xed72a04a,0x24ed793a, + 0x76005b1a,0x26948377,0x9e681f82,0x99f557b9,0xd64954ef,0xae5f9557 } }, + /* 4 */ + { { 0xf26feef9,0x24480c57,0x3a0e1240,0xc31a2694,0x273e2bc7,0x735002c3, + 0x3ef1ed4c,0x8c42e9c5,0x7f4948e8,0x028babf6,0x8a978632,0x6a502f43 }, + { 0xb74536fe,0xf5f13a46,0xd8a9f0eb,0x1d218bab,0x37232768,0x30f36bcc, + 0x576e8c18,0xc5317b31,0x9bbcb766,0xef1d57a6,0xb3e3d4dc,0x917c4930 } }, + /* 5 */ + { { 0xe349ddd0,0x11426e2e,0x9b2fc250,0x9f117ef9,0xec0174a6,0xff36b480, + 0x18458466,0x4f4bde76,0x05806049,0x2f2edb6d,0x19dfca92,0x8adc75d1 }, + { 0xb7d5a7ce,0xa619d097,0xa34411e9,0x874275e5,0x0da4b4ef,0x5403e047, + 0x77901d8f,0x2ebaafd9,0xa747170f,0x5e63ebce,0x7f9d8036,0x12a36944 } }, + /* 6 */ + { { 0x4fc52870,0x28f9c07a,0x1a53a961,0xce0b3748,0x0e1828d9,0xd550fa18, + 0x6adb225a,0xa24abaf7,0x6e58a348,0xd11ed0a5,0x948acb62,0xf3d811e6 }, + { 0x4c61ed22,0x8618dd77,0x80b47c9d,0x0bb747f9,0xde6b8559,0x22bf796f, + 0x680a21e9,0xfdfd1c6d,0x2af2c9dd,0xc0db1577,0xc1e90f3d,0xa09379e6 } }, + /* 7 */ + { { 0xe085c629,0x386c66ef,0x095bc89a,0x5fc2a461,0x203f4b41,0x1353d631, + 0x7e4bd8f5,0x7ca1972b,0xa7df8ce9,0xb077380a,0xee7e4ea3,0xd8a90389 }, + { 0xe7b14461,0x1bc74dc7,0x0c9c4f78,0xdc2cb014,0x84ef0a10,0x52b4b3a6, + 0x20327fe2,0xbde6ea5d,0x660f9615,0xb71ec435,0xb8ad8173,0xeede5a04 } }, + /* 8 */ + { { 0x893b9a2d,0x5584cbb3,0x00850c5d,0x820c660b,0x7df2d43d,0x4126d826, + 0x0109e801,0xdd5bbbf0,0x38172f1c,0x85b92ee3,0xf31430d9,0x609d4f93 }, + { 0xeadaf9d6,0x1e059a07,0x0f125fb0,0x70e6536c,0x560f20e7,0xd6220751, + 0x7aaf3a9a,0xa59489ae,0x64bae14e,0x7b70e2f6,0x76d08249,0x0dd03701 } }, + /* 9 */ + { { 0x8510521f,0x4cc13be8,0xf724cc17,0x87315ba9,0x353dc263,0xb49d83bb, + 0x0c279257,0x8b677efe,0xc93c9537,0x510a1c1c,0xa4702c99,0x33e30cd8 }, + { 0x2208353f,0xf0ffc89d,0xced42b2b,0x0170fa8d,0x26e2a5f5,0x090851ed, + 0xecb52c96,0x81276455,0x7fe1adf4,0x0646c4e1,0xb0868eab,0x513f047e } }, + /* 10 */ + { { 0xdf5bdf53,0xc07611f4,0x58b11a6d,0x45d331a7,0x1c4ee394,0x58965daf, + 0x5a5878d1,0xba8bebe7,0x82dd3025,0xaecc0a18,0xa923eb8b,0xcf2a3899 }, + { 0xd24fd048,0xf98c9281,0x8bbb025d,0x841bfb59,0xc9ab9d53,0xb8ddf8ce, + 0x7fef044e,0x538a4cb6,0x23236662,0x092ac21f,0x0b66f065,0xa919d385 } }, + /* 11 */ + { { 0x85d480d8,0x3db03b40,0x1b287a7d,0x8cd9f479,0x4a8f3bae,0x8f24dc75, + 0x3db41892,0x482eb800,0x9c56e0f5,0x38bf9eb3,0x9a91dc6f,0x8b977320 }, + { 0x7209cfc2,0xa31b05b2,0x05b2db70,0x4c49bf85,0xd619527b,0x56462498, + 0x1fac51ba,0x3fe51039,0xab4b8342,0xfb04f55e,0x04c6eabf,0xc07c10dc } }, + /* 12 */ + { { 0xdb32f048,0xad22fe4c,0x475ed6df,0x5f23bf91,0xaa66b6cb,0xa50ce0c0, + 0xf03405c0,0xdf627a89,0xf95e2d6a,0x3674837d,0xba42e64e,0x081c95b6 }, + { 0xe71d6ceb,0xeba3e036,0x6c6b0271,0xb45bcccf,0x0684701d,0x67b47e63, + 0xe712523f,0x60f8f942,0x5cd47adc,0x82423472,0x87649cbb,0x83027d79 } }, + /* 13 */ + { { 0x3615b0b8,0xb3929ea6,0xa54dac41,0xb41441fd,0xb5b6a368,0x8995d556, + 0x167ef05e,0xa80d4529,0x6d25a27f,0xf6bcb4a1,0x7bd55b68,0x210d6a4c }, + { 0x25351130,0xf3804abb,0x903e37eb,0x1d2df699,0x084c25c8,0x5f201efc, + 0xa1c68e91,0x31a28c87,0x563f62a5,0x81dad253,0xd6c415d4,0x5dd6de70 } }, + /* 14 */ + { { 0x846612ce,0x29f470fd,0xda18d997,0x986f3eec,0x2f34af86,0x6b84c161, + 0x46ddaf8b,0x5ef0a408,0xe49e795f,0x14405a00,0xaa2f7a37,0x5f491b16 }, + { 0xdb41b38d,0xc7f07ae4,0x18fbfcaa,0xef7d119e,0x14443b19,0x3a18e076, + 0x79a19926,0x4356841a,0xe2226fbe,0x91f4a91c,0x3cc88721,0xdc77248c } }, + /* 15 */ + { { 0xe4b1ec9d,0xd570ff1a,0xe7eef706,0x21d23e0e,0xca19e086,0x3cde40f4, + 0xcd4bb270,0x7d6523c4,0xbf13aa6c,0x16c1f06c,0xd14c4b60,0x5aa7245a }, + { 0x44b74de8,0x37f81467,0x620a934e,0x839e7a17,0xde8b1aa1,0xf74d14e8, + 0xf30d75e2,0x8789fa51,0xc81c261e,0x09b24052,0x33c565ee,0x654e2678 } }, + /* 16 */ + { { 0x2f9fbe67,0x378205de,0x7f728e44,0xc4afcb83,0x682e00f1,0xdbcec06c, + 0x114d5423,0xf2a145c3,0x7a52463e,0xa01d9874,0x7d717b0a,0xfc0935b1 }, + { 0xd4d01f95,0x9653bc4f,0x9560ad34,0x9aa83ea8,0xaf8e3f3f,0xf77943dc, + 0xe86fe16e,0x70774a10,0xbf9ffdcf,0x6b62e6f1,0x588745c9,0x8a72f39e } }, + /* 17 */ + { { 0x2341c342,0x73ade4da,0xea704422,0xdd326e54,0x3741cef3,0x336c7d98, + 0x59e61549,0x1eafa00d,0xbd9a3efd,0xcd3ed892,0xc5c6c7e4,0x03faf26c }, + { 0x3045f8ac,0x087e2fcf,0x174f1e73,0x14a65532,0xfe0af9a7,0x2cf84f28, + 0x2cdc935b,0xddfd7a84,0x6929c895,0x4c0f117b,0x4c8bcfcc,0x356572d6 } }, + /* 18 */ + { { 0x7d8c1bba,0x7ecbac01,0x90b0f3d5,0x6058f9c3,0xf6197d0f,0xaee116e3, + 0x4033b128,0xc4dd7068,0xc209b983,0xf084dba6,0x831dbc4a,0x97c7c2cf }, + { 0xf96010e8,0x2f4e61dd,0x529faa17,0xd97e4e20,0x69d37f20,0x4ee66660, + 0x3d366d72,0xccc139ed,0x13488e0f,0x690b6ee2,0xf3a6d533,0x7cad1dc5 } }, + /* 19 */ + { { 0xda57a41f,0x660a9a81,0xec0039b6,0xe74a0412,0x5e1dad15,0x42343c6b, + 0x46681d4c,0x284f3ff5,0x63749e89,0xb51087f1,0x6f9f2f13,0x070f23cc }, + { 0x5d186e14,0x542211da,0xfddb0dff,0x84748f37,0xdb1f4180,0x41a3aab4, + 0xa6402d0e,0x25ed667b,0x02f58355,0x2f2924a9,0xfa44a689,0x5844ee7c } }, + /* 20 */ + { { 0x3f3b236f,0xfab08607,0x81e221da,0x19e9d41d,0x3927b428,0xf3f6571e, + 0x7550f1f6,0x4348a933,0xa85e62f0,0x7167b996,0x7f5452bf,0x62d43759 }, + { 0xf2955926,0xd85feb9e,0x6df78353,0x440a561f,0x9ca36b59,0x389668ec, + 0xa22da016,0x052bf1a1,0xf6093254,0xbdfbff72,0xe22209f3,0x94e50f28 } }, + /* 21 */ + { { 0x3062e8af,0x90b2e5b3,0xe8a3d369,0xa8572375,0x201db7b1,0x3fe1b00b, + 0xee651aa2,0xe926def0,0xb9b10ad7,0x6542c9be,0xa2fcbe74,0x098e309b }, + { 0xfff1d63f,0x779deeb3,0x20bfd374,0x23d0e80a,0x8768f797,0x8452bb3b, + 0x1f952856,0xcf75bb4d,0x29ea3faa,0x8fe6b400,0x81373a53,0x12bd3e40 } }, + /* 22 */ + { { 0x104cbba5,0xc023780d,0xfa35dd4c,0x6207e747,0x1ca9b6a3,0x35c23928, + 0x97987b10,0x4ff19be8,0x8022eee8,0xb8476bbf,0xd3bbe74d,0xaa0a4a14 }, + { 0x187d4543,0x20f94331,0x79f6e066,0x32153870,0xac7e82e1,0x83b0f74e, + 0x828f06ab,0xa7748ba2,0xc26ef35f,0xc5f0298a,0x8e9a7dbd,0x0f0c5070 } }, + /* 23 */ + { { 0xdef029dd,0x0c5c244c,0x850661b8,0x3dabc687,0xfe11d981,0x9992b865, + 0x6274dbad,0xe9801b8f,0x098da242,0xe54e6319,0x91a53d08,0x9929a91a }, + { 0x35285887,0x37bffd72,0xf1418102,0xbc759425,0xfd2e6e20,0x9280cc35, + 0xfbc42ee5,0x735c600c,0x8837619a,0xb7ad2864,0xa778c57b,0xa3627231 } }, + /* 24 */ + { { 0x91361ed8,0xae799b5c,0x6c63366c,0x47d71b75,0x1b265a6a,0x54cdd521, + 0x98d77b74,0xe0215a59,0xbab29db0,0x4424d9b7,0x7fd9e536,0x8b0ffacc }, + { 0x37b5d9ef,0x46d85d12,0xbfa91747,0x5b106d62,0x5f99ba2d,0xed0479f8, + 0x1d104de4,0x0e6f3923,0x25e8983f,0x83a84c84,0xf8105a70,0xa9507e0a } }, + /* 25 */ + { { 0x14cf381c,0xf6c68a6e,0xc22e31cc,0xaf9d27bd,0xaa8a5ccb,0x23568d4d, + 0xe338e4d2,0xe431eec0,0x8f52ad1f,0xf1a828fe,0xe86acd80,0xdb6a0579 }, + { 0x4507832a,0x2885672e,0x887e5289,0x73fc275f,0x05610d08,0x65f80278, + 0x075ff5b0,0x8d9b4554,0x09f712b5,0x3a8e8fb1,0x2ebe9cf2,0x39f0ac86 } }, + /* 26 */ + { { 0x4c52edf5,0xd8fabf78,0xa589ae53,0xdcd737e5,0xd791ab17,0x94918bf0, + 0xbcff06c9,0xb5fbd956,0xdca46d45,0xf6d3032e,0x41a3e486,0x2cdff7e1 }, + { 0x61f47ec8,0x6674b3ba,0xeef84608,0x8a882163,0x4c687f90,0xa257c705, + 0xf6cdf227,0xe30cb2ed,0x7f6ea846,0x2c4c64ca,0xcc6bcd3c,0x186fa17c } }, + /* 27 */ + { { 0x1dfcb91e,0x48a3f536,0x646d358a,0x83595e13,0x91128798,0xbd15827b, + 0x2187757a,0x3ce612b8,0x61bd7372,0x873150a1,0xb662f568,0xf4684530 }, + { 0x401896f6,0x8833950b,0x77f3e090,0xe11cb89a,0x48e7f4a5,0xb2f12cac, + 0xf606677e,0x313dd769,0x16579f93,0xfdcf08b3,0x46b8f22b,0x6429cec9 } }, + /* 28 */ + { { 0xbb75f9a4,0x4984dd54,0x29d3b570,0x4aef06b9,0x3d6e4c1e,0xb5f84ca2, + 0xb083ef35,0x24c61c11,0x392ca9ff,0xce4a7392,0x6730a800,0x865d6517 }, + { 0x722b4a2b,0xca3dfe76,0x7b083e0e,0x12c04bf9,0x1b86b8a5,0x803ce5b5, + 0x6a7e3e0c,0x3fc7632d,0xc81adbe4,0xc89970c2,0x120e16b1,0x3cbcd3ad } }, + /* 29 */ + { { 0xec30ce93,0xfbfb4cc7,0xb72720a2,0x10ed6c7d,0x47b55500,0xec675bf7, + 0x333ff7c3,0x90725903,0x5075bfc0,0xc7c3973e,0x07acf31b,0xb049ecb0 }, + { 0x4f58839c,0xb4076eaf,0xa2b05e4f,0x101896da,0xab40c66e,0x3f6033b0, + 0xc8d864ba,0x19ee9eeb,0x47bf6d2a,0xeb6cf155,0xf826477d,0x8e5a9663 } }, + /* 30 */ + { { 0xf7fbd5e1,0x69e62fdd,0x76912b1d,0x38ecfe54,0xd1da3bfb,0x845a3d56, + 0x1c86f0d4,0x0494950e,0x3bc36ce8,0x83cadbf9,0x4fccc8d1,0x41fce572 }, + { 0x8332c144,0x05f939c2,0x0871e46e,0xb17f248b,0x66e8aff6,0x3d8534e2, + 0x3b85c629,0x1d06f1dc,0xa3131b73,0xdb06a32e,0x8b3f64e5,0xf295184d } }, + /* 31 */ + { { 0x36ddc103,0xd9653ff7,0x95ef606f,0x25f43e37,0xfe06dce8,0x09e301fc, + 0x30b6eebf,0x85af2341,0x0ff56b20,0x79b12b53,0xfe9a3c6b,0x9b4fb499 }, + { 0x51d27ac2,0x0154f892,0x56ca5389,0xd33167e3,0xafc065a6,0x7828ec1f, + 0x7f746c9b,0x0959a258,0x0c44f837,0xb18f1be3,0xc4132fdb,0xa7946117 } }, + /* 32 */ + { { 0x5e3c647b,0xc0426b77,0x8cf05348,0xbfcbd939,0x172c0d3d,0x31d312e3, + 0xee754737,0x5f49fde6,0x6da7ee61,0x895530f0,0xe8b3a5fb,0xcf281b0a }, + { 0x41b8a543,0xfd149735,0x3080dd30,0x41a625a7,0x653908cf,0xe2baae07, + 0xba02a278,0xc3d01436,0x7b21b8f8,0xa0d0222e,0xd7ec1297,0xfdc270e9 } }, + /* 33 */ + { { 0xbc7f41d6,0x00873c0c,0x1b7ad641,0xd976113e,0x238443fb,0x2a536ff4, + 0x41e62e45,0x030d00e2,0x5f545fc6,0x532e9867,0x8e91208c,0xcd033108 }, + { 0x9797612c,0xd1a04c99,0xeea674e2,0xd4393e02,0xe19742a1,0xd56fa69e, + 0x85f0590e,0xdd2ab480,0x48a2243d,0xa5cefc52,0x54383f41,0x48cc67b6 } }, + /* 34 */ + { { 0xfc14ab48,0x4e50430e,0x26706a74,0x195b7f4f,0xcc881ff6,0x2fe8a228, + 0xd945013d,0xb1b968e2,0x4b92162b,0x936aa579,0x364e754a,0x4fb766b7 }, + { 0x31e1ff7f,0x13f93bca,0xce4f2691,0x696eb5ca,0xa2b09e02,0xff754bf8, + 0xe58e3ff8,0x58f13c9c,0x1678c0b0,0xb757346f,0xa86692b3,0xd54200db } }, + /* 35 */ + { { 0x6dda1265,0x9a030bbd,0xe89718dd,0xf7b4f3fc,0x936065b8,0xa6a4931f, + 0x5f72241c,0xbce72d87,0x65775857,0x6cbb51cb,0x4e993675,0xc7161815 }, + { 0x2ee32189,0xe81a0f79,0x277dc0b2,0xef2fab26,0xb71f469f,0x9e64f6fe, + 0xdfdaf859,0xb448ce33,0xbe6b5df1,0x3f5c1c4c,0x1de45f7b,0xfb8dfb00 } }, + /* 36 */ + { { 0x4d5bb921,0xc7345fa7,0x4d2b667e,0x5c7e04be,0x282d7a3e,0x47ed3a80, + 0x7e47b2a4,0x5c2777f8,0x08488e2e,0x89b3b100,0xb2eb5b45,0x9aad77c2 }, + { 0xdaac34ae,0xd681bca7,0x26afb326,0x2452e4e5,0x41a1ee14,0x0c887924, + 0xc2407ade,0x743b04d4,0xfc17a2ac,0xcb5e999b,0x4a701a06,0x4dca2f82 } }, + /* 37 */ + { { 0x1127bc1a,0x68e31ca6,0x17ead3be,0xa3edd59b,0xe25f5a15,0x67b6b645, + 0xa420e15e,0x76221794,0x4b1e872e,0x794fd83b,0xb2dece1b,0x7cab3f03 }, + { 0xca9b3586,0x7119bf15,0x4d250bd7,0xa5545924,0xcc6bcf24,0x173633ea, + 0xb1b6f884,0x9bd308c2,0x447d38c3,0x3bae06f5,0xf341fe1c,0x54dcc135 } }, + /* 38 */ + { { 0x943caf0d,0x56d3598d,0x225ff133,0xce044ea9,0x563fadea,0x9edf6a7c, + 0x73e8dc27,0x632eb944,0x3190dcab,0x814b467e,0x6dbb1e31,0x2d4f4f31 }, + { 0xa143b7ca,0x8d69811c,0xde7cf950,0x4ec1ac32,0x37b5fe82,0x223ab5fd, + 0x9390f1d9,0xe82616e4,0x75804610,0xabff4b20,0x875b08f0,0x11b9be15 } }, + /* 39 */ + { { 0x3bbe682c,0x4ae31a3d,0x74eef2dd,0xbc7c5d26,0x3c47dd40,0x92afd10a, + 0xc14ab9e1,0xec7e0a3b,0xb2e495e4,0x6a6c3dd1,0x309bcd85,0x085ee5e9 }, + { 0x8c2e67fd,0xf381a908,0xe261eaf2,0x32083a80,0x96deee15,0x0fcd6a49, + 0x5e524c79,0xe3b8fb03,0x1d5b08b9,0x8dc360d9,0x7f26719f,0x3a06e2c8 } }, + /* 40 */ + { { 0x7237cac0,0x5cd9f5a8,0x43586794,0x93f0b59d,0xe94f6c4e,0x4384a764, + 0xb62782d3,0x8304ed2b,0xcde06015,0x0b8db8b3,0x5dbe190f,0x4336dd53 }, + { 0x92ab473a,0x57443553,0xbe5ed046,0x031c7275,0x21909aa4,0x3e78678c, + 0x99202ddb,0x4ab7e04f,0x6977e635,0x2648d206,0x093198be,0xd427d184 } }, + /* 41 */ + { { 0x0f9b5a31,0x822848f5,0xbaadb62a,0xbb003468,0x3357559c,0x233a0472, + 0x79aee843,0x49ef6880,0xaeb9e1e3,0xa89867a0,0x1f6f9a55,0xc151931b }, + { 0xad74251e,0xd264eb0b,0x4abf295e,0x37b9b263,0x04960d10,0xb600921b, + 0x4da77dc0,0x0de53dbc,0xd2b18697,0x01d9bab3,0xf7156ddf,0xad54ec7a } }, + /* 42 */ + { { 0x79efdc58,0x8e74dc35,0x4ff68ddb,0x456bd369,0xd32096a5,0x724e74cc, + 0x386783d0,0xe41cff42,0x7c70d8a4,0xa04c7f21,0xe61a19a2,0x41199d2f }, + { 0x29c05dd2,0xd389a3e0,0xe7e3fda9,0x535f2a6b,0x7c2b4df8,0x26ecf72d, + 0xfe745294,0x678275f4,0x9d23f519,0x6319c9cc,0x88048fc4,0x1e05a02d } }, + /* 43 */ + { { 0xd4d5ffe8,0x75cc8e2e,0xdbea17f2,0xf8bb4896,0xcee3cb4a,0x35059790, + 0xa47c6165,0x4c06ee85,0x92935d2f,0xf98fff25,0x32ffd7c7,0x34c4a572 }, + { 0xea0376a2,0xc4b14806,0x4f115e02,0x2ea5e750,0x1e55d7c0,0x532d76e2, + 0xf31044da,0x68dc9411,0x71b77993,0x9272e465,0x93a8cfd5,0xadaa38bb } }, + /* 44 */ + { { 0x7d4ed72a,0x4bf0c712,0xba1f79a3,0xda0e9264,0xf4c39ea4,0x48c0258b, + 0x2a715138,0xa5394ed8,0xbf06c660,0x4af511ce,0xec5c37cd,0xfcebceef }, + { 0x779ae8c1,0xf23b75aa,0xad1e606e,0xdeff59cc,0x22755c82,0xf3f526fd, + 0xbb32cefd,0x64c5ab44,0x915bdefd,0xa96e11a2,0x1143813e,0xab19746a } }, + /* 45 */ + { { 0xec837d7d,0x43c78585,0xb8ee0ba4,0xca5b6fbc,0xd5dbb5ee,0x34e924d9, + 0xbb4f1ca5,0x3f4fa104,0x398640f7,0x15458b72,0xd7f407ea,0x4231faa9 }, + { 0xf96e6896,0x53e0661e,0xd03b0f9d,0x554e4c69,0x9c7858d1,0xd4fcb07b, + 0x52cb04fa,0x7e952793,0x8974e7f7,0x5f5f1574,0x6b6d57c8,0x2e3fa558 } }, + /* 46 */ + { { 0x6a9951a8,0x42cd4803,0x42792ad0,0xa8b15b88,0xabb29a73,0x18e8bcf9, + 0x409933e8,0xbfd9a092,0xefb88dc4,0x760a3594,0x40724458,0x14418863 }, + { 0x99caedc7,0x162a56ee,0x91d101c9,0x8fb12ecd,0x393202da,0xea671967, + 0xa4ccd796,0x1aac8c4a,0x1cf185a8,0x7db05036,0x8cfd095a,0x0c9f86cd } }, + /* 47 */ + { { 0x10b2a556,0x9a728147,0x327b70b2,0x767ca964,0x5e3799b7,0x04ed9e12, + 0x22a3eb2a,0x6781d2dc,0x0d9450ac,0x5bd116eb,0xa7ebe08a,0xeccac1fc }, + { 0xdc2d6e94,0xde68444f,0x35ecf21b,0x3621f429,0x29e03a2c,0x14e2d543, + 0x7d3e7f0a,0x53e42cd5,0x73ed00b9,0xbba26c09,0xc57d2272,0x00297c39 } }, + /* 48 */ + { { 0xb8243a7d,0x3aaaab10,0x8fa58c5b,0x6eeef93e,0x9ae7f764,0xf866fca3, + 0x61ab04d3,0x64105a26,0x03945d66,0xa3578d8a,0x791b848c,0xb08cd3e4 }, + { 0x756d2411,0x45edc5f8,0xa755128c,0xd4a790d9,0x49e5f6a0,0xc2cf0963, + 0xf649beaa,0xc66d267d,0x8467039e,0x3ce6d968,0x42f7816f,0x50046c6b } }, + /* 49 */ + { { 0x66425043,0x92ae1602,0xf08db890,0x1ff66afd,0x8f162ce5,0x386f5a7f, + 0xfcf5598f,0x18d2dea0,0x1a8ca18e,0x78372b3a,0x8cd0e6f7,0xdf0d20eb }, + { 0x75bb4045,0x7edd5e1d,0xb96d94b7,0x252a47ce,0x2c626776,0xbdb29358, + 0x40dd1031,0x853c3943,0x7d5f47fd,0x9dc9becf,0xbae4044a,0x27c2302f } }, + /* 50 */ + { { 0x8f2d49ce,0x2d1d208a,0x162df0a2,0x0d91aa02,0x09a07f65,0x9c5cce87, + 0x84339012,0xdf07238b,0x419442cd,0x5028e2c8,0x72062aba,0x2dcbd358 }, + { 0xe4680967,0xb5fbc3cb,0x9f92d72c,0x2a7bc645,0x116c369d,0x806c76e1, + 0x3177e8d8,0x5c50677a,0x4569df57,0x753739eb,0x36c3f40b,0x2d481ef6 } }, + /* 51 */ + { { 0xfea1103e,0x1a2d39fd,0x95f81b17,0xeaae5592,0xf59b264a,0xdbd0aa18, + 0xcb592ee0,0x90c39c1a,0x9750cca3,0xdf62f80d,0xdf97cc6c,0xda4d8283 }, + { 0x1e201067,0x0a6dd346,0x69fb1f6b,0x1531f859,0x1d60121f,0x4895e552, + 0x4c041c91,0x0b21aab0,0xbcc1ccf8,0x9d896c46,0x3141bde7,0xd24da3b3 } }, + /* 52 */ + { { 0x53b0a354,0x575a0537,0x0c6ddcd8,0x392ff2f4,0x56157b94,0x0b8e8cff, + 0x3b1b80d1,0x073e57bd,0x3fedee15,0x2a75e0f0,0xaa8e6f19,0x752380e4 }, + { 0x6558ffe9,0x1f4e227c,0x19ec5415,0x3a348618,0xf7997085,0xab382d5e, + 0xddc46ac2,0x5e6deaff,0xfc8d094c,0xe5144078,0xf60e37c6,0xf674fe51 } }, + /* 53 */ + { { 0xaf63408f,0x6fb87ae5,0xcd75a737,0xa39c36a9,0xcf4c618d,0x7833313f, + 0xf034c88d,0xfbcd4482,0x39b35288,0x4469a761,0x66b5d9c9,0x77a711c5 }, + { 0x944f8d65,0x4a695dc7,0x161aaba8,0xe6da5f65,0x24601669,0x8654e9c3, + 0x28ae7491,0xbc8b93f5,0x8f5580d8,0x5f1d1e83,0xcea32cc8,0x8ccf9a1a } }, + /* 54 */ + { { 0x7196fee2,0x28ab110c,0x874c8945,0x75799d63,0x29aedadd,0xa2629348, + 0x2be88ff4,0x9714cc7b,0xd58d60d6,0xf71293cf,0x32a564e9,0xda6b6cb3 }, + { 0x3dd821c2,0xf43fddb1,0x90dd323d,0xf2f2785f,0x048489f8,0x91246419, + 0xd24c6749,0x61660f26,0xc803c15c,0x961d9e8c,0xfaadc4c9,0x631c6158 } }, + /* 55 */ + { { 0xfd752366,0xacf2ebe0,0x139be88b,0xb93c340e,0x0f20179e,0x98f66485, + 0xff1da785,0x14820254,0x4f85c16e,0x5278e276,0x7aab1913,0xa246ee45 }, + { 0x53763b33,0x43861eb4,0x45c0bc0d,0xc49f03fc,0xad6b1ea1,0xafff16bc, + 0x6fd49c99,0xce33908b,0xf7fde8c3,0x5c51e9bf,0xff142c5e,0x076a7a39 } }, + /* 56 */ + { { 0x9e338d10,0x04639dfe,0xf42b411b,0x8ee6996f,0xa875cef2,0x960461d1, + 0x95b4d0ba,0x1057b6d6,0xa906e0bc,0x27639252,0xe1c20f8a,0x2c19f09a }, + { 0xeef4c43d,0x5b8fc3f0,0x07a84aa9,0xe2e1b1a8,0x835d2bdb,0x5f455528, + 0x207132dd,0x0f4aee4d,0x3907f675,0xe9f8338c,0x0e0531f0,0x7a874dc9 } }, + /* 57 */ + { { 0x97c27050,0x84b22d45,0x59e70bf8,0xbd0b8df7,0x79738b9b,0xb4d67405, + 0xcd917c4f,0x47f4d5f5,0x13ce6e33,0x9099c4ce,0x521d0f8b,0x942bfd39 }, + { 0xa43b566d,0x5028f0f6,0x21bff7de,0xaf6e8669,0xc44232cd,0x83f6f856, + 0xf915069a,0x65680579,0xecfecb85,0xd12095a2,0xdb01ba16,0xcf7f06ae } }, + /* 58 */ + { { 0x8ef96c80,0x0f56e3c4,0x3ddb609c,0xd521f2b3,0x7dc1450d,0x2be94102, + 0x02a91fe2,0x2d21a071,0x1efa37de,0x2e6f74fa,0x156c28a1,0x9a9a90b8 }, + { 0x9dc7dfcb,0xc54ea9ea,0x2c2c1d62,0xc74e66fc,0x49d3e067,0x9f23f967, + 0x54dd38ad,0x1c7c3a46,0x5946cee3,0xc7005884,0x45cc045d,0x89856368 } }, + /* 59 */ + { { 0xfce73946,0x29da7cd4,0x23168563,0x8f697db5,0xcba92ec6,0x8e235e9c, + 0x9f91d3ea,0x55d4655f,0xaa50a6cd,0xf3689f23,0x21e6a1a0,0xdcf21c26 }, + { 0x61b818bf,0xcffbc82e,0xda47a243,0xc74a2f96,0x8bc1a0cf,0x234e980a, + 0x7929cb6d,0xf35fd6b5,0xefe17d6c,0x81468e12,0x58b2dafb,0xddea6ae5 } }, + /* 60 */ + { { 0x7e787b2e,0x294de887,0x39a9310d,0x258acc1f,0xac14265d,0x92d9714a, + 0x708b48a0,0x18b5591c,0xe1abbf71,0x27cc6bb0,0x568307b9,0xc0581fa3 }, + { 0xf24d4d58,0x9e0f58a3,0xe0ce2327,0xfebe9bb8,0x9d1be702,0x91fd6a41, + 0xfacac993,0x9a7d8a45,0x9e50d66d,0xabc0a08c,0x06498201,0x02c342f7 } }, + /* 61 */ + { { 0x157bdbc2,0xccd71407,0xad0e1605,0x72fa89c6,0xb92a015f,0xb1d3da2b, + 0xa0a3fe56,0x8ad9e7cd,0x24f06737,0x160edcbd,0x61275be6,0x79d4db33 }, + { 0x5f3497c4,0xd3d31fd9,0x04192fb0,0x8cafeaee,0x13a50af3,0xe13ca745, + 0x8c85aae5,0x18826167,0x9eb556ff,0xce06cea8,0xbdb549f3,0x2eef1995 } }, + /* 62 */ + { { 0x50596edc,0x8ed7d3eb,0x905243a2,0xaa359362,0xa4b6d02b,0xa212c2c2, + 0xc4fbec68,0x611fd727,0xb84f733d,0x8a0b8ff7,0x5f0daf0e,0xd85a6b90 }, + { 0xd4091cf7,0x60e899f5,0x2eff2768,0x4fef2b67,0x10c33964,0xc1f195cb, + 0x93626a8f,0x8275d369,0x0d6c840a,0xc77904f4,0x7a868acd,0x88d8b7fd } }, + /* 63 */ + { { 0x7bd98425,0x85f23723,0xc70b154e,0xd4463992,0x96687a2e,0xcbb00ee2, + 0xc83214fd,0x905fdbf7,0x13593684,0x2019d293,0xef51218e,0x0428c393 }, + { 0x981e909a,0x40c7623f,0x7be192da,0x92513385,0x4010907e,0x48fe480f, + 0x3120b459,0xdd7a187c,0xa1fd8f3c,0xc9d7702d,0xe358efc5,0x66e4753b } }, + /* 64 */ + { { 0x16973cf4,0x070d34e1,0x7e4f34f7,0x20aee08b,0x5eb8ad29,0x269af9b9, + 0xa6a45dda,0xdde0a036,0x63df41e0,0xa18b528e,0xa260df2a,0x03cc71b2 }, + { 0xa06b1dd7,0x24a6770a,0x9d2675d3,0x5bfa9c11,0x96844432,0x73c1e2a1, + 0x131a6cf0,0x3660558d,0x2ee79454,0xb0289c83,0xc6d8ddcd,0xa6aefb01 } }, + /* 65 */ + { { 0x01ab5245,0xba1464b4,0xc48d93ff,0x9b8d0b6d,0x93ad272c,0x939867dc, + 0xae9fdc77,0xbebe085e,0x894ea8bd,0x73ae5103,0x39ac22e1,0x740fc89a }, + { 0x28e23b23,0x5e28b0a3,0xe13104d0,0x2352722e,0xb0a2640d,0xf4667a18, + 0x49bb37c3,0xac74a72e,0xe81e183a,0x79f734f0,0x3fd9c0eb,0xbffe5b6c } }, + /* 66 */ + { { 0xc6a2123f,0xb1a358f5,0xfe28df6d,0x927b2d95,0xf199d2f9,0x89702753, + 0x1a3f82dc,0x0a73754c,0x777affe1,0x063d029d,0xdae6d34d,0x5439817e }, + { 0x6b8b83c4,0xf7979eef,0x9d945682,0x615cb214,0xc5e57eae,0x8f0e4fac, + 0x113047dd,0x042b89b8,0x93f36508,0x888356dc,0x5fd1f32f,0xbf008d18 } }, + /* 67 */ + { { 0x4e8068db,0x8012aa24,0xa5729a47,0xc72cc641,0x43f0691d,0x3c33df2c, + 0x1d92145f,0xfa057347,0xb97f7946,0xaefc0f2f,0x2f8121bf,0x813d75cb }, + { 0x4383bba6,0x05613c72,0xa4224b3f,0xa924ce70,0x5f2179a6,0xe59cecbe, + 0x79f62b61,0x78e2e8aa,0x53ad8079,0x3ac2cc3b,0xd8f4fa96,0x55518d71 } }, + /* 68 */ + { { 0x00623f3b,0x03cf2922,0x5f29ebff,0x095c7111,0x80aa6823,0x42d72247, + 0x7458c0b0,0x044c7ba1,0x0959ec20,0xca62f7ef,0xf8ca929f,0x40ae2ab7 }, + { 0xa927b102,0xb8c5377a,0xdc031771,0x398a86a0,0xc216a406,0x04908f9d, + 0x918d3300,0xb423a73a,0xe0b94739,0x634b0ff1,0x2d69f697,0xe29de725 } }, + /* 69 */ + { { 0x8435af04,0x744d1400,0xfec192da,0x5f255b1d,0x336dc542,0x1f17dc12, + 0x636a68a8,0x5c90c2a7,0x7704ca1e,0x960c9eb7,0x6fb3d65a,0x9de8cf1e }, + { 0x511d3d06,0xc60fee0d,0xf9eb52c7,0x466e2313,0x206b0914,0x743c0f5f, + 0x2191aa4d,0x42f55bac,0xffebdbc2,0xcefc7c8f,0xe6e8ed1c,0xd4fa6081 } }, + /* 70 */ + { { 0xb0ab9645,0xb5e405d3,0xd5f1f711,0xaeec7f98,0x585c2a6e,0x8ad42311, + 0x512c6944,0x045acb9e,0xa90db1c6,0xae106c4e,0x898e6563,0xb89f33d5 }, + { 0x7fed2ce4,0x43b07cd9,0xdd815b20,0xf9934e17,0x0a81a349,0x6778d4d5, + 0x52918061,0x9e616ade,0xd7e67112,0xfa06db06,0x88488091,0x1da23cf1 } }, + /* 71 */ + { { 0x42f2c4b5,0x821c46b3,0x66059e47,0x931513ef,0x66f50cd1,0x7030ae43, + 0x43e7b127,0x43b536c9,0x5fca5360,0x006258cf,0x6b557abf,0xe4e3ee79 }, + { 0x24c8b22f,0xbb6b3900,0xfcbf1054,0x2eb5e2c1,0x567492af,0x937b18c9, + 0xacf53957,0xf09432e4,0x1dbf3a56,0x585f5a9d,0xbe0887cf,0xf86751fd } }, + /* 72 */ + { { 0x9d10e0b2,0x157399cb,0x60dc51b7,0x1c0d5956,0x1f583090,0x1d496b8a, + 0x88590484,0x6658bc26,0x03213f28,0x88c08ab7,0x7ae58de4,0x8d2e0f73 }, + { 0x486cfee6,0x9b79bc95,0xe9e5bc57,0x036a26c7,0xcd8ae97a,0x1ad03601, + 0xff3a0494,0x06907f87,0x2c7eb584,0x078f4bbf,0x7e8d0a5a,0xe3731bf5 } }, + /* 73 */ + { { 0xe1cd0abe,0x72f2282b,0x87efefa2,0xd4f9015e,0x6c3834bd,0x9d189806, + 0xb8a29ced,0x9c8cdcc1,0xfee82ebc,0x0601b9f4,0x7206a756,0x371052bc }, + { 0x46f32562,0x76fa1092,0x17351bb4,0xdaad534c,0xb3636bb5,0xc3d64c37, + 0x45d54e00,0x038a8c51,0x32c09e7c,0x301e6180,0x95735151,0x9764eae7 } }, + /* 74 */ + { { 0xcbd5256a,0x8791b19f,0x6ca13a3b,0x4007e0f2,0x4cf06904,0x03b79460, + 0xb6c17589,0xb18a9c22,0x81d45908,0xa1cb7d7d,0x21bb68f1,0x6e13fa9d }, + { 0xa71e6e16,0x47183c62,0xe18749ed,0x5cf0ef8e,0x2e5ed409,0x2c9c7f9b, + 0xe6e117e1,0x042eeacc,0x13fb5a7f,0xb86d4816,0xc9e5feb1,0xea1cf0ed } }, + /* 75 */ + { { 0xcea4cc9b,0x6e6573c9,0xafcec8f3,0x5417961d,0xa438b6f6,0x804bf02a, + 0xdcd4ea88,0xb894b03c,0x3799571f,0xd0f807e9,0x862156e8,0x3466a7f5 }, + { 0x56515664,0x51e59acd,0xa3c5eb0b,0x55b0f93c,0x6a4279db,0x84a06b02, + 0xc5fae08e,0x5c850579,0xa663a1a2,0xcf07b8db,0xf46ffc8d,0x49a36bbc } }, + /* 76 */ + { { 0x46d93106,0xe47f5acc,0xaa897c9c,0x65b7ade0,0x12d7e4be,0x37cf4c94, + 0xd4b2caa9,0xa2ae9b80,0xe60357a3,0x5e7ce09c,0xc8ecd5f9,0x29f77667 }, + { 0xa8a0b1c5,0xdf6868f5,0x62978ad8,0x240858cf,0xdc0002a1,0x0f7ac101, + 0xffe9aa05,0x1d28a9d7,0x5b962c97,0x744984d6,0x3d28c8b2,0xa8a7c00b } }, + /* 77 */ + { { 0xae11a338,0x7c58a852,0xd1af96e7,0xa78613f1,0x5355cc73,0x7e9767d2, + 0x792a2de6,0x6ba37009,0x124386b2,0x7d60f618,0x11157674,0xab09b531 }, + { 0x98eb9dd0,0x95a04841,0x15070328,0xe6c17acc,0x489c6e49,0xafc6da45, + 0xbb211530,0xab45a60a,0x7d7ea933,0xc58d6592,0x095642c6,0xa3ef3c65 } }, + /* 78 */ + { { 0xdf010879,0x89d420e9,0x39576179,0x9d25255d,0xe39513b6,0x9cdefd50, + 0xd5d1c313,0xe4efe45b,0x3f7af771,0xc0149de7,0x340ab06b,0x55a6b4f4 }, + { 0xebeaf771,0xf1325251,0x878d4288,0x2ab44128,0x18e05afe,0xfcd5832e, + 0xcc1fb62b,0xef52a348,0xc1c4792a,0x2bd08274,0x877c6dc7,0x345c5846 } }, + /* 79 */ + { { 0xbea65e90,0xde15ceb0,0x2416d99c,0x0987f72b,0xfd863dec,0x44db578d, + 0xac6a3578,0xf617b74b,0xdb48e999,0x9e62bd7a,0xeab1a1be,0x877cae61 }, + { 0x3a358610,0x23adddaa,0x325e2b07,0x2fc4d6d1,0x1585754e,0x897198f5, + 0xb392b584,0xf741852c,0xb55f7de1,0x9927804c,0x1aa8efae,0xe9e6c4ed } }, + /* 80 */ + { { 0x98683186,0x867db639,0xddcc4ea9,0xfb5cf424,0xd4f0e7bd,0xcc9a7ffe, + 0x7a779f7e,0x7c57f71c,0xd6b25ef2,0x90774079,0xb4081680,0x90eae903 }, + { 0x0ee1fceb,0xdf2aae5e,0xe86c1a1f,0x3ff1da24,0xca193edf,0x80f587d6, + 0xdc9b9d6a,0xa5695523,0x85920303,0x7b840900,0xba6dbdef,0x1efa4dfc } }, + /* 81 */ + { { 0xe0540015,0xfbd838f9,0xc39077dc,0x2c323946,0xad619124,0x8b1fb9e6, + 0x0ca62ea8,0x9612440c,0x2dbe00ff,0x9ad9b52c,0xae197643,0xf52abaa1 }, + { 0x2cac32ad,0xd0e89894,0x62a98f91,0xdfb79e42,0x276f55cb,0x65452ecf, + 0x7ad23e12,0xdb1ac0d2,0xde4986f0,0xf68c5f6a,0x82ce327d,0x389ac37b } }, + /* 82 */ + { { 0xf8e60f5b,0x511188b4,0x48aa2ada,0x7fe67015,0x381abca2,0xdb333cb8, + 0xdaf3fc97,0xb15e6d9d,0x36aabc03,0x4b24f6eb,0x72a748b4,0xc59789df }, + { 0x29cf5279,0x26fcb8a5,0x01ad9a6c,0x7a3c6bfc,0x4b8bac9b,0x866cf88d, + 0x9c80d041,0xf4c89989,0x70add148,0xf0a04241,0x45d81a41,0x5a02f479 } }, + /* 83 */ + { { 0xc1c90202,0xfa5c877c,0xf8ac7570,0xd099d440,0xd17881f7,0x428a5b1b, + 0x5b2501d7,0x61e267db,0xf2e4465b,0xf889bf04,0x76aa4cb8,0x4da3ae08 }, + { 0xe3e66861,0x3ef0fe26,0x3318b86d,0x5e772953,0x747396df,0xc3c35fbc, + 0x439ffd37,0x5115a29c,0xb2d70374,0xbfc4bd97,0x56246b9d,0x088630ea } }, + /* 84 */ + { { 0xb8a9e8c9,0xcd96866d,0x5bb8091e,0xa11963b8,0x045b3cd2,0xc7f90d53, + 0x80f36504,0x755a72b5,0x21d3751c,0x46f8b399,0x53c193de,0x4bffdc91 }, + { 0xb89554e7,0xcd15c049,0xf7a26be6,0x353c6754,0xbd41d970,0x79602370, + 0x12b176c0,0xde16470b,0x40c8809d,0x56ba1175,0xe435fb1e,0xe2db35c3 } }, + /* 85 */ + { { 0x6328e33f,0xd71e4aab,0xaf8136d1,0x5486782b,0x86d57231,0x07a4995f, + 0x1651a968,0xf1f0a5bd,0x76803b6d,0xa5dc5b24,0x42dda935,0x5c587cbc }, + { 0xbae8b4c0,0x2b6cdb32,0xb1331138,0x66d1598b,0x5d7e9614,0x4a23b2d2, + 0x74a8c05d,0x93e402a6,0xda7ce82e,0x45ac94e6,0xe463d465,0xeb9f8281 } }, + /* 86 */ + { { 0xfecf5b9b,0x34e0f9d1,0xf206966a,0xa115b12b,0x1eaa0534,0x5591cf3b, + 0xfb1558f9,0x5f0293cb,0x1bc703a5,0x1c8507a4,0x862c1f81,0x92e6b81c }, + { 0xcdaf24e3,0xcc9ebc66,0x72fcfc70,0x68917ecd,0x8157ba48,0x6dc9a930, + 0xb06ab2b2,0x5d425c08,0x36e929c4,0x362f8ce7,0x62e89324,0x09f6f57c } }, + /* 87 */ + { { 0xd29375fb,0x1c7d6b78,0xe35d1157,0xfabd851e,0x4243ea47,0xf6f62dcd, + 0x8fe30b0f,0x1dd92460,0xffc6e709,0x08166dfa,0x0881e6a7,0xc6c4c693 }, + { 0xd6a53fb0,0x20368f87,0x9eb4d1f9,0x38718e9f,0xafd7e790,0x03f08acd, + 0x72fe2a1c,0x0835eb44,0x88076e5d,0x7e050903,0xa638e731,0x538f765e } }, + /* 88 */ + { { 0xc2663b4b,0x0e0249d9,0x47cd38dd,0xe700ab5b,0x2c46559f,0xb192559d, + 0x4bcde66d,0x8f9f74a8,0x3e2aced5,0xad161523,0x3dd03a5b,0xc155c047 }, + { 0x3be454eb,0x346a8799,0x83b7dccd,0x66ee94db,0xab9d2abe,0x1f6d8378, + 0x7733f355,0x4a396dd2,0xf53553c2,0x419bd40a,0x731dd943,0xd0ead98d } }, + /* 89 */ + { { 0xec142408,0x908e0b0e,0x4114b310,0x98943cb9,0x1742b1d7,0x03dbf7d8, + 0x693412f4,0xd270df6b,0x8f69e20c,0xc5065494,0x697e43a1,0xa76a90c3 }, + { 0x4624825a,0xe0fa3384,0x8acc34c2,0x82e48c0b,0xe9a14f2b,0x7b24bd14, + 0x4db30803,0x4f5dd5e2,0x932da0a3,0x0c77a9e7,0x74c653dc,0x20db90f2 } }, + /* 90 */ + { { 0x0e6c5fd9,0x261179b7,0x6c982eea,0xf8bec123,0xd4957b7e,0x47683338, + 0x0a72f66a,0xcc47e664,0x1bad9350,0xbd54bf6a,0xf454e95a,0xdfbf4c6a }, + { 0x6907f4fa,0x3f7a7afa,0x865ca735,0x7311fae0,0x2a496ada,0x24737ab8, + 0x15feb79b,0x13e425f1,0xa1b93c21,0xe9e97c50,0x4ddd3eb5,0xb26b6eac } }, + /* 91 */ + { { 0x2a2e5f2b,0x81cab9f5,0xbf385ac4,0xf93caf29,0xc909963a,0xf4bf35c3, + 0x74c9143c,0x081e7300,0xc281b4c5,0x3ea57fa8,0x9b340741,0xe497905c }, + { 0x55ab3cfb,0xf556dd8a,0x518db6ad,0xd444b96b,0x5ef4b955,0x34f5425a, + 0xecd26aa3,0xdda7a3ac,0xda655e97,0xb57da11b,0xc2024c70,0x02da3eff } }, + /* 92 */ + { { 0x6481d0d9,0xe24b0036,0x818fdfe2,0x3740dbe5,0x190fda00,0xc1fc1f45, + 0x3cf27fde,0x329c9280,0x6934f43e,0x7435cb53,0x7884e8fe,0x2b505a5d }, + { 0x711adcc9,0x6cfcc6a6,0x531e21e1,0xf034325c,0x9b2a8a99,0xa2f4a967, + 0x3c21bdff,0x9d5f3842,0x31b57d66,0xb25c7811,0x0b8093b9,0xdb5344d8 } }, + /* 93 */ + { { 0xae50a2f5,0x0d72e667,0xe4a861d1,0x9b7f8d8a,0x330df1cb,0xa129f70f, + 0xe04fefc3,0xe90aa5d7,0xe72c3ae1,0xff561ecb,0xcdb955fa,0x0d8fb428 }, + { 0xd7663784,0xd2235f73,0x7e2c456a,0xc05baec6,0x2adbfccc,0xe5c292e4, + 0xefb110d5,0x4fd17988,0xd19d49f3,0x27e57734,0x84f679fe,0x188ac4ce } }, + /* 94 */ + { { 0xa796c53e,0x7ee344cf,0x0868009b,0xbbf6074d,0x474a1295,0x1f1594f7, + 0xac11632d,0x66776edc,0x04e2fa5a,0x1862278b,0xc854a89a,0x52665cf2 }, + { 0x8104ab58,0x7e376464,0x7204fd6d,0x16775913,0x44ea1199,0x86ca06a5, + 0x1c9240dd,0xaa3f765b,0x24746149,0x5f8501a9,0xdcd251d7,0x7b982e30 } }, + /* 95 */ + { { 0xc15f3060,0xe44e9efc,0xa87ebbe6,0x5ad62f2e,0xc79500d4,0x36499d41, + 0x336fa9d1,0xa66d6dc0,0x5afd3b1f,0xf8afc495,0xe5c9822b,0x1d8ccb24 }, + { 0x79d7584b,0x4031422b,0xea3f20dd,0xc54a0580,0x958468c5,0x3f837c8f, + 0xfbea7735,0x3d82f110,0x7dffe2fc,0x679a8778,0x20704803,0x48eba63b } }, + /* 96 */ + { { 0xdf46e2f6,0x89b10d41,0x19514367,0x13ab57f8,0x1d469c87,0x067372b9, + 0x4f6c5798,0x0c195afa,0x272c9acf,0xea43a12a,0x678abdac,0x9dadd8cb }, + { 0xe182579a,0xcce56c6b,0x2d26c2d8,0x86febadb,0x2a44745c,0x1c668ee1, + 0x98dc047a,0x580acd86,0x51b9ec2d,0x5a2b79cc,0x4054f6a0,0x007da608 } }, + /* 97 */ + { { 0x17b00dd0,0x9e3ca352,0x0e81a7a6,0x046779cb,0xd482d871,0xb999fef3, + 0xd9233fbc,0xe6f38134,0xf48cd0e0,0x112c3001,0x3c6c66ae,0x934e7576 }, + { 0xd73234dc,0xb44d4fc3,0x864eafc1,0xfcae2062,0x26bef21a,0x843afe25, + 0xf3b75fdf,0x61355107,0x794c2e6b,0x8367a5aa,0x8548a372,0x3d2629b1 } }, + /* 98 */ + { { 0x437cfaf8,0x6230618f,0x2032c299,0x5b8742cb,0x2293643a,0x949f7247, + 0x09464f79,0xb8040f1a,0x4f254143,0x049462d2,0x366c7e76,0xabd6b522 }, + { 0xd5338f55,0x119b392b,0x01495a0c,0x1a80a9ce,0xf8d7537e,0xf3118ca7, + 0x6bf4b762,0xb715adc2,0xa8482b6c,0x24506165,0x96a7c84d,0xd958d7c6 } }, + /* 99 */ + { { 0xbdc21f31,0x9ad8aa87,0x8063e58c,0xadb3cab4,0xb07dd7b8,0xefd86283, + 0x1be7c6b4,0xc7b9b762,0x015582de,0x2ef58741,0x299addf3,0xc970c52e }, + { 0x22f24d66,0x78f02e2a,0x74cc100a,0xefec1d10,0x09316e1a,0xaf2a6a39, + 0x5849dd49,0xce7c2205,0x96bffc4c,0x9c1fe75c,0x7ba06ec0,0xcad98fd2 } }, + /* 100 */ + { { 0xb648b73e,0xed76e2d0,0x1cfd285e,0xa9f92ce5,0x2ed13de1,0xa8c86c06, + 0xa5191a93,0x1d3a574e,0x1ad1b8bf,0x385cdf8b,0x47d2cfe3,0xbbecc28a }, + { 0x69cec548,0x98d326c0,0xf240a0b2,0x4f5bc1dd,0x29057236,0x241a7062, + 0xc68294a4,0x0fc6e9c5,0xa319f17a,0x4d04838b,0x9ffc1c6f,0x8b612cf1 } }, + /* 101 */ + { { 0x4c3830eb,0x9bb0b501,0x8ee0d0c5,0x3d08f83c,0x79ba9389,0xa4a62642, + 0x9cbc2914,0x5d5d4044,0x074c46f0,0xae9eb83e,0x74ead7d6,0x63bb758f }, + { 0xc6bb29e0,0x1c40d2ea,0x4b02f41e,0x95aa2d87,0x53cb199a,0x92989175, + 0x51584f6d,0xdd91bafe,0x31a1aaec,0x3715efb9,0x46780f9e,0xc1b6ae5b } }, + /* 102 */ + { { 0x42772f41,0xcded3e4b,0x3bcb79d1,0x3a700d5d,0x80feee60,0x4430d50e, + 0xf5e5d4bb,0x444ef1fc,0xe6e358ff,0xc660194f,0x6a91b43c,0xe68a2f32 }, + { 0x977fe4d2,0x5842775c,0x7e2a41eb,0x78fdef5c,0xff8df00e,0x5f3bec02, + 0x5852525d,0xf4b840cd,0x4e6988bd,0x0870483a,0xcc64b837,0x39499e39 } }, + /* 103 */ + { { 0xb08df5fe,0xfc05de80,0x63ba0362,0x0c12957c,0xd5cf1428,0xea379414, + 0x54ef6216,0xc559132a,0xb9e65cf8,0x33d5f12f,0x1695d663,0x09c60278 }, + { 0x61f7a2fb,0x3ac1ced4,0xd4f5eeb8,0xdd838444,0x8318fcad,0x82a38c6c, + 0xe9f1a864,0x315be2e5,0x442daf47,0x317b5771,0x95aa5f9e,0x81b5904a } }, + /* 104 */ + { { 0x8b21d232,0x6b6b1c50,0x8c2cba75,0x87f3dbc0,0xae9f0faf,0xa7e74b46, + 0xbb7b8079,0x036a0985,0x8d974a25,0x4f185b90,0xd9af5ec9,0x5aa7cef0 }, + { 0x57dcfffc,0xe0566a70,0xb8453225,0x6ea311da,0x23368aa9,0x72ea1a8d, + 0x48cd552d,0xed9b2083,0xc80ea435,0xb987967c,0x6c104173,0xad735c75 } }, + /* 105 */ + { { 0xcee76ef4,0xaea85ab3,0xaf1d2b93,0x44997444,0xeacb923f,0x0851929b, + 0x51e3bc0c,0xb080b590,0x59be68a2,0xc4ee1d86,0x64b26cda,0xf00de219 }, + { 0xf2e90d4d,0x8d7fb5c0,0x77d9ec64,0x00e219a7,0x5d1c491c,0xc4e6febd, + 0x1a8f4585,0x080e3754,0x48d2af9c,0x4a9b86c8,0xb6679851,0x2ed70db6 } }, + /* 106 */ + { { 0x586f25cb,0xaee44116,0xa0fcf70f,0xf7b6861f,0x18a350e8,0x55d2cd20, + 0x92dc286f,0x861bf3e5,0x6226aba7,0x9ab18ffa,0xa9857b03,0xd15827be }, + { 0x92e6acef,0x26c1f547,0xac1fbac3,0x422c63c8,0xfcbfd71d,0xa2d8760d, + 0xb2511224,0x35f6a539,0x048d1a21,0xbaa88fa1,0xebf999db,0x49f1abe9 } }, + /* 107 */ + { { 0xf7492b73,0x16f9f4f4,0xcb392b1a,0xcf28ec1e,0x69ca6ffc,0x45b130d4, + 0xb72efa58,0x28ba8d40,0x5ca066f5,0xace987c7,0x4ad022eb,0x3e399246 }, + { 0x752555bb,0x63a2d84e,0x9c2ae394,0xaaa93b4a,0xc89539ca,0xcd80424e, + 0xaa119a99,0x6d6b5a6d,0x379f2629,0xbd50334c,0xef3cc7d3,0x899e925e } }, + /* 108 */ + { { 0xbf825dc4,0xb7ff3651,0x40b9c462,0x0f741cc4,0x5cc4fb5b,0x771ff5a9, + 0x47fd56fe,0xcb9e9c9b,0x5626c0d3,0xbdf053db,0xf7e14098,0xa97ce675 }, + { 0x6c934f5e,0x68afe5a3,0xccefc46f,0x6cd5e148,0xd7a88586,0xc7758570, + 0xdd558d40,0x49978f5e,0x64ae00c1,0xa1d5088a,0xf1d65bb2,0x58f2a720 } }, + /* 109 */ + { { 0x3e4daedb,0x66fdda4a,0x65d1b052,0x38318c12,0x4c4bbf5c,0x28d910a2, + 0x78a9cd14,0x762fe5c4,0xd2cc0aee,0x08e5ebaa,0xca0c654c,0xd2cdf257 }, + { 0x08b717d2,0x48f7c58b,0x386cd07a,0x3807184a,0xae7d0112,0x3240f626, + 0xc43917b0,0x03e9361b,0x20aea018,0xf261a876,0x7e1e6372,0x53f556a4 } }, + /* 110 */ + { { 0x2f512a90,0xc84cee56,0x1b0ea9f1,0x24b3c004,0xe26cc1ea,0x0ee15d2d, + 0xf0c9ef7d,0xd848762c,0xd5341435,0x1026e9c5,0xfdb16b31,0x8f5b73dc }, + { 0xd2c75d95,0x1f69bef2,0xbe064dda,0x8d33d581,0x57ed35e6,0x8c024c12, + 0xc309c281,0xf8d435f9,0xd6960193,0xfd295061,0xe9e49541,0x66618d78 } }, + /* 111 */ + { { 0x8ce382de,0x571cfd45,0xde900dde,0x175806ee,0x34aba3b5,0x61849965, + 0xde7aec95,0xe899778a,0xff4aa97f,0xe8f00f6e,0x010b0c6d,0xae971cb5 }, + { 0x3af788f1,0x1827eebc,0xe413fe2d,0xd46229ff,0x4741c9b4,0x8a15455b, + 0xf8e424eb,0x5f02e690,0xdae87712,0x40a1202e,0x64944f6d,0x49b3bda2 } }, + /* 112 */ + { { 0x035b2d69,0xd63c6067,0x6bed91b0,0xb507150d,0x7afb39b2,0x1f35f82f, + 0x16012b66,0xb9bd9c01,0xed0a5f50,0x00d97960,0x2716f7c9,0xed705451 }, + { 0x127abdb4,0x1576eff4,0xf01e701c,0x6850d698,0x3fc87e2f,0x9fa7d749, + 0xb0ce3e48,0x0b6bcc6f,0xf7d8c1c0,0xf4fbe1f5,0x02719cc6,0xcf75230e } }, + /* 113 */ + { { 0x722d94ed,0x6761d6c2,0x3718820e,0xd1ec3f21,0x25d0e7c6,0x65a40b70, + 0xbaf3cf31,0xd67f830e,0xb93ea430,0x633b3807,0x0bc96c69,0x17faa0ea }, + { 0xdf866b98,0xe6bf3482,0xa9db52d4,0x205c1ee9,0xff9ab869,0x51ef9bbd, + 0x75eeb985,0x3863dad1,0xd3cf442a,0xef216c3b,0xf9c8e321,0x3fb228e3 } }, + /* 114 */ + { { 0x0760ac07,0x94f9b70c,0x9d79bf4d,0xf3c9ccae,0xc5ffc83d,0x73cea084, + 0xdc49c38e,0xef50f943,0xbc9e7330,0xf467a2ae,0x44ea7fba,0x5ee534b6 }, + { 0x03609e7f,0x20cb6272,0x62fdc9f0,0x09844355,0x0f1457f7,0xaf5c8e58, + 0xb4b25941,0xd1f50a6c,0x2ec82395,0x77cb247c,0xda3dca33,0xa5f3e1e5 } }, + /* 115 */ + { { 0x7d85fa94,0x023489d6,0x2db9ce47,0x0ba40537,0xaed7aad1,0x0fdf7a1f, + 0x9a4ccb40,0xa57b0d73,0x5b18967c,0x48fcec99,0xb7274d24,0xf30b5b6e }, + { 0xc81c5338,0x7ccb4773,0xa3ed6bd0,0xb85639e6,0x1d56eada,0x7d9df95f, + 0x0a1607ad,0xe256d57f,0x957574d6,0x6da7ffdc,0x01c7a8c4,0x65f84046 } }, + /* 116 */ + { { 0xcba1e7f1,0x8d45d0cb,0x02b55f64,0xef0a08c0,0x17e19892,0x771ca31b, + 0x4885907e,0xe1843ecb,0x364ce16a,0x67797ebc,0x8df4b338,0x816d2b2d }, + { 0x39aa8671,0xe870b0e5,0xc102b5f5,0x9f0db3e4,0x1720c697,0x34296659, + 0x613c0d2a,0x0ad4c89e,0x418ddd61,0x1af900b2,0xd336e20e,0xe087ca72 } }, + /* 117 */ + { { 0xaba10079,0x222831ff,0x6d64fff2,0x0dc5f87b,0x3e8cb330,0x44547907, + 0x702a33fb,0xe815aaa2,0x5fba3215,0x338d6b2e,0x79f549c8,0x0f7535cb }, + { 0x2ee95923,0x471ecd97,0xc6d1c09f,0x1e868b37,0xc666ef4e,0x2bc7b8ec, + 0x808a4bfc,0xf5416589,0x3fbc4d2e,0xf23e9ee2,0x2d75125b,0x4357236c } }, + /* 118 */ + { { 0xba9cdb1b,0xfe176d95,0x2f82791e,0x45a1ca01,0x4de4cca2,0x97654af2, + 0x5cc4bcb9,0xbdbf9d0e,0xad97ac0a,0xf6a7df50,0x61359fd6,0xc52112b0 }, + { 0x4f05eae3,0x696d9ce3,0xe943ac2b,0x903adc02,0x0848be17,0xa9075347, + 0x2a3973e5,0x1e20f170,0x6feb67e9,0xe1aacc1c,0xe16bc6b9,0x2ca0ac32 } }, + /* 119 */ + { { 0xef871eb5,0xffea12e4,0xa8bf0a7a,0x94c2f25d,0x78134eaa,0x4d1e4c2a, + 0x0360fb10,0x11ed16fb,0x85fc11be,0x4029b6db,0xf4d390fa,0x5e9f7ab7 }, + { 0x30646612,0x5076d72f,0xdda1d0d8,0xa0afed1d,0x85a1d103,0x29022257, + 0x4e276bcd,0xcb499e17,0x51246c3d,0x16d1da71,0x589a0443,0xc72d56d3 } }, + /* 120 */ + { { 0xdae5bb45,0xdf5ffc74,0x261bd6dc,0x99068c4a,0xaa98ec7b,0xdc0afa7a, + 0xf121e96d,0xedd2ee00,0x1414045c,0x163cc7be,0x335af50e,0xb0b1bbce }, + { 0x01a06293,0xd440d785,0x6552e644,0xcdebab7c,0x8c757e46,0x48cb8dbc, + 0x3cabe3cb,0x81f9cf78,0xb123f59a,0xddd02611,0xeeb3784d,0x3dc7b88e } }, + /* 121 */ + { { 0xc4741456,0xe1b8d398,0x6032a121,0xa9dfa902,0x1263245b,0x1cbfc86d, + 0x5244718c,0xf411c762,0x05b0fc54,0x96521d54,0xdbaa4985,0x1afab46e }, + { 0x8674b4ad,0xa75902ba,0x5ad87d12,0x486b43ad,0x36e0d099,0x72b1c736, + 0xbb6cd6d6,0x39890e07,0x59bace4e,0x8128999c,0x7b535e33,0xd8da430b } }, + /* 122 */ + { { 0xc6b75791,0x39f65642,0x21806bfb,0x050947a6,0x1362ef84,0x0ca3e370, + 0x8c3d2391,0x9bc60aed,0x732e1ddc,0x9b488671,0xa98ee077,0x12d10d9e }, + { 0x3651b7dc,0xb6f2822d,0x80abd138,0x6345a5ba,0x472d3c84,0x62033262, + 0xacc57527,0xd54a1d40,0x424447cb,0x6ea46b3a,0x2fb1a496,0x5bc41057 } }, + /* 123 */ + { { 0xa751cd0e,0xe70c57a3,0xeba3c7d6,0x190d8419,0x9d47d55a,0xb1c3bee7, + 0xf912c6d8,0xda941266,0x407a6ad6,0x12e9aacc,0x6e838911,0xd6ce5f11 }, + { 0x70e1f2ce,0x063ca97b,0x8213d434,0xa3e47c72,0x84df810a,0xa016e241, + 0xdfd881a4,0x688ad7b0,0xa89bf0ad,0xa37d99fc,0xa23c2d23,0xd8e3f339 } }, + /* 124 */ + { { 0x750bed6f,0xbdf53163,0x83e68b0a,0x808abc32,0x5bb08a33,0x85a36627, + 0x6b0e4abe,0xf72a3a0f,0xfaf0c6ad,0xf7716d19,0x5379b25f,0x22dcc020 }, + { 0xf9a56e11,0x7400bf8d,0x56a47f21,0x6cb8bad7,0x7a6eb644,0x7c97176f, + 0xd1f5b646,0xe8fd84f7,0x44ddb054,0x98320a94,0x1dde86f5,0x07071ba3 } }, + /* 125 */ + { { 0x98f8fcb9,0x6fdfa0e5,0x94d0d70c,0x89cec8e0,0x106d20a8,0xa0899397, + 0xba8acc9c,0x915bfb9a,0x5507e01c,0x1370c94b,0x8a821ffb,0x83246a60 }, + { 0xbe3c378f,0xa8273a9f,0x35a25be9,0x7e544789,0x4dd929d7,0x6cfa4972, + 0x365bd878,0x987fed9d,0x5c29a7ae,0x4982ac94,0x5ddd7ec5,0x4589a5d7 } }, + /* 126 */ + { { 0xa95540a9,0x9fabb174,0x0162c5b0,0x7cfb886f,0xea3dee18,0x17be766b, + 0xe88e624c,0xff7da41f,0x8b919c38,0xad0b71eb,0xf31ff9a9,0x86a522e0 }, + { 0x868bc259,0xbc8e6f72,0x3ccef9e4,0x6130c638,0x9a466555,0x09f1f454, + 0x19b2bfb4,0x8e6c0f09,0x0ca7bb22,0x945c46c9,0x4dafb67b,0xacd87168 } }, + /* 127 */ + { { 0x10c53841,0x090c72ca,0x55a4fced,0xc20ae01b,0xe10234ad,0x03f7ebd5, + 0x85892064,0xb3f42a6a,0xb4a14722,0xbdbc30c0,0x8ca124cc,0x971bc437 }, + { 0x517ff2ff,0x6f79f46d,0xecba947b,0x6a9c96e2,0x62925122,0x5e79f2f4, + 0x6a4e91f1,0x30a96bb1,0x2d4c72da,0x1147c923,0x5811e4df,0x65bc311f } }, + /* 128 */ + { { 0x139b3239,0x87c7dd7d,0x4d833bae,0x8b57824e,0x9fff0015,0xbcbc4878, + 0x909eaf1a,0x8ffcef8b,0xf1443a78,0x9905f4ee,0xe15cbfed,0x020dd4a2 }, + { 0xa306d695,0xca2969ec,0xb93caf60,0xdf940cad,0x87ea6e39,0x67f7fab7, + 0xf98c4fe5,0x0d0ee10f,0xc19cb91e,0xc646879a,0x7d1d7ab4,0x4b4ea50c } }, + /* 129 */ + { { 0x7a0db57e,0x19e40945,0x9a8c9702,0xe6017cad,0x1be5cff9,0xdbf739e5, + 0xa7a938a2,0x3646b3cd,0x68350dfc,0x04511085,0x56e098b5,0xad3bd6f3 }, + { 0xee2e3e3e,0x935ebabf,0x473926cb,0xfbd01702,0x9e9fb5aa,0x7c735b02, + 0x2e3feff0,0xc52a1b85,0x046b405a,0x9199abd3,0x39039971,0xe306fcec } }, + /* 130 */ + { { 0x23e4712c,0xd6d9aec8,0xc3c198ee,0x7ca8376c,0x31bebd8a,0xe6d83187, + 0xd88bfef3,0xed57aff3,0xcf44edc7,0x72a645ee,0x5cbb1517,0xd4e63d0b }, + { 0xceee0ecf,0x98ce7a1c,0x5383ee8e,0x8f012633,0xa6b455e8,0x3b879078, + 0xc7658c06,0xcbcd3d96,0x0783336a,0x721d6fe7,0x5a677136,0xf21a7263 } }, + /* 131 */ + { { 0x9586ba11,0x19d8b3cd,0x8a5c0480,0xd9e0aeb2,0x2230ef5c,0xe4261dbf, + 0x02e6bf09,0x095a9dee,0x80dc7784,0x8963723c,0x145157b1,0x5c97dbaf }, + { 0x4bc4503e,0x97e74434,0x85a6b370,0x0fb1cb31,0xcd205d4b,0x3e8df2be, + 0xf8f765da,0x497dd1bc,0x6c988a1a,0x92ef95c7,0x64dc4cfa,0x3f924baa } }, + /* 132 */ + { { 0x7268b448,0x6bf1b8dd,0xefd79b94,0xd4c28ba1,0xe4e3551f,0x2fa1f8c8, + 0x5c9187a9,0x769e3ad4,0x40326c0d,0x28843b4d,0x50d5d669,0xfefc8094 }, + { 0x90339366,0x30c85bfd,0x5ccf6c3a,0x4eeb56f1,0x28ccd1dc,0x0e72b149, + 0xf2ce978e,0x73ee85b5,0x3165bb23,0xcdeb2bf3,0x4e410abf,0x8106c923 } }, + /* 133 */ + { { 0x7d02f4ee,0xc8df0161,0x18e21225,0x8a781547,0x6acf9e40,0x4ea895eb, + 0x6e5a633d,0x8b000cb5,0x7e981ffb,0xf31d86d5,0x4475bc32,0xf5c8029c }, + { 0x1b568973,0x764561ce,0xa62996ec,0x2f809b81,0xda085408,0x9e513d64, + 0xe61ce309,0xc27d815d,0x272999e0,0x0da6ff99,0xfead73f7,0xbd284779 } }, + /* 134 */ + { { 0x9b1cdf2b,0x6033c2f9,0xbc5fa151,0x2a99cf06,0x12177b3b,0x7d27d259, + 0xc4485483,0xb1f15273,0x102e2297,0x5fd57d81,0xc7f6acb7,0x3d43e017 }, + { 0x3a70eb28,0x41a8bb0b,0x3e80b06b,0x67de2d8e,0x70c28de5,0x09245a41, + 0xa7b26023,0xad7dbcb1,0x2cbc6c1e,0x70b08a35,0x9b33041f,0xb504fb66 } }, + /* 135 */ + { { 0xf97a27c2,0xa8e85ab5,0xc10a011b,0x6ac5ec8b,0xffbcf161,0x55745533, + 0x65790a60,0x01780e85,0x99ee75b0,0xe451bf85,0x39c29881,0x8907a63b }, + { 0x260189ed,0x76d46738,0x47bd35cb,0x284a4436,0x20cab61e,0xd74e8c40, + 0x416cf20a,0x6264bf8c,0x5fd820ce,0xfa5a6c95,0xf24bb5fc,0xfa7154d0 } }, + /* 136 */ + { { 0x9b3f5034,0x18482cec,0xcd9e68fd,0x962d445a,0x95746f23,0x266fb1d6, + 0x58c94a4b,0xc66ade5a,0xed68a5b6,0xdbbda826,0x7ab0d6ae,0x05664a4d }, + { 0x025e32fc,0xbcd4fe51,0xa96df252,0x61a5aebf,0x31592a31,0xd88a07e2, + 0x98905517,0x5d9d94de,0x5fd440e7,0x96bb4010,0xe807db4c,0x1b0c47a2 } }, + /* 137 */ + { { 0x08223878,0x5c2a6ac8,0xe65a5558,0xba08c269,0x9bbc27fd,0xd22b1b9b, + 0x72b9607d,0x919171bf,0xe588dc58,0x9ab455f9,0x23662d93,0x6d54916e }, + { 0x3b1de0c1,0x8da8e938,0x804f278f,0xa84d186a,0xd3461695,0xbf4988cc, + 0xe10eb0cb,0xf5eae3be,0xbf2a66ed,0x1ff8b68f,0xc305b570,0xa68daf67 } }, + /* 138 */ + { { 0x44b2e045,0xc1004cff,0x4b1c05d4,0x91b5e136,0x88a48a07,0x53ae4090, + 0xea11bb1a,0x73fb2995,0x3d93a4ea,0x32048570,0x3bfc8a5f,0xcce45de8 }, + { 0xc2b3106e,0xaff4a97e,0xb6848b4f,0x9069c630,0xed76241c,0xeda837a6, + 0x6cc3f6cf,0x8a0daf13,0x3da018a8,0x199d049d,0xd9093ba3,0xf867c6b1 } }, + /* 139 */ + { { 0x56527296,0xe4d42a56,0xce71178d,0xae26c73d,0x6c251664,0x70a0adac, + 0x5dc0ae1d,0x813483ae,0xdaab2daf,0x7574eacd,0xc2d55f4f,0xc56b52dc }, + { 0x95f32923,0x872bc167,0x5bdd2a89,0x4be17581,0xa7699f00,0x9b57f1e7, + 0x3ac2de02,0x5fcd9c72,0x92377739,0x83af3ba1,0xfc50b97f,0xa64d4e2b } }, + /* 140 */ + { { 0x0e552b40,0x2172dae2,0xd34d52e8,0x62f49725,0x07958f98,0x7930ee40, + 0x751fdd74,0x56da2a90,0xf53e48c3,0xf1192834,0x8e53c343,0x34d2ac26 }, + { 0x13111286,0x1073c218,0xda9d9827,0x201dac14,0xee95d378,0xec2c29db, + 0x1f3ee0b1,0x9316f119,0x544ce71c,0x7890c9f0,0x27612127,0xd77138af } }, + /* 141 */ + { { 0x3b4ad1cd,0x78045e6d,0x4aa49bc1,0xcd86b94e,0xfd677a16,0x57e51f1d, + 0xfa613697,0xd9290935,0x34f4d893,0x7a3f9593,0x5d5fcf9b,0x8c9c248b }, + { 0x6f70d4e9,0x9f23a482,0x63190ae9,0x17273454,0x5b081a48,0x4bdd7c13, + 0x28d65271,0x1e2de389,0xe5841d1f,0x0bbaaa25,0x746772e5,0xc4c18a79 } }, + /* 142 */ + { { 0x593375ac,0x10ee2681,0x7dd5e113,0x4f3288be,0x240f3538,0x9a97b2fb, + 0x1de6b1e2,0xfa11089f,0x1351bc58,0x516da562,0x2dfa85b5,0x573b6119 }, + { 0x6cba7df5,0x89e96683,0x8c28ab40,0xf299be15,0xad43fcbf,0xe91c9348, + 0x9a1cefb3,0xe9bbc7cc,0x738b2775,0xc8add876,0x775eaa01,0x6e3b1f2e } }, + /* 143 */ + { { 0xb677788b,0x0365a888,0x3fd6173c,0x634ae8c4,0x9e498dbe,0x30498761, + 0xc8f779ab,0x08c43e6d,0x4c09aca9,0x068ae384,0x2018d170,0x2380c70b }, + { 0xa297c5ec,0xcf77fbc3,0xca457948,0xdacbc853,0x336bec7e,0x3690de04, + 0x14eec461,0x26bbac64,0x1f713abf,0xd1c23c7e,0xe6fd569e,0xf08bbfcd } }, + /* 144 */ + { { 0x84770ee3,0x5f8163f4,0x744a1706,0x0e0c7f94,0xe1b2d46d,0x9c8f05f7, + 0xd01fd99a,0x417eafe7,0x11440e5b,0x2ba15df5,0x91a6fbcf,0xdc5c552a }, + { 0xa270f721,0x86271d74,0xa004485b,0x32c0a075,0x8defa075,0x9d1a87e3, + 0xbf0d20fe,0xb590a7ac,0x8feda1f5,0x430c41c2,0x58f6ec24,0x454d2879 } }, + /* 145 */ + { { 0x7c525435,0x52b7a635,0x37c4bdbc,0x3d9ef57f,0xdffcc475,0x2bb93e9e, + 0x7710f3be,0xf7b8ba98,0x21b727de,0x42ee86da,0x2e490d01,0x55ac3f19 }, + { 0xc0c1c390,0x487e3a6e,0x446cde7b,0x036fb345,0x496ae951,0x089eb276, + 0x71ed1234,0xedfed4d9,0x900f0b46,0x661b0dd5,0x8582f0d3,0x11bd6f1b } }, + /* 146 */ + { { 0x076bc9d1,0x5cf9350f,0xcf3cd2c3,0x15d903be,0x25af031c,0x21cfc8c2, + 0x8b1cc657,0xe0ad3248,0x70014e87,0xdd9fb963,0x297f1658,0xf0f3a5a1 }, + { 0xf1f703aa,0xbb908fba,0x2f6760ba,0x2f9cc420,0x66a38b51,0x00ceec66, + 0x05d645da,0x4deda330,0xf7de3394,0xb9cf5c72,0x1ad4c906,0xaeef6502 } }, + /* 147 */ + { { 0x7a19045d,0x0583c8b1,0xd052824c,0xae7c3102,0xff6cfa58,0x2a234979, + 0x62c733c0,0xfe9dffc9,0x9c0c4b09,0x3a7fa250,0x4fe21805,0x516437bb }, + { 0xc2a23ddb,0x9454e3d5,0x289c104e,0x0726d887,0x4fd15243,0x8977d918, + 0x6d7790ba,0xc559e73f,0x465af85f,0x8fd3e87d,0x5feee46b,0xa2615c74 } }, + /* 148 */ + { { 0x4335167d,0xc8d607a8,0xe0f5c887,0x8b42d804,0x398d11f9,0x5f9f13df, + 0x20740c67,0x5aaa5087,0xa3d9234b,0x83da9a6a,0x2a54bad1,0xbd3a5c4e }, + { 0x2db0f658,0xdd13914c,0x5a3f373a,0x29dcb66e,0x5245a72b,0xbfd62df5, + 0x91e40847,0x19d18023,0xb136b1ae,0xd9df74db,0x3f93bc5b,0x72a06b6b } }, + /* 149 */ + { { 0xad19d96f,0x6da19ec3,0xfb2a4099,0xb342daa4,0x662271ea,0x0e61633a, + 0xce8c054b,0x3bcece81,0x8bd62dc6,0x7cc8e061,0xee578d8b,0xae189e19 }, + { 0xdced1eed,0x73e7a25d,0x7875d3ab,0xc1257f0a,0x1cfef026,0x2cb2d5a2, + 0xb1fdf61c,0xd98ef39b,0x24e83e6c,0xcd8e6f69,0xc7b7088b,0xd71e7076 } }, + /* 150 */ + { { 0x9d4245bf,0x33936830,0x2ac2953b,0x22d96217,0x56c3c3cd,0xb3bf5a82, + 0x0d0699e8,0x50c9be91,0x8f366459,0xec094463,0x513b7c35,0x6c056dba }, + { 0x045ab0e3,0x687a6a83,0x445c9295,0x8d40b57f,0xa16f5954,0x0f345048, + 0x3d8f0a87,0x64b5c639,0x9f71c5e2,0x106353a2,0x874f0dd4,0xdd58b475 } }, + /* 151 */ + { { 0x62230c72,0x67ec084f,0x481385e3,0xf14f6cca,0x4cda7774,0xf58bb407, + 0xaa2dbb6b,0xe15011b1,0x0c035ab1,0xd488369d,0x8245f2fd,0xef83c24a }, + { 0x9fdc2538,0xfb57328f,0x191fe46a,0x79808293,0x32ede548,0xe28f5c44, + 0xea1a022c,0x1b3cda99,0x3df2ec7f,0x39e639b7,0x760e9a18,0x77b6272b } }, + /* 152 */ + { { 0xa65d56d5,0x2b1d51bd,0x7ea696e0,0x3a9b71f9,0x9904f4c4,0x95250ecc, + 0xe75774b7,0x8bc4d6eb,0xeaeeb9aa,0x0e343f8a,0x930e04cb,0xc473c1d1 }, + { 0x064cd8ae,0x282321b1,0x5562221c,0xf4b4371e,0xd1bf1221,0xc1cc81ec, + 0xe2c8082f,0xa52a07a9,0xba64a958,0x350d8e59,0x6fb32c9a,0x29e4f3de } }, + /* 153 */ + { { 0xba89aaa5,0x0aa9d56c,0xc4c6059e,0xf0208ac0,0xbd6ddca4,0x7400d9c6, + 0xf2c2f74a,0xb384e475,0xb1562dd3,0x4c1061fc,0x2e153b8d,0x3924e248 }, + { 0x849808ab,0xf38b8d98,0xa491aa36,0x29bf3260,0x88220ede,0x85159ada, + 0xbe5bc422,0x8b47915b,0xd7300967,0xa934d72e,0x2e515d0d,0xc4f30398 } }, + /* 154 */ + { { 0x1b1de38b,0xe3e9ee42,0x42636760,0xa124e25a,0x90165b1a,0x90bf73c0, + 0x146434c5,0x21802a34,0x2e1fa109,0x54aa83f2,0xed9c51e9,0x1d4bd03c }, + { 0x798751e6,0xc2d96a38,0x8c3507f5,0xed27235f,0xc8c24f88,0xb5fb80e2, + 0xd37f4f78,0xf873eefa,0xf224ba96,0x7229fd74,0x9edd7149,0x9dcd9199 } }, + /* 155 */ + { { 0x4e94f22a,0xee9f81a6,0xf71ec341,0xe5609892,0xa998284e,0x6c818ddd, + 0x3b54b098,0x9fd47295,0x0e8a7cc9,0x47a6ac03,0xb207a382,0xde684e5e }, + { 0x2b6b956b,0x4bdd1ecd,0xf01b3583,0x09084414,0x55233b14,0xe2f80b32, + 0xef5ebc5e,0x5a0fec54,0xbf8b29a2,0x74cf25e6,0x7f29e014,0x1c757fa0 } }, + /* 156 */ + { { 0xeb0fdfe4,0x1bcb5c4a,0xf0899367,0xd7c649b3,0x05bc083b,0xaef68e3f, + 0xa78aa607,0x57a06e46,0x21223a44,0xa2136ecc,0x52f5a50b,0x89bd6484 }, + { 0x4455f15a,0x724411b9,0x08a9c0fd,0x23dfa970,0x6db63bef,0x7b0da4d1, + 0xfb162443,0x6f8a7ec1,0xe98284fb,0xc1ac9cee,0x33566022,0x085a582b } }, + /* 157 */ + { { 0xec1f138a,0x15cb61f9,0x668f0c28,0x11c9a230,0xdf93f38f,0xac829729, + 0x4048848d,0xcef25698,0x2bba8fbf,0x3f686da0,0x111c619a,0xed5fea78 }, + { 0xd6d1c833,0x9b4f73bc,0x86e7bf80,0x50951606,0x042b1d51,0xa2a73508, + 0x5fb89ec2,0x9ef6ea49,0x5ef8b892,0xf1008ce9,0x9ae8568b,0x78a7e684 } }, + /* 158 */ + { { 0x10470cd8,0x3fe83a7c,0xf86df000,0x92734682,0xda9409b5,0xb5dac06b, + 0x94939c5f,0x1e7a9660,0x5cc116dc,0xdec6c150,0x66bac8cc,0x1a52b408 }, + { 0x6e864045,0x5303a365,0x9139efc1,0x45eae72a,0x6f31d54f,0x83bec646, + 0x6e958a6d,0x2fb4a86f,0x4ff44030,0x6760718e,0xe91ae0df,0x008117e3 } }, + /* 159 */ + { { 0x384310a2,0x5d5833ba,0x1fd6c9fc,0xbdfb4edc,0x849c4fb8,0xb9a4f102, + 0x581c1e1f,0xe5fb239a,0xd0a9746d,0xba44b2e7,0x3bd942b9,0x78f7b768 }, + { 0xc87607ae,0x076c8ca1,0xd5caaa7e,0x82b23c2e,0x2763e461,0x6a581f39, + 0x3886df11,0xca8a5e4a,0x264e7f22,0xc87e90cf,0x215cfcfc,0x04f74870 } }, + /* 160 */ + { { 0x141d161c,0x5285d116,0x93c4ed17,0x67cd2e0e,0x7c36187e,0x12c62a64, + 0xed2584ca,0xf5329539,0x42fbbd69,0xc4c777c4,0x1bdfc50a,0x107de776 }, + { 0xe96beebd,0x9976dcc5,0xa865a151,0xbe2aff95,0x9d8872af,0x0e0a9da1, + 0xa63c17cc,0x5e357a3d,0xe15cc67c,0xd31fdfd8,0x7970c6d8,0xc44bbefd } }, + /* 161 */ + { { 0x4c0c62f1,0x703f83e2,0x4e195572,0x9b1e28ee,0xfe26cced,0x6a82858b, + 0xc43638fa,0xd381c84b,0xa5ba43d8,0x94f72867,0x10b82743,0x3b4a783d }, + { 0x7576451e,0xee1ad7b5,0x14b6b5c8,0xc3d0b597,0xfcacc1b8,0x3dc30954, + 0x472c9d7b,0x55df110e,0x02f8a328,0x97c86ed7,0x88dc098f,0xd0433413 } }, + /* 162 */ + { { 0x2ca8f2fe,0x1a60d152,0x491bd41f,0x61640948,0x58dfe035,0x6dae29a5, + 0x278e4863,0x9a615bea,0x9ad7c8e5,0xbbdb4477,0x2ceac2fc,0x1c706630 }, + { 0x99699b4b,0x5e2b54c6,0x239e17e8,0xb509ca6d,0xea063a82,0x728165fe, + 0xb6a22e02,0x6b5e609d,0xb26ee1df,0x12813905,0x439491fa,0x07b9f722 } }, + /* 163 */ + { { 0x48ff4e49,0x1592ec14,0x6d644129,0x3e4e9f17,0x1156acc0,0x7acf8288, + 0xbb092b0b,0x5aa34ba8,0x7d38393d,0xcd0f9022,0xea4f8187,0x416724dd }, + { 0xc0139e73,0x3c4e641c,0x91e4d87d,0xe0fe46cf,0xcab61f8a,0xedb3c792, + 0xd3868753,0x4cb46de4,0x20f1098a,0xe449c21d,0xf5b8ea6e,0x5e5fd059 } }, + /* 164 */ + { { 0x75856031,0x7fcadd46,0xeaf2fbd0,0x89c7a4cd,0x7a87c480,0x1af523ce, + 0x61d9ae90,0xe5fc1095,0xbcdb95f5,0x3fb5864f,0xbb5b2c7d,0xbeb5188e }, + { 0x3ae65825,0x3d1563c3,0x0e57d641,0x116854c4,0x1942ebd3,0x11f73d34, + 0xc06955b3,0x24dc5904,0x995a0a62,0x8a0d4c83,0x5d577b7d,0xfb26b86d } }, + /* 165 */ + { { 0xc686ae17,0xc53108e7,0xd1c1da56,0x9090d739,0x9aec50ae,0x4583b013, + 0xa49a6ab2,0xdd9a088b,0xf382f850,0x28192eea,0xf5fe910e,0xcc8df756 }, + { 0x9cab7630,0x877823a3,0xfb8e7fc1,0x64984a9a,0x364bfc16,0x5448ef9c, + 0xc44e2a9a,0xbbb4f871,0x435c95e9,0x901a41ab,0xaaa50a06,0xc6c23e5f } }, + /* 166 */ + { { 0x9034d8dd,0xb78016c1,0x0b13e79b,0x856bb44b,0xb3241a05,0x85c6409a, + 0x2d78ed21,0x8d2fe19a,0x726eddf2,0xdcc7c26d,0x25104f04,0x3ccaff5f }, + { 0x6b21f843,0x397d7edc,0xe975de4c,0xda88e4dd,0x4f5ab69e,0x5273d396, + 0x9aae6cc0,0x537680e3,0x3e6f9461,0xf749cce5,0x957bffd3,0x021ddbd9 } }, + /* 167 */ + { { 0x777233cf,0x7b64585f,0x0942a6f0,0xfe6771f6,0xdfe6eef0,0x636aba7a, + 0x86038029,0x63bbeb56,0xde8fcf36,0xacee5842,0xd4a20524,0x48d9aa99 }, + { 0x0da5e57a,0xcff7a74c,0xe549d6c9,0xc232593c,0xf0f2287b,0x68504bcc, + 0xbc8360b5,0x6d7d098d,0x5b402f41,0xeac5f149,0xb87d1bf1,0x61936f11 } }, + /* 168 */ + { { 0xb8153a9d,0xaa9da167,0x9e83ecf0,0xa49fe3ac,0x1b661384,0x14c18f8e, + 0x38434de1,0x61c24dab,0x283dae96,0x3d973c3a,0x82754fc9,0xc99baa01 }, + { 0x4c26b1e3,0x477d198f,0xa7516202,0x12e8e186,0x362addfa,0x386e52f6, + 0xc3962853,0x31e8f695,0x6aaedb60,0xdec2af13,0x29cf74ac,0xfcfdb4c6 } }, + /* 169 */ + { { 0xcca40298,0x6b3ee958,0xf2f5d195,0xc3878153,0xed2eae5b,0x0c565630, + 0x3a697cf2,0xd089b37e,0xad5029ea,0xc2ed2ac7,0x0f0dda6a,0x7e5cdfad }, + { 0xd9b86202,0xf98426df,0x4335e054,0xed1960b1,0x3f14639e,0x1fdb0246, + 0x0db6c670,0x17f709c3,0x773421e1,0xbfc687ae,0x26c1a8ac,0x13fefc4a } }, + /* 170 */ + { { 0x7ffa0a5f,0xe361a198,0xc63fe109,0xf4b26102,0x6c74e111,0x264acbc5, + 0x77abebaf,0x4af445fa,0x24cddb75,0x448c4fdd,0x44506eea,0x0b13157d }, + { 0x72e9993d,0x22a6b159,0x85e5ecbe,0x2c3c57e4,0xfd83e1a1,0xa673560b, + 0xc3b8c83b,0x6be23f82,0x40bbe38e,0x40b13a96,0xad17399b,0x66eea033 } }, + /* 171 */ + { { 0xb4c6c693,0x49fc6e95,0x36af7d38,0xefc735de,0x35fe42fc,0xe053343d, + 0x6a9ab7c3,0xf0aa427c,0x4a0fcb24,0xc79f0436,0x93ebbc50,0x16287243 }, + { 0x16927e1e,0x5c3d6bd0,0x673b984c,0x40158ed2,0x4cd48b9a,0xa7f86fc8, + 0x60ea282d,0x1643eda6,0xe2a1beed,0x45b393ea,0x19571a94,0x664c839e } }, + /* 172 */ + { { 0x27eeaf94,0x57745750,0xea99e1e7,0x2875c925,0x5086adea,0xc127e7ba, + 0x86fe424f,0x765252a0,0x2b6c0281,0x1143cc6c,0xd671312d,0xc9bb2989 }, + { 0x51acb0a5,0x880c337c,0xd3c60f78,0xa3710915,0x9262b6ed,0x496113c0, + 0x9ce48182,0x5d25d9f8,0xb3813586,0x53b6ad72,0x4c0e159c,0x0ea3bebc } }, + /* 173 */ + { { 0xc5e49bea,0xcaba450a,0x7c05da59,0x684e5415,0xde7ac36c,0xa2e9cab9, + 0x2e6f957b,0x4ca79b5f,0x09b817b1,0xef7b0247,0x7d89df0f,0xeb304990 }, + { 0x46fe5096,0x508f7307,0x2e04eaaf,0x695810e8,0x3512f76c,0x88ef1bd9, + 0x3ebca06b,0x77661351,0xccf158b7,0xf7d4863a,0x94ee57da,0xb2a81e44 } }, + /* 174 */ + { { 0x6d53e6ba,0xff288e5b,0x14484ea2,0xa90de1a9,0xed33c8ec,0x2fadb60c, + 0x28b66a40,0x579d6ef3,0xec24372d,0x4f2dd6dd,0x1d66ec7d,0xe9e33fc9 }, + { 0x039eab6e,0x110899d2,0x3e97bb5e,0xa31a667a,0xcfdce68e,0x6200166d, + 0x5137d54b,0xbe83ebae,0x4800acdf,0x085f7d87,0x0c6f8c86,0xcf4ab133 } }, + /* 175 */ + { { 0x931e08fb,0x03f65845,0x1506e2c0,0x6438551e,0x9c36961f,0x5791f0dc, + 0xe3dcc916,0x68107b29,0xf495d2ca,0x83242374,0x6ee5895b,0xd8cfb663 }, + { 0xa0349b1b,0x525e0f16,0x4a0fab86,0x33cd2c6c,0x2af8dda9,0x46c12ee8, + 0x71e97ad3,0x7cc424ba,0x37621eb0,0x69766ddf,0xa5f0d390,0x95565f56 } }, + /* 176 */ + { { 0x1a0f5e94,0xe0e7bbf2,0x1d82d327,0xf771e115,0xceb111fa,0x10033e3d, + 0xd3426638,0xd269744d,0x00d01ef6,0xbdf2d9da,0xa049ceaf,0x1cb80c71 }, + { 0x9e21c677,0x17f18328,0x19c8f98b,0x6452af05,0x80b67997,0x35b9c5f7, + 0x40f8f3d4,0x5c2e1cbe,0x66d667ca,0x43f91656,0xcf9d6e79,0x9faaa059 } }, + /* 177 */ + { { 0x0a078fe6,0x8ad24618,0x464fd1dd,0xf6cc73e6,0xc3e37448,0x4d2ce34d, + 0xe3271b5f,0x624950c5,0xefc5af72,0x62910f5e,0xaa132bc6,0x8b585bf8 }, + { 0xa839327f,0x11723985,0x4aac252f,0x34e2d27d,0x6296cc4e,0x402f59ef, + 0x47053de9,0x00ae055c,0x28b4f09b,0xfc22a972,0xfa0c180e,0xa9e86264 } }, + /* 178 */ + { { 0xbc310ecc,0x0b7b6224,0x67fa14ed,0x8a1a74f1,0x7214395c,0x87dd0960, + 0xf5c91128,0xdf1b3d09,0x86b264a8,0x39ff23c6,0x3e58d4c5,0xdc2d49d0 }, + { 0xa9d6f501,0x2152b7d3,0xc04094f7,0xf4c32e24,0xd938990f,0xc6366596, + 0x94fb207f,0x084d078f,0x328594cb,0xfd99f1d7,0xcb2d96b3,0x36defa64 } }, + /* 179 */ + { { 0x13ed7cbe,0x4619b781,0x9784bd0e,0x95e50015,0x2c7705fe,0x2a32251c, + 0x5f0dd083,0xa376af99,0x0361a45b,0x55425c6c,0x1f291e7b,0x812d2cef }, + { 0x5fd94972,0xccf581a0,0xe56dc383,0x26e20e39,0x63dbfbf0,0x0093685d, + 0x36b8c575,0x1fc164cc,0x390ef5e7,0xb9c5ab81,0x26908c66,0x40086beb } }, + /* 180 */ + { { 0x37e3c115,0xe5e54f79,0xc1445a8a,0x69b8ee8c,0xb7659709,0x79aedff2, + 0x1b46fbe6,0xe288e163,0xd18d7bb7,0xdb4844f0,0x48aa6424,0xe0ea23d0 }, + { 0xf3d80a73,0x714c0e4e,0x3bd64f98,0x87a0aa9e,0x2ec63080,0x8844b8a8, + 0x255d81a3,0xe0ac9c30,0x455397fc,0x86151237,0x2f820155,0x0b979464 } }, + /* 181 */ + { { 0x4ae03080,0x127a255a,0x580a89fb,0x232306b4,0x6416f539,0x04e8cd6a, + 0x13b02a0e,0xaeb70dee,0x4c09684a,0xa3038cf8,0x28e433ee,0xa710ec3c }, + { 0x681b1f7d,0x77a72567,0x2fc28170,0x86fbce95,0xf5735ac8,0xd3408683, + 0x6bd68e93,0x3a324e2a,0xc027d155,0x7ec74353,0xd4427177,0xab60354c } }, + /* 182 */ + { { 0xef4c209d,0x32a5342a,0x08d62704,0x2ba75274,0xc825d5fe,0x4bb4af6f, + 0xd28e7ff1,0x1c3919ce,0xde0340f6,0x1dfc2fdc,0x29f33ba9,0xc6580baf }, + { 0x41d442cb,0xae121e75,0x3a4724e4,0x4c7727fd,0x524f3474,0xe556d6a4, + 0x785642a2,0x87e13cc7,0xa17845fd,0x182efbb1,0x4e144857,0xdcec0cf1 } }, + /* 183 */ + { { 0xe9539819,0x1cb89541,0x9d94dbf1,0xc8cb3b4f,0x417da578,0x1d353f63, + 0x8053a09e,0xb7a697fb,0xc35d8b78,0x8d841731,0xb656a7a9,0x85748d6f }, + { 0xc1859c5d,0x1fd03947,0x535d22a2,0x6ce965c1,0x0ca3aadc,0x1966a13e, + 0x4fb14eff,0x9802e41d,0x76dd3fcd,0xa9048cbb,0xe9455bba,0x89b182b5 } }, + /* 184 */ + { { 0x43360710,0xd777ad6a,0x55e9936b,0x841287ef,0x04a21b24,0xbaf5c670, + 0x35ad86f1,0xf2c0725f,0xc707e72e,0x338fa650,0xd8883e52,0x2bf8ed2e }, + { 0xb56e0d6a,0xb0212cf4,0x6843290c,0x50537e12,0x98b3dc6f,0xd8b184a1, + 0x0210b722,0xd2be9a35,0x559781ee,0x407406db,0x0bc18534,0x5a78d591 } }, + /* 185 */ + { { 0xd748b02c,0x4d57aa2a,0xa12b3b95,0xbe5b3451,0x64711258,0xadca7a45, + 0x322153db,0x597e091a,0x32eb1eab,0xf3271006,0x2873f301,0xbd9adcba }, + { 0x38543f7f,0xd1dc79d1,0x921b1fef,0x00022092,0x1e5df8ed,0x86db3ef5, + 0x9e6b944a,0x888cae04,0x791a32b4,0x71bd29ec,0xa6d1c13e,0xd3516206 } }, + /* 186 */ + { { 0x55924f43,0x2ef6b952,0x4f9de8d5,0xd2f401ae,0xadc68042,0xfc73e8d7, + 0x0d9d1bb4,0x627ea70c,0xbbf35679,0xc3bb3e3e,0xd882dee4,0x7e8a254a }, + { 0xb5924407,0x08906f50,0xa1ad444a,0xf14a0e61,0x65f3738e,0xaa0efa21, + 0xae71f161,0xd60c7dd6,0xf175894d,0x9e8390fa,0x149f4c00,0xd115cd20 } }, + /* 187 */ + { { 0xa52abf77,0x2f2e2c1d,0x54232568,0xc2a0dca5,0x54966dcc,0xed423ea2, + 0xcd0dd039,0xe48c93c7,0x176405c7,0x1e54a225,0x70d58f2e,0x1efb5b16 }, + { 0x94fb1471,0xa751f9d9,0x67d2941d,0xfdb31e1f,0x53733698,0xa6c74eb2, + 0x89a0f64a,0xd3155d11,0xa4b8d2b6,0x4414cfe4,0xf7a8e9e3,0x8d5a4be8 } }, + /* 188 */ + { { 0x52669e98,0x5c96b4d4,0x8fd42a03,0x4547f922,0xd285174e,0xcf5c1319, + 0x064bffa0,0x805cd1ae,0x246d27e7,0x50e8bc4f,0xd5781e11,0xf89ef98f }, + { 0xdee0b63f,0xb4ff95f6,0x222663a4,0xad850047,0x4d23ce9c,0x02691860, + 0x50019f59,0x3e5309ce,0x69a508ae,0x27e6f722,0x267ba52c,0xe9376652 } }, + /* 189 */ + { { 0xc0368708,0xa04d289c,0x5e306e1d,0xc458872f,0x33112fea,0x76fa23de, + 0x6efde42e,0x718e3974,0x1d206091,0xf0c98cdc,0x14a71987,0x5fa3ca62 }, + { 0xdcaa9f2a,0xeee8188b,0x589a860d,0x312cc732,0xc63aeb1f,0xf9808dd6, + 0x4ea62b53,0x70fd43db,0x890b6e97,0x2c2bfe34,0xfa426aa6,0x105f863c } }, + /* 190 */ + { { 0xb38059ad,0x0b29795d,0x90647ea0,0x5686b77e,0xdb473a3e,0xeff0470e, + 0xf9b6d1e2,0x278d2340,0xbd594ec7,0xebbff95b,0xd3a7f23d,0xf4b72334 }, + { 0xa5a83f0b,0x2a285980,0x9716a8b3,0x0786c41a,0x22511812,0x138901bd, + 0xe2fede6e,0xd1b55221,0xdf4eb590,0x0806e264,0x762e462e,0x6c4c897e } }, + /* 191 */ + { { 0xb4b41d9d,0xd10b905f,0x4523a65b,0x826ca466,0xb699fa37,0x535bbd13, + 0x73bc8f90,0x5b9933d7,0xcd2118ad,0x9332d61f,0xd4a65fd0,0x158c693e }, + { 0xe6806e63,0x4ddfb2a8,0xb5de651b,0xe31ed3ec,0x819bc69a,0xf9460e51, + 0x2c76b1f8,0x6229c0d6,0x901970a3,0xbb78f231,0x9cee72b8,0x31f3820f } }, + /* 192 */ + { { 0xc09e1c72,0xe931caf2,0x12990cf4,0x0715f298,0x943262d8,0x33aad81d, + 0x73048d3f,0x5d292b7a,0xdc7415f6,0xb152aaa4,0x0fd19587,0xc3d10fd9 }, + { 0x75ddadd0,0xf76b35c5,0x1e7b694c,0x9f5f4a51,0xc0663025,0x2f1ab7eb, + 0x920260b0,0x01c9cc87,0x05d39da6,0xc4b1f61a,0xeb4a9c4e,0x6dcd76c4 } }, + /* 193 */ + { { 0xfdc83f01,0x0ba0916f,0x9553e4f9,0x354c8b44,0xffc5e622,0xa6cc511a, + 0xe95be787,0xb954726a,0x75b41a62,0xcb048115,0xebfde989,0xfa2ae6cd }, + { 0x0f24659a,0x6376bbc7,0x4c289c43,0x13a999fd,0xec9abd8b,0xc7134184, + 0xa789ab04,0x28c02bf6,0xd3e526ec,0xff841ebc,0x640893a8,0x442b191e } }, + /* 194 */ + { { 0xfa2b6e20,0x4cac6c62,0xf6d69861,0x97f29e9b,0xbc96d12d,0x228ab1db, + 0x5e8e108d,0x6eb91327,0x40771245,0xd4b3d4d1,0xca8a803a,0x61b20623 }, + { 0xa6a560b1,0x2c2f3b41,0x3859fcf4,0x879e1d40,0x024dbfc3,0x7cdb5145, + 0x3bfa5315,0x55d08f15,0xaa93823a,0x2f57d773,0xc6a2c9a2,0xa97f259c } }, + /* 195 */ + { { 0xe58edbbb,0xc306317b,0x79dfdf13,0x25ade51c,0x16d83dd6,0x6b5beaf1, + 0x1dd8f925,0xe8038a44,0xb2a87b6b,0x7f00143c,0xf5b438de,0xa885d00d }, + { 0xcf9e48bd,0xe9f76790,0xa5162768,0xf0bdf9f0,0xad7b57cb,0x0436709f, + 0xf7c15db7,0x7e151c12,0x5d90ee3b,0x3514f022,0x2c361a8d,0x2e84e803 } }, + /* 196 */ + { { 0x563ec8d8,0x2277607d,0xe3934cb7,0xa661811f,0xf58fd5de,0x3ca72e7a, + 0x62294c6a,0x7989da04,0xf6bbefe9,0x88b3708b,0x53ed7c82,0x0d524cf7 }, + { 0x2f30c073,0x69f699ca,0x9dc1dcf3,0xf0fa264b,0x05f0aaf6,0x44ca4568, + 0xd19b9baf,0x0f5b23c7,0xeabd1107,0x39193f41,0x2a7c9b83,0x9e3e10ad } }, + /* 197 */ + { { 0xd4ae972f,0xa90824f0,0xc6e846e7,0x43eef02b,0x29d2160a,0x7e460612, + 0xfe604e91,0x29a178ac,0x4eb184b2,0x23056f04,0xeb54cdf4,0x4fcad55f }, + { 0xae728d15,0xa0ff96f3,0xc6a00331,0x8a2680c6,0x7ee52556,0x5f84cae0, + 0xc5a65dad,0x5e462c3a,0xe2d23f4f,0x5d2b81df,0xc5b1eb07,0x6e47301b } }, + /* 198 */ + { { 0xaf8219b9,0x77411d68,0x51b1907a,0xcb883ce6,0x101383b5,0x25c87e57, + 0x982f970d,0x9c7d9859,0x118305d2,0xaa6abca5,0x9013a5db,0x725fed2f }, + { 0xababd109,0x487cdbaf,0x87586528,0xc0f8cf56,0x8ad58254,0xa02591e6, + 0xdebbd526,0xc071b1d1,0x961e7e31,0x927dfe8b,0x9263dfe1,0x55f895f9 } }, + /* 199 */ + { { 0xb175645b,0xf899b00d,0xb65b4b92,0x51f3a627,0xb67399ef,0xa2f3ac8d, + 0xe400bc20,0xe717867f,0x1967b952,0x42cc9020,0x3ecd1de1,0x3d596751 }, + { 0xdb979775,0xd41ebcde,0x6a2e7e88,0x99ba61bc,0x321504f2,0x039149a5, + 0x27ba2fad,0xe7dc2314,0xb57d8368,0x9f556308,0x57da80a7,0x2b6d16c9 } }, + /* 200 */ + { { 0x279ad982,0x84af5e76,0x9c8b81a6,0x9bb4c92d,0x0e698e67,0xd79ad44e, + 0x265fc167,0xe8be9048,0x0c3a4ccc,0xf135f7e6,0xb8863a33,0xa0a10d38 }, + { 0xd386efd9,0xe197247c,0xb52346c2,0x0eefd3f9,0x78607bc8,0xc22415f9, + 0x508674ce,0xa2a8f862,0xc8c9d607,0xa72ad09e,0x50fa764f,0xcd9f0ede } }, + /* 201 */ + { { 0xd1a46d4d,0x063391c7,0x9eb01693,0x2df51c11,0x849e83de,0xc5849800, + 0x8ad08382,0x48fd09aa,0xaa742736,0xa405d873,0xe1f9600c,0xee49e61e }, + { 0x48c76f73,0xd76676be,0x01274b2a,0xd9c100f6,0x83f8718d,0x110bb67c, + 0x02fc0d73,0xec85a420,0x744656ad,0xc0449e1e,0x37d9939b,0x28ce7376 } }, + /* 202 */ + { { 0x44544ac7,0x97e9af72,0xba010426,0xf2c658d5,0xfb3adfbd,0x732dec39, + 0xa2df0b07,0xd12faf91,0x2171e208,0x8ac26725,0x5b24fa54,0xf820cdc8 }, + { 0x94f4cf77,0x307a6eea,0x944a33c6,0x18c783d2,0x0b741ac5,0x4b939d4c, + 0x3ffbb6e4,0x1d7acd15,0x7a255e44,0x06a24858,0xce336d50,0x14fbc494 } }, + /* 203 */ + { { 0x51584e3c,0x9b920c0c,0xf7e54027,0xc7733c59,0x88422bbe,0xe24ce139, + 0x523bd6ab,0x11ada812,0xb88e6def,0xde068800,0xfe8c582d,0x7b872671 }, + { 0x7de53510,0x4e746f28,0xf7971968,0x492f8b99,0x7d928ac2,0x1ec80bc7, + 0x432eb1b5,0xb3913e48,0x32028f6e,0xad084866,0x8fc2f38b,0x122bb835 } }, + /* 204 */ + { { 0x3b0b29c3,0x0a9f3b1e,0x4fa44151,0x837b6432,0x17b28ea7,0xb9905c92, + 0x98451750,0xf39bc937,0xce8b6da1,0xcd383c24,0x010620b2,0x299f57db }, + { 0x58afdce3,0x7b6ac396,0x3d05ef47,0xa15206b3,0xb9bb02ff,0xa0ae37e2, + 0x9db3964c,0x107760ab,0x67954bea,0xe29de9a0,0x431c3f82,0x446a1ad8 } }, + /* 205 */ + { { 0x5c6b8195,0xc6fecea0,0xf49e71b9,0xd744a7c5,0x177a7ae7,0xa8e96acc, + 0x358773a7,0x1a05746c,0x37567369,0xa4162146,0x87d1c971,0xaa0217f7 }, + { 0x77fd3226,0x61e9d158,0xe4f600be,0x0f6f2304,0x7a6dff07,0xa9c4cebc, + 0x09f12a24,0xd15afa01,0x8c863ee9,0x2bbadb22,0xe5eb8c78,0xa28290e4 } }, + /* 206 */ + { { 0x3e9de330,0x55b87fa0,0x195c145b,0x12b26066,0xa920bef0,0xe08536e0, + 0x4d195adc,0x7bff6f2c,0x945f4187,0x7f319e9d,0xf892ce47,0xf9848863 }, + { 0x4fe37657,0xd0efc1d3,0x5cf0e45a,0x3c58de82,0x8b0ccbbe,0x626ad21a, + 0xaf952fc5,0xd2a31208,0xeb437357,0x81791995,0x98e95d4f,0x5f19d30f } }, + /* 207 */ + { { 0x0e6865bb,0x72e83d9a,0xf63456a6,0x22f5af3b,0x463c8d9e,0x409e9c73, + 0xdfe6970e,0x40e9e578,0x711b91ca,0x876b6efa,0x942625a3,0x895512cf }, + { 0xcb4e462b,0x84c8eda8,0x4412e7c8,0x84c0154a,0xceb7b71f,0x04325db1, + 0x66f70877,0x1537dde3,0x1992b9ac,0xf3a09399,0xd498ae77,0xa7316606 } }, + /* 208 */ + { { 0xcad260f5,0x13990d2f,0xeec0e8c0,0x76c3be29,0x0f7bd7d5,0x7dc5bee0, + 0xefebda4b,0x9be167d2,0x9122b87e,0xcce3dde6,0x82b5415c,0x75a28b09 }, + { 0xe84607a6,0xf6810bcd,0x6f4dbf0d,0xc6d58128,0x1b4dafeb,0xfead577d, + 0x066b28eb,0x9bc440b2,0x8b17e84b,0x53f1da97,0xcda9a575,0x0459504b } }, + /* 209 */ + { { 0x329e5836,0x13e39a02,0xf717269d,0x2c9e7d51,0xf26c963b,0xc5ac58d6, + 0x79967bf5,0x3b0c6c43,0x55908d9d,0x60bbea3f,0xf07c9ad1,0xd84811e7 }, + { 0x5bd20e4a,0xfe7609a7,0x0a70baa8,0xe4325dd2,0xb3600386,0x3711f370, + 0xd0924302,0x97f9562f,0x4acc4436,0x040dc0c3,0xde79cdd4,0xfd6d725c } }, + /* 210 */ + { { 0xcf13eafb,0xb3efd0e3,0x5aa0ae5f,0x21009cbb,0x79022279,0xe480c553, + 0xb2fc9a6d,0x755cf334,0x07096ae7,0x8564a5bf,0xbd238139,0xddd649d0 }, + { 0x8a045041,0xd0de10b1,0xc957d572,0x6e05b413,0x4e0fb25c,0x5c5ff806, + 0x641162fb,0xd933179b,0xe57439f9,0x42d48485,0x8a8d72aa,0x70c5bd0a } }, + /* 211 */ + { { 0x97bdf646,0xa7671738,0xab329f7c,0xaa1485b4,0xf8f25fdf,0xce3e11d6, + 0xc6221824,0x76a3fc7e,0xf3924740,0x045f281f,0x96d13a9a,0x24557d4e }, + { 0xdd4c27cd,0x875c804b,0x0f5c7fea,0x11c5f0f4,0xdc55ff7e,0xac8c880b, + 0x1103f101,0x2acddec5,0xf99faa89,0x38341a21,0xce9d6b57,0xc7b67a2c } }, + /* 212 */ + { { 0x8e357586,0x9a0d724f,0xdf648da0,0x1d7f4ff5,0xfdee62a5,0x9c3e6c9b, + 0x0389b372,0x0499cef0,0x98eab879,0xe904050d,0x6c051617,0xe8eef1b6 }, + { 0xc37e3ca9,0xebf5bfeb,0xa4e0b91d,0x7c5e946d,0x2c4bea28,0x79097314, + 0xee67b2b7,0x81f6c109,0xdafc5ede,0xaf237d9b,0x2abb04c7,0xd2e60201 } }, + /* 213 */ + { { 0x8a4f57bf,0x6156060c,0xff11182a,0xf9758696,0x6296ef00,0x8336773c, + 0xff666899,0x9c054bce,0x719cd11c,0xd6a11611,0xdbe1acfa,0x9824a641 }, + { 0xba89fd01,0x0b7b7a5f,0x889f79d8,0xf8d3b809,0xf578285c,0xc5e1ea08, + 0xae6d8288,0x7ac74536,0x7521ef5f,0x5d37a200,0xb260a25d,0x5ecc4184 } }, + /* 214 */ + { { 0xa708c8d3,0xddcebb19,0xc63f81ec,0xe63ed04f,0x11873f95,0xd045f5a0, + 0x79f276d5,0x3b5ad544,0x425ae5b3,0x81272a3d,0x10ce1605,0x8bfeb501 }, + { 0x888228bf,0x4233809c,0xb2aff7df,0x4bd82acf,0x0cbd4a7f,0x9c68f180, + 0x6b44323d,0xfcd77124,0x891db957,0x60c0fcf6,0x04da8f7f,0xcfbb4d89 } }, + /* 215 */ + { { 0x3b26139a,0x9a6a5df9,0xb2cc7eb8,0x3e076a83,0x5a964bcd,0x47a8e82d, + 0xb9278d6b,0x8a4e2a39,0xe4443549,0x93506c98,0xf1e0d566,0x06497a8f }, + { 0x2b1efa05,0x3dee8d99,0x45393e33,0x2da63ca8,0xcf0579ad,0xa4af7277, + 0x3236d8ea,0xaf4b4639,0x32b617f5,0x6ccad95b,0xb88bb124,0xce76d8b8 } }, + /* 216 */ + { { 0x083843dc,0x63d2537a,0x1e4153b4,0x89eb3514,0xea9afc94,0x5175ebc4, + 0x8ed1aed7,0x7a652580,0xd85e8297,0x67295611,0xb584b73d,0x8dd2d68b }, + { 0x0133c3a4,0x237139e6,0x4bd278ea,0x9de838ab,0xc062fcd9,0xe829b072, + 0x63ba8706,0x70730d4f,0xd3cd05ec,0x6080483f,0x0c85f84d,0x872ab5b8 } }, + /* 217 */ + { { 0x999d4d49,0xfc0776d3,0xec3f45e7,0xa3eb59de,0x0dae1fc1,0xbc990e44, + 0xa15371ff,0x33596b1e,0x9bc7ab25,0xd447dcb2,0x35979582,0xcd5b63e9 }, + { 0x77d1ff11,0xae3366fa,0xedee6903,0x59f28f05,0xa4433bf2,0x6f43fed1, + 0xdf9ce00e,0x15409c9b,0xaca9c5dc,0x21b5cded,0x82d7bdb4,0xf9f33595 } }, + /* 218 */ + { { 0x9422c792,0x95944378,0xc958b8bf,0x239ea923,0xdf076541,0x4b61a247, + 0xbb9fc544,0x4d29ce85,0x0b424559,0x9a692a67,0x0e486900,0x6e0ca5a0 }, + { 0x85b3bece,0x6b79a782,0xc61f9892,0x41f35e39,0xae747f82,0xff82099a, + 0xd0ca59d6,0x58c8ae3f,0x99406b5f,0x4ac930e2,0x9df24243,0x2ce04eb9 } }, + /* 219 */ + { { 0x1ac37b82,0x4366b994,0x25b04d83,0xff0c728d,0x19c47b7c,0x1f551361, + 0xbeff13e7,0xdbf2d5ed,0xe12a683d,0xf78efd51,0x989cf9c4,0x82cd85b9 }, + { 0xe0cb5d37,0xe23c6db6,0x72ee1a15,0x818aeebd,0x28771b14,0x8212aafd, + 0x1def817d,0x7bc221d9,0x9445c51f,0xdac403a2,0x12c3746b,0x711b0517 } }, + /* 220 */ + { { 0x5ea99ecc,0x0ed9ed48,0xb8cab5e1,0xf799500d,0xb570cbdc,0xa8ec87dc, + 0xd35dfaec,0x52cfb2c2,0x6e4d80a4,0x8d31fae2,0xdcdeabe5,0xe6a37dc9 }, + { 0x1deca452,0x5d365a34,0x0d68b44e,0x09a5f8a5,0xa60744b1,0x59238ea5, + 0xbb4249e9,0xf2fedc0d,0xa909b2e3,0xe395c74e,0x39388250,0xe156d1a5 } }, + /* 221 */ + { { 0x47181ae9,0xd796b3d0,0x44197808,0xbaf44ba8,0x34cf3fac,0xe6933094, + 0xc3bd5c46,0x41aa6ade,0xeed947c6,0x4fda75d8,0x9ea5a525,0xacd9d412 }, + { 0xd430301b,0x65cc55a3,0x7b52ea49,0x3c9a5bcf,0x159507f0,0x22d319cf, + 0xde74a8dd,0x2ee0b9b5,0x877ac2b6,0x20c26a1e,0x92e7c314,0x387d73da } }, + /* 222 */ + { { 0x8cd3fdac,0x13c4833e,0x332e5b8e,0x76fcd473,0xe2fe1fd3,0xff671b4b, + 0x5d98d8ec,0x4d734e8b,0x514bbc11,0xb1ead3c6,0x7b390494,0xd14ca858 }, + { 0x5d2d37e9,0x95a443af,0x00464622,0x73c6ea73,0x15755044,0xa44aeb4b, + 0xfab58fee,0xba3f8575,0xdc680a6f,0x9779dbc9,0x7b37ddfc,0xe1ee5f5a } }, + /* 223 */ + { { 0x12d29f46,0xcd0b4648,0x0ed53137,0x93295b0b,0x80bef6c9,0xbfe26094, + 0x54248b00,0xa6565788,0x80e7f9c4,0x69c43fca,0xbe141ea1,0x2190837b }, + { 0xa1b26cfb,0x875e159a,0x7affe852,0x90ca9f87,0x92ca598e,0x15e6550d, + 0x1938ad11,0xe3e0945d,0x366ef937,0xef7636bb,0xb39869e5,0xb6034d0b } }, + /* 224 */ + { { 0x26d8356e,0x4d255e30,0xd314626f,0xf83666ed,0xd0c8ed64,0x421ddf61, + 0x26677b61,0x96e473c5,0x9e9b18b3,0xdad4af7e,0xa9393f75,0xfceffd4a }, + { 0x11c731d5,0x843138a1,0xb2f141d9,0x05bcb3a1,0x617b7671,0x20e1fa95, + 0x88ccec7b,0xbefce812,0x90f1b568,0x582073dc,0x1f055cb7,0xf572261a } }, + /* 225 */ + { { 0x36973088,0xf3148277,0x86a9f980,0xc008e708,0xe046c261,0x1b795947, + 0xca76bca0,0xdf1e6a7d,0x71acddf0,0xabafd886,0x1364d8f4,0xff7054d9 }, + { 0xe2260594,0x2cf63547,0xd73b277e,0x468a5372,0xef9bd35e,0xc7419e24, + 0x24043cc3,0x2b4a1c20,0x890b39cd,0xa28f047a,0x46f9a2e3,0xdca2cea1 } }, + /* 226 */ + { { 0x53277538,0xab788736,0xcf697738,0xa734e225,0x6b22e2c1,0x66ee1d1e, + 0xebe1d212,0x2c615389,0x02bb0766,0xf36cad40,0x3e64f207,0x120885c3 }, + { 0x90fbfec2,0x59e77d56,0xd7a574ae,0xf9e781aa,0x5d045e53,0x801410b0, + 0xa91b5f0e,0xd3b5f0aa,0x7fbb3521,0xb3d1df00,0xc72bee9a,0x11c4b33e } }, + /* 227 */ + { { 0x83c3a7f3,0xd32b9832,0x88d8a354,0x8083abcf,0x50f4ec5a,0xdeb16404, + 0x641e2907,0x18d747f0,0xf1bbf03e,0x4e8978ae,0x88a0cd89,0x932447dc }, + { 0xcf3d5897,0x561e0feb,0x13600e6d,0xfc3a682f,0xd16a6b73,0xc78b9d73, + 0xd29bf580,0xe713fede,0x08d69e5c,0x0a225223,0x1ff7fda4,0x3a924a57 } }, + /* 228 */ + { { 0xb4093bee,0xfb64554c,0xa58c6ec0,0xa6d65a25,0x43d0ed37,0x4126994d, + 0x55152d44,0xa5689a51,0x284caa8d,0xb8e5ea8c,0xd1f25538,0x33f05d4f }, + { 0x1b615d6e,0xe0fdfe09,0x705507da,0x2ded7e8f,0x17bbcc80,0xdd5631e5, + 0x267fd11f,0x4f87453e,0xff89d62d,0xc6da723f,0xe3cda21d,0x55cbcae2 } }, + /* 229 */ + { { 0x6b4e84f3,0x336bc94e,0x4ef72c35,0x72863031,0xeeb57f99,0x6d85fdee, + 0xa42ece1b,0x7f4e3272,0x36f0320a,0x7f86cbb5,0x923331e6,0xf09b6a2b }, + { 0x56778435,0x21d3ecf1,0x8323b2d2,0x2977ba99,0x1704bc0f,0x6a1b57fb, + 0x389f048a,0xd777cf8b,0xac6b42cd,0x9ce2174f,0x09e6c55a,0x404e2bff } }, + /* 230 */ + { { 0x204c5ddb,0x9b9b135e,0x3eff550e,0x9dbfe044,0xec3be0f6,0x35eab4bf, + 0x0a43e56f,0x8b4c3f0d,0x0e73f9b3,0x4c1c6673,0x2c78c905,0x92ed38bd }, + { 0xa386e27c,0xc7003f6a,0xaced8507,0xb9c4f46f,0x59df5464,0xea024ec8, + 0x429572ea,0x4af96152,0xe1fc1194,0x279cd5e2,0x281e358c,0xaa376a03 } }, + /* 231 */ + { { 0x3cdbc95c,0x07859223,0xef2e337a,0xaae1aa6a,0x472a8544,0xc040108d, + 0x8d037b7d,0x80c853e6,0x8c7eee24,0xd221315c,0x8ee47752,0x195d3856 }, + { 0xdacd7fbe,0xd4b1ba03,0xd3e0c52b,0x4b5ac61e,0x6aab7b52,0x68d3c052, + 0x660e3fea,0xf0d7248c,0x3145efb4,0xafdb3f89,0x8f40936d,0xa73fd9a3 } }, + /* 232 */ + { { 0xbb1b17ce,0x891b9ef3,0xc6127f31,0x14023667,0x305521fd,0x12b2e58d, + 0xe3508088,0x3a47e449,0xff751507,0xe49fc84b,0x5310d16e,0x4023f722 }, + { 0xb73399fa,0xa608e5ed,0xd532aa3e,0xf12632d8,0x845e8415,0x13a2758e, + 0x1fc2d861,0xae4b6f85,0x339d02f2,0x3879f5b1,0x80d99ebd,0x446d22a6 } }, + /* 233 */ + { { 0x4be164f1,0x0f502302,0x88b81920,0x8d09d2d6,0x984aceff,0x514056f1, + 0x75e9e80d,0xa5c4ddf0,0xdf496a93,0x38cb47e6,0x38df6bf7,0x899e1d6b }, + { 0xb59eb2a6,0x69e87e88,0x9b47f38b,0x280d9d63,0x3654e955,0x599411ea, + 0x969aa581,0xcf8dd4fd,0x530742a7,0xff5c2baf,0x1a373085,0xa4391536 } }, + /* 234 */ + { { 0xa8a4bdd2,0x6ace72a3,0xb68ef702,0xc656cdd1,0x90c4dad8,0xd4a33e7e, + 0x9d951c50,0x4aece08a,0x085d68e6,0xea8005ae,0x6f7502b8,0xfdd7a7d7 }, + { 0x98d6fa45,0xce6fb0a6,0x1104eb8c,0x228f8672,0xda09d7dc,0xd23d8787, + 0x2ae93065,0x5521428b,0xea56c366,0x95faba3d,0x0a88aca5,0xedbe5039 } }, + /* 235 */ + { { 0xbfb26c82,0xd64da0ad,0x952c2f9c,0xe5d70b3c,0xf7e77f68,0xf5e8f365, + 0x08f2d695,0x7234e002,0xd12e7be6,0xfaf900ee,0x4acf734e,0x27dc6934 }, + { 0xc260a46a,0x80e4ff5e,0x2dc31c28,0x7da5ebce,0xca69f552,0x485c5d73, + 0x69cc84c2,0xcdfb6b29,0xed6d4eca,0x031c5afe,0x22247637,0xc7bbf4c8 } }, + /* 236 */ + { { 0x49fe01b2,0x9d5b72c7,0x793a91b8,0x34785186,0xcf460438,0xa3ba3c54, + 0x3ab21b6f,0x73e8e43d,0xbe57b8ab,0x50cde8e0,0xdd204264,0x6488b3a7 }, + { 0xdddc4582,0xa9e398b3,0x5bec46fe,0x1698c1a9,0x156d3843,0x7f1446ef, + 0x770329a2,0x3fd25dd8,0x2c710668,0x05b1221a,0xa72ee6cf,0x65b2dc2a } }, + /* 237 */ + { { 0xcd021d63,0x21a885f7,0xfea61f08,0x3f344b15,0xc5cf73e6,0xad5ba6dd, + 0x227a8b23,0x154d0d8f,0xdc559311,0x9b74373c,0x98620fa1,0x4feab715 }, + { 0x7d9ec924,0x5098938e,0x6d47e550,0x84d54a5e,0x1b617506,0x1a2d1bdc, + 0x615868a4,0x99fe1782,0x3005a924,0x171da780,0x7d8f79b6,0xa70bf5ed } }, + /* 238 */ + { { 0xfe2216c5,0x0bc1250d,0x7601b351,0x2c37e250,0xd6f06b7e,0xb6300175, + 0x8bfeb9b7,0x4dde8ca1,0xb82f843d,0x4f210432,0xb1ac0afd,0x8d70e2f9 }, + { 0xaae91abb,0x25c73b78,0x863028f2,0x0230dca3,0xe5cf30b7,0x8b923ecf, + 0x5506f265,0xed754ec2,0x729a5e39,0x8e41b88c,0xbabf889b,0xee67cec2 } }, + /* 239 */ + { { 0x1be46c65,0xe183acf5,0xe7565d7a,0x9789538f,0xd9627b4e,0x87873391, + 0x9f1d9187,0xbf4ac4c1,0x4691f5c8,0x5db99f63,0x74a1fb98,0xa68df803 }, + { 0xbf92b5fa,0x3c448ed1,0x3e0bdc32,0xa098c841,0x79bf016c,0x8e74cd55, + 0x115e244d,0x5df0d09c,0x3410b66e,0x9418ad01,0x17a02130,0x8b6124cb } }, + /* 240 */ + { { 0xc26e3392,0x425ec3af,0xa1722e00,0xc07f8470,0xe2356b43,0xdcc28190, + 0xb1ef59a6,0x4ed97dff,0xc63028c1,0xc22b3ad1,0x68c18988,0x070723c2 }, + { 0x4cf49e7d,0x70da302f,0x3f12a522,0xc5e87c93,0x18594148,0x74acdd1d, + 0xca74124c,0xad5f73ab,0xd69fd478,0xe72e4a3e,0x7b117cc3,0x61593868 } }, + /* 241 */ + { { 0xa9aa0486,0x7b7b9577,0xa063d557,0x6e41fb35,0xda9047d7,0xb017d5c7, + 0x68a87ba9,0x8c748280,0xdf08ad93,0xab45fa5c,0x4c288a28,0xcd9fb217 }, + { 0x5747843d,0x59544642,0xa56111e3,0x34d64c6c,0x4bfce8d5,0x12e47ea1, + 0x6169267f,0x17740e05,0xeed03fb5,0x5c49438e,0x4fc3f513,0x9da30add } }, + /* 242 */ + { { 0xccfa5200,0xc4e85282,0x6a19b13d,0x2707608f,0xf5726e2f,0xdcb9a53d, + 0xe9427de5,0x612407c9,0xd54d582a,0x3e5a17e1,0x655ae118,0xb99877de }, + { 0x015254de,0x6f0e972b,0xf0a6f7c5,0x92a56db1,0xa656f8b2,0xd297e4e1, + 0xad981983,0x99fe0052,0x07cfed84,0xd3652d2f,0x843c1738,0xc784352e } }, + /* 243 */ + { { 0x7e9b2d8a,0x6ee90af0,0x57cf1964,0xac8d7018,0x71f28efc,0xf6ed9031, + 0x6812b20e,0x7f70d5a9,0xf1c61eee,0x27b557f4,0xc6263758,0xf1c9bd57 }, + { 0x2a1a6194,0x5cf7d014,0x1890ab84,0xdd614e0b,0x0e93c2a6,0x3ef9de10, + 0xe0cd91c5,0xf98cf575,0x14befc32,0x504ec0c6,0x6279d68c,0xd0513a66 } }, + /* 244 */ + { { 0xa859fb6a,0xa8eadbad,0xdb283666,0xcf8346e7,0x3e22e355,0x7b35e61a, + 0x99639c6b,0x293ece2c,0x56f241c8,0xfa0162e2,0xbf7a1dda,0xd2e6c7b9 }, + { 0x40075e63,0xd0de6253,0xf9ec8286,0x2405aa61,0x8fe45494,0x2237830a, + 0x364e9c8c,0x4fd01ac7,0x904ba750,0x4d9c3d21,0xaf1b520b,0xd589be14 } }, + /* 245 */ + { { 0x4662e53b,0x13576a4f,0xf9077676,0x35ec2f51,0x97c0af97,0x66297d13, + 0x9e598b58,0xed3201fe,0x5e70f604,0x49bc752a,0xbb12d951,0xb54af535 }, + { 0x212c1c76,0x36ea4c2b,0xeb250dfd,0x18f5bbc7,0x9a0a1a46,0xa0d466cc, + 0xdac2d917,0x52564da4,0x8e95fab5,0x206559f4,0x9ca67a33,0x7487c190 } }, + /* 246 */ + { { 0xdde98e9c,0x75abfe37,0x2a411199,0x99b90b26,0xdcdb1f7c,0x1b410996, + 0x8b3b5675,0xab346f11,0xf1f8ae1e,0x04852193,0x6b8b98c1,0x1ec4d227 }, + { 0x45452baa,0xba3bc926,0xacc4a572,0x387d1858,0xe51f171e,0x9478eff6, + 0x931e1c00,0xf357077d,0xe54c8ca8,0xffee77cd,0x551dc9a4,0xfb4892ff } }, + /* 247 */ + { { 0x2db8dff8,0x5b1bdad0,0x5a2285a2,0xd462f4fd,0xda00b461,0x1d6aad8e, + 0x41306d1b,0x43fbefcf,0x6a13fe19,0x428e86f3,0x17f89404,0xc8b2f118 }, + { 0xf0d51afb,0x762528aa,0x549b1d06,0xa3e2fea4,0xea3ddf66,0x86fad8f2, + 0x4fbdd206,0x0d9ccc4b,0xc189ff5a,0xcde97d4c,0x199f19a6,0xc36793d6 } }, + /* 248 */ + { { 0x51b85197,0xea38909b,0xb4c92895,0xffb17dd0,0x1ddb3f3f,0x0eb0878b, + 0xc57cf0f2,0xb05d28ff,0x1abd57e2,0xd8bde2e7,0xc40c1b20,0x7f2be28d }, + { 0x299a2d48,0x6554dca2,0x8377982d,0x5130ba2e,0x1071971a,0x8863205f, + 0x7cf2825d,0x15ee6282,0x03748f2b,0xd4b6c57f,0x430385a0,0xa9e3f4da } }, + /* 249 */ + { { 0x83fbc9c6,0x33eb7cec,0x4541777e,0x24a311c7,0x4f0767fc,0xc81377f7, + 0x4ab702da,0x12adae36,0x2a779696,0xb7fcb6db,0x01cea6ad,0x4a6fb284 }, + { 0xcdfc73de,0x5e8b1d2a,0x1b02fd32,0xd0efae8d,0xd81d8519,0x3f99c190, + 0xfc808971,0x3c18f7fa,0x51b7ae7b,0x41f713e7,0xf07fc3f8,0x0a4b3435 } }, + /* 250 */ + { { 0x019b7d2e,0x7dda3c4c,0xd4dc4b89,0x631c8d1a,0x1cdb313c,0x5489cd6e, + 0x4c07bb06,0xd44aed10,0x75f000d1,0x8f97e13a,0xdda5df4d,0x0e9ee64f }, + { 0x3e346910,0xeaa99f3b,0xfa294ad7,0x622f6921,0x0d0b2fe9,0x22aaa20d, + 0x1e5881ba,0x4fed2f99,0xc1571802,0x9af3b2d6,0xdc7ee17c,0x919e67a8 } }, + /* 251 */ + { { 0x76250533,0xc724fe4c,0x7d817ef8,0x8a2080e5,0x172c9751,0xa2afb0f4, + 0x17c0702e,0x9b10cdeb,0xc9b7e3e9,0xbf3975e3,0x1cd0cdc5,0x206117df }, + { 0xbe05ebd5,0xfb049e61,0x16c782c0,0xeb0bb55c,0xab7fed09,0x13a331b8, + 0x632863f0,0xf6c58b1d,0x4d3b6195,0x6264ef6e,0x9a53f116,0x92c51b63 } }, + /* 252 */ + { { 0x288b364d,0xa57c7bc8,0x7b41e5c4,0x4a562e08,0x698a9a11,0x699d21c6, + 0xf3f849b9,0xa4ed9581,0x9eb726ba,0xa223eef3,0xcc2884f9,0x13159c23 }, + { 0x3a3f4963,0x73931e58,0x0ada6a81,0x96500389,0x5ab2950b,0x3ee8a1c6, + 0x775fab52,0xeedf4949,0x4f2671b6,0x63d652e1,0x3c4e2f55,0xfed4491c } }, + /* 253 */ + { { 0xf4eb453e,0x335eadc3,0xcadd1a5b,0x5ff74b63,0x5d84a91a,0x6933d0d7, + 0xb49ba337,0x9ca3eeb9,0xc04c15b8,0x1f6facce,0xdc09a7e4,0x4ef19326 }, + { 0x3dca3233,0x53d2d324,0xa2259d4b,0x0ee40590,0x5546f002,0x18c22edb, + 0x09ea6b71,0x92429801,0xb0e91e61,0xaada0add,0x99963c50,0x5fe53ef4 } }, + /* 254 */ + { { 0x90c28c65,0x372dd06b,0x119ce47d,0x1765242c,0x6b22fc82,0xc041fb80, + 0xb0a7ccc1,0x667edf07,0x1261bece,0xc79599e7,0x19cff22a,0xbc69d9ba }, + { 0x13c06819,0x009d77cd,0xe282b79d,0x635a66ae,0x225b1be8,0x4edac4a6, + 0x524008f9,0x57d4f4e4,0xb056af84,0xee299ac5,0x3a0bc386,0xcc38444c } }, + /* 255 */ + { { 0xcd4c2356,0x490643b1,0x750547be,0x740a4851,0xd4944c04,0x643eaf29, + 0x299a98a0,0xba572479,0xee05fdf9,0x48b29f16,0x089b2d7b,0x33fb4f61 }, + { 0xa950f955,0x86704902,0xfedc3ddf,0x97e1034d,0x05fbb6a2,0x211320b6, + 0x432299bb,0x23d7b93f,0x8590e4a3,0x1fe1a057,0xf58c0ce6,0x8e1d0586 } }, +}; + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + return sp_384_ecc_mulmod_stripe_12(r, &p384_base, p384_table, + k, map, heap); +} + +#endif + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[12]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_384_point_new_12(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 12, km); + + err = sp_384_ecc_mulmod_base_12(point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_12(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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_384_iszero_12(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] | a[10] | a[11]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +static void sp_384_add_one_12(sp_digit* a) +{ + __asm__ __volatile__ ( + "ldr r1, [%[a], #0]\n\t" + "ldr r2, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "adds r1, r1, #1\n\t" + "adcs r2, r2, #0\n\t" + "adcs r3, r3, #0\n\t" + "adcs r4, r4, #0\n\t" + "str r1, [%[a], #0]\n\t" + "str r2, [%[a], #4]\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r1, [%[a], #16]\n\t" + "ldr r2, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "adcs r1, r1, #0\n\t" + "adcs r2, r2, #0\n\t" + "adcs r3, r3, #0\n\t" + "adcs r4, r4, #0\n\t" + "str r1, [%[a], #16]\n\t" + "str r2, [%[a], #20]\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r1, [%[a], #32]\n\t" + "ldr r2, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "adcs r1, r1, #0\n\t" + "adcs r2, r2, #0\n\t" + "adcs r3, r3, #0\n\t" + "adcs r4, r4, #0\n\t" + "str r1, [%[a], #32]\n\t" + "str r2, [%[a], #36]\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + : + : [a] "r" (a) + : "memory", "r1", "r2", "r3", "r4" + ); +} + +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; 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_384_ecc_gen_k_12(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[48]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_384_from_bin(k, 12, buf, (int)sizeof(buf)); + if (sp_384_cmp_12(k, p384_order2) < 0) { + sp_384_add_one_12(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_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[12]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 inf; +#endif +#endif + sp_point_384* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity; +#endif + int err; + + (void)heap; + + err = sp_384_point_new_12(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + err = sp_384_ecc_gen_k_12(rng, k); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_12(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_12(infinity, point, p384_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_384_iszero_12(point->x) == 0) || (sp_384_iszero_12(point->y) == 0)) { + err = ECC_INF_E; + } + } +#endif + + if (err == MP_OKAY) { + err = sp_384_to_mp(k, priv); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_12(point, pub); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_384_point_free_12(infinity, 1, heap); +#endif + sp_384_point_free_12(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 48 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_384_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 384 / 8 - 1; + a[j] = 0; + for (i=0; i<12 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + 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_384(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[12]; +#endif + sp_point_384* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 48U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(k, 12, priv); + sp_384_point_from_ecc_point_12(point, pub); + err = sp_384_ecc_mulmod_12(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_384_to_bin(point->x, out); + *outLen = 48; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_384_sub_in_place_12(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r14, #0\n\t" + "add r12, %[a], #48\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#else +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_384_sub_in_place_12(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* 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_384_mul_d_12(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #48\n\t" + "blt 1b\n\t" + "str r3, [%[r], #48]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #28]\n\t" + "# A[8] * B\n\t" + "ldr r8, [%[a], #32]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[9] * B\n\t" + "ldr r8, [%[a], #36]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[10] * B\n\t" + "ldr r8, [%[a], #40]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[11] * B\n\t" + "ldr r8, [%[a], #44]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r7\n\t" + "str r5, [%[r], #44]\n\t" + "str r3, [%[r], #48]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_384_word_12(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + 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_384_mask_12(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<12; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; + r[8] = a[8] & m; + r[9] = a[9] & m; + r[10] = a[10] & m; + r[11] = a[11] & 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 WC_INLINE int sp_384_div_12(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[24], t2[13]; + sp_digit div, r1; + int i; + + (void)m; + + + div = d[11]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 12); + for (i=11; i>=0; i--) { + r1 = div_384_word_12(t1[12 + i], t1[12 + i - 1], div); + + sp_384_mul_d_12(t2, d, r1); + t1[12 + i] += sp_384_sub_in_place_12(&t1[i], t2); + t1[12 + i] -= t2[12]; + sp_384_mask_12(t2, d, t1[12 + i]); + t1[12 + i] += sp_384_add_12(&t1[i], &t1[i], t2); + sp_384_mask_12(t2, d, t1[12 + i]); + t1[12 + i] += sp_384_add_12(&t1[i], &t1[i], t2); + } + + r1 = sp_384_cmp_12(t1, d) >= 0; + sp_384_cond_sub_12(r, t1, d, (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 WC_INLINE int sp_384_mod_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_384_div_12(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P384 curve. */ +static const uint32_t p384_order_minus_2[12] = { + 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U, + 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU +}; +#else +/* The low half of the order-2 of the P384 curve. */ +static const uint32_t p384_order_low[6] = { + 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U + +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P384 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_384_mont_mul_order_12(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_384_mul_12(r, a, b); + sp_384_mont_reduce_order_12(r, p384_order, p384_mp_order); +} + +/* Square number mod the order of P384 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_order_12(sp_digit* r, const sp_digit* a) +{ + sp_384_sqr_12(r, a); + sp_384_mont_reduce_order_12(r, p384_order, p384_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P384 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_n_order_12(sp_digit* r, const sp_digit* a, int n) +{ + int i; + + sp_384_mont_sqr_order_12(r, a); + for (i=1; i=0; i--) { + sp_384_mont_sqr_order_12(t, t); + if ((p384_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_384_mont_mul_order_12(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 12U); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 12; + sp_digit* t3 = td + 4 * 12; + int i; + + /* t = a^2 */ + sp_384_mont_sqr_order_12(t, a); + /* t = a^3 = t * a */ + sp_384_mont_mul_order_12(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_384_mont_sqr_n_order_12(t2, t, 2); + /* t = a^f = t2 * t */ + sp_384_mont_mul_order_12(t, t2, t); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_384_mont_sqr_n_order_12(t2, t, 4); + /* t = a^ff = t2 * t */ + sp_384_mont_mul_order_12(t, t2, t); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_384_mont_sqr_n_order_12(t2, t, 8); + /* t3= a^ffff = t2 * t */ + sp_384_mont_mul_order_12(t3, t2, t); + /* t2= a^ffff0000 = t3 ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_12(t2, t3, 16); + /* t = a^ffffffff = t2 * t3 */ + sp_384_mont_mul_order_12(t, t2, t3); + /* t2= a^ffffffff0000 = t ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_12(t2, t, 16); + /* t = a^ffffffffffff = t2 * t3 */ + sp_384_mont_mul_order_12(t, t2, t3); + /* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */ + sp_384_mont_sqr_n_order_12(t2, t, 48); + /* t= a^fffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_12(t, t2, t); + /* t2= a^ffffffffffffffffffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_order_12(t2, t, 96); + /* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_12(t2, t2, t); + for (i=191; i>=1; i--) { + sp_384_mont_sqr_order_12(t2, t2); + if (((sp_digit)p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_384_mont_mul_order_12(t2, t2, a); + } + } + sp_384_mont_sqr_order_12(t2, t2); + sp_384_mont_mul_order_12(r, t2, a); +#endif /* WOLFSSL_SP_SMALL */ +} + +#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, 384 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 384 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_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit ed[2*12]; + sp_digit xd[2*12]; + sp_digit kd[2*12]; + sp_digit rd[2*12]; + sp_digit td[3 * 2*12]; + sp_point_384 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_384* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int32_t c; + int i; + + (void)heap; + + err = sp_384_point_new_12(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 12; + x = d + 2 * 12; + k = d + 4 * 12; + r = d + 6 * 12; + tmp = d + 8 * 12; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(e, 12, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_384_from_mp(x, 12, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_12(rng, k); + } + else { + sp_384_from_mp(k, 12, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_12(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 12U); + sp_384_norm_12(r); + c = sp_384_cmp_12(r, p384_order); + sp_384_cond_sub_12(r, r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(r); + + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_12(k, k, p384_norm_order); + err = sp_384_mod_12(k, k, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_12(k); + /* kInv = 1/k mod order */ + sp_384_mont_inv_order_12(kInv, k, tmp); + sp_384_norm_12(kInv); + + /* s = r * x + e */ + sp_384_mul_12(x, x, r); + err = sp_384_mod_12(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_12(x); + carry = sp_384_add_12(s, e, x); + sp_384_cond_sub_12(s, s, p384_order, 0 - carry); + sp_384_norm_12(s); + c = sp_384_cmp_12(s, p384_order); + sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_12(s, s, kInv); + sp_384_norm_12(s); + + /* Check that signature is usable. */ + if (sp_384_iszero_12(s) == 0) { + break; + } + } + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 12); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U); +#endif + sp_384_point_free_12(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, 384) + * 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 384 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_384(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit u1d[2*12]; + sp_digit u2d[2*12]; + sp_digit sd[2*12]; + sp_digit tmpd[2*12 * 5]; + sp_point_384 p1d; + sp_point_384 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p1; + sp_point_384* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + + err = sp_384_point_new_12(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 12, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 12; + u2 = d + 2 * 12; + s = d + 4 * 12; + tmp = d + 6 * 12; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 12, hash, (int)hashLen); + sp_384_from_mp(u2, 12, r); + sp_384_from_mp(s, 12, sm); + sp_384_from_mp(p2->x, 12, pX); + sp_384_from_mp(p2->y, 12, pY); + sp_384_from_mp(p2->z, 12, pZ); + + { + sp_384_mul_12(s, s, p384_norm_order); + } + err = sp_384_mod_12(s, s, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_12(s); + { + sp_384_mont_inv_order_12(s, s, tmp); + sp_384_mont_mul_order_12(u1, u1, s); + sp_384_mont_mul_order_12(u2, u2, s); + } + + err = sp_384_ecc_mulmod_base_12(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + { + sp_384_proj_point_add_12(p1, p1, p2, tmp); + if (sp_384_iszero_12(p1->z)) { + if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) { + sp_384_proj_point_dbl_12(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + p1->x[8] = 0; + p1->x[9] = 0; + p1->x[10] = 0; + p1->x[11] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + } + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 12, r); + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_12(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 12, r); + carry = sp_384_add_12(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_12(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_12(u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_384_point_free_12(p1, 0, heap); + sp_384_point_free_12(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*12]; + sp_digit t2d[2*12]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 12; + t2 = d + 2 * 12; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_384_sqr_12(t1, point->y); + (void)sp_384_mod_12(t1, t1, p384_mod); + sp_384_sqr_12(t2, point->x); + (void)sp_384_mod_12(t2, t2, p384_mod); + sp_384_mul_12(t2, t2, point->x); + (void)sp_384_mod_12(t2, t2, p384_mod); + (void)sp_384_sub_12(t2, p384_mod, t2); + sp_384_mont_add_12(t1, t1, t2, p384_mod); + + sp_384_mont_add_12(t1, t1, point->x, p384_mod); + sp_384_mont_add_12(t1, t1, point->x, p384_mod); + sp_384_mont_add_12(t1, t1, point->x, p384_mod); + + if (sp_384_cmp_12(t1, p384_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 pubd; +#endif + sp_point_384* pub; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_12(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_384_from_mp(pub->x, 12, pX); + sp_384_from_mp(pub->y, 12, pY); + sp_384_from_bin(pub->z, 12, one, (int)sizeof(one)); + + err = sp_384_ecc_is_point_12(pub, NULL); + } + + sp_384_point_free_12(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[12]; + sp_point_384 pubd; + sp_point_384 pd; +#endif + sp_digit* priv = NULL; + sp_point_384* pub; + sp_point_384* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_12(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_384_from_mp(pub->x, 12, pX); + sp_384_from_mp(pub->y, 12, pY); + sp_384_from_bin(pub->z, 12, one, (int)sizeof(one)); + sp_384_from_mp(priv, 12, privm); + + /* Check point at infinitiy. */ + if ((sp_384_iszero_12(pub->x) != 0) && + (sp_384_iszero_12(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_384_cmp_12(pub->x, p384_mod) >= 0 || + sp_384_cmp_12(pub->y, p384_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_384_ecc_is_point_12(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_384_ecc_mulmod_12(p, pub, p384_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_384_iszero_12(p->x) == 0) || + (sp_384_iszero_12(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_384_ecc_mulmod_base_12(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_384_cmp_12(p->x, pub->x) != 0 || + sp_384_cmp_12(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, heap); + sp_384_point_free_12(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 12 * 5]; + sp_point_384 pd; + sp_point_384 qd; +#endif + sp_digit* tmp; + sp_point_384* p; + sp_point_384* q = NULL; + int err; + + err = sp_384_point_new_12(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_384_point_new_12(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 12, pX); + sp_384_from_mp(p->y, 12, pY); + sp_384_from_mp(p->z, 12, pZ); + sp_384_from_mp(q->x, 12, qX); + sp_384_from_mp(q->y, 12, qY); + sp_384_from_mp(q->z, 12, qZ); + + sp_384_proj_point_add_12(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(q, 0, NULL); + sp_384_point_free_12(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 12 * 2]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_12(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 12, pX); + sp_384_from_mp(p->y, 12, pY); + sp_384_from_mp(p->z, 12, pZ); + + sp_384_proj_point_dbl_12(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 12 * 6]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_12(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 12, pX); + sp_384_from_mp(p->y, 12, pY); + sp_384_from_mp(p->z, 12, pZ); + + sp_384_map_12(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mont_sqrt_12(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 12]; + sp_digit t2d[2 * 12]; + sp_digit t3d[2 * 12]; + sp_digit t4d[2 * 12]; + sp_digit t5d[2 * 12]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 12; + t2 = d + 2 * 12; + t3 = d + 4 * 12; + t4 = d + 6 * 12; + t5 = d + 8 * 12; +#else + t1 = t1d; + t2 = t2d; + t3 = t3d; + t4 = t4d; + t5 = t5d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_384_mont_sqr_12(t2, y, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3 */ + sp_384_mont_mul_12(t1, t2, y, p384_mod, p384_mp_mod); + /* t5 = y ^ 0xc */ + sp_384_mont_sqr_n_12(t5, t1, 2, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xf */ + sp_384_mont_mul_12(t1, t1, t5, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x1e */ + sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x1f */ + sp_384_mont_mul_12(t3, t2, y, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3e0 */ + sp_384_mont_sqr_n_12(t2, t3, 5, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3ff */ + sp_384_mont_mul_12(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fe0 */ + sp_384_mont_sqr_n_12(t2, t1, 5, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x7fff */ + sp_384_mont_mul_12(t3, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fff800 */ + sp_384_mont_sqr_n_12(t2, t3, 15, p384_mod, p384_mp_mod); + /* t4 = y ^ 0x3ffffff */ + sp_384_mont_mul_12(t4, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffc000000 */ + sp_384_mont_sqr_n_12(t2, t4, 30, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffff */ + sp_384_mont_mul_12(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_12(t2, t1, 60, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_12(t2, t1, 120, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_12(t2, t1, 15, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */ + sp_384_mont_sqr_n_12(t2, t1, 31, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */ + sp_384_mont_mul_12(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */ + sp_384_mont_sqr_n_12(t2, t1, 4, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */ + sp_384_mont_mul_12(t1, t5, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */ + sp_384_mont_sqr_n_12(t2, t1, 62, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */ + sp_384_mont_mul_12(t1, y, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */ + sp_384_mont_sqr_n_12(y, t1, 30, p384_mod, p384_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 12]; + sp_digit yd[2 * 12]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 12, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 12; + y = d + 2 * 12; +#else + x = xd; + y = yd; +#endif + + sp_384_from_mp(x, 12, xm); + err = sp_384_mod_mul_norm_12(x, x, p384_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_384_mont_sqr_12(y, x, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(y, y, x, p384_mod, p384_mp_mod); + } + /* y = x^3 - 3x */ + sp_384_mont_sub_12(y, y, x, p384_mod); + sp_384_mont_sub_12(y, y, x, p384_mod); + sp_384_mont_sub_12(y, y, x, p384_mod); + /* y = x^3 - 3x + b */ + err = sp_384_mod_mul_norm_12(x, p384_b, p384_mod); + } + if (err == MP_OKAY) { + sp_384_mont_add_12(y, y, x, p384_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_384_mont_sqrt_12(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 12, 0, 12U * sizeof(sp_digit)); + sp_384_mont_reduce_12(y, p384_mod, p384_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_384_mont_sub_12(y, p384_mod, y, p384_mod); + } + + err = sp_384_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_384 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_SP_ARM32_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_arm64.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_arm64.c new file mode 100644 index 000000000..ebebe2a55 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_arm64.c @@ -0,0 +1,42082 @@ +/* sp.c + * + * Copyright (C) 2006-2020 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 +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifdef WOLFSSL_SP_ARM64_ASM +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j; + byte* d; + + for (i = n - 1,j = 0; i >= 7; i -= 8) { + r[j] = ((sp_digit)a[i - 0] << 0) | + ((sp_digit)a[i - 1] << 8) | + ((sp_digit)a[i - 2] << 16) | + ((sp_digit)a[i - 3] << 24) | + ((sp_digit)a[i - 4] << 32) | + ((sp_digit)a[i - 5] << 40) | + ((sp_digit)a[i - 6] << 48) | + ((sp_digit)a[i - 7] << 56); + j++; + } + + if (i >= 0) { + r[j] = 0; + + d = (byte*)r; + switch (i) { + case 6: d[n - 1 - 6] = a[6]; //fallthrough + case 5: d[n - 1 - 5] = a[5]; //fallthrough + case 4: d[n - 1 - 4] = a[4]; //fallthrough + case 3: d[n - 1 - 3] = a[3]; //fallthrough + case 2: d[n - 1 - 2] = a[2]; //fallthrough + case 1: d[n - 1 - 1] = a[1]; //fallthrough + case 0: d[n - 1 - 0] = a[0]; //fallthrough + } + j++; + } + + for (; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * 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; + + for (i = 31, j = 0; i >= 0; i--) { + a[j++] = r[i] >> 56; + a[j++] = r[i] >> 48; + a[j++] = r[i] >> 40; + a[j++] = r[i] >> 32; + a[j++] = r[i] >> 24; + a[j++] = r[i] >> 16; + a[j++] = r[i] >> 8; + a[j++] = r[i] >> 0; + } +} + +#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_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[8]; + + __asm__ __volatile__ ( + "ldp x9, x10, [%[a], 0]\n\t" + "ldp x11, x12, [%[a], 16]\n\t" + "ldp x13, x14, [%[a], 32]\n\t" + "ldp x15, x16, [%[a], 48]\n\t" + "ldp x17, x19, [%[b], 0]\n\t" + "ldp x20, x21, [%[b], 16]\n\t" + "ldp x22, x23, [%[b], 32]\n\t" + "ldp x24, x25, [%[b], 48]\n\t" + "# A[0] * B[0]\n\t" + "mul x4, x9, x17\n\t" + "umulh x5, x9, x17\n\t" + "str x4, [%[tmp]]\n\t" + "# A[0] * B[1]\n\t" + "mul x7, x9, x19\n\t" + "umulh x8, x9, x19\n\t" + "adds x5, x5, x7\n\t" + "# A[1] * B[0]\n\t" + "mul x7, x10, x17\n\t" + "adc x6, xzr, x8\n\t" + "umulh x8, x10, x17\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[tmp], 8]\n\t" + "adc x4, xzr, xzr\n\t" + "# A[0] * B[2]\n\t" + "mul x7, x9, x20\n\t" + "umulh x8, x9, x20\n\t" + "adds x6, x6, x7\n\t" + "# A[1] * B[1]\n\t" + "mul x7, x10, x19\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x10, x19\n\t" + "adc x5, xzr, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[2] * B[0]\n\t" + "mul x7, x11, x17\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x11, x17\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[tmp], 16]\n\t" + "adc x5, x5, xzr\n\t" + "# A[0] * B[3]\n\t" + "mul x7, x9, x21\n\t" + "umulh x8, x9, x21\n\t" + "adds x4, x4, x7\n\t" + "# A[1] * B[2]\n\t" + "mul x7, x10, x20\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x10, x20\n\t" + "adc x6, xzr, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[2] * B[1]\n\t" + "mul x7, x11, x19\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x11, x19\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[3] * B[0]\n\t" + "mul x7, x12, x17\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x12, x17\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[tmp], 24]\n\t" + "adc x6, x6, xzr\n\t" + "# A[0] * B[4]\n\t" + "mul x7, x9, x22\n\t" + "umulh x8, x9, x22\n\t" + "adds x5, x5, x7\n\t" + "# A[1] * B[3]\n\t" + "mul x7, x10, x21\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x10, x21\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[2] * B[2]\n\t" + "mul x7, x11, x20\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x11, x20\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[3] * B[1]\n\t" + "mul x7, x12, x19\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x12, x19\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[4] * B[0]\n\t" + "mul x7, x13, x17\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x13, x17\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[tmp], 32]\n\t" + "adc x4, x4, xzr\n\t" + "# A[0] * B[5]\n\t" + "mul x7, x9, x23\n\t" + "umulh x8, x9, x23\n\t" + "adds x6, x6, x7\n\t" + "# A[1] * B[4]\n\t" + "mul x7, x10, x22\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x10, x22\n\t" + "adc x5, xzr, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[2] * B[3]\n\t" + "mul x7, x11, x21\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x11, x21\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[3] * B[2]\n\t" + "mul x7, x12, x20\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x12, x20\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[4] * B[1]\n\t" + "mul x7, x13, x19\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x13, x19\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[5] * B[0]\n\t" + "mul x7, x14, x17\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x14, x17\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[tmp], 40]\n\t" + "adc x5, x5, xzr\n\t" + "# A[0] * B[6]\n\t" + "mul x7, x9, x24\n\t" + "umulh x8, x9, x24\n\t" + "adds x4, x4, x7\n\t" + "# A[1] * B[5]\n\t" + "mul x7, x10, x23\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x10, x23\n\t" + "adc x6, xzr, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[2] * B[4]\n\t" + "mul x7, x11, x22\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x11, x22\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[3] * B[3]\n\t" + "mul x7, x12, x21\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x12, x21\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[4] * B[2]\n\t" + "mul x7, x13, x20\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x13, x20\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[5] * B[1]\n\t" + "mul x7, x14, x19\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x14, x19\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[6] * B[0]\n\t" + "mul x7, x15, x17\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x15, x17\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[tmp], 48]\n\t" + "adc x6, x6, xzr\n\t" + "# A[0] * B[7]\n\t" + "mul x7, x9, x25\n\t" + "umulh x8, x9, x25\n\t" + "adds x5, x5, x7\n\t" + "# A[1] * B[6]\n\t" + "mul x7, x10, x24\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x10, x24\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[2] * B[5]\n\t" + "mul x7, x11, x23\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x11, x23\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[3] * B[4]\n\t" + "mul x7, x12, x22\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x12, x22\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[4] * B[3]\n\t" + "mul x7, x13, x21\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x13, x21\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[5] * B[2]\n\t" + "mul x7, x14, x20\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x14, x20\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[6] * B[1]\n\t" + "mul x7, x15, x19\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x15, x19\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[7] * B[0]\n\t" + "mul x7, x16, x17\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x16, x17\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[tmp], 56]\n\t" + "adc x4, x4, xzr\n\t" + "# A[1] * B[7]\n\t" + "mul x7, x10, x25\n\t" + "umulh x8, x10, x25\n\t" + "adds x6, x6, x7\n\t" + "# A[2] * B[6]\n\t" + "mul x7, x11, x24\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x11, x24\n\t" + "adc x5, xzr, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[3] * B[5]\n\t" + "mul x7, x12, x23\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x12, x23\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[4] * B[4]\n\t" + "mul x7, x13, x22\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x13, x22\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[5] * B[3]\n\t" + "mul x7, x14, x21\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x14, x21\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[6] * B[2]\n\t" + "mul x7, x15, x20\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x15, x20\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[7] * B[1]\n\t" + "mul x7, x16, x19\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x16, x19\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[r], 64]\n\t" + "adc x5, x5, xzr\n\t" + "# A[2] * B[7]\n\t" + "mul x7, x11, x25\n\t" + "umulh x8, x11, x25\n\t" + "adds x4, x4, x7\n\t" + "# A[3] * B[6]\n\t" + "mul x7, x12, x24\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x12, x24\n\t" + "adc x6, xzr, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[4] * B[5]\n\t" + "mul x7, x13, x23\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x13, x23\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[5] * B[4]\n\t" + "mul x7, x14, x22\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x14, x22\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[6] * B[3]\n\t" + "mul x7, x15, x21\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x15, x21\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[7] * B[2]\n\t" + "mul x7, x16, x20\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x16, x20\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[r], 72]\n\t" + "adc x6, x6, xzr\n\t" + "# A[3] * B[7]\n\t" + "mul x7, x12, x25\n\t" + "umulh x8, x12, x25\n\t" + "adds x5, x5, x7\n\t" + "# A[4] * B[6]\n\t" + "mul x7, x13, x24\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x13, x24\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[5] * B[5]\n\t" + "mul x7, x14, x23\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x14, x23\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[6] * B[4]\n\t" + "mul x7, x15, x22\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x15, x22\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[7] * B[3]\n\t" + "mul x7, x16, x21\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x16, x21\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[r], 80]\n\t" + "adc x4, x4, xzr\n\t" + "# A[4] * B[7]\n\t" + "mul x7, x13, x25\n\t" + "umulh x8, x13, x25\n\t" + "adds x6, x6, x7\n\t" + "# A[5] * B[6]\n\t" + "mul x7, x14, x24\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x14, x24\n\t" + "adc x5, xzr, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[6] * B[5]\n\t" + "mul x7, x15, x23\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x15, x23\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[7] * B[4]\n\t" + "mul x7, x16, x22\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x16, x22\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[r], 88]\n\t" + "adc x5, x5, xzr\n\t" + "# A[5] * B[7]\n\t" + "mul x7, x14, x25\n\t" + "umulh x8, x14, x25\n\t" + "adds x4, x4, x7\n\t" + "# A[6] * B[6]\n\t" + "mul x7, x15, x24\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x15, x24\n\t" + "adc x6, xzr, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[7] * B[5]\n\t" + "mul x7, x16, x23\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x16, x23\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[r], 96]\n\t" + "adc x6, x6, xzr\n\t" + "# A[6] * B[7]\n\t" + "mul x7, x15, x25\n\t" + "umulh x8, x15, x25\n\t" + "adds x5, x5, x7\n\t" + "# A[7] * B[6]\n\t" + "mul x7, x16, x24\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x16, x24\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[r], 104]\n\t" + "adc x4, x4, xzr\n\t" + "# A[7] * B[7]\n\t" + "mul x7, x16, x25\n\t" + "umulh x8, x16, x25\n\t" + "adds x6, x6, x7\n\t" + "adc x4, x4, x8\n\t" + "stp x6, x4, [%[r], 112]\n\t" + "ldp x9, x10, [%[tmp], 0]\n\t" + "ldp x11, x12, [%[tmp], 16]\n\t" + "ldp x13, x14, [%[tmp], 32]\n\t" + "ldp x15, x16, [%[tmp], 48]\n\t" + "stp x9, x10, [%[r], 0]\n\t" + "stp x11, x12, [%[r], 16]\n\t" + "stp x13, x14, [%[r], 32]\n\t" + "stp x15, x16, [%[r], 48]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25" + ); +} + +/* 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_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x22, x23, [%[a], 0]\n\t" + "ldp x24, x25, [%[a], 16]\n\t" + "ldp x26, x27, [%[a], 32]\n\t" + "ldp x28, x29, [%[a], 48]\n\t" + "# A[0] * A[1]\n\t" + "mul x3, x22, x23\n\t" + "umulh x7, x22, x23\n\t" + "# A[0] * A[2]\n\t" + "mul x4, x22, x24\n\t" + "umulh x5, x22, x24\n\t" + "adds x7, x7, x4\n\t" + "# A[0] * A[3]\n\t" + "mul x4, x22, x25\n\t" + "adc x8, xzr, x5\n\t" + "umulh x5, x22, x25\n\t" + "adds x8, x8, x4\n\t" + "# A[1] * A[2]\n\t" + "mul x4, x23, x24\n\t" + "adc x9, xzr, x5\n\t" + "umulh x5, x23, x24\n\t" + "adds x8, x8, x4\n\t" + "# A[0] * A[4]\n\t" + "mul x4, x22, x26\n\t" + "adcs x9, x9, x5\n\t" + "umulh x5, x22, x26\n\t" + "adc x10, xzr, xzr\n\t" + "adds x9, x9, x4\n\t" + "# A[1] * A[3]\n\t" + "mul x4, x23, x25\n\t" + "adc x10, x10, x5\n\t" + "umulh x5, x23, x25\n\t" + "adds x9, x9, x4\n\t" + "# A[0] * A[5]\n\t" + "mul x4, x22, x27\n\t" + "adcs x10, x10, x5\n\t" + "umulh x5, x22, x27\n\t" + "adc x11, xzr, xzr\n\t" + "adds x10, x10, x4\n\t" + "# A[1] * A[4]\n\t" + "mul x4, x23, x26\n\t" + "adc x11, x11, x5\n\t" + "umulh x5, x23, x26\n\t" + "adds x10, x10, x4\n\t" + "# A[2] * A[3]\n\t" + "mul x4, x24, x25\n\t" + "adcs x11, x11, x5\n\t" + "umulh x5, x24, x25\n\t" + "adc x12, xzr, xzr\n\t" + "adds x10, x10, x4\n\t" + "# A[0] * A[6]\n\t" + "mul x4, x22, x28\n\t" + "adcs x11, x11, x5\n\t" + "umulh x5, x22, x28\n\t" + "adc x12, x12, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * A[5]\n\t" + "mul x4, x23, x27\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x23, x27\n\t" + "adc x13, xzr, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[2] * A[4]\n\t" + "mul x4, x24, x26\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x24, x26\n\t" + "adc x13, x13, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[0] * A[7]\n\t" + "mul x4, x22, x29\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x22, x29\n\t" + "adc x13, x13, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[1] * A[6]\n\t" + "mul x4, x23, x28\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x23, x28\n\t" + "adc x14, xzr, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[2] * A[5]\n\t" + "mul x4, x24, x27\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x24, x27\n\t" + "adc x14, x14, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[3] * A[4]\n\t" + "mul x4, x25, x26\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x25, x26\n\t" + "adc x14, x14, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[1] * A[7]\n\t" + "mul x4, x23, x29\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x23, x29\n\t" + "adc x14, x14, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[2] * A[6]\n\t" + "mul x4, x24, x28\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x24, x28\n\t" + "adc x15, xzr, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[3] * A[5]\n\t" + "mul x4, x25, x27\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x25, x27\n\t" + "adc x15, x15, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[2] * A[7]\n\t" + "mul x4, x24, x29\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x24, x29\n\t" + "adc x15, x15, xzr\n\t" + "adds x14, x14, x4\n\t" + "# A[3] * A[6]\n\t" + "mul x4, x25, x28\n\t" + "adcs x15, x15, x5\n\t" + "umulh x5, x25, x28\n\t" + "adc x16, xzr, xzr\n\t" + "adds x14, x14, x4\n\t" + "# A[4] * A[5]\n\t" + "mul x4, x26, x27\n\t" + "adcs x15, x15, x5\n\t" + "umulh x5, x26, x27\n\t" + "adc x16, x16, xzr\n\t" + "adds x14, x14, x4\n\t" + "# A[3] * A[7]\n\t" + "mul x4, x25, x29\n\t" + "adcs x15, x15, x5\n\t" + "umulh x5, x25, x29\n\t" + "adc x16, x16, xzr\n\t" + "adds x15, x15, x4\n\t" + "# A[4] * A[6]\n\t" + "mul x4, x26, x28\n\t" + "adcs x16, x16, x5\n\t" + "umulh x5, x26, x28\n\t" + "adc x17, xzr, xzr\n\t" + "adds x15, x15, x4\n\t" + "# A[4] * A[7]\n\t" + "mul x4, x26, x29\n\t" + "adcs x16, x16, x5\n\t" + "umulh x5, x26, x29\n\t" + "adc x17, x17, xzr\n\t" + "adds x16, x16, x4\n\t" + "# A[5] * A[6]\n\t" + "mul x4, x27, x28\n\t" + "adcs x17, x17, x5\n\t" + "umulh x5, x27, x28\n\t" + "adc x19, xzr, xzr\n\t" + "adds x16, x16, x4\n\t" + "# A[5] * A[7]\n\t" + "mul x4, x27, x29\n\t" + "adcs x17, x17, x5\n\t" + "umulh x5, x27, x29\n\t" + "adc x19, x19, xzr\n\t" + "adds x17, x17, x4\n\t" + "# A[6] * A[7]\n\t" + "mul x4, x28, x29\n\t" + "adcs x19, x19, x5\n\t" + "umulh x5, x28, x29\n\t" + "adc x20, xzr, xzr\n\t" + "adds x19, x19, x4\n\t" + "adc x20, x20, x5\n\t" + "# Double\n\t" + "adds x3, x3, x3\n\t" + "adcs x7, x7, x7\n\t" + "adcs x8, x8, x8\n\t" + "adcs x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adcs x11, x11, x11\n\t" + "adcs x12, x12, x12\n\t" + "adcs x13, x13, x13\n\t" + "adcs x14, x14, x14\n\t" + "adcs x15, x15, x15\n\t" + "adcs x16, x16, x16\n\t" + "adcs x17, x17, x17\n\t" + "adcs x19, x19, x19\n\t" + "# A[0] * A[0]\n\t" + "mul x2, x22, x22\n\t" + "adcs x20, x20, x20\n\t" + "umulh x4, x22, x22\n\t" + "cset x21, cs\n\t" + "# A[1] * A[1]\n\t" + "mul x5, x23, x23\n\t" + "adds x3, x3, x4\n\t" + "umulh x6, x23, x23\n\t" + "adcs x7, x7, x5\n\t" + "# A[2] * A[2]\n\t" + "mul x4, x24, x24\n\t" + "adcs x8, x8, x6\n\t" + "umulh x5, x24, x24\n\t" + "adcs x9, x9, x4\n\t" + "# A[3] * A[3]\n\t" + "mul x6, x25, x25\n\t" + "adcs x10, x10, x5\n\t" + "umulh x4, x25, x25\n\t" + "adcs x11, x11, x6\n\t" + "# A[4] * A[4]\n\t" + "mul x5, x26, x26\n\t" + "adcs x12, x12, x4\n\t" + "umulh x6, x26, x26\n\t" + "adcs x13, x13, x5\n\t" + "# A[5] * A[5]\n\t" + "mul x4, x27, x27\n\t" + "adcs x14, x14, x6\n\t" + "umulh x5, x27, x27\n\t" + "adcs x15, x15, x4\n\t" + "# A[6] * A[6]\n\t" + "mul x6, x28, x28\n\t" + "adcs x16, x16, x5\n\t" + "umulh x4, x28, x28\n\t" + "adcs x17, x17, x6\n\t" + "# A[7] * A[7]\n\t" + "mul x5, x29, x29\n\t" + "adcs x19, x19, x4\n\t" + "umulh x6, x29, x29\n\t" + "adcs x20, x20, x5\n\t" + "stp x2, x3, [%[r], 0]\n\t" + "adc x21, x21, x6\n\t" + "stp x7, x8, [%[r], 16]\n\t" + "stp x9, x10, [%[r], 32]\n\t" + "stp x11, x12, [%[r], 48]\n\t" + "stp x13, x14, [%[r], 64]\n\t" + "stp x15, x16, [%[r], 80]\n\t" + "stp x17, x19, [%[r], 96]\n\t" + "stp x20, x21, [%[r], 112]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x4", "x5", "x6", "x2", "x3", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29" + ); +} + +/* 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_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +/* 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) +{ + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "subs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "ldp x2, x3, [%[a], 32]\n\t" + "ldp x6, x7, [%[b], 32]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 48]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 48]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 32]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 48]\n\t" + "ldp x2, x3, [%[a], 64]\n\t" + "ldp x6, x7, [%[b], 64]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 80]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 80]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 64]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 80]\n\t" + "ldp x2, x3, [%[a], 96]\n\t" + "ldp x6, x7, [%[b], 96]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 112]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 112]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 96]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 112]\n\t" + "csetm %[a], cc\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return (sp_digit)a; +} + +/* 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) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)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_8(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; +#endif +} + +/* Add digit to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_add_zero_8(sp_digit* r, const sp_digit* a, + const sp_digit d) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adds x3, x3, %[d]\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 48]\n\t" + : + : [r] "r" (r), [a] "r" (a), [d] "r" (d) + : "memory", "x3", "x4", "x5", "x6" + ); +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit b1[8]; + sp_digit z2[16]; + sp_digit u, ca, cb; + + ca = sp_2048_add_8(a1, a, &a[8]); + cb = sp_2048_add_8(b1, b, &b[8]); + u = ca & cb; + sp_2048_mul_8(z1, a1, b1); + sp_2048_mul_8(z2, &a[8], &b[8]); + sp_2048_mul_8(z0, a, b); + sp_2048_mask_8(r + 16, a1, 0 - cb); + sp_2048_mask_8(b1, b1, 0 - ca); + u += sp_2048_add_8(r + 16, r + 16, b1); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + u += sp_2048_add_8(r + 16, r + 16, z2); + sp_2048_add_zero_8(r + 24, z2 + 8, u); +} + +#ifdef WOLFSSL_SP_SMALL +/* Double a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +static sp_digit sp_2048_dbl_8(sp_digit* r, const sp_digit* a) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 64\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "adcs x3, x3, x3\n\t" + "adcs x4, x4, x4\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a) + : + : "memory", "x3", "x4", "x5", "x6", "x11" + ); + + return c; +} + +#else +/* Double a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +static sp_digit sp_2048_dbl_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "adds x3, x3, x3\n\t" + "ldr x5, [%[a], 16]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 24]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 48]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 56]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6" + ); + + return (sp_digit)r; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[16]; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit u; + + u = sp_2048_add_8(a1, a, &a[8]); + sp_2048_sqr_8(z1, a1); + sp_2048_sqr_8(z2, &a[8]); + sp_2048_sqr_8(z0, a); + sp_2048_mask_8(r + 16, a1, 0 - u); + u += sp_2048_dbl_8(r + 16, r + 16); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + u += sp_2048_add_8(r + 16, r + 16, z2); + sp_2048_add_zero_8(r + 24, z2 + 8, u); + +} + +/* 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) +{ + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "subs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "ldp x2, x3, [%[a], 32]\n\t" + "ldp x6, x7, [%[b], 32]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 48]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 48]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 32]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 48]\n\t" + "ldp x2, x3, [%[a], 64]\n\t" + "ldp x6, x7, [%[b], 64]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 80]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 80]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 64]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 80]\n\t" + "ldp x2, x3, [%[a], 96]\n\t" + "ldp x6, x7, [%[b], 96]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 112]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 112]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 96]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 112]\n\t" + "ldp x2, x3, [%[a], 128]\n\t" + "ldp x6, x7, [%[b], 128]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 144]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 144]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 128]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 144]\n\t" + "ldp x2, x3, [%[a], 160]\n\t" + "ldp x6, x7, [%[b], 160]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 176]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 176]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 160]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 176]\n\t" + "ldp x2, x3, [%[a], 192]\n\t" + "ldp x6, x7, [%[b], 192]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 208]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 208]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 192]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 208]\n\t" + "ldp x2, x3, [%[a], 224]\n\t" + "ldp x6, x7, [%[b], 224]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 240]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 240]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 224]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 240]\n\t" + "csetm %[a], cc\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return (sp_digit)a; +} + +/* 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) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 144]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 176]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "ldp x3, x4, [%[a], 192]\n\t" + "ldp x7, x8, [%[b], 192]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 208]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 192]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 208]\n\t" + "ldp x3, x4, [%[a], 224]\n\t" + "ldp x7, x8, [%[b], 224]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 240]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 224]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 240]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)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_16(sp_digit* r, const 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 +} + +/* Add digit to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_add_zero_16(sp_digit* r, const sp_digit* a, + const sp_digit d) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adds x3, x3, %[d]\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 112]\n\t" + : + : [r] "r" (r), [a] "r" (a), [d] "r" (d) + : "memory", "x3", "x4", "x5", "x6" + ); +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE 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); + u += sp_2048_add_16(r + 32, r + 32, z2); + sp_2048_add_zero_16(r + 48, z2 + 16, u); +} + +#ifdef WOLFSSL_SP_SMALL +/* Double a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +static sp_digit sp_2048_dbl_16(sp_digit* r, const sp_digit* a) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 128\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "adcs x3, x3, x3\n\t" + "adcs x4, x4, x4\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a) + : + : "memory", "x3", "x4", "x5", "x6", "x11" + ); + + return c; +} + +#else +/* Double a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +static sp_digit sp_2048_dbl_16(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "adds x3, x3, x3\n\t" + "ldr x5, [%[a], 16]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 24]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 48]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 56]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 80]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 88]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 112]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 120]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6" + ); + + return (sp_digit)r; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE 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_dbl_16(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); + u += sp_2048_add_16(r + 32, r + 32, z2); + sp_2048_add_zero_16(r + 48, z2 + 16, u); + +} + +#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 sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 256\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "adcs x3, x3, x7\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * 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__ ( + "add x10, %[a], 256\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x2, x3, [%[a]]\n\t" + "ldp x4, x5, [%[a], #16]\n\t" + "ldp x6, x7, [%[b]], #16\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x8, x9, [%[b]], #16\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a]], #16\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x10\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +#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_32(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[64]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 248\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 256\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 496\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + 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_32(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[64]; + + __asm__ __volatile__ ( + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "mov x5, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 248\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "cmp x4, x3\n\t" + "b.eq 4f\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[a], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "b.al 5f\n\t" + "\n4:\n\t" + "ldr x10, [%[a], x3]\n\t" + "mul x9, x10, x10\n\t" + "umulh x10, x10, x10\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "\n5:\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 256\n\t" + "b.eq 3f\n\t" + "cmp x3, x4\n\t" + "b.gt 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 496\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<16; i++) { + r[i] = a[i] & m; + } +} + +#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 sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 128\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "adcs x3, x3, x7\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * 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__ ( + "add x10, %[a], 128\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x2, x3, [%[a]]\n\t" + "ldp x4, x5, [%[a], #16]\n\t" + "ldp x6, x7, [%[b]], #16\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x8, x9, [%[b]], #16\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a]], #16\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x10\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +#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_16(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[32]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 120\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 128\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 240\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + 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[32]; + + __asm__ __volatile__ ( + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "mov x5, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 120\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "cmp x4, x3\n\t" + "b.eq 4f\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[a], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "b.al 5f\n\t" + "\n4:\n\t" + "ldr x10, [%[a], x3]\n\t" + "mul x9, x10, x10\n\t" + "umulh x10, x10, x10\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "\n5:\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 128\n\t" + "b.eq 3f\n\t" + "cmp x3, x4\n\t" + "b.gt 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 240\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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; +} + +/* 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, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x5, %[b], x8\n\t" + "umulh x3, %[b], x8\n\t" + "mov x4, 0\n\t" + "str x5, [%[r]]\n\t" + "mov x5, 0\n\t" + "mov x9, #8\n\t" + "1:\n\t" + "ldr x8, [%[a], x9]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], x9]\n\t" + "mov x3, x4\n\t" + "mov x4, x5\n\t" + "mov x5, #0\n\t" + "add x9, x9, #8\n\t" + "cmp x9, 256\n\t" + "b.lt 1b\n\t" + "str x3, [%[r], 256]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#else + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldp x8, x9, [%[a]]\n\t" + "mul x3, %[b], x8\n\t" + "umulh x4, %[b], x8\n\t" + "mov x5, 0\n\t" + "# A[1] * B\n\t" + "str x3, [%[r]]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "umulh x7, %[b], x9\n\t" + "adds x4, x4, x6\n\t" + "# A[2] * B\n\t" + "ldp x8, x9, [%[a], 16]\n\t" + "str x4, [%[r], 8]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[3] * B\n\t" + "str x5, [%[r], 16]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[4] * B\n\t" + "ldp x8, x9, [%[a], 32]\n\t" + "str x3, [%[r], 24]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[5] * B\n\t" + "str x4, [%[r], 32]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[6] * B\n\t" + "ldp x8, x9, [%[a], 48]\n\t" + "str x5, [%[r], 40]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[7] * B\n\t" + "str x3, [%[r], 48]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[8] * B\n\t" + "ldp x8, x9, [%[a], 64]\n\t" + "str x4, [%[r], 56]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[9] * B\n\t" + "str x5, [%[r], 64]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[10] * B\n\t" + "ldp x8, x9, [%[a], 80]\n\t" + "str x3, [%[r], 72]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[11] * B\n\t" + "str x4, [%[r], 80]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[12] * B\n\t" + "ldp x8, x9, [%[a], 96]\n\t" + "str x5, [%[r], 88]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[13] * B\n\t" + "str x3, [%[r], 96]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[14] * B\n\t" + "ldp x8, x9, [%[a], 112]\n\t" + "str x4, [%[r], 104]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[15] * B\n\t" + "str x5, [%[r], 112]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[16] * B\n\t" + "ldp x8, x9, [%[a], 128]\n\t" + "str x3, [%[r], 120]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[17] * B\n\t" + "str x4, [%[r], 128]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[18] * B\n\t" + "ldp x8, x9, [%[a], 144]\n\t" + "str x5, [%[r], 136]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[19] * B\n\t" + "str x3, [%[r], 144]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[20] * B\n\t" + "ldp x8, x9, [%[a], 160]\n\t" + "str x4, [%[r], 152]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[21] * B\n\t" + "str x5, [%[r], 160]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[22] * B\n\t" + "ldp x8, x9, [%[a], 176]\n\t" + "str x3, [%[r], 168]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[23] * B\n\t" + "str x4, [%[r], 176]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[24] * B\n\t" + "ldp x8, x9, [%[a], 192]\n\t" + "str x5, [%[r], 184]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[25] * B\n\t" + "str x3, [%[r], 192]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[26] * B\n\t" + "ldp x8, x9, [%[a], 208]\n\t" + "str x4, [%[r], 200]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[27] * B\n\t" + "str x5, [%[r], 208]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[28] * B\n\t" + "ldp x8, x9, [%[a], 224]\n\t" + "str x3, [%[r], 216]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[29] * B\n\t" + "str x4, [%[r], 224]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[30] * B\n\t" + "ldp x8, x9, [%[a], 240]\n\t" + "str x5, [%[r], 232]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[31] * B\n\t" + "str x3, [%[r], 240]\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "adc x5, x5, x7\n\t" + "stp x4, x5, [%[r], 248]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#endif +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_2048_mont_norm_16(sp_digit* r, const 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, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "csetm %[c], cc\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 128\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return c; +#else + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x11, x12, [%[b], 48]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 48]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 48]\n\t" + "ldp x5, x7, [%[b], 64]\n\t" + "ldp x11, x12, [%[b], 80]\n\t" + "ldp x4, x6, [%[a], 64]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 80]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 64]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 80]\n\t" + "ldp x5, x7, [%[b], 96]\n\t" + "ldp x11, x12, [%[b], 112]\n\t" + "ldp x4, x6, [%[a], 96]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 112]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 96]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 112]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* 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, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "ldp x14, x15, [%[m], 0]\n\t" + "ldp x16, x17, [%[m], 16]\n\t" + "ldp x19, x20, [%[m], 32]\n\t" + "ldp x21, x22, [%[m], 48]\n\t" + "ldp x23, x24, [%[m], 64]\n\t" + "ldp x25, x26, [%[m], 80]\n\t" + "ldp x27, x28, [%[m], 96]\n\t" + "# i = 16\n\t" + "mov x4, 16\n\t" + "ldp x12, x13, [%[a], 0]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul x9, %[mp], x12\n\t" + "# a[i+0] += m[0] * mu\n\t" + "mul x7, x14, x9\n\t" + "umulh x8, x14, x9\n\t" + "adds x12, x12, x7\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mul x7, x15, x9\n\t" + "adc x6, x8, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x12, x13, x7\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr x13, [%[a], 16]\n\t" + "adc x5, x8, xzr\n\t" + "mul x7, x16, x9\n\t" + "adds x12, x12, x6\n\t" + "umulh x8, x16, x9\n\t" + "adc x5, x5, xzr\n\t" + "adds x13, x13, x7\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr x10, [%[a], 24]\n\t" + "adc x6, x8, xzr\n\t" + "mul x7, x17, x9\n\t" + "adds x13, x13, x5\n\t" + "umulh x8, x17, x9\n\t" + "adc x6, x6, xzr\n\t" + "adds x10, x10, x7\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr x11, [%[a], 32]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x19, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x19, x9\n\t" + "str x10, [%[a], 24]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr x10, [%[a], 40]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x20, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x20, x9\n\t" + "str x11, [%[a], 32]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr x11, [%[a], 48]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x21, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x21, x9\n\t" + "str x10, [%[a], 40]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr x10, [%[a], 56]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x22, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x22, x9\n\t" + "str x11, [%[a], 48]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr x11, [%[a], 64]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x23, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x23, x9\n\t" + "str x10, [%[a], 56]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr x10, [%[a], 72]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x24, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x24, x9\n\t" + "str x11, [%[a], 64]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr x11, [%[a], 80]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x25, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x25, x9\n\t" + "str x10, [%[a], 72]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr x10, [%[a], 88]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x26, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x26, x9\n\t" + "str x11, [%[a], 80]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr x11, [%[a], 96]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x27, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x27, x9\n\t" + "str x10, [%[a], 88]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr x10, [%[a], 104]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x28, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x28, x9\n\t" + "str x11, [%[a], 96]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr x11, [%[a], 112]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 112]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 104]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr x10, [%[a], 120]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 120]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x8, x8, %[ca]\n\t" + "str x11, [%[a], 112]\n\t" + "cset %[ca], cs\n\t" + "adds x10, x10, x6\n\t" + "ldr x11, [%[a], 128]\n\t" + "str x10, [%[a], 120]\n\t" + "adcs x11, x11, x8\n\t" + "str x11, [%[a], 128]\n\t" + "adc %[ca], %[ca], xzr\n\t" + "subs x4, x4, 1\n\t" + "add %[a], %[a], 8\n\t" + "bne 1b\n\t" + "stp x12, x13, [%[a], 0]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); + + 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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const 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, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x5, %[b], x8\n\t" + "umulh x3, %[b], x8\n\t" + "mov x4, 0\n\t" + "str x5, [%[r]]\n\t" + "mov x5, 0\n\t" + "mov x9, #8\n\t" + "1:\n\t" + "ldr x8, [%[a], x9]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], x9]\n\t" + "mov x3, x4\n\t" + "mov x4, x5\n\t" + "mov x5, #0\n\t" + "add x9, x9, #8\n\t" + "cmp x9, 128\n\t" + "b.lt 1b\n\t" + "str x3, [%[r], 128]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#else + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldp x8, x9, [%[a]]\n\t" + "mul x3, %[b], x8\n\t" + "umulh x4, %[b], x8\n\t" + "mov x5, 0\n\t" + "# A[1] * B\n\t" + "str x3, [%[r]]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "umulh x7, %[b], x9\n\t" + "adds x4, x4, x6\n\t" + "# A[2] * B\n\t" + "ldp x8, x9, [%[a], 16]\n\t" + "str x4, [%[r], 8]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[3] * B\n\t" + "str x5, [%[r], 16]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[4] * B\n\t" + "ldp x8, x9, [%[a], 32]\n\t" + "str x3, [%[r], 24]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[5] * B\n\t" + "str x4, [%[r], 32]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[6] * B\n\t" + "ldp x8, x9, [%[a], 48]\n\t" + "str x5, [%[r], 40]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[7] * B\n\t" + "str x3, [%[r], 48]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[8] * B\n\t" + "ldp x8, x9, [%[a], 64]\n\t" + "str x4, [%[r], 56]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[9] * B\n\t" + "str x5, [%[r], 64]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[10] * B\n\t" + "ldp x8, x9, [%[a], 80]\n\t" + "str x3, [%[r], 72]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[11] * B\n\t" + "str x4, [%[r], 80]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[12] * B\n\t" + "ldp x8, x9, [%[a], 96]\n\t" + "str x5, [%[r], 88]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[13] * B\n\t" + "str x3, [%[r], 96]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[14] * B\n\t" + "ldp x8, x9, [%[a], 112]\n\t" + "str x4, [%[r], 104]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[15] * B\n\t" + "str x5, [%[r], 112]\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "stp x3, x4, [%[r], 120]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#endif +} + +/* 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__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "sub %[d0], %[d0], x4\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add %[r], x6, x3\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + 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(const sp_digit* a, const sp_digit* b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "mov x5, 120\n\t" + "1:\n\t" + "ldr x6, [%[a], x5]\n\t" + "ldr x7, [%[b], x5]\n\t" + "and x6, x6, x4\n\t" + "and x7, x7, x4\n\t" + "subs x6, x6, x7\n\t" + "csel x2, x3, x2, hi\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "subs x5, x5, #8\n\t" + "b.cs 1b\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "ldp x7, x8, [%[b], 112]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "ldp x7, x8, [%[b], 80]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "ldp x7, x8, [%[b], 48]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 16]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#endif + + return (int64_t)a; +} + +/* 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 WC_INLINE int sp_2048_div_16(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[32], t2[17]; + sp_digit div, r1; + int i; + + (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); + + 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, d, (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 WC_INLINE int sp_2048_mod_16(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_16(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][32]; +#else + sp_digit* t[16]; + 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) * 16 * 32, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 32; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_16(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 16U); + if (reduceA != 0) { + 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); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 4; + if (c == 64) { + c = 60; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 16); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + } + else if (c < 4) { + y = n >> 60; + n = e[i--]; + c = 4 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 60) & 0xf; + n <<= 4; + c -= 4; + } + + 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) * 16U); + 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; +} +#else +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const 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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 32; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_16(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 16U); + if (reduceA != 0) { + 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--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 5; + if (c == 64) { + c = 59; + } + y = (int)(n >> c); + n <<= 64 - c; + 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); + } + + XMEMSET(&r[16], 0, sizeof(sp_digit) * 16U); + 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; +} +#endif /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* 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 single precision number. + */ +static void sp_2048_mont_norm_32(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 32); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_32(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* 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, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "csetm %[c], cc\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 256\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return c; +#else + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x11, x12, [%[b], 48]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 48]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 48]\n\t" + "ldp x5, x7, [%[b], 64]\n\t" + "ldp x11, x12, [%[b], 80]\n\t" + "ldp x4, x6, [%[a], 64]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 80]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 64]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 80]\n\t" + "ldp x5, x7, [%[b], 96]\n\t" + "ldp x11, x12, [%[b], 112]\n\t" + "ldp x4, x6, [%[a], 96]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 112]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 96]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 112]\n\t" + "ldp x5, x7, [%[b], 128]\n\t" + "ldp x11, x12, [%[b], 144]\n\t" + "ldp x4, x6, [%[a], 128]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 144]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 128]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 144]\n\t" + "ldp x5, x7, [%[b], 160]\n\t" + "ldp x11, x12, [%[b], 176]\n\t" + "ldp x4, x6, [%[a], 160]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 176]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 160]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 176]\n\t" + "ldp x5, x7, [%[b], 192]\n\t" + "ldp x11, x12, [%[b], 208]\n\t" + "ldp x4, x6, [%[a], 192]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 208]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 192]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 208]\n\t" + "ldp x5, x7, [%[b], 224]\n\t" + "ldp x11, x12, [%[b], 240]\n\t" + "ldp x4, x6, [%[a], 224]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 240]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 224]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 240]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* 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, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "ldp x14, x15, [%[m], 0]\n\t" + "ldp x16, x17, [%[m], 16]\n\t" + "ldp x19, x20, [%[m], 32]\n\t" + "ldp x21, x22, [%[m], 48]\n\t" + "ldp x23, x24, [%[m], 64]\n\t" + "ldp x25, x26, [%[m], 80]\n\t" + "ldp x27, x28, [%[m], 96]\n\t" + "# i = 32\n\t" + "mov x4, 32\n\t" + "ldp x12, x13, [%[a], 0]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul x9, %[mp], x12\n\t" + "# a[i+0] += m[0] * mu\n\t" + "mul x7, x14, x9\n\t" + "umulh x8, x14, x9\n\t" + "adds x12, x12, x7\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mul x7, x15, x9\n\t" + "adc x6, x8, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x12, x13, x7\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr x13, [%[a], 16]\n\t" + "adc x5, x8, xzr\n\t" + "mul x7, x16, x9\n\t" + "adds x12, x12, x6\n\t" + "umulh x8, x16, x9\n\t" + "adc x5, x5, xzr\n\t" + "adds x13, x13, x7\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr x10, [%[a], 24]\n\t" + "adc x6, x8, xzr\n\t" + "mul x7, x17, x9\n\t" + "adds x13, x13, x5\n\t" + "umulh x8, x17, x9\n\t" + "adc x6, x6, xzr\n\t" + "adds x10, x10, x7\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr x11, [%[a], 32]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x19, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x19, x9\n\t" + "str x10, [%[a], 24]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr x10, [%[a], 40]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x20, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x20, x9\n\t" + "str x11, [%[a], 32]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr x11, [%[a], 48]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x21, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x21, x9\n\t" + "str x10, [%[a], 40]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr x10, [%[a], 56]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x22, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x22, x9\n\t" + "str x11, [%[a], 48]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr x11, [%[a], 64]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x23, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x23, x9\n\t" + "str x10, [%[a], 56]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr x10, [%[a], 72]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x24, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x24, x9\n\t" + "str x11, [%[a], 64]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr x11, [%[a], 80]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x25, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x25, x9\n\t" + "str x10, [%[a], 72]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr x10, [%[a], 88]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x26, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x26, x9\n\t" + "str x11, [%[a], 80]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr x11, [%[a], 96]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x27, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x27, x9\n\t" + "str x10, [%[a], 88]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr x10, [%[a], 104]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x28, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x28, x9\n\t" + "str x11, [%[a], 96]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr x11, [%[a], 112]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 112]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 104]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr x10, [%[a], 120]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 120]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 112]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr x11, [%[a], 128]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 128]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 120]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr x10, [%[a], 136]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 136]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 128]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr x11, [%[a], 144]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 144]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 136]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr x10, [%[a], 152]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 152]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 144]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr x11, [%[a], 160]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 160]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 152]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr x10, [%[a], 168]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 168]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 160]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr x11, [%[a], 176]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 176]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 168]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr x10, [%[a], 184]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 184]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 176]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr x11, [%[a], 192]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 192]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 184]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr x10, [%[a], 200]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 200]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 192]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr x11, [%[a], 208]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 208]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 200]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr x10, [%[a], 216]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 216]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 208]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr x11, [%[a], 224]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 224]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 216]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr x10, [%[a], 232]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 232]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 224]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr x11, [%[a], 240]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 240]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 232]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr x10, [%[a], 248]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 248]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x8, x8, %[ca]\n\t" + "str x11, [%[a], 240]\n\t" + "cset %[ca], cs\n\t" + "adds x10, x10, x6\n\t" + "ldr x11, [%[a], 256]\n\t" + "str x10, [%[a], 248]\n\t" + "adcs x11, x11, x8\n\t" + "str x11, [%[a], 256]\n\t" + "adc %[ca], %[ca], xzr\n\t" + "subs x4, x4, 1\n\t" + "add %[a], %[a], 8\n\t" + "bne 1b\n\t" + "stp x12, x13, [%[a], 0]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); + + 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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_32(r, a); + sp_2048_mont_reduce_32(r, m, mp); +} + +/* 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__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "sub %[d0], %[d0], x4\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add %[r], x6, x3\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + 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, const 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(const sp_digit* a, const sp_digit* b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "mov x5, 248\n\t" + "1:\n\t" + "ldr x6, [%[a], x5]\n\t" + "ldr x7, [%[b], x5]\n\t" + "and x6, x6, x4\n\t" + "and x7, x7, x4\n\t" + "subs x6, x6, x7\n\t" + "csel x2, x3, x2, hi\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "subs x5, x5, #8\n\t" + "b.cs 1b\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "ldp x7, x8, [%[b], 240]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 224]\n\t" + "ldp x7, x8, [%[b], 224]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "ldp x7, x8, [%[b], 208]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 192]\n\t" + "ldp x7, x8, [%[b], 192]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "ldp x7, x8, [%[b], 176]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 160]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "ldp x7, x8, [%[b], 144]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 128]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "ldp x7, x8, [%[b], 112]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "ldp x7, x8, [%[b], 80]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "ldp x7, x8, [%[b], 48]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 16]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#endif + + return (int64_t)a; +} + +/* 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 WC_INLINE int sp_2048_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (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); + + 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, d, (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 WC_INLINE int sp_2048_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_32(a, m, NULL, 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 sp_digit sp_2048_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 256\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#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 sp_digit sp_2048_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "subs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 144]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 176]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "ldp x3, x4, [%[a], 192]\n\t" + "ldp x7, x8, [%[b], 192]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 208]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 192]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 208]\n\t" + "ldp x3, x4, [%[a], 224]\n\t" + "ldp x7, x8, [%[b], 224]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 240]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 224]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 240]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +#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 MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_32_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (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); + + 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); + } + } + + for (i = 31; i > 0; i--) { + if (t1[i] != d[i]) + break; + } + if (t1[i] >= d[i]) { + sp_2048_sub_32(r, t1, d); + } + else { + XMEMCPY(r, t1, sizeof(*t1) * 32); + } + + 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 WC_INLINE int sp_2048_mod_32_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_32_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][64]; +#else + sp_digit* t[16]; + 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) * 16 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 64; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32U); + if (reduceA != 0) { + 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); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 4; + if (c == 64) { + c = 60; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + } + else if (c < 4) { + y = n >> 60; + n = e[i--]; + c = 4 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 60) & 0xf; + n <<= 4; + c -= 4; + } + + 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); + } + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U); + 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; +} +#else +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const 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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 64; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32U); + if (reduceA != 0) { + 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--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 5; + if (c == 64) { + c = 59; + } + y = (int)(n >> c); + n <<= 64 - c; + 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); + } + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U); + 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 /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[64], m[32], r[64]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; +#endif + sp_digit *ah; + sp_digit e[1]; + int err = MP_OKAY; + + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 32 * 2; + m = r + 32 * 2; + } +#endif + + if (err == MP_OKAY) { + ah = a + 32; + + 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) { + 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); + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) + 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 < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 2048) { + err = MP_READ_E; + } + if (inLen > 256) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 32; + m = a + 64; + r = a; + + sp_2048_from_bin(a, 32, in, inLen); + sp_2048_from_mp(d, 32, dm); + sp_2048_from_mp(m, 32, mm); + err = sp_2048_mod_exp_32(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) * 32); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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 sp_digit sp_2048_cond_add_16(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "cset %[c], cs\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 128\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return c; +#else + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "adds x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x11, x12, [%[b], 48]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 48]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 48]\n\t" + "ldp x5, x7, [%[b], 64]\n\t" + "ldp x11, x12, [%[b], 80]\n\t" + "ldp x4, x6, [%[a], 64]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 80]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 64]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 80]\n\t" + "ldp x5, x7, [%[b], 96]\n\t" + "ldp x11, x12, [%[b], 112]\n\t" + "ldp x4, x6, [%[a], 96]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 112]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 96]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 112]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +#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) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[32 * 2]; + sp_digit p[16], q[16], dp[16]; + sp_digit tmpa[32], tmpb[32]; +#else + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* tmpa; + sp_digit* tmpb; +#endif + sp_digit* r; + sp_digit* qi; + sp_digit* dq; + sp_digit c; + 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 (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 11, NULL, + DYNAMIC_TYPE_RSA); + 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; + + r = t + 32; + } +#else +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + r = a; + qi = dq = dp; +#endif + 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); + + err = sp_2048_mod_exp_16(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 16, dqm); + 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); + c += sp_2048_cond_add_16(tmpa, tmpa, p, c); + sp_2048_cond_add_16(tmpa, tmpa, p, c); + + sp_2048_from_mp(qi, 16, qim); + sp_2048_mul_16(tmpa, tmpa, qi); + err = sp_2048_mod_16(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 16 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + 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)); +#endif + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 32); + r->used = 32; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 64 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && 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 = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_mp(e, 32, exp); + sp_2048_from_mp(m, 32, mod); + + err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_2048 +static void sp_2048_lshift_32(sp_digit* r, sp_digit* a, byte n) +{ + __asm__ __volatile__ ( + "mov x6, 63\n\t" + "sub x6, x6, %[n]\n\t" + "ldr x3, [%[a], 248]\n\t" + "lsr x4, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x4, x4, x6\n\t" + "ldr x2, [%[a], 240]\n\t" + "str x4, [%[r], 256]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 232]\n\t" + "str x3, [%[r], 248]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 224]\n\t" + "str x2, [%[r], 240]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 216]\n\t" + "str x4, [%[r], 232]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 208]\n\t" + "str x3, [%[r], 224]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 200]\n\t" + "str x2, [%[r], 216]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 192]\n\t" + "str x4, [%[r], 208]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 184]\n\t" + "str x3, [%[r], 200]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 176]\n\t" + "str x2, [%[r], 192]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 168]\n\t" + "str x4, [%[r], 184]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 160]\n\t" + "str x3, [%[r], 176]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 152]\n\t" + "str x2, [%[r], 168]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 144]\n\t" + "str x4, [%[r], 160]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 136]\n\t" + "str x3, [%[r], 152]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 128]\n\t" + "str x2, [%[r], 144]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 120]\n\t" + "str x4, [%[r], 136]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 112]\n\t" + "str x3, [%[r], 128]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 104]\n\t" + "str x2, [%[r], 120]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 96]\n\t" + "str x4, [%[r], 112]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 88]\n\t" + "str x3, [%[r], 104]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 80]\n\t" + "str x2, [%[r], 96]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 72]\n\t" + "str x4, [%[r], 88]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 64]\n\t" + "str x3, [%[r], 80]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 56]\n\t" + "str x2, [%[r], 72]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 48]\n\t" + "str x4, [%[r], 64]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 40]\n\t" + "str x3, [%[r], 56]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 32]\n\t" + "str x2, [%[r], 48]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 24]\n\t" + "str x4, [%[r], 40]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 16]\n\t" + "str x3, [%[r], 32]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 8]\n\t" + "str x2, [%[r], 24]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 0]\n\t" + "str x4, [%[r], 16]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "str x2, [%[r]]\n\t" + "str x3, [%[r], 8]\n\t" + : + : [r] "r" (r), [a] "r" (a), [n] "r" (n) + : "memory", "x2", "x3", "x4", "x5", "x6" + ); +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_32(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[64]; + sp_digit td[33]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 97, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 64; +#else + norm = nd; + tmp = td; +#endif + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 6; + if (c == 64) { + c = 58; + } + y = (int)(n >> c); + n <<= 64 - c; + sp_2048_lshift_32(r, norm, y); + for (; i>=0 || c>=6; ) { + if (c == 0) { + n = e[i--]; + y = n >> 58; + n <<= 6; + c = 58; + } + else if (c < 6) { + y = n >> 58; + n = e[i--]; + c = 6 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 58) & 0x3f; + n <<= 6; + c -= 6; + } + + 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_sqr_32(r, r, m, mp); + + sp_2048_lshift_32(r, r, y); + sp_2048_mul_d_32(tmp, norm, r[32]); + r[32] = 0; + o = sp_2048_add_32(r, r, tmp); + sp_2048_cond_sub_32(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U); + 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 /* HAVE_FFDHE_2048 */ + +/* 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. + * returns 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; + + if (mp_count_bits(base) > 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 256) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (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_FFDHE_2048 + if (base->used == 1 && base->dp[0] == 2 && m[31] == (sp_digit)-1) + err = sp_2048_mod_exp_2_32(r, e, expLen * 8, m); + 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 */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[32], e[16], m[16]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 16, base); + sp_2048_from_mp(e, 16, exp); + sp_2048_from_mp(m, 16, mod); + + err = sp_2048_mod_exp_16(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 16, 0, sizeof(*r) * 16U); + err = sp_2048_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j; + byte* d; + + for (i = n - 1,j = 0; i >= 7; i -= 8) { + r[j] = ((sp_digit)a[i - 0] << 0) | + ((sp_digit)a[i - 1] << 8) | + ((sp_digit)a[i - 2] << 16) | + ((sp_digit)a[i - 3] << 24) | + ((sp_digit)a[i - 4] << 32) | + ((sp_digit)a[i - 5] << 40) | + ((sp_digit)a[i - 6] << 48) | + ((sp_digit)a[i - 7] << 56); + j++; + } + + if (i >= 0) { + r[j] = 0; + + d = (byte*)r; + switch (i) { + case 6: d[n - 1 - 6] = a[6]; //fallthrough + case 5: d[n - 1 - 5] = a[5]; //fallthrough + case 4: d[n - 1 - 4] = a[4]; //fallthrough + case 3: d[n - 1 - 3] = a[3]; //fallthrough + case 2: d[n - 1 - 2] = a[2]; //fallthrough + case 1: d[n - 1 - 1] = a[1]; //fallthrough + case 0: d[n - 1 - 0] = a[0]; //fallthrough + } + j++; + } + + for (; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * 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; + + for (i = 47, j = 0; i >= 0; i--) { + a[j++] = r[i] >> 56; + a[j++] = r[i] >> 48; + a[j++] = r[i] >> 40; + a[j++] = r[i] >> 32; + a[j++] = r[i] >> 24; + a[j++] = r[i] >> 16; + a[j++] = r[i] >> 8; + a[j++] = r[i] >> 0; + } +} + +#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_12(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[12]; + + __asm__ __volatile__ ( + "ldp x10, x11, [%[a], 0]\n\t" + "ldp x12, x13, [%[a], 16]\n\t" + "ldp x14, x15, [%[a], 32]\n\t" + "ldp x16, x17, [%[a], 48]\n\t" + "ldp x19, x20, [%[a], 64]\n\t" + "ldp x21, x22, [%[a], 80]\n\t" + "# A[0] * B[0]\n\t" + "ldr x9, [%[b], 0]\n\t" + "mul x4, x10, x9\n\t" + "umulh x5, x10, x9\n\t" + "mov x6, 0\n\t" + "str x4, [%[tmp]]\n\t" + "# A[0] * B[1]\n\t" + "ldr x9, [%[b], 8]\n\t" + "mul x7, x10, x9\n\t" + "umulh x8, x10, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[1] * B[0]\n\t" + "ldr x9, [%[b], 0]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x11, x9\n\t" + "adc x4, xzr, xzr\n\t" + "umulh x8, x11, x9\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[tmp], 8]\n\t" + "adc x4, x4, xzr\n\t" + "# A[0] * B[2]\n\t" + "ldr x9, [%[b], 16]\n\t" + "mul x7, x10, x9\n\t" + "umulh x8, x10, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[1] * B[1]\n\t" + "ldr x9, [%[b], 8]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x11, x9\n\t" + "adc x5, xzr, xzr\n\t" + "umulh x8, x11, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[2] * B[0]\n\t" + "ldr x9, [%[b], 0]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x12, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x12, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[tmp], 16]\n\t" + "adc x5, x5, xzr\n\t" + "# A[0] * B[3]\n\t" + "ldr x9, [%[b], 24]\n\t" + "mul x7, x10, x9\n\t" + "umulh x8, x10, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[1] * B[2]\n\t" + "ldr x9, [%[b], 16]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x11, x9\n\t" + "adc x6, xzr, xzr\n\t" + "umulh x8, x11, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[2] * B[1]\n\t" + "ldr x9, [%[b], 8]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x12, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x12, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[3] * B[0]\n\t" + "ldr x9, [%[b], 0]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x13, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x13, x9\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[tmp], 24]\n\t" + "adc x6, x6, xzr\n\t" + "# A[0] * B[4]\n\t" + "ldr x9, [%[b], 32]\n\t" + "mul x7, x10, x9\n\t" + "umulh x8, x10, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[1] * B[3]\n\t" + "ldr x9, [%[b], 24]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x11, x9\n\t" + "adc x4, xzr, xzr\n\t" + "umulh x8, x11, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[2] * B[2]\n\t" + "ldr x9, [%[b], 16]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x12, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x12, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[3] * B[1]\n\t" + "ldr x9, [%[b], 8]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x13, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x13, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[4] * B[0]\n\t" + "ldr x9, [%[b], 0]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x14, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x14, x9\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[tmp], 32]\n\t" + "adc x4, x4, xzr\n\t" + "# A[0] * B[5]\n\t" + "ldr x9, [%[b], 40]\n\t" + "mul x7, x10, x9\n\t" + "umulh x8, x10, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[1] * B[4]\n\t" + "ldr x9, [%[b], 32]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x11, x9\n\t" + "adc x5, xzr, xzr\n\t" + "umulh x8, x11, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[2] * B[3]\n\t" + "ldr x9, [%[b], 24]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x12, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x12, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[3] * B[2]\n\t" + "ldr x9, [%[b], 16]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x13, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x13, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[4] * B[1]\n\t" + "ldr x9, [%[b], 8]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x14, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x14, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[5] * B[0]\n\t" + "ldr x9, [%[b], 0]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x15, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[tmp], 40]\n\t" + "adc x5, x5, xzr\n\t" + "# A[0] * B[6]\n\t" + "ldr x9, [%[b], 48]\n\t" + "mul x7, x10, x9\n\t" + "umulh x8, x10, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[1] * B[5]\n\t" + "ldr x9, [%[b], 40]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x11, x9\n\t" + "adc x6, xzr, xzr\n\t" + "umulh x8, x11, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[2] * B[4]\n\t" + "ldr x9, [%[b], 32]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x12, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x12, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[3] * B[3]\n\t" + "ldr x9, [%[b], 24]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x13, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x13, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[4] * B[2]\n\t" + "ldr x9, [%[b], 16]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x14, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x14, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[5] * B[1]\n\t" + "ldr x9, [%[b], 8]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x15, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[6] * B[0]\n\t" + "ldr x9, [%[b], 0]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x16, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x16, x9\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[tmp], 48]\n\t" + "adc x6, x6, xzr\n\t" + "# A[0] * B[7]\n\t" + "ldr x9, [%[b], 56]\n\t" + "mul x7, x10, x9\n\t" + "umulh x8, x10, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[1] * B[6]\n\t" + "ldr x9, [%[b], 48]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x11, x9\n\t" + "adc x4, xzr, xzr\n\t" + "umulh x8, x11, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[2] * B[5]\n\t" + "ldr x9, [%[b], 40]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x12, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x12, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[3] * B[4]\n\t" + "ldr x9, [%[b], 32]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x13, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x13, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[4] * B[3]\n\t" + "ldr x9, [%[b], 24]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x14, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x14, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[5] * B[2]\n\t" + "ldr x9, [%[b], 16]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x15, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[6] * B[1]\n\t" + "ldr x9, [%[b], 8]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x16, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x16, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[7] * B[0]\n\t" + "ldr x9, [%[b], 0]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x17, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x17, x9\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[tmp], 56]\n\t" + "adc x4, x4, xzr\n\t" + "# A[0] * B[8]\n\t" + "ldr x9, [%[b], 64]\n\t" + "mul x7, x10, x9\n\t" + "umulh x8, x10, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[1] * B[7]\n\t" + "ldr x9, [%[b], 56]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x11, x9\n\t" + "adc x5, xzr, xzr\n\t" + "umulh x8, x11, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[2] * B[6]\n\t" + "ldr x9, [%[b], 48]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x12, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x12, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[3] * B[5]\n\t" + "ldr x9, [%[b], 40]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x13, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x13, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[4] * B[4]\n\t" + "ldr x9, [%[b], 32]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x14, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x14, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[5] * B[3]\n\t" + "ldr x9, [%[b], 24]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x15, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[6] * B[2]\n\t" + "ldr x9, [%[b], 16]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x16, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x16, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[7] * B[1]\n\t" + "ldr x9, [%[b], 8]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x17, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x17, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[8] * B[0]\n\t" + "ldr x9, [%[b], 0]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x19, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x19, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[tmp], 64]\n\t" + "adc x5, x5, xzr\n\t" + "# A[0] * B[9]\n\t" + "ldr x9, [%[b], 72]\n\t" + "mul x7, x10, x9\n\t" + "umulh x8, x10, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[1] * B[8]\n\t" + "ldr x9, [%[b], 64]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x11, x9\n\t" + "adc x6, xzr, xzr\n\t" + "umulh x8, x11, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[2] * B[7]\n\t" + "ldr x9, [%[b], 56]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x12, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x12, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[3] * B[6]\n\t" + "ldr x9, [%[b], 48]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x13, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x13, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[4] * B[5]\n\t" + "ldr x9, [%[b], 40]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x14, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x14, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[5] * B[4]\n\t" + "ldr x9, [%[b], 32]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x15, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[6] * B[3]\n\t" + "ldr x9, [%[b], 24]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x16, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x16, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[7] * B[2]\n\t" + "ldr x9, [%[b], 16]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x17, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x17, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[8] * B[1]\n\t" + "ldr x9, [%[b], 8]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x19, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x19, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[9] * B[0]\n\t" + "ldr x9, [%[b], 0]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x20, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[tmp], 72]\n\t" + "adc x6, x6, xzr\n\t" + "# A[0] * B[10]\n\t" + "ldr x9, [%[b], 80]\n\t" + "mul x7, x10, x9\n\t" + "umulh x8, x10, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[1] * B[9]\n\t" + "ldr x9, [%[b], 72]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x11, x9\n\t" + "adc x4, xzr, xzr\n\t" + "umulh x8, x11, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[2] * B[8]\n\t" + "ldr x9, [%[b], 64]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x12, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x12, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[3] * B[7]\n\t" + "ldr x9, [%[b], 56]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x13, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x13, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[4] * B[6]\n\t" + "ldr x9, [%[b], 48]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x14, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x14, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[5] * B[5]\n\t" + "ldr x9, [%[b], 40]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x15, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[6] * B[4]\n\t" + "ldr x9, [%[b], 32]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x16, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x16, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[7] * B[3]\n\t" + "ldr x9, [%[b], 24]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x17, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x17, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[8] * B[2]\n\t" + "ldr x9, [%[b], 16]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x19, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x19, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[9] * B[1]\n\t" + "ldr x9, [%[b], 8]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x20, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[10] * B[0]\n\t" + "ldr x9, [%[b], 0]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x21, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x21, x9\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[tmp], 80]\n\t" + "adc x4, x4, xzr\n\t" + "# A[0] * B[11]\n\t" + "ldr x9, [%[b], 88]\n\t" + "mul x7, x10, x9\n\t" + "umulh x8, x10, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[1] * B[10]\n\t" + "ldr x9, [%[b], 80]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x11, x9\n\t" + "adc x5, xzr, xzr\n\t" + "umulh x8, x11, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[2] * B[9]\n\t" + "ldr x9, [%[b], 72]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x12, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x12, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[3] * B[8]\n\t" + "ldr x9, [%[b], 64]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x13, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x13, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[4] * B[7]\n\t" + "ldr x9, [%[b], 56]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x14, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x14, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[5] * B[6]\n\t" + "ldr x9, [%[b], 48]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x15, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[6] * B[5]\n\t" + "ldr x9, [%[b], 40]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x16, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x16, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[7] * B[4]\n\t" + "ldr x9, [%[b], 32]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x17, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x17, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[8] * B[3]\n\t" + "ldr x9, [%[b], 24]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x19, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x19, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[9] * B[2]\n\t" + "ldr x9, [%[b], 16]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x20, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[10] * B[1]\n\t" + "ldr x9, [%[b], 8]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x21, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x21, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[11] * B[0]\n\t" + "ldr x9, [%[b], 0]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x22, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x22, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[tmp], 88]\n\t" + "adc x5, x5, xzr\n\t" + "# A[1] * B[11]\n\t" + "ldr x9, [%[b], 88]\n\t" + "mul x7, x11, x9\n\t" + "umulh x8, x11, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[2] * B[10]\n\t" + "ldr x9, [%[b], 80]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x12, x9\n\t" + "adc x6, xzr, xzr\n\t" + "umulh x8, x12, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[3] * B[9]\n\t" + "ldr x9, [%[b], 72]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x13, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x13, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[4] * B[8]\n\t" + "ldr x9, [%[b], 64]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x14, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x14, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[5] * B[7]\n\t" + "ldr x9, [%[b], 56]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x15, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[6] * B[6]\n\t" + "ldr x9, [%[b], 48]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x16, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x16, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[7] * B[5]\n\t" + "ldr x9, [%[b], 40]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x17, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x17, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[8] * B[4]\n\t" + "ldr x9, [%[b], 32]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x19, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x19, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[9] * B[3]\n\t" + "ldr x9, [%[b], 24]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x20, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[10] * B[2]\n\t" + "ldr x9, [%[b], 16]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x21, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x21, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[11] * B[1]\n\t" + "ldr x9, [%[b], 8]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x22, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x22, x9\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[r], 96]\n\t" + "adc x6, x6, xzr\n\t" + "# A[2] * B[11]\n\t" + "ldr x9, [%[b], 88]\n\t" + "mul x7, x12, x9\n\t" + "umulh x8, x12, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[3] * B[10]\n\t" + "ldr x9, [%[b], 80]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x13, x9\n\t" + "adc x4, xzr, xzr\n\t" + "umulh x8, x13, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[4] * B[9]\n\t" + "ldr x9, [%[b], 72]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x14, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x14, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[5] * B[8]\n\t" + "ldr x9, [%[b], 64]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x15, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[6] * B[7]\n\t" + "ldr x9, [%[b], 56]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x16, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x16, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[7] * B[6]\n\t" + "ldr x9, [%[b], 48]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x17, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x17, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[8] * B[5]\n\t" + "ldr x9, [%[b], 40]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x19, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x19, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[9] * B[4]\n\t" + "ldr x9, [%[b], 32]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x20, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[10] * B[3]\n\t" + "ldr x9, [%[b], 24]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x21, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x21, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[11] * B[2]\n\t" + "ldr x9, [%[b], 16]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x22, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x22, x9\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[r], 104]\n\t" + "adc x4, x4, xzr\n\t" + "# A[3] * B[11]\n\t" + "ldr x9, [%[b], 88]\n\t" + "mul x7, x13, x9\n\t" + "umulh x8, x13, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[4] * B[10]\n\t" + "ldr x9, [%[b], 80]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x14, x9\n\t" + "adc x5, xzr, xzr\n\t" + "umulh x8, x14, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[5] * B[9]\n\t" + "ldr x9, [%[b], 72]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x15, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[6] * B[8]\n\t" + "ldr x9, [%[b], 64]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x16, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x16, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[7] * B[7]\n\t" + "ldr x9, [%[b], 56]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x17, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x17, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[8] * B[6]\n\t" + "ldr x9, [%[b], 48]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x19, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x19, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[9] * B[5]\n\t" + "ldr x9, [%[b], 40]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x20, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[10] * B[4]\n\t" + "ldr x9, [%[b], 32]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x21, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x21, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[11] * B[3]\n\t" + "ldr x9, [%[b], 24]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x22, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x22, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[r], 112]\n\t" + "adc x5, x5, xzr\n\t" + "# A[4] * B[11]\n\t" + "ldr x9, [%[b], 88]\n\t" + "mul x7, x14, x9\n\t" + "umulh x8, x14, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[5] * B[10]\n\t" + "ldr x9, [%[b], 80]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x15, x9\n\t" + "adc x6, xzr, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[6] * B[9]\n\t" + "ldr x9, [%[b], 72]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x16, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x16, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[7] * B[8]\n\t" + "ldr x9, [%[b], 64]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x17, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x17, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[8] * B[7]\n\t" + "ldr x9, [%[b], 56]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x19, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x19, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[9] * B[6]\n\t" + "ldr x9, [%[b], 48]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x20, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[10] * B[5]\n\t" + "ldr x9, [%[b], 40]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x21, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x21, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[11] * B[4]\n\t" + "ldr x9, [%[b], 32]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x22, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x22, x9\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[r], 120]\n\t" + "adc x6, x6, xzr\n\t" + "# A[5] * B[11]\n\t" + "ldr x9, [%[b], 88]\n\t" + "mul x7, x15, x9\n\t" + "umulh x8, x15, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[6] * B[10]\n\t" + "ldr x9, [%[b], 80]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x16, x9\n\t" + "adc x4, xzr, xzr\n\t" + "umulh x8, x16, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[7] * B[9]\n\t" + "ldr x9, [%[b], 72]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x17, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x17, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[8] * B[8]\n\t" + "ldr x9, [%[b], 64]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x19, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x19, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[9] * B[7]\n\t" + "ldr x9, [%[b], 56]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x20, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[10] * B[6]\n\t" + "ldr x9, [%[b], 48]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x21, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x21, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[11] * B[5]\n\t" + "ldr x9, [%[b], 40]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x22, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x22, x9\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[r], 128]\n\t" + "adc x4, x4, xzr\n\t" + "# A[6] * B[11]\n\t" + "ldr x9, [%[b], 88]\n\t" + "mul x7, x16, x9\n\t" + "umulh x8, x16, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[7] * B[10]\n\t" + "ldr x9, [%[b], 80]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x17, x9\n\t" + "adc x5, xzr, xzr\n\t" + "umulh x8, x17, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[8] * B[9]\n\t" + "ldr x9, [%[b], 72]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x19, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x19, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[9] * B[8]\n\t" + "ldr x9, [%[b], 64]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x20, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[10] * B[7]\n\t" + "ldr x9, [%[b], 56]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x21, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x21, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[11] * B[6]\n\t" + "ldr x9, [%[b], 48]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x22, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x22, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[r], 136]\n\t" + "adc x5, x5, xzr\n\t" + "# A[7] * B[11]\n\t" + "ldr x9, [%[b], 88]\n\t" + "mul x7, x17, x9\n\t" + "umulh x8, x17, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[8] * B[10]\n\t" + "ldr x9, [%[b], 80]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x19, x9\n\t" + "adc x6, xzr, xzr\n\t" + "umulh x8, x19, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[9] * B[9]\n\t" + "ldr x9, [%[b], 72]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x20, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[10] * B[8]\n\t" + "ldr x9, [%[b], 64]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x21, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x21, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[11] * B[7]\n\t" + "ldr x9, [%[b], 56]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x22, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x22, x9\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[r], 144]\n\t" + "adc x6, x6, xzr\n\t" + "# A[8] * B[11]\n\t" + "ldr x9, [%[b], 88]\n\t" + "mul x7, x19, x9\n\t" + "umulh x8, x19, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[9] * B[10]\n\t" + "ldr x9, [%[b], 80]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x20, x9\n\t" + "adc x4, xzr, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[10] * B[9]\n\t" + "ldr x9, [%[b], 72]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x21, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x21, x9\n\t" + "adds x5, x5, x7\n\t" + "# A[11] * B[8]\n\t" + "ldr x9, [%[b], 64]\n\t" + "adcs x6, x6, x8\n\t" + "mul x7, x22, x9\n\t" + "adc x4, x4, xzr\n\t" + "umulh x8, x22, x9\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[r], 152]\n\t" + "adc x4, x4, xzr\n\t" + "# A[9] * B[11]\n\t" + "ldr x9, [%[b], 88]\n\t" + "mul x7, x20, x9\n\t" + "umulh x8, x20, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[10] * B[10]\n\t" + "ldr x9, [%[b], 80]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x21, x9\n\t" + "adc x5, xzr, xzr\n\t" + "umulh x8, x21, x9\n\t" + "adds x6, x6, x7\n\t" + "# A[11] * B[9]\n\t" + "ldr x9, [%[b], 72]\n\t" + "adcs x4, x4, x8\n\t" + "mul x7, x22, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x22, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[r], 160]\n\t" + "adc x5, x5, xzr\n\t" + "# A[10] * B[11]\n\t" + "ldr x9, [%[b], 88]\n\t" + "mul x7, x21, x9\n\t" + "umulh x8, x21, x9\n\t" + "adds x4, x4, x7\n\t" + "# A[11] * B[10]\n\t" + "ldr x9, [%[b], 80]\n\t" + "adcs x5, x5, x8\n\t" + "mul x7, x22, x9\n\t" + "adc x6, xzr, xzr\n\t" + "umulh x8, x22, x9\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[r], 168]\n\t" + "adc x6, x6, xzr\n\t" + "# A[11] * B[11]\n\t" + "ldr x9, [%[b], 88]\n\t" + "mul x7, x22, x9\n\t" + "umulh x8, x22, x9\n\t" + "adds x5, x5, x7\n\t" + "adc x6, x6, x8\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "ldp x10, x11, [%[tmp], 0]\n\t" + "ldp x12, x13, [%[tmp], 16]\n\t" + "ldp x14, x15, [%[tmp], 32]\n\t" + "ldp x16, x17, [%[tmp], 48]\n\t" + "ldp x19, x20, [%[tmp], 64]\n\t" + "ldp x21, x22, [%[tmp], 80]\n\t" + "stp x10, x11, [%[r], 0]\n\t" + "stp x12, x13, [%[r], 16]\n\t" + "stp x14, x15, [%[r], 32]\n\t" + "stp x16, x17, [%[r], 48]\n\t" + "stp x19, x20, [%[r], 64]\n\t" + "stp x21, x22, [%[r], 80]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22" + ); +} + +/* 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_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x10, x11, [%[a], 0]\n\t" + "ldp x12, x13, [%[a], 16]\n\t" + "ldp x14, x15, [%[a], 32]\n\t" + "ldp x16, x17, [%[a], 48]\n\t" + "ldp x19, x20, [%[a], 64]\n\t" + "ldp x21, x22, [%[a], 80]\n\t" + "# A[0] * A[0]\n\t" + "mul x2, x10, x10\n\t" + "umulh x3, x10, x10\n\t" + "str x2, [%[r]]\n\t" + "mov x4, 0\n\t" + "# A[0] * A[1]\n\t" + "mul x8, x10, x11\n\t" + "umulh x9, x10, x11\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, xzr, xzr\n\t" + "adds x3, x3, x8\n\t" + "str x3, [%[r], 8]\n\t" + "# A[0] * A[2]\n\t" + "mul x8, x10, x12\n\t" + "adcs x4, x4, x9\n\t" + "umulh x9, x10, x12\n\t" + "adc x2, x2, xzr\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x8\n\t" + "# A[1] * A[1]\n\t" + "mul x8, x11, x11\n\t" + "adcs x2, x2, x9\n\t" + "umulh x9, x11, x11\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x8\n\t" + "str x4, [%[r], 16]\n\t" + "# A[0] * A[3]\n\t" + "mul x8, x10, x13\n\t" + "adcs x2, x2, x9\n\t" + "umulh x9, x10, x13\n\t" + "adc x3, x3, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x2, x2, x8\n\t" + "# A[1] * A[2]\n\t" + "mul x8, x11, x12\n\t" + "adcs x3, x3, x9\n\t" + "umulh x9, x11, x12\n\t" + "adc x4, x4, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "adds x2, x2, x8\n\t" + "str x2, [%[r], 24]\n\t" + "# A[0] * A[4]\n\t" + "mul x8, x10, x14\n\t" + "adcs x3, x3, x9\n\t" + "umulh x9, x10, x14\n\t" + "adc x4, x4, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, xzr, xzr\n\t" + "adds x3, x3, x8\n\t" + "# A[1] * A[3]\n\t" + "mul x8, x11, x13\n\t" + "adcs x4, x4, x9\n\t" + "umulh x9, x11, x13\n\t" + "adc x2, x2, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "adds x3, x3, x8\n\t" + "# A[2] * A[2]\n\t" + "mul x8, x12, x12\n\t" + "adcs x4, x4, x9\n\t" + "umulh x9, x12, x12\n\t" + "adc x2, x2, xzr\n\t" + "adds x3, x3, x8\n\t" + "str x3, [%[r], 32]\n\t" + "# A[0] * A[5]\n\t" + "mul x5, x10, x15\n\t" + "adcs x4, x4, x9\n\t" + "umulh x6, x10, x15\n\t" + "adc x2, x2, xzr\n\t" + "mov x3, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[4]\n\t" + "mul x8, x11, x14\n\t" + "umulh x9, x11, x14\n\t" + "adds x5, x5, x8\n\t" + "# A[2] * A[3]\n\t" + "mul x8, x12, x13\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x12, x13\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x4, x4, x5\n\t" + "adcs x2, x2, x6\n\t" + "adc x3, x3, x7\n\t" + "str x4, [%[r], 40]\n\t" + "# A[0] * A[6]\n\t" + "mul x5, x10, x16\n\t" + "umulh x6, x10, x16\n\t" + "mov x4, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[5]\n\t" + "mul x8, x11, x15\n\t" + "umulh x9, x11, x15\n\t" + "adds x5, x5, x8\n\t" + "# A[2] * A[4]\n\t" + "mul x8, x12, x14\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x12, x14\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[3] * A[3]\n\t" + "mul x8, x13, x13\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x13, x13\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x2, x2, x5\n\t" + "adcs x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "str x2, [%[r], 48]\n\t" + "# A[0] * A[7]\n\t" + "mul x5, x10, x17\n\t" + "umulh x6, x10, x17\n\t" + "mov x2, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[6]\n\t" + "mul x8, x11, x16\n\t" + "umulh x9, x11, x16\n\t" + "adds x5, x5, x8\n\t" + "# A[2] * A[5]\n\t" + "mul x8, x12, x15\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x12, x15\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[3] * A[4]\n\t" + "mul x8, x13, x14\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x13, x14\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x3, x3, x5\n\t" + "adcs x4, x4, x6\n\t" + "adc x2, x2, x7\n\t" + "str x3, [%[r], 56]\n\t" + "# A[0] * A[8]\n\t" + "mul x5, x10, x19\n\t" + "umulh x6, x10, x19\n\t" + "mov x3, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[7]\n\t" + "mul x8, x11, x17\n\t" + "umulh x9, x11, x17\n\t" + "adds x5, x5, x8\n\t" + "# A[2] * A[6]\n\t" + "mul x8, x12, x16\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x12, x16\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[3] * A[5]\n\t" + "mul x8, x13, x15\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x13, x15\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[4] * A[4]\n\t" + "mul x8, x14, x14\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x14, x14\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x4, x4, x5\n\t" + "adcs x2, x2, x6\n\t" + "adc x3, x3, x7\n\t" + "str x4, [%[r], 64]\n\t" + "# A[0] * A[9]\n\t" + "mul x5, x10, x20\n\t" + "umulh x6, x10, x20\n\t" + "mov x4, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[8]\n\t" + "mul x8, x11, x19\n\t" + "umulh x9, x11, x19\n\t" + "adds x5, x5, x8\n\t" + "# A[2] * A[7]\n\t" + "mul x8, x12, x17\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x12, x17\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[3] * A[6]\n\t" + "mul x8, x13, x16\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x13, x16\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[4] * A[5]\n\t" + "mul x8, x14, x15\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x14, x15\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x2, x2, x5\n\t" + "adcs x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "str x2, [%[r], 72]\n\t" + "# A[0] * A[10]\n\t" + "mul x5, x10, x21\n\t" + "umulh x6, x10, x21\n\t" + "mov x2, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[9]\n\t" + "mul x8, x11, x20\n\t" + "umulh x9, x11, x20\n\t" + "adds x5, x5, x8\n\t" + "# A[2] * A[8]\n\t" + "mul x8, x12, x19\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x12, x19\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[3] * A[7]\n\t" + "mul x8, x13, x17\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x13, x17\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[4] * A[6]\n\t" + "mul x8, x14, x16\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x14, x16\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[5] * A[5]\n\t" + "mul x8, x15, x15\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x15, x15\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x3, x3, x5\n\t" + "adcs x4, x4, x6\n\t" + "adc x2, x2, x7\n\t" + "str x3, [%[r], 80]\n\t" + "# A[0] * A[11]\n\t" + "mul x5, x10, x22\n\t" + "umulh x6, x10, x22\n\t" + "mov x3, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[10]\n\t" + "mul x8, x11, x21\n\t" + "umulh x9, x11, x21\n\t" + "adds x5, x5, x8\n\t" + "# A[2] * A[9]\n\t" + "mul x8, x12, x20\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x12, x20\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[3] * A[8]\n\t" + "mul x8, x13, x19\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x13, x19\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[4] * A[7]\n\t" + "mul x8, x14, x17\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x14, x17\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[5] * A[6]\n\t" + "mul x8, x15, x16\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x15, x16\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x4, x4, x5\n\t" + "adcs x2, x2, x6\n\t" + "adc x3, x3, x7\n\t" + "str x4, [%[r], 88]\n\t" + "# A[1] * A[11]\n\t" + "mul x5, x11, x22\n\t" + "umulh x6, x11, x22\n\t" + "mov x4, 0\n\t" + "mov x7, 0\n\t" + "# A[2] * A[10]\n\t" + "mul x8, x12, x21\n\t" + "umulh x9, x12, x21\n\t" + "adds x5, x5, x8\n\t" + "# A[3] * A[9]\n\t" + "mul x8, x13, x20\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x13, x20\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[4] * A[8]\n\t" + "mul x8, x14, x19\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x14, x19\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[5] * A[7]\n\t" + "mul x8, x15, x17\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x15, x17\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[6] * A[6]\n\t" + "mul x8, x16, x16\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x16, x16\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x2, x2, x5\n\t" + "adcs x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "str x2, [%[r], 96]\n\t" + "# A[2] * A[11]\n\t" + "mul x5, x12, x22\n\t" + "umulh x6, x12, x22\n\t" + "mov x2, 0\n\t" + "mov x7, 0\n\t" + "# A[3] * A[10]\n\t" + "mul x8, x13, x21\n\t" + "umulh x9, x13, x21\n\t" + "adds x5, x5, x8\n\t" + "# A[4] * A[9]\n\t" + "mul x8, x14, x20\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x14, x20\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[5] * A[8]\n\t" + "mul x8, x15, x19\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x15, x19\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[6] * A[7]\n\t" + "mul x8, x16, x17\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x16, x17\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x3, x3, x5\n\t" + "adcs x4, x4, x6\n\t" + "adc x2, x2, x7\n\t" + "str x3, [%[r], 104]\n\t" + "# A[3] * A[11]\n\t" + "mul x5, x13, x22\n\t" + "umulh x6, x13, x22\n\t" + "mov x3, 0\n\t" + "mov x7, 0\n\t" + "# A[4] * A[10]\n\t" + "mul x8, x14, x21\n\t" + "umulh x9, x14, x21\n\t" + "adds x5, x5, x8\n\t" + "# A[5] * A[9]\n\t" + "mul x8, x15, x20\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x15, x20\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[6] * A[8]\n\t" + "mul x8, x16, x19\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x16, x19\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[7] * A[7]\n\t" + "mul x8, x17, x17\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x17, x17\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x4, x4, x5\n\t" + "adcs x2, x2, x6\n\t" + "adc x3, x3, x7\n\t" + "str x4, [%[r], 112]\n\t" + "# A[4] * A[11]\n\t" + "mul x5, x14, x22\n\t" + "umulh x6, x14, x22\n\t" + "mov x4, 0\n\t" + "mov x7, 0\n\t" + "# A[5] * A[10]\n\t" + "mul x8, x15, x21\n\t" + "umulh x9, x15, x21\n\t" + "adds x5, x5, x8\n\t" + "# A[6] * A[9]\n\t" + "mul x8, x16, x20\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x16, x20\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[7] * A[8]\n\t" + "mul x8, x17, x19\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x17, x19\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x2, x2, x5\n\t" + "adcs x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "str x2, [%[r], 120]\n\t" + "# A[5] * A[11]\n\t" + "mul x5, x15, x22\n\t" + "umulh x6, x15, x22\n\t" + "mov x2, 0\n\t" + "mov x7, 0\n\t" + "# A[6] * A[10]\n\t" + "mul x8, x16, x21\n\t" + "umulh x9, x16, x21\n\t" + "adds x5, x5, x8\n\t" + "# A[7] * A[9]\n\t" + "mul x8, x17, x20\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x17, x20\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "# A[8] * A[8]\n\t" + "mul x8, x19, x19\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x19, x19\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x3, x3, x5\n\t" + "adcs x4, x4, x6\n\t" + "adc x2, x2, x7\n\t" + "str x3, [%[r], 128]\n\t" + "# A[6] * A[11]\n\t" + "mul x5, x16, x22\n\t" + "umulh x6, x16, x22\n\t" + "mov x3, 0\n\t" + "mov x7, 0\n\t" + "# A[7] * A[10]\n\t" + "mul x8, x17, x21\n\t" + "umulh x9, x17, x21\n\t" + "adds x5, x5, x8\n\t" + "# A[8] * A[9]\n\t" + "mul x8, x19, x20\n\t" + "adcs x6, x6, x9\n\t" + "umulh x9, x19, x20\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x4, x4, x5\n\t" + "adcs x2, x2, x6\n\t" + "adc x3, x3, x7\n\t" + "str x4, [%[r], 136]\n\t" + "# A[7] * A[11]\n\t" + "mul x8, x17, x22\n\t" + "umulh x9, x17, x22\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x2, x2, x8\n\t" + "# A[8] * A[10]\n\t" + "mul x8, x19, x21\n\t" + "adcs x3, x3, x9\n\t" + "umulh x9, x19, x21\n\t" + "adc x4, x4, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "adds x2, x2, x8\n\t" + "# A[9] * A[9]\n\t" + "mul x8, x20, x20\n\t" + "adcs x3, x3, x9\n\t" + "umulh x9, x20, x20\n\t" + "adc x4, x4, xzr\n\t" + "adds x2, x2, x8\n\t" + "str x2, [%[r], 144]\n\t" + "# A[8] * A[11]\n\t" + "mul x8, x19, x22\n\t" + "adcs x3, x3, x9\n\t" + "umulh x9, x19, x22\n\t" + "adc x4, x4, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, xzr, xzr\n\t" + "adds x3, x3, x8\n\t" + "# A[9] * A[10]\n\t" + "mul x8, x20, x21\n\t" + "adcs x4, x4, x9\n\t" + "umulh x9, x20, x21\n\t" + "adc x2, x2, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "adds x3, x3, x8\n\t" + "str x3, [%[r], 152]\n\t" + "# A[9] * A[11]\n\t" + "mul x8, x20, x22\n\t" + "adcs x4, x4, x9\n\t" + "umulh x9, x20, x22\n\t" + "adc x2, x2, xzr\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x8\n\t" + "# A[10] * A[10]\n\t" + "mul x8, x21, x21\n\t" + "adcs x2, x2, x9\n\t" + "umulh x9, x21, x21\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x8\n\t" + "str x4, [%[r], 160]\n\t" + "# A[10] * A[11]\n\t" + "mul x8, x21, x22\n\t" + "adcs x2, x2, x9\n\t" + "umulh x9, x21, x22\n\t" + "adc x3, x3, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x2, x2, x8\n\t" + "str x2, [%[r], 168]\n\t" + "# A[11] * A[11]\n\t" + "mul x8, x22, x22\n\t" + "adcs x3, x3, x9\n\t" + "umulh x9, x22, x22\n\t" + "adc x4, x4, xzr\n\t" + "adds x3, x3, x8\n\t" + "adc x4, x4, x9\n\t" + "stp x3, x4, [%[r], 176]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x2", "x3", "x4", "x8", "x9", "x10", "x5", "x6", "x7", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22" + ); +} + +/* 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_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +/* 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) +{ + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "subs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "ldp x2, x3, [%[a], 32]\n\t" + "ldp x6, x7, [%[b], 32]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 48]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 48]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 32]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 48]\n\t" + "ldp x2, x3, [%[a], 64]\n\t" + "ldp x6, x7, [%[b], 64]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 80]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 80]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 64]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 80]\n\t" + "ldp x2, x3, [%[a], 96]\n\t" + "ldp x6, x7, [%[b], 96]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 112]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 112]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 96]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 112]\n\t" + "ldp x2, x3, [%[a], 128]\n\t" + "ldp x6, x7, [%[b], 128]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 144]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 144]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 128]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 144]\n\t" + "ldp x2, x3, [%[a], 160]\n\t" + "ldp x6, x7, [%[b], 160]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 176]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 176]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 160]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 176]\n\t" + "csetm %[a], cc\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return (sp_digit)a; +} + +/* 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) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 144]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 176]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)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_12(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<12; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; + r[8] = a[8] & m; + r[9] = a[9] & m; + r[10] = a[10] & m; + r[11] = a[11] & m; +#endif +} + +/* Add digit to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_add_zero_12(sp_digit* r, const sp_digit* a, + const sp_digit d) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adds x3, x3, %[d]\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 80]\n\t" + : + : [r] "r" (r), [a] "r" (a), [d] "r" (d) + : "memory", "x3", "x4", "x5", "x6" + ); +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[24]; + sp_digit a1[12]; + sp_digit b1[12]; + sp_digit z2[24]; + sp_digit u, ca, cb; + + ca = sp_3072_add_12(a1, a, &a[12]); + cb = sp_3072_add_12(b1, b, &b[12]); + u = ca & cb; + sp_3072_mul_12(z1, a1, b1); + sp_3072_mul_12(z2, &a[12], &b[12]); + sp_3072_mul_12(z0, a, b); + sp_3072_mask_12(r + 24, a1, 0 - cb); + sp_3072_mask_12(b1, b1, 0 - ca); + u += sp_3072_add_12(r + 24, r + 24, b1); + u += sp_3072_sub_in_place_24(z1, z2); + u += sp_3072_sub_in_place_24(z1, z0); + u += sp_3072_add_24(r + 12, r + 12, z1); + u += sp_3072_add_12(r + 24, r + 24, z2); + sp_3072_add_zero_12(r + 36, z2 + 12, u); +} + +#ifdef WOLFSSL_SP_SMALL +/* Double a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +static sp_digit sp_3072_dbl_12(sp_digit* r, const sp_digit* a) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 96\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "adcs x3, x3, x3\n\t" + "adcs x4, x4, x4\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a) + : + : "memory", "x3", "x4", "x5", "x6", "x11" + ); + + return c; +} + +#else +/* Double a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +static sp_digit sp_3072_dbl_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "adds x3, x3, x3\n\t" + "ldr x5, [%[a], 16]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 24]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 48]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 56]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 80]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 88]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6" + ); + + return (sp_digit)r; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[24]; + sp_digit z1[24]; + sp_digit a1[12]; + sp_digit u; + + u = sp_3072_add_12(a1, a, &a[12]); + sp_3072_sqr_12(z1, a1); + sp_3072_sqr_12(z2, &a[12]); + sp_3072_sqr_12(z0, a); + sp_3072_mask_12(r + 24, a1, 0 - u); + u += sp_3072_dbl_12(r + 24, r + 24); + u += sp_3072_sub_in_place_24(z1, z2); + u += sp_3072_sub_in_place_24(z1, z0); + u += sp_3072_add_24(r + 12, r + 12, z1); + u += sp_3072_add_12(r + 24, r + 24, z2); + sp_3072_add_zero_12(r + 36, z2 + 12, u); + +} + +/* 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) +{ + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "subs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "ldp x2, x3, [%[a], 32]\n\t" + "ldp x6, x7, [%[b], 32]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 48]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 48]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 32]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 48]\n\t" + "ldp x2, x3, [%[a], 64]\n\t" + "ldp x6, x7, [%[b], 64]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 80]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 80]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 64]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 80]\n\t" + "ldp x2, x3, [%[a], 96]\n\t" + "ldp x6, x7, [%[b], 96]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 112]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 112]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 96]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 112]\n\t" + "ldp x2, x3, [%[a], 128]\n\t" + "ldp x6, x7, [%[b], 128]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 144]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 144]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 128]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 144]\n\t" + "ldp x2, x3, [%[a], 160]\n\t" + "ldp x6, x7, [%[b], 160]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 176]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 176]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 160]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 176]\n\t" + "ldp x2, x3, [%[a], 192]\n\t" + "ldp x6, x7, [%[b], 192]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 208]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 208]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 192]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 208]\n\t" + "ldp x2, x3, [%[a], 224]\n\t" + "ldp x6, x7, [%[b], 224]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 240]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 240]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 224]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 240]\n\t" + "ldp x2, x3, [%[a], 256]\n\t" + "ldp x6, x7, [%[b], 256]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 272]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 272]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 256]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 272]\n\t" + "ldp x2, x3, [%[a], 288]\n\t" + "ldp x6, x7, [%[b], 288]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 304]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 304]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 288]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 304]\n\t" + "ldp x2, x3, [%[a], 320]\n\t" + "ldp x6, x7, [%[b], 320]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 336]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 336]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 320]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 336]\n\t" + "ldp x2, x3, [%[a], 352]\n\t" + "ldp x6, x7, [%[b], 352]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 368]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 368]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 352]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 368]\n\t" + "csetm %[a], cc\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return (sp_digit)a; +} + +/* 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) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 144]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 176]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "ldp x3, x4, [%[a], 192]\n\t" + "ldp x7, x8, [%[b], 192]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 208]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 192]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 208]\n\t" + "ldp x3, x4, [%[a], 224]\n\t" + "ldp x7, x8, [%[b], 224]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 240]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 224]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 240]\n\t" + "ldp x3, x4, [%[a], 256]\n\t" + "ldp x7, x8, [%[b], 256]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 272]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 272]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 256]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 272]\n\t" + "ldp x3, x4, [%[a], 288]\n\t" + "ldp x7, x8, [%[b], 288]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 304]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 304]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 288]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 304]\n\t" + "ldp x3, x4, [%[a], 320]\n\t" + "ldp x7, x8, [%[b], 320]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 336]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 336]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 320]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 336]\n\t" + "ldp x3, x4, [%[a], 352]\n\t" + "ldp x7, x8, [%[b], 352]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 368]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 368]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 352]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 368]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)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_24(sp_digit* r, const 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 +} + +/* Add digit to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_add_zero_24(sp_digit* r, const sp_digit* a, + const sp_digit d) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adds x3, x3, %[d]\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 176]\n\t" + : + : [r] "r" (r), [a] "r" (a), [d] "r" (d) + : "memory", "x3", "x4", "x5", "x6" + ); +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE 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); + u += sp_3072_add_24(r + 48, r + 48, z2); + sp_3072_add_zero_24(r + 72, z2 + 24, u); +} + +#ifdef WOLFSSL_SP_SMALL +/* Double a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +static sp_digit sp_3072_dbl_24(sp_digit* r, const sp_digit* a) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 192\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "adcs x3, x3, x3\n\t" + "adcs x4, x4, x4\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a) + : + : "memory", "x3", "x4", "x5", "x6", "x11" + ); + + return c; +} + +#else +/* Double a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +static sp_digit sp_3072_dbl_24(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "adds x3, x3, x3\n\t" + "ldr x5, [%[a], 16]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 24]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 48]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 56]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 80]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 88]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 112]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 120]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 144]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 152]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 176]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 184]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6" + ); + + return (sp_digit)r; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE 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_dbl_24(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); + u += sp_3072_add_24(r + 48, r + 48, z2); + sp_3072_add_zero_24(r + 72, z2 + 24, u); + +} + +#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 sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 384\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "adcs x3, x3, x7\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * 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__ ( + "add x10, %[a], 384\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x2, x3, [%[a]]\n\t" + "ldp x4, x5, [%[a], #16]\n\t" + "ldp x6, x7, [%[b]], #16\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x8, x9, [%[b]], #16\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a]], #16\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x10\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +#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_48(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[96]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 376\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 384\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 752\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + 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_48(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[96]; + + __asm__ __volatile__ ( + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "mov x5, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 376\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "cmp x4, x3\n\t" + "b.eq 4f\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[a], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "b.al 5f\n\t" + "\n4:\n\t" + "ldr x10, [%[a], x3]\n\t" + "mul x9, x10, x10\n\t" + "umulh x10, x10, x10\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "\n5:\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 384\n\t" + "b.eq 3f\n\t" + "cmp x3, x4\n\t" + "b.gt 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 752\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<24; i++) { + r[i] = a[i] & m; + } +} + +#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 sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 192\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "adcs x3, x3, x7\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * 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__ ( + "add x10, %[a], 192\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x2, x3, [%[a]]\n\t" + "ldp x4, x5, [%[a], #16]\n\t" + "ldp x6, x7, [%[b]], #16\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x8, x9, [%[b]], #16\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a]], #16\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x10\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +#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_24(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[48]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 184\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 192\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 368\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + 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[48]; + + __asm__ __volatile__ ( + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "mov x5, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 184\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "cmp x4, x3\n\t" + "b.eq 4f\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[a], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "b.al 5f\n\t" + "\n4:\n\t" + "ldr x10, [%[a], x3]\n\t" + "mul x9, x10, x10\n\t" + "umulh x10, x10, x10\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "\n5:\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 192\n\t" + "b.eq 3f\n\t" + "cmp x3, x4\n\t" + "b.gt 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 368\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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; +} + +/* 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, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x5, %[b], x8\n\t" + "umulh x3, %[b], x8\n\t" + "mov x4, 0\n\t" + "str x5, [%[r]]\n\t" + "mov x5, 0\n\t" + "mov x9, #8\n\t" + "1:\n\t" + "ldr x8, [%[a], x9]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], x9]\n\t" + "mov x3, x4\n\t" + "mov x4, x5\n\t" + "mov x5, #0\n\t" + "add x9, x9, #8\n\t" + "cmp x9, 384\n\t" + "b.lt 1b\n\t" + "str x3, [%[r], 384]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#else + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldp x8, x9, [%[a]]\n\t" + "mul x3, %[b], x8\n\t" + "umulh x4, %[b], x8\n\t" + "mov x5, 0\n\t" + "# A[1] * B\n\t" + "str x3, [%[r]]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "umulh x7, %[b], x9\n\t" + "adds x4, x4, x6\n\t" + "# A[2] * B\n\t" + "ldp x8, x9, [%[a], 16]\n\t" + "str x4, [%[r], 8]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[3] * B\n\t" + "str x5, [%[r], 16]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[4] * B\n\t" + "ldp x8, x9, [%[a], 32]\n\t" + "str x3, [%[r], 24]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[5] * B\n\t" + "str x4, [%[r], 32]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[6] * B\n\t" + "ldp x8, x9, [%[a], 48]\n\t" + "str x5, [%[r], 40]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[7] * B\n\t" + "str x3, [%[r], 48]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[8] * B\n\t" + "ldp x8, x9, [%[a], 64]\n\t" + "str x4, [%[r], 56]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[9] * B\n\t" + "str x5, [%[r], 64]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[10] * B\n\t" + "ldp x8, x9, [%[a], 80]\n\t" + "str x3, [%[r], 72]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[11] * B\n\t" + "str x4, [%[r], 80]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[12] * B\n\t" + "ldp x8, x9, [%[a], 96]\n\t" + "str x5, [%[r], 88]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[13] * B\n\t" + "str x3, [%[r], 96]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[14] * B\n\t" + "ldp x8, x9, [%[a], 112]\n\t" + "str x4, [%[r], 104]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[15] * B\n\t" + "str x5, [%[r], 112]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[16] * B\n\t" + "ldp x8, x9, [%[a], 128]\n\t" + "str x3, [%[r], 120]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[17] * B\n\t" + "str x4, [%[r], 128]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[18] * B\n\t" + "ldp x8, x9, [%[a], 144]\n\t" + "str x5, [%[r], 136]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[19] * B\n\t" + "str x3, [%[r], 144]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[20] * B\n\t" + "ldp x8, x9, [%[a], 160]\n\t" + "str x4, [%[r], 152]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[21] * B\n\t" + "str x5, [%[r], 160]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[22] * B\n\t" + "ldp x8, x9, [%[a], 176]\n\t" + "str x3, [%[r], 168]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[23] * B\n\t" + "str x4, [%[r], 176]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[24] * B\n\t" + "ldp x8, x9, [%[a], 192]\n\t" + "str x5, [%[r], 184]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[25] * B\n\t" + "str x3, [%[r], 192]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[26] * B\n\t" + "ldp x8, x9, [%[a], 208]\n\t" + "str x4, [%[r], 200]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[27] * B\n\t" + "str x5, [%[r], 208]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[28] * B\n\t" + "ldp x8, x9, [%[a], 224]\n\t" + "str x3, [%[r], 216]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[29] * B\n\t" + "str x4, [%[r], 224]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[30] * B\n\t" + "ldp x8, x9, [%[a], 240]\n\t" + "str x5, [%[r], 232]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[31] * B\n\t" + "str x3, [%[r], 240]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[32] * B\n\t" + "ldp x8, x9, [%[a], 256]\n\t" + "str x4, [%[r], 248]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[33] * B\n\t" + "str x5, [%[r], 256]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[34] * B\n\t" + "ldp x8, x9, [%[a], 272]\n\t" + "str x3, [%[r], 264]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[35] * B\n\t" + "str x4, [%[r], 272]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[36] * B\n\t" + "ldp x8, x9, [%[a], 288]\n\t" + "str x5, [%[r], 280]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[37] * B\n\t" + "str x3, [%[r], 288]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[38] * B\n\t" + "ldp x8, x9, [%[a], 304]\n\t" + "str x4, [%[r], 296]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[39] * B\n\t" + "str x5, [%[r], 304]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[40] * B\n\t" + "ldp x8, x9, [%[a], 320]\n\t" + "str x3, [%[r], 312]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[41] * B\n\t" + "str x4, [%[r], 320]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[42] * B\n\t" + "ldp x8, x9, [%[a], 336]\n\t" + "str x5, [%[r], 328]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[43] * B\n\t" + "str x3, [%[r], 336]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[44] * B\n\t" + "ldp x8, x9, [%[a], 352]\n\t" + "str x4, [%[r], 344]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[45] * B\n\t" + "str x5, [%[r], 352]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[46] * B\n\t" + "ldp x8, x9, [%[a], 368]\n\t" + "str x3, [%[r], 360]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[47] * B\n\t" + "str x4, [%[r], 368]\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "adc x3, x3, x7\n\t" + "stp x5, x3, [%[r], 376]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#endif +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_3072_mont_norm_24(sp_digit* r, const 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, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "csetm %[c], cc\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 192\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return c; +#else + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x11, x12, [%[b], 48]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 48]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 48]\n\t" + "ldp x5, x7, [%[b], 64]\n\t" + "ldp x11, x12, [%[b], 80]\n\t" + "ldp x4, x6, [%[a], 64]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 80]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 64]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 80]\n\t" + "ldp x5, x7, [%[b], 96]\n\t" + "ldp x11, x12, [%[b], 112]\n\t" + "ldp x4, x6, [%[a], 96]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 112]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 96]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 112]\n\t" + "ldp x5, x7, [%[b], 128]\n\t" + "ldp x11, x12, [%[b], 144]\n\t" + "ldp x4, x6, [%[a], 128]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 144]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 128]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 144]\n\t" + "ldp x5, x7, [%[b], 160]\n\t" + "ldp x11, x12, [%[b], 176]\n\t" + "ldp x4, x6, [%[a], 160]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 176]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 160]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 176]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* 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, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "ldp x14, x15, [%[m], 0]\n\t" + "ldp x16, x17, [%[m], 16]\n\t" + "ldp x19, x20, [%[m], 32]\n\t" + "ldp x21, x22, [%[m], 48]\n\t" + "ldp x23, x24, [%[m], 64]\n\t" + "ldp x25, x26, [%[m], 80]\n\t" + "ldp x27, x28, [%[m], 96]\n\t" + "# i = 24\n\t" + "mov x4, 24\n\t" + "ldp x12, x13, [%[a], 0]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul x9, %[mp], x12\n\t" + "# a[i+0] += m[0] * mu\n\t" + "mul x7, x14, x9\n\t" + "umulh x8, x14, x9\n\t" + "adds x12, x12, x7\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mul x7, x15, x9\n\t" + "adc x6, x8, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x12, x13, x7\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr x13, [%[a], 16]\n\t" + "adc x5, x8, xzr\n\t" + "mul x7, x16, x9\n\t" + "adds x12, x12, x6\n\t" + "umulh x8, x16, x9\n\t" + "adc x5, x5, xzr\n\t" + "adds x13, x13, x7\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr x10, [%[a], 24]\n\t" + "adc x6, x8, xzr\n\t" + "mul x7, x17, x9\n\t" + "adds x13, x13, x5\n\t" + "umulh x8, x17, x9\n\t" + "adc x6, x6, xzr\n\t" + "adds x10, x10, x7\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr x11, [%[a], 32]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x19, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x19, x9\n\t" + "str x10, [%[a], 24]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr x10, [%[a], 40]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x20, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x20, x9\n\t" + "str x11, [%[a], 32]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr x11, [%[a], 48]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x21, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x21, x9\n\t" + "str x10, [%[a], 40]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr x10, [%[a], 56]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x22, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x22, x9\n\t" + "str x11, [%[a], 48]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr x11, [%[a], 64]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x23, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x23, x9\n\t" + "str x10, [%[a], 56]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr x10, [%[a], 72]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x24, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x24, x9\n\t" + "str x11, [%[a], 64]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr x11, [%[a], 80]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x25, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x25, x9\n\t" + "str x10, [%[a], 72]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr x10, [%[a], 88]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x26, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x26, x9\n\t" + "str x11, [%[a], 80]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr x11, [%[a], 96]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x27, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x27, x9\n\t" + "str x10, [%[a], 88]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr x10, [%[a], 104]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x28, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x28, x9\n\t" + "str x11, [%[a], 96]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr x11, [%[a], 112]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 112]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 104]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr x10, [%[a], 120]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 120]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 112]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr x11, [%[a], 128]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 128]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 120]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr x10, [%[a], 136]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 136]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 128]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr x11, [%[a], 144]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 144]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 136]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr x10, [%[a], 152]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 152]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 144]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr x11, [%[a], 160]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 160]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 152]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr x10, [%[a], 168]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 168]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 160]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr x11, [%[a], 176]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 176]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 168]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr x10, [%[a], 184]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 184]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x8, x8, %[ca]\n\t" + "str x11, [%[a], 176]\n\t" + "cset %[ca], cs\n\t" + "adds x10, x10, x6\n\t" + "ldr x11, [%[a], 192]\n\t" + "str x10, [%[a], 184]\n\t" + "adcs x11, x11, x8\n\t" + "str x11, [%[a], 192]\n\t" + "adc %[ca], %[ca], xzr\n\t" + "subs x4, x4, 1\n\t" + "add %[a], %[a], 8\n\t" + "bne 1b\n\t" + "stp x12, x13, [%[a], 0]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); + + 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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const 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, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x5, %[b], x8\n\t" + "umulh x3, %[b], x8\n\t" + "mov x4, 0\n\t" + "str x5, [%[r]]\n\t" + "mov x5, 0\n\t" + "mov x9, #8\n\t" + "1:\n\t" + "ldr x8, [%[a], x9]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], x9]\n\t" + "mov x3, x4\n\t" + "mov x4, x5\n\t" + "mov x5, #0\n\t" + "add x9, x9, #8\n\t" + "cmp x9, 192\n\t" + "b.lt 1b\n\t" + "str x3, [%[r], 192]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#else + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldp x8, x9, [%[a]]\n\t" + "mul x3, %[b], x8\n\t" + "umulh x4, %[b], x8\n\t" + "mov x5, 0\n\t" + "# A[1] * B\n\t" + "str x3, [%[r]]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "umulh x7, %[b], x9\n\t" + "adds x4, x4, x6\n\t" + "# A[2] * B\n\t" + "ldp x8, x9, [%[a], 16]\n\t" + "str x4, [%[r], 8]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[3] * B\n\t" + "str x5, [%[r], 16]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[4] * B\n\t" + "ldp x8, x9, [%[a], 32]\n\t" + "str x3, [%[r], 24]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[5] * B\n\t" + "str x4, [%[r], 32]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[6] * B\n\t" + "ldp x8, x9, [%[a], 48]\n\t" + "str x5, [%[r], 40]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[7] * B\n\t" + "str x3, [%[r], 48]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[8] * B\n\t" + "ldp x8, x9, [%[a], 64]\n\t" + "str x4, [%[r], 56]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[9] * B\n\t" + "str x5, [%[r], 64]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[10] * B\n\t" + "ldp x8, x9, [%[a], 80]\n\t" + "str x3, [%[r], 72]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[11] * B\n\t" + "str x4, [%[r], 80]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[12] * B\n\t" + "ldp x8, x9, [%[a], 96]\n\t" + "str x5, [%[r], 88]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[13] * B\n\t" + "str x3, [%[r], 96]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[14] * B\n\t" + "ldp x8, x9, [%[a], 112]\n\t" + "str x4, [%[r], 104]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[15] * B\n\t" + "str x5, [%[r], 112]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[16] * B\n\t" + "ldp x8, x9, [%[a], 128]\n\t" + "str x3, [%[r], 120]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[17] * B\n\t" + "str x4, [%[r], 128]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[18] * B\n\t" + "ldp x8, x9, [%[a], 144]\n\t" + "str x5, [%[r], 136]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[19] * B\n\t" + "str x3, [%[r], 144]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[20] * B\n\t" + "ldp x8, x9, [%[a], 160]\n\t" + "str x4, [%[r], 152]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[21] * B\n\t" + "str x5, [%[r], 160]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[22] * B\n\t" + "ldp x8, x9, [%[a], 176]\n\t" + "str x3, [%[r], 168]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[23] * B\n\t" + "str x4, [%[r], 176]\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "adc x3, x3, x7\n\t" + "stp x5, x3, [%[r], 184]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#endif +} + +/* 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__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "sub %[d0], %[d0], x4\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add %[r], x6, x3\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + 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(const sp_digit* a, const sp_digit* b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "mov x5, 184\n\t" + "1:\n\t" + "ldr x6, [%[a], x5]\n\t" + "ldr x7, [%[b], x5]\n\t" + "and x6, x6, x4\n\t" + "and x7, x7, x4\n\t" + "subs x6, x6, x7\n\t" + "csel x2, x3, x2, hi\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "subs x5, x5, #8\n\t" + "b.cs 1b\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "ldp x7, x8, [%[b], 176]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 160]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "ldp x7, x8, [%[b], 144]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 128]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "ldp x7, x8, [%[b], 112]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "ldp x7, x8, [%[b], 80]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "ldp x7, x8, [%[b], 48]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 16]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#endif + + return (int64_t)a; +} + +/* 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 WC_INLINE int sp_3072_div_24(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[48], t2[25]; + sp_digit div, r1; + int i; + + (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); + + 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, d, (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 WC_INLINE int sp_3072_mod_24(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_24(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][48]; +#else + sp_digit* t[16]; + 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) * 16 * 48, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 48; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_24(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 24U); + if (reduceA != 0) { + 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); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 4; + if (c == 64) { + c = 60; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 24); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + } + else if (c < 4) { + y = n >> 60; + n = e[i--]; + c = 4 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 60) & 0xf; + n <<= 4; + c -= 4; + } + + 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); + } + + XMEMSET(&r[24], 0, sizeof(sp_digit) * 24U); + 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; +} +#else +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const 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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 48; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_24(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 24U); + if (reduceA != 0) { + 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--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 5; + if (c == 64) { + c = 59; + } + y = (int)(n >> c); + n <<= 64 - c; + 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); + } + + XMEMSET(&r[24], 0, sizeof(sp_digit) * 24U); + 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; +} +#endif /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* 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 single precision number. + */ +static void sp_3072_mont_norm_48(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 48); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_48(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* 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, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "csetm %[c], cc\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 384\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return c; +#else + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x11, x12, [%[b], 48]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 48]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 48]\n\t" + "ldp x5, x7, [%[b], 64]\n\t" + "ldp x11, x12, [%[b], 80]\n\t" + "ldp x4, x6, [%[a], 64]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 80]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 64]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 80]\n\t" + "ldp x5, x7, [%[b], 96]\n\t" + "ldp x11, x12, [%[b], 112]\n\t" + "ldp x4, x6, [%[a], 96]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 112]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 96]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 112]\n\t" + "ldp x5, x7, [%[b], 128]\n\t" + "ldp x11, x12, [%[b], 144]\n\t" + "ldp x4, x6, [%[a], 128]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 144]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 128]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 144]\n\t" + "ldp x5, x7, [%[b], 160]\n\t" + "ldp x11, x12, [%[b], 176]\n\t" + "ldp x4, x6, [%[a], 160]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 176]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 160]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 176]\n\t" + "ldp x5, x7, [%[b], 192]\n\t" + "ldp x11, x12, [%[b], 208]\n\t" + "ldp x4, x6, [%[a], 192]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 208]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 192]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 208]\n\t" + "ldp x5, x7, [%[b], 224]\n\t" + "ldp x11, x12, [%[b], 240]\n\t" + "ldp x4, x6, [%[a], 224]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 240]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 224]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 240]\n\t" + "ldp x5, x7, [%[b], 256]\n\t" + "ldp x11, x12, [%[b], 272]\n\t" + "ldp x4, x6, [%[a], 256]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 272]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 256]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 272]\n\t" + "ldp x5, x7, [%[b], 288]\n\t" + "ldp x11, x12, [%[b], 304]\n\t" + "ldp x4, x6, [%[a], 288]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 304]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 288]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 304]\n\t" + "ldp x5, x7, [%[b], 320]\n\t" + "ldp x11, x12, [%[b], 336]\n\t" + "ldp x4, x6, [%[a], 320]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 336]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 320]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 336]\n\t" + "ldp x5, x7, [%[b], 352]\n\t" + "ldp x11, x12, [%[b], 368]\n\t" + "ldp x4, x6, [%[a], 352]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 368]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 352]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 368]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* 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, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "ldp x14, x15, [%[m], 0]\n\t" + "ldp x16, x17, [%[m], 16]\n\t" + "ldp x19, x20, [%[m], 32]\n\t" + "ldp x21, x22, [%[m], 48]\n\t" + "ldp x23, x24, [%[m], 64]\n\t" + "ldp x25, x26, [%[m], 80]\n\t" + "ldp x27, x28, [%[m], 96]\n\t" + "# i = 48\n\t" + "mov x4, 48\n\t" + "ldp x12, x13, [%[a], 0]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul x9, %[mp], x12\n\t" + "# a[i+0] += m[0] * mu\n\t" + "mul x7, x14, x9\n\t" + "umulh x8, x14, x9\n\t" + "adds x12, x12, x7\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mul x7, x15, x9\n\t" + "adc x6, x8, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x12, x13, x7\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr x13, [%[a], 16]\n\t" + "adc x5, x8, xzr\n\t" + "mul x7, x16, x9\n\t" + "adds x12, x12, x6\n\t" + "umulh x8, x16, x9\n\t" + "adc x5, x5, xzr\n\t" + "adds x13, x13, x7\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr x10, [%[a], 24]\n\t" + "adc x6, x8, xzr\n\t" + "mul x7, x17, x9\n\t" + "adds x13, x13, x5\n\t" + "umulh x8, x17, x9\n\t" + "adc x6, x6, xzr\n\t" + "adds x10, x10, x7\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr x11, [%[a], 32]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x19, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x19, x9\n\t" + "str x10, [%[a], 24]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr x10, [%[a], 40]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x20, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x20, x9\n\t" + "str x11, [%[a], 32]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr x11, [%[a], 48]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x21, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x21, x9\n\t" + "str x10, [%[a], 40]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr x10, [%[a], 56]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x22, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x22, x9\n\t" + "str x11, [%[a], 48]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr x11, [%[a], 64]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x23, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x23, x9\n\t" + "str x10, [%[a], 56]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr x10, [%[a], 72]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x24, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x24, x9\n\t" + "str x11, [%[a], 64]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr x11, [%[a], 80]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x25, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x25, x9\n\t" + "str x10, [%[a], 72]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr x10, [%[a], 88]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x26, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x26, x9\n\t" + "str x11, [%[a], 80]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr x11, [%[a], 96]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x27, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x27, x9\n\t" + "str x10, [%[a], 88]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr x10, [%[a], 104]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x28, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x28, x9\n\t" + "str x11, [%[a], 96]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr x11, [%[a], 112]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 112]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 104]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr x10, [%[a], 120]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 120]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 112]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr x11, [%[a], 128]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 128]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 120]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr x10, [%[a], 136]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 136]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 128]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr x11, [%[a], 144]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 144]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 136]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr x10, [%[a], 152]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 152]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 144]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr x11, [%[a], 160]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 160]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 152]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr x10, [%[a], 168]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 168]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 160]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr x11, [%[a], 176]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 176]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 168]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr x10, [%[a], 184]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 184]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 176]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr x11, [%[a], 192]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 192]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 184]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr x10, [%[a], 200]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 200]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 192]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr x11, [%[a], 208]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 208]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 200]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr x10, [%[a], 216]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 216]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 208]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr x11, [%[a], 224]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 224]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 216]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr x10, [%[a], 232]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 232]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 224]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr x11, [%[a], 240]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 240]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 232]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr x10, [%[a], 248]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 248]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 240]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+32] += m[32] * mu\n\t" + "ldr x11, [%[a], 256]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 256]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 248]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+33] += m[33] * mu\n\t" + "ldr x10, [%[a], 264]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 264]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 256]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+34] += m[34] * mu\n\t" + "ldr x11, [%[a], 272]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 272]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 264]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+35] += m[35] * mu\n\t" + "ldr x10, [%[a], 280]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 280]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 272]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+36] += m[36] * mu\n\t" + "ldr x11, [%[a], 288]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 288]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 280]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+37] += m[37] * mu\n\t" + "ldr x10, [%[a], 296]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 296]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 288]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+38] += m[38] * mu\n\t" + "ldr x11, [%[a], 304]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 304]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 296]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+39] += m[39] * mu\n\t" + "ldr x10, [%[a], 312]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 312]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 304]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+40] += m[40] * mu\n\t" + "ldr x11, [%[a], 320]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 320]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 312]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+41] += m[41] * mu\n\t" + "ldr x10, [%[a], 328]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 328]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 320]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+42] += m[42] * mu\n\t" + "ldr x11, [%[a], 336]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 336]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 328]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+43] += m[43] * mu\n\t" + "ldr x10, [%[a], 344]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 344]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 336]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+44] += m[44] * mu\n\t" + "ldr x11, [%[a], 352]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 352]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 344]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+45] += m[45] * mu\n\t" + "ldr x10, [%[a], 360]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 360]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 352]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+46] += m[46] * mu\n\t" + "ldr x11, [%[a], 368]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 368]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 360]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+47] += m[47] * mu\n\t" + "ldr x10, [%[a], 376]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 376]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x8, x8, %[ca]\n\t" + "str x11, [%[a], 368]\n\t" + "cset %[ca], cs\n\t" + "adds x10, x10, x6\n\t" + "ldr x11, [%[a], 384]\n\t" + "str x10, [%[a], 376]\n\t" + "adcs x11, x11, x8\n\t" + "str x11, [%[a], 384]\n\t" + "adc %[ca], %[ca], xzr\n\t" + "subs x4, x4, 1\n\t" + "add %[a], %[a], 8\n\t" + "bne 1b\n\t" + "stp x12, x13, [%[a], 0]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); + + 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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_48(r, a); + sp_3072_mont_reduce_48(r, m, mp); +} + +/* 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__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "sub %[d0], %[d0], x4\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add %[r], x6, x3\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + 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, const 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(const sp_digit* a, const sp_digit* b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "mov x5, 376\n\t" + "1:\n\t" + "ldr x6, [%[a], x5]\n\t" + "ldr x7, [%[b], x5]\n\t" + "and x6, x6, x4\n\t" + "and x7, x7, x4\n\t" + "subs x6, x6, x7\n\t" + "csel x2, x3, x2, hi\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "subs x5, x5, #8\n\t" + "b.cs 1b\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "ldp x5, x6, [%[a], 368]\n\t" + "ldp x7, x8, [%[b], 368]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 352]\n\t" + "ldp x7, x8, [%[b], 352]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 336]\n\t" + "ldp x7, x8, [%[b], 336]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 320]\n\t" + "ldp x7, x8, [%[b], 320]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 304]\n\t" + "ldp x7, x8, [%[b], 304]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 288]\n\t" + "ldp x7, x8, [%[b], 288]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 272]\n\t" + "ldp x7, x8, [%[b], 272]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 256]\n\t" + "ldp x7, x8, [%[b], 256]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "ldp x7, x8, [%[b], 240]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 224]\n\t" + "ldp x7, x8, [%[b], 224]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "ldp x7, x8, [%[b], 208]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 192]\n\t" + "ldp x7, x8, [%[b], 192]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "ldp x7, x8, [%[b], 176]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 160]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "ldp x7, x8, [%[b], 144]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 128]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "ldp x7, x8, [%[b], 112]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "ldp x7, x8, [%[b], 80]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "ldp x7, x8, [%[b], 48]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 16]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#endif + + return (int64_t)a; +} + +/* 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 WC_INLINE int sp_3072_div_48(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; + + (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); + + 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, d, (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 WC_INLINE int sp_3072_mod_48(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_48(a, m, NULL, 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 sp_digit sp_3072_sub_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 384\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#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 sp_digit sp_3072_sub_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "subs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 144]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 176]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "ldp x3, x4, [%[a], 192]\n\t" + "ldp x7, x8, [%[b], 192]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 208]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 192]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 208]\n\t" + "ldp x3, x4, [%[a], 224]\n\t" + "ldp x7, x8, [%[b], 224]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 240]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 224]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 240]\n\t" + "ldp x3, x4, [%[a], 256]\n\t" + "ldp x7, x8, [%[b], 256]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 272]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 272]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 256]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 272]\n\t" + "ldp x3, x4, [%[a], 288]\n\t" + "ldp x7, x8, [%[b], 288]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 304]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 304]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 288]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 304]\n\t" + "ldp x3, x4, [%[a], 320]\n\t" + "ldp x7, x8, [%[b], 320]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 336]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 336]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 320]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 336]\n\t" + "ldp x3, x4, [%[a], 352]\n\t" + "ldp x7, x8, [%[b], 352]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 368]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 368]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 352]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 368]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +#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 MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_48_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; + + (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); + + 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); + } + } + + for (i = 47; i > 0; i--) { + if (t1[i] != d[i]) + break; + } + if (t1[i] >= d[i]) { + sp_3072_sub_48(r, t1, d); + } + else { + XMEMCPY(r, t1, sizeof(*t1) * 48); + } + + 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 WC_INLINE int sp_3072_mod_48_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_48_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][96]; +#else + sp_digit* t[16]; + 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) * 16 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 96; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48U); + if (reduceA != 0) { + 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); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 4; + if (c == 64) { + c = 60; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + } + else if (c < 4) { + y = n >> 60; + n = e[i--]; + c = 4 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 60) & 0xf; + n <<= 4; + c -= 4; + } + + 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); + } + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U); + 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; +} +#else +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const 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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 96; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48U); + if (reduceA != 0) { + 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--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 5; + if (c == 64) { + c = 59; + } + y = (int)(n >> c); + n <<= 64 - c; + 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); + } + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U); + 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 /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[96], m[48], r[96]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; +#endif + sp_digit *ah; + sp_digit e[1]; + int err = MP_OKAY; + + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 48 * 2; + m = r + 48 * 2; + } +#endif + + if (err == MP_OKAY) { + ah = a + 48; + + 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) { + 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); + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) + 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 < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 3072) { + err = MP_READ_E; + } + if (inLen > 384) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 48; + m = a + 96; + r = a; + + sp_3072_from_bin(a, 48, in, inLen); + sp_3072_from_mp(d, 48, dm); + sp_3072_from_mp(m, 48, mm); + err = sp_3072_mod_exp_48(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) * 48); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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 sp_digit sp_3072_cond_add_24(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "cset %[c], cs\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 192\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return c; +#else + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "adds x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x11, x12, [%[b], 48]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 48]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 48]\n\t" + "ldp x5, x7, [%[b], 64]\n\t" + "ldp x11, x12, [%[b], 80]\n\t" + "ldp x4, x6, [%[a], 64]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 80]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 64]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 80]\n\t" + "ldp x5, x7, [%[b], 96]\n\t" + "ldp x11, x12, [%[b], 112]\n\t" + "ldp x4, x6, [%[a], 96]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 112]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 96]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 112]\n\t" + "ldp x5, x7, [%[b], 128]\n\t" + "ldp x11, x12, [%[b], 144]\n\t" + "ldp x4, x6, [%[a], 128]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 144]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 128]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 144]\n\t" + "ldp x5, x7, [%[b], 160]\n\t" + "ldp x11, x12, [%[b], 176]\n\t" + "ldp x4, x6, [%[a], 160]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 176]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 160]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 176]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +#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) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[48 * 2]; + sp_digit p[24], q[24], dp[24]; + sp_digit tmpa[48], tmpb[48]; +#else + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* tmpa; + sp_digit* tmpb; +#endif + sp_digit* r; + sp_digit* qi; + sp_digit* dq; + sp_digit c; + 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 (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 24 * 11, NULL, + DYNAMIC_TYPE_RSA); + 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; + + r = t + 48; + } +#else +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + r = a; + qi = dq = dp; +#endif + 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); + + err = sp_3072_mod_exp_24(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 24, dqm); + 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); + c += sp_3072_cond_add_24(tmpa, tmpa, p, c); + sp_3072_cond_add_24(tmpa, tmpa, p, c); + + sp_3072_from_mp(qi, 24, qim); + sp_3072_mul_24(tmpa, tmpa, qi); + err = sp_3072_mod_24(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 24 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + 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)); +#endif + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 48); + r->used = 48; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 48; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 64 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 48; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && 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 = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_mp(e, 48, exp); + sp_3072_from_mp(m, 48, mod); + + err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_3072 +static void sp_3072_lshift_48(sp_digit* r, sp_digit* a, byte n) +{ + __asm__ __volatile__ ( + "mov x6, 63\n\t" + "sub x6, x6, %[n]\n\t" + "ldr x3, [%[a], 376]\n\t" + "lsr x4, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x4, x4, x6\n\t" + "ldr x2, [%[a], 368]\n\t" + "str x4, [%[r], 384]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 360]\n\t" + "str x3, [%[r], 376]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 352]\n\t" + "str x2, [%[r], 368]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 344]\n\t" + "str x4, [%[r], 360]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 336]\n\t" + "str x3, [%[r], 352]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 328]\n\t" + "str x2, [%[r], 344]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 320]\n\t" + "str x4, [%[r], 336]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 312]\n\t" + "str x3, [%[r], 328]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 304]\n\t" + "str x2, [%[r], 320]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 296]\n\t" + "str x4, [%[r], 312]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 288]\n\t" + "str x3, [%[r], 304]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 280]\n\t" + "str x2, [%[r], 296]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 272]\n\t" + "str x4, [%[r], 288]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 264]\n\t" + "str x3, [%[r], 280]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 256]\n\t" + "str x2, [%[r], 272]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 248]\n\t" + "str x4, [%[r], 264]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 240]\n\t" + "str x3, [%[r], 256]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 232]\n\t" + "str x2, [%[r], 248]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 224]\n\t" + "str x4, [%[r], 240]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 216]\n\t" + "str x3, [%[r], 232]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 208]\n\t" + "str x2, [%[r], 224]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 200]\n\t" + "str x4, [%[r], 216]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 192]\n\t" + "str x3, [%[r], 208]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 184]\n\t" + "str x2, [%[r], 200]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 176]\n\t" + "str x4, [%[r], 192]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 168]\n\t" + "str x3, [%[r], 184]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 160]\n\t" + "str x2, [%[r], 176]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 152]\n\t" + "str x4, [%[r], 168]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 144]\n\t" + "str x3, [%[r], 160]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 136]\n\t" + "str x2, [%[r], 152]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 128]\n\t" + "str x4, [%[r], 144]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 120]\n\t" + "str x3, [%[r], 136]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 112]\n\t" + "str x2, [%[r], 128]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 104]\n\t" + "str x4, [%[r], 120]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 96]\n\t" + "str x3, [%[r], 112]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 88]\n\t" + "str x2, [%[r], 104]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 80]\n\t" + "str x4, [%[r], 96]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 72]\n\t" + "str x3, [%[r], 88]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 64]\n\t" + "str x2, [%[r], 80]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 56]\n\t" + "str x4, [%[r], 72]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 48]\n\t" + "str x3, [%[r], 64]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 40]\n\t" + "str x2, [%[r], 56]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 32]\n\t" + "str x4, [%[r], 48]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 24]\n\t" + "str x3, [%[r], 40]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 16]\n\t" + "str x2, [%[r], 32]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 8]\n\t" + "str x4, [%[r], 24]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 0]\n\t" + "str x3, [%[r], 16]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "str x4, [%[r]]\n\t" + "str x2, [%[r], 8]\n\t" + : + : [r] "r" (r), [a] "r" (a), [n] "r" (n) + : "memory", "x2", "x3", "x4", "x5", "x6" + ); +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_48(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[96]; + sp_digit td[49]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 145, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 96; +#else + norm = nd; + tmp = td; +#endif + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 6; + if (c == 64) { + c = 58; + } + y = (int)(n >> c); + n <<= 64 - c; + sp_3072_lshift_48(r, norm, y); + for (; i>=0 || c>=6; ) { + if (c == 0) { + n = e[i--]; + y = n >> 58; + n <<= 6; + c = 58; + } + else if (c < 6) { + y = n >> 58; + n = e[i--]; + c = 6 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 58) & 0x3f; + n <<= 6; + c -= 6; + } + + 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_sqr_48(r, r, m, mp); + + sp_3072_lshift_48(r, r, y); + sp_3072_mul_d_48(tmp, norm, r[48]); + r[48] = 0; + o = sp_3072_add_48(r, r, tmp); + sp_3072_cond_sub_48(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U); + 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 /* HAVE_FFDHE_3072 */ + +/* 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. + * returns 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; + + if (mp_count_bits(base) > 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 384) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (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_FFDHE_3072 + if (base->used == 1 && base->dp[0] == 2 && m[47] == (sp_digit)-1) + err = sp_3072_mod_exp_2_48(r, e, expLen * 8, m); + 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 */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[48], e[24], m[24]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 24, base); + sp_3072_from_mp(e, 24, exp); + sp_3072_from_mp(m, 24, mod); + + err = sp_3072_mod_exp_24(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 24, 0, sizeof(*r) * 24U); + err = sp_3072_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#ifdef WOLFSSL_SP_4096 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j; + byte* d; + + for (i = n - 1,j = 0; i >= 7; i -= 8) { + r[j] = ((sp_digit)a[i - 0] << 0) | + ((sp_digit)a[i - 1] << 8) | + ((sp_digit)a[i - 2] << 16) | + ((sp_digit)a[i - 3] << 24) | + ((sp_digit)a[i - 4] << 32) | + ((sp_digit)a[i - 5] << 40) | + ((sp_digit)a[i - 6] << 48) | + ((sp_digit)a[i - 7] << 56); + j++; + } + + if (i >= 0) { + r[j] = 0; + + d = (byte*)r; + switch (i) { + case 6: d[n - 1 - 6] = a[6]; //fallthrough + case 5: d[n - 1 - 5] = a[5]; //fallthrough + case 4: d[n - 1 - 4] = a[4]; //fallthrough + case 3: d[n - 1 - 3] = a[3]; //fallthrough + case 2: d[n - 1 - 2] = a[2]; //fallthrough + case 1: d[n - 1 - 1] = a[1]; //fallthrough + case 0: d[n - 1 - 0] = a[0]; //fallthrough + } + j++; + } + + for (; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 512 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_4096_to_bin(sp_digit* r, byte* a) +{ + int i, j; + + for (i = 63, j = 0; i >= 0; i--) { + a[j++] = r[i] >> 56; + a[j++] = r[i] >> 48; + a[j++] = r[i] >> 40; + a[j++] = r[i] >> 32; + a[j++] = r[i] >> 24; + a[j++] = r[i] >> 16; + a[j++] = r[i] >> 8; + a[j++] = r[i] >> 0; + } +} + +#ifndef 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 sp_digit sp_4096_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 144]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 176]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "ldp x3, x4, [%[a], 192]\n\t" + "ldp x7, x8, [%[b], 192]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 208]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 192]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 208]\n\t" + "ldp x3, x4, [%[a], 224]\n\t" + "ldp x7, x8, [%[b], 224]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 240]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 224]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 240]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_4096_sub_in_place_64(sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "subs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "ldp x2, x3, [%[a], 32]\n\t" + "ldp x6, x7, [%[b], 32]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 48]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 48]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 32]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 48]\n\t" + "ldp x2, x3, [%[a], 64]\n\t" + "ldp x6, x7, [%[b], 64]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 80]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 80]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 64]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 80]\n\t" + "ldp x2, x3, [%[a], 96]\n\t" + "ldp x6, x7, [%[b], 96]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 112]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 112]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 96]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 112]\n\t" + "ldp x2, x3, [%[a], 128]\n\t" + "ldp x6, x7, [%[b], 128]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 144]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 144]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 128]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 144]\n\t" + "ldp x2, x3, [%[a], 160]\n\t" + "ldp x6, x7, [%[b], 160]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 176]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 176]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 160]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 176]\n\t" + "ldp x2, x3, [%[a], 192]\n\t" + "ldp x6, x7, [%[b], 192]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 208]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 208]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 192]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 208]\n\t" + "ldp x2, x3, [%[a], 224]\n\t" + "ldp x6, x7, [%[b], 224]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 240]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 240]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 224]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 240]\n\t" + "ldp x2, x3, [%[a], 256]\n\t" + "ldp x6, x7, [%[b], 256]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 272]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 272]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 256]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 272]\n\t" + "ldp x2, x3, [%[a], 288]\n\t" + "ldp x6, x7, [%[b], 288]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 304]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 304]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 288]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 304]\n\t" + "ldp x2, x3, [%[a], 320]\n\t" + "ldp x6, x7, [%[b], 320]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 336]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 336]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 320]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 336]\n\t" + "ldp x2, x3, [%[a], 352]\n\t" + "ldp x6, x7, [%[b], 352]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 368]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 368]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 352]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 368]\n\t" + "ldp x2, x3, [%[a], 384]\n\t" + "ldp x6, x7, [%[b], 384]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 400]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 400]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 384]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 400]\n\t" + "ldp x2, x3, [%[a], 416]\n\t" + "ldp x6, x7, [%[b], 416]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 432]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 432]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 416]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 432]\n\t" + "ldp x2, x3, [%[a], 448]\n\t" + "ldp x6, x7, [%[b], 448]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 464]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 464]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 448]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 464]\n\t" + "ldp x2, x3, [%[a], 480]\n\t" + "ldp x6, x7, [%[b], 480]\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 496]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 496]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 480]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 496]\n\t" + "csetm %[a], cc\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return (sp_digit)a; +} + +/* 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_4096_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 144]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 176]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "ldp x3, x4, [%[a], 192]\n\t" + "ldp x7, x8, [%[b], 192]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 208]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 192]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 208]\n\t" + "ldp x3, x4, [%[a], 224]\n\t" + "ldp x7, x8, [%[b], 224]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 240]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 224]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 240]\n\t" + "ldp x3, x4, [%[a], 256]\n\t" + "ldp x7, x8, [%[b], 256]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 272]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 272]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 256]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 272]\n\t" + "ldp x3, x4, [%[a], 288]\n\t" + "ldp x7, x8, [%[b], 288]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 304]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 304]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 288]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 304]\n\t" + "ldp x3, x4, [%[a], 320]\n\t" + "ldp x7, x8, [%[b], 320]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 336]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 336]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 320]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 336]\n\t" + "ldp x3, x4, [%[a], 352]\n\t" + "ldp x7, x8, [%[b], 352]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 368]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 368]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 352]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 368]\n\t" + "ldp x3, x4, [%[a], 384]\n\t" + "ldp x7, x8, [%[b], 384]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 400]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 400]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 384]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 400]\n\t" + "ldp x3, x4, [%[a], 416]\n\t" + "ldp x7, x8, [%[b], 416]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 432]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 432]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 416]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 432]\n\t" + "ldp x3, x4, [%[a], 448]\n\t" + "ldp x7, x8, [%[b], 448]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 464]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 464]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 448]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 464]\n\t" + "ldp x3, x4, [%[a], 480]\n\t" + "ldp x7, x8, [%[b], 480]\n\t" + "adcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 496]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 496]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 480]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 496]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +/* Add digit to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_4096_add_zero_32(sp_digit* r, const sp_digit* a, + const sp_digit d) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adds x3, x3, %[d]\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "ldp x3, x4, [%[a], 192]\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 192]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 208]\n\t" + "ldp x3, x4, [%[a], 224]\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "adcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 224]\n\t" + "adcs x6, x6, xzr\n\t" + "stp x5, x6, [%[r], 240]\n\t" + : + : [r] "r" (r), [a] "r" (a), [d] "r" (d) + : "memory", "x3", "x4", "x5", "x6" + ); +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_4096_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit b1[32]; + sp_digit z2[64]; + sp_digit u, ca, cb; + + ca = sp_2048_add_32(a1, a, &a[32]); + cb = sp_2048_add_32(b1, b, &b[32]); + u = ca & cb; + sp_2048_mul_32(z1, a1, b1); + sp_2048_mul_32(z2, &a[32], &b[32]); + sp_2048_mul_32(z0, a, b); + sp_2048_mask_32(r + 64, a1, 0 - cb); + sp_2048_mask_32(b1, b1, 0 - ca); + u += sp_2048_add_32(r + 64, r + 64, b1); + u += sp_4096_sub_in_place_64(z1, z2); + u += sp_4096_sub_in_place_64(z1, z0); + u += sp_4096_add_64(r + 32, r + 32, z1); + u += sp_4096_add_32(r + 64, r + 64, z2); + sp_4096_add_zero_32(r + 96, z2 + 32, u); +} + +#ifdef WOLFSSL_SP_SMALL +/* Double a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +static sp_digit sp_2048_dbl_32(sp_digit* r, const sp_digit* a) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 256\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "adcs x3, x3, x3\n\t" + "adcs x4, x4, x4\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a) + : + : "memory", "x3", "x4", "x5", "x6", "x11" + ); + + return c; +} + +#else +/* Double a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +static sp_digit sp_2048_dbl_32(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "adds x3, x3, x3\n\t" + "ldr x5, [%[a], 16]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 24]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 48]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 56]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 80]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 88]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 112]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 120]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 144]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 152]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 176]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 184]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "ldp x3, x4, [%[a], 192]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 208]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 216]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 192]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 208]\n\t" + "ldp x3, x4, [%[a], 224]\n\t" + "adcs x3, x3, x3\n\t" + "ldr x5, [%[a], 240]\n\t" + "adcs x4, x4, x4\n\t" + "ldr x6, [%[a], 248]\n\t" + "adcs x5, x5, x5\n\t" + "stp x3, x4, [%[r], 224]\n\t" + "adcs x6, x6, x6\n\t" + "stp x5, x6, [%[r], 240]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6" + ); + + return (sp_digit)r; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_4096_sqr_64(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[64]; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit u; + + u = sp_2048_add_32(a1, a, &a[32]); + sp_2048_sqr_32(z1, a1); + sp_2048_sqr_32(z2, &a[32]); + sp_2048_sqr_32(z0, a); + sp_2048_mask_32(r + 64, a1, 0 - u); + u += sp_2048_dbl_32(r + 64, r + 64); + u += sp_4096_sub_in_place_64(z1, z2); + u += sp_4096_sub_in_place_64(z1, z0); + u += sp_4096_add_64(r + 32, r + 32, z1); + u += sp_4096_add_32(r + 64, r + 64, z2); + sp_4096_add_zero_32(r + 96, z2 + 32, u); + +} + +#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 sp_digit sp_4096_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 512\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "adcs x3, x3, x7\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_4096_sub_in_place_64(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x10, %[a], 512\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x2, x3, [%[a]]\n\t" + "ldp x4, x5, [%[a], #16]\n\t" + "ldp x6, x7, [%[b]], #16\n\t" + "sbcs x2, x2, x6\n\t" + "ldp x8, x9, [%[b]], #16\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a]], #16\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x10\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +#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_4096_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[128]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 504\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 512\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 1008\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + 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_4096_sqr_64(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[128]; + + __asm__ __volatile__ ( + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "mov x5, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 504\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "cmp x4, x3\n\t" + "b.eq 4f\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[a], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "b.al 5f\n\t" + "\n4:\n\t" + "ldr x10, [%[a], x3]\n\t" + "mul x9, x10, x10\n\t" + "umulh x10, x10, x10\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "\n5:\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 512\n\t" + "b.eq 3f\n\t" + "cmp x3, x4\n\t" + "b.gt 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 1008\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_4096_mont_setup(const 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; +} + +/* 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_4096_mul_d_64(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x5, %[b], x8\n\t" + "umulh x3, %[b], x8\n\t" + "mov x4, 0\n\t" + "str x5, [%[r]]\n\t" + "mov x5, 0\n\t" + "mov x9, #8\n\t" + "1:\n\t" + "ldr x8, [%[a], x9]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], x9]\n\t" + "mov x3, x4\n\t" + "mov x4, x5\n\t" + "mov x5, #0\n\t" + "add x9, x9, #8\n\t" + "cmp x9, 512\n\t" + "b.lt 1b\n\t" + "str x3, [%[r], 512]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#else + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldp x8, x9, [%[a]]\n\t" + "mul x3, %[b], x8\n\t" + "umulh x4, %[b], x8\n\t" + "mov x5, 0\n\t" + "# A[1] * B\n\t" + "str x3, [%[r]]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "umulh x7, %[b], x9\n\t" + "adds x4, x4, x6\n\t" + "# A[2] * B\n\t" + "ldp x8, x9, [%[a], 16]\n\t" + "str x4, [%[r], 8]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[3] * B\n\t" + "str x5, [%[r], 16]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[4] * B\n\t" + "ldp x8, x9, [%[a], 32]\n\t" + "str x3, [%[r], 24]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[5] * B\n\t" + "str x4, [%[r], 32]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[6] * B\n\t" + "ldp x8, x9, [%[a], 48]\n\t" + "str x5, [%[r], 40]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[7] * B\n\t" + "str x3, [%[r], 48]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[8] * B\n\t" + "ldp x8, x9, [%[a], 64]\n\t" + "str x4, [%[r], 56]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[9] * B\n\t" + "str x5, [%[r], 64]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[10] * B\n\t" + "ldp x8, x9, [%[a], 80]\n\t" + "str x3, [%[r], 72]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[11] * B\n\t" + "str x4, [%[r], 80]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[12] * B\n\t" + "ldp x8, x9, [%[a], 96]\n\t" + "str x5, [%[r], 88]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[13] * B\n\t" + "str x3, [%[r], 96]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[14] * B\n\t" + "ldp x8, x9, [%[a], 112]\n\t" + "str x4, [%[r], 104]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[15] * B\n\t" + "str x5, [%[r], 112]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[16] * B\n\t" + "ldp x8, x9, [%[a], 128]\n\t" + "str x3, [%[r], 120]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[17] * B\n\t" + "str x4, [%[r], 128]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[18] * B\n\t" + "ldp x8, x9, [%[a], 144]\n\t" + "str x5, [%[r], 136]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[19] * B\n\t" + "str x3, [%[r], 144]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[20] * B\n\t" + "ldp x8, x9, [%[a], 160]\n\t" + "str x4, [%[r], 152]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[21] * B\n\t" + "str x5, [%[r], 160]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[22] * B\n\t" + "ldp x8, x9, [%[a], 176]\n\t" + "str x3, [%[r], 168]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[23] * B\n\t" + "str x4, [%[r], 176]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[24] * B\n\t" + "ldp x8, x9, [%[a], 192]\n\t" + "str x5, [%[r], 184]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[25] * B\n\t" + "str x3, [%[r], 192]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[26] * B\n\t" + "ldp x8, x9, [%[a], 208]\n\t" + "str x4, [%[r], 200]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[27] * B\n\t" + "str x5, [%[r], 208]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[28] * B\n\t" + "ldp x8, x9, [%[a], 224]\n\t" + "str x3, [%[r], 216]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[29] * B\n\t" + "str x4, [%[r], 224]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[30] * B\n\t" + "ldp x8, x9, [%[a], 240]\n\t" + "str x5, [%[r], 232]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[31] * B\n\t" + "str x3, [%[r], 240]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[32] * B\n\t" + "ldp x8, x9, [%[a], 256]\n\t" + "str x4, [%[r], 248]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[33] * B\n\t" + "str x5, [%[r], 256]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[34] * B\n\t" + "ldp x8, x9, [%[a], 272]\n\t" + "str x3, [%[r], 264]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[35] * B\n\t" + "str x4, [%[r], 272]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[36] * B\n\t" + "ldp x8, x9, [%[a], 288]\n\t" + "str x5, [%[r], 280]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[37] * B\n\t" + "str x3, [%[r], 288]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[38] * B\n\t" + "ldp x8, x9, [%[a], 304]\n\t" + "str x4, [%[r], 296]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[39] * B\n\t" + "str x5, [%[r], 304]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[40] * B\n\t" + "ldp x8, x9, [%[a], 320]\n\t" + "str x3, [%[r], 312]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[41] * B\n\t" + "str x4, [%[r], 320]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[42] * B\n\t" + "ldp x8, x9, [%[a], 336]\n\t" + "str x5, [%[r], 328]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[43] * B\n\t" + "str x3, [%[r], 336]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[44] * B\n\t" + "ldp x8, x9, [%[a], 352]\n\t" + "str x4, [%[r], 344]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[45] * B\n\t" + "str x5, [%[r], 352]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[46] * B\n\t" + "ldp x8, x9, [%[a], 368]\n\t" + "str x3, [%[r], 360]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[47] * B\n\t" + "str x4, [%[r], 368]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[48] * B\n\t" + "ldp x8, x9, [%[a], 384]\n\t" + "str x5, [%[r], 376]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[49] * B\n\t" + "str x3, [%[r], 384]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[50] * B\n\t" + "ldp x8, x9, [%[a], 400]\n\t" + "str x4, [%[r], 392]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[51] * B\n\t" + "str x5, [%[r], 400]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[52] * B\n\t" + "ldp x8, x9, [%[a], 416]\n\t" + "str x3, [%[r], 408]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[53] * B\n\t" + "str x4, [%[r], 416]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[54] * B\n\t" + "ldp x8, x9, [%[a], 432]\n\t" + "str x5, [%[r], 424]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[55] * B\n\t" + "str x3, [%[r], 432]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[56] * B\n\t" + "ldp x8, x9, [%[a], 448]\n\t" + "str x4, [%[r], 440]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[57] * B\n\t" + "str x5, [%[r], 448]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[58] * B\n\t" + "ldp x8, x9, [%[a], 464]\n\t" + "str x3, [%[r], 456]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[59] * B\n\t" + "str x4, [%[r], 464]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[60] * B\n\t" + "ldp x8, x9, [%[a], 480]\n\t" + "str x5, [%[r], 472]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[61] * B\n\t" + "str x3, [%[r], 480]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[62] * B\n\t" + "ldp x8, x9, [%[a], 496]\n\t" + "str x4, [%[r], 488]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[63] * B\n\t" + "str x5, [%[r], 496]\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "stp x3, x4, [%[r], 504]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#endif +} + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 4096 bits, just need to subtract. + * + * r A single precision number. + * m A single precision number. + */ +static void sp_4096_mont_norm_64(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 64); + + /* r = 2^n mod m */ + sp_4096_sub_in_place_64(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* 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_4096_cond_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "csetm %[c], cc\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 512\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return c; +#else + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x11, x12, [%[b], 48]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 48]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 48]\n\t" + "ldp x5, x7, [%[b], 64]\n\t" + "ldp x11, x12, [%[b], 80]\n\t" + "ldp x4, x6, [%[a], 64]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 80]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 64]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 80]\n\t" + "ldp x5, x7, [%[b], 96]\n\t" + "ldp x11, x12, [%[b], 112]\n\t" + "ldp x4, x6, [%[a], 96]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 112]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 96]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 112]\n\t" + "ldp x5, x7, [%[b], 128]\n\t" + "ldp x11, x12, [%[b], 144]\n\t" + "ldp x4, x6, [%[a], 128]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 144]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 128]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 144]\n\t" + "ldp x5, x7, [%[b], 160]\n\t" + "ldp x11, x12, [%[b], 176]\n\t" + "ldp x4, x6, [%[a], 160]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 176]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 160]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 176]\n\t" + "ldp x5, x7, [%[b], 192]\n\t" + "ldp x11, x12, [%[b], 208]\n\t" + "ldp x4, x6, [%[a], 192]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 208]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 192]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 208]\n\t" + "ldp x5, x7, [%[b], 224]\n\t" + "ldp x11, x12, [%[b], 240]\n\t" + "ldp x4, x6, [%[a], 224]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 240]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 224]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 240]\n\t" + "ldp x5, x7, [%[b], 256]\n\t" + "ldp x11, x12, [%[b], 272]\n\t" + "ldp x4, x6, [%[a], 256]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 272]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 256]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 272]\n\t" + "ldp x5, x7, [%[b], 288]\n\t" + "ldp x11, x12, [%[b], 304]\n\t" + "ldp x4, x6, [%[a], 288]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 304]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 288]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 304]\n\t" + "ldp x5, x7, [%[b], 320]\n\t" + "ldp x11, x12, [%[b], 336]\n\t" + "ldp x4, x6, [%[a], 320]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 336]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 320]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 336]\n\t" + "ldp x5, x7, [%[b], 352]\n\t" + "ldp x11, x12, [%[b], 368]\n\t" + "ldp x4, x6, [%[a], 352]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 368]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 352]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 368]\n\t" + "ldp x5, x7, [%[b], 384]\n\t" + "ldp x11, x12, [%[b], 400]\n\t" + "ldp x4, x6, [%[a], 384]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 400]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 384]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 400]\n\t" + "ldp x5, x7, [%[b], 416]\n\t" + "ldp x11, x12, [%[b], 432]\n\t" + "ldp x4, x6, [%[a], 416]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 432]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 416]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 432]\n\t" + "ldp x5, x7, [%[b], 448]\n\t" + "ldp x11, x12, [%[b], 464]\n\t" + "ldp x4, x6, [%[a], 448]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 464]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 448]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 464]\n\t" + "ldp x5, x7, [%[b], 480]\n\t" + "ldp x11, x12, [%[b], 496]\n\t" + "ldp x4, x6, [%[a], 480]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 496]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 480]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 496]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Reduce the number back to 4096 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_4096_mont_reduce_64(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "ldp x14, x15, [%[m], 0]\n\t" + "ldp x16, x17, [%[m], 16]\n\t" + "ldp x19, x20, [%[m], 32]\n\t" + "ldp x21, x22, [%[m], 48]\n\t" + "ldp x23, x24, [%[m], 64]\n\t" + "ldp x25, x26, [%[m], 80]\n\t" + "ldp x27, x28, [%[m], 96]\n\t" + "# i = 64\n\t" + "mov x4, 64\n\t" + "ldp x12, x13, [%[a], 0]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul x9, %[mp], x12\n\t" + "# a[i+0] += m[0] * mu\n\t" + "mul x7, x14, x9\n\t" + "umulh x8, x14, x9\n\t" + "adds x12, x12, x7\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mul x7, x15, x9\n\t" + "adc x6, x8, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x12, x13, x7\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr x13, [%[a], 16]\n\t" + "adc x5, x8, xzr\n\t" + "mul x7, x16, x9\n\t" + "adds x12, x12, x6\n\t" + "umulh x8, x16, x9\n\t" + "adc x5, x5, xzr\n\t" + "adds x13, x13, x7\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr x10, [%[a], 24]\n\t" + "adc x6, x8, xzr\n\t" + "mul x7, x17, x9\n\t" + "adds x13, x13, x5\n\t" + "umulh x8, x17, x9\n\t" + "adc x6, x6, xzr\n\t" + "adds x10, x10, x7\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr x11, [%[a], 32]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x19, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x19, x9\n\t" + "str x10, [%[a], 24]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr x10, [%[a], 40]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x20, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x20, x9\n\t" + "str x11, [%[a], 32]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr x11, [%[a], 48]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x21, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x21, x9\n\t" + "str x10, [%[a], 40]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr x10, [%[a], 56]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x22, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x22, x9\n\t" + "str x11, [%[a], 48]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr x11, [%[a], 64]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x23, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x23, x9\n\t" + "str x10, [%[a], 56]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr x10, [%[a], 72]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x24, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x24, x9\n\t" + "str x11, [%[a], 64]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr x11, [%[a], 80]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x25, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x25, x9\n\t" + "str x10, [%[a], 72]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr x10, [%[a], 88]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x26, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x26, x9\n\t" + "str x11, [%[a], 80]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr x11, [%[a], 96]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x27, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x27, x9\n\t" + "str x10, [%[a], 88]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr x10, [%[a], 104]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x28, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x28, x9\n\t" + "str x11, [%[a], 96]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr x11, [%[a], 112]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 112]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 104]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr x10, [%[a], 120]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 120]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 112]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr x11, [%[a], 128]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 128]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 120]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr x10, [%[a], 136]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 136]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 128]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr x11, [%[a], 144]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 144]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 136]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr x10, [%[a], 152]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 152]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 144]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr x11, [%[a], 160]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 160]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 152]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr x10, [%[a], 168]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 168]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 160]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr x11, [%[a], 176]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 176]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 168]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr x10, [%[a], 184]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 184]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 176]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr x11, [%[a], 192]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 192]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 184]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr x10, [%[a], 200]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 200]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 192]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr x11, [%[a], 208]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 208]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 200]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr x10, [%[a], 216]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 216]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 208]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr x11, [%[a], 224]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 224]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 216]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr x10, [%[a], 232]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 232]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 224]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr x11, [%[a], 240]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 240]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 232]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr x10, [%[a], 248]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 248]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 240]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+32] += m[32] * mu\n\t" + "ldr x11, [%[a], 256]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 256]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 248]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+33] += m[33] * mu\n\t" + "ldr x10, [%[a], 264]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 264]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 256]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+34] += m[34] * mu\n\t" + "ldr x11, [%[a], 272]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 272]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 264]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+35] += m[35] * mu\n\t" + "ldr x10, [%[a], 280]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 280]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 272]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+36] += m[36] * mu\n\t" + "ldr x11, [%[a], 288]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 288]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 280]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+37] += m[37] * mu\n\t" + "ldr x10, [%[a], 296]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 296]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 288]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+38] += m[38] * mu\n\t" + "ldr x11, [%[a], 304]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 304]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 296]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+39] += m[39] * mu\n\t" + "ldr x10, [%[a], 312]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 312]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 304]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+40] += m[40] * mu\n\t" + "ldr x11, [%[a], 320]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 320]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 312]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+41] += m[41] * mu\n\t" + "ldr x10, [%[a], 328]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 328]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 320]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+42] += m[42] * mu\n\t" + "ldr x11, [%[a], 336]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 336]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 328]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+43] += m[43] * mu\n\t" + "ldr x10, [%[a], 344]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 344]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 336]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+44] += m[44] * mu\n\t" + "ldr x11, [%[a], 352]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 352]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 344]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+45] += m[45] * mu\n\t" + "ldr x10, [%[a], 360]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 360]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 352]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+46] += m[46] * mu\n\t" + "ldr x11, [%[a], 368]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 368]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 360]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+47] += m[47] * mu\n\t" + "ldr x10, [%[a], 376]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 376]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 368]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+48] += m[48] * mu\n\t" + "ldr x11, [%[a], 384]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 384]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 376]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+49] += m[49] * mu\n\t" + "ldr x10, [%[a], 392]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 392]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 384]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+50] += m[50] * mu\n\t" + "ldr x11, [%[a], 400]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 400]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 392]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+51] += m[51] * mu\n\t" + "ldr x10, [%[a], 408]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 408]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 400]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+52] += m[52] * mu\n\t" + "ldr x11, [%[a], 416]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 416]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 408]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+53] += m[53] * mu\n\t" + "ldr x10, [%[a], 424]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 424]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 416]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+54] += m[54] * mu\n\t" + "ldr x11, [%[a], 432]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 432]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 424]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+55] += m[55] * mu\n\t" + "ldr x10, [%[a], 440]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 440]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 432]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+56] += m[56] * mu\n\t" + "ldr x11, [%[a], 448]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 448]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 440]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+57] += m[57] * mu\n\t" + "ldr x10, [%[a], 456]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 456]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 448]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+58] += m[58] * mu\n\t" + "ldr x11, [%[a], 464]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 464]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 456]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+59] += m[59] * mu\n\t" + "ldr x10, [%[a], 472]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 472]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 464]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+60] += m[60] * mu\n\t" + "ldr x11, [%[a], 480]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 480]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 472]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+61] += m[61] * mu\n\t" + "ldr x10, [%[a], 488]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 488]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x11, [%[a], 480]\n\t" + "adds x10, x10, x7\n\t" + "# a[i+62] += m[62] * mu\n\t" + "ldr x11, [%[a], 496]\n\t" + "adc x5, x8, xzr\n\t" + "ldr x8, [%[m], 496]\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x8, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x8, x9\n\t" + "str x10, [%[a], 488]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+63] += m[63] * mu\n\t" + "ldr x10, [%[a], 504]\n\t" + "adc x6, x8, xzr\n\t" + "ldr x8, [%[m], 504]\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x8, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x8, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x8, x8, %[ca]\n\t" + "str x11, [%[a], 496]\n\t" + "cset %[ca], cs\n\t" + "adds x10, x10, x6\n\t" + "ldr x11, [%[a], 512]\n\t" + "str x10, [%[a], 504]\n\t" + "adcs x11, x11, x8\n\t" + "str x11, [%[a], 512]\n\t" + "adc %[ca], %[ca], xzr\n\t" + "subs x4, x4, 1\n\t" + "add %[a], %[a], 8\n\t" + "bne 1b\n\t" + "stp x12, x13, [%[a], 0]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28" + ); + + sp_4096_cond_sub_64(a - 64, 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_4096_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_4096_mul_64(r, a, b); + sp_4096_mont_reduce_64(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_4096_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_4096_sqr_64(r, a); + sp_4096_mont_reduce_64(r, m, mp); +} + +/* 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_4096_word_64(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "sub %[d0], %[d0], x4\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add %[r], x6, x3\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + 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_4096_mask_64(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<64; 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; + } +#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_4096_cmp_64(const sp_digit* a, const sp_digit* b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "mov x5, 504\n\t" + "1:\n\t" + "ldr x6, [%[a], x5]\n\t" + "ldr x7, [%[b], x5]\n\t" + "and x6, x6, x4\n\t" + "and x7, x7, x4\n\t" + "subs x6, x6, x7\n\t" + "csel x2, x3, x2, hi\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "subs x5, x5, #8\n\t" + "b.cs 1b\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "ldp x5, x6, [%[a], 496]\n\t" + "ldp x7, x8, [%[b], 496]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 480]\n\t" + "ldp x7, x8, [%[b], 480]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 464]\n\t" + "ldp x7, x8, [%[b], 464]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 448]\n\t" + "ldp x7, x8, [%[b], 448]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 432]\n\t" + "ldp x7, x8, [%[b], 432]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 416]\n\t" + "ldp x7, x8, [%[b], 416]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 400]\n\t" + "ldp x7, x8, [%[b], 400]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 384]\n\t" + "ldp x7, x8, [%[b], 384]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 368]\n\t" + "ldp x7, x8, [%[b], 368]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 352]\n\t" + "ldp x7, x8, [%[b], 352]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 336]\n\t" + "ldp x7, x8, [%[b], 336]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 320]\n\t" + "ldp x7, x8, [%[b], 320]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 304]\n\t" + "ldp x7, x8, [%[b], 304]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 288]\n\t" + "ldp x7, x8, [%[b], 288]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 272]\n\t" + "ldp x7, x8, [%[b], 272]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 256]\n\t" + "ldp x7, x8, [%[b], 256]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "ldp x7, x8, [%[b], 240]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 224]\n\t" + "ldp x7, x8, [%[b], 224]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "ldp x7, x8, [%[b], 208]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 192]\n\t" + "ldp x7, x8, [%[b], 192]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "ldp x7, x8, [%[b], 176]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 160]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "ldp x7, x8, [%[b], 144]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 128]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "ldp x7, x8, [%[b], 112]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "ldp x7, x8, [%[b], 80]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "ldp x7, x8, [%[b], 48]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 16]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "ldp x5, x6, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "and x6, x6, x4\n\t" + "and x8, x8, x4\n\t" + "subs x6, x6, x8\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x7, x7, x4\n\t" + "subs x5, x5, x7\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#endif + + return (int64_t)a; +} + +/* 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 WC_INLINE int sp_4096_div_64(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_4096_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_4096_mul_d_64(t2, d, r1); + t1[64 + i] += sp_4096_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + sp_4096_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_4096_add_64(&t1[i], &t1[i], t2); + sp_4096_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_4096_add_64(&t1[i], &t1[i], t2); + } + + r1 = sp_4096_cmp_64(t1, d) >= 0; + sp_4096_cond_sub_64(r, t1, d, (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 WC_INLINE int sp_4096_mod_64(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_64(a, m, NULL, 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 sp_digit sp_4096_sub_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 512\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#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 sp_digit sp_4096_sub_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "subs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 144]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 176]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "ldp x3, x4, [%[a], 192]\n\t" + "ldp x7, x8, [%[b], 192]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 208]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 192]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 208]\n\t" + "ldp x3, x4, [%[a], 224]\n\t" + "ldp x7, x8, [%[b], 224]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 240]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 224]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 240]\n\t" + "ldp x3, x4, [%[a], 256]\n\t" + "ldp x7, x8, [%[b], 256]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 272]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 272]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 256]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 272]\n\t" + "ldp x3, x4, [%[a], 288]\n\t" + "ldp x7, x8, [%[b], 288]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 304]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 304]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 288]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 304]\n\t" + "ldp x3, x4, [%[a], 320]\n\t" + "ldp x7, x8, [%[b], 320]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 336]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 336]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 320]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 336]\n\t" + "ldp x3, x4, [%[a], 352]\n\t" + "ldp x7, x8, [%[b], 352]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 368]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 368]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 352]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 368]\n\t" + "ldp x3, x4, [%[a], 384]\n\t" + "ldp x7, x8, [%[b], 384]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 400]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 400]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 384]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 400]\n\t" + "ldp x3, x4, [%[a], 416]\n\t" + "ldp x7, x8, [%[b], 416]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 432]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 432]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 416]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 432]\n\t" + "ldp x3, x4, [%[a], 448]\n\t" + "ldp x7, x8, [%[b], 448]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 464]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 464]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 448]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 464]\n\t" + "ldp x3, x4, [%[a], 480]\n\t" + "ldp x7, x8, [%[b], 480]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 496]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 496]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 480]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 496]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +#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 MP_OKAY indicating success. + */ +static WC_INLINE int sp_4096_div_64_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_4096_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_4096_mul_d_64(t2, d, r1); + t1[64 + i] += sp_4096_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + if (t1[64 + i] != 0) { + t1[64 + i] += sp_4096_add_64(&t1[i], &t1[i], d); + if (t1[64 + i] != 0) + t1[64 + i] += sp_4096_add_64(&t1[i], &t1[i], d); + } + } + + for (i = 63; i > 0; i--) { + if (t1[i] != d[i]) + break; + } + if (t1[i] >= d[i]) { + sp_4096_sub_64(r, t1, d); + } + else { + XMEMCPY(r, t1, sizeof(*t1) * 64); + } + + 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 WC_INLINE int sp_4096_mod_64_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_64_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* 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_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][128]; +#else + sp_digit* t[16]; + 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) * 16 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 128; + } +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64U); + if (reduceA != 0) { + err = sp_4096_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) { + err = sp_4096_mod_64(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_4096_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_64(t[10], t[ 5], m, mp); + sp_4096_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_64(t[12], t[ 6], m, mp); + sp_4096_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_64(t[14], t[ 7], m, mp); + sp_4096_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 4; + if (c == 64) { + c = 60; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + } + else if (c < 4) { + y = n >> 60; + n = e[i--]; + c = 4 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 60) & 0xf; + n <<= 4; + c -= 4; + } + + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + + sp_4096_mont_mul_64(r, r, t[y], m, mp); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U); + sp_4096_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_4096_cmp_64(r, m) >= 0); + sp_4096_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#else +/* 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_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][128]; +#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 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 128; + } +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64U); + if (reduceA != 0) { + err = sp_4096_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) { + err = sp_4096_mod_64(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_4096_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_64(t[10], t[ 5], m, mp); + sp_4096_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_64(t[12], t[ 6], m, mp); + sp_4096_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_64(t[14], t[ 7], m, mp); + sp_4096_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + sp_4096_mont_sqr_64(t[16], t[ 8], m, mp); + sp_4096_mont_mul_64(t[17], t[ 9], t[ 8], m, mp); + sp_4096_mont_sqr_64(t[18], t[ 9], m, mp); + sp_4096_mont_mul_64(t[19], t[10], t[ 9], m, mp); + sp_4096_mont_sqr_64(t[20], t[10], m, mp); + sp_4096_mont_mul_64(t[21], t[11], t[10], m, mp); + sp_4096_mont_sqr_64(t[22], t[11], m, mp); + sp_4096_mont_mul_64(t[23], t[12], t[11], m, mp); + sp_4096_mont_sqr_64(t[24], t[12], m, mp); + sp_4096_mont_mul_64(t[25], t[13], t[12], m, mp); + sp_4096_mont_sqr_64(t[26], t[13], m, mp); + sp_4096_mont_mul_64(t[27], t[14], t[13], m, mp); + sp_4096_mont_sqr_64(t[28], t[14], m, mp); + sp_4096_mont_mul_64(t[29], t[15], t[14], m, mp); + sp_4096_mont_sqr_64(t[30], t[15], m, mp); + sp_4096_mont_mul_64(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 5; + if (c == 64) { + c = 59; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + 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_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + + sp_4096_mont_mul_64(r, r, t[y], m, mp); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U); + sp_4096_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_4096_cmp_64(r, m) >= 0); + sp_4096_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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 512 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_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[128], m[64], r[128]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; +#endif + sp_digit *ah; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 512) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 64 || inLen > 512 || + mp_count_bits(mm) != 4096)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 64 * 2; + m = r + 64 * 2; + } +#endif + + if (err == MP_OKAY) { + ah = a + 64; + + sp_4096_from_bin(ah, 64, 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_4096_from_mp(m, 64, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_4096_sqr_64(r, ah); + err = sp_4096_mod_64_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_4096_mul_64(r, ah, r); + err = sp_4096_mod_64_cond(r, r, m); + } + } + else { + int i; + sp_digit mp; + + sp_4096_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 64); + err = sp_4096_mod_64_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) * 64); + for (i--; i>=0; i--) { + sp_4096_mont_sqr_64(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) { + sp_4096_mont_mul_64(r, r, a, m, mp); + } + } + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_4096_mont_reduce_64(r, m, mp); + + for (i = 63; i > 0; i--) { + if (r[i] != m[i]) { + break; + } + } + if (r[i] >= m[i]) { + sp_4096_sub_in_place_64(r, m); + } + } + } + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) + 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 < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 4096) { + err = MP_READ_E; + } + if (inLen > 512) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 64; + m = a + 128; + r = a; + + sp_4096_from_bin(a, 64, in, inLen); + sp_4096_from_mp(d, 64, dm); + sp_4096_from_mp(m, 64, mm); + err = sp_4096_mod_exp_64(r, a, d, 4096, m, 0); + } + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 64); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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 sp_digit sp_4096_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "cset %[c], cs\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 256\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return c; +#else + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "adds x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x11, x12, [%[b], 48]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 48]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 48]\n\t" + "ldp x5, x7, [%[b], 64]\n\t" + "ldp x11, x12, [%[b], 80]\n\t" + "ldp x4, x6, [%[a], 64]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 80]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 64]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 80]\n\t" + "ldp x5, x7, [%[b], 96]\n\t" + "ldp x11, x12, [%[b], 112]\n\t" + "ldp x4, x6, [%[a], 96]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 112]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 96]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 112]\n\t" + "ldp x5, x7, [%[b], 128]\n\t" + "ldp x11, x12, [%[b], 144]\n\t" + "ldp x4, x6, [%[a], 128]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 144]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 128]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 144]\n\t" + "ldp x5, x7, [%[b], 160]\n\t" + "ldp x11, x12, [%[b], 176]\n\t" + "ldp x4, x6, [%[a], 160]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 176]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 160]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 176]\n\t" + "ldp x5, x7, [%[b], 192]\n\t" + "ldp x11, x12, [%[b], 208]\n\t" + "ldp x4, x6, [%[a], 192]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 208]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 192]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 208]\n\t" + "ldp x5, x7, [%[b], 224]\n\t" + "ldp x11, x12, [%[b], 240]\n\t" + "ldp x4, x6, [%[a], 224]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 240]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 224]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 240]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +#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 512 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_4096(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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[64 * 2]; + sp_digit p[32], q[32], dp[32]; + sp_digit tmpa[64], tmpb[64]; +#else + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* tmpa; + sp_digit* tmpb; +#endif + sp_digit* r; + sp_digit* qi; + sp_digit* dq; + sp_digit c; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 512) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 512 || mp_count_bits(mm) != 4096)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 64 * 2; + q = p + 32; + qi = dq = dp = q + 32; + tmpa = qi + 32; + tmpb = tmpa + 64; + + r = t + 64; + } +#else +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + r = a; + qi = dq = dp; +#endif + sp_4096_from_bin(a, 64, in, inLen); + sp_4096_from_mp(p, 32, pm); + sp_4096_from_mp(q, 32, qm); + sp_4096_from_mp(dp, 32, dpm); + + err = sp_2048_mod_exp_32(tmpa, a, dp, 2048, p, 1); + } + if (err == MP_OKAY) { + sp_4096_from_mp(dq, 32, dqm); + err = sp_2048_mod_exp_32(tmpb, a, dq, 2048, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_32(tmpa, tmpb); + c += sp_4096_cond_add_32(tmpa, tmpa, p, c); + sp_4096_cond_add_32(tmpa, tmpa, p, c); + + sp_2048_from_mp(qi, 32, qim); + sp_2048_mul_32(tmpa, tmpa, qi); + err = sp_2048_mod_32(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_32(tmpa, q, tmpa); + XMEMSET(&tmpb[32], 0, sizeof(sp_digit) * 32); + sp_4096_add_64(r, tmpb, tmpa); + + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + 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)); +#endif + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_4096_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 64); + r->used = 64; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 64 - s; + } + r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && 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 = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 64, base); + sp_4096_from_mp(e, 64, exp); + sp_4096_from_mp(m, 64, mod); + + err = sp_4096_mod_exp_64(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_4096_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_4096 +static void sp_4096_lshift_64(sp_digit* r, sp_digit* a, byte n) +{ + __asm__ __volatile__ ( + "mov x6, 63\n\t" + "sub x6, x6, %[n]\n\t" + "ldr x3, [%[a], 504]\n\t" + "lsr x4, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x4, x4, x6\n\t" + "ldr x2, [%[a], 496]\n\t" + "str x4, [%[r], 512]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 488]\n\t" + "str x3, [%[r], 504]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 480]\n\t" + "str x2, [%[r], 496]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 472]\n\t" + "str x4, [%[r], 488]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 464]\n\t" + "str x3, [%[r], 480]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 456]\n\t" + "str x2, [%[r], 472]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 448]\n\t" + "str x4, [%[r], 464]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 440]\n\t" + "str x3, [%[r], 456]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 432]\n\t" + "str x2, [%[r], 448]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 424]\n\t" + "str x4, [%[r], 440]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 416]\n\t" + "str x3, [%[r], 432]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 408]\n\t" + "str x2, [%[r], 424]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 400]\n\t" + "str x4, [%[r], 416]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 392]\n\t" + "str x3, [%[r], 408]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 384]\n\t" + "str x2, [%[r], 400]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 376]\n\t" + "str x4, [%[r], 392]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 368]\n\t" + "str x3, [%[r], 384]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 360]\n\t" + "str x2, [%[r], 376]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 352]\n\t" + "str x4, [%[r], 368]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 344]\n\t" + "str x3, [%[r], 360]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 336]\n\t" + "str x2, [%[r], 352]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 328]\n\t" + "str x4, [%[r], 344]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 320]\n\t" + "str x3, [%[r], 336]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 312]\n\t" + "str x2, [%[r], 328]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 304]\n\t" + "str x4, [%[r], 320]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 296]\n\t" + "str x3, [%[r], 312]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 288]\n\t" + "str x2, [%[r], 304]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 280]\n\t" + "str x4, [%[r], 296]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 272]\n\t" + "str x3, [%[r], 288]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 264]\n\t" + "str x2, [%[r], 280]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 256]\n\t" + "str x4, [%[r], 272]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 248]\n\t" + "str x3, [%[r], 264]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 240]\n\t" + "str x2, [%[r], 256]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 232]\n\t" + "str x4, [%[r], 248]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 224]\n\t" + "str x3, [%[r], 240]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 216]\n\t" + "str x2, [%[r], 232]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 208]\n\t" + "str x4, [%[r], 224]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 200]\n\t" + "str x3, [%[r], 216]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 192]\n\t" + "str x2, [%[r], 208]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 184]\n\t" + "str x4, [%[r], 200]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 176]\n\t" + "str x3, [%[r], 192]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 168]\n\t" + "str x2, [%[r], 184]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 160]\n\t" + "str x4, [%[r], 176]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 152]\n\t" + "str x3, [%[r], 168]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 144]\n\t" + "str x2, [%[r], 160]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 136]\n\t" + "str x4, [%[r], 152]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 128]\n\t" + "str x3, [%[r], 144]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 120]\n\t" + "str x2, [%[r], 136]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 112]\n\t" + "str x4, [%[r], 128]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 104]\n\t" + "str x3, [%[r], 120]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 96]\n\t" + "str x2, [%[r], 112]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 88]\n\t" + "str x4, [%[r], 104]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 80]\n\t" + "str x3, [%[r], 96]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 72]\n\t" + "str x2, [%[r], 88]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 64]\n\t" + "str x4, [%[r], 80]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 56]\n\t" + "str x3, [%[r], 72]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 48]\n\t" + "str x2, [%[r], 64]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 40]\n\t" + "str x4, [%[r], 56]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 32]\n\t" + "str x3, [%[r], 48]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 24]\n\t" + "str x2, [%[r], 40]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "ldr x2, [%[a], 16]\n\t" + "str x4, [%[r], 32]\n\t" + "lsr x5, x2, 1\n\t" + "lsl x2, x2, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x3, x3, x5\n\t" + "ldr x4, [%[a], 8]\n\t" + "str x3, [%[r], 24]\n\t" + "lsr x5, x4, 1\n\t" + "lsl x4, x4, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x2, x2, x5\n\t" + "ldr x3, [%[a], 0]\n\t" + "str x2, [%[r], 16]\n\t" + "lsr x5, x3, 1\n\t" + "lsl x3, x3, %[n]\n\t" + "lsr x5, x5, x6\n\t" + "orr x4, x4, x5\n\t" + "str x3, [%[r]]\n\t" + "str x4, [%[r], 8]\n\t" + : + : [r] "r" (r), [a] "r" (a), [n] "r" (n) + : "memory", "x2", "x3", "x4", "x5", "x6" + ); +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[128]; + sp_digit td[65]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 193, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 128; +#else + norm = nd; + tmp = td; +#endif + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_64(norm, m); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + c -= bits % 6; + if (c == 64) { + c = 58; + } + y = (int)(n >> c); + n <<= 64 - c; + sp_4096_lshift_64(r, norm, y); + for (; i>=0 || c>=6; ) { + if (c == 0) { + n = e[i--]; + y = n >> 58; + n <<= 6; + c = 58; + } + else if (c < 6) { + y = n >> 58; + n = e[i--]; + c = 6 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 58) & 0x3f; + n <<= 6; + c -= 6; + } + + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + + sp_4096_lshift_64(r, r, y); + sp_4096_mul_d_64(tmp, norm, r[64]); + r[64] = 0; + o = sp_4096_add_64(r, r, tmp); + sp_4096_cond_sub_64(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U); + sp_4096_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_4096_cmp_64(r, m) >= 0); + sp_4096_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* HAVE_FFDHE_4096 */ + +/* 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 512 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returns 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_4096(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 512) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 64, base); + sp_4096_from_bin(e, 64, exp, expLen); + sp_4096_from_mp(m, 64, mod); + + #ifdef HAVE_FFDHE_4096 + if (base->used == 1 && base->dp[0] == 2 && m[63] == (sp_digit)-1) + err = sp_4096_mod_exp_2_64(r, e, expLen * 8, m); + else + #endif + err = sp_4096_mod_exp_64(r, b, e, expLen * 8, m, 0); + + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + for (i=0; i<512 && 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_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* WOLFSSL_SP_4096 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point_256 { + sp_digit x[2 * 4]; + sp_digit y[2 * 4]; + sp_digit z[2 * 4]; + int infinity; +} sp_point_256; + +/* The modulus (prime) of the curve P256. */ +static const sp_digit p256_mod[4] = { + 0xffffffffffffffffL,0x00000000ffffffffL,0x0000000000000000L, + 0xffffffff00000001L +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static const sp_digit p256_norm_mod[4] = { + 0x0000000000000001L,0xffffffff00000000L,0xffffffffffffffffL, + 0x00000000fffffffeL +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static const 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 const sp_digit p256_order[4] = { + 0xf3b9cac2fc632551L,0xbce6faada7179e84L,0xffffffffffffffffL, + 0xffffffff00000000L +}; +#endif +/* The order of the curve P256 minus 2. */ +static const 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 const 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 const sp_digit p256_mp_order = 0xccd1c8aaee00bc4fL; +#endif +#ifdef WOLFSSL_SP_SMALL +/* The base point of curve P256. */ +static const sp_point_256 p256_base = { + /* X ordinate */ + { + 0xf4a13945d898c296L,0x77037d812deb33a0L,0xf8bce6e563a440f2L, + 0x6b17d1f2e12c4247L, + 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0xcbb6406837bf51f5L,0x2bce33576b315eceL,0x8ee7eb4a7c0f9e16L, + 0x4fe342e2fe1a7f9bL, + 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x0000000000000001L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L, + 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#endif /* WOLFSSL_SP_SMALL */ +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p256_b[4] = { + 0x3bce3c3e27d2604bL,0x651d06b0cc53b0f6L,0xb3ebbd55769886bcL, + 0x5ac635d8aa3a93e7L +}; +#endif + +static int sp_256_point_new_ex_4(void* heap, sp_point_256* sp, sp_point_256** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_256_point_new_4(heap, sp, p) sp_256_point_new_ex_4((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_256_point_new_4(heap, sp, p) sp_256_point_new_ex_4((heap), &(sp), &(p)) +#endif + + +static void sp_256_point_free_4(sp_point_256* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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, const sp_digit* a, const 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. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_256. + * + * p Point of type sp_point_256 (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_4(sp_point_256* p, const 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(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always 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] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(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 != 32 && 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_256 to type ecc_point. + * + * p Point of type sp_point_256. + * 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(const sp_point_256* 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 a into r 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, sp_digit m) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[r], 0]\n\t" + "ldp x7, x8, [%[a], 0]\n\t" + "eor x7, x7, x3\n\t" + "ldp x5, x6, [%[r], 16]\n\t" + "eor x8, x8, x4\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "eor x9, x9, x5\n\t" + "eor x10, x10, x6\n\t" + "and x7, x7, %[m]\n\t" + "and x8, x8, %[m]\n\t" + "and x9, x9, %[m]\n\t" + "and x10, x10, %[m]\n\t" + "eor x3, x3, x7\n\t" + "eor x4, x4, x8\n\t" + "eor x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "eor x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); +} + +/* 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, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + (void)m; + (void)mp; + + __asm__ __volatile__ ( + "ldp x16, x17, [%[a], 0]\n\t" + "ldp x21, x22, [%[b], 0]\n\t" + "# A[0] * B[0]\n\t" + "mul x8, x16, x21\n\t" + "ldr x19, [%[a], 16]\n\t" + "umulh x9, x16, x21\n\t" + "ldr x23, [%[b], 16]\n\t" + "# A[0] * B[1]\n\t" + "mul x4, x16, x22\n\t" + "ldr x20, [%[a], 24]\n\t" + "umulh x5, x16, x22\n\t" + "ldr x24, [%[b], 24]\n\t" + "adds x9, x9, x4\n\t" + "# A[1] * B[0]\n\t" + "mul x4, x17, x21\n\t" + "adc x10, xzr, x5\n\t" + "umulh x5, x17, x21\n\t" + "adds x9, x9, x4\n\t" + "# A[0] * B[2]\n\t" + "mul x4, x16, x23\n\t" + "adcs x10, x10, x5\n\t" + "umulh x5, x16, x23\n\t" + "adc x11, xzr, xzr\n\t" + "adds x10, x10, x4\n\t" + "# A[1] * B[1]\n\t" + "mul x4, x17, x22\n\t" + "adc x11, x11, x5\n\t" + "umulh x5, x17, x22\n\t" + "adds x10, x10, x4\n\t" + "# A[2] * B[0]\n\t" + "mul x4, x19, x21\n\t" + "adcs x11, x11, x5\n\t" + "umulh x5, x19, x21\n\t" + "adc x12, xzr, xzr\n\t" + "adds x10, x10, x4\n\t" + "# A[0] * B[3]\n\t" + "mul x4, x16, x24\n\t" + "adcs x11, x11, x5\n\t" + "umulh x5, x16, x24\n\t" + "adc x12, x12, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * B[2]\n\t" + "mul x4, x17, x23\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x17, x23\n\t" + "adc x13, xzr, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[2] * B[1]\n\t" + "mul x4, x19, x22\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x19, x22\n\t" + "adc x13, x13, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[3] * B[0]\n\t" + "mul x4, x20, x21\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x20, x21\n\t" + "adc x13, x13, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * B[3]\n\t" + "mul x4, x17, x24\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x17, x24\n\t" + "adc x13, x13, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[2] * B[2]\n\t" + "mul x4, x19, x23\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x19, x23\n\t" + "adc x14, xzr, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[3] * B[1]\n\t" + "mul x4, x20, x22\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x20, x22\n\t" + "adc x14, x14, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[2] * B[3]\n\t" + "mul x4, x19, x24\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x19, x24\n\t" + "adc x14, x14, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[3] * B[2]\n\t" + "mul x4, x20, x23\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x20, x23\n\t" + "adc x15, xzr, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[3] * B[3]\n\t" + "mul x4, x20, x24\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x20, x24\n\t" + "adc x15, x15, xzr\n\t" + "adds x14, x14, x4\n\t" + "mov x4, x8\n\t" + "adc x15, x15, x5\n\t" + "# Start Reduction\n\t" + "mov x5, x9\n\t" + "mov x6, x10\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" + "# a[0]-a[2] << 32\n\t" + "lsl x10, x10, 32\n\t" + "add x7, x11, x8\n\t" + "eor x10, x10, x9, lsr #32\n\t" + "lsl x9, x9, 32\n\t" + "add x7, x7, x8\n\t" + "eor x9, x9, x8, lsr #32\n\t" + "# + a[0]-a[2] << 32 << 64\n\t" + "# - a[0] << 32 << 192\n\t" + "adds x5, x5, x8, lsl #32\n\t" + "sub x7, x7, x8, lsl #32\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, x10\n\t" + "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t" + "# a += mu << 256\n\t" + "adds x12, x12, x4\n\t" + "adcs x13, x13, x5\n\t" + "adcs x14, x14, x6\n\t" + "adcs x15, x15, x7\n\t" + "cset x8, cs\n\t" + "# a += mu << 192\n\t" + "# mu <<= 32\n\t" + "# a += (mu << 32) << 64\n\t" + "adds x11, x11, x4\n\t" + "adcs x12, x12, x5\n\t" + "adcs x13, x13, x6\n\t" + "lsr x16, x7, 32\n\t" + "adcs x14, x14, x7\n\t" + "lsl x7, x7, 32\n\t" + "adcs x15, x15, xzr\n\t" + "eor x7, x7, x6, lsr #32\n\t" + "adc x8, x8, xzr\n\t" + "lsl x6, x6, 32\n\t" + "eor x6, x6, x5, lsr #32\n\t" + "adds x11, x11, x6\n\t" + "lsl x5, x5, 32\n\t" + "adcs x12, x12, x7\n\t" + "eor x5, x5, x4, lsr #32\n\t" + "adcs x13, x13, x16\n\t" + "lsl x4, x4, 32\n\t" + "adcs x14, x14, xzr\n\t" + "adcs x15, x15, xzr\n\t" + "adc x8, x8, xzr\n\t" + "# a -= (mu << 32) << 192\n\t" + "subs x11, x11, x4\n\t" + "sbcs x12, x12, x5\n\t" + "sbcs x13, x13, x6\n\t" + "sub x8, xzr, x8\n\t" + "sbcs x14, x14, x7\n\t" + "sub x8, x8, #1\n\t" + "sbcs x15, x15, x16\n\t" + "mov x19, 0xffffffff00000001\n\t" + "adc x8, x8, xzr\n\t" + "# mask m and sub from result if overflow\n\t" + "# m[0] = -1 & mask = mask\n\t" + "subs x12, x12, x8\n\t" + "# m[1] = 0xffffffff & mask = mask >> 32 as mask is all 1s or 0s\n\t" + "lsr x17, x8, 32\n\t" + "sbcs x13, x13, x17\n\t" + "and x19, x19, x8\n\t" + "# m[2] = 0 & mask = 0\n\t" + "sbcs x14, x14, xzr\n\t" + "stp x12, x13, [%[r], 0]\n\t" + "# m[3] = 0xffffffff00000001 & mask\n\t" + "sbc x15, x15, x19\n\t" + "stp x14, x15, [%[r], 16]\n\t" + : [a] "+r" (a), [b] "+r" (b) + : [r] "r" (r) + : "memory", "x4", "x5", "x6", "x7", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15" + ); +} + +/* 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + (void)m; + (void)mp; + + __asm__ __volatile__ ( + "ldp x16, x17, [%[a], 0]\n\t" + "# A[0] * A[1]\n\t" + "mul x9, x16, x17\n\t" + "ldr x19, [%[a], 16]\n\t" + "umulh x10, x16, x17\n\t" + "ldr x20, [%[a], 24]\n\t" + "# A[0] * A[2]\n\t" + "mul x4, x16, x19\n\t" + "umulh x5, x16, x19\n\t" + "adds x10, x10, x4\n\t" + "# A[0] * A[3]\n\t" + "mul x4, x16, x20\n\t" + "adc x11, xzr, x5\n\t" + "umulh x5, x16, x20\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * A[2]\n\t" + "mul x4, x17, x19\n\t" + "adc x12, xzr, x5\n\t" + "umulh x5, x17, x19\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * A[3]\n\t" + "mul x4, x17, x20\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x17, x20\n\t" + "adc x13, xzr, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[2] * A[3]\n\t" + "mul x4, x19, x20\n\t" + "adc x13, x13, x5\n\t" + "umulh x5, x19, x20\n\t" + "adds x13, x13, x4\n\t" + "adc x14, xzr, x5\n\t" + "# Double\n\t" + "adds x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adcs x11, x11, x11\n\t" + "adcs x12, x12, x12\n\t" + "adcs x13, x13, x13\n\t" + "# A[0] * A[0]\n\t" + "mul x8, x16, x16\n\t" + "adcs x14, x14, x14\n\t" + "umulh x3, x16, x16\n\t" + "cset x15, cs\n\t" + "# A[1] * A[1]\n\t" + "mul x4, x17, x17\n\t" + "adds x9, x9, x3\n\t" + "umulh x5, x17, x17\n\t" + "adcs x10, x10, x4\n\t" + "# A[2] * A[2]\n\t" + "mul x6, x19, x19\n\t" + "adcs x11, x11, x5\n\t" + "umulh x7, x19, x19\n\t" + "adcs x12, x12, x6\n\t" + "# A[3] * A[3]\n\t" + "mul x16, x20, x20\n\t" + "adcs x13, x13, x7\n\t" + "umulh x17, x20, x20\n\t" + "adcs x14, x14, x16\n\t" + "mov x3, x8\n\t" + "adc x15, x15, x17\n\t" + "# Start Reduction\n\t" + "mov x4, x9\n\t" + "mov x5, x10\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" + "# a[0]-a[2] << 32\n\t" + "lsl x10, x10, 32\n\t" + "add x6, x11, x8\n\t" + "eor x10, x10, x9, lsr #32\n\t" + "lsl x9, x9, 32\n\t" + "add x6, x6, x8\n\t" + "eor x9, x9, x8, lsr #32\n\t" + "# + a[0]-a[2] << 32 << 64\n\t" + "# - a[0] << 32 << 192\n\t" + "adds x4, x4, x8, lsl #32\n\t" + "sub x6, x6, x8, lsl #32\n\t" + "adcs x5, x5, x9\n\t" + "adc x6, x6, x10\n\t" + "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t" + "# a += mu << 256\n\t" + "adds x12, x12, x3\n\t" + "adcs x13, x13, x4\n\t" + "adcs x14, x14, x5\n\t" + "adcs x15, x15, x6\n\t" + "cset x8, cs\n\t" + "# a += mu << 192\n\t" + "# mu <<= 32\n\t" + "# a += (mu << 32) << 64\n\t" + "adds x11, x11, x3\n\t" + "adcs x12, x12, x4\n\t" + "adcs x13, x13, x5\n\t" + "lsr x7, x6, 32\n\t" + "adcs x14, x14, x6\n\t" + "lsl x6, x6, 32\n\t" + "adcs x15, x15, xzr\n\t" + "eor x6, x6, x5, lsr #32\n\t" + "adc x8, x8, xzr\n\t" + "lsl x5, x5, 32\n\t" + "eor x5, x5, x4, lsr #32\n\t" + "adds x11, x11, x5\n\t" + "lsl x4, x4, 32\n\t" + "adcs x12, x12, x6\n\t" + "eor x4, x4, x3, lsr #32\n\t" + "adcs x13, x13, x7\n\t" + "lsl x3, x3, 32\n\t" + "adcs x14, x14, xzr\n\t" + "adcs x15, x15, xzr\n\t" + "adc x8, x8, xzr\n\t" + "# a -= (mu << 32) << 192\n\t" + "subs x11, x11, x3\n\t" + "sbcs x12, x12, x4\n\t" + "sbcs x13, x13, x5\n\t" + "sub x8, xzr, x8\n\t" + "sbcs x14, x14, x6\n\t" + "sub x8, x8, #1\n\t" + "sbcs x15, x15, x7\n\t" + "mov x17, 0xffffffff00000001\n\t" + "adc x8, x8, xzr\n\t" + "# mask m and sub from result if overflow\n\t" + "# m[0] = -1 & mask = mask\n\t" + "subs x12, x12, x8\n\t" + "# m[1] = 0xffffffff & mask = mask >> 32 as mask is all 1s or 0s\n\t" + "lsr x16, x8, 32\n\t" + "sbcs x13, x13, x16\n\t" + "and x17, x17, x8\n\t" + "# m[2] = 0 & mask = 0\n\t" + "sbcs x14, x14, xzr\n\t" + "stp x12, x13, [%[r], 0]\n\t" + "# m[3] = 0xffffffff00000001 & mask\n\t" + "sbc x15, x15, x17\n\t" + "stp x14, x15, [%[r], 16]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20" + ); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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, const sp_digit* a, int n, + const 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); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint64_t p256_mod_minus_2[4] = { + 0xfffffffffffffffdU,0x00000000ffffffffU,0x0000000000000000U, + 0xffffffff00000001U +}; +#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, const 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_minus_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* t1 = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + /* 0x2 */ + sp_256_mont_sqr_4(t1, a, p256_mod, p256_mp_mod); + /* 0x3 */ + sp_256_mont_mul_4(t2, t1, a, p256_mod, p256_mp_mod); + /* 0xc */ + sp_256_mont_sqr_n_4(t1, t2, 2, p256_mod, p256_mp_mod); + /* 0xd */ + sp_256_mont_mul_4(t3, t1, a, p256_mod, p256_mp_mod); + /* 0xf */ + sp_256_mont_mul_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xf0 */ + sp_256_mont_sqr_n_4(t1, t2, 4, p256_mod, p256_mp_mod); + /* 0xfd */ + sp_256_mont_mul_4(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xff */ + sp_256_mont_mul_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xff00 */ + sp_256_mont_sqr_n_4(t1, t2, 8, p256_mod, p256_mp_mod); + /* 0xfffd */ + sp_256_mont_mul_4(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffff */ + sp_256_mont_mul_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffff0000 */ + sp_256_mont_sqr_n_4(t1, t2, 16, p256_mod, p256_mp_mod); + /* 0xfffffffd */ + sp_256_mont_mul_4(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffffffff */ + sp_256_mont_mul_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000000 */ + sp_256_mont_sqr_n_4(t1, t2, 32, p256_mod, p256_mp_mod); + /* 0xffffffffffffffff */ + sp_256_mont_mul_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000001 */ + sp_256_mont_mul_4(r, t1, a, p256_mod, p256_mp_mod); + /* 0xffffffff000000010000000000000000000000000000000000000000 */ + sp_256_mont_sqr_n_4(r, r, 160, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff */ + sp_256_mont_mul_4(r, r, t2, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */ + sp_256_mont_sqr_n_4(r, r, 32, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */ + sp_256_mont_mul_4(r, r, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* 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(const sp_digit* a, const sp_digit* b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "mov x5, 24\n\t" + "1:\n\t" + "ldr x6, [%[a], x5]\n\t" + "ldr x7, [%[b], x5]\n\t" + "and x6, x6, x4\n\t" + "and x7, x7, x4\n\t" + "subs x6, x6, x7\n\t" + "csel x2, x3, x2, hi\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "subs x5, x5, #8\n\t" + "b.cs 1b\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12" + ); +#else + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "ldp x5, x6, [%[a], 0]\n\t" + "ldp x7, x8, [%[a], 16]\n\t" + "ldp x9, x10, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "and x8, x8, x4\n\t" + "and x12, x12, x4\n\t" + "subs x8, x8, x12\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x7, x7, x4\n\t" + "and x11, x11, x4\n\t" + "subs x7, x7, x11\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x6, x6, x4\n\t" + "and x10, x10, x4\n\t" + "subs x6, x6, x10\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x9, x9, x4\n\t" + "subs x5, x5, x9\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12" + ); +#endif + + return (int64_t)a; +} + +/* 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, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +} + +/* 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) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "subs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +#define sp_256_mont_reduce_order_4 sp_256_mont_reduce_4 + +/* 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, const sp_digit* m, + sp_digit mp) +{ + __asm__ __volatile__ ( + "ldp x9, x10, [%[a], 0]\n\t" + "ldp x11, x12, [%[a], 16]\n\t" + "ldp x17, x19, [%[m], 0]\n\t" + "ldp x20, x21, [%[m], 16]\n\t" + "mov x8, xzr\n\t" + "# mu = a[0] * mp\n\t" + "mul x5, %[mp], x9\n\t" + "ldr x13, [%[a], 32]\n\t" + "# a[0+0] += m[0] * mu\n\t" + "mul x3, x17, x5\n\t" + "ldr x14, [%[a], 40]\n\t" + "umulh x6, x17, x5\n\t" + "ldr x15, [%[a], 48]\n\t" + "adds x9, x9, x3\n\t" + "ldr x16, [%[a], 56]\n\t" + "adc x6, x6, xzr\n\t" + "# a[0+1] += m[1] * mu\n\t" + "mul x3, x19, x5\n\t" + "umulh x7, x19, x5\n\t" + "adds x3, x3, x6\n\t" + "adc x7, x7, xzr\n\t" + "adds x10, x10, x3\n\t" + "adc x7, x7, xzr\n\t" + "# a[0+2] += m[2] * mu\n\t" + "mul x3, x20, x5\n\t" + "umulh x6, x20, x5\n\t" + "adds x3, x3, x7\n\t" + "adc x6, x6, xzr\n\t" + "adds x11, x11, x3\n\t" + "adc x6, x6, xzr\n\t" + "# a[0+3] += m[3] * mu\n\t" + "mul x3, x21, x5\n\t" + "umulh x4, x21, x5\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x8\n\t" + "cset x8, cs\n\t" + "adds x12, x12, x3\n\t" + "adcs x13, x13, x4\n\t" + "adc x8, x8, xzr\n\t" + "# mu = a[1] * mp\n\t" + "mul x5, %[mp], x10\n\t" + "# a[1+0] += m[0] * mu\n\t" + "mul x3, x17, x5\n\t" + "umulh x6, x17, x5\n\t" + "adds x10, x10, x3\n\t" + "adc x6, x6, xzr\n\t" + "# a[1+1] += m[1] * mu\n\t" + "mul x3, x19, x5\n\t" + "umulh x7, x19, x5\n\t" + "adds x3, x3, x6\n\t" + "adc x7, x7, xzr\n\t" + "adds x11, x11, x3\n\t" + "adc x7, x7, xzr\n\t" + "# a[1+2] += m[2] * mu\n\t" + "mul x3, x20, x5\n\t" + "umulh x6, x20, x5\n\t" + "adds x3, x3, x7\n\t" + "adc x6, x6, xzr\n\t" + "adds x12, x12, x3\n\t" + "adc x6, x6, xzr\n\t" + "# a[1+3] += m[3] * mu\n\t" + "mul x3, x21, x5\n\t" + "umulh x4, x21, x5\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x8\n\t" + "cset x8, cs\n\t" + "adds x13, x13, x3\n\t" + "adcs x14, x14, x4\n\t" + "adc x8, x8, xzr\n\t" + "# mu = a[2] * mp\n\t" + "mul x5, %[mp], x11\n\t" + "# a[2+0] += m[0] * mu\n\t" + "mul x3, x17, x5\n\t" + "umulh x6, x17, x5\n\t" + "adds x11, x11, x3\n\t" + "adc x6, x6, xzr\n\t" + "# a[2+1] += m[1] * mu\n\t" + "mul x3, x19, x5\n\t" + "umulh x7, x19, x5\n\t" + "adds x3, x3, x6\n\t" + "adc x7, x7, xzr\n\t" + "adds x12, x12, x3\n\t" + "adc x7, x7, xzr\n\t" + "# a[2+2] += m[2] * mu\n\t" + "mul x3, x20, x5\n\t" + "umulh x6, x20, x5\n\t" + "adds x3, x3, x7\n\t" + "adc x6, x6, xzr\n\t" + "adds x13, x13, x3\n\t" + "adc x6, x6, xzr\n\t" + "# a[2+3] += m[3] * mu\n\t" + "mul x3, x21, x5\n\t" + "umulh x4, x21, x5\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x8\n\t" + "cset x8, cs\n\t" + "adds x14, x14, x3\n\t" + "adcs x15, x15, x4\n\t" + "adc x8, x8, xzr\n\t" + "# mu = a[3] * mp\n\t" + "mul x5, %[mp], x12\n\t" + "# a[3+0] += m[0] * mu\n\t" + "mul x3, x17, x5\n\t" + "umulh x6, x17, x5\n\t" + "adds x12, x12, x3\n\t" + "adc x6, x6, xzr\n\t" + "# a[3+1] += m[1] * mu\n\t" + "mul x3, x19, x5\n\t" + "umulh x7, x19, x5\n\t" + "adds x3, x3, x6\n\t" + "adc x7, x7, xzr\n\t" + "adds x13, x13, x3\n\t" + "adc x7, x7, xzr\n\t" + "# a[3+2] += m[2] * mu\n\t" + "mul x3, x20, x5\n\t" + "umulh x6, x20, x5\n\t" + "adds x3, x3, x7\n\t" + "adc x6, x6, xzr\n\t" + "adds x14, x14, x3\n\t" + "adc x6, x6, xzr\n\t" + "# a[3+3] += m[3] * mu\n\t" + "mul x3, x21, x5\n\t" + "umulh x4, x21, x5\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x8\n\t" + "cset x8, cs\n\t" + "adds x15, x15, x3\n\t" + "adcs x16, x16, x4\n\t" + "adc x8, x8, xzr\n\t" + "sub x3, xzr, x8\n\t" + "and x17, x17, x3\n\t" + "and x19, x19, x3\n\t" + "and x20, x20, x3\n\t" + "and x21, x21, x3\n\t" + "subs x13, x13, x17\n\t" + "sbcs x14, x14, x19\n\t" + "sbcs x15, x15, x20\n\t" + "stp x13, x14, [%[a], 0]\n\t" + "sbc x16, x16, x21\n\t" + "stp x15, x16, [%[a], 16]\n\t" + : + : [a] "r" (a), [m] "r" (m), [mp] "r" (mp) + : "memory", "x3", "x4", "x5", "x8", "x6", "x7", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21" + ); +} + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_4(sp_point_256* r, const sp_point_256* 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) / 2U); + 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_digit)1 : (sp_digit)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) / 2U); + 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_digit)1 : (sp_digit)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, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldp x4, x5, [%[a], 0]\n\t" + "ldp x8, x9, [%[b], 0]\n\t" + "adds x4, x4, x8\n\t" + "ldp x6, x7, [%[a], 16]\n\t" + "adcs x5, x5, x9\n\t" + "ldp x10, x11, [%[b], 16]\n\t" + "adcs x6, x6, x10\n\t" + "adcs x7, x7, x11\n\t" + "mov x13, 0xffffffff00000001\n\t" + "csetm x14, cs\n\t" + "subs x4, x4, x14\n\t" + "lsr x12, x14, 32\n\t" + "sbcs x5, x5, x12\n\t" + "and x13, x13, x14\n\t" + "sbcs x6, x6, xzr\n\t" + "stp x4, x5, [%[r],0]\n\t" + "sbc x7, x7, x13\n\t" + "stp x6, x7, [%[r],16]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14" + ); +} + +/* 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, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a]]\n\t" + "ldp x5, x6, [%[a],16]\n\t" + "adds x3, x3, x3\n\t" + "adcs x4, x4, x4\n\t" + "adcs x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "mov x8, 0xffffffff00000001\n\t" + "csetm x9, cs\n\t" + "subs x3, x3, x9\n\t" + "lsr x7, x9, 32\n\t" + "sbcs x4, x4, x7\n\t" + "and x8, x8, x9\n\t" + "sbcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r],0]\n\t" + "sbc x6, x6, x8\n\t" + "stp x5, x6, [%[r],16]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + (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, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldp x10, x11, [%[a]]\n\t" + "adds x3, x10, x10\n\t" + "ldr x12, [%[a], 16]\n\t" + "adcs x4, x11, x11\n\t" + "ldr x13, [%[a], 24]\n\t" + "adcs x5, x12, x12\n\t" + "adcs x6, x13, x13\n\t" + "mov x8, 0xffffffff00000001\n\t" + "csetm x9, cs\n\t" + "subs x3, x3, x9\n\t" + "lsr x7, x9, 32\n\t" + "sbcs x4, x4, x7\n\t" + "and x8, x8, x9\n\t" + "sbcs x5, x5, xzr\n\t" + "sbc x6, x6, x8\n\t" + "adds x3, x3, x10\n\t" + "adcs x4, x4, x11\n\t" + "adcs x5, x5, x12\n\t" + "adcs x6, x6, x13\n\t" + "mov x8, 0xffffffff00000001\n\t" + "csetm x9, cs\n\t" + "subs x3, x3, x9\n\t" + "lsr x7, x9, 32\n\t" + "sbcs x4, x4, x7\n\t" + "and x8, x8, x9\n\t" + "sbcs x5, x5, xzr\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "sbc x6, x6, x8\n\t" + "stp x5, x6, [%[r], 16]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x10", "x11", "x12", "x13", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + (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, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldp x4, x5, [%[a], 0]\n\t" + "ldp x8, x9, [%[b], 0]\n\t" + "subs x4, x4, x8\n\t" + "ldp x6, x7, [%[a], 16]\n\t" + "sbcs x5, x5, x9\n\t" + "ldp x10, x11, [%[b], 16]\n\t" + "sbcs x6, x6, x10\n\t" + "sbcs x7, x7, x11\n\t" + "mov x13, 0xffffffff00000001\n\t" + "csetm x14, cc\n\t" + "adds x4, x4, x14\n\t" + "lsr x12, x14, 32\n\t" + "adcs x5, x5, x12\n\t" + "and x13, x13, x14\n\t" + "adcs x6, x6, xzr\n\t" + "stp x4, x5, [%[r],0]\n\t" + "adc x7, x7, x13\n\t" + "stp x6, x7, [%[r],16]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14" + ); +} + +/* 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, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "and x9, x3, 1\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "sub x10, xzr, x9\n\t" + "lsr x7, x10, 32\n\t" + "adds x3, x3, x10\n\t" + "and x8, x10, 0xffffffff00000001\n\t" + "adcs x4, x4, x7\n\t" + "lsr x3, x3, 1\n\t" + "adcs x5, x5, xzr\n\t" + "lsr x7, x4, 1\n\t" + "adcs x6, x6, x8\n\t" + "lsr x8, x5, 1\n\t" + "cset x9, cs\n\t" + "lsr x10, x6, 1\n\t" + "orr x3, x3, x4, lsl 63\n\t" + "orr x4, x7, x5, lsl 63\n\t" + "orr x5, x8, x6, lsl 63\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "orr x6, x10, x9, lsl 63\n\t" + "stp x5, x6, [%[r], 16]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + +} + +/* 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_256* r, const sp_point_256* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_4(t1, p->z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_4(z, p->y, p->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, p->x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_4(t1, p->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, p->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, p->x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_sqr_4(x, 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); +} + +/* 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_dbl_4(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldp x8, x9, [%[b]]\n\t" + "ldp x10, x11, [%[b],16]\n\t" + "adds x8, x8, x8\n\t" + "ldp x4, x5, [%[a]]\n\t" + "adcs x9, x9, x9\n\t" + "ldp x6, x7, [%[a],16]\n\t" + "adcs x10, x10, x10\n\t" + "adcs x11, x11, x11\n\t" + "mov x13, 0xffffffff00000001\n\t" + "csetm x14, cs\n\t" + "subs x8, x8, x14\n\t" + "lsr x12, x14, 32\n\t" + "sbcs x9, x9, x12\n\t" + "and x13, x13, x14\n\t" + "sbcs x10, x10, xzr\n\t" + "sbc x11, x11, x13\n\t" + "subs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "sbcs x6, x6, x10\n\t" + "sbcs x7, x7, x11\n\t" + "mov x13, 0xffffffff00000001\n\t" + "csetm x14, cc\n\t" + "adds x4, x4, x14\n\t" + "lsr x12, x14, 32\n\t" + "adcs x5, x5, x12\n\t" + "and x13, x13, x14\n\t" + "adcs x6, x6, xzr\n\t" + "stp x4, x5, [%[r],0]\n\t" + "adc x7, x7, x13\n\t" + "stp x6, x7, [%[r],16]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14" + ); +} + +/* 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_dbl_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldp x4, x5, [%[a]]\n\t" + "ldp x6, x7, [%[a],16]\n\t" + "adds x4, x4, x4\n\t" + "ldp x8, x9, [%[b]]\n\t" + "adcs x5, x5, x5\n\t" + "ldp x10, x11, [%[b],16]\n\t" + "adcs x6, x6, x6\n\t" + "adcs x7, x7, x7\n\t" + "mov x13, 0xffffffff00000001\n\t" + "csetm x14, cs\n\t" + "subs x4, x4, x14\n\t" + "lsr x12, x14, 32\n\t" + "sbcs x5, x5, x12\n\t" + "and x13, x13, x14\n\t" + "sbcs x6, x6, xzr\n\t" + "sbc x7, x7, x13\n\t" + "subs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "sbcs x6, x6, x10\n\t" + "sbcs x7, x7, x11\n\t" + "mov x13, 0xffffffff00000001\n\t" + "csetm x14, cc\n\t" + "adds x4, x4, x14\n\t" + "lsr x12, x14, 32\n\t" + "adcs x5, x5, x12\n\t" + "and x13, x13, x14\n\t" + "adcs x6, x6, xzr\n\t" + "stp x4, x5, [%[r],0]\n\t" + "adc x7, x7, x13\n\t" + "stp x6, x7, [%[r],16]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14" + ); +} + +/* 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_256* p, int n, 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* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* 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); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* 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(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(b, t1, 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_sub_dbl_4(x, x, b, 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(t1, t1, p256_mod, p256_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_256_mont_mul_4(w, w, t1, 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_sub_4(y, y, t1, p256_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* 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(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(b, t1, 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_sub_dbl_4(x, x, b, 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(t1, t1, 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_sub_4(y, y, t1, p256_mod); +#endif + /* 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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, + sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + 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) { + const sp_point_256* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)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))) != 0) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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_256* r, const sp_point_256* 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_256 { + /* Index into pre-computation table. */ + uint8_t i; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode_256; + +/* The index into pre-computation table to use. */ +static const 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 const 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 perform. + */ +static void sp_256_ecc_recode_6_4(const sp_digit* k, ecc_recode_256* 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 coordinates. + * + * 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_256* r, const sp_point_256* g, + const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td[33]; + sp_point_256 rtd, pd; + sp_digit tmpd[2 * 4 * 6]; +#endif + sp_point_256* t; + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_256 v[43]; + int err; + + (void)heap; + + err = sp_256_point_new_4(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_256_point_new_4(heap, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 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_256)); + for (--i; i>=0; i--) { + sp_256_proj_point_dbl_n_4(rt, 6, tmp); + + XMEMCPY(p, &t[v[i].i], sizeof(sp_point_256)); + 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 != 0) { + sp_256_map_4(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + sp_256_point_free_4(p, 0, heap); + sp_256_point_free_4(rt, 0, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_256 { + sp_digit x[4]; + sp_digit y[4]; +} sp_table_entry_256; + +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +/* 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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_4(sp_point_256* r, const sp_point_256* p, + const sp_point_256* q, sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + 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 */ + (void)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))) != 0) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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 Temporary data. + */ +static void sp_256_proj_to_affine_4(sp_point_256* 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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_4(const sp_point_256* a, + sp_table_entry_256* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td, s1d, s2d; +#endif + sp_point_256* t; + sp_point_256* s1 = NULL; + sp_point_256* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_256_point_new_4(heap, td, t); + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_256_point_new_4(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_256)); + /* 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)); + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_4(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)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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)); + } + } + } + + sp_256_point_free_4(s2, 0, heap); + sp_256_point_free_4(s1, 0, heap); + sp_256_point_free_4( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit td[2 * 4 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_256_point_new_4(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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 = !y; + 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 = !y; + sp_256_proj_point_add_qz1_4(rt, rt, p, t); + } + + if (map != 0) { + sp_256_map_4(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(p, 0, heap); + sp_256_point_free_4(rt, 0, heap); + + return err; +} + +#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_256_t { + sp_digit x[4]; + sp_digit y[4]; + sp_table_entry_256 table[256]; + uint32_t cnt; + int set; +} sp_cache_256_t; + +static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_256_last = -1; +static THREAD_LS_T int sp_cache_256_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_256 = 0; + static wolfSSL_Mutex sp_cache_256_lock; +#endif + +static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_256_inited == 0) { + for (i=0; ix, sp_cache_256[i].x) & + sp_256_cmp_equal_4(g->y, sp_cache_256[i].y)) { + sp_cache_256[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_256_last + 1) % FP_ENTRIES; + for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_256[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_256_last) { + least = sp_cache_256[0].cnt; + for (j=1; jx, sizeof(sp_cache_256[i].x)); + XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y)); + sp_cache_256[i].set = 1; + sp_cache_256[i].cnt = 1; + } + + *cache = &sp_cache_256[i]; + sp_cache_256_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 coordinates. + * + * 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_256* r, const sp_point_256* g, const 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_256_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_256 == 0) { + wc_InitMutex(&sp_cache_256_lock); + initCacheMutex_256 = 1; + } + if (wc_LockMutex(&sp_cache_256_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_256(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_256_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 +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[4]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_256_point_new_4(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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); + + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static const sp_table_entry_256 p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x79e730d418a9143cL,0x75ba95fc5fedb601L,0x79fb732b77622510L, + 0x18905f76a53755c6L }, + { 0xddf25357ce95560aL,0x8b4ab8e4ba19e45cL,0xd2e88688dd21f325L, + 0x8571ff1825885d85L } }, + /* 2 */ + { { 0x202886024147519aL,0xd0981eac26b372f0L,0xa9d4a7caa785ebc8L, + 0xd953c50ddbdf58e9L }, + { 0x9d6361ccfd590f8fL,0x72e9626b44e6c917L,0x7fd9611022eb64cfL, + 0x863ebb7e9eb288f3L } }, + /* 3 */ + { { 0x7856b6235cdb6485L,0x808f0ea22f0a2f97L,0x3e68d9544f7e300bL, + 0x00076055b5ff80a0L }, + { 0x7634eb9b838d2010L,0x54014fbb3243708aL,0xe0e47d39842a6606L, + 0x8308776134373ee0L } }, + /* 4 */ + { { 0x4f922fc516a0d2bbL,0x0d5cc16c1a623499L,0x9241cf3a57c62c8bL, + 0x2f5e6961fd1b667fL }, + { 0x5c15c70bf5a01797L,0x3d20b44d60956192L,0x04911b37071fdb52L, + 0xf648f9168d6f0f7bL } }, + /* 5 */ + { { 0x9e566847e137bbbcL,0xe434469e8a6a0becL,0xb1c4276179d73463L, + 0x5abe0285133d0015L }, + { 0x92aa837cc04c7dabL,0x573d9f4c43260c07L,0x0c93156278e6cc37L, + 0x94bb725b6b6f7383L } }, + /* 6 */ + { { 0xbbf9b48f720f141cL,0x6199b3cd2df5bc74L,0xdc3f6129411045c4L, + 0xcdd6bbcb2f7dc4efL }, + { 0xcca6700beaf436fdL,0x6f647f6db99326beL,0x0c0fa792014f2522L, + 0xa361bebd4bdae5f6L } }, + /* 7 */ + { { 0x28aa2558597c13c7L,0xc38d635f50b7c3e1L,0x07039aecf3c09d1dL, + 0xba12ca09c4b5292cL }, + { 0x9e408fa459f91dfdL,0x3af43b66ceea07fbL,0x1eceb0899d780b29L, + 0x53ebb99d701fef4bL } }, + /* 8 */ + { { 0x4fe7ee31b0e63d34L,0xf4600572a9e54fabL,0xc0493334d5e7b5a4L, + 0x8589fb9206d54831L }, + { 0xaa70f5cc6583553aL,0x0879094ae25649e5L,0xcc90450710044652L, + 0xebb0696d02541c4fL } }, + /* 9 */ + { { 0x4616ca15ac1647c5L,0xb8127d47c4cf5799L,0xdc666aa3764dfbacL, + 0xeb2820cbd1b27da3L }, + { 0x9406f8d86a87e008L,0xd87dfa9d922378f3L,0x56ed2e4280ccecb2L, + 0x1f28289b55a7da1dL } }, + /* 10 */ + { { 0xabbaa0c03b89da99L,0xa6f2d79eb8284022L,0x27847862b81c05e8L, + 0x337a4b5905e54d63L }, + { 0x3c67500d21f7794aL,0x207005b77d6d7f61L,0x0a5a378104cfd6e8L, + 0x0d65e0d5f4c2fbd6L } }, + /* 11 */ + { { 0xd9d09bbeb5275d38L,0x4268a7450be0a358L,0xf0762ff4973eb265L, + 0xc23da24252f4a232L }, + { 0x5da1b84f0b94520cL,0x09666763b05bd78eL,0x3a4dcb8694d29ea1L, + 0x19de3b8cc790cff1L } }, + /* 12 */ + { { 0x183a716c26c5fe04L,0x3b28de0b3bba1bdbL,0x7432c586a4cb712cL, + 0xe34dcbd491fccbfdL }, + { 0xb408d46baaa58403L,0x9a69748682e97a53L,0x9e39012736aaa8afL, + 0xe7641f447b4e0f7fL } }, + /* 13 */ + { { 0x7d753941df64ba59L,0xd33f10ec0b0242fcL,0x4f06dfc6a1581859L, + 0x4a12df57052a57bfL }, + { 0xbfa6338f9439dbd0L,0xd3c24bd4bde53e1fL,0xfd5e4ffa21f1b314L, + 0x6af5aa93bb5bea46L } }, + /* 14 */ + { { 0xda10b69910c91999L,0x0a24b4402a580491L,0x3e0094b4b8cc2090L, + 0x5fe3475a66a44013L }, + { 0xb0f8cabdf93e7b4bL,0x292b501a7c23f91aL,0x42e889aecd1e6263L, + 0xb544e308ecfea916L } }, + /* 15 */ + { { 0x6478c6e916ddfdceL,0x2c329166f89179e6L,0x4e8d6e764d4e67e1L, + 0xe0b6b2bda6b0c20bL }, + { 0x0d312df2bb7efb57L,0x1aac0dde790c4007L,0xf90336ad679bc944L, + 0x71c023de25a63774L } }, + /* 16 */ + { { 0x62a8c244bfe20925L,0x91c19ac38fdce867L,0x5a96a5d5dd387063L, + 0x61d587d421d324f6L }, + { 0xe87673a2a37173eaL,0x2384800853778b65L,0x10f8441e05bab43eL, + 0xfa11fe124621efbeL } }, + /* 17 */ + { { 0x1c891f2b2cb19ffdL,0x01ba8d5bb1923c23L,0xb6d03d678ac5ca8eL, + 0x586eb04c1f13bedcL }, + { 0x0c35c6e527e8ed09L,0x1e81a33c1819ede2L,0x278fd6c056c652faL, + 0x19d5ac0870864f11L } }, + /* 18 */ + { { 0x1e99f581309a4e1fL,0xab7de71be9270074L,0x26a5ef0befd28d20L, + 0xe7c0073f7f9c563fL }, + { 0x1f6d663a0ef59f76L,0x669b3b5420fcb050L,0xc08c1f7a7a6602d4L, + 0xe08504fec65b3c0aL } }, + /* 19 */ + { { 0xf098f68da031b3caL,0x6d1cab9ee6da6d66L,0x5bfd81fa94f246e8L, + 0x78f018825b0996b4L }, + { 0xb7eefde43a25787fL,0x8016f80d1dccac9bL,0x0cea4877b35bfc36L, + 0x43a773b87e94747aL } }, + /* 20 */ + { { 0x62577734d2b533d5L,0x673b8af6a1bdddc0L,0x577e7c9aa79ec293L, + 0xbb6de651c3b266b1L }, + { 0xe7e9303ab65259b3L,0xd6a0afd3d03a7480L,0xc5ac83d19b3cfc27L, + 0x60b4619a5d18b99bL } }, + /* 21 */ + { { 0xbd6a38e11ae5aa1cL,0xb8b7652b49e73658L,0x0b130014ee5f87edL, + 0x9d0f27b2aeebffcdL }, + { 0xca9246317a730a55L,0x9c955b2fddbbc83aL,0x07c1dfe0ac019a71L, + 0x244a566d356ec48dL } }, + /* 22 */ + { { 0x6db0394aeacf1f96L,0x9f2122a9024c271cL,0x2626ac1b82cbd3b9L, + 0x45e58c873581ef69L }, + { 0xd3ff479da38f9dbcL,0xa8aaf146e888a040L,0x945adfb246e0bed7L, + 0xc040e21cc1e4b7a4L } }, + /* 23 */ + { { 0x847af0006f8117b6L,0x651969ff73a35433L,0x482b35761d9475ebL, + 0x1cdf5c97682c6ec7L }, + { 0x7db775b411f04839L,0x7dbeacf448de1698L,0xb2921dd1b70b3219L, + 0x046755f8a92dff3dL } }, + /* 24 */ + { { 0xcc8ac5d2bce8ffcdL,0x0d53c48b2fe61a82L,0xf6f161727202d6c7L, + 0x046e5e113b83a5f3L }, + { 0xe7b8ff64d8007f01L,0x7fb1ef125af43183L,0x045c5ea635e1a03cL, + 0x6e0106c3303d005bL } }, + /* 25 */ + { { 0x48c7358488dd73b1L,0x7670708f995ed0d9L,0x38385ea8c56a2ab7L, + 0x442594ede901cf1fL }, + { 0xf8faa2c912d4b65bL,0x94c2343b96c90c37L,0xd326e4a15e978d1fL, + 0xa796fa514c2ee68eL } }, + /* 26 */ + { { 0x359fb604823addd7L,0x9e2a6183e56693b3L,0xf885b78e3cbf3c80L, + 0xe4ad2da9c69766e9L }, + { 0x357f7f428e048a61L,0x082d198cc092d9a0L,0xfc3a1af4c03ed8efL, + 0xc5e94046c37b5143L } }, + /* 27 */ + { { 0x476a538c2be75f9eL,0x6fd1a9e8cb123a78L,0xd85e4df0b109c04bL, + 0x63283dafdb464747L }, + { 0xce728cf7baf2df15L,0xe592c4550ad9a7f4L,0xfab226ade834bcc3L, + 0x68bd19ab1981a938L } }, + /* 28 */ + { { 0xc08ead511887d659L,0x3374d5f4b359305aL,0x96986981cfe74fe3L, + 0x495292f53c6fdfd6L }, + { 0x4a878c9e1acec896L,0xd964b210ec5b4484L,0x6696f7e2664d60a7L, + 0x0ec7530d26036837L } }, + /* 29 */ + { { 0x2da13a05ad2687bbL,0xa1f83b6af32e21faL,0x390f5ef51dd4607bL, + 0x0f6207a664863f0bL }, + { 0xbd67e3bb0f138233L,0xdd66b96c272aa718L,0x8ed0040726ec88aeL, + 0xff0db07208ed6dcfL } }, + /* 30 */ + { { 0x749fa1014c95d553L,0xa44052fd5d680a8aL,0x183b4317ff3b566fL, + 0x313b513c88740ea3L }, + { 0xb402e2ac08d11549L,0x071ee10bb4dee21cL,0x26b987dd47f2320eL, + 0x2d3abcf986f19f81L } }, + /* 31 */ + { { 0x4c288501815581a2L,0x9a0a6d56632211afL,0x19ba7a0f0cab2e99L, + 0xc036fa10ded98cdfL }, + { 0x29ae08bac1fbd009L,0x0b68b19006d15816L,0xc2eb32779b9e0d8fL, + 0xa6b2a2c4b6d40194L } }, + /* 32 */ + { { 0xd433e50f6d3549cfL,0x6f33696ffacd665eL,0x695bfdacce11fcb4L, + 0x810ee252af7c9860L }, + { 0x65450fe17159bb2cL,0xf7dfbebe758b357bL,0x2b057e74d69fea72L, + 0xd485717a92731745L } }, + /* 33 */ + { { 0x11741a8af0cb5a98L,0xd3da8f931f3110bfL,0x1994e2cbab382adfL, + 0x6a6045a72f9a604eL }, + { 0x170c0d3fa2b2411dL,0xbe0eb83e510e96e0L,0x3bcc9f738865b3ccL, + 0xd3e45cfaf9e15790L } }, + /* 34 */ + { { 0xce1f69bbe83f7669L,0x09f8ae8272877d6bL,0x9548ae543244278dL, + 0x207755dee3c2c19cL }, + { 0x87bd61d96fef1945L,0x18813cefb12d28c3L,0x9fbcd1d672df64aaL, + 0x48dc5ee57154b00dL } }, + /* 35 */ + { { 0x123790bff7e5a199L,0xe0efb8cf989ccbb7L,0xc27a2bfe0a519c79L, + 0xf2fb0aeddff6f445L }, + { 0x41c09575f0b5025fL,0x550543d740fa9f22L,0x8fa3c8ad380bfbd0L, + 0xa13e9015db28d525L } }, + /* 36 */ + { { 0xf9f7a350a2b65cbcL,0x0b04b9722a464226L,0x265ce241e23f07a1L, + 0x2bf0d6b01497526fL }, + { 0xd3d4dd3f4b216fb7L,0xf7d7b867fbdda26aL,0xaeb7b83f6708505cL, + 0x42a94a5a162fe89fL } }, + /* 37 */ + { { 0x5846ad0beaadf191L,0x0f8a489025a268d7L,0xe8603050494dc1f6L, + 0x2c2dd969c65ede3dL }, + { 0x6d02171d93849c17L,0x460488ba1da250ddL,0x4810c7063c3a5485L, + 0xf437fa1f42c56dbcL } }, + /* 38 */ + { { 0x6aa0d7144a0f7dabL,0x0f0497931776e9acL,0x52c0a050f5f39786L, + 0xaaf45b3354707aa8L }, + { 0x85e37c33c18d364aL,0xd40b9b063e497165L,0xf417168115ec5444L, + 0xcdf6310df4f272bcL } }, + /* 39 */ + { { 0x7473c6238ea8b7efL,0x08e9351885bc2287L,0x419567722bda8e34L, + 0xf0d008bada9e2ff2L }, + { 0x2912671d2414d3b1L,0xb3754985b019ea76L,0x5c61b96d453bcbdbL, + 0x5bd5c2f5ca887b8bL } }, + /* 40 */ + { { 0xef0f469ef49a3154L,0x3e85a5956e2b2e9aL,0x45aaec1eaa924a9cL, + 0xaa12dfc8a09e4719L }, + { 0x26f272274df69f1dL,0xe0e4c82ca2ff5e73L,0xb9d8ce73b7a9dd44L, + 0x6c036e73e48ca901L } }, + /* 41 */ + { { 0x5cfae12a0f6e3138L,0x6966ef0025ad345aL,0x8993c64b45672bc5L, + 0x292ff65896afbe24L }, + { 0xd5250d445e213402L,0xf6580e274392c9feL,0x097b397fda1c72e8L, + 0x644e0c90311b7276L } }, + /* 42 */ + { { 0xe1e421e1a47153f0L,0xb86c3b79920418c9L,0x93bdce87705d7672L, + 0xf25ae793cab79a77L }, + { 0x1f3194a36d869d0cL,0x9d55c8824986c264L,0x49fb5ea3096e945eL, + 0x39b8e65313db0a3eL } }, + /* 43 */ + { { 0x37754200b6fd2e59L,0x35e2c0669255c98fL,0xd9dab21a0e2a5739L, + 0x39122f2f0f19db06L }, + { 0xcfbce1e003cad53cL,0x225b2c0fe65c17e3L,0x72baf1d29aa13877L, + 0x8de80af8ce80ff8dL } }, + /* 44 */ + { { 0xafbea8d9207bbb76L,0x921c7e7c21782758L,0xdfa2b74b1c0436b1L, + 0x871949062e368c04L }, + { 0xb5f928bba3993df5L,0x639d75b5f3b3d26aL,0x011aa78a85b55050L, + 0xfc315e6a5b74fde1L } }, + /* 45 */ + { { 0x561fd41ae8d6ecfaL,0x5f8c44f61aec7f86L,0x98452a7b4924741dL, + 0xe6d4a7adee389088L }, + { 0x60552ed14593c75dL,0x70a70da4dd271162L,0xd2aede937ba2c7dbL, + 0x35dfaf9a9be2ae57L } }, + /* 46 */ + { { 0x6b956fcdaa736636L,0x09f51d97ae2cab7eL,0xfb10bf410f349966L, + 0x1da5c7d71c830d2bL }, + { 0x5c41e4833cce6825L,0x15ad118ff9573c3bL,0xa28552c7f23036b8L, + 0x7077c0fddbf4b9d6L } }, + /* 47 */ + { { 0xbf63ff8d46b9661cL,0xa1dfd36b0d2cfd71L,0x0373e140a847f8f7L, + 0x53a8632ee50efe44L }, + { 0x0976ff68696d8051L,0xdaec0c95c74f468aL,0x62994dc35e4e26bdL, + 0x028ca76d34e1fcc1L } }, + /* 48 */ + { { 0xd11d47dcfc9877eeL,0xc8b36210801d0002L,0xd002c11754c260b6L, + 0x04c17cd86962f046L }, + { 0x6d9bd094b0daddf5L,0xbea2357524ce55c0L,0x663356e672da03b5L, + 0xf7ba4de9fed97474L } }, + /* 49 */ + { { 0xd0dbfa34ebe1263fL,0x5576373571ae7ce6L,0xd244055382a6f523L, + 0xe31f960052131c41L }, + { 0xd1bb9216ea6b6ec6L,0x37a1d12e73c2fc44L,0xc10e7eac89d0a294L, + 0xaa3a6259ce34d47bL } }, + /* 50 */ + { { 0xfbcf9df536f3dcd3L,0x6ceded50d2bf7360L,0x491710fadf504f5bL, + 0x2398dd627e79daeeL }, + { 0xcf4705a36d09569eL,0xea0619bb5149f769L,0xff9c037735f6034cL, + 0x5717f5b21c046210L } }, + /* 51 */ + { { 0x9fe229c921dd895eL,0x8e51850040c28451L,0xfa13d2391d637ecdL, + 0x660a2c560e3c28deL }, + { 0x9cca88aed67fcbd0L,0xc84724780ea9f096L,0x32b2f48172e92b4dL, + 0x624ee54c4f522453L } }, + /* 52 */ + { { 0x09549ce4d897ecccL,0x4d49d1d93f9880aaL,0x723c2423043a7c20L, + 0x4f392afb92bdfbc0L }, + { 0x6969f8fa7de44fd9L,0xb66cfbe457b32156L,0xdb2fa803368ebc3cL, + 0x8a3e7977ccdb399cL } }, + /* 53 */ + { { 0xdde1881f06c4b125L,0xae34e300f6e3ca8cL,0xef6999de5c7a13e9L, + 0x3888d02370c24404L }, + { 0x7628035644f91081L,0x3d9fcf615f015504L,0x1827edc8632cd36eL, + 0xa5e62e4718102336L } }, + /* 54 */ + { { 0x1a825ee32facd6c8L,0x699c635454bcbc66L,0x0ce3edf798df9931L, + 0x2c4768e6466a5adcL }, + { 0xb346ff8c90a64bc9L,0x630a6020e4779f5cL,0xd949d064bc05e884L, + 0x7b5e6441f9e652a0L } }, + /* 55 */ + { { 0x2169422c1d28444aL,0xe996c5d8be136a39L,0x2387afe5fb0c7fceL, + 0xb8af73cb0c8d744aL }, + { 0x5fde83aa338b86fdL,0xfee3f158a58a5cffL,0xc9ee8f6f20ac9433L, + 0xa036395f7f3f0895L } }, + /* 56 */ + { { 0x8c73c6bba10f7770L,0xa6f16d81a12a0e24L,0x100df68251bc2b9fL, + 0x4be36b01875fb533L }, + { 0x9226086e9fb56dbbL,0x306fef8b07e7a4f8L,0xeeaccc0566d52f20L, + 0x8cbc9a871bdc00c0L } }, + /* 57 */ + { { 0xe131895cc0dac4abL,0xa874a440712ff112L,0x6332ae7c6a1cee57L, + 0x44e7553e0c0835f8L }, + { 0x6d503fff7734002dL,0x9d35cb8b0b34425cL,0x95f702760e8738b5L, + 0x470a683a5eb8fc18L } }, + /* 58 */ + { { 0x81b761dc90513482L,0x0287202a01e9276aL,0xcda441ee0ce73083L, + 0x16410690c63dc6efL }, + { 0xf5034a066d06a2edL,0xdd4d7745189b100bL,0xd914ae72ab8218c9L, + 0xd73479fd7abcbb4fL } }, + /* 59 */ + { { 0x7edefb165ad4c6e5L,0x262cf08f5b06d04dL,0x12ed5bb18575cb14L, + 0x816469e30771666bL }, + { 0xd7ab9d79561e291eL,0xeb9daf22c1de1661L,0xf49827eb135e0513L, + 0x0a36dd23f0dd3f9cL } }, + /* 60 */ + { { 0x098d32c741d5533cL,0x7c5f5a9e8684628fL,0x39a228ade349bd11L, + 0xe331dfd6fdbab118L }, + { 0x5100ab686bcc6ed8L,0x7160c3bdef7a260eL,0x9063d9a7bce850d7L, + 0xd3b4782a492e3389L } }, + /* 61 */ + { { 0xa149b6e8f3821f90L,0x92edd9ed66eb7aadL,0x0bb669531a013116L, + 0x7281275a4c86a5bdL }, + { 0x503858f7d3ff47e5L,0x5e1616bc61016441L,0x62b0f11a7dfd9bb1L, + 0x2c062e7ece145059L } }, + /* 62 */ + { { 0xa76f996f0159ac2eL,0x281e7736cbdb2713L,0x2ad6d28808e46047L, + 0x282a35f92c4e7ef1L }, + { 0x9c354b1ec0ce5cd2L,0xcf99efc91379c229L,0x992caf383e82c11eL, + 0xc71cd513554d2abdL } }, + /* 63 */ + { { 0x4885de9c09b578f4L,0x1884e258e3affa7aL,0x8f76b1b759182f1fL, + 0xc50f6740cf47f3a3L }, + { 0xa9c4adf3374b68eaL,0xa406f32369965fe2L,0x2f86a22285a53050L, + 0xb9ecb3a7212958dcL } }, + /* 64 */ + { { 0x56f8410ef4f8b16aL,0x97241afec47b266aL,0x0a406b8e6d9c87c1L, + 0x803f3e02cd42ab1bL }, + { 0x7f0309a804dbec69L,0xa83b85f73bbad05fL,0xc6097273ad8e197fL, + 0xc097440e5067adc1L } }, + /* 65 */ + { { 0x846a56f2c379ab34L,0xa8ee068b841df8d1L,0x20314459176c68efL, + 0xf1af32d5915f1f30L }, + { 0x99c375315d75bd50L,0x837cffbaf72f67bcL,0x0613a41848d7723fL, + 0x23d0f130e2d41c8bL } }, + /* 66 */ + { { 0x857ab6edf41500d9L,0x0d890ae5fcbeada8L,0x52fe864889725951L, + 0xb0288dd6c0a3faddL }, + { 0x85320f30650bcb08L,0x71af6313695d6e16L,0x31f520a7b989aa76L, + 0xffd3724ff408c8d2L } }, + /* 67 */ + { { 0x53968e64b458e6cbL,0x992dad20317a5d28L,0x3814ae0b7aa75f56L, + 0xf5590f4ad78c26dfL }, + { 0x0fc24bd3cf0ba55aL,0x0fc4724a0c778baeL,0x1ce9864f683b674aL, + 0x18d6da54f6f74a20L } }, + /* 68 */ + { { 0xed93e225d5be5a2bL,0x6fe799835934f3c6L,0x4314092622626ffcL, + 0x50bbb4d97990216aL }, + { 0x378191c6e57ec63eL,0x65422c40181dcdb2L,0x41a8099b0236e0f6L, + 0x2b10011801fe49c3L } }, + /* 69 */ + { { 0xfc68b5c59b391593L,0xc385f5a2598270fcL,0x7144f3aad19adcbbL, + 0xdd55899983fbae0cL }, + { 0x93b88b8e74b82ff4L,0xd2e03c4071e734c9L,0x9a7a9eaf43c0322aL, + 0xe6e4c551149d6041L } }, + /* 70 */ + { { 0x55f655bb1e9af288L,0x647e1a64f7ada931L,0x43697e4bcb2820e5L, + 0x51e00db107ed56ffL }, + { 0x43d169b8771c327eL,0x29cdb20b4a96c2adL,0xc07d51f53deb4779L, + 0xe22f424149829177L } }, + /* 71 */ + { { 0xcd45e8f4635f1abbL,0x7edc0cb568538874L,0xc9472c1fb5a8034dL, + 0xf709373d52dc48c9L }, + { 0x401966bba8af30d6L,0x95bf5f4af137b69cL,0x3966162a9361c47eL, + 0xbd52d288e7275b11L } }, + /* 72 */ + { { 0xab155c7a9c5fa877L,0x17dad6727d3a3d48L,0x43f43f9e73d189d8L, + 0xa0d0f8e4c8aa77a6L }, + { 0x0bbeafd8cc94f92dL,0xd818c8be0c4ddb3aL,0x22cc65f8b82eba14L, + 0xa56c78c7946d6a00L } }, + /* 73 */ + { { 0x2962391b0dd09529L,0x803e0ea63daddfcfL,0x2c77351f5b5bf481L, + 0xd8befdf8731a367aL }, + { 0xab919d42fc0157f4L,0xf51caed7fec8e650L,0xcdf9cb4002d48b0aL, + 0x854a68a5ce9f6478L } }, + /* 74 */ + { { 0xdc35f67b63506ea5L,0x9286c489a4fe0d66L,0x3f101d3bfe95cd4dL, + 0x5cacea0b98846a95L }, + { 0xa90df60c9ceac44dL,0x3db29af4354d1c3aL,0x08dd3de8ad5dbabeL, + 0xe4982d1235e4efa9L } }, + /* 75 */ + { { 0x23104a22c34cd55eL,0x58695bb32680d132L,0xfb345afa1fa1d943L, + 0x8046b7f616b20499L }, + { 0xb533581e38e7d098L,0xd7f61e8df46f0b70L,0x30dea9ea44cb78c4L, + 0xeb17ca7b9082af55L } }, + /* 76 */ + { { 0x1751b59876a145b9L,0xa5cf6b0fc1bc71ecL,0xd3e03565392715bbL, + 0x097b00bafab5e131L }, + { 0xaa66c8e9565f69e1L,0x77e8f75ab5be5199L,0x6033ba11da4fd984L, + 0xf95c747bafdbcc9eL } }, + /* 77 */ + { { 0x558f01d3bebae45eL,0xa8ebe9f0c4bc6955L,0xaeb705b1dbc64fc6L, + 0x3512601e566ed837L }, + { 0x9336f1e1fa1161cdL,0x328ab8d54c65ef87L,0x4757eee2724f21e5L, + 0x0ef971236068ab6bL } }, + /* 78 */ + { { 0x02598cf754ca4226L,0x5eede138f8642c8eL,0x48963f74468e1790L, + 0xfc16d9333b4fbc95L }, + { 0xbe96fb31e7c800caL,0x138063312678adaaL,0x3d6244976ff3e8b5L, + 0x14ca4af1b95d7a17L } }, + /* 79 */ + { { 0x7a4771babd2f81d5L,0x1a5f9d6901f7d196L,0xd898bef7cad9c907L, + 0x4057b063f59c231dL }, + { 0xbffd82fe89c05c0aL,0xe4911c6f1dc0df85L,0x3befccaea35a16dbL, + 0x1c3b5d64f1330b13L } }, + /* 80 */ + { { 0x5fe14bfe80ec21feL,0xf6ce116ac255be82L,0x98bc5a072f4a5d67L, + 0xfad27148db7e63afL }, + { 0x90c0b6ac29ab05b3L,0x37a9a83c4e251ae6L,0x0a7dc875c2aade7dL, + 0x77387de39f0e1a84L } }, + /* 81 */ + { { 0x1e9ecc49a56c0dd7L,0xa5cffcd846086c74L,0x8f7a1408f505aeceL, + 0xb37b85c0bef0c47eL }, + { 0x3596b6e4cc0e6a8fL,0xfd6d4bbf6b388f23L,0xaba453fac39cef4eL, + 0x9c135ac8f9f628d5L } }, + /* 82 */ + { { 0x32aa320284e35743L,0x320d6ab185a3cdefL,0xb821b1761df19819L, + 0x5721361fc433851fL }, + { 0x1f0db36a71fc9168L,0x5f98ba735e5c403cL,0xf64ca87e37bcd8f5L, + 0xdcbac3c9e6bb11bdL } }, + /* 83 */ + { { 0xf01d99684518cbe2L,0xd242fc189c9eb04eL,0x727663c7e47feebfL, + 0xb8c1c89e2d626862L }, + { 0x51a58bddc8e1d569L,0x563809c8b7d88cd0L,0x26c27fd9f11f31ebL, + 0x5d23bbda2f9422d4L } }, + /* 84 */ + { { 0x0a1c729495c8f8beL,0x2961c4803bf362bfL,0x9e418403df63d4acL, + 0xc109f9cb91ece900L }, + { 0xc2d095d058945705L,0xb9083d96ddeb85c0L,0x84692b8d7a40449bL, + 0x9bc3344f2eee1ee1L } }, + /* 85 */ + { { 0x0d5ae35642913074L,0x55491b2748a542b1L,0x469ca665b310732aL, + 0x29591d525f1a4cc1L }, + { 0xe76f5b6bb84f983fL,0xbe7eef419f5f84e1L,0x1200d49680baa189L, + 0x6376551f18ef332cL } }, + /* 86 */ + { { 0xbda5f14e562976ccL,0x22bca3e60ef12c38L,0xbbfa30646cca9852L, + 0xbdb79dc808e2987aL }, + { 0xfd2cb5c9cb06a772L,0x38f475aafe536dceL,0xc2a3e0227c2b5db8L, + 0x8ee86001add3c14aL } }, + /* 87 */ + { { 0xcbe96981a4ade873L,0x7ee9aa4dc4fba48cL,0x2cee28995a054ba5L, + 0x92e51d7a6f77aa4bL }, + { 0x948bafa87190a34dL,0xd698f75bf6bd1ed1L,0xd00ee6e30caf1144L, + 0x5182f86f0a56aaaaL } }, + /* 88 */ + { { 0xfba6212c7a4cc99cL,0xff609b683e6d9ca1L,0x5dbb27cb5ac98c5aL, + 0x91dcab5d4073a6f2L }, + { 0x01b6cc3d5f575a70L,0x0cb361396f8d87faL,0x165d4e8c89981736L, + 0x17a0cedb97974f2bL } }, + /* 89 */ + { { 0x38861e2a076c8d3aL,0x701aad39210f924bL,0x94d0eae413a835d9L, + 0x2e8ce36c7f4cdf41L }, + { 0x91273dab037a862bL,0x01ba9bb760e4c8faL,0xf964538833baf2ddL, + 0xf4ccc6cb34f668f3L } }, + /* 90 */ + { { 0x44ef525cf1f79687L,0x7c59549592efa815L,0xe1231741a5c78d29L, + 0xac0db4889a0df3c9L }, + { 0x86bfc711df01747fL,0x592b9358ef17df13L,0xe5880e4f5ccb6bb5L, + 0x95a64a6194c974a2L } }, + /* 91 */ + { { 0x72c1efdac15a4c93L,0x40269b7382585141L,0x6a8dfb1c16cb0badL, + 0x231e54ba29210677L }, + { 0xa70df9178ae6d2dcL,0x4d6aa63f39112918L,0xf627726b5e5b7223L, + 0xab0be032d8a731e1L } }, + /* 92 */ + { { 0x097ad0e98d131f2dL,0x637f09e33b04f101L,0x1ac86196d5e9a748L, + 0xf1bcc8802cf6a679L }, + { 0x25c69140e8daacb4L,0x3c4e405560f65009L,0x591cc8fc477937a6L, + 0x851694695aebb271L } }, + /* 93 */ + { { 0xde35c143f1dcf593L,0x78202b29b018be3bL,0xe9cdadc29bdd9d3dL, + 0x8f67d9d2daad55d8L }, + { 0x841116567481ea5fL,0xe7d2dde9e34c590cL,0xffdd43f405053fa8L, + 0xf84572b9c0728b5dL } }, + /* 94 */ + { { 0x5e1a7a7197af71c9L,0xa14494447a736565L,0xa1b4ae070e1d5063L, + 0xedee2710616b2c19L }, + { 0xb2f034f511734121L,0x1cac6e554a25e9f0L,0x8dc148f3a40c2ecfL, + 0x9fd27e9b44ebd7f4L } }, + /* 95 */ + { { 0x3cc7658af6e2cb16L,0xe3eb7d2cfe5919b6L,0x5a8c5816168d5583L, + 0xa40c2fb6958ff387L }, + { 0x8c9ec560fedcc158L,0x7ad804c655f23056L,0xd93967049a307e12L, + 0x99bc9bb87dc6decfL } }, + /* 96 */ + { { 0x84a9521d927dafc6L,0x52c1fb695c09cd19L,0x9d9581a0f9366ddeL, + 0x9abe210ba16d7e64L }, + { 0x480af84a48915220L,0xfa73176a4dd816c6L,0xc7d539871681ca5aL, + 0x7881c25787f344b0L } }, + /* 97 */ + { { 0x93399b51e0bcf3ffL,0x0d02cbc5127f74f6L,0x8fb465a2dd01d968L, + 0x15e6e319a30e8940L }, + { 0x646d6e0d3e0e05f4L,0xfad7bddc43588404L,0xbe61c7d1c4f850d3L, + 0x0e55facf191172ceL } }, + /* 98 */ + { { 0x7e9d9806f8787564L,0x1a33172131e85ce6L,0x6b0158cab819e8d6L, + 0xd73d09766fe96577L }, + { 0x424834251eb7206eL,0xa519290fc618bb42L,0x5dcbb8595e30a520L, + 0x9250a3748f15a50bL } }, + /* 99 */ + { { 0xcaff08f8be577410L,0xfd408a035077a8c6L,0xf1f63289ec0a63a4L, + 0x77414082c1cc8c0bL }, + { 0x05a40fa6eb0991cdL,0xc1ca086649fdc296L,0x3a68a3c7b324fd40L, + 0x8cb04f4d12eb20b9L } }, + /* 100 */ + { { 0xb1c2d0556906171cL,0x9073e9cdb0240c3fL,0xdb8e6b4fd8906841L, + 0xe4e429ef47123b51L }, + { 0x0b8dd53c38ec36f4L,0xf9d2dc01ff4b6a27L,0x5d066e07879a9a48L, + 0x37bca2ff3c6e6552L } }, + /* 101 */ + { { 0x4cd2e3c7df562470L,0x44f272a2c0964ac9L,0x7c6d5df980c793beL, + 0x59913edc3002b22aL }, + { 0x7a139a835750592aL,0x99e01d80e783de02L,0xcf8c0375ea05d64fL, + 0x43786e4ab013e226L } }, + /* 102 */ + { { 0xff32b0ed9e56b5a6L,0x0750d9a6d9fc68f9L,0xec15e845597846a7L, + 0x8638ca98b7e79e7aL }, + { 0x2f5ae0960afc24b2L,0x05398eaf4dace8f2L,0x3b765dd0aecba78fL, + 0x1ecdd36a7b3aa6f0L } }, + /* 103 */ + { { 0x5d3acd626c5ff2f3L,0xa2d516c02873a978L,0xad94c9fad2110d54L, + 0xd85d0f85d459f32dL }, + { 0x9f700b8d10b11da3L,0xd2c22c30a78318c4L,0x556988f49208decdL, + 0xa04f19c3b4ed3c62L } }, + /* 104 */ + { { 0x087924c8ed7f93bdL,0xcb64ac5d392f51f6L,0x7cae330a821b71afL, + 0x92b2eeea5c0950b0L }, + { 0x85ac4c9485b6e235L,0xab2ca4a92936c0f0L,0x80faa6b3e0508891L, + 0x1ee782215834276cL } }, + /* 105 */ + { { 0xa60a2e00e63e79f7L,0xf590e7b2f399d906L,0x9021054a6607c09dL, + 0xf3f2ced857a6e150L }, + { 0x200510f3f10d9b55L,0x9d2fcfacd8642648L,0xe5631aa7e8bd0e7cL, + 0x0f56a4543da3e210L } }, + /* 106 */ + { { 0x5b21bffa1043e0dfL,0x6c74b6cc9c007e6dL,0x1a656ec0d4a8517aL, + 0xbd8f17411969e263L }, + { 0x8a9bbb86beb7494aL,0x1567d46f45f3b838L,0xdf7a12a7a4e5a79aL, + 0x2d1a1c3530ccfa09L } }, + /* 107 */ + { { 0x192e3813506508daL,0x336180c4a1d795a7L,0xcddb59497a9944b3L, + 0xa107a65eb91fba46L }, + { 0xe6d1d1c50f94d639L,0x8b4af3758a58b7d7L,0x1a7c5584bd37ca1cL, + 0x183d760af87a9af2L } }, + /* 108 */ + { { 0x29d697110dde59a4L,0xf1ad8d070e8bef87L,0x229b49634f2ebe78L, + 0x1d44179dc269d754L }, + { 0xb32dc0cf8390d30eL,0x0a3b27530de8110cL,0x31af1dc52bc0339aL, + 0x771f9cc29606d262L } }, + /* 109 */ + { { 0x99993e7785040739L,0x44539db98026a939L,0xcf40f6f2f5f8fc26L, + 0x64427a310362718eL }, + { 0x4f4f2d8785428aa8L,0x7b7adc3febfb49a8L,0x201b2c6df23d01acL, + 0x49d9b7496ae90d6dL } }, + /* 110 */ + { { 0xcc78d8bc435d1099L,0x2adbcd4e8e8d1a08L,0x02c2e2a02cb68a41L, + 0x9037d81b3f605445L }, + { 0x7cdbac27074c7b61L,0xfe2031ab57bfd72eL,0x61ccec96596d5352L, + 0x08c3de6a7cc0639cL } }, + /* 111 */ + { { 0x20fdd020f6d552abL,0x56baff9805cd81f1L,0x06fb7c3e91351291L, + 0xc690944245796b2fL }, + { 0x17b3ae9c41231bd1L,0x1eac6e875cc58205L,0x208837abf9d6a122L, + 0x3fa3db02cafe3ac0L } }, + /* 112 */ + { { 0xd75a3e6505058880L,0x7da365ef643943f2L,0x4147861cfab24925L, + 0xc5c4bdb0fdb808ffL }, + { 0x73513e34b272b56bL,0xc8327e9511b9043aL,0xfd8ce37df8844969L, + 0x2d56db9446c2b6b5L } }, + /* 113 */ + { { 0x2461782fff46ac6bL,0xd19f792607a2e425L,0xfafea3c409a48de1L, + 0x0f56bd9de503ba42L }, + { 0x137d4ed1345cda49L,0x821158fc816f299dL,0xe7c6a54aaeb43402L, + 0x4003bb9d1173b5f1L } }, + /* 114 */ + { { 0x3b8e8189a0803387L,0xece115f539cbd404L,0x4297208dd2877f21L, + 0x53765522a07f2f9eL }, + { 0xa4980a21a8a4182dL,0xa2bbd07a3219df79L,0x674d0a2e1a19a2d4L, + 0x7a056f586c5d4549L } }, + /* 115 */ + { { 0x646b25589d8a2a47L,0x5b582948c3df2773L,0x51ec000eabf0d539L, + 0x77d482f17a1a2675L }, + { 0xb8a1bd9587853948L,0xa6f817bd6cfbffeeL,0xab6ec05780681e47L, + 0x4115012b2b38b0e4L } }, + /* 116 */ + { { 0x3c73f0f46de28cedL,0x1d5da7609b13ec47L,0x61b8ce9e6e5c6392L, + 0xcdf04572fbea0946L }, + { 0x1cb3c58b6c53c3b0L,0x97fe3c10447b843cL,0xfb2b8ae12cb9780eL, + 0xee703dda97383109L } }, + /* 117 */ + { { 0x34515140ff57e43aL,0xd44660d3b1b811b8L,0x2b3b5dff8f42b986L, + 0x2a0ad89da162ce21L }, + { 0x64e4a6946bc277baL,0xc788c954c141c276L,0x141aa64ccabf6274L, + 0xd62d0b67ac2b4659L } }, + /* 118 */ + { { 0x39c5d87b2c054ac4L,0x57005859f27df788L,0xedf7cbf3b18128d6L, + 0xb39a23f2991c2426L }, + { 0x95284a15f0b16ae5L,0x0c6a05b1a136f51bL,0x1d63c137f2700783L, + 0x04ed0092c0674cc5L } }, + /* 119 */ + { { 0x1f4185d19ae90393L,0x3047b4294a3d64e6L,0xae0001a69854fc14L, + 0xa0a91fc10177c387L }, + { 0xff0a3f01ae2c831eL,0xbb76ae822b727e16L,0x8f12c8a15a3075b4L, + 0x084cf9889ed20c41L } }, + /* 120 */ + { { 0xd98509defca6becfL,0x2fceae807dffb328L,0x5d8a15c44778e8b9L, + 0xd57955b273abf77eL }, + { 0x210da79e31b5d4f1L,0xaa52f04b3cfa7a1cL,0xd4d12089dc27c20bL, + 0x8e14ea4202d141f1L } }, + /* 121 */ + { { 0xeed50345f2897042L,0x8d05331f43402c4aL,0xc8d9c194c8bdfb21L, + 0x597e1a372aa4d158L }, + { 0x0327ec1acf0bd68cL,0x6d4be0dcab024945L,0x5b9c8d7ac9fe3e84L, + 0xca3f0236199b4deaL } }, + /* 122 */ + { { 0x592a10b56170bd20L,0x0ea897f16d3f5de7L,0xa3363ff144b2ade2L, + 0xbde7fd7e309c07e4L }, + { 0x516bb6d2b8f5432cL,0x210dc1cbe043444bL,0x3db01e6ff8f95b5aL, + 0xb623ad0e0a7dd198L } }, + /* 123 */ + { { 0xa75bd67560c7b65bL,0xab8c559023a4a289L,0xf8220fd0d7b26795L, + 0xd6aa2e4658ec137bL }, + { 0x10abc00b5138bb85L,0x8c31d121d833a95cL,0xb24ff00b1702a32eL, + 0x111662e02dcc513aL } }, + /* 124 */ + { { 0x78114015efb42b87L,0xbd9f5d701b6c4dffL,0x66ecccd7a7d7c129L, + 0xdb3ee1cb94b750f8L }, + { 0xb26f3db0f34837cfL,0xe7eed18bb9578d4fL,0x5d2cdf937c56657dL, + 0x886a644252206a59L } }, + /* 125 */ + { { 0x3c234cfb65b569eaL,0x20011141f72119c1L,0x8badc85da15a619eL, + 0xa70cf4eb018a17bcL }, + { 0x224f97ae8c4a6a65L,0x36e5cf270134378fL,0xbe3a609e4f7e0960L, + 0xaa4772abd1747b77L } }, + /* 126 */ + { { 0x676761317aa60cc0L,0xc79163610368115fL,0xded98bb4bbc1bb5aL, + 0x611a6ddc30faf974L }, + { 0x30e78cbcc15ee47aL,0x2e8962824e0d96a5L,0x36f35adf3dd9ed88L, + 0x5cfffaf816429c88L } }, + /* 127 */ + { { 0xc0d54cff9b7a99cdL,0x7bf3b99d843c45a1L,0x038a908f62c739e1L, + 0x6e5a6b237dc1994cL }, + { 0xef8b454e0ba5db77L,0xb7b8807facf60d63L,0xe591c0c676608378L, + 0x481a238d242dabccL } }, + /* 128 */ + { { 0xe3417bc035d0b34aL,0x440b386b8327c0a7L,0x8fb7262dac0362d1L, + 0x2c41114ce0cdf943L }, + { 0x2ba5cef1ad95a0b1L,0xc09b37a867d54362L,0x26d6cdd201e486c9L, + 0x20477abf42ff9297L } }, + /* 129 */ + { { 0x2f75173c18d65dbfL,0x77bf940e339edad8L,0x7022d26bdcf1001cL, + 0xac66409ac77396b6L }, + { 0x8b0bb36fc6261cc3L,0x213f7bc9190e7e90L,0x6541cebaa45e6c10L, + 0xce8e6975cc122f85L } }, + /* 130 */ + { { 0x0f121b41bc0a67d2L,0x62d4760a444d248aL,0x0e044f1d659b4737L, + 0x08fde365250bb4a8L }, + { 0xaceec3da848bf287L,0xc2a62182d3369d6eL,0x3582dfdc92449482L, + 0x2f7e2fd2565d6cd7L } }, + /* 131 */ + { { 0xae4b92dbc3770fa7L,0x095e8d5c379043f9L,0x54f34e9d17761171L, + 0xc65be92e907702aeL }, + { 0x2758a303f6fd0a40L,0xe7d822e3bcce784bL,0x7ae4f5854f9767bfL, + 0x4bff8e47d1193b3aL } }, + /* 132 */ + { { 0xcd41d21f00ff1480L,0x2ab8fb7d0754db16L,0xac81d2efbbe0f3eaL, + 0x3e4e4ae65772967dL }, + { 0x7e18f36d3c5303e6L,0x3bd9994b92262397L,0x9ed70e261324c3c0L, + 0x5388aefd58ec6028L } }, + /* 133 */ + { { 0xad1317eb5e5d7713L,0x09b985ee75de49daL,0x32f5bc4fc74fb261L, + 0x5cf908d14f75be0eL }, + { 0x760435108e657b12L,0xbfd421a5b96ed9e6L,0x0e29f51f8970ccc2L, + 0xa698ba4060f00ce2L } }, + /* 134 */ + { { 0x73db1686ef748fecL,0xe6e755a27e9d2cf9L,0x630b6544ce265effL, + 0xb142ef8a7aebad8dL }, + { 0xad31af9f17d5770aL,0x66af3b672cb3412fL,0x6bd60d1bdf3359deL, + 0xd1896a9658515075L } }, + /* 135 */ + { { 0xec5957ab33c41c08L,0x87de94ac5468e2e1L,0x18816b73ac472f6cL, + 0x267b0e0b7981da39L }, + { 0x6e554e5d8e62b988L,0xd8ddc755116d21e7L,0x4610faf03d2a6f99L, + 0xb54e287aa1119393L } }, + /* 136 */ + { { 0x0a0122b5178a876bL,0x51ff96ff085104b4L,0x050b31ab14f29f76L, + 0x84abb28b5f87d4e6L }, + { 0xd5ed439f8270790aL,0x2d6cb59d85e3f46bL,0x75f55c1b6c1e2212L, + 0xe5436f6717655640L } }, + /* 137 */ + { { 0x53f9025e2286e8d5L,0x353c95b4864453beL,0xd832f5bde408e3a0L, + 0x0404f68b5b9ce99eL }, + { 0xcad33bdea781e8e5L,0x3cdf5018163c2f5bL,0x575769600119caa3L, + 0x3a4263df0ac1c701L } }, + /* 138 */ + { { 0xc2965ecc9aeb596dL,0x01ea03e7023c92b4L,0x4704b4b62e013961L, + 0x0ca8fd3f905ea367L }, + { 0x92523a42551b2b61L,0x1eb7a89c390fcd06L,0xe7f1d2be0392a63eL, + 0x96dca2644ddb0c33L } }, + /* 139 */ + { { 0x203bb43a387510afL,0x846feaa8a9a36a01L,0xd23a57702f950378L, + 0x4363e2123aad59dcL }, + { 0xca43a1c740246a47L,0xb362b8d2e55dd24dL,0xf9b086045d8faf96L, + 0x840e115cd8bb98c4L } }, + /* 140 */ + { { 0xf12205e21023e8a7L,0xc808a8cdd8dc7a0bL,0xe292a272163a5ddfL, + 0x5e0d6abd30ded6d4L }, + { 0x07a721c27cfc0f64L,0x42eec01d0e55ed88L,0x26a7bef91d1f9db2L, + 0x7dea48f42945a25aL } }, + /* 141 */ + { { 0xabdf6f1ce5060a81L,0xe79f9c72f8f95615L,0xcfd36c5406ac268bL, + 0xabc2a2beebfd16d1L }, + { 0x8ac66f91d3e2eac7L,0x6f10ba63d2dd0466L,0x6790e3770282d31bL, + 0x4ea353946c7eefc1L } }, + /* 142 */ + { { 0xed8a2f8d5266309dL,0x0a51c6c081945a3eL,0xcecaf45a578c5dc1L, + 0x3a76e6891c94ffc3L }, + { 0x9aace8a47d7b0d0fL,0x963ace968f584a5fL,0x51a30c724e697fbeL, + 0x8212a10a465e6464L } }, + /* 143 */ + { { 0xef7c61c3cfab8caaL,0x18eb8e840e142390L,0xcd1dff677e9733caL, + 0xaa7cab71599cb164L }, + { 0x02fc9273bc837bd1L,0xc06407d0c36af5d7L,0x17621292f423da49L, + 0x40e38073fe0617c3L } }, + /* 144 */ + { { 0xf4f80824a7bf9b7cL,0x365d23203fbe30d0L,0xbfbe532097cf9ce3L, + 0xe3604700b3055526L }, + { 0x4dcb99116cc6c2c7L,0x72683708ba4cbee6L,0xdcded434637ad9ecL, + 0x6542d677a3dee15fL } }, + /* 145 */ + { { 0x3f32b6d07b6c377aL,0x6cb03847903448beL,0xd6fdd3a820da8af7L, + 0xa6534aee09bb6f21L }, + { 0x30a1780d1035facfL,0x35e55a339dcb47e6L,0x6ea50fe1c447f393L, + 0xf3cb672fdc9aef22L } }, + /* 146 */ + { { 0xeb3719fe3b55fd83L,0xe0d7a46c875ddd10L,0x33ac9fa905cea784L, + 0x7cafaa2eaae870e7L }, + { 0x9b814d041d53b338L,0xe0acc0a0ef87e6c6L,0xfb93d10811672b0fL, + 0x0aab13c1b9bd522eL } }, + /* 147 */ + { { 0xddcce278d2681297L,0xcb350eb1b509546aL,0x2dc431737661aaf2L, + 0x4b91a602847012e9L }, + { 0xdcff109572f8ddcfL,0x08ebf61e9a911af4L,0x48f4360ac372430eL, + 0x49534c5372321cabL } }, + /* 148 */ + { { 0x83df7d71f07b7e9dL,0xa478efa313cd516fL,0x78ef264b6c047ee3L, + 0xcaf46c4fd65ac5eeL }, + { 0xa04d0c7792aa8266L,0xedf45466913684bbL,0x56e65168ae4b16b0L, + 0x14ce9e5704c6770fL } }, + /* 149 */ + { { 0x99445e3e965e8f91L,0xd3aca1bacb0f2492L,0xd31cc70f90c8a0a0L, + 0x1bb708a53e4c9a71L }, + { 0xd5ca9e69558bdd7aL,0x734a0508018a26b1L,0xb093aa714c9cf1ecL, + 0xf9d126f2da300102L } }, + /* 150 */ + { { 0x749bca7aaff9563eL,0xdd077afeb49914a0L,0xe27a0311bf5f1671L, + 0x807afcb9729ecc69L }, + { 0x7f8a9337c9b08b77L,0x86c3a785443c7e38L,0x85fafa59476fd8baL, + 0x751adcd16568cd8cL } }, + /* 151 */ + { { 0x8aea38b410715c0dL,0xd113ea718f7697f7L,0x665eab1493fbf06dL, + 0x29ec44682537743fL }, + { 0x3d94719cb50bebbcL,0x399ee5bfe4505422L,0x90cd5b3a8d2dedb1L, + 0xff9370e392a4077dL } }, + /* 152 */ + { { 0x59a2d69bc6b75b65L,0x4188f8d5266651c5L,0x28a9f33e3de9d7d2L, + 0x9776478ba2a9d01aL }, + { 0x8852622d929af2c7L,0x334f5d6d4e690923L,0xce6cc7e5a89a51e9L, + 0x74a6313fac2f82faL } }, + /* 153 */ + { { 0xb2f4dfddb75f079cL,0x85b07c9518e36fbbL,0x1b6cfcf0e7cd36ddL, + 0xab75be150ff4863dL }, + { 0x81b367c0173fc9b7L,0xb90a7420d2594fd0L,0x15fdbf03c4091236L, + 0x4ebeac2e0b4459f6L } }, + /* 154 */ + { { 0xeb6c5fe75c9f2c53L,0xd25220118eae9411L,0xc8887633f95ac5d8L, + 0xdf99887b2c1baffcL }, + { 0xbb78eed2850aaecbL,0x9d49181b01d6a272L,0x978dd511b1cdbcacL, + 0x27b040a7779f4058L } }, + /* 155 */ + { { 0x90405db7f73b2eb2L,0xe0df85088e1b2118L,0x501b71525962327eL, + 0xb393dd37e4cfa3f5L }, + { 0xa1230e7b3fd75165L,0xd66344c2bcd33554L,0x6c36f1be0f7b5022L, + 0x09588c12d0463419L } }, + /* 156 */ + { { 0xe086093f02601c3bL,0xfb0252f8cf5c335fL,0x955cf280894aff28L, + 0x81c879a9db9f648bL }, + { 0x040e687cc6f56c51L,0xfed471693f17618cL,0x44f88a419059353bL, + 0xfa0d48f55fc11bc4L } }, + /* 157 */ + { { 0xbc6e1c9de1608e4dL,0x010dda113582822cL,0xf6b7ddc1157ec2d7L, + 0x8ea0e156b6a367d6L }, + { 0xa354e02f2383b3b4L,0x69966b943f01f53cL,0x4ff6632b2de03ca5L, + 0x3f5ab924fa00b5acL } }, + /* 158 */ + { { 0x337bb0d959739efbL,0xc751b0f4e7ebec0dL,0x2da52dd6411a67d1L, + 0x8bc768872b74256eL }, + { 0xa5be3b7282d3d253L,0xa9f679a1f58d779fL,0xa1cac168e16767bbL, + 0xb386f19060fcf34fL } }, + /* 159 */ + { { 0x31f3c1352fedcfc2L,0x5396bf6262f8af0dL,0x9a02b4eae57288c2L, + 0x4cb460f71b069c4dL }, + { 0xae67b4d35b8095eaL,0x92bbf8596fc07603L,0xe1475f66b614a165L, + 0x52c0d50895ef5223L } }, + /* 160 */ + { { 0x231c210e15339848L,0xe87a28e870778c8dL,0x9d1de6616956e170L, + 0x4ac3c9382bb09c0bL }, + { 0x19be05516998987dL,0x8b2376c4ae09f4d6L,0x1de0b7651a3f933dL, + 0x380d94c7e39705f4L } }, + /* 161 */ + { { 0x01a355aa81542e75L,0x96c724a1ee01b9b7L,0x6b3a2977624d7087L, + 0x2ce3e171de2637afL }, + { 0xcfefeb49f5d5bc1aL,0xa655607e2777e2b5L,0x4feaac2f9513756cL, + 0x2e6cd8520b624e4dL } }, + /* 162 */ + { { 0x3685954b8c31c31dL,0x68533d005bf21a0cL,0x0bd7626e75c79ec9L, + 0xca17754742c69d54L }, + { 0xcc6edafff6d2dbb2L,0xfd0d8cbd174a9d18L,0x875e8793aa4578e8L, + 0xa976a7139cab2ce6L } }, + /* 163 */ + { { 0x0a651f1b93fb353dL,0xd75cab8b57fcfa72L,0xaa88cfa731b15281L, + 0x8720a7170a1f4999L }, + { 0x8c3e8d37693e1b90L,0xd345dc0b16f6dfc3L,0x8ea8d00ab52a8742L, + 0x9719ef29c769893cL } }, + /* 164 */ + { { 0x820eed8d58e35909L,0x9366d8dc33ddc116L,0xd7f999d06e205026L, + 0xa5072976e15704c1L }, + { 0x002a37eac4e70b2eL,0x84dcf6576890aa8aL,0xcd71bf18645b2a5cL, + 0x99389c9df7b77725L } }, + /* 165 */ + { { 0x238c08f27ada7a4bL,0x3abe9d03fd389366L,0x6b672e89766f512cL, + 0xa88806aa202c82e4L }, + { 0x6602044ad380184eL,0xa8cb78c4126a8b85L,0x79d670c0ad844f17L, + 0x0043bffb4738dcfeL } }, + /* 166 */ + { { 0x8d59b5dc36d5192eL,0xacf885d34590b2afL,0x83566d0a11601781L, + 0x52f3ef01ba6c4866L }, + { 0x3986732a0edcb64dL,0x0a482c238068379fL,0x16cbe5fa7040f309L, + 0x3296bd899ef27e75L } }, + /* 167 */ + { { 0x476aba89454d81d7L,0x9eade7ef51eb9b3cL,0x619a21cd81c57986L, + 0x3b90febfaee571e9L }, + { 0x9393023e5496f7cbL,0x55be41d87fb51bc4L,0x03f1dd4899beb5ceL, + 0x6e88069d9f810b18L } }, + /* 168 */ + { { 0xce37ab11b43ea1dbL,0x0a7ff1a95259d292L,0x851b02218f84f186L, + 0xa7222beadefaad13L }, + { 0xa2ac78ec2b0a9144L,0x5a024051f2fa59c5L,0x91d1eca56147ce38L, + 0xbe94d523bc2ac690L } }, + /* 169 */ + { { 0x72f4945e0b226ce7L,0xb8afd747967e8b70L,0xedea46f185a6c63eL, + 0x7782defe9be8c766L }, + { 0x760d2aa43db38626L,0x460ae78776f67ad1L,0x341b86fc54499cdbL, + 0x03838567a2892e4bL } }, + /* 170 */ + { { 0x2d8daefd79ec1a0fL,0x3bbcd6fdceb39c97L,0xf5575ffc58f61a95L, + 0xdbd986c4adf7b420L }, + { 0x81aa881415f39eb7L,0x6ee2fcf5b98d976cL,0x5465475dcf2f717dL, + 0x8e24d3c46860bbd0L } }, + /* 171 */ + { { 0x749d8e549a587390L,0x12bb194f0cbec588L,0x46e07da4b25983c6L, + 0x541a99c4407bafc8L }, + { 0xdb241692624c8842L,0x6044c12ad86c05ffL,0xc59d14b44f7fcf62L, + 0xc0092c49f57d35d1L } }, + /* 172 */ + { { 0xd3cc75c3df2e61efL,0x7e8841c82e1b35caL,0xc62d30d1909f29f4L, + 0x75e406347286944dL }, + { 0xe7d41fc5bbc237d0L,0xc9537bf0ec4f01c9L,0x91c51a16282bd534L, + 0x5b7cb658c7848586L } }, + /* 173 */ + { { 0x964a70848a28ead1L,0x802dc508fd3b47f6L,0x9ae4bfd1767e5b39L, + 0x7ae13eba8df097a1L }, + { 0xfd216ef8eadd384eL,0x0361a2d9b6b2ff06L,0x204b98784bcdb5f3L, + 0x787d8074e2a8e3fdL } }, + /* 174 */ + { { 0xc5e25d6b757fbb1cL,0xe47bddb2ca201debL,0x4a55e9a36d2233ffL, + 0x5c2228199ef28484L }, + { 0x773d4a8588315250L,0x21b21a2b827097c1L,0xab7c4ea1def5d33fL, + 0xe45d37abbaf0f2b0L } }, + /* 175 */ + { { 0xd2df1e3428511c8aL,0xebb229c8bdca6cd3L,0x578a71a7627c39a7L, + 0xed7bc12284dfb9d3L }, + { 0xcf22a6df93dea561L,0x5443f18dd48f0ed1L,0xd8b861405bad23e8L, + 0xaac97cc945ca6d27L } }, + /* 176 */ + { { 0xeb54ea74a16bd00aL,0xd839e9adf5c0bcc1L,0x092bb7f11f9bfc06L, + 0x318f97b31163dc4eL }, + { 0xecc0c5bec30d7138L,0x44e8df23abc30220L,0x2bb7972fb0223606L, + 0xfa41faa19a84ff4dL } }, + /* 177 */ + { { 0x4402d974a6642269L,0xc81814ce9bb783bdL,0x398d38e47941e60bL, + 0x38bb6b2c1d26e9e2L }, + { 0xc64e4a256a577f87L,0x8b52d253dc11fe1cL,0xff336abf62280728L, + 0x94dd0905ce7601a5L } }, + /* 178 */ + { { 0x156cf7dcde93f92aL,0xa01333cb89b5f315L,0x02404df9c995e750L, + 0x92077867d25c2ae9L }, + { 0xe2471e010bf39d44L,0x5f2c902096bb53d7L,0x4c44b7b35c9c3d8fL, + 0x81e8428bd29beb51L } }, + /* 179 */ + { { 0x6dd9c2bac477199fL,0x8cb8eeee6b5ecdd9L,0x8af7db3fee40fd0eL, + 0x1b94ab62dbbfa4b1L }, + { 0x44f0d8b3ce47f143L,0x51e623fc63f46163L,0xf18f270fcc599383L, + 0x06a38e28055590eeL } }, + /* 180 */ + { { 0x2e5b0139b3355b49L,0x20e26560b4ebf99bL,0xc08ffa6bd269f3dcL, + 0xa7b36c2083d9d4f8L }, + { 0x64d15c3a1b3e8830L,0xd5fceae1a89f9c0bL,0xcfeee4a2e2d16930L, + 0xbe54c6b4a2822a20L } }, + /* 181 */ + { { 0xd6cdb3df8d91167cL,0x517c3f79e7a6625eL,0x7105648f346ac7f4L, + 0xbf30a5abeae022bbL }, + { 0x8e7785be93828a68L,0x5161c3327f3ef036L,0xe11b5feb592146b2L, + 0xd1c820de2732d13aL } }, + /* 182 */ + { { 0x043e13479038b363L,0x58c11f546b05e519L,0x4fe57abe6026cad1L, + 0xb7d17bed68a18da3L }, + { 0x44ca5891e29c2559L,0x4f7a03765bfffd84L,0x498de4af74e46948L, + 0x3997fd5e6412cc64L } }, + /* 183 */ + { { 0xf20746828bd61507L,0x29e132d534a64d2aL,0xffeddfb08a8a15e3L, + 0x0eeb89293c6c13e8L }, + { 0xe9b69a3ea7e259f8L,0xce1db7e6d13e7e67L,0x277318f6ad1fa685L, + 0x228916f8c922b6efL } }, + /* 184 */ + { { 0x959ae25b0a12ab5bL,0xcc11171f957bc136L,0x8058429ed16e2b0cL, + 0xec05ad1d6e93097eL }, + { 0x157ba5beac3f3708L,0x31baf93530b59d77L,0x47b55237118234e5L, + 0x7d3141567ff11b37L } }, + /* 185 */ + { { 0x7bd9c05cf6dfefabL,0xbe2f2268dcb37707L,0xe53ead973a38bb95L, + 0xe9ce66fc9bc1d7a3L }, + { 0x75aa15766f6a02a1L,0x38c087df60e600edL,0xf8947f3468cdc1b9L, + 0xd9650b0172280651L } }, + /* 186 */ + { { 0x504b4c4a5a057e60L,0xcbccc3be8def25e4L,0xa635320817c1ccbdL, + 0x14d6699a804eb7a2L }, + { 0x2c8a8415db1f411aL,0x09fbaf0bf80d769cL,0xb4deef901c2f77adL, + 0x6f4c68410d43598aL } }, + /* 187 */ + { { 0x8726df4e96c24a96L,0x534dbc85fcbd99a3L,0x3c466ef28b2ae30aL, + 0x4c4350fd61189abbL }, + { 0x2967f716f855b8daL,0x41a42394463c38a1L,0xc37e1413eae93343L, + 0xa726d2425a3118b5L } }, + /* 188 */ + { { 0xdae6b3ee948c1086L,0xf1de503dcbd3a2e1L,0x3f35ed3f03d022f3L, + 0x13639e82cc6cf392L }, + { 0x9ac938fbcdafaa86L,0xf45bc5fb2654a258L,0x1963b26e45051329L, + 0xca9365e1c1a335a3L } }, + /* 189 */ + { { 0x3615ac754c3b2d20L,0x742a5417904e241bL,0xb08521c4cc9d071dL, + 0x9ce29c34970b72a5L }, + { 0x8cc81f736d3e0ad6L,0x8060da9ef2f8434cL,0x35ed1d1a6ce862d9L, + 0x48c4abd7ab42af98L } }, + /* 190 */ + { { 0xd221b0cc40c7485aL,0xead455bbe5274dbfL,0x493c76989263d2e8L, + 0x78017c32f67b33cbL }, + { 0xb9d35769930cb5eeL,0xc0d14e940c408ed2L,0xf8b7bf55272f1a4dL, + 0x53cd0454de5c1c04L } }, + /* 191 */ + { { 0xbcd585fa5d28ccacL,0x5f823e56005b746eL,0x7c79f0a1cd0123aaL, + 0xeea465c1d3d7fa8fL }, + { 0x7810659f0551803bL,0x6c0b599f7ce6af70L,0x4195a77029288e70L, + 0x1b6e42a47ae69193L } }, + /* 192 */ + { { 0x2e80937cf67d04c3L,0x1e312be289eeb811L,0x56b5d88792594d60L, + 0x0224da14187fbd3dL }, + { 0x87abb8630c5fe36fL,0x580f3c604ef51f5fL,0x964fb1bfb3b429ecL, + 0x60838ef042bfff33L } }, + /* 193 */ + { { 0x432cb2f27e0bbe99L,0x7bda44f304aa39eeL,0x5f497c7a9fa93903L, + 0x636eb2022d331643L }, + { 0xfcfd0e6193ae00aaL,0x875a00fe31ae6d2fL,0xf43658a29f93901cL, + 0x8844eeb639218bacL } }, + /* 194 */ + { { 0x114171d26b3bae58L,0x7db3df7117e39f3eL,0xcd37bc7f81a8eadaL, + 0x27ba83dc51fb789eL }, + { 0xa7df439ffbf54de5L,0x7277030bb5fe1a71L,0x42ee8e35db297a48L, + 0xadb62d3487f3a4abL } }, + /* 195 */ + { { 0x9b1168a2a175df2aL,0x082aa04f618c32e9L,0xc9e4f2e7146b0916L, + 0xb990fd7675e7c8b2L }, + { 0x0829d96b4df37313L,0x1c205579d0b40789L,0x66c9ae4a78087711L, + 0x81707ef94d10d18dL } }, + /* 196 */ + { { 0x97d7cab203d6ff96L,0x5b851bfc0d843360L,0x268823c4d042db4bL, + 0x3792daead5a8aa5cL }, + { 0x52818865941afa0bL,0xf3e9e74142d83671L,0x17c825275be4e0a7L, + 0x5abd635e94b001baL } }, + /* 197 */ + { { 0x727fa84e0ac4927cL,0xe3886035a7c8cf23L,0xa4bcd5ea4adca0dfL, + 0x5995bf21846ab610L }, + { 0xe90f860b829dfa33L,0xcaafe2ae958fc18bL,0x9b3baf4478630366L, + 0x44c32ca2d483411eL } }, + /* 198 */ + { { 0xa74a97f1e40ed80cL,0x5f938cb131d2ca82L,0x53f2124b7c2d6ad9L, + 0x1f2162fb8082a54cL }, + { 0x7e467cc5720b173eL,0x40e8a666085f12f9L,0x8cebc20e4c9d65dcL, + 0x8f1d402bc3e907c9L } }, + /* 199 */ + { { 0x4f592f9cfbc4058aL,0xb15e14b6292f5670L,0xc55cfe37bc1d8c57L, + 0xb1980f43926edbf9L }, + { 0x98c33e0932c76b09L,0x1df5279d33b07f78L,0x6f08ead4863bb461L, + 0x2828ad9b37448e45L } }, + /* 200 */ + { { 0x696722c4c4cf4ac5L,0xf5ac1a3fdde64afbL,0x0551baa2e0890832L, + 0x4973f1275a14b390L }, + { 0xe59d8335322eac5dL,0x5e07eef50bd9b568L,0xab36720fa2588393L, + 0x6dac8ed0db168ac7L } }, + /* 201 */ + { { 0xf7b545aeeda835efL,0x4aa113d21d10ed51L,0x035a65e013741b09L, + 0x4b23ef5920b9de4cL }, + { 0xe82bb6803c4c7341L,0xd457706d3f58bc37L,0x73527863a51e3ee8L, + 0x4dd71534ddf49a4eL } }, + /* 202 */ + { { 0xbf94467295476cd9L,0x648d072fe31a725bL,0x1441c8b8fc4b67e0L, + 0xfd3170002f4a4dbbL }, + { 0x1cb43ff48995d0e1L,0x76e695d10ef729aaL,0xe0d5f97641798982L, + 0x14fac58c9569f365L } }, + /* 203 */ + { { 0xad9a0065f312ae18L,0x51958dc0fcc93fc9L,0xd9a142408a7d2846L, + 0xed7c765136abda50L }, + { 0x46270f1a25d4abbcL,0x9b5dd8f3f1a113eaL,0xc609b0755b51952fL, + 0xfefcb7f74d2e9f53L } }, + /* 204 */ + { { 0xbd09497aba119185L,0xd54e8c30aac45ba4L,0x492479deaa521179L, + 0x1801a57e87e0d80bL }, + { 0x073d3f8dfcafffb0L,0x6cf33c0bae255240L,0x781d763b5b5fdfbcL, + 0x9f8fc11e1ead1064L } }, + /* 205 */ + { { 0x1583a1715e69544cL,0x0eaf8567f04b7813L,0x1e22a8fd278a4c32L, + 0xa9d3809d3d3a69a9L }, + { 0x936c2c2c59a2da3bL,0x38ccbcf61895c847L,0x5e65244e63d50869L, + 0x3006b9aee1178ef7L } }, + /* 206 */ + { { 0x0bb1f2b0c9eead28L,0x7eef635d89f4dfbcL,0x074757fdb2ce8939L, + 0x0ab85fd745f8f761L }, + { 0xecda7c933e5b4549L,0x4be2bb5c97922f21L,0x261a1274b43b8040L, + 0xb122d67511e942c2L } }, + /* 207 */ + { { 0x3be607be66a5ae7aL,0x01e703fa76adcbe3L,0xaf9043014eb6e5c5L, + 0x9f599dc1097dbaecL }, + { 0x6d75b7180ff250edL,0x8eb91574349a20dcL,0x425605a410b227a3L, + 0x7d5528e08a294b78L } }, + /* 208 */ + { { 0xf0f58f6620c26defL,0x025585ea582b2d1eL,0xfbe7d79b01ce3881L, + 0x28ccea01303f1730L }, + { 0xd1dabcd179644ba5L,0x1fc643e806fff0b8L,0xa60a76fc66b3e17bL, + 0xc18baf48a1d013bfL } }, + /* 209 */ + { { 0x34e638c85dc4216dL,0x00c01067206142acL,0xd453a17195f5064aL, + 0x9def809db7a9596bL }, + { 0x41e8642e67ab8d2cL,0xb42404336237a2b6L,0x7d506a6d64c4218bL, + 0x0357f8b068808ce5L } }, + /* 210 */ + { { 0x8e9dbe644cd2cc88L,0xcc61c28df0b8f39dL,0x4a309874cd30a0c8L, + 0xe4a01add1b489887L }, + { 0x2ed1eeacf57cd8f9L,0x1b767d3ebd594c48L,0xa7295c717bd2f787L, + 0x466d7d79ce10cc30L } }, + /* 211 */ + { { 0x47d318929dada2c7L,0x4fa0a6c38f9aa27dL,0x90e4fd28820a59e1L, + 0xc672a522451ead1aL }, + { 0x30607cc85d86b655L,0xf0235d3bf9ad4af1L,0x99a08680571172a6L, + 0x5e3d64faf2a67513L } }, + /* 212 */ + { { 0xaa6410c79b3b4416L,0xcd8fcf85eab26d99L,0x5ebff74adb656a74L, + 0x6c8a7a95eb8e42fcL }, + { 0x10c60ba7b02a63bdL,0x6b2f23038b8f0047L,0x8c6c3738312d90b0L, + 0x348ae422ad82ca91L } }, + /* 213 */ + { { 0x7f4746635ccda2fbL,0x22accaa18e0726d2L,0x85adf782492b1f20L, + 0xc1074de0d9ef2d2eL }, + { 0xfcf3ce44ae9a65b3L,0xfd71e4ac05d7151bL,0xd4711f50ce6a9788L, + 0xfbadfbdbc9e54ffcL } }, + /* 214 */ + { { 0x1713f1cd20a99363L,0xb915658f6cf22775L,0x968175cd24d359b2L, + 0xb7f976b483716fcdL }, + { 0x5758e24d5d6dbf74L,0x8d23bafd71c3af36L,0x48f477600243dfe3L, + 0xf4d41b2ecafcc805L } }, + /* 215 */ + { { 0x51f1cf28fdabd48dL,0xce81be3632c078a4L,0x6ace2974117146e9L, + 0x180824eae0160f10L }, + { 0x0387698b66e58358L,0x63568752ce6ca358L,0x82380e345e41e6c5L, + 0x67e5f63983cf6d25L } }, + /* 216 */ + { { 0xf89ccb8dcf4899efL,0x949015f09ebb44c0L,0x546f9276b2598ec9L, + 0x9fef789a04c11fc6L }, + { 0x6d367ecf53d2a071L,0xb10e1a7fa4519b09L,0xca6b3fb0611e2eefL, + 0xbc80c181a99c4e20L } }, + /* 217 */ + { { 0x972536f8e5eb82e6L,0x1a484fc7f56cb920L,0xc78e217150b5da5eL, + 0x49270e629f8cdf10L }, + { 0x1a39b7bbea6b50adL,0x9a0284c1a2388ffcL,0x5403eb178107197bL, + 0xd2ee52f961372f7fL } }, + /* 218 */ + { { 0xd37cd28588e0362aL,0x442fa8a78fa5d94dL,0xaff836e5a434a526L, + 0xdfb478bee5abb733L }, + { 0xa91f1ce7673eede6L,0xa5390ad42b5b2f04L,0x5e66f7bf5530da2fL, + 0xd9a140b408df473aL } }, + /* 219 */ + { { 0x0e0221b56e8ea498L,0x623478293563ee09L,0xe06b8391335d2adeL, + 0x760c058d623f4b1aL }, + { 0x0b89b58cc198aa79L,0xf74890d2f07aba7fL,0x4e204110fde2556aL, + 0x7141982d8f190409L } }, + /* 220 */ + { { 0x6f0a0e334d4b0f45L,0xd9280b38392a94e1L,0x3af324c6b3c61d5eL, + 0x3af9d1ce89d54e47L }, + { 0xfd8f798120930371L,0xeda2664c21c17097L,0x0e9545dcdc42309bL, + 0xb1f815c373957dd6L } }, + /* 221 */ + { { 0x84faa78e89fec44aL,0xc8c2ae473caa4cafL,0x691c807dc1b6a624L, + 0xa41aed141543f052L }, + { 0x424353997d5ffe04L,0x8bacb2df625b6e20L,0x85d660be87817775L, + 0xd6e9c1dd86fb60efL } }, + /* 222 */ + { { 0x3aa2e97ec6853264L,0x771533b7e2304a0bL,0x1b912bb7b8eae9beL, + 0x9c9c6e10ae9bf8c2L }, + { 0xa2309a59e030b74cL,0x4ed7494d6a631e90L,0x89f44b23a49b79f2L, + 0x566bd59640fa61b6L } }, + /* 223 */ + { { 0x066c0118c18061f3L,0x190b25d37c83fc70L,0xf05fc8e027273245L, + 0xcf2c7390f525345eL }, + { 0xa09bceb410eb30cfL,0xcfd2ebba0d77703aL,0xe842c43a150ff255L, + 0x02f517558aa20979L } }, + /* 224 */ + { { 0x396ef794addb7d07L,0x0b4fc74224455500L,0xfaff8eacc78aa3ceL, + 0x14e9ada5e8d4d97dL }, + { 0xdaa480a12f7079e2L,0x45baa3cde4b0800eL,0x01765e2d7838157dL, + 0xa0ad4fab8e9d9ae8L } }, + /* 225 */ + { { 0x0bfb76214a653618L,0x1872813c31eaaa5fL,0x1553e73744949d5eL, + 0xbcd530b86e56ed1eL }, + { 0x169be85332e9c47bL,0xdc2776feb50059abL,0xcdba9761192bfbb4L, + 0x909283cf6979341dL } }, + /* 226 */ + { { 0x67b0032476e81a13L,0x9bee1a9962171239L,0x08ed361bd32e19d6L, + 0x35eeb7c9ace1549aL }, + { 0x1280ae5a7e4e5bdcL,0x2dcd2cd3b6ceec6eL,0x52e4224c6e266bc1L, + 0x9a8b2cf4448ae864L } }, + /* 227 */ + { { 0xf6471bf209d03b59L,0xc90e62a3b65af2abL,0xff7ff168ebd5eec9L, + 0x6bdb60f4d4491379L }, + { 0xdadafebc8a55bc30L,0xc79ead1610097fe0L,0x42e197414c1e3bddL, + 0x01ec3cfd94ba08a9L } }, + /* 228 */ + { { 0xba6277ebdc9485c2L,0x48cc9a7922fb10c7L,0x4f61d60f70a28d8aL, + 0xd1acb1c0475464f6L }, + { 0xd26902b126f36612L,0x59c3a44ee0618d8bL,0x4df8a813308357eeL, + 0x7dcd079d405626c2L } }, + /* 229 */ + { { 0x5ce7d4d3f05a4b48L,0xadcd295237230772L,0xd18f7971812a915aL, + 0x0bf53589377d19b8L }, + { 0x35ecd95a6c68ea73L,0xc7f3bbca823a584dL,0x9fb674c6f473a723L, + 0xd28be4d9e16686fcL } }, + /* 230 */ + { { 0x5d2b990638fa8e4bL,0x559f186e893fd8fcL,0x3a6de2aa436fb6fcL, + 0xd76007aa510f88ceL }, + { 0x2d10aab6523a4988L,0xb455cf4474dd0273L,0x7f467082a3407278L, + 0xf2b52f68b303bb01L } }, + /* 231 */ + { { 0x0d57eafa9835b4caL,0x2d2232fcbb669cbcL,0x8eeeb680c6643198L, + 0xd8dbe98ecc5aed3aL }, + { 0xcba9be3fc5a02709L,0x30be68e5f5ba1fa8L,0xfebd43cdf10ea852L, + 0xe01593a3ee559705L } }, + /* 232 */ + { { 0xd3e5af50ea75a0a6L,0x512226ac57858033L,0x6fe6d50fd0176406L, + 0xafec07b1aeb8ef06L }, + { 0x7fb9956780bb0a31L,0x6f1af3cc37309aaeL,0x9153a15a01abf389L, + 0xa71b93546e2dbfddL } }, + /* 233 */ + { { 0xbf8e12e018f593d2L,0xd1a90428a078122bL,0x150505db0ba4f2adL, + 0x53a2005c628523d9L }, + { 0x07c8b639e7f2b935L,0x2bff975ac182961aL,0x86bceea77518ca2cL, + 0xbf47d19b3d588e3dL } }, + /* 234 */ + { { 0x672967a7dd7665d5L,0x4e3030572f2f4de5L,0x144005ae80d4903fL, + 0x001c2c7f39c9a1b6L }, + { 0x143a801469efc6d6L,0xc810bdaa7bc7a724L,0x5f65670ba78150a4L, + 0xfdadf8e786ffb99bL } }, + /* 235 */ + { { 0xfd38cb88ffc00785L,0x77fa75913b48eb67L,0x0454d055bf368fbcL, + 0x3a838e4d5aa43c94L }, + { 0x561663293e97bb9aL,0x9eb93363441d94d9L,0x515591a60adb2a83L, + 0x3cdb8257873e1da3L } }, + /* 236 */ + { { 0x137140a97de77eabL,0xf7e1c50d41648109L,0x762dcad2ceb1d0dfL, + 0x5a60cc89f1f57fbaL }, + { 0x80b3638240d45673L,0x1b82be195913c655L,0x057284b8dd64b741L, + 0x922ff56fdbfd8fc0L } }, + /* 237 */ + { { 0x1b265deec9a129a1L,0xa5b1ce57cc284e04L,0x04380c46cebfbe3cL, + 0x72919a7df6c5cd62L }, + { 0x298f453a8fb90f9aL,0xd719c00b88e4031bL,0xe32c0e77796f1856L, + 0x5e7917803624089aL } }, + /* 238 */ + { { 0x5c16ec557f63cdfbL,0x8e6a3571f1cae4fdL,0xfce26bea560597caL, + 0x4e0a5371e24c2fabL }, + { 0x276a40d3a5765357L,0x3c89af440d73a2b4L,0xb8f370ae41d11a32L, + 0xf5ff7818d56604eeL } }, + /* 239 */ + { { 0xfbf3e3fe1a09df21L,0x26d5d28ee66e8e47L,0x2096bd0a29c89015L, + 0xe41df0e9533f5e64L }, + { 0x305fda40b3ba9e3fL,0xf2340ceb2604d895L,0x0866e1927f0367c7L, + 0x8edd7d6eac4f155fL } }, + /* 240 */ + { { 0xc9a1dc0e0bfc8ff3L,0x14efd82be936f42fL,0x67016f7ccca381efL, + 0x1432c1caed8aee96L }, + { 0xec68482970b23c26L,0xa64fe8730735b273L,0xe389f6e5eaef0f5aL, + 0xcaef480b5ac8d2c6L } }, + /* 241 */ + { { 0x5245c97875315922L,0xd82951713063cca5L,0xf3ce60d0b64ef2cbL, + 0xd0ba177e8efae236L }, + { 0x53a9ae8fb1b3af60L,0x1a796ae53d2da20eL,0x01d63605df9eef28L, + 0xf31c957c1c54ae16L } }, + /* 242 */ + { { 0xc0f58d5249cc4597L,0xdc5015b0bae0a028L,0xefc5fc55734a814aL, + 0x013404cb96e17c3aL }, + { 0xb29e2585c9a824bfL,0xd593185e001eaed7L,0x8d6ee68261ef68acL, + 0x6f377c4b91933e6cL } }, + /* 243 */ + { { 0x9f93bad1a8333fd2L,0xa89302025a2a95b8L,0x211e5037eaf75aceL, + 0x6dba3e4ed2d09506L }, + { 0xa48ef98cd04399cdL,0x1811c66ee6b73adeL,0x72f60752c17ecaf3L, + 0xf13cf3423becf4a7L } }, + /* 244 */ + { { 0xceeb9ec0a919e2ebL,0x83a9a195f62c0f68L,0xcfba3bb67aba2299L, + 0xc83fa9a9274bbad3L }, + { 0x0d7d1b0b62fa1ce0L,0xe58b60f53418efbfL,0xbfa8ef9e52706f04L, + 0xb49d70f45d702683L } }, + /* 245 */ + { { 0x914c7510fad5513bL,0x05f32eecb1751e2dL,0x6d850418d9fb9d59L, + 0x59cfadbb0c30f1cfL }, + { 0xe167ac2355cb7fd6L,0x249367b8820426a3L,0xeaeec58c90a78864L, + 0x5babf362354a4b67L } }, + /* 246 */ + { { 0x37c981d1ee424865L,0x8b002878f2e5577fL,0x702970f1b9e0c058L, + 0x6188c6a79026c8f0L }, + { 0x06f9a19bd0f244daL,0x1ecced5cfb080873L,0x35470f9b9f213637L, + 0x993fe475df50b9d9L } }, + /* 247 */ + { { 0x68e31cdf9b2c3609L,0x84eb19c02c46d4eaL,0x7ac9ec1a9a775101L, + 0x81f764664c80616bL }, + { 0x1d7c2a5a75fbe978L,0x6743fed3f183b356L,0x838d1f04501dd2bfL, + 0x564a812a5fe9060dL } }, + /* 248 */ + { { 0x7a5a64f4fa817d1dL,0x55f96844bea82e0fL,0xb5ff5a0fcd57f9aaL, + 0x226bf3cf00e51d6cL }, + { 0xd6d1a9f92f2833cfL,0x20a0a35a4f4f89a8L,0x11536c498f3f7f77L, + 0x68779f47ff257836L } }, + /* 249 */ + { { 0x79b0c1c173043d08L,0xa54467741fc020faL,0xd3767e289a6d26d0L, + 0x97bcb0d1eb092e0bL }, + { 0x2ab6eaa8f32ed3c3L,0xc8a4f151b281bc48L,0x4d1bf4f3bfa178f3L, + 0xa872ffe80a784655L } }, + /* 250 */ + { { 0xb1ab7935a32b2086L,0xe1eb710e8160f486L,0x9bd0cd913b6ae6beL, + 0x02812bfcb732a36aL }, + { 0xa63fd7cacf605318L,0x646e5d50fdfd6d1dL,0xa1d683982102d619L, + 0x07391cc9fe5396afL } }, + /* 251 */ + { { 0xc50157f08b80d02bL,0x6b8333d162877f7fL,0x7aca1af878d542aeL, + 0x355d2adc7e6d2a08L }, + { 0xb41f335a287386e1L,0xfd272a94f8e43275L,0x286ca2cde79989eaL, + 0x3dc2b1e37c2a3a79L } }, + /* 252 */ + { { 0xd689d21c04581352L,0x0a00c825376782beL,0x203bd5909fed701fL, + 0xc47869103ccd846bL }, + { 0x5dba770824c768edL,0x72feea026841f657L,0x73313ed56accce0eL, + 0xccc42968d5bb4d32L } }, + /* 253 */ + { { 0x94e50de13d7620b9L,0xd89a5c8a5992a56aL,0xdc007640675487c9L, + 0xe147eb42aa4871cfL }, + { 0x274ab4eeacf3ae46L,0xfd4936fb50350fbeL,0xdf2afe4748c840eaL, + 0x239ac047080e96e3L } }, + /* 254 */ + { { 0x481d1f352bfee8d4L,0xce80b5cffa7b0fecL,0x105c4c9e2ce9af3cL, + 0xc55fa1a3f5f7e59dL }, + { 0x3186f14e8257c227L,0xc5b1653f342be00bL,0x09afc998aa904fb2L, + 0x094cd99cd4f4b699L } }, + /* 255 */ + { { 0x8a981c84d703bebaL,0x8631d15032ceb291L,0xa445f2c9e3bd49ecL, + 0xb90a30b642abad33L }, + { 0xb465404fb4a5abf9L,0x004750c375db7603L,0x6f9a42ccca35d89fL, + 0x019f8b9a1b7924f7L } }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_4(r, &p256_base, p256_table, + k, map, heap); +} + +#else +/* The index into pre-computation table to use. */ +static const uint8_t recode_index_4_7[130] = { + 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, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, + 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 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 const uint8_t recode_neg_4_7[130] = { + 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, 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, + 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 perform. + */ +static void sp_256_ecc_recode_7_4(const sp_digit* k, ecc_recode_256* 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<37; i++) { + y = n; + if (o + 7 < 64) { + y &= 0x7f; + n >>= 7; + o += 7; + } + else if (o + 7 == 64) { + n >>= 7; + if (++j < 4) + n = k[j]; + o = 0; + } + else if (++j < 4) { + n = k[j]; + y |= (n << (64 - o)) & 0x7f; + o -= 57; + n >>= o; + } + + y += carry; + v[i].i = recode_index_4_7[y]; + v[i].neg = recode_neg_4_7[y]; + carry = (y >> 7) + v[i].neg; + } +} + +static const sp_table_entry_256 p256_table[2405] = { + /* 0 << 0 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 0 */ + { { 0x79e730d418a9143cL,0x75ba95fc5fedb601L,0x79fb732b77622510L, + 0x18905f76a53755c6L }, + { 0xddf25357ce95560aL,0x8b4ab8e4ba19e45cL,0xd2e88688dd21f325L, + 0x8571ff1825885d85L } }, + /* 2 << 0 */ + { { 0x850046d410ddd64dL,0xaa6ae3c1a433827dL,0x732205038d1490d9L, + 0xf6bb32e43dcf3a3bL }, + { 0x2f3648d361bee1a5L,0x152cd7cbeb236ff8L,0x19a8fb0e92042dbeL, + 0x78c577510a5b8a3bL } }, + /* 3 << 0 */ + { { 0xffac3f904eebc127L,0xb027f84a087d81fbL,0x66ad77dd87cbbc98L, + 0x26936a3fb6ff747eL }, + { 0xb04c5c1fc983a7ebL,0x583e47ad0861fe1aL,0x788208311a2ee98eL, + 0xd5f06a29e587cc07L } }, + /* 4 << 0 */ + { { 0x74b0b50d46918dccL,0x4650a6edc623c173L,0x0cdaacace8100af2L, + 0x577362f541b0176bL }, + { 0x2d96f24ce4cbaba6L,0x17628471fad6f447L,0x6b6c36dee5ddd22eL, + 0x84b14c394c5ab863L } }, + /* 5 << 0 */ + { { 0xbe1b8aaec45c61f5L,0x90ec649a94b9537dL,0x941cb5aad076c20cL, + 0xc9079605890523c8L }, + { 0xeb309b4ae7ba4f10L,0x73c568efe5eb882bL,0x3540a9877e7a1f68L, + 0x73a076bb2dd1e916L } }, + /* 6 << 0 */ + { { 0x403947373e77664aL,0x55ae744f346cee3eL,0xd50a961a5b17a3adL, + 0x13074b5954213673L }, + { 0x93d36220d377e44bL,0x299c2b53adff14b5L,0xf424d44cef639f11L, + 0xa4c9916d4a07f75fL } }, + /* 7 << 0 */ + { { 0x0746354ea0173b4fL,0x2bd20213d23c00f7L,0xf43eaab50c23bb08L, + 0x13ba5119c3123e03L }, + { 0x2847d0303f5b9d4dL,0x6742f2f25da67bddL,0xef933bdc77c94195L, + 0xeaedd9156e240867L } }, + /* 8 << 0 */ + { { 0x27f14cd19499a78fL,0x462ab5c56f9b3455L,0x8f90f02af02cfc6bL, + 0xb763891eb265230dL }, + { 0xf59da3a9532d4977L,0x21e3327dcf9eba15L,0x123c7b84be60bbf0L, + 0x56ec12f27706df76L } }, + /* 9 << 0 */ + { { 0x75c96e8f264e20e8L,0xabe6bfed59a7a841L,0x2cc09c0444c8eb00L, + 0xe05b3080f0c4e16bL }, + { 0x1eb7777aa45f3314L,0x56af7bedce5d45e3L,0x2b6e019a88b12f1aL, + 0x086659cdfd835f9bL } }, + /* 10 << 0 */ + { { 0x2c18dbd19dc21ec8L,0x98f9868a0fcf8139L,0x737d2cd648250b49L, + 0xcc61c94724b3428fL }, + { 0x0c2b407880dd9e76L,0xc43a8991383fbe08L,0x5f7d2d65779be5d2L, + 0x78719a54eb3b4ab5L } }, + /* 11 << 0 */ + { { 0xea7d260a6245e404L,0x9de407956e7fdfe0L,0x1ff3a4158dac1ab5L, + 0x3e7090f1649c9073L }, + { 0x1a7685612b944e88L,0x250f939ee57f61c8L,0x0c0daa891ead643dL, + 0x68930023e125b88eL } }, + /* 12 << 0 */ + { { 0x04b71aa7d2697768L,0xabdedef5ca345a33L,0x2409d29dee37385eL, + 0x4ee1df77cb83e156L }, + { 0x0cac12d91cbb5b43L,0x170ed2f6ca895637L,0x28228cfa8ade6d66L, + 0x7ff57c9553238acaL } }, + /* 13 << 0 */ + { { 0xccc425634b2ed709L,0x0e356769856fd30dL,0xbcbcd43f559e9811L, + 0x738477ac5395b759L }, + { 0x35752b90c00ee17fL,0x68748390742ed2e3L,0x7cd06422bd1f5bc1L, + 0xfbc08769c9e7b797L } }, + /* 14 << 0 */ + { { 0xa242a35bb0cf664aL,0x126e48f77f9707e3L,0x1717bf54c6832660L, + 0xfaae7332fd12c72eL }, + { 0x27b52db7995d586bL,0xbe29569e832237c2L,0xe8e4193e2a65e7dbL, + 0x152706dc2eaa1bbbL } }, + /* 15 << 0 */ + { { 0x72bcd8b7bc60055bL,0x03cc23ee56e27e4bL,0xee337424e4819370L, + 0xe2aa0e430ad3da09L }, + { 0x40b8524f6383c45dL,0xd766355442a41b25L,0x64efa6de778a4797L, + 0x2042170a7079adf4L } }, + /* 16 << 0 */ + { { 0x808b0b650bc6fb80L,0x5882e0753ffe2e6bL,0xd5ef2f7c2c83f549L, + 0x54d63c809103b723L }, + { 0xf2f11bd652a23f9bL,0x3670c3194b0b6587L,0x55c4623bb1580e9eL, + 0x64edf7b201efe220L } }, + /* 17 << 0 */ + { { 0x97091dcbd53c5c9dL,0xf17624b6ac0a177bL,0xb0f139752cfe2dffL, + 0xc1a35c0a6c7a574eL }, + { 0x227d314693e79987L,0x0575bf30e89cb80eL,0x2f4e247f0d1883bbL, + 0xebd512263274c3d0L } }, + /* 18 << 0 */ + { { 0x5f3e51c856ada97aL,0x4afc964d8f8b403eL,0xa6f247ab412e2979L, + 0x675abd1b6f80ebdaL }, + { 0x66a2bd725e485a1dL,0x4b2a5caf8f4f0b3cL,0x2626927f1b847bbaL, + 0x6c6fc7d90502394dL } }, + /* 19 << 0 */ + { { 0xfea912baa5659ae8L,0x68363aba25e1a16eL,0xb8842277752c41acL, + 0xfe545c282897c3fcL }, + { 0x2d36e9e7dc4c696bL,0x5806244afba977c5L,0x85665e9be39508c1L, + 0xf720ee256d12597bL } }, + /* 20 << 0 */ + { { 0x8a979129d2337a31L,0x5916868f0f862bdcL,0x048099d95dd283baL, + 0xe2d1eeb6fe5bfb4eL }, + { 0x82ef1c417884005dL,0xa2d4ec17ffffcbaeL,0x9161c53f8aa95e66L, + 0x5ee104e1c5fee0d0L } }, + /* 21 << 0 */ + { { 0x562e4cecc135b208L,0x74e1b2654783f47dL,0x6d2a506c5a3f3b30L, + 0xecead9f4c16762fcL }, + { 0xf29dd4b2e286e5b9L,0x1b0fadc083bb3c61L,0x7a75023e7fac29a4L, + 0xc086d5f1c9477fa3L } }, + /* 22 << 0 */ + { { 0x0fc611352f6f3076L,0xc99ffa23e3912a9aL,0x6a0b0685d2f8ba3dL, + 0xfdc777e8e93358a4L }, + { 0x94a787bb35415f04L,0x640c2d6a4d23fea4L,0x9de917da153a35b5L, + 0x793e8d075d5cd074L } }, + /* 23 << 0 */ + { { 0xf4f876532de45068L,0x37c7a7e89e2e1f6eL,0xd0825fa2a3584069L, + 0xaf2cea7c1727bf42L }, + { 0x0360a4fb9e4785a9L,0xe5fda49c27299f4aL,0x48068e1371ac2f71L, + 0x83d0687b9077666fL } }, + /* 24 << 0 */ + { { 0x6d3883b215d02819L,0x6d0d755040dd9a35L,0x61d7cbf91d2b469fL, + 0xf97b232f2efc3115L }, + { 0xa551d750b24bcbc7L,0x11ea494988a1e356L,0x7669f03193cb7501L, + 0x595dc55eca737b8aL } }, + /* 25 << 0 */ + { { 0xa4a319acd837879fL,0x6fc1b49eed6b67b0L,0xe395993332f1f3afL, + 0x966742eb65432a2eL }, + { 0x4b8dc9feb4966228L,0x96cc631243f43950L,0x12068859c9b731eeL, + 0x7b948dc356f79968L } }, + /* 26 << 0 */ + { { 0x61e4ad32ed1f8008L,0xe6c9267ad8b17538L,0x1ac7c5eb857ff6fbL, + 0x994baaa855f2fb10L }, + { 0x84cf14e11d248018L,0x5a39898b628ac508L,0x14fde97b5fa944f5L, + 0xed178030d12e5ac7L } }, + /* 27 << 0 */ + { { 0x042c2af497e2feb4L,0xd36a42d7aebf7313L,0x49d2c9eb084ffdd7L, + 0x9f8aa54b2ef7c76aL }, + { 0x9200b7ba09895e70L,0x3bd0c66fddb7fb58L,0x2d97d10878eb4cbbL, + 0x2d431068d84bde31L } }, + /* 28 << 0 */ + { { 0x4b523eb7172ccd1fL,0x7323cb2830a6a892L,0x97082ec0cfe153ebL, + 0xe97f6b6af2aadb97L }, + { 0x1d3d393ed1a83da1L,0xa6a7f9c7804b2a68L,0x4a688b482d0cb71eL, + 0xa9b4cc5f40585278L } }, + /* 29 << 0 */ + { { 0x5e5db46acb66e132L,0xf1be963a0d925880L,0x944a70270317b9e2L, + 0xe266f95948603d48L }, + { 0x98db66735c208899L,0x90472447a2fb18a3L,0x8a966939777c619fL, + 0x3798142a2a3be21bL } }, + /* 30 << 0 */ + { { 0xb4241cb13298b343L,0xa3a14e49b44f65a1L,0xc5f4d6cd3ac77acdL, + 0xd0288cb552b6fc3cL }, + { 0xd5cc8c2f1c040abcL,0xb675511e06bf9b4aL,0xd667da379b3aa441L, + 0x460d45ce51601f72L } }, + /* 31 << 0 */ + { { 0xe2f73c696755ff89L,0xdd3cf7e7473017e6L,0x8ef5689d3cf7600dL, + 0x948dc4f8b1fc87b4L }, + { 0xd9e9fe814ea53299L,0x2d921ca298eb6028L,0xfaecedfd0c9803fcL, + 0xf38ae8914d7b4745L } }, + /* 32 << 0 */ + { { 0xd8c5fccfc5e3a3d8L,0xbefd904c4079dfbfL,0xbc6d6a58fead0197L, + 0x39227077695532a4L }, + { 0x09e23e6ddbef42f5L,0x7e449b64480a9908L,0x7b969c1aad9a2e40L, + 0x6231d7929591c2a4L } }, + /* 33 << 0 */ + { { 0x871514560f664534L,0x85ceae7c4b68f103L,0xac09c4ae65578ab9L, + 0x33ec6868f044b10cL }, + { 0x6ac4832b3a8ec1f1L,0x5509d1285847d5efL,0xf909604f763f1574L, + 0xb16c4303c32f63c4L } }, + /* 34 << 0 */ + { { 0xb6ab20147ca23cd3L,0xcaa7a5c6a391849dL,0x5b0673a375678d94L, + 0xc982ddd4dd303e64L }, + { 0xfd7b000b5db6f971L,0xbba2cb1f6f876f92L,0xc77332a33c569426L, + 0xa159100c570d74f8L } }, + /* 35 << 0 */ + { { 0xfd16847fdec67ef5L,0x742ee464233e76b7L,0x0b8e4134efc2b4c8L, + 0xca640b8642a3e521L }, + { 0x653a01908ceb6aa9L,0x313c300c547852d5L,0x24e4ab126b237af7L, + 0x2ba901628bb47af8L } }, + /* 36 << 0 */ + { { 0x3d5e58d6a8219bb7L,0xc691d0bd1b06c57fL,0x0ae4cb10d257576eL, + 0x3569656cd54a3dc3L }, + { 0xe5ebaebd94cda03aL,0x934e82d3162bfe13L,0x450ac0bae251a0c6L, + 0x480b9e11dd6da526L } }, + /* 37 << 0 */ + { { 0x00467bc58cce08b5L,0xb636458c7f178d55L,0xc5748baea677d806L, + 0x2763a387dfa394ebL }, + { 0xa12b448a7d3cebb6L,0xe7adda3e6f20d850L,0xf63ebce51558462cL, + 0x58b36143620088a8L } }, + /* 38 << 0 */ + { { 0x8a2cc3ca4d63c0eeL,0x512331170fe948ceL,0x7463fd85222ef33bL, + 0xadf0c7dc7c603d6cL }, + { 0x0ec32d3bfe7765e5L,0xccaab359bf380409L,0xbdaa84d68e59319cL, + 0xd9a4c2809c80c34dL } }, + /* 39 << 0 */ + { { 0xa9d89488a059c142L,0x6f5ae714ff0b9346L,0x068f237d16fb3664L, + 0x5853e4c4363186acL }, + { 0xe2d87d2363c52f98L,0x2ec4a76681828876L,0x47b864fae14e7b1cL, + 0x0c0bc0e569192408L } }, + /* 40 << 0 */ + { { 0xe4d7681db82e9f3eL,0x83200f0bdf25e13cL,0x8909984c66f27280L, + 0x462d7b0075f73227L }, + { 0xd90ba188f2651798L,0x74c6e18c36ab1c34L,0xab256ea35ef54359L, + 0x03466612d1aa702fL } }, + /* 41 << 0 */ + { { 0x624d60492ed22e91L,0x6fdfe0b56f072822L,0xeeca111539ce2271L, + 0x98100a4fdb01614fL }, + { 0xb6b0daa2a35c628fL,0xb6f94d2ec87e9a47L,0xc67732591d57d9ceL, + 0xf70bfeec03884a7bL } }, + /* 42 << 0 */ + { { 0x5fb35ccfed2bad01L,0xa155cbe31da6a5c7L,0xc2e2594c30a92f8fL, + 0x649c89ce5bfafe43L }, + { 0xd158667de9ff257aL,0x9b359611f32c50aeL,0x4b00b20b906014cfL, + 0xf3a8cfe389bc7d3dL } }, + /* 43 << 0 */ + { { 0x4ff23ffd248a7d06L,0x80c5bfb4878873faL,0xb7d9ad9005745981L, + 0x179c85db3db01994L }, + { 0xba41b06261a6966cL,0x4d82d052eadce5a8L,0x9e91cd3ba5e6a318L, + 0x47795f4f95b2dda0L } }, + /* 44 << 0 */ + { { 0xecfd7c1fd55a897cL,0x009194abb29110fbL,0x5f0e2046e381d3b0L, + 0x5f3425f6a98dd291L }, + { 0xbfa06687730d50daL,0x0423446c4b083b7fL,0x397a247dd69d3417L, + 0xeb629f90387ba42aL } }, + /* 45 << 0 */ + { { 0x1ee426ccd5cd79bfL,0x0032940b946c6e18L,0x1b1e8ae057477f58L, + 0xe94f7d346d823278L }, + { 0xc747cb96782ba21aL,0xc5254469f72b33a5L,0x772ef6dec7f80c81L, + 0xd73acbfe2cd9e6b5L } }, + /* 46 << 0 */ + { { 0x4075b5b149ee90d9L,0x785c339aa06e9ebaL,0xa1030d5babf825e0L, + 0xcec684c3a42931dcL }, + { 0x42ab62c9c1586e63L,0x45431d665ab43f2bL,0x57c8b2c055f7835dL, + 0x033da338c1b7f865L } }, + /* 47 << 0 */ + { { 0x283c7513caa76097L,0x0a624fa936c83906L,0x6b20afec715af2c7L, + 0x4b969974eba78bfdL }, + { 0x220755ccd921d60eL,0x9b944e107baeca13L,0x04819d515ded93d4L, + 0x9bbff86e6dddfd27L } }, + /* 48 << 0 */ + { { 0x6b34413077adc612L,0xa7496529bbd803a0L,0x1a1baaa76d8805bdL, + 0xc8403902470343adL }, + { 0x39f59f66175adff1L,0x0b26d7fbb7d8c5b7L,0xa875f5ce529d75e3L, + 0x85efc7e941325cc2L } }, + /* 49 << 0 */ + { { 0x21950b421ff6acd3L,0xffe7048453dc6909L,0xff4cd0b228766127L, + 0xabdbe6084fb7db2bL }, + { 0x837c92285e1109e8L,0x26147d27f4645b5aL,0x4d78f592f7818ed8L, + 0xd394077ef247fa36L } }, + /* 50 << 0 */ + { { 0x0fb9c2d0488c171aL,0xa78bfbaa13685278L,0xedfbe268d5b1fa6aL, + 0x0dceb8db2b7eaba7L }, + { 0xbf9e80899ae2b710L,0xefde7ae6a4449c96L,0x43b7716bcc143a46L, + 0xd7d34194c3628c13L } }, + /* 51 << 0 */ + { { 0x508cec1c3b3f64c9L,0xe20bc0ba1e5edf3fL,0xda1deb852f4318d4L, + 0xd20ebe0d5c3fa443L }, + { 0x370b4ea773241ea3L,0x61f1511c5e1a5f65L,0x99a5e23d82681c62L, + 0xd731e383a2f54c2dL } }, + /* 52 << 0 */ + { { 0x2692f36e83445904L,0x2e0ec469af45f9c0L,0x905a3201c67528b7L, + 0x88f77f34d0e5e542L }, + { 0xf67a8d295864687cL,0x23b92eae22df3562L,0x5c27014b9bbec39eL, + 0x7ef2f2269c0f0f8dL } }, + /* 53 << 0 */ + { { 0x97359638546c4d8dL,0x5f9c3fc492f24679L,0x912e8beda8c8acd9L, + 0xec3a318d306634b0L }, + { 0x80167f41c31cb264L,0x3db82f6f522113f2L,0xb155bcd2dcafe197L, + 0xfba1da5943465283L } }, + /* 54 << 0 */ + { { 0xa0425b8eb212cf53L,0x4f2e512ef8557c5fL,0xc1286ff925c4d56cL, + 0xbb8a0feaee26c851L }, + { 0xc28f70d2e7d6107eL,0x7ee0c444e76265aaL,0x3df277a41d1936b1L, + 0x1a556e3fea9595ebL } }, + /* 55 << 0 */ + { { 0x258bbbf9e7305683L,0x31eea5bf07ef5be6L,0x0deb0e4a46c814c1L, + 0x5cee8449a7b730ddL }, + { 0xeab495c5a0182bdeL,0xee759f879e27a6b4L,0xc2cf6a6880e518caL, + 0x25e8013ff14cf3f4L } }, + /* 56 << 0 */ + { { 0x8fc441407e8d7a14L,0xbb1ff3ca9556f36aL,0x6a84438514600044L, + 0xba3f0c4a7451ae63L }, + { 0xdfcac25b1f9af32aL,0x01e0db86b1f2214bL,0x4e9a5bc2a4b596acL, + 0x83927681026c2c08L } }, + /* 57 << 0 */ + { { 0x3ec832e77acaca28L,0x1bfeea57c7385b29L,0x068212e3fd1eaf38L, + 0xc13298306acf8cccL }, + { 0xb909f2db2aac9e59L,0x5748060db661782aL,0xc5ab2632c79b7a01L, + 0xda44c6c600017626L } }, + /* 58 << 0 */ + { { 0xf26c00e8a7ea82f0L,0x99cac80de4299aafL,0xd66fe3b67ed78be1L, + 0x305f725f648d02cdL }, + { 0x33ed1bc4623fb21bL,0xfa70533e7a6319adL,0x17ab562dbe5ffb3eL, + 0x0637499456674741L } }, + /* 59 << 0 */ + { { 0x69d44ed65c46aa8eL,0x2100d5d3a8d063d1L,0xcb9727eaa2d17c36L, + 0x4c2bab1b8add53b7L }, + { 0xa084e90c15426704L,0x778afcd3a837ebeaL,0x6651f7017ce477f8L, + 0xa062499846fb7a8bL } }, + /* 60 << 0 */ + { { 0xdc1e6828ed8a6e19L,0x33fc23364189d9c7L,0x026f8fe2671c39bcL, + 0xd40c4ccdbc6f9915L }, + { 0xafa135bbf80e75caL,0x12c651a022adff2cL,0xc40a04bd4f51ad96L, + 0x04820109bbe4e832L } }, + /* 61 << 0 */ + { { 0x3667eb1a7f4c04ccL,0x59556621a9404f84L,0x71cdf6537eceb50aL, + 0x994a44a69b8335faL }, + { 0xd7faf819dbeb9b69L,0x473c5680eed4350dL,0xb6658466da44bba2L, + 0x0d1bc780872bdbf3L } }, + /* 62 << 0 */ + { { 0xe535f175a1962f91L,0x6ed7e061ed58f5a7L,0x177aa4c02089a233L, + 0x0dbcb03ae539b413L }, + { 0xe3dc424ebb32e38eL,0x6472e5ef6806701eL,0xdd47ff98814be9eeL, + 0x6b60cfff35ace009L } }, + /* 63 << 0 */ + { { 0xb8d3d9319ff91fe5L,0x039c4800f0518eedL,0x95c376329182cb26L, + 0x0763a43482fc568dL }, + { 0x707c04d5383e76baL,0xac98b930824e8197L,0x92bf7c8f91230de0L, + 0x90876a0140959b70L } }, + /* 64 << 0 */ + { { 0xdb6d96f305968b80L,0x380a0913089f73b9L,0x7da70b83c2c61e01L, + 0x95fb8394569b38c7L }, + { 0x9a3c651280edfe2fL,0x8f726bb98faeaf82L,0x8010a4a078424bf8L, + 0x296720440e844970L } }, + /* 0 << 7 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 7 */ + { { 0x63c5cb817a2ad62aL,0x7ef2b6b9ac62ff54L,0x3749bba4b3ad9db5L, + 0xad311f2c46d5a617L }, + { 0xb77a8087c2ff3b6dL,0xb46feaf3367834ffL,0xf8aa266d75d6b138L, + 0xfa38d320ec008188L } }, + /* 2 << 7 */ + { { 0x486d8ffa696946fcL,0x50fbc6d8b9cba56dL,0x7e3d423e90f35a15L, + 0x7c3da195c0dd962cL }, + { 0xe673fdb03cfd5d8bL,0x0704b7c2889dfca5L,0xf6ce581ff52305aaL, + 0x399d49eb914d5e53L } }, + /* 3 << 7 */ + { { 0x380a496d6ec293cdL,0x733dbda78e7051f5L,0x037e388db849140aL, + 0xee4b32b05946dbf6L }, + { 0xb1c4fda9cae368d1L,0x5001a7b0fdb0b2f3L,0x6df593742e3ac46eL, + 0x4af675f239b3e656L } }, + /* 4 << 7 */ + { { 0x44e3811039949296L,0x5b63827b361db1b5L,0x3e5323ed206eaff5L, + 0x942370d2c21f4290L }, + { 0xf2caaf2ee0d985a1L,0x192cc64b7239846dL,0x7c0b8f47ae6312f8L, + 0x7dc61f9196620108L } }, + /* 5 << 7 */ + { { 0xb830fb5bc2da7de9L,0xd0e643df0ff8d3beL,0x31ee77ba188a9641L, + 0x4e8aa3aabcf6d502L }, + { 0xf9fb65329a49110fL,0xd18317f62dd6b220L,0x7e3ced4152c3ea5aL, + 0x0d296a147d579c4aL } }, + /* 6 << 7 */ + { { 0x35d6a53eed4c3717L,0x9f8240cf3d0ed2a3L,0x8c0d4d05e5543aa5L, + 0x45d5bbfbdd33b4b4L }, + { 0xfa04cc73137fd28eL,0x862ac6efc73b3ffdL,0x403ff9f531f51ef2L, + 0x34d5e0fcbc73f5a2L } }, + /* 7 << 7 */ + { { 0xf252682008913f4fL,0xea20ed61eac93d95L,0x51ed38b46ca6b26cL, + 0x8662dcbcea4327b0L }, + { 0x6daf295c725d2aaaL,0xbad2752f8e52dcdaL,0x2210e7210b17daccL, + 0xa37f7912d51e8232L } }, + /* 8 << 7 */ + { { 0x4f7081e144cc3addL,0xd5ffa1d687be82cfL,0x89890b6c0edd6472L, + 0xada26e1a3ed17863L }, + { 0x276f271563483caaL,0xe6924cd92f6077fdL,0x05a7fe980a466e3cL, + 0xf1c794b0b1902d1fL } }, + /* 9 << 7 */ + { { 0xe521368882a8042cL,0xd931cfafcd278298L,0x069a0ae0f597a740L, + 0x0adbb3f3eb59107cL }, + { 0x983e951e5eaa8eb8L,0xe663a8b511b48e78L,0x1631cc0d8a03f2c5L, + 0x7577c11e11e271e2L } }, + /* 10 << 7 */ + { { 0x33b2385c08369a90L,0x2990c59b190eb4f8L,0x819a6145c68eac80L, + 0x7a786d622ec4a014L }, + { 0x33faadbe20ac3a8dL,0x31a217815aba2d30L,0x209d2742dba4f565L, + 0xdb2ce9e355aa0fbbL } }, + /* 11 << 7 */ + { { 0x8cef334b168984dfL,0xe81dce1733879638L,0xf6e6949c263720f0L, + 0x5c56feaff593cbecL }, + { 0x8bff5601fde58c84L,0x74e241172eccb314L,0xbcf01b614c9a8a78L, + 0xa233e35e544c9868L } }, + /* 12 << 7 */ + { { 0xb3156bf38bd7aff1L,0x1b5ee4cb1d81b146L,0x7ba1ac41d628a915L, + 0x8f3a8f9cfd89699eL }, + { 0x7329b9c9a0748be7L,0x1d391c95a92e621fL,0xe51e6b214d10a837L, + 0xd255f53a4947b435L } }, + /* 13 << 7 */ + { { 0x07669e04f1788ee3L,0xc14f27afa86938a2L,0x8b47a334e93a01c0L, + 0xff627438d9366808L }, + { 0x7a0985d8ca2a5965L,0x3d9a5542d6e9b9b3L,0xc23eb80b4cf972e8L, + 0x5c1c33bb4fdf72fdL } }, + /* 14 << 7 */ + { { 0x0c4a58d474a86108L,0xf8048a8fee4c5d90L,0xe3c7c924e86d4c80L, + 0x28c889de056a1e60L }, + { 0x57e2662eb214a040L,0xe8c48e9837e10347L,0x8774286280ac748aL, + 0xf1c24022186b06f2L } }, + /* 15 << 7 */ + { { 0xac2dd4c35f74040aL,0x409aeb71fceac957L,0x4fbad78255c4ec23L, + 0xb359ed618a7b76ecL }, + { 0x12744926ed6f4a60L,0xe21e8d7f4b912de3L,0xe2575a59fc705a59L, + 0x72f1d4deed2dbc0eL } }, + /* 16 << 7 */ + { { 0x3d2b24b9eb7926b8L,0xbff88cb3cdbe5509L,0xd0f399afe4dd640bL, + 0x3c5fe1302f76ed45L }, + { 0x6f3562f43764fb3dL,0x7b5af3183151b62dL,0xd5bd0bc7d79ce5f3L, + 0xfdaf6b20ec66890fL } }, + /* 17 << 7 */ + { { 0x735c67ec6063540cL,0x50b259c2e5f9cb8fL,0xb8734f9a3f99c6abL, + 0xf8cc13d5a3a7bc85L }, + { 0x80c1b305c5217659L,0xfe5364d44ec12a54L,0xbd87045e681345feL, + 0x7f8efeb1582f897fL } }, + /* 18 << 7 */ + { { 0xe8cbf1e5d5923359L,0xdb0cea9d539b9fb0L,0x0c5b34cf49859b98L, + 0x5e583c56a4403cc6L }, + { 0x11fc1a2dd48185b7L,0xc93fbc7e6e521787L,0x47e7a05805105b8bL, + 0x7b4d4d58db8260c8L } }, + /* 19 << 7 */ + { { 0xe33930b046eb842aL,0x8e844a9a7bdae56dL,0x34ef3a9e13f7fdfcL, + 0xb3768f82636ca176L }, + { 0x2821f4e04e09e61cL,0x414dc3a1a0c7cddcL,0xd537943754945fcdL, + 0x151b6eefb3555ff1L } }, + /* 20 << 7 */ + { { 0xb31bd6136339c083L,0x39ff8155dfb64701L,0x7c3388d2e29604abL, + 0x1e19084ba6b10442L }, + { 0x17cf54c0eccd47efL,0x896933854a5dfb30L,0x69d023fb47daf9f6L, + 0x9222840b7d91d959L } }, + /* 21 << 7 */ + { { 0x439108f5803bac62L,0x0b7dd91d379bd45fL,0xd651e827ca63c581L, + 0x5c5d75f6509c104fL }, + { 0x7d5fc7381f2dc308L,0x20faa7bfd98454beL,0x95374beea517b031L, + 0xf036b9b1642692acL } }, + /* 22 << 7 */ + { { 0xc510610939842194L,0xb7e2353e49d05295L,0xfc8c1d5cefb42ee0L, + 0xe04884eb08ce811cL }, + { 0xf1f75d817419f40eL,0x5b0ac162a995c241L,0x120921bbc4c55646L, + 0x713520c28d33cf97L } }, + /* 23 << 7 */ + { { 0xb4a65a5ce98c5100L,0x6cec871d2ddd0f5aL,0x251f0b7f9ba2e78bL, + 0x224a8434ce3a2a5fL }, + { 0x26827f6125f5c46fL,0x6a22bedc48545ec0L,0x25ae5fa0b1bb5cdcL, + 0xd693682ffcb9b98fL } }, + /* 24 << 7 */ + { { 0x32027fe891e5d7d3L,0xf14b7d1773a07678L,0xf88497b3c0dfdd61L, + 0xf7c2eec02a8c4f48L }, + { 0xaa5573f43756e621L,0xc013a2401825b948L,0x1c03b34563878572L, + 0xa0472bea653a4184L } }, + /* 25 << 7 */ + { { 0xf4222e270ac69a80L,0x34096d25f51e54f6L,0x00a648cb8fffa591L, + 0x4e87acdc69b6527fL }, + { 0x0575e037e285ccb4L,0x188089e450ddcf52L,0xaa96c9a8870ff719L, + 0x74a56cd81fc7e369L } }, + /* 26 << 7 */ + { { 0x41d04ee21726931aL,0x0bbbb2c83660ecfdL,0xa6ef6de524818e18L, + 0xe421cc51e7d57887L }, + { 0xf127d208bea87be6L,0x16a475d3b1cdd682L,0x9db1b684439b63f7L, + 0x5359b3dbf0f113b6L } }, + /* 27 << 7 */ + { { 0xdfccf1de8bf06e31L,0x1fdf8f44dd383901L,0x10775cad5017e7d2L, + 0xdfc3a59758d11eefL }, + { 0x6ec9c8a0b1ecff10L,0xee6ed6cc28400549L,0xb5ad7bae1b4f8d73L, + 0x61b4f11de00aaab9L } }, + /* 28 << 7 */ + { { 0x7b32d69bd4eff2d7L,0x88ae67714288b60fL,0x159461b437a1e723L, + 0x1f3d4789570aae8cL }, + { 0x869118c07f9871daL,0x35fbda78f635e278L,0x738f3641e1541dacL, + 0x6794b13ac0dae45fL } }, + /* 29 << 7 */ + { { 0x065064ac09cc0917L,0x27c53729c68540fdL,0x0d2d4c8eef227671L, + 0xd23a9f80a1785a04L }, + { 0x98c5952852650359L,0xfa09ad0174a1acadL,0x082d5a290b55bf5cL, + 0xa40f1c67419b8084L } }, + /* 30 << 7 */ + { { 0x3a5c752edcc18770L,0x4baf1f2f8825c3a5L,0xebd63f7421b153edL, + 0xa2383e47b2f64723L }, + { 0xe7bf620a2646d19aL,0x56cb44ec03c83ffdL,0xaf7267c94f6be9f1L, + 0x8b2dfd7bc06bb5e9L } }, + /* 31 << 7 */ + { { 0xb87072f2a672c5c7L,0xeacb11c80d53c5e2L,0x22dac29dff435932L, + 0x37bdb99d4408693cL }, + { 0xf6e62fb62899c20fL,0x3535d512447ece24L,0xfbdc6b88ff577ce3L, + 0x726693bd190575f2L } }, + /* 32 << 7 */ + { { 0x6772b0e5ab4b35a2L,0x1d8b6001f5eeaacfL,0x728f7ce4795b9580L, + 0x4a20ed2a41fb81daL }, + { 0x9f685cd44fec01e6L,0x3ed7ddcca7ff50adL,0x460fd2640c2d97fdL, + 0x3a241426eb82f4f9L } }, + /* 33 << 7 */ + { { 0x17d1df2c6a8ea820L,0xb2b50d3bf22cc254L,0x03856cbab7291426L, + 0x87fd26ae04f5ee39L }, + { 0x9cb696cc02bee4baL,0x5312180406820fd6L,0xa5dfc2690212e985L, + 0x666f7ffa160f9a09L } }, + /* 34 << 7 */ + { { 0xc503cd33bccd9617L,0x365dede4ba7730a3L,0x798c63555ddb0786L, + 0xa6c3200efc9cd3bcL }, + { 0x060ffb2ce5e35efdL,0x99a4e25b5555a1c1L,0x11d95375f70b3751L, + 0x0a57354a160e1bf6L } }, + /* 35 << 7 */ + { { 0xecb3ae4bf8e4b065L,0x07a834c42e53022bL,0x1cd300b38692ed96L, + 0x16a6f79261ee14ecL }, + { 0x8f1063c66a8649edL,0xfbcdfcfe869f3e14L,0x2cfb97c100a7b3ecL, + 0xcea49b3c7130c2f1L } }, + /* 36 << 7 */ + { { 0x462d044fe9d96488L,0x4b53d52e8182a0c1L,0x84b6ddd30391e9e9L, + 0x80ab7b48b1741a09L }, + { 0xec0e15d427d3317fL,0x8dfc1ddb1a64671eL,0x93cc5d5fd49c5b92L, + 0xc995d53d3674a331L } }, + /* 37 << 7 */ + { { 0x302e41ec090090aeL,0x2278a0ccedb06830L,0x1d025932fbc99690L, + 0x0c32fbd2b80d68daL }, + { 0xd79146daf341a6c1L,0xae0ba1391bef68a0L,0xc6b8a5638d774b3aL, + 0x1cf307bd880ba4d7L } }, + /* 38 << 7 */ + { { 0xc033bdc719803511L,0xa9f97b3b8888c3beL,0x3d68aebc85c6d05eL, + 0xc3b88a9d193919ebL }, + { 0x2d300748c48b0ee3L,0x7506bc7c07a746c1L,0xfc48437c6e6d57f3L, + 0x5bd71587cfeaa91aL } }, + /* 39 << 7 */ + { { 0xa4ed0408c1bc5225L,0xd0b946db2719226dL,0x109ecd62758d2d43L, + 0x75c8485a2751759bL }, + { 0xb0b75f499ce4177aL,0x4fa61a1e79c10c3dL,0xc062d300a167fcd7L, + 0x4df3874c750f0fa8L } }, + /* 40 << 7 */ + { { 0x29ae2cf983dfedc9L,0xf84371348d87631aL,0xaf5717117429c8d2L, + 0x18d15867146d9272L }, + { 0x83053ecf69769bb7L,0xc55eb856c479ab82L,0x5ef7791c21b0f4b2L, + 0xaa5956ba3d491525L } }, + /* 41 << 7 */ + { { 0x407a96c29fe20ebaL,0xf27168bbe52a5ad3L,0x43b60ab3bf1d9d89L, + 0xe45c51ef710e727aL }, + { 0xdfca5276099b4221L,0x8dc6407c2557a159L,0x0ead833591035895L, + 0x0a9db9579c55dc32L } }, + /* 42 << 7 */ + { { 0xe40736d3df61bc76L,0x13a619c03f778cdbL,0x6dd921a4c56ea28fL, + 0x76a524332fa647b4L }, + { 0x23591891ac5bdc5dL,0xff4a1a72bac7dc01L,0x9905e26162df8453L, + 0x3ac045dfe63b265fL } }, + /* 43 << 7 */ + { { 0x8a3f341bad53dba7L,0x8ec269cc837b625aL,0xd71a27823ae31189L, + 0x8fb4f9a355e96120L }, + { 0x804af823ff9875cfL,0x23224f575d442a9bL,0x1c4d3b9eecc62679L, + 0x91da22fba0e7ddb1L } }, + /* 44 << 7 */ + { { 0xa370324d6c04a661L,0x9710d3b65e376d17L,0xed8c98f03044e357L, + 0xc364ebbe6422701cL }, + { 0x347f5d517733d61cL,0xd55644b9cea826c3L,0x80c6e0ad55a25548L, + 0x0aa7641d844220a7L } }, + /* 45 << 7 */ + { { 0x1438ec8131810660L,0x9dfa6507de4b4043L,0x10b515d8cc3e0273L, + 0x1b6066dd28d8cfb2L }, + { 0xd3b045919c9efebdL,0x425d4bdfa21c1ff4L,0x5fe5af19d57607d3L, + 0xbbf773f754481084L } }, + /* 46 << 7 */ + { { 0x8435bd6994b03ed1L,0xd9ad1de3634cc546L,0x2cf423fc00e420caL, + 0xeed26d80a03096ddL }, + { 0xd7f60be7a4db09d2L,0xf47f569d960622f7L,0xe5925fd77296c729L, + 0xeff2db2626ca2715L } }, + /* 47 << 7 */ + { { 0xa6fcd014b913e759L,0x53da47868ff4de93L,0x14616d79c32068e1L, + 0xb187d664ccdf352eL }, + { 0xf7afb6501dc90b59L,0x8170e9437daa1b26L,0xc8e3bdd8700c0a84L, + 0x6e8d345f6482bdfaL } }, + /* 48 << 7 */ + { { 0x84cfbfa1c5c5ea50L,0xd3baf14c67960681L,0x263984030dd50942L, + 0xe4b7839c4716a663L }, + { 0xd5f1f794e7de6dc0L,0x5cd0f4d4622aa7ceL,0x5295f3f159acfeecL, + 0x8d933552953e0607L } }, + /* 49 << 7 */ + { { 0xc7db8ec5776c5722L,0xdc467e622b5f290cL,0xd4297e704ff425a9L, + 0x4be924c10cf7bb72L }, + { 0x0d5dc5aea1892131L,0x8bf8a8e3a705c992L,0x73a0b0647a305ac5L, + 0x00c9ca4e9a8c77a8L } }, + /* 50 << 7 */ + { { 0x5dfee80f83774bddL,0x6313160285734485L,0xa1b524ae914a69a9L, + 0xebc2ffafd4e300d7L }, + { 0x52c93db77cfa46a5L,0x71e6161f21653b50L,0x3574fc57a4bc580aL, + 0xc09015dde1bc1253L } }, + /* 51 << 7 */ + { { 0x4b7b47b2d174d7aaL,0x4072d8e8f3a15d04L,0xeeb7d47fd6fa07edL, + 0x6f2b9ff9edbdafb1L }, + { 0x18c516153760fe8aL,0x7a96e6bff06c6c13L,0x4d7a04100ea2d071L, + 0xa1914e9b0be2a5ceL } }, + /* 52 << 7 */ + { { 0x5726e357d8a3c5cfL,0x1197ecc32abb2b13L,0x6c0d7f7f31ae88ddL, + 0x15b20d1afdbb3efeL }, + { 0xcd06aa2670584039L,0x2277c969a7dc9747L,0xbca695877855d815L, + 0x899ea2385188b32aL } }, + /* 53 << 7 */ + { { 0x37d9228b760c1c9dL,0xc7efbb119b5c18daL,0x7f0d1bc819f6dbc5L, + 0x4875384b07e6905bL }, + { 0xc7c50baa3ba8cd86L,0xb0ce40fbc2905de0L,0x708406737a231952L, + 0xa912a262cf43de26L } }, + /* 54 << 7 */ + { { 0x9c38ddcceb5b76c1L,0x746f528526fc0ab4L,0x52a63a50d62c269fL, + 0x60049c5599458621L }, + { 0xe7f48f823c2f7c9eL,0x6bd99043917d5cf3L,0xeb1317a88701f469L, + 0xbd3fe2ed9a449fe0L } }, + /* 55 << 7 */ + { { 0x421e79ca12ef3d36L,0x9ee3c36c3e7ea5deL,0xe48198b5cdff36f7L, + 0xaff4f967c6b82228L }, + { 0x15e19dd0c47adb7eL,0x45699b23032e7dfaL,0x40680c8b1fae026aL, + 0x5a347a48550dbf4dL } }, + /* 56 << 7 */ + { { 0xe652533b3cef0d7dL,0xd94f7b182bbb4381L,0x838752be0e80f500L, + 0x8e6e24889e9c9bfbL }, + { 0xc975169716caca6aL,0x866c49d838531ad9L,0xc917e2397151ade1L, + 0x2d016ec16037c407L } }, + /* 57 << 7 */ + { { 0xa407ccc900eac3f9L,0x835f6280e2ed4748L,0xcc54c3471cc98e0dL, + 0x0e969937dcb572ebL }, + { 0x1b16c8e88f30c9cbL,0xa606ae75373c4661L,0x47aa689b35502cabL, + 0xf89014ae4d9bb64fL } }, + /* 58 << 7 */ + { { 0x202f6a9c31c71f7bL,0x01f95aa3296ffe5cL,0x5fc0601453cec3a3L, + 0xeb9912375f498a45L }, + { 0xae9a935e5d91ba87L,0xc6ac62810b564a19L,0x8a8fe81c3bd44e69L, + 0x7c8b467f9dd11d45L } }, + /* 59 << 7 */ + { { 0xf772251fea5b8e69L,0xaeecb3bdc5b75fbcL,0x1aca3331887ff0e5L, + 0xbe5d49ff19f0a131L }, + { 0x582c13aae5c8646fL,0xdbaa12e820e19980L,0x8f40f31af7abbd94L, + 0x1f13f5a81dfc7663L } }, + /* 60 << 7 */ + { { 0x5d81f1eeaceb4fc0L,0x362560025e6f0f42L,0x4b67d6d7751370c8L, + 0x2608b69803e80589L }, + { 0xcfc0d2fc05268301L,0xa6943d3940309212L,0x192a90c21fd0e1c2L, + 0xb209f11337f1dc76L } }, + /* 61 << 7 */ + { { 0xefcc5e0697bf1298L,0xcbdb6730219d639eL,0xd009c116b81e8c6fL, + 0xa3ffdde31a7ce2e5L }, + { 0xc53fbaaaa914d3baL,0x836d500f88df85eeL,0xd98dc71b66ee0751L, + 0x5a3d7005714516fdL } }, + /* 62 << 7 */ + { { 0x21d3634d39eedbbaL,0x35cd2e680455a46dL,0xc8cafe65f9d7eb0cL, + 0xbda3ce9e00cefb3eL }, + { 0xddc17a602c9cf7a4L,0x01572ee47bcb8773L,0xa92b2b018c7548dfL, + 0x732fd309a84600e3L } }, + /* 63 << 7 */ + { { 0xe22109c716543a40L,0x9acafd36fede3c6cL,0xfb2068526824e614L, + 0x2a4544a9da25dca0L }, + { 0x2598526291d60b06L,0x281b7be928753545L,0xec667b1a90f13b27L, + 0x33a83aff940e2eb4L } }, + /* 64 << 7 */ + { { 0x80009862d5d721d5L,0x0c3357a35bd3a182L,0x27f3a83b7aa2cda4L, + 0xb58ae74ef6f83085L }, + { 0x2a911a812e6dad6bL,0xde286051f43d6c5bL,0x4bdccc41f996c4d8L, + 0xe7312ec00ae1e24eL } }, + /* 0 << 14 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 14 */ + { { 0xf8d112e76e6485b3L,0x4d3e24db771c52f8L,0x48e3ee41684a2f6dL, + 0x7161957d21d95551L }, + { 0x19631283cdb12a6cL,0xbf3fa8822e50e164L,0xf6254b633166cc73L, + 0x3aefa7aeaee8cc38L } }, + /* 2 << 14 */ + { { 0x79b0fe623b36f9fdL,0x26543b23fde19fc0L,0x136e64a0958482efL, + 0x23f637719b095825L }, + { 0x14cfd596b6a1142eL,0x5ea6aac6335aac0bL,0x86a0e8bdf3081dd5L, + 0x5fb89d79003dc12aL } }, + /* 3 << 14 */ + { { 0xf615c33af72e34d4L,0x0bd9ea40110eec35L,0x1c12bc5bc1dea34eL, + 0x686584c949ae4699L }, + { 0x13ad95d38c97b942L,0x4609561a4e5c7562L,0x9e94a4aef2737f89L, + 0xf57594c6371c78b6L } }, + /* 4 << 14 */ + { { 0x0f0165fce3779ee3L,0xe00e7f9dbd495d9eL,0x1fa4efa220284e7aL, + 0x4564bade47ac6219L }, + { 0x90e6312ac4708e8eL,0x4f5725fba71e9adfL,0xe95f55ae3d684b9fL, + 0x47f7ccb11e94b415L } }, + /* 5 << 14 */ + { { 0x7322851b8d946581L,0xf0d13133bdf4a012L,0xa3510f696584dae0L, + 0x03a7c1713c9f6c6dL }, + { 0x5be97f38e475381aL,0xca1ba42285823334L,0xf83cc5c70be17ddaL, + 0x158b14940b918c0fL } }, + /* 6 << 14 */ + { { 0xda3a77e5522e6b69L,0x69c908c3bbcd6c18L,0x1f1b9e48d924fd56L, + 0x37c64e36aa4bb3f7L }, + { 0x5a4fdbdfee478d7dL,0xba75c8bc0193f7a0L,0x84bc1e8456cd16dfL, + 0x1fb08f0846fad151L } }, + /* 7 << 14 */ + { { 0x8a7cabf9842e9f30L,0xa331d4bf5eab83afL,0xd272cfba017f2a6aL, + 0x27560abc83aba0e3L }, + { 0x94b833870e3a6b75L,0x25c6aea26b9f50f5L,0x803d691db5fdf6d0L, + 0x03b77509e6333514L } }, + /* 8 << 14 */ + { { 0x3617890361a341c1L,0x3604dc600cfd6142L,0x022295eb8533316cL, + 0x3dbde4ac44af2922L }, + { 0x898afc5d1c7eef69L,0x58896805d14f4fa1L,0x05002160203c21caL, + 0x6f0d1f3040ef730bL } }, + /* 9 << 14 */ + { { 0x8e8c44d4196224f8L,0x75a4ab95374d079dL,0x79085ecc7d48f123L, + 0x56f04d311bf65ad8L }, + { 0xe220bf1cbda602b2L,0x73ee1742f9612c69L,0x76008fc8084fd06bL, + 0x4000ef9ff11380d1L } }, + /* 10 << 14 */ + { { 0x48201b4b12cfe297L,0x3eee129c292f74e5L,0xe1fe114ec9e874e8L, + 0x899b055c92c5fc41L }, + { 0x4e477a643a39c8cfL,0x82f09efe78963cc9L,0x6fd3fd8fd333f863L, + 0x85132b2adc949c63L } }, + /* 11 << 14 */ + { { 0x7e06a3ab516eb17bL,0x73bec06fd2c7372bL,0xe4f74f55ba896da6L, + 0xbb4afef88e9eb40fL }, + { 0x2d75bec8e61d66b0L,0x02bda4b4ef29300bL,0x8bbaa8de026baa5aL, + 0xff54befda07f4440L } }, + /* 12 << 14 */ + { { 0xbd9b8b1dbe7a2af3L,0xec51caa94fb74a72L,0xb9937a4b63879697L, + 0x7c9a9d20ec2687d5L }, + { 0x1773e44f6ef5f014L,0x8abcf412e90c6900L,0x387bd0228142161eL, + 0x50393755fcb6ff2aL } }, + /* 13 << 14 */ + { { 0x9813fd56ed6def63L,0x53cf64827d53106cL,0x991a35bd431f7ac1L, + 0xf1e274dd63e65fafL }, + { 0xf63ffa3c44cc7880L,0x411a426b7c256981L,0xb698b9fd93a420e0L, + 0x89fdddc0ae53f8feL } }, + /* 14 << 14 */ + { { 0x766e072232398baaL,0x205fee425cfca031L,0xa49f53417a029cf2L, + 0xa88c68b84023890dL }, + { 0xbc2750417337aaa8L,0x9ed364ad0eb384f4L,0xe0816f8529aba92fL, + 0x2e9e194104e38a88L } }, + /* 15 << 14 */ + { { 0x57eef44a3dafd2d5L,0x35d1fae597ed98d8L,0x50628c092307f9b1L, + 0x09d84aaed6cba5c6L }, + { 0x67071bc788aaa691L,0x2dea57a9afe6cb03L,0xdfe11bb43d78ac01L, + 0x7286418c7fd7aa51L } }, + /* 16 << 14 */ + { { 0xfabf770977f7195aL,0x8ec86167adeb838fL,0xea1285a8bb4f012dL, + 0xd68835039a3eab3fL }, + { 0xee5d24f8309004c2L,0xa96e4b7613ffe95eL,0x0cdffe12bd223ea4L, + 0x8f5c2ee5b6739a53L } }, + /* 17 << 14 */ + { { 0x5cb4aaa5dd968198L,0xfa131c5272413a6cL,0x53d46a909536d903L, + 0xb270f0d348606d8eL }, + { 0x518c7564a053a3bcL,0x088254b71a86caefL,0xb3ba8cb40ab5efd0L, + 0x5c59900e4605945dL } }, + /* 18 << 14 */ + { { 0xecace1dda1887395L,0x40960f36932a65deL,0x9611ff5c3aa95529L, + 0xc58215b07c1e5a36L }, + { 0xd48c9b58f0e1a524L,0xb406856bf590dfb8L,0xc7605e049cd95662L, + 0x0dd036eea33ecf82L } }, + /* 19 << 14 */ + { { 0xa50171acc33156b3L,0xf09d24ea4a80172eL,0x4e1f72c676dc8eefL, + 0xe60caadc5e3d44eeL }, + { 0x006ef8a6979b1d8fL,0x60908a1c97788d26L,0x6e08f95b266feec0L, + 0x618427c222e8c94eL } }, + /* 20 << 14 */ + { { 0x3d61333959145a65L,0xcd9bc368fa406337L,0x82d11be32d8a52a0L, + 0xf6877b2797a1c590L }, + { 0x837a819bf5cbdb25L,0x2a4fd1d8de090249L,0x622a7de774990e5fL, + 0x840fa5a07945511bL } }, + /* 21 << 14 */ + { { 0x30b974be6558842dL,0x70df8c6417f3d0a6L,0x7c8035207542e46dL, + 0x7251fe7fe4ecc823L }, + { 0xe59134cb5e9aac9aL,0x11bb0934f0045d71L,0x53e5d9b5dbcb1d4eL, + 0x8d97a90592defc91L } }, + /* 22 << 14 */ + { { 0xfe2893277946d3f9L,0xe132bd2407472273L,0xeeeb510c1eb6ae86L, + 0x777708c5f0595067L }, + { 0x18e2c8cd1297029eL,0x2c61095cbbf9305eL,0xe466c2586b85d6d9L, + 0x8ac06c36da1ea530L } }, + /* 23 << 14 */ + { { 0xa365dc39a1304668L,0xe4a9c88507f89606L,0x65a4898facc7228dL, + 0x3e2347ff84ca8303L }, + { 0xa5f6fb77ea7d23a3L,0x2fac257d672a71cdL,0x6908bef87e6a44d3L, + 0x8ff87566891d3d7aL } }, + /* 24 << 14 */ + { { 0xe58e90b36b0cf82eL,0x6438d2462615b5e7L,0x07b1f8fc669c145aL, + 0xb0d8b2da36f1e1cbL }, + { 0x54d5dadbd9184c4dL,0x3dbb18d5f93d9976L,0x0a3e0f56d1147d47L, + 0x2afa8c8da0a48609L } }, + /* 25 << 14 */ + { { 0x275353e8bc36742cL,0x898f427eeea0ed90L,0x26f4947e3e477b00L, + 0x8ad8848a308741e3L }, + { 0x6c703c38d74a2a46L,0x5e3e05a99ba17ba2L,0xc1fa6f664ab9a9e4L, + 0x474a2d9a3841d6ecL } }, + /* 26 << 14 */ + { { 0x871239ad653ae326L,0x14bcf72aa74cbb43L,0x8737650e20d4c083L, + 0x3df86536110ed4afL }, + { 0xd2d86fe7b53ca555L,0x688cb00dabd5d538L,0xcf81bda31ad38468L, + 0x7ccfe3ccf01167b6L } }, + /* 27 << 14 */ + { { 0xcf4f47e06c4c1fe6L,0x557e1f1a298bbb79L,0xf93b974f30d45a14L, + 0x174a1d2d0baf97c4L }, + { 0x7a003b30c51fbf53L,0xd8940991ee68b225L,0x5b0aa7b71c0f4173L, + 0x975797c9a20a7153L } }, + /* 28 << 14 */ + { { 0x26e08c07e3533d77L,0xd7222e6a2e341c99L,0x9d60ec3d8d2dc4edL, + 0xbdfe0d8f7c476cf8L }, + { 0x1fe59ab61d056605L,0xa9ea9df686a8551fL,0x8489941e47fb8d8cL, + 0xfeb874eb4a7f1b10L } }, + /* 29 << 14 */ + { { 0xfe5fea867ee0d98fL,0x201ad34bdbf61864L,0x45d8fe4737c031d4L, + 0xd5f49fae795f0822L }, + { 0xdb0fb291c7f4a40cL,0x2e69d9c1730ddd92L,0x754e105449d76987L, + 0x8a24911d7662db87L } }, + /* 30 << 14 */ + { { 0x61fc181060a71676L,0xe852d1a8f66a8ad1L,0x172bbd656417231eL, + 0x0d6de7bd3babb11fL }, + { 0x6fde6f88c8e347f8L,0x1c5875479bd99cc3L,0x78e54ed034076950L, + 0x97f0f334796e83baL } }, + /* 31 << 14 */ + { { 0xe4dbe1ce4924867aL,0xbd5f51b060b84917L,0x375300403cb09a79L, + 0xdb3fe0f8ff1743d8L }, + { 0xed7894d8556fa9dbL,0xfa26216923412fbfL,0x563be0dbba7b9291L, + 0x6ca8b8c00c9fb234L } }, + /* 32 << 14 */ + { { 0xed406aa9bd763802L,0xc21486a065303da1L,0x61ae291ec7e62ec4L, + 0x622a0492df99333eL }, + { 0x7fd80c9dbb7a8ee0L,0xdc2ed3bc6c01aedbL,0x35c35a1208be74ecL, + 0xd540cb1a469f671fL } }, + /* 33 << 14 */ + { { 0xd16ced4ecf84f6c7L,0x8561fb9c2d090f43L,0x7e693d796f239db4L, + 0xa736f92877bd0d94L }, + { 0x07b4d9292c1950eeL,0xda17754356dc11b3L,0xa5dfbbaa7a6a878eL, + 0x1c70cb294decb08aL } }, + /* 34 << 14 */ + { { 0xfba28c8b6f0f7c50L,0xa8eba2b8854dcc6dL,0x5ff8e89a36b78642L, + 0x070c1c8ef6873adfL }, + { 0xbbd3c3716484d2e4L,0xfb78318f0d414129L,0x2621a39c6ad93b0bL, + 0x979d74c2a9e917f7L } }, + /* 35 << 14 */ + { { 0xfc19564761fb0428L,0x4d78954abee624d4L,0xb94896e0b8ae86fdL, + 0x6667ac0cc91c8b13L }, + { 0x9f18051243bcf832L,0xfbadf8b7a0010137L,0xc69b4089b3ba8aa7L, + 0xfac4bacde687ce85L } }, + /* 36 << 14 */ + { { 0x9164088d977eab40L,0x51f4c5b62760b390L,0xd238238f340dd553L, + 0x358566c3db1d31c9L }, + { 0x3a5ad69e5068f5ffL,0xf31435fcdaff6b06L,0xae549a5bd6debff0L, + 0x59e5f0b775e01331L } }, + /* 37 << 14 */ + { { 0x5d492fb898559acfL,0x96018c2e4db79b50L,0x55f4a48f609f66aaL, + 0x1943b3af4900a14fL }, + { 0xc22496df15a40d39L,0xb2a446844c20f7c5L,0x76a35afa3b98404cL, + 0xbec75725ff5d1b77L } }, + /* 38 << 14 */ + { { 0xb67aa163bea06444L,0x27e95bb2f724b6f2L,0x3c20e3e9d238c8abL, + 0x1213754eddd6ae17L }, + { 0x8c431020716e0f74L,0x6679c82effc095c2L,0x2eb3adf4d0ac2932L, + 0x2cc970d301bb7a76L } }, + /* 39 << 14 */ + { { 0x70c71f2f740f0e66L,0x545c616b2b6b23ccL,0x4528cfcbb40a8bd7L, + 0xff8396332ab27722L }, + { 0x049127d9025ac99aL,0xd314d4a02b63e33bL,0xc8c310e728d84519L, + 0x0fcb8983b3bc84baL } }, + /* 40 << 14 */ + { { 0x2cc5226138634818L,0x501814f4b44c2e0bL,0xf7e181aa54dfdba3L, + 0xcfd58ff0e759718cL }, + { 0xf90cdb14d3b507a8L,0x57bd478ec50bdad8L,0x29c197e250e5f9aaL, + 0x4db6eef8e40bc855L } }, + /* 41 << 14 */ + { { 0x2cc8f21ad1fc0654L,0xc71cc96381269d73L,0xecfbb204077f49f9L, + 0xdde92571ca56b793L }, + { 0x9abed6a3f97ad8f7L,0xe6c19d3f924de3bdL,0x8dce92f4a140a800L, + 0x85f44d1e1337af07L } }, + /* 42 << 14 */ + { { 0x5953c08b09d64c52L,0xa1b5e49ff5df9749L,0x336a8fb852735f7dL, + 0xb332b6db9add676bL }, + { 0x558b88a0b4511aa4L,0x09788752dbd5cc55L,0x16b43b9cd8cd52bdL, + 0x7f0bc5a0c2a2696bL } }, + /* 43 << 14 */ + { { 0x146e12d4c11f61efL,0x9ce107543a83e79eL,0x08ec73d96cbfca15L, + 0x09ff29ad5b49653fL }, + { 0xe31b72bde7da946eL,0xebf9eb3bee80a4f2L,0xd1aabd0817598ce4L, + 0x18b5fef453f37e80L } }, + /* 44 << 14 */ + { { 0xd5d5cdd35958cd79L,0x3580a1b51d373114L,0xa36e4c91fa935726L, + 0xa38c534def20d760L }, + { 0x7088e40a2ff5845bL,0xe5bb40bdbd78177fL,0x4f06a7a8857f9920L, + 0xe3cc3e50e968f05dL } }, + /* 45 << 14 */ + { { 0x1d68b7fee5682d26L,0x5206f76faec7f87cL,0x41110530041951abL, + 0x58ec52c1d4b5a71aL }, + { 0xf3488f990f75cf9aL,0xf411951fba82d0d5L,0x27ee75be618895abL, + 0xeae060d46d8aab14L } }, + /* 46 << 14 */ + { { 0x9ae1df737fb54dc2L,0x1f3e391b25963649L,0x242ec32afe055081L, + 0x5bd450ef8491c9bdL }, + { 0x367efc67981eb389L,0xed7e19283a0550d5L,0x362e776bab3ce75cL, + 0xe890e3081f24c523L } }, + /* 47 << 14 */ + { { 0xb961b682feccef76L,0x8b8e11f58bba6d92L,0x8f2ccc4c2b2375c4L, + 0x0d7f7a52e2f86cfaL }, + { 0xfd94d30a9efe5633L,0x2d8d246b5451f934L,0x2234c6e3244e6a00L, + 0xde2b5b0dddec8c50L } }, + /* 48 << 14 */ + { { 0x2ce53c5abf776f5bL,0x6f72407160357b05L,0xb259371771bf3f7aL, + 0x87d2501c440c4a9fL }, + { 0x440552e187b05340L,0xb7bf7cc821624c32L,0x4155a6ce22facddbL, + 0x5a4228cb889837efL } }, + /* 49 << 14 */ + { { 0xef87d6d6fd4fd671L,0xa233687ec2daa10eL,0x7562224403c0eb96L, + 0x7632d1848bf19be6L }, + { 0x05d0f8e940735ff4L,0x3a3e6e13c00931f1L,0x31ccde6adafe3f18L, + 0xf381366acfe51207L } }, + /* 50 << 14 */ + { { 0x24c222a960167d92L,0x62f9d6f87529f18cL,0x412397c00353b114L, + 0x334d89dcef808043L }, + { 0xd9ec63ba2a4383ceL,0xcec8e9375cf92ba0L,0xfb8b4288c8be74c0L, + 0x67d6912f105d4391L } }, + /* 51 << 14 */ + { { 0x7b996c461b913149L,0x36aae2ef3a4e02daL,0xb68aa003972de594L, + 0x284ec70d4ec6d545L }, + { 0xf3d2b2d061391d54L,0x69c5d5d6fe114e92L,0xbe0f00b5b4482dffL, + 0xe1596fa5f5bf33c5L } }, + /* 52 << 14 */ + { { 0x10595b5696a71cbaL,0x944938b2fdcadeb7L,0xa282da4cfccd8471L, + 0x98ec05f30d37bfe1L }, + { 0xe171ce1b0698304aL,0x2d69144421bdf79bL,0xd0cd3b741b21dec1L, + 0x712ecd8b16a15f71L } }, + /* 53 << 14 */ + { { 0x8d4c00a700fd56e1L,0x02ec9692f9527c18L,0x21c449374a3e42e1L, + 0x9176fbab1392ae0aL }, + { 0x8726f1ba44b7b618L,0xb4d7aae9f1de491cL,0xf91df7b907b582c0L, + 0x7e116c30ef60aa3aL } }, + /* 54 << 14 */ + { { 0x99270f81466265d7L,0xb15b6fe24df7adf0L,0xfe33b2d3f9738f7fL, + 0x48553ab9d6d70f95L }, + { 0x2cc72ac8c21e94dbL,0x795ac38dbdc0bbeeL,0x0a1be4492e40478fL, + 0x81bd3394052bde55L } }, + /* 55 << 14 */ + { { 0x63c8dbe956b3c4f2L,0x017a99cf904177ccL,0x947bbddb4d010fc1L, + 0xacf9b00bbb2c9b21L }, + { 0x2970bc8d47173611L,0x1a4cbe08ac7d756fL,0x06d9f4aa67d541a2L, + 0xa3e8b68959c2cf44L } }, + /* 56 << 14 */ + { { 0xaad066da4d88f1ddL,0xc604f1657ad35deaL,0x7edc07204478ca67L, + 0xa10dfae0ba02ce06L }, + { 0xeceb1c76af36f4e4L,0x994b2292af3f8f48L,0xbf9ed77b77c8a68cL, + 0x74f544ea51744c9dL } }, + /* 57 << 14 */ + { { 0x82d05bb98113a757L,0x4ef2d2b48a9885e4L,0x1e332be51aa7865fL, + 0x22b76b18290d1a52L }, + { 0x308a231044351683L,0x9d861896a3f22840L,0x5959ddcd841ed947L, + 0x0def0c94154b73bfL } }, + /* 58 << 14 */ + { { 0xf01054174c7c15e0L,0x539bfb023a277c32L,0xe699268ef9dccf5fL, + 0x9f5796a50247a3bdL }, + { 0x8b839de84f157269L,0xc825c1e57a30196bL,0x6ef0aabcdc8a5a91L, + 0xf4a8ce6c498b7fe6L } }, + /* 59 << 14 */ + { { 0x1cce35a770cbac78L,0x83488e9bf6b23958L,0x0341a070d76cb011L, + 0xda6c9d06ae1b2658L }, + { 0xb701fb30dd648c52L,0x994ca02c52fb9fd1L,0x069331176f563086L, + 0x3d2b810017856babL } }, + /* 60 << 14 */ + { { 0xe89f48c85963a46eL,0x658ab875a99e61c7L,0x6e296f874b8517b4L, + 0x36c4fcdcfc1bc656L }, + { 0xde5227a1a3906defL,0x9fe95f5762418945L,0x20c91e81fdd96cdeL, + 0x5adbe47eda4480deL } }, + /* 61 << 14 */ + { { 0xa009370f396de2b6L,0x98583d4bf0ecc7bdL,0xf44f6b57e51d0672L, + 0x03d6b078556b1984L }, + { 0x27dbdd93b0b64912L,0x9b3a343415687b09L,0x0dba646151ec20a9L, + 0xec93db7fff28187cL } }, + /* 62 << 14 */ + { { 0x00ff8c2466e48bddL,0x2514f2f911ccd78eL,0xeba11f4fe1250603L, + 0x8a22cd41243fa156L }, + { 0xa4e58df4b283e4c6L,0x78c298598b39783fL,0x5235aee2a5259809L, + 0xc16284b50e0227ddL } }, + /* 63 << 14 */ + { { 0xa5f579161338830dL,0x6d4b8a6bd2123fcaL,0x236ea68af9c546f8L, + 0xc1d36873fa608d36L }, + { 0xcd76e4958d436d13L,0xd4d9c2218fb080afL,0x665c1728e8ad3fb5L, + 0xcf1ebe4db3d572e0L } }, + /* 64 << 14 */ + { { 0xa7a8746a584c5e20L,0x267e4ea1b9dc7035L,0x593a15cfb9548c9bL, + 0x5e6e21354bd012f3L }, + { 0xdf31cc6a8c8f936eL,0x8af84d04b5c241dcL,0x63990a6f345efb86L, + 0x6fef4e61b9b962cbL } }, + /* 0 << 21 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 21 */ + { { 0xf6368f0925722608L,0x131260db131cf5c6L,0x40eb353bfab4f7acL, + 0x85c7888037eee829L }, + { 0x4c1581ffc3bdf24eL,0x5bff75cbf5c3c5a8L,0x35e8c83fa14e6f40L, + 0xb81d1c0f0295e0caL } }, + /* 2 << 21 */ + { { 0xfcde7cc8f43a730fL,0xe89b6f3c33ab590eL,0xc823f529ad03240bL, + 0x82b79afe98bea5dbL }, + { 0x568f2856962fe5deL,0x0c590adb60c591f3L,0x1fc74a144a28a858L, + 0x3b662498b3203f4cL } }, + /* 3 << 21 */ + { { 0x91e3cf0d6c39765aL,0xa2db3acdac3cca0bL,0x288f2f08cb953b50L, + 0x2414582ccf43cf1aL }, + { 0x8dec8bbc60eee9a8L,0x54c79f02729aa042L,0xd81cd5ec6532f5d5L, + 0xa672303acf82e15fL } }, + /* 4 << 21 */ + { { 0x376aafa8719c0563L,0xcd8ad2dcbc5fc79fL,0x303fdb9fcb750cd3L, + 0x14ff052f4418b08eL }, + { 0xf75084cf3e2d6520L,0x7ebdf0f8144ed509L,0xf43bf0f2d3f25b98L, + 0x86ad71cfa354d837L } }, + /* 5 << 21 */ + { { 0xb827fe9226f43572L,0xdfd3ab5b5d824758L,0x315dd23a539094c1L, + 0x85c0e37a66623d68L }, + { 0x575c79727be19ae0L,0x616a3396df0d36b5L,0xa1ebb3c826b1ff7eL, + 0x635b9485140ad453L } }, + /* 6 << 21 */ + { { 0x92bf3cdada430c0bL,0x4702850e3a96dac6L,0xc91cf0a515ac326aL, + 0x95de4f49ab8c25e4L }, + { 0xb01bad09e265c17cL,0x24e45464087b3881L,0xd43e583ce1fac5caL, + 0xe17cb3186ead97a6L } }, + /* 7 << 21 */ + { { 0x6cc3924374dcec46L,0x33cfc02d54c2b73fL,0x82917844f26cd99cL, + 0x8819dd95d1773f89L }, + { 0x09572aa60871f427L,0x8e0cf365f6f01c34L,0x7fa52988bff1f5afL, + 0x4eb357eae75e8e50L } }, + /* 8 << 21 */ + { { 0xd9d0c8c4868af75dL,0xd7325cff45c8c7eaL,0xab471996cc81ecb0L, + 0xff5d55f3611824edL }, + { 0xbe3145411977a0eeL,0x5085c4c5722038c6L,0x2d5335bff94bb495L, + 0x894ad8a6c8e2a082L } }, + /* 9 << 21 */ + { { 0x5c3e2341ada35438L,0xf4a9fc89049b8c4eL,0xbeeb355a9f17cf34L, + 0x3f311e0e6c91fe10L }, + { 0xc2d2003892ab9891L,0x257bdcc13e8ce9a9L,0x1b2d978988c53beeL, + 0x927ce89acdba143aL } }, + /* 10 << 21 */ + { { 0xb0a32cca523db280L,0x5c889f8a50d43783L,0x503e04b34897d16fL, + 0x8cdb6e7808f5f2e8L }, + { 0x6ab91cf0179c8e74L,0xd8874e5248211d60L,0xf948d4d5ea851200L, + 0x4076d41ee6f9840aL } }, + /* 11 << 21 */ + { { 0xc20e263c47b517eaL,0x79a448fd30685e5eL,0xe55f6f78f90631a0L, + 0x88a790b1a79e6346L }, + { 0x62160c7d80969fe8L,0x54f92fd441491bb9L,0xa6645c235c957526L, + 0xf44cc5aebea3ce7bL } }, + /* 12 << 21 */ + { { 0xf76283278b1e68b7L,0xc731ad7a303f29d3L,0xfe5a9ca957d03ecbL, + 0x96c0d50c41bc97a7L }, + { 0xc4669fe79b4f7f24L,0xfdd781d83d9967efL,0x7892c7c35d2c208dL, + 0x8bf64f7cae545cb3L } }, + /* 13 << 21 */ + { { 0xc01f862c467be912L,0xf4c85ee9c73d30ccL,0x1fa6f4be6ab83ec7L, + 0xa07a3c1c4e3e3cf9L }, + { 0x87f8ef450c00beb3L,0x30e2c2b3000d4c3eL,0x1aa00b94fe08bf5bL, + 0x32c133aa9224ef52L } }, + /* 14 << 21 */ + { { 0x38df16bb32e5685dL,0x68a9e06958e6f544L,0x495aaff7cdc5ebc6L, + 0xf894a645378b135fL }, + { 0xf316350a09e27ecfL,0xeced201e58f7179dL,0x2eec273ce97861baL, + 0x47ec2caed693be2eL } }, + /* 15 << 21 */ + { { 0xfa4c97c4f68367ceL,0xe4f47d0bbe5a5755L,0x17de815db298a979L, + 0xd7eca659c177dc7dL }, + { 0x20fdbb7149ded0a3L,0x4cb2aad4fb34d3c5L,0x2cf31d2860858a33L, + 0x3b6873efa24aa40fL } }, + /* 16 << 21 */ + { { 0x540234b22c11bb37L,0x2d0366dded4c74a3L,0xf9a968daeec5f25dL, + 0x3660106867b63142L }, + { 0x07cd6d2c68d7b6d4L,0xa8f74f090c842942L,0xe27514047768b1eeL, + 0x4b5f7e89fe62aee4L } }, + /* 17 << 21 */ + { { 0xc6a7717789070d26L,0xa1f28e4edd1c8bc7L,0xea5f4f06469e1f17L, + 0x78fc242afbdb78e0L }, + { 0xc9c7c5928b0588f1L,0xb6b7a0fd1535921eL,0xcc5bdb91bde5ae35L, + 0xb42c485e12ff1864L } }, + /* 18 << 21 */ + { { 0xa1113e13dbab98aaL,0xde9d469ba17b1024L,0x23f48b37c0462d3aL, + 0x3752e5377c5c078dL }, + { 0xe3a86add15544eb9L,0xf013aea780fba279L,0x8b5bb76cf22001b5L, + 0xe617ba14f02891abL } }, + /* 19 << 21 */ + { { 0xd39182a6936219d3L,0x5ce1f194ae51cb19L,0xc78f8598bf07a74cL, + 0x6d7158f222cbf1bcL }, + { 0x3b846b21e300ce18L,0x35fba6302d11275dL,0x5fe25c36a0239b9bL, + 0xd8beb35ddf05d940L } }, + /* 20 << 21 */ + { { 0x4db02bb01f7e320dL,0x0641c3646da320eaL,0x6d95fa5d821389a3L, + 0x926997488fcd8e3dL }, + { 0x316fef17ceb6c143L,0x67fcb841d933762bL,0xbb837e35118b17f8L, + 0x4b92552f9fd24821L } }, + /* 21 << 21 */ + { { 0xae6bc70e46aca793L,0x1cf0b0e4e579311bL,0x8dc631be5802f716L, + 0x099bdc6fbddbee4dL }, + { 0xcc352bb20caf8b05L,0xf74d505a72d63df2L,0xb9876d4b91c4f408L, + 0x1ce184739e229b2dL } }, + /* 22 << 21 */ + { { 0x4950759783abdb4aL,0x850fbcb6dee84b18L,0x6325236e609e67dcL, + 0x04d831d99336c6d8L }, + { 0x8deaae3bfa12d45dL,0xe425f8ce4746e246L,0x8004c17524f5f31eL, + 0xaca16d8fad62c3b7L } }, + /* 23 << 21 */ + { { 0x0dc15a6a9152f934L,0xf1235e5ded0e12c1L,0xc33c06ecda477dacL, + 0x76be8732b2ea0006L }, + { 0xcf3f78310c0cd313L,0x3c524553a614260dL,0x31a756f8cab22d15L, + 0x03ee10d177827a20L } }, + /* 24 << 21 */ + { { 0xd1e059b21994ef20L,0x2a653b69638ae318L,0x70d5eb582f699010L, + 0x279739f709f5f84aL }, + { 0x5da4663c8b799336L,0xfdfdf14d203c37ebL,0x32d8a9dca1dbfb2dL, + 0xab40cff077d48f9bL } }, + /* 25 << 21 */ + { { 0xc018b383d20b42d5L,0xf9a810ef9f78845fL,0x40af3753bdba9df0L, + 0xb90bdcfc131dfdf9L }, + { 0x18720591f01ab782L,0xc823f2116af12a88L,0xa51b80f30dc14401L, + 0xde248f77fb2dfbe3L } }, + /* 26 << 21 */ + { { 0xef5a44e50cafe751L,0x73997c9cd4dcd221L,0x32fd86d1de854024L, + 0xd5b53adca09b84bbL }, + { 0x008d7a11dcedd8d1L,0x406bd1c874b32c84L,0x5d4472ff05dde8b1L, + 0x2e25f2cdfce2b32fL } }, + /* 27 << 21 */ + { { 0xbec0dd5e29dfc254L,0x4455fcf62b98b267L,0x0b4d43a5c72df2adL, + 0xea70e6be48a75397L }, + { 0x2aad61695820f3bfL,0xf410d2dd9e37f68fL,0x70fb7dba7be5ac83L, + 0x636bb64536ec3eecL } }, + /* 28 << 21 */ + { { 0x27104ea39754e21cL,0xbc87a3e68d63c373L,0x483351d74109db9aL, + 0x0fa724e360134da7L }, + { 0x9ff44c29b0720b16L,0x2dd0cf1306aceeadL,0x5942758ce26929a6L, + 0x96c5db92b766a92bL } }, + /* 29 << 21 */ + { { 0xcec7d4c05f18395eL,0xd3f227441f80d032L,0x7a68b37acb86075bL, + 0x074764ddafef92dbL }, + { 0xded1e9507bc7f389L,0xc580c850b9756460L,0xaeeec2a47da48157L, + 0x3f0b4e7f82c587b3L } }, + /* 30 << 21 */ + { { 0x231c6de8a9f19c53L,0x5717bd736974e34eL,0xd9e1d216f1508fa9L, + 0x9f112361dadaa124L }, + { 0x80145e31823b7348L,0x4dd8f0d5ac634069L,0xe3d82fc72297c258L, + 0x276fcfee9cee7431L } }, + /* 31 << 21 */ + { { 0x8eb61b5e2bc0aea9L,0x4f668fd5de329431L,0x03a32ab138e4b87eL, + 0xe137451773d0ef0bL }, + { 0x1a46f7e6853ac983L,0xc3bdf42e68e78a57L,0xacf207852ea96dd1L, + 0xa10649b9f1638460L } }, + /* 32 << 21 */ + { { 0xf2369f0b879fbbedL,0x0ff0ae86da9d1869L,0x5251d75956766f45L, + 0x4984d8c02be8d0fcL }, + { 0x7ecc95a6d21008f0L,0x29bd54a03a1a1c49L,0xab9828c5d26c50f3L, + 0x32c0087c51d0d251L } }, + /* 33 << 21 */ + { { 0x9bac3ce60c1cdb26L,0xcd94d947557ca205L,0x1b1bd5989db1fdcdL, + 0x0eda0108a3d8b149L }, + { 0x9506661056152fccL,0xc2f037e6e7192b33L,0xdeffb41ac92e05a4L, + 0x1105f6c2c2f6c62eL } }, + /* 34 << 21 */ + { { 0x68e735008733913cL,0xcce861633f3adc40L,0xf407a94238a278e9L, + 0xd13c1b9d2ab21292L }, + { 0x93ed7ec71c74cf5cL,0x8887dc48f1a4c1b4L,0x3830ff304b3a11f1L, + 0x358c5a3c58937cb6L } }, + /* 35 << 21 */ + { { 0x027dc40489022829L,0x40e939773b798f79L,0x90ad333738be6eadL, + 0x9c23f6bcf34c0a5dL }, + { 0xd1711a35fbffd8bbL,0x60fcfb491949d3ddL,0x09c8ef4b7825d93aL, + 0x24233cffa0a8c968L } }, + /* 36 << 21 */ + { { 0x67ade46ce6d982afL,0xebb6bf3ee7544d7cL,0xd6b9ba763d8bd087L, + 0x46fe382d4dc61280L }, + { 0xbd39a7e8b5bdbd75L,0xab381331b8f228feL,0x0709a77cce1c4300L, + 0x6a247e56f337ceacL } }, + /* 37 << 21 */ + { { 0x8f34f21b636288beL,0x9dfdca74c8a7c305L,0x6decfd1bea919e04L, + 0xcdf2688d8e1991f8L }, + { 0xe607df44d0f8a67eL,0xd985df4b0b58d010L,0x57f834c50c24f8f4L, + 0xe976ef56a0bf01aeL } }, + /* 38 << 21 */ + { { 0x536395aca1c32373L,0x351027aa734c0a13L,0xd2f1b5d65e6bd5bcL, + 0x2b539e24223debedL }, + { 0xd4994cec0eaa1d71L,0x2a83381d661dcf65L,0x5f1aed2f7b54c740L, + 0x0bea3fa5d6dda5eeL } }, + /* 39 << 21 */ + { { 0x9d4fb68436cc6134L,0x8eb9bbf3c0a443ddL,0xfc500e2e383b7d2aL, + 0x7aad621c5b775257L }, + { 0x69284d740a8f7cc0L,0xe820c2ce07562d65L,0xbf9531b9499758eeL, + 0x73e95ca56ee0cc2dL } }, + /* 40 << 21 */ + { { 0xf61790abfbaf50a5L,0xdf55e76b684e0750L,0xec516da7f176b005L, + 0x575553bb7a2dddc7L }, + { 0x37c87ca3553afa73L,0x315f3ffc4d55c251L,0xe846442aaf3e5d35L, + 0x61b911496495ff28L } }, + /* 41 << 21 */ + { { 0x23cc95d3fa326dc3L,0x1df4da1f18fc2ceaL,0x24bf9adcd0a37d59L, + 0xb6710053320d6e1eL }, + { 0x96f9667e618344d1L,0xcc7ce042a06445afL,0xa02d8514d68dbc3aL, + 0x4ea109e4280b5a5bL } }, + /* 42 << 21 */ + { { 0x5741a7acb40961bfL,0x4ada59376aa56bfaL,0x7feb914502b765d1L, + 0x561e97bee6ad1582L }, + { 0xbbc4a5b6da3982f5L,0x0c2659edb546f468L,0xb8e7e6aa59612d20L, + 0xd83dfe20ac19e8e0L } }, + /* 43 << 21 */ + { { 0x8530c45fb835398cL,0x6106a8bfb38a41c2L,0x21e8f9a635f5dcdbL, + 0x39707137cae498edL }, + { 0x70c23834d8249f00L,0x9f14b58fab2537a0L,0xd043c3655f61c0c2L, + 0xdc5926d609a194a7L } }, + /* 44 << 21 */ + { { 0xddec03398e77738aL,0xd07a63effba46426L,0x2e58e79cee7f6e86L, + 0xe59b0459ff32d241L }, + { 0xc5ec84e520fa0338L,0x97939ac8eaff5aceL,0x0310a4e3b4a38313L, + 0x9115fba28f9d9885L } }, + /* 45 << 21 */ + { { 0x8dd710c25fadf8c3L,0x66be38a2ce19c0e2L,0xd42a279c4cfe5022L, + 0x597bb5300e24e1b8L }, + { 0x3cde86b7c153ca7fL,0xa8d30fb3707d63bdL,0xac905f92bd60d21eL, + 0x98e7ffb67b9a54abL } }, + /* 46 << 21 */ + { { 0xd7147df8e9726a30L,0xb5e216ffafce3533L,0xb550b7992ff1ec40L, + 0x6b613b87a1e953fdL }, + { 0x87b88dba792d5610L,0x2ee1270aa190fbe1L,0x02f4e2dc2ef581daL, + 0x016530e4eff82a95L } }, + /* 47 << 21 */ + { { 0xcbb93dfd8fd6ee89L,0x16d3d98646848fffL,0x600eff241da47adfL, + 0x1b9754a00ad47a71L }, + { 0x8f9266df70c33b98L,0xaadc87aedf34186eL,0x0d2ce8e14ad24132L, + 0x8a47cbfc19946ebaL } }, + /* 48 << 21 */ + { { 0x47feeb6662b5f3afL,0xcefab5610abb3734L,0x449de60e19f35cb1L, + 0x39f8db14157f0eb9L }, + { 0xffaecc5b3c61bfd6L,0xa5a4d41d41216703L,0x7f8fabed224e1cc2L, + 0x0d5a8186871ad953L } }, + /* 49 << 21 */ + { { 0xf10774f7d22da9a9L,0x45b8a678cc8a9b0dL,0xd9c2e722bdc32cffL, + 0xbf71b5f5337202a5L }, + { 0x95c57f2f69fc4db9L,0xb6dad34c765d01e1L,0x7e0bd13fcb904635L, + 0x61751253763a588cL } }, + /* 50 << 21 */ + { { 0xd85c299781af2c2dL,0xc0f7d9c481b9d7daL,0x838a34ae08533e8dL, + 0x15c4cb08311d8311L }, + { 0x97f832858e121e14L,0xeea7dc1e85000a5fL,0x0c6059b65d256274L, + 0xec9beaceb95075c0L } }, + /* 51 << 21 */ + { { 0x173daad71df97828L,0xbf851cb5a8937877L,0xb083c59401646f3cL, + 0x3bad30cf50c6d352L }, + { 0xfeb2b202496bbceaL,0x3cf9fd4f18a1e8baL,0xd26de7ff1c066029L, + 0x39c81e9e4e9ed4f8L } }, + /* 52 << 21 */ + { { 0xd8be0cb97b390d35L,0x01df2bbd964aab27L,0x3e8c1a65c3ef64f8L, + 0x567291d1716ed1ddL }, + { 0x95499c6c5f5406d3L,0x71fdda395ba8e23fL,0xcfeb320ed5096eceL, + 0xbe7ba92bca66dd16L } }, + /* 53 << 21 */ + { { 0x4608d36bc6fb5a7dL,0xe3eea15a6d2dd0e0L,0x75b0a3eb8f97a36aL, + 0xf59814cc1c83de1eL }, + { 0x56c9c5b01c33c23fL,0xa96c1da46faa4136L,0x46bf2074de316551L, + 0x3b866e7b1f756c8fL } }, + /* 54 << 21 */ + { { 0x727727d81495ed6bL,0xb2394243b682dce7L,0x8ab8454e758610f3L, + 0xc243ce84857d72a4L }, + { 0x7b320d71dbbf370fL,0xff9afa3778e0f7caL,0x0119d1e0ea7b523fL, + 0xb997f8cb058c7d42L } }, + /* 55 << 21 */ + { { 0x285bcd2a37bbb184L,0x51dcec49a45d1fa6L,0x6ade3b64e29634cbL, + 0x080c94a726b86ef1L }, + { 0xba583db12283fbe3L,0x902bddc85a9315edL,0x07c1ccb386964becL, + 0x78f4eacfb6258301L } }, + /* 56 << 21 */ + { { 0x4bdf3a4956f90823L,0xba0f5080741d777bL,0x091d71c3f38bf760L, + 0x9633d50f9b625b02L }, + { 0x03ecb743b8c9de61L,0xb47512545de74720L,0x9f9defc974ce1cb2L, + 0x774a4f6a00bd32efL } }, + /* 57 << 21 */ + { { 0xaca385f773848f22L,0x53dad716f3f8558eL,0xab7b34b093c471f9L, + 0xf530e06919644bc7L }, + { 0x3d9fb1ffdd59d31aL,0x4382e0df08daa795L,0x165c6f4bd5cc88d7L, + 0xeaa392d54a18c900L } }, + /* 58 << 21 */ + { { 0x94203c67648024eeL,0x188763f28c2fabcdL,0xa80f87acbbaec835L, + 0x632c96e0f29d8d54L }, + { 0x29b0a60e4c00a95eL,0x2ef17f40e011e9faL,0xf6c0e1d115b77223L, + 0xaaec2c6214b04e32L } }, + /* 59 << 21 */ + { { 0xd35688d83d84e58cL,0x2af5094c958571dbL,0x4fff7e19760682a6L, + 0x4cb27077e39a407cL }, + { 0x0f59c5474ff0e321L,0x169f34a61b34c8ffL,0x2bff109652bc1ba7L, + 0xa25423b783583544L } }, + /* 60 << 21 */ + { { 0x5d55d5d50ac8b782L,0xff6622ec2db3c892L,0x48fce7416b8bb642L, + 0x31d6998c69d7e3dcL }, + { 0xdbaf8004cadcaed0L,0x801b0142d81d053cL,0x94b189fc59630ec6L, + 0x120e9934af762c8eL } }, + /* 61 << 21 */ + { { 0x53a29aa4fdc6a404L,0x19d8e01ea1909948L,0x3cfcabf1d7e89681L, + 0x3321a50d4e132d37L }, + { 0xd0496863e9a86111L,0x8c0cde6106a3bc65L,0xaf866c49fc9f8eefL, + 0x2066350eff7f5141L } }, + /* 62 << 21 */ + { { 0x4f8a4689e56ddfbdL,0xea1b0c07fe32983aL,0x2b317462873cb8cbL, + 0x658deddc2d93229fL }, + { 0x65efaf4d0f64ef58L,0xfe43287d730cc7a8L,0xaebc0c723d047d70L, + 0x92efa539d92d26c9L } }, + /* 63 << 21 */ + { { 0x06e7845794b56526L,0x415cb80f0961002dL,0x89e5c56576dcb10fL, + 0x8bbb6982ff9259feL }, + { 0x4fe8795b9abc2668L,0xb5d4f5341e678fb1L,0x6601f3be7b7da2b9L, + 0x98da59e2a13d6805L } }, + /* 64 << 21 */ + { { 0x190d8ea601799a52L,0xa20cec41b86d2952L,0x3062ffb27fff2a7cL, + 0x741b32e579f19d37L }, + { 0xf80d81814eb57d47L,0x7a2d0ed416aef06bL,0x09735fb01cecb588L, + 0x1641caaac6061f5bL } }, + /* 0 << 28 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 28 */ + { { 0x7f99824f20151427L,0x206828b692430206L,0xaa9097d7e1112357L, + 0xacf9a2f209e414ecL }, + { 0xdbdac9da27915356L,0x7e0734b7001efee3L,0x54fab5bbd2b288e2L, + 0x4c630fc4f62dd09cL } }, + /* 2 << 28 */ + { { 0x8537107a1ac2703bL,0xb49258d86bc857b5L,0x57df14debcdaccd1L, + 0x24ab68d7c4ae8529L }, + { 0x7ed8b5d4734e59d0L,0x5f8740c8c495cc80L,0x84aedd5a291db9b3L, + 0x80b360f84fb995beL } }, + /* 3 << 28 */ + { { 0xae915f5d5fa067d1L,0x4134b57f9668960cL,0xbd3656d6a48edaacL, + 0xdac1e3e4fc1d7436L }, + { 0x674ff869d81fbb26L,0x449ed3ecb26c33d4L,0x85138705d94203e8L, + 0xccde538bbeeb6f4aL } }, + /* 4 << 28 */ + { { 0x55d5c68da61a76faL,0x598b441dca1554dcL,0xd39923b9773b279cL, + 0x33331d3c36bf9efcL }, + { 0x2d4c848e298de399L,0xcfdb8e77a1a27f56L,0x94c855ea57b8ab70L, + 0xdcdb9dae6f7879baL } }, + /* 5 << 28 */ + { { 0x7bdff8c2019f2a59L,0xb3ce5bb3cb4fbc74L,0xea907f688a9173ddL, + 0x6cd3d0d395a75439L }, + { 0x92ecc4d6efed021cL,0x09a9f9b06a77339aL,0x87ca6b157188c64aL, + 0x10c2996844899158L } }, + /* 6 << 28 */ + { { 0x5859a229ed6e82efL,0x16f338e365ebaf4eL,0x0cd313875ead67aeL, + 0x1c73d22854ef0bb4L }, + { 0x4cb5513174a5c8c7L,0x01cd29707f69ad6aL,0xa04d00dde966f87eL, + 0xd96fe4470b7b0321L } }, + /* 7 << 28 */ + { { 0x342ac06e88fbd381L,0x02cd4a845c35a493L,0xe8fa89de54f1bbcdL, + 0x341d63672575ed4cL }, + { 0xebe357fbd238202bL,0x600b4d1aa984ead9L,0xc35c9f4452436ea0L, + 0x96fe0a39a370751bL } }, + /* 8 << 28 */ + { { 0x4c4f07367f636a38L,0x9f943fb70e76d5cbL,0xb03510baa8b68b8bL, + 0xc246780a9ed07a1fL }, + { 0x3c0514156d549fc2L,0xc2953f31607781caL,0x955e2c69d8d95413L, + 0xb300fadc7bd282e3L } }, + /* 9 << 28 */ + { { 0x81fe7b5087e9189fL,0xdb17375cf42dda27L,0x22f7d896cf0a5904L, + 0xa0e57c5aebe348e6L }, + { 0xa61011d3f40e3c80L,0xb11893218db705c5L,0x4ed9309e50fedec3L, + 0xdcf14a104d6d5c1dL } }, + /* 10 << 28 */ + { { 0x056c265b55691342L,0xe8e0850491049dc7L,0x131329f5c9bae20aL, + 0x96c8b3e8d9dccdb4L }, + { 0x8c5ff838fb4ee6b4L,0xfc5a9aeb41e8ccf0L,0x7417b764fae050c6L, + 0x0953c3d700452080L } }, + /* 11 << 28 */ + { { 0x2137268238dfe7e8L,0xea417e152bb79d4bL,0x59641f1c76e7cf2dL, + 0x271e3059ea0bcfccL }, + { 0x624c7dfd7253ecbdL,0x2f552e254fca6186L,0xcbf84ecd4d866e9cL, + 0x73967709f68d4610L } }, + /* 12 << 28 */ + { { 0xa14b1163c27901b4L,0xfd9236e0899b8bf3L,0x42b091eccbc6da0aL, + 0xbb1dac6f5ad1d297L }, + { 0x80e61d53a91cf76eL,0x4110a412d31f1ee7L,0x2d87c3ba13efcf77L, + 0x1f374bb4df450d76L } }, + /* 13 << 28 */ + { { 0x5e78e2f20d188dabL,0xe3968ed0f4b885efL,0x46c0568e7314570fL, + 0x3161633801170521L }, + { 0x18e1e7e24f0c8afeL,0x4caa75ffdeea78daL,0x82db67f27c5d8a51L, + 0x36a44d866f505370L } }, + /* 14 << 28 */ + { { 0xd72c5bda0333974fL,0x5db516ae27a70146L,0x34705281210ef921L, + 0xbff17a8f0c9c38e5L }, + { 0x78f4814e12476da1L,0xc1e1661333c16980L,0x9e5b386f424d4bcaL, + 0x4c274e87c85740deL } }, + /* 15 << 28 */ + { { 0xb6a9b88d6c2f5226L,0x14d1b944550d7ca8L,0x580c85fc1fc41709L, + 0xc1da368b54c6d519L }, + { 0x2b0785ced5113cf7L,0x0670f6335a34708fL,0x46e2376715cc3f88L, + 0x1b480cfa50c72c8fL } }, + /* 16 << 28 */ + { { 0x202886024147519aL,0xd0981eac26b372f0L,0xa9d4a7caa785ebc8L, + 0xd953c50ddbdf58e9L }, + { 0x9d6361ccfd590f8fL,0x72e9626b44e6c917L,0x7fd9611022eb64cfL, + 0x863ebb7e9eb288f3L } }, + /* 17 << 28 */ + { { 0x6e6ab7616aca8ee7L,0x97d10b39d7b40358L,0x1687d3771e5feb0dL, + 0xc83e50e48265a27aL }, + { 0x8f75a9fec954b313L,0xcc2e8f47310d1f61L,0xf5ba81c56557d0e0L, + 0x25f9680c3eaf6207L } }, + /* 18 << 28 */ + { { 0xf95c66094354080bL,0x5225bfa57bf2fe1cL,0xc5c004e25c7d98faL, + 0x3561bf1c019aaf60L }, + { 0x5e6f9f17ba151474L,0xdec2f934b04f6ecaL,0x64e368a1269acb1eL, + 0x1332d9e40cdda493L } }, + /* 19 << 28 */ + { { 0x60d6cf69df23de05L,0x66d17da2009339a0L,0x9fcac9850a693923L, + 0xbcf057fced7c6a6dL }, + { 0xc3c5c8c5f0b5662cL,0x25318dd8dcba4f24L,0x60e8cb75082b69ffL, + 0x7c23b3ee1e728c01L } }, + /* 20 << 28 */ + { { 0x15e10a0a097e4403L,0xcb3d0a8619854665L,0x88d8e211d67d4826L, + 0xb39af66e0b9d2839L }, + { 0xa5f94588bd475ca8L,0xe06b7966c077b80bL,0xfedb1485da27c26cL, + 0xd290d33afe0fd5e0L } }, + /* 21 << 28 */ + { { 0xa40bcc47f34fb0faL,0xb4760cc81fb1ab09L,0x8fca0993a273bfe3L, + 0x13e4fe07f70b213cL }, + { 0x3bcdb992fdb05163L,0x8c484b110c2b19b6L,0x1acb815faaf2e3e2L, + 0xc6905935b89ff1b4L } }, + /* 22 << 28 */ + { { 0xb2ad6f9d586e74e1L,0x488883ad67b80484L,0x758aa2c7369c3ddbL, + 0x8ab74e699f9afd31L }, + { 0x10fc2d285e21beb1L,0x3484518a318c42f9L,0x377427dc53cf40c3L, + 0x9de0781a391bc1d9L } }, + /* 23 << 28 */ + { { 0x8faee858693807e1L,0xa38653274e81ccc7L,0x02c30ff26f835b84L, + 0xb604437b0d3d38d4L }, + { 0xb3fc8a985ca1823dL,0xb82f7ec903be0324L,0xee36d761cf684a33L, + 0x5a01df0e9f29bf7dL } }, + /* 24 << 28 */ + { { 0x686202f31306583dL,0x05b10da0437c622eL,0xbf9aaa0f076a7bc8L, + 0x25e94efb8f8f4e43L }, + { 0x8a35c9b7fa3dc26dL,0xe0e5fb9396ff03c5L,0xa77e3843ebc394ceL, + 0xcede65958361de60L } }, + /* 25 << 28 */ + { { 0xd27c22f6a1993545L,0xab01cc3624d671baL,0x63fa2877a169c28eL, + 0x925ef9042eb08376L }, + { 0x3b2fa3cf53aa0b32L,0xb27beb5b71c49d7aL,0xb60e1834d105e27fL, + 0xd60897884f68570dL } }, + /* 26 << 28 */ + { { 0x23094ce0d6fbc2acL,0x738037a1815ff551L,0xda73b1bb6bef119cL, + 0xdcf6c430eef506baL }, + { 0x00e4fe7be3ef104aL,0xebdd9a2c0a065628L,0x853a81c38792043eL, + 0x22ad6eceb3b59108L } }, + /* 27 << 28 */ + { { 0x9fb813c039cd297dL,0x8ec7e16e05bda5d9L,0x2834797c0d104b96L, + 0xcc11a2e77c511510L }, + { 0x96ca5a5396ee6380L,0x054c8655cea38742L,0xb5946852d54dfa7dL, + 0x97c422e71f4ab207L } }, + /* 28 << 28 */ + { { 0xbf9075090c22b540L,0x2cde42aab7c267d4L,0xba18f9ed5ab0d693L, + 0x3ba62aa66e4660d9L }, + { 0xb24bf97bab9ea96aL,0x5d039642e3b60e32L,0x4e6a45067c4d9bd5L, + 0x666c5b9e7ed4a6a4L } }, + /* 29 << 28 */ + { { 0xfa3fdcd98edbd7ccL,0x4660bb87c6ccd753L,0x9ae9082021e6b64fL, + 0x8a56a713b36bfb3fL }, + { 0xabfce0965726d47fL,0x9eed01b20b1a9a7fL,0x30e9cad44eb74a37L, + 0x7b2524cc53e9666dL } }, + /* 30 << 28 */ + { { 0x6a29683b8f4b002fL,0xc2200d7a41f4fc20L,0xcf3af47a3a338accL, + 0x6539a4fbe7128975L }, + { 0xcec31c14c33c7fcfL,0x7eb6799bc7be322bL,0x119ef4e96646f623L, + 0x7b7a26a554d7299bL } }, + /* 31 << 28 */ + { { 0xcb37f08d403f46f2L,0x94b8fc431a0ec0c7L,0xbb8514e3c332142fL, + 0xf3ed2c33e80d2a7aL }, + { 0x8d2080afb639126cL,0xf7b6be60e3553adeL,0x3950aa9f1c7e2b09L, + 0x847ff9586410f02bL } }, + /* 32 << 28 */ + { { 0x877b7cf5678a31b0L,0xd50301ae3998b620L,0x734257c5c00fb396L, + 0xf9fb18a004e672a6L }, + { 0xff8bd8ebe8758851L,0x1e64e4c65d99ba44L,0x4b8eaedf7dfd93b7L, + 0xba2f2a9804e76b8cL } }, + /* 33 << 28 */ + { { 0x7d790cbae8053433L,0xc8e725a03d2c9585L,0x58c5c476cdd8f5edL, + 0xd106b952efa9fe1dL }, + { 0x3c5c775b0eff13a9L,0x242442bae057b930L,0xe9f458d4c9b70cbdL, + 0x69b71448a3cdb89aL } }, + /* 34 << 28 */ + { { 0x41ee46f60e2ed742L,0x573f104540067493L,0xb1e154ff9d54c304L, + 0x2ad0436a8d3a7502L }, + { 0xee4aaa2d431a8121L,0xcd38b3ab886f11edL,0x57d49ea6034a0eb7L, + 0xd2b773bdf7e85e58L } }, + /* 35 << 28 */ + { { 0x4a559ac49b5c1f14L,0xc444be1a3e54df2bL,0x13aad704eda41891L, + 0xcd927bec5eb5c788L }, + { 0xeb3c8516e48c8a34L,0x1b7ac8124b546669L,0x1815f896594df8ecL, + 0x87c6a79c79227865L } }, + /* 36 << 28 */ + { { 0xae02a2f09b56ddbdL,0x1339b5ac8a2f1cf3L,0xf2b569c7839dff0dL, + 0xb0b9e864fee9a43dL }, + { 0x4ff8ca4177bb064eL,0x145a2812fd249f63L,0x3ab7beacf86f689aL, + 0x9bafec2701d35f5eL } }, + /* 37 << 28 */ + { { 0x28054c654265aa91L,0xa4b18304035efe42L,0x6887b0e69639dec7L, + 0xf4b8f6ad3d52aea5L }, + { 0xfb9293cc971a8a13L,0x3f159e5d4c934d07L,0x2c50e9b109acbc29L, + 0x08eb65e67154d129L } }, + /* 38 << 28 */ + { { 0x4feff58930b75c3eL,0x0bb82fe294491c93L,0xd8ac377a89af62bbL, + 0xd7b514909685e49fL }, + { 0xabca9a7b04497f19L,0x1b35ed0a1a7ad13fL,0x6b601e213ec86ed6L, + 0xda91fcb9ce0c76f1L } }, + /* 39 << 28 */ + { { 0x9e28507bd7ab27e1L,0x7c19a55563945b7bL,0x6b43f0a1aafc9827L, + 0x443b4fbd3aa55b91L }, + { 0x962b2e656962c88fL,0x139da8d4ce0db0caL,0xb93f05dd1b8d6c4fL, + 0x779cdff7180b9824L } }, + /* 40 << 28 */ + { { 0xbba23fddae57c7b7L,0x345342f21b932522L,0xfd9c80fe556d4aa3L, + 0xa03907ba6525bb61L }, + { 0x38b010e1ff218933L,0xc066b654aa52117bL,0x8e14192094f2e6eaL, + 0x66a27dca0d32f2b2L } }, + /* 41 << 28 */ + { { 0x69c7f993048b3717L,0xbf5a989ab178ae1cL,0x49fa9058564f1d6bL, + 0x27ec6e15d31fde4eL }, + { 0x4cce03737276e7fcL,0x64086d7989d6bf02L,0x5a72f0464ccdd979L, + 0x909c356647775631L } }, + /* 42 << 28 */ + { { 0x1c07bc6b75dd7125L,0xb4c6bc9787a0428dL,0x507ece52fdeb6b9dL, + 0xfca56512b2c95432L }, + { 0x15d97181d0e8bd06L,0x384dd317c6bb46eaL,0x5441ea203952b624L, + 0xbcf70dee4e7dc2fbL } }, + /* 43 << 28 */ + { { 0x372b016e6628e8c3L,0x07a0d667b60a7522L,0xcf05751b0a344ee2L, + 0x0ec09a48118bdeecL }, + { 0x6e4b3d4ed83dce46L,0x43a6316d99d2fc6eL,0xa99d898956cf044cL, + 0x7c7f4454ae3e5fb7L } }, + /* 44 << 28 */ + { { 0xb2e6b121fbabbe92L,0x281850fbe1330076L,0x093581ec97890015L, + 0x69b1dded75ff77f5L }, + { 0x7cf0b18fab105105L,0x953ced31a89ccfefL,0x3151f85feb914009L, + 0x3c9f1b8788ed48adL } }, + /* 45 << 28 */ + { { 0xc9aba1a14a7eadcbL,0x928e7501522e71cfL,0xeaede7273a2e4f83L, + 0x467e10d11ce3bbd3L }, + { 0xf3442ac3b955dcf0L,0xba96307dd3d5e527L,0xf763a10efd77f474L, + 0x5d744bd06a6e1ff0L } }, + /* 46 << 28 */ + { { 0xd287282aa777899eL,0xe20eda8fd03f3cdeL,0x6a7e75bb50b07d31L, + 0x0b7e2a946f379de4L }, + { 0x31cb64ad19f593cfL,0x7b1a9e4f1e76ef1dL,0xe18c9c9db62d609cL, + 0x439bad6de779a650L } }, + /* 47 << 28 */ + { { 0x219d9066e032f144L,0x1db632b8e8b2ec6aL,0xff0d0fd4fda12f78L, + 0x56fb4c2d2a25d265L }, + { 0x5f4e2ee1255a03f1L,0x61cd6af2e96af176L,0xe0317ba8d068bc97L, + 0x927d6bab264b988eL } }, + /* 48 << 28 */ + { { 0xa18f07e0e90fb21eL,0x00fd2b80bba7fca1L,0x20387f2795cd67b5L, + 0x5b89a4e7d39707f7L }, + { 0x8f83ad3f894407ceL,0xa0025b946c226132L,0xc79563c7f906c13bL, + 0x5f548f314e7bb025L } }, + /* 49 << 28 */ + { { 0x2b4c6b8feac6d113L,0xa67e3f9c0e813c76L,0x3982717c3fe1f4b9L, + 0x5886581926d8050eL }, + { 0x99f3640cf7f06f20L,0xdc6102162a66ebc2L,0x52f2c175767a1e08L, + 0x05660e1a5999871bL } }, + /* 50 << 28 */ + { { 0x6b0f17626d3c4693L,0xf0e7d62737ed7beaL,0xc51758c7b75b226dL, + 0x40a886281f91613bL }, + { 0x889dbaa7bbb38ce0L,0xe0404b65bddcad81L,0xfebccd3a8bc9671fL, + 0xfbf9a357ee1f5375L } }, + /* 51 << 28 */ + { { 0x5dc169b028f33398L,0xb07ec11d72e90f65L,0xae7f3b4afaab1eb1L, + 0xd970195e5f17538aL }, + { 0x52b05cbe0181e640L,0xf5debd622643313dL,0x761481545df31f82L, + 0x23e03b333a9e13c5L } }, + /* 52 << 28 */ + { { 0xff7589494fde0c1fL,0xbf8a1abee5b6ec20L,0x702278fb87e1db6cL, + 0xc447ad7a35ed658fL }, + { 0x48d4aa3803d0ccf2L,0x80acb338819a7c03L,0x9bc7c89e6e17ceccL, + 0x46736b8b03be1d82L } }, + /* 53 << 28 */ + { { 0xd65d7b60c0432f96L,0xddebe7a3deb5442fL,0x79a253077dff69a2L, + 0x37a56d9402cf3122L }, + { 0x8bab8aedf2350d0aL,0x13c3f276037b0d9aL,0xc664957c44c65caeL, + 0x88b44089c2e71a88L } }, + /* 54 << 28 */ + { { 0xdb88e5a35cb02664L,0x5d4c0bf18686c72eL,0xea3d9b62a682d53eL, + 0x9b605ef40b2ad431L }, + { 0x71bac202c69645d0L,0xa115f03a6a1b66e7L,0xfe2c563a158f4dc4L, + 0xf715b3a04d12a78cL } }, + /* 55 << 28 */ + { { 0x8f7f0a48d413213aL,0x2035806dc04becdbL,0xecd34a995d8587f5L, + 0x4d8c30799f6d3a71L }, + { 0x1b2a2a678d95a8f6L,0xc58c9d7df2110d0dL,0xdeee81d5cf8fba3fL, + 0xa42be3c00c7cdf68L } }, + /* 56 << 28 */ + { { 0x2126f742d43b5eaaL,0x054a0766dfa59b85L,0x9d0d5e36126bfd45L, + 0xa1f8fbd7384f8a8fL }, + { 0x317680f5d563fcccL,0x48ca5055f280a928L,0xe00b81b227b578cfL, + 0x10aad9182994a514L } }, + /* 57 << 28 */ + { { 0xd9e07b62b7bdc953L,0x9f0f6ff25bc086ddL,0x09d1ccff655eee77L, + 0x45475f795bef7df1L }, + { 0x3faa28fa86f702ccL,0x92e609050f021f07L,0xe9e629687f8fa8c6L, + 0xbd71419af036ea2cL } }, + /* 58 << 28 */ + { { 0x171ee1cc6028da9aL,0x5352fe1ac251f573L,0xf8ff236e3fa997f4L, + 0xd831b6c9a5749d5fL }, + { 0x7c872e1de350e2c2L,0xc56240d91e0ce403L,0xf9deb0776974f5cbL, + 0x7d50ba87961c3728L } }, + /* 59 << 28 */ + { { 0xd6f894265a3a2518L,0xcf817799c6303d43L,0x510a0471619e5696L, + 0xab049ff63a5e307bL }, + { 0xe4cdf9b0feb13ec7L,0xd5e971179d8ff90cL,0xf6f64d069afa96afL, + 0x00d0bf5e9d2012a2L } }, + /* 60 << 28 */ + { { 0xe63f301f358bcdc0L,0x07689e990a9d47f8L,0x1f689e2f4f43d43aL, + 0x4d542a1690920904L }, + { 0xaea293d59ca0a707L,0xd061fe458ac68065L,0x1033bf1b0090008cL, + 0x29749558c08a6db6L } }, + /* 61 << 28 */ + { { 0x74b5fc59c1d5d034L,0xf712e9f667e215e0L,0xfd520cbd860200e6L, + 0x0229acb43ea22588L }, + { 0x9cd1e14cfff0c82eL,0x87684b6259c69e73L,0xda85e61c96ccb989L, + 0x2d5dbb02a3d06493L } }, + /* 62 << 28 */ + { { 0xf22ad33ae86b173cL,0xe8e41ea5a79ff0e3L,0x01d2d725dd0d0c10L, + 0x31f39088032d28f9L }, + { 0x7b3f71e17829839eL,0x0cf691b44502ae58L,0xef658dbdbefc6115L, + 0xa5cd6ee5b3ab5314L } }, + /* 63 << 28 */ + { { 0x206c8d7b5f1d2347L,0x794645ba4cc2253aL,0xd517d8ff58389e08L, + 0x4fa20dee9f847288L }, + { 0xeba072d8d797770aL,0x7360c91dbf429e26L,0x7200a3b380af8279L, + 0x6a1c915082dadce3L } }, + /* 64 << 28 */ + { { 0x0ee6d3a7c35d8794L,0x042e65580356bae5L,0x9f59698d643322fdL, + 0x9379ae1550a61967L }, + { 0x64b9ae62fcc9981eL,0xaed3d6316d2934c6L,0x2454b3025e4e65ebL, + 0xab09f647f9950428L } }, + /* 0 << 35 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 35 */ + { { 0xb2083a1222248accL,0x1f6ec0ef3264e366L,0x5659b7045afdee28L, + 0x7a823a40e6430bb5L }, + { 0x24592a04e1900a79L,0xcde09d4ac9ee6576L,0x52b6463f4b5ea54aL, + 0x1efe9ed3d3ca65a7L } }, + /* 2 << 35 */ + { { 0xe27a6dbe305406ddL,0x8eb7dc7fdd5d1957L,0xf54a6876387d4d8fL, + 0x9c479409c7762de4L }, + { 0xbe4d5b5d99b30778L,0x25380c566e793682L,0x602d37f3dac740e3L, + 0x140deabe1566e4aeL } }, + /* 3 << 35 */ + { { 0x4481d067afd32acfL,0xd8f0fccae1f71ccfL,0xd208dd0cb596f2daL, + 0xd049d7309aad93f9L }, + { 0xc79f263d42ab580eL,0x09411bb123f707b4L,0x8cfde1ff835e0edaL, + 0x7270749090f03402L } }, + /* 4 << 35 */ + { { 0xeaee6126c49a861eL,0x024f3b65e14f0d06L,0x51a3f1e8c69bfc17L, + 0xc3c3a8e9a7686381L }, + { 0x3400752cb103d4c8L,0x02bc46139218b36bL,0xc67f75eb7651504aL, + 0xd6848b56d02aebfaL } }, + /* 5 << 35 */ + { { 0xbd9802e6c30fa92bL,0x5a70d96d9a552784L,0x9085c4ea3f83169bL, + 0xfa9423bb06908228L }, + { 0x2ffebe12fe97a5b9L,0x85da604971b99118L,0x9cbc2f7f63178846L, + 0xfd96bc709153218eL } }, + /* 6 << 35 */ + { { 0x958381db1782269bL,0xae34bf792597e550L,0xbb5c60645f385153L, + 0x6f0e96afe3088048L }, + { 0xbf6a021577884456L,0xb3b5688c69310ea7L,0x17c9429504fad2deL, + 0xe020f0e517896d4dL } }, + /* 7 << 35 */ + { { 0x730ba0ab0976505fL,0x567f6813095e2ec5L,0x470620106331ab71L, + 0x72cfa97741d22b9fL }, + { 0x33e55ead8a2373daL,0xa8d0d5f47ba45a68L,0xba1d8f9c03029d15L, + 0x8f34f1ccfc55b9f3L } }, + /* 8 << 35 */ + { { 0xcca4428dbbe5a1a9L,0x8187fd5f3126bd67L,0x0036973a48105826L, + 0xa39b6663b8bd61a0L }, + { 0x6d42deef2d65a808L,0x4969044f94636b19L,0xf611ee47dd5d564cL, + 0x7b2f3a49d2873077L } }, + /* 9 << 35 */ + { { 0x94157d45300eb294L,0x2b2a656e169c1494L,0xc000dd76d3a47aa9L, + 0xa2864e4fa6243ea4L }, + { 0x82716c47db89842eL,0x12dfd7d761479fb7L,0x3b9a2c56e0b2f6dcL, + 0x46be862ad7f85d67L } }, + /* 10 << 35 */ + { { 0x03b0d8dd0f82b214L,0x460c34f9f103cbc6L,0xf32e5c0318d79e19L, + 0x8b8888baa84117f8L }, + { 0x8f3c37dcc0722677L,0x10d21be91c1c0f27L,0xd47c8468e0f7a0c6L, + 0x9bf02213adecc0e0L } }, + /* 11 << 35 */ + { { 0x0baa7d1242b48b99L,0x1bcb665d48424096L,0x8b847cd6ebfb5cfbL, + 0x87c2ae569ad4d10dL }, + { 0xf1cbb1220de36726L,0xe7043c683fdfbd21L,0x4bd0826a4e79d460L, + 0x11f5e5984bd1a2cbL } }, + /* 12 << 35 */ + { { 0x97554160b7fe7b6eL,0x7d16189a400a3fb2L,0xd73e9beae328ca1eL, + 0x0dd04b97e793d8ccL }, + { 0xa9c83c9b506db8ccL,0x5cd47aaecf38814cL,0x26fc430db64b45e6L, + 0x079b5499d818ea84L } }, + /* 13 << 35 */ + { { 0xebb01102c1c24a3bL,0xca24e5681c161c1aL,0x103eea6936f00a4aL, + 0x9ad76ee876176c7bL }, + { 0x97451fc2538e0ff7L,0x94f898096604b3b0L,0x6311436e3249cfd7L, + 0x27b4a7bd41224f69L } }, + /* 14 << 35 */ + { { 0x03b5d21ae0ac2941L,0x279b0254c2d31937L,0x3307c052cac992d0L, + 0x6aa7cb92efa8b1f3L }, + { 0x5a1825800d37c7a5L,0x13380c37342d5422L,0x92ac2d66d5d2ef92L, + 0x035a70c9030c63c6L } }, + /* 15 << 35 */ + { { 0xc16025dd4ce4f152L,0x1f419a71f9df7c06L,0x6d5b221491e4bb14L, + 0xfc43c6cc839fb4ceL }, + { 0x49f06591925d6b2dL,0x4b37d9d362186598L,0x8c54a971d01b1629L, + 0xe1a9c29f51d50e05L } }, + /* 16 << 35 */ + { { 0x5109b78571ba1861L,0x48b22d5cd0c8f93dL,0xe8fa84a78633bb93L, + 0x53fba6ba5aebbd08L }, + { 0x7ff27df3e5eea7d8L,0x521c879668ca7158L,0xb9d5133bce6f1a05L, + 0x2d50cd53fd0ebee4L } }, + /* 17 << 35 */ + { { 0xc82115d6c5a3ef16L,0x993eff9dba079221L,0xe4da2c5e4b5da81cL, + 0x9a89dbdb8033fd85L }, + { 0x60819ebf2b892891L,0x53902b215d14a4d5L,0x6ac35051d7fda421L, + 0xcc6ab88561c83284L } }, + /* 18 << 35 */ + { { 0x14eba133f74cff17L,0x240aaa03ecb813f2L,0xcfbb65406f665beeL, + 0x084b1fe4a425ad73L }, + { 0x009d5d16d081f6a6L,0x35304fe8eef82c90L,0xf20346d5aa9eaa22L, + 0x0ada9f07ac1c91e3L } }, + /* 19 << 35 */ + { { 0xa6e21678968a6144L,0x54c1f77c07b31a1eL,0xd6bb787e5781fbe1L, + 0x61bd2ee0e31f1c4aL }, + { 0xf25aa1e9781105fcL,0x9cf2971f7b2f8e80L,0x26d15412cdff919bL, + 0x01db4ebe34bc896eL } }, + /* 20 << 35 */ + { { 0x7d9b3e23b40df1cfL,0x5933737394e971b4L,0xbf57bd14669cf921L, + 0x865daedf0c1a1064L }, + { 0x3eb70bd383279125L,0xbc3d5b9f34ecdaabL,0x91e3ed7e5f755cafL, + 0x49699f54d41e6f02L } }, + /* 21 << 35 */ + { { 0x185770e1d4a7a15bL,0x08f3587aeaac87e7L,0x352018db473133eaL, + 0x674ce71904fd30fcL }, + { 0x7b8d9835088b3e0eL,0x7a0356a95d0d47a1L,0x9d9e76596474a3c4L, + 0x61ea48a7ff66966cL } }, + /* 22 << 35 */ + { { 0x304177580f3e4834L,0xfdbb21c217a9afcbL,0x756fa17f2f9a67b3L, + 0x2a6b2421a245c1a8L }, + { 0x64be27944af02291L,0xade465c62a5804feL,0x8dffbd39a6f08fd7L, + 0xc4efa84caa14403bL } }, + /* 23 << 35 */ + { { 0xa1b91b2a442b0f5cL,0xb748e317cf997736L,0x8d1b62bfcee90e16L, + 0x907ae2710b2078c0L }, + { 0xdf31534b0c9bcdddL,0x043fb05439adce83L,0x99031043d826846aL, + 0x61a9c0d6b144f393L } }, + /* 24 << 35 */ + { { 0xdab4804647718427L,0xdf17ff9b6e830f8bL,0x408d7ee8e49a1347L, + 0x6ac71e2391c1d4aeL }, + { 0xc8cbb9fd1defd73cL,0x19840657bbbbfec5L,0x39db1cb59e7ef8eaL, + 0x78aa829664105f30L } }, + /* 25 << 35 */ + { { 0xa3d9b7f0a3738c29L,0x0a2f235abc3250a3L,0x55e506f6445e4cafL, + 0x0974f73d33475f7aL }, + { 0xd37dbba35ba2f5a8L,0x542c6e636af40066L,0x26d99b53c5d73e2cL, + 0x06060d7d6c3ca33eL } }, + /* 26 << 35 */ + { { 0xcdbef1c2065fef4aL,0x77e60f7dfd5b92e3L,0xd7c549f026708350L, + 0x201b3ad034f121bfL }, + { 0x5fcac2a10334fc14L,0x8a9a9e09344552f6L,0x7dd8a1d397653082L, + 0x5fc0738f79d4f289L } }, + /* 27 << 35 */ + { { 0x787d244d17d2d8c3L,0xeffc634570830684L,0x5ddb96dde4f73ae5L, + 0x8efb14b1172549a5L }, + { 0x6eb73eee2245ae7aL,0xbca4061eea11f13eL,0xb577421d30b01f5dL, + 0xaa688b24782e152cL } }, + /* 28 << 35 */ + { { 0x67608e71bd3502baL,0x4ef41f24b4de75a0L,0xb08dde5efd6125e5L, + 0xde484825a409543fL }, + { 0x1f198d9865cc2295L,0x428a37716e0edfa2L,0x4f9697a2adf35fc7L, + 0x01a43c79f7cac3c7L } }, + /* 29 << 35 */ + { { 0xb05d70590fd3659aL,0x8927f30cbb7f2d9aL,0x4023d1ac8cf984d3L, + 0x32125ed302897a45L }, + { 0xfb572dad3d414205L,0x73000ef2e3fa82a9L,0x4c0868e9f10a5581L, + 0x5b61fc676b0b3ca5L } }, + /* 30 << 35 */ + { { 0xc1258d5b7cae440cL,0x21c08b41402b7531L,0xf61a8955de932321L, + 0x3568faf82d1408afL }, + { 0x71b15e999ecf965bL,0xf14ed248e917276fL,0xc6f4caa1820cf9e2L, + 0x681b20b218d83c7eL } }, + /* 31 << 35 */ + { { 0x6cde738dc6c01120L,0x71db0813ae70e0dbL,0x95fc064474afe18cL, + 0x34619053129e2be7L }, + { 0x80615ceadb2a3b15L,0x0a49a19edb4c7073L,0x0e1b84c88fd2d367L, + 0xd74bf462033fb8aaL } }, + /* 32 << 35 */ + { { 0x889f6d65533ef217L,0x7158c7e4c3ca2e87L,0xfb670dfbdc2b4167L, + 0x75910a01844c257fL }, + { 0xf336bf07cf88577dL,0x22245250e45e2aceL,0x2ed92e8d7ca23d85L, + 0x29f8be4c2b812f58L } }, + /* 33 << 35 */ + { { 0xdd9ebaa7076fe12bL,0x3f2400cbae1537f9L,0x1aa9352817bdfb46L, + 0xc0f9843067883b41L }, + { 0x5590ede10170911dL,0x7562f5bb34d4b17fL,0xe1fa1df21826b8d2L, + 0xb40b796a6bd80d59L } }, + /* 34 << 35 */ + { { 0xd65bf1973467ba92L,0x8c9b46dbf70954b0L,0x97c8a0f30e78f15dL, + 0xa8f3a69a85a4c961L }, + { 0x4242660f61e4ce9bL,0xbf06aab36ea6790cL,0xc6706f8eec986416L, + 0x9e56dec19a9fc225L } }, + /* 35 << 35 */ + { { 0x527c46f49a9898d9L,0xd799e77b5633cdefL,0x24eacc167d9e4297L, + 0xabb61cea6b1cb734L }, + { 0xbee2e8a7f778443cL,0x3bb42bf129de2fe6L,0xcbed86a13003bb6fL, + 0xd3918e6cd781cdf6L } }, + /* 36 << 35 */ + { { 0x4bee32719a5103f1L,0x5243efc6f50eac06L,0xb8e122cb6adcc119L, + 0x1b7faa84c0b80a08L }, + { 0x32c3d1bd6dfcd08cL,0x129dec4e0be427deL,0x98ab679c1d263c83L, + 0xafc83cb7cef64effL } }, + /* 37 << 35 */ + { { 0x85eb60882fa6be76L,0x892585fb1328cbfeL,0xc154d3edcf618ddaL, + 0xc44f601b3abaf26eL }, + { 0x7bf57d0b2be1fdfdL,0xa833bd2d21137feeL,0x9353af362db591a8L, + 0xc76f26dc5562a056L } }, + /* 38 << 35 */ + { { 0x1d87e47d3fdf5a51L,0x7afb5f9355c9cab0L,0x91bbf58f89e0586eL, + 0x7c72c0180d843709L }, + { 0xa9a5aafb99b5c3dcL,0xa48a0f1d3844aeb0L,0x7178b7ddb667e482L, + 0x453985e96e23a59aL } }, + /* 39 << 35 */ + { { 0x4a54c86001b25dd8L,0x0dd37f48fb897c8aL,0x5f8aa6100ea90cd9L, + 0xc8892c6816d5830dL }, + { 0xeb4befc0ef514ca5L,0x478eb679e72c9ee6L,0x9bca20dadbc40d5fL, + 0xf015de21dde4f64aL } }, + /* 40 << 35 */ + { { 0xaa6a4de0eaf4b8a5L,0x68cfd9ca4bc60e32L,0x668a4b017fd15e70L, + 0xd9f0694af27dc09dL }, + { 0xf6c3cad5ba708bcdL,0x5cd2ba695bb95c2aL,0xaa28c1d333c0a58fL, + 0x23e274e3abc77870L } }, + /* 41 << 35 */ + { { 0x44c3692ddfd20a4aL,0x091c5fd381a66653L,0x6c0bb69109a0757dL, + 0x9072e8b9667343eaL }, + { 0x31d40eb080848becL,0x95bd480a79fd36ccL,0x01a77c6165ed43f5L, + 0xafccd1272e0d40bfL } }, + /* 42 << 35 */ + { { 0xeccfc82d1cc1884bL,0xc85ac2015d4753b4L,0xc7a6caac658e099fL, + 0xcf46369e04b27390L }, + { 0xe2e7d049506467eaL,0x481b63a237cdecccL,0x4029abd8ed80143aL, + 0x28bfe3c7bcb00b88L } }, + /* 43 << 35 */ + { { 0x3bec10090643d84aL,0x885f3668abd11041L,0xdb02432cf83a34d6L, + 0x32f7b360719ceebeL }, + { 0xf06c7837dad1fe7aL,0x60a157a95441a0b0L,0x704970e9e2d47550L, + 0xcd2bd553271b9020L } }, + /* 44 << 35 */ + { { 0xff57f82f33e24a0bL,0x9cbee23ff2565079L,0x16353427eb5f5825L, + 0x276feec4e948d662L }, + { 0xd1b62bc6da10032bL,0x718351ddf0e72a53L,0x934520762420e7baL, + 0x96368fff3a00118dL } }, + /* 45 << 35 */ + { { 0x00ce2d26150a49e4L,0x0c28b6363f04706bL,0xbad65a4658b196d0L, + 0x6c8455fcec9f8b7cL }, + { 0xe90c895f2d71867eL,0x5c0be31bedf9f38cL,0x2a37a15ed8f6ec04L, + 0x239639e78cd85251L } }, + /* 46 << 35 */ + { { 0xd89753159c7c4c6bL,0x603aa3c0d7409af7L,0xb8d53d0c007132fbL, + 0x68d12af7a6849238L }, + { 0xbe0607e7bf5d9279L,0x9aa50055aada74ceL,0xe81079cbba7e8ccbL, + 0x610c71d1a5f4ff5eL } }, + /* 47 << 35 */ + { { 0x9e2ee1a75aa07093L,0xca84004ba75da47cL,0x074d39513de75401L, + 0xf938f756bb311592L }, + { 0x9619761800a43421L,0x39a2536207bc78c8L,0x278f710a0a171276L, + 0xb28446ea8d1a8f08L } }, + /* 48 << 35 */ + { { 0x184781bfe3b6a661L,0x7751cb1de6d279f7L,0xf8ff95d6c59eb662L, + 0x186d90b758d3dea7L }, + { 0x0e4bb6c1dfb4f754L,0x5c5cf56b2b2801dcL,0xc561e4521f54564dL, + 0xb4fb8c60f0dd7f13L } }, + /* 49 << 35 */ + { { 0xf884963033ff98c7L,0x9619fffacf17769cL,0xf8090bf61bfdd80aL, + 0x14d9a149422cfe63L }, + { 0xb354c3606f6df9eaL,0xdbcf770d218f17eaL,0x207db7c879eb3480L, + 0x213dbda8559b6a26L } }, + /* 50 << 35 */ + { { 0xac4c200b29fc81b3L,0xebc3e09f171d87c1L,0x917995301481aa9eL, + 0x051b92e192e114faL }, + { 0xdf8f92e9ecb5537fL,0x44b1b2cc290c7483L,0xa711455a2adeb016L, + 0x964b685681a10c2cL } }, + /* 51 << 35 */ + { { 0x4f159d99cec03623L,0x05532225ef3271eaL,0xb231bea3c5ee4849L, + 0x57a54f507094f103L }, + { 0x3e2d421d9598b352L,0xe865a49c67412ab4L,0xd2998a251cc3a912L, + 0x5d0928080c74d65dL } }, + /* 52 << 35 */ + { { 0x73f459084088567aL,0xeb6b280e1f214a61L,0x8c9adc34caf0c13dL, + 0x39d12938f561fb80L }, + { 0xb2dc3a5ebc6edfb4L,0x7485b1b1fe4d210eL,0x062e0400e186ae72L, + 0x91e32d5c6eeb3b88L } }, + /* 53 << 35 */ + { { 0x6df574d74be59224L,0xebc88ccc716d55f3L,0x26c2e6d0cad6ed33L, + 0xc6e21e7d0d3e8b10L }, + { 0x2cc5840e5bcc36bbL,0x9292445e7da74f69L,0x8be8d3214e5193a8L, + 0x3ec236298df06413L } }, + /* 54 << 35 */ + { { 0xc7e9ae85b134defaL,0x6073b1d01bb2d475L,0xb9ad615e2863c00dL, + 0x9e29493d525f4ac4L }, + { 0xc32b1dea4e9acf4fL,0x3e1f01c8a50db88dL,0xb05d70ea04da916cL, + 0x714b0d0ad865803eL } }, + /* 55 << 35 */ + { { 0x4bd493fc9920cb5eL,0x5b44b1f792c7a3acL,0xa2a77293bcec9235L, + 0x5ee06e87cd378553L }, + { 0xceff8173da621607L,0x2bb03e4c99f5d290L,0x2945106aa6f734acL, + 0xb5056604d25c4732L } }, + /* 56 << 35 */ + { { 0x5945920ce079afeeL,0x686e17a06789831fL,0x5966bee8b74a5ae5L, + 0x38a673a21e258d46L }, + { 0xbd1cc1f283141c95L,0x3b2ecf4f0e96e486L,0xcd3aa89674e5fc78L, + 0x415ec10c2482fa7aL } }, + /* 57 << 35 */ + { { 0x1523441980503380L,0x513d917ad314b392L,0xb0b52f4e63caecaeL, + 0x07bf22ad2dc7780bL }, + { 0xe761e8a1e4306839L,0x1b3be9625dd7feaaL,0x4fe728de74c778f1L, + 0xf1fa0bda5e0070f6L } }, + /* 58 << 35 */ + { { 0x85205a316ec3f510L,0x2c7e4a14d2980475L,0xde3c19c06f30ebfdL, + 0xdb1c1f38d4b7e644L }, + { 0xfe291a755dce364aL,0xb7b22a3c058f5be3L,0x2cd2c30237fea38cL, + 0x2930967a2e17be17L } }, + /* 59 << 35 */ + { { 0x87f009de0c061c65L,0xcb014aacedc6ed44L,0x49bd1cb43bafb1ebL, + 0x81bd8b5c282d3688L }, + { 0x1cdab87ef01a17afL,0x21f37ac4e710063bL,0x5a6c567642fc8193L, + 0xf4753e7056a6015cL } }, + /* 60 << 35 */ + { { 0x020f795ea15b0a44L,0x8f37c8d78958a958L,0x63b7e89ba4b675b5L, + 0xb4fb0c0c0fc31aeaL }, + { 0xed95e639a7ff1f2eL,0x9880f5a3619614fbL,0xdeb6ff02947151abL, + 0x5bc5118ca868dcdbL } }, + /* 61 << 35 */ + { { 0xd8da20554c20cea5L,0xcac2776e14c4d69aL,0xcccb22c1622d599bL, + 0xa4ddb65368a9bb50L }, + { 0x2c4ff1511b4941b4L,0xe1ff19b46efba588L,0x35034363c48345e0L, + 0x45542e3d1e29dfc4L } }, + /* 62 << 35 */ + { { 0xf197cb91349f7aedL,0x3b2b5a008fca8420L,0x7c175ee823aaf6d8L, + 0x54dcf42135af32b6L }, + { 0x0ba1430727d6561eL,0x879d5ee4d175b1e2L,0xc7c4367399807db5L, + 0x77a544559cd55bcdL } }, + /* 63 << 35 */ + { { 0xe6c2ff130105c072L,0x18f7a99f8dda7da4L,0x4c3018200e2d35c1L, + 0x06a53ca0d9cc6c82L }, + { 0xaa21cc1ef1aa1d9eL,0x324143344a75b1e8L,0x2a6d13280ebe9fdcL, + 0x16bd173f98a4755aL } }, + /* 64 << 35 */ + { { 0xfbb9b2452133ffd9L,0x39a8b2f1830f1a20L,0x484bc97dd5a1f52aL, + 0xd6aebf56a40eddf8L }, + { 0x32257acb76ccdac6L,0xaf4d36ec1586ff27L,0x8eaa8863f8de7dd1L, + 0x0045d5cf88647c16L } }, + /* 0 << 42 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 42 */ + { { 0xa6f3d574c005979dL,0xc2072b426a40e350L,0xfca5c1568de2ecf9L, + 0xa8c8bf5ba515344eL }, + { 0x97aee555114df14aL,0xd4374a4dfdc5ec6bL,0x754cc28f2ca85418L, + 0x71cb9e27d3c41f78L } }, + /* 2 << 42 */ + { { 0x8910507903605c39L,0xf0843d9ea142c96cL,0xf374493416923684L, + 0x732caa2ffa0a2893L }, + { 0xb2e8c27061160170L,0xc32788cc437fbaa3L,0x39cd818ea6eda3acL, + 0xe2e942399e2b2e07L } }, + /* 3 << 42 */ + { { 0x6967d39b0260e52aL,0xd42585cc90653325L,0x0d9bd60521ca7954L, + 0x4fa2087781ed57b3L }, + { 0x60c1eff8e34a0bbeL,0x56b0040c84f6ef64L,0x28be2b24b1af8483L, + 0xb2278163f5531614L } }, + /* 4 << 42 */ + { { 0x8df275455922ac1cL,0xa7b3ef5ca52b3f63L,0x8e77b21471de57c4L, + 0x31682c10834c008bL }, + { 0xc76824f04bd55d31L,0xb6d1c08617b61c71L,0x31db0903c2a5089dL, + 0x9c092172184e5d3fL } }, + /* 5 << 42 */ + { { 0xdd7ced5bc00cc638L,0x1a2015eb61278fc2L,0x2e8e52886a37f8d6L, + 0xc457786fe79933adL }, + { 0xb3fe4cce2c51211aL,0xad9b10b224c20498L,0x90d87a4fd28db5e5L, + 0x698cd1053aca2fc3L } }, + /* 6 << 42 */ + { { 0x4f112d07e91b536dL,0xceb982f29eba09d6L,0x3c157b2c197c396fL, + 0xe23c2d417b66eb24L }, + { 0x480c57d93f330d37L,0xb3a4c8a179108debL,0x702388decb199ce5L, + 0x0b019211b944a8d4L } }, + /* 7 << 42 */ + { { 0x24f2a692840bb336L,0x7c353bdca669fa7bL,0xda20d6fcdec9c300L, + 0x625fbe2fa13a4f17L }, + { 0xa2b1b61adbc17328L,0x008965bfa9515621L,0x49690939c620ff46L, + 0x182dd27d8717e91cL } }, + /* 8 << 42 */ + { { 0x5ace5035ea6c3997L,0x54259aaac2610befL,0xef18bb3f3c80dd39L, + 0x6910b95b5fc3fa39L }, + { 0xfce2f51043e09aeeL,0xced56c9fa7675665L,0x10e265acd872db61L, + 0x6982812eae9fce69L } }, + /* 9 << 42 */ + { { 0x29be11c6ce800998L,0x72bb1752b90360d9L,0x2c1931975a4ad590L, + 0x2ba2f5489fc1dbc0L }, + { 0x7fe4eebbe490ebe0L,0x12a0a4cd7fae11c0L,0x7197cf81e903ba37L, + 0xcf7d4aa8de1c6dd8L } }, + /* 10 << 42 */ + { { 0x92af6bf43fd5684cL,0x2b26eecf80360aa1L,0xbd960f3000546a82L, + 0x407b3c43f59ad8feL }, + { 0x86cae5fe249c82baL,0x9e0faec72463744cL,0x87f551e894916272L, + 0x033f93446ceb0615L } }, + /* 11 << 42 */ + { { 0x1e5eb0d18be82e84L,0x89967f0e7a582fefL,0xbcf687d5a6e921faL, + 0xdfee4cf3d37a09baL }, + { 0x94f06965b493c465L,0x638b9a1c7635c030L,0x7666786466f05e9fL, + 0xccaf6808c04da725L } }, + /* 12 << 42 */ + { { 0xca2eb690768fccfcL,0xf402d37db835b362L,0x0efac0d0e2fdfcceL, + 0xefc9cdefb638d990L }, + { 0x2af12b72d1669a8bL,0x33c536bc5774ccbdL,0x30b21909fb34870eL, + 0xc38fa2f77df25acaL } }, + /* 13 << 42 */ + { { 0x74c5f02bbf81f3f5L,0x0525a5aeaf7e4581L,0x88d2aaba433c54aeL, + 0xed9775db806a56c5L }, + { 0xd320738ac0edb37dL,0x25fdb6ee66cc1f51L,0xac661d1710600d76L, + 0x931ec1f3bdd1ed76L } }, + /* 14 << 42 */ + { { 0x65c11d6219ee43f1L,0x5cd57c3e60829d97L,0xd26c91a3984be6e8L, + 0xf08d93098b0c53bdL }, + { 0x94bc9e5bc016e4eaL,0xd391683911d43d2bL,0x886c5ad773701155L, + 0xe037762620b00715L } }, + /* 15 << 42 */ + { { 0x7f01c9ecaa80ba59L,0x3083411a68538e51L,0x970370f1e88128afL, + 0x625cc3db91dec14bL }, + { 0xfef9666c01ac3107L,0xb2a8d577d5057ac3L,0xb0f2629992be5df7L, + 0xf579c8e500353924L } }, + /* 16 << 42 */ + { { 0xb8fa3d931341ed7aL,0x4223272ca7b59d49L,0x3dcb194783b8c4a4L, + 0x4e413c01ed1302e4L }, + { 0x6d999127e17e44ceL,0xee86bf7533b3adfbL,0xf6902fe625aa96caL, + 0xb73540e4e5aae47dL } }, + /* 17 << 42 */ + { { 0x32801d7b1b4a158cL,0xe571c99e27e2a369L,0x40cb76c010d9f197L, + 0xc308c2893167c0aeL }, + { 0xa6ef9dd3eb7958f2L,0xa7226dfc300879b1L,0x6cd0b3627edf0636L, + 0x4efbce6c7bc37eedL } }, + /* 18 << 42 */ + { { 0x75f92a058d699021L,0x586d4c79772566e3L,0x378ca5f1761ad23aL, + 0x650d86fc1465a8acL }, + { 0x7a4ed457842ba251L,0x6b65e3e642234933L,0xaf1543b731aad657L, + 0xa4cefe98cbfec369L } }, + /* 19 << 42 */ + { { 0xb587da909f47befbL,0x6562e9fb41312d13L,0xa691ea59eff1cefeL, + 0xcc30477a05fc4cf6L }, + { 0xa16324610b0ffd3dL,0xa1f16f3b5b355956L,0x5b148d534224ec24L, + 0xdc834e7bf977012aL } }, + /* 20 << 42 */ + { { 0x7bfc5e75b2c69dbcL,0x3aa77a2903c3da6cL,0xde0df03cca910271L, + 0xcbd5ca4a7806dc55L }, + { 0xe1ca58076db476cbL,0xfde15d625f37a31eL,0xf49af520f41af416L, + 0x96c5c5b17d342db5L } }, + /* 21 << 42 */ + { { 0x155c43b7eb4ceb9bL,0x2e9930104e77371aL,0x1d2987da675d43afL, + 0xef2bc1c08599fd72L }, + { 0x96894b7b9342f6b2L,0x201eadf27c8e71f0L,0xf3479d9f4a1f3efcL, + 0xe0f8a742702a9704L } }, + /* 22 << 42 */ + { { 0xeafd44b6b3eba40cL,0xf9739f29c1c1e0d0L,0x0091471a619d505eL, + 0xc15f9c969d7c263eL }, + { 0x5be4728583afbe33L,0xa3b6d6af04f1e092L,0xe76526b9751a9d11L, + 0x2ec5b26d9a4ae4d2L } }, + /* 23 << 42 */ + { { 0xeb66f4d902f6fb8dL,0x4063c56196912164L,0xeb7050c180ef3000L, + 0x288d1c33eaa5b3f0L }, + { 0xe87c68d607806fd8L,0xb2f7f9d54bbbf50fL,0x25972f3aac8d6627L, + 0xf854777410e8c13bL } }, + /* 24 << 42 */ + { { 0xcc50ef6c872b4a60L,0xab2a34a44613521bL,0x39c5c190983e15d1L, + 0x61dde5df59905512L }, + { 0xe417f6219f2275f3L,0x0750c8b6451d894bL,0x75b04ab978b0bdaaL, + 0x3bfd9fd4458589bdL } }, + /* 25 << 42 */ + { { 0xf1013e30ee9120b6L,0x2b51af9323a4743eL,0xea96ffae48d14d9eL, + 0x71dc0dbe698a1d32L }, + { 0x914962d20180cca4L,0x1ae60677c3568963L,0x8cf227b1437bc444L, + 0xc650c83bc9962c7aL } }, + /* 26 << 42 */ + { { 0x23c2c7ddfe7ccfc4L,0xf925c89d1b929d48L,0x4460f74b06783c33L, + 0xac2c8d49a590475aL }, + { 0xfb40b407b807bba0L,0x9d1e362d69ff8f3aL,0xa33e9681cbef64a4L, + 0x67ece5fa332fb4b2L } }, + /* 27 << 42 */ + { { 0x6900a99b739f10e3L,0xc3341ca9ff525925L,0xee18a626a9e2d041L, + 0xa5a8368529580dddL }, + { 0xf3470c819d7de3cdL,0xedf025862062cf9cL,0xf43522fac010edb0L, + 0x3031413513a4b1aeL } }, + /* 28 << 42 */ + { { 0xc792e02adb22b94bL,0x993d8ae9a1eaa45bL,0x8aad6cd3cd1e1c63L, + 0x89529ca7c5ce688aL }, + { 0x2ccee3aae572a253L,0xe02b643802a21efbL,0xa7091b6ec9430358L, + 0x06d1b1fa9d7db504L } }, + /* 29 << 42 */ + { { 0x58846d32c4744733L,0x40517c71379f9e34L,0x2f65655f130ef6caL, + 0x526e4488f1f3503fL }, + { 0x8467bd177ee4a976L,0x1d9dc913921363d1L,0xd8d24c33b069e041L, + 0x5eb5da0a2cdf7f51L } }, + /* 30 << 42 */ + { { 0x1c0f3cb1197b994fL,0x3c95a6c52843eae9L,0x7766ffc9a6097ea5L, + 0x7bea4093d723b867L }, + { 0xb48e1f734db378f9L,0x70025b00e37b77acL,0x943dc8e7af24ad46L, + 0xb98a15ac16d00a85L } }, + /* 31 << 42 */ + { { 0x3adc38ba2743b004L,0xb1c7f4f7334415eeL,0xea43df8f1e62d05aL, + 0x326189059d76a3b6L }, + { 0x2fbd0bb5a23a0f46L,0x5bc971db6a01918cL,0x7801d94ab4743f94L, + 0xb94df65e676ae22bL } }, + /* 32 << 42 */ + { { 0xaafcbfabaf95894cL,0x7b9bdc07276b2241L,0xeaf983625bdda48bL, + 0x5977faf2a3fcb4dfL }, + { 0xbed042ef052c4b5bL,0x9fe87f71067591f0L,0xc89c73ca22f24ec7L, + 0x7d37fa9ee64a9f1bL } }, + /* 33 << 42 */ + { { 0x2710841a15562627L,0x2c01a613c243b034L,0x1d135c562bc68609L, + 0xc2ca17158b03f1f6L }, + { 0xc9966c2d3eb81d82L,0xc02abf4a8f6df13eL,0x77b34bd78f72b43bL, + 0xaff6218f360c82b0L } }, + /* 34 << 42 */ + { { 0x0aa5726c8d55b9d2L,0xdc0adbe999e9bffbL,0x9097549cefb9e72aL, + 0x167557129dfb3111L }, + { 0xdd8bf984f26847f9L,0xbcb8e387dfb30cb7L,0xc1fd32a75171ef9cL, + 0x977f3fc7389b363fL } }, + /* 35 << 42 */ + { { 0x116eaf2bf4babda0L,0xfeab68bdf7113c8eL,0xd1e3f064b7def526L, + 0x1ac30885e0b3fa02L }, + { 0x1c5a6e7b40142d9dL,0x839b560330921c0bL,0x48f301fa36a116a3L, + 0x380e1107cfd9ee6dL } }, + /* 36 << 42 */ + { { 0x7945ead858854be1L,0x4111c12ecbd4d49dL,0xece3b1ec3a29c2efL, + 0x6356d4048d3616f5L }, + { 0x9f0d6a8f594d320eL,0x0989316df651ccd2L,0x6c32117a0f8fdde4L, + 0x9abe5cc5a26a9bbcL } }, + /* 37 << 42 */ + { { 0xcff560fb9723f671L,0x21b2a12d7f3d593cL,0xe4cb18da24ba0696L, + 0x186e2220c3543384L }, + { 0x722f64e088312c29L,0x94282a9917dc7752L,0x62467bbf5a85ee89L, + 0xf435c650f10076a0L } }, + /* 38 << 42 */ + { { 0xc9ff153943b3a50bL,0x7132130c1a53efbcL,0x31bfe063f7b0c5b7L, + 0xb0179a7d4ea994ccL }, + { 0x12d064b3c85f455bL,0x472593288f6e0062L,0xf64e590bb875d6d9L, + 0x22dd6225ad92bcc7L } }, + /* 39 << 42 */ + { { 0xb658038eb9c3bd6dL,0x00cdb0d6fbba27c8L,0x0c6813371062c45dL, + 0xd8515b8c2d33407dL }, + { 0xcb8f699e8cbb5ecfL,0x8c4347f8c608d7d8L,0x2c11850abb3e00dbL, + 0x20a8dafdecb49d19L } }, + /* 40 << 42 */ + { { 0xbd78148045ee2f40L,0x75e354af416b60cfL,0xde0b58a18d49a8c4L, + 0xe40e94e2fa359536L }, + { 0xbd4fa59f62accd76L,0x05cf466a8c762837L,0xb5abda99448c277bL, + 0x5a9e01bf48b13740L } }, + /* 41 << 42 */ + { { 0x9d457798326aad8dL,0xbdef4954c396f7e7L,0x6fb274a2c253e292L, + 0x2800bf0a1cfe53e7L }, + { 0x22426d3144438fd4L,0xef2339235e259f9aL,0x4188503c03f66264L, + 0x9e5e7f137f9fdfabL } }, + /* 42 << 42 */ + { { 0x565eb76c5fcc1abaL,0xea63254859b5bff8L,0x5587c087aab6d3faL, + 0x92b639ea6ce39c1bL }, + { 0x0706e782953b135cL,0x7308912e425268efL,0x599e92c7090e7469L, + 0x83b90f529bc35e75L } }, + /* 43 << 42 */ + { { 0x4750b3d0244975b3L,0xf3a4435811965d72L,0x179c67749c8dc751L, + 0xff18cdfed23d9ff0L }, + { 0xc40138332028e247L,0x96e280e2f3bfbc79L,0xf60417bdd0880a84L, + 0x263c9f3d2a568151L } }, + /* 44 << 42 */ + { { 0x36be15b32d2ce811L,0x846dc0c2f8291d21L,0x5cfa0ecb789fcfdbL, + 0x45a0beedd7535b9aL }, + { 0xec8e9f0796d69af1L,0x31a7c5b8599ab6dcL,0xd36d45eff9e2e09fL, + 0x3cf49ef1dcee954bL } }, + /* 45 << 42 */ + { { 0x6be34cf3086cff9bL,0x88dbd49139a3360fL,0x1e96b8cc0dbfbd1dL, + 0xc1e5f7bfcb7e2552L }, + { 0x0547b21428819d98L,0xc770dd9c7aea9dcbL,0xaef0d4c7041d68c8L, + 0xcc2b981813cb9ba8L } }, + /* 46 << 42 */ + { { 0x7fc7bc76fe86c607L,0x6b7b9337502a9a95L,0x1948dc27d14dab63L, + 0x249dd198dae047beL }, + { 0xe8356584a981a202L,0x3531dd183a893387L,0x1be11f90c85c7209L, + 0x93d2fe1ee2a52b5aL } }, + /* 47 << 42 */ + { { 0x8225bfe2ec6d6b97L,0x9cf6d6f4bd0aa5deL,0x911459cb54779f5fL, + 0x5649cddb86aeb1f3L }, + { 0x321335793f26ce5aL,0xc289a102550f431eL,0x559dcfda73b84c6fL, + 0x84973819ee3ac4d7L } }, + /* 48 << 42 */ + { { 0xb51e55e6f2606a82L,0xe25f706190f2fb57L,0xacef6c2ab1a4e37cL, + 0x864e359d5dcf2706L }, + { 0x479e6b187ce57316L,0x2cab25003a96b23dL,0xed4898628ef16df7L, + 0x2056538cef3758b5L } }, + /* 49 << 42 */ + { { 0xa7df865ef15d3101L,0x80c5533a61b553d7L,0x366e19974ed14294L, + 0x6620741fb3c0bcd6L }, + { 0x21d1d9c4edc45418L,0x005b859ec1cc4a9dL,0xdf01f630a1c462f0L, + 0x15d06cf3f26820c7L } }, + /* 50 << 42 */ + { { 0x9f7f24ee3484be47L,0x2ff33e964a0c902fL,0x00bdf4575a0bc453L, + 0x2378dfaf1aa238dbL }, + { 0x272420ec856720f2L,0x2ad9d95b96797291L,0xd1242cc6768a1558L, + 0x2e287f8b5cc86aa8L } }, + /* 51 << 42 */ + { { 0x796873d0990cecaaL,0xade55f81675d4080L,0x2645eea321f0cd84L, + 0x7a1efa0fb4e17d02L }, + { 0xf6858420037cc061L,0x682e05f0d5d43e12L,0x59c3699427218710L, + 0x85cbba4d3f7cd2fcL } }, + /* 52 << 42 */ + { { 0x726f97297a3cd22aL,0x9f8cd5dc4a628397L,0x17b93ab9c23165edL, + 0xff5f5dbf122823d4L }, + { 0xc1e4e4b5654a446dL,0xd1a9496f677257baL,0x6387ba94de766a56L, + 0x23608bc8521ec74aL } }, + /* 53 << 42 */ + { { 0x16a522d76688c4d4L,0x9d6b428207373abdL,0xa62f07acb42efaa3L, + 0xf73e00f7e3b90180L }, + { 0x36175fec49421c3eL,0xc4e44f9b3dcf2678L,0x76df436b7220f09fL, + 0x172755fb3aa8b6cfL } }, + /* 54 << 42 */ + { { 0xbab89d57446139ccL,0x0a0a6e025fe0208fL,0xcdbb63e211e5d399L, + 0x33ecaa12a8977f0bL }, + { 0x59598b21f7c42664L,0xb3e91b32ab65d08aL,0x035822eef4502526L, + 0x1dcf0176720a82a9L } }, + /* 55 << 42 */ + { { 0x50f8598f3d589e02L,0xdf0478ffb1d63d2cL,0x8b8068bd1571cd07L, + 0x30c3aa4fd79670cdL }, + { 0x25e8fd4b941ade7fL,0x3d1debdc32790011L,0x65b6dcbd3a3f9ff0L, + 0x282736a4793de69cL } }, + /* 56 << 42 */ + { { 0xef69a0c3d41d3bd3L,0xb533b8c907a26bdeL,0xe2801d97db2edf9fL, + 0xdc4a8269e1877af0L }, + { 0x6c1c58513d590dbeL,0x84632f6bee4e9357L,0xd36d36b779b33374L, + 0xb46833e39bbca2e6L } }, + /* 57 << 42 */ + { { 0x37893913f7fc0586L,0x385315f766bf4719L,0x72c56293b31855dcL, + 0xd1416d4e849061feL }, + { 0xbeb3ab7851047213L,0x447f6e61f040c996L,0xd06d310d638b1d0cL, + 0xe28a413fbad1522eL } }, + /* 58 << 42 */ + { { 0x685a76cb82003f86L,0x610d07f70bcdbca3L,0x6ff660219ca4c455L, + 0x7df39b87cea10eecL }, + { 0xb9255f96e22db218L,0x8cc6d9eb08a34c44L,0xcd4ffb86859f9276L, + 0x8fa15eb250d07335L } }, + /* 59 << 42 */ + { { 0xdf553845cf2c24b5L,0x89f66a9f52f9c3baL,0x8f22b5b9e4a7ceb3L, + 0xaffef8090e134686L }, + { 0x3e53e1c68eb8fac2L,0x93c1e4eb28aec98eL,0xb6b91ec532a43bcbL, + 0x2dbfa947b2d74a51L } }, + /* 60 << 42 */ + { { 0xe065d190ca84bad7L,0xfb13919fad58e65cL,0x3c41718bf1cb6e31L, + 0x688969f006d05c3fL }, + { 0xd4f94ce721264d45L,0xfdfb65e97367532bL,0x5b1be8b10945a39dL, + 0x229f789c2b8baf3bL } }, + /* 61 << 42 */ + { { 0xd8f41f3e6f49f15dL,0x678ce828907f0792L,0xc69ace82fca6e867L, + 0x106451aed01dcc89L }, + { 0x1bb4f7f019fc32d2L,0x64633dfcb00c52d2L,0x8f13549aad9ea445L, + 0x99a3bf50fb323705L } }, + /* 62 << 42 */ + { { 0x0c9625a2534d4dbcL,0x45b8f1d1c2a2fea3L,0x76ec21a1a530fc1aL, + 0x4bac9c2a9e5bd734L }, + { 0x5996d76a7b4e3587L,0x0045cdee1182d9e3L,0x1aee24b91207f13dL, + 0x66452e9797345a41L } }, + /* 63 << 42 */ + { { 0x16e5b0549f950cd0L,0x9cc72fb1d7fdd075L,0x6edd61e766249663L, + 0xde4caa4df043cccbL }, + { 0x11b1f57a55c7ac17L,0x779cbd441a85e24dL,0x78030f86e46081e7L, + 0xfd4a60328e20f643L } }, + /* 64 << 42 */ + { { 0xcc7a64880a750c0fL,0x39bacfe34e548e83L,0x3d418c760c110f05L, + 0x3e4daa4cb1f11588L }, + { 0x2733e7b55ffc69ffL,0x46f147bc92053127L,0x885b2434d722df94L, + 0x6a444f65e6fc6b7cL } }, + /* 0 << 49 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 49 */ + { { 0x7a1a465ac3f16ea8L,0x115a461db2f1d11cL,0x4767dd956c68a172L, + 0x3392f2ebd13a4698L }, + { 0xc7a99ccde526cdc7L,0x8e537fdc22292b81L,0x76d8cf69a6d39198L, + 0xffc5ff432446852dL } }, + /* 2 << 49 */ + { { 0x97b14f7ea90567e6L,0x513257b7b6ae5cb7L,0x85454a3c9f10903dL, + 0xd8d2c9ad69bc3724L }, + { 0x38da93246b29cb44L,0xb540a21d77c8cbacL,0x9bbfe43501918e42L, + 0xfffa707a56c3614eL } }, + /* 3 << 49 */ + { { 0x0ce4e3f1d4e353b7L,0x062d8a14ef46b0a0L,0x6408d5ab574b73fdL, + 0xbc41d1c9d3273ffdL }, + { 0x3538e1e76be77800L,0x71fe8b37c5655031L,0x1cd916216b9b331aL, + 0xad825d0bbb388f73L } }, + /* 4 << 49 */ + { { 0x56c2e05b1cb76219L,0x0ec0bf9171567e7eL,0xe7076f8661c4c910L, + 0xd67b085bbabc04d9L }, + { 0x9fb904595e93a96aL,0x7526c1eafbdc249aL,0x0d44d367ecdd0bb7L, + 0x953999179dc0d695L } }, + /* 5 << 49 */ + { { 0x61360ee99e240d18L,0x057cdcacb4b94466L,0xe7667cd12fe5325cL, + 0x1fa297b521974e3bL }, + { 0xfa4081e7db083d76L,0x31993be6f206bd15L,0x8949269b14c19f8cL, + 0x21468d72a9d92357L } }, + /* 6 << 49 */ + { { 0x2ccbc583a4c506ecL,0x957ed188d1acfe97L,0x8baed83312f1aea2L, + 0xef2a6cb48325362dL }, + { 0x130dde428e195c43L,0xc842025a0e6050c6L,0x2da972a708686a5dL, + 0xb52999a1e508b4a8L } }, + /* 7 << 49 */ + { { 0xd9f090b910a5a8bdL,0xca91d249096864daL,0x8e6a93be3f67dbc1L, + 0xacae6fbaf5f4764cL }, + { 0x1563c6e0d21411a0L,0x28fa787fda0a4ad8L,0xd524491c908c8030L, + 0x1257ba0e4c795f07L } }, + /* 8 << 49 */ + { { 0x83f49167ceca9754L,0x426d2cf64b7939a0L,0x2555e355723fd0bfL, + 0xa96e6d06c4f144e2L }, + { 0x4768a8dd87880e61L,0x15543815e508e4d5L,0x09d7e772b1b65e15L, + 0x63439dd6ac302fa0L } }, + /* 9 << 49 */ + { { 0xb93f802fc14e35c2L,0x71735b7c4341333cL,0x03a2510416d4f362L, + 0x3f4d069bbf433c8eL }, + { 0x0d83ae01f78f5a7cL,0x50a8ffbe7c4eed07L,0xc74f890676e10f83L, + 0x7d0809669ddaf8e1L } }, + /* 10 << 49 */ + { { 0xb11df8e1698e04ccL,0x877be203169005c8L,0x32749e8c4f3c6179L, + 0x2dbc9d0a7853fc05L }, + { 0x187d4f939454d937L,0xe682ce9db4800e1bL,0xa9129ad8165e68e8L, + 0x0fe29735be7f785bL } }, + /* 11 << 49 */ + { { 0x5303f40c5b9e02b7L,0xa37c969235ee04e8L,0x5f46cc2034d6632bL, + 0x55ef72b296ac545bL }, + { 0xabec5c1f7b91b062L,0x0a79e1c7bb33e821L,0xbb04b4283a9f4117L, + 0x0de1f28ffd2a475aL } }, + /* 12 << 49 */ + { { 0x31019ccf3a4434b4L,0xa34581111a7954dcL,0xa9dac80de34972a7L, + 0xb043d05474f6b8ddL }, + { 0x021c319e11137b1aL,0x00a754ceed5cc03fL,0x0aa2c794cbea5ad4L, + 0x093e67f470c015b6L } }, + /* 13 << 49 */ + { { 0x72cdfee9c97e3f6bL,0xc10bcab4b6da7461L,0x3b02d2fcb59806b9L, + 0x85185e89a1de6f47L }, + { 0x39e6931f0eb6c4d4L,0x4d4440bdd4fa5b04L,0x5418786e34be7eb8L, + 0x6380e5219d7259bcL } }, + /* 14 << 49 */ + { { 0x20ac0351d598d710L,0x272c4166cb3a4da4L,0xdb82fe1aca71de1fL, + 0x746e79f2d8f54b0fL }, + { 0x6e7fc7364b573e9bL,0x75d03f46fd4b5040L,0x5c1cc36d0b98d87bL, + 0x513ba3f11f472da1L } }, + /* 15 << 49 */ + { { 0x79d0af26abb177ddL,0xf82ab5687891d564L,0x2b6768a972232173L, + 0xefbb3bb08c1f6619L }, + { 0xb29c11dba6d18358L,0x519e2797b0916d3aL,0xd4dc18f09188e290L, + 0x648e86e398b0ca7fL } }, + /* 16 << 49 */ + { { 0x859d3145983c38b5L,0xb14f176c637abc8bL,0x2793fb9dcaff7be6L, + 0xebe5a55f35a66a5aL }, + { 0x7cec1dcd9f87dc59L,0x7c595cd3fbdbf560L,0x5b543b2226eb3257L, + 0x69080646c4c935fdL } }, + /* 17 << 49 */ + { { 0x7f2e440381e9ede3L,0x243c3894caf6df0aL,0x7c605bb11c073b11L, + 0xcd06a541ba6a4a62L }, + { 0x2916894949d4e2e5L,0x33649d074af66880L,0xbfc0c885e9a85035L, + 0xb4e52113fc410f4bL } }, + /* 18 << 49 */ + { { 0xdca3b70678a6513bL,0x92ea4a2a9edb1943L,0x02642216db6e2dd8L, + 0x9b45d0b49fd57894L }, + { 0x114e70dbc69d11aeL,0x1477dd194c57595fL,0xbc2208b4ec77c272L, + 0x95c5b4d7db68f59cL } }, + /* 19 << 49 */ + { { 0xb8c4fc6342e532b7L,0x386ba4229ae35290L,0xfb5dda42d201ecbcL, + 0x2353dc8ba0e38fd6L }, + { 0x9a0b85ea68f7e978L,0x96ec56822ad6d11fL,0x5e279d6ce5f6886dL, + 0xd3fe03cd3cb1914dL } }, + /* 20 << 49 */ + { { 0xfe541fa47ea67c77L,0x952bd2afe3ea810cL,0x791fef568d01d374L, + 0xa3a1c6210f11336eL }, + { 0x5ad0d5a9c7ec6d79L,0xff7038af3225c342L,0x003c6689bc69601bL, + 0x25059bc745e8747dL } }, + /* 21 << 49 */ + { { 0xfa4965b2f2086fbfL,0xf6840ea686916078L,0xd7ac762070081d6cL, + 0xe600da31b5328645L }, + { 0x01916f63529b8a80L,0xe80e48582d7d6f3eL,0x29eb0fe8d664ca7cL, + 0xf017637be7b43b0cL } }, + /* 22 << 49 */ + { { 0x9a75c80676cb2566L,0x8f76acb1b24892d9L,0x7ae7b9cc1f08fe45L, + 0x19ef73296a4907d8L }, + { 0x2db4ab715f228bf0L,0xf3cdea39817032d7L,0x0b1f482edcabe3c0L, + 0x3baf76b4bb86325cL } }, + /* 23 << 49 */ + { { 0xd49065e010089465L,0x3bab5d298e77c596L,0x7636c3a6193dbd95L, + 0xdef5d294b246e499L }, + { 0xb22c58b9286b2475L,0xa0b93939cd80862bL,0x3002c83af0992388L, + 0x6de01f9beacbe14cL } }, + /* 24 << 49 */ + { { 0x6aac688eadd70482L,0x708de92a7b4a4e8aL,0x75b6dd73758a6eefL, + 0xea4bf352725b3c43L }, + { 0x10041f2c87912868L,0xb1b1be95ef09297aL,0x19ae23c5a9f3860aL, + 0xc4f0f839515dcf4bL } }, + /* 25 << 49 */ + { { 0x3c7ecca397f6306aL,0x744c44ae68a3a4b0L,0x69cd13a0b3a1d8a2L, + 0x7cad0a1e5256b578L }, + { 0xea653fcd33791d9eL,0x9cc2a05d74b2e05fL,0x73b391dcfd7affa2L, + 0xddb7091eb6b05442L } }, + /* 26 << 49 */ + { { 0xc71e27bf8538a5c6L,0x195c63dd89abff17L,0xfd3152851b71e3daL, + 0x9cbdfda7fa680fa0L }, + { 0x9db876ca849d7eabL,0xebe2764b3c273271L,0x663357e3f208dceaL, + 0x8c5bd833565b1b70L } }, + /* 27 << 49 */ + { { 0xccc3b4f59837fc0dL,0x9b641ba8a79cf00fL,0x7428243ddfdf3990L, + 0x83a594c4020786b1L }, + { 0xb712451a526c4502L,0x9d39438e6adb3f93L,0xfdb261e3e9ff0ccdL, + 0x80344e3ce07af4c3L } }, + /* 28 << 49 */ + { { 0x75900d7c2fa4f126L,0x08a3b8655c99a232L,0x2478b6bfdb25e0c3L, + 0x482cc2c271db2edfL }, + { 0x37df7e645f321bb8L,0x8a93821b9a8005b4L,0x3fa2f10ccc8c1958L, + 0x0d3322182c269d0aL } }, + /* 29 << 49 */ + { { 0x20ab8119e246b0e6L,0xb39781e4d349fd17L,0xd293231eb31aa100L, + 0x4b779c97bb032168L }, + { 0x4b3f19e1c8470500L,0x45b7efe90c4c869dL,0xdb84f38aa1a6bbccL, + 0x3b59cb15b2fddbc1L } }, + /* 30 << 49 */ + { { 0xba5514df3fd165e8L,0x499fd6a9061f8811L,0x72cd1fe0bfef9f00L, + 0x120a4bb979ad7e8aL }, + { 0xf2ffd0955f4a5ac5L,0xcfd174f195a7a2f0L,0xd42301ba9d17baf1L, + 0xd2fa487a77f22089L } }, + /* 31 << 49 */ + { { 0x9cb09efeb1dc77e1L,0xe956693921c99682L,0x8c5469016c6067bbL, + 0xfd37857461c24456L }, + { 0x2b6a6cbe81796b33L,0x62d550f658e87f8bL,0x1b763e1c7f1b01b4L, + 0x4b93cfea1b1b5e12L } }, + /* 32 << 49 */ + { { 0xb93452381d531696L,0x57201c0088cdde69L,0xdde922519a86afc7L, + 0xe3043895bd35cea8L }, + { 0x7608c1e18555970dL,0x8267dfa92535935eL,0xd4c60a57322ea38bL, + 0xe0bf7977804ef8b5L } }, + /* 33 << 49 */ + { { 0x1a0dab28c06fece4L,0xd405991e94e7b49dL,0xc542b6d2706dab28L, + 0xcb228da3a91618fbL }, + { 0x224e4164107d1ceaL,0xeb9fdab3d0f5d8f1L,0xc02ba3860d6e41cdL, + 0x676a72c59b1f7146L } }, + /* 34 << 49 */ + { { 0xffd6dd984d6cb00bL,0xcef9c5cade2e8d7cL,0xa1bbf5d7641c7936L, + 0x1b95b230ee8f772eL }, + { 0xf765a92ee8ac25b1L,0xceb04cfc3a18b7c6L,0x27944cef0acc8966L, + 0xcbb3c957434c1004L } }, + /* 35 << 49 */ + { { 0x9c9971a1a43ff93cL,0x5bc2db17a1e358a9L,0x45b4862ea8d9bc82L, + 0x70ebfbfb2201e052L }, + { 0xafdf64c792871591L,0xea5bcae6b42d0219L,0xde536c552ad8f03cL, + 0xcd6c3f4da76aa33cL } }, + /* 36 << 49 */ + { { 0xbeb5f6230bca6de3L,0xdd20dd99b1e706fdL,0x90b3ff9dac9059d4L, + 0x2d7b29027ccccc4eL }, + { 0x8a090a59ce98840fL,0xa5d947e08410680aL,0x49ae346a923379a5L, + 0x7dbc84f9b28a3156L } }, + /* 37 << 49 */ + { { 0xfd40d91654a1aff2L,0xabf318ba3a78fb9bL,0x50152ed83029f95eL, + 0x9fc1dd77c58ad7faL }, + { 0x5fa5791513595c17L,0xb95046688f62b3a9L,0x907b5b24ff3055b0L, + 0x2e995e359a84f125L } }, + /* 38 << 49 */ + { { 0x87dacf697e9bbcfbL,0x95d0c1d6e86d96e3L,0x65726e3c2d95a75cL, + 0x2c3c9001acd27f21L }, + { 0x1deab5616c973f57L,0x108b7e2ca5221643L,0x5fee9859c4ef79d4L, + 0xbd62b88a40d4b8c6L } }, + /* 39 << 49 */ + { { 0xb4dd29c4197c75d6L,0x266a6df2b7076febL,0x9512d0ea4bf2df11L, + 0x1320c24f6b0cc9ecL }, + { 0x6bb1e0e101a59596L,0x8317c5bbeff9aaacL,0x65bb405e385aa6c9L, + 0x613439c18f07988fL } }, + /* 40 << 49 */ + { { 0xd730049f16a66e91L,0xe97f2820fa1b0e0dL,0x4131e003304c28eaL, + 0x820ab732526bac62L }, + { 0xb2ac9ef928714423L,0x54ecfffaadb10cb2L,0x8781476ef886a4ccL, + 0x4b2c87b5db2f8d49L } }, + /* 41 << 49 */ + { { 0xe857cd200a44295dL,0x707d7d2158c6b044L,0xae8521f9f596757cL, + 0x87448f0367b2b714L }, + { 0x13a9bc455ebcd58dL,0x79bcced99122d3c1L,0x3c6442479e076642L, + 0x0cf227782df4767dL } }, + /* 42 << 49 */ + { { 0x5e61aee471d444b6L,0x211236bfc5084a1dL,0x7e15bc9a4fd3eaf6L, + 0x68df2c34ab622bf5L }, + { 0x9e674f0f59bf4f36L,0xf883669bd7f34d73L,0xc48ac1b831497b1dL, + 0x323b925d5106703bL } }, + /* 43 << 49 */ + { { 0x22156f4274082008L,0xeffc521ac8482bcbL,0x5c6831bf12173479L, + 0xcaa2528fc4739490L }, + { 0x84d2102a8f1b3c4dL,0xcf64dfc12d9bec0dL,0x433febad78a546efL, + 0x1f621ec37b73cef1L } }, + /* 44 << 49 */ + { { 0x6aecd62737338615L,0x162082ab01d8edf6L,0x833a811919e86b66L, + 0x6023a251d299b5dbL }, + { 0xf5bb0c3abbf04b89L,0x6735eb69ae749a44L,0xd0e058c54713de3bL, + 0xfdf2593e2c3d4ccdL } }, + /* 45 << 49 */ + { { 0x1b8f414efdd23667L,0xdd52aacafa2015eeL,0x3e31b517bd9625ffL, + 0x5ec9322d8db5918cL }, + { 0xbc73ac85a96f5294L,0x82aa5bf361a0666aL,0x49755810bf08ac42L, + 0xd21cdfd5891cedfcL } }, + /* 46 << 49 */ + { { 0x918cb57b67f8be10L,0x365d1a7c56ffa726L,0x2435c5046532de93L, + 0xc0fc5e102674cd02L }, + { 0x6e51fcf89cbbb142L,0x1d436e5aafc50692L,0x766bffff3fbcae22L, + 0x3148c2fdfd55d3b8L } }, + /* 47 << 49 */ + { { 0x52c7fdc9233222faL,0x89ff1092e419fb6bL,0x3cd6db9925254977L, + 0x2e85a1611cf12ca7L }, + { 0xadd2547cdc810bc9L,0xea3f458f9d257c22L,0x642c1fbe27d6b19bL, + 0xed07e6b5140481a6L } }, + /* 48 << 49 */ + { { 0x6ada1d4286d2e0f8L,0xe59201220e8a9fd5L,0x02c936af708c1b49L, + 0x60f30fee2b4bfaffL }, + { 0x6637ad06858e6a61L,0xce4c77673fd374d0L,0x39d54b2d7188defbL, + 0xa8c9d250f56a6b66L } }, + /* 49 << 49 */ + { { 0x58fc0f5eb24fe1dcL,0x9eaf9dee6b73f24cL,0xa90d588b33650705L, + 0xde5b62c5af2ec729L }, + { 0x5c72cfaed3c2b36eL,0x868c19d5034435daL,0x88605f93e17ee145L, + 0xaa60c4ee77a5d5b1L } }, + /* 50 << 49 */ + { { 0xbcf5bfd23b60c472L,0xaf4ef13ceb1d3049L,0x373f44fce13895c9L, + 0xf29b382f0cbc9822L }, + { 0x1bfcb85373efaef6L,0xcf56ac9ca8c96f40L,0xd7adf1097a191e24L, + 0x98035f44bf8a8dc2L } }, + /* 51 << 49 */ + { { 0xf40a71b91e750c84L,0xc57f7b0c5dc6c469L,0x49a0e79c6fbc19c1L, + 0x6b0f5889a48ebdb8L }, + { 0x5d3fd084a07c4e9fL,0xc3830111ab27de14L,0x0e4929fe33e08dccL, + 0xf4a5ad2440bb73a3L } }, + /* 52 << 49 */ + { { 0xde86c2bf490f97caL,0x288f09c667a1ce18L,0x364bb8861844478dL, + 0x7840fa42ceedb040L }, + { 0x1269fdd25a631b37L,0x94761f1ea47c8b7dL,0xfc0c2e17481c6266L, + 0x85e16ea23daa5fa7L } }, + /* 53 << 49 */ + { { 0xccd8603392491048L,0x0c2f6963f4d402d7L,0x6336f7dfdf6a865cL, + 0x0a2a463cb5c02a87L }, + { 0xb0e29be7bf2f12eeL,0xf0a2200266bad988L,0x27f87e039123c1d7L, + 0x21669c55328a8c98L } }, + /* 54 << 49 */ + { { 0x186b980392f14529L,0xd3d056cc63954df3L,0x2f03fd58175a46f6L, + 0x63e34ebe11558558L }, + { 0xe13fedee5b80cfa5L,0xe872a120d401dbd1L,0x52657616e8a9d667L, + 0xbc8da4b6e08d6693L } }, + /* 55 << 49 */ + { { 0x370fb9bb1b703e75L,0x6773b186d4338363L,0x18dad378ecef7bffL, + 0xaac787ed995677daL }, + { 0x4801ea8b0437164bL,0xf430ad2073fe795eL,0xb164154d8ee5eb73L, + 0x0884ecd8108f7c0eL } }, + /* 56 << 49 */ + { { 0x0e6ec0965f520698L,0x640631fe44f7b8d9L,0x92fd34fca35a68b9L, + 0x9c5a4b664d40cf4eL }, + { 0x949454bf80b6783dL,0x80e701fe3a320a10L,0x8d1a564a1a0a39b2L, + 0x1436d53d320587dbL } }, + /* 57 << 49 */ + { { 0xf5096e6d6556c362L,0xbc23a3c0e2455d7eL,0x3a7aee54807230f9L, + 0x9ba1cfa622ae82fdL }, + { 0x833a057a99c5d706L,0x8be85f4b842315c9L,0xd083179a66a72f12L, + 0x2fc77d5dcdcc73cdL } }, + /* 58 << 49 */ + { { 0x22b88a805616ee30L,0xfb09548fe7ab1083L,0x8ad6ab0d511270cdL, + 0x61f6c57a6924d9abL }, + { 0xa0f7bf7290aecb08L,0x849f87c90df784a4L,0x27c79c15cfaf1d03L, + 0xbbf9f675c463faceL } }, + /* 59 << 49 */ + { { 0x91502c65765ba543L,0x18ce3cac42ea60ddL,0xe5cee6ac6e43ecb3L, + 0x63e4e91068f2aeebL }, + { 0x26234fa3c85932eeL,0x96883e8b4c90c44dL,0x29b9e738a18a50f6L, + 0xbfc62b2a3f0420dfL } }, + /* 60 << 49 */ + { { 0xd22a7d906d3e1fa9L,0x17115618fe05b8a3L,0x2a0c9926bb2b9c01L, + 0xc739fcc6e07e76a2L }, + { 0x540e9157165e439aL,0x06353a626a9063d8L,0x84d9559461e927a3L, + 0x013b9b26e2e0be7fL } }, + /* 61 << 49 */ + { { 0x4feaec3b973497f1L,0x15c0f94e093ebc2dL,0x6af5f22733af0583L, + 0x0c2af206c61f3340L }, + { 0xd25dbdf14457397cL,0x2e8ed017cabcbae0L,0xe3010938c2815306L, + 0xbaa99337e8c6cd68L } }, + /* 62 << 49 */ + { { 0x085131823b0ec7deL,0x1e1b822b58df05dfL,0x5c14842fa5c3b683L, + 0x98fe977e3eba34ceL }, + { 0xfd2316c20d5e8873L,0xe48d839abd0d427dL,0x495b2218623fc961L, + 0x24ee56e7b46fba5eL } }, + /* 63 << 49 */ + { { 0x9184a55b91e4de58L,0xa7488ca5dfdea288L,0xa723862ea8dcc943L, + 0x92d762b2849dc0fcL }, + { 0x3c444a12091ff4a9L,0x581113fa0cada274L,0xb9de0a4530d8eae2L, + 0x5e0fcd85df6b41eaL } }, + /* 64 << 49 */ + { { 0x6233ea68c094dbb5L,0xb77d062ed968d410L,0x3e719bbc58b3002dL, + 0x68e7dd3d3dc49d58L }, + { 0x8d825740013a5e58L,0x213117473c9e3c1bL,0x0cb0a2a77c99b6abL, + 0x5c48a3b3c2f888f2L } }, + /* 0 << 56 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 56 */ + { { 0xc7913e91991724f3L,0x5eda799c39cbd686L,0xddb595c763d4fc1eL, + 0x6b63b80bac4fed54L }, + { 0x6ea0fc697e5fb516L,0x737708bad0f1c964L,0x9628745f11a92ca5L, + 0x61f379589a86967aL } }, + /* 2 << 56 */ + { { 0x9af39b2caa665072L,0x78322fa4efd324efL,0x3d153394c327bd31L, + 0x81d5f2713129dab0L }, + { 0xc72e0c42f48027f5L,0xaa40cdbc8536e717L,0xf45a657a2d369d0fL, + 0xb03bbfc4ea7f74e6L } }, + /* 3 << 56 */ + { { 0x46a8c4180d738dedL,0x6f1a5bb0e0de5729L,0xf10230b98ba81675L, + 0x32c6f30c112b33d4L }, + { 0x7559129dd8fffb62L,0x6a281b47b459bf05L,0x77c1bd3afa3b6776L, + 0x0709b3807829973aL } }, + /* 4 << 56 */ + { { 0x8c26b232a3326505L,0x38d69272ee1d41bfL,0x0459453effe32afaL, + 0xce8143ad7cb3ea87L }, + { 0x932ec1fa7e6ab666L,0x6cd2d23022286264L,0x459a46fe6736f8edL, + 0x50bf0d009eca85bbL } }, + /* 5 << 56 */ + { { 0x0b825852877a21ecL,0x300414a70f537a94L,0x3f1cba4021a9a6a2L, + 0x50824eee76943c00L }, + { 0xa0dbfcecf83cba5dL,0xf953814893b4f3c0L,0x6174416248f24dd7L, + 0x5322d64de4fb09ddL } }, + /* 6 << 56 */ + { { 0x574473843d9325f3L,0xa9bef2d0f371cb84L,0x77d2188ba61e36c5L, + 0xbbd6a7d7c602df72L }, + { 0xba3aa9028f61bc0bL,0xf49085ed6ed0b6a1L,0x8bc625d6ae6e8298L, + 0x832b0b1da2e9c01dL } }, + /* 7 << 56 */ + { { 0xa337c447f1f0ced1L,0x800cc7939492dd2bL,0x4b93151dbea08efaL, + 0x820cf3f8de0a741eL }, + { 0xff1982dc1c0f7d13L,0xef92196084dde6caL,0x1ad7d97245f96ee3L, + 0x319c8dbe29dea0c7L } }, + /* 8 << 56 */ + { { 0xd3ea38717b82b99bL,0x75922d4d470eb624L,0x8f66ec543b95d466L, + 0x66e673ccbee1e346L }, + { 0x6afe67c4b5f2b89aL,0x3de9c1e6290e5cd3L,0x8c278bb6310a2adaL, + 0x420fa3840bdb323bL } }, + /* 9 << 56 */ + { { 0x0ae1d63b0eb919b0L,0xd74ee51da74b9620L,0x395458d0a674290cL, + 0x324c930f4620a510L }, + { 0x2d1f4d19fbac27d4L,0x4086e8ca9bedeeacL,0x0cdd211b9b679ab8L, + 0x5970167d7090fec4L } }, + /* 10 << 56 */ + { { 0x3420f2c9faf1fc63L,0x616d333a328c8bb4L,0x7d65364c57f1fe4aL, + 0x9343e87755e5c73aL }, + { 0x5795176be970e78cL,0xa36ccebf60533627L,0xfc7c738009cdfc1bL, + 0xb39a2afeb3fec326L } }, + /* 11 << 56 */ + { { 0xb7ff1ba16224408aL,0xcc856e92247cfc5eL,0x01f102e7c18bc493L, + 0x4613ab742091c727L }, + { 0xaa25e89cc420bf2bL,0x00a5317690337ec2L,0xd2be9f437d025fc7L, + 0x3316fb856e6fe3dcL } }, + /* 12 << 56 */ + { { 0x27520af59ac50814L,0xfdf95e789a8e4223L,0xb7e7df2a56bec5a0L, + 0xf7022f7ddf159e5dL }, + { 0x93eeeab1cac1fe8fL,0x8040188c37451168L,0x7ee8aa8ad967dce6L, + 0xfa0e79e73abc9299L } }, + /* 13 << 56 */ + { { 0x67332cfc2064cfd1L,0x339c31deb0651934L,0x719b28d52a3bcbeaL, + 0xee74c82b9d6ae5c6L }, + { 0x0927d05ebaf28ee6L,0x82cecf2c9d719028L,0x0b0d353eddb30289L, + 0xfe4bb977fddb2e29L } }, + /* 14 << 56 */ + { { 0xbb5bb990640bfd9eL,0xd226e27782f62108L,0x4bf0098502ffdd56L, + 0x7756758a2ca1b1b5L }, + { 0xc32b62a35285fe91L,0xedbc546a8c9cd140L,0x1e47a013af5cb008L, + 0xbca7e720073ce8f2L } }, + /* 15 << 56 */ + { { 0xe10b2ab817a91caeL,0xb89aab6508e27f63L,0x7b3074a7dba3ddf9L, + 0x1c20ce09330c2972L }, + { 0x6b9917b45fcf7e33L,0xe6793743945ceb42L,0x18fc22155c633d19L, + 0xad1adb3cc7485474L } }, + /* 16 << 56 */ + { { 0x646f96796424c49bL,0xf888dfe867c241c9L,0xe12d4b9324f68b49L, + 0x9a6b62d8a571df20L }, + { 0x81b4b26d179483cbL,0x666f96329511fae2L,0xd281b3e4d53aa51fL, + 0x7f96a7657f3dbd16L } }, + /* 17 << 56 */ + { { 0xa7f8b5bf074a30ceL,0xd7f52107005a32e6L,0x6f9e090750237ed4L, + 0x2f21da478096fa2bL }, + { 0xf3e19cb4eec863a0L,0xd18f77fd9527620aL,0x9505c81c407c1cf8L, + 0x9998db4e1b6ec284L } }, + /* 18 << 56 */ + { { 0x7e3389e5c247d44dL,0x125071413f4f3d80L,0xd4ba01104a78a6c7L, + 0x312874a0767720beL }, + { 0xded059a675944370L,0xd6123d903b2c0bddL,0xa56b717b51c108e3L, + 0x9bb7940e070623e9L } }, + /* 19 << 56 */ + { { 0x794e2d5984ac066cL,0xf5954a92e68c69a0L,0x28c524584fd99dccL, + 0x60e639fcb1012517L }, + { 0xc2e601257de79248L,0xe9ef6404f12fc6d7L,0x4c4f28082a3b5d32L, + 0x865ad32ec768eb8aL } }, + /* 20 << 56 */ + { { 0xac02331b13fb70b6L,0x037b44c195599b27L,0x1a860fc460bd082cL, + 0xa2e25745c980cd01L }, + { 0xee3387a81da0263eL,0x931bfb952d10f3d6L,0x5b687270a1f24a32L, + 0xf140e65dca494b86L } }, + /* 21 << 56 */ + { { 0x4f4ddf91b2f1ac7aL,0xf99eaabb760fee27L,0x57f4008a49c228e5L, + 0x090be4401cf713bbL }, + { 0xac91fbe45004f022L,0xd838c2c2569e1af6L,0xd6c7d20b0f1daaa5L, + 0xaa063ac11bbb02c0L } }, + /* 22 << 56 */ + { { 0x0938a42259558a78L,0x5343c6698435da2fL,0x96f67b18034410dcL, + 0x7cc1e42484510804L }, + { 0x86a1543f16dfbb7dL,0x921fa9425b5bd592L,0x9dcccb6eb33dd03cL, + 0x8581ddd9b843f51eL } }, + /* 23 << 56 */ + { { 0x54935fcb81d73c9eL,0x6d07e9790a5e97abL,0x4dc7b30acf3a6babL, + 0x147ab1f3170bee11L }, + { 0x0aaf8e3d9fafdee4L,0xfab3dbcb538a8b95L,0x405df4b36ef13871L, + 0xf1f4e9cb088d5a49L } }, + /* 24 << 56 */ + { { 0x9bcd24d366b33f1dL,0x3b97b8205ce445c0L,0xe2926549ba93ff61L, + 0xd9c341ce4dafe616L }, + { 0xfb30a76e16efb6f3L,0xdf24b8ca605b953cL,0x8bd52afec2fffb9fL, + 0xbbac5ff7e19d0b96L } }, + /* 25 << 56 */ + { { 0x43c01b87459afccdL,0x6bd45143b7432652L,0x8473453055b5d78eL, + 0x81088fdb1554ba7dL }, + { 0xada0a52c1e269375L,0xf9f037c42dc5ec10L,0xc066060794bfbc11L, + 0xc0a630bbc9c40d2fL } }, + /* 26 << 56 */ + { { 0x5efc797eab64c31eL,0xffdb1dab74507144L,0xf61242871ca6790cL, + 0xe9609d81e69bf1bfL }, + { 0xdb89859500d24fc9L,0x9c750333e51fb417L,0x51830a91fef7bbdeL, + 0x0ce67dc8945f585cL } }, + /* 27 << 56 */ + { { 0x9a730ed44763eb50L,0x24a0e221c1ab0d66L,0x643b6393648748f3L, + 0x1982daa16d3c6291L }, + { 0x6f00a9f78bbc5549L,0x7a1783e17f36384eL,0xe8346323de977f50L, + 0x91ab688db245502aL } }, + /* 28 << 56 */ + { { 0x331ab6b56d0bdd66L,0x0a6ef32e64b71229L,0x1028150efe7c352fL, + 0x27e04350ce7b39d3L }, + { 0x2a3c8acdc1070c82L,0xfb2034d380c9feefL,0x2d729621709f3729L, + 0x8df290bf62cb4549L } }, + /* 29 << 56 */ + { { 0x02f99f33fc2e4326L,0x3b30076d5eddf032L,0xbb21f8cf0c652fb5L, + 0x314fb49eed91cf7bL }, + { 0xa013eca52f700750L,0x2b9e3c23712a4575L,0xe5355557af30fbb0L, + 0x1ada35167c77e771L } }, + /* 30 << 56 */ + { { 0x45f6ecb27b135670L,0xe85d19df7cfc202eL,0x0f1b50c758d1be9fL, + 0x5ebf2c0aead2e344L }, + { 0x1531fe4eabc199c9L,0xc703259256bab0aeL,0x16ab2e486c1fec54L, + 0x0f87fda804280188L } }, + /* 31 << 56 */ + { { 0xdc9f46fc609e4a74L,0x2a44a143ba667f91L,0xbc3d8b95b4d83436L, + 0xa01e4bd0c7bd2958L }, + { 0x7b18293273483c90L,0xa79c6aa1a7c7b598L,0xbf3983c6eaaac07eL, + 0x8f18181e96e0d4e6L } }, + /* 32 << 56 */ + { { 0x8553d37c051af62bL,0xe9a998eb0bf94496L,0xe0844f9fb0d59aa1L, + 0x983fd558e6afb813L }, + { 0x9670c0ca65d69804L,0x732b22de6ea5ff2dL,0xd7640ba95fd8623bL, + 0x9f619163a6351782L } }, + /* 33 << 56 */ + { { 0x0bfc27eeacee5043L,0xae419e732eb10f02L,0x19c028d18943fb05L, + 0x71f01cf7ff13aa2aL }, + { 0x7790737e8887a132L,0x6751330966318410L,0x9819e8a37ddb795eL, + 0xfecb8ef5dad100b2L } }, + /* 34 << 56 */ + { { 0x59f74a223021926aL,0xb7c28a496f9b4c1cL,0xed1a733f912ad0abL, + 0x42a910af01a5659cL }, + { 0x3842c6e07bd68cabL,0x2b57fa3876d70ac8L,0x8a6707a83c53aaebL, + 0x62c1c51065b4db18L } }, + /* 35 << 56 */ + { { 0x8de2c1fbb2d09dc7L,0xc3dfed12266bd23bL,0x927d039bd5b27db6L, + 0x2fb2f0f1103243daL }, + { 0xf855a07b80be7399L,0xed9327ce1f9f27a8L,0xa0bd99c7729bdef7L, + 0x2b67125e28250d88L } }, + /* 36 << 56 */ + { { 0x784b26e88670ced7L,0xe3dfe41fc31bd3b4L,0x9e353a06bcc85cbcL, + 0x302e290960178a9dL }, + { 0x860abf11a6eac16eL,0x76447000aa2b3aacL,0x46ff9d19850afdabL, + 0x35bdd6a5fdb2d4c1L } }, + /* 37 << 56 */ + { { 0xe82594b07e5c9ce9L,0x0f379e5320af346eL,0x608b31e3bc65ad4aL, + 0x710c6b12267c4826L }, + { 0x51c966f971954cf1L,0xb1cec7930d0aa215L,0x1f15598986bd23a8L, + 0xae2ff99cf9452e86L } }, + /* 38 << 56 */ + { { 0xd8dd953c340ceaa2L,0x263552752e2e9333L,0x15d4e5f98586f06dL, + 0xd6bf94a8f7cab546L }, + { 0x33c59a0ab76a9af0L,0x52740ab3ba095af7L,0xc444de8a24389ca0L, + 0xcc6f9863706da0cbL } }, + /* 39 << 56 */ + { { 0xb5a741a76b2515cfL,0x71c416019585c749L,0x78350d4fe683de97L, + 0x31d6152463d0b5f5L }, + { 0x7a0cc5e1fbce090bL,0xaac927edfbcb2a5bL,0xe920de4920d84c35L, + 0x8c06a0b622b4de26L } }, + /* 40 << 56 */ + { { 0xd34dd58bafe7ddf3L,0x55851fedc1e6e55bL,0xd1395616960696e7L, + 0x940304b25f22705fL }, + { 0x6f43f861b0a2a860L,0xcf1212820e7cc981L,0x121862120ab64a96L, + 0x09215b9ab789383cL } }, + /* 41 << 56 */ + { { 0x311eb30537387c09L,0xc5832fcef03ee760L,0x30358f5832f7ea19L, + 0xe01d3c3491d53551L }, + { 0x1ca5ee41da48ea80L,0x34e71e8ecf4fa4c1L,0x312abd257af1e1c7L, + 0xe3afcdeb2153f4a5L } }, + /* 42 << 56 */ + { { 0x9d5c84d700235e9aL,0x0308d3f48c4c836fL,0xc0a66b0489332de5L, + 0x610dd39989e566efL }, + { 0xf8eea460d1ac1635L,0x84cbb3fb20a2c0dfL,0x40afb488e74a48c5L, + 0x29738198d326b150L } }, + /* 43 << 56 */ + { { 0x2a17747fa6d74081L,0x60ea4c0555a26214L,0x53514bb41f88c5feL, + 0xedd645677e83426cL }, + { 0xd5d6cbec96460b25L,0xa12fd0ce68dc115eL,0xc5bc3ed2697840eaL, + 0x969876a8a6331e31L } }, + /* 44 << 56 */ + { { 0x60c36217472ff580L,0xf42297054ad41393L,0x4bd99ef0a03b8b92L, + 0x501c7317c144f4f6L }, + { 0x159009b318464945L,0x6d5e594c74c5c6beL,0x2d587011321a3660L, + 0xd1e184b13898d022L } }, + /* 45 << 56 */ + { { 0x5ba047524c6a7e04L,0x47fa1e2b45550b65L,0x9419daf048c0a9a5L, + 0x663629537c243236L }, + { 0xcd0744b15cb12a88L,0x561b6f9a2b646188L,0x599415a566c2c0c0L, + 0xbe3f08590f83f09aL } }, + /* 46 << 56 */ + { { 0x9141c5beb92041b8L,0x01ae38c726477d0dL,0xca8b71f3d12c7a94L, + 0xfab5b31f765c70dbL }, + { 0x76ae7492487443e9L,0x8595a310990d1349L,0xf8dbeda87d460a37L, + 0x7f7ad0821e45a38fL } }, + /* 47 << 56 */ + { { 0xed1d4db61059705aL,0xa3dd492ae6b9c697L,0x4b92ee3a6eb38bd5L, + 0xbab2609d67cc0bb7L }, + { 0x7fc4fe896e70ee82L,0xeff2c56e13e6b7e3L,0x9b18959e34d26fcaL, + 0x2517ab66889d6b45L } }, + /* 48 << 56 */ + { { 0xf167b4e0bdefdd4fL,0x69958465f366e401L,0x5aa368aba73bbec0L, + 0x121487097b240c21L }, + { 0x378c323318969006L,0xcb4d73cee1fe53d1L,0x5f50a80e130c4361L, + 0xd67f59517ef5212bL } }, + /* 49 << 56 */ + { { 0xf145e21e9e70c72eL,0xb2e52e295566d2fbL,0x44eaba4a032397f5L, + 0x5e56937b7e31a7deL }, + { 0x68dcf517456c61e1L,0xbc2e954aa8b0a388L,0xe3552fa760a8b755L, + 0x03442dae73ad0cdeL } }, + /* 50 << 56 */ + { { 0x37ffe747ceb26210L,0x983545e8787baef9L,0x8b8c853586a3de31L, + 0xc621dbcbfacd46dbL }, + { 0x82e442e959266fbbL,0xa3514c37339d471cL,0x3a11b77162cdad96L, + 0xf0cb3b3cecf9bdf0L } }, + /* 51 << 56 */ + { { 0x3fcbdbce478e2135L,0x7547b5cfbda35342L,0xa97e81f18a677af6L, + 0xc8c2bf8328817987L }, + { 0xdf07eaaf45580985L,0xc68d1f05c93b45cbL,0x106aa2fec77b4cacL, + 0x4c1d8afc04a7ae86L } }, + /* 52 << 56 */ + { { 0xdb41c3fd9eb45ab2L,0x5b234b5bd4b22e74L,0xda253decf215958aL, + 0x67e0606ea04edfa0L }, + { 0xabbbf070ef751b11L,0xf352f175f6f06dceL,0xdfc4b6af6839f6b4L, + 0x53ddf9a89959848eL } }, + /* 53 << 56 */ + { { 0xda49c379c21520b0L,0x90864ff0dbd5d1b6L,0x2f055d235f49c7f7L, + 0xe51e4e6aa796b2d8L }, + { 0xc361a67f5c9dc340L,0x5ad53c37bca7c620L,0xda1d658832c756d0L, + 0xad60d9118bb67e13L } }, + /* 54 << 56 */ + { { 0xd6c47bdf0eeec8c6L,0x4a27fec1078a1821L,0x081f7415c3099524L, + 0x8effdf0b82cd8060L }, + { 0xdb70ec1c65842df8L,0x8821b358d319a901L,0x72ee56eede42b529L, + 0x5bb39592236e4286L } }, + /* 55 << 56 */ + { { 0xd1183316fd6f7140L,0xf9fadb5bbd8e81f7L,0x701d5e0c5a02d962L, + 0xfdee4dbf1b601324L }, + { 0xbed1740735d7620eL,0x04e3c2c3f48c0012L,0x9ee29da73455449aL, + 0x562cdef491a836c4L } }, + /* 56 << 56 */ + { { 0x8f682a5f47701097L,0x617125d8ff88d0c2L,0x948fda2457bb86ddL, + 0x348abb8f289f7286L }, + { 0xeb10eab599d94bbdL,0xd51ba28e4684d160L,0xabe0e51c30c8f41aL, + 0x66588b4513254f4aL } }, + /* 57 << 56 */ + { { 0x147ebf01fad097a5L,0x49883ea8610e815dL,0xe44d60ba8a11de56L, + 0xa970de6e827a7a6dL }, + { 0x2be414245e17fc19L,0xd833c65701214057L,0x1375813b363e723fL, + 0x6820bb88e6a52e9bL } }, + /* 58 << 56 */ + { { 0x7e7f6970d875d56aL,0xd6a0a9ac51fbf6bfL,0x54ba8790a3083c12L, + 0xebaeb23d6ae7eb64L }, + { 0xa8685c3ab99a907aL,0xf1e74550026bf40bL,0x7b73a027c802cd9eL, + 0x9a8a927c4fef4635L } }, + /* 59 << 56 */ + { { 0xe1b6f60c08191224L,0xc4126ebbde4ec091L,0xe1dff4dc4ae38d84L, + 0xde3f57db4f2ef985L }, + { 0x34964337d446a1ddL,0x7bf217a0859e77f6L,0x8ff105278e1d13f5L, + 0xa304ef0374eeae27L } }, + /* 60 << 56 */ + { { 0xfc6f5e47d19dfa5aL,0xdb007de37fad982bL,0x28205ad1613715f5L, + 0x251e67297889529eL }, + { 0x727051841ae98e78L,0xf818537d271cac32L,0xc8a15b7eb7f410f5L, + 0xc474356f81f62393L } }, + /* 61 << 56 */ + { { 0x92dbdc5ac242316bL,0xabe060acdbf4aff5L,0x6e8c38fe909a8ec6L, + 0x43e514e56116cb94L }, + { 0x2078fa3807d784f9L,0x1161a880f4b5b357L,0x5283ce7913adea3dL, + 0x0756c3e6cc6a910bL } }, + /* 62 << 56 */ + { { 0x60bcfe01aaa79697L,0x04a73b2956391db1L,0xdd8dad47189b45a0L, + 0xbfac0dd048d5b8d9L }, + { 0x34ab3af57d3d2ec2L,0x6fa2fc2d207bd3afL,0x9ff4009266550dedL, + 0x719b3e871fd5b913L } }, + /* 63 << 56 */ + { { 0xa573a4966d17fbc7L,0x0cd1a70a73d2b24eL,0x34e2c5cab2676937L, + 0xe7050b06bf669f21L }, + { 0xfbe948b61ede9046L,0xa053005197662659L,0x58cbd4edf10124c5L, + 0xde2646e4dd6c06c8L } }, + /* 64 << 56 */ + { { 0x332f81088cad38c0L,0x471b7e906bd68ae2L,0x56ac3fb20d8e27a3L, + 0xb54660db136b4b0dL }, + { 0x123a1e11a6fd8de4L,0x44dbffeaa37799efL,0x4540b977ce6ac17cL, + 0x495173a8af60acefL } }, + /* 0 << 63 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 63 */ + { { 0x9ebb284d391c2a82L,0xbcdd4863158308e8L,0x006f16ec83f1edcaL, + 0xa13e2c37695dc6c8L }, + { 0x2ab756f04a057a87L,0xa8765500a6b48f98L,0x4252face68651c44L, + 0xa52b540be1765e02L } }, + /* 2 << 63 */ + { { 0x4f922fc516a0d2bbL,0x0d5cc16c1a623499L,0x9241cf3a57c62c8bL, + 0x2f5e6961fd1b667fL }, + { 0x5c15c70bf5a01797L,0x3d20b44d60956192L,0x04911b37071fdb52L, + 0xf648f9168d6f0f7bL } }, + /* 3 << 63 */ + { { 0x6dc1acafe60b7cf7L,0x25860a5084a9d869L,0x56fc6f09e7ba8ac4L, + 0x828c5bd06148d29eL }, + { 0xac6b435edc55ae5fL,0xa527f56cc0117411L,0x94d5045efd24342cL, + 0x2c4c0a3570b67c0dL } }, + /* 4 << 63 */ + { { 0x027cc8b8fac61d9aL,0x7d25e062e3c6fe8aL,0xe08805bfe5bff503L, + 0x13271e6c6ff632f7L }, + { 0x55dca6c0232f76a5L,0x8957c32d701ef426L,0xee728bcba10a5178L, + 0x5ea60411b62c5173L } }, + /* 5 << 63 */ + { { 0xfc4e964ed0b8892bL,0x9ea176839301bb74L,0x6265c5aefcc48626L, + 0xe60cf82ebb3e9102L }, + { 0x57adf797d4df5531L,0x235b59a18deeefe2L,0x60adcf583f306eb1L, + 0x105c27533d09492dL } }, + /* 6 << 63 */ + { { 0x4090914bb5def996L,0x1cb69c83233dd1e7L,0xc1e9c1d39b3d5e76L, + 0x1f3338edfccf6012L }, + { 0xb1e95d0d2f5378a8L,0xacf4c2c72f00cd21L,0x6e984240eb5fe290L, + 0xd66c038d248088aeL } }, + /* 7 << 63 */ + { { 0x804d264af94d70cfL,0xbdb802ef7314bf7eL,0x8fb54de24333ed02L, + 0x740461e0285635d9L }, + { 0x4113b2c8365e9383L,0xea762c833fdef652L,0x4eec6e2e47b956c1L, + 0xa3d814be65620fa4L } }, + /* 8 << 63 */ + { { 0x9ad5462bb4d8bc50L,0x181c0b16a9195770L,0xebd4fe1c78412a68L, + 0xae0341bcc0dff48cL }, + { 0xb6bc45cf7003e866L,0xf11a6dea8a24a41bL,0x5407151ad04c24c2L, + 0x62c9d27dda5b7b68L } }, + /* 9 << 63 */ + { { 0x2e96423588cceff6L,0x8594c54f8b07ed69L,0x1578e73cc84d0d0dL, + 0x7b4e1055ff532868L }, + { 0xa348c0d5b5ec995aL,0xbf4b9d5514289a54L,0x9ba155a658fbd777L, + 0x186ed7a81a84491dL } }, + /* 10 << 63 */ + { { 0xd4992b30614c0900L,0xda98d121bd00c24bL,0x7f534dc87ec4bfa1L, + 0x4a5ff67437dc34bcL }, + { 0x68c196b81d7ea1d7L,0x38cf289380a6d208L,0xfd56cd09e3cbbd6eL, + 0xec72e27e4205a5b6L } }, + /* 11 << 63 */ + { { 0x15ea68f5a44f77f7L,0x7aa5f9fdb43c52bcL,0x86ff676f94f0e609L, + 0xa4cde9632e2d432bL }, + { 0x8cafa0c0eee470afL,0x84137d0e8a3f5ec8L,0xebb40411faa31231L, + 0xa239c13f6f7f7ccfL } }, + /* 12 << 63 */ + { { 0x32865719a8afd30bL,0x867983288a826dceL,0xdf04e891c4a8fbe0L, + 0xbb6b6e1bebf56ad3L }, + { 0x0a695b11471f1ff0L,0xd76c3389be15baf0L,0x018edb95be96c43eL, + 0xf2beaaf490794158L } }, + /* 13 << 63 */ + { { 0x152db09ec3076a27L,0x5e82908ee416545dL,0xa2c41272356d6f2eL, + 0xdc9c964231fd74e1L }, + { 0x66ceb88d519bf615L,0xe29ecd7605a2274eL,0x3a0473c4bf5e2fa0L, + 0x6b6eb67164284e67L } }, + /* 14 << 63 */ + { { 0xe8b97932b88756ddL,0xed4e8652f17e3e61L,0xc2dd14993ee1c4a4L, + 0xc0aaee17597f8c0eL }, + { 0x15c4edb96c168af3L,0x6563c7bfb39ae875L,0xadfadb6f20adb436L, + 0xad55e8c99a042ac0L } }, + /* 15 << 63 */ + { { 0x975a1ed8b76da1f5L,0x10dfa466a58acb94L,0x8dd7f7e3ac060282L, + 0x6813e66a572a051eL }, + { 0xb4ccae1e350cb901L,0xb653d65650cb7822L,0x42484710dfab3b87L, + 0xcd7ee5379b670fd0L } }, + /* 16 << 63 */ + { { 0x0a50b12e523b8bf6L,0x8009eb5b8f910c1bL,0xf535af824a167588L, + 0x0f835f9cfb2a2abdL }, + { 0xf59b29312afceb62L,0xc797df2a169d383fL,0xeb3f5fb066ac02b0L, + 0x029d4c6fdaa2d0caL } }, + /* 17 << 63 */ + { { 0xd4059bc1afab4bc5L,0x833f5c6f56783247L,0xb53466308d2d3605L, + 0x83387891d34d8433L }, + { 0xd973b30fadd9419aL,0xbcca1099afe3fce8L,0x081783150809aac6L, + 0x01b7f21a540f0f11L } }, + /* 18 << 63 */ + { { 0x65c29219909523c8L,0xa62f648fa3a1c741L,0x88598d4f60c9e55aL, + 0xbce9141b0e4f347aL }, + { 0x9af97d8435f9b988L,0x0210da62320475b6L,0x3c076e229191476cL, + 0x7520dbd944fc7834L } }, + /* 19 << 63 */ + { { 0x6a6b2cfec1ab1bbdL,0xef8a65bedc650938L,0x72855540805d7bc4L, + 0xda389396ed11fdfdL }, + { 0xa9d5bd3674660876L,0x11d67c54b45dff35L,0x6af7d148a4f5da94L, + 0xbb8d4c3fc0bbeb31L } }, + /* 20 << 63 */ + { { 0x87a7ebd1e0a1b12aL,0x1e4ef88d770ba95fL,0x8c33345cdc2ae9cbL, + 0xcecf127601cc8403L }, + { 0x687c012e1b39b80fL,0xfd90d0ad35c33ba4L,0xa3ef5a675c9661c2L, + 0x368fc88ee017429eL } }, + /* 21 << 63 */ + { { 0xd30c6761196a2fa2L,0x931b9817bd5b312eL,0xba01000c72f54a31L, + 0xa203d2c866eaa541L }, + { 0xf2abdee098939db3L,0xe37d6c2c3e606c02L,0xf2921574521ff643L, + 0x2781b3c4d7e2fca3L } }, + /* 22 << 63 */ + { { 0x664300b07850ec06L,0xac5a38b97d3a10cfL,0x9233188de34ab39dL, + 0xe77057e45072cbb9L }, + { 0xbcf0c042b59e78dfL,0x4cfc91e81d97de52L,0x4661a26c3ee0ca4aL, + 0x5620a4c1fb8507bcL } }, + /* 23 << 63 */ + { { 0x4b44d4aa049f842cL,0xceabc5d51540e82bL,0x306710fd15c6f156L, + 0xbe5ae52b63db1d72L }, + { 0x06f1e7e6334957f1L,0x57e388f031144a70L,0xfb69bb2fdf96447bL, + 0x0f78ebd373e38a12L } }, + /* 24 << 63 */ + { { 0xb82226052b7ce542L,0xe6d4ce997472bde1L,0x53e16ebe09d2f4daL, + 0x180ff42e53b92b2eL }, + { 0xc59bcc022c34a1c6L,0x3803d6f9422c46c2L,0x18aff74f5c14a8a2L, + 0x55aebf8010a08b28L } }, + /* 25 << 63 */ + { { 0x66097d587135593fL,0x32e6eff72be570cdL,0x584e6a102a8c860dL, + 0xcd185890a2eb4163L }, + { 0x7ceae99d6d97e134L,0xd42c6b70dd8447ceL,0x59ddbb4ab8c50273L, + 0x03c612df3cf34e1eL } }, + /* 26 << 63 */ + { { 0x84b9ca1504b6c5a0L,0x35216f3918f0e3a3L,0x3ec2d2bcbd986c00L, + 0x8bf546d9d19228feL }, + { 0xd1c655a44cd623c3L,0x366ce718502b8e5aL,0x2cfc84b4eea0bfe7L, + 0xe01d5ceecf443e8eL } }, + /* 27 << 63 */ + { { 0x8ec045d9036520f8L,0xdfb3c3d192d40e98L,0x0bac4ccecc559a04L, + 0x35eccae5240ea6b1L }, + { 0x180b32dbf8a5a0acL,0x547972a5eb699700L,0xa3765801ca26bca0L, + 0x57e09d0ea647f25aL } }, + /* 28 << 63 */ + { { 0xb956970e2fdd23ccL,0xb80288bc5682e971L,0xe6e6d91e9ae86ebcL, + 0x0564c83f8c9f1939L }, + { 0x551932a239560368L,0xe893752b049c28e2L,0x0b03cee5a6a158c3L, + 0xe12d656b04964263L } }, + /* 29 << 63 */ + { { 0x4b47554e63e3bc1dL,0xc719b6a245044ff7L,0x4f24d30ae48daa07L, + 0xa3f37556c8c1edc3L }, + { 0x9a47bf760700d360L,0xbb1a1824822ae4e2L,0x22e275a389f1fb4cL, + 0x72b1aa239968c5f5L } }, + /* 30 << 63 */ + { { 0xa75feacabe063f64L,0x9b392f43bce47a09L,0xd42415091ad07acaL, + 0x4b0c591b8d26cd0fL }, + { 0x2d42ddfd92f1169aL,0x63aeb1ac4cbf2392L,0x1de9e8770691a2afL, + 0xebe79af7d98021daL } }, + /* 31 << 63 */ + { { 0xcfdf2a4e40e50acfL,0xf0a98ad7af01d665L,0xefb640bf1831be1fL, + 0x6fe8bd2f80e9ada0L }, + { 0x94c103a16cafbc91L,0x170f87598308e08cL,0x5de2d2ab9780ff4fL, + 0x666466bc45b201f2L } }, + /* 32 << 63 */ + { { 0x58af2010f5b343bcL,0x0f2e400af2f142feL,0x3483bfdea85f4bdfL, + 0xf0b1d09303bfeaa9L }, + { 0x2ea01b95c7081603L,0xe943e4c93dba1097L,0x47be92adb438f3a6L, + 0x00bb7742e5bf6636L } }, + /* 33 << 63 */ + { { 0x136b7083824297b4L,0x9d0e55805584455fL,0xab48cedcf1c7d69eL, + 0x53a9e4812a256e76L }, + { 0x0402b0e065eb2413L,0xdadbbb848fc407a7L,0xa65cd5a48d7f5492L, + 0x21d4429374bae294L } }, + /* 34 << 63 */ + { { 0x66917ce63b5f1cc4L,0x37ae52eace872e62L,0xbb087b722905f244L, + 0x120770861e6af74fL }, + { 0x4b644e491058edeaL,0x827510e3b638ca1dL,0x8cf2b7046038591cL, + 0xffc8b47afe635063L } }, + /* 35 << 63 */ + { { 0x3ae220e61b4d5e63L,0xbd8647429d961b4bL,0x610c107e9bd16bedL, + 0x4270352a1127147bL }, + { 0x7d17ffe664cfc50eL,0x50dee01a1e36cb42L,0x068a762235dc5f9aL, + 0x9a08d536df53f62cL } }, + /* 36 << 63 */ + { { 0x4ed714576be5f7deL,0xd93006f8c2263c9eL,0xe073694ccacacb36L, + 0x2ff7a5b43ae118abL }, + { 0x3cce53f1cd871236L,0xf156a39dc2aa6d52L,0x9cc5f271b198d76dL, + 0xbc615b6f81383d39L } }, + /* 37 << 63 */ + { { 0xa54538e8de3eee6bL,0x58c77538ab910d91L,0x31e5bdbc58d278bdL, + 0x3cde4adfb963acaeL }, + { 0xb1881fd25302169cL,0x8ca60fa0a989ed8bL,0xa1999458ff96a0eeL, + 0xc1141f03ac6c283dL } }, + /* 38 << 63 */ + { { 0x7677408d6dfafed3L,0x33a0165339661588L,0x3c9c15ec0b726fa0L, + 0x090cfd936c9b56daL }, + { 0xe34f4baea3c40af5L,0x3469eadbd21129f1L,0xcc51674a1e207ce8L, + 0x1e293b24c83b1ef9L } }, + /* 39 << 63 */ + { { 0x17173d131e6c0bb4L,0x1900469590776d35L,0xe7980e346de6f922L, + 0x873554cbf4dd9a22L }, + { 0x0316c627cbf18a51L,0x4d93651b3032c081L,0x207f27713946834dL, + 0x2c08d7b430cdbf80L } }, + /* 40 << 63 */ + { { 0x137a4fb486df2a61L,0xa1ed9c07ecf7b4a2L,0xb2e460e27bd042ffL, + 0xb7f5e2fa5f62f5ecL }, + { 0x7aa6ec6bcc2423b7L,0x75ce0a7fba63eea7L,0x67a45fb1f250a6e1L, + 0x93bc919ce53cdc9fL } }, + /* 41 << 63 */ + { { 0x9271f56f871942dfL,0x2372ff6f7859ad66L,0x5f4c2b9633cb1a78L, + 0xe3e291015838aa83L }, + { 0xa7ed1611e4e8110cL,0x2a2d70d5330198ceL,0xbdf132e86720efe0L, + 0xe61a896266a471bfL } }, + /* 42 << 63 */ + { { 0x796d3a85825808bdL,0x51dc3cb73fd6e902L,0x643c768a916219d1L, + 0x36cd7685a2ad7d32L }, + { 0xe3db9d05b22922a4L,0x6494c87edba29660L,0xf0ac91dfbcd2ebc7L, + 0x4deb57a045107f8dL } }, + /* 43 << 63 */ + { { 0x42271f59c3d12a73L,0x5f71687ca5c2c51dL,0xcb1f50c605797bcbL, + 0x29ed0ed9d6d34eb0L }, + { 0xe5fe5b474683c2ebL,0x4956eeb597447c46L,0x5b163a4371207167L, + 0x93fa2fed0248c5efL } }, + /* 44 << 63 */ + { { 0x67930af231f63950L,0xa77797c114caa2c9L,0x526e80ee27ac7e62L, + 0xe1e6e62658b28aecL }, + { 0x636178b0b3c9fef0L,0xaf7752e06d5f90beL,0x94ecaf18eece51cfL, + 0x2864d0edca806e1fL } }, + /* 45 << 63 */ + { { 0x6de2e38397c69134L,0x5a42c316eb291293L,0xc77792196a60bae0L, + 0xa24de3466b7599d1L }, + { 0x49d374aab75d4941L,0x989005862d501ff0L,0x9f16d40eeb7974cfL, + 0x1033860bcdd8c115L } }, + /* 46 << 63 */ + { { 0xb6c69ac82094cec3L,0x9976fb88403b770cL,0x1dea026c4859590dL, + 0xb6acbb468562d1fdL }, + { 0x7cd6c46144569d85L,0xc3190a3697f0891dL,0xc6f5319548d5a17dL, + 0x7d919966d749abc8L } }, + /* 47 << 63 */ + { { 0x65104837dd1c8a20L,0x7e5410c82f683419L,0x958c3ca8be94022eL, + 0x605c31976145dac2L }, + { 0x3fc0750101683d54L,0x1d7127c5595b1234L,0x10b8f87c9481277fL, + 0x677db2a8e65a1adbL } }, + /* 48 << 63 */ + { { 0xec2fccaaddce3345L,0x2a6811b7012a4350L,0x96760ff1ac598bdcL, + 0x054d652ad1bf4128L }, + { 0x0a1151d492a21005L,0xad7f397133110fdfL,0x8c95928c1960100fL, + 0x6c91c8257bf03362L } }, + /* 49 << 63 */ + { { 0xc8c8b2a2ce309f06L,0xfdb27b59ca27204bL,0xd223eaa50848e32eL, + 0xb93e4b2ee7bfaf1eL }, + { 0xc5308ae644aa3dedL,0x317a666ac015d573L,0xc888ce231a979707L, + 0xf141c1e60d5c4958L } }, + /* 50 << 63 */ + { { 0xb53b7de561906373L,0x858dbadeeb999595L,0x8cbb47b2a59e5c36L, + 0x660318b3dcf4e842L }, + { 0xbd161ccd12ba4b7aL,0xf399daabf8c8282aL,0x1587633aeeb2130dL, + 0xa465311ada38dd7dL } }, + /* 51 << 63 */ + { { 0x5f75eec864d3779bL,0x3c5d0476ad64c171L,0x874103712a914428L, + 0x8096a89190e2fc29L }, + { 0xd3d2ae9d23b3ebc2L,0x90bdd6dba580cfd6L,0x52dbb7f3c5b01f6cL, + 0xe68eded4e102a2dcL } }, + /* 52 << 63 */ + { { 0x17785b7799eb6df0L,0x26c3cc517386b779L,0x345ed9886417a48eL, + 0xe990b4e407d6ef31L }, + { 0x0f456b7e2586abbaL,0x239ca6a559c96e9aL,0xe327459ce2eb4206L, + 0x3a4c3313a002b90aL } }, + /* 53 << 63 */ + { { 0x2a114806f6a3f6fbL,0xad5cad2f85c251ddL,0x92c1f613f5a784d3L, + 0xec7bfacf349766d5L }, + { 0x04b3cd333e23cb3bL,0x3979fe84c5a64b2dL,0x192e27207e589106L, + 0xa60c43d1a15b527fL } }, + /* 54 << 63 */ + { { 0x2dae9082be7cf3a6L,0xcc86ba92bc967274L,0xf28a2ce8aea0a8a9L, + 0x404ca6d96ee988b3L }, + { 0xfd7e9c5d005921b8L,0xf56297f144e79bf9L,0xa163b4600d75ddc2L, + 0x30b23616a1f2be87L } }, + /* 55 << 63 */ + { { 0x4b070d21bfe50e2bL,0x7ef8cfd0e1bfede1L,0xadba00112aac4ae0L, + 0x2a3e7d01b9ebd033L }, + { 0x995277ece38d9d1cL,0xb500249e9c5d2de3L,0x8912b820f13ca8c9L, + 0xc8798114877793afL } }, + /* 56 << 63 */ + { { 0x19e6125dec3f1decL,0x07b1f040911178daL,0xd93ededa904a6738L, + 0x55187a5a0bebedcdL }, + { 0xf7d04722eb329d41L,0xf449099ef170b391L,0xfd317a69ca99f828L, + 0x50c3db2b34a4976dL } }, + /* 57 << 63 */ + { { 0xe9ba77843757b392L,0x326caefdaa3ca05aL,0x78e5293bf1e593d4L, + 0x7842a9370d98fd13L }, + { 0xe694bf965f96b10dL,0x373a9df606a8cd05L,0x997d1e51e8f0c7fcL, + 0x1d01979063fd972eL } }, + /* 58 << 63 */ + { { 0x0064d8585499fb32L,0x7b67bad977a8aeb7L,0x1d3eb9772d08eec5L, + 0x5fc047a6cbabae1dL }, + { 0x0577d159e54a64bbL,0x8862201bc43497e4L,0xad6b4e282ce0608dL, + 0x8b687b7d0b167aacL } }, + /* 59 << 63 */ + { { 0x6ed4d3678b2ecfa9L,0x24dfe62da90c3c38L,0xa1862e103fe5c42bL, + 0x1ca73dcad5732a9fL }, + { 0x35f038b776bb87adL,0x674976abf242b81fL,0x4f2bde7eb0fd90cdL, + 0x6efc172ea7fdf092L } }, + /* 60 << 63 */ + { { 0x3806b69b92222f1fL,0x5a2459ca6cf7ae70L,0x6789f69ca85217eeL, + 0x5f232b5ee3dc85acL }, + { 0x660e3ec548e9e516L,0x124b4e473197eb31L,0x10a0cb13aafcca23L, + 0x7bd63ba48213224fL } }, + /* 61 << 63 */ + { { 0xaffad7cc290a7f4fL,0x6b409c9e0286b461L,0x58ab809fffa407afL, + 0xc3122eedc68ac073L }, + { 0x17bf9e504ef24d7eL,0x5d9297943e2a5811L,0x519bc86702902e01L, + 0x76bba5da39c8a851L } }, + /* 62 << 63 */ + { { 0xe9f9669cda94951eL,0x4b6af58d66b8d418L,0xfa32107417d426a4L, + 0xc78e66a99dde6027L }, + { 0x0516c0834a53b964L,0xfc659d38ff602330L,0x0ab55e5c58c5c897L, + 0x985099b2838bc5dfL } }, + /* 63 << 63 */ + { { 0x061d9efcc52fc238L,0x712b27286ac1da3fL,0xfb6581499283fe08L, + 0x4954ac94b8aaa2f7L }, + { 0x85c0ada47fb2e74fL,0xee8ba98eb89926b0L,0xe4f9d37d23d1af5bL, + 0x14ccdbf9ba9b015eL } }, + /* 64 << 63 */ + { { 0xb674481b7bfe7178L,0x4e1debae65405868L,0x061b2821c48c867dL, + 0x69c15b35513b30eaL }, + { 0x3b4a166636871088L,0xe5e29f5d1220b1ffL,0x4b82bb35233d9f4dL, + 0x4e07633318cdc675L } }, + /* 0 << 70 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 70 */ + { { 0x0d53f5c7a3e6fcedL,0xe8cbbdd5f45fbdebL,0xf85c01df13339a70L, + 0x0ff71880142ceb81L }, + { 0x4c4e8774bd70437aL,0x5fb32891ba0bda6aL,0x1cdbebd2f18bd26eL, + 0x2f9526f103a9d522L } }, + /* 2 << 70 */ + { { 0x40ce305192c4d684L,0x8b04d7257612efcdL,0xb9dcda366f9cae20L, + 0x0edc4d24f058856cL }, + { 0x64f2e6bf85427900L,0x3de81295dc09dfeaL,0xd41b4487379bf26cL, + 0x50b62c6d6df135a9L } }, + /* 3 << 70 */ + { { 0xd4f8e3b4c72dfe67L,0xc416b0f690e19fdfL,0x18b9098d4c13bd35L, + 0xac11118a15b8cb9eL }, + { 0xf598a318f0062841L,0xbfe0602f89f356f4L,0x7ae3637e30177a0cL, + 0x3409774761136537L } }, + /* 4 << 70 */ + { { 0x0db2fb5ed005832aL,0x5f5efd3b91042e4fL,0x8c4ffdc6ed70f8caL, + 0xe4645d0bb52da9ccL }, + { 0x9596f58bc9001d1fL,0x52c8f0bc4e117205L,0xfd4aa0d2e398a084L, + 0x815bfe3a104f49deL } }, + /* 5 << 70 */ + { { 0x97e5443f23885e5fL,0xf72f8f99e8433aabL,0xbd00b154e4d4e604L, + 0xd0b35e6ae5e173ffL }, + { 0x57b2a0489164722dL,0x3e3c665b88761ec8L,0x6bdd13973da83832L, + 0x3c8b1a1e73dafe3bL } }, + /* 6 << 70 */ + { { 0x4497ace654317cacL,0xbe600ab9521771b3L,0xb42e409eb0dfe8b8L, + 0x386a67d73942310fL }, + { 0x25548d8d4431cc28L,0xa7cff142985dc524L,0x4d60f5a193c4be32L, + 0x83ebd5c8d071c6e1L } }, + /* 7 << 70 */ + { { 0xba3a80a7b1fd2b0bL,0x9b3ad3965bec33e8L,0xb3868d6179743fb3L, + 0xcfd169fcfdb462faL }, + { 0xd3b499d79ce0a6afL,0x55dc1cf1e42d3ff8L,0x04fb9e6cc6c3e1b2L, + 0x47e6961d6f69a474L } }, + /* 8 << 70 */ + { { 0x54eb3acce548b37bL,0xb38e754284d40549L,0x8c3daa517b341b4fL, + 0x2f6928ec690bf7faL }, + { 0x0496b32386ce6c41L,0x01be1c5510adadcdL,0xc04e67e74bb5faf9L, + 0x3cbaf678e15c9985L } }, + /* 9 << 70 */ + { { 0x8cd1214550ca4247L,0xba1aa47ae7dd30aaL,0x2f81ddf1e58fee24L, + 0x03452936eec9b0e8L }, + { 0x8bdc3b81243aea96L,0x9a2919af15c3d0e5L,0x9ea640ec10948361L, + 0x5ac86d5b6e0bcccfL } }, + /* 10 << 70 */ + { { 0xf892d918c36cf440L,0xaed3e837c939719cL,0xb07b08d2c0218b64L, + 0x6f1bcbbace9790ddL }, + { 0x4a84d6ed60919b8eL,0xd89007918ac1f9ebL,0xf84941aa0dd5daefL, + 0xb22fe40a67fd62c5L } }, + /* 11 << 70 */ + { { 0x97e15ba2157f2db3L,0xbda2fc8f8e28ca9cL,0x5d050da437b9f454L, + 0x3d57eb572379d72eL }, + { 0xe9b5eba2fb5ee997L,0x01648ca2e11538caL,0x32bb76f6f6327974L, + 0x338f14b8ff3f4bb7L } }, + /* 12 << 70 */ + { { 0x524d226ad7ab9a2dL,0x9c00090d7dfae958L,0x0ba5f5398751d8c2L, + 0x8afcbcdd3ab8262dL }, + { 0x57392729e99d043bL,0xef51263baebc943aL,0x9feace9320862935L, + 0x639efc03b06c817bL } }, + /* 13 << 70 */ + { { 0x1fe054b366b4be7aL,0x3f25a9de84a37a1eL,0xf39ef1ad78d75cd9L, + 0xd7b58f495062c1b5L }, + { 0x6f74f9a9ff563436L,0xf718ff29e8af51e7L,0x5234d31315e97fecL, + 0xb6a8e2b1292f1c0aL } }, + /* 14 << 70 */ + { { 0xa7f53aa8327720c1L,0x956ca322ba092cc8L,0x8f03d64a28746c4dL, + 0x51fe178266d0d392L }, + { 0xd19b34db3c832c80L,0x60dccc5c6da2e3b4L,0x245dd62e0a104cccL, + 0xa7ab1de1620b21fdL } }, + /* 15 << 70 */ + { { 0xb293ae0b3893d123L,0xf7b75783b15ee71cL,0x5aa3c61442a9468bL, + 0xd686123cdb15d744L }, + { 0x8c616891a7ab4116L,0x6fcd72c8a4e6a459L,0xac21911077e5fad7L, + 0xfb6a20e7704fa46bL } }, + /* 16 << 70 */ + { { 0xe839be7d341d81dcL,0xcddb688932148379L,0xda6211a1f7026eadL, + 0xf3b2575ff4d1cc5eL }, + { 0x40cfc8f6a7a73ae6L,0x83879a5e61d5b483L,0xc5acb1ed41a50ebcL, + 0x59a60cc83c07d8faL } }, + /* 17 << 70 */ + { { 0x1b73bdceb1876262L,0x2b0d79f012af4ee9L,0x8bcf3b0bd46e1d07L, + 0x17d6af9de45d152fL }, + { 0x735204616d736451L,0x43cbbd9756b0bf5aL,0xb0833a5bd5999b9dL, + 0x702614f0eb72e398L } }, + /* 18 << 70 */ + { { 0x0aadf01a59c3e9f8L,0x40200e77ce6b3d16L,0xda22bdd3deddafadL, + 0x76dedaf4310d72e1L }, + { 0x49ef807c4bc2e88fL,0x6ba81291146dd5a5L,0xa1a4077a7d8d59e9L, + 0x87b6a2e7802db349L } }, + /* 19 << 70 */ + { { 0xd56799971b4e598eL,0xf499ef1f06fe4b1dL,0x3978d3aefcb267c5L, + 0xb582b557235786d0L }, + { 0x32b3b2ca1715cb07L,0x4c3de6a28480241dL,0x63b5ffedcb571ecdL, + 0xeaf53900ed2fe9a9L } }, + /* 20 << 70 */ + { { 0xdec98d4ac3b81990L,0x1cb837229e0cc8feL,0xfe0b0491d2b427b9L, + 0x0f2386ace983a66cL }, + { 0x930c4d1eb3291213L,0xa2f82b2e59a62ae4L,0x77233853f93e89e3L, + 0x7f8063ac11777c7fL } }, + /* 21 << 70 */ + { { 0xff0eb56759ad2877L,0x6f4546429865c754L,0xe6fe701a236e9a84L, + 0xc586ef1606e40fc3L }, + { 0x3f62b6e024bafad9L,0xc8b42bd264da906aL,0xc98e1eb4da3276a0L, + 0x30d0e5fc06cbf852L } }, + /* 22 << 70 */ + { { 0x1b6b2ae1e8b4dfd4L,0xd754d5c78301cbacL,0x66097629112a39acL, + 0xf86b599993ba4ab9L }, + { 0x26c9dea799f9d581L,0x0473b1a8c2fafeaaL,0x1469af553b2505a5L, + 0x227d16d7d6a43323L } }, + /* 23 << 70 */ + { { 0x3316f73cad3d97f9L,0x52bf3bb51f137455L,0x953eafeb09954e7cL, + 0xa721dfeddd732411L }, + { 0xb4929821141d4579L,0x3411321caa3bd435L,0xafb355aa17fa6015L, + 0xb4e7ef4a18e42f0eL } }, + /* 24 << 70 */ + { { 0x604ac97c59371000L,0xe1c48c707f759c18L,0x3f62ecc5a5db6b65L, + 0x0a78b17338a21495L }, + { 0x6be1819dbcc8ad94L,0x70dc04f6d89c3400L,0x462557b4a6b4840aL, + 0x544c6ade60bd21c0L } }, + /* 25 << 70 */ + { { 0x6a00f24e907a544bL,0xa7520dcb313da210L,0xfe939b7511e4994bL, + 0x918b6ba6bc275d70L }, + { 0xd3e5e0fc644be892L,0x707a9816fdaf6c42L,0x60145567f15c13feL, + 0x4818ebaae130a54aL } }, + /* 26 << 70 */ + { { 0x28aad3ad58d2f767L,0xdc5267fdd7e7c773L,0x4919cc88c3afcc98L, + 0xaa2e6ab02db8cd4bL }, + { 0xd46fec04d0c63eaaL,0xa1cb92c519ffa832L,0x678dd178e43a631fL, + 0xfb5ae1cd3dc788b3L } }, + /* 27 << 70 */ + { { 0x68b4fb906e77de04L,0x7992bcf0f06dbb97L,0x896e6a13c417c01dL, + 0x8d96332cb956be01L }, + { 0x902fc93a413aa2b9L,0x99a4d915fc98c8a5L,0x52c29407565f1137L, + 0x4072690f21e4f281L } }, + /* 28 << 70 */ + { { 0x36e607cf02ff6072L,0xa47d2ca98ad98cdcL,0xbf471d1ef5f56609L, + 0xbcf86623f264ada0L }, + { 0xb70c0687aa9e5cb6L,0xc98124f217401c6cL,0x8189635fd4a61435L, + 0xd28fb8afa9d98ea6L } }, + /* 29 << 70 */ + { { 0xb9a67c2a40c251f8L,0x88cd5d87a2da44beL,0x437deb96e09b5423L, + 0x150467db64287dc1L }, + { 0xe161debbcdabb839L,0xa79e9742f1839a3eL,0xbb8dd3c2652d202bL, + 0x7b3e67f7e9f97d96L } }, + /* 30 << 70 */ + { { 0x5aa5d78fb1cb6ac9L,0xffa13e8eca1d0d45L,0x369295dd2ba5bf95L, + 0xd68bd1f839aff05eL }, + { 0xaf0d86f926d783f2L,0x543a59b3fc3aafc1L,0x3fcf81d27b7da97cL, + 0xc990a056d25dee46L } }, + /* 31 << 70 */ + { { 0x3e6775b8519cce2cL,0xfc9af71fae13d863L,0x774a4a6f47c1605cL, + 0x46ba42452fd205e8L }, + { 0xa06feea4d3fd524dL,0x1e7246416de1acc2L,0xf53816f1334e2b42L, + 0x49e5918e922f0024L } }, + /* 32 << 70 */ + { { 0x439530b665c7322dL,0xcf12cc01b3c1b3fbL,0xc70b01860172f685L, + 0xb915ee221b58391dL }, + { 0x9afdf03ba317db24L,0x87dec65917b8ffc4L,0x7f46597be4d3d050L, + 0x80a1c1ed006500e7L } }, + /* 33 << 70 */ + { { 0x84902a9678bf030eL,0xfb5e9c9a50560148L,0x6dae0a9263362426L, + 0xdcaeecf4a9e30c40L }, + { 0xc0d887bb518d0c6bL,0x99181152cb985b9dL,0xad186898ef7bc381L, + 0x18168ffb9ee46201L } }, + /* 34 << 70 */ + { { 0x9a04cdaa2502753cL,0xbb279e2651407c41L,0xeacb03aaf23564e5L, + 0x1833658271e61016L }, + { 0x8684b8c4eb809877L,0xb336e18dea0e672eL,0xefb601f034ee5867L, + 0x2733edbe1341cfd1L } }, + /* 35 << 70 */ + { { 0xb15e809a26025c3cL,0xe6e981a69350df88L,0x923762378502fd8eL, + 0x4791f2160c12be9bL }, + { 0xb725678925f02425L,0xec8631947a974443L,0x7c0ce882fb41cc52L, + 0xc266ff7ef25c07f2L } }, + /* 36 << 70 */ + { { 0x3d4da8c3017025f3L,0xefcf628cfb9579b4L,0x5c4d00161f3716ecL, + 0x9c27ebc46801116eL }, + { 0x5eba0ea11da1767eL,0xfe15145247004c57L,0x3ace6df68c2373b7L, + 0x75c3dffe5dbc37acL } }, + /* 37 << 70 */ + { { 0x3dc32a73ddc925fcL,0xb679c8412f65ee0bL,0x715a3295451cbfebL, + 0xd9889768f76e9a29L }, + { 0xec20ce7fb28ad247L,0xe99146c400894d79L,0x71457d7c9f5e3ea7L, + 0x097b266238030031L } }, + /* 38 << 70 */ + { { 0xdb7f6ae6cf9f82a8L,0x319decb9438f473aL,0xa63ab386283856c3L, + 0x13e3172fb06a361bL }, + { 0x2959f8dc7d5a006cL,0x2dbc27c675fba752L,0xc1227ab287c22c9eL, + 0x06f61f7571a268b2L } }, + /* 39 << 70 */ + { { 0x1b6bb97104779ce2L,0xaca838120aadcb1dL,0x297ae0bcaeaab2d5L, + 0xa5c14ee75bfb9f13L }, + { 0xaa00c583f17a62c7L,0x39eb962c173759f6L,0x1eeba1d486c9a88fL, + 0x0ab6c37adf016c5eL } }, + /* 40 << 70 */ + { { 0xa2a147dba28a0749L,0x246c20d6ee519165L,0x5068d1b1d3810715L, + 0xb1e7018c748160b9L }, + { 0x03f5b1faf380ff62L,0xef7fb1ddf3cb2c1eL,0xeab539a8fc91a7daL, + 0x83ddb707f3f9b561L } }, + /* 41 << 70 */ + { { 0xc550e211fe7df7a4L,0xa7cd07f2063f6f40L,0xb0de36352976879cL, + 0xb5f83f85e55741daL }, + { 0x4ea9d25ef3d8ac3dL,0x6fe2066f62819f02L,0x4ab2b9c2cef4a564L, + 0x1e155d965ffa2de3L } }, + /* 42 << 70 */ + { { 0x0eb0a19bc3a72d00L,0x4037665b8513c31bL,0x2fb2b6bf04c64637L, + 0x45c34d6e08cdc639L }, + { 0x56f1e10ff01fd796L,0x4dfb8101fe3667b8L,0xe0eda2539021d0c0L, + 0x7a94e9ff8a06c6abL } }, + /* 43 << 70 */ + { { 0x2d3bb0d9bb9aa882L,0xea20e4e5ec05fd10L,0xed7eeb5f1a1ca64eL, + 0x2fa6b43cc6327cbdL }, + { 0xb577e3cf3aa91121L,0x8c6bd5ea3a34079bL,0xd7e5ba3960e02fc0L, + 0xf16dd2c390141bf8L } }, + /* 44 << 70 */ + { { 0xb57276d980101b98L,0x760883fdb82f0f66L,0x89d7de754bc3eff3L, + 0x03b606435dc2ab40L }, + { 0xcd6e53dfe05beeacL,0xf2f1e862bc3325cdL,0xdd0f7921774f03c3L, + 0x97ca72214552cc1bL } }, + /* 45 << 70 */ + { { 0x5a0d6afe1cd19f72L,0xa20915dcf183fbebL,0x9fda4b40832c403cL, + 0x32738eddbe425442L }, + { 0x469a1df6b5eccf1aL,0x4b5aff4228bbe1f0L,0x31359d7f570dfc93L, + 0xa18be235f0088628L } }, + /* 46 << 70 */ + { { 0xa5b30fbab00ed3a9L,0x34c6137473cdf8beL,0x2c5c5f46abc56797L, + 0x5cecf93db82a8ae2L }, + { 0x7d3dbe41a968fbf0L,0xd23d45831a5c7f3dL,0xf28f69a0c087a9c7L, + 0xc2d75471474471caL } }, + /* 47 << 70 */ + { { 0x36ec9f4a4eb732ecL,0x6c943bbdb1ca6bedL,0xd64535e1f2457892L, + 0x8b84a8eaf7e2ac06L }, + { 0xe0936cd32499dd5fL,0x12053d7e0ed04e57L,0x4bdd0076e4305d9dL, + 0x34a527b91f67f0a2L } }, + /* 48 << 70 */ + { { 0xe79a4af09cec46eaL,0xb15347a1658b9bc7L,0x6bd2796f35af2f75L, + 0xac9579904051c435L }, + { 0x2669dda3c33a655dL,0x5d503c2e88514aa3L,0xdfa113373753dd41L, + 0x3f0546730b754f78L } }, + /* 49 << 70 */ + { { 0xbf185677496125bdL,0xfb0023c83775006cL,0xfa0f072f3a037899L, + 0x4222b6eb0e4aea57L }, + { 0x3dde5e767866d25aL,0xb6eb04f84837aa6fL,0x5315591a2cf1cdb8L, + 0x6dfb4f412d4e683cL } }, + /* 50 << 70 */ + { { 0x7e923ea448ee1f3aL,0x9604d9f705a2afd5L,0xbe1d4a3340ea4948L, + 0x5b45f1f4b44cbd2fL }, + { 0x5faf83764acc757eL,0xa7cf9ab863d68ff7L,0x8ad62f69df0e404bL, + 0xd65f33c212bdafdfL } }, + /* 51 << 70 */ + { { 0xc365de15a377b14eL,0x6bf5463b8e39f60cL,0x62030d2d2ce68148L, + 0xd95867efe6f843a8L }, + { 0xd39a0244ef5ab017L,0x0bd2d8c14ab55d12L,0xc9503db341639169L, + 0x2d4e25b0f7660c8aL } }, + /* 52 << 70 */ + { { 0x760cb3b5e224c5d7L,0xfa3baf8c68616919L,0x9fbca1138d142552L, + 0x1ab18bf17669ebf5L }, + { 0x55e6f53e9bdf25ddL,0x04cc0bf3cb6cd154L,0x595bef4995e89080L, + 0xfe9459a8104a9ac1L } }, + /* 53 << 70 */ + { { 0xad2d89cacce9bb32L,0xddea65e1f7de8285L,0x62ed8c35b351bd4bL, + 0x4150ff360c0e19a7L }, + { 0x86e3c801345f4e47L,0x3bf21f71203a266cL,0x7ae110d4855b1f13L, + 0x5d6aaf6a07262517L } }, + /* 54 << 70 */ + { { 0x1e0f12e1813d28f1L,0x6000e11d7ad7a523L,0xc7d8deefc744a17bL, + 0x1e990b4814c05a00L }, + { 0x68fddaee93e976d5L,0x696241d146610d63L,0xb204e7c3893dda88L, + 0x8bccfa656a3a6946L } }, + /* 55 << 70 */ + { { 0xb59425b4c5cd1411L,0x701b4042ff3658b1L,0xe3e56bca4784cf93L, + 0x27de5f158fe68d60L }, + { 0x4ab9cfcef8d53f19L,0xddb10311a40a730dL,0x6fa73cd14eee0a8aL, + 0xfd5487485249719dL } }, + /* 56 << 70 */ + { { 0x49d66316a8123ef0L,0x73c32db4e7f95438L,0x2e2ed2090d9e7854L, + 0xf98a93299d9f0507L }, + { 0xc5d33cf60c6aa20aL,0x9a32ba1475279bb2L,0x7e3202cb774a7307L, + 0x64ed4bc4e8c42dbdL } }, + /* 57 << 70 */ + { { 0xc20f1a06d4caed0dL,0xb8021407171d22b3L,0xd426ca04d13268d7L, + 0x9237700725f4d126L }, + { 0x4204cbc371f21a85L,0x18461b7af82369baL,0xc0c07d313fc858f9L, + 0x5deb5a50e2bab569L } }, + /* 58 << 70 */ + { { 0xd5959d46d5eea89eL,0xfdff842408437f4bL,0xf21071e43cfe254fL, + 0x7241769695468321L }, + { 0x5d8288b9102cae3eL,0x2d143e3df1965dffL,0x00c9a376a078d847L, + 0x6fc0da3126028731L } }, + /* 59 << 70 */ + { { 0xa2baeadfe45083a2L,0x66bc72185e5b4bcdL,0x2c826442d04b8e7fL, + 0xc19f54516c4b586bL }, + { 0x60182c495b7eeed5L,0xd9954ecd7aa9dfa1L,0xa403a8ecc73884adL, + 0x7fb17de29bb39041L } }, + /* 60 << 70 */ + { { 0x694b64c5abb020e8L,0x3d18c18419c4eec7L,0x9c4673ef1c4793e5L, + 0xc7b8aeb5056092e6L }, + { 0x3aa1ca43f0f8c16bL,0x224ed5ecd679b2f6L,0x0d56eeaf55a205c9L, + 0xbfe115ba4b8e028bL } }, + /* 61 << 70 */ + { { 0x97e608493927f4feL,0xf91fbf94759aa7c5L,0x985af7696be90a51L, + 0xc1277b7878ccb823L }, + { 0x395b656ee7a75952L,0x00df7de0928da5f5L,0x09c231754ca4454fL, + 0x4ec971f47aa2d3c1L } }, + /* 62 << 70 */ + { { 0x45c3c507e75d9cccL,0x63b7be8a3dc90306L,0x37e09c665db44bdcL, + 0x50d60da16841c6a2L }, + { 0x6f9b65ee08df1b12L,0x387348797ff089dfL,0x9c331a663fe8013dL, + 0x017f5de95f42fcc8L } }, + /* 63 << 70 */ + { { 0x43077866e8e57567L,0xc9f781cef9fcdb18L,0x38131dda9b12e174L, + 0x25d84aa38a03752aL }, + { 0x45e09e094d0c0ce2L,0x1564008b92bebba5L,0xf7e8ad31a87284c7L, + 0xb7c4b46c97e7bbaaL } }, + /* 64 << 70 */ + { { 0x3e22a7b397acf4ecL,0x0426c4005ea8b640L,0x5e3295a64e969285L, + 0x22aabc59a6a45670L }, + { 0xb929714c5f5942bcL,0x9a6168bdfa3182edL,0x2216a665104152baL, + 0x46908d03b6926368L } }, + /* 0 << 77 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 77 */ + { { 0xa9f5d8745a1251fbL,0x967747a8c72725c7L,0x195c33e531ffe89eL, + 0x609d210fe964935eL }, + { 0xcafd6ca82fe12227L,0xaf9b5b960426469dL,0x2e9ee04c5693183cL, + 0x1084a333c8146fefL } }, + /* 2 << 77 */ + { { 0x96649933aed1d1f7L,0x566eaff350563090L,0x345057f0ad2e39cfL, + 0x148ff65b1f832124L }, + { 0x042e89d4cf94cf0dL,0x319bec84520c58b3L,0x2a2676265361aa0dL, + 0xc86fa3028fbc87adL } }, + /* 3 << 77 */ + { { 0xfc83d2ab5c8b06d5L,0xb1a785a2fe4eac46L,0xb99315bc846f7779L, + 0xcf31d816ef9ea505L }, + { 0x2391fe6a15d7dc85L,0x2f132b04b4016b33L,0x29547fe3181cb4c7L, + 0xdb66d8a6650155a1L } }, + /* 4 << 77 */ + { { 0x6b66d7e1adc1696fL,0x98ebe5930acd72d0L,0x65f24550cc1b7435L, + 0xce231393b4b9a5ecL }, + { 0x234a22d4db067df9L,0x98dda095caff9b00L,0x1bbc75a06100c9c1L, + 0x1560a9c8939cf695L } }, + /* 5 << 77 */ + { { 0xcf006d3e99e0925fL,0x2dd74a966322375aL,0xc58b446ab56af5baL, + 0x50292683e0b9b4f1L }, + { 0xe2c34cb41aeaffa3L,0x8b17203f9b9587c1L,0x6d559207ead1350cL, + 0x2b66a215fb7f9604L } }, + /* 6 << 77 */ + { { 0x0850325efe51bf74L,0x9c4f579e5e460094L,0x5c87b92a76da2f25L, + 0x889de4e06febef33L }, + { 0x6900ec06646083ceL,0xbe2a0335bfe12773L,0xadd1da35c5344110L, + 0x757568b7b802cd20L } }, + /* 7 << 77 */ + { { 0x7555977900f7e6c8L,0x38e8b94f0facd2f0L,0xfea1f3af03fde375L, + 0x5e11a1d875881dfcL }, + { 0xb3a6b02ec1e2f2efL,0x193d2bbbc605a6c5L,0x325ffeee339a0b2dL, + 0x27b6a7249e0c8846L } }, + /* 8 << 77 */ + { { 0xe4050f1cf1c367caL,0x9bc85a9bc90fbc7dL,0xa373c4a2e1a11032L, + 0xb64232b7ad0393a9L }, + { 0xf5577eb0167dad29L,0x1604f30194b78ab2L,0x0baa94afe829348bL, + 0x77fbd8dd41654342L } }, + /* 9 << 77 */ + { { 0xdab50ea5b964e39aL,0xd4c29e3cd0d3c76eL,0x80dae67c56d11964L, + 0x7307a8bfe5ffcc2fL }, + { 0x65bbc1aa91708c3bL,0xa151e62c28bf0eebL,0x6cb533816fa34db7L, + 0x5139e05ca29403a8L } }, + /* 10 << 77 */ + { { 0x6ff651b494a7cd2eL,0x5671ffd10699336cL,0x6f5fd2cc979a896aL, + 0x11e893a8d8148cefL }, + { 0x988906a165cf7b10L,0x81b67178c50d8485L,0x7c0deb358a35b3deL, + 0x423ac855c1d29799L } }, + /* 11 << 77 */ + { { 0xaf580d87dac50b74L,0x28b2b89f5869734cL,0x99a3b936874e28fbL, + 0xbb2c919025f3f73aL }, + { 0x199f691884a9d5b7L,0x7ebe23257e770374L,0xf442e1070738efe2L, + 0xcf9f3f56cf9082d2L } }, + /* 12 << 77 */ + { { 0x719f69e109618708L,0xcc9e8364c183f9b1L,0xec203a95366a21afL, + 0x6aec5d6d068b141fL }, + { 0xee2df78a994f04e9L,0xb39ccae8271245b0L,0xb875a4a997e43f4fL, + 0x507dfe11db2cea98L } }, + /* 13 << 77 */ + { { 0x4fbf81cb489b03e9L,0xdb86ec5b6ec414faL,0xfad444f9f51b3ae5L, + 0xca7d33d61914e3feL }, + { 0xa9c32f5c0ae6c4d0L,0xa9ca1d1e73969568L,0x98043c311aa7467eL, + 0xe832e75ce21b5ac6L } }, + /* 14 << 77 */ + { { 0x314b7aea5232123dL,0x08307c8c65ae86dbL,0x06e7165caa4668edL, + 0xb170458bb4d3ec39L }, + { 0x4d2e3ec6c19bb986L,0xc5f34846ae0304edL,0x917695a06c9f9722L, + 0x6c7f73174cab1c0aL } }, + /* 15 << 77 */ + { { 0x6295940e9d6d2e8bL,0xd318b8c1549f7c97L,0x2245320497713885L, + 0x468d834ba8a440feL }, + { 0xd81fe5b2bfba796eL,0x152364db6d71f116L,0xbb8c7c59b5b66e53L, + 0x0b12c61b2641a192L } }, + /* 16 << 77 */ + { { 0x31f14802fcf0a7fdL,0x42fd07895488b01eL,0x71d78d6d9952b498L, + 0x8eb572d907ac5201L }, + { 0xe0a2a44c4d194a88L,0xd2b63fd9ba017e66L,0x78efc6c8f888aefcL, + 0xb76f6bda4a881a11L } }, + /* 17 << 77 */ + { { 0x187f314bb46c2397L,0x004cf5665ded2819L,0xa9ea570438764d34L, + 0xbba4521778084709L }, + { 0x064745711171121eL,0xad7b7eb1e7c9b671L,0xdacfbc40730f7507L, + 0x178cd8c6c7ad7bd1L } }, + /* 18 << 77 */ + { { 0xbf0be101b2a67238L,0x3556d367af9c14f2L,0x104b7831a5662075L, + 0x58ca59bb79d9e60aL }, + { 0x4bc45392a569a73bL,0x517a52e85698f6c9L,0x85643da5aeadd755L, + 0x1aed0cd52a581b84L } }, + /* 19 << 77 */ + { { 0xb9b4ff8480af1372L,0x244c3113f1ba5d1fL,0x2a5dacbef5f98d31L, + 0x2c3323e84375bc2aL }, + { 0x17a3ab4a5594b1ddL,0xa1928bfbceb4797eL,0xe83af245e4886a19L, + 0x8979d54672b5a74aL } }, + /* 20 << 77 */ + { { 0xa0f726bc19f9e967L,0xd9d03152e8fbbf4eL,0xcfd6f51db7707d40L, + 0x633084d963f6e6e0L }, + { 0xedcd9cdc55667eafL,0x73b7f92b2e44d56fL,0xfb2e39b64e962b14L, + 0x7d408f6ef671fcbfL } }, + /* 21 << 77 */ + { { 0xcc634ddc164a89bbL,0x74a42bb23ef3bd05L,0x1280dbb2428decbbL, + 0x6103f6bb402c8596L }, + { 0xfa2bf581355a5752L,0x562f96a800946674L,0x4e4ca16d6da0223bL, + 0xfe47819f28d3aa25L } }, + /* 22 << 77 */ + { { 0x9eea3075f8dfcf8aL,0xa284f0aa95669825L,0xb3fca250867d3fd8L, + 0x20757b5f269d691eL }, + { 0xf2c2402093b8a5deL,0xd3f93359ebc06da6L,0x1178293eb2739c33L, + 0xd2a3e770bcd686e5L } }, + /* 23 << 77 */ + { { 0xa76f49f4cd941534L,0x0d37406be3c71c0eL,0x172d93973b97f7e3L, + 0xec17e239bd7fd0deL }, + { 0xe32905516f496ba2L,0x6a69317236ad50e7L,0xc4e539a283e7eff5L, + 0x752737e718e1b4cfL } }, + /* 24 << 77 */ + { { 0xa2f7932c68af43eeL,0x5502468e703d00bdL,0xe5dc978f2fb061f5L, + 0xc9a1904a28c815adL }, + { 0xd3af538d470c56a4L,0x159abc5f193d8cedL,0x2a37245f20108ef3L, + 0xfa17081e223f7178L } }, + /* 25 << 77 */ + { { 0x27b0fb2b10c8c0f5L,0x2102c3ea40650547L,0x594564df8ac3bfa7L, + 0x98102033509dad96L }, + { 0x6989643ff1d18a13L,0x35eebd91d7fc5af0L,0x078d096afaeaafd8L, + 0xb7a89341def3de98L } }, + /* 26 << 77 */ + { { 0x2a206e8decf2a73aL,0x066a63978e551994L,0x3a6a088ab98d53a2L, + 0x0ce7c67c2d1124aaL }, + { 0x48cec671759a113cL,0xe3b373d34f6f67faL,0x5455d479fd36727bL, + 0xe5a428eea13c0d81L } }, + /* 27 << 77 */ + { { 0xb853dbc81c86682bL,0xb78d2727b8d02b2aL,0xaaf69bed8ebc329aL, + 0xdb6b40b3293b2148L }, + { 0xe42ea77db8c4961fL,0xb1a12f7c20e5e0abL,0xa0ec527479e8b05eL, + 0x68027391fab60a80L } }, + /* 28 << 77 */ + { { 0x6bfeea5f16b1bd5eL,0xf957e4204de30ad3L,0xcbaf664e6a353b9eL, + 0x5c87331226d14febL }, + { 0x4e87f98cb65f57cbL,0xdb60a6215e0cdd41L,0x67c16865a6881440L, + 0x1093ef1a46ab52aaL } }, + /* 29 << 77 */ + { { 0xc095afb53f4ece64L,0x6a6bb02e7604551aL,0x55d44b4e0b26b8cdL, + 0xe5f9a999f971268aL }, + { 0xc08ec42511a7de84L,0x83568095fda469ddL,0x737bfba16c6c90a2L, + 0x1cb9c4a0be229831L } }, + /* 30 << 77 */ + { { 0x93bccbbabb2eec64L,0xa0c23b64da03adbeL,0x5f7aa00ae0e86ac4L, + 0x470b941efc1401e6L }, + { 0x5ad8d6799df43574L,0x4ccfb8a90f65d810L,0x1bce80e3aa7fbd81L, + 0x273291ad9508d20aL } }, + /* 31 << 77 */ + { { 0xf5c4b46b42a92806L,0x810684eca86ab44aL,0x4591640bca0bc9f8L, + 0xb5efcdfc5c4b6054L }, + { 0x16fc89076e9edd12L,0xe29d0b50d4d792f9L,0xa45fd01c9b03116dL, + 0x85035235c81765a4L } }, + /* 32 << 77 */ + { { 0x1fe2a9b2b4b4b67cL,0xc1d10df0e8020604L,0x9d64abfcbc8058d8L, + 0x8943b9b2712a0fbbL }, + { 0x90eed9143b3def04L,0x85ab3aa24ce775ffL,0x605fd4ca7bbc9040L, + 0x8b34a564e2c75dfbL } }, + /* 33 << 77 */ + { { 0x41ffc94a10358560L,0x2d8a50729e5c28aaL,0xe915a0fc4cc7eb15L, + 0xe9efab058f6d0f5dL }, + { 0xdbab47a9d19e9b91L,0x8cfed7450276154cL,0x154357ae2cfede0dL, + 0x520630df19f5a4efL } }, + /* 34 << 77 */ + { { 0x25759f7ce382360fL,0xb6db05c988bf5857L,0x2917d61d6c58d46cL, + 0x14f8e491fd20cb7aL }, + { 0xb68a727a11c20340L,0x0386f86faf7ccbb6L,0x5c8bc6ccfee09a20L, + 0x7d76ff4abb7eea35L } }, + /* 35 << 77 */ + { { 0xa7bdebe7db15be7aL,0x67a08054d89f0302L,0x56bf0ea9c1193364L, + 0xc824446762837ebeL }, + { 0x32bd8e8b20d841b8L,0x127a0548dbb8a54fL,0x83dd4ca663b20236L, + 0x87714718203491faL } }, + /* 36 << 77 */ + { { 0x4dabcaaaaa8a5288L,0x91cc0c8aaf23a1c9L,0x34c72c6a3f220e0cL, + 0xbcc20bdf1232144aL }, + { 0x6e2f42daa20ede1bL,0xc441f00c74a00515L,0xbf46a5b6734b8c4bL, + 0x574095037b56c9a4L } }, + /* 37 << 77 */ + { { 0x9f735261e4585d45L,0x9231faed6734e642L,0x1158a176be70ee6cL, + 0x35f1068d7c3501bfL }, + { 0x6beef900a2d26115L,0x649406f2ef0afee3L,0x3f43a60abc2420a1L, + 0x509002a7d5aee4acL } }, + /* 38 << 77 */ + { { 0xb46836a53ff3571bL,0x24f98b78837927c1L,0x6254256a4533c716L, + 0xf27abb0bd07ee196L }, + { 0xd7cf64fc5c6d5bfdL,0x6915c751f0cd7a77L,0xd9f590128798f534L, + 0x772b0da8f81d8b5fL } }, + /* 39 << 77 */ + { { 0x1244260c2e03fa69L,0x36cf0e3a3be1a374L,0x6e7c1633ef06b960L, + 0xa71a4c55671f90f6L }, + { 0x7a94125133c673dbL,0xc0bea51073e8c131L,0x61a8a699d4f6c734L, + 0x25e78c88341ed001L } }, + /* 40 << 77 */ + { { 0x5c18acf88e2f7d90L,0xfdbf33d777be32cdL,0x0a085cd7d2eb5ee9L, + 0x2d702cfbb3201115L }, + { 0xb6e0ebdb85c88ce8L,0x23a3ce3c1e01d617L,0x3041618e567333acL, + 0x9dd0fd8f157edb6bL } }, + /* 41 << 77 */ + { { 0x27f74702b57872b8L,0x2ef26b4f657d5fe1L,0x95426f0a57cf3d40L, + 0x847e2ad165a6067aL }, + { 0xd474d9a009996a74L,0x16a56acd2a26115cL,0x02a615c3d16f4d43L, + 0xcc3fc965aadb85b7L } }, + /* 42 << 77 */ + { { 0x386bda73ce07d1b0L,0xd82910c258ad4178L,0x124f82cfcd2617f4L, + 0xcc2f5e8def691770L }, + { 0x82702550b8c30cccL,0x7b856aea1a8e575aL,0xbb822fefb1ab9459L, + 0x085928bcec24e38eL } }, + /* 43 << 77 */ + { { 0x5d0402ecba8f4b4dL,0xc07cd4ba00b4d58bL,0x5d8dffd529227e7aL, + 0x61d44d0c31bf386fL }, + { 0xe486dc2b135e6f4dL,0x680962ebe79410efL,0xa61bd343f10088b5L, + 0x6aa76076e2e28686L } }, + /* 44 << 77 */ + { { 0x80463d118fb98871L,0xcb26f5c3bbc76affL,0xd4ab8eddfbe03614L, + 0xc8eb579bc0cf2deeL }, + { 0xcc004c15c93bae41L,0x46fbae5d3aeca3b2L,0x671235cf0f1e9ab1L, + 0xadfba9349ec285c1L } }, + /* 45 << 77 */ + { { 0x88ded013f216c980L,0xc8ac4fb8f79e0bc1L,0xa29b89c6fb97a237L, + 0xb697b7809922d8e7L }, + { 0x3142c639ddb945b5L,0x447b06c7e094c3a9L,0xcdcb364272266c90L, + 0x633aad08a9385046L } }, + /* 46 << 77 */ + { { 0xa36c936bb57c6477L,0x871f8b64e94dbcc6L,0x28d0fb62a591a67bL, + 0x9d40e081c1d926f5L }, + { 0x3111eaf6f2d84b5aL,0x228993f9a565b644L,0x0ccbf5922c83188bL, + 0xf87b30ab3df3e197L } }, + /* 47 << 77 */ + { { 0xb8658b317642bca8L,0x1a032d7f52800f17L,0x051dcae579bf9445L, + 0xeba6b8ee54a2e253L }, + { 0x5c8b9cadd4485692L,0x84bda40e8986e9beL,0xd16d16a42f0db448L, + 0x8ec80050a14d4188L } }, + /* 48 << 77 */ + { { 0xb2b2610798fa7aaaL,0x41209ee4f073aa4eL,0xf1570359f2d6b19bL, + 0xcbe6868cfc577cafL }, + { 0x186c4bdc32c04dd3L,0xa6c35faecfeee397L,0xb4a1b312f086c0cfL, + 0xe0a5ccc6d9461fe2L } }, + /* 49 << 77 */ + { { 0xc32278aa1536189fL,0x1126c55fba6df571L,0x0f71a602b194560eL, + 0x8b2d7405324bd6e1L }, + { 0x8481939e3738be71L,0xb5090b1a1a4d97a9L,0x116c65a3f05ba915L, + 0x21863ad3aae448aaL } }, + /* 50 << 77 */ + { { 0xd24e2679a7aae5d3L,0x7076013d0de5c1c4L,0x2d50f8babb05b629L, + 0x73c1abe26e66efbbL }, + { 0xefd4b422f2488af7L,0xe4105d02663ba575L,0x7eb60a8b53a69457L, + 0x62210008c945973bL } }, + /* 51 << 77 */ + { { 0xfb25547877a50ec6L,0xbf0392f70a37a72cL,0xa0a7a19c4be18e7aL, + 0x90d8ea1625b1e0afL }, + { 0x7582a293ef953f57L,0x90a64d05bdc5465aL,0xca79c497e2510717L, + 0x560dbb7c18cb641fL } }, + /* 52 << 77 */ + { { 0x1d8e32864b66abfbL,0xd26f52e559030900L,0x1ee3f6435584941aL, + 0x6d3b3730569f5958L }, + { 0x9ff2a62f4789dba5L,0x91fcb81572b5c9b7L,0xf446cb7d6c8f9a0eL, + 0x48f625c139b7ecb5L } }, + /* 53 << 77 */ + { { 0xbabae8011c6219b8L,0xe7a562d928ac2f23L,0xe1b4873226e20588L, + 0x06ee1cad775af051L }, + { 0xda29ae43faff79f7L,0xc141a412652ee9e0L,0x1e127f6f195f4bd0L, + 0x29c6ab4f072f34f8L } }, + /* 54 << 77 */ + { { 0x7b7c147730448112L,0x82b51af1e4a38656L,0x2bf2028a2f315010L, + 0xc9a4a01f6ea88cd4L }, + { 0xf63e95d8257e5818L,0xdd8efa10b4519b16L,0xed8973e00da910bfL, + 0xed49d0775c0fe4a9L } }, + /* 55 << 77 */ + { { 0xac3aac5eb7caee1eL,0x1033898da7f4da57L,0x42145c0e5c6669b9L, + 0x42daa688c1aa2aa0L }, + { 0x629cc15c1a1d885aL,0x25572ec0f4b76817L,0x8312e4359c8f8f28L, + 0x8107f8cd81965490L } }, + /* 56 << 77 */ + { { 0x516ff3a36fa6110cL,0x74fb1eb1fb93561fL,0x6c0c90478457522bL, + 0xcfd321046bb8bdc6L }, + { 0x2d6884a2cc80ad57L,0x7c27fc3586a9b637L,0x3461baedadf4e8cdL, + 0x1d56251a617242f0L } }, + /* 57 << 77 */ + { { 0x0b80d209c955bef4L,0xdf02cad206adb047L,0xf0d7cb915ec74feeL, + 0xd25033751111ba44L }, + { 0x9671755edf53cb36L,0x54dcb6123368551bL,0x66d69aacc8a025a4L, + 0x6be946c6e77ef445L } }, + /* 58 << 77 */ + { { 0x719946d1a995e094L,0x65e848f6e51e04d8L,0xe62f33006a1e3113L, + 0x1541c7c1501de503L }, + { 0x4daac9faf4acfadeL,0x0e58589744cd0b71L,0x544fd8690a51cd77L, + 0x60fc20ed0031016dL } }, + /* 59 << 77 */ + { { 0x58b404eca4276867L,0x46f6c3cc34f34993L,0x477ca007c636e5bdL, + 0x8018f5e57c458b47L }, + { 0xa1202270e47b668fL,0xcef48ccdee14f203L,0x23f98bae62ff9b4dL, + 0x55acc035c589edddL } }, + /* 60 << 77 */ + { { 0x3fe712af64db4444L,0x19e9d634becdd480L,0xe08bc047a930978aL, + 0x2dbf24eca1280733L }, + { 0x3c0ae38c2cd706b2L,0x5b012a5b359017b9L,0x3943c38c72e0f5aeL, + 0x786167ea57176fa3L } }, + /* 61 << 77 */ + { { 0xe5f9897d594881dcL,0x6b5efad8cfb820c1L,0xb2179093d55018deL, + 0x39ad7d320bac56ceL }, + { 0xb55122e02cfc0e81L,0x117c4661f6d89daaL,0x362d01e1cb64fa09L, + 0x6a309b4e3e9c4dddL } }, + /* 62 << 77 */ + { { 0xfa979fb7abea49b1L,0xb4b1d27d10e2c6c5L,0xbd61c2c423afde7aL, + 0xeb6614f89786d358L }, + { 0x4a5d816b7f6f7459L,0xe431a44f09360e7bL,0x8c27a032c309914cL, + 0xcea5d68acaede3d8L } }, + /* 63 << 77 */ + { { 0x3668f6653a0a3f95L,0x893694167ceba27bL,0x89981fade4728fe9L, + 0x7102c8a08a093562L }, + { 0xbb80310e235d21c8L,0x505e55d1befb7f7bL,0xa0a9081112958a67L, + 0xd67e106a4d851fefL } }, + /* 64 << 77 */ + { { 0xb84011a9431dd80eL,0xeb7c7cca73306cd9L,0x20fadd29d1b3b730L, + 0x83858b5bfe37b3d3L }, + { 0xbf4cd193b6251d5cL,0x1cca1fd31352d952L,0xc66157a490fbc051L, + 0x7990a63889b98636L } }, + /* 0 << 84 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 84 */ + { { 0xe5aa692a87dec0e1L,0x010ded8df7b39d00L,0x7b1b80c854cfa0b5L, + 0x66beb876a0f8ea28L }, + { 0x50d7f5313476cd0eL,0xa63d0e65b08d3949L,0x1a09eea953479fc6L, + 0x82ae9891f499e742L } }, + /* 2 << 84 */ + { { 0xab58b9105ca7d866L,0x582967e23adb3b34L,0x89ae4447cceac0bcL, + 0x919c667c7bf56af5L }, + { 0x9aec17b160f5dcd7L,0xec697b9fddcaadbcL,0x0b98f341463467f5L, + 0xb187f1f7a967132fL } }, + /* 3 << 84 */ + { { 0x90fe7a1d214aeb18L,0x1506af3c741432f7L,0xbb5565f9e591a0c4L, + 0x10d41a77b44f1bc3L }, + { 0xa09d65e4a84bde96L,0x42f060d8f20a6a1cL,0x652a3bfdf27f9ce7L, + 0xb6bdb65c3b3d739fL } }, + /* 4 << 84 */ + { { 0xeb5ddcb6ec7fae9fL,0x995f2714efb66e5aL,0xdee95d8e69445d52L, + 0x1b6c2d4609e27620L }, + { 0x32621c318129d716L,0xb03909f10958c1aaL,0x8c468ef91af4af63L, + 0x162c429ffba5cdf6L } }, + /* 5 << 84 */ + { { 0x2f682343753b9371L,0x29cab45a5f1f9cd7L,0x571623abb245db96L, + 0xc507db093fd79999L }, + { 0x4e2ef652af036c32L,0x86f0cc7805018e5cL,0xc10a73d4ab8be350L, + 0x6519b3977e826327L } }, + /* 6 << 84 */ + { { 0xe8cb5eef9c053df7L,0x8de25b37b300ea6fL,0xdb03fa92c849cffbL, + 0x242e43a7e84169bbL }, + { 0xe4fa51f4dd6f958eL,0x6925a77ff4445a8dL,0xe6e72a50e90d8949L, + 0xc66648e32b1f6390L } }, + /* 7 << 84 */ + { { 0xb2ab1957173e460cL,0x1bbbce7530704590L,0xc0a90dbddb1c7162L, + 0x505e399e15cdd65dL }, + { 0x68434dcb57797ab7L,0x60ad35ba6a2ca8e8L,0x4bfdb1e0de3336c1L, + 0xbbef99ebd8b39015L } }, + /* 8 << 84 */ + { { 0x6c3b96f31711ebecL,0x2da40f1fce98fdc4L,0xb99774d357b4411fL, + 0x87c8bdf415b65bb6L }, + { 0xda3a89e3c2eef12dL,0xde95bb9b3c7471f3L,0x600f225bd812c594L, + 0x54907c5d2b75a56bL } }, + /* 9 << 84 */ + { { 0xa93cc5f08db60e35L,0x743e3cd6fa833319L,0x7dad5c41f81683c9L, + 0x70c1e7d99c34107eL }, + { 0x0edc4a39a6be0907L,0x36d4703586d0b7d3L,0x8c76da03272bfa60L, + 0x0b4a07ea0f08a414L } }, + /* 10 << 84 */ + { { 0x699e4d2945c1dd53L,0xcadc5898231debb5L,0xdf49fcc7a77f00e0L, + 0x93057bbfa73e5a0eL }, + { 0x2f8b7ecd027a4cd1L,0x114734b3c614011aL,0xe7a01db767677c68L, + 0x89d9be5e7e273f4fL } }, + /* 11 << 84 */ + { { 0xd225cb2e089808efL,0xf1f7a27dd59e4107L,0x53afc7618211b9c9L, + 0x0361bc67e6819159L }, + { 0x2a865d0b7f071426L,0x6a3c1810e7072567L,0x3e3bca1e0d6bcabdL, + 0xa1b02bc1408591bcL } }, + /* 12 << 84 */ + { { 0xe0deee5931fba239L,0xf47424d398bd91d1L,0x0f8886f4071a3c1dL, + 0x3f7d41e8a819233bL }, + { 0x708623c2cf6eb998L,0x86bb49af609a287fL,0x942bb24963c90762L, + 0x0ef6eea555a9654bL } }, + /* 13 << 84 */ + { { 0x5f6d2d7236f5defeL,0xfa9922dc56f99176L,0x6c8c5ecef78ce0c7L, + 0x7b44589dbe09b55eL }, + { 0xe11b3bca9ea83770L,0xd7fa2c7f2ab71547L,0x2a3dd6fa2a1ddcc0L, + 0x09acb4305a7b7707L } }, + /* 14 << 84 */ + { { 0x4add4a2e649d4e57L,0xcd53a2b01917526eL,0xc526233020b44ac4L, + 0x4028746abaa2c31dL }, + { 0x5131839064291d4cL,0xbf48f151ee5ad909L,0xcce57f597b185681L, + 0x7c3ac1b04854d442L } }, + /* 15 << 84 */ + { { 0x65587dc3c093c171L,0xae7acb2424f42b65L,0x5a338adb955996cbL, + 0xc8e656756051f91bL }, + { 0x66711fba28b8d0b1L,0x15d74137b6c10a90L,0x70cdd7eb3a232a80L, + 0xc9e2f07f6191ed24L } }, + /* 16 << 84 */ + { { 0xa80d1db6f79588c0L,0xfa52fc69b55768ccL,0x0b4df1ae7f54438aL, + 0x0cadd1a7f9b46a4fL }, + { 0xb40ea6b31803dd6fL,0x488e4fa555eaae35L,0x9f047d55382e4e16L, + 0xc9b5b7e02f6e0c98L } }, + /* 17 << 84 */ + { { 0x6b1bd2d395762649L,0xa9604ee7c7aea3f6L,0x3646ff276dc6f896L, + 0x9bf0e7f52860bad1L }, + { 0x2d92c8217cb44b92L,0xa2f5ce63aea9c182L,0xd0a2afb19154a5fdL, + 0x482e474c95801da6L } }, + /* 18 << 84 */ + { { 0xc19972d0b611c24bL,0x1d468e6560a8f351L,0xeb7580697bcf6421L, + 0xec9dd0ee88fbc491L }, + { 0x5b59d2bf956c2e32L,0x73dc6864dcddf94eL,0xfd5e2321bcee7665L, + 0xa7b4f8ef5e9a06c4L } }, + /* 19 << 84 */ + { { 0xfba918dd7280f855L,0xbbaac2608baec688L,0xa3b3f00f33400f42L, + 0x3d2dba2966f2e6e4L }, + { 0xb6f71a9498509375L,0x8f33031fcea423ccL,0x009b8dd04807e6fbL, + 0x5163cfe55cdb954cL } }, + /* 20 << 84 */ + { { 0x03cc8f17cf41c6e8L,0xf1f03c2a037b925cL,0xc39c19cc66d2427cL, + 0x823d24ba7b6c18e4L }, + { 0x32ef9013901f0b4fL,0x684360f1f8941c2eL,0x0ebaff522c28092eL, + 0x7891e4e3256c932fL } }, + /* 21 << 84 */ + { { 0x51264319ac445e3dL,0x553432e78ea74381L,0xe6eeaa6967e9c50aL, + 0x27ced28462e628c7L }, + { 0x3f96d3757a4afa57L,0xde0a14c3e484c150L,0x364a24eb38bd9923L, + 0x1df18da0e5177422L } }, + /* 22 << 84 */ + { { 0x174e8f82d8d38a9bL,0x2e97c600e7de1391L,0xc5709850a1c175ddL, + 0x969041a032ae5035L }, + { 0xcbfd533b76a2086bL,0xd6bba71bd7c2e8feL,0xb2d58ee6099dfb67L, + 0x3a8b342d064a85d9L } }, + /* 23 << 84 */ + { { 0x3bc07649522f9be3L,0x690c075bdf1f49a8L,0x80e1aee83854ec42L, + 0x2a7dbf4417689dc7L }, + { 0xc004fc0e3faf4078L,0xb2f02e9edf11862cL,0xf10a5e0fa0a1b7b3L, + 0x30aca6238936ec80L } }, + /* 24 << 84 */ + { { 0xf83cbf0502f40d9aL,0x4681c4682c318a4dL,0x985756180e9c2674L, + 0xbe79d0461847092eL }, + { 0xaf1e480a78bd01e0L,0x6dd359e472a51db9L,0x62ce3821e3afbab6L, + 0xc5cee5b617733199L } }, + /* 25 << 84 */ + { { 0xe08b30d46ffd9fbbL,0x6e5bc69936c610b7L,0xf343cff29ce262cfL, + 0xca2e4e3568b914c1L }, + { 0x011d64c016de36c5L,0xe0b10fdd42e2b829L,0x789429816685aaf8L, + 0xe7511708230ede97L } }, + /* 26 << 84 */ + { { 0x671ed8fc3b922bf8L,0xe4d8c0a04c29b133L,0x87eb12393b6e99c4L, + 0xaff3974c8793bebaL }, + { 0x037494052c18df9bL,0xc5c3a29391007139L,0x6a77234fe37a0b95L, + 0x02c29a21b661c96bL } }, + /* 27 << 84 */ + { { 0xc3aaf1d6141ecf61L,0x9195509e3bb22f53L,0x2959740422d51357L, + 0x1b083822537bed60L }, + { 0xcd7d6e35e07289f0L,0x1f94c48c6dd86effL,0xc8bb1f82eb0f9cfaL, + 0x9ee0b7e61b2eb97dL } }, + /* 28 << 84 */ + { { 0x5a52fe2e34d74e31L,0xa352c3103bf79ab6L,0x97ff6c5aabfeeb8fL, + 0xbfbe8feff5c97305L }, + { 0xd6081ce6a7904608L,0x1f812f3ac4fca249L,0x9b24bc9ab9e5e200L, + 0x91022c6738012ee8L } }, + /* 29 << 84 */ + { { 0xe83d9c5d30a713a1L,0x4876e3f084ef0f93L,0xc9777029c1fbf928L, + 0xef7a6bb3bce7d2a4L }, + { 0xb8067228dfa2a659L,0xd5cd3398d877a48fL,0xbea4fd8f025d0f3fL, + 0xd67d2e352eae7c2bL } }, + /* 30 << 84 */ + { { 0x184de7d7cc5f4394L,0xb5551b5c4536e142L,0x2e89b212d34aa60aL, + 0x14a96feaf50051d5L }, + { 0x4e21ef740d12bb0bL,0xc522f02060b9677eL,0x8b12e4672df7731dL, + 0x39f803827b326d31L } }, + /* 31 << 84 */ + { { 0xdfb8630c39024a94L,0xaacb96a897319452L,0xd68a3961eda3867cL, + 0x0c58e2b077c4ffcaL }, + { 0x3d545d634da919faL,0xef79b69af15e2289L,0x54bc3d3d808bab10L, + 0xc8ab300745f82c37L } }, + /* 32 << 84 */ + { { 0xc12738b67c4a658aL,0xb3c4763940e72182L,0x3b77be468798e44fL, + 0xdc047df217a7f85fL }, + { 0x2439d4c55e59d92dL,0xcedca475e8e64d8dL,0xa724cd0d87ca9b16L, + 0x35e4fd59a5540dfeL } }, + /* 33 << 84 */ + { { 0xf8c1ff18e4bcf6b1L,0x856d6285295018faL,0x433f665c3263c949L, + 0xa6a76dd6a1f21409L }, + { 0x17d32334cc7b4f79L,0xa1d0312206720e4aL,0xadb6661d81d9bed5L, + 0xf0d6fb0211db15d1L } }, + /* 34 << 84 */ + { { 0x7fd11ad51fb747d2L,0xab50f9593033762bL,0x2a7e711bfbefaf5aL, + 0xc73932783fef2bbfL }, + { 0xe29fa2440df6f9beL,0x9092757b71efd215L,0xee60e3114f3d6fd9L, + 0x338542d40acfb78bL } }, + /* 35 << 84 */ + { { 0x44a23f0838961a0fL,0x1426eade986987caL,0x36e6ee2e4a863cc6L, + 0x48059420628b8b79L }, + { 0x30303ad87396e1deL,0x5c8bdc4838c5aad1L,0x3e40e11f5c8f5066L, + 0xabd6e7688d246bbdL } }, + /* 36 << 84 */ + { { 0x68aa40bb23330a01L,0xd23f5ee4c34eafa0L,0x3bbee3155de02c21L, + 0x18dd4397d1d8dd06L }, + { 0x3ba1939a122d7b44L,0xe6d3b40aa33870d6L,0x8e620f701c4fe3f8L, + 0xf6bba1a5d3a50cbfL } }, + /* 37 << 84 */ + { { 0x4a78bde5cfc0aee0L,0x847edc46c08c50bdL,0xbaa2439cad63c9b2L, + 0xceb4a72810fc2acbL }, + { 0xa419e40e26da033dL,0x6cc3889d03e02683L,0x1cd28559fdccf725L, + 0x0fd7e0f18d13d208L } }, + /* 38 << 84 */ + { { 0x01b9733b1f0df9d4L,0x8cc2c5f3a2b5e4f3L,0x43053bfa3a304fd4L, + 0x8e87665c0a9f1aa7L }, + { 0x087f29ecd73dc965L,0x15ace4553e9023dbL,0x2370e3092bce28b4L, + 0xf9723442b6b1e84aL } }, + /* 39 << 84 */ + { { 0xbeee662eb72d9f26L,0xb19396def0e47109L,0x85b1fa73e13289d0L, + 0x436cf77e54e58e32L }, + { 0x0ec833b3e990ef77L,0x7373e3ed1b11fc25L,0xbe0eda870fc332ceL, + 0xced049708d7ea856L } }, + /* 40 << 84 */ + { { 0xf85ff7857e977ca0L,0xb66ee8dadfdd5d2bL,0xf5e37950905af461L, + 0x587b9090966d487cL }, + { 0x6a198a1b32ba0127L,0xa7720e07141615acL,0xa23f3499996ef2f2L, + 0xef5f64b4470bcb3dL } }, + /* 41 << 84 */ + { { 0xa526a96292b8c559L,0x0c14aac069740a0fL,0x0d41a9e3a6bdc0a5L, + 0x97d521069c48aef4L }, + { 0xcf16bd303e7c253bL,0xcc834b1a47fdedc1L,0x7362c6e5373aab2eL, + 0x264ed85ec5f590ffL } }, + /* 42 << 84 */ + { { 0x7a46d9c066d41870L,0xa50c20b14787ba09L,0x185e7e51e3d44635L, + 0xb3b3e08031e2d8dcL }, + { 0xbed1e558a179e9d9L,0x2daa3f7974a76781L,0x4372baf23a40864fL, + 0x46900c544fe75cb5L } }, + /* 43 << 84 */ + { { 0xb95f171ef76765d0L,0x4ad726d295c87502L,0x2ec769da4d7c99bdL, + 0x5e2ddd19c36cdfa8L }, + { 0xc22117fca93e6deaL,0xe8a2583b93771123L,0xbe2f6089fa08a3a2L, + 0x4809d5ed8f0e1112L } }, + /* 44 << 84 */ + { { 0x3b414aa3da7a095eL,0x9049acf126f5aaddL,0x78d46a4d6be8b84aL, + 0xd66b1963b732b9b3L }, + { 0x5c2ac2a0de6e9555L,0xcf52d098b5bd8770L,0x15a15fa60fd28921L, + 0x56ccb81e8b27536dL } }, + /* 45 << 84 */ + { { 0x0f0d8ab89f4ccbb8L,0xed5f44d2db221729L,0x4314198800bed10cL, + 0xc94348a41d735b8bL }, + { 0x79f3e9c429ef8479L,0x4c13a4e3614c693fL,0x32c9af568e143a14L, + 0xbc517799e29ac5c4L } }, + /* 46 << 84 */ + { { 0x05e179922774856fL,0x6e52fb056c1bf55fL,0xaeda4225e4f19e16L, + 0x70f4728aaf5ccb26L }, + { 0x5d2118d1b2947f22L,0xc827ea16281d6fb9L,0x8412328d8cf0eabdL, + 0x45ee9fb203ef9dcfL } }, + /* 47 << 84 */ + { { 0x8e700421bb937d63L,0xdf8ff2d5cc4b37a6L,0xa4c0d5b25ced7b68L, + 0x6537c1efc7308f59L }, + { 0x25ce6a263b37f8e8L,0x170e9a9bdeebc6ceL,0xdd0379528728d72cL, + 0x445b0e55850154bcL } }, + /* 48 << 84 */ + { { 0x4b7d0e0683a7337bL,0x1e3416d4ffecf249L,0x24840eff66a2b71fL, + 0xd0d9a50ab37cc26dL }, + { 0xe21981506fe28ef7L,0x3cc5ef1623324c7fL,0x220f3455769b5263L, + 0xe2ade2f1a10bf475L } }, + /* 49 << 84 */ + { { 0x28cd20fa458d3671L,0x1549722c2dc4847bL,0x6dd01e55591941e3L, + 0x0e6fbcea27128ccbL }, + { 0xae1a1e6b3bef0262L,0xfa8c472c8f54e103L,0x7539c0a872c052ecL, + 0xd7b273695a3490e9L } }, + /* 50 << 84 */ + { { 0x143fe1f171684349L,0x36b4722e32e19b97L,0xdc05922790980affL, + 0x175c9c889e13d674L }, + { 0xa7de5b226e6bfdb1L,0x5ea5b7b2bedb4b46L,0xd5570191d34a6e44L, + 0xfcf60d2ea24ff7e6L } }, + /* 51 << 84 */ + { { 0x614a392d677819e1L,0x7be74c7eaa5a29e8L,0xab50fece63c85f3fL, + 0xaca2e2a946cab337L }, + { 0x7f700388122a6fe3L,0xdb69f703882a04a8L,0x9a77935dcf7aed57L, + 0xdf16207c8d91c86fL } }, + /* 52 << 84 */ + { { 0x2fca49ab63ed9998L,0xa3125c44a77ddf96L,0x05dd8a8624344072L, + 0xa023dda2fec3fb56L }, + { 0x421b41fc0c743032L,0x4f2120c15e438639L,0xfb7cae51c83c1b07L, + 0xb2370caacac2171aL } }, + /* 53 << 84 */ + { { 0x2eb2d9626cc820fbL,0x59feee5cb85a44bfL,0x94620fca5b6598f0L, + 0x6b922cae7e314051L }, + { 0xff8745ad106bed4eL,0x546e71f5dfa1e9abL,0x935c1e481ec29487L, + 0x9509216c4d936530L } }, + /* 54 << 84 */ + { { 0xc7ca306785c9a2dbL,0xd6ae51526be8606fL,0x09dbcae6e14c651dL, + 0xc9536e239bc32f96L }, + { 0xa90535a934521b03L,0xf39c526c878756ffL,0x383172ec8aedf03cL, + 0x20a8075eefe0c034L } }, + /* 55 << 84 */ + { { 0xf22f9c6264026422L,0x8dd1078024b9d076L,0x944c742a3bef2950L, + 0x55b9502e88a2b00bL }, + { 0xa59e14b486a09817L,0xa39dd3ac47bb4071L,0x55137f663be0592fL, + 0x07fcafd4c9e63f5bL } }, + /* 56 << 84 */ + { { 0x963652ee346eb226L,0x7dfab085ec2facb7L,0x273bf2b8691add26L, + 0x30d74540f2b46c44L }, + { 0x05e8e73ef2c2d065L,0xff9b8a00d42eeac9L,0x2fcbd20597209d22L, + 0xeb740ffade14ea2cL } }, + /* 57 << 84 */ + { { 0xc71ff913a8aef518L,0x7bfc74bbfff4cfa2L,0x1716680cb6b36048L, + 0x121b2cce9ef79af1L }, + { 0xbff3c836a01eb3d3L,0x50eb1c6a5f79077bL,0xa48c32d6a004bbcfL, + 0x47a593167d64f61dL } }, + /* 58 << 84 */ + { { 0x6068147f93102016L,0x12c5f65494d12576L,0xefb071a7c9bc6b91L, + 0x7c2da0c56e23ea95L }, + { 0xf4fd45b6d4a1dd5dL,0x3e7ad9b69122b13cL,0x342ca118e6f57a48L, + 0x1c2e94a706f8288fL } }, + /* 59 << 84 */ + { { 0x99e68f075a97d231L,0x7c80de974d838758L,0xbce0f5d005872727L, + 0xbe5d95c219c4d016L }, + { 0x921d5cb19c2492eeL,0x42192dc1404d6fb3L,0x4c84dcd132f988d3L, + 0xde26d61fa17b8e85L } }, + /* 60 << 84 */ + { { 0xc466dcb6137c7408L,0x9a38d7b636a266daL,0x7ef5cb0683bebf1bL, + 0xe5cdcbbf0fd014e3L }, + { 0x30aa376df65965a0L,0x60fe88c2ebb3e95eL,0x33fd0b6166ee6f20L, + 0x8827dcdb3f41f0a0L } }, + /* 61 << 84 */ + { { 0xbf8a9d240c56c690L,0x40265dadddb7641dL,0x522b05bf3a6b662bL, + 0x466d1dfeb1478c9bL }, + { 0xaa6169621484469bL,0x0db6054902df8f9fL,0xc37bca023cb8bf51L, + 0x5effe34621371ce8L } }, + /* 62 << 84 */ + { { 0xe8f65264ff112c32L,0x8a9c736d7b971fb2L,0xa4f194707b75080dL, + 0xfc3f2c5a8839c59bL }, + { 0x1d6c777e5aeb49c2L,0xf3db034dda1addfeL,0xd76fee5a5535affcL, + 0x0853ac70b92251fdL } }, + /* 63 << 84 */ + { { 0x37e3d5948b2a29d5L,0x28f1f4574de00ddbL,0x8083c1b5f42c328bL, + 0xd8ef1d8fe493c73bL }, + { 0x96fb626041dc61bdL,0xf74e8a9d27ee2f8aL,0x7c605a802c946a5dL, + 0xeed48d653839ccfdL } }, + /* 64 << 84 */ + { { 0x9894344f3a29467aL,0xde81e949c51eba6dL,0xdaea066ba5e5c2f2L, + 0x3fc8a61408c8c7b3L }, + { 0x7adff88f06d0de9fL,0xbbc11cf53b75ce0aL,0x9fbb7accfbbc87d5L, + 0xa1458e267badfde2L } }, + /* 0 << 91 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 91 */ + { { 0x1cb43668e039c256L,0x5f26fb8b7c17fd5dL,0xeee426af79aa062bL, + 0x072002d0d78fbf04L }, + { 0x4c9ca237e84fb7e3L,0xb401d8a10c82133dL,0xaaa525926d7e4181L, + 0xe943083373dbb152L } }, + /* 2 << 91 */ + { { 0xf92dda31be24319aL,0x03f7d28be095a8e7L,0xa52fe84098782185L, + 0x276ddafe29c24dbcL }, + { 0x80cd54961d7a64ebL,0xe43608897f1dbe42L,0x2f81a8778438d2d5L, + 0x7e4d52a885169036L } }, + /* 3 << 91 */ + { { 0x19e3d5b11d59715dL,0xc7eaa762d788983eL,0xe5a730b0abf1f248L, + 0xfbab8084fae3fd83L }, + { 0x65e50d2153765b2fL,0xbdd4e083fa127f3dL,0x9cf3c074397b1b10L, + 0x59f8090cb1b59fd3L } }, + /* 4 << 91 */ + { { 0x7b15fd9d615faa8fL,0x8fa1eb40968554edL,0x7bb4447e7aa44882L, + 0x2bb2d0d1029fff32L }, + { 0x075e2a646caa6d2fL,0x8eb879de22e7351bL,0xbcd5624e9a506c62L, + 0x218eaef0a87e24dcL } }, + /* 5 << 91 */ + { { 0x37e5684744ddfa35L,0x9ccfc5c5dab3f747L,0x9ac1df3f1ee96cf4L, + 0x0c0571a13b480b8fL }, + { 0x2fbeb3d54b3a7b3cL,0x35c036695dcdbb99L,0x52a0f5dcb2415b3aL, + 0xd57759b44413ed9aL } }, + /* 6 << 91 */ + { { 0x1fe647d83d30a2c5L,0x0857f77ef78a81dcL,0x11d5a334131a4a9bL, + 0xc0a94af929d393f5L }, + { 0xbc3a5c0bdaa6ec1aL,0xba9fe49388d2d7edL,0xbb4335b4bb614797L, + 0x991c4d6872f83533L } }, + /* 7 << 91 */ + { { 0x53258c28d2f01cb3L,0x93d6eaa3d75db0b1L,0x419a2b0de87d0db4L, + 0xa1e48f03d8fe8493L }, + { 0xf747faf6c508b23aL,0xf137571a35d53549L,0x9f5e58e2fcf9b838L, + 0xc7186ceea7fd3cf5L } }, + /* 8 << 91 */ + { { 0x77b868cee978a1d3L,0xe3a68b337ab92d04L,0x5102979487a5b862L, + 0x5f0606c33a61d41dL }, + { 0x2814be276f9326f1L,0x2f521c14c6fe3c2eL,0x17464d7dacdf7351L, + 0x10f5f9d3777f7e44L } }, + /* 9 << 91 */ + { { 0xce8e616b269fb37dL,0xaaf738047de62de5L,0xaba111754fdd4153L, + 0x515759ba3770b49bL }, + { 0x8b09ebf8aa423a61L,0x592245a1cd41fb92L,0x1cba8ec19b4c8936L, + 0xa87e91e3af36710eL } }, + /* 10 << 91 */ + { { 0x1fd84ce43d34a2e3L,0xee3759ceb43b5d61L,0x895bc78c619186c7L, + 0xf19c3809cbb9725aL }, + { 0xc0be21aade744b1fL,0xa7d222b060f8056bL,0x74be6157b23efe11L, + 0x6fab2b4f0cd68253L } }, + /* 11 << 91 */ + { { 0xad33ea5f4bf1d725L,0x9c1d8ee24f6c950fL,0x544ee78aa377af06L, + 0x54f489bb94a113e1L }, + { 0x8f11d634992fb7e8L,0x0169a7aaa2a44347L,0x1d49d4af95020e00L, + 0x95945722e08e120bL } }, + /* 12 << 91 */ + { { 0xb6e33878a4d32282L,0xe36e029d48020ae7L,0xe05847fb37a9b750L, + 0xf876812cb29e3819L }, + { 0x84ad138ed23a17f0L,0x6d7b4480f0b3950eL,0xdfa8aef42fd67ae0L, + 0x8d3eea2452333af6L } }, + /* 13 << 91 */ + { { 0x0d052075b15d5accL,0xc6d9c79fbd815bc4L,0x8dcafd88dfa36cf2L, + 0x908ccbe238aa9070L }, + { 0x638722c4ba35afceL,0x5a3da8b0fd6abf0bL,0x2dce252cc9c335c1L, + 0x84e7f0de65aa799bL } }, + /* 14 << 91 */ + { { 0x2101a522b99a72cbL,0x06de6e6787618016L,0x5ff8c7cde6f3653eL, + 0x0a821ab5c7a6754aL }, + { 0x7e3fa52b7cb0b5a2L,0xa7fb121cc9048790L,0x1a72502006ce053aL, + 0xb490a31f04e929b0L } }, + /* 15 << 91 */ + { { 0xe17be47d62dd61adL,0x781a961c6be01371L,0x1063bfd3dae3cbbaL, + 0x356474067f73c9baL }, + { 0xf50e957b2736a129L,0xa6313702ed13f256L,0x9436ee653a19fcc5L, + 0xcf2bdb29e7a4c8b6L } }, + /* 16 << 91 */ + { { 0xb06b1244c5f95cd8L,0xda8c8af0f4ab95f4L,0x1bae59c2b9e5836dL, + 0x07d51e7e3acffffcL }, + { 0x01e15e6ac2ccbcdaL,0x3bc1923f8528c3e0L,0x43324577a49fead4L, + 0x61a1b8842aa7a711L } }, + /* 17 << 91 */ + { { 0xf9a86e08700230efL,0x0af585a1bd19adf8L,0x7645f361f55ad8f2L, + 0x6e67622346c3614cL }, + { 0x23cb257c4e774d3fL,0x82a38513ac102d1bL,0x9bcddd887b126aa5L, + 0xe716998beefd3ee4L } }, + /* 18 << 91 */ + { { 0x4239d571fb167583L,0xdd011c78d16c8f8aL,0x271c289569a27519L, + 0x9ce0a3b7d2d64b6aL }, + { 0x8c977289d5ec6738L,0xa3b49f9a8840ef6bL,0x808c14c99a453419L, + 0x5c00295b0cf0a2d5L } }, + /* 19 << 91 */ + { { 0x524414fb1d4bcc76L,0xb07691d2459a88f1L,0x77f43263f70d110fL, + 0x64ada5e0b7abf9f3L }, + { 0xafd0f94e5b544cf5L,0xb4a13a15fd2713feL,0xb99b7d6e250c74f4L, + 0x097f2f7320324e45L } }, + /* 20 << 91 */ + { { 0x994b37d8affa8208L,0xc3c31b0bdc29aafcL,0x3da746517a3a607fL, + 0xd8e1b8c1fe6955d6L }, + { 0x716e1815c8418682L,0x541d487f7dc91d97L,0x48a04669c6996982L, + 0xf39cab1583a6502eL } }, + /* 21 << 91 */ + { { 0x025801a0e68db055L,0xf3569758ba3338d5L,0xb0c8c0aaee2afa84L, + 0x4f6985d3fb6562d1L }, + { 0x351f1f15132ed17aL,0x510ed0b4c04365feL,0xa3f98138e5b1f066L, + 0xbc9d95d632df03dcL } }, + /* 22 << 91 */ + { { 0xa83ccf6e19abd09eL,0x0b4097c14ff17edbL,0x58a5c478d64a06ceL, + 0x2ddcc3fd544a58fdL }, + { 0xd449503d9e8153b8L,0x3324fd027774179bL,0xaf5d47c8dbd9120cL, + 0xeb86016234fa94dbL } }, + /* 23 << 91 */ + { { 0x5817bdd1972f07f4L,0xe5579e2ed27bbcebL,0x86847a1f5f11e5a6L, + 0xb39ed2557c3cf048L }, + { 0xe1076417a2f62e55L,0x6b9ab38f1bcf82a2L,0x4bb7c3197aeb29f9L, + 0xf6d17da317227a46L } }, + /* 24 << 91 */ + { { 0xab53ddbd0f968c00L,0xa03da7ec000c880bL,0x7b2396246a9ad24dL, + 0x612c040101ec60d0L }, + { 0x70d10493109f5df1L,0xfbda403080af7550L,0x30b93f95c6b9a9b3L, + 0x0c74ec71007d9418L } }, + /* 25 << 91 */ + { { 0x941755646edb951fL,0x5f4a9d787f22c282L,0xb7870895b38d1196L, + 0xbc593df3a228ce7cL }, + { 0xc78c5bd46af3641aL,0x7802200b3d9b3dccL,0x0dc73f328be33304L, + 0x847ed87d61ffb79aL } }, + /* 26 << 91 */ + { { 0xf85c974e6d671192L,0x1e14100ade16f60fL,0x45cb0d5a95c38797L, + 0x18923bba9b022da4L }, + { 0xef2be899bbe7e86eL,0x4a1510ee216067bfL,0xd98c815484d5ce3eL, + 0x1af777f0f92a2b90L } }, + /* 27 << 91 */ + { { 0x9fbcb4004ef65724L,0x3e04a4c93c0ca6feL,0xfb3e2cb555002994L, + 0x1f3a93c55363ecabL }, + { 0x1fe00efe3923555bL,0x744bedd91e1751eaL,0x3fb2db596ab69357L, + 0x8dbd7365f5e6618bL } }, + /* 28 << 91 */ + { { 0x99d53099df1ea40eL,0xb3f24a0b57d61e64L,0xd088a198596eb812L, + 0x22c8361b5762940bL }, + { 0x66f01f97f9c0d95cL,0x884611728e43cdaeL,0x11599a7fb72b15c3L, + 0x135a7536420d95ccL } }, + /* 29 << 91 */ + { { 0x2dcdf0f75f7ae2f6L,0x15fc6e1dd7fa6da2L,0x81ca829ad1d441b6L, + 0x84c10cf804a106b6L }, + { 0xa9b26c95a73fbbd0L,0x7f24e0cb4d8f6ee8L,0x48b459371e25a043L, + 0xf8a74fca036f3dfeL } }, + /* 30 << 91 */ + { { 0x1ed46585c9f84296L,0x7fbaa8fb3bc278b0L,0xa8e96cd46c4fcbd0L, + 0x940a120273b60a5fL }, + { 0x34aae12055a4aec8L,0x550e9a74dbd742f0L,0x794456d7228c68abL, + 0x492f8868a4e25ec6L } }, + /* 31 << 91 */ + { { 0x682915adb2d8f398L,0xf13b51cc5b84c953L,0xcda90ab85bb917d6L, + 0x4b6155604ea3dee1L }, + { 0x578b4e850a52c1c8L,0xeab1a69520b75fc4L,0x60c14f3caa0bb3c6L, + 0x220f448ab8216094L } }, + /* 32 << 91 */ + { { 0x4fe7ee31b0e63d34L,0xf4600572a9e54fabL,0xc0493334d5e7b5a4L, + 0x8589fb9206d54831L }, + { 0xaa70f5cc6583553aL,0x0879094ae25649e5L,0xcc90450710044652L, + 0xebb0696d02541c4fL } }, + /* 33 << 91 */ + { { 0x5a171fdeb9718710L,0x38f1bed8f374a9f5L,0xc8c582e1ba39bdc1L, + 0xfc457b0a908cc0ceL }, + { 0x9a187fd4883841e2L,0x8ec25b3938725381L,0x2553ed0596f84395L, + 0x095c76616f6c6897L } }, + /* 34 << 91 */ + { { 0x917ac85c4bdc5610L,0xb2885fe4179eb301L,0x5fc655478b78bdccL, + 0x4a9fc893e59e4699L }, + { 0xbb7ff0cd3ce299afL,0x195be9b3adf38b20L,0x6a929c87d38ddb8fL, + 0x55fcc99cb21a51b9L } }, + /* 35 << 91 */ + { { 0x2b695b4c721a4593L,0xed1e9a15768eaac2L,0xfb63d71c7489f914L, + 0xf98ba31c78118910L }, + { 0x802913739b128eb4L,0x7801214ed448af4aL,0xdbd2e22b55418dd3L, + 0xeffb3c0dd3998242L } }, + /* 36 << 91 */ + { { 0xdfa6077cc7bf3827L,0xf2165bcb47f8238fL,0xfe37cf688564d554L, + 0xe5f825c40a81fb98L }, + { 0x43cc4f67ffed4d6fL,0xbc609578b50a34b0L,0x8aa8fcf95041faf1L, + 0x5659f053651773b6L } }, + /* 37 << 91 */ + { { 0xe87582c36044d63bL,0xa60894090cdb0ca0L,0x8c993e0fbfb2bcf6L, + 0xfc64a71945985cfcL }, + { 0x15c4da8083dbedbaL,0x804ae1122be67df7L,0xda4c9658a23defdeL, + 0x12002ddd5156e0d3L } }, + /* 38 << 91 */ + { { 0xe68eae895dd21b96L,0x8b99f28bcf44624dL,0x0ae008081ec8897aL, + 0xdd0a93036712f76eL }, + { 0x962375224e233de4L,0x192445b12b36a8a5L,0xabf9ff74023993d9L, + 0x21f37bf42aad4a8fL } }, + /* 39 << 91 */ + { { 0x340a4349f8bd2bbdL,0x1d902cd94868195dL,0x3d27bbf1e5fdb6f1L, + 0x7a5ab088124f9f1cL }, + { 0xc466ab06f7a09e03L,0x2f8a197731f2c123L,0xda355dc7041b6657L, + 0xcb840d128ece2a7cL } }, + /* 40 << 91 */ + { { 0xb600ad9f7db32675L,0x78fea13307a06f1bL,0x5d032269b31f6094L, + 0x07753ef583ec37aaL }, + { 0x03485aed9c0bea78L,0x41bb3989bc3f4524L,0x09403761697f726dL, + 0x6109beb3df394820L } }, + /* 41 << 91 */ + { { 0x804111ea3b6d1145L,0xb6271ea9a8582654L,0x619615e624e66562L, + 0xa2554945d7b6ad9cL }, + { 0xd9c4985e99bfe35fL,0x9770ccc07b51cdf6L,0x7c32701392881832L, + 0x8777d45f286b26d1L } }, + /* 42 << 91 */ + { { 0x9bbeda22d847999dL,0x03aa33b6c3525d32L,0x4b7b96d428a959a1L, + 0xbb3786e531e5d234L }, + { 0xaeb5d3ce6961f247L,0x20aa85af02f93d3fL,0x9cd1ad3dd7a7ae4fL, + 0xbf6688f0781adaa8L } }, + /* 43 << 91 */ + { { 0xb1b40e867469ceadL,0x1904c524309fca48L,0x9b7312af4b54bbc7L, + 0xbe24bf8f593affa2L }, + { 0xbe5e0790bd98764bL,0xa0f45f17a26e299eL,0x4af0d2c26b8fe4c7L, + 0xef170db18ae8a3e6L } }, + /* 44 << 91 */ + { { 0x0e8d61a029e0ccc1L,0xcd53e87e60ad36caL,0x328c6623c8173822L, + 0x7ee1767da496be55L }, + { 0x89f13259648945afL,0x9e45a5fd25c8009cL,0xaf2febd91f61ab8cL, + 0x43f6bc868a275385L } }, + /* 45 << 91 */ + { { 0x87792348f2142e79L,0x17d89259c6e6238aL,0x7536d2f64a839d9bL, + 0x1f428fce76a1fbdcL }, + { 0x1c1096010db06dfeL,0xbfc16bc150a3a3ccL,0xf9cbd9ec9b30f41bL, + 0x5b5da0d600138cceL } }, + /* 46 << 91 */ + { { 0xec1d0a4856ef96a7L,0xb47eb848982bf842L,0x66deae32ec3f700dL, + 0x4e43c42caa1181e0L }, + { 0xa1d72a31d1a4aa2aL,0x440d4668c004f3ceL,0x0d6a2d3b45fe8a7aL, + 0x820e52e2fb128365L } }, + /* 47 << 91 */ + { { 0x29ac5fcf25e51b09L,0x180cd2bf2023d159L,0xa9892171a1ebf90eL, + 0xf97c4c877c132181L }, + { 0x9f1dc724c03dbb7eL,0xae043765018cbbe4L,0xfb0b2a360767d153L, + 0xa8e2f4d6249cbaebL } }, + /* 48 << 91 */ + { { 0x172a5247d95ea168L,0x1758fada2970764aL,0xac803a511d978169L, + 0x299cfe2ede77e01bL }, + { 0x652a1e17b0a98927L,0x2e26e1d120014495L,0x7ae0af9f7175b56aL, + 0xc2e22a80d64b9f95L } }, + /* 49 << 91 */ + { { 0x4d0ff9fbd90a060aL,0x496a27dbbaf38085L,0x32305401da776bcfL, + 0xb8cdcef6725f209eL }, + { 0x61ba0f37436a0bbaL,0x263fa10876860049L,0x92beb98eda3542cfL, + 0xa2d4d14ad5849538L } }, + /* 50 << 91 */ + { { 0x989b9d6812e9a1bcL,0x61d9075c5f6e3268L,0x352c6aa999ace638L, + 0xde4e4a55920f43ffL }, + { 0xe5e4144ad673c017L,0x667417ae6f6e05eaL,0x613416aedcd1bd56L, + 0x5eb3620186693711L } }, + /* 51 << 91 */ + { { 0x2d7bc5043a1aa914L,0x175a129976dc5975L,0xe900e0f23fc8125cL, + 0x569ef68c11198875L }, + { 0x9012db6363a113b4L,0xe3bd3f5698835766L,0xa5c94a5276412deaL, + 0xad9e2a09aa735e5cL } }, + /* 52 << 91 */ + { { 0x405a984c508b65e9L,0xbde4a1d16df1a0d1L,0x1a9433a1dfba80daL, + 0xe9192ff99440ad2eL }, + { 0x9f6496965099fe92L,0x25ddb65c0b27a54aL,0x178279ddc590da61L, + 0x5479a999fbde681aL } }, + /* 53 << 91 */ + { { 0xd0e84e05013fe162L,0xbe11dc92632d471bL,0xdf0b0c45fc0e089fL, + 0x04fb15b04c144025L }, + { 0xa61d5fc213c99927L,0xa033e9e03de2eb35L,0xf8185d5cb8dacbb4L, + 0x9a88e2658644549dL } }, + /* 54 << 91 */ + { { 0xf717af6254671ff6L,0x4bd4241b5fa58603L,0x06fba40be67773c0L, + 0xc1d933d26a2847e9L }, + { 0xf4f5acf3689e2c70L,0x92aab0e746bafd31L,0x798d76aa3473f6e5L, + 0xcc6641db93141934L } }, + /* 55 << 91 */ + { { 0xcae27757d31e535eL,0x04cc43b687c2ee11L,0x8d1f96752e029ffaL, + 0xc2150672e4cc7a2cL }, + { 0x3b03c1e08d68b013L,0xa9d6816fedf298f3L,0x1bfbb529a2804464L, + 0x95a52fae5db22125L } }, + /* 56 << 91 */ + { { 0x55b321600e1cb64eL,0x004828f67e7fc9feL,0x13394b821bb0fb93L, + 0xb6293a2d35f1a920L }, + { 0xde35ef21d145d2d9L,0xbe6225b3bb8fa603L,0x00fc8f6b32cf252dL, + 0xa28e52e6117cf8c2L } }, + /* 57 << 91 */ + { { 0x9d1dc89b4c371e6dL,0xcebe067536ef0f28L,0x5de05d09a4292f81L, + 0xa8303593353e3083L }, + { 0xa1715b0a7e37a9bbL,0x8c56f61e2b8faec3L,0x5250743133c9b102L, + 0x0130cefca44431f0L } }, + /* 58 << 91 */ + { { 0x56039fa0bd865cfbL,0x4b03e578bc5f1dd7L,0x40edf2e4babe7224L, + 0xc752496d3a1988f6L }, + { 0xd1572d3b564beb6bL,0x0db1d11039a1c608L,0x568d193416f60126L, + 0x05ae9668f354af33L } }, + /* 59 << 91 */ + { { 0x19de6d37c92544f2L,0xcc084353a35837d5L,0xcbb6869c1a514eceL, + 0xb633e7282e1d1066L }, + { 0xf15dd69f936c581cL,0x96e7b8ce7439c4f9L,0x5e676f482e448a5bL, + 0xb2ca7d5bfd916bbbL } }, + /* 60 << 91 */ + { { 0xd55a2541f5024025L,0x47bc5769e4c2d937L,0x7d31b92a0362189fL, + 0x83f3086eef7816f9L }, + { 0xf9f46d94b587579aL,0xec2d22d830e76c5fL,0x27d57461b000ffcfL, + 0xbb7e65f9364ffc2cL } }, + /* 61 << 91 */ + { { 0x7c7c94776652a220L,0x61618f89d696c981L,0x5021701d89effff3L, + 0xf2c8ff8e7c314163L }, + { 0x2da413ad8efb4d3eL,0x937b5adfce176d95L,0x22867d342a67d51cL, + 0x262b9b1018eb3ac9L } }, + /* 62 << 91 */ + { { 0x4e314fe4c43ff28bL,0x764766276a664e7aL,0x3e90e40bb7a565c2L, + 0x8588993ac1acf831L }, + { 0xd7b501d68f938829L,0x996627ee3edd7d4cL,0x37d44a6290cd34c7L, + 0xa8327499f3833e8dL } }, + /* 63 << 91 */ + { { 0x2e18917d4bf50353L,0x85dd726b556765fbL,0x54fe65d693d5ab66L, + 0x3ddbaced915c25feL }, + { 0xa799d9a412f22e85L,0xe2a248676d06f6bcL,0xf4f1ee5643ca1637L, + 0xfda2828b61ece30aL } }, + /* 64 << 91 */ + { { 0x758c1a3ea2dee7a6L,0xdcde2f3c734b2284L,0xaba445d24eaba6adL, + 0x35aaf66876cee0a7L }, + { 0x7e0b04a9e5aa049aL,0xe74083ad91103e84L,0xbeb183ce40afecc3L, + 0x6b89de9fea043f7aL } }, + /* 0 << 98 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 98 */ + { { 0x0e299d23fe67ba66L,0x9145076093cf2f34L,0xf45b5ea997fcf913L, + 0x5be008438bd7dddaL }, + { 0x358c3e05d53ff04dL,0xbf7ccdc35de91ef7L,0xad684dbfb69ec1a0L, + 0x367e7cf2801fd997L } }, + /* 2 << 98 */ + { { 0x0ca1f3b7b0dc8595L,0x27de46089f1d9f2eL,0x1af3bf39badd82a7L, + 0x79356a7965862448L }, + { 0xc0602345f5f9a052L,0x1a8b0f89139a42f9L,0xb53eee42844d40fcL, + 0x93b0bfe54e5b6368L } }, + /* 3 << 98 */ + { { 0x5434dd02c024789cL,0x90dca9ea41b57bfcL,0x8aa898e2243398dfL, + 0xf607c834894a94bbL }, + { 0xbb07be97c2c99b76L,0x6576ba6718c29302L,0x3d79efcce703a88cL, + 0xf259ced7b6a0d106L } }, + /* 4 << 98 */ + { { 0x0f893a5dc8de610bL,0xe8c515fb67e223ceL,0x7774bfa64ead6dc5L, + 0x89d20f95925c728fL }, + { 0x7a1e0966098583ceL,0xa2eedb9493f2a7d7L,0x1b2820974c304d4aL, + 0x0842e3dac077282dL } }, + /* 5 << 98 */ + { { 0xe4d972a33b9e2d7bL,0x7cc60b27c48218ffL,0x8fc7083884149d91L, + 0x5c04346f2f461eccL }, + { 0xebe9fdf2614650a9L,0x5e35b537c1f666acL,0x645613d188babc83L, + 0x88cace3ac5e1c93eL } }, + /* 6 << 98 */ + { { 0x209ca3753de92e23L,0xccb03cc85fbbb6e3L,0xccb90f03d7b1487eL, + 0xfa9c2a38c710941fL }, + { 0x756c38236724ceedL,0x3a902258192d0323L,0xb150e519ea5e038eL, + 0xdcba2865c7427591L } }, + /* 7 << 98 */ + { { 0xe549237f78890732L,0xc443bef953fcb4d9L,0x9884d8a6eb3480d6L, + 0x8a35b6a13048b186L }, + { 0xb4e4471665e9a90aL,0x45bf380d653006c0L,0x8f3f820d4fe9ae3bL, + 0x244a35a0979a3b71L } }, + /* 8 << 98 */ + { { 0xa1010e9d74cd06ffL,0x9c17c7dfaca3eeacL,0x74c86cd38063aa2bL, + 0x8595c4b3734614ffL }, + { 0xa3de00ca990f62ccL,0xd9bed213ca0c3be5L,0x7886078adf8ce9f5L, + 0xddb27ce35cd44444L } }, + /* 9 << 98 */ + { { 0xed374a6658926dddL,0x138b2d49908015b8L,0x886c6579de1f7ab8L, + 0x888b9aa0c3020b7aL }, + { 0xd3ec034e3a96e355L,0xba65b0b8f30fbe9aL,0x064c8e50ff21367aL, + 0x1f508ea40b04b46eL } }, + /* 10 << 98 */ + { { 0x98561a49747c866cL,0xbbb1e5fe0518a062L,0x20ff4e8becdc3608L, + 0x7f55cded20184027L }, + { 0x8d73ec95f38c85f0L,0x5b589fdf8bc3b8c3L,0xbe95dd980f12b66fL, + 0xf5bd1a090e338e01L } }, + /* 11 << 98 */ + { { 0x65163ae55e915918L,0x6158d6d986f8a46bL,0x8466b538eeebf99cL, + 0xca8761f6bca477efL }, + { 0xaf3449c29ebbc601L,0xef3b0f41e0c3ae2fL,0xaa6c577d5de63752L, + 0xe916660164682a51L } }, + /* 12 << 98 */ + { { 0x5a3097befc15aa1eL,0x40d12548b54b0745L,0x5bad4706519a5f12L, + 0xed03f717a439dee6L }, + { 0x0794bb6c4a02c499L,0xf725083dcffe71d2L,0x2cad75190f3adcafL, + 0x7f68ea1c43729310L } }, + /* 13 << 98 */ + { { 0xe747c8c7b7ffd977L,0xec104c3580761a22L,0x8395ebaf5a3ffb83L, + 0xfb3261f4e4b63db7L }, + { 0x53544960d883e544L,0x13520d708cc2eeb8L,0x08f6337bd3d65f99L, + 0x83997db2781cf95bL } }, + /* 14 << 98 */ + { { 0xce6ff1060dbd2c01L,0x4f8eea6b1f9ce934L,0x546f7c4b0e993921L, + 0x6236a3245e753fc7L }, + { 0x65a41f84a16022e9L,0x0c18d87843d1dbb2L,0x73c556402d4cef9cL, + 0xa042810870444c74L } }, + /* 15 << 98 */ + { { 0x68e4f15e9afdfb3cL,0x49a561435bdfb6dfL,0xa9bc1bd45f823d97L, + 0xbceb5970ea111c2aL }, + { 0x366b455fb269bbc4L,0x7cd85e1ee9bc5d62L,0xc743c41c4f18b086L, + 0xa4b4099095294fb9L } }, + /* 16 << 98 */ + { { 0x9c7c581d26ee8382L,0xcf17dcc5359d638eL,0xee8273abb728ae3dL, + 0x1d112926f821f047L }, + { 0x1149847750491a74L,0x687fa761fde0dfb9L,0x2c2580227ea435abL, + 0x6b8bdb9491ce7e3fL } }, + /* 17 << 98 */ + { { 0x4c5b5dc93bf834aaL,0x043718194f6c7e4bL,0xc284e00a3736bcadL, + 0x0d88111821ae8f8dL }, + { 0xf9cf0f82f48c8e33L,0xa11fd075a1bf40dbL,0xdceab0dedc2733e5L, + 0xc560a8b58e986bd7L } }, + /* 18 << 98 */ + { { 0x48dd1fe23929d097L,0x3885b29092f188f1L,0x0f2ae613da6fcdacL, + 0x9054303eb662a46cL }, + { 0xb6871e440738042aL,0x98e6a977bdaf6449L,0xd8bc0650d1c9df1bL, + 0xef3d645136e098f9L } }, + /* 19 << 98 */ + { { 0x03fbae82b6d72d28L,0x77ca9db1f5d84080L,0x8a112cffa58efc1cL, + 0x518d761cc564cb4aL }, + { 0x69b5740ef0d1b5ceL,0x717039cce9eb1785L,0x3fe29f9022f53382L, + 0x8e54ba566bc7c95cL } }, + /* 20 << 98 */ + { { 0x9c806d8af7f91d0fL,0x3b61b0f1a82a5728L,0x4640032d94d76754L, + 0x273eb5de47d834c6L }, + { 0x2988abf77b4e4d53L,0xb7ce66bfde401777L,0x9fba6b32715071b3L, + 0x82413c24ad3a1a98L } }, + /* 21 << 98 */ + { { 0x5b7fc8c4e0e8ad93L,0xb5679aee5fab868dL,0xb1f9d2fa2b3946f3L, + 0x458897dc5685b50aL }, + { 0x1e98c93089d0caf3L,0x39564c5f78642e92L,0x1b77729a0dbdaf18L, + 0xf9170722579e82e6L } }, + /* 22 << 98 */ + { { 0x680c0317e4515fa5L,0xf85cff84fb0c790fL,0xc7a82aab6d2e0765L, + 0x7446bca935c82b32L }, + { 0x5de607aa6d63184fL,0x7c1a46a8262803a6L,0xd218313daebe8035L, + 0x92113ffdc73c51f8L } }, + /* 23 << 98 */ + { { 0x4b38e08312e7e46cL,0x69d0a37a56126bd5L,0xfb3f324b73c07e04L, + 0xa0c22f678fda7267L }, + { 0x8f2c00514d2c7d8fL,0xbc45ced3cbe2cae5L,0xe1c6cf07a8f0f277L, + 0xbc3923121eb99a98L } }, + /* 24 << 98 */ + { { 0x75537b7e3cc8ac85L,0x8d725f57dd02753bL,0xfd05ff64b737df2fL, + 0x55fe8712f6d2531dL }, + { 0x57ce04a96ab6b01cL,0x69a02a897cd93724L,0x4f82ac35cf86699bL, + 0x8242d3ad9cb4b232L } }, + /* 25 << 98 */ + { { 0x713d0f65d62105e5L,0xbb222bfa2d29be61L,0xf2f9a79e6cfbef09L, + 0xfc24d8d3d5d6782fL }, + { 0x5db77085d4129967L,0xdb81c3ccdc3c2a43L,0x9d655fc005d8d9a3L, + 0x3f5d057a54298026L } }, + /* 26 << 98 */ + { { 0x1157f56d88c54694L,0xb26baba59b09573eL,0x2cab03b022adffd1L, + 0x60a412c8dd69f383L }, + { 0xed76e98b54b25039L,0xd4ee67d3687e714dL,0x877396487b00b594L, + 0xce419775c9ef709bL } }, + /* 27 << 98 */ + { { 0x40f76f851c203a40L,0x30d352d6eafd8f91L,0xaf196d3d95578dd2L, + 0xea4bb3d777cc3f3dL }, + { 0x42a5bd03b98e782bL,0xac958c400624920dL,0xb838134cfc56fcc8L, + 0x86ec4ccf89572e5eL } }, + /* 28 << 98 */ + { { 0x69c435269be47be0L,0x323b7dd8cb28fea1L,0xfa5538ba3a6c67e5L, + 0xef921d701d378e46L }, + { 0xf92961fc3c4b880eL,0x3f6f914e98940a67L,0xa990eb0afef0ff39L, + 0xa6c2920ff0eeff9cL } }, + /* 29 << 98 */ + { { 0xca80416651b8d9a3L,0x42531bc90ffb0db1L,0x72ce4718aa82e7ceL, + 0x6e199913df574741L }, + { 0xd5f1b13dd5d36946L,0x8255dc65f68f0194L,0xdc9df4cd8710d230L, + 0x3453c20f138c1988L } }, + /* 30 << 98 */ + { { 0x9af98dc089a6ef01L,0x4dbcc3f09857df85L,0x348056015c1ad924L, + 0x40448da5d0493046L }, + { 0xf629926d4ee343e2L,0x6343f1bd90e8a301L,0xefc9349140815b3fL, + 0xf882a423de8f66fbL } }, + /* 31 << 98 */ + { { 0x3a12d5f4e7db9f57L,0x7dfba38a3c384c27L,0x7a904bfd6fc660b1L, + 0xeb6c5db32773b21cL }, + { 0xc350ee661cdfe049L,0x9baac0ce44540f29L,0xbc57b6aba5ec6aadL, + 0x167ce8c30a7c1baaL } }, + /* 32 << 98 */ + { { 0xb23a03a553fb2b56L,0x6ce141e74e057f78L,0x796525c389e490d9L, + 0x0bc95725a31a7e75L }, + { 0x1ec567911220fd06L,0x716e3a3c408b0bd6L,0x31cd6bf7e8ebeba9L, + 0xa7326ca6bee6b670L } }, + /* 33 << 98 */ + { { 0x3d9f851ccd090c43L,0x561e8f13f12c3988L,0x50490b6a904b7be4L, + 0x61690ce10410737bL }, + { 0x299e9a370f009052L,0x258758f0f026092eL,0x9fa255f3fdfcdc0fL, + 0xdbc9fb1fc0e1bcd2L } }, + /* 34 << 98 */ + { { 0x35f9dd6e24651840L,0xdca45a84a5c59abcL,0x103d396fecca4938L, + 0x4532da0ab97b3f29L }, + { 0xc4135ea51999a6bfL,0x3aa9505a5e6bf2eeL,0xf77cef063f5be093L, + 0x97d1a0f8a943152eL } }, + /* 35 << 98 */ + { { 0x2cb0ebba2e1c21ddL,0xf41b29fc2c6797c4L,0xc6e17321b300101fL, + 0x4422b0e9d0d79a89L }, + { 0x49e4901c92f1bfc4L,0x06ab1f8fe1e10ed9L,0x84d35577db2926b8L, + 0xca349d39356e8ec2L } }, + /* 36 << 98 */ + { { 0x70b63d32343bf1a9L,0x8fd3bd2837d1a6b1L,0x0454879c316865b4L, + 0xee959ff6c458efa2L }, + { 0x0461dcf89706dc3fL,0x737db0e2164e4b2eL,0x092626802f8843c8L, + 0x54498bbc7745e6f6L } }, + /* 37 << 98 */ + { { 0x359473faa29e24afL,0xfcc3c45470aa87a1L,0xfd2c4bf500573aceL, + 0xb65b514e28dd1965L }, + { 0xe46ae7cf2193e393L,0x60e9a4e1f5444d97L,0xe7594e9600ff38edL, + 0x43d84d2f0a0e0f02L } }, + /* 38 << 98 */ + { { 0x8b6db141ee398a21L,0xb88a56aee3bcc5beL,0x0a1aa52f373460eaL, + 0x20da1a56160bb19bL }, + { 0xfb54999d65bf0384L,0x71a14d245d5a180eL,0xbc44db7b21737b04L, + 0xd84fcb1801dd8e92L } }, + /* 39 << 98 */ + { { 0x80de937bfa44b479L,0x535054995c98fd4fL,0x1edb12ab28f08727L, + 0x4c58b582a5f3ef53L }, + { 0xbfb236d88327f246L,0xc3a3bfaa4d7df320L,0xecd96c59b96024f2L, + 0xfc293a537f4e0433L } }, + /* 40 << 98 */ + { { 0x5341352b5acf6e10L,0xc50343fdafe652c3L,0x4af3792d18577a7fL, + 0xe1a4c617af16823dL }, + { 0x9b26d0cd33425d0aL,0x306399ed9b7bc47fL,0x2a792f33706bb20bL, + 0x3121961498111055L } }, + /* 41 << 98 */ + { { 0x864ec06487f5d28bL,0x11392d91962277fdL,0xb5aa7942bb6aed5fL, + 0x080094dc47e799d9L }, + { 0x4afa588c208ba19bL,0xd3e7570f8512f284L,0xcbae64e602f5799aL, + 0xdeebe7ef514b9492L } }, + /* 42 << 98 */ + { { 0x30300f98e5c298ffL,0x17f561be3678361fL,0xf52ff31298cb9a16L, + 0x6233c3bc5562d490L }, + { 0x7bfa15a192e3a2cbL,0x961bcfd1e6365119L,0x3bdd29bf2c8c53b1L, + 0x739704df822844baL } }, + /* 43 << 98 */ + { { 0x7dacfb587e7b754bL,0x23360791a806c9b9L,0xe7eb88c923504452L, + 0x2983e996852c1783L }, + { 0xdd4ae529958d881dL,0x026bae03262c7b3cL,0x3a6f9193960b52d1L, + 0xd0980f9092696cfbL } }, + /* 44 << 98 */ + { { 0x4c1f428cd5f30851L,0x94dfed272a4f6630L,0x4df53772fc5d48a4L, + 0xdd2d5a2f933260ceL }, + { 0x574115bdd44cc7a5L,0x4ba6b20dbd12533aL,0x30e93cb8243057c9L, + 0x794c486a14de320eL } }, + /* 45 << 98 */ + { { 0xe925d4cef21496e4L,0xf951d198ec696331L,0x9810e2de3e8d812fL, + 0xd0a47259389294abL }, + { 0x513ba2b50e3bab66L,0x462caff5abad306fL,0xe2dc6d59af04c49eL, + 0x1aeb8750e0b84b0bL } }, + /* 46 << 98 */ + { { 0xc034f12f2f7d0ca2L,0x6d2e8128e06acf2fL,0x801f4f8321facc2fL, + 0xa1170c03f40ef607L }, + { 0xfe0a1d4f7805a99cL,0xbde56a36cc26aba5L,0x5b1629d035531f40L, + 0xac212c2b9afa6108L } }, + /* 47 << 98 */ + { { 0x30a06bf315697be5L,0x6f0545dc2c63c7c1L,0x5d8cb8427ccdadafL, + 0xd52e379bac7015bbL }, + { 0xc4f56147f462c23eL,0xd44a429846bc24b0L,0xbc73d23ae2856d4fL, + 0x61cedd8c0832bcdfL } }, + /* 48 << 98 */ + { { 0x6095355699f241d7L,0xee4adbd7001a349dL,0x0b35bf6aaa89e491L, + 0x7f0076f4136f7546L }, + { 0xd19a18ba9264da3dL,0x6eb2d2cd62a7a28bL,0xcdba941f8761c971L, + 0x1550518ba3be4a5dL } }, + /* 49 << 98 */ + { { 0xd0e8e2f057d0b70cL,0xeea8612ecd133ba3L,0x814670f044416aecL, + 0x424db6c330775061L }, + { 0xd96039d116213fd1L,0xc61e7fa518a3478fL,0xa805bdcccb0c5021L, + 0xbdd6f3a80cc616ddL } }, + /* 50 << 98 */ + { { 0x060096675d97f7e2L,0x31db0fc1af0bf4b6L,0x23680ed45491627aL, + 0xb99a3c667d741fb1L }, + { 0xe9bb5f5536b1ff92L,0x29738577512b388dL,0xdb8a2ce750fcf263L, + 0x385346d46c4f7b47L } }, + /* 51 << 98 */ + { { 0xbe86c5ef31631f9eL,0xbf91da2103a57a29L,0xc3b1f7967b23f821L, + 0x0f7d00d2770db354L }, + { 0x8ffc6c3bd8fe79daL,0xcc5e8c40d525c996L,0x4640991dcfff632aL, + 0x64d97e8c67112528L } }, + /* 52 << 98 */ + { { 0xc232d97302f1cd1eL,0xce87eacb1dd212a4L,0x6e4c8c73e69802f7L, + 0x12ef02901fffddbdL }, + { 0x941ec74e1bcea6e2L,0xd0b540243cb92cbbL,0x809fb9d47e8f9d05L, + 0x3bf16159f2992aaeL } }, + /* 53 << 98 */ + { { 0xad40f279f8a7a838L,0x11aea63105615660L,0xbf52e6f1a01f6fa1L, + 0xef0469953dc2aec9L }, + { 0x785dbec9d8080711L,0xe1aec60a9fdedf76L,0xece797b5fa21c126L, + 0xc66e898f05e52732L } }, + /* 54 << 98 */ + { { 0x39bb69c408811fdbL,0x8bfe1ef82fc7f082L,0xc8e7a393174f4138L, + 0xfba8ad1dd58d1f98L }, + { 0xbc21d0cebfd2fd5bL,0x0b839a826ee60d61L,0xaacf7658afd22253L, + 0xb526bed8aae396b3L } }, + /* 55 << 98 */ + { { 0xccc1bbc238564464L,0x9e3ff9478c45bc73L,0xcde9bca358188a78L, + 0x138b8ee0d73bf8f7L }, + { 0x5c7e234c4123c489L,0x66e69368fa643297L,0x0629eeee39a15fa3L, + 0x95fab881a9e2a927L } }, + /* 56 << 98 */ + { { 0xb2497007eafbb1e1L,0xd75c9ce6e75b7a93L,0x3558352defb68d78L, + 0xa2f26699223f6396L }, + { 0xeb911ecfe469b17aL,0x62545779e72d3ec2L,0x8ea47de782cb113fL, + 0xebe4b0864e1fa98dL } }, + /* 57 << 98 */ + { { 0xec2d5ed78cdfedb1L,0xa535c077fe211a74L,0x9678109b11d244c5L, + 0xf17c8bfbbe299a76L }, + { 0xb651412efb11fbc4L,0xea0b548294ab3f65L,0xd8dffd950cf78243L, + 0x2e719e57ce0361d4L } }, + /* 58 << 98 */ + { { 0x9007f085304ddc5bL,0x095e8c6d4daba2eaL,0x5a33cdb43f9d28a9L, + 0x85b95cd8e2283003L }, + { 0xbcd6c819b9744733L,0x29c5f538fc7f5783L,0x6c49b2fad59038e4L, + 0x68349cc13bbe1018L } }, + /* 59 << 98 */ + { { 0xcc490c1d21830ee5L,0x36f9c4eee9bfa297L,0x58fd729448de1a94L, + 0xaadb13a84e8f2cdcL }, + { 0x515eaaa081313dbaL,0xc76bb468c2152dd8L,0x357f8d75a653dbf8L, + 0xe4d8c4d1b14ac143L } }, + /* 60 << 98 */ + { { 0xbdb8e675b055cb40L,0x898f8e7b977b5167L,0xecc65651b82fb863L, + 0x565448146d88f01fL }, + { 0xb0928e95263a75a9L,0xcfb6836f1a22fcdaL,0x651d14db3f3bd37cL, + 0x1d3837fbb6ad4664L } }, + /* 61 << 98 */ + { { 0x7c5fb538ff4f94abL,0x7243c7126d7fb8f2L,0xef13d60ca85c5287L, + 0x18cfb7c74bb8dd1bL }, + { 0x82f9bfe672908219L,0x35c4592b9d5144abL,0x52734f379cf4b42fL, + 0x6bac55e78c60ddc4L } }, + /* 62 << 98 */ + { { 0xb5cd811e94dea0f6L,0x259ecae4e18cc1a3L,0x6a0e836e15e660f8L, + 0x6c639ea60e02bff2L }, + { 0x8721b8cb7e1026fdL,0x9e73b50b63261942L,0xb8c7097477f01da3L, + 0x1839e6a68268f57fL } }, + /* 63 << 98 */ + { { 0x571b94155150b805L,0x1892389ef92c7097L,0x8d69c18e4a084b95L, + 0x7014c512be5b495cL }, + { 0x4780db361b07523cL,0x2f6219ce2c1c64faL,0xc38b81b0602c105aL, + 0xab4f4f205dc8e360L } }, + /* 64 << 98 */ + { { 0x20d3c982cf7d62d2L,0x1f36e29d23ba8150L,0x48ae0bf092763f9eL, + 0x7a527e6b1d3a7007L }, + { 0xb4a89097581a85e3L,0x1f1a520fdc158be5L,0xf98db37d167d726eL, + 0x8802786e1113e862L } }, + /* 0 << 105 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 105 */ + { { 0xefb2149e36f09ab0L,0x03f163ca4a10bb5bL,0xd029704506e20998L, + 0x56f0af001b5a3babL }, + { 0x7af4cfec70880e0dL,0x7332a66fbe3d913fL,0x32e6c84a7eceb4bdL, + 0xedc4a79a9c228f55L } }, + /* 2 << 105 */ + { { 0xc37c7dd0c55c4496L,0xa6a9635725bbabd2L,0x5b7e63f2add7f363L, + 0x9dce37822e73f1dfL }, + { 0xe1e5a16ab2b91f71L,0xe44898235ba0163cL,0xf2759c32f6e515adL, + 0xa5e2f1f88615eecfL } }, + /* 3 << 105 */ + { { 0x74519be7abded551L,0x03d358b8c8b74410L,0x4d00b10b0e10d9a9L, + 0x6392b0b128da52b7L }, + { 0x6744a2980b75c904L,0xc305b0aea8f7f96cL,0x042e421d182cf932L, + 0xf6fc5d509e4636caL } }, + /* 4 << 105 */ + { { 0x795847c9d64cc78cL,0x6c50621b9b6cb27bL,0x07099bf8df8022abL, + 0x48f862ebc04eda1dL }, + { 0xd12732ede1603c16L,0x19a80e0f5c9a9450L,0xe2257f54b429b4fcL, + 0x66d3b2c645460515L } }, + /* 5 << 105 */ + { { 0x6ca4f87e822e37beL,0x73f237b4253bda4eL,0xf747f3a241190aebL, + 0xf06fa36f804cf284L }, + { 0x0a6bbb6efc621c12L,0x5d624b6440b80ec6L,0x4b0724257ba556f3L, + 0x7fa0c3543e2d20a8L } }, + /* 6 << 105 */ + { { 0xe921fa31e3229d41L,0xa929c65294531bd4L,0x84156027a6d38209L, + 0xf3d69f736bdb97bdL }, + { 0x8906d19a16833631L,0x68a34c2e03d51be3L,0xcb59583b0e511cd8L, + 0x99ce6bfdfdc132a8L } }, + /* 7 << 105 */ + { { 0x3facdaaaffcdb463L,0x658bbc1a34a38b08L,0x12a801f8f1a9078dL, + 0x1567bcf96ab855deL }, + { 0xe08498e03572359bL,0xcf0353e58659e68bL,0xbb86e9c87d23807cL, + 0xbc08728d2198e8a2L } }, + /* 8 << 105 */ + { { 0x8de2b7bc453cadd6L,0x203900a7bc0bc1f8L,0xbcd86e47a6abd3afL, + 0x911cac128502effbL }, + { 0x2d550242ec965469L,0x0e9f769229e0017eL,0x633f078f65979885L, + 0xfb87d4494cf751efL } }, + /* 9 << 105 */ + { { 0xe1790e4bfc25419aL,0x364672034bff3cfdL,0xc8db638625b6e83fL, + 0x6cc69f236cad6fd2L }, + { 0x0219e45a6bc68bb9L,0xe43d79b6297f7334L,0x7d445368465dc97cL, + 0x4b9eea322a0b949aL } }, + /* 10 << 105 */ + { { 0x1b96c6ba6102d021L,0xeaafac782f4461eaL,0xd4b85c41c49f19a8L, + 0x275c28e4cf538875L }, + { 0x35451a9ddd2e54e0L,0x6991adb50605618bL,0x5b8b4bcd7b36cd24L, + 0x372a4f8c56f37216L } }, + /* 11 << 105 */ + { { 0xc890bd73a6a5da60L,0x6f083da0dc4c9ff0L,0xf4e14d94f0536e57L, + 0xf9ee1edaaaec8243L }, + { 0x571241ec8bdcf8e7L,0xa5db82710b041e26L,0x9a0b9a99e3fff040L, + 0xcaaf21dd7c271202L } }, + /* 12 << 105 */ + { { 0xb4e2b2e14f0dd2e8L,0xe77e7c4f0a377ac7L,0x69202c3f0d7a2198L, + 0xf759b7ff28200eb8L }, + { 0xc87526eddcfe314eL,0xeb84c52453d5cf99L,0xb1b52ace515138b6L, + 0x5aa7ff8c23fca3f4L } }, + /* 13 << 105 */ + { { 0xff0b13c3b9791a26L,0x960022dacdd58b16L,0xdbd55c9257aad2deL, + 0x3baaaaa3f30fe619L }, + { 0x9a4b23460d881efdL,0x506416c046325e2aL,0x91381e76035c18d4L, + 0xb3bb68bef27817b0L } }, + /* 14 << 105 */ + { { 0x15bfb8bf5116f937L,0x7c64a586c1268943L,0x71e25cc38419a2c8L, + 0x9fd6b0c48335f463L }, + { 0x4bf0ba3ce8ee0e0eL,0x6f6fba60298c21faL,0x57d57b39ae66bee0L, + 0x292d513022672544L } }, + /* 15 << 105 */ + { { 0xf451105dbab093b3L,0x012f59b902839986L,0x8a9158023474a89cL, + 0x048c919c2de03e97L }, + { 0xc476a2b591071cd5L,0x791ed89a034970a5L,0x89bd9042e1b7994bL, + 0x8eaf5179a1057ffdL } }, + /* 16 << 105 */ + { { 0x6066e2a2d551ee10L,0x87a8f1d8727e09a6L,0x00d08bab2c01148dL, + 0x6da8e4f1424f33feL }, + { 0x466d17f0cf9a4e71L,0xff5020103bf5cb19L,0xdccf97d8d062ecc0L, + 0x80c0d9af81d80ac4L } }, + /* 17 << 105 */ + { { 0xe87771d8033f2876L,0xb0186ec67d5cc3dbL,0x58e8bb803bc9bc1dL, + 0x4d1395cc6f6ef60eL }, + { 0xa73c62d6186244a0L,0x918e5f23110a5b53L,0xed4878ca741b7eabL, + 0x3038d71adbe03e51L } }, + /* 18 << 105 */ + { { 0x840204b7a93c3246L,0x21ab6069a0b9b4cdL,0xf5fa6e2bb1d64218L, + 0x1de6ad0ef3d56191L }, + { 0x570aaa88ff1929c7L,0xc6df4c6b640e87b5L,0xde8a74f2c65f0cccL, + 0x8b972fd5e6f6cc01L } }, + /* 19 << 105 */ + { { 0x3fff36b60b846531L,0xba7e45e610a5e475L,0x84a1d10e4145b6c5L, + 0xf1f7f91a5e046d9dL }, + { 0x0317a69244de90d7L,0x951a1d4af199c15eL,0x91f78046c9d73debL, + 0x74c82828fab8224fL } }, + /* 20 << 105 */ + { { 0xaa6778fce7560b90L,0xb4073e61a7e824ceL,0xff0d693cd642eba8L, + 0x7ce2e57a5dccef38L }, + { 0x89c2c7891df1ad46L,0x83a06922098346fdL,0x2d715d72da2fc177L, + 0x7b6dd71d85b6cf1dL } }, + /* 21 << 105 */ + { { 0xc60a6d0a73fa9cb0L,0xedd3992e328bf5a9L,0xc380ddd0832c8c82L, + 0xd182d410a2a0bf50L }, + { 0x7d9d7438d9a528dbL,0xe8b1a0e9caf53994L,0xddd6e5fe0e19987cL, + 0xacb8df03190b059dL } }, + /* 22 << 105 */ + { { 0x53703a328300129fL,0x1f63766268c43bfdL,0xbcbd191300e54051L, + 0x812fcc627bf5a8c5L }, + { 0x3f969d5f29fb85daL,0x72f4e00a694759e8L,0x426b6e52790726b7L, + 0x617bbc873bdbb209L } }, + /* 23 << 105 */ + { { 0x511f8bb997aee317L,0x812a4096e81536a8L,0x137dfe593ac09b9bL, + 0x0682238fba8c9a7aL }, + { 0x7072ead6aeccb4bdL,0x6a34e9aa692ba633L,0xc82eaec26fff9d33L, + 0xfb7535121d4d2b62L } }, + /* 24 << 105 */ + { { 0x1a0445ff1d7aadabL,0x65d38260d5f6a67cL,0x6e62fb0891cfb26fL, + 0xef1e0fa55c7d91d6L }, + { 0x47e7c7ba33db72cdL,0x017cbc09fa7c74b2L,0x3c931590f50a503cL, + 0xcac54f60616baa42L } }, + /* 25 << 105 */ + { { 0x9b6cd380b2369f0fL,0x97d3a70d23c76151L,0x5f9dd6fc9862a9c6L, + 0x044c4ab212312f51L }, + { 0x035ea0fd834a2ddcL,0x49e6b862cc7b826dL,0xb03d688362fce490L, + 0x62f2497ab37e36e9L } }, + /* 26 << 105 */ + { { 0x04b005b6c6458293L,0x36bb5276e8d10af7L,0xacf2dc138ee617b8L, + 0x470d2d35b004b3d4L }, + { 0x06790832feeb1b77L,0x2bb75c3985657f9cL,0xd70bd4edc0f60004L, + 0xfe797ecc219b018bL } }, + /* 27 << 105 */ + { { 0x9b5bec2a753aebccL,0xdaf9f3dcc939eca5L,0xd6bc6833d095ad09L, + 0x98abdd51daa4d2fcL }, + { 0xd9840a318d168be5L,0xcf7c10e02325a23cL,0xa5c02aa07e6ecfafL, + 0x2462e7e6b5bfdf18L } }, + /* 28 << 105 */ + { { 0xab2d8a8ba0cc3f12L,0x68dd485dbc672a29L,0x72039752596f2cd3L, + 0x5d3eea67a0cf3d8dL }, + { 0x810a1a81e6602671L,0x8f144a4014026c0cL,0xbc753a6d76b50f85L, + 0xc4dc21e8645cd4a4L } }, + /* 29 << 105 */ + { { 0xc5262dea521d0378L,0x802b8e0e05011c6fL,0x1ba19cbb0b4c19eaL, + 0x21db64b5ebf0aaecL }, + { 0x1f394ee970342f9dL,0x93a10aee1bc44a14L,0xa7eed31b3efd0baaL, + 0x6e7c824e1d154e65L } }, + /* 30 << 105 */ + { { 0xee23fa819966e7eeL,0x64ec4aa805b7920dL,0x2d44462d2d90aad4L, + 0xf44dd195df277ad5L }, + { 0x8d6471f1bb46b6a1L,0x1e65d313fd885090L,0x33a800f513a977b4L, + 0xaca9d7210797e1efL } }, + /* 31 << 105 */ + { { 0x9a5a85a0fcff6a17L,0x9970a3f31eca7ceeL,0xbb9f0d6bc9504be3L, + 0xe0c504beadd24ee2L }, + { 0x7e09d95677fcc2f4L,0xef1a522765bb5fc4L,0x145d4fb18b9286aaL, + 0x66fd0c5d6649028bL } }, + /* 32 << 105 */ + { { 0x98857ceb1bf4581cL,0xe635e186aca7b166L,0x278ddd22659722acL, + 0xa0903c4c1db68007L }, + { 0x366e458948f21402L,0x31b49c14b96abda2L,0x329c4b09e0403190L, + 0x97197ca3d29f43feL } }, + /* 33 << 105 */ + { { 0x8073dd1e274983d8L,0xda1a3bde55717c8fL,0xfd3d4da20361f9d1L, + 0x1332d0814c7de1ceL }, + { 0x9b7ef7a3aa6d0e10L,0x17db2e73f54f1c4aL,0xaf3dffae4cd35567L, + 0xaaa2f406e56f4e71L } }, + /* 34 << 105 */ + { { 0x8966759e7ace3fc7L,0x9594eacf45a8d8c6L,0x8de3bd8b91834e0eL, + 0xafe4ca53548c0421L }, + { 0xfdd7e856e6ee81c6L,0x8f671beb6b891a3aL,0xf7a58f2bfae63829L, + 0x9ab186fb9c11ac9fL } }, + /* 35 << 105 */ + { { 0x8d6eb36910b5be76L,0x046b7739fb040bcdL,0xccb4529fcb73de88L, + 0x1df0fefccf26be03L }, + { 0xad7757a6bcfcd027L,0xa8786c75bb3165caL,0xe9db1e347e99a4d9L, + 0x99ee86dfb06c504bL } }, + /* 36 << 105 */ + { { 0x5b7c2dddc15c9f0aL,0xdf87a7344295989eL,0x59ece47c03d08fdaL, + 0xb074d3ddad5fc702L }, + { 0x2040790351a03776L,0x2bb1f77b2a608007L,0x25c58f4fe1153185L, + 0xe6df62f6766e6447L } }, + /* 37 << 105 */ + { { 0xefb3d1beed51275aL,0x5de47dc72f0f483fL,0x7932d98e97c2bedfL, + 0xd5c119270219f8a1L }, + { 0x9d751200a73a294eL,0x5f88434a9dc20172L,0xd28d9fd3a26f506aL, + 0xa890cd319d1dcd48L } }, + /* 38 << 105 */ + { { 0x0aebaec170f4d3b4L,0xfd1a13690ffc8d00L,0xb9d9c24057d57838L, + 0x45929d2668bac361L }, + { 0x5a2cd06025b15ca6L,0x4b3c83e16e474446L,0x1aac7578ee1e5134L, + 0xa418f5d6c91e2f41L } }, + /* 39 << 105 */ + { { 0x6936fc8a213ed68bL,0x860ae7ed510a5224L,0x63660335def09b53L, + 0x641b2897cd79c98dL }, + { 0x29bd38e101110f35L,0x79c26f42648b1937L,0x64dae5199d9164f4L, + 0xd85a23100265c273L } }, + /* 40 << 105 */ + { { 0x7173dd5d4b07e2b1L,0xd144c4cb8d9ea221L,0xe8b04ea41105ab14L, + 0x92dda542fe80d8f1L }, + { 0xe9982fa8cf03dce6L,0x8b5ea9651a22cffcL,0xf7f4ea7f3fad88c4L, + 0x62db773e6a5ba95cL } }, + /* 41 << 105 */ + { { 0xd20f02fb93f24567L,0xfd46c69a315257caL,0x0ac74cc78bcab987L, + 0x46f31c015ceca2f5L }, + { 0x40aedb59888b219eL,0xe50ecc37e1fccd02L,0x1bcd9dad911f816cL, + 0x583cc1ec8db9b00cL } }, + /* 42 << 105 */ + { { 0xf3cd2e66a483bf11L,0xfa08a6f5b1b2c169L,0xf375e2454be9fa28L, + 0x99a7ffec5b6d011fL }, + { 0x6a3ebddbc4ae62daL,0x6cea00ae374aef5dL,0xab5fb98d9d4d05bcL, + 0x7cba1423d560f252L } }, + /* 43 << 105 */ + { { 0x49b2cc21208490deL,0x1ca66ec3bcfb2879L,0x7f1166b71b6fb16fL, + 0xfff63e0865fe5db3L }, + { 0xb8345abe8b2610beL,0xb732ed8039de3df4L,0x0e24ed50211c32b4L, + 0xd10d8a69848ff27dL } }, + /* 44 << 105 */ + { { 0xc1074398ed4de248L,0xd7cedace10488927L,0xa4aa6bf885673e13L, + 0xb46bae916daf30afL }, + { 0x07088472fcef7ad8L,0x61151608d4b35e97L,0xbcfe8f26dde29986L, + 0xeb84c4c7d5a34c79L } }, + /* 45 << 105 */ + { { 0xc1eec55c164e1214L,0x891be86da147bb03L,0x9fab4d100ba96835L, + 0xbf01e9b8a5c1ae9fL }, + { 0x6b4de139b186ebc0L,0xd5c74c2685b91bcaL,0x5086a99cc2d93854L, + 0xeed62a7ba7a9dfbcL } }, + /* 46 << 105 */ + { { 0x8778ed6f76b7618aL,0xbff750a503b66062L,0x4cb7be22b65186dbL, + 0x369dfbf0cc3a6d13L }, + { 0xc7dab26c7191a321L,0x9edac3f940ed718eL,0xbc142b36d0cfd183L, + 0xc8af82f67c991693L } }, + /* 47 << 105 */ + { { 0xb3d1e4d897ce0b2aL,0xe6d7c87fc3a55cdfL,0x35846b9568b81afeL, + 0x018d12afd3c239d8L }, + { 0x2b2c620801206e15L,0xe0e42453a3b882c6L,0x854470a3a50162d5L, + 0x081574787017a62aL } }, + /* 48 << 105 */ + { { 0x18bd3fb4820357c7L,0x992039ae6f1458adL,0x9a1df3c525b44aa1L, + 0x2d780357ed3d5281L }, + { 0x58cf7e4dc77ad4d4L,0xd49a7998f9df4fc4L,0x4465a8b51d71205eL, + 0xa0ee0ea6649254aaL } }, + /* 49 << 105 */ + { { 0x4b5eeecfab7bd771L,0x6c87307335c262b9L,0xdc5bd6483c9d61e7L, + 0x233d6d54321460d2L }, + { 0xd20c5626fc195bccL,0x2544595804d78b63L,0xe03fcb3d17ec8ef3L, + 0x54b690d146b8f781L } }, + /* 50 << 105 */ + { { 0x82fa2c8a21230646L,0xf51aabb9084f418cL,0xff4fbec11a30ba43L, + 0x6a5acf73743c9df7L }, + { 0x1da2b357d635b4d5L,0xc3de68ddecd5c1daL,0xa689080bd61af0ddL, + 0xdea5938ad665bf99L } }, + /* 51 << 105 */ + { { 0x0231d71afe637294L,0x01968aa6a5a81cd8L,0x11252d50048e63b5L, + 0xc446bc526ca007e9L }, + { 0xef8c50a696d6134bL,0x9361fbf59e09a05cL,0xf17f85a6dca3291aL, + 0xb178d548ff251a21L } }, + /* 52 << 105 */ + { { 0x87f6374ba4df3915L,0x566ce1bf2fd5d608L,0x425cba4d7de35102L, + 0x6b745f8f58c5d5e2L }, + { 0x88402af663122edfL,0x3190f9ed3b989a89L,0x4ad3d387ebba3156L, + 0xef385ad9c7c469a5L } }, + /* 53 << 105 */ + { { 0xb08281de3f642c29L,0x20be0888910ffb88L,0xf353dd4ad5292546L, + 0x3f1627de8377a262L }, + { 0xa5faa013eefcd638L,0x8f3bf62674cc77c3L,0x32618f65a348f55eL, + 0x5787c0dc9fefeb9eL } }, + /* 54 << 105 */ + { { 0xf1673aa2d9a23e44L,0x88dfa9934e10690dL,0x1ced1b362bf91108L, + 0x9193ceca3af48649L }, + { 0xfb34327d2d738fc5L,0x6697b037975fee6cL,0x2f485da0c04079a5L, + 0x2cdf57352feaa1acL } }, + /* 55 << 105 */ + { { 0x76944420bd55659eL,0x7973e32b4376090cL,0x86bb4fe1163b591aL, + 0x10441aedc196f0caL }, + { 0x3b431f4a045ad915L,0x6c11b437a4afacb1L,0x30b0c7db71fdbbd8L, + 0xb642931feda65acdL } }, + /* 56 << 105 */ + { { 0x4baae6e89c92b235L,0xa73bbd0e6b3993a1L,0xd06d60ec693dd031L, + 0x03cab91b7156881cL }, + { 0xd615862f1db3574bL,0x485b018564bb061aL,0x27434988a0181e06L, + 0x2cd61ad4c1c0c757L } }, + /* 57 << 105 */ + { { 0x3effed5a2ff9f403L,0x8dc98d8b62239029L,0x2206021e1f17b70dL, + 0xafbec0cabf510015L }, + { 0x9fed716480130dfaL,0x306dc2b58a02dcf5L,0x48f06620feb10fc0L, + 0x78d1e1d55a57cf51L } }, + /* 58 << 105 */ + { { 0xadef8c5a192ef710L,0x88afbd4b3b7431f9L,0x7e1f740764250c9eL, + 0x6e31318db58bec07L }, + { 0xfd4fc4b824f89b4eL,0x65a5dd8848c36a2aL,0x4f1eccfff024baa7L, + 0x22a21cf2cba94650L } }, + /* 59 << 105 */ + { { 0x95d29dee42a554f7L,0x828983a5002ec4baL,0x8112a1f78badb73dL, + 0x79ea8897a27c1839L }, + { 0x8969a5a7d065fd83L,0xf49af791b262a0bcL,0xfcdea8b6af2b5127L, + 0x10e913e1564c2dbcL } }, + /* 60 << 105 */ + { { 0x51239d14bc21ef51L,0xe51c3ceb4ce57292L,0x795ff06847bbcc3bL, + 0x86b46e1ebd7e11e6L }, + { 0x0ea6ba2380041ef4L,0xd72fe5056262342eL,0x8abc6dfd31d294d4L, + 0xbbe017a21278c2c9L } }, + /* 61 << 105 */ + { { 0xb1fcfa09b389328aL,0x322fbc62d01771b5L,0x04c0d06360b045bfL, + 0xdb652edc10e52d01L }, + { 0x50ef932c03ec6627L,0xde1b3b2dc1ee50e3L,0x5ab7bdc5dc37a90dL, + 0xfea6721331e33a96L } }, + /* 62 << 105 */ + { { 0x6482b5cb4f2999aaL,0x38476cc6b8cbf0ddL,0x93ebfacb173405bbL, + 0x15cdafe7e52369ecL }, + { 0xd42d5ba4d935b7dbL,0x648b60041c99a4cdL,0x785101bda3b5545bL, + 0x4bf2c38a9dd67fafL } }, + /* 63 << 105 */ + { { 0xb1aadc634442449cL,0xe0e9921a33ad4fb8L,0x5c552313aa686d82L, + 0xdee635fa465d866cL }, + { 0xbc3c224a18ee6e8aL,0xeed748a6ed42e02fL,0xe70f930ad474cd08L, + 0x774ea6ecfff24adfL } }, + /* 64 << 105 */ + { { 0x03e2de1cf3480d4aL,0xf0d8edc7bc8acf1aL,0xf23e330368295a9cL, + 0xfadd5f68c546a97dL }, + { 0x895597ad96f8acb1L,0xbddd49d5671bdae2L,0x16fcd52821dd43f4L, + 0xa5a454126619141aL } }, + /* 0 << 112 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 112 */ + { { 0x8ce9b6bfc360e25aL,0xe6425195075a1a78L,0x9dc756a8481732f4L, + 0x83c0440f5432b57aL }, + { 0xc670b3f1d720281fL,0x2205910ed135e051L,0xded14b0edb052be7L, + 0x697b3d27c568ea39L } }, + /* 2 << 112 */ + { { 0x2e599b9afb3ff9edL,0x28c2e0ab17f6515cL,0x1cbee4fd474da449L, + 0x071279a44f364452L }, + { 0x97abff6601fbe855L,0x3ee394e85fda51c4L,0x190385f667597c0bL, + 0x6e9fccc6a27ee34bL } }, + /* 3 << 112 */ + { { 0x0b89de9314092ebbL,0xf17256bd428e240cL,0xcf89a7f393d2f064L, + 0x4f57841ee1ed3b14L }, + { 0x4ee14405e708d855L,0x856aae7203f1c3d0L,0xc8e5424fbdd7eed5L, + 0x3333e4ef73ab4270L } }, + /* 4 << 112 */ + { { 0x3bc77adedda492f8L,0xc11a3aea78297205L,0x5e89a3e734931b4cL, + 0x17512e2e9f5694bbL }, + { 0x5dc349f3177bf8b6L,0x232ea4ba08c7ff3eL,0x9c4f9d16f511145dL, + 0xccf109a333b379c3L } }, + /* 5 << 112 */ + { { 0xe75e7a88a1f25897L,0x7ac6961fa1b5d4d8L,0xe3e1077308f3ed5cL, + 0x208a54ec0a892dfbL }, + { 0xbe826e1978660710L,0x0cf70a97237df2c8L,0x418a7340ed704da5L, + 0xa3eeb9a908ca33fdL } }, + /* 6 << 112 */ + { { 0x49d96233169bca96L,0x04d286d42da6aafbL,0xc09606eca0c2fa94L, + 0x8869d0d523ff0fb3L }, + { 0xa99937e5d0150d65L,0xa92e2503240c14c9L,0x656bf945108e2d49L, + 0x152a733aa2f59e2bL } }, + /* 7 << 112 */ + { { 0xb4323d588434a920L,0xc0af8e93622103c5L,0x667518ef938dbf9aL, + 0xa184307383a9cdf2L }, + { 0x350a94aa5447ab80L,0xe5e5a325c75a3d61L,0x74ba507f68411a9eL, + 0x10581fc1594f70c5L } }, + /* 8 << 112 */ + { { 0x60e2857080eb24a9L,0x7bedfb4d488e0cfdL,0x721ebbd7c259cdb8L, + 0x0b0da855bc6390a9L }, + { 0x2b4d04dbde314c70L,0xcdbf1fbc6c32e846L,0x33833eabb162fc9eL, + 0x9939b48bb0dd3ab7L } }, + /* 9 << 112 */ + { { 0x5aaa98a7cb0c9c8cL,0x75105f3081c4375cL,0xceee50575ef1c90fL, + 0xb31e065fc23a17bfL }, + { 0x5364d275d4b6d45aL,0xd363f3ad62ec8996L,0xb5d212394391c65bL, + 0x84564765ebb41b47L } }, + /* 10 << 112 */ + { { 0x20d18ecc37107c78L,0xacff3b6b570c2a66L,0x22f975d99bd0d845L, + 0xef0a0c46ba178fa0L }, + { 0x1a41965176b6028eL,0xc49ec674248612d4L,0x5b6ac4f27338af55L, + 0x06145e627bee5a36L } }, + /* 11 << 112 */ + { { 0x33e95d07e75746b5L,0x1c1e1f6dc40c78beL,0x967833ef222ff8e2L, + 0x4bedcf6ab49180adL }, + { 0x6b37e9c13d7a4c8aL,0x2748887c6ddfe760L,0xf7055123aa3a5bbcL, + 0x954ff2257bbb8e74L } }, + /* 12 << 112 */ + { { 0xc42b8ab197c3dfb9L,0x55a549b0cf168154L,0xad6748e7c1b50692L, + 0x2775780f6fc5cbcbL }, + { 0x4eab80b8e1c9d7c8L,0x8c69dae13fdbcd56L,0x47e6b4fb9969eaceL, + 0x002f1085a705cb5aL } }, + /* 13 << 112 */ + { { 0x4e23ca446d3fea55L,0xb4ae9c86f4810568L,0x47bfb91b2a62f27dL, + 0x60deb4c9d9bac28cL }, + { 0xa892d8947de6c34cL,0x4ee682594494587dL,0x914ee14e1a3f8a5bL, + 0xbb113eaa28700385L } }, + /* 14 << 112 */ + { { 0x81ca03b92115b4c9L,0x7c163d388908cad1L,0xc912a118aa18179aL, + 0xe09ed750886e3081L }, + { 0xa676e3fa26f516caL,0x753cacf78e732f91L,0x51592aea833da8b4L, + 0xc626f42f4cbea8aaL } }, + /* 15 << 112 */ + { { 0xef9dc899a7b56eafL,0x00c0e52c34ef7316L,0x5b1e4e24fe818a86L, + 0x9d31e20dc538be47L }, + { 0x22eb932d3ed68974L,0xe44bbc087c4e87c4L,0x4121086e0dde9aefL, + 0x8e6b9cff134f4345L } }, + /* 16 << 112 */ + { { 0x96892c1f711b0eb9L,0xb905f2c8780ab954L,0xace26309a20792dbL, + 0xec8ac9b30684e126L }, + { 0x486ad8b6b40a2447L,0x60121fc19fe3fb24L,0x5626fccf1a8e3b3fL, + 0x4e5686226ad1f394L } }, + /* 17 << 112 */ + { { 0xda7aae0d196aa5a1L,0xe0df8c771041b5fbL,0x451465d926b318b7L, + 0xc29b6e557ab136e9L }, + { 0x2c2ab48b71148463L,0xb5738de364454a76L,0x54ccf9a05a03abe4L, + 0x377c02960427d58eL } }, + /* 18 << 112 */ + { { 0x73f5f0b92bb39c1fL,0x14373f2ce608d8c5L,0xdcbfd31400fbb805L, + 0xdf18fb2083afdcfbL }, + { 0x81a57f4242b3523fL,0xe958532d87f650fbL,0xaa8dc8b68b0a7d7cL, + 0x1b75dfb7150166beL } }, + /* 19 << 112 */ + { { 0x90e4f7c92d7d1413L,0x67e2d6b59834f597L,0x4fd4f4f9a808c3e8L, + 0xaf8237e0d5281ec1L }, + { 0x25ab5fdc84687ceeL,0xc5ded6b1a5b26c09L,0x8e4a5aecc8ea7650L, + 0x23b73e5c14cc417fL } }, + /* 20 << 112 */ + { { 0x2bfb43183037bf52L,0xb61e6db578c725d7L,0x8efd4060bbb3e5d7L, + 0x2e014701dbac488eL }, + { 0xac75cf9a360aa449L,0xb70cfd0579634d08L,0xa591536dfffb15efL, + 0xb2c37582d07c106cL } }, + /* 21 << 112 */ + { { 0xb4293fdcf50225f9L,0xc52e175cb0e12b03L,0xf649c3bad0a8bf64L, + 0x745a8fefeb8ae3c6L }, + { 0x30d7e5a358321bc3L,0xb1732be70bc4df48L,0x1f217993e9ea5058L, + 0xf7a71cde3e4fd745L } }, + /* 22 << 112 */ + { { 0x86cc533e894c5bbbL,0x6915c7d969d83082L,0xa6aa2d055815c244L, + 0xaeeee59249b22ce5L }, + { 0x89e39d1378135486L,0x3a275c1f16b76f2fL,0xdb6bcc1be036e8f5L, + 0x4df69b215e4709f5L } }, + /* 23 << 112 */ + { { 0xa188b2502d0f39aaL,0x622118bb15a85947L,0x2ebf520ffde0f4faL, + 0xa40e9f294860e539L }, + { 0x7b6a51eb22b57f0fL,0x849a33b97e80644aL,0x50e5d16f1cf095feL, + 0xd754b54eec55f002L } }, + /* 24 << 112 */ + { { 0x5cfbbb22236f4a98L,0x0b0c59e9066800bbL,0x4ac69a8f5a9a7774L, + 0x2b33f804d6bec948L }, + { 0xb372929532e6c466L,0x68956d0f4e599c73L,0xa47a249f155c31ccL, + 0x24d80f0de1ce284eL } }, + /* 25 << 112 */ + { { 0xcd821dfb988baf01L,0xe6331a7ddbb16647L,0x1eb8ad33094cb960L, + 0x593cca38c91bbca5L }, + { 0x384aac8d26567456L,0x40fa0309c04b6490L,0x97834cd6dab6c8f6L, + 0x68a7318d3f91e55fL } }, + /* 26 << 112 */ + { { 0xa00fd04efc4d3157L,0xb56f8ab22bf3bdeaL,0x014f56484fa57172L, + 0x948c5860450abdb3L }, + { 0x342b5df00ebd4f08L,0x3e5168cd0e82938eL,0x7aedc1ceb0df5dd0L, + 0x6bbbc6d9e5732516L } }, + /* 27 << 112 */ + { { 0xc7bfd486605daaa6L,0x46fd72b7bb9a6c9eL,0xe4847fb1a124fb89L, + 0x75959cbda2d8ffbcL }, + { 0x42579f65c8a588eeL,0x368c92e6b80b499dL,0xea4ef6cd999a5df1L, + 0xaa73bb7f936fe604L } }, + /* 28 << 112 */ + { { 0xf347a70d6457d188L,0x86eda86b8b7a388bL,0xb7cdff060ccd6013L, + 0xbeb1b6c7d0053fb2L }, + { 0x0b02238799240a9fL,0x1bbb384f776189b2L,0x8695e71e9066193aL, + 0x2eb5009706ffac7eL } }, + /* 29 << 112 */ + { { 0x0654a9c04a7d2caaL,0x6f3fb3d1a5aaa290L,0x835db041ff476e8fL, + 0x540b8b0bc42295e4L }, + { 0xa5c73ac905e214f5L,0x9a74075a56a0b638L,0x2e4b1090ce9e680bL, + 0x57a5b4796b8d9afaL } }, + /* 30 << 112 */ + { { 0x0dca48e726bfe65cL,0x097e391c7290c307L,0x683c462e6669e72eL, + 0xf505be1e062559acL }, + { 0x5fbe3ea1e3a3035aL,0x6431ebf69cd50da8L,0xfd169d5c1f6407f2L, + 0x8d838a9560fce6b8L } }, + /* 31 << 112 */ + { { 0x2a2bfa7f650006f0L,0xdfd7dad350c0fbb2L,0x92452495ccf9ad96L, + 0x183bf494d95635f9L }, + { 0x02d5df434a7bd989L,0x505385cca5431095L,0xdd98e67dfd43f53eL, + 0xd61e1a6c500c34a9L } }, + /* 32 << 112 */ + { { 0x5a4b46c64a8a3d62L,0x8469c4d0247743d2L,0x2bb3a13d88f7e433L, + 0x62b23a1001be5849L }, + { 0xe83596b4a63d1a4cL,0x454e7fea7d183f3eL,0x643fce6117afb01cL, + 0x4e65e5e61c4c3638L } }, + /* 33 << 112 */ + { { 0x41d85ea1ef74c45bL,0x2cfbfa66ae328506L,0x98b078f53ada7da9L, + 0xd985fe37ec752fbbL }, + { 0xeece68fe5a0148b4L,0x6f9a55c72d78136dL,0x232dccc4d2b729ceL, + 0xa27e0dfd90aafbc4L } }, + /* 34 << 112 */ + { { 0x9647445212b4603eL,0xa876c5516b706d14L,0xdf145fcf69a9d412L, + 0xe2ab75b72d479c34L }, + { 0x12df9a761a23ff97L,0xc61389925d359d10L,0x6e51c7aefa835f22L, + 0x69a79cb1c0fcc4d9L } }, + /* 35 << 112 */ + { { 0xf57f350d594cc7e1L,0x3079ca633350ab79L,0x226fb6149aff594aL, + 0x35afec026d59a62bL }, + { 0x9bee46f406ed2c6eL,0x58da17357d939a57L,0x44c504028fd1797eL, + 0xd8853e7c5ccea6caL } }, + /* 36 << 112 */ + { { 0x4065508da35fcd5fL,0x8965df8c495ccaebL,0x0f2da85012e1a962L, + 0xee471b94c1cf1cc4L }, + { 0xcef19bc80a08fb75L,0x704958f581de3591L,0x2867f8b23aef4f88L, + 0x8d749384ea9f9a5fL } }, + /* 37 << 112 */ + { { 0x1b3855378c9049f4L,0x5be948f37b92d8b6L,0xd96f725db6e2bd6bL, + 0x37a222bc958c454dL }, + { 0xe7c61abb8809bf61L,0x46f07fbc1346f18dL,0xfb567a7ae87c0d1cL, + 0x84a461c87ef3d07aL } }, + /* 38 << 112 */ + { { 0x0a5adce6d9278d98L,0x24d948139dfc73e1L,0x4f3528b6054321c3L, + 0x2e03fdde692ea706L }, + { 0x10e6061947b533c0L,0x1a8bc73f2ca3c055L,0xae58d4b21bb62b8fL, + 0xb2045a73584a24e3L } }, + /* 39 << 112 */ + { { 0x3ab3d5afbd76e195L,0x478dd1ad6938a810L,0x6ffab3936ee3d5cbL, + 0xdfb693db22b361e4L }, + { 0xf969449651dbf1a7L,0xcab4b4ef08a2e762L,0xe8c92f25d39bba9aL, + 0x850e61bcf1464d96L } }, + /* 40 << 112 */ + { { 0xb7e830e3dc09508bL,0xfaf6d2cf74317655L,0x72606cebdf690355L, + 0x48bb92b3d0c3ded6L }, + { 0x65b754845c7cf892L,0xf6cd7ac9d5d5f01fL,0xc2c30a5996401d69L, + 0x91268650ed921878L } }, + /* 41 << 112 */ + { { 0x380bf913b78c558fL,0x43c0baebc8afdaa9L,0x377f61d554f169d3L, + 0xf8da07e3ae5ff20bL }, + { 0xb676c49da8a90ea8L,0x81c1ff2b83a29b21L,0x383297ac2ad8d276L, + 0x3001122fba89f982L } }, + /* 42 << 112 */ + { { 0xe1d794be6718e448L,0x246c14827c3e6e13L,0x56646ef85d26b5efL, + 0x80f5091e88069cddL }, + { 0xc5992e2f724bdd38L,0x02e915b48471e8c7L,0x96ff320a0d0ff2a9L, + 0xbf8864874384d1a0L } }, + /* 43 << 112 */ + { { 0xbbe1e6a6c93f72d6L,0xd5f75d12cad800eaL,0xfa40a09fe7acf117L, + 0x32c8cdd57581a355L }, + { 0x742219927023c499L,0xa8afe5d738ec3901L,0x5691afcba90e83f0L, + 0x41bcaa030b8f8eacL } }, + /* 44 << 112 */ + { { 0xe38b5ff98d2668d5L,0x0715281a7ad81965L,0x1bc8fc7c03c6ce11L, + 0xcbbee6e28b650436L }, + { 0x06b00fe80cdb9808L,0x17d6e066fe3ed315L,0x2e9d38c64d0b5018L, + 0xab8bfd56844dcaefL } }, + /* 45 << 112 */ + { { 0x42894a59513aed8bL,0xf77f3b6d314bd07aL,0xbbdecb8f8e42b582L, + 0xf10e2fa8d2390fe6L }, + { 0xefb9502262a2f201L,0x4d59ea5050ee32b0L,0xd87f77286da789a8L, + 0xcf98a2cff79492c4L } }, + /* 46 << 112 */ + { { 0xf9577239720943c2L,0xba044cf53990b9d0L,0x5aa8e82395f2884aL, + 0x834de6ed0278a0afL }, + { 0xc8e1ee9a5f25bd12L,0x9259ceaa6f7ab271L,0x7e6d97a277d00b76L, + 0x5c0c6eeaa437832aL } }, + /* 47 << 112 */ + { { 0x5232c20f5606b81dL,0xabd7b3750d991ee5L,0x4d2bfe358632d951L, + 0x78f8514698ed9364L }, + { 0x951873f0f30c3282L,0x0da8ac80a789230bL,0x3ac7789c5398967fL, + 0xa69b8f7fbdda0fb5L } }, + /* 48 << 112 */ + { { 0xe5db77176add8545L,0x1b71cb6672c49b66L,0xd856073968421d77L, + 0x03840fe883e3afeaL }, + { 0xb391dad51ec69977L,0xae243fb9307f6726L,0xc88ac87be8ca160cL, + 0x5174cced4ce355f4L } }, + /* 49 << 112 */ + { { 0x98a35966e58ba37dL,0xfdcc8da27817335dL,0x5b75283083fbc7bfL, + 0x68e419d4d9c96984L }, + { 0x409a39f402a40380L,0x88940faf1fe977bcL,0xc640a94b8f8edea6L, + 0x1e22cd17ed11547dL } }, + /* 50 << 112 */ + { { 0xe28568ce59ffc3e2L,0x60aa1b55c1dee4e7L,0xc67497c8837cb363L, + 0x06fb438a105a2bf2L }, + { 0x30357ec4500d8e20L,0x1ad9095d0670db10L,0x7f589a05c73b7cfdL, + 0xf544607d880d6d28L } }, + /* 51 << 112 */ + { { 0x17ba93b1a20ef103L,0xad8591306ba6577bL,0x65c91cf66fa214a0L, + 0xd7d49c6c27990da5L }, + { 0xecd9ec8d20bb569dL,0xbd4b2502eeffbc33L,0x2056ca5a6bed0467L, + 0x7916a1f75b63728cL } }, + /* 52 << 112 */ + { { 0xd4f9497d53a4f566L,0x8973466497b56810L,0xf8e1da740494a621L, + 0x82546a938d011c68L }, + { 0x1f3acb19c61ac162L,0x52f8fa9cabad0d3eL,0x15356523b4b7ea43L, + 0x5a16ad61ae608125L } }, + /* 53 << 112 */ + { { 0xb0bcb87f4faed184L,0x5f236b1d5029f45fL,0xd42c76070bc6b1fcL, + 0xc644324e68aefce3L }, + { 0x8e191d595c5d8446L,0xc020807713ae1979L,0xadcaee553ba59cc7L, + 0x20ed6d6ba2cb81baL } }, + /* 54 << 112 */ + { { 0x0952ba19b6efcffcL,0x60f12d6897c0b87cL,0x4ee2c7c49caa30bcL, + 0x767238b797fbff4eL }, + { 0xebc73921501b5d92L,0x3279e3dfc2a37737L,0x9fc12bc86d197543L, + 0xfa94dc6f0a40db4eL } }, + /* 55 << 112 */ + { { 0x7392b41a530ccbbdL,0x87c82146ea823525L,0xa52f984c05d98d0cL, + 0x2ae57d735ef6974cL }, + { 0x9377f7bf3042a6ddL,0xb1a007c019647a64L,0xfaa9079a0cca9767L, + 0x3d81a25bf68f72d5L } }, + /* 56 << 112 */ + { { 0x752067f8ff81578eL,0x786221509045447dL,0xc0c22fcf0505aa6fL, + 0x1030f0a66bed1c77L }, + { 0x31f29f151f0bd739L,0x2d7989c7e6debe85L,0x5c070e728e677e98L, + 0x0a817bd306e81fd5L } }, + /* 57 << 112 */ + { { 0xc110d830b0f2ac95L,0x48d0995aab20e64eL,0x0f3e00e17729cd9aL, + 0x2a570c20dd556946L }, + { 0x912dbcfd4e86214dL,0x2d014ee2cf615498L,0x55e2b1e63530d76eL, + 0xc5135ae4fd0fd6d1L } }, + /* 58 << 112 */ + { { 0x0066273ad4f3049fL,0xbb8e9893e7087477L,0x2dba1ddb14c6e5fdL, + 0xdba3788651f57e6cL }, + { 0x5aaee0a65a72f2cfL,0x1208bfbf7bea5642L,0xf5c6aa3b67872c37L, + 0xd726e08343f93224L } }, + /* 59 << 112 */ + { { 0x1854daa5061f1658L,0xc0016df1df0cd2b3L,0xc2a3f23e833d50deL, + 0x73b681d2bbbd3017L }, + { 0x2f046dc43ac343c0L,0x9c847e7d85716421L,0xe1e13c910917eed4L, + 0x3fc9eebd63a1b9c6L } }, + /* 60 << 112 */ + { { 0x0f816a727fe02299L,0x6335ccc2294f3319L,0x3820179f4745c5beL, + 0xe647b782922f066eL }, + { 0xc22e49de02cafb8aL,0x299bc2fffcc2ecccL,0x9a8feea26e0e8282L, + 0xa627278bfe893205L } }, + /* 61 << 112 */ + { { 0xa7e197337933e47bL,0xf4ff6b132e766402L,0xa4d8be0a98440d9fL, + 0x658f5c2f38938808L }, + { 0x90b75677c95b3b3eL,0xfa0442693137b6ffL,0x077b039b43c47c29L, + 0xcca95dd38a6445b2L } }, + /* 62 << 112 */ + { { 0x0b498ba42333fc4cL,0x274f8e68f736a1b1L,0x6ca348fd5f1d4b2eL, + 0x24d3be78a8f10199L }, + { 0x8535f858ca14f530L,0xa6e7f1635b982e51L,0x847c851236e1bf62L, + 0xf6a7c58e03448418L } }, + /* 63 << 112 */ + { { 0x583f3703f9374ab6L,0x864f91956e564145L,0x33bc3f4822526d50L, + 0x9f323c801262a496L }, + { 0xaa97a7ae3f046a9aL,0x70da183edf8a039aL,0x5b68f71c52aa0ba6L, + 0x9be0fe5121459c2dL } }, + /* 64 << 112 */ + { { 0xc1e17eb6cbc613e5L,0x33131d55497ea61cL,0x2f69d39eaf7eded5L, + 0x73c2f434de6af11bL }, + { 0x4ca52493a4a375faL,0x5f06787cb833c5c2L,0x814e091f3e6e71cfL, + 0x76451f578b746666L } }, + /* 0 << 119 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 119 */ + { { 0x80f9bdef694db7e0L,0xedca8787b9fcddc6L,0x51981c3403b8dce1L, + 0x4274dcf170e10ba1L }, + { 0xf72743b86def6d1aL,0xd25b1670ebdb1866L,0xc4491e8c050c6f58L, + 0x2be2b2ab87fbd7f5L } }, + /* 2 << 119 */ + { { 0x3e0e5c9dd111f8ecL,0xbcc33f8db7c4e760L,0x702f9a91bd392a51L, + 0x7da4a795c132e92dL }, + { 0x1a0b0ae30bb1151bL,0x54febac802e32251L,0xea3a5082694e9e78L, + 0xe58ffec1e4fe40b8L } }, + /* 3 << 119 */ + { { 0xf85592fcd1e0cf9eL,0xdea75f0dc0e7b2e8L,0xc04215cfc135584eL, + 0x174fc7272f57092aL }, + { 0xe7277877eb930beaL,0x504caccb5eb02a5aL,0xf9fe08f7f5241b9bL, + 0xe7fb62f48d5ca954L } }, + /* 4 << 119 */ + { { 0xfbb8349d29c4120bL,0x9f94391fc0d0d915L,0xc4074fa75410ba51L, + 0xa66adbf6150a5911L }, + { 0xc164543c34bfca38L,0xe0f27560b9e1ccfcL,0x99da0f53e820219cL, + 0xe8234498c6b4997aL } }, + /* 5 << 119 */ + { { 0xcfb88b769d4c5423L,0x9e56eb10b0521c49L,0x418e0b5ebe8700a1L, + 0x00cbaad6f93cb58aL }, + { 0xe923fbded92a5e67L,0xca4979ac1f347f11L,0x89162d856bc0585bL, + 0xdd6254afac3c70e3L } }, + /* 6 << 119 */ + { { 0x7b23c513516e19e4L,0x56e2e847c5c4d593L,0x9f727d735ce71ef6L, + 0x5b6304a6f79a44c5L }, + { 0x6638a7363ab7e433L,0x1adea470fe742f83L,0xe054b8545b7fc19fL, + 0xf935381aba1d0698L } }, + /* 7 << 119 */ + { { 0x546eab2d799e9a74L,0x96239e0ea949f729L,0xca274c6b7090055aL, + 0x835142c39020c9b0L }, + { 0xa405667aa2e8807fL,0x29f2c0851aa3d39eL,0xcc555d6442fc72f5L, + 0xe856e0e7fbeacb3cL } }, + /* 8 << 119 */ + { { 0xb5504f9d918e4936L,0x65035ef6b2513982L,0x0553a0c26f4d9cb9L, + 0x6cb10d56bea85509L }, + { 0x48d957b7a242da11L,0x16a4d3dd672b7268L,0x3d7e637c8502a96bL, + 0x27c7032b730d463bL } }, + /* 9 << 119 */ + { { 0xbdc02b18e4136a14L,0xbacf969d678e32bfL,0xc98d89a3dd9c3c03L, + 0x7b92420a23becc4fL }, + { 0xd4b41f78c64d565cL,0x9f969d0010f28295L,0xec7f7f76b13d051aL, + 0x08945e1ea92da585L } }, + /* 10 << 119 */ + { { 0x55366b7d5846426fL,0xe7d09e89247d441dL,0x510b404d736fbf48L, + 0x7fa003d0e784bd7dL }, + { 0x25f7614f17fd9596L,0x49e0e0a135cb98dbL,0x2c65957b2e83a76aL, + 0x5d40da8dcddbe0f8L } }, + /* 11 << 119 */ + { { 0xf2b8c405050bad24L,0x8918426dc2aa4823L,0x2aeab3dda38365a7L, + 0x720317177c91b690L }, + { 0x8b00d69960a94120L,0x478a255de99eaeecL,0xbf656a5f6f60aafdL, + 0xdfd7cb755dee77b3L } }, + /* 12 << 119 */ + { { 0x37f68bb4a595939dL,0x0355647928740217L,0x8e740e7c84ad7612L, + 0xd89bc8439044695fL }, + { 0xf7f3da5d85a9184dL,0x562563bb9fc0b074L,0x06d2e6aaf88a888eL, + 0x612d8643161fbe7cL } }, + /* 13 << 119 */ + { { 0x465edba7f64085e7L,0xb230f30429aa8511L,0x53388426cda2d188L, + 0x908857354b666649L }, + { 0x6f02ff9a652f54f6L,0x65c822945fae2bf0L,0x7816ade062f5eee3L, + 0xdcdbdf43fcc56d70L } }, + /* 14 << 119 */ + { { 0x9fb3bba354530bb2L,0xbde3ef77cb0869eaL,0x89bc90460b431163L, + 0x4d03d7d2e4819a35L }, + { 0x33ae4f9e43b6a782L,0x216db3079c88a686L,0x91dd88e000ffedd9L, + 0xb280da9f12bd4840L } }, + /* 15 << 119 */ + { { 0x32a7cb8a1635e741L,0xfe14008a78be02a7L,0x3fafb3341b7ae030L, + 0x7fd508e75add0ce9L }, + { 0x72c83219d607ad51L,0x0f229c0a8d40964aL,0x1be2c3361c878da2L, + 0xe0c96742eab2ab86L } }, + /* 16 << 119 */ + { { 0x458f86913e538cd7L,0xa7001f6c8e08ad53L,0x52b8c6e6bf5d15ffL, + 0x548234a4011215ddL }, + { 0xff5a9d2d3d5b4045L,0xb0ffeeb64a904190L,0x55a3aca448607f8bL, + 0x8cbd665c30a0672aL } }, + /* 17 << 119 */ + { { 0x87f834e042583068L,0x02da2aebf3f6e683L,0x6b763e5d05c12248L, + 0x7230378f65a8aefcL }, + { 0x93bd80b571e8e5caL,0x53ab041cb3b62524L,0x1b8605136c9c552eL, + 0xe84d402cd5524e66L } }, + /* 18 << 119 */ + { { 0xa37f3573f37f5937L,0xeb0f6c7dd1e4fca5L,0x2965a554ac8ab0fcL, + 0x17fbf56c274676acL }, + { 0x2e2f6bd9acf7d720L,0x41fc8f8810224766L,0x517a14b385d53befL, + 0xdae327a57d76a7d1L } }, + /* 19 << 119 */ + { { 0x6ad0a065c4818267L,0x33aa189b37c1bbc1L,0x64970b5227392a92L, + 0x21699a1c2d1535eaL }, + { 0xcd20779cc2d7a7fdL,0xe318605999c83cf2L,0x9b69440b72c0b8c7L, + 0xa81497d77b9e0e4dL } }, + /* 20 << 119 */ + { { 0x515d5c891f5f82dcL,0x9a7f67d76361079eL,0xa8da81e311a35330L, + 0xe44990c44b18be1bL }, + { 0xc7d5ed95af103e59L,0xece8aba78dac9261L,0xbe82b0999394b8d3L, + 0x6830f09a16adfe83L } }, + /* 21 << 119 */ + { { 0x250a29b488172d01L,0x8b20bd65caff9e02L,0xb8a7661ee8a6329aL, + 0x4520304dd3fce920L }, + { 0xae45da1f2b47f7efL,0xe07f52885bffc540L,0xf79970093464f874L, + 0x2244c2cda6fa1f38L } }, + /* 22 << 119 */ + { { 0x43c41ac194d7d9b1L,0x5bafdd82c82e7f17L,0xdf0614c15fda0fcaL, + 0x74b043a7a8ae37adL }, + { 0x3ba6afa19e71734cL,0x15d5437e9c450f2eL,0x4a5883fe67e242b1L, + 0x5143bdc22c1953c2L } }, + /* 23 << 119 */ + { { 0x542b8b53fc5e8920L,0x363bf9a89a9cee08L,0x02375f10c3486e08L, + 0x2037543b8c5e70d2L }, + { 0x7109bccc625640b4L,0xcbc1051e8bc62c3bL,0xf8455fed803f26eaL, + 0x6badceabeb372424L } }, + /* 24 << 119 */ + { { 0xa2a9ce7c6b53f5f9L,0x642465951b176d99L,0xb1298d36b95c081bL, + 0x53505bb81d9a9ee6L }, + { 0x3f6f9e61f2ba70b0L,0xd07e16c98afad453L,0x9f1694bbe7eb4a6aL, + 0xdfebced93cb0bc8eL } }, + /* 25 << 119 */ + { { 0x92d3dcdc53868c8bL,0x174311a2386107a6L,0x4109e07c689b4e64L, + 0x30e4587f2df3dcb6L }, + { 0x841aea310811b3b2L,0x6144d41d0cce43eaL,0x464c45812a9a7803L, + 0xd03d371f3e158930L } }, + /* 26 << 119 */ + { { 0xc676d7f2b1f3390bL,0x9f7a1b8ca5b61272L,0x4ebebfc9c2e127a9L, + 0x4602500c5dd997bfL }, + { 0x7f09771c4711230fL,0x058eb37c020f09c1L,0xab693d4bfee5e38bL, + 0x9289eb1f4653cbc0L } }, + /* 27 << 119 */ + { { 0xbecf46abd51b9cf5L,0xd2aa9c029f0121afL,0x36aaf7d2e90dc274L, + 0x909e4ea048b95a3cL }, + { 0xe6b704966f32dbdbL,0x672188a08b030b3eL,0xeeffe5b3cfb617e2L, + 0x87e947de7c82709eL } }, + /* 28 << 119 */ + { { 0xa44d2b391770f5a7L,0xe4d4d7910e44eb82L,0x42e69d1e3f69712aL, + 0xbf11c4d6ac6a820eL }, + { 0xb5e7f3e542c4224cL,0xd6b4e81c449d941cL,0x5d72bd165450e878L, + 0x6a61e28aee25ac54L } }, + /* 29 << 119 */ + { { 0x33272094e6f1cd95L,0x7512f30d0d18673fL,0x32f7a4ca5afc1464L, + 0x2f0956566bbb977bL }, + { 0x586f47caa8226200L,0x02c868ad1ac07369L,0x4ef2b845c613acbeL, + 0x43d7563e0386054cL } }, + /* 30 << 119 */ + { { 0x54da9dc7ab952578L,0xb5423df226e84d0bL,0xa8b64eeb9b872042L, + 0xac2057825990f6dfL }, + { 0x4ff696eb21f4c77aL,0x1a79c3e4aab273afL,0x29bc922e9436b3f1L, + 0xff807ef8d6d9a27aL } }, + /* 31 << 119 */ + { { 0x82acea3d778f22a0L,0xfb10b2e85b5e7469L,0xc0b169802818ee7dL, + 0x011afff4c91c1a2fL }, + { 0x95a6d126ad124418L,0x31c081a5e72e295fL,0x36bb283af2f4db75L, + 0xd115540f7acef462L } }, + /* 32 << 119 */ + { { 0xc7f3a8f833f6746cL,0x21e46f65fea990caL,0x915fd5c5caddb0a9L, + 0xbd41f01678614555L }, + { 0x346f4434426ffb58L,0x8055943614dbc204L,0xf3dd20fe5a969b7fL, + 0x9d59e956e899a39aL } }, + /* 33 << 119 */ + { { 0xf1b0971c8ad4cf4bL,0x034488602ffb8fb8L,0xf071ac3c65340ba4L, + 0x408d0596b27fd758L }, + { 0xe7c78ea498c364b0L,0xa4aac4a5051e8ab5L,0xb9e1d560485d9002L, + 0x9acd518a88844455L } }, + /* 34 << 119 */ + { { 0xe4ca688fd06f56c0L,0xa48af70ddf027972L,0x691f0f045e9a609dL, + 0xa9dd82cdee61270eL }, + { 0x8903ca63a0ef18d3L,0x9fb7ee353d6ca3bdL,0xa7b4a09cabf47d03L, + 0x4cdada011c67de8eL } }, + /* 35 << 119 */ + { { 0x520037499355a244L,0xe77fd2b64f2151a9L,0x695d6cf666b4efcbL, + 0xc5a0cacfda2cfe25L }, + { 0x104efe5cef811865L,0xf52813e89ea5cc3dL,0x855683dc40b58dbcL, + 0x0338ecde175fcb11L } }, + /* 36 << 119 */ + { { 0xf9a0563774921592L,0xb4f1261db9bb9d31L,0x551429b74e9c5459L, + 0xbe182e6f6ea71f53L }, + { 0xd3a3b07cdfc50573L,0x9ba1afda62be8d44L,0x9bcfd2cb52ab65d3L, + 0xdf11d547a9571802L } }, + /* 37 << 119 */ + { { 0x099403ee02a2404aL,0x497406f421088a71L,0x994794095004ae71L, + 0xbdb42078a812c362L }, + { 0x2b72a30fd8828442L,0x283add27fcb5ed1cL,0xf7c0e20066a40015L, + 0x3e3be64108b295efL } }, + /* 38 << 119 */ + { { 0xac127dc1e038a675L,0x729deff38c5c6320L,0xb7df8fd4a90d2c53L, + 0x9b74b0ec681e7cd3L }, + { 0x5cb5a623dab407e5L,0xcdbd361576b340c6L,0xa184415a7d28392cL, + 0xc184c1d8e96f7830L } }, + /* 39 << 119 */ + { { 0xc3204f1981d3a80fL,0xfde0c841c8e02432L,0x78203b3e8149e0c1L, + 0x5904bdbb08053a73L }, + { 0x30fc1dd1101b6805L,0x43c223bc49aa6d49L,0x9ed671417a174087L, + 0x311469a0d5997008L } }, + /* 40 << 119 */ + { { 0xb189b6845e43fc61L,0xf3282375e0d3ab57L,0x4fa34b67b1181da8L, + 0x621ed0b299ee52b8L }, + { 0x9b178de1ad990676L,0xd51de67b56d54065L,0x2a2c27c47538c201L, + 0x33856ec838a40f5cL } }, + /* 41 << 119 */ + { { 0x2522fc15be6cdcdeL,0x1e603f339f0c6f89L,0x7994edc3103e30a6L, + 0x033a00db220c853eL }, + { 0xd3cfa409f7bb7fd7L,0x70f8781e462d18f6L,0xbbd82980687fe295L, + 0x6eef4c32595669f3L } }, + /* 42 << 119 */ + { { 0x86a9303b2f7e85c3L,0x5fce462171988f9bL,0x5b935bf6c138acb5L, + 0x30ea7d6725661212L }, + { 0xef1eb5f4e51ab9a2L,0x0587c98aae067c78L,0xb3ce1b3c77ca9ca6L, + 0x2a553d4d54b5f057L } }, + /* 43 << 119 */ + { { 0xc78982364da29ec2L,0xdbdd5d13b9c57316L,0xc57d6e6b2cd80d47L, + 0x80b460cffe9e7391L }, + { 0x98648cabf963c31eL,0x67f9f633cc4d32fdL,0x0af42a9dfdf7c687L, + 0x55f292a30b015ea7L } }, + /* 44 << 119 */ + { { 0x89e468b2cd21ab3dL,0xe504f022c393d392L,0xab21e1d4a5013af9L, + 0xe3283f78c2c28acbL }, + { 0xf38b35f6226bf99fL,0xe83542740e291e69L,0x61673a15b20c162dL, + 0xc101dc75b04fbdbeL } }, + /* 45 << 119 */ + { { 0x8323b4c2255bd617L,0x6c9696936c2a9154L,0xc6e6586062679387L, + 0x8e01db0cb8c88e23L }, + { 0x33c42873893a5559L,0x7630f04b47a3e149L,0xb5d80805ddcf35f8L, + 0x582ca08077dfe732L } }, + /* 46 << 119 */ + { { 0x2c7156e10b1894a0L,0x92034001d81c68c0L,0xed225d00c8b115b5L, + 0x237f9c2283b907f2L }, + { 0x0ea2f32f4470e2c0L,0xb725f7c158be4e95L,0x0f1dcafab1ae5463L, + 0x59ed51871ba2fc04L } }, + /* 47 << 119 */ + { { 0xf6e0f316d0115d4dL,0x5180b12fd3691599L,0x157e32c9527f0a41L, + 0x7b0b081da8e0ecc0L }, + { 0x6dbaaa8abf4f0dd0L,0x99b289c74d252696L,0x79b7755edbf864feL, + 0x6974e2b176cad3abL } }, + /* 48 << 119 */ + { { 0x35dbbee206ddd657L,0xe7cbdd112ff3a96dL,0x88381968076be758L, + 0x2d737e7208c91f5dL }, + { 0x5f83ab6286ec3776L,0x98aa649d945fa7a1L,0xf477ec3772ef0933L, + 0x66f52b1e098c17b1L } }, + /* 49 << 119 */ + { { 0x9eec58fbd803738bL,0x91aaade7e4e86aa4L,0x6b1ae617a5b51492L, + 0x63272121bbc45974L }, + { 0x7e0e28f0862c5129L,0x0a8f79a93321a4a0L,0xe26d16645041c88fL, + 0x0571b80553233e3aL } }, + /* 50 << 119 */ + { { 0xd1b0ccdec9520711L,0x55a9e4ed3c8b84bfL,0x9426bd39a1fef314L, + 0x4f5f638e6eb93f2bL }, + { 0xba2a1ed32bf9341bL,0xd63c13214d42d5a9L,0xd2964a89316dc7c5L, + 0xd1759606ca511851L } }, + /* 51 << 119 */ + { { 0xd8a9201ff9e6ed35L,0xb7b5ee456736925aL,0x0a83fbbc99581af7L, + 0x3076bc4064eeb051L }, + { 0x5511c98c02dec312L,0x270de898238dcb78L,0x2cf4cf9c539c08c9L, + 0xa70cb65e38d3b06eL } }, + /* 52 << 119 */ + { { 0xb12ec10ecfe57bbdL,0x82c7b65635a0c2b5L,0xddc7d5cd161c67bdL, + 0xe32e8985ae3a32ccL }, + { 0x7aba9444d11a5529L,0xe964ed022427fa1aL,0x1528392d24a1770aL, + 0xa152ce2c12c72fcdL } }, + /* 53 << 119 */ + { { 0x714553a48ec07649L,0x18b4c290459dd453L,0xea32b7147b64b110L, + 0xb871bfa52e6f07a2L }, + { 0xb67112e59e2e3c9bL,0xfbf250e544aa90f6L,0xf77aedb8bd539006L, + 0x3b0cdf9ad172a66fL } }, + /* 54 << 119 */ + { { 0xedf69feaf8c51187L,0x05bb67ec741e4da7L,0x47df0f3208114345L, + 0x56facb07bb9792b1L }, + { 0xf3e007e98f6229e4L,0x62d103f4526fba0fL,0x4f33bef7b0339d79L, + 0x9841357bb59bfec1L } }, + /* 55 << 119 */ + { { 0xfa8dbb59c34e6705L,0xc3c7180b7fdaa84cL,0xf95872fca4108537L, + 0x8750cc3b932a3e5aL }, + { 0xb61cc69db7275d7dL,0xffa0168b2e59b2e9L,0xca032abc6ecbb493L, + 0x1d86dbd32c9082d8L } }, + /* 56 << 119 */ + { { 0xae1e0b67e28ef5baL,0x2c9a4699cb18e169L,0x0ecd0e331e6bbd20L, + 0x571b360eaf5e81d2L }, + { 0xcd9fea58101c1d45L,0x6651788e18880452L,0xa99726351f8dd446L, + 0x44bed022e37281d0L } }, + /* 57 << 119 */ + { { 0x094b2b2d33da525dL,0xf193678e13144fd8L,0xb8ab5ba4f4c1061dL, + 0x4343b5fadccbe0f4L }, + { 0xa870237163812713L,0x47bf6d2df7611d93L,0x46729b8cbd21e1d7L, + 0x7484d4e0d629e77dL } }, + /* 58 << 119 */ + { { 0x830e6eea60dbac1fL,0x23d8c484da06a2f7L,0x896714b050ca535bL, + 0xdc8d3644ebd97a9bL }, + { 0x106ef9fab12177b4L,0xf79bf464534d5d9cL,0x2537a349a6ab360bL, + 0xc7c54253a00c744fL } }, + /* 59 << 119 */ + { { 0xb3c7a047e5911a76L,0x61ffa5c8647f1ee7L,0x15aed36f8f56ab42L, + 0x6a0d41b0a3ff9ac9L }, + { 0x68f469f5cc30d357L,0xbe9adf816b72be96L,0x1cd926fe903ad461L, + 0x7e89e38fcaca441bL } }, + /* 60 << 119 */ + { { 0xf0f82de5facf69d4L,0x363b7e764775344cL,0x6894f312b2e36d04L, + 0x3c6cb4fe11d1c9a5L }, + { 0x85d9c3394008e1f2L,0x5e9a85ea249f326cL,0xdc35c60a678c5e06L, + 0xc08b944f9f86fba9L } }, + /* 61 << 119 */ + { { 0xde40c02c89f71f0fL,0xad8f3e31ff3da3c0L,0x3ea5096b42125dedL, + 0x13879cbfa7379183L }, + { 0x6f4714a56b306a0bL,0x359c2ea667646c5eL,0xfacf894307726368L, + 0x07a5893565ff431eL } }, + /* 62 << 119 */ + { { 0x24d661d168754ab0L,0x801fce1d6f429a76L,0xc068a85fa58ce769L, + 0xedc35c545d5eca2bL }, + { 0xea31276fa3f660d1L,0xa0184ebeb8fc7167L,0x0f20f21a1d8db0aeL, + 0xd96d095f56c35e12L } }, + /* 63 << 119 */ + { { 0xedf402b5f8c2a25bL,0x1bb772b9059204b6L,0x50cbeae219b4e34cL, + 0x93109d803fa0845aL }, + { 0x54f7ccf78ef59fb5L,0x3b438fe288070963L,0x9e28c65931f3ba9bL, + 0x9cc31b46ead9da92L } }, + /* 64 << 119 */ + { { 0x3c2f0ba9b733aa5fL,0xdece47cbf05af235L,0xf8e3f715a2ac82a5L, + 0xc97ba6412203f18aL }, + { 0xc3af550409c11060L,0x56ea2c0546af512dL,0xfac28daff3f28146L, + 0x87fab43a959ef494L } }, + /* 0 << 126 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 126 */ + { { 0x09891641d4c5105fL,0x1ae80f8e6d7fbd65L,0x9d67225fbee6bdb0L, + 0x3b433b597fc4d860L }, + { 0x44e66db693e85638L,0xf7b59252e3e9862fL,0xdb785157665c32ecL, + 0x702fefd7ae362f50L } }, + /* 2 << 126 */ + { { 0x3754475d0fefb0c3L,0xd48fb56b46d7c35dL,0xa070b633363798a4L, + 0xae89f3d28fdb98e6L }, + { 0x970b89c86363d14cL,0x8981752167abd27dL,0x9bf7d47444d5a021L, + 0xb3083bafcac72aeeL } }, + /* 3 << 126 */ + { { 0x389741debe949a44L,0x638e9388546a4fa5L,0x3fe6419ca0047bdcL, + 0x7047f648aaea57caL }, + { 0x54e48a9041fbab17L,0xda8e0b28576bdba2L,0xe807eebcc72afddcL, + 0x07d3336df42577bfL } }, + /* 4 << 126 */ + { { 0x62a8c244bfe20925L,0x91c19ac38fdce867L,0x5a96a5d5dd387063L, + 0x61d587d421d324f6L }, + { 0xe87673a2a37173eaL,0x2384800853778b65L,0x10f8441e05bab43eL, + 0xfa11fe124621efbeL } }, + /* 5 << 126 */ + { { 0x047b772e81685d7bL,0x23f27d81bf34a976L,0xc27608e2915f48efL, + 0x3b0b43faa521d5c3L }, + { 0x7613fb2663ca7284L,0x7f5729b41d4db837L,0x87b14898583b526bL, + 0x00b732a6bbadd3d1L } }, + /* 6 << 126 */ + { { 0x8e02f4262048e396L,0x436b50b6383d9de4L,0xf78d3481471e85adL, + 0x8b01ea6ad005c8d6L }, + { 0xd3c7afee97015c07L,0x46cdf1a94e3ba2aeL,0x7a42e50183d3a1d2L, + 0xd54b5268b541dff4L } }, + /* 7 << 126 */ + { { 0x3f24cf304e23e9bcL,0x4387f816126e3624L,0x26a46a033b0b6d61L, + 0xaf1bc8458b2d777cL }, + { 0x25c401ba527de79cL,0x0e1346d44261bbb6L,0x4b96c44b287b4bc7L, + 0x658493c75254562fL } }, + /* 8 << 126 */ + { { 0x23f949feb8a24a20L,0x17ebfed1f52ca53fL,0x9b691bbebcfb4853L, + 0x5617ff6b6278a05dL }, + { 0x241b34c5e3c99ebdL,0xfc64242e1784156aL,0x4206482f695d67dfL, + 0xb967ce0eee27c011L } }, + /* 9 << 126 */ + { { 0x65db375121c80b5dL,0x2e7a563ca31ecca0L,0xe56ffc4e5238a07eL, + 0x3d6c296632ced854L }, + { 0xe99d7d1aaf70b885L,0xafc3bad92d686459L,0x9c78bf460cc8ba5bL, + 0x5a43951918955aa3L } }, + /* 10 << 126 */ + { { 0xf8b517a85fe4e314L,0xe60234d0fcb8906fL,0xffe542acf2061b23L, + 0x287e191f6b4cb59cL }, + { 0x21857ddc09d877d8L,0x1c23478c14678941L,0xbbf0c056b6e05ea4L, + 0x82da4b53b01594feL } }, + /* 11 << 126 */ + { { 0xf7526791fadb8608L,0x049e832d7b74cdf6L,0xa43581ccc2b90a34L, + 0x73639eb89360b10cL }, + { 0x4fba331fe1e4a71bL,0x6ffd6b938072f919L,0x6e53271c65679032L, + 0x67206444f14272ceL } }, + /* 12 << 126 */ + { { 0xc0f734a3b2335834L,0x9526205a90ef6860L,0xcb8be71704e2bb0dL, + 0x2418871e02f383faL }, + { 0xd71776814082c157L,0xcc914ad029c20073L,0xf186c1ebe587e728L, + 0x6fdb3c2261bcd5fdL } }, + /* 13 << 126 */ + { { 0x30d014a6f2f9f8e9L,0x963ece234fec49d2L,0x862025c59605a8d9L, + 0x3987444519f8929aL }, + { 0x01b6ff6512bf476aL,0x598a64d809cf7d91L,0xd7ec774993be56caL, + 0x10899785cbb33615L } }, + /* 14 << 126 */ + { { 0xb8a092fd02eee3adL,0xa86b3d3530145270L,0x323d98c68512b675L, + 0x4b8bc78562ebb40fL }, + { 0x7d301f54413f9cdeL,0xa5e4fb4f2bab5664L,0x1d2b252d1cbfec23L, + 0xfcd576bbe177120dL } }, + /* 15 << 126 */ + { { 0x04427d3e83731a34L,0x2bb9028eed836e8eL,0xb36acff8b612ca7cL, + 0xb88fe5efd3d9c73aL }, + { 0xbe2a6bc6edea4eb3L,0x43b93133488eec77L,0xf41ff566b17106e1L, + 0x469e9172654efa32L } }, + /* 16 << 126 */ + { { 0xb4480f0441c23fa3L,0xb4712eb0c1989a2eL,0x3ccbba0f93a29ca7L, + 0x6e205c14d619428cL }, + { 0x90db7957b3641686L,0x0432691d45ac8b4eL,0x07a759acf64e0350L, + 0x0514d89c9c972517L } }, + /* 17 << 126 */ + { { 0x1701147fa8e67fc3L,0x9e2e0b8bab2085beL,0xd5651824ac284e57L, + 0x890d432574893664L }, + { 0x8a7c5e6ec55e68a3L,0xbf12e90b4339c85aL,0x31846b85f922b655L, + 0x9a54ce4d0bf4d700L } }, + /* 18 << 126 */ + { { 0xd7f4e83af1a14295L,0x916f955cb285d4f9L,0xe57bb0e099ffdabaL, + 0x28a43034eab0d152L }, + { 0x0a36ffa2b8a9cef8L,0x5517407eb9ec051aL,0x9c796096ea68e672L, + 0x853db5fbfb3c77fbL } }, + /* 19 << 126 */ + { { 0x21474ba9e864a51aL,0x6c2676996e8a1b8bL,0x7c82362694120a28L, + 0xe61e9a488383a5dbL }, + { 0x7dd750039f84216dL,0xab020d07ad43cd85L,0x9437ae48da12c659L, + 0x6449c2ebe65452adL } }, + /* 20 << 126 */ + { { 0xcc7c4c1c2cf9d7c1L,0x1320886aee95e5abL,0xbb7b9056beae170cL, + 0xc8a5b250dbc0d662L }, + { 0x4ed81432c11d2303L,0x7da669121f03769fL,0x3ac7a5fd84539828L, + 0x14dada943bccdd02L } }, + /* 21 << 126 */ + { { 0x8b84c3217ef6b0d1L,0x52a9477a7c933f22L,0x5ef6728afd440b82L, + 0x5c3bd8596ce4bd5eL }, + { 0x918b80f5f22c2d3eL,0x368d5040b7bb6cc5L,0xb66142a12695a11cL, + 0x60ac583aeb19ea70L } }, + /* 22 << 126 */ + { { 0x317cbb980eab2437L,0x8cc08c555e2654c8L,0xfe2d6520e6d8307fL, + 0xe9f147f357428993L }, + { 0x5f9c7d14d2fd6cf1L,0xa3ecd0642d4fcbb0L,0xad83fef08e7341f7L, + 0x643f23a03a63115cL } }, + /* 23 << 126 */ + { { 0xd38a78abe65ab743L,0xbf7c75b135edc89cL,0x3dd8752e530df568L, + 0xf85c4a76e308c682L }, + { 0x4c9955b2e68acf37L,0xa544df3dab32af85L,0x4b8ec3f5a25cf493L, + 0x4d8f27641a622febL } }, + /* 24 << 126 */ + { { 0x7bb4f7aaf0dcbc49L,0x7de551f970bbb45bL,0xcfd0f3e49f2ca2e5L, + 0xece587091f5c76efL }, + { 0x32920edd167d79aeL,0x039df8a2fa7d7ec1L,0xf46206c0bb30af91L, + 0x1ff5e2f522676b59L } }, + /* 25 << 126 */ + { { 0x11f4a0396ea51d66L,0x506c1445807d7a26L,0x60da5705755a9b24L, + 0x8fc8cc321f1a319eL }, + { 0x83642d4d9433d67dL,0x7fa5cb8f6a7dd296L,0x576591db9b7bde07L, + 0x13173d25419716fbL } }, + /* 26 << 126 */ + { { 0xea30599dd5b340ffL,0xfc6b5297b0fe76c5L,0x1c6968c8ab8f5adcL, + 0xf723c7f5901c928dL }, + { 0x4203c3219773d402L,0xdf7c6aa31b51dd47L,0x3d49e37a552be23cL, + 0x57febee80b5a6e87L } }, + /* 27 << 126 */ + { { 0xc5ecbee47bd8e739L,0x79d44994ae63bf75L,0x168bd00f38fb8923L, + 0x75d48ee4d0533130L }, + { 0x554f77aadb5cdf33L,0x3396e8963c696769L,0x2fdddbf2d3fd674eL, + 0xbbb8f6ee99d0e3e5L } }, + /* 28 << 126 */ + { { 0x51b90651cbae2f70L,0xefc4bc0593aaa8ebL,0x8ecd8689dd1df499L, + 0x1aee99a822f367a5L }, + { 0x95d485b9ae8274c5L,0x6c14d4457d30b39cL,0xbafea90bbcc1ef81L, + 0x7c5f317aa459a2edL } }, + /* 29 << 126 */ + { { 0x012110754ef44227L,0xa17bed6edc20f496L,0x0cdfe424819853cdL, + 0x13793298f71e2ce7L }, + { 0x3c1f3078dbbe307bL,0x6dd1c20e76ee9936L,0x23ee4b57423caa20L, + 0x4ac3793b8efb840eL } }, + /* 30 << 126 */ + { { 0x934438ebed1f8ca0L,0x3e5466584ebb25a2L,0xc415af0ec069896fL, + 0xc13eddb09a5aa43dL }, + { 0x7a04204fd49eb8f6L,0xd0d5bdfcd74f1670L,0x3697e28656fc0558L, + 0x1020737101cebadeL } }, + /* 31 << 126 */ + { { 0x5f87e6900647a82bL,0x908e0ed48f40054fL,0xa9f633d479853803L, + 0x8ed13c9a4a28b252L }, + { 0x3e2ef6761f460f64L,0x53930b9b36d06336L,0x347073ac8fc4979bL, + 0x84380e0e5ecd5597L } }, + /* 32 << 126 */ + { { 0xe3b22c6bc4fe3c39L,0xba4a81536c7bebdfL,0xf23ab6b725693459L, + 0x53bc377014922b11L }, + { 0x4645c8ab5afc60dbL,0xaa02235520b9f2a3L,0x52a2954cce0fc507L, + 0x8c2731bb7ce1c2e7L } }, + /* 33 << 126 */ + { { 0xf39608ab18a0339dL,0xac7a658d3735436cL,0xb22c2b07cd992b4fL, + 0x4e83daecf40dcfd4L }, + { 0x8a34c7be2f39ea3eL,0xef0c005fb0a56d2eL,0x62731f6a6edd8038L, + 0x5721d7404e3cb075L } }, + /* 34 << 126 */ + { { 0x1ea41511fbeeee1bL,0xd1ef5e73ef1d0c05L,0x42feefd173c07d35L, + 0xe530a00a8a329493L }, + { 0x5d55b7fef15ebfb0L,0x549de03cd322491aL,0xf7b5f602745b3237L, + 0x3632a3a21ab6e2b6L } }, + /* 35 << 126 */ + { { 0x0d3bba890ef59f78L,0x0dfc6443c9e52b9aL,0x1dc7969972631447L, + 0xef033917b3be20b1L }, + { 0x0c92735db1383948L,0xc1fc29a2c0dd7d7dL,0x6485b697403ed068L, + 0x13bfaab3aac93bdcL } }, + /* 36 << 126 */ + { { 0x410dc6a90deeaf52L,0xb003fb024c641c15L,0x1384978c5bc504c4L, + 0x37640487864a6a77L }, + { 0x05991bc6222a77daL,0x62260a575e47eb11L,0xc7af6613f21b432cL, + 0x22f3acc9ab4953e9L } }, + /* 37 << 126 */ + { { 0x529349228e41d155L,0x4d0245683ac059efL,0xb02017554d884411L, + 0xce8055cfa59a178fL }, + { 0xcd77d1aff6204549L,0xa0a00a3ec7066759L,0x471071ef0272c229L, + 0x009bcf6bd3c4b6b0L } }, + /* 38 << 126 */ + { { 0x2a2638a822305177L,0xd51d59df41645bbfL,0xa81142fdc0a7a3c0L, + 0xa17eca6d4c7063eeL }, + { 0x0bb887ed60d9dcecL,0xd6d28e5120ad2455L,0xebed6308a67102baL, + 0x042c31148bffa408L } }, + /* 39 << 126 */ + { { 0xfd099ac58aa68e30L,0x7a6a3d7c1483513eL,0xffcc6b75ba2d8f0cL, + 0x54dacf961e78b954L }, + { 0xf645696fa4a9af89L,0x3a41194006ac98ecL,0x41b8b3f622a67a20L, + 0x2d0b1e0f99dec626L } }, + /* 40 << 126 */ + { { 0x27c8919240be34e8L,0xc7162b3791907f35L,0x90188ec1a956702bL, + 0xca132f7ddf93769cL }, + { 0x3ece44f90e2025b4L,0x67aaec690c62f14cL,0xad74141822e3cc11L, + 0xcf9b75c37ff9a50eL } }, + /* 41 << 126 */ + { { 0x02fa2b164d348272L,0xbd99d61a9959d56dL,0xbc4f19db18762916L, + 0xcc7cce5049c1ac80L }, + { 0x4d59ebaad846bd83L,0x8775a9dca9202849L,0x07ec4ae16e1f4ca9L, + 0x27eb5875ba893f11L } }, + /* 42 << 126 */ + { { 0x00284d51662cc565L,0x82353a6b0db4138dL,0xd9c7aaaaaa32a594L, + 0xf5528b5ea5669c47L }, + { 0xf32202312f23c5ffL,0xe3e8147a6affa3a1L,0xfb423d5c202ddda0L, + 0x3d6414ac6b871bd4L } }, + /* 43 << 126 */ + { { 0x586f82e1a51a168aL,0xb712c67148ae5448L,0x9a2e4bd176233eb8L, + 0x0188223a78811ca9L }, + { 0x553c5e21f7c18de1L,0x7682e451b27bb286L,0x3ed036b30e51e929L, + 0xf487211bec9cb34fL } }, + /* 44 << 126 */ + { { 0x0d0942770c24efc8L,0x0349fd04bef737a4L,0x6d1c9dd2514cdd28L, + 0x29c135ff30da9521L }, + { 0xea6e4508f78b0b6fL,0x176f5dd2678c143cL,0x081484184be21e65L, + 0x27f7525ce7df38c4L } }, + /* 45 << 126 */ + { { 0x1fb70e09748ab1a4L,0x9cba50a05efe4433L,0x7846c7a615f75af2L, + 0x2a7c2c575ee73ea8L }, + { 0x42e566a43f0a449aL,0x45474c3bad90fc3dL,0x7447be3d8b61d057L, + 0x3e9d1cf13a4ec092L } }, + /* 46 << 126 */ + { { 0x1603e453f380a6e6L,0x0b86e4319b1437c2L,0x7a4173f2ef29610aL, + 0x8fa729a7f03d57f7L }, + { 0x3e186f6e6c9c217eL,0xbe1d307991919524L,0x92a62a70153d4fb1L, + 0x32ed3e34d68c2f71L } }, + /* 47 << 126 */ + { { 0xd785027f9eb1a8b7L,0xbc37eb77c5b22fe8L,0x466b34f0b9d6a191L, + 0x008a89af9a05f816L }, + { 0x19b028fb7d42c10aL,0x7fe8c92f49b3f6b8L,0x58907cc0a5a0ade3L, + 0xb3154f51559d1a7cL } }, + /* 48 << 126 */ + { { 0x5066efb6d9790ed6L,0xa77a0cbca6aa793bL,0x1a915f3c223e042eL, + 0x1c5def0469c5874bL }, + { 0x0e83007873b6c1daL,0x55cf85d2fcd8557aL,0x0f7c7c760460f3b1L, + 0x87052acb46e58063L } }, + /* 49 << 126 */ + { { 0x09212b80907eae66L,0x3cb068e04d721c89L,0xa87941aedd45ac1cL, + 0xde8d5c0d0daa0dbbL }, + { 0xda421fdce3502e6eL,0xc89442014d89a084L,0x7307ba5ef0c24bfbL, + 0xda212beb20bde0efL } }, + /* 50 << 126 */ + { { 0xea2da24bf82ce682L,0x058d381607f71fe4L,0x35a024625ffad8deL, + 0xcd7b05dcaadcefabL }, + { 0xd442f8ed1d9f54ecL,0x8be3d618b2d3b5caL,0xe2220ed0e06b2ce2L, + 0x82699a5f1b0da4c0L } }, + /* 51 << 126 */ + { { 0x3ff106f571c0c3a7L,0x8f580f5a0d34180cL,0x4ebb120e22d7d375L, + 0x5e5782cce9513675L }, + { 0x2275580c99c82a70L,0xe8359fbf15ea8c4cL,0x53b48db87b415e70L, + 0xaacf2240100c6014L } }, + /* 52 << 126 */ + { { 0x9faaccf5e4652f1dL,0xbd6fdd2ad56157b2L,0xa4f4fb1f6261ec50L, + 0x244e55ad476bcd52L }, + { 0x881c9305047d320bL,0x1ca983d56181263fL,0x354e9a44278fb8eeL, + 0xad2dbc0f396e4964L } }, + /* 53 << 126 */ + { { 0x723f3aa29268b3deL,0x0d1ca29ae6e0609aL,0x794866aa6cf44252L, + 0x0b59f3e301af87edL }, + { 0xe234e5ff7f4a6c51L,0xa8768fd261dc2f7eL,0xdafc73320a94d81fL, + 0xd7f8428206938ce1L } }, + /* 54 << 126 */ + { { 0xae0b3c0e0546063eL,0x7fbadcb25d61abc6L,0xd5d7a2c9369ac400L, + 0xa5978d09ae67d10cL }, + { 0x290f211e4f85eaacL,0xe61e2ad1facac681L,0xae125225388384cdL, + 0xa7fb68e9ccfde30fL } }, + /* 55 << 126 */ + { { 0x7a59b9363daed4c2L,0x80a9aa402606f789L,0xb40c1ea5f6a6d90aL, + 0x948364d3514d5885L }, + { 0x062ebc6070985182L,0xa6db5b0e33310895L,0x64a12175e329c2f5L, + 0xc5f25bd290ea237eL } }, + /* 56 << 126 */ + { { 0x7915c5242d0a4c23L,0xeb5d26e46bb3cc52L,0x369a9116c09e2c92L, + 0x0c527f92cf182cf8L }, + { 0x9e5919382aede0acL,0xb29222086cc34939L,0x3c9d896299a34361L, + 0x3c81836dc1905fe6L } }, + /* 57 << 126 */ + { { 0x4bfeb57fa001ec5aL,0xe993f5bba0dc5dbaL,0x47884109724a1380L, + 0x8a0369ab32fe9a04L }, + { 0xea068d608c927db8L,0xbf5f37cf94655741L,0x47d402a204b6c7eaL, + 0x4551c2956af259cbL } }, + /* 58 << 126 */ + { { 0x698b71e7ed77ee8bL,0xbddf7bd0f309d5c7L,0x6201c22c34e780caL, + 0xab04f7d84c295ef4L }, + { 0x1c9472944313a8ceL,0xe532e4ac92ca4cfeL,0x89738f80d0a7a97aL, + 0xec088c88a580fd5bL } }, + /* 59 << 126 */ + { { 0x612b1ecc42ce9e51L,0x8f9840fdb25fdd2aL,0x3cda78c001e7f839L, + 0x546b3d3aece05480L }, + { 0x271719a980d30916L,0x45497107584c20c4L,0xaf8f94785bc78608L, + 0x28c7d484277e2a4cL } }, + /* 60 << 126 */ + { { 0xfce0176788a2ffe4L,0xdc506a3528e169a5L,0x0ea108617af9c93aL, + 0x1ed2436103fa0e08L }, + { 0x96eaaa92a3d694e7L,0xc0f43b4def50bc74L,0xce6aa58c64114db4L, + 0x8218e8ea7c000fd4L } }, + /* 61 << 126 */ + { { 0xac815dfb185f8844L,0xcd7e90cb1557abfbL,0x23d16655afbfecdfL, + 0x80f3271f085cac4aL }, + { 0x7fc39aa7d0e62f47L,0x88d519d1460a48e5L,0x59559ac4d28f101eL, + 0x7981d9e9ca9ae816L } }, + /* 62 << 126 */ + { { 0x5c38652c9ac38203L,0x86eaf87f57657fe5L,0x568fc472e21f5416L, + 0x2afff39ce7e597b5L }, + { 0x3adbbb07256d4eabL,0x225986928285ab89L,0x35f8112a041caefeL, + 0x95df02e3a5064c8bL } }, + /* 63 << 126 */ + { { 0x4d63356ec7004bf3L,0x230a08f4db83c7deL,0xca27b2708709a7b7L, + 0x0d1c4cc4cb9abd2dL }, + { 0x8a0bc66e7550fee8L,0x369cd4c79cf7247eL,0x75562e8492b5b7e7L, + 0x8fed0da05802af7bL } }, + /* 64 << 126 */ + { { 0x6a7091c2e48fb889L,0x26882c137b8a9d06L,0xa24986631b82a0e2L, + 0x844ed7363518152dL }, + { 0x282f476fd86e27c7L,0xa04edaca04afefdcL,0x8b256ebc6119e34dL, + 0x56a413e90787d78bL } }, + /* 0 << 133 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 133 */ + { { 0x82ee061d5a74be50L,0xe41781c4dea16ff5L,0xe0b0c81e99bfc8a2L, + 0x624f4d690b547e2dL }, + { 0x3a83545dbdcc9ae4L,0x2573dbb6409b1e8eL,0x482960c4a6c93539L, + 0xf01059ad5ae18798L } }, + /* 2 << 133 */ + { { 0x715c9f973112795fL,0xe8244437984e6ee1L,0x55cb4858ecb66bcdL, + 0x7c136735abaffbeeL }, + { 0x546615955dbec38eL,0x51c0782c388ad153L,0x9ba4c53ac6e0952fL, + 0x27e6782a1b21dfa8L } }, + /* 3 << 133 */ + { { 0x682f903d4ed2dbc2L,0x0eba59c87c3b2d83L,0x8e9dc84d9c7e9335L, + 0x5f9b21b00eb226d7L }, + { 0xe33bd394af267baeL,0xaa86cc25be2e15aeL,0x4f0bf67d6a8ec500L, + 0x5846aa44f9630658L } }, + /* 4 << 133 */ + { { 0xfeb09740e2c2bf15L,0x627a2205a9e99704L,0xec8d73d0c2fbc565L, + 0x223eed8fc20c8de8L }, + { 0x1ee32583a8363b49L,0x1a0b6cb9c9c2b0a6L,0x49f7c3d290dbc85cL, + 0xa8dfbb971ef4c1acL } }, + /* 5 << 133 */ + { { 0xafb34d4c65c7c2abL,0x1d4610e7e2c5ea84L,0x893f6d1b973c4ab5L, + 0xa3cdd7e9945ba5c4L }, + { 0x60514983064417eeL,0x1459b23cad6bdf2bL,0x23b2c3415cf726c3L, + 0x3a82963532d6354aL } }, + /* 6 << 133 */ + { { 0x294f901fab192c18L,0xec5fcbfe7030164fL,0xe2e2fcb7e2246ba6L, + 0x1e7c88b3221a1a0cL }, + { 0x72c7dd93c92d88c5L,0x41c2148e1106fb59L,0x547dd4f5a0f60f14L, + 0xed9b52b263960f31L } }, + /* 7 << 133 */ + { { 0x6c8349ebb0a5b358L,0xb154c5c29e7e2ed6L,0xcad5eccfeda462dbL, + 0xf2d6dbe42de66b69L }, + { 0x426aedf38665e5b2L,0x488a85137b7f5723L,0x15cc43b38bcbb386L, + 0x27ad0af3d791d879L } }, + /* 8 << 133 */ + { { 0xc16c236e846e364fL,0x7f33527cdea50ca0L,0xc48107750926b86dL, + 0x6c2a36090598e70cL }, + { 0xa6755e52f024e924L,0xe0fa07a49db4afcaL,0x15c3ce7d66831790L, + 0x5b4ef350a6cbb0d6L } }, + /* 9 << 133 */ + { { 0x2c4aafc4b6205969L,0x42563f02f6c7854fL,0x016aced51d983b48L, + 0xfeb356d899949755L }, + { 0x8c2a2c81d1a39bd7L,0x8f44340fe6934ae9L,0x148cf91c447904daL, + 0x7340185f0f51a926L } }, + /* 10 << 133 */ + { { 0x2f8f00fb7409ab46L,0x057e78e680e289b2L,0x03e5022ca888e5d1L, + 0x3c87111a9dede4e2L }, + { 0x5b9b0e1c7809460bL,0xe751c85271c9abc7L,0x8b944e28c7cc1dc9L, + 0x4f201ffa1d3cfa08L } }, + /* 11 << 133 */ + { { 0x02fc905c3e6721ceL,0xd52d70dad0b3674cL,0x5dc2e5ca18810da4L, + 0xa984b2735c69dd99L }, + { 0x63b9252784de5ca4L,0x2f1c9872c852dec4L,0x18b03593c2e3de09L, + 0x19d70b019813dc2fL } }, + /* 12 << 133 */ + { { 0x42806b2da6dc1d29L,0xd3030009f871e144L,0xa1feb333aaf49276L, + 0xb5583b9ec70bc04bL }, + { 0x1db0be7895695f20L,0xfc84181189d012b5L,0x6409f27205f61643L, + 0x40d34174d5883128L } }, + /* 13 << 133 */ + { { 0xd79196f567419833L,0x6059e252863b7b08L,0x84da18171c56700cL, + 0x5758ee56b28d3ec4L }, + { 0x7da2771d013b0ea6L,0xfddf524b54c5e9b9L,0x7df4faf824305d80L, + 0x58f5c1bf3a97763fL } }, + /* 14 << 133 */ + { { 0xa5af37f17c696042L,0xd4cba22c4a2538deL,0x211cb9959ea42600L, + 0xcd105f417b069889L }, + { 0xb1e1cf19ddb81e74L,0x472f2d895157b8caL,0x086fb008ee9db885L, + 0x365cd5700f26d131L } }, + /* 15 << 133 */ + { { 0x284b02bba2be7053L,0xdcbbf7c67ab9a6d6L,0x4425559c20f7a530L, + 0x961f2dfa188767c8L }, + { 0xe2fd943570dc80c4L,0x104d6b63f0784120L,0x7f592bc153567122L, + 0xf6bc1246f688ad77L } }, + /* 16 << 133 */ + { { 0x05214c050f15dde9L,0xa47a76a80d5f2b82L,0xbb254d3062e82b62L, + 0x11a05fe03ec955eeL }, + { 0x7eaff46e9d529b36L,0x55ab13018f9e3df6L,0xc463e37199317698L, + 0xfd251438ccda47adL } }, + /* 17 << 133 */ + { { 0xca9c354723d695eaL,0x48ce626e16e589b5L,0x6b5b64c7b187d086L, + 0xd02e1794b2207948L }, + { 0x8b58e98f7198111dL,0x90ca6305dcf9c3ccL,0x5691fe72f34089b0L, + 0x60941af1fc7c80ffL } }, + /* 18 << 133 */ + { { 0xa09bc0a222eb51e5L,0xc0bb7244aa9cf09aL,0x36a8077f80159f06L, + 0x8b5c989edddc560eL }, + { 0x19d2f316512e1f43L,0x02eac554ad08ff62L,0x012ab84c07d20b4eL, + 0x37d1e115d6d4e4e1L } }, + /* 19 << 133 */ + { { 0xb6443e1aab7b19a8L,0xf08d067edef8cd45L,0x63adf3e9685e03daL, + 0xcf15a10e4792b916L }, + { 0xf44bcce5b738a425L,0xebe131d59636b2fdL,0x940688417850d605L, + 0x09684eaab40d749dL } }, + /* 20 << 133 */ + { { 0x8c3c669c72ba075bL,0x89f78b55ba469015L,0x5706aade3e9f8ba8L, + 0x6d8bd565b32d7ed7L }, + { 0x25f4e63b805f08d6L,0x7f48200dc3bcc1b5L,0x4e801968b025d847L, + 0x74afac0487cbe0a8L } }, + /* 21 << 133 */ + { { 0x43ed2c2b7e63d690L,0xefb6bbf00223cdb8L,0x4fec3cae2884d3feL, + 0x065ecce6d75e25a4L }, + { 0x6c2294ce69f79071L,0x0d9a8e5f044b8666L,0x5009f23817b69d8fL, + 0x3c29f8fec5dfdaf7L } }, + /* 22 << 133 */ + { { 0x9067528febae68c4L,0x5b38563230c5ba21L,0x540df1191fdd1aecL, + 0xcf37825bcfba4c78L }, + { 0x77eff980beb11454L,0x40a1a99160c1b066L,0xe8018980f889a1c7L, + 0xb9c52ae976c24be0L } }, + /* 23 << 133 */ + { { 0x05fbbcce45650ef4L,0xae000f108aa29ac7L,0x884b71724f04c470L, + 0x7cd4fde219bb5c25L }, + { 0x6477b22ae8840869L,0xa88688595fbd0686L,0xf23cc02e1116dfbaL, + 0x76cd563fd87d7776L } }, + /* 24 << 133 */ + { { 0xe2a37598a9d82abfL,0x5f188ccbe6c170f5L,0x816822005066b087L, + 0xda22c212c7155adaL }, + { 0x151e5d3afbddb479L,0x4b606b846d715b99L,0x4a73b54bf997cb2eL, + 0x9a1bfe433ecd8b66L } }, + /* 25 << 133 */ + { { 0x1c3128092a67d48aL,0xcd6a671e031fa9e2L,0xbec3312a0e43a34aL, + 0x1d93563955ef47d3L }, + { 0x5ea024898fea73eaL,0x8247b364a035afb2L,0xb58300a65265b54cL, + 0x3286662f722c7148L } }, + /* 26 << 133 */ + { { 0xb77fd76bb4ec4c20L,0xf0a12fa70f3fe3fdL,0xf845bbf541d8c7e8L, + 0xe4d969ca5ec10aa8L }, + { 0x4c0053b743e232a3L,0xdc7a3fac37f8a45aL,0x3c4261c520d81c8fL, + 0xfd4b3453b00eab00L } }, + /* 27 << 133 */ + { { 0x76d48f86d36e3062L,0x626c5277a143ff02L,0x538174deaf76f42eL, + 0x2267aa866407ceacL }, + { 0xfad7635172e572d5L,0xab861af7ba7330ebL,0xa0a1c8c7418d8657L, + 0x988821cb20289a52L } }, + /* 28 << 133 */ + { { 0x79732522cccc18adL,0xaadf3f8df1a6e027L,0xf7382c9317c2354dL, + 0x5ce1680cd818b689L }, + { 0x359ebbfcd9ecbee9L,0x4330689c1cae62acL,0xb55ce5b4c51ac38aL, + 0x7921dfeafe238ee8L } }, + /* 29 << 133 */ + { { 0x3972bef8271d1ca5L,0x3e423bc7e8aabd18L,0x57b09f3f44a3e5e3L, + 0x5da886ae7b444d66L }, + { 0x68206634a9964375L,0x356a2fa3699cd0ffL,0xaf0faa24dba515e9L, + 0x536e1f5cb321d79aL } }, + /* 30 << 133 */ + { { 0xd3b9913a5c04e4eaL,0xd549dcfed6f11513L,0xee227bf579fd1d94L, + 0x9f35afeeb43f2c67L }, + { 0xd2638d24f1314f53L,0x62baf948cabcd822L,0x5542de294ef48db0L, + 0xb3eb6a04fc5f6bb2L } }, + /* 31 << 133 */ + { { 0x23c110ae1208e16aL,0x1a4d15b5f8363e24L,0x30716844164be00bL, + 0xa8e24824f6f4690dL }, + { 0x548773a290b170cfL,0xa1bef33142f191f4L,0x70f418d09247aa97L, + 0xea06028e48be9147L } }, + /* 32 << 133 */ + { { 0xe13122f3dbfb894eL,0xbe9b79f6ce274b18L,0x85a49de5ca58aadfL, + 0x2495775811487351L }, + { 0x111def61bb939099L,0x1d6a974a26d13694L,0x4474b4ced3fc253bL, + 0x3a1485e64c5db15eL } }, + /* 33 << 133 */ + { { 0xe79667b4147c15b4L,0xe34f553b7bc61301L,0x032b80f817094381L, + 0x55d8bafd723eaa21L }, + { 0x5a987995f1c0e74eL,0x5a9b292eebba289cL,0x413cd4b2eb4c8251L, + 0x98b5d243d162db0aL } }, + /* 34 << 133 */ + { { 0xbb47bf6668342520L,0x08d68949baa862d1L,0x11f349c7e906abcdL, + 0x454ce985ed7bf00eL }, + { 0xacab5c9eb55b803bL,0xb03468ea31e3c16dL,0x5c24213dd273bf12L, + 0x211538eb71587887L } }, + /* 35 << 133 */ + { { 0x198e4a2f731dea2dL,0xd5856cf274ed7b2aL,0x86a632eb13a664feL, + 0x932cd909bda41291L }, + { 0x850e95d4c0c4ddc0L,0xc0f422f8347fc2c9L,0xe68cbec486076bcbL, + 0xf9e7c0c0cd6cd286L } }, + /* 36 << 133 */ + { { 0x65994ddb0f5f27caL,0xe85461fba80d59ffL,0xff05481a66601023L, + 0xc665427afc9ebbfbL }, + { 0xb0571a697587fd52L,0x935289f88d49efceL,0x61becc60ea420688L, + 0xb22639d913a786afL } }, + /* 37 << 133 */ + { { 0x1a8e6220361ecf90L,0x001f23e025506463L,0xe4ae9b5d0a5c2b79L, + 0xebc9cdadd8149db5L }, + { 0xb33164a1934aa728L,0x750eb00eae9b60f3L,0x5a91615b9b9cfbfdL, + 0x97015cbfef45f7f6L } }, + /* 38 << 133 */ + { { 0xb462c4a5bf5151dfL,0x21adcc41b07118f2L,0xd60c545b043fa42cL, + 0xfc21aa54e96be1abL }, + { 0xe84bc32f4e51ea80L,0x3dae45f0259b5d8dL,0xbb73c7ebc38f1b5eL, + 0xe405a74ae8ae617dL } }, + /* 39 << 133 */ + { { 0xbb1ae9c69f1c56bdL,0x8c176b9849f196a4L,0xc448f3116875092bL, + 0xb5afe3de9f976033L }, + { 0xa8dafd49145813e5L,0x687fc4d9e2b34226L,0xf2dfc92d4c7ff57fL, + 0x004e3fc1401f1b46L } }, + /* 40 << 133 */ + { { 0x5afddab61430c9abL,0x0bdd41d32238e997L,0xf0947430418042aeL, + 0x71f9addacdddc4cbL }, + { 0x7090c016c52dd907L,0xd9bdf44d29e2047fL,0xe6f1fe801b1011a6L, + 0xb63accbcd9acdc78L } }, + /* 41 << 133 */ + { { 0xcfc7e2351272a95bL,0x0c667717a6276ac8L,0x3c0d3709e2d7eef7L, + 0x5add2b069a685b3eL }, + { 0x363ad32d14ea5d65L,0xf8e01f068d7dd506L,0xc9ea221375b4aac6L, + 0xed2a2bf90d353466L } }, + /* 42 << 133 */ + { { 0x439d79b5e9d3a7c3L,0x8e0ee5a681b7f34bL,0xcf3dacf51dc4ba75L, + 0x1d3d1773eb3310c7L }, + { 0xa8e671127747ae83L,0x31f43160197d6b40L,0x0521cceecd961400L, + 0x67246f11f6535768L } }, + /* 43 << 133 */ + { { 0x702fcc5aef0c3133L,0x247cc45d7e16693bL,0xfd484e49c729b749L, + 0x522cef7db218320fL }, + { 0xe56ef40559ab93b3L,0x225fba119f181071L,0x33bd659515330ed0L, + 0xc4be69d51ddb32f7L } }, + /* 44 << 133 */ + { { 0x264c76680448087cL,0xac30903f71432daeL,0x3851b26600f9bf47L, + 0x400ed3116cdd6d03L }, + { 0x045e79fef8fd2424L,0xfdfd974afa6da98bL,0x45c9f6410c1e673aL, + 0x76f2e7335b2c5168L } }, + /* 45 << 133 */ + { { 0x1adaebb52a601753L,0xb286514cc57c2d49L,0xd87696701e0bfd24L, + 0x950c547e04478922L }, + { 0xd1d41969e5d32bfeL,0x30bc1472750d6c3eL,0x8f3679fee0e27f3aL, + 0x8f64a7dca4a6ee0cL } }, + /* 46 << 133 */ + { { 0x2fe59937633dfb1fL,0xea82c395977f2547L,0xcbdfdf1a661ea646L, + 0xc7ccc591b9085451L }, + { 0x8217796281761e13L,0xda57596f9196885cL,0xbc17e84928ffbd70L, + 0x1e6e0a412671d36fL } }, + /* 47 << 133 */ + { { 0x61ae872c4152fcf5L,0x441c87b09e77e754L,0xd0799dd5a34dff09L, + 0x766b4e4488a6b171L }, + { 0xdc06a51211f1c792L,0xea02ae934be35c3eL,0xe5ca4d6de90c469eL, + 0x4df4368e56e4ff5cL } }, + /* 48 << 133 */ + { { 0x7817acab4baef62eL,0x9f5a2202a85b91e8L,0x9666ebe66ce57610L, + 0x32ad31f3f73bfe03L }, + { 0x628330a425bcf4d6L,0xea950593515056e6L,0x59811c89e1332156L, + 0xc89cf1fe8c11b2d7L } }, + /* 49 << 133 */ + { { 0x75b6391304e60cc0L,0xce811e8d4625d375L,0x030e43fc2d26e562L, + 0xfbb30b4b608d36a0L }, + { 0x634ff82c48528118L,0x7c6fe085cd285911L,0x7f2830c099358f28L, + 0x2e60a95e665e6c09L } }, + /* 50 << 133 */ + { { 0x08407d3d9b785dbfL,0x530889aba759bce7L,0xf228e0e652f61239L, + 0x2b6d14616879be3cL }, + { 0xe6902c0451a7bbf7L,0x30ad99f076f24a64L,0x66d9317a98bc6da0L, + 0xf4f877f3cb596ac0L } }, + /* 51 << 133 */ + { { 0xb05ff62d4c44f119L,0x4555f536e9b77416L,0xc7c0d0598caed63bL, + 0x0cd2b7cec358b2a9L }, + { 0x3f33287b46945fa3L,0xf8785b20d67c8791L,0xc54a7a619637bd08L, + 0x54d4598c18be79d7L } }, + /* 52 << 133 */ + { { 0x889e5acbc46d7ce1L,0x9a515bb78b085877L,0xfac1a03d0b7a5050L, + 0x7d3e738af2926035L }, + { 0x861cc2ce2a6cb0ebL,0x6f2e29558f7adc79L,0x61c4d45133016376L, + 0xd9fd2c805ad59090L } }, + /* 53 << 133 */ + { { 0xe5a83738b2b836a1L,0x855b41a07c0d6622L,0x186fe3177cc19af1L, + 0x6465c1fffdd99acbL }, + { 0x46e5c23f6974b99eL,0x75a7cf8ba2717cbeL,0x4d2ebc3f062be658L, + 0x094b44475f209c98L } }, + /* 54 << 133 */ + { { 0x4af285edb940cb5aL,0x6706d7927cc82f10L,0xc8c8776c030526faL, + 0xfa8e6f76a0da9140L }, + { 0x77ea9d34591ee4f0L,0x5f46e33740274166L,0x1bdf98bbea671457L, + 0xd7c08b46862a1fe2L } }, + /* 55 << 133 */ + { { 0x46cc303c1c08ad63L,0x995434404c845e7bL,0x1b8fbdb548f36bf7L, + 0x5b82c3928c8273a7L }, + { 0x08f712c4928435d5L,0x071cf0f179330380L,0xc74c2d24a8da054aL, + 0xcb0e720143c46b5cL } }, + /* 56 << 133 */ + { { 0x0ad7337ac0b7eff3L,0x8552225ec5e48b3cL,0xe6f78b0c73f13a5fL, + 0x5e70062e82349cbeL }, + { 0x6b8d5048e7073969L,0x392d2a29c33cb3d2L,0xee4f727c4ecaa20fL, + 0xa068c99e2ccde707L } }, + /* 57 << 133 */ + { { 0xfcd5651fb87a2913L,0xea3e3c153cc252f0L,0x777d92df3b6cd3e4L, + 0x7a414143c5a732e7L }, + { 0xa895951aa71ff493L,0xfe980c92bbd37cf6L,0x45bd5e64decfeeffL, + 0x910dc2a9a44c43e9L } }, + /* 58 << 133 */ + { { 0xcb403f26cca9f54dL,0x928bbdfb9303f6dbL,0x3c37951ea9eee67cL, + 0x3bd61a52f79961c3L }, + { 0x09a238e6395c9a79L,0x6940ca2d61eb352dL,0x7d1e5c5ec1875631L, + 0x1e19742c1e1b20d1L } }, + /* 59 << 133 */ + { { 0x4633d90823fc2e6eL,0xa76e29a908959149L,0x61069d9c84ed7da5L, + 0x0baa11cf5dbcad51L }, + { 0xd01eec64961849daL,0x93b75f1faf3d8c28L,0x57bc4f9f1ca2ee44L, + 0x5a26322d00e00558L } }, + /* 60 << 133 */ + { { 0x1888d65861a023efL,0x1d72aab4b9e5246eL,0xa9a26348e5563ec0L, + 0xa0971963c3439a43L }, + { 0x567dd54badb9b5b7L,0x73fac1a1c45a524bL,0x8fe97ef7fe38e608L, + 0x608748d23f384f48L } }, + /* 61 << 133 */ + { { 0xb0571794c486094fL,0x869254a38bf3a8d6L,0x148a8dd1310b0e25L, + 0x99ab9f3f9aa3f7d8L }, + { 0x0927c68a6706c02eL,0x22b5e76c69790e6cL,0x6c3252606c71376cL, + 0x53a5769009ef6657L } }, + /* 62 << 133 */ + { { 0x8d63f852edffcf3aL,0xb4d2ed043c0a6f55L,0xdb3aa8de12519b9eL, + 0x5d38e9c41e0a569aL }, + { 0x871528bf303747e2L,0xa208e77cf5b5c18dL,0x9d129c88ca6bf923L, + 0xbcbf197fbf02839fL } }, + /* 63 << 133 */ + { { 0x9b9bf03027323194L,0x3b055a8b339ca59dL,0xb46b23120f669520L, + 0x19789f1f497e5f24L }, + { 0x9c499468aaf01801L,0x72ee11908b69d59cL,0x8bd39595acf4c079L, + 0x3ee11ece8e0cd048L } }, + /* 64 << 133 */ + { { 0xebde86ec1ed66f18L,0x225d906bd61fce43L,0x5cab07d6e8bed74dL, + 0x16e4617f27855ab7L }, + { 0x6568aaddb2fbc3ddL,0xedb5484f8aeddf5bL,0x878f20e86dcf2fadL, + 0x3516497c615f5699L } }, + /* 0 << 140 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 140 */ + { { 0xef0a3fecfa181e69L,0x9ea02f8130d69a98L,0xb2e9cf8e66eab95dL, + 0x520f2beb24720021L }, + { 0x621c540a1df84361L,0x1203772171fa6d5dL,0x6e3c7b510ff5f6ffL, + 0x817a069babb2bef3L } }, + /* 2 << 140 */ + { { 0x83572fb6b294cda6L,0x6ce9bf75b9039f34L,0x20e012f0095cbb21L, + 0xa0aecc1bd063f0daL }, + { 0x57c21c3af02909e5L,0xc7d59ecf48ce9cdcL,0x2732b8448ae336f8L, + 0x056e37233f4f85f4L } }, + /* 3 << 140 */ + { { 0x8a10b53189e800caL,0x50fe0c17145208fdL,0x9e43c0d3b714ba37L, + 0x427d200e34189accL }, + { 0x05dee24fe616e2c0L,0x9c25f4c8ee1854c1L,0x4d3222a58f342a73L, + 0x0807804fa027c952L } }, + /* 4 << 140 */ + { { 0xc222653a4f0d56f3L,0x961e4047ca28b805L,0x2c03f8b04a73434bL, + 0x4c966787ab712a19L }, + { 0xcc196c42864fee42L,0xc1be93da5b0ece5cL,0xa87d9f22c131c159L, + 0x2bb6d593dce45655L } }, + /* 5 << 140 */ + { { 0x22c49ec9b809b7ceL,0x8a41486be2c72c2cL,0x813b9420fea0bf36L, + 0xb3d36ee9a66dac69L }, + { 0x6fddc08a328cc987L,0x0a3bcd2c3a326461L,0x7103c49dd810dbbaL, + 0xf9d81a284b78a4c4L } }, + /* 6 << 140 */ + { { 0x3de865ade4d55941L,0xdedafa5e30384087L,0x6f414abb4ef18b9bL, + 0x9ee9ea42faee5268L }, + { 0x260faa1637a55a4aL,0xeb19a514015f93b9L,0x51d7ebd29e9c3598L, + 0x523fc56d1932178eL } }, + /* 7 << 140 */ + { { 0x501d070cb98fe684L,0xd60fbe9a124a1458L,0xa45761c892bc6b3fL, + 0xf5384858fe6f27cbL }, + { 0x4b0271f7b59e763bL,0x3d4606a95b5a8e5eL,0x1eda5d9b05a48292L, + 0xda7731d0e6fec446L } }, + /* 8 << 140 */ + { { 0xa3e3369390d45871L,0xe976404006166d8dL,0xb5c3368289a90403L, + 0x4bd1798372f1d637L }, + { 0xa616679ed5d2c53aL,0x5ec4bcd8fdcf3b87L,0xae6d7613b66a694eL, + 0x7460fc76e3fc27e5L } }, + /* 9 << 140 */ + { { 0x70469b8295caabeeL,0xde024ca5889501e3L,0x6bdadc06076ed265L, + 0x0cb1236b5a0ef8b2L }, + { 0x4065ddbf0972ebf9L,0xf1dd387522aca432L,0xa88b97cf744aff76L, + 0xd1359afdfe8e3d24L } }, + /* 10 << 140 */ + { { 0x52a3ba2b91502cf3L,0x2c3832a8084db75dL,0x04a12dddde30b1c9L, + 0x7802eabce31fd60cL }, + { 0x33707327a37fddabL,0x65d6f2abfaafa973L,0x3525c5b811e6f91aL, + 0x76aeb0c95f46530bL } }, + /* 11 << 140 */ + { { 0xe8815ff62f93a675L,0xa6ec968405f48679L,0x6dcbb556358ae884L, + 0x0af61472e19e3873L }, + { 0x72334372a5f696beL,0xc65e57ea6f22fb70L,0x268da30c946cea90L, + 0x136a8a8765681b2aL } }, + /* 12 << 140 */ + { { 0xad5e81dc0f9f44d4L,0xf09a69602c46585aL,0xd1649164c447d1b1L, + 0x3b4b36c8879dc8b1L }, + { 0x20d4177b3b6b234cL,0x096a25051730d9d0L,0x0611b9b8ef80531dL, + 0xba904b3b64bb495dL } }, + /* 13 << 140 */ + { { 0x1192d9d493a3147aL,0x9f30a5dc9a565545L,0x90b1f9cb6ef07212L, + 0x299585460d87fc13L }, + { 0xd3323effc17db9baL,0xcb18548ccb1644a8L,0x18a306d44f49ffbcL, + 0x28d658f14c2e8684L } }, + /* 14 << 140 */ + { { 0x44ba60cda99f8c71L,0x67b7abdb4bf742ffL,0x66310f9c914b3f99L, + 0xae430a32f412c161L }, + { 0x1e6776d388ace52fL,0x4bc0fa2452d7067dL,0x03c286aa8f07cd1bL, + 0x4cb8f38ca985b2c1L } }, + /* 15 << 140 */ + { { 0x83ccbe808c3bff36L,0x005a0bd25263e575L,0x460d7dda259bdcd1L, + 0x4a1c5642fa5cab6bL }, + { 0x2b7bdbb99fe4fc88L,0x09418e28cc97bbb5L,0xd8274fb4a12321aeL, + 0xb137007d5c87b64eL } }, + /* 16 << 140 */ + { { 0x80531fe1c63c4962L,0x50541e89981fdb25L,0xdc1291a1fd4c2b6bL, + 0xc0693a17a6df4fcaL }, + { 0xb2c4604e0117f203L,0x245f19630a99b8d0L,0xaedc20aac6212c44L, + 0xb1ed4e56520f52a8L } }, + /* 17 << 140 */ + { { 0xfe48f575f8547be3L,0x0a7033cda9e45f98L,0x4b45d3a918c50100L, + 0xb2a6cd6aa61d41daL }, + { 0x60bbb4f557933c6bL,0xa7538ebd2b0d7ffcL,0x9ea3ab8d8cd626b6L, + 0x8273a4843601625aL } }, + /* 18 << 140 */ + { { 0x888598450168e508L,0x8cbc9bb299a94abdL,0x713ac792fab0a671L, + 0xa3995b196c9ebffcL }, + { 0xe711668e1239e152L,0x56892558bbb8dff4L,0x8bfc7dabdbf17963L, + 0x5b59fe5ab3de1253L } }, + /* 19 << 140 */ + { { 0x7e3320eb34a9f7aeL,0xe5e8cf72d751efe4L,0x7ea003bcd9be2f37L, + 0xc0f551a0b6c08ef7L }, + { 0x56606268038f6725L,0x1dd38e356d92d3b6L,0x07dfce7cc3cbd686L, + 0x4e549e04651c5da8L } }, + /* 20 << 140 */ + { { 0x4058f93b08b19340L,0xc2fae6f4cac6d89dL,0x4bad8a8c8f159cc7L, + 0x0ddba4b3cb0b601cL }, + { 0xda4fc7b51dd95f8cL,0x1d163cd7cea5c255L,0x30707d06274a8c4cL, + 0x79d9e0082802e9ceL } }, + /* 21 << 140 */ + { { 0x02a29ebfe6ddd505L,0x37064e74b50bed1aL,0x3f6bae65a7327d57L, + 0x3846f5f1f83920bcL }, + { 0x87c3749160df1b9bL,0x4cfb28952d1da29fL,0x10a478ca4ed1743cL, + 0x390c60303edd47c6L } }, + /* 22 << 140 */ + { { 0x8f3e53128c0a78deL,0xccd02bda1e85df70L,0xd6c75c03a61b6582L, + 0x0762921cfc0eebd1L }, + { 0xd34d0823d85010c0L,0xd73aaacb0044cf1fL,0xfb4159bba3b5e78aL, + 0x2287c7f7e5826f3fL } }, + /* 23 << 140 */ + { { 0x4aeaf742580b1a01L,0xf080415d60423b79L,0xe12622cda7dea144L, + 0x49ea499659d62472L }, + { 0xb42991ef571f3913L,0x0610f214f5b25a8aL,0x47adc58530b79e8fL, + 0xf90e3df607a065a2L } }, + /* 24 << 140 */ + { { 0x5d0a5deb43e2e034L,0x53fb5a34444024aaL,0xa8628c686b0c9f7fL, + 0x9c69c29cac563656L }, + { 0x5a231febbace47b6L,0xbdce02899ea5a2ecL,0x05da1fac9463853eL, + 0x96812c52509e78aaL } }, + /* 25 << 140 */ + { { 0xd3fb577157151692L,0xeb2721f8d98e1c44L,0xc050608732399be1L, + 0xda5a5511d979d8b8L }, + { 0x737ed55dc6f56780L,0xe20d30040dc7a7f4L,0x02ce7301f5941a03L, + 0x91ef5215ed30f83aL } }, + /* 26 << 140 */ + { { 0x28727fc14092d85fL,0x72d223c65c49e41aL,0xa7cf30a2ba6a4d81L, + 0x7c086209b030d87dL }, + { 0x04844c7dfc588b09L,0x728cd4995874bbb0L,0xcc1281eee84c0495L, + 0x0769b5baec31958fL } }, + /* 27 << 140 */ + { { 0x665c228bf99c2471L,0xf2d8a11b191eb110L,0x4594f494d36d7024L, + 0x482ded8bcdcb25a1L }, + { 0xc958a9d8dadd4885L,0x7004477ef1d2b547L,0x0a45f6ef2a0af550L, + 0x4fc739d62f8d6351L } }, + /* 28 << 140 */ + { { 0x75cdaf27786f08a9L,0x8700bb2642c2737fL,0x855a71411c4e2670L, + 0x810188c115076fefL }, + { 0xc251d0c9abcd3297L,0xae4c8967f48108ebL,0xbd146de718ceed30L, + 0xf9d4f07ac986bcedL } }, + /* 29 << 140 */ + { { 0x5ad98ed583fa1e08L,0x7780d33ebeabd1fbL,0xe330513c903b1196L, + 0xba11de9ea47bc8c4L }, + { 0x684334da02c2d064L,0x7ecf360da48de23bL,0x57a1b4740a9089d8L, + 0xf28fa439ff36734cL } }, + /* 30 << 140 */ + { { 0xf2a482cbea4570b3L,0xee65d68ba5ebcee9L,0x988d0036b9694cd5L, + 0x53edd0e937885d32L }, + { 0xe37e3307beb9bc6dL,0xe9abb9079f5c6768L,0x4396ccd551f2160fL, + 0x2500888c47336da6L } }, + /* 31 << 140 */ + { { 0x383f9ed9926fce43L,0x809dd1c704da2930L,0x30f6f5968a4cb227L, + 0x0d700c7f73a56b38L }, + { 0x1825ea33ab64a065L,0xaab9b7351338df80L,0x1516100d9b63f57fL, + 0x2574395a27a6a634L } }, + /* 32 << 140 */ + { { 0xb5560fb6700a1acdL,0xe823fd73fd999681L,0xda915d1f6cb4e1baL, + 0x0d0301186ebe00a3L }, + { 0x744fb0c989fca8cdL,0x970d01dbf9da0e0bL,0x0ad8c5647931d76fL, + 0xb15737bff659b96aL } }, + /* 33 << 140 */ + { { 0xdc9933e8a8b484e7L,0xb2fdbdf97a26dec7L,0x2349e9a49f1f0136L, + 0x7860368e70fddddbL }, + { 0xd93d2c1cf9ad3e18L,0x6d6c5f17689f4e79L,0x7a544d91b24ff1b6L, + 0x3e12a5ebfe16cd8cL } }, + /* 34 << 140 */ + { { 0x543574e9a56b872fL,0xa1ad550cfcf68ea2L,0x689e37d23f560ef7L, + 0x8c54b9cac9d47a8bL }, + { 0x46d40a4a088ac342L,0xec450c7c1576c6d0L,0xb589e31c1f9689e9L, + 0xdacf2602b8781718L } }, + /* 35 << 140 */ + { { 0xa89237c6c8cb6b42L,0x1326fc93b96ef381L,0x55d56c6db5f07825L, + 0xacba2eea7449e22dL }, + { 0x74e0887a633c3000L,0xcb6cd172d7cbcf71L,0x309e81dec36cf1beL, + 0x07a18a6d60ae399bL } }, + /* 36 << 140 */ + { { 0xb36c26799edce57eL,0x52b892f4df001d41L,0xd884ae5d16a1f2c6L, + 0x9b329424efcc370aL }, + { 0x3120daf2bd2e21dfL,0x55298d2d02470a99L,0x0b78af6ca05db32eL, + 0x5c76a331601f5636L } }, + /* 37 << 140 */ + { { 0xaae861fff8a4f29cL,0x70dc9240d68f8d49L,0x960e649f81b1321cL, + 0x3d2c801b8792e4ceL }, + { 0xf479f77242521876L,0x0bed93bc416c79b1L,0xa67fbc05263e5bc9L, + 0x01e8e630521db049L } }, + /* 38 << 140 */ + { { 0x76f26738c6f3431eL,0xe609cb02e3267541L,0xb10cff2d818c877cL, + 0x1f0e75ce786a13cbL }, + { 0xf4fdca641158544dL,0x5d777e896cb71ed0L,0x3c233737a9aa4755L, + 0x7b453192e527ab40L } }, + /* 39 << 140 */ + { { 0xdb59f68839f05ffeL,0x8f4f4be06d82574eL,0xcce3450cee292d1bL, + 0xaa448a1261ccd086L }, + { 0xabce91b3f7914967L,0x4537f09b1908a5edL,0xa812421ef51042e7L, + 0xfaf5cebcec0b3a34L } }, + /* 40 << 140 */ + { { 0x730ffd874ca6b39aL,0x70fb72ed02efd342L,0xeb4735f9d75c8edbL, + 0xc11f2157c278aa51L }, + { 0xc459f635bf3bfebfL,0x3a1ff0b46bd9601fL,0xc9d12823c420cb73L, + 0x3e9af3e23c2915a3L } }, + /* 41 << 140 */ + { { 0xe0c82c72b41c3440L,0x175239e5e3039a5fL,0xe1084b8a558795a3L, + 0x328d0a1dd01e5c60L }, + { 0x0a495f2ed3788a04L,0x25d8ff1666c11a9fL,0xf5155f059ed692d6L, + 0x954fa1074f425fe4L } }, + /* 42 << 140 */ + { { 0xd16aabf2e98aaa99L,0x90cd8ba096b0f88aL,0x957f4782c154026aL, + 0x54ee073452af56d2L }, + { 0xbcf89e5445b4147aL,0x3d102f219a52816cL,0x6808517e39b62e77L, + 0x92e2542169169ad8L } }, + /* 43 << 140 */ + { { 0xd721d871bb608558L,0x60e4ebaef6d4ff9bL,0x0ba1081941f2763eL, + 0xca2e45be51ee3247L }, + { 0x66d172ec2bfd7a5fL,0x528a8f2f74d0b12dL,0xe17f1e38dabe70dcL, + 0x1d5d73169f93983cL } }, + /* 44 << 140 */ + { { 0x51b2184adf423e31L,0xcb417291aedb1a10L,0x2054ca93625bcab9L, + 0x54396860a98998f0L }, + { 0x4e53f6c4a54ae57eL,0x0ffeb590ee648e9dL,0xfbbdaadc6afaf6bcL, + 0xf88ae796aa3bfb8aL } }, + /* 45 << 140 */ + { { 0x209f1d44d2359ed9L,0xac68dd03f3544ce2L,0xf378da47fd51e569L, + 0xe1abd8602cc80097L }, + { 0x23ca18d9343b6e3aL,0x480797e8b40a1baeL,0xd1f0c717533f3e67L, + 0x4489697006e6cdfcL } }, + /* 46 << 140 */ + { { 0x8ca2105552a82e8dL,0xb2caf78578460cdcL,0x4c1b7b62e9037178L, + 0xefc09d2cdb514b58L }, + { 0x5f2df9ee9113be5cL,0x2fbda78fb3f9271cL,0xe09a81af8f83fc54L, + 0x06b138668afb5141L } }, + /* 47 << 140 */ + { { 0x38f6480f43e3865dL,0x72dd77a81ddf47d9L,0xf2a8e9714c205ff7L, + 0x46d449d89d088ad8L }, + { 0x926619ea185d706fL,0xe47e02ebc7dd7f62L,0xe7f120a78cbc2031L, + 0xc18bef00998d4ac9L } }, + /* 48 << 140 */ + { { 0x18f37a9c6bdf22daL,0xefbc432f90dc82dfL,0xc52cef8e5d703651L, + 0x82887ba0d99881a5L }, + { 0x7cec9ddab920ec1dL,0xd0d7e8c3ec3e8d3bL,0x445bc3954ca88747L, + 0xedeaa2e09fd53535L } }, + /* 49 << 140 */ + { { 0x461b1d936cc87475L,0xd92a52e26d2383bdL,0xfabccb59d7903546L, + 0x6111a7613d14b112L }, + { 0x0ae584feb3d5f612L,0x5ea69b8d60e828ecL,0x6c07898554087030L, + 0x649cab04ac4821feL } }, + /* 50 << 140 */ + { { 0x25ecedcf8bdce214L,0xb5622f7286af7361L,0x0e1227aa7038b9e2L, + 0xd0efb273ac20fa77L }, + { 0x817ff88b79df975bL,0x856bf2861999503eL,0xb4d5351f5038ec46L, + 0x740a52c5fc42af6eL } }, + /* 51 << 140 */ + { { 0x2e38bb152cbb1a3fL,0xc3eb99fe17a83429L,0xca4fcbf1dd66bb74L, + 0x880784d6cde5e8fcL }, + { 0xddc84c1cb4e7a0beL,0x8780510dbd15a72fL,0x44bcf1af81ec30e1L, + 0x141e50a80a61073eL } }, + /* 52 << 140 */ + { { 0x0d95571847be87aeL,0x68a61417f76a4372L,0xf57e7e87c607c3d3L, + 0x043afaf85252f332L }, + { 0xcc14e1211552a4d2L,0xb6dee692bb4d4ab4L,0xb6ab74c8a03816a4L, + 0x84001ae46f394a29L } }, + /* 53 << 140 */ + { { 0x5bed8344d795fb45L,0x57326e7db79f55a5L,0xc9533ce04accdffcL, + 0x53473caf3993fa04L }, + { 0x7906eb93a13df4c8L,0xa73e51f697cbe46fL,0xd1ab3ae10ae4ccf8L, + 0x256145088a5b3dbcL } }, + /* 54 << 140 */ + { { 0x61eff96211a71b27L,0xdf71412b6bb7fa39L,0xb31ba6b82bd7f3efL, + 0xb0b9c41569180d29L }, + { 0xeec14552014cdde5L,0x702c624b227b4bbbL,0x2b15e8c2d3e988f3L, + 0xee3bcc6da4f7fd04L } }, + /* 55 << 140 */ + { { 0x9d00822a42ac6c85L,0x2db0cea61df9f2b7L,0xd7cad2ab42de1e58L, + 0x346ed5262d6fbb61L }, + { 0xb39629951a2faf09L,0x2fa8a5807c25612eL,0x30ae04da7cf56490L, + 0x756629080eea3961L } }, + /* 56 << 140 */ + { { 0x3609f5c53d080847L,0xcb081d395241d4f6L,0xb4fb381077961a63L, + 0xc20c59842abb66fcL }, + { 0x3d40aa7cf902f245L,0x9cb127364e536b1eL,0x5eda24da99b3134fL, + 0xafbd9c695cd011afL } }, + /* 57 << 140 */ + { { 0x9a16e30ac7088c7dL,0x5ab657103207389fL,0x1b09547fe7407a53L, + 0x2322f9d74fdc6eabL }, + { 0xc0f2f22d7430de4dL,0x19382696e68ca9a9L,0x17f1eff1918e5868L, + 0xe3b5b635586f4204L } }, + /* 58 << 140 */ + { { 0x146ef9803fbc4341L,0x359f2c805b5eed4eL,0x9f35744e7482e41dL, + 0x9a9ac3ecf3b224c2L }, + { 0x9161a6fe91fc50aeL,0x89ccc66bc613fa7cL,0x89268b14c732f15aL, + 0x7cd6f4e2b467ed03L } }, + /* 59 << 140 */ + { { 0xfbf79869ce56b40eL,0xf93e094cc02dde98L,0xefe0c3a8edee2cd7L, + 0x90f3ffc0b268fd42L }, + { 0x81a7fd5608241aedL,0x95ab7ad800b1afe8L,0x401270563e310d52L, + 0xd3ffdeb109d9fc43L } }, + /* 60 << 140 */ + { { 0xc8f85c91d11a8594L,0x2e74d25831cf6db8L,0x829c7ca302b5dfd0L, + 0xe389cfbe69143c86L }, + { 0xd01b6405941768d8L,0x4510399503bf825dL,0xcc4ee16656cd17e2L, + 0xbea3c283ba037e79L } }, + /* 61 << 140 */ + { { 0x4e1ac06ed9a47520L,0xfbfe18aaaf852404L,0x5615f8e28087648aL, + 0x7301e47eb9d150d9L }, + { 0x79f9f9ddb299b977L,0x76697a7ba5b78314L,0x10d674687d7c90e7L, + 0x7afffe03937210b5L } }, + /* 62 << 140 */ + { { 0x5aef3e4b28c22ceeL,0xefb0ecd809fd55aeL,0x4cea71320d2a5d6aL, + 0x9cfb5fa101db6357L }, + { 0x395e0b57f36e1ac5L,0x008fa9ad36cafb7dL,0x8f6cdf705308c4dbL, + 0x51527a3795ed2477L } }, + /* 63 << 140 */ + { { 0xba0dee305bd21311L,0x6ed41b22909c90d7L,0xc5f6b7587c8696d3L, + 0x0db8eaa83ce83a80L }, + { 0xd297fe37b24b4b6fL,0xfe58afe8522d1f0dL,0x973587368c98dbd9L, + 0x6bc226ca9454a527L } }, + /* 64 << 140 */ + { { 0xa12b384ece53c2d0L,0x779d897d5e4606daL,0xa53e47b073ec12b0L, + 0x462dbbba5756f1adL }, + { 0x69fe09f2cafe37b6L,0x273d1ebfecce2e17L,0x8ac1d5383cf607fdL, + 0x8035f7ff12e10c25L } }, + /* 0 << 147 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 147 */ + { { 0x854d34c77e6c5520L,0xc27df9efdcb9ea58L,0x405f2369d686666dL, + 0x29d1febf0417aa85L }, + { 0x9846819e93470afeL,0x3e6a9669e2a27f9eL,0x24d008a2e31e6504L, + 0xdba7cecf9cb7680aL } }, + /* 2 << 147 */ + { { 0xecaff541338d6e43L,0x56f7dd734541d5ccL,0xb5d426de96bc88caL, + 0x48d94f6b9ed3a2c3L }, + { 0x6354a3bb2ef8279cL,0xd575465b0b1867f2L,0xef99b0ff95225151L, + 0xf3e19d88f94500d8L } }, + /* 3 << 147 */ + { { 0x92a83268e32dd620L,0x913ec99f627849a2L,0xedd8fdfa2c378882L, + 0xaf96f33eee6f8cfeL }, + { 0xc06737e5dc3fa8a5L,0x236bb531b0b03a1dL,0x33e59f2989f037b0L, + 0x13f9b5a7d9a12a53L } }, + /* 4 << 147 */ + { { 0x0d0df6ce51efb310L,0xcb5b2eb4958df5beL,0xd6459e2936158e59L, + 0x82aae2b91466e336L }, + { 0xfb658a39411aa636L,0x7152ecc5d4c0a933L,0xf10c758a49f026b7L, + 0xf4837f97cb09311fL } }, + /* 5 << 147 */ + { { 0xddfb02c4c753c45fL,0x18ca81b6f9c840feL,0x846fd09ab0f8a3e6L, + 0xb1162adde7733dbcL }, + { 0x7070ad20236e3ab6L,0xf88cdaf5b2a56326L,0x05fc8719997cbc7aL, + 0x442cd4524b665272L } }, + /* 6 << 147 */ + { { 0x7807f364b71698f5L,0x6ba418d29f7b605eL,0xfd20b00fa03b2cbbL, + 0x883eca37da54386fL }, + { 0xff0be43ff3437f24L,0xe910b432a48bb33cL,0x4963a128329df765L, + 0xac1dd556be2fe6f7L } }, + /* 7 << 147 */ + { { 0x557610f924a0a3fcL,0x38e17bf4e881c3f9L,0x6ba84fafed0dac99L, + 0xd4a222c359eeb918L }, + { 0xc79c1dbe13f542b6L,0x1fc65e0de425d457L,0xeffb754f1debb779L, + 0x638d8fd09e08af60L } }, + /* 8 << 147 */ + { { 0x994f523a626332d5L,0x7bc388335561bb44L,0x005ed4b03d845ea2L, + 0xd39d3ee1c2a1f08aL }, + { 0x6561fdd3e7676b0dL,0x620e35fffb706017L,0x36ce424ff264f9a8L, + 0xc4c3419fda2681f7L } }, + /* 9 << 147 */ + { { 0xfb6afd2f69beb6e8L,0x3a50b9936d700d03L,0xc840b2ad0c83a14fL, + 0x573207be54085befL }, + { 0x5af882e309fe7e5bL,0x957678a43b40a7e1L,0x172d4bdd543056e2L, + 0x9c1b26b40df13c0aL } }, + /* 10 << 147 */ + { { 0x1c30861cf405ff06L,0xebac86bd486e828bL,0xe791a971636933fcL, + 0x50e7c2be7aeee947L }, + { 0xc3d4a095fa90d767L,0xae60eb7be670ab7bL,0x17633a64397b056dL, + 0x93a21f33105012aaL } }, + /* 11 << 147 */ + { { 0x663c370babb88643L,0x91df36d722e21599L,0x183ba8358b761671L, + 0x381eea1d728f3bf1L }, + { 0xb9b2f1ba39966e6cL,0x7c464a28e7295492L,0x0fd5f70a09b26b7fL, + 0xa9aba1f9fbe009dfL } }, + /* 12 << 147 */ + { { 0x857c1f22369b87adL,0x3c00e5d932fca556L,0x1ad74cab90b06466L, + 0xa7112386550faaf2L }, + { 0x7435e1986d9bd5f5L,0x2dcc7e3859c3463fL,0xdc7df748ca7bd4b2L, + 0x13cd4c089dec2f31L } }, + /* 13 << 147 */ + { { 0x0d3b5df8e3237710L,0x0dadb26ecbd2f7b0L,0x9f5966abe4aa082bL, + 0x666ec8de350e966eL }, + { 0x1bfd1ed5ee524216L,0xcd93c59b41dab0b6L,0x658a8435d186d6baL, + 0x1b7d34d2159d1195L } }, + /* 14 << 147 */ + { { 0x5936e46022caf46bL,0x6a45dd8f9a96fe4fL,0xf7925434b98f474eL, + 0x414104120053ef15L }, + { 0x71cf8d1241de97bfL,0xb8547b61bd80bef4L,0xb47d3970c4db0037L, + 0xf1bcd328fef20dffL } }, + /* 15 << 147 */ + { { 0x31a92e0910caad67L,0x1f5919605531a1e1L,0x3bb852e05f4fc840L, + 0x63e297ca93a72c6cL }, + { 0x3c2b0b2e49abad67L,0x6ec405fced3db0d9L,0xdc14a5307fef1d40L, + 0xccd19846280896fcL } }, + /* 16 << 147 */ + { { 0x00f831769bb81648L,0xd69eb485653120d0L,0xd17d75f44ccabc62L, + 0x34a07f82b749fcb1L }, + { 0x2c3af787bbfb5554L,0xb06ed4d062e283f8L,0x5722889fa19213a0L, + 0x162b085edcf3c7b4L } }, + /* 17 << 147 */ + { { 0xbcaecb31e0dd3ecaL,0xc6237fbce52f13a5L,0xcc2b6b0327bac297L, + 0x2ae1cac5b917f54aL }, + { 0x474807d47845ae4fL,0xfec7dd92ce5972e0L,0xc3bd25411d7915bbL, + 0x66f85dc4d94907caL } }, + /* 18 << 147 */ + { { 0xd981b888bdbcf0caL,0xd75f5da6df279e9fL,0x128bbf247054e934L, + 0x3c6ff6e581db134bL }, + { 0x795b7cf4047d26e4L,0xf370f7b85049ec37L,0xc6712d4dced945afL, + 0xdf30b5ec095642bcL } }, + /* 19 << 147 */ + { { 0x9b034c624896246eL,0x5652c016ee90bbd1L,0xeb38636f87fedb73L, + 0x5e32f8470135a613L }, + { 0x0703b312cf933c83L,0xd05bb76e1a7f47e6L,0x825e4f0c949c2415L, + 0x569e56227250d6f8L } }, + /* 20 << 147 */ + { { 0xbbe9eb3a6568013eL,0x8dbd203f22f243fcL,0x9dbd7694b342734aL, + 0x8f6d12f846afa984L }, + { 0xb98610a2c9eade29L,0xbab4f32347dd0f18L,0x5779737b671c0d46L, + 0x10b6a7c6d3e0a42aL } }, + /* 21 << 147 */ + { { 0xfb19ddf33035b41cL,0xd336343f99c45895L,0x61fe493854c857e5L, + 0xc4d506beae4e57d5L }, + { 0x3cd8c8cbbbc33f75L,0x7281f08a9262c77dL,0x083f4ea6f11a2823L, + 0x8895041e9fba2e33L } }, + /* 22 << 147 */ + { { 0xfcdfea499c438edfL,0x7678dcc391edba44L,0xf07b3b87e2ba50f0L, + 0xc13888ef43948c1bL }, + { 0xc2135ad41140af42L,0x8e5104f3926ed1a7L,0xf24430cb88f6695fL, + 0x0ce0637b6d73c120L } }, + /* 23 << 147 */ + { { 0xb2db01e6fe631e8fL,0x1c5563d7d7bdd24bL,0x8daea3ba369ad44fL, + 0x000c81b68187a9f9L }, + { 0x5f48a951aae1fd9aL,0xe35626c78d5aed8aL,0x209527630498c622L, + 0x76d17634773aa504L } }, + /* 24 << 147 */ + { { 0x36d90ddaeb300f7aL,0x9dcf7dfcedb5e801L,0x645cb26874d5244cL, + 0xa127ee79348e3aa2L }, + { 0x488acc53575f1dbbL,0x95037e8580e6161eL,0x57e59283292650d0L, + 0xabe67d9914938216L } }, + /* 25 << 147 */ + { { 0x3c7f944b3f8e1065L,0xed908cb6330e8924L,0x08ee8fd56f530136L, + 0x2227b7d5d7ffc169L }, + { 0x4f55c893b5cd6dd5L,0x82225e11a62796e8L,0x5c6cead1cb18e12cL, + 0x4381ae0c84f5a51aL } }, + /* 26 << 147 */ + { { 0x345913d37fafa4c8L,0x3d9180820491aac0L,0x9347871f3e69264cL, + 0xbea9dd3cb4f4f0cdL }, + { 0xbda5d0673eadd3e7L,0x0033c1b80573bcd8L,0x255893795da2486cL, + 0xcb89ee5b86abbee7L } }, + /* 27 << 147 */ + { { 0x8fe0a8f322532e5dL,0xb6410ff0727dfc4cL,0x619b9d58226726dbL, + 0x5ec256697a2b2dc7L }, + { 0xaf4d2e064c3beb01L,0x852123d07acea556L,0x0e9470faf783487aL, + 0x75a7ea045664b3ebL } }, + /* 28 << 147 */ + { { 0x4ad78f356798e4baL,0x9214e6e5c7d0e091L,0xc420b488b1290403L, + 0x64049e0afc295749L }, + { 0x03ef5af13ae9841fL,0xdbe4ca19b0b662a6L,0x46845c5ffa453458L, + 0xf8dabf1910b66722L } }, + /* 29 << 147 */ + { { 0xb650f0aacce2793bL,0x71db851ec5ec47c1L,0x3eb78f3e3b234fa9L, + 0xb0c60f35fc0106ceL }, + { 0x05427121774eadbdL,0x25367fafce323863L,0x7541b5c9cd086976L, + 0x4ff069e2dc507ad1L } }, + /* 30 << 147 */ + { { 0x741452568776e667L,0x6e76142cb23c6bb5L,0xdbf307121b3a8a87L, + 0x60e7363e98450836L }, + { 0x5741450eb7366d80L,0xe4ee14ca4837dbdfL,0xa765eb9b69d4316fL, + 0x04548dca8ef43825L } }, + /* 31 << 147 */ + { { 0x9c9f4e4c5ae888ebL,0x733abb5156e9ac99L,0xdaad3c20ba6ac029L, + 0x9b8dd3d32ba3e38eL }, + { 0xa9bb4c920bc5d11aL,0xf20127a79c5f88a3L,0x4f52b06e161d3cb8L, + 0x26c1ff096afaf0a6L } }, + /* 32 << 147 */ + { { 0x32670d2f7189e71fL,0xc64387485ecf91e7L,0x15758e57db757a21L, + 0x427d09f8290a9ce5L }, + { 0x846a308f38384a7aL,0xaac3acb4b0732b99L,0x9e94100917845819L, + 0x95cba111a7ce5e03L } }, + /* 33 << 147 */ + { { 0x6f3d4f7fb00009c4L,0xb8396c278ff28b5fL,0xb1a9ae431c97975dL, + 0x9d7ba8afe5d9fed5L }, + { 0x338cf09f34f485b6L,0xbc0ddacc64122516L,0xa450da1205d471feL, + 0x4c3a6250628dd8c9L } }, + /* 34 << 147 */ + { { 0x69c7d103d1295837L,0xa2893e503807eb2fL,0xd6e1e1debdb41491L, + 0xc630745b5e138235L }, + { 0xc892109e48661ae1L,0x8d17e7ebea2b2674L,0x00ec0f87c328d6b5L, + 0x6d858645f079ff9eL } }, + /* 35 << 147 */ + { { 0x6cdf243e19115eadL,0x1ce1393e4bac4fcfL,0x2c960ed09c29f25bL, + 0x59be4d8e9d388a05L }, + { 0x0d46e06cd0def72bL,0xb923db5de0342748L,0xf7d3aacd936d4a3dL, + 0x558519cc0b0b099eL } }, + /* 36 << 147 */ + { { 0x3ea8ebf8827097efL,0x259353dbd054f55dL,0x84c89abc6d2ed089L, + 0x5c548b698e096a7cL }, + { 0xd587f616994b995dL,0x4d1531f6a5845601L,0x792ab31e451fd9f0L, + 0xc8b57bb265adf6caL } }, + /* 37 << 147 */ + { { 0x68440fcb1cd5ad73L,0xb9c860e66144da4fL,0x2ab286aa8462beb8L, + 0xcc6b8fffef46797fL }, + { 0xac820da420c8a471L,0x69ae05a177ff7fafL,0xb9163f39bfb5da77L, + 0xbd03e5902c73ab7aL } }, + /* 38 << 147 */ + { { 0x7e862b5eb2940d9eL,0x3c663d864b9af564L,0xd8309031bde3033dL, + 0x298231b2d42c5bc6L }, + { 0x42090d2c552ad093L,0xa4799d1cff854695L,0x0a88b5d6d31f0d00L, + 0xf8b40825a2f26b46L } }, + /* 39 << 147 */ + { { 0xec29b1edf1bd7218L,0xd491c53b4b24c86eL,0xd2fe588f3395ea65L, + 0x6f3764f74456ef15L }, + { 0xdb43116dcdc34800L,0xcdbcd456c1e33955L,0xefdb554074ab286bL, + 0x948c7a51d18c5d7cL } }, + /* 40 << 147 */ + { { 0xeb81aa377378058eL,0x41c746a104411154L,0xa10c73bcfb828ac7L, + 0x6439be919d972b29L }, + { 0x4bf3b4b043a2fbadL,0x39e6dadf82b5e840L,0x4f7164086397bd4cL, + 0x0f7de5687f1eeccbL } }, + /* 41 << 147 */ + { { 0x5865c5a1d2ffbfc1L,0xf74211fa4ccb6451L,0x66368a88c0b32558L, + 0x5b539dc29ad7812eL }, + { 0x579483d02f3af6f6L,0x5213207899934eceL,0x50b9650fdcc9e983L, + 0xca989ec9aee42b8aL } }, + /* 42 << 147 */ + { { 0x6a44c829d6f62f99L,0x8f06a3094c2a7c0cL,0x4ea2b3a098a0cb0aL, + 0x5c547b70beee8364L }, + { 0x461d40e1682afe11L,0x9e0fc77a7b41c0a8L,0x79e4aefde20d5d36L, + 0x2916e52032dd9f63L } }, + /* 43 << 147 */ + { { 0xf59e52e83f883fafL,0x396f96392b868d35L,0xc902a9df4ca19881L, + 0x0fc96822db2401a6L }, + { 0x4123758766f1c68dL,0x10fc6de3fb476c0dL,0xf8b6b579841f5d90L, + 0x2ba8446cfa24f44aL } }, + /* 44 << 147 */ + { { 0xa237b920ef4a9975L,0x60bb60042330435fL,0xd6f4ab5acfb7e7b5L, + 0xb2ac509783435391L }, + { 0xf036ee2fb0d1ea67L,0xae779a6a74c56230L,0x59bff8c8ab838ae6L, + 0xcd83ca999b38e6f0L } }, + /* 45 << 147 */ + { { 0xbb27bef5e33deed3L,0xe6356f6f001892a8L,0xbf3be6cc7adfbd3eL, + 0xaecbc81c33d1ac9dL }, + { 0xe4feb909e6e861dcL,0x90a247a453f5f801L,0x01c50acb27346e57L, + 0xce29242e461acc1bL } }, + /* 46 << 147 */ + { { 0x04dd214a2f998a91L,0x271ee9b1d4baf27bL,0x7e3027d1e8c26722L, + 0x21d1645c1820dce5L }, + { 0x086f242c7501779cL,0xf0061407fa0e8009L,0xf23ce47760187129L, + 0x05bbdedb0fde9bd0L } }, + /* 47 << 147 */ + { { 0x682f483225d98473L,0xf207fe855c658427L,0xb6fdd7ba4166ffa1L, + 0x0c3140569eed799dL }, + { 0x0db8048f4107e28fL,0x74ed387141216840L,0x74489f8f56a3c06eL, + 0x1e1c005b12777134L } }, + /* 48 << 147 */ + { { 0xdb332a73f37ec3c3L,0xc65259bddd59eba0L,0x2291709cdb4d3257L, + 0x9a793b25bd389390L }, + { 0xf39fe34be43756f0L,0x2f76bdce9afb56c9L,0x9f37867a61208b27L, + 0xea1d4307089972c3L } }, + /* 49 << 147 */ + { { 0x8c5953308bdf623aL,0x5f5accda8441fb7dL,0xfafa941832ddfd95L, + 0x6ad40c5a0fde9be7L }, + { 0x43faba89aeca8709L,0xc64a7cf12c248a9dL,0x1662025272637a76L, + 0xaee1c79122b8d1bbL } }, + /* 50 << 147 */ + { { 0xf0f798fd21a843b2L,0x56e4ed4d8d005cb1L,0x355f77801f0d8abeL, + 0x197b04cf34522326L }, + { 0x41f9b31ffd42c13fL,0x5ef7feb2b40f933dL,0x27326f425d60bad4L, + 0x027ecdb28c92cf89L } }, + /* 51 << 147 */ + { { 0x04aae4d14e3352feL,0x08414d2f73591b90L,0x5ed6124eb7da7d60L, + 0xb985b9314d13d4ecL }, + { 0xa592d3ab96bf36f9L,0x012dbed5bbdf51dfL,0xa57963c0df6c177dL, + 0x010ec86987ca29cfL } }, + /* 52 << 147 */ + { { 0xba1700f6bf926dffL,0x7c9fdbd1f4bf6bc2L,0xdc18dc8f64da11f5L, + 0xa6074b7ad938ae75L }, + { 0x14270066e84f44a4L,0x99998d38d27b954eL,0xc1be8ab2b4f38e9aL, + 0x8bb55bbf15c01016L } }, + /* 53 << 147 */ + { { 0xf73472b40ea2ab30L,0xd365a340f73d68ddL,0xc01a716819c2e1ebL, + 0x32f49e3734061719L }, + { 0xb73c57f101d8b4d6L,0x03c8423c26b47700L,0x321d0bc8a4d8826aL, + 0x6004213c4bc0e638L } }, + /* 54 << 147 */ + { { 0xf78c64a1c1c06681L,0x16e0a16fef018e50L,0x31cbdf91db42b2b3L, + 0xf8f4ffcee0d36f58L }, + { 0xcdcc71cd4cc5e3e0L,0xd55c7cfaa129e3e0L,0xccdb6ba00fb2cbf1L, + 0x6aba0005c4bce3cbL } }, + /* 55 << 147 */ + { { 0x501cdb30d232cfc4L,0x9ddcf12ed58a3cefL,0x02d2cf9c87e09149L, + 0xdc5d7ec72c976257L }, + { 0x6447986e0b50d7ddL,0x88fdbaf7807f112aL,0x58c9822ab00ae9f6L, + 0x6abfb9506d3d27e0L } }, + /* 56 << 147 */ + { { 0xd0a744878a429f4fL,0x0649712bdb516609L,0xb826ba57e769b5dfL, + 0x82335df21fc7aaf2L }, + { 0x2389f0675c93d995L,0x59ac367a68677be6L,0xa77985ff21d9951bL, + 0x038956fb85011cceL } }, + /* 57 << 147 */ + { { 0x608e48cbbb734e37L,0xc08c0bf22be5b26fL,0x17bbdd3bf9b1a0d9L, + 0xeac7d89810483319L }, + { 0xc95c4bafbc1a6deaL,0xfdd0e2bf172aafdbL,0x40373cbc8235c41aL, + 0x14303f21fb6f41d5L } }, + /* 58 << 147 */ + { { 0xba0636210408f237L,0xcad3b09aecd2d1edL,0x4667855a52abb6a2L, + 0xba9157dcaa8b417bL }, + { 0xfe7f35074f013efbL,0x1b112c4baa38c4a2L,0xa1406a609ba64345L, + 0xe53cba336993c80bL } }, + /* 59 << 147 */ + { { 0x45466063ded40d23L,0x3d5f1f4d54908e25L,0x9ebefe62403c3c31L, + 0x274ea0b50672a624L }, + { 0xff818d99451d1b71L,0x80e826438f79cf79L,0xa165df1373ce37f5L, + 0xa744ef4ffe3a21fdL } }, + /* 60 << 147 */ + { { 0x73f1e7f5cf551396L,0xc616898e868c676bL,0x671c28c78c442c36L, + 0xcfe5e5585e0a317dL }, + { 0x1242d8187051f476L,0x56fad2a614f03442L,0x262068bc0a44d0f6L, + 0xdfa2cd6ece6edf4eL } }, + /* 61 << 147 */ + { { 0x0f43813ad15d1517L,0x61214cb2377d44f5L,0xd399aa29c639b35fL, + 0x42136d7154c51c19L }, + { 0x9774711b08417221L,0x0a5546b352545a57L,0x80624c411150582dL, + 0x9ec5c418fbc555bcL } }, + /* 62 << 147 */ + { { 0x2c87dcad771849f1L,0xb0c932c501d7bf6fL,0x6aa5cd3e89116eb2L, + 0xd378c25a51ca7bd3L }, + { 0xc612a0da9e6e3e31L,0x0417a54db68ad5d0L,0x00451e4a22c6edb8L, + 0x9fbfe019b42827ceL } }, + /* 63 << 147 */ + { { 0x2fa92505ba9384a2L,0x21b8596e64ad69c1L,0x8f4fcc49983b35a6L, + 0xde09376072754672L }, + { 0x2f14ccc8f7bffe6dL,0x27566bff5d94263dL,0xb5b4e9c62df3ec30L, + 0x94f1d7d53e6ea6baL } }, + /* 64 << 147 */ + { { 0x97b7851aaaca5e9bL,0x518aa52156713b97L,0x3357e8c7150a61f6L, + 0x7842e7e2ec2c2b69L }, + { 0x8dffaf656868a548L,0xd963bd82e068fc81L,0x64da5c8b65917733L, + 0x927090ff7b247328L } }, + /* 0 << 154 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 154 */ + { { 0x214bc9a7d298c241L,0xe3b697ba56807cfdL,0xef1c78024564eadbL, + 0xdde8cdcfb48149c5L }, + { 0x946bf0a75a4d2604L,0x27154d7f6c1538afL,0x95cc9230de5b1fccL, + 0xd88519e966864f82L } }, + /* 2 << 154 */ + { { 0xb828dd1a7cb1282cL,0xa08d7626be46973aL,0x6baf8d40e708d6b2L, + 0x72571fa14daeb3f3L }, + { 0x85b1732ff22dfd98L,0x87ab01a70087108dL,0xaaaafea85988207aL, + 0xccc832f869f00755L } }, + /* 3 << 154 */ + { { 0x964d950e36ff3bf0L,0x8ad20f6ff0b34638L,0x4d9177b3b5d7585fL, + 0xcf839760ef3f019fL }, + { 0x582fc5b38288c545L,0x2f8e4e9b13116bd1L,0xf91e1b2f332120efL, + 0xcf5687242a17dd23L } }, + /* 4 << 154 */ + { { 0x488f1185ca8d9d1aL,0xadf2c77dd987ded2L,0x5f3039f060c46124L, + 0xe5d70b7571e095f4L }, + { 0x82d586506260e70fL,0x39d75ea7f750d105L,0x8cf3d0b175bac364L, + 0xf3a7564d21d01329L } }, + /* 5 << 154 */ + { { 0x182f04cd2f52d2a7L,0x4fde149ae2df565aL,0xb80c5eeca79fb2f7L, + 0xab491d7b22ddc897L }, + { 0x99d76c18c6312c7fL,0xca0d5f3d6aa41a57L,0x71207325d15363a0L, + 0xe82aa265beb252c2L } }, + /* 6 << 154 */ + { { 0x94ab4700ec3128c2L,0x6c76d8628e383f49L,0xdc36b150c03024ebL, + 0xfb43947753daac69L }, + { 0xfc68764a8dc79623L,0x5b86995db440fbb2L,0xd66879bfccc5ee0dL, + 0x0522894295aa8bd3L } }, + /* 7 << 154 */ + { { 0xb51a40a51e6a75c1L,0x24327c760ea7d817L,0x0663018207774597L, + 0xd6fdbec397fa7164L }, + { 0x20c99dfb13c90f48L,0xd6ac5273686ef263L,0xc6a50bdcfef64eebL, + 0xcd87b28186fdfc32L } }, + /* 8 << 154 */ + { { 0xb24aa43e3fcd3efcL,0xdd26c034b8088e9aL,0xa5ef4dc9bd3d46eaL, + 0xa2f99d588a4c6a6fL }, + { 0xddabd3552f1da46cL,0x72c3f8ce1afacdd1L,0xd90c4eee92d40578L, + 0xd28bb41fca623b94L } }, + /* 9 << 154 */ + { { 0x50fc0711745edc11L,0x9dd9ad7d3dc87558L,0xce6931fbb49d1e64L, + 0x6c77a0a2c98bd0f9L }, + { 0x62b9a6296baf7cb1L,0xcf065f91ccf72d22L,0x7203cce979639071L, + 0x09ae4885f9cb732fL } }, + /* 10 << 154 */ + { { 0x5e7c3becee8314f3L,0x1c068aeddbea298fL,0x08d381f17c80acecL, + 0x03b56be8e330495bL }, + { 0xaeffb8f29222882dL,0x95ff38f6c4af8bf7L,0x50e32d351fc57d8cL, + 0x6635be5217b444f0L } }, + /* 11 << 154 */ + { { 0x04d15276a5177900L,0x4e1dbb47f6858752L,0x5b475622c615796cL, + 0xa6fa0387691867bfL }, + { 0xed7f5d562844c6d0L,0xc633cf9b03a2477dL,0xf6be5c402d3721d6L, + 0xaf312eb7e9fd68e6L } }, + /* 12 << 154 */ + { { 0x242792d2e7417ce1L,0xff42bc71970ee7f5L,0x1ff4dc6d5c67a41eL, + 0x77709b7b20882a58L }, + { 0x3554731dbe217f2cL,0x2af2a8cd5bb72177L,0x58eee769591dd059L, + 0xbb2930c94bba6477L } }, + /* 13 << 154 */ + { { 0x863ee0477d930cfcL,0x4c262ad1396fd1f4L,0xf4765bc8039af7e1L, + 0x2519834b5ba104f6L }, + { 0x7cd61b4cd105f961L,0xa5415da5d63bca54L,0x778280a088a1f17cL, + 0xc49689492329512cL } }, + /* 14 << 154 */ + { { 0x174a9126cecdaa7aL,0xfc8c7e0e0b13247bL,0x29c110d23484c1c4L, + 0xf8eb8757831dfc3bL }, + { 0x022f0212c0067452L,0x3f6f69ee7b9b926cL,0x09032da0ef42daf4L, + 0x79f00ade83f80de4L } }, + /* 15 << 154 */ + { { 0x6210db7181236c97L,0x74f7685b3ee0781fL,0x4df7da7ba3e41372L, + 0x2aae38b1b1a1553eL }, + { 0x1688e222f6dd9d1bL,0x576954485b8b6487L,0x478d21274b2edeaaL, + 0xb2818fa51e85956aL } }, + /* 16 << 154 */ + { { 0x1e6adddaf176f2c0L,0x01ca4604e2572658L,0x0a404ded85342ffbL, + 0x8cf60f96441838d6L }, + { 0x9bbc691cc9071c4aL,0xfd58874434442803L,0x97101c85809c0d81L, + 0xa7fb754c8c456f7fL } }, + /* 17 << 154 */ + { { 0xc95f3c5cd51805e1L,0xab4ccd39b299dca8L,0x3e03d20b47eaf500L, + 0xfa3165c1d7b80893L }, + { 0x005e8b54e160e552L,0xdc4972ba9019d11fL,0x21a6972e0c9a4a7aL, + 0xa52c258f37840fd7L } }, + /* 18 << 154 */ + { { 0xf8559ff4c1e99d81L,0x08e1a7d6a3c617c0L,0xb398fd43248c6ba7L, + 0x6ffedd91d1283794L }, + { 0x8a6a59d2d629d208L,0xa9d141d53490530eL,0x42f6fc1838505989L, + 0x09bf250d479d94eeL } }, + /* 19 << 154 */ + { { 0x223ad3b1b3822790L,0x6c5926c093b8971cL,0x609efc7e75f7fa62L, + 0x45d66a6d1ec2d989L }, + { 0x4422d663987d2792L,0x4a73caad3eb31d2bL,0xf06c2ac1a32cb9e6L, + 0xd9445c5f91aeba84L } }, + /* 20 << 154 */ + { { 0x6af7a1d5af71013fL,0xe68216e50bedc946L,0xf4cba30bd27370a0L, + 0x7981afbf870421ccL }, + { 0x02496a679449f0e1L,0x86cfc4be0a47edaeL,0x3073c936b1feca22L, + 0xf569461203f8f8fbL } }, + /* 21 << 154 */ + { { 0xd063b723901515eaL,0x4c6c77a5749cf038L,0x6361e360ab9e5059L, + 0x596cf171a76a37c0L }, + { 0x800f53fa6530ae7aL,0x0f5e631e0792a7a6L,0x5cc29c24efdb81c9L, + 0xa269e8683f9c40baL } }, + /* 22 << 154 */ + { { 0xec14f9e12cb7191eL,0x78ea1bd8e5b08ea6L,0x3c65aa9b46332bb9L, + 0x84cc22b3bf80ce25L }, + { 0x0098e9e9d49d5bf1L,0xcd4ec1c619087da4L,0x3c9d07c5aef6e357L, + 0x839a02689f8f64b8L } }, + /* 23 << 154 */ + { { 0xc5e9eb62c6d8607fL,0x759689f56aa995e4L,0x70464669bbb48317L, + 0x921474bfe402417dL }, + { 0xcabe135b2a354c8cL,0xd51e52d2812fa4b5L,0xec74109653311fe8L, + 0x4f774535b864514bL } }, + /* 24 << 154 */ + { { 0xbcadd6715bde48f8L,0xc97038732189bc7dL,0x5d45299ec709ee8aL, + 0xd1287ee2845aaff8L }, + { 0x7d1f8874db1dbf1fL,0xea46588b990c88d6L,0x60ba649a84368313L, + 0xd5fdcbce60d543aeL } }, + /* 25 << 154 */ + { { 0x90b46d43810d5ab0L,0x6739d8f904d7e5ccL,0x021c1a580d337c33L, + 0x00a6116268e67c40L }, + { 0x95ef413b379f0a1fL,0xfe126605e9e2ab95L,0x67578b852f5f199cL, + 0xf5c003292cb84913L } }, + /* 26 << 154 */ + { { 0xf795643037577dd8L,0x83b82af429c5fe88L,0x9c1bea26cdbdc132L, + 0x589fa0869c04339eL }, + { 0x033e9538b13799dfL,0x85fa8b21d295d034L,0xdf17f73fbd9ddccaL, + 0xf32bd122ddb66334L } }, + /* 27 << 154 */ + { { 0x55ef88a7858b044cL,0x1f0d69c25aa9e397L,0x55fd9cc340d85559L, + 0xc774df727785ddb2L }, + { 0x5dcce9f6d3bd2e1cL,0xeb30da20a85dfed0L,0x5ed7f5bbd3ed09c4L, + 0x7d42a35c82a9c1bdL } }, + /* 28 << 154 */ + { { 0xcf3de9959890272dL,0x75f3432a3e713a10L,0x5e13479fe28227b8L, + 0xb8561ea9fefacdc8L }, + { 0xa6a297a08332aafdL,0x9b0d8bb573809b62L,0xd2fa1cfd0c63036fL, + 0x7a16eb55bd64bda8L } }, + /* 29 << 154 */ + { { 0x3f5cf5f678e62ddcL,0x2267c45407fd752bL,0x5e361b6b5e437bbeL, + 0x95c595018354e075L }, + { 0xec725f85f2b254d9L,0x844b617d2cb52b4eL,0xed8554f5cf425fb5L, + 0xab67703e2af9f312L } }, + /* 30 << 154 */ + { { 0x4cc34ec13cf48283L,0xb09daa259c8a705eL,0xd1e9d0d05b7d4f84L, + 0x4df6ef64db38929dL }, + { 0xe16b0763aa21ba46L,0xc6b1d178a293f8fbL,0x0ff5b602d520aabfL, + 0x94d671bdc339397aL } }, + /* 31 << 154 */ + { { 0x7c7d98cf4f5792faL,0x7c5e0d6711215261L,0x9b19a631a7c5a6d4L, + 0xc8511a627a45274dL }, + { 0x0c16621ca5a60d99L,0xf7fbab88cf5e48cbL,0xab1e6ca2f7ddee08L, + 0x83bd08cee7867f3cL } }, + /* 32 << 154 */ + { { 0xf7e48e8a2ac13e27L,0x4494f6df4eb1a9f5L,0xedbf84eb981f0a62L, + 0x49badc32536438f0L }, + { 0x50bea541004f7571L,0xbac67d10df1c94eeL,0x253d73a1b727bc31L, + 0xb3d01cf230686e28L } }, + /* 33 << 154 */ + { { 0x51b77b1b55fd0b8bL,0xa099d183feec3173L,0x202b1fb7670e72b7L, + 0xadc88b33a8e1635fL }, + { 0x34e8216af989d905L,0xc2e68d2029b58d01L,0x11f81c926fe55a93L, + 0x15f1462a8f296f40L } }, + /* 34 << 154 */ + { { 0x1915d375ea3d62f2L,0xa17765a301c8977dL,0x7559710ae47b26f6L, + 0xe0bd29c8535077a5L }, + { 0x615f976d08d84858L,0x370dfe8569ced5c1L,0xbbc7503ca734fa56L, + 0xfbb9f1ec91ac4574L } }, + /* 35 << 154 */ + { { 0x95d7ec53060dd7efL,0xeef2dacd6e657979L,0x54511af3e2a08235L, + 0x1e324aa41f4aea3dL }, + { 0x550e7e71e6e67671L,0xbccd5190bf52faf7L,0xf880d316223cc62aL, + 0x0d402c7e2b32eb5dL } }, + /* 36 << 154 */ + { { 0xa40bc039306a5a3bL,0x4e0a41fd96783a1bL,0xa1e8d39a0253cdd4L, + 0x6480be26c7388638L }, + { 0xee365e1d2285f382L,0x188d8d8fec0b5c36L,0x34ef1a481f0f4d82L, + 0x1a8f43e1a487d29aL } }, + /* 37 << 154 */ + { { 0x8168226d77aefb3aL,0xf69a751e1e72c253L,0x8e04359ae9594df1L, + 0x475ffd7dd14c0467L }, + { 0xb5a2c2b13844e95cL,0x85caf647dd12ef94L,0x1ecd2a9ff1063d00L, + 0x1dd2e22923843311L } }, + /* 38 << 154 */ + { { 0x38f0e09d73d17244L,0x3ede77468fc653f1L,0xae4459f5dc20e21cL, + 0x00db2ffa6a8599eaL }, + { 0x11682c3930cfd905L,0x4934d074a5c112a6L,0xbdf063c5568bfe95L, + 0x779a440a016c441aL } }, + /* 39 << 154 */ + { { 0x0c23f21897d6fbdcL,0xd3a5cd87e0776aacL,0xcee37f72d712e8dbL, + 0xfb28c70d26f74e8dL }, + { 0xffe0c728b61301a0L,0xa6282168d3724354L,0x7ff4cb00768ffedcL, + 0xc51b308803b02de9L } }, + /* 40 << 154 */ + { { 0xa5a8147c3902dda5L,0x35d2f706fe6973b4L,0x5ac2efcfc257457eL, + 0x933f48d48700611bL }, + { 0xc365af884912beb2L,0x7f5a4de6162edf94L,0xc646ba7c0c32f34bL, + 0x632c6af3b2091074L } }, + /* 41 << 154 */ + { { 0x58d4f2e3753e43a9L,0x70e1d21724d4e23fL,0xb24bf729afede6a6L, + 0x7f4a94d8710c8b60L }, + { 0xaad90a968d4faa6aL,0xd9ed0b32b066b690L,0x52fcd37b78b6dbfdL, + 0x0b64615e8bd2b431L } }, + /* 42 << 154 */ + { { 0x228e2048cfb9fad5L,0xbeaa386d240b76bdL,0x2d6681c890dad7bcL, + 0x3e553fc306d38f5eL }, + { 0xf27cdb9b9d5f9750L,0x3e85c52ad28c5b0eL,0x190795af5247c39bL, + 0x547831ebbddd6828L } }, + /* 43 << 154 */ + { { 0xf327a2274a82f424L,0x36919c787e47f89dL,0xe478391943c7392cL, + 0xf101b9aa2316fefeL }, + { 0xbcdc9e9c1c5009d2L,0xfb55ea139cd18345L,0xf5b5e231a3ce77c7L, + 0xde6b4527d2f2cb3dL } }, + /* 44 << 154 */ + { { 0x10f6a3339bb26f5fL,0x1e85db8e044d85b6L,0xc3697a0894197e54L, + 0x65e18cc0a7cb4ea8L }, + { 0xa38c4f50a471fe6eL,0xf031747a2f13439cL,0x53c4a6bac007318bL, + 0xa8da3ee51deccb3dL } }, + /* 45 << 154 */ + { { 0x0555b31c558216b1L,0x90c7810c2f79e6c2L,0x9b669f4dfe8eed3cL, + 0x70398ec8e0fac126L }, + { 0xa96a449ef701b235L,0x0ceecdb3eb94f395L,0x285fc368d0cb7431L, + 0x0d37bb5216a18c64L } }, + /* 46 << 154 */ + { { 0x05110d38b880d2ddL,0xa60f177b65930d57L,0x7da34a67f36235f5L, + 0x47f5e17c183816b9L }, + { 0xc7664b57db394af4L,0x39ba215d7036f789L,0x46d2ca0e2f27b472L, + 0xc42647eef73a84b7L } }, + /* 47 << 154 */ + { { 0x44bc754564488f1dL,0xaa922708f4cf85d5L,0x721a01d553e4df63L, + 0x649c0c515db46cedL }, + { 0x6bf0d64e3cffcb6cL,0xe3bf93fe50f71d96L,0x75044558bcc194a0L, + 0x16ae33726afdc554L } }, + /* 48 << 154 */ + { { 0xbfc01adf5ca48f3fL,0x64352f06e22a9b84L,0xcee54da1c1099e4aL, + 0xbbda54e8fa1b89c0L }, + { 0x166a3df56f6e55fbL,0x1ca44a2420176f88L,0x936afd88dfb7b5ffL, + 0xe34c24378611d4a0L } }, + /* 49 << 154 */ + { { 0x7effbb7586142103L,0x6704ba1b1f34fc4dL,0x7c2a468f10c1b122L, + 0x36b3a6108c6aace9L }, + { 0xabfcc0a775a0d050L,0x066f91973ce33e32L,0xce905ef429fe09beL, + 0x89ee25baa8376351L } }, + /* 50 << 154 */ + { { 0x2a3ede22fd29dc76L,0x7fd32ed936f17260L,0x0cadcf68284b4126L, + 0x63422f08a7951fc8L }, + { 0x562b24f40807e199L,0xfe9ce5d122ad4490L,0xc2f51b100db2b1b4L, + 0xeb3613ffe4541d0dL } }, + /* 51 << 154 */ + { { 0xbd2c4a052680813bL,0x527aa55d561b08d6L,0xa9f8a40ea7205558L, + 0xe3eea56f243d0becL }, + { 0x7b853817a0ff58b3L,0xb67d3f651a69e627L,0x0b76bbb9a869b5d6L, + 0xa3afeb82546723edL } }, + /* 52 << 154 */ + { { 0x5f24416d3e554892L,0x8413b53d430e2a45L,0x99c56aee9032a2a0L, + 0x09432bf6eec367b1L }, + { 0x552850c6daf0ecc1L,0x49ebce555bc92048L,0xdfb66ba654811307L, + 0x1b84f7976f298597L } }, + /* 53 << 154 */ + { { 0x795904818d1d7a0dL,0xd9fabe033a6fa556L,0xa40f9c59ba9e5d35L, + 0xcb1771c1f6247577L }, + { 0x542a47cae9a6312bL,0xa34b3560552dd8c5L,0xfdf94de00d794716L, + 0xd46124a99c623094L } }, + /* 54 << 154 */ + { { 0x56b7435d68afe8b4L,0x27f205406c0d8ea1L,0x12b77e1473186898L, + 0xdbc3dd467479490fL }, + { 0x951a9842c03b0c05L,0x8b1b3bb37921bc96L,0xa573b3462b202e0aL, + 0x77e4665d47254d56L } }, + /* 55 << 154 */ + { { 0x08b70dfcd23e3984L,0xab86e8bcebd14236L,0xaa3e07f857114ba7L, + 0x5ac71689ab0ef4f2L }, + { 0x88fca3840139d9afL,0x72733f8876644af0L,0xf122f72a65d74f4aL, + 0x13931577a5626c7aL } }, + /* 56 << 154 */ + { { 0xd5b5d9eb70f8d5a4L,0x375adde7d7bbb228L,0x31e88b860c1c0b32L, + 0xd1f568c4173edbaaL }, + { 0x1592fc835459df02L,0x2beac0fb0fcd9a7eL,0xb0a6fdb81b473b0aL, + 0xe3224c6f0fe8fc48L } }, + /* 57 << 154 */ + { { 0x680bd00ee87edf5bL,0x30385f0220e77cf5L,0xe9ab98c04d42d1b2L, + 0x72d191d2d3816d77L }, + { 0x1564daca0917d9e5L,0x394eab591f8fed7fL,0xa209aa8d7fbb3896L, + 0x5564f3b9be6ac98eL } }, + /* 58 << 154 */ + { { 0xead21d05d73654efL,0x68d1a9c413d78d74L,0x61e017086d4973a0L, + 0x83da350046e6d32aL }, + { 0x6a3dfca468ae0118L,0xa1b9a4c9d02da069L,0x0b2ff9c7ebab8302L, + 0x98af07c3944ba436L } }, + /* 59 << 154 */ + { { 0x85997326995f0f9fL,0x467fade071b58bc6L,0x47e4495abd625a2bL, + 0xfdd2d01d33c3b8cdL }, + { 0x2c38ae28c693f9faL,0x48622329348f7999L,0x97bf738e2161f583L, + 0x15ee2fa7565e8cc9L } }, + /* 60 << 154 */ + { { 0xa1a5c8455777e189L,0xcc10bee0456f2829L,0x8ad95c56da762bd5L, + 0x152e2214e9d91da8L }, + { 0x975b0e727cb23c74L,0xfd5d7670a90c66dfL,0xb5b5b8ad225ffc53L, + 0xab6dff73faded2aeL } }, + /* 61 << 154 */ + { { 0xebd567816f4cbe9dL,0x0ed8b2496a574bd7L,0x41c246fe81a881faL, + 0x91564805c3db9c70L }, + { 0xd7c12b085b862809L,0x1facd1f155858d7bL,0x7693747caf09e92aL, + 0x3b69dcba189a425fL } }, + /* 62 << 154 */ + { { 0x0be28e9f967365efL,0x57300eb2e801f5c9L,0x93b8ac6ad583352fL, + 0xa2cf1f89cd05b2b7L }, + { 0x7c0c9b744dcc40ccL,0xfee38c45ada523fbL,0xb49a4dec1099cc4dL, + 0x325c377f69f069c6L } }, + /* 63 << 154 */ + { { 0xe12458ce476cc9ffL,0x580e0b6cc6d4cb63L,0xd561c8b79072289bL, + 0x0377f264a619e6daL }, + { 0x2668536288e591a5L,0xa453a7bd7523ca2bL,0x8a9536d2c1df4533L, + 0xc8e50f2fbe972f79L } }, + /* 64 << 154 */ + { { 0xd433e50f6d3549cfL,0x6f33696ffacd665eL,0x695bfdacce11fcb4L, + 0x810ee252af7c9860L }, + { 0x65450fe17159bb2cL,0xf7dfbebe758b357bL,0x2b057e74d69fea72L, + 0xd485717a92731745L } }, + /* 0 << 161 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 161 */ + { { 0x896c42e8ee36860cL,0xdaf04dfd4113c22dL,0x1adbb7b744104213L, + 0xe5fd5fa11fd394eaL }, + { 0x68235d941a4e0551L,0x6772cfbe18d10151L,0x276071e309984523L, + 0xe4e879de5a56ba98L } }, + /* 2 << 161 */ + { { 0xaaafafb0285b9491L,0x01a0be881e4c705eL,0xff1d4f5d2ad9caabL, + 0x6e349a4ac37a233fL }, + { 0xcf1c12464a1c6a16L,0xd99e6b6629383260L,0xea3d43665f6d5471L, + 0x36974d04ff8cc89bL } }, + /* 3 << 161 */ + { { 0xc26c49a1cfe89d80L,0xb42c026dda9c8371L,0xca6c013adad066d2L, + 0xfb8f722856a4f3eeL }, + { 0x08b579ecd850935bL,0x34c1a74cd631e1b3L,0xcb5fe596ac198534L, + 0x39ff21f6e1f24f25L } }, + /* 4 << 161 */ + { { 0x27f29e148f929057L,0x7a64ae06c0c853dfL,0x256cd18358e9c5ceL, + 0x9d9cce82ded092a5L }, + { 0xcc6e59796e93b7c7L,0xe1e4709231bb9e27L,0xb70b3083aa9e29a0L, + 0xbf181a753785e644L } }, + /* 5 << 161 */ + { { 0xf53f2c658ead09f7L,0x1335e1d59780d14dL,0x69cc20e0cd1b66bcL, + 0x9b670a37bbe0bfc8L }, + { 0xce53dc8128efbeedL,0x0c74e77c8326a6e5L,0x3604e0d2b88e9a63L, + 0xbab38fca13dc2248L } }, + /* 6 << 161 */ + { { 0x8ed6e8c85c0a3f1eL,0xbcad24927c87c37fL,0xfdfb62bb9ee3b78dL, + 0xeba8e477cbceba46L }, + { 0x37d38cb0eeaede4bL,0x0bc498e87976deb6L,0xb2944c046b6147fbL, + 0x8b123f35f71f9609L } }, + /* 7 << 161 */ + { { 0xa155dcc7de79dc24L,0xf1168a32558f69cdL,0xbac215950d1850dfL, + 0x15c8295bb204c848L }, + { 0xf661aa367d8184ffL,0xc396228e30447bdbL,0x11cd5143bde4a59eL, + 0xe3a26e3b6beab5e6L } }, + /* 8 << 161 */ + { { 0xd3b3a13f1402b9d0L,0x573441c32c7bc863L,0x4b301ec4578c3e6eL, + 0xc26fc9c40adaf57eL }, + { 0x96e71bfd7493cea3L,0xd05d4b3f1af81456L,0xdaca2a8a6a8c608fL, + 0x53ef07f60725b276L } }, + /* 9 << 161 */ + { { 0x07a5fbd27824fc56L,0x3467521813289077L,0x5bf69fd5e0c48349L, + 0xa613ddd3b6aa7875L }, + { 0x7f78c19c5450d866L,0x46f4409c8f84a481L,0x9f1d192890fce239L, + 0x016c4168b2ce44b9L } }, + /* 10 << 161 */ + { { 0xbae023f0c7435978L,0xb152c88820e30e19L,0x9c241645e3fa6fafL, + 0x735d95c184823e60L }, + { 0x0319757303955317L,0x0b4b02a9f03b4995L,0x076bf55970274600L, + 0x32c5cc53aaf57508L } }, + /* 11 << 161 */ + { { 0xe8af6d1f60624129L,0xb7bc5d649a5e2b5eL,0x3814b0485f082d72L, + 0x76f267f2ce19677aL }, + { 0x626c630fb36eed93L,0x55230cd73bf56803L,0x78837949ce2736a0L, + 0x0d792d60aa6c55f1L } }, + /* 12 << 161 */ + { { 0x0318dbfdd5c7c5d2L,0xb38f8da7072b342dL,0x3569bddc7b8de38aL, + 0xf25b5887a1c94842L }, + { 0xb2d5b2842946ad60L,0x854f29ade9d1707eL,0xaa5159dc2c6a4509L, + 0x899f94c057189837L } }, + /* 13 << 161 */ + { { 0xcf6adc51f4a55b03L,0x261762de35e3b2d5L,0x4cc4301204827b51L, + 0xcd22a113c6021442L }, + { 0xce2fd61a247c9569L,0x59a50973d152becaL,0x6c835a1163a716d4L, + 0xc26455ed187dedcfL } }, + /* 14 << 161 */ + { { 0x27f536e049ce89e7L,0x18908539cc890cb5L,0x308909abd83c2aa1L, + 0xecd3142b1ab73bd3L }, + { 0x6a85bf59b3f5ab84L,0x3c320a68f2bea4c6L,0xad8dc5386da4541fL, + 0xeaf34eb0b7c41186L } }, + /* 15 << 161 */ + { { 0x1c780129977c97c4L,0x5ff9beebc57eb9faL,0xa24d0524c822c478L, + 0xfd8eec2a461cd415L }, + { 0xfbde194ef027458cL,0xb4ff53191d1be115L,0x63f874d94866d6f4L, + 0x35c75015b21ad0c9L } }, + /* 16 << 161 */ + { { 0xa6b5c9d646ac49d2L,0x42c77c0b83137aa9L,0x24d000fc68225a38L, + 0x0f63cfc82fe1e907L }, + { 0x22d1b01bc6441f95L,0x7d38f719ec8e448fL,0x9b33fa5f787fb1baL, + 0x94dcfda1190158dfL } }, + /* 17 << 161 */ + { { 0xc47cb3395f6d4a09L,0x6b4f355cee52b826L,0x3d100f5df51b930aL, + 0xf4512fac9f668f69L }, + { 0x546781d5206c4c74L,0xd021d4d4cb4d2e48L,0x494a54c2ca085c2dL, + 0xf1dbaca4520850a8L } }, + /* 18 << 161 */ + { { 0x63c79326490a1acaL,0xcb64dd9c41526b02L,0xbb772591a2979258L, + 0x3f58297048d97846L }, + { 0xd66b70d17c213ba7L,0xc28febb5e8a0ced4L,0x6b911831c10338c1L, + 0x0d54e389bf0126f3L } }, + /* 19 << 161 */ + { { 0x7048d4604af206eeL,0x786c88f677e97cb9L,0xd4375ae1ac64802eL, + 0x469bcfe1d53ec11cL }, + { 0xfc9b340d47062230L,0xe743bb57c5b4a3acL,0xfe00b4aa59ef45acL, + 0x29a4ef2359edf188L } }, + /* 20 << 161 */ + { { 0x40242efeb483689bL,0x2575d3f6513ac262L,0xf30037c80ca6db72L, + 0xc9fcce8298864be2L }, + { 0x84a112ff0149362dL,0x95e575821c4ae971L,0x1fa4b1a8945cf86cL, + 0x4525a7340b024a2fL } }, + /* 21 << 161 */ + { { 0xe76c8b628f338360L,0x483ff59328edf32bL,0x67e8e90a298b1aecL, + 0x9caab338736d9a21L }, + { 0x5c09d2fd66892709L,0x2496b4dcb55a1d41L,0x93f5fb1ae24a4394L, + 0x08c750496fa8f6c1L } }, + /* 22 << 161 */ + { { 0xcaead1c2c905d85fL,0xe9d7f7900733ae57L,0x24c9a65cf07cdd94L, + 0x7389359ca4b55931L }, + { 0xf58709b7367e45f7L,0x1f203067cb7e7adcL,0x82444bffc7b72818L, + 0x07303b35baac8033L } }, + /* 23 << 161 */ + { { 0x1e1ee4e4d13b7ea1L,0xe6489b24e0e74180L,0xa5f2c6107e70ef70L, + 0xa1655412bdd10894L }, + { 0x555ebefb7af4194eL,0x533c1c3c8e89bd9cL,0x735b9b5789895856L, + 0x15fb3cd2567f5c15L } }, + /* 24 << 161 */ + { { 0x057fed45526f09fdL,0xe8a4f10c8128240aL,0x9332efc4ff2bfd8dL, + 0x214e77a0bd35aa31L }, + { 0x32896d7314faa40eL,0x767867ec01e5f186L,0xc9adf8f117a1813eL, + 0xcb6cda7854741795L } }, + /* 25 << 161 */ + { { 0xb7521b6d349d51aaL,0xf56b5a9ee3c7b8e9L,0xc6f1e5c932a096dfL, + 0x083667c4a3635024L }, + { 0x365ea13518087f2fL,0xf1b8eaacd136e45dL,0xc8a0e48473aec989L, + 0xd75a324b142c9259L } }, + /* 26 << 161 */ + { { 0xb7b4d00101dae185L,0x45434e0b9b7a94bcL,0xf54339affbd8cb0bL, + 0xdcc4569ee98ef49eL }, + { 0x7789318a09a51299L,0x81b4d206b2b025d8L,0xf64aa418fae85792L, + 0x3e50258facd7baf7L } }, + /* 27 << 161 */ + { { 0xdce84cdb2996864bL,0xa2e670891f485fa4L,0xb28b2bb6534c6a5aL, + 0x31a7ec6bc94b9d39L }, + { 0x1d217766d6bc20daL,0x4acdb5ec86761190L,0x6872632873701063L, + 0x4d24ee7c2128c29bL } }, + /* 28 << 161 */ + { { 0xc072ebd3a19fd868L,0x612e481cdb8ddd3bL,0xb4e1d7541a64d852L, + 0x00ef95acc4c6c4abL }, + { 0x1536d2edaa0a6c46L,0x6129408643774790L,0x54af25e8343fda10L, + 0x9ff9d98dfd25d6f2L } }, + /* 29 << 161 */ + { { 0x0746af7c468b8835L,0x977a31cb730ecea7L,0xa5096b80c2cf4a81L, + 0xaa9868336458c37aL }, + { 0x6af29bf3a6bd9d34L,0x6a62fe9b33c5d854L,0x50e6c304b7133b5eL, + 0x04b601597d6e6848L } }, + /* 30 << 161 */ + { { 0x4cd296df5579bea4L,0x10e35ac85ceedaf1L,0x04c4c5fde3bcc5b1L, + 0x95f9ee8a89412cf9L }, + { 0x2c9459ee82b6eb0fL,0x2e84576595c2aaddL,0x774a84aed327fcfeL, + 0xd8c937220368d476L } }, + /* 31 << 161 */ + { { 0x0dbd5748f83e8a3bL,0xa579aa968d2495f3L,0x535996a0ae496e9bL, + 0x07afbfe9b7f9bcc2L }, + { 0x3ac1dc6d5b7bd293L,0x3b592cff7022323dL,0xba0deb989c0a3e76L, + 0x18e78e9f4b197acbL } }, + /* 32 << 161 */ + { { 0x211cde10296c36efL,0x7ee8967282c4da77L,0xb617d270a57836daL, + 0xf0cd9c319cb7560bL }, + { 0x01fdcbf7e455fe90L,0x3fb53cbb7e7334f3L,0x781e2ea44e7de4ecL, + 0x8adab3ad0b384fd0L } }, + /* 33 << 161 */ + { { 0x129eee2f53d64829L,0x7a471e17a261492bL,0xe4f9adb9e4cb4a2cL, + 0x3d359f6f97ba2c2dL }, + { 0x346c67860aacd697L,0x92b444c375c2f8a8L,0xc79fa117d85df44eL, + 0x56782372398ddf31L } }, + /* 34 << 161 */ + { { 0x60e690f2bbbab3b8L,0x4851f8ae8b04816bL,0xc72046ab9c92e4d2L, + 0x518c74a17cf3136bL }, + { 0xff4eb50af9877d4cL,0x14578d90a919cabbL,0x8218f8c4ac5eb2b6L, + 0xa3ccc547542016e4L } }, + /* 35 << 161 */ + { { 0x025bf48e327f8349L,0xf3e97346f43cb641L,0xdc2bafdf500f1085L, + 0x571678762f063055L }, + { 0x5bd914b9411925a6L,0x7c078d48a1123de5L,0xee6bf835182b165dL, + 0xb11b5e5bba519727L } }, + /* 36 << 161 */ + { { 0xe33ea76c1eea7b85L,0x2352b46192d4f85eL,0xf101d334afe115bbL, + 0xfabc1294889175a3L }, + { 0x7f6bcdc05233f925L,0xe0a802dbe77fec55L,0xbdb47b758069b659L, + 0x1c5e12def98fbd74L } }, + /* 37 << 161 */ + { { 0x869c58c64b8457eeL,0xa5360f694f7ea9f7L,0xe576c09ff460b38fL, + 0x6b70d54822b7fb36L }, + { 0x3fd237f13bfae315L,0x33797852cbdff369L,0x97df25f525b516f9L, + 0x46f388f2ba38ad2dL } }, + /* 38 << 161 */ + { { 0x656c465889d8ddbbL,0x8830b26e70f38ee8L,0x4320fd5cde1212b0L, + 0xc34f30cfe4a2edb2L }, + { 0xabb131a356ab64b8L,0x7f77f0ccd99c5d26L,0x66856a37bf981d94L, + 0x19e76d09738bd76eL } }, + /* 39 << 161 */ + { { 0xe76c8ac396238f39L,0xc0a482bea830b366L,0xb7b8eaff0b4eb499L, + 0x8ecd83bc4bfb4865L }, + { 0x971b2cb7a2f3776fL,0xb42176a4f4b88adfL,0xb9617df5be1fa446L, + 0x8b32d508cd031bd2L } }, + /* 40 << 161 */ + { { 0x1c6bd47d53b618c0L,0xc424f46c6a227923L,0x7303ffdedd92d964L, + 0xe971287871b5abf2L }, + { 0x8f48a632f815561dL,0x85f48ff5d3c055d1L,0x222a14277525684fL, + 0xd0d841a067360cc3L } }, + /* 41 << 161 */ + { { 0x4245a9260b9267c6L,0xc78913f1cf07f863L,0xaa844c8e4d0d9e24L, + 0xa42ad5223d5f9017L }, + { 0xbd371749a2c989d5L,0x928292dfe1f5e78eL,0x493b383e0a1ea6daL, + 0x5136fd8d13aee529L } }, + /* 42 << 161 */ + { { 0x860c44b1f2c34a99L,0x3b00aca4bf5855acL,0xabf6aaa0faaf37beL, + 0x65f436822a53ec08L }, + { 0x1d9a5801a11b12e1L,0x78a7ab2ce20ed475L,0x0de1067e9a41e0d5L, + 0x30473f5f305023eaL } }, + /* 43 << 161 */ + { { 0xdd3ae09d169c7d97L,0x5cd5baa4cfaef9cdL,0x5cd7440b65a44803L, + 0xdc13966a47f364deL }, + { 0x077b2be82b8357c1L,0x0cb1b4c5e9d57c2aL,0x7a4ceb3205ff363eL, + 0xf310fa4dca35a9efL } }, + /* 44 << 161 */ + { { 0xdbb7b352f97f68c6L,0x0c773b500b02cf58L,0xea2e48213c1f96d9L, + 0xffb357b0eee01815L }, + { 0xb9c924cde0f28039L,0x0b36c95a46a3fbe4L,0x1faaaea45e46db6cL, + 0xcae575c31928aaffL } }, + /* 45 << 161 */ + { { 0x7f671302a70dab86L,0xfcbd12a971c58cfcL,0xcbef9acfbee0cb92L, + 0x573da0b9f8c1b583L }, + { 0x4752fcfe0d41d550L,0xe7eec0e32155cffeL,0x0fc39fcb545ae248L, + 0x522cb8d18065f44eL } }, + /* 46 << 161 */ + { { 0x263c962a70cbb96cL,0xe034362abcd124a9L,0xf120db283c2ae58dL, + 0xb9a38d49fef6d507L }, + { 0xb1fd2a821ff140fdL,0xbd162f3020aee7e0L,0x4e17a5d4cb251949L, + 0x2aebcb834f7e1c3dL } }, + /* 47 << 161 */ + { { 0x608eb25f937b0527L,0xf42e1e47eb7d9997L,0xeba699c4b8a53a29L, + 0x1f921c71e091b536L }, + { 0xcce29e7b5b26bbd5L,0x7a8ef5ed3b61a680L,0xe5ef8043ba1f1c7eL, + 0x16ea821718158ddaL } }, + /* 48 << 161 */ + { { 0x01778a2b599ff0f9L,0x68a923d78104fc6bL,0x5bfa44dfda694ff3L, + 0x4f7199dbf7667f12L }, + { 0xc06d8ff6e46f2a79L,0x08b5deade9f8131dL,0x02519a59abb4ce7cL, + 0xc4f710bcb42aec3eL } }, + /* 49 << 161 */ + { { 0x3d77b05778bde41aL,0x6474bf80b4186b5aL,0x048b3f6788c65741L, + 0xc64519de03c7c154L }, + { 0xdf0738460edfcc4fL,0x319aa73748f1aa6bL,0x8b9f8a02ca909f77L, + 0x902581397580bfefL } }, + /* 50 << 161 */ + { { 0xd8bfd3cac0c22719L,0xc60209e4c9ca151eL,0x7a744ab5d9a1a69cL, + 0x6de5048b14937f8fL }, + { 0x171938d8e115ac04L,0x7df709401c6b16d2L,0xa6aeb6637f8e94e7L, + 0xc130388e2a2cf094L } }, + /* 51 << 161 */ + { { 0x1850be8477f54e6eL,0x9f258a7265d60fe5L,0xff7ff0c06c9146d6L, + 0x039aaf90e63a830bL }, + { 0x38f27a739460342fL,0x4703148c3f795f8aL,0x1bb5467b9681a97eL, + 0x00931ba5ecaeb594L } }, + /* 52 << 161 */ + { { 0xcdb6719d786f337cL,0xd9c01cd2e704397dL,0x0f4a3f20555c2fefL, + 0x004525097c0af223L }, + { 0x54a5804784db8e76L,0x3bacf1aa93c8aa06L,0x11ca957cf7919422L, + 0x5064105378cdaa40L } }, + /* 53 << 161 */ + { { 0x7a3038749f7144aeL,0x170c963f43d4acfdL,0x5e14814958ddd3efL, + 0xa7bde5829e72dba8L }, + { 0x0769da8b6fa68750L,0xfa64e532572e0249L,0xfcaadf9d2619ad31L, + 0x87882daaa7b349cdL } }, + /* 54 << 161 */ + { { 0x9f6eb7316c67a775L,0xcb10471aefc5d0b1L,0xb433750ce1b806b2L, + 0x19c5714d57b1ae7eL }, + { 0xc0dc8b7bed03fd3fL,0xdd03344f31bc194eL,0xa66c52a78c6320b5L, + 0x8bc82ce3d0b6fd93L } }, + /* 55 << 161 */ + { { 0xf8e13501b35f1341L,0xe53156dd25a43e42L,0xd3adf27e4daeb85cL, + 0xb81d8379bbeddeb5L }, + { 0x1b0b546e2e435867L,0x9020eb94eba5dd60L,0x37d911618210cb9dL, + 0x4c596b315c91f1cfL } }, + /* 56 << 161 */ + { { 0xb228a90f0e0b040dL,0xbaf02d8245ff897fL,0x2aac79e600fa6122L, + 0x248288178e36f557L }, + { 0xb9521d31113ec356L,0x9e48861e15eff1f8L,0x2aa1d412e0d41715L, + 0x71f8620353f131b8L } }, + /* 57 << 161 */ + { { 0xf60da8da3fd19408L,0x4aa716dc278d9d99L,0x394531f7a8c51c90L, + 0xb560b0e8f59db51cL }, + { 0xa28fc992fa34bdadL,0xf024fa149cd4f8bdL,0x5cf530f723a9d0d3L, + 0x615ca193e28c9b56L } }, + /* 58 << 161 */ + { { 0x6d2a483d6f73c51eL,0xa4cb2412ea0dc2ddL,0x50663c411eb917ffL, + 0x3d3a74cfeade299eL }, + { 0x29b3990f4a7a9202L,0xa9bccf59a7b15c3dL,0x66a3ccdca5df9208L, + 0x48027c1443f2f929L } }, + /* 59 << 161 */ + { { 0xd385377c40b557f0L,0xe001c366cd684660L,0x1b18ed6be2183a27L, + 0x879738d863210329L }, + { 0xa687c74bbda94882L,0xd1bbcc48a684b299L,0xaf6f1112863b3724L, + 0x6943d1b42c8ce9f8L } }, + /* 60 << 161 */ + { { 0xe044a3bb098cafb4L,0x27ed231060d48cafL,0x542b56753a31b84dL, + 0xcbf3dd50fcddbed7L }, + { 0x25031f1641b1d830L,0xa7ec851dcb0c1e27L,0xac1c8fe0b5ae75dbL, + 0xb24c755708c52120L } }, + /* 61 << 161 */ + { { 0x57f811dc1d4636c3L,0xf8436526681a9939L,0x1f6bc6d99c81adb3L, + 0x840f8ac35b7d80d4L }, + { 0x731a9811f4387f1aL,0x7c501cd3b5156880L,0xa5ca4a07dfe68867L, + 0xf123d8f05fcea120L } }, + /* 62 << 161 */ + { { 0x1fbb0e71d607039eL,0x2b70e215cd3a4546L,0x32d2f01d53324091L, + 0xb796ff08180ab19bL }, + { 0x32d87a863c57c4aaL,0x2aed9cafb7c49a27L,0x9fb35eac31630d98L, + 0x338e8cdf5c3e20a3L } }, + /* 63 << 161 */ + { { 0x80f1618266cde8dbL,0x4e1599802d72fd36L,0xd7b8f13b9b6e5072L, + 0xf52139073b7b5dc1L }, + { 0x4d431f1d8ce4396eL,0x37a1a680a7ed2142L,0xbf375696d01aaf6bL, + 0xaa1c0c54e63aab66L } }, + /* 64 << 161 */ + { { 0x3014368b4ed80940L,0x67e6d0567a6fceddL,0x7c208c49ca97579fL, + 0xfe3d7a81a23597f6L }, + { 0x5e2032027e096ae2L,0xb1f3e1e724b39366L,0x26da26f32fdcdffcL, + 0x79422f1d6097be83L } }, + /* 0 << 168 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 168 */ + { { 0x263a2cfb9db3b381L,0x9c3a2deed4df0a4bL,0x728d06e97d04e61fL, + 0x8b1adfbc42449325L }, + { 0x6ec1d9397e053a1bL,0xee2be5c766daf707L,0x80ba1e14810ac7abL, + 0xdd2ae778f530f174L } }, + /* 2 << 168 */ + { { 0x0435d97a205b9d8bL,0x6eb8f064056756d4L,0xd5e88a8bb6f8210eL, + 0x070ef12dec9fd9eaL }, + { 0x4d8495053bcc876aL,0x12a75338a7404ce3L,0xd22b49e1b8a1db5eL, + 0xec1f205114bfa5adL } }, + /* 3 << 168 */ + { { 0xadbaeb79b6828f36L,0x9d7a025801bd5b9eL,0xeda01e0d1e844b0cL, + 0x4b625175887edfc9L }, + { 0x14109fdd9669b621L,0x88a2ca56f6f87b98L,0xfe2eb788170df6bcL, + 0x0cea06f4ffa473f9L } }, + /* 4 << 168 */ + { { 0x43ed81b5c4e83d33L,0xd9f358795efd488bL,0x164a620f9deb4d0fL, + 0xc6927bdbac6a7394L }, + { 0x45c28df79f9e0f03L,0x2868661efcd7e1a9L,0x7cf4e8d0ffa348f1L, + 0x6bd4c284398538e0L } }, + /* 5 << 168 */ + { { 0x2618a091289a8619L,0xef796e606671b173L,0x664e46e59090c632L, + 0xa38062d41e66f8fbL }, + { 0x6c744a200573274eL,0xd07b67e4a9271394L,0x391223b26bdc0e20L, + 0xbe2d93f1eb0a05a7L } }, + /* 6 << 168 */ + { { 0xf23e2e533f36d141L,0xe84bb3d44dfca442L,0xb804a48d6b7c023aL, + 0x1e16a8fa76431c3bL }, + { 0x1b5452adddd472e0L,0x7d405ee70d1ee127L,0x50fc6f1dffa27599L, + 0x351ac53cbf391b35L } }, + /* 7 << 168 */ + { { 0x7efa14b84444896bL,0x64974d2ff94027fbL,0xefdcd0e8de84487dL, + 0x8c45b2602b48989bL }, + { 0xa8fcbbc2d8463487L,0xd1b2b3f73fbc476cL,0x21d005b7c8f443c0L, + 0x518f2e6740c0139cL } }, + /* 8 << 168 */ + { { 0x56036e8c06d75fc1L,0x2dcf7bb73249a89fL,0x81dd1d3de245e7ddL, + 0xf578dc4bebd6e2a7L }, + { 0x4c028903df2ce7a0L,0xaee362889c39afacL,0xdc847c31146404abL, + 0x6304c0d8a4e97818L } }, + /* 9 << 168 */ + { { 0xae51dca2a91f6791L,0x2abe41909baa9efcL,0xd9d2e2f4559c7ac1L, + 0xe82f4b51fc9f773aL }, + { 0xa77130274073e81cL,0xc0276facfbb596fcL,0x1d819fc9a684f70cL, + 0x29b47fddc9f7b1e0L } }, + /* 10 << 168 */ + { { 0x358de103459b1940L,0xec881c595b013e93L,0x51574c9349532ad3L, + 0x2db1d445b37b46deL }, + { 0xc6445b87df239fd8L,0xc718af75151d24eeL,0xaea1c4a4f43c6259L, + 0x40c0e5d770be02f7L } }, + /* 11 << 168 */ + { { 0x6a4590f4721b33f2L,0x2124f1fbfedf04eaL,0xf8e53cde9745efe7L, + 0xe7e1043265f046d9L }, + { 0xc3fca28ee4d0c7e6L,0x847e339a87253b1bL,0x9b5953483743e643L, + 0xcb6a0a0b4fd12fc5L } }, + /* 12 << 168 */ + { { 0xfb6836c327d02dccL,0x5ad009827a68bcc2L,0x1b24b44c005e912dL, + 0xcc83d20f811fdcfeL }, + { 0x36527ec1666fba0cL,0x6994819714754635L,0xfcdcb1a8556da9c2L, + 0xa593426781a732b2L } }, + /* 13 << 168 */ + { { 0xec1214eda714181dL,0x609ac13b6067b341L,0xff4b4c97a545df1fL, + 0xa124050134d2076bL }, + { 0x6efa0c231409ca97L,0x254cc1a820638c43L,0xd4e363afdcfb46cdL, + 0x62c2adc303942a27L } }, + /* 14 << 168 */ + { { 0xc67b9df056e46483L,0xa55abb2063736356L,0xab93c098c551bc52L, + 0x382b49f9b15fe64bL }, + { 0x9ec221ad4dff8d47L,0x79caf615437df4d6L,0x5f13dc64bb456509L, + 0xe4c589d9191f0714L } }, + /* 15 << 168 */ + { { 0x27b6a8ab3fd40e09L,0xe455842e77313ea9L,0x8b51d1e21f55988bL, + 0x5716dd73062bbbfcL }, + { 0x633c11e54e8bf3deL,0x9a0e77b61b85be3bL,0x565107290911cca6L, + 0x27e76495efa6590fL } }, + /* 16 << 168 */ + { { 0xe4ac8b33070d3aabL,0x2643672b9a2cd5e5L,0x52eff79b1cfc9173L, + 0x665ca49b90a7c13fL }, + { 0x5a8dda59b3efb998L,0x8a5b922d052f1341L,0xae9ebbab3cf9a530L, + 0x35986e7bf56da4d7L } }, + /* 17 << 168 */ + { { 0x3a636b5cff3513ccL,0xbb0cf8ba3198f7ddL,0xb8d4052241f16f86L, + 0x760575d8de13a7bfL }, + { 0x36f74e169f7aa181L,0x163a3ecff509ed1cL,0x6aead61f3c40a491L, + 0x158c95fcdfe8fcaaL } }, + /* 18 << 168 */ + { { 0xa3991b6e13cda46fL,0x79482415342faed0L,0xf3ba5bde666b5970L, + 0x1d52e6bcb26ab6ddL }, + { 0x768ba1e78608dd3dL,0x4930db2aea076586L,0xd9575714e7dc1afaL, + 0x1fc7bf7df7c58817L } }, + /* 19 << 168 */ + { { 0x6b47accdd9eee96cL,0x0ca277fbe58cec37L,0x113fe413e702c42aL, + 0xdd1764eec47cbe51L }, + { 0x041e7cde7b3ed739L,0x50cb74595ce9e1c0L,0x355685132925b212L, + 0x7cff95c4001b081cL } }, + /* 20 << 168 */ + { { 0x63ee4cbd8088b454L,0xdb7f32f79a9e0c8aL,0xb377d4186b2447cbL, + 0xe3e982aad370219bL }, + { 0x06ccc1e4c2a2a593L,0x72c368650773f24fL,0xa13b4da795859423L, + 0x8bbf1d3375040c8fL } }, + /* 21 << 168 */ + { { 0x726f0973da50c991L,0x48afcd5b822d6ee2L,0xe5fc718b20fd7771L, + 0xb9e8e77dfd0807a1L }, + { 0x7f5e0f4499a7703dL,0x6972930e618e36f3L,0x2b7c77b823807bbeL, + 0xe5b82405cb27ff50L } }, + /* 22 << 168 */ + { { 0xba8b8be3bd379062L,0xd64b7a1d2dce4a92L,0x040a73c5b2952e37L, + 0x0a9e252ed438aecaL }, + { 0xdd43956bc39d3bcbL,0x1a31ca00b32b2d63L,0xd67133b85c417a18L, + 0xd08e47902ef442c8L } }, + /* 23 << 168 */ + { { 0x98cb1ae9255c0980L,0x4bd863812b4a739fL,0x5a5c31e11e4a45a1L, + 0x1e5d55fe9cb0db2fL }, + { 0x74661b068ff5cc29L,0x026b389f0eb8a4f4L,0x536b21a458848c24L, + 0x2e5bf8ec81dc72b0L } }, + /* 24 << 168 */ + { { 0x03c187d0ad886aacL,0x5c16878ab771b645L,0xb07dfc6fc74045abL, + 0x2c6360bf7800caedL }, + { 0x24295bb5b9c972a3L,0xc9e6f88e7c9a6dbaL,0x90ffbf2492a79aa6L, + 0xde29d50a41c26ac2L } }, + /* 25 << 168 */ + { { 0x9f0af483d309cbe6L,0x5b020d8ae0bced4fL,0x606e986db38023e3L, + 0xad8f2c9d1abc6933L }, + { 0x19292e1de7400e93L,0xfe3e18a952be5e4dL,0xe8e9771d2e0680bfL, + 0x8c5bec98c54db063L } }, + /* 26 << 168 */ + { { 0x2af9662a74a55d1fL,0xe3fbf28f046f66d8L,0xa3a72ab4d4dc4794L, + 0x09779f455c7c2dd8L }, + { 0xd893bdafc3d19d8dL,0xd5a7509457d6a6dfL,0x8cf8fef9952e6255L, + 0x3da67cfbda9a8affL } }, + /* 27 << 168 */ + { { 0x4c23f62a2c160dcdL,0x34e6c5e38f90eaefL,0x35865519a9a65d5aL, + 0x07c48aae8fd38a3dL }, + { 0xb7e7aeda50068527L,0x2c09ef231c90936aL,0x31ecfeb6e879324cL, + 0xa0871f6bfb0ec938L } }, + /* 28 << 168 */ + { { 0xb1f0fb68d84d835dL,0xc90caf39861dc1e6L,0x12e5b0467594f8d7L, + 0x26897ae265012b92L }, + { 0xbcf68a08a4d6755dL,0x403ee41c0991fbdaL,0x733e343e3bbf17e8L, + 0xd2c7980d679b3d65L } }, + /* 29 << 168 */ + { { 0x33056232d2e11305L,0x966be492f3c07a6fL,0x6a8878ffbb15509dL, + 0xff2211010a9b59a4L }, + { 0x6c9f564aabe30129L,0xc6f2c940336e64cfL,0x0fe752628b0c8022L, + 0xbe0267e96ae8db87L } }, + /* 30 << 168 */ + { { 0x22e192f193bc042bL,0xf085b534b237c458L,0xa0d192bd832c4168L, + 0x7a76e9e3bdf6271dL }, + { 0x52a882fab88911b5L,0xc85345e4b4db0eb5L,0xa3be02a681a7c3ffL, + 0x51889c8cf0ec0469L } }, + /* 31 << 168 */ + { { 0x9d031369a5e829e5L,0xcbb4c6fc1607aa41L,0x75ac59a6241d84c1L, + 0xc043f2bf8829e0eeL }, + { 0x82a38f758ea5e185L,0x8bda40b9d87cbd9fL,0x9e65e75e2d8fc601L, + 0x3d515f74a35690b3L } }, + /* 32 << 168 */ + { { 0x534acf4fda79e5acL,0x68b83b3a8630215fL,0x5c748b2ed085756eL, + 0xb0317258e5d37cb2L }, + { 0x6735841ac5ccc2c4L,0x7d7dc96b3d9d5069L,0xa147e410fd1754bdL, + 0x65296e94d399ddd5L } }, + /* 33 << 168 */ + { { 0xf6b5b2d0bc8fa5bcL,0x8a5ead67500c277bL,0x214625e6dfa08a5dL, + 0x51fdfedc959cf047L }, + { 0x6bc9430b289fca32L,0xe36ff0cf9d9bdc3fL,0x2fe187cb58ea0edeL, + 0xed66af205a900b3fL } }, + /* 34 << 168 */ + { { 0x00e0968b5fa9f4d6L,0x2d4066ce37a362e7L,0xa99a9748bd07e772L, + 0x710989c006a4f1d0L }, + { 0xd5dedf35ce40cbd8L,0xab55c5f01743293dL,0x766f11448aa24e2cL, + 0x94d874f8605fbcb4L } }, + /* 35 << 168 */ + { { 0xa365f0e8a518001bL,0xee605eb69d04ef0fL,0x5a3915cdba8d4d25L, + 0x44c0e1b8b5113472L }, + { 0xcbb024e88b6740dcL,0x89087a53ee1d4f0cL,0xa88fa05c1fc4e372L, + 0x8bf395cbaf8b3af2L } }, + /* 36 << 168 */ + { { 0x1e71c9a1deb8568bL,0xa35daea080fb3d32L,0xe8b6f2662cf8fb81L, + 0x6d51afe89490696aL }, + { 0x81beac6e51803a19L,0xe3d24b7f86219080L,0x727cfd9ddf6f463cL, + 0x8c6865ca72284ee8L } }, + /* 37 << 168 */ + { { 0x32c88b7db743f4efL,0x3793909be7d11dceL,0xd398f9222ff2ebe8L, + 0x2c70ca44e5e49796L }, + { 0xdf4d9929cb1131b1L,0x7826f29825888e79L,0x4d3a112cf1d8740aL, + 0x00384cb6270afa8bL } }, + /* 38 << 168 */ + { { 0xcb64125b3ab48095L,0x3451c25662d05106L,0xd73d577da4955845L, + 0x39570c16bf9f4433L }, + { 0xd7dfaad3adecf263L,0xf1c3d8d1dc76e102L,0x5e774a5854c6a836L, + 0xdad4b6723e92d47bL } }, + /* 39 << 168 */ + { { 0xbe7e990ff0d796a0L,0x5fc62478df0e8b02L,0x8aae8bf4030c00adL, + 0x3d2db93b9004ba0fL }, + { 0xe48c8a79d85d5ddcL,0xe907caa76bb07f34L,0x58db343aa39eaed5L, + 0x0ea6e007adaf5724L } }, + /* 40 << 168 */ + { { 0xe00df169d23233f3L,0x3e32279677cb637fL,0x1f897c0e1da0cf6cL, + 0xa651f5d831d6bbddL }, + { 0xdd61af191a230c76L,0xbd527272cdaa5e4aL,0xca753636d0abcd7eL, + 0x78bdd37c370bd8dcL } }, + /* 41 << 168 */ + { { 0xc23916c217cd93feL,0x65b97a4ddadce6e2L,0xe04ed4eb174e42f8L, + 0x1491ccaabb21480aL }, + { 0x145a828023196332L,0x3c3862d7587b479aL,0x9f4a88a301dcd0edL, + 0x4da2b7ef3ea12f1fL } }, + /* 42 << 168 */ + { { 0xf8e7ae33b126e48eL,0x404a0b32f494e237L,0x9beac474c55acadbL, + 0x4ee5cf3bcbec9fd9L }, + { 0x336b33b97df3c8c3L,0xbd905fe3b76808fdL,0x8f436981aa45c16aL, + 0x255c5bfa3dd27b62L } }, + /* 43 << 168 */ + { { 0x71965cbfc3dd9b4dL,0xce23edbffc068a87L,0xb78d4725745b029bL, + 0x74610713cefdd9bdL }, + { 0x7116f75f1266bf52L,0x0204672218e49bb6L,0xdf43df9f3d6f19e3L, + 0xef1bc7d0e685cb2fL } }, + /* 44 << 168 */ + { { 0xcddb27c17078c432L,0xe1961b9cb77fedb7L,0x1edc2f5cc2290570L, + 0x2c3fefca19cbd886L }, + { 0xcf880a36c2af389aL,0x96c610fdbda71ceaL,0xf03977a932aa8463L, + 0x8eb7763f8586d90aL } }, + /* 45 << 168 */ + { { 0x3f3424542a296e77L,0xc871868342837a35L,0x7dc710906a09c731L, + 0x54778ffb51b816dbL }, + { 0x6b33bfecaf06defdL,0xfe3c105f8592b70bL,0xf937fda461da6114L, + 0x3c13e6514c266ad7L } }, + /* 46 << 168 */ + { { 0xe363a829855938e8L,0x2eeb5d9e9de54b72L,0xbeb93b0e20ccfab9L, + 0x3dffbb5f25e61a25L }, + { 0x7f655e431acc093dL,0x0cb6cc3d3964ce61L,0x6ab283a1e5e9b460L, + 0x55d787c5a1c7e72dL } }, + /* 47 << 168 */ + { { 0x4d2efd47deadbf02L,0x11e80219ac459068L,0x810c762671f311f0L, + 0xfa17ef8d4ab6ef53L }, + { 0xaf47fd2593e43bffL,0x5cb5ff3f0be40632L,0x546871068ee61da3L, + 0x7764196eb08afd0fL } }, + /* 48 << 168 */ + { { 0x831ab3edf0290a8fL,0xcae81966cb47c387L,0xaad7dece184efb4fL, + 0xdcfc53b34749110eL }, + { 0x6698f23c4cb632f9L,0xc42a1ad6b91f8067L,0xb116a81d6284180aL, + 0xebedf5f8e901326fL } }, + /* 49 << 168 */ + { { 0xf2274c9f97e3e044L,0x4201852011d09fc9L,0x56a65f17d18e6e23L, + 0x2ea61e2a352b683cL }, + { 0x27d291bc575eaa94L,0x9e7bc721b8ff522dL,0x5f7268bfa7f04d6fL, + 0x5868c73faba41748L } }, + /* 50 << 168 */ + { { 0x9f85c2db7be0eeadL,0x511e7842ff719135L,0x5a06b1e9c5ea90d7L, + 0x0c19e28326fab631L }, + { 0x8af8f0cfe9206c55L,0x89389cb43553c06aL,0x39dbed97f65f8004L, + 0x0621b037c508991dL } }, + /* 51 << 168 */ + { { 0x1c52e63596e78cc4L,0x5385c8b20c06b4a8L,0xd84ddfdbb0e87d03L, + 0xc49dfb66934bafadL }, + { 0x7071e17059f70772L,0x3a073a843a1db56bL,0x034949033b8af190L, + 0x7d882de3d32920f0L } }, + /* 52 << 168 */ + { { 0x91633f0ab2cf8940L,0x72b0b1786f948f51L,0x2d28dc30782653c8L, + 0x88829849db903a05L }, + { 0xb8095d0c6a19d2bbL,0x4b9e7f0c86f782cbL,0x7af739882d907064L, + 0xd12be0fe8b32643cL } }, + /* 53 << 168 */ + { { 0x358ed23d0e165dc3L,0x3d47ce624e2378ceL,0x7e2bb0b9feb8a087L, + 0x3246e8aee29e10b9L }, + { 0x459f4ec703ce2b4dL,0xe9b4ca1bbbc077cfL,0x2613b4f20e9940c1L, + 0xfc598bb9047d1eb1L } }, + /* 54 << 168 */ + { { 0x9744c62b45036099L,0xa9dee742167c65d8L,0x0c511525dabe1943L, + 0xda11055493c6c624L }, + { 0xae00a52c651a3be2L,0xcda5111d884449a6L,0x063c06f4ff33bed1L, + 0x73baaf9a0d3d76b4L } }, + /* 55 << 168 */ + { { 0x52fb0c9d7fc63668L,0x6886c9dd0c039cdeL,0x602bd59955b22351L, + 0xb00cab02360c7c13L }, + { 0x8cb616bc81b69442L,0x41486700b55c3ceeL,0x71093281f49ba278L, + 0xad956d9c64a50710L } }, + /* 56 << 168 */ + { { 0x9561f28b638a7e81L,0x54155cdf5980ddc3L,0xb2db4a96d26f247aL, + 0x9d774e4e4787d100L }, + { 0x1a9e6e2e078637d2L,0x1c363e2d5e0ae06aL,0x7493483ee9cfa354L, + 0x76843cb37f74b98dL } }, + /* 57 << 168 */ + { { 0xbaca6591d4b66947L,0xb452ce9804460a8cL,0x6830d24643768f55L, + 0xf4197ed87dff12dfL }, + { 0x6521b472400dd0f7L,0x59f5ca8f4b1e7093L,0x6feff11b080338aeL, + 0x0ada31f6a29ca3c6L } }, + /* 58 << 168 */ + { { 0x24794eb694a2c215L,0xd83a43ab05a57ab4L,0x264a543a2a6f89feL, + 0x2c2a3868dd5ec7c2L }, + { 0xd33739408439d9b2L,0x715ea6720acd1f11L,0x42c1d235e7e6cc19L, + 0x81ce6e96b990585cL } }, + /* 59 << 168 */ + { { 0x04e5dfe0d809c7bdL,0xd7b2580c8f1050abL,0x6d91ad78d8a4176fL, + 0x0af556ee4e2e897cL }, + { 0x162a8b73921de0acL,0x52ac9c227ea78400L,0xee2a4eeaefce2174L, + 0xbe61844e6d637f79L } }, + /* 60 << 168 */ + { { 0x0491f1bc789a283bL,0x72d3ac3d880836f4L,0xaa1c5ea388e5402dL, + 0x1b192421d5cc473dL }, + { 0x5c0b99989dc84cacL,0xb0a8482d9c6e75b8L,0x639961d03a191ce2L, + 0xda3bc8656d837930L } }, + /* 61 << 168 */ + { { 0xca990653056e6f8fL,0x84861c4164d133a7L,0x8b403276746abe40L, + 0xb7b4d51aebf8e303L }, + { 0x05b43211220a255dL,0xc997152c02419e6eL,0x76ff47b6630c2feaL, + 0x50518677281fdadeL } }, + /* 62 << 168 */ + { { 0x3283b8bacf902b0bL,0x8d4b4eb537db303bL,0xcc89f42d755011bcL, + 0xb43d74bbdd09d19bL }, + { 0x65746bc98adba350L,0x364eaf8cb51c1927L,0x13c7659610ad72ecL, + 0x30045121f8d40c20L } }, + /* 63 << 168 */ + { { 0x6d2d99b7ea7b979bL,0xcd78cd74e6fb3bcdL,0x11e45a9e86cffbfeL, + 0x78a61cf4637024f6L }, + { 0xd06bc8723d502295L,0xf1376854458cb288L,0xb9db26a1342f8586L, + 0xf33effcf4beee09eL } }, + /* 64 << 168 */ + { { 0xd7e0c4cdb30cfb3aL,0x6d09b8c16c9db4c8L,0x40ba1a4207c8d9dfL, + 0x6fd495f71c52c66dL }, + { 0xfb0e169f275264daL,0x80c2b746e57d8362L,0xedd987f749ad7222L, + 0xfdc229af4398ec7bL } }, + /* 0 << 175 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 175 */ + { { 0xb0d1ed8452666a58L,0x4bcb6e00e6a9c3c2L,0x3c57411c26906408L, + 0xcfc2075513556400L }, + { 0xa08b1c505294dba3L,0xa30ba2868b7dd31eL,0xd70ba90e991eca74L, + 0x094e142ce762c2b9L } }, + /* 2 << 175 */ + { { 0xb81d783e979f3925L,0x1efd130aaf4c89a7L,0x525c2144fd1bf7faL, + 0x4b2969041b265a9eL }, + { 0xed8e9634b9db65b6L,0x35c82e3203599d8aL,0xdaa7a54f403563f3L, + 0x9df088ad022c38abL } }, + /* 3 << 175 */ + { { 0xe5cfb066bb3fd30aL,0x429169daeff0354eL,0x809cf8523524e36cL, + 0x136f4fb30155be1dL }, + { 0x4826af011fbba712L,0x6ef0f0b4506ba1a1L,0xd9928b3177aea73eL, + 0xe2bf6af25eaa244eL } }, + /* 4 << 175 */ + { { 0x8d084f124237b64bL,0x688ebe99e3ecfd07L,0x57b8a70cf6845dd8L, + 0x808fc59c5da4a325L }, + { 0xa9032b2ba3585862L,0xb66825d5edf29386L,0xb5a5a8db431ec29bL, + 0xbb143a983a1e8dc8L } }, + /* 5 << 175 */ + { { 0x35ee94ce12ae381bL,0x3a7f176c86ccda90L,0xc63a657e4606eacaL, + 0x9ae5a38043cd04dfL }, + { 0x9bec8d15ed251b46L,0x1f5d6d30caca5e64L,0x347b3b359ff20f07L, + 0x4d65f034f7e4b286L } }, + /* 6 << 175 */ + { { 0x9e93ba24f111661eL,0xedced484b105eb04L,0x96dc9ba1f424b578L, + 0xbf8f66b7e83e9069L }, + { 0x872d4df4d7ed8216L,0xbf07f3778e2cbecfL,0x4281d89998e73754L, + 0xfec85fbb8aab8708L } }, + /* 7 << 175 */ + { { 0x9a3c0deea5ba5b0bL,0xe6a116ce42d05299L,0xae9775fee9b02d42L, + 0x72b05200a1545cb6L }, + { 0xbc506f7d31a3b4eaL,0xe58930788bbd9b32L,0xc8bc5f37e4b12a97L, + 0x6b000c064a73b671L } }, + /* 8 << 175 */ + { { 0x13b5bf22765fa7d0L,0x59805bf01d6a5370L,0x67a5e29d4280db98L, + 0x4f53916f776b1ce3L }, + { 0x714ff61f33ddf626L,0x4206238ea085d103L,0x1c50d4b7e5809ee3L, + 0x999f450d85f8eb1dL } }, + /* 9 << 175 */ + { { 0x658a6051e4c79e9bL,0x1394cb73c66a9feaL,0x27f31ed5c6be7b23L, + 0xf4c88f365aa6f8feL }, + { 0x0fb0721f4aaa499eL,0x68b3a7d5e3fb2a6bL,0xa788097d3a92851dL, + 0x060e7f8ae96f4913L } }, + /* 10 << 175 */ + { { 0x82eebe731a3a93bcL,0x42bbf465a21adc1aL,0xc10b6fa4ef030efdL, + 0x247aa4c787b097bbL }, + { 0x8b8dc632f60c77daL,0x6ffbc26ac223523eL,0xa4f6ff11344579cfL, + 0x5825653c980250f6L } }, + /* 11 << 175 */ + { { 0xb2dd097ebc1aa2b9L,0x0788939337a0333aL,0x1cf55e7137a0db38L, + 0x2648487f792c1613L }, + { 0xdad013363fcef261L,0x6239c81d0eabf129L,0x8ee761de9d276be2L, + 0x406a7a341eda6ad3L } }, + /* 12 << 175 */ + { { 0x4bf367ba4a493b31L,0x54f20a529bf7f026L,0xb696e0629795914bL, + 0xcddab96d8bf236acL }, + { 0x4ff2c70aed25ea13L,0xfa1d09eb81cbbbe7L,0x88fc8c87468544c5L, + 0x847a670d696b3317L } }, + /* 13 << 175 */ + { { 0xf133421e64bcb626L,0xaea638c826dee0b5L,0xd6e7680bb310346cL, + 0xe06f4097d5d4ced3L }, + { 0x099614527512a30bL,0xf3d867fde589a59aL,0x2e73254f52d0c180L, + 0x9063d8a3333c74acL } }, + /* 14 << 175 */ + { { 0xeda6c595d314e7bcL,0x2ee7464b467899edL,0x1cef423c0a1ed5d3L, + 0x217e76ea69cc7613L }, + { 0x27ccce1fe7cda917L,0x12d8016b8a893f16L,0xbcd6de849fc74f6bL, + 0xfa5817e2f3144e61L } }, + /* 15 << 175 */ + { { 0x1f3541640821ee4cL,0x1583eab40bc61992L,0x7490caf61d72879fL, + 0x998ad9f3f76ae7b2L }, + { 0x1e181950a41157f7L,0xa9d7e1e6e8da3a7eL,0x963784eb8426b95fL, + 0x0ee4ed6e542e2a10L } }, + /* 16 << 175 */ + { { 0xb79d4cc5ac751e7bL,0x93f96472fd4211bdL,0x8c72d3d2c8de4fc6L, + 0x7b69cbf5df44f064L }, + { 0x3da90ca2f4bf94e1L,0x1a5325f8f12894e2L,0x0a437f6c7917d60bL, + 0x9be7048696c9cb5dL } }, + /* 17 << 175 */ + { { 0xb4d880bfe1dc5c05L,0xd738addaeebeeb57L,0x6f0119d3df0fe6a3L, + 0x5c686e5566eaaf5aL }, + { 0x9cb10b50dfd0b7ecL,0xbdd0264b6a497c21L,0xfc0935148c546c96L, + 0x58a947fa79dbf42aL } }, + /* 18 << 175 */ + { { 0xc0b48d4e49ccd6d7L,0xff8fb02c88bd5580L,0xc75235e907d473b2L, + 0x4fab1ac5a2188af3L }, + { 0x030fa3bc97576ec0L,0xe8c946e80b7e7d2fL,0x40a5c9cc70305600L, + 0x6d8260a9c8b013b4L } }, + /* 19 << 175 */ + { { 0x0368304f70bba85cL,0xad090da1a4a0d311L,0x7170e8702415eec1L, + 0xbfba35fe8461ea47L }, + { 0x6279019ac1e91938L,0xa47638f31afc415fL,0x36c65cbbbcba0e0fL, + 0x02160efb034e2c48L } }, + /* 20 << 175 */ + { { 0xe6c51073615cd9e4L,0x498ec047f1243c06L,0x3e5a8809b17b3d8cL, + 0x5cd99e610cc565f1L }, + { 0x81e312df7851dafeL,0xf156f5baa79061e2L,0x80d62b71880c590eL, + 0xbec9746f0a39faa1L } }, + /* 21 << 175 */ + { { 0x1d98a9c1c8ed1f7aL,0x09e43bb5a81d5ff2L,0xd5f00f680da0794aL, + 0x412050d9661aa836L }, + { 0xa89f7c4e90747e40L,0x6dc05ebbb62a3686L,0xdf4de847308e3353L, + 0x53868fbb9fb53bb9L } }, + /* 22 << 175 */ + { { 0x2b09d2c3cfdcf7ddL,0x41a9fce3723fcab4L,0x73d905f707f57ca3L, + 0x080f9fb1ac8e1555L }, + { 0x7c088e849ba7a531L,0x07d35586ed9a147fL,0x602846abaf48c336L, + 0x7320fd320ccf0e79L } }, + /* 23 << 175 */ + { { 0xaa780798b18bd1ffL,0x52c2e300afdd2905L,0xf27ea3d6434267cdL, + 0x8b96d16d15605b5fL }, + { 0x7bb310494b45706bL,0xe7f58b8e743d25f8L,0xe9b5e45b87f30076L, + 0xd19448d65d053d5aL } }, + /* 24 << 175 */ + { { 0x1ecc8cb9d3210a04L,0x6bc7d463dafb5269L,0x3e59b10a67c3489fL, + 0x1769788c65641e1bL }, + { 0x8a53b82dbd6cb838L,0x7066d6e6236d5f22L,0x03aa1c616908536eL, + 0xc971da0d66ae9809L } }, + /* 25 << 175 */ + { { 0x01b3a86bc49a2facL,0x3b8420c03092e77aL,0x020573007d6fb556L, + 0x6941b2a1bff40a87L }, + { 0x140b63080658ff2aL,0x878043633424ab36L,0x0253bd515751e299L, + 0xc75bcd76449c3e3aL } }, + /* 26 << 175 */ + { { 0x92eb40907f8f875dL,0x9c9d754e56c26bbfL,0x158cea618110bbe7L, + 0x62a6b802745f91eaL }, + { 0xa79c41aac6e7394bL,0x445b6a83ad57ef10L,0x0c5277eb6ea6f40cL, + 0x319fe96b88633365L } }, + /* 27 << 175 */ + { { 0x0b0fc61f385f63cbL,0x41250c8422bdd127L,0x67d153f109e942c2L, + 0x60920d08c021ad5dL }, + { 0x229f5746724d81a5L,0xb7ffb8925bba3299L,0x518c51a1de413032L, + 0x2a9bfe773c2fd94cL } }, + /* 28 << 175 */ + { { 0xcbcde2393191f4fdL,0x43093e16d3d6ada1L,0x184579f358769606L, + 0x2c94a8b3d236625cL }, + { 0x6922b9c05c437d8eL,0x3d4ae423d8d9f3c8L,0xf72c31c12e7090a2L, + 0x4ac3f5f3d76a55bdL } }, + /* 29 << 175 */ + { { 0x342508fc6b6af991L,0x0d5271001b5cebbdL,0xb84740d0dd440dd7L, + 0x748ef841780162fdL }, + { 0xa8dbfe0edfc6fafbL,0xeadfdf05f7300f27L,0x7d06555ffeba4ec9L, + 0x12c56f839e25fa97L } }, + /* 30 << 175 */ + { { 0x77f84203d39b8c34L,0xed8b1be63125eddbL,0x5bbf2441f6e39dc5L, + 0xb00f6ee66a5d678aL }, + { 0xba456ecf57d0ea99L,0xdcae0f5817e06c43L,0x01643de40f5b4baaL, + 0x2c324341d161b9beL } }, + /* 31 << 175 */ + { { 0x80177f55e126d468L,0xed325f1f76748e09L,0x6116004acfa9bdc2L, + 0x2d8607e63a9fb468L }, + { 0x0e573e276009d660L,0x3a525d2e8d10c5a1L,0xd26cb45c3b9009a0L, + 0xb6b0cdc0de9d7448L } }, + /* 32 << 175 */ + { { 0x949c9976e1337c26L,0x6faadebdd73d68e5L,0x9e158614f1b768d9L, + 0x22dfa5579cc4f069L }, + { 0xccd6da17be93c6d6L,0x24866c61a504f5b9L,0x2121353c8d694da1L, + 0x1c6ca5800140b8c6L } }, + /* 33 << 175 */ + { { 0xc245ad8ce964021eL,0xb83bffba032b82b3L,0xfaa220c647ef9898L, + 0x7e8d3ac6982c948aL }, + { 0x1faa2091bc2d124aL,0xbd54c3dd05b15ff4L,0x386bf3abc87c6fb7L, + 0xfb2b0563fdeb6f66L } }, + /* 34 << 175 */ + { { 0x4e77c5575b45afb4L,0xe9ded649efb8912dL,0x7ec9bbf542f6e557L, + 0x2570dfff62671f00L }, + { 0x2b3bfb7888e084bdL,0xa024b238f37fe5b4L,0x44e7dc0495649aeeL, + 0x498ca2555e7ec1d8L } }, + /* 35 << 175 */ + { { 0x3bc766eaaaa07e86L,0x0db6facbf3608586L,0xbadd2549bdc259c8L, + 0x95af3c6e041c649fL }, + { 0xb36a928c02e30afbL,0x9b5356ad008a88b8L,0x4b67a5f1cf1d9e9dL, + 0xc6542e47a5d8d8ceL } }, + /* 36 << 175 */ + { { 0x73061fe87adfb6ccL,0xcc826fd398678141L,0x00e758b13c80515aL, + 0x6afe324741485083L }, + { 0x0fcb08b9b6ae8a75L,0xb8cf388d4acf51e1L,0x344a55606961b9d6L, + 0x1a6778b86a97fd0cL } }, + /* 37 << 175 */ + { { 0xd840fdc1ecc4c7e3L,0xde9fe47d16db68ccL,0xe95f89dea3e216aaL, + 0x84f1a6a49594a8beL }, + { 0x7ddc7d725a7b162bL,0xc5cfda19adc817a3L,0x80a5d35078b58d46L, + 0x93365b1382978f19L } }, + /* 38 << 175 */ + { { 0x2e44d22526a1fc90L,0x0d6d10d24d70705dL,0xd94b6b10d70c45f4L, + 0x0f201022b216c079L }, + { 0xcec966c5658fde41L,0xa8d2bc7d7e27601dL,0xbfcce3e1ff230be7L, + 0x3394ff6b0033ffb5L } }, + /* 39 << 175 */ + { { 0xd890c5098132c9afL,0xaac4b0eb361e7868L,0x5194ded3e82d15aaL, + 0x4550bd2e23ae6b7dL }, + { 0x3fda318eea5399d4L,0xd989bffa91638b80L,0x5ea124d0a14aa12dL, + 0x1fb1b8993667b944L } }, + /* 40 << 175 */ + { { 0x95ec796944c44d6aL,0x91df144a57e86137L,0x915fd62073adac44L, + 0x8f01732d59a83801L }, + { 0xec579d253aa0a633L,0x06de5e7cc9d6d59cL,0xc132f958b1ef8010L, + 0x29476f96e65c1a02L } }, + /* 41 << 175 */ + { { 0x336a77c0d34c3565L,0xef1105b21b9f1e9eL,0x63e6d08bf9e08002L, + 0x9aff2f21c613809eL }, + { 0xb5754f853a80e75dL,0xde71853e6bbda681L,0x86f041df8197fd7aL, + 0x8b332e08127817faL } }, + /* 42 << 175 */ + { { 0x05d99be8b9c20cdaL,0x89f7aad5d5cd0c98L,0x7ef936fe5bb94183L, + 0x92ca0753b05cd7f2L }, + { 0x9d65db1174a1e035L,0x02628cc813eaea92L,0xf2d9e24249e4fbf2L, + 0x94fdfd9be384f8b7L } }, + /* 43 << 175 */ + { { 0x65f5605463428c6bL,0x2f7205b290b409a5L,0xf778bb78ff45ae11L, + 0xa13045bec5ee53b2L }, + { 0xe00a14ff03ef77feL,0x689cd59fffef8befL,0x3578f0ed1e9ade22L, + 0xe99f3ec06268b6a8L } }, + /* 44 << 175 */ + { { 0xa2057d91ea1b3c3eL,0x2d1a7053b8823a4aL,0xabbb336a2cca451eL, + 0xcd2466e32218bb5dL }, + { 0x3ac1f42fc8cb762dL,0x7e312aae7690211fL,0xebb9bd7345d07450L, + 0x207c4b8246c2213fL } }, + /* 45 << 175 */ + { { 0x99d425c1375913ecL,0x94e45e9667908220L,0xc08f3087cd67dbf6L, + 0xa5670fbec0887056L }, + { 0x6717b64a66f5b8fcL,0xd5a56aea786fec28L,0xa8c3f55fc0ff4952L, + 0xa77fefae457ac49bL } }, + /* 46 << 175 */ + { { 0x29882d7c98379d44L,0xd000bdfb509edc8aL,0xc6f95979e66fe464L, + 0x504a6115fa61bde0L }, + { 0x56b3b871effea31aL,0x2d3de26df0c21a54L,0x21dbff31834753bfL, + 0xe67ecf4969269d86L } }, + /* 47 << 175 */ + { { 0x7a176952151fe690L,0x035158047f2adb5fL,0xee794b15d1b62a8dL, + 0xf004ceecaae454e6L }, + { 0x0897ea7cf0386facL,0x3b62ff12d1fca751L,0x154181df1b7a04ecL, + 0x2008e04afb5847ecL } }, + /* 48 << 175 */ + { { 0xd147148e41dbd772L,0x2b419f7322942654L,0x669f30d3e9c544f7L, + 0x52a2c223c8540149L }, + { 0x5da9ee14634dfb02L,0x5f074ff0f47869f3L,0x74ee878da3933accL, + 0xe65106514fe35ed1L } }, + /* 49 << 175 */ + { { 0xb3eb9482f1012e7aL,0x51013cc0a8a566aeL,0xdd5e924347c00d3bL, + 0x7fde089d946bb0e5L }, + { 0x030754fec731b4b3L,0x12a136a499fda062L,0x7c1064b85a1a35bcL, + 0xbf1f5763446c84efL } }, + /* 50 << 175 */ + { { 0xed29a56da16d4b34L,0x7fba9d09dca21c4fL,0x66d7ac006d8de486L, + 0x6006198773a2a5e1L }, + { 0x8b400f869da28ff0L,0x3133f70843c4599cL,0x9911c9b8ee28cb0dL, + 0xcd7e28748e0af61dL } }, + /* 51 << 175 */ + { { 0x5a85f0f272ed91fcL,0x85214f319cd4a373L,0x881fe5be1925253cL, + 0xd8dc98e091e8bc76L }, + { 0x7120affe585cc3a2L,0x724952ed735bf97aL,0x5581e7dc3eb34581L, + 0x5cbff4f2e52ee57dL } }, + /* 52 << 175 */ + { { 0x8d320a0e87d8cc7bL,0x9beaa7f3f1d280d0L,0x7a0b95719beec704L, + 0x9126332e5b7f0057L }, + { 0x01fbc1b48ed3bd6dL,0x35bb2c12d945eb24L,0x6404694e9a8ae255L, + 0xb6092eec8d6abfb3L } }, + /* 53 << 175 */ + { { 0x4d76143fcc058865L,0x7b0a5af26e249922L,0x8aef94406a50d353L, + 0xe11e4bcc64f0e07aL }, + { 0x4472993aa14a90faL,0x7706e20cba0c51d4L,0xf403292f1532672dL, + 0x52573bfa21829382L } }, + /* 54 << 175 */ + { { 0x6a7bb6a93b5bdb83L,0x08da65c0a4a72318L,0xc58d22aa63eb065fL, + 0x1717596c1b15d685L }, + { 0x112df0d0b266d88bL,0xf688ae975941945aL,0x487386e37c292cacL, + 0x42f3b50d57d6985cL } }, + /* 55 << 175 */ + { { 0x6da4f9986a90fc34L,0xc8f257d365ca8a8dL,0xc2feabca6951f762L, + 0xe1bc81d074c323acL }, + { 0x1bc68f67251a2a12L,0x10d86587be8a70dcL,0xd648af7ff0f84d2eL, + 0xf0aa9ebc6a43ac92L } }, + /* 56 << 175 */ + { { 0x69e3be0427596893L,0xb6bb02a645bf452bL,0x0875c11af4c698c8L, + 0x6652b5c7bece3794L }, + { 0x7b3755fd4f5c0499L,0x6ea16558b5532b38L,0xd1c69889a2e96ef7L, + 0x9c773c3a61ed8f48L } }, + /* 57 << 175 */ + { { 0x2b653a409b323abcL,0xe26605e1f0e1d791L,0x45d410644a87157aL, + 0x8f9a78b7cbbce616L }, + { 0xcf1e44aac407edddL,0x81ddd1d8a35b964fL,0x473e339efd083999L, + 0x6c94bdde8e796802L } }, + /* 58 << 175 */ + { { 0x5a304ada8545d185L,0x82ae44ea738bb8cbL,0x628a35e3df87e10eL, + 0xd3624f3da15b9fe3L }, + { 0xcc44209b14be4254L,0x7d0efcbcbdbc2ea5L,0x1f60336204c37bbeL, + 0x21f363f556a5852cL } }, + /* 59 << 175 */ + { { 0xa1503d1ca8501550L,0x2251e0e1d8ab10bbL,0xde129c966961c51cL, + 0x1f7246a481910f68L }, + { 0x2eb744ee5f2591f2L,0x3c47d33f5e627157L,0x4d6d62c922f3bd68L, + 0x6120a64bcb8df856L } }, + /* 60 << 175 */ + { { 0x3a9ac6c07b5d07dfL,0xa92b95587ef39783L,0xe128a134ab3a9b4fL, + 0x41c18807b1252f05L }, + { 0xfc7ed08980ba9b1cL,0xac8dc6dec532a9ddL,0xbf829cef55246809L, + 0x101b784f5b4ee80fL } }, + /* 61 << 175 */ + { { 0xc09945bbb6f11603L,0x57b09dbe41d2801eL,0xfba5202fa97534a8L, + 0x7fd8ae5fc17b9614L }, + { 0xa50ba66678308435L,0x9572f77cd3868c4dL,0x0cef7bfd2dd7aab0L, + 0xe7958e082c7c79ffL } }, + /* 62 << 175 */ + { { 0x81262e4225346689L,0x716da290b07c7004L,0x35f911eab7950ee3L, + 0x6fd72969261d21b5L }, + { 0x5238980308b640d3L,0x5b0026ee887f12a1L,0x20e21660742e9311L, + 0x0ef6d5415ff77ff7L } }, + /* 63 << 175 */ + { { 0x969127f0f9c41135L,0xf21d60c968a64993L,0x656e5d0ce541875cL, + 0xf1e0f84ea1d3c233L }, + { 0x9bcca35906002d60L,0xbe2da60c06191552L,0x5da8bbae61181ec3L, + 0x9f04b82365806f19L } }, + /* 64 << 175 */ + { { 0xf1604a7dd4b79bb8L,0xaee806fb52c878c8L,0x34144f118d47b8e8L, + 0x72edf52b949f9054L }, + { 0xebfca84e2127015aL,0x9051d0c09cb7cef3L,0x86e8fe58296deec8L, + 0x33b2818841010d74L } }, + /* 0 << 182 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 182 */ + { { 0x01079383171b445fL,0x9bcf21e38131ad4cL,0x8cdfe205c93987e8L, + 0xe63f4152c92e8c8fL }, + { 0x729462a930add43dL,0x62ebb143c980f05aL,0x4f3954e53b06e968L, + 0xfe1d75ad242cf6b1L } }, + /* 2 << 182 */ + { { 0x5f95c6c7af8685c8L,0xd4c1c8ce2f8f01aaL,0xc44bbe322574692aL, + 0xb8003478d4a4a068L }, + { 0x7c8fc6e52eca3cdbL,0xea1db16bec04d399L,0xb05bc82e8f2bc5cfL, + 0x763d517ff44793d2L } }, + /* 3 << 182 */ + { { 0x4451c1b808bd98d0L,0x644b1cd46575f240L,0x6907eb337375d270L, + 0x56c8bebdfa2286bdL }, + { 0xc713d2acc4632b46L,0x17da427aafd60242L,0x313065b7c95c7546L, + 0xf8239898bf17a3deL } }, + /* 4 << 182 */ + { { 0xf3b7963f4c830320L,0x842c7aa0903203e3L,0xaf22ca0ae7327afbL, + 0x38e13092967609b6L }, + { 0x73b8fb62757558f1L,0x3cc3e831f7eca8c1L,0xe4174474f6331627L, + 0xa77989cac3c40234L } }, + /* 5 << 182 */ + { { 0xe5fd17a144a081e0L,0xd797fb7db70e296aL,0x2b472b30481f719cL, + 0x0e632a98fe6f8c52L }, + { 0x89ccd116c5f0c284L,0xf51088af2d987c62L,0x2a2bccda4c2de6cfL, + 0x810f9efef679f0f9L } }, + /* 6 << 182 */ + { { 0xb0f394b97ffe4b3eL,0x0b691d21e5fa5d21L,0xb0bd77479dfbbc75L, + 0xd2830fdafaf78b00L }, + { 0xf78c249c52434f57L,0x4b1f754598096dabL,0x73bf6f948ff8c0b3L, + 0x34aef03d454e134cL } }, + /* 7 << 182 */ + { { 0xf8d151f4b7ac7ec5L,0xd6ceb95ae50da7d5L,0xa1b492b0dc3a0eb8L, + 0x75157b69b3dd2863L }, + { 0xe2c4c74ec5413d62L,0xbe329ff7bc5fc4c7L,0x835a2aea60fa9ddaL, + 0xf117f5ad7445cb87L } }, + /* 8 << 182 */ + { { 0xae8317f4b0166f7aL,0xfbd3e3f7ceec74e6L,0xfdb516ace0874bfdL, + 0x3d846019c681f3a3L }, + { 0x0b12ee5c7c1620b0L,0xba68b4dd2b63c501L,0xac03cd326668c51eL, + 0x2a6279f74e0bcb5bL } }, + /* 9 << 182 */ + { { 0x17bd69b06ae85c10L,0x729469791dfdd3a6L,0xd9a032682c078becL, + 0x41c6a658bfd68a52L }, + { 0xcdea10240e023900L,0xbaeec121b10d144dL,0x5a600e74058ab8dcL, + 0x1333af21bb89ccddL } }, + /* 10 << 182 */ + { { 0xdf25eae03aaba1f1L,0x2cada16e3b7144cfL,0x657ee27d71ab98bcL, + 0x99088b4c7a6fc96eL }, + { 0x05d5c0a03549dbd4L,0x42cbdf8ff158c3acL,0x3fb6b3b087edd685L, + 0x22071cf686f064d0L } }, + /* 11 << 182 */ + { { 0xd2d6721fff2811e5L,0xdb81b703fe7fae8cL,0x3cfb74efd3f1f7bbL, + 0x0cdbcd7616cdeb5dL }, + { 0x4f39642a566a808cL,0x02b74454340064d6L,0xfabbadca0528fa6fL, + 0xe4c3074cd3fc0bb6L } }, + /* 12 << 182 */ + { { 0xb32cb8b0b796d219L,0xc3e95f4f34741dd9L,0x8721212568edf6f5L, + 0x7a03aee4a2b9cb8eL }, + { 0x0cd3c376f53a89aaL,0x0d8af9b1948a28dcL,0xcf86a3f4902ab04fL, + 0x8aacb62a7f42002dL } }, + /* 13 << 182 */ + { { 0x106985ebf62ffd52L,0xe670b54e5797bf10L,0x4b405209c5e30aefL, + 0x12c97a204365b5e9L }, + { 0x104646ce1fe32093L,0x13cb4ff63907a8c9L,0x8b9f30d1d46e726bL, + 0xe1985e21aba0f499L } }, + /* 14 << 182 */ + { { 0xc573dea910a230cdL,0x24f46a93cd30f947L,0xf2623fcfabe2010aL, + 0x3f278cb273f00e4fL }, + { 0xed55c67d50b920ebL,0xf1cb9a2d8e760571L,0x7c50d1090895b709L, + 0x4207cf07190d4369L } }, + /* 15 << 182 */ + { { 0x3b027e81c4127fe1L,0xa9f8b9ad3ae9c566L,0x5ab10851acbfbba5L, + 0xa747d648569556f5L }, + { 0xcc172b5c2ba97bf7L,0x15e0f77dbcfa3324L,0xa345b7977686279dL, + 0x5a723480e38003d3L } }, + /* 16 << 182 */ + { { 0xfd8e139f8f5fcda8L,0xf3e558c4bdee5bfdL,0xd76cbaf4e33f9f77L, + 0x3a4c97a471771969L }, + { 0xda27e84bf6dce6a7L,0xff373d9613e6c2d1L,0xf115193cd759a6e9L, + 0x3f9b702563d2262cL } }, + /* 17 << 182 */ + { { 0xd9764a31317cd062L,0x30779d8e199f8332L,0xd807410616b11b0bL, + 0x7917ab9f78aeaed8L }, + { 0xb67a9cbe28fb1d8eL,0x2e313563136eda33L,0x010b7069a371a86cL, + 0x44d90fa26744e6b7L } }, + /* 18 << 182 */ + { { 0x68190867d6b3e243L,0x9fe6cd9d59048c48L,0xb900b02895731538L, + 0xa012062f32cae04fL }, + { 0x8107c8bc9399d082L,0x47e8c54a41df12e2L,0x14ba5117b6ef3f73L, + 0x22260bea81362f0bL } }, + /* 19 << 182 */ + { { 0x90ea261e1a18cc20L,0x2192999f2321d636L,0xef64d314e311b6a0L, + 0xd7401e4c3b54a1f5L }, + { 0x190199836fbca2baL,0x46ad32938fbffc4bL,0xa142d3f63786bf40L, + 0xeb5cbc26b67039fcL } }, + /* 20 << 182 */ + { { 0x9cb0ae6c252bd479L,0x05e0f88a12b5848fL,0x78f6d2b2a5c97663L, + 0x6f6e149bc162225cL }, + { 0xe602235cde601a89L,0xd17bbe98f373be1fL,0xcaf49a5ba8471827L, + 0x7e1a0a8518aaa116L } }, + /* 21 << 182 */ + { { 0x6c833196270580c3L,0x1e233839f1c98a14L,0x67b2f7b4ae34e0a5L, + 0x47ac8745d8ce7289L }, + { 0x2b74779a100dd467L,0x274a43374ee50d09L,0x603dcf1383608bc9L, + 0xcd9da6c3c89e8388L } }, + /* 22 << 182 */ + { { 0x2660199f355116acL,0xcc38bb59b6d18eedL,0x3075f31f2f4bc071L, + 0x9774457f265dc57eL }, + { 0x06a6a9c8c6db88bbL,0x6429d07f4ec98e04L,0x8d05e57b05ecaa8bL, + 0x20f140b17872ea7bL } }, + /* 23 << 182 */ + { { 0xdf8c0f09ca494693L,0x48d3a020f252e909L,0x4c5c29af57b14b12L, + 0x7e6fa37dbf47ad1cL }, + { 0x66e7b50649a0c938L,0xb72c0d486be5f41fL,0x6a6242b8b2359412L, + 0xcd35c7748e859480L } }, + /* 24 << 182 */ + { { 0x12536fea87baa627L,0x58c1fec1f72aa680L,0x6c29b637601e5dc9L, + 0x9e3c3c1cde9e01b9L }, + { 0xefc8127b2bcfe0b0L,0x351071022a12f50dL,0x6ccd6cb14879b397L, + 0xf792f804f8a82f21L } }, + /* 25 << 182 */ + { { 0x509d4804a9b46402L,0xedddf85dc10f0850L,0x928410dc4b6208aaL, + 0xf6229c46391012dcL }, + { 0xc5a7c41e7727b9b6L,0x289e4e4baa444842L,0x049ba1d9e9a947eaL, + 0x44f9e47f83c8debcL } }, + /* 26 << 182 */ + { { 0xfa77a1fe611f8b8eL,0xfd2e416af518f427L,0xc5fffa70114ebac3L, + 0xfe57c4e95d89697bL }, + { 0xfdd053acb1aaf613L,0x31df210fea585a45L,0x318cc10e24985034L, + 0x1a38efd15f1d6130L } }, + /* 27 << 182 */ + { { 0xbf86f2370b1e9e21L,0xb258514d1dbe88aaL,0x1e38a58890c1baf9L, + 0x2936a01ebdb9b692L }, + { 0xd576de986dd5b20cL,0xb586bf7170f98ecfL,0xcccf0f12c42d2fd7L, + 0x8717e61cfb35bd7bL } }, + /* 28 << 182 */ + { { 0x8b1e572235e6fc06L,0x3477728f0b3e13d5L,0x150c294daa8a7372L, + 0xc0291d433bfa528aL }, + { 0xc6c8bc67cec5a196L,0xdeeb31e45c2e8a7cL,0xba93e244fb6e1c51L, + 0xb9f8b71b2e28e156L } }, + /* 29 << 182 */ + { { 0xce65a287968a2ab9L,0xe3c5ce6946bbcb1fL,0xf8c835b9e7ae3f30L, + 0x16bbee26ff72b82bL }, + { 0x665e2017fd42cd22L,0x1e139970f8b1d2a0L,0x125cda2979204932L, + 0x7aee94a549c3bee5L } }, + /* 30 << 182 */ + { { 0x68c7016089821a66L,0xf7c376788f981669L,0xd90829fc48cc3645L, + 0x346af049d70addfcL }, + { 0x2057b232370bf29cL,0xf90c73ce42e650eeL,0xe03386eaa126ab90L, + 0x0e266e7e975a087bL } }, + /* 31 << 182 */ + { { 0x80578eb90fca65d9L,0x7e2989ea16af45b8L,0x7438212dcac75a4eL, + 0x38c7ca394fef36b8L }, + { 0x8650c494d402676aL,0x26ab5a66f72c7c48L,0x4e6cb426ce3a464eL, + 0xf8f998962b72f841L } }, + /* 32 << 182 */ + { { 0x8c3184911a335cc8L,0x563459ba6a5913e4L,0x1b920d61c7b32919L, + 0x805ab8b6a02425adL }, + { 0x2ac512da8d006086L,0x6ca4846abcf5c0fdL,0xafea51d8ac2138d7L, + 0xcb647545344cd443L } }, + /* 33 << 182 */ + { { 0x0429ee8fbd7d9040L,0xee66a2de819b9c96L,0x54f9ec25dea7d744L, + 0x2ffea642671721bbL }, + { 0x4f19dbd1114344eaL,0x04304536fd0dbc8bL,0x014b50aa29ec7f91L, + 0xb5fc22febb06014dL } }, + /* 34 << 182 */ + { { 0x60d963a91ee682e0L,0xdf48abc0fe85c727L,0x0cadba132e707c2dL, + 0xde608d3aa645aeffL }, + { 0x05f1c28bedafd883L,0x3c362edebd94de1fL,0x8dd0629d13593e41L, + 0x0a5e736f766d6eafL } }, + /* 35 << 182 */ + { { 0xbfa92311f68cf9d1L,0xa4f9ef87c1797556L,0x10d75a1f5601c209L, + 0x651c374c09b07361L }, + { 0x49950b5888b5ceadL,0x0ef000586fa9dbaaL,0xf51ddc264e15f33aL, + 0x1f8b5ca62ef46140L } }, + /* 36 << 182 */ + { { 0x343ac0a3ee9523f0L,0xbb75eab2975ea978L,0x1bccf332107387f4L, + 0x790f92599ab0062eL }, + { 0xf1a363ad1e4f6a5fL,0x06e08b8462519a50L,0x609151877265f1eeL, + 0x6a80ca3493ae985eL } }, + /* 37 << 182 */ + { { 0x81b29768aaba4864L,0xb13cabf28d52a7d6L,0xb5c363488ead03f1L, + 0xc932ad9581c7c1c0L }, + { 0x5452708ecae1e27bL,0x9dac42691b0df648L,0x233e3f0cdfcdb8bcL, + 0xe6ceccdfec540174L } }, + /* 38 << 182 */ + { { 0xbd0d845e95081181L,0xcc8a7920699355d5L,0x111c0f6dc3b375a8L, + 0xfd95bc6bfd51e0dcL }, + { 0x4a106a266888523aL,0x4d142bd6cb01a06dL,0x79bfd289adb9b397L, + 0x0bdbfb94e9863914L } }, + /* 39 << 182 */ + { { 0x29d8a2291660f6a6L,0x7f6abcd6551c042dL,0x13039deb0ac3ffe8L, + 0xa01be628ec8523fbL }, + { 0x6ea341030ca1c328L,0xc74114bdb903928eL,0x8aa4ff4e9e9144b0L, + 0x7064091f7f9a4b17L } }, + /* 40 << 182 */ + { { 0xa3f4f521e447f2c4L,0x81b8da7a604291f0L,0xd680bc467d5926deL, + 0x84f21fd534a1202fL }, + { 0x1d1e31814e9df3d8L,0x1ca4861a39ab8d34L,0x809ddeec5b19aa4aL, + 0x59f72f7e4d329366L } }, + /* 41 << 182 */ + { { 0xa2f93f41386d5087L,0x40bf739cdd67d64fL,0xb449420566702158L, + 0xc33c65be73b1e178L }, + { 0xcdcd657c38ca6153L,0x97f4519adc791976L,0xcc7c7f29cd6e1f39L, + 0x38de9cfb7e3c3932L } }, + /* 42 << 182 */ + { { 0xe448eba37b793f85L,0xe9f8dbf9f067e914L,0xc0390266f114ae87L, + 0x39ed75a7cd6a8e2aL }, + { 0xadb148487ffba390L,0x67f8cb8b6af9bc09L,0x322c38489c7476dbL, + 0xa320fecf52a538d6L } }, + /* 43 << 182 */ + { { 0xe0493002b2aced2bL,0xdfba1809616bd430L,0x531c4644c331be70L, + 0xbc04d32e90d2e450L }, + { 0x1805a0d10f9f142dL,0x2c44a0c547ee5a23L,0x31875a433989b4e3L, + 0x6b1949fd0c063481L } }, + /* 44 << 182 */ + { { 0x2dfb9e08be0f4492L,0x3ff0da03e9d5e517L,0x03dbe9a1f79466a8L, + 0x0b87bcd015ea9932L }, + { 0xeb64fc83ab1f58abL,0x6d9598da817edc8aL,0x699cff661d3b67e5L, + 0x645c0f2992635853L } }, + /* 45 << 182 */ + { { 0x253cdd82eabaf21cL,0x82b9602a2241659eL,0x2cae07ec2d9f7091L, + 0xbe4c720c8b48cd9bL }, + { 0x6ce5bc036f08d6c9L,0x36e8a997af10bf40L,0x83422d213e10ff12L, + 0x7b26d3ebbcc12494L } }, + /* 46 << 182 */ + { { 0xb240d2d0c9469ad6L,0xc4a11b4d30afa05bL,0x4b604acedd6ba286L, + 0x184866003ee2864cL }, + { 0x5869d6ba8d9ce5beL,0x0d8f68c5ff4bfb0dL,0xb69f210b5700cf73L, + 0x61f6653a6d37c135L } }, + /* 47 << 182 */ + { { 0xff3d432b5aff5a48L,0x0d81c4b972ba3a69L,0xee879ae9fa1899efL, + 0xbac7e2a02d6acafdL }, + { 0xd6d93f6c1c664399L,0x4c288de15bcb135dL,0x83031dab9dab7cbfL, + 0xfe23feb03abbf5f0L } }, + /* 48 << 182 */ + { { 0x9f1b2466cdedca85L,0x140bb7101a09538cL,0xac8ae8515e11115dL, + 0x0d63ff676f03f59eL }, + { 0x755e55517d234afbL,0x61c2db4e7e208fc1L,0xaa9859cef28a4b5dL, + 0xbdd6d4fc34af030fL } }, + /* 49 << 182 */ + { { 0xd1c4a26d3be01cb1L,0x9ba14ffc243aa07cL,0xf95cd3a9b2503502L, + 0xe379bc067d2a93abL }, + { 0x3efc18e9d4ca8d68L,0x083558ec80bb412aL,0xd903b9409645a968L, + 0xa499f0b69ba6054fL } }, + /* 50 << 182 */ + { { 0x208b573cb8349abeL,0x3baab3e530b4fc1cL,0x87e978bacb524990L, + 0x3524194eccdf0e80L }, + { 0x627117257d4bcc42L,0xe90a3d9bb90109baL,0x3b1bdd571323e1e0L, + 0xb78e9bd55eae1599L } }, + /* 51 << 182 */ + { { 0x0794b7469e03d278L,0x80178605d70e6297L,0x171792f899c97855L, + 0x11b393eef5a86b5cL }, + { 0x48ef6582d8884f27L,0xbd44737abf19ba5fL,0x8698de4ca42062c6L, + 0x8975eb8061ce9c54L } }, + /* 52 << 182 */ + { { 0xd50e57c7d7fe71f3L,0x15342190bc97ce38L,0x51bda2de4df07b63L, + 0xba12aeae200eb87dL }, + { 0xabe135d2a9b4f8f6L,0x04619d65fad6d99cL,0x4a6683a77994937cL, + 0x7a778c8b6f94f09aL } }, + /* 53 << 182 */ + { { 0x8c50862320a71b89L,0x241a2aed1c229165L,0x352be595aaf83a99L, + 0x9fbfee7f1562bac8L }, + { 0xeaf658b95c4017e3L,0x1dc7f9e015120b86L,0xd84f13dd4c034d6fL, + 0x283dd737eaea3038L } }, + /* 54 << 182 */ + { { 0x197f2609cd85d6a2L,0x6ebbc345fae60177L,0xb80f031b4e12fedeL, + 0xde55d0c207a2186bL }, + { 0x1fb3e37f24dcdd5aL,0x8d602da57ed191fbL,0x108fb05676023e0dL, + 0x70178c71459c20c0L } }, + /* 55 << 182 */ + { { 0xfad5a3863fe54cf0L,0xa4a3ec4f02bbb475L,0x1aa5ec20919d94d7L, + 0x5d3b63b5a81e4ab3L }, + { 0x7fa733d85ad3d2afL,0xfbc586ddd1ac7a37L,0x282925de40779614L, + 0xfe0ffffbe74a242aL } }, + /* 56 << 182 */ + { { 0x3f39e67f906151e5L,0xcea27f5f55e10649L,0xdca1d4e1c17cf7b7L, + 0x0c326d122fe2362dL }, + { 0x05f7ac337dd35df3L,0x0c3b7639c396dbdfL,0x0912f5ac03b7db1cL, + 0x9dea4b705c9ed4a9L } }, + /* 57 << 182 */ + { { 0x475e6e53aae3f639L,0xfaba0e7cfc278bacL,0x16f9e2219490375fL, + 0xaebf9746a5a7ed0aL }, + { 0x45f9af3ff41ad5d6L,0x03c4623cb2e99224L,0x82c5bb5cb3cf56aaL, + 0x6431181934567ed3L } }, + /* 58 << 182 */ + { { 0xec57f2118be489acL,0x2821895db9a1104bL,0x610dc8756064e007L, + 0x8e526f3f5b20d0feL }, + { 0x6e71ca775b645aeeL,0x3d1dcb9f800e10ffL,0x36b51162189cf6deL, + 0x2c5a3e306bb17353L } }, + /* 59 << 182 */ + { { 0xc186cd3e2a6c6fbfL,0xa74516fa4bf97906L,0x5b4b8f4b279d6901L, + 0x0c4e57b42b573743L }, + { 0x75fdb229b6e386b6L,0xb46793fd99deac27L,0xeeec47eacf712629L, + 0xe965f3c4cbc3b2ddL } }, + /* 60 << 182 */ + { { 0x8dd1fb83425c6559L,0x7fc00ee60af06fdaL,0xe98c922533d956dfL, + 0x0f1ef3354fbdc8a2L }, + { 0x2abb5145b79b8ea2L,0x40fd2945bdbff288L,0x6a814ac4d7185db7L, + 0xc4329d6fc084609aL } }, + /* 61 << 182 */ + { { 0xc9ba7b52ed1be45dL,0x891dd20de4cd2c74L,0x5a4d4a7f824139b1L, + 0x66c17716b873c710L }, + { 0x5e5bc1412843c4e0L,0xd5ac4817b97eb5bfL,0xc0f8af54450c95c7L, + 0xc91b3fa0318406c5L } }, + /* 62 << 182 */ + { { 0x360c340aab9d97f8L,0xfb57bd0790a2d611L,0x4339ae3ca6a6f7e5L, + 0x9c1fcd2a2feb8a10L }, + { 0x972bcca9c7ea7432L,0x1b0b924c308076f6L,0x80b2814a2a5b4ca5L, + 0x2f78f55b61ef3b29L } }, + /* 63 << 182 */ + { { 0xf838744ac18a414fL,0xc611eaae903d0a86L,0x94dabc162a453f55L, + 0xe6f2e3da14efb279L }, + { 0x5b7a60179320dc3cL,0x692e382f8df6b5a4L,0x3f5e15e02d40fa90L, + 0xc87883ae643dd318L } }, + /* 64 << 182 */ + { { 0x511053e453544774L,0x834d0ecc3adba2bcL,0x4215d7f7bae371f5L, + 0xfcfd57bf6c8663bcL }, + { 0xded2383dd6901b1dL,0x3b49fbb4b5587dc3L,0xfd44a08d07625f62L, + 0x3ee4d65b9de9b762L } }, + /* 0 << 189 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 189 */ + { { 0x64e5137d0d63d1faL,0x658fc05202a9d89fL,0x4889487450436309L, + 0xe9ae30f8d598da61L }, + { 0x2ed710d1818baf91L,0xe27e9e068b6a0c20L,0x1e28dcfb1c1a6b44L, + 0x883acb64d6ac57dcL } }, + /* 2 << 189 */ + { { 0x8735728dc2c6ff70L,0x79d6122fc5dc2235L,0x23f5d00319e277f9L, + 0x7ee84e25dded8cc7L }, + { 0x91a8afb063cd880aL,0x3f3ea7c63574af60L,0x0cfcdc8402de7f42L, + 0x62d0792fb31aa152L } }, + /* 3 << 189 */ + { { 0x8e1b4e438a5807ceL,0xad283893e4109a7eL,0xc30cc9cbafd59ddaL, + 0xf65f36c63d8d8093L }, + { 0xdf31469ea60d32b2L,0xee93df4b3e8191c8L,0x9c1017c5355bdeb5L, + 0xd26231858616aa28L } }, + /* 4 << 189 */ + { { 0xb02c83f9dec31a21L,0x988c8b236ad9d573L,0x53e983aea57be365L, + 0xe968734d646f834eL }, + { 0x9137ea8f5da6309bL,0x10f3a624c1f1ce16L,0x782a9ea2ca440921L, + 0xdf94739e5b46f1b5L } }, + /* 5 << 189 */ + { { 0x9f9be006cce85c9bL,0x360e70d6a4c7c2d3L,0x2cd5beeaaefa1e60L, + 0x64cf63c08c3d2b6dL }, + { 0xfb107fa3e1cf6f90L,0xb7e937c6d5e044e6L,0x74e8ca78ce34db9fL, + 0x4f8b36c13e210bd0L } }, + /* 6 << 189 */ + { { 0x1df165a434a35ea8L,0x3418e0f74d4412f6L,0x5af1f8af518836c3L, + 0x42ceef4d130e1965L }, + { 0x5560ca0b543a1957L,0xc33761e5886cb123L,0x66624b1ffe98ed30L, + 0xf772f4bf1090997dL } }, + /* 7 << 189 */ + { { 0xf4e540bb4885d410L,0x7287f8109ba5f8d7L,0x22d0d865de98dfb1L, + 0x49ff51a1bcfbb8a3L }, + { 0xb6b6fa536bc3012eL,0x3d31fd72170d541dL,0x8018724f4b0f4966L, + 0x79e7399f87dbde07L } }, + /* 8 << 189 */ + { { 0x56f8410ef4f8b16aL,0x97241afec47b266aL,0x0a406b8e6d9c87c1L, + 0x803f3e02cd42ab1bL }, + { 0x7f0309a804dbec69L,0xa83b85f73bbad05fL,0xc6097273ad8e197fL, + 0xc097440e5067adc1L } }, + /* 9 << 189 */ + { { 0x730eafb63524ff16L,0xd7f9b51e823fc6ceL,0x27bd0d32443e4ac0L, + 0x40c59ad94d66f217L }, + { 0x6c33136f17c387a4L,0x5043b8d5eb86804dL,0x74970312675a73c9L, + 0x838fdb31f16669b6L } }, + /* 10 << 189 */ + { { 0xc507b6dd418e7dddL,0x39888d93472f19d6L,0x7eae26be0c27eb4dL, + 0x17b53ed3fbabb884L }, + { 0xfc27021b2b01ae4fL,0x88462e87cf488682L,0xbee096ec215e2d87L, + 0xeb2fea9ad242e29bL } }, + /* 11 << 189 */ + { { 0x5d985b5fb821fc28L,0x89d2e197dc1e2ad2L,0x55b566b89030ba62L, + 0xe3fd41b54f41b1c6L }, + { 0xb738ac2eb9a96d61L,0x7f8567ca369443f4L,0x8698622df803a440L, + 0x2b5862368fe2f4dcL } }, + /* 12 << 189 */ + { { 0xbbcc00c756b95bceL,0x5ec03906616da680L,0x79162ee672214252L, + 0x43132b6386a892d2L }, + { 0x4bdd3ff22f3263bfL,0xd5b3733c9cd0a142L,0x592eaa8244415ccbL, + 0x663e89248d5474eaL } }, + /* 13 << 189 */ + { { 0x8058a25e5236344eL,0x82e8df9dbda76ee6L,0xdcf6efd811cc3d22L, + 0x00089cda3b4ab529L }, + { 0x91d3a071bd38a3dbL,0x4ea97fc0ef72b925L,0x0c9fc15bea3edf75L, + 0x5a6297cda4348ed3L } }, + /* 14 << 189 */ + { { 0x0d38ab35ce7c42d4L,0x9fd493ef82feab10L,0x46056b6d82111b45L, + 0xda11dae173efc5c3L }, + { 0xdc7402785545a7fbL,0xbdb2601c40d507e6L,0x121dfeeb7066fa58L, + 0x214369a839ae8c2aL } }, + /* 15 << 189 */ + { { 0x195709cb06e0956cL,0x4c9d254f010cd34bL,0xf51e13f70471a532L, + 0xe19d67911e73054dL }, + { 0xf702a628db5c7be3L,0xc7141218b24dde05L,0xdc18233cf29b2e2eL, + 0x3a6bd1e885342dbaL } }, + /* 16 << 189 */ + { { 0x3f747fa0b311898cL,0xe2a272e4cd0eac65L,0x4bba5851f914d0bcL, + 0x7a1a9660c4a43ee3L }, + { 0xe5a367cea1c8cde9L,0x9d958ba97271abe3L,0xf3ff7eb63d1615cdL, + 0xa2280dcef5ae20b0L } }, + /* 17 << 189 */ + { { 0x56dba5c1cf640147L,0xea5a2e3d5e83d118L,0x04cd6b6dda24c511L, + 0x1c0f4671e854d214L }, + { 0x91a6b7a969565381L,0xdc966240decf1f5bL,0x1b22d21cfcf5d009L, + 0x2a05f6419021dbd5L } }, + /* 18 << 189 */ + { { 0x8c0ed566d4312483L,0x5179a95d643e216fL,0xcc185fec17044493L, + 0xb306333954991a21L }, + { 0xd801ecdb0081a726L,0x0149b0c64fa89bbbL,0xafe9065a4391b6b9L, + 0xedc92786d633f3a3L } }, + /* 19 << 189 */ + { { 0xe408c24aae6a8e13L,0x85833fde9f3897abL,0x43800e7ed81a0715L, + 0xde08e346b44ffc5fL }, + { 0x7094184ccdeff2e0L,0x49f9387b165eaed1L,0x635d6129777c468aL, + 0x8c0dcfd1538c2dd8L } }, + /* 20 << 189 */ + { { 0xd6d9d9e37a6a308bL,0x623758304c2767d3L,0x874a8bc6f38cbeb6L, + 0xd94d3f1accb6fd9eL }, + { 0x92a9735bba21f248L,0x272ad0e56cd1efb0L,0x7437b69c05b03284L, + 0xe7f047026948c225L } }, + /* 21 << 189 */ + { { 0x8a56c04acba2ececL,0x0c181270e3a73e41L,0x6cb34e9d03e93725L, + 0xf77c8713496521a9L }, + { 0x94569183fa7f9f90L,0xf2e7aa4c8c9707adL,0xced2c9ba26c1c9a3L, + 0x9109fe9640197507L } }, + /* 22 << 189 */ + { { 0x9ae868a9e9adfe1cL,0x3984403d314e39bbL,0xb5875720f2fe378fL, + 0x33f901e0ba44a628L }, + { 0xea1125fe3652438cL,0xae9ec4e69dd1f20bL,0x1e740d9ebebf7fbdL, + 0x6dbd3ddc42dbe79cL } }, + /* 23 << 189 */ + { { 0x62082aecedd36776L,0xf612c478e9859039L,0xa493b201032f7065L, + 0xebd4d8f24ff9b211L }, + { 0x3f23a0aaaac4cb32L,0xea3aadb715ed4005L,0xacf17ea4afa27e63L, + 0x56125c1ac11fd66cL } }, + /* 24 << 189 */ + { { 0x266344a43794f8dcL,0xdcca923a483c5c36L,0x2d6b6bbf3f9d10a0L, + 0xb320c5ca81d9bdf3L }, + { 0x620e28ff47b50a95L,0x933e3b01cef03371L,0xf081bf8599100153L, + 0x183be9a0c3a8c8d6L } }, + /* 25 << 189 */ + { { 0x4e3ddc5ad6bbe24dL,0xc6c7463053843795L,0x78193dd765ec2d4cL, + 0xb8df26cccd3c89b2L }, + { 0x98dbe3995a483f8dL,0x72d8a9577dd3313aL,0x65087294ab0bd375L, + 0xfcd892487c259d16L } }, + /* 26 << 189 */ + { { 0x8a9443d77613aa81L,0x8010080085fe6584L,0x70fc4dbc7fb10288L, + 0xf58280d3e86beee8L }, + { 0x14fdd82f7c978c38L,0xdf1204c10de44d7bL,0xa08a1c844160252fL, + 0x591554cac17646a5L } }, + /* 27 << 189 */ + { { 0x214a37d6a05bd525L,0x48d5f09b07957b3cL,0x0247cdcbd7109bc9L, + 0x40f9e4bb30599ce7L }, + { 0xc325fa03f46ad2ecL,0x00f766cfc3e3f9eeL,0xab556668d43a4577L, + 0x68d30a613ee03b93L } }, + /* 28 << 189 */ + { { 0x7ddc81ea77b46a08L,0xcf5a6477c7480699L,0x43a8cb346633f683L, + 0x1b867e6b92363c60L }, + { 0x439211141f60558eL,0xcdbcdd632f41450eL,0x7fc04601cc630e8bL, + 0xea7c66d597038b43L } }, + /* 29 << 189 */ + { { 0x7259b8a504e99fd8L,0x98a8dd124785549aL,0x0e459a7c840552e1L, + 0xcdfcf4d04bb0909eL }, + { 0x34a86db253758da7L,0xe643bb83eac997e1L,0x96400bd7530c5b7eL, + 0x9f97af87b41c8b52L } }, + /* 30 << 189 */ + { { 0x34fc8820fbeee3f9L,0x93e5349049091afdL,0x764b9be59a31f35cL, + 0x71f3786457e3d924L }, + { 0x02fb34e0943aa75eL,0xa18c9c58ab8ff6e4L,0x080f31b133cf0d19L, + 0x5c9682db083518a7L } }, + /* 31 << 189 */ + { { 0x873d4ca6b709c3deL,0x64a842623575b8f0L,0x6275da1f020154bbL, + 0x97678caad17cf1abL }, + { 0x8779795f951a95c3L,0xdd35b16350fccc08L,0x3270962733d8f031L, + 0x3c5ab10a498dd85cL } }, + /* 32 << 189 */ + { { 0xb6c185c341dca566L,0x7de7fedad8622aa3L,0x99e84d92901b6dfbL, + 0x30a02b0e7c4ad288L }, + { 0xc7c81daa2fd3cf36L,0xd1319547df89e59fL,0xb2be8184cd496733L, + 0xd5f449eb93d3412bL } }, + /* 33 << 189 */ + { { 0x7ea41b1b25fe531dL,0xf97974326a1d5646L,0x86067f722bde501aL, + 0xf91481c00c85e89cL }, + { 0xca8ee465f8b05bc6L,0x1844e1cf02e83cdaL,0xca82114ab4dbe33bL, + 0x0f9f87694eabfde2L } }, + /* 34 << 189 */ + { { 0x4936b1c038b27fe2L,0x63b6359baba402dfL,0x40c0ea2f656bdbabL, + 0x9c992a896580c39cL }, + { 0x600e8f152a60aed1L,0xeb089ca4e0bf49dfL,0x9c233d7d2d42d99aL, + 0x648d3f954c6bc2faL } }, + /* 35 << 189 */ + { { 0xdcc383a8e1add3f3L,0xf42c0c6a4f64a348L,0x2abd176f0030dbdbL, + 0x4de501a37d6c215eL }, + { 0x4a107c1f4b9a64bcL,0xa77f0ad32496cd59L,0xfb78ac627688dffbL, + 0x7025a2ca67937d8eL } }, + /* 36 << 189 */ + { { 0xfde8b2d1d1a8f4e7L,0xf5b3da477354927cL,0xe48606a3d9205735L, + 0xac477cc6e177b917L }, + { 0xfb1f73d2a883239aL,0xe12572f6cc8b8357L,0x9d355e9cfb1f4f86L, + 0x89b795f8d9f3ec6eL } }, + /* 37 << 189 */ + { { 0x27be56f1b54398dcL,0x1890efd73fedeed5L,0x62f77f1f9c6d0140L, + 0x7ef0e314596f0ee4L }, + { 0x50ca6631cc61dab3L,0x4a39801df4866e4fL,0x66c8d032ae363b39L, + 0x22c591e52ead66aaL } }, + /* 38 << 189 */ + { { 0x954ba308de02a53eL,0x2a6c060fd389f357L,0xe6cfcde8fbf40b66L, + 0x8e02fc56c6340ce1L }, + { 0xe495779573adb4baL,0x7b86122ca7b03805L,0x63f835120c8e6fa6L, + 0x83660ea0057d7804L } }, + /* 39 << 189 */ + { { 0xbad7910521ba473cL,0xb6c50beeded5389dL,0xee2caf4daa7c9bc0L, + 0xd97b8de48c4e98a7L }, + { 0xa9f63e70ab3bbddbL,0x3898aabf2597815aL,0x7659af89ac15b3d9L, + 0xedf7725b703ce784L } }, + /* 40 << 189 */ + { { 0x25470fabe085116bL,0x04a4337587285310L,0x4e39187ee2bfd52fL, + 0x36166b447d9ebc74L }, + { 0x92ad433cfd4b322cL,0x726aa817ba79ab51L,0xf96eacd8c1db15ebL, + 0xfaf71e910476be63L } }, + /* 41 << 189 */ + { { 0xdd69a640641fad98L,0xb799591829622559L,0x03c6daa5de4199dcL, + 0x92cadc97ad545eb4L }, + { 0x1028238b256534e4L,0x73e80ce68595409aL,0x690d4c66d05dc59bL, + 0xc95f7b8f981dee80L } }, + /* 42 << 189 */ + { { 0xf4337014d856ac25L,0x441bd9ddac524dcaL,0x640b3d855f0499f5L, + 0x39cf84a9d5fda182L }, + { 0x04e7b055b2aa95a0L,0x29e33f0a0ddf1860L,0x082e74b5423f6b43L, + 0x217edeb90aaa2b0fL } }, + /* 43 << 189 */ + { { 0x58b83f3583cbea55L,0xc485ee4dbc185d70L,0x833ff03b1e5f6992L, + 0xb5b9b9cccf0c0dd5L }, + { 0x7caaee8e4e9e8a50L,0x462e907b6269dafdL,0x6ed5cee9fbe791c6L, + 0x68ca3259ed430790L } }, + /* 44 << 189 */ + { { 0x2b72bdf213b5ba88L,0x60294c8a35ef0ac4L,0x9c3230ed19b99b08L, + 0x560fff176c2589aaL }, + { 0x552b8487d6770374L,0xa373202d9a56f685L,0xd3e7f90745f175d9L, + 0x3c2f315fd080d810L } }, + /* 45 << 189 */ + { { 0x1130e9dd7b9520e8L,0xc078f9e20af037b5L,0x38cd2ec71e9c104cL, + 0x0f684368c472fe92L }, + { 0xd3f1b5ed6247e7efL,0xb32d33a9396dfe21L,0x46f59cf44a9aa2c2L, + 0x69cd5168ff0f7e41L } }, + /* 46 << 189 */ + { { 0x3f59da0f4b3234daL,0xcf0b0235b4579ebeL,0x6d1cbb256d2476c7L, + 0x4f0837e69dc30f08L }, + { 0x9a4075bb906f6e98L,0x253bb434c761e7d1L,0xde2e645f6e73af10L, + 0xb89a40600c5f131cL } }, + /* 47 << 189 */ + { { 0xd12840c5b8cc037fL,0x3d093a5b7405bb47L,0x6202c253206348b8L, + 0xbf5d57fcc55a3ca7L }, + { 0x89f6c90c8c3bef48L,0x23ac76235a0a960aL,0xdfbd3d6b552b42abL, + 0x3ef22458132061f6L } }, + /* 48 << 189 */ + { { 0xd74e9bdac97e6516L,0x88779360c230f49eL,0xa6ec1de31e74ea49L, + 0x581dcee53fb645a2L }, + { 0xbaef23918f483f14L,0x6d2dddfcd137d13bL,0x54cde50ed2743a42L, + 0x89a34fc5e4d97e67L } }, + /* 49 << 189 */ + { { 0x13f1f5b312e08ce5L,0xa80540b8a7f0b2caL,0x854bcf7701982805L, + 0xb8653ffd233bea04L }, + { 0x8e7b878702b0b4c9L,0x2675261f9acb170aL,0x061a9d90930c14e5L, + 0xb59b30e0def0abeaL } }, + /* 50 << 189 */ + { { 0x1dc19ea60200ec7dL,0xb6f4a3f90bce132bL,0xb8d5de90f13e27e0L, + 0xbaee5ef01fade16fL }, + { 0x6f406aaae4c6cf38L,0xab4cfe06d1369815L,0x0dcffe87efd550c6L, + 0x9d4f59c775ff7d39L } }, + /* 51 << 189 */ + { { 0xb02553b151deb6adL,0x812399a4b1877749L,0xce90f71fca6006e1L, + 0xc32363a6b02b6e77L }, + { 0x02284fbedc36c64dL,0x86c81e31a7e1ae61L,0x2576c7e5b909d94aL, + 0x8b6f7d02818b2bb0L } }, + /* 52 << 189 */ + { { 0xeca3ed0756faa38aL,0xa3790e6c9305bb54L,0xd784eeda7bc73061L, + 0xbd56d3696dd50614L }, + { 0xd6575949229a8aa9L,0xdcca8f474595ec28L,0x814305c106ab4fe6L, + 0xc8c3976824f43f16L } }, + /* 53 << 189 */ + { { 0xe2a45f36523f2b36L,0x995c6493920d93bbL,0xf8afdab790f1632bL, + 0x79ebbecd1c295954L }, + { 0xc7bb3ddb79592f48L,0x67216a7b5f88e998L,0xd91f098bbc01193eL, + 0xf7d928a5b1db83fcL } }, + /* 54 << 189 */ + { { 0x55e38417e991f600L,0x2a91113e2981a934L,0xcbc9d64806b13bdeL, + 0xb011b6ac0755ff44L }, + { 0x6f4cb518045ec613L,0x522d2d31c2f5930aL,0x5acae1af382e65deL, + 0x5764306727bc966fL } }, + /* 55 << 189 */ + { { 0x5e12705d1c7193f0L,0xf0f32f473be8858eL,0x785c3d7d96c6dfc7L, + 0xd75b4a20bf31795dL }, + { 0x91acf17b342659d4L,0xe596ea3444f0378fL,0x4515708fce52129dL, + 0x17387e1e79f2f585L } }, + /* 56 << 189 */ + { { 0x72cfd2e949dee168L,0x1ae052233e2af239L,0x009e75be1d94066aL, + 0x6cca31c738abf413L }, + { 0xb50bd61d9bc49908L,0x4a9b4a8cf5e2bc1eL,0xeb6cc5f7946f83acL, + 0x27da93fcebffab28L } }, + /* 57 << 189 */ + { { 0xea314c964821c8c5L,0x8de49deda83c15f4L,0x7a64cf207af33004L, + 0x45f1bfebc9627e10L }, + { 0x878b062654b9df60L,0x5e4fdc3ca95c0b33L,0xe54a37cac2035d8eL, + 0x9087cda980f20b8cL } }, + /* 58 << 189 */ + { { 0x36f61c238319ade4L,0x766f287ade8cfdf8L,0x48821948346f3705L, + 0x49a7b85316e4f4a2L }, + { 0xb9b3f8a75cedadfdL,0x8f5628158db2a815L,0xc0b7d55401f68f95L, + 0x12971e27688a208eL } }, + /* 59 << 189 */ + { { 0xc9f8b696d0ff34fcL,0x20824de21222718cL,0x7213cf9f0c95284dL, + 0xe2ad741bdc158240L }, + { 0x0ee3a6df54043ccfL,0x16ff479bd84412b3L,0xf6c74ee0dfc98af0L, + 0xa78a169f52fcd2fbL } }, + /* 60 << 189 */ + { { 0xd8ae874699c930e9L,0x1d33e85849e117a5L,0x7581fcb46624759fL, + 0xde50644f5bedc01dL }, + { 0xbeec5d00caf3155eL,0x672d66acbc73e75fL,0x86b9d8c6270b01dbL, + 0xd249ef8350f55b79L } }, + /* 61 << 189 */ + { { 0x6131d6d473978fe3L,0xcc4e4542754b00a1L,0x4e05df0557dfcfe9L, + 0x94b29cdd51ef6bf0L }, + { 0xe4530cff9bc7edf2L,0x8ac236fdd3da65f3L,0x0faf7d5fc8eb0b48L, + 0x4d2de14c660eb039L } }, + /* 62 << 189 */ + { { 0xc006bba760430e54L,0x10a2d0d6da3289abL,0x9c037a5dd7979c59L, + 0x04d1f3d3a116d944L }, + { 0x9ff224738a0983cdL,0x28e25b38c883cabbL,0xe968dba547a58995L, + 0x2c80b505774eebdfL } }, + /* 63 << 189 */ + { { 0xee763b714a953bebL,0x502e223f1642e7f6L,0x6fe4b64161d5e722L, + 0x9d37c5b0dbef5316L }, + { 0x0115ed70f8330bc7L,0x139850e675a72789L,0x27d7faecffceccc2L, + 0x3016a8604fd9f7f6L } }, + /* 64 << 189 */ + { { 0xc492ec644cd8f64cL,0x58a2d790279d7b51L,0x0ced1fc51fc75256L, + 0x3e658aed8f433017L }, + { 0x0b61942e05da59ebL,0xba3d60a30ddc3722L,0x7c311cd1742e7f87L, + 0x6473ffeef6b01b6eL } }, + /* 0 << 196 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 196 */ + { { 0x8303604f692ac542L,0xf079ffe1227b91d3L,0x19f63e6315aaf9bdL, + 0xf99ee565f1f344fbL }, + { 0x8a1d661fd6219199L,0x8c883bc6d48ce41cL,0x1065118f3c74d904L, + 0x713889ee0faf8b1bL } }, + /* 2 << 196 */ + { { 0x972b3f8f81a1b3beL,0x4f3ce145ce2764a0L,0xe2d0f1cc28c4f5f7L, + 0xdeee0c0dc7f3985bL }, + { 0x7df4adc0d39e25c3L,0x40619820c467a080L,0x440ebc9361cf5a58L, + 0x527729a6422ad600L } }, + /* 3 << 196 */ + { { 0xca6c0937b1b76ba6L,0x1a2eab854d2026dcL,0xb1715e1519d9ae0aL, + 0xf1ad9199bac4a026L }, + { 0x35b3dfb807ea7b0eL,0xedf5496f3ed9eb89L,0x8932e5ff2d6d08abL, + 0xf314874e25bd2731L } }, + /* 4 << 196 */ + { { 0xefb26a753f73f449L,0x1d1c94f88d44fc79L,0x49f0fbc53bc0dc4dL, + 0xb747ea0b3698a0d0L }, + { 0x5218c3fe228d291eL,0x35b804b543c129d6L,0xfac859b8d1acc516L, + 0x6c10697d95d6e668L } }, + /* 5 << 196 */ + { { 0xc38e438f0876fd4eL,0x45f0c30783d2f383L,0x203cc2ecb10934cbL, + 0x6a8f24392c9d46eeL }, + { 0xf16b431b65ccde7bL,0x41e2cd1827e76a6fL,0xb9c8cf8f4e3484d7L, + 0x64426efd8315244aL } }, + /* 6 << 196 */ + { { 0x1c0a8e44fc94dea3L,0x34c8cdbfdad6a0b0L,0x919c384004113cefL, + 0xfd32fba415490ffaL }, + { 0x58d190f6795dcfb7L,0xfef01b0383588bafL,0x9e6d1d63ca1fc1c0L, + 0x53173f96f0a41ac9L } }, + /* 7 << 196 */ + { { 0x2b1d402aba16f73bL,0x2fb310148cf9b9fcL,0x2d51e60e446ef7bfL, + 0xc731021bb91e1745L }, + { 0x9d3b47244fee99d4L,0x4bca48b6fac5c1eaL,0x70f5f514bbea9af7L, + 0x751f55a5974c283aL } }, + /* 8 << 196 */ + { { 0x6e30251acb452fdbL,0x31ee696550f30650L,0xb0b3e508933548d9L, + 0xb8949a4ff4b0ef5bL }, + { 0x208b83263c88f3bdL,0xab147c30db1d9989L,0xed6515fd44d4df03L, + 0x17a12f75e72eb0c5L } }, + /* 9 << 196 */ + { { 0x3b59796d36cf69dbL,0x1219eee956670c18L,0xfe3341f77a070d8eL, + 0x9b70130ba327f90cL }, + { 0x36a324620ae18e0eL,0x2021a62346c0a638L,0x251b5817c62eb0d4L, + 0x87bfbcdf4c762293L } }, + /* 10 << 196 */ + { { 0xf78ab505cdd61d64L,0x8c7a53fcc8c18857L,0xa653ce6f16147515L, + 0x9c923aa5ea7d52d5L }, + { 0xc24709cb5c18871fL,0x7d53bec873b3cc74L,0x59264afffdd1d4c4L, + 0x5555917e240da582L } }, + /* 11 << 196 */ + { { 0xcae8bbda548f5a0eL,0x1910eaba3bbfbbe1L,0xae5796857677afc3L, + 0x49ea61f173ff0b5cL }, + { 0x786554784f7c3922L,0x95d337cd20c68eefL,0x68f1e1e5df779ab9L, + 0x14b491b0b5cf69a8L } }, + /* 12 << 196 */ + { { 0x7a6cbbe028e3fe89L,0xe7e1fee4c5aac0ebL,0x7f47eda5697e5140L, + 0x4f450137b454921fL }, + { 0xdb625f8495cd8185L,0x74be0ba1cdb2e583L,0xaee4fd7cdd5e6de4L, + 0x4251437de8101739L } }, + /* 13 << 196 */ + { { 0x686d72a0ac620366L,0x4be3fb9cb6d59344L,0x6e8b44e7a1eb75b9L, + 0x84e39da391a5c10cL }, + { 0x37cc1490b38f0409L,0x029519432c2ade82L,0x9b6887831190a2d8L, + 0x25627d14231182baL } }, + /* 14 << 196 */ + { { 0x6eb550aa658a6d87L,0x1405aaa7cf9c7325L,0xd147142e5c8748c9L, + 0x7f637e4f53ede0e0L }, + { 0xf8ca277614ffad2cL,0xe58fb1bdbafb6791L,0x17158c23bf8f93fcL, + 0x7f15b3730a4a4655L } }, + /* 15 << 196 */ + { { 0x39d4add2d842ca72L,0xa71e43913ed96305L,0x5bb09cbe6700be14L, + 0x68d69d54d8befcf6L }, + { 0xa45f536737183bcfL,0x7152b7bb3370dff7L,0xcf887baabf12525bL, + 0xe7ac7bddd6d1e3cdL } }, + /* 16 << 196 */ + { { 0x25914f7881fdad90L,0xcf638f560d2cf6abL,0xb90bc03fcc054de5L, + 0x932811a718b06350L }, + { 0x2f00b3309bbd11ffL,0x76108a6fb4044974L,0x801bb9e0a851d266L, + 0x0dd099bebf8990c1L } }, + /* 17 << 196 */ + { { 0x58c5aaaaabe32986L,0x0fe9dd2a50d59c27L,0x84951ff48d307305L, + 0x6c23f82986529b78L }, + { 0x50bb22180b136a79L,0x7e2174de77a20996L,0x6f00a4b9c0bb4da6L, + 0x89a25a17efdde8daL } }, + /* 18 << 196 */ + { { 0xf728a27ec11ee01dL,0xf900553ae5f10dfbL,0x189a83c802ec893cL, + 0x3ca5bdc123f66d77L }, + { 0x9878153797eada9fL,0x59c50ab310256230L,0x346042d9323c69b3L, + 0x1b715a6d2c460449L } }, + /* 19 << 196 */ + { { 0xa41dd4766ae06e0bL,0xcdd7888e9d42e25fL,0x0f395f7456b25a20L, + 0xeadfe0ae8700e27eL }, + { 0xb09d52a969950093L,0x3525d9cb327f8d40L,0xb8235a9467df886aL, + 0x77e4b0dd035faec2L } }, + /* 20 << 196 */ + { { 0x115eb20a517d7061L,0x77fe34336c2df683L,0x6870ddc7cdc6fc67L, + 0xb16105880b87de83L }, + { 0x343584cad9c4ddbeL,0xb3164f1c3d754be2L,0x0731ed3ac1e6c894L, + 0x26327dec4f6b904cL } }, + /* 21 << 196 */ + { { 0x9d49c6de97b5cd32L,0x40835daeb5eceecdL,0xc66350edd9ded7feL, + 0x8aeebb5c7a678804L }, + { 0x51d42fb75b8ee9ecL,0xd7a17bdd8e3ca118L,0x40d7511a2ef4400eL, + 0xc48990ac875a66f4L } }, + /* 22 << 196 */ + { { 0x8de07d2a2199e347L,0xbee755562a39e051L,0x56918786916e51dcL, + 0xeb1913134a2d89ecL }, + { 0x6679610d37d341edL,0x434fbb4156d51c2bL,0xe54b7ee7d7492dbaL, + 0xaa33a79a59021493L } }, + /* 23 << 196 */ + { { 0x49fc5054e4bd6d3dL,0x09540f045ab551d0L,0x8acc90854942d3a6L, + 0x231af02f2d28323bL }, + { 0x93458cac0992c163L,0x1fef8e71888e3bb4L,0x27578da5be8c268cL, + 0xcc8be792e805ec00L } }, + /* 24 << 196 */ + { { 0x29267baec61c3855L,0xebff429d58c1fd3bL,0x22d886c08c0b93b8L, + 0xca5e00b22ddb8953L }, + { 0xcf330117c3fed8b7L,0xd49ac6fa819c01f6L,0x6ddaa6bd3c0fbd54L, + 0x917430688049a2cfL } }, + /* 25 << 196 */ + { { 0xd67f981eaff2ef81L,0xc3654d352818ae80L,0x81d050441b2aa892L, + 0x2db067bf3d099328L }, + { 0xe7c79e86703dcc97L,0xe66f9b37e133e215L,0xcdf119a6e39a7a5cL, + 0x47c60de3876f1b61L } }, + /* 26 << 196 */ + { { 0x6e405939d860f1b2L,0x3e9a1dbcf5ed4d4aL,0x3f23619ec9b6bcbdL, + 0x5ee790cf734e4497L }, + { 0xf0a834b15bdaf9bbL,0x02cedda74ca295f0L,0x4619aa2bcb8e378cL, + 0xe5613244cc987ea4L } }, + /* 27 << 196 */ + { { 0x0bc022cc76b23a50L,0x4a2793ad0a6c21ceL,0x3832878089cac3f5L, + 0x29176f1bcba26d56L }, + { 0x062961874f6f59ebL,0x86e9bca98bdc658eL,0x2ca9c4d357e30402L, + 0x5438b216516a09bbL } }, + /* 28 << 196 */ + { { 0x0a6a063c7672765aL,0x37a3ce640547b9bfL,0x42c099c898b1a633L, + 0xb5ab800d05ee6961L }, + { 0xf1963f5911a5acd6L,0xbaee615746201063L,0x36d9a649a596210aL, + 0xaed043631ba7138cL } }, + /* 29 << 196 */ + { { 0xcf817d1ca4a82b76L,0x5586960ef3806be9L,0x7ab67c8909dc6bb5L, + 0x52ace7a0114fe7ebL }, + { 0xcd987618cbbc9b70L,0x4f06fd5a604ca5e1L,0x90af14ca6dbde133L, + 0x1afe4322948a3264L } }, + /* 30 << 196 */ + { { 0xa70d2ca6c44b2c6cL,0xab7267990ef87dfeL,0x310f64dc2e696377L, + 0x49b42e684c8126a0L }, + { 0x0ea444c3cea0b176L,0x53a8ddf7cb269182L,0xf3e674ebbbba9dcbL, + 0x0d2878a8d8669d33L } }, + /* 31 << 196 */ + { { 0x04b935d5d019b6a3L,0xbb5cf88e406f1e46L,0xa1912d165b57c111L, + 0x9803fc2119ebfd78L }, + { 0x4f231c9ec07764a9L,0xd93286eeb75bd055L,0x83a9457d8ee6c9deL, + 0x046959156087ec90L } }, + /* 32 << 196 */ + { { 0x14c6dd8a58d6cd46L,0x9cb633b58e6634d2L,0xc1305047f81bc328L, + 0x12ede0e226a177e5L }, + { 0x332cca62065a6f4fL,0xc3a47ecd67be487bL,0x741eb1870f47ed1cL, + 0x99e66e58e7598b14L } }, + /* 33 << 196 */ + { { 0x6f0544ca63d0ff12L,0xe5efc784b610a05fL,0xf72917b17cad7b47L, + 0x3ff6ea20f2cac0c0L }, + { 0xcc23791bf21db8b7L,0x7dac70b1d7d93565L,0x682cda1d694bdaadL, + 0xeb88bb8c1023516dL } }, + /* 34 << 196 */ + { { 0xc4c634b4dfdbeb1bL,0x22f5ca72b4ee4deaL,0x1045a368e6524821L, + 0xed9e8a3f052b18b2L }, + { 0x9b7f2cb1b961f49aL,0x7fee2ec17b009670L,0x350d875422507a6dL, + 0x561bd7114db55f1dL } }, + /* 35 << 196 */ + { { 0x4c189ccc320bbcafL,0x568434cfdf1de48cL,0x6af1b00e0fa8f128L, + 0xf0ba9d028907583cL }, + { 0x735a400432ff9f60L,0x3dd8e4b6c25dcf33L,0xf2230f1642c74cefL, + 0xd8117623013fa8adL } }, + /* 36 << 196 */ + { { 0x36822876f51fe76eL,0x8a6811cc11d62589L,0xc3fc7e6546225718L, + 0xb7df2c9fc82fdbcdL }, + { 0x3b1d4e52dd7b205bL,0xb695947847a2e414L,0x05e4d793efa91148L, + 0xb47ed446fd2e9675L } }, + /* 37 << 196 */ + { { 0x1a7098b904c9d9bfL,0x661e28811b793048L,0xb1a16966b01ee461L, + 0xbc5213082954746fL }, + { 0xc909a0fc2477de50L,0xd80bb41c7dbd51efL,0xa85be7ec53294905L, + 0x6d465b1883958f97L } }, + /* 38 << 196 */ + { { 0x16f6f330fb6840fdL,0xfaaeb2143401e6c8L,0xaf83d30fccb5b4f8L, + 0x22885739266dec4bL }, + { 0x51b4367c7bc467dfL,0x926562e3d842d27aL,0xdfcb66140fea14a6L, + 0xeb394daef2734cd9L } }, + /* 39 << 196 */ + { { 0x3eeae5d211c0be98L,0xb1e6ed11814e8165L,0x191086bce52bce1cL, + 0x14b74cc6a75a04daL }, + { 0x63cf11868c060985L,0x071047de2dbd7f7cL,0x4e433b8bce0942caL, + 0xecbac447d8fec61dL } }, + /* 40 << 196 */ + { { 0x8f0ed0e2ebf3232fL,0xfff80f9ec52a2eddL,0xad9ab43375b55fdbL, + 0x73ca7820e42e0c11L }, + { 0x6dace0a0e6251b46L,0x89bc6b5c4c0d932dL,0x3438cd77095da19aL, + 0x2f24a9398d48bdfbL } }, + /* 41 << 196 */ + { { 0x99b47e46766561b7L,0x736600e60ed0322aL,0x06a47cb1638e1865L, + 0x927c1c2dcb136000L }, + { 0x295423370cc5df69L,0x99b37c0209d649a9L,0xc5f0043c6aefdb27L, + 0x6cdd99871be95c27L } }, + /* 42 << 196 */ + { { 0x69850931390420d2L,0x299c40ac0983efa4L,0x3a05e778af39aeadL, + 0x8427440843a45193L }, + { 0x6bcd0fb991a711a0L,0x461592c89f52ab17L,0xb49302b4da3c6ed6L, + 0xc51fddc7330d7067L } }, + /* 43 << 196 */ + { { 0x94babeb6da50d531L,0x521b840da6a7b9daL,0x5305151e404bdc89L, + 0x1bcde201d0d07449L }, + { 0xf427a78b3b76a59aL,0xf84841ce07791a1bL,0xebd314bebf91ed1cL, + 0x8e61d34cbf172943L } }, + /* 44 << 196 */ + { { 0x1d5dc4515541b892L,0xb186ee41fc9d9e54L,0x9d9f345ed5bf610dL, + 0x3e7ba65df6acca9fL }, + { 0x9dda787aa8369486L,0x09f9dab78eb5ba53L,0x5afb2033d6481bc3L, + 0x76f4ce30afa62104L } }, + /* 45 << 196 */ + { { 0xa8fa00cff4f066b5L,0x89ab5143461dafc2L,0x44339ed7a3389998L, + 0x2ff862f1bc214903L }, + { 0x2c88f985b05556e3L,0xcd96058e3467081eL,0x7d6a4176edc637eaL, + 0xe1743d0936a5acdcL } }, + /* 46 << 196 */ + { { 0x66fd72e27eb37726L,0xf7fa264e1481a037L,0x9fbd3bde45f4aa79L, + 0xed1e0147767c3e22L }, + { 0x7621f97982e7abe2L,0x19eedc7245f633f8L,0xe69b155e6137bf3aL, + 0xa0ad13ce414ee94eL } }, + /* 47 << 196 */ + { { 0x93e3d5241c0e651aL,0xab1a6e2a02ce227eL,0xe7af17974ab27ecaL, + 0x245446debd444f39L }, + { 0x59e22a2156c07613L,0x43deafcef4275498L,0x10834ccb67fd0946L, + 0xa75841e547406edfL } }, + /* 48 << 196 */ + { { 0xebd6a6777b0ac93dL,0xa6e37b0d78f5e0d7L,0x2516c09676f5492bL, + 0x1e4bf8889ac05f3aL }, + { 0xcdb42ce04df0ba2bL,0x935d5cfd5062341bL,0x8a30333382acac20L, + 0x429438c45198b00eL } }, + /* 49 << 196 */ + { { 0x1d083bc9049d33faL,0x58b82dda946f67ffL,0xac3e2db867a1d6a3L, + 0x62e6bead1798aac8L }, + { 0xfc85980fde46c58cL,0xa7f6937969c8d7beL,0x23557927837b35ecL, + 0x06a933d8e0790c0cL } }, + /* 50 << 196 */ + { { 0x827c0e9b077ff55dL,0x53977798bb26e680L,0x595308741d9cb54fL, + 0xcca3f4494aac53efL }, + { 0x11dc5c87a07eda0fL,0xc138bccffd6400c8L,0x549680d313e5da72L, + 0xc93eed824540617eL } }, + /* 51 << 196 */ + { { 0xfd3db1574d0b75c0L,0x9716eb426386075bL,0x0639605c817b2c16L, + 0x09915109f1e4f201L }, + { 0x35c9a9285cca6c3bL,0xb25f7d1a3505c900L,0xeb9f7d20630480c4L, + 0xc3c7b8c62a1a501cL } }, + /* 52 << 196 */ + { { 0x3f99183c5a1f8e24L,0xfdb118fa9dd255f0L,0xb9b18b90c27f62a6L, + 0xe8f732f7396ec191L }, + { 0x524a2d910be786abL,0x5d32adef0ac5a0f5L,0x9b53d4d69725f694L, + 0x032a76c60510ba89L } }, + /* 53 << 196 */ + { { 0x840391a3ebeb1544L,0x44b7b88c3ed73ac3L,0xd24bae7a256cb8b3L, + 0x7ceb151ae394cb12L }, + { 0xbd6b66d05bc1e6a8L,0xec70cecb090f07bfL,0x270644ed7d937589L, + 0xee9e1a3d5f1dccfeL } }, + /* 54 << 196 */ + { { 0xb0d40a84745b98d2L,0xda429a212556ed40L,0xf676eced85148cb9L, + 0x5a22d40cded18936L }, + { 0x3bc4b9e570e8a4ceL,0xbfd1445b9eae0379L,0xf23f2c0c1a0bd47eL, + 0xa9c0bb31e1845531L } }, + /* 55 << 196 */ + { { 0x9ddc4d600a4c3f6bL,0xbdfaad792c15ef44L,0xce55a2367f484accL, + 0x08653ca7055b1f15L }, + { 0x2efa8724538873a3L,0x09299e5dace1c7e7L,0x07afab66ade332baL, + 0x9be1fdf692dd71b7L } }, + /* 56 << 196 */ + { { 0xa49b5d595758b11cL,0x0b852893c8654f40L,0xb63ef6f452379447L, + 0xd4957d29105e690cL }, + { 0x7d484363646559b0L,0xf4a8273c49788a8eL,0xee406cb834ce54a9L, + 0x1e1c260ff86fda9bL } }, + /* 57 << 196 */ + { { 0xe150e228cf6a4a81L,0x1fa3b6a31b488772L,0x1e6ff110c5a9c15bL, + 0xc6133b918ad6aa47L }, + { 0x8ac5d55c9dffa978L,0xba1d1c1d5f3965f2L,0xf969f4e07732b52fL, + 0xfceecdb5a5172a07L } }, + /* 58 << 196 */ + { { 0xb0120a5f10f2b8f5L,0xc83a6cdf5c4c2f63L,0x4d47a491f8f9c213L, + 0xd9e1cce5d3f1bbd5L }, + { 0x0d91bc7caba7e372L,0xfcdc74c8dfd1a2dbL,0x05efa800374618e5L, + 0x1121696915a7925eL } }, + /* 59 << 196 */ + { { 0xd4c89823f6021c5dL,0x880d5e84eff14423L,0x6523bc5a6dcd1396L, + 0xd1acfdfc113c978bL }, + { 0xb0c164e8bbb66840L,0xf7f4301e72b58459L,0xc29ad4a6a638e8ecL, + 0xf5ab896146b78699L } }, + /* 60 << 196 */ + { { 0x9dbd79740e954750L,0x0121de8864f9d2c6L,0x2e597b42d985232eL, + 0x55b6c3c553451777L }, + { 0xbb53e547519cb9fbL,0xf134019f8428600dL,0x5a473176e081791aL, + 0x2f3e226335fb0c08L } }, + /* 61 << 196 */ + { { 0xb28c301773d273b0L,0xccd210767721ef9aL,0x054cc292b650dc39L, + 0x662246de6188045eL }, + { 0x904b52fa6b83c0d1L,0xa72df26797e9cd46L,0x886b43cd899725e4L, + 0x2b651688d849ff22L } }, + /* 62 << 196 */ + { { 0x60479b7902f34533L,0x5e354c140c77c148L,0xb4bb7581a8537c78L, + 0x188043d7efe1495fL }, + { 0x9ba12f428c1d5026L,0x2e0c8a2693d4aaabL,0xbdba7b8baa57c450L, + 0x140c9ad69bbdafefL } }, + /* 63 << 196 */ + { { 0x2067aa4225ac0f18L,0xf7b1295b04d1fbf3L,0x14829111a4b04824L, + 0x2ce3f19233bd5e91L }, + { 0x9c7a1d558f2e1b72L,0xfe932286302aa243L,0x497ca7b4d4be9554L, + 0xb8e821b8e0547a6eL } }, + /* 64 << 196 */ + { { 0xfb2838be67e573e0L,0x05891db94084c44bL,0x9131137396c1c2c5L, + 0x6aebfa3fd958444bL }, + { 0xac9cdce9e56e55c1L,0x7148ced32caa46d0L,0x2e10c7efb61fe8ebL, + 0x9fd835daff97cf4dL } }, + /* 0 << 203 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 203 */ + { { 0xa36da109081e9387L,0xfb9780d78c935828L,0xd5940332e540b015L, + 0xc9d7b51be0f466faL }, + { 0xfaadcd41d6d9f671L,0xba6c1e28b1a2ac17L,0x066a7833ed201e5fL, + 0x19d99719f90f462bL } }, + /* 2 << 203 */ + { { 0xf431f462060b5f61L,0xa56f46b47bd057c2L,0x348dca6c47e1bf65L, + 0x9a38783e41bcf1ffL }, + { 0x7a5d33a9da710718L,0x5a7799872e0aeaf6L,0xca87314d2d29d187L, + 0xfa0edc3ec687d733L } }, + /* 3 << 203 */ + { { 0x9df336216a31e09bL,0xde89e44dc1350e35L,0x292148714ca0cf52L, + 0xdf3796720b88a538L }, + { 0xc92a510a2591d61bL,0x79aa87d7585b447bL,0xf67db604e5287f77L, + 0x1697c8bf5efe7a80L } }, + /* 4 << 203 */ + { { 0x1c894849cb198ac7L,0xa884a93d0f264665L,0x2da964ef9b200678L, + 0x3c351b87009834e6L }, + { 0xafb2ef9fe2c4b44bL,0x580f6c473326790cL,0xb84805210b02264aL, + 0x8ba6f9e242a194e2L } }, + /* 5 << 203 */ + { { 0xfc87975f8fb54738L,0x3516078827c3ead3L,0x834116d2b74a085aL, + 0x53c99a73a62fe996L }, + { 0x87585be05b81c51bL,0x925bafa8be0852b7L,0x76a4fafda84d19a7L, + 0x39a45982585206d4L } }, + /* 6 << 203 */ + { { 0x499b6ab65eb03c0eL,0xf19b795472bc3fdeL,0xa86b5b9c6e3a80d2L, + 0xe43775086d42819fL }, + { 0xc1663650bb3ee8a3L,0x75eb14fcb132075fL,0xa8ccc9067ad834f6L, + 0xea6a2474e6e92ffdL } }, + /* 7 << 203 */ + { { 0x9d72fd950f8d6758L,0xcb84e101408c07ddL,0xb9114bfda5e23221L, + 0x358b5fe2e94e742cL }, + { 0x1c0577ec95f40e75L,0xf01554513d73f3d6L,0x9d55cd67bd1b9b66L, + 0x63e86e78af8d63c7L } }, + /* 8 << 203 */ + { { 0x39d934abd3c095f1L,0x04b261bee4b76d71L,0x1d2e6970e73e6984L, + 0x879fb23b5e5fcb11L }, + { 0x11506c72dfd75490L,0x3a97d08561bcf1c1L,0x43201d82bf5e7007L, + 0x7f0ac52f798232a7L } }, + /* 9 << 203 */ + { { 0x2715cbc46eb564d4L,0x8d6c752c9e570e29L,0xf80247c89ef5fd5dL, + 0xc3c66b46d53eb514L }, + { 0x9666b4010f87de56L,0xce62c06fc6c603b5L,0xae7b4c607e4fc942L, + 0x38ac0b77663a9c19L } }, + /* 10 << 203 */ + { { 0xcb4d20ee4b049136L,0x8b63bf12356a4613L,0x1221aef670e08128L, + 0xe62d8c514acb6b16L }, + { 0x71f64a67379e7896L,0xb25237a2cafd7fa5L,0xf077bd983841ba6aL, + 0xc4ac02443cd16e7eL } }, + /* 11 << 203 */ + { { 0x548ba86921fea4caL,0xd36d0817f3dfdac1L,0x09d8d71ff4685fafL, + 0x8eff66bec52c459aL }, + { 0x182faee70b57235eL,0xee3c39b10106712bL,0x5107331fc0fcdcb0L, + 0x669fb9dca51054baL } }, + /* 12 << 203 */ + { { 0xb25101fb319d7682L,0xb02931290a982feeL,0x51c1c9b90261b344L, + 0x0e008c5bbfd371faL }, + { 0xd866dd1c0278ca33L,0x666f76a6e5aa53b1L,0xe5cfb7796013a2cfL, + 0x1d3a1aada3521836L } }, + /* 13 << 203 */ + { { 0xcedd253173faa485L,0xc8ee6c4fc0a76878L,0xddbccfc92a11667dL, + 0x1a418ea91c2f695aL }, + { 0xdb11bd9251f73971L,0x3e4b3c82da2ed89fL,0x9a44f3f4e73e0319L, + 0xd1e3de0f303431afL } }, + /* 14 << 203 */ + { { 0x3c5604ff50f75f9cL,0x1d8eddf37e752b22L,0x0ef074dd3c9a1118L, + 0xd0ffc172ccb86d7bL }, + { 0xabd1ece3037d90f2L,0xe3f307d66055856cL,0x422f93287e4c6dafL, + 0x902aac66334879a0L } }, + /* 15 << 203 */ + { { 0xb6a1e7bf94cdfadeL,0x6c97e1ed7fc6d634L,0x662ad24da2fb63f8L, + 0xf81be1b9a5928405L }, + { 0x86d765e4d14b4206L,0xbecc2e0e8fa0db65L,0xa28838e0b17fc76cL, + 0xe49a602ae37cf24eL } }, + /* 16 << 203 */ + { { 0x76b4131a567193ecL,0xaf3c305ae5f6e70bL,0x9587bd39031eebddL, + 0x5709def871bbe831L }, + { 0x570599830eb2b669L,0x4d80ce1b875b7029L,0x838a7da80364ac16L, + 0x2f431d23be1c83abL } }, + /* 17 << 203 */ + { { 0xe56812a6f9294dd3L,0xb448d01f9b4b0d77L,0xf3ae606104e8305cL, + 0x2bead64594d8c63eL }, + { 0x0a85434d84fd8b07L,0x537b983ff7a9dee5L,0xedcc5f18ef55bd85L, + 0x2041af6221c6cf8bL } }, + /* 18 << 203 */ + { { 0x8e52874cb940c71eL,0x211935a9db5f4b3aL,0x94350492301b1dc3L, + 0x33d2646d29958620L }, + { 0x16b0d64bef911404L,0x9d1f25ea9a3c5ef4L,0x20f200eb4a352c78L, + 0x43929f2c4bd0b428L } }, + /* 19 << 203 */ + { { 0xa5656667c7196e29L,0x7992c2f09391be48L,0xaaa97cbd9ee0cd6eL, + 0x51b0310c3dc8c9bfL }, + { 0x237f8acfdd9f22cbL,0xbb1d81a1b585d584L,0x8d5d85f58c416388L, + 0x0d6e5a5a42fe474fL } }, + /* 20 << 203 */ + { { 0xe781276638235d4eL,0x1c62bd67496e3298L,0x8378660c3f175bc8L, + 0x4d04e18917afdd4dL }, + { 0x32a8160185a8068cL,0xdb58e4e192b29a85L,0xe8a65b86c70d8a3bL, + 0x5f0e6f4e98a0403bL } }, + /* 21 << 203 */ + { { 0x0812968469ed2370L,0x34dc30bd0871ee26L,0x3a5ce9487c9c5b05L, + 0x7d487b8043a90c87L }, + { 0x4089ba37dd0e7179L,0x45f80191b4041811L,0x1c3e105898747ba5L, + 0x98c4e13a6e1ae592L } }, + /* 22 << 203 */ + { { 0xd44636e6e82c9f9eL,0x711db87cc33a1043L,0x6f431263aa8aec05L, + 0x43ff120d2744a4aaL }, + { 0xd3bd892fae77779bL,0xf0fe0cc98cdc9f82L,0xca5f7fe6f1c5b1bcL, + 0xcc63a68244929a72L } }, + /* 23 << 203 */ + { { 0xc7eaba0c09dbe19aL,0x2f3585ad6b5c73c2L,0x8ab8924b0ae50c30L, + 0x17fcd27a638b30baL }, + { 0xaf414d3410b3d5a5L,0x09c107d22a9accf1L,0x15dac49f946a6242L, + 0xaec3df2ad707d642L } }, + /* 24 << 203 */ + { { 0x2c2492b73f894ae0L,0xf59df3e5b75f18ceL,0x7cb740d28f53cad0L, + 0x3eb585fbc4f01294L }, + { 0x17da0c8632c7f717L,0xeb8c795baf943f4cL,0x4ee23fb5f67c51d2L, + 0xef18757568889949L } }, + /* 25 << 203 */ + { { 0xa6b4bdb20389168bL,0xc4ecd258ea577d03L,0x3a63782b55743082L, + 0x6f678f4cc72f08cdL }, + { 0x553511cf65e58dd8L,0xd53b4e3ed402c0cdL,0x37de3e29a037c14cL, + 0x86b6c516c05712aaL } }, + /* 26 << 203 */ + { { 0x2834da3eb38dff6fL,0xbe012c52ea636be8L,0x292d238c61dd37f8L, + 0x0e54523f8f8142dbL }, + { 0xe31eb436036a05d8L,0x83e3cdff1e93c0ffL,0x3fd2fe0f50821ddfL, + 0xc8e19b0dff9eb33bL } }, + /* 27 << 203 */ + { { 0xc8cc943fb569a5feL,0xad0090d4d4342d75L,0x82090b4bcaeca000L, + 0xca39687f1bd410ebL }, + { 0xe7bb0df765959d77L,0x39d782189c964999L,0xd87f62e8b2415451L, + 0xe5efb774bed76108L } }, + /* 28 << 203 */ + { { 0x3ea011a4e822f0d0L,0xbc647ad15a8704f8L,0xbb315b3550c6820fL, + 0x863dec3db7e76becL }, + { 0x01ff5d3af017bfc7L,0x20054439976b8229L,0x067fca370bbd0d3bL, + 0xf63dde647f5e3d0fL } }, + /* 29 << 203 */ + { { 0x22dbefb32a4c94e9L,0xafbff0fe96f8278aL,0x80aea0b13503793dL, + 0xb22380295f06cd29L }, + { 0x65703e578ec3fecaL,0x06c38314393e7053L,0xa0b751eb7c6734c4L, + 0xd2e8a435c59f0f1eL } }, + /* 30 << 203 */ + { { 0x147d90525e9ca895L,0x2f4dd31e972072dfL,0xa16fda8ee6c6755cL, + 0xc66826ffcf196558L }, + { 0x1f1a76a30cf43895L,0xa9d604e083c3097bL,0xe190830966390e0eL, + 0xa50bf753b3c85effL } }, + /* 31 << 203 */ + { { 0x0696bddef6a70251L,0x548b801b3c6ab16aL,0x37fcf704a4d08762L, + 0x090b3defdff76c4eL }, + { 0x87e8cb8969cb9158L,0x44a90744995ece43L,0xf85395f40ad9fbf5L, + 0x49b0f6c54fb0c82dL } }, + /* 32 << 203 */ + { { 0x75d9bc15adf7cccfL,0x81a3e5d6dfa1e1b0L,0x8c39e444249bc17eL, + 0xf37dccb28ea7fd43L }, + { 0xda654873907fba12L,0x35daa6da4a372904L,0x0564cfc66283a6c5L, + 0xd09fa4f64a9395bfL } }, + /* 33 << 203 */ + { { 0x688e9ec9aeb19a36L,0xd913f1cec7bfbfb4L,0x797b9a3c61c2faa6L, + 0x2f979bec6a0a9c12L }, + { 0xb5969d0f359679ecL,0xebcf523d079b0460L,0xfd6b000810fab870L, + 0x3f2edcda9373a39cL } }, + /* 34 << 203 */ + { { 0x0d64f9a76f568431L,0xf848c27c02f8898cL,0xf418ade1260b5bd5L, + 0xc1f3e3236973dee8L }, + { 0x46e9319c26c185ddL,0x6d85b7d8546f0ac4L,0x427965f2247f9d57L, + 0xb519b636b0035f48L } }, + /* 35 << 203 */ + { { 0x6b6163a9ab87d59cL,0xff9f58c339caaa11L,0x4ac39cde3177387bL, + 0x5f6557c2873e77f9L }, + { 0x6750400636a83041L,0x9b1c96ca75ef196cL,0xf34283deb08c7940L, + 0x7ea096441128c316L } }, + /* 36 << 203 */ + { { 0xb510b3b56aa39dffL,0x59b43da29f8e4d8cL,0xa8ce31fd9e4c4b9fL, + 0x0e20be26c1303c01L }, + { 0x18187182e8ee47c9L,0xd9687cdb7db98101L,0x7a520e4da1e14ff6L, + 0x429808ba8836d572L } }, + /* 37 << 203 */ + { { 0xa37ca60d4944b663L,0xf901f7a9a3f91ae5L,0xe4e3e76e9e36e3b1L, + 0x9aa219cf29d93250L }, + { 0x347fe275056a2512L,0xa4d643d9de65d95cL,0x9669d396699fc3edL, + 0xb598dee2cf8c6bbeL } }, + /* 38 << 203 */ + { { 0x682ac1e5dda9e5c6L,0x4e0d3c72caa9fc95L,0x17faaade772bea44L, + 0x5ef8428cab0009c8L }, + { 0xcc4ce47a460ff016L,0xda6d12bf725281cbL,0x44c678480223aad2L, + 0x6e342afa36256e28L } }, + /* 39 << 203 */ + { { 0x1400bb0b93a37c04L,0x62b1bc9bdd10bd96L,0x7251adeb0dac46b7L, + 0x7d33b92e7be4ef51L }, + { 0x28b2a94be61fa29aL,0x4b2be13f06422233L,0x36d6d062330d8d37L, + 0x5ef80e1eb28ca005L } }, + /* 40 << 203 */ + { { 0x174d46996d16768eL,0x9fc4ff6a628bf217L,0x77705a94154e490dL, + 0x9d96dd288d2d997aL }, + { 0x77e2d9d8ce5d72c4L,0x9d06c5a4c11c714fL,0x02aa513679e4a03eL, + 0x1386b3c2030ff28bL } }, + /* 41 << 203 */ + { { 0xfe82e8a6fb283f61L,0x7df203e5f3abc3fbL,0xeec7c3513a4d3622L, + 0xf7d17dbfdf762761L }, + { 0xc3956e44522055f0L,0xde3012db8fa748dbL,0xca9fcb63bf1dcc14L, + 0xa56d9dcfbe4e2f3aL } }, + /* 42 << 203 */ + { { 0xb86186b68bcec9c2L,0x7cf24df9680b9f06L,0xc46b45eac0d29281L, + 0xfff42bc507b10e12L }, + { 0x12263c404d289427L,0x3d5f1899b4848ec4L,0x11f97010d040800cL, + 0xb4c5f529300feb20L } }, + /* 43 << 203 */ + { { 0xcc543f8fde94fdcbL,0xe96af739c7c2f05eL,0xaa5e0036882692e1L, + 0x09c75b68950d4ae9L }, + { 0x62f63df2b5932a7aL,0x2658252ede0979adL,0x2a19343fb5e69631L, + 0x718c7501525b666bL } }, + /* 44 << 203 */ + { { 0x26a42d69ea40dc3aL,0xdc84ad22aecc018fL,0x25c36c7b3270f04aL, + 0x46ba6d4750fa72edL }, + { 0x6c37d1c593e58a8eL,0xa2394731120c088cL,0xc3be4263cb6e86daL, + 0x2c417d367126d038L } }, + /* 45 << 203 */ + { { 0x5b70f9c58b6f8efaL,0x671a2faa37718536L,0xd3ced3c6b539c92bL, + 0xe56f1bd9a31203c2L }, + { 0x8b096ec49ff3c8ebL,0x2deae43243491ceaL,0x2465c6eb17943794L, + 0x5d267e6620586843L } }, + /* 46 << 203 */ + { { 0x9d3d116db07159d0L,0xae07a67fc1896210L,0x8fc84d87bb961579L, + 0x30009e491c1f8dd6L }, + { 0x8a8caf22e3132819L,0xcffa197cf23ab4ffL,0x58103a44205dd687L, + 0x57b796c30ded67a2L } }, + /* 47 << 203 */ + { { 0x0b9c3a6ca1779ad7L,0xa33cfe2e357c09c5L,0x2ea293153db4a57eL, + 0x919596958ebeb52eL }, + { 0x118db9a6e546c879L,0x8e996df46295c8d6L,0xdd99048455ec806bL, + 0x24f291ca165c1035L } }, + /* 48 << 203 */ + { { 0xcca523bb440e2229L,0x324673a273ef4d04L,0xaf3adf343e11ec39L, + 0x6136d7f1dc5968d3L }, + { 0x7a7b2899b053a927L,0x3eaa2661ae067ecdL,0x8549b9c802779cd9L, + 0x061d7940c53385eaL } }, + /* 49 << 203 */ + { { 0x3e0ba883f06d18bdL,0x4ba6de53b2700843L,0xb966b668591a9e4dL, + 0x93f675677f4fa0edL }, + { 0x5a02711b4347237bL,0xbc041e2fe794608eL,0x55af10f570f73d8cL, + 0xd2d4d4f7bb7564f7L } }, + /* 50 << 203 */ + { { 0xd7d27a89b3e93ce7L,0xf7b5a8755d3a2c1bL,0xb29e68a0255b218aL, + 0xb533837e8af76754L }, + { 0xd1b05a73579fab2eL,0xb41055a1ecd74385L,0xb2369274445e9115L, + 0x2972a7c4f520274eL } }, + /* 51 << 203 */ + { { 0x6c08334ef678e68aL,0x4e4160f099b057edL,0x3cfe11b852ccb69aL, + 0x2fd1823a21c8f772L }, + { 0xdf7f072f3298f055L,0x8c0566f9fec74a6eL,0xe549e0195bb4d041L, + 0x7c3930ba9208d850L } }, + /* 52 << 203 */ + { { 0xe07141fcaaa2902bL,0x539ad799e4f69ad3L,0xa6453f94813f9ffdL, + 0xc58d3c48375bc2f7L }, + { 0xb3326fad5dc64e96L,0x3aafcaa9b240e354L,0x1d1b0903aca1e7a9L, + 0x4ceb97671211b8a0L } }, + /* 53 << 203 */ + { { 0xeca83e49e32a858eL,0x4c32892eae907badL,0xd5b42ab62eb9b494L, + 0x7fde3ee21eabae1bL }, + { 0x13b5ab09caf54957L,0xbfb028bee5f5d5d5L,0x928a06502003e2c0L, + 0x90793aac67476843L } }, + /* 54 << 203 */ + { { 0x5e942e79c81710a0L,0x557e4a3627ccadd4L,0x72a2bc564bcf6d0cL, + 0x09ee5f4326d7b80cL }, + { 0x6b70dbe9d4292f19L,0x56f74c2663f16b18L,0xc23db0f735fbb42aL, + 0xb606bdf66ae10040L } }, + /* 55 << 203 */ + { { 0x1eb15d4d044573acL,0x7dc3cf86556b0ba4L,0x97af9a33c60df6f7L, + 0x0b1ef85ca716ce8cL }, + { 0x2922f884c96958beL,0x7c32fa9435690963L,0x2d7f667ceaa00061L, + 0xeaaf7c173547365cL } }, + /* 56 << 203 */ + { { 0x1eb4de4687032d58L,0xc54f3d835e2c79e0L,0x07818df45d04ef23L, + 0x55faa9c8673d41b4L }, + { 0xced64f6f89b95355L,0x4860d2eab7415c84L,0x5fdb9bd2050ebad3L, + 0xdb53e0cc6685a5bfL } }, + /* 57 << 203 */ + { { 0xb830c0319feb6593L,0xdd87f3106accff17L,0x2303ebab9f555c10L, + 0x94603695287e7065L }, + { 0xf88311c32e83358cL,0x508dd9b4eefb0178L,0x7ca237062dba8652L, + 0x62aac5a30047abe5L } }, + /* 58 << 203 */ + { { 0x9a61d2a08b1ea7b3L,0xd495ab63ae8b1485L,0x38740f8487052f99L, + 0x178ebe5bb2974eeaL }, + { 0x030bbcca5b36d17fL,0xb5e4cce3aaf86eeaL,0xb51a022068f8e9e0L, + 0xa434879609eb3e75L } }, + /* 59 << 203 */ + { { 0xbe592309eef1a752L,0x5d7162d76f2aa1edL,0xaebfb5ed0f007dd2L, + 0x255e14b2c89edd22L }, + { 0xba85e0720303b697L,0xc5d17e25f05720ffL,0x02b58d6e5128ebb6L, + 0x2c80242dd754e113L } }, + /* 60 << 203 */ + { { 0x919fca5fabfae1caL,0x937afaac1a21459bL,0x9e0ca91c1f66a4d2L, + 0x194cc7f323ec1331L }, + { 0xad25143a8aa11690L,0xbe40ad8d09b59e08L,0x37d60d9be750860aL, + 0x6c53b008c6bf434cL } }, + /* 61 << 203 */ + { { 0xb572415d1356eb80L,0xb8bf9da39578ded8L,0x22658e365e8fb38bL, + 0x9b70ce225af8cb22L }, + { 0x7c00018a829a8180L,0x84329f93b81ed295L,0x7c343ea25f3cea83L, + 0x38f8655f67586536L } }, + /* 62 << 203 */ + { { 0xa661a0d01d3ec517L,0x98744652512321aeL,0x084ca591eca92598L, + 0xa9bb9dc91dcb3febL }, + { 0x14c5435578b4c240L,0x5ed62a3b610cafdcL,0x07512f371b38846bL, + 0x571bb70ab0e38161L } }, + /* 63 << 203 */ + { { 0xb556b95b2da705d2L,0x3ef8ada6b1a08f98L,0x85302ca7ddecfbe5L, + 0x0e530573943105cdL }, + { 0x60554d5521a9255dL,0x63a32fa1f2f3802aL,0x35c8c5b0cd477875L, + 0x97f458ea6ad42da1L } }, + /* 64 << 203 */ + { { 0x832d7080eb6b242dL,0xd30bd0233b71e246L,0x7027991bbe31139dL, + 0x68797e91462e4e53L }, + { 0x423fe20a6b4e185aL,0x82f2c67e42d9b707L,0x25c817684cf7811bL, + 0xbd53005e045bb95dL } }, + /* 0 << 210 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 210 */ + { { 0xe5f649be9d8e68fdL,0xdb0f05331b044320L,0xf6fde9b3e0c33398L, + 0x92f4209b66c8cfaeL }, + { 0xe9d1afcc1a739d4bL,0x09aea75fa28ab8deL,0x14375fb5eac6f1d0L, + 0x6420b560708f7aa5L } }, + /* 2 << 210 */ + { { 0x9eae499c6254dc41L,0x7e2939247a837e7eL,0x74aec08c090524a7L, + 0xf82b92198d6f55f2L }, + { 0x493c962e1402cec5L,0x9f17ca17fa2f30e7L,0xbcd783e8e9b879cbL, + 0xea3d8c145a6f145fL } }, + /* 3 << 210 */ + { { 0xdede15e75e0dee6eL,0x74f24872dc628aa2L,0xd3e9c4fe7861bb93L, + 0x56d4822a6187b2e0L }, + { 0xb66417cfc59826f9L,0xca2609692408169eL,0xedf69d06c79ef885L, + 0x00031f8adc7d138fL } }, + /* 4 << 210 */ + { { 0x103c46e60ebcf726L,0x4482b8316231470eL,0x6f6dfaca487c2109L, + 0x2e0ace9762e666efL }, + { 0x3246a9d31f8d1f42L,0x1b1e83f1574944d2L,0x13dfa63aa57f334bL, + 0x0cf8daed9f025d81L } }, + /* 5 << 210 */ + { { 0x30d78ea800ee11c1L,0xeb053cd4b5e3dd75L,0x9b65b13ed58c43c5L, + 0xc3ad49bdbd151663L }, + { 0x99fd8e41b6427990L,0x12cf15bd707eae1eL,0x29ad4f1b1aabb71eL, + 0x5143e74d07545d0eL } }, + /* 6 << 210 */ + { { 0x30266336c88bdee1L,0x25f293065876767cL,0x9c078571c6731996L, + 0xc88690b2ed552951L }, + { 0x274f2c2d852705b4L,0xb0bf8d444e09552dL,0x7628beeb986575d1L, + 0x407be2387f864651L } }, + /* 7 << 210 */ + { { 0x0e5e3049a639fc6bL,0xe75c35d986003625L,0x0cf35bd85dcc1646L, + 0x8bcaced26c26273aL }, + { 0xe22ecf1db5536742L,0x013dd8971a9e068bL,0x17f411cb8a7909c5L, + 0x5757ac98861dd506L } }, + /* 8 << 210 */ + { { 0x85de1f0d1e935abbL,0xdefd10b4154de37aL,0xb8d9e392369cebb5L, + 0x54d5ef9b761324beL }, + { 0x4d6341ba74f17e26L,0xc0a0e3c878c1dde4L,0xa6d7758187d918fdL, + 0x6687601502ca3a13L } }, + /* 9 << 210 */ + { { 0xc7313e9cf36658f0L,0xc433ef1c71f8057eL,0x853262461b6a835aL, + 0xc8f053987c86394cL }, + { 0xff398cdfe983c4a1L,0xbf5e816203b7b931L,0x93193c46b7b9045bL, + 0x1e4ebf5da4a6e46bL } }, + /* 10 << 210 */ + { { 0xf9942a6043a24fe7L,0x29c1191effb3492bL,0x9f662449902fde05L, + 0xc792a7ac6713c32dL }, + { 0x2fd88ad8b737982cL,0x7e3a0319a21e60e3L,0x09b0de447383591aL, + 0x6df141ee8310a456L } }, + /* 11 << 210 */ + { { 0xaec1a039e6d6f471L,0x14b2ba0f1198d12eL,0xebc1a1603aeee5acL, + 0x401f4836e0b964ceL }, + { 0x2ee437964fd03f66L,0x3fdb4e49dd8f3f12L,0x6ef267f629380f18L, + 0x3e8e96708da64d16L } }, + /* 12 << 210 */ + { { 0xbc19180c207674f1L,0x112e09a733ae8fdbL,0x996675546aaeb71eL, + 0x79432af1e101b1c7L }, + { 0xd5eb558fde2ddec6L,0x81392d1f5357753fL,0xa7a76b973ae1158aL, + 0x416fbbff4a899991L } }, + /* 13 << 210 */ + { { 0x9e65fdfd0d4a9dcfL,0x7bc29e48944ddf12L,0xbc1a92d93c856866L, + 0x273c69056e98dfe2L }, + { 0x69fce418cdfaa6b8L,0x606bd8235061c69fL,0x42d495a06af75e27L, + 0x8ed3d5056d873a1fL } }, + /* 14 << 210 */ + { { 0xaf5528416ab25b6aL,0xc6c0ffc72b1a4523L,0xab18827b21c99e03L, + 0x060e86489034691bL }, + { 0x5207f90f93c7f398L,0x9f4a96cb82f8d10bL,0xdd71cd793ad0f9e3L, + 0x84f435d2fc3a54f5L } }, + /* 15 << 210 */ + { { 0x4b03c55b8e33787fL,0xef42f975a6384673L,0xff7304f75051b9f0L, + 0x18aca1dc741c87c2L }, + { 0x56f120a72d4bfe80L,0xfd823b3d053e732cL,0x11bccfe47537ca16L, + 0xdf6c9c741b5a996bL } }, + /* 16 << 210 */ + { { 0xee7332c7904fc3faL,0x14a23f45c7e3636aL,0xc38659c3f091d9aaL, + 0x4a995e5db12d8540L }, + { 0x20a53becf3a5598aL,0x56534b17b1eaa995L,0x9ed3dca4bf04e03cL, + 0x716c563ad8d56268L } }, + /* 17 << 210 */ + { { 0x27ba77a41d6178e7L,0xe4c80c4068a1ff8eL,0x750110990a13f63dL, + 0x7bf33521a61d46f3L }, + { 0x0aff218e10b365bbL,0x810218040fd7ea75L,0x05a3fd8aa4b3a925L, + 0xb829e75f9b3db4e6L } }, + /* 18 << 210 */ + { { 0x6bdc75a54d53e5fbL,0x04a5dc02d52717e3L,0x86af502fe9a42ec2L, + 0x8867e8fb2630e382L }, + { 0xbf845c6ebec9889bL,0x54f491f2cb47c98dL,0xa3091fba790c2a12L, + 0xd7f6fd78c20f708bL } }, + /* 19 << 210 */ + { { 0xa569ac30acde5e17L,0xd0f996d06852b4d7L,0xe51d4bb54609ae54L, + 0x3fa37d170daed061L }, + { 0x62a8868434b8fb41L,0x99a2acbd9efb64f1L,0xb75c1a5e6448e1f2L, + 0xfa99951a42b5a069L } }, + /* 20 << 210 */ + { { 0x6d956e892f3b26e7L,0xf4709860da875247L,0x3ad151792482dda3L, + 0xd64110e3017d82f0L }, + { 0x14928d2cfad414e4L,0x2b155f582ed02b24L,0x481a141bcb821bf1L, + 0x12e3c7704f81f5daL } }, + /* 21 << 210 */ + { { 0xe49c5de59fff8381L,0x110532325bbec894L,0xa0d051cc454d88c4L, + 0x4f6db89c1f8e531bL }, + { 0x34fe3fd6ca563a44L,0x7f5c221558da8ab9L,0x8445016d9474f0a1L, + 0x17d34d61cb7d8a0aL } }, + /* 22 << 210 */ + { { 0x8e9d39101c474019L,0xcaff2629d52ceefbL,0xf9cf3e32c1622c2bL, + 0xd4b95e3ce9071a05L }, + { 0xfbbca61f1594438cL,0x1eb6e6a604aadedfL,0x853027f468e14940L, + 0x221d322adfabda9cL } }, + /* 23 << 210 */ + { { 0xed8ea9f6b7cb179aL,0xdc7b764db7934dccL,0xfcb139405e09180dL, + 0x6629a6bfb47dc2ddL }, + { 0xbfc55e4e9f5a915eL,0xb1db9d376204441eL,0xf82d68cf930c5f53L, + 0x17d3a142cbb605b1L } }, + /* 24 << 210 */ + { { 0xdd5944ea308780f2L,0xdc8de7613845f5e4L,0x6beaba7d7624d7a3L, + 0x1e709afd304df11eL }, + { 0x9536437602170456L,0xbf204b3ac8f94b64L,0x4e53af7c5680ca68L, + 0x0526074ae0c67574L } }, + /* 25 << 210 */ + { { 0x95d8cef8ecd92af6L,0xe6b9fa7a6cd1745aL,0x3d546d3da325c3e4L, + 0x1f57691d9ae93aaeL }, + { 0xe891f3fe9d2e1a33L,0xd430093fac063d35L,0xeda59b125513a327L, + 0xdc2134f35536f18fL } }, + /* 26 << 210 */ + { { 0xaa51fe2c5c210286L,0x3f68aaee1cab658cL,0x5a23a00bf9357292L, + 0x9a626f397efdabedL }, + { 0xfe2b3bf3199d78e3L,0xb7a2af7771bbc345L,0x3d19827a1e59802cL, + 0x823bbc15b487a51cL } }, + /* 27 << 210 */ + { { 0x856139f299d0a422L,0x9ac3df65f456c6fbL,0xaddf65c6701f8bd6L, + 0x149f321e3758df87L }, + { 0xb1ecf714721b7ebaL,0xe17df09831a3312aL,0xdb2fd6ecd5c4d581L, + 0xfd02996f8fcea1b3L } }, + /* 28 << 210 */ + { { 0xe29fa63e7882f14fL,0xc9f6dc3507c6cadcL,0x46f22d6fb882bed0L, + 0x1a45755bd118e52cL }, + { 0x9f2c7c277c4608cfL,0x7ccbdf32568012c2L,0xfcb0aedd61729b0eL, + 0x7ca2ca9ef7d75dbfL } }, + /* 29 << 210 */ + { { 0xf58fecb16f640f62L,0xe274b92b39f51946L,0x7f4dfc046288af44L, + 0x0a91f32aeac329e5L }, + { 0x43ad274bd6aaba31L,0x719a16400f6884f9L,0x685d29f6daf91e20L, + 0x5ec1cc3327e49d52L } }, + /* 30 << 210 */ + { { 0x38f4de963b54a059L,0x0e0015e5efbcfdb3L,0x177d23d94dbb8da6L, + 0x98724aa297a617adL }, + { 0x30f0885bfdb6558eL,0xf9f7a28ac7899a96L,0xd2ae8ac8872dc112L, + 0xfa0642ca73c3c459L } }, + /* 31 << 210 */ + { { 0x15296981e7dfc8d6L,0x67cd44501fb5b94aL,0x0ec71cf10eddfd37L, + 0xc7e5eeb39a8eddc7L }, + { 0x02ac8e3d81d95028L,0x0088f17270b0e35dL,0xec041fabe1881fe3L, + 0x62cf71b8d99e7faaL } }, + /* 32 << 210 */ + { { 0x5043dea7e0f222c2L,0x309d42ac72e65142L,0x94fe9ddd9216cd30L, + 0xd6539c7d0f87feecL }, + { 0x03c5a57c432ac7d7L,0x72692cf0327fda10L,0xec28c85f280698deL, + 0x2331fb467ec283b1L } }, + /* 33 << 210 */ + { { 0xd34bfa322867e633L,0x78709a820a9cc815L,0xb7fe6964875e2fa5L, + 0x25cc064f9e98bfb5L }, + { 0x9eb0151c493a65c5L,0x5fb5d94153182464L,0x69e6f130f04618e2L, + 0xa8ecec22f89c8ab6L } }, + /* 34 << 210 */ + { { 0xcd6ac88bb96209bdL,0x65fa8cdbb3e1c9e0L,0xa47d22f54a8d8eacL, + 0x83895cdf8d33f963L }, + { 0xa8adca59b56cd3d1L,0x10c8350bdaf38232L,0x2b161fb3a5080a9fL, + 0xbe7f5c643af65b3aL } }, + /* 35 << 210 */ + { { 0x2c75403997403a11L,0x94626cf7121b96afL,0x431de7c46a983ec2L, + 0x3780dd3a52cc3df7L }, + { 0xe28a0e462baf8e3bL,0xabe68aad51d299aeL,0x603eb8f9647a2408L, + 0x14c61ed65c750981L } }, + /* 36 << 210 */ + { { 0x88b34414c53352e7L,0x5a34889c1337d46eL,0x612c1560f95f2bc8L, + 0x8a3f8441d4807a3aL }, + { 0x680d9e975224da68L,0x60cd6e88c3eb00e9L,0x3875a98e9a6bc375L, + 0xdc80f9244fd554c2L } }, + /* 37 << 210 */ + { { 0x6c4b34156ac77407L,0xa1e5ea8f25420681L,0x541bfa144607a458L, + 0x5dbc7e7a96d7fbf9L }, + { 0x646a851b31590a47L,0x039e85ba15ee6df8L,0xd19fa231d7b43fc0L, + 0x84bc8be8299a0e04L } }, + /* 38 << 210 */ + { { 0x2b9d2936f20df03aL,0x240543828608d472L,0x76b6ba049149202aL, + 0xb21c38313670e7b7L }, + { 0xddd93059d6fdee10L,0x9da47ad378488e71L,0x99cc1dfda0fcfb25L, + 0x42abde1064696954L } }, + /* 39 << 210 */ + { { 0x14cc15fc17eab9feL,0xd6e863e4d3e70972L,0x29a7765c6432112cL, + 0x886600015b0774d8L }, + { 0x3729175a2c088eaeL,0x13afbcae8230b8d4L,0x44768151915f4379L, + 0xf086431ad8d22812L } }, + /* 40 << 210 */ + { { 0x37461955c298b974L,0x905fb5f0f8711e04L,0x787abf3afe969d18L, + 0x392167c26f6a494eL }, + { 0xfc7a0d2d28c511daL,0xf127c7dcb66a262dL,0xf9c4bb95fd63fdf0L, + 0x900165893913ef46L } }, + /* 41 << 210 */ + { { 0x74d2a73c11aa600dL,0x2f5379bd9fb5ab52L,0xe49e53a47fb70068L, + 0x68dd39e5404aa9a7L }, + { 0xb9b0cf572ecaa9c3L,0xba0e103be824826bL,0x60c2198b4631a3c4L, + 0xc5ff84abfa8966a2L } }, + /* 42 << 210 */ + { { 0x2d6ebe22ac95aff8L,0x1c9bb6dbb5a46d09L,0x419062da53ee4f8dL, + 0x7b9042d0bb97efefL }, + { 0x0f87f080830cf6bdL,0x4861d19a6ec8a6c6L,0xd3a0daa1202f01aaL, + 0xb0111674f25afbd5L } }, + /* 43 << 210 */ + { { 0x6d00d6cf1afb20d9L,0x1369500040671bc5L,0x913ab0dc2485ea9bL, + 0x1f2bed069eef61acL }, + { 0x850c82176d799e20L,0x93415f373271c2deL,0x5afb06e96c4f5910L, + 0x688a52dfc4e9e421L } }, + /* 44 << 210 */ + { { 0x30495ba3e2a9a6dbL,0x4601303d58f9268bL,0xbe3b0dad7eb0f04fL, + 0x4ea472504456936dL }, + { 0x8caf8798d33fd3e7L,0x1ccd8a89eb433708L,0x9effe3e887fd50adL, + 0xbe240a566b29c4dfL } }, + /* 45 << 210 */ + { { 0xec4ffd98ca0e7ebdL,0xf586783ae748616eL,0xa5b00d8fc77baa99L, + 0x0acada29b4f34c9cL }, + { 0x36dad67d0fe723acL,0x1d8e53a539c36c1eL,0xe4dd342d1f4bea41L, + 0x64fd5e35ebc9e4e0L } }, + /* 46 << 210 */ + { { 0x96f01f9057908805L,0xb5b9ea3d5ed480ddL,0x366c5dc23efd2dd0L, + 0xed2fe3056e9dfa27L }, + { 0x4575e8926e9197e2L,0x11719c09ab502a5dL,0x264c7bece81f213fL, + 0x741b924155f5c457L } }, + /* 47 << 210 */ + { { 0x78ac7b6849a5f4f4L,0xf91d70a29fc45b7dL,0x39b05544b0f5f355L, + 0x11f06bceeef930d9L }, + { 0xdb84d25d038d05e1L,0x04838ee5bacc1d51L,0x9da3ce869e8ee00bL, + 0xc3412057c36eda1fL } }, + /* 48 << 210 */ + { { 0xae80b91364d9c2f4L,0x7468bac3a010a8ffL,0xdfd2003737359d41L, + 0x1a0f5ab815efeaccL }, + { 0x7c25ad2f659d0ce0L,0x4011bcbb6785cff1L,0x128b99127e2192c7L, + 0xa549d8e113ccb0e8L } }, + /* 49 << 210 */ + { { 0x805588d8c85438b1L,0x5680332dbc25cb27L,0xdcd1bc961a4bfdf4L, + 0x779ff428706f6566L }, + { 0x8bbee998f059987aL,0xf6ce8cf2cc686de7L,0xf8ad3c4a953cfdb2L, + 0xd1d426d92205da36L } }, + /* 50 << 210 */ + { { 0xb3c0f13fc781a241L,0x3e89360ed75362a8L,0xccd05863c8a91184L, + 0x9bd0c9b7efa8a7f4L }, + { 0x97ee4d538a912a4bL,0xde5e15f8bcf518fdL,0x6a055bf8c467e1e0L, + 0x10be4b4b1587e256L } }, + /* 51 << 210 */ + { { 0xd90c14f2668621c9L,0xd5518f51ab9c92c1L,0x8e6a0100d6d47b3cL, + 0xcbe980dd66716175L }, + { 0x500d3f10ddd83683L,0x3b6cb35d99cac73cL,0x53730c8b6083d550L, + 0xcf159767df0a1987L } }, + /* 52 << 210 */ + { { 0x84bfcf5343ad73b3L,0x1b528c204f035a94L,0x4294edf733eeac69L, + 0xb6283e83817f3240L }, + { 0xc3fdc9590a5f25b1L,0xefaf8aa55844ee22L,0xde269ba5dbdde4deL, + 0xe3347160c56133bfL } }, + /* 53 << 210 */ + { { 0xc11842198d9ea9f8L,0x090de5dbf3fc1ab5L,0x404c37b10bf22cdaL, + 0x7de20ec8f5618894L }, + { 0x754c588eecdaecabL,0x6ca4b0ed88342743L,0x76f08bddf4a938ecL, + 0xd182de8991493ccbL } }, + /* 54 << 210 */ + { { 0xd652c53ec8a4186aL,0xb3e878db946d8e33L,0x088453c05f37663cL, + 0x5cd9daaab407748bL }, + { 0xa1f5197f586d5e72L,0x47500be8c443ca59L,0x78ef35b2e2652424L, + 0x09c5d26f6dd7767dL } }, + /* 55 << 210 */ + { { 0x7175a79aa74d3f7bL,0x0428fd8dcf5ea459L,0x511cb97ca5d1746dL, + 0x36363939e71d1278L }, + { 0xcf2df95510350bf4L,0xb381743960aae782L,0xa748c0e43e688809L, + 0x98021fbfd7a5a006L } }, + /* 56 << 210 */ + { { 0x9076a70c0e367a98L,0xbea1bc150f62b7c2L,0x2645a68c30fe0343L, + 0xacaffa78699dc14fL }, + { 0xf4469964457bf9c4L,0x0db6407b0d2ead83L,0x68d56cadb2c6f3ebL, + 0x3b512e73f376356cL } }, + /* 57 << 210 */ + { { 0xe43b0e1ffce10408L,0x89ddc0035a5e257dL,0xb0ae0d120362e5b3L, + 0x07f983c7b0519161L }, + { 0xc2e94d155d5231e7L,0xcff22aed0b4f9513L,0xb02588dd6ad0b0b5L, + 0xb967d1ac11d0dcd5L } }, + /* 58 << 210 */ + { { 0x8dac6bc6cf777b6cL,0x0062bdbd4c6d1959L,0x53da71b50ef5cc85L, + 0x07012c7d4006f14fL }, + { 0x4617f962ac47800dL,0x53365f2bc102ed75L,0xb422efcb4ab8c9d3L, + 0x195cb26b34af31c9L } }, + /* 59 << 210 */ + { { 0x3a926e2905f2c4ceL,0xbd2bdecb9856966cL,0x5d16ab3a85527015L, + 0x9f81609e4486c231L }, + { 0xd8b96b2cda350002L,0xbd054690fa1b7d36L,0xdc90ebf5e71d79bcL, + 0xf241b6f908964e4eL } }, + /* 60 << 210 */ + { { 0x7c8386432fe3cd4cL,0xe0f33acbb4bc633cL,0xb4a9ecec3d139f1fL, + 0x05ce69cddc4a1f49L }, + { 0xa19d1b16f5f98aafL,0x45bb71d66f23e0efL,0x33789fcd46cdfdd3L, + 0x9b8e2978cee040caL } }, + /* 61 << 210 */ + { { 0x9c69b246ae0a6828L,0xba533d247078d5aaL,0x7a2e42c07bb4fbdbL, + 0xcfb4879a7035385cL }, + { 0x8c3dd30b3281705bL,0x7e361c6c404fe081L,0x7b21649c3f604edfL, + 0x5dbf6a3fe52ffe47L } }, + /* 62 << 210 */ + { { 0xc41b7c234b54d9bfL,0x1374e6813511c3d9L,0x1863bf16c1b2b758L, + 0x90e785071e9e6a96L }, + { 0xab4bf98d5d86f174L,0xd74e0bd385e96fe4L,0x8afde39fcac5d344L, + 0x90946dbcbd91b847L } }, + /* 63 << 210 */ + { { 0xf5b42358fe1a838cL,0x05aae6c5620ac9d8L,0x8e193bd8a1ce5a0bL, + 0x8f7105714dabfd72L }, + { 0x8d8fdd48182caaacL,0x8c4aeefa040745cfL,0x73c6c30af3b93e6dL, + 0x991241f316f42011L } }, + /* 64 << 210 */ + { { 0xa0158eeae457a477L,0xd19857dbee6ddc05L,0xb326522418c41671L, + 0x3ffdfc7e3c2c0d58L }, + { 0x3a3a525426ee7cdaL,0x341b0869df02c3a8L,0xa023bf42723bbfc8L, + 0x3d15002a14452691L } }, + /* 0 << 217 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 217 */ + { { 0x5ef7324c85edfa30L,0x2597655487d4f3daL,0x352f5bc0dcb50c86L, + 0x8f6927b04832a96cL }, + { 0xd08ee1ba55f2f94cL,0x6a996f99344b45faL,0xe133cb8da8aa455dL, + 0x5d0721ec758dc1f7L } }, + /* 2 << 217 */ + { { 0x6ba7a92079e5fb67L,0xe1331feb70aa725eL,0x5080ccf57df5d837L, + 0xe4cae01d7ff72e21L }, + { 0xd9243ee60412a77dL,0x06ff7cacdf449025L,0xbe75f7cd23ef5a31L, + 0xbc9578220ddef7a8L } }, + /* 3 << 217 */ + { { 0x8cf7230cb0ce1c55L,0x5b534d050bbfb607L,0xee1ef1130e16363bL, + 0x27e0aa7ab4999e82L }, + { 0xce1dac2d79362c41L,0x67920c9091bb6cb0L,0x1e648d632223df24L, + 0x0f7d9eefe32e8f28L } }, + /* 4 << 217 */ + { { 0x6943f39afa833834L,0x22951722a6328562L,0x81d63dd54170fc10L, + 0x9f5fa58faecc2e6dL }, + { 0xb66c8725e77d9a3bL,0x11235cea6384ebe0L,0x06a8c1185845e24aL, + 0x0137b286ebd093b1L } }, + /* 5 << 217 */ + { { 0xc589e1ce44ace150L,0xe0f8d3d94381e97cL,0x59e99b1162c5a4b8L, + 0x90d262f7fd0ec9f9L }, + { 0xfbc854c9283e13c9L,0x2d04fde7aedc7085L,0x057d776547dcbecbL, + 0x8dbdf5919a76fa5fL } }, + /* 6 << 217 */ + { { 0xd01506950de1e578L,0x2e1463e7e9f72bc6L,0xffa684411b39eca5L, + 0x673c85307c037f2fL }, + { 0xd0d6a600747f91daL,0xb08d43e1c9cb78e9L,0x0fc0c64427b5cef5L, + 0x5c1d160aa60a2fd6L } }, + /* 7 << 217 */ + { { 0xf98cae5328c8e13bL,0x375f10c4b2eddcd1L,0xd4eb8b7f5cce06adL, + 0xb4669f4580a2e1efL }, + { 0xd593f9d05bbd8699L,0x5528a4c9e7976d13L,0x3923e0951c7e28d3L, + 0xb92937903f6bb577L } }, + /* 8 << 217 */ + { { 0xdb567d6ac42bd6d2L,0x6df86468bb1f96aeL,0x0efe5b1a4843b28eL, + 0x961bbb056379b240L }, + { 0xb6caf5f070a6a26bL,0x70686c0d328e6e39L,0x80da06cf895fc8d3L, + 0x804d8810b363fdc9L } }, + /* 9 << 217 */ + { { 0xbe22877b207f1670L,0x9b0dd1884e615291L,0x625ae8dc97a3c2bfL, + 0x08584ef7439b86e8L }, + { 0xde7190a5dcd898ffL,0x26286c402058ee3dL,0x3db0b2175f87b1c1L, + 0xcc334771102a6db5L } }, + /* 10 << 217 */ + { { 0xd99de9542f770fb1L,0x97c1c6204cd7535eL,0xd3b6c4483f09cefcL, + 0xd725af155a63b4f8L }, + { 0x0c95d24fc01e20ecL,0xdfd374949ae7121fL,0x7d6ddb72ec77b7ecL, + 0xfe079d3b0353a4aeL } }, + /* 11 << 217 */ + { { 0x3066e70a2e6ac8d2L,0x9c6b5a43106e5c05L,0x52d3c6f5ede59b8cL, + 0x30d6a5c3fccec9aeL }, + { 0xedec7c224fc0a9efL,0x190ff08395c16cedL,0xbe12ec8f94de0fdeL, + 0x0d131ab8852d3433L } }, + /* 12 << 217 */ + { { 0x42ace07e85701291L,0x94793ed9194061a8L,0x30e83ed6d7f4a485L, + 0x9eec7269f9eeff4dL }, + { 0x90acba590c9d8005L,0x5feca4581e79b9d1L,0x8fbe54271d506a1eL, + 0xa32b2c8e2439cfa7L } }, + /* 13 << 217 */ + { { 0x1671c17373dd0b4eL,0x37a2821444a054c6L,0x81760a1b4e8b53f1L, + 0xa6c04224f9f93b9eL }, + { 0x18784b34cf671e3cL,0x81bbecd2cda9b994L,0x38831979b2ab3848L, + 0xef54feb7f2e03c2dL } }, + /* 14 << 217 */ + { { 0xcf197ca7fb8088faL,0x014272474ddc96c5L,0xa2d2550a30777176L, + 0x534698984d0cf71dL }, + { 0x6ce937b83a2aaac6L,0xe9f91dc35af38d9bL,0x2598ad83c8bf2899L, + 0x8e706ac9b5536c16L } }, + /* 15 << 217 */ + { { 0x40dc7495f688dc98L,0x26490cd7124c4afcL,0xe651ec841f18775cL, + 0x393ea6c3b4fdaf4aL }, + { 0x1e1f33437f338e0dL,0x39fb832b6053e7b5L,0x46e702da619e14d5L, + 0x859cacd1cdeef6e0L } }, + /* 16 << 217 */ + { { 0x63b99ce74462007dL,0xb8ab48a54cb5f5b7L,0x9ec673d2f55edde7L, + 0xd1567f748cfaefdaL }, + { 0x46381b6b0887bcecL,0x694497cee178f3c2L,0x5e6525e31e6266cbL, + 0x5931de26697d6413L } }, + /* 17 << 217 */ + { { 0x87f8df7c0e58d493L,0xb1ae5ed058b73f12L,0xc368f784dea0c34dL, + 0x9bd0a120859a91a0L }, + { 0xb00d88b7cc863c68L,0x3a1cc11e3d1f4d65L,0xea38e0e70aa85593L, + 0x37f13e987dc4aee8L } }, + /* 18 << 217 */ + { { 0x10d38667bc947badL,0x738e07ce2a36ee2eL,0xc93470cdc577fcacL, + 0xdee1b6162782470dL }, + { 0x36a25e672e793d12L,0xd6aa6caee0f186daL,0x474d0fd980e07af7L, + 0xf7cdc47dba8a5cd4L } }, + /* 19 << 217 */ + { { 0x28af6d9dab15247fL,0x7c789c10493a537fL,0x7ac9b11023a334e7L, + 0x0236ac0912c9c277L }, + { 0xa7e5bd251d7a5144L,0x098b9c2af13ec4ecL,0x3639dacad3f0abcaL, + 0x642da81aa23960f9L } }, + /* 20 << 217 */ + { { 0x7d2e5c054f7269b1L,0xfcf30777e287c385L,0x10edc84ff2a46f21L, + 0x354417574f43fa36L }, + { 0xf1327899fd703431L,0xa438d7a616dd587aL,0x65c34c57e9c8352dL, + 0xa728edab5cc5a24eL } }, + /* 21 << 217 */ + { { 0xaed78abc42531689L,0x0a51a0e8010963efL,0x5776fa0ad717d9b3L, + 0xf356c2397dd3428bL }, + { 0x29903fff8d3a3dacL,0x409597fa3d94491fL,0x4cd7a5ffbf4a56a4L, + 0xe50964748adab462L } }, + /* 22 << 217 */ + { { 0xa97b51265c3427b0L,0x6401405cd282c9bdL,0x3629f8d7222c5c45L, + 0xb1c02c16e8d50aedL }, + { 0xbea2ed75d9635bc9L,0x226790c76e24552fL,0x3c33f2a365f1d066L, + 0x2a43463e6dfccc2eL } }, + /* 23 << 217 */ + { { 0x8cc3453adb483761L,0xe7cc608565d5672bL,0x277ed6cbde3efc87L, + 0x19f2f36869234eafL }, + { 0x9aaf43175c0b800bL,0x1f1e7c898b6da6e2L,0x6cfb4715b94ec75eL, + 0xd590dd5f453118c2L } }, + /* 24 << 217 */ + { { 0x14e49da11f17a34cL,0x5420ab39235a1456L,0xb76372412f50363bL, + 0x7b15d623c3fabb6eL }, + { 0xa0ef40b1e274e49cL,0x5cf5074496b1860aL,0xd6583fbf66afe5a4L, + 0x44240510f47e3e9aL } }, + /* 25 << 217 */ + { { 0x9925434311b2d595L,0xf1367499eec8df57L,0x3cb12c613e73dd05L, + 0xd248c0337dac102aL }, + { 0xcf154f13a77739f5L,0xbf4288cb23d2af42L,0xaa64c9b632e4a1cfL, + 0xee8c07a8c8a208f3L } }, + /* 26 << 217 */ + { { 0xe10d49996fe8393fL,0x0f809a3fe91f3a32L,0x61096d1c802f63c8L, + 0x289e146257750d3dL }, + { 0xed06167e9889feeaL,0xd5c9c0e2e0993909L,0x46fca0d856508ac6L, + 0x918260474f1b8e83L } }, + /* 27 << 217 */ + { { 0x4f2c877a9a4a2751L,0x71bd0072cae6feadL,0x38df8dcc06aa1941L, + 0x5a074b4c63beeaa8L }, + { 0xd6d65934c1cec8edL,0xa6ecb49eaabc03bdL,0xaade91c2de8a8415L, + 0xcfb0efdf691136e0L } }, + /* 28 << 217 */ + { { 0x11af45ee23ab3495L,0xa132df880b77463dL,0x8923c15c815d06f4L, + 0xc3ceb3f50d61a436L }, + { 0xaf52291de88fb1daL,0xea0579741da12179L,0xb0d7218cd2fef720L, + 0x6c0899c98e1d8845L } }, + /* 29 << 217 */ + { { 0x98157504752ddad7L,0xd60bd74fa1a68a97L,0x7047a3a9f658fb99L, + 0x1f5d86d65f8511e4L }, + { 0xb8a4bc424b5a6d88L,0x69eb2c331abefa7dL,0x95bf39e813c9c510L, + 0xf571960ad48aab43L } }, + /* 30 << 217 */ + { { 0x7e8cfbcf704e23c6L,0xc71b7d2228aaa65bL,0xa041b2bd245e3c83L, + 0x69b98834d21854ffL }, + { 0x89d227a3963bfeecL,0x99947aaade7da7cbL,0x1d9ee9dbee68a9b1L, + 0x0a08f003698ec368L } }, + /* 31 << 217 */ + { { 0xe9ea409478ef2487L,0xc8d2d41502cfec26L,0xc52f9a6eb7dcf328L, + 0x0ed489e385b6a937L }, + { 0x9b94986bbef3366eL,0x0de59c70edddddb8L,0xffdb748ceadddbe2L, + 0x9b9784bb8266ea40L } }, + /* 32 << 217 */ + { { 0x142b55021a93507aL,0xb4cd11878d3c06cfL,0xdf70e76a91ec3f40L, + 0x484e81ad4e7553c2L }, + { 0x830f87b5272e9d6eL,0xea1c93e5c6ff514aL,0x67cc2adcc4192a8eL, + 0xc77e27e242f4535aL } }, + /* 33 << 217 */ + { { 0x9cdbab36d2b713c5L,0x86274ea0cf7b0cd3L,0x784680f309af826bL, + 0xbfcc837a0c72dea3L }, + { 0xa8bdfe9dd6529b73L,0x708aa22863a88002L,0x6c7a9a54c91d45b9L, + 0xdf1a38bbfd004f56L } }, + /* 34 << 217 */ + { { 0x2e8c9a26b8bad853L,0x2d52cea33723eae7L,0x054d6d8156ca2830L, + 0xa3317d149a8dc411L }, + { 0xa08662fefd4ddedaL,0xed2a153ab55d792bL,0x7035c16abfc6e944L, + 0xb6bc583400171cf3L } }, + /* 35 << 217 */ + { { 0xe27152b383d102b6L,0xfe695a470646b848L,0xa5bb09d8916e6d37L, + 0xb4269d640d17015eL }, + { 0x8d8156a10a1d2285L,0xfeef6c5146d26d72L,0x9dac57c84c5434a7L, + 0x0282e5be59d39e31L } }, + /* 36 << 217 */ + { { 0xedfff181721c486dL,0x301baf10bc58824eL,0x8136a6aa00570031L, + 0x55aaf78c1cddde68L }, + { 0x2682937159c63952L,0x3a3bd2748bc25bafL,0xecdf8657b7e52dc3L, + 0x2dd8c087fd78e6c8L } }, + /* 37 << 217 */ + { { 0x20553274f5531461L,0x8b4a12815d95499bL,0xe2c8763a1a80f9d2L, + 0xd1dbe32b4ddec758L }, + { 0xaf12210d30c34169L,0xba74a95378baa533L,0x3d133c6ea438f254L, + 0xa431531a201bef5bL } }, + /* 38 << 217 */ + { { 0x15295e22f669d7ecL,0xca374f64357fb515L,0x8a8406ffeaa3fdb3L, + 0x106ae448df3f2da8L }, + { 0x8f9b0a9033c8e9a1L,0x234645e271ad5885L,0x3d0832241c0aed14L, + 0xf10a7d3e7a942d46L } }, + /* 39 << 217 */ + { { 0x7c11deee40d5c9beL,0xb2bae7ffba84ed98L,0x93e97139aad58dddL, + 0x3d8727963f6d1fa3L }, + { 0x483aca818569ff13L,0x8b89a5fb9a600f72L,0x4cbc27c3c06f2b86L, + 0x2213071363ad9c0bL } }, + /* 40 << 217 */ + { { 0xb5358b1e48ac2840L,0x18311294ecba9477L,0xda58f990a6946b43L, + 0x3098baf99ab41819L }, + { 0x66c4c1584198da52L,0xab4fc17c146bfd1bL,0x2f0a4c3cbf36a908L, + 0x2ae9e34b58cf7838L } }, + /* 41 << 217 */ + { { 0xf411529e3fa11b1fL,0x21e43677974af2b4L,0x7c20958ec230793bL, + 0x710ea88516e840f3L }, + { 0xfc0b21fcc5dc67cfL,0x08d5164788405718L,0xd955c21fcfe49eb7L, + 0x9722a5d556dd4a1fL } }, + /* 42 << 217 */ + { { 0xc9ef50e2c861baa5L,0xc0c21a5d9505ac3eL,0xaf6b9a338b7c063fL, + 0xc63703392f4779c1L }, + { 0x22df99c7638167c3L,0xfe6ffe76795db30cL,0x2b822d33a4854989L, + 0xfef031dd30563aa5L } }, + /* 43 << 217 */ + { { 0x16b09f82d57c667fL,0xc70312cecc0b76f1L,0xbf04a9e6c9118aecL, + 0x82fcb4193409d133L }, + { 0x1a8ab385ab45d44dL,0xfba07222617b83a3L,0xb05f50dd58e81b52L, + 0x1d8db55321ce5affL } }, + /* 44 << 217 */ + { { 0x3097b8d4e344a873L,0x7d8d116dfe36d53eL,0x6db22f587875e750L, + 0x2dc5e37343e144eaL }, + { 0xc05f32e6e799eb95L,0xe9e5f4df6899e6ecL,0xbdc3bd681fab23d5L, + 0xb72b8ab773af60e6L } }, + /* 45 << 217 */ + { { 0x8db27ae02cecc84aL,0x600016d87bdb871cL,0x42a44b13d7c46f58L, + 0xb8919727c3a77d39L }, + { 0xcfc6bbbddafd6088L,0x1a7401466bd20d39L,0x8c747abd98c41072L, + 0x4c91e765bdf68ea1L } }, + /* 46 << 217 */ + { { 0x7c95e5ca08819a78L,0xcf48b729c9587921L,0x091c7c5fdebbcc7dL, + 0x6f287404f0e05149L }, + { 0xf83b5ac226cd44ecL,0x88ae32a6cfea250eL,0x6ac5047a1d06ebc5L, + 0xc7e550b4d434f781L } }, + /* 47 << 217 */ + { { 0x61ab1cf25c727bd2L,0x2e4badb11cf915b0L,0x1b4dadecf69d3920L, + 0xe61b1ca6f14c1dfeL }, + { 0x90b479ccbd6bd51fL,0x8024e4018045ec30L,0xcab29ca325ef0e62L, + 0x4f2e941649e4ebc0L } }, + /* 48 << 217 */ + { { 0x45eb40ec0ccced58L,0x25cd4b9c0da44f98L,0x43e06458871812c6L, + 0x99f80d5516cef651L }, + { 0x571340c9ce6dc153L,0x138d5117d8665521L,0xacdb45bc4e07014dL, + 0x2f34bb3884b60b91L } }, + /* 49 << 217 */ + { { 0xf44a4fd22ae8921eL,0xb039288e892ba1e2L,0x9da50174b1c180b2L, + 0x6b70ab661693dc87L }, + { 0x7e9babc9e7057481L,0x4581ddef9c80dc41L,0x0c890da951294682L, + 0x0b5629d33f4736e5L } }, + /* 50 << 217 */ + { { 0x2340c79eb06f5b41L,0xa42e84ce4e243469L,0xf9a20135045a71a9L, + 0xefbfb415d27b6fb6L }, + { 0x25ebea239d33cd6fL,0x9caedb88aa6c0af8L,0x53dc7e9ad9ce6f96L, + 0x3897f9fd51e0b15aL } }, + /* 51 << 217 */ + { { 0xf51cb1f88e5d788eL,0x1aec7ba8e1d490eeL,0x265991e0cc58cb3cL, + 0x9f306e8c9fc3ad31L }, + { 0x5fed006e5040a0acL,0xca9d5043fb476f2eL,0xa19c06e8beea7a23L, + 0xd28658010edabb63L } }, + /* 52 << 217 */ + { { 0xdb92293f6967469aL,0x2894d8398d8a8ed8L,0x87c9e406bbc77122L, + 0x8671c6f12ea3a26aL }, + { 0xe42df8d6d7de9853L,0x2e3ce346b1f2bcc7L,0xda601dfc899d50cfL, + 0xbfc913defb1b598fL } }, + /* 53 << 217 */ + { { 0x81c4909fe61f7908L,0x192e304f9bbc7b29L,0xc3ed8738c104b338L, + 0xedbe9e47783f5d61L }, + { 0x0c06e9be2db30660L,0xda3e613fc0eb7d8eL,0xd8fa3e97322e096eL, + 0xfebd91e8d336e247L } }, + /* 54 << 217 */ + { { 0x8f13ccc4df655a49L,0xa9e00dfc5eb20210L,0x84631d0fc656b6eaL, + 0x93a058cdd8c0d947L }, + { 0x6846904a67bd3448L,0x4a3d4e1af394fd5cL,0xc102c1a5db225f52L, + 0xe3455bbafc4f5e9aL } }, + /* 55 << 217 */ + { { 0x6b36985b4b9ad1ceL,0xa98185365bb7f793L,0x6c25e1d048b1a416L, + 0x1381dd533c81bee7L }, + { 0xd2a30d617a4a7620L,0xc841292639b8944cL,0x3c1c6fbe7a97c33aL, + 0x941e541d938664e7L } }, + /* 56 << 217 */ + { { 0x417499e84a34f239L,0x15fdb83cb90402d5L,0xb75f46bf433aa832L, + 0xb61e15af63215db1L }, + { 0xaabe59d4a127f89aL,0x5d541e0c07e816daL,0xaaba0659a618b692L, + 0x5532773317266026L } }, + /* 57 << 217 */ + { { 0xaf53a0fc95f57552L,0x329476506cacb0c9L,0x253ff58dc821be01L, + 0xb0309531a06f1146L }, + { 0x59bbbdf505c2e54dL,0x158f27ad26e8dd22L,0xcc5b7ffb397e1e53L, + 0xae03f65b7fc1e50dL } }, + /* 58 << 217 */ + { { 0xa9784ebd9c95f0f9L,0x5ed9deb224640771L,0x31244af7035561c4L, + 0x87332f3a7ee857deL }, + { 0x09e16e9e2b9e0d88L,0x52d910f456a06049L,0x507ed477a9592f48L, + 0x85cb917b2365d678L } }, + /* 59 << 217 */ + { { 0xf8511c934c8998d1L,0x2186a3f1730ea58fL,0x50189626b2029db0L, + 0x9137a6d902ceb75aL }, + { 0x2fe17f37748bc82cL,0x87c2e93180469f8cL,0x850f71cdbf891aa2L, + 0x0ca1b89b75ec3d8dL } }, + /* 60 << 217 */ + { { 0x516c43aa5e1cd3cdL,0x893978089a887c28L,0x0059c699ddea1f9fL, + 0x7737d6fa8e6868f7L }, + { 0x6d93746a60f1524bL,0x36985e55ba052aa7L,0x41b1d322ed923ea5L, + 0x3429759f25852a11L } }, + /* 61 << 217 */ + { { 0xbeca6ec3092e9f41L,0x3a238c6662256bbdL,0xd82958ea70ad487dL, + 0x4ac8aaf965610d93L }, + { 0x3fa101b15e4ccab0L,0x9bf430f29de14bfbL,0xa10f5cc66531899dL, + 0x590005fbea8ce17dL } }, + /* 62 << 217 */ + { { 0xc437912f24544cb6L,0x9987b71ad79ac2e3L,0x13e3d9ddc058a212L, + 0x00075aacd2de9606L }, + { 0x80ab508b6cac8369L,0x87842be7f54f6c89L,0xa7ad663d6bc532a4L, + 0x67813de778a91bc8L } }, + /* 63 << 217 */ + { { 0x5dcb61cec3427239L,0x5f3c7cf0c56934d9L,0xc079e0fbe3191591L, + 0xe40896bdb01aada7L }, + { 0x8d4667910492d25fL,0x8aeb30c9e7408276L,0xe94374959287aaccL, + 0x23d4708d79fe03d4L } }, + /* 64 << 217 */ + { { 0x8cda9cf2d0c05199L,0x502fbc22fae78454L,0xc0bda9dff572a182L, + 0x5f9b71b86158b372L }, + { 0xe0f33a592b82dd07L,0x763027359523032eL,0x7fe1a721c4505a32L, + 0x7b6e3e82f796409fL } }, + /* 0 << 224 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 224 */ + { { 0xe3417bc035d0b34aL,0x440b386b8327c0a7L,0x8fb7262dac0362d1L, + 0x2c41114ce0cdf943L }, + { 0x2ba5cef1ad95a0b1L,0xc09b37a867d54362L,0x26d6cdd201e486c9L, + 0x20477abf42ff9297L } }, + /* 2 << 224 */ + { { 0xa004dcb3292a9287L,0xddc15cf677b092c7L,0x083a8464806c0605L, + 0x4a68df703db997b0L }, + { 0x9c134e4505bf7dd0L,0xa4e63d398ccf7f8cL,0xa6e6517f41b5f8afL, + 0xaa8b9342ad7bc1ccL } }, + /* 3 << 224 */ + { { 0x126f35b51e706ad9L,0xb99cebb4c3a9ebdfL,0xa75389afbf608d90L, + 0x76113c4fc6c89858L }, + { 0x80de8eb097e2b5aaL,0x7e1022cc63b91304L,0x3bdab6056ccc066cL, + 0x33cbb144b2edf900L } }, + /* 4 << 224 */ + { { 0xc41764717af715d2L,0xe2f7f594d0134a96L,0x2c1873efa41ec956L, + 0xe4e7b4f677821304L }, + { 0xe5c8ff9788d5374aL,0x2b915e6380823d5bL,0xea6bc755b2ee8fe2L, + 0x6657624ce7112651L } }, + /* 5 << 224 */ + { { 0x157af101dace5acaL,0xc4fdbcf211a6a267L,0xdaddf340c49c8609L, + 0x97e49f52e9604a65L }, + { 0x9be8e790937e2ad5L,0x846e2508326e17f1L,0x3f38007a0bbbc0dcL, + 0xcf03603fb11e16d6L } }, + /* 6 << 224 */ + { { 0xd6f800e07442f1d5L,0x475607d166e0e3abL,0x82807f16b7c64047L, + 0x8858e1e3a749883dL }, + { 0x5859120b8231ee10L,0x1b80e7eb638a1eceL,0xcb72525ac6aa73a4L, + 0xa7cdea3d844423acL } }, + /* 7 << 224 */ + { { 0x5ed0c007f8ae7c38L,0x6db07a5c3d740192L,0xbe5e9c2a5fe36db3L, + 0xd5b9d57a76e95046L }, + { 0x54ac32e78eba20f2L,0xef11ca8f71b9a352L,0x305e373eff98a658L, + 0xffe5a100823eb667L } }, + /* 8 << 224 */ + { { 0x57477b11e51732d2L,0xdfd6eb282538fc0eL,0x5c43b0cc3b39eec5L, + 0x6af12778cb36cc57L }, + { 0x70b0852d06c425aeL,0x6df92f8c5c221b9bL,0x6c8d4f9ece826d9cL, + 0xf59aba7bb49359c3L } }, + /* 9 << 224 */ + { { 0x5c8ed8d5da64309dL,0x61a6de5691b30704L,0xd6b52f6a2f9b5808L, + 0x0eee419498c958a7L }, + { 0xcddd9aab771e4caaL,0x83965dfd78bc21beL,0x02affce3b3b504f5L, + 0x30847a21561c8291L } }, + /* 10 << 224 */ + { { 0xd2eb2cf152bfda05L,0xe0e4c4e96197b98cL,0x1d35076cf8a1726fL, + 0x6c06085b2db11e3dL }, + { 0x15c0c4d74463ba14L,0x9d292f830030238cL,0x1311ee8b3727536dL, + 0xfeea86efbeaedc1eL } }, + /* 11 << 224 */ + { { 0xb9d18cd366131e2eL,0xf31d974f80fe2682L,0xb6e49e0fe4160289L, + 0x7c48ec0b08e92799L }, + { 0x818111d8d1989aa7L,0xb34fa0aaebf926f9L,0xdb5fe2f5a245474aL, + 0xf80a6ebb3c7ca756L } }, + /* 12 << 224 */ + { { 0xa7f96054afa05dd8L,0x26dfcf21fcaf119eL,0xe20ef2e30564bb59L, + 0xef4dca5061cb02b8L }, + { 0xcda7838a65d30672L,0x8b08d534fd657e86L,0x4c5b439546d595c8L, + 0x39b58725425cb836L } }, + /* 13 << 224 */ + { { 0x8ea610593de9abe3L,0x404348819cdc03beL,0x9b261245cfedce8cL, + 0x78c318b4cf5234a1L }, + { 0x510bcf16fde24c99L,0x2a77cb75a2c2ff5dL,0x9c895c2b27960fb4L, + 0xd30ce975b0eda42bL } }, + /* 14 << 224 */ + { { 0xfda853931a62cc26L,0x23c69b9650c0e052L,0xa227df15bfc633f3L, + 0x2ac788481bae7d48L }, + { 0x487878f9187d073dL,0x6c2be919967f807dL,0x765861d8336e6d8fL, + 0x88b8974cce528a43L } }, + /* 15 << 224 */ + { { 0x09521177ff57d051L,0x2ff38037fb6a1961L,0xfc0aba74a3d76ad4L, + 0x7c76480325a7ec17L }, + { 0x7532d75f48879bc8L,0xea7eacc058ce6bc1L,0xc82176b48e896c16L, + 0x9a30e0b22c750fedL } }, + /* 16 << 224 */ + { { 0xc37e2c2e421d3aa4L,0xf926407ce84fa840L,0x18abc03d1454e41cL, + 0x26605ecd3f7af644L }, + { 0x242341a6d6a5eabfL,0x1edb84f4216b668eL,0xd836edb804010102L, + 0x5b337ce7945e1d8cL } }, + /* 17 << 224 */ + { { 0xd2075c77c055dc14L,0x2a0ffa2581d89cdfL,0x8ce815ea6ffdcbafL, + 0xa3428878fb648867L }, + { 0x277699cf884655fbL,0xfa5b5bd6364d3e41L,0x01f680c6441e1cb7L, + 0x3fd61e66b70a7d67L } }, + /* 18 << 224 */ + { { 0x666ba2dccc78cf66L,0xb30181746fdbff77L,0x8d4dd0db168d4668L, + 0x259455d01dab3a2aL }, + { 0xf58564c5cde3acecL,0x7714192513adb276L,0x527d725d8a303f65L, + 0x55deb6c9e6f38f7bL } }, + /* 19 << 224 */ + { { 0xfd5bb657b1fa70fbL,0xfa07f50fd8073a00L,0xf72e3aa7bca02500L, + 0xf68f895d9975740dL }, + { 0x301120605cae2a6aL,0x01bd721802874842L,0x3d4238917ce47bd3L, + 0xa66663c1789544f6L } }, + /* 20 << 224 */ + { { 0x864d05d73272d838L,0xe22924f9fa6295c5L,0x8189593f6c2fda32L, + 0x330d7189b184b544L }, + { 0x79efa62cbde1f714L,0x35771c94e5cb1a63L,0x2f4826b8641c8332L, + 0x00a894fbc8cee854L } }, + /* 21 << 224 */ + { { 0xb4b9a39b36194d40L,0xe857a7c577612601L,0xf4209dd24ecf2f58L, + 0x82b9e66d5a033487L }, + { 0xc1e36934e4e8b9ddL,0xd2372c9da42377d7L,0x51dc94c70e3ae43bL, + 0x4c57761e04474f6fL } }, + /* 22 << 224 */ + { { 0xdcdacd0a1058a318L,0x369cf3f578053a9aL,0xc6c3de5031c68de2L, + 0x4653a5763c4b6d9fL }, + { 0x1688dd5aaa4e5c97L,0x5be80aa1b7ab3c74L,0x70cefe7cbc65c283L, + 0x57f95f1306867091L } }, + /* 23 << 224 */ + { { 0xa39114e24415503bL,0xc08ff7c64cbb17e9L,0x1eff674dd7dec966L, + 0x6d4690af53376f63L }, + { 0xff6fe32eea74237bL,0xc436d17ecd57508eL,0x15aa28e1edcc40feL, + 0x0d769c04581bbb44L } }, + /* 24 << 224 */ + { { 0xc240b6de34eaacdaL,0xd9e116e82ba0f1deL,0xcbe45ec779438e55L, + 0x91787c9d96f752d7L }, + { 0x897f532bf129ac2fL,0xd307b7c85a36e22cL,0x91940675749fb8f3L, + 0xd14f95d0157fdb28L } }, + /* 25 << 224 */ + { { 0xfe51d0296ae55043L,0x8931e98f44a87de1L,0xe57f1cc609e4fee2L, + 0x0d063b674e072d92L }, + { 0x70a998b9ed0e4316L,0xe74a736b306aca46L,0xecf0fbf24fda97c7L, + 0xa40f65cb3e178d93L } }, + /* 26 << 224 */ + { { 0x1625360416df4285L,0xb0c9babbd0c56ae2L,0x73032b19cfc5cfc3L, + 0xe497e5c309752056L }, + { 0x12096bb4164bda96L,0x1ee42419a0b74da1L,0x8fc36243403826baL, + 0x0c8f0069dc09e660L } }, + /* 27 << 224 */ + { { 0x8667e981c27253c9L,0x05a6aefb92b36a45L,0xa62c4b369cb7bb46L, + 0x8394f37511f7027bL }, + { 0x747bc79c5f109d0fL,0xcad88a765b8cc60aL,0x80c5a66b58f09e68L, + 0xe753d451f6127eacL } }, + /* 28 << 224 */ + { { 0xc44b74a15b0ec6f5L,0x47989fe45289b2b8L,0x745f848458d6fc73L, + 0xec362a6ff61c70abL }, + { 0x070c98a7b3a8ad41L,0x73a20fc07b63db51L,0xed2c2173f44c35f4L, + 0x8a56149d9acc9dcaL } }, + /* 29 << 224 */ + { { 0x98f178819ac6e0f4L,0x360fdeafa413b5edL,0x0625b8f4a300b0fdL, + 0xf1f4d76a5b3222d3L }, + { 0x9d6f5109587f76b8L,0x8b4ee08d2317fdb5L,0x88089bb78c68b095L, + 0x95570e9a5808d9b9L } }, + /* 30 << 224 */ + { { 0xa395c36f35d33ae7L,0x200ea12350bb5a94L,0x20c789bd0bafe84bL, + 0x243ef52d0919276aL }, + { 0x3934c577e23ae233L,0xb93807afa460d1ecL,0xb72a53b1f8fa76a4L, + 0xd8914cb0c3ca4491L } }, + /* 31 << 224 */ + { { 0x2e1284943fb42622L,0x3b2700ac500907d5L,0xf370fb091a95ec63L, + 0xf8f30be231b6dfbdL }, + { 0xf2b2f8d269e55f15L,0x1fead851cc1323e9L,0xfa366010d9e5eef6L, + 0x64d487b0e316107eL } }, + /* 32 << 224 */ + { { 0x4c076b86d23ddc82L,0x03fd344c7e0143f0L,0xa95362ff317af2c5L, + 0x0add3db7e18b7a4fL }, + { 0x9c673e3f8260e01bL,0xfbeb49e554a1cc91L,0x91351bf292f2e433L, + 0xc755e7ec851141ebL } }, + /* 33 << 224 */ + { { 0xc9a9513929607745L,0x0ca07420a26f2b28L,0xcb2790e74bc6f9ddL, + 0x345bbb58adcaffc0L }, + { 0xc65ea38cbe0f27a2L,0x67c24d7c641fcb56L,0x2c25f0a7a9e2c757L, + 0x93f5cdb016f16c49L } }, + /* 34 << 224 */ + { { 0x2ca5a9d7c5ee30a1L,0xd1593635b909b729L,0x804ce9f3dadeff48L, + 0xec464751b07c30c3L }, + { 0x89d65ff39e49af6aL,0xf2d6238a6f3d01bcL,0x1095561e0bced843L, + 0x51789e12c8a13fd8L } }, + /* 35 << 224 */ + { { 0xd633f929763231dfL,0x46df9f7de7cbddefL,0x01c889c0cb265da8L, + 0xfce1ad10af4336d2L }, + { 0x8d110df6fc6a0a7eL,0xdd431b986da425dcL,0xcdc4aeab1834aabeL, + 0x84deb1248439b7fcL } }, + /* 36 << 224 */ + { { 0x8796f1693c2a5998L,0x9b9247b47947190dL,0x55b9d9a511597014L, + 0x7e9dd70d7b1566eeL }, + { 0x94ad78f7cbcd5e64L,0x0359ac179bd4c032L,0x3b11baaf7cc222aeL, + 0xa6a6e284ba78e812L } }, + /* 37 << 224 */ + { { 0x8392053f24cea1a0L,0xc97bce4a33621491L,0x7eb1db3435399ee9L, + 0x473f78efece81ad1L }, + { 0x41d72fe0f63d3d0dL,0xe620b880afab62fcL,0x92096bc993158383L, + 0x41a213578f896f6cL } }, + /* 38 << 224 */ + { { 0x1b5ee2fac7dcfcabL,0x650acfde9546e007L,0xc081b749b1b02e07L, + 0xda9e41a0f9eca03dL }, + { 0x013ba727175a54abL,0xca0cd190ea5d8d10L,0x85ea52c095fd96a9L, + 0x2c591b9fbc5c3940L } }, + /* 39 << 224 */ + { { 0x6fb4d4e42bad4d5fL,0xfa4c3590fef0059bL,0x6a10218af5122294L, + 0x9a78a81aa85751d1L }, + { 0x04f20579a98e84e7L,0xfe1242c04997e5b5L,0xe77a273bca21e1e4L, + 0xfcc8b1ef9411939dL } }, + /* 40 << 224 */ + { { 0xe20ea30292d0487aL,0x1442dbec294b91feL,0x1f7a4afebb6b0e8fL, + 0x1700ef746889c318L }, + { 0xf5bbffc370f1fc62L,0x3b31d4b669c79ccaL,0xe8bc2aaba7f6340dL, + 0xb0b08ab4a725e10aL } }, + /* 41 << 224 */ + { { 0x44f05701ae340050L,0xba4b30161cf0c569L,0x5aa29f83fbe19a51L, + 0x1b9ed428b71d752eL }, + { 0x1666e54eeb4819f5L,0x616cdfed9e18b75bL,0x112ed5be3ee27b0bL, + 0xfbf2831944c7de4dL } }, + /* 42 << 224 */ + { { 0xd685ec85e0e60d84L,0x68037e301db7ee78L,0x5b65bdcd003c4d6eL, + 0x33e7363a93e29a6aL }, + { 0x995b3a6108d0756cL,0xd727f85c2faf134bL,0xfac6edf71d337823L, + 0x99b9aa500439b8b4L } }, + /* 43 << 224 */ + { { 0x722eb104e2b4e075L,0x49987295437c4926L,0xb1e4c0e446a9b82dL, + 0xd0cb319757a006f5L }, + { 0xf3de0f7dd7808c56L,0xb5c54d8f51f89772L,0x500a114aadbd31aaL, + 0x9afaaaa6295f6cabL } }, + /* 44 << 224 */ + { { 0x94705e2104cf667aL,0xfc2a811b9d3935d7L,0x560b02806d09267cL, + 0xf19ed119f780e53bL }, + { 0xf0227c09067b6269L,0x967b85335caef599L,0x155b924368efeebcL, + 0xcd6d34f5c497bae6L } }, + /* 45 << 224 */ + { { 0x1dd8d5d36cceb370L,0x2aeac579a78d7bf9L,0x5d65017d70b67a62L, + 0x70c8e44f17c53f67L }, + { 0xd1fc095086a34d09L,0xe0fca256e7134907L,0xe24fa29c80fdd315L, + 0x2c4acd03d87499adL } }, + /* 46 << 224 */ + { { 0xbaaf75173b5a9ba6L,0xb9cbe1f612e51a51L,0xd88edae35e154897L, + 0xe4309c3c77b66ca0L }, + { 0xf5555805f67f3746L,0x85fc37baa36401ffL,0xdf86e2cad9499a53L, + 0x6270b2a3ecbc955bL } }, + /* 47 << 224 */ + { { 0xafae64f5974ad33bL,0x04d85977fe7b2df1L,0x2a3db3ff4ab03f73L, + 0x0b87878a8702740aL }, + { 0x6d263f015a061732L,0xc25430cea32a1901L,0xf7ebab3ddb155018L, + 0x3a86f69363a9b78eL } }, + /* 48 << 224 */ + { { 0x349ae368da9f3804L,0x470f07fea164349cL,0xd52f4cc98562baa5L, + 0xc74a9e862b290df3L }, + { 0xd3a1aa3543471a24L,0x239446beb8194511L,0xbec2dd0081dcd44dL, + 0xca3d7f0fc42ac82dL } }, + /* 49 << 224 */ + { { 0x1f3db085fdaf4520L,0xbb6d3e804549daf2L,0xf5969d8a19ad5c42L, + 0x7052b13ddbfd1511L }, + { 0x11890d1b682b9060L,0xa71d3883ac34452cL,0xa438055b783805b4L, + 0x432412774725b23eL } }, + /* 50 << 224 */ + { { 0xf20cf96e4901bbedL,0x6419c710f432a2bbL,0x57a0fbb9dfa9cd7dL, + 0x589111e400daa249L }, + { 0x19809a337b60554eL,0xea5f8887ede283a4L,0x2d713802503bfd35L, + 0x151bb0af585d2a53L } }, + /* 51 << 224 */ + { { 0x40b08f7443b30ca8L,0xe10b5bbad9934583L,0xe8a546d6b51110adL, + 0x1dd50e6628e0b6c5L }, + { 0x292e9d54cff2b821L,0x3882555d47281760L,0x134838f83724d6e3L, + 0xf2c679e022ddcda1L } }, + /* 52 << 224 */ + { { 0x40ee88156d2a5768L,0x7f227bd21c1e7e2dL,0x487ba134d04ff443L, + 0x76e2ff3dc614e54bL }, + { 0x36b88d6fa3177ec7L,0xbf731d512328fff5L,0x758caea249ba158eL, + 0x5ab8ff4c02938188L } }, + /* 53 << 224 */ + { { 0x33e1605635edc56dL,0x5a69d3497e940d79L,0x6c4fd00103866dcbL, + 0x20a38f574893cdefL }, + { 0xfbf3e790fac3a15bL,0x6ed7ea2e7a4f8e6bL,0xa663eb4fbc3aca86L, + 0x22061ea5080d53f7L } }, + /* 54 << 224 */ + { { 0x2480dfe6f546783fL,0xd38bc6da5a0a641eL,0xfb093cd12ede8965L, + 0x89654db4acb455cfL }, + { 0x413cbf9a26e1adeeL,0x291f3764373294d4L,0x00797257648083feL, + 0x25f504d3208cc341L } }, + /* 55 << 224 */ + { { 0x635a8e5ec3a0ee43L,0x70aaebca679898ffL,0x9ee9f5475dc63d56L, + 0xce987966ffb34d00L }, + { 0xf9f86b195e26310aL,0x9e435484382a8ca8L,0x253bcb81c2352fe4L, + 0xa4eac8b04474b571L } }, + /* 56 << 224 */ + { { 0xc1b97512c1ad8cf8L,0x193b4e9e99e0b697L,0x939d271601e85df0L, + 0x4fb265b3cd44eafdL }, + { 0x321e7dcde51e1ae2L,0x8e3a8ca6e3d8b096L,0x8de46cb052604998L, + 0x91099ad839072aa7L } }, + /* 57 << 224 */ + { { 0x2617f91c93aa96b8L,0x0fc8716b7fca2e13L,0xa7106f5e95328723L, + 0xd1c9c40b262e6522L }, + { 0xb9bafe8642b7c094L,0x1873439d1543c021L,0xe1baa5de5cbefd5dL, + 0xa363fc5e521e8affL } }, + /* 58 << 224 */ + { { 0xefe6320df862eaacL,0x14419c6322c647dcL,0x0e06707c4e46d428L, + 0xcb6c834f4a178f8fL }, + { 0x0f993a45d30f917cL,0xd4c4b0499879afeeL,0xb6142a1e70500063L, + 0x7c9b41c3a5d9d605L } }, + /* 59 << 224 */ + { { 0xbc00fc2f2f8ba2c7L,0x0966eb2f7c67aa28L,0x13f7b5165a786972L, + 0x3bfb75578a2fbba0L }, + { 0x131c4f235a2b9620L,0xbff3ed276faf46beL,0x9b4473d17e172323L, + 0x421e8878339f6246L } }, + /* 60 << 224 */ + { { 0x0fa8587a25a41632L,0xc0814124a35b6c93L,0x2b18a9f559ebb8dbL, + 0x264e335776edb29cL }, + { 0xaf245ccdc87c51e2L,0x16b3015b501e6214L,0xbb31c5600a3882ceL, + 0x6961bb94fec11e04L } }, + /* 61 << 224 */ + { { 0x3b825b8deff7a3a0L,0xbec33738b1df7326L,0x68ad747c99604a1fL, + 0xd154c9349a3bd499L }, + { 0xac33506f1cc7a906L,0x73bb53926c560e8fL,0x6428fcbe263e3944L, + 0xc11828d51c387434L } }, + /* 62 << 224 */ + { { 0x3cd04be13e4b12ffL,0xc3aad9f92d88667cL,0xc52ddcf8248120cfL, + 0x985a892e2a389532L }, + { 0xfbb4b21b3bb85fa0L,0xf95375e08dfc6269L,0xfb4fb06c7ee2aceaL, + 0x6785426e309c4d1fL } }, + /* 63 << 224 */ + { { 0x659b17c8d8ceb147L,0x9b649eeeb70a5554L,0x6b7fa0b5ac6bc634L, + 0xd99fe2c71d6e732fL }, + { 0x30e6e7628d3abba2L,0x18fee6e7a797b799L,0x5c9d360dc696464dL, + 0xe3baeb4827bfde12L } }, + /* 64 << 224 */ + { { 0x2bf5db47f23206d5L,0x2f6d34201d260152L,0x17b876533f8ff89aL, + 0x5157c30c378fa458L }, + { 0x7517c5c52d4fb936L,0xef22f7ace6518cdcL,0xdeb483e6bf847a64L, + 0xf508455892e0fa89L } }, + /* 0 << 231 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 231 */ + { { 0xab9659d8df7304d4L,0xb71bcf1bff210e8eL,0xa9a2438bd73fbd60L, + 0x4595cd1f5d11b4deL }, + { 0x9c0d329a4835859dL,0x4a0f0d2d7dbb6e56L,0xc6038e5edf928a4eL, + 0xc94296218f5ad154L } }, + /* 2 << 231 */ + { { 0x91213462f23f2d92L,0x6cab71bd60b94078L,0x6bdd0a63176cde20L, + 0x54c9b20cee4d54bcL }, + { 0x3cd2d8aa9f2ac02fL,0x03f8e617206eedb0L,0xc7f68e1693086434L, + 0x831469c592dd3db9L } }, + /* 3 << 231 */ + { { 0x8521df248f981354L,0x587e23ec3588a259L,0xcbedf281d7a0992cL, + 0x06930a5538961407L }, + { 0x09320debbe5bbe21L,0xa7ffa5b52491817fL,0xe6c8b4d909065160L, + 0xac4f3992fff6d2a9L } }, + /* 4 << 231 */ + { { 0x7aa7a1583ae9c1bdL,0xe0af6d98e37ce240L,0xe54342d928ab38b4L, + 0xe8b750070a1c98caL }, + { 0xefce86afe02358f2L,0x31b8b856ea921228L,0x052a19120a1c67fcL, + 0xb4069ea4e3aead59L } }, + /* 5 << 231 */ + { { 0x3232d6e27fa03cb3L,0xdb938e5b0fdd7d88L,0x04c1d2cd2ccbfc5dL, + 0xd2f45c12af3a580fL }, + { 0x592620b57883e614L,0x5fd27e68be7c5f26L,0x139e45a91567e1e3L, + 0x2cc71d2d44d8aaafL } }, + /* 6 << 231 */ + { { 0x4a9090cde36d0757L,0xf722d7b1d9a29382L,0xfb7fb04c04b48ddfL, + 0x628ad2a7ebe16f43L }, + { 0xcd3fbfb520226040L,0x6c34ecb15104b6c4L,0x30c0754ec903c188L, + 0xec336b082d23cab0L } }, + /* 7 << 231 */ + { { 0x473d62a21e206ee5L,0xf1e274808c49a633L,0x87ab956ce9f6b2c3L, + 0x61830b4862b606eaL }, + { 0x67cd6846e78e815fL,0xfe40139f4c02082aL,0x52bbbfcb952ec365L, + 0x74c116426b9836abL } }, + /* 8 << 231 */ + { { 0x9f51439e558df019L,0x230da4baac712b27L,0x518919e355185a24L, + 0x4dcefcdd84b78f50L }, + { 0xa7d90fb2a47d4c5aL,0x55ac9abfb30e009eL,0xfd2fc35974eed273L, + 0xb72d824cdbea8fafL } }, + /* 9 << 231 */ + { { 0xce721a744513e2caL,0x0b41861238240b2cL,0x05199968d5baa450L, + 0xeb1757ed2b0e8c25L }, + { 0x6ebc3e283dfac6d5L,0xb2431e2e48a237f5L,0x2acb5e2352f61499L, + 0x5558a2a7e06c936bL } }, + /* 10 << 231 */ + { { 0xd213f923cbb13d1bL,0x98799f425bfb9bfeL,0x1ae8ddc9701144a9L, + 0x0b8b3bb64c5595eeL }, + { 0x0ea9ef2e3ecebb21L,0x17cb6c4b3671f9a7L,0x47ef464f726f1d1fL, + 0x171b94846943a276L } }, + /* 11 << 231 */ + { { 0x51a4ae2d7ef0329cL,0x0850922291c4402aL,0x64a61d35afd45bbcL, + 0x38f096fe3035a851L }, + { 0xc7468b74a1dec027L,0xe8cf10e74fc7dcbaL,0xea35ff40f4a06353L, + 0x0b4c0dfa8b77dd66L } }, + /* 12 << 231 */ + { { 0x779b8552de7e5c19L,0xfab28609c1c0256cL,0x64f58eeeabd4743dL, + 0x4e8ef8387b6cc93bL }, + { 0xee650d264cb1bf3dL,0x4c1f9d0973dedf61L,0xaef7c9d7bfb70cedL, + 0x1ec0507e1641de1eL } }, + /* 13 << 231 */ + { { 0xcd7e5cc7cde45079L,0xde173c9a516ac9e4L,0x517a8494c170315cL, + 0x438fd90591d8e8fbL }, + { 0x5145c506c7d9630bL,0x6457a87bf47d4d75L,0xd31646bf0d9a80e8L, + 0x453add2bcef3aabeL } }, + /* 14 << 231 */ + { { 0xc9941109a607419dL,0xfaa71e62bb6bca80L,0x34158c1307c431f3L, + 0x594abebc992bc47aL }, + { 0x6dfea691eb78399fL,0x48aafb353f42cba4L,0xedcd65af077c04f0L, + 0x1a29a366e884491aL } }, + /* 15 << 231 */ + { { 0x023a40e51c21f2bfL,0xf99a513ca5057aeeL,0xa3fe7e25bcab072eL, + 0x8568d2e140e32bcfL }, + { 0x904594ebd3f69d9fL,0x181a973307affab1L,0xe4d68d76b6e330f4L, + 0x87a6dafbc75a7fc1L } }, + /* 16 << 231 */ + { { 0x549db2b5ef7d9289L,0x2480d4a8197f015aL,0x61d5590bc40493b6L, + 0x3a55b52e6f780331L }, + { 0x40eb8115309eadb0L,0xdea7de5a92e5c625L,0x64d631f0cc6a3d5aL, + 0x9d5e9d7c93e8dd61L } }, + /* 17 << 231 */ + { { 0xf297bef5206d3ffcL,0x23d5e0337d808bd4L,0x4a4f6912d24cf5baL, + 0xe4d8163b09cdaa8aL }, + { 0x0e0de9efd3082e8eL,0x4fe1246c0192f360L,0x1f9001504b8eee0aL, + 0x5219da81f1da391bL } }, + /* 18 << 231 */ + { { 0x7bf6a5c1f7ea25aaL,0xd165e6bffbb07d5fL,0xe353936189e78671L, + 0xa3fcac892bac4219L }, + { 0xdfab6fd4f0baa8abL,0x5a4adac1e2c1c2e5L,0x6cd75e3140d85849L, + 0xce263fea19b39181L } }, + /* 19 << 231 */ + { { 0xcb6803d307032c72L,0x7f40d5ce790968c8L,0xa6de86bddce978f0L, + 0x25547c4f368f751cL }, + { 0xb1e685fd65fb2a9eL,0xce69336f1eb9179cL,0xb15d1c2712504442L, + 0xb7df465cb911a06bL } }, + /* 20 << 231 */ + { { 0xb8d804a3315980cdL,0x693bc492fa3bebf7L,0x3578aeee2253c504L, + 0x158de498cd2474a2L }, + { 0x1331f5c7cfda8368L,0xd2d7bbb378d7177eL,0xdf61133af3c1e46eL, + 0x5836ce7dd30e7be8L } }, + /* 21 << 231 */ + { { 0x83084f1994f834cbL,0xd35653d4429ed782L,0xa542f16f59e58243L, + 0xc2b52f650470a22dL }, + { 0xe3b6221b18f23d96L,0xcb05abac3f5252b4L,0xca00938b87d61402L, + 0x2f186cdd411933e4L } }, + /* 22 << 231 */ + { { 0xe042ece59a29a5c5L,0xb19b3c073b6c8402L,0xc97667c719d92684L, + 0xb5624622ebc66372L }, + { 0x0cb96e653c04fa02L,0x83a7176c8eaa39aaL,0x2033561deaa1633fL, + 0x45a9d0864533df73L } }, + /* 23 << 231 */ + { { 0xe0542c1d3dc090bcL,0x82c996efaa59c167L,0xe3f735e80ee7fc4dL, + 0x7b1793937c35db79L }, + { 0xb6419e25f8c5dbfdL,0x4d9d7a1e1f327b04L,0x979f6f9b298dfca8L, + 0xc7c5dff18de9366aL } }, + /* 24 << 231 */ + { { 0x1b7a588d04c82bddL,0x68005534f8319dfdL,0xde8a55b5d8eb9580L, + 0x5ea886da8d5bca81L }, + { 0xe8530a01252a0b4dL,0x1bffb4fe35eaa0a1L,0x2ad828b1d8e99563L, + 0x7de96ef595f9cd87L } }, + /* 25 << 231 */ + { { 0x4abb2d0cd77d970cL,0x03cfb933d33ef9cbL,0xb0547c018b211fe9L, + 0x2fe64809a56ed1c6L }, + { 0xcb7d5624c2ac98ccL,0x2a1372c01a393e33L,0xc8d1ec1c29660521L, + 0xf3d31b04b37ac3e9L } }, + /* 26 << 231 */ + { { 0xa29ae9df5ece6e7cL,0x0603ac8f0facfb55L,0xcfe85b7adda233a5L, + 0xe618919fbd75f0b8L }, + { 0xf555a3d299bf1603L,0x1f43afc9f184255aL,0xdcdaf341319a3e02L, + 0xd3b117ef03903a39L } }, + /* 27 << 231 */ + { { 0xe095da1365d1d131L,0x86f16367c37ad03eL,0x5f37389e462cd8ddL, + 0xc103fa04d67a60e6L }, + { 0x57c34344f4b478f0L,0xce91edd8e117c98dL,0x001777b0231fc12eL, + 0x11ae47f2b207bccbL } }, + /* 28 << 231 */ + { { 0xd983cf8d20f8a242L,0x7aff5b1df22e1ad8L,0x68fd11d07fc4feb3L, + 0x5d53ae90b0f1c3e1L }, + { 0x50fb7905ec041803L,0x85e3c97714404888L,0x0e67faedac628d8fL, + 0x2e8651506668532cL } }, + /* 29 << 231 */ + { { 0x15acaaa46a67a6b0L,0xf4cdee25b25cec41L,0x49ee565ae4c6701eL, + 0x2a04ca66fc7d63d8L }, + { 0xeb105018ef0543fbL,0xf709a4f5d1b0d81dL,0x5b906ee62915d333L, + 0xf4a8741296f1f0abL } }, + /* 30 << 231 */ + { { 0xb6b82fa74d82f4c2L,0x90725a606804efb3L,0xbc82ec46adc3425eL, + 0xb7b805812787843eL }, + { 0xdf46d91cdd1fc74cL,0xdc1c62cbe783a6c4L,0x59d1b9f31a04cbbaL, + 0xd87f6f7295e40764L } }, + /* 31 << 231 */ + { { 0x02b4cfc1317f4a76L,0x8d2703eb91036bceL,0x98206cc6a5e72a56L, + 0x57be9ed1cf53fb0fL }, + { 0x09374571ef0b17acL,0x74b2655ed9181b38L,0xc8f80ea889935d0eL, + 0xc0d9e94291529936L } }, + /* 32 << 231 */ + { { 0x196860411e84e0e5L,0xa5db84d3aea34c93L,0xf9d5bb197073a732L, + 0xb8d2fe566bcfd7c0L }, + { 0x45775f36f3eb82faL,0x8cb20cccfdff8b58L,0x1659b65f8374c110L, + 0xb8b4a422330c789aL } }, + /* 33 << 231 */ + { { 0x75e3c3ea6fe8208bL,0xbd74b9e4286e78feL,0x0be2e81bd7d93a1aL, + 0x7ed06e27dd0a5aaeL }, + { 0x721f5a586be8b800L,0x428299d1d846db28L,0x95cb8e6b5be88ed3L, + 0xc3186b231c034e11L } }, + /* 34 << 231 */ + { { 0xa6312c9e8977d99bL,0xbe94433183f531e7L,0x8232c0c218d3b1d4L, + 0x617aae8be1247b73L }, + { 0x40153fc4282aec3bL,0xc6063d2ff7b8f823L,0x68f10e583304f94cL, + 0x31efae74ee676346L } }, + /* 35 << 231 */ + { { 0xbadb6c6d40a9b97cL,0x14702c634f666256L,0xdeb954f15184b2e3L, + 0x5184a52694b6ca40L }, + { 0xfff05337003c32eaL,0x5aa374dd205974c7L,0x9a7638544b0dd71aL, + 0x459cd27fdeb947ecL } }, + /* 36 << 231 */ + { { 0xa6e28161459c2b92L,0x2f020fa875ee8ef5L,0xb132ec2d30b06310L, + 0xc3e15899bc6a4530L }, + { 0xdc5f53feaa3f451aL,0x3a3c7f23c2d9acacL,0x2ec2f8926b27e58bL, + 0x68466ee7d742799fL } }, + /* 37 << 231 */ + { { 0x98324dd41fa26613L,0xa2dc6dabbdc29d63L,0xf9675faad712d657L, + 0x813994be21fd8d15L }, + { 0x5ccbb722fd4f7553L,0x5135ff8bf3a36b20L,0x44be28af69559df5L, + 0x40b65bed9d41bf30L } }, + /* 38 << 231 */ + { { 0xd98bf2a43734e520L,0x5e3abbe3209bdcbaL,0x77c76553bc945b35L, + 0x5331c093c6ef14aaL }, + { 0x518ffe2976b60c80L,0x2285593b7ace16f8L,0xab1f64ccbe2b9784L, + 0xe8f2c0d9ab2421b6L } }, + /* 39 << 231 */ + { { 0x617d7174c1df065cL,0xafeeb5ab5f6578faL,0x16ff1329263b54a8L, + 0x45c55808c990dce3L }, + { 0x42eab6c0ecc8c177L,0x799ea9b55982ecaaL,0xf65da244b607ef8eL, + 0x8ab226ce32a3fc2cL } }, + /* 40 << 231 */ + { { 0x745741e57ea973dcL,0x5c00ca7020888f2eL,0x7cdce3cf45fd9cf1L, + 0x8a741ef15507f872L }, + { 0x47c51c2f196b4cecL,0x70d08e43c97ea618L,0x930da15c15b18a2bL, + 0x33b6c6782f610514L } }, + /* 41 << 231 */ + { { 0xc662e4f807ac9794L,0x1eccf050ba06cb79L,0x1ff08623e7d954e5L, + 0x6ef2c5fb24cf71c3L }, + { 0xb2c063d267978453L,0xa0cf37961d654af8L,0x7cb242ea7ebdaa37L, + 0x206e0b10b86747e0L } }, + /* 42 << 231 */ + { { 0x481dae5fd5ecfefcL,0x07084fd8c2bff8fcL,0x8040a01aea324596L, + 0x4c646980d4de4036L }, + { 0x9eb8ab4ed65abfc3L,0xe01cb91f13541ec7L,0x8f029adbfd695012L, + 0x9ae284833c7569ecL } }, + /* 43 << 231 */ + { { 0xa5614c9ea66d80a1L,0x680a3e4475f5f911L,0x0c07b14dceba4fc1L, + 0x891c285ba13071c1L }, + { 0xcac67ceb799ece3cL,0x29b910a941e07e27L,0x66bdb409f2e43123L, + 0x06f8b1377ac9ecbeL } }, + /* 44 << 231 */ + { { 0x5981fafd38547090L,0x19ab8b9f85e3415dL,0xfc28c194c7e31b27L, + 0x843be0aa6fbcbb42L }, + { 0xf3b1ed43a6db836cL,0x2a1330e401a45c05L,0x4f19f3c595c1a377L, + 0xa85f39d044b5ee33L } }, + /* 45 << 231 */ + { { 0x3da18e6d4ae52834L,0x5a403b397423dcb0L,0xbb555e0af2374aefL, + 0x2ad599c41e8ca111L }, + { 0x1b3a2fb9014b3bf8L,0x73092684f66d5007L,0x079f1426c4340102L, + 0x1827cf818fddf4deL } }, + /* 46 << 231 */ + { { 0xc83605f6f10ff927L,0xd387145123739fc6L,0x6d163450cac1c2ccL, + 0x6b521296a2ec1ac5L }, + { 0x0606c4f96e3cb4a5L,0xe47d3f41778abff7L,0x425a8d5ebe8e3a45L, + 0x53ea9e97a6102160L } }, + /* 47 << 231 */ + { { 0x477a106e39cbb688L,0x532401d2f3386d32L,0x8e564f64b1b9b421L, + 0xca9b838881dad33fL }, + { 0xb1422b4e2093913eL,0x533d2f9269bc8112L,0x3fa017beebe7b2c7L, + 0xb2767c4acaf197c6L } }, + /* 48 << 231 */ + { { 0xc925ff87aedbae9fL,0x7daf0eb936880a54L,0x9284ddf59c4d0e71L, + 0x1581cf93316f8cf5L }, + { 0x3eeca8873ac1f452L,0xb417fce9fb6aeffeL,0xa5918046eefb8dc3L, + 0x73d318ac02209400L } }, + /* 49 << 231 */ + { { 0xe800400f728693e5L,0xe87d814b339927edL,0x93e94d3b57ea9910L, + 0xff8a35b62245fb69L }, + { 0x043853d77f200d34L,0x470f1e680f653ce1L,0x81ac05bd59a06379L, + 0xa14052c203930c29L } }, + /* 50 << 231 */ + { { 0x6b72fab526bc2797L,0x13670d1699f16771L,0x001700521e3e48d1L, + 0x978fe401b7adf678L }, + { 0x55ecfb92d41c5dd4L,0x5ff8e247c7b27da5L,0xe7518272013fb606L, + 0x5768d7e52f547a3cL } }, + /* 51 << 231 */ + { { 0xbb24eaa360017a5fL,0x6b18e6e49c64ce9bL,0xc225c655103dde07L, + 0xfc3672ae7592f7eaL }, + { 0x9606ad77d06283a1L,0x542fc650e4d59d99L,0xabb57c492a40e7c2L, + 0xac948f13a8db9f55L } }, + /* 52 << 231 */ + { { 0x6d4c9682b04465c3L,0xe3d062fa6468bd15L,0xa51729ac5f318d7eL, + 0x1fc87df69eb6fc95L }, + { 0x63d146a80591f652L,0xa861b8f7589621aaL,0x59f5f15ace31348cL, + 0x8f663391440da6daL } }, + /* 53 << 231 */ + { { 0xcfa778acb591ffa3L,0x027ca9c54cdfebceL,0xbe8e05a5444ea6b3L, + 0x8aab4e69a78d8254L }, + { 0x2437f04fb474d6b8L,0x6597ffd4045b3855L,0xbb0aea4eca47ecaaL, + 0x568aae8385c7ebfcL } }, + /* 54 << 231 */ + { { 0x0e966e64c73b2383L,0x49eb3447d17d8762L,0xde1078218da05dabL, + 0x443d8baa016b7236L }, + { 0x163b63a5ea7610d6L,0xe47e4185ce1ca979L,0xae648b6580baa132L, + 0xebf53de20e0d5b64L } }, + /* 55 << 231 */ + { { 0x8d3bfcb4d3c8c1caL,0x0d914ef35d04b309L,0x55ef64153de7d395L, + 0xbde1666f26b850e8L }, + { 0xdbe1ca6ed449ab19L,0x8902b322e89a2672L,0xb1674b7edacb7a53L, + 0x8e9faf6ef52523ffL } }, + /* 56 << 231 */ + { { 0x6ba535da9a85788bL,0xd21f03aebd0626d4L,0x099f8c47e873dc64L, + 0xcda8564d018ec97eL }, + { 0x3e8d7a5cde92c68cL,0x78e035a173323cc4L,0x3ef26275f880ff7cL, + 0xa4ee3dff273eedaaL } }, + /* 57 << 231 */ + { { 0x58823507af4e18f8L,0x967ec9b50672f328L,0x9ded19d9559d3186L, + 0x5e2ab3de6cdce39cL }, + { 0xabad6e4d11c226dfL,0xf9783f4387723014L,0x9a49a0cf1a885719L, + 0xfc0c1a5a90da9dbfL } }, + /* 58 << 231 */ + { { 0x8bbaec49571d92acL,0x569e85fe4692517fL,0x8333b014a14ea4afL, + 0x32f2a62f12e5c5adL }, + { 0x98c2ce3a06d89b85L,0xb90741aa2ff77a08L,0x2530defc01f795a2L, + 0xd6e5ba0b84b3c199L } }, + /* 59 << 231 */ + { { 0x7d8e845112e4c936L,0xae419f7dbd0be17bL,0xa583fc8c22262bc9L, + 0x6b842ac791bfe2bdL }, + { 0x33cef4e9440d6827L,0x5f69f4deef81fb14L,0xf16cf6f6234fbb92L, + 0x76ae3fc3d9e7e158L } }, + /* 60 << 231 */ + { { 0x4e89f6c2e9740b33L,0x677bc85d4962d6a1L,0x6c6d8a7f68d10d15L, + 0x5f9a72240257b1cdL }, + { 0x7096b9164ad85961L,0x5f8c47f7e657ab4aL,0xde57d7d0f7461d7eL, + 0x7eb6094d80ce5ee2L } }, + /* 61 << 231 */ + { { 0x0b1e1dfd34190547L,0x8a394f43f05dd150L,0x0a9eb24d97df44e6L, + 0x78ca06bf87675719L }, + { 0x6f0b34626ffeec22L,0x9d91bcea36cdd8fbL,0xac83363ca105be47L, + 0x81ba76c1069710e3L } }, + /* 62 << 231 */ + { { 0x3d1b24cb28c682c6L,0x27f252288612575bL,0xb587c779e8e66e98L, + 0x7b0c03e9405eb1feL }, + { 0xfdf0d03015b548e7L,0xa8be76e038b36af7L,0x4cdab04a4f310c40L, + 0x6287223ef47ecaecL } }, + /* 63 << 231 */ + { { 0x678e60558b399320L,0x61fe3fa6c01e4646L,0xc482866b03261a5eL, + 0xdfcf45b85c2f244aL }, + { 0x8fab9a512f684b43L,0xf796c654c7220a66L,0x1d90707ef5afa58fL, + 0x2c421d974fdbe0deL } }, + /* 64 << 231 */ + { { 0xc4f4cda3af2ebc2fL,0xa0af843dcb4efe24L,0x53b857c19ccd10b1L, + 0xddc9d1eb914d3e04L }, + { 0x7bdec8bb62771debL,0x829277aa91c5aa81L,0x7af18dd6832391aeL, + 0x1740f316c71a84caL } }, + /* 0 << 238 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 238 */ + { { 0x8928e99aeeaf8c49L,0xee7aa73d6e24d728L,0x4c5007c2e72b156cL, + 0x5fcf57c5ed408a1dL }, + { 0x9f719e39b6057604L,0x7d343c01c2868bbfL,0x2cca254b7e103e2dL, + 0xe6eb38a9f131bea2L } }, + /* 2 << 238 */ + { { 0xb33e624f8be762b4L,0x2a9ee4d1058e3413L,0x968e636967d805faL, + 0x9848949b7db8bfd7L }, + { 0x5308d7e5d23a8417L,0x892f3b1df3e29da5L,0xc95c139e3dee471fL, + 0x8631594dd757e089L } }, + /* 3 << 238 */ + { { 0xe0c82a3cde918dccL,0x2e7b599426fdcf4bL,0x82c5024932cb1b2dL, + 0xea613a9d7657ae07L }, + { 0xc2eb5f6cf1fdc9f7L,0xb6eae8b8879fe682L,0x253dfee0591cbc7fL, + 0x000da7133e1290e6L } }, + /* 4 << 238 */ + { { 0x1083e2ea1f095615L,0x0a28ad7714e68c33L,0x6bfc02523d8818beL, + 0xb585113af35850cdL }, + { 0x7d935f0b30df8aa1L,0xaddda07c4ab7e3acL,0x92c34299552f00cbL, + 0xc33ed1de2909df6cL } }, + /* 5 << 238 */ + { { 0x22c2195d80e87766L,0x9e99e6d89ddf4ac0L,0x09642e4e65e74934L, + 0x2610ffa2ff1ff241L }, + { 0x4d1d47d4751c8159L,0x697b4985af3a9363L,0x0318ca4687477c33L, + 0xa90cb5659441eff3L } }, + /* 6 << 238 */ + { { 0x58bb384836f024cbL,0x85be1f7736016168L,0x6c59587cdc7e07f1L, + 0x191be071af1d8f02L }, + { 0xbf169fa5cca5e55cL,0x3864ba3cf7d04eacL,0x915e367f8d7d05dbL, + 0xb48a876da6549e5dL } }, + /* 7 << 238 */ + { { 0xef89c656580e40a2L,0xf194ed8c728068bcL,0x74528045a47990c9L, + 0xf53fc7d75e1a4649L }, + { 0xbec5ae9b78593e7dL,0x2cac4ee341db65d7L,0xa8c1eb2404a3d39bL, + 0x53b7d63403f8f3efL } }, + /* 8 << 238 */ + { { 0x2dc40d483e07113cL,0x6e4a5d397d8b63aeL,0x5582a94b79684c2bL, + 0x932b33d4622da26cL }, + { 0xf534f6510dbbf08dL,0x211d07c964c23a52L,0x0eeece0fee5bdc9bL, + 0xdf178168f7015558L } }, + /* 9 << 238 */ + { { 0xd42946350a712229L,0x93cbe44809273f8cL,0x00b095ef8f13bc83L, + 0xbb7419728798978cL }, + { 0x9d7309a256dbe6e7L,0xe578ec565a5d39ecL,0x3961151b851f9a31L, + 0x2da7715de5709eb4L } }, + /* 10 << 238 */ + { { 0x867f301753dfabf0L,0x728d2078b8e39259L,0x5c75a0cd815d9958L, + 0xf84867a616603be1L }, + { 0xc865b13d70e35b1cL,0x0241446819b03e2cL,0xe46041daac1f3121L, + 0x7c9017ad6f028a7cL } }, + /* 11 << 238 */ + { { 0xabc96de90a482873L,0x4265d6b1b77e54d4L,0x68c38e79a57d88e7L, + 0xd461d7669ce82de3L }, + { 0x817a9ec564a7e489L,0xcc5675cda0def5f2L,0x9a00e785985d494eL, + 0xc626833f1b03514aL } }, + /* 12 << 238 */ + { { 0xabe7905a83cdd60eL,0x50602fb5a1170184L,0x689886cdb023642aL, + 0xd568d090a6e1fb00L }, + { 0x5b1922c70259217fL,0x93831cd9c43141e4L,0xdfca35870c95f86eL, + 0xdec2057a568ae828L } }, + /* 13 << 238 */ + { { 0xc44ea599f98a759aL,0x55a0a7a2f7c23c1dL,0xd5ffb6e694c4f687L, + 0x3563cce212848478L }, + { 0x812b3517e7b1fbe1L,0x8a7dc9794f7338e0L,0x211ecee952d048dbL, + 0x2eea4056c86ea3b8L } }, + /* 14 << 238 */ + { { 0xd8cb68a7ba772b34L,0xe16ed3415f4e2541L,0x9b32f6a60fec14dbL, + 0xeee376f7391698beL }, + { 0xe9a7aa1783674c02L,0x65832f975843022aL,0x29f3a8da5ba4990fL, + 0x79a59c3afb8e3216L } }, + /* 15 << 238 */ + { { 0x9cdc4d2ebd19bb16L,0xc6c7cfd0b3262d86L,0xd4ce14d0969c0b47L, + 0x1fa352b713e56128L }, + { 0x383d55b8973db6d3L,0x71836850e8e5b7bfL,0xc7714596e6bb571fL, + 0x259df31f2d5b2dd2L } }, + /* 16 << 238 */ + { { 0x568f8925913cc16dL,0x18bc5b6de1a26f5aL,0xdfa413bef5f499aeL, + 0xf8835decc3f0ae84L }, + { 0xb6e60bd865a40ab0L,0x65596439194b377eL,0xbcd8562592084a69L, + 0x5ce433b94f23ede0L } }, + /* 17 << 238 */ + { { 0xe8e8f04f6ad65143L,0x11511827d6e14af6L,0x3d390a108295c0c7L, + 0x71e29ee4621eba16L }, + { 0xa588fc0963717b46L,0x02be02fee06ad4a2L,0x931558c604c22b22L, + 0xbb4d4bd612f3c849L } }, + /* 18 << 238 */ + { { 0x54a4f49620efd662L,0x92ba6d20c5952d14L,0x2db8ea1ecc9784c2L, + 0x81cc10ca4b353644L }, + { 0x40b570ad4b4d7f6cL,0x5c9f1d9684a1dcd2L,0x01379f813147e797L, + 0xe5c6097b2bd499f5L } }, + /* 19 << 238 */ + { { 0x40dcafa6328e5e20L,0xf7b5244a54815550L,0xb9a4f11847bfc978L, + 0x0ea0e79fd25825b1L }, + { 0xa50f96eb646c7ecfL,0xeb811493446dea9dL,0x2af04677dfabcf69L, + 0xbe3a068fc713f6e8L } }, + /* 20 << 238 */ + { { 0x860d523d42e06189L,0xbf0779414e3aff13L,0x0b616dcac1b20650L, + 0xe66dd6d12131300dL }, + { 0xd4a0fd67ff99abdeL,0xc9903550c7aac50dL,0x022ecf8b7c46b2d7L, + 0x3333b1e83abf92afL } }, + /* 21 << 238 */ + { { 0x11cc113c6c491c14L,0x0597668880dd3f88L,0xf5b4d9e729d932edL, + 0xe982aad8a2c38b6dL }, + { 0x6f9253478be0dcf0L,0x700080ae65ca53f2L,0xd8131156443ca77fL, + 0xe92d6942ec51f984L } }, + /* 22 << 238 */ + { { 0xd2a08af885dfe9aeL,0xd825d9a54d2a86caL,0x2c53988d39dff020L, + 0xf38b135a430cdc40L }, + { 0x0c918ae062a7150bL,0xf31fd8de0c340e9bL,0xafa0e7ae4dbbf02eL, + 0x5847fb2a5eba6239L } }, + /* 23 << 238 */ + { { 0x6b1647dcdccbac8bL,0xb642aa7806f485c8L,0x873f37657038ecdfL, + 0x2ce5e865fa49d3feL }, + { 0xea223788c98c4400L,0x8104a8cdf1fa5279L,0xbcf7cc7a06becfd7L, + 0x49424316c8f974aeL } }, + /* 24 << 238 */ + { { 0xc0da65e784d6365dL,0xbcb7443f8f759fb8L,0x35c712b17ae81930L, + 0x80428dff4c6e08abL }, + { 0xf19dafefa4faf843L,0xced8538dffa9855fL,0x20ac409cbe3ac7ceL, + 0x358c1fb6882da71eL } }, + /* 25 << 238 */ + { { 0xafa9c0e5fd349961L,0x2b2cfa518421c2fcL,0x2a80db17f3a28d38L, + 0xa8aba5395d138e7eL }, + { 0x52012d1d6e96eb8dL,0x65d8dea0cbaf9622L,0x57735447b264f56cL, + 0xbeebef3f1b6c8da2L } }, + /* 26 << 238 */ + { { 0xfc346d98ce785254L,0xd50e8d72bb64a161L,0xc03567c749794addL, + 0x15a76065752c7ef6L }, + { 0x59f3a222961f23d6L,0x378e443873ecc0b0L,0xc74be4345a82fde4L, + 0xae509af2d8b9cf34L } }, + /* 27 << 238 */ + { { 0x4a61ee46577f44a1L,0xe09b748cb611deebL,0xc0481b2cf5f7b884L, + 0x3562667861acfa6bL }, + { 0x37f4c518bf8d21e6L,0x22d96531b205a76dL,0x37fb85e1954073c0L, + 0xbceafe4f65b3a567L } }, + /* 28 << 238 */ + { { 0xefecdef7be42a582L,0xd3fc608065046be6L,0xc9af13c809e8dba9L, + 0x1e6c9847641491ffL }, + { 0x3b574925d30c31f7L,0xb7eb72baac2a2122L,0x776a0dacef0859e7L, + 0x06fec31421900942L } }, + /* 29 << 238 */ + { { 0x2464bc10f8c22049L,0x9bfbcce7875ebf69L,0xd7a88e2a4336326bL, + 0xda05261c5bc2acfaL }, + { 0xc29f5bdceba7efc8L,0x471237ca25dbbf2eL,0xa72773f22975f127L, + 0xdc744e8e04d0b326L } }, + /* 30 << 238 */ + { { 0x38a7ed16a56edb73L,0x64357e372c007e70L,0xa167d15b5080b400L, + 0x07b4116423de4be1L }, + { 0xb2d91e3274c89883L,0x3c1628212882e7edL,0xad6b36ba7503e482L, + 0x48434e8e0ea34331L } }, + /* 31 << 238 */ + { { 0x79f4f24f2c7ae0b9L,0xc46fbf811939b44aL,0x76fefae856595eb1L, + 0x417b66abcd5f29c7L }, + { 0x5f2332b2c5ceec20L,0xd69661ffe1a1cae2L,0x5ede7e529b0286e6L, + 0x9d062529e276b993L } }, + /* 32 << 238 */ + { { 0x324794b07e50122bL,0xdd744f8b4af07ca5L,0x30a12f08d63fc97bL, + 0x39650f1a76626d9dL }, + { 0x101b47f71fa38477L,0x3d815f19d4dc124fL,0x1569ae95b26eb58aL, + 0xc3cde18895fb1887L } }, + /* 33 << 238 */ + { { 0x54e9f37bf9539a48L,0xb0100e067408c1a5L,0x821d9811ea580cbbL, + 0x8af52d3586e50c56L }, + { 0xdfbd9d47dbbf698bL,0x2961a1ea03dc1c73L,0x203d38f8e76a5df8L, + 0x08a53a686def707aL } }, + /* 34 << 238 */ + { { 0x26eefb481bee45d4L,0xb3cee3463c688036L,0x463c5315c42f2469L, + 0x19d84d2e81378162L }, + { 0x22d7c3c51c4d349fL,0x65965844163d59c5L,0xcf198c56b8abceaeL, + 0x6fb1fb1b628559d5L } }, + /* 35 << 238 */ + { { 0x8bbffd0607bf8fe3L,0x46259c583467734bL,0xd8953cea35f7f0d3L, + 0x1f0bece2d65b0ff1L }, + { 0xf7d5b4b3f3c72914L,0x29e8ea953cb53389L,0x4a365626836b6d46L, + 0xe849f910ea174fdeL } }, + /* 36 << 238 */ + { { 0x7ec62fbbf4737f21L,0xd8dba5ab6209f5acL,0x24b5d7a9a5f9adbeL, + 0x707d28f7a61dc768L }, + { 0x7711460bcaa999eaL,0xba7b174d1c92e4ccL,0x3c4bab6618d4bf2dL, + 0xb8f0c980eb8bd279L } }, + /* 37 << 238 */ + { { 0x024bea9a324b4737L,0xfba9e42332a83bcaL,0x6e635643a232dcedL, + 0x996193672571c8baL }, + { 0xe8c9f35754b7032bL,0xf936b3ba2442d54aL,0x2263f0f08290c65aL, + 0x48989780ee2c7fdbL } }, + /* 38 << 238 */ + { { 0xadc5d55a13d4f95eL,0x737cff85ad9b8500L,0x271c557b8a73f43dL, + 0xbed617a4e18bc476L }, + { 0x662454017dfd8ab2L,0xae7b89ae3a2870aaL,0x1b555f5323a7e545L, + 0x6791e247be057e4cL } }, + /* 39 << 238 */ + { { 0x860136ad324fa34dL,0xea1114474cbeae28L,0x023a4270bedd3299L, + 0x3d5c3a7fc1c35c34L }, + { 0xb0f6db678d0412d2L,0xd92625e2fcdc6b9aL,0x92ae5ccc4e28a982L, + 0xea251c3647a3ce7eL } }, + /* 40 << 238 */ + { { 0x9d658932790691bfL,0xed61058906b736aeL,0x712c2f04c0d63b6eL, + 0x5cf06fd5c63d488fL }, + { 0x97363facd9588e41L,0x1f9bf7622b93257eL,0xa9d1ffc4667acaceL, + 0x1cf4a1aa0a061ecfL } }, + /* 41 << 238 */ + { { 0x40e48a49dc1818d0L,0x0643ff39a3621ab0L,0x5768640ce39ef639L, + 0x1fc099ea04d86854L }, + { 0x9130b9c3eccd28fdL,0xd743cbd27eec54abL,0x052b146fe5b475b6L, + 0x058d9a82900a7d1fL } }, + /* 42 << 238 */ + { { 0x65e0229291262b72L,0x96f924f9bb0edf03L,0x5cfa59c8fe206842L, + 0xf60370045eafa720L }, + { 0x5f30699e18d7dd96L,0x381e8782cbab2495L,0x91669b46dd8be949L, + 0xb40606f526aae8efL } }, + /* 43 << 238 */ + { { 0x2812b839fc6751a4L,0x16196214fba800efL,0x4398d5ca4c1a2875L, + 0x720c00ee653d8349L }, + { 0xc2699eb0d820007cL,0x880ee660a39b5825L,0x70694694471f6984L, + 0xf7d16ea8e3dda99aL } }, + /* 44 << 238 */ + { { 0x28d675b2c0519a23L,0x9ebf94fe4f6952e3L,0xf28bb767a2294a8aL, + 0x85512b4dfe0af3f5L }, + { 0x18958ba899b16a0dL,0x95c2430cba7548a7L,0xb30d1b10a16be615L, + 0xe3ebbb9785bfb74cL } }, + /* 45 << 238 */ + { { 0xa3273cfe18549fdbL,0xf6e200bf4fcdb792L,0x54a76e1883aba56cL, + 0x73ec66f689ef6aa2L }, + { 0x8d17add7d1b9a305L,0xa959c5b9b7ae1b9dL,0x886435226bcc094aL, + 0xcc5616c4d7d429b9L } }, + /* 46 << 238 */ + { { 0xa6dada01e6a33f7cL,0xc6217a079d4e70adL,0xd619a81809c15b7cL, + 0xea06b3290e80c854L }, + { 0x174811cea5f5e7b9L,0x66dfc310787c65f4L,0x4ea7bd693316ab54L, + 0xc12c4acb1dcc0f70L } }, + /* 47 << 238 */ + { { 0xe4308d1a1e407dd9L,0xe8a3587c91afa997L,0xea296c12ab77b7a5L, + 0xb5ad49e4673c0d52L }, + { 0x40f9b2b27006085aL,0xa88ff34087bf6ec2L,0x978603b14e3066a6L, + 0xb3f99fc2b5e486e2L } }, + /* 48 << 238 */ + { { 0x07b53f5eb2e63645L,0xbe57e54784c84232L,0xd779c2167214d5cfL, + 0x617969cd029a3acaL }, + { 0xd17668cd8a7017a0L,0x77b4d19abe9b7ee8L,0x58fd0e939c161776L, + 0xa8c4f4efd5968a72L } }, + /* 49 << 238 */ + { { 0x296071cc67b3de77L,0xae3c0b8e634f7905L,0x67e440c28a7100c9L, + 0xbb8c3c1beb4b9b42L }, + { 0x6d71e8eac51b3583L,0x7591f5af9525e642L,0xf73a2f7b13f509f3L, + 0x618487aa5619ac9bL } }, + /* 50 << 238 */ + { { 0x3a72e5f79d61718aL,0x00413bcc7592d28cL,0x7d9b11d3963c35cfL, + 0x77623bcfb90a46edL }, + { 0xdeef273bdcdd2a50L,0x4a741f9b0601846eL,0x33b89e510ec6e929L, + 0xcb02319f8b7f22cdL } }, + /* 51 << 238 */ + { { 0xbbe1500d084bae24L,0x2f0ae8d7343d2693L,0xacffb5f27cdef811L, + 0xaa0c030a263fb94fL }, + { 0x6eef0d61a0f442deL,0xf92e181727b139d3L,0x1ae6deb70ad8bc28L, + 0xa89e38dcc0514130L } }, + /* 52 << 238 */ + { { 0x81eeb865d2fdca23L,0x5a15ee08cc8ef895L,0x768fa10a01905614L, + 0xeff5b8ef880ee19bL }, + { 0xf0c0cabbcb1c8a0eL,0x2e1ee9cdb8c838f9L,0x0587d8b88a4a14c0L, + 0xf6f278962ff698e5L } }, + /* 53 << 238 */ + { { 0xed38ef1c89ee6256L,0xf44ee1fe6b353b45L,0x9115c0c770e903b3L, + 0xc78ec0a1818f31dfL }, + { 0x6c003324b7dccbc6L,0xd96dd1f3163bbc25L,0x33aa82dd5cedd805L, + 0x123aae4f7f7eb2f1L } }, + /* 54 << 238 */ + { { 0x1723fcf5a26262cdL,0x1f7f4d5d0060ebd5L,0xf19c5c01b2eaa3afL, + 0x2ccb9b149790accfL }, + { 0x1f9c1cad52324aa6L,0x632005267247df54L,0x5732fe42bac96f82L, + 0x52fe771f01a1c384L } }, + /* 55 << 238 */ + { { 0x546ca13db1001684L,0xb56b4eeea1709f75L,0x266545a9d5db8672L, + 0xed971c901e8f3cfbL }, + { 0x4e7d8691e3a07b29L,0x7570d9ece4b696b9L,0xdc5fa0677bc7e9aeL, + 0x68b44cafc82c4844L } }, + /* 56 << 238 */ + { { 0x519d34b3bf44da80L,0x283834f95ab32e66L,0x6e6087976278a000L, + 0x1e62960e627312f6L }, + { 0x9b87b27be6901c55L,0x80e7853824fdbc1fL,0xbbbc09512facc27dL, + 0x06394239ac143b5aL } }, + /* 57 << 238 */ + { { 0x35bb4a40376c1944L,0x7cb6269463da1511L,0xafd29161b7148a3bL, + 0xa6f9d9ed4e2ea2eeL }, + { 0x15dc2ca2880dd212L,0x903c3813a61139a9L,0x2aa7b46d6c0f8785L, + 0x36ce2871901c60ffL } }, + /* 58 << 238 */ + { { 0xc683b028e10d9c12L,0x7573baa2032f33d3L,0x87a9b1f667a31b58L, + 0xfd3ed11af4ffae12L }, + { 0x83dcaa9a0cb2748eL,0x8239f0185d6fdf16L,0xba67b49c72753941L, + 0x2beec455c321cb36L } }, + /* 59 << 238 */ + { { 0x880156063f8b84ceL,0x764170838d38c86fL,0x054f1ca7598953ddL, + 0xc939e1104e8e7429L }, + { 0x9b1ac2b35a914f2fL,0x39e35ed3e74b8f9cL,0xd0debdb2781b2fb0L, + 0x1585638f2d997ba2L } }, + /* 60 << 238 */ + { { 0x9c4b646e9e2fce99L,0x68a210811e80857fL,0x06d54e443643b52aL, + 0xde8d6d630d8eb843L }, + { 0x7032156342146a0aL,0x8ba826f25eaa3622L,0x227a58bd86138787L, + 0x43b6c03c10281d37L } }, + /* 61 << 238 */ + { { 0x6326afbbb54dde39L,0x744e5e8adb6f2d5fL,0x48b2a99acff158e1L, + 0xa93c8fa0ef87918fL }, + { 0x2182f956de058c5cL,0x216235d2936f9e7aL,0xace0c0dbd2e31e67L, + 0xc96449bff23ac3e7L } }, + /* 62 << 238 */ + { { 0x7e9a2874170693bdL,0xa28e14fda45e6335L,0x5757f6b356427344L, + 0x822e4556acf8edf9L }, + { 0x2b7a6ee2e6a285cdL,0x5866f211a9df3af0L,0x40dde2ddf845b844L, + 0x986c3726110e5e49L } }, + /* 63 << 238 */ + { { 0x73680c2af7172277L,0x57b94f0f0cccb244L,0xbdff72672d438ca7L, + 0xbad1ce11cf4663fdL }, + { 0x9813ed9dd8f71caeL,0xf43272a6961fdaa6L,0xbeff0119bd6d1637L, + 0xfebc4f9130361978L } }, + /* 64 << 238 */ + { { 0x02b37a952f41deffL,0x0e44a59ae63b89b7L,0x673257dc143ff951L, + 0x19c02205d752baf4L }, + { 0x46c23069c4b7d692L,0x2e6392c3fd1502acL,0x6057b1a21b220846L, + 0xe51ff9460c1b5b63L } }, + /* 0 << 245 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 245 */ + { { 0x6e85cb51566c5c43L,0xcff9c9193597f046L,0x9354e90c4994d94aL, + 0xe0a393322147927dL }, + { 0x8427fac10dc1eb2bL,0x88cfd8c22ff319faL,0xe2d4e68401965274L, + 0xfa2e067d67aaa746L } }, + /* 2 << 245 */ + { { 0xb6d92a7f3e5f9f11L,0x9afe153ad6cb3b8eL,0x4d1a6dd7ddf800bdL, + 0xf6c13cc0caf17e19L }, + { 0x15f6c58e325fc3eeL,0x71095400a31dc3b2L,0x168e7c07afa3d3e7L, + 0x3f8417a194c7ae2dL } }, + /* 3 << 245 */ + { { 0xec234772813b230dL,0x634d0f5f17344427L,0x11548ab1d77fc56aL, + 0x7fab1750ce06af77L }, + { 0xb62c10a74f7c4f83L,0xa7d2edc4220a67d9L,0x1c404170921209a0L, + 0x0b9815a0face59f0L } }, + /* 4 << 245 */ + { { 0x2842589b319540c3L,0x18490f59a283d6f8L,0xa2731f84daae9fcbL, + 0x3db6d960c3683ba0L }, + { 0xc85c63bb14611069L,0xb19436af0788bf05L,0x905459df347460d2L, + 0x73f6e094e11a7db1L } }, + /* 5 << 245 */ + { { 0xdc7f938eb6357f37L,0xc5d00f792bd8aa62L,0xc878dcb92ca979fcL, + 0x37e83ed9eb023a99L }, + { 0x6b23e2731560bf3dL,0x1086e4591d0fae61L,0x782483169a9414bdL, + 0x1b956bc0f0ea9ea1L } }, + /* 6 << 245 */ + { { 0x7b85bb91c31b9c38L,0x0c5aa90b48ef57b5L,0xdedeb169af3bab6fL, + 0xe610ad732d373685L }, + { 0xf13870df02ba8e15L,0x0337edb68ca7f771L,0xe4acf747b62c036cL, + 0xd921d576b6b94e81L } }, + /* 7 << 245 */ + { { 0xdbc864392c422f7aL,0xfb635362ed348898L,0x83084668c45bfcd1L, + 0xc357c9e32b315e11L }, + { 0xb173b5405b2e5b8cL,0x7e946931e102b9a4L,0x17c890eb7b0fb199L, + 0xec225a83d61b662bL } }, + /* 8 << 245 */ + { { 0xf306a3c8ee3c76cbL,0x3cf11623d32a1f6eL,0xe6d5ab646863e956L, + 0x3b8a4cbe5c005c26L }, + { 0xdcd529a59ce6bb27L,0xc4afaa5204d4b16fL,0xb0624a267923798dL, + 0x85e56df66b307fabL } }, + /* 9 << 245 */ + { { 0x0281893c2bf29698L,0x91fc19a4d7ce7603L,0x75a5dca3ad9a558fL, + 0x40ceb3fa4d50bf77L }, + { 0x1baf6060bc9ba369L,0x927e1037597888c2L,0xd936bf1986a34c07L, + 0xd4cf10c1c34ae980L } }, + /* 10 << 245 */ + { { 0x3a3e5334859dd614L,0x9c475b5b18d0c8eeL,0x63080d1f07cd51d5L, + 0xc9c0d0a6b88b4326L }, + { 0x1ac98691c234296fL,0x2a0a83a494887fb6L,0x565114270cea9cf2L, + 0x5230a6e8a24802f5L } }, + /* 11 << 245 */ + { { 0xf7a2bf0f72e3d5c1L,0x377174464f21439eL,0xfedcbf259ce30334L, + 0xe0030a787ce202f9L }, + { 0x6f2d9ebf1202e9caL,0xe79dde6c75e6e591L,0xf52072aff1dac4f8L, + 0x6c8d087ebb9b404dL } }, + /* 12 << 245 */ + { { 0xad0fc73dbce913afL,0x909e587b458a07cbL,0x1300da84d4f00c8aL, + 0x425cd048b54466acL }, + { 0xb59cb9be90e9d8bfL,0x991616db3e431b0eL,0xd3aa117a531aecffL, + 0x91af92d359f4dc3bL } }, + /* 13 << 245 */ + { { 0x9b1ec292e93fda29L,0x76bb6c17e97d91bcL,0x7509d95faface1e6L, + 0x3653fe47be855ae3L }, + { 0x73180b280f680e75L,0x75eefd1beeb6c26cL,0xa4cdf29fb66d4236L, + 0x2d70a9976b5821d8L } }, + /* 14 << 245 */ + { { 0x7a3ee20720445c36L,0x71d1ac8259877174L,0x0fc539f7949f73e9L, + 0xd05cf3d7982e3081L }, + { 0x8758e20b7b1c7129L,0xffadcc20569e61f2L,0xb05d3a2f59544c2dL, + 0xbe16f5c19fff5e53L } }, + /* 15 << 245 */ + { { 0x73cf65b8aad58135L,0x622c2119037aa5beL,0x79373b3f646fd6a0L, + 0x0e029db50d3978cfL }, + { 0x8bdfc43794fba037L,0xaefbd687620797a6L,0x3fa5382bbd30d38eL, + 0x7627cfbf585d7464L } }, + /* 16 << 245 */ + { { 0xb2330fef4e4ca463L,0xbcef72873566cc63L,0xd161d2cacf780900L, + 0x135dc5395b54827dL }, + { 0x638f052e27bf1bc6L,0x10a224f007dfa06cL,0xe973586d6d3321daL, + 0x8b0c573826152c8fL } }, + /* 17 << 245 */ + { { 0x07ef4f2a34606074L,0x80fe7fe8a0f7047aL,0x3d1a8152e1a0e306L, + 0x32cf43d888da5222L }, + { 0xbf89a95f5f02ffe6L,0x3d9eb9a4806ad3eaL,0x012c17bb79c8e55eL, + 0xfdcd1a7499c81dacL } }, + /* 18 << 245 */ + { { 0x7043178bb9556098L,0x4090a1df801c3886L,0x759800ff9b67b912L, + 0x3e5c0304232620c8L }, + { 0x4b9d3c4b70dceecaL,0xbb2d3c15181f648eL,0xf981d8376e33345cL, + 0xb626289b0cf2297aL } }, + /* 19 << 245 */ + { { 0x766ac6598baebdcfL,0x1a28ae0975df01e5L,0xb71283da375876d8L, + 0x4865a96d607b9800L }, + { 0x25dd1bcd237936b2L,0x332f4f4b60417494L,0xd0923d68370a2147L, + 0x497f5dfbdc842203L } }, + /* 20 << 245 */ + { { 0x9dc74cbd32be5e0fL,0x7475bcb717a01375L,0x438477c950d872b1L, + 0xcec67879ffe1d63dL }, + { 0x9b006014d8578c70L,0xc9ad99a878bb6b8bL,0x6799008e11fb3806L, + 0xcfe81435cd44cab3L } }, + /* 21 << 245 */ + { { 0xa2ee15822f4fb344L,0xb8823450483fa6ebL,0x622d323d652c7749L, + 0xd8474a98beb0a15bL }, + { 0xe43c154d5d1c00d0L,0x7fd581d90e3e7aacL,0x2b44c6192525ddf8L, + 0x67a033ebb8ae9739L } }, + /* 22 << 245 */ + { { 0x113ffec19ef2d2e4L,0x1bf6767ed5a0ea7fL,0x57fff75e03714c0aL, + 0xa23c422e0a23e9eeL }, + { 0xdd5f6b2d540f83afL,0xc2c2c27e55ea46a7L,0xeb6b4246672a1208L, + 0xd13599f7ae634f7aL } }, + /* 23 << 245 */ + { { 0xcf914b5cd7b32c6eL,0x61a5a640eaf61814L,0x8dc3df8b208a1bbbL, + 0xef627fd6b6d79aa5L }, + { 0x44232ffcc4c86bc8L,0xe6f9231b061539feL,0x1d04f25a958b9533L, + 0x180cf93449e8c885L } }, + /* 24 << 245 */ + { { 0x896895959884aaf7L,0xb1959be307b348a6L,0x96250e573c147c87L, + 0xae0efb3add0c61f8L }, + { 0xed00745eca8c325eL,0x3c911696ecff3f70L,0x73acbc65319ad41dL, + 0x7b01a020f0b1c7efL } }, + /* 25 << 245 */ + { { 0xea32b29363a1483fL,0x89eabe717a248f96L,0x9c6231d3343157e5L, + 0x93a375e5df3c546dL }, + { 0xe76e93436a2afe69L,0xc4f89100e166c88eL,0x248efd0d4f872093L, + 0xae0eb3ea8fe0ea61L } }, + /* 26 << 245 */ + { { 0xaf89790d9d79046eL,0x4d650f2d6cee0976L,0xa3935d9a43071ecaL, + 0x66fcd2c9283b0bfeL }, + { 0x0e665eb5696605f1L,0xe77e5d07a54cd38dL,0x90ee050a43d950cfL, + 0x86ddebdad32e69b5L } }, + /* 27 << 245 */ + { { 0x6ad94a3dfddf7415L,0xf7fa13093f6e8d5aL,0xc4831d1de9957f75L, + 0x7de28501d5817447L }, + { 0x6f1d70789e2aeb6bL,0xba2b9ff4f67a53c2L,0x36963767df9defc3L, + 0x479deed30d38022cL } }, + /* 28 << 245 */ + { { 0xd2edb89b3a8631e8L,0x8de855de7a213746L,0xb2056cb7b00c5f11L, + 0xdeaefbd02c9b85e4L }, + { 0x03f39a8dd150892dL,0x37b84686218b7985L,0x36296dd8b7375f1aL, + 0x472cd4b1b78e898eL } }, + /* 29 << 245 */ + { { 0x15dff651e9f05de9L,0xd40450692ce98ba9L,0x8466a7ae9b38024cL, + 0xb910e700e5a6b5efL }, + { 0xae1c56eab3aa8f0dL,0xbab2a5077eee74a6L,0x0dca11e24b4c4620L, + 0xfd896e2e4c47d1f4L } }, + /* 30 << 245 */ + { { 0xeb45ae53308fbd93L,0x46cd5a2e02c36fdaL,0x6a3d4e90baa48385L, + 0xdd55e62e9dbe9960L }, + { 0xa1406aa02a81ede7L,0x6860dd14f9274ea7L,0xcfdcb0c280414f86L, + 0xff410b1022f94327L } }, + /* 31 << 245 */ + { { 0x5a33cc3849ad467bL,0xefb48b6c0a7335f1L,0x14fb54a4b153a360L, + 0x604aa9d2b52469ccL }, + { 0x5e9dc486754e48e9L,0x693cb45537471e8eL,0xfb2fd7cd8d3b37b6L, + 0x63345e16cf09ff07L } }, + /* 32 << 245 */ + { { 0x9910ba6b23a5d896L,0x1fe19e357fe4364eL,0x6e1da8c39a33c677L, + 0x15b4488b29fd9fd0L }, + { 0x1f4392541a1f22bfL,0x920a8a70ab8163e8L,0x3fd1b24907e5658eL, + 0xf2c4f79cb6ec839bL } }, + /* 33 << 245 */ + { { 0x1abbc3d04aa38d1bL,0x3b0db35cb5d9510eL,0x1754ac783e60dec0L, + 0x53272fd7ea099b33L }, + { 0x5fb0494f07a8e107L,0x4a89e1376a8191faL,0xa113b7f63c4ad544L, + 0x88a2e9096cb9897bL } }, + /* 34 << 245 */ + { { 0x17d55de3b44a3f84L,0xacb2f34417c6c690L,0x3208816810232390L, + 0xf2e8a61f6c733bf7L }, + { 0xa774aab69c2d7652L,0xfb5307e3ed95c5bcL,0xa05c73c24981f110L, + 0x1baae31ca39458c9L } }, + /* 35 << 245 */ + { { 0x1def185bcbea62e7L,0xe8ac9eaeeaf63059L,0x098a8cfd9921851cL, + 0xd959c3f13abe2f5bL }, + { 0xa4f1952520e40ae5L,0x320789e307a24aa1L,0x259e69277392b2bcL, + 0x58f6c6671918668bL } }, + /* 36 << 245 */ + { { 0xce1db2bbc55d2d8bL,0x41d58bb7f4f6ca56L,0x7650b6808f877614L, + 0x905e16baf4c349edL }, + { 0xed415140f661acacL,0x3b8784f0cb2270afL,0x3bc280ac8a402cbaL, + 0xd53f71460937921aL } }, + /* 37 << 245 */ + { { 0xc03c8ee5e5681e83L,0x62126105f6ac9e4aL,0x9503a53f936b1a38L, + 0x3d45e2d4782fecbdL }, + { 0x69a5c43976e8ae98L,0xb53b2eebbfb4b00eL,0xf167471272386c89L, + 0x30ca34a24268bce4L } }, + /* 38 << 245 */ + { { 0x7f1ed86c78341730L,0x8ef5beb8b525e248L,0xbbc489fdb74fbf38L, + 0x38a92a0e91a0b382L }, + { 0x7a77ba3f22433ccfL,0xde8362d6a29f05a9L,0x7f6a30ea61189afcL, + 0x693b550559ef114fL } }, + /* 39 << 245 */ + { { 0x50266bc0cd1797a1L,0xea17b47ef4b7af2dL,0xd6c4025c3df9483eL, + 0x8cbb9d9fa37b18c9L }, + { 0x91cbfd9c4d8424cfL,0xdb7048f1ab1c3506L,0x9eaf641f028206a3L, + 0xf986f3f925bdf6ceL } }, + /* 40 << 245 */ + { { 0x262143b5224c08dcL,0x2bbb09b481b50c91L,0xc16ed709aca8c84fL, + 0xa6210d9db2850ca8L }, + { 0x6d8df67a09cb54d6L,0x91eef6e0500919a4L,0x90f613810f132857L, + 0x9acede47f8d5028bL } }, + /* 41 << 245 */ + { { 0x844d1b7190b771c3L,0x563b71e4ba6426beL,0x2efa2e83bdb802ffL, + 0x3410cbabab5b4a41L }, + { 0x555b2d2630da84ddL,0xd0711ae9ee1cc29aL,0xcf3e8c602f547792L, + 0x03d7d5dedc678b35L } }, + /* 42 << 245 */ + { { 0x071a2fa8ced806b8L,0x222e6134697f1478L,0xdc16fd5dabfcdbbfL, + 0x44912ebf121b53b8L }, + { 0xac9436742496c27cL,0x8ea3176c1ffc26b0L,0xb6e224ac13debf2cL, + 0x524cc235f372a832L } }, + /* 43 << 245 */ + { { 0xd706e1d89f6f1b18L,0x2552f00544cce35bL,0x8c8326c2a88e31fcL, + 0xb5468b2cf9552047L }, + { 0xce683e883ff90f2bL,0x77947bdf2f0a5423L,0xd0a1b28bed56e328L, + 0xaee35253c20134acL } }, + /* 44 << 245 */ + { { 0x7e98367d3567962fL,0x379ed61f8188bffbL,0x73bba348faf130a1L, + 0x6c1f75e1904ed734L }, + { 0x189566423b4a79fcL,0xf20bc83d54ef4493L,0x836d425d9111eca1L, + 0xe5b5c318009a8dcfL } }, + /* 45 << 245 */ + { { 0x3360b25d13221bc5L,0x707baad26b3eeaf7L,0xd7279ed8743a95a1L, + 0x7450a875969e809fL }, + { 0x32b6bd53e5d0338fL,0x1e77f7af2b883bbcL,0x90da12cc1063ecd0L, + 0xe2697b58c315be47L } }, + /* 46 << 245 */ + { { 0x2771a5bdda85d534L,0x53e78c1fff980eeaL,0xadf1cf84900385e7L, + 0x7d3b14f6c9387b62L }, + { 0x170e74b0cb8f2bd2L,0x2d50b486827fa993L,0xcdbe8c9af6f32babL, + 0x55e906b0c3b93ab8L } }, + /* 47 << 245 */ + { { 0x747f22fc8fe280d1L,0xcd8e0de5b2e114abL,0x5ab7dbebe10b68b0L, + 0x9dc63a9ca480d4b2L }, + { 0x78d4bc3b4be1495fL,0x25eb3db89359122dL,0x3f8ac05b0809cbdcL, + 0xbf4187bbd37c702fL } }, + /* 48 << 245 */ + { { 0x84cea0691416a6a5L,0x8f860c7943ef881cL,0x41311f8a38038a5dL, + 0xe78c2ec0fc612067L }, + { 0x494d2e815ad73581L,0xb4cc9e0059604097L,0xff558aecf3612cbaL, + 0x35beef7a9e36c39eL } }, + /* 49 << 245 */ + { { 0x1845c7cfdbcf41b9L,0x5703662aaea997c0L,0x8b925afee402f6d8L, + 0xd0a1b1ae4dd72162L }, + { 0x9f47b37503c41c4bL,0xa023829b0391d042L,0x5f5045c3503b8b0aL, + 0x123c268898c010e5L } }, + /* 50 << 245 */ + { { 0x324ec0cc36ba06eeL,0xface31153dd2cc0cL,0xb364f3bef333e91fL, + 0xef8aff7328e832b0L }, + { 0x1e9bad042d05841bL,0x42f0e3df356a21e2L,0xa3270bcb4add627eL, + 0xb09a8158d322e711L } }, + /* 51 << 245 */ + { { 0x86e326a10fee104aL,0xad7788f83703f65dL,0x7e76543047bc4833L, + 0x6cee582b2b9b893aL }, + { 0x9cd2a167e8f55a7bL,0xefbee3c6d9e4190dL,0x33ee7185d40c2e9dL, + 0x844cc9c5a380b548L } }, + /* 52 << 245 */ + { { 0x323f8ecd66926e04L,0x0001e38f8110c1baL,0x8dbcac12fc6a7f07L, + 0xd65e1d580cec0827L }, + { 0xd2cd4141be76ca2dL,0x7895cf5ce892f33aL,0x956d230d367139d2L, + 0xa91abd3ed012c4c1L } }, + /* 53 << 245 */ + { { 0x34fa488387eb36bfL,0xc5f07102914b8fb4L,0x90f0e579adb9c95fL, + 0xfe6ea8cb28888195L }, + { 0x7b9b5065edfa9284L,0x6c510bd22b8c8d65L,0xd7b8ebefcbe8aafdL, + 0xedb3af9896b1da07L } }, + /* 54 << 245 */ + { { 0x28ff779d6295d426L,0x0c4f6ac73fa3ad7bL,0xec44d0548b8e2604L, + 0x9b32a66d8b0050e1L }, + { 0x1f943366f0476ce2L,0x7554d953a602c7b4L,0xbe35aca6524f2809L, + 0xb6881229fd4edbeaL } }, + /* 55 << 245 */ + { { 0xe8cd0c8f508efb63L,0x9eb5b5c86abcefc7L,0xf5621f5fb441ab4fL, + 0x79e6c046b76a2b22L }, + { 0x74a4792ce37a1f69L,0xcbd252cb03542b60L,0x785f65d5b3c20bd3L, + 0x8dea61434fabc60cL } }, + /* 56 << 245 */ + { { 0x45e21446de673629L,0x57f7aa1e703c2d21L,0xa0e99b7f98c868c7L, + 0x4e42f66d8b641676L }, + { 0x602884dc91077896L,0xa0d690cfc2c9885bL,0xfeb4da333b9a5187L, + 0x5f789598153c87eeL } }, + /* 57 << 245 */ + { { 0x2192dd4752b16dbaL,0xdeefc0e63524c1b1L,0x465ea76ee4383693L, + 0x79401711361b8d98L }, + { 0xa5f9ace9f21a15cbL,0x73d26163efee9aebL,0xcca844b3e677016cL, + 0x6c122b0757eaee06L } }, + /* 58 << 245 */ + { { 0xb782dce715f09690L,0x508b9b122dfc0fc9L,0x9015ab4b65d89fc6L, + 0x5e79dab7d6d5bb0fL }, + { 0x64f021f06c775aa2L,0xdf09d8cc37c7eca1L,0x9a761367ef2fa506L, + 0xed4ca4765b81eec6L } }, + /* 59 << 245 */ + { { 0x262ede3610bbb8b5L,0x0737ce830641ada3L,0x4c94288ae9831cccL, + 0x487fc1ce8065e635L }, + { 0xb13d7ab3b8bb3659L,0xdea5df3e855e4120L,0xb9a1857385eb0244L, + 0x1a1b8ea3a7cfe0a3L } }, + /* 60 << 245 */ + { { 0x3b83711967b0867cL,0x8d5e0d089d364520L,0x52dccc1ed930f0e3L, + 0xefbbcec7bf20bbafL }, + { 0x99cffcab0263ad10L,0xd8199e6dfcd18f8aL,0x64e2773fe9f10617L, + 0x0079e8e108704848L } }, + /* 61 << 245 */ + { { 0x1169989f8a342283L,0x8097799ca83012e6L,0xece966cb8a6a9001L, + 0x93b3afef072ac7fcL }, + { 0xe6893a2a2db3d5baL,0x263dc46289bf4fdcL,0x8852dfc9e0396673L, + 0x7ac708953af362b6L } }, + /* 62 << 245 */ + { { 0xbb9cce4d5c2f342bL,0xbf80907ab52d7aaeL,0x97f3d3cd2161bcd0L, + 0xb25b08340962744dL }, + { 0xc5b18ea56c3a1ddaL,0xfe4ec7eb06c92317L,0xb787b890ad1c4afeL, + 0xdccd9a920ede801aL } }, + /* 63 << 245 */ + { { 0x9ac6dddadb58da1fL,0x22bbc12fb8cae6eeL,0xc6f8bced815c4a43L, + 0x8105a92cf96480c7L }, + { 0x0dc3dbf37a859d51L,0xe3ec7ce63041196bL,0xd9f64b250d1067c9L, + 0xf23213213d1f8dd8L } }, + /* 64 << 245 */ + { { 0x8b5c619c76497ee8L,0x5d2b0ac6c717370eL,0x98204cb64fcf68e1L, + 0x0bdec21162bc6792L }, + { 0x6973ccefa63b1011L,0xf9e3fa97e0de1ac5L,0x5efb693e3d0e0c8bL, + 0x037248e9d2d4fcb4L } }, + /* 0 << 252 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 252 */ + { { 0x80802dc91ec34f9eL,0xd8772d3533810603L,0x3f06d66c530cb4f3L, + 0x7be5ed0dc475c129L }, + { 0xcb9e3c1931e82b10L,0xc63d2857c9ff6b4cL,0xb92118c692a1b45eL, + 0x0aec44147285bbcaL } }, + /* 2 << 252 */ + { { 0xfc189ae71e29a3efL,0xcbe906f04c93302eL,0xd0107914ceaae10eL, + 0xb7a23f34b68e19f8L }, + { 0xe9d875c2efd2119dL,0x03198c6efcadc9c8L,0x65591bf64da17113L, + 0x3cf0bbf83d443038L } }, + /* 3 << 252 */ + { { 0xae485bb72b724759L,0x945353e1b2d4c63aL,0x82159d07de7d6f2cL, + 0x389caef34ec5b109L }, + { 0x4a8ebb53db65ef14L,0x2dc2cb7edd99de43L,0x816fa3ed83f2405fL, + 0x73429bb9c14208a3L } }, + /* 4 << 252 */ + { { 0xb618d590b01e6e27L,0x047e2ccde180b2dcL,0xd1b299b504aea4a9L, + 0x412c9e1e9fa403a4L }, + { 0x88d28a3679407552L,0x49c50136f332b8e3L,0x3a1b6fcce668de19L, + 0x178851bc75122b97L } }, + /* 5 << 252 */ + { { 0xb1e13752fb85fa4cL,0xd61257ce383c8ce9L,0xd43da670d2f74daeL, + 0xa35aa23fbf846bbbL }, + { 0x5e74235d4421fc83L,0xf6df8ee0c363473bL,0x34d7f52a3c4aa158L, + 0x50d05aab9bc6d22eL } }, + /* 6 << 252 */ + { { 0x8c56e735a64785f4L,0xbc56637b5f29cd07L,0x53b2bb803ee35067L, + 0x50235a0fdc919270L }, + { 0x191ab6d8f2c4aa65L,0xc34758318396023bL,0x80400ba5f0f805baL, + 0x8881065b5ec0f80fL } }, + /* 7 << 252 */ + { { 0xc370e522cc1b5e83L,0xde2d4ad1860b8bfbL,0xad364df067b256dfL, + 0x8f12502ee0138997L }, + { 0x503fa0dc7783920aL,0xe80014adc0bc866aL,0x3f89b744d3064ba6L, + 0x03511dcdcba5dba5L } }, + /* 8 << 252 */ + { { 0x197dd46d95a7b1a2L,0x9c4e7ad63c6341fbL,0x426eca29484c2eceL, + 0x9211e489de7f4f8aL }, + { 0x14997f6ec78ef1f4L,0x2b2c091006574586L,0x17286a6e1c3eede8L, + 0x25f92e470f60e018L } }, + /* 9 << 252 */ + { { 0x805c564631890a36L,0x703ef60057feea5bL,0x389f747caf3c3030L, + 0xe0e5daeb54dd3739L }, + { 0xfe24a4c3c9c9f155L,0x7e4bf176b5393962L,0x37183de2af20bf29L, + 0x4a1bd7b5f95a8c3bL } }, + /* 10 << 252 */ + { { 0xa83b969946191d3dL,0x281fc8dd7b87f257L,0xb18e2c1354107588L, + 0x6372def79b2bafe8L }, + { 0xdaf4bb480d8972caL,0x3f2dd4b756167a3fL,0x1eace32d84310cf4L, + 0xe3bcefafe42700aaL } }, + /* 11 << 252 */ + { { 0x5fe5691ed785e73dL,0xa5db5ab62ea60467L,0x02e23d41dfc6514aL, + 0x35e8048ee03c3665L }, + { 0x3f8b118f1adaa0f8L,0x28ec3b4584ce1a5aL,0xe8cacc6e2c6646b8L, + 0x1343d185dbd0e40fL } }, + /* 12 << 252 */ + { { 0xe5d7f844caaa358cL,0x1a1db7e49924182aL,0xd64cd42d9c875d9aL, + 0xb37b515f042eeec8L }, + { 0x4d4dd4097b165fbeL,0xfc322ed9e206eff3L,0x7dee410259b7e17eL, + 0x55a481c08236ca00L } }, + /* 13 << 252 */ + { { 0x8c885312c23fc975L,0x1571580605d6297bL,0xa078868ef78edd39L, + 0x956b31e003c45e52L }, + { 0x470275d5ff7b33a6L,0xc8d5dc3a0c7e673fL,0x419227b47e2f2598L, + 0x8b37b6344c14a975L } }, + /* 14 << 252 */ + { { 0xd0667ed68b11888cL,0x5e0e8c3e803e25dcL,0x34e5d0dcb987a24aL, + 0x9f40ac3bae920323L }, + { 0x5463de9534e0f63aL,0xa128bf926b6328f9L,0x491ccd7cda64f1b7L, + 0x7ef1ec27c47bde35L } }, + /* 15 << 252 */ + { { 0xa857240fa36a2737L,0x35dc136663621bc1L,0x7a3a6453d4fb6897L, + 0x80f1a439c929319dL }, + { 0xfc18274bf8cb0ba0L,0xb0b537668078c5ebL,0xfb0d49241e01d0efL, + 0x50d7c67d372ab09cL } }, + /* 16 << 252 */ + { { 0xb4e370af3aeac968L,0xe4f7fee9c4b63266L,0xb4acd4c2e3ac5664L, + 0xf8910bd2ceb38cbfL }, + { 0x1c3ae50cc9c0726eL,0x15309569d97b40bfL,0x70884b7ffd5a5a1bL, + 0x3890896aef8314cdL } }, + /* 17 << 252 */ + { { 0x58e1515ca5618c93L,0xe665432b77d942d1L,0xb32181bfb6f767a8L, + 0x753794e83a604110L }, + { 0x09afeb7ce8c0dbccL,0x31e02613598673a3L,0x5d98e5577d46db00L, + 0xfc21fb8c9d985b28L } }, + /* 18 << 252 */ + { { 0xc9040116b0843e0bL,0x53b1b3a869b04531L,0xdd1649f085d7d830L, + 0xbb3bcc87cb7427e8L }, + { 0x77261100c93dce83L,0x7e79da61a1922a2aL,0x587a2b02f3149ce8L, + 0x147e1384de92ec83L } }, + /* 19 << 252 */ + { { 0x484c83d3af077f30L,0xea78f8440658b53aL,0x912076c2027aec53L, + 0xf34714e393c8177dL }, + { 0x37ef5d15c2376c84L,0x8315b6593d1aa783L,0x3a75c484ef852a90L, + 0x0ba0c58a16086bd4L } }, + /* 20 << 252 */ + { { 0x29688d7a529a6d48L,0x9c7f250dc2f19203L,0x123042fb682e2df9L, + 0x2b7587e7ad8121bcL }, + { 0x30fc0233e0182a65L,0xb82ecf87e3e1128aL,0x7168286193fb098fL, + 0x043e21ae85e9e6a7L } }, + /* 21 << 252 */ + { { 0xab5b49d666c834eaL,0x3be43e1847414287L,0xf40fb859219a2a47L, + 0x0e6559e9cc58df3cL }, + { 0xfe1dfe8e0c6615b4L,0x14abc8fd56459d70L,0x7be0fa8e05de0386L, + 0x8e63ef68e9035c7cL } }, + /* 22 << 252 */ + { { 0x116401b453b31e91L,0x0cba7ad44436b4d8L,0x9151f9a0107afd66L, + 0xafaca8d01f0ee4c4L }, + { 0x75fe5c1d9ee9761cL,0x3497a16bf0c0588fL,0x3ee2bebd0304804cL, + 0xa8fb9a60c2c990b9L } }, + /* 23 << 252 */ + { { 0xd14d32fe39251114L,0x36bf25bccac73366L,0xc9562c66dba7495cL, + 0x324d301b46ad348bL }, + { 0x9f46620cd670407eL,0x0ea8d4f1e3733a01L,0xd396d532b0c324e0L, + 0x5b211a0e03c317cdL } }, + /* 24 << 252 */ + { { 0x090d7d205ffe7b37L,0x3b7f3efb1747d2daL,0xa2cb525fb54fc519L, + 0x6e220932f66a971eL }, + { 0xddc160dfb486d440L,0x7fcfec463fe13465L,0x83da7e4e76e4c151L, + 0xd6fa48a1d8d302b5L } }, + /* 25 << 252 */ + { { 0xc6304f265872cd88L,0x806c1d3c278b90a1L,0x3553e725caf0bc1cL, + 0xff59e603bb9d8d5cL }, + { 0xa4550f327a0b85ddL,0xdec5720a93ecc217L,0x0b88b74169d62213L, + 0x7212f2455b365955L } }, + /* 26 << 252 */ + { { 0x20764111b5cae787L,0x13cb7f581dfd3124L,0x2dca77da1175aefbL, + 0xeb75466bffaae775L }, + { 0x74d76f3bdb6cff32L,0x7440f37a61fcda9aL,0x1bb3ac92b525028bL, + 0x20fbf8f7a1975f29L } }, + /* 27 << 252 */ + { { 0x982692e1df83097fL,0x28738f6c554b0800L,0xdc703717a2ce2f2fL, + 0x7913b93c40814194L }, + { 0x049245931fe89636L,0x7b98443ff78834a6L,0x11c6ab015114a5a1L, + 0x60deb383ffba5f4cL } }, + /* 28 << 252 */ + { { 0x4caa54c601a982e6L,0x1dd35e113491cd26L,0x973c315f7cbd6b05L, + 0xcab0077552494724L }, + { 0x04659b1f6565e15aL,0xbf30f5298c8fb026L,0xfc21641ba8a0de37L, + 0xe9c7a366fa5e5114L } }, + /* 29 << 252 */ + { { 0xdb849ca552f03ad8L,0xc7e8dbe9024e35c0L,0xa1a2bbaccfc3c789L, + 0xbf733e7d9c26f262L }, + { 0x882ffbf5b8444823L,0xb7224e886bf8483bL,0x53023b8b65bef640L, + 0xaabfec91d4d5f8cdL } }, + /* 30 << 252 */ + { { 0xa40e1510079ea1bdL,0x1ad9addcd05d5d26L,0xdb3f2eab13e68d4fL, + 0x1cff1ae2640f803fL }, + { 0xe0e7b749d4cee117L,0x8e9f275b4036d909L,0xce34e31d8f4d4c38L, + 0x22b37f69d75130fcL } }, + /* 31 << 252 */ + { { 0x83e0f1fdb4014604L,0xa8ce991989415078L,0x82375b7541792efeL, + 0x4f59bf5c97d4515bL }, + { 0xac4f324f923a277dL,0xd9bc9b7d650f3406L,0xc6fa87d18a39bc51L, + 0x825885305ccc108fL } }, + /* 32 << 252 */ + { { 0x5ced3c9f82e4c634L,0x8efb83143a4464f8L,0xe706381b7a1dca25L, + 0x6cd15a3c5a2a412bL }, + { 0x9347a8fdbfcd8fb5L,0x31db2eef6e54cd22L,0xc4aeb11ef8d8932fL, + 0x11e7c1ed344411afL } }, + /* 33 << 252 */ + { { 0x2653050cdc9a151eL,0x9edbfc083bb0a859L,0x926c81c7fd5691e7L, + 0x9c1b23426f39019aL }, + { 0x64a81c8b7f8474b9L,0x90657c0701761819L,0x390b333155e0375aL, + 0xc676c626b6ebc47dL } }, + /* 34 << 252 */ + { { 0x51623247b7d6dee8L,0x0948d92779659313L,0x99700161e9ab35edL, + 0x06cc32b48ddde408L }, + { 0x6f2fd664061ef338L,0x1606fa02c202e9edL,0x55388bc1929ba99bL, + 0xc4428c5e1e81df69L } }, + /* 35 << 252 */ + { { 0xce2028aef91b0b2aL,0xce870a23f03dfd3fL,0x66ec2c870affe8edL, + 0xb205fb46284d0c00L }, + { 0xbf5dffe744cefa48L,0xb6fc37a8a19876d7L,0xbecfa84c08b72863L, + 0xd7205ff52576374fL } }, + /* 36 << 252 */ + { { 0x80330d328887de41L,0x5de0df0c869ea534L,0x13f427533c56ea17L, + 0xeb1f6069452b1a78L }, + { 0x50474396e30ea15cL,0x575816a1c1494125L,0xbe1ce55bfe6bb38fL, + 0xb901a94896ae30f7L } }, + /* 37 << 252 */ + { { 0xe5af0f08d8fc3548L,0x5010b5d0d73bfd08L,0x993d288053fe655aL, + 0x99f2630b1c1309fdL }, + { 0xd8677bafb4e3b76fL,0x14e51ddcb840784bL,0x326c750cbf0092ceL, + 0xc83d306bf528320fL } }, + /* 38 << 252 */ + { { 0xc445671577d4715cL,0xd30019f96b703235L,0x207ccb2ed669e986L, + 0x57c824aff6dbfc28L }, + { 0xf0eb532fd8f92a23L,0x4a557fd49bb98fd2L,0xa57acea7c1e6199aL, + 0x0c6638208b94b1edL } }, + /* 39 << 252 */ + { { 0x9b42be8ff83a9266L,0xc7741c970101bd45L,0x95770c1107bd9cebL, + 0x1f50250a8b2e0744L }, + { 0xf762eec81477b654L,0xc65b900e15efe59aL,0x88c961489546a897L, + 0x7e8025b3c30b4d7cL } }, + /* 40 << 252 */ + { { 0xae4065ef12045cf9L,0x6fcb2caf9ccce8bdL,0x1fa0ba4ef2cf6525L, + 0xf683125dcb72c312L }, + { 0xa01da4eae312410eL,0x67e286776cd8e830L,0xabd9575298fb3f07L, + 0x05f11e11eef649a5L } }, + /* 41 << 252 */ + { { 0xba47faef9d3472c2L,0x3adff697c77d1345L,0x4761fa04dd15afeeL, + 0x64f1f61ab9e69462L }, + { 0xfa691fab9bfb9093L,0x3df8ae8fa1133dfeL,0xcd5f896758cc710dL, + 0xfbb88d5016c7fe79L } }, + /* 42 << 252 */ + { { 0x8e011b4ce88c50d1L,0x7532e807a8771c4fL,0x64c78a48e2278ee4L, + 0x0b283e833845072aL }, + { 0x98a6f29149e69274L,0xb96e96681868b21cL,0x38f0adc2b1a8908eL, + 0x90afcff71feb829dL } }, + /* 43 << 252 */ + { { 0x9915a383210b0856L,0xa5a80602def04889L,0x800e9af97c64d509L, + 0x81382d0bb8996f6fL }, + { 0x490eba5381927e27L,0x46c63b324af50182L,0x784c5fd9d3ad62ceL, + 0xe4fa1870f8ae8736L } }, + /* 44 << 252 */ + { { 0x4ec9d0bcd7466b25L,0x84ddbe1adb235c65L,0x5e2645ee163c1688L, + 0x570bd00e00eba747L }, + { 0xfa51b629128bfa0fL,0x92fce1bd6c1d3b68L,0x3e7361dcb66778b1L, + 0x9c7d249d5561d2bbL } }, + /* 45 << 252 */ + { { 0xa40b28bf0bbc6229L,0x1c83c05edfd91497L,0x5f9f5154f083df05L, + 0xbac38b3ceee66c9dL }, + { 0xf71db7e3ec0dfcfdL,0xf2ecda8e8b0a8416L,0x52fddd867812aa66L, + 0x2896ef104e6f4272L } }, + /* 46 << 252 */ + { { 0xff27186a0fe9a745L,0x08249fcd49ca70dbL,0x7425a2e6441cac49L, + 0xf4a0885aece5ff57L }, + { 0x6e2cb7317d7ead58L,0xf96cf7d61898d104L,0xafe67c9d4f2c9a89L, + 0x89895a501c7bf5bcL } }, + /* 47 << 252 */ + { { 0xdc7cb8e5573cecfaL,0x66497eaed15f03e6L,0x6bc0de693f084420L, + 0x323b9b36acd532b0L }, + { 0xcfed390a0115a3c1L,0x9414c40b2d65ca0eL,0x641406bd2f530c78L, + 0x29369a44833438f2L } }, + /* 48 << 252 */ + { { 0x996884f5903fa271L,0xe6da0fd2b9da921eL,0xa6f2f2695db01e54L, + 0x1ee3e9bd6876214eL }, + { 0xa26e181ce27a9497L,0x36d254e48e215e04L,0x42f32a6c252cabcaL, + 0x9948148780b57614L } }, + /* 49 << 252 */ + { { 0x4c4dfe6940d9cae1L,0x0586958011a10f09L,0xca287b573491b64bL, + 0x77862d5d3fd4a53bL }, + { 0xbf94856e50349126L,0x2be30bd171c5268fL,0x10393f19cbb650a6L, + 0x639531fe778cf9fdL } }, + /* 50 << 252 */ + { { 0x02556a11b2935359L,0xda38aa96af8c126eL,0x47dbe6c20960167fL, + 0x37bbabb6501901cdL }, + { 0xb6e979e02c947778L,0xd69a51757a1a1dc6L,0xc3ed50959d9faf0cL, + 0x4dd9c0961d5fa5f0L } }, + /* 51 << 252 */ + { { 0xa0c4304d64f16ea8L,0x8b1cac167e718623L,0x0b5765467c67f03eL, + 0x559cf5adcbd88c01L }, + { 0x074877bb0e2af19aL,0x1f717ec1a1228c92L,0x70bcb800326e8920L, + 0xec6e2c5c4f312804L } }, + /* 52 << 252 */ + { { 0x426aea7d3fca4752L,0xf12c09492211f62aL,0x24beecd87be7b6b5L, + 0xb77eaf4c36d7a27dL }, + { 0x154c2781fda78fd3L,0x848a83b0264eeabeL,0x81287ef04ffe2bc4L, + 0x7b6d88c6b6b6fc2aL } }, + /* 53 << 252 */ + { { 0x805fb947ce417d99L,0x4b93dcc38b916cc4L,0x72e65bb321273323L, + 0xbcc1badd6ea9886eL }, + { 0x0e2230114bc5ee85L,0xa561be74c18ee1e4L,0x762fd2d4a6bcf1f1L, + 0x50e6a5a495231489L } }, + /* 54 << 252 */ + { { 0xca96001fa00b500bL,0x5c098cfc5d7dcdf5L,0xa64e2d2e8c446a85L, + 0xbae9bcf1971f3c62L }, + { 0x4ec226838435a2c5L,0x8ceaed6c4bad4643L,0xe9f8fb47ccccf4e3L, + 0xbd4f3fa41ce3b21eL } }, + /* 55 << 252 */ + { { 0xd79fb110a3db3292L,0xe28a37dab536c66aL,0x279ce87b8e49e6a9L, + 0x70ccfe8dfdcec8e3L }, + { 0x2193e4e03ba464b2L,0x0f39d60eaca9a398L,0x7d7932aff82c12abL, + 0xd8ff50ed91e7e0f7L } }, + /* 56 << 252 */ + { { 0xea961058fa28a7e0L,0xc726cf250bf5ec74L,0xe74d55c8db229666L, + 0x0bd9abbfa57f5799L }, + { 0x7479ef074dfc47b3L,0xd9c65fc30c52f91dL,0x8e0283fe36a8bde2L, + 0xa32a8b5e7d4b7280L } }, + /* 57 << 252 */ + { { 0x6a677c6112e83233L,0x0fbb3512dcc9bf28L,0x562e8ea50d780f61L, + 0x0db8b22b1dc4e89cL }, + { 0x0a6fd1fb89be0144L,0x8c77d246ca57113bL,0x4639075dff09c91cL, + 0x5b47b17f5060824cL } }, + /* 58 << 252 */ + { { 0x58aea2b016287b52L,0xa1343520d0cd8eb0L,0x6148b4d0c5d58573L, + 0xdd2b6170291c68aeL }, + { 0xa61b39291da3b3b7L,0x5f946d7908c4ac10L,0x4105d4a57217d583L, + 0x5061da3d25e6de5eL } }, + /* 59 << 252 */ + { { 0x3113940dec1b4991L,0xf12195e136f485aeL,0xa7507fb2731a2ee0L, + 0x95057a8e6e9e196eL }, + { 0xa3c2c9112e130136L,0x97dfbb3633c60d15L,0xcaf3c581b300ee2bL, + 0x77f25d90f4bac8b8L } }, + /* 60 << 252 */ + { { 0xdb1c4f986d840cd6L,0x471d62c0e634288cL,0x8ec2f85ecec8a161L, + 0x41f37cbcfa6f4ae2L }, + { 0x6793a20f4b709985L,0x7a7bd33befa8985bL,0x2c6a3fbd938e6446L, + 0x190426192a8d47c1L } }, + /* 61 << 252 */ + { { 0x16848667cc36975fL,0x02acf1689d5f1dfbL,0x62d41ad4613baa94L, + 0xb56fbb929f684670L }, + { 0xce610d0de9e40569L,0x7b99c65f35489fefL,0x0c88ad1b3df18b97L, + 0x81b7d9be5d0e9edbL } }, + /* 62 << 252 */ + { { 0xd85218c0c716cc0aL,0xf4b5ff9085691c49L,0xa4fd666bce356ac6L, + 0x17c728954b327a7aL }, + { 0xf93d5085da6be7deL,0xff71530e3301d34eL,0x4cd96442d8f448e8L, + 0x9283d3312ed18ffaL } }, + /* 63 << 252 */ + { { 0x4d33dd992a849870L,0xa716964b41576335L,0xff5e3a9b179be0e5L, + 0x5b9d6b1b83b13632L }, + { 0x3b8bd7d4a52f313bL,0xc9dd95a0637a4660L,0x300359620b3e218fL, + 0xce1481a3c7b28a3cL } }, + /* 64 << 252 */ + { { 0xab41b43a43228d83L,0x24ae1c304ad63f99L,0x8e525f1a46a51229L, + 0x14af860fcd26d2b4L }, + { 0xd6baef613f714aa1L,0xf51865adeb78795eL,0xd3e21fcee6a9d694L, + 0x82ceb1dd8a37b527L } }, +}; + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_add_only_4(sp_point_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit tmpd[2 * 4 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_256 v[37]; + int err; + + (void)g; + (void)heap; + + err = sp_256_point_new_4(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_256_point_new_4(heap, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + tmp = tmpd; +#endif + negy = tmp; + + if (err == MP_OKAY) { + sp_256_ecc_recode_7_4(k, v); + + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + i = 36; + XMEMCPY(rt->x, table[i * 65 + v[i].i].x, sizeof(table->x)); + XMEMCPY(rt->y, table[i * 65 + v[i].i].y, sizeof(table->y)); + rt->infinity = !v[i].i; + for (--i; i>=0; i--) { + XMEMCPY(p->x, table[i * 65 + v[i].i].x, sizeof(table->x)); + XMEMCPY(p->y, table[i * 65 + v[i].i].y, sizeof(table->y)); + p->infinity = !v[i].i; + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, 0 - v[i].neg); + sp_256_proj_point_add_qz1_4(rt, rt, p, tmp); + } + if (map != 0) { + sp_256_map_4(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmp, sizeof(sp_digit) * 2 * 4 * 5); +#endif + sp_256_point_free_4(p, 0, heap); + sp_256_point_free_4(rt, 0, heap); + + return MP_OKAY; +} + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_add_only_4(r, NULL, p256_table, + k, map, heap); +} + +#endif /* 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 coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[4]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_256_point_new_4(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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); + + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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 || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +static void sp_256_add_one_4(sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x1, x2, [%[a], 0]\n\t" + "adds x1, x1, #1\n\t" + "ldr x3, [%[a], 16]\n\t" + "adcs x2, x2, xzr\n\t" + "ldr x4, [%[a], 24]\n\t" + "adcs x3, x3, xzr\n\t" + "stp x1, x2, [%[a], 0]\n\t" + "adcs x4, x4, xzr\n\t" + "stp x3, x4, [%[a], 16]\n\t" + : + : [a] "r" (a) + : "memory", "x1", "x2", "x3", "x4" + ); +} + +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j; + byte* d; + + for (i = n - 1,j = 0; i >= 7; i -= 8) { + r[j] = ((sp_digit)a[i - 0] << 0) | + ((sp_digit)a[i - 1] << 8) | + ((sp_digit)a[i - 2] << 16) | + ((sp_digit)a[i - 3] << 24) | + ((sp_digit)a[i - 4] << 32) | + ((sp_digit)a[i - 5] << 40) | + ((sp_digit)a[i - 6] << 48) | + ((sp_digit)a[i - 7] << 56); + j++; + } + + if (i >= 0) { + r[j] = 0; + + d = (byte*)r; + switch (i) { + case 6: d[n - 1 - 6] = a[6]; //fallthrough + case 5: d[n - 1 - 5] = a[5]; //fallthrough + case 4: d[n - 1 - 4] = a[4]; //fallthrough + case 3: d[n - 1 - 3] = a[3]; //fallthrough + case 2: d[n - 1 - 2] = a[2]; //fallthrough + case 1: d[n - 1 - 1] = a[1]; //fallthrough + case 0: d[n - 1 - 0] = a[0]; //fallthrough + } + j++; + } + + for (; j < size; 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, (int)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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[4]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 inf; +#endif +#endif + sp_point_256* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity; +#endif + int err; + + (void)heap; + + err = sp_256_point_new_4(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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) { + err = sp_256_ecc_mulmod_base_4(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_4(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_256_iszero_4(point->x) == 0) || (sp_256_iszero_4(point->y) == 0)) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_256_point_free_4(infinity, 1, heap); +#endif + sp_256_point_free_4(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte array. + * 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; + + for (i = 3, j = 0; i >= 0; i--) { + a[j++] = r[i] >> 56; + a[j++] = r[i] >> 48; + a[j++] = r[i] >> 40; + a[j++] = r[i] >> 32; + a[j++] = r[i] >> 24; + a[j++] = r[i] >> 16; + a[j++] = r[i] >> 8; + a[j++] = r[i] >> 0; + } +} + +/* 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[4]; +#endif + sp_point_256* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 32U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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); + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(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) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#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_4(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[8]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 24\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 32\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 48\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#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_4(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[4]; + + __asm__ __volatile__ ( + "ldp x16, x17, [%[a], 0]\n\t" + "ldp x21, x22, [%[b], 0]\n\t" + "# A[0] * B[0]\n\t" + "mul x8, x16, x21\n\t" + "ldr x19, [%[a], 16]\n\t" + "umulh x9, x16, x21\n\t" + "ldr x23, [%[b], 16]\n\t" + "# A[0] * B[1]\n\t" + "mul x4, x16, x22\n\t" + "ldr x20, [%[a], 24]\n\t" + "umulh x5, x16, x22\n\t" + "ldr x24, [%[b], 24]\n\t" + "adds x9, x9, x4\n\t" + "# A[1] * B[0]\n\t" + "mul x4, x17, x21\n\t" + "adc x10, xzr, x5\n\t" + "umulh x5, x17, x21\n\t" + "adds x9, x9, x4\n\t" + "# A[0] * B[2]\n\t" + "mul x4, x16, x23\n\t" + "adcs x10, x10, x5\n\t" + "umulh x5, x16, x23\n\t" + "adc x11, xzr, xzr\n\t" + "adds x10, x10, x4\n\t" + "# A[1] * B[1]\n\t" + "mul x4, x17, x22\n\t" + "adc x11, x11, x5\n\t" + "umulh x5, x17, x22\n\t" + "adds x10, x10, x4\n\t" + "# A[2] * B[0]\n\t" + "mul x4, x19, x21\n\t" + "adcs x11, x11, x5\n\t" + "umulh x5, x19, x21\n\t" + "adc x12, xzr, xzr\n\t" + "adds x10, x10, x4\n\t" + "# A[0] * B[3]\n\t" + "mul x4, x16, x24\n\t" + "adcs x11, x11, x5\n\t" + "umulh x5, x16, x24\n\t" + "adc x12, x12, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * B[2]\n\t" + "mul x4, x17, x23\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x17, x23\n\t" + "adc x13, xzr, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[2] * B[1]\n\t" + "mul x4, x19, x22\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x19, x22\n\t" + "adc x13, x13, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[3] * B[0]\n\t" + "mul x4, x20, x21\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x20, x21\n\t" + "adc x13, x13, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * B[3]\n\t" + "mul x4, x17, x24\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x17, x24\n\t" + "adc x13, x13, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[2] * B[2]\n\t" + "mul x4, x19, x23\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x19, x23\n\t" + "adc x14, xzr, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[3] * B[1]\n\t" + "mul x4, x20, x22\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x20, x22\n\t" + "adc x14, x14, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[2] * B[3]\n\t" + "mul x4, x19, x24\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x19, x24\n\t" + "adc x14, x14, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[3] * B[2]\n\t" + "mul x4, x20, x23\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x20, x23\n\t" + "adc x15, xzr, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[3] * B[3]\n\t" + "mul x4, x20, x24\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x20, x24\n\t" + "adc x15, x15, xzr\n\t" + "adds x14, x14, x4\n\t" + "adc x15, x15, x5\n\t" + "stp x8, x9, [%[r], 0]\n\t" + "stp x10, x11, [%[r], 16]\n\t" + "stp x12, x13, [%[r], 32]\n\t" + "stp x14, x15, [%[r], 48]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "x4", "x5", "x6", "x7", "x16", "x17", "x19", "x20", "x21", "x22", "x23", "x24", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#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) +{ + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "subs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "csetm %[a], cc\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return (sp_digit)a; +} + +/* 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, + sp_digit b) +{ + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldp x2, x3, [%[a]]\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "umulh x7, %[b], x2\n\t" + "mul x2, %[b], x2\n\t" + "# A[1] * B\n\t" + "mul x8, %[b], x3\n\t" + "umulh x9, %[b], x3\n\t" + "adds x3, x7, x8\n\t" + "# A[2] * B\n\t" + "mul x8, %[b], x4\n\t" + "adc x7, xzr, x9\n\t" + "umulh x9, %[b], x4\n\t" + "adds x4, x7, x8\n\t" + "# A[3] * B\n\t" + "mul x8, %[b], x5\n\t" + "adc x7, xzr, x9\n\t" + "umulh x9, %[b], x5\n\t" + "adds x5, x7, x8\n\t" + "str x2, [%[r]]\n\t" + "adc x6, xzr, x9\n\t" + "stp x3, x4, [%[r], 8]\n\t" + "stp x5, x6, [%[r], 24]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +} + +/* 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__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "sub %[d0], %[d0], x4\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add %[r], x6, x3\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + 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, const 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 WC_INLINE int sp_256_div_4(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[8], t2[5]; + sp_digit div, r1; + int i; + + (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); + + 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, d, (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 WC_INLINE int sp_256_mod_4(sp_digit* r, const sp_digit* a, const 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) +{ + __asm__ __volatile__ ( + "ldp x16, x17, [%[a], 0]\n\t" + "# A[0] * A[1]\n\t" + "mul x9, x16, x17\n\t" + "ldr x19, [%[a], 16]\n\t" + "umulh x10, x16, x17\n\t" + "ldr x20, [%[a], 24]\n\t" + "# A[0] * A[2]\n\t" + "mul x4, x16, x19\n\t" + "umulh x5, x16, x19\n\t" + "adds x10, x10, x4\n\t" + "# A[0] * A[3]\n\t" + "mul x4, x16, x20\n\t" + "adc x11, xzr, x5\n\t" + "umulh x5, x16, x20\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * A[2]\n\t" + "mul x4, x17, x19\n\t" + "adc x12, xzr, x5\n\t" + "umulh x5, x17, x19\n\t" + "adds x11, x11, x4\n\t" + "# A[1] * A[3]\n\t" + "mul x4, x17, x20\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x17, x20\n\t" + "adc x13, xzr, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[2] * A[3]\n\t" + "mul x4, x19, x20\n\t" + "adc x13, x13, x5\n\t" + "umulh x5, x19, x20\n\t" + "adds x13, x13, x4\n\t" + "adc x14, xzr, x5\n\t" + "# Double\n\t" + "adds x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adcs x11, x11, x11\n\t" + "adcs x12, x12, x12\n\t" + "adcs x13, x13, x13\n\t" + "# A[0] * A[0]\n\t" + "mul x8, x16, x16\n\t" + "adcs x14, x14, x14\n\t" + "umulh x3, x16, x16\n\t" + "cset x15, cs\n\t" + "# A[1] * A[1]\n\t" + "mul x4, x17, x17\n\t" + "adds x9, x9, x3\n\t" + "umulh x5, x17, x17\n\t" + "adcs x10, x10, x4\n\t" + "# A[2] * A[2]\n\t" + "mul x6, x19, x19\n\t" + "adcs x11, x11, x5\n\t" + "umulh x7, x19, x19\n\t" + "adcs x12, x12, x6\n\t" + "# A[3] * A[3]\n\t" + "mul x16, x20, x20\n\t" + "adcs x13, x13, x7\n\t" + "umulh x17, x20, x20\n\t" + "adcs x14, x14, x16\n\t" + "adc x15, x15, x17\n\t" + "stp x8, x9, [%[r], 0]\n\t" + "stp x10, x11, [%[r], 16]\n\t" + "stp x12, x13, [%[r], 32]\n\t" + "stp x14, x15, [%[r], 48]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20" + ); +} + +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint64_t p256_order_minus_2[4] = { + 0xf3b9cac2fc63254fU,0xbce6faada7179e84U,0xffffffffffffffffU, + 0xffffffff00000000U +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint64_t p256_order_low[2] = { + 0xf3b9cac2fc63254fU,0xbce6faada7179e84U +}; +#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, const sp_digit* a, const sp_digit* b) +{ + sp_256_mul_4(r, a, b); + sp_256_mont_reduce_order_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, const sp_digit* a) +{ + sp_256_sqr_4(r, a); + sp_256_mont_reduce_order_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, const 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_minus_2[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + sp_256_mont_mul_order_4(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 4U); +#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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 */ +} + +#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, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#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_256 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_256* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int64_t c; + int i; + + (void)heap; + + err = sp_256_point_new_4(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 4; + x = d + 2 * 4; + k = d + 4 * 4; + r = d + 6 * 4; + tmp = d + 8 * 4; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(e, 4, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 4, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_4(rng, k); + } + else { + sp_256_from_mp(k, 4, km); + mp_zero(km); + } + if (err == MP_OKAY) { + 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) * 4U); + sp_256_norm_4(r); + c = sp_256_cmp_4(r, p256_order); + sp_256_cond_sub_4(r, r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_4(r); + + /* Conv k to Montgomery form (mod order) */ + 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 */ + sp_256_mont_inv_order_4(kInv, k, tmp); + sp_256_norm_4(kInv); + + /* s = r * x + e */ + 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, 0L - (sp_digit)(c >= 0)); + sp_256_norm_4(s); + + /* s = s * k^-1 mod order */ + 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) == 0) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 4); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 4U); +#endif + sp_256_point_free_4(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_256 p1d; + sp_point_256 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p1; + sp_point_256* p2 = NULL; + sp_digit carry; + int64_t c; + int err; + + err = sp_256_point_new_4(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 4; + u2 = d + 2 * 4; + s = d + 4 * 4; + tmp = d + 6 * 4; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 4, hash, (int)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); + + { + 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); + { + 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); + } + + err = sp_256_ecc_mulmod_base_4(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_4(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + { + sp_256_proj_point_add_4(p1, p1, p2, tmp); + if (sp_256_iszero_4(p1->z)) { + if (sp_256_iszero_4(p1->x) && sp_256_iszero_4(p1->y)) { + sp_256_proj_point_dbl_4(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + } + + /* (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 = (int)(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 == 0) { + 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 = (int)(sp_256_cmp_4(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_256_point_free_4(p1, 0, heap); + sp_256_point_free_4(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_4(sp_point_256* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*4]; + sp_digit t2d[2*4]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 4; + t2 = d + 2 * 4; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_256_sqr_4(t1, point->y); + (void)sp_256_mod_4(t1, t1, p256_mod); + sp_256_sqr_4(t2, point->x); + (void)sp_256_mod_4(t2, t2, p256_mod); + sp_256_mul_4(t2, t2, point->x); + (void)sp_256_mod_4(t2, t2, p256_mod); + (void)sp_256_sub_4(t2, p256_mod, t2); + sp_256_mont_add_4(t1, t1, t2, p256_mod); + + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_4(t1, p256_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 pubd; +#endif + sp_point_256* pub; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_4(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 4, pX); + sp_256_from_mp(pub->y, 4, pY); + sp_256_from_bin(pub->z, 4, one, (int)sizeof(one)); + + err = sp_256_ecc_is_point_4(pub, NULL); + } + + sp_256_point_free_4(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[4]; + sp_point_256 pubd; + sp_point_256 pd; +#endif + sp_digit* priv = NULL; + sp_point_256* pub; + sp_point_256* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_4(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_256_from_mp(pub->x, 4, pX); + sp_256_from_mp(pub->y, 4, pY); + sp_256_from_bin(pub->z, 4, one, (int)sizeof(one)); + sp_256_from_mp(priv, 4, privm); + + /* Check point at infinitiy. */ + if ((sp_256_iszero_4(pub->x) != 0) && + (sp_256_iszero_4(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_4(pub->x, p256_mod) >= 0 || + sp_256_cmp_4(pub->y, p256_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_4(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_256_ecc_mulmod_4(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_256_iszero_4(p->x) == 0) || + (sp_256_iszero_4(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_256_ecc_mulmod_base_4(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_4(p->x, pub->x) != 0 || + sp_256_cmp_4(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(p, 0, heap); + sp_256_point_free_4(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 4 * 5]; + sp_point_256 pd; + sp_point_256 qd; +#endif + sp_digit* tmp; + sp_point_256* p; + sp_point_256* q = NULL; + int err; + + err = sp_256_point_new_4(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_256_point_new_4(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + sp_256_from_mp(q->x, 4, qX); + sp_256_from_mp(q->y, 4, qY); + sp_256_from_mp(q->z, 4, qZ); + + sp_256_proj_point_add_4(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(q, 0, NULL); + sp_256_point_free_4(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 4 * 2]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_4(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + + sp_256_proj_point_dbl_4(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 4 * 4]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_4(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + + sp_256_map_4(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_4(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 4]; + sp_digit t2d[2 * 4]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 4; + t2 = d + 2 * 4; +#else + t1 = t1d; + t2 = t2d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_4(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_4(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_4(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_4(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_4(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_4(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_4(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_4(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 4]; + sp_digit yd[2 * 4]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 4; + y = d + 2 * 4; +#else + x = xd; + y = yd; +#endif + + sp_256_from_mp(x, 4, xm); + err = sp_256_mod_mul_norm_4(x, x, p256_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_4(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_4(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_4(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_4(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 4, 0, 4U * sizeof(sp_digit)); + sp_256_mont_reduce_4(y, p256_mod, p256_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_256_mont_sub_4(y, p256_mod, y, p256_mod); + } + + err = sp_256_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#ifdef WOLFSSL_SP_384 + +/* Point structure to use. */ +typedef struct sp_point_384 { + sp_digit x[2 * 6]; + sp_digit y[2 * 6]; + sp_digit z[2 * 6]; + int infinity; +} sp_point_384; + +/* The modulus (prime) of the curve P384. */ +static const sp_digit p384_mod[6] = { + 0x00000000ffffffffL,0xffffffff00000000L,0xfffffffffffffffeL, + 0xffffffffffffffffL,0xffffffffffffffffL,0xffffffffffffffffL +}; +/* The Montogmery normalizer for modulus of the curve P384. */ +static const sp_digit p384_norm_mod[6] = { + 0xffffffff00000001L,0x00000000ffffffffL,0x0000000000000001L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L +}; +/* The Montogmery multiplier for modulus of the curve P384. */ +static sp_digit p384_mp_mod = 0x0000000100000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P384. */ +static const sp_digit p384_order[6] = { + 0xecec196accc52973L,0x581a0db248b0a77aL,0xc7634d81f4372ddfL, + 0xffffffffffffffffL,0xffffffffffffffffL,0xffffffffffffffffL +}; +#endif +/* The order of the curve P384 minus 2. */ +static const sp_digit p384_order2[6] = { + 0xecec196accc52971L,0x581a0db248b0a77aL,0xc7634d81f4372ddfL, + 0xffffffffffffffffL,0xffffffffffffffffL,0xffffffffffffffffL +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P384. */ +static const sp_digit p384_norm_order[6] = { + 0x1313e695333ad68dL,0xa7e5f24db74f5885L,0x389cb27e0bc8d220L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P384. */ +static sp_digit p384_mp_order = 0x6ed46089e88fdc45l; +#endif +/* The base point of curve P384. */ +static const sp_point_384 p384_base = { + /* X ordinate */ + { + 0x3a545e3872760ab7L,0x5502f25dbf55296cL,0x59f741e082542a38L, + 0x6e1d3b628ba79b98L,0x8eb1c71ef320ad74L,0xaa87ca22be8b0537L, + 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x7a431d7c90ea0e5fL,0x0a60b1ce1d7e819dL,0xe9da3113b5f0b8c0L, + 0xf8f41dbd289a147cL,0x5d9e98bf9292dc29L,0x3617de4a96262c6fL, + 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x0000000000000001L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L, + 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p384_b[6] = { + 0x2a85c8edd3ec2aefL,0xc656398d8a2ed19dL,0x0314088f5013875aL, + 0x181d9c6efe814112L,0x988e056be3f82d19L,0xb3312fa7e23ee7e4L +}; +#endif + +static int sp_384_point_new_ex_6(void* heap, sp_point_384* sp, sp_point_384** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_384_point_new_6(heap, sp, p) sp_384_point_new_ex_6((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_384_point_new_6(heap, sp, p) sp_384_point_new_ex_6((heap), &(sp), &(p)) +#endif + + +static void sp_384_point_free_6(sp_point_384* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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_384_mod_mul_norm_6(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* td; +#else + int64_t td[12]; + int64_t a32d[12]; +#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)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + a32 = td + 12; +#else + t = td; + a32 = a32d; +#endif + + 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; + a32[8] = a[4] & 0xffffffff; + a32[9] = a[4] >> 32; + a32[10] = a[5] & 0xffffffff; + a32[11] = a[5] >> 32; + + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + a32[0] + a32[8] + a32[9] - a32[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - a32[0] + a32[1] - a32[8] + a32[10] + a32[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - a32[1] + a32[2] - a32[9] + a32[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + a32[0] - a32[2] + a32[3] + a32[8] + a32[9] - a32[10] - a32[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + a32[0] + a32[1] - a32[3] + a32[4] + a32[8] + 2 * a32[9] + a32[10] - 2 * a32[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + a32[1] + a32[2] - a32[4] + a32[5] + a32[9] + 2 * a32[10] + a32[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + a32[2] + a32[3] - a32[5] + a32[6] + a32[10] + 2 * a32[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + a32[3] + a32[4] - a32[6] + a32[7] + a32[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + a32[4] + a32[5] - a32[7] + a32[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + a32[5] + a32[6] - a32[8] + a32[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + a32[6] + a32[7] - a32[9] + a32[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + a32[7] + a32[8] - a32[10] + a32[11]; + + 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 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]; + r[4] = (t[9] << 32) | t[8]; + r[5] = (t[11] << 32) | t[10]; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_6(sp_point_384* p, const 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_384_from_mp(p->x, 6, pm->x); + sp_384_from_mp(p->y, 6, pm->y); + sp_384_from_mp(p->z, 6, 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_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 6); + r->used = 6; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 6; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 64 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 6; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && 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 = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_6(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + +/* Conditionally copy a into r 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_384_cond_copy_6(sp_digit* r, const sp_digit* a, sp_digit m) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[r], 0]\n\t" + "ldp x5, x6, [%[r], 16]\n\t" + "ldp x7, x8, [%[r], 32]\n\t" + "ldp x9, x10, [%[a], 0]\n\t" + "ldp x11, x12, [%[a], 16]\n\t" + "ldp x13, x14, [%[a], 32]\n\t" + "eor x9, x9, x3\n\t" + "eor x10, x10, x4\n\t" + "eor x11, x11, x5\n\t" + "eor x12, x12, x6\n\t" + "eor x13, x13, x7\n\t" + "eor x14, x14, x8\n\t" + "and x9, x9, %[m]\n\t" + "and x10, x10, %[m]\n\t" + "and x11, x11, %[m]\n\t" + "and x12, x12, %[m]\n\t" + "and x13, x13, %[m]\n\t" + "and x14, x14, %[m]\n\t" + "eor x3, x3, x9\n\t" + "eor x4, x4, x10\n\t" + "eor x5, x5, x11\n\t" + "eor x6, x6, x12\n\t" + "eor x7, x7, x13\n\t" + "eor x8, x8, x14\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "stp x7, x8, [%[r], 32]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14" + ); +} + +#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_384_mul_6(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[12]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 40\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 48\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 80\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#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_384_mul_6(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[6]; + + __asm__ __volatile__ ( + "ldp x9, x10, [%[a], 0]\n\t" + "ldp x11, x12, [%[a], 16]\n\t" + "ldp x13, x14, [%[a], 32]\n\t" + "ldp x15, x16, [%[b], 0]\n\t" + "ldp x17, x19, [%[b], 16]\n\t" + "ldp x20, x21, [%[b], 32]\n\t" + "# A[0] * B[0]\n\t" + "mul x4, x9, x15\n\t" + "umulh x5, x9, x15\n\t" + "str x4, [%[tmp]]\n\t" + "# A[0] * B[1]\n\t" + "mul x7, x9, x16\n\t" + "umulh x8, x9, x16\n\t" + "adds x5, x5, x7\n\t" + "# A[1] * B[0]\n\t" + "mul x7, x10, x15\n\t" + "adc x6, xzr, x8\n\t" + "umulh x8, x10, x15\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[tmp], 8]\n\t" + "adc x4, xzr, xzr\n\t" + "# A[0] * B[2]\n\t" + "mul x7, x9, x17\n\t" + "umulh x8, x9, x17\n\t" + "adds x6, x6, x7\n\t" + "# A[1] * B[1]\n\t" + "mul x7, x10, x16\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x10, x16\n\t" + "adc x5, xzr, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[2] * B[0]\n\t" + "mul x7, x11, x15\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x11, x15\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[tmp], 16]\n\t" + "adc x5, x5, xzr\n\t" + "# A[0] * B[3]\n\t" + "mul x7, x9, x19\n\t" + "umulh x8, x9, x19\n\t" + "adds x4, x4, x7\n\t" + "# A[1] * B[2]\n\t" + "mul x7, x10, x17\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x10, x17\n\t" + "adc x6, xzr, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[2] * B[1]\n\t" + "mul x7, x11, x16\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x11, x16\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[3] * B[0]\n\t" + "mul x7, x12, x15\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x12, x15\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[tmp], 24]\n\t" + "adc x6, x6, xzr\n\t" + "# A[0] * B[4]\n\t" + "mul x7, x9, x20\n\t" + "umulh x8, x9, x20\n\t" + "adds x5, x5, x7\n\t" + "# A[1] * B[3]\n\t" + "mul x7, x10, x19\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x10, x19\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[2] * B[2]\n\t" + "mul x7, x11, x17\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x11, x17\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[3] * B[1]\n\t" + "mul x7, x12, x16\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x12, x16\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[4] * B[0]\n\t" + "mul x7, x13, x15\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x13, x15\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[tmp], 32]\n\t" + "adc x4, x4, xzr\n\t" + "# A[0] * B[5]\n\t" + "mul x7, x9, x21\n\t" + "umulh x8, x9, x21\n\t" + "adds x6, x6, x7\n\t" + "# A[1] * B[4]\n\t" + "mul x7, x10, x20\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x10, x20\n\t" + "adc x5, xzr, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[2] * B[3]\n\t" + "mul x7, x11, x19\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x11, x19\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[3] * B[2]\n\t" + "mul x7, x12, x17\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x12, x17\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[4] * B[1]\n\t" + "mul x7, x13, x16\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x13, x16\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[5] * B[0]\n\t" + "mul x7, x14, x15\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x14, x15\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[tmp], 40]\n\t" + "adc x5, x5, xzr\n\t" + "# A[1] * B[5]\n\t" + "mul x7, x10, x21\n\t" + "umulh x8, x10, x21\n\t" + "adds x4, x4, x7\n\t" + "# A[2] * B[4]\n\t" + "mul x7, x11, x20\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x11, x20\n\t" + "adc x6, xzr, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[3] * B[3]\n\t" + "mul x7, x12, x19\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x12, x19\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[4] * B[2]\n\t" + "mul x7, x13, x17\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x13, x17\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "# A[5] * B[1]\n\t" + "mul x7, x14, x16\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x14, x16\n\t" + "adc x6, x6, xzr\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[r], 48]\n\t" + "adc x6, x6, xzr\n\t" + "# A[2] * B[5]\n\t" + "mul x7, x11, x21\n\t" + "umulh x8, x11, x21\n\t" + "adds x5, x5, x7\n\t" + "# A[3] * B[4]\n\t" + "mul x7, x12, x20\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x12, x20\n\t" + "adc x4, xzr, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[4] * B[3]\n\t" + "mul x7, x13, x19\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x13, x19\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "# A[5] * B[2]\n\t" + "mul x7, x14, x17\n\t" + "adcs x6, x6, x8\n\t" + "umulh x8, x14, x17\n\t" + "adc x4, x4, xzr\n\t" + "adds x5, x5, x7\n\t" + "adcs x6, x6, x8\n\t" + "str x5, [%[r], 56]\n\t" + "adc x4, x4, xzr\n\t" + "# A[3] * B[5]\n\t" + "mul x7, x12, x21\n\t" + "umulh x8, x12, x21\n\t" + "adds x6, x6, x7\n\t" + "# A[4] * B[4]\n\t" + "mul x7, x13, x20\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x13, x20\n\t" + "adc x5, xzr, xzr\n\t" + "adds x6, x6, x7\n\t" + "# A[5] * B[3]\n\t" + "mul x7, x14, x19\n\t" + "adcs x4, x4, x8\n\t" + "umulh x8, x14, x19\n\t" + "adc x5, x5, xzr\n\t" + "adds x6, x6, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x6, [%[r], 64]\n\t" + "adc x5, x5, xzr\n\t" + "# A[4] * B[5]\n\t" + "mul x7, x13, x21\n\t" + "umulh x8, x13, x21\n\t" + "adds x4, x4, x7\n\t" + "# A[5] * B[4]\n\t" + "mul x7, x14, x20\n\t" + "adcs x5, x5, x8\n\t" + "umulh x8, x14, x20\n\t" + "adc x6, xzr, xzr\n\t" + "adds x4, x4, x7\n\t" + "adcs x5, x5, x8\n\t" + "str x4, [%[r], 72]\n\t" + "adc x6, x6, xzr\n\t" + "# A[5] * B[5]\n\t" + "mul x7, x14, x21\n\t" + "umulh x8, x14, x21\n\t" + "adds x5, x5, x7\n\t" + "adc x6, x6, x8\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x9, x10, [%[tmp], 0]\n\t" + "ldp x11, x12, [%[tmp], 16]\n\t" + "ldp x13, x14, [%[tmp], 32]\n\t" + "stp x9, x10, [%[r], 0]\n\t" + "stp x11, x12, [%[r], 16]\n\t" + "stp x13, x14, [%[r], 32]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* 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_384_cond_sub_6(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "sbcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "sbcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "sbcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +} + +#define sp_384_mont_reduce_order_6 sp_384_mont_reduce_6 + +/* Reduce the number back to 384 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_384_mont_reduce_6(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "ldp x14, x15, [%[m], 0]\n\t" + "ldp x16, x17, [%[m], 16]\n\t" + "ldp x19, x20, [%[m], 32]\n\t" + "# i = 6\n\t" + "mov x4, 6\n\t" + "ldp x12, x13, [%[a], 0]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul x9, %[mp], x12\n\t" + "# a[i+0] += m[0] * mu\n\t" + "mul x7, x14, x9\n\t" + "umulh x8, x14, x9\n\t" + "adds x12, x12, x7\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mul x7, x15, x9\n\t" + "adc x6, x8, xzr\n\t" + "umulh x8, x15, x9\n\t" + "adds x12, x13, x7\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr x13, [%[a], 16]\n\t" + "adc x5, x8, xzr\n\t" + "mul x7, x16, x9\n\t" + "adds x12, x12, x6\n\t" + "umulh x8, x16, x9\n\t" + "adc x5, x5, xzr\n\t" + "adds x13, x13, x7\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr x10, [%[a], 24]\n\t" + "adc x6, x8, xzr\n\t" + "mul x7, x17, x9\n\t" + "adds x13, x13, x5\n\t" + "umulh x8, x17, x9\n\t" + "adc x6, x6, xzr\n\t" + "adds x10, x10, x7\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr x11, [%[a], 32]\n\t" + "adc x5, x8, xzr\n\t" + "adds x10, x10, x6\n\t" + "mul x7, x19, x9\n\t" + "adc x5, x5, xzr\n\t" + "umulh x8, x19, x9\n\t" + "str x10, [%[a], 24]\n\t" + "adds x11, x11, x7\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr x10, [%[a], 40]\n\t" + "adc x6, x8, xzr\n\t" + "adds x11, x11, x5\n\t" + "mul x7, x20, x9\n\t" + "adc x6, x6, xzr\n\t" + "umulh x8, x20, x9\n\t" + "adds x6, x6, x7\n\t" + "adcs x8, x8, %[ca]\n\t" + "str x11, [%[a], 32]\n\t" + "cset %[ca], cs\n\t" + "adds x10, x10, x6\n\t" + "ldr x11, [%[a], 48]\n\t" + "str x10, [%[a], 40]\n\t" + "adcs x11, x11, x8\n\t" + "str x11, [%[a], 48]\n\t" + "adc %[ca], %[ca], xzr\n\t" + "subs x4, x4, 1\n\t" + "add %[a], %[a], 8\n\t" + "bne 1b\n\t" + "stp x12, x13, [%[a], 0]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20" + ); + + sp_384_cond_sub_6(a - 6, 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_384_mont_mul_6(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_384_mul_6(r, a, b); + sp_384_mont_reduce_6(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_384_sqr_6(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[12]; + + __asm__ __volatile__ ( + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "mov x5, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 40\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "cmp x4, x3\n\t" + "b.eq 4f\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[a], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "b.al 5f\n\t" + "\n4:\n\t" + "ldr x10, [%[a], x3]\n\t" + "mul x9, x10, x10\n\t" + "umulh x10, x10, x10\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "\n5:\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 48\n\t" + "b.eq 3f\n\t" + "cmp x3, x4\n\t" + "b.gt 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 80\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_384_sqr_6(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x17, x19, [%[a], 0]\n\t" + "ldp x20, x21, [%[a], 16]\n\t" + "ldp x22, x23, [%[a], 32]\n\t" + "# A[0] * A[1]\n\t" + "mul x3, x17, x19\n\t" + "umulh x7, x17, x19\n\t" + "# A[0] * A[2]\n\t" + "mul x4, x17, x20\n\t" + "umulh x5, x17, x20\n\t" + "adds x7, x7, x4\n\t" + "# A[0] * A[3]\n\t" + "mul x4, x17, x21\n\t" + "adc x8, xzr, x5\n\t" + "umulh x5, x17, x21\n\t" + "adds x8, x8, x4\n\t" + "# A[1] * A[2]\n\t" + "mul x4, x19, x20\n\t" + "adc x9, xzr, x5\n\t" + "umulh x5, x19, x20\n\t" + "adds x8, x8, x4\n\t" + "# A[0] * A[4]\n\t" + "mul x4, x17, x22\n\t" + "adcs x9, x9, x5\n\t" + "umulh x5, x17, x22\n\t" + "adc x10, xzr, xzr\n\t" + "adds x9, x9, x4\n\t" + "# A[1] * A[3]\n\t" + "mul x4, x19, x21\n\t" + "adc x10, x10, x5\n\t" + "umulh x5, x19, x21\n\t" + "adds x9, x9, x4\n\t" + "# A[0] * A[5]\n\t" + "mul x4, x17, x23\n\t" + "adcs x10, x10, x5\n\t" + "umulh x5, x17, x23\n\t" + "adc x11, xzr, xzr\n\t" + "adds x10, x10, x4\n\t" + "# A[1] * A[4]\n\t" + "mul x4, x19, x22\n\t" + "adc x11, x11, x5\n\t" + "umulh x5, x19, x22\n\t" + "adds x10, x10, x4\n\t" + "# A[2] * A[3]\n\t" + "mul x4, x20, x21\n\t" + "adcs x11, x11, x5\n\t" + "umulh x5, x20, x21\n\t" + "adc x12, xzr, xzr\n\t" + "adds x10, x10, x4\n\t" + "# A[1] * A[5]\n\t" + "mul x4, x19, x23\n\t" + "adcs x11, x11, x5\n\t" + "umulh x5, x19, x23\n\t" + "adc x12, x12, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[2] * A[4]\n\t" + "mul x4, x20, x22\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x20, x22\n\t" + "adc x13, xzr, xzr\n\t" + "adds x11, x11, x4\n\t" + "# A[2] * A[5]\n\t" + "mul x4, x20, x23\n\t" + "adcs x12, x12, x5\n\t" + "umulh x5, x20, x23\n\t" + "adc x13, x13, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[3] * A[4]\n\t" + "mul x4, x21, x22\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x21, x22\n\t" + "adc x14, xzr, xzr\n\t" + "adds x12, x12, x4\n\t" + "# A[3] * A[5]\n\t" + "mul x4, x21, x23\n\t" + "adcs x13, x13, x5\n\t" + "umulh x5, x21, x23\n\t" + "adc x14, x14, xzr\n\t" + "adds x13, x13, x4\n\t" + "# A[4] * A[5]\n\t" + "mul x4, x22, x23\n\t" + "adcs x14, x14, x5\n\t" + "umulh x5, x22, x23\n\t" + "adc x15, xzr, xzr\n\t" + "adds x14, x14, x4\n\t" + "adc x15, x15, x5\n\t" + "# Double\n\t" + "adds x3, x3, x3\n\t" + "adcs x7, x7, x7\n\t" + "adcs x8, x8, x8\n\t" + "adcs x9, x9, x9\n\t" + "adcs x10, x10, x10\n\t" + "adcs x11, x11, x11\n\t" + "adcs x12, x12, x12\n\t" + "adcs x13, x13, x13\n\t" + "adcs x14, x14, x14\n\t" + "# A[0] * A[0]\n\t" + "mul x2, x17, x17\n\t" + "adcs x15, x15, x15\n\t" + "umulh x4, x17, x17\n\t" + "cset x16, cs\n\t" + "# A[1] * A[1]\n\t" + "mul x5, x19, x19\n\t" + "adds x3, x3, x4\n\t" + "umulh x6, x19, x19\n\t" + "adcs x7, x7, x5\n\t" + "# A[2] * A[2]\n\t" + "mul x4, x20, x20\n\t" + "adcs x8, x8, x6\n\t" + "umulh x5, x20, x20\n\t" + "adcs x9, x9, x4\n\t" + "# A[3] * A[3]\n\t" + "mul x6, x21, x21\n\t" + "adcs x10, x10, x5\n\t" + "umulh x4, x21, x21\n\t" + "adcs x11, x11, x6\n\t" + "# A[4] * A[4]\n\t" + "mul x5, x22, x22\n\t" + "adcs x12, x12, x4\n\t" + "umulh x6, x22, x22\n\t" + "adcs x13, x13, x5\n\t" + "# A[5] * A[5]\n\t" + "mul x4, x23, x23\n\t" + "adcs x14, x14, x6\n\t" + "umulh x5, x23, x23\n\t" + "adcs x15, x15, x4\n\t" + "stp x2, x3, [%[r], 0]\n\t" + "adc x16, x16, x5\n\t" + "stp x7, x8, [%[r], 16]\n\t" + "stp x9, x10, [%[r], 32]\n\t" + "stp x11, x12, [%[r], 48]\n\t" + "stp x13, x14, [%[r], 64]\n\t" + "stp x15, x16, [%[r], 80]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x4", "x5", "x6", "x2", "x3", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21", "x22", "x23" + ); +} + +#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_384_mont_sqr_6(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_384_sqr_6(r, a); + sp_384_mont_reduce_6(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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_384_mont_sqr_n_6(sp_digit* r, const sp_digit* a, int n, + const sp_digit* m, sp_digit mp) +{ + sp_384_mont_sqr_6(r, a, m, mp); + for (; n > 1; n--) { + sp_384_mont_sqr_6(r, r, m, mp); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P384 curve. */ +static const uint64_t p384_mod_minus_2[6] = { + 0x00000000fffffffdU,0xffffffff00000000U,0xfffffffffffffffeU, + 0xffffffffffffffffU,0xffffffffffffffffU,0xffffffffffffffffU +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P384 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_384_mont_inv_6(sp_digit* r, const sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 6); + for (i=382; i>=0; i--) { + sp_384_mont_sqr_6(t, t, p384_mod, p384_mp_mod); + if (p384_mod_minus_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_384_mont_mul_6(t, t, a, p384_mod, p384_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 6); +#else + sp_digit* t1 = td; + sp_digit* t2 = td + 2 * 6; + sp_digit* t3 = td + 4 * 6; + sp_digit* t4 = td + 6 * 6; + sp_digit* t5 = td + 8 * 6; + + /* 0x2 */ + sp_384_mont_sqr_6(t1, a, p384_mod, p384_mp_mod); + /* 0x3 */ + sp_384_mont_mul_6(t5, t1, a, p384_mod, p384_mp_mod); + /* 0xc */ + sp_384_mont_sqr_n_6(t1, t5, 2, p384_mod, p384_mp_mod); + /* 0xf */ + sp_384_mont_mul_6(t2, t5, t1, p384_mod, p384_mp_mod); + /* 0x1e */ + sp_384_mont_sqr_6(t1, t2, p384_mod, p384_mp_mod); + /* 0x1f */ + sp_384_mont_mul_6(t4, t1, a, p384_mod, p384_mp_mod); + /* 0x3e0 */ + sp_384_mont_sqr_n_6(t1, t4, 5, p384_mod, p384_mp_mod); + /* 0x3ff */ + sp_384_mont_mul_6(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0x7fe0 */ + sp_384_mont_sqr_n_6(t1, t2, 5, p384_mod, p384_mp_mod); + /* 0x7fff */ + sp_384_mont_mul_6(t4, t4, t1, p384_mod, p384_mp_mod); + /* 0x3fff8000 */ + sp_384_mont_sqr_n_6(t1, t4, 15, p384_mod, p384_mp_mod); + /* 0x3fffffff */ + sp_384_mont_mul_6(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffc */ + sp_384_mont_sqr_n_6(t3, t2, 2, p384_mod, p384_mp_mod); + /* 0xfffffffd */ + sp_384_mont_mul_6(r, t3, a, p384_mod, p384_mp_mod); + /* 0xffffffff */ + sp_384_mont_mul_6(t3, t5, t3, p384_mod, p384_mp_mod); + /* 0xfffffffc0000000 */ + sp_384_mont_sqr_n_6(t1, t2, 30, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff */ + sp_384_mont_mul_6(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_6(t1, t2, 60, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_6(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_6(t1, t2, 120, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_6(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_6(t1, t2, 15, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_6(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */ + sp_384_mont_sqr_n_6(t1, t2, 33, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */ + sp_384_mont_mul_6(t2, t3, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_6(t1, t2, 96, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */ + sp_384_mont_mul_6(r, r, t1, p384_mod, p384_mp_mod); + +#endif /* WOLFSSL_SP_SMALL */ +} + +/* 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_384_cmp_6(const sp_digit* a, const sp_digit* b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "mov x5, 40\n\t" + "1:\n\t" + "ldr x6, [%[a], x5]\n\t" + "ldr x7, [%[b], x5]\n\t" + "and x6, x6, x4\n\t" + "and x7, x7, x4\n\t" + "subs x6, x6, x7\n\t" + "csel x2, x3, x2, hi\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "subs x5, x5, #8\n\t" + "b.cs 1b\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16" + ); +#else + __asm__ __volatile__ ( + "mov x2, -1\n\t" + "mov x3, 1\n\t" + "mov x4, -1\n\t" + "ldp x5, x6, [%[a], 0]\n\t" + "ldp x7, x8, [%[a], 16]\n\t" + "ldp x9, x10, [%[a], 32]\n\t" + "ldp x11, x12, [%[b], 0]\n\t" + "ldp x13, x14, [%[b], 16]\n\t" + "ldp x15, x16, [%[b], 32]\n\t" + "and x10, x10, x4\n\t" + "and x16, x16, x4\n\t" + "subs x10, x10, x16\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x9, x9, x4\n\t" + "and x15, x15, x4\n\t" + "subs x9, x9, x15\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x8, x8, x4\n\t" + "and x14, x14, x4\n\t" + "subs x8, x8, x14\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x7, x7, x4\n\t" + "and x13, x13, x4\n\t" + "subs x7, x7, x13\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x6, x6, x4\n\t" + "and x12, x12, x4\n\t" + "subs x6, x6, x12\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "and x5, x5, x4\n\t" + "and x11, x11, x4\n\t" + "subs x5, x5, x11\n\t" + "csel x2, x4, x2, lo\n\t" + "csel x4, x4, xzr, eq\n\t" + "csel x2, x3, x2, hi\n\t" + "eor %[a], x2, x4\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16" + ); +#endif + + return (int64_t)a; +} + +/* Normalize the values in each word to 64. + * + * a Array of sp_digit to normalize. + */ +#define sp_384_norm_6(a) + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_384_map_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*6; + int64_t n; + + sp_384_mont_inv_6(t1, p->z, t + 2*6); + + sp_384_mont_sqr_6(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t1, t2, t1, p384_mod, p384_mp_mod); + + /* x /= z^2 */ + sp_384_mont_mul_6(r->x, p->x, t2, p384_mod, p384_mp_mod); + XMEMSET(r->x + 6, 0, sizeof(r->x) / 2U); + sp_384_mont_reduce_6(r->x, p384_mod, p384_mp_mod); + /* Reduce x to less than modulus */ + n = sp_384_cmp_6(r->x, p384_mod); + sp_384_cond_sub_6(r->x, r->x, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_6(r->x); + + /* y /= z^3 */ + sp_384_mont_mul_6(r->y, p->y, t1, p384_mod, p384_mp_mod); + XMEMSET(r->y + 6, 0, sizeof(r->y) / 2U); + sp_384_mont_reduce_6(r->y, p384_mod, p384_mp_mod); + /* Reduce y to less than modulus */ + n = sp_384_cmp_6(r->y, p384_mod); + sp_384_cond_sub_6(r->y, r->y, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_6(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +/* 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_384_add_6(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "adds x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "adcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "adcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldr x3, [%[a], 32]\n\t" + "ldr x4, [%[a], 40]\n\t" + "ldr x7, [%[b], 32]\n\t" + "ldr x8, [%[b], 40]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "str x3, [%[r], 32]\n\t" + "str x4, [%[r], 40]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +/* 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_384_mont_add_6(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_6(r, a, b); + sp_384_cond_sub_6(r, r, m, 0 - o); +} + +/* 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_384_mont_dbl_6(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_6(r, a, a); + sp_384_cond_sub_6(r, r, m, 0 - o); +} + +/* 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_384_mont_tpl_6(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_6(r, a, a); + sp_384_cond_sub_6(r, r, m, 0 - o); + o = sp_384_add_6(r, r, a); + sp_384_cond_sub_6(r, r, m, 0 - o); +} + +/* 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_384_sub_6(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "subs x3, x3, x7\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "sbcs x6, x6, x10\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldr x3, [%[a], 32]\n\t" + "ldr x4, [%[a], 40]\n\t" + "ldr x7, [%[b], 32]\n\t" + "ldr x8, [%[b], 40]\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "str x3, [%[r], 32]\n\t" + "str x4, [%[r], 40]\n\t" + "csetm %[r], cc\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return (sp_digit)r; +} + +/* 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 sp_digit sp_384_cond_add_6(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "cset %[c], cs\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 48\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return c; +#else + __asm__ __volatile__ ( + + "ldp x5, x7, [%[b], 0]\n\t" + "ldp x11, x12, [%[b], 16]\n\t" + "ldp x4, x6, [%[a], 0]\n\t" + "and x5, x5, %[m]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "and x7, x7, %[m]\n\t" + "adds x4, x4, x5\n\t" + "and x11, x11, %[m]\n\t" + "adcs x6, x6, x7\n\t" + "and x12, x12, %[m]\n\t" + "adcs x9, x9, x11\n\t" + "stp x4, x6, [%[r], 0]\n\t" + "adcs x10, x10, x12\n\t" + "stp x9, x10, [%[r], 16]\n\t" + "ldp x5, x7, [%[b], 32]\n\t" + "ldp x4, x6, [%[a], 32]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "adcs x4, x4, x5\n\t" + "adcs x6, x6, x7\n\t" + "stp x4, x6, [%[r], 32]\n\t" + "cset %[r], cs\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8", "x9", "x10", "x11", "x12" + ); + + return (sp_digit)r; +#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_384_mont_sub_6(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + sp_digit o; + + o = sp_384_sub_6(r, a, b); + sp_384_cond_add_6(r, r, m, o); +} + +static void sp_384_rshift1_6(sp_digit* r, sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x2, x3, [%[a]]\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "ldp x6, x7, [%[a], 32]\n\t" + "lsr x11, x6, 1\n\t" + "lsr x10, x5, 1\n\t" + "lsr x9, x4, 1\n\t" + "lsr x8, x3, 1\n\t" + "lsr x2, x2, 1\n\t" + "orr x2, x2, x3, lsl 63\n\t" + "orr x3, x8, x4, lsl 63\n\t" + "orr x4, x9, x5, lsl 63\n\t" + "orr x5, x10, x6, lsl 63\n\t" + "orr x6, x11, x7, lsl 63\n\t" + "lsr x7, x7, 1\n\t" + "stp x2, x3, [%[r]]\n\t" + "stp x4, x5, [%[r], 16]\n\t" + "stp x6, x7, [%[r], 32]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); +} + +/* 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_384_div2_6(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_cond_add_6(r, a, m, 0 - (a[0] & 1)); + sp_384_rshift1_6(r, r); + r[5] |= o << 63; +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_dbl_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*6; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_384_mont_sqr_6(t1, p->z, p384_mod, p384_mp_mod); + /* Z = Y * Z */ + sp_384_mont_mul_6(z, p->y, p->z, p384_mod, p384_mp_mod); + /* Z = 2Z */ + sp_384_mont_dbl_6(z, z, p384_mod); + /* T2 = X - T1 */ + sp_384_mont_sub_6(t2, p->x, t1, p384_mod); + /* T1 = X + T1 */ + sp_384_mont_add_6(t1, p->x, t1, p384_mod); + /* T2 = T1 * T2 */ + sp_384_mont_mul_6(t2, t1, t2, p384_mod, p384_mp_mod); + /* T1 = 3T2 */ + sp_384_mont_tpl_6(t1, t2, p384_mod); + /* Y = 2Y */ + sp_384_mont_dbl_6(y, p->y, p384_mod); + /* Y = Y * Y */ + sp_384_mont_sqr_6(y, y, p384_mod, p384_mp_mod); + /* T2 = Y * Y */ + sp_384_mont_sqr_6(t2, y, p384_mod, p384_mp_mod); + /* T2 = T2/2 */ + sp_384_div2_6(t2, t2, p384_mod); + /* Y = Y * X */ + sp_384_mont_mul_6(y, y, p->x, p384_mod, p384_mp_mod); + /* X = T1 * T1 */ + sp_384_mont_sqr_6(x, t1, p384_mod, p384_mp_mod); + /* X = X - Y */ + sp_384_mont_sub_6(x, x, y, p384_mod); + /* X = X - Y */ + sp_384_mont_sub_6(x, x, y, p384_mod); + /* Y = Y - X */ + sp_384_mont_sub_6(y, y, x, p384_mod); + /* Y = Y * T1 */ + sp_384_mont_mul_6(y, y, t1, p384_mod, p384_mp_mod); + /* Y = Y - T2 */ + sp_384_mont_sub_6(y, y, t2, p384_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_384_proj_point_dbl_n_6(sp_point_384* p, int n, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*6; + sp_digit* b = t + 4*6; + sp_digit* t1 = t + 6*6; + sp_digit* t2 = t + 8*6; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_384_mont_dbl_6(y, y, p384_mod); + /* W = Z^4 */ + sp_384_mont_sqr_6(w, z, p384_mod, p384_mp_mod); + sp_384_mont_sqr_6(w, w, p384_mod, p384_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_6(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(t1, t1, w, p384_mod); + sp_384_mont_tpl_6(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_6(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_6(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_6(t2, b, p384_mod); + sp_384_mont_sub_6(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_6(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_6(t1, t1, p384_mod, p384_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_384_mont_mul_6(w, w, t1, p384_mod, p384_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_6(y, b, x, p384_mod); + sp_384_mont_mul_6(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_6(y, y, p384_mod); + sp_384_mont_sub_6(y, y, t1, p384_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_6(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(t1, t1, w, p384_mod); + sp_384_mont_tpl_6(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_6(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_6(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_6(t2, b, p384_mod); + sp_384_mont_sub_6(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_6(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_6(t1, t1, p384_mod, p384_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_6(y, b, x, p384_mod); + sp_384_mont_mul_6(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_6(y, y, p384_mod); + sp_384_mont_sub_6(y, y, t1, p384_mod); +#endif + /* Y = Y/2 */ + sp_384_div2_6(y, y, p384_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_384_cmp_equal_6(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])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_6(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, + sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*6; + sp_digit* t3 = t + 4*6; + sp_digit* t4 = t + 6*6; + sp_digit* t5 = t + 8*6; + 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) { + const sp_point_384* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_384_sub_6(t1, p384_mod, q->y); + sp_384_norm_6(t1); + if ((sp_384_cmp_equal_6(p->x, q->x) & sp_384_cmp_equal_6(p->z, q->z) & + (sp_384_cmp_equal_6(p->y, q->y) | sp_384_cmp_equal_6(p->y, t1))) != 0) { + sp_384_proj_point_dbl_6(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<6; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<6; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<6; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_6(t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t3, t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t1, t1, x, p384_mod, p384_mp_mod); + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_6(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_6(t3, t3, y, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_6(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - U1 */ + sp_384_mont_sub_6(t2, t2, t1, p384_mod); + /* R = S2 - S1 */ + sp_384_mont_sub_6(t4, t4, t3, p384_mod); + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_6(z, z, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_6(x, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_6(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(y, t1, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(x, x, t5, p384_mod); + sp_384_mont_dbl_6(t1, y, p384_mod); + sp_384_mont_sub_6(x, x, t1, p384_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_mul_6(y, y, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t5, t5, t3, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(y, y, t5, p384_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_384_proj_point_dbl_n_store_6(sp_point_384* r, const sp_point_384* p, + int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*6; + sp_digit* b = t + 4*6; + sp_digit* t1 = t + 6*6; + sp_digit* t2 = t + 8*6; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + } + for (i=0; i<6; i++) { + y[i] = p->y[i]; + } + for (i=0; i<6; i++) { + z[i] = p->z[i]; + } + + /* Y = 2*Y */ + sp_384_mont_dbl_6(y, y, p384_mod); + /* W = Z^4 */ + sp_384_mont_sqr_6(w, z, p384_mod, p384_mp_mod); + sp_384_mont_sqr_6(w, w, p384_mod, p384_mp_mod); + for (i=1; i<=n; i++) { + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_6(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(t1, t1, w, p384_mod); + sp_384_mont_tpl_6(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_6(t2, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(b, t2, x, p384_mod, p384_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_384_mont_sqr_6(t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t3, t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t1, t1, x, p384_mod, p384_mp_mod); + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_6(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_6(t3, t3, y, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_6(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - U1 */ + sp_384_mont_sub_6(t2, t2, t1, p384_mod); + /* RS = S2 + S1 */ + sp_384_mont_add_6(t6, t4, t3, p384_mod); + /* R = S2 - S1 */ + sp_384_mont_sub_6(t4, t4, t3, p384_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_384_mont_mul_6(z, z, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(z, z, t2, p384_mod, p384_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_384_mont_sqr_6(x, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_6(xs, t6, p384_mod, p384_mp_mod); + sp_384_mont_sqr_6(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(y, t1, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(x, x, t5, p384_mod); + sp_384_mont_sub_6(xs, xs, t5, p384_mod); + sp_384_mont_dbl_6(t1, y, p384_mod); + sp_384_mont_sub_6(x, x, t1, p384_mod); + sp_384_mont_sub_6(xs, xs, t1, p384_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_384_mont_sub_6(ys, y, xs, p384_mod); + sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_mul_6(y, y, t4, p384_mod, p384_mp_mod); + sp_384_sub_6(t6, p384_mod, t6); + sp_384_mont_mul_6(ys, ys, t6, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t5, t5, t3, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(y, y, t5, p384_mod); + sp_384_mont_sub_6(ys, ys, t5, p384_mod); +} + +/* Structure used to describe recoding of scalar multiplication. */ +typedef struct ecc_recode_384 { + /* Index into pre-computation table. */ + uint8_t i; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode_384; + +/* The index into pre-computation table to use. */ +static const uint8_t recode_index_6_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 const uint8_t recode_neg_6_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 perform. + */ +static void sp_384_ecc_recode_6_6(const sp_digit* k, ecc_recode_384* 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<65; i++) { + y = n; + if (o + 6 < 64) { + y &= 0x3f; + n >>= 6; + o += 6; + } + else if (o + 6 == 64) { + n >>= 6; + if (++j < 6) + n = k[j]; + o = 0; + } + else if (++j < 6) { + n = k[j]; + y |= (n << (64 - o)) & 0x3f; + o -= 58; + n >>= o; + } + + y += carry; + v[i].i = recode_index_6_6[y]; + v[i].neg = recode_neg_6_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 coordinates. + * + * 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_384_ecc_mulmod_win_add_sub_6(sp_point_384* r, const sp_point_384* g, + const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td[33]; + sp_point_384 rtd, pd; + sp_digit tmpd[2 * 6 * 6]; +#endif + sp_point_384* t; + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_384 v[65]; + int err; + + (void)heap; + + err = sp_384_point_new_6(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_384_point_new_6(heap, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 33, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 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_384_mod_mul_norm_6(t[1].x, g->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t[1].y, g->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t[1].z, g->z, p384_mod); + } + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[32] */ + sp_384_proj_point_dbl_n_store_6(t, &t[ 1], 5, 1, tmp); + sp_384_proj_point_add_6(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[ 6], &t[ 3], tmp); + sp_384_proj_point_add_sub_6(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[10], &t[ 5], tmp); + sp_384_proj_point_add_sub_6(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[12], &t[ 6], tmp); + sp_384_proj_point_dbl_6(&t[14], &t[ 7], tmp); + sp_384_proj_point_add_sub_6(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[18], &t[ 9], tmp); + sp_384_proj_point_add_sub_6(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[20], &t[10], tmp); + sp_384_proj_point_dbl_6(&t[22], &t[11], tmp); + sp_384_proj_point_add_sub_6(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[24], &t[12], tmp); + sp_384_proj_point_dbl_6(&t[26], &t[13], tmp); + sp_384_proj_point_add_sub_6(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[28], &t[14], tmp); + sp_384_proj_point_dbl_6(&t[30], &t[15], tmp); + sp_384_proj_point_add_sub_6(&t[31], &t[29], &t[30], &t[ 1], tmp); + + negy = t[0].y; + + sp_384_ecc_recode_6_6(k, v); + + i = 64; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_384)); + for (--i; i>=0; i--) { + sp_384_proj_point_dbl_n_6(rt, 6, tmp); + + XMEMCPY(p, &t[v[i].i], sizeof(sp_point_384)); + sp_384_sub_6(negy, p384_mod, p->y); + sp_384_cond_copy_6(p->y, negy, (sp_digit)0 - v[i].neg); + sp_384_proj_point_add_6(rt, rt, p, tmp); + } + + if (map != 0) { + sp_384_map_6(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + sp_384_point_free_6(p, 0, heap); + sp_384_point_free_6(rt, 0, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_384 { + sp_digit x[6]; + sp_digit y[6]; +} sp_table_entry_384; + +#ifdef FP_ECC +#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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_qz1_6(sp_point_384* r, const sp_point_384* p, + const sp_point_384* q, sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*6; + sp_digit* t3 = t + 4*6; + sp_digit* t4 = t + 6*6; + sp_digit* t5 = t + 8*6; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_384_sub_6(t1, p384_mod, q->y); + sp_384_norm_6(t1); + if ((sp_384_cmp_equal_6(p->x, q->x) & sp_384_cmp_equal_6(p->z, q->z) & + (sp_384_cmp_equal_6(p->y, q->y) | sp_384_cmp_equal_6(p->y, t1))) != 0) { + sp_384_proj_point_dbl_6(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<6; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<6; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<6; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_6(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_6(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - X1 */ + sp_384_mont_sub_6(t2, t2, x, p384_mod); + /* R = S2 - Y1 */ + sp_384_mont_sub_6(t4, t4, y, p384_mod); + /* Z3 = H*Z1 */ + sp_384_mont_mul_6(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_384_mont_sqr_6(t1, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_6(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t3, x, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(x, t1, t5, p384_mod); + sp_384_mont_dbl_6(t1, t3, p384_mod); + sp_384_mont_sub_6(x, x, t1, p384_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_384_mont_sub_6(t3, t3, x, p384_mod); + sp_384_mont_mul_6(t3, t3, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t5, t5, y, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(y, t3, t5, p384_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_384_proj_to_affine_6(sp_point_384* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 6; + sp_digit* tmp = t + 4 * 6; + + sp_384_mont_inv_6(t1, a->z, tmp); + + sp_384_mont_sqr_6(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t1, t2, t1, p384_mod, p384_mp_mod); + + sp_384_mont_mul_6(a->x, a->x, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(a->y, a->y, t1, p384_mod, p384_mp_mod); + XMEMCPY(a->z, p384_norm_mod, sizeof(p384_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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_384_gen_stripe_table_6(const sp_point_384* a, + sp_table_entry_384* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td, s1d, s2d; +#endif + sp_point_384* t; + sp_point_384* s1 = NULL; + sp_point_384* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_384_point_new_6(heap, td, t); + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t->x, a->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t->y, a->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t->z, a->z, p384_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_384_proj_to_affine_6(t, tmp); + + XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_384)); + /* 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)); + + for (i=1; i<8; i++) { + sp_384_proj_point_dbl_n_6(t, 48, tmp); + sp_384_proj_to_affine_6(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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_384_proj_point_add_qz1_6(t, s1, s2, tmp); + sp_384_proj_to_affine_6(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_384_point_free_6(s2, 0, heap); + sp_384_point_free_6(s1, 0, heap); + sp_384_point_free_6( 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 coordinates. + * + * 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_384_ecc_mulmod_stripe_6(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 rtd; + sp_point_384 pd; + sp_digit td[2 * 6 * 6]; +#endif + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_384_point_new_6(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + y = 0; + for (j=0,x=47; j<8; j++,x+=48) { + 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 = !y; + for (i=46; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=48) { + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + } + + sp_384_proj_point_dbl_6(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 = !y; + sp_384_proj_point_add_qz1_6(rt, rt, p, t); + } + + if (map != 0) { + sp_384_map_6(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(p, 0, heap); + sp_384_point_free_6(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_384_t { + sp_digit x[6]; + sp_digit y[6]; + sp_table_entry_384 table[256]; + uint32_t cnt; + int set; +} sp_cache_384_t; + +static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_384_last = -1; +static THREAD_LS_T int sp_cache_384_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_384 = 0; + static wolfSSL_Mutex sp_cache_384_lock; +#endif + +static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_384_inited == 0) { + for (i=0; ix, sp_cache_384[i].x) & + sp_384_cmp_equal_6(g->y, sp_cache_384[i].y)) { + sp_cache_384[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_384_last + 1) % FP_ENTRIES; + for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_384[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_384_last) { + least = sp_cache_384[0].cnt; + for (j=1; jx, sizeof(sp_cache_384[i].x)); + XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y)); + sp_cache_384[i].set = 1; + sp_cache_384[i].cnt = 1; + } + + *cache = &sp_cache_384[i]; + sp_cache_384_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_6(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_384_ecc_mulmod_win_add_sub_6(r, g, k, map, heap); +#else + sp_digit tmp[2 * 6 * 7]; + sp_cache_384_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_384 == 0) { + wc_InitMutex(&sp_cache_384_lock); + initCacheMutex_384 = 1; + } + if (wc_LockMutex(&sp_cache_384_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_384(g, &cache); + if (cache->cnt == 2) + sp_384_gen_stripe_table_6(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_384_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_384_ecc_mulmod_win_add_sub_6(r, g, k, map, heap); + } + else { + err = sp_384_ecc_mulmod_stripe_6(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[6]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_384_point_new_6(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 6, km); + sp_384_point_from_ecc_point_6(point, gm); + + err = sp_384_ecc_mulmod_6(point, point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_6(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(point, 0, heap); + + return err; +} + +static const sp_table_entry_384 p384_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x3dd0756649c0b528L,0x20e378e2a0d6ce38L,0x879c3afc541b4d6eL, + 0x6454868459a30effL,0x812ff723614ede2bL,0x4d3aadc2299e1513L }, + { 0x23043dad4b03a4feL,0xa1bfa8bf7bb4a9acL,0x8bade7562e83b050L, + 0xc6c3521968f4ffd9L,0xdd8002263969a840L,0x2b78abc25a15c5e9L } }, + /* 2 */ + { { 0x298647532b0c535bL,0x90dd695370506296L,0x038cd6b4216ab9acL, + 0x3df9b7b7be12d76aL,0x13f4d9785f347bdbL,0x222c5c9c13e94489L }, + { 0x5f8e796f2680dc64L,0x120e7cb758352417L,0x254b5d8ad10740b8L, + 0xc38b8efb5337dee6L,0xf688c2e194f02247L,0x7b5c75f36c25bc4cL } }, + /* 3 */ + { { 0xe26a3cc39edffea5L,0x35bbfd1c37d7e9fcL,0xf0e7700d9bde3ef6L, + 0x0380eb471a538f5aL,0x2e9da8bb05bf9eb3L,0xdbb93c731a460c3eL }, + { 0x37dba260f526b605L,0x95d4978efd785537L,0x24ed793aed72a04aL, + 0x2694837776005b1aL,0x99f557b99e681f82L,0xae5f9557d64954efL } }, + /* 4 */ + { { 0x24480c57f26feef9L,0xc31a26943a0e1240L,0x735002c3273e2bc7L, + 0x8c42e9c53ef1ed4cL,0x028babf67f4948e8L,0x6a502f438a978632L }, + { 0xf5f13a46b74536feL,0x1d218babd8a9f0ebL,0x30f36bcc37232768L, + 0xc5317b31576e8c18L,0xef1d57a69bbcb766L,0x917c4930b3e3d4dcL } }, + /* 5 */ + { { 0x11426e2ee349ddd0L,0x9f117ef99b2fc250L,0xff36b480ec0174a6L, + 0x4f4bde7618458466L,0x2f2edb6d05806049L,0x8adc75d119dfca92L }, + { 0xa619d097b7d5a7ceL,0x874275e5a34411e9L,0x5403e0470da4b4efL, + 0x2ebaafd977901d8fL,0x5e63ebcea747170fL,0x12a369447f9d8036L } }, + /* 6 */ + { { 0x28f9c07a4fc52870L,0xce0b37481a53a961L,0xd550fa180e1828d9L, + 0xa24abaf76adb225aL,0xd11ed0a56e58a348L,0xf3d811e6948acb62L }, + { 0x8618dd774c61ed22L,0x0bb747f980b47c9dL,0x22bf796fde6b8559L, + 0xfdfd1c6d680a21e9L,0xc0db15772af2c9ddL,0xa09379e6c1e90f3dL } }, + /* 7 */ + { { 0x386c66efe085c629L,0x5fc2a461095bc89aL,0x1353d631203f4b41L, + 0x7ca1972b7e4bd8f5L,0xb077380aa7df8ce9L,0xd8a90389ee7e4ea3L }, + { 0x1bc74dc7e7b14461L,0xdc2cb0140c9c4f78L,0x52b4b3a684ef0a10L, + 0xbde6ea5d20327fe2L,0xb71ec435660f9615L,0xeede5a04b8ad8173L } }, + /* 8 */ + { { 0x5584cbb3893b9a2dL,0x820c660b00850c5dL,0x4126d8267df2d43dL, + 0xdd5bbbf00109e801L,0x85b92ee338172f1cL,0x609d4f93f31430d9L }, + { 0x1e059a07eadaf9d6L,0x70e6536c0f125fb0L,0xd6220751560f20e7L, + 0xa59489ae7aaf3a9aL,0x7b70e2f664bae14eL,0x0dd0370176d08249L } }, + /* 9 */ + { { 0x4cc13be88510521fL,0x87315ba9f724cc17L,0xb49d83bb353dc263L, + 0x8b677efe0c279257L,0x510a1c1cc93c9537L,0x33e30cd8a4702c99L }, + { 0xf0ffc89d2208353fL,0x0170fa8dced42b2bL,0x090851ed26e2a5f5L, + 0x81276455ecb52c96L,0x0646c4e17fe1adf4L,0x513f047eb0868eabL } }, + /* 10 */ + { { 0xc07611f4df5bdf53L,0x45d331a758b11a6dL,0x58965daf1c4ee394L, + 0xba8bebe75a5878d1L,0xaecc0a1882dd3025L,0xcf2a3899a923eb8bL }, + { 0xf98c9281d24fd048L,0x841bfb598bbb025dL,0xb8ddf8cec9ab9d53L, + 0x538a4cb67fef044eL,0x092ac21f23236662L,0xa919d3850b66f065L } }, + /* 11 */ + { { 0x3db03b4085d480d8L,0x8cd9f4791b287a7dL,0x8f24dc754a8f3baeL, + 0x482eb8003db41892L,0x38bf9eb39c56e0f5L,0x8b9773209a91dc6fL }, + { 0xa31b05b27209cfc2L,0x4c49bf8505b2db70L,0x56462498d619527bL, + 0x3fe510391fac51baL,0xfb04f55eab4b8342L,0xc07c10dc04c6eabfL } }, + /* 12 */ + { { 0xad22fe4cdb32f048L,0x5f23bf91475ed6dfL,0xa50ce0c0aa66b6cbL, + 0xdf627a89f03405c0L,0x3674837df95e2d6aL,0x081c95b6ba42e64eL }, + { 0xeba3e036e71d6cebL,0xb45bcccf6c6b0271L,0x67b47e630684701dL, + 0x60f8f942e712523fL,0x824234725cd47adcL,0x83027d7987649cbbL } }, + /* 13 */ + { { 0xb3929ea63615b0b8L,0xb41441fda54dac41L,0x8995d556b5b6a368L, + 0xa80d4529167ef05eL,0xf6bcb4a16d25a27fL,0x210d6a4c7bd55b68L }, + { 0xf3804abb25351130L,0x1d2df699903e37ebL,0x5f201efc084c25c8L, + 0x31a28c87a1c68e91L,0x81dad253563f62a5L,0x5dd6de70d6c415d4L } }, + /* 14 */ + { { 0x29f470fd846612ceL,0x986f3eecda18d997L,0x6b84c1612f34af86L, + 0x5ef0a40846ddaf8bL,0x14405a00e49e795fL,0x5f491b16aa2f7a37L }, + { 0xc7f07ae4db41b38dL,0xef7d119e18fbfcaaL,0x3a18e07614443b19L, + 0x4356841a79a19926L,0x91f4a91ce2226fbeL,0xdc77248c3cc88721L } }, + /* 15 */ + { { 0xd570ff1ae4b1ec9dL,0x21d23e0ee7eef706L,0x3cde40f4ca19e086L, + 0x7d6523c4cd4bb270L,0x16c1f06cbf13aa6cL,0x5aa7245ad14c4b60L }, + { 0x37f8146744b74de8L,0x839e7a17620a934eL,0xf74d14e8de8b1aa1L, + 0x8789fa51f30d75e2L,0x09b24052c81c261eL,0x654e267833c565eeL } }, + /* 16 */ + { { 0x378205de2f9fbe67L,0xc4afcb837f728e44L,0xdbcec06c682e00f1L, + 0xf2a145c3114d5423L,0xa01d98747a52463eL,0xfc0935b17d717b0aL }, + { 0x9653bc4fd4d01f95L,0x9aa83ea89560ad34L,0xf77943dcaf8e3f3fL, + 0x70774a10e86fe16eL,0x6b62e6f1bf9ffdcfL,0x8a72f39e588745c9L } }, + /* 17 */ + { { 0x73ade4da2341c342L,0xdd326e54ea704422L,0x336c7d983741cef3L, + 0x1eafa00d59e61549L,0xcd3ed892bd9a3efdL,0x03faf26cc5c6c7e4L }, + { 0x087e2fcf3045f8acL,0x14a65532174f1e73L,0x2cf84f28fe0af9a7L, + 0xddfd7a842cdc935bL,0x4c0f117b6929c895L,0x356572d64c8bcfccL } }, + /* 18 */ + { { 0x7ecbac017d8c1bbaL,0x6058f9c390b0f3d5L,0xaee116e3f6197d0fL, + 0xc4dd70684033b128L,0xf084dba6c209b983L,0x97c7c2cf831dbc4aL }, + { 0x2f4e61ddf96010e8L,0xd97e4e20529faa17L,0x4ee6666069d37f20L, + 0xccc139ed3d366d72L,0x690b6ee213488e0fL,0x7cad1dc5f3a6d533L } }, + /* 19 */ + { { 0x660a9a81da57a41fL,0xe74a0412ec0039b6L,0x42343c6b5e1dad15L, + 0x284f3ff546681d4cL,0xb51087f163749e89L,0x070f23cc6f9f2f13L }, + { 0x542211da5d186e14L,0x84748f37fddb0dffL,0x41a3aab4db1f4180L, + 0x25ed667ba6402d0eL,0x2f2924a902f58355L,0x5844ee7cfa44a689L } }, + /* 20 */ + { { 0xfab086073f3b236fL,0x19e9d41d81e221daL,0xf3f6571e3927b428L, + 0x4348a9337550f1f6L,0x7167b996a85e62f0L,0x62d437597f5452bfL }, + { 0xd85feb9ef2955926L,0x440a561f6df78353L,0x389668ec9ca36b59L, + 0x052bf1a1a22da016L,0xbdfbff72f6093254L,0x94e50f28e22209f3L } }, + /* 21 */ + { { 0x90b2e5b33062e8afL,0xa8572375e8a3d369L,0x3fe1b00b201db7b1L, + 0xe926def0ee651aa2L,0x6542c9beb9b10ad7L,0x098e309ba2fcbe74L }, + { 0x779deeb3fff1d63fL,0x23d0e80a20bfd374L,0x8452bb3b8768f797L, + 0xcf75bb4d1f952856L,0x8fe6b40029ea3faaL,0x12bd3e4081373a53L } }, + /* 22 */ + { { 0xc023780d104cbba5L,0x6207e747fa35dd4cL,0x35c239281ca9b6a3L, + 0x4ff19be897987b10L,0xb8476bbf8022eee8L,0xaa0a4a14d3bbe74dL }, + { 0x20f94331187d4543L,0x3215387079f6e066L,0x83b0f74eac7e82e1L, + 0xa7748ba2828f06abL,0xc5f0298ac26ef35fL,0x0f0c50708e9a7dbdL } }, + /* 23 */ + { { 0x0c5c244cdef029ddL,0x3dabc687850661b8L,0x9992b865fe11d981L, + 0xe9801b8f6274dbadL,0xe54e6319098da242L,0x9929a91a91a53d08L }, + { 0x37bffd7235285887L,0xbc759425f1418102L,0x9280cc35fd2e6e20L, + 0x735c600cfbc42ee5L,0xb7ad28648837619aL,0xa3627231a778c57bL } }, + /* 24 */ + { { 0xae799b5c91361ed8L,0x47d71b756c63366cL,0x54cdd5211b265a6aL, + 0xe0215a5998d77b74L,0x4424d9b7bab29db0L,0x8b0ffacc7fd9e536L }, + { 0x46d85d1237b5d9efL,0x5b106d62bfa91747L,0xed0479f85f99ba2dL, + 0x0e6f39231d104de4L,0x83a84c8425e8983fL,0xa9507e0af8105a70L } }, + /* 25 */ + { { 0xf6c68a6e14cf381cL,0xaf9d27bdc22e31ccL,0x23568d4daa8a5ccbL, + 0xe431eec0e338e4d2L,0xf1a828fe8f52ad1fL,0xdb6a0579e86acd80L }, + { 0x2885672e4507832aL,0x73fc275f887e5289L,0x65f8027805610d08L, + 0x8d9b4554075ff5b0L,0x3a8e8fb109f712b5L,0x39f0ac862ebe9cf2L } }, + /* 26 */ + { { 0xd8fabf784c52edf5L,0xdcd737e5a589ae53L,0x94918bf0d791ab17L, + 0xb5fbd956bcff06c9L,0xf6d3032edca46d45L,0x2cdff7e141a3e486L }, + { 0x6674b3ba61f47ec8L,0x8a882163eef84608L,0xa257c7054c687f90L, + 0xe30cb2edf6cdf227L,0x2c4c64ca7f6ea846L,0x186fa17ccc6bcd3cL } }, + /* 27 */ + { { 0x48a3f5361dfcb91eL,0x83595e13646d358aL,0xbd15827b91128798L, + 0x3ce612b82187757aL,0x873150a161bd7372L,0xf4684530b662f568L }, + { 0x8833950b401896f6L,0xe11cb89a77f3e090L,0xb2f12cac48e7f4a5L, + 0x313dd769f606677eL,0xfdcf08b316579f93L,0x6429cec946b8f22bL } }, + /* 28 */ + { { 0x4984dd54bb75f9a4L,0x4aef06b929d3b570L,0xb5f84ca23d6e4c1eL, + 0x24c61c11b083ef35L,0xce4a7392392ca9ffL,0x865d65176730a800L }, + { 0xca3dfe76722b4a2bL,0x12c04bf97b083e0eL,0x803ce5b51b86b8a5L, + 0x3fc7632d6a7e3e0cL,0xc89970c2c81adbe4L,0x3cbcd3ad120e16b1L } }, + /* 29 */ + { { 0xfbfb4cc7ec30ce93L,0x10ed6c7db72720a2L,0xec675bf747b55500L, + 0x90725903333ff7c3L,0xc7c3973e5075bfc0L,0xb049ecb007acf31bL }, + { 0xb4076eaf4f58839cL,0x101896daa2b05e4fL,0x3f6033b0ab40c66eL, + 0x19ee9eebc8d864baL,0xeb6cf15547bf6d2aL,0x8e5a9663f826477dL } }, + /* 30 */ + { { 0x69e62fddf7fbd5e1L,0x38ecfe5476912b1dL,0x845a3d56d1da3bfbL, + 0x0494950e1c86f0d4L,0x83cadbf93bc36ce8L,0x41fce5724fccc8d1L }, + { 0x05f939c28332c144L,0xb17f248b0871e46eL,0x3d8534e266e8aff6L, + 0x1d06f1dc3b85c629L,0xdb06a32ea3131b73L,0xf295184d8b3f64e5L } }, + /* 31 */ + { { 0xd9653ff736ddc103L,0x25f43e3795ef606fL,0x09e301fcfe06dce8L, + 0x85af234130b6eebfL,0x79b12b530ff56b20L,0x9b4fb499fe9a3c6bL }, + { 0x0154f89251d27ac2L,0xd33167e356ca5389L,0x7828ec1fafc065a6L, + 0x0959a2587f746c9bL,0xb18f1be30c44f837L,0xa7946117c4132fdbL } }, + /* 32 */ + { { 0xc0426b775e3c647bL,0xbfcbd9398cf05348L,0x31d312e3172c0d3dL, + 0x5f49fde6ee754737L,0x895530f06da7ee61L,0xcf281b0ae8b3a5fbL }, + { 0xfd14973541b8a543L,0x41a625a73080dd30L,0xe2baae07653908cfL, + 0xc3d01436ba02a278L,0xa0d0222e7b21b8f8L,0xfdc270e9d7ec1297L } }, + /* 33 */ + { { 0x00873c0cbc7f41d6L,0xd976113e1b7ad641L,0x2a536ff4238443fbL, + 0x030d00e241e62e45L,0x532e98675f545fc6L,0xcd0331088e91208cL }, + { 0xd1a04c999797612cL,0xd4393e02eea674e2L,0xd56fa69ee19742a1L, + 0xdd2ab48085f0590eL,0xa5cefc5248a2243dL,0x48cc67b654383f41L } }, + /* 34 */ + { { 0x4e50430efc14ab48L,0x195b7f4f26706a74L,0x2fe8a228cc881ff6L, + 0xb1b968e2d945013dL,0x936aa5794b92162bL,0x4fb766b7364e754aL }, + { 0x13f93bca31e1ff7fL,0x696eb5cace4f2691L,0xff754bf8a2b09e02L, + 0x58f13c9ce58e3ff8L,0xb757346f1678c0b0L,0xd54200dba86692b3L } }, + /* 35 */ + { { 0x9a030bbd6dda1265L,0xf7b4f3fce89718ddL,0xa6a4931f936065b8L, + 0xbce72d875f72241cL,0x6cbb51cb65775857L,0xc71618154e993675L }, + { 0xe81a0f792ee32189L,0xef2fab26277dc0b2L,0x9e64f6feb71f469fL, + 0xb448ce33dfdaf859L,0x3f5c1c4cbe6b5df1L,0xfb8dfb001de45f7bL } }, + /* 36 */ + { { 0xc7345fa74d5bb921L,0x5c7e04be4d2b667eL,0x47ed3a80282d7a3eL, + 0x5c2777f87e47b2a4L,0x89b3b10008488e2eL,0x9aad77c2b2eb5b45L }, + { 0xd681bca7daac34aeL,0x2452e4e526afb326L,0x0c88792441a1ee14L, + 0x743b04d4c2407adeL,0xcb5e999bfc17a2acL,0x4dca2f824a701a06L } }, + /* 37 */ + { { 0x68e31ca61127bc1aL,0xa3edd59b17ead3beL,0x67b6b645e25f5a15L, + 0x76221794a420e15eL,0x794fd83b4b1e872eL,0x7cab3f03b2dece1bL }, + { 0x7119bf15ca9b3586L,0xa55459244d250bd7L,0x173633eacc6bcf24L, + 0x9bd308c2b1b6f884L,0x3bae06f5447d38c3L,0x54dcc135f341fe1cL } }, + /* 38 */ + { { 0x56d3598d943caf0dL,0xce044ea9225ff133L,0x9edf6a7c563fadeaL, + 0x632eb94473e8dc27L,0x814b467e3190dcabL,0x2d4f4f316dbb1e31L }, + { 0x8d69811ca143b7caL,0x4ec1ac32de7cf950L,0x223ab5fd37b5fe82L, + 0xe82616e49390f1d9L,0xabff4b2075804610L,0x11b9be15875b08f0L } }, + /* 39 */ + { { 0x4ae31a3d3bbe682cL,0xbc7c5d2674eef2ddL,0x92afd10a3c47dd40L, + 0xec7e0a3bc14ab9e1L,0x6a6c3dd1b2e495e4L,0x085ee5e9309bcd85L }, + { 0xf381a9088c2e67fdL,0x32083a80e261eaf2L,0x0fcd6a4996deee15L, + 0xe3b8fb035e524c79L,0x8dc360d91d5b08b9L,0x3a06e2c87f26719fL } }, + /* 40 */ + { { 0x5cd9f5a87237cac0L,0x93f0b59d43586794L,0x4384a764e94f6c4eL, + 0x8304ed2bb62782d3L,0x0b8db8b3cde06015L,0x4336dd535dbe190fL }, + { 0x5744355392ab473aL,0x031c7275be5ed046L,0x3e78678c21909aa4L, + 0x4ab7e04f99202ddbL,0x2648d2066977e635L,0xd427d184093198beL } }, + /* 41 */ + { { 0x822848f50f9b5a31L,0xbb003468baadb62aL,0x233a04723357559cL, + 0x49ef688079aee843L,0xa89867a0aeb9e1e3L,0xc151931b1f6f9a55L }, + { 0xd264eb0bad74251eL,0x37b9b2634abf295eL,0xb600921b04960d10L, + 0x0de53dbc4da77dc0L,0x01d9bab3d2b18697L,0xad54ec7af7156ddfL } }, + /* 42 */ + { { 0x8e74dc3579efdc58L,0x456bd3694ff68ddbL,0x724e74ccd32096a5L, + 0xe41cff42386783d0L,0xa04c7f217c70d8a4L,0x41199d2fe61a19a2L }, + { 0xd389a3e029c05dd2L,0x535f2a6be7e3fda9L,0x26ecf72d7c2b4df8L, + 0x678275f4fe745294L,0x6319c9cc9d23f519L,0x1e05a02d88048fc4L } }, + /* 43 */ + { { 0x75cc8e2ed4d5ffe8L,0xf8bb4896dbea17f2L,0x35059790cee3cb4aL, + 0x4c06ee85a47c6165L,0xf98fff2592935d2fL,0x34c4a57232ffd7c7L }, + { 0xc4b14806ea0376a2L,0x2ea5e7504f115e02L,0x532d76e21e55d7c0L, + 0x68dc9411f31044daL,0x9272e46571b77993L,0xadaa38bb93a8cfd5L } }, + /* 44 */ + { { 0x4bf0c7127d4ed72aL,0xda0e9264ba1f79a3L,0x48c0258bf4c39ea4L, + 0xa5394ed82a715138L,0x4af511cebf06c660L,0xfcebceefec5c37cdL }, + { 0xf23b75aa779ae8c1L,0xdeff59ccad1e606eL,0xf3f526fd22755c82L, + 0x64c5ab44bb32cefdL,0xa96e11a2915bdefdL,0xab19746a1143813eL } }, + /* 45 */ + { { 0x43c78585ec837d7dL,0xca5b6fbcb8ee0ba4L,0x34e924d9d5dbb5eeL, + 0x3f4fa104bb4f1ca5L,0x15458b72398640f7L,0x4231faa9d7f407eaL }, + { 0x53e0661ef96e6896L,0x554e4c69d03b0f9dL,0xd4fcb07b9c7858d1L, + 0x7e95279352cb04faL,0x5f5f15748974e7f7L,0x2e3fa5586b6d57c8L } }, + /* 46 */ + { { 0x42cd48036a9951a8L,0xa8b15b8842792ad0L,0x18e8bcf9abb29a73L, + 0xbfd9a092409933e8L,0x760a3594efb88dc4L,0x1441886340724458L }, + { 0x162a56ee99caedc7L,0x8fb12ecd91d101c9L,0xea671967393202daL, + 0x1aac8c4aa4ccd796L,0x7db050361cf185a8L,0x0c9f86cd8cfd095aL } }, + /* 47 */ + { { 0x9a72814710b2a556L,0x767ca964327b70b2L,0x04ed9e125e3799b7L, + 0x6781d2dc22a3eb2aL,0x5bd116eb0d9450acL,0xeccac1fca7ebe08aL }, + { 0xde68444fdc2d6e94L,0x3621f42935ecf21bL,0x14e2d54329e03a2cL, + 0x53e42cd57d3e7f0aL,0xbba26c0973ed00b9L,0x00297c39c57d2272L } }, + /* 48 */ + { { 0x3aaaab10b8243a7dL,0x6eeef93e8fa58c5bL,0xf866fca39ae7f764L, + 0x64105a2661ab04d3L,0xa3578d8a03945d66L,0xb08cd3e4791b848cL }, + { 0x45edc5f8756d2411L,0xd4a790d9a755128cL,0xc2cf096349e5f6a0L, + 0xc66d267df649beaaL,0x3ce6d9688467039eL,0x50046c6b42f7816fL } }, + /* 49 */ + { { 0x92ae160266425043L,0x1ff66afdf08db890L,0x386f5a7f8f162ce5L, + 0x18d2dea0fcf5598fL,0x78372b3a1a8ca18eL,0xdf0d20eb8cd0e6f7L }, + { 0x7edd5e1d75bb4045L,0x252a47ceb96d94b7L,0xbdb293582c626776L, + 0x853c394340dd1031L,0x9dc9becf7d5f47fdL,0x27c2302fbae4044aL } }, + /* 50 */ + { { 0x2d1d208a8f2d49ceL,0x0d91aa02162df0a2L,0x9c5cce8709a07f65L, + 0xdf07238b84339012L,0x5028e2c8419442cdL,0x2dcbd35872062abaL }, + { 0xb5fbc3cbe4680967L,0x2a7bc6459f92d72cL,0x806c76e1116c369dL, + 0x5c50677a3177e8d8L,0x753739eb4569df57L,0x2d481ef636c3f40bL } }, + /* 51 */ + { { 0x1a2d39fdfea1103eL,0xeaae559295f81b17L,0xdbd0aa18f59b264aL, + 0x90c39c1acb592ee0L,0xdf62f80d9750cca3L,0xda4d8283df97cc6cL }, + { 0x0a6dd3461e201067L,0x1531f85969fb1f6bL,0x4895e5521d60121fL, + 0x0b21aab04c041c91L,0x9d896c46bcc1ccf8L,0xd24da3b33141bde7L } }, + /* 52 */ + { { 0x575a053753b0a354L,0x392ff2f40c6ddcd8L,0x0b8e8cff56157b94L, + 0x073e57bd3b1b80d1L,0x2a75e0f03fedee15L,0x752380e4aa8e6f19L }, + { 0x1f4e227c6558ffe9L,0x3a34861819ec5415L,0xab382d5ef7997085L, + 0x5e6deaffddc46ac2L,0xe5144078fc8d094cL,0xf674fe51f60e37c6L } }, + /* 53 */ + { { 0x6fb87ae5af63408fL,0xa39c36a9cd75a737L,0x7833313fcf4c618dL, + 0xfbcd4482f034c88dL,0x4469a76139b35288L,0x77a711c566b5d9c9L }, + { 0x4a695dc7944f8d65L,0xe6da5f65161aaba8L,0x8654e9c324601669L, + 0xbc8b93f528ae7491L,0x5f1d1e838f5580d8L,0x8ccf9a1acea32cc8L } }, + /* 54 */ + { { 0x28ab110c7196fee2L,0x75799d63874c8945L,0xa262934829aedaddL, + 0x9714cc7b2be88ff4L,0xf71293cfd58d60d6L,0xda6b6cb332a564e9L }, + { 0xf43fddb13dd821c2L,0xf2f2785f90dd323dL,0x91246419048489f8L, + 0x61660f26d24c6749L,0x961d9e8cc803c15cL,0x631c6158faadc4c9L } }, + /* 55 */ + { { 0xacf2ebe0fd752366L,0xb93c340e139be88bL,0x98f664850f20179eL, + 0x14820254ff1da785L,0x5278e2764f85c16eL,0xa246ee457aab1913L }, + { 0x43861eb453763b33L,0xc49f03fc45c0bc0dL,0xafff16bcad6b1ea1L, + 0xce33908b6fd49c99L,0x5c51e9bff7fde8c3L,0x076a7a39ff142c5eL } }, + /* 56 */ + { { 0x04639dfe9e338d10L,0x8ee6996ff42b411bL,0x960461d1a875cef2L, + 0x1057b6d695b4d0baL,0x27639252a906e0bcL,0x2c19f09ae1c20f8aL }, + { 0x5b8fc3f0eef4c43dL,0xe2e1b1a807a84aa9L,0x5f455528835d2bdbL, + 0x0f4aee4d207132ddL,0xe9f8338c3907f675L,0x7a874dc90e0531f0L } }, + /* 57 */ + { { 0x84b22d4597c27050L,0xbd0b8df759e70bf8L,0xb4d6740579738b9bL, + 0x47f4d5f5cd917c4fL,0x9099c4ce13ce6e33L,0x942bfd39521d0f8bL }, + { 0x5028f0f6a43b566dL,0xaf6e866921bff7deL,0x83f6f856c44232cdL, + 0x65680579f915069aL,0xd12095a2ecfecb85L,0xcf7f06aedb01ba16L } }, + /* 58 */ + { { 0x0f56e3c48ef96c80L,0xd521f2b33ddb609cL,0x2be941027dc1450dL, + 0x2d21a07102a91fe2L,0x2e6f74fa1efa37deL,0x9a9a90b8156c28a1L }, + { 0xc54ea9ea9dc7dfcbL,0xc74e66fc2c2c1d62L,0x9f23f96749d3e067L, + 0x1c7c3a4654dd38adL,0xc70058845946cee3L,0x8985636845cc045dL } }, + /* 59 */ + { { 0x29da7cd4fce73946L,0x8f697db523168563L,0x8e235e9ccba92ec6L, + 0x55d4655f9f91d3eaL,0xf3689f23aa50a6cdL,0xdcf21c2621e6a1a0L }, + { 0xcffbc82e61b818bfL,0xc74a2f96da47a243L,0x234e980a8bc1a0cfL, + 0xf35fd6b57929cb6dL,0x81468e12efe17d6cL,0xddea6ae558b2dafbL } }, + /* 60 */ + { { 0x294de8877e787b2eL,0x258acc1f39a9310dL,0x92d9714aac14265dL, + 0x18b5591c708b48a0L,0x27cc6bb0e1abbf71L,0xc0581fa3568307b9L }, + { 0x9e0f58a3f24d4d58L,0xfebe9bb8e0ce2327L,0x91fd6a419d1be702L, + 0x9a7d8a45facac993L,0xabc0a08c9e50d66dL,0x02c342f706498201L } }, + /* 61 */ + { { 0xccd71407157bdbc2L,0x72fa89c6ad0e1605L,0xb1d3da2bb92a015fL, + 0x8ad9e7cda0a3fe56L,0x160edcbd24f06737L,0x79d4db3361275be6L }, + { 0xd3d31fd95f3497c4L,0x8cafeaee04192fb0L,0xe13ca74513a50af3L, + 0x188261678c85aae5L,0xce06cea89eb556ffL,0x2eef1995bdb549f3L } }, + /* 62 */ + { { 0x8ed7d3eb50596edcL,0xaa359362905243a2L,0xa212c2c2a4b6d02bL, + 0x611fd727c4fbec68L,0x8a0b8ff7b84f733dL,0xd85a6b905f0daf0eL }, + { 0x60e899f5d4091cf7L,0x4fef2b672eff2768L,0xc1f195cb10c33964L, + 0x8275d36993626a8fL,0xc77904f40d6c840aL,0x88d8b7fd7a868acdL } }, + /* 63 */ + { { 0x85f237237bd98425L,0xd4463992c70b154eL,0xcbb00ee296687a2eL, + 0x905fdbf7c83214fdL,0x2019d29313593684L,0x0428c393ef51218eL }, + { 0x40c7623f981e909aL,0x925133857be192daL,0x48fe480f4010907eL, + 0xdd7a187c3120b459L,0xc9d7702da1fd8f3cL,0x66e4753be358efc5L } }, + /* 64 */ + { { 0x070d34e116973cf4L,0x20aee08b7e4f34f7L,0x269af9b95eb8ad29L, + 0xdde0a036a6a45ddaL,0xa18b528e63df41e0L,0x03cc71b2a260df2aL }, + { 0x24a6770aa06b1dd7L,0x5bfa9c119d2675d3L,0x73c1e2a196844432L, + 0x3660558d131a6cf0L,0xb0289c832ee79454L,0xa6aefb01c6d8ddcdL } }, + /* 65 */ + { { 0xba1464b401ab5245L,0x9b8d0b6dc48d93ffL,0x939867dc93ad272cL, + 0xbebe085eae9fdc77L,0x73ae5103894ea8bdL,0x740fc89a39ac22e1L }, + { 0x5e28b0a328e23b23L,0x2352722ee13104d0L,0xf4667a18b0a2640dL, + 0xac74a72e49bb37c3L,0x79f734f0e81e183aL,0xbffe5b6c3fd9c0ebL } }, + /* 66 */ + { { 0xb1a358f5c6a2123fL,0x927b2d95fe28df6dL,0x89702753f199d2f9L, + 0x0a73754c1a3f82dcL,0x063d029d777affe1L,0x5439817edae6d34dL }, + { 0xf7979eef6b8b83c4L,0x615cb2149d945682L,0x8f0e4facc5e57eaeL, + 0x042b89b8113047ddL,0x888356dc93f36508L,0xbf008d185fd1f32fL } }, + /* 67 */ + { { 0x8012aa244e8068dbL,0xc72cc641a5729a47L,0x3c33df2c43f0691dL, + 0xfa0573471d92145fL,0xaefc0f2fb97f7946L,0x813d75cb2f8121bfL }, + { 0x05613c724383bba6L,0xa924ce70a4224b3fL,0xe59cecbe5f2179a6L, + 0x78e2e8aa79f62b61L,0x3ac2cc3b53ad8079L,0x55518d71d8f4fa96L } }, + /* 68 */ + { { 0x03cf292200623f3bL,0x095c71115f29ebffL,0x42d7224780aa6823L, + 0x044c7ba17458c0b0L,0xca62f7ef0959ec20L,0x40ae2ab7f8ca929fL }, + { 0xb8c5377aa927b102L,0x398a86a0dc031771L,0x04908f9dc216a406L, + 0xb423a73a918d3300L,0x634b0ff1e0b94739L,0xe29de7252d69f697L } }, + /* 69 */ + { { 0x744d14008435af04L,0x5f255b1dfec192daL,0x1f17dc12336dc542L, + 0x5c90c2a7636a68a8L,0x960c9eb77704ca1eL,0x9de8cf1e6fb3d65aL }, + { 0xc60fee0d511d3d06L,0x466e2313f9eb52c7L,0x743c0f5f206b0914L, + 0x42f55bac2191aa4dL,0xcefc7c8fffebdbc2L,0xd4fa6081e6e8ed1cL } }, + /* 70 */ + { { 0xb5e405d3b0ab9645L,0xaeec7f98d5f1f711L,0x8ad42311585c2a6eL, + 0x045acb9e512c6944L,0xae106c4ea90db1c6L,0xb89f33d5898e6563L }, + { 0x43b07cd97fed2ce4L,0xf9934e17dd815b20L,0x6778d4d50a81a349L, + 0x9e616ade52918061L,0xfa06db06d7e67112L,0x1da23cf188488091L } }, + /* 71 */ + { { 0x821c46b342f2c4b5L,0x931513ef66059e47L,0x7030ae4366f50cd1L, + 0x43b536c943e7b127L,0x006258cf5fca5360L,0xe4e3ee796b557abfL }, + { 0xbb6b390024c8b22fL,0x2eb5e2c1fcbf1054L,0x937b18c9567492afL, + 0xf09432e4acf53957L,0x585f5a9d1dbf3a56L,0xf86751fdbe0887cfL } }, + /* 72 */ + { { 0x157399cb9d10e0b2L,0x1c0d595660dc51b7L,0x1d496b8a1f583090L, + 0x6658bc2688590484L,0x88c08ab703213f28L,0x8d2e0f737ae58de4L }, + { 0x9b79bc95486cfee6L,0x036a26c7e9e5bc57L,0x1ad03601cd8ae97aL, + 0x06907f87ff3a0494L,0x078f4bbf2c7eb584L,0xe3731bf57e8d0a5aL } }, + /* 73 */ + { { 0x72f2282be1cd0abeL,0xd4f9015e87efefa2L,0x9d1898066c3834bdL, + 0x9c8cdcc1b8a29cedL,0x0601b9f4fee82ebcL,0x371052bc7206a756L }, + { 0x76fa109246f32562L,0xdaad534c17351bb4L,0xc3d64c37b3636bb5L, + 0x038a8c5145d54e00L,0x301e618032c09e7cL,0x9764eae795735151L } }, + /* 74 */ + { { 0x8791b19fcbd5256aL,0x4007e0f26ca13a3bL,0x03b794604cf06904L, + 0xb18a9c22b6c17589L,0xa1cb7d7d81d45908L,0x6e13fa9d21bb68f1L }, + { 0x47183c62a71e6e16L,0x5cf0ef8ee18749edL,0x2c9c7f9b2e5ed409L, + 0x042eeacce6e117e1L,0xb86d481613fb5a7fL,0xea1cf0edc9e5feb1L } }, + /* 75 */ + { { 0x6e6573c9cea4cc9bL,0x5417961dafcec8f3L,0x804bf02aa438b6f6L, + 0xb894b03cdcd4ea88L,0xd0f807e93799571fL,0x3466a7f5862156e8L }, + { 0x51e59acd56515664L,0x55b0f93ca3c5eb0bL,0x84a06b026a4279dbL, + 0x5c850579c5fae08eL,0xcf07b8dba663a1a2L,0x49a36bbcf46ffc8dL } }, + /* 76 */ + { { 0xe47f5acc46d93106L,0x65b7ade0aa897c9cL,0x37cf4c9412d7e4beL, + 0xa2ae9b80d4b2caa9L,0x5e7ce09ce60357a3L,0x29f77667c8ecd5f9L }, + { 0xdf6868f5a8a0b1c5L,0x240858cf62978ad8L,0x0f7ac101dc0002a1L, + 0x1d28a9d7ffe9aa05L,0x744984d65b962c97L,0xa8a7c00b3d28c8b2L } }, + /* 77 */ + { { 0x7c58a852ae11a338L,0xa78613f1d1af96e7L,0x7e9767d25355cc73L, + 0x6ba37009792a2de6L,0x7d60f618124386b2L,0xab09b53111157674L }, + { 0x95a0484198eb9dd0L,0xe6c17acc15070328L,0xafc6da45489c6e49L, + 0xab45a60abb211530L,0xc58d65927d7ea933L,0xa3ef3c65095642c6L } }, + /* 78 */ + { { 0x89d420e9df010879L,0x9d25255d39576179L,0x9cdefd50e39513b6L, + 0xe4efe45bd5d1c313L,0xc0149de73f7af771L,0x55a6b4f4340ab06bL }, + { 0xf1325251ebeaf771L,0x2ab44128878d4288L,0xfcd5832e18e05afeL, + 0xef52a348cc1fb62bL,0x2bd08274c1c4792aL,0x345c5846877c6dc7L } }, + /* 79 */ + { { 0xde15ceb0bea65e90L,0x0987f72b2416d99cL,0x44db578dfd863decL, + 0xf617b74bac6a3578L,0x9e62bd7adb48e999L,0x877cae61eab1a1beL }, + { 0x23adddaa3a358610L,0x2fc4d6d1325e2b07L,0x897198f51585754eL, + 0xf741852cb392b584L,0x9927804cb55f7de1L,0xe9e6c4ed1aa8efaeL } }, + /* 80 */ + { { 0x867db63998683186L,0xfb5cf424ddcc4ea9L,0xcc9a7ffed4f0e7bdL, + 0x7c57f71c7a779f7eL,0x90774079d6b25ef2L,0x90eae903b4081680L }, + { 0xdf2aae5e0ee1fcebL,0x3ff1da24e86c1a1fL,0x80f587d6ca193edfL, + 0xa5695523dc9b9d6aL,0x7b84090085920303L,0x1efa4dfcba6dbdefL } }, + /* 81 */ + { { 0xfbd838f9e0540015L,0x2c323946c39077dcL,0x8b1fb9e6ad619124L, + 0x9612440c0ca62ea8L,0x9ad9b52c2dbe00ffL,0xf52abaa1ae197643L }, + { 0xd0e898942cac32adL,0xdfb79e4262a98f91L,0x65452ecf276f55cbL, + 0xdb1ac0d27ad23e12L,0xf68c5f6ade4986f0L,0x389ac37b82ce327dL } }, + /* 82 */ + { { 0x511188b4f8e60f5bL,0x7fe6701548aa2adaL,0xdb333cb8381abca2L, + 0xb15e6d9ddaf3fc97L,0x4b24f6eb36aabc03L,0xc59789df72a748b4L }, + { 0x26fcb8a529cf5279L,0x7a3c6bfc01ad9a6cL,0x866cf88d4b8bac9bL, + 0xf4c899899c80d041L,0xf0a0424170add148L,0x5a02f47945d81a41L } }, + /* 83 */ + { { 0xfa5c877cc1c90202L,0xd099d440f8ac7570L,0x428a5b1bd17881f7L, + 0x61e267db5b2501d7L,0xf889bf04f2e4465bL,0x4da3ae0876aa4cb8L }, + { 0x3ef0fe26e3e66861L,0x5e7729533318b86dL,0xc3c35fbc747396dfL, + 0x5115a29c439ffd37L,0xbfc4bd97b2d70374L,0x088630ea56246b9dL } }, + /* 84 */ + { { 0xcd96866db8a9e8c9L,0xa11963b85bb8091eL,0xc7f90d53045b3cd2L, + 0x755a72b580f36504L,0x46f8b39921d3751cL,0x4bffdc9153c193deL }, + { 0xcd15c049b89554e7L,0x353c6754f7a26be6L,0x79602370bd41d970L, + 0xde16470b12b176c0L,0x56ba117540c8809dL,0xe2db35c3e435fb1eL } }, + /* 85 */ + { { 0xd71e4aab6328e33fL,0x5486782baf8136d1L,0x07a4995f86d57231L, + 0xf1f0a5bd1651a968L,0xa5dc5b2476803b6dL,0x5c587cbc42dda935L }, + { 0x2b6cdb32bae8b4c0L,0x66d1598bb1331138L,0x4a23b2d25d7e9614L, + 0x93e402a674a8c05dL,0x45ac94e6da7ce82eL,0xeb9f8281e463d465L } }, + /* 86 */ + { { 0x34e0f9d1fecf5b9bL,0xa115b12bf206966aL,0x5591cf3b1eaa0534L, + 0x5f0293cbfb1558f9L,0x1c8507a41bc703a5L,0x92e6b81c862c1f81L }, + { 0xcc9ebc66cdaf24e3L,0x68917ecd72fcfc70L,0x6dc9a9308157ba48L, + 0x5d425c08b06ab2b2L,0x362f8ce736e929c4L,0x09f6f57c62e89324L } }, + /* 87 */ + { { 0x1c7d6b78d29375fbL,0xfabd851ee35d1157L,0xf6f62dcd4243ea47L, + 0x1dd924608fe30b0fL,0x08166dfaffc6e709L,0xc6c4c6930881e6a7L }, + { 0x20368f87d6a53fb0L,0x38718e9f9eb4d1f9L,0x03f08acdafd7e790L, + 0x0835eb4472fe2a1cL,0x7e05090388076e5dL,0x538f765ea638e731L } }, + /* 88 */ + { { 0x0e0249d9c2663b4bL,0xe700ab5b47cd38ddL,0xb192559d2c46559fL, + 0x8f9f74a84bcde66dL,0xad1615233e2aced5L,0xc155c0473dd03a5bL }, + { 0x346a87993be454ebL,0x66ee94db83b7dccdL,0x1f6d8378ab9d2abeL, + 0x4a396dd27733f355L,0x419bd40af53553c2L,0xd0ead98d731dd943L } }, + /* 89 */ + { { 0x908e0b0eec142408L,0x98943cb94114b310L,0x03dbf7d81742b1d7L, + 0xd270df6b693412f4L,0xc50654948f69e20cL,0xa76a90c3697e43a1L }, + { 0xe0fa33844624825aL,0x82e48c0b8acc34c2L,0x7b24bd14e9a14f2bL, + 0x4f5dd5e24db30803L,0x0c77a9e7932da0a3L,0x20db90f274c653dcL } }, + /* 90 */ + { { 0x261179b70e6c5fd9L,0xf8bec1236c982eeaL,0x47683338d4957b7eL, + 0xcc47e6640a72f66aL,0xbd54bf6a1bad9350L,0xdfbf4c6af454e95aL }, + { 0x3f7a7afa6907f4faL,0x7311fae0865ca735L,0x24737ab82a496adaL, + 0x13e425f115feb79bL,0xe9e97c50a1b93c21L,0xb26b6eac4ddd3eb5L } }, + /* 91 */ + { { 0x81cab9f52a2e5f2bL,0xf93caf29bf385ac4L,0xf4bf35c3c909963aL, + 0x081e730074c9143cL,0x3ea57fa8c281b4c5L,0xe497905c9b340741L }, + { 0xf556dd8a55ab3cfbL,0xd444b96b518db6adL,0x34f5425a5ef4b955L, + 0xdda7a3acecd26aa3L,0xb57da11bda655e97L,0x02da3effc2024c70L } }, + /* 92 */ + { { 0xe24b00366481d0d9L,0x3740dbe5818fdfe2L,0xc1fc1f45190fda00L, + 0x329c92803cf27fdeL,0x7435cb536934f43eL,0x2b505a5d7884e8feL }, + { 0x6cfcc6a6711adcc9L,0xf034325c531e21e1L,0xa2f4a9679b2a8a99L, + 0x9d5f38423c21bdffL,0xb25c781131b57d66L,0xdb5344d80b8093b9L } }, + /* 93 */ + { { 0x0d72e667ae50a2f5L,0x9b7f8d8ae4a861d1L,0xa129f70f330df1cbL, + 0xe90aa5d7e04fefc3L,0xff561ecbe72c3ae1L,0x0d8fb428cdb955faL }, + { 0xd2235f73d7663784L,0xc05baec67e2c456aL,0xe5c292e42adbfcccL, + 0x4fd17988efb110d5L,0x27e57734d19d49f3L,0x188ac4ce84f679feL } }, + /* 94 */ + { { 0x7ee344cfa796c53eL,0xbbf6074d0868009bL,0x1f1594f7474a1295L, + 0x66776edcac11632dL,0x1862278b04e2fa5aL,0x52665cf2c854a89aL }, + { 0x7e3764648104ab58L,0x167759137204fd6dL,0x86ca06a544ea1199L, + 0xaa3f765b1c9240ddL,0x5f8501a924746149L,0x7b982e30dcd251d7L } }, + /* 95 */ + { { 0xe44e9efcc15f3060L,0x5ad62f2ea87ebbe6L,0x36499d41c79500d4L, + 0xa66d6dc0336fa9d1L,0xf8afc4955afd3b1fL,0x1d8ccb24e5c9822bL }, + { 0x4031422b79d7584bL,0xc54a0580ea3f20ddL,0x3f837c8f958468c5L, + 0x3d82f110fbea7735L,0x679a87787dffe2fcL,0x48eba63b20704803L } }, + /* 96 */ + { { 0x89b10d41df46e2f6L,0x13ab57f819514367L,0x067372b91d469c87L, + 0x0c195afa4f6c5798L,0xea43a12a272c9acfL,0x9dadd8cb678abdacL }, + { 0xcce56c6be182579aL,0x86febadb2d26c2d8L,0x1c668ee12a44745cL, + 0x580acd8698dc047aL,0x5a2b79cc51b9ec2dL,0x007da6084054f6a0L } }, + /* 97 */ + { { 0x9e3ca35217b00dd0L,0x046779cb0e81a7a6L,0xb999fef3d482d871L, + 0xe6f38134d9233fbcL,0x112c3001f48cd0e0L,0x934e75763c6c66aeL }, + { 0xb44d4fc3d73234dcL,0xfcae2062864eafc1L,0x843afe2526bef21aL, + 0x61355107f3b75fdfL,0x8367a5aa794c2e6bL,0x3d2629b18548a372L } }, + /* 98 */ + { { 0x6230618f437cfaf8L,0x5b8742cb2032c299L,0x949f72472293643aL, + 0xb8040f1a09464f79L,0x049462d24f254143L,0xabd6b522366c7e76L }, + { 0x119b392bd5338f55L,0x1a80a9ce01495a0cL,0xf3118ca7f8d7537eL, + 0xb715adc26bf4b762L,0x24506165a8482b6cL,0xd958d7c696a7c84dL } }, + /* 99 */ + { { 0x9ad8aa87bdc21f31L,0xadb3cab48063e58cL,0xefd86283b07dd7b8L, + 0xc7b9b7621be7c6b4L,0x2ef58741015582deL,0xc970c52e299addf3L }, + { 0x78f02e2a22f24d66L,0xefec1d1074cc100aL,0xaf2a6a3909316e1aL, + 0xce7c22055849dd49L,0x9c1fe75c96bffc4cL,0xcad98fd27ba06ec0L } }, + /* 100 */ + { { 0xed76e2d0b648b73eL,0xa9f92ce51cfd285eL,0xa8c86c062ed13de1L, + 0x1d3a574ea5191a93L,0x385cdf8b1ad1b8bfL,0xbbecc28a47d2cfe3L }, + { 0x98d326c069cec548L,0x4f5bc1ddf240a0b2L,0x241a706229057236L, + 0x0fc6e9c5c68294a4L,0x4d04838ba319f17aL,0x8b612cf19ffc1c6fL } }, + /* 101 */ + { { 0x9bb0b5014c3830ebL,0x3d08f83c8ee0d0c5L,0xa4a6264279ba9389L, + 0x5d5d40449cbc2914L,0xae9eb83e074c46f0L,0x63bb758f74ead7d6L }, + { 0x1c40d2eac6bb29e0L,0x95aa2d874b02f41eL,0x9298917553cb199aL, + 0xdd91bafe51584f6dL,0x3715efb931a1aaecL,0xc1b6ae5b46780f9eL } }, + /* 102 */ + { { 0xcded3e4b42772f41L,0x3a700d5d3bcb79d1L,0x4430d50e80feee60L, + 0x444ef1fcf5e5d4bbL,0xc660194fe6e358ffL,0xe68a2f326a91b43cL }, + { 0x5842775c977fe4d2L,0x78fdef5c7e2a41ebL,0x5f3bec02ff8df00eL, + 0xf4b840cd5852525dL,0x0870483a4e6988bdL,0x39499e39cc64b837L } }, + /* 103 */ + { { 0xfc05de80b08df5feL,0x0c12957c63ba0362L,0xea379414d5cf1428L, + 0xc559132a54ef6216L,0x33d5f12fb9e65cf8L,0x09c602781695d663L }, + { 0x3ac1ced461f7a2fbL,0xdd838444d4f5eeb8L,0x82a38c6c8318fcadL, + 0x315be2e5e9f1a864L,0x317b5771442daf47L,0x81b5904a95aa5f9eL } }, + /* 104 */ + { { 0x6b6b1c508b21d232L,0x87f3dbc08c2cba75L,0xa7e74b46ae9f0fafL, + 0x036a0985bb7b8079L,0x4f185b908d974a25L,0x5aa7cef0d9af5ec9L }, + { 0xe0566a7057dcfffcL,0x6ea311dab8453225L,0x72ea1a8d23368aa9L, + 0xed9b208348cd552dL,0xb987967cc80ea435L,0xad735c756c104173L } }, + /* 105 */ + { { 0xaea85ab3cee76ef4L,0x44997444af1d2b93L,0x0851929beacb923fL, + 0xb080b59051e3bc0cL,0xc4ee1d8659be68a2L,0xf00de21964b26cdaL }, + { 0x8d7fb5c0f2e90d4dL,0x00e219a777d9ec64L,0xc4e6febd5d1c491cL, + 0x080e37541a8f4585L,0x4a9b86c848d2af9cL,0x2ed70db6b6679851L } }, + /* 106 */ + { { 0xaee44116586f25cbL,0xf7b6861fa0fcf70fL,0x55d2cd2018a350e8L, + 0x861bf3e592dc286fL,0x9ab18ffa6226aba7L,0xd15827bea9857b03L }, + { 0x26c1f54792e6acefL,0x422c63c8ac1fbac3L,0xa2d8760dfcbfd71dL, + 0x35f6a539b2511224L,0xbaa88fa1048d1a21L,0x49f1abe9ebf999dbL } }, + /* 107 */ + { { 0x16f9f4f4f7492b73L,0xcf28ec1ecb392b1aL,0x45b130d469ca6ffcL, + 0x28ba8d40b72efa58L,0xace987c75ca066f5L,0x3e3992464ad022ebL }, + { 0x63a2d84e752555bbL,0xaaa93b4a9c2ae394L,0xcd80424ec89539caL, + 0x6d6b5a6daa119a99L,0xbd50334c379f2629L,0x899e925eef3cc7d3L } }, + /* 108 */ + { { 0xb7ff3651bf825dc4L,0x0f741cc440b9c462L,0x771ff5a95cc4fb5bL, + 0xcb9e9c9b47fd56feL,0xbdf053db5626c0d3L,0xa97ce675f7e14098L }, + { 0x68afe5a36c934f5eL,0x6cd5e148ccefc46fL,0xc7758570d7a88586L, + 0x49978f5edd558d40L,0xa1d5088a64ae00c1L,0x58f2a720f1d65bb2L } }, + /* 109 */ + { { 0x66fdda4a3e4daedbL,0x38318c1265d1b052L,0x28d910a24c4bbf5cL, + 0x762fe5c478a9cd14L,0x08e5ebaad2cc0aeeL,0xd2cdf257ca0c654cL }, + { 0x48f7c58b08b717d2L,0x3807184a386cd07aL,0x3240f626ae7d0112L, + 0x03e9361bc43917b0L,0xf261a87620aea018L,0x53f556a47e1e6372L } }, + /* 110 */ + { { 0xc84cee562f512a90L,0x24b3c0041b0ea9f1L,0x0ee15d2de26cc1eaL, + 0xd848762cf0c9ef7dL,0x1026e9c5d5341435L,0x8f5b73dcfdb16b31L }, + { 0x1f69bef2d2c75d95L,0x8d33d581be064ddaL,0x8c024c1257ed35e6L, + 0xf8d435f9c309c281L,0xfd295061d6960193L,0x66618d78e9e49541L } }, + /* 111 */ + { { 0x571cfd458ce382deL,0x175806eede900ddeL,0x6184996534aba3b5L, + 0xe899778ade7aec95L,0xe8f00f6eff4aa97fL,0xae971cb5010b0c6dL }, + { 0x1827eebc3af788f1L,0xd46229ffe413fe2dL,0x8a15455b4741c9b4L, + 0x5f02e690f8e424ebL,0x40a1202edae87712L,0x49b3bda264944f6dL } }, + /* 112 */ + { { 0xd63c6067035b2d69L,0xb507150d6bed91b0L,0x1f35f82f7afb39b2L, + 0xb9bd9c0116012b66L,0x00d97960ed0a5f50L,0xed7054512716f7c9L }, + { 0x1576eff4127abdb4L,0x6850d698f01e701cL,0x9fa7d7493fc87e2fL, + 0x0b6bcc6fb0ce3e48L,0xf4fbe1f5f7d8c1c0L,0xcf75230e02719cc6L } }, + /* 113 */ + { { 0x6761d6c2722d94edL,0xd1ec3f213718820eL,0x65a40b7025d0e7c6L, + 0xd67f830ebaf3cf31L,0x633b3807b93ea430L,0x17faa0ea0bc96c69L }, + { 0xe6bf3482df866b98L,0x205c1ee9a9db52d4L,0x51ef9bbdff9ab869L, + 0x3863dad175eeb985L,0xef216c3bd3cf442aL,0x3fb228e3f9c8e321L } }, + /* 114 */ + { { 0x94f9b70c0760ac07L,0xf3c9ccae9d79bf4dL,0x73cea084c5ffc83dL, + 0xef50f943dc49c38eL,0xf467a2aebc9e7330L,0x5ee534b644ea7fbaL }, + { 0x20cb627203609e7fL,0x0984435562fdc9f0L,0xaf5c8e580f1457f7L, + 0xd1f50a6cb4b25941L,0x77cb247c2ec82395L,0xa5f3e1e5da3dca33L } }, + /* 115 */ + { { 0x023489d67d85fa94L,0x0ba405372db9ce47L,0x0fdf7a1faed7aad1L, + 0xa57b0d739a4ccb40L,0x48fcec995b18967cL,0xf30b5b6eb7274d24L }, + { 0x7ccb4773c81c5338L,0xb85639e6a3ed6bd0L,0x7d9df95f1d56eadaL, + 0xe256d57f0a1607adL,0x6da7ffdc957574d6L,0x65f8404601c7a8c4L } }, + /* 116 */ + { { 0x8d45d0cbcba1e7f1L,0xef0a08c002b55f64L,0x771ca31b17e19892L, + 0xe1843ecb4885907eL,0x67797ebc364ce16aL,0x816d2b2d8df4b338L }, + { 0xe870b0e539aa8671L,0x9f0db3e4c102b5f5L,0x342966591720c697L, + 0x0ad4c89e613c0d2aL,0x1af900b2418ddd61L,0xe087ca72d336e20eL } }, + /* 117 */ + { { 0x222831ffaba10079L,0x0dc5f87b6d64fff2L,0x445479073e8cb330L, + 0xe815aaa2702a33fbL,0x338d6b2e5fba3215L,0x0f7535cb79f549c8L }, + { 0x471ecd972ee95923L,0x1e868b37c6d1c09fL,0x2bc7b8ecc666ef4eL, + 0xf5416589808a4bfcL,0xf23e9ee23fbc4d2eL,0x4357236c2d75125bL } }, + /* 118 */ + { { 0xfe176d95ba9cdb1bL,0x45a1ca012f82791eL,0x97654af24de4cca2L, + 0xbdbf9d0e5cc4bcb9L,0xf6a7df50ad97ac0aL,0xc52112b061359fd6L }, + { 0x696d9ce34f05eae3L,0x903adc02e943ac2bL,0xa90753470848be17L, + 0x1e20f1702a3973e5L,0xe1aacc1c6feb67e9L,0x2ca0ac32e16bc6b9L } }, + /* 119 */ + { { 0xffea12e4ef871eb5L,0x94c2f25da8bf0a7aL,0x4d1e4c2a78134eaaL, + 0x11ed16fb0360fb10L,0x4029b6db85fc11beL,0x5e9f7ab7f4d390faL }, + { 0x5076d72f30646612L,0xa0afed1ddda1d0d8L,0x2902225785a1d103L, + 0xcb499e174e276bcdL,0x16d1da7151246c3dL,0xc72d56d3589a0443L } }, + /* 120 */ + { { 0xdf5ffc74dae5bb45L,0x99068c4a261bd6dcL,0xdc0afa7aaa98ec7bL, + 0xedd2ee00f121e96dL,0x163cc7be1414045cL,0xb0b1bbce335af50eL }, + { 0xd440d78501a06293L,0xcdebab7c6552e644L,0x48cb8dbc8c757e46L, + 0x81f9cf783cabe3cbL,0xddd02611b123f59aL,0x3dc7b88eeeb3784dL } }, + /* 121 */ + { { 0xe1b8d398c4741456L,0xa9dfa9026032a121L,0x1cbfc86d1263245bL, + 0xf411c7625244718cL,0x96521d5405b0fc54L,0x1afab46edbaa4985L }, + { 0xa75902ba8674b4adL,0x486b43ad5ad87d12L,0x72b1c73636e0d099L, + 0x39890e07bb6cd6d6L,0x8128999c59bace4eL,0xd8da430b7b535e33L } }, + /* 122 */ + { { 0x39f65642c6b75791L,0x050947a621806bfbL,0x0ca3e3701362ef84L, + 0x9bc60aed8c3d2391L,0x9b488671732e1ddcL,0x12d10d9ea98ee077L }, + { 0xb6f2822d3651b7dcL,0x6345a5ba80abd138L,0x62033262472d3c84L, + 0xd54a1d40acc57527L,0x6ea46b3a424447cbL,0x5bc410572fb1a496L } }, + /* 123 */ + { { 0xe70c57a3a751cd0eL,0x190d8419eba3c7d6L,0xb1c3bee79d47d55aL, + 0xda941266f912c6d8L,0x12e9aacc407a6ad6L,0xd6ce5f116e838911L }, + { 0x063ca97b70e1f2ceL,0xa3e47c728213d434L,0xa016e24184df810aL, + 0x688ad7b0dfd881a4L,0xa37d99fca89bf0adL,0xd8e3f339a23c2d23L } }, + /* 124 */ + { { 0xbdf53163750bed6fL,0x808abc3283e68b0aL,0x85a366275bb08a33L, + 0xf72a3a0f6b0e4abeL,0xf7716d19faf0c6adL,0x22dcc0205379b25fL }, + { 0x7400bf8df9a56e11L,0x6cb8bad756a47f21L,0x7c97176f7a6eb644L, + 0xe8fd84f7d1f5b646L,0x98320a9444ddb054L,0x07071ba31dde86f5L } }, + /* 125 */ + { { 0x6fdfa0e598f8fcb9L,0x89cec8e094d0d70cL,0xa0899397106d20a8L, + 0x915bfb9aba8acc9cL,0x1370c94b5507e01cL,0x83246a608a821ffbL }, + { 0xa8273a9fbe3c378fL,0x7e54478935a25be9L,0x6cfa49724dd929d7L, + 0x987fed9d365bd878L,0x4982ac945c29a7aeL,0x4589a5d75ddd7ec5L } }, + /* 126 */ + { { 0x9fabb174a95540a9L,0x7cfb886f0162c5b0L,0x17be766bea3dee18L, + 0xff7da41fe88e624cL,0xad0b71eb8b919c38L,0x86a522e0f31ff9a9L }, + { 0xbc8e6f72868bc259L,0x6130c6383ccef9e4L,0x09f1f4549a466555L, + 0x8e6c0f0919b2bfb4L,0x945c46c90ca7bb22L,0xacd871684dafb67bL } }, + /* 127 */ + { { 0x090c72ca10c53841L,0xc20ae01b55a4fcedL,0x03f7ebd5e10234adL, + 0xb3f42a6a85892064L,0xbdbc30c0b4a14722L,0x971bc4378ca124ccL }, + { 0x6f79f46d517ff2ffL,0x6a9c96e2ecba947bL,0x5e79f2f462925122L, + 0x30a96bb16a4e91f1L,0x1147c9232d4c72daL,0x65bc311f5811e4dfL } }, + /* 128 */ + { { 0x87c7dd7d139b3239L,0x8b57824e4d833baeL,0xbcbc48789fff0015L, + 0x8ffcef8b909eaf1aL,0x9905f4eef1443a78L,0x020dd4a2e15cbfedL }, + { 0xca2969eca306d695L,0xdf940cadb93caf60L,0x67f7fab787ea6e39L, + 0x0d0ee10ff98c4fe5L,0xc646879ac19cb91eL,0x4b4ea50c7d1d7ab4L } }, + /* 129 */ + { { 0x19e409457a0db57eL,0xe6017cad9a8c9702L,0xdbf739e51be5cff9L, + 0x3646b3cda7a938a2L,0x0451108568350dfcL,0xad3bd6f356e098b5L }, + { 0x935ebabfee2e3e3eL,0xfbd01702473926cbL,0x7c735b029e9fb5aaL, + 0xc52a1b852e3feff0L,0x9199abd3046b405aL,0xe306fcec39039971L } }, + /* 130 */ + { { 0xd6d9aec823e4712cL,0x7ca8376cc3c198eeL,0xe6d8318731bebd8aL, + 0xed57aff3d88bfef3L,0x72a645eecf44edc7L,0xd4e63d0b5cbb1517L }, + { 0x98ce7a1cceee0ecfL,0x8f0126335383ee8eL,0x3b879078a6b455e8L, + 0xcbcd3d96c7658c06L,0x721d6fe70783336aL,0xf21a72635a677136L } }, + /* 131 */ + { { 0x19d8b3cd9586ba11L,0xd9e0aeb28a5c0480L,0xe4261dbf2230ef5cL, + 0x095a9dee02e6bf09L,0x8963723c80dc7784L,0x5c97dbaf145157b1L }, + { 0x97e744344bc4503eL,0x0fb1cb3185a6b370L,0x3e8df2becd205d4bL, + 0x497dd1bcf8f765daL,0x92ef95c76c988a1aL,0x3f924baa64dc4cfaL } }, + /* 132 */ + { { 0x6bf1b8dd7268b448L,0xd4c28ba1efd79b94L,0x2fa1f8c8e4e3551fL, + 0x769e3ad45c9187a9L,0x28843b4d40326c0dL,0xfefc809450d5d669L }, + { 0x30c85bfd90339366L,0x4eeb56f15ccf6c3aL,0x0e72b14928ccd1dcL, + 0x73ee85b5f2ce978eL,0xcdeb2bf33165bb23L,0x8106c9234e410abfL } }, + /* 133 */ + { { 0xc8df01617d02f4eeL,0x8a78154718e21225L,0x4ea895eb6acf9e40L, + 0x8b000cb56e5a633dL,0xf31d86d57e981ffbL,0xf5c8029c4475bc32L }, + { 0x764561ce1b568973L,0x2f809b81a62996ecL,0x9e513d64da085408L, + 0xc27d815de61ce309L,0x0da6ff99272999e0L,0xbd284779fead73f7L } }, + /* 134 */ + { { 0x6033c2f99b1cdf2bL,0x2a99cf06bc5fa151L,0x7d27d25912177b3bL, + 0xb1f15273c4485483L,0x5fd57d81102e2297L,0x3d43e017c7f6acb7L }, + { 0x41a8bb0b3a70eb28L,0x67de2d8e3e80b06bL,0x09245a4170c28de5L, + 0xad7dbcb1a7b26023L,0x70b08a352cbc6c1eL,0xb504fb669b33041fL } }, + /* 135 */ + { { 0xa8e85ab5f97a27c2L,0x6ac5ec8bc10a011bL,0x55745533ffbcf161L, + 0x01780e8565790a60L,0xe451bf8599ee75b0L,0x8907a63b39c29881L }, + { 0x76d46738260189edL,0x284a443647bd35cbL,0xd74e8c4020cab61eL, + 0x6264bf8c416cf20aL,0xfa5a6c955fd820ceL,0xfa7154d0f24bb5fcL } }, + /* 136 */ + { { 0x18482cec9b3f5034L,0x962d445acd9e68fdL,0x266fb1d695746f23L, + 0xc66ade5a58c94a4bL,0xdbbda826ed68a5b6L,0x05664a4d7ab0d6aeL }, + { 0xbcd4fe51025e32fcL,0x61a5aebfa96df252L,0xd88a07e231592a31L, + 0x5d9d94de98905517L,0x96bb40105fd440e7L,0x1b0c47a2e807db4cL } }, + /* 137 */ + { { 0x5c2a6ac808223878L,0xba08c269e65a5558L,0xd22b1b9b9bbc27fdL, + 0x919171bf72b9607dL,0x9ab455f9e588dc58L,0x6d54916e23662d93L }, + { 0x8da8e9383b1de0c1L,0xa84d186a804f278fL,0xbf4988ccd3461695L, + 0xf5eae3bee10eb0cbL,0x1ff8b68fbf2a66edL,0xa68daf67c305b570L } }, + /* 138 */ + { { 0xc1004cff44b2e045L,0x91b5e1364b1c05d4L,0x53ae409088a48a07L, + 0x73fb2995ea11bb1aL,0x320485703d93a4eaL,0xcce45de83bfc8a5fL }, + { 0xaff4a97ec2b3106eL,0x9069c630b6848b4fL,0xeda837a6ed76241cL, + 0x8a0daf136cc3f6cfL,0x199d049d3da018a8L,0xf867c6b1d9093ba3L } }, + /* 139 */ + { { 0xe4d42a5656527296L,0xae26c73dce71178dL,0x70a0adac6c251664L, + 0x813483ae5dc0ae1dL,0x7574eacddaab2dafL,0xc56b52dcc2d55f4fL }, + { 0x872bc16795f32923L,0x4be175815bdd2a89L,0x9b57f1e7a7699f00L, + 0x5fcd9c723ac2de02L,0x83af3ba192377739L,0xa64d4e2bfc50b97fL } }, + /* 140 */ + { { 0x2172dae20e552b40L,0x62f49725d34d52e8L,0x7930ee4007958f98L, + 0x56da2a90751fdd74L,0xf1192834f53e48c3L,0x34d2ac268e53c343L }, + { 0x1073c21813111286L,0x201dac14da9d9827L,0xec2c29dbee95d378L, + 0x9316f1191f3ee0b1L,0x7890c9f0544ce71cL,0xd77138af27612127L } }, + /* 141 */ + { { 0x78045e6d3b4ad1cdL,0xcd86b94e4aa49bc1L,0x57e51f1dfd677a16L, + 0xd9290935fa613697L,0x7a3f959334f4d893L,0x8c9c248b5d5fcf9bL }, + { 0x9f23a4826f70d4e9L,0x1727345463190ae9L,0x4bdd7c135b081a48L, + 0x1e2de38928d65271L,0x0bbaaa25e5841d1fL,0xc4c18a79746772e5L } }, + /* 142 */ + { { 0x10ee2681593375acL,0x4f3288be7dd5e113L,0x9a97b2fb240f3538L, + 0xfa11089f1de6b1e2L,0x516da5621351bc58L,0x573b61192dfa85b5L }, + { 0x89e966836cba7df5L,0xf299be158c28ab40L,0xe91c9348ad43fcbfL, + 0xe9bbc7cc9a1cefb3L,0xc8add876738b2775L,0x6e3b1f2e775eaa01L } }, + /* 143 */ + { { 0x0365a888b677788bL,0x634ae8c43fd6173cL,0x304987619e498dbeL, + 0x08c43e6dc8f779abL,0x068ae3844c09aca9L,0x2380c70b2018d170L }, + { 0xcf77fbc3a297c5ecL,0xdacbc853ca457948L,0x3690de04336bec7eL, + 0x26bbac6414eec461L,0xd1c23c7e1f713abfL,0xf08bbfcde6fd569eL } }, + /* 144 */ + { { 0x5f8163f484770ee3L,0x0e0c7f94744a1706L,0x9c8f05f7e1b2d46dL, + 0x417eafe7d01fd99aL,0x2ba15df511440e5bL,0xdc5c552a91a6fbcfL }, + { 0x86271d74a270f721L,0x32c0a075a004485bL,0x9d1a87e38defa075L, + 0xb590a7acbf0d20feL,0x430c41c28feda1f5L,0x454d287958f6ec24L } }, + /* 145 */ + { { 0x52b7a6357c525435L,0x3d9ef57f37c4bdbcL,0x2bb93e9edffcc475L, + 0xf7b8ba987710f3beL,0x42ee86da21b727deL,0x55ac3f192e490d01L }, + { 0x487e3a6ec0c1c390L,0x036fb345446cde7bL,0x089eb276496ae951L, + 0xedfed4d971ed1234L,0x661b0dd5900f0b46L,0x11bd6f1b8582f0d3L } }, + /* 146 */ + { { 0x5cf9350f076bc9d1L,0x15d903becf3cd2c3L,0x21cfc8c225af031cL, + 0xe0ad32488b1cc657L,0xdd9fb96370014e87L,0xf0f3a5a1297f1658L }, + { 0xbb908fbaf1f703aaL,0x2f9cc4202f6760baL,0x00ceec6666a38b51L, + 0x4deda33005d645daL,0xb9cf5c72f7de3394L,0xaeef65021ad4c906L } }, + /* 147 */ + { { 0x0583c8b17a19045dL,0xae7c3102d052824cL,0x2a234979ff6cfa58L, + 0xfe9dffc962c733c0L,0x3a7fa2509c0c4b09L,0x516437bb4fe21805L }, + { 0x9454e3d5c2a23ddbL,0x0726d887289c104eL,0x8977d9184fd15243L, + 0xc559e73f6d7790baL,0x8fd3e87d465af85fL,0xa2615c745feee46bL } }, + /* 148 */ + { { 0xc8d607a84335167dL,0x8b42d804e0f5c887L,0x5f9f13df398d11f9L, + 0x5aaa508720740c67L,0x83da9a6aa3d9234bL,0xbd3a5c4e2a54bad1L }, + { 0xdd13914c2db0f658L,0x29dcb66e5a3f373aL,0xbfd62df55245a72bL, + 0x19d1802391e40847L,0xd9df74dbb136b1aeL,0x72a06b6b3f93bc5bL } }, + /* 149 */ + { { 0x6da19ec3ad19d96fL,0xb342daa4fb2a4099L,0x0e61633a662271eaL, + 0x3bcece81ce8c054bL,0x7cc8e0618bd62dc6L,0xae189e19ee578d8bL }, + { 0x73e7a25ddced1eedL,0xc1257f0a7875d3abL,0x2cb2d5a21cfef026L, + 0xd98ef39bb1fdf61cL,0xcd8e6f6924e83e6cL,0xd71e7076c7b7088bL } }, + /* 150 */ + { { 0x339368309d4245bfL,0x22d962172ac2953bL,0xb3bf5a8256c3c3cdL, + 0x50c9be910d0699e8L,0xec0944638f366459L,0x6c056dba513b7c35L }, + { 0x687a6a83045ab0e3L,0x8d40b57f445c9295L,0x0f345048a16f5954L, + 0x64b5c6393d8f0a87L,0x106353a29f71c5e2L,0xdd58b475874f0dd4L } }, + /* 151 */ + { { 0x67ec084f62230c72L,0xf14f6cca481385e3L,0xf58bb4074cda7774L, + 0xe15011b1aa2dbb6bL,0xd488369d0c035ab1L,0xef83c24a8245f2fdL }, + { 0xfb57328f9fdc2538L,0x79808293191fe46aL,0xe28f5c4432ede548L, + 0x1b3cda99ea1a022cL,0x39e639b73df2ec7fL,0x77b6272b760e9a18L } }, + /* 152 */ + { { 0x2b1d51bda65d56d5L,0x3a9b71f97ea696e0L,0x95250ecc9904f4c4L, + 0x8bc4d6ebe75774b7L,0x0e343f8aeaeeb9aaL,0xc473c1d1930e04cbL }, + { 0x282321b1064cd8aeL,0xf4b4371e5562221cL,0xc1cc81ecd1bf1221L, + 0xa52a07a9e2c8082fL,0x350d8e59ba64a958L,0x29e4f3de6fb32c9aL } }, + /* 153 */ + { { 0x0aa9d56cba89aaa5L,0xf0208ac0c4c6059eL,0x7400d9c6bd6ddca4L, + 0xb384e475f2c2f74aL,0x4c1061fcb1562dd3L,0x3924e2482e153b8dL }, + { 0xf38b8d98849808abL,0x29bf3260a491aa36L,0x85159ada88220edeL, + 0x8b47915bbe5bc422L,0xa934d72ed7300967L,0xc4f303982e515d0dL } }, + /* 154 */ + { { 0xe3e9ee421b1de38bL,0xa124e25a42636760L,0x90bf73c090165b1aL, + 0x21802a34146434c5L,0x54aa83f22e1fa109L,0x1d4bd03ced9c51e9L }, + { 0xc2d96a38798751e6L,0xed27235f8c3507f5L,0xb5fb80e2c8c24f88L, + 0xf873eefad37f4f78L,0x7229fd74f224ba96L,0x9dcd91999edd7149L } }, + /* 155 */ + { { 0xee9f81a64e94f22aL,0xe5609892f71ec341L,0x6c818ddda998284eL, + 0x9fd472953b54b098L,0x47a6ac030e8a7cc9L,0xde684e5eb207a382L }, + { 0x4bdd1ecd2b6b956bL,0x09084414f01b3583L,0xe2f80b3255233b14L, + 0x5a0fec54ef5ebc5eL,0x74cf25e6bf8b29a2L,0x1c757fa07f29e014L } }, + /* 156 */ + { { 0x1bcb5c4aeb0fdfe4L,0xd7c649b3f0899367L,0xaef68e3f05bc083bL, + 0x57a06e46a78aa607L,0xa2136ecc21223a44L,0x89bd648452f5a50bL }, + { 0x724411b94455f15aL,0x23dfa97008a9c0fdL,0x7b0da4d16db63befL, + 0x6f8a7ec1fb162443L,0xc1ac9ceee98284fbL,0x085a582b33566022L } }, + /* 157 */ + { { 0x15cb61f9ec1f138aL,0x11c9a230668f0c28L,0xac829729df93f38fL, + 0xcef256984048848dL,0x3f686da02bba8fbfL,0xed5fea78111c619aL }, + { 0x9b4f73bcd6d1c833L,0x5095160686e7bf80L,0xa2a73508042b1d51L, + 0x9ef6ea495fb89ec2L,0xf1008ce95ef8b892L,0x78a7e6849ae8568bL } }, + /* 158 */ + { { 0x3fe83a7c10470cd8L,0x92734682f86df000L,0xb5dac06bda9409b5L, + 0x1e7a966094939c5fL,0xdec6c1505cc116dcL,0x1a52b40866bac8ccL }, + { 0x5303a3656e864045L,0x45eae72a9139efc1L,0x83bec6466f31d54fL, + 0x2fb4a86f6e958a6dL,0x6760718e4ff44030L,0x008117e3e91ae0dfL } }, + /* 159 */ + { { 0x5d5833ba384310a2L,0xbdfb4edc1fd6c9fcL,0xb9a4f102849c4fb8L, + 0xe5fb239a581c1e1fL,0xba44b2e7d0a9746dL,0x78f7b7683bd942b9L }, + { 0x076c8ca1c87607aeL,0x82b23c2ed5caaa7eL,0x6a581f392763e461L, + 0xca8a5e4a3886df11L,0xc87e90cf264e7f22L,0x04f74870215cfcfcL } }, + /* 160 */ + { { 0x5285d116141d161cL,0x67cd2e0e93c4ed17L,0x12c62a647c36187eL, + 0xf5329539ed2584caL,0xc4c777c442fbbd69L,0x107de7761bdfc50aL }, + { 0x9976dcc5e96beebdL,0xbe2aff95a865a151L,0x0e0a9da19d8872afL, + 0x5e357a3da63c17ccL,0xd31fdfd8e15cc67cL,0xc44bbefd7970c6d8L } }, + /* 161 */ + { { 0x703f83e24c0c62f1L,0x9b1e28ee4e195572L,0x6a82858bfe26ccedL, + 0xd381c84bc43638faL,0x94f72867a5ba43d8L,0x3b4a783d10b82743L }, + { 0xee1ad7b57576451eL,0xc3d0b59714b6b5c8L,0x3dc30954fcacc1b8L, + 0x55df110e472c9d7bL,0x97c86ed702f8a328L,0xd043341388dc098fL } }, + /* 162 */ + { { 0x1a60d1522ca8f2feL,0x61640948491bd41fL,0x6dae29a558dfe035L, + 0x9a615bea278e4863L,0xbbdb44779ad7c8e5L,0x1c7066302ceac2fcL }, + { 0x5e2b54c699699b4bL,0xb509ca6d239e17e8L,0x728165feea063a82L, + 0x6b5e609db6a22e02L,0x12813905b26ee1dfL,0x07b9f722439491faL } }, + /* 163 */ + { { 0x1592ec1448ff4e49L,0x3e4e9f176d644129L,0x7acf82881156acc0L, + 0x5aa34ba8bb092b0bL,0xcd0f90227d38393dL,0x416724ddea4f8187L }, + { 0x3c4e641cc0139e73L,0xe0fe46cf91e4d87dL,0xedb3c792cab61f8aL, + 0x4cb46de4d3868753L,0xe449c21d20f1098aL,0x5e5fd059f5b8ea6eL } }, + /* 164 */ + { { 0x7fcadd4675856031L,0x89c7a4cdeaf2fbd0L,0x1af523ce7a87c480L, + 0xe5fc109561d9ae90L,0x3fb5864fbcdb95f5L,0xbeb5188ebb5b2c7dL }, + { 0x3d1563c33ae65825L,0x116854c40e57d641L,0x11f73d341942ebd3L, + 0x24dc5904c06955b3L,0x8a0d4c83995a0a62L,0xfb26b86d5d577b7dL } }, + /* 165 */ + { { 0xc53108e7c686ae17L,0x9090d739d1c1da56L,0x4583b0139aec50aeL, + 0xdd9a088ba49a6ab2L,0x28192eeaf382f850L,0xcc8df756f5fe910eL }, + { 0x877823a39cab7630L,0x64984a9afb8e7fc1L,0x5448ef9c364bfc16L, + 0xbbb4f871c44e2a9aL,0x901a41ab435c95e9L,0xc6c23e5faaa50a06L } }, + /* 166 */ + { { 0xb78016c19034d8ddL,0x856bb44b0b13e79bL,0x85c6409ab3241a05L, + 0x8d2fe19a2d78ed21L,0xdcc7c26d726eddf2L,0x3ccaff5f25104f04L }, + { 0x397d7edc6b21f843L,0xda88e4dde975de4cL,0x5273d3964f5ab69eL, + 0x537680e39aae6cc0L,0xf749cce53e6f9461L,0x021ddbd9957bffd3L } }, + /* 167 */ + { { 0x7b64585f777233cfL,0xfe6771f60942a6f0L,0x636aba7adfe6eef0L, + 0x63bbeb5686038029L,0xacee5842de8fcf36L,0x48d9aa99d4a20524L }, + { 0xcff7a74c0da5e57aL,0xc232593ce549d6c9L,0x68504bccf0f2287bL, + 0x6d7d098dbc8360b5L,0xeac5f1495b402f41L,0x61936f11b87d1bf1L } }, + /* 168 */ + { { 0xaa9da167b8153a9dL,0xa49fe3ac9e83ecf0L,0x14c18f8e1b661384L, + 0x61c24dab38434de1L,0x3d973c3a283dae96L,0xc99baa0182754fc9L }, + { 0x477d198f4c26b1e3L,0x12e8e186a7516202L,0x386e52f6362addfaL, + 0x31e8f695c3962853L,0xdec2af136aaedb60L,0xfcfdb4c629cf74acL } }, + /* 169 */ + { { 0x6b3ee958cca40298L,0xc3878153f2f5d195L,0x0c565630ed2eae5bL, + 0xd089b37e3a697cf2L,0xc2ed2ac7ad5029eaL,0x7e5cdfad0f0dda6aL }, + { 0xf98426dfd9b86202L,0xed1960b14335e054L,0x1fdb02463f14639eL, + 0x17f709c30db6c670L,0xbfc687ae773421e1L,0x13fefc4a26c1a8acL } }, + /* 170 */ + { { 0xe361a1987ffa0a5fL,0xf4b26102c63fe109L,0x264acbc56c74e111L, + 0x4af445fa77abebafL,0x448c4fdd24cddb75L,0x0b13157d44506eeaL }, + { 0x22a6b15972e9993dL,0x2c3c57e485e5ecbeL,0xa673560bfd83e1a1L, + 0x6be23f82c3b8c83bL,0x40b13a9640bbe38eL,0x66eea033ad17399bL } }, + /* 171 */ + { { 0x49fc6e95b4c6c693L,0xefc735de36af7d38L,0xe053343d35fe42fcL, + 0xf0aa427c6a9ab7c3L,0xc79f04364a0fcb24L,0x1628724393ebbc50L }, + { 0x5c3d6bd016927e1eL,0x40158ed2673b984cL,0xa7f86fc84cd48b9aL, + 0x1643eda660ea282dL,0x45b393eae2a1beedL,0x664c839e19571a94L } }, + /* 172 */ + { { 0x5774575027eeaf94L,0x2875c925ea99e1e7L,0xc127e7ba5086adeaL, + 0x765252a086fe424fL,0x1143cc6c2b6c0281L,0xc9bb2989d671312dL }, + { 0x880c337c51acb0a5L,0xa3710915d3c60f78L,0x496113c09262b6edL, + 0x5d25d9f89ce48182L,0x53b6ad72b3813586L,0x0ea3bebc4c0e159cL } }, + /* 173 */ + { { 0xcaba450ac5e49beaL,0x684e54157c05da59L,0xa2e9cab9de7ac36cL, + 0x4ca79b5f2e6f957bL,0xef7b024709b817b1L,0xeb3049907d89df0fL }, + { 0x508f730746fe5096L,0x695810e82e04eaafL,0x88ef1bd93512f76cL, + 0x776613513ebca06bL,0xf7d4863accf158b7L,0xb2a81e4494ee57daL } }, + /* 174 */ + { { 0xff288e5b6d53e6baL,0xa90de1a914484ea2L,0x2fadb60ced33c8ecL, + 0x579d6ef328b66a40L,0x4f2dd6ddec24372dL,0xe9e33fc91d66ec7dL }, + { 0x110899d2039eab6eL,0xa31a667a3e97bb5eL,0x6200166dcfdce68eL, + 0xbe83ebae5137d54bL,0x085f7d874800acdfL,0xcf4ab1330c6f8c86L } }, + /* 175 */ + { { 0x03f65845931e08fbL,0x6438551e1506e2c0L,0x5791f0dc9c36961fL, + 0x68107b29e3dcc916L,0x83242374f495d2caL,0xd8cfb6636ee5895bL }, + { 0x525e0f16a0349b1bL,0x33cd2c6c4a0fab86L,0x46c12ee82af8dda9L, + 0x7cc424ba71e97ad3L,0x69766ddf37621eb0L,0x95565f56a5f0d390L } }, + /* 176 */ + { { 0xe0e7bbf21a0f5e94L,0xf771e1151d82d327L,0x10033e3dceb111faL, + 0xd269744dd3426638L,0xbdf2d9da00d01ef6L,0x1cb80c71a049ceafL }, + { 0x17f183289e21c677L,0x6452af0519c8f98bL,0x35b9c5f780b67997L, + 0x5c2e1cbe40f8f3d4L,0x43f9165666d667caL,0x9faaa059cf9d6e79L } }, + /* 177 */ + { { 0x8ad246180a078fe6L,0xf6cc73e6464fd1ddL,0x4d2ce34dc3e37448L, + 0x624950c5e3271b5fL,0x62910f5eefc5af72L,0x8b585bf8aa132bc6L }, + { 0x11723985a839327fL,0x34e2d27d4aac252fL,0x402f59ef6296cc4eL, + 0x00ae055c47053de9L,0xfc22a97228b4f09bL,0xa9e86264fa0c180eL } }, + /* 178 */ + { { 0x0b7b6224bc310eccL,0x8a1a74f167fa14edL,0x87dd09607214395cL, + 0xdf1b3d09f5c91128L,0x39ff23c686b264a8L,0xdc2d49d03e58d4c5L }, + { 0x2152b7d3a9d6f501L,0xf4c32e24c04094f7L,0xc6366596d938990fL, + 0x084d078f94fb207fL,0xfd99f1d7328594cbL,0x36defa64cb2d96b3L } }, + /* 179 */ + { { 0x4619b78113ed7cbeL,0x95e500159784bd0eL,0x2a32251c2c7705feL, + 0xa376af995f0dd083L,0x55425c6c0361a45bL,0x812d2cef1f291e7bL }, + { 0xccf581a05fd94972L,0x26e20e39e56dc383L,0x0093685d63dbfbf0L, + 0x1fc164cc36b8c575L,0xb9c5ab81390ef5e7L,0x40086beb26908c66L } }, + /* 180 */ + { { 0xe5e54f7937e3c115L,0x69b8ee8cc1445a8aL,0x79aedff2b7659709L, + 0xe288e1631b46fbe6L,0xdb4844f0d18d7bb7L,0xe0ea23d048aa6424L }, + { 0x714c0e4ef3d80a73L,0x87a0aa9e3bd64f98L,0x8844b8a82ec63080L, + 0xe0ac9c30255d81a3L,0x86151237455397fcL,0x0b9794642f820155L } }, + /* 181 */ + { { 0x127a255a4ae03080L,0x232306b4580a89fbL,0x04e8cd6a6416f539L, + 0xaeb70dee13b02a0eL,0xa3038cf84c09684aL,0xa710ec3c28e433eeL }, + { 0x77a72567681b1f7dL,0x86fbce952fc28170L,0xd3408683f5735ac8L, + 0x3a324e2a6bd68e93L,0x7ec74353c027d155L,0xab60354cd4427177L } }, + /* 182 */ + { { 0x32a5342aef4c209dL,0x2ba7527408d62704L,0x4bb4af6fc825d5feL, + 0x1c3919ced28e7ff1L,0x1dfc2fdcde0340f6L,0xc6580baf29f33ba9L }, + { 0xae121e7541d442cbL,0x4c7727fd3a4724e4L,0xe556d6a4524f3474L, + 0x87e13cc7785642a2L,0x182efbb1a17845fdL,0xdcec0cf14e144857L } }, + /* 183 */ + { { 0x1cb89541e9539819L,0xc8cb3b4f9d94dbf1L,0x1d353f63417da578L, + 0xb7a697fb8053a09eL,0x8d841731c35d8b78L,0x85748d6fb656a7a9L }, + { 0x1fd03947c1859c5dL,0x6ce965c1535d22a2L,0x1966a13e0ca3aadcL, + 0x9802e41d4fb14effL,0xa9048cbb76dd3fcdL,0x89b182b5e9455bbaL } }, + /* 184 */ + { { 0xd777ad6a43360710L,0x841287ef55e9936bL,0xbaf5c67004a21b24L, + 0xf2c0725f35ad86f1L,0x338fa650c707e72eL,0x2bf8ed2ed8883e52L }, + { 0xb0212cf4b56e0d6aL,0x50537e126843290cL,0xd8b184a198b3dc6fL, + 0xd2be9a350210b722L,0x407406db559781eeL,0x5a78d5910bc18534L } }, + /* 185 */ + { { 0x4d57aa2ad748b02cL,0xbe5b3451a12b3b95L,0xadca7a4564711258L, + 0x597e091a322153dbL,0xf327100632eb1eabL,0xbd9adcba2873f301L }, + { 0xd1dc79d138543f7fL,0x00022092921b1fefL,0x86db3ef51e5df8edL, + 0x888cae049e6b944aL,0x71bd29ec791a32b4L,0xd3516206a6d1c13eL } }, + /* 186 */ + { { 0x2ef6b95255924f43L,0xd2f401ae4f9de8d5L,0xfc73e8d7adc68042L, + 0x627ea70c0d9d1bb4L,0xc3bb3e3ebbf35679L,0x7e8a254ad882dee4L }, + { 0x08906f50b5924407L,0xf14a0e61a1ad444aL,0xaa0efa2165f3738eL, + 0xd60c7dd6ae71f161L,0x9e8390faf175894dL,0xd115cd20149f4c00L } }, + /* 187 */ + { { 0x2f2e2c1da52abf77L,0xc2a0dca554232568L,0xed423ea254966dccL, + 0xe48c93c7cd0dd039L,0x1e54a225176405c7L,0x1efb5b1670d58f2eL }, + { 0xa751f9d994fb1471L,0xfdb31e1f67d2941dL,0xa6c74eb253733698L, + 0xd3155d1189a0f64aL,0x4414cfe4a4b8d2b6L,0x8d5a4be8f7a8e9e3L } }, + /* 188 */ + { { 0x5c96b4d452669e98L,0x4547f9228fd42a03L,0xcf5c1319d285174eL, + 0x805cd1ae064bffa0L,0x50e8bc4f246d27e7L,0xf89ef98fd5781e11L }, + { 0xb4ff95f6dee0b63fL,0xad850047222663a4L,0x026918604d23ce9cL, + 0x3e5309ce50019f59L,0x27e6f72269a508aeL,0xe9376652267ba52cL } }, + /* 189 */ + { { 0xa04d289cc0368708L,0xc458872f5e306e1dL,0x76fa23de33112feaL, + 0x718e39746efde42eL,0xf0c98cdc1d206091L,0x5fa3ca6214a71987L }, + { 0xeee8188bdcaa9f2aL,0x312cc732589a860dL,0xf9808dd6c63aeb1fL, + 0x70fd43db4ea62b53L,0x2c2bfe34890b6e97L,0x105f863cfa426aa6L } }, + /* 190 */ + { { 0x0b29795db38059adL,0x5686b77e90647ea0L,0xeff0470edb473a3eL, + 0x278d2340f9b6d1e2L,0xebbff95bbd594ec7L,0xf4b72334d3a7f23dL }, + { 0x2a285980a5a83f0bL,0x0786c41a9716a8b3L,0x138901bd22511812L, + 0xd1b55221e2fede6eL,0x0806e264df4eb590L,0x6c4c897e762e462eL } }, + /* 191 */ + { { 0xd10b905fb4b41d9dL,0x826ca4664523a65bL,0x535bbd13b699fa37L, + 0x5b9933d773bc8f90L,0x9332d61fcd2118adL,0x158c693ed4a65fd0L }, + { 0x4ddfb2a8e6806e63L,0xe31ed3ecb5de651bL,0xf9460e51819bc69aL, + 0x6229c0d62c76b1f8L,0xbb78f231901970a3L,0x31f3820f9cee72b8L } }, + /* 192 */ + { { 0xe931caf2c09e1c72L,0x0715f29812990cf4L,0x33aad81d943262d8L, + 0x5d292b7a73048d3fL,0xb152aaa4dc7415f6L,0xc3d10fd90fd19587L }, + { 0xf76b35c575ddadd0L,0x9f5f4a511e7b694cL,0x2f1ab7ebc0663025L, + 0x01c9cc87920260b0L,0xc4b1f61a05d39da6L,0x6dcd76c4eb4a9c4eL } }, + /* 193 */ + { { 0x0ba0916ffdc83f01L,0x354c8b449553e4f9L,0xa6cc511affc5e622L, + 0xb954726ae95be787L,0xcb04811575b41a62L,0xfa2ae6cdebfde989L }, + { 0x6376bbc70f24659aL,0x13a999fd4c289c43L,0xc7134184ec9abd8bL, + 0x28c02bf6a789ab04L,0xff841ebcd3e526ecL,0x442b191e640893a8L } }, + /* 194 */ + { { 0x4cac6c62fa2b6e20L,0x97f29e9bf6d69861L,0x228ab1dbbc96d12dL, + 0x6eb913275e8e108dL,0xd4b3d4d140771245L,0x61b20623ca8a803aL }, + { 0x2c2f3b41a6a560b1L,0x879e1d403859fcf4L,0x7cdb5145024dbfc3L, + 0x55d08f153bfa5315L,0x2f57d773aa93823aL,0xa97f259cc6a2c9a2L } }, + /* 195 */ + { { 0xc306317be58edbbbL,0x25ade51c79dfdf13L,0x6b5beaf116d83dd6L, + 0xe8038a441dd8f925L,0x7f00143cb2a87b6bL,0xa885d00df5b438deL }, + { 0xe9f76790cf9e48bdL,0xf0bdf9f0a5162768L,0x0436709fad7b57cbL, + 0x7e151c12f7c15db7L,0x3514f0225d90ee3bL,0x2e84e8032c361a8dL } }, + /* 196 */ + { { 0x2277607d563ec8d8L,0xa661811fe3934cb7L,0x3ca72e7af58fd5deL, + 0x7989da0462294c6aL,0x88b3708bf6bbefe9L,0x0d524cf753ed7c82L }, + { 0x69f699ca2f30c073L,0xf0fa264b9dc1dcf3L,0x44ca456805f0aaf6L, + 0x0f5b23c7d19b9bafL,0x39193f41eabd1107L,0x9e3e10ad2a7c9b83L } }, + /* 197 */ + { { 0xa90824f0d4ae972fL,0x43eef02bc6e846e7L,0x7e46061229d2160aL, + 0x29a178acfe604e91L,0x23056f044eb184b2L,0x4fcad55feb54cdf4L }, + { 0xa0ff96f3ae728d15L,0x8a2680c6c6a00331L,0x5f84cae07ee52556L, + 0x5e462c3ac5a65dadL,0x5d2b81dfe2d23f4fL,0x6e47301bc5b1eb07L } }, + /* 198 */ + { { 0x77411d68af8219b9L,0xcb883ce651b1907aL,0x25c87e57101383b5L, + 0x9c7d9859982f970dL,0xaa6abca5118305d2L,0x725fed2f9013a5dbL }, + { 0x487cdbafababd109L,0xc0f8cf5687586528L,0xa02591e68ad58254L, + 0xc071b1d1debbd526L,0x927dfe8b961e7e31L,0x55f895f99263dfe1L } }, + /* 199 */ + { { 0xf899b00db175645bL,0x51f3a627b65b4b92L,0xa2f3ac8db67399efL, + 0xe717867fe400bc20L,0x42cc90201967b952L,0x3d5967513ecd1de1L }, + { 0xd41ebcdedb979775L,0x99ba61bc6a2e7e88L,0x039149a5321504f2L, + 0xe7dc231427ba2fadL,0x9f556308b57d8368L,0x2b6d16c957da80a7L } }, + /* 200 */ + { { 0x84af5e76279ad982L,0x9bb4c92d9c8b81a6L,0xd79ad44e0e698e67L, + 0xe8be9048265fc167L,0xf135f7e60c3a4cccL,0xa0a10d38b8863a33L }, + { 0xe197247cd386efd9L,0x0eefd3f9b52346c2L,0xc22415f978607bc8L, + 0xa2a8f862508674ceL,0xa72ad09ec8c9d607L,0xcd9f0ede50fa764fL } }, + /* 201 */ + { { 0x063391c7d1a46d4dL,0x2df51c119eb01693L,0xc5849800849e83deL, + 0x48fd09aa8ad08382L,0xa405d873aa742736L,0xee49e61ee1f9600cL }, + { 0xd76676be48c76f73L,0xd9c100f601274b2aL,0x110bb67c83f8718dL, + 0xec85a42002fc0d73L,0xc0449e1e744656adL,0x28ce737637d9939bL } }, + /* 202 */ + { { 0x97e9af7244544ac7L,0xf2c658d5ba010426L,0x732dec39fb3adfbdL, + 0xd12faf91a2df0b07L,0x8ac267252171e208L,0xf820cdc85b24fa54L }, + { 0x307a6eea94f4cf77L,0x18c783d2944a33c6L,0x4b939d4c0b741ac5L, + 0x1d7acd153ffbb6e4L,0x06a248587a255e44L,0x14fbc494ce336d50L } }, + /* 203 */ + { { 0x9b920c0c51584e3cL,0xc7733c59f7e54027L,0xe24ce13988422bbeL, + 0x11ada812523bd6abL,0xde068800b88e6defL,0x7b872671fe8c582dL }, + { 0x4e746f287de53510L,0x492f8b99f7971968L,0x1ec80bc77d928ac2L, + 0xb3913e48432eb1b5L,0xad08486632028f6eL,0x122bb8358fc2f38bL } }, + /* 204 */ + { { 0x0a9f3b1e3b0b29c3L,0x837b64324fa44151L,0xb9905c9217b28ea7L, + 0xf39bc93798451750L,0xcd383c24ce8b6da1L,0x299f57db010620b2L }, + { 0x7b6ac39658afdce3L,0xa15206b33d05ef47L,0xa0ae37e2b9bb02ffL, + 0x107760ab9db3964cL,0xe29de9a067954beaL,0x446a1ad8431c3f82L } }, + /* 205 */ + { { 0xc6fecea05c6b8195L,0xd744a7c5f49e71b9L,0xa8e96acc177a7ae7L, + 0x1a05746c358773a7L,0xa416214637567369L,0xaa0217f787d1c971L }, + { 0x61e9d15877fd3226L,0x0f6f2304e4f600beL,0xa9c4cebc7a6dff07L, + 0xd15afa0109f12a24L,0x2bbadb228c863ee9L,0xa28290e4e5eb8c78L } }, + /* 206 */ + { { 0x55b87fa03e9de330L,0x12b26066195c145bL,0xe08536e0a920bef0L, + 0x7bff6f2c4d195adcL,0x7f319e9d945f4187L,0xf9848863f892ce47L }, + { 0xd0efc1d34fe37657L,0x3c58de825cf0e45aL,0x626ad21a8b0ccbbeL, + 0xd2a31208af952fc5L,0x81791995eb437357L,0x5f19d30f98e95d4fL } }, + /* 207 */ + { { 0x72e83d9a0e6865bbL,0x22f5af3bf63456a6L,0x409e9c73463c8d9eL, + 0x40e9e578dfe6970eL,0x876b6efa711b91caL,0x895512cf942625a3L }, + { 0x84c8eda8cb4e462bL,0x84c0154a4412e7c8L,0x04325db1ceb7b71fL, + 0x1537dde366f70877L,0xf3a093991992b9acL,0xa7316606d498ae77L } }, + /* 208 */ + { { 0x13990d2fcad260f5L,0x76c3be29eec0e8c0L,0x7dc5bee00f7bd7d5L, + 0x9be167d2efebda4bL,0xcce3dde69122b87eL,0x75a28b0982b5415cL }, + { 0xf6810bcde84607a6L,0xc6d581286f4dbf0dL,0xfead577d1b4dafebL, + 0x9bc440b2066b28ebL,0x53f1da978b17e84bL,0x0459504bcda9a575L } }, + /* 209 */ + { { 0x13e39a02329e5836L,0x2c9e7d51f717269dL,0xc5ac58d6f26c963bL, + 0x3b0c6c4379967bf5L,0x60bbea3f55908d9dL,0xd84811e7f07c9ad1L }, + { 0xfe7609a75bd20e4aL,0xe4325dd20a70baa8L,0x3711f370b3600386L, + 0x97f9562fd0924302L,0x040dc0c34acc4436L,0xfd6d725cde79cdd4L } }, + /* 210 */ + { { 0xb3efd0e3cf13eafbL,0x21009cbb5aa0ae5fL,0xe480c55379022279L, + 0x755cf334b2fc9a6dL,0x8564a5bf07096ae7L,0xddd649d0bd238139L }, + { 0xd0de10b18a045041L,0x6e05b413c957d572L,0x5c5ff8064e0fb25cL, + 0xd933179b641162fbL,0x42d48485e57439f9L,0x70c5bd0a8a8d72aaL } }, + /* 211 */ + { { 0xa767173897bdf646L,0xaa1485b4ab329f7cL,0xce3e11d6f8f25fdfL, + 0x76a3fc7ec6221824L,0x045f281ff3924740L,0x24557d4e96d13a9aL }, + { 0x875c804bdd4c27cdL,0x11c5f0f40f5c7feaL,0xac8c880bdc55ff7eL, + 0x2acddec51103f101L,0x38341a21f99faa89L,0xc7b67a2cce9d6b57L } }, + /* 212 */ + { { 0x9a0d724f8e357586L,0x1d7f4ff5df648da0L,0x9c3e6c9bfdee62a5L, + 0x0499cef00389b372L,0xe904050d98eab879L,0xe8eef1b66c051617L }, + { 0xebf5bfebc37e3ca9L,0x7c5e946da4e0b91dL,0x790973142c4bea28L, + 0x81f6c109ee67b2b7L,0xaf237d9bdafc5edeL,0xd2e602012abb04c7L } }, + /* 213 */ + { { 0x6156060c8a4f57bfL,0xf9758696ff11182aL,0x8336773c6296ef00L, + 0x9c054bceff666899L,0xd6a11611719cd11cL,0x9824a641dbe1acfaL }, + { 0x0b7b7a5fba89fd01L,0xf8d3b809889f79d8L,0xc5e1ea08f578285cL, + 0x7ac74536ae6d8288L,0x5d37a2007521ef5fL,0x5ecc4184b260a25dL } }, + /* 214 */ + { { 0xddcebb19a708c8d3L,0xe63ed04fc63f81ecL,0xd045f5a011873f95L, + 0x3b5ad54479f276d5L,0x81272a3d425ae5b3L,0x8bfeb50110ce1605L }, + { 0x4233809c888228bfL,0x4bd82acfb2aff7dfL,0x9c68f1800cbd4a7fL, + 0xfcd771246b44323dL,0x60c0fcf6891db957L,0xcfbb4d8904da8f7fL } }, + /* 215 */ + { { 0x9a6a5df93b26139aL,0x3e076a83b2cc7eb8L,0x47a8e82d5a964bcdL, + 0x8a4e2a39b9278d6bL,0x93506c98e4443549L,0x06497a8ff1e0d566L }, + { 0x3dee8d992b1efa05L,0x2da63ca845393e33L,0xa4af7277cf0579adL, + 0xaf4b46393236d8eaL,0x6ccad95b32b617f5L,0xce76d8b8b88bb124L } }, + /* 216 */ + { { 0x63d2537a083843dcL,0x89eb35141e4153b4L,0x5175ebc4ea9afc94L, + 0x7a6525808ed1aed7L,0x67295611d85e8297L,0x8dd2d68bb584b73dL }, + { 0x237139e60133c3a4L,0x9de838ab4bd278eaL,0xe829b072c062fcd9L, + 0x70730d4f63ba8706L,0x6080483fd3cd05ecL,0x872ab5b80c85f84dL } }, + /* 217 */ + { { 0xfc0776d3999d4d49L,0xa3eb59deec3f45e7L,0xbc990e440dae1fc1L, + 0x33596b1ea15371ffL,0xd447dcb29bc7ab25L,0xcd5b63e935979582L }, + { 0xae3366fa77d1ff11L,0x59f28f05edee6903L,0x6f43fed1a4433bf2L, + 0x15409c9bdf9ce00eL,0x21b5cdedaca9c5dcL,0xf9f3359582d7bdb4L } }, + /* 218 */ + { { 0x959443789422c792L,0x239ea923c958b8bfL,0x4b61a247df076541L, + 0x4d29ce85bb9fc544L,0x9a692a670b424559L,0x6e0ca5a00e486900L }, + { 0x6b79a78285b3beceL,0x41f35e39c61f9892L,0xff82099aae747f82L, + 0x58c8ae3fd0ca59d6L,0x4ac930e299406b5fL,0x2ce04eb99df24243L } }, + /* 219 */ + { { 0x4366b9941ac37b82L,0xff0c728d25b04d83L,0x1f55136119c47b7cL, + 0xdbf2d5edbeff13e7L,0xf78efd51e12a683dL,0x82cd85b9989cf9c4L }, + { 0xe23c6db6e0cb5d37L,0x818aeebd72ee1a15L,0x8212aafd28771b14L, + 0x7bc221d91def817dL,0xdac403a29445c51fL,0x711b051712c3746bL } }, + /* 220 */ + { { 0x0ed9ed485ea99eccL,0xf799500db8cab5e1L,0xa8ec87dcb570cbdcL, + 0x52cfb2c2d35dfaecL,0x8d31fae26e4d80a4L,0xe6a37dc9dcdeabe5L }, + { 0x5d365a341deca452L,0x09a5f8a50d68b44eL,0x59238ea5a60744b1L, + 0xf2fedc0dbb4249e9L,0xe395c74ea909b2e3L,0xe156d1a539388250L } }, + /* 221 */ + { { 0xd796b3d047181ae9L,0xbaf44ba844197808L,0xe693309434cf3facL, + 0x41aa6adec3bd5c46L,0x4fda75d8eed947c6L,0xacd9d4129ea5a525L }, + { 0x65cc55a3d430301bL,0x3c9a5bcf7b52ea49L,0x22d319cf159507f0L, + 0x2ee0b9b5de74a8ddL,0x20c26a1e877ac2b6L,0x387d73da92e7c314L } }, + /* 222 */ + { { 0x13c4833e8cd3fdacL,0x76fcd473332e5b8eL,0xff671b4be2fe1fd3L, + 0x4d734e8b5d98d8ecL,0xb1ead3c6514bbc11L,0xd14ca8587b390494L }, + { 0x95a443af5d2d37e9L,0x73c6ea7300464622L,0xa44aeb4b15755044L, + 0xba3f8575fab58feeL,0x9779dbc9dc680a6fL,0xe1ee5f5a7b37ddfcL } }, + /* 223 */ + { { 0xcd0b464812d29f46L,0x93295b0b0ed53137L,0xbfe2609480bef6c9L, + 0xa656578854248b00L,0x69c43fca80e7f9c4L,0x2190837bbe141ea1L }, + { 0x875e159aa1b26cfbL,0x90ca9f877affe852L,0x15e6550d92ca598eL, + 0xe3e0945d1938ad11L,0xef7636bb366ef937L,0xb6034d0bb39869e5L } }, + /* 224 */ + { { 0x4d255e3026d8356eL,0xf83666edd314626fL,0x421ddf61d0c8ed64L, + 0x96e473c526677b61L,0xdad4af7e9e9b18b3L,0xfceffd4aa9393f75L }, + { 0x843138a111c731d5L,0x05bcb3a1b2f141d9L,0x20e1fa95617b7671L, + 0xbefce81288ccec7bL,0x582073dc90f1b568L,0xf572261a1f055cb7L } }, + /* 225 */ + { { 0xf314827736973088L,0xc008e70886a9f980L,0x1b795947e046c261L, + 0xdf1e6a7dca76bca0L,0xabafd88671acddf0L,0xff7054d91364d8f4L }, + { 0x2cf63547e2260594L,0x468a5372d73b277eL,0xc7419e24ef9bd35eL, + 0x2b4a1c2024043cc3L,0xa28f047a890b39cdL,0xdca2cea146f9a2e3L } }, + /* 226 */ + { { 0xab78873653277538L,0xa734e225cf697738L,0x66ee1d1e6b22e2c1L, + 0x2c615389ebe1d212L,0xf36cad4002bb0766L,0x120885c33e64f207L }, + { 0x59e77d5690fbfec2L,0xf9e781aad7a574aeL,0x801410b05d045e53L, + 0xd3b5f0aaa91b5f0eL,0xb3d1df007fbb3521L,0x11c4b33ec72bee9aL } }, + /* 227 */ + { { 0xd32b983283c3a7f3L,0x8083abcf88d8a354L,0xdeb1640450f4ec5aL, + 0x18d747f0641e2907L,0x4e8978aef1bbf03eL,0x932447dc88a0cd89L }, + { 0x561e0febcf3d5897L,0xfc3a682f13600e6dL,0xc78b9d73d16a6b73L, + 0xe713feded29bf580L,0x0a22522308d69e5cL,0x3a924a571ff7fda4L } }, + /* 228 */ + { { 0xfb64554cb4093beeL,0xa6d65a25a58c6ec0L,0x4126994d43d0ed37L, + 0xa5689a5155152d44L,0xb8e5ea8c284caa8dL,0x33f05d4fd1f25538L }, + { 0xe0fdfe091b615d6eL,0x2ded7e8f705507daL,0xdd5631e517bbcc80L, + 0x4f87453e267fd11fL,0xc6da723fff89d62dL,0x55cbcae2e3cda21dL } }, + /* 229 */ + { { 0x336bc94e6b4e84f3L,0x728630314ef72c35L,0x6d85fdeeeeb57f99L, + 0x7f4e3272a42ece1bL,0x7f86cbb536f0320aL,0xf09b6a2b923331e6L }, + { 0x21d3ecf156778435L,0x2977ba998323b2d2L,0x6a1b57fb1704bc0fL, + 0xd777cf8b389f048aL,0x9ce2174fac6b42cdL,0x404e2bff09e6c55aL } }, + /* 230 */ + { { 0x9b9b135e204c5ddbL,0x9dbfe0443eff550eL,0x35eab4bfec3be0f6L, + 0x8b4c3f0d0a43e56fL,0x4c1c66730e73f9b3L,0x92ed38bd2c78c905L }, + { 0xc7003f6aa386e27cL,0xb9c4f46faced8507L,0xea024ec859df5464L, + 0x4af96152429572eaL,0x279cd5e2e1fc1194L,0xaa376a03281e358cL } }, + /* 231 */ + { { 0x078592233cdbc95cL,0xaae1aa6aef2e337aL,0xc040108d472a8544L, + 0x80c853e68d037b7dL,0xd221315c8c7eee24L,0x195d38568ee47752L }, + { 0xd4b1ba03dacd7fbeL,0x4b5ac61ed3e0c52bL,0x68d3c0526aab7b52L, + 0xf0d7248c660e3feaL,0xafdb3f893145efb4L,0xa73fd9a38f40936dL } }, + /* 232 */ + { { 0x891b9ef3bb1b17ceL,0x14023667c6127f31L,0x12b2e58d305521fdL, + 0x3a47e449e3508088L,0xe49fc84bff751507L,0x4023f7225310d16eL }, + { 0xa608e5edb73399faL,0xf12632d8d532aa3eL,0x13a2758e845e8415L, + 0xae4b6f851fc2d861L,0x3879f5b1339d02f2L,0x446d22a680d99ebdL } }, + /* 233 */ + { { 0x0f5023024be164f1L,0x8d09d2d688b81920L,0x514056f1984aceffL, + 0xa5c4ddf075e9e80dL,0x38cb47e6df496a93L,0x899e1d6b38df6bf7L }, + { 0x69e87e88b59eb2a6L,0x280d9d639b47f38bL,0x599411ea3654e955L, + 0xcf8dd4fd969aa581L,0xff5c2baf530742a7L,0xa43915361a373085L } }, + /* 234 */ + { { 0x6ace72a3a8a4bdd2L,0xc656cdd1b68ef702L,0xd4a33e7e90c4dad8L, + 0x4aece08a9d951c50L,0xea8005ae085d68e6L,0xfdd7a7d76f7502b8L }, + { 0xce6fb0a698d6fa45L,0x228f86721104eb8cL,0xd23d8787da09d7dcL, + 0x5521428b2ae93065L,0x95faba3dea56c366L,0xedbe50390a88aca5L } }, + /* 235 */ + { { 0xd64da0adbfb26c82L,0xe5d70b3c952c2f9cL,0xf5e8f365f7e77f68L, + 0x7234e00208f2d695L,0xfaf900eed12e7be6L,0x27dc69344acf734eL }, + { 0x80e4ff5ec260a46aL,0x7da5ebce2dc31c28L,0x485c5d73ca69f552L, + 0xcdfb6b2969cc84c2L,0x031c5afeed6d4ecaL,0xc7bbf4c822247637L } }, + /* 236 */ + { { 0x9d5b72c749fe01b2L,0x34785186793a91b8L,0xa3ba3c54cf460438L, + 0x73e8e43d3ab21b6fL,0x50cde8e0be57b8abL,0x6488b3a7dd204264L }, + { 0xa9e398b3dddc4582L,0x1698c1a95bec46feL,0x7f1446ef156d3843L, + 0x3fd25dd8770329a2L,0x05b1221a2c710668L,0x65b2dc2aa72ee6cfL } }, + /* 237 */ + { { 0x21a885f7cd021d63L,0x3f344b15fea61f08L,0xad5ba6ddc5cf73e6L, + 0x154d0d8f227a8b23L,0x9b74373cdc559311L,0x4feab71598620fa1L }, + { 0x5098938e7d9ec924L,0x84d54a5e6d47e550L,0x1a2d1bdc1b617506L, + 0x99fe1782615868a4L,0x171da7803005a924L,0xa70bf5ed7d8f79b6L } }, + /* 238 */ + { { 0x0bc1250dfe2216c5L,0x2c37e2507601b351L,0xb6300175d6f06b7eL, + 0x4dde8ca18bfeb9b7L,0x4f210432b82f843dL,0x8d70e2f9b1ac0afdL }, + { 0x25c73b78aae91abbL,0x0230dca3863028f2L,0x8b923ecfe5cf30b7L, + 0xed754ec25506f265L,0x8e41b88c729a5e39L,0xee67cec2babf889bL } }, + /* 239 */ + { { 0xe183acf51be46c65L,0x9789538fe7565d7aL,0x87873391d9627b4eL, + 0xbf4ac4c19f1d9187L,0x5db99f634691f5c8L,0xa68df80374a1fb98L }, + { 0x3c448ed1bf92b5faL,0xa098c8413e0bdc32L,0x8e74cd5579bf016cL, + 0x5df0d09c115e244dL,0x9418ad013410b66eL,0x8b6124cb17a02130L } }, + /* 240 */ + { { 0x425ec3afc26e3392L,0xc07f8470a1722e00L,0xdcc28190e2356b43L, + 0x4ed97dffb1ef59a6L,0xc22b3ad1c63028c1L,0x070723c268c18988L }, + { 0x70da302f4cf49e7dL,0xc5e87c933f12a522L,0x74acdd1d18594148L, + 0xad5f73abca74124cL,0xe72e4a3ed69fd478L,0x615938687b117cc3L } }, + /* 241 */ + { { 0x7b7b9577a9aa0486L,0x6e41fb35a063d557L,0xb017d5c7da9047d7L, + 0x8c74828068a87ba9L,0xab45fa5cdf08ad93L,0xcd9fb2174c288a28L }, + { 0x595446425747843dL,0x34d64c6ca56111e3L,0x12e47ea14bfce8d5L, + 0x17740e056169267fL,0x5c49438eeed03fb5L,0x9da30add4fc3f513L } }, + /* 242 */ + { { 0xc4e85282ccfa5200L,0x2707608f6a19b13dL,0xdcb9a53df5726e2fL, + 0x612407c9e9427de5L,0x3e5a17e1d54d582aL,0xb99877de655ae118L }, + { 0x6f0e972b015254deL,0x92a56db1f0a6f7c5L,0xd297e4e1a656f8b2L, + 0x99fe0052ad981983L,0xd3652d2f07cfed84L,0xc784352e843c1738L } }, + /* 243 */ + { { 0x6ee90af07e9b2d8aL,0xac8d701857cf1964L,0xf6ed903171f28efcL, + 0x7f70d5a96812b20eL,0x27b557f4f1c61eeeL,0xf1c9bd57c6263758L }, + { 0x5cf7d0142a1a6194L,0xdd614e0b1890ab84L,0x3ef9de100e93c2a6L, + 0xf98cf575e0cd91c5L,0x504ec0c614befc32L,0xd0513a666279d68cL } }, + /* 244 */ + { { 0xa8eadbada859fb6aL,0xcf8346e7db283666L,0x7b35e61a3e22e355L, + 0x293ece2c99639c6bL,0xfa0162e256f241c8L,0xd2e6c7b9bf7a1ddaL }, + { 0xd0de625340075e63L,0x2405aa61f9ec8286L,0x2237830a8fe45494L, + 0x4fd01ac7364e9c8cL,0x4d9c3d21904ba750L,0xd589be14af1b520bL } }, + /* 245 */ + { { 0x13576a4f4662e53bL,0x35ec2f51f9077676L,0x66297d1397c0af97L, + 0xed3201fe9e598b58L,0x49bc752a5e70f604L,0xb54af535bb12d951L }, + { 0x36ea4c2b212c1c76L,0x18f5bbc7eb250dfdL,0xa0d466cc9a0a1a46L, + 0x52564da4dac2d917L,0x206559f48e95fab5L,0x7487c1909ca67a33L } }, + /* 246 */ + { { 0x75abfe37dde98e9cL,0x99b90b262a411199L,0x1b410996dcdb1f7cL, + 0xab346f118b3b5675L,0x04852193f1f8ae1eL,0x1ec4d2276b8b98c1L }, + { 0xba3bc92645452baaL,0x387d1858acc4a572L,0x9478eff6e51f171eL, + 0xf357077d931e1c00L,0xffee77cde54c8ca8L,0xfb4892ff551dc9a4L } }, + /* 247 */ + { { 0x5b1bdad02db8dff8L,0xd462f4fd5a2285a2L,0x1d6aad8eda00b461L, + 0x43fbefcf41306d1bL,0x428e86f36a13fe19L,0xc8b2f11817f89404L }, + { 0x762528aaf0d51afbL,0xa3e2fea4549b1d06L,0x86fad8f2ea3ddf66L, + 0x0d9ccc4b4fbdd206L,0xcde97d4cc189ff5aL,0xc36793d6199f19a6L } }, + /* 248 */ + { { 0xea38909b51b85197L,0xffb17dd0b4c92895L,0x0eb0878b1ddb3f3fL, + 0xb05d28ffc57cf0f2L,0xd8bde2e71abd57e2L,0x7f2be28dc40c1b20L }, + { 0x6554dca2299a2d48L,0x5130ba2e8377982dL,0x8863205f1071971aL, + 0x15ee62827cf2825dL,0xd4b6c57f03748f2bL,0xa9e3f4da430385a0L } }, + /* 249 */ + { { 0x33eb7cec83fbc9c6L,0x24a311c74541777eL,0xc81377f74f0767fcL, + 0x12adae364ab702daL,0xb7fcb6db2a779696L,0x4a6fb28401cea6adL }, + { 0x5e8b1d2acdfc73deL,0xd0efae8d1b02fd32L,0x3f99c190d81d8519L, + 0x3c18f7fafc808971L,0x41f713e751b7ae7bL,0x0a4b3435f07fc3f8L } }, + /* 250 */ + { { 0x7dda3c4c019b7d2eL,0x631c8d1ad4dc4b89L,0x5489cd6e1cdb313cL, + 0xd44aed104c07bb06L,0x8f97e13a75f000d1L,0x0e9ee64fdda5df4dL }, + { 0xeaa99f3b3e346910L,0x622f6921fa294ad7L,0x22aaa20d0d0b2fe9L, + 0x4fed2f991e5881baL,0x9af3b2d6c1571802L,0x919e67a8dc7ee17cL } }, + /* 251 */ + { { 0xc724fe4c76250533L,0x8a2080e57d817ef8L,0xa2afb0f4172c9751L, + 0x9b10cdeb17c0702eL,0xbf3975e3c9b7e3e9L,0x206117df1cd0cdc5L }, + { 0xfb049e61be05ebd5L,0xeb0bb55c16c782c0L,0x13a331b8ab7fed09L, + 0xf6c58b1d632863f0L,0x6264ef6e4d3b6195L,0x92c51b639a53f116L } }, + /* 252 */ + { { 0xa57c7bc8288b364dL,0x4a562e087b41e5c4L,0x699d21c6698a9a11L, + 0xa4ed9581f3f849b9L,0xa223eef39eb726baL,0x13159c23cc2884f9L }, + { 0x73931e583a3f4963L,0x965003890ada6a81L,0x3ee8a1c65ab2950bL, + 0xeedf4949775fab52L,0x63d652e14f2671b6L,0xfed4491c3c4e2f55L } }, + /* 253 */ + { { 0x335eadc3f4eb453eL,0x5ff74b63cadd1a5bL,0x6933d0d75d84a91aL, + 0x9ca3eeb9b49ba337L,0x1f6faccec04c15b8L,0x4ef19326dc09a7e4L }, + { 0x53d2d3243dca3233L,0x0ee40590a2259d4bL,0x18c22edb5546f002L, + 0x9242980109ea6b71L,0xaada0addb0e91e61L,0x5fe53ef499963c50L } }, + /* 254 */ + { { 0x372dd06b90c28c65L,0x1765242c119ce47dL,0xc041fb806b22fc82L, + 0x667edf07b0a7ccc1L,0xc79599e71261beceL,0xbc69d9ba19cff22aL }, + { 0x009d77cd13c06819L,0x635a66aee282b79dL,0x4edac4a6225b1be8L, + 0x57d4f4e4524008f9L,0xee299ac5b056af84L,0xcc38444c3a0bc386L } }, + /* 255 */ + { { 0x490643b1cd4c2356L,0x740a4851750547beL,0x643eaf29d4944c04L, + 0xba572479299a98a0L,0x48b29f16ee05fdf9L,0x33fb4f61089b2d7bL }, + { 0x86704902a950f955L,0x97e1034dfedc3ddfL,0x211320b605fbb6a2L, + 0x23d7b93f432299bbL,0x1fe1a0578590e4a3L,0x8e1d0586f58c0ce6L } }, +}; + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_6(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + return sp_384_ecc_mulmod_stripe_6(r, &p384_base, p384_table, + k, map, heap); +} + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[6]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_384_point_new_6(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 6, km); + + err = sp_384_ecc_mulmod_base_6(point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_6(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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_384_iszero_6(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +static void sp_384_add_one_6(sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x1, x2, [%[a], 0]\n\t" + "adds x1, x1, #1\n\t" + "ldr x3, [%[a], 16]\n\t" + "adcs x2, x2, xzr\n\t" + "ldr x4, [%[a], 24]\n\t" + "adcs x3, x3, xzr\n\t" + "stp x1, x2, [%[a], 0]\n\t" + "adcs x4, x4, xzr\n\t" + "stp x3, x4, [%[a], 16]\n\t" + "ldp x1, x2, [%[a], 32]\n\t" + "adcs x1, x1, xzr\n\t" + "adcs x2, x2, xzr\n\t" + "stp x1, x2, [%[a], 32]\n\t" + : + : [a] "r" (a) + : "memory", "x1", "x2", "x3", "x4" + ); +} + +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j; + byte* d; + + for (i = n - 1,j = 0; i >= 7; i -= 8) { + r[j] = ((sp_digit)a[i - 0] << 0) | + ((sp_digit)a[i - 1] << 8) | + ((sp_digit)a[i - 2] << 16) | + ((sp_digit)a[i - 3] << 24) | + ((sp_digit)a[i - 4] << 32) | + ((sp_digit)a[i - 5] << 40) | + ((sp_digit)a[i - 6] << 48) | + ((sp_digit)a[i - 7] << 56); + j++; + } + + if (i >= 0) { + r[j] = 0; + + d = (byte*)r; + switch (i) { + case 6: d[n - 1 - 6] = a[6]; //fallthrough + case 5: d[n - 1 - 5] = a[5]; //fallthrough + case 4: d[n - 1 - 4] = a[4]; //fallthrough + case 3: d[n - 1 - 3] = a[3]; //fallthrough + case 2: d[n - 1 - 2] = a[2]; //fallthrough + case 1: d[n - 1 - 1] = a[1]; //fallthrough + case 0: d[n - 1 - 0] = a[0]; //fallthrough + } + j++; + } + + for (; j < size; 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_384_ecc_gen_k_6(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[48]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_384_from_bin(k, 6, buf, (int)sizeof(buf)); + if (sp_384_cmp_6(k, p384_order2) < 0) { + sp_384_add_one_6(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_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[6]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 inf; +#endif +#endif + sp_point_384* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity; +#endif + int err; + + (void)heap; + + err = sp_384_point_new_6(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + err = sp_384_ecc_gen_k_6(rng, k); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_6(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_6(infinity, point, p384_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_384_iszero_6(point->x) == 0) || (sp_384_iszero_6(point->y) == 0)) { + err = ECC_INF_E; + } + } +#endif + + if (err == MP_OKAY) { + err = sp_384_to_mp(k, priv); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_6(point, pub); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_384_point_free_6(infinity, 1, heap); +#endif + sp_384_point_free_6(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 48 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_384_to_bin(sp_digit* r, byte* a) +{ + int i, j; + + for (i = 5, j = 0; i >= 0; i--) { + a[j++] = r[i] >> 56; + a[j++] = r[i] >> 48; + a[j++] = r[i] >> 40; + a[j++] = r[i] >> 32; + a[j++] = r[i] >> 24; + a[j++] = r[i] >> 16; + a[j++] = r[i] >> 8; + a[j++] = r[i] >> 0; + } +} + +/* 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_384(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[6]; +#endif + sp_point_384* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 48U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(k, 6, priv); + sp_384_point_from_ecc_point_6(point, pub); + err = sp_384_ecc_mulmod_6(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_384_to_bin(point->x, out); + *outLen = 48; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#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_384_sub_in_place_6(sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "subs x2, x2, x6\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "sbcs x3, x3, x7\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "sbcs x4, x4, x8\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "sbcs x5, x5, x9\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "ldr x2, [%[a], 32]\n\t" + "ldr x3, [%[a], 40]\n\t" + "ldr x6, [%[b], 32]\n\t" + "ldr x7, [%[b], 40]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "str x2, [%[a], 32]\n\t" + "str x3, [%[a], 40]\n\t" + "csetm %[a], cc\n\t" + : [a] "+r" (a) + : [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return (sp_digit)a; +} + +/* 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_384_mul_d_6(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x5, %[b], x8\n\t" + "umulh x3, %[b], x8\n\t" + "mov x4, 0\n\t" + "str x5, [%[r]]\n\t" + "mov x5, 0\n\t" + "mov x9, #8\n\t" + "1:\n\t" + "ldr x8, [%[a], x9]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], x9]\n\t" + "mov x3, x4\n\t" + "mov x4, x5\n\t" + "mov x5, #0\n\t" + "add x9, x9, #8\n\t" + "cmp x9, 48\n\t" + "b.lt 1b\n\t" + "str x3, [%[r], 48]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#else + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldp x8, x9, [%[a]]\n\t" + "mul x3, %[b], x8\n\t" + "umulh x4, %[b], x8\n\t" + "mov x5, 0\n\t" + "# A[1] * B\n\t" + "str x3, [%[r]]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x9\n\t" + "umulh x7, %[b], x9\n\t" + "adds x4, x4, x6\n\t" + "# A[2] * B\n\t" + "ldp x8, x9, [%[a], 16]\n\t" + "str x4, [%[r], 8]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "# A[3] * B\n\t" + "str x5, [%[r], 16]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x9\n\t" + "adcs x3, x3, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x3, x3, x6\n\t" + "# A[4] * B\n\t" + "ldp x8, x9, [%[a], 32]\n\t" + "str x3, [%[r], 24]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "adcs x4, x4, x7\n\t" + "umulh x7, %[b], x8\n\t" + "adc x5, xzr, xzr\n\t" + "adds x4, x4, x6\n\t" + "# A[5] * B\n\t" + "str x4, [%[r], 32]\n\t" + "mul x6, %[b], x9\n\t" + "adcs x5, x5, x7\n\t" + "umulh x7, %[b], x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x5, x5, x6\n\t" + "adc x3, x3, x7\n\t" + "stp x5, x3, [%[r], 40]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); +#endif +} + +/* 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_384_word_6(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsr x3, %[d0], 32\n\t" + "orr x3, x3, %[d1], lsl 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "sub %[d0], %[d0], x4\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add %[r], x6, x3\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + 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_384_mask_6(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<6; 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; + r[4] = a[4] & m; + r[5] = a[5] & 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 WC_INLINE int sp_384_div_6(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[12], t2[7]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[5]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 6); + for (i=5; i>=0; i--) { + r1 = div_384_word_6(t1[6 + i], t1[6 + i - 1], div); + + sp_384_mul_d_6(t2, d, r1); + t1[6 + i] += sp_384_sub_in_place_6(&t1[i], t2); + t1[6 + i] -= t2[6]; + sp_384_mask_6(t2, d, t1[6 + i]); + t1[6 + i] += sp_384_add_6(&t1[i], &t1[i], t2); + sp_384_mask_6(t2, d, t1[6 + i]); + t1[6 + i] += sp_384_add_6(&t1[i], &t1[i], t2); + } + + r1 = sp_384_cmp_6(t1, d) >= 0; + sp_384_cond_sub_6(r, t1, d, (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 WC_INLINE int sp_384_mod_6(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_384_div_6(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P384 curve. */ +static const uint64_t p384_order_minus_2[6] = { + 0xecec196accc52971U,0x581a0db248b0a77aU,0xc7634d81f4372ddfU, + 0xffffffffffffffffU,0xffffffffffffffffU,0xffffffffffffffffU +}; +#else +/* The low half of the order-2 of the P384 curve. */ +static const uint64_t p384_order_low[3] = { + 0xecec196accc52971U,0x581a0db248b0a77aU,0xc7634d81f4372ddfU + +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P384 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_384_mont_mul_order_6(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_384_mul_6(r, a, b); + sp_384_mont_reduce_order_6(r, p384_order, p384_mp_order); +} + +/* Square number mod the order of P384 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_order_6(sp_digit* r, const sp_digit* a) +{ + sp_384_sqr_6(r, a); + sp_384_mont_reduce_order_6(r, p384_order, p384_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P384 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_n_order_6(sp_digit* r, const sp_digit* a, int n) +{ + int i; + + sp_384_mont_sqr_order_6(r, a); + for (i=1; i=0; i--) { + sp_384_mont_sqr_order_6(t, t); + if ((p384_order_minus_2[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + sp_384_mont_mul_order_6(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 6U); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 6; + sp_digit* t3 = td + 4 * 6; + int i; + + /* t = a^2 */ + sp_384_mont_sqr_order_6(t, a); + /* t = a^3 = t * a */ + sp_384_mont_mul_order_6(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_384_mont_sqr_n_order_6(t2, t, 2); + /* t = a^f = t2 * t */ + sp_384_mont_mul_order_6(t, t2, t); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_384_mont_sqr_n_order_6(t2, t, 4); + /* t = a^ff = t2 * t */ + sp_384_mont_mul_order_6(t, t2, t); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_384_mont_sqr_n_order_6(t2, t, 8); + /* t3= a^ffff = t2 * t */ + sp_384_mont_mul_order_6(t3, t2, t); + /* t2= a^ffff0000 = t3 ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_6(t2, t3, 16); + /* t = a^ffffffff = t2 * t3 */ + sp_384_mont_mul_order_6(t, t2, t3); + /* t2= a^ffffffff0000 = t ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_6(t2, t, 16); + /* t = a^ffffffffffff = t2 * t3 */ + sp_384_mont_mul_order_6(t, t2, t3); + /* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */ + sp_384_mont_sqr_n_order_6(t2, t, 48); + /* t= a^fffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_6(t, t2, t); + /* t2= a^ffffffffffffffffffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_order_6(t2, t, 96); + /* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_6(t2, t2, t); + for (i=191; i>=1; i--) { + sp_384_mont_sqr_order_6(t2, t2); + if (((sp_digit)p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + sp_384_mont_mul_order_6(t2, t2, a); + } + } + sp_384_mont_sqr_order_6(t2, t2); + sp_384_mont_mul_order_6(r, t2, a); +#endif /* WOLFSSL_SP_SMALL */ +} + +#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, 384 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 384 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_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit ed[2*6]; + sp_digit xd[2*6]; + sp_digit kd[2*6]; + sp_digit rd[2*6]; + sp_digit td[3 * 2*6]; + sp_point_384 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_384* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int64_t c; + int i; + + (void)heap; + + err = sp_384_point_new_6(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 6, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 6; + x = d + 2 * 6; + k = d + 4 * 6; + r = d + 6 * 6; + tmp = d + 8 * 6; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(e, 6, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_384_from_mp(x, 6, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_6(rng, k); + } + else { + sp_384_from_mp(k, 6, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_6(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 6U); + sp_384_norm_6(r); + c = sp_384_cmp_6(r, p384_order); + sp_384_cond_sub_6(r, r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(r); + + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_6(k, k, p384_norm_order); + err = sp_384_mod_6(k, k, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_6(k); + /* kInv = 1/k mod order */ + sp_384_mont_inv_order_6(kInv, k, tmp); + sp_384_norm_6(kInv); + + /* s = r * x + e */ + sp_384_mul_6(x, x, r); + err = sp_384_mod_6(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_6(x); + carry = sp_384_add_6(s, e, x); + sp_384_cond_sub_6(s, s, p384_order, 0 - carry); + sp_384_norm_6(s); + c = sp_384_cmp_6(s, p384_order); + sp_384_cond_sub_6(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_6(s, s, kInv); + sp_384_norm_6(s); + + /* Check that signature is usable. */ + if (sp_384_iszero_6(s) == 0) { + break; + } + } + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 6); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 6U); +#endif + sp_384_point_free_6(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, 384) + * 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 384 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_384(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit u1d[2*6]; + sp_digit u2d[2*6]; + sp_digit sd[2*6]; + sp_digit tmpd[2*6 * 5]; + sp_point_384 p1d; + sp_point_384 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p1; + sp_point_384* p2 = NULL; + sp_digit carry; + int64_t c; + int err; + + err = sp_384_point_new_6(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 6, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 6; + u2 = d + 2 * 6; + s = d + 4 * 6; + tmp = d + 6 * 6; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 6, hash, (int)hashLen); + sp_384_from_mp(u2, 6, r); + sp_384_from_mp(s, 6, sm); + sp_384_from_mp(p2->x, 6, pX); + sp_384_from_mp(p2->y, 6, pY); + sp_384_from_mp(p2->z, 6, pZ); + + { + sp_384_mul_6(s, s, p384_norm_order); + } + err = sp_384_mod_6(s, s, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_6(s); + { + sp_384_mont_inv_order_6(s, s, tmp); + sp_384_mont_mul_order_6(u1, u1, s); + sp_384_mont_mul_order_6(u2, u2, s); + } + + err = sp_384_ecc_mulmod_base_6(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_6(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + { + sp_384_proj_point_add_6(p1, p1, p2, tmp); + if (sp_384_iszero_6(p1->z)) { + if (sp_384_iszero_6(p1->x) && sp_384_iszero_6(p1->y)) { + sp_384_proj_point_dbl_6(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + } + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 6, r); + err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_6(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_6(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 6, r); + carry = sp_384_add_6(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_6(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_6(u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_6(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_384_point_free_6(p1, 0, heap); + sp_384_point_free_6(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_384_ecc_is_point_6(sp_point_384* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*6]; + sp_digit t2d[2*6]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 6; + t2 = d + 2 * 6; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_384_sqr_6(t1, point->y); + (void)sp_384_mod_6(t1, t1, p384_mod); + sp_384_sqr_6(t2, point->x); + (void)sp_384_mod_6(t2, t2, p384_mod); + sp_384_mul_6(t2, t2, point->x); + (void)sp_384_mod_6(t2, t2, p384_mod); + (void)sp_384_sub_6(t2, p384_mod, t2); + sp_384_mont_add_6(t1, t1, t2, p384_mod); + + sp_384_mont_add_6(t1, t1, point->x, p384_mod); + sp_384_mont_add_6(t1, t1, point->x, p384_mod); + sp_384_mont_add_6(t1, t1, point->x, p384_mod); + + if (sp_384_cmp_6(t1, p384_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 pubd; +#endif + sp_point_384* pub; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_6(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_384_from_mp(pub->x, 6, pX); + sp_384_from_mp(pub->y, 6, pY); + sp_384_from_bin(pub->z, 6, one, (int)sizeof(one)); + + err = sp_384_ecc_is_point_6(pub, NULL); + } + + sp_384_point_free_6(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[6]; + sp_point_384 pubd; + sp_point_384 pd; +#endif + sp_digit* priv = NULL; + sp_point_384* pub; + sp_point_384* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_6(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_384_from_mp(pub->x, 6, pX); + sp_384_from_mp(pub->y, 6, pY); + sp_384_from_bin(pub->z, 6, one, (int)sizeof(one)); + sp_384_from_mp(priv, 6, privm); + + /* Check point at infinitiy. */ + if ((sp_384_iszero_6(pub->x) != 0) && + (sp_384_iszero_6(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_384_cmp_6(pub->x, p384_mod) >= 0 || + sp_384_cmp_6(pub->y, p384_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_384_ecc_is_point_6(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_384_ecc_mulmod_6(p, pub, p384_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_384_iszero_6(p->x) == 0) || + (sp_384_iszero_6(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_384_ecc_mulmod_base_6(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_384_cmp_6(p->x, pub->x) != 0 || + sp_384_cmp_6(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(p, 0, heap); + sp_384_point_free_6(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 6 * 5]; + sp_point_384 pd; + sp_point_384 qd; +#endif + sp_digit* tmp; + sp_point_384* p; + sp_point_384* q = NULL; + int err; + + err = sp_384_point_new_6(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_384_point_new_6(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 6, pX); + sp_384_from_mp(p->y, 6, pY); + sp_384_from_mp(p->z, 6, pZ); + sp_384_from_mp(q->x, 6, qX); + sp_384_from_mp(q->y, 6, qY); + sp_384_from_mp(q->z, 6, qZ); + + sp_384_proj_point_add_6(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(q, 0, NULL); + sp_384_point_free_6(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 6 * 2]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_6(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 6, pX); + sp_384_from_mp(p->y, 6, pY); + sp_384_from_mp(p->z, 6, pZ); + + sp_384_proj_point_dbl_6(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 6 * 6]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_6(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 6, pX); + sp_384_from_mp(p->y, 6, pY); + sp_384_from_mp(p->z, 6, pZ); + + sp_384_map_6(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mont_sqrt_6(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 6]; + sp_digit t2d[2 * 6]; + sp_digit t3d[2 * 6]; + sp_digit t4d[2 * 6]; + sp_digit t5d[2 * 6]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 6, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 6; + t2 = d + 2 * 6; + t3 = d + 4 * 6; + t4 = d + 6 * 6; + t5 = d + 8 * 6; +#else + t1 = t1d; + t2 = t2d; + t3 = t3d; + t4 = t4d; + t5 = t5d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_384_mont_sqr_6(t2, y, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3 */ + sp_384_mont_mul_6(t1, t2, y, p384_mod, p384_mp_mod); + /* t5 = y ^ 0xc */ + sp_384_mont_sqr_n_6(t5, t1, 2, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xf */ + sp_384_mont_mul_6(t1, t1, t5, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x1e */ + sp_384_mont_sqr_6(t2, t1, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x1f */ + sp_384_mont_mul_6(t3, t2, y, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3e0 */ + sp_384_mont_sqr_n_6(t2, t3, 5, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3ff */ + sp_384_mont_mul_6(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fe0 */ + sp_384_mont_sqr_n_6(t2, t1, 5, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x7fff */ + sp_384_mont_mul_6(t3, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fff800 */ + sp_384_mont_sqr_n_6(t2, t3, 15, p384_mod, p384_mp_mod); + /* t4 = y ^ 0x3ffffff */ + sp_384_mont_mul_6(t4, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffc000000 */ + sp_384_mont_sqr_n_6(t2, t4, 30, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffff */ + sp_384_mont_mul_6(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_6(t2, t1, 60, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_6(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_6(t2, t1, 120, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_6(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_6(t2, t1, 15, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_6(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */ + sp_384_mont_sqr_n_6(t2, t1, 31, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */ + sp_384_mont_mul_6(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */ + sp_384_mont_sqr_n_6(t2, t1, 4, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */ + sp_384_mont_mul_6(t1, t5, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */ + sp_384_mont_sqr_n_6(t2, t1, 62, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */ + sp_384_mont_mul_6(t1, y, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */ + sp_384_mont_sqr_n_6(y, t1, 30, p384_mod, p384_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 6]; + sp_digit yd[2 * 6]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 6, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 6; + y = d + 2 * 6; +#else + x = xd; + y = yd; +#endif + + sp_384_from_mp(x, 6, xm); + err = sp_384_mod_mul_norm_6(x, x, p384_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_384_mont_sqr_6(y, x, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(y, y, x, p384_mod, p384_mp_mod); + } + /* y = x^3 - 3x */ + sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_sub_6(y, y, x, p384_mod); + /* y = x^3 - 3x + b */ + err = sp_384_mod_mul_norm_6(x, p384_b, p384_mod); + } + if (err == MP_OKAY) { + sp_384_mont_add_6(y, y, x, p384_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_384_mont_sqrt_6(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 6, 0, 6U * sizeof(sp_digit)); + sp_384_mont_reduce_6(y, p384_mod, p384_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_384_mont_sub_6(y, p384_mod, y, p384_mod); + } + + err = sp_384_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_384 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_SP_ARM64_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_armthumb.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_armthumb.c new file mode 100644 index 000000000..40cb431a3 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_armthumb.c @@ -0,0 +1,27863 @@ +/* sp.c + * + * Copyright (C) 2006-2020 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 +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifdef WOLFSSL_SP_ARM_THUMB_ASM +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * 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<64 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + 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. + */ +SP_NOINLINE static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[8 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #32\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #28\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #56\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + 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. + */ +SP_NOINLINE static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #64\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #28\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #32\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #56\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #60\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #64\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_16(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + 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_8(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[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. + */ +SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit b1[8]; + sp_digit z2[16]; + sp_digit u, ca, cb; + + ca = sp_2048_add_8(a1, a, &a[8]); + cb = sp_2048_add_8(b1, b, &b[8]); + u = ca & cb; + sp_2048_mul_8(z1, a1, b1); + sp_2048_mul_8(z2, &a[8], &b[8]); + sp_2048_mul_8(z0, a, b); + sp_2048_mask_8(r + 16, a1, 0 - cb); + sp_2048_mask_8(b1, b1, 0 - ca); + u += sp_2048_add_8(r + 16, r + 16, b1); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + (void)sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[16]; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit u; + + u = sp_2048_add_8(a1, a, &a[8]); + sp_2048_sqr_8(z1, a1); + sp_2048_sqr_8(z2, &a[8]); + sp_2048_sqr_8(z0, a); + sp_2048_mask_8(r + 16, a1, 0 - u); + u += sp_2048_add_8(r + 16, r + 16, r + 16); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + (void)sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_32(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + 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, const 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. + */ +SP_NOINLINE 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)); + (void)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. + */ +SP_NOINLINE 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)); + (void)sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_64(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mvn r7, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "add %[r], #0x80\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r7" + ); + + 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_32(sp_digit* r, const 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 +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit b1[32]; + sp_digit z2[64]; + sp_digit u, ca, cb; + + ca = sp_2048_add_32(a1, a, &a[32]); + cb = sp_2048_add_32(b1, b, &b[32]); + u = ca & cb; + sp_2048_mul_32(z1, a1, b1); + sp_2048_mul_32(z2, &a[32], &b[32]); + sp_2048_mul_32(z0, a, b); + sp_2048_mask_32(r + 64, a1, 0 - cb); + sp_2048_mask_32(b1, b1, 0 - ca); + u += sp_2048_add_32(r + 64, r + 64, b1); + u += sp_2048_sub_in_place_64(z1, z2); + u += sp_2048_sub_in_place_64(z1, z0); + u += sp_2048_add_64(r + 32, r + 32, z1); + r[96] = u; + XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1)); + (void)sp_2048_add_64(r + 64, r + 64, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[64]; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit u; + + u = sp_2048_add_32(a1, a, &a[32]); + sp_2048_sqr_32(z1, a1); + sp_2048_sqr_32(z2, &a[32]); + sp_2048_sqr_32(z0, a); + sp_2048_mask_32(r + 64, a1, 0 - u); + u += sp_2048_add_32(r + 64, r + 64, r + 64); + u += sp_2048_sub_in_place_64(z1, z2); + u += sp_2048_sub_in_place_64(z1, z0); + u += sp_2048_add_64(r + 32, r + 32, z1); + r[96] = u; + XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1)); + (void)sp_2048_add_64(r + 64, r + 64, z2); +} + +#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. + */ +SP_NOINLINE static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "mov r4, #1\n\t" + "lsl r4, #8\n\t" + "sub r7, #1\n\t" + "add r6, r4\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_64(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "mov r5, #1\n\t" + "lsl r5, #8\n\t" + "add r7, r5\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[64 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #252\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + 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. + */ +SP_NOINLINE static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #252\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #1\n\t" + "lsl r3, r3, #8\n\t" + "add r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<32; i++) { + r[i] = a[i] & m; + } +} + +#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. + */ +SP_NOINLINE static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, #128\n\t" + "sub r7, #1\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_32(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "add r7, #128\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[32 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #128\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #124\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + 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. + */ +SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #124\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #128\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* 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. + */ +SP_NOINLINE static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_2048_mont_norm_32(sp_digit* r, const 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. + */ +SP_NOINLINE static sp_digit sp_2048_cond_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #128\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + 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, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #124\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+31] += m[31] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[31] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[31] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #128\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + 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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const 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. + */ +SP_NOINLINE static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #128\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + 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. + */ +SP_NOINLINE static int32_t sp_2048_cmp_32(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #124\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + 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 WC_INLINE int sp_2048_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (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); + + 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, d, (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 WC_INLINE int sp_2048_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_32(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][64]; +#else + sp_digit* t[16]; + 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) * 16 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 64; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32U); + if (reduceA != 0) { + 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); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + 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); + } + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U); + 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; +} +#else +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const 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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 64; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32U); + if (reduceA != 0) { + 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) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 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); + } + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U); + 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 /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* 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 single precision number. + */ +static void sp_2048_mont_norm_64(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 64); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_64(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* 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. + */ +SP_NOINLINE static sp_digit sp_2048_cond_sub_64(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #1\n\t" + "lsl r5, r5, #8\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + 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_64(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #252\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+63] += m[63] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[63] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[63] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #1\n\t" + "lsl r4, r4, #8\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_2048_cond_sub_64(a - 64, 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_64(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_2048_mul_64(r, a, b); + sp_2048_mont_reduce_64(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_64(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_64(r, a); + sp_2048_mont_reduce_64(r, m, mp); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_2048_word_64(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + 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_64(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<64; 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; + } +#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. + */ +SP_NOINLINE static int32_t sp_2048_cmp_64(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #252\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + 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 WC_INLINE int sp_2048_div_64(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_2048_mul_d_64(t2, d, r1); + t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + sp_2048_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2); + sp_2048_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_64(t1, d) >= 0; + sp_2048_cond_sub_64(r, t1, d, (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 WC_INLINE int sp_2048_mod_64(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_64(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 WC_INLINE int sp_2048_div_64_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_2048_mul_d_64(t2, d, r1); + t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + if (t1[64 + i] != 0) { + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d); + if (t1[64 + i] != 0) + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d); + } + } + + r1 = sp_2048_cmp_64(t1, d) >= 0; + sp_2048_cond_sub_64(r, t1, d, (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 WC_INLINE int sp_2048_mod_64_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_64_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* 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_64(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][128]; +#else + sp_digit* t[16]; + 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) * 16 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 128; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64U); + if (reduceA != 0) { + err = sp_2048_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) { + err = sp_2048_mod_64(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_2048_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_64(t[10], t[ 5], m, mp); + sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_64(t[12], t[ 6], m, mp); + sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_64(t[14], t[ 7], m, mp); + sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_mont_mul_64(r, r, t[y], m, mp); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#else +/* 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_64(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][128]; +#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 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 128; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64U); + if (reduceA != 0) { + err = sp_2048_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) { + err = sp_2048_mod_64(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_2048_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_64(t[10], t[ 5], m, mp); + sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_64(t[12], t[ 6], m, mp); + sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_64(t[14], t[ 7], m, mp); + sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_64(t[16], t[ 8], m, mp); + sp_2048_mont_mul_64(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_64(t[18], t[ 9], m, mp); + sp_2048_mont_mul_64(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_64(t[20], t[10], m, mp); + sp_2048_mont_mul_64(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_64(t[22], t[11], m, mp); + sp_2048_mont_mul_64(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_64(t[24], t[12], m, mp); + sp_2048_mont_mul_64(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_64(t[26], t[13], m, mp); + sp_2048_mont_mul_64(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_64(t[28], t[14], m, mp); + sp_2048_mont_mul_64(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_64(t[30], t[15], m, mp); + sp_2048_mont_mul_64(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_mont_mul_64(r, r, t[y], m, mp); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[128], m[64], r[128]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; +#endif + sp_digit *ah; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 64 * 2; + m = r + 64 * 2; + } +#endif + + if (err == MP_OKAY) { + ah = a + 64; + + sp_2048_from_bin(ah, 64, in, inLen); +#if DIGIT_BIT >= 32 + 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, 64, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_2048_sqr_64(r, ah); + err = sp_2048_mod_64_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_64(r, ah, r); + err = sp_2048_mod_64_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) * 64); + err = sp_2048_mod_64_cond(a, a, m); + + if (err == MP_OKAY) { + for (i = 31; i >= 0; i--) { + if (e[0] >> i) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 64); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_64(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) { + sp_2048_mont_mul_64(r, r, a, m, mp); + } + } + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_2048_mont_reduce_64(r, m, mp); + + for (i = 63; i > 0; i--) { + if (r[i] != m[i]) { + break; + } + } + if (r[i] >= m[i]) { + sp_2048_sub_in_place_64(r, m); + } + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) + 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 < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 2048) { + err = MP_READ_E; + } + if (inLen > 256) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 64; + m = a + 128; + r = a; + + sp_2048_from_bin(a, 64, in, inLen); + sp_2048_from_mp(d, 64, dm); + sp_2048_from_mp(m, 64, mm); + err = sp_2048_mod_exp_64(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) * 64); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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. + */ +SP_NOINLINE static sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #128\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, #1\n\t" + "add r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "adc r5, r6\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[64 * 2]; + sp_digit p[32], q[32], dp[32]; + sp_digit tmpa[64], tmpb[64]; +#else + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* tmpa; + sp_digit* tmpb; +#endif + sp_digit* r; + sp_digit* qi; + sp_digit* dq; + sp_digit c; + 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 (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 64 * 2; + q = p + 32; + qi = dq = dp = q + 32; + tmpa = qi + 32; + tmpb = tmpa + 64; + + r = t + 64; + } +#else +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + r = a; + qi = dq = dp; +#endif + sp_2048_from_bin(a, 64, in, inLen); + sp_2048_from_mp(p, 32, pm); + sp_2048_from_mp(q, 32, qm); + sp_2048_from_mp(dp, 32, dpm); + + err = sp_2048_mod_exp_32(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 32, dqm); + err = sp_2048_mod_exp_32(tmpb, a, dq, 1024, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_32(tmpa, tmpb); + c += sp_2048_cond_add_32(tmpa, tmpa, p, c); + sp_2048_cond_add_32(tmpa, tmpa, p, c); + + sp_2048_from_mp(qi, 32, qim); + sp_2048_mul_32(tmpa, tmpa, qi); + err = sp_2048_mod_32(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_32(tmpa, q, tmpa); + XMEMSET(&tmpb[32], 0, sizeof(sp_digit) * 32); + sp_2048_add_64(r, tmpb, tmpa); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + 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)); +#endif + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 64); + r->used = 64; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 64, base); + sp_2048_from_mp(e, 64, exp); + sp_2048_from_mp(m, 64, mod); + + err = sp_2048_mod_exp_64(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_2048 +static void sp_2048_lshift_64(sp_digit* r, sp_digit* a, byte n) +{ + __asm__ __volatile__ ( + "mov r6, #31\n\t" + "sub r6, r6, %[n]\n\t" + "add %[a], %[a], #192\n\t" + "add %[r], %[r], #192\n\t" + "ldr r3, [%[a], #60]\n\t" + "lsr r4, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r4, r4, r6\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r4, [%[a], #60]\n\t" + "str r3, [%[r], #68]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #56]\n\t" + "str r2, [%[r], #64]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #52]\n\t" + "str r4, [%[r], #60]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #48]\n\t" + "str r3, [%[r], #56]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #44]\n\t" + "str r2, [%[r], #52]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #40]\n\t" + "str r4, [%[r], #48]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #36]\n\t" + "str r3, [%[r], #44]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #32]\n\t" + "str r2, [%[r], #40]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #28]\n\t" + "str r4, [%[r], #36]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #24]\n\t" + "str r3, [%[r], #32]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #20]\n\t" + "str r2, [%[r], #28]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #16]\n\t" + "str r4, [%[r], #24]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #12]\n\t" + "str r3, [%[r], #20]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #8]\n\t" + "str r2, [%[r], #16]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #4]\n\t" + "str r4, [%[r], #12]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #0]\n\t" + "str r3, [%[r], #8]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r3, [%[a], #60]\n\t" + "str r2, [%[r], #68]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "str r3, [%[r]]\n\t" + "str r4, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [n] "r" (n) + : "memory", "r2", "r3", "r4", "r5", "r6" + ); +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_64(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[128]; + sp_digit td[65]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 193, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 128; +#else + norm = nd; + tmp = td; +#endif + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + sp_2048_lshift_64(r, norm, y); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_lshift_64(r, r, y); + sp_2048_mul_d_64(tmp, norm, r[64]); + r[64] = 0; + o = sp_2048_add_64(r, r, tmp); + sp_2048_cond_sub_64(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* HAVE_FFDHE_2048 */ + +/* 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. + * returns 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[128], e[64], m[64]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 256) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 64, base); + sp_2048_from_bin(e, 64, exp, expLen); + sp_2048_from_mp(m, 64, mod); + + #ifdef HAVE_FFDHE_2048 + if (base->used == 1 && base->dp[0] == 2 && m[63] == (sp_digit)-1) + err = sp_2048_mod_exp_2_64(r, e, expLen * 8, m); + else + #endif + err = sp_2048_mod_exp_64(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 */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_mp(e, 32, exp); + sp_2048_from_mp(m, 32, mod); + + err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 32, 0, sizeof(*r) * 32U); + err = sp_2048_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * 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<96 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + 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. + */ +SP_NOINLINE static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[12 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #48\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #44\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #88\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + 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. + */ +SP_NOINLINE static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #96\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #44\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #48\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #88\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #92\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #96\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_24(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + 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_12(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<12; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; + r[8] = a[8] & m; + r[9] = a[9] & m; + r[10] = a[10] & m; + r[11] = a[11] & 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. + */ +SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[24]; + sp_digit a1[12]; + sp_digit b1[12]; + sp_digit z2[24]; + sp_digit u, ca, cb; + + ca = sp_3072_add_12(a1, a, &a[12]); + cb = sp_3072_add_12(b1, b, &b[12]); + u = ca & cb; + sp_3072_mul_12(z1, a1, b1); + sp_3072_mul_12(z2, &a[12], &b[12]); + sp_3072_mul_12(z0, a, b); + sp_3072_mask_12(r + 24, a1, 0 - cb); + sp_3072_mask_12(b1, b1, 0 - ca); + u += sp_3072_add_12(r + 24, r + 24, b1); + u += sp_3072_sub_in_place_24(z1, z2); + u += sp_3072_sub_in_place_24(z1, z0); + u += sp_3072_add_24(r + 12, r + 12, z1); + r[36] = u; + XMEMSET(r + 36 + 1, 0, sizeof(sp_digit) * (12 - 1)); + (void)sp_3072_add_24(r + 24, r + 24, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[24]; + sp_digit z1[24]; + sp_digit a1[12]; + sp_digit u; + + u = sp_3072_add_12(a1, a, &a[12]); + sp_3072_sqr_12(z1, a1); + sp_3072_sqr_12(z2, &a[12]); + sp_3072_sqr_12(z0, a); + sp_3072_mask_12(r + 24, a1, 0 - u); + u += sp_3072_add_12(r + 24, r + 24, r + 24); + u += sp_3072_sub_in_place_24(z1, z2); + u += sp_3072_sub_in_place_24(z1, z0); + u += sp_3072_add_24(r + 12, r + 12, z1); + r[36] = u; + XMEMSET(r + 36 + 1, 0, sizeof(sp_digit) * (12 - 1)); + (void)sp_3072_add_24(r + 24, r + 24, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_48(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mvn r7, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "add %[r], #0x80\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r7" + ); + + 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, const 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. + */ +SP_NOINLINE 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)); + (void)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. + */ +SP_NOINLINE 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)); + (void)sp_3072_add_48(r + 48, r + 48, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_96(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mvn r7, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "add %[r], #0x80\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "add %[r], #0x80\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r7" + ); + + 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_48(sp_digit* r, const 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 +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[96]; + sp_digit a1[48]; + sp_digit b1[48]; + sp_digit z2[96]; + sp_digit u, ca, cb; + + ca = sp_3072_add_48(a1, a, &a[48]); + cb = sp_3072_add_48(b1, b, &b[48]); + u = ca & cb; + sp_3072_mul_48(z1, a1, b1); + sp_3072_mul_48(z2, &a[48], &b[48]); + sp_3072_mul_48(z0, a, b); + sp_3072_mask_48(r + 96, a1, 0 - cb); + sp_3072_mask_48(b1, b1, 0 - ca); + u += sp_3072_add_48(r + 96, r + 96, b1); + u += sp_3072_sub_in_place_96(z1, z2); + u += sp_3072_sub_in_place_96(z1, z0); + u += sp_3072_add_96(r + 48, r + 48, z1); + r[144] = u; + XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1)); + (void)sp_3072_add_96(r + 96, r + 96, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[96]; + sp_digit z1[96]; + sp_digit a1[48]; + sp_digit u; + + u = sp_3072_add_48(a1, a, &a[48]); + sp_3072_sqr_48(z1, a1); + sp_3072_sqr_48(z2, &a[48]); + sp_3072_sqr_48(z0, a); + sp_3072_mask_48(r + 96, a1, 0 - u); + u += sp_3072_add_48(r + 96, r + 96, r + 96); + u += sp_3072_sub_in_place_96(z1, z2); + u += sp_3072_sub_in_place_96(z1, z0); + u += sp_3072_add_96(r + 48, r + 48, z1); + r[144] = u; + XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1)); + (void)sp_3072_add_96(r + 96, r + 96, z2); +} + +#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. + */ +SP_NOINLINE static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "mov r4, #1\n\t" + "lsl r4, #8\n\t" + "add r4, #128\n\t" + "sub r7, #1\n\t" + "add r6, r4\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_96(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "mov r5, #1\n\t" + "lsl r5, #8\n\t" + "add r5, #128\n\t" + "add r7, r5\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[96 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #128\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #124\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + 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. + */ +SP_NOINLINE static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #3\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #124\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #128\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #2\n\t" + "lsl r3, r3, #8\n\t" + "add r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #3\n\t" + "lsl r6, r6, #8\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<48; i++) { + r[i] = a[i] & m; + } +} + +#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. + */ +SP_NOINLINE static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, #192\n\t" + "sub r7, #1\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_48(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "add r7, #192\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[48 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #192\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #188\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #120\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + 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. + */ +SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #128\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #188\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #192\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #120\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #1\n\t" + "lsl r3, r3, #8\n\t" + "add r3, #124\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #128\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* 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. + */ +SP_NOINLINE static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #128\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_3072_mont_norm_48(sp_digit* r, const 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. + */ +SP_NOINLINE static sp_digit sp_3072_cond_sub_48(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #192\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + 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, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #188\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+47] += m[47] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[47] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[47] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #192\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + 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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const 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. + */ +SP_NOINLINE static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #192\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + 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. + */ +SP_NOINLINE static int32_t sp_3072_cmp_48(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #188\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + 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 WC_INLINE int sp_3072_div_48(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; + + (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); + + 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, d, (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 WC_INLINE int sp_3072_mod_48(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_48(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][96]; +#else + sp_digit* t[16]; + 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) * 16 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 96; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48U); + if (reduceA != 0) { + 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); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + 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); + } + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U); + 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; +} +#else +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const 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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 96; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48U); + if (reduceA != 0) { + 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) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 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); + } + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U); + 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 /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* 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 single precision number. + */ +static void sp_3072_mont_norm_96(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 96); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_96(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* 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. + */ +SP_NOINLINE static sp_digit sp_3072_cond_sub_96(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #1\n\t" + "lsl r5, r5, #8\n\t" + "add r5, #128\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + 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_96(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #1\n\t" + "lsl r4, r4, #8\n\t" + "add r4, #124\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+95] += m[95] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[95] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[95] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #1\n\t" + "lsl r4, r4, #8\n\t" + "add r4, #128\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_3072_cond_sub_96(a - 96, 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_96(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_3072_mul_96(r, a, b); + sp_3072_mont_reduce_96(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_96(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_96(r, a); + sp_3072_mont_reduce_96(r, m, mp); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_3072_word_96(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + 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_96(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<96; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 96; 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. + */ +SP_NOINLINE static int32_t sp_3072_cmp_96(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #124\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + 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 WC_INLINE int sp_3072_div_96(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[192], t2[97]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[95]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 96); + for (i=95; i>=0; i--) { + r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div); + + sp_3072_mul_d_96(t2, d, r1); + t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2); + t1[96 + i] -= t2[96]; + sp_3072_mask_96(t2, d, t1[96 + i]); + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2); + sp_3072_mask_96(t2, d, t1[96 + i]); + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_96(t1, d) >= 0; + sp_3072_cond_sub_96(r, t1, d, (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 WC_INLINE int sp_3072_mod_96(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_96(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 WC_INLINE int sp_3072_div_96_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[192], t2[97]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[95]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 96); + for (i=95; i>=0; i--) { + r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div); + + sp_3072_mul_d_96(t2, d, r1); + t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2); + t1[96 + i] -= t2[96]; + if (t1[96 + i] != 0) { + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d); + if (t1[96 + i] != 0) + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d); + } + } + + r1 = sp_3072_cmp_96(t1, d) >= 0; + sp_3072_cond_sub_96(r, t1, d, (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 WC_INLINE int sp_3072_mod_96_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_96_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* 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_96(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][192]; +#else + sp_digit* t[16]; + 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) * 16 * 192, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 192; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 96U); + if (reduceA != 0) { + err = sp_3072_mod_96(t[1] + 96, a, m); + if (err == MP_OKAY) { + err = sp_3072_mod_96(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96); + err = sp_3072_mod_96(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_96(t[10], t[ 5], m, mp); + sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_96(t[12], t[ 6], m, mp); + sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_96(t[14], t[ 7], m, mp); + sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 96); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_mont_mul_96(r, r, t[y], m, mp); + } + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#else +/* 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_96(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][192]; +#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 * 192, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 192; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 96U); + if (reduceA != 0) { + err = sp_3072_mod_96(t[1] + 96, a, m); + if (err == MP_OKAY) { + err = sp_3072_mod_96(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96); + err = sp_3072_mod_96(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_96(t[10], t[ 5], m, mp); + sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_96(t[12], t[ 6], m, mp); + sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_96(t[14], t[ 7], m, mp); + sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_96(t[16], t[ 8], m, mp); + sp_3072_mont_mul_96(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_96(t[18], t[ 9], m, mp); + sp_3072_mont_mul_96(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_96(t[20], t[10], m, mp); + sp_3072_mont_mul_96(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_96(t[22], t[11], m, mp); + sp_3072_mont_mul_96(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_96(t[24], t[12], m, mp); + sp_3072_mont_mul_96(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_96(t[26], t[13], m, mp); + sp_3072_mont_mul_96(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_96(t[28], t[14], m, mp); + sp_3072_mont_mul_96(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_96(t[30], t[15], m, mp); + sp_3072_mont_mul_96(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 96); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_mont_mul_96(r, r, t[y], m, mp); + } + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[192], m[96], r[192]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; +#endif + sp_digit *ah; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 96 * 2; + m = r + 96 * 2; + } +#endif + + if (err == MP_OKAY) { + ah = a + 96; + + sp_3072_from_bin(ah, 96, in, inLen); +#if DIGIT_BIT >= 32 + 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, 96, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_3072_sqr_96(r, ah); + err = sp_3072_mod_96_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_96(r, ah, r); + err = sp_3072_mod_96_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) * 96); + err = sp_3072_mod_96_cond(a, a, m); + + if (err == MP_OKAY) { + for (i = 31; i >= 0; i--) { + if (e[0] >> i) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 96); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_96(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) { + sp_3072_mont_mul_96(r, r, a, m, mp); + } + } + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96); + sp_3072_mont_reduce_96(r, m, mp); + + for (i = 95; i > 0; i--) { + if (r[i] != m[i]) { + break; + } + } + if (r[i] >= m[i]) { + sp_3072_sub_in_place_96(r, m); + } + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) + 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 < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 3072) { + err = MP_READ_E; + } + if (inLen > 384) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 96; + m = a + 192; + r = a; + + sp_3072_from_bin(a, 96, in, inLen); + sp_3072_from_mp(d, 96, dm); + sp_3072_from_mp(m, 96, mm); + err = sp_3072_mod_exp_96(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) * 96); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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. + */ +SP_NOINLINE static sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #192\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, #1\n\t" + "add r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "adc r5, r6\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[96 * 2]; + sp_digit p[48], q[48], dp[48]; + sp_digit tmpa[96], tmpb[96]; +#else + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* tmpa; + sp_digit* tmpb; +#endif + sp_digit* r; + sp_digit* qi; + sp_digit* dq; + sp_digit c; + 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 (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 96 * 2; + q = p + 48; + qi = dq = dp = q + 48; + tmpa = qi + 48; + tmpb = tmpa + 96; + + r = t + 96; + } +#else +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + r = a; + qi = dq = dp; +#endif + sp_3072_from_bin(a, 96, in, inLen); + sp_3072_from_mp(p, 48, pm); + sp_3072_from_mp(q, 48, qm); + sp_3072_from_mp(dp, 48, dpm); + + err = sp_3072_mod_exp_48(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 48, dqm); + err = sp_3072_mod_exp_48(tmpb, a, dq, 1536, q, 1); + } + + if (err == MP_OKAY) { + c = sp_3072_sub_in_place_48(tmpa, tmpb); + c += sp_3072_cond_add_48(tmpa, tmpa, p, c); + sp_3072_cond_add_48(tmpa, tmpa, p, c); + + sp_3072_from_mp(qi, 48, qim); + sp_3072_mul_48(tmpa, tmpa, qi); + err = sp_3072_mod_48(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_48(tmpa, q, tmpa); + XMEMSET(&tmpb[48], 0, sizeof(sp_digit) * 48); + sp_3072_add_96(r, tmpb, tmpa); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 48 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + 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)); +#endif + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 96); + r->used = 96; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 96; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 96; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[192], e[96], m[96]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 96, base); + sp_3072_from_mp(e, 96, exp); + sp_3072_from_mp(m, 96, mod); + + err = sp_3072_mod_exp_96(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_3072 +static void sp_3072_lshift_96(sp_digit* r, sp_digit* a, byte n) +{ + __asm__ __volatile__ ( + "mov r6, #31\n\t" + "sub r6, r6, %[n]\n\t" + "add %[a], %[a], #255\n\t" + "add %[r], %[r], #255\n\t" + "add %[a], %[a], #65\n\t" + "add %[r], %[r], #65\n\t" + "ldr r3, [%[a], #60]\n\t" + "lsr r4, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r4, r4, r6\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r4, [%[a], #60]\n\t" + "str r3, [%[r], #68]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #56]\n\t" + "str r2, [%[r], #64]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #52]\n\t" + "str r4, [%[r], #60]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #48]\n\t" + "str r3, [%[r], #56]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #44]\n\t" + "str r2, [%[r], #52]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #40]\n\t" + "str r4, [%[r], #48]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #36]\n\t" + "str r3, [%[r], #44]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #32]\n\t" + "str r2, [%[r], #40]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #28]\n\t" + "str r4, [%[r], #36]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #24]\n\t" + "str r3, [%[r], #32]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #20]\n\t" + "str r2, [%[r], #28]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #16]\n\t" + "str r4, [%[r], #24]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #12]\n\t" + "str r3, [%[r], #20]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #8]\n\t" + "str r2, [%[r], #16]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #4]\n\t" + "str r4, [%[r], #12]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #0]\n\t" + "str r3, [%[r], #8]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r3, [%[a], #60]\n\t" + "str r2, [%[r], #68]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r4, [%[a], #60]\n\t" + "str r3, [%[r], #68]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #56]\n\t" + "str r2, [%[r], #64]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #52]\n\t" + "str r4, [%[r], #60]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #48]\n\t" + "str r3, [%[r], #56]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #44]\n\t" + "str r2, [%[r], #52]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #40]\n\t" + "str r4, [%[r], #48]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #36]\n\t" + "str r3, [%[r], #44]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #32]\n\t" + "str r2, [%[r], #40]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #28]\n\t" + "str r4, [%[r], #36]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #24]\n\t" + "str r3, [%[r], #32]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #20]\n\t" + "str r2, [%[r], #28]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #16]\n\t" + "str r4, [%[r], #24]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #12]\n\t" + "str r3, [%[r], #20]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #8]\n\t" + "str r2, [%[r], #16]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #4]\n\t" + "str r4, [%[r], #12]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #0]\n\t" + "str r3, [%[r], #8]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "str r4, [%[r]]\n\t" + "str r2, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [n] "r" (n) + : "memory", "r2", "r3", "r4", "r5", "r6" + ); +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_96(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[192]; + sp_digit td[97]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 289, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 192; +#else + norm = nd; + tmp = td; +#endif + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + sp_3072_lshift_96(r, norm, y); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_lshift_96(r, r, y); + sp_3072_mul_d_96(tmp, norm, r[96]); + r[96] = 0; + o = sp_3072_add_96(r, r, tmp); + sp_3072_cond_sub_96(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* HAVE_FFDHE_3072 */ + +/* 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. + * returns 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[192], e[96], m[96]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 384) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 96, base); + sp_3072_from_bin(e, 96, exp, expLen); + sp_3072_from_mp(m, 96, mod); + + #ifdef HAVE_FFDHE_3072 + if (base->used == 1 && base->dp[0] == 2 && m[95] == (sp_digit)-1) + err = sp_3072_mod_exp_2_96(r, e, expLen * 8, m); + else + #endif + err = sp_3072_mod_exp_96(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 */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_mp(e, 48, exp); + sp_3072_from_mp(m, 48, mod); + + err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 48, 0, sizeof(*r) * 48U); + err = sp_3072_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#ifdef WOLFSSL_SP_4096 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 512 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_4096_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 4096 / 8 - 1; + a[j] = 0; + for (i=0; i<128 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + a[j] = 0; + } + if (s != 0) { + j++; + } + } +} + +#ifndef 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. + */ +SP_NOINLINE static sp_digit sp_4096_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mvn r7, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "add %[r], #0x80\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r7" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_4096_sub_in_place_128(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_4096_add_128(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mvn r7, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "add %[r], #0x80\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "add %[r], #0x80\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "add %[r], #0x80\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r7" + ); + + return c; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_4096_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[64 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #252\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* 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_4096_mask_64(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<64; 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; + } +#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. + */ +SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[128]; + sp_digit a1[64]; + sp_digit b1[64]; + sp_digit z2[128]; + sp_digit u, ca, cb; + + ca = sp_2048_add_64(a1, a, &a[64]); + cb = sp_2048_add_64(b1, b, &b[64]); + u = ca & cb; + sp_2048_mul_64(z1, a1, b1); + sp_2048_mul_64(z2, &a[64], &b[64]); + sp_2048_mul_64(z0, a, b); + sp_2048_mask_64(r + 128, a1, 0 - cb); + sp_2048_mask_64(b1, b1, 0 - ca); + u += sp_2048_add_64(r + 128, r + 128, b1); + u += sp_4096_sub_in_place_128(z1, z2); + u += sp_4096_sub_in_place_128(z1, z0); + u += sp_4096_add_128(r + 64, r + 64, z1); + r[192] = u; + XMEMSET(r + 192 + 1, 0, sizeof(sp_digit) * (64 - 1)); + (void)sp_4096_add_128(r + 128, r + 128, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_4096_sqr_64(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #252\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #1\n\t" + "lsl r3, r3, #8\n\t" + "add r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[128]; + sp_digit z1[128]; + sp_digit a1[64]; + sp_digit u; + + u = sp_2048_add_64(a1, a, &a[64]); + sp_2048_sqr_64(z1, a1); + sp_2048_sqr_64(z2, &a[64]); + sp_2048_sqr_64(z0, a); + sp_2048_mask_64(r + 128, a1, 0 - u); + u += sp_2048_add_64(r + 128, r + 128, r + 128); + u += sp_4096_sub_in_place_128(z1, z2); + u += sp_4096_sub_in_place_128(z1, z0); + u += sp_4096_add_128(r + 64, r + 64, z1); + r[192] = u; + XMEMSET(r + 192 + 1, 0, sizeof(sp_digit) * (64 - 1)); + (void)sp_4096_add_128(r + 128, r + 128, z2); +} + +#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. + */ +SP_NOINLINE static sp_digit sp_4096_add_128(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "mov r4, #2\n\t" + "lsl r4, #8\n\t" + "sub r7, #1\n\t" + "add r6, r4\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_4096_sub_in_place_128(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "mov r5, #2\n\t" + "lsl r5, #8\n\t" + "add r7, r5\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[128 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #252\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #3\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + 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. + */ +SP_NOINLINE static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #4\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #252\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #3\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #3\n\t" + "lsl r3, r3, #8\n\t" + "add r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #4\n\t" + "lsl r6, r6, #8\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_4096_mont_setup(const 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 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* 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. + */ +SP_NOINLINE static void sp_4096_mul_d_128(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 4096 bits, just need to subtract. + * + * r A single precision number. + * m A single precision number. + */ +static void sp_4096_mont_norm_128(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 128); + + /* r = 2^n mod m */ + sp_4096_sub_in_place_128(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* 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. + */ +SP_NOINLINE static sp_digit sp_4096_cond_sub_128(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #2\n\t" + "lsl r5, r5, #8\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* Reduce the number back to 4096 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_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #1\n\t" + "lsl r4, r4, #8\n\t" + "add r4, #252\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+127] += m[127] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[127] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[127] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #2\n\t" + "lsl r4, r4, #8\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_4096_cond_sub_128(a - 128, 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_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_4096_mul_128(r, a, b); + sp_4096_mont_reduce_128(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_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_4096_sqr_128(r, a); + sp_4096_mont_reduce_128(r, m, mp); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_4096_word_128(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + 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_4096_mask_128(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<128; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 128; 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. + */ +SP_NOINLINE static int32_t sp_4096_cmp_128(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #252\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + 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 WC_INLINE int sp_4096_div_128(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[256], t2[129]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[127]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 128); + for (i=127; i>=0; i--) { + r1 = div_4096_word_128(t1[128 + i], t1[128 + i - 1], div); + + sp_4096_mul_d_128(t2, d, r1); + t1[128 + i] += sp_4096_sub_in_place_128(&t1[i], t2); + t1[128 + i] -= t2[128]; + sp_4096_mask_128(t2, d, t1[128 + i]); + t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], t2); + sp_4096_mask_128(t2, d, t1[128 + i]); + t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], t2); + } + + r1 = sp_4096_cmp_128(t1, d) >= 0; + sp_4096_cond_sub_128(r, t1, d, (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 WC_INLINE int sp_4096_mod_128(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_128(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 WC_INLINE int sp_4096_div_128_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[256], t2[129]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[127]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 128); + for (i=127; i>=0; i--) { + r1 = div_4096_word_128(t1[128 + i], t1[128 + i - 1], div); + + sp_4096_mul_d_128(t2, d, r1); + t1[128 + i] += sp_4096_sub_in_place_128(&t1[i], t2); + t1[128 + i] -= t2[128]; + if (t1[128 + i] != 0) { + t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], d); + if (t1[128 + i] != 0) + t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], d); + } + } + + r1 = sp_4096_cmp_128(t1, d) >= 0; + sp_4096_cond_sub_128(r, t1, d, (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 WC_INLINE int sp_4096_mod_128_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_128_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* 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_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][256]; +#else + sp_digit* t[16]; + 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) * 16 * 256, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 256; + } +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_128(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 128U); + if (reduceA != 0) { + err = sp_4096_mod_128(t[1] + 128, a, m); + if (err == MP_OKAY) { + err = sp_4096_mod_128(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 128, a, sizeof(sp_digit) * 128); + err = sp_4096_mod_128(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_128(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_128(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_128(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_128(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_128(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_128(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_128(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_128(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_128(t[10], t[ 5], m, mp); + sp_4096_mont_mul_128(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_128(t[12], t[ 6], m, mp); + sp_4096_mont_mul_128(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_128(t[14], t[ 7], m, mp); + sp_4096_mont_mul_128(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 128); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + + sp_4096_mont_mul_128(r, r, t[y], m, mp); + } + + XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U); + sp_4096_mont_reduce_128(r, m, mp); + + mask = 0 - (sp_4096_cmp_128(r, m) >= 0); + sp_4096_cond_sub_128(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#else +/* 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_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][256]; +#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 * 256, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 256; + } +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_128(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 128U); + if (reduceA != 0) { + err = sp_4096_mod_128(t[1] + 128, a, m); + if (err == MP_OKAY) { + err = sp_4096_mod_128(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 128, a, sizeof(sp_digit) * 128); + err = sp_4096_mod_128(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_128(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_128(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_128(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_128(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_128(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_128(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_128(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_128(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_128(t[10], t[ 5], m, mp); + sp_4096_mont_mul_128(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_128(t[12], t[ 6], m, mp); + sp_4096_mont_mul_128(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_128(t[14], t[ 7], m, mp); + sp_4096_mont_mul_128(t[15], t[ 8], t[ 7], m, mp); + sp_4096_mont_sqr_128(t[16], t[ 8], m, mp); + sp_4096_mont_mul_128(t[17], t[ 9], t[ 8], m, mp); + sp_4096_mont_sqr_128(t[18], t[ 9], m, mp); + sp_4096_mont_mul_128(t[19], t[10], t[ 9], m, mp); + sp_4096_mont_sqr_128(t[20], t[10], m, mp); + sp_4096_mont_mul_128(t[21], t[11], t[10], m, mp); + sp_4096_mont_sqr_128(t[22], t[11], m, mp); + sp_4096_mont_mul_128(t[23], t[12], t[11], m, mp); + sp_4096_mont_sqr_128(t[24], t[12], m, mp); + sp_4096_mont_mul_128(t[25], t[13], t[12], m, mp); + sp_4096_mont_sqr_128(t[26], t[13], m, mp); + sp_4096_mont_mul_128(t[27], t[14], t[13], m, mp); + sp_4096_mont_sqr_128(t[28], t[14], m, mp); + sp_4096_mont_mul_128(t[29], t[15], t[14], m, mp); + sp_4096_mont_sqr_128(t[30], t[15], m, mp); + sp_4096_mont_mul_128(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 128); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + + sp_4096_mont_mul_128(r, r, t[y], m, mp); + } + + XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U); + sp_4096_mont_reduce_128(r, m, mp); + + mask = 0 - (sp_4096_cmp_128(r, m) >= 0); + sp_4096_cond_sub_128(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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 512 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_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[256], m[128], r[256]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; +#endif + sp_digit *ah; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 512) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 512 || + mp_count_bits(mm) != 4096)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 128 * 2; + m = r + 128 * 2; + } +#endif + + if (err == MP_OKAY) { + ah = a + 128; + + sp_4096_from_bin(ah, 128, in, inLen); +#if DIGIT_BIT >= 32 + 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_4096_from_mp(m, 128, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_4096_sqr_128(r, ah); + err = sp_4096_mod_128_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_4096_mul_128(r, ah, r); + err = sp_4096_mod_128_cond(r, r, m); + } + } + else { + int i; + sp_digit mp; + + sp_4096_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 128); + err = sp_4096_mod_128_cond(a, a, m); + + if (err == MP_OKAY) { + for (i = 31; i >= 0; i--) { + if (e[0] >> i) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 128); + for (i--; i>=0; i--) { + sp_4096_mont_sqr_128(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) { + sp_4096_mont_mul_128(r, r, a, m, mp); + } + } + XMEMSET(&r[128], 0, sizeof(sp_digit) * 128); + sp_4096_mont_reduce_128(r, m, mp); + + for (i = 127; i > 0; i--) { + if (r[i] != m[i]) { + break; + } + } + if (r[i] >= m[i]) { + sp_4096_sub_in_place_128(r, m); + } + } + } + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) + 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 < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 4096) { + err = MP_READ_E; + } + if (inLen > 512) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 128; + m = a + 256; + r = a; + + sp_4096_from_bin(a, 128, in, inLen); + sp_4096_from_mp(d, 128, dm); + sp_4096_from_mp(m, 128, mm); + err = sp_4096_mod_exp_128(r, a, d, 4096, m, 0); + } + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 128); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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. + */ +SP_NOINLINE static sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #1\n\t" + "lsl r5, r5, #8\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, #1\n\t" + "add r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "adc r5, r6\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* 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 512 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_4096(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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[128 * 2]; + sp_digit p[64], q[64], dp[64]; + sp_digit tmpa[128], tmpb[128]; +#else + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* tmpa; + sp_digit* tmpb; +#endif + sp_digit* r; + sp_digit* qi; + sp_digit* dq; + sp_digit c; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 512) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 512 || mp_count_bits(mm) != 4096)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 128 * 2; + q = p + 64; + qi = dq = dp = q + 64; + tmpa = qi + 64; + tmpb = tmpa + 128; + + r = t + 128; + } +#else +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + r = a; + qi = dq = dp; +#endif + sp_4096_from_bin(a, 128, in, inLen); + sp_4096_from_mp(p, 64, pm); + sp_4096_from_mp(q, 64, qm); + sp_4096_from_mp(dp, 64, dpm); + + err = sp_2048_mod_exp_64(tmpa, a, dp, 2048, p, 1); + } + if (err == MP_OKAY) { + sp_4096_from_mp(dq, 64, dqm); + err = sp_2048_mod_exp_64(tmpb, a, dq, 2048, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_64(tmpa, tmpb); + c += sp_4096_cond_add_64(tmpa, tmpa, p, c); + sp_4096_cond_add_64(tmpa, tmpa, p, c); + + sp_2048_from_mp(qi, 64, qim); + sp_2048_mul_64(tmpa, tmpa, qi); + err = sp_2048_mod_64(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_64(tmpa, q, tmpa); + XMEMSET(&tmpb[64], 0, sizeof(sp_digit) * 64); + sp_4096_add_128(r, tmpb, tmpa); + + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 64 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + 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)); +#endif + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_4096_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 128); + r->used = 128; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 128; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 128; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[256], e[128], m[128]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 128, base); + sp_4096_from_mp(e, 128, exp); + sp_4096_from_mp(m, 128, mod); + + err = sp_4096_mod_exp_128(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_4096_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_4096 +static void sp_4096_lshift_128(sp_digit* r, sp_digit* a, byte n) +{ + __asm__ __volatile__ ( + "mov r6, #31\n\t" + "sub r6, r6, %[n]\n\t" + "add %[a], %[a], #255\n\t" + "add %[r], %[r], #255\n\t" + "add %[a], %[a], #193\n\t" + "add %[r], %[r], #193\n\t" + "ldr r3, [%[a], #60]\n\t" + "lsr r4, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r4, r4, r6\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r4, [%[a], #60]\n\t" + "str r3, [%[r], #68]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #56]\n\t" + "str r2, [%[r], #64]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #52]\n\t" + "str r4, [%[r], #60]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #48]\n\t" + "str r3, [%[r], #56]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #44]\n\t" + "str r2, [%[r], #52]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #40]\n\t" + "str r4, [%[r], #48]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #36]\n\t" + "str r3, [%[r], #44]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #32]\n\t" + "str r2, [%[r], #40]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #28]\n\t" + "str r4, [%[r], #36]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #24]\n\t" + "str r3, [%[r], #32]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #20]\n\t" + "str r2, [%[r], #28]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #16]\n\t" + "str r4, [%[r], #24]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #12]\n\t" + "str r3, [%[r], #20]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #8]\n\t" + "str r2, [%[r], #16]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #4]\n\t" + "str r4, [%[r], #12]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #0]\n\t" + "str r3, [%[r], #8]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r3, [%[a], #60]\n\t" + "str r2, [%[r], #68]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r4, [%[a], #60]\n\t" + "str r3, [%[r], #68]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #56]\n\t" + "str r2, [%[r], #64]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #52]\n\t" + "str r4, [%[r], #60]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #48]\n\t" + "str r3, [%[r], #56]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #44]\n\t" + "str r2, [%[r], #52]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #40]\n\t" + "str r4, [%[r], #48]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #36]\n\t" + "str r3, [%[r], #44]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #32]\n\t" + "str r2, [%[r], #40]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #28]\n\t" + "str r4, [%[r], #36]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #24]\n\t" + "str r3, [%[r], #32]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #20]\n\t" + "str r2, [%[r], #28]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #16]\n\t" + "str r4, [%[r], #24]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #12]\n\t" + "str r3, [%[r], #20]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #8]\n\t" + "str r2, [%[r], #16]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #4]\n\t" + "str r4, [%[r], #12]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #0]\n\t" + "str r3, [%[r], #8]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r3, [%[a], #60]\n\t" + "str r2, [%[r], #68]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "str r2, [%[r]]\n\t" + "str r3, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [n] "r" (n) + : "memory", "r2", "r3", "r4", "r5", "r6" + ); +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[256]; + sp_digit td[129]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 385, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 256; +#else + norm = nd; + tmp = td; +#endif + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_128(norm, m); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + sp_4096_lshift_128(r, norm, y); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + + sp_4096_lshift_128(r, r, y); + sp_4096_mul_d_128(tmp, norm, r[128]); + r[128] = 0; + o = sp_4096_add_128(r, r, tmp); + sp_4096_cond_sub_128(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U); + sp_4096_mont_reduce_128(r, m, mp); + + mask = 0 - (sp_4096_cmp_128(r, m) >= 0); + sp_4096_cond_sub_128(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* HAVE_FFDHE_4096 */ + +/* 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 512 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returns 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_4096(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[256], e[128], m[128]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 512) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 128, base); + sp_4096_from_bin(e, 128, exp, expLen); + sp_4096_from_mp(m, 128, mod); + + #ifdef HAVE_FFDHE_4096 + if (base->used == 1 && base->dp[0] == 2 && m[127] == (sp_digit)-1) + err = sp_4096_mod_exp_2_128(r, e, expLen * 8, m); + else + #endif + err = sp_4096_mod_exp_128(r, b, e, expLen * 8, m, 0); + + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + for (i=0; i<512 && 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_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* WOLFSSL_SP_4096 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point_256 { + sp_digit x[2 * 8]; + sp_digit y[2 * 8]; + sp_digit z[2 * 8]; + int infinity; +} sp_point_256; + +/* The modulus (prime) of the curve P256. */ +static const sp_digit p256_mod[8] = { + 0xffffffff,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000, + 0x00000001,0xffffffff +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static const sp_digit p256_norm_mod[8] = { + 0x00000001,0x00000000,0x00000000,0xffffffff,0xffffffff,0xffffffff, + 0xfffffffe,0x00000000 +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static const sp_digit p256_mp_mod = 0x00000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static const sp_digit p256_order[8] = { + 0xfc632551,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#endif +/* The order of the curve P256 minus 2. */ +static const sp_digit p256_order2[8] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static const sp_digit p256_norm_order[8] = { + 0x039cdaaf,0x0c46353d,0x58e8617b,0x43190552,0x00000000,0x00000000, + 0xffffffff,0x00000000 +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static const sp_digit p256_mp_order = 0xee00bc4f; +#endif +/* The base point of curve P256. */ +static const sp_point_256 p256_base = { + /* X ordinate */ + { + 0xd898c296,0xf4a13945,0x2deb33a0,0x77037d81,0x63a440f2,0xf8bce6e5, + 0xe12c4247,0x6b17d1f2, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x37bf51f5,0xcbb64068,0x6b315ece,0x2bce3357,0x7c0f9e16,0x8ee7eb4a, + 0xfe1a7f9b,0x4fe342e2, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p256_b[8] = { + 0x27d2604b,0x3bce3c3e,0xcc53b0f6,0x651d06b0,0x769886bc,0xb3ebbd55, + 0xaa3a93e7,0x5ac635d8 +}; +#endif + +static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp, sp_point_256** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), &(sp), &(p)) +#endif + + +static void sp_256_point_free_8(sp_point_256* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + int64_t t[8]; + int64_t a64[8]; + int64_t o; + + (void)m; + + a64[0] = a[0]; + a64[1] = a[1]; + a64[2] = a[2]; + a64[3] = a[3]; + a64[4] = a[4]; + a64[5] = a[5]; + a64[6] = a[6]; + a64[7] = a[7]; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a64[0] + a64[1] - a64[3] - a64[4] - a64[5] - a64[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a64[1] + a64[2] - a64[4] - a64[5] - a64[6] - a64[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a64[2] + a64[3] - a64[5] - a64[6] - a64[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a64[0] - a64[1] + 2 * a64[3] + 2 * a64[4] + a64[5] - a64[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a64[1] - a64[2] + 2 * a64[4] + 2 * a64[5] + a64[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a64[2] - a64[3] + 2 * a64[5] + 2 * a64[6] + a64[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a64[0] - a64[1] + a64[5] + 3 * a64[6] + 2 * a64[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a64[0] - a64[2] - a64[3] - a64[4] - a64[5] + 3 * a64[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[1] = t[1]; + r[2] = t[2]; + r[3] = t[3]; + r[4] = t[4]; + r[5] = t[5]; + r[6] = t[6]; + r[7] = t[7]; + + return MP_OKAY; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_256. + * + * p Point of type sp_point_256 (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_8(sp_point_256* p, const 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, 8, pm->x); + sp_256_from_mp(p->y, 8, pm->y); + sp_256_from_mp(p->z, 8, 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(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 8); + r->used = 8; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 8; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - 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 < 8; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_256 to type ecc_point. + * + * p Point of type sp_point_256. + * 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_8(const sp_point_256* 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; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[8 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #32\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #28\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #56\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* 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. + */ +SP_NOINLINE static sp_digit sp_256_cond_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #32\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + 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_8(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + (void)mp; + (void)m; + + __asm__ __volatile__ ( + "mov r2, #0\n\t" + "mov r1, #0\n\t" + "# i = 0\n\t" + "mov r8, r2\n\t" + "\n1:\n\t" + "mov r4, #0\n\t" + "# mu = a[i] * 1 (mp) = a[i]\n\t" + "ldr r3, [%[a]]\n\t" + "# a[i+0] += -1 * mu\n\t" + "mov r5, r3\n\t" + "str r4, [%[a], #0]\n\t" + "# a[i+1] += -1 * mu\n\t" + "ldr r6, [%[a], #4]\n\t" + "mov r4, r3\n\t" + "sub r5, r3\n\t" + "sbc r4, r2\n\t" + "add r5, r6\n\t" + "adc r4, r2\n\t" + "str r5, [%[a], #4]\n\t" + "# a[i+2] += -1 * mu\n\t" + "ldr r6, [%[a], #8]\n\t" + "mov r5, r3\n\t" + "sub r4, r3\n\t" + "sbc r5, r2\n\t" + "add r4, r6\n\t" + "adc r5, r2\n\t" + "str r4, [%[a], #8]\n\t" + "# a[i+3] += 0 * mu\n\t" + "ldr r6, [%[a], #12]\n\t" + "mov r4, #0\n\t" + "add r5, r6\n\t" + "adc r4, r2\n\t" + "str r5, [%[a], #12]\n\t" + "# a[i+4] += 0 * mu\n\t" + "ldr r6, [%[a], #16]\n\t" + "mov r5, #0\n\t" + "add r4, r6\n\t" + "adc r5, r2\n\t" + "str r4, [%[a], #16]\n\t" + "# a[i+5] += 0 * mu\n\t" + "ldr r6, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "add r5, r6\n\t" + "adc r4, r2\n\t" + "str r5, [%[a], #20]\n\t" + "# a[i+6] += 1 * mu\n\t" + "ldr r6, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "add r4, r3\n\t" + "adc r5, r2\n\t" + "add r4, r6\n\t" + "adc r5, r2\n\t" + "str r4, [%[a], #24]\n\t" + "# a[i+7] += -1 * mu\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[a], #32]\n\t" + "add r4, r1, r3\n\t" + "mov r1, #0\n\t" + "adc r1, r2\n\t" + "sub r5, r3\n\t" + "sbc r4, r2\n\t" + "sbc r1, r2\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc r1, r2\n\t" + "str r5, [%[a], #28]\n\t" + "str r4, [%[a], #32]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r8, r6\n\t" + "add %[a], #4\n\t" + "mov r6, #32\n\t" + "cmp r8, r6\n\t" + "blt 1b\n\t" + "sub %[a], #32\n\t" + "mov r3, r1\n\t" + "sub r1, #1\n\t" + "mvn r1, r1\n\t" + "ldr r5, [%[a],#32]\n\t" + "ldr r4, [%[a],#36]\n\t" + "ldr r6, [%[a],#40]\n\t" + "ldr r7, [%[a],#44]\n\t" + "sub r5, r1\n\t" + "sbc r4, r1\n\t" + "sbc r6, r1\n\t" + "sbc r7, r2\n\t" + "str r5, [%[a],#0]\n\t" + "str r4, [%[a],#4]\n\t" + "str r6, [%[a],#8]\n\t" + "str r7, [%[a],#12]\n\t" + "ldr r5, [%[a],#48]\n\t" + "ldr r4, [%[a],#52]\n\t" + "ldr r6, [%[a],#56]\n\t" + "ldr r7, [%[a],#60]\n\t" + "sbc r5, r2\n\t" + "sbc r4, r2\n\t" + "sbc r6, r3\n\t" + "sbc r7, r1\n\t" + "str r5, [%[a],#16]\n\t" + "str r4, [%[a],#20]\n\t" + "str r6, [%[a],#24]\n\t" + "str r7, [%[a],#28]\n\t" + : [a] "+r" (a) + : + : "memory", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8" + ); + + + (void)m; + (void)mp; +} + +/* 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_order_8(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #28\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+7] += m[7] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[7] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[7] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #32\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_256_cond_sub_8(a - 8, 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_256_mont_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_256_mul_8(r, a, b); + sp_256_mont_reduce_8(r, m, mp); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #64\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #28\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #32\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #56\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #60\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #64\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* 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_8(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_256_sqr_8(r, a); + sp_256_mont_reduce_8(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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_8(sp_digit* r, const sp_digit* a, int n, + const sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_8(r, a, m, mp); + for (; n > 1; n--) { + sp_256_mont_sqr_8(r, r, m, mp); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint32_t p256_mod_minus_2[8] = { + 0xfffffffdU,0xffffffffU,0xffffffffU,0x00000000U,0x00000000U,0x00000000U, + 0x00000001U,0xffffffffU +}; +#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_8(sp_digit* r, const sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 8); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_8(t, t, p256_mod, p256_mp_mod); + if (p256_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 8); +#else + sp_digit* t1 = td; + sp_digit* t2 = td + 2 * 8; + sp_digit* t3 = td + 4 * 8; + /* 0x2 */ + sp_256_mont_sqr_8(t1, a, p256_mod, p256_mp_mod); + /* 0x3 */ + sp_256_mont_mul_8(t2, t1, a, p256_mod, p256_mp_mod); + /* 0xc */ + sp_256_mont_sqr_n_8(t1, t2, 2, p256_mod, p256_mp_mod); + /* 0xd */ + sp_256_mont_mul_8(t3, t1, a, p256_mod, p256_mp_mod); + /* 0xf */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xf0 */ + sp_256_mont_sqr_n_8(t1, t2, 4, p256_mod, p256_mp_mod); + /* 0xfd */ + sp_256_mont_mul_8(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xff */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xff00 */ + sp_256_mont_sqr_n_8(t1, t2, 8, p256_mod, p256_mp_mod); + /* 0xfffd */ + sp_256_mont_mul_8(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffff */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffff0000 */ + sp_256_mont_sqr_n_8(t1, t2, 16, p256_mod, p256_mp_mod); + /* 0xfffffffd */ + sp_256_mont_mul_8(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffffffff */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000000 */ + sp_256_mont_sqr_n_8(t1, t2, 32, p256_mod, p256_mp_mod); + /* 0xffffffffffffffff */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000001 */ + sp_256_mont_mul_8(r, t1, a, p256_mod, p256_mp_mod); + /* 0xffffffff000000010000000000000000000000000000000000000000 */ + sp_256_mont_sqr_n_8(r, r, 160, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff */ + sp_256_mont_mul_8(r, r, t2, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */ + sp_256_mont_sqr_n_8(r, r, 32, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */ + sp_256_mont_mul_8(r, r, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* 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. + */ +SP_NOINLINE static int32_t sp_256_cmp_8(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #28\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Normalize the values in each word to 32. + * + * a Array of sp_digit to normalize. + */ +#define sp_256_norm_8(a) + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + int32_t n; + + sp_256_mont_inv_8(t1, p->z, t + 2*8); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_8(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 8, 0, sizeof(r->x) / 2U); + sp_256_mont_reduce_8(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_8(r->x, p256_mod); + sp_256_cond_sub_8(r->x, r->x, p256_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_256_norm_8(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_8(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 8, 0, sizeof(r->y) / 2U); + sp_256_mont_reduce_8(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_8(r->y, p256_mod); + sp_256_cond_sub_8(r->y, r->y, p256_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_256_norm_8(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. + */ +SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, #32\n\t" + "sub r7, #1\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +#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). + */ +SP_NOINLINE static void sp_256_mont_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[b],#0]\n\t" + "ldr r7, [%[b],#4]\n\t" + "add r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[a],#8]\n\t" + "ldr r5, [%[a],#12]\n\t" + "ldr r6, [%[b],#8]\n\t" + "ldr r7, [%[b],#12]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[b],#16]\n\t" + "ldr r7, [%[b],#20]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "mov r8, r4\n\t" + "mov r9, r5\n\t" + "ldr r4, [%[a],#24]\n\t" + "ldr r5, [%[a],#28]\n\t" + "ldr r6, [%[b],#24]\n\t" + "ldr r7, [%[b],#28]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "mov r10, r4\n\t" + "mov r11, r5\n\t" + "adc r3, r3\n\t" + "mov r6, r3\n\t" + "sub r3, #1\n\t" + "mvn r3, r3\n\t" + "mov r7, #0\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "sub r4, r3\n\t" + "sbc r5, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[r],#8]\n\t" + "ldr r5, [%[r],#12]\n\t" + "sbc r4, r3\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "mov r4, r8\n\t" + "mov r5, r9\n\t" + "sbc r4, r7\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r],#16]\n\t" + "str r5, [%[r],#20]\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "sbc r4, r6\n\t" + "sbc r5, r3\n\t" + "str r4, [%[r],#24]\n\t" + "str r5, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "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). + */ +SP_NOINLINE static void sp_256_mont_dbl_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[a],#8]\n\t" + "ldr r7, [%[a],#12]\n\t" + "add r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "str r7, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[a],#24]\n\t" + "ldr r7, [%[a],#28]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "mov r8, r4\n\t" + "mov r9, r5\n\t" + "mov r10, r6\n\t" + "mov r11, r7\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "adc r3, r3\n\t" + "mov r2, r3\n\t" + "sub r3, #1\n\t" + "mvn r3, r3\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "ldr r6, [%[r],#8]\n\t" + "sub r4, r3\n\t" + "sbc r5, r3\n\t" + "sbc r6, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "ldr r4, [%[r],#12]\n\t" + "mov r5, r8\n\t" + "mov r6, r9\n\t" + "sbc r4, r7\n\t" + "sbc r5, r7\n\t" + "sbc r6, r7\n\t" + "str r4, [%[r],#12]\n\t" + "str r5, [%[r],#16]\n\t" + "str r6, [%[r],#20]\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "sbc r4, r2\n\t" + "sbc r5, r3\n\t" + "str r4, [%[r],#24]\n\t" + "str r5, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r3", "r2", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_mont_tpl_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "ldr r6, [%[a],#0]\n\t" + "ldr r7, [%[a],#4]\n\t" + "ldr r4, [%[a],#8]\n\t" + "ldr r5, [%[a],#12]\n\t" + "add r6, r6\n\t" + "adc r7, r7\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "mov r8, r4\n\t" + "mov r9, r5\n\t" + "ldr r2, [%[a],#16]\n\t" + "ldr r3, [%[a],#20]\n\t" + "ldr r4, [%[a],#24]\n\t" + "ldr r5, [%[a],#28]\n\t" + "adc r2, r2\n\t" + "adc r3, r3\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "mov r10, r2\n\t" + "mov r11, r3\n\t" + "mov r12, r4\n\t" + "mov r14, r5\n\t" + "mov r3, #0\n\t" + "mov r5, #0\n\t" + "adc r3, r3\n\t" + "mov r4, r3\n\t" + "sub r3, #1\n\t" + "mvn r3, r3\n\t" + "sub r6, r3\n\t" + "sbc r7, r3\n\t" + "mov r2, r8\n\t" + "sbc r2, r3\n\t" + "mov r8, r2\n\t" + "mov r2, r9\n\t" + "sbc r2, r5\n\t" + "mov r9, r2\n\t" + "mov r2, r10\n\t" + "sbc r2, r5\n\t" + "mov r10, r2\n\t" + "mov r2, r11\n\t" + "sbc r2, r5\n\t" + "mov r11, r2\n\t" + "mov r2, r12\n\t" + "sbc r2, r4\n\t" + "mov r12, r2\n\t" + "mov r2, r14\n\t" + "sbc r2, r3\n\t" + "mov r14, r2\n\t" + "ldr r2, [%[a],#0]\n\t" + "ldr r3, [%[a],#4]\n\t" + "add r6, r2\n\t" + "adc r7, r3\n\t" + "ldr r2, [%[a],#8]\n\t" + "ldr r3, [%[a],#12]\n\t" + "mov r4, r8\n\t" + "mov r5, r9\n\t" + "adc r2, r4\n\t" + "adc r3, r5\n\t" + "mov r8, r2\n\t" + "mov r9, r3\n\t" + "ldr r2, [%[a],#16]\n\t" + "ldr r3, [%[a],#20]\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "adc r2, r4\n\t" + "adc r3, r5\n\t" + "mov r10, r2\n\t" + "mov r11, r3\n\t" + "ldr r2, [%[a],#24]\n\t" + "ldr r3, [%[a],#28]\n\t" + "mov r4, r12\n\t" + "mov r5, r14\n\t" + "adc r2, r4\n\t" + "adc r3, r5\n\t" + "mov r12, r2\n\t" + "mov r14, r3\n\t" + "mov r3, #0\n\t" + "mov r5, #0\n\t" + "adc r3, r3\n\t" + "mov r4, r3\n\t" + "sub r3, #1\n\t" + "mvn r3, r3\n\t" + "sub r6, r3\n\t" + "str r6, [%[r],#0]\n\t" + "sbc r7, r3\n\t" + "str r7, [%[r],#4]\n\t" + "mov r2, r8\n\t" + "sbc r2, r3\n\t" + "str r2, [%[r],#8]\n\t" + "mov r2, r9\n\t" + "sbc r2, r5\n\t" + "str r2, [%[r],#12]\n\t" + "mov r2, r10\n\t" + "sbc r2, r5\n\t" + "str r2, [%[r],#16]\n\t" + "mov r2, r11\n\t" + "sbc r2, r5\n\t" + "str r2, [%[r],#20]\n\t" + "mov r2, r12\n\t" + "sbc r2, r4\n\t" + "str r2, [%[r],#24]\n\t" + "mov r2, r14\n\t" + "sbc r2, r3\n\t" + "str r2, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); +} + +/* 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). + */ +SP_NOINLINE static void sp_256_mont_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[b],#0]\n\t" + "ldr r7, [%[b],#4]\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[a],#8]\n\t" + "ldr r5, [%[a],#12]\n\t" + "ldr r6, [%[b],#8]\n\t" + "ldr r7, [%[b],#12]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[b],#16]\n\t" + "ldr r7, [%[b],#20]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "mov r8, r4\n\t" + "mov r9, r5\n\t" + "ldr r4, [%[a],#24]\n\t" + "ldr r5, [%[a],#28]\n\t" + "ldr r6, [%[b],#24]\n\t" + "ldr r7, [%[b],#28]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "mov r10, r4\n\t" + "mov r11, r5\n\t" + "sbc r3, r3\n\t" + "lsr r7, r3, #31\n\t" + "mov r6, #0\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "add r4, r3\n\t" + "adc r5, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[r],#8]\n\t" + "ldr r5, [%[r],#12]\n\t" + "adc r4, r3\n\t" + "adc r5, r6\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "mov r4, r8\n\t" + "mov r5, r9\n\t" + "adc r4, r6\n\t" + "adc r5, r6\n\t" + "str r4, [%[r],#16]\n\t" + "str r5, [%[r],#20]\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "adc r4, r7\n\t" + "adc r5, r3\n\t" + "str r4, [%[r],#24]\n\t" + "str r5, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "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). + */ +SP_NOINLINE static void sp_256_div2_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr r7, [%[a], #0]\n\t" + "lsl r7, r7, #31\n\t" + "lsr r7, r7, #31\n\t" + "mov r5, #0\n\t" + "sub r5, r7\n\t" + "mov r7, #0\n\t" + "lsl r6, r5, #31\n\t" + "lsr r6, r6, #31\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "add r3, r5\n\t" + "adc r4, r5\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "adc r3, r5\n\t" + "adc r4, r7\n\t" + "str r3, [%[r], #8]\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "adc r3, r7\n\t" + "adc r4, r7\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "adc r3, r6\n\t" + "adc r4, r5\n\t" + "adc r7, r7\n\t" + "lsl r7, r7, #31\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, #31\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r4\n\t" + "orr r6, r7\n\t" + "mov r7, r3\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, #31\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r4\n\t" + "orr r6, r7\n\t" + "mov r7, r3\n\t" + "str r5, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, #31\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r4\n\t" + "orr r6, r7\n\t" + "mov r7, r3\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[r], #0]\n\t" + "ldr r4, [%[r], #4]\n\t" + "lsr r5, r3, #1\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r4\n\t" + "orr r6, r7\n\t" + "str r5, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "r3", "r4", "r5", "r6", "r7" + ); +} + +/* 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_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_8(t1, p->z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_8(z, p->y, p->z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_8(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_8(t2, p->x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_8(t1, p->x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_8(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_8(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_8(y, p->y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_8(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_8(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_8(y, y, p->x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_sqr_8(x, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_8(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_8(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_8(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_8(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_8(y, y, t2, p256_mod); +} + +#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. + */ +SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "add r6, #32\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "sbc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* 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_8(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])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, + sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* t3 = t + 4*8; + sp_digit* t4 = t + 6*8; + sp_digit* t5 = t + 8*8; + 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) { + const sp_point_256* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_256_sub_8(t1, p256_mod, q->y); + sp_256_norm_8(t1); + if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) != 0) { + sp_256_proj_point_dbl_8(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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<8; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<8; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<8; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_8(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_8(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_8(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_8(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_8(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_8(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(x, x, t5, p256_mod); + sp_256_mont_dbl_8(t1, y, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_mul_8(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(y, y, t5, p256_mod); + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td[16]; + sp_point_256 rtd; + sp_digit tmpd[2 * 8 * 5]; +#endif + sp_point_256* t; + sp_point_256* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_256_point_new_8(heap, rtd, rt); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 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 */ + (void)sp_256_mod_mul_norm_8(t[1].x, g->x, p256_mod); + (void)sp_256_mod_mul_norm_8(t[1].y, g->y, p256_mod); + (void)sp_256_mod_mul_norm_8(t[1].z, g->z, p256_mod); + t[1].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_256_proj_point_add_8(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_256_proj_point_add_8(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_256_proj_point_add_8(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_256_proj_point_add_8(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_256_proj_point_dbl_8(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_256_proj_point_add_8(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_256_proj_point_dbl_8(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_256_proj_point_add_8(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_256_proj_point_dbl_8(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_256_proj_point_add_8(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 6; + n = k[i+1] << 0; + c = 28; + y = n >> 28; + XMEMCPY(rt, &t[y], sizeof(sp_point_256)); + n <<= 4; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--]; + c += 32; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + + sp_256_proj_point_add_8(rt, rt, &t[y], tmp); + } + + if (map != 0) { + sp_256_map_8(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 8 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_256) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_256_point_free_8(rt, 1, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_256 { + sp_digit x[8]; + sp_digit y[8]; +} sp_table_entry_256; + +#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_8(sp_point_256* p, int n, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*8; + sp_digit* b = t + 4*8; + sp_digit* t1 = t + 6*8; + sp_digit* t2 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_256_mont_dbl_8(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_8(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(w, w, p256_mod, p256_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(t1, t1, w, p256_mod); + sp_256_mont_tpl_8(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_8(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(b, t1, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(t2, b, p256_mod); + sp_256_mont_sub_8(x, x, t2, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_8(t1, t1, p256_mod, p256_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_256_mont_mul_8(w, w, t1, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_8(y, b, x, p256_mod); + sp_256_mont_mul_8(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(y, y, p256_mod); + sp_256_mont_sub_8(y, y, t1, p256_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(t1, t1, w, p256_mod); + sp_256_mont_tpl_8(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_8(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(b, t1, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(t2, b, p256_mod); + sp_256_mont_sub_8(x, x, t2, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_8(t1, t1, p256_mod, p256_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_8(y, b, x, p256_mod); + sp_256_mont_mul_8(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(y, y, p256_mod); + sp_256_mont_sub_8(y, y, t1, p256_mod); +#endif + /* Y = Y/2 */ + sp_256_div2_8(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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_8(sp_point_256* r, const sp_point_256* p, + const sp_point_256* q, sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* t3 = t + 4*8; + sp_digit* t4 = t + 6*8; + sp_digit* t5 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_256_sub_8(t1, p256_mod, q->y); + sp_256_norm_8(t1); + if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) != 0) { + sp_256_proj_point_dbl_8(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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<8; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<8; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<8; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_8(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_8(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_8(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(x, t1, t5, p256_mod); + sp_256_mont_dbl_8(t1, t3, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_8(t3, t3, x, p256_mod); + sp_256_mont_mul_8(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(y, t3, t5, p256_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 8; + sp_digit* tmp = t + 4 * 8; + + sp_256_mont_inv_8(t1, a->z, tmp); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_8(const sp_point_256* a, + sp_table_entry_256* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td, s1d, s2d; +#endif + sp_point_256* t; + sp_point_256* s1 = NULL; + sp_point_256* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_256_point_new_8(heap, td, t); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_8(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_256)); + /* 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)); + + for (i=1; i<4; i++) { + sp_256_proj_point_dbl_n_8(t, 64, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<4; i++) { + XMEMCPY(s1->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_8(t, s1, s2, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_256_point_free_8(s2, 0, heap); + sp_256_point_free_8(s1, 0, heap); + sp_256_point_free_8( 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 coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit td[2 * 8 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_256_point_new_8(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 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=63; j<4; j++,x+=64) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=62; i>=0; i--) { + y = 0; + for (j=0,x=i; j<4; j++,x+=64) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + + sp_256_proj_point_dbl_8(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 = !y; + sp_256_proj_point_add_qz1_8(rt, rt, p, t); + } + + if (map != 0) { + sp_256_map_8(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, heap); + sp_256_point_free_8(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_256_t { + sp_digit x[8]; + sp_digit y[8]; + sp_table_entry_256 table[16]; + uint32_t cnt; + int set; +} sp_cache_256_t; + +static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_256_last = -1; +static THREAD_LS_T int sp_cache_256_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_256 = 0; + static wolfSSL_Mutex sp_cache_256_lock; +#endif + +static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_256_inited == 0) { + for (i=0; ix, sp_cache_256[i].x) & + sp_256_cmp_equal_8(g->y, sp_cache_256[i].y)) { + sp_cache_256[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_256_last + 1) % FP_ENTRIES; + for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_256[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_256_last) { + least = sp_cache_256[0].cnt; + for (j=1; jx, sizeof(sp_cache_256[i].x)); + XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y)); + sp_cache_256[i].set = 1; + sp_cache_256[i].cnt = 1; + } + + *cache = &sp_cache_256[i]; + sp_cache_256_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 coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); +#else + sp_digit tmp[2 * 8 * 5]; + sp_cache_256_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_256 == 0) { + wc_InitMutex(&sp_cache_256_lock); + initCacheMutex_256 = 1; + } + if (wc_LockMutex(&sp_cache_256_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_256(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_8(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_256_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#else +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_8(const sp_point_256* a, + sp_table_entry_256* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td, s1d, s2d; +#endif + sp_point_256* t; + sp_point_256* s1 = NULL; + sp_point_256* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_256_point_new_8(heap, td, t); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_8(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_256)); + /* 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)); + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_8(t, 32, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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_8(t, s1, s2, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_256_point_free_8(s2, 0, heap); + sp_256_point_free_8(s1, 0, heap); + sp_256_point_free_8( 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 coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit td[2 * 8 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_256_point_new_8(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 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 / 32] >> (x % 32)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + + sp_256_proj_point_dbl_8(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 = !y; + sp_256_proj_point_add_qz1_8(rt, rt, p, t); + } + + if (map != 0) { + sp_256_map_8(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, heap); + sp_256_point_free_8(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_256_t { + sp_digit x[8]; + sp_digit y[8]; + sp_table_entry_256 table[256]; + uint32_t cnt; + int set; +} sp_cache_256_t; + +static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_256_last = -1; +static THREAD_LS_T int sp_cache_256_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_256 = 0; + static wolfSSL_Mutex sp_cache_256_lock; +#endif + +static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_256_inited == 0) { + for (i=0; ix, sp_cache_256[i].x) & + sp_256_cmp_equal_8(g->y, sp_cache_256[i].y)) { + sp_cache_256[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_256_last + 1) % FP_ENTRIES; + for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_256[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_256_last) { + least = sp_cache_256[0].cnt; + for (j=1; jx, sizeof(sp_cache_256[i].x)); + XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y)); + sp_cache_256[i].set = 1; + sp_cache_256[i].cnt = 1; + } + + *cache = &sp_cache_256[i]; + sp_cache_256_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 coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); +#else + sp_digit tmp[2 * 8 * 5]; + sp_cache_256_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_256 == 0) { + wc_InitMutex(&sp_cache_256_lock); + initCacheMutex_256 = 1; + } + if (wc_LockMutex(&sp_cache_256_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_256(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_8(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_256_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[8]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_256_point_new_8(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, km); + sp_256_point_from_ecc_point_8(point, gm); + + err = sp_256_ecc_mulmod_8(point, point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_8(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static const sp_table_entry_256 p256_table[16] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76 }, + { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18 } }, + /* 2 */ + { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961 }, + { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37, + 0x8d6f0f7b,0xf648f916 } }, + /* 3 */ + { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285 }, + { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562, + 0x6b6f7383,0x94bb725b } }, + /* 4 */ + { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4 }, + { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12 } }, + /* 5 */ + { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c }, + { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08 } }, + /* 6 */ + { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651 }, + { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a } }, + /* 7 */ + { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014, + 0xaeebffcd,0x9d0f27b2 }, + { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0, + 0x356ec48d,0x244a566d } }, + /* 8 */ + { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e, + 0xcd42ab1b,0x803f3e02 }, + { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e } }, + /* 9 */ + { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5 }, + { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418, + 0xe2d41c8b,0x23d0f130 } }, + /* 10 */ + { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9 }, + { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b, + 0x01fe49c3,0x2b100118 } }, + /* 11 */ + { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999 }, + { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551 } }, + /* 12 */ + { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148 }, + { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875, + 0x9f0e1a84,0x77387de3 } }, + /* 13 */ + { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0 }, + { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8 } }, + /* 14 */ + { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb }, + { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f } }, + /* 15 */ + { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52 }, + { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f } }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_8(sp_point_256* r, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table, + k, map, heap); +} + +#else +static const sp_table_entry_256 p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76 }, + { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18 } }, + /* 2 */ + { { 0x4147519a,0x20288602,0x26b372f0,0xd0981eac,0xa785ebc8,0xa9d4a7ca, + 0xdbdf58e9,0xd953c50d }, + { 0xfd590f8f,0x9d6361cc,0x44e6c917,0x72e9626b,0x22eb64cf,0x7fd96110, + 0x9eb288f3,0x863ebb7e } }, + /* 3 */ + { { 0x5cdb6485,0x7856b623,0x2f0a2f97,0x808f0ea2,0x4f7e300b,0x3e68d954, + 0xb5ff80a0,0x00076055 }, + { 0x838d2010,0x7634eb9b,0x3243708a,0x54014fbb,0x842a6606,0xe0e47d39, + 0x34373ee0,0x83087761 } }, + /* 4 */ + { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961 }, + { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37, + 0x8d6f0f7b,0xf648f916 } }, + /* 5 */ + { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285 }, + { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562, + 0x6b6f7383,0x94bb725b } }, + /* 6 */ + { { 0x720f141c,0xbbf9b48f,0x2df5bc74,0x6199b3cd,0x411045c4,0xdc3f6129, + 0x2f7dc4ef,0xcdd6bbcb }, + { 0xeaf436fd,0xcca6700b,0xb99326be,0x6f647f6d,0x014f2522,0x0c0fa792, + 0x4bdae5f6,0xa361bebd } }, + /* 7 */ + { { 0x597c13c7,0x28aa2558,0x50b7c3e1,0xc38d635f,0xf3c09d1d,0x07039aec, + 0xc4b5292c,0xba12ca09 }, + { 0x59f91dfd,0x9e408fa4,0xceea07fb,0x3af43b66,0x9d780b29,0x1eceb089, + 0x701fef4b,0x53ebb99d } }, + /* 8 */ + { { 0xb0e63d34,0x4fe7ee31,0xa9e54fab,0xf4600572,0xd5e7b5a4,0xc0493334, + 0x06d54831,0x8589fb92 }, + { 0x6583553a,0xaa70f5cc,0xe25649e5,0x0879094a,0x10044652,0xcc904507, + 0x02541c4f,0xebb0696d } }, + /* 9 */ + { { 0xac1647c5,0x4616ca15,0xc4cf5799,0xb8127d47,0x764dfbac,0xdc666aa3, + 0xd1b27da3,0xeb2820cb }, + { 0x6a87e008,0x9406f8d8,0x922378f3,0xd87dfa9d,0x80ccecb2,0x56ed2e42, + 0x55a7da1d,0x1f28289b } }, + /* 10 */ + { { 0x3b89da99,0xabbaa0c0,0xb8284022,0xa6f2d79e,0xb81c05e8,0x27847862, + 0x05e54d63,0x337a4b59 }, + { 0x21f7794a,0x3c67500d,0x7d6d7f61,0x207005b7,0x04cfd6e8,0x0a5a3781, + 0xf4c2fbd6,0x0d65e0d5 } }, + /* 11 */ + { { 0xb5275d38,0xd9d09bbe,0x0be0a358,0x4268a745,0x973eb265,0xf0762ff4, + 0x52f4a232,0xc23da242 }, + { 0x0b94520c,0x5da1b84f,0xb05bd78e,0x09666763,0x94d29ea1,0x3a4dcb86, + 0xc790cff1,0x19de3b8c } }, + /* 12 */ + { { 0x26c5fe04,0x183a716c,0x3bba1bdb,0x3b28de0b,0xa4cb712c,0x7432c586, + 0x91fccbfd,0xe34dcbd4 }, + { 0xaaa58403,0xb408d46b,0x82e97a53,0x9a697486,0x36aaa8af,0x9e390127, + 0x7b4e0f7f,0xe7641f44 } }, + /* 13 */ + { { 0xdf64ba59,0x7d753941,0x0b0242fc,0xd33f10ec,0xa1581859,0x4f06dfc6, + 0x052a57bf,0x4a12df57 }, + { 0x9439dbd0,0xbfa6338f,0xbde53e1f,0xd3c24bd4,0x21f1b314,0xfd5e4ffa, + 0xbb5bea46,0x6af5aa93 } }, + /* 14 */ + { { 0x10c91999,0xda10b699,0x2a580491,0x0a24b440,0xb8cc2090,0x3e0094b4, + 0x66a44013,0x5fe3475a }, + { 0xf93e7b4b,0xb0f8cabd,0x7c23f91a,0x292b501a,0xcd1e6263,0x42e889ae, + 0xecfea916,0xb544e308 } }, + /* 15 */ + { { 0x16ddfdce,0x6478c6e9,0xf89179e6,0x2c329166,0x4d4e67e1,0x4e8d6e76, + 0xa6b0c20b,0xe0b6b2bd }, + { 0xbb7efb57,0x0d312df2,0x790c4007,0x1aac0dde,0x679bc944,0xf90336ad, + 0x25a63774,0x71c023de } }, + /* 16 */ + { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4 }, + { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12 } }, + /* 17 */ + { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c }, + { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08 } }, + /* 18 */ + { { 0x309a4e1f,0x1e99f581,0xe9270074,0xab7de71b,0xefd28d20,0x26a5ef0b, + 0x7f9c563f,0xe7c0073f }, + { 0x0ef59f76,0x1f6d663a,0x20fcb050,0x669b3b54,0x7a6602d4,0xc08c1f7a, + 0xc65b3c0a,0xe08504fe } }, + /* 19 */ + { { 0xa031b3ca,0xf098f68d,0xe6da6d66,0x6d1cab9e,0x94f246e8,0x5bfd81fa, + 0x5b0996b4,0x78f01882 }, + { 0x3a25787f,0xb7eefde4,0x1dccac9b,0x8016f80d,0xb35bfc36,0x0cea4877, + 0x7e94747a,0x43a773b8 } }, + /* 20 */ + { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651 }, + { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a } }, + /* 21 */ + { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014, + 0xaeebffcd,0x9d0f27b2 }, + { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0, + 0x356ec48d,0x244a566d } }, + /* 22 */ + { { 0xeacf1f96,0x6db0394a,0x024c271c,0x9f2122a9,0x82cbd3b9,0x2626ac1b, + 0x3581ef69,0x45e58c87 }, + { 0xa38f9dbc,0xd3ff479d,0xe888a040,0xa8aaf146,0x46e0bed7,0x945adfb2, + 0xc1e4b7a4,0xc040e21c } }, + /* 23 */ + { { 0x6f8117b6,0x847af000,0x73a35433,0x651969ff,0x1d9475eb,0x482b3576, + 0x682c6ec7,0x1cdf5c97 }, + { 0x11f04839,0x7db775b4,0x48de1698,0x7dbeacf4,0xb70b3219,0xb2921dd1, + 0xa92dff3d,0x046755f8 } }, + /* 24 */ + { { 0xbce8ffcd,0xcc8ac5d2,0x2fe61a82,0x0d53c48b,0x7202d6c7,0xf6f16172, + 0x3b83a5f3,0x046e5e11 }, + { 0xd8007f01,0xe7b8ff64,0x5af43183,0x7fb1ef12,0x35e1a03c,0x045c5ea6, + 0x303d005b,0x6e0106c3 } }, + /* 25 */ + { { 0x88dd73b1,0x48c73584,0x995ed0d9,0x7670708f,0xc56a2ab7,0x38385ea8, + 0xe901cf1f,0x442594ed }, + { 0x12d4b65b,0xf8faa2c9,0x96c90c37,0x94c2343b,0x5e978d1f,0xd326e4a1, + 0x4c2ee68e,0xa796fa51 } }, + /* 26 */ + { { 0x823addd7,0x359fb604,0xe56693b3,0x9e2a6183,0x3cbf3c80,0xf885b78e, + 0xc69766e9,0xe4ad2da9 }, + { 0x8e048a61,0x357f7f42,0xc092d9a0,0x082d198c,0xc03ed8ef,0xfc3a1af4, + 0xc37b5143,0xc5e94046 } }, + /* 27 */ + { { 0x2be75f9e,0x476a538c,0xcb123a78,0x6fd1a9e8,0xb109c04b,0xd85e4df0, + 0xdb464747,0x63283daf }, + { 0xbaf2df15,0xce728cf7,0x0ad9a7f4,0xe592c455,0xe834bcc3,0xfab226ad, + 0x1981a938,0x68bd19ab } }, + /* 28 */ + { { 0x1887d659,0xc08ead51,0xb359305a,0x3374d5f4,0xcfe74fe3,0x96986981, + 0x3c6fdfd6,0x495292f5 }, + { 0x1acec896,0x4a878c9e,0xec5b4484,0xd964b210,0x664d60a7,0x6696f7e2, + 0x26036837,0x0ec7530d } }, + /* 29 */ + { { 0xad2687bb,0x2da13a05,0xf32e21fa,0xa1f83b6a,0x1dd4607b,0x390f5ef5, + 0x64863f0b,0x0f6207a6 }, + { 0x0f138233,0xbd67e3bb,0x272aa718,0xdd66b96c,0x26ec88ae,0x8ed00407, + 0x08ed6dcf,0xff0db072 } }, + /* 30 */ + { { 0x4c95d553,0x749fa101,0x5d680a8a,0xa44052fd,0xff3b566f,0x183b4317, + 0x88740ea3,0x313b513c }, + { 0x08d11549,0xb402e2ac,0xb4dee21c,0x071ee10b,0x47f2320e,0x26b987dd, + 0x86f19f81,0x2d3abcf9 } }, + /* 31 */ + { { 0x815581a2,0x4c288501,0x632211af,0x9a0a6d56,0x0cab2e99,0x19ba7a0f, + 0xded98cdf,0xc036fa10 }, + { 0xc1fbd009,0x29ae08ba,0x06d15816,0x0b68b190,0x9b9e0d8f,0xc2eb3277, + 0xb6d40194,0xa6b2a2c4 } }, + /* 32 */ + { { 0x6d3549cf,0xd433e50f,0xfacd665e,0x6f33696f,0xce11fcb4,0x695bfdac, + 0xaf7c9860,0x810ee252 }, + { 0x7159bb2c,0x65450fe1,0x758b357b,0xf7dfbebe,0xd69fea72,0x2b057e74, + 0x92731745,0xd485717a } }, + /* 33 */ + { { 0xf0cb5a98,0x11741a8a,0x1f3110bf,0xd3da8f93,0xab382adf,0x1994e2cb, + 0x2f9a604e,0x6a6045a7 }, + { 0xa2b2411d,0x170c0d3f,0x510e96e0,0xbe0eb83e,0x8865b3cc,0x3bcc9f73, + 0xf9e15790,0xd3e45cfa } }, + /* 34 */ + { { 0xe83f7669,0xce1f69bb,0x72877d6b,0x09f8ae82,0x3244278d,0x9548ae54, + 0xe3c2c19c,0x207755de }, + { 0x6fef1945,0x87bd61d9,0xb12d28c3,0x18813cef,0x72df64aa,0x9fbcd1d6, + 0x7154b00d,0x48dc5ee5 } }, + /* 35 */ + { { 0xf7e5a199,0x123790bf,0x989ccbb7,0xe0efb8cf,0x0a519c79,0xc27a2bfe, + 0xdff6f445,0xf2fb0aed }, + { 0xf0b5025f,0x41c09575,0x40fa9f22,0x550543d7,0x380bfbd0,0x8fa3c8ad, + 0xdb28d525,0xa13e9015 } }, + /* 36 */ + { { 0xa2b65cbc,0xf9f7a350,0x2a464226,0x0b04b972,0xe23f07a1,0x265ce241, + 0x1497526f,0x2bf0d6b0 }, + { 0x4b216fb7,0xd3d4dd3f,0xfbdda26a,0xf7d7b867,0x6708505c,0xaeb7b83f, + 0x162fe89f,0x42a94a5a } }, + /* 37 */ + { { 0xeaadf191,0x5846ad0b,0x25a268d7,0x0f8a4890,0x494dc1f6,0xe8603050, + 0xc65ede3d,0x2c2dd969 }, + { 0x93849c17,0x6d02171d,0x1da250dd,0x460488ba,0x3c3a5485,0x4810c706, + 0x42c56dbc,0xf437fa1f } }, + /* 38 */ + { { 0x4a0f7dab,0x6aa0d714,0x1776e9ac,0x0f049793,0xf5f39786,0x52c0a050, + 0x54707aa8,0xaaf45b33 }, + { 0xc18d364a,0x85e37c33,0x3e497165,0xd40b9b06,0x15ec5444,0xf4171681, + 0xf4f272bc,0xcdf6310d } }, + /* 39 */ + { { 0x8ea8b7ef,0x7473c623,0x85bc2287,0x08e93518,0x2bda8e34,0x41956772, + 0xda9e2ff2,0xf0d008ba }, + { 0x2414d3b1,0x2912671d,0xb019ea76,0xb3754985,0x453bcbdb,0x5c61b96d, + 0xca887b8b,0x5bd5c2f5 } }, + /* 40 */ + { { 0xf49a3154,0xef0f469e,0x6e2b2e9a,0x3e85a595,0xaa924a9c,0x45aaec1e, + 0xa09e4719,0xaa12dfc8 }, + { 0x4df69f1d,0x26f27227,0xa2ff5e73,0xe0e4c82c,0xb7a9dd44,0xb9d8ce73, + 0xe48ca901,0x6c036e73 } }, + /* 41 */ + { { 0x0f6e3138,0x5cfae12a,0x25ad345a,0x6966ef00,0x45672bc5,0x8993c64b, + 0x96afbe24,0x292ff658 }, + { 0x5e213402,0xd5250d44,0x4392c9fe,0xf6580e27,0xda1c72e8,0x097b397f, + 0x311b7276,0x644e0c90 } }, + /* 42 */ + { { 0xa47153f0,0xe1e421e1,0x920418c9,0xb86c3b79,0x705d7672,0x93bdce87, + 0xcab79a77,0xf25ae793 }, + { 0x6d869d0c,0x1f3194a3,0x4986c264,0x9d55c882,0x096e945e,0x49fb5ea3, + 0x13db0a3e,0x39b8e653 } }, + /* 43 */ + { { 0xb6fd2e59,0x37754200,0x9255c98f,0x35e2c066,0x0e2a5739,0xd9dab21a, + 0x0f19db06,0x39122f2f }, + { 0x03cad53c,0xcfbce1e0,0xe65c17e3,0x225b2c0f,0x9aa13877,0x72baf1d2, + 0xce80ff8d,0x8de80af8 } }, + /* 44 */ + { { 0x207bbb76,0xafbea8d9,0x21782758,0x921c7e7c,0x1c0436b1,0xdfa2b74b, + 0x2e368c04,0x87194906 }, + { 0xa3993df5,0xb5f928bb,0xf3b3d26a,0x639d75b5,0x85b55050,0x011aa78a, + 0x5b74fde1,0xfc315e6a } }, + /* 45 */ + { { 0xe8d6ecfa,0x561fd41a,0x1aec7f86,0x5f8c44f6,0x4924741d,0x98452a7b, + 0xee389088,0xe6d4a7ad }, + { 0x4593c75d,0x60552ed1,0xdd271162,0x70a70da4,0x7ba2c7db,0xd2aede93, + 0x9be2ae57,0x35dfaf9a } }, + /* 46 */ + { { 0xaa736636,0x6b956fcd,0xae2cab7e,0x09f51d97,0x0f349966,0xfb10bf41, + 0x1c830d2b,0x1da5c7d7 }, + { 0x3cce6825,0x5c41e483,0xf9573c3b,0x15ad118f,0xf23036b8,0xa28552c7, + 0xdbf4b9d6,0x7077c0fd } }, + /* 47 */ + { { 0x46b9661c,0xbf63ff8d,0x0d2cfd71,0xa1dfd36b,0xa847f8f7,0x0373e140, + 0xe50efe44,0x53a8632e }, + { 0x696d8051,0x0976ff68,0xc74f468a,0xdaec0c95,0x5e4e26bd,0x62994dc3, + 0x34e1fcc1,0x028ca76d } }, + /* 48 */ + { { 0xfc9877ee,0xd11d47dc,0x801d0002,0xc8b36210,0x54c260b6,0xd002c117, + 0x6962f046,0x04c17cd8 }, + { 0xb0daddf5,0x6d9bd094,0x24ce55c0,0xbea23575,0x72da03b5,0x663356e6, + 0xfed97474,0xf7ba4de9 } }, + /* 49 */ + { { 0xebe1263f,0xd0dbfa34,0x71ae7ce6,0x55763735,0x82a6f523,0xd2440553, + 0x52131c41,0xe31f9600 }, + { 0xea6b6ec6,0xd1bb9216,0x73c2fc44,0x37a1d12e,0x89d0a294,0xc10e7eac, + 0xce34d47b,0xaa3a6259 } }, + /* 50 */ + { { 0x36f3dcd3,0xfbcf9df5,0xd2bf7360,0x6ceded50,0xdf504f5b,0x491710fa, + 0x7e79daee,0x2398dd62 }, + { 0x6d09569e,0xcf4705a3,0x5149f769,0xea0619bb,0x35f6034c,0xff9c0377, + 0x1c046210,0x5717f5b2 } }, + /* 51 */ + { { 0x21dd895e,0x9fe229c9,0x40c28451,0x8e518500,0x1d637ecd,0xfa13d239, + 0x0e3c28de,0x660a2c56 }, + { 0xd67fcbd0,0x9cca88ae,0x0ea9f096,0xc8472478,0x72e92b4d,0x32b2f481, + 0x4f522453,0x624ee54c } }, + /* 52 */ + { { 0xd897eccc,0x09549ce4,0x3f9880aa,0x4d49d1d9,0x043a7c20,0x723c2423, + 0x92bdfbc0,0x4f392afb }, + { 0x7de44fd9,0x6969f8fa,0x57b32156,0xb66cfbe4,0x368ebc3c,0xdb2fa803, + 0xccdb399c,0x8a3e7977 } }, + /* 53 */ + { { 0x06c4b125,0xdde1881f,0xf6e3ca8c,0xae34e300,0x5c7a13e9,0xef6999de, + 0x70c24404,0x3888d023 }, + { 0x44f91081,0x76280356,0x5f015504,0x3d9fcf61,0x632cd36e,0x1827edc8, + 0x18102336,0xa5e62e47 } }, + /* 54 */ + { { 0x2facd6c8,0x1a825ee3,0x54bcbc66,0x699c6354,0x98df9931,0x0ce3edf7, + 0x466a5adc,0x2c4768e6 }, + { 0x90a64bc9,0xb346ff8c,0xe4779f5c,0x630a6020,0xbc05e884,0xd949d064, + 0xf9e652a0,0x7b5e6441 } }, + /* 55 */ + { { 0x1d28444a,0x2169422c,0xbe136a39,0xe996c5d8,0xfb0c7fce,0x2387afe5, + 0x0c8d744a,0xb8af73cb }, + { 0x338b86fd,0x5fde83aa,0xa58a5cff,0xfee3f158,0x20ac9433,0xc9ee8f6f, + 0x7f3f0895,0xa036395f } }, + /* 56 */ + { { 0xa10f7770,0x8c73c6bb,0xa12a0e24,0xa6f16d81,0x51bc2b9f,0x100df682, + 0x875fb533,0x4be36b01 }, + { 0x9fb56dbb,0x9226086e,0x07e7a4f8,0x306fef8b,0x66d52f20,0xeeaccc05, + 0x1bdc00c0,0x8cbc9a87 } }, + /* 57 */ + { { 0xc0dac4ab,0xe131895c,0x712ff112,0xa874a440,0x6a1cee57,0x6332ae7c, + 0x0c0835f8,0x44e7553e }, + { 0x7734002d,0x6d503fff,0x0b34425c,0x9d35cb8b,0x0e8738b5,0x95f70276, + 0x5eb8fc18,0x470a683a } }, + /* 58 */ + { { 0x90513482,0x81b761dc,0x01e9276a,0x0287202a,0x0ce73083,0xcda441ee, + 0xc63dc6ef,0x16410690 }, + { 0x6d06a2ed,0xf5034a06,0x189b100b,0xdd4d7745,0xab8218c9,0xd914ae72, + 0x7abcbb4f,0xd73479fd } }, + /* 59 */ + { { 0x5ad4c6e5,0x7edefb16,0x5b06d04d,0x262cf08f,0x8575cb14,0x12ed5bb1, + 0x0771666b,0x816469e3 }, + { 0x561e291e,0xd7ab9d79,0xc1de1661,0xeb9daf22,0x135e0513,0xf49827eb, + 0xf0dd3f9c,0x0a36dd23 } }, + /* 60 */ + { { 0x41d5533c,0x098d32c7,0x8684628f,0x7c5f5a9e,0xe349bd11,0x39a228ad, + 0xfdbab118,0xe331dfd6 }, + { 0x6bcc6ed8,0x5100ab68,0xef7a260e,0x7160c3bd,0xbce850d7,0x9063d9a7, + 0x492e3389,0xd3b4782a } }, + /* 61 */ + { { 0xf3821f90,0xa149b6e8,0x66eb7aad,0x92edd9ed,0x1a013116,0x0bb66953, + 0x4c86a5bd,0x7281275a }, + { 0xd3ff47e5,0x503858f7,0x61016441,0x5e1616bc,0x7dfd9bb1,0x62b0f11a, + 0xce145059,0x2c062e7e } }, + /* 62 */ + { { 0x0159ac2e,0xa76f996f,0xcbdb2713,0x281e7736,0x08e46047,0x2ad6d288, + 0x2c4e7ef1,0x282a35f9 }, + { 0xc0ce5cd2,0x9c354b1e,0x1379c229,0xcf99efc9,0x3e82c11e,0x992caf38, + 0x554d2abd,0xc71cd513 } }, + /* 63 */ + { { 0x09b578f4,0x4885de9c,0xe3affa7a,0x1884e258,0x59182f1f,0x8f76b1b7, + 0xcf47f3a3,0xc50f6740 }, + { 0x374b68ea,0xa9c4adf3,0x69965fe2,0xa406f323,0x85a53050,0x2f86a222, + 0x212958dc,0xb9ecb3a7 } }, + /* 64 */ + { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e, + 0xcd42ab1b,0x803f3e02 }, + { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e } }, + /* 65 */ + { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5 }, + { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418, + 0xe2d41c8b,0x23d0f130 } }, + /* 66 */ + { { 0xf41500d9,0x857ab6ed,0xfcbeada8,0x0d890ae5,0x89725951,0x52fe8648, + 0xc0a3fadd,0xb0288dd6 }, + { 0x650bcb08,0x85320f30,0x695d6e16,0x71af6313,0xb989aa76,0x31f520a7, + 0xf408c8d2,0xffd3724f } }, + /* 67 */ + { { 0xb458e6cb,0x53968e64,0x317a5d28,0x992dad20,0x7aa75f56,0x3814ae0b, + 0xd78c26df,0xf5590f4a }, + { 0xcf0ba55a,0x0fc24bd3,0x0c778bae,0x0fc4724a,0x683b674a,0x1ce9864f, + 0xf6f74a20,0x18d6da54 } }, + /* 68 */ + { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9 }, + { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b, + 0x01fe49c3,0x2b100118 } }, + /* 69 */ + { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999 }, + { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551 } }, + /* 70 */ + { { 0x1e9af288,0x55f655bb,0xf7ada931,0x647e1a64,0xcb2820e5,0x43697e4b, + 0x07ed56ff,0x51e00db1 }, + { 0x771c327e,0x43d169b8,0x4a96c2ad,0x29cdb20b,0x3deb4779,0xc07d51f5, + 0x49829177,0xe22f4241 } }, + /* 71 */ + { { 0x635f1abb,0xcd45e8f4,0x68538874,0x7edc0cb5,0xb5a8034d,0xc9472c1f, + 0x52dc48c9,0xf709373d }, + { 0xa8af30d6,0x401966bb,0xf137b69c,0x95bf5f4a,0x9361c47e,0x3966162a, + 0xe7275b11,0xbd52d288 } }, + /* 72 */ + { { 0x9c5fa877,0xab155c7a,0x7d3a3d48,0x17dad672,0x73d189d8,0x43f43f9e, + 0xc8aa77a6,0xa0d0f8e4 }, + { 0xcc94f92d,0x0bbeafd8,0x0c4ddb3a,0xd818c8be,0xb82eba14,0x22cc65f8, + 0x946d6a00,0xa56c78c7 } }, + /* 73 */ + { { 0x0dd09529,0x2962391b,0x3daddfcf,0x803e0ea6,0x5b5bf481,0x2c77351f, + 0x731a367a,0xd8befdf8 }, + { 0xfc0157f4,0xab919d42,0xfec8e650,0xf51caed7,0x02d48b0a,0xcdf9cb40, + 0xce9f6478,0x854a68a5 } }, + /* 74 */ + { { 0x63506ea5,0xdc35f67b,0xa4fe0d66,0x9286c489,0xfe95cd4d,0x3f101d3b, + 0x98846a95,0x5cacea0b }, + { 0x9ceac44d,0xa90df60c,0x354d1c3a,0x3db29af4,0xad5dbabe,0x08dd3de8, + 0x35e4efa9,0xe4982d12 } }, + /* 75 */ + { { 0xc34cd55e,0x23104a22,0x2680d132,0x58695bb3,0x1fa1d943,0xfb345afa, + 0x16b20499,0x8046b7f6 }, + { 0x38e7d098,0xb533581e,0xf46f0b70,0xd7f61e8d,0x44cb78c4,0x30dea9ea, + 0x9082af55,0xeb17ca7b } }, + /* 76 */ + { { 0x76a145b9,0x1751b598,0xc1bc71ec,0xa5cf6b0f,0x392715bb,0xd3e03565, + 0xfab5e131,0x097b00ba }, + { 0x565f69e1,0xaa66c8e9,0xb5be5199,0x77e8f75a,0xda4fd984,0x6033ba11, + 0xafdbcc9e,0xf95c747b } }, + /* 77 */ + { { 0xbebae45e,0x558f01d3,0xc4bc6955,0xa8ebe9f0,0xdbc64fc6,0xaeb705b1, + 0x566ed837,0x3512601e }, + { 0xfa1161cd,0x9336f1e1,0x4c65ef87,0x328ab8d5,0x724f21e5,0x4757eee2, + 0x6068ab6b,0x0ef97123 } }, + /* 78 */ + { { 0x54ca4226,0x02598cf7,0xf8642c8e,0x5eede138,0x468e1790,0x48963f74, + 0x3b4fbc95,0xfc16d933 }, + { 0xe7c800ca,0xbe96fb31,0x2678adaa,0x13806331,0x6ff3e8b5,0x3d624497, + 0xb95d7a17,0x14ca4af1 } }, + /* 79 */ + { { 0xbd2f81d5,0x7a4771ba,0x01f7d196,0x1a5f9d69,0xcad9c907,0xd898bef7, + 0xf59c231d,0x4057b063 }, + { 0x89c05c0a,0xbffd82fe,0x1dc0df85,0xe4911c6f,0xa35a16db,0x3befccae, + 0xf1330b13,0x1c3b5d64 } }, + /* 80 */ + { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148 }, + { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875, + 0x9f0e1a84,0x77387de3 } }, + /* 81 */ + { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0 }, + { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8 } }, + /* 82 */ + { { 0x84e35743,0x32aa3202,0x85a3cdef,0x320d6ab1,0x1df19819,0xb821b176, + 0xc433851f,0x5721361f }, + { 0x71fc9168,0x1f0db36a,0x5e5c403c,0x5f98ba73,0x37bcd8f5,0xf64ca87e, + 0xe6bb11bd,0xdcbac3c9 } }, + /* 83 */ + { { 0x4518cbe2,0xf01d9968,0x9c9eb04e,0xd242fc18,0xe47feebf,0x727663c7, + 0x2d626862,0xb8c1c89e }, + { 0xc8e1d569,0x51a58bdd,0xb7d88cd0,0x563809c8,0xf11f31eb,0x26c27fd9, + 0x2f9422d4,0x5d23bbda } }, + /* 84 */ + { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb }, + { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f } }, + /* 85 */ + { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52 }, + { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f } }, + /* 86 */ + { { 0x562976cc,0xbda5f14e,0x0ef12c38,0x22bca3e6,0x6cca9852,0xbbfa3064, + 0x08e2987a,0xbdb79dc8 }, + { 0xcb06a772,0xfd2cb5c9,0xfe536dce,0x38f475aa,0x7c2b5db8,0xc2a3e022, + 0xadd3c14a,0x8ee86001 } }, + /* 87 */ + { { 0xa4ade873,0xcbe96981,0xc4fba48c,0x7ee9aa4d,0x5a054ba5,0x2cee2899, + 0x6f77aa4b,0x92e51d7a }, + { 0x7190a34d,0x948bafa8,0xf6bd1ed1,0xd698f75b,0x0caf1144,0xd00ee6e3, + 0x0a56aaaa,0x5182f86f } }, + /* 88 */ + { { 0x7a4cc99c,0xfba6212c,0x3e6d9ca1,0xff609b68,0x5ac98c5a,0x5dbb27cb, + 0x4073a6f2,0x91dcab5d }, + { 0x5f575a70,0x01b6cc3d,0x6f8d87fa,0x0cb36139,0x89981736,0x165d4e8c, + 0x97974f2b,0x17a0cedb } }, + /* 89 */ + { { 0x076c8d3a,0x38861e2a,0x210f924b,0x701aad39,0x13a835d9,0x94d0eae4, + 0x7f4cdf41,0x2e8ce36c }, + { 0x037a862b,0x91273dab,0x60e4c8fa,0x01ba9bb7,0x33baf2dd,0xf9645388, + 0x34f668f3,0xf4ccc6cb } }, + /* 90 */ + { { 0xf1f79687,0x44ef525c,0x92efa815,0x7c595495,0xa5c78d29,0xe1231741, + 0x9a0df3c9,0xac0db488 }, + { 0xdf01747f,0x86bfc711,0xef17df13,0x592b9358,0x5ccb6bb5,0xe5880e4f, + 0x94c974a2,0x95a64a61 } }, + /* 91 */ + { { 0xc15a4c93,0x72c1efda,0x82585141,0x40269b73,0x16cb0bad,0x6a8dfb1c, + 0x29210677,0x231e54ba }, + { 0x8ae6d2dc,0xa70df917,0x39112918,0x4d6aa63f,0x5e5b7223,0xf627726b, + 0xd8a731e1,0xab0be032 } }, + /* 92 */ + { { 0x8d131f2d,0x097ad0e9,0x3b04f101,0x637f09e3,0xd5e9a748,0x1ac86196, + 0x2cf6a679,0xf1bcc880 }, + { 0xe8daacb4,0x25c69140,0x60f65009,0x3c4e4055,0x477937a6,0x591cc8fc, + 0x5aebb271,0x85169469 } }, + /* 93 */ + { { 0xf1dcf593,0xde35c143,0xb018be3b,0x78202b29,0x9bdd9d3d,0xe9cdadc2, + 0xdaad55d8,0x8f67d9d2 }, + { 0x7481ea5f,0x84111656,0xe34c590c,0xe7d2dde9,0x05053fa8,0xffdd43f4, + 0xc0728b5d,0xf84572b9 } }, + /* 94 */ + { { 0x97af71c9,0x5e1a7a71,0x7a736565,0xa1449444,0x0e1d5063,0xa1b4ae07, + 0x616b2c19,0xedee2710 }, + { 0x11734121,0xb2f034f5,0x4a25e9f0,0x1cac6e55,0xa40c2ecf,0x8dc148f3, + 0x44ebd7f4,0x9fd27e9b } }, + /* 95 */ + { { 0xf6e2cb16,0x3cc7658a,0xfe5919b6,0xe3eb7d2c,0x168d5583,0x5a8c5816, + 0x958ff387,0xa40c2fb6 }, + { 0xfedcc158,0x8c9ec560,0x55f23056,0x7ad804c6,0x9a307e12,0xd9396704, + 0x7dc6decf,0x99bc9bb8 } }, + /* 96 */ + { { 0x927dafc6,0x84a9521d,0x5c09cd19,0x52c1fb69,0xf9366dde,0x9d9581a0, + 0xa16d7e64,0x9abe210b }, + { 0x48915220,0x480af84a,0x4dd816c6,0xfa73176a,0x1681ca5a,0xc7d53987, + 0x87f344b0,0x7881c257 } }, + /* 97 */ + { { 0xe0bcf3ff,0x93399b51,0x127f74f6,0x0d02cbc5,0xdd01d968,0x8fb465a2, + 0xa30e8940,0x15e6e319 }, + { 0x3e0e05f4,0x646d6e0d,0x43588404,0xfad7bddc,0xc4f850d3,0xbe61c7d1, + 0x191172ce,0x0e55facf } }, + /* 98 */ + { { 0xf8787564,0x7e9d9806,0x31e85ce6,0x1a331721,0xb819e8d6,0x6b0158ca, + 0x6fe96577,0xd73d0976 }, + { 0x1eb7206e,0x42483425,0xc618bb42,0xa519290f,0x5e30a520,0x5dcbb859, + 0x8f15a50b,0x9250a374 } }, + /* 99 */ + { { 0xbe577410,0xcaff08f8,0x5077a8c6,0xfd408a03,0xec0a63a4,0xf1f63289, + 0xc1cc8c0b,0x77414082 }, + { 0xeb0991cd,0x05a40fa6,0x49fdc296,0xc1ca0866,0xb324fd40,0x3a68a3c7, + 0x12eb20b9,0x8cb04f4d } }, + /* 100 */ + { { 0x6906171c,0xb1c2d055,0xb0240c3f,0x9073e9cd,0xd8906841,0xdb8e6b4f, + 0x47123b51,0xe4e429ef }, + { 0x38ec36f4,0x0b8dd53c,0xff4b6a27,0xf9d2dc01,0x879a9a48,0x5d066e07, + 0x3c6e6552,0x37bca2ff } }, + /* 101 */ + { { 0xdf562470,0x4cd2e3c7,0xc0964ac9,0x44f272a2,0x80c793be,0x7c6d5df9, + 0x3002b22a,0x59913edc }, + { 0x5750592a,0x7a139a83,0xe783de02,0x99e01d80,0xea05d64f,0xcf8c0375, + 0xb013e226,0x43786e4a } }, + /* 102 */ + { { 0x9e56b5a6,0xff32b0ed,0xd9fc68f9,0x0750d9a6,0x597846a7,0xec15e845, + 0xb7e79e7a,0x8638ca98 }, + { 0x0afc24b2,0x2f5ae096,0x4dace8f2,0x05398eaf,0xaecba78f,0x3b765dd0, + 0x7b3aa6f0,0x1ecdd36a } }, + /* 103 */ + { { 0x6c5ff2f3,0x5d3acd62,0x2873a978,0xa2d516c0,0xd2110d54,0xad94c9fa, + 0xd459f32d,0xd85d0f85 }, + { 0x10b11da3,0x9f700b8d,0xa78318c4,0xd2c22c30,0x9208decd,0x556988f4, + 0xb4ed3c62,0xa04f19c3 } }, + /* 104 */ + { { 0xed7f93bd,0x087924c8,0x392f51f6,0xcb64ac5d,0x821b71af,0x7cae330a, + 0x5c0950b0,0x92b2eeea }, + { 0x85b6e235,0x85ac4c94,0x2936c0f0,0xab2ca4a9,0xe0508891,0x80faa6b3, + 0x5834276c,0x1ee78221 } }, + /* 105 */ + { { 0xe63e79f7,0xa60a2e00,0xf399d906,0xf590e7b2,0x6607c09d,0x9021054a, + 0x57a6e150,0xf3f2ced8 }, + { 0xf10d9b55,0x200510f3,0xd8642648,0x9d2fcfac,0xe8bd0e7c,0xe5631aa7, + 0x3da3e210,0x0f56a454 } }, + /* 106 */ + { { 0x1043e0df,0x5b21bffa,0x9c007e6d,0x6c74b6cc,0xd4a8517a,0x1a656ec0, + 0x1969e263,0xbd8f1741 }, + { 0xbeb7494a,0x8a9bbb86,0x45f3b838,0x1567d46f,0xa4e5a79a,0xdf7a12a7, + 0x30ccfa09,0x2d1a1c35 } }, + /* 107 */ + { { 0x506508da,0x192e3813,0xa1d795a7,0x336180c4,0x7a9944b3,0xcddb5949, + 0xb91fba46,0xa107a65e }, + { 0x0f94d639,0xe6d1d1c5,0x8a58b7d7,0x8b4af375,0xbd37ca1c,0x1a7c5584, + 0xf87a9af2,0x183d760a } }, + /* 108 */ + { { 0x0dde59a4,0x29d69711,0x0e8bef87,0xf1ad8d07,0x4f2ebe78,0x229b4963, + 0xc269d754,0x1d44179d }, + { 0x8390d30e,0xb32dc0cf,0x0de8110c,0x0a3b2753,0x2bc0339a,0x31af1dc5, + 0x9606d262,0x771f9cc2 } }, + /* 109 */ + { { 0x85040739,0x99993e77,0x8026a939,0x44539db9,0xf5f8fc26,0xcf40f6f2, + 0x0362718e,0x64427a31 }, + { 0x85428aa8,0x4f4f2d87,0xebfb49a8,0x7b7adc3f,0xf23d01ac,0x201b2c6d, + 0x6ae90d6d,0x49d9b749 } }, + /* 110 */ + { { 0x435d1099,0xcc78d8bc,0x8e8d1a08,0x2adbcd4e,0x2cb68a41,0x02c2e2a0, + 0x3f605445,0x9037d81b }, + { 0x074c7b61,0x7cdbac27,0x57bfd72e,0xfe2031ab,0x596d5352,0x61ccec96, + 0x7cc0639c,0x08c3de6a } }, + /* 111 */ + { { 0xf6d552ab,0x20fdd020,0x05cd81f1,0x56baff98,0x91351291,0x06fb7c3e, + 0x45796b2f,0xc6909442 }, + { 0x41231bd1,0x17b3ae9c,0x5cc58205,0x1eac6e87,0xf9d6a122,0x208837ab, + 0xcafe3ac0,0x3fa3db02 } }, + /* 112 */ + { { 0x05058880,0xd75a3e65,0x643943f2,0x7da365ef,0xfab24925,0x4147861c, + 0xfdb808ff,0xc5c4bdb0 }, + { 0xb272b56b,0x73513e34,0x11b9043a,0xc8327e95,0xf8844969,0xfd8ce37d, + 0x46c2b6b5,0x2d56db94 } }, + /* 113 */ + { { 0xff46ac6b,0x2461782f,0x07a2e425,0xd19f7926,0x09a48de1,0xfafea3c4, + 0xe503ba42,0x0f56bd9d }, + { 0x345cda49,0x137d4ed1,0x816f299d,0x821158fc,0xaeb43402,0xe7c6a54a, + 0x1173b5f1,0x4003bb9d } }, + /* 114 */ + { { 0xa0803387,0x3b8e8189,0x39cbd404,0xece115f5,0xd2877f21,0x4297208d, + 0xa07f2f9e,0x53765522 }, + { 0xa8a4182d,0xa4980a21,0x3219df79,0xa2bbd07a,0x1a19a2d4,0x674d0a2e, + 0x6c5d4549,0x7a056f58 } }, + /* 115 */ + { { 0x9d8a2a47,0x646b2558,0xc3df2773,0x5b582948,0xabf0d539,0x51ec000e, + 0x7a1a2675,0x77d482f1 }, + { 0x87853948,0xb8a1bd95,0x6cfbffee,0xa6f817bd,0x80681e47,0xab6ec057, + 0x2b38b0e4,0x4115012b } }, + /* 116 */ + { { 0x6de28ced,0x3c73f0f4,0x9b13ec47,0x1d5da760,0x6e5c6392,0x61b8ce9e, + 0xfbea0946,0xcdf04572 }, + { 0x6c53c3b0,0x1cb3c58b,0x447b843c,0x97fe3c10,0x2cb9780e,0xfb2b8ae1, + 0x97383109,0xee703dda } }, + /* 117 */ + { { 0xff57e43a,0x34515140,0xb1b811b8,0xd44660d3,0x8f42b986,0x2b3b5dff, + 0xa162ce21,0x2a0ad89d }, + { 0x6bc277ba,0x64e4a694,0xc141c276,0xc788c954,0xcabf6274,0x141aa64c, + 0xac2b4659,0xd62d0b67 } }, + /* 118 */ + { { 0x2c054ac4,0x39c5d87b,0xf27df788,0x57005859,0xb18128d6,0xedf7cbf3, + 0x991c2426,0xb39a23f2 }, + { 0xf0b16ae5,0x95284a15,0xa136f51b,0x0c6a05b1,0xf2700783,0x1d63c137, + 0xc0674cc5,0x04ed0092 } }, + /* 119 */ + { { 0x9ae90393,0x1f4185d1,0x4a3d64e6,0x3047b429,0x9854fc14,0xae0001a6, + 0x0177c387,0xa0a91fc1 }, + { 0xae2c831e,0xff0a3f01,0x2b727e16,0xbb76ae82,0x5a3075b4,0x8f12c8a1, + 0x9ed20c41,0x084cf988 } }, + /* 120 */ + { { 0xfca6becf,0xd98509de,0x7dffb328,0x2fceae80,0x4778e8b9,0x5d8a15c4, + 0x73abf77e,0xd57955b2 }, + { 0x31b5d4f1,0x210da79e,0x3cfa7a1c,0xaa52f04b,0xdc27c20b,0xd4d12089, + 0x02d141f1,0x8e14ea42 } }, + /* 121 */ + { { 0xf2897042,0xeed50345,0x43402c4a,0x8d05331f,0xc8bdfb21,0xc8d9c194, + 0x2aa4d158,0x597e1a37 }, + { 0xcf0bd68c,0x0327ec1a,0xab024945,0x6d4be0dc,0xc9fe3e84,0x5b9c8d7a, + 0x199b4dea,0xca3f0236 } }, + /* 122 */ + { { 0x6170bd20,0x592a10b5,0x6d3f5de7,0x0ea897f1,0x44b2ade2,0xa3363ff1, + 0x309c07e4,0xbde7fd7e }, + { 0xb8f5432c,0x516bb6d2,0xe043444b,0x210dc1cb,0xf8f95b5a,0x3db01e6f, + 0x0a7dd198,0xb623ad0e } }, + /* 123 */ + { { 0x60c7b65b,0xa75bd675,0x23a4a289,0xab8c5590,0xd7b26795,0xf8220fd0, + 0x58ec137b,0xd6aa2e46 }, + { 0x5138bb85,0x10abc00b,0xd833a95c,0x8c31d121,0x1702a32e,0xb24ff00b, + 0x2dcc513a,0x111662e0 } }, + /* 124 */ + { { 0xefb42b87,0x78114015,0x1b6c4dff,0xbd9f5d70,0xa7d7c129,0x66ecccd7, + 0x94b750f8,0xdb3ee1cb }, + { 0xf34837cf,0xb26f3db0,0xb9578d4f,0xe7eed18b,0x7c56657d,0x5d2cdf93, + 0x52206a59,0x886a6442 } }, + /* 125 */ + { { 0x65b569ea,0x3c234cfb,0xf72119c1,0x20011141,0xa15a619e,0x8badc85d, + 0x018a17bc,0xa70cf4eb }, + { 0x8c4a6a65,0x224f97ae,0x0134378f,0x36e5cf27,0x4f7e0960,0xbe3a609e, + 0xd1747b77,0xaa4772ab } }, + /* 126 */ + { { 0x7aa60cc0,0x67676131,0x0368115f,0xc7916361,0xbbc1bb5a,0xded98bb4, + 0x30faf974,0x611a6ddc }, + { 0xc15ee47a,0x30e78cbc,0x4e0d96a5,0x2e896282,0x3dd9ed88,0x36f35adf, + 0x16429c88,0x5cfffaf8 } }, + /* 127 */ + { { 0x9b7a99cd,0xc0d54cff,0x843c45a1,0x7bf3b99d,0x62c739e1,0x038a908f, + 0x7dc1994c,0x6e5a6b23 }, + { 0x0ba5db77,0xef8b454e,0xacf60d63,0xb7b8807f,0x76608378,0xe591c0c6, + 0x242dabcc,0x481a238d } }, + /* 128 */ + { { 0x35d0b34a,0xe3417bc0,0x8327c0a7,0x440b386b,0xac0362d1,0x8fb7262d, + 0xe0cdf943,0x2c41114c }, + { 0xad95a0b1,0x2ba5cef1,0x67d54362,0xc09b37a8,0x01e486c9,0x26d6cdd2, + 0x42ff9297,0x20477abf } }, + /* 129 */ + { { 0x18d65dbf,0x2f75173c,0x339edad8,0x77bf940e,0xdcf1001c,0x7022d26b, + 0xc77396b6,0xac66409a }, + { 0xc6261cc3,0x8b0bb36f,0x190e7e90,0x213f7bc9,0xa45e6c10,0x6541ceba, + 0xcc122f85,0xce8e6975 } }, + /* 130 */ + { { 0xbc0a67d2,0x0f121b41,0x444d248a,0x62d4760a,0x659b4737,0x0e044f1d, + 0x250bb4a8,0x08fde365 }, + { 0x848bf287,0xaceec3da,0xd3369d6e,0xc2a62182,0x92449482,0x3582dfdc, + 0x565d6cd7,0x2f7e2fd2 } }, + /* 131 */ + { { 0xc3770fa7,0xae4b92db,0x379043f9,0x095e8d5c,0x17761171,0x54f34e9d, + 0x907702ae,0xc65be92e }, + { 0xf6fd0a40,0x2758a303,0xbcce784b,0xe7d822e3,0x4f9767bf,0x7ae4f585, + 0xd1193b3a,0x4bff8e47 } }, + /* 132 */ + { { 0x00ff1480,0xcd41d21f,0x0754db16,0x2ab8fb7d,0xbbe0f3ea,0xac81d2ef, + 0x5772967d,0x3e4e4ae6 }, + { 0x3c5303e6,0x7e18f36d,0x92262397,0x3bd9994b,0x1324c3c0,0x9ed70e26, + 0x58ec6028,0x5388aefd } }, + /* 133 */ + { { 0x5e5d7713,0xad1317eb,0x75de49da,0x09b985ee,0xc74fb261,0x32f5bc4f, + 0x4f75be0e,0x5cf908d1 }, + { 0x8e657b12,0x76043510,0xb96ed9e6,0xbfd421a5,0x8970ccc2,0x0e29f51f, + 0x60f00ce2,0xa698ba40 } }, + /* 134 */ + { { 0xef748fec,0x73db1686,0x7e9d2cf9,0xe6e755a2,0xce265eff,0x630b6544, + 0x7aebad8d,0xb142ef8a }, + { 0x17d5770a,0xad31af9f,0x2cb3412f,0x66af3b67,0xdf3359de,0x6bd60d1b, + 0x58515075,0xd1896a96 } }, + /* 135 */ + { { 0x33c41c08,0xec5957ab,0x5468e2e1,0x87de94ac,0xac472f6c,0x18816b73, + 0x7981da39,0x267b0e0b }, + { 0x8e62b988,0x6e554e5d,0x116d21e7,0xd8ddc755,0x3d2a6f99,0x4610faf0, + 0xa1119393,0xb54e287a } }, + /* 136 */ + { { 0x178a876b,0x0a0122b5,0x085104b4,0x51ff96ff,0x14f29f76,0x050b31ab, + 0x5f87d4e6,0x84abb28b }, + { 0x8270790a,0xd5ed439f,0x85e3f46b,0x2d6cb59d,0x6c1e2212,0x75f55c1b, + 0x17655640,0xe5436f67 } }, + /* 137 */ + { { 0x2286e8d5,0x53f9025e,0x864453be,0x353c95b4,0xe408e3a0,0xd832f5bd, + 0x5b9ce99e,0x0404f68b }, + { 0xa781e8e5,0xcad33bde,0x163c2f5b,0x3cdf5018,0x0119caa3,0x57576960, + 0x0ac1c701,0x3a4263df } }, + /* 138 */ + { { 0x9aeb596d,0xc2965ecc,0x023c92b4,0x01ea03e7,0x2e013961,0x4704b4b6, + 0x905ea367,0x0ca8fd3f }, + { 0x551b2b61,0x92523a42,0x390fcd06,0x1eb7a89c,0x0392a63e,0xe7f1d2be, + 0x4ddb0c33,0x96dca264 } }, + /* 139 */ + { { 0x387510af,0x203bb43a,0xa9a36a01,0x846feaa8,0x2f950378,0xd23a5770, + 0x3aad59dc,0x4363e212 }, + { 0x40246a47,0xca43a1c7,0xe55dd24d,0xb362b8d2,0x5d8faf96,0xf9b08604, + 0xd8bb98c4,0x840e115c } }, + /* 140 */ + { { 0x1023e8a7,0xf12205e2,0xd8dc7a0b,0xc808a8cd,0x163a5ddf,0xe292a272, + 0x30ded6d4,0x5e0d6abd }, + { 0x7cfc0f64,0x07a721c2,0x0e55ed88,0x42eec01d,0x1d1f9db2,0x26a7bef9, + 0x2945a25a,0x7dea48f4 } }, + /* 141 */ + { { 0xe5060a81,0xabdf6f1c,0xf8f95615,0xe79f9c72,0x06ac268b,0xcfd36c54, + 0xebfd16d1,0xabc2a2be }, + { 0xd3e2eac7,0x8ac66f91,0xd2dd0466,0x6f10ba63,0x0282d31b,0x6790e377, + 0x6c7eefc1,0x4ea35394 } }, + /* 142 */ + { { 0x5266309d,0xed8a2f8d,0x81945a3e,0x0a51c6c0,0x578c5dc1,0xcecaf45a, + 0x1c94ffc3,0x3a76e689 }, + { 0x7d7b0d0f,0x9aace8a4,0x8f584a5f,0x963ace96,0x4e697fbe,0x51a30c72, + 0x465e6464,0x8212a10a } }, + /* 143 */ + { { 0xcfab8caa,0xef7c61c3,0x0e142390,0x18eb8e84,0x7e9733ca,0xcd1dff67, + 0x599cb164,0xaa7cab71 }, + { 0xbc837bd1,0x02fc9273,0xc36af5d7,0xc06407d0,0xf423da49,0x17621292, + 0xfe0617c3,0x40e38073 } }, + /* 144 */ + { { 0xa7bf9b7c,0xf4f80824,0x3fbe30d0,0x365d2320,0x97cf9ce3,0xbfbe5320, + 0xb3055526,0xe3604700 }, + { 0x6cc6c2c7,0x4dcb9911,0xba4cbee6,0x72683708,0x637ad9ec,0xdcded434, + 0xa3dee15f,0x6542d677 } }, + /* 145 */ + { { 0x7b6c377a,0x3f32b6d0,0x903448be,0x6cb03847,0x20da8af7,0xd6fdd3a8, + 0x09bb6f21,0xa6534aee }, + { 0x1035facf,0x30a1780d,0x9dcb47e6,0x35e55a33,0xc447f393,0x6ea50fe1, + 0xdc9aef22,0xf3cb672f } }, + /* 146 */ + { { 0x3b55fd83,0xeb3719fe,0x875ddd10,0xe0d7a46c,0x05cea784,0x33ac9fa9, + 0xaae870e7,0x7cafaa2e }, + { 0x1d53b338,0x9b814d04,0xef87e6c6,0xe0acc0a0,0x11672b0f,0xfb93d108, + 0xb9bd522e,0x0aab13c1 } }, + /* 147 */ + { { 0xd2681297,0xddcce278,0xb509546a,0xcb350eb1,0x7661aaf2,0x2dc43173, + 0x847012e9,0x4b91a602 }, + { 0x72f8ddcf,0xdcff1095,0x9a911af4,0x08ebf61e,0xc372430e,0x48f4360a, + 0x72321cab,0x49534c53 } }, + /* 148 */ + { { 0xf07b7e9d,0x83df7d71,0x13cd516f,0xa478efa3,0x6c047ee3,0x78ef264b, + 0xd65ac5ee,0xcaf46c4f }, + { 0x92aa8266,0xa04d0c77,0x913684bb,0xedf45466,0xae4b16b0,0x56e65168, + 0x04c6770f,0x14ce9e57 } }, + /* 149 */ + { { 0x965e8f91,0x99445e3e,0xcb0f2492,0xd3aca1ba,0x90c8a0a0,0xd31cc70f, + 0x3e4c9a71,0x1bb708a5 }, + { 0x558bdd7a,0xd5ca9e69,0x018a26b1,0x734a0508,0x4c9cf1ec,0xb093aa71, + 0xda300102,0xf9d126f2 } }, + /* 150 */ + { { 0xaff9563e,0x749bca7a,0xb49914a0,0xdd077afe,0xbf5f1671,0xe27a0311, + 0x729ecc69,0x807afcb9 }, + { 0xc9b08b77,0x7f8a9337,0x443c7e38,0x86c3a785,0x476fd8ba,0x85fafa59, + 0x6568cd8c,0x751adcd1 } }, + /* 151 */ + { { 0x10715c0d,0x8aea38b4,0x8f7697f7,0xd113ea71,0x93fbf06d,0x665eab14, + 0x2537743f,0x29ec4468 }, + { 0xb50bebbc,0x3d94719c,0xe4505422,0x399ee5bf,0x8d2dedb1,0x90cd5b3a, + 0x92a4077d,0xff9370e3 } }, + /* 152 */ + { { 0xc6b75b65,0x59a2d69b,0x266651c5,0x4188f8d5,0x3de9d7d2,0x28a9f33e, + 0xa2a9d01a,0x9776478b }, + { 0x929af2c7,0x8852622d,0x4e690923,0x334f5d6d,0xa89a51e9,0xce6cc7e5, + 0xac2f82fa,0x74a6313f } }, + /* 153 */ + { { 0xb75f079c,0xb2f4dfdd,0x18e36fbb,0x85b07c95,0xe7cd36dd,0x1b6cfcf0, + 0x0ff4863d,0xab75be15 }, + { 0x173fc9b7,0x81b367c0,0xd2594fd0,0xb90a7420,0xc4091236,0x15fdbf03, + 0x0b4459f6,0x4ebeac2e } }, + /* 154 */ + { { 0x5c9f2c53,0xeb6c5fe7,0x8eae9411,0xd2522011,0xf95ac5d8,0xc8887633, + 0x2c1baffc,0xdf99887b }, + { 0x850aaecb,0xbb78eed2,0x01d6a272,0x9d49181b,0xb1cdbcac,0x978dd511, + 0x779f4058,0x27b040a7 } }, + /* 155 */ + { { 0xf73b2eb2,0x90405db7,0x8e1b2118,0xe0df8508,0x5962327e,0x501b7152, + 0xe4cfa3f5,0xb393dd37 }, + { 0x3fd75165,0xa1230e7b,0xbcd33554,0xd66344c2,0x0f7b5022,0x6c36f1be, + 0xd0463419,0x09588c12 } }, + /* 156 */ + { { 0x02601c3b,0xe086093f,0xcf5c335f,0xfb0252f8,0x894aff28,0x955cf280, + 0xdb9f648b,0x81c879a9 }, + { 0xc6f56c51,0x040e687c,0x3f17618c,0xfed47169,0x9059353b,0x44f88a41, + 0x5fc11bc4,0xfa0d48f5 } }, + /* 157 */ + { { 0xe1608e4d,0xbc6e1c9d,0x3582822c,0x010dda11,0x157ec2d7,0xf6b7ddc1, + 0xb6a367d6,0x8ea0e156 }, + { 0x2383b3b4,0xa354e02f,0x3f01f53c,0x69966b94,0x2de03ca5,0x4ff6632b, + 0xfa00b5ac,0x3f5ab924 } }, + /* 158 */ + { { 0x59739efb,0x337bb0d9,0xe7ebec0d,0xc751b0f4,0x411a67d1,0x2da52dd6, + 0x2b74256e,0x8bc76887 }, + { 0x82d3d253,0xa5be3b72,0xf58d779f,0xa9f679a1,0xe16767bb,0xa1cac168, + 0x60fcf34f,0xb386f190 } }, + /* 159 */ + { { 0x2fedcfc2,0x31f3c135,0x62f8af0d,0x5396bf62,0xe57288c2,0x9a02b4ea, + 0x1b069c4d,0x4cb460f7 }, + { 0x5b8095ea,0xae67b4d3,0x6fc07603,0x92bbf859,0xb614a165,0xe1475f66, + 0x95ef5223,0x52c0d508 } }, + /* 160 */ + { { 0x15339848,0x231c210e,0x70778c8d,0xe87a28e8,0x6956e170,0x9d1de661, + 0x2bb09c0b,0x4ac3c938 }, + { 0x6998987d,0x19be0551,0xae09f4d6,0x8b2376c4,0x1a3f933d,0x1de0b765, + 0xe39705f4,0x380d94c7 } }, + /* 161 */ + { { 0x81542e75,0x01a355aa,0xee01b9b7,0x96c724a1,0x624d7087,0x6b3a2977, + 0xde2637af,0x2ce3e171 }, + { 0xf5d5bc1a,0xcfefeb49,0x2777e2b5,0xa655607e,0x9513756c,0x4feaac2f, + 0x0b624e4d,0x2e6cd852 } }, + /* 162 */ + { { 0x8c31c31d,0x3685954b,0x5bf21a0c,0x68533d00,0x75c79ec9,0x0bd7626e, + 0x42c69d54,0xca177547 }, + { 0xf6d2dbb2,0xcc6edaff,0x174a9d18,0xfd0d8cbd,0xaa4578e8,0x875e8793, + 0x9cab2ce6,0xa976a713 } }, + /* 163 */ + { { 0x93fb353d,0x0a651f1b,0x57fcfa72,0xd75cab8b,0x31b15281,0xaa88cfa7, + 0x0a1f4999,0x8720a717 }, + { 0x693e1b90,0x8c3e8d37,0x16f6dfc3,0xd345dc0b,0xb52a8742,0x8ea8d00a, + 0xc769893c,0x9719ef29 } }, + /* 164 */ + { { 0x58e35909,0x820eed8d,0x33ddc116,0x9366d8dc,0x6e205026,0xd7f999d0, + 0xe15704c1,0xa5072976 }, + { 0xc4e70b2e,0x002a37ea,0x6890aa8a,0x84dcf657,0x645b2a5c,0xcd71bf18, + 0xf7b77725,0x99389c9d } }, + /* 165 */ + { { 0x7ada7a4b,0x238c08f2,0xfd389366,0x3abe9d03,0x766f512c,0x6b672e89, + 0x202c82e4,0xa88806aa }, + { 0xd380184e,0x6602044a,0x126a8b85,0xa8cb78c4,0xad844f17,0x79d670c0, + 0x4738dcfe,0x0043bffb } }, + /* 166 */ + { { 0x36d5192e,0x8d59b5dc,0x4590b2af,0xacf885d3,0x11601781,0x83566d0a, + 0xba6c4866,0x52f3ef01 }, + { 0x0edcb64d,0x3986732a,0x8068379f,0x0a482c23,0x7040f309,0x16cbe5fa, + 0x9ef27e75,0x3296bd89 } }, + /* 167 */ + { { 0x454d81d7,0x476aba89,0x51eb9b3c,0x9eade7ef,0x81c57986,0x619a21cd, + 0xaee571e9,0x3b90febf }, + { 0x5496f7cb,0x9393023e,0x7fb51bc4,0x55be41d8,0x99beb5ce,0x03f1dd48, + 0x9f810b18,0x6e88069d } }, + /* 168 */ + { { 0xb43ea1db,0xce37ab11,0x5259d292,0x0a7ff1a9,0x8f84f186,0x851b0221, + 0xdefaad13,0xa7222bea }, + { 0x2b0a9144,0xa2ac78ec,0xf2fa59c5,0x5a024051,0x6147ce38,0x91d1eca5, + 0xbc2ac690,0xbe94d523 } }, + /* 169 */ + { { 0x0b226ce7,0x72f4945e,0x967e8b70,0xb8afd747,0x85a6c63e,0xedea46f1, + 0x9be8c766,0x7782defe }, + { 0x3db38626,0x760d2aa4,0x76f67ad1,0x460ae787,0x54499cdb,0x341b86fc, + 0xa2892e4b,0x03838567 } }, + /* 170 */ + { { 0x79ec1a0f,0x2d8daefd,0xceb39c97,0x3bbcd6fd,0x58f61a95,0xf5575ffc, + 0xadf7b420,0xdbd986c4 }, + { 0x15f39eb7,0x81aa8814,0xb98d976c,0x6ee2fcf5,0xcf2f717d,0x5465475d, + 0x6860bbd0,0x8e24d3c4 } }, + /* 171 */ + { { 0x9a587390,0x749d8e54,0x0cbec588,0x12bb194f,0xb25983c6,0x46e07da4, + 0x407bafc8,0x541a99c4 }, + { 0x624c8842,0xdb241692,0xd86c05ff,0x6044c12a,0x4f7fcf62,0xc59d14b4, + 0xf57d35d1,0xc0092c49 } }, + /* 172 */ + { { 0xdf2e61ef,0xd3cc75c3,0x2e1b35ca,0x7e8841c8,0x909f29f4,0xc62d30d1, + 0x7286944d,0x75e40634 }, + { 0xbbc237d0,0xe7d41fc5,0xec4f01c9,0xc9537bf0,0x282bd534,0x91c51a16, + 0xc7848586,0x5b7cb658 } }, + /* 173 */ + { { 0x8a28ead1,0x964a7084,0xfd3b47f6,0x802dc508,0x767e5b39,0x9ae4bfd1, + 0x8df097a1,0x7ae13eba }, + { 0xeadd384e,0xfd216ef8,0xb6b2ff06,0x0361a2d9,0x4bcdb5f3,0x204b9878, + 0xe2a8e3fd,0x787d8074 } }, + /* 174 */ + { { 0x757fbb1c,0xc5e25d6b,0xca201deb,0xe47bddb2,0x6d2233ff,0x4a55e9a3, + 0x9ef28484,0x5c222819 }, + { 0x88315250,0x773d4a85,0x827097c1,0x21b21a2b,0xdef5d33f,0xab7c4ea1, + 0xbaf0f2b0,0xe45d37ab } }, + /* 175 */ + { { 0x28511c8a,0xd2df1e34,0xbdca6cd3,0xebb229c8,0x627c39a7,0x578a71a7, + 0x84dfb9d3,0xed7bc122 }, + { 0x93dea561,0xcf22a6df,0xd48f0ed1,0x5443f18d,0x5bad23e8,0xd8b86140, + 0x45ca6d27,0xaac97cc9 } }, + /* 176 */ + { { 0xa16bd00a,0xeb54ea74,0xf5c0bcc1,0xd839e9ad,0x1f9bfc06,0x092bb7f1, + 0x1163dc4e,0x318f97b3 }, + { 0xc30d7138,0xecc0c5be,0xabc30220,0x44e8df23,0xb0223606,0x2bb7972f, + 0x9a84ff4d,0xfa41faa1 } }, + /* 177 */ + { { 0xa6642269,0x4402d974,0x9bb783bd,0xc81814ce,0x7941e60b,0x398d38e4, + 0x1d26e9e2,0x38bb6b2c }, + { 0x6a577f87,0xc64e4a25,0xdc11fe1c,0x8b52d253,0x62280728,0xff336abf, + 0xce7601a5,0x94dd0905 } }, + /* 178 */ + { { 0xde93f92a,0x156cf7dc,0x89b5f315,0xa01333cb,0xc995e750,0x02404df9, + 0xd25c2ae9,0x92077867 }, + { 0x0bf39d44,0xe2471e01,0x96bb53d7,0x5f2c9020,0x5c9c3d8f,0x4c44b7b3, + 0xd29beb51,0x81e8428b } }, + /* 179 */ + { { 0xc477199f,0x6dd9c2ba,0x6b5ecdd9,0x8cb8eeee,0xee40fd0e,0x8af7db3f, + 0xdbbfa4b1,0x1b94ab62 }, + { 0xce47f143,0x44f0d8b3,0x63f46163,0x51e623fc,0xcc599383,0xf18f270f, + 0x055590ee,0x06a38e28 } }, + /* 180 */ + { { 0xb3355b49,0x2e5b0139,0xb4ebf99b,0x20e26560,0xd269f3dc,0xc08ffa6b, + 0x83d9d4f8,0xa7b36c20 }, + { 0x1b3e8830,0x64d15c3a,0xa89f9c0b,0xd5fceae1,0xe2d16930,0xcfeee4a2, + 0xa2822a20,0xbe54c6b4 } }, + /* 181 */ + { { 0x8d91167c,0xd6cdb3df,0xe7a6625e,0x517c3f79,0x346ac7f4,0x7105648f, + 0xeae022bb,0xbf30a5ab }, + { 0x93828a68,0x8e7785be,0x7f3ef036,0x5161c332,0x592146b2,0xe11b5feb, + 0x2732d13a,0xd1c820de } }, + /* 182 */ + { { 0x9038b363,0x043e1347,0x6b05e519,0x58c11f54,0x6026cad1,0x4fe57abe, + 0x68a18da3,0xb7d17bed }, + { 0xe29c2559,0x44ca5891,0x5bfffd84,0x4f7a0376,0x74e46948,0x498de4af, + 0x6412cc64,0x3997fd5e } }, + /* 183 */ + { { 0x8bd61507,0xf2074682,0x34a64d2a,0x29e132d5,0x8a8a15e3,0xffeddfb0, + 0x3c6c13e8,0x0eeb8929 }, + { 0xa7e259f8,0xe9b69a3e,0xd13e7e67,0xce1db7e6,0xad1fa685,0x277318f6, + 0xc922b6ef,0x228916f8 } }, + /* 184 */ + { { 0x0a12ab5b,0x959ae25b,0x957bc136,0xcc11171f,0xd16e2b0c,0x8058429e, + 0x6e93097e,0xec05ad1d }, + { 0xac3f3708,0x157ba5be,0x30b59d77,0x31baf935,0x118234e5,0x47b55237, + 0x7ff11b37,0x7d314156 } }, + /* 185 */ + { { 0xf6dfefab,0x7bd9c05c,0xdcb37707,0xbe2f2268,0x3a38bb95,0xe53ead97, + 0x9bc1d7a3,0xe9ce66fc }, + { 0x6f6a02a1,0x75aa1576,0x60e600ed,0x38c087df,0x68cdc1b9,0xf8947f34, + 0x72280651,0xd9650b01 } }, + /* 186 */ + { { 0x5a057e60,0x504b4c4a,0x8def25e4,0xcbccc3be,0x17c1ccbd,0xa6353208, + 0x804eb7a2,0x14d6699a }, + { 0xdb1f411a,0x2c8a8415,0xf80d769c,0x09fbaf0b,0x1c2f77ad,0xb4deef90, + 0x0d43598a,0x6f4c6841 } }, + /* 187 */ + { { 0x96c24a96,0x8726df4e,0xfcbd99a3,0x534dbc85,0x8b2ae30a,0x3c466ef2, + 0x61189abb,0x4c4350fd }, + { 0xf855b8da,0x2967f716,0x463c38a1,0x41a42394,0xeae93343,0xc37e1413, + 0x5a3118b5,0xa726d242 } }, + /* 188 */ + { { 0x948c1086,0xdae6b3ee,0xcbd3a2e1,0xf1de503d,0x03d022f3,0x3f35ed3f, + 0xcc6cf392,0x13639e82 }, + { 0xcdafaa86,0x9ac938fb,0x2654a258,0xf45bc5fb,0x45051329,0x1963b26e, + 0xc1a335a3,0xca9365e1 } }, + /* 189 */ + { { 0x4c3b2d20,0x3615ac75,0x904e241b,0x742a5417,0xcc9d071d,0xb08521c4, + 0x970b72a5,0x9ce29c34 }, + { 0x6d3e0ad6,0x8cc81f73,0xf2f8434c,0x8060da9e,0x6ce862d9,0x35ed1d1a, + 0xab42af98,0x48c4abd7 } }, + /* 190 */ + { { 0x40c7485a,0xd221b0cc,0xe5274dbf,0xead455bb,0x9263d2e8,0x493c7698, + 0xf67b33cb,0x78017c32 }, + { 0x930cb5ee,0xb9d35769,0x0c408ed2,0xc0d14e94,0x272f1a4d,0xf8b7bf55, + 0xde5c1c04,0x53cd0454 } }, + /* 191 */ + { { 0x5d28ccac,0xbcd585fa,0x005b746e,0x5f823e56,0xcd0123aa,0x7c79f0a1, + 0xd3d7fa8f,0xeea465c1 }, + { 0x0551803b,0x7810659f,0x7ce6af70,0x6c0b599f,0x29288e70,0x4195a770, + 0x7ae69193,0x1b6e42a4 } }, + /* 192 */ + { { 0xf67d04c3,0x2e80937c,0x89eeb811,0x1e312be2,0x92594d60,0x56b5d887, + 0x187fbd3d,0x0224da14 }, + { 0x0c5fe36f,0x87abb863,0x4ef51f5f,0x580f3c60,0xb3b429ec,0x964fb1bf, + 0x42bfff33,0x60838ef0 } }, + /* 193 */ + { { 0x7e0bbe99,0x432cb2f2,0x04aa39ee,0x7bda44f3,0x9fa93903,0x5f497c7a, + 0x2d331643,0x636eb202 }, + { 0x93ae00aa,0xfcfd0e61,0x31ae6d2f,0x875a00fe,0x9f93901c,0xf43658a2, + 0x39218bac,0x8844eeb6 } }, + /* 194 */ + { { 0x6b3bae58,0x114171d2,0x17e39f3e,0x7db3df71,0x81a8eada,0xcd37bc7f, + 0x51fb789e,0x27ba83dc }, + { 0xfbf54de5,0xa7df439f,0xb5fe1a71,0x7277030b,0xdb297a48,0x42ee8e35, + 0x87f3a4ab,0xadb62d34 } }, + /* 195 */ + { { 0xa175df2a,0x9b1168a2,0x618c32e9,0x082aa04f,0x146b0916,0xc9e4f2e7, + 0x75e7c8b2,0xb990fd76 }, + { 0x4df37313,0x0829d96b,0xd0b40789,0x1c205579,0x78087711,0x66c9ae4a, + 0x4d10d18d,0x81707ef9 } }, + /* 196 */ + { { 0x03d6ff96,0x97d7cab2,0x0d843360,0x5b851bfc,0xd042db4b,0x268823c4, + 0xd5a8aa5c,0x3792daea }, + { 0x941afa0b,0x52818865,0x42d83671,0xf3e9e741,0x5be4e0a7,0x17c82527, + 0x94b001ba,0x5abd635e } }, + /* 197 */ + { { 0x0ac4927c,0x727fa84e,0xa7c8cf23,0xe3886035,0x4adca0df,0xa4bcd5ea, + 0x846ab610,0x5995bf21 }, + { 0x829dfa33,0xe90f860b,0x958fc18b,0xcaafe2ae,0x78630366,0x9b3baf44, + 0xd483411e,0x44c32ca2 } }, + /* 198 */ + { { 0xe40ed80c,0xa74a97f1,0x31d2ca82,0x5f938cb1,0x7c2d6ad9,0x53f2124b, + 0x8082a54c,0x1f2162fb }, + { 0x720b173e,0x7e467cc5,0x085f12f9,0x40e8a666,0x4c9d65dc,0x8cebc20e, + 0xc3e907c9,0x8f1d402b } }, + /* 199 */ + { { 0xfbc4058a,0x4f592f9c,0x292f5670,0xb15e14b6,0xbc1d8c57,0xc55cfe37, + 0x926edbf9,0xb1980f43 }, + { 0x32c76b09,0x98c33e09,0x33b07f78,0x1df5279d,0x863bb461,0x6f08ead4, + 0x37448e45,0x2828ad9b } }, + /* 200 */ + { { 0xc4cf4ac5,0x696722c4,0xdde64afb,0xf5ac1a3f,0xe0890832,0x0551baa2, + 0x5a14b390,0x4973f127 }, + { 0x322eac5d,0xe59d8335,0x0bd9b568,0x5e07eef5,0xa2588393,0xab36720f, + 0xdb168ac7,0x6dac8ed0 } }, + /* 201 */ + { { 0xeda835ef,0xf7b545ae,0x1d10ed51,0x4aa113d2,0x13741b09,0x035a65e0, + 0x20b9de4c,0x4b23ef59 }, + { 0x3c4c7341,0xe82bb680,0x3f58bc37,0xd457706d,0xa51e3ee8,0x73527863, + 0xddf49a4e,0x4dd71534 } }, + /* 202 */ + { { 0x95476cd9,0xbf944672,0xe31a725b,0x648d072f,0xfc4b67e0,0x1441c8b8, + 0x2f4a4dbb,0xfd317000 }, + { 0x8995d0e1,0x1cb43ff4,0x0ef729aa,0x76e695d1,0x41798982,0xe0d5f976, + 0x9569f365,0x14fac58c } }, + /* 203 */ + { { 0xf312ae18,0xad9a0065,0xfcc93fc9,0x51958dc0,0x8a7d2846,0xd9a14240, + 0x36abda50,0xed7c7651 }, + { 0x25d4abbc,0x46270f1a,0xf1a113ea,0x9b5dd8f3,0x5b51952f,0xc609b075, + 0x4d2e9f53,0xfefcb7f7 } }, + /* 204 */ + { { 0xba119185,0xbd09497a,0xaac45ba4,0xd54e8c30,0xaa521179,0x492479de, + 0x87e0d80b,0x1801a57e }, + { 0xfcafffb0,0x073d3f8d,0xae255240,0x6cf33c0b,0x5b5fdfbc,0x781d763b, + 0x1ead1064,0x9f8fc11e } }, + /* 205 */ + { { 0x5e69544c,0x1583a171,0xf04b7813,0x0eaf8567,0x278a4c32,0x1e22a8fd, + 0x3d3a69a9,0xa9d3809d }, + { 0x59a2da3b,0x936c2c2c,0x1895c847,0x38ccbcf6,0x63d50869,0x5e65244e, + 0xe1178ef7,0x3006b9ae } }, + /* 206 */ + { { 0xc9eead28,0x0bb1f2b0,0x89f4dfbc,0x7eef635d,0xb2ce8939,0x074757fd, + 0x45f8f761,0x0ab85fd7 }, + { 0x3e5b4549,0xecda7c93,0x97922f21,0x4be2bb5c,0xb43b8040,0x261a1274, + 0x11e942c2,0xb122d675 } }, + /* 207 */ + { { 0x66a5ae7a,0x3be607be,0x76adcbe3,0x01e703fa,0x4eb6e5c5,0xaf904301, + 0x097dbaec,0x9f599dc1 }, + { 0x0ff250ed,0x6d75b718,0x349a20dc,0x8eb91574,0x10b227a3,0x425605a4, + 0x8a294b78,0x7d5528e0 } }, + /* 208 */ + { { 0x20c26def,0xf0f58f66,0x582b2d1e,0x025585ea,0x01ce3881,0xfbe7d79b, + 0x303f1730,0x28ccea01 }, + { 0x79644ba5,0xd1dabcd1,0x06fff0b8,0x1fc643e8,0x66b3e17b,0xa60a76fc, + 0xa1d013bf,0xc18baf48 } }, + /* 209 */ + { { 0x5dc4216d,0x34e638c8,0x206142ac,0x00c01067,0x95f5064a,0xd453a171, + 0xb7a9596b,0x9def809d }, + { 0x67ab8d2c,0x41e8642e,0x6237a2b6,0xb4240433,0x64c4218b,0x7d506a6d, + 0x68808ce5,0x0357f8b0 } }, + /* 210 */ + { { 0x4cd2cc88,0x8e9dbe64,0xf0b8f39d,0xcc61c28d,0xcd30a0c8,0x4a309874, + 0x1b489887,0xe4a01add }, + { 0xf57cd8f9,0x2ed1eeac,0xbd594c48,0x1b767d3e,0x7bd2f787,0xa7295c71, + 0xce10cc30,0x466d7d79 } }, + /* 211 */ + { { 0x9dada2c7,0x47d31892,0x8f9aa27d,0x4fa0a6c3,0x820a59e1,0x90e4fd28, + 0x451ead1a,0xc672a522 }, + { 0x5d86b655,0x30607cc8,0xf9ad4af1,0xf0235d3b,0x571172a6,0x99a08680, + 0xf2a67513,0x5e3d64fa } }, + /* 212 */ + { { 0x9b3b4416,0xaa6410c7,0xeab26d99,0xcd8fcf85,0xdb656a74,0x5ebff74a, + 0xeb8e42fc,0x6c8a7a95 }, + { 0xb02a63bd,0x10c60ba7,0x8b8f0047,0x6b2f2303,0x312d90b0,0x8c6c3738, + 0xad82ca91,0x348ae422 } }, + /* 213 */ + { { 0x5ccda2fb,0x7f474663,0x8e0726d2,0x22accaa1,0x492b1f20,0x85adf782, + 0xd9ef2d2e,0xc1074de0 }, + { 0xae9a65b3,0xfcf3ce44,0x05d7151b,0xfd71e4ac,0xce6a9788,0xd4711f50, + 0xc9e54ffc,0xfbadfbdb } }, + /* 214 */ + { { 0x20a99363,0x1713f1cd,0x6cf22775,0xb915658f,0x24d359b2,0x968175cd, + 0x83716fcd,0xb7f976b4 }, + { 0x5d6dbf74,0x5758e24d,0x71c3af36,0x8d23bafd,0x0243dfe3,0x48f47760, + 0xcafcc805,0xf4d41b2e } }, + /* 215 */ + { { 0xfdabd48d,0x51f1cf28,0x32c078a4,0xce81be36,0x117146e9,0x6ace2974, + 0xe0160f10,0x180824ea }, + { 0x66e58358,0x0387698b,0xce6ca358,0x63568752,0x5e41e6c5,0x82380e34, + 0x83cf6d25,0x67e5f639 } }, + /* 216 */ + { { 0xcf4899ef,0xf89ccb8d,0x9ebb44c0,0x949015f0,0xb2598ec9,0x546f9276, + 0x04c11fc6,0x9fef789a }, + { 0x53d2a071,0x6d367ecf,0xa4519b09,0xb10e1a7f,0x611e2eef,0xca6b3fb0, + 0xa99c4e20,0xbc80c181 } }, + /* 217 */ + { { 0xe5eb82e6,0x972536f8,0xf56cb920,0x1a484fc7,0x50b5da5e,0xc78e2171, + 0x9f8cdf10,0x49270e62 }, + { 0xea6b50ad,0x1a39b7bb,0xa2388ffc,0x9a0284c1,0x8107197b,0x5403eb17, + 0x61372f7f,0xd2ee52f9 } }, + /* 218 */ + { { 0x88e0362a,0xd37cd285,0x8fa5d94d,0x442fa8a7,0xa434a526,0xaff836e5, + 0xe5abb733,0xdfb478be }, + { 0x673eede6,0xa91f1ce7,0x2b5b2f04,0xa5390ad4,0x5530da2f,0x5e66f7bf, + 0x08df473a,0xd9a140b4 } }, + /* 219 */ + { { 0x6e8ea498,0x0e0221b5,0x3563ee09,0x62347829,0x335d2ade,0xe06b8391, + 0x623f4b1a,0x760c058d }, + { 0xc198aa79,0x0b89b58c,0xf07aba7f,0xf74890d2,0xfde2556a,0x4e204110, + 0x8f190409,0x7141982d } }, + /* 220 */ + { { 0x4d4b0f45,0x6f0a0e33,0x392a94e1,0xd9280b38,0xb3c61d5e,0x3af324c6, + 0x89d54e47,0x3af9d1ce }, + { 0x20930371,0xfd8f7981,0x21c17097,0xeda2664c,0xdc42309b,0x0e9545dc, + 0x73957dd6,0xb1f815c3 } }, + /* 221 */ + { { 0x89fec44a,0x84faa78e,0x3caa4caf,0xc8c2ae47,0xc1b6a624,0x691c807d, + 0x1543f052,0xa41aed14 }, + { 0x7d5ffe04,0x42435399,0x625b6e20,0x8bacb2df,0x87817775,0x85d660be, + 0x86fb60ef,0xd6e9c1dd } }, + /* 222 */ + { { 0xc6853264,0x3aa2e97e,0xe2304a0b,0x771533b7,0xb8eae9be,0x1b912bb7, + 0xae9bf8c2,0x9c9c6e10 }, + { 0xe030b74c,0xa2309a59,0x6a631e90,0x4ed7494d,0xa49b79f2,0x89f44b23, + 0x40fa61b6,0x566bd596 } }, + /* 223 */ + { { 0xc18061f3,0x066c0118,0x7c83fc70,0x190b25d3,0x27273245,0xf05fc8e0, + 0xf525345e,0xcf2c7390 }, + { 0x10eb30cf,0xa09bceb4,0x0d77703a,0xcfd2ebba,0x150ff255,0xe842c43a, + 0x8aa20979,0x02f51755 } }, + /* 224 */ + { { 0xaddb7d07,0x396ef794,0x24455500,0x0b4fc742,0xc78aa3ce,0xfaff8eac, + 0xe8d4d97d,0x14e9ada5 }, + { 0x2f7079e2,0xdaa480a1,0xe4b0800e,0x45baa3cd,0x7838157d,0x01765e2d, + 0x8e9d9ae8,0xa0ad4fab } }, + /* 225 */ + { { 0x4a653618,0x0bfb7621,0x31eaaa5f,0x1872813c,0x44949d5e,0x1553e737, + 0x6e56ed1e,0xbcd530b8 }, + { 0x32e9c47b,0x169be853,0xb50059ab,0xdc2776fe,0x192bfbb4,0xcdba9761, + 0x6979341d,0x909283cf } }, + /* 226 */ + { { 0x76e81a13,0x67b00324,0x62171239,0x9bee1a99,0xd32e19d6,0x08ed361b, + 0xace1549a,0x35eeb7c9 }, + { 0x7e4e5bdc,0x1280ae5a,0xb6ceec6e,0x2dcd2cd3,0x6e266bc1,0x52e4224c, + 0x448ae864,0x9a8b2cf4 } }, + /* 227 */ + { { 0x09d03b59,0xf6471bf2,0xb65af2ab,0xc90e62a3,0xebd5eec9,0xff7ff168, + 0xd4491379,0x6bdb60f4 }, + { 0x8a55bc30,0xdadafebc,0x10097fe0,0xc79ead16,0x4c1e3bdd,0x42e19741, + 0x94ba08a9,0x01ec3cfd } }, + /* 228 */ + { { 0xdc9485c2,0xba6277eb,0x22fb10c7,0x48cc9a79,0x70a28d8a,0x4f61d60f, + 0x475464f6,0xd1acb1c0 }, + { 0x26f36612,0xd26902b1,0xe0618d8b,0x59c3a44e,0x308357ee,0x4df8a813, + 0x405626c2,0x7dcd079d } }, + /* 229 */ + { { 0xf05a4b48,0x5ce7d4d3,0x37230772,0xadcd2952,0x812a915a,0xd18f7971, + 0x377d19b8,0x0bf53589 }, + { 0x6c68ea73,0x35ecd95a,0x823a584d,0xc7f3bbca,0xf473a723,0x9fb674c6, + 0xe16686fc,0xd28be4d9 } }, + /* 230 */ + { { 0x38fa8e4b,0x5d2b9906,0x893fd8fc,0x559f186e,0x436fb6fc,0x3a6de2aa, + 0x510f88ce,0xd76007aa }, + { 0x523a4988,0x2d10aab6,0x74dd0273,0xb455cf44,0xa3407278,0x7f467082, + 0xb303bb01,0xf2b52f68 } }, + /* 231 */ + { { 0x9835b4ca,0x0d57eafa,0xbb669cbc,0x2d2232fc,0xc6643198,0x8eeeb680, + 0xcc5aed3a,0xd8dbe98e }, + { 0xc5a02709,0xcba9be3f,0xf5ba1fa8,0x30be68e5,0xf10ea852,0xfebd43cd, + 0xee559705,0xe01593a3 } }, + /* 232 */ + { { 0xea75a0a6,0xd3e5af50,0x57858033,0x512226ac,0xd0176406,0x6fe6d50f, + 0xaeb8ef06,0xafec07b1 }, + { 0x80bb0a31,0x7fb99567,0x37309aae,0x6f1af3cc,0x01abf389,0x9153a15a, + 0x6e2dbfdd,0xa71b9354 } }, + /* 233 */ + { { 0x18f593d2,0xbf8e12e0,0xa078122b,0xd1a90428,0x0ba4f2ad,0x150505db, + 0x628523d9,0x53a2005c }, + { 0xe7f2b935,0x07c8b639,0xc182961a,0x2bff975a,0x7518ca2c,0x86bceea7, + 0x3d588e3d,0xbf47d19b } }, + /* 234 */ + { { 0xdd7665d5,0x672967a7,0x2f2f4de5,0x4e303057,0x80d4903f,0x144005ae, + 0x39c9a1b6,0x001c2c7f }, + { 0x69efc6d6,0x143a8014,0x7bc7a724,0xc810bdaa,0xa78150a4,0x5f65670b, + 0x86ffb99b,0xfdadf8e7 } }, + /* 235 */ + { { 0xffc00785,0xfd38cb88,0x3b48eb67,0x77fa7591,0xbf368fbc,0x0454d055, + 0x5aa43c94,0x3a838e4d }, + { 0x3e97bb9a,0x56166329,0x441d94d9,0x9eb93363,0x0adb2a83,0x515591a6, + 0x873e1da3,0x3cdb8257 } }, + /* 236 */ + { { 0x7de77eab,0x137140a9,0x41648109,0xf7e1c50d,0xceb1d0df,0x762dcad2, + 0xf1f57fba,0x5a60cc89 }, + { 0x40d45673,0x80b36382,0x5913c655,0x1b82be19,0xdd64b741,0x057284b8, + 0xdbfd8fc0,0x922ff56f } }, + /* 237 */ + { { 0xc9a129a1,0x1b265dee,0xcc284e04,0xa5b1ce57,0xcebfbe3c,0x04380c46, + 0xf6c5cd62,0x72919a7d }, + { 0x8fb90f9a,0x298f453a,0x88e4031b,0xd719c00b,0x796f1856,0xe32c0e77, + 0x3624089a,0x5e791780 } }, + /* 238 */ + { { 0x7f63cdfb,0x5c16ec55,0xf1cae4fd,0x8e6a3571,0x560597ca,0xfce26bea, + 0xe24c2fab,0x4e0a5371 }, + { 0xa5765357,0x276a40d3,0x0d73a2b4,0x3c89af44,0x41d11a32,0xb8f370ae, + 0xd56604ee,0xf5ff7818 } }, + /* 239 */ + { { 0x1a09df21,0xfbf3e3fe,0xe66e8e47,0x26d5d28e,0x29c89015,0x2096bd0a, + 0x533f5e64,0xe41df0e9 }, + { 0xb3ba9e3f,0x305fda40,0x2604d895,0xf2340ceb,0x7f0367c7,0x0866e192, + 0xac4f155f,0x8edd7d6e } }, + /* 240 */ + { { 0x0bfc8ff3,0xc9a1dc0e,0xe936f42f,0x14efd82b,0xcca381ef,0x67016f7c, + 0xed8aee96,0x1432c1ca }, + { 0x70b23c26,0xec684829,0x0735b273,0xa64fe873,0xeaef0f5a,0xe389f6e5, + 0x5ac8d2c6,0xcaef480b } }, + /* 241 */ + { { 0x75315922,0x5245c978,0x3063cca5,0xd8295171,0xb64ef2cb,0xf3ce60d0, + 0x8efae236,0xd0ba177e }, + { 0xb1b3af60,0x53a9ae8f,0x3d2da20e,0x1a796ae5,0xdf9eef28,0x01d63605, + 0x1c54ae16,0xf31c957c } }, + /* 242 */ + { { 0x49cc4597,0xc0f58d52,0xbae0a028,0xdc5015b0,0x734a814a,0xefc5fc55, + 0x96e17c3a,0x013404cb }, + { 0xc9a824bf,0xb29e2585,0x001eaed7,0xd593185e,0x61ef68ac,0x8d6ee682, + 0x91933e6c,0x6f377c4b } }, + /* 243 */ + { { 0xa8333fd2,0x9f93bad1,0x5a2a95b8,0xa8930202,0xeaf75ace,0x211e5037, + 0xd2d09506,0x6dba3e4e }, + { 0xd04399cd,0xa48ef98c,0xe6b73ade,0x1811c66e,0xc17ecaf3,0x72f60752, + 0x3becf4a7,0xf13cf342 } }, + /* 244 */ + { { 0xa919e2eb,0xceeb9ec0,0xf62c0f68,0x83a9a195,0x7aba2299,0xcfba3bb6, + 0x274bbad3,0xc83fa9a9 }, + { 0x62fa1ce0,0x0d7d1b0b,0x3418efbf,0xe58b60f5,0x52706f04,0xbfa8ef9e, + 0x5d702683,0xb49d70f4 } }, + /* 245 */ + { { 0xfad5513b,0x914c7510,0xb1751e2d,0x05f32eec,0xd9fb9d59,0x6d850418, + 0x0c30f1cf,0x59cfadbb }, + { 0x55cb7fd6,0xe167ac23,0x820426a3,0x249367b8,0x90a78864,0xeaeec58c, + 0x354a4b67,0x5babf362 } }, + /* 246 */ + { { 0xee424865,0x37c981d1,0xf2e5577f,0x8b002878,0xb9e0c058,0x702970f1, + 0x9026c8f0,0x6188c6a7 }, + { 0xd0f244da,0x06f9a19b,0xfb080873,0x1ecced5c,0x9f213637,0x35470f9b, + 0xdf50b9d9,0x993fe475 } }, + /* 247 */ + { { 0x9b2c3609,0x68e31cdf,0x2c46d4ea,0x84eb19c0,0x9a775101,0x7ac9ec1a, + 0x4c80616b,0x81f76466 }, + { 0x75fbe978,0x1d7c2a5a,0xf183b356,0x6743fed3,0x501dd2bf,0x838d1f04, + 0x5fe9060d,0x564a812a } }, + /* 248 */ + { { 0xfa817d1d,0x7a5a64f4,0xbea82e0f,0x55f96844,0xcd57f9aa,0xb5ff5a0f, + 0x00e51d6c,0x226bf3cf }, + { 0x2f2833cf,0xd6d1a9f9,0x4f4f89a8,0x20a0a35a,0x8f3f7f77,0x11536c49, + 0xff257836,0x68779f47 } }, + /* 249 */ + { { 0x73043d08,0x79b0c1c1,0x1fc020fa,0xa5446774,0x9a6d26d0,0xd3767e28, + 0xeb092e0b,0x97bcb0d1 }, + { 0xf32ed3c3,0x2ab6eaa8,0xb281bc48,0xc8a4f151,0xbfa178f3,0x4d1bf4f3, + 0x0a784655,0xa872ffe8 } }, + /* 250 */ + { { 0xa32b2086,0xb1ab7935,0x8160f486,0xe1eb710e,0x3b6ae6be,0x9bd0cd91, + 0xb732a36a,0x02812bfc }, + { 0xcf605318,0xa63fd7ca,0xfdfd6d1d,0x646e5d50,0x2102d619,0xa1d68398, + 0xfe5396af,0x07391cc9 } }, + /* 251 */ + { { 0x8b80d02b,0xc50157f0,0x62877f7f,0x6b8333d1,0x78d542ae,0x7aca1af8, + 0x7e6d2a08,0x355d2adc }, + { 0x287386e1,0xb41f335a,0xf8e43275,0xfd272a94,0xe79989ea,0x286ca2cd, + 0x7c2a3a79,0x3dc2b1e3 } }, + /* 252 */ + { { 0x04581352,0xd689d21c,0x376782be,0x0a00c825,0x9fed701f,0x203bd590, + 0x3ccd846b,0xc4786910 }, + { 0x24c768ed,0x5dba7708,0x6841f657,0x72feea02,0x6accce0e,0x73313ed5, + 0xd5bb4d32,0xccc42968 } }, + /* 253 */ + { { 0x3d7620b9,0x94e50de1,0x5992a56a,0xd89a5c8a,0x675487c9,0xdc007640, + 0xaa4871cf,0xe147eb42 }, + { 0xacf3ae46,0x274ab4ee,0x50350fbe,0xfd4936fb,0x48c840ea,0xdf2afe47, + 0x080e96e3,0x239ac047 } }, + /* 254 */ + { { 0x2bfee8d4,0x481d1f35,0xfa7b0fec,0xce80b5cf,0x2ce9af3c,0x105c4c9e, + 0xf5f7e59d,0xc55fa1a3 }, + { 0x8257c227,0x3186f14e,0x342be00b,0xc5b1653f,0xaa904fb2,0x09afc998, + 0xd4f4b699,0x094cd99c } }, + /* 255 */ + { { 0xd703beba,0x8a981c84,0x32ceb291,0x8631d150,0xe3bd49ec,0xa445f2c9, + 0x42abad33,0xb90a30b6 }, + { 0xb4a5abf9,0xb465404f,0x75db7603,0x004750c3,0xca35d89f,0x6f9a42cc, + 0x1b7924f7,0x019f8b9a } }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_8(sp_point_256* r, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_8(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 coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[8]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_256_point_new_8(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, km); + + err = sp_256_ecc_mulmod_base_8(point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_8(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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_8(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_add_one_8(sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r2, #1\n\t" + "ldr r1, [%[a], #0]\n\t" + "add r1, r2\n\t" + "mov r2, #0\n\t" + "str r1, [%[a], #0]\n\t" + "ldr r1, [%[a], #4]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #4]\n\t" + "ldr r1, [%[a], #8]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #8]\n\t" + "ldr r1, [%[a], #12]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #12]\n\t" + "ldr r1, [%[a], #16]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #16]\n\t" + "ldr r1, [%[a], #20]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #20]\n\t" + "ldr r1, [%[a], #24]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #24]\n\t" + "ldr r1, [%[a], #28]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #28]\n\t" + : + : [a] "r" (a) + : "memory", "r1", "r2" + ); +} + +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; 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_8(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, 8, buf, (int)sizeof(buf)); + if (sp_256_cmp_8(k, p256_order2) < 0) { + sp_256_add_one_8(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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[8]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 inf; +#endif +#endif + sp_point_256* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity; +#endif + int err; + + (void)heap; + + err = sp_256_point_new_8(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + err = sp_256_ecc_gen_k_8(rng, k); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_256_iszero_8(point->x) == 0) || (sp_256_iszero_8(point->y) == 0)) { + 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_8(point, pub); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_256_point_free_8(infinity, 1, heap); +#endif + sp_256_point_free_8(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte array. + * 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<8 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[8]; +#endif + sp_point_256* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 32U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, priv); + sp_256_point_from_ecc_point_8(point, pub); + err = sp_256_ecc_mulmod_8(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_in_place_8(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "add r7, #32\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_256_sub_in_place_8(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* 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. + */ +SP_NOINLINE static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #32\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_256_word_8(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + 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_8(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & 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 WC_INLINE int sp_256_div_8(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[16], t2[9]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[7]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 8); + for (i=7; i>=0; i--) { + r1 = div_256_word_8(t1[8 + i], t1[8 + i - 1], div); + + sp_256_mul_d_8(t2, d, r1); + t1[8 + i] += sp_256_sub_in_place_8(&t1[i], t2); + t1[8 + i] -= t2[8]; + sp_256_mask_8(t2, d, t1[8 + i]); + t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2); + sp_256_mask_8(t2, d, t1[8 + i]); + t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2); + } + + r1 = sp_256_cmp_8(t1, d) >= 0; + sp_256_cond_sub_8(r, t1, d, (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 WC_INLINE int sp_256_mod_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_256_div_8(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_minus_2[8] = { + 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU,0xffffffffU,0xffffffffU, + 0x00000000U,0xffffffffU +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint32_t p256_order_low[4] = { + 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU +}; +#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_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_256_mul_8(r, a, b); + sp_256_mont_reduce_order_8(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_8(sp_digit* r, const sp_digit* a) +{ + sp_256_sqr_8(r, a); + sp_256_mont_reduce_order_8(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_8(sp_digit* r, const sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_8(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_8(t, t); + if ((p256_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 8U); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 8; + sp_digit* t3 = td + 4 * 8; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_8(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_8(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_8(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_8(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_8(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_8(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_8(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_8(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_8(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_8(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_8(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_8(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_8(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_8(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t2, t2, a); + } + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t2, t2, a); + } + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t2, t2, a); + } + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t2, t2, a); + } + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_8(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#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, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit ed[2*8]; + sp_digit xd[2*8]; + sp_digit kd[2*8]; + sp_digit rd[2*8]; + sp_digit td[3 * 2*8]; + sp_point_256 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_256* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int32_t c; + int i; + + (void)heap; + + err = sp_256_point_new_8(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 8; + x = d + 2 * 8; + k = d + 4 * 8; + r = d + 6 * 8; + tmp = d + 8 * 8; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(e, 8, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 8, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_8(rng, k); + } + else { + sp_256_from_mp(k, 8, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 8U); + sp_256_norm_8(r); + c = sp_256_cmp_8(r, p256_order); + sp_256_cond_sub_8(r, r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(r); + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(k, k, p256_norm_order); + err = sp_256_mod_8(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(k); + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_8(kInv, k, tmp); + sp_256_norm_8(kInv); + + /* s = r * x + e */ + sp_256_mul_8(x, x, r); + err = sp_256_mod_8(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(x); + carry = sp_256_add_8(s, e, x); + sp_256_cond_sub_8(s, s, p256_order, 0 - carry); + sp_256_norm_8(s); + c = sp_256_cmp_8(s, p256_order); + sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(s, s, kInv); + sp_256_norm_8(s); + + /* Check that signature is usable. */ + if (sp_256_iszero_8(s) == 0) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 8); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U); +#endif + sp_256_point_free_8(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit u1d[2*8]; + sp_digit u2d[2*8]; + sp_digit sd[2*8]; + sp_digit tmpd[2*8 * 5]; + sp_point_256 p1d; + sp_point_256 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p1; + sp_point_256* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + + err = sp_256_point_new_8(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 8; + u2 = d + 2 * 8; + s = d + 4 * 8; + tmp = d + 6 * 8; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 8, hash, (int)hashLen); + sp_256_from_mp(u2, 8, r); + sp_256_from_mp(s, 8, sm); + sp_256_from_mp(p2->x, 8, pX); + sp_256_from_mp(p2->y, 8, pY); + sp_256_from_mp(p2->z, 8, pZ); + + { + sp_256_mul_8(s, s, p256_norm_order); + } + err = sp_256_mod_8(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(s); + { + sp_256_mont_inv_order_8(s, s, tmp); + sp_256_mont_mul_order_8(u1, u1, s); + sp_256_mont_mul_order_8(u2, u2, s); + } + + err = sp_256_ecc_mulmod_base_8(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + { + sp_256_proj_point_add_8(p1, p1, p2, tmp); + if (sp_256_iszero_8(p1->z)) { + if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) { + sp_256_proj_point_dbl_8(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + } + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 8, r); + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 8, r); + carry = sp_256_add_8(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_8(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_256_point_free_8(p1, 0, heap); + sp_256_point_free_8(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*8]; + sp_digit t2d[2*8]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 8; + t2 = d + 2 * 8; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_256_sqr_8(t1, point->y); + (void)sp_256_mod_8(t1, t1, p256_mod); + sp_256_sqr_8(t2, point->x); + (void)sp_256_mod_8(t2, t2, p256_mod); + sp_256_mul_8(t2, t2, point->x); + (void)sp_256_mod_8(t2, t2, p256_mod); + (void)sp_256_sub_8(t2, p256_mod, t2); + sp_256_mont_add_8(t1, t1, t2, p256_mod); + + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_8(t1, p256_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 pubd; +#endif + sp_point_256* pub; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_8(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 8, pX); + sp_256_from_mp(pub->y, 8, pY); + sp_256_from_bin(pub->z, 8, one, (int)sizeof(one)); + + err = sp_256_ecc_is_point_8(pub, NULL); + } + + sp_256_point_free_8(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[8]; + sp_point_256 pubd; + sp_point_256 pd; +#endif + sp_digit* priv = NULL; + sp_point_256* pub; + sp_point_256* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_8(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_256_from_mp(pub->x, 8, pX); + sp_256_from_mp(pub->y, 8, pY); + sp_256_from_bin(pub->z, 8, one, (int)sizeof(one)); + sp_256_from_mp(priv, 8, privm); + + /* Check point at infinitiy. */ + if ((sp_256_iszero_8(pub->x) != 0) && + (sp_256_iszero_8(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_8(pub->x, p256_mod) >= 0 || + sp_256_cmp_8(pub->y, p256_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_8(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_256_iszero_8(p->x) == 0) || + (sp_256_iszero_8(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_256_ecc_mulmod_base_8(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_8(p->x, pub->x) != 0 || + sp_256_cmp_8(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, heap); + sp_256_point_free_8(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 8 * 5]; + sp_point_256 pd; + sp_point_256 qd; +#endif + sp_digit* tmp; + sp_point_256* p; + sp_point_256* q = NULL; + int err; + + err = sp_256_point_new_8(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_256_point_new_8(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + sp_256_from_mp(q->x, 8, qX); + sp_256_from_mp(q->y, 8, qY); + sp_256_from_mp(q->z, 8, qZ); + + sp_256_proj_point_add_8(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(q, 0, NULL); + sp_256_point_free_8(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 8 * 2]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_8(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + + sp_256_proj_point_dbl_8(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 8 * 4]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_8(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + + sp_256_map_8(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_8(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 8]; + sp_digit t2d[2 * 8]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 8; + t2 = d + 2 * 8; +#else + t1 = t1d; + t2 = t2d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_8(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_8(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_8(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_8(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_8(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_8(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_8(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_8(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 8]; + sp_digit yd[2 * 8]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 8; + y = d + 2 * 8; +#else + x = xd; + y = yd; +#endif + + sp_256_from_mp(x, 8, xm); + err = sp_256_mod_mul_norm_8(x, x, p256_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_8(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_sub_8(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_8(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_8(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_8(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 8, 0, 8U * sizeof(sp_digit)); + sp_256_mont_reduce_8(y, p256_mod, p256_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_256_mont_sub_8(y, p256_mod, y, p256_mod); + } + + err = sp_256_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#ifdef WOLFSSL_SP_384 + +/* Point structure to use. */ +typedef struct sp_point_384 { + sp_digit x[2 * 12]; + sp_digit y[2 * 12]; + sp_digit z[2 * 12]; + int infinity; +} sp_point_384; + +/* The modulus (prime) of the curve P384. */ +static const sp_digit p384_mod[12] = { + 0xffffffff,0x00000000,0x00000000,0xffffffff,0xfffffffe,0xffffffff, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +}; +/* The Montogmery normalizer for modulus of the curve P384. */ +static const sp_digit p384_norm_mod[12] = { + 0x00000001,0xffffffff,0xffffffff,0x00000000,0x00000001,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 +}; +/* The Montogmery multiplier for modulus of the curve P384. */ +static sp_digit p384_mp_mod = 0x00000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P384. */ +static const sp_digit p384_order[12] = { + 0xccc52973,0xecec196a,0x48b0a77a,0x581a0db2,0xf4372ddf,0xc7634d81, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +}; +#endif +/* The order of the curve P384 minus 2. */ +static const sp_digit p384_order2[12] = { + 0xccc52971,0xecec196a,0x48b0a77a,0x581a0db2,0xf4372ddf,0xc7634d81, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P384. */ +static const sp_digit p384_norm_order[12] = { + 0x333ad68d,0x1313e695,0xb74f5885,0xa7e5f24d,0x0bc8d220,0x389cb27e, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P384. */ +static sp_digit p384_mp_order = 0xe88fdc45; +#endif +/* The base point of curve P384. */ +static const sp_point_384 p384_base = { + /* X ordinate */ + { + 0x72760ab7,0x3a545e38,0xbf55296c,0x5502f25d,0x82542a38,0x59f741e0, + 0x8ba79b98,0x6e1d3b62,0xf320ad74,0x8eb1c71e,0xbe8b0537,0xaa87ca22, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x90ea0e5f,0x7a431d7c,0x1d7e819d,0x0a60b1ce,0xb5f0b8c0,0xe9da3113, + 0x289a147c,0xf8f41dbd,0x9292dc29,0x5d9e98bf,0x96262c6f,0x3617de4a, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p384_b[12] = { + 0xd3ec2aef,0x2a85c8ed,0x8a2ed19d,0xc656398d,0x5013875a,0x0314088f, + 0xfe814112,0x181d9c6e,0xe3f82d19,0x988e056b,0xe23ee7e4,0xb3312fa7 +}; +#endif + +static int sp_384_point_new_ex_12(void* heap, sp_point_384* sp, sp_point_384** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), &(sp), &(p)) +#endif + + +static void sp_384_point_free_12(sp_point_384* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* t; +#else + int64_t t[12]; +#endif + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + (uint64_t)a[0] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[8] + (uint64_t)a[10] + (uint64_t)a[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[9] + (uint64_t)a[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + (uint64_t)a[0] - (uint64_t)a[2] + (uint64_t)a[3] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[10] - (uint64_t)a[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[3] + (uint64_t)a[4] + (uint64_t)a[8] + 2 * (uint64_t)a[9] + (uint64_t)a[10] - 2 * (uint64_t)a[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[4] + (uint64_t)a[5] + (uint64_t)a[9] + 2 * (uint64_t)a[10] + (uint64_t)a[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + (uint64_t)a[2] + (uint64_t)a[3] - (uint64_t)a[5] + (uint64_t)a[6] + (uint64_t)a[10] + 2 * (uint64_t)a[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + (uint64_t)a[3] + (uint64_t)a[4] - (uint64_t)a[6] + (uint64_t)a[7] + (uint64_t)a[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + (uint64_t)a[4] + (uint64_t)a[5] - (uint64_t)a[7] + (uint64_t)a[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + (uint64_t)a[5] + (uint64_t)a[6] - (uint64_t)a[8] + (uint64_t)a[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + (uint64_t)a[6] + (uint64_t)a[7] - (uint64_t)a[9] + (uint64_t)a[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + (uint64_t)a[7] + (uint64_t)a[8] - (uint64_t)a[10] + (uint64_t)a[11]; + + 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + + r[0] = t[0]; + r[1] = t[1]; + r[2] = t[2]; + r[3] = t[3]; + r[4] = t[4]; + r[5] = t[5]; + r[6] = t[6]; + r[7] = t[7]; + r[8] = t[8]; + r[9] = t[9]; + r[10] = t[10]; + r[11] = t[11]; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_12(sp_point_384* p, const 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_384_from_mp(p->x, 12, pm->x); + sp_384_from_mp(p->y, 12, pm->y); + sp_384_from_mp(p->z, 12, 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_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 12); + r->used = 12; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 12; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 12; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_384_mul_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[12 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #48\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #44\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #88\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* 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. + */ +SP_NOINLINE static sp_digit sp_384_cond_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #48\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +#define sp_384_mont_reduce_order_12 sp_384_mont_reduce_12 + +/* Reduce the number back to 384 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_384_mont_reduce_12(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #44\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+11] += m[11] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[11] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[11] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #48\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_384_cond_sub_12(a - 12, 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_384_mont_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_384_mul_12(r, a, b); + sp_384_mont_reduce_12(r, m, mp); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #96\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #44\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #48\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #88\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #92\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #96\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* 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_384_mont_sqr_12(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_384_sqr_12(r, a); + sp_384_mont_reduce_12(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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_384_mont_sqr_n_12(sp_digit* r, const sp_digit* a, int n, + const sp_digit* m, sp_digit mp) +{ + sp_384_mont_sqr_12(r, a, m, mp); + for (; n > 1; n--) { + sp_384_mont_sqr_12(r, r, m, mp); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P384 curve. */ +static const uint32_t p384_mod_minus_2[12] = { + 0xfffffffdU,0x00000000U,0x00000000U,0xffffffffU,0xfffffffeU,0xffffffffU, + 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P384 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_384_mont_inv_12(sp_digit* r, const sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 12); + for (i=382; i>=0; i--) { + sp_384_mont_sqr_12(t, t, p384_mod, p384_mp_mod); + if (p384_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_384_mont_mul_12(t, t, a, p384_mod, p384_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 12); +#else + sp_digit* t1 = td; + sp_digit* t2 = td + 2 * 12; + sp_digit* t3 = td + 4 * 12; + sp_digit* t4 = td + 6 * 12; + sp_digit* t5 = td + 8 * 12; + + /* 0x2 */ + sp_384_mont_sqr_12(t1, a, p384_mod, p384_mp_mod); + /* 0x3 */ + sp_384_mont_mul_12(t5, t1, a, p384_mod, p384_mp_mod); + /* 0xc */ + sp_384_mont_sqr_n_12(t1, t5, 2, p384_mod, p384_mp_mod); + /* 0xf */ + sp_384_mont_mul_12(t2, t5, t1, p384_mod, p384_mp_mod); + /* 0x1e */ + sp_384_mont_sqr_12(t1, t2, p384_mod, p384_mp_mod); + /* 0x1f */ + sp_384_mont_mul_12(t4, t1, a, p384_mod, p384_mp_mod); + /* 0x3e0 */ + sp_384_mont_sqr_n_12(t1, t4, 5, p384_mod, p384_mp_mod); + /* 0x3ff */ + sp_384_mont_mul_12(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0x7fe0 */ + sp_384_mont_sqr_n_12(t1, t2, 5, p384_mod, p384_mp_mod); + /* 0x7fff */ + sp_384_mont_mul_12(t4, t4, t1, p384_mod, p384_mp_mod); + /* 0x3fff8000 */ + sp_384_mont_sqr_n_12(t1, t4, 15, p384_mod, p384_mp_mod); + /* 0x3fffffff */ + sp_384_mont_mul_12(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffc */ + sp_384_mont_sqr_n_12(t3, t2, 2, p384_mod, p384_mp_mod); + /* 0xfffffffd */ + sp_384_mont_mul_12(r, t3, a, p384_mod, p384_mp_mod); + /* 0xffffffff */ + sp_384_mont_mul_12(t3, t5, t3, p384_mod, p384_mp_mod); + /* 0xfffffffc0000000 */ + sp_384_mont_sqr_n_12(t1, t2, 30, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff */ + sp_384_mont_mul_12(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_12(t1, t2, 60, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_12(t1, t2, 120, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_12(t1, t2, 15, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */ + sp_384_mont_sqr_n_12(t1, t2, 33, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */ + sp_384_mont_mul_12(t2, t3, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_12(t1, t2, 96, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */ + sp_384_mont_mul_12(r, r, t1, p384_mod, p384_mp_mod); + +#endif /* WOLFSSL_SP_SMALL */ +} + +/* 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. + */ +SP_NOINLINE static int32_t sp_384_cmp_12(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #44\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Normalize the values in each word to 32. + * + * a Array of sp_digit to normalize. + */ +#define sp_384_norm_12(a) + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*12; + int32_t n; + + sp_384_mont_inv_12(t1, p->z, t + 2*12); + + sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod); + + /* x /= z^2 */ + sp_384_mont_mul_12(r->x, p->x, t2, p384_mod, p384_mp_mod); + XMEMSET(r->x + 12, 0, sizeof(r->x) / 2U); + sp_384_mont_reduce_12(r->x, p384_mod, p384_mp_mod); + /* Reduce x to less than modulus */ + n = sp_384_cmp_12(r->x, p384_mod); + sp_384_cond_sub_12(r->x, r->x, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_12(r->x); + + /* y /= z^3 */ + sp_384_mont_mul_12(r->y, p->y, t1, p384_mod, p384_mp_mod); + XMEMSET(r->y + 12, 0, sizeof(r->y) / 2U); + sp_384_mont_reduce_12(r->y, p384_mod, p384_mp_mod); + /* Reduce y to less than modulus */ + n = sp_384_cmp_12(r->y, p384_mod); + sp_384_cond_sub_12(r->y, r->y, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_12(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. + */ +SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, #48\n\t" + "sub r7, #1\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +#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). + */ +SP_NOINLINE static void sp_384_mont_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_12(r, a, b); + sp_384_cond_sub_12(r, r, m, 0 - o); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_384_mont_dbl_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_12(r, a, a); + sp_384_cond_sub_12(r, r, m, 0 - o); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_384_mont_tpl_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_12(r, a, a); + sp_384_cond_sub_12(r, r, m, 0 - o); + o = sp_384_add_12(r, r, a); + sp_384_cond_sub_12(r, r, m, 0 - o); +} + +#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. + */ +SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "add r6, #48\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "sbc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_384_cond_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #48\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, #1\n\t" + "add r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "adc r5, r6\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* 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). + */ +SP_NOINLINE static void sp_384_mont_sub_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + sp_digit o; + + o = sp_384_sub_12(r, a, b); + sp_384_cond_add_12(r, r, m, o); +} + +static void sp_384_rshift1_12(sp_digit* r, sp_digit* a) +{ + __asm__ __volatile__ ( + "ldr r2, [%[a]]\n\t" + "ldr r3, [%[a], #4]\n\t" + "lsr r2, r2, #1\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r2, [%[r], #0]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r3, [%[r], #4]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r4, [%[r], #8]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r2, [%[r], #12]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r3, [%[r], #16]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r4, [%[r], #20]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r2, [%[r], #24]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r3, [%[r], #28]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r4, [%[r], #32]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r2, [%[r], #36]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "str r3, [%[r], #40]\n\t" + "str r4, [%[r], #44]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5" + ); +} + +/* 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). + */ +SP_NOINLINE static void sp_384_div2_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_cond_add_12(r, a, m, 0 - (a[0] & 1)); + sp_384_rshift1_12(r, r); + r[11] |= o << 31; +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_dbl_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*12; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_384_mont_sqr_12(t1, p->z, p384_mod, p384_mp_mod); + /* Z = Y * Z */ + sp_384_mont_mul_12(z, p->y, p->z, p384_mod, p384_mp_mod); + /* Z = 2Z */ + sp_384_mont_dbl_12(z, z, p384_mod); + /* T2 = X - T1 */ + sp_384_mont_sub_12(t2, p->x, t1, p384_mod); + /* T1 = X + T1 */ + sp_384_mont_add_12(t1, p->x, t1, p384_mod); + /* T2 = T1 * T2 */ + sp_384_mont_mul_12(t2, t1, t2, p384_mod, p384_mp_mod); + /* T1 = 3T2 */ + sp_384_mont_tpl_12(t1, t2, p384_mod); + /* Y = 2Y */ + sp_384_mont_dbl_12(y, p->y, p384_mod); + /* Y = Y * Y */ + sp_384_mont_sqr_12(y, y, p384_mod, p384_mp_mod); + /* T2 = Y * Y */ + sp_384_mont_sqr_12(t2, y, p384_mod, p384_mp_mod); + /* T2 = T2/2 */ + sp_384_div2_12(t2, t2, p384_mod); + /* Y = Y * X */ + sp_384_mont_mul_12(y, y, p->x, p384_mod, p384_mp_mod); + /* X = T1 * T1 */ + sp_384_mont_sqr_12(x, t1, p384_mod, p384_mp_mod); + /* X = X - Y */ + sp_384_mont_sub_12(x, x, y, p384_mod); + /* X = X - Y */ + sp_384_mont_sub_12(x, x, y, p384_mod); + /* Y = Y - X */ + sp_384_mont_sub_12(y, y, x, p384_mod); + /* Y = Y * T1 */ + sp_384_mont_mul_12(y, y, t1, p384_mod, p384_mp_mod); + /* Y = Y - T2 */ + sp_384_mont_sub_12(y, y, t2, p384_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_384_cmp_equal_12(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]) | (a[10] ^ b[10]) | (a[11] ^ b[11])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, + sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*12; + sp_digit* t3 = t + 4*12; + sp_digit* t4 = t + 6*12; + sp_digit* t5 = t + 8*12; + 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) { + const sp_point_384* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_384_sub_12(t1, p384_mod, q->y); + sp_384_norm_12(t1); + if ((sp_384_cmp_equal_12(p->x, q->x) & sp_384_cmp_equal_12(p->z, q->z) & + (sp_384_cmp_equal_12(p->y, q->y) | sp_384_cmp_equal_12(p->y, t1))) != 0) { + sp_384_proj_point_dbl_12(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<12; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<12; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<12; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_12(t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t3, t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t1, t1, x, p384_mod, p384_mp_mod); + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_12(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_12(t3, t3, y, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_12(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - U1 */ + sp_384_mont_sub_12(t2, t2, t1, p384_mod); + /* R = S2 - S1 */ + sp_384_mont_sub_12(t4, t4, t3, p384_mod); + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_12(z, z, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_12(x, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_12(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(y, t1, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(x, x, t5, p384_mod); + sp_384_mont_dbl_12(t1, y, p384_mod); + sp_384_mont_sub_12(x, x, t1, p384_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_12(y, y, x, p384_mod); + sp_384_mont_mul_12(y, y, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t5, t5, t3, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(y, y, t5, p384_mod); + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td[16]; + sp_point_384 rtd; + sp_digit tmpd[2 * 12 * 6]; +#endif + sp_point_384* t; + sp_point_384* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_384_point_new_12(heap, rtd, rt); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 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 */ + (void)sp_384_mod_mul_norm_12(t[1].x, g->x, p384_mod); + (void)sp_384_mod_mul_norm_12(t[1].y, g->y, p384_mod); + (void)sp_384_mod_mul_norm_12(t[1].z, g->z, p384_mod); + t[1].infinity = 0; + sp_384_proj_point_dbl_12(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_384_proj_point_add_12(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_384_proj_point_dbl_12(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_384_proj_point_add_12(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_384_proj_point_dbl_12(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_384_proj_point_add_12(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_384_proj_point_dbl_12(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_384_proj_point_add_12(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_384_proj_point_dbl_12(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_384_proj_point_add_12(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_384_proj_point_dbl_12(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_384_proj_point_add_12(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_384_proj_point_dbl_12(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_384_proj_point_add_12(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 10; + n = k[i+1] << 0; + c = 28; + y = n >> 28; + XMEMCPY(rt, &t[y], sizeof(sp_point_384)); + n <<= 4; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--]; + c += 32; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_384_proj_point_dbl_12(rt, rt, tmp); + sp_384_proj_point_dbl_12(rt, rt, tmp); + sp_384_proj_point_dbl_12(rt, rt, tmp); + sp_384_proj_point_dbl_12(rt, rt, tmp); + + sp_384_proj_point_add_12(rt, rt, &t[y], tmp); + } + + if (map != 0) { + sp_384_map_12(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 12 * 6); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_384) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_384_point_free_12(rt, 1, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_384 { + sp_digit x[12]; + sp_digit y[12]; +} sp_table_entry_384; + +#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_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*12; + sp_digit* b = t + 4*12; + sp_digit* t1 = t + 6*12; + sp_digit* t2 = t + 8*12; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_384_mont_dbl_12(y, y, p384_mod); + /* W = Z^4 */ + sp_384_mont_sqr_12(w, z, p384_mod, p384_mp_mod); + sp_384_mont_sqr_12(w, w, p384_mod, p384_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_12(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(t1, t1, w, p384_mod); + sp_384_mont_tpl_12(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_12(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_12(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_12(t2, b, p384_mod); + sp_384_mont_sub_12(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_12(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_12(t1, t1, p384_mod, p384_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_384_mont_mul_12(w, w, t1, p384_mod, p384_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_12(y, b, x, p384_mod); + sp_384_mont_mul_12(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_12(y, y, p384_mod); + sp_384_mont_sub_12(y, y, t1, p384_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_12(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(t1, t1, w, p384_mod); + sp_384_mont_tpl_12(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_12(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_12(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_12(t2, b, p384_mod); + sp_384_mont_sub_12(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_12(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_12(t1, t1, p384_mod, p384_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_12(y, b, x, p384_mod); + sp_384_mont_mul_12(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_12(y, y, p384_mod); + sp_384_mont_sub_12(y, y, t1, p384_mod); +#endif + /* Y = Y/2 */ + sp_384_div2_12(y, y, p384_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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_qz1_12(sp_point_384* r, const sp_point_384* p, + const sp_point_384* q, sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*12; + sp_digit* t3 = t + 4*12; + sp_digit* t4 = t + 6*12; + sp_digit* t5 = t + 8*12; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_384_sub_12(t1, p384_mod, q->y); + sp_384_norm_12(t1); + if ((sp_384_cmp_equal_12(p->x, q->x) & sp_384_cmp_equal_12(p->z, q->z) & + (sp_384_cmp_equal_12(p->y, q->y) | sp_384_cmp_equal_12(p->y, t1))) != 0) { + sp_384_proj_point_dbl_12(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<12; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<12; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<12; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_12(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_12(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - X1 */ + sp_384_mont_sub_12(t2, t2, x, p384_mod); + /* R = S2 - Y1 */ + sp_384_mont_sub_12(t4, t4, y, p384_mod); + /* Z3 = H*Z1 */ + sp_384_mont_mul_12(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_384_mont_sqr_12(t1, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_12(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t3, x, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(x, t1, t5, p384_mod); + sp_384_mont_dbl_12(t1, t3, p384_mod); + sp_384_mont_sub_12(x, x, t1, p384_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_384_mont_sub_12(t3, t3, x, p384_mod); + sp_384_mont_mul_12(t3, t3, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t5, t5, y, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(y, t3, t5, p384_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 12; + sp_digit* tmp = t + 4 * 12; + + sp_384_mont_inv_12(t1, a->z, tmp); + + sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod); + + sp_384_mont_mul_12(a->x, a->x, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(a->y, a->y, t1, p384_mod, p384_mp_mod); + XMEMCPY(a->z, p384_norm_mod, sizeof(p384_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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_384_gen_stripe_table_12(const sp_point_384* a, + sp_table_entry_384* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td, s1d, s2d; +#endif + sp_point_384* t; + sp_point_384* s1 = NULL; + sp_point_384* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_384_point_new_12(heap, td, t); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->y, a->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->z, a->z, p384_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_384_proj_to_affine_12(t, tmp); + + XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_384)); + /* 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)); + + for (i=1; i<4; i++) { + sp_384_proj_point_dbl_n_12(t, 96, tmp); + sp_384_proj_to_affine_12(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<4; i++) { + XMEMCPY(s1->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_384_proj_point_add_qz1_12(t, s1, s2, tmp); + sp_384_proj_to_affine_12(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_384_point_free_12(s2, 0, heap); + sp_384_point_free_12(s1, 0, heap); + sp_384_point_free_12( 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 coordinates. + * + * 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_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 rtd; + sp_point_384 pd; + sp_digit td[2 * 12 * 6]; +#endif + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_384_point_new_12(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + y = 0; + for (j=0,x=95; j<4; j++,x+=96) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=94; i>=0; i--) { + y = 0; + for (j=0,x=i; j<4; j++,x+=96) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + + sp_384_proj_point_dbl_12(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 = !y; + sp_384_proj_point_add_qz1_12(rt, rt, p, t); + } + + if (map != 0) { + sp_384_map_12(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, heap); + sp_384_point_free_12(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_384_t { + sp_digit x[12]; + sp_digit y[12]; + sp_table_entry_384 table[16]; + uint32_t cnt; + int set; +} sp_cache_384_t; + +static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_384_last = -1; +static THREAD_LS_T int sp_cache_384_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_384 = 0; + static wolfSSL_Mutex sp_cache_384_lock; +#endif + +static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_384_inited == 0) { + for (i=0; ix, sp_cache_384[i].x) & + sp_384_cmp_equal_12(g->y, sp_cache_384[i].y)) { + sp_cache_384[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_384_last + 1) % FP_ENTRIES; + for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_384[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_384_last) { + least = sp_cache_384[0].cnt; + for (j=1; jx, sizeof(sp_cache_384[i].x)); + XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y)); + sp_cache_384[i].set = 1; + sp_cache_384[i].cnt = 1; + } + + *cache = &sp_cache_384[i]; + sp_cache_384_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_384_ecc_mulmod_fast_12(r, g, k, map, heap); +#else + sp_digit tmp[2 * 12 * 7]; + sp_cache_384_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_384 == 0) { + wc_InitMutex(&sp_cache_384_lock); + initCacheMutex_384 = 1; + } + if (wc_LockMutex(&sp_cache_384_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_384(g, &cache); + if (cache->cnt == 2) + sp_384_gen_stripe_table_12(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_384_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_384_ecc_mulmod_fast_12(r, g, k, map, heap); + } + else { + err = sp_384_ecc_mulmod_stripe_12(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#else +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_384_gen_stripe_table_12(const sp_point_384* a, + sp_table_entry_384* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td, s1d, s2d; +#endif + sp_point_384* t; + sp_point_384* s1 = NULL; + sp_point_384* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_384_point_new_12(heap, td, t); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->y, a->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->z, a->z, p384_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_384_proj_to_affine_12(t, tmp); + + XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_384)); + /* 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)); + + for (i=1; i<8; i++) { + sp_384_proj_point_dbl_n_12(t, 48, tmp); + sp_384_proj_to_affine_12(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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_384_proj_point_add_qz1_12(t, s1, s2, tmp); + sp_384_proj_to_affine_12(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_384_point_free_12(s2, 0, heap); + sp_384_point_free_12(s1, 0, heap); + sp_384_point_free_12( 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 coordinates. + * + * 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_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 rtd; + sp_point_384 pd; + sp_digit td[2 * 12 * 6]; +#endif + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_384_point_new_12(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + y = 0; + for (j=0,x=47; j<8; j++,x+=48) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=46; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=48) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + + sp_384_proj_point_dbl_12(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 = !y; + sp_384_proj_point_add_qz1_12(rt, rt, p, t); + } + + if (map != 0) { + sp_384_map_12(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, heap); + sp_384_point_free_12(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_384_t { + sp_digit x[12]; + sp_digit y[12]; + sp_table_entry_384 table[256]; + uint32_t cnt; + int set; +} sp_cache_384_t; + +static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_384_last = -1; +static THREAD_LS_T int sp_cache_384_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_384 = 0; + static wolfSSL_Mutex sp_cache_384_lock; +#endif + +static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_384_inited == 0) { + for (i=0; ix, sp_cache_384[i].x) & + sp_384_cmp_equal_12(g->y, sp_cache_384[i].y)) { + sp_cache_384[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_384_last + 1) % FP_ENTRIES; + for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_384[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_384_last) { + least = sp_cache_384[0].cnt; + for (j=1; jx, sizeof(sp_cache_384[i].x)); + XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y)); + sp_cache_384[i].set = 1; + sp_cache_384[i].cnt = 1; + } + + *cache = &sp_cache_384[i]; + sp_cache_384_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_384_ecc_mulmod_fast_12(r, g, k, map, heap); +#else + sp_digit tmp[2 * 12 * 7]; + sp_cache_384_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_384 == 0) { + wc_InitMutex(&sp_cache_384_lock); + initCacheMutex_384 = 1; + } + if (wc_LockMutex(&sp_cache_384_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_384(g, &cache); + if (cache->cnt == 2) + sp_384_gen_stripe_table_12(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_384_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_384_ecc_mulmod_fast_12(r, g, k, map, heap); + } + else { + err = sp_384_ecc_mulmod_stripe_12(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[12]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_384_point_new_12(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 12, km); + sp_384_point_from_ecc_point_12(point, gm); + + err = sp_384_ecc_mulmod_12(point, point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_12(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static const sp_table_entry_384 p384_table[16] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x49c0b528,0x3dd07566,0xa0d6ce38,0x20e378e2,0x541b4d6e,0x879c3afc, + 0x59a30eff,0x64548684,0x614ede2b,0x812ff723,0x299e1513,0x4d3aadc2 }, + { 0x4b03a4fe,0x23043dad,0x7bb4a9ac,0xa1bfa8bf,0x2e83b050,0x8bade756, + 0x68f4ffd9,0xc6c35219,0x3969a840,0xdd800226,0x5a15c5e9,0x2b78abc2 } }, + /* 2 */ + { { 0xf26feef9,0x24480c57,0x3a0e1240,0xc31a2694,0x273e2bc7,0x735002c3, + 0x3ef1ed4c,0x8c42e9c5,0x7f4948e8,0x028babf6,0x8a978632,0x6a502f43 }, + { 0xb74536fe,0xf5f13a46,0xd8a9f0eb,0x1d218bab,0x37232768,0x30f36bcc, + 0x576e8c18,0xc5317b31,0x9bbcb766,0xef1d57a6,0xb3e3d4dc,0x917c4930 } }, + /* 3 */ + { { 0xe349ddd0,0x11426e2e,0x9b2fc250,0x9f117ef9,0xec0174a6,0xff36b480, + 0x18458466,0x4f4bde76,0x05806049,0x2f2edb6d,0x19dfca92,0x8adc75d1 }, + { 0xb7d5a7ce,0xa619d097,0xa34411e9,0x874275e5,0x0da4b4ef,0x5403e047, + 0x77901d8f,0x2ebaafd9,0xa747170f,0x5e63ebce,0x7f9d8036,0x12a36944 } }, + /* 4 */ + { { 0x2f9fbe67,0x378205de,0x7f728e44,0xc4afcb83,0x682e00f1,0xdbcec06c, + 0x114d5423,0xf2a145c3,0x7a52463e,0xa01d9874,0x7d717b0a,0xfc0935b1 }, + { 0xd4d01f95,0x9653bc4f,0x9560ad34,0x9aa83ea8,0xaf8e3f3f,0xf77943dc, + 0xe86fe16e,0x70774a10,0xbf9ffdcf,0x6b62e6f1,0x588745c9,0x8a72f39e } }, + /* 5 */ + { { 0x2341c342,0x73ade4da,0xea704422,0xdd326e54,0x3741cef3,0x336c7d98, + 0x59e61549,0x1eafa00d,0xbd9a3efd,0xcd3ed892,0xc5c6c7e4,0x03faf26c }, + { 0x3045f8ac,0x087e2fcf,0x174f1e73,0x14a65532,0xfe0af9a7,0x2cf84f28, + 0x2cdc935b,0xddfd7a84,0x6929c895,0x4c0f117b,0x4c8bcfcc,0x356572d6 } }, + /* 6 */ + { { 0x3f3b236f,0xfab08607,0x81e221da,0x19e9d41d,0x3927b428,0xf3f6571e, + 0x7550f1f6,0x4348a933,0xa85e62f0,0x7167b996,0x7f5452bf,0x62d43759 }, + { 0xf2955926,0xd85feb9e,0x6df78353,0x440a561f,0x9ca36b59,0x389668ec, + 0xa22da016,0x052bf1a1,0xf6093254,0xbdfbff72,0xe22209f3,0x94e50f28 } }, + /* 7 */ + { { 0x3062e8af,0x90b2e5b3,0xe8a3d369,0xa8572375,0x201db7b1,0x3fe1b00b, + 0xee651aa2,0xe926def0,0xb9b10ad7,0x6542c9be,0xa2fcbe74,0x098e309b }, + { 0xfff1d63f,0x779deeb3,0x20bfd374,0x23d0e80a,0x8768f797,0x8452bb3b, + 0x1f952856,0xcf75bb4d,0x29ea3faa,0x8fe6b400,0x81373a53,0x12bd3e40 } }, + /* 8 */ + { { 0x16973cf4,0x070d34e1,0x7e4f34f7,0x20aee08b,0x5eb8ad29,0x269af9b9, + 0xa6a45dda,0xdde0a036,0x63df41e0,0xa18b528e,0xa260df2a,0x03cc71b2 }, + { 0xa06b1dd7,0x24a6770a,0x9d2675d3,0x5bfa9c11,0x96844432,0x73c1e2a1, + 0x131a6cf0,0x3660558d,0x2ee79454,0xb0289c83,0xc6d8ddcd,0xa6aefb01 } }, + /* 9 */ + { { 0x01ab5245,0xba1464b4,0xc48d93ff,0x9b8d0b6d,0x93ad272c,0x939867dc, + 0xae9fdc77,0xbebe085e,0x894ea8bd,0x73ae5103,0x39ac22e1,0x740fc89a }, + { 0x28e23b23,0x5e28b0a3,0xe13104d0,0x2352722e,0xb0a2640d,0xf4667a18, + 0x49bb37c3,0xac74a72e,0xe81e183a,0x79f734f0,0x3fd9c0eb,0xbffe5b6c } }, + /* 10 */ + { { 0x00623f3b,0x03cf2922,0x5f29ebff,0x095c7111,0x80aa6823,0x42d72247, + 0x7458c0b0,0x044c7ba1,0x0959ec20,0xca62f7ef,0xf8ca929f,0x40ae2ab7 }, + { 0xa927b102,0xb8c5377a,0xdc031771,0x398a86a0,0xc216a406,0x04908f9d, + 0x918d3300,0xb423a73a,0xe0b94739,0x634b0ff1,0x2d69f697,0xe29de725 } }, + /* 11 */ + { { 0x8435af04,0x744d1400,0xfec192da,0x5f255b1d,0x336dc542,0x1f17dc12, + 0x636a68a8,0x5c90c2a7,0x7704ca1e,0x960c9eb7,0x6fb3d65a,0x9de8cf1e }, + { 0x511d3d06,0xc60fee0d,0xf9eb52c7,0x466e2313,0x206b0914,0x743c0f5f, + 0x2191aa4d,0x42f55bac,0xffebdbc2,0xcefc7c8f,0xe6e8ed1c,0xd4fa6081 } }, + /* 12 */ + { { 0x98683186,0x867db639,0xddcc4ea9,0xfb5cf424,0xd4f0e7bd,0xcc9a7ffe, + 0x7a779f7e,0x7c57f71c,0xd6b25ef2,0x90774079,0xb4081680,0x90eae903 }, + { 0x0ee1fceb,0xdf2aae5e,0xe86c1a1f,0x3ff1da24,0xca193edf,0x80f587d6, + 0xdc9b9d6a,0xa5695523,0x85920303,0x7b840900,0xba6dbdef,0x1efa4dfc } }, + /* 13 */ + { { 0xe0540015,0xfbd838f9,0xc39077dc,0x2c323946,0xad619124,0x8b1fb9e6, + 0x0ca62ea8,0x9612440c,0x2dbe00ff,0x9ad9b52c,0xae197643,0xf52abaa1 }, + { 0x2cac32ad,0xd0e89894,0x62a98f91,0xdfb79e42,0x276f55cb,0x65452ecf, + 0x7ad23e12,0xdb1ac0d2,0xde4986f0,0xf68c5f6a,0x82ce327d,0x389ac37b } }, + /* 14 */ + { { 0xb8a9e8c9,0xcd96866d,0x5bb8091e,0xa11963b8,0x045b3cd2,0xc7f90d53, + 0x80f36504,0x755a72b5,0x21d3751c,0x46f8b399,0x53c193de,0x4bffdc91 }, + { 0xb89554e7,0xcd15c049,0xf7a26be6,0x353c6754,0xbd41d970,0x79602370, + 0x12b176c0,0xde16470b,0x40c8809d,0x56ba1175,0xe435fb1e,0xe2db35c3 } }, + /* 15 */ + { { 0x6328e33f,0xd71e4aab,0xaf8136d1,0x5486782b,0x86d57231,0x07a4995f, + 0x1651a968,0xf1f0a5bd,0x76803b6d,0xa5dc5b24,0x42dda935,0x5c587cbc }, + { 0xbae8b4c0,0x2b6cdb32,0xb1331138,0x66d1598b,0x5d7e9614,0x4a23b2d2, + 0x74a8c05d,0x93e402a6,0xda7ce82e,0x45ac94e6,0xe463d465,0xeb9f8281 } }, +}; + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + return sp_384_ecc_mulmod_stripe_12(r, &p384_base, p384_table, + k, map, heap); +} + +#else +static const sp_table_entry_384 p384_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x49c0b528,0x3dd07566,0xa0d6ce38,0x20e378e2,0x541b4d6e,0x879c3afc, + 0x59a30eff,0x64548684,0x614ede2b,0x812ff723,0x299e1513,0x4d3aadc2 }, + { 0x4b03a4fe,0x23043dad,0x7bb4a9ac,0xa1bfa8bf,0x2e83b050,0x8bade756, + 0x68f4ffd9,0xc6c35219,0x3969a840,0xdd800226,0x5a15c5e9,0x2b78abc2 } }, + /* 2 */ + { { 0x2b0c535b,0x29864753,0x70506296,0x90dd6953,0x216ab9ac,0x038cd6b4, + 0xbe12d76a,0x3df9b7b7,0x5f347bdb,0x13f4d978,0x13e94489,0x222c5c9c }, + { 0x2680dc64,0x5f8e796f,0x58352417,0x120e7cb7,0xd10740b8,0x254b5d8a, + 0x5337dee6,0xc38b8efb,0x94f02247,0xf688c2e1,0x6c25bc4c,0x7b5c75f3 } }, + /* 3 */ + { { 0x9edffea5,0xe26a3cc3,0x37d7e9fc,0x35bbfd1c,0x9bde3ef6,0xf0e7700d, + 0x1a538f5a,0x0380eb47,0x05bf9eb3,0x2e9da8bb,0x1a460c3e,0xdbb93c73 }, + { 0xf526b605,0x37dba260,0xfd785537,0x95d4978e,0xed72a04a,0x24ed793a, + 0x76005b1a,0x26948377,0x9e681f82,0x99f557b9,0xd64954ef,0xae5f9557 } }, + /* 4 */ + { { 0xf26feef9,0x24480c57,0x3a0e1240,0xc31a2694,0x273e2bc7,0x735002c3, + 0x3ef1ed4c,0x8c42e9c5,0x7f4948e8,0x028babf6,0x8a978632,0x6a502f43 }, + { 0xb74536fe,0xf5f13a46,0xd8a9f0eb,0x1d218bab,0x37232768,0x30f36bcc, + 0x576e8c18,0xc5317b31,0x9bbcb766,0xef1d57a6,0xb3e3d4dc,0x917c4930 } }, + /* 5 */ + { { 0xe349ddd0,0x11426e2e,0x9b2fc250,0x9f117ef9,0xec0174a6,0xff36b480, + 0x18458466,0x4f4bde76,0x05806049,0x2f2edb6d,0x19dfca92,0x8adc75d1 }, + { 0xb7d5a7ce,0xa619d097,0xa34411e9,0x874275e5,0x0da4b4ef,0x5403e047, + 0x77901d8f,0x2ebaafd9,0xa747170f,0x5e63ebce,0x7f9d8036,0x12a36944 } }, + /* 6 */ + { { 0x4fc52870,0x28f9c07a,0x1a53a961,0xce0b3748,0x0e1828d9,0xd550fa18, + 0x6adb225a,0xa24abaf7,0x6e58a348,0xd11ed0a5,0x948acb62,0xf3d811e6 }, + { 0x4c61ed22,0x8618dd77,0x80b47c9d,0x0bb747f9,0xde6b8559,0x22bf796f, + 0x680a21e9,0xfdfd1c6d,0x2af2c9dd,0xc0db1577,0xc1e90f3d,0xa09379e6 } }, + /* 7 */ + { { 0xe085c629,0x386c66ef,0x095bc89a,0x5fc2a461,0x203f4b41,0x1353d631, + 0x7e4bd8f5,0x7ca1972b,0xa7df8ce9,0xb077380a,0xee7e4ea3,0xd8a90389 }, + { 0xe7b14461,0x1bc74dc7,0x0c9c4f78,0xdc2cb014,0x84ef0a10,0x52b4b3a6, + 0x20327fe2,0xbde6ea5d,0x660f9615,0xb71ec435,0xb8ad8173,0xeede5a04 } }, + /* 8 */ + { { 0x893b9a2d,0x5584cbb3,0x00850c5d,0x820c660b,0x7df2d43d,0x4126d826, + 0x0109e801,0xdd5bbbf0,0x38172f1c,0x85b92ee3,0xf31430d9,0x609d4f93 }, + { 0xeadaf9d6,0x1e059a07,0x0f125fb0,0x70e6536c,0x560f20e7,0xd6220751, + 0x7aaf3a9a,0xa59489ae,0x64bae14e,0x7b70e2f6,0x76d08249,0x0dd03701 } }, + /* 9 */ + { { 0x8510521f,0x4cc13be8,0xf724cc17,0x87315ba9,0x353dc263,0xb49d83bb, + 0x0c279257,0x8b677efe,0xc93c9537,0x510a1c1c,0xa4702c99,0x33e30cd8 }, + { 0x2208353f,0xf0ffc89d,0xced42b2b,0x0170fa8d,0x26e2a5f5,0x090851ed, + 0xecb52c96,0x81276455,0x7fe1adf4,0x0646c4e1,0xb0868eab,0x513f047e } }, + /* 10 */ + { { 0xdf5bdf53,0xc07611f4,0x58b11a6d,0x45d331a7,0x1c4ee394,0x58965daf, + 0x5a5878d1,0xba8bebe7,0x82dd3025,0xaecc0a18,0xa923eb8b,0xcf2a3899 }, + { 0xd24fd048,0xf98c9281,0x8bbb025d,0x841bfb59,0xc9ab9d53,0xb8ddf8ce, + 0x7fef044e,0x538a4cb6,0x23236662,0x092ac21f,0x0b66f065,0xa919d385 } }, + /* 11 */ + { { 0x85d480d8,0x3db03b40,0x1b287a7d,0x8cd9f479,0x4a8f3bae,0x8f24dc75, + 0x3db41892,0x482eb800,0x9c56e0f5,0x38bf9eb3,0x9a91dc6f,0x8b977320 }, + { 0x7209cfc2,0xa31b05b2,0x05b2db70,0x4c49bf85,0xd619527b,0x56462498, + 0x1fac51ba,0x3fe51039,0xab4b8342,0xfb04f55e,0x04c6eabf,0xc07c10dc } }, + /* 12 */ + { { 0xdb32f048,0xad22fe4c,0x475ed6df,0x5f23bf91,0xaa66b6cb,0xa50ce0c0, + 0xf03405c0,0xdf627a89,0xf95e2d6a,0x3674837d,0xba42e64e,0x081c95b6 }, + { 0xe71d6ceb,0xeba3e036,0x6c6b0271,0xb45bcccf,0x0684701d,0x67b47e63, + 0xe712523f,0x60f8f942,0x5cd47adc,0x82423472,0x87649cbb,0x83027d79 } }, + /* 13 */ + { { 0x3615b0b8,0xb3929ea6,0xa54dac41,0xb41441fd,0xb5b6a368,0x8995d556, + 0x167ef05e,0xa80d4529,0x6d25a27f,0xf6bcb4a1,0x7bd55b68,0x210d6a4c }, + { 0x25351130,0xf3804abb,0x903e37eb,0x1d2df699,0x084c25c8,0x5f201efc, + 0xa1c68e91,0x31a28c87,0x563f62a5,0x81dad253,0xd6c415d4,0x5dd6de70 } }, + /* 14 */ + { { 0x846612ce,0x29f470fd,0xda18d997,0x986f3eec,0x2f34af86,0x6b84c161, + 0x46ddaf8b,0x5ef0a408,0xe49e795f,0x14405a00,0xaa2f7a37,0x5f491b16 }, + { 0xdb41b38d,0xc7f07ae4,0x18fbfcaa,0xef7d119e,0x14443b19,0x3a18e076, + 0x79a19926,0x4356841a,0xe2226fbe,0x91f4a91c,0x3cc88721,0xdc77248c } }, + /* 15 */ + { { 0xe4b1ec9d,0xd570ff1a,0xe7eef706,0x21d23e0e,0xca19e086,0x3cde40f4, + 0xcd4bb270,0x7d6523c4,0xbf13aa6c,0x16c1f06c,0xd14c4b60,0x5aa7245a }, + { 0x44b74de8,0x37f81467,0x620a934e,0x839e7a17,0xde8b1aa1,0xf74d14e8, + 0xf30d75e2,0x8789fa51,0xc81c261e,0x09b24052,0x33c565ee,0x654e2678 } }, + /* 16 */ + { { 0x2f9fbe67,0x378205de,0x7f728e44,0xc4afcb83,0x682e00f1,0xdbcec06c, + 0x114d5423,0xf2a145c3,0x7a52463e,0xa01d9874,0x7d717b0a,0xfc0935b1 }, + { 0xd4d01f95,0x9653bc4f,0x9560ad34,0x9aa83ea8,0xaf8e3f3f,0xf77943dc, + 0xe86fe16e,0x70774a10,0xbf9ffdcf,0x6b62e6f1,0x588745c9,0x8a72f39e } }, + /* 17 */ + { { 0x2341c342,0x73ade4da,0xea704422,0xdd326e54,0x3741cef3,0x336c7d98, + 0x59e61549,0x1eafa00d,0xbd9a3efd,0xcd3ed892,0xc5c6c7e4,0x03faf26c }, + { 0x3045f8ac,0x087e2fcf,0x174f1e73,0x14a65532,0xfe0af9a7,0x2cf84f28, + 0x2cdc935b,0xddfd7a84,0x6929c895,0x4c0f117b,0x4c8bcfcc,0x356572d6 } }, + /* 18 */ + { { 0x7d8c1bba,0x7ecbac01,0x90b0f3d5,0x6058f9c3,0xf6197d0f,0xaee116e3, + 0x4033b128,0xc4dd7068,0xc209b983,0xf084dba6,0x831dbc4a,0x97c7c2cf }, + { 0xf96010e8,0x2f4e61dd,0x529faa17,0xd97e4e20,0x69d37f20,0x4ee66660, + 0x3d366d72,0xccc139ed,0x13488e0f,0x690b6ee2,0xf3a6d533,0x7cad1dc5 } }, + /* 19 */ + { { 0xda57a41f,0x660a9a81,0xec0039b6,0xe74a0412,0x5e1dad15,0x42343c6b, + 0x46681d4c,0x284f3ff5,0x63749e89,0xb51087f1,0x6f9f2f13,0x070f23cc }, + { 0x5d186e14,0x542211da,0xfddb0dff,0x84748f37,0xdb1f4180,0x41a3aab4, + 0xa6402d0e,0x25ed667b,0x02f58355,0x2f2924a9,0xfa44a689,0x5844ee7c } }, + /* 20 */ + { { 0x3f3b236f,0xfab08607,0x81e221da,0x19e9d41d,0x3927b428,0xf3f6571e, + 0x7550f1f6,0x4348a933,0xa85e62f0,0x7167b996,0x7f5452bf,0x62d43759 }, + { 0xf2955926,0xd85feb9e,0x6df78353,0x440a561f,0x9ca36b59,0x389668ec, + 0xa22da016,0x052bf1a1,0xf6093254,0xbdfbff72,0xe22209f3,0x94e50f28 } }, + /* 21 */ + { { 0x3062e8af,0x90b2e5b3,0xe8a3d369,0xa8572375,0x201db7b1,0x3fe1b00b, + 0xee651aa2,0xe926def0,0xb9b10ad7,0x6542c9be,0xa2fcbe74,0x098e309b }, + { 0xfff1d63f,0x779deeb3,0x20bfd374,0x23d0e80a,0x8768f797,0x8452bb3b, + 0x1f952856,0xcf75bb4d,0x29ea3faa,0x8fe6b400,0x81373a53,0x12bd3e40 } }, + /* 22 */ + { { 0x104cbba5,0xc023780d,0xfa35dd4c,0x6207e747,0x1ca9b6a3,0x35c23928, + 0x97987b10,0x4ff19be8,0x8022eee8,0xb8476bbf,0xd3bbe74d,0xaa0a4a14 }, + { 0x187d4543,0x20f94331,0x79f6e066,0x32153870,0xac7e82e1,0x83b0f74e, + 0x828f06ab,0xa7748ba2,0xc26ef35f,0xc5f0298a,0x8e9a7dbd,0x0f0c5070 } }, + /* 23 */ + { { 0xdef029dd,0x0c5c244c,0x850661b8,0x3dabc687,0xfe11d981,0x9992b865, + 0x6274dbad,0xe9801b8f,0x098da242,0xe54e6319,0x91a53d08,0x9929a91a }, + { 0x35285887,0x37bffd72,0xf1418102,0xbc759425,0xfd2e6e20,0x9280cc35, + 0xfbc42ee5,0x735c600c,0x8837619a,0xb7ad2864,0xa778c57b,0xa3627231 } }, + /* 24 */ + { { 0x91361ed8,0xae799b5c,0x6c63366c,0x47d71b75,0x1b265a6a,0x54cdd521, + 0x98d77b74,0xe0215a59,0xbab29db0,0x4424d9b7,0x7fd9e536,0x8b0ffacc }, + { 0x37b5d9ef,0x46d85d12,0xbfa91747,0x5b106d62,0x5f99ba2d,0xed0479f8, + 0x1d104de4,0x0e6f3923,0x25e8983f,0x83a84c84,0xf8105a70,0xa9507e0a } }, + /* 25 */ + { { 0x14cf381c,0xf6c68a6e,0xc22e31cc,0xaf9d27bd,0xaa8a5ccb,0x23568d4d, + 0xe338e4d2,0xe431eec0,0x8f52ad1f,0xf1a828fe,0xe86acd80,0xdb6a0579 }, + { 0x4507832a,0x2885672e,0x887e5289,0x73fc275f,0x05610d08,0x65f80278, + 0x075ff5b0,0x8d9b4554,0x09f712b5,0x3a8e8fb1,0x2ebe9cf2,0x39f0ac86 } }, + /* 26 */ + { { 0x4c52edf5,0xd8fabf78,0xa589ae53,0xdcd737e5,0xd791ab17,0x94918bf0, + 0xbcff06c9,0xb5fbd956,0xdca46d45,0xf6d3032e,0x41a3e486,0x2cdff7e1 }, + { 0x61f47ec8,0x6674b3ba,0xeef84608,0x8a882163,0x4c687f90,0xa257c705, + 0xf6cdf227,0xe30cb2ed,0x7f6ea846,0x2c4c64ca,0xcc6bcd3c,0x186fa17c } }, + /* 27 */ + { { 0x1dfcb91e,0x48a3f536,0x646d358a,0x83595e13,0x91128798,0xbd15827b, + 0x2187757a,0x3ce612b8,0x61bd7372,0x873150a1,0xb662f568,0xf4684530 }, + { 0x401896f6,0x8833950b,0x77f3e090,0xe11cb89a,0x48e7f4a5,0xb2f12cac, + 0xf606677e,0x313dd769,0x16579f93,0xfdcf08b3,0x46b8f22b,0x6429cec9 } }, + /* 28 */ + { { 0xbb75f9a4,0x4984dd54,0x29d3b570,0x4aef06b9,0x3d6e4c1e,0xb5f84ca2, + 0xb083ef35,0x24c61c11,0x392ca9ff,0xce4a7392,0x6730a800,0x865d6517 }, + { 0x722b4a2b,0xca3dfe76,0x7b083e0e,0x12c04bf9,0x1b86b8a5,0x803ce5b5, + 0x6a7e3e0c,0x3fc7632d,0xc81adbe4,0xc89970c2,0x120e16b1,0x3cbcd3ad } }, + /* 29 */ + { { 0xec30ce93,0xfbfb4cc7,0xb72720a2,0x10ed6c7d,0x47b55500,0xec675bf7, + 0x333ff7c3,0x90725903,0x5075bfc0,0xc7c3973e,0x07acf31b,0xb049ecb0 }, + { 0x4f58839c,0xb4076eaf,0xa2b05e4f,0x101896da,0xab40c66e,0x3f6033b0, + 0xc8d864ba,0x19ee9eeb,0x47bf6d2a,0xeb6cf155,0xf826477d,0x8e5a9663 } }, + /* 30 */ + { { 0xf7fbd5e1,0x69e62fdd,0x76912b1d,0x38ecfe54,0xd1da3bfb,0x845a3d56, + 0x1c86f0d4,0x0494950e,0x3bc36ce8,0x83cadbf9,0x4fccc8d1,0x41fce572 }, + { 0x8332c144,0x05f939c2,0x0871e46e,0xb17f248b,0x66e8aff6,0x3d8534e2, + 0x3b85c629,0x1d06f1dc,0xa3131b73,0xdb06a32e,0x8b3f64e5,0xf295184d } }, + /* 31 */ + { { 0x36ddc103,0xd9653ff7,0x95ef606f,0x25f43e37,0xfe06dce8,0x09e301fc, + 0x30b6eebf,0x85af2341,0x0ff56b20,0x79b12b53,0xfe9a3c6b,0x9b4fb499 }, + { 0x51d27ac2,0x0154f892,0x56ca5389,0xd33167e3,0xafc065a6,0x7828ec1f, + 0x7f746c9b,0x0959a258,0x0c44f837,0xb18f1be3,0xc4132fdb,0xa7946117 } }, + /* 32 */ + { { 0x5e3c647b,0xc0426b77,0x8cf05348,0xbfcbd939,0x172c0d3d,0x31d312e3, + 0xee754737,0x5f49fde6,0x6da7ee61,0x895530f0,0xe8b3a5fb,0xcf281b0a }, + { 0x41b8a543,0xfd149735,0x3080dd30,0x41a625a7,0x653908cf,0xe2baae07, + 0xba02a278,0xc3d01436,0x7b21b8f8,0xa0d0222e,0xd7ec1297,0xfdc270e9 } }, + /* 33 */ + { { 0xbc7f41d6,0x00873c0c,0x1b7ad641,0xd976113e,0x238443fb,0x2a536ff4, + 0x41e62e45,0x030d00e2,0x5f545fc6,0x532e9867,0x8e91208c,0xcd033108 }, + { 0x9797612c,0xd1a04c99,0xeea674e2,0xd4393e02,0xe19742a1,0xd56fa69e, + 0x85f0590e,0xdd2ab480,0x48a2243d,0xa5cefc52,0x54383f41,0x48cc67b6 } }, + /* 34 */ + { { 0xfc14ab48,0x4e50430e,0x26706a74,0x195b7f4f,0xcc881ff6,0x2fe8a228, + 0xd945013d,0xb1b968e2,0x4b92162b,0x936aa579,0x364e754a,0x4fb766b7 }, + { 0x31e1ff7f,0x13f93bca,0xce4f2691,0x696eb5ca,0xa2b09e02,0xff754bf8, + 0xe58e3ff8,0x58f13c9c,0x1678c0b0,0xb757346f,0xa86692b3,0xd54200db } }, + /* 35 */ + { { 0x6dda1265,0x9a030bbd,0xe89718dd,0xf7b4f3fc,0x936065b8,0xa6a4931f, + 0x5f72241c,0xbce72d87,0x65775857,0x6cbb51cb,0x4e993675,0xc7161815 }, + { 0x2ee32189,0xe81a0f79,0x277dc0b2,0xef2fab26,0xb71f469f,0x9e64f6fe, + 0xdfdaf859,0xb448ce33,0xbe6b5df1,0x3f5c1c4c,0x1de45f7b,0xfb8dfb00 } }, + /* 36 */ + { { 0x4d5bb921,0xc7345fa7,0x4d2b667e,0x5c7e04be,0x282d7a3e,0x47ed3a80, + 0x7e47b2a4,0x5c2777f8,0x08488e2e,0x89b3b100,0xb2eb5b45,0x9aad77c2 }, + { 0xdaac34ae,0xd681bca7,0x26afb326,0x2452e4e5,0x41a1ee14,0x0c887924, + 0xc2407ade,0x743b04d4,0xfc17a2ac,0xcb5e999b,0x4a701a06,0x4dca2f82 } }, + /* 37 */ + { { 0x1127bc1a,0x68e31ca6,0x17ead3be,0xa3edd59b,0xe25f5a15,0x67b6b645, + 0xa420e15e,0x76221794,0x4b1e872e,0x794fd83b,0xb2dece1b,0x7cab3f03 }, + { 0xca9b3586,0x7119bf15,0x4d250bd7,0xa5545924,0xcc6bcf24,0x173633ea, + 0xb1b6f884,0x9bd308c2,0x447d38c3,0x3bae06f5,0xf341fe1c,0x54dcc135 } }, + /* 38 */ + { { 0x943caf0d,0x56d3598d,0x225ff133,0xce044ea9,0x563fadea,0x9edf6a7c, + 0x73e8dc27,0x632eb944,0x3190dcab,0x814b467e,0x6dbb1e31,0x2d4f4f31 }, + { 0xa143b7ca,0x8d69811c,0xde7cf950,0x4ec1ac32,0x37b5fe82,0x223ab5fd, + 0x9390f1d9,0xe82616e4,0x75804610,0xabff4b20,0x875b08f0,0x11b9be15 } }, + /* 39 */ + { { 0x3bbe682c,0x4ae31a3d,0x74eef2dd,0xbc7c5d26,0x3c47dd40,0x92afd10a, + 0xc14ab9e1,0xec7e0a3b,0xb2e495e4,0x6a6c3dd1,0x309bcd85,0x085ee5e9 }, + { 0x8c2e67fd,0xf381a908,0xe261eaf2,0x32083a80,0x96deee15,0x0fcd6a49, + 0x5e524c79,0xe3b8fb03,0x1d5b08b9,0x8dc360d9,0x7f26719f,0x3a06e2c8 } }, + /* 40 */ + { { 0x7237cac0,0x5cd9f5a8,0x43586794,0x93f0b59d,0xe94f6c4e,0x4384a764, + 0xb62782d3,0x8304ed2b,0xcde06015,0x0b8db8b3,0x5dbe190f,0x4336dd53 }, + { 0x92ab473a,0x57443553,0xbe5ed046,0x031c7275,0x21909aa4,0x3e78678c, + 0x99202ddb,0x4ab7e04f,0x6977e635,0x2648d206,0x093198be,0xd427d184 } }, + /* 41 */ + { { 0x0f9b5a31,0x822848f5,0xbaadb62a,0xbb003468,0x3357559c,0x233a0472, + 0x79aee843,0x49ef6880,0xaeb9e1e3,0xa89867a0,0x1f6f9a55,0xc151931b }, + { 0xad74251e,0xd264eb0b,0x4abf295e,0x37b9b263,0x04960d10,0xb600921b, + 0x4da77dc0,0x0de53dbc,0xd2b18697,0x01d9bab3,0xf7156ddf,0xad54ec7a } }, + /* 42 */ + { { 0x79efdc58,0x8e74dc35,0x4ff68ddb,0x456bd369,0xd32096a5,0x724e74cc, + 0x386783d0,0xe41cff42,0x7c70d8a4,0xa04c7f21,0xe61a19a2,0x41199d2f }, + { 0x29c05dd2,0xd389a3e0,0xe7e3fda9,0x535f2a6b,0x7c2b4df8,0x26ecf72d, + 0xfe745294,0x678275f4,0x9d23f519,0x6319c9cc,0x88048fc4,0x1e05a02d } }, + /* 43 */ + { { 0xd4d5ffe8,0x75cc8e2e,0xdbea17f2,0xf8bb4896,0xcee3cb4a,0x35059790, + 0xa47c6165,0x4c06ee85,0x92935d2f,0xf98fff25,0x32ffd7c7,0x34c4a572 }, + { 0xea0376a2,0xc4b14806,0x4f115e02,0x2ea5e750,0x1e55d7c0,0x532d76e2, + 0xf31044da,0x68dc9411,0x71b77993,0x9272e465,0x93a8cfd5,0xadaa38bb } }, + /* 44 */ + { { 0x7d4ed72a,0x4bf0c712,0xba1f79a3,0xda0e9264,0xf4c39ea4,0x48c0258b, + 0x2a715138,0xa5394ed8,0xbf06c660,0x4af511ce,0xec5c37cd,0xfcebceef }, + { 0x779ae8c1,0xf23b75aa,0xad1e606e,0xdeff59cc,0x22755c82,0xf3f526fd, + 0xbb32cefd,0x64c5ab44,0x915bdefd,0xa96e11a2,0x1143813e,0xab19746a } }, + /* 45 */ + { { 0xec837d7d,0x43c78585,0xb8ee0ba4,0xca5b6fbc,0xd5dbb5ee,0x34e924d9, + 0xbb4f1ca5,0x3f4fa104,0x398640f7,0x15458b72,0xd7f407ea,0x4231faa9 }, + { 0xf96e6896,0x53e0661e,0xd03b0f9d,0x554e4c69,0x9c7858d1,0xd4fcb07b, + 0x52cb04fa,0x7e952793,0x8974e7f7,0x5f5f1574,0x6b6d57c8,0x2e3fa558 } }, + /* 46 */ + { { 0x6a9951a8,0x42cd4803,0x42792ad0,0xa8b15b88,0xabb29a73,0x18e8bcf9, + 0x409933e8,0xbfd9a092,0xefb88dc4,0x760a3594,0x40724458,0x14418863 }, + { 0x99caedc7,0x162a56ee,0x91d101c9,0x8fb12ecd,0x393202da,0xea671967, + 0xa4ccd796,0x1aac8c4a,0x1cf185a8,0x7db05036,0x8cfd095a,0x0c9f86cd } }, + /* 47 */ + { { 0x10b2a556,0x9a728147,0x327b70b2,0x767ca964,0x5e3799b7,0x04ed9e12, + 0x22a3eb2a,0x6781d2dc,0x0d9450ac,0x5bd116eb,0xa7ebe08a,0xeccac1fc }, + { 0xdc2d6e94,0xde68444f,0x35ecf21b,0x3621f429,0x29e03a2c,0x14e2d543, + 0x7d3e7f0a,0x53e42cd5,0x73ed00b9,0xbba26c09,0xc57d2272,0x00297c39 } }, + /* 48 */ + { { 0xb8243a7d,0x3aaaab10,0x8fa58c5b,0x6eeef93e,0x9ae7f764,0xf866fca3, + 0x61ab04d3,0x64105a26,0x03945d66,0xa3578d8a,0x791b848c,0xb08cd3e4 }, + { 0x756d2411,0x45edc5f8,0xa755128c,0xd4a790d9,0x49e5f6a0,0xc2cf0963, + 0xf649beaa,0xc66d267d,0x8467039e,0x3ce6d968,0x42f7816f,0x50046c6b } }, + /* 49 */ + { { 0x66425043,0x92ae1602,0xf08db890,0x1ff66afd,0x8f162ce5,0x386f5a7f, + 0xfcf5598f,0x18d2dea0,0x1a8ca18e,0x78372b3a,0x8cd0e6f7,0xdf0d20eb }, + { 0x75bb4045,0x7edd5e1d,0xb96d94b7,0x252a47ce,0x2c626776,0xbdb29358, + 0x40dd1031,0x853c3943,0x7d5f47fd,0x9dc9becf,0xbae4044a,0x27c2302f } }, + /* 50 */ + { { 0x8f2d49ce,0x2d1d208a,0x162df0a2,0x0d91aa02,0x09a07f65,0x9c5cce87, + 0x84339012,0xdf07238b,0x419442cd,0x5028e2c8,0x72062aba,0x2dcbd358 }, + { 0xe4680967,0xb5fbc3cb,0x9f92d72c,0x2a7bc645,0x116c369d,0x806c76e1, + 0x3177e8d8,0x5c50677a,0x4569df57,0x753739eb,0x36c3f40b,0x2d481ef6 } }, + /* 51 */ + { { 0xfea1103e,0x1a2d39fd,0x95f81b17,0xeaae5592,0xf59b264a,0xdbd0aa18, + 0xcb592ee0,0x90c39c1a,0x9750cca3,0xdf62f80d,0xdf97cc6c,0xda4d8283 }, + { 0x1e201067,0x0a6dd346,0x69fb1f6b,0x1531f859,0x1d60121f,0x4895e552, + 0x4c041c91,0x0b21aab0,0xbcc1ccf8,0x9d896c46,0x3141bde7,0xd24da3b3 } }, + /* 52 */ + { { 0x53b0a354,0x575a0537,0x0c6ddcd8,0x392ff2f4,0x56157b94,0x0b8e8cff, + 0x3b1b80d1,0x073e57bd,0x3fedee15,0x2a75e0f0,0xaa8e6f19,0x752380e4 }, + { 0x6558ffe9,0x1f4e227c,0x19ec5415,0x3a348618,0xf7997085,0xab382d5e, + 0xddc46ac2,0x5e6deaff,0xfc8d094c,0xe5144078,0xf60e37c6,0xf674fe51 } }, + /* 53 */ + { { 0xaf63408f,0x6fb87ae5,0xcd75a737,0xa39c36a9,0xcf4c618d,0x7833313f, + 0xf034c88d,0xfbcd4482,0x39b35288,0x4469a761,0x66b5d9c9,0x77a711c5 }, + { 0x944f8d65,0x4a695dc7,0x161aaba8,0xe6da5f65,0x24601669,0x8654e9c3, + 0x28ae7491,0xbc8b93f5,0x8f5580d8,0x5f1d1e83,0xcea32cc8,0x8ccf9a1a } }, + /* 54 */ + { { 0x7196fee2,0x28ab110c,0x874c8945,0x75799d63,0x29aedadd,0xa2629348, + 0x2be88ff4,0x9714cc7b,0xd58d60d6,0xf71293cf,0x32a564e9,0xda6b6cb3 }, + { 0x3dd821c2,0xf43fddb1,0x90dd323d,0xf2f2785f,0x048489f8,0x91246419, + 0xd24c6749,0x61660f26,0xc803c15c,0x961d9e8c,0xfaadc4c9,0x631c6158 } }, + /* 55 */ + { { 0xfd752366,0xacf2ebe0,0x139be88b,0xb93c340e,0x0f20179e,0x98f66485, + 0xff1da785,0x14820254,0x4f85c16e,0x5278e276,0x7aab1913,0xa246ee45 }, + { 0x53763b33,0x43861eb4,0x45c0bc0d,0xc49f03fc,0xad6b1ea1,0xafff16bc, + 0x6fd49c99,0xce33908b,0xf7fde8c3,0x5c51e9bf,0xff142c5e,0x076a7a39 } }, + /* 56 */ + { { 0x9e338d10,0x04639dfe,0xf42b411b,0x8ee6996f,0xa875cef2,0x960461d1, + 0x95b4d0ba,0x1057b6d6,0xa906e0bc,0x27639252,0xe1c20f8a,0x2c19f09a }, + { 0xeef4c43d,0x5b8fc3f0,0x07a84aa9,0xe2e1b1a8,0x835d2bdb,0x5f455528, + 0x207132dd,0x0f4aee4d,0x3907f675,0xe9f8338c,0x0e0531f0,0x7a874dc9 } }, + /* 57 */ + { { 0x97c27050,0x84b22d45,0x59e70bf8,0xbd0b8df7,0x79738b9b,0xb4d67405, + 0xcd917c4f,0x47f4d5f5,0x13ce6e33,0x9099c4ce,0x521d0f8b,0x942bfd39 }, + { 0xa43b566d,0x5028f0f6,0x21bff7de,0xaf6e8669,0xc44232cd,0x83f6f856, + 0xf915069a,0x65680579,0xecfecb85,0xd12095a2,0xdb01ba16,0xcf7f06ae } }, + /* 58 */ + { { 0x8ef96c80,0x0f56e3c4,0x3ddb609c,0xd521f2b3,0x7dc1450d,0x2be94102, + 0x02a91fe2,0x2d21a071,0x1efa37de,0x2e6f74fa,0x156c28a1,0x9a9a90b8 }, + { 0x9dc7dfcb,0xc54ea9ea,0x2c2c1d62,0xc74e66fc,0x49d3e067,0x9f23f967, + 0x54dd38ad,0x1c7c3a46,0x5946cee3,0xc7005884,0x45cc045d,0x89856368 } }, + /* 59 */ + { { 0xfce73946,0x29da7cd4,0x23168563,0x8f697db5,0xcba92ec6,0x8e235e9c, + 0x9f91d3ea,0x55d4655f,0xaa50a6cd,0xf3689f23,0x21e6a1a0,0xdcf21c26 }, + { 0x61b818bf,0xcffbc82e,0xda47a243,0xc74a2f96,0x8bc1a0cf,0x234e980a, + 0x7929cb6d,0xf35fd6b5,0xefe17d6c,0x81468e12,0x58b2dafb,0xddea6ae5 } }, + /* 60 */ + { { 0x7e787b2e,0x294de887,0x39a9310d,0x258acc1f,0xac14265d,0x92d9714a, + 0x708b48a0,0x18b5591c,0xe1abbf71,0x27cc6bb0,0x568307b9,0xc0581fa3 }, + { 0xf24d4d58,0x9e0f58a3,0xe0ce2327,0xfebe9bb8,0x9d1be702,0x91fd6a41, + 0xfacac993,0x9a7d8a45,0x9e50d66d,0xabc0a08c,0x06498201,0x02c342f7 } }, + /* 61 */ + { { 0x157bdbc2,0xccd71407,0xad0e1605,0x72fa89c6,0xb92a015f,0xb1d3da2b, + 0xa0a3fe56,0x8ad9e7cd,0x24f06737,0x160edcbd,0x61275be6,0x79d4db33 }, + { 0x5f3497c4,0xd3d31fd9,0x04192fb0,0x8cafeaee,0x13a50af3,0xe13ca745, + 0x8c85aae5,0x18826167,0x9eb556ff,0xce06cea8,0xbdb549f3,0x2eef1995 } }, + /* 62 */ + { { 0x50596edc,0x8ed7d3eb,0x905243a2,0xaa359362,0xa4b6d02b,0xa212c2c2, + 0xc4fbec68,0x611fd727,0xb84f733d,0x8a0b8ff7,0x5f0daf0e,0xd85a6b90 }, + { 0xd4091cf7,0x60e899f5,0x2eff2768,0x4fef2b67,0x10c33964,0xc1f195cb, + 0x93626a8f,0x8275d369,0x0d6c840a,0xc77904f4,0x7a868acd,0x88d8b7fd } }, + /* 63 */ + { { 0x7bd98425,0x85f23723,0xc70b154e,0xd4463992,0x96687a2e,0xcbb00ee2, + 0xc83214fd,0x905fdbf7,0x13593684,0x2019d293,0xef51218e,0x0428c393 }, + { 0x981e909a,0x40c7623f,0x7be192da,0x92513385,0x4010907e,0x48fe480f, + 0x3120b459,0xdd7a187c,0xa1fd8f3c,0xc9d7702d,0xe358efc5,0x66e4753b } }, + /* 64 */ + { { 0x16973cf4,0x070d34e1,0x7e4f34f7,0x20aee08b,0x5eb8ad29,0x269af9b9, + 0xa6a45dda,0xdde0a036,0x63df41e0,0xa18b528e,0xa260df2a,0x03cc71b2 }, + { 0xa06b1dd7,0x24a6770a,0x9d2675d3,0x5bfa9c11,0x96844432,0x73c1e2a1, + 0x131a6cf0,0x3660558d,0x2ee79454,0xb0289c83,0xc6d8ddcd,0xa6aefb01 } }, + /* 65 */ + { { 0x01ab5245,0xba1464b4,0xc48d93ff,0x9b8d0b6d,0x93ad272c,0x939867dc, + 0xae9fdc77,0xbebe085e,0x894ea8bd,0x73ae5103,0x39ac22e1,0x740fc89a }, + { 0x28e23b23,0x5e28b0a3,0xe13104d0,0x2352722e,0xb0a2640d,0xf4667a18, + 0x49bb37c3,0xac74a72e,0xe81e183a,0x79f734f0,0x3fd9c0eb,0xbffe5b6c } }, + /* 66 */ + { { 0xc6a2123f,0xb1a358f5,0xfe28df6d,0x927b2d95,0xf199d2f9,0x89702753, + 0x1a3f82dc,0x0a73754c,0x777affe1,0x063d029d,0xdae6d34d,0x5439817e }, + { 0x6b8b83c4,0xf7979eef,0x9d945682,0x615cb214,0xc5e57eae,0x8f0e4fac, + 0x113047dd,0x042b89b8,0x93f36508,0x888356dc,0x5fd1f32f,0xbf008d18 } }, + /* 67 */ + { { 0x4e8068db,0x8012aa24,0xa5729a47,0xc72cc641,0x43f0691d,0x3c33df2c, + 0x1d92145f,0xfa057347,0xb97f7946,0xaefc0f2f,0x2f8121bf,0x813d75cb }, + { 0x4383bba6,0x05613c72,0xa4224b3f,0xa924ce70,0x5f2179a6,0xe59cecbe, + 0x79f62b61,0x78e2e8aa,0x53ad8079,0x3ac2cc3b,0xd8f4fa96,0x55518d71 } }, + /* 68 */ + { { 0x00623f3b,0x03cf2922,0x5f29ebff,0x095c7111,0x80aa6823,0x42d72247, + 0x7458c0b0,0x044c7ba1,0x0959ec20,0xca62f7ef,0xf8ca929f,0x40ae2ab7 }, + { 0xa927b102,0xb8c5377a,0xdc031771,0x398a86a0,0xc216a406,0x04908f9d, + 0x918d3300,0xb423a73a,0xe0b94739,0x634b0ff1,0x2d69f697,0xe29de725 } }, + /* 69 */ + { { 0x8435af04,0x744d1400,0xfec192da,0x5f255b1d,0x336dc542,0x1f17dc12, + 0x636a68a8,0x5c90c2a7,0x7704ca1e,0x960c9eb7,0x6fb3d65a,0x9de8cf1e }, + { 0x511d3d06,0xc60fee0d,0xf9eb52c7,0x466e2313,0x206b0914,0x743c0f5f, + 0x2191aa4d,0x42f55bac,0xffebdbc2,0xcefc7c8f,0xe6e8ed1c,0xd4fa6081 } }, + /* 70 */ + { { 0xb0ab9645,0xb5e405d3,0xd5f1f711,0xaeec7f98,0x585c2a6e,0x8ad42311, + 0x512c6944,0x045acb9e,0xa90db1c6,0xae106c4e,0x898e6563,0xb89f33d5 }, + { 0x7fed2ce4,0x43b07cd9,0xdd815b20,0xf9934e17,0x0a81a349,0x6778d4d5, + 0x52918061,0x9e616ade,0xd7e67112,0xfa06db06,0x88488091,0x1da23cf1 } }, + /* 71 */ + { { 0x42f2c4b5,0x821c46b3,0x66059e47,0x931513ef,0x66f50cd1,0x7030ae43, + 0x43e7b127,0x43b536c9,0x5fca5360,0x006258cf,0x6b557abf,0xe4e3ee79 }, + { 0x24c8b22f,0xbb6b3900,0xfcbf1054,0x2eb5e2c1,0x567492af,0x937b18c9, + 0xacf53957,0xf09432e4,0x1dbf3a56,0x585f5a9d,0xbe0887cf,0xf86751fd } }, + /* 72 */ + { { 0x9d10e0b2,0x157399cb,0x60dc51b7,0x1c0d5956,0x1f583090,0x1d496b8a, + 0x88590484,0x6658bc26,0x03213f28,0x88c08ab7,0x7ae58de4,0x8d2e0f73 }, + { 0x486cfee6,0x9b79bc95,0xe9e5bc57,0x036a26c7,0xcd8ae97a,0x1ad03601, + 0xff3a0494,0x06907f87,0x2c7eb584,0x078f4bbf,0x7e8d0a5a,0xe3731bf5 } }, + /* 73 */ + { { 0xe1cd0abe,0x72f2282b,0x87efefa2,0xd4f9015e,0x6c3834bd,0x9d189806, + 0xb8a29ced,0x9c8cdcc1,0xfee82ebc,0x0601b9f4,0x7206a756,0x371052bc }, + { 0x46f32562,0x76fa1092,0x17351bb4,0xdaad534c,0xb3636bb5,0xc3d64c37, + 0x45d54e00,0x038a8c51,0x32c09e7c,0x301e6180,0x95735151,0x9764eae7 } }, + /* 74 */ + { { 0xcbd5256a,0x8791b19f,0x6ca13a3b,0x4007e0f2,0x4cf06904,0x03b79460, + 0xb6c17589,0xb18a9c22,0x81d45908,0xa1cb7d7d,0x21bb68f1,0x6e13fa9d }, + { 0xa71e6e16,0x47183c62,0xe18749ed,0x5cf0ef8e,0x2e5ed409,0x2c9c7f9b, + 0xe6e117e1,0x042eeacc,0x13fb5a7f,0xb86d4816,0xc9e5feb1,0xea1cf0ed } }, + /* 75 */ + { { 0xcea4cc9b,0x6e6573c9,0xafcec8f3,0x5417961d,0xa438b6f6,0x804bf02a, + 0xdcd4ea88,0xb894b03c,0x3799571f,0xd0f807e9,0x862156e8,0x3466a7f5 }, + { 0x56515664,0x51e59acd,0xa3c5eb0b,0x55b0f93c,0x6a4279db,0x84a06b02, + 0xc5fae08e,0x5c850579,0xa663a1a2,0xcf07b8db,0xf46ffc8d,0x49a36bbc } }, + /* 76 */ + { { 0x46d93106,0xe47f5acc,0xaa897c9c,0x65b7ade0,0x12d7e4be,0x37cf4c94, + 0xd4b2caa9,0xa2ae9b80,0xe60357a3,0x5e7ce09c,0xc8ecd5f9,0x29f77667 }, + { 0xa8a0b1c5,0xdf6868f5,0x62978ad8,0x240858cf,0xdc0002a1,0x0f7ac101, + 0xffe9aa05,0x1d28a9d7,0x5b962c97,0x744984d6,0x3d28c8b2,0xa8a7c00b } }, + /* 77 */ + { { 0xae11a338,0x7c58a852,0xd1af96e7,0xa78613f1,0x5355cc73,0x7e9767d2, + 0x792a2de6,0x6ba37009,0x124386b2,0x7d60f618,0x11157674,0xab09b531 }, + { 0x98eb9dd0,0x95a04841,0x15070328,0xe6c17acc,0x489c6e49,0xafc6da45, + 0xbb211530,0xab45a60a,0x7d7ea933,0xc58d6592,0x095642c6,0xa3ef3c65 } }, + /* 78 */ + { { 0xdf010879,0x89d420e9,0x39576179,0x9d25255d,0xe39513b6,0x9cdefd50, + 0xd5d1c313,0xe4efe45b,0x3f7af771,0xc0149de7,0x340ab06b,0x55a6b4f4 }, + { 0xebeaf771,0xf1325251,0x878d4288,0x2ab44128,0x18e05afe,0xfcd5832e, + 0xcc1fb62b,0xef52a348,0xc1c4792a,0x2bd08274,0x877c6dc7,0x345c5846 } }, + /* 79 */ + { { 0xbea65e90,0xde15ceb0,0x2416d99c,0x0987f72b,0xfd863dec,0x44db578d, + 0xac6a3578,0xf617b74b,0xdb48e999,0x9e62bd7a,0xeab1a1be,0x877cae61 }, + { 0x3a358610,0x23adddaa,0x325e2b07,0x2fc4d6d1,0x1585754e,0x897198f5, + 0xb392b584,0xf741852c,0xb55f7de1,0x9927804c,0x1aa8efae,0xe9e6c4ed } }, + /* 80 */ + { { 0x98683186,0x867db639,0xddcc4ea9,0xfb5cf424,0xd4f0e7bd,0xcc9a7ffe, + 0x7a779f7e,0x7c57f71c,0xd6b25ef2,0x90774079,0xb4081680,0x90eae903 }, + { 0x0ee1fceb,0xdf2aae5e,0xe86c1a1f,0x3ff1da24,0xca193edf,0x80f587d6, + 0xdc9b9d6a,0xa5695523,0x85920303,0x7b840900,0xba6dbdef,0x1efa4dfc } }, + /* 81 */ + { { 0xe0540015,0xfbd838f9,0xc39077dc,0x2c323946,0xad619124,0x8b1fb9e6, + 0x0ca62ea8,0x9612440c,0x2dbe00ff,0x9ad9b52c,0xae197643,0xf52abaa1 }, + { 0x2cac32ad,0xd0e89894,0x62a98f91,0xdfb79e42,0x276f55cb,0x65452ecf, + 0x7ad23e12,0xdb1ac0d2,0xde4986f0,0xf68c5f6a,0x82ce327d,0x389ac37b } }, + /* 82 */ + { { 0xf8e60f5b,0x511188b4,0x48aa2ada,0x7fe67015,0x381abca2,0xdb333cb8, + 0xdaf3fc97,0xb15e6d9d,0x36aabc03,0x4b24f6eb,0x72a748b4,0xc59789df }, + { 0x29cf5279,0x26fcb8a5,0x01ad9a6c,0x7a3c6bfc,0x4b8bac9b,0x866cf88d, + 0x9c80d041,0xf4c89989,0x70add148,0xf0a04241,0x45d81a41,0x5a02f479 } }, + /* 83 */ + { { 0xc1c90202,0xfa5c877c,0xf8ac7570,0xd099d440,0xd17881f7,0x428a5b1b, + 0x5b2501d7,0x61e267db,0xf2e4465b,0xf889bf04,0x76aa4cb8,0x4da3ae08 }, + { 0xe3e66861,0x3ef0fe26,0x3318b86d,0x5e772953,0x747396df,0xc3c35fbc, + 0x439ffd37,0x5115a29c,0xb2d70374,0xbfc4bd97,0x56246b9d,0x088630ea } }, + /* 84 */ + { { 0xb8a9e8c9,0xcd96866d,0x5bb8091e,0xa11963b8,0x045b3cd2,0xc7f90d53, + 0x80f36504,0x755a72b5,0x21d3751c,0x46f8b399,0x53c193de,0x4bffdc91 }, + { 0xb89554e7,0xcd15c049,0xf7a26be6,0x353c6754,0xbd41d970,0x79602370, + 0x12b176c0,0xde16470b,0x40c8809d,0x56ba1175,0xe435fb1e,0xe2db35c3 } }, + /* 85 */ + { { 0x6328e33f,0xd71e4aab,0xaf8136d1,0x5486782b,0x86d57231,0x07a4995f, + 0x1651a968,0xf1f0a5bd,0x76803b6d,0xa5dc5b24,0x42dda935,0x5c587cbc }, + { 0xbae8b4c0,0x2b6cdb32,0xb1331138,0x66d1598b,0x5d7e9614,0x4a23b2d2, + 0x74a8c05d,0x93e402a6,0xda7ce82e,0x45ac94e6,0xe463d465,0xeb9f8281 } }, + /* 86 */ + { { 0xfecf5b9b,0x34e0f9d1,0xf206966a,0xa115b12b,0x1eaa0534,0x5591cf3b, + 0xfb1558f9,0x5f0293cb,0x1bc703a5,0x1c8507a4,0x862c1f81,0x92e6b81c }, + { 0xcdaf24e3,0xcc9ebc66,0x72fcfc70,0x68917ecd,0x8157ba48,0x6dc9a930, + 0xb06ab2b2,0x5d425c08,0x36e929c4,0x362f8ce7,0x62e89324,0x09f6f57c } }, + /* 87 */ + { { 0xd29375fb,0x1c7d6b78,0xe35d1157,0xfabd851e,0x4243ea47,0xf6f62dcd, + 0x8fe30b0f,0x1dd92460,0xffc6e709,0x08166dfa,0x0881e6a7,0xc6c4c693 }, + { 0xd6a53fb0,0x20368f87,0x9eb4d1f9,0x38718e9f,0xafd7e790,0x03f08acd, + 0x72fe2a1c,0x0835eb44,0x88076e5d,0x7e050903,0xa638e731,0x538f765e } }, + /* 88 */ + { { 0xc2663b4b,0x0e0249d9,0x47cd38dd,0xe700ab5b,0x2c46559f,0xb192559d, + 0x4bcde66d,0x8f9f74a8,0x3e2aced5,0xad161523,0x3dd03a5b,0xc155c047 }, + { 0x3be454eb,0x346a8799,0x83b7dccd,0x66ee94db,0xab9d2abe,0x1f6d8378, + 0x7733f355,0x4a396dd2,0xf53553c2,0x419bd40a,0x731dd943,0xd0ead98d } }, + /* 89 */ + { { 0xec142408,0x908e0b0e,0x4114b310,0x98943cb9,0x1742b1d7,0x03dbf7d8, + 0x693412f4,0xd270df6b,0x8f69e20c,0xc5065494,0x697e43a1,0xa76a90c3 }, + { 0x4624825a,0xe0fa3384,0x8acc34c2,0x82e48c0b,0xe9a14f2b,0x7b24bd14, + 0x4db30803,0x4f5dd5e2,0x932da0a3,0x0c77a9e7,0x74c653dc,0x20db90f2 } }, + /* 90 */ + { { 0x0e6c5fd9,0x261179b7,0x6c982eea,0xf8bec123,0xd4957b7e,0x47683338, + 0x0a72f66a,0xcc47e664,0x1bad9350,0xbd54bf6a,0xf454e95a,0xdfbf4c6a }, + { 0x6907f4fa,0x3f7a7afa,0x865ca735,0x7311fae0,0x2a496ada,0x24737ab8, + 0x15feb79b,0x13e425f1,0xa1b93c21,0xe9e97c50,0x4ddd3eb5,0xb26b6eac } }, + /* 91 */ + { { 0x2a2e5f2b,0x81cab9f5,0xbf385ac4,0xf93caf29,0xc909963a,0xf4bf35c3, + 0x74c9143c,0x081e7300,0xc281b4c5,0x3ea57fa8,0x9b340741,0xe497905c }, + { 0x55ab3cfb,0xf556dd8a,0x518db6ad,0xd444b96b,0x5ef4b955,0x34f5425a, + 0xecd26aa3,0xdda7a3ac,0xda655e97,0xb57da11b,0xc2024c70,0x02da3eff } }, + /* 92 */ + { { 0x6481d0d9,0xe24b0036,0x818fdfe2,0x3740dbe5,0x190fda00,0xc1fc1f45, + 0x3cf27fde,0x329c9280,0x6934f43e,0x7435cb53,0x7884e8fe,0x2b505a5d }, + { 0x711adcc9,0x6cfcc6a6,0x531e21e1,0xf034325c,0x9b2a8a99,0xa2f4a967, + 0x3c21bdff,0x9d5f3842,0x31b57d66,0xb25c7811,0x0b8093b9,0xdb5344d8 } }, + /* 93 */ + { { 0xae50a2f5,0x0d72e667,0xe4a861d1,0x9b7f8d8a,0x330df1cb,0xa129f70f, + 0xe04fefc3,0xe90aa5d7,0xe72c3ae1,0xff561ecb,0xcdb955fa,0x0d8fb428 }, + { 0xd7663784,0xd2235f73,0x7e2c456a,0xc05baec6,0x2adbfccc,0xe5c292e4, + 0xefb110d5,0x4fd17988,0xd19d49f3,0x27e57734,0x84f679fe,0x188ac4ce } }, + /* 94 */ + { { 0xa796c53e,0x7ee344cf,0x0868009b,0xbbf6074d,0x474a1295,0x1f1594f7, + 0xac11632d,0x66776edc,0x04e2fa5a,0x1862278b,0xc854a89a,0x52665cf2 }, + { 0x8104ab58,0x7e376464,0x7204fd6d,0x16775913,0x44ea1199,0x86ca06a5, + 0x1c9240dd,0xaa3f765b,0x24746149,0x5f8501a9,0xdcd251d7,0x7b982e30 } }, + /* 95 */ + { { 0xc15f3060,0xe44e9efc,0xa87ebbe6,0x5ad62f2e,0xc79500d4,0x36499d41, + 0x336fa9d1,0xa66d6dc0,0x5afd3b1f,0xf8afc495,0xe5c9822b,0x1d8ccb24 }, + { 0x79d7584b,0x4031422b,0xea3f20dd,0xc54a0580,0x958468c5,0x3f837c8f, + 0xfbea7735,0x3d82f110,0x7dffe2fc,0x679a8778,0x20704803,0x48eba63b } }, + /* 96 */ + { { 0xdf46e2f6,0x89b10d41,0x19514367,0x13ab57f8,0x1d469c87,0x067372b9, + 0x4f6c5798,0x0c195afa,0x272c9acf,0xea43a12a,0x678abdac,0x9dadd8cb }, + { 0xe182579a,0xcce56c6b,0x2d26c2d8,0x86febadb,0x2a44745c,0x1c668ee1, + 0x98dc047a,0x580acd86,0x51b9ec2d,0x5a2b79cc,0x4054f6a0,0x007da608 } }, + /* 97 */ + { { 0x17b00dd0,0x9e3ca352,0x0e81a7a6,0x046779cb,0xd482d871,0xb999fef3, + 0xd9233fbc,0xe6f38134,0xf48cd0e0,0x112c3001,0x3c6c66ae,0x934e7576 }, + { 0xd73234dc,0xb44d4fc3,0x864eafc1,0xfcae2062,0x26bef21a,0x843afe25, + 0xf3b75fdf,0x61355107,0x794c2e6b,0x8367a5aa,0x8548a372,0x3d2629b1 } }, + /* 98 */ + { { 0x437cfaf8,0x6230618f,0x2032c299,0x5b8742cb,0x2293643a,0x949f7247, + 0x09464f79,0xb8040f1a,0x4f254143,0x049462d2,0x366c7e76,0xabd6b522 }, + { 0xd5338f55,0x119b392b,0x01495a0c,0x1a80a9ce,0xf8d7537e,0xf3118ca7, + 0x6bf4b762,0xb715adc2,0xa8482b6c,0x24506165,0x96a7c84d,0xd958d7c6 } }, + /* 99 */ + { { 0xbdc21f31,0x9ad8aa87,0x8063e58c,0xadb3cab4,0xb07dd7b8,0xefd86283, + 0x1be7c6b4,0xc7b9b762,0x015582de,0x2ef58741,0x299addf3,0xc970c52e }, + { 0x22f24d66,0x78f02e2a,0x74cc100a,0xefec1d10,0x09316e1a,0xaf2a6a39, + 0x5849dd49,0xce7c2205,0x96bffc4c,0x9c1fe75c,0x7ba06ec0,0xcad98fd2 } }, + /* 100 */ + { { 0xb648b73e,0xed76e2d0,0x1cfd285e,0xa9f92ce5,0x2ed13de1,0xa8c86c06, + 0xa5191a93,0x1d3a574e,0x1ad1b8bf,0x385cdf8b,0x47d2cfe3,0xbbecc28a }, + { 0x69cec548,0x98d326c0,0xf240a0b2,0x4f5bc1dd,0x29057236,0x241a7062, + 0xc68294a4,0x0fc6e9c5,0xa319f17a,0x4d04838b,0x9ffc1c6f,0x8b612cf1 } }, + /* 101 */ + { { 0x4c3830eb,0x9bb0b501,0x8ee0d0c5,0x3d08f83c,0x79ba9389,0xa4a62642, + 0x9cbc2914,0x5d5d4044,0x074c46f0,0xae9eb83e,0x74ead7d6,0x63bb758f }, + { 0xc6bb29e0,0x1c40d2ea,0x4b02f41e,0x95aa2d87,0x53cb199a,0x92989175, + 0x51584f6d,0xdd91bafe,0x31a1aaec,0x3715efb9,0x46780f9e,0xc1b6ae5b } }, + /* 102 */ + { { 0x42772f41,0xcded3e4b,0x3bcb79d1,0x3a700d5d,0x80feee60,0x4430d50e, + 0xf5e5d4bb,0x444ef1fc,0xe6e358ff,0xc660194f,0x6a91b43c,0xe68a2f32 }, + { 0x977fe4d2,0x5842775c,0x7e2a41eb,0x78fdef5c,0xff8df00e,0x5f3bec02, + 0x5852525d,0xf4b840cd,0x4e6988bd,0x0870483a,0xcc64b837,0x39499e39 } }, + /* 103 */ + { { 0xb08df5fe,0xfc05de80,0x63ba0362,0x0c12957c,0xd5cf1428,0xea379414, + 0x54ef6216,0xc559132a,0xb9e65cf8,0x33d5f12f,0x1695d663,0x09c60278 }, + { 0x61f7a2fb,0x3ac1ced4,0xd4f5eeb8,0xdd838444,0x8318fcad,0x82a38c6c, + 0xe9f1a864,0x315be2e5,0x442daf47,0x317b5771,0x95aa5f9e,0x81b5904a } }, + /* 104 */ + { { 0x8b21d232,0x6b6b1c50,0x8c2cba75,0x87f3dbc0,0xae9f0faf,0xa7e74b46, + 0xbb7b8079,0x036a0985,0x8d974a25,0x4f185b90,0xd9af5ec9,0x5aa7cef0 }, + { 0x57dcfffc,0xe0566a70,0xb8453225,0x6ea311da,0x23368aa9,0x72ea1a8d, + 0x48cd552d,0xed9b2083,0xc80ea435,0xb987967c,0x6c104173,0xad735c75 } }, + /* 105 */ + { { 0xcee76ef4,0xaea85ab3,0xaf1d2b93,0x44997444,0xeacb923f,0x0851929b, + 0x51e3bc0c,0xb080b590,0x59be68a2,0xc4ee1d86,0x64b26cda,0xf00de219 }, + { 0xf2e90d4d,0x8d7fb5c0,0x77d9ec64,0x00e219a7,0x5d1c491c,0xc4e6febd, + 0x1a8f4585,0x080e3754,0x48d2af9c,0x4a9b86c8,0xb6679851,0x2ed70db6 } }, + /* 106 */ + { { 0x586f25cb,0xaee44116,0xa0fcf70f,0xf7b6861f,0x18a350e8,0x55d2cd20, + 0x92dc286f,0x861bf3e5,0x6226aba7,0x9ab18ffa,0xa9857b03,0xd15827be }, + { 0x92e6acef,0x26c1f547,0xac1fbac3,0x422c63c8,0xfcbfd71d,0xa2d8760d, + 0xb2511224,0x35f6a539,0x048d1a21,0xbaa88fa1,0xebf999db,0x49f1abe9 } }, + /* 107 */ + { { 0xf7492b73,0x16f9f4f4,0xcb392b1a,0xcf28ec1e,0x69ca6ffc,0x45b130d4, + 0xb72efa58,0x28ba8d40,0x5ca066f5,0xace987c7,0x4ad022eb,0x3e399246 }, + { 0x752555bb,0x63a2d84e,0x9c2ae394,0xaaa93b4a,0xc89539ca,0xcd80424e, + 0xaa119a99,0x6d6b5a6d,0x379f2629,0xbd50334c,0xef3cc7d3,0x899e925e } }, + /* 108 */ + { { 0xbf825dc4,0xb7ff3651,0x40b9c462,0x0f741cc4,0x5cc4fb5b,0x771ff5a9, + 0x47fd56fe,0xcb9e9c9b,0x5626c0d3,0xbdf053db,0xf7e14098,0xa97ce675 }, + { 0x6c934f5e,0x68afe5a3,0xccefc46f,0x6cd5e148,0xd7a88586,0xc7758570, + 0xdd558d40,0x49978f5e,0x64ae00c1,0xa1d5088a,0xf1d65bb2,0x58f2a720 } }, + /* 109 */ + { { 0x3e4daedb,0x66fdda4a,0x65d1b052,0x38318c12,0x4c4bbf5c,0x28d910a2, + 0x78a9cd14,0x762fe5c4,0xd2cc0aee,0x08e5ebaa,0xca0c654c,0xd2cdf257 }, + { 0x08b717d2,0x48f7c58b,0x386cd07a,0x3807184a,0xae7d0112,0x3240f626, + 0xc43917b0,0x03e9361b,0x20aea018,0xf261a876,0x7e1e6372,0x53f556a4 } }, + /* 110 */ + { { 0x2f512a90,0xc84cee56,0x1b0ea9f1,0x24b3c004,0xe26cc1ea,0x0ee15d2d, + 0xf0c9ef7d,0xd848762c,0xd5341435,0x1026e9c5,0xfdb16b31,0x8f5b73dc }, + { 0xd2c75d95,0x1f69bef2,0xbe064dda,0x8d33d581,0x57ed35e6,0x8c024c12, + 0xc309c281,0xf8d435f9,0xd6960193,0xfd295061,0xe9e49541,0x66618d78 } }, + /* 111 */ + { { 0x8ce382de,0x571cfd45,0xde900dde,0x175806ee,0x34aba3b5,0x61849965, + 0xde7aec95,0xe899778a,0xff4aa97f,0xe8f00f6e,0x010b0c6d,0xae971cb5 }, + { 0x3af788f1,0x1827eebc,0xe413fe2d,0xd46229ff,0x4741c9b4,0x8a15455b, + 0xf8e424eb,0x5f02e690,0xdae87712,0x40a1202e,0x64944f6d,0x49b3bda2 } }, + /* 112 */ + { { 0x035b2d69,0xd63c6067,0x6bed91b0,0xb507150d,0x7afb39b2,0x1f35f82f, + 0x16012b66,0xb9bd9c01,0xed0a5f50,0x00d97960,0x2716f7c9,0xed705451 }, + { 0x127abdb4,0x1576eff4,0xf01e701c,0x6850d698,0x3fc87e2f,0x9fa7d749, + 0xb0ce3e48,0x0b6bcc6f,0xf7d8c1c0,0xf4fbe1f5,0x02719cc6,0xcf75230e } }, + /* 113 */ + { { 0x722d94ed,0x6761d6c2,0x3718820e,0xd1ec3f21,0x25d0e7c6,0x65a40b70, + 0xbaf3cf31,0xd67f830e,0xb93ea430,0x633b3807,0x0bc96c69,0x17faa0ea }, + { 0xdf866b98,0xe6bf3482,0xa9db52d4,0x205c1ee9,0xff9ab869,0x51ef9bbd, + 0x75eeb985,0x3863dad1,0xd3cf442a,0xef216c3b,0xf9c8e321,0x3fb228e3 } }, + /* 114 */ + { { 0x0760ac07,0x94f9b70c,0x9d79bf4d,0xf3c9ccae,0xc5ffc83d,0x73cea084, + 0xdc49c38e,0xef50f943,0xbc9e7330,0xf467a2ae,0x44ea7fba,0x5ee534b6 }, + { 0x03609e7f,0x20cb6272,0x62fdc9f0,0x09844355,0x0f1457f7,0xaf5c8e58, + 0xb4b25941,0xd1f50a6c,0x2ec82395,0x77cb247c,0xda3dca33,0xa5f3e1e5 } }, + /* 115 */ + { { 0x7d85fa94,0x023489d6,0x2db9ce47,0x0ba40537,0xaed7aad1,0x0fdf7a1f, + 0x9a4ccb40,0xa57b0d73,0x5b18967c,0x48fcec99,0xb7274d24,0xf30b5b6e }, + { 0xc81c5338,0x7ccb4773,0xa3ed6bd0,0xb85639e6,0x1d56eada,0x7d9df95f, + 0x0a1607ad,0xe256d57f,0x957574d6,0x6da7ffdc,0x01c7a8c4,0x65f84046 } }, + /* 116 */ + { { 0xcba1e7f1,0x8d45d0cb,0x02b55f64,0xef0a08c0,0x17e19892,0x771ca31b, + 0x4885907e,0xe1843ecb,0x364ce16a,0x67797ebc,0x8df4b338,0x816d2b2d }, + { 0x39aa8671,0xe870b0e5,0xc102b5f5,0x9f0db3e4,0x1720c697,0x34296659, + 0x613c0d2a,0x0ad4c89e,0x418ddd61,0x1af900b2,0xd336e20e,0xe087ca72 } }, + /* 117 */ + { { 0xaba10079,0x222831ff,0x6d64fff2,0x0dc5f87b,0x3e8cb330,0x44547907, + 0x702a33fb,0xe815aaa2,0x5fba3215,0x338d6b2e,0x79f549c8,0x0f7535cb }, + { 0x2ee95923,0x471ecd97,0xc6d1c09f,0x1e868b37,0xc666ef4e,0x2bc7b8ec, + 0x808a4bfc,0xf5416589,0x3fbc4d2e,0xf23e9ee2,0x2d75125b,0x4357236c } }, + /* 118 */ + { { 0xba9cdb1b,0xfe176d95,0x2f82791e,0x45a1ca01,0x4de4cca2,0x97654af2, + 0x5cc4bcb9,0xbdbf9d0e,0xad97ac0a,0xf6a7df50,0x61359fd6,0xc52112b0 }, + { 0x4f05eae3,0x696d9ce3,0xe943ac2b,0x903adc02,0x0848be17,0xa9075347, + 0x2a3973e5,0x1e20f170,0x6feb67e9,0xe1aacc1c,0xe16bc6b9,0x2ca0ac32 } }, + /* 119 */ + { { 0xef871eb5,0xffea12e4,0xa8bf0a7a,0x94c2f25d,0x78134eaa,0x4d1e4c2a, + 0x0360fb10,0x11ed16fb,0x85fc11be,0x4029b6db,0xf4d390fa,0x5e9f7ab7 }, + { 0x30646612,0x5076d72f,0xdda1d0d8,0xa0afed1d,0x85a1d103,0x29022257, + 0x4e276bcd,0xcb499e17,0x51246c3d,0x16d1da71,0x589a0443,0xc72d56d3 } }, + /* 120 */ + { { 0xdae5bb45,0xdf5ffc74,0x261bd6dc,0x99068c4a,0xaa98ec7b,0xdc0afa7a, + 0xf121e96d,0xedd2ee00,0x1414045c,0x163cc7be,0x335af50e,0xb0b1bbce }, + { 0x01a06293,0xd440d785,0x6552e644,0xcdebab7c,0x8c757e46,0x48cb8dbc, + 0x3cabe3cb,0x81f9cf78,0xb123f59a,0xddd02611,0xeeb3784d,0x3dc7b88e } }, + /* 121 */ + { { 0xc4741456,0xe1b8d398,0x6032a121,0xa9dfa902,0x1263245b,0x1cbfc86d, + 0x5244718c,0xf411c762,0x05b0fc54,0x96521d54,0xdbaa4985,0x1afab46e }, + { 0x8674b4ad,0xa75902ba,0x5ad87d12,0x486b43ad,0x36e0d099,0x72b1c736, + 0xbb6cd6d6,0x39890e07,0x59bace4e,0x8128999c,0x7b535e33,0xd8da430b } }, + /* 122 */ + { { 0xc6b75791,0x39f65642,0x21806bfb,0x050947a6,0x1362ef84,0x0ca3e370, + 0x8c3d2391,0x9bc60aed,0x732e1ddc,0x9b488671,0xa98ee077,0x12d10d9e }, + { 0x3651b7dc,0xb6f2822d,0x80abd138,0x6345a5ba,0x472d3c84,0x62033262, + 0xacc57527,0xd54a1d40,0x424447cb,0x6ea46b3a,0x2fb1a496,0x5bc41057 } }, + /* 123 */ + { { 0xa751cd0e,0xe70c57a3,0xeba3c7d6,0x190d8419,0x9d47d55a,0xb1c3bee7, + 0xf912c6d8,0xda941266,0x407a6ad6,0x12e9aacc,0x6e838911,0xd6ce5f11 }, + { 0x70e1f2ce,0x063ca97b,0x8213d434,0xa3e47c72,0x84df810a,0xa016e241, + 0xdfd881a4,0x688ad7b0,0xa89bf0ad,0xa37d99fc,0xa23c2d23,0xd8e3f339 } }, + /* 124 */ + { { 0x750bed6f,0xbdf53163,0x83e68b0a,0x808abc32,0x5bb08a33,0x85a36627, + 0x6b0e4abe,0xf72a3a0f,0xfaf0c6ad,0xf7716d19,0x5379b25f,0x22dcc020 }, + { 0xf9a56e11,0x7400bf8d,0x56a47f21,0x6cb8bad7,0x7a6eb644,0x7c97176f, + 0xd1f5b646,0xe8fd84f7,0x44ddb054,0x98320a94,0x1dde86f5,0x07071ba3 } }, + /* 125 */ + { { 0x98f8fcb9,0x6fdfa0e5,0x94d0d70c,0x89cec8e0,0x106d20a8,0xa0899397, + 0xba8acc9c,0x915bfb9a,0x5507e01c,0x1370c94b,0x8a821ffb,0x83246a60 }, + { 0xbe3c378f,0xa8273a9f,0x35a25be9,0x7e544789,0x4dd929d7,0x6cfa4972, + 0x365bd878,0x987fed9d,0x5c29a7ae,0x4982ac94,0x5ddd7ec5,0x4589a5d7 } }, + /* 126 */ + { { 0xa95540a9,0x9fabb174,0x0162c5b0,0x7cfb886f,0xea3dee18,0x17be766b, + 0xe88e624c,0xff7da41f,0x8b919c38,0xad0b71eb,0xf31ff9a9,0x86a522e0 }, + { 0x868bc259,0xbc8e6f72,0x3ccef9e4,0x6130c638,0x9a466555,0x09f1f454, + 0x19b2bfb4,0x8e6c0f09,0x0ca7bb22,0x945c46c9,0x4dafb67b,0xacd87168 } }, + /* 127 */ + { { 0x10c53841,0x090c72ca,0x55a4fced,0xc20ae01b,0xe10234ad,0x03f7ebd5, + 0x85892064,0xb3f42a6a,0xb4a14722,0xbdbc30c0,0x8ca124cc,0x971bc437 }, + { 0x517ff2ff,0x6f79f46d,0xecba947b,0x6a9c96e2,0x62925122,0x5e79f2f4, + 0x6a4e91f1,0x30a96bb1,0x2d4c72da,0x1147c923,0x5811e4df,0x65bc311f } }, + /* 128 */ + { { 0x139b3239,0x87c7dd7d,0x4d833bae,0x8b57824e,0x9fff0015,0xbcbc4878, + 0x909eaf1a,0x8ffcef8b,0xf1443a78,0x9905f4ee,0xe15cbfed,0x020dd4a2 }, + { 0xa306d695,0xca2969ec,0xb93caf60,0xdf940cad,0x87ea6e39,0x67f7fab7, + 0xf98c4fe5,0x0d0ee10f,0xc19cb91e,0xc646879a,0x7d1d7ab4,0x4b4ea50c } }, + /* 129 */ + { { 0x7a0db57e,0x19e40945,0x9a8c9702,0xe6017cad,0x1be5cff9,0xdbf739e5, + 0xa7a938a2,0x3646b3cd,0x68350dfc,0x04511085,0x56e098b5,0xad3bd6f3 }, + { 0xee2e3e3e,0x935ebabf,0x473926cb,0xfbd01702,0x9e9fb5aa,0x7c735b02, + 0x2e3feff0,0xc52a1b85,0x046b405a,0x9199abd3,0x39039971,0xe306fcec } }, + /* 130 */ + { { 0x23e4712c,0xd6d9aec8,0xc3c198ee,0x7ca8376c,0x31bebd8a,0xe6d83187, + 0xd88bfef3,0xed57aff3,0xcf44edc7,0x72a645ee,0x5cbb1517,0xd4e63d0b }, + { 0xceee0ecf,0x98ce7a1c,0x5383ee8e,0x8f012633,0xa6b455e8,0x3b879078, + 0xc7658c06,0xcbcd3d96,0x0783336a,0x721d6fe7,0x5a677136,0xf21a7263 } }, + /* 131 */ + { { 0x9586ba11,0x19d8b3cd,0x8a5c0480,0xd9e0aeb2,0x2230ef5c,0xe4261dbf, + 0x02e6bf09,0x095a9dee,0x80dc7784,0x8963723c,0x145157b1,0x5c97dbaf }, + { 0x4bc4503e,0x97e74434,0x85a6b370,0x0fb1cb31,0xcd205d4b,0x3e8df2be, + 0xf8f765da,0x497dd1bc,0x6c988a1a,0x92ef95c7,0x64dc4cfa,0x3f924baa } }, + /* 132 */ + { { 0x7268b448,0x6bf1b8dd,0xefd79b94,0xd4c28ba1,0xe4e3551f,0x2fa1f8c8, + 0x5c9187a9,0x769e3ad4,0x40326c0d,0x28843b4d,0x50d5d669,0xfefc8094 }, + { 0x90339366,0x30c85bfd,0x5ccf6c3a,0x4eeb56f1,0x28ccd1dc,0x0e72b149, + 0xf2ce978e,0x73ee85b5,0x3165bb23,0xcdeb2bf3,0x4e410abf,0x8106c923 } }, + /* 133 */ + { { 0x7d02f4ee,0xc8df0161,0x18e21225,0x8a781547,0x6acf9e40,0x4ea895eb, + 0x6e5a633d,0x8b000cb5,0x7e981ffb,0xf31d86d5,0x4475bc32,0xf5c8029c }, + { 0x1b568973,0x764561ce,0xa62996ec,0x2f809b81,0xda085408,0x9e513d64, + 0xe61ce309,0xc27d815d,0x272999e0,0x0da6ff99,0xfead73f7,0xbd284779 } }, + /* 134 */ + { { 0x9b1cdf2b,0x6033c2f9,0xbc5fa151,0x2a99cf06,0x12177b3b,0x7d27d259, + 0xc4485483,0xb1f15273,0x102e2297,0x5fd57d81,0xc7f6acb7,0x3d43e017 }, + { 0x3a70eb28,0x41a8bb0b,0x3e80b06b,0x67de2d8e,0x70c28de5,0x09245a41, + 0xa7b26023,0xad7dbcb1,0x2cbc6c1e,0x70b08a35,0x9b33041f,0xb504fb66 } }, + /* 135 */ + { { 0xf97a27c2,0xa8e85ab5,0xc10a011b,0x6ac5ec8b,0xffbcf161,0x55745533, + 0x65790a60,0x01780e85,0x99ee75b0,0xe451bf85,0x39c29881,0x8907a63b }, + { 0x260189ed,0x76d46738,0x47bd35cb,0x284a4436,0x20cab61e,0xd74e8c40, + 0x416cf20a,0x6264bf8c,0x5fd820ce,0xfa5a6c95,0xf24bb5fc,0xfa7154d0 } }, + /* 136 */ + { { 0x9b3f5034,0x18482cec,0xcd9e68fd,0x962d445a,0x95746f23,0x266fb1d6, + 0x58c94a4b,0xc66ade5a,0xed68a5b6,0xdbbda826,0x7ab0d6ae,0x05664a4d }, + { 0x025e32fc,0xbcd4fe51,0xa96df252,0x61a5aebf,0x31592a31,0xd88a07e2, + 0x98905517,0x5d9d94de,0x5fd440e7,0x96bb4010,0xe807db4c,0x1b0c47a2 } }, + /* 137 */ + { { 0x08223878,0x5c2a6ac8,0xe65a5558,0xba08c269,0x9bbc27fd,0xd22b1b9b, + 0x72b9607d,0x919171bf,0xe588dc58,0x9ab455f9,0x23662d93,0x6d54916e }, + { 0x3b1de0c1,0x8da8e938,0x804f278f,0xa84d186a,0xd3461695,0xbf4988cc, + 0xe10eb0cb,0xf5eae3be,0xbf2a66ed,0x1ff8b68f,0xc305b570,0xa68daf67 } }, + /* 138 */ + { { 0x44b2e045,0xc1004cff,0x4b1c05d4,0x91b5e136,0x88a48a07,0x53ae4090, + 0xea11bb1a,0x73fb2995,0x3d93a4ea,0x32048570,0x3bfc8a5f,0xcce45de8 }, + { 0xc2b3106e,0xaff4a97e,0xb6848b4f,0x9069c630,0xed76241c,0xeda837a6, + 0x6cc3f6cf,0x8a0daf13,0x3da018a8,0x199d049d,0xd9093ba3,0xf867c6b1 } }, + /* 139 */ + { { 0x56527296,0xe4d42a56,0xce71178d,0xae26c73d,0x6c251664,0x70a0adac, + 0x5dc0ae1d,0x813483ae,0xdaab2daf,0x7574eacd,0xc2d55f4f,0xc56b52dc }, + { 0x95f32923,0x872bc167,0x5bdd2a89,0x4be17581,0xa7699f00,0x9b57f1e7, + 0x3ac2de02,0x5fcd9c72,0x92377739,0x83af3ba1,0xfc50b97f,0xa64d4e2b } }, + /* 140 */ + { { 0x0e552b40,0x2172dae2,0xd34d52e8,0x62f49725,0x07958f98,0x7930ee40, + 0x751fdd74,0x56da2a90,0xf53e48c3,0xf1192834,0x8e53c343,0x34d2ac26 }, + { 0x13111286,0x1073c218,0xda9d9827,0x201dac14,0xee95d378,0xec2c29db, + 0x1f3ee0b1,0x9316f119,0x544ce71c,0x7890c9f0,0x27612127,0xd77138af } }, + /* 141 */ + { { 0x3b4ad1cd,0x78045e6d,0x4aa49bc1,0xcd86b94e,0xfd677a16,0x57e51f1d, + 0xfa613697,0xd9290935,0x34f4d893,0x7a3f9593,0x5d5fcf9b,0x8c9c248b }, + { 0x6f70d4e9,0x9f23a482,0x63190ae9,0x17273454,0x5b081a48,0x4bdd7c13, + 0x28d65271,0x1e2de389,0xe5841d1f,0x0bbaaa25,0x746772e5,0xc4c18a79 } }, + /* 142 */ + { { 0x593375ac,0x10ee2681,0x7dd5e113,0x4f3288be,0x240f3538,0x9a97b2fb, + 0x1de6b1e2,0xfa11089f,0x1351bc58,0x516da562,0x2dfa85b5,0x573b6119 }, + { 0x6cba7df5,0x89e96683,0x8c28ab40,0xf299be15,0xad43fcbf,0xe91c9348, + 0x9a1cefb3,0xe9bbc7cc,0x738b2775,0xc8add876,0x775eaa01,0x6e3b1f2e } }, + /* 143 */ + { { 0xb677788b,0x0365a888,0x3fd6173c,0x634ae8c4,0x9e498dbe,0x30498761, + 0xc8f779ab,0x08c43e6d,0x4c09aca9,0x068ae384,0x2018d170,0x2380c70b }, + { 0xa297c5ec,0xcf77fbc3,0xca457948,0xdacbc853,0x336bec7e,0x3690de04, + 0x14eec461,0x26bbac64,0x1f713abf,0xd1c23c7e,0xe6fd569e,0xf08bbfcd } }, + /* 144 */ + { { 0x84770ee3,0x5f8163f4,0x744a1706,0x0e0c7f94,0xe1b2d46d,0x9c8f05f7, + 0xd01fd99a,0x417eafe7,0x11440e5b,0x2ba15df5,0x91a6fbcf,0xdc5c552a }, + { 0xa270f721,0x86271d74,0xa004485b,0x32c0a075,0x8defa075,0x9d1a87e3, + 0xbf0d20fe,0xb590a7ac,0x8feda1f5,0x430c41c2,0x58f6ec24,0x454d2879 } }, + /* 145 */ + { { 0x7c525435,0x52b7a635,0x37c4bdbc,0x3d9ef57f,0xdffcc475,0x2bb93e9e, + 0x7710f3be,0xf7b8ba98,0x21b727de,0x42ee86da,0x2e490d01,0x55ac3f19 }, + { 0xc0c1c390,0x487e3a6e,0x446cde7b,0x036fb345,0x496ae951,0x089eb276, + 0x71ed1234,0xedfed4d9,0x900f0b46,0x661b0dd5,0x8582f0d3,0x11bd6f1b } }, + /* 146 */ + { { 0x076bc9d1,0x5cf9350f,0xcf3cd2c3,0x15d903be,0x25af031c,0x21cfc8c2, + 0x8b1cc657,0xe0ad3248,0x70014e87,0xdd9fb963,0x297f1658,0xf0f3a5a1 }, + { 0xf1f703aa,0xbb908fba,0x2f6760ba,0x2f9cc420,0x66a38b51,0x00ceec66, + 0x05d645da,0x4deda330,0xf7de3394,0xb9cf5c72,0x1ad4c906,0xaeef6502 } }, + /* 147 */ + { { 0x7a19045d,0x0583c8b1,0xd052824c,0xae7c3102,0xff6cfa58,0x2a234979, + 0x62c733c0,0xfe9dffc9,0x9c0c4b09,0x3a7fa250,0x4fe21805,0x516437bb }, + { 0xc2a23ddb,0x9454e3d5,0x289c104e,0x0726d887,0x4fd15243,0x8977d918, + 0x6d7790ba,0xc559e73f,0x465af85f,0x8fd3e87d,0x5feee46b,0xa2615c74 } }, + /* 148 */ + { { 0x4335167d,0xc8d607a8,0xe0f5c887,0x8b42d804,0x398d11f9,0x5f9f13df, + 0x20740c67,0x5aaa5087,0xa3d9234b,0x83da9a6a,0x2a54bad1,0xbd3a5c4e }, + { 0x2db0f658,0xdd13914c,0x5a3f373a,0x29dcb66e,0x5245a72b,0xbfd62df5, + 0x91e40847,0x19d18023,0xb136b1ae,0xd9df74db,0x3f93bc5b,0x72a06b6b } }, + /* 149 */ + { { 0xad19d96f,0x6da19ec3,0xfb2a4099,0xb342daa4,0x662271ea,0x0e61633a, + 0xce8c054b,0x3bcece81,0x8bd62dc6,0x7cc8e061,0xee578d8b,0xae189e19 }, + { 0xdced1eed,0x73e7a25d,0x7875d3ab,0xc1257f0a,0x1cfef026,0x2cb2d5a2, + 0xb1fdf61c,0xd98ef39b,0x24e83e6c,0xcd8e6f69,0xc7b7088b,0xd71e7076 } }, + /* 150 */ + { { 0x9d4245bf,0x33936830,0x2ac2953b,0x22d96217,0x56c3c3cd,0xb3bf5a82, + 0x0d0699e8,0x50c9be91,0x8f366459,0xec094463,0x513b7c35,0x6c056dba }, + { 0x045ab0e3,0x687a6a83,0x445c9295,0x8d40b57f,0xa16f5954,0x0f345048, + 0x3d8f0a87,0x64b5c639,0x9f71c5e2,0x106353a2,0x874f0dd4,0xdd58b475 } }, + /* 151 */ + { { 0x62230c72,0x67ec084f,0x481385e3,0xf14f6cca,0x4cda7774,0xf58bb407, + 0xaa2dbb6b,0xe15011b1,0x0c035ab1,0xd488369d,0x8245f2fd,0xef83c24a }, + { 0x9fdc2538,0xfb57328f,0x191fe46a,0x79808293,0x32ede548,0xe28f5c44, + 0xea1a022c,0x1b3cda99,0x3df2ec7f,0x39e639b7,0x760e9a18,0x77b6272b } }, + /* 152 */ + { { 0xa65d56d5,0x2b1d51bd,0x7ea696e0,0x3a9b71f9,0x9904f4c4,0x95250ecc, + 0xe75774b7,0x8bc4d6eb,0xeaeeb9aa,0x0e343f8a,0x930e04cb,0xc473c1d1 }, + { 0x064cd8ae,0x282321b1,0x5562221c,0xf4b4371e,0xd1bf1221,0xc1cc81ec, + 0xe2c8082f,0xa52a07a9,0xba64a958,0x350d8e59,0x6fb32c9a,0x29e4f3de } }, + /* 153 */ + { { 0xba89aaa5,0x0aa9d56c,0xc4c6059e,0xf0208ac0,0xbd6ddca4,0x7400d9c6, + 0xf2c2f74a,0xb384e475,0xb1562dd3,0x4c1061fc,0x2e153b8d,0x3924e248 }, + { 0x849808ab,0xf38b8d98,0xa491aa36,0x29bf3260,0x88220ede,0x85159ada, + 0xbe5bc422,0x8b47915b,0xd7300967,0xa934d72e,0x2e515d0d,0xc4f30398 } }, + /* 154 */ + { { 0x1b1de38b,0xe3e9ee42,0x42636760,0xa124e25a,0x90165b1a,0x90bf73c0, + 0x146434c5,0x21802a34,0x2e1fa109,0x54aa83f2,0xed9c51e9,0x1d4bd03c }, + { 0x798751e6,0xc2d96a38,0x8c3507f5,0xed27235f,0xc8c24f88,0xb5fb80e2, + 0xd37f4f78,0xf873eefa,0xf224ba96,0x7229fd74,0x9edd7149,0x9dcd9199 } }, + /* 155 */ + { { 0x4e94f22a,0xee9f81a6,0xf71ec341,0xe5609892,0xa998284e,0x6c818ddd, + 0x3b54b098,0x9fd47295,0x0e8a7cc9,0x47a6ac03,0xb207a382,0xde684e5e }, + { 0x2b6b956b,0x4bdd1ecd,0xf01b3583,0x09084414,0x55233b14,0xe2f80b32, + 0xef5ebc5e,0x5a0fec54,0xbf8b29a2,0x74cf25e6,0x7f29e014,0x1c757fa0 } }, + /* 156 */ + { { 0xeb0fdfe4,0x1bcb5c4a,0xf0899367,0xd7c649b3,0x05bc083b,0xaef68e3f, + 0xa78aa607,0x57a06e46,0x21223a44,0xa2136ecc,0x52f5a50b,0x89bd6484 }, + { 0x4455f15a,0x724411b9,0x08a9c0fd,0x23dfa970,0x6db63bef,0x7b0da4d1, + 0xfb162443,0x6f8a7ec1,0xe98284fb,0xc1ac9cee,0x33566022,0x085a582b } }, + /* 157 */ + { { 0xec1f138a,0x15cb61f9,0x668f0c28,0x11c9a230,0xdf93f38f,0xac829729, + 0x4048848d,0xcef25698,0x2bba8fbf,0x3f686da0,0x111c619a,0xed5fea78 }, + { 0xd6d1c833,0x9b4f73bc,0x86e7bf80,0x50951606,0x042b1d51,0xa2a73508, + 0x5fb89ec2,0x9ef6ea49,0x5ef8b892,0xf1008ce9,0x9ae8568b,0x78a7e684 } }, + /* 158 */ + { { 0x10470cd8,0x3fe83a7c,0xf86df000,0x92734682,0xda9409b5,0xb5dac06b, + 0x94939c5f,0x1e7a9660,0x5cc116dc,0xdec6c150,0x66bac8cc,0x1a52b408 }, + { 0x6e864045,0x5303a365,0x9139efc1,0x45eae72a,0x6f31d54f,0x83bec646, + 0x6e958a6d,0x2fb4a86f,0x4ff44030,0x6760718e,0xe91ae0df,0x008117e3 } }, + /* 159 */ + { { 0x384310a2,0x5d5833ba,0x1fd6c9fc,0xbdfb4edc,0x849c4fb8,0xb9a4f102, + 0x581c1e1f,0xe5fb239a,0xd0a9746d,0xba44b2e7,0x3bd942b9,0x78f7b768 }, + { 0xc87607ae,0x076c8ca1,0xd5caaa7e,0x82b23c2e,0x2763e461,0x6a581f39, + 0x3886df11,0xca8a5e4a,0x264e7f22,0xc87e90cf,0x215cfcfc,0x04f74870 } }, + /* 160 */ + { { 0x141d161c,0x5285d116,0x93c4ed17,0x67cd2e0e,0x7c36187e,0x12c62a64, + 0xed2584ca,0xf5329539,0x42fbbd69,0xc4c777c4,0x1bdfc50a,0x107de776 }, + { 0xe96beebd,0x9976dcc5,0xa865a151,0xbe2aff95,0x9d8872af,0x0e0a9da1, + 0xa63c17cc,0x5e357a3d,0xe15cc67c,0xd31fdfd8,0x7970c6d8,0xc44bbefd } }, + /* 161 */ + { { 0x4c0c62f1,0x703f83e2,0x4e195572,0x9b1e28ee,0xfe26cced,0x6a82858b, + 0xc43638fa,0xd381c84b,0xa5ba43d8,0x94f72867,0x10b82743,0x3b4a783d }, + { 0x7576451e,0xee1ad7b5,0x14b6b5c8,0xc3d0b597,0xfcacc1b8,0x3dc30954, + 0x472c9d7b,0x55df110e,0x02f8a328,0x97c86ed7,0x88dc098f,0xd0433413 } }, + /* 162 */ + { { 0x2ca8f2fe,0x1a60d152,0x491bd41f,0x61640948,0x58dfe035,0x6dae29a5, + 0x278e4863,0x9a615bea,0x9ad7c8e5,0xbbdb4477,0x2ceac2fc,0x1c706630 }, + { 0x99699b4b,0x5e2b54c6,0x239e17e8,0xb509ca6d,0xea063a82,0x728165fe, + 0xb6a22e02,0x6b5e609d,0xb26ee1df,0x12813905,0x439491fa,0x07b9f722 } }, + /* 163 */ + { { 0x48ff4e49,0x1592ec14,0x6d644129,0x3e4e9f17,0x1156acc0,0x7acf8288, + 0xbb092b0b,0x5aa34ba8,0x7d38393d,0xcd0f9022,0xea4f8187,0x416724dd }, + { 0xc0139e73,0x3c4e641c,0x91e4d87d,0xe0fe46cf,0xcab61f8a,0xedb3c792, + 0xd3868753,0x4cb46de4,0x20f1098a,0xe449c21d,0xf5b8ea6e,0x5e5fd059 } }, + /* 164 */ + { { 0x75856031,0x7fcadd46,0xeaf2fbd0,0x89c7a4cd,0x7a87c480,0x1af523ce, + 0x61d9ae90,0xe5fc1095,0xbcdb95f5,0x3fb5864f,0xbb5b2c7d,0xbeb5188e }, + { 0x3ae65825,0x3d1563c3,0x0e57d641,0x116854c4,0x1942ebd3,0x11f73d34, + 0xc06955b3,0x24dc5904,0x995a0a62,0x8a0d4c83,0x5d577b7d,0xfb26b86d } }, + /* 165 */ + { { 0xc686ae17,0xc53108e7,0xd1c1da56,0x9090d739,0x9aec50ae,0x4583b013, + 0xa49a6ab2,0xdd9a088b,0xf382f850,0x28192eea,0xf5fe910e,0xcc8df756 }, + { 0x9cab7630,0x877823a3,0xfb8e7fc1,0x64984a9a,0x364bfc16,0x5448ef9c, + 0xc44e2a9a,0xbbb4f871,0x435c95e9,0x901a41ab,0xaaa50a06,0xc6c23e5f } }, + /* 166 */ + { { 0x9034d8dd,0xb78016c1,0x0b13e79b,0x856bb44b,0xb3241a05,0x85c6409a, + 0x2d78ed21,0x8d2fe19a,0x726eddf2,0xdcc7c26d,0x25104f04,0x3ccaff5f }, + { 0x6b21f843,0x397d7edc,0xe975de4c,0xda88e4dd,0x4f5ab69e,0x5273d396, + 0x9aae6cc0,0x537680e3,0x3e6f9461,0xf749cce5,0x957bffd3,0x021ddbd9 } }, + /* 167 */ + { { 0x777233cf,0x7b64585f,0x0942a6f0,0xfe6771f6,0xdfe6eef0,0x636aba7a, + 0x86038029,0x63bbeb56,0xde8fcf36,0xacee5842,0xd4a20524,0x48d9aa99 }, + { 0x0da5e57a,0xcff7a74c,0xe549d6c9,0xc232593c,0xf0f2287b,0x68504bcc, + 0xbc8360b5,0x6d7d098d,0x5b402f41,0xeac5f149,0xb87d1bf1,0x61936f11 } }, + /* 168 */ + { { 0xb8153a9d,0xaa9da167,0x9e83ecf0,0xa49fe3ac,0x1b661384,0x14c18f8e, + 0x38434de1,0x61c24dab,0x283dae96,0x3d973c3a,0x82754fc9,0xc99baa01 }, + { 0x4c26b1e3,0x477d198f,0xa7516202,0x12e8e186,0x362addfa,0x386e52f6, + 0xc3962853,0x31e8f695,0x6aaedb60,0xdec2af13,0x29cf74ac,0xfcfdb4c6 } }, + /* 169 */ + { { 0xcca40298,0x6b3ee958,0xf2f5d195,0xc3878153,0xed2eae5b,0x0c565630, + 0x3a697cf2,0xd089b37e,0xad5029ea,0xc2ed2ac7,0x0f0dda6a,0x7e5cdfad }, + { 0xd9b86202,0xf98426df,0x4335e054,0xed1960b1,0x3f14639e,0x1fdb0246, + 0x0db6c670,0x17f709c3,0x773421e1,0xbfc687ae,0x26c1a8ac,0x13fefc4a } }, + /* 170 */ + { { 0x7ffa0a5f,0xe361a198,0xc63fe109,0xf4b26102,0x6c74e111,0x264acbc5, + 0x77abebaf,0x4af445fa,0x24cddb75,0x448c4fdd,0x44506eea,0x0b13157d }, + { 0x72e9993d,0x22a6b159,0x85e5ecbe,0x2c3c57e4,0xfd83e1a1,0xa673560b, + 0xc3b8c83b,0x6be23f82,0x40bbe38e,0x40b13a96,0xad17399b,0x66eea033 } }, + /* 171 */ + { { 0xb4c6c693,0x49fc6e95,0x36af7d38,0xefc735de,0x35fe42fc,0xe053343d, + 0x6a9ab7c3,0xf0aa427c,0x4a0fcb24,0xc79f0436,0x93ebbc50,0x16287243 }, + { 0x16927e1e,0x5c3d6bd0,0x673b984c,0x40158ed2,0x4cd48b9a,0xa7f86fc8, + 0x60ea282d,0x1643eda6,0xe2a1beed,0x45b393ea,0x19571a94,0x664c839e } }, + /* 172 */ + { { 0x27eeaf94,0x57745750,0xea99e1e7,0x2875c925,0x5086adea,0xc127e7ba, + 0x86fe424f,0x765252a0,0x2b6c0281,0x1143cc6c,0xd671312d,0xc9bb2989 }, + { 0x51acb0a5,0x880c337c,0xd3c60f78,0xa3710915,0x9262b6ed,0x496113c0, + 0x9ce48182,0x5d25d9f8,0xb3813586,0x53b6ad72,0x4c0e159c,0x0ea3bebc } }, + /* 173 */ + { { 0xc5e49bea,0xcaba450a,0x7c05da59,0x684e5415,0xde7ac36c,0xa2e9cab9, + 0x2e6f957b,0x4ca79b5f,0x09b817b1,0xef7b0247,0x7d89df0f,0xeb304990 }, + { 0x46fe5096,0x508f7307,0x2e04eaaf,0x695810e8,0x3512f76c,0x88ef1bd9, + 0x3ebca06b,0x77661351,0xccf158b7,0xf7d4863a,0x94ee57da,0xb2a81e44 } }, + /* 174 */ + { { 0x6d53e6ba,0xff288e5b,0x14484ea2,0xa90de1a9,0xed33c8ec,0x2fadb60c, + 0x28b66a40,0x579d6ef3,0xec24372d,0x4f2dd6dd,0x1d66ec7d,0xe9e33fc9 }, + { 0x039eab6e,0x110899d2,0x3e97bb5e,0xa31a667a,0xcfdce68e,0x6200166d, + 0x5137d54b,0xbe83ebae,0x4800acdf,0x085f7d87,0x0c6f8c86,0xcf4ab133 } }, + /* 175 */ + { { 0x931e08fb,0x03f65845,0x1506e2c0,0x6438551e,0x9c36961f,0x5791f0dc, + 0xe3dcc916,0x68107b29,0xf495d2ca,0x83242374,0x6ee5895b,0xd8cfb663 }, + { 0xa0349b1b,0x525e0f16,0x4a0fab86,0x33cd2c6c,0x2af8dda9,0x46c12ee8, + 0x71e97ad3,0x7cc424ba,0x37621eb0,0x69766ddf,0xa5f0d390,0x95565f56 } }, + /* 176 */ + { { 0x1a0f5e94,0xe0e7bbf2,0x1d82d327,0xf771e115,0xceb111fa,0x10033e3d, + 0xd3426638,0xd269744d,0x00d01ef6,0xbdf2d9da,0xa049ceaf,0x1cb80c71 }, + { 0x9e21c677,0x17f18328,0x19c8f98b,0x6452af05,0x80b67997,0x35b9c5f7, + 0x40f8f3d4,0x5c2e1cbe,0x66d667ca,0x43f91656,0xcf9d6e79,0x9faaa059 } }, + /* 177 */ + { { 0x0a078fe6,0x8ad24618,0x464fd1dd,0xf6cc73e6,0xc3e37448,0x4d2ce34d, + 0xe3271b5f,0x624950c5,0xefc5af72,0x62910f5e,0xaa132bc6,0x8b585bf8 }, + { 0xa839327f,0x11723985,0x4aac252f,0x34e2d27d,0x6296cc4e,0x402f59ef, + 0x47053de9,0x00ae055c,0x28b4f09b,0xfc22a972,0xfa0c180e,0xa9e86264 } }, + /* 178 */ + { { 0xbc310ecc,0x0b7b6224,0x67fa14ed,0x8a1a74f1,0x7214395c,0x87dd0960, + 0xf5c91128,0xdf1b3d09,0x86b264a8,0x39ff23c6,0x3e58d4c5,0xdc2d49d0 }, + { 0xa9d6f501,0x2152b7d3,0xc04094f7,0xf4c32e24,0xd938990f,0xc6366596, + 0x94fb207f,0x084d078f,0x328594cb,0xfd99f1d7,0xcb2d96b3,0x36defa64 } }, + /* 179 */ + { { 0x13ed7cbe,0x4619b781,0x9784bd0e,0x95e50015,0x2c7705fe,0x2a32251c, + 0x5f0dd083,0xa376af99,0x0361a45b,0x55425c6c,0x1f291e7b,0x812d2cef }, + { 0x5fd94972,0xccf581a0,0xe56dc383,0x26e20e39,0x63dbfbf0,0x0093685d, + 0x36b8c575,0x1fc164cc,0x390ef5e7,0xb9c5ab81,0x26908c66,0x40086beb } }, + /* 180 */ + { { 0x37e3c115,0xe5e54f79,0xc1445a8a,0x69b8ee8c,0xb7659709,0x79aedff2, + 0x1b46fbe6,0xe288e163,0xd18d7bb7,0xdb4844f0,0x48aa6424,0xe0ea23d0 }, + { 0xf3d80a73,0x714c0e4e,0x3bd64f98,0x87a0aa9e,0x2ec63080,0x8844b8a8, + 0x255d81a3,0xe0ac9c30,0x455397fc,0x86151237,0x2f820155,0x0b979464 } }, + /* 181 */ + { { 0x4ae03080,0x127a255a,0x580a89fb,0x232306b4,0x6416f539,0x04e8cd6a, + 0x13b02a0e,0xaeb70dee,0x4c09684a,0xa3038cf8,0x28e433ee,0xa710ec3c }, + { 0x681b1f7d,0x77a72567,0x2fc28170,0x86fbce95,0xf5735ac8,0xd3408683, + 0x6bd68e93,0x3a324e2a,0xc027d155,0x7ec74353,0xd4427177,0xab60354c } }, + /* 182 */ + { { 0xef4c209d,0x32a5342a,0x08d62704,0x2ba75274,0xc825d5fe,0x4bb4af6f, + 0xd28e7ff1,0x1c3919ce,0xde0340f6,0x1dfc2fdc,0x29f33ba9,0xc6580baf }, + { 0x41d442cb,0xae121e75,0x3a4724e4,0x4c7727fd,0x524f3474,0xe556d6a4, + 0x785642a2,0x87e13cc7,0xa17845fd,0x182efbb1,0x4e144857,0xdcec0cf1 } }, + /* 183 */ + { { 0xe9539819,0x1cb89541,0x9d94dbf1,0xc8cb3b4f,0x417da578,0x1d353f63, + 0x8053a09e,0xb7a697fb,0xc35d8b78,0x8d841731,0xb656a7a9,0x85748d6f }, + { 0xc1859c5d,0x1fd03947,0x535d22a2,0x6ce965c1,0x0ca3aadc,0x1966a13e, + 0x4fb14eff,0x9802e41d,0x76dd3fcd,0xa9048cbb,0xe9455bba,0x89b182b5 } }, + /* 184 */ + { { 0x43360710,0xd777ad6a,0x55e9936b,0x841287ef,0x04a21b24,0xbaf5c670, + 0x35ad86f1,0xf2c0725f,0xc707e72e,0x338fa650,0xd8883e52,0x2bf8ed2e }, + { 0xb56e0d6a,0xb0212cf4,0x6843290c,0x50537e12,0x98b3dc6f,0xd8b184a1, + 0x0210b722,0xd2be9a35,0x559781ee,0x407406db,0x0bc18534,0x5a78d591 } }, + /* 185 */ + { { 0xd748b02c,0x4d57aa2a,0xa12b3b95,0xbe5b3451,0x64711258,0xadca7a45, + 0x322153db,0x597e091a,0x32eb1eab,0xf3271006,0x2873f301,0xbd9adcba }, + { 0x38543f7f,0xd1dc79d1,0x921b1fef,0x00022092,0x1e5df8ed,0x86db3ef5, + 0x9e6b944a,0x888cae04,0x791a32b4,0x71bd29ec,0xa6d1c13e,0xd3516206 } }, + /* 186 */ + { { 0x55924f43,0x2ef6b952,0x4f9de8d5,0xd2f401ae,0xadc68042,0xfc73e8d7, + 0x0d9d1bb4,0x627ea70c,0xbbf35679,0xc3bb3e3e,0xd882dee4,0x7e8a254a }, + { 0xb5924407,0x08906f50,0xa1ad444a,0xf14a0e61,0x65f3738e,0xaa0efa21, + 0xae71f161,0xd60c7dd6,0xf175894d,0x9e8390fa,0x149f4c00,0xd115cd20 } }, + /* 187 */ + { { 0xa52abf77,0x2f2e2c1d,0x54232568,0xc2a0dca5,0x54966dcc,0xed423ea2, + 0xcd0dd039,0xe48c93c7,0x176405c7,0x1e54a225,0x70d58f2e,0x1efb5b16 }, + { 0x94fb1471,0xa751f9d9,0x67d2941d,0xfdb31e1f,0x53733698,0xa6c74eb2, + 0x89a0f64a,0xd3155d11,0xa4b8d2b6,0x4414cfe4,0xf7a8e9e3,0x8d5a4be8 } }, + /* 188 */ + { { 0x52669e98,0x5c96b4d4,0x8fd42a03,0x4547f922,0xd285174e,0xcf5c1319, + 0x064bffa0,0x805cd1ae,0x246d27e7,0x50e8bc4f,0xd5781e11,0xf89ef98f }, + { 0xdee0b63f,0xb4ff95f6,0x222663a4,0xad850047,0x4d23ce9c,0x02691860, + 0x50019f59,0x3e5309ce,0x69a508ae,0x27e6f722,0x267ba52c,0xe9376652 } }, + /* 189 */ + { { 0xc0368708,0xa04d289c,0x5e306e1d,0xc458872f,0x33112fea,0x76fa23de, + 0x6efde42e,0x718e3974,0x1d206091,0xf0c98cdc,0x14a71987,0x5fa3ca62 }, + { 0xdcaa9f2a,0xeee8188b,0x589a860d,0x312cc732,0xc63aeb1f,0xf9808dd6, + 0x4ea62b53,0x70fd43db,0x890b6e97,0x2c2bfe34,0xfa426aa6,0x105f863c } }, + /* 190 */ + { { 0xb38059ad,0x0b29795d,0x90647ea0,0x5686b77e,0xdb473a3e,0xeff0470e, + 0xf9b6d1e2,0x278d2340,0xbd594ec7,0xebbff95b,0xd3a7f23d,0xf4b72334 }, + { 0xa5a83f0b,0x2a285980,0x9716a8b3,0x0786c41a,0x22511812,0x138901bd, + 0xe2fede6e,0xd1b55221,0xdf4eb590,0x0806e264,0x762e462e,0x6c4c897e } }, + /* 191 */ + { { 0xb4b41d9d,0xd10b905f,0x4523a65b,0x826ca466,0xb699fa37,0x535bbd13, + 0x73bc8f90,0x5b9933d7,0xcd2118ad,0x9332d61f,0xd4a65fd0,0x158c693e }, + { 0xe6806e63,0x4ddfb2a8,0xb5de651b,0xe31ed3ec,0x819bc69a,0xf9460e51, + 0x2c76b1f8,0x6229c0d6,0x901970a3,0xbb78f231,0x9cee72b8,0x31f3820f } }, + /* 192 */ + { { 0xc09e1c72,0xe931caf2,0x12990cf4,0x0715f298,0x943262d8,0x33aad81d, + 0x73048d3f,0x5d292b7a,0xdc7415f6,0xb152aaa4,0x0fd19587,0xc3d10fd9 }, + { 0x75ddadd0,0xf76b35c5,0x1e7b694c,0x9f5f4a51,0xc0663025,0x2f1ab7eb, + 0x920260b0,0x01c9cc87,0x05d39da6,0xc4b1f61a,0xeb4a9c4e,0x6dcd76c4 } }, + /* 193 */ + { { 0xfdc83f01,0x0ba0916f,0x9553e4f9,0x354c8b44,0xffc5e622,0xa6cc511a, + 0xe95be787,0xb954726a,0x75b41a62,0xcb048115,0xebfde989,0xfa2ae6cd }, + { 0x0f24659a,0x6376bbc7,0x4c289c43,0x13a999fd,0xec9abd8b,0xc7134184, + 0xa789ab04,0x28c02bf6,0xd3e526ec,0xff841ebc,0x640893a8,0x442b191e } }, + /* 194 */ + { { 0xfa2b6e20,0x4cac6c62,0xf6d69861,0x97f29e9b,0xbc96d12d,0x228ab1db, + 0x5e8e108d,0x6eb91327,0x40771245,0xd4b3d4d1,0xca8a803a,0x61b20623 }, + { 0xa6a560b1,0x2c2f3b41,0x3859fcf4,0x879e1d40,0x024dbfc3,0x7cdb5145, + 0x3bfa5315,0x55d08f15,0xaa93823a,0x2f57d773,0xc6a2c9a2,0xa97f259c } }, + /* 195 */ + { { 0xe58edbbb,0xc306317b,0x79dfdf13,0x25ade51c,0x16d83dd6,0x6b5beaf1, + 0x1dd8f925,0xe8038a44,0xb2a87b6b,0x7f00143c,0xf5b438de,0xa885d00d }, + { 0xcf9e48bd,0xe9f76790,0xa5162768,0xf0bdf9f0,0xad7b57cb,0x0436709f, + 0xf7c15db7,0x7e151c12,0x5d90ee3b,0x3514f022,0x2c361a8d,0x2e84e803 } }, + /* 196 */ + { { 0x563ec8d8,0x2277607d,0xe3934cb7,0xa661811f,0xf58fd5de,0x3ca72e7a, + 0x62294c6a,0x7989da04,0xf6bbefe9,0x88b3708b,0x53ed7c82,0x0d524cf7 }, + { 0x2f30c073,0x69f699ca,0x9dc1dcf3,0xf0fa264b,0x05f0aaf6,0x44ca4568, + 0xd19b9baf,0x0f5b23c7,0xeabd1107,0x39193f41,0x2a7c9b83,0x9e3e10ad } }, + /* 197 */ + { { 0xd4ae972f,0xa90824f0,0xc6e846e7,0x43eef02b,0x29d2160a,0x7e460612, + 0xfe604e91,0x29a178ac,0x4eb184b2,0x23056f04,0xeb54cdf4,0x4fcad55f }, + { 0xae728d15,0xa0ff96f3,0xc6a00331,0x8a2680c6,0x7ee52556,0x5f84cae0, + 0xc5a65dad,0x5e462c3a,0xe2d23f4f,0x5d2b81df,0xc5b1eb07,0x6e47301b } }, + /* 198 */ + { { 0xaf8219b9,0x77411d68,0x51b1907a,0xcb883ce6,0x101383b5,0x25c87e57, + 0x982f970d,0x9c7d9859,0x118305d2,0xaa6abca5,0x9013a5db,0x725fed2f }, + { 0xababd109,0x487cdbaf,0x87586528,0xc0f8cf56,0x8ad58254,0xa02591e6, + 0xdebbd526,0xc071b1d1,0x961e7e31,0x927dfe8b,0x9263dfe1,0x55f895f9 } }, + /* 199 */ + { { 0xb175645b,0xf899b00d,0xb65b4b92,0x51f3a627,0xb67399ef,0xa2f3ac8d, + 0xe400bc20,0xe717867f,0x1967b952,0x42cc9020,0x3ecd1de1,0x3d596751 }, + { 0xdb979775,0xd41ebcde,0x6a2e7e88,0x99ba61bc,0x321504f2,0x039149a5, + 0x27ba2fad,0xe7dc2314,0xb57d8368,0x9f556308,0x57da80a7,0x2b6d16c9 } }, + /* 200 */ + { { 0x279ad982,0x84af5e76,0x9c8b81a6,0x9bb4c92d,0x0e698e67,0xd79ad44e, + 0x265fc167,0xe8be9048,0x0c3a4ccc,0xf135f7e6,0xb8863a33,0xa0a10d38 }, + { 0xd386efd9,0xe197247c,0xb52346c2,0x0eefd3f9,0x78607bc8,0xc22415f9, + 0x508674ce,0xa2a8f862,0xc8c9d607,0xa72ad09e,0x50fa764f,0xcd9f0ede } }, + /* 201 */ + { { 0xd1a46d4d,0x063391c7,0x9eb01693,0x2df51c11,0x849e83de,0xc5849800, + 0x8ad08382,0x48fd09aa,0xaa742736,0xa405d873,0xe1f9600c,0xee49e61e }, + { 0x48c76f73,0xd76676be,0x01274b2a,0xd9c100f6,0x83f8718d,0x110bb67c, + 0x02fc0d73,0xec85a420,0x744656ad,0xc0449e1e,0x37d9939b,0x28ce7376 } }, + /* 202 */ + { { 0x44544ac7,0x97e9af72,0xba010426,0xf2c658d5,0xfb3adfbd,0x732dec39, + 0xa2df0b07,0xd12faf91,0x2171e208,0x8ac26725,0x5b24fa54,0xf820cdc8 }, + { 0x94f4cf77,0x307a6eea,0x944a33c6,0x18c783d2,0x0b741ac5,0x4b939d4c, + 0x3ffbb6e4,0x1d7acd15,0x7a255e44,0x06a24858,0xce336d50,0x14fbc494 } }, + /* 203 */ + { { 0x51584e3c,0x9b920c0c,0xf7e54027,0xc7733c59,0x88422bbe,0xe24ce139, + 0x523bd6ab,0x11ada812,0xb88e6def,0xde068800,0xfe8c582d,0x7b872671 }, + { 0x7de53510,0x4e746f28,0xf7971968,0x492f8b99,0x7d928ac2,0x1ec80bc7, + 0x432eb1b5,0xb3913e48,0x32028f6e,0xad084866,0x8fc2f38b,0x122bb835 } }, + /* 204 */ + { { 0x3b0b29c3,0x0a9f3b1e,0x4fa44151,0x837b6432,0x17b28ea7,0xb9905c92, + 0x98451750,0xf39bc937,0xce8b6da1,0xcd383c24,0x010620b2,0x299f57db }, + { 0x58afdce3,0x7b6ac396,0x3d05ef47,0xa15206b3,0xb9bb02ff,0xa0ae37e2, + 0x9db3964c,0x107760ab,0x67954bea,0xe29de9a0,0x431c3f82,0x446a1ad8 } }, + /* 205 */ + { { 0x5c6b8195,0xc6fecea0,0xf49e71b9,0xd744a7c5,0x177a7ae7,0xa8e96acc, + 0x358773a7,0x1a05746c,0x37567369,0xa4162146,0x87d1c971,0xaa0217f7 }, + { 0x77fd3226,0x61e9d158,0xe4f600be,0x0f6f2304,0x7a6dff07,0xa9c4cebc, + 0x09f12a24,0xd15afa01,0x8c863ee9,0x2bbadb22,0xe5eb8c78,0xa28290e4 } }, + /* 206 */ + { { 0x3e9de330,0x55b87fa0,0x195c145b,0x12b26066,0xa920bef0,0xe08536e0, + 0x4d195adc,0x7bff6f2c,0x945f4187,0x7f319e9d,0xf892ce47,0xf9848863 }, + { 0x4fe37657,0xd0efc1d3,0x5cf0e45a,0x3c58de82,0x8b0ccbbe,0x626ad21a, + 0xaf952fc5,0xd2a31208,0xeb437357,0x81791995,0x98e95d4f,0x5f19d30f } }, + /* 207 */ + { { 0x0e6865bb,0x72e83d9a,0xf63456a6,0x22f5af3b,0x463c8d9e,0x409e9c73, + 0xdfe6970e,0x40e9e578,0x711b91ca,0x876b6efa,0x942625a3,0x895512cf }, + { 0xcb4e462b,0x84c8eda8,0x4412e7c8,0x84c0154a,0xceb7b71f,0x04325db1, + 0x66f70877,0x1537dde3,0x1992b9ac,0xf3a09399,0xd498ae77,0xa7316606 } }, + /* 208 */ + { { 0xcad260f5,0x13990d2f,0xeec0e8c0,0x76c3be29,0x0f7bd7d5,0x7dc5bee0, + 0xefebda4b,0x9be167d2,0x9122b87e,0xcce3dde6,0x82b5415c,0x75a28b09 }, + { 0xe84607a6,0xf6810bcd,0x6f4dbf0d,0xc6d58128,0x1b4dafeb,0xfead577d, + 0x066b28eb,0x9bc440b2,0x8b17e84b,0x53f1da97,0xcda9a575,0x0459504b } }, + /* 209 */ + { { 0x329e5836,0x13e39a02,0xf717269d,0x2c9e7d51,0xf26c963b,0xc5ac58d6, + 0x79967bf5,0x3b0c6c43,0x55908d9d,0x60bbea3f,0xf07c9ad1,0xd84811e7 }, + { 0x5bd20e4a,0xfe7609a7,0x0a70baa8,0xe4325dd2,0xb3600386,0x3711f370, + 0xd0924302,0x97f9562f,0x4acc4436,0x040dc0c3,0xde79cdd4,0xfd6d725c } }, + /* 210 */ + { { 0xcf13eafb,0xb3efd0e3,0x5aa0ae5f,0x21009cbb,0x79022279,0xe480c553, + 0xb2fc9a6d,0x755cf334,0x07096ae7,0x8564a5bf,0xbd238139,0xddd649d0 }, + { 0x8a045041,0xd0de10b1,0xc957d572,0x6e05b413,0x4e0fb25c,0x5c5ff806, + 0x641162fb,0xd933179b,0xe57439f9,0x42d48485,0x8a8d72aa,0x70c5bd0a } }, + /* 211 */ + { { 0x97bdf646,0xa7671738,0xab329f7c,0xaa1485b4,0xf8f25fdf,0xce3e11d6, + 0xc6221824,0x76a3fc7e,0xf3924740,0x045f281f,0x96d13a9a,0x24557d4e }, + { 0xdd4c27cd,0x875c804b,0x0f5c7fea,0x11c5f0f4,0xdc55ff7e,0xac8c880b, + 0x1103f101,0x2acddec5,0xf99faa89,0x38341a21,0xce9d6b57,0xc7b67a2c } }, + /* 212 */ + { { 0x8e357586,0x9a0d724f,0xdf648da0,0x1d7f4ff5,0xfdee62a5,0x9c3e6c9b, + 0x0389b372,0x0499cef0,0x98eab879,0xe904050d,0x6c051617,0xe8eef1b6 }, + { 0xc37e3ca9,0xebf5bfeb,0xa4e0b91d,0x7c5e946d,0x2c4bea28,0x79097314, + 0xee67b2b7,0x81f6c109,0xdafc5ede,0xaf237d9b,0x2abb04c7,0xd2e60201 } }, + /* 213 */ + { { 0x8a4f57bf,0x6156060c,0xff11182a,0xf9758696,0x6296ef00,0x8336773c, + 0xff666899,0x9c054bce,0x719cd11c,0xd6a11611,0xdbe1acfa,0x9824a641 }, + { 0xba89fd01,0x0b7b7a5f,0x889f79d8,0xf8d3b809,0xf578285c,0xc5e1ea08, + 0xae6d8288,0x7ac74536,0x7521ef5f,0x5d37a200,0xb260a25d,0x5ecc4184 } }, + /* 214 */ + { { 0xa708c8d3,0xddcebb19,0xc63f81ec,0xe63ed04f,0x11873f95,0xd045f5a0, + 0x79f276d5,0x3b5ad544,0x425ae5b3,0x81272a3d,0x10ce1605,0x8bfeb501 }, + { 0x888228bf,0x4233809c,0xb2aff7df,0x4bd82acf,0x0cbd4a7f,0x9c68f180, + 0x6b44323d,0xfcd77124,0x891db957,0x60c0fcf6,0x04da8f7f,0xcfbb4d89 } }, + /* 215 */ + { { 0x3b26139a,0x9a6a5df9,0xb2cc7eb8,0x3e076a83,0x5a964bcd,0x47a8e82d, + 0xb9278d6b,0x8a4e2a39,0xe4443549,0x93506c98,0xf1e0d566,0x06497a8f }, + { 0x2b1efa05,0x3dee8d99,0x45393e33,0x2da63ca8,0xcf0579ad,0xa4af7277, + 0x3236d8ea,0xaf4b4639,0x32b617f5,0x6ccad95b,0xb88bb124,0xce76d8b8 } }, + /* 216 */ + { { 0x083843dc,0x63d2537a,0x1e4153b4,0x89eb3514,0xea9afc94,0x5175ebc4, + 0x8ed1aed7,0x7a652580,0xd85e8297,0x67295611,0xb584b73d,0x8dd2d68b }, + { 0x0133c3a4,0x237139e6,0x4bd278ea,0x9de838ab,0xc062fcd9,0xe829b072, + 0x63ba8706,0x70730d4f,0xd3cd05ec,0x6080483f,0x0c85f84d,0x872ab5b8 } }, + /* 217 */ + { { 0x999d4d49,0xfc0776d3,0xec3f45e7,0xa3eb59de,0x0dae1fc1,0xbc990e44, + 0xa15371ff,0x33596b1e,0x9bc7ab25,0xd447dcb2,0x35979582,0xcd5b63e9 }, + { 0x77d1ff11,0xae3366fa,0xedee6903,0x59f28f05,0xa4433bf2,0x6f43fed1, + 0xdf9ce00e,0x15409c9b,0xaca9c5dc,0x21b5cded,0x82d7bdb4,0xf9f33595 } }, + /* 218 */ + { { 0x9422c792,0x95944378,0xc958b8bf,0x239ea923,0xdf076541,0x4b61a247, + 0xbb9fc544,0x4d29ce85,0x0b424559,0x9a692a67,0x0e486900,0x6e0ca5a0 }, + { 0x85b3bece,0x6b79a782,0xc61f9892,0x41f35e39,0xae747f82,0xff82099a, + 0xd0ca59d6,0x58c8ae3f,0x99406b5f,0x4ac930e2,0x9df24243,0x2ce04eb9 } }, + /* 219 */ + { { 0x1ac37b82,0x4366b994,0x25b04d83,0xff0c728d,0x19c47b7c,0x1f551361, + 0xbeff13e7,0xdbf2d5ed,0xe12a683d,0xf78efd51,0x989cf9c4,0x82cd85b9 }, + { 0xe0cb5d37,0xe23c6db6,0x72ee1a15,0x818aeebd,0x28771b14,0x8212aafd, + 0x1def817d,0x7bc221d9,0x9445c51f,0xdac403a2,0x12c3746b,0x711b0517 } }, + /* 220 */ + { { 0x5ea99ecc,0x0ed9ed48,0xb8cab5e1,0xf799500d,0xb570cbdc,0xa8ec87dc, + 0xd35dfaec,0x52cfb2c2,0x6e4d80a4,0x8d31fae2,0xdcdeabe5,0xe6a37dc9 }, + { 0x1deca452,0x5d365a34,0x0d68b44e,0x09a5f8a5,0xa60744b1,0x59238ea5, + 0xbb4249e9,0xf2fedc0d,0xa909b2e3,0xe395c74e,0x39388250,0xe156d1a5 } }, + /* 221 */ + { { 0x47181ae9,0xd796b3d0,0x44197808,0xbaf44ba8,0x34cf3fac,0xe6933094, + 0xc3bd5c46,0x41aa6ade,0xeed947c6,0x4fda75d8,0x9ea5a525,0xacd9d412 }, + { 0xd430301b,0x65cc55a3,0x7b52ea49,0x3c9a5bcf,0x159507f0,0x22d319cf, + 0xde74a8dd,0x2ee0b9b5,0x877ac2b6,0x20c26a1e,0x92e7c314,0x387d73da } }, + /* 222 */ + { { 0x8cd3fdac,0x13c4833e,0x332e5b8e,0x76fcd473,0xe2fe1fd3,0xff671b4b, + 0x5d98d8ec,0x4d734e8b,0x514bbc11,0xb1ead3c6,0x7b390494,0xd14ca858 }, + { 0x5d2d37e9,0x95a443af,0x00464622,0x73c6ea73,0x15755044,0xa44aeb4b, + 0xfab58fee,0xba3f8575,0xdc680a6f,0x9779dbc9,0x7b37ddfc,0xe1ee5f5a } }, + /* 223 */ + { { 0x12d29f46,0xcd0b4648,0x0ed53137,0x93295b0b,0x80bef6c9,0xbfe26094, + 0x54248b00,0xa6565788,0x80e7f9c4,0x69c43fca,0xbe141ea1,0x2190837b }, + { 0xa1b26cfb,0x875e159a,0x7affe852,0x90ca9f87,0x92ca598e,0x15e6550d, + 0x1938ad11,0xe3e0945d,0x366ef937,0xef7636bb,0xb39869e5,0xb6034d0b } }, + /* 224 */ + { { 0x26d8356e,0x4d255e30,0xd314626f,0xf83666ed,0xd0c8ed64,0x421ddf61, + 0x26677b61,0x96e473c5,0x9e9b18b3,0xdad4af7e,0xa9393f75,0xfceffd4a }, + { 0x11c731d5,0x843138a1,0xb2f141d9,0x05bcb3a1,0x617b7671,0x20e1fa95, + 0x88ccec7b,0xbefce812,0x90f1b568,0x582073dc,0x1f055cb7,0xf572261a } }, + /* 225 */ + { { 0x36973088,0xf3148277,0x86a9f980,0xc008e708,0xe046c261,0x1b795947, + 0xca76bca0,0xdf1e6a7d,0x71acddf0,0xabafd886,0x1364d8f4,0xff7054d9 }, + { 0xe2260594,0x2cf63547,0xd73b277e,0x468a5372,0xef9bd35e,0xc7419e24, + 0x24043cc3,0x2b4a1c20,0x890b39cd,0xa28f047a,0x46f9a2e3,0xdca2cea1 } }, + /* 226 */ + { { 0x53277538,0xab788736,0xcf697738,0xa734e225,0x6b22e2c1,0x66ee1d1e, + 0xebe1d212,0x2c615389,0x02bb0766,0xf36cad40,0x3e64f207,0x120885c3 }, + { 0x90fbfec2,0x59e77d56,0xd7a574ae,0xf9e781aa,0x5d045e53,0x801410b0, + 0xa91b5f0e,0xd3b5f0aa,0x7fbb3521,0xb3d1df00,0xc72bee9a,0x11c4b33e } }, + /* 227 */ + { { 0x83c3a7f3,0xd32b9832,0x88d8a354,0x8083abcf,0x50f4ec5a,0xdeb16404, + 0x641e2907,0x18d747f0,0xf1bbf03e,0x4e8978ae,0x88a0cd89,0x932447dc }, + { 0xcf3d5897,0x561e0feb,0x13600e6d,0xfc3a682f,0xd16a6b73,0xc78b9d73, + 0xd29bf580,0xe713fede,0x08d69e5c,0x0a225223,0x1ff7fda4,0x3a924a57 } }, + /* 228 */ + { { 0xb4093bee,0xfb64554c,0xa58c6ec0,0xa6d65a25,0x43d0ed37,0x4126994d, + 0x55152d44,0xa5689a51,0x284caa8d,0xb8e5ea8c,0xd1f25538,0x33f05d4f }, + { 0x1b615d6e,0xe0fdfe09,0x705507da,0x2ded7e8f,0x17bbcc80,0xdd5631e5, + 0x267fd11f,0x4f87453e,0xff89d62d,0xc6da723f,0xe3cda21d,0x55cbcae2 } }, + /* 229 */ + { { 0x6b4e84f3,0x336bc94e,0x4ef72c35,0x72863031,0xeeb57f99,0x6d85fdee, + 0xa42ece1b,0x7f4e3272,0x36f0320a,0x7f86cbb5,0x923331e6,0xf09b6a2b }, + { 0x56778435,0x21d3ecf1,0x8323b2d2,0x2977ba99,0x1704bc0f,0x6a1b57fb, + 0x389f048a,0xd777cf8b,0xac6b42cd,0x9ce2174f,0x09e6c55a,0x404e2bff } }, + /* 230 */ + { { 0x204c5ddb,0x9b9b135e,0x3eff550e,0x9dbfe044,0xec3be0f6,0x35eab4bf, + 0x0a43e56f,0x8b4c3f0d,0x0e73f9b3,0x4c1c6673,0x2c78c905,0x92ed38bd }, + { 0xa386e27c,0xc7003f6a,0xaced8507,0xb9c4f46f,0x59df5464,0xea024ec8, + 0x429572ea,0x4af96152,0xe1fc1194,0x279cd5e2,0x281e358c,0xaa376a03 } }, + /* 231 */ + { { 0x3cdbc95c,0x07859223,0xef2e337a,0xaae1aa6a,0x472a8544,0xc040108d, + 0x8d037b7d,0x80c853e6,0x8c7eee24,0xd221315c,0x8ee47752,0x195d3856 }, + { 0xdacd7fbe,0xd4b1ba03,0xd3e0c52b,0x4b5ac61e,0x6aab7b52,0x68d3c052, + 0x660e3fea,0xf0d7248c,0x3145efb4,0xafdb3f89,0x8f40936d,0xa73fd9a3 } }, + /* 232 */ + { { 0xbb1b17ce,0x891b9ef3,0xc6127f31,0x14023667,0x305521fd,0x12b2e58d, + 0xe3508088,0x3a47e449,0xff751507,0xe49fc84b,0x5310d16e,0x4023f722 }, + { 0xb73399fa,0xa608e5ed,0xd532aa3e,0xf12632d8,0x845e8415,0x13a2758e, + 0x1fc2d861,0xae4b6f85,0x339d02f2,0x3879f5b1,0x80d99ebd,0x446d22a6 } }, + /* 233 */ + { { 0x4be164f1,0x0f502302,0x88b81920,0x8d09d2d6,0x984aceff,0x514056f1, + 0x75e9e80d,0xa5c4ddf0,0xdf496a93,0x38cb47e6,0x38df6bf7,0x899e1d6b }, + { 0xb59eb2a6,0x69e87e88,0x9b47f38b,0x280d9d63,0x3654e955,0x599411ea, + 0x969aa581,0xcf8dd4fd,0x530742a7,0xff5c2baf,0x1a373085,0xa4391536 } }, + /* 234 */ + { { 0xa8a4bdd2,0x6ace72a3,0xb68ef702,0xc656cdd1,0x90c4dad8,0xd4a33e7e, + 0x9d951c50,0x4aece08a,0x085d68e6,0xea8005ae,0x6f7502b8,0xfdd7a7d7 }, + { 0x98d6fa45,0xce6fb0a6,0x1104eb8c,0x228f8672,0xda09d7dc,0xd23d8787, + 0x2ae93065,0x5521428b,0xea56c366,0x95faba3d,0x0a88aca5,0xedbe5039 } }, + /* 235 */ + { { 0xbfb26c82,0xd64da0ad,0x952c2f9c,0xe5d70b3c,0xf7e77f68,0xf5e8f365, + 0x08f2d695,0x7234e002,0xd12e7be6,0xfaf900ee,0x4acf734e,0x27dc6934 }, + { 0xc260a46a,0x80e4ff5e,0x2dc31c28,0x7da5ebce,0xca69f552,0x485c5d73, + 0x69cc84c2,0xcdfb6b29,0xed6d4eca,0x031c5afe,0x22247637,0xc7bbf4c8 } }, + /* 236 */ + { { 0x49fe01b2,0x9d5b72c7,0x793a91b8,0x34785186,0xcf460438,0xa3ba3c54, + 0x3ab21b6f,0x73e8e43d,0xbe57b8ab,0x50cde8e0,0xdd204264,0x6488b3a7 }, + { 0xdddc4582,0xa9e398b3,0x5bec46fe,0x1698c1a9,0x156d3843,0x7f1446ef, + 0x770329a2,0x3fd25dd8,0x2c710668,0x05b1221a,0xa72ee6cf,0x65b2dc2a } }, + /* 237 */ + { { 0xcd021d63,0x21a885f7,0xfea61f08,0x3f344b15,0xc5cf73e6,0xad5ba6dd, + 0x227a8b23,0x154d0d8f,0xdc559311,0x9b74373c,0x98620fa1,0x4feab715 }, + { 0x7d9ec924,0x5098938e,0x6d47e550,0x84d54a5e,0x1b617506,0x1a2d1bdc, + 0x615868a4,0x99fe1782,0x3005a924,0x171da780,0x7d8f79b6,0xa70bf5ed } }, + /* 238 */ + { { 0xfe2216c5,0x0bc1250d,0x7601b351,0x2c37e250,0xd6f06b7e,0xb6300175, + 0x8bfeb9b7,0x4dde8ca1,0xb82f843d,0x4f210432,0xb1ac0afd,0x8d70e2f9 }, + { 0xaae91abb,0x25c73b78,0x863028f2,0x0230dca3,0xe5cf30b7,0x8b923ecf, + 0x5506f265,0xed754ec2,0x729a5e39,0x8e41b88c,0xbabf889b,0xee67cec2 } }, + /* 239 */ + { { 0x1be46c65,0xe183acf5,0xe7565d7a,0x9789538f,0xd9627b4e,0x87873391, + 0x9f1d9187,0xbf4ac4c1,0x4691f5c8,0x5db99f63,0x74a1fb98,0xa68df803 }, + { 0xbf92b5fa,0x3c448ed1,0x3e0bdc32,0xa098c841,0x79bf016c,0x8e74cd55, + 0x115e244d,0x5df0d09c,0x3410b66e,0x9418ad01,0x17a02130,0x8b6124cb } }, + /* 240 */ + { { 0xc26e3392,0x425ec3af,0xa1722e00,0xc07f8470,0xe2356b43,0xdcc28190, + 0xb1ef59a6,0x4ed97dff,0xc63028c1,0xc22b3ad1,0x68c18988,0x070723c2 }, + { 0x4cf49e7d,0x70da302f,0x3f12a522,0xc5e87c93,0x18594148,0x74acdd1d, + 0xca74124c,0xad5f73ab,0xd69fd478,0xe72e4a3e,0x7b117cc3,0x61593868 } }, + /* 241 */ + { { 0xa9aa0486,0x7b7b9577,0xa063d557,0x6e41fb35,0xda9047d7,0xb017d5c7, + 0x68a87ba9,0x8c748280,0xdf08ad93,0xab45fa5c,0x4c288a28,0xcd9fb217 }, + { 0x5747843d,0x59544642,0xa56111e3,0x34d64c6c,0x4bfce8d5,0x12e47ea1, + 0x6169267f,0x17740e05,0xeed03fb5,0x5c49438e,0x4fc3f513,0x9da30add } }, + /* 242 */ + { { 0xccfa5200,0xc4e85282,0x6a19b13d,0x2707608f,0xf5726e2f,0xdcb9a53d, + 0xe9427de5,0x612407c9,0xd54d582a,0x3e5a17e1,0x655ae118,0xb99877de }, + { 0x015254de,0x6f0e972b,0xf0a6f7c5,0x92a56db1,0xa656f8b2,0xd297e4e1, + 0xad981983,0x99fe0052,0x07cfed84,0xd3652d2f,0x843c1738,0xc784352e } }, + /* 243 */ + { { 0x7e9b2d8a,0x6ee90af0,0x57cf1964,0xac8d7018,0x71f28efc,0xf6ed9031, + 0x6812b20e,0x7f70d5a9,0xf1c61eee,0x27b557f4,0xc6263758,0xf1c9bd57 }, + { 0x2a1a6194,0x5cf7d014,0x1890ab84,0xdd614e0b,0x0e93c2a6,0x3ef9de10, + 0xe0cd91c5,0xf98cf575,0x14befc32,0x504ec0c6,0x6279d68c,0xd0513a66 } }, + /* 244 */ + { { 0xa859fb6a,0xa8eadbad,0xdb283666,0xcf8346e7,0x3e22e355,0x7b35e61a, + 0x99639c6b,0x293ece2c,0x56f241c8,0xfa0162e2,0xbf7a1dda,0xd2e6c7b9 }, + { 0x40075e63,0xd0de6253,0xf9ec8286,0x2405aa61,0x8fe45494,0x2237830a, + 0x364e9c8c,0x4fd01ac7,0x904ba750,0x4d9c3d21,0xaf1b520b,0xd589be14 } }, + /* 245 */ + { { 0x4662e53b,0x13576a4f,0xf9077676,0x35ec2f51,0x97c0af97,0x66297d13, + 0x9e598b58,0xed3201fe,0x5e70f604,0x49bc752a,0xbb12d951,0xb54af535 }, + { 0x212c1c76,0x36ea4c2b,0xeb250dfd,0x18f5bbc7,0x9a0a1a46,0xa0d466cc, + 0xdac2d917,0x52564da4,0x8e95fab5,0x206559f4,0x9ca67a33,0x7487c190 } }, + /* 246 */ + { { 0xdde98e9c,0x75abfe37,0x2a411199,0x99b90b26,0xdcdb1f7c,0x1b410996, + 0x8b3b5675,0xab346f11,0xf1f8ae1e,0x04852193,0x6b8b98c1,0x1ec4d227 }, + { 0x45452baa,0xba3bc926,0xacc4a572,0x387d1858,0xe51f171e,0x9478eff6, + 0x931e1c00,0xf357077d,0xe54c8ca8,0xffee77cd,0x551dc9a4,0xfb4892ff } }, + /* 247 */ + { { 0x2db8dff8,0x5b1bdad0,0x5a2285a2,0xd462f4fd,0xda00b461,0x1d6aad8e, + 0x41306d1b,0x43fbefcf,0x6a13fe19,0x428e86f3,0x17f89404,0xc8b2f118 }, + { 0xf0d51afb,0x762528aa,0x549b1d06,0xa3e2fea4,0xea3ddf66,0x86fad8f2, + 0x4fbdd206,0x0d9ccc4b,0xc189ff5a,0xcde97d4c,0x199f19a6,0xc36793d6 } }, + /* 248 */ + { { 0x51b85197,0xea38909b,0xb4c92895,0xffb17dd0,0x1ddb3f3f,0x0eb0878b, + 0xc57cf0f2,0xb05d28ff,0x1abd57e2,0xd8bde2e7,0xc40c1b20,0x7f2be28d }, + { 0x299a2d48,0x6554dca2,0x8377982d,0x5130ba2e,0x1071971a,0x8863205f, + 0x7cf2825d,0x15ee6282,0x03748f2b,0xd4b6c57f,0x430385a0,0xa9e3f4da } }, + /* 249 */ + { { 0x83fbc9c6,0x33eb7cec,0x4541777e,0x24a311c7,0x4f0767fc,0xc81377f7, + 0x4ab702da,0x12adae36,0x2a779696,0xb7fcb6db,0x01cea6ad,0x4a6fb284 }, + { 0xcdfc73de,0x5e8b1d2a,0x1b02fd32,0xd0efae8d,0xd81d8519,0x3f99c190, + 0xfc808971,0x3c18f7fa,0x51b7ae7b,0x41f713e7,0xf07fc3f8,0x0a4b3435 } }, + /* 250 */ + { { 0x019b7d2e,0x7dda3c4c,0xd4dc4b89,0x631c8d1a,0x1cdb313c,0x5489cd6e, + 0x4c07bb06,0xd44aed10,0x75f000d1,0x8f97e13a,0xdda5df4d,0x0e9ee64f }, + { 0x3e346910,0xeaa99f3b,0xfa294ad7,0x622f6921,0x0d0b2fe9,0x22aaa20d, + 0x1e5881ba,0x4fed2f99,0xc1571802,0x9af3b2d6,0xdc7ee17c,0x919e67a8 } }, + /* 251 */ + { { 0x76250533,0xc724fe4c,0x7d817ef8,0x8a2080e5,0x172c9751,0xa2afb0f4, + 0x17c0702e,0x9b10cdeb,0xc9b7e3e9,0xbf3975e3,0x1cd0cdc5,0x206117df }, + { 0xbe05ebd5,0xfb049e61,0x16c782c0,0xeb0bb55c,0xab7fed09,0x13a331b8, + 0x632863f0,0xf6c58b1d,0x4d3b6195,0x6264ef6e,0x9a53f116,0x92c51b63 } }, + /* 252 */ + { { 0x288b364d,0xa57c7bc8,0x7b41e5c4,0x4a562e08,0x698a9a11,0x699d21c6, + 0xf3f849b9,0xa4ed9581,0x9eb726ba,0xa223eef3,0xcc2884f9,0x13159c23 }, + { 0x3a3f4963,0x73931e58,0x0ada6a81,0x96500389,0x5ab2950b,0x3ee8a1c6, + 0x775fab52,0xeedf4949,0x4f2671b6,0x63d652e1,0x3c4e2f55,0xfed4491c } }, + /* 253 */ + { { 0xf4eb453e,0x335eadc3,0xcadd1a5b,0x5ff74b63,0x5d84a91a,0x6933d0d7, + 0xb49ba337,0x9ca3eeb9,0xc04c15b8,0x1f6facce,0xdc09a7e4,0x4ef19326 }, + { 0x3dca3233,0x53d2d324,0xa2259d4b,0x0ee40590,0x5546f002,0x18c22edb, + 0x09ea6b71,0x92429801,0xb0e91e61,0xaada0add,0x99963c50,0x5fe53ef4 } }, + /* 254 */ + { { 0x90c28c65,0x372dd06b,0x119ce47d,0x1765242c,0x6b22fc82,0xc041fb80, + 0xb0a7ccc1,0x667edf07,0x1261bece,0xc79599e7,0x19cff22a,0xbc69d9ba }, + { 0x13c06819,0x009d77cd,0xe282b79d,0x635a66ae,0x225b1be8,0x4edac4a6, + 0x524008f9,0x57d4f4e4,0xb056af84,0xee299ac5,0x3a0bc386,0xcc38444c } }, + /* 255 */ + { { 0xcd4c2356,0x490643b1,0x750547be,0x740a4851,0xd4944c04,0x643eaf29, + 0x299a98a0,0xba572479,0xee05fdf9,0x48b29f16,0x089b2d7b,0x33fb4f61 }, + { 0xa950f955,0x86704902,0xfedc3ddf,0x97e1034d,0x05fbb6a2,0x211320b6, + 0x432299bb,0x23d7b93f,0x8590e4a3,0x1fe1a057,0xf58c0ce6,0x8e1d0586 } }, +}; + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + return sp_384_ecc_mulmod_stripe_12(r, &p384_base, p384_table, + k, map, heap); +} + +#endif + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[12]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_384_point_new_12(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 12, km); + + err = sp_384_ecc_mulmod_base_12(point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_12(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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_384_iszero_12(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] | a[10] | a[11]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_add_one_12(sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r2, #1\n\t" + "ldr r1, [%[a], #0]\n\t" + "add r1, r2\n\t" + "mov r2, #0\n\t" + "str r1, [%[a], #0]\n\t" + "ldr r1, [%[a], #4]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #4]\n\t" + "ldr r1, [%[a], #8]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #8]\n\t" + "ldr r1, [%[a], #12]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #12]\n\t" + "ldr r1, [%[a], #16]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #16]\n\t" + "ldr r1, [%[a], #20]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #20]\n\t" + "ldr r1, [%[a], #24]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #24]\n\t" + "ldr r1, [%[a], #28]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #28]\n\t" + "ldr r1, [%[a], #32]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #32]\n\t" + "ldr r1, [%[a], #36]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #36]\n\t" + "ldr r1, [%[a], #40]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #40]\n\t" + "ldr r1, [%[a], #44]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #44]\n\t" + : + : [a] "r" (a) + : "memory", "r1", "r2" + ); +} + +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; 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_384_ecc_gen_k_12(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[48]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_384_from_bin(k, 12, buf, (int)sizeof(buf)); + if (sp_384_cmp_12(k, p384_order2) < 0) { + sp_384_add_one_12(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_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[12]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 inf; +#endif +#endif + sp_point_384* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity; +#endif + int err; + + (void)heap; + + err = sp_384_point_new_12(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + err = sp_384_ecc_gen_k_12(rng, k); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_12(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_12(infinity, point, p384_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_384_iszero_12(point->x) == 0) || (sp_384_iszero_12(point->y) == 0)) { + err = ECC_INF_E; + } + } +#endif + + if (err == MP_OKAY) { + err = sp_384_to_mp(k, priv); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_12(point, pub); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_384_point_free_12(infinity, 1, heap); +#endif + sp_384_point_free_12(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 48 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_384_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 384 / 8 - 1; + a[j] = 0; + for (i=0; i<12 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + 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_384(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[12]; +#endif + sp_point_384* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 48U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(k, 12, priv); + sp_384_point_from_ecc_point_12(point, pub); + err = sp_384_ecc_mulmod_12(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_384_to_bin(point->x, out); + *outLen = 48; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_384_sub_in_place_12(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "add r7, #48\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_384_sub_in_place_12(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* 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. + */ +SP_NOINLINE static void sp_384_mul_d_12(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #48\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_384_word_12(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + 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_384_mask_12(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<12; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; + r[8] = a[8] & m; + r[9] = a[9] & m; + r[10] = a[10] & m; + r[11] = a[11] & 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 WC_INLINE int sp_384_div_12(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[24], t2[13]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[11]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 12); + for (i=11; i>=0; i--) { + r1 = div_384_word_12(t1[12 + i], t1[12 + i - 1], div); + + sp_384_mul_d_12(t2, d, r1); + t1[12 + i] += sp_384_sub_in_place_12(&t1[i], t2); + t1[12 + i] -= t2[12]; + sp_384_mask_12(t2, d, t1[12 + i]); + t1[12 + i] += sp_384_add_12(&t1[i], &t1[i], t2); + sp_384_mask_12(t2, d, t1[12 + i]); + t1[12 + i] += sp_384_add_12(&t1[i], &t1[i], t2); + } + + r1 = sp_384_cmp_12(t1, d) >= 0; + sp_384_cond_sub_12(r, t1, d, (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 WC_INLINE int sp_384_mod_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_384_div_12(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P384 curve. */ +static const uint32_t p384_order_minus_2[12] = { + 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U, + 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU +}; +#else +/* The low half of the order-2 of the P384 curve. */ +static const uint32_t p384_order_low[6] = { + 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U + +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P384 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_384_mont_mul_order_12(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_384_mul_12(r, a, b); + sp_384_mont_reduce_order_12(r, p384_order, p384_mp_order); +} + +/* Square number mod the order of P384 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_order_12(sp_digit* r, const sp_digit* a) +{ + sp_384_sqr_12(r, a); + sp_384_mont_reduce_order_12(r, p384_order, p384_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P384 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_n_order_12(sp_digit* r, const sp_digit* a, int n) +{ + int i; + + sp_384_mont_sqr_order_12(r, a); + for (i=1; i=0; i--) { + sp_384_mont_sqr_order_12(t, t); + if ((p384_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_384_mont_mul_order_12(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 12U); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 12; + sp_digit* t3 = td + 4 * 12; + int i; + + /* t = a^2 */ + sp_384_mont_sqr_order_12(t, a); + /* t = a^3 = t * a */ + sp_384_mont_mul_order_12(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_384_mont_sqr_n_order_12(t2, t, 2); + /* t = a^f = t2 * t */ + sp_384_mont_mul_order_12(t, t2, t); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_384_mont_sqr_n_order_12(t2, t, 4); + /* t = a^ff = t2 * t */ + sp_384_mont_mul_order_12(t, t2, t); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_384_mont_sqr_n_order_12(t2, t, 8); + /* t3= a^ffff = t2 * t */ + sp_384_mont_mul_order_12(t3, t2, t); + /* t2= a^ffff0000 = t3 ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_12(t2, t3, 16); + /* t = a^ffffffff = t2 * t3 */ + sp_384_mont_mul_order_12(t, t2, t3); + /* t2= a^ffffffff0000 = t ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_12(t2, t, 16); + /* t = a^ffffffffffff = t2 * t3 */ + sp_384_mont_mul_order_12(t, t2, t3); + /* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */ + sp_384_mont_sqr_n_order_12(t2, t, 48); + /* t= a^fffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_12(t, t2, t); + /* t2= a^ffffffffffffffffffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_order_12(t2, t, 96); + /* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_12(t2, t2, t); + for (i=191; i>=1; i--) { + sp_384_mont_sqr_order_12(t2, t2); + if (((sp_digit)p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_384_mont_mul_order_12(t2, t2, a); + } + } + sp_384_mont_sqr_order_12(t2, t2); + sp_384_mont_mul_order_12(r, t2, a); +#endif /* WOLFSSL_SP_SMALL */ +} + +#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, 384 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 384 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_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit ed[2*12]; + sp_digit xd[2*12]; + sp_digit kd[2*12]; + sp_digit rd[2*12]; + sp_digit td[3 * 2*12]; + sp_point_384 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_384* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int32_t c; + int i; + + (void)heap; + + err = sp_384_point_new_12(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 12; + x = d + 2 * 12; + k = d + 4 * 12; + r = d + 6 * 12; + tmp = d + 8 * 12; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(e, 12, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_384_from_mp(x, 12, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_12(rng, k); + } + else { + sp_384_from_mp(k, 12, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_12(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 12U); + sp_384_norm_12(r); + c = sp_384_cmp_12(r, p384_order); + sp_384_cond_sub_12(r, r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(r); + + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_12(k, k, p384_norm_order); + err = sp_384_mod_12(k, k, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_12(k); + /* kInv = 1/k mod order */ + sp_384_mont_inv_order_12(kInv, k, tmp); + sp_384_norm_12(kInv); + + /* s = r * x + e */ + sp_384_mul_12(x, x, r); + err = sp_384_mod_12(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_12(x); + carry = sp_384_add_12(s, e, x); + sp_384_cond_sub_12(s, s, p384_order, 0 - carry); + sp_384_norm_12(s); + c = sp_384_cmp_12(s, p384_order); + sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_12(s, s, kInv); + sp_384_norm_12(s); + + /* Check that signature is usable. */ + if (sp_384_iszero_12(s) == 0) { + break; + } + } + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 12); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U); +#endif + sp_384_point_free_12(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, 384) + * 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 384 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_384(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit u1d[2*12]; + sp_digit u2d[2*12]; + sp_digit sd[2*12]; + sp_digit tmpd[2*12 * 5]; + sp_point_384 p1d; + sp_point_384 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p1; + sp_point_384* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + + err = sp_384_point_new_12(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 12, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 12; + u2 = d + 2 * 12; + s = d + 4 * 12; + tmp = d + 6 * 12; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 12, hash, (int)hashLen); + sp_384_from_mp(u2, 12, r); + sp_384_from_mp(s, 12, sm); + sp_384_from_mp(p2->x, 12, pX); + sp_384_from_mp(p2->y, 12, pY); + sp_384_from_mp(p2->z, 12, pZ); + + { + sp_384_mul_12(s, s, p384_norm_order); + } + err = sp_384_mod_12(s, s, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_12(s); + { + sp_384_mont_inv_order_12(s, s, tmp); + sp_384_mont_mul_order_12(u1, u1, s); + sp_384_mont_mul_order_12(u2, u2, s); + } + + err = sp_384_ecc_mulmod_base_12(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + { + sp_384_proj_point_add_12(p1, p1, p2, tmp); + if (sp_384_iszero_12(p1->z)) { + if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) { + sp_384_proj_point_dbl_12(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + p1->x[8] = 0; + p1->x[9] = 0; + p1->x[10] = 0; + p1->x[11] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + } + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 12, r); + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_12(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 12, r); + carry = sp_384_add_12(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_12(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_12(u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_384_point_free_12(p1, 0, heap); + sp_384_point_free_12(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*12]; + sp_digit t2d[2*12]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 12; + t2 = d + 2 * 12; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_384_sqr_12(t1, point->y); + (void)sp_384_mod_12(t1, t1, p384_mod); + sp_384_sqr_12(t2, point->x); + (void)sp_384_mod_12(t2, t2, p384_mod); + sp_384_mul_12(t2, t2, point->x); + (void)sp_384_mod_12(t2, t2, p384_mod); + (void)sp_384_sub_12(t2, p384_mod, t2); + sp_384_mont_add_12(t1, t1, t2, p384_mod); + + sp_384_mont_add_12(t1, t1, point->x, p384_mod); + sp_384_mont_add_12(t1, t1, point->x, p384_mod); + sp_384_mont_add_12(t1, t1, point->x, p384_mod); + + if (sp_384_cmp_12(t1, p384_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 pubd; +#endif + sp_point_384* pub; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_12(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_384_from_mp(pub->x, 12, pX); + sp_384_from_mp(pub->y, 12, pY); + sp_384_from_bin(pub->z, 12, one, (int)sizeof(one)); + + err = sp_384_ecc_is_point_12(pub, NULL); + } + + sp_384_point_free_12(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[12]; + sp_point_384 pubd; + sp_point_384 pd; +#endif + sp_digit* priv = NULL; + sp_point_384* pub; + sp_point_384* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_12(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_384_from_mp(pub->x, 12, pX); + sp_384_from_mp(pub->y, 12, pY); + sp_384_from_bin(pub->z, 12, one, (int)sizeof(one)); + sp_384_from_mp(priv, 12, privm); + + /* Check point at infinitiy. */ + if ((sp_384_iszero_12(pub->x) != 0) && + (sp_384_iszero_12(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_384_cmp_12(pub->x, p384_mod) >= 0 || + sp_384_cmp_12(pub->y, p384_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_384_ecc_is_point_12(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_384_ecc_mulmod_12(p, pub, p384_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_384_iszero_12(p->x) == 0) || + (sp_384_iszero_12(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_384_ecc_mulmod_base_12(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_384_cmp_12(p->x, pub->x) != 0 || + sp_384_cmp_12(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, heap); + sp_384_point_free_12(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 12 * 5]; + sp_point_384 pd; + sp_point_384 qd; +#endif + sp_digit* tmp; + sp_point_384* p; + sp_point_384* q = NULL; + int err; + + err = sp_384_point_new_12(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_384_point_new_12(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 12, pX); + sp_384_from_mp(p->y, 12, pY); + sp_384_from_mp(p->z, 12, pZ); + sp_384_from_mp(q->x, 12, qX); + sp_384_from_mp(q->y, 12, qY); + sp_384_from_mp(q->z, 12, qZ); + + sp_384_proj_point_add_12(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(q, 0, NULL); + sp_384_point_free_12(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 12 * 2]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_12(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 12, pX); + sp_384_from_mp(p->y, 12, pY); + sp_384_from_mp(p->z, 12, pZ); + + sp_384_proj_point_dbl_12(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 12 * 6]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_12(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 12, pX); + sp_384_from_mp(p->y, 12, pY); + sp_384_from_mp(p->z, 12, pZ); + + sp_384_map_12(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mont_sqrt_12(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 12]; + sp_digit t2d[2 * 12]; + sp_digit t3d[2 * 12]; + sp_digit t4d[2 * 12]; + sp_digit t5d[2 * 12]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 12; + t2 = d + 2 * 12; + t3 = d + 4 * 12; + t4 = d + 6 * 12; + t5 = d + 8 * 12; +#else + t1 = t1d; + t2 = t2d; + t3 = t3d; + t4 = t4d; + t5 = t5d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_384_mont_sqr_12(t2, y, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3 */ + sp_384_mont_mul_12(t1, t2, y, p384_mod, p384_mp_mod); + /* t5 = y ^ 0xc */ + sp_384_mont_sqr_n_12(t5, t1, 2, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xf */ + sp_384_mont_mul_12(t1, t1, t5, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x1e */ + sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x1f */ + sp_384_mont_mul_12(t3, t2, y, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3e0 */ + sp_384_mont_sqr_n_12(t2, t3, 5, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3ff */ + sp_384_mont_mul_12(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fe0 */ + sp_384_mont_sqr_n_12(t2, t1, 5, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x7fff */ + sp_384_mont_mul_12(t3, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fff800 */ + sp_384_mont_sqr_n_12(t2, t3, 15, p384_mod, p384_mp_mod); + /* t4 = y ^ 0x3ffffff */ + sp_384_mont_mul_12(t4, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffc000000 */ + sp_384_mont_sqr_n_12(t2, t4, 30, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffff */ + sp_384_mont_mul_12(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_12(t2, t1, 60, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_12(t2, t1, 120, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_12(t2, t1, 15, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */ + sp_384_mont_sqr_n_12(t2, t1, 31, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */ + sp_384_mont_mul_12(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */ + sp_384_mont_sqr_n_12(t2, t1, 4, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */ + sp_384_mont_mul_12(t1, t5, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */ + sp_384_mont_sqr_n_12(t2, t1, 62, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */ + sp_384_mont_mul_12(t1, y, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */ + sp_384_mont_sqr_n_12(y, t1, 30, p384_mod, p384_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 12]; + sp_digit yd[2 * 12]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 12, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 12; + y = d + 2 * 12; +#else + x = xd; + y = yd; +#endif + + sp_384_from_mp(x, 12, xm); + err = sp_384_mod_mul_norm_12(x, x, p384_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_384_mont_sqr_12(y, x, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(y, y, x, p384_mod, p384_mp_mod); + } + /* y = x^3 - 3x */ + sp_384_mont_sub_12(y, y, x, p384_mod); + sp_384_mont_sub_12(y, y, x, p384_mod); + sp_384_mont_sub_12(y, y, x, p384_mod); + /* y = x^3 - 3x + b */ + err = sp_384_mod_mul_norm_12(x, p384_b, p384_mod); + } + if (err == MP_OKAY) { + sp_384_mont_add_12(y, y, x, p384_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_384_mont_sqrt_12(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 12, 0, 12U * sizeof(sp_digit)); + sp_384_mont_reduce_12(y, p384_mod, p384_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_384_mont_sub_12(y, p384_mod, y, p384_mod); + } + + err = sp_384_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_384 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_SP_ARM_THUMB_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_c32.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_c32.c new file mode 100644 index 000000000..4b9596dc7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_c32.c @@ -0,0 +1,23857 @@ +/* sp.c + * + * Copyright (C) 2006-2020 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 +#ifndef SP_RSA_PRIVATE_EXP_D +#define SP_RSA_PRIVATE_EXP_D +#endif + +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifndef WOLFSSL_SP_ASM +#if SP_WORD_SIZE == 32 +#if (defined(WOLFSSL_SP_CACHE_RESISTANT) || defined(WOLFSSL_SP_SMALL)) && (defined(WOLFSSL_HAVE_SP_ECC) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* 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 + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 15U) { + r[j] &= 0x7fffff; + s = 23U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 23 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 23 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x7fffff; + s = 23U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 23U) <= (word32)DIGIT_BIT) { + s += 23U; + r[j] &= 0x7fffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 23) { + r[j] &= 0x7fffff; + if (j + 1 >= size) { + break; + } + s = 23 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * 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<89; i++) { + r[i+1] += r[i] >> 23; + r[i] &= 0x7fffff; + } + j = 2048 / 8 - 1; + a[j] = 0; + for (i=0; i<90 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 23) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 23); + if (j >= 0) { + 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. + */ +SP_NOINLINE static void sp_2048_mul_15(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[ 0]) * b[10] + + ((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)a[10]) * b[ 0]; + int64_t t11 = ((int64_t)a[ 0]) * b[11] + + ((int64_t)a[ 1]) * b[10] + + ((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)a[10]) * b[ 1] + + ((int64_t)a[11]) * b[ 0]; + int64_t t12 = ((int64_t)a[ 0]) * b[12] + + ((int64_t)a[ 1]) * b[11] + + ((int64_t)a[ 2]) * b[10] + + ((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)a[10]) * b[ 2] + + ((int64_t)a[11]) * b[ 1] + + ((int64_t)a[12]) * b[ 0]; + int64_t t13 = ((int64_t)a[ 0]) * b[13] + + ((int64_t)a[ 1]) * b[12] + + ((int64_t)a[ 2]) * b[11] + + ((int64_t)a[ 3]) * b[10] + + ((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)a[10]) * b[ 3] + + ((int64_t)a[11]) * b[ 2] + + ((int64_t)a[12]) * b[ 1] + + ((int64_t)a[13]) * b[ 0]; + int64_t t14 = ((int64_t)a[ 0]) * b[14] + + ((int64_t)a[ 1]) * b[13] + + ((int64_t)a[ 2]) * b[12] + + ((int64_t)a[ 3]) * b[11] + + ((int64_t)a[ 4]) * b[10] + + ((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)a[10]) * b[ 4] + + ((int64_t)a[11]) * b[ 3] + + ((int64_t)a[12]) * b[ 2] + + ((int64_t)a[13]) * b[ 1] + + ((int64_t)a[14]) * b[ 0]; + int64_t t15 = ((int64_t)a[ 1]) * b[14] + + ((int64_t)a[ 2]) * b[13] + + ((int64_t)a[ 3]) * b[12] + + ((int64_t)a[ 4]) * b[11] + + ((int64_t)a[ 5]) * b[10] + + ((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)a[10]) * b[ 5] + + ((int64_t)a[11]) * b[ 4] + + ((int64_t)a[12]) * b[ 3] + + ((int64_t)a[13]) * b[ 2] + + ((int64_t)a[14]) * b[ 1]; + int64_t t16 = ((int64_t)a[ 2]) * b[14] + + ((int64_t)a[ 3]) * b[13] + + ((int64_t)a[ 4]) * b[12] + + ((int64_t)a[ 5]) * b[11] + + ((int64_t)a[ 6]) * b[10] + + ((int64_t)a[ 7]) * b[ 9] + + ((int64_t)a[ 8]) * b[ 8] + + ((int64_t)a[ 9]) * b[ 7] + + ((int64_t)a[10]) * b[ 6] + + ((int64_t)a[11]) * b[ 5] + + ((int64_t)a[12]) * b[ 4] + + ((int64_t)a[13]) * b[ 3] + + ((int64_t)a[14]) * b[ 2]; + int64_t t17 = ((int64_t)a[ 3]) * b[14] + + ((int64_t)a[ 4]) * b[13] + + ((int64_t)a[ 5]) * b[12] + + ((int64_t)a[ 6]) * b[11] + + ((int64_t)a[ 7]) * b[10] + + ((int64_t)a[ 8]) * b[ 9] + + ((int64_t)a[ 9]) * b[ 8] + + ((int64_t)a[10]) * b[ 7] + + ((int64_t)a[11]) * b[ 6] + + ((int64_t)a[12]) * b[ 5] + + ((int64_t)a[13]) * b[ 4] + + ((int64_t)a[14]) * b[ 3]; + int64_t t18 = ((int64_t)a[ 4]) * b[14] + + ((int64_t)a[ 5]) * b[13] + + ((int64_t)a[ 6]) * b[12] + + ((int64_t)a[ 7]) * b[11] + + ((int64_t)a[ 8]) * b[10] + + ((int64_t)a[ 9]) * b[ 9] + + ((int64_t)a[10]) * b[ 8] + + ((int64_t)a[11]) * b[ 7] + + ((int64_t)a[12]) * b[ 6] + + ((int64_t)a[13]) * b[ 5] + + ((int64_t)a[14]) * b[ 4]; + int64_t t19 = ((int64_t)a[ 5]) * b[14] + + ((int64_t)a[ 6]) * b[13] + + ((int64_t)a[ 7]) * b[12] + + ((int64_t)a[ 8]) * b[11] + + ((int64_t)a[ 9]) * b[10] + + ((int64_t)a[10]) * b[ 9] + + ((int64_t)a[11]) * b[ 8] + + ((int64_t)a[12]) * b[ 7] + + ((int64_t)a[13]) * b[ 6] + + ((int64_t)a[14]) * b[ 5]; + int64_t t20 = ((int64_t)a[ 6]) * b[14] + + ((int64_t)a[ 7]) * b[13] + + ((int64_t)a[ 8]) * b[12] + + ((int64_t)a[ 9]) * b[11] + + ((int64_t)a[10]) * b[10] + + ((int64_t)a[11]) * b[ 9] + + ((int64_t)a[12]) * b[ 8] + + ((int64_t)a[13]) * b[ 7] + + ((int64_t)a[14]) * b[ 6]; + int64_t t21 = ((int64_t)a[ 7]) * b[14] + + ((int64_t)a[ 8]) * b[13] + + ((int64_t)a[ 9]) * b[12] + + ((int64_t)a[10]) * b[11] + + ((int64_t)a[11]) * b[10] + + ((int64_t)a[12]) * b[ 9] + + ((int64_t)a[13]) * b[ 8] + + ((int64_t)a[14]) * b[ 7]; + int64_t t22 = ((int64_t)a[ 8]) * b[14] + + ((int64_t)a[ 9]) * b[13] + + ((int64_t)a[10]) * b[12] + + ((int64_t)a[11]) * b[11] + + ((int64_t)a[12]) * b[10] + + ((int64_t)a[13]) * b[ 9] + + ((int64_t)a[14]) * b[ 8]; + int64_t t23 = ((int64_t)a[ 9]) * b[14] + + ((int64_t)a[10]) * b[13] + + ((int64_t)a[11]) * b[12] + + ((int64_t)a[12]) * b[11] + + ((int64_t)a[13]) * b[10] + + ((int64_t)a[14]) * b[ 9]; + int64_t t24 = ((int64_t)a[10]) * b[14] + + ((int64_t)a[11]) * b[13] + + ((int64_t)a[12]) * b[12] + + ((int64_t)a[13]) * b[11] + + ((int64_t)a[14]) * b[10]; + int64_t t25 = ((int64_t)a[11]) * b[14] + + ((int64_t)a[12]) * b[13] + + ((int64_t)a[13]) * b[12] + + ((int64_t)a[14]) * b[11]; + int64_t t26 = ((int64_t)a[12]) * b[14] + + ((int64_t)a[13]) * b[13] + + ((int64_t)a[14]) * b[12]; + int64_t t27 = ((int64_t)a[13]) * b[14] + + ((int64_t)a[14]) * b[13]; + int64_t t28 = ((int64_t)a[14]) * b[14]; + + t1 += t0 >> 23; r[ 0] = t0 & 0x7fffff; + t2 += t1 >> 23; r[ 1] = t1 & 0x7fffff; + t3 += t2 >> 23; r[ 2] = t2 & 0x7fffff; + t4 += t3 >> 23; r[ 3] = t3 & 0x7fffff; + t5 += t4 >> 23; r[ 4] = t4 & 0x7fffff; + t6 += t5 >> 23; r[ 5] = t5 & 0x7fffff; + t7 += t6 >> 23; r[ 6] = t6 & 0x7fffff; + t8 += t7 >> 23; r[ 7] = t7 & 0x7fffff; + t9 += t8 >> 23; r[ 8] = t8 & 0x7fffff; + t10 += t9 >> 23; r[ 9] = t9 & 0x7fffff; + t11 += t10 >> 23; r[10] = t10 & 0x7fffff; + t12 += t11 >> 23; r[11] = t11 & 0x7fffff; + t13 += t12 >> 23; r[12] = t12 & 0x7fffff; + t14 += t13 >> 23; r[13] = t13 & 0x7fffff; + t15 += t14 >> 23; r[14] = t14 & 0x7fffff; + t16 += t15 >> 23; r[15] = t15 & 0x7fffff; + t17 += t16 >> 23; r[16] = t16 & 0x7fffff; + t18 += t17 >> 23; r[17] = t17 & 0x7fffff; + t19 += t18 >> 23; r[18] = t18 & 0x7fffff; + t20 += t19 >> 23; r[19] = t19 & 0x7fffff; + t21 += t20 >> 23; r[20] = t20 & 0x7fffff; + t22 += t21 >> 23; r[21] = t21 & 0x7fffff; + t23 += t22 >> 23; r[22] = t22 & 0x7fffff; + t24 += t23 >> 23; r[23] = t23 & 0x7fffff; + t25 += t24 >> 23; r[24] = t24 & 0x7fffff; + t26 += t25 >> 23; r[25] = t25 & 0x7fffff; + t27 += t26 >> 23; r[26] = t26 & 0x7fffff; + t28 += t27 >> 23; r[27] = t27 & 0x7fffff; + r[29] = (sp_digit)(t28 >> 23); + r[28] = t28 & 0x7fffff; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_15(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[ 0]) * a[10] + + ((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[ 0]) * a[11] + + ((int64_t)a[ 1]) * a[10] + + ((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[ 0]) * a[12] + + ((int64_t)a[ 1]) * a[11] + + ((int64_t)a[ 2]) * a[10] + + ((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[ 0]) * a[13] + + ((int64_t)a[ 1]) * a[12] + + ((int64_t)a[ 2]) * a[11] + + ((int64_t)a[ 3]) * a[10] + + ((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[ 0]) * a[14] + + ((int64_t)a[ 1]) * a[13] + + ((int64_t)a[ 2]) * a[12] + + ((int64_t)a[ 3]) * a[11] + + ((int64_t)a[ 4]) * a[10] + + ((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[ 1]) * a[14] + + ((int64_t)a[ 2]) * a[13] + + ((int64_t)a[ 3]) * a[12] + + ((int64_t)a[ 4]) * a[11] + + ((int64_t)a[ 5]) * a[10] + + ((int64_t)a[ 6]) * a[ 9] + + ((int64_t)a[ 7]) * a[ 8]) * 2; + int64_t t16 = (((int64_t)a[ 2]) * a[14] + + ((int64_t)a[ 3]) * a[13] + + ((int64_t)a[ 4]) * a[12] + + ((int64_t)a[ 5]) * a[11] + + ((int64_t)a[ 6]) * a[10] + + ((int64_t)a[ 7]) * a[ 9]) * 2 + + ((int64_t)a[ 8]) * a[ 8]; + int64_t t17 = (((int64_t)a[ 3]) * a[14] + + ((int64_t)a[ 4]) * a[13] + + ((int64_t)a[ 5]) * a[12] + + ((int64_t)a[ 6]) * a[11] + + ((int64_t)a[ 7]) * a[10] + + ((int64_t)a[ 8]) * a[ 9]) * 2; + int64_t t18 = (((int64_t)a[ 4]) * a[14] + + ((int64_t)a[ 5]) * a[13] + + ((int64_t)a[ 6]) * a[12] + + ((int64_t)a[ 7]) * a[11] + + ((int64_t)a[ 8]) * a[10]) * 2 + + ((int64_t)a[ 9]) * a[ 9]; + int64_t t19 = (((int64_t)a[ 5]) * a[14] + + ((int64_t)a[ 6]) * a[13] + + ((int64_t)a[ 7]) * a[12] + + ((int64_t)a[ 8]) * a[11] + + ((int64_t)a[ 9]) * a[10]) * 2; + int64_t t20 = (((int64_t)a[ 6]) * a[14] + + ((int64_t)a[ 7]) * a[13] + + ((int64_t)a[ 8]) * a[12] + + ((int64_t)a[ 9]) * a[11]) * 2 + + ((int64_t)a[10]) * a[10]; + int64_t t21 = (((int64_t)a[ 7]) * a[14] + + ((int64_t)a[ 8]) * a[13] + + ((int64_t)a[ 9]) * a[12] + + ((int64_t)a[10]) * a[11]) * 2; + int64_t t22 = (((int64_t)a[ 8]) * a[14] + + ((int64_t)a[ 9]) * a[13] + + ((int64_t)a[10]) * a[12]) * 2 + + ((int64_t)a[11]) * a[11]; + int64_t t23 = (((int64_t)a[ 9]) * a[14] + + ((int64_t)a[10]) * a[13] + + ((int64_t)a[11]) * a[12]) * 2; + int64_t t24 = (((int64_t)a[10]) * a[14] + + ((int64_t)a[11]) * a[13]) * 2 + + ((int64_t)a[12]) * a[12]; + int64_t t25 = (((int64_t)a[11]) * a[14] + + ((int64_t)a[12]) * a[13]) * 2; + int64_t t26 = (((int64_t)a[12]) * a[14]) * 2 + + ((int64_t)a[13]) * a[13]; + int64_t t27 = (((int64_t)a[13]) * a[14]) * 2; + int64_t t28 = ((int64_t)a[14]) * a[14]; + + t1 += t0 >> 23; r[ 0] = t0 & 0x7fffff; + t2 += t1 >> 23; r[ 1] = t1 & 0x7fffff; + t3 += t2 >> 23; r[ 2] = t2 & 0x7fffff; + t4 += t3 >> 23; r[ 3] = t3 & 0x7fffff; + t5 += t4 >> 23; r[ 4] = t4 & 0x7fffff; + t6 += t5 >> 23; r[ 5] = t5 & 0x7fffff; + t7 += t6 >> 23; r[ 6] = t6 & 0x7fffff; + t8 += t7 >> 23; r[ 7] = t7 & 0x7fffff; + t9 += t8 >> 23; r[ 8] = t8 & 0x7fffff; + t10 += t9 >> 23; r[ 9] = t9 & 0x7fffff; + t11 += t10 >> 23; r[10] = t10 & 0x7fffff; + t12 += t11 >> 23; r[11] = t11 & 0x7fffff; + t13 += t12 >> 23; r[12] = t12 & 0x7fffff; + t14 += t13 >> 23; r[13] = t13 & 0x7fffff; + t15 += t14 >> 23; r[14] = t14 & 0x7fffff; + t16 += t15 >> 23; r[15] = t15 & 0x7fffff; + t17 += t16 >> 23; r[16] = t16 & 0x7fffff; + t18 += t17 >> 23; r[17] = t17 & 0x7fffff; + t19 += t18 >> 23; r[18] = t18 & 0x7fffff; + t20 += t19 >> 23; r[19] = t19 & 0x7fffff; + t21 += t20 >> 23; r[20] = t20 & 0x7fffff; + t22 += t21 >> 23; r[21] = t21 & 0x7fffff; + t23 += t22 >> 23; r[22] = t22 & 0x7fffff; + t24 += t23 >> 23; r[23] = t23 & 0x7fffff; + t25 += t24 >> 23; r[24] = t24 & 0x7fffff; + t26 += t25 >> 23; r[25] = t25 & 0x7fffff; + t27 += t26 >> 23; r[26] = t26 & 0x7fffff; + t28 += t27 >> 23; r[27] = t27 & 0x7fffff; + r[29] = (sp_digit)(t28 >> 23); + r[28] = t28 & 0x7fffff; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_15(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]; + r[10] = a[10] + b[10]; + r[11] = a[11] + b[11]; + r[12] = a[12] + b[12]; + r[13] = a[13] + b[13]; + r[14] = a[14] + b[14]; + + 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. + */ +SP_NOINLINE static int sp_2048_sub_30(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]; + r[27] = a[27] - b[27]; + r[28] = a[28] - b[28]; + r[29] = a[29] - b[29]; + + 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. + */ +SP_NOINLINE static int sp_2048_add_30(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]; + r[27] = a[27] + b[27]; + r[28] = a[28] + b[28]; + r[29] = a[29] + b[29]; + + 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. + */ +SP_NOINLINE static void sp_2048_mul_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit p0[30]; + sp_digit p1[30]; + sp_digit p2[30]; + sp_digit p3[30]; + sp_digit p4[30]; + sp_digit p5[30]; + sp_digit t0[30]; + sp_digit t1[30]; + sp_digit t2[30]; + sp_digit a0[15]; + sp_digit a1[15]; + sp_digit a2[15]; + sp_digit b0[15]; + sp_digit b1[15]; + sp_digit b2[15]; + (void)sp_2048_add_15(a0, a, &a[15]); + (void)sp_2048_add_15(b0, b, &b[15]); + (void)sp_2048_add_15(a1, &a[15], &a[30]); + (void)sp_2048_add_15(b1, &b[15], &b[30]); + (void)sp_2048_add_15(a2, a0, &a[30]); + (void)sp_2048_add_15(b2, b0, &b[30]); + sp_2048_mul_15(p0, a, b); + sp_2048_mul_15(p2, &a[15], &b[15]); + sp_2048_mul_15(p4, &a[30], &b[30]); + sp_2048_mul_15(p1, a0, b0); + sp_2048_mul_15(p3, a1, b1); + sp_2048_mul_15(p5, a2, b2); + XMEMSET(r, 0, sizeof(*r)*2U*45U); + (void)sp_2048_sub_30(t0, p3, p2); + (void)sp_2048_sub_30(t1, p1, p2); + (void)sp_2048_sub_30(t2, p5, t0); + (void)sp_2048_sub_30(t2, t2, t1); + (void)sp_2048_sub_30(t0, t0, p4); + (void)sp_2048_sub_30(t1, t1, p0); + (void)sp_2048_add_30(r, r, p0); + (void)sp_2048_add_30(&r[15], &r[15], t1); + (void)sp_2048_add_30(&r[30], &r[30], t2); + (void)sp_2048_add_30(&r[45], &r[45], t0); + (void)sp_2048_add_30(&r[60], &r[60], p4); +} + +/* Square a into r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_45(sp_digit* r, const sp_digit* a) +{ + sp_digit p0[30]; + sp_digit p1[30]; + sp_digit p2[30]; + sp_digit p3[30]; + sp_digit p4[30]; + sp_digit p5[30]; + sp_digit t0[30]; + sp_digit t1[30]; + sp_digit t2[30]; + sp_digit a0[15]; + sp_digit a1[15]; + sp_digit a2[15]; + (void)sp_2048_add_15(a0, a, &a[15]); + (void)sp_2048_add_15(a1, &a[15], &a[30]); + (void)sp_2048_add_15(a2, a0, &a[30]); + sp_2048_sqr_15(p0, a); + sp_2048_sqr_15(p2, &a[15]); + sp_2048_sqr_15(p4, &a[30]); + sp_2048_sqr_15(p1, a0); + sp_2048_sqr_15(p3, a1); + sp_2048_sqr_15(p5, a2); + XMEMSET(r, 0, sizeof(*r)*2U*45U); + (void)sp_2048_sub_30(t0, p3, p2); + (void)sp_2048_sub_30(t1, p1, p2); + (void)sp_2048_sub_30(t2, p5, t0); + (void)sp_2048_sub_30(t2, t2, t1); + (void)sp_2048_sub_30(t0, t0, p4); + (void)sp_2048_sub_30(t1, t1, p0); + (void)sp_2048_add_30(r, r, p0); + (void)sp_2048_add_30(&r[15], &r[15], t1); + (void)sp_2048_add_30(&r[30], &r[30], t2); + (void)sp_2048_add_30(&r[45], &r[45], t0); + (void)sp_2048_add_30(&r[60], &r[60], p4); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 40; 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[40] = a[40] + b[40]; + r[41] = a[41] + b[41]; + r[42] = a[42] + b[42]; + r[43] = a[43] + b[43]; + r[44] = a[44] + b[44]; + + 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. + */ +SP_NOINLINE static int sp_2048_add_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 88; 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[88] = a[88] + b[88]; + r[89] = a[89] + b[89]; + + 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. + */ +SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 88; 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[88] = a[88] - b[88]; + r[89] = a[89] - b[89]; + + 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. + */ +SP_NOINLINE static void sp_2048_mul_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[90]; + sp_digit* a1 = z1; + sp_digit b1[45]; + sp_digit* z2 = r + 90; + (void)sp_2048_add_45(a1, a, &a[45]); + (void)sp_2048_add_45(b1, b, &b[45]); + sp_2048_mul_45(z2, &a[45], &b[45]); + sp_2048_mul_45(z0, a, b); + sp_2048_mul_45(z1, a1, b1); + (void)sp_2048_sub_90(z1, z1, z2); + (void)sp_2048_sub_90(z1, z1, z0); + (void)sp_2048_add_90(r + 45, r + 45, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_90(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[90]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 90; + (void)sp_2048_add_45(a1, a, &a[45]); + sp_2048_sqr_45(z2, &a[45]); + sp_2048_sqr_45(z0, a); + sp_2048_sqr_45(z1, a1); + (void)sp_2048_sub_90(z1, z1, z2); + (void)sp_2048_sub_90(z1, z1, z0); + (void)sp_2048_add_90(r + 45, r + 45, 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. + */ +SP_NOINLINE static int sp_2048_add_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 90; 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. + */ +SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 90; 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. + */ +SP_NOINLINE static void sp_2048_mul_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[89]) * b[89]; + r[179] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 177; k >= 0; k--) { + for (i = 89; i >= 0; i--) { + j = k - i; + if (j >= 90) { + break; + } + if (j < 0) { + continue; + } + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_90(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[89]) * a[89]; + r[179] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 177; k >= 0; k--) { + for (i = 89; i >= 0; i--) { + j = k - i; + if (j >= 90 || 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 >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#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. + */ +SP_NOINLINE static int sp_2048_add_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 45; 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. + */ +SP_NOINLINE static int sp_2048_sub_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 45; 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. + */ +SP_NOINLINE static int sp_2048_sub_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 40; 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[40] = a[40] - b[40]; + r[41] = a[41] - b[41]; + r[42] = a[42] - b[42]; + r[43] = a[43] - b[43]; + r[44] = a[44] - b[44]; + + 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. + */ +SP_NOINLINE static void sp_2048_mul_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[44]) * b[44]; + r[89] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 87; k >= 0; k--) { + for (i = 44; i >= 0; i--) { + j = k - i; + if (j >= 45) { + break; + } + if (j < 0) { + continue; + } + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_45(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[44]) * a[44]; + r[89] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 87; k >= 0; k--) { + for (i = 44; i >= 0; i--) { + j = k - i; + if (j >= 45 || 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 >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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 &= 0x7fffff; + + /* rho = -1/m mod b */ + *rho = (1L << 23) - x; +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_2048_mul_d_90(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 90; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[90] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff; + for (i = 0; i < 88; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[89]; + r[89] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + r[90] = (sp_digit)(t[1] >> 23); +#endif /* WOLFSSL_SP_SMALL */ +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_2048_mont_norm_45(sp_digit* r, const sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<44; i++) { + r[i] = 0x7fffff; + } +#else + int i; + + for (i = 0; i < 40; i += 8) { + r[i + 0] = 0x7fffff; + r[i + 1] = 0x7fffff; + r[i + 2] = 0x7fffff; + r[i + 3] = 0x7fffff; + r[i + 4] = 0x7fffff; + r[i + 5] = 0x7fffff; + r[i + 6] = 0x7fffff; + r[i + 7] = 0x7fffff; + } + r[40] = 0x7fffff; + r[41] = 0x7fffff; + r[42] = 0x7fffff; + r[43] = 0x7fffff; +#endif + r[44] = 0xfffL; + + /* r = (2^n - 1) mod n */ + (void)sp_2048_sub_45(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_45(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=44; i>=0; i--) { + r |= (a[i] - b[i]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[44] - b[44]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[43] - b[43]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[42] - b[42]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[41] - b[41]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[40] - b[40]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 32; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#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_45(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 < 45; i++) { + r[i] = a[i] - (b[i] & m); + } +#else + int i; + + for (i = 0; i < 40; 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[40] = a[40] - (b[40] & m); + r[41] = a[41] - (b[41] & m); + r[42] = a[42] - (b[42] & m); + r[43] = a[43] - (b[43] & m); + r[44] = a[44] - (b[44] & 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. + */ +SP_NOINLINE static void sp_2048_mul_add_45(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 < 45; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[45] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x7fffff); + for (i = 0; i < 40; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (sp_digit)((t[0] >> 23) + (t[1] & 0x7fffff)); + t[2] = tb * a[i+2]; + r[i+2] += (sp_digit)((t[1] >> 23) + (t[2] & 0x7fffff)); + t[3] = tb * a[i+3]; + r[i+3] += (sp_digit)((t[2] >> 23) + (t[3] & 0x7fffff)); + t[4] = tb * a[i+4]; + r[i+4] += (sp_digit)((t[3] >> 23) + (t[4] & 0x7fffff)); + t[5] = tb * a[i+5]; + r[i+5] += (sp_digit)((t[4] >> 23) + (t[5] & 0x7fffff)); + t[6] = tb * a[i+6]; + r[i+6] += (sp_digit)((t[5] >> 23) + (t[6] & 0x7fffff)); + t[7] = tb * a[i+7]; + r[i+7] += (sp_digit)((t[6] >> 23) + (t[7] & 0x7fffff)); + t[0] = tb * a[i+8]; + r[i+8] += (sp_digit)((t[7] >> 23) + (t[0] & 0x7fffff)); + } + t[1] = tb * a[41]; r[41] += (sp_digit)((t[0] >> 23) + (t[1] & 0x7fffff)); + t[2] = tb * a[42]; r[42] += (sp_digit)((t[1] >> 23) + (t[2] & 0x7fffff)); + t[3] = tb * a[43]; r[43] += (sp_digit)((t[2] >> 23) + (t[3] & 0x7fffff)); + t[4] = tb * a[44]; r[44] += (sp_digit)((t[3] >> 23) + (t[4] & 0x7fffff)); + r[45] += (sp_digit)(t[4] >> 23); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 23. + * + * a Array of sp_digit to normalize. + */ +static void sp_2048_norm_45(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 44; i++) { + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + int i; + for (i = 0; i < 40; i += 8) { + a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff; + a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff; + a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff; + a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff; + a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff; + a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff; + a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff; + a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff; + a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff; + } + a[40+1] += a[40] >> 23; + a[40] &= 0x7fffff; + a[41+1] += a[41] >> 23; + a[41] &= 0x7fffff; + a[42+1] += a[42] >> 23; + a[42] &= 0x7fffff; + a[43+1] += a[43] >> 23; + a[43] &= 0x7fffff; +#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_45(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int64_t n = a[44] >> 12; + n += ((int64_t)a[45]) << 11; + + for (i = 0; i < 44; i++) { + r[i] = n & 0x7fffff; + n >>= 23; + n += ((int64_t)a[46 + i]) << 11; + } + r[44] = (sp_digit)n; +#else + int i; + int64_t n = a[44] >> 12; + n += ((int64_t)a[45]) << 11; + for (i = 0; i < 40; i += 8) { + r[i + 0] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 46]) << 11; + r[i + 1] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 47]) << 11; + r[i + 2] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 48]) << 11; + r[i + 3] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 49]) << 11; + r[i + 4] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 50]) << 11; + r[i + 5] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 51]) << 11; + r[i + 6] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 52]) << 11; + r[i + 7] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 53]) << 11; + } + r[40] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[86]) << 11; + r[41] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[87]) << 11; + r[42] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[88]) << 11; + r[43] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[89]) << 11; + r[44] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[45], 0, sizeof(*r) * 45U); +} + +/* 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_45(sp_digit* a, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_2048_norm_45(a + 45); + + for (i=0; i<44; i++) { + mu = (a[i] * mp) & 0x7fffff; + sp_2048_mul_add_45(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = (a[i] * mp) & 0xfffL; + sp_2048_mul_add_45(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + + sp_2048_mont_shift_45(a, a); + sp_2048_cond_sub_45(a, a, m, 0 - (((a[44] >> 12) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_2048_norm_45(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_45(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_2048_mul_45(r, a, b); + sp_2048_mont_reduce_45(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_45(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_45(r, a); + sp_2048_mont_reduce_45(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. + */ +SP_NOINLINE static void sp_2048_mul_d_45(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 45; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[45] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff; + for (i = 0; i < 40; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[41]; + r[41] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[42]; + r[42] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[43]; + r[43] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[44]; + r[44] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + r[45] = (sp_digit)(t[4] >> 23); +#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_45(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 < 45; i++) { + r[i] = a[i] + (b[i] & m); + } +#else + int i; + + for (i = 0; i < 40; 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[40] = a[40] + (b[40] & m); + r[41] = a[41] + (b[41] & m); + r[42] = a[42] + (b[42] & m); + r[43] = a[43] + (b[43] & m); + r[44] = a[44] + (b[44] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_2048_add_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 45; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#endif +SP_NOINLINE static void sp_2048_rshift_45(sp_digit* r, sp_digit* a, byte n) +{ + int i; + +#ifdef WOLFSSL_SP_SMALL + for (i=0; i<44; i++) { + r[i] = ((a[i] >> n) | (a[i + 1] << (23 - n))) & 0x7fffff; + } +#else + for (i=0; i<40; i += 8) { + r[i+0] = ((a[i+0] >> n) | (a[i+1] << (23 - n))) & 0x7fffff; + r[i+1] = ((a[i+1] >> n) | (a[i+2] << (23 - n))) & 0x7fffff; + r[i+2] = ((a[i+2] >> n) | (a[i+3] << (23 - n))) & 0x7fffff; + r[i+3] = ((a[i+3] >> n) | (a[i+4] << (23 - n))) & 0x7fffff; + r[i+4] = ((a[i+4] >> n) | (a[i+5] << (23 - n))) & 0x7fffff; + r[i+5] = ((a[i+5] >> n) | (a[i+6] << (23 - n))) & 0x7fffff; + r[i+6] = ((a[i+6] >> n) | (a[i+7] << (23 - n))) & 0x7fffff; + r[i+7] = ((a[i+7] >> n) | (a[i+8] << (23 - n))) & 0x7fffff; + } + r[40] = ((a[40] >> n) | (a[41] << (23 - n))) & 0x7fffff; + r[41] = ((a[41] >> n) | (a[42] << (23 - n))) & 0x7fffff; + r[42] = ((a[42] >> n) | (a[43] << (23 - n))) & 0x7fffff; + r[43] = ((a[43] >> n) | (a[44] << (23 - n))) & 0x7fffff; +#endif + r[44] = a[44] >> n; +} + +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_2048_div_word_45(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 23 bits from d1 and top 8 bits from d0. */ + d = (d1 << 8) | (d0 >> 15); + r = d / dv; + d -= r * dv; + /* Up to 9 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 7) & ((1 << 8) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 17 bits in r */ + /* Remaining 7 bits from d0. */ + r <<= 7; + d <<= 7; + d |= d0 & ((1 << 7) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* 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_45(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[90 + 1], t2d[45 + 1], sdd[45 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* sd; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 45 + 3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + (void)m; + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 90 + 1; + sd = t2 + 45 + 1; +#else + t1 = t1d; + t2 = t2d; + sd = sdd; +#endif + + sp_2048_mul_d_45(sd, d, 1L << 11); + sp_2048_mul_d_90(t1, a, 1L << 11); + dv = sd[44]; + for (i=45; i>=0; i--) { + t1[45 + i] += t1[45 + i - 1] >> 23; + t1[45 + i - 1] &= 0x7fffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[45 + i]; + d1 <<= 23; + d1 += t1[45 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_2048_div_word_45(t1[45 + i], t1[45 + i - 1], dv); +#endif + + sp_2048_mul_d_45(t2, sd, r1); + (void)sp_2048_sub_45(&t1[i], &t1[i], t2); + t1[45 + i] -= t2[45]; + t1[45 + i] += t1[45 + i - 1] >> 23; + t1[45 + i - 1] &= 0x7fffff; + r1 = (((-t1[45 + i]) << 23) - t1[45 + i - 1]) / dv; + r1 -= t1[45 + i]; + sp_2048_mul_d_45(t2, sd, r1); + (void)sp_2048_add_45(&t1[i], &t1[i], t2); + t1[45 + i] += t1[45 + i - 1] >> 23; + t1[45 + i - 1] &= 0x7fffff; + } + t1[45 - 1] += t1[45 - 2] >> 23; + t1[45 - 2] &= 0x7fffff; + r1 = t1[45 - 1] / dv; + + sp_2048_mul_d_45(t2, sd, r1); + sp_2048_sub_45(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 45U); + for (i=0; i<43; i++) { + r[i+1] += r[i] >> 23; + r[i] &= 0x7fffff; + } + sp_2048_cond_add_45(r, r, sd, 0 - ((r[44] < 0) ? + (sp_digit)1 : (sp_digit)0)); + + sp_2048_norm_45(r); + sp_2048_rshift_45(r, r, 11); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_45(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_45(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_45(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, + const 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 * 45 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3U * 45U * 2U); + + norm = t[0] = td; + t[1] = &td[45 * 2]; + t[2] = &td[2 * 45 * 2]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_45(norm, m); + + if (reduceA != 0) { + err = sp_2048_mod_45(t[1], a, m); + } + else { + XMEMCPY(t[1], a, sizeof(sp_digit) * 45U); + } + } + if (err == MP_OKAY) { + sp_2048_mul_45(t[1], t[1], norm); + err = sp_2048_mod_45(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) { + break; + } + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_2048_mont_mul_45(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]) * 45 * 2); + sp_2048_mont_sqr_45(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]) * 45 * 2); + } + + sp_2048_mont_reduce_45(t[0], m, mp); + n = sp_2048_cmp_45(t[0], m); + sp_2048_cond_sub_45(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 45 * 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][90]; +#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 * 45 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t[0] = td; + t[1] = &td[45 * 2]; + t[2] = &td[2 * 45 * 2]; +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_45(norm, m); + + if (reduceA != 0) { + err = sp_2048_mod_45(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_45(t[1], t[1], norm); + err = sp_2048_mod_45(t[1], t[1], m); + } + } + else { + sp_2048_mul_45(t[1], a, norm); + err = sp_2048_mod_45(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) { + break; + } + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_2048_mont_mul_45(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_45(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_45(t[0], m, mp); + n = sp_2048_cmp_45(t[0], m); + sp_2048_cond_sub_45(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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][90]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[90]; + 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 * 90, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 90; +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_45(norm, m); + + if (reduceA != 0) { + err = sp_2048_mod_45(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_45(t[1], t[1], norm); + err = sp_2048_mod_45(t[1], t[1], m); + } + } + else { + sp_2048_mul_45(t[1], a, norm); + err = sp_2048_mod_45(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_45(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_45(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_45(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_45(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_45(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_45(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_45(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_45(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_45(t[10], t[ 5], m, mp); + sp_2048_mont_mul_45(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_45(t[12], t[ 6], m, mp); + sp_2048_mont_mul_45(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_45(t[14], t[ 7], m, mp); + sp_2048_mont_mul_45(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_45(t[16], t[ 8], m, mp); + sp_2048_mont_mul_45(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_45(t[18], t[ 9], m, mp); + sp_2048_mont_mul_45(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_45(t[20], t[10], m, mp); + sp_2048_mont_mul_45(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_45(t[22], t[11], m, mp); + sp_2048_mont_mul_45(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_45(t[24], t[12], m, mp); + sp_2048_mont_mul_45(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_45(t[26], t[13], m, mp); + sp_2048_mont_mul_45(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_45(t[28], t[14], m, mp); + sp_2048_mont_mul_45(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_45(t[30], t[15], m, mp); + sp_2048_mont_mul_45(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 22) / 23) - 1; + c = bits % 23; + if (c == 0) { + c = 23; + } + if (i < 45) { + n = e[i--] << (32 - c); + } + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + + sp_2048_mont_sqr_45(rt, rt, m, mp); + sp_2048_mont_sqr_45(rt, rt, m, mp); + sp_2048_mont_sqr_45(rt, rt, m, mp); + sp_2048_mont_sqr_45(rt, rt, m, mp); + sp_2048_mont_sqr_45(rt, rt, m, mp); + + sp_2048_mont_mul_45(rt, rt, t[y], m, mp); + } + + sp_2048_mont_reduce_45(rt, m, mp); + n = sp_2048_cmp_45(rt, m); + sp_2048_cond_sub_45(rt, rt, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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 /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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 single precision number. + */ +static void sp_2048_mont_norm_90(sp_digit* r, const sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<89; i++) { + r[i] = 0x7fffff; + } +#else + int i; + + for (i = 0; i < 88; i += 8) { + r[i + 0] = 0x7fffff; + r[i + 1] = 0x7fffff; + r[i + 2] = 0x7fffff; + r[i + 3] = 0x7fffff; + r[i + 4] = 0x7fffff; + r[i + 5] = 0x7fffff; + r[i + 6] = 0x7fffff; + r[i + 7] = 0x7fffff; + } + r[88] = 0x7fffff; +#endif + r[89] = 0x1L; + + /* r = (2^n - 1) mod n */ + (void)sp_2048_sub_90(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_90(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=89; i>=0; i--) { + r |= (a[i] - b[i]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[89] - b[89]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[88] - b[88]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 80; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#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_90(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 < 90; i++) { + r[i] = a[i] - (b[i] & m); + } +#else + int i; + + for (i = 0; i < 88; 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[88] = a[88] - (b[88] & m); + r[89] = a[89] - (b[89] & 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. + */ +SP_NOINLINE static void sp_2048_mul_add_90(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 < 90; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[90] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x7fffff); + for (i = 0; i < 88; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (sp_digit)((t[0] >> 23) + (t[1] & 0x7fffff)); + t[2] = tb * a[i+2]; + r[i+2] += (sp_digit)((t[1] >> 23) + (t[2] & 0x7fffff)); + t[3] = tb * a[i+3]; + r[i+3] += (sp_digit)((t[2] >> 23) + (t[3] & 0x7fffff)); + t[4] = tb * a[i+4]; + r[i+4] += (sp_digit)((t[3] >> 23) + (t[4] & 0x7fffff)); + t[5] = tb * a[i+5]; + r[i+5] += (sp_digit)((t[4] >> 23) + (t[5] & 0x7fffff)); + t[6] = tb * a[i+6]; + r[i+6] += (sp_digit)((t[5] >> 23) + (t[6] & 0x7fffff)); + t[7] = tb * a[i+7]; + r[i+7] += (sp_digit)((t[6] >> 23) + (t[7] & 0x7fffff)); + t[0] = tb * a[i+8]; + r[i+8] += (sp_digit)((t[7] >> 23) + (t[0] & 0x7fffff)); + } + t[1] = tb * a[89]; r[89] += (sp_digit)((t[0] >> 23) + (t[1] & 0x7fffff)); + r[90] += (sp_digit)(t[1] >> 23); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 23. + * + * a Array of sp_digit to normalize. + */ +static void sp_2048_norm_90(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 89; i++) { + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + int i; + for (i = 0; i < 88; i += 8) { + a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff; + a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff; + a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff; + a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff; + a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff; + a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff; + a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff; + a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff; + a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff; + } + a[88+1] += a[88] >> 23; + a[88] &= 0x7fffff; +#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_90(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int64_t n = a[89] >> 1; + n += ((int64_t)a[90]) << 22; + + for (i = 0; i < 89; i++) { + r[i] = n & 0x7fffff; + n >>= 23; + n += ((int64_t)a[91 + i]) << 22; + } + r[89] = (sp_digit)n; +#else + int i; + int64_t n = a[89] >> 1; + n += ((int64_t)a[90]) << 22; + for (i = 0; i < 88; i += 8) { + r[i + 0] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 91]) << 22; + r[i + 1] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 92]) << 22; + r[i + 2] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 93]) << 22; + r[i + 3] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 94]) << 22; + r[i + 4] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 95]) << 22; + r[i + 5] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 96]) << 22; + r[i + 6] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 97]) << 22; + r[i + 7] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 98]) << 22; + } + r[88] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[179]) << 22; + r[89] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[90], 0, sizeof(*r) * 90U); +} + +/* 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_90(sp_digit* a, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_2048_norm_90(a + 90); + +#ifdef WOLFSSL_SP_DH + if (mp != 1) { + for (i=0; i<89; i++) { + mu = (a[i] * mp) & 0x7fffff; + sp_2048_mul_add_90(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = (a[i] * mp) & 0x1L; + sp_2048_mul_add_90(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } + else { + for (i=0; i<89; i++) { + mu = a[i] & 0x7fffff; + sp_2048_mul_add_90(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = a[i] & 0x1L; + sp_2048_mul_add_90(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + for (i=0; i<89; i++) { + mu = (a[i] * mp) & 0x7fffff; + sp_2048_mul_add_90(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = (a[i] * mp) & 0x1L; + sp_2048_mul_add_90(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; +#endif + + sp_2048_mont_shift_90(a, a); + sp_2048_cond_sub_90(a, a, m, 0 - (((a[89] >> 1) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_2048_norm_90(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_90(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_2048_mul_90(r, a, b); + sp_2048_mont_reduce_90(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_90(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_90(r, a); + sp_2048_mont_reduce_90(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. + */ +SP_NOINLINE static void sp_2048_mul_d_180(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 180; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[180] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff; + for (i = 0; i < 176; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[177]; + r[177] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[178]; + r[178] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[179]; + r[179] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + r[180] = (sp_digit)(t[3] >> 23); +#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_90(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 < 90; i++) { + r[i] = a[i] + (b[i] & m); + } +#else + int i; + + for (i = 0; i < 88; 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[88] = a[88] + (b[88] & m); + r[89] = a[89] + (b[89] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 90; i++) { + r[i] = a[i] - b[i]; + } + + return 0; +} + +#endif +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_2048_add_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 90; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#endif +SP_NOINLINE static void sp_2048_rshift_90(sp_digit* r, sp_digit* a, byte n) +{ + int i; + +#ifdef WOLFSSL_SP_SMALL + for (i=0; i<89; i++) { + r[i] = ((a[i] >> n) | (a[i + 1] << (23 - n))) & 0x7fffff; + } +#else + for (i=0; i<88; i += 8) { + r[i+0] = ((a[i+0] >> n) | (a[i+1] << (23 - n))) & 0x7fffff; + r[i+1] = ((a[i+1] >> n) | (a[i+2] << (23 - n))) & 0x7fffff; + r[i+2] = ((a[i+2] >> n) | (a[i+3] << (23 - n))) & 0x7fffff; + r[i+3] = ((a[i+3] >> n) | (a[i+4] << (23 - n))) & 0x7fffff; + r[i+4] = ((a[i+4] >> n) | (a[i+5] << (23 - n))) & 0x7fffff; + r[i+5] = ((a[i+5] >> n) | (a[i+6] << (23 - n))) & 0x7fffff; + r[i+6] = ((a[i+6] >> n) | (a[i+7] << (23 - n))) & 0x7fffff; + r[i+7] = ((a[i+7] >> n) | (a[i+8] << (23 - n))) & 0x7fffff; + } + r[88] = ((a[88] >> n) | (a[89] << (23 - n))) & 0x7fffff; +#endif + r[89] = a[89] >> n; +} + +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_2048_div_word_90(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 23 bits from d1 and top 8 bits from d0. */ + d = (d1 << 8) | (d0 >> 15); + r = d / dv; + d -= r * dv; + /* Up to 9 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 7) & ((1 << 8) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 17 bits in r */ + /* Remaining 7 bits from d0. */ + r <<= 7; + d <<= 7; + d |= d0 & ((1 << 7) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* 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_90(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[180 + 1], t2d[90 + 1], sdd[90 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* sd; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 90 + 3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + (void)m; + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 180 + 1; + sd = t2 + 90 + 1; +#else + t1 = t1d; + t2 = t2d; + sd = sdd; +#endif + + sp_2048_mul_d_90(sd, d, 1L << 22); + sp_2048_mul_d_180(t1, a, 1L << 22); + dv = sd[89]; + for (i=90; i>=0; i--) { + t1[90 + i] += t1[90 + i - 1] >> 23; + t1[90 + i - 1] &= 0x7fffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[90 + i]; + d1 <<= 23; + d1 += t1[90 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_2048_div_word_90(t1[90 + i], t1[90 + i - 1], dv); +#endif + + sp_2048_mul_d_90(t2, sd, r1); + (void)sp_2048_sub_90(&t1[i], &t1[i], t2); + t1[90 + i] -= t2[90]; + t1[90 + i] += t1[90 + i - 1] >> 23; + t1[90 + i - 1] &= 0x7fffff; + r1 = (((-t1[90 + i]) << 23) - t1[90 + i - 1]) / dv; + r1 -= t1[90 + i]; + sp_2048_mul_d_90(t2, sd, r1); + (void)sp_2048_add_90(&t1[i], &t1[i], t2); + t1[90 + i] += t1[90 + i - 1] >> 23; + t1[90 + i - 1] &= 0x7fffff; + } + t1[90 - 1] += t1[90 - 2] >> 23; + t1[90 - 2] &= 0x7fffff; + r1 = t1[90 - 1] / dv; + + sp_2048_mul_d_90(t2, sd, r1); + sp_2048_sub_90(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 90U); + for (i=0; i<88; i++) { + r[i+1] += r[i] >> 23; + r[i] &= 0x7fffff; + } + sp_2048_cond_add_90(r, r, sd, 0 - ((r[89] < 0) ? + (sp_digit)1 : (sp_digit)0)); + + sp_2048_norm_90(r); + sp_2048_rshift_90(r, r, 22); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_90(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_90(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + 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_90(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, + const 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 * 90 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3U * 90U * 2U); + + norm = t[0] = td; + t[1] = &td[90 * 2]; + t[2] = &td[2 * 90 * 2]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_90(norm, m); + + if (reduceA != 0) { + err = sp_2048_mod_90(t[1], a, m); + } + else { + XMEMCPY(t[1], a, sizeof(sp_digit) * 90U); + } + } + if (err == MP_OKAY) { + sp_2048_mul_90(t[1], t[1], norm); + err = sp_2048_mod_90(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) { + break; + } + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_2048_mont_mul_90(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]) * 90 * 2); + sp_2048_mont_sqr_90(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]) * 90 * 2); + } + + sp_2048_mont_reduce_90(t[0], m, mp); + n = sp_2048_cmp_90(t[0], m); + sp_2048_cond_sub_90(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 90 * 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][180]; +#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 * 90 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t[0] = td; + t[1] = &td[90 * 2]; + t[2] = &td[2 * 90 * 2]; +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_90(norm, m); + + if (reduceA != 0) { + err = sp_2048_mod_90(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_90(t[1], t[1], norm); + err = sp_2048_mod_90(t[1], t[1], m); + } + } + else { + sp_2048_mul_90(t[1], a, norm); + err = sp_2048_mod_90(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) { + break; + } + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_2048_mont_mul_90(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_90(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_90(t[0], m, mp); + n = sp_2048_cmp_90(t[0], m); + sp_2048_cond_sub_90(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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][180]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[180]; + 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 * 180, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 180; +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_90(norm, m); + + if (reduceA != 0) { + err = sp_2048_mod_90(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_90(t[1], t[1], norm); + err = sp_2048_mod_90(t[1], t[1], m); + } + } + else { + sp_2048_mul_90(t[1], a, norm); + err = sp_2048_mod_90(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_90(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_90(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_90(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_90(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_90(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_90(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_90(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_90(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_90(t[10], t[ 5], m, mp); + sp_2048_mont_mul_90(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_90(t[12], t[ 6], m, mp); + sp_2048_mont_mul_90(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_90(t[14], t[ 7], m, mp); + sp_2048_mont_mul_90(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_90(t[16], t[ 8], m, mp); + sp_2048_mont_mul_90(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_90(t[18], t[ 9], m, mp); + sp_2048_mont_mul_90(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_90(t[20], t[10], m, mp); + sp_2048_mont_mul_90(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_90(t[22], t[11], m, mp); + sp_2048_mont_mul_90(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_90(t[24], t[12], m, mp); + sp_2048_mont_mul_90(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_90(t[26], t[13], m, mp); + sp_2048_mont_mul_90(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_90(t[28], t[14], m, mp); + sp_2048_mont_mul_90(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_90(t[30], t[15], m, mp); + sp_2048_mont_mul_90(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 22) / 23) - 1; + c = bits % 23; + if (c == 0) { + c = 23; + } + if (i < 90) { + n = e[i--] << (32 - c); + } + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + + sp_2048_mont_sqr_90(rt, rt, m, mp); + sp_2048_mont_sqr_90(rt, rt, m, mp); + sp_2048_mont_sqr_90(rt, rt, m, mp); + sp_2048_mont_sqr_90(rt, rt, m, mp); + sp_2048_mont_sqr_90(rt, rt, m, mp); + + sp_2048_mont_mul_90(rt, rt, t[y], m, mp); + } + + sp_2048_mont_reduce_90(rt, m, mp); + n = sp_2048_cmp_90(rt, m); + sp_2048_cond_sub_90(rt, rt, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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 /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ + /* 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) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1] = {0}; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 256U) { + err = MP_TO_E; + } + + if (err == MP_OKAY) { + if (mp_count_bits(em) > 23) { + err = MP_READ_E; + } + if (inLen > 256U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 90 * 2; + m = r + 90 * 2; + norm = r; + + sp_2048_from_bin(a, 90, in, inLen); +#if DIGIT_BIT >= 23 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)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, 90, mm); + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_90(norm, m); + } + if (err == MP_OKAY) { + sp_2048_mul_90(a, a, norm); + err = sp_2048_mod_90(a, a, m); + } + if (err == MP_OKAY) { + for (i=22; i>=0; i--) { + if ((e[0] >> i) != 0) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 90 * 2); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_90(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) { + sp_2048_mont_mul_90(r, r, a, m, mp); + } + } + sp_2048_mont_reduce_90(r, m, mp); + mp = sp_2048_cmp_90(r, m); + sp_2048_cond_sub_90(r, r, m, ((mp < 0) ? + (sp_digit)1 : (sp_digit)0)- 1); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit ad[180], md[90], rd[180]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit e[1] = {0}; + int err = MP_OKAY; + + if (*outLen < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(em) > 23) { + err = MP_READ_E; + } + if (inLen > 256U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 2048) { + err = MP_READ_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + a = d; + r = a + 90 * 2; + m = r + 90 * 2; + } +#else + a = ad; + m = md; + r = rd; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 90, in, inLen); +#if DIGIT_BIT >= 23 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)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, 90, mm); + + if (e[0] == 0x3) { + sp_2048_sqr_90(r, a); + err = sp_2048_mod_90(r, r, m); + if (err == MP_OKAY) { + sp_2048_mul_90(r, a, r); + err = sp_2048_mod_90(r, r, m); + } + } + else { + sp_digit* norm = r; + int i; + sp_digit mp; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_90(norm, m); + + sp_2048_mul_90(a, a, norm); + err = sp_2048_mod_90(a, a, m); + + if (err == MP_OKAY) { + for (i=22; i>=0; i--) { + if ((e[0] >> i) != 0) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 180U); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_90(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) { + sp_2048_mont_mul_90(r, r, a, m, mp); + } + } + sp_2048_mont_reduce_90(r, m, mp); + mp = sp_2048_cmp_90(r, m); + sp_2048_cond_sub_90(r, r, m, ((mp < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM) +#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */ +/* 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(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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 < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 2048) { + err = MP_READ_E; + } + if (inLen > 256) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 90; + m = a + 180; + r = a; + + sp_2048_from_bin(a, 90, in, inLen); + sp_2048_from_mp(d, 90, dm); + sp_2048_from_mp(m, 90, mm); + err = sp_2048_mod_exp_90(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) * 90); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[180], d[90], m[90]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 2048) { + err = MP_READ_E; + } + if (inLen > 256U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 90, in, inLen); + sp_2048_from_mp(d, 90, dm); + sp_2048_from_mp(m, 90, mm); + err = sp_2048_mod_exp_90(r, a, d, 2048, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + + XMEMSET(d, 0, sizeof(sp_digit) * 90); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#else +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (inLen > 256) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 45 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = t; + p = a + 90 * 2; + q = p + 45; + qi = dq = dp = q + 45; + tmpa = qi + 45; + tmpb = tmpa + 90; + + r = t + 90; + + sp_2048_from_bin(a, 90, in, inLen); + sp_2048_from_mp(p, 45, pm); + sp_2048_from_mp(q, 45, qm); + sp_2048_from_mp(dp, 45, dpm); + err = sp_2048_mod_exp_45(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 45, dqm); + err = sp_2048_mod_exp_45(tmpb, a, dq, 1024, q, 1); + } + if (err == MP_OKAY) { + (void)sp_2048_sub_45(tmpa, tmpa, tmpb); + sp_2048_cond_add_45(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[44] >> 31)); + sp_2048_cond_add_45(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[44] >> 31)); + + sp_2048_from_mp(qi, 45, qim); + sp_2048_mul_45(tmpa, tmpa, qi); + err = sp_2048_mod_45(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_45(tmpa, q, tmpa); + (void)sp_2048_add_90(r, tmpb, tmpa); + sp_2048_norm_90(r); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 45 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[90 * 2]; + sp_digit p[45], q[45], dp[45], dq[45], qi[45]; + sp_digit tmpa[90], tmpb[90]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (inLen > 256U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 90, in, inLen); + sp_2048_from_mp(p, 45, pm); + sp_2048_from_mp(q, 45, qm); + sp_2048_from_mp(dp, 45, dpm); + sp_2048_from_mp(dq, 45, dqm); + sp_2048_from_mp(qi, 45, qim); + + err = sp_2048_mod_exp_45(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + err = sp_2048_mod_exp_45(tmpb, a, dq, 1024, q, 1); + } + + if (err == MP_OKAY) { + (void)sp_2048_sub_45(tmpa, tmpa, tmpb); + sp_2048_cond_add_45(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[44] >> 31)); + sp_2048_cond_add_45(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[44] >> 31)); + sp_2048_mul_45(tmpa, tmpa, qi); + err = sp_2048_mod_45(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_45(tmpa, tmpa, q); + (void)sp_2048_add_90(r, tmpb, tmpa); + sp_2048_norm_90(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 || RSA_LOW_MEM */ +} + +#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 23 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 90); + r->used = 90; + mp_clamp(r); +#elif DIGIT_BIT < 23 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 90; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 23) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 23 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 90; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 23 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 23 - s; + } + else { + s += 23; + } + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + b = d; + e = b + 90 * 2; + m = e + 90; + r = b; + + sp_2048_from_mp(b, 90, base); + sp_2048_from_mp(e, 90, exp); + sp_2048_from_mp(m, 90, mod); + + err = sp_2048_mod_exp_90(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 90U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[180], ed[90], md[90]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 90 * 2; + m = e + 90; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 90, base); + sp_2048_from_mp(e, 90, exp); + sp_2048_from_mp(m, 90, mod); + + err = sp_2048_mod_exp_90(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 90U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 90U); +#endif + + return err; +#endif +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_2048 +SP_NOINLINE static void sp_2048_lshift_90(sp_digit* r, sp_digit* a, byte n) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + r[90] = a[89] >> (23 - n); + for (i=89; i>0; i--) { + r[i] = ((a[i] << n) | (a[i-1] >> (23 - n))) & 0x7fffff; + } +#else + sp_int_digit s, t; + + s = (sp_int_digit)a[89]; + r[90] = s >> (23U - n); + s = (sp_int_digit)(a[89]); t = (sp_int_digit)(a[88]); + r[89] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[88]); t = (sp_int_digit)(a[87]); + r[88] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[87]); t = (sp_int_digit)(a[86]); + r[87] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[86]); t = (sp_int_digit)(a[85]); + r[86] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[85]); t = (sp_int_digit)(a[84]); + r[85] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[84]); t = (sp_int_digit)(a[83]); + r[84] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[83]); t = (sp_int_digit)(a[82]); + r[83] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[82]); t = (sp_int_digit)(a[81]); + r[82] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[81]); t = (sp_int_digit)(a[80]); + r[81] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[80]); t = (sp_int_digit)(a[79]); + r[80] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[79]); t = (sp_int_digit)(a[78]); + r[79] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[78]); t = (sp_int_digit)(a[77]); + r[78] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[77]); t = (sp_int_digit)(a[76]); + r[77] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[76]); t = (sp_int_digit)(a[75]); + r[76] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[75]); t = (sp_int_digit)(a[74]); + r[75] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[74]); t = (sp_int_digit)(a[73]); + r[74] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[73]); t = (sp_int_digit)(a[72]); + r[73] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[72]); t = (sp_int_digit)(a[71]); + r[72] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]); + r[71] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]); + r[70] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]); + r[69] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]); + r[68] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]); + r[67] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]); + r[66] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]); + r[65] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]); + r[64] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]); + r[63] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]); + r[62] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]); + r[61] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]); + r[60] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]); + r[59] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]); + r[58] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]); + r[57] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]); + r[56] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]); + r[55] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]); + r[54] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]); + r[53] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]); + r[52] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]); + r[51] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]); + r[50] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]); + r[49] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]); + r[48] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]); + r[47] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]); + r[46] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]); + r[45] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]); + r[44] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]); + r[43] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]); + r[42] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]); + r[41] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]); + r[40] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]); + r[39] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]); + r[38] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]); + r[37] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]); + r[36] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); + r[35] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); + r[34] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); + r[33] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); + r[32] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); + r[31] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); + r[30] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); + r[29] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); + r[28] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); + r[27] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); + r[26] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); + r[25] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); + r[24] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); + r[23] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); + r[22] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); + r[21] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); + r[20] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); + r[19] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); + r[18] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); + r[17] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); + r[16] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); + r[15] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); + r[14] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); + r[13] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); + r[12] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); + r[11] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); + r[10] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); + r[9] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); + r[8] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); + r[7] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); + r[6] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); + r[5] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); + r[4] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); + r[3] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); + r[2] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); + r[1] = ((s << n) | (t >> (23U - n))) & 0x7fffff; +#endif + r[0] = (a[0] << n) & 0x7fffff; +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_90(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[180]; + sp_digit td[91]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 271, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 180; + XMEMSET(td, 0, sizeof(sp_digit) * 271); +#else + norm = nd; + tmp = td; + XMEMSET(td, 0, sizeof(td)); +#endif + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_90(norm, m); + + bits = ((bits + 3) / 4) * 4; + i = ((bits + 22) / 23) - 1; + c = bits % 23; + if (c == 0) { + c = 23; + } + if (i < 90) { + n = e[i--] << (32 - c); + } + else { + n = 0; + i--; + } + if (c < 4) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + sp_2048_lshift_90(r, norm, y); + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_2048_mont_sqr_90(r, r, m, mp); + sp_2048_mont_sqr_90(r, r, m, mp); + sp_2048_mont_sqr_90(r, r, m, mp); + sp_2048_mont_sqr_90(r, r, m, mp); + + sp_2048_lshift_90(r, r, y); + sp_2048_mul_d_90(tmp, norm, (r[90] << 22) + (r[89] >> 1)); + r[90] = 0; + r[89] &= 0x1L; + (void)sp_2048_add_90(r, r, tmp); + sp_2048_norm_90(r); + o = sp_2048_cmp_90(r, m); + sp_2048_cond_sub_90(r, r, m, ((o < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + + sp_2048_mont_reduce_90(r, m, mp); + n = sp_2048_cmp_90(r, m); + sp_2048_cond_sub_90(r, r, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} + +#endif /* HAVE_FFDHE_2048 */ + +/* 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. + * returns 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) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 256) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + b = d; + e = b + 90 * 2; + m = e + 90; + r = b; + + sp_2048_from_mp(b, 90, base); + sp_2048_from_bin(e, 90, exp, expLen); + sp_2048_from_mp(m, 90, mod); + + #ifdef HAVE_FFDHE_2048 + if (base->used == 1 && base->dp[0] == 2 && + ((m[89] << 15) | (m[88] >> 8)) == 0xffffL) { + err = sp_2048_mod_exp_2_90(r, e, expLen * 8, m); + } + else + #endif + err = sp_2048_mod_exp_90(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) * 90U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[180], ed[90], md[90]; +#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) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 256U) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 90 * 2; + m = e + 90; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 90, base); + sp_2048_from_bin(e, 90, exp, expLen); + sp_2048_from_mp(m, 90, mod); + + #ifdef HAVE_FFDHE_2048 + if (base->used == 1 && base->dp[0] == 2U && + ((m[89] << 15) | (m[88] >> 8)) == 0xffffL) { + err = sp_2048_mod_exp_2_90(r, e, expLen * 8U, m); + } + else { + #endif + err = sp_2048_mod_exp_90(r, b, e, expLen * 8U, m, 0); + #ifdef HAVE_FFDHE_2048 + } + #endif + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256U && out[i] == 0U; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 90U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 90U); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 45 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + b = d; + e = b + 45 * 2; + m = e + 45; + r = b; + + sp_2048_from_mp(b, 45, base); + sp_2048_from_mp(e, 45, exp); + sp_2048_from_mp(m, 45, mod); + + err = sp_2048_mod_exp_45(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 45, 0, sizeof(*r) * 45U); + err = sp_2048_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 45U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[90], ed[45], md[45]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 45 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 45 * 2; + m = e + 45; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 45, base); + sp_2048_from_mp(e, 45, exp); + sp_2048_from_mp(m, 45, mod); + + err = sp_2048_mod_exp_45(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 45, 0, sizeof(*r) * 45U); + err = sp_2048_to_mp(r, res); + } + + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 45U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 45U); +#endif + + return err; +#endif +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 15U) { + r[j] &= 0x7fffff; + s = 23U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 23 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 23 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x7fffff; + s = 23U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 23U) <= (word32)DIGIT_BIT) { + s += 23U; + r[j] &= 0x7fffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 23) { + r[j] &= 0x7fffff; + if (j + 1 >= size) { + break; + } + s = 23 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * 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<133; i++) { + r[i+1] += r[i] >> 23; + r[i] &= 0x7fffff; + } + j = 3072 / 8 - 1; + a[j] = 0; + for (i=0; i<134 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 23) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 23); + if (j >= 0) { + 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. + */ +SP_NOINLINE static void sp_3072_mul_67(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j; + int64_t t[134]; + + XMEMSET(t, 0, sizeof(t)); + for (i=0; i<67; i++) { + for (j=0; j<67; j++) { + t[i+j] += ((int64_t)a[i]) * b[j]; + } + } + for (i=0; i<133; i++) { + r[i] = t[i] & 0x7fffff; + t[i+1] += t[i] >> 23; + } + r[133] = (sp_digit)t[133]; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_67(sp_digit* r, const sp_digit* a) +{ + int i, j; + int64_t t[134]; + + XMEMSET(t, 0, sizeof(t)); + for (i=0; i<67; i++) { + for (j=0; j> 23; + } + r[133] = (sp_digit)t[133]; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_67(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]; + + 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. + */ +SP_NOINLINE static int sp_3072_add_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 128; 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[128] = a[128] + b[128]; + r[129] = a[129] + b[129]; + r[130] = a[130] + b[130]; + r[131] = a[131] + b[131]; + r[132] = a[132] + b[132]; + r[133] = a[133] + b[133]; + + 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. + */ +SP_NOINLINE static int sp_3072_sub_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 128; 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[128] = a[128] - b[128]; + r[129] = a[129] - b[129]; + r[130] = a[130] - b[130]; + r[131] = a[131] - b[131]; + r[132] = a[132] - b[132]; + r[133] = a[133] - b[133]; + + 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. + */ +SP_NOINLINE static void sp_3072_mul_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[134]; + sp_digit* a1 = z1; + sp_digit b1[67]; + sp_digit* z2 = r + 134; + (void)sp_3072_add_67(a1, a, &a[67]); + (void)sp_3072_add_67(b1, b, &b[67]); + sp_3072_mul_67(z2, &a[67], &b[67]); + sp_3072_mul_67(z0, a, b); + sp_3072_mul_67(z1, a1, b1); + (void)sp_3072_sub_134(z1, z1, z2); + (void)sp_3072_sub_134(z1, z1, z0); + (void)sp_3072_add_134(r + 67, r + 67, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_134(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[134]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 134; + (void)sp_3072_add_67(a1, a, &a[67]); + sp_3072_sqr_67(z2, &a[67]); + sp_3072_sqr_67(z0, a); + sp_3072_sqr_67(z1, a1); + (void)sp_3072_sub_134(z1, z1, z2); + (void)sp_3072_sub_134(z1, z1, z0); + (void)sp_3072_add_134(r + 67, r + 67, 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. + */ +SP_NOINLINE static int sp_3072_add_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 134; 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. + */ +SP_NOINLINE static int sp_3072_sub_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 134; 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. + */ +SP_NOINLINE static void sp_3072_mul_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[133]) * b[133]; + r[267] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 265; k >= 0; k--) { + for (i = 133; i >= 0; i--) { + j = k - i; + if (j >= 134) { + break; + } + if (j < 0) { + continue; + } + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_134(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[133]) * a[133]; + r[267] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 265; k >= 0; k--) { + for (i = 133; i >= 0; i--) { + j = k - i; + if (j >= 134 || 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 >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#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. + */ +SP_NOINLINE static int sp_3072_add_67(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 67; 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. + */ +SP_NOINLINE static int sp_3072_sub_67(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 67; 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. + */ +SP_NOINLINE static int sp_3072_sub_67(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]; + + 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. + */ +SP_NOINLINE static void sp_3072_mul_67(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[66]) * b[66]; + r[133] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 131; k >= 0; k--) { + for (i = 66; i >= 0; i--) { + j = k - i; + if (j >= 67) { + break; + } + if (j < 0) { + continue; + } + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_67(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[66]) * a[66]; + r[133] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 131; k >= 0; k--) { + for (i = 66; i >= 0; i--) { + j = k - i; + if (j >= 67 || 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 >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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 &= 0x7fffff; + + /* rho = -1/m mod b */ + *rho = (1L << 23) - x; +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_3072_mul_d_134(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 134; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[134] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff; + for (i = 0; i < 128; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[129]; + r[129] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[130]; + r[130] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[131]; + r[131] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[132]; + r[132] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[133]; + r[133] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + r[134] = (sp_digit)(t[5] >> 23); +#endif /* WOLFSSL_SP_SMALL */ +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_3072_mont_norm_67(sp_digit* r, const sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<66; i++) { + r[i] = 0x7fffff; + } +#else + int i; + + for (i = 0; i < 64; i += 8) { + r[i + 0] = 0x7fffff; + r[i + 1] = 0x7fffff; + r[i + 2] = 0x7fffff; + r[i + 3] = 0x7fffff; + r[i + 4] = 0x7fffff; + r[i + 5] = 0x7fffff; + r[i + 6] = 0x7fffff; + r[i + 7] = 0x7fffff; + } + r[64] = 0x7fffff; + r[65] = 0x7fffff; +#endif + r[66] = 0x3ffffL; + + /* r = (2^n - 1) mod n */ + (void)sp_3072_sub_67(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_67(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=66; i>=0; i--) { + r |= (a[i] - b[i]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[66] - b[66]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[65] - b[65]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[64] - b[64]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 56; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#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_67(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 < 67; 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); +#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. + */ +SP_NOINLINE static void sp_3072_mul_add_67(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 < 67; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[67] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x7fffff); + for (i = 0; i < 64; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (sp_digit)((t[0] >> 23) + (t[1] & 0x7fffff)); + t[2] = tb * a[i+2]; + r[i+2] += (sp_digit)((t[1] >> 23) + (t[2] & 0x7fffff)); + t[3] = tb * a[i+3]; + r[i+3] += (sp_digit)((t[2] >> 23) + (t[3] & 0x7fffff)); + t[4] = tb * a[i+4]; + r[i+4] += (sp_digit)((t[3] >> 23) + (t[4] & 0x7fffff)); + t[5] = tb * a[i+5]; + r[i+5] += (sp_digit)((t[4] >> 23) + (t[5] & 0x7fffff)); + t[6] = tb * a[i+6]; + r[i+6] += (sp_digit)((t[5] >> 23) + (t[6] & 0x7fffff)); + t[7] = tb * a[i+7]; + r[i+7] += (sp_digit)((t[6] >> 23) + (t[7] & 0x7fffff)); + t[0] = tb * a[i+8]; + r[i+8] += (sp_digit)((t[7] >> 23) + (t[0] & 0x7fffff)); + } + t[1] = tb * a[65]; r[65] += (sp_digit)((t[0] >> 23) + (t[1] & 0x7fffff)); + t[2] = tb * a[66]; r[66] += (sp_digit)((t[1] >> 23) + (t[2] & 0x7fffff)); + r[67] += (sp_digit)(t[2] >> 23); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 23. + * + * a Array of sp_digit to normalize. + */ +static void sp_3072_norm_67(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 66; i++) { + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + int i; + for (i = 0; i < 64; i += 8) { + a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff; + a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff; + a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff; + a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff; + a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff; + a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff; + a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff; + a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff; + a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff; + } + a[64+1] += a[64] >> 23; + a[64] &= 0x7fffff; + a[65+1] += a[65] >> 23; + a[65] &= 0x7fffff; +#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_67(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + sp_digit n, s; + + s = a[67]; + n = a[66] >> 18; + for (i = 0; i < 66; i++) { + n += (s & 0x7fffff) << 5; + r[i] = n & 0x7fffff; + n >>= 23; + s = a[68 + i] + (s >> 23); + } + n += s << 5; + r[66] = n; +#else + sp_digit n, s; + int i; + + s = a[67]; n = a[66] >> 18; + for (i = 0; i < 64; i += 8) { + n += (s & 0x7fffff) << 5; r[i+0] = n & 0x7fffff; + n >>= 23; s = a[i+68] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+1] = n & 0x7fffff; + n >>= 23; s = a[i+69] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+2] = n & 0x7fffff; + n >>= 23; s = a[i+70] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+3] = n & 0x7fffff; + n >>= 23; s = a[i+71] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+4] = n & 0x7fffff; + n >>= 23; s = a[i+72] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+5] = n & 0x7fffff; + n >>= 23; s = a[i+73] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+6] = n & 0x7fffff; + n >>= 23; s = a[i+74] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+7] = n & 0x7fffff; + n >>= 23; s = a[i+75] + (s >> 23); + } + n += (s & 0x7fffff) << 5; r[64] = n & 0x7fffff; + n >>= 23; s = a[132] + (s >> 23); + n += (s & 0x7fffff) << 5; r[65] = n & 0x7fffff; + n >>= 23; s = a[133] + (s >> 23); + n += s << 5; r[66] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[67], 0, sizeof(*r) * 67U); +} + +/* 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_67(sp_digit* a, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_3072_norm_67(a + 67); + + for (i=0; i<66; i++) { + mu = (a[i] * mp) & 0x7fffff; + sp_3072_mul_add_67(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = (a[i] * mp) & 0x3ffffL; + sp_3072_mul_add_67(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + + sp_3072_mont_shift_67(a, a); + sp_3072_cond_sub_67(a, a, m, 0 - (((a[66] >> 18) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_3072_norm_67(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_67(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_3072_mul_67(r, a, b); + sp_3072_mont_reduce_67(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_67(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_67(r, a); + sp_3072_mont_reduce_67(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. + */ +SP_NOINLINE static void sp_3072_mul_d_67(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 67; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[67] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff; + for (i = 0; i < 64; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[65]; + r[65] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[66]; + r[66] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + r[67] = (sp_digit)(t[2] >> 23); +#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_67(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 < 67; 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); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_3072_add_67(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 67; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#endif +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_3072_div_word_67(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 23 bits from d1 and top 8 bits from d0. */ + d = (d1 << 8) | (d0 >> 15); + r = d / dv; + d -= r * dv; + /* Up to 9 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 7) & ((1 << 8) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 17 bits in r */ + /* Remaining 7 bits from d0. */ + r <<= 7; + d <<= 7; + d |= d0 & ((1 << 7) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* 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 Number 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_67(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[134], t2d[67 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 67 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 2 * 67; +#else + t1 = t1d; + t2 = t2d; +#endif + + dv = d[66]; + XMEMCPY(t1, a, sizeof(*t1) * 2U * 67U); + for (i=66; i>=0; i--) { + t1[67 + i] += t1[67 + i - 1] >> 23; + t1[67 + i - 1] &= 0x7fffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[67 + i]; + d1 <<= 23; + d1 += t1[67 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_3072_div_word_67(t1[67 + i], t1[67 + i - 1], dv); +#endif + + sp_3072_mul_d_67(t2, d, r1); + (void)sp_3072_sub_67(&t1[i], &t1[i], t2); + t1[67 + i] -= t2[67]; + t1[67 + i] += t1[67 + i - 1] >> 23; + t1[67 + i - 1] &= 0x7fffff; + r1 = (((-t1[67 + i]) << 23) - t1[67 + i - 1]) / dv; + r1++; + sp_3072_mul_d_67(t2, d, r1); + (void)sp_3072_add_67(&t1[i], &t1[i], t2); + t1[67 + i] += t1[67 + i - 1] >> 23; + t1[67 + i - 1] &= 0x7fffff; + } + t1[67 - 1] += t1[67 - 2] >> 23; + t1[67 - 2] &= 0x7fffff; + r1 = t1[67 - 1] / dv; + + sp_3072_mul_d_67(t2, d, r1); + (void)sp_3072_sub_67(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 67U); + for (i=0; i<65; i++) { + r[i+1] += r[i] >> 23; + r[i] &= 0x7fffff; + } + sp_3072_cond_add_67(r, r, d, 0 - ((r[66] < 0) ? + (sp_digit)1 : (sp_digit)0)); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_67(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_67(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_67(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, + const 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 * 67 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3U * 67U * 2U); + + norm = t[0] = td; + t[1] = &td[67 * 2]; + t[2] = &td[2 * 67 * 2]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_67(norm, m); + + if (reduceA != 0) { + err = sp_3072_mod_67(t[1], a, m); + } + else { + XMEMCPY(t[1], a, sizeof(sp_digit) * 67U); + } + } + if (err == MP_OKAY) { + sp_3072_mul_67(t[1], t[1], norm); + err = sp_3072_mod_67(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) { + break; + } + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_3072_mont_mul_67(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]) * 67 * 2); + sp_3072_mont_sqr_67(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]) * 67 * 2); + } + + sp_3072_mont_reduce_67(t[0], m, mp); + n = sp_3072_cmp_67(t[0], m); + sp_3072_cond_sub_67(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 67 * 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][134]; +#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 * 67 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t[0] = td; + t[1] = &td[67 * 2]; + t[2] = &td[2 * 67 * 2]; +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_67(norm, m); + + if (reduceA != 0) { + err = sp_3072_mod_67(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_67(t[1], t[1], norm); + err = sp_3072_mod_67(t[1], t[1], m); + } + } + else { + sp_3072_mul_67(t[1], a, norm); + err = sp_3072_mod_67(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) { + break; + } + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_3072_mont_mul_67(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_67(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_67(t[0], m, mp); + n = sp_3072_cmp_67(t[0], m); + sp_3072_cond_sub_67(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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][134]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[134]; + 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 * 134, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 134; +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_67(norm, m); + + if (reduceA != 0) { + err = sp_3072_mod_67(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_67(t[1], t[1], norm); + err = sp_3072_mod_67(t[1], t[1], m); + } + } + else { + sp_3072_mul_67(t[1], a, norm); + err = sp_3072_mod_67(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_67(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_67(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_67(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_67(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_67(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_67(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_67(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_67(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_67(t[10], t[ 5], m, mp); + sp_3072_mont_mul_67(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_67(t[12], t[ 6], m, mp); + sp_3072_mont_mul_67(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_67(t[14], t[ 7], m, mp); + sp_3072_mont_mul_67(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_67(t[16], t[ 8], m, mp); + sp_3072_mont_mul_67(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_67(t[18], t[ 9], m, mp); + sp_3072_mont_mul_67(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_67(t[20], t[10], m, mp); + sp_3072_mont_mul_67(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_67(t[22], t[11], m, mp); + sp_3072_mont_mul_67(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_67(t[24], t[12], m, mp); + sp_3072_mont_mul_67(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_67(t[26], t[13], m, mp); + sp_3072_mont_mul_67(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_67(t[28], t[14], m, mp); + sp_3072_mont_mul_67(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_67(t[30], t[15], m, mp); + sp_3072_mont_mul_67(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 22) / 23) - 1; + c = bits % 23; + if (c == 0) { + c = 23; + } + if (i < 67) { + n = e[i--] << (32 - c); + } + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + + sp_3072_mont_sqr_67(rt, rt, m, mp); + sp_3072_mont_sqr_67(rt, rt, m, mp); + sp_3072_mont_sqr_67(rt, rt, m, mp); + sp_3072_mont_sqr_67(rt, rt, m, mp); + sp_3072_mont_sqr_67(rt, rt, m, mp); + + sp_3072_mont_mul_67(rt, rt, t[y], m, mp); + } + + sp_3072_mont_reduce_67(rt, m, mp); + n = sp_3072_cmp_67(rt, m); + sp_3072_cond_sub_67(rt, rt, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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 /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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 single precision number. + */ +static void sp_3072_mont_norm_134(sp_digit* r, const sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<133; i++) { + r[i] = 0x7fffff; + } +#else + int i; + + for (i = 0; i < 128; i += 8) { + r[i + 0] = 0x7fffff; + r[i + 1] = 0x7fffff; + r[i + 2] = 0x7fffff; + r[i + 3] = 0x7fffff; + r[i + 4] = 0x7fffff; + r[i + 5] = 0x7fffff; + r[i + 6] = 0x7fffff; + r[i + 7] = 0x7fffff; + } + r[128] = 0x7fffff; + r[129] = 0x7fffff; + r[130] = 0x7fffff; + r[131] = 0x7fffff; + r[132] = 0x7fffff; +#endif + r[133] = 0x1fffL; + + /* r = (2^n - 1) mod n */ + (void)sp_3072_sub_134(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_134(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=133; i>=0; i--) { + r |= (a[i] - b[i]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[133] - b[133]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[132] - b[132]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[131] - b[131]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[130] - b[130]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[129] - b[129]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[128] - b[128]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 120; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#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_134(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 < 134; i++) { + r[i] = a[i] - (b[i] & m); + } +#else + int i; + + for (i = 0; i < 128; 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[128] = a[128] - (b[128] & m); + r[129] = a[129] - (b[129] & m); + r[130] = a[130] - (b[130] & m); + r[131] = a[131] - (b[131] & m); + r[132] = a[132] - (b[132] & m); + r[133] = a[133] - (b[133] & 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. + */ +SP_NOINLINE static void sp_3072_mul_add_134(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 < 134; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[134] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x7fffff); + for (i = 0; i < 128; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (sp_digit)((t[0] >> 23) + (t[1] & 0x7fffff)); + t[2] = tb * a[i+2]; + r[i+2] += (sp_digit)((t[1] >> 23) + (t[2] & 0x7fffff)); + t[3] = tb * a[i+3]; + r[i+3] += (sp_digit)((t[2] >> 23) + (t[3] & 0x7fffff)); + t[4] = tb * a[i+4]; + r[i+4] += (sp_digit)((t[3] >> 23) + (t[4] & 0x7fffff)); + t[5] = tb * a[i+5]; + r[i+5] += (sp_digit)((t[4] >> 23) + (t[5] & 0x7fffff)); + t[6] = tb * a[i+6]; + r[i+6] += (sp_digit)((t[5] >> 23) + (t[6] & 0x7fffff)); + t[7] = tb * a[i+7]; + r[i+7] += (sp_digit)((t[6] >> 23) + (t[7] & 0x7fffff)); + t[0] = tb * a[i+8]; + r[i+8] += (sp_digit)((t[7] >> 23) + (t[0] & 0x7fffff)); + } + t[1] = tb * a[129]; r[129] += (sp_digit)((t[0] >> 23) + (t[1] & 0x7fffff)); + t[2] = tb * a[130]; r[130] += (sp_digit)((t[1] >> 23) + (t[2] & 0x7fffff)); + t[3] = tb * a[131]; r[131] += (sp_digit)((t[2] >> 23) + (t[3] & 0x7fffff)); + t[4] = tb * a[132]; r[132] += (sp_digit)((t[3] >> 23) + (t[4] & 0x7fffff)); + t[5] = tb * a[133]; r[133] += (sp_digit)((t[4] >> 23) + (t[5] & 0x7fffff)); + r[134] += (sp_digit)(t[5] >> 23); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 23. + * + * a Array of sp_digit to normalize. + */ +static void sp_3072_norm_134(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 133; i++) { + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + int i; + for (i = 0; i < 128; i += 8) { + a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff; + a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff; + a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff; + a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff; + a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff; + a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff; + a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff; + a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff; + a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff; + } + a[128+1] += a[128] >> 23; + a[128] &= 0x7fffff; + a[129+1] += a[129] >> 23; + a[129] &= 0x7fffff; + a[130+1] += a[130] >> 23; + a[130] &= 0x7fffff; + a[131+1] += a[131] >> 23; + a[131] &= 0x7fffff; + a[132+1] += a[132] >> 23; + a[132] &= 0x7fffff; +#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_134(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int64_t n = a[133] >> 13; + n += ((int64_t)a[134]) << 10; + + for (i = 0; i < 133; i++) { + r[i] = n & 0x7fffff; + n >>= 23; + n += ((int64_t)a[135 + i]) << 10; + } + r[133] = (sp_digit)n; +#else + int i; + int64_t n = a[133] >> 13; + n += ((int64_t)a[134]) << 10; + for (i = 0; i < 128; i += 8) { + r[i + 0] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 135]) << 10; + r[i + 1] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 136]) << 10; + r[i + 2] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 137]) << 10; + r[i + 3] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 138]) << 10; + r[i + 4] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 139]) << 10; + r[i + 5] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 140]) << 10; + r[i + 6] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 141]) << 10; + r[i + 7] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 142]) << 10; + } + r[128] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[263]) << 10; + r[129] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[264]) << 10; + r[130] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[265]) << 10; + r[131] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[266]) << 10; + r[132] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[267]) << 10; + r[133] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[134], 0, sizeof(*r) * 134U); +} + +/* 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_134(sp_digit* a, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_3072_norm_134(a + 134); + +#ifdef WOLFSSL_SP_DH + if (mp != 1) { + for (i=0; i<133; i++) { + mu = (a[i] * mp) & 0x7fffff; + sp_3072_mul_add_134(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = (a[i] * mp) & 0x1fffL; + sp_3072_mul_add_134(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } + else { + for (i=0; i<133; i++) { + mu = a[i] & 0x7fffff; + sp_3072_mul_add_134(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = a[i] & 0x1fffL; + sp_3072_mul_add_134(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + for (i=0; i<133; i++) { + mu = (a[i] * mp) & 0x7fffff; + sp_3072_mul_add_134(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = (a[i] * mp) & 0x1fffL; + sp_3072_mul_add_134(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; +#endif + + sp_3072_mont_shift_134(a, a); + sp_3072_cond_sub_134(a, a, m, 0 - (((a[133] >> 13) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_3072_norm_134(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_134(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_3072_mul_134(r, a, b); + sp_3072_mont_reduce_134(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_134(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_134(r, a); + sp_3072_mont_reduce_134(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. + */ +SP_NOINLINE static void sp_3072_mul_d_268(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 268; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[268] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff; + for (i = 0; i < 264; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[265]; + r[265] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[266]; + r[266] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[267]; + r[267] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + r[268] = (sp_digit)(t[3] >> 23); +#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_134(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 < 134; i++) { + r[i] = a[i] + (b[i] & m); + } +#else + int i; + + for (i = 0; i < 128; 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[128] = a[128] + (b[128] & m); + r[129] = a[129] + (b[129] & m); + r[130] = a[130] + (b[130] & m); + r[131] = a[131] + (b[131] & m); + r[132] = a[132] + (b[132] & m); + r[133] = a[133] + (b[133] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_3072_sub_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 134; i++) { + r[i] = a[i] - b[i]; + } + + return 0; +} + +#endif +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_3072_add_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 134; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#endif +SP_NOINLINE static void sp_3072_rshift_134(sp_digit* r, sp_digit* a, byte n) +{ + int i; + +#ifdef WOLFSSL_SP_SMALL + for (i=0; i<133; i++) { + r[i] = ((a[i] >> n) | (a[i + 1] << (23 - n))) & 0x7fffff; + } +#else + for (i=0; i<128; i += 8) { + r[i+0] = ((a[i+0] >> n) | (a[i+1] << (23 - n))) & 0x7fffff; + r[i+1] = ((a[i+1] >> n) | (a[i+2] << (23 - n))) & 0x7fffff; + r[i+2] = ((a[i+2] >> n) | (a[i+3] << (23 - n))) & 0x7fffff; + r[i+3] = ((a[i+3] >> n) | (a[i+4] << (23 - n))) & 0x7fffff; + r[i+4] = ((a[i+4] >> n) | (a[i+5] << (23 - n))) & 0x7fffff; + r[i+5] = ((a[i+5] >> n) | (a[i+6] << (23 - n))) & 0x7fffff; + r[i+6] = ((a[i+6] >> n) | (a[i+7] << (23 - n))) & 0x7fffff; + r[i+7] = ((a[i+7] >> n) | (a[i+8] << (23 - n))) & 0x7fffff; + } + r[128] = ((a[128] >> n) | (a[129] << (23 - n))) & 0x7fffff; + r[129] = ((a[129] >> n) | (a[130] << (23 - n))) & 0x7fffff; + r[130] = ((a[130] >> n) | (a[131] << (23 - n))) & 0x7fffff; + r[131] = ((a[131] >> n) | (a[132] << (23 - n))) & 0x7fffff; + r[132] = ((a[132] >> n) | (a[133] << (23 - n))) & 0x7fffff; +#endif + r[133] = a[133] >> n; +} + +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_3072_div_word_134(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 23 bits from d1 and top 8 bits from d0. */ + d = (d1 << 8) | (d0 >> 15); + r = d / dv; + d -= r * dv; + /* Up to 9 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 7) & ((1 << 8) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 17 bits in r */ + /* Remaining 7 bits from d0. */ + r <<= 7; + d <<= 7; + d |= d0 & ((1 << 7) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* 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_134(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[268 + 1], t2d[134 + 1], sdd[134 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* sd; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 134 + 3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + (void)m; + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 268 + 1; + sd = t2 + 134 + 1; +#else + t1 = t1d; + t2 = t2d; + sd = sdd; +#endif + + sp_3072_mul_d_134(sd, d, 1L << 10); + sp_3072_mul_d_268(t1, a, 1L << 10); + dv = sd[133]; + for (i=134; i>=0; i--) { + t1[134 + i] += t1[134 + i - 1] >> 23; + t1[134 + i - 1] &= 0x7fffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[134 + i]; + d1 <<= 23; + d1 += t1[134 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_3072_div_word_134(t1[134 + i], t1[134 + i - 1], dv); +#endif + + sp_3072_mul_d_134(t2, sd, r1); + (void)sp_3072_sub_134(&t1[i], &t1[i], t2); + t1[134 + i] -= t2[134]; + t1[134 + i] += t1[134 + i - 1] >> 23; + t1[134 + i - 1] &= 0x7fffff; + r1 = (((-t1[134 + i]) << 23) - t1[134 + i - 1]) / dv; + r1 -= t1[134 + i]; + sp_3072_mul_d_134(t2, sd, r1); + (void)sp_3072_add_134(&t1[i], &t1[i], t2); + t1[134 + i] += t1[134 + i - 1] >> 23; + t1[134 + i - 1] &= 0x7fffff; + } + t1[134 - 1] += t1[134 - 2] >> 23; + t1[134 - 2] &= 0x7fffff; + r1 = t1[134 - 1] / dv; + + sp_3072_mul_d_134(t2, sd, r1); + sp_3072_sub_134(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 134U); + for (i=0; i<132; i++) { + r[i+1] += r[i] >> 23; + r[i] &= 0x7fffff; + } + sp_3072_cond_add_134(r, r, sd, 0 - ((r[133] < 0) ? + (sp_digit)1 : (sp_digit)0)); + + sp_3072_norm_134(r); + sp_3072_rshift_134(r, r, 10); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_134(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_134(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + 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_134(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, + const 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 * 134 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3U * 134U * 2U); + + norm = t[0] = td; + t[1] = &td[134 * 2]; + t[2] = &td[2 * 134 * 2]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_134(norm, m); + + if (reduceA != 0) { + err = sp_3072_mod_134(t[1], a, m); + } + else { + XMEMCPY(t[1], a, sizeof(sp_digit) * 134U); + } + } + if (err == MP_OKAY) { + sp_3072_mul_134(t[1], t[1], norm); + err = sp_3072_mod_134(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) { + break; + } + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_3072_mont_mul_134(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]) * 134 * 2); + sp_3072_mont_sqr_134(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]) * 134 * 2); + } + + sp_3072_mont_reduce_134(t[0], m, mp); + n = sp_3072_cmp_134(t[0], m); + sp_3072_cond_sub_134(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 134 * 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][268]; +#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 * 134 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t[0] = td; + t[1] = &td[134 * 2]; + t[2] = &td[2 * 134 * 2]; +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_134(norm, m); + + if (reduceA != 0) { + err = sp_3072_mod_134(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_134(t[1], t[1], norm); + err = sp_3072_mod_134(t[1], t[1], m); + } + } + else { + sp_3072_mul_134(t[1], a, norm); + err = sp_3072_mod_134(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) { + break; + } + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_3072_mont_mul_134(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_134(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_134(t[0], m, mp); + n = sp_3072_cmp_134(t[0], m); + sp_3072_cond_sub_134(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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][268]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[268]; + 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 * 268, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 268; +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_134(norm, m); + + if (reduceA != 0) { + err = sp_3072_mod_134(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_134(t[1], t[1], norm); + err = sp_3072_mod_134(t[1], t[1], m); + } + } + else { + sp_3072_mul_134(t[1], a, norm); + err = sp_3072_mod_134(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_134(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_134(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_134(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_134(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_134(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_134(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_134(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_134(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_134(t[10], t[ 5], m, mp); + sp_3072_mont_mul_134(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_134(t[12], t[ 6], m, mp); + sp_3072_mont_mul_134(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_134(t[14], t[ 7], m, mp); + sp_3072_mont_mul_134(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_134(t[16], t[ 8], m, mp); + sp_3072_mont_mul_134(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_134(t[18], t[ 9], m, mp); + sp_3072_mont_mul_134(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_134(t[20], t[10], m, mp); + sp_3072_mont_mul_134(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_134(t[22], t[11], m, mp); + sp_3072_mont_mul_134(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_134(t[24], t[12], m, mp); + sp_3072_mont_mul_134(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_134(t[26], t[13], m, mp); + sp_3072_mont_mul_134(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_134(t[28], t[14], m, mp); + sp_3072_mont_mul_134(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_134(t[30], t[15], m, mp); + sp_3072_mont_mul_134(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 22) / 23) - 1; + c = bits % 23; + if (c == 0) { + c = 23; + } + if (i < 134) { + n = e[i--] << (32 - c); + } + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + + sp_3072_mont_sqr_134(rt, rt, m, mp); + sp_3072_mont_sqr_134(rt, rt, m, mp); + sp_3072_mont_sqr_134(rt, rt, m, mp); + sp_3072_mont_sqr_134(rt, rt, m, mp); + sp_3072_mont_sqr_134(rt, rt, m, mp); + + sp_3072_mont_mul_134(rt, rt, t[y], m, mp); + } + + sp_3072_mont_reduce_134(rt, m, mp); + n = sp_3072_cmp_134(rt, m); + sp_3072_cond_sub_134(rt, rt, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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 /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ + /* 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) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1] = {0}; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 384U) { + err = MP_TO_E; + } + + if (err == MP_OKAY) { + if (mp_count_bits(em) > 23) { + err = MP_READ_E; + } + if (inLen > 384U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 134 * 2; + m = r + 134 * 2; + norm = r; + + sp_3072_from_bin(a, 134, in, inLen); +#if DIGIT_BIT >= 23 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)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, 134, mm); + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_134(norm, m); + } + if (err == MP_OKAY) { + sp_3072_mul_134(a, a, norm); + err = sp_3072_mod_134(a, a, m); + } + if (err == MP_OKAY) { + for (i=22; i>=0; i--) { + if ((e[0] >> i) != 0) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 134 * 2); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_134(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) { + sp_3072_mont_mul_134(r, r, a, m, mp); + } + } + sp_3072_mont_reduce_134(r, m, mp); + mp = sp_3072_cmp_134(r, m); + sp_3072_cond_sub_134(r, r, m, ((mp < 0) ? + (sp_digit)1 : (sp_digit)0)- 1); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit ad[268], md[134], rd[268]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit e[1] = {0}; + int err = MP_OKAY; + + if (*outLen < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(em) > 23) { + err = MP_READ_E; + } + if (inLen > 384U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 3072) { + err = MP_READ_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + a = d; + r = a + 134 * 2; + m = r + 134 * 2; + } +#else + a = ad; + m = md; + r = rd; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 134, in, inLen); +#if DIGIT_BIT >= 23 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)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, 134, mm); + + if (e[0] == 0x3) { + sp_3072_sqr_134(r, a); + err = sp_3072_mod_134(r, r, m); + if (err == MP_OKAY) { + sp_3072_mul_134(r, a, r); + err = sp_3072_mod_134(r, r, m); + } + } + else { + sp_digit* norm = r; + int i; + sp_digit mp; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_134(norm, m); + + sp_3072_mul_134(a, a, norm); + err = sp_3072_mod_134(a, a, m); + + if (err == MP_OKAY) { + for (i=22; i>=0; i--) { + if ((e[0] >> i) != 0) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 268U); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_134(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) { + sp_3072_mont_mul_134(r, r, a, m, mp); + } + } + sp_3072_mont_reduce_134(r, m, mp); + mp = sp_3072_cmp_134(r, m); + sp_3072_cond_sub_134(r, r, m, ((mp < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM) +#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */ +/* 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(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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 < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 3072) { + err = MP_READ_E; + } + if (inLen > 384) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 134; + m = a + 268; + r = a; + + sp_3072_from_bin(a, 134, in, inLen); + sp_3072_from_mp(d, 134, dm); + sp_3072_from_mp(m, 134, mm); + err = sp_3072_mod_exp_134(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) * 134); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[268], d[134], m[134]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 3072) { + err = MP_READ_E; + } + if (inLen > 384U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 134, in, inLen); + sp_3072_from_mp(d, 134, dm); + sp_3072_from_mp(m, 134, mm); + err = sp_3072_mod_exp_134(r, a, d, 3072, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + + XMEMSET(d, 0, sizeof(sp_digit) * 134); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#else +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (inLen > 384) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 67 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = t; + p = a + 134 * 2; + q = p + 67; + qi = dq = dp = q + 67; + tmpa = qi + 67; + tmpb = tmpa + 134; + + r = t + 134; + + sp_3072_from_bin(a, 134, in, inLen); + sp_3072_from_mp(p, 67, pm); + sp_3072_from_mp(q, 67, qm); + sp_3072_from_mp(dp, 67, dpm); + err = sp_3072_mod_exp_67(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 67, dqm); + err = sp_3072_mod_exp_67(tmpb, a, dq, 1536, q, 1); + } + if (err == MP_OKAY) { + (void)sp_3072_sub_67(tmpa, tmpa, tmpb); + sp_3072_cond_add_67(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[66] >> 31)); + sp_3072_cond_add_67(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[66] >> 31)); + + sp_3072_from_mp(qi, 67, qim); + sp_3072_mul_67(tmpa, tmpa, qi); + err = sp_3072_mod_67(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_67(tmpa, q, tmpa); + (void)sp_3072_add_134(r, tmpb, tmpa); + sp_3072_norm_134(r); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 67 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[134 * 2]; + sp_digit p[67], q[67], dp[67], dq[67], qi[67]; + sp_digit tmpa[134], tmpb[134]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (inLen > 384U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 134, in, inLen); + sp_3072_from_mp(p, 67, pm); + sp_3072_from_mp(q, 67, qm); + sp_3072_from_mp(dp, 67, dpm); + sp_3072_from_mp(dq, 67, dqm); + sp_3072_from_mp(qi, 67, qim); + + err = sp_3072_mod_exp_67(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + err = sp_3072_mod_exp_67(tmpb, a, dq, 1536, q, 1); + } + + if (err == MP_OKAY) { + (void)sp_3072_sub_67(tmpa, tmpa, tmpb); + sp_3072_cond_add_67(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[66] >> 31)); + sp_3072_cond_add_67(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[66] >> 31)); + sp_3072_mul_67(tmpa, tmpa, qi); + err = sp_3072_mod_67(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_67(tmpa, tmpa, q); + (void)sp_3072_add_134(r, tmpb, tmpa); + sp_3072_norm_134(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 || RSA_LOW_MEM */ +} + +#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 23 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 134); + r->used = 134; + mp_clamp(r); +#elif DIGIT_BIT < 23 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 134; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 23) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 23 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 134; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 23 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 23 - s; + } + else { + s += 23; + } + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 134 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + b = d; + e = b + 134 * 2; + m = e + 134; + r = b; + + sp_3072_from_mp(b, 134, base); + sp_3072_from_mp(e, 134, exp); + sp_3072_from_mp(m, 134, mod); + + err = sp_3072_mod_exp_134(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 134U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[268], ed[134], md[134]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 134 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 134 * 2; + m = e + 134; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 134, base); + sp_3072_from_mp(e, 134, exp); + sp_3072_from_mp(m, 134, mod); + + err = sp_3072_mod_exp_134(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 134U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 134U); +#endif + + return err; +#endif +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_3072 +SP_NOINLINE static void sp_3072_lshift_134(sp_digit* r, sp_digit* a, byte n) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + r[134] = a[133] >> (23 - n); + for (i=133; i>0; i--) { + r[i] = ((a[i] << n) | (a[i-1] >> (23 - n))) & 0x7fffff; + } +#else + sp_int_digit s, t; + + s = (sp_int_digit)a[133]; + r[134] = s >> (23U - n); + s = (sp_int_digit)(a[133]); t = (sp_int_digit)(a[132]); + r[133] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[132]); t = (sp_int_digit)(a[131]); + r[132] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[131]); t = (sp_int_digit)(a[130]); + r[131] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[130]); t = (sp_int_digit)(a[129]); + r[130] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[129]); t = (sp_int_digit)(a[128]); + r[129] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[128]); t = (sp_int_digit)(a[127]); + r[128] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[127]); t = (sp_int_digit)(a[126]); + r[127] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[126]); t = (sp_int_digit)(a[125]); + r[126] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[125]); t = (sp_int_digit)(a[124]); + r[125] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[124]); t = (sp_int_digit)(a[123]); + r[124] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[123]); t = (sp_int_digit)(a[122]); + r[123] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[122]); t = (sp_int_digit)(a[121]); + r[122] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[121]); t = (sp_int_digit)(a[120]); + r[121] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[120]); t = (sp_int_digit)(a[119]); + r[120] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[119]); t = (sp_int_digit)(a[118]); + r[119] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[118]); t = (sp_int_digit)(a[117]); + r[118] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[117]); t = (sp_int_digit)(a[116]); + r[117] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[116]); t = (sp_int_digit)(a[115]); + r[116] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[115]); t = (sp_int_digit)(a[114]); + r[115] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[114]); t = (sp_int_digit)(a[113]); + r[114] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[113]); t = (sp_int_digit)(a[112]); + r[113] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[112]); t = (sp_int_digit)(a[111]); + r[112] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[111]); t = (sp_int_digit)(a[110]); + r[111] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[110]); t = (sp_int_digit)(a[109]); + r[110] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[109]); t = (sp_int_digit)(a[108]); + r[109] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[108]); t = (sp_int_digit)(a[107]); + r[108] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[107]); t = (sp_int_digit)(a[106]); + r[107] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[106]); t = (sp_int_digit)(a[105]); + r[106] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[105]); t = (sp_int_digit)(a[104]); + r[105] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[104]); t = (sp_int_digit)(a[103]); + r[104] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[103]); t = (sp_int_digit)(a[102]); + r[103] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[102]); t = (sp_int_digit)(a[101]); + r[102] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[101]); t = (sp_int_digit)(a[100]); + r[101] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[100]); t = (sp_int_digit)(a[99]); + r[100] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[99]); t = (sp_int_digit)(a[98]); + r[99] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[98]); t = (sp_int_digit)(a[97]); + r[98] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[97]); t = (sp_int_digit)(a[96]); + r[97] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[96]); t = (sp_int_digit)(a[95]); + r[96] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[95]); t = (sp_int_digit)(a[94]); + r[95] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[94]); t = (sp_int_digit)(a[93]); + r[94] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[93]); t = (sp_int_digit)(a[92]); + r[93] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[92]); t = (sp_int_digit)(a[91]); + r[92] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[91]); t = (sp_int_digit)(a[90]); + r[91] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[90]); t = (sp_int_digit)(a[89]); + r[90] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[89]); t = (sp_int_digit)(a[88]); + r[89] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[88]); t = (sp_int_digit)(a[87]); + r[88] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[87]); t = (sp_int_digit)(a[86]); + r[87] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[86]); t = (sp_int_digit)(a[85]); + r[86] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[85]); t = (sp_int_digit)(a[84]); + r[85] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[84]); t = (sp_int_digit)(a[83]); + r[84] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[83]); t = (sp_int_digit)(a[82]); + r[83] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[82]); t = (sp_int_digit)(a[81]); + r[82] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[81]); t = (sp_int_digit)(a[80]); + r[81] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[80]); t = (sp_int_digit)(a[79]); + r[80] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[79]); t = (sp_int_digit)(a[78]); + r[79] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[78]); t = (sp_int_digit)(a[77]); + r[78] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[77]); t = (sp_int_digit)(a[76]); + r[77] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[76]); t = (sp_int_digit)(a[75]); + r[76] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[75]); t = (sp_int_digit)(a[74]); + r[75] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[74]); t = (sp_int_digit)(a[73]); + r[74] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[73]); t = (sp_int_digit)(a[72]); + r[73] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[72]); t = (sp_int_digit)(a[71]); + r[72] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]); + r[71] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]); + r[70] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]); + r[69] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]); + r[68] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]); + r[67] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]); + r[66] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]); + r[65] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]); + r[64] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]); + r[63] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]); + r[62] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]); + r[61] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]); + r[60] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]); + r[59] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]); + r[58] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]); + r[57] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]); + r[56] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]); + r[55] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]); + r[54] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]); + r[53] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]); + r[52] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]); + r[51] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]); + r[50] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]); + r[49] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]); + r[48] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]); + r[47] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]); + r[46] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]); + r[45] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]); + r[44] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]); + r[43] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]); + r[42] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]); + r[41] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]); + r[40] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]); + r[39] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]); + r[38] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]); + r[37] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]); + r[36] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); + r[35] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); + r[34] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); + r[33] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); + r[32] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); + r[31] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); + r[30] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); + r[29] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); + r[28] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); + r[27] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); + r[26] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); + r[25] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); + r[24] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); + r[23] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); + r[22] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); + r[21] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); + r[20] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); + r[19] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); + r[18] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); + r[17] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); + r[16] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); + r[15] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); + r[14] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); + r[13] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); + r[12] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); + r[11] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); + r[10] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); + r[9] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); + r[8] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); + r[7] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); + r[6] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); + r[5] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); + r[4] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); + r[3] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); + r[2] = ((s << n) | (t >> (23U - n))) & 0x7fffff; + s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); + r[1] = ((s << n) | (t >> (23U - n))) & 0x7fffff; +#endif + r[0] = (a[0] << n) & 0x7fffff; +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_134(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[268]; + sp_digit td[135]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 403, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 268; + XMEMSET(td, 0, sizeof(sp_digit) * 403); +#else + norm = nd; + tmp = td; + XMEMSET(td, 0, sizeof(td)); +#endif + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_134(norm, m); + + bits = ((bits + 3) / 4) * 4; + i = ((bits + 22) / 23) - 1; + c = bits % 23; + if (c == 0) { + c = 23; + } + if (i < 134) { + n = e[i--] << (32 - c); + } + else { + n = 0; + i--; + } + if (c < 4) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + sp_3072_lshift_134(r, norm, y); + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_3072_mont_sqr_134(r, r, m, mp); + sp_3072_mont_sqr_134(r, r, m, mp); + sp_3072_mont_sqr_134(r, r, m, mp); + sp_3072_mont_sqr_134(r, r, m, mp); + + sp_3072_lshift_134(r, r, y); + sp_3072_mul_d_134(tmp, norm, (r[134] << 10) + (r[133] >> 13)); + r[134] = 0; + r[133] &= 0x1fffL; + (void)sp_3072_add_134(r, r, tmp); + sp_3072_norm_134(r); + o = sp_3072_cmp_134(r, m); + sp_3072_cond_sub_134(r, r, m, ((o < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + + sp_3072_mont_reduce_134(r, m, mp); + n = sp_3072_cmp_134(r, m); + sp_3072_cond_sub_134(r, r, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} + +#endif /* HAVE_FFDHE_3072 */ + +/* 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. + * returns 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) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 384) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 134 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + b = d; + e = b + 134 * 2; + m = e + 134; + r = b; + + sp_3072_from_mp(b, 134, base); + sp_3072_from_bin(e, 134, exp, expLen); + sp_3072_from_mp(m, 134, mod); + + #ifdef HAVE_FFDHE_3072 + if (base->used == 1 && base->dp[0] == 2 && + ((m[133] << 3) | (m[132] >> 20)) == 0xffffL) { + err = sp_3072_mod_exp_2_134(r, e, expLen * 8, m); + } + else + #endif + err = sp_3072_mod_exp_134(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) * 134U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[268], ed[134], md[134]; +#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) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 384U) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 134 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 134 * 2; + m = e + 134; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 134, base); + sp_3072_from_bin(e, 134, exp, expLen); + sp_3072_from_mp(m, 134, mod); + + #ifdef HAVE_FFDHE_3072 + if (base->used == 1 && base->dp[0] == 2U && + ((m[133] << 3) | (m[132] >> 20)) == 0xffffL) { + err = sp_3072_mod_exp_2_134(r, e, expLen * 8U, m); + } + else { + #endif + err = sp_3072_mod_exp_134(r, b, e, expLen * 8U, m, 0); + #ifdef HAVE_FFDHE_3072 + } + #endif + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384U && out[i] == 0U; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 134U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 134U); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 67 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + b = d; + e = b + 67 * 2; + m = e + 67; + r = b; + + sp_3072_from_mp(b, 67, base); + sp_3072_from_mp(e, 67, exp); + sp_3072_from_mp(m, 67, mod); + + err = sp_3072_mod_exp_67(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 67, 0, sizeof(*r) * 67U); + err = sp_3072_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 67U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[134], ed[67], md[67]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 67 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 67 * 2; + m = e + 67; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 67, base); + sp_3072_from_mp(e, 67, exp); + sp_3072_from_mp(m, 67, mod); + + err = sp_3072_mod_exp_67(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 67, 0, sizeof(*r) * 67U); + err = sp_3072_to_mp(r, res); + } + + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 67U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 67U); +#endif + + return err; +#endif +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#ifdef WOLFSSL_SP_4096 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 13U) { + r[j] &= 0x1fffff; + s = 21U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 21 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 21 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x1fffff; + s = 21U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 21U) <= (word32)DIGIT_BIT) { + s += 21U; + r[j] &= 0x1fffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 21) { + r[j] &= 0x1fffff; + if (j + 1 >= size) { + break; + } + s = 21 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 512 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_4096_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<195; i++) { + r[i+1] += r[i] >> 21; + r[i] &= 0x1fffff; + } + j = 4096 / 8 - 1; + a[j] = 0; + for (i=0; i<196 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 21) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 21); + if (j >= 0) { + 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. + */ +SP_NOINLINE static void sp_4096_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. + */ +SP_NOINLINE static void sp_4096_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. + */ +SP_NOINLINE static int sp_4096_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. + */ +SP_NOINLINE static int sp_4096_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. + */ +SP_NOINLINE static int sp_4096_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. + */ +SP_NOINLINE static void sp_4096_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; + (void)sp_4096_add_49(a1, a, &a[49]); + (void)sp_4096_add_49(b1, b, &b[49]); + sp_4096_mul_49(z2, &a[49], &b[49]); + sp_4096_mul_49(z0, a, b); + sp_4096_mul_49(z1, a1, b1); + (void)sp_4096_sub_98(z1, z1, z2); + (void)sp_4096_sub_98(z1, z1, z0); + (void)sp_4096_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. + */ +SP_NOINLINE static void sp_4096_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; + (void)sp_4096_add_49(a1, a, &a[49]); + sp_4096_sqr_49(z2, &a[49]); + sp_4096_sqr_49(z0, a); + sp_4096_sqr_49(z1, a1); + (void)sp_4096_sub_98(z1, z1, z2); + (void)sp_4096_sub_98(z1, z1, z0); + (void)sp_4096_add_98(r + 49, r + 49, 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. + */ +SP_NOINLINE static int sp_4096_add_196(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 192; 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[192] = a[192] + b[192]; + r[193] = a[193] + b[193]; + r[194] = a[194] + b[194]; + r[195] = a[195] + b[195]; + + 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. + */ +SP_NOINLINE static int sp_4096_sub_196(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 192; 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[192] = a[192] - b[192]; + r[193] = a[193] - b[193]; + r[194] = a[194] - b[194]; + r[195] = a[195] - b[195]; + + 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. + */ +SP_NOINLINE static void sp_4096_mul_196(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[196]; + sp_digit* a1 = z1; + sp_digit b1[98]; + sp_digit* z2 = r + 196; + (void)sp_4096_add_98(a1, a, &a[98]); + (void)sp_4096_add_98(b1, b, &b[98]); + sp_4096_mul_98(z2, &a[98], &b[98]); + sp_4096_mul_98(z0, a, b); + sp_4096_mul_98(z1, a1, b1); + (void)sp_4096_sub_196(z1, z1, z2); + (void)sp_4096_sub_196(z1, z1, z0); + (void)sp_4096_add_196(r + 98, r + 98, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_4096_sqr_196(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[196]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 196; + (void)sp_4096_add_98(a1, a, &a[98]); + sp_4096_sqr_98(z2, &a[98]); + sp_4096_sqr_98(z0, a); + sp_4096_sqr_98(z1, a1); + (void)sp_4096_sub_196(z1, z1, z2); + (void)sp_4096_sub_196(z1, z1, z0); + (void)sp_4096_add_196(r + 98, r + 98, 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. + */ +SP_NOINLINE static int sp_4096_add_196(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 196; 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. + */ +SP_NOINLINE static int sp_4096_sub_196(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 196; 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. + */ +SP_NOINLINE static void sp_4096_mul_196(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[195]) * b[195]; + r[391] = (sp_digit)(c >> 21); + c = (c & 0x1fffff) << 21; + for (k = 389; k >= 0; k--) { + for (i = 195; i >= 0; i--) { + j = k - i; + if (j >= 196) { + 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. + */ +SP_NOINLINE static void sp_4096_sqr_196(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[195]) * a[195]; + r[391] = (sp_digit)(c >> 21); + c = (c & 0x1fffff) << 21; + for (k = 389; k >= 0; k--) { + for (i = 195; i >= 0; i--) { + j = k - i; + if (j >= 196 || 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(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) +#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. + */ +SP_NOINLINE static int sp_4096_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. + */ +SP_NOINLINE static int sp_4096_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. + */ +SP_NOINLINE static void sp_4096_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. + */ +SP_NOINLINE static void sp_4096_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 */ +#endif /* WOLFSSL_HAVE_SP_RSA && !SP_RSA_PRIVATE_EXP_D */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_4096_mont_setup(const 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; +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_4096_mul_d_196(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 196; i++) { + t += tb * a[i]; + r[i] = t & 0x1fffff; + t >>= 21; + } + r[196] = (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 < 192; 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[193]; + r[193] = (sp_digit)(t[0] >> 21) + (t[1] & 0x1fffff); + t[2] = tb * a[194]; + r[194] = (sp_digit)(t[1] >> 21) + (t[2] & 0x1fffff); + t[3] = tb * a[195]; + r[195] = (sp_digit)(t[2] >> 21) + (t[3] & 0x1fffff); + r[196] = (sp_digit)(t[3] >> 21); +#endif /* WOLFSSL_SP_SMALL */ +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 4096 bits, just need to subtract. + * + * r A single precision number. + * m A single precision number. + */ +static void sp_4096_mont_norm_98(sp_digit* r, const 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 */ + (void)sp_4096_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_4096_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 == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[97] - b[97]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[96] - b[96]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 88; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#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_4096_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. + */ +SP_NOINLINE static void sp_4096_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] += (sp_digit)(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 */ +} + +/* Normalize the values in each word to 21. + * + * a Array of sp_digit to normalize. + */ +static void sp_4096_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_4096_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) * 98U); +} + +/* Reduce the number back to 4096 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_4096_mont_reduce_98(sp_digit* a, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_4096_norm_98(a + 98); + + for (i=0; i<97; i++) { + mu = (a[i] * mp) & 0x1fffff; + sp_4096_mul_add_98(a+i, m, mu); + a[i+1] += a[i] >> 21; + } + mu = (a[i] * mp) & 0x7ffL; + sp_4096_mul_add_98(a+i, m, mu); + a[i+1] += a[i] >> 21; + a[i] &= 0x1fffff; + + sp_4096_mont_shift_98(a, a); + sp_4096_cond_sub_98(a, a, m, 0 - (((a[97] >> 11) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_4096_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_4096_mont_mul_98(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_4096_mul_98(r, a, b); + sp_4096_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_4096_mont_sqr_98(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_4096_sqr_98(r, a); + sp_4096_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. + */ +SP_NOINLINE static void sp_4096_mul_d_98(sp_digit* r, const sp_digit* a, + 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_4096_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 */ +} + +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_4096_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 +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_4096_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 +SP_NOINLINE static void sp_4096_rshift_98(sp_digit* r, sp_digit* a, byte n) +{ + int i; + +#ifdef WOLFSSL_SP_SMALL + for (i=0; i<97; i++) { + r[i] = ((a[i] >> n) | (a[i + 1] << (21 - n))) & 0x1fffff; + } +#else + for (i=0; i<96; i += 8) { + r[i+0] = ((a[i+0] >> n) | (a[i+1] << (21 - n))) & 0x1fffff; + r[i+1] = ((a[i+1] >> n) | (a[i+2] << (21 - n))) & 0x1fffff; + r[i+2] = ((a[i+2] >> n) | (a[i+3] << (21 - n))) & 0x1fffff; + r[i+3] = ((a[i+3] >> n) | (a[i+4] << (21 - n))) & 0x1fffff; + r[i+4] = ((a[i+4] >> n) | (a[i+5] << (21 - n))) & 0x1fffff; + r[i+5] = ((a[i+5] >> n) | (a[i+6] << (21 - n))) & 0x1fffff; + r[i+6] = ((a[i+6] >> n) | (a[i+7] << (21 - n))) & 0x1fffff; + r[i+7] = ((a[i+7] >> n) | (a[i+8] << (21 - n))) & 0x1fffff; + } + r[96] = ((a[96] >> n) | (a[97] << (21 - n))) & 0x1fffff; +#endif + r[97] = a[97] >> n; +} + +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_4096_div_word_98(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 21 bits from d1 and top 10 bits from d0. */ + d = (d1 << 10) | (d0 >> 11); + r = d / dv; + d -= r * dv; + /* Up to 11 bits in r */ + /* Next 10 bits from d0. */ + r <<= 10; + d <<= 10; + d |= (d0 >> 1) & ((1 << 10) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 21 bits in r */ + /* Remaining 1 bits from d0. */ + r <<= 1; + d <<= 1; + d |= d0 & ((1 << 1) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* 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_4096_div_98(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[196 + 1], t2d[98 + 1], sdd[98 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* sd; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 98 + 3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + (void)m; + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 196 + 1; + sd = t2 + 98 + 1; +#else + t1 = t1d; + t2 = t2d; + sd = sdd; +#endif + + sp_4096_mul_d_98(sd, d, 1L << 10); + sp_4096_mul_d_196(t1, a, 1L << 10); + dv = sd[97]; + for (i=98; i>=0; i--) { + t1[98 + i] += t1[98 + i - 1] >> 21; + t1[98 + i - 1] &= 0x1fffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[98 + i]; + d1 <<= 21; + d1 += t1[98 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_4096_div_word_98(t1[98 + i], t1[98 + i - 1], dv); +#endif + + sp_4096_mul_d_98(t2, sd, r1); + (void)sp_4096_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]) / dv; + r1 -= t1[98 + i]; + sp_4096_mul_d_98(t2, sd, r1); + (void)sp_4096_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; + r1 = t1[98 - 1] / dv; + + sp_4096_mul_d_98(t2, sd, r1); + sp_4096_sub_98(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 98U); + for (i=0; i<96; i++) { + r[i+1] += r[i] >> 21; + r[i] &= 0x1fffff; + } + sp_4096_cond_add_98(r, r, sd, 0 - ((r[97] < 0) ? + (sp_digit)1 : (sp_digit)0)); + + sp_4096_norm_98(r); + sp_4096_rshift_98(r, r, 10); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_4096_mod_98(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_98(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_4096_mod_exp_98(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, + const 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) * 3U * 98U * 2U); + + norm = t[0] = td; + t[1] = &td[98 * 2]; + t[2] = &td[2 * 98 * 2]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_98(norm, m); + + if (reduceA != 0) { + err = sp_4096_mod_98(t[1], a, m); + } + else { + XMEMCPY(t[1], a, sizeof(sp_digit) * 98U); + } + } + if (err == MP_OKAY) { + sp_4096_mul_98(t[1], t[1], norm); + err = sp_4096_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_4096_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_4096_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_4096_mont_reduce_98(t[0], m, mp); + n = sp_4096_cmp_98(t[0], m); + sp_4096_cond_sub_98(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t[0] = td; + t[1] = &td[98 * 2]; + t[2] = &td[2 * 98 * 2]; +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_98(norm, m); + + if (reduceA != 0) { + err = sp_4096_mod_98(t[1], a, m); + if (err == MP_OKAY) { + sp_4096_mul_98(t[1], t[1], norm); + err = sp_4096_mod_98(t[1], t[1], m); + } + } + else { + sp_4096_mul_98(t[1], a, norm); + err = sp_4096_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_4096_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_4096_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_4096_mont_reduce_98(t[0], m, mp); + n = sp_4096_cmp_98(t[0], m); + sp_4096_cond_sub_98(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 196; +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_98(norm, m); + + if (reduceA != 0) { + err = sp_4096_mod_98(t[1], a, m); + if (err == MP_OKAY) { + sp_4096_mul_98(t[1], t[1], norm); + err = sp_4096_mod_98(t[1], t[1], m); + } + } + else { + sp_4096_mul_98(t[1], a, norm); + err = sp_4096_mod_98(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_98(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_98(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_98(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_98(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_98(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_98(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_98(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_98(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_98(t[10], t[ 5], m, mp); + sp_4096_mont_mul_98(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_98(t[12], t[ 6], m, mp); + sp_4096_mont_mul_98(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_98(t[14], t[ 7], m, mp); + sp_4096_mont_mul_98(t[15], t[ 8], t[ 7], m, mp); + sp_4096_mont_sqr_98(t[16], t[ 8], m, mp); + sp_4096_mont_mul_98(t[17], t[ 9], t[ 8], m, mp); + sp_4096_mont_sqr_98(t[18], t[ 9], m, mp); + sp_4096_mont_mul_98(t[19], t[10], t[ 9], m, mp); + sp_4096_mont_sqr_98(t[20], t[10], m, mp); + sp_4096_mont_mul_98(t[21], t[11], t[10], m, mp); + sp_4096_mont_sqr_98(t[22], t[11], m, mp); + sp_4096_mont_mul_98(t[23], t[12], t[11], m, mp); + sp_4096_mont_sqr_98(t[24], t[12], m, mp); + sp_4096_mont_mul_98(t[25], t[13], t[12], m, mp); + sp_4096_mont_sqr_98(t[26], t[13], m, mp); + sp_4096_mont_mul_98(t[27], t[14], t[13], m, mp); + sp_4096_mont_sqr_98(t[28], t[14], m, mp); + sp_4096_mont_mul_98(t[29], t[15], t[14], m, mp); + sp_4096_mont_sqr_98(t[30], t[15], m, mp); + sp_4096_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) & 0x1f; + 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_4096_mont_sqr_98(rt, rt, m, mp); + sp_4096_mont_sqr_98(rt, rt, m, mp); + sp_4096_mont_sqr_98(rt, rt, m, mp); + sp_4096_mont_sqr_98(rt, rt, m, mp); + sp_4096_mont_sqr_98(rt, rt, m, mp); + + sp_4096_mont_mul_98(rt, rt, t[y], m, mp); + } + + sp_4096_mont_reduce_98(rt, m, mp); + n = sp_4096_cmp_98(rt, m); + sp_4096_cond_sub_98(rt, rt, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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 /* WOLFSSL_HAVE_SP_RSA && !SP_RSA_PRIVATE_EXP_D */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 4096 bits, just need to subtract. + * + * r A single precision number. + * m A single precision number. + */ +static void sp_4096_mont_norm_196(sp_digit* r, const sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<195; i++) { + r[i] = 0x1fffff; + } +#else + int i; + + for (i = 0; i < 192; 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[192] = 0x1fffff; + r[193] = 0x1fffff; + r[194] = 0x1fffff; +#endif + r[195] = 0x1L; + + /* r = (2^n - 1) mod n */ + (void)sp_4096_sub_196(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_4096_cmp_196(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=195; i>=0; i--) { + r |= (a[i] - b[i]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[195] - b[195]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[194] - b[194]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[193] - b[193]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[192] - b[192]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 184; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#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_4096_cond_sub_196(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 < 196; i++) { + r[i] = a[i] - (b[i] & m); + } +#else + int i; + + for (i = 0; i < 192; 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[192] = a[192] - (b[192] & m); + r[193] = a[193] - (b[193] & m); + r[194] = a[194] - (b[194] & m); + r[195] = a[195] - (b[195] & 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. + */ +SP_NOINLINE static void sp_4096_mul_add_196(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 < 196; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1fffff; + t >>= 21; + } + r[196] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1fffff); + for (i = 0; i < 192; 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[193]; r[193] += (sp_digit)((t[0] >> 21) + (t[1] & 0x1fffff)); + t[2] = tb * a[194]; r[194] += (sp_digit)((t[1] >> 21) + (t[2] & 0x1fffff)); + t[3] = tb * a[195]; r[195] += (sp_digit)((t[2] >> 21) + (t[3] & 0x1fffff)); + r[196] += (sp_digit)(t[3] >> 21); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 21. + * + * a Array of sp_digit to normalize. + */ +static void sp_4096_norm_196(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 195; i++) { + a[i+1] += a[i] >> 21; + a[i] &= 0x1fffff; + } +#else + int i; + for (i = 0; i < 192; 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[192+1] += a[192] >> 21; + a[192] &= 0x1fffff; + a[193+1] += a[193] >> 21; + a[193] &= 0x1fffff; + a[194+1] += a[194] >> 21; + a[194] &= 0x1fffff; +#endif +} + +/* Shift the result in the high 4096 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_4096_mont_shift_196(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int64_t n = a[195] >> 1; + n += ((int64_t)a[196]) << 20; + + for (i = 0; i < 195; i++) { + r[i] = n & 0x1fffff; + n >>= 21; + n += ((int64_t)a[197 + i]) << 20; + } + r[195] = (sp_digit)n; +#else + int i; + int64_t n = a[195] >> 1; + n += ((int64_t)a[196]) << 20; + for (i = 0; i < 192; i += 8) { + r[i + 0] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 197]) << 20; + r[i + 1] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 198]) << 20; + r[i + 2] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 199]) << 20; + r[i + 3] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 200]) << 20; + r[i + 4] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 201]) << 20; + r[i + 5] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 202]) << 20; + r[i + 6] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 203]) << 20; + r[i + 7] = n & 0x1fffff; + n >>= 21; n += ((int64_t)a[i + 204]) << 20; + } + r[192] = n & 0x1fffff; n >>= 21; n += ((int64_t)a[389]) << 20; + r[193] = n & 0x1fffff; n >>= 21; n += ((int64_t)a[390]) << 20; + r[194] = n & 0x1fffff; n >>= 21; n += ((int64_t)a[391]) << 20; + r[195] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[196], 0, sizeof(*r) * 196U); +} + +/* Reduce the number back to 4096 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_4096_mont_reduce_196(sp_digit* a, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_4096_norm_196(a + 196); + +#ifdef WOLFSSL_SP_DH + if (mp != 1) { + for (i=0; i<195; i++) { + mu = (a[i] * mp) & 0x1fffff; + sp_4096_mul_add_196(a+i, m, mu); + a[i+1] += a[i] >> 21; + } + mu = (a[i] * mp) & 0x1L; + sp_4096_mul_add_196(a+i, m, mu); + a[i+1] += a[i] >> 21; + a[i] &= 0x1fffff; + } + else { + for (i=0; i<195; i++) { + mu = a[i] & 0x1fffff; + sp_4096_mul_add_196(a+i, m, mu); + a[i+1] += a[i] >> 21; + } + mu = a[i] & 0x1L; + sp_4096_mul_add_196(a+i, m, mu); + a[i+1] += a[i] >> 21; + a[i] &= 0x1fffff; + } +#else + for (i=0; i<195; i++) { + mu = (a[i] * mp) & 0x1fffff; + sp_4096_mul_add_196(a+i, m, mu); + a[i+1] += a[i] >> 21; + } + mu = (a[i] * mp) & 0x1L; + sp_4096_mul_add_196(a+i, m, mu); + a[i+1] += a[i] >> 21; + a[i] &= 0x1fffff; +#endif + + sp_4096_mont_shift_196(a, a); + sp_4096_cond_sub_196(a, a, m, 0 - (((a[195] >> 1) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_4096_norm_196(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_4096_mont_mul_196(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_4096_mul_196(r, a, b); + sp_4096_mont_reduce_196(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_4096_mont_sqr_196(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_4096_sqr_196(r, a); + sp_4096_mont_reduce_196(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. + */ +SP_NOINLINE static void sp_4096_mul_d_392(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 392; i++) { + t += tb * a[i]; + r[i] = t & 0x1fffff; + t >>= 21; + } + r[392] = (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 < 392; 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[392] = (sp_digit)(t[7] >> 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_4096_cond_add_196(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 < 196; i++) { + r[i] = a[i] + (b[i] & m); + } +#else + int i; + + for (i = 0; i < 192; 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[192] = a[192] + (b[192] & m); + r[193] = a[193] + (b[193] & m); + r[194] = a[194] + (b[194] & m); + r[195] = a[195] + (b[195] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_4096_sub_196(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 196; i++) { + r[i] = a[i] - b[i]; + } + + return 0; +} + +#endif +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_4096_add_196(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 196; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#endif +SP_NOINLINE static void sp_4096_rshift_196(sp_digit* r, sp_digit* a, byte n) +{ + int i; + +#ifdef WOLFSSL_SP_SMALL + for (i=0; i<195; i++) { + r[i] = ((a[i] >> n) | (a[i + 1] << (21 - n))) & 0x1fffff; + } +#else + for (i=0; i<192; i += 8) { + r[i+0] = ((a[i+0] >> n) | (a[i+1] << (21 - n))) & 0x1fffff; + r[i+1] = ((a[i+1] >> n) | (a[i+2] << (21 - n))) & 0x1fffff; + r[i+2] = ((a[i+2] >> n) | (a[i+3] << (21 - n))) & 0x1fffff; + r[i+3] = ((a[i+3] >> n) | (a[i+4] << (21 - n))) & 0x1fffff; + r[i+4] = ((a[i+4] >> n) | (a[i+5] << (21 - n))) & 0x1fffff; + r[i+5] = ((a[i+5] >> n) | (a[i+6] << (21 - n))) & 0x1fffff; + r[i+6] = ((a[i+6] >> n) | (a[i+7] << (21 - n))) & 0x1fffff; + r[i+7] = ((a[i+7] >> n) | (a[i+8] << (21 - n))) & 0x1fffff; + } + r[192] = ((a[192] >> n) | (a[193] << (21 - n))) & 0x1fffff; + r[193] = ((a[193] >> n) | (a[194] << (21 - n))) & 0x1fffff; + r[194] = ((a[194] >> n) | (a[195] << (21 - n))) & 0x1fffff; +#endif + r[195] = a[195] >> n; +} + +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_4096_div_word_196(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 21 bits from d1 and top 10 bits from d0. */ + d = (d1 << 10) | (d0 >> 11); + r = d / dv; + d -= r * dv; + /* Up to 11 bits in r */ + /* Next 10 bits from d0. */ + r <<= 10; + d <<= 10; + d |= (d0 >> 1) & ((1 << 10) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 21 bits in r */ + /* Remaining 1 bits from d0. */ + r <<= 1; + d <<= 1; + d |= d0 & ((1 << 1) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* 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_4096_div_196(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[392 + 1], t2d[196 + 1], sdd[196 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* sd; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 196 + 3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + (void)m; + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 392 + 1; + sd = t2 + 196 + 1; +#else + t1 = t1d; + t2 = t2d; + sd = sdd; +#endif + + sp_4096_mul_d_196(sd, d, 1L << 20); + sp_4096_mul_d_392(t1, a, 1L << 20); + dv = sd[195]; + for (i=196; i>=0; i--) { + t1[196 + i] += t1[196 + i - 1] >> 21; + t1[196 + i - 1] &= 0x1fffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[196 + i]; + d1 <<= 21; + d1 += t1[196 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_4096_div_word_196(t1[196 + i], t1[196 + i - 1], dv); +#endif + + sp_4096_mul_d_196(t2, sd, r1); + (void)sp_4096_sub_196(&t1[i], &t1[i], t2); + t1[196 + i] -= t2[196]; + t1[196 + i] += t1[196 + i - 1] >> 21; + t1[196 + i - 1] &= 0x1fffff; + r1 = (((-t1[196 + i]) << 21) - t1[196 + i - 1]) / dv; + r1 -= t1[196 + i]; + sp_4096_mul_d_196(t2, sd, r1); + (void)sp_4096_add_196(&t1[i], &t1[i], t2); + t1[196 + i] += t1[196 + i - 1] >> 21; + t1[196 + i - 1] &= 0x1fffff; + } + t1[196 - 1] += t1[196 - 2] >> 21; + t1[196 - 2] &= 0x1fffff; + r1 = t1[196 - 1] / dv; + + sp_4096_mul_d_196(t2, sd, r1); + sp_4096_sub_196(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 196U); + for (i=0; i<194; i++) { + r[i+1] += r[i] >> 21; + r[i] &= 0x1fffff; + } + sp_4096_cond_add_196(r, r, sd, 0 - ((r[195] < 0) ? + (sp_digit)1 : (sp_digit)0)); + + sp_4096_norm_196(r); + sp_4096_rshift_196(r, r, 20); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_4096_mod_196(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_196(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + 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_4096_mod_exp_196(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, + const 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 * 196 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3U * 196U * 2U); + + norm = t[0] = td; + t[1] = &td[196 * 2]; + t[2] = &td[2 * 196 * 2]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_196(norm, m); + + if (reduceA != 0) { + err = sp_4096_mod_196(t[1], a, m); + } + else { + XMEMCPY(t[1], a, sizeof(sp_digit) * 196U); + } + } + if (err == MP_OKAY) { + sp_4096_mul_196(t[1], t[1], norm); + err = sp_4096_mod_196(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_4096_mont_mul_196(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]) * 196 * 2); + sp_4096_mont_sqr_196(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]) * 196 * 2); + } + + sp_4096_mont_reduce_196(t[0], m, mp); + n = sp_4096_cmp_196(t[0], m); + sp_4096_cond_sub_196(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 196 * 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][392]; +#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 * 196 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t[0] = td; + t[1] = &td[196 * 2]; + t[2] = &td[2 * 196 * 2]; +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_196(norm, m); + + if (reduceA != 0) { + err = sp_4096_mod_196(t[1], a, m); + if (err == MP_OKAY) { + sp_4096_mul_196(t[1], t[1], norm); + err = sp_4096_mod_196(t[1], t[1], m); + } + } + else { + sp_4096_mul_196(t[1], a, norm); + err = sp_4096_mod_196(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_4096_mont_mul_196(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_4096_mont_sqr_196(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_4096_mont_reduce_196(t[0], m, mp); + n = sp_4096_cmp_196(t[0], m); + sp_4096_cond_sub_196(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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][392]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[392]; + 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 * 392, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 392; +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_196(norm, m); + + if (reduceA != 0) { + err = sp_4096_mod_196(t[1], a, m); + if (err == MP_OKAY) { + sp_4096_mul_196(t[1], t[1], norm); + err = sp_4096_mod_196(t[1], t[1], m); + } + } + else { + sp_4096_mul_196(t[1], a, norm); + err = sp_4096_mod_196(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_196(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_196(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_196(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_196(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_196(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_196(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_196(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_196(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_196(t[10], t[ 5], m, mp); + sp_4096_mont_mul_196(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_196(t[12], t[ 6], m, mp); + sp_4096_mont_mul_196(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_196(t[14], t[ 7], m, mp); + sp_4096_mont_mul_196(t[15], t[ 8], t[ 7], m, mp); + sp_4096_mont_sqr_196(t[16], t[ 8], m, mp); + sp_4096_mont_mul_196(t[17], t[ 9], t[ 8], m, mp); + sp_4096_mont_sqr_196(t[18], t[ 9], m, mp); + sp_4096_mont_mul_196(t[19], t[10], t[ 9], m, mp); + sp_4096_mont_sqr_196(t[20], t[10], m, mp); + sp_4096_mont_mul_196(t[21], t[11], t[10], m, mp); + sp_4096_mont_sqr_196(t[22], t[11], m, mp); + sp_4096_mont_mul_196(t[23], t[12], t[11], m, mp); + sp_4096_mont_sqr_196(t[24], t[12], m, mp); + sp_4096_mont_mul_196(t[25], t[13], t[12], m, mp); + sp_4096_mont_sqr_196(t[26], t[13], m, mp); + sp_4096_mont_mul_196(t[27], t[14], t[13], m, mp); + sp_4096_mont_sqr_196(t[28], t[14], m, mp); + sp_4096_mont_mul_196(t[29], t[15], t[14], m, mp); + sp_4096_mont_sqr_196(t[30], t[15], m, mp); + sp_4096_mont_mul_196(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 < 196) { + n = e[i--] << (32 - c); + } + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (11 - c); + c += 21; + } + y = (n >> 27) & 0x1f; + 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_4096_mont_sqr_196(rt, rt, m, mp); + sp_4096_mont_sqr_196(rt, rt, m, mp); + sp_4096_mont_sqr_196(rt, rt, m, mp); + sp_4096_mont_sqr_196(rt, rt, m, mp); + sp_4096_mont_sqr_196(rt, rt, m, mp); + + sp_4096_mont_mul_196(rt, rt, t[y], m, mp); + } + + sp_4096_mont_reduce_196(rt, m, mp); + n = sp_4096_cmp_196(rt, m); + sp_4096_cond_sub_196(rt, rt, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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 /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ + /* 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 512 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_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1] = {0}; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 512U) { + err = MP_TO_E; + } + + if (err == MP_OKAY) { + if (mp_count_bits(em) > 21) { + err = MP_READ_E; + } + if (inLen > 512U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 196 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 196 * 2; + m = r + 196 * 2; + norm = r; + + sp_4096_from_bin(a, 196, in, inLen); +#if DIGIT_BIT >= 21 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)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_4096_from_mp(m, 196, mm); + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_196(norm, m); + } + if (err == MP_OKAY) { + sp_4096_mul_196(a, a, norm); + err = sp_4096_mod_196(a, a, m); + } + if (err == MP_OKAY) { + for (i=20; i>=0; i--) { + if ((e[0] >> i) != 0) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 196 * 2); + for (i--; i>=0; i--) { + sp_4096_mont_sqr_196(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) { + sp_4096_mont_mul_196(r, r, a, m, mp); + } + } + sp_4096_mont_reduce_196(r, m, mp); + mp = sp_4096_cmp_196(r, m); + sp_4096_cond_sub_196(r, r, m, ((mp < 0) ? + (sp_digit)1 : (sp_digit)0)- 1); + + sp_4096_to_bin(r, out); + *outLen = 512; + } + + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit ad[392], md[196], rd[392]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit e[1] = {0}; + int err = MP_OKAY; + + if (*outLen < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(em) > 21) { + err = MP_READ_E; + } + if (inLen > 512U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 196 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + a = d; + r = a + 196 * 2; + m = r + 196 * 2; + } +#else + a = ad; + m = md; + r = rd; +#endif + + if (err == MP_OKAY) { + sp_4096_from_bin(a, 196, in, inLen); +#if DIGIT_BIT >= 21 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)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_4096_from_mp(m, 196, mm); + + if (e[0] == 0x3) { + sp_4096_sqr_196(r, a); + err = sp_4096_mod_196(r, r, m); + if (err == MP_OKAY) { + sp_4096_mul_196(r, a, r); + err = sp_4096_mod_196(r, r, m); + } + } + else { + sp_digit* norm = r; + int i; + sp_digit mp; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_196(norm, m); + + sp_4096_mul_196(a, a, norm); + err = sp_4096_mod_196(a, a, m); + + if (err == MP_OKAY) { + for (i=20; i>=0; i--) { + if ((e[0] >> i) != 0) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 392U); + for (i--; i>=0; i--) { + sp_4096_mont_sqr_196(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) { + sp_4096_mont_mul_196(r, r, a, m, mp); + } + } + sp_4096_mont_reduce_196(r, m, mp); + mp = sp_4096_cmp_196(r, m); + sp_4096_cond_sub_196(r, r, m, ((mp < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM) +#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */ +/* 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 512 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_4096(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(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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 < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 4096) { + err = MP_READ_E; + } + if (inLen > 512) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 196 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 196; + m = a + 392; + r = a; + + sp_4096_from_bin(a, 196, in, inLen); + sp_4096_from_mp(d, 196, dm); + sp_4096_from_mp(m, 196, mm); + err = sp_4096_mod_exp_196(r, a, d, 4096, m, 0); + } + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 196); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[392], d[196], m[196]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 4096) { + err = MP_READ_E; + } + if (inLen > 512U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_4096_from_bin(a, 196, in, inLen); + sp_4096_from_mp(d, 196, dm); + sp_4096_from_mp(m, 196, mm); + err = sp_4096_mod_exp_196(r, a, d, 4096, m, 0); + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + + XMEMSET(d, 0, sizeof(sp_digit) * 196); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#else +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (inLen > 512) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 98 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = t; + p = a + 196 * 2; + q = p + 98; + qi = dq = dp = q + 98; + tmpa = qi + 98; + tmpb = tmpa + 196; + + r = t + 196; + + sp_4096_from_bin(a, 196, in, inLen); + sp_4096_from_mp(p, 98, pm); + sp_4096_from_mp(q, 98, qm); + sp_4096_from_mp(dp, 98, dpm); + err = sp_4096_mod_exp_98(tmpa, a, dp, 2048, p, 1); + } + if (err == MP_OKAY) { + sp_4096_from_mp(dq, 98, dqm); + err = sp_4096_mod_exp_98(tmpb, a, dq, 2048, q, 1); + } + if (err == MP_OKAY) { + (void)sp_4096_sub_98(tmpa, tmpa, tmpb); + sp_4096_cond_add_98(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[97] >> 31)); + sp_4096_cond_add_98(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[97] >> 31)); + + sp_4096_from_mp(qi, 98, qim); + sp_4096_mul_98(tmpa, tmpa, qi); + err = sp_4096_mod_98(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_4096_mul_98(tmpa, q, tmpa); + (void)sp_4096_add_196(r, tmpb, tmpa); + sp_4096_norm_196(r); + + sp_4096_to_bin(r, out); + *outLen = 512; + } + + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 98 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[196 * 2]; + sp_digit p[98], q[98], dp[98], dq[98], qi[98]; + sp_digit tmpa[196], tmpb[196]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (inLen > 512U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_4096_from_bin(a, 196, in, inLen); + sp_4096_from_mp(p, 98, pm); + sp_4096_from_mp(q, 98, qm); + sp_4096_from_mp(dp, 98, dpm); + sp_4096_from_mp(dq, 98, dqm); + sp_4096_from_mp(qi, 98, qim); + + err = sp_4096_mod_exp_98(tmpa, a, dp, 2048, p, 1); + } + if (err == MP_OKAY) { + err = sp_4096_mod_exp_98(tmpb, a, dq, 2048, q, 1); + } + + if (err == MP_OKAY) { + (void)sp_4096_sub_98(tmpa, tmpa, tmpb); + sp_4096_cond_add_98(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[97] >> 31)); + sp_4096_cond_add_98(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[97] >> 31)); + sp_4096_mul_98(tmpa, tmpa, qi); + err = sp_4096_mod_98(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_4096_mul_98(tmpa, tmpa, q); + (void)sp_4096_add_196(r, tmpb, tmpa); + sp_4096_norm_196(r); + + sp_4096_to_bin(r, out); + *outLen = 512; + } + + 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 || RSA_LOW_MEM */ +} + +#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_4096_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 21 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 196); + r->used = 196; + mp_clamp(r); +#elif DIGIT_BIT < 21 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 196; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 21) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 21 - s; + } + r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 196; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 21 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 21 - s; + } + else { + s += 21; + } + } + r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 196 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + b = d; + e = b + 196 * 2; + m = e + 196; + r = b; + + sp_4096_from_mp(b, 196, base); + sp_4096_from_mp(e, 196, exp); + sp_4096_from_mp(m, 196, mod); + + err = sp_4096_mod_exp_196(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + err = sp_4096_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 196U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[392], ed[196], md[196]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 196 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 196 * 2; + m = e + 196; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 196, base); + sp_4096_from_mp(e, 196, exp); + sp_4096_from_mp(m, 196, mod); + + err = sp_4096_mod_exp_196(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_4096_to_mp(r, res); + } + + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 196U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 196U); +#endif + + return err; +#endif +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_4096 +SP_NOINLINE static void sp_4096_lshift_196(sp_digit* r, sp_digit* a, byte n) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + r[196] = a[195] >> (21 - n); + for (i=195; i>0; i--) { + r[i] = ((a[i] << n) | (a[i-1] >> (21 - n))) & 0x1fffff; + } +#else + sp_int_digit s, t; + + s = (sp_int_digit)a[195]; + r[196] = s >> (21U - n); + s = (sp_int_digit)(a[195]); t = (sp_int_digit)(a[194]); + r[195] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[194]); t = (sp_int_digit)(a[193]); + r[194] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[193]); t = (sp_int_digit)(a[192]); + r[193] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[192]); t = (sp_int_digit)(a[191]); + r[192] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[191]); t = (sp_int_digit)(a[190]); + r[191] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[190]); t = (sp_int_digit)(a[189]); + r[190] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[189]); t = (sp_int_digit)(a[188]); + r[189] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[188]); t = (sp_int_digit)(a[187]); + r[188] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[187]); t = (sp_int_digit)(a[186]); + r[187] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[186]); t = (sp_int_digit)(a[185]); + r[186] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[185]); t = (sp_int_digit)(a[184]); + r[185] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[184]); t = (sp_int_digit)(a[183]); + r[184] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[183]); t = (sp_int_digit)(a[182]); + r[183] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[182]); t = (sp_int_digit)(a[181]); + r[182] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[181]); t = (sp_int_digit)(a[180]); + r[181] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[180]); t = (sp_int_digit)(a[179]); + r[180] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[179]); t = (sp_int_digit)(a[178]); + r[179] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[178]); t = (sp_int_digit)(a[177]); + r[178] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[177]); t = (sp_int_digit)(a[176]); + r[177] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[176]); t = (sp_int_digit)(a[175]); + r[176] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[175]); t = (sp_int_digit)(a[174]); + r[175] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[174]); t = (sp_int_digit)(a[173]); + r[174] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[173]); t = (sp_int_digit)(a[172]); + r[173] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[172]); t = (sp_int_digit)(a[171]); + r[172] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[171]); t = (sp_int_digit)(a[170]); + r[171] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[170]); t = (sp_int_digit)(a[169]); + r[170] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[169]); t = (sp_int_digit)(a[168]); + r[169] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[168]); t = (sp_int_digit)(a[167]); + r[168] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[167]); t = (sp_int_digit)(a[166]); + r[167] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[166]); t = (sp_int_digit)(a[165]); + r[166] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[165]); t = (sp_int_digit)(a[164]); + r[165] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[164]); t = (sp_int_digit)(a[163]); + r[164] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[163]); t = (sp_int_digit)(a[162]); + r[163] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[162]); t = (sp_int_digit)(a[161]); + r[162] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[161]); t = (sp_int_digit)(a[160]); + r[161] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[160]); t = (sp_int_digit)(a[159]); + r[160] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[159]); t = (sp_int_digit)(a[158]); + r[159] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[158]); t = (sp_int_digit)(a[157]); + r[158] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[157]); t = (sp_int_digit)(a[156]); + r[157] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[156]); t = (sp_int_digit)(a[155]); + r[156] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[155]); t = (sp_int_digit)(a[154]); + r[155] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[154]); t = (sp_int_digit)(a[153]); + r[154] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[153]); t = (sp_int_digit)(a[152]); + r[153] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[152]); t = (sp_int_digit)(a[151]); + r[152] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[151]); t = (sp_int_digit)(a[150]); + r[151] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[150]); t = (sp_int_digit)(a[149]); + r[150] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[149]); t = (sp_int_digit)(a[148]); + r[149] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[148]); t = (sp_int_digit)(a[147]); + r[148] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[147]); t = (sp_int_digit)(a[146]); + r[147] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[146]); t = (sp_int_digit)(a[145]); + r[146] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[145]); t = (sp_int_digit)(a[144]); + r[145] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[144]); t = (sp_int_digit)(a[143]); + r[144] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[143]); t = (sp_int_digit)(a[142]); + r[143] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[142]); t = (sp_int_digit)(a[141]); + r[142] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[141]); t = (sp_int_digit)(a[140]); + r[141] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[140]); t = (sp_int_digit)(a[139]); + r[140] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[139]); t = (sp_int_digit)(a[138]); + r[139] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[138]); t = (sp_int_digit)(a[137]); + r[138] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[137]); t = (sp_int_digit)(a[136]); + r[137] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[136]); t = (sp_int_digit)(a[135]); + r[136] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[135]); t = (sp_int_digit)(a[134]); + r[135] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[134]); t = (sp_int_digit)(a[133]); + r[134] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[133]); t = (sp_int_digit)(a[132]); + r[133] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[132]); t = (sp_int_digit)(a[131]); + r[132] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[131]); t = (sp_int_digit)(a[130]); + r[131] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[130]); t = (sp_int_digit)(a[129]); + r[130] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[129]); t = (sp_int_digit)(a[128]); + r[129] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[128]); t = (sp_int_digit)(a[127]); + r[128] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[127]); t = (sp_int_digit)(a[126]); + r[127] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[126]); t = (sp_int_digit)(a[125]); + r[126] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[125]); t = (sp_int_digit)(a[124]); + r[125] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[124]); t = (sp_int_digit)(a[123]); + r[124] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[123]); t = (sp_int_digit)(a[122]); + r[123] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[122]); t = (sp_int_digit)(a[121]); + r[122] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[121]); t = (sp_int_digit)(a[120]); + r[121] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[120]); t = (sp_int_digit)(a[119]); + r[120] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[119]); t = (sp_int_digit)(a[118]); + r[119] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[118]); t = (sp_int_digit)(a[117]); + r[118] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[117]); t = (sp_int_digit)(a[116]); + r[117] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[116]); t = (sp_int_digit)(a[115]); + r[116] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[115]); t = (sp_int_digit)(a[114]); + r[115] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[114]); t = (sp_int_digit)(a[113]); + r[114] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[113]); t = (sp_int_digit)(a[112]); + r[113] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[112]); t = (sp_int_digit)(a[111]); + r[112] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[111]); t = (sp_int_digit)(a[110]); + r[111] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[110]); t = (sp_int_digit)(a[109]); + r[110] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[109]); t = (sp_int_digit)(a[108]); + r[109] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[108]); t = (sp_int_digit)(a[107]); + r[108] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[107]); t = (sp_int_digit)(a[106]); + r[107] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[106]); t = (sp_int_digit)(a[105]); + r[106] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[105]); t = (sp_int_digit)(a[104]); + r[105] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[104]); t = (sp_int_digit)(a[103]); + r[104] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[103]); t = (sp_int_digit)(a[102]); + r[103] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[102]); t = (sp_int_digit)(a[101]); + r[102] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[101]); t = (sp_int_digit)(a[100]); + r[101] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[100]); t = (sp_int_digit)(a[99]); + r[100] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[99]); t = (sp_int_digit)(a[98]); + r[99] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[98]); t = (sp_int_digit)(a[97]); + r[98] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[97]); t = (sp_int_digit)(a[96]); + r[97] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[96]); t = (sp_int_digit)(a[95]); + r[96] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[95]); t = (sp_int_digit)(a[94]); + r[95] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[94]); t = (sp_int_digit)(a[93]); + r[94] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[93]); t = (sp_int_digit)(a[92]); + r[93] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[92]); t = (sp_int_digit)(a[91]); + r[92] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[91]); t = (sp_int_digit)(a[90]); + r[91] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[90]); t = (sp_int_digit)(a[89]); + r[90] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[89]); t = (sp_int_digit)(a[88]); + r[89] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[88]); t = (sp_int_digit)(a[87]); + r[88] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[87]); t = (sp_int_digit)(a[86]); + r[87] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[86]); t = (sp_int_digit)(a[85]); + r[86] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[85]); t = (sp_int_digit)(a[84]); + r[85] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[84]); t = (sp_int_digit)(a[83]); + r[84] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[83]); t = (sp_int_digit)(a[82]); + r[83] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[82]); t = (sp_int_digit)(a[81]); + r[82] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[81]); t = (sp_int_digit)(a[80]); + r[81] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[80]); t = (sp_int_digit)(a[79]); + r[80] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[79]); t = (sp_int_digit)(a[78]); + r[79] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[78]); t = (sp_int_digit)(a[77]); + r[78] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[77]); t = (sp_int_digit)(a[76]); + r[77] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[76]); t = (sp_int_digit)(a[75]); + r[76] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[75]); t = (sp_int_digit)(a[74]); + r[75] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[74]); t = (sp_int_digit)(a[73]); + r[74] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[73]); t = (sp_int_digit)(a[72]); + r[73] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[72]); t = (sp_int_digit)(a[71]); + r[72] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]); + r[71] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]); + r[70] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]); + r[69] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]); + r[68] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]); + r[67] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]); + r[66] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]); + r[65] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]); + r[64] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]); + r[63] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]); + r[62] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]); + r[61] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]); + r[60] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]); + r[59] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]); + r[58] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]); + r[57] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]); + r[56] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]); + r[55] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]); + r[54] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]); + r[53] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]); + r[52] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]); + r[51] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]); + r[50] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]); + r[49] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]); + r[48] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]); + r[47] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]); + r[46] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]); + r[45] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]); + r[44] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]); + r[43] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]); + r[42] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]); + r[41] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]); + r[40] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]); + r[39] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]); + r[38] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]); + r[37] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]); + r[36] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); + r[35] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); + r[34] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); + r[33] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); + r[32] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); + r[31] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); + r[30] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); + r[29] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); + r[28] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); + r[27] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); + r[26] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); + r[25] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); + r[24] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); + r[23] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); + r[22] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); + r[21] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); + r[20] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); + r[19] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); + r[18] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); + r[17] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); + r[16] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); + r[15] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); + r[14] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); + r[13] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); + r[12] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); + r[11] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); + r[10] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); + r[9] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); + r[8] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); + r[7] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); + r[6] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); + r[5] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); + r[4] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); + r[3] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); + r[2] = ((s << n) | (t >> (21U - n))) & 0x1fffff; + s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); + r[1] = ((s << n) | (t >> (21U - n))) & 0x1fffff; +#endif + r[0] = (a[0] << n) & 0x1fffff; +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_4096_mod_exp_2_196(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[392]; + sp_digit td[197]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 589, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 392; + XMEMSET(td, 0, sizeof(sp_digit) * 589); +#else + norm = nd; + tmp = td; + XMEMSET(td, 0, sizeof(td)); +#endif + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_196(norm, m); + + bits = ((bits + 3) / 4) * 4; + i = ((bits + 20) / 21) - 1; + c = bits % 21; + if (c == 0) { + c = 21; + } + if (i < 196) { + n = e[i--] << (32 - c); + } + else { + n = 0; + i--; + } + if (c < 4) { + n |= e[i--] << (11 - c); + c += 21; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + sp_4096_lshift_196(r, norm, y); + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= e[i--] << (11 - c); + c += 21; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_4096_mont_sqr_196(r, r, m, mp); + sp_4096_mont_sqr_196(r, r, m, mp); + sp_4096_mont_sqr_196(r, r, m, mp); + sp_4096_mont_sqr_196(r, r, m, mp); + + sp_4096_lshift_196(r, r, y); + sp_4096_mul_d_196(tmp, norm, (r[196] << 20) + (r[195] >> 1)); + r[196] = 0; + r[195] &= 0x1L; + (void)sp_4096_add_196(r, r, tmp); + sp_4096_norm_196(r); + o = sp_4096_cmp_196(r, m); + sp_4096_cond_sub_196(r, r, m, ((o < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + + sp_4096_mont_reduce_196(r, m, mp); + n = sp_4096_cmp_196(r, m); + sp_4096_cond_sub_196(r, r, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} + +#endif /* HAVE_FFDHE_4096 */ + +/* 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 512 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returns 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_4096(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) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 512) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 196 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + b = d; + e = b + 196 * 2; + m = e + 196; + r = b; + + sp_4096_from_mp(b, 196, base); + sp_4096_from_bin(e, 196, exp, expLen); + sp_4096_from_mp(m, 196, mod); + + #ifdef HAVE_FFDHE_4096 + if (base->used == 1 && base->dp[0] == 2 && + ((m[195] << 15) | (m[194] >> 6)) == 0xffffL) { + err = sp_4096_mod_exp_2_196(r, e, expLen * 8, m); + } + else + #endif + err = sp_4096_mod_exp_196(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + for (i=0; i<512 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 196U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[392], ed[196], md[196]; +#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) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 512U) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 196 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 196 * 2; + m = e + 196; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 196, base); + sp_4096_from_bin(e, 196, exp, expLen); + sp_4096_from_mp(m, 196, mod); + + #ifdef HAVE_FFDHE_4096 + if (base->used == 1 && base->dp[0] == 2U && + ((m[195] << 15) | (m[194] >> 6)) == 0xffffL) { + err = sp_4096_mod_exp_2_196(r, e, expLen * 8U, m); + } + else { + #endif + err = sp_4096_mod_exp_196(r, b, e, expLen * 8U, m, 0); + #ifdef HAVE_FFDHE_4096 + } + #endif + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + for (i=0; i<512U && out[i] == 0U; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 196U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 196U); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* WOLFSSL_SP_4096 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point_256 { + sp_digit x[2 * 10]; + sp_digit y[2 * 10]; + sp_digit z[2 * 10]; + int infinity; +} sp_point_256; + +/* The modulus (prime) of the curve P256. */ +static const sp_digit p256_mod[10] = { + 0x3ffffff,0x3ffffff,0x3ffffff,0x003ffff,0x0000000,0x0000000,0x0000000, + 0x0000400,0x3ff0000,0x03fffff +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static const sp_digit p256_norm_mod[10] = { + 0x0000001,0x0000000,0x0000000,0x3fc0000,0x3ffffff,0x3ffffff,0x3ffffff, + 0x3fffbff,0x000ffff,0x0000000 +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static const 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 const 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 const 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 const 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 const sp_digit p256_mp_order = 0x200bc4f; +#endif +/* The base point of curve P256. */ +static const sp_point_256 p256_base = { + /* X ordinate */ + { + 0x098c296,0x04e5176,0x33a0f4a,0x204b7ac,0x277037d,0x0e9103c,0x3ce6e56, + 0x1091fe2,0x1f2e12c,0x01ac5f4, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x3bf51f5,0x1901a0d,0x1ececbb,0x15dacc5,0x22bce33,0x303e785,0x27eb4a7, + 0x1fe6e3b,0x2e2fe1a,0x013f8d0, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000,0x0000000,0x0000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p256_b[10] = { + 0x3d2604b,0x38f0f89,0x30f63bc,0x2c3314e,0x0651d06,0x1a621af,0x2bbd557, + 0x24f9ecf,0x1d8aa3a,0x016b18d +}; +#endif + +static int sp_256_point_new_ex_10(void* heap, sp_point_256* sp, sp_point_256** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_256_point_new_10(heap, sp, p) sp_256_point_new_ex_10((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_256_point_new_10(heap, sp, p) sp_256_point_new_ex_10((heap), &(sp), &(p)) +#endif + + +static void sp_256_point_free_10(sp_point_256* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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, const sp_digit* a, const sp_digit* m) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC); + if (td == NULL) { + return MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + a32 = td + 8; +#else + t = td; + a32 = a32d; +#endif + + a32[0] = a[0]; + a32[0] |= a[1] << 26U; + a32[0] &= 0xffffffffL; + a32[1] = (sp_digit)(a[1] >> 6); + a32[1] |= a[2] << 20U; + a32[1] &= 0xffffffffL; + a32[2] = (sp_digit)(a[2] >> 12); + a32[2] |= a[3] << 14U; + a32[2] &= 0xffffffffL; + a32[3] = (sp_digit)(a[3] >> 18); + a32[3] |= a[4] << 8U; + a32[3] &= 0xffffffffL; + a32[4] = (sp_digit)(a[4] >> 24); + a32[4] |= a[5] << 2U; + a32[4] |= a[6] << 28U; + a32[4] &= 0xffffffffL; + a32[5] = (sp_digit)(a[6] >> 4); + a32[5] |= a[7] << 22U; + a32[5] &= 0xffffffffL; + a32[6] = (sp_digit)(a[7] >> 10); + a32[6] |= a[8] << 16U; + a32[6] &= 0xffffffffL; + a32[7] = (sp_digit)(a[8] >> 16); + a32[7] |= a[9] << 10U; + a32[7] &= 0xffffffffL; + + /* 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] >> 32U; t[0] &= 0xffffffffL; + t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; + t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; + t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; + t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; + t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; + t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; + o = t[7] >> 32U; t[7] &= 0xffffffffL; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32U; t[0] &= 0xffffffffL; + t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; + t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; + t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; + t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; + t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; + t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; + + r[0] = (sp_digit)(t[0]) & 0x3ffffffL; + r[1] = (sp_digit)(t[0] >> 26U); + r[1] |= t[1] << 6U; + r[1] &= 0x3ffffffL; + r[2] = (sp_digit)(t[1] >> 20U); + r[2] |= t[2] << 12U; + r[2] &= 0x3ffffffL; + r[3] = (sp_digit)(t[2] >> 14U); + r[3] |= t[3] << 18U; + r[3] &= 0x3ffffffL; + r[4] = (sp_digit)(t[3] >> 8U); + r[4] |= t[4] << 24U; + r[4] &= 0x3ffffffL; + r[5] = (sp_digit)(t[4] >> 2U) & 0x3ffffffL; + r[6] = (sp_digit)(t[4] >> 28U); + r[6] |= t[5] << 4U; + r[6] &= 0x3ffffffL; + r[7] = (sp_digit)(t[5] >> 22U); + r[7] |= t[6] << 10U; + r[7] &= 0x3ffffffL; + r[8] = (sp_digit)(t[6] >> 16U); + r[8] |= t[7] << 16U; + r[8] &= 0x3ffffffL; + r[9] = (sp_digit)(t[7] >> 10U); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 26 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 26 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x3ffffff; + s = 26U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 26U) <= (word32)DIGIT_BIT) { + s += 26U; + r[j] &= 0x3ffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 26) { + r[j] &= 0x3ffffff; + if (j + 1 >= size) { + break; + } + s = 26 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_256. + * + * p Point of type sp_point_256 (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_10(sp_point_256* p, const 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(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always 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] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 26) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(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 && DIGIT_BIT != 64 + 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_256 to type ecc_point. + * + * p Point of type sp_point_256. + * 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(const sp_point_256* 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; +} + +#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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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 */ +#define sp_256_mont_reduce_order_10 sp_256_mont_reduce_10 + +/* 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 == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + r |= (a[ 9] - b[ 9]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 8] - b[ 8]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 7] - b[ 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 6] - b[ 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 5] - b[ 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 4] - b[ 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 3] - b[ 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 2] - b[ 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 1] - b[ 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 0] - b[ 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); +#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_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. + */ +SP_NOINLINE 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] += (sp_digit) (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 */ +} + +/* 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 +} + +/* 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) * 10U); +} + +/* 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, const 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_digit)1 : (sp_digit)0)); + sp_256_norm_10(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_256_mont_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b, + const 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_256_sqr_10(r, a); + sp_256_mont_reduce_10(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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, const sp_digit* a, int n, + const 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); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint32_t p256_mod_minus_2[8] = { + 0xfffffffdU,0xffffffffU,0xffffffffU,0x00000000U,0x00000000U,0x00000000U, + 0x00000001U,0xffffffffU +}; +#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, const 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_minus_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* t1 = td; + sp_digit* t2 = td + 2 * 10; + sp_digit* t3 = td + 4 * 10; + /* 0x2 */ + sp_256_mont_sqr_10(t1, a, p256_mod, p256_mp_mod); + /* 0x3 */ + sp_256_mont_mul_10(t2, t1, a, p256_mod, p256_mp_mod); + /* 0xc */ + sp_256_mont_sqr_n_10(t1, t2, 2, p256_mod, p256_mp_mod); + /* 0xd */ + sp_256_mont_mul_10(t3, t1, a, p256_mod, p256_mp_mod); + /* 0xf */ + sp_256_mont_mul_10(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xf0 */ + sp_256_mont_sqr_n_10(t1, t2, 4, p256_mod, p256_mp_mod); + /* 0xfd */ + sp_256_mont_mul_10(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xff */ + sp_256_mont_mul_10(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xff00 */ + sp_256_mont_sqr_n_10(t1, t2, 8, p256_mod, p256_mp_mod); + /* 0xfffd */ + sp_256_mont_mul_10(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffff */ + sp_256_mont_mul_10(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffff0000 */ + sp_256_mont_sqr_n_10(t1, t2, 16, p256_mod, p256_mp_mod); + /* 0xfffffffd */ + sp_256_mont_mul_10(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffffffff */ + sp_256_mont_mul_10(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000000 */ + sp_256_mont_sqr_n_10(t1, t2, 32, p256_mod, p256_mp_mod); + /* 0xffffffffffffffff */ + sp_256_mont_mul_10(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000001 */ + sp_256_mont_mul_10(r, t1, a, p256_mod, p256_mp_mod); + /* 0xffffffff000000010000000000000000000000000000000000000000 */ + sp_256_mont_sqr_n_10(r, r, 160, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff */ + sp_256_mont_mul_10(r, r, t2, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */ + sp_256_mont_sqr_n_10(r, r, 32, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */ + sp_256_mont_mul_10(r, r, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_10(sp_point_256* r, const sp_point_256* 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) / 2U); + 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_digit)1 : (sp_digit)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) / 2U); + 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_digit)1 : (sp_digit)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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)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_digit)1 : (sp_digit)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, const sp_digit* a, const sp_digit* m) +{ + (void)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_digit)1 : (sp_digit)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, const sp_digit* a, const sp_digit* m) +{ + (void)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_digit)1 : (sp_digit)0)); + sp_256_norm_10(r); + (void)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_digit)1 : (sp_digit)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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)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. + */ +SP_NOINLINE static void sp_256_rshift1_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, const sp_digit* a, const sp_digit* m) +{ + sp_256_cond_add_10(r, a, m, 0 - (a[0] & 1)); + sp_256_norm_10(r); + sp_256_rshift1_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_256* r, const sp_point_256* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*10; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_10(t1, p->z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_10(z, p->y, p->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, p->x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_10(t1, p->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, p->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, p->x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_sqr_10(x, 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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_10(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, + sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + 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) { + const sp_point_256* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)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))) != 0) { + sp_256_proj_point_dbl_10(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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 coordinates. + * + * 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_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#ifdef WOLFSSL_SP_NO_MALLOC + sp_point_256 t[3]; + sp_digit tmp[2 * 10 * 5]; +#else + sp_point_256* t; + sp_digit* tmp; +#endif + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + +#ifndef WOLFSSL_SP_NO_MALLOC + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 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; +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_256) * 3); + + /* 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_256)); + 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_256)); + } + + if (map != 0) { + sp_256_map_10(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_256)); + } + } + +#ifndef WOLFSSL_SP_NO_MALLOC + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 10 * 5); + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_256) * 3); + XFREE(t, NULL, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmp, sizeof(tmp)); + ForceZero(t, sizeof(t)); +#endif + + 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 coordinates. + * + * 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_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 t[3]; + sp_digit tmp[2 * 10 * 5]; +#else + sp_point_256* t; + sp_digit* tmp; +#endif + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point*)XMALLOC(sizeof(*t) * 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; +#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 */ + t[1].infinity = 0; + 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 != 0) { + sp_256_map_10(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_256) * 3); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmp, sizeof(tmp)); + ForceZero(t, sizeof(t)); +#endif + + return err; +} + +#else +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_256 { + sp_digit x[10]; + sp_digit y[10]; +} sp_table_entry_256; + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td[16]; + sp_point_256 rtd; + sp_digit tmpd[2 * 10 * 5]; +#endif + sp_point_256* t; + sp_point_256* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_256_point_new_10(heap, rtd, rt); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 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 */ + (void)sp_256_mod_mul_norm_10(t[1].x, g->x, p256_mod); + (void)sp_256_mod_mul_norm_10(t[1].y, g->y, p256_mod); + (void)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_256)); + 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 != 0) { + sp_256_map_10(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_256) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_256_point_free_10(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_256* p, int n, sp_digit* t) +{ + 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; + + x = p->x; + y = p->y; + z = p->z; + + /* 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); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* 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(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(b, t1, 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(t2, b, p256_mod); + sp_256_mont_sub_10(x, x, t2, 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(t1, t1, p256_mod, p256_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_256_mont_mul_10(w, w, t1, 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, t1, p256_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* 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(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(b, t1, 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(t2, b, p256_mod); + sp_256_mont_sub_10(x, x, t2, 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(t1, t1, 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, t1, p256_mod); +#endif + /* 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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_10(sp_point_256* r, const sp_point_256* p, + const sp_point_256* q, sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + 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 */ + (void)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))) != 0) { + sp_256_proj_point_dbl_10(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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 Temporary data. + */ +static void sp_256_proj_to_affine_10(sp_point_256* 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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_10(const sp_point_256* a, + sp_table_entry_256* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td, s1d, s2d; +#endif + sp_point_256* t; + sp_point_256* s1 = NULL; + sp_point_256* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_256_point_new_10(heap, td, t); + if (err == MP_OKAY) { + err = sp_256_point_new_10(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_256_point_new_10(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_256)); + /* 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)); + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_10(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)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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)); + } + } + } + + sp_256_point_free_10(s2, 0, heap); + sp_256_point_free_10(s1, 0, heap); + sp_256_point_free_10( 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 coordinates. + * + * 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_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit td[2 * 10 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_256_point_new_10(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_256_point_new_10(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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 = !y; + 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 = !y; + sp_256_proj_point_add_qz1_10(rt, rt, p, t); + } + + if (map != 0) { + sp_256_map_10(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_10(p, 0, heap); + sp_256_point_free_10(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_256_t { + sp_digit x[10]; + sp_digit y[10]; + sp_table_entry_256 table[256]; + uint32_t cnt; + int set; +} sp_cache_256_t; + +static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_256_last = -1; +static THREAD_LS_T int sp_cache_256_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_256 = 0; + static wolfSSL_Mutex sp_cache_256_lock; +#endif + +static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_256_inited == 0) { + for (i=0; ix, sp_cache_256[i].x) & + sp_256_cmp_equal_10(g->y, sp_cache_256[i].y)) { + sp_cache_256[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_256_last + 1) % FP_ENTRIES; + for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_256[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_256_last) { + least = sp_cache_256[0].cnt; + for (j=1; jx, sizeof(sp_cache_256[i].x)); + XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y)); + sp_cache_256[i].set = 1; + sp_cache_256[i].cnt = 1; + } + + *cache = &sp_cache_256[i]; + sp_cache_256_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 coordinates. + * + * 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_256* r, const sp_point_256* g, const 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_256_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_256 == 0) { + wc_InitMutex(&sp_cache_256_lock); + initCacheMutex_256 = 1; + } + if (wc_LockMutex(&sp_cache_256_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_256(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_256_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 coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[10]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_256_point_new_10(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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); + + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_10(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 coordinates. + * + * 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_256* r, const sp_digit* k, + int map, void* heap) +{ + /* No pre-computed values. */ + return sp_256_ecc_mulmod_10(r, &p256_base, k, map, heap); +} + +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const 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 const sp_table_entry_256 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 */ + { { 0x0a9143c,0x1cc3506,0x360179e,0x3f17fb6,0x075ba95,0x1d88944, + 0x3b732b7,0x15719e7,0x376a537,0x0062417 }, + { 0x295560a,0x094d5f3,0x245cddf,0x392e867,0x18b4ab8,0x3487cc9, + 0x288688d,0x176174b,0x3182588,0x0215c7f } }, + /* 2 */ + { { 0x147519a,0x2218090,0x32f0202,0x2b09acd,0x0d0981e,0x1e17af2, + 0x14a7caa,0x163a6a7,0x10ddbdf,0x03654f1 }, + { 0x1590f8f,0x0d8733f,0x09179d6,0x1ad139b,0x372e962,0x0bad933, + 0x1961102,0x223cdff,0x37e9eb2,0x0218fae } }, + /* 3 */ + { { 0x0db6485,0x1ad88d7,0x2f97785,0x288bc28,0x3808f0e,0x3df8c02, + 0x28d9544,0x20280f9,0x055b5ff,0x00001d8 }, + { 0x38d2010,0x13ae6e0,0x308a763,0x2ecc90d,0x254014f,0x10a9981, + 0x247d398,0x0fb8383,0x3613437,0x020c21d } }, + /* 4 */ + { { 0x2a0d2bb,0x08bf145,0x34994f9,0x1b06988,0x30d5cc1,0x1f18b22, + 0x01cf3a5,0x199fe49,0x161fd1b,0x00bd79a }, + { 0x1a01797,0x171c2fd,0x21925c1,0x1358255,0x23d20b4,0x1c7f6d4, + 0x111b370,0x03dec12,0x1168d6f,0x03d923e } }, + /* 5 */ + { { 0x137bbbc,0x19a11f8,0x0bec9e5,0x27a29a8,0x3e43446,0x275cd18, + 0x0427617,0x00056c7,0x285133d,0x016af80 }, + { 0x04c7dab,0x2a0df30,0x0c0792a,0x1310c98,0x3573d9f,0x239b30d, + 0x1315627,0x1ce0c32,0x25b6b6f,0x0252edc } }, + /* 6 */ + { { 0x20f141c,0x26d23dc,0x3c74bbf,0x334b7d6,0x06199b3,0x0441171, + 0x3f61294,0x313bf70,0x3cb2f7d,0x03375ae }, + { 0x2f436fd,0x19c02fa,0x26becca,0x1b6e64c,0x26f647f,0x053c948, + 0x0fa7920,0x397d830,0x2bd4bda,0x028d86f } }, + /* 7 */ + { { 0x17c13c7,0x2895616,0x03e128a,0x17d42df,0x1c38d63,0x0f02747, + 0x039aecf,0x0a4b01c,0x209c4b5,0x02e84b2 }, + { 0x1f91dfd,0x023e916,0x07fb9e4,0x19b3ba8,0x13af43b,0x35e02ca, + 0x0eb0899,0x3bd2c7b,0x19d701f,0x014faee } }, + /* 8 */ + { { 0x0e63d34,0x1fb8c6c,0x0fab4fe,0x1caa795,0x0f46005,0x179ed69, + 0x093334d,0x120c701,0x39206d5,0x021627e }, + { 0x183553a,0x03d7319,0x09e5aa7,0x12b8959,0x2087909,0x0011194, + 0x1045071,0x0713f32,0x16d0254,0x03aec1a } }, + /* 9 */ + { { 0x01647c5,0x1b2856b,0x1799461,0x11f133d,0x0b8127d,0x1937eeb, + 0x266aa37,0x1f68f71,0x0cbd1b2,0x03aca08 }, + { 0x287e008,0x1be361a,0x38f3940,0x276488d,0x2d87dfa,0x0333b2c, + 0x2d2e428,0x368755b,0x09b55a7,0x007ca0a } }, + /* 10 */ + { { 0x389da99,0x2a8300e,0x0022abb,0x27ae0a1,0x0a6f2d7,0x207017a, + 0x047862b,0x1358c9e,0x35905e5,0x00cde92 }, + { 0x1f7794a,0x1d40348,0x3f613c6,0x2ddf5b5,0x0207005,0x133f5ba, + 0x1a37810,0x3ef5829,0x0d5f4c2,0x0035978 } }, + /* 11 */ + { { 0x1275d38,0x026efad,0x2358d9d,0x1142f82,0x14268a7,0x1cfac99, + 0x362ff49,0x288cbc1,0x24252f4,0x0308f68 }, + { 0x394520c,0x06e13c2,0x178e5da,0x18ec16f,0x1096667,0x134a7a8, + 0x0dcb869,0x33fc4e9,0x38cc790,0x006778e } }, + /* 12 */ + { { 0x2c5fe04,0x29c5b09,0x1bdb183,0x02ceee8,0x03b28de,0x132dc4b, + 0x32c586a,0x32ff5d0,0x3d491fc,0x038d372 }, + { 0x2a58403,0x2351aea,0x3a53b40,0x21a0ba5,0x39a6974,0x1aaaa2b, + 0x3901273,0x03dfe78,0x3447b4e,0x039d907 } }, + /* 13 */ + { { 0x364ba59,0x14e5077,0x02fc7d7,0x3b02c09,0x1d33f10,0x0560616, + 0x06dfc6a,0x15efd3c,0x357052a,0x01284b7 }, + { 0x039dbd0,0x18ce3e5,0x3e1fbfa,0x352f794,0x0d3c24b,0x07c6cc5, + 0x1e4ffa2,0x3a91bf5,0x293bb5b,0x01abd6a } }, + /* 14 */ + { { 0x0c91999,0x02da644,0x0491da1,0x100a960,0x00a24b4,0x2330824, + 0x0094b4b,0x1004cf8,0x35a66a4,0x017f8d1 }, + { 0x13e7b4b,0x232af7e,0x391ab0f,0x069f08f,0x3292b50,0x3479898, + 0x2889aec,0x2a4590b,0x308ecfe,0x02d5138 } }, + /* 15 */ + { { 0x2ddfdce,0x231ba45,0x39e6647,0x19be245,0x12c3291,0x35399f8, + 0x0d6e764,0x3082d3a,0x2bda6b0,0x0382dac }, + { 0x37efb57,0x04b7cae,0x00070d3,0x379e431,0x01aac0d,0x1e6f251, + 0x0336ad6,0x0ddd3e4,0x3de25a6,0x01c7008 } }, + /* 16 */ + { { 0x3e20925,0x230912f,0x286762a,0x30e3f73,0x391c19a,0x34e1c18, + 0x16a5d5d,0x093d96a,0x3d421d3,0x0187561 }, + { 0x37173ea,0x19ce8a8,0x0b65e87,0x0214dde,0x2238480,0x16ead0f, + 0x38441e0,0x3bef843,0x2124621,0x03e847f } }, + /* 17 */ + { { 0x0b19ffd,0x247cacb,0x3c231c8,0x16ec648,0x201ba8d,0x2b172a3, + 0x103d678,0x2fb72db,0x04c1f13,0x0161bac }, + { 0x3e8ed09,0x171b949,0x2de20c3,0x0f06067,0x21e81a3,0x1b194be, + 0x0fd6c05,0x13c449e,0x0087086,0x006756b } }, + /* 18 */ + { { 0x09a4e1f,0x27d604c,0x00741e9,0x06fa49c,0x0ab7de7,0x3f4a348, + 0x25ef0be,0x158fc9a,0x33f7f9c,0x039f001 }, + { 0x2f59f76,0x3598e83,0x30501f6,0x15083f2,0x0669b3b,0x29980b5, + 0x0c1f7a7,0x0f02b02,0x0fec65b,0x0382141 } }, + /* 19 */ + { { 0x031b3ca,0x23da368,0x2d66f09,0x27b9b69,0x06d1cab,0x13c91ba, + 0x3d81fa9,0x25ad16f,0x0825b09,0x01e3c06 }, + { 0x225787f,0x3bf790e,0x2c9bb7e,0x0347732,0x28016f8,0x0d6ff0d, + 0x2a4877b,0x1d1e833,0x3b87e94,0x010e9dc } }, + /* 20 */ + { { 0x2b533d5,0x1ddcd34,0x1dc0625,0x3da86f7,0x3673b8a,0x1e7b0a4, + 0x3e7c9aa,0x19ac55d,0x251c3b2,0x02edb79 }, + { 0x25259b3,0x24c0ead,0x3480e7e,0x34f40e9,0x3d6a0af,0x2cf3f09, + 0x2c83d19,0x2e66f16,0x19a5d18,0x0182d18 } }, + /* 21 */ + { { 0x2e5aa1c,0x28e3846,0x3658bd6,0x0ad279c,0x1b8b765,0x397e1fb, + 0x130014e,0x3ff342c,0x3b2aeeb,0x02743c9 }, + { 0x2730a55,0x0918c5e,0x083aca9,0x0bf76ef,0x19c955b,0x300669c, + 0x01dfe0a,0x312341f,0x26d356e,0x0091295 } }, + /* 22 */ + { { 0x2cf1f96,0x00e52ba,0x271c6db,0x2a40930,0x19f2122,0x0b2f4ee, + 0x26ac1b8,0x3bda498,0x0873581,0x0117963 }, + { 0x38f9dbc,0x3d1e768,0x2040d3f,0x11ba222,0x3a8aaf1,0x1b82fb5, + 0x1adfb24,0x2de9251,0x21cc1e4,0x0301038 } }, + /* 23 */ + { { 0x38117b6,0x2bc001b,0x1433847,0x3fdce8d,0x3651969,0x3651d7a, + 0x2b35761,0x1bb1d20,0x097682c,0x00737d7 }, + { 0x1f04839,0x1dd6d04,0x16987db,0x3d12378,0x17dbeac,0x1c2cc86, + 0x121dd1b,0x3fcf6ca,0x1f8a92d,0x00119d5 } }, + /* 24 */ + { { 0x0e8ffcd,0x2b174af,0x1a82cc8,0x22cbf98,0x30d53c4,0x080b5b1, + 0x3161727,0x297cfdb,0x2113b83,0x0011b97 }, + { 0x0007f01,0x23fd936,0x3183e7b,0x0496bd0,0x07fb1ef,0x178680f, + 0x1c5ea63,0x0016c11,0x2c3303d,0x01b8041 } }, + /* 25 */ + { { 0x0dd73b1,0x1cd6122,0x10d948c,0x23e657b,0x3767070,0x15a8aad, + 0x385ea8c,0x33c7ce0,0x0ede901,0x0110965 }, + { 0x2d4b65b,0x2a8b244,0x0c37f8f,0x0ee5b24,0x394c234,0x3a5e347, + 0x26e4a15,0x39a3b4c,0x2514c2e,0x029e5be } }, + /* 26 */ + { { 0x23addd7,0x3ed8120,0x13b3359,0x20f959a,0x09e2a61,0x32fcf20, + 0x05b78e3,0x19ba7e2,0x1a9c697,0x0392b4b }, + { 0x2048a61,0x3dfd0a3,0x19a0357,0x233024b,0x3082d19,0x00fb63b, + 0x3a1af4c,0x1450ff0,0x046c37b,0x0317a50 } }, + /* 27 */ + { { 0x3e75f9e,0x294e30a,0x3a78476,0x3a32c48,0x36fd1a9,0x0427012, + 0x1e4df0b,0x11d1f61,0x1afdb46,0x018ca0f }, + { 0x2f2df15,0x0a33dee,0x27f4ce7,0x1542b66,0x3e592c4,0x20d2f30, + 0x3226ade,0x2a4e3ea,0x1ab1981,0x01a2f46 } }, + /* 28 */ + { { 0x087d659,0x3ab5446,0x305ac08,0x3d2cd64,0x33374d5,0x3f9d3f8, + 0x186981c,0x37f5a5a,0x2f53c6f,0x01254a4 }, + { 0x2cec896,0x1e32786,0x04844a8,0x043b16d,0x3d964b2,0x1935829, + 0x16f7e26,0x1a0dd9a,0x30d2603,0x003b1d4 } }, + /* 29 */ + { { 0x12687bb,0x04e816b,0x21fa2da,0x1abccb8,0x3a1f83b,0x375181e, + 0x0f5ef51,0x0fc2ce4,0x3a66486,0x003d881 }, + { 0x3138233,0x1f8eec3,0x2718bd6,0x1b09caa,0x2dd66b9,0x1bb222b, + 0x1004072,0x1b73e3b,0x07208ed,0x03fc36c } }, + /* 30 */ + { { 0x095d553,0x3e84053,0x0a8a749,0x3f575a0,0x3a44052,0x3ced59b, + 0x3b4317f,0x03a8c60,0x13c8874,0x00c4ed4 }, + { 0x0d11549,0x0b8ab02,0x221cb40,0x02ed37b,0x2071ee1,0x1fc8c83, + 0x3987dd4,0x27e049a,0x0f986f1,0x00b4eaf } }, + /* 31 */ + { { 0x15581a2,0x2214060,0x11af4c2,0x1598c88,0x19a0a6d,0x32acba6, + 0x3a7a0f0,0x2337c66,0x210ded9,0x0300dbe }, + { 0x1fbd009,0x3822eb0,0x181629a,0x2401b45,0x30b68b1,0x2e78363, + 0x2b32779,0x006530b,0x2c4b6d4,0x029aca8 } }, + /* 32 */ + { { 0x13549cf,0x0f943db,0x265ed43,0x1bfeb35,0x06f3369,0x3847f2d, + 0x1bfdacc,0x26181a5,0x252af7c,0x02043b8 }, + { 0x159bb2c,0x143f85c,0x357b654,0x2f9d62c,0x2f7dfbe,0x1a7fa9c, + 0x057e74d,0x05d14ac,0x17a9273,0x035215c } }, + /* 33 */ + { { 0x0cb5a98,0x106a2bc,0x10bf117,0x24c7cc4,0x3d3da8f,0x2ce0ab7, + 0x14e2cba,0x1813866,0x1a72f9a,0x01a9811 }, + { 0x2b2411d,0x3034fe8,0x16e0170,0x0f9443a,0x0be0eb8,0x2196cf3, + 0x0c9f738,0x15e40ef,0x0faf9e1,0x034f917 } }, + /* 34 */ + { { 0x03f7669,0x3da6efa,0x3d6bce1,0x209ca1d,0x109f8ae,0x09109e3, + 0x08ae543,0x3067255,0x1dee3c2,0x0081dd5 }, + { 0x3ef1945,0x358765b,0x28c387b,0x3bec4b4,0x218813c,0x0b7d92a, + 0x3cd1d67,0x2c0367e,0x2e57154,0x0123717 } }, + /* 35 */ + { { 0x3e5a199,0x1e42ffd,0x0bb7123,0x33e6273,0x1e0efb8,0x294671e, + 0x3a2bfe0,0x3d11709,0x2eddff6,0x03cbec2 }, + { 0x0b5025f,0x0255d7c,0x1f2241c,0x35d03ea,0x0550543,0x202fef4, + 0x23c8ad3,0x354963e,0x015db28,0x0284fa4 } }, + /* 36 */ + { { 0x2b65cbc,0x1e8d428,0x0226f9f,0x1c8a919,0x10b04b9,0x08fc1e8, + 0x1ce241e,0x149bc99,0x2b01497,0x00afc35 }, + { 0x3216fb7,0x1374fd2,0x226ad3d,0x19fef76,0x0f7d7b8,0x1c21417, + 0x37b83f6,0x3a27eba,0x25a162f,0x010aa52 } }, + /* 37 */ + { { 0x2adf191,0x1ab42fa,0x28d7584,0x2409689,0x20f8a48,0x253707d, + 0x2030504,0x378f7a1,0x169c65e,0x00b0b76 }, + { 0x3849c17,0x085c764,0x10dd6d0,0x2e87689,0x1460488,0x30e9521, + 0x10c7063,0x1b6f120,0x21f42c5,0x03d0dfe } }, + /* 38 */ + { { 0x20f7dab,0x035c512,0x29ac6aa,0x24c5ddb,0x20f0497,0x17ce5e1, + 0x00a050f,0x1eaa14b,0x3335470,0x02abd16 }, + { 0x18d364a,0x0df0cf0,0x316585e,0x018f925,0x0d40b9b,0x17b1511, + 0x1716811,0x1caf3d0,0x10df4f2,0x0337d8c } }, + /* 39 */ + { { 0x2a8b7ef,0x0f188e3,0x2287747,0x06216f0,0x008e935,0x2f6a38d, + 0x1567722,0x0bfc906,0x0bada9e,0x03c3402 }, + { 0x014d3b1,0x099c749,0x2a76291,0x216c067,0x3b37549,0x14ef2f6, + 0x21b96d4,0x1ee2d71,0x2f5ca88,0x016f570 } }, + /* 40 */ + { { 0x09a3154,0x3d1a7bd,0x2e9aef0,0x255b8ac,0x03e85a5,0x2a492a7, + 0x2aec1ea,0x11c6516,0x3c8a09e,0x02a84b7 }, + { 0x1f69f1d,0x09c89d3,0x1e7326f,0x0b28bfd,0x0e0e4c8,0x1ea7751, + 0x18ce73b,0x2a406e7,0x273e48c,0x01b00db } }, + /* 41 */ + { { 0x36e3138,0x2b84a83,0x345a5cf,0x00096b4,0x16966ef,0x159caf1, + 0x13c64b4,0x2f89226,0x25896af,0x00a4bfd }, + { 0x2213402,0x1435117,0x09fed52,0x09d0e4b,0x0f6580e,0x2871cba, + 0x3b397fd,0x1c9d825,0x090311b,0x0191383 } }, + /* 42 */ + { { 0x07153f0,0x1087869,0x18c9e1e,0x1e64810,0x2b86c3b,0x0175d9c, + 0x3dce877,0x269de4e,0x393cab7,0x03c96b9 }, + { 0x1869d0c,0x06528db,0x02641f3,0x209261b,0x29d55c8,0x25ba517, + 0x3b5ea30,0x028f927,0x25313db,0x00e6e39 } }, + /* 43 */ + { { 0x2fd2e59,0x150802d,0x098f377,0x19a4957,0x135e2c0,0x38a95ce, + 0x1ab21a0,0x36c1b67,0x32f0f19,0x00e448b }, + { 0x3cad53c,0x3387800,0x17e3cfb,0x03f9970,0x3225b2c,0x2a84e1d, + 0x3af1d29,0x3fe35ca,0x2f8ce80,0x0237a02 } }, + /* 44 */ + { { 0x07bbb76,0x3aa3648,0x2758afb,0x1f085e0,0x1921c7e,0x3010dac, + 0x22b74b1,0x230137e,0x1062e36,0x021c652 }, + { 0x3993df5,0x24a2ee8,0x126ab5f,0x2d7cecf,0x0639d75,0x16d5414, + 0x1aa78a8,0x3f78404,0x26a5b74,0x03f0c57 } }, + /* 45 */ + { { 0x0d6ecfa,0x3f506ba,0x3f86561,0x3d86bb1,0x15f8c44,0x2491d07, + 0x052a7b4,0x2422261,0x3adee38,0x039b529 }, + { 0x193c75d,0x14bb451,0x1162605,0x293749c,0x370a70d,0x2e8b1f6, + 0x2ede937,0x2b95f4a,0x39a9be2,0x00d77eb } }, + /* 46 */ + { { 0x2736636,0x15bf36a,0x2b7e6b9,0x25eb8b2,0x209f51d,0x3cd2659, + 0x10bf410,0x034afec,0x3d71c83,0x0076971 }, + { 0x0ce6825,0x07920cf,0x3c3b5c4,0x23fe55c,0x015ad11,0x08c0dae, + 0x0552c7f,0x2e75a8a,0x0fddbf4,0x01c1df0 } }, + /* 47 */ + { { 0x2b9661c,0x0ffe351,0x3d71bf6,0x1ac34b3,0x3a1dfd3,0x211fe3d, + 0x33e140a,0x3f9100d,0x32ee50e,0x014ea18 }, + { 0x16d8051,0x1bfda1a,0x068a097,0x2571d3d,0x1daec0c,0x39389af, + 0x194dc35,0x3f3058a,0x36d34e1,0x000a329 } }, + /* 48 */ + { { 0x09877ee,0x351f73f,0x0002d11,0x0420074,0x2c8b362,0x130982d, + 0x02c1175,0x3c11b40,0x0d86962,0x001305f }, + { 0x0daddf5,0x2f4252c,0x15c06d9,0x1d49339,0x1bea235,0x0b680ed, + 0x3356e67,0x1d1d198,0x1e9fed9,0x03dee93 } }, + /* 49 */ + { { 0x3e1263f,0x2fe8d3a,0x3ce6d0d,0x0d5c6b9,0x3557637,0x0a9bd48, + 0x0405538,0x0710749,0x2005213,0x038c7e5 }, + { 0x26b6ec6,0x2e485ba,0x3c44d1b,0x0b9cf0b,0x037a1d1,0x27428a5, + 0x0e7eac8,0x351ef04,0x259ce34,0x02a8e98 } }, + /* 50 */ + { { 0x2f3dcd3,0x3e77d4d,0x3360fbc,0x1434afd,0x36ceded,0x3d413d6, + 0x1710fad,0x36bb924,0x1627e79,0x008e637 }, + { 0x109569e,0x1c168db,0x3769cf4,0x2ed4527,0x0ea0619,0x17d80d3, + 0x1c03773,0x18843fe,0x1b21c04,0x015c5fd } }, + /* 51 */ + { { 0x1dd895e,0x08a7248,0x04519fe,0x001030a,0x18e5185,0x358dfb3, + 0x13d2391,0x0a37be8,0x0560e3c,0x019828b }, + { 0x27fcbd0,0x2a22bb5,0x30969cc,0x1e03aa7,0x1c84724,0x0ba4ad3, + 0x32f4817,0x0914cca,0x14c4f52,0x01893b9 } }, + /* 52 */ + { { 0x097eccc,0x1273936,0x00aa095,0x364fe62,0x04d49d1,0x10e9f08, + 0x3c24230,0x3ef01c8,0x2fb92bd,0x013ce4a }, + { 0x1e44fd9,0x27e3e9f,0x2156696,0x3915ecc,0x0b66cfb,0x1a3af0f, + 0x2fa8033,0x0e6736c,0x177ccdb,0x0228f9e } }, + /* 53 */ + { { 0x2c4b125,0x06207c1,0x0a8cdde,0x003db8f,0x1ae34e3,0x31e84fa, + 0x2999de5,0x11013bd,0x02370c2,0x00e2234 }, + { 0x0f91081,0x200d591,0x1504762,0x1857c05,0x23d9fcf,0x0cb34db, + 0x27edc86,0x08cd860,0x2471810,0x029798b } }, + /* 54 */ + { { 0x3acd6c8,0x097b8cb,0x3c661a8,0x15152f2,0x1699c63,0x237e64c, + 0x23edf79,0x16b7033,0x0e6466a,0x00b11da }, + { 0x0a64bc9,0x1bfe324,0x1f5cb34,0x08391de,0x0630a60,0x3017a21, + 0x09d064b,0x14a8365,0x041f9e6,0x01ed799 } }, + /* 55 */ + { { 0x128444a,0x2508b07,0x2a39216,0x362f84d,0x2e996c5,0x2c31ff3, + 0x07afe5f,0x1d1288e,0x3cb0c8d,0x02e2bdc }, + { 0x38b86fd,0x3a0ea8c,0x1cff5fd,0x1629629,0x3fee3f1,0x02b250c, + 0x2e8f6f2,0x0225727,0x15f7f3f,0x0280d8e } }, + /* 56 */ + { { 0x10f7770,0x0f1aee8,0x0e248c7,0x20684a8,0x3a6f16d,0x06f0ae7, + 0x0df6825,0x2d4cc40,0x301875f,0x012f8da }, + { 0x3b56dbb,0x1821ba7,0x24f8922,0x22c1f9e,0x0306fef,0x1b54bc8, + 0x2ccc056,0x00303ba,0x2871bdc,0x0232f26 } }, + /* 57 */ + { { 0x0dac4ab,0x0625730,0x3112e13,0x101c4bf,0x3a874a4,0x2873b95, + 0x32ae7c6,0x0d7e18c,0x13e0c08,0x01139d5 }, + { 0x334002d,0x00fffdd,0x025c6d5,0x22c2cd1,0x19d35cb,0x3a1ce2d, + 0x3702760,0x3f06257,0x03a5eb8,0x011c29a } }, + /* 58 */ + { { 0x0513482,0x1d87724,0x276a81b,0x0a807a4,0x3028720,0x339cc20, + 0x2441ee0,0x31bbf36,0x290c63d,0x0059041 }, + { 0x106a2ed,0x0d2819b,0x100bf50,0x114626c,0x1dd4d77,0x2e08632, + 0x14ae72a,0x2ed3f64,0x1fd7abc,0x035cd1e } }, + /* 59 */ + { { 0x2d4c6e5,0x3bec596,0x104d7ed,0x23d6c1b,0x0262cf0,0x15d72c5, + 0x2d5bb18,0x199ac4b,0x1e30771,0x020591a }, + { 0x21e291e,0x2e75e55,0x1661d7a,0x08b0778,0x3eb9daf,0x0d78144, + 0x1827eb1,0x0fe73d2,0x123f0dd,0x0028db7 } }, + /* 60 */ + { { 0x1d5533c,0x34cb1d0,0x228f098,0x27a1a11,0x17c5f5a,0x0d26f44, + 0x2228ade,0x2c460e6,0x3d6fdba,0x038cc77 }, + { 0x3cc6ed8,0x02ada1a,0x260e510,0x2f7bde8,0x37160c3,0x33a1435, + 0x23d9a7b,0x0ce2641,0x02a492e,0x034ed1e } }, + /* 61 */ + { { 0x3821f90,0x26dba3c,0x3aada14,0x3b59bad,0x292edd9,0x2804c45, + 0x3669531,0x296f42e,0x35a4c86,0x01ca049 }, + { 0x3ff47e5,0x2163df4,0x2441503,0x2f18405,0x15e1616,0x37f66ec, + 0x30f11a7,0x141658a,0x27ece14,0x00b018b } }, + /* 62 */ + { { 0x159ac2e,0x3e65bc0,0x2713a76,0x0db2f6c,0x3281e77,0x2391811, + 0x16d2880,0x1fbc4ab,0x1f92c4e,0x00a0a8d }, + { 0x0ce5cd2,0x152c7b0,0x02299c3,0x3244de7,0x2cf99ef,0x3a0b047, + 0x2caf383,0x0aaf664,0x113554d,0x031c735 } }, + /* 63 */ + { { 0x1b578f4,0x177a702,0x3a7a488,0x1638ebf,0x31884e2,0x2460bc7, + 0x36b1b75,0x3ce8e3d,0x340cf47,0x03143d9 }, + { 0x34b68ea,0x12b7ccd,0x1fe2a9c,0x08da659,0x0a406f3,0x1694c14, + 0x06a2228,0x16370be,0x3a72129,0x02e7b2c } }, + /* 64 */ + { { 0x0f8b16a,0x21043bd,0x266a56f,0x3fb11ec,0x197241a,0x36721f0, + 0x006b8e6,0x2ac6c29,0x202cd42,0x0200fcf }, + { 0x0dbec69,0x0c26a01,0x105f7f0,0x3dceeeb,0x3a83b85,0x363865f, + 0x097273a,0x2b70718,0x00e5067,0x03025d1 } }, + /* 65 */ + { { 0x379ab34,0x295bcb0,0x38d1846,0x22e1077,0x3a8ee06,0x1db1a3b, + 0x3144591,0x07cc080,0x2d5915f,0x03c6bcc }, + { 0x175bd50,0x0dd4c57,0x27bc99c,0x2ebdcbd,0x3837cff,0x235dc8f, + 0x13a4184,0x0722c18,0x130e2d4,0x008f43c } }, + /* 66 */ + { { 0x01500d9,0x2adbb7d,0x2da8857,0x397f2fa,0x10d890a,0x25c9654, + 0x3e86488,0x3eb754b,0x1d6c0a3,0x02c0a23 }, + { 0x10bcb08,0x083cc19,0x2e16853,0x04da575,0x271af63,0x2626a9d, + 0x3520a7b,0x32348c7,0x24ff408,0x03ff4dc } }, + /* 67 */ + { { 0x058e6cb,0x1a3992d,0x1d28539,0x080c5e9,0x2992dad,0x2a9d7d5, + 0x14ae0b7,0x09b7ce0,0x34ad78c,0x03d5643 }, + { 0x30ba55a,0x092f4f3,0x0bae0fc,0x12831de,0x20fc472,0x20ed9d2, + 0x29864f6,0x1288073,0x254f6f7,0x00635b6 } }, + /* 68 */ + { { 0x1be5a2b,0x0f88975,0x33c6ed9,0x20d64d3,0x06fe799,0x0989bff, + 0x1409262,0x085a90c,0x0d97990,0x0142eed }, + { 0x17ec63e,0x06471b9,0x0db2378,0x1006077,0x265422c,0x08db83d, + 0x28099b0,0x1270d06,0x11801fe,0x00ac400 } }, + /* 69 */ + { { 0x3391593,0x22d7166,0x30fcfc6,0x2896609,0x3c385f5,0x066b72e, + 0x04f3aad,0x2b831c5,0x19983fb,0x0375562 }, + { 0x0b82ff4,0x222e39d,0x34c993b,0x101c79c,0x2d2e03c,0x0f00c8a, + 0x3a9eaf4,0x1810669,0x151149d,0x039b931 } }, + /* 70 */ + { { 0x29af288,0x1956ec7,0x293155f,0x193deb6,0x1647e1a,0x2ca0839, + 0x297e4bc,0x15bfd0d,0x1b107ed,0x0147803 }, + { 0x31c327e,0x05a6e1d,0x02ad43d,0x02d2a5b,0x129cdb2,0x37ad1de, + 0x3d51f53,0x245df01,0x2414982,0x0388bd0 } }, + /* 71 */ + { { 0x35f1abb,0x17a3d18,0x0874cd4,0x2d5a14e,0x17edc0c,0x16a00d3, + 0x072c1fb,0x1232725,0x33d52dc,0x03dc24d }, + { 0x0af30d6,0x259aeea,0x369c401,0x12bc4de,0x295bf5f,0x0d8711f, + 0x26162a9,0x16c44e5,0x288e727,0x02f54b4 } }, + /* 72 */ + { { 0x05fa877,0x1571ea7,0x3d48ab1,0x1c9f4e8,0x017dad6,0x0f46276, + 0x343f9e7,0x1de990f,0x0e4c8aa,0x028343e }, + { 0x094f92d,0x3abf633,0x1b3a0bb,0x2f83137,0x0d818c8,0x20bae85, + 0x0c65f8b,0x1a8008b,0x0c7946d,0x0295b1e } }, + /* 73 */ + { { 0x1d09529,0x08e46c3,0x1fcf296,0x298f6b7,0x1803e0e,0x2d6fd20, + 0x37351f5,0x0d9e8b1,0x1f8731a,0x0362fbf }, + { 0x00157f4,0x06750bf,0x2650ab9,0x35ffb23,0x2f51cae,0x0b522c2, + 0x39cb400,0x191e337,0x0a5ce9f,0x021529a } }, + /* 74 */ + { { 0x3506ea5,0x17d9ed8,0x0d66dc3,0x22693f8,0x19286c4,0x3a57353, + 0x101d3bf,0x1aa54fc,0x20b9884,0x0172b3a }, + { 0x0eac44d,0x37d8327,0x1c3aa90,0x3d0d534,0x23db29a,0x3576eaf, + 0x1d3de8a,0x3bea423,0x11235e4,0x039260b } }, + /* 75 */ + { { 0x34cd55e,0x01288b0,0x1132231,0x2cc9a03,0x358695b,0x3e87650, + 0x345afa1,0x01267ec,0x3f616b2,0x02011ad }, + { 0x0e7d098,0x0d6078e,0x0b70b53,0x237d1bc,0x0d7f61e,0x132de31, + 0x1ea9ea4,0x2bd54c3,0x27b9082,0x03ac5f2 } }, + /* 76 */ + { { 0x2a145b9,0x06d661d,0x31ec175,0x03f06f1,0x3a5cf6b,0x249c56e, + 0x2035653,0x384c74f,0x0bafab5,0x0025ec0 }, + { 0x25f69e1,0x1b23a55,0x1199aa6,0x16ad6f9,0x077e8f7,0x293f661, + 0x33ba11d,0x3327980,0x07bafdb,0x03e571d } }, + /* 77 */ + { { 0x2bae45e,0x3c074ef,0x2955558,0x3c312f1,0x2a8ebe9,0x2f193f1, + 0x3705b1d,0x360deba,0x01e566e,0x00d4498 }, + { 0x21161cd,0x1bc787e,0x2f87933,0x3553197,0x1328ab8,0x093c879, + 0x17eee27,0x2adad1d,0x1236068,0x003be5c } }, + /* 78 */ + { { 0x0ca4226,0x2633dd5,0x2c8e025,0x0e3e190,0x05eede1,0x1a385e4, + 0x163f744,0x2f25522,0x1333b4f,0x03f05b6 }, + { 0x3c800ca,0x1becc79,0x2daabe9,0x0c499e2,0x1138063,0x3fcfa2d, + 0x2244976,0x1e85cf5,0x2f1b95d,0x0053292 } }, + /* 79 */ + { { 0x12f81d5,0x1dc6eaf,0x11967a4,0x1a407df,0x31a5f9d,0x2b67241, + 0x18bef7c,0x08c7762,0x063f59c,0x01015ec }, + { 0x1c05c0a,0x360bfa2,0x1f85bff,0x1bc7703,0x3e4911c,0x0d685b6, + 0x2fccaea,0x02c4cef,0x164f133,0x0070ed7 } }, + /* 80 */ + { { 0x0ec21fe,0x052ffa0,0x3e825fe,0x1ab0956,0x3f6ce11,0x3d29759, + 0x3c5a072,0x18ebe62,0x148db7e,0x03eb49c }, + { 0x1ab05b3,0x02dab0a,0x1ae690c,0x0f13894,0x137a9a8,0x0aab79f, + 0x3dc875c,0x06a1029,0x1e39f0e,0x01dce1f } }, + /* 81 */ + { { 0x16c0dd7,0x3b31269,0x2c741e9,0x3611821,0x2a5cffc,0x1416bb3, + 0x3a1408f,0x311fa3d,0x1c0bef0,0x02cdee1 }, + { 0x00e6a8f,0x1adb933,0x0f23359,0x2fdace2,0x2fd6d4b,0x0e73bd3, + 0x2453fac,0x0a356ae,0x2c8f9f6,0x02704d6 } }, + /* 82 */ + { { 0x0e35743,0x28c80a1,0x0def32a,0x2c6168f,0x1320d6a,0x37c6606, + 0x21b1761,0x2147ee0,0x21fc433,0x015c84d }, + { 0x1fc9168,0x36cda9c,0x003c1f0,0x1cd7971,0x15f98ba,0x1ef363d, + 0x0ca87e3,0x046f7d9,0x3c9e6bb,0x0372eb0 } }, + /* 83 */ + { { 0x118cbe2,0x3665a11,0x304ef01,0x062727a,0x3d242fc,0x11ffbaf, + 0x3663c7e,0x1a189c9,0x09e2d62,0x02e3072 }, + { 0x0e1d569,0x162f772,0x0cd051a,0x322df62,0x3563809,0x047cc7a, + 0x027fd9f,0x08b509b,0x3da2f94,0x01748ee } }, + /* 84 */ + { { 0x1c8f8be,0x31ca525,0x22bf0a1,0x200efcd,0x02961c4,0x3d8f52b, + 0x018403d,0x3a40279,0x1cb91ec,0x030427e }, + { 0x0945705,0x0257416,0x05c0c2d,0x25b77ae,0x3b9083d,0x2901126, + 0x292b8d7,0x07b8611,0x04f2eee,0x026f0cd } }, + /* 85 */ + { { 0x2913074,0x2b8d590,0x02b10d5,0x09d2295,0x255491b,0x0c41cca, + 0x1ca665b,0x133051a,0x1525f1a,0x00a5647 }, + { 0x04f983f,0x3d6daee,0x04e1e76,0x1067d7e,0x1be7eef,0x02ea862, + 0x00d4968,0x0ccb048,0x11f18ef,0x018dd95 } }, + /* 86 */ + { { 0x22976cc,0x17c5395,0x2c38bda,0x3983bc4,0x222bca3,0x332a614, + 0x3a30646,0x261eaef,0x1c808e2,0x02f6de7 }, + { 0x306a772,0x32d7272,0x2dcefd2,0x2abf94d,0x038f475,0x30ad76e, + 0x23e0227,0x3052b0a,0x001add3,0x023ba18 } }, + /* 87 */ + { { 0x0ade873,0x25a6069,0x248ccbe,0x13713ee,0x17ee9aa,0x28152e9, + 0x2e28995,0x2a92cb3,0x17a6f77,0x024b947 }, + { 0x190a34d,0x2ebea1c,0x1ed1948,0x16fdaf4,0x0d698f7,0x32bc451, + 0x0ee6e30,0x2aaab40,0x06f0a56,0x01460be } }, + /* 88 */ + { { 0x24cc99c,0x1884b1e,0x1ca1fba,0x1a0f9b6,0x2ff609b,0x2b26316, + 0x3b27cb5,0x29bc976,0x35d4073,0x024772a }, + { 0x3575a70,0x1b30f57,0x07fa01b,0x0e5be36,0x20cb361,0x26605cd, + 0x1d4e8c8,0x13cac59,0x2db9797,0x005e833 } }, + /* 89 */ + { { 0x36c8d3a,0x1878a81,0x124b388,0x0e4843e,0x1701aad,0x0ea0d76, + 0x10eae41,0x37d0653,0x36c7f4c,0x00ba338 }, + { 0x37a862b,0x1cf6ac0,0x08fa912,0x2dd8393,0x101ba9b,0x0eebcb7, + 0x2453883,0x1a3cfe5,0x2cb34f6,0x03d3331 } }, + /* 90 */ + { { 0x1f79687,0x3d4973c,0x281544e,0x2564bbe,0x17c5954,0x171e34a, + 0x231741a,0x3cf2784,0x0889a0d,0x02b036d }, + { 0x301747f,0x3f1c477,0x1f1386b,0x163bc5f,0x1592b93,0x332daed, + 0x080e4f5,0x1d28b96,0x26194c9,0x0256992 } }, + /* 91 */ + { { 0x15a4c93,0x07bf6b0,0x114172c,0x1ce0961,0x140269b,0x1b2c2eb, + 0x0dfb1c1,0x019ddaa,0x0ba2921,0x008c795 }, + { 0x2e6d2dc,0x37e45e2,0x2918a70,0x0fce444,0x34d6aa6,0x396dc88, + 0x27726b5,0x0c787d8,0x032d8a7,0x02ac2f8 } }, + /* 92 */ + { { 0x1131f2d,0x2b43a63,0x3101097,0x38cec13,0x0637f09,0x17a69d2, + 0x086196d,0x299e46b,0x0802cf6,0x03c6f32 }, + { 0x0daacb4,0x1a4503a,0x100925c,0x15583d9,0x23c4e40,0x1de4de9, + 0x1cc8fc4,0x2c9c564,0x0695aeb,0x02145a5 } }, + /* 93 */ + { { 0x1dcf593,0x17050fc,0x3e3bde3,0x0a6c062,0x178202b,0x2f7674f, + 0x0dadc29,0x15763a7,0x1d2daad,0x023d9f6 }, + { 0x081ea5f,0x045959d,0x190c841,0x3a78d31,0x0e7d2dd,0x1414fea, + 0x1d43f40,0x22d77ff,0x2b9c072,0x03e115c } }, + /* 94 */ + { { 0x3af71c9,0x29e9c65,0x25655e1,0x111e9cd,0x3a14494,0x3875418, + 0x34ae070,0x0b06686,0x310616b,0x03b7b89 }, + { 0x1734121,0x00d3d44,0x29f0b2f,0x1552897,0x31cac6e,0x1030bb3, + 0x0148f3a,0x35fd237,0x29b44eb,0x027f49f } }, + /* 95 */ + { { 0x2e2cb16,0x1d962bd,0x19b63cc,0x0b3f964,0x3e3eb7d,0x1a35560, + 0x0c58161,0x3ce1d6a,0x3b6958f,0x029030b }, + { 0x2dcc158,0x3b1583f,0x30568c9,0x31957c8,0x27ad804,0x28c1f84, + 0x3967049,0x37b3f64,0x3b87dc6,0x0266f26 } }, + /* 96 */ + { { 0x27dafc6,0x2548764,0x0d1984a,0x1a57027,0x252c1fb,0x24d9b77, + 0x1581a0f,0x1f99276,0x10ba16d,0x026af88 }, + { 0x0915220,0x2be1292,0x16c6480,0x1a93760,0x2fa7317,0x1a07296, + 0x1539871,0x112c31f,0x25787f3,0x01e2070 } }, + /* 97 */ + { { 0x0bcf3ff,0x266d478,0x34f6933,0x31449fd,0x00d02cb,0x340765a, + 0x3465a2d,0x225023e,0x319a30e,0x00579b8 }, + { 0x20e05f4,0x35b834f,0x0404646,0x3710d62,0x3fad7bd,0x13e1434, + 0x21c7d1c,0x1cb3af9,0x2cf1911,0x003957e } }, + /* 98 */ + { { 0x0787564,0x36601be,0x1ce67e9,0x084c7a1,0x21a3317,0x2067a35, + 0x0158cab,0x195ddac,0x1766fe9,0x035cf42 }, + { 0x2b7206e,0x20d0947,0x3b42424,0x03f1862,0x0a51929,0x38c2948, + 0x0bb8595,0x2942d77,0x3748f15,0x0249428 } }, + /* 99 */ + { { 0x2577410,0x3c23e2f,0x28c6caf,0x00d41de,0x0fd408a,0x30298e9, + 0x363289e,0x2302fc7,0x082c1cc,0x01dd050 }, + { 0x30991cd,0x103e9ba,0x029605a,0x19927f7,0x0c1ca08,0x0c93f50, + 0x28a3c7b,0x082e4e9,0x34d12eb,0x0232c13 } }, + /* 100 */ + { { 0x106171c,0x0b4155a,0x0c3fb1c,0x336c090,0x19073e9,0x2241a10, + 0x0e6b4fd,0x0ed476e,0x1ef4712,0x039390a }, + { 0x0ec36f4,0x3754f0e,0x2a270b8,0x007fd2d,0x0f9d2dc,0x1e6a692, + 0x066e078,0x1954974,0x2ff3c6e,0x00def28 } }, + /* 101 */ + { { 0x3562470,0x0b8f1f7,0x0ac94cd,0x28b0259,0x244f272,0x031e4ef, + 0x2d5df98,0x2c8a9f1,0x2dc3002,0x016644f }, + { 0x350592a,0x0e6a0d5,0x1e027a1,0x2039e0f,0x399e01d,0x2817593, + 0x0c0375e,0x3889b3e,0x24ab013,0x010de1b } }, + /* 102 */ + { { 0x256b5a6,0x0ac3b67,0x28f9ff3,0x29b67f1,0x30750d9,0x25e11a9, + 0x15e8455,0x279ebb0,0x298b7e7,0x0218e32 }, + { 0x2fc24b2,0x2b82582,0x28f22f5,0x2bd36b3,0x305398e,0x3b2e9e3, + 0x365dd0a,0x29bc0ed,0x36a7b3a,0x007b374 } }, + /* 103 */ + { { 0x05ff2f3,0x2b3589b,0x29785d3,0x300a1ce,0x0a2d516,0x0844355, + 0x14c9fad,0x3ccb6b6,0x385d459,0x0361743 }, + { 0x0b11da3,0x002e344,0x18c49f7,0x0c29e0c,0x1d2c22c,0x08237b3, + 0x2988f49,0x0f18955,0x1c3b4ed,0x02813c6 } }, + /* 104 */ + { { 0x17f93bd,0x249323b,0x11f6087,0x174e4bd,0x3cb64ac,0x086dc6b, + 0x2e330a8,0x142c1f2,0x2ea5c09,0x024acbb }, + { 0x1b6e235,0x3132521,0x00f085a,0x2a4a4db,0x1ab2ca4,0x0142224, + 0x3aa6b3e,0x09db203,0x2215834,0x007b9e0 } }, + /* 105 */ + { { 0x23e79f7,0x28b8039,0x1906a60,0x2cbce67,0x1f590e7,0x181f027, + 0x21054a6,0x3854240,0x2d857a6,0x03cfcb3 }, + { 0x10d9b55,0x1443cfc,0x2648200,0x2b36190,0x09d2fcf,0x22f439f, + 0x231aa7e,0x3884395,0x0543da3,0x003d5a9 } }, + /* 106 */ + { { 0x043e0df,0x06ffe84,0x3e6d5b2,0x3327001,0x26c74b6,0x12a145e, + 0x256ec0d,0x3898c69,0x3411969,0x02f63c5 }, + { 0x2b7494a,0x2eee1af,0x38388a9,0x1bd17ce,0x21567d4,0x13969e6, + 0x3a12a7a,0x3e8277d,0x03530cc,0x00b4687 } }, + /* 107 */ + { { 0x06508da,0x38e04d4,0x15a7192,0x312875e,0x3336180,0x2a6512c, + 0x1b59497,0x2e91b37,0x25eb91f,0x02841e9 }, + { 0x394d639,0x0747143,0x37d7e6d,0x1d62962,0x08b4af3,0x34df287, + 0x3c5584b,0x26bc869,0x20af87a,0x0060f5d } }, + /* 108 */ + { { 0x1de59a4,0x1a5c443,0x2f8729d,0x01c3a2f,0x0f1ad8d,0x3cbaf9e, + 0x1b49634,0x35d508a,0x39dc269,0x0075105 }, + { 0x390d30e,0x37033e0,0x110cb32,0x14c37a0,0x20a3b27,0x2f00ce6, + 0x2f1dc52,0x34988c6,0x0c29606,0x01dc7e7 } }, + /* 109 */ + { { 0x1040739,0x24f9de1,0x2939999,0x2e6009a,0x244539d,0x17e3f09, + 0x00f6f2f,0x1c63b3d,0x2310362,0x019109e }, + { 0x1428aa8,0x3cb61e1,0x09a84f4,0x0ffafed,0x07b7adc,0x08f406b, + 0x1b2c6df,0x035b480,0x3496ae9,0x012766d } }, + /* 110 */ + { { 0x35d1099,0x2362f10,0x1a08cc7,0x13a3a34,0x12adbcd,0x32da290, + 0x02e2a02,0x151140b,0x01b3f60,0x0240df6 }, + { 0x34c7b61,0x2eb09c1,0x172e7cd,0x2ad5eff,0x2fe2031,0x25b54d4, + 0x0cec965,0x18e7187,0x26a7cc0,0x00230f7 } }, + /* 111 */ + { { 0x2d552ab,0x374083d,0x01f120f,0x2601736,0x156baff,0x04d44a4, + 0x3b7c3e9,0x1acbc1b,0x0424579,0x031a425 }, + { 0x1231bd1,0x0eba710,0x020517b,0x21d7316,0x21eac6e,0x275a848, + 0x0837abf,0x0eb0082,0x302cafe,0x00fe8f6 } }, + /* 112 */ + { { 0x1058880,0x28f9941,0x03f2d75,0x3bd90e5,0x17da365,0x2ac9249, + 0x07861cf,0x023fd05,0x1b0fdb8,0x031712f }, + { 0x272b56b,0x04f8d2c,0x043a735,0x25446e4,0x1c8327e,0x221125a, + 0x0ce37df,0x2dad7f6,0x39446c2,0x00b55b6 } }, + /* 113 */ + { { 0x346ac6b,0x05e0bff,0x2425246,0x0981e8b,0x1d19f79,0x2692378, + 0x3ea3c40,0x2e90beb,0x19de503,0x003d5af }, + { 0x05cda49,0x353b44d,0x299d137,0x3f205bc,0x2821158,0x3ad0d00, + 0x06a54aa,0x2d7c79f,0x39d1173,0x01000ee } }, + /* 114 */ + { { 0x0803387,0x3a06268,0x14043b8,0x3d4e72f,0x1ece115,0x0a1dfc8, + 0x17208dd,0x0be790a,0x122a07f,0x014dd95 }, + { 0x0a4182d,0x202886a,0x1f79a49,0x1e8c867,0x0a2bbd0,0x28668b5, + 0x0d0a2e1,0x115259d,0x3586c5d,0x01e815b } }, + /* 115 */ + { { 0x18a2a47,0x2c95627,0x2773646,0x1230f7c,0x15b5829,0x2fc354e, + 0x2c000ea,0x099d547,0x2f17a1a,0x01df520 }, + { 0x3853948,0x06f6561,0x3feeb8a,0x2f5b3ef,0x3a6f817,0x01a0791, + 0x2ec0578,0x2c392ad,0x12b2b38,0x0104540 } }, + /* 116 */ + { { 0x1e28ced,0x0fc3d1b,0x2c473c7,0x1826c4f,0x21d5da7,0x39718e4, + 0x38ce9e6,0x0251986,0x172fbea,0x0337c11 }, + { 0x053c3b0,0x0f162db,0x043c1cb,0x04111ee,0x297fe3c,0x32e5e03, + 0x2b8ae12,0x0c427ec,0x1da9738,0x03b9c0f } }, + /* 117 */ + { { 0x357e43a,0x054503f,0x11b8345,0x34ec6e0,0x2d44660,0x3d0ae61, + 0x3b5dff8,0x33884ac,0x09da162,0x00a82b6 }, + { 0x3c277ba,0x129a51a,0x027664e,0x1530507,0x0c788c9,0x2afd89d, + 0x1aa64cc,0x1196450,0x367ac2b,0x0358b42 } }, + /* 118 */ + { { 0x0054ac4,0x1761ecb,0x378839c,0x167c9f7,0x2570058,0x0604a35, + 0x37cbf3b,0x0909bb7,0x3f2991c,0x02ce688 }, + { 0x0b16ae5,0x212857c,0x351b952,0x2c684db,0x30c6a05,0x09c01e0, + 0x23c137f,0x1331475,0x092c067,0x0013b40 } }, + /* 119 */ + { { 0x2e90393,0x0617466,0x24e61f4,0x0a528f5,0x03047b4,0x2153f05, + 0x0001a69,0x30e1eb8,0x3c10177,0x0282a47 }, + { 0x22c831e,0x28fc06b,0x3e16ff0,0x208adc9,0x0bb76ae,0x28c1d6d, + 0x12c8a15,0x031063c,0x1889ed2,0x002133e } }, + /* 120 */ + { { 0x0a6becf,0x14277bf,0x3328d98,0x201f7fe,0x12fceae,0x1de3a2e, + 0x0a15c44,0x3ddf976,0x1b273ab,0x0355e55 }, + { 0x1b5d4f1,0x369e78c,0x3a1c210,0x12cf3e9,0x3aa52f0,0x309f082, + 0x112089d,0x107c753,0x24202d1,0x023853a } }, + /* 121 */ + { { 0x2897042,0x140d17c,0x2c4aeed,0x07d0d00,0x18d0533,0x22f7ec8, + 0x19c194c,0x3456323,0x2372aa4,0x0165f86 }, + { 0x30bd68c,0x1fb06b3,0x0945032,0x372ac09,0x06d4be0,0x27f8fa1, + 0x1c8d7ac,0x137a96e,0x236199b,0x0328fc0 } }, + /* 122 */ + { { 0x170bd20,0x2842d58,0x1de7592,0x3c5b4fd,0x20ea897,0x12cab78, + 0x363ff14,0x01f928c,0x17e309c,0x02f79ff }, + { 0x0f5432c,0x2edb4ae,0x044b516,0x32f810d,0x2210dc1,0x23e56d6, + 0x301e6ff,0x34660f6,0x10e0a7d,0x02d88eb } }, + /* 123 */ + { { 0x0c7b65b,0x2f59d58,0x2289a75,0x2408e92,0x1ab8c55,0x1ec99e5, + 0x220fd0d,0x04defe0,0x24658ec,0x035aa8b }, + { 0x138bb85,0x2f002d4,0x295c10a,0x08760ce,0x28c31d1,0x1c0a8cb, + 0x0ff00b1,0x144eac9,0x2e02dcc,0x0044598 } }, + /* 124 */ + { { 0x3b42b87,0x050057b,0x0dff781,0x1c06db1,0x1bd9f5d,0x1f5f04a, + 0x2cccd7a,0x143e19b,0x1cb94b7,0x036cfb8 }, + { 0x34837cf,0x3cf6c3c,0x0d4fb26,0x22ee55e,0x1e7eed1,0x315995f, + 0x2cdf937,0x1a96574,0x0425220,0x0221a99 } }, + /* 125 */ + { { 0x1b569ea,0x0d33ed9,0x19c13c2,0x107dc84,0x2200111,0x0569867, + 0x2dc85da,0x05ef22e,0x0eb018a,0x029c33d }, + { 0x04a6a65,0x3e5eba3,0x378f224,0x09c04d0,0x036e5cf,0x3df8258, + 0x3a609e4,0x1eddef8,0x2abd174,0x02a91dc } }, + /* 126 */ + { { 0x2a60cc0,0x1d84c5e,0x115f676,0x1840da0,0x2c79163,0x2f06ed6, + 0x198bb4b,0x3e5d37b,0x1dc30fa,0x018469b }, + { 0x15ee47a,0x1e32f30,0x16a530e,0x2093836,0x02e8962,0x3767b62, + 0x335adf3,0x27220db,0x2f81642,0x0173ffe } }, + /* 127 */ + { { 0x37a99cd,0x1533fe6,0x05a1c0d,0x27610f1,0x17bf3b9,0x0b1ce78, + 0x0a908f6,0x265300e,0x3237dc1,0x01b969a }, + { 0x3a5db77,0x2d15382,0x0d63ef8,0x1feb3d8,0x0b7b880,0x19820de, + 0x11c0c67,0x2af3396,0x38d242d,0x0120688 } }, + /* 128 */ + { { 0x1d0b34a,0x05ef00d,0x00a7e34,0x1ae0c9f,0x1440b38,0x300d8b4, + 0x37262da,0x3e50e3e,0x14ce0cd,0x00b1044 }, + { 0x195a0b1,0x173bc6b,0x03622ba,0x2a19f55,0x1c09b37,0x07921b2, + 0x16cdd20,0x24a5c9b,0x2bf42ff,0x00811de } }, + /* 129 */ + { { 0x0d65dbf,0x145cf06,0x1ad82f7,0x038ce7b,0x077bf94,0x33c4007, + 0x22d26bd,0x25ad9c0,0x09ac773,0x02b1990 }, + { 0x2261cc3,0x2ecdbf1,0x3e908b0,0x3246439,0x0213f7b,0x1179b04, + 0x01cebaa,0x0be1595,0x175cc12,0x033a39a } }, + /* 130 */ + { { 0x00a67d2,0x086d06f,0x248a0f1,0x0291134,0x362d476,0x166d1cd, + 0x044f1d6,0x2d2a038,0x365250b,0x0023f78 }, + { 0x08bf287,0x3b0f6a1,0x1d6eace,0x20b4cda,0x2c2a621,0x0912520, + 0x02dfdc9,0x1b35cd6,0x3d2565d,0x00bdf8b } }, + /* 131 */ + { { 0x3770fa7,0x2e4b6f0,0x03f9ae4,0x170de41,0x1095e8d,0x1dd845c, + 0x334e9d1,0x00ab953,0x12e9077,0x03196fa }, + { 0x2fd0a40,0x228c0fd,0x384b275,0x38ef339,0x3e7d822,0x3e5d9ef, + 0x24f5854,0x0ece9eb,0x247d119,0x012ffe3 } }, + /* 132 */ + { { 0x0ff1480,0x07487c0,0x1b16cd4,0x1f41d53,0x22ab8fb,0x2f83cfa, + 0x01d2efb,0x259f6b2,0x2e65772,0x00f9392 }, + { 0x05303e6,0x23cdb4f,0x23977e1,0x12e4898,0x03bd999,0x0c930f0, + 0x170e261,0x180a27b,0x2fd58ec,0x014e22b } }, + /* 133 */ + { { 0x25d7713,0x0c5fad7,0x09daad1,0x3b9d779,0x109b985,0x1d3ec98, + 0x35bc4fc,0x2f838cb,0x0d14f75,0x0173e42 }, + { 0x2657b12,0x10d4423,0x19e6760,0x296e5bb,0x2bfd421,0x25c3330, + 0x29f51f8,0x0338838,0x24060f0,0x029a62e } }, + /* 134 */ + { { 0x3748fec,0x2c5a1bb,0x2cf973d,0x289fa74,0x3e6e755,0x38997bf, + 0x0b6544c,0x2b6358c,0x38a7aeb,0x02c50bb }, + { 0x3d5770a,0x06be7c5,0x012fad3,0x19cb2cd,0x266af3b,0x3ccd677, + 0x160d1bd,0x141d5af,0x2965851,0x034625a } }, + /* 135 */ + { { 0x3c41c08,0x255eacc,0x22e1ec5,0x2b151a3,0x087de94,0x311cbdb, + 0x016b73a,0x368e462,0x20b7981,0x0099ec3 }, + { 0x262b988,0x1539763,0x21e76e5,0x15445b4,0x1d8ddc7,0x34a9be6, + 0x10faf03,0x24e4d18,0x07aa111,0x02d538a } }, + /* 136 */ + { { 0x38a876b,0x048ad45,0x04b40a0,0x3fc2144,0x251ff96,0x13ca7dd, + 0x0b31ab1,0x3539814,0x28b5f87,0x0212aec }, + { 0x270790a,0x350e7e0,0x346bd5e,0x276178f,0x22d6cb5,0x3078884, + 0x355c1b6,0x15901d7,0x3671765,0x03950db } }, + /* 137 */ + { { 0x286e8d5,0x2409788,0x13be53f,0x2d21911,0x0353c95,0x10238e8, + 0x32f5bde,0x3a67b60,0x28b5b9c,0x001013d }, + { 0x381e8e5,0x0cef7a9,0x2f5bcad,0x06058f0,0x33cdf50,0x04672a8, + 0x1769600,0x31c055d,0x3df0ac1,0x00e9098 } }, + /* 138 */ + { { 0x2eb596d,0x197b326,0x12b4c29,0x39c08f2,0x101ea03,0x3804e58, + 0x04b4b62,0x28d9d1c,0x13f905e,0x0032a3f }, + { 0x11b2b61,0x08e9095,0x0d06925,0x270e43f,0x21eb7a8,0x0e4a98f, + 0x31d2be0,0x030cf9f,0x2644ddb,0x025b728 } }, + /* 139 */ + { { 0x07510af,0x2ed0e8e,0x2a01203,0x2a2a68d,0x0846fea,0x3e540de, + 0x3a57702,0x1677348,0x2123aad,0x010d8f8 }, + { 0x0246a47,0x0e871d0,0x124dca4,0x34b9577,0x2b362b8,0x363ebe5, + 0x3086045,0x26313e6,0x15cd8bb,0x0210384 } }, + /* 140 */ + { { 0x023e8a7,0x0817884,0x3a0bf12,0x3376371,0x3c808a8,0x18e9777, + 0x12a2721,0x35b538a,0x2bd30de,0x017835a }, + { 0x0fc0f64,0x1c8709f,0x2d8807a,0x0743957,0x242eec0,0x347e76c, + 0x27bef91,0x289689a,0x0f42945,0x01f7a92 } }, + /* 141 */ + { { 0x1060a81,0x3dbc739,0x1615abd,0x1cbe3e5,0x3e79f9c,0x1ab09a2, + 0x136c540,0x05b473f,0x2beebfd,0x02af0a8 }, + { 0x3e2eac7,0x19be474,0x04668ac,0x18f4b74,0x36f10ba,0x0a0b4c6, + 0x10e3770,0x3bf059e,0x3946c7e,0x013a8d4 } }, + /* 142 */ + { { 0x266309d,0x28be354,0x1a3eed8,0x3020651,0x10a51c6,0x1e31770, + 0x0af45a5,0x3ff0f3b,0x2891c94,0x00e9db9 }, + { 0x17b0d0f,0x33a291f,0x0a5f9aa,0x25a3d61,0x2963ace,0x39a5fef, + 0x230c724,0x1919146,0x10a465e,0x02084a8 } }, + /* 143 */ + { { 0x3ab8caa,0x31870f3,0x2390ef7,0x2103850,0x218eb8e,0x3a5ccf2, + 0x1dff677,0x2c59334,0x371599c,0x02a9f2a }, + { 0x0837bd1,0x3249cef,0x35d702f,0x3430dab,0x1c06407,0x108f692, + 0x221292f,0x05f0c5d,0x073fe06,0x01038e0 } }, + /* 144 */ + { { 0x3bf9b7c,0x2020929,0x30d0f4f,0x080fef8,0x3365d23,0x1f3e738, + 0x3e53209,0x1549afe,0x300b305,0x038d811 }, + { 0x0c6c2c7,0x2e6445b,0x3ee64dc,0x022e932,0x0726837,0x0deb67b, + 0x1ed4346,0x3857f73,0x277a3de,0x01950b5 } }, + /* 145 */ + { { 0x36c377a,0x0adb41e,0x08be3f3,0x11e40d1,0x36cb038,0x036a2bd, + 0x3dd3a82,0x1bc875b,0x2ee09bb,0x02994d2 }, + { 0x035facf,0x05e0344,0x07e630a,0x0ce772d,0x335e55a,0x111fce4, + 0x250fe1c,0x3bc89ba,0x32fdc9a,0x03cf2d9 } }, + /* 146 */ + { { 0x355fd83,0x1c67f8e,0x1d10eb3,0x1b21d77,0x0e0d7a4,0x173a9e1, + 0x2c9fa90,0x1c39cce,0x22eaae8,0x01f2bea }, + { 0x153b338,0x0534107,0x26c69b8,0x283be1f,0x3e0acc0,0x059cac3, + 0x13d1081,0x148bbee,0x3c1b9bd,0x002aac4 } }, + /* 147 */ + { { 0x2681297,0x3389e34,0x146addc,0x2c6d425,0x2cb350e,0x1986abc, + 0x0431737,0x04ba4b7,0x2028470,0x012e469 }, + { 0x2f8ddcf,0x3c4255c,0x1af4dcf,0x07a6a44,0x208ebf6,0x0dc90c3, + 0x34360ac,0x072ad23,0x0537232,0x01254d3 } }, + /* 148 */ + { { 0x07b7e9d,0x3df5c7c,0x116f83d,0x28c4f35,0x3a478ef,0x3011fb8, + 0x2f264b6,0x317b9e3,0x04fd65a,0x032bd1b }, + { 0x2aa8266,0x3431de4,0x04bba04,0x19a44da,0x0edf454,0x392c5ac, + 0x265168a,0x1dc3d5b,0x25704c6,0x00533a7 } }, + /* 149 */ + { { 0x25e8f91,0x1178fa5,0x2492994,0x2eb2c3c,0x0d3aca1,0x0322828, + 0x1cc70f9,0x269c74c,0x0a53e4c,0x006edc2 }, + { 0x18bdd7a,0x2a79a55,0x26b1d5c,0x0200628,0x0734a05,0x3273c7b, + 0x13aa714,0x0040ac2,0x2f2da30,0x03e7449 } }, + /* 150 */ + { { 0x3f9563e,0x2f29eab,0x14a0749,0x3fad264,0x1dd077a,0x3d7c59c, + 0x3a0311b,0x331a789,0x0b9729e,0x0201ebf }, + { 0x1b08b77,0x2a4cdf2,0x3e387f8,0x21510f1,0x286c3a7,0x1dbf62e, + 0x3afa594,0x3363217,0x0d16568,0x01d46b7 } }, + /* 151 */ + { { 0x0715c0d,0x28e2d04,0x17f78ae,0x1c63dda,0x1d113ea,0x0fefc1b, + 0x1eab149,0x1d0fd99,0x0682537,0x00a7b11 }, + { 0x10bebbc,0x11c672d,0x14223d9,0x2ff9141,0x1399ee5,0x34b7b6c, + 0x0d5b3a8,0x01df643,0x0e392a4,0x03fe4dc } }, + /* 152 */ + { { 0x2b75b65,0x0b5a6f1,0x11c559a,0x3549999,0x24188f8,0x37a75f4, + 0x29f33e3,0x34068a2,0x38ba2a9,0x025dd91 }, + { 0x29af2c7,0x0988b64,0x0923885,0x1b539a4,0x1334f5d,0x226947a, + 0x2cc7e5a,0x20beb39,0x13fac2f,0x01d298c } }, + /* 153 */ + { { 0x35f079c,0x137f76d,0x2fbbb2f,0x254638d,0x185b07c,0x1f34db7, + 0x2cfcf0e,0x218f46d,0x2150ff4,0x02add6f }, + { 0x33fc9b7,0x0d9f005,0x0fd081b,0x0834965,0x2b90a74,0x102448d, + 0x3dbf03c,0x167d857,0x02e0b44,0x013afab } }, + /* 154 */ + { { 0x09f2c53,0x317f9d7,0x1411eb6,0x0463aba,0x0d25220,0x256b176, + 0x087633f,0x2bff322,0x07b2c1b,0x037e662 }, + { 0x10aaecb,0x23bb4a1,0x2272bb7,0x06c075a,0x09d4918,0x0736f2b, + 0x0dd511b,0x101625e,0x0a7779f,0x009ec10 } }, + /* 155 */ + { { 0x33b2eb2,0x0176dfd,0x2118904,0x022386c,0x2e0df85,0x2588c9f, + 0x1b71525,0x28fd540,0x137e4cf,0x02ce4f7 }, + { 0x3d75165,0x0c39ecf,0x3554a12,0x30af34c,0x2d66344,0x3ded408, + 0x36f1be0,0x0d065b0,0x012d046,0x0025623 } }, + /* 156 */ + { { 0x2601c3b,0x1824fc0,0x335fe08,0x3e33d70,0x0fb0252,0x252bfca, + 0x1cf2808,0x1922e55,0x1a9db9f,0x020721e }, + { 0x2f56c51,0x39a1f31,0x218c040,0x1a4fc5d,0x3fed471,0x0164d4e, + 0x388a419,0x06f1113,0x0f55fc1,0x03e8352 } }, + /* 157 */ + { { 0x1608e4d,0x3872778,0x022cbc6,0x044d60a,0x3010dda,0x15fb0b5, + 0x37ddc11,0x19f5bda,0x156b6a3,0x023a838 }, + { 0x383b3b4,0x1380bc8,0x353ca35,0x250fc07,0x169966b,0x3780f29, + 0x36632b2,0x2d6b13f,0x124fa00,0x00fd6ae } }, + /* 158 */ + { { 0x1739efb,0x2ec3656,0x2c0d337,0x3d39faf,0x1c751b0,0x04699f4, + 0x252dd64,0x095b8b6,0x0872b74,0x022f1da }, + { 0x2d3d253,0x38edca0,0x379fa5b,0x287d635,0x3a9f679,0x059d9ee, + 0x0ac168e,0x3cd3e87,0x19060fc,0x02ce1bc } }, + /* 159 */ + { { 0x3edcfc2,0x0f04d4b,0x2f0d31f,0x1898be2,0x25396bf,0x15ca230, + 0x02b4eae,0x2713668,0x0f71b06,0x0132d18 }, + { 0x38095ea,0x1ed34d6,0x3603ae6,0x165bf01,0x192bbf8,0x1852859, + 0x075f66b,0x1488f85,0x10895ef,0x014b035 } }, + /* 160 */ + { { 0x1339848,0x3084385,0x0c8d231,0x3a1c1de,0x0e87a28,0x255b85c, + 0x1de6616,0x2702e74,0x1382bb0,0x012b0f2 }, + { 0x198987d,0x381545a,0x34d619b,0x312b827,0x18b2376,0x28fe4cf, + 0x20b7651,0x017d077,0x0c7e397,0x00e0365 } }, + /* 161 */ + { { 0x1542e75,0x0d56aa0,0x39b701a,0x287b806,0x396c724,0x0935c21, + 0x3a29776,0x0debdac,0x171de26,0x00b38f8 }, + { 0x1d5bc1a,0x3fad27d,0x22b5cfe,0x1f89ddf,0x0a65560,0x144dd5b, + 0x2aac2f9,0x139353f,0x0520b62,0x00b9b36 } }, + /* 162 */ + { { 0x031c31d,0x16552e3,0x1a0c368,0x0016fc8,0x168533d,0x171e7b2, + 0x17626e7,0x275502f,0x14742c6,0x03285dd }, + { 0x2d2dbb2,0x3b6bffd,0x1d18cc6,0x2f45d2a,0x0fd0d8c,0x2915e3a, + 0x1e8793a,0x0b39a1d,0x3139cab,0x02a5da9 } }, + /* 163 */ + { { 0x3fb353d,0x147c6e4,0x3a720a6,0x22d5ff3,0x1d75cab,0x06c54a0, + 0x08cfa73,0x12666aa,0x3170a1f,0x021c829 }, + { 0x13e1b90,0x3a34dda,0x1fc38c3,0x02c5bdb,0x2d345dc,0x14aa1d0, + 0x28d00ab,0x224f23a,0x329c769,0x025c67b } }, + /* 164 */ + { { 0x0e35909,0x3bb6356,0x0116820,0x370cf77,0x29366d8,0x3881409, + 0x3999d06,0x013075f,0x176e157,0x02941ca }, + { 0x0e70b2e,0x28dfab1,0x2a8a002,0x15da242,0x084dcf6,0x116ca97, + 0x31bf186,0x1dc9735,0x09df7b7,0x0264e27 } }, + /* 165 */ + { { 0x2da7a4b,0x3023c9e,0x1366238,0x00ff4e2,0x03abe9d,0x19bd44b, + 0x272e897,0x20b91ad,0x2aa202c,0x02a2201 }, + { 0x380184e,0x08112b4,0x0b85660,0x31049aa,0x3a8cb78,0x36113c5, + 0x1670c0a,0x373f9e7,0x3fb4738,0x00010ef } }, + /* 166 */ + { { 0x2d5192e,0x26d770d,0x32af8d5,0x34d1642,0x1acf885,0x05805e0, + 0x166d0a1,0x1219a0d,0x301ba6c,0x014bcfb }, + { 0x2dcb64d,0x19cca83,0x379f398,0x08e01a0,0x10a482c,0x0103cc2, + 0x0be5fa7,0x1f9d45b,0x1899ef2,0x00ca5af } }, + /* 167 */ + { { 0x14d81d7,0x2aea251,0x1b3c476,0x3bd47ae,0x29eade7,0x0715e61, + 0x1a21cd8,0x1c7a586,0x2bfaee5,0x00ee43f }, + { 0x096f7cb,0x0c08f95,0x1bc4939,0x361fed4,0x255be41,0x26fad73, + 0x31dd489,0x02c600f,0x29d9f81,0x01ba201 } }, + /* 168 */ + { { 0x03ea1db,0x1eac46d,0x1292ce3,0x2a54967,0x20a7ff1,0x3e13c61, + 0x1b02218,0x2b44e14,0x3eadefa,0x029c88a }, + { 0x30a9144,0x31e3b0a,0x19c5a2a,0x147cbe9,0x05a0240,0x051f38e, + 0x11eca56,0x31a4247,0x123bc2a,0x02fa535 } }, + /* 169 */ + { { 0x3226ce7,0x1251782,0x0b7072f,0x11e59fa,0x2b8afd7,0x169b18f, + 0x2a46f18,0x31d9bb7,0x2fe9be8,0x01de0b7 }, + { 0x1b38626,0x34aa90f,0x3ad1760,0x21ddbd9,0x3460ae7,0x1126736, + 0x1b86fc5,0x0b92cd0,0x167a289,0x000e0e1 } }, + /* 170 */ + { { 0x1ec1a0f,0x36bbf5e,0x1c972d8,0x3f73ace,0x13bbcd6,0x23d86a5, + 0x175ffc5,0x2d083d5,0x2c4adf7,0x036f661 }, + { 0x1f39eb7,0x2a20505,0x176c81a,0x3d6e636,0x16ee2fc,0x3cbdc5f, + 0x25475dc,0x2ef4151,0x3c46860,0x0238934 } }, + /* 171 */ + { { 0x2587390,0x3639526,0x0588749,0x13c32fb,0x212bb19,0x09660f1, + 0x207da4b,0x2bf211b,0x1c4407b,0x01506a6 }, + { 0x24c8842,0x105a498,0x05ffdb2,0x0ab61b0,0x26044c1,0x3dff3d8, + 0x1d14b44,0x0d74716,0x049f57d,0x030024b } }, + /* 172 */ + { { 0x32e61ef,0x31d70f7,0x35cad3c,0x320b86c,0x07e8841,0x027ca7d, + 0x2d30d19,0x2513718,0x2347286,0x01d7901 }, + { 0x3c237d0,0x107f16e,0x01c9e7d,0x3c3b13c,0x0c9537b,0x20af54d, + 0x051a162,0x2161a47,0x258c784,0x016df2d } }, + /* 173 */ + { { 0x228ead1,0x29c2122,0x07f6964,0x023f4ed,0x1802dc5,0x19f96ce, + 0x24bfd17,0x25e866b,0x2ba8df0,0x01eb84f }, + { 0x2dd384e,0x05bbe3a,0x3f06fd2,0x366dacb,0x30361a2,0x2f36d7c, + 0x0b98784,0x38ff481,0x074e2a8,0x01e1f60 } }, + /* 174 */ + { { 0x17fbb1c,0x0975add,0x1debc5e,0x2cb2880,0x3e47bdd,0x3488cff, + 0x15e9a36,0x2121129,0x0199ef2,0x017088a }, + { 0x0315250,0x352a162,0x17c1773,0x0ae09c2,0x321b21a,0x3bd74cf, + 0x3c4ea1d,0x3cac2ad,0x3abbaf0,0x039174d } }, + /* 175 */ + { { 0x0511c8a,0x3c78d0a,0x2cd3d2d,0x322f729,0x3ebb229,0x09f0e69, + 0x0a71a76,0x2e74d5e,0x12284df,0x03b5ef0 }, + { 0x3dea561,0x0a9b7e4,0x0ed1cf2,0x237523c,0x05443f1,0x2eb48fa, + 0x3861405,0x1b49f62,0x0c945ca,0x02ab25f } }, + /* 176 */ + { { 0x16bd00a,0x13a9d28,0x3cc1eb5,0x2b7d702,0x2d839e9,0x3e6ff01, + 0x2bb7f11,0x3713824,0x3b31163,0x00c63e5 }, + { 0x30d7138,0x0316fb0,0x0220ecc,0x08eaf0c,0x244e8df,0x0088d81, + 0x37972fb,0x3fd34ae,0x2a19a84,0x03e907e } }, + /* 177 */ + { { 0x2642269,0x0b65d29,0x03bd440,0x33a6ede,0x3c81814,0x2507982, + 0x0d38e47,0x3a788e6,0x32c1d26,0x00e2eda }, + { 0x2577f87,0x392895a,0x3e1cc64,0x14f7047,0x08b52d2,0x08a01ca, + 0x336abf6,0x00697fc,0x105ce76,0x0253742 } }, + /* 178 */ + { { 0x293f92a,0x33df737,0x3315156,0x32e26d7,0x0a01333,0x26579d4, + 0x004df9c,0x0aba409,0x067d25c,0x02481de }, + { 0x3f39d44,0x1c78042,0x13d7e24,0x0825aed,0x35f2c90,0x3270f63, + 0x04b7b35,0x3ad4531,0x28bd29b,0x0207a10 } }, + /* 179 */ + { { 0x077199f,0x270aeb1,0x0dd96dd,0x3b9ad7b,0x28cb8ee,0x3903f43, + 0x37db3fe,0x292c62b,0x362dbbf,0x006e52a }, + { 0x247f143,0x0362cf3,0x216344f,0x3f18fd1,0x351e623,0x31664e0, + 0x0f270fc,0x243bbc6,0x2280555,0x001a8e3 } }, + /* 180 */ + { { 0x3355b49,0x2c04e6c,0x399b2e5,0x182d3af,0x020e265,0x09a7cf7, + 0x0ffa6bd,0x353e302,0x02083d9,0x029ecdb }, + { 0x33e8830,0x0570e86,0x1c0b64d,0x386a27e,0x0d5fcea,0x0b45a4c, + 0x2ee4a2e,0x0a8833f,0x2b4a282,0x02f9531 } }, + /* 181 */ + { { 0x191167c,0x36cf7e3,0x225ed6c,0x1e79e99,0x0517c3f,0x11ab1fd, + 0x05648f3,0x08aedc4,0x1abeae0,0x02fcc29 }, + { 0x3828a68,0x1e16fa4,0x30368e7,0x0c9fcfb,0x25161c3,0x24851ac, + 0x1b5feb5,0x344eb84,0x0de2732,0x0347208 } }, + /* 182 */ + { { 0x038b363,0x384d1e4,0x2519043,0x151ac17,0x158c11f,0x009b2b4, + 0x257abe6,0x2368d3f,0x3ed68a1,0x02df45e }, + { 0x29c2559,0x2962478,0x3d8444c,0x1d96fff,0x04f7a03,0x1391a52, + 0x0de4af7,0x3319126,0x15e6412,0x00e65ff } }, + /* 183 */ + { { 0x3d61507,0x1d1a0a2,0x0d2af20,0x354d299,0x329e132,0x2a28578, + 0x2ddfb08,0x04fa3ff,0x1293c6c,0x003bae2 }, + { 0x3e259f8,0x1a68fa9,0x3e67e9b,0x39b44f9,0x1ce1db7,0x347e9a1, + 0x3318f6a,0x2dbbc9d,0x2f8c922,0x008a245 } }, + /* 184 */ + { { 0x212ab5b,0x2b896c2,0x0136959,0x07e55ef,0x0cc1117,0x05b8ac3, + 0x18429ed,0x025fa01,0x11d6e93,0x03b016b }, + { 0x03f3708,0x2e96fab,0x1d77157,0x0d4c2d6,0x131baf9,0x0608d39, + 0x3552371,0x06cdd1e,0x1567ff1,0x01f4c50 } }, + /* 185 */ + { { 0x2dfefab,0x270173d,0x37077bd,0x1a372cd,0x1be2f22,0x28e2ee5, + 0x3ead973,0x35e8f94,0x2fc9bc1,0x03a7399 }, + { 0x36a02a1,0x2855d9b,0x00ed75a,0x37d8398,0x138c087,0x233706e, + 0x147f346,0x01947e2,0x3017228,0x0365942 } }, + /* 186 */ + { { 0x2057e60,0x2d31296,0x25e4504,0x2fa37bc,0x1cbccc3,0x1f0732f, + 0x3532081,0x2de8a98,0x19a804e,0x005359a }, + { 0x31f411a,0x2a10576,0x369c2c8,0x02fe035,0x109fbaf,0x30bddeb, + 0x1eef901,0x1662ad3,0x0410d43,0x01bd31a } }, + /* 187 */ + { { 0x2c24a96,0x1b7d3a5,0x19a3872,0x217f2f6,0x2534dbc,0x2cab8c2, + 0x066ef28,0x26aecf1,0x0fd6118,0x01310d4 }, + { 0x055b8da,0x1fdc5be,0x38a1296,0x25118f0,0x341a423,0x2ba4cd0, + 0x3e1413e,0x062d70d,0x2425a31,0x029c9b4 } }, + /* 188 */ + { { 0x08c1086,0x1acfba5,0x22e1dae,0x0f72f4e,0x3f1de50,0x0f408bc, + 0x35ed3f0,0x3ce48fc,0x282cc6c,0x004d8e7 }, + { 0x1afaa86,0x24e3ef3,0x22589ac,0x3ec9952,0x1f45bc5,0x14144ca, + 0x23b26e4,0x0d68c65,0x1e1c1a3,0x032a4d9 } }, + /* 189 */ + { { 0x03b2d20,0x16b1d53,0x241b361,0x05e4138,0x1742a54,0x32741c7, + 0x0521c4c,0x1ca96c2,0x034970b,0x02738a7 }, + { 0x13e0ad6,0x207dcdb,0x034c8cc,0x27bcbe1,0x18060da,0x33a18b6, + 0x2d1d1a6,0x2be60d7,0x3d7ab42,0x012312a } }, + /* 190 */ + { { 0x0c7485a,0x06c3310,0x0dbfd22,0x2ef949d,0x0ead455,0x098f4ba, + 0x3c76989,0x0cf2d24,0x032f67b,0x01e005f }, + { 0x30cb5ee,0x0d5da64,0x0ed2b9d,0x2503102,0x1c0d14e,0x1cbc693, + 0x37bf552,0x07013e2,0x054de5c,0x014f341 } }, + /* 191 */ + { { 0x128ccac,0x1617e97,0x346ebcd,0x158016d,0x25f823e,0x34048ea, + 0x39f0a1c,0x3ea3df1,0x1c1d3d7,0x03ba919 }, + { 0x151803b,0x01967c1,0x2f70781,0x27df39a,0x06c0b59,0x24a239c, + 0x15a7702,0x2464d06,0x2a47ae6,0x006db90 } }, + /* 192 */ + { { 0x27d04c3,0x024df3d,0x38112e8,0x38a27ba,0x01e312b,0x0965358, + 0x35d8879,0x2f4f55a,0x214187f,0x0008936 }, + { 0x05fe36f,0x2ee18c3,0x1f5f87a,0x1813bd4,0x0580f3c,0x0ed0a7b, + 0x0fb1bfb,0x3fcce59,0x2f042bf,0x01820e3 } }, + /* 193 */ + { { 0x20bbe99,0x32cbc9f,0x39ee432,0x3cc12a8,0x37bda44,0x3ea4e40, + 0x097c7a9,0x0590d7d,0x2022d33,0x018dbac }, + { 0x3ae00aa,0x3439864,0x2d2ffcf,0x3f8c6b9,0x0875a00,0x3e4e407, + 0x3658a29,0x22eb3d0,0x2b63921,0x022113b } }, + /* 194 */ + { { 0x33bae58,0x05c749a,0x1f3e114,0x1c45f8e,0x27db3df,0x06a3ab6, + 0x37bc7f8,0x1e27b34,0x3dc51fb,0x009eea0 }, + { 0x3f54de5,0x3d0e7fe,0x1a71a7d,0x02ed7f8,0x0727703,0x2ca5e92, + 0x2e8e35d,0x292ad0b,0x13487f3,0x02b6d8b } }, + /* 195 */ + { { 0x175df2a,0x05a28a8,0x32e99b1,0x13d8630,0x2082aa0,0x11ac245, + 0x24f2e71,0x322cb27,0x17675e7,0x02e643f }, + { 0x1f37313,0x2765ad3,0x0789082,0x1e742d0,0x11c2055,0x2021dc4, + 0x09ae4a7,0x346359b,0x2f94d10,0x0205c1f } }, + /* 196 */ + { { 0x3d6ff96,0x1f2ac80,0x336097d,0x3f03610,0x35b851b,0x010b6d2, + 0x0823c4d,0x2a9709a,0x2ead5a8,0x00de4b6 }, + { 0x01afa0b,0x0621965,0x3671528,0x1050b60,0x3f3e9e7,0x2f93829, + 0x0825275,0x006e85f,0x35e94b0,0x016af58 } }, + /* 197 */ + { { 0x2c4927c,0x3ea1382,0x0f23727,0x0d69f23,0x3e38860,0x2b72837, + 0x3cd5ea4,0x2d84292,0x321846a,0x016656f }, + { 0x29dfa33,0x3e182e0,0x018be90,0x2ba563f,0x2caafe2,0x218c0d9, + 0x3baf447,0x1047a6c,0x0a2d483,0x01130cb } }, + /* 198 */ + { { 0x00ed80c,0x2a5fc79,0x0a82a74,0x2c4c74b,0x15f938c,0x30b5ab6, + 0x32124b7,0x295314f,0x2fb8082,0x007c858 }, + { 0x20b173e,0x19f315c,0x12f97e4,0x198217c,0x040e8a6,0x3275977, + 0x2bc20e4,0x01f2633,0x02bc3e9,0x023c750 } }, + /* 199 */ + { { 0x3c4058a,0x24be73e,0x16704f5,0x2d8a4bd,0x3b15e14,0x3076315, + 0x1cfe37b,0x36fe715,0x343926e,0x02c6603 }, + { 0x2c76b09,0x0cf824c,0x3f7898c,0x274cec1,0x11df527,0x18eed18, + 0x08ead48,0x23915bc,0x19b3744,0x00a0a2b } }, + /* 200 */ + { { 0x0cf4ac5,0x1c8b131,0x0afb696,0x0ff7799,0x2f5ac1a,0x022420c, + 0x11baa2e,0x2ce4015,0x1275a14,0x0125cfc }, + { 0x22eac5d,0x360cd4c,0x3568e59,0x3d42f66,0x35e07ee,0x09620e4, + 0x36720fa,0x22b1eac,0x2d0db16,0x01b6b23 } }, + /* 201 */ + { { 0x1a835ef,0x1516bbb,0x2d51f7b,0x3487443,0x14aa113,0x0dd06c2, + 0x1a65e01,0x379300d,0x35920b9,0x012c8fb }, + { 0x04c7341,0x2eda00f,0x3c37e82,0x1b4fd62,0x0d45770,0x1478fba, + 0x127863a,0x26939cd,0x134ddf4,0x01375c5 } }, + /* 202 */ + { { 0x1476cd9,0x1119ca5,0x325bbf9,0x0bf8c69,0x0648d07,0x312d9f8, + 0x01c8b8f,0x136ec51,0x0002f4a,0x03f4c5c }, + { 0x195d0e1,0x10ffd22,0x29aa1cb,0x3443bdc,0x276e695,0x05e6260, + 0x15f9764,0x3cd9783,0x18c9569,0x0053eb1 } }, + /* 203 */ + { { 0x312ae18,0x280197c,0x3fc9ad9,0x303f324,0x251958d,0x29f4a11, + 0x2142408,0x3694366,0x25136ab,0x03b5f1d }, + { 0x1d4abbc,0x1c3c689,0x13ea462,0x3cfc684,0x39b5dd8,0x2d4654b, + 0x09b0755,0x27d4f18,0x3f74d2e,0x03fbf2d } }, + /* 204 */ + { { 0x2119185,0x2525eae,0x1ba4bd0,0x0c2ab11,0x1d54e8c,0x294845e, + 0x2479dea,0x3602d24,0x17e87e0,0x0060069 }, + { 0x0afffb0,0x34fe37f,0x1240073,0x02eb895,0x06cf33c,0x2d7f7ef, + 0x1d763b5,0x04191e0,0x11e1ead,0x027e3f0 } }, + /* 205 */ + { { 0x269544c,0x0e85c57,0x3813158,0x19fc12d,0x20eaf85,0x1e2930c, + 0x22a8fd2,0x1a6a478,0x09d3d3a,0x02a74e0 }, + { 0x1a2da3b,0x30b0b16,0x0847936,0x3d86257,0x138ccbc,0x0f5421a, + 0x25244e6,0x23bdd79,0x1aee117,0x00c01ae } }, + /* 206 */ + { { 0x1eead28,0x07cac32,0x1fbc0bb,0x17627d3,0x17eef63,0x0b3a24e, + 0x0757fdb,0x3dd841d,0x3d745f8,0x002ae17 }, + { 0x25b4549,0x29f24cf,0x2f21ecd,0x1725e48,0x04be2bb,0x10ee010, + 0x1a1274b,0x10b0898,0x27511e9,0x02c48b5 } }, + /* 207 */ + { { 0x2a5ae7a,0x181ef99,0x0be33be,0x3e9dab7,0x101e703,0x3adb971, + 0x1043014,0x2ebb2be,0x1c1097d,0x027d667 }, + { 0x3f250ed,0x16dc603,0x20dc6d7,0x1d0d268,0x38eb915,0x02c89e8, + 0x1605a41,0x12de109,0x0e08a29,0x01f554a } }, + /* 208 */ + { { 0x0c26def,0x163d988,0x2d1ef0f,0x3a960ac,0x1025585,0x0738e20, + 0x27d79b0,0x05cc3ef,0x201303f,0x00a333a }, + { 0x1644ba5,0x2af345e,0x30b8d1d,0x3a01bff,0x31fc643,0x1acf85e, + 0x0a76fc6,0x04efe98,0x348a1d0,0x03062eb } }, + /* 209 */ + { { 0x1c4216d,0x18e3217,0x02ac34e,0x19c8185,0x200c010,0x17d4192, + 0x13a1719,0x165af51,0x09db7a9,0x0277be0 }, + { 0x3ab8d2c,0x2190b99,0x22b641e,0x0cd88de,0x3b42404,0x1310862, + 0x106a6d6,0x23395f5,0x0b06880,0x000d5fe } }, + /* 210 */ + { { 0x0d2cc88,0x36f9913,0x339d8e9,0x237c2e3,0x0cc61c2,0x34c2832, + 0x309874c,0x2621d28,0x2dd1b48,0x0392806 }, + { 0x17cd8f9,0x07bab3d,0x0c482ed,0x0faf565,0x31b767d,0x2f4bde1, + 0x295c717,0x330c29c,0x179ce10,0x0119b5f } }, + /* 211 */ + { { 0x1ada2c7,0x0c624a7,0x227d47d,0x30e3e6a,0x14fa0a6,0x0829678, + 0x24fd288,0x2b46a43,0x122451e,0x0319ca9 }, + { 0x186b655,0x01f3217,0x0af1306,0x0efe6b5,0x2f0235d,0x1c45ca9, + 0x2086805,0x1d44e66,0x0faf2a6,0x0178f59 } }, + /* 212 */ + { { 0x33b4416,0x10431e6,0x2d99aa6,0x217aac9,0x0cd8fcf,0x2d95a9d, + 0x3ff74ad,0x10bf17a,0x295eb8e,0x01b229e }, + { 0x02a63bd,0x182e9ec,0x004710c,0x00e2e3c,0x06b2f23,0x04b642c, + 0x2c37383,0x32a4631,0x022ad82,0x00d22b9 } }, + /* 213 */ + { { 0x0cda2fb,0x1d198d7,0x26d27f4,0x286381c,0x022acca,0x24ac7c8, + 0x2df7824,0x0b4ba16,0x1e0d9ef,0x03041d3 }, + { 0x29a65b3,0x0f3912b,0x151bfcf,0x2b0175c,0x0fd71e4,0x39aa5e2, + 0x311f50c,0x13ff351,0x3dbc9e5,0x03eeb7e } }, + /* 214 */ + { { 0x0a99363,0x0fc7348,0x2775171,0x23db3c8,0x2b91565,0x134d66c, + 0x0175cd2,0x1bf365a,0x2b48371,0x02dfe5d }, + { 0x16dbf74,0x2389357,0x2f36575,0x3f5c70e,0x38d23ba,0x090f7f8, + 0x3477600,0x3201523,0x32ecafc,0x03d3506 } }, + /* 215 */ + { { 0x1abd48d,0x073ca3f,0x38a451f,0x0d8cb01,0x1ce81be,0x05c51ba, + 0x0e29741,0x03c41ab,0x0eae016,0x0060209 }, + { 0x2e58358,0x1da62d9,0x2358038,0x14b39b2,0x1635687,0x39079b1, + 0x380e345,0x1b49608,0x23983cf,0x019f97d } }, + /* 216 */ + { { 0x34899ef,0x332e373,0x04c0f89,0x3c27aed,0x1949015,0x09663b2, + 0x2f9276b,0x07f1951,0x09a04c1,0x027fbde }, + { 0x3d2a071,0x19fb3d4,0x1b096d3,0x1fe9146,0x3b10e1a,0x0478bbb, + 0x2b3fb06,0x1388329,0x181a99c,0x02f2030 } }, + /* 217 */ + { { 0x1eb82e6,0x14dbe39,0x3920972,0x31fd5b2,0x21a484f,0x02d7697, + 0x0e21715,0x37c431e,0x2629f8c,0x01249c3 }, + { 0x26b50ad,0x26deefa,0x0ffc1a3,0x30688e2,0x39a0284,0x041c65e, + 0x03eb178,0x0bdfd50,0x2f96137,0x034bb94 } }, + /* 218 */ + { { 0x0e0362a,0x334a162,0x194dd37,0x29e3e97,0x2442fa8,0x10d2949, + 0x3836e5a,0x2dccebf,0x0bee5ab,0x037ed1e }, + { 0x33eede6,0x3c739d9,0x2f04a91,0x350ad6c,0x3a5390a,0x14c368b, + 0x26f7bf5,0x11ce979,0x0b408df,0x0366850 } }, + /* 219 */ + { { 0x28ea498,0x0886d5b,0x2e090e0,0x0a4d58f,0x2623478,0x0d74ab7, + 0x2b83913,0x12c6b81,0x18d623f,0x01d8301 }, + { 0x198aa79,0x26d6330,0x3a7f0b8,0x34bc1ea,0x2f74890,0x378955a, + 0x204110f,0x0102538,0x02d8f19,0x01c5066 } }, + /* 220 */ + { { 0x14b0f45,0x2838cd3,0x14e16f0,0x0e0e4aa,0x2d9280b,0x0f18757, + 0x3324c6b,0x1391ceb,0x1ce89d5,0x00ebe74 }, + { 0x0930371,0x3de6048,0x3097fd8,0x1308705,0x3eda266,0x3108c26, + 0x1545dcd,0x1f7583a,0x1c37395,0x02c7e05 } }, + /* 221 */ + { { 0x1fec44a,0x2a9e3a2,0x0caf84f,0x11cf2a9,0x0c8c2ae,0x06da989, + 0x1c807dc,0x3c149a4,0x1141543,0x02906bb }, + { 0x15ffe04,0x0d4e65f,0x2e20424,0x37d896d,0x18bacb2,0x1e05ddd, + 0x1660be8,0x183be17,0x1dd86fb,0x035ba70 } }, + /* 222 */ + { { 0x2853264,0x0ba5fb1,0x0a0b3aa,0x2df88c1,0x2771533,0x23aba6f, + 0x112bb7b,0x3e3086e,0x210ae9b,0x027271b }, + { 0x030b74c,0x0269678,0x1e90a23,0x135a98c,0x24ed749,0x126de7c, + 0x344b23a,0x186da27,0x19640fa,0x0159af5 } }, + /* 223 */ + { { 0x18061f3,0x3004630,0x3c70066,0x34df20f,0x1190b25,0x1c9cc91, + 0x1fc8e02,0x0d17bc1,0x390f525,0x033cb1c }, + { 0x0eb30cf,0x2f3ad04,0x303aa09,0x2e835dd,0x1cfd2eb,0x143fc95, + 0x02c43a1,0x025e7a1,0x3558aa2,0x000bd45 } }, + /* 224 */ + { { 0x1db7d07,0x3bde52b,0x1500396,0x1089115,0x20b4fc7,0x1e2a8f3, + 0x3f8eacc,0x365f7eb,0x1a5e8d4,0x0053a6b }, + { 0x37079e2,0x120284b,0x000edaa,0x33792c2,0x145baa3,0x20e055f, + 0x365e2d7,0x26ba005,0x3ab8e9d,0x0282b53 } }, + /* 225 */ + { { 0x2653618,0x2dd8852,0x2a5f0bf,0x0f0c7aa,0x2187281,0x1252757, + 0x13e7374,0x3b47855,0x0b86e56,0x02f354c }, + { 0x2e9c47b,0x2fa14cc,0x19ab169,0x3fad401,0x0dc2776,0x24afeed, + 0x3a97611,0x0d07736,0x3cf6979,0x02424a0 } }, + /* 226 */ + { { 0x2e81a13,0x000c91d,0x123967b,0x265885c,0x29bee1a,0x0cb8675, + 0x2d361bd,0x1526823,0x3c9ace1,0x00d7bad }, + { 0x24e5bdc,0x02b969f,0x2c6e128,0x34edb3b,0x12dcd2c,0x3899af0, + 0x24224c6,0x3a1914b,0x0f4448a,0x026a2cb } }, + /* 227 */ + { { 0x1d03b59,0x1c6fc82,0x32abf64,0x28ed96b,0x1c90e62,0x2f57bb2, + 0x3ff168e,0x04de7fd,0x0f4d449,0x01af6d8 }, + { 0x255bc30,0x2bfaf22,0x3fe0dad,0x0584025,0x1c79ead,0x3078ef7, + 0x2197414,0x022a50b,0x0fd94ba,0x0007b0f } }, + /* 228 */ + { { 0x09485c2,0x09dfaf7,0x10c7ba6,0x1e48bec,0x248cc9a,0x028a362, + 0x21d60f7,0x193d93d,0x1c04754,0x0346b2c }, + { 0x2f36612,0x240ac49,0x0d8bd26,0x13b8186,0x259c3a4,0x020d5fb, + 0x38a8133,0x09b0937,0x39d4056,0x01f7341 } }, + /* 229 */ + { { 0x05a4b48,0x1f534fc,0x07725ce,0x148dc8c,0x2adcd29,0x04aa456, + 0x0f79718,0x066e346,0x189377d,0x002fd4d }, + { 0x068ea73,0x336569b,0x184d35e,0x32a08e9,0x3c7f3bb,0x11ce9c8, + 0x3674c6f,0x21bf27e,0x0d9e166,0x034a2f9 } }, + /* 230 */ + { { 0x0fa8e4b,0x2e6418e,0x18fc5d2,0x1ba24ff,0x0559f18,0x0dbedbf, + 0x2de2aa4,0x22338e9,0x3aa510f,0x035d801 }, + { 0x23a4988,0x02aad94,0x02732d1,0x111d374,0x0b455cf,0x0d01c9e, + 0x067082a,0x2ec05fd,0x368b303,0x03cad4b } }, + /* 231 */ + { { 0x035b4ca,0x1fabea6,0x1cbc0d5,0x3f2ed9a,0x02d2232,0x1990c66, + 0x2eb680c,0x3b4ea3b,0x18ecc5a,0x03636fa }, + { 0x1a02709,0x26f8ff1,0x1fa8cba,0x397d6e8,0x230be68,0x043aa14, + 0x3d43cdf,0x25c17fa,0x3a3ee55,0x0380564 } }, + /* 232 */ + { { 0x275a0a6,0x16bd43a,0x0033d3e,0x2b15e16,0x2512226,0x005d901, + 0x26d50fd,0x3bc19bf,0x3b1aeb8,0x02bfb01 }, + { 0x0bb0a31,0x26559e0,0x1aae7fb,0x330dcc2,0x16f1af3,0x06afce2, + 0x13a15a0,0x2ff7645,0x3546e2d,0x029c6e4 } }, + /* 233 */ + { { 0x0f593d2,0x384b806,0x122bbf8,0x0a281e0,0x1d1a904,0x2e93cab, + 0x0505db0,0x08f6454,0x05c6285,0x014e880 }, + { 0x3f2b935,0x22d8e79,0x161a07c,0x16b060a,0x02bff97,0x146328b, + 0x3ceea77,0x238f61a,0x19b3d58,0x02fd1f4 } }, + /* 234 */ + { { 0x17665d5,0x259e9f7,0x0de5672,0x15cbcbd,0x34e3030,0x035240f, + 0x0005ae8,0x286d851,0x07f39c9,0x000070b }, + { 0x1efc6d6,0x2a0051a,0x2724143,0x2a9ef1e,0x0c810bd,0x1e05429, + 0x25670ba,0x2e66d7d,0x0e786ff,0x03f6b7e } }, + /* 235 */ + { { 0x3c00785,0x232e23f,0x2b67fd3,0x244ed23,0x077fa75,0x3cda3ef, + 0x14d055b,0x0f25011,0x24d5aa4,0x00ea0e3 }, + { 0x297bb9a,0x198ca4f,0x14d9561,0x18d1076,0x39eb933,0x2b6caa0, + 0x1591a60,0x0768d45,0x257873e,0x00f36e0 } }, + /* 236 */ + { { 0x1e77eab,0x0502a5f,0x0109137,0x0350592,0x3f7e1c5,0x3ac7437, + 0x2dcad2c,0x1fee9d8,0x089f1f5,0x0169833 }, + { 0x0d45673,0x0d8e090,0x065580b,0x065644f,0x11b82be,0x3592dd0, + 0x3284b8d,0x23f0015,0x16fdbfd,0x0248bfd } }, + /* 237 */ + { { 0x1a129a1,0x1977bb2,0x0e041b2,0x15f30a1,0x0a5b1ce,0x3afef8f, + 0x380c46c,0x3358810,0x27df6c5,0x01ca466 }, + { 0x3b90f9a,0x3d14ea3,0x031b298,0x02e2390,0x2d719c0,0x25bc615, + 0x2c0e777,0x0226b8c,0x3803624,0x0179e45 } }, + /* 238 */ + { { 0x363cdfb,0x1bb155f,0x24fd5c1,0x1c7c72b,0x28e6a35,0x18165f2, + 0x226bea5,0x0beaff3,0x371e24c,0x0138294 }, + { 0x1765357,0x29034e9,0x22b4276,0x11035ce,0x23c89af,0x074468c, + 0x3370ae4,0x013bae3,0x018d566,0x03d7fde } }, + /* 239 */ + { { 0x209df21,0x0f8ff86,0x0e47fbf,0x23b99ba,0x126d5d2,0x2722405, + 0x16bd0a2,0x1799082,0x0e9533f,0x039077c }, + { 0x3ba9e3f,0x3f6902c,0x1895305,0x3ac9813,0x3f2340c,0x3c0d9f1, + 0x26e1927,0x0557c21,0x16eac4f,0x023b75f } }, + /* 240 */ + { { 0x3fc8ff3,0x0770382,0x342fc9a,0x0afa4db,0x314efd8,0x328e07b, + 0x016f7cc,0x3ba599c,0x1caed8a,0x0050cb0 }, + { 0x0b23c26,0x2120a5c,0x3273ec6,0x1cc1cd6,0x2a64fe8,0x2bbc3d6, + 0x09f6e5e,0x34b1b8e,0x00b5ac8,0x032bbd2 } }, + /* 241 */ + { { 0x1315922,0x1725e1d,0x0ca5524,0x1c4c18f,0x3d82951,0x193bcb2, + 0x0e60d0b,0x388dbcf,0x37e8efa,0x0342e85 }, + { 0x1b3af60,0x26ba3ec,0x220e53a,0x394f4b6,0x01a796a,0x3e7bbca, + 0x163605d,0x2b85807,0x17c1c54,0x03cc725 } }, + /* 242 */ + { { 0x1cc4597,0x1635492,0x2028c0f,0x2c2eb82,0x2dc5015,0x0d2a052, + 0x05fc557,0x1f0ebbf,0x0cb96e1,0x0004d01 }, + { 0x1a824bf,0x3896172,0x2ed7b29,0x178007a,0x0d59318,0x07bda2b, + 0x2ee6826,0x0f9b235,0x04b9193,0x01bcddf } }, + /* 243 */ + { { 0x0333fd2,0x0eeb46a,0x15b89f9,0x00968aa,0x2a89302,0x2bdd6b3, + 0x1e5037e,0x2541884,0x24ed2d0,0x01b6e8f }, + { 0x04399cd,0x3be6334,0x3adea48,0x1bb9adc,0x31811c6,0x05fb2bc, + 0x360752c,0x3d29dcb,0x3423bec,0x03c4f3c } }, + /* 244 */ + { { 0x119e2eb,0x2e7b02a,0x0f68cee,0x257d8b0,0x183a9a1,0x2ae88a6, + 0x3a3bb67,0x2eb4f3e,0x1a9274b,0x0320fea }, + { 0x2fa1ce0,0x346c2d8,0x2fbf0d7,0x3d4d063,0x0e58b60,0x09c1bc1, + 0x28ef9e5,0x09a0efe,0x0f45d70,0x02d275c } }, + /* 245 */ + { { 0x2d5513b,0x31d443e,0x1e2d914,0x3b2c5d4,0x105f32e,0x27ee756, + 0x050418d,0x3c73db6,0x1bb0c30,0x01673eb }, + { 0x1cb7fd6,0x1eb08d5,0x26a3e16,0x2e20810,0x0249367,0x029e219, + 0x2ec58c9,0x12d9fab,0x362354a,0x016eafc } }, + /* 246 */ + { { 0x2424865,0x260747b,0x177f37c,0x1e3cb95,0x08b0028,0x2783016, + 0x2970f1b,0x323c1c0,0x2a79026,0x0186231 }, + { 0x0f244da,0x26866f4,0x087306f,0x173ec20,0x31ecced,0x3c84d8d, + 0x070f9b9,0x2e764d5,0x075df50,0x0264ff9 } }, + /* 247 */ + { { 0x32c3609,0x0c737e6,0x14ea68e,0x300b11b,0x184eb19,0x29dd440, + 0x09ec1a9,0x185adeb,0x0664c80,0x0207dd9 }, + { 0x1fbe978,0x30a969d,0x33561d7,0x34fc60e,0x36743fe,0x00774af, + 0x0d1f045,0x018360e,0x12a5fe9,0x01592a0 } }, + /* 248 */ + { { 0x2817d1d,0x2993d3e,0x2e0f7a5,0x112faa0,0x255f968,0x355fe6a, + 0x3f5a0fc,0x075b2d7,0x3cf00e5,0x0089afc }, + { 0x32833cf,0x06a7e4b,0x09a8d6d,0x1693d3e,0x320a0a3,0x3cfdfdd, + 0x136c498,0x1e0d845,0x347ff25,0x01a1de7 } }, + /* 249 */ + { { 0x3043d08,0x030705c,0x20fa79b,0x1d07f00,0x0a54467,0x29b49b4, + 0x367e289,0x0b82f4d,0x0d1eb09,0x025ef2c }, + { 0x32ed3c3,0x1baaa3c,0x3c482ab,0x146ca06,0x3c8a4f1,0x3e85e3c, + 0x1bf4f3b,0x1195534,0x3e80a78,0x02a1cbf } }, + /* 250 */ + { { 0x32b2086,0x2de4d68,0x3486b1a,0x03a0583,0x2e1eb71,0x2dab9af, + 0x10cd913,0x28daa6f,0x3fcb732,0x000a04a }, + { 0x3605318,0x3f5f2b3,0x2d1da63,0x143f7f5,0x1646e5d,0x040b586, + 0x1683982,0x25abe87,0x0c9fe53,0x001ce47 } }, + /* 251 */ + { { 0x380d02b,0x055fc22,0x3f7fc50,0x3458a1d,0x26b8333,0x23550ab, + 0x0a1af87,0x0a821eb,0x2dc7e6d,0x00d574a }, + { 0x07386e1,0x3ccd68a,0x3275b41,0x253e390,0x2fd272a,0x1e6627a, + 0x2ca2cde,0x0e9e4a1,0x1e37c2a,0x00f70ac } }, + /* 252 */ + { { 0x0581352,0x2748701,0x02bed68,0x094dd9e,0x30a00c8,0x3fb5c07, + 0x3bd5909,0x211ac80,0x1103ccd,0x0311e1a }, + { 0x0c768ed,0x29dc209,0x36575db,0x009a107,0x272feea,0x2b33383, + 0x313ed56,0x134c9cc,0x168d5bb,0x033310a } }, + /* 253 */ + { { 0x17620b9,0x143784f,0x256a94e,0x229664a,0x1d89a5c,0x1d521f2, + 0x0076406,0x1c73f70,0x342aa48,0x03851fa }, + { 0x0f3ae46,0x2ad3bab,0x0fbe274,0x3ed40d4,0x2fd4936,0x232103a, + 0x2afe474,0x25b8f7c,0x047080e,0x008e6b0 } }, + /* 254 */ + { { 0x3fee8d4,0x347cd4a,0x0fec481,0x33fe9ec,0x0ce80b5,0x33a6bcf, + 0x1c4c9e2,0x3967441,0x1a3f5f7,0x03157e8 }, + { 0x257c227,0x1bc53a0,0x200b318,0x0fcd0af,0x2c5b165,0x2a413ec, + 0x2fc998a,0x2da6426,0x19cd4f4,0x0025336 } }, + /* 255 */ + { { 0x303beba,0x2072135,0x32918a9,0x140cb3a,0x08631d1,0x0ef527b, + 0x05f2c9e,0x2b4ce91,0x0b642ab,0x02e428c }, + { 0x0a5abf9,0x15013ed,0x3603b46,0x30dd76d,0x3004750,0x28d7627, + 0x1a42ccc,0x093ddbe,0x39a1b79,0x00067e2 } }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const 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 coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[10]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_256_point_new_10(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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); + + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_10(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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 || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_add_one_10(sp_digit* a) +{ + a[0]++; + sp_256_norm_10(a); +} + +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 18U) { + r[j] &= 0x3ffffff; + s = 26U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; 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, (int)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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[10]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 inf; +#endif +#endif + sp_point_256* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity; +#endif + int err; + + (void)heap; + + err = sp_256_point_new_10(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_point_new_10(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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) { + err = sp_256_ecc_mulmod_base_10(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_10(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_256_iszero_10(point->x) == 0) || (sp_256_iszero_10(point->y) == 0)) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_256_point_free_10(infinity, 1, heap); +#endif + sp_256_point_free_10(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte array. + * 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; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 26) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 26); + if (j >= 0) { + 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[10]; +#endif + sp_point_256* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 32U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_256_point_new_10(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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); + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_10(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#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. + */ +SP_NOINLINE static void sp_256_mul_d_10(sp_digit* r, const sp_digit* a, + 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 */ +} + +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_256_div_word_10(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 26 bits from d1 and top 5 bits from d0. */ + d = (d1 << 5) | (d0 >> 21); + r = d / dv; + d -= r * dv; + /* Up to 6 bits in r */ + /* Next 5 bits from d0. */ + r <<= 5; + d <<= 5; + d |= (d0 >> 16) & ((1 << 5) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 11 bits in r */ + /* Next 5 bits from d0. */ + r <<= 5; + d <<= 5; + d |= (d0 >> 11) & ((1 << 5) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 16 bits in r */ + /* Next 5 bits from d0. */ + r <<= 5; + d <<= 5; + d |= (d0 >> 6) & ((1 << 5) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 21 bits in r */ + /* Next 5 bits from d0. */ + r <<= 5; + d <<= 5; + d |= (d0 >> 1) & ((1 << 5) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 26 bits in r */ + /* Remaining 1 bits from d0. */ + r <<= 1; + d <<= 1; + d |= d0 & ((1 << 1) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* 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 Number 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(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[20], t2d[10 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 10 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 2 * 10; +#else + t1 = t1d; + t2 = t2d; +#endif + + dv = d[9]; + XMEMCPY(t1, a, sizeof(*t1) * 2U * 10U); + for (i=9; i>=0; i--) { + t1[10 + i] += t1[10 + i - 1] >> 26; + t1[10 + i - 1] &= 0x3ffffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[10 + i]; + d1 <<= 26; + d1 += t1[10 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_256_div_word_10(t1[10 + i], t1[10 + i - 1], dv); +#endif + + sp_256_mul_d_10(t2, d, r1); + (void)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]) / dv; + r1++; + sp_256_mul_d_10(t2, d, r1); + (void)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; + r1 = t1[10 - 1] / dv; + + sp_256_mul_d_10(t2, d, r1); + (void)sp_256_sub_10(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 10U); + 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) ? + (sp_digit)1 : (sp_digit)0)); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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, const sp_digit* a, const 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_minus_2[8] = { + 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU,0xffffffffU,0xffffffffU, + 0x00000000U,0xffffffffU +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint32_t p256_order_low[4] = { + 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU +}; +#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, const sp_digit* a, const sp_digit* b) +{ + sp_256_mul_10(r, a, b); + sp_256_mont_reduce_order_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, const sp_digit* a) +{ + sp_256_sqr_10(r, a); + sp_256_mont_reduce_order_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, const 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_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_10(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 10U); +#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 (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + 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 (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + 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 (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + 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 (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + 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 */ +} + +#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, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#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_256 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_256* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int32_t c; + int i; + + (void)heap; + + err = sp_256_point_new_10(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 10, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 10; + x = d + 2 * 10; + k = d + 4 * 10; + r = d + 6 * 10; + tmp = d + 8 * 10; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(e, 10, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 10, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_10(rng, k); + } + else { + sp_256_from_mp(k, 10, km); + mp_zero(km); + } + if (err == MP_OKAY) { + 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) * 10U); + sp_256_norm_10(r); + c = sp_256_cmp_10(r, p256_order); + sp_256_cond_sub_10(r, r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_10(r); + + /* Conv k to Montgomery form (mod order) */ + 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 */ + sp_256_mont_inv_order_10(kInv, k, tmp); + sp_256_norm_10(kInv); + + /* s = r * x + e */ + 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, 0L - (sp_digit)(c >= 0)); + sp_256_norm_10(s); + + /* s = s * k^-1 mod order */ + 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) == 0) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 10); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 10U); +#endif + sp_256_point_free_10(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_256 p1d; + sp_point_256 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p1; + sp_point_256* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + + err = sp_256_point_new_10(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_256_point_new_10(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 10, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 10; + u2 = d + 2 * 10; + s = d + 4 * 10; + tmp = d + 6 * 10; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 10, hash, (int)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); + + { + 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); + { + 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); + } + + err = sp_256_ecc_mulmod_base_10(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_10(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + { + sp_256_proj_point_add_10(p1, p1, p2, tmp); + if (sp_256_iszero_10(p1->z)) { + if (sp_256_iszero_10(p1->x) && sp_256_iszero_10(p1->y)) { + sp_256_proj_point_dbl_10(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + p1->x[8] = 0; + p1->x[9] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + } + + /* (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 = (int)(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 == 0) { + 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 = (int)(sp_256_cmp_10(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_256_point_free_10(p1, 0, heap); + sp_256_point_free_10(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_10(sp_point_256* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*10]; + sp_digit t2d[2*10]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 10; + t2 = d + 2 * 10; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_256_sqr_10(t1, point->y); + (void)sp_256_mod_10(t1, t1, p256_mod); + sp_256_sqr_10(t2, point->x); + (void)sp_256_mod_10(t2, t2, p256_mod); + sp_256_mul_10(t2, t2, point->x); + (void)sp_256_mod_10(t2, t2, p256_mod); + (void)sp_256_sub_10(t2, p256_mod, t2); + sp_256_mont_add_10(t1, t1, t2, p256_mod); + + sp_256_mont_add_10(t1, t1, point->x, p256_mod); + sp_256_mont_add_10(t1, t1, point->x, p256_mod); + sp_256_mont_add_10(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_10(t1, p256_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 pubd; +#endif + sp_point_256* pub; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_10(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 10, pX); + sp_256_from_mp(pub->y, 10, pY); + sp_256_from_bin(pub->z, 10, one, (int)sizeof(one)); + + err = sp_256_ecc_is_point_10(pub, NULL); + } + + sp_256_point_free_10(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[10]; + sp_point_256 pubd; + sp_point_256 pd; +#endif + sp_digit* priv = NULL; + sp_point_256* pub; + sp_point_256* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_10(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_256_point_new_10(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_256_from_mp(pub->x, 10, pX); + sp_256_from_mp(pub->y, 10, pY); + sp_256_from_bin(pub->z, 10, one, (int)sizeof(one)); + sp_256_from_mp(priv, 10, privm); + + /* Check point at infinitiy. */ + if ((sp_256_iszero_10(pub->x) != 0) && + (sp_256_iszero_10(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_10(pub->x, p256_mod) >= 0 || + sp_256_cmp_10(pub->y, p256_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_10(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_256_ecc_mulmod_10(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_256_iszero_10(p->x) == 0) || + (sp_256_iszero_10(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_256_ecc_mulmod_base_10(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_10(p->x, pub->x) != 0 || + sp_256_cmp_10(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_10(p, 0, heap); + sp_256_point_free_10(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 10 * 5]; + sp_point_256 pd; + sp_point_256 qd; +#endif + sp_digit* tmp; + sp_point_256* p; + sp_point_256* q = NULL; + int err; + + err = sp_256_point_new_10(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_256_point_new_10(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 10, pX); + sp_256_from_mp(p->y, 10, pY); + sp_256_from_mp(p->z, 10, pZ); + sp_256_from_mp(q->x, 10, qX); + sp_256_from_mp(q->y, 10, qY); + sp_256_from_mp(q->z, 10, qZ); + + sp_256_proj_point_add_10(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_10(q, 0, NULL); + sp_256_point_free_10(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 10 * 2]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_10(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 10, pX); + sp_256_from_mp(p->y, 10, pY); + sp_256_from_mp(p->z, 10, pZ); + + sp_256_proj_point_dbl_10(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_10(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 10 * 4]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_10(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 10, pX); + sp_256_from_mp(p->y, 10, pY); + sp_256_from_mp(p->z, 10, pZ); + + sp_256_map_10(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_10(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_10(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 10]; + sp_digit t2d[2 * 10]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 10; + t2 = d + 2 * 10; +#else + t1 = t1d; + t2 = t2d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_10(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_10(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_10(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_10(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_10(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_10(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_10(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_10(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_10(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_10(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_10(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 10]; + sp_digit yd[2 * 10]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 10; + y = d + 2 * 10; +#else + x = xd; + y = yd; +#endif + + sp_256_from_mp(x, 10, xm); + err = sp_256_mod_mul_norm_10(x, x, p256_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_10(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_10(y, y, x, p256_mod); + sp_256_mont_sub_10(y, y, x, p256_mod); + sp_256_mont_sub_10(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_10(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_10(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_10(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 10, 0, 10U * sizeof(sp_digit)); + sp_256_mont_reduce_10(y, p256_mod, p256_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_256_mont_sub_10(y, p256_mod, y, p256_mod); + } + + err = sp_256_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#ifdef WOLFSSL_SP_384 + +/* Point structure to use. */ +typedef struct sp_point_384 { + sp_digit x[2 * 15]; + sp_digit y[2 * 15]; + sp_digit z[2 * 15]; + int infinity; +} sp_point_384; + +/* The modulus (prime) of the curve P384. */ +static const sp_digit p384_mod[15] = { + 0x3ffffff,0x000003f,0x0000000,0x3fc0000,0x2ffffff,0x3ffffff,0x3ffffff, + 0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x00fffff + +}; +/* The Montogmery normalizer for modulus of the curve P384. */ +static const sp_digit p384_norm_mod[15] = { + 0x0000001,0x3ffffc0,0x3ffffff,0x003ffff,0x1000000,0x0000000,0x0000000, + 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000 + +}; +/* The Montogmery multiplier for modulus of the curve P384. */ +static sp_digit p384_mp_mod = 0x000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P384. */ +static const sp_digit p384_order[15] = { + 0x0c52973,0x3065ab3,0x277aece,0x2c922c2,0x3581a0d,0x10dcb77,0x234d81f, + 0x3ffff1d,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x00fffff + +}; +#endif +/* The order of the curve P384 minus 2. */ +static const sp_digit p384_order2[15] = { + 0x0c52971,0x3065ab3,0x277aece,0x2c922c2,0x3581a0d,0x10dcb77,0x234d81f, + 0x3ffff1d,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x00fffff + +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P384. */ +static const sp_digit p384_norm_order[15] = { + 0x33ad68d,0x0f9a54c,0x1885131,0x136dd3d,0x0a7e5f2,0x2f23488,0x1cb27e0, + 0x00000e2,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000 + +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P384. */ +static sp_digit p384_mp_order = 0x8fdc45; +#endif +/* The base point of curve P384. */ +static const sp_point_384 p384_base = { + /* X ordinate */ + { + 0x2760ab7,0x1178e1c,0x296c3a5,0x176fd54,0x05502f2,0x0950a8e,0x3741e08, + 0x26e6167,0x3628ba7,0x11b874e,0x3320ad7,0x2c71c7b,0x305378e,0x288afa2,0x00aa87c, + + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x0ea0e5f,0x0c75f24,0x019d7a4,0x33875fa,0x00a60b1,0x17c2e30,0x1a3113b, + 0x051f3a7,0x1bd289a,0x27e3d07,0x1292dc2,0x27a62fe,0x22c6f5d,0x392a589,0x003617d, + + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p384_b[15] = { + 0x3ec2aef,0x1723b74,0x119d2a8,0x23628bb,0x2c65639,0x004e1d6,0x14088f5, + 0x104480c,0x06efe81,0x2460767,0x23f82d1,0x23815af,0x2e7e498,0x3e9f88f,0x00b3312 + +}; +#endif + +static int sp_384_point_new_ex_15(void* heap, sp_point_384* sp, sp_point_384** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_384_point_new_15(heap, sp, p) sp_384_point_new_ex_15((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_384_point_new_15(heap, sp, p) sp_384_point_new_ex_15((heap), &(sp), &(p)) +#endif + + +static void sp_384_point_free_15(sp_point_384* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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_384_mod_mul_norm_15(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* td; +#else + int64_t td[12]; + int64_t a32d[12]; +#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)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + a32 = td + 12; +#else + t = td; + a32 = a32d; +#endif + + a32[0] = a[0]; + a32[0] |= a[1] << 26U; + a32[0] &= 0xffffffffL; + a32[1] = (sp_digit)(a[1] >> 6); + a32[1] |= a[2] << 20U; + a32[1] &= 0xffffffffL; + a32[2] = (sp_digit)(a[2] >> 12); + a32[2] |= a[3] << 14U; + a32[2] &= 0xffffffffL; + a32[3] = (sp_digit)(a[3] >> 18); + a32[3] |= a[4] << 8U; + a32[3] &= 0xffffffffL; + a32[4] = (sp_digit)(a[4] >> 24); + a32[4] |= a[5] << 2U; + a32[4] |= a[6] << 28U; + a32[4] &= 0xffffffffL; + a32[5] = (sp_digit)(a[6] >> 4); + a32[5] |= a[7] << 22U; + a32[5] &= 0xffffffffL; + a32[6] = (sp_digit)(a[7] >> 10); + a32[6] |= a[8] << 16U; + a32[6] &= 0xffffffffL; + a32[7] = (sp_digit)(a[8] >> 16); + a32[7] |= a[9] << 10U; + a32[7] &= 0xffffffffL; + a32[8] = (sp_digit)(a[9] >> 22); + a32[8] |= a[10] << 4U; + a32[8] |= a[11] << 30U; + a32[8] &= 0xffffffffL; + a32[9] = (sp_digit)(a[11] >> 2); + a32[9] |= a[12] << 24U; + a32[9] &= 0xffffffffL; + a32[10] = (sp_digit)(a[12] >> 8); + a32[10] |= a[13] << 18U; + a32[10] &= 0xffffffffL; + a32[11] = (sp_digit)(a[13] >> 14); + a32[11] |= a[14] << 12U; + a32[11] &= 0xffffffffL; + + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + a32[0] + a32[8] + a32[9] - a32[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - a32[0] + a32[1] - a32[8] + a32[10] + a32[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - a32[1] + a32[2] - a32[9] + a32[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + a32[0] - a32[2] + a32[3] + a32[8] + a32[9] - a32[10] - a32[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + a32[0] + a32[1] - a32[3] + a32[4] + a32[8] + 2 * a32[9] + a32[10] - 2 * a32[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + a32[1] + a32[2] - a32[4] + a32[5] + a32[9] + 2 * a32[10] + a32[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + a32[2] + a32[3] - a32[5] + a32[6] + a32[10] + 2 * a32[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + a32[3] + a32[4] - a32[6] + a32[7] + a32[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + a32[4] + a32[5] - a32[7] + a32[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + a32[5] + a32[6] - a32[8] + a32[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + a32[6] + a32[7] - a32[9] + a32[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + a32[7] + a32[8] - a32[10] + a32[11]; + + 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + + r[0] = (sp_digit)(t[0]) & 0x3ffffffL; + r[1] = (sp_digit)(t[0] >> 26U); + r[1] |= t[1] << 6U; + r[1] &= 0x3ffffffL; + r[2] = (sp_digit)(t[1] >> 20U); + r[2] |= t[2] << 12U; + r[2] &= 0x3ffffffL; + r[3] = (sp_digit)(t[2] >> 14U); + r[3] |= t[3] << 18U; + r[3] &= 0x3ffffffL; + r[4] = (sp_digit)(t[3] >> 8U); + r[4] |= t[4] << 24U; + r[4] &= 0x3ffffffL; + r[5] = (sp_digit)(t[4] >> 2U) & 0x3ffffffL; + r[6] = (sp_digit)(t[4] >> 28U); + r[6] |= t[5] << 4U; + r[6] &= 0x3ffffffL; + r[7] = (sp_digit)(t[5] >> 22U); + r[7] |= t[6] << 10U; + r[7] &= 0x3ffffffL; + r[8] = (sp_digit)(t[6] >> 16U); + r[8] |= t[7] << 16U; + r[8] &= 0x3ffffffL; + r[9] = (sp_digit)(t[7] >> 10U); + r[9] |= t[8] << 22U; + r[9] &= 0x3ffffffL; + r[10] = (sp_digit)(t[8] >> 4U) & 0x3ffffffL; + r[11] = (sp_digit)(t[8] >> 30U); + r[11] |= t[9] << 2U; + r[11] &= 0x3ffffffL; + r[12] = (sp_digit)(t[9] >> 24U); + r[12] |= t[10] << 8U; + r[12] &= 0x3ffffffL; + r[13] = (sp_digit)(t[10] >> 18U); + r[13] |= t[11] << 14U; + r[13] &= 0x3ffffffL; + r[14] = (sp_digit)(t[11] >> 12U); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 26 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 26 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x3ffffff; + s = 26U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 26U) <= (word32)DIGIT_BIT) { + s += 26U; + r[j] &= 0x3ffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 26) { + r[j] &= 0x3ffffff; + if (j + 1 >= size) { + break; + } + s = 26 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_15(sp_point_384* p, const 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_384_from_mp(p->x, 15, pm->x); + sp_384_from_mp(p->y, 15, pm->y); + sp_384_from_mp(p->z, 15, 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_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 26 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 15); + r->used = 15; + mp_clamp(r); +#elif DIGIT_BIT < 26 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 15; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 26) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 26 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 15; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 26 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + 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 = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_15(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + +#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. + */ +SP_NOINLINE static void sp_384_mul_15(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[14]) * b[14]; + r[29] = (sp_digit)(c >> 26); + c = (c & 0x3ffffff) << 26; + for (k = 27; k >= 0; k--) { + for (i = 14; i >= 0; i--) { + j = k - i; + if (j >= 15) { + 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. + */ +SP_NOINLINE static void sp_384_mul_15(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[ 0]) * b[10] + + ((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)a[10]) * b[ 0]; + int64_t t11 = ((int64_t)a[ 0]) * b[11] + + ((int64_t)a[ 1]) * b[10] + + ((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)a[10]) * b[ 1] + + ((int64_t)a[11]) * b[ 0]; + int64_t t12 = ((int64_t)a[ 0]) * b[12] + + ((int64_t)a[ 1]) * b[11] + + ((int64_t)a[ 2]) * b[10] + + ((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)a[10]) * b[ 2] + + ((int64_t)a[11]) * b[ 1] + + ((int64_t)a[12]) * b[ 0]; + int64_t t13 = ((int64_t)a[ 0]) * b[13] + + ((int64_t)a[ 1]) * b[12] + + ((int64_t)a[ 2]) * b[11] + + ((int64_t)a[ 3]) * b[10] + + ((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)a[10]) * b[ 3] + + ((int64_t)a[11]) * b[ 2] + + ((int64_t)a[12]) * b[ 1] + + ((int64_t)a[13]) * b[ 0]; + int64_t t14 = ((int64_t)a[ 0]) * b[14] + + ((int64_t)a[ 1]) * b[13] + + ((int64_t)a[ 2]) * b[12] + + ((int64_t)a[ 3]) * b[11] + + ((int64_t)a[ 4]) * b[10] + + ((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)a[10]) * b[ 4] + + ((int64_t)a[11]) * b[ 3] + + ((int64_t)a[12]) * b[ 2] + + ((int64_t)a[13]) * b[ 1] + + ((int64_t)a[14]) * b[ 0]; + int64_t t15 = ((int64_t)a[ 1]) * b[14] + + ((int64_t)a[ 2]) * b[13] + + ((int64_t)a[ 3]) * b[12] + + ((int64_t)a[ 4]) * b[11] + + ((int64_t)a[ 5]) * b[10] + + ((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)a[10]) * b[ 5] + + ((int64_t)a[11]) * b[ 4] + + ((int64_t)a[12]) * b[ 3] + + ((int64_t)a[13]) * b[ 2] + + ((int64_t)a[14]) * b[ 1]; + int64_t t16 = ((int64_t)a[ 2]) * b[14] + + ((int64_t)a[ 3]) * b[13] + + ((int64_t)a[ 4]) * b[12] + + ((int64_t)a[ 5]) * b[11] + + ((int64_t)a[ 6]) * b[10] + + ((int64_t)a[ 7]) * b[ 9] + + ((int64_t)a[ 8]) * b[ 8] + + ((int64_t)a[ 9]) * b[ 7] + + ((int64_t)a[10]) * b[ 6] + + ((int64_t)a[11]) * b[ 5] + + ((int64_t)a[12]) * b[ 4] + + ((int64_t)a[13]) * b[ 3] + + ((int64_t)a[14]) * b[ 2]; + int64_t t17 = ((int64_t)a[ 3]) * b[14] + + ((int64_t)a[ 4]) * b[13] + + ((int64_t)a[ 5]) * b[12] + + ((int64_t)a[ 6]) * b[11] + + ((int64_t)a[ 7]) * b[10] + + ((int64_t)a[ 8]) * b[ 9] + + ((int64_t)a[ 9]) * b[ 8] + + ((int64_t)a[10]) * b[ 7] + + ((int64_t)a[11]) * b[ 6] + + ((int64_t)a[12]) * b[ 5] + + ((int64_t)a[13]) * b[ 4] + + ((int64_t)a[14]) * b[ 3]; + int64_t t18 = ((int64_t)a[ 4]) * b[14] + + ((int64_t)a[ 5]) * b[13] + + ((int64_t)a[ 6]) * b[12] + + ((int64_t)a[ 7]) * b[11] + + ((int64_t)a[ 8]) * b[10] + + ((int64_t)a[ 9]) * b[ 9] + + ((int64_t)a[10]) * b[ 8] + + ((int64_t)a[11]) * b[ 7] + + ((int64_t)a[12]) * b[ 6] + + ((int64_t)a[13]) * b[ 5] + + ((int64_t)a[14]) * b[ 4]; + int64_t t19 = ((int64_t)a[ 5]) * b[14] + + ((int64_t)a[ 6]) * b[13] + + ((int64_t)a[ 7]) * b[12] + + ((int64_t)a[ 8]) * b[11] + + ((int64_t)a[ 9]) * b[10] + + ((int64_t)a[10]) * b[ 9] + + ((int64_t)a[11]) * b[ 8] + + ((int64_t)a[12]) * b[ 7] + + ((int64_t)a[13]) * b[ 6] + + ((int64_t)a[14]) * b[ 5]; + int64_t t20 = ((int64_t)a[ 6]) * b[14] + + ((int64_t)a[ 7]) * b[13] + + ((int64_t)a[ 8]) * b[12] + + ((int64_t)a[ 9]) * b[11] + + ((int64_t)a[10]) * b[10] + + ((int64_t)a[11]) * b[ 9] + + ((int64_t)a[12]) * b[ 8] + + ((int64_t)a[13]) * b[ 7] + + ((int64_t)a[14]) * b[ 6]; + int64_t t21 = ((int64_t)a[ 7]) * b[14] + + ((int64_t)a[ 8]) * b[13] + + ((int64_t)a[ 9]) * b[12] + + ((int64_t)a[10]) * b[11] + + ((int64_t)a[11]) * b[10] + + ((int64_t)a[12]) * b[ 9] + + ((int64_t)a[13]) * b[ 8] + + ((int64_t)a[14]) * b[ 7]; + int64_t t22 = ((int64_t)a[ 8]) * b[14] + + ((int64_t)a[ 9]) * b[13] + + ((int64_t)a[10]) * b[12] + + ((int64_t)a[11]) * b[11] + + ((int64_t)a[12]) * b[10] + + ((int64_t)a[13]) * b[ 9] + + ((int64_t)a[14]) * b[ 8]; + int64_t t23 = ((int64_t)a[ 9]) * b[14] + + ((int64_t)a[10]) * b[13] + + ((int64_t)a[11]) * b[12] + + ((int64_t)a[12]) * b[11] + + ((int64_t)a[13]) * b[10] + + ((int64_t)a[14]) * b[ 9]; + int64_t t24 = ((int64_t)a[10]) * b[14] + + ((int64_t)a[11]) * b[13] + + ((int64_t)a[12]) * b[12] + + ((int64_t)a[13]) * b[11] + + ((int64_t)a[14]) * b[10]; + int64_t t25 = ((int64_t)a[11]) * b[14] + + ((int64_t)a[12]) * b[13] + + ((int64_t)a[13]) * b[12] + + ((int64_t)a[14]) * b[11]; + int64_t t26 = ((int64_t)a[12]) * b[14] + + ((int64_t)a[13]) * b[13] + + ((int64_t)a[14]) * b[12]; + int64_t t27 = ((int64_t)a[13]) * b[14] + + ((int64_t)a[14]) * b[13]; + int64_t t28 = ((int64_t)a[14]) * b[14]; + + 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; + t19 += t18 >> 26; r[18] = t18 & 0x3ffffff; + t20 += t19 >> 26; r[19] = t19 & 0x3ffffff; + t21 += t20 >> 26; r[20] = t20 & 0x3ffffff; + t22 += t21 >> 26; r[21] = t21 & 0x3ffffff; + t23 += t22 >> 26; r[22] = t22 & 0x3ffffff; + t24 += t23 >> 26; r[23] = t23 & 0x3ffffff; + t25 += t24 >> 26; r[24] = t24 & 0x3ffffff; + t26 += t25 >> 26; r[25] = t25 & 0x3ffffff; + t27 += t26 >> 26; r[26] = t26 & 0x3ffffff; + t28 += t27 >> 26; r[27] = t27 & 0x3ffffff; + r[29] = (sp_digit)(t28 >> 26); + r[28] = t28 & 0x3ffffff; +} + +#endif /* WOLFSSL_SP_SMALL */ +#define sp_384_mont_reduce_order_15 sp_384_mont_reduce_15 + +/* 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_384_cmp_15(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=14; i>=0; i--) { + r |= (a[i] - b[i]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + r |= (a[14] - b[14]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[13] - b[13]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[12] - b[12]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[11] - b[11]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[10] - b[10]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 9] - b[ 9]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 8] - b[ 8]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 7] - b[ 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 6] - b[ 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 5] - b[ 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 4] - b[ 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 3] - b[ 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 2] - b[ 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 1] - b[ 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 0] - b[ 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); +#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_384_cond_sub_15(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 < 15; 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); + r[10] = a[10] - (b[10] & m); + r[11] = a[11] - (b[11] & m); + r[12] = a[12] - (b[12] & m); + r[13] = a[13] - (b[13] & m); + r[14] = a[14] - (b[14] & 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. + */ +SP_NOINLINE static void sp_384_mul_add_15(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 < 15; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x3ffffff; + t >>= 26; + } + r[15] += t; +#else + int64_t tb = b; + int64_t t[15]; + + 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]; + t[10] = tb * a[10]; + t[11] = tb * a[11]; + t[12] = tb * a[12]; + t[13] = tb * a[13]; + t[14] = tb * a[14]; + r[ 0] += (sp_digit) (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) + (t[10] & 0x3ffffff)); + r[11] += (sp_digit)((t[10] >> 26) + (t[11] & 0x3ffffff)); + r[12] += (sp_digit)((t[11] >> 26) + (t[12] & 0x3ffffff)); + r[13] += (sp_digit)((t[12] >> 26) + (t[13] & 0x3ffffff)); + r[14] += (sp_digit)((t[13] >> 26) + (t[14] & 0x3ffffff)); + r[15] += (sp_digit) (t[14] >> 26); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 26. + * + * a Array of sp_digit to normalize. + */ +static void sp_384_norm_15(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 14; 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; + a[10] += a[9] >> 26; a[9] &= 0x3ffffff; + a[11] += a[10] >> 26; a[10] &= 0x3ffffff; + a[12] += a[11] >> 26; a[11] &= 0x3ffffff; + a[13] += a[12] >> 26; a[12] &= 0x3ffffff; + a[14] += a[13] >> 26; a[13] &= 0x3ffffff; +#endif +} + +/* Shift the result in the high 384 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_384_mont_shift_15(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int64_t n = a[14] >> 20; + n += ((int64_t)a[15]) << 6; + + for (i = 0; i < 14; i++) { + r[i] = n & 0x3ffffff; + n >>= 26; + n += ((int64_t)a[16 + i]) << 6; + } + r[14] = (sp_digit)n; +#else + int64_t n = a[14] >> 20; + n += ((int64_t)a[15]) << 6; + r[ 0] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[16]) << 6; + r[ 1] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[17]) << 6; + r[ 2] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[18]) << 6; + r[ 3] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[19]) << 6; + r[ 4] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[20]) << 6; + r[ 5] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[21]) << 6; + r[ 6] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[22]) << 6; + r[ 7] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[23]) << 6; + r[ 8] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[24]) << 6; + r[ 9] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[25]) << 6; + r[10] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[26]) << 6; + r[11] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[27]) << 6; + r[12] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[28]) << 6; + r[13] = n & 0x3ffffff; n >>= 26; n += ((int64_t)a[29]) << 6; + r[14] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[15], 0, sizeof(*r) * 15U); +} + +/* Reduce the number back to 384 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_384_mont_reduce_15(sp_digit* a, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_384_norm_15(a + 15); + + for (i=0; i<14; i++) { + mu = (a[i] * mp) & 0x3ffffff; + sp_384_mul_add_15(a+i, m, mu); + a[i+1] += a[i] >> 26; + } + mu = (a[i] * mp) & 0xfffffL; + sp_384_mul_add_15(a+i, m, mu); + a[i+1] += a[i] >> 26; + a[i] &= 0x3ffffff; + + sp_384_mont_shift_15(a, a); + sp_384_cond_sub_15(a, a, m, 0 - (((a[14] >> 20) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_15(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_384_mont_mul_15(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_384_mul_15(r, a, b); + sp_384_mont_reduce_15(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. + */ +SP_NOINLINE static void sp_384_sqr_15(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[14]) * a[14]; + r[29] = (sp_digit)(c >> 26); + c = (c & 0x3ffffff) << 26; + for (k = 27; k >= 0; k--) { + for (i = 14; i >= 0; i--) { + j = k - i; + if (j >= 15 || 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. + */ +SP_NOINLINE static void sp_384_sqr_15(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[ 0]) * a[10] + + ((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[ 0]) * a[11] + + ((int64_t)a[ 1]) * a[10] + + ((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[ 0]) * a[12] + + ((int64_t)a[ 1]) * a[11] + + ((int64_t)a[ 2]) * a[10] + + ((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[ 0]) * a[13] + + ((int64_t)a[ 1]) * a[12] + + ((int64_t)a[ 2]) * a[11] + + ((int64_t)a[ 3]) * a[10] + + ((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[ 0]) * a[14] + + ((int64_t)a[ 1]) * a[13] + + ((int64_t)a[ 2]) * a[12] + + ((int64_t)a[ 3]) * a[11] + + ((int64_t)a[ 4]) * a[10] + + ((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[ 1]) * a[14] + + ((int64_t)a[ 2]) * a[13] + + ((int64_t)a[ 3]) * a[12] + + ((int64_t)a[ 4]) * a[11] + + ((int64_t)a[ 5]) * a[10] + + ((int64_t)a[ 6]) * a[ 9] + + ((int64_t)a[ 7]) * a[ 8]) * 2; + int64_t t16 = (((int64_t)a[ 2]) * a[14] + + ((int64_t)a[ 3]) * a[13] + + ((int64_t)a[ 4]) * a[12] + + ((int64_t)a[ 5]) * a[11] + + ((int64_t)a[ 6]) * a[10] + + ((int64_t)a[ 7]) * a[ 9]) * 2 + + ((int64_t)a[ 8]) * a[ 8]; + int64_t t17 = (((int64_t)a[ 3]) * a[14] + + ((int64_t)a[ 4]) * a[13] + + ((int64_t)a[ 5]) * a[12] + + ((int64_t)a[ 6]) * a[11] + + ((int64_t)a[ 7]) * a[10] + + ((int64_t)a[ 8]) * a[ 9]) * 2; + int64_t t18 = (((int64_t)a[ 4]) * a[14] + + ((int64_t)a[ 5]) * a[13] + + ((int64_t)a[ 6]) * a[12] + + ((int64_t)a[ 7]) * a[11] + + ((int64_t)a[ 8]) * a[10]) * 2 + + ((int64_t)a[ 9]) * a[ 9]; + int64_t t19 = (((int64_t)a[ 5]) * a[14] + + ((int64_t)a[ 6]) * a[13] + + ((int64_t)a[ 7]) * a[12] + + ((int64_t)a[ 8]) * a[11] + + ((int64_t)a[ 9]) * a[10]) * 2; + int64_t t20 = (((int64_t)a[ 6]) * a[14] + + ((int64_t)a[ 7]) * a[13] + + ((int64_t)a[ 8]) * a[12] + + ((int64_t)a[ 9]) * a[11]) * 2 + + ((int64_t)a[10]) * a[10]; + int64_t t21 = (((int64_t)a[ 7]) * a[14] + + ((int64_t)a[ 8]) * a[13] + + ((int64_t)a[ 9]) * a[12] + + ((int64_t)a[10]) * a[11]) * 2; + int64_t t22 = (((int64_t)a[ 8]) * a[14] + + ((int64_t)a[ 9]) * a[13] + + ((int64_t)a[10]) * a[12]) * 2 + + ((int64_t)a[11]) * a[11]; + int64_t t23 = (((int64_t)a[ 9]) * a[14] + + ((int64_t)a[10]) * a[13] + + ((int64_t)a[11]) * a[12]) * 2; + int64_t t24 = (((int64_t)a[10]) * a[14] + + ((int64_t)a[11]) * a[13]) * 2 + + ((int64_t)a[12]) * a[12]; + int64_t t25 = (((int64_t)a[11]) * a[14] + + ((int64_t)a[12]) * a[13]) * 2; + int64_t t26 = (((int64_t)a[12]) * a[14]) * 2 + + ((int64_t)a[13]) * a[13]; + int64_t t27 = (((int64_t)a[13]) * a[14]) * 2; + int64_t t28 = ((int64_t)a[14]) * a[14]; + + 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; + t19 += t18 >> 26; r[18] = t18 & 0x3ffffff; + t20 += t19 >> 26; r[19] = t19 & 0x3ffffff; + t21 += t20 >> 26; r[20] = t20 & 0x3ffffff; + t22 += t21 >> 26; r[21] = t21 & 0x3ffffff; + t23 += t22 >> 26; r[22] = t22 & 0x3ffffff; + t24 += t23 >> 26; r[23] = t23 & 0x3ffffff; + t25 += t24 >> 26; r[24] = t24 & 0x3ffffff; + t26 += t25 >> 26; r[25] = t25 & 0x3ffffff; + t27 += t26 >> 26; r[26] = t26 & 0x3ffffff; + t28 += t27 >> 26; r[27] = t27 & 0x3ffffff; + r[29] = (sp_digit)(t28 >> 26); + r[28] = t28 & 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_384_mont_sqr_15(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_384_sqr_15(r, a); + sp_384_mont_reduce_15(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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_384_mont_sqr_n_15(sp_digit* r, const sp_digit* a, int n, + const sp_digit* m, sp_digit mp) +{ + sp_384_mont_sqr_15(r, a, m, mp); + for (; n > 1; n--) { + sp_384_mont_sqr_15(r, r, m, mp); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P384 curve. */ +static const uint32_t p384_mod_minus_2[12] = { + 0xfffffffdU,0x00000000U,0x00000000U,0xffffffffU,0xfffffffeU,0xffffffffU, + 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P384 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_384_mont_inv_15(sp_digit* r, const sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 15); + for (i=382; i>=0; i--) { + sp_384_mont_sqr_15(t, t, p384_mod, p384_mp_mod); + if (p384_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_384_mont_mul_15(t, t, a, p384_mod, p384_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 15); +#else + sp_digit* t1 = td; + sp_digit* t2 = td + 2 * 15; + sp_digit* t3 = td + 4 * 15; + sp_digit* t4 = td + 6 * 15; + sp_digit* t5 = td + 8 * 15; + + /* 0x2 */ + sp_384_mont_sqr_15(t1, a, p384_mod, p384_mp_mod); + /* 0x3 */ + sp_384_mont_mul_15(t5, t1, a, p384_mod, p384_mp_mod); + /* 0xc */ + sp_384_mont_sqr_n_15(t1, t5, 2, p384_mod, p384_mp_mod); + /* 0xf */ + sp_384_mont_mul_15(t2, t5, t1, p384_mod, p384_mp_mod); + /* 0x1e */ + sp_384_mont_sqr_15(t1, t2, p384_mod, p384_mp_mod); + /* 0x1f */ + sp_384_mont_mul_15(t4, t1, a, p384_mod, p384_mp_mod); + /* 0x3e0 */ + sp_384_mont_sqr_n_15(t1, t4, 5, p384_mod, p384_mp_mod); + /* 0x3ff */ + sp_384_mont_mul_15(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0x7fe0 */ + sp_384_mont_sqr_n_15(t1, t2, 5, p384_mod, p384_mp_mod); + /* 0x7fff */ + sp_384_mont_mul_15(t4, t4, t1, p384_mod, p384_mp_mod); + /* 0x3fff8000 */ + sp_384_mont_sqr_n_15(t1, t4, 15, p384_mod, p384_mp_mod); + /* 0x3fffffff */ + sp_384_mont_mul_15(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffc */ + sp_384_mont_sqr_n_15(t3, t2, 2, p384_mod, p384_mp_mod); + /* 0xfffffffd */ + sp_384_mont_mul_15(r, t3, a, p384_mod, p384_mp_mod); + /* 0xffffffff */ + sp_384_mont_mul_15(t3, t5, t3, p384_mod, p384_mp_mod); + /* 0xfffffffc0000000 */ + sp_384_mont_sqr_n_15(t1, t2, 30, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff */ + sp_384_mont_mul_15(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_15(t1, t2, 60, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_15(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_15(t1, t2, 120, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_15(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_15(t1, t2, 15, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_15(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */ + sp_384_mont_sqr_n_15(t1, t2, 33, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */ + sp_384_mont_mul_15(t2, t3, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_15(t1, t2, 96, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */ + sp_384_mont_mul_15(r, r, t1, p384_mod, p384_mp_mod); + +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_384_map_15(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*15; + int32_t n; + + sp_384_mont_inv_15(t1, p->z, t + 2*15); + + sp_384_mont_sqr_15(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t1, t2, t1, p384_mod, p384_mp_mod); + + /* x /= z^2 */ + sp_384_mont_mul_15(r->x, p->x, t2, p384_mod, p384_mp_mod); + XMEMSET(r->x + 15, 0, sizeof(r->x) / 2U); + sp_384_mont_reduce_15(r->x, p384_mod, p384_mp_mod); + /* Reduce x to less than modulus */ + n = sp_384_cmp_15(r->x, p384_mod); + sp_384_cond_sub_15(r->x, r->x, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_15(r->x); + + /* y /= z^3 */ + sp_384_mont_mul_15(r->y, p->y, t1, p384_mod, p384_mp_mod); + XMEMSET(r->y + 15, 0, sizeof(r->y) / 2U); + sp_384_mont_reduce_15(r->y, p384_mod, p384_mp_mod); + /* Reduce y to less than modulus */ + n = sp_384_cmp_15(r->y, p384_mod); + sp_384_cond_sub_15(r->y, r->y, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_15(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. + */ +SP_NOINLINE static int sp_384_add_15(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 15; 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. + */ +SP_NOINLINE static int sp_384_add_15(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]; + r[10] = a[10] + b[10]; + r[11] = a[11] + b[11]; + r[12] = a[12] + b[12]; + r[13] = a[13] + b[13]; + r[14] = a[14] + b[14]; + + 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_384_mont_add_15(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)sp_384_add_15(r, a, b); + sp_384_norm_15(r); + sp_384_cond_sub_15(r, r, m, 0 - (((r[14] >> 20) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_15(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_384_mont_dbl_15(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)sp_384_add_15(r, a, a); + sp_384_norm_15(r); + sp_384_cond_sub_15(r, r, m, 0 - (((r[14] >> 20) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_15(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_384_mont_tpl_15(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)sp_384_add_15(r, a, a); + sp_384_norm_15(r); + sp_384_cond_sub_15(r, r, m, 0 - (((r[14] >> 20) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_15(r); + (void)sp_384_add_15(r, r, a); + sp_384_norm_15(r); + sp_384_cond_sub_15(r, r, m, 0 - (((r[14] >> 20) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_15(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. + */ +SP_NOINLINE static int sp_384_sub_15(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 15; 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. + */ +SP_NOINLINE static int sp_384_sub_15(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]; + r[10] = a[10] - b[10]; + r[11] = a[11] - b[11]; + r[12] = a[12] - b[12]; + r[13] = a[13] - b[13]; + r[14] = a[14] - b[14]; + + 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_384_cond_add_15(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 < 15; 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); + r[10] = a[10] + (b[10] & m); + r[11] = a[11] + (b[11] & m); + r[12] = a[12] + (b[12] & m); + r[13] = a[13] + (b[13] & m); + r[14] = a[14] + (b[14] & 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_384_mont_sub_15(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)sp_384_sub_15(r, a, b); + sp_384_cond_add_15(r, r, m, r[14] >> 20); + sp_384_norm_15(r); +} + +/* Shift number left one bit. + * Bottom bit is lost. + * + * r Result of shift. + * a Number to shift. + */ +SP_NOINLINE static void sp_384_rshift1_15(sp_digit* r, sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<14; 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; + r[9] = ((a[9] >> 1) | (a[10] << 25)) & 0x3ffffff; + r[10] = ((a[10] >> 1) | (a[11] << 25)) & 0x3ffffff; + r[11] = ((a[11] >> 1) | (a[12] << 25)) & 0x3ffffff; + r[12] = ((a[12] >> 1) | (a[13] << 25)) & 0x3ffffff; + r[13] = ((a[13] >> 1) | (a[14] << 25)) & 0x3ffffff; +#endif + r[14] = a[14] >> 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_384_div2_15(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_384_cond_add_15(r, a, m, 0 - (a[0] & 1)); + sp_384_norm_15(r); + sp_384_rshift1_15(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_384_proj_point_dbl_15(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*15; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_384_mont_sqr_15(t1, p->z, p384_mod, p384_mp_mod); + /* Z = Y * Z */ + sp_384_mont_mul_15(z, p->y, p->z, p384_mod, p384_mp_mod); + /* Z = 2Z */ + sp_384_mont_dbl_15(z, z, p384_mod); + /* T2 = X - T1 */ + sp_384_mont_sub_15(t2, p->x, t1, p384_mod); + /* T1 = X + T1 */ + sp_384_mont_add_15(t1, p->x, t1, p384_mod); + /* T2 = T1 * T2 */ + sp_384_mont_mul_15(t2, t1, t2, p384_mod, p384_mp_mod); + /* T1 = 3T2 */ + sp_384_mont_tpl_15(t1, t2, p384_mod); + /* Y = 2Y */ + sp_384_mont_dbl_15(y, p->y, p384_mod); + /* Y = Y * Y */ + sp_384_mont_sqr_15(y, y, p384_mod, p384_mp_mod); + /* T2 = Y * Y */ + sp_384_mont_sqr_15(t2, y, p384_mod, p384_mp_mod); + /* T2 = T2/2 */ + sp_384_div2_15(t2, t2, p384_mod); + /* Y = Y * X */ + sp_384_mont_mul_15(y, y, p->x, p384_mod, p384_mp_mod); + /* X = T1 * T1 */ + sp_384_mont_sqr_15(x, t1, p384_mod, p384_mp_mod); + /* X = X - Y */ + sp_384_mont_sub_15(x, x, y, p384_mod); + /* X = X - Y */ + sp_384_mont_sub_15(x, x, y, p384_mod); + /* Y = Y - X */ + sp_384_mont_sub_15(y, y, x, p384_mod); + /* Y = Y * T1 */ + sp_384_mont_mul_15(y, y, t1, p384_mod, p384_mp_mod); + /* Y = Y - T2 */ + sp_384_mont_sub_15(y, y, t2, p384_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_384_cmp_equal_15(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]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) | + (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_15(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, + sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*15; + sp_digit* t3 = t + 4*15; + sp_digit* t4 = t + 6*15; + sp_digit* t5 = t + 8*15; + 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) { + const sp_point_384* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_384_sub_15(t1, p384_mod, q->y); + sp_384_norm_15(t1); + if ((sp_384_cmp_equal_15(p->x, q->x) & sp_384_cmp_equal_15(p->z, q->z) & + (sp_384_cmp_equal_15(p->y, q->y) | sp_384_cmp_equal_15(p->y, t1))) != 0) { + sp_384_proj_point_dbl_15(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<15; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<15; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<15; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_15(t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t3, t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t1, t1, x, p384_mod, p384_mp_mod); + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_15(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_15(t3, t3, y, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_15(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - U1 */ + sp_384_mont_sub_15(t2, t2, t1, p384_mod); + /* R = S2 - S1 */ + sp_384_mont_sub_15(t4, t4, t3, p384_mod); + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_15(z, z, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_15(x, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_15(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(y, t1, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_15(x, x, t5, p384_mod); + sp_384_mont_dbl_15(t1, y, p384_mod); + sp_384_mont_sub_15(x, x, t1, p384_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_15(y, y, x, p384_mod); + sp_384_mont_mul_15(y, y, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t5, t5, t3, p384_mod, p384_mp_mod); + sp_384_mont_sub_15(y, y, t5, p384_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifdef WOLFSSL_SP_NO_MALLOC + sp_point_384 t[3]; + sp_digit tmp[2 * 15 * 6]; +#else + sp_point_384* t; + sp_digit* tmp; +#endif + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + +#ifndef WOLFSSL_SP_NO_MALLOC + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_384) * 3); + + /* t[0] = {0, 0, 1} * norm */ + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_384_mod_mul_norm_15(t[1].x, g->x, p384_mod); + } + if (err == MP_OKAY) + err = sp_384_mod_mul_norm_15(t[1].y, g->y, p384_mod); + if (err == MP_OKAY) + err = sp_384_mod_mul_norm_15(t[1].z, g->z, p384_mod); + + if (err == MP_OKAY) { + i = 14; + c = 20; + 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_384_proj_point_add_15(&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_384)); + sp_384_proj_point_dbl_15(&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_384)); + } + + if (map != 0) { + sp_384_map_15(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_384)); + } + } + +#ifndef WOLFSSL_SP_NO_MALLOC + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 15 * 6); + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_384) * 3); + XFREE(t, NULL, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmp, sizeof(tmp)); + ForceZero(t, sizeof(t)); +#endif + + 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 coordinates. + * + * 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_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 t[3]; + sp_digit tmp[2 * 15 * 6]; +#else + sp_point_384* t; + sp_digit* tmp; +#endif + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point*)XMALLOC(sizeof(*t) * 3, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#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 */ + t[1].infinity = 0; + err = sp_384_mod_mul_norm_15(t[1].x, g->x, p384_mod); + } + if (err == MP_OKAY) + err = sp_384_mod_mul_norm_15(t[1].y, g->y, p384_mod); + if (err == MP_OKAY) + err = sp_384_mod_mul_norm_15(t[1].z, g->z, p384_mod); + + if (err == MP_OKAY) { + i = 14; + c = 20; + 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_384_proj_point_add_15(&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_384_proj_point_dbl_15(&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 != 0) { + sp_384_map_15(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 15 * 6); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_384) * 3); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmp, sizeof(tmp)); + ForceZero(t, sizeof(t)); +#endif + + return err; +} + +#else +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_384 { + sp_digit x[15]; + sp_digit y[15]; +} sp_table_entry_384; + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_fast_15(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td[16]; + sp_point_384 rtd; + sp_digit tmpd[2 * 15 * 6]; +#endif + sp_point_384* t; + sp_point_384* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_384_point_new_15(heap, rtd, rt); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 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 */ + (void)sp_384_mod_mul_norm_15(t[1].x, g->x, p384_mod); + (void)sp_384_mod_mul_norm_15(t[1].y, g->y, p384_mod); + (void)sp_384_mod_mul_norm_15(t[1].z, g->z, p384_mod); + t[1].infinity = 0; + sp_384_proj_point_dbl_15(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_384_proj_point_add_15(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_384_proj_point_dbl_15(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_384_proj_point_add_15(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_384_proj_point_dbl_15(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_384_proj_point_add_15(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_384_proj_point_dbl_15(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_384_proj_point_add_15(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_384_proj_point_dbl_15(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_384_proj_point_add_15(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_384_proj_point_dbl_15(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_384_proj_point_add_15(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_384_proj_point_dbl_15(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_384_proj_point_add_15(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 13; + n = k[i+1] << 6; + c = 16; + y = n >> 22; + XMEMCPY(rt, &t[y], sizeof(sp_point_384)); + n <<= 10; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--] << (6 - c); + c += 26; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_384_proj_point_dbl_15(rt, rt, tmp); + sp_384_proj_point_dbl_15(rt, rt, tmp); + sp_384_proj_point_dbl_15(rt, rt, tmp); + sp_384_proj_point_dbl_15(rt, rt, tmp); + + sp_384_proj_point_add_15(rt, rt, &t[y], tmp); + } + + if (map != 0) { + sp_384_map_15(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 15 * 6); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_384) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_384_point_free_15(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_384_proj_point_dbl_n_15(sp_point_384* p, int n, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*15; + sp_digit* b = t + 4*15; + sp_digit* t1 = t + 6*15; + sp_digit* t2 = t + 8*15; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_384_mont_dbl_15(y, y, p384_mod); + /* W = Z^4 */ + sp_384_mont_sqr_15(w, z, p384_mod, p384_mp_mod); + sp_384_mont_sqr_15(w, w, p384_mod, p384_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_15(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_15(t1, t1, w, p384_mod); + sp_384_mont_tpl_15(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_15(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_15(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_15(t2, b, p384_mod); + sp_384_mont_sub_15(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_15(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_15(t1, t1, p384_mod, p384_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_384_mont_mul_15(w, w, t1, p384_mod, p384_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_15(y, b, x, p384_mod); + sp_384_mont_mul_15(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_15(y, y, p384_mod); + sp_384_mont_sub_15(y, y, t1, p384_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_15(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_15(t1, t1, w, p384_mod); + sp_384_mont_tpl_15(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_15(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_15(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_15(t2, b, p384_mod); + sp_384_mont_sub_15(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_15(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_15(t1, t1, p384_mod, p384_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_15(y, b, x, p384_mod); + sp_384_mont_mul_15(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_15(y, y, p384_mod); + sp_384_mont_sub_15(y, y, t1, p384_mod); +#endif + /* Y = Y/2 */ + sp_384_div2_15(y, y, p384_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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_qz1_15(sp_point_384* r, const sp_point_384* p, + const sp_point_384* q, sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*15; + sp_digit* t3 = t + 4*15; + sp_digit* t4 = t + 6*15; + sp_digit* t5 = t + 8*15; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_384_sub_15(t1, p384_mod, q->y); + sp_384_norm_15(t1); + if ((sp_384_cmp_equal_15(p->x, q->x) & sp_384_cmp_equal_15(p->z, q->z) & + (sp_384_cmp_equal_15(p->y, q->y) | sp_384_cmp_equal_15(p->y, t1))) != 0) { + sp_384_proj_point_dbl_15(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<15; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<15; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<15; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_15(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_15(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - X1 */ + sp_384_mont_sub_15(t2, t2, x, p384_mod); + /* R = S2 - Y1 */ + sp_384_mont_sub_15(t4, t4, y, p384_mod); + /* Z3 = H*Z1 */ + sp_384_mont_mul_15(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_384_mont_sqr_15(t1, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_15(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t3, x, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_15(x, t1, t5, p384_mod); + sp_384_mont_dbl_15(t1, t3, p384_mod); + sp_384_mont_sub_15(x, x, t1, p384_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_384_mont_sub_15(t3, t3, x, p384_mod); + sp_384_mont_mul_15(t3, t3, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t5, t5, y, p384_mod, p384_mp_mod); + sp_384_mont_sub_15(y, t3, t5, p384_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_384_proj_to_affine_15(sp_point_384* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 15; + sp_digit* tmp = t + 4 * 15; + + sp_384_mont_inv_15(t1, a->z, tmp); + + sp_384_mont_sqr_15(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(t1, t2, t1, p384_mod, p384_mp_mod); + + sp_384_mont_mul_15(a->x, a->x, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(a->y, a->y, t1, p384_mod, p384_mp_mod); + XMEMCPY(a->z, p384_norm_mod, sizeof(p384_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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_384_gen_stripe_table_15(const sp_point_384* a, + sp_table_entry_384* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td, s1d, s2d; +#endif + sp_point_384* t; + sp_point_384* s1 = NULL; + sp_point_384* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_384_point_new_15(heap, td, t); + if (err == MP_OKAY) { + err = sp_384_point_new_15(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_384_point_new_15(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_15(t->x, a->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_15(t->y, a->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_15(t->z, a->z, p384_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_384_proj_to_affine_15(t, tmp); + + XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_384)); + /* 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)); + + for (i=1; i<8; i++) { + sp_384_proj_point_dbl_n_15(t, 48, tmp); + sp_384_proj_to_affine_15(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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_384_proj_point_add_qz1_15(t, s1, s2, tmp); + sp_384_proj_to_affine_15(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_384_point_free_15(s2, 0, heap); + sp_384_point_free_15(s1, 0, heap); + sp_384_point_free_15( 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 coordinates. + * + * 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_384_ecc_mulmod_stripe_15(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 rtd; + sp_point_384 pd; + sp_digit td[2 * 15 * 6]; +#endif + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_384_point_new_15(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_384_point_new_15(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + y = 0; + for (j=0,x=47; j<8; j++,x+=48) { + 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 = !y; + for (i=46; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=48) { + y |= ((k[x / 26] >> (x % 26)) & 1) << j; + } + + sp_384_proj_point_dbl_15(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 = !y; + sp_384_proj_point_add_qz1_15(rt, rt, p, t); + } + + if (map != 0) { + sp_384_map_15(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_15(p, 0, heap); + sp_384_point_free_15(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_384_t { + sp_digit x[15]; + sp_digit y[15]; + sp_table_entry_384 table[256]; + uint32_t cnt; + int set; +} sp_cache_384_t; + +static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_384_last = -1; +static THREAD_LS_T int sp_cache_384_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_384 = 0; + static wolfSSL_Mutex sp_cache_384_lock; +#endif + +static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_384_inited == 0) { + for (i=0; ix, sp_cache_384[i].x) & + sp_384_cmp_equal_15(g->y, sp_cache_384[i].y)) { + sp_cache_384[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_384_last + 1) % FP_ENTRIES; + for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_384[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_384_last) { + least = sp_cache_384[0].cnt; + for (j=1; jx, sizeof(sp_cache_384[i].x)); + XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y)); + sp_cache_384[i].set = 1; + sp_cache_384[i].cnt = 1; + } + + *cache = &sp_cache_384[i]; + sp_cache_384_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_384_ecc_mulmod_fast_15(r, g, k, map, heap); +#else + sp_digit tmp[2 * 15 * 7]; + sp_cache_384_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_384 == 0) { + wc_InitMutex(&sp_cache_384_lock); + initCacheMutex_384 = 1; + } + if (wc_LockMutex(&sp_cache_384_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_384(g, &cache); + if (cache->cnt == 2) + sp_384_gen_stripe_table_15(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_384_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_384_ecc_mulmod_fast_15(r, g, k, map, heap); + } + else { + err = sp_384_ecc_mulmod_stripe_15(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 coordinates. + * + * 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_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[15]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_384_point_new_15(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 15, km); + sp_384_point_from_ecc_point_15(point, gm); + + err = sp_384_ecc_mulmod_15(point, point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_15(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_15(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_15(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + /* No pre-computed values. */ + return sp_384_ecc_mulmod_15(r, &p384_base, k, map, heap); +} + +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_15(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + /* No pre-computed values. */ + return sp_384_ecc_mulmod_15(r, &p384_base, k, map, heap); +} + +#else +static const sp_table_entry_384 p384_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x1c0b528,0x01d5992,0x0e383dd,0x38a835b,0x220e378,0x106d35b, + 0x1c3afc5,0x03bfe1e,0x28459a3,0x2d91521,0x214ede2,0x0bfdc8d, + 0x2151381,0x3708a67,0x004d3aa }, + { 0x303a4fe,0x10f6b52,0x29ac230,0x2fdeed2,0x0a1bfa8,0x3a0ec14, + 0x2de7562,0x3ff662e,0x21968f4,0x031b0d4,0x3969a84,0x2000898, + 0x1c5e9dd,0x2f09685,0x002b78a } }, + /* 2 */ + { { 0x30c535b,0x191d4ca,0x2296298,0x14dc141,0x090dd69,0x05aae6b, + 0x0cd6b42,0x35da80e,0x3b7be12,0x2cf7e6d,0x1f347bd,0x3d365e1, + 0x1448913,0x32704fa,0x00222c5 }, + { 0x280dc64,0x39e5bc9,0x24175f8,0x2dd60d4,0x0120e7c,0x041d02e, + 0x0b5d8ad,0x37b9895,0x2fb5337,0x1f0e2e3,0x14f0224,0x2230b86, + 0x1bc4cf6,0x17cdb09,0x007b5c7 } }, + /* 3 */ + { { 0x2dffea5,0x28f30e7,0x29fce26,0x070df5f,0x235bbfd,0x2f78fbd, + 0x27700d9,0x23d6bc3,0x3471a53,0x0c0e03a,0x05bf9eb,0x276a2ec, + 0x20c3e2e,0x31cc691,0x00dbb93 }, + { 0x126b605,0x2e8983d,0x153737d,0x23bf5e1,0x295d497,0x35ca812, + 0x2d793ae,0x16c6893,0x3777600,0x089a520,0x1e681f8,0x3d55ee6, + 0x154ef99,0x155f592,0x00ae5f9 } }, + /* 4 */ + { { 0x26feef9,0x20315fc,0x1240244,0x250e838,0x3c31a26,0x1cf8af1, + 0x1002c32,0x3b531cd,0x1c53ef1,0x22310ba,0x3f4948e,0x22eafd9, + 0x3863202,0x3d0e2a5,0x006a502 }, + { 0x34536fe,0x04e91ad,0x30ebf5f,0x2af62a7,0x01d218b,0x1c8c9da, + 0x336bcc3,0x23060c3,0x331576e,0x1b14c5e,0x1bbcb76,0x0755e9a, + 0x3d4dcef,0x24c2cf8,0x00917c4 } }, + /* 5 */ + { { 0x349ddd0,0x09b8bb8,0x0250114,0x3e66cbf,0x29f117e,0x3005d29, + 0x36b480e,0x2119bfc,0x2761845,0x253d2f7,0x0580604,0x0bb6db4, + 0x3ca922f,0x1744677,0x008adc7 }, + { 0x3d5a7ce,0x27425ed,0x11e9a61,0x3968d10,0x3874275,0x3692d3b, + 0x03e0470,0x0763d50,0x3d97790,0x3cbaeab,0x2747170,0x18faf3a, + 0x180365e,0x2511fe7,0x0012a36 } }, + /* 6 */ + { { 0x3c52870,0x2701e93,0x296128f,0x120694e,0x1ce0b37,0x3860a36, + 0x10fa180,0x0896b55,0x2f76adb,0x22892ae,0x2e58a34,0x07b4295, + 0x2cb62d1,0x079a522,0x00f3d81 }, + { 0x061ed22,0x2375dd3,0x3c9d861,0x3e602d1,0x10bb747,0x39ae156, + 0x3f796fd,0x087a48a,0x06d680a,0x37f7f47,0x2af2c9d,0x36c55dc, + 0x10f3dc0,0x279b07a,0x00a0937 } }, + /* 7 */ + { { 0x085c629,0x319bbf8,0x089a386,0x184256f,0x15fc2a4,0x00fd2d0, + 0x13d6312,0x363d44d,0x32b7e4b,0x25f2865,0x27df8ce,0x1dce02a, + 0x24ea3b0,0x0e27b9f,0x00d8a90 }, + { 0x3b14461,0x1d371f9,0x0f781bc,0x0503271,0x0dc2cb0,0x13bc284, + 0x34b3a68,0x1ff894a,0x25d2032,0x16f79ba,0x260f961,0x07b10d5, + 0x18173b7,0x2812e2b,0x00eede5 } }, + /* 8 */ + { { 0x13b9a2d,0x132ece2,0x0c5d558,0x02c0214,0x1820c66,0x37cb50f, + 0x26d8267,0x3a00504,0x3f00109,0x33756ee,0x38172f1,0x2e4bb8c, + 0x030d985,0x3e4fcc5,0x00609d4 }, + { 0x2daf9d6,0x16681fa,0x1fb01e0,0x1b03c49,0x370e653,0x183c839, + 0x2207515,0x0ea6b58,0x1ae7aaf,0x3a96522,0x24bae14,0x1c38bd9, + 0x082497b,0x1c05db4,0x000dd03 } }, + /* 9 */ + { { 0x110521f,0x04efa21,0x0c174cc,0x2a7dc93,0x387315b,0x14f7098, + 0x1d83bb3,0x2495ed2,0x2fe0c27,0x1e2d9df,0x093c953,0x0287073, + 0x02c9951,0x336291c,0x0033e30 }, + { 0x208353f,0x3f22748,0x2b2bf0f,0x2373b50,0x10170fa,0x1b8a97d, + 0x0851ed2,0x0b25824,0x055ecb5,0x12049d9,0x3fe1adf,0x11b1385, + 0x28eab06,0x11fac21,0x00513f0 } }, + /* 10 */ + { { 0x35bdf53,0x1847d37,0x1a6dc07,0x29d62c4,0x045d331,0x313b8e5, + 0x165daf1,0x1e34562,0x3e75a58,0x16ea2fa,0x02dd302,0x3302862, + 0x3eb8bae,0x2266a48,0x00cf2a3 }, + { 0x24fd048,0x324a074,0x025df98,0x1662eec,0x3841bfb,0x26ae754, + 0x1df8cec,0x0113ae3,0x0b67fef,0x094e293,0x2323666,0x0ab087c, + 0x2f06509,0x0e142d9,0x00a919d } }, + /* 11 */ + { { 0x1d480d8,0x00ed021,0x3a7d3db,0x1e46ca1,0x28cd9f4,0x2a3ceeb, + 0x24dc754,0x0624a3c,0x0003db4,0x1520bae,0x1c56e0f,0x2fe7ace, + 0x1dc6f38,0x0c826a4,0x008b977 }, + { 0x209cfc2,0x2c16c9c,0x1b70a31,0x21416cb,0x34c49bf,0x186549e, + 0x062498d,0x146e959,0x0391fac,0x08ff944,0x2b4b834,0x013d57a, + 0x2eabffb,0x0370131,0x00c07c1 } }, + /* 12 */ + { { 0x332f048,0x0bf9336,0x16dfad2,0x2451d7b,0x35f23bf,0x299adb2, + 0x0ce0c0a,0x0170294,0x289f034,0x2b7d89e,0x395e2d6,0x1d20df7, + 0x2e64e36,0x16dae90,0x00081c9 }, + { 0x31d6ceb,0x0f80db9,0x0271eba,0x33db1ac,0x1b45bcc,0x1a11c07, + 0x347e630,0x148fd9e,0x142e712,0x3183e3e,0x1cd47ad,0x108d1c9, + 0x09cbb82,0x35e61d9,0x0083027 } }, + /* 13 */ + { { 0x215b0b8,0x0a7a98d,0x2c41b39,0x3f69536,0x0b41441,0x16da8da, + 0x15d556b,0x3c17a26,0x129167e,0x3ea0351,0x2d25a27,0x2f2d285, + 0x15b68f6,0x2931ef5,0x00210d6 }, + { 0x1351130,0x012aec9,0x37ebf38,0x26640f8,0x01d2df6,0x2130972, + 0x201efc0,0x23a457c,0x087a1c6,0x14c68a3,0x163f62a,0x36b494d, + 0x015d481,0x39c35b1,0x005dd6d } }, + /* 14 */ + { { 0x06612ce,0x11c3f61,0x199729f,0x3b36863,0x2986f3e,0x3cd2be1, + 0x04c1612,0x2be2dae,0x00846dd,0x3d7bc29,0x249e795,0x1016803, + 0x37a3714,0x2c5aa8b,0x005f491 }, + { 0x341b38d,0x01eb936,0x3caac7f,0x27863ef,0x1ef7d11,0x1110ec6, + 0x18e0761,0x26498e8,0x01a79a1,0x390d5a1,0x22226fb,0x3d2a473, + 0x0872191,0x1230f32,0x00dc772 } }, + /* 15 */ + { { 0x0b1ec9d,0x03fc6b9,0x3706d57,0x03b9fbb,0x221d23e,0x2867821, + 0x1e40f4c,0x2c9c0f3,0x3c4cd4b,0x31f5948,0x3f13aa6,0x307c1b2, + 0x04b6016,0x116b453,0x005aa72 }, + { 0x0b74de8,0x20519d1,0x134e37f,0x05d882a,0x1839e7a,0x3a2c6a8, + 0x0d14e8d,0x1d78bdd,0x251f30d,0x3a1e27e,0x081c261,0x2c9014b, + 0x165ee09,0x19e0cf1,0x00654e2 } }, + /* 16 */ + { { 0x39fbe67,0x081778b,0x0e44378,0x20dfdca,0x1c4afcb,0x20b803c, + 0x0ec06c6,0x1508f6f,0x1c3114d,0x3bca851,0x3a52463,0x07661d1, + 0x17b0aa0,0x16c5f5c,0x00fc093 }, + { 0x0d01f95,0x0ef13f5,0x2d34965,0x2a25582,0x39aa83e,0x3e38fcf, + 0x3943dca,0x385bbdd,0x210e86f,0x3dc1dd2,0x3f9ffdc,0x18b9bc6, + 0x345c96b,0x0e79621,0x008a72f } }, + /* 17 */ + { { 0x341c342,0x3793688,0x042273a,0x153a9c1,0x3dd326e,0x1d073bc, + 0x2c7d983,0x05524cd,0x00d59e6,0x347abe8,0x3d9a3ef,0x0fb624a, + 0x2c7e4cd,0x09b3171,0x0003faf }, + { 0x045f8ac,0x38bf3cc,0x1e73087,0x0c85d3c,0x314a655,0x382be69, + 0x384f28f,0x24d6cb3,0x2842cdc,0x1777f5e,0x2929c89,0x03c45ed, + 0x3cfcc4c,0x0b59322,0x0035657 } }, + /* 18 */ + { { 0x18c1bba,0x2eb005f,0x33d57ec,0x30e42c3,0x36058f9,0x1865f43, + 0x2116e3f,0x2c4a2bb,0x0684033,0x0f1375c,0x0209b98,0x2136e9b, + 0x1bc4af0,0x0b3e0c7,0x0097c7c }, + { 0x16010e8,0x398777e,0x2a172f4,0x0814a7e,0x0d97e4e,0x274dfc8, + 0x2666606,0x1b5c93b,0x1ed3d36,0x3f3304e,0x13488e0,0x02dbb88, + 0x2d53369,0x3717ce9,0x007cad1 } }, + /* 19 */ + { { 0x257a41f,0x2a6a076,0x39b6660,0x04bb000,0x1e74a04,0x3876b45, + 0x343c6b5,0x0753108,0x3f54668,0x24a13cf,0x23749e8,0x0421fc5, + 0x32f13b5,0x0f31be7,0x00070f2 }, + { 0x1186e14,0x0847697,0x0dff542,0x0dff76c,0x084748f,0x2c7d060, + 0x23aab4d,0x0b43906,0x27ba640,0x1497b59,0x02f5835,0x0a492a4, + 0x0a6892f,0x39f3e91,0x005844e } }, + /* 20 */ + { { 0x33b236f,0x02181cf,0x21dafab,0x0760788,0x019e9d4,0x249ed0a, + 0x36571e3,0x3c7dbcf,0x1337550,0x010d22a,0x285e62f,0x19ee65a, + 0x052bf71,0x1d65fd5,0x0062d43 }, + { 0x2955926,0x3fae7bc,0x0353d85,0x07db7de,0x1440a56,0x328dad6, + 0x1668ec9,0x28058e2,0x1a1a22d,0x1014afc,0x3609325,0x3effdcb, + 0x209f3bd,0x3ca3888,0x0094e50 } }, + /* 21 */ + { { 0x062e8af,0x0b96ccc,0x136990b,0x1d7a28f,0x1a85723,0x0076dec, + 0x21b00b2,0x06a88ff,0x2f0ee65,0x1fa49b7,0x39b10ad,0x10b26fa, + 0x0be7465,0x026e8bf,0x00098e3 }, + { 0x3f1d63f,0x37bacff,0x1374779,0x02882ff,0x323d0e8,0x1da3de5, + 0x12bb3b8,0x0a15a11,0x34d1f95,0x2b3dd6e,0x29ea3fa,0x39ad000, + 0x33a538f,0x390204d,0x0012bd3 } }, + /* 22 */ + { { 0x04cbba5,0x0de0344,0x1d4cc02,0x11fe8d7,0x36207e7,0x32a6da8, + 0x0239281,0x1ec40d7,0x3e89798,0x213fc66,0x0022eee,0x11daefe, + 0x3e74db8,0x28534ee,0x00aa0a4 }, + { 0x07d4543,0x250cc46,0x206620f,0x1c1e7db,0x1321538,0x31fa0b8, + 0x30f74ea,0x01aae0e,0x3a2828f,0x3e9dd22,0x026ef35,0x3c0a62b, + 0x27dbdc5,0x01c23a6,0x000f0c5 } }, + /* 23 */ + { { 0x2f029dd,0x3091337,0x21b80c5,0x21e1419,0x13dabc6,0x3847660, + 0x12b865f,0x36eb666,0x38f6274,0x0ba6006,0x098da24,0x1398c64, + 0x13d08e5,0x246a469,0x009929a }, + { 0x1285887,0x3ff5c8d,0x010237b,0x097c506,0x0bc7594,0x34b9b88, + 0x00cc35f,0x0bb964a,0x00cfbc4,0x29cd718,0x0837619,0x2b4a192, + 0x0c57bb7,0x08c69de,0x00a3627 } }, + /* 24 */ + { { 0x1361ed8,0x266d724,0x366cae7,0x1d5b18c,0x247d71b,0x2c9969a, + 0x0dd5211,0x1edd153,0x25998d7,0x0380856,0x3ab29db,0x09366de, + 0x1e53644,0x2b31ff6,0x008b0ff }, + { 0x3b5d9ef,0x217448d,0x174746d,0x18afea4,0x15b106d,0x3e66e8b, + 0x0479f85,0x13793b4,0x1231d10,0x3c39bce,0x25e8983,0x2a13210, + 0x05a7083,0x382be04,0x00a9507 } }, + /* 25 */ + { { 0x0cf381c,0x1a29b85,0x31ccf6c,0x2f708b8,0x3af9d27,0x2a29732, + 0x168d4da,0x393488d,0x2c0e338,0x3f90c7b,0x0f52ad1,0x2a0a3fa, + 0x2cd80f1,0x15e7a1a,0x00db6a0 }, + { 0x107832a,0x159cb91,0x1289288,0x17e21f9,0x073fc27,0x1584342, + 0x3802780,0x3d6c197,0x154075f,0x16366d1,0x09f712b,0x23a3ec4, + 0x29cf23a,0x3218baf,0x0039f0a } }, + /* 26 */ + { { 0x052edf5,0x2afde13,0x2e53d8f,0x3969626,0x3dcd737,0x1e46ac5, + 0x118bf0d,0x01b2652,0x156bcff,0x16d7ef6,0x1ca46d4,0x34c0cbb, + 0x3e486f6,0x1f85068,0x002cdff }, + { 0x1f47ec8,0x12cee98,0x0608667,0x18fbbe1,0x08a8821,0x31a1fe4, + 0x17c7054,0x3c89e89,0x2edf6cd,0x1b8c32c,0x3f6ea84,0x1319329, + 0x3cd3c2c,0x05f331a,0x00186fa } }, + /* 27 */ + { { 0x1fcb91e,0x0fd4d87,0x358a48a,0x04d91b4,0x083595e,0x044a1e6, + 0x15827b9,0x1d5eaf4,0x2b82187,0x08f3984,0x21bd737,0x0c54285, + 0x2f56887,0x14c2d98,0x00f4684 }, + { 0x01896f6,0x0e542d0,0x2090883,0x269dfcf,0x1e11cb8,0x239fd29, + 0x312cac4,0x19dfacb,0x369f606,0x0cc4f75,0x16579f9,0x33c22cc, + 0x0f22bfd,0x3b251ae,0x006429c } }, + /* 28 */ + { { 0x375f9a4,0x137552e,0x3570498,0x2e4a74e,0x24aef06,0x35b9307, + 0x384ca23,0x3bcd6d7,0x011b083,0x3c93187,0x392ca9f,0x129ce48, + 0x0a800ce,0x145d9cc,0x00865d6 }, + { 0x22b4a2b,0x37f9d9c,0x3e0eca3,0x3e5ec20,0x112c04b,0x2e1ae29, + 0x3ce5b51,0x0f83200,0x32d6a7e,0x10ff1d8,0x081adbe,0x265c30b, + 0x216b1c8,0x0eb4483,0x003cbcd } }, + /* 29 */ + { { 0x030ce93,0x2d331fb,0x20a2fbf,0x1f6dc9c,0x010ed6c,0x1ed5540, + 0x275bf74,0x3df0fb1,0x103333f,0x0241c96,0x1075bfc,0x30e5cf9, + 0x0f31bc7,0x32c01eb,0x00b049e }, + { 0x358839c,0x1dbabd3,0x1e4fb40,0x36a8ac1,0x2101896,0x2d0319b, + 0x2033b0a,0x192e8fd,0x2ebc8d8,0x2867ba7,0x07bf6d2,0x1b3c555, + 0x2477deb,0x198fe09,0x008e5a9 } }, + /* 30 */ + { { 0x3fbd5e1,0x18bf77d,0x2b1d69e,0x151da44,0x338ecfe,0x0768efe, + 0x1a3d56d,0x3c35211,0x10e1c86,0x2012525,0x3bc36ce,0x32b6fe4, + 0x0c8d183,0x15c93f3,0x0041fce }, + { 0x332c144,0x24e70a0,0x246e05f,0x22c21c7,0x2b17f24,0x1ba2bfd, + 0x0534e26,0x318a4f6,0x1dc3b85,0x0c741bc,0x23131b7,0x01a8cba, + 0x364e5db,0x21362cf,0x00f2951 } }, + /* 31 */ + { { 0x2ddc103,0x14ffdcd,0x206fd96,0x0de57bd,0x025f43e,0x381b73a, + 0x2301fcf,0x3bafc27,0x34130b6,0x0216bc8,0x0ff56b2,0x2c4ad4c, + 0x23c6b79,0x1267fa6,0x009b4fb }, + { 0x1d27ac2,0x13e2494,0x1389015,0x38d5b29,0x2d33167,0x3f01969, + 0x28ec1fa,0x1b26de0,0x2587f74,0x1c25668,0x0c44f83,0x23c6f8c, + 0x32fdbb1,0x045f104,0x00a7946 } }, + /* 32 */ + { { 0x23c647b,0x09addd7,0x1348c04,0x0e633c1,0x1bfcbd9,0x1cb034f, + 0x1312e31,0x11cdcc7,0x1e6ee75,0x057d27f,0x2da7ee6,0x154c3c1, + 0x3a5fb89,0x2c2ba2c,0x00cf281 }, + { 0x1b8a543,0x125cd50,0x1d30fd1,0x29cc203,0x341a625,0x14e4233, + 0x3aae076,0x289e38a,0x036ba02,0x230f405,0x3b21b8f,0x34088b9, + 0x01297a0,0x03a75fb,0x00fdc27 } }, + /* 33 */ + { { 0x07f41d6,0x1cf032f,0x1641008,0x0f86deb,0x3d97611,0x0e110fe, + 0x136ff42,0x0b914a9,0x0e241e6,0x180c340,0x1f545fc,0x0ba619d, + 0x1208c53,0x04223a4,0x00cd033 }, + { 0x397612c,0x0132665,0x34e2d1a,0x00bba99,0x1d4393e,0x065d0a8, + 0x2fa69ee,0x1643b55,0x08085f0,0x3774aad,0x08a2243,0x33bf149, + 0x03f41a5,0x1ed950e,0x0048cc6 } }, + /* 34 */ + { { 0x014ab48,0x010c3bf,0x2a744e5,0x13c99c1,0x2195b7f,0x32207fd, + 0x28a228c,0x004f4bf,0x0e2d945,0x2ec6e5a,0x0b92162,0x1aa95e5, + 0x2754a93,0x1adcd93,0x004fb76 }, + { 0x1e1ff7f,0x24ef28c,0x269113f,0x32b393c,0x2696eb5,0x0ac2780, + 0x354bf8a,0x0ffe3fd,0x09ce58e,0x0163c4f,0x1678c0b,0x15cd1bc, + 0x292b3b7,0x036ea19,0x00d5420 } }, + /* 35 */ + { { 0x1da1265,0x0c2ef5b,0x18dd9a0,0x3f3a25c,0x0f7b4f3,0x0d8196e, + 0x24931f9,0x090729a,0x1875f72,0x1ef39cb,0x2577585,0x2ed472d, + 0x136756c,0x20553a6,0x00c7161 }, + { 0x2e32189,0x283de4b,0x00b2e81,0x0989df7,0x3ef2fab,0x1c7d1a7, + 0x24f6feb,0x3e16679,0x233dfda,0x06d1233,0x3e6b5df,0x1707132, + 0x05f7b3f,0x2c00779,0x00fb8df } }, + /* 36 */ + { { 0x15bb921,0x117e9d3,0x267ec73,0x2f934ad,0x25c7e04,0x20b5e8f, + 0x2d3a802,0x2ca911f,0x3f87e47,0x39709dd,0x08488e2,0x2cec400, + 0x35b4589,0x1f0acba,0x009aad7 }, + { 0x2ac34ae,0x06f29f6,0x3326d68,0x3949abe,0x02452e4,0x0687b85, + 0x0879244,0x1eb7832,0x0d4c240,0x31d0ec1,0x3c17a2a,0x17a666f, + 0x01a06cb,0x3e0929c,0x004dca2 } }, + /* 37 */ + { { 0x127bc1a,0x0c72984,0x13be68e,0x26c5fab,0x1a3edd5,0x097d685, + 0x36b645e,0x385799e,0x394a420,0x39d8885,0x0b1e872,0x13f60ed, + 0x2ce1b79,0x3c0ecb7,0x007cab3 }, + { 0x29b3586,0x26fc572,0x0bd7711,0x0913494,0x0a55459,0x31af3c9, + 0x3633eac,0x3e2105c,0x0c2b1b6,0x0e6f4c2,0x047d38c,0x2b81bd5, + 0x1fe1c3b,0x04d7cd0,0x0054dcc } }, + /* 38 */ + { { 0x03caf0d,0x0d66365,0x313356d,0x2a4897f,0x2ce044e,0x18feb7a, + 0x1f6a7c5,0x3709e7b,0x14473e8,0x2d8cbae,0x3190dca,0x12d19f8, + 0x31e3181,0x3cc5b6e,0x002d4f4 }, + { 0x143b7ca,0x2604728,0x39508d6,0x0cb79f3,0x24ec1ac,0x1ed7fa0, + 0x3ab5fd3,0x3c76488,0x2e49390,0x03a0985,0x3580461,0x3fd2c81, + 0x308f0ab,0x38561d6,0x0011b9b } }, + /* 39 */ + { { 0x3be682c,0x0c68f4e,0x32dd4ae,0x099d3bb,0x0bc7c5d,0x311f750, + 0x2fd10a3,0x2e7864a,0x23bc14a,0x13b1f82,0x32e495e,0x1b0f746, + 0x3cd856a,0x17a4c26,0x00085ee }, + { 0x02e67fd,0x06a4223,0x2af2f38,0x2038987,0x132083a,0x1b7bb85, + 0x0d6a499,0x131e43f,0x3035e52,0x278ee3e,0x1d5b08b,0x30d8364, + 0x2719f8d,0x0b21fc9,0x003a06e } }, + /* 40 */ + { { 0x237cac0,0x27d6a1c,0x27945cd,0x2750d61,0x293f0b5,0x253db13, + 0x04a764e,0x20b4d0e,0x12bb627,0x160c13b,0x0de0601,0x236e2cf, + 0x2190f0b,0x354d76f,0x004336d }, + { 0x2ab473a,0x10d54e4,0x1046574,0x1d6f97b,0x0031c72,0x06426a9, + 0x38678c2,0x0b76cf9,0x04f9920,0x152adf8,0x2977e63,0x1234819, + 0x198be26,0x061024c,0x00d427d } }, + /* 41 */ + { { 0x39b5a31,0x2123d43,0x362a822,0x1a2eab6,0x0bb0034,0x0d5d567, + 0x3a04723,0x3a10c8c,0x08079ae,0x0d27bda,0x2eb9e1e,0x2619e82, + 0x39a55a8,0x0c6c7db,0x00c1519 }, + { 0x174251e,0x13ac2eb,0x295ed26,0x18d2afc,0x037b9b2,0x1258344, + 0x00921b0,0x1f702d8,0x1bc4da7,0x1c3794f,0x12b1869,0x366eacf, + 0x16ddf01,0x31ebdc5,0x00ad54e } }, + /* 42 */ + { { 0x1efdc58,0x1370d5e,0x0ddb8e7,0x1a53fda,0x1456bd3,0x0c825a9, + 0x0e74ccd,0x20f41c9,0x3423867,0x139073f,0x3c70d8a,0x131fc85, + 0x219a2a0,0x34bf986,0x0041199 }, + { 0x1c05dd2,0x268f80a,0x3da9d38,0x1af9f8f,0x0535f2a,0x30ad37e, + 0x2cf72d7,0x14a509b,0x1f4fe74,0x259e09d,0x1d23f51,0x0672732, + 0x08fc463,0x00b6201,0x001e05a } }, + /* 43 */ + { { 0x0d5ffe8,0x3238bb5,0x17f275c,0x25b6fa8,0x2f8bb48,0x3b8f2d2, + 0x059790c,0x18594d4,0x285a47c,0x3d301bb,0x12935d2,0x23ffc96, + 0x3d7c7f9,0x15c8cbf,0x0034c4a }, + { 0x20376a2,0x05201ba,0x1e02c4b,0x1413c45,0x02ea5e7,0x39575f0, + 0x2d76e21,0x113694c,0x011f310,0x0da3725,0x31b7799,0x1cb9195, + 0x0cfd592,0x22ee4ea,0x00adaa3 } }, + /* 44 */ + { { 0x14ed72a,0x031c49f,0x39a34bf,0x192e87d,0x0da0e92,0x130e7a9, + 0x00258bf,0x144e123,0x2d82a71,0x0294e53,0x3f06c66,0x3d4473a, + 0x037cd4a,0x3bbfb17,0x00fcebc }, + { 0x39ae8c1,0x2dd6a9d,0x206ef23,0x332b479,0x2deff59,0x09d5720, + 0x3526fd2,0x33bf7cf,0x344bb32,0x359316a,0x115bdef,0x1b8468a, + 0x3813ea9,0x11a8450,0x00ab197 } }, + /* 45 */ + { { 0x0837d7d,0x1e1617b,0x0ba443c,0x2f2e3b8,0x2ca5b6f,0x176ed7b, + 0x2924d9d,0x07294d3,0x104bb4f,0x1cfd3e8,0x398640f,0x1162dc8, + 0x007ea15,0x2aa75fd,0x004231f }, + { 0x16e6896,0x01987be,0x0f9d53e,0x1a740ec,0x1554e4c,0x31e1634, + 0x3cb07b9,0x013eb53,0x39352cb,0x1dfa549,0x0974e7f,0x17c55d2, + 0x157c85f,0x1561adb,0x002e3fa } }, + /* 46 */ + { { 0x29951a8,0x35200da,0x2ad042c,0x22109e4,0x3a8b15b,0x2eca69c, + 0x28bcf9a,0x0cfa063,0x0924099,0x12ff668,0x2fb88dc,0x028d653, + 0x2445876,0x218d01c,0x0014418 }, + { 0x1caedc7,0x295bba6,0x01c9162,0x3364744,0x28fb12e,0x24c80b6, + 0x2719673,0x35e5ba9,0x04aa4cc,0x206ab23,0x1cf185a,0x2c140d8, + 0x1095a7d,0x1b3633f,0x000c9f8 } }, + /* 47 */ + { { 0x0b2a556,0x0a051c4,0x30b29a7,0x190c9ed,0x3767ca9,0x38de66d, + 0x2d9e125,0x3aca813,0x2dc22a3,0x319e074,0x0d9450a,0x3445bac, + 0x3e08a5b,0x07f29fa,0x00eccac }, + { 0x02d6e94,0x21113f7,0x321bde6,0x0a4d7b3,0x03621f4,0x2780e8b, + 0x22d5432,0x1fc2853,0x0d57d3e,0x254f90b,0x33ed00b,0x289b025, + 0x12272bb,0x30e715f,0x0000297 } }, + /* 48 */ + { { 0x0243a7d,0x2aac42e,0x0c5b3aa,0x0fa3e96,0x06eeef9,0x2b9fdd9, + 0x26fca39,0x0134fe1,0x22661ab,0x1990416,0x03945d6,0x15e3628, + 0x3848ca3,0x0f91e46,0x00b08cd }, + { 0x16d2411,0x3717e1d,0x128c45e,0x3669d54,0x0d4a790,0x2797da8, + 0x0f09634,0x2faab0b,0x27df649,0x3b19b49,0x0467039,0x39b65a2, + 0x3816f3c,0x31ad0bd,0x0050046 } }, + /* 49 */ + { { 0x2425043,0x3858099,0x389092a,0x3f7c236,0x11ff66a,0x3c58b39, + 0x2f5a7f8,0x1663ce1,0x2a0fcf5,0x38634b7,0x1a8ca18,0x0dcace8, + 0x0e6f778,0x03ae334,0x00df0d2 }, + { 0x1bb4045,0x357875d,0x14b77ed,0x33ae5b6,0x2252a47,0x31899dd, + 0x3293582,0x040c6f6,0x14340dd,0x3614f0e,0x3d5f47f,0x326fb3d, + 0x0044a9d,0x00beeb9,0x0027c23 } }, + /* 50 */ + { { 0x32d49ce,0x34822a3,0x30a22d1,0x00858b7,0x10d91aa,0x2681fd9, + 0x1cce870,0x2404a71,0x38b8433,0x377c1c8,0x019442c,0x0a38b21, + 0x22aba50,0x0d61c81,0x002dcbd }, + { 0x0680967,0x2f0f2f9,0x172cb5f,0x1167e4b,0x12a7bc6,0x05b0da7, + 0x2c76e11,0x3a36201,0x37a3177,0x1d71419,0x0569df5,0x0dce7ad, + 0x3f40b75,0x3bd8db0,0x002d481 } }, + /* 51 */ + { { 0x2a1103e,0x34e7f7f,0x1b171a2,0x24a57e0,0x2eaae55,0x166c992, + 0x10aa18f,0x0bb836f,0x01acb59,0x0e430e7,0x1750cca,0x18be036, + 0x3cc6cdf,0x0a0f7e5,0x00da4d8 }, + { 0x2201067,0x374d187,0x1f6b0a6,0x165a7ec,0x31531f8,0x3580487, + 0x15e5521,0x0724522,0x2b04c04,0x202c86a,0x3cc1ccf,0x225b11a, + 0x1bde79d,0x0eccc50,0x00d24da } }, + /* 52 */ + { { 0x3b0a354,0x2814dd4,0x1cd8575,0x3d031b7,0x0392ff2,0x1855ee5, + 0x0e8cff5,0x203442e,0x3bd3b1b,0x141cf95,0x3fedee1,0x1d783c0, + 0x26f192a,0x0392aa3,0x0075238 }, + { 0x158ffe9,0x3889f19,0x14151f4,0x06067b1,0x13a3486,0x1e65c21, + 0x382d5ef,0x1ab0aac,0x2ffddc4,0x3179b7a,0x3c8d094,0x05101e3, + 0x237c6e5,0x3947d83,0x00f674f } }, + /* 53 */ + { { 0x363408f,0x21eb96b,0x27376fb,0x2a735d6,0x1a39c36,0x3d31863, + 0x33313fc,0x32235e0,0x082f034,0x23ef351,0x39b3528,0x1a69d84, + 0x1d9c944,0x07159ad,0x0077a71 }, + { 0x04f8d65,0x25771e5,0x2ba84a6,0x194586a,0x1e6da5f,0x118059a, + 0x14e9c32,0x1d24619,0x3f528ae,0x22f22e4,0x0f5580d,0x0747a0e, + 0x32cc85f,0x286b3a8,0x008ccf9 } }, + /* 54 */ + { { 0x196fee2,0x2c4431c,0x094528a,0x18e1d32,0x175799d,0x26bb6b7, + 0x2293482,0x23fd289,0x07b2be8,0x1a5c533,0x158d60d,0x04a4f3f, + 0x164e9f7,0x32ccca9,0x00da6b6 }, + { 0x1d821c2,0x3f76c4f,0x323df43,0x17e4374,0x0f2f278,0x121227e, + 0x2464190,0x19d2644,0x326d24c,0x3185983,0x0803c15,0x0767a33, + 0x1c4c996,0x0563eab,0x00631c6 } }, + /* 55 */ + { { 0x1752366,0x0baf83f,0x288bacf,0x0384e6f,0x2b93c34,0x3c805e7, + 0x3664850,0x29e1663,0x254ff1d,0x3852080,0x0f85c16,0x1e389d9, + 0x3191352,0x3915eaa,0x00a246e }, + { 0x3763b33,0x187ad14,0x3c0d438,0x3f11702,0x1c49f03,0x35ac7a8, + 0x3f16bca,0x27266bf,0x08b6fd4,0x0f38ce4,0x37fde8c,0x147a6ff, + 0x02c5e5c,0x28e7fc5,0x00076a7 } }, + /* 56 */ + { { 0x2338d10,0x0e77fa7,0x011b046,0x1bfd0ad,0x28ee699,0x21d73bc, + 0x0461d1a,0x342ea58,0x2d695b4,0x30415ed,0x2906e0b,0x18e494a, + 0x20f8a27,0x026b870,0x002c19f }, + { 0x2f4c43d,0x3f0fc3b,0x0aa95b8,0x2a01ea1,0x3e2e1b1,0x0d74af6, + 0x0555288,0x0cb757d,0x24d2071,0x143d2bb,0x3907f67,0x3e0ce30, + 0x131f0e9,0x3724381,0x007a874 } }, + /* 57 */ + { { 0x3c27050,0x08b5165,0x0bf884b,0x3dd679c,0x3bd0b8d,0x25ce2e6, + 0x1674057,0x1f13ed3,0x1f5cd91,0x0d1fd35,0x13ce6e3,0x2671338, + 0x10f8b90,0x34e5487,0x00942bf }, + { 0x03b566d,0x23c3da9,0x37de502,0x1a486ff,0x1af6e86,0x1108cb3, + 0x36f856c,0x01a6a0f,0x179f915,0x1595a01,0x2cfecb8,0x082568b, + 0x1ba16d1,0x1abb6c0,0x00cf7f0 } }, + /* 58 */ + { { 0x2f96c80,0x1b8f123,0x209c0f5,0x2ccf76d,0x1d521f2,0x3705143, + 0x2941027,0x07f88af,0x07102a9,0x38b4868,0x1efa37d,0x1bdd3e8, + 0x028a12e,0x02e055b,0x009a9a9 }, + { 0x1c7dfcb,0x3aa7aa7,0x1d62c54,0x3f0b0b0,0x3c74e66,0x274f819, + 0x23f9674,0x0e2b67c,0x24654dd,0x0c71f0e,0x1946cee,0x0016211, + 0x0045dc7,0x0da1173,0x0089856 } }, + /* 59 */ + { { 0x0e73946,0x29f353f,0x056329d,0x2d48c5a,0x28f697d,0x2ea4bb1, + 0x235e9cc,0x34faa38,0x15f9f91,0x3557519,0x2a50a6c,0x1a27c8e, + 0x2a1a0f3,0x3098879,0x00dcf21 }, + { 0x1b818bf,0x2f20b98,0x2243cff,0x25b691e,0x3c74a2f,0x2f06833, + 0x0e980a8,0x32db48d,0x2b57929,0x33cd7f5,0x2fe17d6,0x11a384b, + 0x2dafb81,0x2b9562c,0x00ddea6 } }, + /* 60 */ + { { 0x2787b2e,0x37a21df,0x310d294,0x07ce6a4,0x1258acc,0x3050997, + 0x19714aa,0x122824b,0x11c708b,0x0462d56,0x21abbf7,0x331aec3, + 0x307b927,0x3e8d5a0,0x00c0581 }, + { 0x24d4d58,0x3d628fc,0x23279e0,0x2e38338,0x2febe9b,0x346f9c0, + 0x3d6a419,0x3264e47,0x245faca,0x3669f62,0x1e50d66,0x3028232, + 0x18201ab,0x0bdc192,0x0002c34 } }, + /* 61 */ + { { 0x17bdbc2,0x1c501c5,0x1605ccd,0x31ab438,0x372fa89,0x24a8057, + 0x13da2bb,0x3f95ac7,0x3cda0a3,0x1e2b679,0x24f0673,0x03b72f4, + 0x35be616,0x2ccd849,0x0079d4d }, + { 0x33497c4,0x0c7f657,0x2fb0d3d,0x3b81064,0x38cafea,0x0e942bc, + 0x3ca7451,0x2ab9784,0x1678c85,0x3c62098,0x1eb556f,0x01b3aa2, + 0x149f3ce,0x2656f6d,0x002eef1 } }, + /* 62 */ + { { 0x0596edc,0x1f4fad4,0x03a28ed,0x18a4149,0x3aa3593,0x12db40a, + 0x12c2c2a,0x3b1a288,0x327c4fb,0x35847f5,0x384f733,0x02e3fde, + 0x1af0e8a,0x2e417c3,0x00d85a6 }, + { 0x0091cf7,0x2267d75,0x276860e,0x19cbbfc,0x04fef2b,0x030ce59, + 0x3195cb1,0x1aa3f07,0x3699362,0x2a09d74,0x0d6c840,0x1e413d0, + 0x28acdc7,0x1ff5ea1,0x0088d8b } }, + /* 63 */ + { { 0x3d98425,0x08dc8de,0x154e85f,0x24b1c2c,0x2d44639,0x19a1e8b, + 0x300ee29,0x053f72e,0x3f7c832,0x12417f6,0x1359368,0x0674a4c, + 0x1218e20,0x0e4fbd4,0x000428c }, + { 0x01e909a,0x1d88fe6,0x12da40c,0x215ef86,0x2925133,0x004241f, + 0x3e480f4,0x2d16523,0x07c3120,0x3375e86,0x21fd8f3,0x35dc0b6, + 0x0efc5c9,0x14ef8d6,0x0066e47 } }, + /* 64 */ + { { 0x2973cf4,0x34d3845,0x34f7070,0x22df93c,0x120aee0,0x3ae2b4a, + 0x1af9b95,0x177689a,0x036a6a4,0x0377828,0x23df41e,0x22d4a39, + 0x0df2aa1,0x06ca898,0x0003cc7 }, + { 0x06b1dd7,0x19dc2a8,0x35d324a,0x0467499,0x25bfa9c,0x1a1110c, + 0x01e2a19,0x1b3c1cf,0x18d131a,0x10d9815,0x2ee7945,0x0a2720c, + 0x0ddcdb0,0x2c071b6,0x00a6aef } }, + /* 65 */ + { { 0x1ab5245,0x1192d00,0x13ffba1,0x1b71236,0x09b8d0b,0x0eb49cb, + 0x1867dc9,0x371de4e,0x05eae9f,0x36faf82,0x094ea8b,0x2b9440e, + 0x022e173,0x2268e6b,0x00740fc }, + { 0x0e23b23,0x22c28ca,0x04d05e2,0x0bb84c4,0x1235272,0x0289903, + 0x267a18b,0x0df0fd1,0x32e49bb,0x2ab1d29,0x281e183,0x3dcd3c3, + 0x1c0eb79,0x2db0ff6,0x00bffe5 } }, + /* 66 */ + { { 0x2a2123f,0x0d63d71,0x1f6db1a,0x257f8a3,0x1927b2d,0x06674be, + 0x302753f,0x20b7225,0x14c1a3f,0x0429cdd,0x377affe,0x0f40a75, + 0x2d34d06,0x05fb6b9,0x0054398 }, + { 0x38b83c4,0x1e7bbda,0x1682f79,0x0527651,0x2615cb2,0x1795fab, + 0x0e4facc,0x11f763c,0x1b81130,0x2010ae2,0x13f3650,0x20d5b72, + 0x1f32f88,0x34617f4,0x00bf008 } }, + /* 67 */ + { { 0x28068db,0x0aa8913,0x1a47801,0x10695ca,0x1c72cc6,0x0fc1a47, + 0x33df2c4,0x0517cf0,0x3471d92,0x1be815c,0x397f794,0x3f03cbe, + 0x121bfae,0x172cbe0,0x00813d7 }, + { 0x383bba6,0x04f1c90,0x0b3f056,0x1c29089,0x2a924ce,0x3c85e69, + 0x1cecbe5,0x0ad8796,0x0aa79f6,0x25e38ba,0x13ad807,0x30b30ed, + 0x0fa963a,0x35c763d,0x0055518 } }, + /* 68 */ + { { 0x0623f3b,0x3ca4880,0x2bff03c,0x0457ca7,0x3095c71,0x02a9a08, + 0x1722478,0x302c10b,0x3a17458,0x001131e,0x0959ec2,0x18bdfbc, + 0x2929fca,0x2adfe32,0x0040ae2 }, + { 0x127b102,0x14ddeaa,0x1771b8c,0x283700c,0x2398a86,0x085a901, + 0x108f9dc,0x0cc0012,0x33a918d,0x26d08e9,0x20b9473,0x12c3fc7, + 0x1f69763,0x1c94b5a,0x00e29de } }, + /* 69 */ + { { 0x035af04,0x3450021,0x12da744,0x077fb06,0x25f255b,0x0db7150, + 0x17dc123,0x1a2a07c,0x2a7636a,0x3972430,0x3704ca1,0x0327add, + 0x3d65a96,0x3c79bec,0x009de8c }, + { 0x11d3d06,0x3fb8354,0x12c7c60,0x04fe7ad,0x0466e23,0x01ac245, + 0x3c0f5f2,0x2a935d0,0x3ac2191,0x090bd56,0x3febdbc,0x3f1f23f, + 0x0ed1cce,0x02079ba,0x00d4fa6 } }, + /* 70 */ + { { 0x0ab9645,0x10174ec,0x3711b5e,0x26357c7,0x2aeec7f,0x2170a9b, + 0x1423115,0x1a5122b,0x39e512c,0x18116b2,0x290db1c,0x041b13a, + 0x26563ae,0x0f56263,0x00b89f3 }, + { 0x3ed2ce4,0x01f365f,0x1b2043b,0x05f7605,0x1f9934e,0x2a068d2, + 0x38d4d50,0x201859d,0x2de5291,0x0a7985a,0x17e6711,0x01b6c1b, + 0x08091fa,0x33c6212,0x001da23 } }, + /* 71 */ + { { 0x2f2c4b5,0x311acd0,0x1e47821,0x3bd9816,0x1931513,0x1bd4334, + 0x30ae436,0x2c49dc0,0x2c943e7,0x010ed4d,0x1fca536,0x189633d, + 0x17abf00,0x39e5ad5,0x00e4e3e }, + { 0x0c8b22f,0x2ce4009,0x1054bb6,0x307f2fc,0x32eb5e2,0x19d24ab, + 0x3b18c95,0x0e55e4d,0x2e4acf5,0x1bc250c,0x1dbf3a5,0x17d6a74, + 0x087cf58,0x07f6f82,0x00f8675 } }, + /* 72 */ + { { 0x110e0b2,0x0e672e7,0x11b7157,0x1598371,0x01c0d59,0x3d60c24, + 0x096b8a1,0x0121075,0x0268859,0x219962f,0x03213f2,0x3022adc, + 0x18de488,0x3dcdeb9,0x008d2e0 }, + { 0x06cfee6,0x26f2552,0x3c579b7,0x31fa796,0x2036a26,0x362ba5e, + 0x103601c,0x012506b,0x387ff3a,0x101a41f,0x2c7eb58,0x23d2efc, + 0x10a5a07,0x2fd5fa3,0x00e3731 } }, + /* 73 */ + { { 0x1cd0abe,0x08a0af8,0x2fa272f,0x17a1fbf,0x1d4f901,0x30e0d2f, + 0x1898066,0x273b674,0x0c1b8a2,0x3272337,0x3ee82eb,0x006e7d3, + 0x2a75606,0x0af1c81,0x0037105 }, + { 0x2f32562,0x2842491,0x1bb476f,0x1305cd4,0x1daad53,0x0d8daed, + 0x164c37b,0x138030f,0x05145d5,0x300e2a3,0x32c09e7,0x0798600, + 0x3515130,0x2b9e55c,0x009764e } }, + /* 74 */ + { { 0x3d5256a,0x06c67f2,0x3a3b879,0x3c9b284,0x04007e0,0x33c1a41, + 0x3794604,0x1d6240e,0x022b6c1,0x22c62a7,0x01d4590,0x32df5f6, + 0x368f1a1,0x2a7486e,0x006e13f }, + { 0x31e6e16,0x20f18a9,0x09ed471,0x23b861d,0x15cf0ef,0x397b502, + 0x1c7f9b2,0x05f84b2,0x2cce6e1,0x3c10bba,0x13fb5a7,0x1b52058, + 0x1feb1b8,0x03b7279,0x00ea1cf } }, + /* 75 */ + { { 0x2a4cc9b,0x15cf273,0x08f36e6,0x076bf3b,0x2541796,0x10e2dbd, + 0x0bf02aa,0x3aa2201,0x03cdcd4,0x3ee252c,0x3799571,0x3e01fa4, + 0x156e8d0,0x1fd6188,0x003466a }, + { 0x2515664,0x166b355,0x2b0b51e,0x0f28f17,0x355b0f9,0x2909e76, + 0x206b026,0x3823a12,0x179c5fa,0x0972141,0x2663a1a,0x01ee36e, + 0x3fc8dcf,0x2ef3d1b,0x0049a36 } }, + /* 76 */ + { { 0x2d93106,0x3d6b311,0x3c9ce47,0x382aa25,0x265b7ad,0x0b5f92f, + 0x0f4c941,0x32aa4df,0x380d4b2,0x0e8aba6,0x260357a,0x1f38273, + 0x0d5f95e,0x199f23b,0x0029f77 }, + { 0x0a0b1c5,0x21a3d6a,0x0ad8df6,0x33d8a5e,0x1240858,0x30000a8, + 0x3ac101d,0x2a8143d,0x1d7ffe9,0x1c74a2a,0x1b962c9,0x1261359, + 0x0c8b274,0x002cf4a,0x00a8a7c } }, + /* 77 */ + { { 0x211a338,0x22a14ab,0x16e77c5,0x3c746be,0x3a78613,0x0d5731c, + 0x1767d25,0x0b799fa,0x009792a,0x09ae8dc,0x124386b,0x183d860, + 0x176747d,0x14c4445,0x00ab09b }, + { 0x0eb9dd0,0x0121066,0x032895a,0x330541c,0x1e6c17a,0x2271b92, + 0x06da454,0x054c2bf,0x20abb21,0x0ead169,0x3d7ea93,0x2359649, + 0x242c6c5,0x3194255,0x00a3ef3 } }, + /* 78 */ + { { 0x3010879,0x1083a77,0x217989d,0x174e55d,0x29d2525,0x0e544ed, + 0x1efd50e,0x30c4e73,0x05bd5d1,0x0793bf9,0x3f7af77,0x052779c, + 0x2b06bc0,0x13d0d02,0x0055a6b }, + { 0x3eaf771,0x094947a,0x0288f13,0x0a21e35,0x22ab441,0x23816bf, + 0x15832e1,0x2d8aff3,0x348cc1f,0x2bbd4a8,0x01c4792,0x34209d3, + 0x06dc72b,0x211a1df,0x00345c5 } }, + /* 79 */ + { { 0x2a65e90,0x173ac2f,0x199cde1,0x0ac905b,0x00987f7,0x3618f7b, + 0x1b578df,0x0d5e113,0x34bac6a,0x27d85ed,0x1b48e99,0x18af5eb, + 0x1a1be9e,0x3987aac,0x00877ca }, + { 0x2358610,0x3776a8e,0x2b0723a,0x344c978,0x22fc4d6,0x1615d53, + 0x3198f51,0x2d61225,0x12cb392,0x07dd061,0x355f7de,0x09e0132, + 0x0efae99,0x13b46aa,0x00e9e6c } }, + /* 80 */ + { { 0x0683186,0x36d8e66,0x0ea9867,0x0937731,0x1fb5cf4,0x13c39ef, + 0x1a7ffed,0x27dfb32,0x31c7a77,0x09f15fd,0x16b25ef,0x1dd01e7, + 0x0168090,0x240ed02,0x0090eae }, + { 0x2e1fceb,0x2ab9783,0x1a1fdf2,0x093a1b0,0x33ff1da,0x2864fb7, + 0x3587d6c,0x275aa03,0x123dc9b,0x0e95a55,0x0592030,0x2102402, + 0x1bdef7b,0x37f2e9b,0x001efa4 } }, + /* 81 */ + { { 0x0540015,0x20e3e78,0x37dcfbd,0x11b0e41,0x02c3239,0x3586449, + 0x1fb9e6a,0x0baa22c,0x00c0ca6,0x3e58491,0x2dbe00f,0x366d4b0, + 0x176439a,0x2a86b86,0x00f52ab }, + { 0x0ac32ad,0x226250b,0x0f91d0e,0x1098aa6,0x3dfb79e,0x1dbd572, + 0x052ecf2,0x0f84995,0x0d27ad2,0x036c6b0,0x1e4986f,0x2317dab, + 0x2327df6,0x0dee0b3,0x00389ac } }, + /* 82 */ + { { 0x0e60f5b,0x0622d3e,0x2ada511,0x05522a8,0x27fe670,0x206af28, + 0x333cb83,0x3f25f6c,0x19ddaf3,0x0ec579b,0x36aabc0,0x093dbac, + 0x348b44b,0x277dca9,0x00c5978 }, + { 0x1cf5279,0x32e294a,0x1a6c26f,0x3f006b6,0x37a3c6b,0x2e2eb26, + 0x2cf88d4,0x3410619,0x1899c80,0x23d3226,0x30add14,0x2810905, + 0x01a41f0,0x11e5176,0x005a02f } }, + /* 83 */ + { { 0x1c90202,0x321df30,0x3570fa5,0x103e2b1,0x3d099d4,0x05e207d, + 0x0a5b1bd,0x0075d0a,0x3db5b25,0x2d87899,0x32e4465,0x226fc13, + 0x24cb8f8,0x3821daa,0x004da3a }, + { 0x3e66861,0x03f89b8,0x386d3ef,0x14ccc62,0x35e7729,0x11ce5b7, + 0x035fbc7,0x3f4df0f,0x29c439f,0x1144568,0x32d7037,0x312f65e, + 0x06b9dbf,0x03a9589,0x0008863 } }, + /* 84 */ + { { 0x0a9e8c9,0x1a19b6e,0x091ecd9,0x2e16ee0,0x2a11963,0x116cf34, + 0x390d530,0x194131f,0x2b580f3,0x31d569c,0x21d3751,0x3e2ce64, + 0x193de46,0x32454f0,0x004bffd }, + { 0x09554e7,0x170126e,0x2be6cd1,0x153de89,0x0353c67,0x350765c, + 0x202370b,0x1db01e5,0x30b12b1,0x3778591,0x00c8809,0x2e845d5, + 0x1fb1e56,0x170f90d,0x00e2db3 } }, + /* 85 */ + { { 0x328e33f,0x392aad8,0x36d1d71,0x0aebe04,0x1548678,0x1b55c8c, + 0x24995f8,0x2a5a01e,0x1bd1651,0x37c7c29,0x36803b6,0x3716c91, + 0x1a935a5,0x32f10b7,0x005c587 }, + { 0x2e8b4c0,0x336ccae,0x11382b6,0x22ec4cc,0x066d159,0x35fa585, + 0x23b2d25,0x3017528,0x2a674a8,0x3a4f900,0x1a7ce82,0x2b2539b, + 0x3d46545,0x0a07918,0x00eb9f8 } }, + /* 86 */ + { { 0x2cf5b9b,0x03e747f,0x166a34e,0x0afc81a,0x0a115b1,0x3aa814d, + 0x11cf3b1,0x163e556,0x3cbfb15,0x157c0a4,0x1bc703a,0x2141e90, + 0x01f811c,0x207218b,0x0092e6b }, + { 0x1af24e3,0x3af19b3,0x3c70cc9,0x335cbf3,0x068917e,0x055ee92, + 0x09a9308,0x2cac9b7,0x008b06a,0x1175097,0x36e929c,0x0be339c, + 0x0932436,0x15f18ba,0x0009f6f } }, + /* 87 */ + { { 0x29375fb,0x35ade34,0x11571c7,0x07b8d74,0x3fabd85,0x090fa91, + 0x362dcd4,0x02c3fdb,0x0608fe3,0x2477649,0x3fc6e70,0x059b7eb, + 0x1e6a708,0x1a4c220,0x00c6c4c }, + { 0x2a53fb0,0x1a3e1f5,0x11f9203,0x27e7ad3,0x038718e,0x3f5f9e4, + 0x308acda,0x0a8700f,0x34472fe,0x3420d7a,0x08076e5,0x014240e, + 0x0e7317e,0x197a98e,0x00538f7 } }, + /* 88 */ + { { 0x2663b4b,0x0927670,0x38dd0e0,0x16d1f34,0x3e700ab,0x3119567, + 0x12559d2,0x399b6c6,0x0a84bcd,0x163e7dd,0x3e2aced,0x058548c, + 0x03a5bad,0x011cf74,0x00c155c }, + { 0x3e454eb,0x2a1e64e,0x1ccd346,0x36e0edf,0x266ee94,0x2e74aaf, + 0x2d8378a,0x3cd547d,0x1d27733,0x0928e5b,0x353553c,0x26f502b, + 0x1d94341,0x2635cc7,0x00d0ead } }, + /* 89 */ + { { 0x0142408,0x382c3bb,0x3310908,0x2e50452,0x398943c,0x1d0ac75, + 0x1bf7d81,0x04bd00f,0x36b6934,0x3349c37,0x0f69e20,0x0195252, + 0x243a1c5,0x030da5f,0x00a76a9 }, + { 0x224825a,0x28ce111,0x34c2e0f,0x02e2b30,0x382e48c,0x26853ca, + 0x24bd14e,0x0200dec,0x1e24db3,0x0d3d775,0x132da0a,0x1dea79e, + 0x253dc0c,0x03c9d31,0x0020db9 } }, + /* 90 */ + { { 0x26c5fd9,0x05e6dc3,0x2eea261,0x08db260,0x2f8bec1,0x1255edf, + 0x283338d,0x3d9a91d,0x2640a72,0x03311f9,0x1bad935,0x152fda8, + 0x0e95abd,0x31abd15,0x00dfbf4 }, + { 0x107f4fa,0x29ebe9a,0x27353f7,0x3821972,0x27311fa,0x2925ab6, + 0x337ab82,0x2de6c91,0x1f115fe,0x044f909,0x21b93c2,0x3a5f142, + 0x13eb5e9,0x3ab1377,0x00b26b6 } }, + /* 91 */ + { { 0x22e5f2b,0x2ae7d4a,0x1ac481c,0x0a6fce1,0x2f93caf,0x242658e, + 0x3f35c3c,0x050f3d2,0x30074c9,0x142079c,0x0281b4c,0x295fea3, + 0x007413e,0x01726cd,0x00e4979 }, + { 0x1ab3cfb,0x1b76295,0x36adf55,0x1ad4636,0x1d444b9,0x3bd2e55, + 0x35425a5,0x1aa8cd3,0x3acecd2,0x1f769e8,0x1a655e9,0x1f6846f, + 0x24c70b5,0x3bff080,0x0002da3 } }, + /* 92 */ + { { 0x081d0d9,0x2c00d99,0x1fe2e24,0x396063f,0x03740db,0x243f680, + 0x3c1f451,0x1ff7b07,0x2803cf2,0x38ca724,0x2934f43,0x0d72d4d, + 0x0e8fe74,0x2975e21,0x002b505 }, + { 0x11adcc9,0x331a99c,0x21e16cf,0x1714c78,0x1f03432,0x2caa2a6, + 0x34a9679,0x2f7fe8b,0x0423c21,0x1a757ce,0x31b57d6,0x171e044, + 0x093b9b2,0x13602e0,0x00db534 } }, + /* 93 */ + { { 0x250a2f5,0x0b999eb,0x21d10d7,0x22b92a1,0x39b7f8d,0x0c37c72, + 0x29f70f3,0x3bf0e84,0x1d7e04f,0x07a42a9,0x272c3ae,0x1587b2f, + 0x155faff,0x10a336e,0x000d8fb }, + { 0x3663784,0x0d7dcf5,0x056ad22,0x319f8b1,0x0c05bae,0x2b6ff33, + 0x0292e42,0x0435797,0x188efb1,0x0d3f45e,0x119d49f,0x395dcd3, + 0x279fe27,0x133a13d,0x00188ac } }, + /* 94 */ + { { 0x396c53e,0x0d133e9,0x009b7ee,0x13421a0,0x1bbf607,0x1d284a5, + 0x1594f74,0x18cb47c,0x2dcac11,0x2999ddb,0x04e2fa5,0x1889e2c, + 0x0a89a18,0x33cb215,0x0052665 }, + { 0x104ab58,0x1d91920,0x3d6d7e3,0x04dc813,0x1167759,0x13a8466, + 0x0a06a54,0x103761b,0x25b1c92,0x26a8fdd,0x2474614,0x21406a4, + 0x251d75f,0x38c3734,0x007b982 } }, + /* 95 */ + { { 0x15f3060,0x3a7bf30,0x3be6e44,0x0baa1fa,0x05ad62f,0x1e54035, + 0x099d41c,0x2a744d9,0x1c0336f,0x3e99b5b,0x1afd3b1,0x2bf1255, + 0x1822bf8,0x2c93972,0x001d8cc }, + { 0x1d7584b,0x0508ade,0x20dd403,0x203a8fc,0x1c54a05,0x1611a31, + 0x037c8f9,0x1dcd4fe,0x110fbea,0x30f60bc,0x3dffe2f,0x26a1de1, + 0x0480367,0x18ec81c,0x0048eba } }, + /* 96 */ + { { 0x346e2f6,0x0435077,0x036789b,0x3e06545,0x313ab57,0x351a721, + 0x3372b91,0x15e6019,0x2fa4f6c,0x3c30656,0x272c9ac,0x10e84a8, + 0x2bdacea,0x232d9e2,0x009dadd }, + { 0x182579a,0x15b1af8,0x02d8cce,0x36cb49b,0x086feba,0x2911d17, + 0x268ee12,0x011e871,0x18698dc,0x35602b3,0x11b9ec2,0x0ade731, + 0x0f6a05a,0x1821015,0x00007da } }, + /* 97 */ + { { 0x3b00dd0,0x328d485,0x27a69e3,0x32c3a06,0x1046779,0x120b61c, + 0x19fef3d,0x0fef2e6,0x134d923,0x039bce0,0x348cd0e,0x0b0c007, + 0x066ae11,0x15d8f1b,0x00934e7 }, + { 0x33234dc,0x353f0f5,0x2fc1b44,0x18a193a,0x2fcae20,0x1afbc86, + 0x3afe252,0x17f7e10,0x107f3b7,0x2d84d54,0x394c2e6,0x19e96a9, + 0x0a37283,0x26c6152,0x003d262 } }, + /* 98 */ + { { 0x37cfaf8,0x01863d0,0x0299623,0x32c80cb,0x25b8742,0x0a4d90e, + 0x1f72472,0x13de652,0x31a0946,0x0ee0103,0x0f25414,0x2518b49, + 0x07e7604,0x1488d9b,0x00abd6b }, + { 0x1338f55,0x2ce4af5,0x1a0c119,0x3380525,0x21a80a9,0x235d4df, + 0x118ca7f,0x2dd8bcc,0x1c26bf4,0x32dc56b,0x28482b6,0x1418596, + 0x3c84d24,0x1f1a5a9,0x00d958d } }, + /* 99 */ + { { 0x1c21f31,0x22aa1ef,0x258c9ad,0x2d2018f,0x0adb3ca,0x01f75ee, + 0x186283b,0x31ad3bf,0x3621be7,0x3b1ee6d,0x015582d,0x3d61d04, + 0x2ddf32e,0x14b8a66,0x00c970c }, + { 0x2f24d66,0x00b8a88,0x100a78f,0x041d330,0x2efec1d,0x24c5b86, + 0x2a6a390,0x37526bc,0x2055849,0x3339f08,0x16bffc4,0x07f9d72, + 0x06ec09c,0x3f49ee8,0x00cad98 } }, + /* 100 */ + { { 0x248b73e,0x1b8b42d,0x285eed7,0x39473f4,0x1a9f92c,0x3b44f78, + 0x086c062,0x06a4ea3,0x34ea519,0x3c74e95,0x1ad1b8b,0x1737e2c, + 0x2cfe338,0x0a291f4,0x00bbecc }, + { 0x1cec548,0x0c9b01a,0x20b298d,0x377c902,0x24f5bc1,0x2415c8d, + 0x1a70622,0x2529090,0x1c5c682,0x283f1ba,0x2319f17,0x0120e2e, + 0x01c6f4d,0x33c67ff,0x008b612 } }, + /* 101 */ + { { 0x03830eb,0x02d4053,0x10c59bb,0x0f23b83,0x13d08f8,0x26ea4e2, + 0x2626427,0x0a45292,0x0449cbc,0x0175750,0x074c46f,0x27ae0f8, + 0x2d7d6ae,0x163dd3a,0x0063bb7 }, + { 0x2bb29e0,0x034bab1,0x341e1c4,0x21d2c0b,0x295aa2d,0x0f2c666, + 0x1891755,0x13db64a,0x2fe5158,0x337646e,0x31a1aae,0x057bee4, + 0x00f9e37,0x396d19e,0x00c1b6a } }, + /* 102 */ + { { 0x2772f41,0x34f92d0,0x39d1cde,0x174ef2d,0x03a700d,0x03fbb98, + 0x30d50e8,0x352ed10,0x1fcf5e5,0x3d113bc,0x26e358f,0x180653f, + 0x1b43cc6,0x3cc9aa4,0x00e68a2 }, + { 0x37fe4d2,0x09dd725,0x01eb584,0x171f8a9,0x278fdef,0x3e37c03, + 0x3bec02f,0x149757c,0x0cd5852,0x37d2e10,0x0e6988b,0x1c120e9, + 0x0b83708,0x38e7319,0x0039499 } }, + /* 103 */ + { { 0x08df5fe,0x177a02c,0x0362fc0,0x1f18ee8,0x00c1295,0x173c50a, + 0x379414d,0x1885ba8,0x32a54ef,0x2315644,0x39e65cf,0x357c4be, + 0x1d66333,0x09e05a5,0x0009c60 }, + { 0x1f7a2fb,0x073b518,0x2eb83ac,0x11353d7,0x1dd8384,0x0c63f2b, + 0x238c6c8,0x2a1920a,0x2e5e9f1,0x1cc56f8,0x042daf4,0x1ed5dc5, + 0x25f9e31,0x012a56a,0x0081b59 } }, + /* 104 */ + { { 0x321d232,0x2c71422,0x3a756b6,0x30230b2,0x387f3db,0x3a7c3eb, + 0x274b46a,0x201e69f,0x185bb7b,0x140da82,0x0d974a2,0x0616e42, + 0x35ec94f,0x3bc366b,0x005aa7c }, + { 0x3dcfffc,0x19a9c15,0x3225e05,0x36ae114,0x16ea311,0x0cda2aa, + 0x2a1a8d2,0x154b5cb,0x08348cd,0x17b66c8,0x080ea43,0x21e59f3, + 0x04173b9,0x31d5b04,0x00ad735 } }, + /* 105 */ + { { 0x2e76ef4,0x216acf3,0x2b93aea,0x112bc74,0x3449974,0x2b2e48f, + 0x11929be,0x2f03021,0x19051e3,0x0ac202d,0x19be68a,0x3b87619, + 0x26cdac4,0x086592c,0x00f00de }, + { 0x2e90d4d,0x3ed703c,0x2c648d7,0x29ddf67,0x000e219,0x3471247, + 0x26febd5,0x1161713,0x3541a8f,0x302038d,0x08d2af9,0x26e1b21, + 0x398514a,0x36dad99,0x002ed70 } }, + /* 106 */ + { { 0x06f25cb,0x1104596,0x370faee,0x07e83f3,0x0f7b686,0x228d43a, + 0x12cd201,0x0a1bd57,0x3e592dc,0x1e186fc,0x2226aba,0x2c63fe9, + 0x17b039a,0x1efaa61,0x00d1582 }, + { 0x2e6acef,0x07d51e4,0x3ac326c,0x322b07e,0x1422c63,0x32ff5c7, + 0x18760df,0x048928b,0x139b251,0x04d7da9,0x048d1a2,0x2a23e84, + 0x199dbba,0x2fa7afe,0x0049f1a } }, + /* 107 */ + { { 0x3492b73,0x27d3d3d,0x2b1a16f,0x07b2ce4,0x0cf28ec,0x2729bff, + 0x3130d46,0x3e96116,0x140b72e,0x14a2ea3,0x1ca066f,0x3a61f1d, + 0x022ebac,0x09192b4,0x003e399 }, + { 0x12555bb,0x0b6139d,0x239463a,0x12a70ab,0x2aaa93b,0x2254e72, + 0x00424ec,0x26a6736,0x26daa11,0x25b5ad6,0x379f262,0x140cd30, + 0x0c7d3bd,0x097bbcf,0x00899e9 } }, + /* 108 */ + { { 0x3825dc4,0x3cd946f,0x0462b7f,0x31102e7,0x30f741c,0x3313ed6, + 0x1ff5a95,0x15bf9dc,0x09b47fd,0x0f2e7a7,0x1626c0d,0x3c14f6d, + 0x14098bd,0x19d7df8,0x00a97ce }, + { 0x0934f5e,0x3f968db,0x046f68a,0x12333bf,0x26cd5e1,0x1ea2161, + 0x358570d,0x235031d,0x35edd55,0x05265e3,0x24ae00c,0x3542229, + 0x25bb2a1,0x1c83c75,0x0058f2a } }, + /* 109 */ + { { 0x24daedb,0x376928f,0x305266f,0x0499746,0x038318c,0x312efd7, + 0x1910a24,0x33450a3,0x1c478a9,0x39d8bf9,0x12cc0ae,0x397aeab, + 0x0654c08,0x095f283,0x00d2cdf }, + { 0x0b717d2,0x1f162c2,0x107a48f,0x128e1b3,0x2380718,0x39f4044, + 0x00f626a,0x05ec0c9,0x21bc439,0x200fa4d,0x20aea01,0x186a1d8, + 0x26372f2,0x1a91f87,0x0053f55 } }, + /* 110 */ + { { 0x3512a90,0x33b958b,0x29f1c84,0x0106c3a,0x224b3c0,0x09b307a, + 0x215d2de,0x3bdf43b,0x22cf0c9,0x176121d,0x1534143,0x09ba717, + 0x16b3110,0x0f73f6c,0x008f5b7 }, + { 0x2c75d95,0x26fbcb4,0x0dda1f6,0x206f819,0x28d33d5,0x1fb4d79, + 0x024c125,0x30a0630,0x1f9c309,0x0fe350d,0x1696019,0x0a54187, + 0x09541fd,0x35e3a79,0x0066618 } }, + /* 111 */ + { { 0x0e382de,0x33f5163,0x0dde571,0x3bb7a40,0x1175806,0x12ae8ed, + 0x0499653,0x3b25586,0x38ade7a,0x3fa265d,0x3f4aa97,0x3c03dbb, + 0x30c6de8,0x32d4042,0x00ae971 }, + { 0x2f788f1,0x1fbaf0e,0x3e2d182,0x3ff904f,0x0d46229,0x1d0726d, + 0x15455b4,0x093ae28,0x290f8e4,0x097c0b9,0x1ae8771,0x28480bb, + 0x04f6d40,0x3689925,0x0049b3b } }, + /* 112 */ + { { 0x35b2d69,0x31819c0,0x11b0d63,0x035afb6,0x2b50715,0x2bece6c, + 0x35f82f7,0x0ad987c,0x0011601,0x02e6f67,0x2d0a5f5,0x365e583, + 0x2f7c900,0x11449c5,0x00ed705 }, + { 0x27abdb4,0x1bbfd04,0x301c157,0x263c079,0x36850d6,0x3f21f8b, + 0x27d7493,0x0f9227e,0x06fb0ce,0x002daf3,0x37d8c1c,0x3ef87d7, + 0x19cc6f4,0x0c3809c,0x00cf752 } }, + /* 113 */ + { { 0x22d94ed,0x075b09c,0x020e676,0x084dc62,0x2d1ec3f,0x17439f1, + 0x240b702,0x33cc596,0x30ebaf3,0x0359fe0,0x393ea43,0x0ece01e, + 0x16c6963,0x03a82f2,0x0017faa }, + { 0x3866b98,0x3cd20b7,0x12d4e6b,0x3a6a76d,0x1205c1e,0x3e6ae1a, + 0x2f9bbdf,0x2e61547,0x2d175ee,0x28e18f6,0x13cf442,0x085b0ef, + 0x0e321ef,0x238fe72,0x003fb22 } }, + /* 114 */ + { { 0x360ac07,0x26dc301,0x3f4d94f,0x2ba75e6,0x1f3c9cc,0x17ff20f, + 0x0ea084c,0x30e39cf,0x143dc49,0x03bd43e,0x3c9e733,0x19e8aba, + 0x27fbaf4,0x12d913a,0x005ee53 }, + { 0x3609e7f,0x2d89c80,0x09f020c,0x1558bf7,0x3098443,0x3c515fd, + 0x1c8e580,0x16506bd,0x26cb4b2,0x1747d42,0x2ec8239,0x32c91f0, + 0x1ca3377,0x079768f,0x00a5f3e } }, + /* 115 */ + { { 0x185fa94,0x122759f,0x0e47023,0x0dcb6e7,0x10ba405,0x3b5eab4, + 0x1f7a1fa,0x32d003f,0x1739a4c,0x3295ec3,0x1b18967,0x3f3b265, + 0x34d2448,0x2dbadc9,0x00f30b5 }, + { 0x01c5338,0x2d1dcf2,0x2bd07cc,0x39a8fb5,0x2b85639,0x355bab6, + 0x1df95f1,0x01eb5f6,0x17f0a16,0x1b895b5,0x157574d,0x29fff72, + 0x3a8c46d,0x0118071,0x0065f84 } }, + /* 116 */ + { { 0x3a1e7f1,0x17432f2,0x1f648d4,0x3000ad5,0x2ef0a08,0x1f86624, + 0x1ca31b1,0x241f9dc,0x2cb4885,0x2b8610f,0x364ce16,0x1e5faf0, + 0x0b33867,0x2cb637d,0x00816d2 }, + { 0x1aa8671,0x02c394e,0x35f5e87,0x393040a,0x39f0db3,0x1c831a5, + 0x2966591,0x034a8d0,0x09e613c,0x042b532,0x018ddd6,0x3e402c9, + 0x2e20e1a,0x29cb4cd,0x00e087c } }, + /* 117 */ + { { 0x3a10079,0x20c7fea,0x3ff2222,0x1edb593,0x00dc5f8,0x3a32ccc, + 0x1479073,0x0cfed11,0x2a2702a,0x17a056a,0x1fba321,0x235acb9, + 0x149c833,0x172de7d,0x000f753 }, + { 0x2e95923,0x3b365cb,0x009f471,0x0df1b47,0x21e868b,0x199bbd3, + 0x07b8ecc,0x12ff0af,0x189808a,0x3bd5059,0x3fbc4d2,0x0fa7b88, + 0x1125bf2,0x0db0b5d,0x0043572 } }, + /* 118 */ + { { 0x29cdb1b,0x1db656e,0x391efe1,0x004be09,0x245a1ca,0x3793328, + 0x254af24,0x2f2e65d,0x10e5cc4,0x2af6fe7,0x2d97ac0,0x29f7d42, + 0x19fd6f6,0x0ac184d,0x00c5211 }, + { 0x305eae3,0x36738d3,0x2c2b696,0x00ba50e,0x3903adc,0x2122f85, + 0x0753470,0x1cf96a4,0x1702a39,0x247883c,0x2feb67e,0x2ab3071, + 0x3c6b9e1,0x30cb85a,0x002ca0a } }, + /* 119 */ + { { 0x3871eb5,0x284b93b,0x0a7affe,0x176a2fc,0x294c2f2,0x204d3aa, + 0x1e4c2a7,0x3ec4134,0x2fb0360,0x3847b45,0x05fc11b,0x0a6db6e, + 0x390fa40,0x2adfd34,0x005e9f7 }, + { 0x0646612,0x1b5cbcc,0x10d8507,0x0777687,0x3a0afed,0x1687440, + 0x0222578,0x1af34a4,0x2174e27,0x372d267,0x11246c3,0x34769c5, + 0x2044316,0x1b4d626,0x00c72d5 } }, + /* 120 */ + { { 0x2e5bb45,0x3ff1d36,0x16dcdf5,0x128986f,0x399068c,0x2a63b1e, + 0x0afa7aa,0x3a5b770,0x200f121,0x33b74bb,0x1414045,0x0f31ef8, + 0x2f50e16,0x2f38cd6,0x00b0b1b }, + { 0x1a06293,0x035e140,0x2644d44,0x1f1954b,0x2cdebab,0x31d5f91, + 0x0b8dbc8,0x38f2d23,0x3783cab,0x2a07e73,0x3123f59,0x3409846, + 0x3784ddd,0x223bbac,0x003dc7b } }, + /* 121 */ + { { 0x0741456,0x234e631,0x2121e1b,0x00980ca,0x3a9dfa9,0x098c916, + 0x3fc86d1,0x1c63072,0x3625244,0x13d0471,0x05b0fc5,0x1487550, + 0x2498596,0x11bb6ea,0x001afab }, + { 0x274b4ad,0x240aea1,0x3d12a75,0x2b56b61,0x1486b43,0x1b83426, + 0x31c7363,0x35b59ca,0x207bb6c,0x38e6243,0x19bace4,0x0a26671, + 0x35e3381,0x0c2ded4,0x00d8da4 } }, + /* 122 */ + { { 0x2b75791,0x19590b1,0x2bfb39f,0x2988601,0x0050947,0x0d8bbe1, + 0x23e3701,0x08e4432,0x2ed8c3d,0x326f182,0x332e1dd,0x12219c5, + 0x2e0779b,0x367aa63,0x0012d10 }, + { 0x251b7dc,0x0a08b4d,0x1138b6f,0x2ea02af,0x06345a5,0x1cb4f21, + 0x0332624,0x1d49d88,0x140acc5,0x2f55287,0x024447c,0x291ace9, + 0x1a4966e,0x015cbec,0x005bc41 } }, + /* 123 */ + { { 0x351cd0e,0x315e8e9,0x07d6e70,0x067ae8f,0x2190d84,0x351f556, + 0x03bee79,0x31b62c7,0x266f912,0x1b6a504,0x007a6ad,0x3a6ab31, + 0x3891112,0x3c45ba0,0x00d6ce5 }, + { 0x0e1f2ce,0x32a5edc,0x1434063,0x1ca084f,0x2a3e47c,0x137e042, + 0x16e2418,0x2069280,0x3b0dfd8,0x35a22b5,0x289bf0a,0x1f667f2, + 0x02d23a3,0x0ce688f,0x00d8e3f } }, + /* 124 */ + { { 0x10bed6f,0x14c58dd,0x0b0abdf,0x0ca0f9a,0x3808abc,0x2ec228c, + 0x2366275,0x12afa16,0x20f6b0e,0x37dca8e,0x3af0c6a,0x1c5b467, + 0x1b25ff7,0x00814de,0x0022dcc }, + { 0x1a56e11,0x02fe37e,0x3f21740,0x35d5a91,0x06cb8ba,0x29bad91, + 0x17176f7,0x2d919f2,0x0f7d1f5,0x13a3f61,0x04ddb05,0x0c82a51, + 0x286f598,0x2e8c777,0x0007071 } }, + /* 125 */ + { { 0x0f8fcb9,0x3e83966,0x170c6fd,0x3825343,0x089cec8,0x01b482a, + 0x0993971,0x3327282,0x39aba8a,0x32456fe,0x1507e01,0x1c3252d, + 0x21ffb13,0x29822a0,0x0083246 }, + { 0x23c378f,0x1cea7ef,0x1be9a82,0x224d689,0x37e5447,0x3764a75, + 0x3a49724,0x361e1b3,0x19d365b,0x3a61ffb,0x1c29a7a,0x20ab251, + 0x17ec549,0x175d777,0x004589a } }, + /* 126 */ + { { 0x15540a9,0x2ec5d2a,0x05b09fa,0x1bc058b,0x07cfb88,0x28f7b86, + 0x3e766be,0x189305e,0x01fe88e,0x23fdf69,0x0b919c3,0x02dc7ae, + 0x3f9a9ad,0x0b83cc7,0x0086a52 }, + { 0x28bc259,0x39bdca1,0x39e4bc8,0x0e0f33b,0x16130c6,0x2919955, + 0x31f4549,0x2fed027,0x30919b2,0x0a39b03,0x0ca7bb2,0x1711b24, + 0x3b67b94,0x05a136b,0x00acd87 } }, + /* 127 */ + { { 0x0c53841,0x31cb284,0x3ced090,0x06d5693,0x1c20ae0,0x0408d2b, + 0x37ebd5e,0x081900f,0x26a8589,0x0acfd0a,0x34a1472,0x2f0c302, + 0x124ccbd,0x10de328,0x00971bc }, + { 0x17ff2ff,0x27d1b54,0x147b6f7,0x38bb2ea,0x26a9c96,0x0a49448, + 0x39f2f46,0x247c579,0x3b16a4e,0x28c2a5a,0x2d4c72d,0x11f248c, + 0x1e4df11,0x047d604,0x0065bc3 } }, + /* 128 */ + { { 0x39b3239,0x1f75f44,0x3bae87c,0x139360c,0x18b5782,0x3ffc005, + 0x3c48789,0x2bc6af2,0x38b909e,0x223ff3b,0x31443a7,0x017d3bb, + 0x0bfed99,0x128b857,0x00020dd }, + { 0x306d695,0x25a7b28,0x2f60ca2,0x2b6e4f2,0x1df940c,0x1fa9b8e, + 0x37fab78,0x13f959f,0x10ff98c,0x38343b8,0x019cb91,0x11a1e6b, + 0x17ab4c6,0x1431f47,0x004b4ea } }, + /* 129 */ + { { 0x20db57e,0x102515e,0x170219e,0x2b66a32,0x1e6017c,0x2f973fe, + 0x3739e51,0x0e28b6f,0x3cda7a9,0x30d91ac,0x28350df,0x1444215, + 0x098b504,0x1bcd5b8,0x00ad3bd }, + { 0x22e3e3e,0x3aeaffb,0x26cb935,0x0091ce4,0x2fbd017,0x3a7ed6a, + 0x335b029,0x3bfc1f1,0x3852e3f,0x2b14a86,0x046b405,0x266af4c, + 0x3997191,0x33b0e40,0x00e306f } }, + /* 130 */ + { { 0x3e4712c,0x26bb208,0x18eed6d,0x1b30f06,0x27ca837,0x06faf62, + 0x1831873,0x3fbcf9b,0x3f3d88b,0x1fb55eb,0x0f44edc,0x29917bb, + 0x3151772,0x342d72e,0x00d4e63 }, + { 0x2ee0ecf,0x39e8733,0x2e8e98c,0x0cd4e0f,0x08f0126,0x1ad157a, + 0x079078a,0x23018ee,0x196c765,0x2b2f34f,0x0783336,0x075bf9c, + 0x3713672,0x098d699,0x00f21a7 } }, + /* 131 */ + { { 0x186ba11,0x22cf365,0x048019d,0x2ca2970,0x0d9e0ae,0x08c3bd7, + 0x261dbf2,0x2fc2790,0x1ee02e6,0x10256a7,0x00dc778,0x18dc8f2, + 0x157b189,0x2ebc514,0x005c97d }, + { 0x3c4503e,0x1d10d12,0x337097e,0x0c6169a,0x30fb1cb,0x3481752, + 0x0df2bec,0x19768fa,0x1bcf8f7,0x2925f74,0x2c988a1,0x3be571d, + 0x04cfa92,0x2ea9937,0x003f924 } }, + /* 132 */ + { { 0x268b448,0x06e375c,0x1b946bf,0x287bf5e,0x3d4c28b,0x138d547, + 0x21f8c8e,0x21ea4be,0x2d45c91,0x35da78e,0x00326c0,0x210ed35, + 0x1d66928,0x0251435,0x00fefc8 }, + { 0x0339366,0x216ff64,0x2c3a30c,0x3c5733d,0x04eeb56,0x2333477, + 0x32b1492,0x25e3839,0x1b5f2ce,0x0dcfba1,0x3165bb2,0x3acafcc, + 0x10abfcd,0x248d390,0x008106c } }, + /* 133 */ + { { 0x102f4ee,0x3c0585f,0x1225c8d,0x11c6388,0x08a7815,0x2b3e790, + 0x2895eb6,0x18cf53a,0x0b56e5a,0x2e2c003,0x3e981ff,0x0761b55, + 0x1bc32f3,0x0a7111d,0x00f5c80 }, + { 0x3568973,0x1587386,0x16ec764,0x20698a6,0x02f809b,0x2821502, + 0x113d64d,0x38c2679,0x15de61c,0x0309f60,0x272999e,0x29bfe64, + 0x173f70d,0x1de7fab,0x00bd284 } }, + /* 134 */ + { { 0x31cdf2b,0x0f0be66,0x2151603,0x01af17e,0x32a99cf,0x085dece, + 0x27d2591,0x1520df4,0x273c448,0x1ec7c54,0x102e229,0x355f604, + 0x2acb75f,0x005f1fd,0x003d43e }, + { 0x270eb28,0x22ec2ce,0x306b41a,0x238fa02,0x167de2d,0x030a379, + 0x245a417,0x1808c24,0x0b1a7b2,0x3ab5f6f,0x2cbc6c1,0x2c228d4, + 0x3041f70,0x2d9a6cc,0x00b504f } }, + /* 135 */ + { { 0x17a27c2,0x216ad7e,0x011ba8e,0x22f0428,0x16ac5ec,0x3ef3c58, + 0x345533f,0x0298155,0x2856579,0x0005e03,0x19ee75b,0x146fe16, + 0x29881e4,0x18ece70,0x008907a }, + { 0x20189ed,0x119ce09,0x35cb76d,0x0d91ef4,0x2284a44,0x032ad87, + 0x0e8c402,0x3c82b5d,0x38c416c,0x398992f,0x1fd820c,0x169b255, + 0x3b5fcfa,0x1343c92,0x00fa715 } }, + /* 136 */ + { { 0x33f5034,0x20b3b26,0x28fd184,0x16b3679,0x3962d44,0x15d1bc8, + 0x2fb1d69,0x1292c99,0x25a58c9,0x1b19ab7,0x2d68a5b,0x2f6a09b, + 0x0d6aedb,0x2935eac,0x0005664 }, + { 0x25e32fc,0x13f9440,0x3252bcd,0x2fea5b7,0x161a5ae,0x0564a8c, + 0x0a07e23,0x1545f62,0x0de9890,0x1d76765,0x1fd440e,0x2ed0041, + 0x3db4c96,0x1e8ba01,0x001b0c4 } }, + /* 137 */ + { { 0x0223878,0x29ab202,0x15585c2,0x1a79969,0x1ba08c2,0x2ef09ff, + 0x2b1b9b9,0x181f748,0x1bf72b9,0x224645c,0x2588dc5,0x2d157e7, + 0x22d939a,0x05b88d9,0x006d549 }, + { 0x31de0c1,0x23a4e0e,0x278f8da,0x1aa013c,0x1a84d18,0x0d185a5, + 0x0988ccd,0x2c32efd,0x3bee10e,0x37d7ab8,0x3f2a66e,0x3e2da3e, + 0x1b5701f,0x3d9f0c1,0x00a68da } }, + /* 138 */ + { { 0x0b2e045,0x0133fd1,0x05d4c10,0x0d92c70,0x391b5e1,0x2292281, + 0x2e40908,0x2ec694e,0x195ea11,0x29cfeca,0x3d93a4e,0x01215c0, + 0x08a5f32,0x37a0eff,0x00cce45 }, + { 0x2b3106e,0x12a5fb0,0x0b4faff,0x0c2da12,0x09069c6,0x35d8907, + 0x2837a6e,0x3db3fb6,0x3136cc3,0x222836b,0x3da018a,0x2741274, + 0x13ba319,0x1ac7642,0x00f867c } }, + /* 139 */ + { { 0x2527296,0x10a9595,0x178de4d,0x0f739c4,0x0ae26c7,0x3094599, + 0x20adac6,0x2b875c2,0x3ae5dc0,0x3e04d20,0x1aab2da,0x1d3ab37, + 0x15f4f75,0x0b730b5,0x00c56b5 }, + { 0x1f32923,0x2f059e5,0x2a89872,0x2056f74,0x04be175,0x1da67c0, + 0x17f1e7a,0x3780a6d,0x0723ac2,0x257f367,0x1237773,0x2bcee86, + 0x0b97f83,0x38aff14,0x00a64d4 } }, + /* 140 */ + { { 0x2552b40,0x0b6b883,0x12e8217,0x0974d35,0x062f497,0x1e563e6, + 0x30ee400,0x375d1e4,0x290751f,0x0d5b68a,0x353e48c,0x064a0d3, + 0x3c343f1,0x309a394,0x0034d2a }, + { 0x3111286,0x0f08604,0x1827107,0x0536a76,0x0201dac,0x3a574de, + 0x2c29dbe,0x382c7b0,0x1191f3e,0x324c5bc,0x144ce71,0x24327c1, + 0x1212778,0x22bc9d8,0x00d7713 } }, + /* 141 */ + { { 0x34ad1cd,0x1179b4e,0x1bc1780,0x1392a92,0x2cd86b9,0x359de85, + 0x251f1df,0x0da5d5f,0x135fa61,0x0f64a42,0x34f4d89,0x0fe564c, + 0x3cf9b7a,0x122d757,0x008c9c2 }, + { 0x370d4e9,0x0e9209b,0x0ae99f2,0x1518c64,0x0172734,0x2c20692, + 0x1d7c135,0x149c52f,0x38928d6,0x3c78b78,0x25841d1,0x2eaa897, + 0x372e50b,0x29e5d19,0x00c4c18 } }, + /* 142 */ + { { 0x13375ac,0x389a056,0x211310e,0x2f9f757,0x04f3288,0x103cd4e, + 0x17b2fb2,0x2c78a6a,0x09f1de6,0x23e8442,0x1351bc5,0x1b69588, + 0x285b551,0x0464b7e,0x00573b6 }, + { 0x0ba7df5,0x259a0db,0x2b4089e,0x05630a2,0x3f299be,0x350ff2f, + 0x1c9348a,0x3becfa4,0x3cc9a1c,0x17a6ef1,0x338b277,0x2b761d9, + 0x2aa01c8,0x3cb9dd7,0x006e3b1 } }, + /* 143 */ + { { 0x277788b,0x16a222d,0x173c036,0x310ff58,0x2634ae8,0x392636f, + 0x0987619,0x1e6acc1,0x26dc8f7,0x242310f,0x0c09aca,0x22b8e11, + 0x0d17006,0x1c2c806,0x002380c }, + { 0x297c5ec,0x1fef0e8,0x3948cf7,0x14f2915,0x2dacbc8,0x0dafb1f, + 0x10de043,0x31184da,0x06414ee,0x3c9aeeb,0x1f713ab,0x308f1f8, + 0x1569ed1,0x3f379bf,0x00f08bb } }, + /* 144 */ + { { 0x0770ee3,0x058fd21,0x17065f8,0x251d128,0x10e0c7f,0x06cb51b, + 0x0f05f7e,0x3666a72,0x3e7d01f,0x2d05fab,0x11440e5,0x28577d4, + 0x2fbcf2b,0x14aa469,0x00dc5c5 }, + { 0x270f721,0x1c75d28,0x085b862,0x1d68011,0x132c0a0,0x37be81d, + 0x1a87e38,0x083fa74,0x3acbf0d,0x16d6429,0x0feda1f,0x031070a, + 0x2ec2443,0x21e563d,0x00454d2 } }, + /* 145 */ + { { 0x0525435,0x1e98d5f,0x3dbc52b,0x1fcdf12,0x13d9ef5,0x3ff311d, + 0x393e9ed,0x3cef8ae,0x2987710,0x3bdee2e,0x21b727d,0x3ba1b68, + 0x10d0142,0x3c64b92,0x0055ac3 }, + { 0x0c1c390,0x38e9bb0,0x1e7b487,0x11511b3,0x1036fb3,0x25aba54, + 0x1eb2764,0x048d022,0x0d971ed,0x1bb7fb5,0x100f0b4,0x06c3756, + 0x2f0d366,0x3c6e160,0x0011bd6 } }, + /* 146 */ + { { 0x36bc9d1,0x24d43c1,0x12c35cf,0x2fb3cf3,0x015d903,0x16bc0c7, + 0x0fc8c22,0x3195c87,0x2488b1c,0x1f82b4c,0x30014e8,0x27ee58d, + 0x31658dd,0x1684a5f,0x00f0f3a }, + { 0x1f703aa,0x023eebc,0x20babb9,0x080bd9d,0x12f9cc4,0x1a8e2d4, + 0x0eec666,0x1176803,0x33005d6,0x1137b68,0x37de339,0x33d71cb, + 0x0c906b9,0x14086b5,0x00aeef6 } }, + /* 147 */ + { { 0x219045d,0x0f22c5e,0x024c058,0x00b414a,0x0ae7c31,0x3db3e96, + 0x234979f,0x0cf00a8,0x3c962c7,0x27fa77f,0x1c0c4b0,0x1fe8942, + 0x218053a,0x1eed3f8,0x0051643 }, + { 0x2a23ddb,0x138f570,0x104e945,0x21ca270,0x30726d8,0x3f45490, + 0x37d9184,0x242ea25,0x33f6d77,0x3f15679,0x065af85,0x34fa1f5, + 0x2e46b8f,0x31d17fb,0x00a2615 } }, + /* 148 */ + { { 0x335167d,0x181ea10,0x0887c8d,0x01383d7,0x18b42d8,0x263447e, + 0x1f13df3,0x0319d7e,0x0872074,0x2d6aa94,0x23d9234,0x36a69aa, + 0x0bad183,0x3138a95,0x00bd3a5 }, + { 0x1b0f658,0x0e4530b,0x373add1,0x1b968fc,0x329dcb6,0x09169ca, + 0x162df55,0x0211eff,0x02391e4,0x3867460,0x3136b1a,0x37dd36e, + 0x3bc5bd9,0x2dacfe4,0x0072a06 } }, + /* 149 */ + { { 0x119d96f,0x067b0eb,0x00996da,0x293eca9,0x2b342da,0x1889c7a, + 0x21633a6,0x0152c39,0x281ce8c,0x18ef3b3,0x0bd62dc,0x3238186, + 0x38d8b7c,0x3867b95,0x00ae189 }, + { 0x0ed1eed,0x1e89777,0x13ab73e,0x029e1d7,0x2c1257f,0x33fbc09, + 0x32d5a21,0x3d870b2,0x39bb1fd,0x33663bc,0x24e83e6,0x239bda4, + 0x3088bcd,0x01db1ed,0x00d71e7 } }, + /* 150 */ + { { 0x14245bf,0x0da0c27,0x153b339,0x05cab0a,0x122d962,0x1b0f0f3, + 0x3f5a825,0x267a2ce,0x2910d06,0x254326f,0x0f36645,0x025118e, + 0x37c35ec,0x36e944e,0x006c056 }, + { 0x05ab0e3,0x29aa0c1,0x1295687,0x1fd1172,0x08d40b5,0x05bd655, + 0x345048a,0x02a1c3c,0x2393d8f,0x0992d71,0x1f71c5e,0x18d4e8a, + 0x30dd410,0x11d61d3,0x00dd58b } }, + /* 151 */ + { { 0x2230c72,0x30213d8,0x05e367e,0x329204e,0x0f14f6c,0x3369ddd, + 0x0bb4074,0x2edafd6,0x1b1aa2d,0x0785404,0x0c035ab,0x220da74, + 0x1f2fdd4,0x092a091,0x00ef83c }, + { 0x3dc2538,0x1cca3e7,0x246afb5,0x24c647f,0x0798082,0x0bb7952, + 0x0f5c443,0x008b38a,0x299ea1a,0x3c6cf36,0x3df2ec7,0x398e6dc, + 0x29a1839,0x1cadd83,0x0077b62 } }, + /* 152 */ + { { 0x25d56d5,0x3546f69,0x16e02b1,0x3e5fa9a,0x03a9b71,0x2413d31, + 0x250ecc9,0x1d2de54,0x2ebe757,0x2a2f135,0x2aeeb9a,0x0d0fe2b, + 0x204cb0e,0x07464c3,0x00c473c }, + { 0x24cd8ae,0x0c86c41,0x221c282,0x0795588,0x1f4b437,0x06fc488, + 0x0c81ecd,0x020bf07,0x3a9e2c8,0x2294a81,0x3a64a95,0x0363966, + 0x32c9a35,0x0f79bec,0x0029e4f } }, + /* 153 */ + { { 0x289aaa5,0x2755b2e,0x059e0aa,0x3031318,0x0f0208a,0x35b7729, + 0x00d9c6b,0x3dd29d0,0x075f2c2,0x0ece139,0x31562dd,0x04187f2, + 0x13b8d4c,0x0920b85,0x003924e }, + { 0x09808ab,0x2e36621,0x2a36f38,0x1829246,0x229bf32,0x20883b7, + 0x159ada8,0x3108a14,0x15bbe5b,0x1e2d1e4,0x1730096,0x0d35cbb, + 0x15d0da9,0x0e60b94,0x00c4f30 } }, + /* 154 */ + { { 0x31de38b,0x27b9086,0x2760e3e,0x169098d,0x2a124e2,0x00596c6, + 0x3f73c09,0x0d31642,0x2341464,0x248600a,0x2e1fa10,0x2aa0fc8, + 0x051e954,0x00f3b67,0x001d4bd }, + { 0x18751e6,0x25a8e1e,0x07f5c2d,0x17e30d4,0x0ed2723,0x23093e2, + 0x3b80e2c,0x13de2d7,0x2fad37f,0x1be1cfb,0x3224ba9,0x0a7f5d3, + 0x1714972,0x06667b7,0x009dcd9 } }, + /* 155 */ + { { 0x294f22a,0x3e06993,0x0341ee9,0x24bdc7b,0x2e56098,0x2660a13, + 0x018ddda,0x2c261b2,0x2953b54,0x267f51c,0x0e8a7cc,0x29ab00c, + 0x3a38247,0x397ac81,0x00de684 }, + { 0x36b956b,0x347b34a,0x35834bd,0x053c06c,0x0090844,0x148cec5, + 0x380b325,0x2f17b8b,0x054ef5e,0x09683fb,0x3f8b29a,0x33c979a, + 0x1e01474,0x3e81fca,0x001c757 } }, + /* 156 */ + { { 0x30fdfe4,0x2d712ba,0x13671bc,0x2cfc226,0x3d7c649,0x16f020e, + 0x368e3f0,0x2981ebb,0x246a78a,0x115e81b,0x21223a4,0x04dbb30, + 0x1a50ba2,0x12114bd,0x0089bd6 }, + { 0x055f15a,0x1046e51,0x00fd724,0x1c022a7,0x323dfa9,0x36d8efb, + 0x0da4d16,0x0910dec,0x2c1fb16,0x2dbe29f,0x298284f,0x2b273bb, + 0x26022c1,0x20accd5,0x00085a5 } }, + /* 157 */ + { { 0x01f138a,0x2d87e7b,0x0c2815c,0x0c19a3c,0x311c9a2,0x3e4fce3, + 0x029729d,0x21236b2,0x2984048,0x3f3bc95,0x2bba8fb,0x1a1b680, + 0x0619a3f,0x29e0447,0x00ed5fe }, + { 0x2d1c833,0x3dcef35,0x3f809b4,0x01a1b9e,0x1509516,0x10ac754, + 0x2735080,0x27b0a8a,0x2495fb8,0x0a7bdba,0x1ef8b89,0x00233a5, + 0x0568bf1,0x1a126ba,0x0078a7e } }, + /* 158 */ + { { 0x0470cd8,0x20e9f04,0x30003fe,0x20be1b7,0x1927346,0x2a5026d, + 0x1ac06bd,0x2717ed7,0x2609493,0x3079ea5,0x1cc116d,0x31b0541, + 0x2c8ccde,0x10219ae,0x001a52b }, + { 0x2864045,0x0e8d95b,0x2fc1530,0x0aa44e7,0x345eae7,0x3cc7553, + 0x3ec6466,0x229b60e,0x06f6e95,0x00bed2a,0x0ff4403,0x181c639, + 0x2e0df67,0x1f8fa46,0x0000811 } }, + /* 159 */ + { { 0x04310a2,0x20cee8e,0x09fc5d5,0x3707f5b,0x0bdfb4e,0x12713ee, + 0x24f1028,0x0787ee6,0x39a581c,0x3797ec8,0x10a9746,0x112cb9f, + 0x142b9ba,0x1da0ef6,0x0078f7b }, + { 0x07607ae,0x3232872,0x2a7e076,0x0bb572a,0x182b23c,0x1d8f918, + 0x181f392,0x37c45a9,0x24a3886,0x0b2a297,0x264e7f2,0x1fa433c, + 0x0fcfcc8,0x21c0857,0x0004f74 } }, + /* 160 */ + { { 0x01d161c,0x1744585,0x2d17528,0x03a4f13,0x267cd2e,0x30d861f, + 0x062a647,0x213284b,0x139ed25,0x27d4ca5,0x02fbbd6,0x31ddf11, + 0x3c50ac4,0x1dd86f7,0x00107de }, + { 0x16beebd,0x1b7317a,0x2151997,0x256a196,0x3be2aff,0x3621cab, + 0x0a9da19,0x05f3038,0x23da63c,0x3178d5e,0x215cc67,0x07f7f63, + 0x0c6d8d3,0x3bf5e5c,0x00c44bb } }, + /* 161 */ + { { 0x00c62f1,0x3e0f893,0x1572703,0x3b93865,0x19b1e28,0x389b33b, + 0x02858bf,0x0e3e9aa,0x04bc436,0x234e072,0x25ba43d,0x3dca19e, + 0x0274394,0x20f442e,0x003b4a7 }, + { 0x176451e,0x2b5ed5d,0x35c8ee1,0x25c52da,0x0c3d0b5,0x32b306e, + 0x030954f,0x275ecf7,0x10e472c,0x21577c4,0x02f8a32,0x321bb5c, + 0x0098f97,0x104e237,0x00d0433 } }, + /* 162 */ + { { 0x0a8f2fe,0x034548b,0x141f1a6,0x121246f,0x1616409,0x237f80d, + 0x2e29a55,0x1218db6,0x3ea278e,0x1669856,0x1ad7c8e,0x36d11de, + 0x2c2fcbb,0x18c0b3a,0x001c706 }, + { 0x1699b4b,0x2d531a6,0x17e85e2,0x1b48e78,0x2b509ca,0x2818ea0, + 0x0165fee,0x0b809ca,0x09db6a2,0x3dad798,0x326ee1d,0x204e416, + 0x091fa12,0x1c890e5,0x0007b9f } }, + /* 163 */ + { { 0x0ff4e49,0x0bb0512,0x0129159,0x05db591,0x03e4e9f,0x055ab30, + 0x0f82881,0x0ac2deb,0x3a8bb09,0x356a8d2,0x3d38393,0x03e4089, + 0x38187cd,0x1377a93,0x0041672 }, + { 0x0139e73,0x3990730,0x187d3c4,0x33e4793,0x2e0fe46,0x2ad87e2, + 0x33c792c,0x21d4fb6,0x1e4d386,0x2932d1b,0x20f1098,0x1270874, + 0x0ea6ee4,0x0167d6e,0x005e5fd } }, + /* 164 */ + { { 0x1856031,0x2b7519d,0x3bd07fc,0x337abcb,0x089c7a4,0x2a1f120, + 0x3523ce7,0x2ba406b,0x09561d9,0x1797f04,0x3cdb95f,0x2d6193e, + 0x32c7d3f,0x223aed6,0x00beb51 }, + { 0x2e65825,0x158f0ce,0x16413d1,0x310395f,0x3116854,0x250baf4, + 0x373d341,0x156cc47,0x104c069,0x0893716,0x195a0a6,0x035320e, + 0x37b7d8a,0x21b5755,0x00fb26b } }, + /* 165 */ + { { 0x286ae17,0x04239f1,0x1a56c53,0x0e74707,0x29090d7,0x2bb142b, + 0x03b0139,0x1aac916,0x08ba49a,0x0376682,0x3382f85,0x064bbab, + 0x2910e28,0x1d5bd7f,0x00cc8df }, + { 0x0ab7630,0x208e8e7,0x3fc1877,0x26bee39,0x264984a,0x192ff05, + 0x08ef9c3,0x0aa6951,0x071c44e,0x26eed3e,0x035c95e,0x06906ad, + 0x10a0690,0x397eaa9,0x00c6c23 } }, + /* 166 */ + { { 0x034d8dd,0x005b064,0x279bb78,0x12c2c4f,0x1856bb4,0x0c90681, + 0x06409ab,0x3b48617,0x19a2d78,0x0a34bf8,0x326eddf,0x31f09b5, + 0x04f04dc,0x3d7c944,0x003ccaf }, + { 0x321f843,0x35fb71a,0x1e4c397,0x377a5d7,0x2da88e4,0x3d6ada7, + 0x33d3964,0x1b30149,0x0e39aae,0x054dda0,0x3e6f946,0x1273394, + 0x3ffd3f7,0x2f6655e,0x00021dd } }, + /* 167 */ + { { 0x37233cf,0x11617dd,0x26f07b6,0x3d8250a,0x0fe6771,0x3f9bbbc, + 0x2aba7ad,0x200a58d,0x3568603,0x198eefa,0x1e8fcf3,0x3b9610b, + 0x20524ac,0x2a67528,0x0048d9a }, + { 0x1a5e57a,0x1e9d303,0x16c9cff,0x0f39527,0x3c23259,0x03c8a1e, + 0x104bccf,0x182d5a1,0x18dbc83,0x05b5f42,0x1b402f4,0x317c525, + 0x11bf1ea,0x3c46e1f,0x0061936 } }, + /* 168 */ + { { 0x0153a9d,0x36859ee,0x2cf0aa9,0x2b27a0f,0x0a49fe3,0x2d984e1, + 0x018f8e1,0x1378453,0x1ab3843,0x1987093,0x283dae9,0x25cf0e8, + 0x14fc93d,0x280609d,0x00c99ba }, + { 0x026b1e3,0x34663d3,0x2202477,0x21a9d45,0x212e8e1,0x18ab77e, + 0x2e52f63,0x0a14ce1,0x295c396,0x00c7a3d,0x2aaedb6,0x30abc4d, + 0x374acde,0x1318a73,0x00fcfdb } }, + /* 169 */ + { { 0x0a40298,0x3ba5633,0x11956b3,0x14fcbd7,0x3c38781,0x34bab96, + 0x165630e,0x1f3c831,0x37e3a69,0x2b4226c,0x2d5029e,0x3b4ab1e, + 0x1da6ac2,0x3eb43c3,0x007e5cd }, + { 0x1b86202,0x109b7f6,0x2054f98,0x2c50cd7,0x2ed1960,0x3c518e7, + 0x1b02463,0x319c07f,0x1c30db6,0x045fdc2,0x373421e,0x31a1eb9, + 0x1a8acbf,0x31289b0,0x0013fef } }, + /* 170 */ + { { 0x3fa0a5f,0x068661f,0x2109e36,0x00b18ff,0x1f4b261,0x31d3844, + 0x0acbc56,0x3aebc99,0x1fa77ab,0x152bd11,0x24cddb7,0x2313f74, + 0x06eea44,0x15f5114,0x000b131 }, + { 0x2e9993d,0x1ac565c,0x2cbe22a,0x3921797,0x12c3c57,0x360f868, + 0x33560bf,0x320ee99,0x382c3b8,0x39af88f,0x00bbe38,0x2c4ea59, + 0x3399b40,0x00ceb45,0x0066eea } }, + /* 171 */ + { { 0x0c6c693,0x31ba56d,0x3d3849f,0x378dabd,0x0efc735,0x17f90bf, + 0x13343d3,0x2df0f81,0x27c6a9a,0x13c2a90,0x0a0fcb2,0x27c10d9, + 0x3bc50c7,0x090e4fa,0x0016287 }, + { 0x2927e1e,0x35af405,0x184c5c3,0x3499cee,0x240158e,0x33522e6, + 0x386fc84,0x0a0b69f,0x1a660ea,0x34590fb,0x22a1bee,0x2ce4fab, + 0x31a9445,0x0e78655,0x00664c8 } }, + /* 172 */ + { { 0x3eeaf94,0x115d409,0x21e7577,0x097aa67,0x22875c9,0x021ab7a, + 0x27e7ba5,0x1093f04,0x2a086fe,0x05d9494,0x2b6c028,0x10f31b0, + 0x1312d11,0x262759c,0x00c9bb2 }, + { 0x1acb0a5,0x30cdf14,0x0f78880,0x0574f18,0x1a37109,0x098adbb, + 0x2113c09,0x2060925,0x1f89ce4,0x1974976,0x3381358,0x2dab5ca, + 0x2159c53,0x3af1303,0x000ea3b } }, + /* 173 */ + { { 0x1e49bea,0x29142b1,0x1a59cab,0x055f017,0x0684e54,0x39eb0db, + 0x29cab9d,0x255ee8b,0x35f2e6f,0x05329e6,0x09b817b,0x1ec091c, + 0x1df0fef,0x2641f62,0x00eb304 }, + { 0x2fe5096,0x3dcc1d1,0x2aaf508,0x3a0b813,0x0695810,0x144bddb, + 0x2f1bd93,0x281ae23,0x3513ebc,0x1ddd984,0x0cf158b,0x35218eb, + 0x257daf7,0x391253b,0x00b2a81 } }, + /* 174 */ + { { 0x153e6ba,0x22396db,0x0ea2ff2,0x2a45121,0x0a90de1,0x34cf23b, + 0x2db60ce,0x1a900be,0x2f328b6,0x355e75b,0x2c24372,0x0b75b77, + 0x2ec7d4f,0x3f24759,0x00e9e33 }, + { 0x39eab6e,0x2267480,0x3b5e110,0x1e8fa5e,0x2a31a66,0x3f739a3, + 0x00166dc,0x3552d88,0x3ae5137,0x3efa0fa,0x0800acd,0x17df61d, + 0x38c8608,0x04cc31b,0x00cf4ab } }, + /* 175 */ + { { 0x31e08fb,0x1961164,0x22c003f,0x078541b,0x3643855,0x30da587, + 0x11f0dc9,0x324595e,0x329e3dc,0x29a041e,0x3495d2c,0x0908dd3, + 0x1895b83,0x198dbb9,0x00d8cfb }, + { 0x0349b1b,0x383c5a8,0x2b86525,0x1b1283e,0x133cd2c,0x2be376a, + 0x012ee82,0x1eb4d1b,0x0ba71e9,0x01f3109,0x37621eb,0x1d9b77c, + 0x0d39069,0x3d5a97c,0x0095565 } }, + /* 176 */ + { { 0x20f5e94,0x1eefc86,0x1327e0e,0x054760b,0x2f771e1,0x3ac447e, + 0x033e3dc,0x198e040,0x04dd342,0x1b49a5d,0x00d01ef,0x3cb6768, + 0x1ceafbd,0x31c6812,0x001cb80 }, + { 0x221c677,0x060ca27,0x398b17f,0x0146723,0x36452af,0x02d9e65, + 0x39c5f78,0x3cf50d6,0x0be40f8,0x2970b87,0x26d667c,0x3e45959, + 0x16e7943,0x01673e7,0x009faaa } }, + /* 177 */ + { { 0x2078fe6,0x0918602,0x11dd8ad,0x399193f,0x0f6cc73,0x0f8dd12, + 0x2ce34dc,0x06d7d34,0x0c5e327,0x0989254,0x2fc5af7,0x2443d7b, + 0x32bc662,0x2fe2a84,0x008b585 }, + { 0x039327f,0x08e616a,0x252f117,0x1f52ab0,0x234e2d2,0x0a5b313, + 0x2f59ef6,0x0f7a500,0x15c4705,0x2c02b81,0x28b4f09,0x08aa5c8, + 0x0180efc,0x0993e83,0x00a9e86 } }, + /* 178 */ + { { 0x0310ecc,0x2d8892f,0x14ed0b7,0x3c59fe8,0x08a1a74,0x0850e57, + 0x1d09607,0x044a21f,0x109f5c9,0x237c6cf,0x06b264a,0x3fc8f1a, + 0x0d4c539,0x2740f96,0x00dc2d4 }, + { 0x1d6f501,0x0adf4ea,0x14f7215,0x0930102,0x3f4c32e,0x24e2643, + 0x366596d,0x081ff18,0x38f94fb,0x2c21341,0x328594c,0x267c75c, + 0x196b3fd,0x29932cb,0x0036def } }, + /* 179 */ + { { 0x3ed7cbe,0x26de044,0x3d0e461,0x0565e12,0x295e500,0x31dc17f, + 0x32251c2,0x3420ca8,0x3995f0d,0x2e8ddab,0x0361a45,0x10971b0, + 0x11e7b55,0x33bc7ca,0x00812d2 }, + { 0x3d94972,0x1606817,0x0383ccf,0x0e795b7,0x026e20e,0x0f6fefc, + 0x13685d6,0x315d402,0x0cc36b8,0x1c7f059,0x390ef5e,0x316ae04, + 0x08c66b9,0x2fac9a4,0x0040086 } }, + /* 180 */ + { { 0x3e3c115,0x153de4d,0x1a8ae5e,0x2330511,0x169b8ee,0x1d965c2, + 0x2edff2b,0x3ef99e6,0x1631b46,0x1f8a238,0x118d7bb,0x12113c3, + 0x26424db,0x0f4122a,0x00e0ea2 }, + { 0x3d80a73,0x30393bc,0x0f98714,0x278ef59,0x087a0aa,0x3b18c20, + 0x04b8a82,0x2068e21,0x030255d,0x3382b27,0x055397f,0x05448dd, + 0x2015586,0x1190be0,0x000b979 } }, + /* 181 */ + { { 0x2e03080,0x2895692,0x09fb127,0x2d1602a,0x1232306,0x105bd4e, + 0x28cd6a6,0x0a83813,0x1ee13b0,0x2abadc3,0x0c09684,0x00e33e1, + 0x033eea3,0x30f0a39,0x00a710e }, + { 0x01b1f7d,0x1c959da,0x017077a,0x254bf0a,0x086fbce,0x15cd6b2, + 0x008683f,0x23a4f4d,0x22a6bd6,0x14e8c93,0x0027d15,0x31d0d4f, + 0x271777e,0x1533510,0x00ab603 } }, + /* 182 */ + { { 0x34c209d,0x14d0abb,0x270432a,0x1d02358,0x22ba752,0x209757f, + 0x34af6fc,0x1ffc52e,0x1ced28e,0x1870e46,0x1e0340f,0x3f0bf73, + 0x33ba91d,0x2ebca7c,0x00c6580 }, + { 0x1d442cb,0x0879d50,0x24e4ae1,0x3f4e91c,0x04c7727,0x093cd1d, + 0x16d6a45,0x10a8b95,0x0c77856,0x361f84f,0x217845f,0x0bbeec6, + 0x0485718,0x33c5385,0x00dcec0 } }, + /* 183 */ + { { 0x1539819,0x225507a,0x1bf11cb,0x13e7653,0x0c8cb3b,0x05f695e, + 0x353f634,0x2827874,0x3fb8053,0x22de9a5,0x035d8b7,0x2105cc7, + 0x2a7a98d,0x35bed95,0x0085748 }, + { 0x1859c5d,0x00e51f0,0x22a21fd,0x3054d74,0x06ce965,0x328eab7, + 0x26a13e0,0x13bfc65,0x01d4fb1,0x36600b9,0x36dd3fc,0x01232ed, + 0x15bbaa9,0x0ad7a51,0x0089b18 } }, + /* 184 */ + { { 0x3360710,0x1eb5a90,0x136bd77,0x3bd57a6,0x0841287,0x12886c9, + 0x35c6700,0x21bc6eb,0x25f35ad,0x3bcb01c,0x0707e72,0x23e9943, + 0x03e5233,0x34bb622,0x002bf8e }, + { 0x16e0d6a,0x04b3d2d,0x290cb02,0x049a10c,0x350537e,0x22cf71b, + 0x3184a19,0x2dc8b62,0x2350210,0x3b4afa6,0x159781e,0x1d01b6d, + 0x1853440,0x16442f0,0x005a78d } }, + /* 185 */ + { { 0x348b02c,0x1ea8ab5,0x3b954d5,0x14684ac,0x0be5b34,0x11c4496, + 0x0a7a456,0x14f6eb7,0x11a3221,0x2d65f82,0x32eb1ea,0x09c4018, + 0x3f301f3,0x32e8a1c,0x00bd9ad }, + { 0x0543f7f,0x31e744e,0x1fefd1d,0x24a486c,0x1000220,0x3977e3b, + 0x1b3ef51,0x2512a1b,0x2049e6b,0x122232b,0x391a32b,0x2f4a7b1, + 0x1c13e71,0x081a9b4,0x00d3516 } }, + /* 186 */ + { { 0x1924f43,0x1ae5495,0x28d52ef,0x2b93e77,0x2d2f401,0x371a010, + 0x33e8d7a,0x06ed3f1,0x30c0d9d,0x2589fa9,0x3bf3567,0x2ecf8fa, + 0x2dee4c3,0x152b620,0x007e8a2 }, + { 0x1924407,0x01bd42d,0x044a089,0x18686b5,0x2f14a0e,0x17cdce3, + 0x0efa216,0x3c586a8,0x1d6ae71,0x375831f,0x3175894,0x20e43eb, + 0x34c009e,0x3480527,0x00d115c } }, + /* 187 */ + { { 0x12abf77,0x38b0769,0x25682f2,0x295508c,0x0c2a0dc,0x1259b73, + 0x023ea25,0x340e7b5,0x3c7cd0d,0x1f92324,0x176405c,0x1528894, + 0x18f2e1e,0x2c59c35,0x001efb5 }, + { 0x0fb1471,0x07e7665,0x141da75,0x07d9f4a,0x0fdb31e,0x0dccda6, + 0x074eb25,0x3d92a9b,0x11189a0,0x1b4c557,0x24b8d2b,0x0533f92, + 0x0e9e344,0x2fa3dea,0x008d5a4 } }, + /* 188 */ + { { 0x2669e98,0x1ad3514,0x2a035c9,0x08a3f50,0x24547f9,0x0a145d3, + 0x1c1319d,0x3fe833d,0x1ae064b,0x1e01734,0x246d27e,0x3a2f13c, + 0x01e1150,0x263f55e,0x00f89ef }, + { 0x2e0b63f,0x3e57db7,0x23a4b4f,0x11c8899,0x0ad8500,0x348f3a7, + 0x2918604,0x27d6409,0x1ce5001,0x38f94c2,0x29a508a,0x39bdc89, + 0x3a52c27,0x194899e,0x00e9376 } }, + /* 189 */ + { { 0x0368708,0x34a2730,0x2e1da04,0x0bd78c1,0x2c45887,0x0c44bfa, + 0x3a23de3,0x390b9db,0x1746efd,0x05c638e,0x1d20609,0x3263370, + 0x31987f0,0x2988529,0x005fa3c }, + { 0x0aa9f2a,0x20622f7,0x060deee,0x0c9626a,0x3312cc7,0x18ebac7, + 0x008dd6c,0x0ad4fe6,0x3db4ea6,0x1dc3f50,0x090b6e9,0x0aff8d2, + 0x26aa62c,0x18f3e90,0x00105f8 } }, + /* 190 */ + { { 0x38059ad,0x25e576c,0x3ea00b2,0x1fa4191,0x25686b7,0x2d1ce8f, + 0x30470ed,0x3478bbf,0x340f9b6,0x1c9e348,0x3d594ec,0x2ffe56e, + 0x3f23deb,0x0cd34e9,0x00f4b72 }, + { 0x1a83f0b,0x2166029,0x28b32a2,0x06a5c5a,0x20786c4,0x0944604, + 0x0901bd2,0x379b84e,0x221e2fe,0x0346d54,0x1f4eb59,0x01b8993, + 0x2462e08,0x25f9d8b,0x006c4c8 } }, + /* 191 */ + { { 0x0b41d9d,0x2e417ed,0x265bd10,0x199148e,0x3826ca4,0x1a67e8d, + 0x1bbd13b,0x23e414d,0x3d773bc,0x356e64c,0x0d2118a,0x0cb587f, + 0x25fd093,0x24fb529,0x00158c6 }, + { 0x2806e63,0x3ecaa39,0x251b4dd,0x3b2d779,0x2e31ed3,0x066f1a6, + 0x060e518,0x2c7e3e5,0x0d62c76,0x0d88a70,0x101970a,0x1e3c8c6, + 0x272b8bb,0x083e73b,0x0031f38 } }, + /* 192 */ + { { 0x09e1c72,0x072bcb0,0x0cf4e93,0x2604a64,0x00715f2,0x10c98b6, + 0x2ad81d9,0x234fcce,0x37a7304,0x1974a4a,0x1c7415f,0x14aaa93, + 0x19587b1,0x3f643f4,0x00c3d10 }, + { 0x1ddadd0,0x2cd715d,0x294cf76,0x14479ed,0x19f5f4a,0x0198c09, + 0x1ab7ebc,0x182c0bc,0x0879202,0x1807273,0x05d39da,0x2c7d868, + 0x29c4ec4,0x1b13ad2,0x006dcd7 } }, + /* 193 */ + { { 0x1c83f01,0x0245bff,0x24f90ba,0x112554f,0x2354c8b,0x3f17988, + 0x0c511af,0x39e1e9b,0x26ae95b,0x0ae551c,0x35b41a6,0x0120455, + 0x1e989cb,0x1b37aff,0x00fa2ae }, + { 0x324659a,0x1aef1c3,0x1c43637,0x3f530a2,0x313a999,0x326af62, + 0x134184e,0x2ac131c,0x3f6a789,0x30a300a,0x13e526e,0x2107af3, + 0x093a8ff,0x2479902,0x00442b1 } }, + /* 194 */ + { { 0x22b6e20,0x31b18be,0x18614ca,0x26fdb5a,0x197f29e,0x325b44b, + 0x0ab1dbb,0x042348a,0x3275e8e,0x15bae44,0x0077124,0x2cf5345, + 0x2803ad4,0x188f2a2,0x0061b20 }, + { 0x2a560b1,0x3ced069,0x3cf42c2,0x100e167,0x3879e1d,0x0936ff0, + 0x1b51450,0x14c55f3,0x3153bfa,0x2957423,0x2a93823,0x15f5dce, + 0x2c9a22f,0x16731a8,0x00a97f2 } }, + /* 195 */ + { { 0x18edbbb,0x18c5ef9,0x1f13c30,0x071e77f,0x225ade5,0x1b60f75, + 0x1beaf11,0x3e495ad,0x2441dd8,0x2fa00e2,0x32a87b6,0x00050f2, + 0x038de7f,0x0037d6d,0x00a885d }, + { 0x39e48bd,0x1d9e433,0x2768e9f,0x3c29458,0x3f0bdf9,0x35ed5f2, + 0x36709fa,0x176dc10,0x012f7c1,0x2df8547,0x1d90ee3,0x053c089, + 0x21a8d35,0x200cb0d,0x002e84e } }, + /* 196 */ + { { 0x23ec8d8,0x1d81f55,0x0cb7227,0x07f8e4d,0x2a66181,0x163f577, + 0x272e7af,0x131a8f2,0x2046229,0x25e6276,0x36bbefe,0x2cdc22f, + 0x17c8288,0x33dd4fb,0x000d524 }, + { 0x330c073,0x1a6728b,0x1cf369f,0x12e7707,0x2f0fa26,0x17c2abd, + 0x0a45680,0x26ebd13,0x3c7d19b,0x1c3d6c8,0x2abd110,0x064fd07, + 0x09b8339,0x02b4a9f,0x009e3e1 } }, + /* 197 */ + { { 0x0ae972f,0x2093c35,0x06e7a90,0x0af1ba1,0x243eef0,0x2748582, + 0x0606122,0x13a45f9,0x0acfe60,0x08a685e,0x0eb184b,0x015bc11, + 0x0cdf423,0x157fad5,0x004fcad }, + { 0x2728d15,0x3e5bceb,0x0331a0f,0x31b1a80,0x28a2680,0x3b94955, + 0x04cae07,0x176b57e,0x03ac5a6,0x3d7918b,0x22d23f4,0x0ae077f, + 0x1eb075d,0x006f16c,0x006e473 } }, + /* 198 */ + { { 0x38219b9,0x0475a2b,0x107a774,0x39946c6,0x1cb883c,0x004e0ed, + 0x087e571,0x25c3497,0x059982f,0x0a71f66,0x118305d,0x1aaf294, + 0x3a5dbaa,0x34be404,0x00725fe }, + { 0x3abd109,0x336ebea,0x2528487,0x15a1d61,0x0c0f8cf,0x2b56095, + 0x2591e68,0x3549a80,0x1d1debb,0x0701c6c,0x161e7e3,0x1f7fa2e, + 0x3dfe192,0x17e6498,0x0055f89 } }, + /* 199 */ + { { 0x175645b,0x26c036c,0x0b92f89,0x09ed96d,0x351f3a6,0x19ce67b, + 0x33ac8db,0x2f0828b,0x27fe400,0x0b9c5e1,0x1967b95,0x3324080, + 0x11de142,0x1d44fb3,0x003d596 }, + { 0x3979775,0x3af37b6,0x3e88d41,0x2f1a8b9,0x299ba61,0x085413c, + 0x1149a53,0x0beb40e,0x31427ba,0x239f708,0x357d836,0x1558c22, + 0x280a79f,0x1b255f6,0x002b6d1 } }, + /* 200 */ + { { 0x39ad982,0x3d79d89,0x01a684a,0x0b6722e,0x39bb4c9,0x39a6399, + 0x1ad44e0,0x3059f5e,0x048265f,0x33a2fa4,0x0c3a4cc,0x0d7df98, + 0x23a33f1,0x34e2e21,0x00a0a10 }, + { 0x386efd9,0x1c91f34,0x06c2e19,0x3e6d48d,0x00eefd3,0x2181ef2, + 0x2415f97,0x1d33b08,0x0625086,0x1e8aa3e,0x08c9d60,0x0ab427b, + 0x2764fa7,0x3b7943e,0x00cd9f0 } }, + /* 201 */ + { { 0x1a46d4d,0x0e471f4,0x1693063,0x0467ac0,0x22df51c,0x127a0f7, + 0x0498008,0x20e0b16,0x1aa8ad0,0x1923f42,0x2a74273,0x01761ce, + 0x1600ca4,0x187b87e,0x00ee49e }, + { 0x0c76f73,0x19daf92,0x0b2ad76,0x3d8049d,0x1d9c100,0x0fe1c63, + 0x0bb67c8,0x035cc44,0x02002fc,0x37b2169,0x344656a,0x1127879, + 0x1939bc0,0x0dd8df6,0x0028ce7 } }, + /* 202 */ + { { 0x0544ac7,0x26bdc91,0x042697e,0x356e804,0x1f2c658,0x2ceb7ef, + 0x2dec39f,0x02c1dcc,0x391a2df,0x2344beb,0x2171e20,0x3099c94, + 0x0fa548a,0x37216c9,0x00f820c }, + { 0x0f4cf77,0x29bbaa5,0x33c6307,0x34a5128,0x118c783,0x2dd06b1, + 0x139d4c0,0x2db912e,0x1153ffb,0x1075eb3,0x3a255e4,0x2892161, + 0x36d5006,0x125338c,0x0014fbc } }, + /* 203 */ + { { 0x1584e3c,0x0830314,0x00279b9,0x167df95,0x2c7733c,0x2108aef, + 0x0ce1398,0x35aaf89,0x012523b,0x3c46b6a,0x388e6de,0x01a2002, + 0x0582dde,0x19c7fa3,0x007b872 }, + { 0x1e53510,0x11bca1f,0x19684e7,0x267de5c,0x2492f8b,0x364a2b0, + 0x080bc77,0x2c6d47b,0x248432e,0x3ace44f,0x32028f6,0x0212198, + 0x2f38bad,0x20d63f0,0x00122bb } }, + /* 204 */ + { { 0x30b29c3,0x3cec78e,0x01510a9,0x0c93e91,0x3837b64,0x1eca3a9, + 0x105c921,0x05d42e6,0x1379845,0x07ce6f2,0x0e8b6da,0x0e0f093, + 0x220b2cd,0x1f6c041,0x00299f5 }, + { 0x0afdce3,0x2b0e596,0x2f477b6,0x2ccf417,0x3a15206,0x26ec0bf, + 0x2e37e2b,0x2593282,0x0ab9db3,0x2841dd8,0x27954be,0x277a681, + 0x03f82e2,0x2b610c7,0x00446a1 } }, + /* 205 */ + { { 0x06b8195,0x3b3a817,0x31b9c6f,0x317d279,0x3d744a7,0x1de9eb9, + 0x296acc1,0x1ce9ea3,0x06c3587,0x246815d,0x3756736,0x0588518, + 0x1c971a4,0x1fde1f4,0x00aa021 }, + { 0x3fd3226,0x274561d,0x00be61e,0x01393d8,0x30f6f23,0x29b7fc1, + 0x04cebc7,0x0a892a7,0x20109f1,0x27456be,0x0c863ee,0x2eb6c8a, + 0x38c782b,0x039397a,0x00a2829 } }, + /* 206 */ + { { 0x29de330,0x21fe80f,0x145b55b,0x1986570,0x012b260,0x2482fbc, + 0x0536e0a,0x16b7382,0x32c4d19,0x1deffdb,0x145f418,0x0c67a76, + 0x2ce477f,0x218fe24,0x00f9848 }, + { 0x3e37657,0x3f074d3,0x245ad0e,0x20973c3,0x23c58de,0x2c332ef, + 0x2ad21a8,0x0bf1589,0x208af95,0x1f4a8c4,0x2b43735,0x1e46657, + 0x15d4f81,0x0c3e63a,0x005f19d } }, + /* 207 */ + { { 0x26865bb,0x20f6683,0x16a672e,0x0efd8d1,0x222f5af,0x18f2367, + 0x1e9c734,0x25c3902,0x178dfe6,0x2903a79,0x311b91c,0x1adbbe9, + 0x225a387,0x0b3e509,0x0089551 }, + { 0x34e462b,0x23b6a32,0x27c884c,0x129104b,0x384c015,0x3adedc7, + 0x325db1c,0x021dc10,0x1e366f7,0x3054df7,0x1992b9a,0x2824e64, + 0x0ae77f3,0x181b526,0x00a7316 } }, + /* 208 */ + { { 0x2d260f5,0x2434bf2,0x28c0139,0x0a7bb03,0x176c3be,0x3def5f5, + 0x05bee00,0x3692df7,0x3d2efeb,0x3a6f859,0x1122b87,0x38f779a, + 0x1415ccc,0x2c260ad,0x0075a28 }, + { 0x04607a6,0x042f37a,0x3f0df68,0x0a1bd36,0x3c6d581,0x2d36bfa, + 0x2d577d1,0x0a3affa,0x0b2066b,0x2e6f110,0x0b17e84,0x3c76a5e, + 0x1a57553,0x012f36a,0x0004595 } }, + /* 209 */ + { { 0x29e5836,0x0e6808c,0x269d13e,0x147dc5c,0x32c9e7d,0x09b258e, + 0x2c58d6f,0x1efd716,0x0437996,0x34ec31b,0x15908d9,0x2efa8fd, + 0x09ad160,0x079fc1f,0x00d8481 }, + { 0x3d20e4a,0x18269d6,0x3aa8fe7,0x34829c2,0x2e4325d,0x0d800e1, + 0x11f370b,0x10c08dc,0x22fd092,0x1a5fe55,0x0acc443,0x037030d, + 0x1cdd404,0x097379e,0x00fd6d7 } }, + /* 210 */ + { { 0x313eafb,0x3f438f3,0x2e5fb3e,0x2ed6a82,0x121009c,0x240889e, + 0x00c5537,0x269b792,0x334b2fc,0x1dd573c,0x07096ae,0x19296fc, + 0x3813985,0x2742f48,0x00ddd64 }, + { 0x2045041,0x3842c62,0x1572d0d,0x04f255f,0x06e05b4,0x383ec97, + 0x1ff8064,0x18bed71,0x39b6411,0x2764cc5,0x257439f,0x3521217, + 0x172aa42,0x342a2a3,0x0070c5b } }, + /* 211 */ + { { 0x3bdf646,0x1c5ce25,0x1f7ca76,0x2d2acca,0x3aa1485,0x23c97f7, + 0x3e11d6f,0x0609338,0x07ec622,0x01da8ff,0x3392474,0x17ca07f, + 0x13a9a04,0x353a5b4,0x0024557 }, + { 0x14c27cd,0x32012f7,0x3fea875,0x3d03d71,0x211c5f0,0x3157fdf, + 0x0c880bd,0x3c406b2,0x2c51103,0x24ab377,0x399faa8,0x0d06887, + 0x16b5738,0x28b33a7,0x00c7b67 } }, + /* 212 */ + { { 0x2357586,0x35c93e3,0x0da09a0,0x3d77d92,0x11d7f4f,0x37b98a9, + 0x3e6c9bf,0x2cdca70,0x2f00389,0x2412673,0x18eab87,0x0101436, + 0x11617e9,0x06d9b01,0x00e8eef }, + { 0x37e3ca9,0x16ffaf0,0x391debf,0x1b69382,0x07c5e94,0x312fa8a, + 0x0973142,0x2cadde4,0x109ee67,0x3a07db0,0x1afc5ed,0x08df66f, + 0x304c7af,0x0804aae,0x00d2e60 } }, + /* 213 */ + { { 0x24f57bf,0x1818322,0x182a615,0x25bfc44,0x0f97586,0x0a5bbc0, + 0x36773c6,0x1a2660c,0x3ceff66,0x3270152,0x319cd11,0x2845845, + 0x1acfad6,0x19076f8,0x009824a }, + { 0x289fd01,0x2de97ee,0x39d80b7,0x026227d,0x0f8d3b8,0x15e0a17, + 0x21ea08f,0x20a2317,0x136ae6d,0x3deb1d1,0x3521ef5,0x0de8801, + 0x0a25d5d,0x0612c98,0x005ecc4 } }, + /* 214 */ + { { 0x308c8d3,0x3aec669,0x01ecddc,0x13f18fe,0x1e63ed0,0x061cfe5, + 0x05f5a01,0x1db5741,0x14479f2,0x0ced6b5,0x025ae5b,0x09ca8f5, + 0x2160581,0x1404433,0x008bfeb }, + { 0x08228bf,0x0e02722,0x37df423,0x33ecabf,0x34bd82a,0x32f529f, + 0x28f1800,0x0c8f671,0x1246b44,0x1ff35dc,0x091db95,0x303f3da, + 0x28f7f60,0x3624136,0x00cfbb4 } }, + /* 215 */ + { { 0x326139a,0x2977e4e,0x3eb89a6,0x20ecb31,0x13e076a,0x2a592f3, + 0x28e82d5,0x235ad1e,0x239b927,0x262938a,0x2444354,0x141b263, + 0x0d56693,0x2a3fc78,0x0006497 }, + { 0x31efa05,0x3a3664a,0x3e333de,0x2a114e4,0x12da63c,0x3c15e6b, + 0x2f7277c,0x363aa92,0x2393236,0x16bd2d1,0x32b617f,0x32b656c, + 0x3b1246c,0x22e2e22,0x00ce76d } }, + /* 216 */ + { { 0x03843dc,0x094de82,0x13b463d,0x0507905,0x089eb35,0x2a6bf25, + 0x35ebc4e,0x2bb5d45,0x1808ed1,0x1de9949,0x185e829,0x0a55847, + 0x0b73d67,0x1a2ed61,0x008dd2d }, + { 0x133c3a4,0x04e7980,0x38ea237,0x2ad2f49,0x19de838,0x018bf36, + 0x29b072c,0x21c1ba0,0x14f63ba,0x31c1cc3,0x13cd05e,0x20120ff, + 0x1f84d60,0x16e0321,0x00872ab } }, + /* 217 */ + { { 0x19d4d49,0x1ddb4e6,0x05e7fc0,0x37bb0fd,0x1a3eb59,0x36b87f0, + 0x190e440,0x1c7fef2,0x31ea153,0x14cd65a,0x1bc7ab2,0x11f72ca, + 0x39582d4,0x0fa4d65,0x00cd5b6 }, + { 0x3d1ff11,0x0d9be9d,0x2903ae3,0x017b7b9,0x259f28f,0x110cefc, + 0x03fed1a,0x38039bd,0x09bdf9c,0x3055027,0x2ca9c5d,0x2d737b6, + 0x3bdb421,0x16560b5,0x00f9f33 } }, + /* 218 */ + { { 0x022c792,0x110de25,0x38bf959,0x08f2562,0x1239ea9,0x3c1d950, + 0x21a247d,0x315112d,0x285bb9f,0x2534a73,0x0b42455,0x1a4a99c, + 0x069009a,0x1680392,0x006e0ca }, + { 0x1b3bece,0x269e0a1,0x18926b7,0x0e7187e,0x241f35e,0x39d1fe0, + 0x02099aa,0x1675bfe,0x23fd0ca,0x3d6322b,0x19406b5,0x324c38a, + 0x242434a,0x3ae677c,0x002ce04 } }, + /* 219 */ + { { 0x2c37b82,0x1ae6506,0x0d83436,0x23496c1,0x0ff0c72,0x2711edf, + 0x1513611,0x04f9c7d,0x1edbeff,0x376fcb5,0x212a683,0x23bf547, + 0x0f9c4f7,0x16e6627,0x0082cd8 }, + { 0x0cb5d37,0x31b6db8,0x1a15e23,0x2f5cbb8,0x0818aee,0x21dc6c5, + 0x12aafd2,0x205f608,0x1d91def,0x3def088,0x1445c51,0x3100e8a, + 0x3746bda,0x145c4b0,0x00711b0 } }, + /* 220 */ + { { 0x2a99ecc,0x27b5217,0x35e10ed,0x036e32a,0x0f79950,0x15c32f7, + 0x2c87dcb,0x3ebb2a3,0x2c2d35d,0x114b3ec,0x2e4d80a,0x0c7eb89, + 0x2abe58d,0x3727737,0x00e6a37 }, + { 0x1eca452,0x1968d07,0x344e5d3,0x29435a2,0x109a5f8,0x181d12c, + 0x238ea5a,0x127a564,0x00dbb42,0x0fcbfb7,0x2909b2e,0x2571d3a, + 0x08250e3,0x0694e4e,0x00e156d } }, + /* 221 */ + { { 0x3181ae9,0x1acf411,0x3808d79,0x2a11065,0x0baf44b,0x133cfeb, + 0x1330943,0x1711b9a,0x2dec3bd,0x1906a9a,0x2ed947c,0x369d763, + 0x1a5254f,0x104a7a9,0x00acd9d }, + { 0x030301b,0x31568f5,0x2a4965c,0x33ded4b,0x03c9a5b,0x16541fc, + 0x1319cf1,0x2a3748b,0x1b5de74,0x18bb82e,0x077ac2b,0x309a87a, + 0x3c31420,0x0f6a4b9,0x00387d7 } }, + /* 222 */ + { { 0x0d3fdac,0x120cfa3,0x1b8e13c,0x1ccccb9,0x376fcd4,0x0bf87f4, + 0x271b4be,0x363b3fd,0x28b5d98,0x0535cd3,0x114bbc1,0x3ab4f19, + 0x10494b1,0x2161ece,0x00d14ca }, + { 0x12d37e9,0x110ebd7,0x062295a,0x1cc0119,0x073c6ea,0x15d5411, + 0x0aeb4b1,0x23fba91,0x175fab5,0x3ee8fe1,0x1c680a6,0x1e76f27, + 0x3ddfc97,0x3d69ecd,0x00e1ee5 } }, + /* 223 */ + { { 0x2d29f46,0x2d19204,0x3137cd0,0x02c3b54,0x193295b,0x02fbdb2, + 0x2260948,0x22c02ff,0x3885424,0x1299595,0x00e7f9c,0x310ff2a, + 0x01ea169,0x0deef85,0x0021908 }, + { 0x1b26cfb,0x38566a8,0x2852875,0x21debff,0x290ca9f,0x0b29663, + 0x26550d9,0x2b44457,0x05d1938,0x1f8f825,0x366ef93,0x1d8daec, + 0x069e5ef,0x342ece6,0x00b6034 } }, + /* 224 */ + { { 0x2d8356e,0x1578c09,0x226f4d2,0x3b74c51,0x0f83666,0x0323b59, + 0x1ddf61d,0x1ed8508,0x3c52667,0x0e5b91c,0x1e9b18b,0x352bdfa, + 0x13f75da,0x352aa4e,0x00fceff }, + { 0x1c731d5,0x04e2844,0x01d9843,0x286cbc5,0x105bcb3,0x05edd9c, + 0x21fa956,0x3b1ec83,0x01288cc,0x22fbf3a,0x10f1b56,0x081cf72, + 0x15cb758,0x18687c1,0x00f5722 } }, + /* 225 */ + { { 0x2973088,0x1209dcd,0x3980f31,0x0221aa7,0x1c008e7,0x011b098, + 0x395947e,0x2f2806d,0x27dca76,0x037c79a,0x31acddf,0x2bf6219, + 0x0d8f4ab,0x13644d9,0x00ff705 }, + { 0x2260594,0x18d51f8,0x277e2cf,0x1cb5cec,0x2468a53,0x3e6f4d7, + 0x019e24e,0x0f30f1d,0x0202404,0x34ad287,0x090b39c,0x23c11ea, + 0x1a2e3a2,0x3a851be,0x00dca2c } }, + /* 226 */ + { { 0x3277538,0x221cd94,0x3738ab7,0x0973da5,0x1a734e2,0x2c8b8b0, + 0x2e1d1e6,0x348499b,0x389ebe1,0x18b1854,0x02bb076,0x1b2b500, + 0x0f207f3,0x170cf99,0x0012088 }, + { 0x0fbfec2,0x1df55a4,0x34ae59e,0x2ab5e95,0x3f9e781,0x3411794, + 0x1410b05,0x17c3a00,0x0aaa91b,0x074ed7c,0x3fbb352,0x3477c01, + 0x3ee9ab3,0x0cfb1ca,0x0011c4b } }, + /* 227 */ + { { 0x3c3a7f3,0x2e60ca0,0x2354d32,0x33e2362,0x28083ab,0x03d3b16, + 0x3164045,0x0a41f7a,0x3f0641e,0x38635d1,0x31bbf03,0x225e2bb, + 0x0cd894e,0x1f72228,0x0093244 }, + { 0x33d5897,0x383faf3,0x0e6d561,0x0bc4d80,0x3fc3a68,0x05a9adc, + 0x0b9d73d,0x3d6031e,0x2ded29b,0x339c4ff,0x08d69e5,0x089488c, + 0x3fda40a,0x295c7fd,0x003a924 } }, + /* 228 */ + { { 0x0093bee,0x115532d,0x2ec0fb6,0x0969631,0x3a6d65a,0x0f43b4d, + 0x26994d4,0x0b51104,0x2515515,0x3695a26,0x284caa8,0x397aa30, + 0x25538b8,0x353f47c,0x0033f05 }, + { 0x3615d6e,0x37f8246,0x07dae0f,0x23dc154,0x02ded7e,0x1eef320, + 0x1631e51,0x3447f75,0x13e267f,0x353e1d1,0x3f89d62,0x369c8ff, + 0x1a21dc6,0x2b8b8f3,0x0055cbc } }, + /* 229 */ + { { 0x34e84f3,0x2f2539a,0x2c35336,0x0c53bdc,0x1728630,0x3ad5fe6, + 0x05fdeee,0x3386db6,0x272a42e,0x29fd38c,0x36f0320,0x21b2ed4, + 0x331e67f,0x28ae48c,0x00f09b6 }, + { 0x2778435,0x0fb3c55,0x32d221d,0x2660c8e,0x32977ba,0x1c12f03, + 0x1b57fb1,0x01229a8,0x38b389f,0x375ddf3,0x2c6b42c,0x3885d3e, + 0x2c55a9c,0x2ffc279,0x00404e2 } }, + /* 230 */ + { { 0x04c5ddb,0x2c4d788,0x150e9b9,0x110fbfd,0x29dbfe0,0x30ef83d, + 0x2ab4bfe,0x395bcd7,0x30d0a43,0x0e2d30f,0x0e73f9b,0x07199cc, + 0x0c9054c,0x22f4b1e,0x0092ed3 }, + { 0x386e27c,0x00fdaa8,0x0507c70,0x1beb3b6,0x0b9c4f4,0x277d519, + 0x024ec85,0x1cbaba8,0x1524295,0x112be58,0x21fc119,0x273578b, + 0x2358c27,0x280ca07,0x00aa376 } }, + /* 231 */ + { { 0x0dbc95c,0x16488cf,0x337a078,0x1abbcb8,0x0aae1aa,0x1caa151, + 0x00108d4,0x1edf701,0x3e68d03,0x1203214,0x0c7eee2,0x084c572, + 0x07752d2,0x215a3b9,0x00195d3 }, + { 0x2cd7fbe,0x06e80f6,0x052bd4b,0x07b4f83,0x24b5ac6,0x2aaded4, + 0x13c0526,0x0ffa9a3,0x08c660e,0x13c35c9,0x3145efb,0x36cfe24, + 0x0936daf,0x268e3d0,0x00a73fd } }, + /* 232 */ + { { 0x31b17ce,0x2e7bcee,0x3f31891,0x19f1849,0x1140236,0x015487f, + 0x32e58d3,0x202204a,0x049e350,0x1ce91f9,0x3f75150,0x27f212f, + 0x0d16ee4,0x1c894c4,0x004023f }, + { 0x33399fa,0x2397b6d,0x2a3ea60,0x36354ca,0x1f12632,0x117a105, + 0x22758e8,0x361844e,0x3851fc2,0x0ab92db,0x339d02f,0x1e7d6c4, + 0x19ebd38,0x0a9a036,0x00446d2 } }, + /* 233 */ + { { 0x3e164f1,0x008c092,0x19200f5,0x35a22e0,0x38d09d2,0x212b3bf, + 0x0056f19,0x3a03545,0x1f075e9,0x0e97137,0x1f496a9,0x32d1f9b, + 0x36bf738,0x35ace37,0x00899e1 }, + { 0x19eb2a6,0x21fa22d,0x338b69e,0x18e6d1f,0x1280d9d,0x1953a55, + 0x1411ea3,0x2960566,0x0fd969a,0x1f3e375,0x130742a,0x170aebd, + 0x33085ff,0x14d868d,0x00a4391 } }, + /* 234 */ + { { 0x0a4bdd2,0x39ca8ea,0x37026ac,0x346da3b,0x0c656cd,0x03136b6, + 0x233e7e9,0x0714352,0x08a9d95,0x192bb38,0x085d68e,0x20016b8, + 0x102b8ea,0x1f5dbdd,0x00fdd7a }, + { 0x0d6fa45,0x3ec29a6,0x2b8cce6,0x1c84413,0x0228f86,0x28275f7, + 0x3d8787d,0x0c19748,0x28b2ae9,0x1954850,0x2a56c36,0x3eae8f7, + 0x0aca595,0x00e42a2,0x00edbe5 } }, + /* 235 */ + { { 0x3b26c82,0x3682b6f,0x2f9cd64,0x0f254b0,0x0e5d70b,0x1f9dfda, + 0x28f365f,0x35a57d7,0x00208f2,0x19c8d38,0x112e7be,0x3e403bb, + 0x3734efa,0x24d12b3,0x0027dc6 }, + { 0x260a46a,0x13fd7b0,0x1c2880e,0x338b70c,0x27da5eb,0x29a7d54, + 0x1c5d73c,0x2130921,0x32969cc,0x2b37eda,0x2d6d4ec,0x0716bfb, + 0x0763703,0x1320889,0x00c7bbf } }, + /* 236 */ + { { 0x1fe01b2,0x2dcb1d2,0x11b89d5,0x219e4ea,0x0347851,0x3d1810e, + 0x3a3c54c,0x06dbe8e,0x03d3ab2,0x2dcfa39,0x3e57b8a,0x337a382, + 0x0426450,0x0e9f748,0x006488b }, + { 0x1dc4582,0x0e62cf7,0x06fea9e,0x2a56fb1,0x31698c1,0x15b4e10, + 0x1446ef1,0x0a689fc,0x1d87703,0x20ff497,0x2c71066,0x2c48868, + 0x2e6cf05,0x30aa9cb,0x0065b2d } }, + /* 237 */ + { { 0x1021d63,0x2217df3,0x1f0821a,0x057fa98,0x23f344b,0x173dcf9, + 0x1ba6ddc,0x22c8eb5,0x18f227a,0x0455343,0x1c55931,0x1d0dcf3, + 0x20fa19b,0x1c56618,0x004feab }, + { 0x19ec924,0x224e39f,0x2550509,0x179b51f,0x284d54a,0x2d85d41, + 0x2d1bdc1,0x1a29068,0x3826158,0x1267f85,0x3005a92,0x0769e00, + 0x379b617,0x17b5f63,0x00a70bf } }, + /* 238 */ + { { 0x22216c5,0x049437f,0x33510bc,0x141d806,0x22c37e2,0x1bc1adf, + 0x300175d,0x2e6ded8,0x0a18bfe,0x35377a3,0x382f843,0x08410ca, + 0x00afd4f,0x0be6c6b,0x008d70e }, + { 0x2e91abb,0x1cede2a,0x28f225c,0x28e18c0,0x30230dc,0x173cc2d, + 0x123ecfe,0x3c9962e,0x2c25506,0x27b5d53,0x329a5e3,0x106e231, + 0x3889b8e,0x3b0aeaf,0x00ee67c } }, + /* 239 */ + { { 0x3e46c65,0x0eb3d46,0x1d7ae18,0x23f9d59,0x2978953,0x2589ed3, + 0x073391d,0x2461e1e,0x0c19f1d,0x22fd2b1,0x0691f5c,0x2e67d8d, + 0x1fb985d,0x200dd28,0x00a68df }, + { 0x392b5fa,0x123b46f,0x1c323c4,0x104f82f,0x0a098c8,0x26fc05b, + 0x34cd557,0x0913639,0x09c115e,0x3977c34,0x3410b66,0x062b404, + 0x0213094,0x132c5e8,0x008b612 } }, + /* 240 */ + { { 0x26e3392,0x3b0ebf0,0x2e00425,0x1c285c8,0x3c07f84,0x08d5ad0, + 0x028190e,0x1669b73,0x1ffb1ef,0x053b65f,0x063028c,0x0aceb47, + 0x18988c2,0x0f09a30,0x0007072 }, + { 0x0f49e7d,0x28c0bd3,0x252270d,0x24cfc4a,0x0c5e87c,0x2165052, + 0x2cdd1d1,0x04931d2,0x3abca74,0x22b57dc,0x169fd47,0x0b928fb, + 0x17cc3e7,0x21a1ec4,0x0061593 } }, + /* 241 */ + { { 0x1aa0486,0x2e55dea,0x15577b7,0x0d6818f,0x36e41fb,0x2a411f5, + 0x17d5c7d,0x1eea6c0,0x28068a8,0x0e31d20,0x1f08ad9,0x117e973, + 0x08a28ab,0x085d30a,0x00cd9fb }, + { 0x347843d,0x1119095,0x11e3595,0x1b29584,0x134d64c,0x2ff3a35, + 0x247ea14,0x099fc4b,0x2056169,0x145dd03,0x2ed03fb,0x1250e3b, + 0x3f5135c,0x2b753f0,0x009da30 } }, + /* 242 */ + { { 0x0fa5200,0x214a0b3,0x313dc4e,0x23da866,0x3270760,0x15c9b8b, + 0x39a53df,0x1f79772,0x3c9e942,0x2984901,0x154d582,0x1685f87, + 0x2e1183e,0x1f79956,0x00b9987 }, + { 0x15254de,0x3a5cac0,0x37c56f0,0x2c7c29b,0x292a56d,0x195be2c, + 0x17e4e1a,0x0660f4a,0x052ad98,0x1267f80,0x07cfed8,0x194b4bc, + 0x01738d3,0x14ba10f,0x00c7843 } }, + /* 243 */ + { { 0x29b2d8a,0x242bc1f,0x19646ee,0x0615f3c,0x0ac8d70,0x07ca3bf, + 0x2d90317,0x2c83bdb,0x1a96812,0x39fdc35,0x31c61ee,0x2d55fd3, + 0x2375827,0x355f189,0x00f1c9b }, + { 0x21a6194,0x1f4050a,0x2b845cf,0x02c6242,0x2dd614e,0x3a4f0a9, + 0x39de100,0x24714fb,0x175e0cd,0x0be633d,0x14befc3,0x13b0318, + 0x1d68c50,0x299989e,0x00d0513 } }, + /* 244 */ + { { 0x059fb6a,0x2b6eb6a,0x3666a8e,0x39f6ca0,0x1cf8346,0x388b8d5, + 0x35e61a3,0x271adec,0x22c9963,0x20a4fb3,0x16f241c,0x0058b89, + 0x21ddafa,0x1ee6fde,0x00d2e6c }, + { 0x0075e63,0x39894d0,0x0286d0d,0x187e7b2,0x02405aa,0x3f91525, + 0x37830a8,0x2723088,0x2c7364e,0x013f406,0x104ba75,0x270f486, + 0x3520b4d,0x3852bc6,0x00d589b } }, + /* 245 */ + { { 0x262e53b,0x1da93d1,0x3676135,0x147e41d,0x335ec2f,0x1f02be5, + 0x297d139,0x22d6198,0x1fe9e59,0x13b4c80,0x1e70f60,0x2f1d4a9, + 0x2d95149,0x14d6ec4,0x00b54af }, + { 0x12c1c76,0x2930ac8,0x0dfd36e,0x31fac94,0x218f5bb,0x2828691, + 0x1466cc9,0x3645e83,0x1a4dac2,0x1549593,0x0e95fab,0x19567d2, + 0x27a3320,0x0642729,0x007487c } }, + /* 246 */ + { { 0x1e98e9c,0x2ff8df7,0x119975a,0x098a904,0x099b90b,0x336c7df, + 0x010996d,0x159d46d,0x3118b3b,0x3aacd1b,0x31f8ae1,0x214864f, + 0x398c104,0x089dae2,0x001ec4d }, + { 0x1452baa,0x2f24991,0x2572ba3,0x162b312,0x2387d18,0x147c5c7, + 0x38eff6e,0x0700251,0x37d931e,0x23cd5c1,0x254c8ca,0x3b9df37, + 0x1c9a4ff,0x0bfd547,0x00fb489 } }, + /* 247 */ + { { 0x1b8dff8,0x2f6b40b,0x05a25b1,0x3f5688a,0x1d462f4,0x2802d18, + 0x2aad8ed,0x1b46c75,0x3cf4130,0x250fefb,0x2a13fe1,0x23a1bcd, + 0x0940442,0x04605fe,0x00c8b2f }, + { 0x0d51afb,0x14a2abc,0x1d06762,0x291526c,0x2a3e2fe,0x28f77d9, + 0x3ad8f2e,0x3481a1b,0x04b4fbd,0x2836733,0x0189ff5,0x3a5f533, + 0x319a6cd,0x0f58667,0x00c3679 } }, + /* 248 */ + { { 0x1b85197,0x22426d4,0x2895ea3,0x342d324,0x3ffb17d,0x376cfcf, + 0x30878b1,0x3c3c83a,0x0ffc57c,0x0ac174a,0x1abd57e,0x2f78b9c, + 0x01b20d8,0x0a37103,0x007f2be }, + { 0x19a2d48,0x137288a,0x182d655,0x0ba0dde,0x25130ba,0x01c65c6, + 0x23205f1,0x2097621,0x2827cf2,0x2c57b98,0x03748f2,0x2db15fc, + 0x385a0d4,0x13690c0,0x00a9e3f } }, + /* 249 */ + { { 0x3fbc9c6,0x2df3b20,0x377e33e,0x31d1505,0x024a311,0x3c1d9ff, + 0x1377f74,0x00b6b20,0x2364ab7,0x184ab6b,0x2a77969,0x3f2db6c, + 0x2a6adb7,0x0a10073,0x004a6fb }, + { 0x1fc73de,0x2c74ab3,0x3d325e8,0x2346c0b,0x1d0efae,0x2076146, + 0x19c190d,0x225c4fe,0x3fafc80,0x2cf063d,0x11b7ae7,0x3dc4f9d, + 0x3c3f841,0x10d7c1f,0x000a4b3 } }, + /* 250 */ + { { 0x19b7d2e,0x28f1300,0x0b897dd,0x06b5371,0x0631c8d,0x336cc4f, + 0x09cd6e1,0x2ec1952,0x1104c07,0x07512bb,0x35f000d,0x25f84e9, + 0x1df4d8f,0x193f769,0x000e9ee }, + { 0x2346910,0x267cecf,0x0ad7eaa,0x087e8a5,0x1622f69,0x342cbfa, + 0x2aa20d0,0x206e88a,0x3991e58,0x093fb4b,0x0157180,0x3cecb5b, + 0x2e17c9a,0x1ea371f,0x00919e6 } }, + /* 251 */ + { { 0x2250533,0x13f931d,0x3ef8c72,0x395f605,0x18a2080,0x1cb25d4, + 0x2fb0f41,0x1c0ba8a,0x1eb17c0,0x266c433,0x09b7e3e,0x0e5d78f, + 0x0cdc5bf,0x1f7c734,0x0020611 }, + { 0x205ebd5,0x127986f,0x02c0fb0,0x1705b1e,0x1eb0bb5,0x2dffb42, + 0x2331b8a,0x18fc04e,0x31d6328,0x17db162,0x0d3b619,0x193bdb9, + 0x3f11662,0x2d8e694,0x0092c51 } }, + /* 252 */ + { { 0x08b364d,0x31ef20a,0x25c4a57,0x021ed07,0x14a562e,0x262a684, + 0x1d21c66,0x126e5a6,0x181f3f8,0x2a93b65,0x1eb726b,0x08fbbce, + 0x084f9a2,0x308f30a,0x0013159 }, + { 0x23f4963,0x0c7960e,0x2a81739,0x2242b69,0x3965003,0x2aca542, + 0x28a1c65,0x2ad48fb,0x149775f,0x1bbb7d2,0x0f2671b,0x3594b85, + 0x22f5563,0x2470f13,0x00fed44 } }, + /* 253 */ + { { 0x0eb453e,0x3ab70fd,0x1a5b335,0x18f2b74,0x25ff74b,0x3612a46, + 0x33d0d75,0x28cdda4,0x2b9b49b,0x22728fb,0x004c15b,0x1beb33b, + 0x1a7e41f,0x0c9b702,0x004ef19 }, + { 0x1ca3233,0x0b4c90f,0x1d4b53d,0x2428896,0x20ee405,0x151bc00, + 0x022edb5,0x1adc463,0x00109ea,0x06490a6,0x30e91e6,0x3682b76, + 0x23c50aa,0x3bd2665,0x005fe53 } }, + /* 254 */ + { { 0x0c28c65,0x3741ae4,0x247d372,0x0b04673,0x2176524,0x2c8bf20, + 0x01fb806,0x3330701,0x307b0a7,0x3999fb7,0x1261bec,0x256679c, + 0x3f22ac7,0x26e8673,0x00bc69d }, + { 0x3c06819,0x35df344,0x379d009,0x2bb8a0a,0x0635a66,0x096c6fa, + 0x1ac4a62,0x023e53b,0x0e45240,0x115f53d,0x3056af8,0x0a66b16, + 0x3c386ee,0x1130e82,0x00cc384 } }, + /* 255 */ + { { 0x14c2356,0x190ec73,0x07be490,0x145d415,0x0740a48,0x1251301, + 0x3eaf29d,0x2628190,0x079299a,0x26e95c9,0x2e05fdf,0x2ca7c5b, + 0x32d7b48,0x3d84226,0x0033fb4 }, + { 0x150f955,0x01240aa,0x3ddf867,0x137fb70,0x297e103,0x17eeda8, + 0x1320b60,0x266ec84,0x13f4322,0x0c8f5ee,0x0590e4a,0x386815e, + 0x00ce61f,0x161bd63,0x008e1d0 } }, +}; + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_15(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + return sp_384_ecc_mulmod_stripe_15(r, &p384_base, p384_table, + k, map, heap); +} + +#endif + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[15]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_384_point_new_15(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 15, km); + + err = sp_384_ecc_mulmod_base_15(point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_15(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_15(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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_384_iszero_15(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] | a[10] | a[11] | a[12] | a[13] | a[14]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_add_one_15(sp_digit* a) +{ + a[0]++; + sp_384_norm_15(a); +} + +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 18U) { + r[j] &= 0x3ffffff; + s = 26U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; 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_384_ecc_gen_k_15(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[48]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_384_from_bin(k, 15, buf, (int)sizeof(buf)); + if (sp_384_cmp_15(k, p384_order2) < 0) { + sp_384_add_one_15(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_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[15]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 inf; +#endif +#endif + sp_point_384* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity; +#endif + int err; + + (void)heap; + + err = sp_384_point_new_15(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_point_new_15(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + err = sp_384_ecc_gen_k_15(rng, k); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_15(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_15(infinity, point, p384_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_384_iszero_15(point->x) == 0) || (sp_384_iszero_15(point->y) == 0)) { + err = ECC_INF_E; + } + } +#endif + + if (err == MP_OKAY) { + err = sp_384_to_mp(k, priv); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_15(point, pub); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_384_point_free_15(infinity, 1, heap); +#endif + sp_384_point_free_15(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 48 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_384_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<14; i++) { + r[i+1] += r[i] >> 26; + r[i] &= 0x3ffffff; + } + j = 384 / 8 - 1; + a[j] = 0; + for (i=0; i<15 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 26) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 26); + if (j >= 0) { + 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_384(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[15]; +#endif + sp_point_384* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 48U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_384_point_new_15(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(k, 15, priv); + sp_384_point_from_ecc_point_15(point, pub); + err = sp_384_ecc_mulmod_15(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_384_to_bin(point->x, out); + *outLen = 48; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_15(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#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. + */ +SP_NOINLINE static void sp_384_mul_d_15(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 15; i++) { + t += tb * a[i]; + r[i] = t & 0x3ffffff; + t >>= 26; + } + r[15] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[15]; + + 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]; + t[10] = tb * a[10]; + t[11] = tb * a[11]; + t[12] = tb * a[12]; + t[13] = tb * a[13]; + t[14] = tb * a[14]; + 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) + (t[10] & 0x3ffffff); + r[11] = (sp_digit)(t[10] >> 26) + (t[11] & 0x3ffffff); + r[12] = (sp_digit)(t[11] >> 26) + (t[12] & 0x3ffffff); + r[13] = (sp_digit)(t[12] >> 26) + (t[13] & 0x3ffffff); + r[14] = (sp_digit)(t[13] >> 26) + (t[14] & 0x3ffffff); + r[15] = (sp_digit)(t[14] >> 26); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_384_div_word_15(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 26 bits from d1 and top 5 bits from d0. */ + d = (d1 << 5) | (d0 >> 21); + r = d / dv; + d -= r * dv; + /* Up to 6 bits in r */ + /* Next 5 bits from d0. */ + r <<= 5; + d <<= 5; + d |= (d0 >> 16) & ((1 << 5) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 11 bits in r */ + /* Next 5 bits from d0. */ + r <<= 5; + d <<= 5; + d |= (d0 >> 11) & ((1 << 5) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 16 bits in r */ + /* Next 5 bits from d0. */ + r <<= 5; + d <<= 5; + d |= (d0 >> 6) & ((1 << 5) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 21 bits in r */ + /* Next 5 bits from d0. */ + r <<= 5; + d <<= 5; + d |= (d0 >> 1) & ((1 << 5) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 26 bits in r */ + /* Remaining 1 bits from d0. */ + r <<= 1; + d <<= 1; + d |= d0 & ((1 << 1) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* 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 Number 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_384_div_15(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[30], t2d[15 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 15 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 2 * 15; +#else + t1 = t1d; + t2 = t2d; +#endif + + dv = d[14]; + XMEMCPY(t1, a, sizeof(*t1) * 2U * 15U); + for (i=14; i>=0; i--) { + t1[15 + i] += t1[15 + i - 1] >> 26; + t1[15 + i - 1] &= 0x3ffffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[15 + i]; + d1 <<= 26; + d1 += t1[15 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_384_div_word_15(t1[15 + i], t1[15 + i - 1], dv); +#endif + + sp_384_mul_d_15(t2, d, r1); + (void)sp_384_sub_15(&t1[i], &t1[i], t2); + t1[15 + i] -= t2[15]; + t1[15 + i] += t1[15 + i - 1] >> 26; + t1[15 + i - 1] &= 0x3ffffff; + r1 = (((-t1[15 + i]) << 26) - t1[15 + i - 1]) / dv; + r1++; + sp_384_mul_d_15(t2, d, r1); + (void)sp_384_add_15(&t1[i], &t1[i], t2); + t1[15 + i] += t1[15 + i - 1] >> 26; + t1[15 + i - 1] &= 0x3ffffff; + } + t1[15 - 1] += t1[15 - 2] >> 26; + t1[15 - 2] &= 0x3ffffff; + r1 = t1[15 - 1] / dv; + + sp_384_mul_d_15(t2, d, r1); + (void)sp_384_sub_15(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 15U); + for (i=0; i<13; i++) { + r[i+1] += r[i] >> 26; + r[i] &= 0x3ffffff; + } + sp_384_cond_add_15(r, r, d, 0 - ((r[14] < 0) ? + (sp_digit)1 : (sp_digit)0)); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_384_mod_15(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_384_div_15(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P384 curve. */ +static const uint32_t p384_order_minus_2[12] = { + 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U, + 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU +}; +#else +/* The low half of the order-2 of the P384 curve. */ +static const uint32_t p384_order_low[6] = { + 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U + +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P384 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_384_mont_mul_order_15(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_384_mul_15(r, a, b); + sp_384_mont_reduce_order_15(r, p384_order, p384_mp_order); +} + +/* Square number mod the order of P384 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_order_15(sp_digit* r, const sp_digit* a) +{ + sp_384_sqr_15(r, a); + sp_384_mont_reduce_order_15(r, p384_order, p384_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P384 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_n_order_15(sp_digit* r, const sp_digit* a, int n) +{ + int i; + + sp_384_mont_sqr_order_15(r, a); + for (i=1; i=0; i--) { + sp_384_mont_sqr_order_15(t, t); + if ((p384_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_384_mont_mul_order_15(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 15U); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 15; + sp_digit* t3 = td + 4 * 15; + int i; + + /* t = a^2 */ + sp_384_mont_sqr_order_15(t, a); + /* t = a^3 = t * a */ + sp_384_mont_mul_order_15(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_384_mont_sqr_n_order_15(t2, t, 2); + /* t = a^f = t2 * t */ + sp_384_mont_mul_order_15(t, t2, t); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_384_mont_sqr_n_order_15(t2, t, 4); + /* t = a^ff = t2 * t */ + sp_384_mont_mul_order_15(t, t2, t); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_384_mont_sqr_n_order_15(t2, t, 8); + /* t3= a^ffff = t2 * t */ + sp_384_mont_mul_order_15(t3, t2, t); + /* t2= a^ffff0000 = t3 ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_15(t2, t3, 16); + /* t = a^ffffffff = t2 * t3 */ + sp_384_mont_mul_order_15(t, t2, t3); + /* t2= a^ffffffff0000 = t ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_15(t2, t, 16); + /* t = a^ffffffffffff = t2 * t3 */ + sp_384_mont_mul_order_15(t, t2, t3); + /* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */ + sp_384_mont_sqr_n_order_15(t2, t, 48); + /* t= a^fffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_15(t, t2, t); + /* t2= a^ffffffffffffffffffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_order_15(t2, t, 96); + /* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_15(t2, t2, t); + for (i=191; i>=1; i--) { + sp_384_mont_sqr_order_15(t2, t2); + if (((sp_digit)p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_384_mont_mul_order_15(t2, t2, a); + } + } + sp_384_mont_sqr_order_15(t2, t2); + sp_384_mont_mul_order_15(r, t2, a); +#endif /* WOLFSSL_SP_SMALL */ +} + +#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, 384 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 384 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_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit ed[2*15]; + sp_digit xd[2*15]; + sp_digit kd[2*15]; + sp_digit rd[2*15]; + sp_digit td[3 * 2*15]; + sp_point_384 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_384* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int32_t c; + int i; + + (void)heap; + + err = sp_384_point_new_15(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 15, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 15; + x = d + 2 * 15; + k = d + 4 * 15; + r = d + 6 * 15; + tmp = d + 8 * 15; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(e, 15, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_384_from_mp(x, 15, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_15(rng, k); + } + else { + sp_384_from_mp(k, 15, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_15(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 15U); + sp_384_norm_15(r); + c = sp_384_cmp_15(r, p384_order); + sp_384_cond_sub_15(r, r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_15(r); + + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_15(k, k, p384_norm_order); + err = sp_384_mod_15(k, k, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_15(k); + /* kInv = 1/k mod order */ + sp_384_mont_inv_order_15(kInv, k, tmp); + sp_384_norm_15(kInv); + + /* s = r * x + e */ + sp_384_mul_15(x, x, r); + err = sp_384_mod_15(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_15(x); + carry = sp_384_add_15(s, e, x); + sp_384_cond_sub_15(s, s, p384_order, 0 - carry); + sp_384_norm_15(s); + c = sp_384_cmp_15(s, p384_order); + sp_384_cond_sub_15(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_15(s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_15(s, s, kInv); + sp_384_norm_15(s); + + /* Check that signature is usable. */ + if (sp_384_iszero_15(s) == 0) { + break; + } + } + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 15); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 15U); +#endif + sp_384_point_free_15(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, 384) + * 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 384 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_384(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit u1d[2*15]; + sp_digit u2d[2*15]; + sp_digit sd[2*15]; + sp_digit tmpd[2*15 * 5]; + sp_point_384 p1d; + sp_point_384 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p1; + sp_point_384* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + + err = sp_384_point_new_15(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_384_point_new_15(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 15, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 15; + u2 = d + 2 * 15; + s = d + 4 * 15; + tmp = d + 6 * 15; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 15, hash, (int)hashLen); + sp_384_from_mp(u2, 15, r); + sp_384_from_mp(s, 15, sm); + sp_384_from_mp(p2->x, 15, pX); + sp_384_from_mp(p2->y, 15, pY); + sp_384_from_mp(p2->z, 15, pZ); + + { + sp_384_mul_15(s, s, p384_norm_order); + } + err = sp_384_mod_15(s, s, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_15(s); + { + sp_384_mont_inv_order_15(s, s, tmp); + sp_384_mont_mul_order_15(u1, u1, s); + sp_384_mont_mul_order_15(u2, u2, s); + } + + err = sp_384_ecc_mulmod_base_15(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_15(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + { + sp_384_proj_point_add_15(p1, p1, p2, tmp); + if (sp_384_iszero_15(p1->z)) { + if (sp_384_iszero_15(p1->x) && sp_384_iszero_15(p1->y)) { + sp_384_proj_point_dbl_15(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + p1->x[8] = 0; + p1->x[9] = 0; + p1->x[10] = 0; + p1->x[11] = 0; + p1->x[12] = 0; + p1->x[13] = 0; + p1->x[14] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + } + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 15, r); + err = sp_384_mod_mul_norm_15(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_15(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_15(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 15, r); + carry = sp_384_add_15(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_15(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_15(u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_15(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_15(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_15(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_384_point_free_15(p1, 0, heap); + sp_384_point_free_15(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_384_ecc_is_point_15(sp_point_384* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*15]; + sp_digit t2d[2*15]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 15; + t2 = d + 2 * 15; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_384_sqr_15(t1, point->y); + (void)sp_384_mod_15(t1, t1, p384_mod); + sp_384_sqr_15(t2, point->x); + (void)sp_384_mod_15(t2, t2, p384_mod); + sp_384_mul_15(t2, t2, point->x); + (void)sp_384_mod_15(t2, t2, p384_mod); + (void)sp_384_sub_15(t2, p384_mod, t2); + sp_384_mont_add_15(t1, t1, t2, p384_mod); + + sp_384_mont_add_15(t1, t1, point->x, p384_mod); + sp_384_mont_add_15(t1, t1, point->x, p384_mod); + sp_384_mont_add_15(t1, t1, point->x, p384_mod); + + if (sp_384_cmp_15(t1, p384_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 pubd; +#endif + sp_point_384* pub; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_15(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_384_from_mp(pub->x, 15, pX); + sp_384_from_mp(pub->y, 15, pY); + sp_384_from_bin(pub->z, 15, one, (int)sizeof(one)); + + err = sp_384_ecc_is_point_15(pub, NULL); + } + + sp_384_point_free_15(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[15]; + sp_point_384 pubd; + sp_point_384 pd; +#endif + sp_digit* priv = NULL; + sp_point_384* pub; + sp_point_384* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_15(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_384_point_new_15(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_384_from_mp(pub->x, 15, pX); + sp_384_from_mp(pub->y, 15, pY); + sp_384_from_bin(pub->z, 15, one, (int)sizeof(one)); + sp_384_from_mp(priv, 15, privm); + + /* Check point at infinitiy. */ + if ((sp_384_iszero_15(pub->x) != 0) && + (sp_384_iszero_15(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_384_cmp_15(pub->x, p384_mod) >= 0 || + sp_384_cmp_15(pub->y, p384_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_384_ecc_is_point_15(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_384_ecc_mulmod_15(p, pub, p384_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_384_iszero_15(p->x) == 0) || + (sp_384_iszero_15(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_384_ecc_mulmod_base_15(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_384_cmp_15(p->x, pub->x) != 0 || + sp_384_cmp_15(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_15(p, 0, heap); + sp_384_point_free_15(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 15 * 5]; + sp_point_384 pd; + sp_point_384 qd; +#endif + sp_digit* tmp; + sp_point_384* p; + sp_point_384* q = NULL; + int err; + + err = sp_384_point_new_15(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_384_point_new_15(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 15, pX); + sp_384_from_mp(p->y, 15, pY); + sp_384_from_mp(p->z, 15, pZ); + sp_384_from_mp(q->x, 15, qX); + sp_384_from_mp(q->y, 15, qY); + sp_384_from_mp(q->z, 15, qZ); + + sp_384_proj_point_add_15(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_15(q, 0, NULL); + sp_384_point_free_15(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 15 * 2]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_15(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 15, pX); + sp_384_from_mp(p->y, 15, pY); + sp_384_from_mp(p->z, 15, pZ); + + sp_384_proj_point_dbl_15(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_15(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 15 * 6]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_15(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 15, pX); + sp_384_from_mp(p->y, 15, pY); + sp_384_from_mp(p->z, 15, pZ); + + sp_384_map_15(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_15(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mont_sqrt_15(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 15]; + sp_digit t2d[2 * 15]; + sp_digit t3d[2 * 15]; + sp_digit t4d[2 * 15]; + sp_digit t5d[2 * 15]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 15, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 15; + t2 = d + 2 * 15; + t3 = d + 4 * 15; + t4 = d + 6 * 15; + t5 = d + 8 * 15; +#else + t1 = t1d; + t2 = t2d; + t3 = t3d; + t4 = t4d; + t5 = t5d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_384_mont_sqr_15(t2, y, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3 */ + sp_384_mont_mul_15(t1, t2, y, p384_mod, p384_mp_mod); + /* t5 = y ^ 0xc */ + sp_384_mont_sqr_n_15(t5, t1, 2, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xf */ + sp_384_mont_mul_15(t1, t1, t5, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x1e */ + sp_384_mont_sqr_15(t2, t1, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x1f */ + sp_384_mont_mul_15(t3, t2, y, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3e0 */ + sp_384_mont_sqr_n_15(t2, t3, 5, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3ff */ + sp_384_mont_mul_15(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fe0 */ + sp_384_mont_sqr_n_15(t2, t1, 5, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x7fff */ + sp_384_mont_mul_15(t3, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fff800 */ + sp_384_mont_sqr_n_15(t2, t3, 15, p384_mod, p384_mp_mod); + /* t4 = y ^ 0x3ffffff */ + sp_384_mont_mul_15(t4, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffc000000 */ + sp_384_mont_sqr_n_15(t2, t4, 30, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffff */ + sp_384_mont_mul_15(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_15(t2, t1, 60, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_15(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_15(t2, t1, 120, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_15(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_15(t2, t1, 15, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_15(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */ + sp_384_mont_sqr_n_15(t2, t1, 31, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */ + sp_384_mont_mul_15(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */ + sp_384_mont_sqr_n_15(t2, t1, 4, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */ + sp_384_mont_mul_15(t1, t5, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */ + sp_384_mont_sqr_n_15(t2, t1, 62, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */ + sp_384_mont_mul_15(t1, y, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */ + sp_384_mont_sqr_n_15(y, t1, 30, p384_mod, p384_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 15]; + sp_digit yd[2 * 15]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 15, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 15; + y = d + 2 * 15; +#else + x = xd; + y = yd; +#endif + + sp_384_from_mp(x, 15, xm); + err = sp_384_mod_mul_norm_15(x, x, p384_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_384_mont_sqr_15(y, x, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(y, y, x, p384_mod, p384_mp_mod); + } + /* y = x^3 - 3x */ + sp_384_mont_sub_15(y, y, x, p384_mod); + sp_384_mont_sub_15(y, y, x, p384_mod); + sp_384_mont_sub_15(y, y, x, p384_mod); + /* y = x^3 - 3x + b */ + err = sp_384_mod_mul_norm_15(x, p384_b, p384_mod); + } + if (err == MP_OKAY) { + sp_384_mont_add_15(y, y, x, p384_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_384_mont_sqrt_15(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 15, 0, 15U * sizeof(sp_digit)); + sp_384_mont_reduce_15(y, p384_mod, p384_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_384_mont_sub_15(y, p384_mod, y, p384_mod); + } + + err = sp_384_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_384 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* SP_WORD_SIZE == 32 */ +#endif /* !WOLFSSL_SP_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_c64.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_c64.c new file mode 100644 index 000000000..9038173ed --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_c64.c @@ -0,0 +1,23220 @@ +/* sp.c + * + * Copyright (C) 2006-2020 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 +#ifndef SP_RSA_PRIVATE_EXP_D +#define SP_RSA_PRIVATE_EXP_D +#endif + +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifndef WOLFSSL_SP_ASM +#if SP_WORD_SIZE == 64 +#if (defined(WOLFSSL_SP_CACHE_RESISTANT) || defined(WOLFSSL_SP_SMALL)) && (defined(WOLFSSL_HAVE_SP_ECC) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* 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 + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 49U) { + r[j] &= 0x1ffffffffffffffL; + s = 57U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 57 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 57 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x1ffffffffffffffL; + s = 57U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 57U) <= (word32)DIGIT_BIT) { + s += 57U; + r[j] &= 0x1ffffffffffffffL; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 57) { + r[j] &= 0x1ffffffffffffffL; + if (j + 1 >= size) { + break; + } + s = 57 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * 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; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 57) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 57); + if (j >= 0) { + 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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; + (void)sp_2048_add_9(a1, a, &a[9]); + (void)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); + (void)sp_2048_sub_18(z1, z1, z2); + (void)sp_2048_sub_18(z1, z1, z0); + (void)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. + */ +SP_NOINLINE 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; + (void)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); + (void)sp_2048_sub_18(z1, z1, z2); + (void)sp_2048_sub_18(z1, z1, z0); + (void)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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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; + (void)sp_2048_add_18(a1, a, &a[18]); + (void)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); + (void)sp_2048_sub_36(z1, z1, z2); + (void)sp_2048_sub_36(z1, z1, z0); + (void)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. + */ +SP_NOINLINE 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; + (void)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); + (void)sp_2048_sub_36(z1, z1, z2); + (void)sp_2048_sub_36(z1, z1, z0); + (void)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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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 /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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; +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_2048_mul_d_36(sp_digit* r, const sp_digit* a, + 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 */ +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_2048_mont_norm_18(sp_digit* r, const 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 */ + (void)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 == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[17] - b[17]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[16] - b[16]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 8; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#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. + */ +SP_NOINLINE 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] += (sp_digit)(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 */ +} + +/* 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 += (word64)a[18 + i] << 2; + r[i] = n & 0x1ffffffffffffffL; + n >>= 57; + } + n += (word64)a[35] << 2; + r[17] = n; +#else + word64 n; + int i; + + n = (word64)a[17]; + n = n >> 55U; + for (i = 0; i < 16; i += 8) { + n += (word64)a[i+18] << 2U; r[i+0] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+19] << 2U; r[i+1] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+20] << 2U; r[i+2] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+21] << 2U; r[i+3] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+22] << 2U; r[i+4] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+23] << 2U; r[i+5] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+24] << 2U; r[i+6] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[i+25] << 2U; r[i+7] = n & 0x1ffffffffffffffUL; n >>= 57U; + } + n += (word64)a[34] << 2U; r[16] = n & 0x1ffffffffffffffUL; n >>= 57U; + n += (word64)a[35] << 2U; r[17] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[18], 0, sizeof(*r) * 18U); +} + +/* 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, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_2048_norm_18(a + 18); + + 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_digit)1 : (sp_digit)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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const 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. + */ +SP_NOINLINE static void sp_2048_mul_d_18(sp_digit* r, const sp_digit* a, + 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 */ +} + +#ifdef WOLFSSL_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. + */ +SP_NOINLINE 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 +#ifdef WOLFSSL_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. + */ +SP_NOINLINE 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 +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 57 bits from d1 and top 6 bits from d0. */ + d = (d1 << 6) | (d0 >> 51); + r = d / dv; + d -= r * dv; + /* Up to 7 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 45) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 13 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 39) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 19 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 33) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 25 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 27) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 31 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 21) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 37 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 15) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 43 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 9) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 49 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 3) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 55 bits in r */ + /* Remaining 3 bits from d0. */ + r <<= 3; + d <<= 3; + d |= d0 & ((1 << 3) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* 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 Number 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(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[36], t2d[18 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 18 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 2 * 18; +#else + t1 = t1d; + t2 = t2d; +#endif + + dv = d[17]; + XMEMCPY(t1, a, sizeof(*t1) * 2U * 18U); + for (i=17; i>=0; i--) { + t1[18 + i] += t1[18 + i - 1] >> 57; + t1[18 + i - 1] &= 0x1ffffffffffffffL; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[18 + i]; + d1 <<= 57; + d1 += t1[18 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_2048_div_word_18(t1[18 + i], t1[18 + i - 1], dv); +#endif + + sp_2048_mul_d_18(t2, d, r1); + (void)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]) / dv; + r1++; + sp_2048_mul_d_18(t2, d, r1); + (void)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; + r1 = t1[18 - 1] / dv; + + sp_2048_mul_d_18(t2, d, r1); + (void)sp_2048_sub_18(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 18U); + 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) ? + (sp_digit)1 : (sp_digit)0)); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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, const sp_digit* a, const 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, const sp_digit* a, const sp_digit* e, int bits, + const 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) * 3U * 18U * 2U); + + 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 != 0) { + err = sp_2048_mod_18(t[1], a, m); + } + else { + XMEMCPY(t[1], a, sizeof(sp_digit) * 18U); + } + } + 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) ? + (sp_digit)1 : (sp_digit)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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t[0] = td; + t[1] = &td[18 * 2]; + t[2] = &td[2 * 18 * 2]; +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_18(norm, m); + + if (reduceA != 0) { + 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) ? + (sp_digit)1 : (sp_digit)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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 36; +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_18(norm, m); + + if (reduceA != 0) { + 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) & 0x1f; + 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) ? + (sp_digit)1 : (sp_digit)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 /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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 single precision number. + */ +static void sp_2048_mont_norm_36(sp_digit* r, const 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 */ + (void)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 == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[35] - b[35]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[34] - b[34]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[33] - b[33]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[32] - b[32]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 24; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#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. + */ +SP_NOINLINE 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] += (sp_digit)(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 */ +} + +/* 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) * 36U); +} + +/* 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, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_2048_norm_36(a + 36); + +#ifdef WOLFSSL_SP_DH + 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; + } +#else + 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; +#endif + + sp_2048_mont_shift_36(a, a); + sp_2048_cond_sub_36(a, a, m, 0 - (((a[35] >> 53) > 0) ? + (sp_digit)1 : (sp_digit)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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_36(r, a); + sp_2048_mont_reduce_36(r, m, mp); +} + +/* 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 */ +} + +#ifdef WOLFSSL_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. + */ +SP_NOINLINE 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 +#ifdef WOLFSSL_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. + */ +SP_NOINLINE 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 +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 57 bits from d1 and top 6 bits from d0. */ + d = (d1 << 6) | (d0 >> 51); + r = d / dv; + d -= r * dv; + /* Up to 7 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 45) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 13 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 39) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 19 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 33) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 25 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 27) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 31 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 21) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 37 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 15) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 43 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 9) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 49 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 3) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 55 bits in r */ + /* Remaining 3 bits from d0. */ + r <<= 3; + d <<= 3; + d |= d0 & ((1 << 3) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* 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 Number 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(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[72], t2d[36 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 36 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 2 * 36; +#else + t1 = t1d; + t2 = t2d; +#endif + + dv = d[35]; + XMEMCPY(t1, a, sizeof(*t1) * 2U * 36U); + for (i=35; i>=0; i--) { + t1[36 + i] += t1[36 + i - 1] >> 57; + t1[36 + i - 1] &= 0x1ffffffffffffffL; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[36 + i]; + d1 <<= 57; + d1 += t1[36 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_2048_div_word_36(t1[36 + i], t1[36 + i - 1], dv); +#endif + + sp_2048_mul_d_36(t2, d, r1); + (void)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]) / dv; + r1++; + sp_2048_mul_d_36(t2, d, r1); + (void)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; + r1 = t1[36 - 1] / dv; + + sp_2048_mul_d_36(t2, d, r1); + (void)sp_2048_sub_36(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 36U); + 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) ? + (sp_digit)1 : (sp_digit)0)); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_36(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + 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, const sp_digit* a, const sp_digit* e, int bits, + const 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) * 3U * 36U * 2U); + + 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 != 0) { + err = sp_2048_mod_36(t[1], a, m); + } + else { + XMEMCPY(t[1], a, sizeof(sp_digit) * 36U); + } + } + 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) ? + (sp_digit)1 : (sp_digit)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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t[0] = td; + t[1] = &td[36 * 2]; + t[2] = &td[2 * 36 * 2]; +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + + if (reduceA != 0) { + 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) ? + (sp_digit)1 : (sp_digit)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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 72; +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + + if (reduceA != 0) { + 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) & 0x1f; + 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) ? + (sp_digit)1 : (sp_digit)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 /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ + /* 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) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1] = {0}; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 256U) { + err = MP_TO_E; + } + + if (err == MP_OKAY) { + if (mp_count_bits(em) > 57) { + err = MP_READ_E; + } + if (inLen > 256U) { + err = MP_READ_E; + } + if (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_RSA); + 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] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)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) != 0) { + 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) ? + (sp_digit)1 : (sp_digit)0)- 1); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + 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] = {0}; + int err = MP_OKAY; + + if (*outLen < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(em) > 57) { + err = MP_READ_E; + } + if (inLen > 256U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 2048) { + err = MP_READ_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 5, NULL, + DYNAMIC_TYPE_RSA); + 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] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)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) { + 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); + + 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) != 0) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 72U); + 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) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM) +#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */ +/* 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(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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 < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 2048) { + err = MP_READ_E; + } + if (inLen > 256) { + err = MP_READ_E; + } + if (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_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 36; + m = a + 72; + 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_RSA); + } + + 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 < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 2048) { + err = MP_READ_E; + } + if (inLen > 256U) { + err = MP_READ_E; + } + if (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)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (inLen > 256) { + err = MP_READ_E; + } + if (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_RSA); + 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; + + r = t + 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) { + (void)sp_2048_sub_18(tmpa, tmpa, tmpb); + sp_2048_cond_add_18(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[17] >> 63)); + sp_2048_cond_add_18(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[17] >> 63)); + + 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); + (void)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_RSA); + } + + return err; +#else + sp_digit a[36 * 2]; + sp_digit p[18], q[18], dp[18], dq[18], qi[18]; + sp_digit tmpa[36], tmpb[36]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (inLen > 256U) { + err = MP_READ_E; + } + if (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) { + (void)sp_2048_sub_18(tmpa, tmpa, tmpb); + sp_2048_cond_add_18(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[17] >> 63)); + sp_2048_cond_add_18(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[17] >> 63)); + 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); + (void)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 || RSA_LOW_MEM */ +} + +#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 57 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 36); + r->used = 36; + mp_clamp(r); +#elif DIGIT_BIT < 57 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 36; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 57) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 57 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 36; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 57 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 57 - s; + } + else { + s += 57; + } + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL, DYNAMIC_TYPE_DH); + 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_mp(e, 36, exp); + sp_2048_from_mp(m, 36, mod); + + err = sp_2048_mod_exp_36(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 36U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + 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; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (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_DH); + 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_mp(e, 36, exp); + sp_2048_from_mp(m, 36, mod); + + err = sp_2048_mod_exp_36(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 36U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 36U); +#endif + + return err; +#endif +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_2048 +SP_NOINLINE static void sp_2048_lshift_36(sp_digit* r, sp_digit* a, byte n) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + r[36] = a[35] >> (57 - n); + for (i=35; i>0; i--) { + r[i] = ((a[i] << n) | (a[i-1] >> (57 - n))) & 0x1ffffffffffffffL; + } +#else + sp_int_digit s, t; + + s = (sp_int_digit)a[35]; + r[36] = s >> (57U - n); + s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); + r[35] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); + r[34] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); + r[33] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); + r[32] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); + r[31] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); + r[30] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); + r[29] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); + r[28] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); + r[27] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); + r[26] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); + r[25] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); + r[24] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); + r[23] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); + r[22] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); + r[21] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); + r[20] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); + r[19] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); + r[18] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); + r[17] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); + r[16] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); + r[15] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); + r[14] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); + r[13] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); + r[12] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); + r[11] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); + r[10] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); + r[9] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); + r[8] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); + r[7] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); + r[6] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); + r[5] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); + r[4] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); + r[3] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); + r[2] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); + r[1] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; +#endif + r[0] = (a[0] << n) & 0x1ffffffffffffffL; +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_36(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[72]; + sp_digit td[37]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 109, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 72; + XMEMSET(td, 0, sizeof(sp_digit) * 109); +#else + norm = nd; + tmp = td; + XMEMSET(td, 0, sizeof(td)); +#endif + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + + 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) & 0x1f; + n <<= 5; + c -= 5; + sp_2048_lshift_36(r, norm, y); + 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(r, r, m, mp); + sp_2048_mont_sqr_36(r, r, m, mp); + sp_2048_mont_sqr_36(r, r, m, mp); + sp_2048_mont_sqr_36(r, r, m, mp); + sp_2048_mont_sqr_36(r, r, m, mp); + + sp_2048_lshift_36(r, r, y); + sp_2048_mul_d_36(tmp, norm, (r[36] << 4) + (r[35] >> 53)); + r[36] = 0; + r[35] &= 0x1fffffffffffffL; + (void)sp_2048_add_36(r, r, tmp); + sp_2048_norm_36(r); + o = sp_2048_cmp_36(r, m); + sp_2048_cond_sub_36(r, r, m, ((o < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + + sp_2048_mont_reduce_36(r, m, mp); + n = sp_2048_cmp_36(r, m); + sp_2048_cond_sub_36(r, r, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} + +#endif /* HAVE_FFDHE_2048 */ + +/* 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. + * returns 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) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 256) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL, DYNAMIC_TYPE_DH); + 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); + + #ifdef HAVE_FFDHE_2048 + if (base->used == 1 && base->dp[0] == 2 && + (m[35] >> 21) == 0xffffffffL) { + err = sp_2048_mod_exp_2_36(r, e, expLen * 8, m); + } + else + #endif + 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) * 36U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + 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) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 256U) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (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_DH); + 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); + + #ifdef HAVE_FFDHE_2048 + if (base->used == 1 && base->dp[0] == 2U && + (m[35] >> 21) == 0xffffffffL) { + err = sp_2048_mod_exp_2_36(r, e, expLen * 8U, m); + } + else { + #endif + err = sp_2048_mod_exp_36(r, b, e, expLen * 8U, m, 0); + #ifdef HAVE_FFDHE_2048 + } + #endif + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256U && out[i] == 0U; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 36U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 36U); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 18 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + b = d; + e = b + 18 * 2; + m = e + 18; + r = b; + + sp_2048_from_mp(b, 18, base); + sp_2048_from_mp(e, 18, exp); + sp_2048_from_mp(m, 18, mod); + + err = sp_2048_mod_exp_18(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 18, 0, sizeof(*r) * 18U); + err = sp_2048_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 18U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[36], ed[18], md[18]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 18 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 18 * 2; + m = e + 18; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 18, base); + sp_2048_from_mp(e, 18, exp); + sp_2048_from_mp(m, 18, mod); + + err = sp_2048_mod_exp_18(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 18, 0, sizeof(*r) * 18U); + err = sp_2048_to_mp(r, res); + } + + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 18U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 18U); +#endif + + return err; +#endif +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 49U) { + r[j] &= 0x1ffffffffffffffL; + s = 57U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 57 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 57 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x1ffffffffffffffL; + s = 57U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 57U) <= (word32)DIGIT_BIT) { + s += 57U; + r[j] &= 0x1ffffffffffffffL; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 57) { + r[j] &= 0x1ffffffffffffffL; + if (j + 1 >= size) { + break; + } + s = 57 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * 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; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 57) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 57); + if (j >= 0) { + 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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; + (void)sp_3072_add_9(a1, a, &a[9]); + (void)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); + (void)sp_3072_sub_18(z1, z1, z2); + (void)sp_3072_sub_18(z1, z1, z0); + (void)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. + */ +SP_NOINLINE 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; + (void)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); + (void)sp_3072_sub_18(z1, z1, z2); + (void)sp_3072_sub_18(z1, z1, z0); + (void)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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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]; + (void)sp_3072_add_18(a0, a, &a[18]); + (void)sp_3072_add_18(b0, b, &b[18]); + (void)sp_3072_add_18(a1, &a[18], &a[36]); + (void)sp_3072_add_18(b1, &b[18], &b[36]); + (void)sp_3072_add_18(a2, a0, &a[36]); + (void)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)*2U*54U); + (void)sp_3072_sub_36(t0, p3, p2); + (void)sp_3072_sub_36(t1, p1, p2); + (void)sp_3072_sub_36(t2, p5, t0); + (void)sp_3072_sub_36(t2, t2, t1); + (void)sp_3072_sub_36(t0, t0, p4); + (void)sp_3072_sub_36(t1, t1, p0); + (void)sp_3072_add_36(r, r, p0); + (void)sp_3072_add_36(&r[18], &r[18], t1); + (void)sp_3072_add_36(&r[36], &r[36], t2); + (void)sp_3072_add_36(&r[54], &r[54], t0); + (void)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. + */ +SP_NOINLINE 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]; + (void)sp_3072_add_18(a0, a, &a[18]); + (void)sp_3072_add_18(a1, &a[18], &a[36]); + (void)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)*2U*54U); + (void)sp_3072_sub_36(t0, p3, p2); + (void)sp_3072_sub_36(t1, p1, p2); + (void)sp_3072_sub_36(t2, p5, t0); + (void)sp_3072_sub_36(t2, t2, t1); + (void)sp_3072_sub_36(t0, t0, p4); + (void)sp_3072_sub_36(t1, t1, p0); + (void)sp_3072_add_36(r, r, p0); + (void)sp_3072_add_36(&r[18], &r[18], t1); + (void)sp_3072_add_36(&r[36], &r[36], t2); + (void)sp_3072_add_36(&r[54], &r[54], t0); + (void)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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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 /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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; +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_3072_mul_d_54(sp_digit* r, const sp_digit* a, + 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 */ +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_3072_mont_norm_27(sp_digit* r, const 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 */ + (void)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 == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[26] - b[26]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[25] - b[25]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[24] - b[24]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 16; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#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. + */ +SP_NOINLINE 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] += (sp_digit)(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 */ +} + +/* 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) * 27U); +} + +/* 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, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_3072_norm_27(a + 27); + + 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_digit)1 : (sp_digit)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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const 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. + */ +SP_NOINLINE static void sp_3072_mul_d_27(sp_digit* r, const sp_digit* a, + 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 */ +} + +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 57 bits from d1 and top 6 bits from d0. */ + d = (d1 << 6) | (d0 >> 51); + r = d / dv; + d -= r * dv; + /* Up to 7 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 45) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 13 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 39) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 19 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 33) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 25 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 27) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 31 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 21) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 37 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 15) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 43 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 9) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 49 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 3) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 55 bits in r */ + /* Remaining 3 bits from d0. */ + r <<= 3; + d <<= 3; + d |= d0 & ((1 << 3) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* 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 Number 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(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[54], t2d[27 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 27 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 2 * 27; +#else + t1 = t1d; + t2 = t2d; +#endif + + dv = d[26]; + XMEMCPY(t1, a, sizeof(*t1) * 2U * 27U); + for (i=26; i>=0; i--) { + t1[27 + i] += t1[27 + i - 1] >> 57; + t1[27 + i - 1] &= 0x1ffffffffffffffL; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[27 + i]; + d1 <<= 57; + d1 += t1[27 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_3072_div_word_27(t1[27 + i], t1[27 + i - 1], dv); +#endif + + sp_3072_mul_d_27(t2, d, r1); + (void)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]) / dv; + r1++; + sp_3072_mul_d_27(t2, d, r1); + (void)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; + r1 = t1[27 - 1] / dv; + + sp_3072_mul_d_27(t2, d, r1); + (void)sp_3072_sub_27(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 27U); + 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) ? + (sp_digit)1 : (sp_digit)0)); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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, const sp_digit* a, const 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, const sp_digit* a, const sp_digit* e, int bits, + const 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) * 3U * 27U * 2U); + + 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 != 0) { + err = sp_3072_mod_27(t[1], a, m); + } + else { + XMEMCPY(t[1], a, sizeof(sp_digit) * 27U); + } + } + 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) ? + (sp_digit)1 : (sp_digit)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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t[0] = td; + t[1] = &td[27 * 2]; + t[2] = &td[2 * 27 * 2]; +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_27(norm, m); + + if (reduceA != 0) { + 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) ? + (sp_digit)1 : (sp_digit)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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 54; +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_27(norm, m); + + if (reduceA != 0) { + 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) & 0x1f; + 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) ? + (sp_digit)1 : (sp_digit)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 /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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 single precision number. + */ +static void sp_3072_mont_norm_54(sp_digit* r, const 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 */ + (void)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 == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[53] - b[53]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[52] - b[52]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[51] - b[51]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[50] - b[50]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[49] - b[49]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[48] - b[48]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 40; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#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. + */ +SP_NOINLINE 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] += (sp_digit)(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 */ +} + +/* 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) * 54U); +} + +/* 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, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_3072_norm_54(a + 54); + +#ifdef WOLFSSL_SP_DH + 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; + } +#else + 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; +#endif + + sp_3072_mont_shift_54(a, a); + sp_3072_cond_sub_54(a, a, m, 0 - (((a[53] >> 51) > 0) ? + (sp_digit)1 : (sp_digit)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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_54(r, a); + sp_3072_mont_reduce_54(r, m, mp); +} + +/* 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 */ +} + +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 57 bits from d1 and top 6 bits from d0. */ + d = (d1 << 6) | (d0 >> 51); + r = d / dv; + d -= r * dv; + /* Up to 7 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 45) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 13 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 39) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 19 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 33) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 25 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 27) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 31 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 21) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 37 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 15) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 43 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 9) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 49 bits in r */ + /* Next 6 bits from d0. */ + r <<= 6; + d <<= 6; + d |= (d0 >> 3) & ((1 << 6) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 55 bits in r */ + /* Remaining 3 bits from d0. */ + r <<= 3; + d <<= 3; + d |= d0 & ((1 << 3) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* 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 Number 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(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[108], t2d[54 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 54 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 2 * 54; +#else + t1 = t1d; + t2 = t2d; +#endif + + dv = d[53]; + XMEMCPY(t1, a, sizeof(*t1) * 2U * 54U); + for (i=53; i>=0; i--) { + t1[54 + i] += t1[54 + i - 1] >> 57; + t1[54 + i - 1] &= 0x1ffffffffffffffL; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[54 + i]; + d1 <<= 57; + d1 += t1[54 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_3072_div_word_54(t1[54 + i], t1[54 + i - 1], dv); +#endif + + sp_3072_mul_d_54(t2, d, r1); + (void)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]) / dv; + r1++; + sp_3072_mul_d_54(t2, d, r1); + (void)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; + r1 = t1[54 - 1] / dv; + + sp_3072_mul_d_54(t2, d, r1); + (void)sp_3072_sub_54(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 54U); + 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) ? + (sp_digit)1 : (sp_digit)0)); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_54(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + 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, const sp_digit* a, const sp_digit* e, int bits, + const 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) * 3U * 54U * 2U); + + 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 != 0) { + err = sp_3072_mod_54(t[1], a, m); + } + else { + XMEMCPY(t[1], a, sizeof(sp_digit) * 54U); + } + } + 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) ? + (sp_digit)1 : (sp_digit)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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t[0] = td; + t[1] = &td[54 * 2]; + t[2] = &td[2 * 54 * 2]; +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + + if (reduceA != 0) { + 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) ? + (sp_digit)1 : (sp_digit)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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 108; +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + + if (reduceA != 0) { + 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) & 0x1f; + 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) ? + (sp_digit)1 : (sp_digit)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 /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ + /* 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) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1] = {0}; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 384U) { + err = MP_TO_E; + } + + if (err == MP_OKAY) { + if (mp_count_bits(em) > 57) { + err = MP_READ_E; + } + if (inLen > 384U) { + err = MP_READ_E; + } + if (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_RSA); + 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] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)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) != 0) { + 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) ? + (sp_digit)1 : (sp_digit)0)- 1); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + 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] = {0}; + int err = MP_OKAY; + + if (*outLen < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(em) > 57) { + err = MP_READ_E; + } + if (inLen > 384U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 3072) { + err = MP_READ_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 5, NULL, + DYNAMIC_TYPE_RSA); + 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] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)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) { + 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); + + 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) != 0) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 108U); + 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) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM) +#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */ +/* 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(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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 < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 3072) { + err = MP_READ_E; + } + if (inLen > 384) { + err = MP_READ_E; + } + if (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_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 54; + m = a + 108; + 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_RSA); + } + + 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 < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 3072) { + err = MP_READ_E; + } + if (inLen > 384U) { + err = MP_READ_E; + } + if (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)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (inLen > 384) { + err = MP_READ_E; + } + if (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_RSA); + 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; + + r = t + 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) { + (void)sp_3072_sub_27(tmpa, tmpa, tmpb); + sp_3072_cond_add_27(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[26] >> 63)); + sp_3072_cond_add_27(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[26] >> 63)); + + 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); + (void)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_RSA); + } + + return err; +#else + sp_digit a[54 * 2]; + sp_digit p[27], q[27], dp[27], dq[27], qi[27]; + sp_digit tmpa[54], tmpb[54]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (inLen > 384U) { + err = MP_READ_E; + } + if (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) { + (void)sp_3072_sub_27(tmpa, tmpa, tmpb); + sp_3072_cond_add_27(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[26] >> 63)); + sp_3072_cond_add_27(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[26] >> 63)); + 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); + (void)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 || RSA_LOW_MEM */ +} + +#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 57 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 54); + r->used = 54; + mp_clamp(r); +#elif DIGIT_BIT < 57 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 54; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 57) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 57 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 54; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 57 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 57 - s; + } + else { + s += 57; + } + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL, DYNAMIC_TYPE_DH); + 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_mp(e, 54, exp); + sp_3072_from_mp(m, 54, mod); + + err = sp_3072_mod_exp_54(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 54U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + 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; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (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_DH); + 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_mp(e, 54, exp); + sp_3072_from_mp(m, 54, mod); + + err = sp_3072_mod_exp_54(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 54U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 54U); +#endif + + return err; +#endif +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_3072 +SP_NOINLINE static void sp_3072_lshift_54(sp_digit* r, sp_digit* a, byte n) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + r[54] = a[53] >> (57 - n); + for (i=53; i>0; i--) { + r[i] = ((a[i] << n) | (a[i-1] >> (57 - n))) & 0x1ffffffffffffffL; + } +#else + sp_int_digit s, t; + + s = (sp_int_digit)a[53]; + r[54] = s >> (57U - n); + s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]); + r[53] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]); + r[52] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]); + r[51] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]); + r[50] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]); + r[49] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]); + r[48] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]); + r[47] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]); + r[46] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]); + r[45] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]); + r[44] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]); + r[43] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]); + r[42] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]); + r[41] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]); + r[40] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]); + r[39] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]); + r[38] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]); + r[37] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]); + r[36] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); + r[35] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); + r[34] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); + r[33] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); + r[32] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); + r[31] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); + r[30] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); + r[29] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); + r[28] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); + r[27] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); + r[26] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); + r[25] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); + r[24] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); + r[23] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); + r[22] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); + r[21] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); + r[20] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); + r[19] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); + r[18] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); + r[17] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); + r[16] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); + r[15] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); + r[14] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); + r[13] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); + r[12] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); + r[11] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); + r[10] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); + r[9] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); + r[8] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); + r[7] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); + r[6] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); + r[5] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); + r[4] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); + r[3] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); + r[2] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; + s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); + r[1] = ((s << n) | (t >> (57U - n))) & 0x1ffffffffffffffUL; +#endif + r[0] = (a[0] << n) & 0x1ffffffffffffffL; +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_54(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[108]; + sp_digit td[55]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 163, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 108; + XMEMSET(td, 0, sizeof(sp_digit) * 163); +#else + norm = nd; + tmp = td; + XMEMSET(td, 0, sizeof(td)); +#endif + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + + 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) & 0x1f; + n <<= 5; + c -= 5; + sp_3072_lshift_54(r, norm, y); + 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(r, r, m, mp); + sp_3072_mont_sqr_54(r, r, m, mp); + sp_3072_mont_sqr_54(r, r, m, mp); + sp_3072_mont_sqr_54(r, r, m, mp); + sp_3072_mont_sqr_54(r, r, m, mp); + + sp_3072_lshift_54(r, r, y); + sp_3072_mul_d_54(tmp, norm, (r[54] << 6) + (r[53] >> 51)); + r[54] = 0; + r[53] &= 0x7ffffffffffffL; + (void)sp_3072_add_54(r, r, tmp); + sp_3072_norm_54(r); + o = sp_3072_cmp_54(r, m); + sp_3072_cond_sub_54(r, r, m, ((o < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + + sp_3072_mont_reduce_54(r, m, mp); + n = sp_3072_cmp_54(r, m); + sp_3072_cond_sub_54(r, r, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} + +#endif /* HAVE_FFDHE_3072 */ + +/* 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. + * returns 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) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 384) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL, DYNAMIC_TYPE_DH); + 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); + + #ifdef HAVE_FFDHE_3072 + if (base->used == 1 && base->dp[0] == 2 && + (m[53] >> 19) == 0xffffffffL) { + err = sp_3072_mod_exp_2_54(r, e, expLen * 8, m); + } + else + #endif + 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) * 54U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + 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) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 384U) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (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_DH); + 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); + + #ifdef HAVE_FFDHE_3072 + if (base->used == 1 && base->dp[0] == 2U && + (m[53] >> 19) == 0xffffffffL) { + err = sp_3072_mod_exp_2_54(r, e, expLen * 8U, m); + } + else { + #endif + err = sp_3072_mod_exp_54(r, b, e, expLen * 8U, m, 0); + #ifdef HAVE_FFDHE_3072 + } + #endif + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384U && out[i] == 0U; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 54U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 54U); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 27 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + b = d; + e = b + 27 * 2; + m = e + 27; + r = b; + + sp_3072_from_mp(b, 27, base); + sp_3072_from_mp(e, 27, exp); + sp_3072_from_mp(m, 27, mod); + + err = sp_3072_mod_exp_27(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 27, 0, sizeof(*r) * 27U); + err = sp_3072_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 27U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[54], ed[27], md[27]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 27 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 27 * 2; + m = e + 27; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 27, base); + sp_3072_from_mp(e, 27, exp); + sp_3072_from_mp(m, 27, mod); + + err = sp_3072_mod_exp_27(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 27, 0, sizeof(*r) * 27U); + err = sp_3072_to_mp(r, res); + } + + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 27U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 27U); +#endif + + return err; +#endif +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#ifdef WOLFSSL_SP_4096 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 45U) { + r[j] &= 0x1fffffffffffffL; + s = 53U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 53 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 53 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x1fffffffffffffL; + s = 53U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 53U) <= (word32)DIGIT_BIT) { + s += 53U; + r[j] &= 0x1fffffffffffffL; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 53) { + r[j] &= 0x1fffffffffffffL; + if (j + 1 >= size) { + break; + } + s = 53 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 512 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_4096_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<77; i++) { + r[i+1] += r[i] >> 53; + r[i] &= 0x1fffffffffffffL; + } + j = 4096 / 8 - 1; + a[j] = 0; + for (i=0; i<78 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 53) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 53); + if (j >= 0) { + 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. + */ +SP_NOINLINE static void sp_4096_mul_13(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[ 0]) * b[ 9] + + ((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)a[ 9]) * b[ 0]; + int128_t t10 = ((int128_t)a[ 0]) * b[10] + + ((int128_t)a[ 1]) * b[ 9] + + ((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)a[ 9]) * b[ 1] + + ((int128_t)a[10]) * b[ 0]; + int128_t t11 = ((int128_t)a[ 0]) * b[11] + + ((int128_t)a[ 1]) * b[10] + + ((int128_t)a[ 2]) * b[ 9] + + ((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)a[ 9]) * b[ 2] + + ((int128_t)a[10]) * b[ 1] + + ((int128_t)a[11]) * b[ 0]; + int128_t t12 = ((int128_t)a[ 0]) * b[12] + + ((int128_t)a[ 1]) * b[11] + + ((int128_t)a[ 2]) * b[10] + + ((int128_t)a[ 3]) * b[ 9] + + ((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)a[ 9]) * b[ 3] + + ((int128_t)a[10]) * b[ 2] + + ((int128_t)a[11]) * b[ 1] + + ((int128_t)a[12]) * b[ 0]; + int128_t t13 = ((int128_t)a[ 1]) * b[12] + + ((int128_t)a[ 2]) * b[11] + + ((int128_t)a[ 3]) * b[10] + + ((int128_t)a[ 4]) * b[ 9] + + ((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)a[ 9]) * b[ 4] + + ((int128_t)a[10]) * b[ 3] + + ((int128_t)a[11]) * b[ 2] + + ((int128_t)a[12]) * b[ 1]; + int128_t t14 = ((int128_t)a[ 2]) * b[12] + + ((int128_t)a[ 3]) * b[11] + + ((int128_t)a[ 4]) * b[10] + + ((int128_t)a[ 5]) * b[ 9] + + ((int128_t)a[ 6]) * b[ 8] + + ((int128_t)a[ 7]) * b[ 7] + + ((int128_t)a[ 8]) * b[ 6] + + ((int128_t)a[ 9]) * b[ 5] + + ((int128_t)a[10]) * b[ 4] + + ((int128_t)a[11]) * b[ 3] + + ((int128_t)a[12]) * b[ 2]; + int128_t t15 = ((int128_t)a[ 3]) * b[12] + + ((int128_t)a[ 4]) * b[11] + + ((int128_t)a[ 5]) * b[10] + + ((int128_t)a[ 6]) * b[ 9] + + ((int128_t)a[ 7]) * b[ 8] + + ((int128_t)a[ 8]) * b[ 7] + + ((int128_t)a[ 9]) * b[ 6] + + ((int128_t)a[10]) * b[ 5] + + ((int128_t)a[11]) * b[ 4] + + ((int128_t)a[12]) * b[ 3]; + int128_t t16 = ((int128_t)a[ 4]) * b[12] + + ((int128_t)a[ 5]) * b[11] + + ((int128_t)a[ 6]) * b[10] + + ((int128_t)a[ 7]) * b[ 9] + + ((int128_t)a[ 8]) * b[ 8] + + ((int128_t)a[ 9]) * b[ 7] + + ((int128_t)a[10]) * b[ 6] + + ((int128_t)a[11]) * b[ 5] + + ((int128_t)a[12]) * b[ 4]; + int128_t t17 = ((int128_t)a[ 5]) * b[12] + + ((int128_t)a[ 6]) * b[11] + + ((int128_t)a[ 7]) * b[10] + + ((int128_t)a[ 8]) * b[ 9] + + ((int128_t)a[ 9]) * b[ 8] + + ((int128_t)a[10]) * b[ 7] + + ((int128_t)a[11]) * b[ 6] + + ((int128_t)a[12]) * b[ 5]; + int128_t t18 = ((int128_t)a[ 6]) * b[12] + + ((int128_t)a[ 7]) * b[11] + + ((int128_t)a[ 8]) * b[10] + + ((int128_t)a[ 9]) * b[ 9] + + ((int128_t)a[10]) * b[ 8] + + ((int128_t)a[11]) * b[ 7] + + ((int128_t)a[12]) * b[ 6]; + int128_t t19 = ((int128_t)a[ 7]) * b[12] + + ((int128_t)a[ 8]) * b[11] + + ((int128_t)a[ 9]) * b[10] + + ((int128_t)a[10]) * b[ 9] + + ((int128_t)a[11]) * b[ 8] + + ((int128_t)a[12]) * b[ 7]; + int128_t t20 = ((int128_t)a[ 8]) * b[12] + + ((int128_t)a[ 9]) * b[11] + + ((int128_t)a[10]) * b[10] + + ((int128_t)a[11]) * b[ 9] + + ((int128_t)a[12]) * b[ 8]; + int128_t t21 = ((int128_t)a[ 9]) * b[12] + + ((int128_t)a[10]) * b[11] + + ((int128_t)a[11]) * b[10] + + ((int128_t)a[12]) * b[ 9]; + int128_t t22 = ((int128_t)a[10]) * b[12] + + ((int128_t)a[11]) * b[11] + + ((int128_t)a[12]) * b[10]; + int128_t t23 = ((int128_t)a[11]) * b[12] + + ((int128_t)a[12]) * b[11]; + int128_t t24 = ((int128_t)a[12]) * b[12]; + + t1 += t0 >> 53; r[ 0] = t0 & 0x1fffffffffffffL; + t2 += t1 >> 53; r[ 1] = t1 & 0x1fffffffffffffL; + t3 += t2 >> 53; r[ 2] = t2 & 0x1fffffffffffffL; + t4 += t3 >> 53; r[ 3] = t3 & 0x1fffffffffffffL; + t5 += t4 >> 53; r[ 4] = t4 & 0x1fffffffffffffL; + t6 += t5 >> 53; r[ 5] = t5 & 0x1fffffffffffffL; + t7 += t6 >> 53; r[ 6] = t6 & 0x1fffffffffffffL; + t8 += t7 >> 53; r[ 7] = t7 & 0x1fffffffffffffL; + t9 += t8 >> 53; r[ 8] = t8 & 0x1fffffffffffffL; + t10 += t9 >> 53; r[ 9] = t9 & 0x1fffffffffffffL; + t11 += t10 >> 53; r[10] = t10 & 0x1fffffffffffffL; + t12 += t11 >> 53; r[11] = t11 & 0x1fffffffffffffL; + t13 += t12 >> 53; r[12] = t12 & 0x1fffffffffffffL; + t14 += t13 >> 53; r[13] = t13 & 0x1fffffffffffffL; + t15 += t14 >> 53; r[14] = t14 & 0x1fffffffffffffL; + t16 += t15 >> 53; r[15] = t15 & 0x1fffffffffffffL; + t17 += t16 >> 53; r[16] = t16 & 0x1fffffffffffffL; + t18 += t17 >> 53; r[17] = t17 & 0x1fffffffffffffL; + t19 += t18 >> 53; r[18] = t18 & 0x1fffffffffffffL; + t20 += t19 >> 53; r[19] = t19 & 0x1fffffffffffffL; + t21 += t20 >> 53; r[20] = t20 & 0x1fffffffffffffL; + t22 += t21 >> 53; r[21] = t21 & 0x1fffffffffffffL; + t23 += t22 >> 53; r[22] = t22 & 0x1fffffffffffffL; + t24 += t23 >> 53; r[23] = t23 & 0x1fffffffffffffL; + r[25] = (sp_digit)(t24 >> 53); + r[24] = t24 & 0x1fffffffffffffL; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_4096_sqr_13(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[ 0]) * a[ 9] + + ((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[ 0]) * a[10] + + ((int128_t)a[ 1]) * a[ 9] + + ((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[ 0]) * a[11] + + ((int128_t)a[ 1]) * a[10] + + ((int128_t)a[ 2]) * a[ 9] + + ((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[ 0]) * a[12] + + ((int128_t)a[ 1]) * a[11] + + ((int128_t)a[ 2]) * a[10] + + ((int128_t)a[ 3]) * a[ 9] + + ((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[ 1]) * a[12] + + ((int128_t)a[ 2]) * a[11] + + ((int128_t)a[ 3]) * a[10] + + ((int128_t)a[ 4]) * a[ 9] + + ((int128_t)a[ 5]) * a[ 8] + + ((int128_t)a[ 6]) * a[ 7]) * 2; + int128_t t14 = (((int128_t)a[ 2]) * a[12] + + ((int128_t)a[ 3]) * a[11] + + ((int128_t)a[ 4]) * a[10] + + ((int128_t)a[ 5]) * a[ 9] + + ((int128_t)a[ 6]) * a[ 8]) * 2 + + ((int128_t)a[ 7]) * a[ 7]; + int128_t t15 = (((int128_t)a[ 3]) * a[12] + + ((int128_t)a[ 4]) * a[11] + + ((int128_t)a[ 5]) * a[10] + + ((int128_t)a[ 6]) * a[ 9] + + ((int128_t)a[ 7]) * a[ 8]) * 2; + int128_t t16 = (((int128_t)a[ 4]) * a[12] + + ((int128_t)a[ 5]) * a[11] + + ((int128_t)a[ 6]) * a[10] + + ((int128_t)a[ 7]) * a[ 9]) * 2 + + ((int128_t)a[ 8]) * a[ 8]; + int128_t t17 = (((int128_t)a[ 5]) * a[12] + + ((int128_t)a[ 6]) * a[11] + + ((int128_t)a[ 7]) * a[10] + + ((int128_t)a[ 8]) * a[ 9]) * 2; + int128_t t18 = (((int128_t)a[ 6]) * a[12] + + ((int128_t)a[ 7]) * a[11] + + ((int128_t)a[ 8]) * a[10]) * 2 + + ((int128_t)a[ 9]) * a[ 9]; + int128_t t19 = (((int128_t)a[ 7]) * a[12] + + ((int128_t)a[ 8]) * a[11] + + ((int128_t)a[ 9]) * a[10]) * 2; + int128_t t20 = (((int128_t)a[ 8]) * a[12] + + ((int128_t)a[ 9]) * a[11]) * 2 + + ((int128_t)a[10]) * a[10]; + int128_t t21 = (((int128_t)a[ 9]) * a[12] + + ((int128_t)a[10]) * a[11]) * 2; + int128_t t22 = (((int128_t)a[10]) * a[12]) * 2 + + ((int128_t)a[11]) * a[11]; + int128_t t23 = (((int128_t)a[11]) * a[12]) * 2; + int128_t t24 = ((int128_t)a[12]) * a[12]; + + t1 += t0 >> 53; r[ 0] = t0 & 0x1fffffffffffffL; + t2 += t1 >> 53; r[ 1] = t1 & 0x1fffffffffffffL; + t3 += t2 >> 53; r[ 2] = t2 & 0x1fffffffffffffL; + t4 += t3 >> 53; r[ 3] = t3 & 0x1fffffffffffffL; + t5 += t4 >> 53; r[ 4] = t4 & 0x1fffffffffffffL; + t6 += t5 >> 53; r[ 5] = t5 & 0x1fffffffffffffL; + t7 += t6 >> 53; r[ 6] = t6 & 0x1fffffffffffffL; + t8 += t7 >> 53; r[ 7] = t7 & 0x1fffffffffffffL; + t9 += t8 >> 53; r[ 8] = t8 & 0x1fffffffffffffL; + t10 += t9 >> 53; r[ 9] = t9 & 0x1fffffffffffffL; + t11 += t10 >> 53; r[10] = t10 & 0x1fffffffffffffL; + t12 += t11 >> 53; r[11] = t11 & 0x1fffffffffffffL; + t13 += t12 >> 53; r[12] = t12 & 0x1fffffffffffffL; + t14 += t13 >> 53; r[13] = t13 & 0x1fffffffffffffL; + t15 += t14 >> 53; r[14] = t14 & 0x1fffffffffffffL; + t16 += t15 >> 53; r[15] = t15 & 0x1fffffffffffffL; + t17 += t16 >> 53; r[16] = t16 & 0x1fffffffffffffL; + t18 += t17 >> 53; r[17] = t17 & 0x1fffffffffffffL; + t19 += t18 >> 53; r[18] = t18 & 0x1fffffffffffffL; + t20 += t19 >> 53; r[19] = t19 & 0x1fffffffffffffL; + t21 += t20 >> 53; r[20] = t20 & 0x1fffffffffffffL; + t22 += t21 >> 53; r[21] = t21 & 0x1fffffffffffffL; + t23 += t22 >> 53; r[22] = t22 & 0x1fffffffffffffL; + t24 += t23 >> 53; r[23] = t23 & 0x1fffffffffffffL; + r[25] = (sp_digit)(t24 >> 53); + r[24] = t24 & 0x1fffffffffffffL; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_4096_add_13(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]; + r[10] = a[10] + b[10]; + r[11] = a[11] + b[11]; + r[12] = a[12] + b[12]; + + 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. + */ +SP_NOINLINE static int sp_4096_sub_26(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]; + + 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. + */ +SP_NOINLINE static int sp_4096_add_26(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]; + + 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. + */ +SP_NOINLINE static void sp_4096_mul_39(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit p0[26]; + sp_digit p1[26]; + sp_digit p2[26]; + sp_digit p3[26]; + sp_digit p4[26]; + sp_digit p5[26]; + sp_digit t0[26]; + sp_digit t1[26]; + sp_digit t2[26]; + sp_digit a0[13]; + sp_digit a1[13]; + sp_digit a2[13]; + sp_digit b0[13]; + sp_digit b1[13]; + sp_digit b2[13]; + (void)sp_4096_add_13(a0, a, &a[13]); + (void)sp_4096_add_13(b0, b, &b[13]); + (void)sp_4096_add_13(a1, &a[13], &a[26]); + (void)sp_4096_add_13(b1, &b[13], &b[26]); + (void)sp_4096_add_13(a2, a0, &a[26]); + (void)sp_4096_add_13(b2, b0, &b[26]); + sp_4096_mul_13(p0, a, b); + sp_4096_mul_13(p2, &a[13], &b[13]); + sp_4096_mul_13(p4, &a[26], &b[26]); + sp_4096_mul_13(p1, a0, b0); + sp_4096_mul_13(p3, a1, b1); + sp_4096_mul_13(p5, a2, b2); + XMEMSET(r, 0, sizeof(*r)*2U*39U); + (void)sp_4096_sub_26(t0, p3, p2); + (void)sp_4096_sub_26(t1, p1, p2); + (void)sp_4096_sub_26(t2, p5, t0); + (void)sp_4096_sub_26(t2, t2, t1); + (void)sp_4096_sub_26(t0, t0, p4); + (void)sp_4096_sub_26(t1, t1, p0); + (void)sp_4096_add_26(r, r, p0); + (void)sp_4096_add_26(&r[13], &r[13], t1); + (void)sp_4096_add_26(&r[26], &r[26], t2); + (void)sp_4096_add_26(&r[39], &r[39], t0); + (void)sp_4096_add_26(&r[52], &r[52], p4); +} + +/* Square a into r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_4096_sqr_39(sp_digit* r, const sp_digit* a) +{ + sp_digit p0[26]; + sp_digit p1[26]; + sp_digit p2[26]; + sp_digit p3[26]; + sp_digit p4[26]; + sp_digit p5[26]; + sp_digit t0[26]; + sp_digit t1[26]; + sp_digit t2[26]; + sp_digit a0[13]; + sp_digit a1[13]; + sp_digit a2[13]; + (void)sp_4096_add_13(a0, a, &a[13]); + (void)sp_4096_add_13(a1, &a[13], &a[26]); + (void)sp_4096_add_13(a2, a0, &a[26]); + sp_4096_sqr_13(p0, a); + sp_4096_sqr_13(p2, &a[13]); + sp_4096_sqr_13(p4, &a[26]); + sp_4096_sqr_13(p1, a0); + sp_4096_sqr_13(p3, a1); + sp_4096_sqr_13(p5, a2); + XMEMSET(r, 0, sizeof(*r)*2U*39U); + (void)sp_4096_sub_26(t0, p3, p2); + (void)sp_4096_sub_26(t1, p1, p2); + (void)sp_4096_sub_26(t2, p5, t0); + (void)sp_4096_sub_26(t2, t2, t1); + (void)sp_4096_sub_26(t0, t0, p4); + (void)sp_4096_sub_26(t1, t1, p0); + (void)sp_4096_add_26(r, r, p0); + (void)sp_4096_add_26(&r[13], &r[13], t1); + (void)sp_4096_add_26(&r[26], &r[26], t2); + (void)sp_4096_add_26(&r[39], &r[39], t0); + (void)sp_4096_add_26(&r[52], &r[52], p4); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_4096_add_39(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]; + r[36] = a[36] + b[36]; + r[37] = a[37] + b[37]; + r[38] = a[38] + b[38]; + + 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. + */ +SP_NOINLINE static int sp_4096_add_78(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 72; 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[72] = a[72] + b[72]; + r[73] = a[73] + b[73]; + r[74] = a[74] + b[74]; + r[75] = a[75] + b[75]; + r[76] = a[76] + b[76]; + r[77] = a[77] + b[77]; + + 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. + */ +SP_NOINLINE static int sp_4096_sub_78(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 72; 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[72] = a[72] - b[72]; + r[73] = a[73] - b[73]; + r[74] = a[74] - b[74]; + r[75] = a[75] - b[75]; + r[76] = a[76] - b[76]; + r[77] = a[77] - b[77]; + + 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. + */ +SP_NOINLINE static void sp_4096_mul_78(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[78]; + sp_digit* a1 = z1; + sp_digit b1[39]; + sp_digit* z2 = r + 78; + (void)sp_4096_add_39(a1, a, &a[39]); + (void)sp_4096_add_39(b1, b, &b[39]); + sp_4096_mul_39(z2, &a[39], &b[39]); + sp_4096_mul_39(z0, a, b); + sp_4096_mul_39(z1, a1, b1); + (void)sp_4096_sub_78(z1, z1, z2); + (void)sp_4096_sub_78(z1, z1, z0); + (void)sp_4096_add_78(r + 39, r + 39, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_4096_sqr_78(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[78]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 78; + (void)sp_4096_add_39(a1, a, &a[39]); + sp_4096_sqr_39(z2, &a[39]); + sp_4096_sqr_39(z0, a); + sp_4096_sqr_39(z1, a1); + (void)sp_4096_sub_78(z1, z1, z2); + (void)sp_4096_sub_78(z1, z1, z0); + (void)sp_4096_add_78(r + 39, r + 39, 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. + */ +SP_NOINLINE static int sp_4096_add_78(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 78; 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. + */ +SP_NOINLINE static int sp_4096_sub_78(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 78; 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. + */ +SP_NOINLINE static void sp_4096_mul_78(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[77]) * b[77]; + r[155] = (sp_digit)(c >> 53); + c = (c & 0x1fffffffffffffL) << 53; + for (k = 153; k >= 0; k--) { + for (i = 77; i >= 0; i--) { + j = k - i; + if (j >= 78) { + break; + } + if (j < 0) { + continue; + } + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 106; + r[k + 1] = (c >> 53) & 0x1fffffffffffffL; + c = (c & 0x1fffffffffffffL) << 53; + } + r[0] = (sp_digit)(c >> 53); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_4096_sqr_78(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[77]) * a[77]; + r[155] = (sp_digit)(c >> 53); + c = (c & 0x1fffffffffffffL) << 53; + for (k = 153; k >= 0; k--) { + for (i = 77; i >= 0; i--) { + j = k - i; + if (j >= 78 || 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 >> 106; + r[k + 1] = (c >> 53) & 0x1fffffffffffffL; + c = (c & 0x1fffffffffffffL) << 53; + } + r[0] = (sp_digit)(c >> 53); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) +#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. + */ +SP_NOINLINE static int sp_4096_add_39(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 39; 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. + */ +SP_NOINLINE static int sp_4096_sub_39(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 39; 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. + */ +SP_NOINLINE static int sp_4096_sub_39(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]; + r[36] = a[36] - b[36]; + r[37] = a[37] - b[37]; + r[38] = a[38] - b[38]; + + 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. + */ +SP_NOINLINE static void sp_4096_mul_39(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[38]) * b[38]; + r[77] = (sp_digit)(c >> 53); + c = (c & 0x1fffffffffffffL) << 53; + for (k = 75; k >= 0; k--) { + for (i = 38; i >= 0; i--) { + j = k - i; + if (j >= 39) { + break; + } + if (j < 0) { + continue; + } + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 106; + r[k + 1] = (c >> 53) & 0x1fffffffffffffL; + c = (c & 0x1fffffffffffffL) << 53; + } + r[0] = (sp_digit)(c >> 53); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_4096_sqr_39(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[38]) * a[38]; + r[77] = (sp_digit)(c >> 53); + c = (c & 0x1fffffffffffffL) << 53; + for (k = 75; k >= 0; k--) { + for (i = 38; i >= 0; i--) { + j = k - i; + if (j >= 39 || 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 >> 106; + r[k + 1] = (c >> 53) & 0x1fffffffffffffL; + c = (c & 0x1fffffffffffffL) << 53; + } + r[0] = (sp_digit)(c >> 53); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* WOLFSSL_HAVE_SP_RSA && !SP_RSA_PRIVATE_EXP_D */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_4096_mont_setup(const 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 &= 0x1fffffffffffffL; + + /* rho = -1/m mod b */ + *rho = (1L << 53) - x; +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_4096_mul_d_78(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 78; i++) { + t += tb * a[i]; + r[i] = t & 0x1fffffffffffffL; + t >>= 53; + } + r[78] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1fffffffffffffL; + for (i = 0; i < 72; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 53) + (t[1] & 0x1fffffffffffffL); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 53) + (t[2] & 0x1fffffffffffffL); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 53) + (t[3] & 0x1fffffffffffffL); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 53) + (t[4] & 0x1fffffffffffffL); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 53) + (t[5] & 0x1fffffffffffffL); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 53) + (t[6] & 0x1fffffffffffffL); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 53) + (t[7] & 0x1fffffffffffffL); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 53) + (t[0] & 0x1fffffffffffffL); + } + t[1] = tb * a[73]; + r[73] = (sp_digit)(t[0] >> 53) + (t[1] & 0x1fffffffffffffL); + t[2] = tb * a[74]; + r[74] = (sp_digit)(t[1] >> 53) + (t[2] & 0x1fffffffffffffL); + t[3] = tb * a[75]; + r[75] = (sp_digit)(t[2] >> 53) + (t[3] & 0x1fffffffffffffL); + t[4] = tb * a[76]; + r[76] = (sp_digit)(t[3] >> 53) + (t[4] & 0x1fffffffffffffL); + t[5] = tb * a[77]; + r[77] = (sp_digit)(t[4] >> 53) + (t[5] & 0x1fffffffffffffL); + r[78] = (sp_digit)(t[5] >> 53); +#endif /* WOLFSSL_SP_SMALL */ +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 4096 bits, just need to subtract. + * + * r A single precision number. + * m A single precision number. + */ +static void sp_4096_mont_norm_39(sp_digit* r, const sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<38; i++) { + r[i] = 0x1fffffffffffffL; + } +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = 0x1fffffffffffffL; + r[i + 1] = 0x1fffffffffffffL; + r[i + 2] = 0x1fffffffffffffL; + r[i + 3] = 0x1fffffffffffffL; + r[i + 4] = 0x1fffffffffffffL; + r[i + 5] = 0x1fffffffffffffL; + r[i + 6] = 0x1fffffffffffffL; + r[i + 7] = 0x1fffffffffffffL; + } + r[32] = 0x1fffffffffffffL; + r[33] = 0x1fffffffffffffL; + r[34] = 0x1fffffffffffffL; + r[35] = 0x1fffffffffffffL; + r[36] = 0x1fffffffffffffL; + r[37] = 0x1fffffffffffffL; +#endif + r[38] = 0x3ffffffffL; + + /* r = (2^n - 1) mod n */ + (void)sp_4096_sub_39(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_4096_cmp_39(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=38; i>=0; i--) { + r |= (a[i] - b[i]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[38] - b[38]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[37] - b[37]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[36] - b[36]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[35] - b[35]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[34] - b[34]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[33] - b[33]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[32] - b[32]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 24; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#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_4096_cond_sub_39(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 < 39; 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); + r[36] = a[36] - (b[36] & m); + r[37] = a[37] - (b[37] & m); + r[38] = a[38] - (b[38] & 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. + */ +SP_NOINLINE static void sp_4096_mul_add_39(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 < 39; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1fffffffffffffL; + t >>= 53; + } + r[39] += t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1fffffffffffffL); + for (i = 0; i < 32; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (sp_digit)((t[0] >> 53) + (t[1] & 0x1fffffffffffffL)); + t[2] = tb * a[i+2]; + r[i+2] += (sp_digit)((t[1] >> 53) + (t[2] & 0x1fffffffffffffL)); + t[3] = tb * a[i+3]; + r[i+3] += (sp_digit)((t[2] >> 53) + (t[3] & 0x1fffffffffffffL)); + t[4] = tb * a[i+4]; + r[i+4] += (sp_digit)((t[3] >> 53) + (t[4] & 0x1fffffffffffffL)); + t[5] = tb * a[i+5]; + r[i+5] += (sp_digit)((t[4] >> 53) + (t[5] & 0x1fffffffffffffL)); + t[6] = tb * a[i+6]; + r[i+6] += (sp_digit)((t[5] >> 53) + (t[6] & 0x1fffffffffffffL)); + t[7] = tb * a[i+7]; + r[i+7] += (sp_digit)((t[6] >> 53) + (t[7] & 0x1fffffffffffffL)); + t[0] = tb * a[i+8]; + r[i+8] += (sp_digit)((t[7] >> 53) + (t[0] & 0x1fffffffffffffL)); + } + t[1] = tb * a[33]; r[33] += (sp_digit)((t[0] >> 53) + (t[1] & 0x1fffffffffffffL)); + t[2] = tb * a[34]; r[34] += (sp_digit)((t[1] >> 53) + (t[2] & 0x1fffffffffffffL)); + t[3] = tb * a[35]; r[35] += (sp_digit)((t[2] >> 53) + (t[3] & 0x1fffffffffffffL)); + t[4] = tb * a[36]; r[36] += (sp_digit)((t[3] >> 53) + (t[4] & 0x1fffffffffffffL)); + t[5] = tb * a[37]; r[37] += (sp_digit)((t[4] >> 53) + (t[5] & 0x1fffffffffffffL)); + t[6] = tb * a[38]; r[38] += (sp_digit)((t[5] >> 53) + (t[6] & 0x1fffffffffffffL)); + r[39] += (sp_digit)(t[6] >> 53); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 53. + * + * a Array of sp_digit to normalize. + */ +static void sp_4096_norm_39(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 38; i++) { + a[i+1] += a[i] >> 53; + a[i] &= 0x1fffffffffffffL; + } +#else + int i; + for (i = 0; i < 32; i += 8) { + a[i+1] += a[i+0] >> 53; a[i+0] &= 0x1fffffffffffffL; + a[i+2] += a[i+1] >> 53; a[i+1] &= 0x1fffffffffffffL; + a[i+3] += a[i+2] >> 53; a[i+2] &= 0x1fffffffffffffL; + a[i+4] += a[i+3] >> 53; a[i+3] &= 0x1fffffffffffffL; + a[i+5] += a[i+4] >> 53; a[i+4] &= 0x1fffffffffffffL; + a[i+6] += a[i+5] >> 53; a[i+5] &= 0x1fffffffffffffL; + a[i+7] += a[i+6] >> 53; a[i+6] &= 0x1fffffffffffffL; + a[i+8] += a[i+7] >> 53; a[i+7] &= 0x1fffffffffffffL; + a[i+9] += a[i+8] >> 53; a[i+8] &= 0x1fffffffffffffL; + } + a[32+1] += a[32] >> 53; + a[32] &= 0x1fffffffffffffL; + a[33+1] += a[33] >> 53; + a[33] &= 0x1fffffffffffffL; + a[34+1] += a[34] >> 53; + a[34] &= 0x1fffffffffffffL; + a[35+1] += a[35] >> 53; + a[35] &= 0x1fffffffffffffL; + a[36+1] += a[36] >> 53; + a[36] &= 0x1fffffffffffffL; + a[37+1] += a[37] >> 53; + a[37] &= 0x1fffffffffffffL; +#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_4096_mont_shift_39(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int128_t n = a[38] >> 34; + n += ((int128_t)a[39]) << 19; + + for (i = 0; i < 38; i++) { + r[i] = n & 0x1fffffffffffffL; + n >>= 53; + n += ((int128_t)a[40 + i]) << 19; + } + r[38] = (sp_digit)n; +#else + int i; + int128_t n = a[38] >> 34; + n += ((int128_t)a[39]) << 19; + for (i = 0; i < 32; i += 8) { + r[i + 0] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 40]) << 19; + r[i + 1] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 41]) << 19; + r[i + 2] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 42]) << 19; + r[i + 3] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 43]) << 19; + r[i + 4] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 44]) << 19; + r[i + 5] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 45]) << 19; + r[i + 6] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 46]) << 19; + r[i + 7] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 47]) << 19; + } + r[32] = n & 0x1fffffffffffffL; n >>= 53; n += ((int128_t)a[72]) << 19; + r[33] = n & 0x1fffffffffffffL; n >>= 53; n += ((int128_t)a[73]) << 19; + r[34] = n & 0x1fffffffffffffL; n >>= 53; n += ((int128_t)a[74]) << 19; + r[35] = n & 0x1fffffffffffffL; n >>= 53; n += ((int128_t)a[75]) << 19; + r[36] = n & 0x1fffffffffffffL; n >>= 53; n += ((int128_t)a[76]) << 19; + r[37] = n & 0x1fffffffffffffL; n >>= 53; n += ((int128_t)a[77]) << 19; + r[38] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[39], 0, sizeof(*r) * 39U); +} + +/* Reduce the number back to 4096 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_4096_mont_reduce_39(sp_digit* a, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_4096_norm_39(a + 39); + + for (i=0; i<38; i++) { + mu = (a[i] * mp) & 0x1fffffffffffffL; + sp_4096_mul_add_39(a+i, m, mu); + a[i+1] += a[i] >> 53; + } + mu = (a[i] * mp) & 0x3ffffffffL; + sp_4096_mul_add_39(a+i, m, mu); + a[i+1] += a[i] >> 53; + a[i] &= 0x1fffffffffffffL; + + sp_4096_mont_shift_39(a, a); + sp_4096_cond_sub_39(a, a, m, 0 - (((a[38] >> 34) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_4096_norm_39(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_4096_mont_mul_39(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_4096_mul_39(r, a, b); + sp_4096_mont_reduce_39(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_4096_mont_sqr_39(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_4096_sqr_39(r, a); + sp_4096_mont_reduce_39(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. + */ +SP_NOINLINE static void sp_4096_mul_d_39(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 39; i++) { + t += tb * a[i]; + r[i] = t & 0x1fffffffffffffL; + t >>= 53; + } + r[39] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1fffffffffffffL; + for (i = 0; i < 32; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 53) + (t[1] & 0x1fffffffffffffL); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 53) + (t[2] & 0x1fffffffffffffL); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 53) + (t[3] & 0x1fffffffffffffL); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 53) + (t[4] & 0x1fffffffffffffL); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 53) + (t[5] & 0x1fffffffffffffL); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 53) + (t[6] & 0x1fffffffffffffL); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 53) + (t[7] & 0x1fffffffffffffL); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 53) + (t[0] & 0x1fffffffffffffL); + } + t[1] = tb * a[33]; + r[33] = (sp_digit)(t[0] >> 53) + (t[1] & 0x1fffffffffffffL); + t[2] = tb * a[34]; + r[34] = (sp_digit)(t[1] >> 53) + (t[2] & 0x1fffffffffffffL); + t[3] = tb * a[35]; + r[35] = (sp_digit)(t[2] >> 53) + (t[3] & 0x1fffffffffffffL); + t[4] = tb * a[36]; + r[36] = (sp_digit)(t[3] >> 53) + (t[4] & 0x1fffffffffffffL); + t[5] = tb * a[37]; + r[37] = (sp_digit)(t[4] >> 53) + (t[5] & 0x1fffffffffffffL); + t[6] = tb * a[38]; + r[38] = (sp_digit)(t[5] >> 53) + (t[6] & 0x1fffffffffffffL); + r[39] = (sp_digit)(t[6] >> 53); +#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_4096_cond_add_39(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 < 39; 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); + r[36] = a[36] + (b[36] & m); + r[37] = a[37] + (b[37] & m); + r[38] = a[38] + (b[38] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_4096_add_39(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 39; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#endif +SP_NOINLINE static void sp_4096_rshift_39(sp_digit* r, sp_digit* a, byte n) +{ + int i; + +#ifdef WOLFSSL_SP_SMALL + for (i=0; i<38; i++) { + r[i] = ((a[i] >> n) | (a[i + 1] << (53 - n))) & 0x1fffffffffffffL; + } +#else + for (i=0; i<32; i += 8) { + r[i+0] = ((a[i+0] >> n) | (a[i+1] << (53 - n))) & 0x1fffffffffffffL; + r[i+1] = ((a[i+1] >> n) | (a[i+2] << (53 - n))) & 0x1fffffffffffffL; + r[i+2] = ((a[i+2] >> n) | (a[i+3] << (53 - n))) & 0x1fffffffffffffL; + r[i+3] = ((a[i+3] >> n) | (a[i+4] << (53 - n))) & 0x1fffffffffffffL; + r[i+4] = ((a[i+4] >> n) | (a[i+5] << (53 - n))) & 0x1fffffffffffffL; + r[i+5] = ((a[i+5] >> n) | (a[i+6] << (53 - n))) & 0x1fffffffffffffL; + r[i+6] = ((a[i+6] >> n) | (a[i+7] << (53 - n))) & 0x1fffffffffffffL; + r[i+7] = ((a[i+7] >> n) | (a[i+8] << (53 - n))) & 0x1fffffffffffffL; + } + r[32] = ((a[32] >> n) | (a[33] << (53 - n))) & 0x1fffffffffffffL; + r[33] = ((a[33] >> n) | (a[34] << (53 - n))) & 0x1fffffffffffffL; + r[34] = ((a[34] >> n) | (a[35] << (53 - n))) & 0x1fffffffffffffL; + r[35] = ((a[35] >> n) | (a[36] << (53 - n))) & 0x1fffffffffffffL; + r[36] = ((a[36] >> n) | (a[37] << (53 - n))) & 0x1fffffffffffffL; + r[37] = ((a[37] >> n) | (a[38] << (53 - n))) & 0x1fffffffffffffL; +#endif + r[38] = a[38] >> n; +} + +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_4096_div_word_39(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 53 bits from d1 and top 10 bits from d0. */ + d = (d1 << 10) | (d0 >> 43); + r = d / dv; + d -= r * dv; + /* Up to 11 bits in r */ + /* Next 10 bits from d0. */ + r <<= 10; + d <<= 10; + d |= (d0 >> 33) & ((1 << 10) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 21 bits in r */ + /* Next 10 bits from d0. */ + r <<= 10; + d <<= 10; + d |= (d0 >> 23) & ((1 << 10) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 31 bits in r */ + /* Next 10 bits from d0. */ + r <<= 10; + d <<= 10; + d |= (d0 >> 13) & ((1 << 10) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 41 bits in r */ + /* Next 10 bits from d0. */ + r <<= 10; + d <<= 10; + d |= (d0 >> 3) & ((1 << 10) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 51 bits in r */ + /* Remaining 3 bits from d0. */ + r <<= 3; + d <<= 3; + d |= d0 & ((1 << 3) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* 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_4096_div_39(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[78 + 1], t2d[39 + 1], sdd[39 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* sd; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 39 + 3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + (void)m; + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 78 + 1; + sd = t2 + 39 + 1; +#else + t1 = t1d; + t2 = t2d; + sd = sdd; +#endif + + sp_4096_mul_d_39(sd, d, 1L << 19); + sp_4096_mul_d_78(t1, a, 1L << 19); + dv = sd[38]; + for (i=39; i>=0; i--) { + t1[39 + i] += t1[39 + i - 1] >> 53; + t1[39 + i - 1] &= 0x1fffffffffffffL; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[39 + i]; + d1 <<= 53; + d1 += t1[39 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_4096_div_word_39(t1[39 + i], t1[39 + i - 1], dv); +#endif + + sp_4096_mul_d_39(t2, sd, r1); + (void)sp_4096_sub_39(&t1[i], &t1[i], t2); + t1[39 + i] -= t2[39]; + t1[39 + i] += t1[39 + i - 1] >> 53; + t1[39 + i - 1] &= 0x1fffffffffffffL; + r1 = (((-t1[39 + i]) << 53) - t1[39 + i - 1]) / dv; + r1 -= t1[39 + i]; + sp_4096_mul_d_39(t2, sd, r1); + (void)sp_4096_add_39(&t1[i], &t1[i], t2); + t1[39 + i] += t1[39 + i - 1] >> 53; + t1[39 + i - 1] &= 0x1fffffffffffffL; + } + t1[39 - 1] += t1[39 - 2] >> 53; + t1[39 - 2] &= 0x1fffffffffffffL; + r1 = t1[39 - 1] / dv; + + sp_4096_mul_d_39(t2, sd, r1); + sp_4096_sub_39(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 39U); + for (i=0; i<37; i++) { + r[i+1] += r[i] >> 53; + r[i] &= 0x1fffffffffffffL; + } + sp_4096_cond_add_39(r, r, sd, 0 - ((r[38] < 0) ? + (sp_digit)1 : (sp_digit)0)); + + sp_4096_norm_39(r); + sp_4096_rshift_39(r, r, 19); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_4096_mod_39(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_39(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_4096_mod_exp_39(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, + const 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 * 39 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3U * 39U * 2U); + + norm = t[0] = td; + t[1] = &td[39 * 2]; + t[2] = &td[2 * 39 * 2]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_39(norm, m); + + if (reduceA != 0) { + err = sp_4096_mod_39(t[1], a, m); + } + else { + XMEMCPY(t[1], a, sizeof(sp_digit) * 39U); + } + } + if (err == MP_OKAY) { + sp_4096_mul_39(t[1], t[1], norm); + err = sp_4096_mod_39(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 53; + c = bits % 53; + n = e[i--] << (53 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) { + break; + } + + n = e[i--]; + c = 53; + } + + y = (n >> 52) & 1; + n <<= 1; + + sp_4096_mont_mul_39(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]) * 39 * 2); + sp_4096_mont_sqr_39(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]) * 39 * 2); + } + + sp_4096_mont_reduce_39(t[0], m, mp); + n = sp_4096_cmp_39(t[0], m); + sp_4096_cond_sub_39(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 39 * 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][78]; +#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 * 39 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t[0] = td; + t[1] = &td[39 * 2]; + t[2] = &td[2 * 39 * 2]; +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_39(norm, m); + + if (reduceA != 0) { + err = sp_4096_mod_39(t[1], a, m); + if (err == MP_OKAY) { + sp_4096_mul_39(t[1], t[1], norm); + err = sp_4096_mod_39(t[1], t[1], m); + } + } + else { + sp_4096_mul_39(t[1], a, norm); + err = sp_4096_mod_39(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 53; + c = bits % 53; + n = e[i--] << (53 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) { + break; + } + + n = e[i--]; + c = 53; + } + + y = (n >> 52) & 1; + n <<= 1; + + sp_4096_mont_mul_39(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_4096_mont_sqr_39(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_4096_mont_reduce_39(t[0], m, mp); + n = sp_4096_cmp_39(t[0], m); + sp_4096_cond_sub_39(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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][78]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[78]; + 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 * 78, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 78; +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_39(norm, m); + + if (reduceA != 0) { + err = sp_4096_mod_39(t[1], a, m); + if (err == MP_OKAY) { + sp_4096_mul_39(t[1], t[1], norm); + err = sp_4096_mod_39(t[1], t[1], m); + } + } + else { + sp_4096_mul_39(t[1], a, norm); + err = sp_4096_mod_39(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_39(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_39(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_39(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_39(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_39(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_39(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_39(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_39(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_39(t[10], t[ 5], m, mp); + sp_4096_mont_mul_39(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_39(t[12], t[ 6], m, mp); + sp_4096_mont_mul_39(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_39(t[14], t[ 7], m, mp); + sp_4096_mont_mul_39(t[15], t[ 8], t[ 7], m, mp); + sp_4096_mont_sqr_39(t[16], t[ 8], m, mp); + sp_4096_mont_mul_39(t[17], t[ 9], t[ 8], m, mp); + sp_4096_mont_sqr_39(t[18], t[ 9], m, mp); + sp_4096_mont_mul_39(t[19], t[10], t[ 9], m, mp); + sp_4096_mont_sqr_39(t[20], t[10], m, mp); + sp_4096_mont_mul_39(t[21], t[11], t[10], m, mp); + sp_4096_mont_sqr_39(t[22], t[11], m, mp); + sp_4096_mont_mul_39(t[23], t[12], t[11], m, mp); + sp_4096_mont_sqr_39(t[24], t[12], m, mp); + sp_4096_mont_mul_39(t[25], t[13], t[12], m, mp); + sp_4096_mont_sqr_39(t[26], t[13], m, mp); + sp_4096_mont_mul_39(t[27], t[14], t[13], m, mp); + sp_4096_mont_sqr_39(t[28], t[14], m, mp); + sp_4096_mont_mul_39(t[29], t[15], t[14], m, mp); + sp_4096_mont_sqr_39(t[30], t[15], m, mp); + sp_4096_mont_mul_39(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 52) / 53) - 1; + c = bits % 53; + if (c == 0) { + c = 53; + } + if (i < 39) { + n = e[i--] << (64 - c); + } + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (11 - c); + c += 53; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (11 - c); + c += 53; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + + sp_4096_mont_sqr_39(rt, rt, m, mp); + sp_4096_mont_sqr_39(rt, rt, m, mp); + sp_4096_mont_sqr_39(rt, rt, m, mp); + sp_4096_mont_sqr_39(rt, rt, m, mp); + sp_4096_mont_sqr_39(rt, rt, m, mp); + + sp_4096_mont_mul_39(rt, rt, t[y], m, mp); + } + + sp_4096_mont_reduce_39(rt, m, mp); + n = sp_4096_cmp_39(rt, m); + sp_4096_cond_sub_39(rt, rt, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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 /* WOLFSSL_HAVE_SP_RSA && !SP_RSA_PRIVATE_EXP_D */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 4096 bits, just need to subtract. + * + * r A single precision number. + * m A single precision number. + */ +static void sp_4096_mont_norm_78(sp_digit* r, const sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<77; i++) { + r[i] = 0x1fffffffffffffL; + } +#else + int i; + + for (i = 0; i < 72; i += 8) { + r[i + 0] = 0x1fffffffffffffL; + r[i + 1] = 0x1fffffffffffffL; + r[i + 2] = 0x1fffffffffffffL; + r[i + 3] = 0x1fffffffffffffL; + r[i + 4] = 0x1fffffffffffffL; + r[i + 5] = 0x1fffffffffffffL; + r[i + 6] = 0x1fffffffffffffL; + r[i + 7] = 0x1fffffffffffffL; + } + r[72] = 0x1fffffffffffffL; + r[73] = 0x1fffffffffffffL; + r[74] = 0x1fffffffffffffL; + r[75] = 0x1fffffffffffffL; + r[76] = 0x1fffffffffffffL; +#endif + r[77] = 0x7fffL; + + /* r = (2^n - 1) mod n */ + (void)sp_4096_sub_78(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_4096_cmp_78(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=77; i>=0; i--) { + r |= (a[i] - b[i]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + int i; + + r |= (a[77] - b[77]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[76] - b[76]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[75] - b[75]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[74] - b[74]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[73] - b[73]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[72] - b[72]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + for (i = 64; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 6] - b[i + 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 5] - b[i + 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 4] - b[i + 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 3] - b[i + 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 2] - b[i + 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 1] - b[i + 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[i + 0] - b[i + 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#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_4096_cond_sub_78(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 < 78; i++) { + r[i] = a[i] - (b[i] & m); + } +#else + int i; + + for (i = 0; i < 72; 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[72] = a[72] - (b[72] & m); + r[73] = a[73] - (b[73] & m); + r[74] = a[74] - (b[74] & m); + r[75] = a[75] - (b[75] & m); + r[76] = a[76] - (b[76] & m); + r[77] = a[77] - (b[77] & 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. + */ +SP_NOINLINE static void sp_4096_mul_add_78(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 < 78; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1fffffffffffffL; + t >>= 53; + } + r[78] += t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1fffffffffffffL); + for (i = 0; i < 72; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (sp_digit)((t[0] >> 53) + (t[1] & 0x1fffffffffffffL)); + t[2] = tb * a[i+2]; + r[i+2] += (sp_digit)((t[1] >> 53) + (t[2] & 0x1fffffffffffffL)); + t[3] = tb * a[i+3]; + r[i+3] += (sp_digit)((t[2] >> 53) + (t[3] & 0x1fffffffffffffL)); + t[4] = tb * a[i+4]; + r[i+4] += (sp_digit)((t[3] >> 53) + (t[4] & 0x1fffffffffffffL)); + t[5] = tb * a[i+5]; + r[i+5] += (sp_digit)((t[4] >> 53) + (t[5] & 0x1fffffffffffffL)); + t[6] = tb * a[i+6]; + r[i+6] += (sp_digit)((t[5] >> 53) + (t[6] & 0x1fffffffffffffL)); + t[7] = tb * a[i+7]; + r[i+7] += (sp_digit)((t[6] >> 53) + (t[7] & 0x1fffffffffffffL)); + t[0] = tb * a[i+8]; + r[i+8] += (sp_digit)((t[7] >> 53) + (t[0] & 0x1fffffffffffffL)); + } + t[1] = tb * a[73]; r[73] += (sp_digit)((t[0] >> 53) + (t[1] & 0x1fffffffffffffL)); + t[2] = tb * a[74]; r[74] += (sp_digit)((t[1] >> 53) + (t[2] & 0x1fffffffffffffL)); + t[3] = tb * a[75]; r[75] += (sp_digit)((t[2] >> 53) + (t[3] & 0x1fffffffffffffL)); + t[4] = tb * a[76]; r[76] += (sp_digit)((t[3] >> 53) + (t[4] & 0x1fffffffffffffL)); + t[5] = tb * a[77]; r[77] += (sp_digit)((t[4] >> 53) + (t[5] & 0x1fffffffffffffL)); + r[78] += (sp_digit)(t[5] >> 53); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 53. + * + * a Array of sp_digit to normalize. + */ +static void sp_4096_norm_78(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 77; i++) { + a[i+1] += a[i] >> 53; + a[i] &= 0x1fffffffffffffL; + } +#else + int i; + for (i = 0; i < 72; i += 8) { + a[i+1] += a[i+0] >> 53; a[i+0] &= 0x1fffffffffffffL; + a[i+2] += a[i+1] >> 53; a[i+1] &= 0x1fffffffffffffL; + a[i+3] += a[i+2] >> 53; a[i+2] &= 0x1fffffffffffffL; + a[i+4] += a[i+3] >> 53; a[i+3] &= 0x1fffffffffffffL; + a[i+5] += a[i+4] >> 53; a[i+4] &= 0x1fffffffffffffL; + a[i+6] += a[i+5] >> 53; a[i+5] &= 0x1fffffffffffffL; + a[i+7] += a[i+6] >> 53; a[i+6] &= 0x1fffffffffffffL; + a[i+8] += a[i+7] >> 53; a[i+7] &= 0x1fffffffffffffL; + a[i+9] += a[i+8] >> 53; a[i+8] &= 0x1fffffffffffffL; + } + a[72+1] += a[72] >> 53; + a[72] &= 0x1fffffffffffffL; + a[73+1] += a[73] >> 53; + a[73] &= 0x1fffffffffffffL; + a[74+1] += a[74] >> 53; + a[74] &= 0x1fffffffffffffL; + a[75+1] += a[75] >> 53; + a[75] &= 0x1fffffffffffffL; + a[76+1] += a[76] >> 53; + a[76] &= 0x1fffffffffffffL; +#endif +} + +/* Shift the result in the high 4096 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_4096_mont_shift_78(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int128_t n = a[77] >> 15; + n += ((int128_t)a[78]) << 38; + + for (i = 0; i < 77; i++) { + r[i] = n & 0x1fffffffffffffL; + n >>= 53; + n += ((int128_t)a[79 + i]) << 38; + } + r[77] = (sp_digit)n; +#else + int i; + int128_t n = a[77] >> 15; + n += ((int128_t)a[78]) << 38; + for (i = 0; i < 72; i += 8) { + r[i + 0] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 79]) << 38; + r[i + 1] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 80]) << 38; + r[i + 2] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 81]) << 38; + r[i + 3] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 82]) << 38; + r[i + 4] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 83]) << 38; + r[i + 5] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 84]) << 38; + r[i + 6] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 85]) << 38; + r[i + 7] = n & 0x1fffffffffffffL; + n >>= 53; n += ((int128_t)a[i + 86]) << 38; + } + r[72] = n & 0x1fffffffffffffL; n >>= 53; n += ((int128_t)a[151]) << 38; + r[73] = n & 0x1fffffffffffffL; n >>= 53; n += ((int128_t)a[152]) << 38; + r[74] = n & 0x1fffffffffffffL; n >>= 53; n += ((int128_t)a[153]) << 38; + r[75] = n & 0x1fffffffffffffL; n >>= 53; n += ((int128_t)a[154]) << 38; + r[76] = n & 0x1fffffffffffffL; n >>= 53; n += ((int128_t)a[155]) << 38; + r[77] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[78], 0, sizeof(*r) * 78U); +} + +/* Reduce the number back to 4096 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_4096_mont_reduce_78(sp_digit* a, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_4096_norm_78(a + 78); + +#ifdef WOLFSSL_SP_DH + if (mp != 1) { + for (i=0; i<77; i++) { + mu = (a[i] * mp) & 0x1fffffffffffffL; + sp_4096_mul_add_78(a+i, m, mu); + a[i+1] += a[i] >> 53; + } + mu = (a[i] * mp) & 0x7fffL; + sp_4096_mul_add_78(a+i, m, mu); + a[i+1] += a[i] >> 53; + a[i] &= 0x1fffffffffffffL; + } + else { + for (i=0; i<77; i++) { + mu = a[i] & 0x1fffffffffffffL; + sp_4096_mul_add_78(a+i, m, mu); + a[i+1] += a[i] >> 53; + } + mu = a[i] & 0x7fffL; + sp_4096_mul_add_78(a+i, m, mu); + a[i+1] += a[i] >> 53; + a[i] &= 0x1fffffffffffffL; + } +#else + for (i=0; i<77; i++) { + mu = (a[i] * mp) & 0x1fffffffffffffL; + sp_4096_mul_add_78(a+i, m, mu); + a[i+1] += a[i] >> 53; + } + mu = (a[i] * mp) & 0x7fffL; + sp_4096_mul_add_78(a+i, m, mu); + a[i+1] += a[i] >> 53; + a[i] &= 0x1fffffffffffffL; +#endif + + sp_4096_mont_shift_78(a, a); + sp_4096_cond_sub_78(a, a, m, 0 - (((a[77] >> 15) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_4096_norm_78(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_4096_mont_mul_78(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_4096_mul_78(r, a, b); + sp_4096_mont_reduce_78(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_4096_mont_sqr_78(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_4096_sqr_78(r, a); + sp_4096_mont_reduce_78(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. + */ +SP_NOINLINE static void sp_4096_mul_d_156(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 156; i++) { + t += tb * a[i]; + r[i] = t & 0x1fffffffffffffL; + t >>= 53; + } + r[156] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1fffffffffffffL; + for (i = 0; i < 152; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 53) + (t[1] & 0x1fffffffffffffL); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 53) + (t[2] & 0x1fffffffffffffL); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 53) + (t[3] & 0x1fffffffffffffL); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 53) + (t[4] & 0x1fffffffffffffL); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 53) + (t[5] & 0x1fffffffffffffL); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 53) + (t[6] & 0x1fffffffffffffL); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 53) + (t[7] & 0x1fffffffffffffL); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 53) + (t[0] & 0x1fffffffffffffL); + } + t[1] = tb * a[153]; + r[153] = (sp_digit)(t[0] >> 53) + (t[1] & 0x1fffffffffffffL); + t[2] = tb * a[154]; + r[154] = (sp_digit)(t[1] >> 53) + (t[2] & 0x1fffffffffffffL); + t[3] = tb * a[155]; + r[155] = (sp_digit)(t[2] >> 53) + (t[3] & 0x1fffffffffffffL); + r[156] = (sp_digit)(t[3] >> 53); +#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_4096_cond_add_78(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 < 78; i++) { + r[i] = a[i] + (b[i] & m); + } +#else + int i; + + for (i = 0; i < 72; 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[72] = a[72] + (b[72] & m); + r[73] = a[73] + (b[73] & m); + r[74] = a[74] + (b[74] & m); + r[75] = a[75] + (b[75] & m); + r[76] = a[76] + (b[76] & m); + r[77] = a[77] + (b[77] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_4096_sub_78(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 78; i++) { + r[i] = a[i] - b[i]; + } + + return 0; +} + +#endif +#ifdef WOLFSSL_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. + */ +SP_NOINLINE static int sp_4096_add_78(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 78; i++) { + r[i] = a[i] + b[i]; + } + + return 0; +} +#endif +SP_NOINLINE static void sp_4096_rshift_78(sp_digit* r, sp_digit* a, byte n) +{ + int i; + +#ifdef WOLFSSL_SP_SMALL + for (i=0; i<77; i++) { + r[i] = ((a[i] >> n) | (a[i + 1] << (53 - n))) & 0x1fffffffffffffL; + } +#else + for (i=0; i<72; i += 8) { + r[i+0] = ((a[i+0] >> n) | (a[i+1] << (53 - n))) & 0x1fffffffffffffL; + r[i+1] = ((a[i+1] >> n) | (a[i+2] << (53 - n))) & 0x1fffffffffffffL; + r[i+2] = ((a[i+2] >> n) | (a[i+3] << (53 - n))) & 0x1fffffffffffffL; + r[i+3] = ((a[i+3] >> n) | (a[i+4] << (53 - n))) & 0x1fffffffffffffL; + r[i+4] = ((a[i+4] >> n) | (a[i+5] << (53 - n))) & 0x1fffffffffffffL; + r[i+5] = ((a[i+5] >> n) | (a[i+6] << (53 - n))) & 0x1fffffffffffffL; + r[i+6] = ((a[i+6] >> n) | (a[i+7] << (53 - n))) & 0x1fffffffffffffL; + r[i+7] = ((a[i+7] >> n) | (a[i+8] << (53 - n))) & 0x1fffffffffffffL; + } + r[72] = ((a[72] >> n) | (a[73] << (53 - n))) & 0x1fffffffffffffL; + r[73] = ((a[73] >> n) | (a[74] << (53 - n))) & 0x1fffffffffffffL; + r[74] = ((a[74] >> n) | (a[75] << (53 - n))) & 0x1fffffffffffffL; + r[75] = ((a[75] >> n) | (a[76] << (53 - n))) & 0x1fffffffffffffL; + r[76] = ((a[76] >> n) | (a[77] << (53 - n))) & 0x1fffffffffffffL; +#endif + r[77] = a[77] >> n; +} + +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_4096_div_word_78(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 53 bits from d1 and top 10 bits from d0. */ + d = (d1 << 10) | (d0 >> 43); + r = d / dv; + d -= r * dv; + /* Up to 11 bits in r */ + /* Next 10 bits from d0. */ + r <<= 10; + d <<= 10; + d |= (d0 >> 33) & ((1 << 10) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 21 bits in r */ + /* Next 10 bits from d0. */ + r <<= 10; + d <<= 10; + d |= (d0 >> 23) & ((1 << 10) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 31 bits in r */ + /* Next 10 bits from d0. */ + r <<= 10; + d <<= 10; + d |= (d0 >> 13) & ((1 << 10) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 41 bits in r */ + /* Next 10 bits from d0. */ + r <<= 10; + d <<= 10; + d |= (d0 >> 3) & ((1 << 10) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 51 bits in r */ + /* Remaining 3 bits from d0. */ + r <<= 3; + d <<= 3; + d |= d0 & ((1 << 3) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* 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_4096_div_78(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[156 + 1], t2d[78 + 1], sdd[78 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* sd; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 78 + 3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + (void)m; + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 156 + 1; + sd = t2 + 78 + 1; +#else + t1 = t1d; + t2 = t2d; + sd = sdd; +#endif + + sp_4096_mul_d_78(sd, d, 1L << 38); + sp_4096_mul_d_156(t1, a, 1L << 38); + dv = sd[77]; + for (i=78; i>=0; i--) { + t1[78 + i] += t1[78 + i - 1] >> 53; + t1[78 + i - 1] &= 0x1fffffffffffffL; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[78 + i]; + d1 <<= 53; + d1 += t1[78 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_4096_div_word_78(t1[78 + i], t1[78 + i - 1], dv); +#endif + + sp_4096_mul_d_78(t2, sd, r1); + (void)sp_4096_sub_78(&t1[i], &t1[i], t2); + t1[78 + i] -= t2[78]; + t1[78 + i] += t1[78 + i - 1] >> 53; + t1[78 + i - 1] &= 0x1fffffffffffffL; + r1 = (((-t1[78 + i]) << 53) - t1[78 + i - 1]) / dv; + r1 -= t1[78 + i]; + sp_4096_mul_d_78(t2, sd, r1); + (void)sp_4096_add_78(&t1[i], &t1[i], t2); + t1[78 + i] += t1[78 + i - 1] >> 53; + t1[78 + i - 1] &= 0x1fffffffffffffL; + } + t1[78 - 1] += t1[78 - 2] >> 53; + t1[78 - 2] &= 0x1fffffffffffffL; + r1 = t1[78 - 1] / dv; + + sp_4096_mul_d_78(t2, sd, r1); + sp_4096_sub_78(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 78U); + for (i=0; i<76; i++) { + r[i+1] += r[i] >> 53; + r[i] &= 0x1fffffffffffffL; + } + sp_4096_cond_add_78(r, r, sd, 0 - ((r[77] < 0) ? + (sp_digit)1 : (sp_digit)0)); + + sp_4096_norm_78(r); + sp_4096_rshift_78(r, r, 38); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_4096_mod_78(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_78(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + 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_4096_mod_exp_78(sp_digit* r, const sp_digit* a, const sp_digit* e, int bits, + const 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 * 78 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3U * 78U * 2U); + + norm = t[0] = td; + t[1] = &td[78 * 2]; + t[2] = &td[2 * 78 * 2]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_78(norm, m); + + if (reduceA != 0) { + err = sp_4096_mod_78(t[1], a, m); + } + else { + XMEMCPY(t[1], a, sizeof(sp_digit) * 78U); + } + } + if (err == MP_OKAY) { + sp_4096_mul_78(t[1], t[1], norm); + err = sp_4096_mod_78(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 53; + c = bits % 53; + n = e[i--] << (53 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) { + break; + } + + n = e[i--]; + c = 53; + } + + y = (n >> 52) & 1; + n <<= 1; + + sp_4096_mont_mul_78(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]) * 78 * 2); + sp_4096_mont_sqr_78(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]) * 78 * 2); + } + + sp_4096_mont_reduce_78(t[0], m, mp); + n = sp_4096_cmp_78(t[0], m); + sp_4096_cond_sub_78(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 78 * 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][156]; +#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 * 78 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t[0] = td; + t[1] = &td[78 * 2]; + t[2] = &td[2 * 78 * 2]; +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_78(norm, m); + + if (reduceA != 0) { + err = sp_4096_mod_78(t[1], a, m); + if (err == MP_OKAY) { + sp_4096_mul_78(t[1], t[1], norm); + err = sp_4096_mod_78(t[1], t[1], m); + } + } + else { + sp_4096_mul_78(t[1], a, norm); + err = sp_4096_mod_78(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 53; + c = bits % 53; + n = e[i--] << (53 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) { + break; + } + + n = e[i--]; + c = 53; + } + + y = (n >> 52) & 1; + n <<= 1; + + sp_4096_mont_mul_78(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_4096_mont_sqr_78(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_4096_mont_reduce_78(t[0], m, mp); + n = sp_4096_cmp_78(t[0], m); + sp_4096_cond_sub_78(t[0], t[0], m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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][156]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[156]; + 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 * 156, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 156; +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_78(norm, m); + + if (reduceA != 0) { + err = sp_4096_mod_78(t[1], a, m); + if (err == MP_OKAY) { + sp_4096_mul_78(t[1], t[1], norm); + err = sp_4096_mod_78(t[1], t[1], m); + } + } + else { + sp_4096_mul_78(t[1], a, norm); + err = sp_4096_mod_78(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_78(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_78(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_78(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_78(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_78(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_78(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_78(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_78(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_78(t[10], t[ 5], m, mp); + sp_4096_mont_mul_78(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_78(t[12], t[ 6], m, mp); + sp_4096_mont_mul_78(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_78(t[14], t[ 7], m, mp); + sp_4096_mont_mul_78(t[15], t[ 8], t[ 7], m, mp); + sp_4096_mont_sqr_78(t[16], t[ 8], m, mp); + sp_4096_mont_mul_78(t[17], t[ 9], t[ 8], m, mp); + sp_4096_mont_sqr_78(t[18], t[ 9], m, mp); + sp_4096_mont_mul_78(t[19], t[10], t[ 9], m, mp); + sp_4096_mont_sqr_78(t[20], t[10], m, mp); + sp_4096_mont_mul_78(t[21], t[11], t[10], m, mp); + sp_4096_mont_sqr_78(t[22], t[11], m, mp); + sp_4096_mont_mul_78(t[23], t[12], t[11], m, mp); + sp_4096_mont_sqr_78(t[24], t[12], m, mp); + sp_4096_mont_mul_78(t[25], t[13], t[12], m, mp); + sp_4096_mont_sqr_78(t[26], t[13], m, mp); + sp_4096_mont_mul_78(t[27], t[14], t[13], m, mp); + sp_4096_mont_sqr_78(t[28], t[14], m, mp); + sp_4096_mont_mul_78(t[29], t[15], t[14], m, mp); + sp_4096_mont_sqr_78(t[30], t[15], m, mp); + sp_4096_mont_mul_78(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 52) / 53) - 1; + c = bits % 53; + if (c == 0) { + c = 53; + } + if (i < 78) { + n = e[i--] << (64 - c); + } + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (11 - c); + c += 53; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (11 - c); + c += 53; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + + sp_4096_mont_sqr_78(rt, rt, m, mp); + sp_4096_mont_sqr_78(rt, rt, m, mp); + sp_4096_mont_sqr_78(rt, rt, m, mp); + sp_4096_mont_sqr_78(rt, rt, m, mp); + sp_4096_mont_sqr_78(rt, rt, m, mp); + + sp_4096_mont_mul_78(rt, rt, t[y], m, mp); + } + + sp_4096_mont_reduce_78(rt, m, mp); + n = sp_4096_cmp_78(rt, m); + sp_4096_cond_sub_78(rt, rt, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)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 /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ + /* 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 512 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_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1] = {0}; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 512U) { + err = MP_TO_E; + } + + if (err == MP_OKAY) { + if (mp_count_bits(em) > 53) { + err = MP_READ_E; + } + if (inLen > 512U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 78 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 78 * 2; + m = r + 78 * 2; + norm = r; + + sp_4096_from_bin(a, 78, in, inLen); +#if DIGIT_BIT >= 53 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)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_4096_from_mp(m, 78, mm); + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_78(norm, m); + } + if (err == MP_OKAY) { + sp_4096_mul_78(a, a, norm); + err = sp_4096_mod_78(a, a, m); + } + if (err == MP_OKAY) { + for (i=52; i>=0; i--) { + if ((e[0] >> i) != 0) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 78 * 2); + for (i--; i>=0; i--) { + sp_4096_mont_sqr_78(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) { + sp_4096_mont_mul_78(r, r, a, m, mp); + } + } + sp_4096_mont_reduce_78(r, m, mp); + mp = sp_4096_cmp_78(r, m); + sp_4096_cond_sub_78(r, r, m, ((mp < 0) ? + (sp_digit)1 : (sp_digit)0)- 1); + + sp_4096_to_bin(r, out); + *outLen = 512; + } + + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit ad[156], md[78], rd[156]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit e[1] = {0}; + int err = MP_OKAY; + + if (*outLen < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(em) > 53) { + err = MP_READ_E; + } + if (inLen > 512U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 78 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + a = d; + r = a + 78 * 2; + m = r + 78 * 2; + } +#else + a = ad; + m = md; + r = rd; +#endif + + if (err == MP_OKAY) { + sp_4096_from_bin(a, 78, in, inLen); +#if DIGIT_BIT >= 53 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)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_4096_from_mp(m, 78, mm); + + if (e[0] == 0x3) { + sp_4096_sqr_78(r, a); + err = sp_4096_mod_78(r, r, m); + if (err == MP_OKAY) { + sp_4096_mul_78(r, a, r); + err = sp_4096_mod_78(r, r, m); + } + } + else { + sp_digit* norm = r; + int i; + sp_digit mp; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_78(norm, m); + + sp_4096_mul_78(a, a, norm); + err = sp_4096_mod_78(a, a, m); + + if (err == MP_OKAY) { + for (i=52; i>=0; i--) { + if ((e[0] >> i) != 0) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 156U); + for (i--; i>=0; i--) { + sp_4096_mont_sqr_78(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) { + sp_4096_mont_mul_78(r, r, a, m, mp); + } + } + sp_4096_mont_reduce_78(r, m, mp); + mp = sp_4096_cmp_78(r, m); + sp_4096_cond_sub_78(r, r, m, ((mp < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM) +#endif /* !SP_RSA_PRIVATE_EXP_D && !RSA_LOW_MEM */ +/* 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 512 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_4096(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(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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 < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 4096) { + err = MP_READ_E; + } + if (inLen > 512) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 78 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 78; + m = a + 156; + r = a; + + sp_4096_from_bin(a, 78, in, inLen); + sp_4096_from_mp(d, 78, dm); + sp_4096_from_mp(m, 78, mm); + err = sp_4096_mod_exp_78(r, a, d, 4096, m, 0); + } + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 78); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[156], d[78], m[78]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 4096) { + err = MP_READ_E; + } + if (inLen > 512U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_4096_from_bin(a, 78, in, inLen); + sp_4096_from_mp(d, 78, dm); + sp_4096_from_mp(m, 78, mm); + err = sp_4096_mod_exp_78(r, a, d, 4096, m, 0); + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + + XMEMSET(d, 0, sizeof(sp_digit) * 78); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#else +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (inLen > 512) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 39 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = t; + p = a + 78 * 2; + q = p + 39; + qi = dq = dp = q + 39; + tmpa = qi + 39; + tmpb = tmpa + 78; + + r = t + 78; + + sp_4096_from_bin(a, 78, in, inLen); + sp_4096_from_mp(p, 39, pm); + sp_4096_from_mp(q, 39, qm); + sp_4096_from_mp(dp, 39, dpm); + err = sp_4096_mod_exp_39(tmpa, a, dp, 2048, p, 1); + } + if (err == MP_OKAY) { + sp_4096_from_mp(dq, 39, dqm); + err = sp_4096_mod_exp_39(tmpb, a, dq, 2048, q, 1); + } + if (err == MP_OKAY) { + (void)sp_4096_sub_39(tmpa, tmpa, tmpb); + sp_4096_cond_add_39(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[38] >> 63)); + sp_4096_cond_add_39(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[38] >> 63)); + + sp_4096_from_mp(qi, 39, qim); + sp_4096_mul_39(tmpa, tmpa, qi); + err = sp_4096_mod_39(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_4096_mul_39(tmpa, q, tmpa); + (void)sp_4096_add_78(r, tmpb, tmpa); + sp_4096_norm_78(r); + + sp_4096_to_bin(r, out); + *outLen = 512; + } + + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 39 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[78 * 2]; + sp_digit p[39], q[39], dp[39], dq[39], qi[39]; + sp_digit tmpa[78], tmpb[78]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (inLen > 512U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_4096_from_bin(a, 78, in, inLen); + sp_4096_from_mp(p, 39, pm); + sp_4096_from_mp(q, 39, qm); + sp_4096_from_mp(dp, 39, dpm); + sp_4096_from_mp(dq, 39, dqm); + sp_4096_from_mp(qi, 39, qim); + + err = sp_4096_mod_exp_39(tmpa, a, dp, 2048, p, 1); + } + if (err == MP_OKAY) { + err = sp_4096_mod_exp_39(tmpb, a, dq, 2048, q, 1); + } + + if (err == MP_OKAY) { + (void)sp_4096_sub_39(tmpa, tmpa, tmpb); + sp_4096_cond_add_39(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[38] >> 63)); + sp_4096_cond_add_39(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[38] >> 63)); + sp_4096_mul_39(tmpa, tmpa, qi); + err = sp_4096_mod_39(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_4096_mul_39(tmpa, tmpa, q); + (void)sp_4096_add_78(r, tmpb, tmpa); + sp_4096_norm_78(r); + + sp_4096_to_bin(r, out); + *outLen = 512; + } + + 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 || RSA_LOW_MEM */ +} + +#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_4096_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 53 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 78); + r->used = 78; + mp_clamp(r); +#elif DIGIT_BIT < 53 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 78; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 53) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 53 - s; + } + r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 78; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 53 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 53 - s; + } + else { + s += 53; + } + } + r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 78 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + b = d; + e = b + 78 * 2; + m = e + 78; + r = b; + + sp_4096_from_mp(b, 78, base); + sp_4096_from_mp(e, 78, exp); + sp_4096_from_mp(m, 78, mod); + + err = sp_4096_mod_exp_78(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + err = sp_4096_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 78U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[156], ed[78], md[78]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 78 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 78 * 2; + m = e + 78; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 78, base); + sp_4096_from_mp(e, 78, exp); + sp_4096_from_mp(m, 78, mod); + + err = sp_4096_mod_exp_78(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_4096_to_mp(r, res); + } + + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 78U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 78U); +#endif + + return err; +#endif +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_4096 +SP_NOINLINE static void sp_4096_lshift_78(sp_digit* r, sp_digit* a, byte n) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + r[78] = a[77] >> (53 - n); + for (i=77; i>0; i--) { + r[i] = ((a[i] << n) | (a[i-1] >> (53 - n))) & 0x1fffffffffffffL; + } +#else + sp_int_digit s, t; + + s = (sp_int_digit)a[77]; + r[78] = s >> (53U - n); + s = (sp_int_digit)(a[77]); t = (sp_int_digit)(a[76]); + r[77] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[76]); t = (sp_int_digit)(a[75]); + r[76] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[75]); t = (sp_int_digit)(a[74]); + r[75] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[74]); t = (sp_int_digit)(a[73]); + r[74] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[73]); t = (sp_int_digit)(a[72]); + r[73] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[72]); t = (sp_int_digit)(a[71]); + r[72] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]); + r[71] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]); + r[70] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]); + r[69] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]); + r[68] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]); + r[67] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]); + r[66] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]); + r[65] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]); + r[64] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]); + r[63] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]); + r[62] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]); + r[61] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]); + r[60] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]); + r[59] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]); + r[58] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]); + r[57] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]); + r[56] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]); + r[55] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]); + r[54] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]); + r[53] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]); + r[52] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]); + r[51] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]); + r[50] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]); + r[49] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]); + r[48] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]); + r[47] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]); + r[46] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]); + r[45] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]); + r[44] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]); + r[43] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]); + r[42] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]); + r[41] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]); + r[40] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]); + r[39] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]); + r[38] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]); + r[37] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]); + r[36] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]); + r[35] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]); + r[34] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]); + r[33] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]); + r[32] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]); + r[31] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]); + r[30] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]); + r[29] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]); + r[28] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]); + r[27] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]); + r[26] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]); + r[25] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]); + r[24] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]); + r[23] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]); + r[22] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]); + r[21] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]); + r[20] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]); + r[19] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]); + r[18] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]); + r[17] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]); + r[16] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]); + r[15] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]); + r[14] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]); + r[13] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]); + r[12] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]); + r[11] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]); + r[10] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]); + r[9] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]); + r[8] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]); + r[7] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]); + r[6] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]); + r[5] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]); + r[4] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]); + r[3] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]); + r[2] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; + s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]); + r[1] = ((s << n) | (t >> (53U - n))) & 0x1fffffffffffffUL; +#endif + r[0] = (a[0] << n) & 0x1fffffffffffffL; +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_4096_mod_exp_2_78(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[156]; + sp_digit td[79]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 235, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 156; + XMEMSET(td, 0, sizeof(sp_digit) * 235); +#else + norm = nd; + tmp = td; + XMEMSET(td, 0, sizeof(td)); +#endif + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_78(norm, m); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 52) / 53) - 1; + c = bits % 53; + if (c == 0) { + c = 53; + } + if (i < 78) { + n = e[i--] << (64 - c); + } + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (11 - c); + c += 53; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + sp_4096_lshift_78(r, norm, y); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (11 - c); + c += 53; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + + sp_4096_mont_sqr_78(r, r, m, mp); + sp_4096_mont_sqr_78(r, r, m, mp); + sp_4096_mont_sqr_78(r, r, m, mp); + sp_4096_mont_sqr_78(r, r, m, mp); + sp_4096_mont_sqr_78(r, r, m, mp); + + sp_4096_lshift_78(r, r, y); + sp_4096_mul_d_78(tmp, norm, (r[78] << 38) + (r[77] >> 15)); + r[78] = 0; + r[77] &= 0x7fffL; + (void)sp_4096_add_78(r, r, tmp); + sp_4096_norm_78(r); + o = sp_4096_cmp_78(r, m); + sp_4096_cond_sub_78(r, r, m, ((o < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + + sp_4096_mont_reduce_78(r, m, mp); + n = sp_4096_cmp_78(r, m); + sp_4096_cond_sub_78(r, r, m, ((n < 0) ? + (sp_digit)1 : (sp_digit)0) - 1); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} + +#endif /* HAVE_FFDHE_4096 */ + +/* 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 512 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returns 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_4096(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) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 512) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 78 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) { + err = MEMORY_E; + } + } + + if (err == MP_OKAY) { + b = d; + e = b + 78 * 2; + m = e + 78; + r = b; + + sp_4096_from_mp(b, 78, base); + sp_4096_from_bin(e, 78, exp, expLen); + sp_4096_from_mp(m, 78, mod); + + #ifdef HAVE_FFDHE_4096 + if (base->used == 1 && base->dp[0] == 2 && + ((m[77] << 17) | (m[76] >> 36)) == 0xffffffffL) { + err = sp_4096_mod_exp_2_78(r, e, expLen * 8, m); + } + else + #endif + err = sp_4096_mod_exp_78(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + for (i=0; i<512 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 78U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[156], ed[78], md[78]; +#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) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 512U) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 78 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 78 * 2; + m = e + 78; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 78, base); + sp_4096_from_bin(e, 78, exp, expLen); + sp_4096_from_mp(m, 78, mod); + + #ifdef HAVE_FFDHE_4096 + if (base->used == 1 && base->dp[0] == 2U && + ((m[77] << 17) | (m[76] >> 36)) == 0xffffffffL) { + err = sp_4096_mod_exp_2_78(r, e, expLen * 8U, m); + } + else { + #endif + err = sp_4096_mod_exp_78(r, b, e, expLen * 8U, m, 0); + #ifdef HAVE_FFDHE_4096 + } + #endif + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + for (i=0; i<512U && out[i] == 0U; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 78U); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 78U); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* WOLFSSL_SP_4096 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point_256 { + sp_digit x[2 * 5]; + sp_digit y[2 * 5]; + sp_digit z[2 * 5]; + int infinity; +} sp_point_256; + +/* The modulus (prime) of the curve P256. */ +static const sp_digit p256_mod[5] = { + 0xfffffffffffffL,0x00fffffffffffL,0x0000000000000L,0x0001000000000L, + 0x0ffffffff0000L +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static const sp_digit p256_norm_mod[5] = { + 0x0000000000001L,0xff00000000000L,0xfffffffffffffL,0xfffefffffffffL, + 0x000000000ffffL +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static const 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 const sp_digit p256_order[5] = { + 0x9cac2fc632551L,0xada7179e84f3bL,0xfffffffbce6faL,0x0000fffffffffL, + 0x0ffffffff0000L +}; +#endif +/* The order of the curve P256 minus 2. */ +static const 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 const 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 const sp_digit p256_mp_order = 0x1c8aaee00bc4fL; +#endif +/* The base point of curve P256. */ +static const sp_point_256 p256_base = { + /* X ordinate */ + { + 0x13945d898c296L,0x812deb33a0f4aL,0x3a440f277037dL,0x4247f8bce6e56L, + 0x06b17d1f2e12cL, + 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x6406837bf51f5L,0x576b315ececbbL,0xc0f9e162bce33L,0x7f9b8ee7eb4a7L, + 0x04fe342e2fe1aL, + 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x0000000000001L,0x0000000000000L,0x0000000000000L,0x0000000000000L, + 0x0000000000000L, + 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p256_b[5] = { + 0xe3c3e27d2604bL,0xb0cc53b0f63bcL,0x69886bc651d06L,0x93e7b3ebbd557L, + 0x05ac635d8aa3aL +}; +#endif + +static int sp_256_point_new_ex_5(void* heap, sp_point_256* sp, sp_point_256** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_256_point_new_5(heap, sp, p) sp_256_point_new_ex_5((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_256_point_new_5(heap, sp, p) sp_256_point_new_ex_5((heap), &(sp), &(p)) +#endif + + +static void sp_256_point_free_5(sp_point_256* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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, const sp_digit* a, const sp_digit* m) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC); + if (td == NULL) { + return MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + a32 = td + 8; +#else + t = td; + a32 = a32d; +#endif + + a32[0] = (sp_digit)(a[0]) & 0xffffffffL; + a32[1] = (sp_digit)(a[0] >> 32U); + a32[1] |= a[1] << 20U; + a32[1] &= 0xffffffffL; + a32[2] = (sp_digit)(a[1] >> 12U) & 0xffffffffL; + a32[3] = (sp_digit)(a[1] >> 44U); + a32[3] |= a[2] << 8U; + a32[3] &= 0xffffffffL; + a32[4] = (sp_digit)(a[2] >> 24U); + a32[4] |= a[3] << 28U; + a32[4] &= 0xffffffffL; + a32[5] = (sp_digit)(a[3] >> 4U) & 0xffffffffL; + a32[6] = (sp_digit)(a[3] >> 36U); + a32[6] |= a[4] << 16U; + a32[6] &= 0xffffffffL; + a32[7] = (sp_digit)(a[4] >> 16U) & 0xffffffffL; + + /* 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] >> 32U; t[0] &= 0xffffffffL; + t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; + t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; + t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; + t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; + t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; + t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; + o = t[7] >> 32U; t[7] &= 0xffffffffL; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32U; t[0] &= 0xffffffffL; + t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; + t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; + t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; + t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; + t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; + t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; + + r[0] = t[0]; + r[0] |= t[1] << 32U; + r[0] &= 0xfffffffffffffLL; + r[1] = (sp_digit)(t[1] >> 20); + r[1] |= t[2] << 12U; + r[1] |= t[3] << 44U; + r[1] &= 0xfffffffffffffLL; + r[2] = (sp_digit)(t[3] >> 8); + r[2] |= t[4] << 24U; + r[2] &= 0xfffffffffffffLL; + r[3] = (sp_digit)(t[4] >> 28); + r[3] |= t[5] << 4U; + r[3] |= t[6] << 36U; + r[3] &= 0xfffffffffffffLL; + r[4] = (sp_digit)(t[6] >> 16); + r[4] |= t[7] << 16U; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 52 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 52 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xfffffffffffffL; + s = 52U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 52U) <= (word32)DIGIT_BIT) { + s += 52U; + r[j] &= 0xfffffffffffffL; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 52) { + r[j] &= 0xfffffffffffffL; + if (j + 1 >= size) { + break; + } + s = 52 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_256. + * + * p Point of type sp_point_256 (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_5(sp_point_256* p, const 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(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always 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] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 52) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(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 != 32 && 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_256 to type ecc_point. + * + * p Point of type sp_point_256. + * 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(const sp_point_256* 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; +} + +#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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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 */ +#define sp_256_mont_reduce_order_5 sp_256_mont_reduce_5 + +/* 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 == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + r |= (a[ 4] - b[ 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 3] - b[ 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 2] - b[ 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 1] - b[ 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 0] - b[ 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); +#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_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. + */ +SP_NOINLINE 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] += (sp_digit) (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 */ +} + +/* 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 +} + +/* 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 += (word64)a[5 + i] << 4; + r[i] = n & 0xfffffffffffffL; + n >>= 52; + } + n += (word64)a[9] << 4; + r[4] = n; +#else + word64 n; + + n = a[4] >> 48; + n += (word64)a[ 5] << 4U; r[ 0] = n & 0xfffffffffffffUL; n >>= 52U; + n += (word64)a[ 6] << 4U; r[ 1] = n & 0xfffffffffffffUL; n >>= 52U; + n += (word64)a[ 7] << 4U; r[ 2] = n & 0xfffffffffffffUL; n >>= 52U; + n += (word64)a[ 8] << 4U; r[ 3] = n & 0xfffffffffffffUL; n >>= 52U; + n += (word64)a[ 9] << 4U; r[ 4] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[5], 0, sizeof(*r) * 5U); +} + +/* 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, const 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_digit)1 : (sp_digit)0)); + sp_256_norm_5(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_256_mont_mul_5(sp_digit* r, const sp_digit* a, const sp_digit* b, + const 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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_256_sqr_5(r, a); + sp_256_mont_reduce_5(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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, const sp_digit* a, int n, + const 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); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint64_t p256_mod_minus_2[4] = { + 0xfffffffffffffffdU,0x00000000ffffffffU,0x0000000000000000U, + 0xffffffff00000001U +}; +#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, const 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_minus_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* t1 = td; + sp_digit* t2 = td + 2 * 5; + sp_digit* t3 = td + 4 * 5; + /* 0x2 */ + sp_256_mont_sqr_5(t1, a, p256_mod, p256_mp_mod); + /* 0x3 */ + sp_256_mont_mul_5(t2, t1, a, p256_mod, p256_mp_mod); + /* 0xc */ + sp_256_mont_sqr_n_5(t1, t2, 2, p256_mod, p256_mp_mod); + /* 0xd */ + sp_256_mont_mul_5(t3, t1, a, p256_mod, p256_mp_mod); + /* 0xf */ + sp_256_mont_mul_5(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xf0 */ + sp_256_mont_sqr_n_5(t1, t2, 4, p256_mod, p256_mp_mod); + /* 0xfd */ + sp_256_mont_mul_5(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xff */ + sp_256_mont_mul_5(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xff00 */ + sp_256_mont_sqr_n_5(t1, t2, 8, p256_mod, p256_mp_mod); + /* 0xfffd */ + sp_256_mont_mul_5(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffff */ + sp_256_mont_mul_5(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffff0000 */ + sp_256_mont_sqr_n_5(t1, t2, 16, p256_mod, p256_mp_mod); + /* 0xfffffffd */ + sp_256_mont_mul_5(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffffffff */ + sp_256_mont_mul_5(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000000 */ + sp_256_mont_sqr_n_5(t1, t2, 32, p256_mod, p256_mp_mod); + /* 0xffffffffffffffff */ + sp_256_mont_mul_5(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000001 */ + sp_256_mont_mul_5(r, t1, a, p256_mod, p256_mp_mod); + /* 0xffffffff000000010000000000000000000000000000000000000000 */ + sp_256_mont_sqr_n_5(r, r, 160, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff */ + sp_256_mont_mul_5(r, r, t2, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */ + sp_256_mont_sqr_n_5(r, r, 32, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */ + sp_256_mont_mul_5(r, r, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_5(sp_point_256* r, const sp_point_256* 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) / 2U); + 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_digit)1 : (sp_digit)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) / 2U); + 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_digit)1 : (sp_digit)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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)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_digit)1 : (sp_digit)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, const sp_digit* a, const sp_digit* m) +{ + (void)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_digit)1 : (sp_digit)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, const sp_digit* a, const sp_digit* m) +{ + (void)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_digit)1 : (sp_digit)0)); + sp_256_norm_5(r); + (void)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_digit)1 : (sp_digit)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. + */ +SP_NOINLINE 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. + */ +SP_NOINLINE 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, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)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. + */ +SP_NOINLINE static void sp_256_rshift1_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, const sp_digit* a, const sp_digit* m) +{ + sp_256_cond_add_5(r, a, m, 0 - (a[0] & 1)); + sp_256_norm_5(r); + sp_256_rshift1_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_256* r, const sp_point_256* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*5; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_5(t1, p->z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_5(z, p->y, p->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, p->x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_5(t1, p->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, p->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, p->x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_sqr_5(x, 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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_5(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, + sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + 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) { + const sp_point_256* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)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))) != 0) { + sp_256_proj_point_dbl_5(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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 coordinates. + * + * 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_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#ifdef WOLFSSL_SP_NO_MALLOC + sp_point_256 t[3]; + sp_digit tmp[2 * 5 * 5]; +#else + sp_point_256* t; + sp_digit* tmp; +#endif + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + +#ifndef WOLFSSL_SP_NO_MALLOC + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 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; +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_256) * 3); + + /* 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_256)); + 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_256)); + } + + if (map != 0) { + sp_256_map_5(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_256)); + } + } + +#ifndef WOLFSSL_SP_NO_MALLOC + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 5 * 5); + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_256) * 3); + XFREE(t, NULL, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmp, sizeof(tmp)); + ForceZero(t, sizeof(t)); +#endif + + 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 coordinates. + * + * 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_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 t[3]; + sp_digit tmp[2 * 5 * 5]; +#else + sp_point_256* t; + sp_digit* tmp; +#endif + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point*)XMALLOC(sizeof(*t) * 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; +#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 */ + t[1].infinity = 0; + 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 != 0) { + sp_256_map_5(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_256) * 3); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmp, sizeof(tmp)); + ForceZero(t, sizeof(t)); +#endif + + return err; +} + +#else +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_256 { + sp_digit x[5]; + sp_digit y[5]; +} sp_table_entry_256; + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td[16]; + sp_point_256 rtd; + sp_digit tmpd[2 * 5 * 5]; +#endif + sp_point_256* t; + sp_point_256* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_256_point_new_5(heap, rtd, rt); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 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 */ + (void)sp_256_mod_mul_norm_5(t[1].x, g->x, p256_mod); + (void)sp_256_mod_mul_norm_5(t[1].y, g->y, p256_mod); + (void)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_256)); + 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 != 0) { + sp_256_map_5(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_256) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_256_point_free_5(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_256* p, int n, sp_digit* t) +{ + 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; + + x = p->x; + y = p->y; + z = p->z; + + /* 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); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* 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(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(b, t1, 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(t2, b, p256_mod); + sp_256_mont_sub_5(x, x, t2, 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(t1, t1, p256_mod, p256_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_256_mont_mul_5(w, w, t1, 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, t1, p256_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* 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(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(b, t1, 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(t2, b, p256_mod); + sp_256_mont_sub_5(x, x, t2, 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(t1, t1, 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, t1, p256_mod); +#endif + /* 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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_5(sp_point_256* r, const sp_point_256* p, + const sp_point_256* q, sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + 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 */ + (void)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))) != 0) { + sp_256_proj_point_dbl_5(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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 Temporary data. + */ +static void sp_256_proj_to_affine_5(sp_point_256* 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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_5(const sp_point_256* a, + sp_table_entry_256* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td, s1d, s2d; +#endif + sp_point_256* t; + sp_point_256* s1 = NULL; + sp_point_256* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_256_point_new_5(heap, td, t); + if (err == MP_OKAY) { + err = sp_256_point_new_5(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_256_point_new_5(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_256)); + /* 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)); + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_5(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)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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)); + } + } + } + + sp_256_point_free_5(s2, 0, heap); + sp_256_point_free_5(s1, 0, heap); + sp_256_point_free_5( 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 coordinates. + * + * 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_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit td[2 * 5 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_256_point_new_5(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_256_point_new_5(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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 = !y; + 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 = !y; + sp_256_proj_point_add_qz1_5(rt, rt, p, t); + } + + if (map != 0) { + sp_256_map_5(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_5(p, 0, heap); + sp_256_point_free_5(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_256_t { + sp_digit x[5]; + sp_digit y[5]; + sp_table_entry_256 table[256]; + uint32_t cnt; + int set; +} sp_cache_256_t; + +static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_256_last = -1; +static THREAD_LS_T int sp_cache_256_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_256 = 0; + static wolfSSL_Mutex sp_cache_256_lock; +#endif + +static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_256_inited == 0) { + for (i=0; ix, sp_cache_256[i].x) & + sp_256_cmp_equal_5(g->y, sp_cache_256[i].y)) { + sp_cache_256[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_256_last + 1) % FP_ENTRIES; + for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_256[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_256_last) { + least = sp_cache_256[0].cnt; + for (j=1; jx, sizeof(sp_cache_256[i].x)); + XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y)); + sp_cache_256[i].set = 1; + sp_cache_256[i].cnt = 1; + } + + *cache = &sp_cache_256[i]; + sp_cache_256_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 coordinates. + * + * 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_256* r, const sp_point_256* g, const 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_256_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_256 == 0) { + wc_InitMutex(&sp_cache_256_lock); + initCacheMutex_256 = 1; + } + if (wc_LockMutex(&sp_cache_256_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_256(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_256_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 coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[5]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_256_point_new_5(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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); + + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_5(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 coordinates. + * + * 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_256* r, const sp_digit* k, + int map, void* heap) +{ + /* No pre-computed values. */ + return sp_256_ecc_mulmod_5(r, &p256_base, k, map, heap); +} + +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const 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 const sp_table_entry_256 p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x730d418a9143cL,0xfc5fedb60179eL,0x762251075ba95L,0x55c679fb732b7L, + 0x018905f76a537L }, + { 0x25357ce95560aL,0xe4ba19e45cddfL,0xd21f3258b4ab8L,0x5d85d2e88688dL, + 0x08571ff182588L } }, + /* 2 */ + { { 0x886024147519aL,0xac26b372f0202L,0x785ebc8d0981eL,0x58e9a9d4a7caaL, + 0x0d953c50ddbdfL }, + { 0x361ccfd590f8fL,0x6b44e6c9179d6L,0x2eb64cf72e962L,0x88f37fd961102L, + 0x0863ebb7e9eb2L } }, + /* 3 */ + { { 0x6b6235cdb6485L,0xa22f0a2f97785L,0xf7e300b808f0eL,0x80a03e68d9544L, + 0x000076055b5ffL }, + { 0x4eb9b838d2010L,0xbb3243708a763L,0x42a660654014fL,0x3ee0e0e47d398L, + 0x0830877613437L } }, + /* 4 */ + { { 0x22fc516a0d2bbL,0x6c1a6234994f9L,0x7c62c8b0d5cc1L,0x667f9241cf3a5L, + 0x02f5e6961fd1bL }, + { 0x5c70bf5a01797L,0x4d609561925c1L,0x71fdb523d20b4L,0x0f7b04911b370L, + 0x0f648f9168d6fL } }, + /* 5 */ + { { 0x66847e137bbbcL,0x9e8a6a0bec9e5L,0x9d73463e43446L,0x0015b1c427617L, + 0x05abe0285133dL }, + { 0xa837cc04c7dabL,0x4c43260c0792aL,0x8e6cc37573d9fL,0x73830c9315627L, + 0x094bb725b6b6fL } }, + /* 6 */ + { { 0x9b48f720f141cL,0xcd2df5bc74bbfL,0x11045c46199b3L,0xc4efdc3f61294L, + 0x0cdd6bbcb2f7dL }, + { 0x6700beaf436fdL,0x6db99326beccaL,0x14f25226f647fL,0xe5f60c0fa7920L, + 0x0a361bebd4bdaL } }, + /* 7 */ + { { 0xa2558597c13c7L,0x5f50b7c3e128aL,0x3c09d1dc38d63L,0x292c07039aecfL, + 0x0ba12ca09c4b5L }, + { 0x08fa459f91dfdL,0x66ceea07fb9e4L,0xd780b293af43bL,0xef4b1eceb0899L, + 0x053ebb99d701fL } }, + /* 8 */ + { { 0x7ee31b0e63d34L,0x72a9e54fab4feL,0x5e7b5a4f46005L,0x4831c0493334dL, + 0x08589fb9206d5L }, + { 0x0f5cc6583553aL,0x4ae25649e5aa7L,0x0044652087909L,0x1c4fcc9045071L, + 0x0ebb0696d0254L } }, + /* 9 */ + { { 0x6ca15ac1647c5L,0x47c4cf5799461L,0x64dfbacb8127dL,0x7da3dc666aa37L, + 0x0eb2820cbd1b2L }, + { 0x6f8d86a87e008L,0x9d922378f3940L,0x0ccecb2d87dfaL,0xda1d56ed2e428L, + 0x01f28289b55a7L } }, + /* 10 */ + { { 0xaa0c03b89da99L,0x9eb8284022abbL,0x81c05e8a6f2d7L,0x4d6327847862bL, + 0x0337a4b5905e5L }, + { 0x7500d21f7794aL,0xb77d6d7f613c6L,0x4cfd6e8207005L,0xfbd60a5a37810L, + 0x00d65e0d5f4c2L } }, + /* 11 */ + { { 0x09bbeb5275d38L,0x450be0a358d9dL,0x73eb2654268a7L,0xa232f0762ff49L, + 0x0c23da24252f4L }, + { 0x1b84f0b94520cL,0x63b05bd78e5daL,0x4d29ea1096667L,0xcff13a4dcb869L, + 0x019de3b8cc790L } }, + /* 12 */ + { { 0xa716c26c5fe04L,0x0b3bba1bdb183L,0x4cb712c3b28deL,0xcbfd7432c586aL, + 0x0e34dcbd491fcL }, + { 0x8d46baaa58403L,0x8682e97a53b40L,0x6aaa8af9a6974L,0x0f7f9e3901273L, + 0x0e7641f447b4eL } }, + /* 13 */ + { { 0x53941df64ba59L,0xec0b0242fc7d7L,0x1581859d33f10L,0x57bf4f06dfc6aL, + 0x04a12df57052aL }, + { 0x6338f9439dbd0L,0xd4bde53e1fbfaL,0x1f1b314d3c24bL,0xea46fd5e4ffa2L, + 0x06af5aa93bb5bL } }, + /* 14 */ + { { 0x0b69910c91999L,0x402a580491da1L,0x8cc20900a24b4L,0x40133e0094b4bL, + 0x05fe3475a66a4L }, + { 0x8cabdf93e7b4bL,0x1a7c23f91ab0fL,0xd1e6263292b50L,0xa91642e889aecL, + 0x0b544e308ecfeL } }, + /* 15 */ + { { 0x8c6e916ddfdceL,0x66f89179e6647L,0xd4e67e12c3291L,0xc20b4e8d6e764L, + 0x0e0b6b2bda6b0L }, + { 0x12df2bb7efb57L,0xde790c40070d3L,0x79bc9441aac0dL,0x3774f90336ad6L, + 0x071c023de25a6L } }, + /* 16 */ + { { 0x8c244bfe20925L,0xc38fdce86762aL,0xd38706391c19aL,0x24f65a96a5d5dL, + 0x061d587d421d3L }, + { 0x673a2a37173eaL,0x0853778b65e87L,0x5bab43e238480L,0xefbe10f8441e0L, + 0x0fa11fe124621L } }, + /* 17 */ + { { 0x91f2b2cb19ffdL,0x5bb1923c231c8L,0xac5ca8e01ba8dL,0xbedcb6d03d678L, + 0x0586eb04c1f13L }, + { 0x5c6e527e8ed09L,0x3c1819ede20c3L,0x6c652fa1e81a3L,0x4f11278fd6c05L, + 0x019d5ac087086L } }, + /* 18 */ + { { 0x9f581309a4e1fL,0x1be92700741e9L,0xfd28d20ab7de7L,0x563f26a5ef0beL, + 0x0e7c0073f7f9cL }, + { 0xd663a0ef59f76L,0x5420fcb0501f6L,0xa6602d4669b3bL,0x3c0ac08c1f7a7L, + 0x0e08504fec65bL } }, + /* 19 */ + { { 0x8f68da031b3caL,0x9ee6da6d66f09L,0x4f246e86d1cabL,0x96b45bfd81fa9L, + 0x078f018825b09L }, + { 0xefde43a25787fL,0x0d1dccac9bb7eL,0x35bfc368016f8L,0x747a0cea4877bL, + 0x043a773b87e94L } }, + /* 20 */ + { { 0x77734d2b533d5L,0xf6a1bdddc0625L,0x79ec293673b8aL,0x66b1577e7c9aaL, + 0x0bb6de651c3b2L }, + { 0x9303ab65259b3L,0xd3d03a7480e7eL,0xb3cfc27d6a0afL,0xb99bc5ac83d19L, + 0x060b4619a5d18L } }, + /* 21 */ + { { 0xa38e11ae5aa1cL,0x2b49e73658bd6L,0xe5f87edb8b765L,0xffcd0b130014eL, + 0x09d0f27b2aeebL }, + { 0x246317a730a55L,0x2fddbbc83aca9L,0xc019a719c955bL,0xc48d07c1dfe0aL, + 0x0244a566d356eL } }, + /* 22 */ + { { 0x0394aeacf1f96L,0xa9024c271c6dbL,0x2cbd3b99f2122L,0xef692626ac1b8L, + 0x045e58c873581L }, + { 0xf479da38f9dbcL,0x46e888a040d3fL,0x6e0bed7a8aaf1L,0xb7a4945adfb24L, + 0x0c040e21cc1e4L } }, + /* 23 */ + { { 0xaf0006f8117b6L,0xff73a35433847L,0xd9475eb651969L,0x6ec7482b35761L, + 0x01cdf5c97682cL }, + { 0x775b411f04839L,0xf448de16987dbL,0x70b32197dbeacL,0xff3db2921dd1bL, + 0x0046755f8a92dL } }, + /* 24 */ + { { 0xac5d2bce8ffcdL,0x8b2fe61a82cc8L,0x202d6c70d53c4L,0xa5f3f6f161727L, + 0x0046e5e113b83L }, + { 0x8ff64d8007f01L,0x125af43183e7bL,0x5e1a03c7fb1efL,0x005b045c5ea63L, + 0x06e0106c3303dL } }, + /* 25 */ + { { 0x7358488dd73b1L,0x8f995ed0d948cL,0x56a2ab7767070L,0xcf1f38385ea8cL, + 0x0442594ede901L }, + { 0xaa2c912d4b65bL,0x3b96c90c37f8fL,0xe978d1f94c234L,0xe68ed326e4a15L, + 0x0a796fa514c2eL } }, + /* 26 */ + { { 0xfb604823addd7L,0x83e56693b3359L,0xcbf3c809e2a61L,0x66e9f885b78e3L, + 0x0e4ad2da9c697L }, + { 0xf7f428e048a61L,0x8cc092d9a0357L,0x03ed8ef082d19L,0x5143fc3a1af4cL, + 0x0c5e94046c37bL } }, + /* 27 */ + { { 0xa538c2be75f9eL,0xe8cb123a78476L,0x109c04b6fd1a9L,0x4747d85e4df0bL, + 0x063283dafdb46L }, + { 0x28cf7baf2df15L,0x550ad9a7f4ce7L,0x834bcc3e592c4L,0xa938fab226adeL, + 0x068bd19ab1981L } }, + /* 28 */ + { { 0xead511887d659L,0xf4b359305ac08L,0xfe74fe33374d5L,0xdfd696986981cL, + 0x0495292f53c6fL }, + { 0x78c9e1acec896L,0x10ec5b44844a8L,0x64d60a7d964b2L,0x68376696f7e26L, + 0x00ec7530d2603L } }, + /* 29 */ + { { 0x13a05ad2687bbL,0x6af32e21fa2daL,0xdd4607ba1f83bL,0x3f0b390f5ef51L, + 0x00f6207a66486L }, + { 0x7e3bb0f138233L,0x6c272aa718bd6L,0x6ec88aedd66b9L,0x6dcf8ed004072L, + 0x0ff0db07208edL } }, + /* 30 */ + { { 0xfa1014c95d553L,0xfd5d680a8a749L,0xf3b566fa44052L,0x0ea3183b4317fL, + 0x0313b513c8874L }, + { 0x2e2ac08d11549L,0x0bb4dee21cb40L,0x7f2320e071ee1L,0x9f8126b987dd4L, + 0x02d3abcf986f1L } }, + /* 31 */ + { { 0x88501815581a2L,0x56632211af4c2L,0xcab2e999a0a6dL,0x8cdf19ba7a0f0L, + 0x0c036fa10ded9L }, + { 0xe08bac1fbd009L,0x9006d1581629aL,0xb9e0d8f0b68b1L,0x0194c2eb32779L, + 0x0a6b2a2c4b6d4L } }, + /* 32 */ + { { 0x3e50f6d3549cfL,0x6ffacd665ed43L,0xe11fcb46f3369L,0x9860695bfdaccL, + 0x0810ee252af7cL }, + { 0x50fe17159bb2cL,0xbe758b357b654L,0x69fea72f7dfbeL,0x17452b057e74dL, + 0x0d485717a9273L } }, + /* 33 */ + { { 0x41a8af0cb5a98L,0x931f3110bf117L,0xb382adfd3da8fL,0x604e1994e2cbaL, + 0x06a6045a72f9aL }, + { 0xc0d3fa2b2411dL,0x3e510e96e0170L,0x865b3ccbe0eb8L,0x57903bcc9f738L, + 0x0d3e45cfaf9e1L } }, + /* 34 */ + { { 0xf69bbe83f7669L,0x8272877d6bce1L,0x244278d09f8aeL,0xc19c9548ae543L, + 0x0207755dee3c2L }, + { 0xd61d96fef1945L,0xefb12d28c387bL,0x2df64aa18813cL,0xb00d9fbcd1d67L, + 0x048dc5ee57154L } }, + /* 35 */ + { { 0x790bff7e5a199L,0xcf989ccbb7123L,0xa519c79e0efb8L,0xf445c27a2bfe0L, + 0x0f2fb0aeddff6L }, + { 0x09575f0b5025fL,0xd740fa9f2241cL,0x80bfbd0550543L,0xd5258fa3c8ad3L, + 0x0a13e9015db28L } }, + /* 36 */ + { { 0x7a350a2b65cbcL,0x722a464226f9fL,0x23f07a10b04b9L,0x526f265ce241eL, + 0x02bf0d6b01497L }, + { 0x4dd3f4b216fb7L,0x67fbdda26ad3dL,0x708505cf7d7b8L,0xe89faeb7b83f6L, + 0x042a94a5a162fL } }, + /* 37 */ + { { 0x6ad0beaadf191L,0x9025a268d7584L,0x94dc1f60f8a48L,0xde3de86030504L, + 0x02c2dd969c65eL }, + { 0x2171d93849c17L,0xba1da250dd6d0L,0xc3a5485460488L,0x6dbc4810c7063L, + 0x0f437fa1f42c5L } }, + /* 38 */ + { { 0x0d7144a0f7dabL,0x931776e9ac6aaL,0x5f397860f0497L,0x7aa852c0a050fL, + 0x0aaf45b335470L }, + { 0x37c33c18d364aL,0x063e49716585eL,0x5ec5444d40b9bL,0x72bcf41716811L, + 0x0cdf6310df4f2L } }, + /* 39 */ + { { 0x3c6238ea8b7efL,0x1885bc2287747L,0xbda8e3408e935L,0x2ff2419567722L, + 0x0f0d008bada9eL }, + { 0x2671d2414d3b1L,0x85b019ea76291L,0x53bcbdbb37549L,0x7b8b5c61b96d4L, + 0x05bd5c2f5ca88L } }, + /* 40 */ + { { 0xf469ef49a3154L,0x956e2b2e9aef0L,0xa924a9c3e85a5L,0x471945aaec1eaL, + 0x0aa12dfc8a09eL }, + { 0x272274df69f1dL,0x2ca2ff5e7326fL,0x7a9dd44e0e4c8L,0xa901b9d8ce73bL, + 0x06c036e73e48cL } }, + /* 41 */ + { { 0xae12a0f6e3138L,0x0025ad345a5cfL,0x5672bc56966efL,0xbe248993c64b4L, + 0x0292ff65896afL }, + { 0x50d445e213402L,0x274392c9fed52L,0xa1c72e8f6580eL,0x7276097b397fdL, + 0x0644e0c90311bL } }, + /* 42 */ + { { 0x421e1a47153f0L,0x79920418c9e1eL,0x05d7672b86c3bL,0x9a7793bdce877L, + 0x0f25ae793cab7L }, + { 0x194a36d869d0cL,0x824986c2641f3L,0x96e945e9d55c8L,0x0a3e49fb5ea30L, + 0x039b8e65313dbL } }, + /* 43 */ + { { 0x54200b6fd2e59L,0x669255c98f377L,0xe2a573935e2c0L,0xdb06d9dab21a0L, + 0x039122f2f0f19L }, + { 0xce1e003cad53cL,0x0fe65c17e3cfbL,0xaa13877225b2cL,0xff8d72baf1d29L, + 0x08de80af8ce80L } }, + /* 44 */ + { { 0xea8d9207bbb76L,0x7c21782758afbL,0xc0436b1921c7eL,0x8c04dfa2b74b1L, + 0x0871949062e36L }, + { 0x928bba3993df5L,0xb5f3b3d26ab5fL,0x5b55050639d75L,0xfde1011aa78a8L, + 0x0fc315e6a5b74L } }, + /* 45 */ + { { 0xfd41ae8d6ecfaL,0xf61aec7f86561L,0x924741d5f8c44L,0x908898452a7b4L, + 0x0e6d4a7adee38L }, + { 0x52ed14593c75dL,0xa4dd271162605L,0xba2c7db70a70dL,0xae57d2aede937L, + 0x035dfaf9a9be2L } }, + /* 46 */ + { { 0x56fcdaa736636L,0x97ae2cab7e6b9L,0xf34996609f51dL,0x0d2bfb10bf410L, + 0x01da5c7d71c83L }, + { 0x1e4833cce6825L,0x8ff9573c3b5c4L,0x23036b815ad11L,0xb9d6a28552c7fL, + 0x07077c0fddbf4L } }, + /* 47 */ + { { 0x3ff8d46b9661cL,0x6b0d2cfd71bf6L,0x847f8f7a1dfd3L,0xfe440373e140aL, + 0x053a8632ee50eL }, + { 0x6ff68696d8051L,0x95c74f468a097L,0xe4e26bddaec0cL,0xfcc162994dc35L, + 0x0028ca76d34e1L } }, + /* 48 */ + { { 0xd47dcfc9877eeL,0x10801d0002d11L,0x4c260b6c8b362L,0xf046d002c1175L, + 0x004c17cd86962L }, + { 0xbd094b0daddf5L,0x7524ce55c06d9L,0x2da03b5bea235L,0x7474663356e67L, + 0x0f7ba4de9fed9L } }, + /* 49 */ + { { 0xbfa34ebe1263fL,0x3571ae7ce6d0dL,0x2a6f523557637L,0x1c41d24405538L, + 0x0e31f96005213L }, + { 0xb9216ea6b6ec6L,0x2e73c2fc44d1bL,0x9d0a29437a1d1L,0xd47bc10e7eac8L, + 0x0aa3a6259ce34L } }, + /* 50 */ + { { 0xf9df536f3dcd3L,0x50d2bf7360fbcL,0xf504f5b6cededL,0xdaee491710fadL, + 0x02398dd627e79L }, + { 0x705a36d09569eL,0xbb5149f769cf4L,0x5f6034cea0619L,0x6210ff9c03773L, + 0x05717f5b21c04L } }, + /* 51 */ + { { 0x229c921dd895eL,0x0040c284519feL,0xd637ecd8e5185L,0x28defa13d2391L, + 0x0660a2c560e3cL }, + { 0xa88aed67fcbd0L,0x780ea9f0969ccL,0x2e92b4dc84724L,0x245332b2f4817L, + 0x0624ee54c4f52L } }, + /* 52 */ + { { 0x49ce4d897ecccL,0xd93f9880aa095L,0x43a7c204d49d1L,0xfbc0723c24230L, + 0x04f392afb92bdL }, + { 0x9f8fa7de44fd9L,0xe457b32156696L,0x68ebc3cb66cfbL,0x399cdb2fa8033L, + 0x08a3e7977ccdbL } }, + /* 53 */ + { { 0x1881f06c4b125L,0x00f6e3ca8cddeL,0xc7a13e9ae34e3L,0x4404ef6999de5L, + 0x03888d02370c2L }, + { 0x8035644f91081L,0x615f015504762L,0x32cd36e3d9fcfL,0x23361827edc86L, + 0x0a5e62e471810L } }, + /* 54 */ + { { 0x25ee32facd6c8L,0x5454bcbc661a8L,0x8df9931699c63L,0x5adc0ce3edf79L, + 0x02c4768e6466aL }, + { 0x6ff8c90a64bc9L,0x20e4779f5cb34L,0xc05e884630a60L,0x52a0d949d064bL, + 0x07b5e6441f9e6L } }, + /* 55 */ + { { 0x9422c1d28444aL,0xd8be136a39216L,0xb0c7fcee996c5L,0x744a2387afe5fL, + 0x0b8af73cb0c8dL }, + { 0xe83aa338b86fdL,0x58a58a5cff5fdL,0x0ac9433fee3f1L,0x0895c9ee8f6f2L, + 0x0a036395f7f3fL } }, + /* 56 */ + { { 0x3c6bba10f7770L,0x81a12a0e248c7L,0x1bc2b9fa6f16dL,0xb533100df6825L, + 0x04be36b01875fL }, + { 0x6086e9fb56dbbL,0x8b07e7a4f8922L,0x6d52f20306fefL,0x00c0eeaccc056L, + 0x08cbc9a871bdcL } }, + /* 57 */ + { { 0x1895cc0dac4abL,0x40712ff112e13L,0xa1cee57a874a4L,0x35f86332ae7c6L, + 0x044e7553e0c08L }, + { 0x03fff7734002dL,0x8b0b34425c6d5L,0xe8738b59d35cbL,0xfc1895f702760L, + 0x0470a683a5eb8L } }, + /* 58 */ + { { 0x761dc90513482L,0x2a01e9276a81bL,0xce73083028720L,0xc6efcda441ee0L, + 0x016410690c63dL }, + { 0x34a066d06a2edL,0x45189b100bf50L,0xb8218c9dd4d77L,0xbb4fd914ae72aL, + 0x0d73479fd7abcL } }, + /* 59 */ + { { 0xefb165ad4c6e5L,0x8f5b06d04d7edL,0x575cb14262cf0L,0x666b12ed5bb18L, + 0x0816469e30771L }, + { 0xb9d79561e291eL,0x22c1de1661d7aL,0x35e0513eb9dafL,0x3f9cf49827eb1L, + 0x00a36dd23f0ddL } }, + /* 60 */ + { { 0xd32c741d5533cL,0x9e8684628f098L,0x349bd117c5f5aL,0xb11839a228adeL, + 0x0e331dfd6fdbaL }, + { 0x0ab686bcc6ed8L,0xbdef7a260e510L,0xce850d77160c3L,0x33899063d9a7bL, + 0x0d3b4782a492eL } }, + /* 61 */ + { { 0x9b6e8f3821f90L,0xed66eb7aada14L,0xa01311692edd9L,0xa5bd0bb669531L, + 0x07281275a4c86L }, + { 0x858f7d3ff47e5L,0xbc61016441503L,0xdfd9bb15e1616L,0x505962b0f11a7L, + 0x02c062e7ece14L } }, + /* 62 */ + { { 0xf996f0159ac2eL,0x36cbdb2713a76L,0x8e46047281e77L,0x7ef12ad6d2880L, + 0x0282a35f92c4eL }, + { 0x54b1ec0ce5cd2L,0xc91379c2299c3L,0xe82c11ecf99efL,0x2abd992caf383L, + 0x0c71cd513554dL } }, + /* 63 */ + { { 0x5de9c09b578f4L,0x58e3affa7a488L,0x9182f1f1884e2L,0xf3a38f76b1b75L, + 0x0c50f6740cf47L }, + { 0x4adf3374b68eaL,0x2369965fe2a9cL,0x5a53050a406f3L,0x58dc2f86a2228L, + 0x0b9ecb3a72129L } }, + /* 64 */ + { { 0x8410ef4f8b16aL,0xfec47b266a56fL,0xd9c87c197241aL,0xab1b0a406b8e6L, + 0x0803f3e02cd42L }, + { 0x309a804dbec69L,0xf73bbad05f7f0L,0xd8e197fa83b85L,0xadc1c6097273aL, + 0x0c097440e5067L } }, + /* 65 */ + { { 0xa56f2c379ab34L,0x8b841df8d1846L,0x76c68efa8ee06L,0x1f30203144591L, + 0x0f1af32d5915fL }, + { 0x375315d75bd50L,0xbaf72f67bc99cL,0x8d7723f837cffL,0x1c8b0613a4184L, + 0x023d0f130e2d4L } }, + /* 66 */ + { { 0xab6edf41500d9L,0xe5fcbeada8857L,0x97259510d890aL,0xfadd52fe86488L, + 0x0b0288dd6c0a3L }, + { 0x20f30650bcb08L,0x13695d6e16853L,0x989aa7671af63L,0xc8d231f520a7bL, + 0x0ffd3724ff408L } }, + /* 67 */ + { { 0x68e64b458e6cbL,0x20317a5d28539L,0xaa75f56992dadL,0x26df3814ae0b7L, + 0x0f5590f4ad78cL }, + { 0x24bd3cf0ba55aL,0x4a0c778bae0fcL,0x83b674a0fc472L,0x4a201ce9864f6L, + 0x018d6da54f6f7L } }, + /* 68 */ + { { 0x3e225d5be5a2bL,0x835934f3c6ed9L,0x2626ffc6fe799L,0x216a431409262L, + 0x050bbb4d97990L }, + { 0x191c6e57ec63eL,0x40181dcdb2378L,0x236e0f665422cL,0x49c341a8099b0L, + 0x02b10011801feL } }, + /* 69 */ + { { 0x8b5c59b391593L,0xa2598270fcfc6L,0x19adcbbc385f5L,0xae0c7144f3aadL, + 0x0dd55899983fbL }, + { 0x88b8e74b82ff4L,0x4071e734c993bL,0x3c0322ad2e03cL,0x60419a7a9eaf4L, + 0x0e6e4c551149dL } }, + /* 70 */ + { { 0x655bb1e9af288L,0x64f7ada93155fL,0xb2820e5647e1aL,0x56ff43697e4bcL, + 0x051e00db107edL }, + { 0x169b8771c327eL,0x0b4a96c2ad43dL,0xdeb477929cdb2L,0x9177c07d51f53L, + 0x0e22f42414982L } }, + /* 71 */ + { { 0x5e8f4635f1abbL,0xb568538874cd4L,0x5a8034d7edc0cL,0x48c9c9472c1fbL, + 0x0f709373d52dcL }, + { 0x966bba8af30d6L,0x4af137b69c401L,0x361c47e95bf5fL,0x5b113966162a9L, + 0x0bd52d288e727L } }, + /* 72 */ + { { 0x55c7a9c5fa877L,0x727d3a3d48ab1L,0x3d189d817dad6L,0x77a643f43f9e7L, + 0x0a0d0f8e4c8aaL }, + { 0xeafd8cc94f92dL,0xbe0c4ddb3a0bbL,0x82eba14d818c8L,0x6a0022cc65f8bL, + 0x0a56c78c7946dL } }, + /* 73 */ + { { 0x2391b0dd09529L,0xa63daddfcf296L,0xb5bf481803e0eL,0x367a2c77351f5L, + 0x0d8befdf8731aL }, + { 0x19d42fc0157f4L,0xd7fec8e650ab9L,0x2d48b0af51caeL,0x6478cdf9cb400L, + 0x0854a68a5ce9fL } }, + /* 74 */ + { { 0x5f67b63506ea5L,0x89a4fe0d66dc3L,0xe95cd4d9286c4L,0x6a953f101d3bfL, + 0x05cacea0b9884L }, + { 0xdf60c9ceac44dL,0xf4354d1c3aa90L,0xd5dbabe3db29aL,0xefa908dd3de8aL, + 0x0e4982d1235e4L } }, + /* 75 */ + { { 0x04a22c34cd55eL,0xb32680d132231L,0xfa1d94358695bL,0x0499fb345afa1L, + 0x08046b7f616b2L }, + { 0x3581e38e7d098L,0x8df46f0b70b53L,0x4cb78c4d7f61eL,0xaf5530dea9ea4L, + 0x0eb17ca7b9082L } }, + /* 76 */ + { { 0x1b59876a145b9L,0x0fc1bc71ec175L,0x92715bba5cf6bL,0xe131d3e035653L, + 0x0097b00bafab5L }, + { 0x6c8e9565f69e1L,0x5ab5be5199aa6L,0xa4fd98477e8f7L,0xcc9e6033ba11dL, + 0x0f95c747bafdbL } }, + /* 77 */ + { { 0xf01d3bebae45eL,0xf0c4bc6955558L,0xbc64fc6a8ebe9L,0xd837aeb705b1dL, + 0x03512601e566eL }, + { 0x6f1e1fa1161cdL,0xd54c65ef87933L,0x24f21e5328ab8L,0xab6b4757eee27L, + 0x00ef971236068L } }, + /* 78 */ + { { 0x98cf754ca4226L,0x38f8642c8e025L,0x68e17905eede1L,0xbc9548963f744L, + 0x0fc16d9333b4fL }, + { 0x6fb31e7c800caL,0x312678adaabe9L,0xff3e8b5138063L,0x7a173d6244976L, + 0x014ca4af1b95dL } }, + /* 79 */ + { { 0x771babd2f81d5L,0x6901f7d1967a4L,0xad9c9071a5f9dL,0x231dd898bef7cL, + 0x04057b063f59cL }, + { 0xd82fe89c05c0aL,0x6f1dc0df85bffL,0x35a16dbe4911cL,0x0b133befccaeaL, + 0x01c3b5d64f133L } }, + /* 80 */ + { { 0x14bfe80ec21feL,0x6ac255be825feL,0xf4a5d67f6ce11L,0x63af98bc5a072L, + 0x0fad27148db7eL }, + { 0x0b6ac29ab05b3L,0x3c4e251ae690cL,0x2aade7d37a9a8L,0x1a840a7dc875cL, + 0x077387de39f0eL } }, + /* 81 */ + { { 0xecc49a56c0dd7L,0xd846086c741e9L,0x505aecea5cffcL,0xc47e8f7a1408fL, + 0x0b37b85c0bef0L }, + { 0x6b6e4cc0e6a8fL,0xbf6b388f23359L,0x39cef4efd6d4bL,0x28d5aba453facL, + 0x09c135ac8f9f6L } }, + /* 82 */ + { { 0xa320284e35743L,0xb185a3cdef32aL,0xdf19819320d6aL,0x851fb821b1761L, + 0x05721361fc433L }, + { 0xdb36a71fc9168L,0x735e5c403c1f0L,0x7bcd8f55f98baL,0x11bdf64ca87e3L, + 0x0dcbac3c9e6bbL } }, + /* 83 */ + { { 0xd99684518cbe2L,0x189c9eb04ef01L,0x47feebfd242fcL,0x6862727663c7eL, + 0x0b8c1c89e2d62L }, + { 0x58bddc8e1d569L,0xc8b7d88cd051aL,0x11f31eb563809L,0x22d426c27fd9fL, + 0x05d23bbda2f94L } }, + /* 84 */ + { { 0xc729495c8f8beL,0x803bf362bf0a1L,0xf63d4ac2961c4L,0xe9009e418403dL, + 0x0c109f9cb91ecL }, + { 0x095d058945705L,0x96ddeb85c0c2dL,0xa40449bb9083dL,0x1ee184692b8d7L, + 0x09bc3344f2eeeL } }, + /* 85 */ + { { 0xae35642913074L,0x2748a542b10d5L,0x310732a55491bL,0x4cc1469ca665bL, + 0x029591d525f1aL }, + { 0xf5b6bb84f983fL,0x419f5f84e1e76L,0x0baa189be7eefL,0x332c1200d4968L, + 0x06376551f18efL } }, + /* 86 */ + { { 0x5f14e562976ccL,0xe60ef12c38bdaL,0xcca985222bca3L,0x987abbfa30646L, + 0x0bdb79dc808e2L }, + { 0xcb5c9cb06a772L,0xaafe536dcefd2L,0xc2b5db838f475L,0xc14ac2a3e0227L, + 0x08ee86001add3L } }, + /* 87 */ + { { 0x96981a4ade873L,0x4dc4fba48ccbeL,0xa054ba57ee9aaL,0xaa4b2cee28995L, + 0x092e51d7a6f77L }, + { 0xbafa87190a34dL,0x5bf6bd1ed1948L,0xcaf1144d698f7L,0xaaaad00ee6e30L, + 0x05182f86f0a56L } }, + /* 88 */ + { { 0x6212c7a4cc99cL,0x683e6d9ca1fbaL,0xac98c5aff609bL,0xa6f25dbb27cb5L, + 0x091dcab5d4073L }, + { 0x6cc3d5f575a70L,0x396f8d87fa01bL,0x99817360cb361L,0x4f2b165d4e8c8L, + 0x017a0cedb9797L } }, + /* 89 */ + { { 0x61e2a076c8d3aL,0x39210f924b388L,0x3a835d9701aadL,0xdf4194d0eae41L, + 0x02e8ce36c7f4cL }, + { 0x73dab037a862bL,0xb760e4c8fa912L,0x3baf2dd01ba9bL,0x68f3f96453883L, + 0x0f4ccc6cb34f6L } }, + /* 90 */ + { { 0xf525cf1f79687L,0x9592efa81544eL,0x5c78d297c5954L,0xf3c9e1231741aL, + 0x0ac0db4889a0dL }, + { 0xfc711df01747fL,0x58ef17df1386bL,0xccb6bb5592b93L,0x74a2e5880e4f5L, + 0x095a64a6194c9L } }, + /* 91 */ + { { 0x1efdac15a4c93L,0x738258514172cL,0x6cb0bad40269bL,0x06776a8dfb1c1L, + 0x0231e54ba2921L }, + { 0xdf9178ae6d2dcL,0x3f39112918a70L,0xe5b72234d6aa6L,0x31e1f627726b5L, + 0x0ab0be032d8a7L } }, + /* 92 */ + { { 0xad0e98d131f2dL,0xe33b04f101097L,0x5e9a748637f09L,0xa6791ac86196dL, + 0x0f1bcc8802cf6L }, + { 0x69140e8daacb4L,0x5560f6500925cL,0x77937a63c4e40L,0xb271591cc8fc4L, + 0x0851694695aebL } }, + /* 93 */ + { { 0x5c143f1dcf593L,0x29b018be3bde3L,0xbdd9d3d78202bL,0x55d8e9cdadc29L, + 0x08f67d9d2daadL }, + { 0x116567481ea5fL,0xe9e34c590c841L,0x5053fa8e7d2ddL,0x8b5dffdd43f40L, + 0x0f84572b9c072L } }, + /* 94 */ + { { 0xa7a7197af71c9L,0x447a7365655e1L,0xe1d5063a14494L,0x2c19a1b4ae070L, + 0x0edee2710616bL }, + { 0x034f511734121L,0x554a25e9f0b2fL,0x40c2ecf1cac6eL,0xd7f48dc148f3aL, + 0x09fd27e9b44ebL } }, + /* 95 */ + { { 0x7658af6e2cb16L,0x2cfe5919b63ccL,0x68d5583e3eb7dL,0xf3875a8c58161L, + 0x0a40c2fb6958fL }, + { 0xec560fedcc158L,0xc655f230568c9L,0xa307e127ad804L,0xdecfd93967049L, + 0x099bc9bb87dc6L } }, + /* 96 */ + { { 0x9521d927dafc6L,0x695c09cd1984aL,0x9366dde52c1fbL,0x7e649d9581a0fL, + 0x09abe210ba16dL }, + { 0xaf84a48915220L,0x6a4dd816c6480L,0x681ca5afa7317L,0x44b0c7d539871L, + 0x07881c25787f3L } }, + /* 97 */ + { { 0x99b51e0bcf3ffL,0xc5127f74f6933L,0xd01d9680d02cbL,0x89408fb465a2dL, + 0x015e6e319a30eL }, + { 0xd6e0d3e0e05f4L,0xdc43588404646L,0x4f850d3fad7bdL,0x72cebe61c7d1cL, + 0x00e55facf1911L } }, + /* 98 */ + { { 0xd9806f8787564L,0x2131e85ce67e9L,0x819e8d61a3317L,0x65776b0158cabL, + 0x0d73d09766fe9L }, + { 0x834251eb7206eL,0x0fc618bb42424L,0xe30a520a51929L,0xa50b5dcbb8595L, + 0x09250a3748f15L } }, + /* 99 */ + { { 0xf08f8be577410L,0x035077a8c6cafL,0xc0a63a4fd408aL,0x8c0bf1f63289eL, + 0x077414082c1ccL }, + { 0x40fa6eb0991cdL,0x6649fdc29605aL,0x324fd40c1ca08L,0x20b93a68a3c7bL, + 0x08cb04f4d12ebL } }, + /* 100 */ + { { 0x2d0556906171cL,0xcdb0240c3fb1cL,0x89068419073e9L,0x3b51db8e6b4fdL, + 0x0e4e429ef4712L }, + { 0xdd53c38ec36f4L,0x01ff4b6a270b8L,0x79a9a48f9d2dcL,0x65525d066e078L, + 0x037bca2ff3c6eL } }, + /* 101 */ + { { 0x2e3c7df562470L,0xa2c0964ac94cdL,0x0c793be44f272L,0xb22a7c6d5df98L, + 0x059913edc3002L }, + { 0x39a835750592aL,0x80e783de027a1L,0xa05d64f99e01dL,0xe226cf8c0375eL, + 0x043786e4ab013L } }, + /* 102 */ + { { 0x2b0ed9e56b5a6L,0xa6d9fc68f9ff3L,0x97846a70750d9L,0x9e7aec15e8455L, + 0x08638ca98b7e7L }, + { 0xae0960afc24b2L,0xaf4dace8f22f5L,0xecba78f05398eL,0xa6f03b765dd0aL, + 0x01ecdd36a7b3aL } }, + /* 103 */ + { { 0xacd626c5ff2f3L,0xc02873a9785d3L,0x2110d54a2d516L,0xf32dad94c9fadL, + 0x0d85d0f85d459L }, + { 0x00b8d10b11da3L,0x30a78318c49f7L,0x208decdd2c22cL,0x3c62556988f49L, + 0x0a04f19c3b4edL } }, + /* 104 */ + { { 0x924c8ed7f93bdL,0x5d392f51f6087L,0x21b71afcb64acL,0x50b07cae330a8L, + 0x092b2eeea5c09L }, + { 0xc4c9485b6e235L,0xa92936c0f085aL,0x0508891ab2ca4L,0x276c80faa6b3eL, + 0x01ee782215834L } }, + /* 105 */ + { { 0xa2e00e63e79f7L,0xb2f399d906a60L,0x607c09df590e7L,0xe1509021054a6L, + 0x0f3f2ced857a6L }, + { 0x510f3f10d9b55L,0xacd8642648200L,0x8bd0e7c9d2fcfL,0xe210e5631aa7eL, + 0x00f56a4543da3L } }, + /* 106 */ + { { 0x1bffa1043e0dfL,0xcc9c007e6d5b2L,0x4a8517a6c74b6L,0xe2631a656ec0dL, + 0x0bd8f17411969L }, + { 0xbbb86beb7494aL,0x6f45f3b8388a9L,0x4e5a79a1567d4L,0xfa09df7a12a7aL, + 0x02d1a1c3530ccL } }, + /* 107 */ + { { 0xe3813506508daL,0xc4a1d795a7192L,0xa9944b3336180L,0xba46cddb59497L, + 0x0a107a65eb91fL }, + { 0x1d1c50f94d639L,0x758a58b7d7e6dL,0xd37ca1c8b4af3L,0x9af21a7c5584bL, + 0x0183d760af87aL } }, + /* 108 */ + { { 0x697110dde59a4L,0x070e8bef8729dL,0xf2ebe78f1ad8dL,0xd754229b49634L, + 0x01d44179dc269L }, + { 0xdc0cf8390d30eL,0x530de8110cb32L,0xbc0339a0a3b27L,0xd26231af1dc52L, + 0x0771f9cc29606L } }, + /* 109 */ + { { 0x93e7785040739L,0xb98026a939999L,0x5f8fc2644539dL,0x718ecf40f6f2fL, + 0x064427a310362L }, + { 0xf2d8785428aa8L,0x3febfb49a84f4L,0x23d01ac7b7adcL,0x0d6d201b2c6dfL, + 0x049d9b7496ae9L } }, + /* 110 */ + { { 0x8d8bc435d1099L,0x4e8e8d1a08cc7L,0xcb68a412adbcdL,0x544502c2e2a02L, + 0x09037d81b3f60L }, + { 0xbac27074c7b61L,0xab57bfd72e7cdL,0x96d5352fe2031L,0x639c61ccec965L, + 0x008c3de6a7cc0L } }, + /* 111 */ + { { 0xdd020f6d552abL,0x9805cd81f120fL,0x135129156baffL,0x6b2f06fb7c3e9L, + 0x0c69094424579L }, + { 0x3ae9c41231bd1L,0x875cc5820517bL,0x9d6a1221eac6eL,0x3ac0208837abfL, + 0x03fa3db02cafeL } }, + /* 112 */ + { { 0xa3e6505058880L,0xef643943f2d75L,0xab249257da365L,0x08ff4147861cfL, + 0x0c5c4bdb0fdb8L }, + { 0x13e34b272b56bL,0x9511b9043a735L,0x8844969c8327eL,0xb6b5fd8ce37dfL, + 0x02d56db9446c2L } }, + /* 113 */ + { { 0x1782fff46ac6bL,0x2607a2e425246L,0x9a48de1d19f79L,0xba42fafea3c40L, + 0x00f56bd9de503L }, + { 0xd4ed1345cda49L,0xfc816f299d137L,0xeb43402821158L,0xb5f1e7c6a54aaL, + 0x04003bb9d1173L } }, + /* 114 */ + { { 0xe8189a0803387L,0xf539cbd4043b8L,0x2877f21ece115L,0x2f9e4297208ddL, + 0x053765522a07fL }, + { 0x80a21a8a4182dL,0x7a3219df79a49L,0xa19a2d4a2bbd0L,0x4549674d0a2e1L, + 0x07a056f586c5dL } }, + /* 115 */ + { { 0xb25589d8a2a47L,0x48c3df2773646L,0xbf0d5395b5829L,0x267551ec000eaL, + 0x077d482f17a1aL }, + { 0x1bd9587853948L,0xbd6cfbffeeb8aL,0x0681e47a6f817L,0xb0e4ab6ec0578L, + 0x04115012b2b38L } }, + /* 116 */ + { { 0x3f0f46de28cedL,0x609b13ec473c7L,0xe5c63921d5da7L,0x094661b8ce9e6L, + 0x0cdf04572fbeaL }, + { 0x3c58b6c53c3b0L,0x10447b843c1cbL,0xcb9780e97fe3cL,0x3109fb2b8ae12L, + 0x0ee703dda9738L } }, + /* 117 */ + { { 0x15140ff57e43aL,0xd3b1b811b8345L,0xf42b986d44660L,0xce212b3b5dff8L, + 0x02a0ad89da162L }, + { 0x4a6946bc277baL,0x54c141c27664eL,0xabf6274c788c9L,0x4659141aa64ccL, + 0x0d62d0b67ac2bL } }, + /* 118 */ + { { 0x5d87b2c054ac4L,0x59f27df78839cL,0x18128d6570058L,0x2426edf7cbf3bL, + 0x0b39a23f2991cL }, + { 0x84a15f0b16ae5L,0xb1a136f51b952L,0x27007830c6a05L,0x4cc51d63c137fL, + 0x004ed0092c067L } }, + /* 119 */ + { { 0x185d19ae90393L,0x294a3d64e61f4L,0x854fc143047b4L,0xc387ae0001a69L, + 0x0a0a91fc10177L }, + { 0xa3f01ae2c831eL,0x822b727e16ff0L,0xa3075b4bb76aeL,0x0c418f12c8a15L, + 0x0084cf9889ed2L } }, + /* 120 */ + { { 0x509defca6becfL,0x807dffb328d98L,0x778e8b92fceaeL,0xf77e5d8a15c44L, + 0x0d57955b273abL }, + { 0xda79e31b5d4f1L,0x4b3cfa7a1c210L,0xc27c20baa52f0L,0x41f1d4d12089dL, + 0x08e14ea4202d1L } }, + /* 121 */ + { { 0x50345f2897042L,0x1f43402c4aeedL,0x8bdfb218d0533L,0xd158c8d9c194cL, + 0x0597e1a372aa4L }, + { 0x7ec1acf0bd68cL,0xdcab024945032L,0x9fe3e846d4be0L,0x4dea5b9c8d7acL, + 0x0ca3f0236199bL } }, + /* 122 */ + { { 0xa10b56170bd20L,0xf16d3f5de7592L,0x4b2ade20ea897L,0x07e4a3363ff14L, + 0x0bde7fd7e309cL }, + { 0xbb6d2b8f5432cL,0xcbe043444b516L,0x8f95b5a210dc1L,0xd1983db01e6ffL, + 0x0b623ad0e0a7dL } }, + /* 123 */ + { { 0xbd67560c7b65bL,0x9023a4a289a75L,0x7b26795ab8c55L,0x137bf8220fd0dL, + 0x0d6aa2e4658ecL }, + { 0xbc00b5138bb85L,0x21d833a95c10aL,0x702a32e8c31d1L,0x513ab24ff00b1L, + 0x0111662e02dccL } }, + /* 124 */ + { { 0x14015efb42b87L,0x701b6c4dff781L,0x7d7c129bd9f5dL,0x50f866ecccd7aL, + 0x0db3ee1cb94b7L }, + { 0xf3db0f34837cfL,0x8bb9578d4fb26L,0xc56657de7eed1L,0x6a595d2cdf937L, + 0x0886a64425220L } }, + /* 125 */ + { { 0x34cfb65b569eaL,0x41f72119c13c2L,0x15a619e200111L,0x17bc8badc85daL, + 0x0a70cf4eb018aL }, + { 0xf97ae8c4a6a65L,0x270134378f224L,0xf7e096036e5cfL,0x7b77be3a609e4L, + 0x0aa4772abd174L } }, + /* 126 */ + { { 0x761317aa60cc0L,0x610368115f676L,0xbc1bb5ac79163L,0xf974ded98bb4bL, + 0x0611a6ddc30faL }, + { 0x78cbcc15ee47aL,0x824e0d96a530eL,0xdd9ed882e8962L,0x9c8836f35adf3L, + 0x05cfffaf81642L } }, + /* 127 */ + { { 0x54cff9b7a99cdL,0x9d843c45a1c0dL,0x2c739e17bf3b9L,0x994c038a908f6L, + 0x06e5a6b237dc1L }, + { 0xb454e0ba5db77L,0x7facf60d63ef8L,0x6608378b7b880L,0xabcce591c0c67L, + 0x0481a238d242dL } }, + /* 128 */ + { { 0x17bc035d0b34aL,0x6b8327c0a7e34L,0xc0362d1440b38L,0xf9438fb7262daL, + 0x02c41114ce0cdL }, + { 0x5cef1ad95a0b1L,0xa867d543622baL,0x1e486c9c09b37L,0x929726d6cdd20L, + 0x020477abf42ffL } }, + /* 129 */ + { { 0x5173c18d65dbfL,0x0e339edad82f7L,0xcf1001c77bf94L,0x96b67022d26bdL, + 0x0ac66409ac773L }, + { 0xbb36fc6261cc3L,0xc9190e7e908b0L,0x45e6c10213f7bL,0x2f856541cebaaL, + 0x0ce8e6975cc12L } }, + /* 130 */ + { { 0x21b41bc0a67d2L,0x0a444d248a0f1L,0x59b473762d476L,0xb4a80e044f1d6L, + 0x008fde365250bL }, + { 0xec3da848bf287L,0x82d3369d6eaceL,0x2449482c2a621L,0x6cd73582dfdc9L, + 0x02f7e2fd2565dL } }, + /* 131 */ + { { 0xb92dbc3770fa7L,0x5c379043f9ae4L,0x7761171095e8dL,0x02ae54f34e9d1L, + 0x0c65be92e9077L }, + { 0x8a303f6fd0a40L,0xe3bcce784b275L,0xf9767bfe7d822L,0x3b3a7ae4f5854L, + 0x04bff8e47d119L } }, + /* 132 */ + { { 0x1d21f00ff1480L,0x7d0754db16cd4L,0xbe0f3ea2ab8fbL,0x967dac81d2efbL, + 0x03e4e4ae65772L }, + { 0x8f36d3c5303e6L,0x4b922623977e1L,0x324c3c03bd999L,0x60289ed70e261L, + 0x05388aefd58ecL } }, + /* 133 */ + { { 0x317eb5e5d7713L,0xee75de49daad1L,0x74fb26109b985L,0xbe0e32f5bc4fcL, + 0x05cf908d14f75L }, + { 0x435108e657b12L,0xa5b96ed9e6760L,0x970ccc2bfd421L,0x0ce20e29f51f8L, + 0x0a698ba4060f0L } }, + /* 134 */ + { { 0xb1686ef748fecL,0xa27e9d2cf973dL,0xe265effe6e755L,0xad8d630b6544cL, + 0x0b142ef8a7aebL }, + { 0x1af9f17d5770aL,0x672cb3412fad3L,0xf3359de66af3bL,0x50756bd60d1bdL, + 0x0d1896a965851L } }, + /* 135 */ + { { 0x957ab33c41c08L,0xac5468e2e1ec5L,0xc472f6c87de94L,0xda3918816b73aL, + 0x0267b0e0b7981L }, + { 0x54e5d8e62b988L,0x55116d21e76e5L,0xd2a6f99d8ddc7L,0x93934610faf03L, + 0x0b54e287aa111L } }, + /* 136 */ + { { 0x122b5178a876bL,0xff085104b40a0L,0x4f29f7651ff96L,0xd4e6050b31ab1L, + 0x084abb28b5f87L }, + { 0xd439f8270790aL,0x9d85e3f46bd5eL,0xc1e22122d6cb5L,0x564075f55c1b6L, + 0x0e5436f671765L } }, + /* 137 */ + { { 0x9025e2286e8d5L,0xb4864453be53fL,0x408e3a0353c95L,0xe99ed832f5bdeL, + 0x00404f68b5b9cL }, + { 0x33bdea781e8e5L,0x18163c2f5bcadL,0x119caa33cdf50L,0xc701575769600L, + 0x03a4263df0ac1L } }, + /* 138 */ + { { 0x65ecc9aeb596dL,0xe7023c92b4c29L,0xe01396101ea03L,0xa3674704b4b62L, + 0x00ca8fd3f905eL }, + { 0x23a42551b2b61L,0x9c390fcd06925L,0x392a63e1eb7a8L,0x0c33e7f1d2be0L, + 0x096dca2644ddbL } }, + /* 139 */ + { { 0xbb43a387510afL,0xa8a9a36a01203L,0xf950378846feaL,0x59dcd23a57702L, + 0x04363e2123aadL }, + { 0x3a1c740246a47L,0xd2e55dd24dca4L,0xd8faf96b362b8L,0x98c4f9b086045L, + 0x0840e115cd8bbL } }, + /* 140 */ + { { 0x205e21023e8a7L,0xcdd8dc7a0bf12L,0x63a5ddfc808a8L,0xd6d4e292a2721L, + 0x05e0d6abd30deL }, + { 0x721c27cfc0f64L,0x1d0e55ed8807aL,0xd1f9db242eec0L,0xa25a26a7bef91L, + 0x07dea48f42945L } }, + /* 141 */ + { { 0xf6f1ce5060a81L,0x72f8f95615abdL,0x6ac268be79f9cL,0x16d1cfd36c540L, + 0x0abc2a2beebfdL }, + { 0x66f91d3e2eac7L,0x63d2dd04668acL,0x282d31b6f10baL,0xefc16790e3770L, + 0x04ea353946c7eL } }, + /* 142 */ + { { 0xa2f8d5266309dL,0xc081945a3eed8L,0x78c5dc10a51c6L,0xffc3cecaf45a5L, + 0x03a76e6891c94L }, + { 0xce8a47d7b0d0fL,0x968f584a5f9aaL,0xe697fbe963aceL,0x646451a30c724L, + 0x08212a10a465eL } }, + /* 143 */ + { { 0xc61c3cfab8caaL,0x840e142390ef7L,0xe9733ca18eb8eL,0xb164cd1dff677L, + 0x0aa7cab71599cL }, + { 0xc9273bc837bd1L,0xd0c36af5d702fL,0x423da49c06407L,0x17c317621292fL, + 0x040e38073fe06L } }, + /* 144 */ + { { 0x80824a7bf9b7cL,0x203fbe30d0f4fL,0x7cf9ce3365d23L,0x5526bfbe53209L, + 0x0e3604700b305L }, + { 0xb99116cc6c2c7L,0x08ba4cbee64dcL,0x37ad9ec726837L,0xe15fdcded4346L, + 0x06542d677a3deL } }, + /* 145 */ + { { 0x2b6d07b6c377aL,0x47903448be3f3L,0x0da8af76cb038L,0x6f21d6fdd3a82L, + 0x0a6534aee09bbL }, + { 0x1780d1035facfL,0x339dcb47e630aL,0x447f39335e55aL,0xef226ea50fe1cL, + 0x0f3cb672fdc9aL } }, + /* 146 */ + { { 0x719fe3b55fd83L,0x6c875ddd10eb3L,0x5cea784e0d7a4L,0x70e733ac9fa90L, + 0x07cafaa2eaae8L }, + { 0x14d041d53b338L,0xa0ef87e6c69b8L,0x1672b0fe0acc0L,0x522efb93d1081L, + 0x00aab13c1b9bdL } }, + /* 147 */ + { { 0xce278d2681297L,0xb1b509546addcL,0x661aaf2cb350eL,0x12e92dc431737L, + 0x04b91a6028470L }, + { 0xf109572f8ddcfL,0x1e9a911af4dcfL,0x372430e08ebf6L,0x1cab48f4360acL, + 0x049534c537232L } }, + /* 148 */ + { { 0xf7d71f07b7e9dL,0xa313cd516f83dL,0xc047ee3a478efL,0xc5ee78ef264b6L, + 0x0caf46c4fd65aL }, + { 0xd0c7792aa8266L,0x66913684bba04L,0xe4b16b0edf454L,0x770f56e65168aL, + 0x014ce9e5704c6L } }, + /* 149 */ + { { 0x45e3e965e8f91L,0xbacb0f2492994L,0x0c8a0a0d3aca1L,0x9a71d31cc70f9L, + 0x01bb708a53e4cL }, + { 0xa9e69558bdd7aL,0x08018a26b1d5cL,0xc9cf1ec734a05L,0x0102b093aa714L, + 0x0f9d126f2da30L } }, + /* 150 */ + { { 0xbca7aaff9563eL,0xfeb49914a0749L,0xf5f1671dd077aL,0xcc69e27a0311bL, + 0x0807afcb9729eL }, + { 0xa9337c9b08b77L,0x85443c7e387f8L,0x76fd8ba86c3a7L,0xcd8c85fafa594L, + 0x0751adcd16568L } }, + /* 151 */ + { { 0xa38b410715c0dL,0x718f7697f78aeL,0x3fbf06dd113eaL,0x743f665eab149L, + 0x029ec44682537L }, + { 0x4719cb50bebbcL,0xbfe45054223d9L,0xd2dedb1399ee5L,0x077d90cd5b3a8L, + 0x0ff9370e392a4L } }, + /* 152 */ + { { 0x2d69bc6b75b65L,0xd5266651c559aL,0xde9d7d24188f8L,0xd01a28a9f33e3L, + 0x09776478ba2a9L }, + { 0x2622d929af2c7L,0x6d4e690923885L,0x89a51e9334f5dL,0x82face6cc7e5aL, + 0x074a6313fac2fL } }, + /* 153 */ + { { 0x4dfddb75f079cL,0x9518e36fbbb2fL,0x7cd36dd85b07cL,0x863d1b6cfcf0eL, + 0x0ab75be150ff4L }, + { 0x367c0173fc9b7L,0x20d2594fd081bL,0x4091236b90a74L,0x59f615fdbf03cL, + 0x04ebeac2e0b44L } }, + /* 154 */ + { { 0xc5fe75c9f2c53L,0x118eae9411eb6L,0x95ac5d8d25220L,0xaffcc8887633fL, + 0x0df99887b2c1bL }, + { 0x8eed2850aaecbL,0x1b01d6a272bb7L,0x1cdbcac9d4918L,0x4058978dd511bL, + 0x027b040a7779fL } }, + /* 155 */ + { { 0x05db7f73b2eb2L,0x088e1b2118904L,0x962327ee0df85L,0xa3f5501b71525L, + 0x0b393dd37e4cfL }, + { 0x30e7b3fd75165L,0xc2bcd33554a12L,0xf7b5022d66344L,0x34196c36f1be0L, + 0x009588c12d046L } }, + /* 156 */ + { { 0x6093f02601c3bL,0xf8cf5c335fe08L,0x94aff28fb0252L,0x648b955cf2808L, + 0x081c879a9db9fL }, + { 0xe687cc6f56c51L,0x693f17618c040L,0x059353bfed471L,0x1bc444f88a419L, + 0x0fa0d48f55fc1L } }, + /* 157 */ + { { 0xe1c9de1608e4dL,0x113582822cbc6L,0x57ec2d7010ddaL,0x67d6f6b7ddc11L, + 0x08ea0e156b6a3L }, + { 0x4e02f2383b3b4L,0x943f01f53ca35L,0xde03ca569966bL,0xb5ac4ff6632b2L, + 0x03f5ab924fa00L } }, + /* 158 */ + { { 0xbb0d959739efbL,0xf4e7ebec0d337L,0x11a67d1c751b0L,0x256e2da52dd64L, + 0x08bc768872b74L }, + { 0xe3b7282d3d253L,0xa1f58d779fa5bL,0x16767bba9f679L,0xf34fa1cac168eL, + 0x0b386f19060fcL } }, + /* 159 */ + { { 0x3c1352fedcfc2L,0x6262f8af0d31fL,0x57288c25396bfL,0x9c4d9a02b4eaeL, + 0x04cb460f71b06L }, + { 0x7b4d35b8095eaL,0x596fc07603ae6L,0x614a16592bbf8L,0x5223e1475f66bL, + 0x052c0d50895efL } }, + /* 160 */ + { { 0xc210e15339848L,0xe870778c8d231L,0x956e170e87a28L,0x9c0b9d1de6616L, + 0x04ac3c9382bb0L }, + { 0xe05516998987dL,0xc4ae09f4d619bL,0xa3f933d8b2376L,0x05f41de0b7651L, + 0x0380d94c7e397L } }, + /* 161 */ + { { 0x355aa81542e75L,0xa1ee01b9b701aL,0x24d708796c724L,0x37af6b3a29776L, + 0x02ce3e171de26L }, + { 0xfeb49f5d5bc1aL,0x7e2777e2b5cfeL,0x513756ca65560L,0x4e4d4feaac2f9L, + 0x02e6cd8520b62L } }, + /* 162 */ + { { 0x5954b8c31c31dL,0x005bf21a0c368L,0x5c79ec968533dL,0x9d540bd7626e7L, + 0x0ca17754742c6L }, + { 0xedafff6d2dbb2L,0xbd174a9d18cc6L,0xa4578e8fd0d8cL,0x2ce6875e8793aL, + 0x0a976a7139cabL } }, + /* 163 */ + { { 0x51f1b93fb353dL,0x8b57fcfa720a6L,0x1b15281d75cabL,0x4999aa88cfa73L, + 0x08720a7170a1fL }, + { 0xe8d37693e1b90L,0x0b16f6dfc38c3L,0x52a8742d345dcL,0x893c8ea8d00abL, + 0x09719ef29c769L } }, + /* 164 */ + { { 0xeed8d58e35909L,0xdc33ddc116820L,0xe2050269366d8L,0x04c1d7f999d06L, + 0x0a5072976e157L }, + { 0xa37eac4e70b2eL,0x576890aa8a002L,0x45b2a5c84dcf6L,0x7725cd71bf186L, + 0x099389c9df7b7L } }, + /* 165 */ + { { 0xc08f27ada7a4bL,0x03fd389366238L,0x66f512c3abe9dL,0x82e46b672e897L, + 0x0a88806aa202cL }, + { 0x2044ad380184eL,0xc4126a8b85660L,0xd844f17a8cb78L,0xdcfe79d670c0aL, + 0x00043bffb4738L } }, + /* 166 */ + { { 0x9b5dc36d5192eL,0xd34590b2af8d5L,0x1601781acf885L,0x486683566d0a1L, + 0x052f3ef01ba6cL }, + { 0x6732a0edcb64dL,0x238068379f398L,0x040f3090a482cL,0x7e7516cbe5fa7L, + 0x03296bd899ef2L } }, + /* 167 */ + { { 0xaba89454d81d7L,0xef51eb9b3c476L,0x1c579869eade7L,0x71e9619a21cd8L, + 0x03b90febfaee5L }, + { 0x3023e5496f7cbL,0xd87fb51bc4939L,0x9beb5ce55be41L,0x0b1803f1dd489L, + 0x06e88069d9f81L } }, + /* 168 */ + { { 0x7ab11b43ea1dbL,0xa95259d292ce3L,0xf84f1860a7ff1L,0xad13851b02218L, + 0x0a7222beadefaL }, + { 0xc78ec2b0a9144L,0x51f2fa59c5a2aL,0x147ce385a0240L,0xc69091d1eca56L, + 0x0be94d523bc2aL } }, + /* 169 */ + { { 0x4945e0b226ce7L,0x47967e8b7072fL,0x5a6c63eb8afd7L,0xc766edea46f18L, + 0x07782defe9be8L }, + { 0xd2aa43db38626L,0x8776f67ad1760L,0x4499cdb460ae7L,0x2e4b341b86fc5L, + 0x003838567a289L } }, + /* 170 */ + { { 0xdaefd79ec1a0fL,0xfdceb39c972d8L,0x8f61a953bbcd6L,0xb420f5575ffc5L, + 0x0dbd986c4adf7L }, + { 0xa881415f39eb7L,0xf5b98d976c81aL,0xf2f717d6ee2fcL,0xbbd05465475dcL, + 0x08e24d3c46860L } }, + /* 171 */ + { { 0xd8e549a587390L,0x4f0cbec588749L,0x25983c612bb19L,0xafc846e07da4bL, + 0x0541a99c4407bL }, + { 0x41692624c8842L,0x2ad86c05ffdb2L,0xf7fcf626044c1L,0x35d1c59d14b44L, + 0x0c0092c49f57dL } }, + /* 172 */ + { { 0xc75c3df2e61efL,0xc82e1b35cad3cL,0x09f29f47e8841L,0x944dc62d30d19L, + 0x075e406347286L }, + { 0x41fc5bbc237d0L,0xf0ec4f01c9e7dL,0x82bd534c9537bL,0x858691c51a162L, + 0x05b7cb658c784L } }, + /* 173 */ + { { 0xa70848a28ead1L,0x08fd3b47f6964L,0x67e5b39802dc5L,0x97a19ae4bfd17L, + 0x07ae13eba8df0L }, + { 0x16ef8eadd384eL,0xd9b6b2ff06fd2L,0xbcdb5f30361a2L,0xe3fd204b98784L, + 0x0787d8074e2a8L } }, + /* 174 */ + { { 0x25d6b757fbb1cL,0xb2ca201debc5eL,0xd2233ffe47bddL,0x84844a55e9a36L, + 0x05c2228199ef2L }, + { 0xd4a8588315250L,0x2b827097c1773L,0xef5d33f21b21aL,0xf2b0ab7c4ea1dL, + 0x0e45d37abbaf0L } }, + /* 175 */ + { { 0xf1e3428511c8aL,0xc8bdca6cd3d2dL,0x27c39a7ebb229L,0xb9d3578a71a76L, + 0x0ed7bc12284dfL }, + { 0x2a6df93dea561L,0x8dd48f0ed1cf2L,0xbad23e85443f1L,0x6d27d8b861405L, + 0x0aac97cc945caL } }, + /* 176 */ + { { 0x4ea74a16bd00aL,0xadf5c0bcc1eb5L,0xf9bfc06d839e9L,0xdc4e092bb7f11L, + 0x0318f97b31163L }, + { 0x0c5bec30d7138L,0x23abc30220eccL,0x022360644e8dfL,0xff4d2bb7972fbL, + 0x0fa41faa19a84L } }, + /* 177 */ + { { 0x2d974a6642269L,0xce9bb783bd440L,0x941e60bc81814L,0xe9e2398d38e47L, + 0x038bb6b2c1d26L }, + { 0xe4a256a577f87L,0x53dc11fe1cc64L,0x22807288b52d2L,0x01a5ff336abf6L, + 0x094dd0905ce76L } }, + /* 178 */ + { { 0xcf7dcde93f92aL,0xcb89b5f315156L,0x995e750a01333L,0x2ae902404df9cL, + 0x092077867d25cL }, + { 0x71e010bf39d44L,0x2096bb53d7e24L,0xc9c3d8f5f2c90L,0xeb514c44b7b35L, + 0x081e8428bd29bL } }, + /* 179 */ + { { 0x9c2bac477199fL,0xee6b5ecdd96ddL,0xe40fd0e8cb8eeL,0xa4b18af7db3feL, + 0x01b94ab62dbbfL }, + { 0x0d8b3ce47f143L,0xfc63f4616344fL,0xc59938351e623L,0x90eef18f270fcL, + 0x006a38e280555L } }, + /* 180 */ + { { 0xb0139b3355b49L,0x60b4ebf99b2e5L,0x269f3dc20e265L,0xd4f8c08ffa6bdL, + 0x0a7b36c2083d9L }, + { 0x15c3a1b3e8830L,0xe1a89f9c0b64dL,0x2d16930d5fceaL,0x2a20cfeee4a2eL, + 0x0be54c6b4a282L } }, + /* 181 */ + { { 0xdb3df8d91167cL,0x79e7a6625ed6cL,0x46ac7f4517c3fL,0x22bb7105648f3L, + 0x0bf30a5abeae0L }, + { 0x785be93828a68L,0x327f3ef0368e7L,0x92146b25161c3L,0xd13ae11b5feb5L, + 0x0d1c820de2732L } }, + /* 182 */ + { { 0xe13479038b363L,0x546b05e519043L,0x026cad158c11fL,0x8da34fe57abe6L, + 0x0b7d17bed68a1L }, + { 0xa5891e29c2559L,0x765bfffd8444cL,0x4e469484f7a03L,0xcc64498de4af7L, + 0x03997fd5e6412L } }, + /* 183 */ + { { 0x746828bd61507L,0xd534a64d2af20L,0xa8a15e329e132L,0x13e8ffeddfb08L, + 0x00eeb89293c6cL }, + { 0x69a3ea7e259f8L,0xe6d13e7e67e9bL,0xd1fa685ce1db7L,0xb6ef277318f6aL, + 0x0228916f8c922L } }, + /* 184 */ + { { 0xae25b0a12ab5bL,0x1f957bc136959L,0x16e2b0ccc1117L,0x097e8058429edL, + 0x0ec05ad1d6e93L }, + { 0xba5beac3f3708L,0x3530b59d77157L,0x18234e531baf9L,0x1b3747b552371L, + 0x07d3141567ff1L } }, + /* 185 */ + { { 0x9c05cf6dfefabL,0x68dcb377077bdL,0xa38bb95be2f22L,0xd7a3e53ead973L, + 0x0e9ce66fc9bc1L }, + { 0xa15766f6a02a1L,0xdf60e600ed75aL,0x8cdc1b938c087L,0x0651f8947f346L, + 0x0d9650b017228L } }, + /* 186 */ + { { 0xb4c4a5a057e60L,0xbe8def25e4504L,0x7c1ccbdcbccc3L,0xb7a2a63532081L, + 0x014d6699a804eL }, + { 0xa8415db1f411aL,0x0bf80d769c2c8L,0xc2f77ad09fbafL,0x598ab4deef901L, + 0x06f4c68410d43L } }, + /* 187 */ + { { 0x6df4e96c24a96L,0x85fcbd99a3872L,0xb2ae30a534dbcL,0x9abb3c466ef28L, + 0x04c4350fd6118L }, + { 0x7f716f855b8daL,0x94463c38a1296L,0xae9334341a423L,0x18b5c37e1413eL, + 0x0a726d2425a31L } }, + /* 188 */ + { { 0x6b3ee948c1086L,0x3dcbd3a2e1daeL,0x3d022f3f1de50L,0xf3923f35ed3f0L, + 0x013639e82cc6cL }, + { 0x938fbcdafaa86L,0xfb2654a2589acL,0x5051329f45bc5L,0x35a31963b26e4L, + 0x0ca9365e1c1a3L } }, + /* 189 */ + { { 0x5ac754c3b2d20L,0x17904e241b361L,0xc9d071d742a54L,0x72a5b08521c4cL, + 0x09ce29c34970bL }, + { 0x81f736d3e0ad6L,0x9ef2f8434c8ccL,0xce862d98060daL,0xaf9835ed1d1a6L, + 0x048c4abd7ab42L } }, + /* 190 */ + { { 0x1b0cc40c7485aL,0xbbe5274dbfd22L,0x263d2e8ead455L,0x33cb493c76989L, + 0x078017c32f67bL }, + { 0x35769930cb5eeL,0x940c408ed2b9dL,0x72f1a4dc0d14eL,0x1c04f8b7bf552L, + 0x053cd0454de5cL } }, + /* 191 */ + { { 0x585fa5d28ccacL,0x56005b746ebcdL,0xd0123aa5f823eL,0xfa8f7c79f0a1cL, + 0x0eea465c1d3d7L }, + { 0x0659f0551803bL,0x9f7ce6af70781L,0x9288e706c0b59L,0x91934195a7702L, + 0x01b6e42a47ae6L } }, + /* 192 */ + { { 0x0937cf67d04c3L,0xe289eeb8112e8L,0x2594d601e312bL,0xbd3d56b5d8879L, + 0x00224da14187fL }, + { 0xbb8630c5fe36fL,0x604ef51f5f87aL,0x3b429ec580f3cL,0xff33964fb1bfbL, + 0x060838ef042bfL } }, + /* 193 */ + { { 0xcb2f27e0bbe99L,0xf304aa39ee432L,0xfa939037bda44L,0x16435f497c7a9L, + 0x0636eb2022d33L }, + { 0xd0e6193ae00aaL,0xfe31ae6d2ffcfL,0xf93901c875a00L,0x8bacf43658a29L, + 0x08844eeb63921L } }, + /* 194 */ + { { 0x171d26b3bae58L,0x7117e39f3e114L,0x1a8eada7db3dfL,0x789ecd37bc7f8L, + 0x027ba83dc51fbL }, + { 0xf439ffbf54de5L,0x0bb5fe1a71a7dL,0xb297a48727703L,0xa4ab42ee8e35dL, + 0x0adb62d3487f3L } }, + /* 195 */ + { { 0x168a2a175df2aL,0x4f618c32e99b1L,0x46b0916082aa0L,0xc8b2c9e4f2e71L, + 0x0b990fd7675e7L }, + { 0x9d96b4df37313L,0x79d0b40789082L,0x80877111c2055L,0xd18d66c9ae4a7L, + 0x081707ef94d10L } }, + /* 196 */ + { { 0x7cab203d6ff96L,0xfc0d84336097dL,0x042db4b5b851bL,0xaa5c268823c4dL, + 0x03792daead5a8L }, + { 0x18865941afa0bL,0x4142d83671528L,0xbe4e0a7f3e9e7L,0x01ba17c825275L, + 0x05abd635e94b0L } }, + /* 197 */ + { { 0xfa84e0ac4927cL,0x35a7c8cf23727L,0xadca0dfe38860L,0xb610a4bcd5ea4L, + 0x05995bf21846aL }, + { 0xf860b829dfa33L,0xae958fc18be90L,0x8630366caafe2L,0x411e9b3baf447L, + 0x044c32ca2d483L } }, + /* 198 */ + { { 0xa97f1e40ed80cL,0xb131d2ca82a74L,0xc2d6ad95f938cL,0xa54c53f2124b7L, + 0x01f2162fb8082L }, + { 0x67cc5720b173eL,0x66085f12f97e4L,0xc9d65dc40e8a6L,0x07c98cebc20e4L, + 0x08f1d402bc3e9L } }, + /* 199 */ + { { 0x92f9cfbc4058aL,0xb6292f56704f5L,0xc1d8c57b15e14L,0xdbf9c55cfe37bL, + 0x0b1980f43926eL }, + { 0x33e0932c76b09L,0x9d33b07f7898cL,0x63bb4611df527L,0x8e456f08ead48L, + 0x02828ad9b3744L } }, + /* 200 */ + { { 0x722c4c4cf4ac5L,0x3fdde64afb696L,0x0890832f5ac1aL,0xb3900551baa2eL, + 0x04973f1275a14L }, + { 0xd8335322eac5dL,0xf50bd9b568e59L,0x25883935e07eeL,0x8ac7ab36720faL, + 0x06dac8ed0db16L } }, + /* 201 */ + { { 0x545aeeda835efL,0xd21d10ed51f7bL,0x3741b094aa113L,0xde4c035a65e01L, + 0x04b23ef5920b9L }, + { 0xbb6803c4c7341L,0x6d3f58bc37e82L,0x51e3ee8d45770L,0x9a4e73527863aL, + 0x04dd71534ddf4L } }, + /* 202 */ + { { 0x4467295476cd9L,0x2fe31a725bbf9L,0xc4b67e0648d07L,0x4dbb1441c8b8fL, + 0x0fd3170002f4aL }, + { 0x43ff48995d0e1L,0xd10ef729aa1cbL,0x179898276e695L,0xf365e0d5f9764L, + 0x014fac58c9569L } }, + /* 203 */ + { { 0xa0065f312ae18L,0xc0fcc93fc9ad9L,0xa7d284651958dL,0xda50d9a142408L, + 0x0ed7c765136abL }, + { 0x70f1a25d4abbcL,0xf3f1a113ea462L,0xb51952f9b5dd8L,0x9f53c609b0755L, + 0x0fefcb7f74d2eL } }, + /* 204 */ + { { 0x9497aba119185L,0x30aac45ba4bd0L,0xa521179d54e8cL,0xd80b492479deaL, + 0x01801a57e87e0L }, + { 0xd3f8dfcafffb0L,0x0bae255240073L,0xb5fdfbc6cf33cL,0x1064781d763b5L, + 0x09f8fc11e1eadL } }, + /* 205 */ + { { 0x3a1715e69544cL,0x67f04b7813158L,0x78a4c320eaf85L,0x69a91e22a8fd2L, + 0x0a9d3809d3d3aL }, + { 0xc2c2c59a2da3bL,0xf61895c847936L,0x3d5086938ccbcL,0x8ef75e65244e6L, + 0x03006b9aee117L } }, + /* 206 */ + { { 0x1f2b0c9eead28L,0x5d89f4dfbc0bbL,0x2ce89397eef63L,0xf761074757fdbL, + 0x00ab85fd745f8L }, + { 0xa7c933e5b4549L,0x5c97922f21ecdL,0x43b80404be2bbL,0x42c2261a1274bL, + 0x0b122d67511e9L } }, + /* 207 */ + { { 0x607be66a5ae7aL,0xfa76adcbe33beL,0xeb6e5c501e703L,0xbaecaf9043014L, + 0x09f599dc1097dL }, + { 0x5b7180ff250edL,0x74349a20dc6d7L,0x0b227a38eb915L,0x4b78425605a41L, + 0x07d5528e08a29L } }, + /* 208 */ + { { 0x58f6620c26defL,0xea582b2d1ef0fL,0x1ce3881025585L,0x1730fbe7d79b0L, + 0x028ccea01303fL }, + { 0xabcd179644ba5L,0xe806fff0b8d1dL,0x6b3e17b1fc643L,0x13bfa60a76fc6L, + 0x0c18baf48a1d0L } }, + /* 209 */ + { { 0x638c85dc4216dL,0x67206142ac34eL,0x5f5064a00c010L,0x596bd453a1719L, + 0x09def809db7a9L }, + { 0x8642e67ab8d2cL,0x336237a2b641eL,0x4c4218bb42404L,0x8ce57d506a6d6L, + 0x00357f8b06880L } }, + /* 210 */ + { { 0xdbe644cd2cc88L,0x8df0b8f39d8e9L,0xd30a0c8cc61c2L,0x98874a309874cL, + 0x0e4a01add1b48L }, + { 0x1eeacf57cd8f9L,0x3ebd594c482edL,0xbd2f7871b767dL,0xcc30a7295c717L, + 0x0466d7d79ce10L } }, + /* 211 */ + { { 0x318929dada2c7L,0xc38f9aa27d47dL,0x20a59e14fa0a6L,0xad1a90e4fd288L, + 0x0c672a522451eL }, + { 0x07cc85d86b655L,0x3bf9ad4af1306L,0x71172a6f0235dL,0x751399a086805L, + 0x05e3d64faf2a6L } }, + /* 212 */ + { { 0x410c79b3b4416L,0x85eab26d99aa6L,0xb656a74cd8fcfL,0x42fc5ebff74adL, + 0x06c8a7a95eb8eL }, + { 0x60ba7b02a63bdL,0x038b8f004710cL,0x12d90b06b2f23L,0xca918c6c37383L, + 0x0348ae422ad82L } }, + /* 213 */ + { { 0x746635ccda2fbL,0xa18e0726d27f4L,0x92b1f2022accaL,0x2d2e85adf7824L, + 0x0c1074de0d9efL }, + { 0x3ce44ae9a65b3L,0xac05d7151bfcfL,0xe6a9788fd71e4L,0x4ffcd4711f50cL, + 0x0fbadfbdbc9e5L } }, + /* 214 */ + { { 0x3f1cd20a99363L,0x8f6cf22775171L,0x4d359b2b91565L,0x6fcd968175cd2L, + 0x0b7f976b48371L }, + { 0x8e24d5d6dbf74L,0xfd71c3af36575L,0x243dfe38d23baL,0xc80548f477600L, + 0x0f4d41b2ecafcL } }, + /* 215 */ + { { 0x1cf28fdabd48dL,0x3632c078a451fL,0x17146e9ce81beL,0x0f106ace29741L, + 0x0180824eae016L }, + { 0x7698b66e58358L,0x52ce6ca358038L,0xe41e6c5635687L,0x6d2582380e345L, + 0x067e5f63983cfL } }, + /* 216 */ + { { 0xccb8dcf4899efL,0xf09ebb44c0f89L,0x2598ec9949015L,0x1fc6546f9276bL, + 0x09fef789a04c1L }, + { 0x67ecf53d2a071L,0x7fa4519b096d3L,0x11e2eefb10e1aL,0x4e20ca6b3fb06L, + 0x0bc80c181a99cL } }, + /* 217 */ + { { 0x536f8e5eb82e6L,0xc7f56cb920972L,0x0b5da5e1a484fL,0xdf10c78e21715L, + 0x049270e629f8cL }, + { 0x9b7bbea6b50adL,0xc1a2388ffc1a3L,0x107197b9a0284L,0x2f7f5403eb178L, + 0x0d2ee52f96137L } }, + /* 218 */ + { { 0xcd28588e0362aL,0xa78fa5d94dd37L,0x434a526442fa8L,0xb733aff836e5aL, + 0x0dfb478bee5abL }, + { 0xf1ce7673eede6L,0xd42b5b2f04a91L,0x530da2fa5390aL,0x473a5e66f7bf5L, + 0x0d9a140b408dfL } }, + /* 219 */ + { { 0x221b56e8ea498L,0x293563ee090e0L,0x35d2ade623478L,0x4b1ae06b83913L, + 0x0760c058d623fL }, + { 0x9b58cc198aa79L,0xd2f07aba7f0b8L,0xde2556af74890L,0x04094e204110fL, + 0x07141982d8f19L } }, + /* 220 */ + { { 0xa0e334d4b0f45L,0x38392a94e16f0L,0x3c61d5ed9280bL,0x4e473af324c6bL, + 0x03af9d1ce89d5L }, + { 0xf798120930371L,0x4c21c17097fd8L,0xc42309beda266L,0x7dd60e9545dcdL, + 0x0b1f815c37395L } }, + /* 221 */ + { { 0xaa78e89fec44aL,0x473caa4caf84fL,0x1b6a624c8c2aeL,0xf052691c807dcL, + 0x0a41aed141543L }, + { 0x353997d5ffe04L,0xdf625b6e20424L,0x78177758bacb2L,0x60ef85d660be8L, + 0x0d6e9c1dd86fbL } }, + /* 222 */ + { { 0x2e97ec6853264L,0xb7e2304a0b3aaL,0x8eae9be771533L,0xf8c21b912bb7bL, + 0x09c9c6e10ae9bL }, + { 0x09a59e030b74cL,0x4d6a631e90a23L,0x49b79f24ed749L,0x61b689f44b23aL, + 0x0566bd59640faL } }, + /* 223 */ + { { 0xc0118c18061f3L,0xd37c83fc70066L,0x7273245190b25L,0x345ef05fc8e02L, + 0x0cf2c7390f525L }, + { 0xbceb410eb30cfL,0xba0d77703aa09L,0x50ff255cfd2ebL,0x0979e842c43a1L, + 0x002f517558aa2L } }, + /* 224 */ + { { 0xef794addb7d07L,0x4224455500396L,0x78aa3ce0b4fc7L,0xd97dfaff8eaccL, + 0x014e9ada5e8d4L }, + { 0x480a12f7079e2L,0xcde4b0800edaaL,0x838157d45baa3L,0x9ae801765e2d7L, + 0x0a0ad4fab8e9dL } }, + /* 225 */ + { { 0xb76214a653618L,0x3c31eaaa5f0bfL,0x4949d5e187281L,0xed1e1553e7374L, + 0x0bcd530b86e56L }, + { 0xbe85332e9c47bL,0xfeb50059ab169L,0x92bfbb4dc2776L,0x341dcdba97611L, + 0x0909283cf6979L } }, + /* 226 */ + { { 0x0032476e81a13L,0x996217123967bL,0x32e19d69bee1aL,0x549a08ed361bdL, + 0x035eeb7c9ace1L }, + { 0x0ae5a7e4e5bdcL,0xd3b6ceec6e128L,0xe266bc12dcd2cL,0xe86452e4224c6L, + 0x09a8b2cf4448aL } }, + /* 227 */ + { { 0x71bf209d03b59L,0xa3b65af2abf64L,0xbd5eec9c90e62L,0x1379ff7ff168eL, + 0x06bdb60f4d449L }, + { 0xafebc8a55bc30L,0x1610097fe0dadL,0xc1e3bddc79eadL,0x08a942e197414L, + 0x001ec3cfd94baL } }, + /* 228 */ + { { 0x277ebdc9485c2L,0x7922fb10c7ba6L,0x0a28d8a48cc9aL,0x64f64f61d60f7L, + 0x0d1acb1c04754L }, + { 0x902b126f36612L,0x4ee0618d8bd26L,0x08357ee59c3a4L,0x26c24df8a8133L, + 0x07dcd079d4056L } }, + /* 229 */ + { { 0x7d4d3f05a4b48L,0x52372307725ceL,0x12a915aadcd29L,0x19b8d18f79718L, + 0x00bf53589377dL }, + { 0xcd95a6c68ea73L,0xca823a584d35eL,0x473a723c7f3bbL,0x86fc9fb674c6fL, + 0x0d28be4d9e166L } }, + /* 230 */ + { { 0xb990638fa8e4bL,0x6e893fd8fc5d2L,0x36fb6fc559f18L,0x88ce3a6de2aa4L, + 0x0d76007aa510fL }, + { 0x0aab6523a4988L,0x4474dd02732d1L,0x3407278b455cfL,0xbb017f467082aL, + 0x0f2b52f68b303L } }, + /* 231 */ + { { 0x7eafa9835b4caL,0xfcbb669cbc0d5L,0x66431982d2232L,0xed3a8eeeb680cL, + 0x0d8dbe98ecc5aL }, + { 0x9be3fc5a02709L,0xe5f5ba1fa8cbaL,0x10ea85230be68L,0x9705febd43cdfL, + 0x0e01593a3ee55L } }, + /* 232 */ + { { 0x5af50ea75a0a6L,0xac57858033d3eL,0x0176406512226L,0xef066fe6d50fdL, + 0x0afec07b1aeb8L }, + { 0x9956780bb0a31L,0xcc37309aae7fbL,0x1abf3896f1af3L,0xbfdd9153a15a0L, + 0x0a71b93546e2dL } }, + /* 233 */ + { { 0xe12e018f593d2L,0x28a078122bbf8L,0xba4f2add1a904L,0x23d9150505db0L, + 0x053a2005c6285L }, + { 0x8b639e7f2b935L,0x5ac182961a07cL,0x518ca2c2bff97L,0x8e3d86bceea77L, + 0x0bf47d19b3d58L } }, + /* 234 */ + { { 0x967a7dd7665d5L,0x572f2f4de5672L,0x0d4903f4e3030L,0xa1b6144005ae8L, + 0x0001c2c7f39c9L }, + { 0xa801469efc6d6L,0xaa7bc7a724143L,0x78150a4c810bdL,0xb99b5f65670baL, + 0x0fdadf8e786ffL } }, + /* 235 */ + { { 0x8cb88ffc00785L,0x913b48eb67fd3L,0xf368fbc77fa75L,0x3c940454d055bL, + 0x03a838e4d5aa4L }, + { 0x663293e97bb9aL,0x63441d94d9561L,0xadb2a839eb933L,0x1da3515591a60L, + 0x03cdb8257873eL } }, + /* 236 */ + { { 0x140a97de77eabL,0x0d41648109137L,0xeb1d0dff7e1c5L,0x7fba762dcad2cL, + 0x05a60cc89f1f5L }, + { 0x3638240d45673L,0x195913c65580bL,0xd64b7411b82beL,0x8fc0057284b8dL, + 0x0922ff56fdbfdL } }, + /* 237 */ + { { 0x65deec9a129a1L,0x57cc284e041b2L,0xebfbe3ca5b1ceL,0xcd6204380c46cL, + 0x072919a7df6c5L }, + { 0xf453a8fb90f9aL,0x0b88e4031b298L,0x96f1856d719c0L,0x089ae32c0e777L, + 0x05e7917803624L } }, + /* 238 */ + { { 0x6ec557f63cdfbL,0x71f1cae4fd5c1L,0x60597ca8e6a35L,0x2fabfce26bea5L, + 0x04e0a5371e24cL }, + { 0xa40d3a5765357L,0x440d73a2b4276L,0x1d11a323c89afL,0x04eeb8f370ae4L, + 0x0f5ff7818d566L } }, + /* 239 */ + { { 0x3e3fe1a09df21L,0x8ee66e8e47fbfL,0x9c8901526d5d2L,0x5e642096bd0a2L, + 0x0e41df0e9533fL }, + { 0xfda40b3ba9e3fL,0xeb2604d895305L,0xf0367c7f2340cL,0x155f0866e1927L, + 0x08edd7d6eac4fL } }, + /* 240 */ + { { 0x1dc0e0bfc8ff3L,0x2be936f42fc9aL,0xca381ef14efd8L,0xee9667016f7ccL, + 0x01432c1caed8aL }, + { 0x8482970b23c26L,0x730735b273ec6L,0xaef0f5aa64fe8L,0xd2c6e389f6e5eL, + 0x0caef480b5ac8L } }, + /* 241 */ + { { 0x5c97875315922L,0x713063cca5524L,0x64ef2cbd82951L,0xe236f3ce60d0bL, + 0x0d0ba177e8efaL }, + { 0x9ae8fb1b3af60L,0xe53d2da20e53aL,0xf9eef281a796aL,0xae1601d63605dL, + 0x0f31c957c1c54L } }, + /* 242 */ + { { 0x58d5249cc4597L,0xb0bae0a028c0fL,0x34a814adc5015L,0x7c3aefc5fc557L, + 0x0013404cb96e1L }, + { 0xe2585c9a824bfL,0x5e001eaed7b29L,0x1ef68acd59318L,0x3e6c8d6ee6826L, + 0x06f377c4b9193L } }, + /* 243 */ + { { 0x3bad1a8333fd2L,0x025a2a95b89f9L,0xaf75acea89302L,0x9506211e5037eL, + 0x06dba3e4ed2d0L }, + { 0xef98cd04399cdL,0x6ee6b73adea48L,0x17ecaf31811c6L,0xf4a772f60752cL, + 0x0f13cf3423becL } }, + /* 244 */ + { { 0xb9ec0a919e2ebL,0x95f62c0f68ceeL,0xaba229983a9a1L,0xbad3cfba3bb67L, + 0x0c83fa9a9274bL }, + { 0xd1b0b62fa1ce0L,0xf53418efbf0d7L,0x2706f04e58b60L,0x2683bfa8ef9e5L, + 0x0b49d70f45d70L } }, + /* 245 */ + { { 0xc7510fad5513bL,0xecb1751e2d914L,0x9fb9d5905f32eL,0xf1cf6d850418dL, + 0x059cfadbb0c30L }, + { 0x7ac2355cb7fd6L,0xb8820426a3e16L,0x0a78864249367L,0x4b67eaeec58c9L, + 0x05babf362354aL } }, + /* 246 */ + { { 0x981d1ee424865L,0x78f2e5577f37cL,0x9e0c0588b0028L,0xc8f0702970f1bL, + 0x06188c6a79026L }, + { 0x9a19bd0f244daL,0x5cfb08087306fL,0xf2136371eccedL,0xb9d935470f9b9L, + 0x0993fe475df50L } }, + /* 247 */ + { { 0x31cdf9b2c3609L,0xc02c46d4ea68eL,0xa77510184eb19L,0x616b7ac9ec1a9L, + 0x081f764664c80L }, + { 0xc2a5a75fbe978L,0xd3f183b3561d7L,0x01dd2bf6743feL,0x060d838d1f045L, + 0x0564a812a5fe9L } }, + /* 248 */ + { { 0xa64f4fa817d1dL,0x44bea82e0f7a5L,0xd57f9aa55f968L,0x1d6cb5ff5a0fcL, + 0x0226bf3cf00e5L }, + { 0x1a9f92f2833cfL,0x5a4f4f89a8d6dL,0xf3f7f7720a0a3L,0x783611536c498L, + 0x068779f47ff25L } }, + /* 249 */ + { { 0x0c1c173043d08L,0x741fc020fa79bL,0xa6d26d0a54467L,0x2e0bd3767e289L, + 0x097bcb0d1eb09L }, + { 0x6eaa8f32ed3c3L,0x51b281bc482abL,0xfa178f3c8a4f1L,0x46554d1bf4f3bL, + 0x0a872ffe80a78L } }, + /* 250 */ + { { 0xb7935a32b2086L,0x0e8160f486b1aL,0xb6ae6bee1eb71L,0xa36a9bd0cd913L, + 0x002812bfcb732L }, + { 0xfd7cacf605318L,0x50fdfd6d1da63L,0x102d619646e5dL,0x96afa1d683982L, + 0x007391cc9fe53L } }, + /* 251 */ + { { 0x157f08b80d02bL,0xd162877f7fc50L,0x8d542ae6b8333L,0x2a087aca1af87L, + 0x0355d2adc7e6dL }, + { 0xf335a287386e1L,0x94f8e43275b41L,0x79989eafd272aL,0x3a79286ca2cdeL, + 0x03dc2b1e37c2aL } }, + /* 252 */ + { { 0x9d21c04581352L,0x25376782bed68L,0xfed701f0a00c8L,0x846b203bd5909L, + 0x0c47869103ccdL }, + { 0xa770824c768edL,0x026841f6575dbL,0xaccce0e72feeaL,0x4d3273313ed56L, + 0x0ccc42968d5bbL } }, + /* 253 */ + { { 0x50de13d7620b9L,0x8a5992a56a94eL,0x75487c9d89a5cL,0x71cfdc0076406L, + 0x0e147eb42aa48L }, + { 0xab4eeacf3ae46L,0xfb50350fbe274L,0x8c840eafd4936L,0x96e3df2afe474L, + 0x0239ac047080eL } }, + /* 254 */ + { { 0xd1f352bfee8d4L,0xcffa7b0fec481L,0xce9af3cce80b5L,0xe59d105c4c9e2L, + 0x0c55fa1a3f5f7L }, + { 0x6f14e8257c227L,0x3f342be00b318L,0xa904fb2c5b165L,0xb69909afc998aL, + 0x0094cd99cd4f4L } }, + /* 255 */ + { { 0x81c84d703bebaL,0x5032ceb2918a9L,0x3bd49ec8631d1L,0xad33a445f2c9eL, + 0x0b90a30b642abL }, + { 0x5404fb4a5abf9L,0xc375db7603b46L,0xa35d89f004750L,0x24f76f9a42cccL, + 0x0019f8b9a1b79L } }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const 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 coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[5]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_256_point_new_5(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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); + + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_5(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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 || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_add_one_5(sp_digit* a) +{ + a[0]++; + sp_256_norm_5(a); +} + +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 44U) { + r[j] &= 0xfffffffffffffL; + s = 52U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; 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, (int)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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[5]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 inf; +#endif +#endif + sp_point_256* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity; +#endif + int err; + + (void)heap; + + err = sp_256_point_new_5(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_point_new_5(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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) { + err = sp_256_ecc_mulmod_base_5(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_5(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_256_iszero_5(point->x) == 0) || (sp_256_iszero_5(point->y) == 0)) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_256_point_free_5(infinity, 1, heap); +#endif + sp_256_point_free_5(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte array. + * 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; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 52) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 52); + if (j >= 0) { + 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[5]; +#endif + sp_point_256* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 32U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_256_point_new_5(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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); + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_5(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#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. + */ +SP_NOINLINE static void sp_256_mul_d_5(sp_digit* r, const sp_digit* a, + 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 */ +} + +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_256_div_word_5(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 52 bits from d1 and top 11 bits from d0. */ + d = (d1 << 11) | (d0 >> 41); + r = d / dv; + d -= r * dv; + /* Up to 12 bits in r */ + /* Next 11 bits from d0. */ + r <<= 11; + d <<= 11; + d |= (d0 >> 30) & ((1 << 11) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 23 bits in r */ + /* Next 11 bits from d0. */ + r <<= 11; + d <<= 11; + d |= (d0 >> 19) & ((1 << 11) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 34 bits in r */ + /* Next 11 bits from d0. */ + r <<= 11; + d <<= 11; + d |= (d0 >> 8) & ((1 << 11) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 45 bits in r */ + /* Remaining 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= d0 & ((1 << 8) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* 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 Number 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(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[10], t2d[5 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 5 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 2 * 5; +#else + t1 = t1d; + t2 = t2d; +#endif + + dv = d[4]; + XMEMCPY(t1, a, sizeof(*t1) * 2U * 5U); + for (i=4; i>=0; i--) { + t1[5 + i] += t1[5 + i - 1] >> 52; + t1[5 + i - 1] &= 0xfffffffffffffL; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[5 + i]; + d1 <<= 52; + d1 += t1[5 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_256_div_word_5(t1[5 + i], t1[5 + i - 1], dv); +#endif + + sp_256_mul_d_5(t2, d, r1); + (void)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]) / dv; + r1++; + sp_256_mul_d_5(t2, d, r1); + (void)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; + r1 = t1[5 - 1] / dv; + + sp_256_mul_d_5(t2, d, r1); + (void)sp_256_sub_5(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 5U); + 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) ? + (sp_digit)1 : (sp_digit)0)); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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, const sp_digit* a, const 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_minus_2[4] = { + 0xf3b9cac2fc63254fU,0xbce6faada7179e84U,0xffffffffffffffffU, + 0xffffffff00000000U +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint64_t p256_order_low[2] = { + 0xf3b9cac2fc63254fU,0xbce6faada7179e84U +}; +#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, const sp_digit* a, const sp_digit* b) +{ + sp_256_mul_5(r, a, b); + sp_256_mont_reduce_order_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, const sp_digit* a) +{ + sp_256_sqr_5(r, a); + sp_256_mont_reduce_order_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, const 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_minus_2[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + sp_256_mont_mul_order_5(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 5U); +#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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 */ +} + +#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, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#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_256 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_256* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int64_t c; + int i; + + (void)heap; + + err = sp_256_point_new_5(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 5, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 5; + x = d + 2 * 5; + k = d + 4 * 5; + r = d + 6 * 5; + tmp = d + 8 * 5; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(e, 5, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 5, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_5(rng, k); + } + else { + sp_256_from_mp(k, 5, km); + mp_zero(km); + } + if (err == MP_OKAY) { + 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) * 5U); + sp_256_norm_5(r); + c = sp_256_cmp_5(r, p256_order); + sp_256_cond_sub_5(r, r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_5(r); + + /* Conv k to Montgomery form (mod order) */ + 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 */ + sp_256_mont_inv_order_5(kInv, k, tmp); + sp_256_norm_5(kInv); + + /* s = r * x + e */ + 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, 0L - (sp_digit)(c >= 0)); + sp_256_norm_5(s); + + /* s = s * k^-1 mod order */ + 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) == 0) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 5); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 5U); +#endif + sp_256_point_free_5(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_256 p1d; + sp_point_256 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p1; + sp_point_256* p2 = NULL; + sp_digit carry; + int64_t c; + int err; + + err = sp_256_point_new_5(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_256_point_new_5(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 5, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 5; + u2 = d + 2 * 5; + s = d + 4 * 5; + tmp = d + 6 * 5; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 5, hash, (int)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); + + { + 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); + { + 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); + } + + err = sp_256_ecc_mulmod_base_5(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_5(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + { + sp_256_proj_point_add_5(p1, p1, p2, tmp); + if (sp_256_iszero_5(p1->z)) { + if (sp_256_iszero_5(p1->x) && sp_256_iszero_5(p1->y)) { + sp_256_proj_point_dbl_5(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + } + + /* (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 = (int)(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 == 0) { + 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 = (int)(sp_256_cmp_5(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_256_point_free_5(p1, 0, heap); + sp_256_point_free_5(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_5(sp_point_256* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*5]; + sp_digit t2d[2*5]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 5; + t2 = d + 2 * 5; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_256_sqr_5(t1, point->y); + (void)sp_256_mod_5(t1, t1, p256_mod); + sp_256_sqr_5(t2, point->x); + (void)sp_256_mod_5(t2, t2, p256_mod); + sp_256_mul_5(t2, t2, point->x); + (void)sp_256_mod_5(t2, t2, p256_mod); + (void)sp_256_sub_5(t2, p256_mod, t2); + sp_256_mont_add_5(t1, t1, t2, p256_mod); + + sp_256_mont_add_5(t1, t1, point->x, p256_mod); + sp_256_mont_add_5(t1, t1, point->x, p256_mod); + sp_256_mont_add_5(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_5(t1, p256_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 pubd; +#endif + sp_point_256* pub; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_5(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 5, pX); + sp_256_from_mp(pub->y, 5, pY); + sp_256_from_bin(pub->z, 5, one, (int)sizeof(one)); + + err = sp_256_ecc_is_point_5(pub, NULL); + } + + sp_256_point_free_5(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[5]; + sp_point_256 pubd; + sp_point_256 pd; +#endif + sp_digit* priv = NULL; + sp_point_256* pub; + sp_point_256* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_5(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_256_point_new_5(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_256_from_mp(pub->x, 5, pX); + sp_256_from_mp(pub->y, 5, pY); + sp_256_from_bin(pub->z, 5, one, (int)sizeof(one)); + sp_256_from_mp(priv, 5, privm); + + /* Check point at infinitiy. */ + if ((sp_256_iszero_5(pub->x) != 0) && + (sp_256_iszero_5(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_5(pub->x, p256_mod) >= 0 || + sp_256_cmp_5(pub->y, p256_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_5(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_256_ecc_mulmod_5(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_256_iszero_5(p->x) == 0) || + (sp_256_iszero_5(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_256_ecc_mulmod_base_5(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_5(p->x, pub->x) != 0 || + sp_256_cmp_5(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_5(p, 0, heap); + sp_256_point_free_5(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 5 * 5]; + sp_point_256 pd; + sp_point_256 qd; +#endif + sp_digit* tmp; + sp_point_256* p; + sp_point_256* q = NULL; + int err; + + err = sp_256_point_new_5(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_256_point_new_5(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 5, pX); + sp_256_from_mp(p->y, 5, pY); + sp_256_from_mp(p->z, 5, pZ); + sp_256_from_mp(q->x, 5, qX); + sp_256_from_mp(q->y, 5, qY); + sp_256_from_mp(q->z, 5, qZ); + + sp_256_proj_point_add_5(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_5(q, 0, NULL); + sp_256_point_free_5(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 5 * 2]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_5(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 5, pX); + sp_256_from_mp(p->y, 5, pY); + sp_256_from_mp(p->z, 5, pZ); + + sp_256_proj_point_dbl_5(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_5(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 5 * 4]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_5(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 5, pX); + sp_256_from_mp(p->y, 5, pY); + sp_256_from_mp(p->z, 5, pZ); + + sp_256_map_5(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_5(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_5(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 5]; + sp_digit t2d[2 * 5]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 5; + t2 = d + 2 * 5; +#else + t1 = t1d; + t2 = t2d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_5(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_5(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_5(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_5(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_5(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_5(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_5(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_5(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_5(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_5(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 5]; + sp_digit yd[2 * 5]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 5; + y = d + 2 * 5; +#else + x = xd; + y = yd; +#endif + + sp_256_from_mp(x, 5, xm); + err = sp_256_mod_mul_norm_5(x, x, p256_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_5(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_5(y, y, x, p256_mod); + sp_256_mont_sub_5(y, y, x, p256_mod); + sp_256_mont_sub_5(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_5(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_5(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_5(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 5, 0, 5U * sizeof(sp_digit)); + sp_256_mont_reduce_5(y, p256_mod, p256_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_256_mont_sub_5(y, p256_mod, y, p256_mod); + } + + err = sp_256_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#ifdef WOLFSSL_SP_384 + +/* Point structure to use. */ +typedef struct sp_point_384 { + sp_digit x[2 * 7]; + sp_digit y[2 * 7]; + sp_digit z[2 * 7]; + int infinity; +} sp_point_384; + +/* The modulus (prime) of the curve P384. */ +static const sp_digit p384_mod[7] = { + 0x000000ffffffffL,0x7ffe0000000000L,0x7ffffffffbffffL,0x7fffffffffffffL, + 0x7fffffffffffffL,0x7fffffffffffffL,0x3fffffffffffffL +}; +/* The Montogmery normalizer for modulus of the curve P384. */ +static const sp_digit p384_norm_mod[7] = { + 0x7fffff00000001L,0x0001ffffffffffL,0x00000000040000L,0x00000000000000L, + 0x00000000000000L,0x00000000000000L,0x00000000000000L +}; +/* The Montogmery multiplier for modulus of the curve P384. */ +static sp_digit p384_mp_mod = 0x0000100000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P384. */ +static const sp_digit p384_order[7] = { + 0x6c196accc52973L,0x1b6491614ef5d9L,0x07d0dcb77d6068L,0x7ffffffe3b1a6cL, + 0x7fffffffffffffL,0x7fffffffffffffL,0x3fffffffffffffL +}; +#endif +/* The order of the curve P384 minus 2. */ +static const sp_digit p384_order2[7] = { + 0x6c196accc52971L,0x1b6491614ef5d9L,0x07d0dcb77d6068L,0x7ffffffe3b1a6cL, + 0x7fffffffffffffL,0x7fffffffffffffL,0x3fffffffffffffL +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P384. */ +static const sp_digit p384_norm_order[7] = { + 0x13e695333ad68dL,0x649b6e9eb10a26L,0x782f2348829f97L,0x00000001c4e593L, + 0x00000000000000L,0x00000000000000L,0x00000000000000L +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P384. */ +static sp_digit p384_mp_order = 0x546089e88fdc45l; +#endif +/* The base point of curve P384. */ +static const sp_point_384 p384_base = { + /* X ordinate */ + { + 0x545e3872760ab7L,0x64bb7eaa52d874L,0x020950a8e1540bL, + 0x5d3cdcc2cfba0fL,0x0ad746e1d3b628L,0x26f1d638e3de64L,0x2aa1f288afa2c1L, + 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x431d7c90ea0e5fL,0x639c3afd033af4L,0x4ed7c2e3002982L, + 0x44d0a3e74ed188L,0x2dc29f8f41dbd2L,0x0debb3d317f252L,0x0d85f792a5898bL, + 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x00000000000001L,0x00000000000000L,0x00000000000000L, + 0x00000000000000L,0x00000000000000L,0x00000000000000L,0x00000000000000L, + 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p384_b[7] = { + 0x05c8edd3ec2aefL,0x731b145da33a55L,0x3d404e1d6b1958L,0x740a089018a044L, + 0x02d19181d9c6efL,0x7c9311c0ad7c7fL,0x2ccc4be9f88fb9L +}; +#endif + +static int sp_384_point_new_ex_7(void* heap, sp_point_384* sp, sp_point_384** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_384_point_new_7(heap, sp, p) sp_384_point_new_ex_7((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_384_point_new_7(heap, sp, p) sp_384_point_new_ex_7((heap), &(sp), &(p)) +#endif + + +static void sp_384_point_free_7(sp_point_384* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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_384_mod_mul_norm_7(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* td; +#else + int64_t td[12]; + int64_t a32d[12]; +#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)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + a32 = td + 12; +#else + t = td; + a32 = a32d; +#endif + + a32[0] = (sp_digit)(a[0]) & 0xffffffffL; + a32[1] = (sp_digit)(a[0] >> 32U); + a32[1] |= a[1] << 23U; + a32[1] &= 0xffffffffL; + a32[2] = (sp_digit)(a[1] >> 9U) & 0xffffffffL; + a32[3] = (sp_digit)(a[1] >> 41U); + a32[3] |= a[2] << 14U; + a32[3] &= 0xffffffffL; + a32[4] = (sp_digit)(a[2] >> 18U) & 0xffffffffL; + a32[5] = (sp_digit)(a[2] >> 50U); + a32[5] |= a[3] << 5U; + a32[5] &= 0xffffffffL; + a32[6] = (sp_digit)(a[3] >> 27U); + a32[6] |= a[4] << 28U; + a32[6] &= 0xffffffffL; + a32[7] = (sp_digit)(a[4] >> 4U) & 0xffffffffL; + a32[8] = (sp_digit)(a[4] >> 36U); + a32[8] |= a[5] << 19U; + a32[8] &= 0xffffffffL; + a32[9] = (sp_digit)(a[5] >> 13U) & 0xffffffffL; + a32[10] = (sp_digit)(a[5] >> 45U); + a32[10] |= a[6] << 10U; + a32[10] &= 0xffffffffL; + a32[11] = (sp_digit)(a[6] >> 22U) & 0xffffffffL; + + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + a32[0] + a32[8] + a32[9] - a32[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - a32[0] + a32[1] - a32[8] + a32[10] + a32[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - a32[1] + a32[2] - a32[9] + a32[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + a32[0] - a32[2] + a32[3] + a32[8] + a32[9] - a32[10] - a32[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + a32[0] + a32[1] - a32[3] + a32[4] + a32[8] + 2 * a32[9] + a32[10] - 2 * a32[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + a32[1] + a32[2] - a32[4] + a32[5] + a32[9] + 2 * a32[10] + a32[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + a32[2] + a32[3] - a32[5] + a32[6] + a32[10] + 2 * a32[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + a32[3] + a32[4] - a32[6] + a32[7] + a32[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + a32[4] + a32[5] - a32[7] + a32[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + a32[5] + a32[6] - a32[8] + a32[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + a32[6] + a32[7] - a32[9] + a32[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + a32[7] + a32[8] - a32[10] + a32[11]; + + 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + + r[0] = t[0]; + r[0] |= t[1] << 32U; + r[0] &= 0x7fffffffffffffLL; + r[1] = (sp_digit)(t[1] >> 23); + r[1] |= t[2] << 9U; + r[1] |= t[3] << 41U; + r[1] &= 0x7fffffffffffffLL; + r[2] = (sp_digit)(t[3] >> 14); + r[2] |= t[4] << 18U; + r[2] |= t[5] << 50U; + r[2] &= 0x7fffffffffffffLL; + r[3] = (sp_digit)(t[5] >> 5); + r[3] |= t[6] << 27U; + r[3] &= 0x7fffffffffffffLL; + r[4] = (sp_digit)(t[6] >> 28); + r[4] |= t[7] << 4U; + r[4] |= t[8] << 36U; + r[4] &= 0x7fffffffffffffLL; + r[5] = (sp_digit)(t[8] >> 19); + r[5] |= t[9] << 13U; + r[5] |= t[10] << 45U; + r[5] &= 0x7fffffffffffffLL; + r[6] = (sp_digit)(t[10] >> 10); + r[6] |= t[11] << 22U; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 55 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 55 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0x7fffffffffffffL; + s = 55U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 55U) <= (word32)DIGIT_BIT) { + s += 55U; + r[j] &= 0x7fffffffffffffL; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 55) { + r[j] &= 0x7fffffffffffffL; + if (j + 1 >= size) { + break; + } + s = 55 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_7(sp_point_384* p, const 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_384_from_mp(p->x, 7, pm->x); + sp_384_from_mp(p->y, 7, pm->y); + sp_384_from_mp(p->z, 7, 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_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 55 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 7); + r->used = 7; + mp_clamp(r); +#elif DIGIT_BIT < 55 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 7; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 55) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 55 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 7; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 55 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 55 - s; + } + else { + s += 55; + } + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_7(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + +#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. + */ +SP_NOINLINE static void sp_384_mul_7(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[6]) * b[6]; + r[13] = (sp_digit)(c >> 55); + c = (c & 0x7fffffffffffffL) << 55; + for (k = 11; k >= 0; k--) { + for (i = 6; i >= 0; i--) { + j = k - i; + if (j >= 7) { + break; + } + if (j < 0) { + continue; + } + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 110; + r[k + 1] = (c >> 55) & 0x7fffffffffffffL; + c = (c & 0x7fffffffffffffL) << 55; + } + r[0] = (sp_digit)(c >> 55); +} + +#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. + */ +SP_NOINLINE static void sp_384_mul_7(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[ 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 t8 = ((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 t9 = ((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 t10 = ((int128_t)a[ 4]) * b[ 6] + + ((int128_t)a[ 5]) * b[ 5] + + ((int128_t)a[ 6]) * b[ 4]; + int128_t t11 = ((int128_t)a[ 5]) * b[ 6] + + ((int128_t)a[ 6]) * b[ 5]; + int128_t t12 = ((int128_t)a[ 6]) * b[ 6]; + + t1 += t0 >> 55; r[ 0] = t0 & 0x7fffffffffffffL; + t2 += t1 >> 55; r[ 1] = t1 & 0x7fffffffffffffL; + t3 += t2 >> 55; r[ 2] = t2 & 0x7fffffffffffffL; + t4 += t3 >> 55; r[ 3] = t3 & 0x7fffffffffffffL; + t5 += t4 >> 55; r[ 4] = t4 & 0x7fffffffffffffL; + t6 += t5 >> 55; r[ 5] = t5 & 0x7fffffffffffffL; + t7 += t6 >> 55; r[ 6] = t6 & 0x7fffffffffffffL; + t8 += t7 >> 55; r[ 7] = t7 & 0x7fffffffffffffL; + t9 += t8 >> 55; r[ 8] = t8 & 0x7fffffffffffffL; + t10 += t9 >> 55; r[ 9] = t9 & 0x7fffffffffffffL; + t11 += t10 >> 55; r[10] = t10 & 0x7fffffffffffffL; + t12 += t11 >> 55; r[11] = t11 & 0x7fffffffffffffL; + r[13] = (sp_digit)(t12 >> 55); + r[12] = t12 & 0x7fffffffffffffL; +} + +#endif /* WOLFSSL_SP_SMALL */ +#define sp_384_mont_reduce_order_7 sp_384_mont_reduce_7 + +/* 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_384_cmp_7(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=6; i>=0; i--) { + r |= (a[i] - b[i]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + r |= (a[ 6] - b[ 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 5] - b[ 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 4] - b[ 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 3] - b[ 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 2] - b[ 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 1] - b[ 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 0] - b[ 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); +#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_384_cond_sub_7(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 < 7; 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); +#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. + */ +SP_NOINLINE static void sp_384_mul_add_7(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 < 7; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x7fffffffffffffL; + t >>= 55; + } + r[7] += t; +#else + int128_t tb = b; + int128_t t[7]; + + 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]; + r[ 0] += (sp_digit) (t[ 0] & 0x7fffffffffffffL); + r[ 1] += (sp_digit)((t[ 0] >> 55) + (t[ 1] & 0x7fffffffffffffL)); + r[ 2] += (sp_digit)((t[ 1] >> 55) + (t[ 2] & 0x7fffffffffffffL)); + r[ 3] += (sp_digit)((t[ 2] >> 55) + (t[ 3] & 0x7fffffffffffffL)); + r[ 4] += (sp_digit)((t[ 3] >> 55) + (t[ 4] & 0x7fffffffffffffL)); + r[ 5] += (sp_digit)((t[ 4] >> 55) + (t[ 5] & 0x7fffffffffffffL)); + r[ 6] += (sp_digit)((t[ 5] >> 55) + (t[ 6] & 0x7fffffffffffffL)); + r[ 7] += (sp_digit) (t[ 6] >> 55); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 55. + * + * a Array of sp_digit to normalize. + */ +static void sp_384_norm_7(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 6; i++) { + a[i+1] += a[i] >> 55; + a[i] &= 0x7fffffffffffffL; + } +#else + a[1] += a[0] >> 55; a[0] &= 0x7fffffffffffffL; + a[2] += a[1] >> 55; a[1] &= 0x7fffffffffffffL; + a[3] += a[2] >> 55; a[2] &= 0x7fffffffffffffL; + a[4] += a[3] >> 55; a[3] &= 0x7fffffffffffffL; + a[5] += a[4] >> 55; a[4] &= 0x7fffffffffffffL; + a[6] += a[5] >> 55; a[5] &= 0x7fffffffffffffL; +#endif +} + +/* Shift the result in the high 384 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_384_mont_shift_7(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + word64 n; + + n = a[6] >> 54; + for (i = 0; i < 6; i++) { + n += (word64)a[7 + i] << 1; + r[i] = n & 0x7fffffffffffffL; + n >>= 55; + } + n += (word64)a[13] << 1; + r[6] = n; +#else + word64 n; + + n = a[6] >> 54; + n += (word64)a[ 7] << 1U; r[ 0] = n & 0x7fffffffffffffUL; n >>= 55U; + n += (word64)a[ 8] << 1U; r[ 1] = n & 0x7fffffffffffffUL; n >>= 55U; + n += (word64)a[ 9] << 1U; r[ 2] = n & 0x7fffffffffffffUL; n >>= 55U; + n += (word64)a[10] << 1U; r[ 3] = n & 0x7fffffffffffffUL; n >>= 55U; + n += (word64)a[11] << 1U; r[ 4] = n & 0x7fffffffffffffUL; n >>= 55U; + n += (word64)a[12] << 1U; r[ 5] = n & 0x7fffffffffffffUL; n >>= 55U; + n += (word64)a[13] << 1U; r[ 6] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[7], 0, sizeof(*r) * 7U); +} + +/* Reduce the number back to 384 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_384_mont_reduce_7(sp_digit* a, const sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + sp_384_norm_7(a + 7); + + for (i=0; i<6; i++) { + mu = (a[i] * mp) & 0x7fffffffffffffL; + sp_384_mul_add_7(a+i, m, mu); + a[i+1] += a[i] >> 55; + } + mu = (a[i] * mp) & 0x3fffffffffffffL; + sp_384_mul_add_7(a+i, m, mu); + a[i+1] += a[i] >> 55; + a[i] &= 0x7fffffffffffffL; + + sp_384_mont_shift_7(a, a); + sp_384_cond_sub_7(a, a, m, 0 - (((a[6] >> 54) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_7(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_384_mont_mul_7(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_384_mul_7(r, a, b); + sp_384_mont_reduce_7(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. + */ +SP_NOINLINE static void sp_384_sqr_7(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[6]) * a[6]; + r[13] = (sp_digit)(c >> 55); + c = (c & 0x7fffffffffffffL) << 55; + for (k = 11; k >= 0; k--) { + for (i = 6; i >= 0; i--) { + j = k - i; + if (j >= 7 || 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 >> 110; + r[k + 1] = (c >> 55) & 0x7fffffffffffffL; + c = (c & 0x7fffffffffffffL) << 55; + } + r[0] = (sp_digit)(c >> 55); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_sqr_7(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[ 1]) * a[ 6] + + ((int128_t)a[ 2]) * a[ 5] + + ((int128_t)a[ 3]) * a[ 4]) * 2; + int128_t t8 = (((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[ 3]) * a[ 6] + + ((int128_t)a[ 4]) * a[ 5]) * 2; + int128_t t10 = (((int128_t)a[ 4]) * a[ 6]) * 2 + + ((int128_t)a[ 5]) * a[ 5]; + int128_t t11 = (((int128_t)a[ 5]) * a[ 6]) * 2; + int128_t t12 = ((int128_t)a[ 6]) * a[ 6]; + + t1 += t0 >> 55; r[ 0] = t0 & 0x7fffffffffffffL; + t2 += t1 >> 55; r[ 1] = t1 & 0x7fffffffffffffL; + t3 += t2 >> 55; r[ 2] = t2 & 0x7fffffffffffffL; + t4 += t3 >> 55; r[ 3] = t3 & 0x7fffffffffffffL; + t5 += t4 >> 55; r[ 4] = t4 & 0x7fffffffffffffL; + t6 += t5 >> 55; r[ 5] = t5 & 0x7fffffffffffffL; + t7 += t6 >> 55; r[ 6] = t6 & 0x7fffffffffffffL; + t8 += t7 >> 55; r[ 7] = t7 & 0x7fffffffffffffL; + t9 += t8 >> 55; r[ 8] = t8 & 0x7fffffffffffffL; + t10 += t9 >> 55; r[ 9] = t9 & 0x7fffffffffffffL; + t11 += t10 >> 55; r[10] = t10 & 0x7fffffffffffffL; + t12 += t11 >> 55; r[11] = t11 & 0x7fffffffffffffL; + r[13] = (sp_digit)(t12 >> 55); + r[12] = t12 & 0x7fffffffffffffL; +} + +#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_384_mont_sqr_7(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_384_sqr_7(r, a); + sp_384_mont_reduce_7(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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_384_mont_sqr_n_7(sp_digit* r, const sp_digit* a, int n, + const sp_digit* m, sp_digit mp) +{ + sp_384_mont_sqr_7(r, a, m, mp); + for (; n > 1; n--) { + sp_384_mont_sqr_7(r, r, m, mp); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P384 curve. */ +static const uint64_t p384_mod_minus_2[6] = { + 0x00000000fffffffdU,0xffffffff00000000U,0xfffffffffffffffeU, + 0xffffffffffffffffU,0xffffffffffffffffU,0xffffffffffffffffU +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P384 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_384_mont_inv_7(sp_digit* r, const sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 7); + for (i=382; i>=0; i--) { + sp_384_mont_sqr_7(t, t, p384_mod, p384_mp_mod); + if (p384_mod_minus_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_384_mont_mul_7(t, t, a, p384_mod, p384_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 7); +#else + sp_digit* t1 = td; + sp_digit* t2 = td + 2 * 7; + sp_digit* t3 = td + 4 * 7; + sp_digit* t4 = td + 6 * 7; + sp_digit* t5 = td + 8 * 7; + + /* 0x2 */ + sp_384_mont_sqr_7(t1, a, p384_mod, p384_mp_mod); + /* 0x3 */ + sp_384_mont_mul_7(t5, t1, a, p384_mod, p384_mp_mod); + /* 0xc */ + sp_384_mont_sqr_n_7(t1, t5, 2, p384_mod, p384_mp_mod); + /* 0xf */ + sp_384_mont_mul_7(t2, t5, t1, p384_mod, p384_mp_mod); + /* 0x1e */ + sp_384_mont_sqr_7(t1, t2, p384_mod, p384_mp_mod); + /* 0x1f */ + sp_384_mont_mul_7(t4, t1, a, p384_mod, p384_mp_mod); + /* 0x3e0 */ + sp_384_mont_sqr_n_7(t1, t4, 5, p384_mod, p384_mp_mod); + /* 0x3ff */ + sp_384_mont_mul_7(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0x7fe0 */ + sp_384_mont_sqr_n_7(t1, t2, 5, p384_mod, p384_mp_mod); + /* 0x7fff */ + sp_384_mont_mul_7(t4, t4, t1, p384_mod, p384_mp_mod); + /* 0x3fff8000 */ + sp_384_mont_sqr_n_7(t1, t4, 15, p384_mod, p384_mp_mod); + /* 0x3fffffff */ + sp_384_mont_mul_7(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffc */ + sp_384_mont_sqr_n_7(t3, t2, 2, p384_mod, p384_mp_mod); + /* 0xfffffffd */ + sp_384_mont_mul_7(r, t3, a, p384_mod, p384_mp_mod); + /* 0xffffffff */ + sp_384_mont_mul_7(t3, t5, t3, p384_mod, p384_mp_mod); + /* 0xfffffffc0000000 */ + sp_384_mont_sqr_n_7(t1, t2, 30, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff */ + sp_384_mont_mul_7(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_7(t1, t2, 60, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_7(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_7(t1, t2, 120, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_7(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_7(t1, t2, 15, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_7(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */ + sp_384_mont_sqr_n_7(t1, t2, 33, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */ + sp_384_mont_mul_7(t2, t3, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_7(t1, t2, 96, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */ + sp_384_mont_mul_7(r, r, t1, p384_mod, p384_mp_mod); + +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_384_map_7(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*7; + int64_t n; + + sp_384_mont_inv_7(t1, p->z, t + 2*7); + + sp_384_mont_sqr_7(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t1, t2, t1, p384_mod, p384_mp_mod); + + /* x /= z^2 */ + sp_384_mont_mul_7(r->x, p->x, t2, p384_mod, p384_mp_mod); + XMEMSET(r->x + 7, 0, sizeof(r->x) / 2U); + sp_384_mont_reduce_7(r->x, p384_mod, p384_mp_mod); + /* Reduce x to less than modulus */ + n = sp_384_cmp_7(r->x, p384_mod); + sp_384_cond_sub_7(r->x, r->x, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_7(r->x); + + /* y /= z^3 */ + sp_384_mont_mul_7(r->y, p->y, t1, p384_mod, p384_mp_mod); + XMEMSET(r->y + 7, 0, sizeof(r->y) / 2U); + sp_384_mont_reduce_7(r->y, p384_mod, p384_mp_mod); + /* Reduce y to less than modulus */ + n = sp_384_cmp_7(r->y, p384_mod); + sp_384_cond_sub_7(r->y, r->y, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_7(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. + */ +SP_NOINLINE static int sp_384_add_7(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 7; 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. + */ +SP_NOINLINE static int sp_384_add_7(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]; + + 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_384_mont_add_7(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)sp_384_add_7(r, a, b); + sp_384_norm_7(r); + sp_384_cond_sub_7(r, r, m, 0 - (((r[6] >> 54) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_7(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_384_mont_dbl_7(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)sp_384_add_7(r, a, a); + sp_384_norm_7(r); + sp_384_cond_sub_7(r, r, m, 0 - (((r[6] >> 54) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_7(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_384_mont_tpl_7(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)sp_384_add_7(r, a, a); + sp_384_norm_7(r); + sp_384_cond_sub_7(r, r, m, 0 - (((r[6] >> 54) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_7(r); + (void)sp_384_add_7(r, r, a); + sp_384_norm_7(r); + sp_384_cond_sub_7(r, r, m, 0 - (((r[6] >> 54) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_7(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. + */ +SP_NOINLINE static int sp_384_sub_7(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 7; 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. + */ +SP_NOINLINE static int sp_384_sub_7(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]; + + 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_384_cond_add_7(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 < 7; 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); +#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_384_mont_sub_7(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)sp_384_sub_7(r, a, b); + sp_384_cond_add_7(r, r, m, r[6] >> 54); + sp_384_norm_7(r); +} + +/* Shift number left one bit. + * Bottom bit is lost. + * + * r Result of shift. + * a Number to shift. + */ +SP_NOINLINE static void sp_384_rshift1_7(sp_digit* r, sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<6; i++) { + r[i] = ((a[i] >> 1) | (a[i + 1] << 54)) & 0x7fffffffffffffL; + } +#else + r[0] = ((a[0] >> 1) | (a[1] << 54)) & 0x7fffffffffffffL; + r[1] = ((a[1] >> 1) | (a[2] << 54)) & 0x7fffffffffffffL; + r[2] = ((a[2] >> 1) | (a[3] << 54)) & 0x7fffffffffffffL; + r[3] = ((a[3] >> 1) | (a[4] << 54)) & 0x7fffffffffffffL; + r[4] = ((a[4] >> 1) | (a[5] << 54)) & 0x7fffffffffffffL; + r[5] = ((a[5] >> 1) | (a[6] << 54)) & 0x7fffffffffffffL; +#endif + r[6] = a[6] >> 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_384_div2_7(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_384_cond_add_7(r, a, m, 0 - (a[0] & 1)); + sp_384_norm_7(r); + sp_384_rshift1_7(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_384_proj_point_dbl_7(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*7; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_384_mont_sqr_7(t1, p->z, p384_mod, p384_mp_mod); + /* Z = Y * Z */ + sp_384_mont_mul_7(z, p->y, p->z, p384_mod, p384_mp_mod); + /* Z = 2Z */ + sp_384_mont_dbl_7(z, z, p384_mod); + /* T2 = X - T1 */ + sp_384_mont_sub_7(t2, p->x, t1, p384_mod); + /* T1 = X + T1 */ + sp_384_mont_add_7(t1, p->x, t1, p384_mod); + /* T2 = T1 * T2 */ + sp_384_mont_mul_7(t2, t1, t2, p384_mod, p384_mp_mod); + /* T1 = 3T2 */ + sp_384_mont_tpl_7(t1, t2, p384_mod); + /* Y = 2Y */ + sp_384_mont_dbl_7(y, p->y, p384_mod); + /* Y = Y * Y */ + sp_384_mont_sqr_7(y, y, p384_mod, p384_mp_mod); + /* T2 = Y * Y */ + sp_384_mont_sqr_7(t2, y, p384_mod, p384_mp_mod); + /* T2 = T2/2 */ + sp_384_div2_7(t2, t2, p384_mod); + /* Y = Y * X */ + sp_384_mont_mul_7(y, y, p->x, p384_mod, p384_mp_mod); + /* X = T1 * T1 */ + sp_384_mont_sqr_7(x, t1, p384_mod, p384_mp_mod); + /* X = X - Y */ + sp_384_mont_sub_7(x, x, y, p384_mod); + /* X = X - Y */ + sp_384_mont_sub_7(x, x, y, p384_mod); + /* Y = Y - X */ + sp_384_mont_sub_7(y, y, x, p384_mod); + /* Y = Y * T1 */ + sp_384_mont_mul_7(y, y, t1, p384_mod, p384_mp_mod); + /* Y = Y - T2 */ + sp_384_mont_sub_7(y, y, t2, p384_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_384_cmp_equal_7(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])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_7(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, + sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*7; + sp_digit* t3 = t + 4*7; + sp_digit* t4 = t + 6*7; + sp_digit* t5 = t + 8*7; + 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) { + const sp_point_384* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_384_sub_7(t1, p384_mod, q->y); + sp_384_norm_7(t1); + if ((sp_384_cmp_equal_7(p->x, q->x) & sp_384_cmp_equal_7(p->z, q->z) & + (sp_384_cmp_equal_7(p->y, q->y) | sp_384_cmp_equal_7(p->y, t1))) != 0) { + sp_384_proj_point_dbl_7(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<7; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<7; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<7; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_7(t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t3, t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t1, t1, x, p384_mod, p384_mp_mod); + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_7(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_7(t3, t3, y, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_7(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - U1 */ + sp_384_mont_sub_7(t2, t2, t1, p384_mod); + /* R = S2 - S1 */ + sp_384_mont_sub_7(t4, t4, t3, p384_mod); + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_7(z, z, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_7(x, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_7(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(y, t1, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_7(x, x, t5, p384_mod); + sp_384_mont_dbl_7(t1, y, p384_mod); + sp_384_mont_sub_7(x, x, t1, p384_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_7(y, y, x, p384_mod); + sp_384_mont_mul_7(y, y, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t5, t5, t3, p384_mod, p384_mp_mod); + sp_384_mont_sub_7(y, y, t5, p384_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_7(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifdef WOLFSSL_SP_NO_MALLOC + sp_point_384 t[3]; + sp_digit tmp[2 * 7 * 6]; +#else + sp_point_384* t; + sp_digit* tmp; +#endif + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + +#ifndef WOLFSSL_SP_NO_MALLOC + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_384) * 3); + + /* t[0] = {0, 0, 1} * norm */ + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_384_mod_mul_norm_7(t[1].x, g->x, p384_mod); + } + if (err == MP_OKAY) + err = sp_384_mod_mul_norm_7(t[1].y, g->y, p384_mod); + if (err == MP_OKAY) + err = sp_384_mod_mul_norm_7(t[1].z, g->z, p384_mod); + + if (err == MP_OKAY) { + i = 6; + c = 54; + n = k[i--] << (55 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 55; + } + + y = (n >> 54) & 1; + n <<= 1; + + sp_384_proj_point_add_7(&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_384)); + sp_384_proj_point_dbl_7(&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_384)); + } + + if (map != 0) { + sp_384_map_7(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_384)); + } + } + +#ifndef WOLFSSL_SP_NO_MALLOC + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 7 * 6); + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_384) * 3); + XFREE(t, NULL, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmp, sizeof(tmp)); + ForceZero(t, sizeof(t)); +#endif + + 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 coordinates. + * + * 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_384_ecc_mulmod_7(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 t[3]; + sp_digit tmp[2 * 7 * 6]; +#else + sp_point_384* t; + sp_digit* tmp; +#endif + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point*)XMALLOC(sizeof(*t) * 3, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#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 */ + t[1].infinity = 0; + err = sp_384_mod_mul_norm_7(t[1].x, g->x, p384_mod); + } + if (err == MP_OKAY) + err = sp_384_mod_mul_norm_7(t[1].y, g->y, p384_mod); + if (err == MP_OKAY) + err = sp_384_mod_mul_norm_7(t[1].z, g->z, p384_mod); + + if (err == MP_OKAY) { + i = 6; + c = 54; + n = k[i--] << (55 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 55; + } + + y = (n >> 54) & 1; + n <<= 1; + + sp_384_proj_point_add_7(&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_384_proj_point_dbl_7(&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 != 0) { + sp_384_map_7(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 7 * 6); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_384) * 3); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmp, sizeof(tmp)); + ForceZero(t, sizeof(t)); +#endif + + return err; +} + +#else +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_384 { + sp_digit x[7]; + sp_digit y[7]; +} sp_table_entry_384; + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_fast_7(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td[16]; + sp_point_384 rtd; + sp_digit tmpd[2 * 7 * 6]; +#endif + sp_point_384* t; + sp_point_384* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_384_point_new_7(heap, rtd, rt); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 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 */ + (void)sp_384_mod_mul_norm_7(t[1].x, g->x, p384_mod); + (void)sp_384_mod_mul_norm_7(t[1].y, g->y, p384_mod); + (void)sp_384_mod_mul_norm_7(t[1].z, g->z, p384_mod); + t[1].infinity = 0; + sp_384_proj_point_dbl_7(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_384_proj_point_add_7(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_384_proj_point_dbl_7(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_384_proj_point_add_7(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_384_proj_point_dbl_7(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_384_proj_point_add_7(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_384_proj_point_dbl_7(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_384_proj_point_add_7(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_384_proj_point_dbl_7(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_384_proj_point_add_7(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_384_proj_point_dbl_7(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_384_proj_point_add_7(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_384_proj_point_dbl_7(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_384_proj_point_add_7(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 5; + n = k[i+1] << 9; + c = 50; + y = n >> 59; + XMEMCPY(rt, &t[y], sizeof(sp_point_384)); + n <<= 5; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--] << (9 - c); + c += 55; + } + y = (n >> 60) & 0xf; + n <<= 4; + c -= 4; + + sp_384_proj_point_dbl_7(rt, rt, tmp); + sp_384_proj_point_dbl_7(rt, rt, tmp); + sp_384_proj_point_dbl_7(rt, rt, tmp); + sp_384_proj_point_dbl_7(rt, rt, tmp); + + sp_384_proj_point_add_7(rt, rt, &t[y], tmp); + } + + if (map != 0) { + sp_384_map_7(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 7 * 6); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_384) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_384_point_free_7(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_384_proj_point_dbl_n_7(sp_point_384* p, int n, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*7; + sp_digit* b = t + 4*7; + sp_digit* t1 = t + 6*7; + sp_digit* t2 = t + 8*7; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_384_mont_dbl_7(y, y, p384_mod); + /* W = Z^4 */ + sp_384_mont_sqr_7(w, z, p384_mod, p384_mp_mod); + sp_384_mont_sqr_7(w, w, p384_mod, p384_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_7(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_7(t1, t1, w, p384_mod); + sp_384_mont_tpl_7(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_7(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_7(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_7(t2, b, p384_mod); + sp_384_mont_sub_7(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_7(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_7(t1, t1, p384_mod, p384_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_384_mont_mul_7(w, w, t1, p384_mod, p384_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_7(y, b, x, p384_mod); + sp_384_mont_mul_7(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_7(y, y, p384_mod); + sp_384_mont_sub_7(y, y, t1, p384_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_7(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_7(t1, t1, w, p384_mod); + sp_384_mont_tpl_7(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_7(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_7(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_7(t2, b, p384_mod); + sp_384_mont_sub_7(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_7(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_7(t1, t1, p384_mod, p384_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_7(y, b, x, p384_mod); + sp_384_mont_mul_7(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_7(y, y, p384_mod); + sp_384_mont_sub_7(y, y, t1, p384_mod); +#endif + /* Y = Y/2 */ + sp_384_div2_7(y, y, p384_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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_qz1_7(sp_point_384* r, const sp_point_384* p, + const sp_point_384* q, sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*7; + sp_digit* t3 = t + 4*7; + sp_digit* t4 = t + 6*7; + sp_digit* t5 = t + 8*7; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_384_sub_7(t1, p384_mod, q->y); + sp_384_norm_7(t1); + if ((sp_384_cmp_equal_7(p->x, q->x) & sp_384_cmp_equal_7(p->z, q->z) & + (sp_384_cmp_equal_7(p->y, q->y) | sp_384_cmp_equal_7(p->y, t1))) != 0) { + sp_384_proj_point_dbl_7(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<7; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<7; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<7; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_7(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_7(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - X1 */ + sp_384_mont_sub_7(t2, t2, x, p384_mod); + /* R = S2 - Y1 */ + sp_384_mont_sub_7(t4, t4, y, p384_mod); + /* Z3 = H*Z1 */ + sp_384_mont_mul_7(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_384_mont_sqr_7(t1, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_7(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t3, x, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_7(x, t1, t5, p384_mod); + sp_384_mont_dbl_7(t1, t3, p384_mod); + sp_384_mont_sub_7(x, x, t1, p384_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_384_mont_sub_7(t3, t3, x, p384_mod); + sp_384_mont_mul_7(t3, t3, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t5, t5, y, p384_mod, p384_mp_mod); + sp_384_mont_sub_7(y, t3, t5, p384_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_384_proj_to_affine_7(sp_point_384* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 7; + sp_digit* tmp = t + 4 * 7; + + sp_384_mont_inv_7(t1, a->z, tmp); + + sp_384_mont_sqr_7(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(t1, t2, t1, p384_mod, p384_mp_mod); + + sp_384_mont_mul_7(a->x, a->x, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(a->y, a->y, t1, p384_mod, p384_mp_mod); + XMEMCPY(a->z, p384_norm_mod, sizeof(p384_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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_384_gen_stripe_table_7(const sp_point_384* a, + sp_table_entry_384* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td, s1d, s2d; +#endif + sp_point_384* t; + sp_point_384* s1 = NULL; + sp_point_384* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_384_point_new_7(heap, td, t); + if (err == MP_OKAY) { + err = sp_384_point_new_7(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_384_point_new_7(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_7(t->x, a->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_7(t->y, a->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_7(t->z, a->z, p384_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_384_proj_to_affine_7(t, tmp); + + XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_384)); + /* 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)); + + for (i=1; i<8; i++) { + sp_384_proj_point_dbl_n_7(t, 48, tmp); + sp_384_proj_to_affine_7(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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_384_proj_point_add_qz1_7(t, s1, s2, tmp); + sp_384_proj_to_affine_7(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_384_point_free_7(s2, 0, heap); + sp_384_point_free_7(s1, 0, heap); + sp_384_point_free_7( 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 coordinates. + * + * 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_384_ecc_mulmod_stripe_7(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 rtd; + sp_point_384 pd; + sp_digit td[2 * 7 * 6]; +#endif + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_384_point_new_7(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_384_point_new_7(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + y = 0; + for (j=0,x=47; j<8; j++,x+=48) { + y |= ((k[x / 55] >> (x % 55)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=46; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=48) { + y |= ((k[x / 55] >> (x % 55)) & 1) << j; + } + + sp_384_proj_point_dbl_7(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 = !y; + sp_384_proj_point_add_qz1_7(rt, rt, p, t); + } + + if (map != 0) { + sp_384_map_7(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_7(p, 0, heap); + sp_384_point_free_7(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_384_t { + sp_digit x[7]; + sp_digit y[7]; + sp_table_entry_384 table[256]; + uint32_t cnt; + int set; +} sp_cache_384_t; + +static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_384_last = -1; +static THREAD_LS_T int sp_cache_384_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_384 = 0; + static wolfSSL_Mutex sp_cache_384_lock; +#endif + +static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_384_inited == 0) { + for (i=0; ix, sp_cache_384[i].x) & + sp_384_cmp_equal_7(g->y, sp_cache_384[i].y)) { + sp_cache_384[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_384_last + 1) % FP_ENTRIES; + for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_384[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_384_last) { + least = sp_cache_384[0].cnt; + for (j=1; jx, sizeof(sp_cache_384[i].x)); + XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y)); + sp_cache_384[i].set = 1; + sp_cache_384[i].cnt = 1; + } + + *cache = &sp_cache_384[i]; + sp_cache_384_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_7(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_384_ecc_mulmod_fast_7(r, g, k, map, heap); +#else + sp_digit tmp[2 * 7 * 7]; + sp_cache_384_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_384 == 0) { + wc_InitMutex(&sp_cache_384_lock); + initCacheMutex_384 = 1; + } + if (wc_LockMutex(&sp_cache_384_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_384(g, &cache); + if (cache->cnt == 2) + sp_384_gen_stripe_table_7(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_384_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_384_ecc_mulmod_fast_7(r, g, k, map, heap); + } + else { + err = sp_384_ecc_mulmod_stripe_7(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 coordinates. + * + * 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_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[7]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_384_point_new_7(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 7, km); + sp_384_point_from_ecc_point_7(point, gm); + + err = sp_384_ecc_mulmod_7(point, point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_7(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_7(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_7(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + /* No pre-computed values. */ + return sp_384_ecc_mulmod_7(r, &p384_base, k, map, heap); +} + +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_7(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + /* No pre-computed values. */ + return sp_384_ecc_mulmod_7(r, &p384_base, k, map, heap); +} + +#else +static const sp_table_entry_384 p384_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x50756649c0b528L,0x71c541ad9c707bL,0x71506d35b8838dL, + 0x4d1877fc3ce1d7L,0x6de2b645486845L,0x227025fee46c29L, + 0x134eab708a6785L }, + { 0x043dad4b03a4feL,0x517ef769535846L,0x58ba0ec14286feL, + 0x47a7fecc5d6f3aL,0x1a840c6c352196L,0x3d3bb00044c72dL, + 0x0ade2af0968571L } }, + /* 2 */ + { { 0x0647532b0c535bL,0x52a6e0a0c52c53L,0x5085aae6b24375L, + 0x7096bb501c66b5L,0x47bdb3df9b7b7bL,0x11227e9b2f0be6L, + 0x088b172704fa51L }, + { 0x0e796f2680dc64L,0x796eb06a482ebfL,0x2b441d02e04839L, + 0x19bef7312a5aecL,0x02247c38b8efb5L,0x099ed1185c329eL, + 0x1ed71d7cdb096fL } }, + /* 3 */ + { { 0x6a3cc39edffea5L,0x7a386fafd3f9c4L,0x366f78fbd8d6efL, + 0x529c7ad7873b80L,0x79eb30380eb471L,0x07c5d3b51760b7L, + 0x36ee4f1cc69183L }, + { 0x5ba260f526b605L,0x2f1dfaf0aa6e6fL,0x6bb5ca812a5752L, + 0x3002d8d1276bc9L,0x01f82269483777L,0x1df33eaaf733cdL, + 0x2b97e555f59255L } }, + /* 4 */ + { { 0x480c57f26feef9L,0x4d28741c248048L,0x0c9cf8af1f0c68L, + 0x778f6a639a8016L,0x148e88c42e9c53L,0x464051757ecfe9L, + 0x1a940bd0e2a5e1L }, + { 0x713a46b74536feL,0x1757b153e1d7ebL,0x30dc8c9da07486L, + 0x3b7460c1879b5eL,0x4b766c5317b315L,0x1b9de3aaf4d377L, + 0x245f124c2cf8f5L } }, + /* 5 */ + { { 0x426e2ee349ddd0L,0x7df3365f84a022L,0x03b005d29a7c45L, + 0x422c2337f9b5a4L,0x060494f4bde761L,0x5245e5db6da0b0L, + 0x22b71d744677f2L }, + { 0x19d097b7d5a7ceL,0x6bcb468823d34cL,0x1c3692d3be1d09L, + 0x3c80ec7aa01f02L,0x7170f2ebaafd97L,0x06cbcc7d79d4e8L, + 0x04a8da511fe760L } }, + /* 6 */ + { { 0x79c07a4fc52870L,0x6e9034a752c251L,0x603860a367382cL, + 0x56d912d6aa87d0L,0x0a348a24abaf76L,0x6c5a23da14adcbL, + 0x3cf60479a522b2L }, + { 0x18dd774c61ed22L,0x0ff30168f93b0cL,0x3f79ae15642eddL, + 0x40510f4915fbcbL,0x2c9ddfdfd1c6d6L,0x67b81b62aee55eL, + 0x2824de79b07a43L } }, + /* 7 */ + { { 0x6c66efe085c629L,0x48c212b7913470L,0x4480fd2d057f0aL, + 0x725ec7a89a9eb1L,0x78ce97ca1972b7L,0x54760ee70154fbL, + 0x362a40e27b9f93L }, + { 0x474dc7e7b14461L,0x602819389ef037L,0x1a13bc284370b2L, + 0x0193ff1295a59dL,0x79615bde6ea5d2L,0x2e76e3d886acc1L, + 0x3bb796812e2b60L } }, + /* 8 */ + { { 0x04cbb3893b9a2dL,0x4c16010a18baabL,0x19f7cb50f60831L, + 0x084f400a0936c1L,0x72f1cdd5bbbf00L,0x1b30b725dc6702L, + 0x182753e4fcc50cL }, + { 0x059a07eadaf9d6L,0x26d81e24bf603cL,0x45583c839dc399L, + 0x5579d4d6b1103aL,0x2e14ea59489ae7L,0x492f6e1c5ecc97L, + 0x03740dc05db420L } }, + /* 9 */ + { { 0x413be88510521fL,0x3753ee49982e99L,0x6cd4f7098e1cc5L, + 0x613c92bda4ec1dL,0x495378b677efe0L,0x132a2143839927L, + 0x0cf8c336291c0bL }, + { 0x7fc89d2208353fL,0x751b9da85657e1L,0x349b8a97d405c3L, + 0x65a964b048428fL,0x1adf481276455eL,0x5560c8d89c2ffcL, + 0x144fc11fac21a3L } }, + /* 10 */ + { { 0x7611f4df5bdf53L,0x634eb16234db80L,0x3c713b8e51174cL, + 0x52c3c68ac4b2edL,0x53025ba8bebe75L,0x7175d98143105bL, + 0x33ca8e266a48faL }, + { 0x0c9281d24fd048L,0x76b3177604bbf3L,0x3b26ae754e106fL, + 0x7f782275c6efc6L,0x36662538a4cb67L,0x0ca1255843e464L, + 0x2a4674e142d9bcL } }, + /* 11 */ + { { 0x303b4085d480d8L,0x68f23650f4fa7bL,0x552a3ceeba3367L, + 0x6da0c4947926e3L,0x6e0f5482eb8003L,0x0de717f3d6738aL, + 0x22e5dcc826a477L }, + { 0x1b05b27209cfc2L,0x7f0a0b65b6e146L,0x63586549ed3126L, + 0x7d628dd2b23124L,0x383423fe510391L,0x57ff609eabd569L, + 0x301f04370131baL } }, + /* 12 */ + { { 0x22fe4cdb32f048L,0x7f228ebdadbf5aL,0x02a99adb2d7c8eL, + 0x01a02e05286706L,0x62d6adf627a89fL,0x49c6ce906fbf2bL, + 0x0207256dae90b9L }, + { 0x23e036e71d6cebL,0x199ed8d604e3d7L,0x0c1a11c076d16fL, + 0x389291fb3da3f3L,0x47adc60f8f942eL,0x177048468e4b9aL, + 0x20c09f5e61d927L } }, + /* 13 */ + { { 0x129ea63615b0b8L,0x03fb4a9b588367L,0x5ad6da8da2d051L, + 0x33f782f44caeaaL,0x5a27fa80d45291L,0x6d1ed796942da4L, + 0x08435a931ef556L }, + { 0x004abb25351130L,0x6d33207c6fd7e7L,0x702130972074b7L, + 0x0e34748af900f7L,0x762a531a28c87aL,0x3a903b5a4a6ac7L, + 0x1775b79c35b105L } }, + /* 14 */ + { { 0x7470fd846612ceL,0x7dd9b431b32e53L,0x04bcd2be1a61bcL, + 0x36ed7c5b5c260bL,0x6795f5ef0a4084L,0x46e2880b401c93L, + 0x17d246c5aa8bdeL }, + { 0x707ae4db41b38dL,0x233c31f7f9558fL,0x585110ec67bdf4L, + 0x4d0cc931d0c703L,0x26fbe4356841a7L,0x64323e95239c44L, + 0x371dc9230f3221L } }, + /* 15 */ + { { 0x70ff1ae4b1ec9dL,0x7c1dcfddee0daaL,0x53286782188748L, + 0x6a5d9381e6f207L,0x3aa6c7d6523c4cL,0x6c02d83e0d97e2L, + 0x16a9c916b45312L }, + { 0x78146744b74de8L,0x742ec415269c6fL,0x237a2c6a860e79L, + 0x186baf17ba68a7L,0x4261e8789fa51fL,0x3dc136480a5903L, + 0x1953899e0cf159L } }, + /* 16 */ + { { 0x0205de2f9fbe67L,0x1706fee51c886fL,0x31a0b803c712bfL, + 0x0a6aa11ede7603L,0x2463ef2a145c31L,0x615403b30e8f4aL, + 0x3f024d6c5f5c5eL }, + { 0x53bc4fd4d01f95L,0x7d512ac15a692cL,0x72be38fcfe6aa0L, + 0x437f0b77bbca1eL,0x7fdcf70774a10eL,0x392d6c5cde37f3L, + 0x229cbce79621d1L } }, + /* 17 */ + { { 0x2de4da2341c342L,0x5ca9d4e08844e7L,0x60dd073bcf74c9L, + 0x4f30aa499b63ecL,0x23efd1eafa00d5L,0x7c99a7db1257b3L, + 0x00febc9b3171b1L }, + { 0x7e2fcf3045f8acL,0x2a642e9e3ce610L,0x23f82be69c5299L, + 0x66e49ad967c279L,0x1c895ddfd7a842L,0x798981e22f6d25L, + 0x0d595cb59322f3L } }, + /* 18 */ + { { 0x4bac017d8c1bbaL,0x73872161e7aafdL,0x0fd865f43d8163L, + 0x019d89457708b7L,0x1b983c4dd70684L,0x095e109b74d841L, + 0x25f1f0b3e0c76fL }, + { 0x4e61ddf96010e8L,0x1c40a53f542e5eL,0x01a74dfc8365f9L, + 0x69b36b92773333L,0x08e0fccc139ed3L,0x266d216ddc4269L, + 0x1f2b47717ce9b5L } }, + /* 19 */ + { { 0x0a9a81da57a41fL,0x0825d800736cccL,0x2d7876b4579d28L, + 0x3340ea6211a1e3L,0x49e89284f3ff54L,0x6276a210fe2c6eL, + 0x01c3c8f31be7cbL }, + { 0x2211da5d186e14L,0x1e6ffbb61bfea8L,0x536c7d060211d2L, + 0x320168720d1d55L,0x5835525ed667baL,0x5125e52495205eL, + 0x16113b9f3e9129L } }, + /* 20 */ + { { 0x3086073f3b236fL,0x283b03c443b5f5L,0x78e49ed0a067a7L, + 0x2a878fb79fb2b8L,0x662f04348a9337L,0x57ee2cf732d50bL, + 0x18b50dd65fd514L }, + { 0x5feb9ef2955926L,0x2c3edbef06a7b0L,0x32728dad651029L, + 0x116d00b1c4b347L,0x13254052bf1a1aL,0x3e77bf7fee5ec1L, + 0x253943ca388882L } }, + /* 21 */ + { { 0x32e5b33062e8afL,0x46ebd147a6d321L,0x2c8076dec6a15cL, + 0x7328d511ff0d80L,0x10ad7e926def0eL,0x4e8ca85937d736L, + 0x02638c26e8bf2fL }, + { 0x1deeb3fff1d63fL,0x5014417fa6e8efL,0x6e1da3de5c8f43L, + 0x7ca942b42295d9L,0x23faacf75bb4d1L,0x4a71fcd680053dL, + 0x04af4f90204dceL } }, + /* 22 */ + { { 0x23780d104cbba5L,0x4e8ff46bba9980L,0x2072a6da8d881fL, + 0x3cc3d881ae11c9L,0x2eee84ff19be89L,0x69b708ed77f004L, + 0x2a82928534eef9L }, + { 0x794331187d4543L,0x70e0f3edc0cc41L,0x3ab1fa0b84c854L, + 0x1478355c1d87baL,0x6f35fa7748ba28L,0x37b8be0531584dL, + 0x03c3141c23a69fL } }, + /* 23 */ + { { 0x5c244cdef029ddL,0x0d0f0a0cc37018L,0x17f8476604f6afL, + 0x13a6dd6ccc95c3L,0x5a242e9801b8f6L,0x211ca9cc632131L, + 0x264a6a46a4694fL }, + { 0x3ffd7235285887L,0x284be28302046fL,0x57f4b9b882f1d6L, + 0x5e21772c940661L,0x7619a735c600cfL,0x2f76f5a50c9106L, + 0x28d89c8c69de31L } }, + /* 24 */ + { { 0x799b5c91361ed8L,0x36ead8c66cd95cL,0x046c9969a91f5cL, + 0x46bbdba2a66ea9L,0x29db0e0215a599L,0x26c8849b36f756L, + 0x22c3feb31ff679L }, + { 0x585d1237b5d9efL,0x5ac57f522e8e8dL,0x617e66e8b56c41L, + 0x68826f276823cfL,0x0983f0e6f39231L,0x4e1075099084bdL, + 0x2a541f82be0416L } }, + /* 25 */ + { { 0x468a6e14cf381cL,0x4f7b845c6399edL,0x36aa29732ebe74L, + 0x19c726911ab46aL,0x2ad1fe431eec0eL,0x301e35051fd1eaL, + 0x36da815e7a1ab3L }, + { 0x05672e4507832aL,0x4ebf10fca51251L,0x6015843421cff0L, + 0x3affad832fc013L,0x712b58d9b45540L,0x1e4751d1f6213eL, + 0x0e7c2b218bafa7L } }, + /* 26 */ + { { 0x7abf784c52edf5L,0x6fcb4b135ca7b1L,0x435e46ac5f735cL, + 0x67f8364ca48c5fL,0x46d45b5fbd956bL,0x10deda6065db94L, + 0x0b37fdf85068f9L }, + { 0x74b3ba61f47ec8L,0x42c7ddf08c10ccL,0x1531a1fe422a20L, + 0x366f913d12be38L,0x6a846e30cb2edfL,0x2785898c994fedL, + 0x061be85f331af3L } }, + /* 27 */ + { { 0x23f5361dfcb91eL,0x3c26c8da6b1491L,0x6e444a1e620d65L, + 0x0c3babd5e8ac13L,0x573723ce612b82L,0x2d10e62a142c37L, + 0x3d1a114c2d98bdL }, + { 0x33950b401896f6L,0x7134efe7c12110L,0x31239fd2978472L, + 0x30333bf5978965L,0x79f93313dd769fL,0x457fb9e11662caL, + 0x190a73b251ae3cL } }, + /* 28 */ + { { 0x04dd54bb75f9a4L,0x0d7253a76ae093L,0x08f5b930792bbcL, + 0x041f79adafc265L,0x4a9ff24c61c11bL,0x0019c94e724725L, + 0x21975945d9cc2aL }, + { 0x3dfe76722b4a2bL,0x17f2f6107c1d94L,0x546e1ae2944b01L, + 0x53f1f06401e72dL,0x2dbe43fc7632d6L,0x5639132e185903L, + 0x0f2f34eb448385L } }, + /* 29 */ + { { 0x7b4cc7ec30ce93L,0x58fb6e4e4145f7L,0x5d1ed5540043b5L, + 0x19ffbe1f633adfL,0x5bfc0907259033L,0x6378f872e7ca0eL, + 0x2c127b2c01eb3cL }, + { 0x076eaf4f58839cL,0x2db54560bc9f68L,0x42ad0319b84062L, + 0x46c325d1fb019dL,0x76d2a19ee9eebcL,0x6fbd6d9e2aa8f7L, + 0x2396a598fe0991L } }, + /* 30 */ + { { 0x662fddf7fbd5e1L,0x7ca8ed22563ad3L,0x5b4768efece3b3L, + 0x643786a422d1eaL,0x36ce80494950e1L,0x1a30795b7f2778L, + 0x107f395c93f332L }, + { 0x7939c28332c144L,0x491610e3c8dc0bL,0x099ba2bfdac5fcL, + 0x5c2e3149ec29a7L,0x31b731d06f1dc3L,0x1cbb60d465d462L, + 0x3ca5461362cfd9L } }, + /* 31 */ + { { 0x653ff736ddc103L,0x7c6f2bdec0dfb2L,0x73f81b73a097d0L, + 0x05b775f84f180fL,0x56b2085af23413L,0x0d6f36256a61feL, + 0x26d3ed267fa68fL }, + { 0x54f89251d27ac2L,0x4fc6ad94a71202L,0x7ebf01969b4cc5L, + 0x7ba364dbc14760L,0x4f8370959a2587L,0x7b7631e37c6188L, + 0x29e51845f104cbL } }, + /* 32 */ + { { 0x426b775e3c647bL,0x327319e0a69180L,0x0c5cb034f6ff2fL, + 0x73aa39b98e9897L,0x7ee615f49fde6eL,0x3f712aa61e0db4L, + 0x33ca06c2ba2ce9L }, + { 0x14973541b8a543L,0x4b4e6101ba61faL,0x1d94e4233d0698L, + 0x501513c715d570L,0x1b8f8c3d01436bL,0x52f41a0445cf64L, + 0x3f709c3a75fb04L } }, + /* 33 */ + { { 0x073c0cbc7f41d6L,0x227c36f5ac8201L,0x508e110fef65d8L, + 0x0f317229529b7fL,0x45fc6030d00e24L,0x118a65d30cebeaL, + 0x3340cc4223a448L }, + { 0x204c999797612cL,0x7c05dd4ce9c5a3L,0x7b865d0a8750e4L, + 0x2f82c876ab7d34L,0x2243ddd2ab4808L,0x6834b9df8a4914L, + 0x123319ed950e0fL } }, + /* 34 */ + { { 0x50430efc14ab48L,0x7e9e4ce0d4e89cL,0x2332207fd8656dL, + 0x4a2809e97f4511L,0x2162bb1b968e2dL,0x29526d54af2972L, + 0x13edd9adcd939dL }, + { 0x793bca31e1ff7fL,0x6b959c9e4d2227L,0x628ac27809a5baL, + 0x2c71ffc7fbaa5fL,0x0c0b058f13c9ceL,0x5676eae68de2cfL, + 0x35508036ea19a4L } }, + /* 35 */ + { { 0x030bbd6dda1265L,0x67f9d12e31bb34L,0x7e4d8196e3ded3L, + 0x7b9120e5352498L,0x75857bce72d875L,0x4ead976a396caeL, + 0x31c5860553a64dL }, + { 0x1a0f792ee32189L,0x564c4efb8165d0L,0x7adc7d1a7fbcbeL, + 0x7ed7c2ccf327b7L,0x35df1b448ce33dL,0x6f67eb838997cdL, + 0x3ee37ec0077917L } }, + /* 36 */ + { { 0x345fa74d5bb921L,0x097c9a56ccfd8eL,0x00a0b5e8f971f8L, + 0x723d95223f69d4L,0x08e2e5c2777f87L,0x68b13676200109L, + 0x26ab5df0acbad6L }, + { 0x01bca7daac34aeL,0x49ca4d5f664dadL,0x110687b850914bL, + 0x1203d6f06443c9L,0x7a2ac743b04d4cL,0x40d96bd3337f82L, + 0x13728be0929c06L } }, + /* 37 */ + { { 0x631ca61127bc1aL,0x2b362fd5a77cd1L,0x17897d68568fb7L, + 0x21070af33db5b2L,0x6872e76221794aL,0x436f29fb076963L, + 0x1f2acfc0ecb7b3L }, + { 0x19bf15ca9b3586L,0x32489a4a17aee2L,0x2b31af3c929551L, + 0x0db7c420b9b19fL,0x538c39bd308c2bL,0x438775c0dea88fL, + 0x1537304d7cd07fL } }, + /* 38 */ + { { 0x53598d943caf0dL,0x1d5244bfe266adL,0x7158feb7ab3811L, + 0x1f46e13cf6fb53L,0x0dcab632eb9447L,0x46302968cfc632L, + 0x0b53d3cc5b6ec7L }, + { 0x69811ca143b7caL,0x5865bcf9f2a11aL,0x74ded7fa093b06L, + 0x1c878ec911d5afL,0x04610e82616e49L,0x1e157fe9640eb0L, + 0x046e6f8561d6c2L } }, + /* 39 */ + { { 0x631a3d3bbe682cL,0x3a4ce9dde5ba95L,0x28f11f7502f1f1L, + 0x0a55cf0c957e88L,0x495e4ec7e0a3bcL,0x30ad4d87ba365cL, + 0x0217b97a4c26f3L }, + { 0x01a9088c2e67fdL,0x7501c4c3d5e5e7L,0x265b7bb854c820L, + 0x729263c87e6b52L,0x308b9e3b8fb035L,0x33f1b86c1b23abL, + 0x0e81b8b21fc99cL } }, + /* 40 */ + { { 0x59f5a87237cac0L,0x6b3a86b0cf28b9L,0x13a53db13a4fc2L, + 0x313c169a1c253bL,0x060158304ed2bbL,0x21e171b71679bcL, + 0x10cdb754d76f86L }, + { 0x44355392ab473aL,0x64eb7cbda08caeL,0x3086426a900c71L, + 0x49016ed9f3c33cL,0x7e6354ab7e04f9L,0x17c4c91a40cd2eL, + 0x3509f461024c66L } }, + /* 41 */ + { { 0x2848f50f9b5a31L,0x68d1755b6c5504L,0x48cd5d5672ec00L, + 0x4d77421919d023L,0x1e1e349ef68807L,0x4ab5130cf415d7L, + 0x305464c6c7dbe6L }, + { 0x64eb0bad74251eL,0x64c6957e52bda4L,0x6c12583440dee6L, + 0x6d3bee05b00490L,0x186970de53dbc4L,0x3be03b37567a56L, + 0x2b553b1ebdc55bL } }, + /* 42 */ + { { 0x74dc3579efdc58L,0x26d29fed1bb71cL,0x334c825a9515afL, + 0x433c1e839273a6L,0x0d8a4e41cff423L,0x3454098fe42f8eL, + 0x1046674bf98686L }, + { 0x09a3e029c05dd2L,0x54d7cfc7fb53a7L,0x35f0ad37e14d7cL, + 0x73a294a13767b9L,0x3f519678275f4fL,0x788c63393993a4L, + 0x0781680b620123L } }, + /* 43 */ + { { 0x4c8e2ed4d5ffe8L,0x112db7d42fe4ebL,0x433b8f2d2be2edL, + 0x23e30b29a82cbcL,0x35d2f4c06ee85aL,0x78ff31ffe4b252L, + 0x0d31295c8cbff5L }, + { 0x314806ea0376a2L,0x4ea09e22bc0589L,0x0879575f00ba97L, + 0x188226d2996bb7L,0x7799368dc9411fL,0x7ab24e5c8cae36L, + 0x2b6a8e2ee4ea33L } }, + /* 44 */ + { { 0x70c7127d4ed72aL,0x24c9743ef34697L,0x2fd30e7a93683aL, + 0x538a89c246012cL,0x6c660a5394ed82L,0x79a95ea239d7e0L, + 0x3f3af3bbfb170dL }, + { 0x3b75aa779ae8c1L,0x33995a3cc0dde4L,0x7489d5720b7bfdL, + 0x599677ef9fa937L,0x3defd64c5ab44bL,0x27d52dc234522bL, + 0x2ac65d1a8450e0L } }, + /* 45 */ + { { 0x478585ec837d7dL,0x5f7971dc174887L,0x67576ed7bb296dL, + 0x5a78e529a74926L,0x640f73f4fa104bL,0x7d42a8b16e4730L, + 0x108c7eaa75fd01L }, + { 0x60661ef96e6896L,0x18d3a0761f3aa7L,0x6e71e163455539L, + 0x165827d6a7e583L,0x4e7f77e9527935L,0x790bebe2ae912eL, + 0x0b8fe9561adb55L } }, + /* 46 */ + { { 0x4d48036a9951a8L,0x371084f255a085L,0x66aeca69cea2c5L, + 0x04c99f40c745e7L,0x08dc4bfd9a0924L,0x0b0ec146b29df7L, + 0x05106218d01c91L }, + { 0x2a56ee99caedc7L,0x5d9b23a203922cL,0x1ce4c80b6a3ec4L, + 0x2666bcb75338cbL,0x185a81aac8c4aaL,0x2b4fb60a06c39eL, + 0x0327e1b3633f42L } }, + /* 47 */ + { { 0x72814710b2a556L,0x52c864f6e16534L,0x4978de66ddd9f2L, + 0x151f5950276cf0L,0x450ac6781d2dc2L,0x114b7a22dd61b2L, + 0x3b32b07f29faf8L }, + { 0x68444fdc2d6e94L,0x68526bd9e437bcL,0x0ca780e8b0d887L, + 0x69f3f850a716aaL,0x500b953e42cd57L,0x4e57744d812e7dL, + 0x000a5f0e715f48L } }, + /* 48 */ + { { 0x2aab10b8243a7dL,0x727d1f4b18b675L,0x0e6b9fdd91bbbbL, + 0x0d58269fc337e5L,0x45d6664105a266L,0x11946af1b14072L, + 0x2c2334f91e46e1L }, + { 0x6dc5f8756d2411L,0x21b34eaa25188bL,0x0d2797da83529eL, + 0x324df55616784bL,0x7039ec66d267dfL,0x2de79cdb2d108cL, + 0x14011b1ad0bde0L } }, + /* 49 */ + { { 0x2e160266425043L,0x55fbe11b712125L,0x7e3c58b3947fd9L, + 0x67aacc79c37ad3L,0x4a18e18d2dea0fL,0x5eef06e5674351L, + 0x37c3483ae33439L }, + { 0x5d5e1d75bb4045L,0x0f9d72db296efdL,0x60b1899dd894a9L, + 0x06e8818ded949aL,0x747fd853c39434L,0x0953b937d9efabL, + 0x09f08c0beeb901L } }, + /* 50 */ + { { 0x1d208a8f2d49ceL,0x54042c5be1445aL,0x1c2681fd943646L, + 0x219c8094e2e674L,0x442cddf07238b8L,0x574a051c590832L, + 0x0b72f4d61c818aL }, + { 0x7bc3cbe4680967L,0x0c8b3f25ae596bL,0x0445b0da74a9efL, + 0x0bbf46c40363b7L,0x1df575c50677a3L,0x016ea6e73d68adL, + 0x0b5207bd8db0fdL } }, + /* 51 */ + { { 0x2d39fdfea1103eL,0x2b252bf0362e34L,0x63d66c992baab9L, + 0x5ac97706de8550L,0x0cca390c39c1acL,0x0d9bec5f01b2eaL, + 0x369360a0f7e5f3L }, + { 0x6dd3461e201067L,0x70b2d3f63ed614L,0x487580487c54c7L, + 0x6020e48a44af2aL,0x1ccf80b21aab04L,0x3cf3b12d88d798L, + 0x349368eccc506fL } }, + /* 52 */ + { { 0x5a053753b0a354L,0x65e818dbb9b0aeL,0x7d5855ee50e4bfL, + 0x58dc06885c7467L,0x5ee15073e57bd3L,0x63254ebc1e07fdL, + 0x1d48e0392aa39bL }, + { 0x4e227c6558ffe9L,0x0c3033d8a82a3eL,0x7bde65c214e8d2L, + 0x6e23561559c16aL,0x5094c5e6deaffdL,0x78dca2880f1f91L, + 0x3d9d3f947d838dL } }, + /* 53 */ + { { 0x387ae5af63408fL,0x6d539aeb4e6edfL,0x7f3d3186368e70L, + 0x01a6446bc19989L,0x35288fbcd4482fL,0x39288d34ec2736L, + 0x1de9c47159ad76L }, + { 0x695dc7944f8d65L,0x3eca2c35575094L,0x0c918059a79b69L, + 0x4573a48c32a74eL,0x580d8bc8b93f52L,0x190be3a3d071eaL, + 0x2333e686b3a8cbL } }, + /* 54 */ + { { 0x2b110c7196fee2L,0x3ac70e99128a51L,0x20a6bb6b75d5e6L, + 0x5f447fa513149aL,0x560d69714cc7b2L,0x1d3ee25279fab1L, + 0x369adb2ccca959L }, + { 0x3fddb13dd821c2L,0x70bf21ba647be8L,0x64121227e3cbc9L, + 0x12633a4c892320L,0x3c15c61660f26dL,0x1932c3b3d19900L, + 0x18c718563eab71L } }, + /* 55 */ + { { 0x72ebe0fd752366L,0x681c2737d11759L,0x143c805e7ae4f0L, + 0x78ed3c2cc7b324L,0x5c16e14820254fL,0x226a4f1c4ec9f0L, + 0x2891bb915eaac6L }, + { 0x061eb453763b33L,0x07f88b81781a87L,0x72b5ac7a87127cL, + 0x7ea4e4cd7ff8b5L,0x5e8c3ce33908b6L,0x0bcb8a3d37feffL, + 0x01da9e8e7fc50bL } }, + /* 56 */ + { { 0x639dfe9e338d10L,0x32dfe856823608L,0x46a1d73bca3b9aL, + 0x2da685d4b0230eL,0x6e0bc1057b6d69L,0x7144ec724a5520L, + 0x0b067c26b87083L }, + { 0x0fc3f0eef4c43dL,0x63500f509552b7L,0x220d74af6f8b86L, + 0x038996eafa2aa9L,0x7f6750f4aee4d2L,0x3e1d3f06718720L, + 0x1ea1d37243814cL } }, + /* 57 */ + { { 0x322d4597c27050L,0x1beeb3ce17f109L,0x15e5ce2e6ef42eL, + 0x6c8be27da6b3a0L,0x66e3347f4d5f5cL,0x7172133899c279L, + 0x250aff4e548743L }, + { 0x28f0f6a43b566dL,0x0cd2437fefbca0L,0x5b1108cb36bdbaL, + 0x48a834d41fb7c2L,0x6cb8565680579fL,0x42da2412b45d9fL, + 0x33dfc1abb6c06eL } }, + /* 58 */ + { { 0x56e3c48ef96c80L,0x65667bb6c1381eL,0x09f70514375487L, + 0x1548ff115f4a08L,0x237de2d21a0710L,0x1425cdee9f43dfL, + 0x26a6a42e055b0aL }, + { 0x4ea9ea9dc7dfcbL,0x4df858583ac58aL,0x1d274f819f1d39L, + 0x26e9c56cf91fcbL,0x6cee31c7c3a465L,0x0bb8e00b108b28L, + 0x226158da117301L } }, + /* 59 */ + { { 0x5a7cd4fce73946L,0x7b6a462d0ac653L,0x732ea4bb1a3da5L, + 0x7c8e9f54711af4L,0x0a6cd55d4655f9L,0x341e6d13e4754aL, + 0x373c87098879a8L }, + { 0x7bc82e61b818bfL,0x5f2db48f44879fL,0x2a2f06833f1d28L, + 0x494e5b691a74c0L,0x17d6cf35fd6b57L,0x5f7028d1c25dfcL, + 0x377a9ab9562cb6L } }, + /* 60 */ + { { 0x4de8877e787b2eL,0x183e7352621a52L,0x2ab0509974962bL, + 0x045a450496cb8aL,0x3bf7118b5591c7L,0x7724f98d761c35L, + 0x301607e8d5a0c1L }, + { 0x0f58a3f24d4d58L,0x3771c19c464f3cL,0x06746f9c0bfafaL, + 0x56564c9c8feb52L,0x0d66d9a7d8a45fL,0x403578141193caL, + 0x00b0d0bdc19260L } }, + /* 61 */ + { { 0x571407157bdbc2L,0x138d5a1c2c0b99L,0x2ee4a8057dcbeaL, + 0x051ff2b58e9ed1L,0x067378ad9e7cdaL,0x7cc2c1db97a49eL, + 0x1e7536ccd849d6L }, + { 0x531fd95f3497c4L,0x55dc08325f61a7L,0x144e942bce32bfL, + 0x642d572f09e53aL,0x556ff188261678L,0x3e79c0d9d513d6L, + 0x0bbbc6656f6d52L } }, + /* 62 */ + { { 0x57d3eb50596edcL,0x26c520a487451dL,0x0a92db40aea8d6L, + 0x27df6345109616L,0x7733d611fd727cL,0x61d14171fef709L, + 0x36169ae417c36bL }, + { 0x6899f5d4091cf7L,0x56ce5dfe4ed0c1L,0x2c430ce5913fbcL, + 0x1b13547e0f8caeL,0x4840a8275d3699L,0x59b8ef209e81adL, + 0x22362dff5ea1a2L } }, + /* 63 */ + { { 0x7237237bd98425L,0x73258e162a9d0bL,0x0a59a1e8bb5118L, + 0x4190a7ee5d8077L,0x13684905fdbf7cL,0x31c4033a52626bL, + 0x010a30e4fbd448L }, + { 0x47623f981e909aL,0x670af7c325b481L,0x3d004241fa4944L, + 0x0905a2ca47f240L,0x58f3cdd7a187c3L,0x78b93aee05b43fL, + 0x19b91d4ef8d63bL } }, + /* 64 */ + { { 0x0d34e116973cf4L,0x4116fc9e69ee0eL,0x657ae2b4a482bbL, + 0x3522eed134d7cdL,0x741e0dde0a036aL,0x6554316a51cc7bL, + 0x00f31c6ca89837L }, + { 0x26770aa06b1dd7L,0x38233a4ceba649L,0x065a1110c96feaL, + 0x18d367839e0f15L,0x794543660558d1L,0x39b605139065dcL, + 0x29abbec071b637L } }, + /* 65 */ + { { 0x1464b401ab5245L,0x16db891b27ff74L,0x724eb49cb26e34L, + 0x74fee3bc9cc33eL,0x6a8bdbebe085eaL,0x5c2e75ca207129L, + 0x1d03f2268e6b08L }, + { 0x28b0a328e23b23L,0x645dc26209a0bcL,0x62c28990348d49L, + 0x4dd9be1fa333d0L,0x6183aac74a72e4L,0x1d6f3ee69e1d03L, + 0x2fff96db0ff670L } }, + /* 66 */ + { { 0x2358f5c6a2123fL,0x5b2bfc51bedb63L,0x4fc6674be649ecL, + 0x51fc16e44b813aL,0x2ffe10a73754c1L,0x69a0c7a053aeefL, + 0x150e605fb6b9b4L }, + { 0x179eef6b8b83c4L,0x64293b28ad05efL,0x331795fab98572L, + 0x09823eec78727dL,0x36508042b89b81L,0x65f1106adb927eL, + 0x2fc0234617f47cL } }, + /* 67 */ + { { 0x12aa244e8068dbL,0x0c834ae5348f00L,0x310fc1a4771cb3L, + 0x6c90a2f9e19ef9L,0x77946fa0573471L,0x37f5df81e5f72fL, + 0x204f5d72cbe048L }, + { 0x613c724383bba6L,0x1ce14844967e0aL,0x797c85e69aa493L, + 0x4fb15b0f2ce765L,0x5807978e2e8aa7L,0x52c75859876a75L, + 0x1554635c763d3eL } }, + /* 68 */ + { { 0x4f292200623f3bL,0x6222be53d7fe07L,0x1e02a9a08c2571L, + 0x22c6058216b912L,0x1ec20044c7ba17L,0x53f94c5efde12bL, + 0x102b8aadfe32a4L }, + { 0x45377aa927b102L,0x0d41b8062ee371L,0x77085a9018e62aL, + 0x0c69980024847cL,0x14739b423a73a9L,0x52ec6961fe3c17L, + 0x38a779c94b5a7dL } }, + /* 69 */ + { { 0x4d14008435af04L,0x363bfd8325b4e8L,0x48cdb715097c95L, + 0x1b534540f8bee0L,0x4ca1e5c90c2a76L,0x4b52c193d6eee0L, + 0x277a33c79becf5L }, + { 0x0fee0d511d3d06L,0x4627f3d6a58f8cL,0x7c81ac245119b8L, + 0x0c8d526ba1e07aL,0x3dbc242f55bac2L,0x2399df8f91fffdL, + 0x353e982079ba3bL } }, + /* 70 */ + { { 0x6405d3b0ab9645L,0x7f31abe3ee236bL,0x456170a9babbb1L, + 0x09634a2456a118L,0x5b1c6045acb9e5L,0x2c75c20d89d521L, + 0x2e27ccf5626399L }, + { 0x307cd97fed2ce4L,0x1c2fbb02b64087L,0x542a068d27e64dL, + 0x148c030b3bc6a6L,0x671129e616ade5L,0x123f40db60dafcL, + 0x07688f3c621220L } }, + /* 71 */ + { { 0x1c46b342f2c4b5L,0x27decc0b3c8f04L,0x0d9bd433464c54L, + 0x1f3d893b818572L,0x2536043b536c94L,0x57e00c4b19ebf9L, + 0x3938fb9e5ad55eL }, + { 0x6b390024c8b22fL,0x4583f97e20a976L,0x2559d24abcbad7L, + 0x67a9cabc9bd8c6L,0x73a56f09432e4aL,0x79eb0beb53a3b7L, + 0x3e19d47f6f8221L } }, + /* 72 */ + { { 0x7399cb9d10e0b2L,0x32acc1b8a36e2aL,0x287d60c2407035L, + 0x42c82420ea4b5cL,0x13f286658bc268L,0x3c91181156e064L, + 0x234b83dcdeb963L }, + { 0x79bc95486cfee6L,0x4d8fd3cb78af36L,0x07362ba5e80da8L, + 0x79d024a0d681b0L,0x6b58406907f87fL,0x4b40f1e977e58fL, + 0x38dcc6fd5fa342L } }, + /* 73 */ + { { 0x72282be1cd0abeL,0x02bd0fdfdf44e5L,0x19b0e0d2f753e4L, + 0x4514e76ce8c4c0L,0x02ebc9c8cdcc1bL,0x6ac0c0373e9fddL, + 0x0dc414af1c81a9L }, + { 0x7a109246f32562L,0x26982e6a3768edL,0x5ecd8daed76ab5L, + 0x2eaa70061eb261L,0x09e7c038a8c514L,0x2a2603cc300658L, + 0x25d93ab9e55cd4L } }, + /* 74 */ + { { 0x11b19fcbd5256aL,0x41e4d94274770fL,0x0133c1a411001fL, + 0x360bac481dbca3L,0x45908b18a9c22bL,0x1e34396fafb03aL, + 0x1b84fea7486edaL }, + { 0x183c62a71e6e16L,0x5f1dc30e93da8eL,0x6cb97b502573c3L, + 0x3708bf0964e3fcL,0x35a7f042eeacceL,0x56370da902c27fL, + 0x3a873c3b72797fL } }, + /* 75 */ + { { 0x6573c9cea4cc9bL,0x2c3b5f9d91e6dcL,0x2a90e2dbd9505eL, + 0x66a75444025f81L,0x1571fb894b03cdL,0x5d1a1f00fd26f3L, + 0x0d19a9fd618855L }, + { 0x659acd56515664L,0x7279478bd616a3L,0x09a909e76d56c3L, + 0x2fd70474250358L,0x3a1a25c850579cL,0x11b9e0f71b74ccL, + 0x1268daef3d1bffL } }, + /* 76 */ + { { 0x7f5acc46d93106L,0x5bc15512f939c8L,0x504b5f92f996deL, + 0x25965549be7a64L,0x357a3a2ae9b80dL,0x3f2bcf9c139cc0L, + 0x0a7ddd99f23b35L }, + { 0x6868f5a8a0b1c5L,0x319ec52f15b1beL,0x0770000a849021L, + 0x7f4d50287bd608L,0x62c971d28a9d7fL,0x164e89309acb72L, + 0x2a29f002cf4a32L } }, + /* 77 */ + { { 0x58a852ae11a338L,0x27e3a35f2dcef8L,0x494d5731ce9e18L, + 0x49516f33f4bb3eL,0x386b26ba370097L,0x4e8fac1ec30248L, + 0x2ac26d4c44455dL }, + { 0x20484198eb9dd0L,0x75982a0e06512bL,0x152271b9279b05L, + 0x5908a9857e36d2L,0x6a933ab45a60abL,0x58d8b1acb24fafL, + 0x28fbcf19425590L } }, + /* 78 */ + { { 0x5420e9df010879L,0x4aba72aec2f313L,0x438e544eda7494L, + 0x2e8e189ce6f7eaL,0x2f771e4efe45bdL,0x0d780293bce7efL, + 0x1569ad3d0d02acL }, + { 0x325251ebeaf771L,0x02510f1a8511e2L,0x3863816bf8aad1L, + 0x60fdb15fe6ac19L,0x4792aef52a348cL,0x38e57a104e9838L, + 0x0d171611a1df1bL } }, + /* 79 */ + { { 0x15ceb0bea65e90L,0x6e56482db339bcL,0x37f618f7b0261fL, + 0x6351abc226dabcL,0x0e999f617b74baL,0x37d3cc57af5b69L, + 0x21df2b987aac68L }, + { 0x2dddaa3a358610L,0x2da264bc560e47L,0x545615d538bf13L, + 0x1c95ac244b8cc7L,0x77de1f741852cbL,0x75d324f00996abL, + 0x3a79b13b46aa3bL } }, + /* 80 */ + { { 0x7db63998683186L,0x6849bb989d530cL,0x7b53c39ef7ed73L, + 0x53bcfbf664d3ffL,0x25ef27c57f71c7L,0x50120ee80f3ad6L, + 0x243aba40ed0205L }, + { 0x2aae5e0ee1fcebL,0x3449d0d8343fbeL,0x5b2864fb7cffc7L, + 0x64dceb5407ac3eL,0x20303a5695523dL,0x3def70812010b2L, + 0x07be937f2e9b6fL } }, + /* 81 */ + { { 0x5838f9e0540015L,0x728d8720efb9f7L,0x1ab5864490b0c8L, + 0x6531754458fdcfL,0x600ff9612440c0L,0x48735b36a585b7L, + 0x3d4aaea86b865dL }, + { 0x6898942cac32adL,0x3c84c5531f23a1L,0x3c9dbd572f7edeL, + 0x5691f0932a2976L,0x186f0db1ac0d27L,0x4fbed18bed5bc9L, + 0x0e26b0dee0b38cL } }, + /* 82 */ + { { 0x1188b4f8e60f5bL,0x602a915455b4a2L,0x60e06af289ff99L, + 0x579fe4bed999e5L,0x2bc03b15e6d9ddL,0x1689649edd66d5L, + 0x3165e277dca9d2L }, + { 0x7cb8a529cf5279L,0x57f8035b34d84dL,0x352e2eb26de8f1L, + 0x6406820c3367c4L,0x5d148f4c899899L,0x483e1408482e15L, + 0x1680bd1e517606L } }, + /* 83 */ + { { 0x5c877cc1c90202L,0x2881f158eae1f4L,0x6f45e207df4267L, + 0x59280eba1452d8L,0x4465b61e267db5L,0x171f1137e09e5cL, + 0x1368eb821daa93L }, + { 0x70fe26e3e66861L,0x52a6663170da7dL,0x71d1ce5b7d79dcL, + 0x1cffe9be1e1afdL,0x703745115a29c4L,0x73b7f897b2f65aL, + 0x02218c3a95891aL } }, + /* 84 */ + { { 0x16866db8a9e8c9L,0x4770b770123d9bL,0x4c116cf34a8465L, + 0x079b28263fc86aL,0x3751c755a72b58L,0x7bc8df1673243aL, + 0x12fff72454f064L }, + { 0x15c049b89554e7L,0x4ea9ef44d7cd9aL,0x42f50765c0d4f1L, + 0x158bb603cb011bL,0x0809dde16470b1L,0x63cad7422ea819L, + 0x38b6cd70f90d7eL } }, + /* 85 */ + { { 0x1e4aab6328e33fL,0x70575f026da3aeL,0x7e1b55c8c55219L, + 0x328d4b403d24caL,0x03b6df1f0a5bd1L,0x26b4bb8b648ed0L, + 0x17161f2f10b76aL }, + { 0x6cdb32bae8b4c0L,0x33176266227056L,0x4975fa58519b45L, + 0x254602ea511d96L,0x4e82e93e402a67L,0x0ca8b5929cdb4fL, + 0x3ae7e0a07918f5L } }, + /* 86 */ + { { 0x60f9d1fecf5b9bL,0x6257e40d2cd469L,0x6c7aa814d28456L, + 0x58aac7caac8e79L,0x703a55f0293cbfL,0x702390a0f48378L, + 0x24b9ae07218b07L }, + { 0x1ebc66cdaf24e3L,0x7d9ae5f9f8e199L,0x42055ee921a245L, + 0x035595936e4d49L,0x129c45d425c08bL,0x6486c5f19ce6ddL, + 0x027dbd5f18ba24L } }, + /* 87 */ + { { 0x7d6b78d29375fbL,0x0a3dc6ba22ae38L,0x35090fa91feaf6L, + 0x7f18587fb7b16eL,0x6e7091dd924608L,0x54e102cdbf5ff8L, + 0x31b131a4c22079L }, + { 0x368f87d6a53fb0L,0x1d3f3d69a3f240L,0x36bf5f9e40e1c6L, + 0x17f150e01f8456L,0x76e5d0835eb447L,0x662fc0a1207100L, + 0x14e3dd97a98e39L } }, + /* 88 */ + { { 0x0249d9c2663b4bL,0x56b68f9a71ba1cL,0x74b119567f9c02L, + 0x5e6f336d8c92acL,0x2ced58f9f74a84L,0x4b75a2c2a467c5L, + 0x30557011cf740eL }, + { 0x6a87993be454ebL,0x29b7076fb99a68L,0x62ae74aaf99bbaL, + 0x399f9aa8fb6c1bL,0x553c24a396dd27L,0x2868337a815ea6L, + 0x343ab6635cc776L } }, + /* 89 */ + { { 0x0e0b0eec142408L,0x79728229662121L,0x605d0ac75e6250L, + 0x49a097a01edfbeL,0x1e20cd270df6b6L,0x7438a0ca9291edL, + 0x29daa430da5f90L }, + { 0x7a33844624825aL,0x181715986985c1L,0x53a6853cae0b92L, + 0x6d98401bd925e8L,0x5a0a34f5dd5e24L,0x7b818ef53cf265L, + 0x0836e43c9d3194L } }, + /* 90 */ + { { 0x1179b70e6c5fd9L,0x0246d9305dd44cL,0x635255edfbe2fbL, + 0x5397b3523b4199L,0x59350cc47e6640L,0x2b57aa97ed4375L, + 0x37efd31abd153aL }, + { 0x7a7afa6907f4faL,0x75c10cb94e6a7eL,0x60a925ab69cc47L, + 0x2ff5bcd9239bd5L,0x13c2113e425f11L,0x56bd3d2f8a1437L, + 0x2c9adbab13774fL } }, + /* 91 */ + { { 0x4ab9f52a2e5f2bL,0x5e537e70b58903L,0x0f242658ebe4f2L, + 0x2648a1e7a5f9aeL,0x1b4c5081e73007L,0x6827d4aff51850L, + 0x3925e41726cd01L }, + { 0x56dd8a55ab3cfbL,0x72d6a31b6d5beaL,0x697bd2e5575112L, + 0x66935519a7aa12L,0x55e97dda7a3aceL,0x0e16afb4237b4cL, + 0x00b68fbff08093L } }, + /* 92 */ + { { 0x4b00366481d0d9L,0x37cb031fbfc5c4L,0x14643f6800dd03L, + 0x6793fef60fe0faL,0x4f43e329c92803L,0x1fce86b96a6d26L, + 0x0ad416975e213aL }, + { 0x7cc6a6711adcc9L,0x64b8a63c43c2d9L,0x1e6caa2a67c0d0L, + 0x610deffd17a54bL,0x57d669d5f38423L,0x77364b8f022636L, + 0x36d4d13602e024L } }, + /* 93 */ + { { 0x72e667ae50a2f5L,0x1b15c950c3a21aL,0x3ccc37c72e6dfeL, + 0x027f7e1d094fb8L,0x43ae1e90aa5d7eL,0x3f5feac3d97ce5L, + 0x0363ed0a336e55L }, + { 0x235f73d7663784L,0x5d8cfc588ad5a4L,0x10ab6ff333016eL, + 0x7d8886af2e1497L,0x549f34fd17988eL,0x3fc4fcaee69a33L, + 0x0622b133a13d9eL } }, + /* 94 */ + { { 0x6344cfa796c53eL,0x0e9a10d00136fdL,0x5d1d284a56efd8L, + 0x608b1968f8aca7L,0x2fa5a66776edcaL,0x13430c44f1609cL, + 0x1499973cb2152aL }, + { 0x3764648104ab58L,0x3226e409fadafcL,0x1513a8466459ddL, + 0x649206ec365035L,0x46149aa3f765b1L,0x3aebf0a035248eL, + 0x1ee60b8c373494L } }, + /* 95 */ + { { 0x4e9efcc15f3060L,0x5e5d50fd77cdc8L,0x071e5403516b58L, + 0x1b7d4e89b24ceaL,0x53b1fa66d6dc03L,0x457f15f892ab5fL, + 0x076332c9397260L }, + { 0x31422b79d7584bL,0x0b01d47e41ba80L,0x3e5611a3171528L, + 0x5f53b9a9fc1be4L,0x7e2fc3d82f110fL,0x006cf350ef0fbfL, + 0x123ae98ec81c12L } }, + /* 96 */ + { { 0x310d41df46e2f6L,0x2ff032a286cf13L,0x64751a721c4eadL, + 0x7b62bcc0339b95L,0x49acf0c195afa4L,0x359d48742544e5L, + 0x276b7632d9e2afL }, + { 0x656c6be182579aL,0x75b65a4d85b199L,0x04a911d1721bfaL, + 0x46e023d0e33477L,0x1ec2d580acd869L,0x540b456f398a37L, + 0x001f698210153dL } }, + /* 97 */ + { { 0x3ca35217b00dd0L,0x73961d034f4d3cL,0x4f520b61c4119dL, + 0x4919fde5cccff7L,0x4d0e0e6f38134dL,0x55c22586003e91L, + 0x24d39d5d8f1b19L }, + { 0x4d4fc3d73234dcL,0x40c50c9d5f8368L,0x149afbc86bf2b8L, + 0x1dbafefc21d7f1L,0x42e6b61355107fL,0x6e506cf4b54f29L, + 0x0f498a6c615228L } }, + /* 98 */ + { { 0x30618f437cfaf8L,0x059640658532c4L,0x1c8a4d90e96e1dL, + 0x4a327bcca4fb92L,0x54143b8040f1a0L,0x4ec0928c5a49e4L, + 0x2af5ad488d9b1fL }, + { 0x1b392bd5338f55L,0x539c0292b41823L,0x1fe35d4df86a02L, + 0x5fa5bb17988c65L,0x02b6cb715adc26L,0x09a48a0c2cb509L, + 0x365635f1a5a9f2L } }, + /* 99 */ + { { 0x58aa87bdc21f31L,0x156900c7cb1935L,0x0ec1f75ee2b6cfL, + 0x5f3e35a77ec314L,0x582dec7b9b7621L,0x3e65deb0e8202aL, + 0x325c314b8a66b7L }, + { 0x702e2a22f24d66L,0x3a20e9982014f1L,0x6424c5b86bbfb0L, + 0x424eea4d795351L,0x7fc4cce7c22055L,0x581383fceb92d7L, + 0x32b663f49ee81bL } }, + /* 100 */ + { { 0x76e2d0b648b73eL,0x59ca39fa50bddaL,0x18bb44f786a7e4L, + 0x28c8d49d464360L,0x1b8bf1d3a574eaL,0x7c670b9bf1635aL, + 0x2efb30a291f4b3L }, + { 0x5326c069cec548L,0x03bbe481416531L,0x08a415c8d93d6fL, + 0x3414a52120d383L,0x1f17a0fc6e9c5cL,0x0de9a090717463L, + 0x22d84b3c67ff07L } }, + /* 101 */ + { { 0x30b5014c3830ebL,0x70791dc1a18b37L,0x09e6ea4e24f423L, + 0x65e148a5253132L,0x446f05d5d40449L,0x7ad5d3d707c0e9L, + 0x18eedd63dd3ab5L }, + { 0x40d2eac6bb29e0L,0x5b0e9605e83c38L,0x554f2c666a56a8L, + 0x0ac27b6c94c48bL,0x1aaecdd91bafe5L,0x73c6e2bdf72634L, + 0x306dab96d19e03L } }, + /* 102 */ + { { 0x6d3e4b42772f41L,0x1aba7796f3a39bL,0x3a03fbb980e9c0L, + 0x2f2ea5da2186a8L,0x358ff444ef1fcfL,0x0798cc0329fcdcL, + 0x39a28bcc9aa46dL }, + { 0x42775c977fe4d2L,0x5eb8fc5483d6b0L,0x0bfe37c039e3f7L, + 0x429292eaf9df60L,0x188bdf4b840cd5L,0x06e10e090749cdL, + 0x0e52678e73192eL } }, + /* 103 */ + { { 0x05de80b08df5feL,0x2af8c77406c5f8L,0x53573c50a0304aL, + 0x277b10b751bca0L,0x65cf8c559132a5L,0x4c667abe25f73cL, + 0x0271809e05a575L }, + { 0x41ced461f7a2fbL,0x0889a9ebdd7075L,0x320c63f2b7760eL, + 0x4f8d4324151c63L,0x5af47315be2e5eL,0x73c62f6aee2885L, + 0x206d6412a56a97L } }, + /* 104 */ + { { 0x6b1c508b21d232L,0x3781185974ead6L,0x1aba7c3ebe1fcfL, + 0x5bdc03cd3f3a5aL,0x74a25036a0985bL,0x5929e30b7211b2L, + 0x16a9f3bc366bd7L }, + { 0x566a7057dcfffcL,0x23b5708a644bc0L,0x348cda2aa5ba8cL, + 0x466aa96b9750d4L,0x6a435ed9b20834L,0x2e7730f2cf9901L, + 0x2b5cd71d5b0410L } }, + /* 105 */ + { { 0x285ab3cee76ef4L,0x68895e3a57275dL,0x6fab2e48fd1265L, + 0x0f1de060428c94L,0x668a2b080b5905L,0x1b589dc3b0cb37L, + 0x3c037886592c9bL }, + { 0x7fb5c0f2e90d4dL,0x334eefb3d8c91aL,0x75747124700388L, + 0x547a2c2e2737f5L,0x2af9c080e37541L,0x0a295370d9091aL, + 0x0bb5c36dad99e6L } }, + /* 106 */ + { { 0x644116586f25cbL,0x0c3f41f9ee1f5dL,0x00628d43a3dedaL, + 0x16e1437aae9669L,0x6aba7861bf3e59L,0x60735631ff4c44L, + 0x345609efaa615eL }, + { 0x41f54792e6acefL,0x4791583f75864dL,0x37f2ff5c7508b1L, + 0x1288912516c3b0L,0x51a2135f6a539bL,0x3b775511f42091L, + 0x127c6afa7afe66L } }, + /* 107 */ + { { 0x79f4f4f7492b73L,0x583d967256342dL,0x51a729bff33ca3L, + 0x3977d2c22d8986L,0x066f528ba8d40bL,0x5d759d30f8eb94L, + 0x0f8e649192b408L }, + { 0x22d84e752555bbL,0x76953855c728c7L,0x3b2254e72aaaa4L, + 0x508cd4ce6c0212L,0x726296d6b5a6daL,0x7a77aa066986f3L, + 0x2267a497bbcf31L } }, + /* 108 */ + { { 0x7f3651bf825dc4L,0x3988817388c56fL,0x257313ed6c3dd0L, + 0x3feab7f3b8ffadL,0x6c0d3cb9e9c9b4L,0x1317be0a7b6ac4L, + 0x2a5f399d7df850L }, + { 0x2fe5a36c934f5eL,0x429199df88ded1L,0x435ea21619b357L, + 0x6aac6a063bac2bL,0x600c149978f5edL,0x76543aa1114c95L, + 0x163ca9c83c7596L } }, + /* 109 */ + { { 0x7dda4a3e4daedbL,0x1824cba360a4cdL,0x09312efd70e0c6L, + 0x454e68a146c885L,0x40aee762fe5c47L,0x29811cbd755a59L, + 0x34b37c95f28319L }, + { 0x77c58b08b717d2L,0x309470d9a0f491L,0x1ab9f40448e01cL, + 0x21c8bd819207b1L,0x6a01803e9361bcL,0x6e5e4c350ec415L, + 0x14fd55a91f8798L } }, + /* 110 */ + { { 0x4cee562f512a90L,0x0008361d53e390L,0x3789b307a892cfL, + 0x064f7be8770ae9L,0x41435d848762cfL,0x662204dd38baa6L, + 0x23d6dcf73f6c5aL }, + { 0x69bef2d2c75d95L,0x2b037c0c9bb43eL,0x495fb4d79a34cfL, + 0x184e140c601260L,0x60193f8d435f9cL,0x283fa52a0c3ad2L, + 0x1998635e3a7925L } }, + /* 111 */ + { { 0x1cfd458ce382deL,0x0dddbd201bbcaeL,0x14d2ae8ed45d60L, + 0x73d764ab0c24cbL,0x2a97fe899778adL,0x0dbd1e01eddfe9L, + 0x2ba5c72d4042c3L }, + { 0x27eebc3af788f1L,0x53ffc827fc5a30L,0x6d1d0726d35188L, + 0x4721275c50aa2aL,0x077125f02e690fL,0x6da8142405db5dL, + 0x126cef68992513L } }, + /* 112 */ + { { 0x3c6067035b2d69L,0x2a1ad7db2361acL,0x3debece6cad41cL, + 0x30095b30f9afc1L,0x25f50b9bd9c011L,0x79201b2f2c1da1L, + 0x3b5c151449c5bdL }, + { 0x76eff4127abdb4L,0x2d31e03ce0382aL,0x24ff21f8bda143L, + 0x0671f244fd3ebaL,0x0c1c00b6bcc6fbL,0x18de9f7c3ebefbL, + 0x33dd48c3809c67L } }, + /* 113 */ + { { 0x61d6c2722d94edL,0x7e426e31041cceL,0x4097439f1b47b0L, + 0x579e798b2d205bL,0x6a430d67f830ebL,0x0d2c676700f727L, + 0x05fea83a82f25bL }, + { 0x3f3482df866b98L,0x3dd353b6a5a9cdL,0x77fe6ae1a48170L, + 0x2f75cc2a8f7cddL,0x7442a3863dad17L,0x643de42d877a79L, + 0x0fec8a38fe7238L } }, + /* 114 */ + { { 0x79b70c0760ac07L,0x195d3af37e9b29L,0x1317ff20f7cf27L, + 0x624e1c739e7504L,0x67330ef50f943dL,0x775e8cf455d793L, + 0x17b94d2d913a9fL }, + { 0x4b627203609e7fL,0x06aac5fb93e041L,0x603c515fdc2611L, + 0x2592ca0d7ae472L,0x02395d1f50a6cbL,0x466ef9648f85d9L, + 0x297cf879768f72L } }, + /* 115 */ + { { 0x3489d67d85fa94L,0x0a6e5b739c8e04L,0x7ebb5eab442e90L, + 0x52665a007efbd0L,0x0967ca57b0d739L,0x24891f9d932b63L, + 0x3cc2d6dbadc9d3L }, + { 0x4b4773c81c5338L,0x73cd47dad7a0f9L,0x7c755bab6ae158L, + 0x50b03d6becefcaL,0x574d6e256d57f0L,0x188db4fffb92aeL, + 0x197e10118071eaL } }, + /* 116 */ + { { 0x45d0cbcba1e7f1L,0x1180056abec91aL,0x6c5f86624bbc28L, + 0x442c83f3b8e518L,0x4e16ae1843ecb4L,0x670cef2fd786c9L, + 0x205b4acb637d2cL }, + { 0x70b0e539aa8671L,0x67c982056bebd0L,0x645c831a5e7c36L, + 0x09e06951a14b32L,0x5dd610ad4c89e6L,0x41c35f20164831L, + 0x3821f29cb4cdb8L } }, + /* 117 */ + { { 0x2831ffaba10079L,0x70f6dac9ffe444L,0x1cfa32ccc03717L, + 0x01519fda22a3c8L,0x23215e815aaa27L,0x390671ad65cbf7L, + 0x03dd4d72de7d52L }, + { 0x1ecd972ee95923L,0x166f8da3813e8eL,0x33199bbd387a1aL, + 0x04525fe15e3dc7L,0x44d2ef54165898L,0x4b7e47d3dc47f7L, + 0x10d5c8db0b5d44L } }, + /* 118 */ + { { 0x176d95ba9cdb1bL,0x14025f04f23dfcL,0x49379332891687L, + 0x6625e5ccbb2a57L,0x7ac0abdbf9d0e5L,0x7aded4fbea15b2L, + 0x314844ac184d67L }, + { 0x6d9ce34f05eae3L,0x3805d2875856d2L,0x1c2122f85e40ebL, + 0x51cb9f2d483a9aL,0x367e91e20f1702L,0x573c3559838dfdL, + 0x0b282b0cb85af1L } }, + /* 119 */ + { { 0x6a12e4ef871eb5L,0x64bb517e14f5ffL,0x29e04d3aaa530bL, + 0x1b07d88268f261L,0x411be11ed16fb0L,0x1f480536db70bfL, + 0x17a7deadfd34e4L }, + { 0x76d72f30646612L,0x5a3bbb43a1b0a0L,0x5e1687440e82bfL, + 0x713b5e69481112L,0x46c3dcb499e174L,0x0862da3b4e2a24L, + 0x31cb55b4d62681L } }, + /* 120 */ + { { 0x5ffc74dae5bb45L,0x18944c37adb9beL,0x6aaa63b1ee641aL, + 0x090f4b6ee057d3L,0x4045cedd2ee00fL,0x21c2c798f7c282L, + 0x2c2c6ef38cd6bdL }, + { 0x40d78501a06293L,0x56f8caa5cc89a8L,0x7231d5f91b37aeL, + 0x655f1e5a465c6dL,0x3f59a81f9cf783L,0x09bbba04c23624L, + 0x0f71ee23bbacdeL } }, + /* 121 */ + { { 0x38d398c4741456L,0x5204c0654243c3L,0x34498c916ea77eL, + 0x12238c60e5fe43L,0x0fc54f411c7625L,0x30b2ca43aa80b6L, + 0x06bead1bb6ea92L }, + { 0x5902ba8674b4adL,0x075ab5b0fa254eL,0x58db83426521adL, + 0x5b66b6b3958e39L,0x2ce4e39890e07bL,0x46702513338b37L, + 0x363690c2ded4d7L } }, + /* 122 */ + { { 0x765642c6b75791L,0x0f4c4300d7f673L,0x404d8bbe101425L, + 0x61e91c88651f1bL,0x61ddc9bc60aed8L,0x0ef36910ce2e65L, + 0x04b44367aa63b8L }, + { 0x72822d3651b7dcL,0x4b750157a2716dL,0x091cb4f2118d16L, + 0x662ba93b101993L,0x447cbd54a1d40aL,0x12cdd48d674848L, + 0x16f10415cbec69L } }, + /* 123 */ + { { 0x0c57a3a751cd0eL,0x0833d7478fadceL,0x1e751f55686436L, + 0x489636c58e1df7L,0x26ad6da941266fL,0x22225d3559880fL, + 0x35b397c45ba0e2L }, + { 0x3ca97b70e1f2ceL,0x78e50427a8680cL,0x06137e042a8f91L, + 0x7ec40d2500b712L,0x3f0ad688ad7b0dL,0x24746fb33f9513L, + 0x3638fcce688f0bL } }, + /* 124 */ + { { 0x753163750bed6fL,0x786507cd16157bL,0x1d6ec228ce022aL, + 0x587255f42d1b31L,0x0c6adf72a3a0f6L,0x4bfeee2da33f5eL, + 0x08b7300814de6cL }, + { 0x00bf8df9a56e11L,0x75aead48fe42e8L,0x3de9bad911b2e2L, + 0x0fadb233e4b8bbL,0x5b054e8fd84f7dL,0x5eb3064152889bL, + 0x01c1c6e8c777a1L } }, + /* 125 */ + { { 0x5fa0e598f8fcb9L,0x11c129a1ae18dfL,0x5c41b482a2273bL, + 0x545664e5044c9cL,0x7e01c915bfb9abL,0x7f626e19296aa0L, + 0x20c91a9822a087L }, + { 0x273a9fbe3c378fL,0x0f126b44b7d350L,0x493764a75df951L, + 0x32dec3c367d24bL,0x1a7ae987fed9d3L,0x58a93055928b85L, + 0x11626975d7775fL } }, + /* 126 */ + { { 0x2bb174a95540a9L,0x10de02c58b613fL,0x2fa8f7b861f3eeL, + 0x44731260bdf3b3L,0x19c38ff7da41feL,0x3535a16e3d7172L, + 0x21a948b83cc7feL }, + { 0x0e6f72868bc259L,0x0c70799df3c979L,0x526919955584c3L, + 0x4d95fda04f8fa2L,0x7bb228e6c0f091L,0x4f728b88d92194L, + 0x2b361c5a136bedL } }, + /* 127 */ + { { 0x0c72ca10c53841L,0x4036ab49f9da12L,0x578408d2b7082bL, + 0x2c4903201fbf5eL,0x14722b3f42a6a8L,0x1997b786181694L, + 0x25c6f10de32849L }, + { 0x79f46d517ff2ffL,0x2dc5d97528f6deL,0x518a494489aa72L, + 0x52748f8af3cf97L,0x472da30a96bb16L,0x1be228f92465a9L, + 0x196f0c47d60479L } }, + /* 128 */ + { { 0x47dd7d139b3239L,0x049c9b06775d0fL,0x627ffc00562d5eL, + 0x04f578d5e5e243L,0x43a788ffcef8b9L,0x7db320be9dde28L, + 0x00837528b8572fL }, + { 0x2969eca306d695L,0x195b72795ec194L,0x5e1fa9b8e77e50L, + 0x4c627f2b3fbfd5L,0x4b91e0d0ee10ffL,0x5698c8d0f35833L, + 0x12d3a9431f475eL } }, + /* 129 */ + { { 0x6409457a0db57eL,0x795b35192e0433L,0x146f973fe79805L, + 0x3d49c516dfb9cfL,0x50dfc3646b3cdaL,0x16a08a2210ad06L, + 0x2b4ef5bcd5b826L }, + { 0x5ebabfee2e3e3eL,0x2e048e724d9726L,0x0a7a7ed6abef40L, + 0x71ff7f83e39ad8L,0x3405ac52a1b852L,0x2e3233357a608dL, + 0x38c1bf3b0e40e6L } }, + /* 130 */ + { { 0x59aec823e4712cL,0x6ed9878331ddadL,0x1cc6faf629f2a0L, + 0x445ff79f36c18cL,0x4edc7ed57aff3dL,0x22ee54c8bdd9e8L, + 0x35398f42d72ec5L }, + { 0x4e7a1cceee0ecfL,0x4c66a707dd1d31L,0x629ad157a23c04L, + 0x3b2c6031dc3c83L,0x3336acbcd3d96cL,0x26ce43adfce0f0L, + 0x3c869c98d699dcL } }, + /* 131 */ + { { 0x58b3cd9586ba11L,0x5d6514b8090033L,0x7c88c3bd736782L, + 0x1735f84f2130edL,0x47784095a9dee0L,0x76312c6e47901bL, + 0x1725f6ebc51455L }, + { 0x6744344bc4503eL,0x16630b4d66e12fL,0x7b3481752c3ec7L, + 0x47bb2ed1f46f95L,0x08a1a497dd1bcfL,0x1f525df2b8ed93L, + 0x0fe492ea993713L } }, + /* 132 */ + { { 0x71b8dd7268b448L,0x1743dfaf3728d7L,0x23938d547f530aL, + 0x648c3d497d0fc6L,0x26c0d769e3ad45L,0x4d25108769a806L, + 0x3fbf2025143575L }, + { 0x485bfd90339366L,0x2de2b99ed87461L,0x24a33347713badL, + 0x1674bc7073958aL,0x5bb2373ee85b5fL,0x57f9bd657e662cL, + 0x2041b248d39042L } }, + /* 133 */ + { { 0x5f01617d02f4eeL,0x2a8e31c4244b91L,0x2dab3e790229e0L, + 0x72d319ea7544afL,0x01ffb8b000cb56L,0x065e63b0daafd3L, + 0x3d7200a7111d6fL }, + { 0x4561ce1b568973L,0x37034c532dd8ecL,0x1368215020be02L, + 0x30e7184cf289ebL,0x199e0c27d815deL,0x7ee1b4dff324e5L, + 0x2f4a11de7fab5cL } }, + /* 134 */ + { { 0x33c2f99b1cdf2bL,0x1e0d78bf42a2c0L,0x64485dececaa67L, + 0x2242a41be93e92L,0x62297b1f15273cL,0x16ebfaafb02205L, + 0x0f50f805f1fdabL }, + { 0x28bb0b3a70eb28L,0x5b1c7d0160d683L,0x05c30a37959f78L, + 0x3d9301184922d2L,0x46c1ead7dbcb1aL,0x03ee161146a597L, + 0x2d413ed9a6ccc1L } }, + /* 135 */ + { { 0x685ab5f97a27c2L,0x59178214023751L,0x4ffef3c585ab17L, + 0x2bc85302aba2a9L,0x675b001780e856L,0x103c8a37f0b33dL, + 0x2241e98ece70a6L }, + { 0x546738260189edL,0x086c8f7a6b96edL,0x00832ad878a129L, + 0x0b679056ba7462L,0x020ce6264bf8c4L,0x3f9f4b4d92abfbL, + 0x3e9c55343c92edL } }, + /* 136 */ + { { 0x482cec9b3f5034L,0x08b59b3cd1fa30L,0x5a55d1bc8e58b5L, + 0x464a5259337d8eL,0x0a5b6c66ade5a5L,0x55db77b504ddadL, + 0x015992935eac35L }, + { 0x54fe51025e32fcL,0x5d7f52dbe4a579L,0x08c564a8c58696L, + 0x4482a8bec4503fL,0x440e75d9d94de9L,0x6992d768020bfaL, + 0x06c311e8ba01f6L } }, + /* 137 */ + { { 0x2a6ac808223878L,0x04d3ccb4aab0b8L,0x6e6ef09ff6e823L, + 0x15cb03ee9158dcL,0x0dc58919171bf7L,0x3273568abf3cb1L, + 0x1b55245b88d98bL }, + { 0x28e9383b1de0c1L,0x30d5009e4f1f1bL,0x334d185a56a134L, + 0x0875865dfa4c46L,0x266edf5eae3beeL,0x2e03ff16d1f7e5L, + 0x29a36bd9f0c16dL } }, + /* 138 */ + { { 0x004cff44b2e045L,0x426c96380ba982L,0x422292281e46d7L, + 0x508dd8d29d7204L,0x3a4ea73fb2995eL,0x4be64090ae07b2L, + 0x3339177a0eff22L }, + { 0x74a97ec2b3106eL,0x0c616d09169f5fL,0x1bb5d8907241a7L, + 0x661fb67f6d41bdL,0x018a88a0daf136L,0x746333a093a7b4L, + 0x3e19f1ac76424eL } }, + /* 139 */ + { { 0x542a5656527296L,0x0e7b9ce22f1bc9L,0x31b0945992b89bL, + 0x6e0570eb85056dL,0x32daf813483ae5L,0x69eeae9d59bb55L, + 0x315ad4b730b557L }, + { 0x2bc16795f32923L,0x6b02b7ba55130eL,0x1e9da67c012f85L, + 0x5616f014dabf8fL,0x777395fcd9c723L,0x2ff075e7743246L, + 0x2993538aff142eL } }, + /* 140 */ + { { 0x72dae20e552b40L,0x2e4ba69aa5d042L,0x001e563e618bd2L, + 0x28feeba3c98772L,0x648c356da2a907L,0x687e2325069ea7L, + 0x0d34ab09a394f0L }, + { 0x73c21813111286L,0x5829b53b304e20L,0x6fba574de08076L, + 0x79f7058f61614eL,0x4e71c9316f1191L,0x24ef12193e0a89L, + 0x35dc4e2bc9d848L } }, + /* 141 */ + { { 0x045e6d3b4ad1cdL,0x729c95493782f0L,0x77f59de85b361aL, + 0x5309b4babf28f8L,0x4d893d9290935fL,0x736f47f2b2669eL, + 0x23270922d757f3L }, + { 0x23a4826f70d4e9L,0x68a8c63215d33eL,0x4d6c2069205c9cL, + 0x46b2938a5eebe0L,0x41d1f1e2de3892L,0x5ca1775544bcb0L, + 0x3130629e5d19dcL } }, + /* 142 */ + { { 0x6e2681593375acL,0x117cfbabc22621L,0x6c903cd4e13ccaL, + 0x6f358f14d4bd97L,0x1bc58fa11089f1L,0x36aa2db4ac426aL, + 0x15ced8464b7ea1L }, + { 0x6966836cba7df5L,0x7c2b1851568113L,0x22b50ff2ffca66L, + 0x50e77d9f48e49aL,0x32775e9bbc7cc9L,0x403915bb0ece71L, + 0x1b8ec7cb9dd7aaL } }, + /* 143 */ + { { 0x65a888b677788bL,0x51887fac2e7806L,0x06792636f98d2bL, + 0x47bbcd59824c3bL,0x1aca908c43e6dcL,0x2e00d15c708981L, + 0x08e031c2c80634L }, + { 0x77fbc3a297c5ecL,0x10a7948af2919eL,0x10cdafb1fb6b2fL, + 0x27762309b486f0L,0x13abf26bbac641L,0x53da38478fc3eeL, + 0x3c22eff379bf55L } }, + /* 144 */ + { { 0x0163f484770ee3L,0x7f28e8942e0cbfL,0x5f86cb51b43831L, + 0x00feccd4e4782fL,0x40e5b417eafe7dL,0x79e5742bbea228L, + 0x3717154aa469beL }, + { 0x271d74a270f721L,0x40eb400890b70cL,0x0e37be81d4cb02L, + 0x786907f4e8d43fL,0x5a1f5b590a7acbL,0x048861883851fdL, + 0x11534a1e563dbbL } }, + /* 145 */ + { { 0x37a6357c525435L,0x6afe6f897b78a5L,0x7b7ff311d4f67bL, + 0x38879df15dc9f4L,0x727def7b8ba987L,0x20285dd0db4436L, + 0x156b0fc64b9243L }, + { 0x7e3a6ec0c1c390L,0x668a88d9bcf690L,0x5925aba5440dbeL, + 0x0f6891a044f593L,0x70b46edfed4d97L,0x1a6cc361bab201L, + 0x046f5bc6e160bcL } }, + /* 146 */ + { { 0x79350f076bc9d1L,0x077d9e79a586b9L,0x0896bc0c705764L, + 0x58e632b90e7e46L,0x14e87e0ad32488L,0x4b1bb3f72c6e00L, + 0x3c3ce9684a5fc5L }, + { 0x108fbaf1f703aaL,0x08405ecec17577L,0x199a8e2d44be73L, + 0x2eb22ed0067763L,0x633944deda3300L,0x20d739eb8e5efbL, + 0x2bbbd94086b532L } }, + /* 147 */ + { { 0x03c8b17a19045dL,0x6205a0a504980bL,0x67fdb3e962b9f0L, + 0x16399e01511a4bL,0x44b09fe9dffc96L,0x00a74ff44a1381L, + 0x14590deed3f886L }, + { 0x54e3d5c2a23ddbL,0x310e5138209d28L,0x613f45490c1c9bL, + 0x6bbc85d44bbec8L,0x2f85fc559e73f6L,0x0d71fa7d0fa8cbL, + 0x2898571d17fbb9L } }, + /* 148 */ + { { 0x5607a84335167dL,0x3009c1eb910f91L,0x7ce63447e62d0bL, + 0x03a0633afcf89eL,0x1234b5aaa50872L,0x5a307b534d547bL, + 0x2f4e97138a952eL }, + { 0x13914c2db0f658L,0x6cdcb47e6e75baL,0x5549169caca772L, + 0x0f20423dfeb16fL,0x6b1ae19d180239L,0x0b7b3bee9b7626L, + 0x1ca81adacfe4efL } }, + /* 149 */ + { { 0x219ec3ad19d96fL,0x3549f6548132dbL,0x699889c7aacd0bL, + 0x74602a58730b19L,0x62dc63bcece81cL,0x316f991c0c317aL, + 0x2b8627867b95e3L }, + { 0x67a25ddced1eedL,0x7e14f0eba756e7L,0x0873fbc09b0495L, + 0x0fefb0e16596adL,0x03e6cd98ef39bbL,0x1179b1cded249dL, + 0x35c79c1db1edc2L } }, + /* 150 */ + { { 0x1368309d4245bfL,0x442e55852a7667L,0x095b0f0f348b65L, + 0x6834cf459dfad4L,0x6645950c9be910L,0x06bd81288c71e6L, + 0x1b015b6e944edfL }, + { 0x7a6a83045ab0e3L,0x6afe88b9252ad0L,0x2285bd65523502L, + 0x6c78543879a282L,0x1c5e264b5c6393L,0x3a820c6a7453eeL, + 0x37562d1d61d3c3L } }, + /* 151 */ + { { 0x6c084f62230c72L,0x599490270bc6cfL,0x1d3369ddd3c53dL, + 0x516ddb5fac5da0L,0x35ab1e15011b1aL,0x5fba9106d3a180L, + 0x3be0f092a0917cL }, + { 0x57328f9fdc2538L,0x0526323fc8d5f6L,0x10cbb79521e602L, + 0x50d01167147ae2L,0x2ec7f1b3cda99eL,0x43073cc736e7beL, + 0x1ded89cadd83a6L } }, + /* 152 */ + { { 0x1d51bda65d56d5L,0x63f2fd4d2dc056L,0x326413d310ea6dL, + 0x3abba5bca92876L,0x6b9aa8bc4d6ebeL,0x1961c687f15d5dL, + 0x311cf07464c381L }, + { 0x2321b1064cd8aeL,0x6e3caac4443850L,0x3346fc4887d2d0L, + 0x1640417e0e640fL,0x4a958a52a07a9eL,0x1346a1b1cb374cL, + 0x0a793cf79beccbL } }, + /* 153 */ + { { 0x29d56cba89aaa5L,0x1581898c0b3c15L,0x1af5b77293c082L, + 0x1617ba53a006ceL,0x62dd3b384e475fL,0x71a9820c3f962aL, + 0x0e4938920b854eL }, + { 0x0b8d98849808abL,0x64c14923546de7L,0x6a20883b78a6fcL, + 0x72de211428acd6L,0x009678b47915bbL,0x21b5269ae5dae6L, + 0x313cc0e60b9457L } }, + /* 154 */ + { { 0x69ee421b1de38bL,0x44b484c6cec1c7L,0x0240596c6a8493L, + 0x2321a62c85fb9eL,0x7a10921802a341L,0x3d2a95507e45c3L, + 0x0752f40f3b6714L }, + { 0x596a38798751e6L,0x46bf186a0feb85L,0x0b23093e23b49cL, + 0x1bfa7bc5afdc07L,0x4ba96f873eefadL,0x292e453fae9e44L, + 0x2773646667b75cL } }, + /* 155 */ + { { 0x1f81a64e94f22aL,0x3125ee3d8683ddL,0x76a660a13b9582L, + 0x5aa584c3640c6eL,0x27cc99fd472953L,0x7048f4d58061d1L, + 0x379a1397ac81e8L }, + { 0x5d1ecd2b6b956bL,0x0829e0366b0697L,0x49548cec502421L, + 0x7af5e2f717c059L,0x329a25a0fec54eL,0x028e99e4bcd7f1L, + 0x071d5fe81fca78L } }, + /* 156 */ + { { 0x4b5c4aeb0fdfe4L,0x1367e11326ce37L,0x7c16f020ef5f19L, + 0x3c55303d77b471L,0x23a4457a06e46aL,0x2174426dd98424L, + 0x226f592114bd69L }, + { 0x4411b94455f15aL,0x52e0115381fae4L,0x45b6d8efbc8f7eL, + 0x58b1221bd86d26L,0x284fb6f8a7ec1fL,0x045835939ddd30L, + 0x0216960accd598L } }, + /* 157 */ + { { 0x4b61f9ec1f138aL,0x4460cd1e18502bL,0x277e4fce3c4726L, + 0x0244246d6414b9L,0x28fbfcef256984L,0x3347ed0db40577L, + 0x3b57fa9e044718L }, + { 0x4f73bcd6d1c833L,0x2c0d0dcf7f0136L,0x2010ac75454254L, + 0x7dc4f6151539a8L,0x0b8929ef6ea495L,0x517e20119d2bdfL, + 0x1e29f9a126ba15L } }, + /* 158 */ + { { 0x683a7c10470cd8L,0x0d05f0dbe0007fL,0x2f6a5026d649cdL, + 0x249ce2fdaed603L,0x116dc1e7a96609L,0x199bd8d82a0b98L, + 0x0694ad0219aeb2L }, + { 0x03a3656e864045L,0x4e552273df82a6L,0x19bcc7553d17abL, + 0x74ac536c1df632L,0x440302fb4a86f6L,0x1becec0e31c9feL, + 0x002045f8fa46b8L } }, + /* 159 */ + { { 0x5833ba384310a2L,0x1db83fad93f8baL,0x0a12713ee2f7edL, + 0x40e0f0fdcd2788L,0x1746de5fb239a5L,0x573748965cfa15L, + 0x1e3dedda0ef650L }, + { 0x6c8ca1c87607aeL,0x785dab9554fc0eL,0x649d8f91860ac8L, + 0x4436f88b52c0f9L,0x67f22ca8a5e4a3L,0x1f990fd219e4c9L, + 0x013dd21c08573fL } }, + /* 160 */ + { { 0x05d116141d161cL,0x5c1d2789da2ea5L,0x11f0d861f99f34L, + 0x692c2650963153L,0x3bd69f5329539eL,0x215898eef8885fL, + 0x041f79dd86f7f1L }, + { 0x76dcc5e96beebdL,0x7f2b50cb42a332L,0x067621cabef8abL, + 0x31e0be607054edL,0x4c67c5e357a3daL,0x5b1a63fbfb1c2bL, + 0x3112efbf5e5c31L } }, + /* 161 */ + { { 0x3f83e24c0c62f1L,0x51dc9c32aae4e0L,0x2ff89b33b66c78L, + 0x21b1c7d354142cL,0x243d8d381c84bcL,0x68729ee50cf4b7L, + 0x0ed29e0f442e09L }, + { 0x1ad7b57576451eL,0x6b2e296d6b91dcL,0x53f2b306e30f42L, + 0x3964ebd9ee184aL,0x0a32855df110e4L,0x31f2f90ddae05fL, + 0x3410cd04e23702L } }, + /* 162 */ + { { 0x60d1522ca8f2feL,0x12909237a83e34L,0x15637f80d58590L, + 0x3c72431b6d714dL,0x7c8e59a615bea2L,0x5f977b688ef35aL, + 0x071c198c0b3ab0L }, + { 0x2b54c699699b4bL,0x14da473c2fd0bcL,0x7ba818ea0ad427L, + 0x35117013940b2fL,0x6e1df6b5e609dbL,0x3f42502720b64dL, + 0x01ee7dc890e524L } }, + /* 163 */ + { { 0x12ec1448ff4e49L,0x3e2edac882522bL,0x20455ab300f93aL, + 0x5849585bd67c14L,0x0393d5aa34ba8bL,0x30f9a1f2044fa7L, + 0x1059c9377a93e0L }, + { 0x4e641cc0139e73L,0x0d9f23c9b0fa78L,0x4b2ad87e2b83f9L, + 0x1c343a9f6d9e3cL,0x1098a4cb46de4dL,0x4ddc893843a41eL, + 0x1797f4167d6e3aL } }, + /* 164 */ + { { 0x4add4675856031L,0x499bd5e5f7a0ffL,0x39ea1f1202271eL, + 0x0ecd7480d7a91eL,0x395f5e5fc10956L,0x0fa7f6b0c9f79bL, + 0x2fad4623aed6cbL }, + { 0x1563c33ae65825L,0x29881cafac827aL,0x50650baf4c45a1L, + 0x034aad988fb9e9L,0x20a6224dc5904cL,0x6fb141a990732bL, + 0x3ec9ae1b5755deL } }, + /* 165 */ + { { 0x3108e7c686ae17L,0x2e73a383b4ad8aL,0x4e6bb142ba4243L, + 0x24d355922c1d80L,0x2f850dd9a088baL,0x21c50325dd5e70L, + 0x33237dd5bd7fa4L }, + { 0x7823a39cab7630L,0x1535f71cff830eL,0x70d92ff0599261L, + 0x227154d2a2477cL,0x495e9bbb4f871cL,0x40d2034835686bL, + 0x31b08f97eaa942L } }, + /* 166 */ + { { 0x0016c19034d8ddL,0x68961627cf376fL,0x6acc90681615aeL, + 0x6bc7690c2e3204L,0x6ddf28d2fe19a2L,0x609b98f84dae4dL, + 0x0f32bfd7c94413L }, + { 0x7d7edc6b21f843L,0x49bbd2ebbc9872L,0x593d6ada7b6a23L, + 0x55736602939e9cL,0x79461537680e39L,0x7a7ee9399ca7cdL, + 0x008776f6655effL } }, + /* 167 */ + { { 0x64585f777233cfL,0x63ec12854de0f6L,0x6b7f9bbbc3f99dL, + 0x301c014b1b55d3L,0x7cf3663bbeb568L,0x24959dcb085bd1L, + 0x12366aa6752881L }, + { 0x77a74c0da5e57aL,0x3279ca93ad939fL,0x33c3c8a1ef08c9L, + 0x641b05ab42825eL,0x02f416d7d098dbL,0x7e3d58be292b68L, + 0x1864dbc46e1f46L } }, + /* 168 */ + { { 0x1da167b8153a9dL,0x47593d07d9e155L,0x386d984e12927fL, + 0x421a6f08a60c7cL,0x5ae9661c24dab3L,0x7927b2e7874507L, + 0x3266ea80609d53L }, + { 0x7d198f4c26b1e3L,0x430d4ea2c4048eL,0x58d8ab77e84ba3L, + 0x1cb14299c37297L,0x6db6031e8f695cL,0x159bd855e26d55L, + 0x3f3f6d318a73ddL } }, + /* 169 */ + { { 0x3ee958cca40298L,0x02a7e5eba32ad6L,0x43b4bab96f0e1eL, + 0x534be79062b2b1L,0x029ead089b37e3L,0x4d585da558f5aaL, + 0x1f9737eb43c376L }, + { 0x0426dfd9b86202L,0x4162866bc0a9f3L,0x18fc518e7bb465L, + 0x6db63380fed812L,0x421e117f709c30L,0x1597f8d0f5cee6L, + 0x04ffbf1289b06aL } }, + /* 170 */ + { { 0x61a1987ffa0a5fL,0x42058c7fc213c6L,0x15b1d38447d2c9L, + 0x3d5f5d7932565eL,0x5db754af445fa7L,0x5d489189fba499L, + 0x02c4c55f51141bL }, + { 0x26b15972e9993dL,0x2fc90bcbd97c45L,0x2ff60f8684b0f1L, + 0x1dc641dd339ab0L,0x3e38e6be23f82cL,0x3368162752c817L, + 0x19bba80ceb45ceL } }, + /* 171 */ + { { 0x7c6e95b4c6c693L,0x6bbc6d5efa7093L,0x74d7f90bf3bf1cL, + 0x54d5be1f0299a1L,0x7cb24f0aa427c6L,0x0a18f3e086c941L, + 0x058a1c90e4faefL }, + { 0x3d6bd016927e1eL,0x1da4ce773098b8L,0x2133522e690056L, + 0x0751416d3fc37eL,0x1beed1643eda66L,0x5288b6727d5c54L, + 0x199320e78655c6L } }, + /* 172 */ + { { 0x74575027eeaf94L,0x124bd533c3ceaeL,0x69421ab7a8a1d7L, + 0x37f2127e093f3dL,0x40281765252a08L,0x25a228798d856dL, + 0x326eca62759c4cL }, + { 0x0c337c51acb0a5L,0x122ba78c1ef110L,0x02498adbb68dc4L, + 0x67240c124b089eL,0x135865d25d9f89L,0x338a76d5ae5670L, + 0x03a8efaf130385L } }, + /* 173 */ + { { 0x3a450ac5e49beaL,0x282af80bb4b395L,0x6779eb0db1a139L, + 0x737cabdd174e55L,0x017b14ca79b5f2L,0x61fdef6048e137L, + 0x3acc12641f6277L }, + { 0x0f730746fe5096L,0x21d05c09d55ea1L,0x64d44bddb1a560L, + 0x75e5035c4778deL,0x158b7776613513L,0x7b5efa90c7599eL, + 0x2caa0791253b95L } }, + /* 174 */ + { { 0x288e5b6d53e6baL,0x435228909d45feL,0x33b4cf23b2a437L, + 0x45b352017d6db0L,0x4372d579d6ef32L,0x0fa9e5badbbd84L, + 0x3a78cff24759bbL }, + { 0x0899d2039eab6eL,0x4cf47d2f76bc22L,0x373f739a3a8c69L, + 0x09beaa5b1000b3L,0x0acdfbe83ebae5L,0x10c10befb0e900L, + 0x33d2ac4cc31be3L } }, + /* 175 */ + { { 0x765845931e08fbL,0x2a3c2a0dc58007L,0x7270da587d90e1L, + 0x1ee648b2bc8f86L,0x5d2ca68107b29eL,0x2b7064846e9e92L, + 0x3633ed98dbb962L }, + { 0x5e0f16a0349b1bL,0x58d8941f570ca4L,0x20abe376a4cf34L, + 0x0f4bd69a360977L,0x21eb07cc424ba7L,0x720d2ecdbbe6ecL, + 0x255597d5a97c34L } }, + /* 176 */ + { { 0x67bbf21a0f5e94L,0x422a3b05a64fc1L,0x773ac447ebddc7L, + 0x1a1331c08019f1L,0x01ef6d269744ddL,0x55f7be5b3b401aL, + 0x072e031c681273L }, + { 0x7183289e21c677L,0x5e0a3391f3162fL,0x5e02d9e65d914aL, + 0x07c79ea1adce2fL,0x667ca5c2e1cbe4L,0x4f287f22caccdaL, + 0x27eaa81673e75bL } }, + /* 177 */ + { { 0x5246180a078fe6L,0x67cc8c9fa3bb15L,0x370f8dd123db31L, + 0x1938dafa69671aL,0x5af72624950c5eL,0x78cc5221ebddf8L, + 0x22d616fe2a84caL }, + { 0x723985a839327fL,0x24fa95584a5e22L,0x3d8a5b3138d38bL, + 0x3829ef4a017acfL,0x4f09b00ae055c4L,0x01df84552e4516L, + 0x2a7a18993e8306L } }, + /* 178 */ + { { 0x7b6224bc310eccL,0x69e2cff429da16L,0x01c850e5722869L, + 0x2e4889443ee84bL,0x264a8df1b3d09fL,0x18a73fe478d0d6L, + 0x370b52740f9635L }, + { 0x52b7d3a9d6f501L,0x5c49808129ee42L,0x5b64e2643fd30cL, + 0x27d903fe31b32cL,0x594cb084d078f9L,0x567fb33e3ae650L, + 0x0db7be9932cb65L } }, + /* 179 */ + { { 0x19b78113ed7cbeL,0x002b2f097a1c8cL,0x70b1dc17fa5794L, + 0x786e8419519128L,0x1a45ba376af995L,0x4f6aa84b8d806cL, + 0x204b4b3bc7ca47L }, + { 0x7581a05fd94972L,0x1c73cadb870799L,0x758f6fefc09b88L, + 0x35c62ba8049b42L,0x6f5e71fc164cc3L,0x0cd738b5702721L, + 0x10021afac9a423L } }, + /* 180 */ + { { 0x654f7937e3c115L,0x5d198288b515cbL,0x4add965c25a6e3L, + 0x5a37df33cd76ffL,0x57bb7e288e1631L,0x049b69089e1a31L, + 0x383a88f4122a99L }, + { 0x4c0e4ef3d80a73L,0x553c77ac9f30e2L,0x20bb18c2021e82L, + 0x2aec0d1c4225c5L,0x397fce0ac9c302L,0x2ab0c2a246e8aaL, + 0x02e5e5190be080L } }, + /* 181 */ + { { 0x7a255a4ae03080L,0x0d68b01513f624L,0x29905bd4e48c8cL, + 0x1d81507027466bL,0x1684aaeb70dee1L,0x7dd460719f0981L, + 0x29c43b0f0a390cL }, + { 0x272567681b1f7dL,0x1d2a5f8502e0efL,0x0fd5cd6b221befL, + 0x5eb4749e9a0434L,0x7d1553a324e2a6L,0x2eefd8e86a7804L, + 0x2ad80d5335109cL } }, + /* 182 */ + { { 0x25342aef4c209dL,0x24e811ac4e0865L,0x3f209757f8ae9dL, + 0x1473ff8a5da57bL,0x340f61c3919cedL,0x7523bf85fb9bc0L, + 0x319602ebca7cceL }, + { 0x121e7541d442cbL,0x4ffa748e49c95cL,0x11493cd1d131dcL, + 0x42b215172ab6b5L,0x045fd87e13cc77L,0x0ae305df76342fL, + 0x373b033c538512L } }, + /* 183 */ + { { 0x389541e9539819L,0x769f3b29b7e239L,0x0d05f695e3232cL, + 0x029d04f0e9a9fbL,0x58b78b7a697fb8L,0x7531b082e6386bL, + 0x215d235bed95a9L }, + { 0x503947c1859c5dL,0x4b82a6ba45443fL,0x78328eab71b3a5L, + 0x7d8a77f8cb3509L,0x53fcd9802e41d4L,0x77552091976edbL, + 0x226c60ad7a5156L } }, + /* 184 */ + { { 0x77ad6a43360710L,0x0fdeabd326d7aeL,0x4012886c92104aL, + 0x2d6c378dd7ae33L,0x7e72ef2c0725f3L,0x4a4671f4ca18e0L, + 0x0afe3b4bb6220fL }, + { 0x212cf4b56e0d6aL,0x7c24d086521960L,0x0662cf71bd414dL, + 0x1085b916c58c25L,0x781eed2be9a350L,0x26880e80db6ab2L, + 0x169e356442f061L } }, + /* 185 */ + { { 0x57aa2ad748b02cL,0x68a34256772a9aL,0x1591c44962f96cL, + 0x110a9edd6e53d2L,0x31eab597e091a3L,0x603e64e200c65dL, + 0x2f66b72e8a1cfcL }, + { 0x5c79d138543f7fL,0x412524363fdfa3L,0x547977e3b40008L, + 0x735ca25436d9f7L,0x232b4888cae049L,0x27ce37a53d8f23L, + 0x34d45881a9b470L } }, + /* 186 */ + { { 0x76b95255924f43L,0x035c9f3bd1aa5dL,0x5eb71a010b4bd0L, + 0x6ce8dda7e39f46L,0x35679627ea70c0L,0x5c987767c7d77eL, + 0x1fa28952b620b7L }, + { 0x106f50b5924407L,0x1cc3435a889411L,0x0597cdce3bc528L, + 0x738f8b0d5077d1L,0x5894dd60c7dd6aL,0x0013d0721f5e2eL, + 0x344573480527d3L } }, + /* 187 */ + { { 0x2e2c1da52abf77L,0x394aa8464ad05eL,0x095259b7330a83L, + 0x686e81cf6a11f5L,0x405c7e48c93c7cL,0x65c3ca9444a2ecL, + 0x07bed6c59c3563L }, + { 0x51f9d994fb1471L,0x3c3ecfa5283b4eL,0x494dccda63f6ccL, + 0x4d07b255363a75L,0x0d2b6d3155d118L,0x3c688299fc9497L, + 0x235692fa3dea3aL } }, + /* 188 */ + { { 0x16b4d452669e98L,0x72451fa85406b9L,0x674a145d39151fL, + 0x325ffd067ae098L,0x527e7805cd1ae0L,0x422a1d1789e48dL, + 0x3e27be63f55e07L }, + { 0x7f95f6dee0b63fL,0x008e444cc74969L,0x01348f3a72b614L, + 0x000cfac81348c3L,0x508ae3e5309ce5L,0x2584fcdee44d34L, + 0x3a4dd994899ee9L } }, + /* 189 */ + { { 0x4d289cc0368708L,0x0e5ebc60dc3b40L,0x78cc44bfab1162L, + 0x77ef2173b7d11eL,0x06091718e39746L,0x30fe19319b83a4L, + 0x17e8f2988529c6L }, + { 0x68188bdcaa9f2aL,0x0e64b1350c1bddL,0x5b18ebac7cc4b3L, + 0x75315a9fcc046eL,0x36e9770fd43db4L,0x54c5857fc69121L, + 0x0417e18f3e909aL } }, + /* 190 */ + { { 0x29795db38059adL,0x6efd20c8fd4016L,0x3b6d1ce8f95a1aL, + 0x4db68f177f8238L,0x14ec7278d2340fL,0x47bd77ff2b77abL, + 0x3d2dc8cd34e9fcL }, + { 0x285980a5a83f0bL,0x08352e2d516654L,0x74894460481e1bL, + 0x17f6f3709c480dL,0x6b590d1b55221eL,0x45c100dc4c9be9L, + 0x1b13225f9d8b91L } }, + /* 191 */ + { { 0x0b905fb4b41d9dL,0x48cc8a474cb7a2L,0x4eda67e8de09b2L, + 0x1de47c829adde8L,0x118ad5b9933d77L,0x7a12665ac3f9a4L, + 0x05631a4fb52997L }, + { 0x5fb2a8e6806e63L,0x27d96bbcca369bL,0x46066f1a6b8c7bL, + 0x63b58fc7ca3072L,0x170a36229c0d62L,0x57176f1e463203L, + 0x0c7ce083e73b9cL } }, + /* 192 */ + { { 0x31caf2c09e1c72L,0x6530253219e9d2L,0x7650c98b601c57L, + 0x182469f99d56c0L,0x415f65d292b7a7L,0x30f62a55549b8eL, + 0x30f443f643f465L }, + { 0x6b35c575ddadd0L,0x14a23cf6d299eeL,0x2f0198c0967d7dL, + 0x1013058178d5bfL,0x39da601c9cc879L,0x09d8963ec340baL, + 0x1b735db13ad2a7L } }, + /* 193 */ + { { 0x20916ffdc83f01L,0x16892aa7c9f217L,0x6bff179888d532L, + 0x4adf3c3d366288L,0x41a62b954726aeL,0x3139609022aeb6L, + 0x3e8ab9b37aff7aL }, + { 0x76bbc70f24659aL,0x33fa98513886c6L,0x13b26af62c4ea6L, + 0x3c4d5826389a0cL,0x526ec28c02bf6aL,0x751ff083d79a7cL, + 0x110ac647990224L } }, + /* 194 */ + { { 0x2c6c62fa2b6e20L,0x3d37edad30c299L,0x6ef25b44b65fcaL, + 0x7470846914558eL,0x712456eb913275L,0x075a967a9a280eL, + 0x186c8188f2a2a0L }, + { 0x2f3b41a6a560b1L,0x3a8070b3f9e858L,0x140936ff0e1e78L, + 0x5fd298abe6da8aL,0x3823a55d08f153L,0x3445eafaee7552L, + 0x2a5fc96731a8b2L } }, + /* 195 */ + { { 0x06317be58edbbbL,0x4a38f3bfbe2786L,0x445b60f75896b7L, + 0x6ec7c92b5adf57L,0x07b6be8038a441L,0x1bcfe002879655L, + 0x2a2174037d6d0eL }, + { 0x776790cf9e48bdL,0x73e14a2c4ed1d3L,0x7eb5ed5f2fc2f7L, + 0x3e0aedb821b384L,0x0ee3b7e151c12fL,0x51a6a29e044bb2L, + 0x0ba13a00cb0d86L } }, + /* 196 */ + { { 0x77607d563ec8d8L,0x023fc726996e44L,0x6bd63f577a9986L, + 0x114a6351e53973L,0x3efe97989da046L,0x1051166e117ed7L, + 0x0354933dd4fb5fL }, + { 0x7699ca2f30c073L,0x4c973b83b9e6d3L,0x2017c2abdbc3e8L, + 0x0cdcdd7a26522bL,0x511070f5b23c7dL,0x70672327e83d57L, + 0x278f842b4a9f26L } }, + /* 197 */ + { { 0x0824f0d4ae972fL,0x60578dd08dcf52L,0x48a74858290fbbL, + 0x7302748bf23030L,0x184b229a178acfL,0x3e8460ade089d6L, + 0x13f2b557fad533L }, + { 0x7f96f3ae728d15L,0x018d8d40066341L,0x01fb94955a289aL, + 0x2d32ed6afc2657L,0x23f4f5e462c3acL,0x60eba5703bfc5aL, + 0x1b91cc06f16c7aL } }, + /* 198 */ + { { 0x411d68af8219b9L,0x79cca36320f4eeL,0x5c404e0ed72e20L, + 0x417cb8692e43f2L,0x305d29c7d98599L,0x3b754d5794a230L, + 0x1c97fb4be404e9L }, + { 0x7cdbafababd109L,0x1ead0eb0ca5090L,0x1a2b56095303e3L, + 0x75dea935012c8fL,0x67e31c071b1d1dL,0x7c324fbfd172c3L, + 0x157e257e6498f7L } }, + /* 199 */ + { { 0x19b00db175645bL,0x4c4f6cb69725f1L,0x36d9ce67bd47ceL, + 0x2005e105179d64L,0x7b952e717867feL,0x3c28599204032cL, + 0x0f5659d44fb347L }, + { 0x1ebcdedb979775L,0x4378d45cfd11a8L,0x14c85413ca66e9L, + 0x3dd17d681c8a4dL,0x58368e7dc23142L,0x14f3eaac6116afL, + 0x0adb45b255f6a0L } }, + /* 200 */ + { { 0x2f5e76279ad982L,0x125b3917034d09L,0x3839a6399e6ed3L, + 0x32fe0b3ebcd6a2L,0x24ccce8be90482L,0x467e26befcc187L, + 0x2828434e2e218eL }, + { 0x17247cd386efd9L,0x27f36a468d85c3L,0x65e181ef203bbfL, + 0x0433a6761120afL,0x1d607a2a8f8625L,0x49f4e55a13d919L, + 0x3367c3b7943e9dL } }, + /* 201 */ + { { 0x3391c7d1a46d4dL,0x38233d602d260cL,0x02127a0f78b7d4L, + 0x56841c162c24c0L,0x4273648fd09aa8L,0x019480bb0e754eL, + 0x3b927987b87e58L }, + { 0x6676be48c76f73L,0x01ec024e9655aeL,0x720fe1c6376704L, + 0x17e06b98885db3L,0x656adec85a4200L,0x73780893c3ce88L, + 0x0a339cdd8df664L } }, + /* 202 */ + { { 0x69af7244544ac7L,0x31ab7402084d2fL,0x67eceb7ef7cb19L, + 0x16f8583b996f61L,0x1e208d12faf91aL,0x4a91584ce4a42eL, + 0x3e08337216c93eL }, + { 0x7a6eea94f4cf77L,0x07a52894678c60L,0x302dd06b14631eL, + 0x7fddb7225c9ceaL,0x55e441d7acd153L,0x2a00d4490b0f44L, + 0x053ef125338cdbL } }, + /* 203 */ + { { 0x120c0c51584e3cL,0x78b3efca804f37L,0x662108aefb1dccL, + 0x11deb55f126709L,0x66def11ada8125L,0x05bbc0d1001711L, + 0x1ee1c99c7fa316L }, + { 0x746f287de53510L,0x1733ef2e32d09cL,0x1df64a2b0924beL, + 0x19758da8f6405eL,0x28f6eb3913e484L,0x7175a1090cc640L, + 0x048aee0d63f0bcL } }, + /* 204 */ + { { 0x1f3b1e3b0b29c3L,0x48649f4882a215L,0x485eca3a9e0dedL, + 0x4228ba85cc82e4L,0x36da1f39bc9379L,0x1659a7078499d1L, + 0x0a67d5f6c04188L }, + { 0x6ac39658afdce3L,0x0d667a0bde8ef6L,0x0ae6ec0bfe8548L, + 0x6d9cb2650571bfL,0x54bea107760ab9L,0x705c53bd340cf2L, + 0x111a86b610c70fL } }, + /* 205 */ + { { 0x7ecea05c6b8195L,0x4f8be93ce3738dL,0x305de9eb9f5d12L, + 0x2c3b9d3d474b56L,0x673691a05746c3L,0x2e3482c428c6eaL, + 0x2a8085fde1f472L }, + { 0x69d15877fd3226L,0x4609c9ec017cc3L,0x71e9b7fc1c3dbcL, + 0x4f8951254e2675L,0x63ee9d15afa010L,0x0f05775b645190L, + 0x28a0a439397ae3L } }, + /* 206 */ + { { 0x387fa03e9de330L,0x40cc32b828b6abL,0x02a482fbc04ac9L, + 0x68cad6e70429b7L,0x741877bff6f2c4L,0x48efe633d3b28bL, + 0x3e612218fe24b3L }, + { 0x6fc1d34fe37657L,0x3d04b9e1c8b5a1L,0x6a2c332ef8f163L, + 0x7ca97e2b135690L,0x37357d2a31208aL,0x29f02f2332bd68L, + 0x17c674c3e63a57L } }, + /* 207 */ + { { 0x683d9a0e6865bbL,0x5e77ec68ad4ce5L,0x4d18f236788bd6L, + 0x7f34b87204f4e3L,0x391ca40e9e578dL,0x3470ed6ddf4e23L, + 0x225544b3e50989L }, + { 0x48eda8cb4e462bL,0x2a948825cf9109L,0x473adedc7e1300L, + 0x37b843b82192edL,0x2b9ac1537dde36L,0x4efe7412732332L, + 0x29cc5981b5262bL } }, + /* 208 */ + { { 0x190d2fcad260f5L,0x7c53dd81d18027L,0x003def5f55db0eL, + 0x7f5ed25bee2df7L,0x2b87e9be167d2eL,0x2b999c7bbcd224L, + 0x1d68a2c260ad50L }, + { 0x010bcde84607a6L,0x0250de9b7e1bedL,0x746d36bfaf1b56L, + 0x3359475ff56abbL,0x7e84b9bc440b20L,0x2eaa7e3b52f162L, + 0x01165412f36a69L } }, + /* 209 */ + { { 0x639a02329e5836L,0x7aa3ee2e4d3a27L,0x5bc9b258ecb279L, + 0x4cb3dfae2d62c6L,0x08d9d3b0c6c437L,0x5a2c177d47eab2L, + 0x36120479fc1f26L }, + { 0x7609a75bd20e4aL,0x3ba414e17551fcL,0x42cd800e1b90c9L, + 0x04921811b88f9bL,0x4443697f9562fdL,0x3a8081b8186959L, + 0x3f5b5c97379e73L } }, + /* 210 */ + { { 0x6fd0e3cf13eafbL,0x3976b5415cbf67L,0x4de40889e48402L, + 0x17e4d36f24062aL,0x16ae7755cf334bL,0x2730ac94b7e0e1L, + 0x377592742f48e0L }, + { 0x5e10b18a045041L,0x682792afaae5a1L,0x19383ec971b816L, + 0x208b17dae2ffc0L,0x439f9d933179b6L,0x55485a9090bcaeL, + 0x1c316f42a2a35cL } }, + /* 211 */ + { { 0x67173897bdf646L,0x0b6956653ef94eL,0x5be3c97f7ea852L, + 0x3110c12671f08eL,0x2474076a3fc7ecL,0x53408be503fe72L, + 0x09155f53a5b44eL }, + { 0x5c804bdd4c27cdL,0x61e81eb8ffd50eL,0x2f7157fdf84717L, + 0x081f880d646440L,0x7aa892acddec51L,0x6ae70683443f33L, + 0x31ed9e8b33a75aL } }, + /* 212 */ + { { 0x0d724f8e357586L,0x1febbec91b4134L,0x6ff7b98a9475fdL, + 0x1c4d9b94e1f364L,0x2b8790499cef00L,0x42fd2080a1b31dL, + 0x3a3bbc6d9b0145L }, + { 0x75bfebc37e3ca9L,0x28db49c1723bd7L,0x50b12fa8a1f17aL, + 0x733d95bbc84b98L,0x45ede81f6c109eL,0x18f5e46fb37b5fL, + 0x34b980804aaec1L } }, + /* 213 */ + { { 0x56060c8a4f57bfL,0x0d2dfe223054c2L,0x718a5bbc03e5d6L, + 0x7b3344cc19b3b9L,0x4d11c9c054bcefL,0x1f5ad422c22e33L, + 0x2609299076f86bL }, + { 0x7b7a5fba89fd01L,0x7013113ef3b016L,0x23d5e0a173e34eL, + 0x736c14462f0f50L,0x1ef5f7ac74536aL,0x4baba6f4400ea4L, + 0x17b310612c9828L } }, + /* 214 */ + { { 0x4ebb19a708c8d3L,0x209f8c7f03d9bbL,0x00461cfe5798fbL, + 0x4f93b6ae822fadL,0x2e5b33b5ad5447L,0x40b024e547a84bL, + 0x22ffad40443385L }, + { 0x33809c888228bfL,0x559f655fefbe84L,0x0032f529fd2f60L, + 0x5a2191ece3478cL,0x5b957fcd771246L,0x6fec181f9ed123L, + 0x33eed3624136a3L } }, + /* 215 */ + { { 0x6a5df93b26139aL,0x55076598fd7134L,0x356a592f34f81dL, + 0x493c6b5a3d4741L,0x435498a4e2a39bL,0x2cd26a0d931c88L, + 0x01925ea3fc7835L }, + { 0x6e8d992b1efa05L,0x79508a727c667bL,0x5f3c15e6b4b698L, + 0x11b6c755257b93L,0x617f5af4b46393L,0x248d995b2b6656L, + 0x339db62e2e22ecL } }, + /* 216 */ + { { 0x52537a083843dcL,0x6a283c82a768c7L,0x13aa6bf25227acL, + 0x768d76ba8baf5eL,0x682977a6525808L,0x67ace52ac23b0bL, + 0x2374b5a2ed612dL }, + { 0x7139e60133c3a4L,0x715697a4f1d446L,0x4b018bf36677a0L, + 0x1dd43837414d83L,0x505ec70730d4f6L,0x09ac100907fa79L, + 0x21caad6e03217eL } }, + /* 217 */ + { { 0x0776d3999d4d49L,0x33bdd87e8bcff8L,0x1036b87f068fadL, + 0x0a9b8ffde4c872L,0x7ab2533596b1eaL,0x305a88fb965378L, + 0x3356d8fa4d65e5L }, + { 0x3366fa77d1ff11L,0x1e0bdbdcd2075cL,0x46910cefc967caL, + 0x7ce700737a1ff6L,0x1c5dc15409c9bdL,0x368436b9bdb595L, + 0x3e7ccd6560b5efL } }, + /* 218 */ + { { 0x1443789422c792L,0x524792b1717f2bL,0x1f7c1d95048e7aL, + 0x5cfe2a225b0d12L,0x245594d29ce85bL,0x20134d254ce168L, + 0x1b83296803921aL }, + { 0x79a78285b3beceL,0x3c738c3f3124d6L,0x6ab9d1fe0907cdL, + 0x0652ceb7fc104cL,0x06b5f58c8ae3fdL,0x486959261c5328L, + 0x0b3813ae677c90L } }, + /* 219 */ + { { 0x66b9941ac37b82L,0x651a4b609b0686L,0x046711edf3fc31L, + 0x77f89f38faa89bL,0x2683ddbf2d5edbL,0x389ef1dfaa3c25L, + 0x20b3616e66273eL }, + { 0x3c6db6e0cb5d37L,0x5d7ae5dc342bc4L,0x74a1dc6c52062bL, + 0x6f7c0bec109557L,0x5c51f7bc221d91L,0x0d7b5880745288L, + 0x1c46c145c4b0ddL } }, + /* 220 */ + { { 0x59ed485ea99eccL,0x201b71956bc21dL,0x72d5c32f73de65L, + 0x1aefd76547643eL,0x580a452cfb2c2dL,0x7cb1a63f5c4dc9L, + 0x39a8df727737aaL }, + { 0x365a341deca452L,0x714a1ad1689cbaL,0x16981d12c42697L, + 0x5a124f4ac91c75L,0x1b2e3f2fedc0dbL,0x4a1c72b8e9d521L, + 0x3855b4694e4e20L } }, + /* 221 */ + { { 0x16b3d047181ae9L,0x17508832f011afL,0x50d33cfeb2ebd1L, + 0x1deae237349984L,0x147c641aa6adecL,0x24a9fb4ebb1ddbL, + 0x2b367504a7a969L }, + { 0x4c55a3d430301bL,0x379ef6a5d492cbL,0x3c56541fc0f269L, + 0x73a546e91698ceL,0x2c2b62ee0b9b5dL,0x6284184d43d0efL, + 0x0e1f5cf6a4b9f0L } }, + /* 222 */ + { { 0x44833e8cd3fdacL,0x28e6665cb71c27L,0x2f8bf87f4ddbf3L, + 0x6cc6c767fb38daL,0x3bc114d734e8b5L,0x12963d5a78ca29L, + 0x34532a161ece41L }, + { 0x2443af5d2d37e9L,0x54e6008c8c452bL,0x2c55d54111cf1bL, + 0x55ac7f7522575aL,0x00a6fba3f8575fL,0x3f92ef3b793b8dL, + 0x387b97d69ecdf7L } }, + /* 223 */ + { { 0x0b464812d29f46L,0x36161daa626f9aL,0x5202fbdb264ca5L, + 0x21245805ff1304L,0x7f9c4a65657885L,0x542d3887f9501cL, + 0x086420deef8507L }, + { 0x5e159aa1b26cfbL,0x3f0ef5ffd0a50eL,0x364b29663a432aL, + 0x49c56888af32a8L,0x6f937e3e0945d1L,0x3cbdeec6d766cdL, + 0x2d80d342ece61aL } }, + /* 224 */ + { { 0x255e3026d8356eL,0x4ddba628c4de9aL,0x074323b593e0d9L, + 0x333bdb0a10eefbL,0x318b396e473c52L,0x6ebb5a95efd3d3L, + 0x3f3bff52aa4e4fL }, + { 0x3138a111c731d5L,0x674365e283b308L,0x5585edd9c416f2L, + 0x466763d9070fd4L,0x1b568befce8128L,0x16eb040e7b921eL, + 0x3d5c898687c157L } }, + /* 225 */ + { { 0x14827736973088L,0x4e110d53f301e6L,0x1f811b09870023L, + 0x53b5e500dbcacaL,0x4ddf0df1e6a7dcL,0x1e9575fb10ce35L, + 0x3fdc153644d936L }, + { 0x763547e2260594L,0x26e5ae764efc59L,0x13be6f4d791a29L, + 0x2021e61e3a0cf1L,0x339cd2b4a1c202L,0x5c7451e08f5121L, + 0x3728b3a851be68L } }, + /* 226 */ + { { 0x78873653277538L,0x444b9ed2ee7156L,0x79ac8b8b069cd3L, + 0x5f0e90933770e8L,0x307662c615389eL,0x40fe6d95a80057L, + 0x04822170cf993cL }, + { 0x677d5690fbfec2L,0x0355af4ae95cb3L,0x417411794fe79eL, + 0x48daf87400a085L,0x33521d3b5f0aaaL,0x53567a3be00ff7L, + 0x04712ccfb1cafbL } }, + /* 227 */ + { { 0x2b983283c3a7f3L,0x579f11b146a9a6L,0x1143d3b16a020eL, + 0x20f1483ef58b20L,0x3f03e18d747f06L,0x3129d12f15de37L, + 0x24c911f7222833L }, + { 0x1e0febcf3d5897L,0x505e26c01cdaacL,0x4f45a9adcff0e9L, + 0x14dfac063c5cebL,0x69e5ce713fededL,0x3481444a44611aL, + 0x0ea49295c7fdffL } }, + /* 228 */ + { { 0x64554cb4093beeL,0x344b4b18dd81f6L,0x350f43b4de9b59L, + 0x28a96a220934caL,0x4aa8da5689a515L,0x27171cbd518509L, + 0x0cfc1753f47c95L }, + { 0x7dfe091b615d6eL,0x7d1ee0aa0fb5c1L,0x145eef3200b7b5L, + 0x33fe88feeab18fL,0x1d62d4f87453e2L,0x43b8db4e47fff1L, + 0x1572f2b8b8f368L } }, + /* 229 */ + { { 0x6bc94e6b4e84f3L,0x60629dee586a66L,0x3bbad5fe65ca18L, + 0x217670db6c2fefL,0x0320a7f4e3272aL,0x3ccff0d976a6deL, + 0x3c26da8ae48cccL }, + { 0x53ecf156778435L,0x7533064765a443L,0x6c5c12f03ca5deL, + 0x44f8245350dabfL,0x342cdd777cf8b3L,0x2b539c42e9f58dL, + 0x10138affc279b1L } }, + /* 230 */ + { { 0x1b135e204c5ddbL,0x40887dfeaa1d37L,0x7fb0ef83da76ffL, + 0x521f2b79af55a5L,0x3f9b38b4c3f0d0L,0x20a9838cce61ceL, + 0x24bb4e2f4b1e32L }, + { 0x003f6aa386e27cL,0x68df59db0a0f8eL,0x21677d5192e713L, + 0x14ab9757501276L,0x411944af961524L,0x3184f39abc5c3fL, + 0x2a8dda80ca078dL } }, + /* 231 */ + { { 0x0592233cdbc95cL,0x54d5de5c66f40fL,0x351caa1512ab86L, + 0x681bdbee020084L,0x6ee2480c853e68L,0x6a5a44262b918fL, + 0x06574e15a3b91dL }, + { 0x31ba03dacd7fbeL,0x0c3da7c18a57a9L,0x49aaaded492d6bL, + 0x3071ff53469e02L,0x5efb4f0d7248c6L,0x6db5fb67f12628L, + 0x29cff668e3d024L } }, + /* 232 */ + { { 0x1b9ef3bb1b17ceL,0x6ccf8c24fe6312L,0x34c15487f45008L, + 0x1a84044095972cL,0x515073a47e449eL,0x2ddc93f9097feeL, + 0x1008fdc894c434L }, + { 0x08e5edb73399faL,0x65b1aa65547d4cL,0x3a117a1057c498L, + 0x7e16c3089d13acL,0x502f2ae4b6f851L,0x57a70f3eb62673L, + 0x111b48a9a03667L } }, + /* 233 */ + { { 0x5023024be164f1L,0x25ad117032401eL,0x46612b3bfe3427L, + 0x2f4f406a8a02b7L,0x16a93a5c4ddf07L,0x7ee71968fcdbe9L, + 0x2267875ace37daL }, + { 0x687e88b59eb2a6L,0x3ac7368fe716d3L,0x28d953a554a036L, + 0x34d52c0acca08fL,0x742a7cf8dd4fd9L,0x10bfeb8575ea60L, + 0x290e454d868dccL } }, + /* 234 */ + { { 0x4e72a3a8a4bdd2L,0x1ba36d1dee04d5L,0x7a43136b63195bL, + 0x6ca8e286a519f3L,0x568e64aece08a9L,0x571d5000b5c10bL, + 0x3f75e9f5dbdd40L }, + { 0x6fb0a698d6fa45L,0x0ce42209d7199cL,0x1f68275f708a3eL, + 0x5749832e91ec3cL,0x6c3665521428b2L,0x14b2bf5747bd4aL, + 0x3b6f940e42a22bL } }, + /* 235 */ + { { 0x4da0adbfb26c82L,0x16792a585f39acL,0x17df9dfda3975cL, + 0x4796b4afaf479bL,0x67be67234e0020L,0x69df5f201dda25L, + 0x09f71a4d12b3dcL }, + { 0x64ff5ec260a46aL,0x579c5b86385101L,0x4f29a7d549f697L, + 0x4e64261242e2ebL,0x54ecacdfb6b296L,0x46e0638b5fddadL, + 0x31eefd3208891dL } }, + /* 236 */ + { { 0x5b72c749fe01b2L,0x230cf27523713aL,0x533d1810e0d1e1L, + 0x5590db7d1dd1e2L,0x7b8ab73e8e43d3L,0x4c8a19bd1c17caL, + 0x19222ce9f74810L }, + { 0x6398b3dddc4582L,0x0352b7d88dfd53L,0x3c55b4e10c5a63L, + 0x38194d13f8a237L,0x106683fd25dd87L,0x59e0b62443458eL, + 0x196cb70aa9cbb9L } }, + /* 237 */ + { { 0x2885f7cd021d63L,0x162bfd4c3e1043L,0x77173dcf98fcd1L, + 0x13d4591d6add36L,0x59311154d0d8f2L,0x74336e86e79b8aL, + 0x13faadc5661883L }, + { 0x18938e7d9ec924L,0x14bcda8fcaa0a1L,0x706d85d41a1355L, + 0x0ac34520d168deL,0x5a92499fe17826L,0x36c2e3b4f00600L, + 0x29c2fd7b5f63deL } }, + /* 238 */ + { { 0x41250dfe2216c5L,0x44a0ec0366a217L,0x575bc1adf8b0dfL, + 0x5ff5cdbdb1800bL,0x7843d4dde8ca18L,0x5fa9e420865705L, + 0x235c38be6c6b02L }, + { 0x473b78aae91abbL,0x39470c6051e44bL,0x3f973cc2dc08c3L, + 0x2837932c5c91f6L,0x25e39ed754ec25L,0x1371c837118e53L, + 0x3b99f3b0aeafe2L } }, + /* 239 */ + { { 0x03acf51be46c65L,0x271fceacbaf5c3L,0x476589ed3a5e25L, + 0x78ec8c3c3c399cL,0x1f5c8bf4ac4c19L,0x730bb733ec68d2L, + 0x29a37e00dd287eL }, + { 0x448ed1bf92b5faL,0x10827c17b86478L,0x55e6fc05b28263L, + 0x0af1226c73a66aL,0x0b66e5df0d09c1L,0x26128315a02682L, + 0x22d84932c5e808L } }, + /* 240 */ + { { 0x5ec3afc26e3392L,0x08e142e45c0084L,0x4388d5ad0f01feL, + 0x0f7acd36e6140cL,0x028c14ed97dffbL,0x311845675a38c6L, + 0x01c1c8f09a3062L }, + { 0x5a302f4cf49e7dL,0x79267e254a44e1L,0x746165052317a1L, + 0x53a09263a566e8L,0x7d478ad5f73abcL,0x187ce5c947dad3L, + 0x18564e1a1ec45fL } }, + /* 241 */ + { { 0x7b9577a9aa0486L,0x766b40c7aaaef6L,0x1f6a411f5db907L, + 0x4543dd4d80beaeL,0x0ad938c7482806L,0x451568bf4b9be1L, + 0x3367ec85d30a22L }, + { 0x5446425747843dL,0x18d94ac223c6b2L,0x052ff3a354d359L, + 0x0b4933f89723f5L,0x03fb517740e056L,0x226b892871dddaL, + 0x2768c2b753f0fdL } }, + /* 242 */ + { { 0x685282ccfa5200L,0x411ed433627b89L,0x77d5c9b8bc9c1dL, + 0x4a13ef2ee5cd29L,0x5582a612407c9eL,0x2307cb42fc3aa9L, + 0x2e661df79956b8L }, + { 0x0e972b015254deL,0x5b63e14def8adeL,0x06995be2ca4a95L, + 0x6cc0cc1e94bf27L,0x7ed8499fe0052aL,0x671a6ca5a5e0f9L, + 0x31e10d4ba10f05L } }, + /* 243 */ + { { 0x690af07e9b2d8aL,0x6030af9e32c8ddL,0x45c7ca3bf2b235L, + 0x40959077b76c81L,0x61eee7f70d5a96L,0x6b04f6aafe9e38L, + 0x3c726f55f1898dL }, + { 0x77d0142a1a6194L,0x1c1631215708b9L,0x403a4f0a9b7585L, + 0x066c8e29f7cef0L,0x6fc32f98cf575eL,0x518a09d818c297L, + 0x34144e99989e75L } }, + /* 244 */ + { { 0x6adbada859fb6aL,0x0dcfb6506ccd51L,0x68f88b8d573e0dL, + 0x4b1ce35bd9af30L,0x241c8293ece2c9L,0x3b5f402c5c4adeL, + 0x34b9b1ee6fde87L }, + { 0x5e625340075e63L,0x54c3f3d9050da1L,0x2a3f9152509016L, + 0x3274e46111bc18L,0x3a7504fd01ac73L,0x4169b387a43209L, + 0x35626f852bc6d4L } }, + /* 245 */ + { { 0x576a4f4662e53bL,0x5ea3f20eecec26L,0x4e5f02be5cd7b0L, + 0x72cc5ac3314be8L,0x0f604ed3201fe9L,0x2a29378ea54bceL, + 0x2d52bd4d6ec4b6L }, + { 0x6a4c2b212c1c76L,0x778fd64a1bfa6dL,0x326828691863d6L, + 0x5616c8bd06a336L,0x5fab552564da4dL,0x46640cab3e91d2L, + 0x1d21f06427299eL } }, + /* 246 */ + { { 0x2bfe37dde98e9cL,0x164c54822332ebL,0x5b736c7df266e4L, + 0x59dab3a8da084cL,0x0ae1eab346f118L,0x182090a4327e3fL, + 0x07b13489dae2e6L }, + { 0x3bc92645452baaL,0x30b159894ae574L,0x5b947c5c78e1f4L, + 0x18f0e004a3c77fL,0x48ca8f357077d9L,0x349ffdcef9bca9L, + 0x3ed224bfd54772L } }, + /* 247 */ + { { 0x1bdad02db8dff8L,0x69fab4450b44b6L,0x3b6802d187518bL, + 0x098368d8eb556cL,0x3fe1943fbefcf4L,0x008851d0de6d42L, + 0x322cbc4605fe25L }, + { 0x2528aaf0d51afbL,0x7d48a9363a0cecL,0x4ba8f77d9a8f8bL, + 0x7dee903437d6c7L,0x1ff5a0d9ccc4b4L,0x34d9bd2fa99831L, + 0x30d9e4f58667c6L } }, + /* 248 */ + { { 0x38909b51b85197L,0x7ba16992512bd4L,0x2c776cfcfffec5L, + 0x2be7879075843cL,0x557e2b05d28ffcL,0x641b17bc5ce357L, + 0x1fcaf8a3710306L }, + { 0x54dca2299a2d48L,0x745d06ef305acaL,0x7c41c65c6944c2L, + 0x679412ec431902L,0x48f2b15ee62827L,0x341a96d8afe06eL, + 0x2a78fd3690c0e1L } }, + /* 249 */ + { { 0x6b7cec83fbc9c6L,0x238e8a82eefc67L,0x5d3c1d9ff0928cL, + 0x55b816d6409bbfL,0x7969612adae364L,0x55b6ff96db654eL, + 0x129beca10073a9L }, + { 0x0b1d2acdfc73deL,0x5d1a3605fa64bdL,0x436076146743beL, + 0x64044b89fcce0cL,0x7ae7b3c18f7fafL,0x7f083ee27cea36L, + 0x0292cd0d7c1ff0L } }, + /* 250 */ + { { 0x5a3c4c019b7d2eL,0x1a35a9b89712fbL,0x38736cc4f18c72L, + 0x603dd832a44e6bL,0x000d1d44aed104L,0x69b1f2fc274ebeL, + 0x03a7b993f76977L }, + { 0x299f3b3e346910L,0x5243f45295afd5L,0x34342cbfa588bdL, + 0x72c40dd1155510L,0x718024fed2f991L,0x2f935e765ad82aL, + 0x246799ea371fb8L } }, + /* 251 */ + { { 0x24fe4c76250533L,0x01cafb02fdf18eL,0x505cb25d462882L, + 0x3e038175157d87L,0x7e3e99b10cdeb1L,0x38b7e72ebc7936L, + 0x081845f7c73433L }, + { 0x049e61be05ebd5L,0x6ab82d8f0581f6L,0x62adffb427ac2eL, + 0x19431f809d198dL,0x36195f6c58b1d6L,0x22cc4c9dedc9a7L, + 0x24b146d8e694fcL } }, + /* 252 */ + { { 0x7c7bc8288b364dL,0x5c10f683cb894aL,0x19a62a68452958L, + 0x1fc24dcb4ce90eL,0x726baa4ed9581fL,0x1f34447dde73d6L, + 0x04c56708f30a21L }, + { 0x131e583a3f4963L,0x071215b4d502e7L,0x196aca542e5940L, + 0x3afd5a91f7450eL,0x671b6eedf49497L,0x6aac7aca5c29e4L, + 0x3fb512470f138bL } }, + /* 253 */ + { { 0x5eadc3f4eb453eL,0x16c795ba34b666L,0x5d7612a4697fddL, + 0x24dd19bb499e86L,0x415b89ca3eeb9bL,0x7c83edf599d809L, + 0x13bc64c9b70269L }, + { 0x52d3243dca3233L,0x0b21444b3a96a7L,0x6d551bc0083b90L, + 0x4f535b88c61176L,0x11e61924298010L,0x0a155b415bb61dL, + 0x17f94fbd26658fL } }, + /* 254 */ + { { 0x2dd06b90c28c65L,0x48582339c8fa6eL,0x01ac8bf2085d94L, + 0x053e660e020fdcL,0x1bece667edf07bL,0x4558f2b33ce24cL, + 0x2f1a766e8673fcL }, + { 0x1d77cd13c06819L,0x4d5dc5056f3a01L,0x18896c6fa18d69L, + 0x120047ca76d625L,0x6af8457d4f4e45L,0x70ddc53358b60aL, + 0x330e11130e82f0L } }, + /* 255 */ + { { 0x0643b1cd4c2356L,0x10a2ea0a8f7c92L,0x2752513011d029L, + 0x4cd4c50321f579L,0x5fdf9ba5724792L,0x2f691653e2ddc0L, + 0x0cfed3d84226cbL }, + { 0x704902a950f955L,0x069bfdb87bbf0cL,0x5817eeda8a5f84L, + 0x1914cdd9089905L,0x0e4a323d7b93f4L,0x1cc3fc340af0b2L, + 0x23874161bd6303L } }, +}; + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_7(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + return sp_384_ecc_mulmod_stripe_7(r, &p384_base, p384_table, + k, map, heap); +} + +#endif + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[7]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_384_point_new_7(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 7, km); + + err = sp_384_ecc_mulmod_base_7(point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_7(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_7(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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_384_iszero_7(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_add_one_7(sp_digit* a) +{ + a[0]++; + sp_384_norm_7(a); +} + +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 47U) { + r[j] &= 0x7fffffffffffffL; + s = 55U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; 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_384_ecc_gen_k_7(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[48]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_384_from_bin(k, 7, buf, (int)sizeof(buf)); + if (sp_384_cmp_7(k, p384_order2) < 0) { + sp_384_add_one_7(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_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[7]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 inf; +#endif +#endif + sp_point_384* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity; +#endif + int err; + + (void)heap; + + err = sp_384_point_new_7(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_point_new_7(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + err = sp_384_ecc_gen_k_7(rng, k); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_7(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_7(infinity, point, p384_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_384_iszero_7(point->x) == 0) || (sp_384_iszero_7(point->y) == 0)) { + err = ECC_INF_E; + } + } +#endif + + if (err == MP_OKAY) { + err = sp_384_to_mp(k, priv); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_7(point, pub); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_384_point_free_7(infinity, 1, heap); +#endif + sp_384_point_free_7(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 48 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_384_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<6; i++) { + r[i+1] += r[i] >> 55; + r[i] &= 0x7fffffffffffffL; + } + j = 384 / 8 - 1; + a[j] = 0; + for (i=0; i<7 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 55) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 55); + if (j >= 0) { + 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_384(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[7]; +#endif + sp_point_384* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 48U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_384_point_new_7(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(k, 7, priv); + sp_384_point_from_ecc_point_7(point, pub); + err = sp_384_ecc_mulmod_7(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_384_to_bin(point->x, out); + *outLen = 48; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_7(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#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. + */ +SP_NOINLINE static void sp_384_mul_d_7(sp_digit* r, const sp_digit* a, + sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 7; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffffffffffffL; + t >>= 55; + } + r[7] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[7]; + + 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]; + r[ 0] = (t[ 0] & 0x7fffffffffffffL); + r[ 1] = (sp_digit)(t[ 0] >> 55) + (t[ 1] & 0x7fffffffffffffL); + r[ 2] = (sp_digit)(t[ 1] >> 55) + (t[ 2] & 0x7fffffffffffffL); + r[ 3] = (sp_digit)(t[ 2] >> 55) + (t[ 3] & 0x7fffffffffffffL); + r[ 4] = (sp_digit)(t[ 3] >> 55) + (t[ 4] & 0x7fffffffffffffL); + r[ 5] = (sp_digit)(t[ 4] >> 55) + (t[ 5] & 0x7fffffffffffffL); + r[ 6] = (sp_digit)(t[ 5] >> 55) + (t[ 6] & 0x7fffffffffffffL); + r[ 7] = (sp_digit)(t[ 6] >> 55); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_384_div_word_7(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t; + + /* All 55 bits from d1 and top 8 bits from d0. */ + d = (d1 << 8) | (d0 >> 47); + r = d / dv; + d -= r * dv; + /* Up to 9 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 39) & ((1 << 8) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 17 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 31) & ((1 << 8) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 25 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 23) & ((1 << 8) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 33 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 15) & ((1 << 8) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 41 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 7) & ((1 << 8) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 49 bits in r */ + /* Remaining 7 bits from d0. */ + r <<= 7; + d <<= 7; + d |= d0 & ((1 << 7) - 1); + t = d / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* 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 Number 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_384_div_7(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit dv, r1; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* td; +#else + sp_digit t1d[14], t2d[7 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 7 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = td; + t2 = td + 2 * 7; +#else + t1 = t1d; + t2 = t2d; +#endif + + dv = d[6]; + XMEMCPY(t1, a, sizeof(*t1) * 2U * 7U); + for (i=6; i>=0; i--) { + t1[7 + i] += t1[7 + i - 1] >> 55; + t1[7 + i - 1] &= 0x7fffffffffffffL; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[7 + i]; + d1 <<= 55; + d1 += t1[7 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_384_div_word_7(t1[7 + i], t1[7 + i - 1], dv); +#endif + + sp_384_mul_d_7(t2, d, r1); + (void)sp_384_sub_7(&t1[i], &t1[i], t2); + t1[7 + i] -= t2[7]; + t1[7 + i] += t1[7 + i - 1] >> 55; + t1[7 + i - 1] &= 0x7fffffffffffffL; + r1 = (((-t1[7 + i]) << 55) - t1[7 + i - 1]) / dv; + r1++; + sp_384_mul_d_7(t2, d, r1); + (void)sp_384_add_7(&t1[i], &t1[i], t2); + t1[7 + i] += t1[7 + i - 1] >> 55; + t1[7 + i - 1] &= 0x7fffffffffffffL; + } + t1[7 - 1] += t1[7 - 2] >> 55; + t1[7 - 2] &= 0x7fffffffffffffL; + r1 = t1[7 - 1] / dv; + + sp_384_mul_d_7(t2, d, r1); + (void)sp_384_sub_7(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 7U); + for (i=0; i<5; i++) { + r[i+1] += r[i] >> 55; + r[i] &= 0x7fffffffffffffL; + } + sp_384_cond_add_7(r, r, d, 0 - ((r[6] < 0) ? + (sp_digit)1 : (sp_digit)0)); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_384_mod_7(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_384_div_7(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P384 curve. */ +static const uint64_t p384_order_minus_2[6] = { + 0xecec196accc52971U,0x581a0db248b0a77aU,0xc7634d81f4372ddfU, + 0xffffffffffffffffU,0xffffffffffffffffU,0xffffffffffffffffU +}; +#else +/* The low half of the order-2 of the P384 curve. */ +static const uint64_t p384_order_low[3] = { + 0xecec196accc52971U,0x581a0db248b0a77aU,0xc7634d81f4372ddfU + +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P384 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_384_mont_mul_order_7(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_384_mul_7(r, a, b); + sp_384_mont_reduce_order_7(r, p384_order, p384_mp_order); +} + +/* Square number mod the order of P384 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_order_7(sp_digit* r, const sp_digit* a) +{ + sp_384_sqr_7(r, a); + sp_384_mont_reduce_order_7(r, p384_order, p384_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P384 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_n_order_7(sp_digit* r, const sp_digit* a, int n) +{ + int i; + + sp_384_mont_sqr_order_7(r, a); + for (i=1; i=0; i--) { + sp_384_mont_sqr_order_7(t, t); + if ((p384_order_minus_2[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + sp_384_mont_mul_order_7(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 7U); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 7; + sp_digit* t3 = td + 4 * 7; + int i; + + /* t = a^2 */ + sp_384_mont_sqr_order_7(t, a); + /* t = a^3 = t * a */ + sp_384_mont_mul_order_7(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_384_mont_sqr_n_order_7(t2, t, 2); + /* t = a^f = t2 * t */ + sp_384_mont_mul_order_7(t, t2, t); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_384_mont_sqr_n_order_7(t2, t, 4); + /* t = a^ff = t2 * t */ + sp_384_mont_mul_order_7(t, t2, t); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_384_mont_sqr_n_order_7(t2, t, 8); + /* t3= a^ffff = t2 * t */ + sp_384_mont_mul_order_7(t3, t2, t); + /* t2= a^ffff0000 = t3 ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_7(t2, t3, 16); + /* t = a^ffffffff = t2 * t3 */ + sp_384_mont_mul_order_7(t, t2, t3); + /* t2= a^ffffffff0000 = t ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_7(t2, t, 16); + /* t = a^ffffffffffff = t2 * t3 */ + sp_384_mont_mul_order_7(t, t2, t3); + /* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */ + sp_384_mont_sqr_n_order_7(t2, t, 48); + /* t= a^fffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_7(t, t2, t); + /* t2= a^ffffffffffffffffffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_order_7(t2, t, 96); + /* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_7(t2, t2, t); + for (i=191; i>=1; i--) { + sp_384_mont_sqr_order_7(t2, t2); + if (((sp_digit)p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + sp_384_mont_mul_order_7(t2, t2, a); + } + } + sp_384_mont_sqr_order_7(t2, t2); + sp_384_mont_mul_order_7(r, t2, a); +#endif /* WOLFSSL_SP_SMALL */ +} + +#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, 384 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 384 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_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit ed[2*7]; + sp_digit xd[2*7]; + sp_digit kd[2*7]; + sp_digit rd[2*7]; + sp_digit td[3 * 2*7]; + sp_point_384 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_384* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int64_t c; + int i; + + (void)heap; + + err = sp_384_point_new_7(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 7, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 7; + x = d + 2 * 7; + k = d + 4 * 7; + r = d + 6 * 7; + tmp = d + 8 * 7; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(e, 7, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_384_from_mp(x, 7, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_7(rng, k); + } + else { + sp_384_from_mp(k, 7, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_7(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 7U); + sp_384_norm_7(r); + c = sp_384_cmp_7(r, p384_order); + sp_384_cond_sub_7(r, r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_7(r); + + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_7(k, k, p384_norm_order); + err = sp_384_mod_7(k, k, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_7(k); + /* kInv = 1/k mod order */ + sp_384_mont_inv_order_7(kInv, k, tmp); + sp_384_norm_7(kInv); + + /* s = r * x + e */ + sp_384_mul_7(x, x, r); + err = sp_384_mod_7(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_7(x); + carry = sp_384_add_7(s, e, x); + sp_384_cond_sub_7(s, s, p384_order, 0 - carry); + sp_384_norm_7(s); + c = sp_384_cmp_7(s, p384_order); + sp_384_cond_sub_7(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_7(s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_7(s, s, kInv); + sp_384_norm_7(s); + + /* Check that signature is usable. */ + if (sp_384_iszero_7(s) == 0) { + break; + } + } + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 7); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 7U); +#endif + sp_384_point_free_7(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, 384) + * 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 384 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_384(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit u1d[2*7]; + sp_digit u2d[2*7]; + sp_digit sd[2*7]; + sp_digit tmpd[2*7 * 5]; + sp_point_384 p1d; + sp_point_384 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p1; + sp_point_384* p2 = NULL; + sp_digit carry; + int64_t c; + int err; + + err = sp_384_point_new_7(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_384_point_new_7(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 7, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 7; + u2 = d + 2 * 7; + s = d + 4 * 7; + tmp = d + 6 * 7; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 7, hash, (int)hashLen); + sp_384_from_mp(u2, 7, r); + sp_384_from_mp(s, 7, sm); + sp_384_from_mp(p2->x, 7, pX); + sp_384_from_mp(p2->y, 7, pY); + sp_384_from_mp(p2->z, 7, pZ); + + { + sp_384_mul_7(s, s, p384_norm_order); + } + err = sp_384_mod_7(s, s, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_7(s); + { + sp_384_mont_inv_order_7(s, s, tmp); + sp_384_mont_mul_order_7(u1, u1, s); + sp_384_mont_mul_order_7(u2, u2, s); + } + + err = sp_384_ecc_mulmod_base_7(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_7(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + { + sp_384_proj_point_add_7(p1, p1, p2, tmp); + if (sp_384_iszero_7(p1->z)) { + if (sp_384_iszero_7(p1->x) && sp_384_iszero_7(p1->y)) { + sp_384_proj_point_dbl_7(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + } + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 7, r); + err = sp_384_mod_mul_norm_7(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_7(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_7(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 7, r); + carry = sp_384_add_7(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_7(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_7(u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_7(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_7(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_7(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_384_point_free_7(p1, 0, heap); + sp_384_point_free_7(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_384_ecc_is_point_7(sp_point_384* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*7]; + sp_digit t2d[2*7]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 7; + t2 = d + 2 * 7; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_384_sqr_7(t1, point->y); + (void)sp_384_mod_7(t1, t1, p384_mod); + sp_384_sqr_7(t2, point->x); + (void)sp_384_mod_7(t2, t2, p384_mod); + sp_384_mul_7(t2, t2, point->x); + (void)sp_384_mod_7(t2, t2, p384_mod); + (void)sp_384_sub_7(t2, p384_mod, t2); + sp_384_mont_add_7(t1, t1, t2, p384_mod); + + sp_384_mont_add_7(t1, t1, point->x, p384_mod); + sp_384_mont_add_7(t1, t1, point->x, p384_mod); + sp_384_mont_add_7(t1, t1, point->x, p384_mod); + + if (sp_384_cmp_7(t1, p384_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 pubd; +#endif + sp_point_384* pub; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_7(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_384_from_mp(pub->x, 7, pX); + sp_384_from_mp(pub->y, 7, pY); + sp_384_from_bin(pub->z, 7, one, (int)sizeof(one)); + + err = sp_384_ecc_is_point_7(pub, NULL); + } + + sp_384_point_free_7(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[7]; + sp_point_384 pubd; + sp_point_384 pd; +#endif + sp_digit* priv = NULL; + sp_point_384* pub; + sp_point_384* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_7(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_384_point_new_7(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_384_from_mp(pub->x, 7, pX); + sp_384_from_mp(pub->y, 7, pY); + sp_384_from_bin(pub->z, 7, one, (int)sizeof(one)); + sp_384_from_mp(priv, 7, privm); + + /* Check point at infinitiy. */ + if ((sp_384_iszero_7(pub->x) != 0) && + (sp_384_iszero_7(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_384_cmp_7(pub->x, p384_mod) >= 0 || + sp_384_cmp_7(pub->y, p384_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_384_ecc_is_point_7(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_384_ecc_mulmod_7(p, pub, p384_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_384_iszero_7(p->x) == 0) || + (sp_384_iszero_7(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_384_ecc_mulmod_base_7(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_384_cmp_7(p->x, pub->x) != 0 || + sp_384_cmp_7(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_7(p, 0, heap); + sp_384_point_free_7(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 7 * 5]; + sp_point_384 pd; + sp_point_384 qd; +#endif + sp_digit* tmp; + sp_point_384* p; + sp_point_384* q = NULL; + int err; + + err = sp_384_point_new_7(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_384_point_new_7(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 7, pX); + sp_384_from_mp(p->y, 7, pY); + sp_384_from_mp(p->z, 7, pZ); + sp_384_from_mp(q->x, 7, qX); + sp_384_from_mp(q->y, 7, qY); + sp_384_from_mp(q->z, 7, qZ); + + sp_384_proj_point_add_7(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_7(q, 0, NULL); + sp_384_point_free_7(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 7 * 2]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_7(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 7, pX); + sp_384_from_mp(p->y, 7, pY); + sp_384_from_mp(p->z, 7, pZ); + + sp_384_proj_point_dbl_7(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_7(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 7 * 6]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_7(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 6, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 7, pX); + sp_384_from_mp(p->y, 7, pY); + sp_384_from_mp(p->z, 7, pZ); + + sp_384_map_7(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_7(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mont_sqrt_7(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 7]; + sp_digit t2d[2 * 7]; + sp_digit t3d[2 * 7]; + sp_digit t4d[2 * 7]; + sp_digit t5d[2 * 7]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 7, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 7; + t2 = d + 2 * 7; + t3 = d + 4 * 7; + t4 = d + 6 * 7; + t5 = d + 8 * 7; +#else + t1 = t1d; + t2 = t2d; + t3 = t3d; + t4 = t4d; + t5 = t5d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_384_mont_sqr_7(t2, y, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3 */ + sp_384_mont_mul_7(t1, t2, y, p384_mod, p384_mp_mod); + /* t5 = y ^ 0xc */ + sp_384_mont_sqr_n_7(t5, t1, 2, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xf */ + sp_384_mont_mul_7(t1, t1, t5, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x1e */ + sp_384_mont_sqr_7(t2, t1, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x1f */ + sp_384_mont_mul_7(t3, t2, y, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3e0 */ + sp_384_mont_sqr_n_7(t2, t3, 5, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3ff */ + sp_384_mont_mul_7(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fe0 */ + sp_384_mont_sqr_n_7(t2, t1, 5, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x7fff */ + sp_384_mont_mul_7(t3, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fff800 */ + sp_384_mont_sqr_n_7(t2, t3, 15, p384_mod, p384_mp_mod); + /* t4 = y ^ 0x3ffffff */ + sp_384_mont_mul_7(t4, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffc000000 */ + sp_384_mont_sqr_n_7(t2, t4, 30, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffff */ + sp_384_mont_mul_7(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_7(t2, t1, 60, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_7(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_7(t2, t1, 120, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_7(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_7(t2, t1, 15, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_7(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */ + sp_384_mont_sqr_n_7(t2, t1, 31, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */ + sp_384_mont_mul_7(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */ + sp_384_mont_sqr_n_7(t2, t1, 4, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */ + sp_384_mont_mul_7(t1, t5, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */ + sp_384_mont_sqr_n_7(t2, t1, 62, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */ + sp_384_mont_mul_7(t1, y, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */ + sp_384_mont_sqr_n_7(y, t1, 30, p384_mod, p384_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 7]; + sp_digit yd[2 * 7]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 7, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 7; + y = d + 2 * 7; +#else + x = xd; + y = yd; +#endif + + sp_384_from_mp(x, 7, xm); + err = sp_384_mod_mul_norm_7(x, x, p384_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_384_mont_sqr_7(y, x, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(y, y, x, p384_mod, p384_mp_mod); + } + /* y = x^3 - 3x */ + sp_384_mont_sub_7(y, y, x, p384_mod); + sp_384_mont_sub_7(y, y, x, p384_mod); + sp_384_mont_sub_7(y, y, x, p384_mod); + /* y = x^3 - 3x + b */ + err = sp_384_mod_mul_norm_7(x, p384_b, p384_mod); + } + if (err == MP_OKAY) { + sp_384_mont_add_7(y, y, x, p384_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_384_mont_sqrt_7(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 7, 0, 7U * sizeof(sp_digit)); + sp_384_mont_reduce_7(y, p384_mod, p384_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_384_mont_sub_7(y, p384_mod, y, p384_mod); + } + + err = sp_384_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_384 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* SP_WORD_SIZE == 64 */ +#endif /* !WOLFSSL_SP_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_cortexm.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_cortexm.c new file mode 100644 index 000000000..b03de8ab4 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_cortexm.c @@ -0,0 +1,25687 @@ +/* sp.c + * + * Copyright (C) 2006-2020 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 +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifdef __IAR_SYSTEMS_ICC__ +#define __asm__ asm +#define __volatile__ volatile +#endif /* __IAR_SYSTEMS_ICC__ */ +#ifdef __KEIL__ +#define __asm__ __asm +#define __volatile__ volatile +#endif + +#ifdef WOLFSSL_SP_ARM_CORTEX_M_ASM +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * 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<64 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + 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. + */ +SP_NOINLINE static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[8]; + + __asm__ __volatile__ ( + /* A[0] * B[0] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r3, r4, r6, r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[tmp], #0]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[1] */ + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r8\n\t" + /* A[1] * B[0] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[tmp], #4]\n\t" + "mov r4, #0\n\t" + /* A[0] * B[2] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * B[1] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * B[0] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[tmp], #8]\n\t" + "mov r5, #0\n\t" + /* A[0] * B[3] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[1] * B[2] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[2] * B[1] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * B[0] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[tmp], #12]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[4] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[1] * B[3] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[2] * B[2] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[3] * B[1] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[4] * B[0] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[tmp], #16]\n\t" + "mov r4, #0\n\t" + /* A[0] * B[5] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * B[4] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * B[3] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * B[2] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[4] * B[1] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * B[0] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[tmp], #20]\n\t" + "mov r5, #0\n\t" + /* A[0] * B[6] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[1] * B[5] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[2] * B[4] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * B[3] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[4] * B[2] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[5] * B[1] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * B[0] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[tmp], #24]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[7] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[1] * B[6] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[2] * B[5] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[3] * B[4] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[4] * B[3] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[5] * B[2] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[6] * B[1] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[7] * B[0] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[tmp], #28]\n\t" + "mov r4, #0\n\t" + /* A[1] * B[7] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * B[6] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * B[5] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[4] * B[4] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * B[3] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[6] * B[2] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[7] * B[1] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[r], #32]\n\t" + "mov r5, #0\n\t" + /* A[2] * B[7] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * B[6] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[4] * B[5] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[5] * B[4] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * B[3] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[7] * B[2] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[r], #36]\n\t" + "mov r3, #0\n\t" + /* A[3] * B[7] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[4] * B[6] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[5] * B[5] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[6] * B[4] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[7] * B[3] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[r], #40]\n\t" + "mov r4, #0\n\t" + /* A[4] * B[7] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * B[6] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[6] * B[5] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[7] * B[4] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[r], #44]\n\t" + "mov r5, #0\n\t" + /* A[5] * B[7] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * B[6] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[7] * B[5] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[r], #48]\n\t" + "mov r3, #0\n\t" + /* A[6] * B[7] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[7] * B[6] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[r], #52]\n\t" + "mov r4, #0\n\t" + /* A[7] * B[7] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r8\n\t" + "str r5, [%[r], #56]\n\t" + "str r3, [%[r], #60]\n\t" + /* Transfer tmp to r */ + "ldr r3, [%[tmp], #0]\n\t" + "ldr r4, [%[tmp], #4]\n\t" + "ldr r5, [%[tmp], #8]\n\t" + "ldr r6, [%[tmp], #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[tmp], #16]\n\t" + "ldr r4, [%[tmp], #20]\n\t" + "ldr r5, [%[tmp], #24]\n\t" + "ldr r6, [%[tmp], #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "r3", "r4", "r5", "r6", "r8" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[8]; + __asm__ __volatile__ ( + /* A[0] * A[0] */ + "ldr r6, [%[a], #0]\n\t" + "umull r3, r4, r6, r6\n\t" + "mov r5, #0\n\t" + "str r3, [%[tmp], #0]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[1] */ + "ldr r8, [%[a], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[tmp], #4]\n\t" + "mov r4, #0\n\t" + /* A[0] * A[2] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * A[1] */ + "ldr r6, [%[a], #4]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[tmp], #8]\n\t" + "mov r5, #0\n\t" + /* A[0] * A[3] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[2] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adc r5, r5, r11\n\t" + "str r3, [%[tmp], #12]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[4] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[3] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[2] * A[2] */ + "ldr r6, [%[a], #8]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r4, r4, r9\n\t" + "adcs r5, r5, r10\n\t" + "adc r3, r3, r11\n\t" + "str r4, [%[tmp], #16]\n\t" + "mov r4, #0\n\t" + /* A[0] * A[5] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[4] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[2] * A[3] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r5, r5, r9\n\t" + "adcs r3, r3, r10\n\t" + "adc r4, r4, r11\n\t" + "str r5, [%[tmp], #20]\n\t" + "mov r5, #0\n\t" + /* A[0] * A[6] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[5] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[2] * A[4] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[3] * A[3] */ + "ldr r6, [%[a], #12]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adc r5, r5, r11\n\t" + "str r3, [%[tmp], #24]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[7] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[6] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[2] * A[5] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[3] * A[4] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r4, r4, r9\n\t" + "adcs r5, r5, r10\n\t" + "adc r3, r3, r11\n\t" + "str r4, [%[tmp], #28]\n\t" + "mov r4, #0\n\t" + /* A[1] * A[7] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[2] * A[6] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[3] * A[5] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[4] * A[4] */ + "ldr r6, [%[a], #16]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r5, r5, r9\n\t" + "adcs r3, r3, r10\n\t" + "adc r4, r4, r11\n\t" + "str r5, [%[r], #32]\n\t" + "mov r5, #0\n\t" + /* A[2] * A[7] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[3] * A[6] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[4] * A[5] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adc r5, r5, r11\n\t" + "str r3, [%[r], #36]\n\t" + "mov r3, #0\n\t" + /* A[3] * A[7] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[4] * A[6] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[5] * A[5] */ + "ldr r6, [%[a], #20]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r4, r4, r9\n\t" + "adcs r5, r5, r10\n\t" + "adc r3, r3, r11\n\t" + "str r4, [%[r], #40]\n\t" + "mov r4, #0\n\t" + /* A[4] * A[7] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * A[6] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[r], #44]\n\t" + "mov r5, #0\n\t" + /* A[5] * A[7] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * A[6] */ + "ldr r6, [%[a], #24]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[r], #48]\n\t" + "mov r3, #0\n\t" + /* A[6] * A[7] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[r], #52]\n\t" + "mov r4, #0\n\t" + /* A[7] * A[7] */ + "ldr r6, [%[a], #28]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r8\n\t" + "str r5, [%[r], #56]\n\t" + "str r3, [%[r], #60]\n\t" + /* Transfer tmp to r */ + "ldr r3, [%[tmp], #0]\n\t" + "ldr r4, [%[tmp], #4]\n\t" + "ldr r5, [%[tmp], #8]\n\t" + "ldr r6, [%[tmp], #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[tmp], #16]\n\t" + "ldr r4, [%[tmp], #20]\n\t" + "ldr r5, [%[tmp], #24]\n\t" + "ldr r6, [%[tmp], #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_16(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + 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_8(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[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. + */ +SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit b1[8]; + sp_digit z2[16]; + sp_digit u, ca, cb; + + ca = sp_2048_add_8(a1, a, &a[8]); + cb = sp_2048_add_8(b1, b, &b[8]); + u = ca & cb; + sp_2048_mul_8(z1, a1, b1); + sp_2048_mul_8(z2, &a[8], &b[8]); + sp_2048_mul_8(z0, a, b); + sp_2048_mask_8(r + 16, a1, 0 - cb); + sp_2048_mask_8(b1, b1, 0 - ca); + u += sp_2048_add_8(r + 16, r + 16, b1); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + (void)sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[16]; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit u; + + u = sp_2048_add_8(a1, a, &a[8]); + sp_2048_sqr_8(z1, a1); + sp_2048_sqr_8(z2, &a[8]); + sp_2048_sqr_8(z0, a); + sp_2048_mask_8(r + 16, a1, 0 - u); + u += sp_2048_add_8(r + 16, r + 16, r + 16); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + (void)sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_32(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + 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, const 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. + */ +SP_NOINLINE 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)); + (void)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. + */ +SP_NOINLINE 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)); + (void)sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_64(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + 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_32(sp_digit* r, const 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 +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit b1[32]; + sp_digit z2[64]; + sp_digit u, ca, cb; + + ca = sp_2048_add_32(a1, a, &a[32]); + cb = sp_2048_add_32(b1, b, &b[32]); + u = ca & cb; + sp_2048_mul_32(z1, a1, b1); + sp_2048_mul_32(z2, &a[32], &b[32]); + sp_2048_mul_32(z0, a, b); + sp_2048_mask_32(r + 64, a1, 0 - cb); + sp_2048_mask_32(b1, b1, 0 - ca); + u += sp_2048_add_32(r + 64, r + 64, b1); + u += sp_2048_sub_in_place_64(z1, z2); + u += sp_2048_sub_in_place_64(z1, z0); + u += sp_2048_add_64(r + 32, r + 32, z1); + r[96] = u; + XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1)); + (void)sp_2048_add_64(r + 64, r + 64, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[64]; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit u; + + u = sp_2048_add_32(a1, a, &a[32]); + sp_2048_sqr_32(z1, a1); + sp_2048_sqr_32(z2, &a[32]); + sp_2048_sqr_32(z0, a); + sp_2048_mask_32(r + 64, a1, 0 - u); + u += sp_2048_add_32(r + 64, r + 64, r + 64); + u += sp_2048_sub_in_place_64(z1, z2); + u += sp_2048_sub_in_place_64(z1, z0); + u += sp_2048_add_64(r + 32, r + 32, z1); + r[96] = u; + XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1)); + (void)sp_2048_add_64(r + 64, r + 64, z2); +} + +#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. + */ +SP_NOINLINE static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r8, #0\n\t" + "add r6, r6, #256\n\t" + "sub r8, r8, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r8\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_64(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r8, %[a]\n\t" + "add r8, r8, #256\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r8\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[64 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r10, %[a]\n\t" + "mov r11, %[b]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, r10\n\t" + "mov r14, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #252\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r9\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add %[b], %[b], r11\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [%[b]]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r14\n\t" + "beq 3f\n\t" + "mov r6, r9\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r12\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #248\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[a], r10\n\t" + "mov %[b], r11\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + 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. + */ +SP_NOINLINE static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r11, sp\n\t" + "mov r10, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #252\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r9\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add r2, r2, r10\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [r2]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ + "bal 5f\n\t" + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r8, r9\n\t" + "add r8, r8, r10\n\t" + "cmp %[a], r8\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #248\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "mov %[a], r10\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[r], r12\n\t" + "mov %[a], r11\n\t" + "mov r3, #1\n\t" + "lsl r3, r3, #8\n\t" + "add r3, r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<32; i++) { + r[i] = a[i] & m; + } +} + +#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. + */ +SP_NOINLINE static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r8, #0\n\t" + "add r6, r6, #128\n\t" + "sub r8, r8, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r8\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_32(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r8, %[a]\n\t" + "add r8, r8, #128\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r8\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[32 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r10, %[a]\n\t" + "mov r11, %[b]\n\t" + "mov r6, #128\n\t" + "add r6, r6, r10\n\t" + "mov r14, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #124\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r9\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add %[b], %[b], r11\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [%[b]]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r14\n\t" + "beq 3f\n\t" + "mov r6, r9\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r12\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #248\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[a], r10\n\t" + "mov %[b], r11\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + 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. + */ +SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r11, sp\n\t" + "mov r10, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #124\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r9\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add r2, r2, r10\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [r2]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ + "bal 5f\n\t" + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #128\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r8, r9\n\t" + "add r8, r8, r10\n\t" + "cmp %[a], r8\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #248\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "mov %[a], r10\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[r], r12\n\t" + "mov %[a], r11\n\t" + "mov r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* 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. + */ +SP_NOINLINE static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "add r9, %[a], #256\n\t" + /* A[0] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r5, r3, r6, %[b]\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]], #4\n\t" + /* A[0] * B - Done */ + "\n1:\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r6, r8, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[] * B - Done */ + "str r3, [%[r]], #4\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9" + ); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_2048_mont_norm_32(sp_digit* r, const 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. + */ +SP_NOINLINE static sp_digit sp_2048_cond_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #128\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r8]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + 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, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r9, %[mp]\n\t" + "mov r12, %[m]\n\t" + "mov r10, %[a]\n\t" + "mov r4, #0\n\t" + "add r11, r10, #128\n\t" + "\n1:\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r9\n\t" + "ldr %[a], [r10]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r12\n\t" + "add r14, r10, #120\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+j+1] += m[j+1] * mu */ + "ldr %[a], [r10]\n\t" + "mov r4, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r4, r4, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r5, r5, %[a]\n\t" + "adc r4, r4, #0\n\t" + "str r5, [r10], #4\n\t" + "cmp r10, r14\n\t" + "blt 2b\n\t" + /* a[i+30] += m[30] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+31] += m[31] * mu */ + "mov r4, %[ca]\n\t" + "mov %[ca], #0\n\t" + /* Multiply m[31] and mu - Start */ + "ldr r8, [%[m]]\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc %[ca], %[ca], #0\n\t" + /* Multiply m[31] and mu - Done */ + "ldr r6, [r10]\n\t" + "ldr r8, [r10, #4]\n\t" + "adds r6, r6, r5\n\t" + "adcs r8, r8, r4\n\t" + "adc %[ca], %[ca], #0\n\t" + "str r6, [r10]\n\t" + "str r8, [r10, #4]\n\t" + /* Next word in a */ + "sub r10, r10, #120\n\t" + "cmp r10, r11\n\t" + "blt 1b\n\t" + "mov %[a], r10\n\t" + "mov %[m], r12\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + 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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const 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. + */ +SP_NOINLINE static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "add r9, %[a], #128\n\t" + /* A[0] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r5, r3, r6, %[b]\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]], #4\n\t" + /* A[0] * B - Done */ + "\n1:\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r6, r8, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[] * B - Done */ + "str r3, [%[r]], #4\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9" + ); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r8, r4, #16\n\t" + "umull r4, r5, %[div], r8\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r8, r8, r4\n\t" + "mov %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r8" + ); + 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. + */ +SP_NOINLINE static int32_t sp_2048_cmp_32(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #124\n\t" + "\n1:\n\t" + "ldr r8, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r8, r8, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r8\n\t" + "subs r8, r8, r5\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "subs r5, r5, r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "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 WC_INLINE int sp_2048_div_32(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (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); + + 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, d, (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 WC_INLINE int sp_2048_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_32(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][64]; +#else + sp_digit* t[16]; + 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) * 16 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 64; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32U); + if (reduceA != 0) { + 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); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + 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); + } + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U); + 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; +} +#else +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const 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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 64; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32U); + if (reduceA != 0) { + 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) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 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); + } + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32U); + 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 /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* 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 single precision number. + */ +static void sp_2048_mont_norm_64(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 64); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_64(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* 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. + */ +SP_NOINLINE static sp_digit sp_2048_cond_sub_64(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #1\n\t" + "lsl r5, r5, #8\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r8]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + 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_64(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r9, %[mp]\n\t" + "mov r12, %[m]\n\t" + "mov r10, %[a]\n\t" + "mov r4, #0\n\t" + "add r11, r10, #256\n\t" + "\n1:\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r9\n\t" + "ldr %[a], [r10]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r12\n\t" + "add r14, r10, #248\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+j+1] += m[j+1] * mu */ + "ldr %[a], [r10]\n\t" + "mov r4, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r4, r4, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r5, r5, %[a]\n\t" + "adc r4, r4, #0\n\t" + "str r5, [r10], #4\n\t" + "cmp r10, r14\n\t" + "blt 2b\n\t" + /* a[i+62] += m[62] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+63] += m[63] * mu */ + "mov r4, %[ca]\n\t" + "mov %[ca], #0\n\t" + /* Multiply m[63] and mu - Start */ + "ldr r8, [%[m]]\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc %[ca], %[ca], #0\n\t" + /* Multiply m[63] and mu - Done */ + "ldr r6, [r10]\n\t" + "ldr r8, [r10, #4]\n\t" + "adds r6, r6, r5\n\t" + "adcs r8, r8, r4\n\t" + "adc %[ca], %[ca], #0\n\t" + "str r6, [r10]\n\t" + "str r8, [r10, #4]\n\t" + /* Next word in a */ + "sub r10, r10, #248\n\t" + "cmp r10, r11\n\t" + "blt 1b\n\t" + "mov %[a], r10\n\t" + "mov %[m], r12\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_2048_cond_sub_64(a - 64, 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_64(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_2048_mul_64(r, a, b); + sp_2048_mont_reduce_64(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_64(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_64(r, a); + sp_2048_mont_reduce_64(r, m, mp); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_2048_word_64(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r8, r4, #16\n\t" + "umull r4, r5, %[div], r8\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r8, r8, r4\n\t" + "mov %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r8" + ); + 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_64(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<64; 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; + } +#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. + */ +SP_NOINLINE static int32_t sp_2048_cmp_64(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #252\n\t" + "\n1:\n\t" + "ldr r8, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r8, r8, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r8\n\t" + "subs r8, r8, r5\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "subs r5, r5, r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "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 WC_INLINE int sp_2048_div_64(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_2048_mul_d_64(t2, d, r1); + t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + sp_2048_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2); + sp_2048_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_64(t1, d) >= 0; + sp_2048_cond_sub_64(r, t1, d, (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 WC_INLINE int sp_2048_mod_64(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_64(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 WC_INLINE int sp_2048_div_64_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_2048_mul_d_64(t2, d, r1); + t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + if (t1[64 + i] != 0) { + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d); + if (t1[64 + i] != 0) + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d); + } + } + + r1 = sp_2048_cmp_64(t1, d) >= 0; + sp_2048_cond_sub_64(r, t1, d, (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 WC_INLINE int sp_2048_mod_64_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_64_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* 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_64(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][128]; +#else + sp_digit* t[16]; + 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) * 16 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 128; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64U); + if (reduceA != 0) { + err = sp_2048_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) { + err = sp_2048_mod_64(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_2048_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_64(t[10], t[ 5], m, mp); + sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_64(t[12], t[ 6], m, mp); + sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_64(t[14], t[ 7], m, mp); + sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_mont_mul_64(r, r, t[y], m, mp); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#else +/* 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_64(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][128]; +#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 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 128; + } +#endif + norm = t[0]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64U); + if (reduceA != 0) { + err = sp_2048_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) { + err = sp_2048_mod_64(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_2048_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_64(t[10], t[ 5], m, mp); + sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_64(t[12], t[ 6], m, mp); + sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_64(t[14], t[ 7], m, mp); + sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_64(t[16], t[ 8], m, mp); + sp_2048_mont_mul_64(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_64(t[18], t[ 9], m, mp); + sp_2048_mont_mul_64(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_64(t[20], t[10], m, mp); + sp_2048_mont_mul_64(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_64(t[22], t[11], m, mp); + sp_2048_mont_mul_64(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_64(t[24], t[12], m, mp); + sp_2048_mont_mul_64(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_64(t[26], t[13], m, mp); + sp_2048_mont_mul_64(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_64(t[28], t[14], m, mp); + sp_2048_mont_mul_64(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_64(t[30], t[15], m, mp); + sp_2048_mont_mul_64(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_mont_mul_64(r, r, t[y], m, mp); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[128], m[64], r[128]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; +#endif + sp_digit *ah; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 64 * 2; + m = r + 64 * 2; + } +#endif + + if (err == MP_OKAY) { + ah = a + 64; + + sp_2048_from_bin(ah, 64, in, inLen); +#if DIGIT_BIT >= 32 + 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, 64, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_2048_sqr_64(r, ah); + err = sp_2048_mod_64_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_64(r, ah, r); + err = sp_2048_mod_64_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) * 64); + err = sp_2048_mod_64_cond(a, a, m); + + if (err == MP_OKAY) { + for (i = 31; i >= 0; i--) { + if (e[0] >> i) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 64); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_64(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) { + sp_2048_mont_mul_64(r, r, a, m, mp); + } + } + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_2048_mont_reduce_64(r, m, mp); + + for (i = 63; i > 0; i--) { + if (r[i] != m[i]) { + break; + } + } + if (r[i] >= m[i]) { + sp_2048_sub_in_place_64(r, m); + } + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) + 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 < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 2048) { + err = MP_READ_E; + } + if (inLen > 256) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 64; + m = a + 128; + r = a; + + sp_2048_from_bin(a, 64, in, inLen); + sp_2048_from_mp(d, 64, dm); + sp_2048_from_mp(m, 64, mm); + err = sp_2048_mod_exp_64(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) * 64); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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. + */ +SP_NOINLINE static sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #128\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "adds r5, %[c], #-1\n\t" + "ldr r5, [%[a], r8]\n\t" + "adcs r5, r5, r6\n\t" + "mov %[c], #0\n\t" + "adcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + return c; +} + +/* 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[64 * 2]; + sp_digit p[32], q[32], dp[32]; + sp_digit tmpa[64], tmpb[64]; +#else + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* tmpa; + sp_digit* tmpb; +#endif + sp_digit* r; + sp_digit* qi; + sp_digit* dq; + sp_digit c; + 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 (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 64 * 2; + q = p + 32; + qi = dq = dp = q + 32; + tmpa = qi + 32; + tmpb = tmpa + 64; + + r = t + 64; + } +#else +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + r = a; + qi = dq = dp; +#endif + sp_2048_from_bin(a, 64, in, inLen); + sp_2048_from_mp(p, 32, pm); + sp_2048_from_mp(q, 32, qm); + sp_2048_from_mp(dp, 32, dpm); + + err = sp_2048_mod_exp_32(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 32, dqm); + err = sp_2048_mod_exp_32(tmpb, a, dq, 1024, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_32(tmpa, tmpb); + c += sp_2048_cond_add_32(tmpa, tmpa, p, c); + sp_2048_cond_add_32(tmpa, tmpa, p, c); + + sp_2048_from_mp(qi, 32, qim); + sp_2048_mul_32(tmpa, tmpa, qi); + err = sp_2048_mod_32(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_32(tmpa, q, tmpa); + XMEMSET(&tmpb[32], 0, sizeof(sp_digit) * 32); + sp_2048_add_64(r, tmpb, tmpa); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + 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)); +#endif + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 64); + r->used = 64; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 64, base); + sp_2048_from_mp(e, 64, exp); + sp_2048_from_mp(m, 64, mod); + + err = sp_2048_mod_exp_64(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_2048 +static void sp_2048_lshift_64(sp_digit* r, sp_digit* a, byte n) +{ + __asm__ __volatile__ ( + "mov r6, #31\n\t" + "sub r6, r6, %[n]\n\t" + "add %[a], %[a], #192\n\t" + "add %[r], %[r], #192\n\t" + "ldr r3, [%[a], #60]\n\t" + "lsr r4, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r4, r4, r6\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r4, [%[a], #60]\n\t" + "str r3, [%[r], #68]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #56]\n\t" + "str r2, [%[r], #64]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #52]\n\t" + "str r4, [%[r], #60]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #48]\n\t" + "str r3, [%[r], #56]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #44]\n\t" + "str r2, [%[r], #52]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #40]\n\t" + "str r4, [%[r], #48]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #36]\n\t" + "str r3, [%[r], #44]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #32]\n\t" + "str r2, [%[r], #40]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #28]\n\t" + "str r4, [%[r], #36]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #24]\n\t" + "str r3, [%[r], #32]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #20]\n\t" + "str r2, [%[r], #28]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #16]\n\t" + "str r4, [%[r], #24]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #12]\n\t" + "str r3, [%[r], #20]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #8]\n\t" + "str r2, [%[r], #16]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #4]\n\t" + "str r4, [%[r], #12]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #0]\n\t" + "str r3, [%[r], #8]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r3, [%[a], #60]\n\t" + "str r2, [%[r], #68]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "str r3, [%[r]]\n\t" + "str r4, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [n] "r" (n) + : "memory", "r2", "r3", "r4", "r5", "r6" + ); +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_64(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[128]; + sp_digit td[65]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 193, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 128; +#else + norm = nd; + tmp = td; +#endif + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + sp_2048_lshift_64(r, norm, y); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_lshift_64(r, r, y); + sp_2048_mul_d_64(tmp, norm, r[64]); + r[64] = 0; + o = sp_2048_add_64(r, r, tmp); + sp_2048_cond_sub_64(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64U); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* HAVE_FFDHE_2048 */ + +/* 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. + * returns 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[128], e[64], m[64]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 256) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 64, base); + sp_2048_from_bin(e, 64, exp, expLen); + sp_2048_from_mp(m, 64, mod); + + #ifdef HAVE_FFDHE_2048 + if (base->used == 1 && base->dp[0] == 2 && m[63] == (sp_digit)-1) + err = sp_2048_mod_exp_2_64(r, e, expLen * 8, m); + else + #endif + err = sp_2048_mod_exp_64(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 */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_mp(e, 32, exp); + sp_2048_from_mp(m, 32, mod); + + err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 32, 0, sizeof(*r) * 32U); + err = sp_2048_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * 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<96 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + 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. + */ +SP_NOINLINE static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[12 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r10, %[a]\n\t" + "mov r11, %[b]\n\t" + "mov r6, #48\n\t" + "add r6, r6, r10\n\t" + "mov r14, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #44\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r9\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add %[b], %[b], r11\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [%[b]]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r14\n\t" + "beq 3f\n\t" + "mov r6, r9\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r12\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #88\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[a], r10\n\t" + "mov %[b], r11\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + 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. + */ +SP_NOINLINE static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r6, #96\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r11, sp\n\t" + "mov r10, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #44\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r9\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add r2, r2, r10\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [r2]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ + "bal 5f\n\t" + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #48\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r8, r9\n\t" + "add r8, r8, r10\n\t" + "cmp %[a], r8\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #88\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "mov %[a], r10\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[r], r12\n\t" + "mov %[a], r11\n\t" + "mov r3, #92\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #96\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_24(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + 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_12(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<12; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; + r[8] = a[8] & m; + r[9] = a[9] & m; + r[10] = a[10] & m; + r[11] = a[11] & 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. + */ +SP_NOINLINE static void sp_3072_mul_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[24]; + sp_digit a1[12]; + sp_digit b1[12]; + sp_digit z2[24]; + sp_digit u, ca, cb; + + ca = sp_3072_add_12(a1, a, &a[12]); + cb = sp_3072_add_12(b1, b, &b[12]); + u = ca & cb; + sp_3072_mul_12(z1, a1, b1); + sp_3072_mul_12(z2, &a[12], &b[12]); + sp_3072_mul_12(z0, a, b); + sp_3072_mask_12(r + 24, a1, 0 - cb); + sp_3072_mask_12(b1, b1, 0 - ca); + u += sp_3072_add_12(r + 24, r + 24, b1); + u += sp_3072_sub_in_place_24(z1, z2); + u += sp_3072_sub_in_place_24(z1, z0); + u += sp_3072_add_24(r + 12, r + 12, z1); + r[36] = u; + XMEMSET(r + 36 + 1, 0, sizeof(sp_digit) * (12 - 1)); + (void)sp_3072_add_24(r + 24, r + 24, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[24]; + sp_digit z1[24]; + sp_digit a1[12]; + sp_digit u; + + u = sp_3072_add_12(a1, a, &a[12]); + sp_3072_sqr_12(z1, a1); + sp_3072_sqr_12(z2, &a[12]); + sp_3072_sqr_12(z0, a); + sp_3072_mask_12(r + 24, a1, 0 - u); + u += sp_3072_add_12(r + 24, r + 24, r + 24); + u += sp_3072_sub_in_place_24(z1, z2); + u += sp_3072_sub_in_place_24(z1, z0); + u += sp_3072_add_24(r + 12, r + 12, z1); + r[36] = u; + XMEMSET(r + 36 + 1, 0, sizeof(sp_digit) * (12 - 1)); + (void)sp_3072_add_24(r + 24, r + 24, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_48(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + 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, const 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. + */ +SP_NOINLINE 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)); + (void)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. + */ +SP_NOINLINE 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)); + (void)sp_3072_add_48(r + 48, r + 48, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_96(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + 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_48(sp_digit* r, const 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 +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[96]; + sp_digit a1[48]; + sp_digit b1[48]; + sp_digit z2[96]; + sp_digit u, ca, cb; + + ca = sp_3072_add_48(a1, a, &a[48]); + cb = sp_3072_add_48(b1, b, &b[48]); + u = ca & cb; + sp_3072_mul_48(z1, a1, b1); + sp_3072_mul_48(z2, &a[48], &b[48]); + sp_3072_mul_48(z0, a, b); + sp_3072_mask_48(r + 96, a1, 0 - cb); + sp_3072_mask_48(b1, b1, 0 - ca); + u += sp_3072_add_48(r + 96, r + 96, b1); + u += sp_3072_sub_in_place_96(z1, z2); + u += sp_3072_sub_in_place_96(z1, z0); + u += sp_3072_add_96(r + 48, r + 48, z1); + r[144] = u; + XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1)); + (void)sp_3072_add_96(r + 96, r + 96, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[96]; + sp_digit z1[96]; + sp_digit a1[48]; + sp_digit u; + + u = sp_3072_add_48(a1, a, &a[48]); + sp_3072_sqr_48(z1, a1); + sp_3072_sqr_48(z2, &a[48]); + sp_3072_sqr_48(z0, a); + sp_3072_mask_48(r + 96, a1, 0 - u); + u += sp_3072_add_48(r + 96, r + 96, r + 96); + u += sp_3072_sub_in_place_96(z1, z2); + u += sp_3072_sub_in_place_96(z1, z0); + u += sp_3072_add_96(r + 48, r + 48, z1); + r[144] = u; + XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1)); + (void)sp_3072_add_96(r + 96, r + 96, z2); +} + +#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. + */ +SP_NOINLINE static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r8, #0\n\t" + "add r6, r6, #384\n\t" + "sub r8, r8, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r8\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_96(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r8, %[a]\n\t" + "add r8, r8, #384\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r8\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[96 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r10, %[a]\n\t" + "mov r11, %[b]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #128\n\t" + "add r6, r6, r10\n\t" + "mov r14, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #124\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r9\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add %[b], %[b], r11\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [%[b]]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r14\n\t" + "beq 3f\n\t" + "mov r6, r9\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r12\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #248\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[a], r10\n\t" + "mov %[b], r11\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + 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. + */ +SP_NOINLINE static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r6, #3\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r11, sp\n\t" + "mov r10, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #124\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r9\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add r2, r2, r10\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [r2]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ + "bal 5f\n\t" + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #128\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r8, r9\n\t" + "add r8, r8, r10\n\t" + "cmp %[a], r8\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #248\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "mov %[a], r10\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[r], r12\n\t" + "mov %[a], r11\n\t" + "mov r3, #2\n\t" + "lsl r3, r3, #8\n\t" + "add r3, r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #3\n\t" + "lsl r6, r6, #8\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<48; i++) { + r[i] = a[i] & m; + } +} + +#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. + */ +SP_NOINLINE static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r8, #0\n\t" + "add r6, r6, #192\n\t" + "sub r8, r8, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r8\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_48(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r8, %[a]\n\t" + "add r8, r8, #192\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r8\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[48 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r10, %[a]\n\t" + "mov r11, %[b]\n\t" + "mov r6, #192\n\t" + "add r6, r6, r10\n\t" + "mov r14, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #188\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r9\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add %[b], %[b], r11\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [%[b]]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r14\n\t" + "beq 3f\n\t" + "mov r6, r9\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r12\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #120\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[a], r10\n\t" + "mov %[b], r11\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + 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. + */ +SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #128\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r11, sp\n\t" + "mov r10, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #188\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r9\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add r2, r2, r10\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [r2]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ + "bal 5f\n\t" + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #192\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r8, r9\n\t" + "add r8, r8, r10\n\t" + "cmp %[a], r8\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #120\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "mov %[a], r10\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[r], r12\n\t" + "mov %[a], r11\n\t" + "mov r3, #1\n\t" + "lsl r3, r3, #8\n\t" + "add r3, r3, #124\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #128\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* 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. + */ +SP_NOINLINE static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "add r9, %[a], #384\n\t" + /* A[0] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r5, r3, r6, %[b]\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]], #4\n\t" + /* A[0] * B - Done */ + "\n1:\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r6, r8, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[] * B - Done */ + "str r3, [%[r]], #4\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9" + ); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_3072_mont_norm_48(sp_digit* r, const 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. + */ +SP_NOINLINE static sp_digit sp_3072_cond_sub_48(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #192\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r8]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + 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, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r9, %[mp]\n\t" + "mov r12, %[m]\n\t" + "mov r10, %[a]\n\t" + "mov r4, #0\n\t" + "add r11, r10, #192\n\t" + "\n1:\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r9\n\t" + "ldr %[a], [r10]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r12\n\t" + "add r14, r10, #184\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+j+1] += m[j+1] * mu */ + "ldr %[a], [r10]\n\t" + "mov r4, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r4, r4, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r5, r5, %[a]\n\t" + "adc r4, r4, #0\n\t" + "str r5, [r10], #4\n\t" + "cmp r10, r14\n\t" + "blt 2b\n\t" + /* a[i+46] += m[46] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+47] += m[47] * mu */ + "mov r4, %[ca]\n\t" + "mov %[ca], #0\n\t" + /* Multiply m[47] and mu - Start */ + "ldr r8, [%[m]]\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc %[ca], %[ca], #0\n\t" + /* Multiply m[47] and mu - Done */ + "ldr r6, [r10]\n\t" + "ldr r8, [r10, #4]\n\t" + "adds r6, r6, r5\n\t" + "adcs r8, r8, r4\n\t" + "adc %[ca], %[ca], #0\n\t" + "str r6, [r10]\n\t" + "str r8, [r10, #4]\n\t" + /* Next word in a */ + "sub r10, r10, #184\n\t" + "cmp r10, r11\n\t" + "blt 1b\n\t" + "mov %[a], r10\n\t" + "mov %[m], r12\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + 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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const 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. + */ +SP_NOINLINE static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "add r9, %[a], #192\n\t" + /* A[0] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r5, r3, r6, %[b]\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]], #4\n\t" + /* A[0] * B - Done */ + "\n1:\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r6, r8, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[] * B - Done */ + "str r3, [%[r]], #4\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9" + ); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r8, r4, #16\n\t" + "umull r4, r5, %[div], r8\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r8, r8, r4\n\t" + "mov %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r8" + ); + 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. + */ +SP_NOINLINE static int32_t sp_3072_cmp_48(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #188\n\t" + "\n1:\n\t" + "ldr r8, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r8, r8, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r8\n\t" + "subs r8, r8, r5\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "subs r5, r5, r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "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 WC_INLINE int sp_3072_div_48(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; + + (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); + + 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, d, (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 WC_INLINE int sp_3072_mod_48(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_48(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][96]; +#else + sp_digit* t[16]; + 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) * 16 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 96; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48U); + if (reduceA != 0) { + 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); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + 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); + } + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U); + 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; +} +#else +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const 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; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 96; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48U); + if (reduceA != 0) { + 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) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 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); + } + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48U); + 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 /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* 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 single precision number. + */ +static void sp_3072_mont_norm_96(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 96); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_96(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* 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. + */ +SP_NOINLINE static sp_digit sp_3072_cond_sub_96(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #1\n\t" + "lsl r5, r5, #8\n\t" + "add r5, r5, #128\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r8]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + 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_96(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r9, %[mp]\n\t" + "mov r12, %[m]\n\t" + "mov r10, %[a]\n\t" + "mov r4, #0\n\t" + "add r11, r10, #384\n\t" + "\n1:\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r9\n\t" + "ldr %[a], [r10]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r12\n\t" + "add r14, r10, #376\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+j+1] += m[j+1] * mu */ + "ldr %[a], [r10]\n\t" + "mov r4, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r4, r4, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r5, r5, %[a]\n\t" + "adc r4, r4, #0\n\t" + "str r5, [r10], #4\n\t" + "cmp r10, r14\n\t" + "blt 2b\n\t" + /* a[i+94] += m[94] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+95] += m[95] * mu */ + "mov r4, %[ca]\n\t" + "mov %[ca], #0\n\t" + /* Multiply m[95] and mu - Start */ + "ldr r8, [%[m]]\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc %[ca], %[ca], #0\n\t" + /* Multiply m[95] and mu - Done */ + "ldr r6, [r10]\n\t" + "ldr r8, [r10, #4]\n\t" + "adds r6, r6, r5\n\t" + "adcs r8, r8, r4\n\t" + "adc %[ca], %[ca], #0\n\t" + "str r6, [r10]\n\t" + "str r8, [r10, #4]\n\t" + /* Next word in a */ + "sub r10, r10, #376\n\t" + "cmp r10, r11\n\t" + "blt 1b\n\t" + "mov %[a], r10\n\t" + "mov %[m], r12\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_3072_cond_sub_96(a - 96, 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_96(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_3072_mul_96(r, a, b); + sp_3072_mont_reduce_96(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_96(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_96(r, a); + sp_3072_mont_reduce_96(r, m, mp); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_3072_word_96(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r8, r4, #16\n\t" + "umull r4, r5, %[div], r8\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r8, r8, r4\n\t" + "mov %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r8" + ); + 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_96(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<96; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 96; 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. + */ +SP_NOINLINE static int32_t sp_3072_cmp_96(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #124\n\t" + "\n1:\n\t" + "ldr r8, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r8, r8, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r8\n\t" + "subs r8, r8, r5\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "subs r5, r5, r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "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 WC_INLINE int sp_3072_div_96(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[192], t2[97]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[95]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 96); + for (i=95; i>=0; i--) { + r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div); + + sp_3072_mul_d_96(t2, d, r1); + t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2); + t1[96 + i] -= t2[96]; + sp_3072_mask_96(t2, d, t1[96 + i]); + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2); + sp_3072_mask_96(t2, d, t1[96 + i]); + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_96(t1, d) >= 0; + sp_3072_cond_sub_96(r, t1, d, (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 WC_INLINE int sp_3072_mod_96(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_96(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 WC_INLINE int sp_3072_div_96_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[192], t2[97]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[95]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 96); + for (i=95; i>=0; i--) { + r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div); + + sp_3072_mul_d_96(t2, d, r1); + t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2); + t1[96 + i] -= t2[96]; + if (t1[96 + i] != 0) { + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d); + if (t1[96 + i] != 0) + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d); + } + } + + r1 = sp_3072_cmp_96(t1, d) >= 0; + sp_3072_cond_sub_96(r, t1, d, (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 WC_INLINE int sp_3072_mod_96_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_96_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* 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_96(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][192]; +#else + sp_digit* t[16]; + 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) * 16 * 192, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 192; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 96U); + if (reduceA != 0) { + err = sp_3072_mod_96(t[1] + 96, a, m); + if (err == MP_OKAY) { + err = sp_3072_mod_96(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96); + err = sp_3072_mod_96(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_96(t[10], t[ 5], m, mp); + sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_96(t[12], t[ 6], m, mp); + sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_96(t[14], t[ 7], m, mp); + sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 96); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_mont_mul_96(r, r, t[y], m, mp); + } + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#else +/* 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_96(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][192]; +#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 * 192, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 192; + } +#endif + norm = t[0]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 96U); + if (reduceA != 0) { + err = sp_3072_mod_96(t[1] + 96, a, m); + if (err == MP_OKAY) { + err = sp_3072_mod_96(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96); + err = sp_3072_mod_96(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_96(t[10], t[ 5], m, mp); + sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_96(t[12], t[ 6], m, mp); + sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_96(t[14], t[ 7], m, mp); + sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_96(t[16], t[ 8], m, mp); + sp_3072_mont_mul_96(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_96(t[18], t[ 9], m, mp); + sp_3072_mont_mul_96(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_96(t[20], t[10], m, mp); + sp_3072_mont_mul_96(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_96(t[22], t[11], m, mp); + sp_3072_mont_mul_96(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_96(t[24], t[12], m, mp); + sp_3072_mont_mul_96(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_96(t[26], t[13], m, mp); + sp_3072_mont_mul_96(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_96(t[28], t[14], m, mp); + sp_3072_mont_mul_96(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_96(t[30], t[15], m, mp); + sp_3072_mont_mul_96(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 96); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_mont_mul_96(r, r, t[y], m, mp); + } + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[192], m[96], r[192]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; +#endif + sp_digit *ah; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 96 * 2; + m = r + 96 * 2; + } +#endif + + if (err == MP_OKAY) { + ah = a + 96; + + sp_3072_from_bin(ah, 96, in, inLen); +#if DIGIT_BIT >= 32 + 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, 96, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_3072_sqr_96(r, ah); + err = sp_3072_mod_96_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_96(r, ah, r); + err = sp_3072_mod_96_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) * 96); + err = sp_3072_mod_96_cond(a, a, m); + + if (err == MP_OKAY) { + for (i = 31; i >= 0; i--) { + if (e[0] >> i) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 96); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_96(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) { + sp_3072_mont_mul_96(r, r, a, m, mp); + } + } + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96); + sp_3072_mont_reduce_96(r, m, mp); + + for (i = 95; i > 0; i--) { + if (r[i] != m[i]) { + break; + } + } + if (r[i] >= m[i]) { + sp_3072_sub_in_place_96(r, m); + } + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) + 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 < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 3072) { + err = MP_READ_E; + } + if (inLen > 384) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 96; + m = a + 192; + r = a; + + sp_3072_from_bin(a, 96, in, inLen); + sp_3072_from_mp(d, 96, dm); + sp_3072_from_mp(m, 96, mm); + err = sp_3072_mod_exp_96(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) * 96); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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. + */ +SP_NOINLINE static sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #192\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "adds r5, %[c], #-1\n\t" + "ldr r5, [%[a], r8]\n\t" + "adcs r5, r5, r6\n\t" + "mov %[c], #0\n\t" + "adcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + return c; +} + +/* 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[96 * 2]; + sp_digit p[48], q[48], dp[48]; + sp_digit tmpa[96], tmpb[96]; +#else + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* tmpa; + sp_digit* tmpb; +#endif + sp_digit* r; + sp_digit* qi; + sp_digit* dq; + sp_digit c; + 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 (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 96 * 2; + q = p + 48; + qi = dq = dp = q + 48; + tmpa = qi + 48; + tmpb = tmpa + 96; + + r = t + 96; + } +#else +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + r = a; + qi = dq = dp; +#endif + sp_3072_from_bin(a, 96, in, inLen); + sp_3072_from_mp(p, 48, pm); + sp_3072_from_mp(q, 48, qm); + sp_3072_from_mp(dp, 48, dpm); + + err = sp_3072_mod_exp_48(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 48, dqm); + err = sp_3072_mod_exp_48(tmpb, a, dq, 1536, q, 1); + } + + if (err == MP_OKAY) { + c = sp_3072_sub_in_place_48(tmpa, tmpb); + c += sp_3072_cond_add_48(tmpa, tmpa, p, c); + sp_3072_cond_add_48(tmpa, tmpa, p, c); + + sp_3072_from_mp(qi, 48, qim); + sp_3072_mul_48(tmpa, tmpa, qi); + err = sp_3072_mod_48(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_48(tmpa, q, tmpa); + XMEMSET(&tmpb[48], 0, sizeof(sp_digit) * 48); + sp_3072_add_96(r, tmpb, tmpa); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 48 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + 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)); +#endif + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 96); + r->used = 96; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 96; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 96; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[192], e[96], m[96]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 96, base); + sp_3072_from_mp(e, 96, exp); + sp_3072_from_mp(m, 96, mod); + + err = sp_3072_mod_exp_96(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_3072 +static void sp_3072_lshift_96(sp_digit* r, sp_digit* a, byte n) +{ + __asm__ __volatile__ ( + "mov r6, #31\n\t" + "sub r6, r6, %[n]\n\t" + "add %[a], %[a], #320\n\t" + "add %[r], %[r], #320\n\t" + "ldr r3, [%[a], #60]\n\t" + "lsr r4, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r4, r4, r6\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r4, [%[a], #60]\n\t" + "str r3, [%[r], #68]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #56]\n\t" + "str r2, [%[r], #64]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #52]\n\t" + "str r4, [%[r], #60]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #48]\n\t" + "str r3, [%[r], #56]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #44]\n\t" + "str r2, [%[r], #52]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #40]\n\t" + "str r4, [%[r], #48]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #36]\n\t" + "str r3, [%[r], #44]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #32]\n\t" + "str r2, [%[r], #40]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #28]\n\t" + "str r4, [%[r], #36]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #24]\n\t" + "str r3, [%[r], #32]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #20]\n\t" + "str r2, [%[r], #28]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #16]\n\t" + "str r4, [%[r], #24]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #12]\n\t" + "str r3, [%[r], #20]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #8]\n\t" + "str r2, [%[r], #16]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #4]\n\t" + "str r4, [%[r], #12]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #0]\n\t" + "str r3, [%[r], #8]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r3, [%[a], #60]\n\t" + "str r2, [%[r], #68]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r4, [%[a], #60]\n\t" + "str r3, [%[r], #68]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #56]\n\t" + "str r2, [%[r], #64]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #52]\n\t" + "str r4, [%[r], #60]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #48]\n\t" + "str r3, [%[r], #56]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #44]\n\t" + "str r2, [%[r], #52]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #40]\n\t" + "str r4, [%[r], #48]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #36]\n\t" + "str r3, [%[r], #44]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #32]\n\t" + "str r2, [%[r], #40]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #28]\n\t" + "str r4, [%[r], #36]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #24]\n\t" + "str r3, [%[r], #32]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #20]\n\t" + "str r2, [%[r], #28]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #16]\n\t" + "str r4, [%[r], #24]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #12]\n\t" + "str r3, [%[r], #20]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #8]\n\t" + "str r2, [%[r], #16]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #4]\n\t" + "str r4, [%[r], #12]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #0]\n\t" + "str r3, [%[r], #8]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "str r4, [%[r]]\n\t" + "str r2, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [n] "r" (n) + : "memory", "r2", "r3", "r4", "r5", "r6" + ); +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_96(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[192]; + sp_digit td[97]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 289, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 192; +#else + norm = nd; + tmp = td; +#endif + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + sp_3072_lshift_96(r, norm, y); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_lshift_96(r, r, y); + sp_3072_mul_d_96(tmp, norm, r[96]); + r[96] = 0; + o = sp_3072_add_96(r, r, tmp); + sp_3072_cond_sub_96(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96U); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* HAVE_FFDHE_3072 */ + +/* 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. + * returns 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[192], e[96], m[96]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 384) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 96, base); + sp_3072_from_bin(e, 96, exp, expLen); + sp_3072_from_mp(m, 96, mod); + + #ifdef HAVE_FFDHE_3072 + if (base->used == 1 && base->dp[0] == 2 && m[95] == (sp_digit)-1) + err = sp_3072_mod_exp_2_96(r, e, expLen * 8, m); + else + #endif + err = sp_3072_mod_exp_96(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 */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_mp(e, 48, exp); + sp_3072_from_mp(m, 48, mod); + + err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 48, 0, sizeof(*r) * 48U); + err = sp_3072_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#ifdef WOLFSSL_SP_4096 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 512 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_4096_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 4096 / 8 - 1; + a[j] = 0; + for (i=0; i<128 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + a[j] = 0; + } + if (s != 0) { + j++; + } + } +} + +#ifndef 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. + */ +SP_NOINLINE static sp_digit sp_4096_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_4096_sub_in_place_128(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + 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. + */ +SP_NOINLINE static sp_digit sp_4096_add_128(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_4096_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[64 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r10, %[a]\n\t" + "mov r11, %[b]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, r10\n\t" + "mov r14, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #252\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r9\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add %[b], %[b], r11\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [%[b]]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r14\n\t" + "beq 3f\n\t" + "mov r6, r9\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r12\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #248\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[a], r10\n\t" + "mov %[b], r11\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* 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_4096_mask_64(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<64; 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; + } +#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. + */ +SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[128]; + sp_digit a1[64]; + sp_digit b1[64]; + sp_digit z2[128]; + sp_digit u, ca, cb; + + ca = sp_2048_add_64(a1, a, &a[64]); + cb = sp_2048_add_64(b1, b, &b[64]); + u = ca & cb; + sp_2048_mul_64(z1, a1, b1); + sp_2048_mul_64(z2, &a[64], &b[64]); + sp_2048_mul_64(z0, a, b); + sp_2048_mask_64(r + 128, a1, 0 - cb); + sp_2048_mask_64(b1, b1, 0 - ca); + u += sp_2048_add_64(r + 128, r + 128, b1); + u += sp_4096_sub_in_place_128(z1, z2); + u += sp_4096_sub_in_place_128(z1, z0); + u += sp_4096_add_128(r + 64, r + 64, z1); + r[192] = u; + XMEMSET(r + 192 + 1, 0, sizeof(sp_digit) * (64 - 1)); + (void)sp_4096_add_128(r + 128, r + 128, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_4096_sqr_64(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r11, sp\n\t" + "mov r10, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #252\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r9\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add r2, r2, r10\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [r2]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ + "bal 5f\n\t" + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r8, r9\n\t" + "add r8, r8, r10\n\t" + "cmp %[a], r8\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #248\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "mov %[a], r10\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[r], r12\n\t" + "mov %[a], r11\n\t" + "mov r3, #1\n\t" + "lsl r3, r3, #8\n\t" + "add r3, r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[128]; + sp_digit z1[128]; + sp_digit a1[64]; + sp_digit u; + + u = sp_2048_add_64(a1, a, &a[64]); + sp_2048_sqr_64(z1, a1); + sp_2048_sqr_64(z2, &a[64]); + sp_2048_sqr_64(z0, a); + sp_2048_mask_64(r + 128, a1, 0 - u); + u += sp_2048_add_64(r + 128, r + 128, r + 128); + u += sp_4096_sub_in_place_128(z1, z2); + u += sp_4096_sub_in_place_128(z1, z0); + u += sp_4096_add_128(r + 64, r + 64, z1); + r[192] = u; + XMEMSET(r + 192 + 1, 0, sizeof(sp_digit) * (64 - 1)); + (void)sp_4096_add_128(r + 128, r + 128, z2); +} + +#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. + */ +SP_NOINLINE static sp_digit sp_4096_add_128(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r8, #0\n\t" + "add r6, r6, #512\n\t" + "sub r8, r8, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r8\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_4096_sub_in_place_128(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r8, %[a]\n\t" + "add r8, r8, #512\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r8\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[128 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r10, %[a]\n\t" + "mov r11, %[b]\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, r10\n\t" + "mov r14, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #252\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r9\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add %[b], %[b], r11\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [%[b]]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r14\n\t" + "beq 3f\n\t" + "mov r6, r9\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r12\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #3\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #248\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[a], r10\n\t" + "mov %[b], r11\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + 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. + */ +SP_NOINLINE static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r6, #4\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r11, sp\n\t" + "mov r10, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #252\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r9\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add r2, r2, r10\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [r2]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ + "bal 5f\n\t" + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r8, r9\n\t" + "add r8, r8, r10\n\t" + "cmp %[a], r8\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #3\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #248\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "mov %[a], r10\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[r], r12\n\t" + "mov %[a], r11\n\t" + "mov r3, #3\n\t" + "lsl r3, r3, #8\n\t" + "add r3, r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #4\n\t" + "lsl r6, r6, #8\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_4096_mont_setup(const 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 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* 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. + */ +SP_NOINLINE static void sp_4096_mul_d_128(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "add r9, %[a], #512\n\t" + /* A[0] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r5, r3, r6, %[b]\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]], #4\n\t" + /* A[0] * B - Done */ + "\n1:\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r6, r8, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[] * B - Done */ + "str r3, [%[r]], #4\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9" + ); +} + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 4096 bits, just need to subtract. + * + * r A single precision number. + * m A single precision number. + */ +static void sp_4096_mont_norm_128(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 128); + + /* r = 2^n mod m */ + sp_4096_sub_in_place_128(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* 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. + */ +SP_NOINLINE static sp_digit sp_4096_cond_sub_128(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #2\n\t" + "lsl r5, r5, #8\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r8]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + return c; +} + +/* Reduce the number back to 4096 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_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r9, %[mp]\n\t" + "mov r12, %[m]\n\t" + "mov r10, %[a]\n\t" + "mov r4, #0\n\t" + "add r11, r10, #512\n\t" + "\n1:\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r9\n\t" + "ldr %[a], [r10]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r12\n\t" + "add r14, r10, #504\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+j+1] += m[j+1] * mu */ + "ldr %[a], [r10]\n\t" + "mov r4, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r4, r4, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r5, r5, %[a]\n\t" + "adc r4, r4, #0\n\t" + "str r5, [r10], #4\n\t" + "cmp r10, r14\n\t" + "blt 2b\n\t" + /* a[i+126] += m[126] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+127] += m[127] * mu */ + "mov r4, %[ca]\n\t" + "mov %[ca], #0\n\t" + /* Multiply m[127] and mu - Start */ + "ldr r8, [%[m]]\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc %[ca], %[ca], #0\n\t" + /* Multiply m[127] and mu - Done */ + "ldr r6, [r10]\n\t" + "ldr r8, [r10, #4]\n\t" + "adds r6, r6, r5\n\t" + "adcs r8, r8, r4\n\t" + "adc %[ca], %[ca], #0\n\t" + "str r6, [r10]\n\t" + "str r8, [r10, #4]\n\t" + /* Next word in a */ + "sub r10, r10, #504\n\t" + "cmp r10, r11\n\t" + "blt 1b\n\t" + "mov %[a], r10\n\t" + "mov %[m], r12\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_4096_cond_sub_128(a - 128, 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_4096_mont_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_4096_mul_128(r, a, b); + sp_4096_mont_reduce_128(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_4096_mont_sqr_128(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_4096_sqr_128(r, a); + sp_4096_mont_reduce_128(r, m, mp); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_4096_word_128(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r8, r4, #16\n\t" + "umull r4, r5, %[div], r8\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r8, r8, r4\n\t" + "mov %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r8" + ); + 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_4096_mask_128(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<128; i++) { + r[i] = a[i] & m; + } +#else + int i; + + for (i = 0; i < 128; 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. + */ +SP_NOINLINE static int32_t sp_4096_cmp_128(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #252\n\t" + "\n1:\n\t" + "ldr r8, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r8, r8, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r8\n\t" + "subs r8, r8, r5\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "subs r5, r5, r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "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 WC_INLINE int sp_4096_div_128(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[256], t2[129]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[127]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 128); + for (i=127; i>=0; i--) { + r1 = div_4096_word_128(t1[128 + i], t1[128 + i - 1], div); + + sp_4096_mul_d_128(t2, d, r1); + t1[128 + i] += sp_4096_sub_in_place_128(&t1[i], t2); + t1[128 + i] -= t2[128]; + sp_4096_mask_128(t2, d, t1[128 + i]); + t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], t2); + sp_4096_mask_128(t2, d, t1[128 + i]); + t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], t2); + } + + r1 = sp_4096_cmp_128(t1, d) >= 0; + sp_4096_cond_sub_128(r, t1, d, (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 WC_INLINE int sp_4096_mod_128(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_128(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 WC_INLINE int sp_4096_div_128_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[256], t2[129]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[127]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 128); + for (i=127; i>=0; i--) { + r1 = div_4096_word_128(t1[128 + i], t1[128 + i - 1], div); + + sp_4096_mul_d_128(t2, d, r1); + t1[128 + i] += sp_4096_sub_in_place_128(&t1[i], t2); + t1[128 + i] -= t2[128]; + if (t1[128 + i] != 0) { + t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], d); + if (t1[128 + i] != 0) + t1[128 + i] += sp_4096_add_128(&t1[i], &t1[i], d); + } + } + + r1 = sp_4096_cmp_128(t1, d) >= 0; + sp_4096_cond_sub_128(r, t1, d, (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 WC_INLINE int sp_4096_mod_128_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_128_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* 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_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][256]; +#else + sp_digit* t[16]; + 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) * 16 * 256, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<16; i++) { + t[i] = td + i * 256; + } +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_128(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 128U); + if (reduceA != 0) { + err = sp_4096_mod_128(t[1] + 128, a, m); + if (err == MP_OKAY) { + err = sp_4096_mod_128(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 128, a, sizeof(sp_digit) * 128); + err = sp_4096_mod_128(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_128(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_128(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_128(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_128(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_128(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_128(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_128(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_128(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_128(t[10], t[ 5], m, mp); + sp_4096_mont_mul_128(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_128(t[12], t[ 6], m, mp); + sp_4096_mont_mul_128(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_128(t[14], t[ 7], m, mp); + sp_4096_mont_mul_128(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 4; + if (c == 32) { + c = 28; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 128); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + + sp_4096_mont_mul_128(r, r, t[y], m, mp); + } + + XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U); + sp_4096_mont_reduce_128(r, m, mp); + + mask = 0 - (sp_4096_cmp_128(r, m) >= 0); + sp_4096_cond_sub_128(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#else +/* 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_4096_mod_exp_128(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][256]; +#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 * 256, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) { + t[i] = td + i * 256; + } +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_128(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 128U); + if (reduceA != 0) { + err = sp_4096_mod_128(t[1] + 128, a, m); + if (err == MP_OKAY) { + err = sp_4096_mod_128(t[1], t[1], m); + } + } + else { + XMEMCPY(t[1] + 128, a, sizeof(sp_digit) * 128); + err = sp_4096_mod_128(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_128(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_128(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_128(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_128(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_128(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_128(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_128(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_128(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_128(t[10], t[ 5], m, mp); + sp_4096_mont_mul_128(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_128(t[12], t[ 6], m, mp); + sp_4096_mont_mul_128(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_128(t[14], t[ 7], m, mp); + sp_4096_mont_mul_128(t[15], t[ 8], t[ 7], m, mp); + sp_4096_mont_sqr_128(t[16], t[ 8], m, mp); + sp_4096_mont_mul_128(t[17], t[ 9], t[ 8], m, mp); + sp_4096_mont_sqr_128(t[18], t[ 9], m, mp); + sp_4096_mont_mul_128(t[19], t[10], t[ 9], m, mp); + sp_4096_mont_sqr_128(t[20], t[10], m, mp); + sp_4096_mont_mul_128(t[21], t[11], t[10], m, mp); + sp_4096_mont_sqr_128(t[22], t[11], m, mp); + sp_4096_mont_mul_128(t[23], t[12], t[11], m, mp); + sp_4096_mont_sqr_128(t[24], t[12], m, mp); + sp_4096_mont_mul_128(t[25], t[13], t[12], m, mp); + sp_4096_mont_sqr_128(t[26], t[13], m, mp); + sp_4096_mont_mul_128(t[27], t[14], t[13], m, mp); + sp_4096_mont_sqr_128(t[28], t[14], m, mp); + sp_4096_mont_mul_128(t[29], t[15], t[14], m, mp); + sp_4096_mont_sqr_128(t[30], t[15], m, mp); + sp_4096_mont_mul_128(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 128); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + + sp_4096_mont_mul_128(r, r, t[y], m, mp); + } + + XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U); + sp_4096_mont_reduce_128(r, m, mp); + + mask = 0 - (sp_4096_cmp_128(r, m) >= 0); + sp_4096_cond_sub_128(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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 512 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_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[256], m[128], r[256]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; +#endif + sp_digit *ah; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 512) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 512 || + mp_count_bits(mm) != 4096)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 128 * 2; + m = r + 128 * 2; + } +#endif + + if (err == MP_OKAY) { + ah = a + 128; + + sp_4096_from_bin(ah, 128, in, inLen); +#if DIGIT_BIT >= 32 + 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_4096_from_mp(m, 128, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_4096_sqr_128(r, ah); + err = sp_4096_mod_128_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_4096_mul_128(r, ah, r); + err = sp_4096_mod_128_cond(r, r, m); + } + } + else { + int i; + sp_digit mp; + + sp_4096_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 128); + err = sp_4096_mod_128_cond(a, a, m); + + if (err == MP_OKAY) { + for (i = 31; i >= 0; i--) { + if (e[0] >> i) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 128); + for (i--; i>=0; i--) { + sp_4096_mont_sqr_128(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) { + sp_4096_mont_mul_128(r, r, a, m, mp); + } + } + XMEMSET(&r[128], 0, sizeof(sp_digit) * 128); + sp_4096_mont_reduce_128(r, m, mp); + + for (i = 127; i > 0; i--) { + if (r[i] != m[i]) { + break; + } + } + if (r[i] >= m[i]) { + sp_4096_sub_in_place_128(r, m); + } + } + } + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) + 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 < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 4096) { + err = MP_READ_E; + } + if (inLen > 512) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 128 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } + if (err == MP_OKAY) { + a = d + 128; + m = a + 256; + r = a; + + sp_4096_from_bin(a, 128, in, inLen); + sp_4096_from_mp(d, 128, dm); + sp_4096_from_mp(m, 128, mm); + err = sp_4096_mod_exp_128(r, a, d, 4096, m, 0); + } + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 128); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* 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. + */ +SP_NOINLINE static sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #1\n\t" + "lsl r5, r5, #8\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "adds r5, %[c], #-1\n\t" + "ldr r5, [%[a], r8]\n\t" + "adcs r5, r5, r6\n\t" + "mov %[c], #0\n\t" + "adcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + return c; +} + +/* 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 512 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_4096(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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit a[128 * 2]; + sp_digit p[64], q[64], dp[64]; + sp_digit tmpa[128], tmpb[128]; +#else + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* tmpa; + sp_digit* tmpb; +#endif + sp_digit* r; + sp_digit* qi; + sp_digit* dq; + sp_digit c; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 512) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 512 || mp_count_bits(mm) != 4096)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 128 * 2; + q = p + 64; + qi = dq = dp = q + 64; + tmpa = qi + 64; + tmpb = tmpa + 128; + + r = t + 128; + } +#else +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + r = a; + qi = dq = dp; +#endif + sp_4096_from_bin(a, 128, in, inLen); + sp_4096_from_mp(p, 64, pm); + sp_4096_from_mp(q, 64, qm); + sp_4096_from_mp(dp, 64, dpm); + + err = sp_2048_mod_exp_64(tmpa, a, dp, 2048, p, 1); + } + if (err == MP_OKAY) { + sp_4096_from_mp(dq, 64, dqm); + err = sp_2048_mod_exp_64(tmpb, a, dq, 2048, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_64(tmpa, tmpb); + c += sp_4096_cond_add_64(tmpa, tmpa, p, c); + sp_4096_cond_add_64(tmpa, tmpa, p, c); + + sp_2048_from_mp(qi, 64, qim); + sp_2048_mul_64(tmpa, tmpa, qi); + err = sp_2048_mod_64(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_64(tmpa, q, tmpa); + XMEMSET(&tmpb[64], 0, sizeof(sp_digit) * 64); + sp_4096_add_128(r, tmpb, tmpa); + + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 64 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + 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)); +#endif + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_4096_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 128); + r->used = 128; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 128; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 128; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[256], e[128], m[128]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expBits > 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 128, base); + sp_4096_from_mp(e, 128, exp); + sp_4096_from_mp(m, 128, mod); + + err = sp_4096_mod_exp_128(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_4096_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH + +#ifdef HAVE_FFDHE_4096 +static void sp_4096_lshift_128(sp_digit* r, sp_digit* a, byte n) +{ + __asm__ __volatile__ ( + "mov r6, #31\n\t" + "sub r6, r6, %[n]\n\t" + "add %[a], %[a], #448\n\t" + "add %[r], %[r], #448\n\t" + "ldr r3, [%[a], #60]\n\t" + "lsr r4, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r4, r4, r6\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r4, [%[a], #60]\n\t" + "str r3, [%[r], #68]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #56]\n\t" + "str r2, [%[r], #64]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #52]\n\t" + "str r4, [%[r], #60]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #48]\n\t" + "str r3, [%[r], #56]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #44]\n\t" + "str r2, [%[r], #52]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #40]\n\t" + "str r4, [%[r], #48]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #36]\n\t" + "str r3, [%[r], #44]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #32]\n\t" + "str r2, [%[r], #40]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #28]\n\t" + "str r4, [%[r], #36]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #24]\n\t" + "str r3, [%[r], #32]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #20]\n\t" + "str r2, [%[r], #28]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #16]\n\t" + "str r4, [%[r], #24]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #12]\n\t" + "str r3, [%[r], #20]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #8]\n\t" + "str r2, [%[r], #16]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #4]\n\t" + "str r4, [%[r], #12]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #0]\n\t" + "str r3, [%[r], #8]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r3, [%[a], #60]\n\t" + "str r2, [%[r], #68]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r4, [%[a], #60]\n\t" + "str r3, [%[r], #68]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #56]\n\t" + "str r2, [%[r], #64]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #52]\n\t" + "str r4, [%[r], #60]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #48]\n\t" + "str r3, [%[r], #56]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #44]\n\t" + "str r2, [%[r], #52]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #40]\n\t" + "str r4, [%[r], #48]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #36]\n\t" + "str r3, [%[r], #44]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #32]\n\t" + "str r2, [%[r], #40]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #28]\n\t" + "str r4, [%[r], #36]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #24]\n\t" + "str r3, [%[r], #32]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #20]\n\t" + "str r2, [%[r], #28]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #16]\n\t" + "str r4, [%[r], #24]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #12]\n\t" + "str r3, [%[r], #20]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #8]\n\t" + "str r2, [%[r], #16]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #4]\n\t" + "str r4, [%[r], #12]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #0]\n\t" + "str r3, [%[r], #8]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r3, [%[a], #60]\n\t" + "str r2, [%[r], #68]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #56]\n\t" + "str r4, [%[r], #64]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #52]\n\t" + "str r3, [%[r], #60]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #48]\n\t" + "str r2, [%[r], #56]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #44]\n\t" + "str r4, [%[r], #52]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #40]\n\t" + "str r3, [%[r], #48]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #36]\n\t" + "str r2, [%[r], #44]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #32]\n\t" + "str r4, [%[r], #40]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #28]\n\t" + "str r3, [%[r], #36]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #24]\n\t" + "str r2, [%[r], #32]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #20]\n\t" + "str r4, [%[r], #28]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #16]\n\t" + "str r3, [%[r], #24]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #12]\n\t" + "str r2, [%[r], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #8]\n\t" + "str r4, [%[r], #16]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #4]\n\t" + "str r3, [%[r], #12]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #0]\n\t" + "str r2, [%[r], #8]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "sub %[a], %[a], #64\n\t" + "sub %[r], %[r], #64\n\t" + "ldr r2, [%[a], #60]\n\t" + "str r4, [%[r], #68]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #56]\n\t" + "str r3, [%[r], #64]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #52]\n\t" + "str r2, [%[r], #60]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #48]\n\t" + "str r4, [%[r], #56]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r3, [%[r], #52]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r2, [%[r], #48]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r4, [%[r], #44]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r3, [%[r], #40]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r2, [%[r], #36]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r4, [%[r], #32]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r3, [%[r], #28]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r2, [%[r], #24]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r4, [%[r], #20]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r3, [%[r], #16]\n\t" + "lsr r5, r4, #1\n\t" + "lsl r4, r4, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r2, r2, r5\n\t" + "ldr r3, [%[a], #4]\n\t" + "str r2, [%[r], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r4, r4, r5\n\t" + "ldr r2, [%[a], #0]\n\t" + "str r4, [%[r], #8]\n\t" + "lsr r5, r2, #1\n\t" + "lsl r2, r2, %[n]\n\t" + "lsr r5, r5, r6\n\t" + "orr r3, r3, r5\n\t" + "str r2, [%[r]]\n\t" + "str r3, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [n] "r" (n) + : "memory", "r2", "r3", "r4", "r5", "r6" + ); +} + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_4096_mod_exp_2_128(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[256]; + sp_digit td[129]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 385, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 256; +#else + norm = nd; + tmp = td; +#endif + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_128(norm, m); + + i = (bits - 1) / 32; + n = e[i--]; + c = bits & 31; + if (c == 0) { + c = 32; + } + c -= bits % 5; + if (c == 32) { + c = 27; + } + y = (int)(n >> c); + n <<= 32 - c; + sp_4096_lshift_128(r, norm, y); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + sp_4096_mont_sqr_128(r, r, m, mp); + + sp_4096_lshift_128(r, r, y); + sp_4096_mul_d_128(tmp, norm, r[128]); + r[128] = 0; + o = sp_4096_add_128(r, r, tmp); + sp_4096_cond_sub_128(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[128], 0, sizeof(sp_digit) * 128U); + sp_4096_mont_reduce_128(r, m, mp); + + mask = 0 - (sp_4096_cmp_128(r, m) >= 0); + sp_4096_cond_sub_128(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return err; +} +#endif /* HAVE_FFDHE_4096 */ + +/* 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 512 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returns 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_4096(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[256], e[128], m[128]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + if (expLen > 512) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + if (mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + } + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 128, base); + sp_4096_from_bin(e, 128, exp, expLen); + sp_4096_from_mp(m, 128, mod); + + #ifdef HAVE_FFDHE_4096 + if (base->used == 1 && base->dp[0] == 2 && m[127] == (sp_digit)-1) + err = sp_4096_mod_exp_2_128(r, e, expLen * 8, m); + else + #endif + err = sp_4096_mod_exp_128(r, b, e, expLen * 8, m, 0); + + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + for (i=0; i<512 && 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_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* WOLFSSL_SP_4096 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point_256 { + sp_digit x[2 * 8]; + sp_digit y[2 * 8]; + sp_digit z[2 * 8]; + int infinity; +} sp_point_256; + +/* The modulus (prime) of the curve P256. */ +static const sp_digit p256_mod[8] = { + 0xffffffff,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000, + 0x00000001,0xffffffff +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static const sp_digit p256_norm_mod[8] = { + 0x00000001,0x00000000,0x00000000,0xffffffff,0xffffffff,0xffffffff, + 0xfffffffe,0x00000000 +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static const sp_digit p256_mp_mod = 0x00000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static const sp_digit p256_order[8] = { + 0xfc632551,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#endif +/* The order of the curve P256 minus 2. */ +static const sp_digit p256_order2[8] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static const sp_digit p256_norm_order[8] = { + 0x039cdaaf,0x0c46353d,0x58e8617b,0x43190552,0x00000000,0x00000000, + 0xffffffff,0x00000000 +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static const sp_digit p256_mp_order = 0xee00bc4f; +#endif +/* The base point of curve P256. */ +static const sp_point_256 p256_base = { + /* X ordinate */ + { + 0xd898c296,0xf4a13945,0x2deb33a0,0x77037d81,0x63a440f2,0xf8bce6e5, + 0xe12c4247,0x6b17d1f2, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x37bf51f5,0xcbb64068,0x6b315ece,0x2bce3357,0x7c0f9e16,0x8ee7eb4a, + 0xfe1a7f9b,0x4fe342e2, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p256_b[8] = { + 0x27d2604b,0x3bce3c3e,0xcc53b0f6,0x651d06b0,0x769886bc,0xb3ebbd55, + 0xaa3a93e7,0x5ac635d8 +}; +#endif + +static int sp_256_point_new_ex_8(void* heap, sp_point_256* sp, sp_point_256** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_256_point_new_8(heap, sp, p) sp_256_point_new_ex_8((heap), &(sp), &(p)) +#endif + + +static void sp_256_point_free_8(sp_point_256* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + int64_t t[8]; + int64_t a64[8]; + int64_t o; + + (void)m; + + a64[0] = a[0]; + a64[1] = a[1]; + a64[2] = a[2]; + a64[3] = a[3]; + a64[4] = a[4]; + a64[5] = a[5]; + a64[6] = a[6]; + a64[7] = a[7]; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a64[0] + a64[1] - a64[3] - a64[4] - a64[5] - a64[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a64[1] + a64[2] - a64[4] - a64[5] - a64[6] - a64[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a64[2] + a64[3] - a64[5] - a64[6] - a64[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a64[0] - a64[1] + 2 * a64[3] + 2 * a64[4] + a64[5] - a64[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a64[1] - a64[2] + 2 * a64[4] + 2 * a64[5] + a64[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a64[2] - a64[3] + 2 * a64[5] + 2 * a64[6] + a64[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a64[0] - a64[1] + a64[5] + 3 * a64[6] + 2 * a64[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a64[0] - a64[2] - a64[3] - a64[4] - a64[5] + 3 * a64[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[1] = t[1]; + r[2] = t[2]; + r[3] = t[3]; + r[4] = t[4]; + r[5] = t[5]; + r[6] = t[6]; + r[7] = t[7]; + + return MP_OKAY; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_256. + * + * p Point of type sp_point_256 (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_8(sp_point_256* p, const 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, 8, pm->x); + sp_256_from_mp(p->y, 8, pm->y); + sp_256_from_mp(p->z, 8, 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(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 8); + r->used = 8; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 8; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - 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 < 8; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_256 to type ecc_point. + * + * p Point of type sp_point_256. + * 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_8(const sp_point_256* 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; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[8]; + + __asm__ __volatile__ ( + /* A[0] * B[0] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r3, r4, r6, r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[tmp], #0]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[1] */ + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r8\n\t" + /* A[1] * B[0] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[tmp], #4]\n\t" + "mov r4, #0\n\t" + /* A[0] * B[2] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * B[1] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * B[0] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[tmp], #8]\n\t" + "mov r5, #0\n\t" + /* A[0] * B[3] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[1] * B[2] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[2] * B[1] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * B[0] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[tmp], #12]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[4] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[1] * B[3] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[2] * B[2] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[3] * B[1] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[4] * B[0] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[tmp], #16]\n\t" + "mov r4, #0\n\t" + /* A[0] * B[5] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * B[4] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * B[3] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * B[2] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[4] * B[1] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * B[0] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[tmp], #20]\n\t" + "mov r5, #0\n\t" + /* A[0] * B[6] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[1] * B[5] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[2] * B[4] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * B[3] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[4] * B[2] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[5] * B[1] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * B[0] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[tmp], #24]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[7] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[1] * B[6] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[2] * B[5] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[3] * B[4] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[4] * B[3] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[5] * B[2] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[6] * B[1] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[7] * B[0] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #0]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[tmp], #28]\n\t" + "mov r4, #0\n\t" + /* A[1] * B[7] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[2] * B[6] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[3] * B[5] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[4] * B[4] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * B[3] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[6] * B[2] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[7] * B[1] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[r], #32]\n\t" + "mov r5, #0\n\t" + /* A[2] * B[7] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[3] * B[6] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[4] * B[5] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[5] * B[4] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * B[3] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[7] * B[2] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[r], #36]\n\t" + "mov r3, #0\n\t" + /* A[3] * B[7] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[4] * B[6] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[5] * B[5] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[6] * B[4] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[7] * B[3] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[r], #40]\n\t" + "mov r4, #0\n\t" + /* A[4] * B[7] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * B[6] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[6] * B[5] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[7] * B[4] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[r], #44]\n\t" + "mov r5, #0\n\t" + /* A[5] * B[7] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * B[6] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[7] * B[5] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[r], #48]\n\t" + "mov r3, #0\n\t" + /* A[6] * B[7] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + /* A[7] * B[6] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[r], #52]\n\t" + "mov r4, #0\n\t" + /* A[7] * B[7] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[b], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r8\n\t" + "str r5, [%[r], #56]\n\t" + "str r3, [%[r], #60]\n\t" + /* Transfer tmp to r */ + "ldr r3, [%[tmp], #0]\n\t" + "ldr r4, [%[tmp], #4]\n\t" + "ldr r5, [%[tmp], #8]\n\t" + "ldr r6, [%[tmp], #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[tmp], #16]\n\t" + "ldr r4, [%[tmp], #20]\n\t" + "ldr r5, [%[tmp], #24]\n\t" + "ldr r6, [%[tmp], #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "r3", "r4", "r5", "r6", "r8" + ); +} + +/* 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. + */ +SP_NOINLINE static sp_digit sp_256_cond_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #32\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r8]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + 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_8(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + (void)mp; + (void)m; + + __asm__ __volatile__ ( + "mov r2, #0\n\t" + "mov r1, #0\n\t" + /* i = 0 */ + "mov r9, r2\n\t" + "\n1:\n\t" + "mov r4, #0\n\t" + /* mu = a[i] * 1 (mp) = a[i] */ + "ldr r3, [%[a]]\n\t" + /* a[i] += -1 * mu = -1 * a[i] => a[i] = 0 no carry */ + /* a[i+1] += -1 * mu */ + "ldr r6, [%[a], #4]\n\t" + "mov r5, #0\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r2\n\t" + "str r4, [%[a], #4]\n\t" + /* a[i+2] += -1 * mu */ + "ldr r6, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "adds r5, r5, r6\n\t" + "adc r4, r4, r2\n\t" + "str r5, [%[a], #8]\n\t" + /* a[i+3] += 0 * mu */ + "ldr r6, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "adds r4, r4, r3\n\t" + "adc r5, r5, r2\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r2\n\t" + "str r4, [%[a], #12]\n\t" + /* a[i+4] += 0 * mu */ + "ldr r6, [%[a], #16]\n\t" + "mov r4, #0\n\t" + "adds r5, r5, r6\n\t" + "adc r4, r4, r2\n\t" + "str r5, [%[a], #16]\n\t" + /* a[i+5] += 0 * mu */ + "ldr r6, [%[a], #20]\n\t" + "mov r5, #0\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r2\n\t" + "str r4, [%[a], #20]\n\t" + /* a[i+6] += 1 * mu */ + "ldr r6, [%[a], #24]\n\t" + "mov r4, #0\n\t" + "adds r5, r5, r3\n\t" + "adc r4, r4, r2\n\t" + "adds r5, r5, r6\n\t" + "adc r4, r4, r2\n\t" + "str r5, [%[a], #24]\n\t" + /* a[i+7] += -1 * mu */ + "ldr r6, [%[a], #28]\n\t" + "ldr r8, [%[a], #32]\n\t" + "adds r5, r1, r3\n\t" + "mov r1, #0\n\t" + "adc r1, r1, r2\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, r2\n\t" + "sbc r1, r1, r2\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r1, r1, r2\n\t" + "str r4, [%[a], #28]\n\t" + "str r5, [%[a], #32]\n\t" + /* i += 1 */ + "add r9, r9, #1\n\t" + "add %[a], %[a], #4\n\t" + "mov r6, #8\n\t" + "cmp r9, r6\n\t" + "blt 1b\n\t" + "sub %[a], %[a], #32\n\t" + "mov r3, r1\n\t" + "sub r1, r1, #1\n\t" + "mvn r1, r1\n\t" + "ldr r4, [%[a],#32]\n\t" + "ldr r5, [%[a],#36]\n\t" + "ldr r6, [%[a],#40]\n\t" + "ldr r8, [%[a],#44]\n\t" + "subs r4, r4, r1\n\t" + "sbcs r5, r5, r1\n\t" + "sbcs r6, r6, r1\n\t" + "sbcs r8, r8, r2\n\t" + "str r4, [%[a],#0]\n\t" + "str r5, [%[a],#4]\n\t" + "str r6, [%[a],#8]\n\t" + "str r8, [%[a],#12]\n\t" + "ldr r4, [%[a],#48]\n\t" + "ldr r5, [%[a],#52]\n\t" + "ldr r6, [%[a],#56]\n\t" + "ldr r8, [%[a],#60]\n\t" + "sbcs r4, r4, r2\n\t" + "sbcs r5, r5, r2\n\t" + "sbcs r6, r6, r3\n\t" + "sbc r8, r8, r1\n\t" + "str r4, [%[a],#16]\n\t" + "str r5, [%[a],#20]\n\t" + "str r6, [%[a],#24]\n\t" + "str r8, [%[a],#28]\n\t" + : [a] "+r" (a) + : + : "memory", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9" + ); + + + (void)m; + (void)mp; +} + +/* 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_order_8(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r9, %[mp]\n\t" + "mov r12, %[m]\n\t" + "mov r10, %[a]\n\t" + "mov r4, #0\n\t" + "add r11, r10, #32\n\t" + "\n1:\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r9\n\t" + "ldr %[a], [r10]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r12\n\t" + "add r14, r10, #24\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+j+1] += m[j+1] * mu */ + "ldr %[a], [r10]\n\t" + "mov r4, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r4, r4, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r5, r5, %[a]\n\t" + "adc r4, r4, #0\n\t" + "str r5, [r10], #4\n\t" + "cmp r10, r14\n\t" + "blt 2b\n\t" + /* a[i+6] += m[6] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+7] += m[7] * mu */ + "mov r4, %[ca]\n\t" + "mov %[ca], #0\n\t" + /* Multiply m[7] and mu - Start */ + "ldr r8, [%[m]]\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc %[ca], %[ca], #0\n\t" + /* Multiply m[7] and mu - Done */ + "ldr r6, [r10]\n\t" + "ldr r8, [r10, #4]\n\t" + "adds r6, r6, r5\n\t" + "adcs r8, r8, r4\n\t" + "adc %[ca], %[ca], #0\n\t" + "str r6, [r10]\n\t" + "str r8, [r10, #4]\n\t" + /* Next word in a */ + "sub r10, r10, #24\n\t" + "cmp r10, r11\n\t" + "blt 1b\n\t" + "mov %[a], r10\n\t" + "mov %[m], r12\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_256_cond_sub_8(a - 8, 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_256_mont_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_256_mul_8(r, a, b); + sp_256_mont_reduce_8(r, m, mp); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[8]; + __asm__ __volatile__ ( + /* A[0] * A[0] */ + "ldr r6, [%[a], #0]\n\t" + "umull r3, r4, r6, r6\n\t" + "mov r5, #0\n\t" + "str r3, [%[tmp], #0]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[1] */ + "ldr r8, [%[a], #4]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[tmp], #4]\n\t" + "mov r4, #0\n\t" + /* A[0] * A[2] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[1] * A[1] */ + "ldr r6, [%[a], #4]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[tmp], #8]\n\t" + "mov r5, #0\n\t" + /* A[0] * A[3] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[2] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adc r5, r5, r11\n\t" + "str r3, [%[tmp], #12]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[4] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[3] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[2] * A[2] */ + "ldr r6, [%[a], #8]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r4, r4, r9\n\t" + "adcs r5, r5, r10\n\t" + "adc r3, r3, r11\n\t" + "str r4, [%[tmp], #16]\n\t" + "mov r4, #0\n\t" + /* A[0] * A[5] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[4] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[2] * A[3] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r5, r5, r9\n\t" + "adcs r3, r3, r10\n\t" + "adc r4, r4, r11\n\t" + "str r5, [%[tmp], #20]\n\t" + "mov r5, #0\n\t" + /* A[0] * A[6] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[5] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[2] * A[4] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[3] * A[3] */ + "ldr r6, [%[a], #12]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adc r5, r5, r11\n\t" + "str r3, [%[tmp], #24]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[7] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[1] * A[6] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[2] * A[5] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[3] * A[4] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r4, r4, r9\n\t" + "adcs r5, r5, r10\n\t" + "adc r3, r3, r11\n\t" + "str r4, [%[tmp], #28]\n\t" + "mov r4, #0\n\t" + /* A[1] * A[7] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[2] * A[6] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[3] * A[5] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[4] * A[4] */ + "ldr r6, [%[a], #16]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r5, r5, r9\n\t" + "adcs r3, r3, r10\n\t" + "adc r4, r4, r11\n\t" + "str r5, [%[r], #32]\n\t" + "mov r5, #0\n\t" + /* A[2] * A[7] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[3] * A[6] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[4] * A[5] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adc r5, r5, r11\n\t" + "str r3, [%[r], #36]\n\t" + "mov r3, #0\n\t" + /* A[3] * A[7] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r9, r10, r6, r8\n\t" + "mov r11, #0\n\t" + /* A[4] * A[6] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r9, r9, r6\n\t" + "adcs r10, r10, r8\n\t" + "adc r11, r11, #0\n\t" + /* A[5] * A[5] */ + "ldr r6, [%[a], #20]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "adds r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adc r11, r11, r11\n\t" + "adds r4, r4, r9\n\t" + "adcs r5, r5, r10\n\t" + "adc r3, r3, r11\n\t" + "str r4, [%[r], #40]\n\t" + "mov r4, #0\n\t" + /* A[4] * A[7] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + /* A[5] * A[6] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r8\n\t" + "adc r4, r4, #0\n\t" + "str r5, [%[r], #44]\n\t" + "mov r5, #0\n\t" + /* A[5] * A[7] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[6] * A[6] */ + "ldr r6, [%[a], #24]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + "str r3, [%[r], #48]\n\t" + "mov r3, #0\n\t" + /* A[6] * A[7] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "adc r3, r3, #0\n\t" + "str r4, [%[r], #52]\n\t" + "mov r4, #0\n\t" + /* A[7] * A[7] */ + "ldr r6, [%[a], #28]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r8\n\t" + "str r5, [%[r], #56]\n\t" + "str r3, [%[r], #60]\n\t" + /* Transfer tmp to r */ + "ldr r3, [%[tmp], #0]\n\t" + "ldr r4, [%[tmp], #4]\n\t" + "ldr r5, [%[tmp], #8]\n\t" + "ldr r6, [%[tmp], #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[tmp], #16]\n\t" + "ldr r4, [%[tmp], #20]\n\t" + "ldr r5, [%[tmp], #24]\n\t" + "ldr r6, [%[tmp], #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11" + ); +} + +/* 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_8(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_256_sqr_8(r, a); + sp_256_mont_reduce_8(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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_8(sp_digit* r, const sp_digit* a, int n, + const sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_8(r, a, m, mp); + for (; n > 1; n--) { + sp_256_mont_sqr_8(r, r, m, mp); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint32_t p256_mod_minus_2[8] = { + 0xfffffffdU,0xffffffffU,0xffffffffU,0x00000000U,0x00000000U,0x00000000U, + 0x00000001U,0xffffffffU +}; +#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_8(sp_digit* r, const sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 8); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_8(t, t, p256_mod, p256_mp_mod); + if (p256_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 8); +#else + sp_digit* t1 = td; + sp_digit* t2 = td + 2 * 8; + sp_digit* t3 = td + 4 * 8; + /* 0x2 */ + sp_256_mont_sqr_8(t1, a, p256_mod, p256_mp_mod); + /* 0x3 */ + sp_256_mont_mul_8(t2, t1, a, p256_mod, p256_mp_mod); + /* 0xc */ + sp_256_mont_sqr_n_8(t1, t2, 2, p256_mod, p256_mp_mod); + /* 0xd */ + sp_256_mont_mul_8(t3, t1, a, p256_mod, p256_mp_mod); + /* 0xf */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xf0 */ + sp_256_mont_sqr_n_8(t1, t2, 4, p256_mod, p256_mp_mod); + /* 0xfd */ + sp_256_mont_mul_8(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xff */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xff00 */ + sp_256_mont_sqr_n_8(t1, t2, 8, p256_mod, p256_mp_mod); + /* 0xfffd */ + sp_256_mont_mul_8(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffff */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffff0000 */ + sp_256_mont_sqr_n_8(t1, t2, 16, p256_mod, p256_mp_mod); + /* 0xfffffffd */ + sp_256_mont_mul_8(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffffffff */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000000 */ + sp_256_mont_sqr_n_8(t1, t2, 32, p256_mod, p256_mp_mod); + /* 0xffffffffffffffff */ + sp_256_mont_mul_8(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000001 */ + sp_256_mont_mul_8(r, t1, a, p256_mod, p256_mp_mod); + /* 0xffffffff000000010000000000000000000000000000000000000000 */ + sp_256_mont_sqr_n_8(r, r, 160, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff */ + sp_256_mont_mul_8(r, r, t2, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */ + sp_256_mont_sqr_n_8(r, r, 32, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */ + sp_256_mont_mul_8(r, r, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* 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. + */ +SP_NOINLINE static int32_t sp_256_cmp_8(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #28\n\t" + "\n1:\n\t" + "ldr r8, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r8, r8, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r8\n\t" + "subs r8, r8, r5\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "subs r5, r5, r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r8" + ); + + return r; +} + +/* Normalize the values in each word to 32. + * + * a Array of sp_digit to normalize. + */ +#define sp_256_norm_8(a) + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + int32_t n; + + sp_256_mont_inv_8(t1, p->z, t + 2*8); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_8(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 8, 0, sizeof(r->x) / 2U); + sp_256_mont_reduce_8(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_8(r->x, p256_mod); + sp_256_cond_sub_8(r->x, r->x, p256_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_256_norm_8(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_8(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 8, 0, sizeof(r->y) / 2U); + sp_256_mont_reduce_8(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_8(r->y, p256_mod); + sp_256_cond_sub_8(r->y, r->y, p256_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_256_norm_8(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. + */ +SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r8, #0\n\t" + "add r6, r6, #32\n\t" + "sub r8, r8, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r8\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#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). + */ +SP_NOINLINE static void sp_256_mont_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[b],#0]\n\t" + "ldr r8, [%[b],#4]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[a],#8]\n\t" + "ldr r5, [%[a],#12]\n\t" + "ldr r6, [%[b],#8]\n\t" + "ldr r8, [%[b],#12]\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[b],#16]\n\t" + "ldr r8, [%[b],#20]\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "mov r9, r4\n\t" + "mov r10, r5\n\t" + "ldr r4, [%[a],#24]\n\t" + "ldr r5, [%[a],#28]\n\t" + "ldr r6, [%[b],#24]\n\t" + "ldr r8, [%[b],#28]\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "mov r11, r4\n\t" + "mov r12, r5\n\t" + "adc r3, r3, r3\n\t" + "mov r6, r3\n\t" + "sub r3, r3, #1\n\t" + "mvn r3, r3\n\t" + "mov r8, #0\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[r],#8]\n\t" + "ldr r5, [%[r],#12]\n\t" + "sbcs r4, r4, r3\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "mov r4, r9\n\t" + "mov r5, r10\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r],#16]\n\t" + "str r5, [%[r],#20]\n\t" + "mov r4, r11\n\t" + "mov r5, r12\n\t" + "sbcs r4, r4, r6\n\t" + "sbc r5, r5, r3\n\t" + "str r4, [%[r],#24]\n\t" + "str r5, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_mont_dbl_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[a],#8]\n\t" + "ldr r8, [%[a],#12]\n\t" + "adds r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r8, r8, r8\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "str r8, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[a],#24]\n\t" + "ldr r8, [%[a],#28]\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r8, r8, r8\n\t" + "mov r9, r4\n\t" + "mov r10, r5\n\t" + "mov r11, r6\n\t" + "mov r12, r8\n\t" + "mov r3, #0\n\t" + "mov r8, #0\n\t" + "adc r3, r3, r3\n\t" + "mov r2, r3\n\t" + "sub r3, r3, #1\n\t" + "mvn r3, r3\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "ldr r6, [%[r],#8]\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, r3\n\t" + "sbcs r6, r6, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "ldr r4, [%[r],#12]\n\t" + "mov r5, r9\n\t" + "mov r6, r10\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r8\n\t" + "sbcs r6, r6, r8\n\t" + "str r4, [%[r],#12]\n\t" + "str r5, [%[r],#16]\n\t" + "str r6, [%[r],#20]\n\t" + "mov r4, r11\n\t" + "mov r5, r12\n\t" + "sbcs r4, r4, r2\n\t" + "sbc r5, r5, r3\n\t" + "str r4, [%[r],#24]\n\t" + "str r5, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r3", "r2", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_mont_tpl_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "ldr r2, [%[a],#0]\n\t" + "ldr r3, [%[a],#4]\n\t" + "ldr r4, [%[a],#8]\n\t" + "ldr r5, [%[a],#12]\n\t" + "ldr r6, [%[a],#16]\n\t" + "ldr r8, [%[a],#20]\n\t" + "ldr r9, [%[a],#24]\n\t" + "ldr r10, [%[a],#28]\n\t" + "adds r2, r2, r2\n\t" + "adcs r3, r3, r3\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "mov r11, #0\n\t" + "mov r14, #0\n\t" + "adc r11, r11, r11\n\t" + "mov r12, r11\n\t" + "sub r11, r11, #1\n\t" + "mvn r11, r11\n\t" + "subs r2, r2, r11\n\t" + "sbcs r3, r3, r11\n\t" + "sbcs r4, r4, r11\n\t" + "sbcs r5, r5, r14\n\t" + "sbcs r6, r6, r14\n\t" + "sbcs r8, r8, r14\n\t" + "sbcs r9, r9, r12\n\t" + "sbc r10, r10, r11\n\t" + "ldr r12, [%[a],#0]\n\t" + "ldr r14, [%[a],#4]\n\t" + "adds r2, r2, r12\n\t" + "adcs r3, r3, r14\n\t" + "ldr r12, [%[a],#8]\n\t" + "ldr r14, [%[a],#12]\n\t" + "adcs r4, r4, r12\n\t" + "adcs r5, r5, r14\n\t" + "ldr r12, [%[a],#16]\n\t" + "ldr r14, [%[a],#20]\n\t" + "adcs r6, r6, r12\n\t" + "adcs r8, r8, r14\n\t" + "ldr r12, [%[a],#24]\n\t" + "ldr r14, [%[a],#28]\n\t" + "adcs r9, r9, r12\n\t" + "adcs r10, r10, r14\n\t" + "mov r11, #0\n\t" + "mov r14, #0\n\t" + "adc r11, r11, r11\n\t" + "mov r12, r11\n\t" + "sub r11, r11, #1\n\t" + "mvn r11, r11\n\t" + "subs r2, r2, r11\n\t" + "str r2, [%[r],#0]\n\t" + "sbcs r3, r3, r11\n\t" + "str r3, [%[r],#4]\n\t" + "sbcs r4, r4, r11\n\t" + "str r4, [%[r],#8]\n\t" + "sbcs r5, r5, r14\n\t" + "str r5, [%[r],#12]\n\t" + "sbcs r6, r6, r14\n\t" + "str r6, [%[r],#16]\n\t" + "sbcs r8, r8, r14\n\t" + "str r8, [%[r],#20]\n\t" + "sbcs r9, r9, r12\n\t" + "str r9, [%[r],#24]\n\t" + "sbc r10, r10, r11\n\t" + "str r10, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r11", "r12", "r14", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10" + ); +} + +/* 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). + */ +SP_NOINLINE static void sp_256_mont_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[b],#0]\n\t" + "ldr r8, [%[b],#4]\n\t" + "subs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[a],#8]\n\t" + "ldr r5, [%[a],#12]\n\t" + "ldr r6, [%[b],#8]\n\t" + "ldr r8, [%[b],#12]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[b],#16]\n\t" + "ldr r8, [%[b],#20]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "mov r9, r4\n\t" + "mov r10, r5\n\t" + "ldr r4, [%[a],#24]\n\t" + "ldr r5, [%[a],#28]\n\t" + "ldr r6, [%[b],#24]\n\t" + "ldr r8, [%[b],#28]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "mov r11, r4\n\t" + "mov r12, r5\n\t" + "sbc r3, r3, r3\n\t" + "lsr r8, r3, #31\n\t" + "mov r6, #0\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[r],#8]\n\t" + "ldr r5, [%[r],#12]\n\t" + "adcs r4, r4, r3\n\t" + "adcs r5, r5, r6\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "mov r4, r9\n\t" + "mov r5, r10\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r6\n\t" + "str r4, [%[r],#16]\n\t" + "str r5, [%[r],#20]\n\t" + "mov r4, r11\n\t" + "mov r5, r12\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, r3\n\t" + "str r4, [%[r],#24]\n\t" + "str r5, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +/* 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). + */ +SP_NOINLINE static void sp_256_div2_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr r8, [%[a], #0]\n\t" + "lsl r8, r8, #31\n\t" + "lsr r8, r8, #31\n\t" + "mov r5, #0\n\t" + "sub r5, r5, r8\n\t" + "mov r8, #0\n\t" + "lsl r6, r5, #31\n\t" + "lsr r6, r6, #31\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r5\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "adcs r3, r3, r5\n\t" + "adcs r4, r4, r8\n\t" + "str r3, [%[r], #8]\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "adcs r3, r3, r8\n\t" + "adcs r4, r4, r8\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "adcs r3, r3, r6\n\t" + "adcs r4, r4, r5\n\t" + "adc r8, r8, r8\n\t" + "lsl r8, r8, #31\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, #31\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r5, r4\n\t" + "orr r6, r6, r8\n\t" + "mov r8, r3\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, #31\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r5, r4\n\t" + "orr r6, r6, r8\n\t" + "mov r8, r3\n\t" + "str r5, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, #31\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r5, r4\n\t" + "orr r6, r6, r8\n\t" + "mov r8, r3\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[r], #0]\n\t" + "ldr r4, [%[r], #4]\n\t" + "lsr r5, r3, #1\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r5, r4\n\t" + "orr r6, r6, r8\n\t" + "str r5, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "r3", "r4", "r5", "r6", "r8" + ); +} + +/* 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_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_8(t1, p->z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_8(z, p->y, p->z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_8(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_8(t2, p->x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_8(t1, p->x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_8(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_8(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_8(y, p->y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_8(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_8(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_8(y, y, p->x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_sqr_8(x, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_8(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_8(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_8(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_8(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_8(y, y, t2, p256_mod); +} + +#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. + */ +SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "add r6, r6, #32\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "sbcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r8, [%[b], #4]\n\t" + "subs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r8, [%[b], #12]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r8, [%[b], #28]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* 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_8(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])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, + sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* t3 = t + 4*8; + sp_digit* t4 = t + 6*8; + sp_digit* t5 = t + 8*8; + 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) { + const sp_point_256* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_256_sub_8(t1, p256_mod, q->y); + sp_256_norm_8(t1); + if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) != 0) { + sp_256_proj_point_dbl_8(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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<8; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<8; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<8; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_8(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_8(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_8(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_8(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_8(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_8(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(x, x, t5, p256_mod); + sp_256_mont_dbl_8(t1, y, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_mul_8(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(y, y, t5, p256_mod); + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td[16]; + sp_point_256 rtd; + sp_digit tmpd[2 * 8 * 5]; +#endif + sp_point_256* t; + sp_point_256* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_256_point_new_8(heap, rtd, rt); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 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 */ + (void)sp_256_mod_mul_norm_8(t[1].x, g->x, p256_mod); + (void)sp_256_mod_mul_norm_8(t[1].y, g->y, p256_mod); + (void)sp_256_mod_mul_norm_8(t[1].z, g->z, p256_mod); + t[1].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_256_proj_point_add_8(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_256_proj_point_add_8(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_256_proj_point_add_8(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_256_proj_point_add_8(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_256_proj_point_dbl_8(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_256_proj_point_add_8(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_256_proj_point_dbl_8(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_256_proj_point_add_8(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_256_proj_point_dbl_8(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_256_proj_point_add_8(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 6; + n = k[i+1] << 0; + c = 28; + y = n >> 28; + XMEMCPY(rt, &t[y], sizeof(sp_point_256)); + n <<= 4; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--]; + c += 32; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + + sp_256_proj_point_add_8(rt, rt, &t[y], tmp); + } + + if (map != 0) { + sp_256_map_8(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 8 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_256) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_256_point_free_8(rt, 1, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_256 { + sp_digit x[8]; + sp_digit y[8]; +} sp_table_entry_256; + +#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_8(sp_point_256* p, int n, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*8; + sp_digit* b = t + 4*8; + sp_digit* t1 = t + 6*8; + sp_digit* t2 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_256_mont_dbl_8(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_8(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(w, w, p256_mod, p256_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(t1, t1, w, p256_mod); + sp_256_mont_tpl_8(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_8(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(b, t1, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(t2, b, p256_mod); + sp_256_mont_sub_8(x, x, t2, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_8(t1, t1, p256_mod, p256_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_256_mont_mul_8(w, w, t1, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_8(y, b, x, p256_mod); + sp_256_mont_mul_8(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(y, y, p256_mod); + sp_256_mont_sub_8(y, y, t1, p256_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(t1, t1, w, p256_mod); + sp_256_mont_tpl_8(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_8(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(b, t1, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(t2, b, p256_mod); + sp_256_mont_sub_8(x, x, t2, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_8(t1, t1, p256_mod, p256_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_8(y, b, x, p256_mod); + sp_256_mont_mul_8(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(y, y, p256_mod); + sp_256_mont_sub_8(y, y, t1, p256_mod); +#endif + /* Y = Y/2 */ + sp_256_div2_8(y, y, p256_mod); +} + +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_256_proj_to_affine_8(sp_point_256* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 8; + sp_digit* tmp = t + 4 * 8; + + sp_256_mont_inv_8(t1, a->z, tmp); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_8(sp_point_256* r, const sp_point_256* p, + const sp_point_256* q, sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* t3 = t + 4*8; + sp_digit* t4 = t + 6*8; + sp_digit* t5 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_256_sub_8(t1, p256_mod, q->y); + sp_256_norm_8(t1); + if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) != 0) { + sp_256_proj_point_dbl_8(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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<8; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<8; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<8; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_8(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_8(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_8(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(x, t1, t5, p256_mod); + sp_256_mont_dbl_8(t1, t3, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_8(t3, t3, x, p256_mod); + sp_256_mont_mul_8(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(y, t3, t5, p256_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_8(const sp_point_256* a, + sp_table_entry_256* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td, s1d, s2d; +#endif + sp_point_256* t; + sp_point_256* s1 = NULL; + sp_point_256* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_256_point_new_8(heap, td, t); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_8(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_256)); + /* 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)); + + for (i=1; i<4; i++) { + sp_256_proj_point_dbl_n_8(t, 64, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<4; i++) { + XMEMCPY(s1->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_8(t, s1, s2, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_256_point_free_8(s2, 0, heap); + sp_256_point_free_8(s1, 0, heap); + sp_256_point_free_8( 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 coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit td[2 * 8 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_256_point_new_8(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 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=63; j<4; j++,x+=64) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=62; i>=0; i--) { + y = 0; + for (j=0,x=i; j<4; j++,x+=64) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + + sp_256_proj_point_dbl_8(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 = !y; + sp_256_proj_point_add_qz1_8(rt, rt, p, t); + } + + if (map != 0) { + sp_256_map_8(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, heap); + sp_256_point_free_8(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_256_t { + sp_digit x[8]; + sp_digit y[8]; + sp_table_entry_256 table[16]; + uint32_t cnt; + int set; +} sp_cache_256_t; + +static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_256_last = -1; +static THREAD_LS_T int sp_cache_256_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_256 = 0; + static wolfSSL_Mutex sp_cache_256_lock; +#endif + +static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_256_inited == 0) { + for (i=0; ix, sp_cache_256[i].x) & + sp_256_cmp_equal_8(g->y, sp_cache_256[i].y)) { + sp_cache_256[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_256_last + 1) % FP_ENTRIES; + for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_256[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_256_last) { + least = sp_cache_256[0].cnt; + for (j=1; jx, sizeof(sp_cache_256[i].x)); + XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y)); + sp_cache_256[i].set = 1; + sp_cache_256[i].cnt = 1; + } + + *cache = &sp_cache_256[i]; + sp_cache_256_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 coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); +#else + sp_digit tmp[2 * 8 * 5]; + sp_cache_256_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_256 == 0) { + wc_InitMutex(&sp_cache_256_lock); + initCacheMutex_256 = 1; + } + if (wc_LockMutex(&sp_cache_256_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_256(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_8(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_256_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#else +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_8(const sp_point_256* a, + sp_table_entry_256* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td, s1d, s2d; +#endif + sp_point_256* t; + sp_point_256* s1 = NULL; + sp_point_256* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_256_point_new_8(heap, td, t); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod); + } + if (err == MP_OKAY) { + err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_8(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_256)); + /* 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)); + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_8(t, 32, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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_8(t, s1, s2, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_256_point_free_8(s2, 0, heap); + sp_256_point_free_8(s1, 0, heap); + sp_256_point_free_8( 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 coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit td[2 * 8 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_256_point_new_8(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 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 / 32] >> (x % 32)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + + sp_256_proj_point_dbl_8(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 = !y; + sp_256_proj_point_add_qz1_8(rt, rt, p, t); + } + + if (map != 0) { + sp_256_map_8(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, heap); + sp_256_point_free_8(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_256_t { + sp_digit x[8]; + sp_digit y[8]; + sp_table_entry_256 table[256]; + uint32_t cnt; + int set; +} sp_cache_256_t; + +static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_256_last = -1; +static THREAD_LS_T int sp_cache_256_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_256 = 0; + static wolfSSL_Mutex sp_cache_256_lock; +#endif + +static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_256_inited == 0) { + for (i=0; ix, sp_cache_256[i].x) & + sp_256_cmp_equal_8(g->y, sp_cache_256[i].y)) { + sp_cache_256[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_256_last + 1) % FP_ENTRIES; + for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_256[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_256_last) { + least = sp_cache_256[0].cnt; + for (j=1; jx, sizeof(sp_cache_256[i].x)); + XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y)); + sp_cache_256[i].set = 1; + sp_cache_256[i].cnt = 1; + } + + *cache = &sp_cache_256[i]; + sp_cache_256_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 coordinates. + * + * 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_8(sp_point_256* r, const sp_point_256* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); +#else + sp_digit tmp[2 * 8 * 5]; + sp_cache_256_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_256 == 0) { + wc_InitMutex(&sp_cache_256_lock); + initCacheMutex_256 = 1; + } + if (wc_LockMutex(&sp_cache_256_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_256(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_8(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_256_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[8]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_256_point_new_8(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, km); + sp_256_point_from_ecc_point_8(point, gm); + + err = sp_256_ecc_mulmod_8(point, point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_8(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static const sp_table_entry_256 p256_table[16] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76 }, + { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18 } }, + /* 2 */ + { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961 }, + { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37, + 0x8d6f0f7b,0xf648f916 } }, + /* 3 */ + { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285 }, + { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562, + 0x6b6f7383,0x94bb725b } }, + /* 4 */ + { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4 }, + { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12 } }, + /* 5 */ + { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c }, + { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08 } }, + /* 6 */ + { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651 }, + { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a } }, + /* 7 */ + { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014, + 0xaeebffcd,0x9d0f27b2 }, + { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0, + 0x356ec48d,0x244a566d } }, + /* 8 */ + { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e, + 0xcd42ab1b,0x803f3e02 }, + { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e } }, + /* 9 */ + { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5 }, + { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418, + 0xe2d41c8b,0x23d0f130 } }, + /* 10 */ + { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9 }, + { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b, + 0x01fe49c3,0x2b100118 } }, + /* 11 */ + { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999 }, + { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551 } }, + /* 12 */ + { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148 }, + { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875, + 0x9f0e1a84,0x77387de3 } }, + /* 13 */ + { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0 }, + { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8 } }, + /* 14 */ + { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb }, + { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f } }, + /* 15 */ + { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52 }, + { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f } }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_8(sp_point_256* r, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table, + k, map, heap); +} + +#else +static const sp_table_entry_256 p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76 }, + { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18 } }, + /* 2 */ + { { 0x4147519a,0x20288602,0x26b372f0,0xd0981eac,0xa785ebc8,0xa9d4a7ca, + 0xdbdf58e9,0xd953c50d }, + { 0xfd590f8f,0x9d6361cc,0x44e6c917,0x72e9626b,0x22eb64cf,0x7fd96110, + 0x9eb288f3,0x863ebb7e } }, + /* 3 */ + { { 0x5cdb6485,0x7856b623,0x2f0a2f97,0x808f0ea2,0x4f7e300b,0x3e68d954, + 0xb5ff80a0,0x00076055 }, + { 0x838d2010,0x7634eb9b,0x3243708a,0x54014fbb,0x842a6606,0xe0e47d39, + 0x34373ee0,0x83087761 } }, + /* 4 */ + { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961 }, + { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37, + 0x8d6f0f7b,0xf648f916 } }, + /* 5 */ + { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285 }, + { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562, + 0x6b6f7383,0x94bb725b } }, + /* 6 */ + { { 0x720f141c,0xbbf9b48f,0x2df5bc74,0x6199b3cd,0x411045c4,0xdc3f6129, + 0x2f7dc4ef,0xcdd6bbcb }, + { 0xeaf436fd,0xcca6700b,0xb99326be,0x6f647f6d,0x014f2522,0x0c0fa792, + 0x4bdae5f6,0xa361bebd } }, + /* 7 */ + { { 0x597c13c7,0x28aa2558,0x50b7c3e1,0xc38d635f,0xf3c09d1d,0x07039aec, + 0xc4b5292c,0xba12ca09 }, + { 0x59f91dfd,0x9e408fa4,0xceea07fb,0x3af43b66,0x9d780b29,0x1eceb089, + 0x701fef4b,0x53ebb99d } }, + /* 8 */ + { { 0xb0e63d34,0x4fe7ee31,0xa9e54fab,0xf4600572,0xd5e7b5a4,0xc0493334, + 0x06d54831,0x8589fb92 }, + { 0x6583553a,0xaa70f5cc,0xe25649e5,0x0879094a,0x10044652,0xcc904507, + 0x02541c4f,0xebb0696d } }, + /* 9 */ + { { 0xac1647c5,0x4616ca15,0xc4cf5799,0xb8127d47,0x764dfbac,0xdc666aa3, + 0xd1b27da3,0xeb2820cb }, + { 0x6a87e008,0x9406f8d8,0x922378f3,0xd87dfa9d,0x80ccecb2,0x56ed2e42, + 0x55a7da1d,0x1f28289b } }, + /* 10 */ + { { 0x3b89da99,0xabbaa0c0,0xb8284022,0xa6f2d79e,0xb81c05e8,0x27847862, + 0x05e54d63,0x337a4b59 }, + { 0x21f7794a,0x3c67500d,0x7d6d7f61,0x207005b7,0x04cfd6e8,0x0a5a3781, + 0xf4c2fbd6,0x0d65e0d5 } }, + /* 11 */ + { { 0xb5275d38,0xd9d09bbe,0x0be0a358,0x4268a745,0x973eb265,0xf0762ff4, + 0x52f4a232,0xc23da242 }, + { 0x0b94520c,0x5da1b84f,0xb05bd78e,0x09666763,0x94d29ea1,0x3a4dcb86, + 0xc790cff1,0x19de3b8c } }, + /* 12 */ + { { 0x26c5fe04,0x183a716c,0x3bba1bdb,0x3b28de0b,0xa4cb712c,0x7432c586, + 0x91fccbfd,0xe34dcbd4 }, + { 0xaaa58403,0xb408d46b,0x82e97a53,0x9a697486,0x36aaa8af,0x9e390127, + 0x7b4e0f7f,0xe7641f44 } }, + /* 13 */ + { { 0xdf64ba59,0x7d753941,0x0b0242fc,0xd33f10ec,0xa1581859,0x4f06dfc6, + 0x052a57bf,0x4a12df57 }, + { 0x9439dbd0,0xbfa6338f,0xbde53e1f,0xd3c24bd4,0x21f1b314,0xfd5e4ffa, + 0xbb5bea46,0x6af5aa93 } }, + /* 14 */ + { { 0x10c91999,0xda10b699,0x2a580491,0x0a24b440,0xb8cc2090,0x3e0094b4, + 0x66a44013,0x5fe3475a }, + { 0xf93e7b4b,0xb0f8cabd,0x7c23f91a,0x292b501a,0xcd1e6263,0x42e889ae, + 0xecfea916,0xb544e308 } }, + /* 15 */ + { { 0x16ddfdce,0x6478c6e9,0xf89179e6,0x2c329166,0x4d4e67e1,0x4e8d6e76, + 0xa6b0c20b,0xe0b6b2bd }, + { 0xbb7efb57,0x0d312df2,0x790c4007,0x1aac0dde,0x679bc944,0xf90336ad, + 0x25a63774,0x71c023de } }, + /* 16 */ + { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4 }, + { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12 } }, + /* 17 */ + { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c }, + { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08 } }, + /* 18 */ + { { 0x309a4e1f,0x1e99f581,0xe9270074,0xab7de71b,0xefd28d20,0x26a5ef0b, + 0x7f9c563f,0xe7c0073f }, + { 0x0ef59f76,0x1f6d663a,0x20fcb050,0x669b3b54,0x7a6602d4,0xc08c1f7a, + 0xc65b3c0a,0xe08504fe } }, + /* 19 */ + { { 0xa031b3ca,0xf098f68d,0xe6da6d66,0x6d1cab9e,0x94f246e8,0x5bfd81fa, + 0x5b0996b4,0x78f01882 }, + { 0x3a25787f,0xb7eefde4,0x1dccac9b,0x8016f80d,0xb35bfc36,0x0cea4877, + 0x7e94747a,0x43a773b8 } }, + /* 20 */ + { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651 }, + { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a } }, + /* 21 */ + { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014, + 0xaeebffcd,0x9d0f27b2 }, + { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0, + 0x356ec48d,0x244a566d } }, + /* 22 */ + { { 0xeacf1f96,0x6db0394a,0x024c271c,0x9f2122a9,0x82cbd3b9,0x2626ac1b, + 0x3581ef69,0x45e58c87 }, + { 0xa38f9dbc,0xd3ff479d,0xe888a040,0xa8aaf146,0x46e0bed7,0x945adfb2, + 0xc1e4b7a4,0xc040e21c } }, + /* 23 */ + { { 0x6f8117b6,0x847af000,0x73a35433,0x651969ff,0x1d9475eb,0x482b3576, + 0x682c6ec7,0x1cdf5c97 }, + { 0x11f04839,0x7db775b4,0x48de1698,0x7dbeacf4,0xb70b3219,0xb2921dd1, + 0xa92dff3d,0x046755f8 } }, + /* 24 */ + { { 0xbce8ffcd,0xcc8ac5d2,0x2fe61a82,0x0d53c48b,0x7202d6c7,0xf6f16172, + 0x3b83a5f3,0x046e5e11 }, + { 0xd8007f01,0xe7b8ff64,0x5af43183,0x7fb1ef12,0x35e1a03c,0x045c5ea6, + 0x303d005b,0x6e0106c3 } }, + /* 25 */ + { { 0x88dd73b1,0x48c73584,0x995ed0d9,0x7670708f,0xc56a2ab7,0x38385ea8, + 0xe901cf1f,0x442594ed }, + { 0x12d4b65b,0xf8faa2c9,0x96c90c37,0x94c2343b,0x5e978d1f,0xd326e4a1, + 0x4c2ee68e,0xa796fa51 } }, + /* 26 */ + { { 0x823addd7,0x359fb604,0xe56693b3,0x9e2a6183,0x3cbf3c80,0xf885b78e, + 0xc69766e9,0xe4ad2da9 }, + { 0x8e048a61,0x357f7f42,0xc092d9a0,0x082d198c,0xc03ed8ef,0xfc3a1af4, + 0xc37b5143,0xc5e94046 } }, + /* 27 */ + { { 0x2be75f9e,0x476a538c,0xcb123a78,0x6fd1a9e8,0xb109c04b,0xd85e4df0, + 0xdb464747,0x63283daf }, + { 0xbaf2df15,0xce728cf7,0x0ad9a7f4,0xe592c455,0xe834bcc3,0xfab226ad, + 0x1981a938,0x68bd19ab } }, + /* 28 */ + { { 0x1887d659,0xc08ead51,0xb359305a,0x3374d5f4,0xcfe74fe3,0x96986981, + 0x3c6fdfd6,0x495292f5 }, + { 0x1acec896,0x4a878c9e,0xec5b4484,0xd964b210,0x664d60a7,0x6696f7e2, + 0x26036837,0x0ec7530d } }, + /* 29 */ + { { 0xad2687bb,0x2da13a05,0xf32e21fa,0xa1f83b6a,0x1dd4607b,0x390f5ef5, + 0x64863f0b,0x0f6207a6 }, + { 0x0f138233,0xbd67e3bb,0x272aa718,0xdd66b96c,0x26ec88ae,0x8ed00407, + 0x08ed6dcf,0xff0db072 } }, + /* 30 */ + { { 0x4c95d553,0x749fa101,0x5d680a8a,0xa44052fd,0xff3b566f,0x183b4317, + 0x88740ea3,0x313b513c }, + { 0x08d11549,0xb402e2ac,0xb4dee21c,0x071ee10b,0x47f2320e,0x26b987dd, + 0x86f19f81,0x2d3abcf9 } }, + /* 31 */ + { { 0x815581a2,0x4c288501,0x632211af,0x9a0a6d56,0x0cab2e99,0x19ba7a0f, + 0xded98cdf,0xc036fa10 }, + { 0xc1fbd009,0x29ae08ba,0x06d15816,0x0b68b190,0x9b9e0d8f,0xc2eb3277, + 0xb6d40194,0xa6b2a2c4 } }, + /* 32 */ + { { 0x6d3549cf,0xd433e50f,0xfacd665e,0x6f33696f,0xce11fcb4,0x695bfdac, + 0xaf7c9860,0x810ee252 }, + { 0x7159bb2c,0x65450fe1,0x758b357b,0xf7dfbebe,0xd69fea72,0x2b057e74, + 0x92731745,0xd485717a } }, + /* 33 */ + { { 0xf0cb5a98,0x11741a8a,0x1f3110bf,0xd3da8f93,0xab382adf,0x1994e2cb, + 0x2f9a604e,0x6a6045a7 }, + { 0xa2b2411d,0x170c0d3f,0x510e96e0,0xbe0eb83e,0x8865b3cc,0x3bcc9f73, + 0xf9e15790,0xd3e45cfa } }, + /* 34 */ + { { 0xe83f7669,0xce1f69bb,0x72877d6b,0x09f8ae82,0x3244278d,0x9548ae54, + 0xe3c2c19c,0x207755de }, + { 0x6fef1945,0x87bd61d9,0xb12d28c3,0x18813cef,0x72df64aa,0x9fbcd1d6, + 0x7154b00d,0x48dc5ee5 } }, + /* 35 */ + { { 0xf7e5a199,0x123790bf,0x989ccbb7,0xe0efb8cf,0x0a519c79,0xc27a2bfe, + 0xdff6f445,0xf2fb0aed }, + { 0xf0b5025f,0x41c09575,0x40fa9f22,0x550543d7,0x380bfbd0,0x8fa3c8ad, + 0xdb28d525,0xa13e9015 } }, + /* 36 */ + { { 0xa2b65cbc,0xf9f7a350,0x2a464226,0x0b04b972,0xe23f07a1,0x265ce241, + 0x1497526f,0x2bf0d6b0 }, + { 0x4b216fb7,0xd3d4dd3f,0xfbdda26a,0xf7d7b867,0x6708505c,0xaeb7b83f, + 0x162fe89f,0x42a94a5a } }, + /* 37 */ + { { 0xeaadf191,0x5846ad0b,0x25a268d7,0x0f8a4890,0x494dc1f6,0xe8603050, + 0xc65ede3d,0x2c2dd969 }, + { 0x93849c17,0x6d02171d,0x1da250dd,0x460488ba,0x3c3a5485,0x4810c706, + 0x42c56dbc,0xf437fa1f } }, + /* 38 */ + { { 0x4a0f7dab,0x6aa0d714,0x1776e9ac,0x0f049793,0xf5f39786,0x52c0a050, + 0x54707aa8,0xaaf45b33 }, + { 0xc18d364a,0x85e37c33,0x3e497165,0xd40b9b06,0x15ec5444,0xf4171681, + 0xf4f272bc,0xcdf6310d } }, + /* 39 */ + { { 0x8ea8b7ef,0x7473c623,0x85bc2287,0x08e93518,0x2bda8e34,0x41956772, + 0xda9e2ff2,0xf0d008ba }, + { 0x2414d3b1,0x2912671d,0xb019ea76,0xb3754985,0x453bcbdb,0x5c61b96d, + 0xca887b8b,0x5bd5c2f5 } }, + /* 40 */ + { { 0xf49a3154,0xef0f469e,0x6e2b2e9a,0x3e85a595,0xaa924a9c,0x45aaec1e, + 0xa09e4719,0xaa12dfc8 }, + { 0x4df69f1d,0x26f27227,0xa2ff5e73,0xe0e4c82c,0xb7a9dd44,0xb9d8ce73, + 0xe48ca901,0x6c036e73 } }, + /* 41 */ + { { 0x0f6e3138,0x5cfae12a,0x25ad345a,0x6966ef00,0x45672bc5,0x8993c64b, + 0x96afbe24,0x292ff658 }, + { 0x5e213402,0xd5250d44,0x4392c9fe,0xf6580e27,0xda1c72e8,0x097b397f, + 0x311b7276,0x644e0c90 } }, + /* 42 */ + { { 0xa47153f0,0xe1e421e1,0x920418c9,0xb86c3b79,0x705d7672,0x93bdce87, + 0xcab79a77,0xf25ae793 }, + { 0x6d869d0c,0x1f3194a3,0x4986c264,0x9d55c882,0x096e945e,0x49fb5ea3, + 0x13db0a3e,0x39b8e653 } }, + /* 43 */ + { { 0xb6fd2e59,0x37754200,0x9255c98f,0x35e2c066,0x0e2a5739,0xd9dab21a, + 0x0f19db06,0x39122f2f }, + { 0x03cad53c,0xcfbce1e0,0xe65c17e3,0x225b2c0f,0x9aa13877,0x72baf1d2, + 0xce80ff8d,0x8de80af8 } }, + /* 44 */ + { { 0x207bbb76,0xafbea8d9,0x21782758,0x921c7e7c,0x1c0436b1,0xdfa2b74b, + 0x2e368c04,0x87194906 }, + { 0xa3993df5,0xb5f928bb,0xf3b3d26a,0x639d75b5,0x85b55050,0x011aa78a, + 0x5b74fde1,0xfc315e6a } }, + /* 45 */ + { { 0xe8d6ecfa,0x561fd41a,0x1aec7f86,0x5f8c44f6,0x4924741d,0x98452a7b, + 0xee389088,0xe6d4a7ad }, + { 0x4593c75d,0x60552ed1,0xdd271162,0x70a70da4,0x7ba2c7db,0xd2aede93, + 0x9be2ae57,0x35dfaf9a } }, + /* 46 */ + { { 0xaa736636,0x6b956fcd,0xae2cab7e,0x09f51d97,0x0f349966,0xfb10bf41, + 0x1c830d2b,0x1da5c7d7 }, + { 0x3cce6825,0x5c41e483,0xf9573c3b,0x15ad118f,0xf23036b8,0xa28552c7, + 0xdbf4b9d6,0x7077c0fd } }, + /* 47 */ + { { 0x46b9661c,0xbf63ff8d,0x0d2cfd71,0xa1dfd36b,0xa847f8f7,0x0373e140, + 0xe50efe44,0x53a8632e }, + { 0x696d8051,0x0976ff68,0xc74f468a,0xdaec0c95,0x5e4e26bd,0x62994dc3, + 0x34e1fcc1,0x028ca76d } }, + /* 48 */ + { { 0xfc9877ee,0xd11d47dc,0x801d0002,0xc8b36210,0x54c260b6,0xd002c117, + 0x6962f046,0x04c17cd8 }, + { 0xb0daddf5,0x6d9bd094,0x24ce55c0,0xbea23575,0x72da03b5,0x663356e6, + 0xfed97474,0xf7ba4de9 } }, + /* 49 */ + { { 0xebe1263f,0xd0dbfa34,0x71ae7ce6,0x55763735,0x82a6f523,0xd2440553, + 0x52131c41,0xe31f9600 }, + { 0xea6b6ec6,0xd1bb9216,0x73c2fc44,0x37a1d12e,0x89d0a294,0xc10e7eac, + 0xce34d47b,0xaa3a6259 } }, + /* 50 */ + { { 0x36f3dcd3,0xfbcf9df5,0xd2bf7360,0x6ceded50,0xdf504f5b,0x491710fa, + 0x7e79daee,0x2398dd62 }, + { 0x6d09569e,0xcf4705a3,0x5149f769,0xea0619bb,0x35f6034c,0xff9c0377, + 0x1c046210,0x5717f5b2 } }, + /* 51 */ + { { 0x21dd895e,0x9fe229c9,0x40c28451,0x8e518500,0x1d637ecd,0xfa13d239, + 0x0e3c28de,0x660a2c56 }, + { 0xd67fcbd0,0x9cca88ae,0x0ea9f096,0xc8472478,0x72e92b4d,0x32b2f481, + 0x4f522453,0x624ee54c } }, + /* 52 */ + { { 0xd897eccc,0x09549ce4,0x3f9880aa,0x4d49d1d9,0x043a7c20,0x723c2423, + 0x92bdfbc0,0x4f392afb }, + { 0x7de44fd9,0x6969f8fa,0x57b32156,0xb66cfbe4,0x368ebc3c,0xdb2fa803, + 0xccdb399c,0x8a3e7977 } }, + /* 53 */ + { { 0x06c4b125,0xdde1881f,0xf6e3ca8c,0xae34e300,0x5c7a13e9,0xef6999de, + 0x70c24404,0x3888d023 }, + { 0x44f91081,0x76280356,0x5f015504,0x3d9fcf61,0x632cd36e,0x1827edc8, + 0x18102336,0xa5e62e47 } }, + /* 54 */ + { { 0x2facd6c8,0x1a825ee3,0x54bcbc66,0x699c6354,0x98df9931,0x0ce3edf7, + 0x466a5adc,0x2c4768e6 }, + { 0x90a64bc9,0xb346ff8c,0xe4779f5c,0x630a6020,0xbc05e884,0xd949d064, + 0xf9e652a0,0x7b5e6441 } }, + /* 55 */ + { { 0x1d28444a,0x2169422c,0xbe136a39,0xe996c5d8,0xfb0c7fce,0x2387afe5, + 0x0c8d744a,0xb8af73cb }, + { 0x338b86fd,0x5fde83aa,0xa58a5cff,0xfee3f158,0x20ac9433,0xc9ee8f6f, + 0x7f3f0895,0xa036395f } }, + /* 56 */ + { { 0xa10f7770,0x8c73c6bb,0xa12a0e24,0xa6f16d81,0x51bc2b9f,0x100df682, + 0x875fb533,0x4be36b01 }, + { 0x9fb56dbb,0x9226086e,0x07e7a4f8,0x306fef8b,0x66d52f20,0xeeaccc05, + 0x1bdc00c0,0x8cbc9a87 } }, + /* 57 */ + { { 0xc0dac4ab,0xe131895c,0x712ff112,0xa874a440,0x6a1cee57,0x6332ae7c, + 0x0c0835f8,0x44e7553e }, + { 0x7734002d,0x6d503fff,0x0b34425c,0x9d35cb8b,0x0e8738b5,0x95f70276, + 0x5eb8fc18,0x470a683a } }, + /* 58 */ + { { 0x90513482,0x81b761dc,0x01e9276a,0x0287202a,0x0ce73083,0xcda441ee, + 0xc63dc6ef,0x16410690 }, + { 0x6d06a2ed,0xf5034a06,0x189b100b,0xdd4d7745,0xab8218c9,0xd914ae72, + 0x7abcbb4f,0xd73479fd } }, + /* 59 */ + { { 0x5ad4c6e5,0x7edefb16,0x5b06d04d,0x262cf08f,0x8575cb14,0x12ed5bb1, + 0x0771666b,0x816469e3 }, + { 0x561e291e,0xd7ab9d79,0xc1de1661,0xeb9daf22,0x135e0513,0xf49827eb, + 0xf0dd3f9c,0x0a36dd23 } }, + /* 60 */ + { { 0x41d5533c,0x098d32c7,0x8684628f,0x7c5f5a9e,0xe349bd11,0x39a228ad, + 0xfdbab118,0xe331dfd6 }, + { 0x6bcc6ed8,0x5100ab68,0xef7a260e,0x7160c3bd,0xbce850d7,0x9063d9a7, + 0x492e3389,0xd3b4782a } }, + /* 61 */ + { { 0xf3821f90,0xa149b6e8,0x66eb7aad,0x92edd9ed,0x1a013116,0x0bb66953, + 0x4c86a5bd,0x7281275a }, + { 0xd3ff47e5,0x503858f7,0x61016441,0x5e1616bc,0x7dfd9bb1,0x62b0f11a, + 0xce145059,0x2c062e7e } }, + /* 62 */ + { { 0x0159ac2e,0xa76f996f,0xcbdb2713,0x281e7736,0x08e46047,0x2ad6d288, + 0x2c4e7ef1,0x282a35f9 }, + { 0xc0ce5cd2,0x9c354b1e,0x1379c229,0xcf99efc9,0x3e82c11e,0x992caf38, + 0x554d2abd,0xc71cd513 } }, + /* 63 */ + { { 0x09b578f4,0x4885de9c,0xe3affa7a,0x1884e258,0x59182f1f,0x8f76b1b7, + 0xcf47f3a3,0xc50f6740 }, + { 0x374b68ea,0xa9c4adf3,0x69965fe2,0xa406f323,0x85a53050,0x2f86a222, + 0x212958dc,0xb9ecb3a7 } }, + /* 64 */ + { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e, + 0xcd42ab1b,0x803f3e02 }, + { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e } }, + /* 65 */ + { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5 }, + { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418, + 0xe2d41c8b,0x23d0f130 } }, + /* 66 */ + { { 0xf41500d9,0x857ab6ed,0xfcbeada8,0x0d890ae5,0x89725951,0x52fe8648, + 0xc0a3fadd,0xb0288dd6 }, + { 0x650bcb08,0x85320f30,0x695d6e16,0x71af6313,0xb989aa76,0x31f520a7, + 0xf408c8d2,0xffd3724f } }, + /* 67 */ + { { 0xb458e6cb,0x53968e64,0x317a5d28,0x992dad20,0x7aa75f56,0x3814ae0b, + 0xd78c26df,0xf5590f4a }, + { 0xcf0ba55a,0x0fc24bd3,0x0c778bae,0x0fc4724a,0x683b674a,0x1ce9864f, + 0xf6f74a20,0x18d6da54 } }, + /* 68 */ + { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9 }, + { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b, + 0x01fe49c3,0x2b100118 } }, + /* 69 */ + { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999 }, + { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551 } }, + /* 70 */ + { { 0x1e9af288,0x55f655bb,0xf7ada931,0x647e1a64,0xcb2820e5,0x43697e4b, + 0x07ed56ff,0x51e00db1 }, + { 0x771c327e,0x43d169b8,0x4a96c2ad,0x29cdb20b,0x3deb4779,0xc07d51f5, + 0x49829177,0xe22f4241 } }, + /* 71 */ + { { 0x635f1abb,0xcd45e8f4,0x68538874,0x7edc0cb5,0xb5a8034d,0xc9472c1f, + 0x52dc48c9,0xf709373d }, + { 0xa8af30d6,0x401966bb,0xf137b69c,0x95bf5f4a,0x9361c47e,0x3966162a, + 0xe7275b11,0xbd52d288 } }, + /* 72 */ + { { 0x9c5fa877,0xab155c7a,0x7d3a3d48,0x17dad672,0x73d189d8,0x43f43f9e, + 0xc8aa77a6,0xa0d0f8e4 }, + { 0xcc94f92d,0x0bbeafd8,0x0c4ddb3a,0xd818c8be,0xb82eba14,0x22cc65f8, + 0x946d6a00,0xa56c78c7 } }, + /* 73 */ + { { 0x0dd09529,0x2962391b,0x3daddfcf,0x803e0ea6,0x5b5bf481,0x2c77351f, + 0x731a367a,0xd8befdf8 }, + { 0xfc0157f4,0xab919d42,0xfec8e650,0xf51caed7,0x02d48b0a,0xcdf9cb40, + 0xce9f6478,0x854a68a5 } }, + /* 74 */ + { { 0x63506ea5,0xdc35f67b,0xa4fe0d66,0x9286c489,0xfe95cd4d,0x3f101d3b, + 0x98846a95,0x5cacea0b }, + { 0x9ceac44d,0xa90df60c,0x354d1c3a,0x3db29af4,0xad5dbabe,0x08dd3de8, + 0x35e4efa9,0xe4982d12 } }, + /* 75 */ + { { 0xc34cd55e,0x23104a22,0x2680d132,0x58695bb3,0x1fa1d943,0xfb345afa, + 0x16b20499,0x8046b7f6 }, + { 0x38e7d098,0xb533581e,0xf46f0b70,0xd7f61e8d,0x44cb78c4,0x30dea9ea, + 0x9082af55,0xeb17ca7b } }, + /* 76 */ + { { 0x76a145b9,0x1751b598,0xc1bc71ec,0xa5cf6b0f,0x392715bb,0xd3e03565, + 0xfab5e131,0x097b00ba }, + { 0x565f69e1,0xaa66c8e9,0xb5be5199,0x77e8f75a,0xda4fd984,0x6033ba11, + 0xafdbcc9e,0xf95c747b } }, + /* 77 */ + { { 0xbebae45e,0x558f01d3,0xc4bc6955,0xa8ebe9f0,0xdbc64fc6,0xaeb705b1, + 0x566ed837,0x3512601e }, + { 0xfa1161cd,0x9336f1e1,0x4c65ef87,0x328ab8d5,0x724f21e5,0x4757eee2, + 0x6068ab6b,0x0ef97123 } }, + /* 78 */ + { { 0x54ca4226,0x02598cf7,0xf8642c8e,0x5eede138,0x468e1790,0x48963f74, + 0x3b4fbc95,0xfc16d933 }, + { 0xe7c800ca,0xbe96fb31,0x2678adaa,0x13806331,0x6ff3e8b5,0x3d624497, + 0xb95d7a17,0x14ca4af1 } }, + /* 79 */ + { { 0xbd2f81d5,0x7a4771ba,0x01f7d196,0x1a5f9d69,0xcad9c907,0xd898bef7, + 0xf59c231d,0x4057b063 }, + { 0x89c05c0a,0xbffd82fe,0x1dc0df85,0xe4911c6f,0xa35a16db,0x3befccae, + 0xf1330b13,0x1c3b5d64 } }, + /* 80 */ + { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148 }, + { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875, + 0x9f0e1a84,0x77387de3 } }, + /* 81 */ + { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0 }, + { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8 } }, + /* 82 */ + { { 0x84e35743,0x32aa3202,0x85a3cdef,0x320d6ab1,0x1df19819,0xb821b176, + 0xc433851f,0x5721361f }, + { 0x71fc9168,0x1f0db36a,0x5e5c403c,0x5f98ba73,0x37bcd8f5,0xf64ca87e, + 0xe6bb11bd,0xdcbac3c9 } }, + /* 83 */ + { { 0x4518cbe2,0xf01d9968,0x9c9eb04e,0xd242fc18,0xe47feebf,0x727663c7, + 0x2d626862,0xb8c1c89e }, + { 0xc8e1d569,0x51a58bdd,0xb7d88cd0,0x563809c8,0xf11f31eb,0x26c27fd9, + 0x2f9422d4,0x5d23bbda } }, + /* 84 */ + { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb }, + { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f } }, + /* 85 */ + { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52 }, + { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f } }, + /* 86 */ + { { 0x562976cc,0xbda5f14e,0x0ef12c38,0x22bca3e6,0x6cca9852,0xbbfa3064, + 0x08e2987a,0xbdb79dc8 }, + { 0xcb06a772,0xfd2cb5c9,0xfe536dce,0x38f475aa,0x7c2b5db8,0xc2a3e022, + 0xadd3c14a,0x8ee86001 } }, + /* 87 */ + { { 0xa4ade873,0xcbe96981,0xc4fba48c,0x7ee9aa4d,0x5a054ba5,0x2cee2899, + 0x6f77aa4b,0x92e51d7a }, + { 0x7190a34d,0x948bafa8,0xf6bd1ed1,0xd698f75b,0x0caf1144,0xd00ee6e3, + 0x0a56aaaa,0x5182f86f } }, + /* 88 */ + { { 0x7a4cc99c,0xfba6212c,0x3e6d9ca1,0xff609b68,0x5ac98c5a,0x5dbb27cb, + 0x4073a6f2,0x91dcab5d }, + { 0x5f575a70,0x01b6cc3d,0x6f8d87fa,0x0cb36139,0x89981736,0x165d4e8c, + 0x97974f2b,0x17a0cedb } }, + /* 89 */ + { { 0x076c8d3a,0x38861e2a,0x210f924b,0x701aad39,0x13a835d9,0x94d0eae4, + 0x7f4cdf41,0x2e8ce36c }, + { 0x037a862b,0x91273dab,0x60e4c8fa,0x01ba9bb7,0x33baf2dd,0xf9645388, + 0x34f668f3,0xf4ccc6cb } }, + /* 90 */ + { { 0xf1f79687,0x44ef525c,0x92efa815,0x7c595495,0xa5c78d29,0xe1231741, + 0x9a0df3c9,0xac0db488 }, + { 0xdf01747f,0x86bfc711,0xef17df13,0x592b9358,0x5ccb6bb5,0xe5880e4f, + 0x94c974a2,0x95a64a61 } }, + /* 91 */ + { { 0xc15a4c93,0x72c1efda,0x82585141,0x40269b73,0x16cb0bad,0x6a8dfb1c, + 0x29210677,0x231e54ba }, + { 0x8ae6d2dc,0xa70df917,0x39112918,0x4d6aa63f,0x5e5b7223,0xf627726b, + 0xd8a731e1,0xab0be032 } }, + /* 92 */ + { { 0x8d131f2d,0x097ad0e9,0x3b04f101,0x637f09e3,0xd5e9a748,0x1ac86196, + 0x2cf6a679,0xf1bcc880 }, + { 0xe8daacb4,0x25c69140,0x60f65009,0x3c4e4055,0x477937a6,0x591cc8fc, + 0x5aebb271,0x85169469 } }, + /* 93 */ + { { 0xf1dcf593,0xde35c143,0xb018be3b,0x78202b29,0x9bdd9d3d,0xe9cdadc2, + 0xdaad55d8,0x8f67d9d2 }, + { 0x7481ea5f,0x84111656,0xe34c590c,0xe7d2dde9,0x05053fa8,0xffdd43f4, + 0xc0728b5d,0xf84572b9 } }, + /* 94 */ + { { 0x97af71c9,0x5e1a7a71,0x7a736565,0xa1449444,0x0e1d5063,0xa1b4ae07, + 0x616b2c19,0xedee2710 }, + { 0x11734121,0xb2f034f5,0x4a25e9f0,0x1cac6e55,0xa40c2ecf,0x8dc148f3, + 0x44ebd7f4,0x9fd27e9b } }, + /* 95 */ + { { 0xf6e2cb16,0x3cc7658a,0xfe5919b6,0xe3eb7d2c,0x168d5583,0x5a8c5816, + 0x958ff387,0xa40c2fb6 }, + { 0xfedcc158,0x8c9ec560,0x55f23056,0x7ad804c6,0x9a307e12,0xd9396704, + 0x7dc6decf,0x99bc9bb8 } }, + /* 96 */ + { { 0x927dafc6,0x84a9521d,0x5c09cd19,0x52c1fb69,0xf9366dde,0x9d9581a0, + 0xa16d7e64,0x9abe210b }, + { 0x48915220,0x480af84a,0x4dd816c6,0xfa73176a,0x1681ca5a,0xc7d53987, + 0x87f344b0,0x7881c257 } }, + /* 97 */ + { { 0xe0bcf3ff,0x93399b51,0x127f74f6,0x0d02cbc5,0xdd01d968,0x8fb465a2, + 0xa30e8940,0x15e6e319 }, + { 0x3e0e05f4,0x646d6e0d,0x43588404,0xfad7bddc,0xc4f850d3,0xbe61c7d1, + 0x191172ce,0x0e55facf } }, + /* 98 */ + { { 0xf8787564,0x7e9d9806,0x31e85ce6,0x1a331721,0xb819e8d6,0x6b0158ca, + 0x6fe96577,0xd73d0976 }, + { 0x1eb7206e,0x42483425,0xc618bb42,0xa519290f,0x5e30a520,0x5dcbb859, + 0x8f15a50b,0x9250a374 } }, + /* 99 */ + { { 0xbe577410,0xcaff08f8,0x5077a8c6,0xfd408a03,0xec0a63a4,0xf1f63289, + 0xc1cc8c0b,0x77414082 }, + { 0xeb0991cd,0x05a40fa6,0x49fdc296,0xc1ca0866,0xb324fd40,0x3a68a3c7, + 0x12eb20b9,0x8cb04f4d } }, + /* 100 */ + { { 0x6906171c,0xb1c2d055,0xb0240c3f,0x9073e9cd,0xd8906841,0xdb8e6b4f, + 0x47123b51,0xe4e429ef }, + { 0x38ec36f4,0x0b8dd53c,0xff4b6a27,0xf9d2dc01,0x879a9a48,0x5d066e07, + 0x3c6e6552,0x37bca2ff } }, + /* 101 */ + { { 0xdf562470,0x4cd2e3c7,0xc0964ac9,0x44f272a2,0x80c793be,0x7c6d5df9, + 0x3002b22a,0x59913edc }, + { 0x5750592a,0x7a139a83,0xe783de02,0x99e01d80,0xea05d64f,0xcf8c0375, + 0xb013e226,0x43786e4a } }, + /* 102 */ + { { 0x9e56b5a6,0xff32b0ed,0xd9fc68f9,0x0750d9a6,0x597846a7,0xec15e845, + 0xb7e79e7a,0x8638ca98 }, + { 0x0afc24b2,0x2f5ae096,0x4dace8f2,0x05398eaf,0xaecba78f,0x3b765dd0, + 0x7b3aa6f0,0x1ecdd36a } }, + /* 103 */ + { { 0x6c5ff2f3,0x5d3acd62,0x2873a978,0xa2d516c0,0xd2110d54,0xad94c9fa, + 0xd459f32d,0xd85d0f85 }, + { 0x10b11da3,0x9f700b8d,0xa78318c4,0xd2c22c30,0x9208decd,0x556988f4, + 0xb4ed3c62,0xa04f19c3 } }, + /* 104 */ + { { 0xed7f93bd,0x087924c8,0x392f51f6,0xcb64ac5d,0x821b71af,0x7cae330a, + 0x5c0950b0,0x92b2eeea }, + { 0x85b6e235,0x85ac4c94,0x2936c0f0,0xab2ca4a9,0xe0508891,0x80faa6b3, + 0x5834276c,0x1ee78221 } }, + /* 105 */ + { { 0xe63e79f7,0xa60a2e00,0xf399d906,0xf590e7b2,0x6607c09d,0x9021054a, + 0x57a6e150,0xf3f2ced8 }, + { 0xf10d9b55,0x200510f3,0xd8642648,0x9d2fcfac,0xe8bd0e7c,0xe5631aa7, + 0x3da3e210,0x0f56a454 } }, + /* 106 */ + { { 0x1043e0df,0x5b21bffa,0x9c007e6d,0x6c74b6cc,0xd4a8517a,0x1a656ec0, + 0x1969e263,0xbd8f1741 }, + { 0xbeb7494a,0x8a9bbb86,0x45f3b838,0x1567d46f,0xa4e5a79a,0xdf7a12a7, + 0x30ccfa09,0x2d1a1c35 } }, + /* 107 */ + { { 0x506508da,0x192e3813,0xa1d795a7,0x336180c4,0x7a9944b3,0xcddb5949, + 0xb91fba46,0xa107a65e }, + { 0x0f94d639,0xe6d1d1c5,0x8a58b7d7,0x8b4af375,0xbd37ca1c,0x1a7c5584, + 0xf87a9af2,0x183d760a } }, + /* 108 */ + { { 0x0dde59a4,0x29d69711,0x0e8bef87,0xf1ad8d07,0x4f2ebe78,0x229b4963, + 0xc269d754,0x1d44179d }, + { 0x8390d30e,0xb32dc0cf,0x0de8110c,0x0a3b2753,0x2bc0339a,0x31af1dc5, + 0x9606d262,0x771f9cc2 } }, + /* 109 */ + { { 0x85040739,0x99993e77,0x8026a939,0x44539db9,0xf5f8fc26,0xcf40f6f2, + 0x0362718e,0x64427a31 }, + { 0x85428aa8,0x4f4f2d87,0xebfb49a8,0x7b7adc3f,0xf23d01ac,0x201b2c6d, + 0x6ae90d6d,0x49d9b749 } }, + /* 110 */ + { { 0x435d1099,0xcc78d8bc,0x8e8d1a08,0x2adbcd4e,0x2cb68a41,0x02c2e2a0, + 0x3f605445,0x9037d81b }, + { 0x074c7b61,0x7cdbac27,0x57bfd72e,0xfe2031ab,0x596d5352,0x61ccec96, + 0x7cc0639c,0x08c3de6a } }, + /* 111 */ + { { 0xf6d552ab,0x20fdd020,0x05cd81f1,0x56baff98,0x91351291,0x06fb7c3e, + 0x45796b2f,0xc6909442 }, + { 0x41231bd1,0x17b3ae9c,0x5cc58205,0x1eac6e87,0xf9d6a122,0x208837ab, + 0xcafe3ac0,0x3fa3db02 } }, + /* 112 */ + { { 0x05058880,0xd75a3e65,0x643943f2,0x7da365ef,0xfab24925,0x4147861c, + 0xfdb808ff,0xc5c4bdb0 }, + { 0xb272b56b,0x73513e34,0x11b9043a,0xc8327e95,0xf8844969,0xfd8ce37d, + 0x46c2b6b5,0x2d56db94 } }, + /* 113 */ + { { 0xff46ac6b,0x2461782f,0x07a2e425,0xd19f7926,0x09a48de1,0xfafea3c4, + 0xe503ba42,0x0f56bd9d }, + { 0x345cda49,0x137d4ed1,0x816f299d,0x821158fc,0xaeb43402,0xe7c6a54a, + 0x1173b5f1,0x4003bb9d } }, + /* 114 */ + { { 0xa0803387,0x3b8e8189,0x39cbd404,0xece115f5,0xd2877f21,0x4297208d, + 0xa07f2f9e,0x53765522 }, + { 0xa8a4182d,0xa4980a21,0x3219df79,0xa2bbd07a,0x1a19a2d4,0x674d0a2e, + 0x6c5d4549,0x7a056f58 } }, + /* 115 */ + { { 0x9d8a2a47,0x646b2558,0xc3df2773,0x5b582948,0xabf0d539,0x51ec000e, + 0x7a1a2675,0x77d482f1 }, + { 0x87853948,0xb8a1bd95,0x6cfbffee,0xa6f817bd,0x80681e47,0xab6ec057, + 0x2b38b0e4,0x4115012b } }, + /* 116 */ + { { 0x6de28ced,0x3c73f0f4,0x9b13ec47,0x1d5da760,0x6e5c6392,0x61b8ce9e, + 0xfbea0946,0xcdf04572 }, + { 0x6c53c3b0,0x1cb3c58b,0x447b843c,0x97fe3c10,0x2cb9780e,0xfb2b8ae1, + 0x97383109,0xee703dda } }, + /* 117 */ + { { 0xff57e43a,0x34515140,0xb1b811b8,0xd44660d3,0x8f42b986,0x2b3b5dff, + 0xa162ce21,0x2a0ad89d }, + { 0x6bc277ba,0x64e4a694,0xc141c276,0xc788c954,0xcabf6274,0x141aa64c, + 0xac2b4659,0xd62d0b67 } }, + /* 118 */ + { { 0x2c054ac4,0x39c5d87b,0xf27df788,0x57005859,0xb18128d6,0xedf7cbf3, + 0x991c2426,0xb39a23f2 }, + { 0xf0b16ae5,0x95284a15,0xa136f51b,0x0c6a05b1,0xf2700783,0x1d63c137, + 0xc0674cc5,0x04ed0092 } }, + /* 119 */ + { { 0x9ae90393,0x1f4185d1,0x4a3d64e6,0x3047b429,0x9854fc14,0xae0001a6, + 0x0177c387,0xa0a91fc1 }, + { 0xae2c831e,0xff0a3f01,0x2b727e16,0xbb76ae82,0x5a3075b4,0x8f12c8a1, + 0x9ed20c41,0x084cf988 } }, + /* 120 */ + { { 0xfca6becf,0xd98509de,0x7dffb328,0x2fceae80,0x4778e8b9,0x5d8a15c4, + 0x73abf77e,0xd57955b2 }, + { 0x31b5d4f1,0x210da79e,0x3cfa7a1c,0xaa52f04b,0xdc27c20b,0xd4d12089, + 0x02d141f1,0x8e14ea42 } }, + /* 121 */ + { { 0xf2897042,0xeed50345,0x43402c4a,0x8d05331f,0xc8bdfb21,0xc8d9c194, + 0x2aa4d158,0x597e1a37 }, + { 0xcf0bd68c,0x0327ec1a,0xab024945,0x6d4be0dc,0xc9fe3e84,0x5b9c8d7a, + 0x199b4dea,0xca3f0236 } }, + /* 122 */ + { { 0x6170bd20,0x592a10b5,0x6d3f5de7,0x0ea897f1,0x44b2ade2,0xa3363ff1, + 0x309c07e4,0xbde7fd7e }, + { 0xb8f5432c,0x516bb6d2,0xe043444b,0x210dc1cb,0xf8f95b5a,0x3db01e6f, + 0x0a7dd198,0xb623ad0e } }, + /* 123 */ + { { 0x60c7b65b,0xa75bd675,0x23a4a289,0xab8c5590,0xd7b26795,0xf8220fd0, + 0x58ec137b,0xd6aa2e46 }, + { 0x5138bb85,0x10abc00b,0xd833a95c,0x8c31d121,0x1702a32e,0xb24ff00b, + 0x2dcc513a,0x111662e0 } }, + /* 124 */ + { { 0xefb42b87,0x78114015,0x1b6c4dff,0xbd9f5d70,0xa7d7c129,0x66ecccd7, + 0x94b750f8,0xdb3ee1cb }, + { 0xf34837cf,0xb26f3db0,0xb9578d4f,0xe7eed18b,0x7c56657d,0x5d2cdf93, + 0x52206a59,0x886a6442 } }, + /* 125 */ + { { 0x65b569ea,0x3c234cfb,0xf72119c1,0x20011141,0xa15a619e,0x8badc85d, + 0x018a17bc,0xa70cf4eb }, + { 0x8c4a6a65,0x224f97ae,0x0134378f,0x36e5cf27,0x4f7e0960,0xbe3a609e, + 0xd1747b77,0xaa4772ab } }, + /* 126 */ + { { 0x7aa60cc0,0x67676131,0x0368115f,0xc7916361,0xbbc1bb5a,0xded98bb4, + 0x30faf974,0x611a6ddc }, + { 0xc15ee47a,0x30e78cbc,0x4e0d96a5,0x2e896282,0x3dd9ed88,0x36f35adf, + 0x16429c88,0x5cfffaf8 } }, + /* 127 */ + { { 0x9b7a99cd,0xc0d54cff,0x843c45a1,0x7bf3b99d,0x62c739e1,0x038a908f, + 0x7dc1994c,0x6e5a6b23 }, + { 0x0ba5db77,0xef8b454e,0xacf60d63,0xb7b8807f,0x76608378,0xe591c0c6, + 0x242dabcc,0x481a238d } }, + /* 128 */ + { { 0x35d0b34a,0xe3417bc0,0x8327c0a7,0x440b386b,0xac0362d1,0x8fb7262d, + 0xe0cdf943,0x2c41114c }, + { 0xad95a0b1,0x2ba5cef1,0x67d54362,0xc09b37a8,0x01e486c9,0x26d6cdd2, + 0x42ff9297,0x20477abf } }, + /* 129 */ + { { 0x18d65dbf,0x2f75173c,0x339edad8,0x77bf940e,0xdcf1001c,0x7022d26b, + 0xc77396b6,0xac66409a }, + { 0xc6261cc3,0x8b0bb36f,0x190e7e90,0x213f7bc9,0xa45e6c10,0x6541ceba, + 0xcc122f85,0xce8e6975 } }, + /* 130 */ + { { 0xbc0a67d2,0x0f121b41,0x444d248a,0x62d4760a,0x659b4737,0x0e044f1d, + 0x250bb4a8,0x08fde365 }, + { 0x848bf287,0xaceec3da,0xd3369d6e,0xc2a62182,0x92449482,0x3582dfdc, + 0x565d6cd7,0x2f7e2fd2 } }, + /* 131 */ + { { 0xc3770fa7,0xae4b92db,0x379043f9,0x095e8d5c,0x17761171,0x54f34e9d, + 0x907702ae,0xc65be92e }, + { 0xf6fd0a40,0x2758a303,0xbcce784b,0xe7d822e3,0x4f9767bf,0x7ae4f585, + 0xd1193b3a,0x4bff8e47 } }, + /* 132 */ + { { 0x00ff1480,0xcd41d21f,0x0754db16,0x2ab8fb7d,0xbbe0f3ea,0xac81d2ef, + 0x5772967d,0x3e4e4ae6 }, + { 0x3c5303e6,0x7e18f36d,0x92262397,0x3bd9994b,0x1324c3c0,0x9ed70e26, + 0x58ec6028,0x5388aefd } }, + /* 133 */ + { { 0x5e5d7713,0xad1317eb,0x75de49da,0x09b985ee,0xc74fb261,0x32f5bc4f, + 0x4f75be0e,0x5cf908d1 }, + { 0x8e657b12,0x76043510,0xb96ed9e6,0xbfd421a5,0x8970ccc2,0x0e29f51f, + 0x60f00ce2,0xa698ba40 } }, + /* 134 */ + { { 0xef748fec,0x73db1686,0x7e9d2cf9,0xe6e755a2,0xce265eff,0x630b6544, + 0x7aebad8d,0xb142ef8a }, + { 0x17d5770a,0xad31af9f,0x2cb3412f,0x66af3b67,0xdf3359de,0x6bd60d1b, + 0x58515075,0xd1896a96 } }, + /* 135 */ + { { 0x33c41c08,0xec5957ab,0x5468e2e1,0x87de94ac,0xac472f6c,0x18816b73, + 0x7981da39,0x267b0e0b }, + { 0x8e62b988,0x6e554e5d,0x116d21e7,0xd8ddc755,0x3d2a6f99,0x4610faf0, + 0xa1119393,0xb54e287a } }, + /* 136 */ + { { 0x178a876b,0x0a0122b5,0x085104b4,0x51ff96ff,0x14f29f76,0x050b31ab, + 0x5f87d4e6,0x84abb28b }, + { 0x8270790a,0xd5ed439f,0x85e3f46b,0x2d6cb59d,0x6c1e2212,0x75f55c1b, + 0x17655640,0xe5436f67 } }, + /* 137 */ + { { 0x2286e8d5,0x53f9025e,0x864453be,0x353c95b4,0xe408e3a0,0xd832f5bd, + 0x5b9ce99e,0x0404f68b }, + { 0xa781e8e5,0xcad33bde,0x163c2f5b,0x3cdf5018,0x0119caa3,0x57576960, + 0x0ac1c701,0x3a4263df } }, + /* 138 */ + { { 0x9aeb596d,0xc2965ecc,0x023c92b4,0x01ea03e7,0x2e013961,0x4704b4b6, + 0x905ea367,0x0ca8fd3f }, + { 0x551b2b61,0x92523a42,0x390fcd06,0x1eb7a89c,0x0392a63e,0xe7f1d2be, + 0x4ddb0c33,0x96dca264 } }, + /* 139 */ + { { 0x387510af,0x203bb43a,0xa9a36a01,0x846feaa8,0x2f950378,0xd23a5770, + 0x3aad59dc,0x4363e212 }, + { 0x40246a47,0xca43a1c7,0xe55dd24d,0xb362b8d2,0x5d8faf96,0xf9b08604, + 0xd8bb98c4,0x840e115c } }, + /* 140 */ + { { 0x1023e8a7,0xf12205e2,0xd8dc7a0b,0xc808a8cd,0x163a5ddf,0xe292a272, + 0x30ded6d4,0x5e0d6abd }, + { 0x7cfc0f64,0x07a721c2,0x0e55ed88,0x42eec01d,0x1d1f9db2,0x26a7bef9, + 0x2945a25a,0x7dea48f4 } }, + /* 141 */ + { { 0xe5060a81,0xabdf6f1c,0xf8f95615,0xe79f9c72,0x06ac268b,0xcfd36c54, + 0xebfd16d1,0xabc2a2be }, + { 0xd3e2eac7,0x8ac66f91,0xd2dd0466,0x6f10ba63,0x0282d31b,0x6790e377, + 0x6c7eefc1,0x4ea35394 } }, + /* 142 */ + { { 0x5266309d,0xed8a2f8d,0x81945a3e,0x0a51c6c0,0x578c5dc1,0xcecaf45a, + 0x1c94ffc3,0x3a76e689 }, + { 0x7d7b0d0f,0x9aace8a4,0x8f584a5f,0x963ace96,0x4e697fbe,0x51a30c72, + 0x465e6464,0x8212a10a } }, + /* 143 */ + { { 0xcfab8caa,0xef7c61c3,0x0e142390,0x18eb8e84,0x7e9733ca,0xcd1dff67, + 0x599cb164,0xaa7cab71 }, + { 0xbc837bd1,0x02fc9273,0xc36af5d7,0xc06407d0,0xf423da49,0x17621292, + 0xfe0617c3,0x40e38073 } }, + /* 144 */ + { { 0xa7bf9b7c,0xf4f80824,0x3fbe30d0,0x365d2320,0x97cf9ce3,0xbfbe5320, + 0xb3055526,0xe3604700 }, + { 0x6cc6c2c7,0x4dcb9911,0xba4cbee6,0x72683708,0x637ad9ec,0xdcded434, + 0xa3dee15f,0x6542d677 } }, + /* 145 */ + { { 0x7b6c377a,0x3f32b6d0,0x903448be,0x6cb03847,0x20da8af7,0xd6fdd3a8, + 0x09bb6f21,0xa6534aee }, + { 0x1035facf,0x30a1780d,0x9dcb47e6,0x35e55a33,0xc447f393,0x6ea50fe1, + 0xdc9aef22,0xf3cb672f } }, + /* 146 */ + { { 0x3b55fd83,0xeb3719fe,0x875ddd10,0xe0d7a46c,0x05cea784,0x33ac9fa9, + 0xaae870e7,0x7cafaa2e }, + { 0x1d53b338,0x9b814d04,0xef87e6c6,0xe0acc0a0,0x11672b0f,0xfb93d108, + 0xb9bd522e,0x0aab13c1 } }, + /* 147 */ + { { 0xd2681297,0xddcce278,0xb509546a,0xcb350eb1,0x7661aaf2,0x2dc43173, + 0x847012e9,0x4b91a602 }, + { 0x72f8ddcf,0xdcff1095,0x9a911af4,0x08ebf61e,0xc372430e,0x48f4360a, + 0x72321cab,0x49534c53 } }, + /* 148 */ + { { 0xf07b7e9d,0x83df7d71,0x13cd516f,0xa478efa3,0x6c047ee3,0x78ef264b, + 0xd65ac5ee,0xcaf46c4f }, + { 0x92aa8266,0xa04d0c77,0x913684bb,0xedf45466,0xae4b16b0,0x56e65168, + 0x04c6770f,0x14ce9e57 } }, + /* 149 */ + { { 0x965e8f91,0x99445e3e,0xcb0f2492,0xd3aca1ba,0x90c8a0a0,0xd31cc70f, + 0x3e4c9a71,0x1bb708a5 }, + { 0x558bdd7a,0xd5ca9e69,0x018a26b1,0x734a0508,0x4c9cf1ec,0xb093aa71, + 0xda300102,0xf9d126f2 } }, + /* 150 */ + { { 0xaff9563e,0x749bca7a,0xb49914a0,0xdd077afe,0xbf5f1671,0xe27a0311, + 0x729ecc69,0x807afcb9 }, + { 0xc9b08b77,0x7f8a9337,0x443c7e38,0x86c3a785,0x476fd8ba,0x85fafa59, + 0x6568cd8c,0x751adcd1 } }, + /* 151 */ + { { 0x10715c0d,0x8aea38b4,0x8f7697f7,0xd113ea71,0x93fbf06d,0x665eab14, + 0x2537743f,0x29ec4468 }, + { 0xb50bebbc,0x3d94719c,0xe4505422,0x399ee5bf,0x8d2dedb1,0x90cd5b3a, + 0x92a4077d,0xff9370e3 } }, + /* 152 */ + { { 0xc6b75b65,0x59a2d69b,0x266651c5,0x4188f8d5,0x3de9d7d2,0x28a9f33e, + 0xa2a9d01a,0x9776478b }, + { 0x929af2c7,0x8852622d,0x4e690923,0x334f5d6d,0xa89a51e9,0xce6cc7e5, + 0xac2f82fa,0x74a6313f } }, + /* 153 */ + { { 0xb75f079c,0xb2f4dfdd,0x18e36fbb,0x85b07c95,0xe7cd36dd,0x1b6cfcf0, + 0x0ff4863d,0xab75be15 }, + { 0x173fc9b7,0x81b367c0,0xd2594fd0,0xb90a7420,0xc4091236,0x15fdbf03, + 0x0b4459f6,0x4ebeac2e } }, + /* 154 */ + { { 0x5c9f2c53,0xeb6c5fe7,0x8eae9411,0xd2522011,0xf95ac5d8,0xc8887633, + 0x2c1baffc,0xdf99887b }, + { 0x850aaecb,0xbb78eed2,0x01d6a272,0x9d49181b,0xb1cdbcac,0x978dd511, + 0x779f4058,0x27b040a7 } }, + /* 155 */ + { { 0xf73b2eb2,0x90405db7,0x8e1b2118,0xe0df8508,0x5962327e,0x501b7152, + 0xe4cfa3f5,0xb393dd37 }, + { 0x3fd75165,0xa1230e7b,0xbcd33554,0xd66344c2,0x0f7b5022,0x6c36f1be, + 0xd0463419,0x09588c12 } }, + /* 156 */ + { { 0x02601c3b,0xe086093f,0xcf5c335f,0xfb0252f8,0x894aff28,0x955cf280, + 0xdb9f648b,0x81c879a9 }, + { 0xc6f56c51,0x040e687c,0x3f17618c,0xfed47169,0x9059353b,0x44f88a41, + 0x5fc11bc4,0xfa0d48f5 } }, + /* 157 */ + { { 0xe1608e4d,0xbc6e1c9d,0x3582822c,0x010dda11,0x157ec2d7,0xf6b7ddc1, + 0xb6a367d6,0x8ea0e156 }, + { 0x2383b3b4,0xa354e02f,0x3f01f53c,0x69966b94,0x2de03ca5,0x4ff6632b, + 0xfa00b5ac,0x3f5ab924 } }, + /* 158 */ + { { 0x59739efb,0x337bb0d9,0xe7ebec0d,0xc751b0f4,0x411a67d1,0x2da52dd6, + 0x2b74256e,0x8bc76887 }, + { 0x82d3d253,0xa5be3b72,0xf58d779f,0xa9f679a1,0xe16767bb,0xa1cac168, + 0x60fcf34f,0xb386f190 } }, + /* 159 */ + { { 0x2fedcfc2,0x31f3c135,0x62f8af0d,0x5396bf62,0xe57288c2,0x9a02b4ea, + 0x1b069c4d,0x4cb460f7 }, + { 0x5b8095ea,0xae67b4d3,0x6fc07603,0x92bbf859,0xb614a165,0xe1475f66, + 0x95ef5223,0x52c0d508 } }, + /* 160 */ + { { 0x15339848,0x231c210e,0x70778c8d,0xe87a28e8,0x6956e170,0x9d1de661, + 0x2bb09c0b,0x4ac3c938 }, + { 0x6998987d,0x19be0551,0xae09f4d6,0x8b2376c4,0x1a3f933d,0x1de0b765, + 0xe39705f4,0x380d94c7 } }, + /* 161 */ + { { 0x81542e75,0x01a355aa,0xee01b9b7,0x96c724a1,0x624d7087,0x6b3a2977, + 0xde2637af,0x2ce3e171 }, + { 0xf5d5bc1a,0xcfefeb49,0x2777e2b5,0xa655607e,0x9513756c,0x4feaac2f, + 0x0b624e4d,0x2e6cd852 } }, + /* 162 */ + { { 0x8c31c31d,0x3685954b,0x5bf21a0c,0x68533d00,0x75c79ec9,0x0bd7626e, + 0x42c69d54,0xca177547 }, + { 0xf6d2dbb2,0xcc6edaff,0x174a9d18,0xfd0d8cbd,0xaa4578e8,0x875e8793, + 0x9cab2ce6,0xa976a713 } }, + /* 163 */ + { { 0x93fb353d,0x0a651f1b,0x57fcfa72,0xd75cab8b,0x31b15281,0xaa88cfa7, + 0x0a1f4999,0x8720a717 }, + { 0x693e1b90,0x8c3e8d37,0x16f6dfc3,0xd345dc0b,0xb52a8742,0x8ea8d00a, + 0xc769893c,0x9719ef29 } }, + /* 164 */ + { { 0x58e35909,0x820eed8d,0x33ddc116,0x9366d8dc,0x6e205026,0xd7f999d0, + 0xe15704c1,0xa5072976 }, + { 0xc4e70b2e,0x002a37ea,0x6890aa8a,0x84dcf657,0x645b2a5c,0xcd71bf18, + 0xf7b77725,0x99389c9d } }, + /* 165 */ + { { 0x7ada7a4b,0x238c08f2,0xfd389366,0x3abe9d03,0x766f512c,0x6b672e89, + 0x202c82e4,0xa88806aa }, + { 0xd380184e,0x6602044a,0x126a8b85,0xa8cb78c4,0xad844f17,0x79d670c0, + 0x4738dcfe,0x0043bffb } }, + /* 166 */ + { { 0x36d5192e,0x8d59b5dc,0x4590b2af,0xacf885d3,0x11601781,0x83566d0a, + 0xba6c4866,0x52f3ef01 }, + { 0x0edcb64d,0x3986732a,0x8068379f,0x0a482c23,0x7040f309,0x16cbe5fa, + 0x9ef27e75,0x3296bd89 } }, + /* 167 */ + { { 0x454d81d7,0x476aba89,0x51eb9b3c,0x9eade7ef,0x81c57986,0x619a21cd, + 0xaee571e9,0x3b90febf }, + { 0x5496f7cb,0x9393023e,0x7fb51bc4,0x55be41d8,0x99beb5ce,0x03f1dd48, + 0x9f810b18,0x6e88069d } }, + /* 168 */ + { { 0xb43ea1db,0xce37ab11,0x5259d292,0x0a7ff1a9,0x8f84f186,0x851b0221, + 0xdefaad13,0xa7222bea }, + { 0x2b0a9144,0xa2ac78ec,0xf2fa59c5,0x5a024051,0x6147ce38,0x91d1eca5, + 0xbc2ac690,0xbe94d523 } }, + /* 169 */ + { { 0x0b226ce7,0x72f4945e,0x967e8b70,0xb8afd747,0x85a6c63e,0xedea46f1, + 0x9be8c766,0x7782defe }, + { 0x3db38626,0x760d2aa4,0x76f67ad1,0x460ae787,0x54499cdb,0x341b86fc, + 0xa2892e4b,0x03838567 } }, + /* 170 */ + { { 0x79ec1a0f,0x2d8daefd,0xceb39c97,0x3bbcd6fd,0x58f61a95,0xf5575ffc, + 0xadf7b420,0xdbd986c4 }, + { 0x15f39eb7,0x81aa8814,0xb98d976c,0x6ee2fcf5,0xcf2f717d,0x5465475d, + 0x6860bbd0,0x8e24d3c4 } }, + /* 171 */ + { { 0x9a587390,0x749d8e54,0x0cbec588,0x12bb194f,0xb25983c6,0x46e07da4, + 0x407bafc8,0x541a99c4 }, + { 0x624c8842,0xdb241692,0xd86c05ff,0x6044c12a,0x4f7fcf62,0xc59d14b4, + 0xf57d35d1,0xc0092c49 } }, + /* 172 */ + { { 0xdf2e61ef,0xd3cc75c3,0x2e1b35ca,0x7e8841c8,0x909f29f4,0xc62d30d1, + 0x7286944d,0x75e40634 }, + { 0xbbc237d0,0xe7d41fc5,0xec4f01c9,0xc9537bf0,0x282bd534,0x91c51a16, + 0xc7848586,0x5b7cb658 } }, + /* 173 */ + { { 0x8a28ead1,0x964a7084,0xfd3b47f6,0x802dc508,0x767e5b39,0x9ae4bfd1, + 0x8df097a1,0x7ae13eba }, + { 0xeadd384e,0xfd216ef8,0xb6b2ff06,0x0361a2d9,0x4bcdb5f3,0x204b9878, + 0xe2a8e3fd,0x787d8074 } }, + /* 174 */ + { { 0x757fbb1c,0xc5e25d6b,0xca201deb,0xe47bddb2,0x6d2233ff,0x4a55e9a3, + 0x9ef28484,0x5c222819 }, + { 0x88315250,0x773d4a85,0x827097c1,0x21b21a2b,0xdef5d33f,0xab7c4ea1, + 0xbaf0f2b0,0xe45d37ab } }, + /* 175 */ + { { 0x28511c8a,0xd2df1e34,0xbdca6cd3,0xebb229c8,0x627c39a7,0x578a71a7, + 0x84dfb9d3,0xed7bc122 }, + { 0x93dea561,0xcf22a6df,0xd48f0ed1,0x5443f18d,0x5bad23e8,0xd8b86140, + 0x45ca6d27,0xaac97cc9 } }, + /* 176 */ + { { 0xa16bd00a,0xeb54ea74,0xf5c0bcc1,0xd839e9ad,0x1f9bfc06,0x092bb7f1, + 0x1163dc4e,0x318f97b3 }, + { 0xc30d7138,0xecc0c5be,0xabc30220,0x44e8df23,0xb0223606,0x2bb7972f, + 0x9a84ff4d,0xfa41faa1 } }, + /* 177 */ + { { 0xa6642269,0x4402d974,0x9bb783bd,0xc81814ce,0x7941e60b,0x398d38e4, + 0x1d26e9e2,0x38bb6b2c }, + { 0x6a577f87,0xc64e4a25,0xdc11fe1c,0x8b52d253,0x62280728,0xff336abf, + 0xce7601a5,0x94dd0905 } }, + /* 178 */ + { { 0xde93f92a,0x156cf7dc,0x89b5f315,0xa01333cb,0xc995e750,0x02404df9, + 0xd25c2ae9,0x92077867 }, + { 0x0bf39d44,0xe2471e01,0x96bb53d7,0x5f2c9020,0x5c9c3d8f,0x4c44b7b3, + 0xd29beb51,0x81e8428b } }, + /* 179 */ + { { 0xc477199f,0x6dd9c2ba,0x6b5ecdd9,0x8cb8eeee,0xee40fd0e,0x8af7db3f, + 0xdbbfa4b1,0x1b94ab62 }, + { 0xce47f143,0x44f0d8b3,0x63f46163,0x51e623fc,0xcc599383,0xf18f270f, + 0x055590ee,0x06a38e28 } }, + /* 180 */ + { { 0xb3355b49,0x2e5b0139,0xb4ebf99b,0x20e26560,0xd269f3dc,0xc08ffa6b, + 0x83d9d4f8,0xa7b36c20 }, + { 0x1b3e8830,0x64d15c3a,0xa89f9c0b,0xd5fceae1,0xe2d16930,0xcfeee4a2, + 0xa2822a20,0xbe54c6b4 } }, + /* 181 */ + { { 0x8d91167c,0xd6cdb3df,0xe7a6625e,0x517c3f79,0x346ac7f4,0x7105648f, + 0xeae022bb,0xbf30a5ab }, + { 0x93828a68,0x8e7785be,0x7f3ef036,0x5161c332,0x592146b2,0xe11b5feb, + 0x2732d13a,0xd1c820de } }, + /* 182 */ + { { 0x9038b363,0x043e1347,0x6b05e519,0x58c11f54,0x6026cad1,0x4fe57abe, + 0x68a18da3,0xb7d17bed }, + { 0xe29c2559,0x44ca5891,0x5bfffd84,0x4f7a0376,0x74e46948,0x498de4af, + 0x6412cc64,0x3997fd5e } }, + /* 183 */ + { { 0x8bd61507,0xf2074682,0x34a64d2a,0x29e132d5,0x8a8a15e3,0xffeddfb0, + 0x3c6c13e8,0x0eeb8929 }, + { 0xa7e259f8,0xe9b69a3e,0xd13e7e67,0xce1db7e6,0xad1fa685,0x277318f6, + 0xc922b6ef,0x228916f8 } }, + /* 184 */ + { { 0x0a12ab5b,0x959ae25b,0x957bc136,0xcc11171f,0xd16e2b0c,0x8058429e, + 0x6e93097e,0xec05ad1d }, + { 0xac3f3708,0x157ba5be,0x30b59d77,0x31baf935,0x118234e5,0x47b55237, + 0x7ff11b37,0x7d314156 } }, + /* 185 */ + { { 0xf6dfefab,0x7bd9c05c,0xdcb37707,0xbe2f2268,0x3a38bb95,0xe53ead97, + 0x9bc1d7a3,0xe9ce66fc }, + { 0x6f6a02a1,0x75aa1576,0x60e600ed,0x38c087df,0x68cdc1b9,0xf8947f34, + 0x72280651,0xd9650b01 } }, + /* 186 */ + { { 0x5a057e60,0x504b4c4a,0x8def25e4,0xcbccc3be,0x17c1ccbd,0xa6353208, + 0x804eb7a2,0x14d6699a }, + { 0xdb1f411a,0x2c8a8415,0xf80d769c,0x09fbaf0b,0x1c2f77ad,0xb4deef90, + 0x0d43598a,0x6f4c6841 } }, + /* 187 */ + { { 0x96c24a96,0x8726df4e,0xfcbd99a3,0x534dbc85,0x8b2ae30a,0x3c466ef2, + 0x61189abb,0x4c4350fd }, + { 0xf855b8da,0x2967f716,0x463c38a1,0x41a42394,0xeae93343,0xc37e1413, + 0x5a3118b5,0xa726d242 } }, + /* 188 */ + { { 0x948c1086,0xdae6b3ee,0xcbd3a2e1,0xf1de503d,0x03d022f3,0x3f35ed3f, + 0xcc6cf392,0x13639e82 }, + { 0xcdafaa86,0x9ac938fb,0x2654a258,0xf45bc5fb,0x45051329,0x1963b26e, + 0xc1a335a3,0xca9365e1 } }, + /* 189 */ + { { 0x4c3b2d20,0x3615ac75,0x904e241b,0x742a5417,0xcc9d071d,0xb08521c4, + 0x970b72a5,0x9ce29c34 }, + { 0x6d3e0ad6,0x8cc81f73,0xf2f8434c,0x8060da9e,0x6ce862d9,0x35ed1d1a, + 0xab42af98,0x48c4abd7 } }, + /* 190 */ + { { 0x40c7485a,0xd221b0cc,0xe5274dbf,0xead455bb,0x9263d2e8,0x493c7698, + 0xf67b33cb,0x78017c32 }, + { 0x930cb5ee,0xb9d35769,0x0c408ed2,0xc0d14e94,0x272f1a4d,0xf8b7bf55, + 0xde5c1c04,0x53cd0454 } }, + /* 191 */ + { { 0x5d28ccac,0xbcd585fa,0x005b746e,0x5f823e56,0xcd0123aa,0x7c79f0a1, + 0xd3d7fa8f,0xeea465c1 }, + { 0x0551803b,0x7810659f,0x7ce6af70,0x6c0b599f,0x29288e70,0x4195a770, + 0x7ae69193,0x1b6e42a4 } }, + /* 192 */ + { { 0xf67d04c3,0x2e80937c,0x89eeb811,0x1e312be2,0x92594d60,0x56b5d887, + 0x187fbd3d,0x0224da14 }, + { 0x0c5fe36f,0x87abb863,0x4ef51f5f,0x580f3c60,0xb3b429ec,0x964fb1bf, + 0x42bfff33,0x60838ef0 } }, + /* 193 */ + { { 0x7e0bbe99,0x432cb2f2,0x04aa39ee,0x7bda44f3,0x9fa93903,0x5f497c7a, + 0x2d331643,0x636eb202 }, + { 0x93ae00aa,0xfcfd0e61,0x31ae6d2f,0x875a00fe,0x9f93901c,0xf43658a2, + 0x39218bac,0x8844eeb6 } }, + /* 194 */ + { { 0x6b3bae58,0x114171d2,0x17e39f3e,0x7db3df71,0x81a8eada,0xcd37bc7f, + 0x51fb789e,0x27ba83dc }, + { 0xfbf54de5,0xa7df439f,0xb5fe1a71,0x7277030b,0xdb297a48,0x42ee8e35, + 0x87f3a4ab,0xadb62d34 } }, + /* 195 */ + { { 0xa175df2a,0x9b1168a2,0x618c32e9,0x082aa04f,0x146b0916,0xc9e4f2e7, + 0x75e7c8b2,0xb990fd76 }, + { 0x4df37313,0x0829d96b,0xd0b40789,0x1c205579,0x78087711,0x66c9ae4a, + 0x4d10d18d,0x81707ef9 } }, + /* 196 */ + { { 0x03d6ff96,0x97d7cab2,0x0d843360,0x5b851bfc,0xd042db4b,0x268823c4, + 0xd5a8aa5c,0x3792daea }, + { 0x941afa0b,0x52818865,0x42d83671,0xf3e9e741,0x5be4e0a7,0x17c82527, + 0x94b001ba,0x5abd635e } }, + /* 197 */ + { { 0x0ac4927c,0x727fa84e,0xa7c8cf23,0xe3886035,0x4adca0df,0xa4bcd5ea, + 0x846ab610,0x5995bf21 }, + { 0x829dfa33,0xe90f860b,0x958fc18b,0xcaafe2ae,0x78630366,0x9b3baf44, + 0xd483411e,0x44c32ca2 } }, + /* 198 */ + { { 0xe40ed80c,0xa74a97f1,0x31d2ca82,0x5f938cb1,0x7c2d6ad9,0x53f2124b, + 0x8082a54c,0x1f2162fb }, + { 0x720b173e,0x7e467cc5,0x085f12f9,0x40e8a666,0x4c9d65dc,0x8cebc20e, + 0xc3e907c9,0x8f1d402b } }, + /* 199 */ + { { 0xfbc4058a,0x4f592f9c,0x292f5670,0xb15e14b6,0xbc1d8c57,0xc55cfe37, + 0x926edbf9,0xb1980f43 }, + { 0x32c76b09,0x98c33e09,0x33b07f78,0x1df5279d,0x863bb461,0x6f08ead4, + 0x37448e45,0x2828ad9b } }, + /* 200 */ + { { 0xc4cf4ac5,0x696722c4,0xdde64afb,0xf5ac1a3f,0xe0890832,0x0551baa2, + 0x5a14b390,0x4973f127 }, + { 0x322eac5d,0xe59d8335,0x0bd9b568,0x5e07eef5,0xa2588393,0xab36720f, + 0xdb168ac7,0x6dac8ed0 } }, + /* 201 */ + { { 0xeda835ef,0xf7b545ae,0x1d10ed51,0x4aa113d2,0x13741b09,0x035a65e0, + 0x20b9de4c,0x4b23ef59 }, + { 0x3c4c7341,0xe82bb680,0x3f58bc37,0xd457706d,0xa51e3ee8,0x73527863, + 0xddf49a4e,0x4dd71534 } }, + /* 202 */ + { { 0x95476cd9,0xbf944672,0xe31a725b,0x648d072f,0xfc4b67e0,0x1441c8b8, + 0x2f4a4dbb,0xfd317000 }, + { 0x8995d0e1,0x1cb43ff4,0x0ef729aa,0x76e695d1,0x41798982,0xe0d5f976, + 0x9569f365,0x14fac58c } }, + /* 203 */ + { { 0xf312ae18,0xad9a0065,0xfcc93fc9,0x51958dc0,0x8a7d2846,0xd9a14240, + 0x36abda50,0xed7c7651 }, + { 0x25d4abbc,0x46270f1a,0xf1a113ea,0x9b5dd8f3,0x5b51952f,0xc609b075, + 0x4d2e9f53,0xfefcb7f7 } }, + /* 204 */ + { { 0xba119185,0xbd09497a,0xaac45ba4,0xd54e8c30,0xaa521179,0x492479de, + 0x87e0d80b,0x1801a57e }, + { 0xfcafffb0,0x073d3f8d,0xae255240,0x6cf33c0b,0x5b5fdfbc,0x781d763b, + 0x1ead1064,0x9f8fc11e } }, + /* 205 */ + { { 0x5e69544c,0x1583a171,0xf04b7813,0x0eaf8567,0x278a4c32,0x1e22a8fd, + 0x3d3a69a9,0xa9d3809d }, + { 0x59a2da3b,0x936c2c2c,0x1895c847,0x38ccbcf6,0x63d50869,0x5e65244e, + 0xe1178ef7,0x3006b9ae } }, + /* 206 */ + { { 0xc9eead28,0x0bb1f2b0,0x89f4dfbc,0x7eef635d,0xb2ce8939,0x074757fd, + 0x45f8f761,0x0ab85fd7 }, + { 0x3e5b4549,0xecda7c93,0x97922f21,0x4be2bb5c,0xb43b8040,0x261a1274, + 0x11e942c2,0xb122d675 } }, + /* 207 */ + { { 0x66a5ae7a,0x3be607be,0x76adcbe3,0x01e703fa,0x4eb6e5c5,0xaf904301, + 0x097dbaec,0x9f599dc1 }, + { 0x0ff250ed,0x6d75b718,0x349a20dc,0x8eb91574,0x10b227a3,0x425605a4, + 0x8a294b78,0x7d5528e0 } }, + /* 208 */ + { { 0x20c26def,0xf0f58f66,0x582b2d1e,0x025585ea,0x01ce3881,0xfbe7d79b, + 0x303f1730,0x28ccea01 }, + { 0x79644ba5,0xd1dabcd1,0x06fff0b8,0x1fc643e8,0x66b3e17b,0xa60a76fc, + 0xa1d013bf,0xc18baf48 } }, + /* 209 */ + { { 0x5dc4216d,0x34e638c8,0x206142ac,0x00c01067,0x95f5064a,0xd453a171, + 0xb7a9596b,0x9def809d }, + { 0x67ab8d2c,0x41e8642e,0x6237a2b6,0xb4240433,0x64c4218b,0x7d506a6d, + 0x68808ce5,0x0357f8b0 } }, + /* 210 */ + { { 0x4cd2cc88,0x8e9dbe64,0xf0b8f39d,0xcc61c28d,0xcd30a0c8,0x4a309874, + 0x1b489887,0xe4a01add }, + { 0xf57cd8f9,0x2ed1eeac,0xbd594c48,0x1b767d3e,0x7bd2f787,0xa7295c71, + 0xce10cc30,0x466d7d79 } }, + /* 211 */ + { { 0x9dada2c7,0x47d31892,0x8f9aa27d,0x4fa0a6c3,0x820a59e1,0x90e4fd28, + 0x451ead1a,0xc672a522 }, + { 0x5d86b655,0x30607cc8,0xf9ad4af1,0xf0235d3b,0x571172a6,0x99a08680, + 0xf2a67513,0x5e3d64fa } }, + /* 212 */ + { { 0x9b3b4416,0xaa6410c7,0xeab26d99,0xcd8fcf85,0xdb656a74,0x5ebff74a, + 0xeb8e42fc,0x6c8a7a95 }, + { 0xb02a63bd,0x10c60ba7,0x8b8f0047,0x6b2f2303,0x312d90b0,0x8c6c3738, + 0xad82ca91,0x348ae422 } }, + /* 213 */ + { { 0x5ccda2fb,0x7f474663,0x8e0726d2,0x22accaa1,0x492b1f20,0x85adf782, + 0xd9ef2d2e,0xc1074de0 }, + { 0xae9a65b3,0xfcf3ce44,0x05d7151b,0xfd71e4ac,0xce6a9788,0xd4711f50, + 0xc9e54ffc,0xfbadfbdb } }, + /* 214 */ + { { 0x20a99363,0x1713f1cd,0x6cf22775,0xb915658f,0x24d359b2,0x968175cd, + 0x83716fcd,0xb7f976b4 }, + { 0x5d6dbf74,0x5758e24d,0x71c3af36,0x8d23bafd,0x0243dfe3,0x48f47760, + 0xcafcc805,0xf4d41b2e } }, + /* 215 */ + { { 0xfdabd48d,0x51f1cf28,0x32c078a4,0xce81be36,0x117146e9,0x6ace2974, + 0xe0160f10,0x180824ea }, + { 0x66e58358,0x0387698b,0xce6ca358,0x63568752,0x5e41e6c5,0x82380e34, + 0x83cf6d25,0x67e5f639 } }, + /* 216 */ + { { 0xcf4899ef,0xf89ccb8d,0x9ebb44c0,0x949015f0,0xb2598ec9,0x546f9276, + 0x04c11fc6,0x9fef789a }, + { 0x53d2a071,0x6d367ecf,0xa4519b09,0xb10e1a7f,0x611e2eef,0xca6b3fb0, + 0xa99c4e20,0xbc80c181 } }, + /* 217 */ + { { 0xe5eb82e6,0x972536f8,0xf56cb920,0x1a484fc7,0x50b5da5e,0xc78e2171, + 0x9f8cdf10,0x49270e62 }, + { 0xea6b50ad,0x1a39b7bb,0xa2388ffc,0x9a0284c1,0x8107197b,0x5403eb17, + 0x61372f7f,0xd2ee52f9 } }, + /* 218 */ + { { 0x88e0362a,0xd37cd285,0x8fa5d94d,0x442fa8a7,0xa434a526,0xaff836e5, + 0xe5abb733,0xdfb478be }, + { 0x673eede6,0xa91f1ce7,0x2b5b2f04,0xa5390ad4,0x5530da2f,0x5e66f7bf, + 0x08df473a,0xd9a140b4 } }, + /* 219 */ + { { 0x6e8ea498,0x0e0221b5,0x3563ee09,0x62347829,0x335d2ade,0xe06b8391, + 0x623f4b1a,0x760c058d }, + { 0xc198aa79,0x0b89b58c,0xf07aba7f,0xf74890d2,0xfde2556a,0x4e204110, + 0x8f190409,0x7141982d } }, + /* 220 */ + { { 0x4d4b0f45,0x6f0a0e33,0x392a94e1,0xd9280b38,0xb3c61d5e,0x3af324c6, + 0x89d54e47,0x3af9d1ce }, + { 0x20930371,0xfd8f7981,0x21c17097,0xeda2664c,0xdc42309b,0x0e9545dc, + 0x73957dd6,0xb1f815c3 } }, + /* 221 */ + { { 0x89fec44a,0x84faa78e,0x3caa4caf,0xc8c2ae47,0xc1b6a624,0x691c807d, + 0x1543f052,0xa41aed14 }, + { 0x7d5ffe04,0x42435399,0x625b6e20,0x8bacb2df,0x87817775,0x85d660be, + 0x86fb60ef,0xd6e9c1dd } }, + /* 222 */ + { { 0xc6853264,0x3aa2e97e,0xe2304a0b,0x771533b7,0xb8eae9be,0x1b912bb7, + 0xae9bf8c2,0x9c9c6e10 }, + { 0xe030b74c,0xa2309a59,0x6a631e90,0x4ed7494d,0xa49b79f2,0x89f44b23, + 0x40fa61b6,0x566bd596 } }, + /* 223 */ + { { 0xc18061f3,0x066c0118,0x7c83fc70,0x190b25d3,0x27273245,0xf05fc8e0, + 0xf525345e,0xcf2c7390 }, + { 0x10eb30cf,0xa09bceb4,0x0d77703a,0xcfd2ebba,0x150ff255,0xe842c43a, + 0x8aa20979,0x02f51755 } }, + /* 224 */ + { { 0xaddb7d07,0x396ef794,0x24455500,0x0b4fc742,0xc78aa3ce,0xfaff8eac, + 0xe8d4d97d,0x14e9ada5 }, + { 0x2f7079e2,0xdaa480a1,0xe4b0800e,0x45baa3cd,0x7838157d,0x01765e2d, + 0x8e9d9ae8,0xa0ad4fab } }, + /* 225 */ + { { 0x4a653618,0x0bfb7621,0x31eaaa5f,0x1872813c,0x44949d5e,0x1553e737, + 0x6e56ed1e,0xbcd530b8 }, + { 0x32e9c47b,0x169be853,0xb50059ab,0xdc2776fe,0x192bfbb4,0xcdba9761, + 0x6979341d,0x909283cf } }, + /* 226 */ + { { 0x76e81a13,0x67b00324,0x62171239,0x9bee1a99,0xd32e19d6,0x08ed361b, + 0xace1549a,0x35eeb7c9 }, + { 0x7e4e5bdc,0x1280ae5a,0xb6ceec6e,0x2dcd2cd3,0x6e266bc1,0x52e4224c, + 0x448ae864,0x9a8b2cf4 } }, + /* 227 */ + { { 0x09d03b59,0xf6471bf2,0xb65af2ab,0xc90e62a3,0xebd5eec9,0xff7ff168, + 0xd4491379,0x6bdb60f4 }, + { 0x8a55bc30,0xdadafebc,0x10097fe0,0xc79ead16,0x4c1e3bdd,0x42e19741, + 0x94ba08a9,0x01ec3cfd } }, + /* 228 */ + { { 0xdc9485c2,0xba6277eb,0x22fb10c7,0x48cc9a79,0x70a28d8a,0x4f61d60f, + 0x475464f6,0xd1acb1c0 }, + { 0x26f36612,0xd26902b1,0xe0618d8b,0x59c3a44e,0x308357ee,0x4df8a813, + 0x405626c2,0x7dcd079d } }, + /* 229 */ + { { 0xf05a4b48,0x5ce7d4d3,0x37230772,0xadcd2952,0x812a915a,0xd18f7971, + 0x377d19b8,0x0bf53589 }, + { 0x6c68ea73,0x35ecd95a,0x823a584d,0xc7f3bbca,0xf473a723,0x9fb674c6, + 0xe16686fc,0xd28be4d9 } }, + /* 230 */ + { { 0x38fa8e4b,0x5d2b9906,0x893fd8fc,0x559f186e,0x436fb6fc,0x3a6de2aa, + 0x510f88ce,0xd76007aa }, + { 0x523a4988,0x2d10aab6,0x74dd0273,0xb455cf44,0xa3407278,0x7f467082, + 0xb303bb01,0xf2b52f68 } }, + /* 231 */ + { { 0x9835b4ca,0x0d57eafa,0xbb669cbc,0x2d2232fc,0xc6643198,0x8eeeb680, + 0xcc5aed3a,0xd8dbe98e }, + { 0xc5a02709,0xcba9be3f,0xf5ba1fa8,0x30be68e5,0xf10ea852,0xfebd43cd, + 0xee559705,0xe01593a3 } }, + /* 232 */ + { { 0xea75a0a6,0xd3e5af50,0x57858033,0x512226ac,0xd0176406,0x6fe6d50f, + 0xaeb8ef06,0xafec07b1 }, + { 0x80bb0a31,0x7fb99567,0x37309aae,0x6f1af3cc,0x01abf389,0x9153a15a, + 0x6e2dbfdd,0xa71b9354 } }, + /* 233 */ + { { 0x18f593d2,0xbf8e12e0,0xa078122b,0xd1a90428,0x0ba4f2ad,0x150505db, + 0x628523d9,0x53a2005c }, + { 0xe7f2b935,0x07c8b639,0xc182961a,0x2bff975a,0x7518ca2c,0x86bceea7, + 0x3d588e3d,0xbf47d19b } }, + /* 234 */ + { { 0xdd7665d5,0x672967a7,0x2f2f4de5,0x4e303057,0x80d4903f,0x144005ae, + 0x39c9a1b6,0x001c2c7f }, + { 0x69efc6d6,0x143a8014,0x7bc7a724,0xc810bdaa,0xa78150a4,0x5f65670b, + 0x86ffb99b,0xfdadf8e7 } }, + /* 235 */ + { { 0xffc00785,0xfd38cb88,0x3b48eb67,0x77fa7591,0xbf368fbc,0x0454d055, + 0x5aa43c94,0x3a838e4d }, + { 0x3e97bb9a,0x56166329,0x441d94d9,0x9eb93363,0x0adb2a83,0x515591a6, + 0x873e1da3,0x3cdb8257 } }, + /* 236 */ + { { 0x7de77eab,0x137140a9,0x41648109,0xf7e1c50d,0xceb1d0df,0x762dcad2, + 0xf1f57fba,0x5a60cc89 }, + { 0x40d45673,0x80b36382,0x5913c655,0x1b82be19,0xdd64b741,0x057284b8, + 0xdbfd8fc0,0x922ff56f } }, + /* 237 */ + { { 0xc9a129a1,0x1b265dee,0xcc284e04,0xa5b1ce57,0xcebfbe3c,0x04380c46, + 0xf6c5cd62,0x72919a7d }, + { 0x8fb90f9a,0x298f453a,0x88e4031b,0xd719c00b,0x796f1856,0xe32c0e77, + 0x3624089a,0x5e791780 } }, + /* 238 */ + { { 0x7f63cdfb,0x5c16ec55,0xf1cae4fd,0x8e6a3571,0x560597ca,0xfce26bea, + 0xe24c2fab,0x4e0a5371 }, + { 0xa5765357,0x276a40d3,0x0d73a2b4,0x3c89af44,0x41d11a32,0xb8f370ae, + 0xd56604ee,0xf5ff7818 } }, + /* 239 */ + { { 0x1a09df21,0xfbf3e3fe,0xe66e8e47,0x26d5d28e,0x29c89015,0x2096bd0a, + 0x533f5e64,0xe41df0e9 }, + { 0xb3ba9e3f,0x305fda40,0x2604d895,0xf2340ceb,0x7f0367c7,0x0866e192, + 0xac4f155f,0x8edd7d6e } }, + /* 240 */ + { { 0x0bfc8ff3,0xc9a1dc0e,0xe936f42f,0x14efd82b,0xcca381ef,0x67016f7c, + 0xed8aee96,0x1432c1ca }, + { 0x70b23c26,0xec684829,0x0735b273,0xa64fe873,0xeaef0f5a,0xe389f6e5, + 0x5ac8d2c6,0xcaef480b } }, + /* 241 */ + { { 0x75315922,0x5245c978,0x3063cca5,0xd8295171,0xb64ef2cb,0xf3ce60d0, + 0x8efae236,0xd0ba177e }, + { 0xb1b3af60,0x53a9ae8f,0x3d2da20e,0x1a796ae5,0xdf9eef28,0x01d63605, + 0x1c54ae16,0xf31c957c } }, + /* 242 */ + { { 0x49cc4597,0xc0f58d52,0xbae0a028,0xdc5015b0,0x734a814a,0xefc5fc55, + 0x96e17c3a,0x013404cb }, + { 0xc9a824bf,0xb29e2585,0x001eaed7,0xd593185e,0x61ef68ac,0x8d6ee682, + 0x91933e6c,0x6f377c4b } }, + /* 243 */ + { { 0xa8333fd2,0x9f93bad1,0x5a2a95b8,0xa8930202,0xeaf75ace,0x211e5037, + 0xd2d09506,0x6dba3e4e }, + { 0xd04399cd,0xa48ef98c,0xe6b73ade,0x1811c66e,0xc17ecaf3,0x72f60752, + 0x3becf4a7,0xf13cf342 } }, + /* 244 */ + { { 0xa919e2eb,0xceeb9ec0,0xf62c0f68,0x83a9a195,0x7aba2299,0xcfba3bb6, + 0x274bbad3,0xc83fa9a9 }, + { 0x62fa1ce0,0x0d7d1b0b,0x3418efbf,0xe58b60f5,0x52706f04,0xbfa8ef9e, + 0x5d702683,0xb49d70f4 } }, + /* 245 */ + { { 0xfad5513b,0x914c7510,0xb1751e2d,0x05f32eec,0xd9fb9d59,0x6d850418, + 0x0c30f1cf,0x59cfadbb }, + { 0x55cb7fd6,0xe167ac23,0x820426a3,0x249367b8,0x90a78864,0xeaeec58c, + 0x354a4b67,0x5babf362 } }, + /* 246 */ + { { 0xee424865,0x37c981d1,0xf2e5577f,0x8b002878,0xb9e0c058,0x702970f1, + 0x9026c8f0,0x6188c6a7 }, + { 0xd0f244da,0x06f9a19b,0xfb080873,0x1ecced5c,0x9f213637,0x35470f9b, + 0xdf50b9d9,0x993fe475 } }, + /* 247 */ + { { 0x9b2c3609,0x68e31cdf,0x2c46d4ea,0x84eb19c0,0x9a775101,0x7ac9ec1a, + 0x4c80616b,0x81f76466 }, + { 0x75fbe978,0x1d7c2a5a,0xf183b356,0x6743fed3,0x501dd2bf,0x838d1f04, + 0x5fe9060d,0x564a812a } }, + /* 248 */ + { { 0xfa817d1d,0x7a5a64f4,0xbea82e0f,0x55f96844,0xcd57f9aa,0xb5ff5a0f, + 0x00e51d6c,0x226bf3cf }, + { 0x2f2833cf,0xd6d1a9f9,0x4f4f89a8,0x20a0a35a,0x8f3f7f77,0x11536c49, + 0xff257836,0x68779f47 } }, + /* 249 */ + { { 0x73043d08,0x79b0c1c1,0x1fc020fa,0xa5446774,0x9a6d26d0,0xd3767e28, + 0xeb092e0b,0x97bcb0d1 }, + { 0xf32ed3c3,0x2ab6eaa8,0xb281bc48,0xc8a4f151,0xbfa178f3,0x4d1bf4f3, + 0x0a784655,0xa872ffe8 } }, + /* 250 */ + { { 0xa32b2086,0xb1ab7935,0x8160f486,0xe1eb710e,0x3b6ae6be,0x9bd0cd91, + 0xb732a36a,0x02812bfc }, + { 0xcf605318,0xa63fd7ca,0xfdfd6d1d,0x646e5d50,0x2102d619,0xa1d68398, + 0xfe5396af,0x07391cc9 } }, + /* 251 */ + { { 0x8b80d02b,0xc50157f0,0x62877f7f,0x6b8333d1,0x78d542ae,0x7aca1af8, + 0x7e6d2a08,0x355d2adc }, + { 0x287386e1,0xb41f335a,0xf8e43275,0xfd272a94,0xe79989ea,0x286ca2cd, + 0x7c2a3a79,0x3dc2b1e3 } }, + /* 252 */ + { { 0x04581352,0xd689d21c,0x376782be,0x0a00c825,0x9fed701f,0x203bd590, + 0x3ccd846b,0xc4786910 }, + { 0x24c768ed,0x5dba7708,0x6841f657,0x72feea02,0x6accce0e,0x73313ed5, + 0xd5bb4d32,0xccc42968 } }, + /* 253 */ + { { 0x3d7620b9,0x94e50de1,0x5992a56a,0xd89a5c8a,0x675487c9,0xdc007640, + 0xaa4871cf,0xe147eb42 }, + { 0xacf3ae46,0x274ab4ee,0x50350fbe,0xfd4936fb,0x48c840ea,0xdf2afe47, + 0x080e96e3,0x239ac047 } }, + /* 254 */ + { { 0x2bfee8d4,0x481d1f35,0xfa7b0fec,0xce80b5cf,0x2ce9af3c,0x105c4c9e, + 0xf5f7e59d,0xc55fa1a3 }, + { 0x8257c227,0x3186f14e,0x342be00b,0xc5b1653f,0xaa904fb2,0x09afc998, + 0xd4f4b699,0x094cd99c } }, + /* 255 */ + { { 0xd703beba,0x8a981c84,0x32ceb291,0x8631d150,0xe3bd49ec,0xa445f2c9, + 0x42abad33,0xb90a30b6 }, + { 0xb4a5abf9,0xb465404f,0x75db7603,0x004750c3,0xca35d89f,0x6f9a42cc, + 0x1b7924f7,0x019f8b9a } }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_8(sp_point_256* r, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_8(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 coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[8]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_256_point_new_8(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, km); + + err = sp_256_ecc_mulmod_base_8(point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_8(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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_8(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_add_one_8(sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r2, #1\n\t" + "ldr r1, [%[a], #0]\n\t" + "adds r1, r1, r2\n\t" + "mov r2, #0\n\t" + "str r1, [%[a], #0]\n\t" + "ldr r1, [%[a], #4]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #4]\n\t" + "ldr r1, [%[a], #8]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #8]\n\t" + "ldr r1, [%[a], #12]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #12]\n\t" + "ldr r1, [%[a], #16]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #16]\n\t" + "ldr r1, [%[a], #20]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #20]\n\t" + "ldr r1, [%[a], #24]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #24]\n\t" + "ldr r1, [%[a], #28]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #28]\n\t" + : + : [a] "r" (a) + : "memory", "r1", "r2" + ); +} + +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; 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_8(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, 8, buf, (int)sizeof(buf)); + if (sp_256_cmp_8(k, p256_order2) < 0) { + sp_256_add_one_8(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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[8]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 inf; +#endif +#endif + sp_point_256* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity; +#endif + int err; + + (void)heap; + + err = sp_256_point_new_8(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + err = sp_256_ecc_gen_k_8(rng, k); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_256_iszero_8(point->x) == 0) || (sp_256_iszero_8(point->y) == 0)) { + 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_8(point, pub); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_256_point_free_8(infinity, 1, heap); +#endif + sp_256_point_free_8(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte array. + * 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<8 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[8]; +#endif + sp_point_256* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 32U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, priv); + sp_256_point_from_ecc_point_8(point, pub); + err = sp_256_ecc_mulmod_8(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_in_place_8(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r8, %[a]\n\t" + "add r8, r8, #32\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r8\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_256_sub_in_place_8(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* 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. + */ +SP_NOINLINE static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "add r9, %[a], #32\n\t" + /* A[0] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r5, r3, r6, %[b]\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]], #4\n\t" + /* A[0] * B - Done */ + "\n1:\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r6, r8, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[] * B - Done */ + "str r3, [%[r]], #4\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9" + ); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_256_word_8(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r8, r4, #16\n\t" + "umull r4, r5, %[div], r8\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r8, r8, r4\n\t" + "mov %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r8" + ); + 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_8(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & 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 WC_INLINE int sp_256_div_8(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[16], t2[9]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[7]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 8); + for (i=7; i>=0; i--) { + r1 = div_256_word_8(t1[8 + i], t1[8 + i - 1], div); + + sp_256_mul_d_8(t2, d, r1); + t1[8 + i] += sp_256_sub_in_place_8(&t1[i], t2); + t1[8 + i] -= t2[8]; + sp_256_mask_8(t2, d, t1[8 + i]); + t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2); + sp_256_mask_8(t2, d, t1[8 + i]); + t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2); + } + + r1 = sp_256_cmp_8(t1, d) >= 0; + sp_256_cond_sub_8(r, t1, d, (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 WC_INLINE int sp_256_mod_8(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_256_div_8(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_minus_2[8] = { + 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU,0xffffffffU,0xffffffffU, + 0x00000000U,0xffffffffU +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint32_t p256_order_low[4] = { + 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU +}; +#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_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_256_mul_8(r, a, b); + sp_256_mont_reduce_order_8(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_8(sp_digit* r, const sp_digit* a) +{ + sp_256_sqr_8(r, a); + sp_256_mont_reduce_order_8(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_8(sp_digit* r, const sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_8(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_8(t, t); + if ((p256_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 8U); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 8; + sp_digit* t3 = td + 4 * 8; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_8(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_8(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_8(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_8(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_8(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_8(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_8(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_8(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_8(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_8(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_8(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_8(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_8(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_8(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t2, t2, a); + } + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t2, t2, a); + } + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t2, t2, a); + } + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_8(t2, t2, a); + } + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_8(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#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, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit ed[2*8]; + sp_digit xd[2*8]; + sp_digit kd[2*8]; + sp_digit rd[2*8]; + sp_digit td[3 * 2*8]; + sp_point_256 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_256* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int32_t c; + int i; + + (void)heap; + + err = sp_256_point_new_8(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 8; + x = d + 2 * 8; + k = d + 4 * 8; + r = d + 6 * 8; + tmp = d + 8 * 8; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(e, 8, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 8, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_8(rng, k); + } + else { + sp_256_from_mp(k, 8, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 8U); + sp_256_norm_8(r); + c = sp_256_cmp_8(r, p256_order); + sp_256_cond_sub_8(r, r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(r); + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(k, k, p256_norm_order); + err = sp_256_mod_8(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(k); + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_8(kInv, k, tmp); + sp_256_norm_8(kInv); + + /* s = r * x + e */ + sp_256_mul_8(x, x, r); + err = sp_256_mod_8(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(x); + carry = sp_256_add_8(s, e, x); + sp_256_cond_sub_8(s, s, p256_order, 0 - carry); + sp_256_norm_8(s); + c = sp_256_cmp_8(s, p256_order); + sp_256_cond_sub_8(s, s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(s, s, kInv); + sp_256_norm_8(s); + + /* Check that signature is usable. */ + if (sp_256_iszero_8(s) == 0) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 8); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U); +#endif + sp_256_point_free_8(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit u1d[2*8]; + sp_digit u2d[2*8]; + sp_digit sd[2*8]; + sp_digit tmpd[2*8 * 5]; + sp_point_256 p1d; + sp_point_256 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p1; + sp_point_256* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + + err = sp_256_point_new_8(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 8; + u2 = d + 2 * 8; + s = d + 4 * 8; + tmp = d + 6 * 8; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 8, hash, (int)hashLen); + sp_256_from_mp(u2, 8, r); + sp_256_from_mp(s, 8, sm); + sp_256_from_mp(p2->x, 8, pX); + sp_256_from_mp(p2->y, 8, pY); + sp_256_from_mp(p2->z, 8, pZ); + + { + sp_256_mul_8(s, s, p256_norm_order); + } + err = sp_256_mod_8(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(s); + { + sp_256_mont_inv_order_8(s, s, tmp); + sp_256_mont_mul_order_8(u1, u1, s); + sp_256_mont_mul_order_8(u2, u2, s); + } + + err = sp_256_ecc_mulmod_base_8(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + { + sp_256_proj_point_add_8(p1, p1, p2, tmp); + if (sp_256_iszero_8(p1->z)) { + if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) { + sp_256_proj_point_dbl_8(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + } + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 8, r); + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 8, r); + carry = sp_256_add_8(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_8(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_256_point_free_8(p1, 0, heap); + sp_256_point_free_8(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_8(sp_point_256* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*8]; + sp_digit t2d[2*8]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 8; + t2 = d + 2 * 8; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_256_sqr_8(t1, point->y); + (void)sp_256_mod_8(t1, t1, p256_mod); + sp_256_sqr_8(t2, point->x); + (void)sp_256_mod_8(t2, t2, p256_mod); + sp_256_mul_8(t2, t2, point->x); + (void)sp_256_mod_8(t2, t2, p256_mod); + (void)sp_256_sub_8(t2, p256_mod, t2); + sp_256_mont_add_8(t1, t1, t2, p256_mod); + + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_8(t1, p256_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 pubd; +#endif + sp_point_256* pub; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_8(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 8, pX); + sp_256_from_mp(pub->y, 8, pY); + sp_256_from_bin(pub->z, 8, one, (int)sizeof(one)); + + err = sp_256_ecc_is_point_8(pub, NULL); + } + + sp_256_point_free_8(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[8]; + sp_point_256 pubd; + sp_point_256 pd; +#endif + sp_digit* priv = NULL; + sp_point_256* pub; + sp_point_256* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_8(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_256_point_new_8(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_256_from_mp(pub->x, 8, pX); + sp_256_from_mp(pub->y, 8, pY); + sp_256_from_bin(pub->z, 8, one, (int)sizeof(one)); + sp_256_from_mp(priv, 8, privm); + + /* Check point at infinitiy. */ + if ((sp_256_iszero_8(pub->x) != 0) && + (sp_256_iszero_8(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_8(pub->x, p256_mod) >= 0 || + sp_256_cmp_8(pub->y, p256_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_8(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_256_iszero_8(p->x) == 0) || + (sp_256_iszero_8(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_256_ecc_mulmod_base_8(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_8(p->x, pub->x) != 0 || + sp_256_cmp_8(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, heap); + sp_256_point_free_8(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 8 * 5]; + sp_point_256 pd; + sp_point_256 qd; +#endif + sp_digit* tmp; + sp_point_256* p; + sp_point_256* q = NULL; + int err; + + err = sp_256_point_new_8(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_256_point_new_8(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + sp_256_from_mp(q->x, 8, qX); + sp_256_from_mp(q->y, 8, qY); + sp_256_from_mp(q->z, 8, qZ); + + sp_256_proj_point_add_8(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(q, 0, NULL); + sp_256_point_free_8(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 8 * 2]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_8(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + + sp_256_proj_point_dbl_8(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 8 * 4]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_8(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + + sp_256_map_8(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_8(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_8(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 8]; + sp_digit t2d[2 * 8]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 8; + t2 = d + 2 * 8; +#else + t1 = t1d; + t2 = t2d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_8(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_8(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_8(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_8(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_8(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_8(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_8(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_8(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 8]; + sp_digit yd[2 * 8]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 8; + y = d + 2 * 8; +#else + x = xd; + y = yd; +#endif + + sp_256_from_mp(x, 8, xm); + err = sp_256_mod_mul_norm_8(x, x, p256_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_8(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_sub_8(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_8(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_8(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_8(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 8, 0, 8U * sizeof(sp_digit)); + sp_256_mont_reduce_8(y, p256_mod, p256_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_256_mont_sub_8(y, p256_mod, y, p256_mod); + } + + err = sp_256_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#ifdef WOLFSSL_SP_384 + +/* Point structure to use. */ +typedef struct sp_point_384 { + sp_digit x[2 * 12]; + sp_digit y[2 * 12]; + sp_digit z[2 * 12]; + int infinity; +} sp_point_384; + +/* The modulus (prime) of the curve P384. */ +static const sp_digit p384_mod[12] = { + 0xffffffff,0x00000000,0x00000000,0xffffffff,0xfffffffe,0xffffffff, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +}; +/* The Montogmery normalizer for modulus of the curve P384. */ +static const sp_digit p384_norm_mod[12] = { + 0x00000001,0xffffffff,0xffffffff,0x00000000,0x00000001,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 +}; +/* The Montogmery multiplier for modulus of the curve P384. */ +static sp_digit p384_mp_mod = 0x00000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P384. */ +static const sp_digit p384_order[12] = { + 0xccc52973,0xecec196a,0x48b0a77a,0x581a0db2,0xf4372ddf,0xc7634d81, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +}; +#endif +/* The order of the curve P384 minus 2. */ +static const sp_digit p384_order2[12] = { + 0xccc52971,0xecec196a,0x48b0a77a,0x581a0db2,0xf4372ddf,0xc7634d81, + 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P384. */ +static const sp_digit p384_norm_order[12] = { + 0x333ad68d,0x1313e695,0xb74f5885,0xa7e5f24d,0x0bc8d220,0x389cb27e, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P384. */ +static sp_digit p384_mp_order = 0xe88fdc45; +#endif +/* The base point of curve P384. */ +static const sp_point_384 p384_base = { + /* X ordinate */ + { + 0x72760ab7,0x3a545e38,0xbf55296c,0x5502f25d,0x82542a38,0x59f741e0, + 0x8ba79b98,0x6e1d3b62,0xf320ad74,0x8eb1c71e,0xbe8b0537,0xaa87ca22, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x90ea0e5f,0x7a431d7c,0x1d7e819d,0x0a60b1ce,0xb5f0b8c0,0xe9da3113, + 0x289a147c,0xf8f41dbd,0x9292dc29,0x5d9e98bf,0x96262c6f,0x3617de4a, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p384_b[12] = { + 0xd3ec2aef,0x2a85c8ed,0x8a2ed19d,0xc656398d,0x5013875a,0x0314088f, + 0xfe814112,0x181d9c6e,0xe3f82d19,0x988e056b,0xe23ee7e4,0xb3312fa7 +}; +#endif + +static int sp_384_point_new_ex_12(void* heap, sp_point_384* sp, sp_point_384** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_384_point_new_12(heap, sp, p) sp_384_point_new_ex_12((heap), &(sp), &(p)) +#endif + + +static void sp_384_point_free_12(sp_point_384* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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_384_mod_mul_norm_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* t; +#else + int64_t t[12]; +#endif + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (int64_t*)XMALLOC(sizeof(int64_t) * 12, NULL, DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + (uint64_t)a[0] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[8] + (uint64_t)a[10] + (uint64_t)a[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[9] + (uint64_t)a[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + (uint64_t)a[0] - (uint64_t)a[2] + (uint64_t)a[3] + (uint64_t)a[8] + (uint64_t)a[9] - (uint64_t)a[10] - (uint64_t)a[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + (uint64_t)a[0] + (uint64_t)a[1] - (uint64_t)a[3] + (uint64_t)a[4] + (uint64_t)a[8] + 2 * (uint64_t)a[9] + (uint64_t)a[10] - 2 * (uint64_t)a[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + (uint64_t)a[1] + (uint64_t)a[2] - (uint64_t)a[4] + (uint64_t)a[5] + (uint64_t)a[9] + 2 * (uint64_t)a[10] + (uint64_t)a[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + (uint64_t)a[2] + (uint64_t)a[3] - (uint64_t)a[5] + (uint64_t)a[6] + (uint64_t)a[10] + 2 * (uint64_t)a[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + (uint64_t)a[3] + (uint64_t)a[4] - (uint64_t)a[6] + (uint64_t)a[7] + (uint64_t)a[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + (uint64_t)a[4] + (uint64_t)a[5] - (uint64_t)a[7] + (uint64_t)a[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + (uint64_t)a[5] + (uint64_t)a[6] - (uint64_t)a[8] + (uint64_t)a[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + (uint64_t)a[6] + (uint64_t)a[7] - (uint64_t)a[9] + (uint64_t)a[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + (uint64_t)a[7] + (uint64_t)a[8] - (uint64_t)a[10] + (uint64_t)a[11]; + + 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + + r[0] = t[0]; + r[1] = t[1]; + r[2] = t[2]; + r[3] = t[3]; + r[4] = t[4]; + r[5] = t[5]; + r[6] = t[6]; + r[7] = t[7]; + r[8] = t[8]; + r[9] = t[9]; + r[10] = t[10]; + r[11] = t[11]; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 32 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 32U) <= (word32)DIGIT_BIT) { + s += 32U; + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= size) { + break; + } + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_12(sp_point_384* p, const 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_384_from_mp(p->x, 12, pm->x); + sp_384_from_mp(p->y, 12, pm->y); + sp_384_from_mp(p->z, 12, 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_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 12); + r->used = 12; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 12; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 32 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 12; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1L << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else { + s += 32; + } + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_12(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_384_mul_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[12 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r10, %[a]\n\t" + "mov r11, %[b]\n\t" + "mov r6, #48\n\t" + "add r6, r6, r10\n\t" + "mov r14, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #44\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r9\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add %[b], %[b], r11\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [%[b]]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r14\n\t" + "beq 3f\n\t" + "mov r6, r9\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r12\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #88\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[a], r10\n\t" + "mov %[b], r11\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* 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. + */ +SP_NOINLINE static sp_digit sp_384_cond_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #48\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r8]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + return c; +} + +#define sp_384_mont_reduce_order_12 sp_384_mont_reduce_12 + +/* Reduce the number back to 384 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_384_mont_reduce_12(sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r9, %[mp]\n\t" + "mov r12, %[m]\n\t" + "mov r10, %[a]\n\t" + "mov r4, #0\n\t" + "add r11, r10, #48\n\t" + "\n1:\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r9\n\t" + "ldr %[a], [r10]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r12\n\t" + "add r14, r10, #40\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+j+1] += m[j+1] * mu */ + "ldr %[a], [r10]\n\t" + "mov r4, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r4, r4, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r5, r5, %[a]\n\t" + "adc r4, r4, #0\n\t" + "str r5, [r10], #4\n\t" + "cmp r10, r14\n\t" + "blt 2b\n\t" + /* a[i+10] += m[10] * mu */ + "ldr %[a], [r10]\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r8, [%[m]], #4\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds %[a], %[a], r6\n\t" + "adc r5, r5, r8\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, #0\n\t" + "str r4, [r10], #4\n\t" + /* a[i+11] += m[11] * mu */ + "mov r4, %[ca]\n\t" + "mov %[ca], #0\n\t" + /* Multiply m[11] and mu - Start */ + "ldr r8, [%[m]]\n\t" + "umull r6, r8, %[mp], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc %[ca], %[ca], #0\n\t" + /* Multiply m[11] and mu - Done */ + "ldr r6, [r10]\n\t" + "ldr r8, [r10, #4]\n\t" + "adds r6, r6, r5\n\t" + "adcs r8, r8, r4\n\t" + "adc %[ca], %[ca], #0\n\t" + "str r6, [r10]\n\t" + "str r8, [r10, #4]\n\t" + /* Next word in a */ + "sub r10, r10, #40\n\t" + "cmp r10, r11\n\t" + "blt 1b\n\t" + "mov %[a], r10\n\t" + "mov %[m], r12\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_384_cond_sub_12(a - 12, 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_384_mont_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_384_mul_12(r, a, b); + sp_384_mont_reduce_12(r, m, mp); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r9, r3\n\t" + "mov r12, %[r]\n\t" + "mov r6, #96\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r11, sp\n\t" + "mov r10, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #44\n\t" + "mov %[a], r9\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r9\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r10\n\t" + "add r2, r2, r10\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r8, [r2]\n\t" + "umull r6, r8, r6, r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ + "bal 5f\n\t" + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r8, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #48\n\t" + "add r6, r6, r10\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r8, r9\n\t" + "add r8, r8, r10\n\t" + "cmp %[a], r8\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r8, r9\n\t" + "str r3, [%[r], r8]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r8, r8, #4\n\t" + "mov r9, r8\n\t" + "mov r6, #88\n\t" + "cmp r8, r6\n\t" + "ble 1b\n\t" + "mov %[a], r10\n\t" + "str r3, [%[r], r8]\n\t" + "mov %[r], r12\n\t" + "mov %[a], r11\n\t" + "mov r3, #92\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #96\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); +} + +/* 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_384_mont_sqr_12(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_384_sqr_12(r, a); + sp_384_mont_reduce_12(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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_384_mont_sqr_n_12(sp_digit* r, const sp_digit* a, int n, + const sp_digit* m, sp_digit mp) +{ + sp_384_mont_sqr_12(r, a, m, mp); + for (; n > 1; n--) { + sp_384_mont_sqr_12(r, r, m, mp); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P384 curve. */ +static const uint32_t p384_mod_minus_2[12] = { + 0xfffffffdU,0x00000000U,0x00000000U,0xffffffffU,0xfffffffeU,0xffffffffU, + 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P384 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_384_mont_inv_12(sp_digit* r, const sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 12); + for (i=382; i>=0; i--) { + sp_384_mont_sqr_12(t, t, p384_mod, p384_mp_mod); + if (p384_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_384_mont_mul_12(t, t, a, p384_mod, p384_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 12); +#else + sp_digit* t1 = td; + sp_digit* t2 = td + 2 * 12; + sp_digit* t3 = td + 4 * 12; + sp_digit* t4 = td + 6 * 12; + sp_digit* t5 = td + 8 * 12; + + /* 0x2 */ + sp_384_mont_sqr_12(t1, a, p384_mod, p384_mp_mod); + /* 0x3 */ + sp_384_mont_mul_12(t5, t1, a, p384_mod, p384_mp_mod); + /* 0xc */ + sp_384_mont_sqr_n_12(t1, t5, 2, p384_mod, p384_mp_mod); + /* 0xf */ + sp_384_mont_mul_12(t2, t5, t1, p384_mod, p384_mp_mod); + /* 0x1e */ + sp_384_mont_sqr_12(t1, t2, p384_mod, p384_mp_mod); + /* 0x1f */ + sp_384_mont_mul_12(t4, t1, a, p384_mod, p384_mp_mod); + /* 0x3e0 */ + sp_384_mont_sqr_n_12(t1, t4, 5, p384_mod, p384_mp_mod); + /* 0x3ff */ + sp_384_mont_mul_12(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0x7fe0 */ + sp_384_mont_sqr_n_12(t1, t2, 5, p384_mod, p384_mp_mod); + /* 0x7fff */ + sp_384_mont_mul_12(t4, t4, t1, p384_mod, p384_mp_mod); + /* 0x3fff8000 */ + sp_384_mont_sqr_n_12(t1, t4, 15, p384_mod, p384_mp_mod); + /* 0x3fffffff */ + sp_384_mont_mul_12(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffc */ + sp_384_mont_sqr_n_12(t3, t2, 2, p384_mod, p384_mp_mod); + /* 0xfffffffd */ + sp_384_mont_mul_12(r, t3, a, p384_mod, p384_mp_mod); + /* 0xffffffff */ + sp_384_mont_mul_12(t3, t5, t3, p384_mod, p384_mp_mod); + /* 0xfffffffc0000000 */ + sp_384_mont_sqr_n_12(t1, t2, 30, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff */ + sp_384_mont_mul_12(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_12(t1, t2, 60, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_12(t1, t2, 120, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_12(t1, t2, 15, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */ + sp_384_mont_sqr_n_12(t1, t2, 33, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */ + sp_384_mont_mul_12(t2, t3, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_12(t1, t2, 96, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */ + sp_384_mont_mul_12(r, r, t1, p384_mod, p384_mp_mod); + +#endif /* WOLFSSL_SP_SMALL */ +} + +/* 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. + */ +SP_NOINLINE static int32_t sp_384_cmp_12(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #44\n\t" + "\n1:\n\t" + "ldr r8, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r8, r8, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r8\n\t" + "subs r8, r8, r5\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "subs r5, r5, r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + "mvn r8, r8\n\t" + "and r3, r3, r8\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r8" + ); + + return r; +} + +/* Normalize the values in each word to 32. + * + * a Array of sp_digit to normalize. + */ +#define sp_384_norm_12(a) + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_384_map_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*12; + int32_t n; + + sp_384_mont_inv_12(t1, p->z, t + 2*12); + + sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod); + + /* x /= z^2 */ + sp_384_mont_mul_12(r->x, p->x, t2, p384_mod, p384_mp_mod); + XMEMSET(r->x + 12, 0, sizeof(r->x) / 2U); + sp_384_mont_reduce_12(r->x, p384_mod, p384_mp_mod); + /* Reduce x to less than modulus */ + n = sp_384_cmp_12(r->x, p384_mod); + sp_384_cond_sub_12(r->x, r->x, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_12(r->x); + + /* y /= z^3 */ + sp_384_mont_mul_12(r->y, p->y, t1, p384_mod, p384_mp_mod); + XMEMSET(r->y + 12, 0, sizeof(r->y) / 2U); + sp_384_mont_reduce_12(r->y, p384_mod, p384_mp_mod); + /* Reduce y to less than modulus */ + n = sp_384_cmp_12(r->y, p384_mod); + sp_384_cond_sub_12(r->y, r->y, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_12(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. + */ +SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r8, #0\n\t" + "add r6, r6, #48\n\t" + "sub r8, r8, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r8\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "ldm %[a]!, {r4, r5}\n\t" + "ldm %[b]!, {r6, r8}\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r8\n\t" + "stm %[r]!, {r4, r5}\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#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). + */ +SP_NOINLINE static void sp_384_mont_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_12(r, a, b); + sp_384_cond_sub_12(r, r, m, 0 - o); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_384_mont_dbl_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_12(r, a, a); + sp_384_cond_sub_12(r, r, m, 0 - o); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_384_mont_tpl_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_12(r, a, a); + sp_384_cond_sub_12(r, r, m, 0 - o); + o = sp_384_add_12(r, r, a); + sp_384_cond_sub_12(r, r, m, 0 - o); +} + +#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. + */ +SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "add r6, r6, #48\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "sbcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r8, [%[b], #4]\n\t" + "subs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r8, [%[b], #12]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r8, [%[b], #28]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r8, [%[b], #36]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #40]\n\t" + "ldr r8, [%[b], #44]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r8\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_384_cond_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #48\n\t" + "mov r9, r5\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r8]\n\t" + "and r6, r6, %[m]\n\t" + "adds r5, %[c], #-1\n\t" + "ldr r5, [%[a], r8]\n\t" + "adcs r5, r5, r6\n\t" + "mov %[c], #0\n\t" + "adcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, r9\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r8", "r9" + ); + + return c; +} + +/* 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). + */ +SP_NOINLINE static void sp_384_mont_sub_12(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + sp_digit o; + + o = sp_384_sub_12(r, a, b); + sp_384_cond_add_12(r, r, m, o); +} + +static void sp_384_rshift1_12(sp_digit* r, sp_digit* a) +{ + __asm__ __volatile__ ( + "ldr r2, [%[a]]\n\t" + "ldr r3, [%[a], #4]\n\t" + "lsr r2, r2, #1\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #8]\n\t" + "str r2, [%[r], #0]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #12]\n\t" + "str r3, [%[r], #4]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #16]\n\t" + "str r4, [%[r], #8]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #20]\n\t" + "str r2, [%[r], #12]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #24]\n\t" + "str r3, [%[r], #16]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #28]\n\t" + "str r4, [%[r], #20]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #32]\n\t" + "str r2, [%[r], #24]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "ldr r2, [%[a], #36]\n\t" + "str r3, [%[r], #28]\n\t" + "lsl r5, r2, #31\n\t" + "lsr r2, r2, #1\n\t" + "orr r4, r4, r5\n\t" + "ldr r3, [%[a], #40]\n\t" + "str r4, [%[r], #32]\n\t" + "lsl r5, r3, #31\n\t" + "lsr r3, r3, #1\n\t" + "orr r2, r2, r5\n\t" + "ldr r4, [%[a], #44]\n\t" + "str r2, [%[r], #36]\n\t" + "lsl r5, r4, #31\n\t" + "lsr r4, r4, #1\n\t" + "orr r3, r3, r5\n\t" + "str r3, [%[r], #40]\n\t" + "str r4, [%[r], #44]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5" + ); +} + +/* 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). + */ +SP_NOINLINE static void sp_384_div2_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_cond_add_12(r, a, m, 0 - (a[0] & 1)); + sp_384_rshift1_12(r, r); + r[11] |= o << 31; +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_dbl_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*12; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_384_mont_sqr_12(t1, p->z, p384_mod, p384_mp_mod); + /* Z = Y * Z */ + sp_384_mont_mul_12(z, p->y, p->z, p384_mod, p384_mp_mod); + /* Z = 2Z */ + sp_384_mont_dbl_12(z, z, p384_mod); + /* T2 = X - T1 */ + sp_384_mont_sub_12(t2, p->x, t1, p384_mod); + /* T1 = X + T1 */ + sp_384_mont_add_12(t1, p->x, t1, p384_mod); + /* T2 = T1 * T2 */ + sp_384_mont_mul_12(t2, t1, t2, p384_mod, p384_mp_mod); + /* T1 = 3T2 */ + sp_384_mont_tpl_12(t1, t2, p384_mod); + /* Y = 2Y */ + sp_384_mont_dbl_12(y, p->y, p384_mod); + /* Y = Y * Y */ + sp_384_mont_sqr_12(y, y, p384_mod, p384_mp_mod); + /* T2 = Y * Y */ + sp_384_mont_sqr_12(t2, y, p384_mod, p384_mp_mod); + /* T2 = T2/2 */ + sp_384_div2_12(t2, t2, p384_mod); + /* Y = Y * X */ + sp_384_mont_mul_12(y, y, p->x, p384_mod, p384_mp_mod); + /* X = T1 * T1 */ + sp_384_mont_sqr_12(x, t1, p384_mod, p384_mp_mod); + /* X = X - Y */ + sp_384_mont_sub_12(x, x, y, p384_mod); + /* X = X - Y */ + sp_384_mont_sub_12(x, x, y, p384_mod); + /* Y = Y - X */ + sp_384_mont_sub_12(y, y, x, p384_mod); + /* Y = Y * T1 */ + sp_384_mont_mul_12(y, y, t1, p384_mod, p384_mp_mod); + /* Y = Y - T2 */ + sp_384_mont_sub_12(y, y, t2, p384_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_384_cmp_equal_12(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]) | (a[10] ^ b[10]) | (a[11] ^ b[11])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, + sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*12; + sp_digit* t3 = t + 4*12; + sp_digit* t4 = t + 6*12; + sp_digit* t5 = t + 8*12; + 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) { + const sp_point_384* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_384_sub_12(t1, p384_mod, q->y); + sp_384_norm_12(t1); + if ((sp_384_cmp_equal_12(p->x, q->x) & sp_384_cmp_equal_12(p->z, q->z) & + (sp_384_cmp_equal_12(p->y, q->y) | sp_384_cmp_equal_12(p->y, t1))) != 0) { + sp_384_proj_point_dbl_12(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<12; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<12; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<12; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_12(t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t3, t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t1, t1, x, p384_mod, p384_mp_mod); + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_12(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_12(t3, t3, y, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_12(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - U1 */ + sp_384_mont_sub_12(t2, t2, t1, p384_mod); + /* R = S2 - S1 */ + sp_384_mont_sub_12(t4, t4, t3, p384_mod); + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_12(z, z, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_12(x, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_12(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(y, t1, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(x, x, t5, p384_mod); + sp_384_mont_dbl_12(t1, y, p384_mod); + sp_384_mont_sub_12(x, x, t1, p384_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_12(y, y, x, p384_mod); + sp_384_mont_mul_12(y, y, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t5, t5, t3, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(y, y, t5, p384_mod); + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_fast_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td[16]; + sp_point_384 rtd; + sp_digit tmpd[2 * 12 * 6]; +#endif + sp_point_384* t; + sp_point_384* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_384_point_new_12(heap, rtd, rt); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 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 */ + (void)sp_384_mod_mul_norm_12(t[1].x, g->x, p384_mod); + (void)sp_384_mod_mul_norm_12(t[1].y, g->y, p384_mod); + (void)sp_384_mod_mul_norm_12(t[1].z, g->z, p384_mod); + t[1].infinity = 0; + sp_384_proj_point_dbl_12(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_384_proj_point_add_12(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_384_proj_point_dbl_12(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_384_proj_point_add_12(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_384_proj_point_dbl_12(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_384_proj_point_add_12(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_384_proj_point_dbl_12(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_384_proj_point_add_12(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_384_proj_point_dbl_12(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_384_proj_point_add_12(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_384_proj_point_dbl_12(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_384_proj_point_add_12(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_384_proj_point_dbl_12(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_384_proj_point_add_12(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 10; + n = k[i+1] << 0; + c = 28; + y = n >> 28; + XMEMCPY(rt, &t[y], sizeof(sp_point_384)); + n <<= 4; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--]; + c += 32; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_384_proj_point_dbl_12(rt, rt, tmp); + sp_384_proj_point_dbl_12(rt, rt, tmp); + sp_384_proj_point_dbl_12(rt, rt, tmp); + sp_384_proj_point_dbl_12(rt, rt, tmp); + + sp_384_proj_point_add_12(rt, rt, &t[y], tmp); + } + + if (map != 0) { + sp_384_map_12(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 12 * 6); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point_384) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_384_point_free_12(rt, 1, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_384 { + sp_digit x[12]; + sp_digit y[12]; +} sp_table_entry_384; + +#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_384_proj_point_dbl_n_12(sp_point_384* p, int n, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*12; + sp_digit* b = t + 4*12; + sp_digit* t1 = t + 6*12; + sp_digit* t2 = t + 8*12; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_384_mont_dbl_12(y, y, p384_mod); + /* W = Z^4 */ + sp_384_mont_sqr_12(w, z, p384_mod, p384_mp_mod); + sp_384_mont_sqr_12(w, w, p384_mod, p384_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_12(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(t1, t1, w, p384_mod); + sp_384_mont_tpl_12(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_12(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_12(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_12(t2, b, p384_mod); + sp_384_mont_sub_12(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_12(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_12(t1, t1, p384_mod, p384_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_384_mont_mul_12(w, w, t1, p384_mod, p384_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_12(y, b, x, p384_mod); + sp_384_mont_mul_12(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_12(y, y, p384_mod); + sp_384_mont_sub_12(y, y, t1, p384_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_12(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(t1, t1, w, p384_mod); + sp_384_mont_tpl_12(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_12(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_12(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_12(t2, b, p384_mod); + sp_384_mont_sub_12(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_12(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_12(t1, t1, p384_mod, p384_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_12(y, b, x, p384_mod); + sp_384_mont_mul_12(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_12(y, y, p384_mod); + sp_384_mont_sub_12(y, y, t1, p384_mod); +#endif + /* Y = Y/2 */ + sp_384_div2_12(y, y, p384_mod); +} + +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_384_proj_to_affine_12(sp_point_384* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 12; + sp_digit* tmp = t + 4 * 12; + + sp_384_mont_inv_12(t1, a->z, tmp); + + sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t1, t2, t1, p384_mod, p384_mp_mod); + + sp_384_mont_mul_12(a->x, a->x, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(a->y, a->y, t1, p384_mod, p384_mp_mod); + XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_qz1_12(sp_point_384* r, const sp_point_384* p, + const sp_point_384* q, sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*12; + sp_digit* t3 = t + 4*12; + sp_digit* t4 = t + 6*12; + sp_digit* t5 = t + 8*12; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_384_sub_12(t1, p384_mod, q->y); + sp_384_norm_12(t1); + if ((sp_384_cmp_equal_12(p->x, q->x) & sp_384_cmp_equal_12(p->z, q->z) & + (sp_384_cmp_equal_12(p->y, q->y) | sp_384_cmp_equal_12(p->y, t1))) != 0) { + sp_384_proj_point_dbl_12(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<12; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<12; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<12; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_12(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_12(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - X1 */ + sp_384_mont_sub_12(t2, t2, x, p384_mod); + /* R = S2 - Y1 */ + sp_384_mont_sub_12(t4, t4, y, p384_mod); + /* Z3 = H*Z1 */ + sp_384_mont_mul_12(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_384_mont_sqr_12(t1, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_12(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t3, x, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(x, t1, t5, p384_mod); + sp_384_mont_dbl_12(t1, t3, p384_mod); + sp_384_mont_sub_12(x, x, t1, p384_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_384_mont_sub_12(t3, t3, x, p384_mod); + sp_384_mont_mul_12(t3, t3, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(t5, t5, y, p384_mod, p384_mp_mod); + sp_384_mont_sub_12(y, t3, t5, p384_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_384_gen_stripe_table_12(const sp_point_384* a, + sp_table_entry_384* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td, s1d, s2d; +#endif + sp_point_384* t; + sp_point_384* s1 = NULL; + sp_point_384* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_384_point_new_12(heap, td, t); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->y, a->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->z, a->z, p384_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_384_proj_to_affine_12(t, tmp); + + XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_384)); + /* 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)); + + for (i=1; i<4; i++) { + sp_384_proj_point_dbl_n_12(t, 96, tmp); + sp_384_proj_to_affine_12(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<4; i++) { + XMEMCPY(s1->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_384_proj_point_add_qz1_12(t, s1, s2, tmp); + sp_384_proj_to_affine_12(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_384_point_free_12(s2, 0, heap); + sp_384_point_free_12(s1, 0, heap); + sp_384_point_free_12( 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 coordinates. + * + * 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_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 rtd; + sp_point_384 pd; + sp_digit td[2 * 12 * 6]; +#endif + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_384_point_new_12(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + y = 0; + for (j=0,x=95; j<4; j++,x+=96) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=94; i>=0; i--) { + y = 0; + for (j=0,x=i; j<4; j++,x+=96) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + + sp_384_proj_point_dbl_12(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 = !y; + sp_384_proj_point_add_qz1_12(rt, rt, p, t); + } + + if (map != 0) { + sp_384_map_12(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, heap); + sp_384_point_free_12(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_384_t { + sp_digit x[12]; + sp_digit y[12]; + sp_table_entry_384 table[16]; + uint32_t cnt; + int set; +} sp_cache_384_t; + +static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_384_last = -1; +static THREAD_LS_T int sp_cache_384_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_384 = 0; + static wolfSSL_Mutex sp_cache_384_lock; +#endif + +static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_384_inited == 0) { + for (i=0; ix, sp_cache_384[i].x) & + sp_384_cmp_equal_12(g->y, sp_cache_384[i].y)) { + sp_cache_384[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_384_last + 1) % FP_ENTRIES; + for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_384[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_384_last) { + least = sp_cache_384[0].cnt; + for (j=1; jx, sizeof(sp_cache_384[i].x)); + XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y)); + sp_cache_384[i].set = 1; + sp_cache_384[i].cnt = 1; + } + + *cache = &sp_cache_384[i]; + sp_cache_384_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_384_ecc_mulmod_fast_12(r, g, k, map, heap); +#else + sp_digit tmp[2 * 12 * 7]; + sp_cache_384_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_384 == 0) { + wc_InitMutex(&sp_cache_384_lock); + initCacheMutex_384 = 1; + } + if (wc_LockMutex(&sp_cache_384_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_384(g, &cache); + if (cache->cnt == 2) + sp_384_gen_stripe_table_12(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_384_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_384_ecc_mulmod_fast_12(r, g, k, map, heap); + } + else { + err = sp_384_ecc_mulmod_stripe_12(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#else +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temporary data. + * heap Heap to use for allocation. + */ +static int sp_384_gen_stripe_table_12(const sp_point_384* a, + sp_table_entry_384* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td, s1d, s2d; +#endif + sp_point_384* t; + sp_point_384* s1 = NULL; + sp_point_384* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_384_point_new_12(heap, td, t); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->x, a->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->y, a->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_12(t->z, a->z, p384_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_384_proj_to_affine_12(t, tmp); + + XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_384)); + /* 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)); + + for (i=1; i<8; i++) { + sp_384_proj_point_dbl_n_12(t, 48, tmp); + sp_384_proj_to_affine_12(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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_384_proj_point_add_qz1_12(t, s1, s2, tmp); + sp_384_proj_to_affine_12(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_384_point_free_12(s2, 0, heap); + sp_384_point_free_12(s1, 0, heap); + sp_384_point_free_12( 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 coordinates. + * + * 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_384_ecc_mulmod_stripe_12(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 rtd; + sp_point_384 pd; + sp_digit td[2 * 12 * 6]; +#endif + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_384_point_new_12(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + y = 0; + for (j=0,x=47; j<8; j++,x+=48) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = !y; + for (i=46; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=48) { + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + } + + sp_384_proj_point_dbl_12(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 = !y; + sp_384_proj_point_add_qz1_12(rt, rt, p, t); + } + + if (map != 0) { + sp_384_map_12(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, heap); + sp_384_point_free_12(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_384_t { + sp_digit x[12]; + sp_digit y[12]; + sp_table_entry_384 table[256]; + uint32_t cnt; + int set; +} sp_cache_384_t; + +static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_384_last = -1; +static THREAD_LS_T int sp_cache_384_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_384 = 0; + static wolfSSL_Mutex sp_cache_384_lock; +#endif + +static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_384_inited == 0) { + for (i=0; ix, sp_cache_384[i].x) & + sp_384_cmp_equal_12(g->y, sp_cache_384[i].y)) { + sp_cache_384[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_384_last + 1) % FP_ENTRIES; + for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_384[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_384_last) { + least = sp_cache_384[0].cnt; + for (j=1; jx, sizeof(sp_cache_384[i].x)); + XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y)); + sp_cache_384[i].set = 1; + sp_cache_384[i].cnt = 1; + } + + *cache = &sp_cache_384[i]; + sp_cache_384_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_12(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_384_ecc_mulmod_fast_12(r, g, k, map, heap); +#else + sp_digit tmp[2 * 12 * 7]; + sp_cache_384_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_384 == 0) { + wc_InitMutex(&sp_cache_384_lock); + initCacheMutex_384 = 1; + } + if (wc_LockMutex(&sp_cache_384_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_384(g, &cache); + if (cache->cnt == 2) + sp_384_gen_stripe_table_12(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_384_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_384_ecc_mulmod_fast_12(r, g, k, map, heap); + } + else { + err = sp_384_ecc_mulmod_stripe_12(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[12]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_384_point_new_12(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 12, km); + sp_384_point_from_ecc_point_12(point, gm); + + err = sp_384_ecc_mulmod_12(point, point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_12(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static const sp_table_entry_384 p384_table[16] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x49c0b528,0x3dd07566,0xa0d6ce38,0x20e378e2,0x541b4d6e,0x879c3afc, + 0x59a30eff,0x64548684,0x614ede2b,0x812ff723,0x299e1513,0x4d3aadc2 }, + { 0x4b03a4fe,0x23043dad,0x7bb4a9ac,0xa1bfa8bf,0x2e83b050,0x8bade756, + 0x68f4ffd9,0xc6c35219,0x3969a840,0xdd800226,0x5a15c5e9,0x2b78abc2 } }, + /* 2 */ + { { 0xf26feef9,0x24480c57,0x3a0e1240,0xc31a2694,0x273e2bc7,0x735002c3, + 0x3ef1ed4c,0x8c42e9c5,0x7f4948e8,0x028babf6,0x8a978632,0x6a502f43 }, + { 0xb74536fe,0xf5f13a46,0xd8a9f0eb,0x1d218bab,0x37232768,0x30f36bcc, + 0x576e8c18,0xc5317b31,0x9bbcb766,0xef1d57a6,0xb3e3d4dc,0x917c4930 } }, + /* 3 */ + { { 0xe349ddd0,0x11426e2e,0x9b2fc250,0x9f117ef9,0xec0174a6,0xff36b480, + 0x18458466,0x4f4bde76,0x05806049,0x2f2edb6d,0x19dfca92,0x8adc75d1 }, + { 0xb7d5a7ce,0xa619d097,0xa34411e9,0x874275e5,0x0da4b4ef,0x5403e047, + 0x77901d8f,0x2ebaafd9,0xa747170f,0x5e63ebce,0x7f9d8036,0x12a36944 } }, + /* 4 */ + { { 0x2f9fbe67,0x378205de,0x7f728e44,0xc4afcb83,0x682e00f1,0xdbcec06c, + 0x114d5423,0xf2a145c3,0x7a52463e,0xa01d9874,0x7d717b0a,0xfc0935b1 }, + { 0xd4d01f95,0x9653bc4f,0x9560ad34,0x9aa83ea8,0xaf8e3f3f,0xf77943dc, + 0xe86fe16e,0x70774a10,0xbf9ffdcf,0x6b62e6f1,0x588745c9,0x8a72f39e } }, + /* 5 */ + { { 0x2341c342,0x73ade4da,0xea704422,0xdd326e54,0x3741cef3,0x336c7d98, + 0x59e61549,0x1eafa00d,0xbd9a3efd,0xcd3ed892,0xc5c6c7e4,0x03faf26c }, + { 0x3045f8ac,0x087e2fcf,0x174f1e73,0x14a65532,0xfe0af9a7,0x2cf84f28, + 0x2cdc935b,0xddfd7a84,0x6929c895,0x4c0f117b,0x4c8bcfcc,0x356572d6 } }, + /* 6 */ + { { 0x3f3b236f,0xfab08607,0x81e221da,0x19e9d41d,0x3927b428,0xf3f6571e, + 0x7550f1f6,0x4348a933,0xa85e62f0,0x7167b996,0x7f5452bf,0x62d43759 }, + { 0xf2955926,0xd85feb9e,0x6df78353,0x440a561f,0x9ca36b59,0x389668ec, + 0xa22da016,0x052bf1a1,0xf6093254,0xbdfbff72,0xe22209f3,0x94e50f28 } }, + /* 7 */ + { { 0x3062e8af,0x90b2e5b3,0xe8a3d369,0xa8572375,0x201db7b1,0x3fe1b00b, + 0xee651aa2,0xe926def0,0xb9b10ad7,0x6542c9be,0xa2fcbe74,0x098e309b }, + { 0xfff1d63f,0x779deeb3,0x20bfd374,0x23d0e80a,0x8768f797,0x8452bb3b, + 0x1f952856,0xcf75bb4d,0x29ea3faa,0x8fe6b400,0x81373a53,0x12bd3e40 } }, + /* 8 */ + { { 0x16973cf4,0x070d34e1,0x7e4f34f7,0x20aee08b,0x5eb8ad29,0x269af9b9, + 0xa6a45dda,0xdde0a036,0x63df41e0,0xa18b528e,0xa260df2a,0x03cc71b2 }, + { 0xa06b1dd7,0x24a6770a,0x9d2675d3,0x5bfa9c11,0x96844432,0x73c1e2a1, + 0x131a6cf0,0x3660558d,0x2ee79454,0xb0289c83,0xc6d8ddcd,0xa6aefb01 } }, + /* 9 */ + { { 0x01ab5245,0xba1464b4,0xc48d93ff,0x9b8d0b6d,0x93ad272c,0x939867dc, + 0xae9fdc77,0xbebe085e,0x894ea8bd,0x73ae5103,0x39ac22e1,0x740fc89a }, + { 0x28e23b23,0x5e28b0a3,0xe13104d0,0x2352722e,0xb0a2640d,0xf4667a18, + 0x49bb37c3,0xac74a72e,0xe81e183a,0x79f734f0,0x3fd9c0eb,0xbffe5b6c } }, + /* 10 */ + { { 0x00623f3b,0x03cf2922,0x5f29ebff,0x095c7111,0x80aa6823,0x42d72247, + 0x7458c0b0,0x044c7ba1,0x0959ec20,0xca62f7ef,0xf8ca929f,0x40ae2ab7 }, + { 0xa927b102,0xb8c5377a,0xdc031771,0x398a86a0,0xc216a406,0x04908f9d, + 0x918d3300,0xb423a73a,0xe0b94739,0x634b0ff1,0x2d69f697,0xe29de725 } }, + /* 11 */ + { { 0x8435af04,0x744d1400,0xfec192da,0x5f255b1d,0x336dc542,0x1f17dc12, + 0x636a68a8,0x5c90c2a7,0x7704ca1e,0x960c9eb7,0x6fb3d65a,0x9de8cf1e }, + { 0x511d3d06,0xc60fee0d,0xf9eb52c7,0x466e2313,0x206b0914,0x743c0f5f, + 0x2191aa4d,0x42f55bac,0xffebdbc2,0xcefc7c8f,0xe6e8ed1c,0xd4fa6081 } }, + /* 12 */ + { { 0x98683186,0x867db639,0xddcc4ea9,0xfb5cf424,0xd4f0e7bd,0xcc9a7ffe, + 0x7a779f7e,0x7c57f71c,0xd6b25ef2,0x90774079,0xb4081680,0x90eae903 }, + { 0x0ee1fceb,0xdf2aae5e,0xe86c1a1f,0x3ff1da24,0xca193edf,0x80f587d6, + 0xdc9b9d6a,0xa5695523,0x85920303,0x7b840900,0xba6dbdef,0x1efa4dfc } }, + /* 13 */ + { { 0xe0540015,0xfbd838f9,0xc39077dc,0x2c323946,0xad619124,0x8b1fb9e6, + 0x0ca62ea8,0x9612440c,0x2dbe00ff,0x9ad9b52c,0xae197643,0xf52abaa1 }, + { 0x2cac32ad,0xd0e89894,0x62a98f91,0xdfb79e42,0x276f55cb,0x65452ecf, + 0x7ad23e12,0xdb1ac0d2,0xde4986f0,0xf68c5f6a,0x82ce327d,0x389ac37b } }, + /* 14 */ + { { 0xb8a9e8c9,0xcd96866d,0x5bb8091e,0xa11963b8,0x045b3cd2,0xc7f90d53, + 0x80f36504,0x755a72b5,0x21d3751c,0x46f8b399,0x53c193de,0x4bffdc91 }, + { 0xb89554e7,0xcd15c049,0xf7a26be6,0x353c6754,0xbd41d970,0x79602370, + 0x12b176c0,0xde16470b,0x40c8809d,0x56ba1175,0xe435fb1e,0xe2db35c3 } }, + /* 15 */ + { { 0x6328e33f,0xd71e4aab,0xaf8136d1,0x5486782b,0x86d57231,0x07a4995f, + 0x1651a968,0xf1f0a5bd,0x76803b6d,0xa5dc5b24,0x42dda935,0x5c587cbc }, + { 0xbae8b4c0,0x2b6cdb32,0xb1331138,0x66d1598b,0x5d7e9614,0x4a23b2d2, + 0x74a8c05d,0x93e402a6,0xda7ce82e,0x45ac94e6,0xe463d465,0xeb9f8281 } }, +}; + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + return sp_384_ecc_mulmod_stripe_12(r, &p384_base, p384_table, + k, map, heap); +} + +#else +static const sp_table_entry_384 p384_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x49c0b528,0x3dd07566,0xa0d6ce38,0x20e378e2,0x541b4d6e,0x879c3afc, + 0x59a30eff,0x64548684,0x614ede2b,0x812ff723,0x299e1513,0x4d3aadc2 }, + { 0x4b03a4fe,0x23043dad,0x7bb4a9ac,0xa1bfa8bf,0x2e83b050,0x8bade756, + 0x68f4ffd9,0xc6c35219,0x3969a840,0xdd800226,0x5a15c5e9,0x2b78abc2 } }, + /* 2 */ + { { 0x2b0c535b,0x29864753,0x70506296,0x90dd6953,0x216ab9ac,0x038cd6b4, + 0xbe12d76a,0x3df9b7b7,0x5f347bdb,0x13f4d978,0x13e94489,0x222c5c9c }, + { 0x2680dc64,0x5f8e796f,0x58352417,0x120e7cb7,0xd10740b8,0x254b5d8a, + 0x5337dee6,0xc38b8efb,0x94f02247,0xf688c2e1,0x6c25bc4c,0x7b5c75f3 } }, + /* 3 */ + { { 0x9edffea5,0xe26a3cc3,0x37d7e9fc,0x35bbfd1c,0x9bde3ef6,0xf0e7700d, + 0x1a538f5a,0x0380eb47,0x05bf9eb3,0x2e9da8bb,0x1a460c3e,0xdbb93c73 }, + { 0xf526b605,0x37dba260,0xfd785537,0x95d4978e,0xed72a04a,0x24ed793a, + 0x76005b1a,0x26948377,0x9e681f82,0x99f557b9,0xd64954ef,0xae5f9557 } }, + /* 4 */ + { { 0xf26feef9,0x24480c57,0x3a0e1240,0xc31a2694,0x273e2bc7,0x735002c3, + 0x3ef1ed4c,0x8c42e9c5,0x7f4948e8,0x028babf6,0x8a978632,0x6a502f43 }, + { 0xb74536fe,0xf5f13a46,0xd8a9f0eb,0x1d218bab,0x37232768,0x30f36bcc, + 0x576e8c18,0xc5317b31,0x9bbcb766,0xef1d57a6,0xb3e3d4dc,0x917c4930 } }, + /* 5 */ + { { 0xe349ddd0,0x11426e2e,0x9b2fc250,0x9f117ef9,0xec0174a6,0xff36b480, + 0x18458466,0x4f4bde76,0x05806049,0x2f2edb6d,0x19dfca92,0x8adc75d1 }, + { 0xb7d5a7ce,0xa619d097,0xa34411e9,0x874275e5,0x0da4b4ef,0x5403e047, + 0x77901d8f,0x2ebaafd9,0xa747170f,0x5e63ebce,0x7f9d8036,0x12a36944 } }, + /* 6 */ + { { 0x4fc52870,0x28f9c07a,0x1a53a961,0xce0b3748,0x0e1828d9,0xd550fa18, + 0x6adb225a,0xa24abaf7,0x6e58a348,0xd11ed0a5,0x948acb62,0xf3d811e6 }, + { 0x4c61ed22,0x8618dd77,0x80b47c9d,0x0bb747f9,0xde6b8559,0x22bf796f, + 0x680a21e9,0xfdfd1c6d,0x2af2c9dd,0xc0db1577,0xc1e90f3d,0xa09379e6 } }, + /* 7 */ + { { 0xe085c629,0x386c66ef,0x095bc89a,0x5fc2a461,0x203f4b41,0x1353d631, + 0x7e4bd8f5,0x7ca1972b,0xa7df8ce9,0xb077380a,0xee7e4ea3,0xd8a90389 }, + { 0xe7b14461,0x1bc74dc7,0x0c9c4f78,0xdc2cb014,0x84ef0a10,0x52b4b3a6, + 0x20327fe2,0xbde6ea5d,0x660f9615,0xb71ec435,0xb8ad8173,0xeede5a04 } }, + /* 8 */ + { { 0x893b9a2d,0x5584cbb3,0x00850c5d,0x820c660b,0x7df2d43d,0x4126d826, + 0x0109e801,0xdd5bbbf0,0x38172f1c,0x85b92ee3,0xf31430d9,0x609d4f93 }, + { 0xeadaf9d6,0x1e059a07,0x0f125fb0,0x70e6536c,0x560f20e7,0xd6220751, + 0x7aaf3a9a,0xa59489ae,0x64bae14e,0x7b70e2f6,0x76d08249,0x0dd03701 } }, + /* 9 */ + { { 0x8510521f,0x4cc13be8,0xf724cc17,0x87315ba9,0x353dc263,0xb49d83bb, + 0x0c279257,0x8b677efe,0xc93c9537,0x510a1c1c,0xa4702c99,0x33e30cd8 }, + { 0x2208353f,0xf0ffc89d,0xced42b2b,0x0170fa8d,0x26e2a5f5,0x090851ed, + 0xecb52c96,0x81276455,0x7fe1adf4,0x0646c4e1,0xb0868eab,0x513f047e } }, + /* 10 */ + { { 0xdf5bdf53,0xc07611f4,0x58b11a6d,0x45d331a7,0x1c4ee394,0x58965daf, + 0x5a5878d1,0xba8bebe7,0x82dd3025,0xaecc0a18,0xa923eb8b,0xcf2a3899 }, + { 0xd24fd048,0xf98c9281,0x8bbb025d,0x841bfb59,0xc9ab9d53,0xb8ddf8ce, + 0x7fef044e,0x538a4cb6,0x23236662,0x092ac21f,0x0b66f065,0xa919d385 } }, + /* 11 */ + { { 0x85d480d8,0x3db03b40,0x1b287a7d,0x8cd9f479,0x4a8f3bae,0x8f24dc75, + 0x3db41892,0x482eb800,0x9c56e0f5,0x38bf9eb3,0x9a91dc6f,0x8b977320 }, + { 0x7209cfc2,0xa31b05b2,0x05b2db70,0x4c49bf85,0xd619527b,0x56462498, + 0x1fac51ba,0x3fe51039,0xab4b8342,0xfb04f55e,0x04c6eabf,0xc07c10dc } }, + /* 12 */ + { { 0xdb32f048,0xad22fe4c,0x475ed6df,0x5f23bf91,0xaa66b6cb,0xa50ce0c0, + 0xf03405c0,0xdf627a89,0xf95e2d6a,0x3674837d,0xba42e64e,0x081c95b6 }, + { 0xe71d6ceb,0xeba3e036,0x6c6b0271,0xb45bcccf,0x0684701d,0x67b47e63, + 0xe712523f,0x60f8f942,0x5cd47adc,0x82423472,0x87649cbb,0x83027d79 } }, + /* 13 */ + { { 0x3615b0b8,0xb3929ea6,0xa54dac41,0xb41441fd,0xb5b6a368,0x8995d556, + 0x167ef05e,0xa80d4529,0x6d25a27f,0xf6bcb4a1,0x7bd55b68,0x210d6a4c }, + { 0x25351130,0xf3804abb,0x903e37eb,0x1d2df699,0x084c25c8,0x5f201efc, + 0xa1c68e91,0x31a28c87,0x563f62a5,0x81dad253,0xd6c415d4,0x5dd6de70 } }, + /* 14 */ + { { 0x846612ce,0x29f470fd,0xda18d997,0x986f3eec,0x2f34af86,0x6b84c161, + 0x46ddaf8b,0x5ef0a408,0xe49e795f,0x14405a00,0xaa2f7a37,0x5f491b16 }, + { 0xdb41b38d,0xc7f07ae4,0x18fbfcaa,0xef7d119e,0x14443b19,0x3a18e076, + 0x79a19926,0x4356841a,0xe2226fbe,0x91f4a91c,0x3cc88721,0xdc77248c } }, + /* 15 */ + { { 0xe4b1ec9d,0xd570ff1a,0xe7eef706,0x21d23e0e,0xca19e086,0x3cde40f4, + 0xcd4bb270,0x7d6523c4,0xbf13aa6c,0x16c1f06c,0xd14c4b60,0x5aa7245a }, + { 0x44b74de8,0x37f81467,0x620a934e,0x839e7a17,0xde8b1aa1,0xf74d14e8, + 0xf30d75e2,0x8789fa51,0xc81c261e,0x09b24052,0x33c565ee,0x654e2678 } }, + /* 16 */ + { { 0x2f9fbe67,0x378205de,0x7f728e44,0xc4afcb83,0x682e00f1,0xdbcec06c, + 0x114d5423,0xf2a145c3,0x7a52463e,0xa01d9874,0x7d717b0a,0xfc0935b1 }, + { 0xd4d01f95,0x9653bc4f,0x9560ad34,0x9aa83ea8,0xaf8e3f3f,0xf77943dc, + 0xe86fe16e,0x70774a10,0xbf9ffdcf,0x6b62e6f1,0x588745c9,0x8a72f39e } }, + /* 17 */ + { { 0x2341c342,0x73ade4da,0xea704422,0xdd326e54,0x3741cef3,0x336c7d98, + 0x59e61549,0x1eafa00d,0xbd9a3efd,0xcd3ed892,0xc5c6c7e4,0x03faf26c }, + { 0x3045f8ac,0x087e2fcf,0x174f1e73,0x14a65532,0xfe0af9a7,0x2cf84f28, + 0x2cdc935b,0xddfd7a84,0x6929c895,0x4c0f117b,0x4c8bcfcc,0x356572d6 } }, + /* 18 */ + { { 0x7d8c1bba,0x7ecbac01,0x90b0f3d5,0x6058f9c3,0xf6197d0f,0xaee116e3, + 0x4033b128,0xc4dd7068,0xc209b983,0xf084dba6,0x831dbc4a,0x97c7c2cf }, + { 0xf96010e8,0x2f4e61dd,0x529faa17,0xd97e4e20,0x69d37f20,0x4ee66660, + 0x3d366d72,0xccc139ed,0x13488e0f,0x690b6ee2,0xf3a6d533,0x7cad1dc5 } }, + /* 19 */ + { { 0xda57a41f,0x660a9a81,0xec0039b6,0xe74a0412,0x5e1dad15,0x42343c6b, + 0x46681d4c,0x284f3ff5,0x63749e89,0xb51087f1,0x6f9f2f13,0x070f23cc }, + { 0x5d186e14,0x542211da,0xfddb0dff,0x84748f37,0xdb1f4180,0x41a3aab4, + 0xa6402d0e,0x25ed667b,0x02f58355,0x2f2924a9,0xfa44a689,0x5844ee7c } }, + /* 20 */ + { { 0x3f3b236f,0xfab08607,0x81e221da,0x19e9d41d,0x3927b428,0xf3f6571e, + 0x7550f1f6,0x4348a933,0xa85e62f0,0x7167b996,0x7f5452bf,0x62d43759 }, + { 0xf2955926,0xd85feb9e,0x6df78353,0x440a561f,0x9ca36b59,0x389668ec, + 0xa22da016,0x052bf1a1,0xf6093254,0xbdfbff72,0xe22209f3,0x94e50f28 } }, + /* 21 */ + { { 0x3062e8af,0x90b2e5b3,0xe8a3d369,0xa8572375,0x201db7b1,0x3fe1b00b, + 0xee651aa2,0xe926def0,0xb9b10ad7,0x6542c9be,0xa2fcbe74,0x098e309b }, + { 0xfff1d63f,0x779deeb3,0x20bfd374,0x23d0e80a,0x8768f797,0x8452bb3b, + 0x1f952856,0xcf75bb4d,0x29ea3faa,0x8fe6b400,0x81373a53,0x12bd3e40 } }, + /* 22 */ + { { 0x104cbba5,0xc023780d,0xfa35dd4c,0x6207e747,0x1ca9b6a3,0x35c23928, + 0x97987b10,0x4ff19be8,0x8022eee8,0xb8476bbf,0xd3bbe74d,0xaa0a4a14 }, + { 0x187d4543,0x20f94331,0x79f6e066,0x32153870,0xac7e82e1,0x83b0f74e, + 0x828f06ab,0xa7748ba2,0xc26ef35f,0xc5f0298a,0x8e9a7dbd,0x0f0c5070 } }, + /* 23 */ + { { 0xdef029dd,0x0c5c244c,0x850661b8,0x3dabc687,0xfe11d981,0x9992b865, + 0x6274dbad,0xe9801b8f,0x098da242,0xe54e6319,0x91a53d08,0x9929a91a }, + { 0x35285887,0x37bffd72,0xf1418102,0xbc759425,0xfd2e6e20,0x9280cc35, + 0xfbc42ee5,0x735c600c,0x8837619a,0xb7ad2864,0xa778c57b,0xa3627231 } }, + /* 24 */ + { { 0x91361ed8,0xae799b5c,0x6c63366c,0x47d71b75,0x1b265a6a,0x54cdd521, + 0x98d77b74,0xe0215a59,0xbab29db0,0x4424d9b7,0x7fd9e536,0x8b0ffacc }, + { 0x37b5d9ef,0x46d85d12,0xbfa91747,0x5b106d62,0x5f99ba2d,0xed0479f8, + 0x1d104de4,0x0e6f3923,0x25e8983f,0x83a84c84,0xf8105a70,0xa9507e0a } }, + /* 25 */ + { { 0x14cf381c,0xf6c68a6e,0xc22e31cc,0xaf9d27bd,0xaa8a5ccb,0x23568d4d, + 0xe338e4d2,0xe431eec0,0x8f52ad1f,0xf1a828fe,0xe86acd80,0xdb6a0579 }, + { 0x4507832a,0x2885672e,0x887e5289,0x73fc275f,0x05610d08,0x65f80278, + 0x075ff5b0,0x8d9b4554,0x09f712b5,0x3a8e8fb1,0x2ebe9cf2,0x39f0ac86 } }, + /* 26 */ + { { 0x4c52edf5,0xd8fabf78,0xa589ae53,0xdcd737e5,0xd791ab17,0x94918bf0, + 0xbcff06c9,0xb5fbd956,0xdca46d45,0xf6d3032e,0x41a3e486,0x2cdff7e1 }, + { 0x61f47ec8,0x6674b3ba,0xeef84608,0x8a882163,0x4c687f90,0xa257c705, + 0xf6cdf227,0xe30cb2ed,0x7f6ea846,0x2c4c64ca,0xcc6bcd3c,0x186fa17c } }, + /* 27 */ + { { 0x1dfcb91e,0x48a3f536,0x646d358a,0x83595e13,0x91128798,0xbd15827b, + 0x2187757a,0x3ce612b8,0x61bd7372,0x873150a1,0xb662f568,0xf4684530 }, + { 0x401896f6,0x8833950b,0x77f3e090,0xe11cb89a,0x48e7f4a5,0xb2f12cac, + 0xf606677e,0x313dd769,0x16579f93,0xfdcf08b3,0x46b8f22b,0x6429cec9 } }, + /* 28 */ + { { 0xbb75f9a4,0x4984dd54,0x29d3b570,0x4aef06b9,0x3d6e4c1e,0xb5f84ca2, + 0xb083ef35,0x24c61c11,0x392ca9ff,0xce4a7392,0x6730a800,0x865d6517 }, + { 0x722b4a2b,0xca3dfe76,0x7b083e0e,0x12c04bf9,0x1b86b8a5,0x803ce5b5, + 0x6a7e3e0c,0x3fc7632d,0xc81adbe4,0xc89970c2,0x120e16b1,0x3cbcd3ad } }, + /* 29 */ + { { 0xec30ce93,0xfbfb4cc7,0xb72720a2,0x10ed6c7d,0x47b55500,0xec675bf7, + 0x333ff7c3,0x90725903,0x5075bfc0,0xc7c3973e,0x07acf31b,0xb049ecb0 }, + { 0x4f58839c,0xb4076eaf,0xa2b05e4f,0x101896da,0xab40c66e,0x3f6033b0, + 0xc8d864ba,0x19ee9eeb,0x47bf6d2a,0xeb6cf155,0xf826477d,0x8e5a9663 } }, + /* 30 */ + { { 0xf7fbd5e1,0x69e62fdd,0x76912b1d,0x38ecfe54,0xd1da3bfb,0x845a3d56, + 0x1c86f0d4,0x0494950e,0x3bc36ce8,0x83cadbf9,0x4fccc8d1,0x41fce572 }, + { 0x8332c144,0x05f939c2,0x0871e46e,0xb17f248b,0x66e8aff6,0x3d8534e2, + 0x3b85c629,0x1d06f1dc,0xa3131b73,0xdb06a32e,0x8b3f64e5,0xf295184d } }, + /* 31 */ + { { 0x36ddc103,0xd9653ff7,0x95ef606f,0x25f43e37,0xfe06dce8,0x09e301fc, + 0x30b6eebf,0x85af2341,0x0ff56b20,0x79b12b53,0xfe9a3c6b,0x9b4fb499 }, + { 0x51d27ac2,0x0154f892,0x56ca5389,0xd33167e3,0xafc065a6,0x7828ec1f, + 0x7f746c9b,0x0959a258,0x0c44f837,0xb18f1be3,0xc4132fdb,0xa7946117 } }, + /* 32 */ + { { 0x5e3c647b,0xc0426b77,0x8cf05348,0xbfcbd939,0x172c0d3d,0x31d312e3, + 0xee754737,0x5f49fde6,0x6da7ee61,0x895530f0,0xe8b3a5fb,0xcf281b0a }, + { 0x41b8a543,0xfd149735,0x3080dd30,0x41a625a7,0x653908cf,0xe2baae07, + 0xba02a278,0xc3d01436,0x7b21b8f8,0xa0d0222e,0xd7ec1297,0xfdc270e9 } }, + /* 33 */ + { { 0xbc7f41d6,0x00873c0c,0x1b7ad641,0xd976113e,0x238443fb,0x2a536ff4, + 0x41e62e45,0x030d00e2,0x5f545fc6,0x532e9867,0x8e91208c,0xcd033108 }, + { 0x9797612c,0xd1a04c99,0xeea674e2,0xd4393e02,0xe19742a1,0xd56fa69e, + 0x85f0590e,0xdd2ab480,0x48a2243d,0xa5cefc52,0x54383f41,0x48cc67b6 } }, + /* 34 */ + { { 0xfc14ab48,0x4e50430e,0x26706a74,0x195b7f4f,0xcc881ff6,0x2fe8a228, + 0xd945013d,0xb1b968e2,0x4b92162b,0x936aa579,0x364e754a,0x4fb766b7 }, + { 0x31e1ff7f,0x13f93bca,0xce4f2691,0x696eb5ca,0xa2b09e02,0xff754bf8, + 0xe58e3ff8,0x58f13c9c,0x1678c0b0,0xb757346f,0xa86692b3,0xd54200db } }, + /* 35 */ + { { 0x6dda1265,0x9a030bbd,0xe89718dd,0xf7b4f3fc,0x936065b8,0xa6a4931f, + 0x5f72241c,0xbce72d87,0x65775857,0x6cbb51cb,0x4e993675,0xc7161815 }, + { 0x2ee32189,0xe81a0f79,0x277dc0b2,0xef2fab26,0xb71f469f,0x9e64f6fe, + 0xdfdaf859,0xb448ce33,0xbe6b5df1,0x3f5c1c4c,0x1de45f7b,0xfb8dfb00 } }, + /* 36 */ + { { 0x4d5bb921,0xc7345fa7,0x4d2b667e,0x5c7e04be,0x282d7a3e,0x47ed3a80, + 0x7e47b2a4,0x5c2777f8,0x08488e2e,0x89b3b100,0xb2eb5b45,0x9aad77c2 }, + { 0xdaac34ae,0xd681bca7,0x26afb326,0x2452e4e5,0x41a1ee14,0x0c887924, + 0xc2407ade,0x743b04d4,0xfc17a2ac,0xcb5e999b,0x4a701a06,0x4dca2f82 } }, + /* 37 */ + { { 0x1127bc1a,0x68e31ca6,0x17ead3be,0xa3edd59b,0xe25f5a15,0x67b6b645, + 0xa420e15e,0x76221794,0x4b1e872e,0x794fd83b,0xb2dece1b,0x7cab3f03 }, + { 0xca9b3586,0x7119bf15,0x4d250bd7,0xa5545924,0xcc6bcf24,0x173633ea, + 0xb1b6f884,0x9bd308c2,0x447d38c3,0x3bae06f5,0xf341fe1c,0x54dcc135 } }, + /* 38 */ + { { 0x943caf0d,0x56d3598d,0x225ff133,0xce044ea9,0x563fadea,0x9edf6a7c, + 0x73e8dc27,0x632eb944,0x3190dcab,0x814b467e,0x6dbb1e31,0x2d4f4f31 }, + { 0xa143b7ca,0x8d69811c,0xde7cf950,0x4ec1ac32,0x37b5fe82,0x223ab5fd, + 0x9390f1d9,0xe82616e4,0x75804610,0xabff4b20,0x875b08f0,0x11b9be15 } }, + /* 39 */ + { { 0x3bbe682c,0x4ae31a3d,0x74eef2dd,0xbc7c5d26,0x3c47dd40,0x92afd10a, + 0xc14ab9e1,0xec7e0a3b,0xb2e495e4,0x6a6c3dd1,0x309bcd85,0x085ee5e9 }, + { 0x8c2e67fd,0xf381a908,0xe261eaf2,0x32083a80,0x96deee15,0x0fcd6a49, + 0x5e524c79,0xe3b8fb03,0x1d5b08b9,0x8dc360d9,0x7f26719f,0x3a06e2c8 } }, + /* 40 */ + { { 0x7237cac0,0x5cd9f5a8,0x43586794,0x93f0b59d,0xe94f6c4e,0x4384a764, + 0xb62782d3,0x8304ed2b,0xcde06015,0x0b8db8b3,0x5dbe190f,0x4336dd53 }, + { 0x92ab473a,0x57443553,0xbe5ed046,0x031c7275,0x21909aa4,0x3e78678c, + 0x99202ddb,0x4ab7e04f,0x6977e635,0x2648d206,0x093198be,0xd427d184 } }, + /* 41 */ + { { 0x0f9b5a31,0x822848f5,0xbaadb62a,0xbb003468,0x3357559c,0x233a0472, + 0x79aee843,0x49ef6880,0xaeb9e1e3,0xa89867a0,0x1f6f9a55,0xc151931b }, + { 0xad74251e,0xd264eb0b,0x4abf295e,0x37b9b263,0x04960d10,0xb600921b, + 0x4da77dc0,0x0de53dbc,0xd2b18697,0x01d9bab3,0xf7156ddf,0xad54ec7a } }, + /* 42 */ + { { 0x79efdc58,0x8e74dc35,0x4ff68ddb,0x456bd369,0xd32096a5,0x724e74cc, + 0x386783d0,0xe41cff42,0x7c70d8a4,0xa04c7f21,0xe61a19a2,0x41199d2f }, + { 0x29c05dd2,0xd389a3e0,0xe7e3fda9,0x535f2a6b,0x7c2b4df8,0x26ecf72d, + 0xfe745294,0x678275f4,0x9d23f519,0x6319c9cc,0x88048fc4,0x1e05a02d } }, + /* 43 */ + { { 0xd4d5ffe8,0x75cc8e2e,0xdbea17f2,0xf8bb4896,0xcee3cb4a,0x35059790, + 0xa47c6165,0x4c06ee85,0x92935d2f,0xf98fff25,0x32ffd7c7,0x34c4a572 }, + { 0xea0376a2,0xc4b14806,0x4f115e02,0x2ea5e750,0x1e55d7c0,0x532d76e2, + 0xf31044da,0x68dc9411,0x71b77993,0x9272e465,0x93a8cfd5,0xadaa38bb } }, + /* 44 */ + { { 0x7d4ed72a,0x4bf0c712,0xba1f79a3,0xda0e9264,0xf4c39ea4,0x48c0258b, + 0x2a715138,0xa5394ed8,0xbf06c660,0x4af511ce,0xec5c37cd,0xfcebceef }, + { 0x779ae8c1,0xf23b75aa,0xad1e606e,0xdeff59cc,0x22755c82,0xf3f526fd, + 0xbb32cefd,0x64c5ab44,0x915bdefd,0xa96e11a2,0x1143813e,0xab19746a } }, + /* 45 */ + { { 0xec837d7d,0x43c78585,0xb8ee0ba4,0xca5b6fbc,0xd5dbb5ee,0x34e924d9, + 0xbb4f1ca5,0x3f4fa104,0x398640f7,0x15458b72,0xd7f407ea,0x4231faa9 }, + { 0xf96e6896,0x53e0661e,0xd03b0f9d,0x554e4c69,0x9c7858d1,0xd4fcb07b, + 0x52cb04fa,0x7e952793,0x8974e7f7,0x5f5f1574,0x6b6d57c8,0x2e3fa558 } }, + /* 46 */ + { { 0x6a9951a8,0x42cd4803,0x42792ad0,0xa8b15b88,0xabb29a73,0x18e8bcf9, + 0x409933e8,0xbfd9a092,0xefb88dc4,0x760a3594,0x40724458,0x14418863 }, + { 0x99caedc7,0x162a56ee,0x91d101c9,0x8fb12ecd,0x393202da,0xea671967, + 0xa4ccd796,0x1aac8c4a,0x1cf185a8,0x7db05036,0x8cfd095a,0x0c9f86cd } }, + /* 47 */ + { { 0x10b2a556,0x9a728147,0x327b70b2,0x767ca964,0x5e3799b7,0x04ed9e12, + 0x22a3eb2a,0x6781d2dc,0x0d9450ac,0x5bd116eb,0xa7ebe08a,0xeccac1fc }, + { 0xdc2d6e94,0xde68444f,0x35ecf21b,0x3621f429,0x29e03a2c,0x14e2d543, + 0x7d3e7f0a,0x53e42cd5,0x73ed00b9,0xbba26c09,0xc57d2272,0x00297c39 } }, + /* 48 */ + { { 0xb8243a7d,0x3aaaab10,0x8fa58c5b,0x6eeef93e,0x9ae7f764,0xf866fca3, + 0x61ab04d3,0x64105a26,0x03945d66,0xa3578d8a,0x791b848c,0xb08cd3e4 }, + { 0x756d2411,0x45edc5f8,0xa755128c,0xd4a790d9,0x49e5f6a0,0xc2cf0963, + 0xf649beaa,0xc66d267d,0x8467039e,0x3ce6d968,0x42f7816f,0x50046c6b } }, + /* 49 */ + { { 0x66425043,0x92ae1602,0xf08db890,0x1ff66afd,0x8f162ce5,0x386f5a7f, + 0xfcf5598f,0x18d2dea0,0x1a8ca18e,0x78372b3a,0x8cd0e6f7,0xdf0d20eb }, + { 0x75bb4045,0x7edd5e1d,0xb96d94b7,0x252a47ce,0x2c626776,0xbdb29358, + 0x40dd1031,0x853c3943,0x7d5f47fd,0x9dc9becf,0xbae4044a,0x27c2302f } }, + /* 50 */ + { { 0x8f2d49ce,0x2d1d208a,0x162df0a2,0x0d91aa02,0x09a07f65,0x9c5cce87, + 0x84339012,0xdf07238b,0x419442cd,0x5028e2c8,0x72062aba,0x2dcbd358 }, + { 0xe4680967,0xb5fbc3cb,0x9f92d72c,0x2a7bc645,0x116c369d,0x806c76e1, + 0x3177e8d8,0x5c50677a,0x4569df57,0x753739eb,0x36c3f40b,0x2d481ef6 } }, + /* 51 */ + { { 0xfea1103e,0x1a2d39fd,0x95f81b17,0xeaae5592,0xf59b264a,0xdbd0aa18, + 0xcb592ee0,0x90c39c1a,0x9750cca3,0xdf62f80d,0xdf97cc6c,0xda4d8283 }, + { 0x1e201067,0x0a6dd346,0x69fb1f6b,0x1531f859,0x1d60121f,0x4895e552, + 0x4c041c91,0x0b21aab0,0xbcc1ccf8,0x9d896c46,0x3141bde7,0xd24da3b3 } }, + /* 52 */ + { { 0x53b0a354,0x575a0537,0x0c6ddcd8,0x392ff2f4,0x56157b94,0x0b8e8cff, + 0x3b1b80d1,0x073e57bd,0x3fedee15,0x2a75e0f0,0xaa8e6f19,0x752380e4 }, + { 0x6558ffe9,0x1f4e227c,0x19ec5415,0x3a348618,0xf7997085,0xab382d5e, + 0xddc46ac2,0x5e6deaff,0xfc8d094c,0xe5144078,0xf60e37c6,0xf674fe51 } }, + /* 53 */ + { { 0xaf63408f,0x6fb87ae5,0xcd75a737,0xa39c36a9,0xcf4c618d,0x7833313f, + 0xf034c88d,0xfbcd4482,0x39b35288,0x4469a761,0x66b5d9c9,0x77a711c5 }, + { 0x944f8d65,0x4a695dc7,0x161aaba8,0xe6da5f65,0x24601669,0x8654e9c3, + 0x28ae7491,0xbc8b93f5,0x8f5580d8,0x5f1d1e83,0xcea32cc8,0x8ccf9a1a } }, + /* 54 */ + { { 0x7196fee2,0x28ab110c,0x874c8945,0x75799d63,0x29aedadd,0xa2629348, + 0x2be88ff4,0x9714cc7b,0xd58d60d6,0xf71293cf,0x32a564e9,0xda6b6cb3 }, + { 0x3dd821c2,0xf43fddb1,0x90dd323d,0xf2f2785f,0x048489f8,0x91246419, + 0xd24c6749,0x61660f26,0xc803c15c,0x961d9e8c,0xfaadc4c9,0x631c6158 } }, + /* 55 */ + { { 0xfd752366,0xacf2ebe0,0x139be88b,0xb93c340e,0x0f20179e,0x98f66485, + 0xff1da785,0x14820254,0x4f85c16e,0x5278e276,0x7aab1913,0xa246ee45 }, + { 0x53763b33,0x43861eb4,0x45c0bc0d,0xc49f03fc,0xad6b1ea1,0xafff16bc, + 0x6fd49c99,0xce33908b,0xf7fde8c3,0x5c51e9bf,0xff142c5e,0x076a7a39 } }, + /* 56 */ + { { 0x9e338d10,0x04639dfe,0xf42b411b,0x8ee6996f,0xa875cef2,0x960461d1, + 0x95b4d0ba,0x1057b6d6,0xa906e0bc,0x27639252,0xe1c20f8a,0x2c19f09a }, + { 0xeef4c43d,0x5b8fc3f0,0x07a84aa9,0xe2e1b1a8,0x835d2bdb,0x5f455528, + 0x207132dd,0x0f4aee4d,0x3907f675,0xe9f8338c,0x0e0531f0,0x7a874dc9 } }, + /* 57 */ + { { 0x97c27050,0x84b22d45,0x59e70bf8,0xbd0b8df7,0x79738b9b,0xb4d67405, + 0xcd917c4f,0x47f4d5f5,0x13ce6e33,0x9099c4ce,0x521d0f8b,0x942bfd39 }, + { 0xa43b566d,0x5028f0f6,0x21bff7de,0xaf6e8669,0xc44232cd,0x83f6f856, + 0xf915069a,0x65680579,0xecfecb85,0xd12095a2,0xdb01ba16,0xcf7f06ae } }, + /* 58 */ + { { 0x8ef96c80,0x0f56e3c4,0x3ddb609c,0xd521f2b3,0x7dc1450d,0x2be94102, + 0x02a91fe2,0x2d21a071,0x1efa37de,0x2e6f74fa,0x156c28a1,0x9a9a90b8 }, + { 0x9dc7dfcb,0xc54ea9ea,0x2c2c1d62,0xc74e66fc,0x49d3e067,0x9f23f967, + 0x54dd38ad,0x1c7c3a46,0x5946cee3,0xc7005884,0x45cc045d,0x89856368 } }, + /* 59 */ + { { 0xfce73946,0x29da7cd4,0x23168563,0x8f697db5,0xcba92ec6,0x8e235e9c, + 0x9f91d3ea,0x55d4655f,0xaa50a6cd,0xf3689f23,0x21e6a1a0,0xdcf21c26 }, + { 0x61b818bf,0xcffbc82e,0xda47a243,0xc74a2f96,0x8bc1a0cf,0x234e980a, + 0x7929cb6d,0xf35fd6b5,0xefe17d6c,0x81468e12,0x58b2dafb,0xddea6ae5 } }, + /* 60 */ + { { 0x7e787b2e,0x294de887,0x39a9310d,0x258acc1f,0xac14265d,0x92d9714a, + 0x708b48a0,0x18b5591c,0xe1abbf71,0x27cc6bb0,0x568307b9,0xc0581fa3 }, + { 0xf24d4d58,0x9e0f58a3,0xe0ce2327,0xfebe9bb8,0x9d1be702,0x91fd6a41, + 0xfacac993,0x9a7d8a45,0x9e50d66d,0xabc0a08c,0x06498201,0x02c342f7 } }, + /* 61 */ + { { 0x157bdbc2,0xccd71407,0xad0e1605,0x72fa89c6,0xb92a015f,0xb1d3da2b, + 0xa0a3fe56,0x8ad9e7cd,0x24f06737,0x160edcbd,0x61275be6,0x79d4db33 }, + { 0x5f3497c4,0xd3d31fd9,0x04192fb0,0x8cafeaee,0x13a50af3,0xe13ca745, + 0x8c85aae5,0x18826167,0x9eb556ff,0xce06cea8,0xbdb549f3,0x2eef1995 } }, + /* 62 */ + { { 0x50596edc,0x8ed7d3eb,0x905243a2,0xaa359362,0xa4b6d02b,0xa212c2c2, + 0xc4fbec68,0x611fd727,0xb84f733d,0x8a0b8ff7,0x5f0daf0e,0xd85a6b90 }, + { 0xd4091cf7,0x60e899f5,0x2eff2768,0x4fef2b67,0x10c33964,0xc1f195cb, + 0x93626a8f,0x8275d369,0x0d6c840a,0xc77904f4,0x7a868acd,0x88d8b7fd } }, + /* 63 */ + { { 0x7bd98425,0x85f23723,0xc70b154e,0xd4463992,0x96687a2e,0xcbb00ee2, + 0xc83214fd,0x905fdbf7,0x13593684,0x2019d293,0xef51218e,0x0428c393 }, + { 0x981e909a,0x40c7623f,0x7be192da,0x92513385,0x4010907e,0x48fe480f, + 0x3120b459,0xdd7a187c,0xa1fd8f3c,0xc9d7702d,0xe358efc5,0x66e4753b } }, + /* 64 */ + { { 0x16973cf4,0x070d34e1,0x7e4f34f7,0x20aee08b,0x5eb8ad29,0x269af9b9, + 0xa6a45dda,0xdde0a036,0x63df41e0,0xa18b528e,0xa260df2a,0x03cc71b2 }, + { 0xa06b1dd7,0x24a6770a,0x9d2675d3,0x5bfa9c11,0x96844432,0x73c1e2a1, + 0x131a6cf0,0x3660558d,0x2ee79454,0xb0289c83,0xc6d8ddcd,0xa6aefb01 } }, + /* 65 */ + { { 0x01ab5245,0xba1464b4,0xc48d93ff,0x9b8d0b6d,0x93ad272c,0x939867dc, + 0xae9fdc77,0xbebe085e,0x894ea8bd,0x73ae5103,0x39ac22e1,0x740fc89a }, + { 0x28e23b23,0x5e28b0a3,0xe13104d0,0x2352722e,0xb0a2640d,0xf4667a18, + 0x49bb37c3,0xac74a72e,0xe81e183a,0x79f734f0,0x3fd9c0eb,0xbffe5b6c } }, + /* 66 */ + { { 0xc6a2123f,0xb1a358f5,0xfe28df6d,0x927b2d95,0xf199d2f9,0x89702753, + 0x1a3f82dc,0x0a73754c,0x777affe1,0x063d029d,0xdae6d34d,0x5439817e }, + { 0x6b8b83c4,0xf7979eef,0x9d945682,0x615cb214,0xc5e57eae,0x8f0e4fac, + 0x113047dd,0x042b89b8,0x93f36508,0x888356dc,0x5fd1f32f,0xbf008d18 } }, + /* 67 */ + { { 0x4e8068db,0x8012aa24,0xa5729a47,0xc72cc641,0x43f0691d,0x3c33df2c, + 0x1d92145f,0xfa057347,0xb97f7946,0xaefc0f2f,0x2f8121bf,0x813d75cb }, + { 0x4383bba6,0x05613c72,0xa4224b3f,0xa924ce70,0x5f2179a6,0xe59cecbe, + 0x79f62b61,0x78e2e8aa,0x53ad8079,0x3ac2cc3b,0xd8f4fa96,0x55518d71 } }, + /* 68 */ + { { 0x00623f3b,0x03cf2922,0x5f29ebff,0x095c7111,0x80aa6823,0x42d72247, + 0x7458c0b0,0x044c7ba1,0x0959ec20,0xca62f7ef,0xf8ca929f,0x40ae2ab7 }, + { 0xa927b102,0xb8c5377a,0xdc031771,0x398a86a0,0xc216a406,0x04908f9d, + 0x918d3300,0xb423a73a,0xe0b94739,0x634b0ff1,0x2d69f697,0xe29de725 } }, + /* 69 */ + { { 0x8435af04,0x744d1400,0xfec192da,0x5f255b1d,0x336dc542,0x1f17dc12, + 0x636a68a8,0x5c90c2a7,0x7704ca1e,0x960c9eb7,0x6fb3d65a,0x9de8cf1e }, + { 0x511d3d06,0xc60fee0d,0xf9eb52c7,0x466e2313,0x206b0914,0x743c0f5f, + 0x2191aa4d,0x42f55bac,0xffebdbc2,0xcefc7c8f,0xe6e8ed1c,0xd4fa6081 } }, + /* 70 */ + { { 0xb0ab9645,0xb5e405d3,0xd5f1f711,0xaeec7f98,0x585c2a6e,0x8ad42311, + 0x512c6944,0x045acb9e,0xa90db1c6,0xae106c4e,0x898e6563,0xb89f33d5 }, + { 0x7fed2ce4,0x43b07cd9,0xdd815b20,0xf9934e17,0x0a81a349,0x6778d4d5, + 0x52918061,0x9e616ade,0xd7e67112,0xfa06db06,0x88488091,0x1da23cf1 } }, + /* 71 */ + { { 0x42f2c4b5,0x821c46b3,0x66059e47,0x931513ef,0x66f50cd1,0x7030ae43, + 0x43e7b127,0x43b536c9,0x5fca5360,0x006258cf,0x6b557abf,0xe4e3ee79 }, + { 0x24c8b22f,0xbb6b3900,0xfcbf1054,0x2eb5e2c1,0x567492af,0x937b18c9, + 0xacf53957,0xf09432e4,0x1dbf3a56,0x585f5a9d,0xbe0887cf,0xf86751fd } }, + /* 72 */ + { { 0x9d10e0b2,0x157399cb,0x60dc51b7,0x1c0d5956,0x1f583090,0x1d496b8a, + 0x88590484,0x6658bc26,0x03213f28,0x88c08ab7,0x7ae58de4,0x8d2e0f73 }, + { 0x486cfee6,0x9b79bc95,0xe9e5bc57,0x036a26c7,0xcd8ae97a,0x1ad03601, + 0xff3a0494,0x06907f87,0x2c7eb584,0x078f4bbf,0x7e8d0a5a,0xe3731bf5 } }, + /* 73 */ + { { 0xe1cd0abe,0x72f2282b,0x87efefa2,0xd4f9015e,0x6c3834bd,0x9d189806, + 0xb8a29ced,0x9c8cdcc1,0xfee82ebc,0x0601b9f4,0x7206a756,0x371052bc }, + { 0x46f32562,0x76fa1092,0x17351bb4,0xdaad534c,0xb3636bb5,0xc3d64c37, + 0x45d54e00,0x038a8c51,0x32c09e7c,0x301e6180,0x95735151,0x9764eae7 } }, + /* 74 */ + { { 0xcbd5256a,0x8791b19f,0x6ca13a3b,0x4007e0f2,0x4cf06904,0x03b79460, + 0xb6c17589,0xb18a9c22,0x81d45908,0xa1cb7d7d,0x21bb68f1,0x6e13fa9d }, + { 0xa71e6e16,0x47183c62,0xe18749ed,0x5cf0ef8e,0x2e5ed409,0x2c9c7f9b, + 0xe6e117e1,0x042eeacc,0x13fb5a7f,0xb86d4816,0xc9e5feb1,0xea1cf0ed } }, + /* 75 */ + { { 0xcea4cc9b,0x6e6573c9,0xafcec8f3,0x5417961d,0xa438b6f6,0x804bf02a, + 0xdcd4ea88,0xb894b03c,0x3799571f,0xd0f807e9,0x862156e8,0x3466a7f5 }, + { 0x56515664,0x51e59acd,0xa3c5eb0b,0x55b0f93c,0x6a4279db,0x84a06b02, + 0xc5fae08e,0x5c850579,0xa663a1a2,0xcf07b8db,0xf46ffc8d,0x49a36bbc } }, + /* 76 */ + { { 0x46d93106,0xe47f5acc,0xaa897c9c,0x65b7ade0,0x12d7e4be,0x37cf4c94, + 0xd4b2caa9,0xa2ae9b80,0xe60357a3,0x5e7ce09c,0xc8ecd5f9,0x29f77667 }, + { 0xa8a0b1c5,0xdf6868f5,0x62978ad8,0x240858cf,0xdc0002a1,0x0f7ac101, + 0xffe9aa05,0x1d28a9d7,0x5b962c97,0x744984d6,0x3d28c8b2,0xa8a7c00b } }, + /* 77 */ + { { 0xae11a338,0x7c58a852,0xd1af96e7,0xa78613f1,0x5355cc73,0x7e9767d2, + 0x792a2de6,0x6ba37009,0x124386b2,0x7d60f618,0x11157674,0xab09b531 }, + { 0x98eb9dd0,0x95a04841,0x15070328,0xe6c17acc,0x489c6e49,0xafc6da45, + 0xbb211530,0xab45a60a,0x7d7ea933,0xc58d6592,0x095642c6,0xa3ef3c65 } }, + /* 78 */ + { { 0xdf010879,0x89d420e9,0x39576179,0x9d25255d,0xe39513b6,0x9cdefd50, + 0xd5d1c313,0xe4efe45b,0x3f7af771,0xc0149de7,0x340ab06b,0x55a6b4f4 }, + { 0xebeaf771,0xf1325251,0x878d4288,0x2ab44128,0x18e05afe,0xfcd5832e, + 0xcc1fb62b,0xef52a348,0xc1c4792a,0x2bd08274,0x877c6dc7,0x345c5846 } }, + /* 79 */ + { { 0xbea65e90,0xde15ceb0,0x2416d99c,0x0987f72b,0xfd863dec,0x44db578d, + 0xac6a3578,0xf617b74b,0xdb48e999,0x9e62bd7a,0xeab1a1be,0x877cae61 }, + { 0x3a358610,0x23adddaa,0x325e2b07,0x2fc4d6d1,0x1585754e,0x897198f5, + 0xb392b584,0xf741852c,0xb55f7de1,0x9927804c,0x1aa8efae,0xe9e6c4ed } }, + /* 80 */ + { { 0x98683186,0x867db639,0xddcc4ea9,0xfb5cf424,0xd4f0e7bd,0xcc9a7ffe, + 0x7a779f7e,0x7c57f71c,0xd6b25ef2,0x90774079,0xb4081680,0x90eae903 }, + { 0x0ee1fceb,0xdf2aae5e,0xe86c1a1f,0x3ff1da24,0xca193edf,0x80f587d6, + 0xdc9b9d6a,0xa5695523,0x85920303,0x7b840900,0xba6dbdef,0x1efa4dfc } }, + /* 81 */ + { { 0xe0540015,0xfbd838f9,0xc39077dc,0x2c323946,0xad619124,0x8b1fb9e6, + 0x0ca62ea8,0x9612440c,0x2dbe00ff,0x9ad9b52c,0xae197643,0xf52abaa1 }, + { 0x2cac32ad,0xd0e89894,0x62a98f91,0xdfb79e42,0x276f55cb,0x65452ecf, + 0x7ad23e12,0xdb1ac0d2,0xde4986f0,0xf68c5f6a,0x82ce327d,0x389ac37b } }, + /* 82 */ + { { 0xf8e60f5b,0x511188b4,0x48aa2ada,0x7fe67015,0x381abca2,0xdb333cb8, + 0xdaf3fc97,0xb15e6d9d,0x36aabc03,0x4b24f6eb,0x72a748b4,0xc59789df }, + { 0x29cf5279,0x26fcb8a5,0x01ad9a6c,0x7a3c6bfc,0x4b8bac9b,0x866cf88d, + 0x9c80d041,0xf4c89989,0x70add148,0xf0a04241,0x45d81a41,0x5a02f479 } }, + /* 83 */ + { { 0xc1c90202,0xfa5c877c,0xf8ac7570,0xd099d440,0xd17881f7,0x428a5b1b, + 0x5b2501d7,0x61e267db,0xf2e4465b,0xf889bf04,0x76aa4cb8,0x4da3ae08 }, + { 0xe3e66861,0x3ef0fe26,0x3318b86d,0x5e772953,0x747396df,0xc3c35fbc, + 0x439ffd37,0x5115a29c,0xb2d70374,0xbfc4bd97,0x56246b9d,0x088630ea } }, + /* 84 */ + { { 0xb8a9e8c9,0xcd96866d,0x5bb8091e,0xa11963b8,0x045b3cd2,0xc7f90d53, + 0x80f36504,0x755a72b5,0x21d3751c,0x46f8b399,0x53c193de,0x4bffdc91 }, + { 0xb89554e7,0xcd15c049,0xf7a26be6,0x353c6754,0xbd41d970,0x79602370, + 0x12b176c0,0xde16470b,0x40c8809d,0x56ba1175,0xe435fb1e,0xe2db35c3 } }, + /* 85 */ + { { 0x6328e33f,0xd71e4aab,0xaf8136d1,0x5486782b,0x86d57231,0x07a4995f, + 0x1651a968,0xf1f0a5bd,0x76803b6d,0xa5dc5b24,0x42dda935,0x5c587cbc }, + { 0xbae8b4c0,0x2b6cdb32,0xb1331138,0x66d1598b,0x5d7e9614,0x4a23b2d2, + 0x74a8c05d,0x93e402a6,0xda7ce82e,0x45ac94e6,0xe463d465,0xeb9f8281 } }, + /* 86 */ + { { 0xfecf5b9b,0x34e0f9d1,0xf206966a,0xa115b12b,0x1eaa0534,0x5591cf3b, + 0xfb1558f9,0x5f0293cb,0x1bc703a5,0x1c8507a4,0x862c1f81,0x92e6b81c }, + { 0xcdaf24e3,0xcc9ebc66,0x72fcfc70,0x68917ecd,0x8157ba48,0x6dc9a930, + 0xb06ab2b2,0x5d425c08,0x36e929c4,0x362f8ce7,0x62e89324,0x09f6f57c } }, + /* 87 */ + { { 0xd29375fb,0x1c7d6b78,0xe35d1157,0xfabd851e,0x4243ea47,0xf6f62dcd, + 0x8fe30b0f,0x1dd92460,0xffc6e709,0x08166dfa,0x0881e6a7,0xc6c4c693 }, + { 0xd6a53fb0,0x20368f87,0x9eb4d1f9,0x38718e9f,0xafd7e790,0x03f08acd, + 0x72fe2a1c,0x0835eb44,0x88076e5d,0x7e050903,0xa638e731,0x538f765e } }, + /* 88 */ + { { 0xc2663b4b,0x0e0249d9,0x47cd38dd,0xe700ab5b,0x2c46559f,0xb192559d, + 0x4bcde66d,0x8f9f74a8,0x3e2aced5,0xad161523,0x3dd03a5b,0xc155c047 }, + { 0x3be454eb,0x346a8799,0x83b7dccd,0x66ee94db,0xab9d2abe,0x1f6d8378, + 0x7733f355,0x4a396dd2,0xf53553c2,0x419bd40a,0x731dd943,0xd0ead98d } }, + /* 89 */ + { { 0xec142408,0x908e0b0e,0x4114b310,0x98943cb9,0x1742b1d7,0x03dbf7d8, + 0x693412f4,0xd270df6b,0x8f69e20c,0xc5065494,0x697e43a1,0xa76a90c3 }, + { 0x4624825a,0xe0fa3384,0x8acc34c2,0x82e48c0b,0xe9a14f2b,0x7b24bd14, + 0x4db30803,0x4f5dd5e2,0x932da0a3,0x0c77a9e7,0x74c653dc,0x20db90f2 } }, + /* 90 */ + { { 0x0e6c5fd9,0x261179b7,0x6c982eea,0xf8bec123,0xd4957b7e,0x47683338, + 0x0a72f66a,0xcc47e664,0x1bad9350,0xbd54bf6a,0xf454e95a,0xdfbf4c6a }, + { 0x6907f4fa,0x3f7a7afa,0x865ca735,0x7311fae0,0x2a496ada,0x24737ab8, + 0x15feb79b,0x13e425f1,0xa1b93c21,0xe9e97c50,0x4ddd3eb5,0xb26b6eac } }, + /* 91 */ + { { 0x2a2e5f2b,0x81cab9f5,0xbf385ac4,0xf93caf29,0xc909963a,0xf4bf35c3, + 0x74c9143c,0x081e7300,0xc281b4c5,0x3ea57fa8,0x9b340741,0xe497905c }, + { 0x55ab3cfb,0xf556dd8a,0x518db6ad,0xd444b96b,0x5ef4b955,0x34f5425a, + 0xecd26aa3,0xdda7a3ac,0xda655e97,0xb57da11b,0xc2024c70,0x02da3eff } }, + /* 92 */ + { { 0x6481d0d9,0xe24b0036,0x818fdfe2,0x3740dbe5,0x190fda00,0xc1fc1f45, + 0x3cf27fde,0x329c9280,0x6934f43e,0x7435cb53,0x7884e8fe,0x2b505a5d }, + { 0x711adcc9,0x6cfcc6a6,0x531e21e1,0xf034325c,0x9b2a8a99,0xa2f4a967, + 0x3c21bdff,0x9d5f3842,0x31b57d66,0xb25c7811,0x0b8093b9,0xdb5344d8 } }, + /* 93 */ + { { 0xae50a2f5,0x0d72e667,0xe4a861d1,0x9b7f8d8a,0x330df1cb,0xa129f70f, + 0xe04fefc3,0xe90aa5d7,0xe72c3ae1,0xff561ecb,0xcdb955fa,0x0d8fb428 }, + { 0xd7663784,0xd2235f73,0x7e2c456a,0xc05baec6,0x2adbfccc,0xe5c292e4, + 0xefb110d5,0x4fd17988,0xd19d49f3,0x27e57734,0x84f679fe,0x188ac4ce } }, + /* 94 */ + { { 0xa796c53e,0x7ee344cf,0x0868009b,0xbbf6074d,0x474a1295,0x1f1594f7, + 0xac11632d,0x66776edc,0x04e2fa5a,0x1862278b,0xc854a89a,0x52665cf2 }, + { 0x8104ab58,0x7e376464,0x7204fd6d,0x16775913,0x44ea1199,0x86ca06a5, + 0x1c9240dd,0xaa3f765b,0x24746149,0x5f8501a9,0xdcd251d7,0x7b982e30 } }, + /* 95 */ + { { 0xc15f3060,0xe44e9efc,0xa87ebbe6,0x5ad62f2e,0xc79500d4,0x36499d41, + 0x336fa9d1,0xa66d6dc0,0x5afd3b1f,0xf8afc495,0xe5c9822b,0x1d8ccb24 }, + { 0x79d7584b,0x4031422b,0xea3f20dd,0xc54a0580,0x958468c5,0x3f837c8f, + 0xfbea7735,0x3d82f110,0x7dffe2fc,0x679a8778,0x20704803,0x48eba63b } }, + /* 96 */ + { { 0xdf46e2f6,0x89b10d41,0x19514367,0x13ab57f8,0x1d469c87,0x067372b9, + 0x4f6c5798,0x0c195afa,0x272c9acf,0xea43a12a,0x678abdac,0x9dadd8cb }, + { 0xe182579a,0xcce56c6b,0x2d26c2d8,0x86febadb,0x2a44745c,0x1c668ee1, + 0x98dc047a,0x580acd86,0x51b9ec2d,0x5a2b79cc,0x4054f6a0,0x007da608 } }, + /* 97 */ + { { 0x17b00dd0,0x9e3ca352,0x0e81a7a6,0x046779cb,0xd482d871,0xb999fef3, + 0xd9233fbc,0xe6f38134,0xf48cd0e0,0x112c3001,0x3c6c66ae,0x934e7576 }, + { 0xd73234dc,0xb44d4fc3,0x864eafc1,0xfcae2062,0x26bef21a,0x843afe25, + 0xf3b75fdf,0x61355107,0x794c2e6b,0x8367a5aa,0x8548a372,0x3d2629b1 } }, + /* 98 */ + { { 0x437cfaf8,0x6230618f,0x2032c299,0x5b8742cb,0x2293643a,0x949f7247, + 0x09464f79,0xb8040f1a,0x4f254143,0x049462d2,0x366c7e76,0xabd6b522 }, + { 0xd5338f55,0x119b392b,0x01495a0c,0x1a80a9ce,0xf8d7537e,0xf3118ca7, + 0x6bf4b762,0xb715adc2,0xa8482b6c,0x24506165,0x96a7c84d,0xd958d7c6 } }, + /* 99 */ + { { 0xbdc21f31,0x9ad8aa87,0x8063e58c,0xadb3cab4,0xb07dd7b8,0xefd86283, + 0x1be7c6b4,0xc7b9b762,0x015582de,0x2ef58741,0x299addf3,0xc970c52e }, + { 0x22f24d66,0x78f02e2a,0x74cc100a,0xefec1d10,0x09316e1a,0xaf2a6a39, + 0x5849dd49,0xce7c2205,0x96bffc4c,0x9c1fe75c,0x7ba06ec0,0xcad98fd2 } }, + /* 100 */ + { { 0xb648b73e,0xed76e2d0,0x1cfd285e,0xa9f92ce5,0x2ed13de1,0xa8c86c06, + 0xa5191a93,0x1d3a574e,0x1ad1b8bf,0x385cdf8b,0x47d2cfe3,0xbbecc28a }, + { 0x69cec548,0x98d326c0,0xf240a0b2,0x4f5bc1dd,0x29057236,0x241a7062, + 0xc68294a4,0x0fc6e9c5,0xa319f17a,0x4d04838b,0x9ffc1c6f,0x8b612cf1 } }, + /* 101 */ + { { 0x4c3830eb,0x9bb0b501,0x8ee0d0c5,0x3d08f83c,0x79ba9389,0xa4a62642, + 0x9cbc2914,0x5d5d4044,0x074c46f0,0xae9eb83e,0x74ead7d6,0x63bb758f }, + { 0xc6bb29e0,0x1c40d2ea,0x4b02f41e,0x95aa2d87,0x53cb199a,0x92989175, + 0x51584f6d,0xdd91bafe,0x31a1aaec,0x3715efb9,0x46780f9e,0xc1b6ae5b } }, + /* 102 */ + { { 0x42772f41,0xcded3e4b,0x3bcb79d1,0x3a700d5d,0x80feee60,0x4430d50e, + 0xf5e5d4bb,0x444ef1fc,0xe6e358ff,0xc660194f,0x6a91b43c,0xe68a2f32 }, + { 0x977fe4d2,0x5842775c,0x7e2a41eb,0x78fdef5c,0xff8df00e,0x5f3bec02, + 0x5852525d,0xf4b840cd,0x4e6988bd,0x0870483a,0xcc64b837,0x39499e39 } }, + /* 103 */ + { { 0xb08df5fe,0xfc05de80,0x63ba0362,0x0c12957c,0xd5cf1428,0xea379414, + 0x54ef6216,0xc559132a,0xb9e65cf8,0x33d5f12f,0x1695d663,0x09c60278 }, + { 0x61f7a2fb,0x3ac1ced4,0xd4f5eeb8,0xdd838444,0x8318fcad,0x82a38c6c, + 0xe9f1a864,0x315be2e5,0x442daf47,0x317b5771,0x95aa5f9e,0x81b5904a } }, + /* 104 */ + { { 0x8b21d232,0x6b6b1c50,0x8c2cba75,0x87f3dbc0,0xae9f0faf,0xa7e74b46, + 0xbb7b8079,0x036a0985,0x8d974a25,0x4f185b90,0xd9af5ec9,0x5aa7cef0 }, + { 0x57dcfffc,0xe0566a70,0xb8453225,0x6ea311da,0x23368aa9,0x72ea1a8d, + 0x48cd552d,0xed9b2083,0xc80ea435,0xb987967c,0x6c104173,0xad735c75 } }, + /* 105 */ + { { 0xcee76ef4,0xaea85ab3,0xaf1d2b93,0x44997444,0xeacb923f,0x0851929b, + 0x51e3bc0c,0xb080b590,0x59be68a2,0xc4ee1d86,0x64b26cda,0xf00de219 }, + { 0xf2e90d4d,0x8d7fb5c0,0x77d9ec64,0x00e219a7,0x5d1c491c,0xc4e6febd, + 0x1a8f4585,0x080e3754,0x48d2af9c,0x4a9b86c8,0xb6679851,0x2ed70db6 } }, + /* 106 */ + { { 0x586f25cb,0xaee44116,0xa0fcf70f,0xf7b6861f,0x18a350e8,0x55d2cd20, + 0x92dc286f,0x861bf3e5,0x6226aba7,0x9ab18ffa,0xa9857b03,0xd15827be }, + { 0x92e6acef,0x26c1f547,0xac1fbac3,0x422c63c8,0xfcbfd71d,0xa2d8760d, + 0xb2511224,0x35f6a539,0x048d1a21,0xbaa88fa1,0xebf999db,0x49f1abe9 } }, + /* 107 */ + { { 0xf7492b73,0x16f9f4f4,0xcb392b1a,0xcf28ec1e,0x69ca6ffc,0x45b130d4, + 0xb72efa58,0x28ba8d40,0x5ca066f5,0xace987c7,0x4ad022eb,0x3e399246 }, + { 0x752555bb,0x63a2d84e,0x9c2ae394,0xaaa93b4a,0xc89539ca,0xcd80424e, + 0xaa119a99,0x6d6b5a6d,0x379f2629,0xbd50334c,0xef3cc7d3,0x899e925e } }, + /* 108 */ + { { 0xbf825dc4,0xb7ff3651,0x40b9c462,0x0f741cc4,0x5cc4fb5b,0x771ff5a9, + 0x47fd56fe,0xcb9e9c9b,0x5626c0d3,0xbdf053db,0xf7e14098,0xa97ce675 }, + { 0x6c934f5e,0x68afe5a3,0xccefc46f,0x6cd5e148,0xd7a88586,0xc7758570, + 0xdd558d40,0x49978f5e,0x64ae00c1,0xa1d5088a,0xf1d65bb2,0x58f2a720 } }, + /* 109 */ + { { 0x3e4daedb,0x66fdda4a,0x65d1b052,0x38318c12,0x4c4bbf5c,0x28d910a2, + 0x78a9cd14,0x762fe5c4,0xd2cc0aee,0x08e5ebaa,0xca0c654c,0xd2cdf257 }, + { 0x08b717d2,0x48f7c58b,0x386cd07a,0x3807184a,0xae7d0112,0x3240f626, + 0xc43917b0,0x03e9361b,0x20aea018,0xf261a876,0x7e1e6372,0x53f556a4 } }, + /* 110 */ + { { 0x2f512a90,0xc84cee56,0x1b0ea9f1,0x24b3c004,0xe26cc1ea,0x0ee15d2d, + 0xf0c9ef7d,0xd848762c,0xd5341435,0x1026e9c5,0xfdb16b31,0x8f5b73dc }, + { 0xd2c75d95,0x1f69bef2,0xbe064dda,0x8d33d581,0x57ed35e6,0x8c024c12, + 0xc309c281,0xf8d435f9,0xd6960193,0xfd295061,0xe9e49541,0x66618d78 } }, + /* 111 */ + { { 0x8ce382de,0x571cfd45,0xde900dde,0x175806ee,0x34aba3b5,0x61849965, + 0xde7aec95,0xe899778a,0xff4aa97f,0xe8f00f6e,0x010b0c6d,0xae971cb5 }, + { 0x3af788f1,0x1827eebc,0xe413fe2d,0xd46229ff,0x4741c9b4,0x8a15455b, + 0xf8e424eb,0x5f02e690,0xdae87712,0x40a1202e,0x64944f6d,0x49b3bda2 } }, + /* 112 */ + { { 0x035b2d69,0xd63c6067,0x6bed91b0,0xb507150d,0x7afb39b2,0x1f35f82f, + 0x16012b66,0xb9bd9c01,0xed0a5f50,0x00d97960,0x2716f7c9,0xed705451 }, + { 0x127abdb4,0x1576eff4,0xf01e701c,0x6850d698,0x3fc87e2f,0x9fa7d749, + 0xb0ce3e48,0x0b6bcc6f,0xf7d8c1c0,0xf4fbe1f5,0x02719cc6,0xcf75230e } }, + /* 113 */ + { { 0x722d94ed,0x6761d6c2,0x3718820e,0xd1ec3f21,0x25d0e7c6,0x65a40b70, + 0xbaf3cf31,0xd67f830e,0xb93ea430,0x633b3807,0x0bc96c69,0x17faa0ea }, + { 0xdf866b98,0xe6bf3482,0xa9db52d4,0x205c1ee9,0xff9ab869,0x51ef9bbd, + 0x75eeb985,0x3863dad1,0xd3cf442a,0xef216c3b,0xf9c8e321,0x3fb228e3 } }, + /* 114 */ + { { 0x0760ac07,0x94f9b70c,0x9d79bf4d,0xf3c9ccae,0xc5ffc83d,0x73cea084, + 0xdc49c38e,0xef50f943,0xbc9e7330,0xf467a2ae,0x44ea7fba,0x5ee534b6 }, + { 0x03609e7f,0x20cb6272,0x62fdc9f0,0x09844355,0x0f1457f7,0xaf5c8e58, + 0xb4b25941,0xd1f50a6c,0x2ec82395,0x77cb247c,0xda3dca33,0xa5f3e1e5 } }, + /* 115 */ + { { 0x7d85fa94,0x023489d6,0x2db9ce47,0x0ba40537,0xaed7aad1,0x0fdf7a1f, + 0x9a4ccb40,0xa57b0d73,0x5b18967c,0x48fcec99,0xb7274d24,0xf30b5b6e }, + { 0xc81c5338,0x7ccb4773,0xa3ed6bd0,0xb85639e6,0x1d56eada,0x7d9df95f, + 0x0a1607ad,0xe256d57f,0x957574d6,0x6da7ffdc,0x01c7a8c4,0x65f84046 } }, + /* 116 */ + { { 0xcba1e7f1,0x8d45d0cb,0x02b55f64,0xef0a08c0,0x17e19892,0x771ca31b, + 0x4885907e,0xe1843ecb,0x364ce16a,0x67797ebc,0x8df4b338,0x816d2b2d }, + { 0x39aa8671,0xe870b0e5,0xc102b5f5,0x9f0db3e4,0x1720c697,0x34296659, + 0x613c0d2a,0x0ad4c89e,0x418ddd61,0x1af900b2,0xd336e20e,0xe087ca72 } }, + /* 117 */ + { { 0xaba10079,0x222831ff,0x6d64fff2,0x0dc5f87b,0x3e8cb330,0x44547907, + 0x702a33fb,0xe815aaa2,0x5fba3215,0x338d6b2e,0x79f549c8,0x0f7535cb }, + { 0x2ee95923,0x471ecd97,0xc6d1c09f,0x1e868b37,0xc666ef4e,0x2bc7b8ec, + 0x808a4bfc,0xf5416589,0x3fbc4d2e,0xf23e9ee2,0x2d75125b,0x4357236c } }, + /* 118 */ + { { 0xba9cdb1b,0xfe176d95,0x2f82791e,0x45a1ca01,0x4de4cca2,0x97654af2, + 0x5cc4bcb9,0xbdbf9d0e,0xad97ac0a,0xf6a7df50,0x61359fd6,0xc52112b0 }, + { 0x4f05eae3,0x696d9ce3,0xe943ac2b,0x903adc02,0x0848be17,0xa9075347, + 0x2a3973e5,0x1e20f170,0x6feb67e9,0xe1aacc1c,0xe16bc6b9,0x2ca0ac32 } }, + /* 119 */ + { { 0xef871eb5,0xffea12e4,0xa8bf0a7a,0x94c2f25d,0x78134eaa,0x4d1e4c2a, + 0x0360fb10,0x11ed16fb,0x85fc11be,0x4029b6db,0xf4d390fa,0x5e9f7ab7 }, + { 0x30646612,0x5076d72f,0xdda1d0d8,0xa0afed1d,0x85a1d103,0x29022257, + 0x4e276bcd,0xcb499e17,0x51246c3d,0x16d1da71,0x589a0443,0xc72d56d3 } }, + /* 120 */ + { { 0xdae5bb45,0xdf5ffc74,0x261bd6dc,0x99068c4a,0xaa98ec7b,0xdc0afa7a, + 0xf121e96d,0xedd2ee00,0x1414045c,0x163cc7be,0x335af50e,0xb0b1bbce }, + { 0x01a06293,0xd440d785,0x6552e644,0xcdebab7c,0x8c757e46,0x48cb8dbc, + 0x3cabe3cb,0x81f9cf78,0xb123f59a,0xddd02611,0xeeb3784d,0x3dc7b88e } }, + /* 121 */ + { { 0xc4741456,0xe1b8d398,0x6032a121,0xa9dfa902,0x1263245b,0x1cbfc86d, + 0x5244718c,0xf411c762,0x05b0fc54,0x96521d54,0xdbaa4985,0x1afab46e }, + { 0x8674b4ad,0xa75902ba,0x5ad87d12,0x486b43ad,0x36e0d099,0x72b1c736, + 0xbb6cd6d6,0x39890e07,0x59bace4e,0x8128999c,0x7b535e33,0xd8da430b } }, + /* 122 */ + { { 0xc6b75791,0x39f65642,0x21806bfb,0x050947a6,0x1362ef84,0x0ca3e370, + 0x8c3d2391,0x9bc60aed,0x732e1ddc,0x9b488671,0xa98ee077,0x12d10d9e }, + { 0x3651b7dc,0xb6f2822d,0x80abd138,0x6345a5ba,0x472d3c84,0x62033262, + 0xacc57527,0xd54a1d40,0x424447cb,0x6ea46b3a,0x2fb1a496,0x5bc41057 } }, + /* 123 */ + { { 0xa751cd0e,0xe70c57a3,0xeba3c7d6,0x190d8419,0x9d47d55a,0xb1c3bee7, + 0xf912c6d8,0xda941266,0x407a6ad6,0x12e9aacc,0x6e838911,0xd6ce5f11 }, + { 0x70e1f2ce,0x063ca97b,0x8213d434,0xa3e47c72,0x84df810a,0xa016e241, + 0xdfd881a4,0x688ad7b0,0xa89bf0ad,0xa37d99fc,0xa23c2d23,0xd8e3f339 } }, + /* 124 */ + { { 0x750bed6f,0xbdf53163,0x83e68b0a,0x808abc32,0x5bb08a33,0x85a36627, + 0x6b0e4abe,0xf72a3a0f,0xfaf0c6ad,0xf7716d19,0x5379b25f,0x22dcc020 }, + { 0xf9a56e11,0x7400bf8d,0x56a47f21,0x6cb8bad7,0x7a6eb644,0x7c97176f, + 0xd1f5b646,0xe8fd84f7,0x44ddb054,0x98320a94,0x1dde86f5,0x07071ba3 } }, + /* 125 */ + { { 0x98f8fcb9,0x6fdfa0e5,0x94d0d70c,0x89cec8e0,0x106d20a8,0xa0899397, + 0xba8acc9c,0x915bfb9a,0x5507e01c,0x1370c94b,0x8a821ffb,0x83246a60 }, + { 0xbe3c378f,0xa8273a9f,0x35a25be9,0x7e544789,0x4dd929d7,0x6cfa4972, + 0x365bd878,0x987fed9d,0x5c29a7ae,0x4982ac94,0x5ddd7ec5,0x4589a5d7 } }, + /* 126 */ + { { 0xa95540a9,0x9fabb174,0x0162c5b0,0x7cfb886f,0xea3dee18,0x17be766b, + 0xe88e624c,0xff7da41f,0x8b919c38,0xad0b71eb,0xf31ff9a9,0x86a522e0 }, + { 0x868bc259,0xbc8e6f72,0x3ccef9e4,0x6130c638,0x9a466555,0x09f1f454, + 0x19b2bfb4,0x8e6c0f09,0x0ca7bb22,0x945c46c9,0x4dafb67b,0xacd87168 } }, + /* 127 */ + { { 0x10c53841,0x090c72ca,0x55a4fced,0xc20ae01b,0xe10234ad,0x03f7ebd5, + 0x85892064,0xb3f42a6a,0xb4a14722,0xbdbc30c0,0x8ca124cc,0x971bc437 }, + { 0x517ff2ff,0x6f79f46d,0xecba947b,0x6a9c96e2,0x62925122,0x5e79f2f4, + 0x6a4e91f1,0x30a96bb1,0x2d4c72da,0x1147c923,0x5811e4df,0x65bc311f } }, + /* 128 */ + { { 0x139b3239,0x87c7dd7d,0x4d833bae,0x8b57824e,0x9fff0015,0xbcbc4878, + 0x909eaf1a,0x8ffcef8b,0xf1443a78,0x9905f4ee,0xe15cbfed,0x020dd4a2 }, + { 0xa306d695,0xca2969ec,0xb93caf60,0xdf940cad,0x87ea6e39,0x67f7fab7, + 0xf98c4fe5,0x0d0ee10f,0xc19cb91e,0xc646879a,0x7d1d7ab4,0x4b4ea50c } }, + /* 129 */ + { { 0x7a0db57e,0x19e40945,0x9a8c9702,0xe6017cad,0x1be5cff9,0xdbf739e5, + 0xa7a938a2,0x3646b3cd,0x68350dfc,0x04511085,0x56e098b5,0xad3bd6f3 }, + { 0xee2e3e3e,0x935ebabf,0x473926cb,0xfbd01702,0x9e9fb5aa,0x7c735b02, + 0x2e3feff0,0xc52a1b85,0x046b405a,0x9199abd3,0x39039971,0xe306fcec } }, + /* 130 */ + { { 0x23e4712c,0xd6d9aec8,0xc3c198ee,0x7ca8376c,0x31bebd8a,0xe6d83187, + 0xd88bfef3,0xed57aff3,0xcf44edc7,0x72a645ee,0x5cbb1517,0xd4e63d0b }, + { 0xceee0ecf,0x98ce7a1c,0x5383ee8e,0x8f012633,0xa6b455e8,0x3b879078, + 0xc7658c06,0xcbcd3d96,0x0783336a,0x721d6fe7,0x5a677136,0xf21a7263 } }, + /* 131 */ + { { 0x9586ba11,0x19d8b3cd,0x8a5c0480,0xd9e0aeb2,0x2230ef5c,0xe4261dbf, + 0x02e6bf09,0x095a9dee,0x80dc7784,0x8963723c,0x145157b1,0x5c97dbaf }, + { 0x4bc4503e,0x97e74434,0x85a6b370,0x0fb1cb31,0xcd205d4b,0x3e8df2be, + 0xf8f765da,0x497dd1bc,0x6c988a1a,0x92ef95c7,0x64dc4cfa,0x3f924baa } }, + /* 132 */ + { { 0x7268b448,0x6bf1b8dd,0xefd79b94,0xd4c28ba1,0xe4e3551f,0x2fa1f8c8, + 0x5c9187a9,0x769e3ad4,0x40326c0d,0x28843b4d,0x50d5d669,0xfefc8094 }, + { 0x90339366,0x30c85bfd,0x5ccf6c3a,0x4eeb56f1,0x28ccd1dc,0x0e72b149, + 0xf2ce978e,0x73ee85b5,0x3165bb23,0xcdeb2bf3,0x4e410abf,0x8106c923 } }, + /* 133 */ + { { 0x7d02f4ee,0xc8df0161,0x18e21225,0x8a781547,0x6acf9e40,0x4ea895eb, + 0x6e5a633d,0x8b000cb5,0x7e981ffb,0xf31d86d5,0x4475bc32,0xf5c8029c }, + { 0x1b568973,0x764561ce,0xa62996ec,0x2f809b81,0xda085408,0x9e513d64, + 0xe61ce309,0xc27d815d,0x272999e0,0x0da6ff99,0xfead73f7,0xbd284779 } }, + /* 134 */ + { { 0x9b1cdf2b,0x6033c2f9,0xbc5fa151,0x2a99cf06,0x12177b3b,0x7d27d259, + 0xc4485483,0xb1f15273,0x102e2297,0x5fd57d81,0xc7f6acb7,0x3d43e017 }, + { 0x3a70eb28,0x41a8bb0b,0x3e80b06b,0x67de2d8e,0x70c28de5,0x09245a41, + 0xa7b26023,0xad7dbcb1,0x2cbc6c1e,0x70b08a35,0x9b33041f,0xb504fb66 } }, + /* 135 */ + { { 0xf97a27c2,0xa8e85ab5,0xc10a011b,0x6ac5ec8b,0xffbcf161,0x55745533, + 0x65790a60,0x01780e85,0x99ee75b0,0xe451bf85,0x39c29881,0x8907a63b }, + { 0x260189ed,0x76d46738,0x47bd35cb,0x284a4436,0x20cab61e,0xd74e8c40, + 0x416cf20a,0x6264bf8c,0x5fd820ce,0xfa5a6c95,0xf24bb5fc,0xfa7154d0 } }, + /* 136 */ + { { 0x9b3f5034,0x18482cec,0xcd9e68fd,0x962d445a,0x95746f23,0x266fb1d6, + 0x58c94a4b,0xc66ade5a,0xed68a5b6,0xdbbda826,0x7ab0d6ae,0x05664a4d }, + { 0x025e32fc,0xbcd4fe51,0xa96df252,0x61a5aebf,0x31592a31,0xd88a07e2, + 0x98905517,0x5d9d94de,0x5fd440e7,0x96bb4010,0xe807db4c,0x1b0c47a2 } }, + /* 137 */ + { { 0x08223878,0x5c2a6ac8,0xe65a5558,0xba08c269,0x9bbc27fd,0xd22b1b9b, + 0x72b9607d,0x919171bf,0xe588dc58,0x9ab455f9,0x23662d93,0x6d54916e }, + { 0x3b1de0c1,0x8da8e938,0x804f278f,0xa84d186a,0xd3461695,0xbf4988cc, + 0xe10eb0cb,0xf5eae3be,0xbf2a66ed,0x1ff8b68f,0xc305b570,0xa68daf67 } }, + /* 138 */ + { { 0x44b2e045,0xc1004cff,0x4b1c05d4,0x91b5e136,0x88a48a07,0x53ae4090, + 0xea11bb1a,0x73fb2995,0x3d93a4ea,0x32048570,0x3bfc8a5f,0xcce45de8 }, + { 0xc2b3106e,0xaff4a97e,0xb6848b4f,0x9069c630,0xed76241c,0xeda837a6, + 0x6cc3f6cf,0x8a0daf13,0x3da018a8,0x199d049d,0xd9093ba3,0xf867c6b1 } }, + /* 139 */ + { { 0x56527296,0xe4d42a56,0xce71178d,0xae26c73d,0x6c251664,0x70a0adac, + 0x5dc0ae1d,0x813483ae,0xdaab2daf,0x7574eacd,0xc2d55f4f,0xc56b52dc }, + { 0x95f32923,0x872bc167,0x5bdd2a89,0x4be17581,0xa7699f00,0x9b57f1e7, + 0x3ac2de02,0x5fcd9c72,0x92377739,0x83af3ba1,0xfc50b97f,0xa64d4e2b } }, + /* 140 */ + { { 0x0e552b40,0x2172dae2,0xd34d52e8,0x62f49725,0x07958f98,0x7930ee40, + 0x751fdd74,0x56da2a90,0xf53e48c3,0xf1192834,0x8e53c343,0x34d2ac26 }, + { 0x13111286,0x1073c218,0xda9d9827,0x201dac14,0xee95d378,0xec2c29db, + 0x1f3ee0b1,0x9316f119,0x544ce71c,0x7890c9f0,0x27612127,0xd77138af } }, + /* 141 */ + { { 0x3b4ad1cd,0x78045e6d,0x4aa49bc1,0xcd86b94e,0xfd677a16,0x57e51f1d, + 0xfa613697,0xd9290935,0x34f4d893,0x7a3f9593,0x5d5fcf9b,0x8c9c248b }, + { 0x6f70d4e9,0x9f23a482,0x63190ae9,0x17273454,0x5b081a48,0x4bdd7c13, + 0x28d65271,0x1e2de389,0xe5841d1f,0x0bbaaa25,0x746772e5,0xc4c18a79 } }, + /* 142 */ + { { 0x593375ac,0x10ee2681,0x7dd5e113,0x4f3288be,0x240f3538,0x9a97b2fb, + 0x1de6b1e2,0xfa11089f,0x1351bc58,0x516da562,0x2dfa85b5,0x573b6119 }, + { 0x6cba7df5,0x89e96683,0x8c28ab40,0xf299be15,0xad43fcbf,0xe91c9348, + 0x9a1cefb3,0xe9bbc7cc,0x738b2775,0xc8add876,0x775eaa01,0x6e3b1f2e } }, + /* 143 */ + { { 0xb677788b,0x0365a888,0x3fd6173c,0x634ae8c4,0x9e498dbe,0x30498761, + 0xc8f779ab,0x08c43e6d,0x4c09aca9,0x068ae384,0x2018d170,0x2380c70b }, + { 0xa297c5ec,0xcf77fbc3,0xca457948,0xdacbc853,0x336bec7e,0x3690de04, + 0x14eec461,0x26bbac64,0x1f713abf,0xd1c23c7e,0xe6fd569e,0xf08bbfcd } }, + /* 144 */ + { { 0x84770ee3,0x5f8163f4,0x744a1706,0x0e0c7f94,0xe1b2d46d,0x9c8f05f7, + 0xd01fd99a,0x417eafe7,0x11440e5b,0x2ba15df5,0x91a6fbcf,0xdc5c552a }, + { 0xa270f721,0x86271d74,0xa004485b,0x32c0a075,0x8defa075,0x9d1a87e3, + 0xbf0d20fe,0xb590a7ac,0x8feda1f5,0x430c41c2,0x58f6ec24,0x454d2879 } }, + /* 145 */ + { { 0x7c525435,0x52b7a635,0x37c4bdbc,0x3d9ef57f,0xdffcc475,0x2bb93e9e, + 0x7710f3be,0xf7b8ba98,0x21b727de,0x42ee86da,0x2e490d01,0x55ac3f19 }, + { 0xc0c1c390,0x487e3a6e,0x446cde7b,0x036fb345,0x496ae951,0x089eb276, + 0x71ed1234,0xedfed4d9,0x900f0b46,0x661b0dd5,0x8582f0d3,0x11bd6f1b } }, + /* 146 */ + { { 0x076bc9d1,0x5cf9350f,0xcf3cd2c3,0x15d903be,0x25af031c,0x21cfc8c2, + 0x8b1cc657,0xe0ad3248,0x70014e87,0xdd9fb963,0x297f1658,0xf0f3a5a1 }, + { 0xf1f703aa,0xbb908fba,0x2f6760ba,0x2f9cc420,0x66a38b51,0x00ceec66, + 0x05d645da,0x4deda330,0xf7de3394,0xb9cf5c72,0x1ad4c906,0xaeef6502 } }, + /* 147 */ + { { 0x7a19045d,0x0583c8b1,0xd052824c,0xae7c3102,0xff6cfa58,0x2a234979, + 0x62c733c0,0xfe9dffc9,0x9c0c4b09,0x3a7fa250,0x4fe21805,0x516437bb }, + { 0xc2a23ddb,0x9454e3d5,0x289c104e,0x0726d887,0x4fd15243,0x8977d918, + 0x6d7790ba,0xc559e73f,0x465af85f,0x8fd3e87d,0x5feee46b,0xa2615c74 } }, + /* 148 */ + { { 0x4335167d,0xc8d607a8,0xe0f5c887,0x8b42d804,0x398d11f9,0x5f9f13df, + 0x20740c67,0x5aaa5087,0xa3d9234b,0x83da9a6a,0x2a54bad1,0xbd3a5c4e }, + { 0x2db0f658,0xdd13914c,0x5a3f373a,0x29dcb66e,0x5245a72b,0xbfd62df5, + 0x91e40847,0x19d18023,0xb136b1ae,0xd9df74db,0x3f93bc5b,0x72a06b6b } }, + /* 149 */ + { { 0xad19d96f,0x6da19ec3,0xfb2a4099,0xb342daa4,0x662271ea,0x0e61633a, + 0xce8c054b,0x3bcece81,0x8bd62dc6,0x7cc8e061,0xee578d8b,0xae189e19 }, + { 0xdced1eed,0x73e7a25d,0x7875d3ab,0xc1257f0a,0x1cfef026,0x2cb2d5a2, + 0xb1fdf61c,0xd98ef39b,0x24e83e6c,0xcd8e6f69,0xc7b7088b,0xd71e7076 } }, + /* 150 */ + { { 0x9d4245bf,0x33936830,0x2ac2953b,0x22d96217,0x56c3c3cd,0xb3bf5a82, + 0x0d0699e8,0x50c9be91,0x8f366459,0xec094463,0x513b7c35,0x6c056dba }, + { 0x045ab0e3,0x687a6a83,0x445c9295,0x8d40b57f,0xa16f5954,0x0f345048, + 0x3d8f0a87,0x64b5c639,0x9f71c5e2,0x106353a2,0x874f0dd4,0xdd58b475 } }, + /* 151 */ + { { 0x62230c72,0x67ec084f,0x481385e3,0xf14f6cca,0x4cda7774,0xf58bb407, + 0xaa2dbb6b,0xe15011b1,0x0c035ab1,0xd488369d,0x8245f2fd,0xef83c24a }, + { 0x9fdc2538,0xfb57328f,0x191fe46a,0x79808293,0x32ede548,0xe28f5c44, + 0xea1a022c,0x1b3cda99,0x3df2ec7f,0x39e639b7,0x760e9a18,0x77b6272b } }, + /* 152 */ + { { 0xa65d56d5,0x2b1d51bd,0x7ea696e0,0x3a9b71f9,0x9904f4c4,0x95250ecc, + 0xe75774b7,0x8bc4d6eb,0xeaeeb9aa,0x0e343f8a,0x930e04cb,0xc473c1d1 }, + { 0x064cd8ae,0x282321b1,0x5562221c,0xf4b4371e,0xd1bf1221,0xc1cc81ec, + 0xe2c8082f,0xa52a07a9,0xba64a958,0x350d8e59,0x6fb32c9a,0x29e4f3de } }, + /* 153 */ + { { 0xba89aaa5,0x0aa9d56c,0xc4c6059e,0xf0208ac0,0xbd6ddca4,0x7400d9c6, + 0xf2c2f74a,0xb384e475,0xb1562dd3,0x4c1061fc,0x2e153b8d,0x3924e248 }, + { 0x849808ab,0xf38b8d98,0xa491aa36,0x29bf3260,0x88220ede,0x85159ada, + 0xbe5bc422,0x8b47915b,0xd7300967,0xa934d72e,0x2e515d0d,0xc4f30398 } }, + /* 154 */ + { { 0x1b1de38b,0xe3e9ee42,0x42636760,0xa124e25a,0x90165b1a,0x90bf73c0, + 0x146434c5,0x21802a34,0x2e1fa109,0x54aa83f2,0xed9c51e9,0x1d4bd03c }, + { 0x798751e6,0xc2d96a38,0x8c3507f5,0xed27235f,0xc8c24f88,0xb5fb80e2, + 0xd37f4f78,0xf873eefa,0xf224ba96,0x7229fd74,0x9edd7149,0x9dcd9199 } }, + /* 155 */ + { { 0x4e94f22a,0xee9f81a6,0xf71ec341,0xe5609892,0xa998284e,0x6c818ddd, + 0x3b54b098,0x9fd47295,0x0e8a7cc9,0x47a6ac03,0xb207a382,0xde684e5e }, + { 0x2b6b956b,0x4bdd1ecd,0xf01b3583,0x09084414,0x55233b14,0xe2f80b32, + 0xef5ebc5e,0x5a0fec54,0xbf8b29a2,0x74cf25e6,0x7f29e014,0x1c757fa0 } }, + /* 156 */ + { { 0xeb0fdfe4,0x1bcb5c4a,0xf0899367,0xd7c649b3,0x05bc083b,0xaef68e3f, + 0xa78aa607,0x57a06e46,0x21223a44,0xa2136ecc,0x52f5a50b,0x89bd6484 }, + { 0x4455f15a,0x724411b9,0x08a9c0fd,0x23dfa970,0x6db63bef,0x7b0da4d1, + 0xfb162443,0x6f8a7ec1,0xe98284fb,0xc1ac9cee,0x33566022,0x085a582b } }, + /* 157 */ + { { 0xec1f138a,0x15cb61f9,0x668f0c28,0x11c9a230,0xdf93f38f,0xac829729, + 0x4048848d,0xcef25698,0x2bba8fbf,0x3f686da0,0x111c619a,0xed5fea78 }, + { 0xd6d1c833,0x9b4f73bc,0x86e7bf80,0x50951606,0x042b1d51,0xa2a73508, + 0x5fb89ec2,0x9ef6ea49,0x5ef8b892,0xf1008ce9,0x9ae8568b,0x78a7e684 } }, + /* 158 */ + { { 0x10470cd8,0x3fe83a7c,0xf86df000,0x92734682,0xda9409b5,0xb5dac06b, + 0x94939c5f,0x1e7a9660,0x5cc116dc,0xdec6c150,0x66bac8cc,0x1a52b408 }, + { 0x6e864045,0x5303a365,0x9139efc1,0x45eae72a,0x6f31d54f,0x83bec646, + 0x6e958a6d,0x2fb4a86f,0x4ff44030,0x6760718e,0xe91ae0df,0x008117e3 } }, + /* 159 */ + { { 0x384310a2,0x5d5833ba,0x1fd6c9fc,0xbdfb4edc,0x849c4fb8,0xb9a4f102, + 0x581c1e1f,0xe5fb239a,0xd0a9746d,0xba44b2e7,0x3bd942b9,0x78f7b768 }, + { 0xc87607ae,0x076c8ca1,0xd5caaa7e,0x82b23c2e,0x2763e461,0x6a581f39, + 0x3886df11,0xca8a5e4a,0x264e7f22,0xc87e90cf,0x215cfcfc,0x04f74870 } }, + /* 160 */ + { { 0x141d161c,0x5285d116,0x93c4ed17,0x67cd2e0e,0x7c36187e,0x12c62a64, + 0xed2584ca,0xf5329539,0x42fbbd69,0xc4c777c4,0x1bdfc50a,0x107de776 }, + { 0xe96beebd,0x9976dcc5,0xa865a151,0xbe2aff95,0x9d8872af,0x0e0a9da1, + 0xa63c17cc,0x5e357a3d,0xe15cc67c,0xd31fdfd8,0x7970c6d8,0xc44bbefd } }, + /* 161 */ + { { 0x4c0c62f1,0x703f83e2,0x4e195572,0x9b1e28ee,0xfe26cced,0x6a82858b, + 0xc43638fa,0xd381c84b,0xa5ba43d8,0x94f72867,0x10b82743,0x3b4a783d }, + { 0x7576451e,0xee1ad7b5,0x14b6b5c8,0xc3d0b597,0xfcacc1b8,0x3dc30954, + 0x472c9d7b,0x55df110e,0x02f8a328,0x97c86ed7,0x88dc098f,0xd0433413 } }, + /* 162 */ + { { 0x2ca8f2fe,0x1a60d152,0x491bd41f,0x61640948,0x58dfe035,0x6dae29a5, + 0x278e4863,0x9a615bea,0x9ad7c8e5,0xbbdb4477,0x2ceac2fc,0x1c706630 }, + { 0x99699b4b,0x5e2b54c6,0x239e17e8,0xb509ca6d,0xea063a82,0x728165fe, + 0xb6a22e02,0x6b5e609d,0xb26ee1df,0x12813905,0x439491fa,0x07b9f722 } }, + /* 163 */ + { { 0x48ff4e49,0x1592ec14,0x6d644129,0x3e4e9f17,0x1156acc0,0x7acf8288, + 0xbb092b0b,0x5aa34ba8,0x7d38393d,0xcd0f9022,0xea4f8187,0x416724dd }, + { 0xc0139e73,0x3c4e641c,0x91e4d87d,0xe0fe46cf,0xcab61f8a,0xedb3c792, + 0xd3868753,0x4cb46de4,0x20f1098a,0xe449c21d,0xf5b8ea6e,0x5e5fd059 } }, + /* 164 */ + { { 0x75856031,0x7fcadd46,0xeaf2fbd0,0x89c7a4cd,0x7a87c480,0x1af523ce, + 0x61d9ae90,0xe5fc1095,0xbcdb95f5,0x3fb5864f,0xbb5b2c7d,0xbeb5188e }, + { 0x3ae65825,0x3d1563c3,0x0e57d641,0x116854c4,0x1942ebd3,0x11f73d34, + 0xc06955b3,0x24dc5904,0x995a0a62,0x8a0d4c83,0x5d577b7d,0xfb26b86d } }, + /* 165 */ + { { 0xc686ae17,0xc53108e7,0xd1c1da56,0x9090d739,0x9aec50ae,0x4583b013, + 0xa49a6ab2,0xdd9a088b,0xf382f850,0x28192eea,0xf5fe910e,0xcc8df756 }, + { 0x9cab7630,0x877823a3,0xfb8e7fc1,0x64984a9a,0x364bfc16,0x5448ef9c, + 0xc44e2a9a,0xbbb4f871,0x435c95e9,0x901a41ab,0xaaa50a06,0xc6c23e5f } }, + /* 166 */ + { { 0x9034d8dd,0xb78016c1,0x0b13e79b,0x856bb44b,0xb3241a05,0x85c6409a, + 0x2d78ed21,0x8d2fe19a,0x726eddf2,0xdcc7c26d,0x25104f04,0x3ccaff5f }, + { 0x6b21f843,0x397d7edc,0xe975de4c,0xda88e4dd,0x4f5ab69e,0x5273d396, + 0x9aae6cc0,0x537680e3,0x3e6f9461,0xf749cce5,0x957bffd3,0x021ddbd9 } }, + /* 167 */ + { { 0x777233cf,0x7b64585f,0x0942a6f0,0xfe6771f6,0xdfe6eef0,0x636aba7a, + 0x86038029,0x63bbeb56,0xde8fcf36,0xacee5842,0xd4a20524,0x48d9aa99 }, + { 0x0da5e57a,0xcff7a74c,0xe549d6c9,0xc232593c,0xf0f2287b,0x68504bcc, + 0xbc8360b5,0x6d7d098d,0x5b402f41,0xeac5f149,0xb87d1bf1,0x61936f11 } }, + /* 168 */ + { { 0xb8153a9d,0xaa9da167,0x9e83ecf0,0xa49fe3ac,0x1b661384,0x14c18f8e, + 0x38434de1,0x61c24dab,0x283dae96,0x3d973c3a,0x82754fc9,0xc99baa01 }, + { 0x4c26b1e3,0x477d198f,0xa7516202,0x12e8e186,0x362addfa,0x386e52f6, + 0xc3962853,0x31e8f695,0x6aaedb60,0xdec2af13,0x29cf74ac,0xfcfdb4c6 } }, + /* 169 */ + { { 0xcca40298,0x6b3ee958,0xf2f5d195,0xc3878153,0xed2eae5b,0x0c565630, + 0x3a697cf2,0xd089b37e,0xad5029ea,0xc2ed2ac7,0x0f0dda6a,0x7e5cdfad }, + { 0xd9b86202,0xf98426df,0x4335e054,0xed1960b1,0x3f14639e,0x1fdb0246, + 0x0db6c670,0x17f709c3,0x773421e1,0xbfc687ae,0x26c1a8ac,0x13fefc4a } }, + /* 170 */ + { { 0x7ffa0a5f,0xe361a198,0xc63fe109,0xf4b26102,0x6c74e111,0x264acbc5, + 0x77abebaf,0x4af445fa,0x24cddb75,0x448c4fdd,0x44506eea,0x0b13157d }, + { 0x72e9993d,0x22a6b159,0x85e5ecbe,0x2c3c57e4,0xfd83e1a1,0xa673560b, + 0xc3b8c83b,0x6be23f82,0x40bbe38e,0x40b13a96,0xad17399b,0x66eea033 } }, + /* 171 */ + { { 0xb4c6c693,0x49fc6e95,0x36af7d38,0xefc735de,0x35fe42fc,0xe053343d, + 0x6a9ab7c3,0xf0aa427c,0x4a0fcb24,0xc79f0436,0x93ebbc50,0x16287243 }, + { 0x16927e1e,0x5c3d6bd0,0x673b984c,0x40158ed2,0x4cd48b9a,0xa7f86fc8, + 0x60ea282d,0x1643eda6,0xe2a1beed,0x45b393ea,0x19571a94,0x664c839e } }, + /* 172 */ + { { 0x27eeaf94,0x57745750,0xea99e1e7,0x2875c925,0x5086adea,0xc127e7ba, + 0x86fe424f,0x765252a0,0x2b6c0281,0x1143cc6c,0xd671312d,0xc9bb2989 }, + { 0x51acb0a5,0x880c337c,0xd3c60f78,0xa3710915,0x9262b6ed,0x496113c0, + 0x9ce48182,0x5d25d9f8,0xb3813586,0x53b6ad72,0x4c0e159c,0x0ea3bebc } }, + /* 173 */ + { { 0xc5e49bea,0xcaba450a,0x7c05da59,0x684e5415,0xde7ac36c,0xa2e9cab9, + 0x2e6f957b,0x4ca79b5f,0x09b817b1,0xef7b0247,0x7d89df0f,0xeb304990 }, + { 0x46fe5096,0x508f7307,0x2e04eaaf,0x695810e8,0x3512f76c,0x88ef1bd9, + 0x3ebca06b,0x77661351,0xccf158b7,0xf7d4863a,0x94ee57da,0xb2a81e44 } }, + /* 174 */ + { { 0x6d53e6ba,0xff288e5b,0x14484ea2,0xa90de1a9,0xed33c8ec,0x2fadb60c, + 0x28b66a40,0x579d6ef3,0xec24372d,0x4f2dd6dd,0x1d66ec7d,0xe9e33fc9 }, + { 0x039eab6e,0x110899d2,0x3e97bb5e,0xa31a667a,0xcfdce68e,0x6200166d, + 0x5137d54b,0xbe83ebae,0x4800acdf,0x085f7d87,0x0c6f8c86,0xcf4ab133 } }, + /* 175 */ + { { 0x931e08fb,0x03f65845,0x1506e2c0,0x6438551e,0x9c36961f,0x5791f0dc, + 0xe3dcc916,0x68107b29,0xf495d2ca,0x83242374,0x6ee5895b,0xd8cfb663 }, + { 0xa0349b1b,0x525e0f16,0x4a0fab86,0x33cd2c6c,0x2af8dda9,0x46c12ee8, + 0x71e97ad3,0x7cc424ba,0x37621eb0,0x69766ddf,0xa5f0d390,0x95565f56 } }, + /* 176 */ + { { 0x1a0f5e94,0xe0e7bbf2,0x1d82d327,0xf771e115,0xceb111fa,0x10033e3d, + 0xd3426638,0xd269744d,0x00d01ef6,0xbdf2d9da,0xa049ceaf,0x1cb80c71 }, + { 0x9e21c677,0x17f18328,0x19c8f98b,0x6452af05,0x80b67997,0x35b9c5f7, + 0x40f8f3d4,0x5c2e1cbe,0x66d667ca,0x43f91656,0xcf9d6e79,0x9faaa059 } }, + /* 177 */ + { { 0x0a078fe6,0x8ad24618,0x464fd1dd,0xf6cc73e6,0xc3e37448,0x4d2ce34d, + 0xe3271b5f,0x624950c5,0xefc5af72,0x62910f5e,0xaa132bc6,0x8b585bf8 }, + { 0xa839327f,0x11723985,0x4aac252f,0x34e2d27d,0x6296cc4e,0x402f59ef, + 0x47053de9,0x00ae055c,0x28b4f09b,0xfc22a972,0xfa0c180e,0xa9e86264 } }, + /* 178 */ + { { 0xbc310ecc,0x0b7b6224,0x67fa14ed,0x8a1a74f1,0x7214395c,0x87dd0960, + 0xf5c91128,0xdf1b3d09,0x86b264a8,0x39ff23c6,0x3e58d4c5,0xdc2d49d0 }, + { 0xa9d6f501,0x2152b7d3,0xc04094f7,0xf4c32e24,0xd938990f,0xc6366596, + 0x94fb207f,0x084d078f,0x328594cb,0xfd99f1d7,0xcb2d96b3,0x36defa64 } }, + /* 179 */ + { { 0x13ed7cbe,0x4619b781,0x9784bd0e,0x95e50015,0x2c7705fe,0x2a32251c, + 0x5f0dd083,0xa376af99,0x0361a45b,0x55425c6c,0x1f291e7b,0x812d2cef }, + { 0x5fd94972,0xccf581a0,0xe56dc383,0x26e20e39,0x63dbfbf0,0x0093685d, + 0x36b8c575,0x1fc164cc,0x390ef5e7,0xb9c5ab81,0x26908c66,0x40086beb } }, + /* 180 */ + { { 0x37e3c115,0xe5e54f79,0xc1445a8a,0x69b8ee8c,0xb7659709,0x79aedff2, + 0x1b46fbe6,0xe288e163,0xd18d7bb7,0xdb4844f0,0x48aa6424,0xe0ea23d0 }, + { 0xf3d80a73,0x714c0e4e,0x3bd64f98,0x87a0aa9e,0x2ec63080,0x8844b8a8, + 0x255d81a3,0xe0ac9c30,0x455397fc,0x86151237,0x2f820155,0x0b979464 } }, + /* 181 */ + { { 0x4ae03080,0x127a255a,0x580a89fb,0x232306b4,0x6416f539,0x04e8cd6a, + 0x13b02a0e,0xaeb70dee,0x4c09684a,0xa3038cf8,0x28e433ee,0xa710ec3c }, + { 0x681b1f7d,0x77a72567,0x2fc28170,0x86fbce95,0xf5735ac8,0xd3408683, + 0x6bd68e93,0x3a324e2a,0xc027d155,0x7ec74353,0xd4427177,0xab60354c } }, + /* 182 */ + { { 0xef4c209d,0x32a5342a,0x08d62704,0x2ba75274,0xc825d5fe,0x4bb4af6f, + 0xd28e7ff1,0x1c3919ce,0xde0340f6,0x1dfc2fdc,0x29f33ba9,0xc6580baf }, + { 0x41d442cb,0xae121e75,0x3a4724e4,0x4c7727fd,0x524f3474,0xe556d6a4, + 0x785642a2,0x87e13cc7,0xa17845fd,0x182efbb1,0x4e144857,0xdcec0cf1 } }, + /* 183 */ + { { 0xe9539819,0x1cb89541,0x9d94dbf1,0xc8cb3b4f,0x417da578,0x1d353f63, + 0x8053a09e,0xb7a697fb,0xc35d8b78,0x8d841731,0xb656a7a9,0x85748d6f }, + { 0xc1859c5d,0x1fd03947,0x535d22a2,0x6ce965c1,0x0ca3aadc,0x1966a13e, + 0x4fb14eff,0x9802e41d,0x76dd3fcd,0xa9048cbb,0xe9455bba,0x89b182b5 } }, + /* 184 */ + { { 0x43360710,0xd777ad6a,0x55e9936b,0x841287ef,0x04a21b24,0xbaf5c670, + 0x35ad86f1,0xf2c0725f,0xc707e72e,0x338fa650,0xd8883e52,0x2bf8ed2e }, + { 0xb56e0d6a,0xb0212cf4,0x6843290c,0x50537e12,0x98b3dc6f,0xd8b184a1, + 0x0210b722,0xd2be9a35,0x559781ee,0x407406db,0x0bc18534,0x5a78d591 } }, + /* 185 */ + { { 0xd748b02c,0x4d57aa2a,0xa12b3b95,0xbe5b3451,0x64711258,0xadca7a45, + 0x322153db,0x597e091a,0x32eb1eab,0xf3271006,0x2873f301,0xbd9adcba }, + { 0x38543f7f,0xd1dc79d1,0x921b1fef,0x00022092,0x1e5df8ed,0x86db3ef5, + 0x9e6b944a,0x888cae04,0x791a32b4,0x71bd29ec,0xa6d1c13e,0xd3516206 } }, + /* 186 */ + { { 0x55924f43,0x2ef6b952,0x4f9de8d5,0xd2f401ae,0xadc68042,0xfc73e8d7, + 0x0d9d1bb4,0x627ea70c,0xbbf35679,0xc3bb3e3e,0xd882dee4,0x7e8a254a }, + { 0xb5924407,0x08906f50,0xa1ad444a,0xf14a0e61,0x65f3738e,0xaa0efa21, + 0xae71f161,0xd60c7dd6,0xf175894d,0x9e8390fa,0x149f4c00,0xd115cd20 } }, + /* 187 */ + { { 0xa52abf77,0x2f2e2c1d,0x54232568,0xc2a0dca5,0x54966dcc,0xed423ea2, + 0xcd0dd039,0xe48c93c7,0x176405c7,0x1e54a225,0x70d58f2e,0x1efb5b16 }, + { 0x94fb1471,0xa751f9d9,0x67d2941d,0xfdb31e1f,0x53733698,0xa6c74eb2, + 0x89a0f64a,0xd3155d11,0xa4b8d2b6,0x4414cfe4,0xf7a8e9e3,0x8d5a4be8 } }, + /* 188 */ + { { 0x52669e98,0x5c96b4d4,0x8fd42a03,0x4547f922,0xd285174e,0xcf5c1319, + 0x064bffa0,0x805cd1ae,0x246d27e7,0x50e8bc4f,0xd5781e11,0xf89ef98f }, + { 0xdee0b63f,0xb4ff95f6,0x222663a4,0xad850047,0x4d23ce9c,0x02691860, + 0x50019f59,0x3e5309ce,0x69a508ae,0x27e6f722,0x267ba52c,0xe9376652 } }, + /* 189 */ + { { 0xc0368708,0xa04d289c,0x5e306e1d,0xc458872f,0x33112fea,0x76fa23de, + 0x6efde42e,0x718e3974,0x1d206091,0xf0c98cdc,0x14a71987,0x5fa3ca62 }, + { 0xdcaa9f2a,0xeee8188b,0x589a860d,0x312cc732,0xc63aeb1f,0xf9808dd6, + 0x4ea62b53,0x70fd43db,0x890b6e97,0x2c2bfe34,0xfa426aa6,0x105f863c } }, + /* 190 */ + { { 0xb38059ad,0x0b29795d,0x90647ea0,0x5686b77e,0xdb473a3e,0xeff0470e, + 0xf9b6d1e2,0x278d2340,0xbd594ec7,0xebbff95b,0xd3a7f23d,0xf4b72334 }, + { 0xa5a83f0b,0x2a285980,0x9716a8b3,0x0786c41a,0x22511812,0x138901bd, + 0xe2fede6e,0xd1b55221,0xdf4eb590,0x0806e264,0x762e462e,0x6c4c897e } }, + /* 191 */ + { { 0xb4b41d9d,0xd10b905f,0x4523a65b,0x826ca466,0xb699fa37,0x535bbd13, + 0x73bc8f90,0x5b9933d7,0xcd2118ad,0x9332d61f,0xd4a65fd0,0x158c693e }, + { 0xe6806e63,0x4ddfb2a8,0xb5de651b,0xe31ed3ec,0x819bc69a,0xf9460e51, + 0x2c76b1f8,0x6229c0d6,0x901970a3,0xbb78f231,0x9cee72b8,0x31f3820f } }, + /* 192 */ + { { 0xc09e1c72,0xe931caf2,0x12990cf4,0x0715f298,0x943262d8,0x33aad81d, + 0x73048d3f,0x5d292b7a,0xdc7415f6,0xb152aaa4,0x0fd19587,0xc3d10fd9 }, + { 0x75ddadd0,0xf76b35c5,0x1e7b694c,0x9f5f4a51,0xc0663025,0x2f1ab7eb, + 0x920260b0,0x01c9cc87,0x05d39da6,0xc4b1f61a,0xeb4a9c4e,0x6dcd76c4 } }, + /* 193 */ + { { 0xfdc83f01,0x0ba0916f,0x9553e4f9,0x354c8b44,0xffc5e622,0xa6cc511a, + 0xe95be787,0xb954726a,0x75b41a62,0xcb048115,0xebfde989,0xfa2ae6cd }, + { 0x0f24659a,0x6376bbc7,0x4c289c43,0x13a999fd,0xec9abd8b,0xc7134184, + 0xa789ab04,0x28c02bf6,0xd3e526ec,0xff841ebc,0x640893a8,0x442b191e } }, + /* 194 */ + { { 0xfa2b6e20,0x4cac6c62,0xf6d69861,0x97f29e9b,0xbc96d12d,0x228ab1db, + 0x5e8e108d,0x6eb91327,0x40771245,0xd4b3d4d1,0xca8a803a,0x61b20623 }, + { 0xa6a560b1,0x2c2f3b41,0x3859fcf4,0x879e1d40,0x024dbfc3,0x7cdb5145, + 0x3bfa5315,0x55d08f15,0xaa93823a,0x2f57d773,0xc6a2c9a2,0xa97f259c } }, + /* 195 */ + { { 0xe58edbbb,0xc306317b,0x79dfdf13,0x25ade51c,0x16d83dd6,0x6b5beaf1, + 0x1dd8f925,0xe8038a44,0xb2a87b6b,0x7f00143c,0xf5b438de,0xa885d00d }, + { 0xcf9e48bd,0xe9f76790,0xa5162768,0xf0bdf9f0,0xad7b57cb,0x0436709f, + 0xf7c15db7,0x7e151c12,0x5d90ee3b,0x3514f022,0x2c361a8d,0x2e84e803 } }, + /* 196 */ + { { 0x563ec8d8,0x2277607d,0xe3934cb7,0xa661811f,0xf58fd5de,0x3ca72e7a, + 0x62294c6a,0x7989da04,0xf6bbefe9,0x88b3708b,0x53ed7c82,0x0d524cf7 }, + { 0x2f30c073,0x69f699ca,0x9dc1dcf3,0xf0fa264b,0x05f0aaf6,0x44ca4568, + 0xd19b9baf,0x0f5b23c7,0xeabd1107,0x39193f41,0x2a7c9b83,0x9e3e10ad } }, + /* 197 */ + { { 0xd4ae972f,0xa90824f0,0xc6e846e7,0x43eef02b,0x29d2160a,0x7e460612, + 0xfe604e91,0x29a178ac,0x4eb184b2,0x23056f04,0xeb54cdf4,0x4fcad55f }, + { 0xae728d15,0xa0ff96f3,0xc6a00331,0x8a2680c6,0x7ee52556,0x5f84cae0, + 0xc5a65dad,0x5e462c3a,0xe2d23f4f,0x5d2b81df,0xc5b1eb07,0x6e47301b } }, + /* 198 */ + { { 0xaf8219b9,0x77411d68,0x51b1907a,0xcb883ce6,0x101383b5,0x25c87e57, + 0x982f970d,0x9c7d9859,0x118305d2,0xaa6abca5,0x9013a5db,0x725fed2f }, + { 0xababd109,0x487cdbaf,0x87586528,0xc0f8cf56,0x8ad58254,0xa02591e6, + 0xdebbd526,0xc071b1d1,0x961e7e31,0x927dfe8b,0x9263dfe1,0x55f895f9 } }, + /* 199 */ + { { 0xb175645b,0xf899b00d,0xb65b4b92,0x51f3a627,0xb67399ef,0xa2f3ac8d, + 0xe400bc20,0xe717867f,0x1967b952,0x42cc9020,0x3ecd1de1,0x3d596751 }, + { 0xdb979775,0xd41ebcde,0x6a2e7e88,0x99ba61bc,0x321504f2,0x039149a5, + 0x27ba2fad,0xe7dc2314,0xb57d8368,0x9f556308,0x57da80a7,0x2b6d16c9 } }, + /* 200 */ + { { 0x279ad982,0x84af5e76,0x9c8b81a6,0x9bb4c92d,0x0e698e67,0xd79ad44e, + 0x265fc167,0xe8be9048,0x0c3a4ccc,0xf135f7e6,0xb8863a33,0xa0a10d38 }, + { 0xd386efd9,0xe197247c,0xb52346c2,0x0eefd3f9,0x78607bc8,0xc22415f9, + 0x508674ce,0xa2a8f862,0xc8c9d607,0xa72ad09e,0x50fa764f,0xcd9f0ede } }, + /* 201 */ + { { 0xd1a46d4d,0x063391c7,0x9eb01693,0x2df51c11,0x849e83de,0xc5849800, + 0x8ad08382,0x48fd09aa,0xaa742736,0xa405d873,0xe1f9600c,0xee49e61e }, + { 0x48c76f73,0xd76676be,0x01274b2a,0xd9c100f6,0x83f8718d,0x110bb67c, + 0x02fc0d73,0xec85a420,0x744656ad,0xc0449e1e,0x37d9939b,0x28ce7376 } }, + /* 202 */ + { { 0x44544ac7,0x97e9af72,0xba010426,0xf2c658d5,0xfb3adfbd,0x732dec39, + 0xa2df0b07,0xd12faf91,0x2171e208,0x8ac26725,0x5b24fa54,0xf820cdc8 }, + { 0x94f4cf77,0x307a6eea,0x944a33c6,0x18c783d2,0x0b741ac5,0x4b939d4c, + 0x3ffbb6e4,0x1d7acd15,0x7a255e44,0x06a24858,0xce336d50,0x14fbc494 } }, + /* 203 */ + { { 0x51584e3c,0x9b920c0c,0xf7e54027,0xc7733c59,0x88422bbe,0xe24ce139, + 0x523bd6ab,0x11ada812,0xb88e6def,0xde068800,0xfe8c582d,0x7b872671 }, + { 0x7de53510,0x4e746f28,0xf7971968,0x492f8b99,0x7d928ac2,0x1ec80bc7, + 0x432eb1b5,0xb3913e48,0x32028f6e,0xad084866,0x8fc2f38b,0x122bb835 } }, + /* 204 */ + { { 0x3b0b29c3,0x0a9f3b1e,0x4fa44151,0x837b6432,0x17b28ea7,0xb9905c92, + 0x98451750,0xf39bc937,0xce8b6da1,0xcd383c24,0x010620b2,0x299f57db }, + { 0x58afdce3,0x7b6ac396,0x3d05ef47,0xa15206b3,0xb9bb02ff,0xa0ae37e2, + 0x9db3964c,0x107760ab,0x67954bea,0xe29de9a0,0x431c3f82,0x446a1ad8 } }, + /* 205 */ + { { 0x5c6b8195,0xc6fecea0,0xf49e71b9,0xd744a7c5,0x177a7ae7,0xa8e96acc, + 0x358773a7,0x1a05746c,0x37567369,0xa4162146,0x87d1c971,0xaa0217f7 }, + { 0x77fd3226,0x61e9d158,0xe4f600be,0x0f6f2304,0x7a6dff07,0xa9c4cebc, + 0x09f12a24,0xd15afa01,0x8c863ee9,0x2bbadb22,0xe5eb8c78,0xa28290e4 } }, + /* 206 */ + { { 0x3e9de330,0x55b87fa0,0x195c145b,0x12b26066,0xa920bef0,0xe08536e0, + 0x4d195adc,0x7bff6f2c,0x945f4187,0x7f319e9d,0xf892ce47,0xf9848863 }, + { 0x4fe37657,0xd0efc1d3,0x5cf0e45a,0x3c58de82,0x8b0ccbbe,0x626ad21a, + 0xaf952fc5,0xd2a31208,0xeb437357,0x81791995,0x98e95d4f,0x5f19d30f } }, + /* 207 */ + { { 0x0e6865bb,0x72e83d9a,0xf63456a6,0x22f5af3b,0x463c8d9e,0x409e9c73, + 0xdfe6970e,0x40e9e578,0x711b91ca,0x876b6efa,0x942625a3,0x895512cf }, + { 0xcb4e462b,0x84c8eda8,0x4412e7c8,0x84c0154a,0xceb7b71f,0x04325db1, + 0x66f70877,0x1537dde3,0x1992b9ac,0xf3a09399,0xd498ae77,0xa7316606 } }, + /* 208 */ + { { 0xcad260f5,0x13990d2f,0xeec0e8c0,0x76c3be29,0x0f7bd7d5,0x7dc5bee0, + 0xefebda4b,0x9be167d2,0x9122b87e,0xcce3dde6,0x82b5415c,0x75a28b09 }, + { 0xe84607a6,0xf6810bcd,0x6f4dbf0d,0xc6d58128,0x1b4dafeb,0xfead577d, + 0x066b28eb,0x9bc440b2,0x8b17e84b,0x53f1da97,0xcda9a575,0x0459504b } }, + /* 209 */ + { { 0x329e5836,0x13e39a02,0xf717269d,0x2c9e7d51,0xf26c963b,0xc5ac58d6, + 0x79967bf5,0x3b0c6c43,0x55908d9d,0x60bbea3f,0xf07c9ad1,0xd84811e7 }, + { 0x5bd20e4a,0xfe7609a7,0x0a70baa8,0xe4325dd2,0xb3600386,0x3711f370, + 0xd0924302,0x97f9562f,0x4acc4436,0x040dc0c3,0xde79cdd4,0xfd6d725c } }, + /* 210 */ + { { 0xcf13eafb,0xb3efd0e3,0x5aa0ae5f,0x21009cbb,0x79022279,0xe480c553, + 0xb2fc9a6d,0x755cf334,0x07096ae7,0x8564a5bf,0xbd238139,0xddd649d0 }, + { 0x8a045041,0xd0de10b1,0xc957d572,0x6e05b413,0x4e0fb25c,0x5c5ff806, + 0x641162fb,0xd933179b,0xe57439f9,0x42d48485,0x8a8d72aa,0x70c5bd0a } }, + /* 211 */ + { { 0x97bdf646,0xa7671738,0xab329f7c,0xaa1485b4,0xf8f25fdf,0xce3e11d6, + 0xc6221824,0x76a3fc7e,0xf3924740,0x045f281f,0x96d13a9a,0x24557d4e }, + { 0xdd4c27cd,0x875c804b,0x0f5c7fea,0x11c5f0f4,0xdc55ff7e,0xac8c880b, + 0x1103f101,0x2acddec5,0xf99faa89,0x38341a21,0xce9d6b57,0xc7b67a2c } }, + /* 212 */ + { { 0x8e357586,0x9a0d724f,0xdf648da0,0x1d7f4ff5,0xfdee62a5,0x9c3e6c9b, + 0x0389b372,0x0499cef0,0x98eab879,0xe904050d,0x6c051617,0xe8eef1b6 }, + { 0xc37e3ca9,0xebf5bfeb,0xa4e0b91d,0x7c5e946d,0x2c4bea28,0x79097314, + 0xee67b2b7,0x81f6c109,0xdafc5ede,0xaf237d9b,0x2abb04c7,0xd2e60201 } }, + /* 213 */ + { { 0x8a4f57bf,0x6156060c,0xff11182a,0xf9758696,0x6296ef00,0x8336773c, + 0xff666899,0x9c054bce,0x719cd11c,0xd6a11611,0xdbe1acfa,0x9824a641 }, + { 0xba89fd01,0x0b7b7a5f,0x889f79d8,0xf8d3b809,0xf578285c,0xc5e1ea08, + 0xae6d8288,0x7ac74536,0x7521ef5f,0x5d37a200,0xb260a25d,0x5ecc4184 } }, + /* 214 */ + { { 0xa708c8d3,0xddcebb19,0xc63f81ec,0xe63ed04f,0x11873f95,0xd045f5a0, + 0x79f276d5,0x3b5ad544,0x425ae5b3,0x81272a3d,0x10ce1605,0x8bfeb501 }, + { 0x888228bf,0x4233809c,0xb2aff7df,0x4bd82acf,0x0cbd4a7f,0x9c68f180, + 0x6b44323d,0xfcd77124,0x891db957,0x60c0fcf6,0x04da8f7f,0xcfbb4d89 } }, + /* 215 */ + { { 0x3b26139a,0x9a6a5df9,0xb2cc7eb8,0x3e076a83,0x5a964bcd,0x47a8e82d, + 0xb9278d6b,0x8a4e2a39,0xe4443549,0x93506c98,0xf1e0d566,0x06497a8f }, + { 0x2b1efa05,0x3dee8d99,0x45393e33,0x2da63ca8,0xcf0579ad,0xa4af7277, + 0x3236d8ea,0xaf4b4639,0x32b617f5,0x6ccad95b,0xb88bb124,0xce76d8b8 } }, + /* 216 */ + { { 0x083843dc,0x63d2537a,0x1e4153b4,0x89eb3514,0xea9afc94,0x5175ebc4, + 0x8ed1aed7,0x7a652580,0xd85e8297,0x67295611,0xb584b73d,0x8dd2d68b }, + { 0x0133c3a4,0x237139e6,0x4bd278ea,0x9de838ab,0xc062fcd9,0xe829b072, + 0x63ba8706,0x70730d4f,0xd3cd05ec,0x6080483f,0x0c85f84d,0x872ab5b8 } }, + /* 217 */ + { { 0x999d4d49,0xfc0776d3,0xec3f45e7,0xa3eb59de,0x0dae1fc1,0xbc990e44, + 0xa15371ff,0x33596b1e,0x9bc7ab25,0xd447dcb2,0x35979582,0xcd5b63e9 }, + { 0x77d1ff11,0xae3366fa,0xedee6903,0x59f28f05,0xa4433bf2,0x6f43fed1, + 0xdf9ce00e,0x15409c9b,0xaca9c5dc,0x21b5cded,0x82d7bdb4,0xf9f33595 } }, + /* 218 */ + { { 0x9422c792,0x95944378,0xc958b8bf,0x239ea923,0xdf076541,0x4b61a247, + 0xbb9fc544,0x4d29ce85,0x0b424559,0x9a692a67,0x0e486900,0x6e0ca5a0 }, + { 0x85b3bece,0x6b79a782,0xc61f9892,0x41f35e39,0xae747f82,0xff82099a, + 0xd0ca59d6,0x58c8ae3f,0x99406b5f,0x4ac930e2,0x9df24243,0x2ce04eb9 } }, + /* 219 */ + { { 0x1ac37b82,0x4366b994,0x25b04d83,0xff0c728d,0x19c47b7c,0x1f551361, + 0xbeff13e7,0xdbf2d5ed,0xe12a683d,0xf78efd51,0x989cf9c4,0x82cd85b9 }, + { 0xe0cb5d37,0xe23c6db6,0x72ee1a15,0x818aeebd,0x28771b14,0x8212aafd, + 0x1def817d,0x7bc221d9,0x9445c51f,0xdac403a2,0x12c3746b,0x711b0517 } }, + /* 220 */ + { { 0x5ea99ecc,0x0ed9ed48,0xb8cab5e1,0xf799500d,0xb570cbdc,0xa8ec87dc, + 0xd35dfaec,0x52cfb2c2,0x6e4d80a4,0x8d31fae2,0xdcdeabe5,0xe6a37dc9 }, + { 0x1deca452,0x5d365a34,0x0d68b44e,0x09a5f8a5,0xa60744b1,0x59238ea5, + 0xbb4249e9,0xf2fedc0d,0xa909b2e3,0xe395c74e,0x39388250,0xe156d1a5 } }, + /* 221 */ + { { 0x47181ae9,0xd796b3d0,0x44197808,0xbaf44ba8,0x34cf3fac,0xe6933094, + 0xc3bd5c46,0x41aa6ade,0xeed947c6,0x4fda75d8,0x9ea5a525,0xacd9d412 }, + { 0xd430301b,0x65cc55a3,0x7b52ea49,0x3c9a5bcf,0x159507f0,0x22d319cf, + 0xde74a8dd,0x2ee0b9b5,0x877ac2b6,0x20c26a1e,0x92e7c314,0x387d73da } }, + /* 222 */ + { { 0x8cd3fdac,0x13c4833e,0x332e5b8e,0x76fcd473,0xe2fe1fd3,0xff671b4b, + 0x5d98d8ec,0x4d734e8b,0x514bbc11,0xb1ead3c6,0x7b390494,0xd14ca858 }, + { 0x5d2d37e9,0x95a443af,0x00464622,0x73c6ea73,0x15755044,0xa44aeb4b, + 0xfab58fee,0xba3f8575,0xdc680a6f,0x9779dbc9,0x7b37ddfc,0xe1ee5f5a } }, + /* 223 */ + { { 0x12d29f46,0xcd0b4648,0x0ed53137,0x93295b0b,0x80bef6c9,0xbfe26094, + 0x54248b00,0xa6565788,0x80e7f9c4,0x69c43fca,0xbe141ea1,0x2190837b }, + { 0xa1b26cfb,0x875e159a,0x7affe852,0x90ca9f87,0x92ca598e,0x15e6550d, + 0x1938ad11,0xe3e0945d,0x366ef937,0xef7636bb,0xb39869e5,0xb6034d0b } }, + /* 224 */ + { { 0x26d8356e,0x4d255e30,0xd314626f,0xf83666ed,0xd0c8ed64,0x421ddf61, + 0x26677b61,0x96e473c5,0x9e9b18b3,0xdad4af7e,0xa9393f75,0xfceffd4a }, + { 0x11c731d5,0x843138a1,0xb2f141d9,0x05bcb3a1,0x617b7671,0x20e1fa95, + 0x88ccec7b,0xbefce812,0x90f1b568,0x582073dc,0x1f055cb7,0xf572261a } }, + /* 225 */ + { { 0x36973088,0xf3148277,0x86a9f980,0xc008e708,0xe046c261,0x1b795947, + 0xca76bca0,0xdf1e6a7d,0x71acddf0,0xabafd886,0x1364d8f4,0xff7054d9 }, + { 0xe2260594,0x2cf63547,0xd73b277e,0x468a5372,0xef9bd35e,0xc7419e24, + 0x24043cc3,0x2b4a1c20,0x890b39cd,0xa28f047a,0x46f9a2e3,0xdca2cea1 } }, + /* 226 */ + { { 0x53277538,0xab788736,0xcf697738,0xa734e225,0x6b22e2c1,0x66ee1d1e, + 0xebe1d212,0x2c615389,0x02bb0766,0xf36cad40,0x3e64f207,0x120885c3 }, + { 0x90fbfec2,0x59e77d56,0xd7a574ae,0xf9e781aa,0x5d045e53,0x801410b0, + 0xa91b5f0e,0xd3b5f0aa,0x7fbb3521,0xb3d1df00,0xc72bee9a,0x11c4b33e } }, + /* 227 */ + { { 0x83c3a7f3,0xd32b9832,0x88d8a354,0x8083abcf,0x50f4ec5a,0xdeb16404, + 0x641e2907,0x18d747f0,0xf1bbf03e,0x4e8978ae,0x88a0cd89,0x932447dc }, + { 0xcf3d5897,0x561e0feb,0x13600e6d,0xfc3a682f,0xd16a6b73,0xc78b9d73, + 0xd29bf580,0xe713fede,0x08d69e5c,0x0a225223,0x1ff7fda4,0x3a924a57 } }, + /* 228 */ + { { 0xb4093bee,0xfb64554c,0xa58c6ec0,0xa6d65a25,0x43d0ed37,0x4126994d, + 0x55152d44,0xa5689a51,0x284caa8d,0xb8e5ea8c,0xd1f25538,0x33f05d4f }, + { 0x1b615d6e,0xe0fdfe09,0x705507da,0x2ded7e8f,0x17bbcc80,0xdd5631e5, + 0x267fd11f,0x4f87453e,0xff89d62d,0xc6da723f,0xe3cda21d,0x55cbcae2 } }, + /* 229 */ + { { 0x6b4e84f3,0x336bc94e,0x4ef72c35,0x72863031,0xeeb57f99,0x6d85fdee, + 0xa42ece1b,0x7f4e3272,0x36f0320a,0x7f86cbb5,0x923331e6,0xf09b6a2b }, + { 0x56778435,0x21d3ecf1,0x8323b2d2,0x2977ba99,0x1704bc0f,0x6a1b57fb, + 0x389f048a,0xd777cf8b,0xac6b42cd,0x9ce2174f,0x09e6c55a,0x404e2bff } }, + /* 230 */ + { { 0x204c5ddb,0x9b9b135e,0x3eff550e,0x9dbfe044,0xec3be0f6,0x35eab4bf, + 0x0a43e56f,0x8b4c3f0d,0x0e73f9b3,0x4c1c6673,0x2c78c905,0x92ed38bd }, + { 0xa386e27c,0xc7003f6a,0xaced8507,0xb9c4f46f,0x59df5464,0xea024ec8, + 0x429572ea,0x4af96152,0xe1fc1194,0x279cd5e2,0x281e358c,0xaa376a03 } }, + /* 231 */ + { { 0x3cdbc95c,0x07859223,0xef2e337a,0xaae1aa6a,0x472a8544,0xc040108d, + 0x8d037b7d,0x80c853e6,0x8c7eee24,0xd221315c,0x8ee47752,0x195d3856 }, + { 0xdacd7fbe,0xd4b1ba03,0xd3e0c52b,0x4b5ac61e,0x6aab7b52,0x68d3c052, + 0x660e3fea,0xf0d7248c,0x3145efb4,0xafdb3f89,0x8f40936d,0xa73fd9a3 } }, + /* 232 */ + { { 0xbb1b17ce,0x891b9ef3,0xc6127f31,0x14023667,0x305521fd,0x12b2e58d, + 0xe3508088,0x3a47e449,0xff751507,0xe49fc84b,0x5310d16e,0x4023f722 }, + { 0xb73399fa,0xa608e5ed,0xd532aa3e,0xf12632d8,0x845e8415,0x13a2758e, + 0x1fc2d861,0xae4b6f85,0x339d02f2,0x3879f5b1,0x80d99ebd,0x446d22a6 } }, + /* 233 */ + { { 0x4be164f1,0x0f502302,0x88b81920,0x8d09d2d6,0x984aceff,0x514056f1, + 0x75e9e80d,0xa5c4ddf0,0xdf496a93,0x38cb47e6,0x38df6bf7,0x899e1d6b }, + { 0xb59eb2a6,0x69e87e88,0x9b47f38b,0x280d9d63,0x3654e955,0x599411ea, + 0x969aa581,0xcf8dd4fd,0x530742a7,0xff5c2baf,0x1a373085,0xa4391536 } }, + /* 234 */ + { { 0xa8a4bdd2,0x6ace72a3,0xb68ef702,0xc656cdd1,0x90c4dad8,0xd4a33e7e, + 0x9d951c50,0x4aece08a,0x085d68e6,0xea8005ae,0x6f7502b8,0xfdd7a7d7 }, + { 0x98d6fa45,0xce6fb0a6,0x1104eb8c,0x228f8672,0xda09d7dc,0xd23d8787, + 0x2ae93065,0x5521428b,0xea56c366,0x95faba3d,0x0a88aca5,0xedbe5039 } }, + /* 235 */ + { { 0xbfb26c82,0xd64da0ad,0x952c2f9c,0xe5d70b3c,0xf7e77f68,0xf5e8f365, + 0x08f2d695,0x7234e002,0xd12e7be6,0xfaf900ee,0x4acf734e,0x27dc6934 }, + { 0xc260a46a,0x80e4ff5e,0x2dc31c28,0x7da5ebce,0xca69f552,0x485c5d73, + 0x69cc84c2,0xcdfb6b29,0xed6d4eca,0x031c5afe,0x22247637,0xc7bbf4c8 } }, + /* 236 */ + { { 0x49fe01b2,0x9d5b72c7,0x793a91b8,0x34785186,0xcf460438,0xa3ba3c54, + 0x3ab21b6f,0x73e8e43d,0xbe57b8ab,0x50cde8e0,0xdd204264,0x6488b3a7 }, + { 0xdddc4582,0xa9e398b3,0x5bec46fe,0x1698c1a9,0x156d3843,0x7f1446ef, + 0x770329a2,0x3fd25dd8,0x2c710668,0x05b1221a,0xa72ee6cf,0x65b2dc2a } }, + /* 237 */ + { { 0xcd021d63,0x21a885f7,0xfea61f08,0x3f344b15,0xc5cf73e6,0xad5ba6dd, + 0x227a8b23,0x154d0d8f,0xdc559311,0x9b74373c,0x98620fa1,0x4feab715 }, + { 0x7d9ec924,0x5098938e,0x6d47e550,0x84d54a5e,0x1b617506,0x1a2d1bdc, + 0x615868a4,0x99fe1782,0x3005a924,0x171da780,0x7d8f79b6,0xa70bf5ed } }, + /* 238 */ + { { 0xfe2216c5,0x0bc1250d,0x7601b351,0x2c37e250,0xd6f06b7e,0xb6300175, + 0x8bfeb9b7,0x4dde8ca1,0xb82f843d,0x4f210432,0xb1ac0afd,0x8d70e2f9 }, + { 0xaae91abb,0x25c73b78,0x863028f2,0x0230dca3,0xe5cf30b7,0x8b923ecf, + 0x5506f265,0xed754ec2,0x729a5e39,0x8e41b88c,0xbabf889b,0xee67cec2 } }, + /* 239 */ + { { 0x1be46c65,0xe183acf5,0xe7565d7a,0x9789538f,0xd9627b4e,0x87873391, + 0x9f1d9187,0xbf4ac4c1,0x4691f5c8,0x5db99f63,0x74a1fb98,0xa68df803 }, + { 0xbf92b5fa,0x3c448ed1,0x3e0bdc32,0xa098c841,0x79bf016c,0x8e74cd55, + 0x115e244d,0x5df0d09c,0x3410b66e,0x9418ad01,0x17a02130,0x8b6124cb } }, + /* 240 */ + { { 0xc26e3392,0x425ec3af,0xa1722e00,0xc07f8470,0xe2356b43,0xdcc28190, + 0xb1ef59a6,0x4ed97dff,0xc63028c1,0xc22b3ad1,0x68c18988,0x070723c2 }, + { 0x4cf49e7d,0x70da302f,0x3f12a522,0xc5e87c93,0x18594148,0x74acdd1d, + 0xca74124c,0xad5f73ab,0xd69fd478,0xe72e4a3e,0x7b117cc3,0x61593868 } }, + /* 241 */ + { { 0xa9aa0486,0x7b7b9577,0xa063d557,0x6e41fb35,0xda9047d7,0xb017d5c7, + 0x68a87ba9,0x8c748280,0xdf08ad93,0xab45fa5c,0x4c288a28,0xcd9fb217 }, + { 0x5747843d,0x59544642,0xa56111e3,0x34d64c6c,0x4bfce8d5,0x12e47ea1, + 0x6169267f,0x17740e05,0xeed03fb5,0x5c49438e,0x4fc3f513,0x9da30add } }, + /* 242 */ + { { 0xccfa5200,0xc4e85282,0x6a19b13d,0x2707608f,0xf5726e2f,0xdcb9a53d, + 0xe9427de5,0x612407c9,0xd54d582a,0x3e5a17e1,0x655ae118,0xb99877de }, + { 0x015254de,0x6f0e972b,0xf0a6f7c5,0x92a56db1,0xa656f8b2,0xd297e4e1, + 0xad981983,0x99fe0052,0x07cfed84,0xd3652d2f,0x843c1738,0xc784352e } }, + /* 243 */ + { { 0x7e9b2d8a,0x6ee90af0,0x57cf1964,0xac8d7018,0x71f28efc,0xf6ed9031, + 0x6812b20e,0x7f70d5a9,0xf1c61eee,0x27b557f4,0xc6263758,0xf1c9bd57 }, + { 0x2a1a6194,0x5cf7d014,0x1890ab84,0xdd614e0b,0x0e93c2a6,0x3ef9de10, + 0xe0cd91c5,0xf98cf575,0x14befc32,0x504ec0c6,0x6279d68c,0xd0513a66 } }, + /* 244 */ + { { 0xa859fb6a,0xa8eadbad,0xdb283666,0xcf8346e7,0x3e22e355,0x7b35e61a, + 0x99639c6b,0x293ece2c,0x56f241c8,0xfa0162e2,0xbf7a1dda,0xd2e6c7b9 }, + { 0x40075e63,0xd0de6253,0xf9ec8286,0x2405aa61,0x8fe45494,0x2237830a, + 0x364e9c8c,0x4fd01ac7,0x904ba750,0x4d9c3d21,0xaf1b520b,0xd589be14 } }, + /* 245 */ + { { 0x4662e53b,0x13576a4f,0xf9077676,0x35ec2f51,0x97c0af97,0x66297d13, + 0x9e598b58,0xed3201fe,0x5e70f604,0x49bc752a,0xbb12d951,0xb54af535 }, + { 0x212c1c76,0x36ea4c2b,0xeb250dfd,0x18f5bbc7,0x9a0a1a46,0xa0d466cc, + 0xdac2d917,0x52564da4,0x8e95fab5,0x206559f4,0x9ca67a33,0x7487c190 } }, + /* 246 */ + { { 0xdde98e9c,0x75abfe37,0x2a411199,0x99b90b26,0xdcdb1f7c,0x1b410996, + 0x8b3b5675,0xab346f11,0xf1f8ae1e,0x04852193,0x6b8b98c1,0x1ec4d227 }, + { 0x45452baa,0xba3bc926,0xacc4a572,0x387d1858,0xe51f171e,0x9478eff6, + 0x931e1c00,0xf357077d,0xe54c8ca8,0xffee77cd,0x551dc9a4,0xfb4892ff } }, + /* 247 */ + { { 0x2db8dff8,0x5b1bdad0,0x5a2285a2,0xd462f4fd,0xda00b461,0x1d6aad8e, + 0x41306d1b,0x43fbefcf,0x6a13fe19,0x428e86f3,0x17f89404,0xc8b2f118 }, + { 0xf0d51afb,0x762528aa,0x549b1d06,0xa3e2fea4,0xea3ddf66,0x86fad8f2, + 0x4fbdd206,0x0d9ccc4b,0xc189ff5a,0xcde97d4c,0x199f19a6,0xc36793d6 } }, + /* 248 */ + { { 0x51b85197,0xea38909b,0xb4c92895,0xffb17dd0,0x1ddb3f3f,0x0eb0878b, + 0xc57cf0f2,0xb05d28ff,0x1abd57e2,0xd8bde2e7,0xc40c1b20,0x7f2be28d }, + { 0x299a2d48,0x6554dca2,0x8377982d,0x5130ba2e,0x1071971a,0x8863205f, + 0x7cf2825d,0x15ee6282,0x03748f2b,0xd4b6c57f,0x430385a0,0xa9e3f4da } }, + /* 249 */ + { { 0x83fbc9c6,0x33eb7cec,0x4541777e,0x24a311c7,0x4f0767fc,0xc81377f7, + 0x4ab702da,0x12adae36,0x2a779696,0xb7fcb6db,0x01cea6ad,0x4a6fb284 }, + { 0xcdfc73de,0x5e8b1d2a,0x1b02fd32,0xd0efae8d,0xd81d8519,0x3f99c190, + 0xfc808971,0x3c18f7fa,0x51b7ae7b,0x41f713e7,0xf07fc3f8,0x0a4b3435 } }, + /* 250 */ + { { 0x019b7d2e,0x7dda3c4c,0xd4dc4b89,0x631c8d1a,0x1cdb313c,0x5489cd6e, + 0x4c07bb06,0xd44aed10,0x75f000d1,0x8f97e13a,0xdda5df4d,0x0e9ee64f }, + { 0x3e346910,0xeaa99f3b,0xfa294ad7,0x622f6921,0x0d0b2fe9,0x22aaa20d, + 0x1e5881ba,0x4fed2f99,0xc1571802,0x9af3b2d6,0xdc7ee17c,0x919e67a8 } }, + /* 251 */ + { { 0x76250533,0xc724fe4c,0x7d817ef8,0x8a2080e5,0x172c9751,0xa2afb0f4, + 0x17c0702e,0x9b10cdeb,0xc9b7e3e9,0xbf3975e3,0x1cd0cdc5,0x206117df }, + { 0xbe05ebd5,0xfb049e61,0x16c782c0,0xeb0bb55c,0xab7fed09,0x13a331b8, + 0x632863f0,0xf6c58b1d,0x4d3b6195,0x6264ef6e,0x9a53f116,0x92c51b63 } }, + /* 252 */ + { { 0x288b364d,0xa57c7bc8,0x7b41e5c4,0x4a562e08,0x698a9a11,0x699d21c6, + 0xf3f849b9,0xa4ed9581,0x9eb726ba,0xa223eef3,0xcc2884f9,0x13159c23 }, + { 0x3a3f4963,0x73931e58,0x0ada6a81,0x96500389,0x5ab2950b,0x3ee8a1c6, + 0x775fab52,0xeedf4949,0x4f2671b6,0x63d652e1,0x3c4e2f55,0xfed4491c } }, + /* 253 */ + { { 0xf4eb453e,0x335eadc3,0xcadd1a5b,0x5ff74b63,0x5d84a91a,0x6933d0d7, + 0xb49ba337,0x9ca3eeb9,0xc04c15b8,0x1f6facce,0xdc09a7e4,0x4ef19326 }, + { 0x3dca3233,0x53d2d324,0xa2259d4b,0x0ee40590,0x5546f002,0x18c22edb, + 0x09ea6b71,0x92429801,0xb0e91e61,0xaada0add,0x99963c50,0x5fe53ef4 } }, + /* 254 */ + { { 0x90c28c65,0x372dd06b,0x119ce47d,0x1765242c,0x6b22fc82,0xc041fb80, + 0xb0a7ccc1,0x667edf07,0x1261bece,0xc79599e7,0x19cff22a,0xbc69d9ba }, + { 0x13c06819,0x009d77cd,0xe282b79d,0x635a66ae,0x225b1be8,0x4edac4a6, + 0x524008f9,0x57d4f4e4,0xb056af84,0xee299ac5,0x3a0bc386,0xcc38444c } }, + /* 255 */ + { { 0xcd4c2356,0x490643b1,0x750547be,0x740a4851,0xd4944c04,0x643eaf29, + 0x299a98a0,0xba572479,0xee05fdf9,0x48b29f16,0x089b2d7b,0x33fb4f61 }, + { 0xa950f955,0x86704902,0xfedc3ddf,0x97e1034d,0x05fbb6a2,0x211320b6, + 0x432299bb,0x23d7b93f,0x8590e4a3,0x1fe1a057,0xf58c0ce6,0x8e1d0586 } }, +}; + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_12(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + return sp_384_ecc_mulmod_stripe_12(r, &p384_base, p384_table, + k, map, heap); +} + +#endif + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[12]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_384_point_new_12(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 12, km); + + err = sp_384_ecc_mulmod_base_12(point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_12(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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_384_iszero_12(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] | a[10] | a[11]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +SP_NOINLINE static void sp_384_add_one_12(sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r2, #1\n\t" + "ldr r1, [%[a], #0]\n\t" + "adds r1, r1, r2\n\t" + "mov r2, #0\n\t" + "str r1, [%[a], #0]\n\t" + "ldr r1, [%[a], #4]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #4]\n\t" + "ldr r1, [%[a], #8]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #8]\n\t" + "ldr r1, [%[a], #12]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #12]\n\t" + "ldr r1, [%[a], #16]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #16]\n\t" + "ldr r1, [%[a], #20]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #20]\n\t" + "ldr r1, [%[a], #24]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #24]\n\t" + "ldr r1, [%[a], #28]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #28]\n\t" + "ldr r1, [%[a], #32]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #32]\n\t" + "ldr r1, [%[a], #36]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #36]\n\t" + "ldr r1, [%[a], #40]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #40]\n\t" + "ldr r1, [%[a], #44]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #44]\n\t" + : + : [a] "r" (a) + : "memory", "r1", "r2" + ); +} + +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((sp_digit)a[i]) << s); + if (s >= 24U) { + r[j] &= 0xffffffff; + s = 32U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (sp_digit)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; 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_384_ecc_gen_k_12(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[48]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_384_from_bin(k, 12, buf, (int)sizeof(buf)); + if (sp_384_cmp_12(k, p384_order2) < 0) { + sp_384_add_one_12(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_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[12]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 inf; +#endif +#endif + sp_point_384* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity; +#endif + int err; + + (void)heap; + + err = sp_384_point_new_12(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + err = sp_384_ecc_gen_k_12(rng, k); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_12(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_12(infinity, point, p384_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_384_iszero_12(point->x) == 0) || (sp_384_iszero_12(point->y) == 0)) { + err = ECC_INF_E; + } + } +#endif + + if (err == MP_OKAY) { + err = sp_384_to_mp(k, priv); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_12(point, pub); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_384_point_free_12(infinity, 1, heap); +#endif + sp_384_point_free_12(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 48 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_384_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 384 / 8 - 1; + a[j] = 0; + for (i=0; i<12 && j>=0; i++) { + b = 0; + /* lint allow cast of mismatch sp_digit and int */ + a[j--] |= (byte)(r[i] << s); /*lint !e9033*/ + b += 8 - s; + if (j < 0) { + break; + } + while (b < 32) { + a[j--] = (byte)(r[i] >> b); + b += 8; + if (j < 0) { + break; + } + } + s = 8 - (b - 32); + if (j >= 0) { + 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_384(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[12]; +#endif + sp_point_384* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 48U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(k, 12, priv); + sp_384_point_from_ecc_point_12(point, pub); + err = sp_384_ecc_mulmod_12(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_384_to_bin(point->x, out); + *outLen = 48; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_384_sub_in_place_12(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r8, %[a]\n\t" + "add r8, r8, #48\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r8\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r8" + ); + + return c; +} + +#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. + */ +SP_NOINLINE static sp_digit sp_384_sub_in_place_12(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "ldm %[a], {r3, r4}\n\t" + "ldm %[b]!, {r5, r6}\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "stm %[a]!, {r3, r4}\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* 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. + */ +SP_NOINLINE static void sp_384_mul_d_12(sp_digit* r, const sp_digit* a, + sp_digit b) +{ + __asm__ __volatile__ ( + "add r9, %[a], #48\n\t" + /* A[0] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r5, r3, r6, %[b]\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]], #4\n\t" + /* A[0] * B - Done */ + "\n1:\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]], #4\n\t" + "umull r6, r8, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r8\n\t" + "adc r5, r5, #0\n\t" + /* A[] * B - Done */ + "str r3, [%[r]], #4\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r8", "r9" + ); +} + +/* 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. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_384_word_12(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r8, r4, #16\n\t" + "umull r4, r5, %[div], r8\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr #16\n\t" + "udiv r4, r4, r6\n\t" + "add r8, r8, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r8, r8, r4\n\t" + "mov %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r8" + ); + 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_384_mask_12(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<12; 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; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; + r[8] = a[8] & m; + r[9] = a[9] & m; + r[10] = a[10] & m; + r[11] = a[11] & 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 WC_INLINE int sp_384_div_12(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[24], t2[13]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[11]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 12); + for (i=11; i>=0; i--) { + r1 = div_384_word_12(t1[12 + i], t1[12 + i - 1], div); + + sp_384_mul_d_12(t2, d, r1); + t1[12 + i] += sp_384_sub_in_place_12(&t1[i], t2); + t1[12 + i] -= t2[12]; + sp_384_mask_12(t2, d, t1[12 + i]); + t1[12 + i] += sp_384_add_12(&t1[i], &t1[i], t2); + sp_384_mask_12(t2, d, t1[12 + i]); + t1[12 + i] += sp_384_add_12(&t1[i], &t1[i], t2); + } + + r1 = sp_384_cmp_12(t1, d) >= 0; + sp_384_cond_sub_12(r, t1, d, (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 WC_INLINE int sp_384_mod_12(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_384_div_12(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P384 curve. */ +static const uint32_t p384_order_minus_2[12] = { + 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U, + 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU +}; +#else +/* The low half of the order-2 of the P384 curve. */ +static const uint32_t p384_order_low[6] = { + 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U + +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P384 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_384_mont_mul_order_12(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_384_mul_12(r, a, b); + sp_384_mont_reduce_order_12(r, p384_order, p384_mp_order); +} + +/* Square number mod the order of P384 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_order_12(sp_digit* r, const sp_digit* a) +{ + sp_384_sqr_12(r, a); + sp_384_mont_reduce_order_12(r, p384_order, p384_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P384 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_n_order_12(sp_digit* r, const sp_digit* a, int n) +{ + int i; + + sp_384_mont_sqr_order_12(r, a); + for (i=1; i=0; i--) { + sp_384_mont_sqr_order_12(t, t); + if ((p384_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_384_mont_mul_order_12(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 12U); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 12; + sp_digit* t3 = td + 4 * 12; + int i; + + /* t = a^2 */ + sp_384_mont_sqr_order_12(t, a); + /* t = a^3 = t * a */ + sp_384_mont_mul_order_12(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_384_mont_sqr_n_order_12(t2, t, 2); + /* t = a^f = t2 * t */ + sp_384_mont_mul_order_12(t, t2, t); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_384_mont_sqr_n_order_12(t2, t, 4); + /* t = a^ff = t2 * t */ + sp_384_mont_mul_order_12(t, t2, t); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_384_mont_sqr_n_order_12(t2, t, 8); + /* t3= a^ffff = t2 * t */ + sp_384_mont_mul_order_12(t3, t2, t); + /* t2= a^ffff0000 = t3 ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_12(t2, t3, 16); + /* t = a^ffffffff = t2 * t3 */ + sp_384_mont_mul_order_12(t, t2, t3); + /* t2= a^ffffffff0000 = t ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_12(t2, t, 16); + /* t = a^ffffffffffff = t2 * t3 */ + sp_384_mont_mul_order_12(t, t2, t3); + /* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */ + sp_384_mont_sqr_n_order_12(t2, t, 48); + /* t= a^fffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_12(t, t2, t); + /* t2= a^ffffffffffffffffffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_order_12(t2, t, 96); + /* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_12(t2, t2, t); + for (i=191; i>=1; i--) { + sp_384_mont_sqr_order_12(t2, t2); + if (((sp_digit)p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + sp_384_mont_mul_order_12(t2, t2, a); + } + } + sp_384_mont_sqr_order_12(t2, t2); + sp_384_mont_mul_order_12(r, t2, a); +#endif /* WOLFSSL_SP_SMALL */ +} + +#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, 384 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 384 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_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit ed[2*12]; + sp_digit xd[2*12]; + sp_digit kd[2*12]; + sp_digit rd[2*12]; + sp_digit td[3 * 2*12]; + sp_point_384 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_384* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int32_t c; + int i; + + (void)heap; + + err = sp_384_point_new_12(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 12; + x = d + 2 * 12; + k = d + 4 * 12; + r = d + 6 * 12; + tmp = d + 8 * 12; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(e, 12, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_384_from_mp(x, 12, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_12(rng, k); + } + else { + sp_384_from_mp(k, 12, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_12(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 12U); + sp_384_norm_12(r); + c = sp_384_cmp_12(r, p384_order); + sp_384_cond_sub_12(r, r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(r); + + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_12(k, k, p384_norm_order); + err = sp_384_mod_12(k, k, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_12(k); + /* kInv = 1/k mod order */ + sp_384_mont_inv_order_12(kInv, k, tmp); + sp_384_norm_12(kInv); + + /* s = r * x + e */ + sp_384_mul_12(x, x, r); + err = sp_384_mod_12(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_12(x); + carry = sp_384_add_12(s, e, x); + sp_384_cond_sub_12(s, s, p384_order, 0 - carry); + sp_384_norm_12(s); + c = sp_384_cmp_12(s, p384_order); + sp_384_cond_sub_12(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_12(s, s, kInv); + sp_384_norm_12(s); + + /* Check that signature is usable. */ + if (sp_384_iszero_12(s) == 0) { + break; + } + } + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 12); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U); +#endif + sp_384_point_free_12(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, 384) + * 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 384 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_384(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit u1d[2*12]; + sp_digit u2d[2*12]; + sp_digit sd[2*12]; + sp_digit tmpd[2*12 * 5]; + sp_point_384 p1d; + sp_point_384 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p1; + sp_point_384* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + + err = sp_384_point_new_12(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 12, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 12; + u2 = d + 2 * 12; + s = d + 4 * 12; + tmp = d + 6 * 12; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 12, hash, (int)hashLen); + sp_384_from_mp(u2, 12, r); + sp_384_from_mp(s, 12, sm); + sp_384_from_mp(p2->x, 12, pX); + sp_384_from_mp(p2->y, 12, pY); + sp_384_from_mp(p2->z, 12, pZ); + + { + sp_384_mul_12(s, s, p384_norm_order); + } + err = sp_384_mod_12(s, s, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_12(s); + { + sp_384_mont_inv_order_12(s, s, tmp); + sp_384_mont_mul_order_12(u1, u1, s); + sp_384_mont_mul_order_12(u2, u2, s); + } + + err = sp_384_ecc_mulmod_base_12(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_12(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + { + sp_384_proj_point_add_12(p1, p1, p2, tmp); + if (sp_384_iszero_12(p1->z)) { + if (sp_384_iszero_12(p1->x) && sp_384_iszero_12(p1->y)) { + sp_384_proj_point_dbl_12(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + p1->x[6] = 0; + p1->x[7] = 0; + p1->x[8] = 0; + p1->x[9] = 0; + p1->x[10] = 0; + p1->x[11] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + } + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 12, r); + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_12(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 12, r); + carry = sp_384_add_12(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_12(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_12(u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_384_point_free_12(p1, 0, heap); + sp_384_point_free_12(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_384_ecc_is_point_12(sp_point_384* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*12]; + sp_digit t2d[2*12]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 12; + t2 = d + 2 * 12; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_384_sqr_12(t1, point->y); + (void)sp_384_mod_12(t1, t1, p384_mod); + sp_384_sqr_12(t2, point->x); + (void)sp_384_mod_12(t2, t2, p384_mod); + sp_384_mul_12(t2, t2, point->x); + (void)sp_384_mod_12(t2, t2, p384_mod); + (void)sp_384_sub_12(t2, p384_mod, t2); + sp_384_mont_add_12(t1, t1, t2, p384_mod); + + sp_384_mont_add_12(t1, t1, point->x, p384_mod); + sp_384_mont_add_12(t1, t1, point->x, p384_mod); + sp_384_mont_add_12(t1, t1, point->x, p384_mod); + + if (sp_384_cmp_12(t1, p384_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 pubd; +#endif + sp_point_384* pub; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_12(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_384_from_mp(pub->x, 12, pX); + sp_384_from_mp(pub->y, 12, pY); + sp_384_from_bin(pub->z, 12, one, (int)sizeof(one)); + + err = sp_384_ecc_is_point_12(pub, NULL); + } + + sp_384_point_free_12(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[12]; + sp_point_384 pubd; + sp_point_384 pd; +#endif + sp_digit* priv = NULL; + sp_point_384* pub; + sp_point_384* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_12(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_384_point_new_12(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 12, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_384_from_mp(pub->x, 12, pX); + sp_384_from_mp(pub->y, 12, pY); + sp_384_from_bin(pub->z, 12, one, (int)sizeof(one)); + sp_384_from_mp(priv, 12, privm); + + /* Check point at infinitiy. */ + if ((sp_384_iszero_12(pub->x) != 0) && + (sp_384_iszero_12(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_384_cmp_12(pub->x, p384_mod) >= 0 || + sp_384_cmp_12(pub->y, p384_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_384_ecc_is_point_12(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_384_ecc_mulmod_12(p, pub, p384_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_384_iszero_12(p->x) == 0) || + (sp_384_iszero_12(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_384_ecc_mulmod_base_12(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_384_cmp_12(p->x, pub->x) != 0 || + sp_384_cmp_12(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, heap); + sp_384_point_free_12(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 12 * 5]; + sp_point_384 pd; + sp_point_384 qd; +#endif + sp_digit* tmp; + sp_point_384* p; + sp_point_384* q = NULL; + int err; + + err = sp_384_point_new_12(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_384_point_new_12(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 12, pX); + sp_384_from_mp(p->y, 12, pY); + sp_384_from_mp(p->z, 12, pZ); + sp_384_from_mp(q->x, 12, qX); + sp_384_from_mp(q->y, 12, qY); + sp_384_from_mp(q->z, 12, qZ); + + sp_384_proj_point_add_12(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(q, 0, NULL); + sp_384_point_free_12(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 12 * 2]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_12(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 12, pX); + sp_384_from_mp(p->y, 12, pY); + sp_384_from_mp(p->z, 12, pZ); + + sp_384_proj_point_dbl_12(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 12 * 6]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_12(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 12 * 6, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 12, pX); + sp_384_from_mp(p->y, 12, pY); + sp_384_from_mp(p->z, 12, pZ); + + sp_384_map_12(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_12(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mont_sqrt_12(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 12]; + sp_digit t2d[2 * 12]; + sp_digit t3d[2 * 12]; + sp_digit t4d[2 * 12]; + sp_digit t5d[2 * 12]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 12; + t2 = d + 2 * 12; + t3 = d + 4 * 12; + t4 = d + 6 * 12; + t5 = d + 8 * 12; +#else + t1 = t1d; + t2 = t2d; + t3 = t3d; + t4 = t4d; + t5 = t5d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_384_mont_sqr_12(t2, y, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3 */ + sp_384_mont_mul_12(t1, t2, y, p384_mod, p384_mp_mod); + /* t5 = y ^ 0xc */ + sp_384_mont_sqr_n_12(t5, t1, 2, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xf */ + sp_384_mont_mul_12(t1, t1, t5, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x1e */ + sp_384_mont_sqr_12(t2, t1, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x1f */ + sp_384_mont_mul_12(t3, t2, y, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3e0 */ + sp_384_mont_sqr_n_12(t2, t3, 5, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3ff */ + sp_384_mont_mul_12(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fe0 */ + sp_384_mont_sqr_n_12(t2, t1, 5, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x7fff */ + sp_384_mont_mul_12(t3, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fff800 */ + sp_384_mont_sqr_n_12(t2, t3, 15, p384_mod, p384_mp_mod); + /* t4 = y ^ 0x3ffffff */ + sp_384_mont_mul_12(t4, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffc000000 */ + sp_384_mont_sqr_n_12(t2, t4, 30, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffff */ + sp_384_mont_mul_12(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_12(t2, t1, 60, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_12(t2, t1, 120, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_12(t2, t1, 15, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_12(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */ + sp_384_mont_sqr_n_12(t2, t1, 31, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */ + sp_384_mont_mul_12(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */ + sp_384_mont_sqr_n_12(t2, t1, 4, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */ + sp_384_mont_mul_12(t1, t5, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */ + sp_384_mont_sqr_n_12(t2, t1, 62, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */ + sp_384_mont_mul_12(t1, y, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */ + sp_384_mont_sqr_n_12(y, t1, 30, p384_mod, p384_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 12]; + sp_digit yd[2 * 12]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 12, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 12; + y = d + 2 * 12; +#else + x = xd; + y = yd; +#endif + + sp_384_from_mp(x, 12, xm); + err = sp_384_mod_mul_norm_12(x, x, p384_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_384_mont_sqr_12(y, x, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(y, y, x, p384_mod, p384_mp_mod); + } + /* y = x^3 - 3x */ + sp_384_mont_sub_12(y, y, x, p384_mod); + sp_384_mont_sub_12(y, y, x, p384_mod); + sp_384_mont_sub_12(y, y, x, p384_mod); + /* y = x^3 - 3x + b */ + err = sp_384_mod_mul_norm_12(x, p384_b, p384_mod); + } + if (err == MP_OKAY) { + sp_384_mont_add_12(y, y, x, p384_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_384_mont_sqrt_12(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 12, 0, 12U * sizeof(sp_digit)); + sp_384_mont_reduce_12(y, p384_mod, p384_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_384_mont_sub_12(y, p384_mod, y, p384_mod); + } + + err = sp_384_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_384 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_SP_ARM_CORTEX_M_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_dsp32.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_dsp32.c new file mode 100644 index 000000000..ef95c06fb --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_dsp32.c @@ -0,0 +1,4908 @@ +/* sp_cdsp_signed.c + * + * Copyright (C) 2006-2020 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 + */ + +/* from wolfcrypt/src/sp_c32.c */ + +#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_ECC) +#ifdef WOLFSSL_DSP + +#include +#include "remote.h" +#include "hexagon_protos.h" +#include "hexagon_types.h" + +#if (defined(WOLFSSL_SP_CACHE_RESISTANT) || defined(WOLFSSL_SP_SMALL)) && (defined(WOLFSSL_HAVE_SP_ECC) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* 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 + +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point { + sp_digit x[2 * 10] __attribute__((aligned(128))); + sp_digit y[2 * 10] __attribute__((aligned(128))); + sp_digit z[2 * 10] __attribute__((aligned(128))); + int infinity; +} sp_point; + +/* The modulus (prime) of the curve P256. */ +static const sp_digit p256_mod[10] __attribute__((aligned(128))) = { + 0x3ffffff,0x3ffffff,0x3ffffff,0x003ffff,0x0000000,0x0000000,0x0000000, + 0x0000400,0x3ff0000,0x03fffff +}; +#ifndef WOLFSSL_SP_SMALL +/* The Montogmery normalizer for modulus of the curve P256. */ +static const sp_digit p256_norm_mod[10] __attribute__((aligned(128))) = { + 0x0000001,0x0000000,0x0000000,0x3fc0000,0x3ffffff,0x3ffffff,0x3ffffff, + 0x3fffbff,0x000ffff,0x0000000 +}; +#endif /* WOLFSSL_SP_SMALL */ +/* The Montogmery multiplier for modulus of the curve P256. */ +static const sp_digit p256_mp_mod __attribute__((aligned(128))) = 0x000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static const sp_digit p256_order[10] __attribute__((aligned(128))) = { + 0x0632551,0x272b0bf,0x1e84f3b,0x2b69c5e,0x3bce6fa,0x3ffffff,0x3ffffff, + 0x00003ff,0x3ff0000,0x03fffff +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static const sp_digit p256_norm_order[10] __attribute__((aligned(128))) = { + 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 const sp_digit p256_mp_order __attribute__((aligned(128))) = 0x200bc4f; +#endif +/* The base point of curve P256. */ +static const sp_point p256_base __attribute__((aligned(128))) = { + /* X ordinate */ + { + 0x098c296,0x04e5176,0x33a0f4a,0x204b7ac,0x277037d,0x0e9103c,0x3ce6e56, + 0x1091fe2,0x1f2e12c,0x01ac5f4, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x3bf51f5,0x1901a0d,0x1ececbb,0x15dacc5,0x22bce33,0x303e785,0x27eb4a7, + 0x1fe6e3b,0x2e2fe1a,0x013f8d0, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000,0x0000000,0x0000000, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; + +static int sp_ecc_point_new_ex(void* heap, sp_point* sp, sp_point** p) +{ + int ret = MP_OKAY; + (void)heap; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + (void)sp; + *p = (sp_point*)XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* Allocate memory for point and return error. */ +#define sp_ecc_point_new(heap, sp, p) sp_ecc_point_new_ex((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_ecc_point_new(heap, sp, p) sp_ecc_point_new_ex((heap), &(sp), &(p)) +#endif + + +static void sp_ecc_point_free(sp_point* p, int clear, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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, const sp_digit* a, const 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 = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = td; + a32 = td + 8; +#else + t = td; + a32 = a32d; +#endif + + a32[0] = a[0]; + a32[0] |= a[1] << 26U; + a32[0] &= 0xffffffffL; + a32[1] = (sp_digit)(a[1] >> 6); + a32[1] |= a[2] << 20U; + a32[1] &= 0xffffffffL; + a32[2] = (sp_digit)(a[2] >> 12); + a32[2] |= a[3] << 14U; + a32[2] &= 0xffffffffL; + a32[3] = (sp_digit)(a[3] >> 18); + a32[3] |= a[4] << 8U; + a32[3] &= 0xffffffffL; + a32[4] = (sp_digit)(a[4] >> 24); + a32[4] |= a[5] << 2U; + a32[4] |= a[6] << 28U; + a32[4] &= 0xffffffffL; + a32[5] = (sp_digit)(a[6] >> 4); + a32[5] |= a[7] << 22U; + a32[5] &= 0xffffffffL; + a32[6] = (sp_digit)(a[7] >> 10); + a32[6] |= a[8] << 16U; + a32[6] &= 0xffffffffL; + a32[7] = (sp_digit)(a[8] >> 16); + a32[7] |= a[9] << 10U; + a32[7] &= 0xffffffffL; + + /* 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] >> 32U; t[0] &= 0xffffffffL; + t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; + t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; + t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; + t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; + t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; + t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; + o = t[7] >> 32U; t[7] &= 0xffffffffL; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32U; t[0] &= 0xffffffffL; + t[2] += t[1] >> 32U; t[1] &= 0xffffffffL; + t[3] += t[2] >> 32U; t[2] &= 0xffffffffL; + t[4] += t[3] >> 32U; t[3] &= 0xffffffffL; + t[5] += t[4] >> 32U; t[4] &= 0xffffffffL; + t[6] += t[5] >> 32U; t[5] &= 0xffffffffL; + t[7] += t[6] >> 32U; t[6] &= 0xffffffffL; + + r[0] = (sp_digit)(t[0]) & 0x3ffffffL; + r[1] = (sp_digit)(t[0] >> 26U); + r[1] |= t[1] << 6U; + r[1] &= 0x3ffffffL; + r[2] = (sp_digit)(t[1] >> 20U); + r[2] |= t[2] << 12U; + r[2] &= 0x3ffffffL; + r[3] = (sp_digit)(t[2] >> 14U); + r[3] |= t[3] << 18U; + r[3] &= 0x3ffffffL; + r[4] = (sp_digit)(t[3] >> 8U); + r[4] |= t[4] << 24U; + r[4] &= 0x3ffffffL; + r[5] = (sp_digit)(t[4] >> 2U) & 0x3ffffffL; + r[6] = (sp_digit)(t[4] >> 28U); + r[6] |= t[5] << 4U; + r[6] &= 0x3ffffffL; + r[7] = (sp_digit)(t[5] >> 22U); + r[7] |= t[6] << 10U; + r[7] &= 0x3ffffffL; + r[8] = (sp_digit)(t[6] >> 16U); + r[8] |= t[7] << 16U; + r[8] &= 0x3ffffffL; + r[9] = (sp_digit)(t[7] >> 10U); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) { + XFREE(td, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + 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 == 0) ? (sp_digit)1 : (sp_digit)0)); + } +#else + r |= (a[ 9] - b[ 9]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 8] - b[ 8]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 7] - b[ 7]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 6] - b[ 6]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 5] - b[ 5]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 4] - b[ 4]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 3] - b[ 3]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 2] - b[ 2]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 1] - b[ 1]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); + r |= (a[ 0] - b[ 0]) & (0 - ((r == 0) ? (sp_digit)1 : (sp_digit)0)); +#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] = Q6_R_and_RR(a[0], 0x3ffffff); + a[2] += a[1] >> 26; a[1] = Q6_R_and_RR(a[1], 0x3ffffff); + a[3] += a[2] >> 26; a[2] = Q6_R_and_RR(a[2], 0x3ffffff); + a[4] += a[3] >> 26; a[3] = Q6_R_and_RR(a[3], 0x3ffffff); + a[5] += a[4] >> 26; a[4] = Q6_R_and_RR(a[4], 0x3ffffff); + a[6] += a[5] >> 26; a[5] = Q6_R_and_RR(a[5], 0x3ffffff); + a[7] += a[6] >> 26; a[6] = Q6_R_and_RR(a[6], 0x3ffffff); + a[8] += a[7] >> 26; a[7] = Q6_R_and_RR(a[7], 0x3ffffff); + a[9] += a[8] >> 26; a[8] = Q6_R_and_RR(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] = Q6_R_sub_RR(a[ 0], Q6_R_and_RR(b[ 0], m)); + r[ 1] = Q6_R_sub_RR(a[ 1], Q6_R_and_RR(b[ 1], m)); + r[ 2] = Q6_R_sub_RR(a[ 2], Q6_R_and_RR(b[ 2], m)); + r[ 3] = Q6_R_sub_RR(a[ 3], Q6_R_and_RR(b[ 3], m)); + r[ 4] = Q6_R_sub_RR(a[ 4], Q6_R_and_RR(b[ 4], m)); + r[ 5] = Q6_R_sub_RR(a[ 5], Q6_R_and_RR(b[ 5], m)); + r[ 6] = Q6_R_sub_RR(a[ 6], Q6_R_and_RR(b[ 6], m)); + r[ 7] = Q6_R_sub_RR(a[ 7], Q6_R_and_RR(b[ 7], m)); + r[ 8] = Q6_R_sub_RR(a[ 8], Q6_R_and_RR(b[ 8], m)); + r[ 9] = Q6_R_sub_RR(a[ 9], Q6_R_and_RR(b[ 9], m)); +#endif /* WOLFSSL_SP_SMALL */ +} + +#define sp_256_mont_reduce_order_10 sp_256_mont_reduce_10 + +/* 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. + */ +SP_NOINLINE 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] = Q6_P_mpy_RR(tb, a[ 0]); + t[ 1] = Q6_P_mpy_RR(tb, a[ 1]); + t[ 2] = Q6_P_mpy_RR(tb, a[ 2]); + t[ 3] = Q6_P_mpy_RR(tb, a[ 3]); + t[ 4] = Q6_P_mpy_RR(tb, a[ 4]); + t[ 5] = Q6_P_mpy_RR(tb, a[ 5]); + t[ 6] = Q6_P_mpy_RR(tb, a[ 6]); + t[ 7] = Q6_P_mpy_RR(tb, a[ 7]); + t[ 8] = Q6_P_mpy_RR(tb, a[ 8]); + t[ 9] = Q6_P_mpy_RR(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] = Q6_R_and_RR(n, 0x3ffffff); + n >>= 26; s = a[11] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 1] = Q6_R_and_RR(n, 0x3ffffff); + n >>= 26; s = a[12] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 2] = Q6_R_and_RR(n, 0x3ffffff); + n >>= 26; s = a[13] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 3] = Q6_R_and_RR(n, 0x3ffffff); + n >>= 26; s = a[14] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 4] = Q6_R_and_RR(n, 0x3ffffff); + n >>= 26; s = a[15] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 5] = Q6_R_and_RR(n, 0x3ffffff); + n >>= 26; s = a[16] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 6] = Q6_R_and_RR(n, 0x3ffffff); + n >>= 26; s = a[17] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 7] = Q6_R_and_RR(n, 0x3ffffff); + n >>= 26; s = a[18] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 8] = Q6_R_and_RR(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) * 10U); +} + + +/* 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, const sp_digit* m, sp_digit mp) +{ + sp_digit mu; + + + /* unrolled for loops due to unexpected behavior with -O optimizations */ + if (mp != 1) { + mu = Q6_P_mpy_RR(a[0], mp) & 0x3ffffff; + sp_256_mul_add_10(a+0, m, mu); + a[0+1] += a[0] >> 26; + + mu = Q6_P_mpy_RR(a[1], mp) & 0x3ffffff; + sp_256_mul_add_10(a+1, m, mu); + a[1+1] += a[1] >> 26; + + mu = Q6_P_mpy_RR(a[2], mp) & 0x3ffffff; + sp_256_mul_add_10(a+2, m, mu); + a[2+1] += a[2] >> 26; + + mu = Q6_P_mpy_RR(a[3], mp) & 0x3ffffff; + sp_256_mul_add_10(a+3, m, mu); + a[3+1] += a[3] >> 26; + + mu = Q6_P_mpy_RR(a[4], mp) & 0x3ffffff; + sp_256_mul_add_10(a+4, m, mu); + a[4+1] += a[4] >> 26; + + mu = Q6_P_mpy_RR(a[5], mp) & 0x3ffffff; + sp_256_mul_add_10(a+5, m, mu); + a[5+1] += a[5] >> 26; + + mu = Q6_P_mpy_RR(a[6], mp) & 0x3ffffff; + sp_256_mul_add_10(a+6, m, mu); + a[6+1] += a[6] >> 26; + + mu = Q6_P_mpy_RR(a[7], mp) & 0x3ffffff; + sp_256_mul_add_10(a+7, m, mu); + a[7+1] += a[7] >> 26; + + mu = Q6_P_mpy_RR(a[8], mp) & 0x3ffffff; + sp_256_mul_add_10(a+8, m, mu); + a[8+1] += a[8] >> 26; + + mu = Q6_P_mpy_RR(a[9], mp) & 0x3fffffL; + sp_256_mul_add_10(a+9, m, mu); + a[9+1] += a[9] >> 26; + a[9] &= 0x3ffffff; + } + else { + mu = Q6_P_mpy_RR(a[0], mp) & 0x3ffffff; + sp_256_mul_add_10(a+0, p256_mod, mu); + a[0+1] += a[0] >> 26; + + mu = Q6_P_mpy_RR(a[1], mp) & 0x3ffffff; + sp_256_mul_add_10(a+1, p256_mod, mu); + a[1+1] += a[1] >> 26; + + mu = Q6_P_mpy_RR(a[2], mp) & 0x3ffffff; + sp_256_mul_add_10(a+2, p256_mod, mu); + a[2+1] += a[2] >> 26; + + mu = Q6_P_mpy_RR(a[3], mp) & 0x3ffffff; + sp_256_mul_add_10(a+3, p256_mod, mu); + a[3+1] += a[3] >> 26; + + mu = Q6_P_mpy_RR(a[4], mp) & 0x3ffffff; + sp_256_mul_add_10(a+4, p256_mod, mu); + a[4+1] += a[4] >> 26; + + mu = Q6_P_mpy_RR(a[5], mp) & 0x3ffffff; + sp_256_mul_add_10(a+5, p256_mod, mu); + a[5+1] += a[5] >> 26; + + mu = Q6_P_mpy_RR(a[6], mp) & 0x3ffffff; + sp_256_mul_add_10(a+6, p256_mod, mu); + a[6+1] += a[6] >> 26; + + mu = Q6_P_mpy_RR(a[7], mp) & 0x3ffffff; + sp_256_mul_add_10(a+7, p256_mod, mu); + a[7+1] += a[7] >> 26; + + mu = Q6_P_mpy_RR(a[8], mp) & 0x3ffffff; + sp_256_mul_add_10(a+8, p256_mod, mu); + a[8+1] += a[8] >> 26; + + mu = Q6_P_mpy_RR(a[9], mp) & 0x3fffffL; + sp_256_mul_add_10(a+9, p256_mod, mu); + a[9+1] += a[9] >> 26; + a[9] &= 0x3ffffff; + } + + + sp_256_mont_shift_10(a, a); + sp_256_cond_sub_10(a, a, m, 0 - (((a[9] >> 22) > 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_256_norm_10(a); +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_256_mul_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ +#if 1 + int64_t t0 = Q6_P_mpy_RR(a[0], b[0]); + int64_t t1 = Q6_P_mpy_RR(a[0], b[1]) + + Q6_P_mpy_RR(a[1], b[0]); + int64_t t2 = Q6_P_mpy_RR(a[0], b[2]) + + Q6_P_mpy_RR(a[1], b[1]) + + Q6_P_mpy_RR(a[2], b[0]); + int64_t t3 = Q6_P_mpy_RR(a[0], b[3]) + + Q6_P_mpy_RR(a[1], b[2]) + + Q6_P_mpy_RR(a[2], b[1]) + + Q6_P_mpy_RR(a[3], b[0]); + int64_t t4 = Q6_P_mpy_RR(a[0], b[4]) + + Q6_P_mpy_RR(a[1], b[3]) + + Q6_P_mpy_RR(a[2], b[2]) + + Q6_P_mpy_RR(a[3], b[1]) + + Q6_P_mpy_RR(a[4], b[0]); + int64_t t5 = Q6_P_mpy_RR(a[0], b[5]) + + Q6_P_mpy_RR(a[1], b[4]) + + Q6_P_mpy_RR(a[2], b[3]) + + Q6_P_mpy_RR(a[3], b[2]) + + Q6_P_mpy_RR(a[4], b[1]) + + Q6_P_mpy_RR(a[5], b[0]); + int64_t t6 = Q6_P_mpy_RR(a[0], b[6]) + + Q6_P_mpy_RR(a[1], b[5]) + + Q6_P_mpy_RR(a[2], b[4]) + + Q6_P_mpy_RR(a[3], b[3]) + + Q6_P_mpy_RR(a[4], b[2]) + + Q6_P_mpy_RR(a[5], b[1]) + + Q6_P_mpy_RR(a[6], b[0]); + int64_t t7 = Q6_P_mpy_RR(a[0], b[7]) + + Q6_P_mpy_RR(a[1], b[6]) + + Q6_P_mpy_RR(a[2], b[5]) + + Q6_P_mpy_RR(a[3], b[4]) + + Q6_P_mpy_RR(a[4], b[3]) + + Q6_P_mpy_RR(a[5], b[2]) + + Q6_P_mpy_RR(a[6], b[1]) + + Q6_P_mpy_RR(a[7], b[0]); + int64_t t8 = Q6_P_mpy_RR(a[0], b[8]) + + Q6_P_mpy_RR(a[1], b[7]) + + Q6_P_mpy_RR(a[2], b[6]) + + Q6_P_mpy_RR(a[3], b[5]) + + Q6_P_mpy_RR(a[4], b[4]) + + Q6_P_mpy_RR(a[5], b[3]) + + Q6_P_mpy_RR(a[6], b[2]) + + Q6_P_mpy_RR(a[7], b[1]) + + Q6_P_mpy_RR(a[8], b[0]); + int64_t t9 = Q6_P_mpy_RR(a[0], b[9]) + + Q6_P_mpy_RR(a[1], b[8]) + + Q6_P_mpy_RR(a[2], b[7]) + + Q6_P_mpy_RR(a[3], b[6]) + + Q6_P_mpy_RR(a[4], b[5]) + + Q6_P_mpy_RR(a[5], b[4]) + + Q6_P_mpy_RR(a[6], b[3]) + + Q6_P_mpy_RR(a[7], b[2]) + + Q6_P_mpy_RR(a[8], b[1]) + + Q6_P_mpy_RR(a[9], b[0]); + int64_t t10 = Q6_P_mpy_RR(a[1], b[9]) + + Q6_P_mpy_RR(a[2], b[8]) + + Q6_P_mpy_RR(a[3], b[7]) + + Q6_P_mpy_RR(a[4], b[6]) + + Q6_P_mpy_RR(a[5], b[5]) + + Q6_P_mpy_RR(a[6], b[4]) + + Q6_P_mpy_RR(a[7], b[3]) + + Q6_P_mpy_RR(a[8], b[2]) + + Q6_P_mpy_RR(a[9], b[1]); + int64_t t11 = Q6_P_mpy_RR(a[2], b[9]) + + Q6_P_mpy_RR(a[3], b[8]) + + Q6_P_mpy_RR(a[4], b[7]) + + Q6_P_mpy_RR(a[5], b[6]) + + Q6_P_mpy_RR(a[6], b[5]) + + Q6_P_mpy_RR(a[7], b[4]) + + Q6_P_mpy_RR(a[8], b[3]) + + Q6_P_mpy_RR(a[9], b[2]); + int64_t t12 = Q6_P_mpy_RR(a[3], b[9]) + + Q6_P_mpy_RR(a[4], b[8]) + + Q6_P_mpy_RR(a[5], b[7]) + + Q6_P_mpy_RR(a[6], b[6]) + + Q6_P_mpy_RR(a[7], b[5]) + + Q6_P_mpy_RR(a[8], b[4]) + + Q6_P_mpy_RR(a[9], b[3]); + int64_t t13 = Q6_P_mpy_RR(a[4], b[9]) + + Q6_P_mpy_RR(a[5], b[8]) + + Q6_P_mpy_RR(a[6], b[7]) + + Q6_P_mpy_RR(a[7], b[6]) + + Q6_P_mpy_RR(a[8], b[5]) + + Q6_P_mpy_RR(a[9], b[4]); + int64_t t14 = Q6_P_mpy_RR(a[5], b[9]) + + Q6_P_mpy_RR(a[6], b[8]) + + Q6_P_mpy_RR(a[7], b[7]) + + Q6_P_mpy_RR(a[8], b[6]) + + Q6_P_mpy_RR(a[9], b[5]); + int64_t t15 = Q6_P_mpy_RR(a[6], b[9]) + + Q6_P_mpy_RR(a[7], b[8]) + + Q6_P_mpy_RR(a[8], b[7]) + + Q6_P_mpy_RR(a[9], b[6]); + int64_t t16 = Q6_P_mpy_RR(a[7], b[9]) + + Q6_P_mpy_RR(a[8], b[8]) + + Q6_P_mpy_RR(a[9], b[7]); + int64_t t17 = Q6_P_mpy_RR(a[8], b[9]) + + Q6_P_mpy_RR(a[9], b[8]); + int64_t t18 = Q6_P_mpy_RR(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 +#if 0 + /* Testing speeds with using HVX_Vectors */ + { + int64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18; + HVX_Vector av, splat; + HVX_Vector vlow, vhi; + + av = Q6_V_vzero(); + vlow = Q6_V_vzero(); + vhi = Q6_V_vzero(); + + XMEMCPY((byte*)&av, (byte*)a, 40); + + splat = Q6_V_vsplat_R(b[0]); + vlow = Q6_Vw_vmpyieo_VhVh(av, splat); + vlow = Q6_Vw_vmpyieacc_VwVwVuh(vlow, av, splat); + + vhi = Q6_Vw_vmpye_VwVuh(av, splat); + vhi = Q6_Vw_vmpyoacc_VwVwVh_s1_sat_shift(vhi, av, splat); + unsigned int* loi = (unsigned int*)&vlow; + int* hii = (int*)&vhi; + + /* a[0] * b[0] */ + t0 = loi[0] | ((int64_t)hii[0] << 31); + + /* a[1] * b[0] */ + t1 = loi[1] | ((int64_t)hii[1] << 31); + + /* a[2] * b[0] */ + t2 = loi[2] | ((int64_t)hii[2] << 31); + + /* a[3] * b[0] */ + t3 = loi[3] | ((int64_t)hii[3] << 31); + + /* a[4] * b[0] */ + t4 = loi[4] | ((int64_t)hii[4] << 31); + + /* a[5] * b[0] */ + t5 = loi[5] | ((int64_t)hii[5] << 31); + + /* a[6] * b[0] */ + t6 = loi[6] | ((int64_t)hii[6] << 31); + + /* a[7] * b[0] */ + t7 = loi[7] | ((int64_t)hii[7] << 31); + + /* a[8] * b[0] */ + t8 = loi[8] | ((int64_t)hii[8] << 31); + + /* a[9] * b[0] */ + t9 = loi[9] | ((int64_t)hii[9] << 31); + + /* a[*] * b[1] */ + splat = Q6_V_vsplat_R(b[1]); + vlow = Q6_Vw_vmpyieo_VhVh(av, splat); + vlow = Q6_Vw_vmpyieacc_VwVwVuh(vlow, av, splat); + vhi = Q6_Vw_vmpye_VwVuh(av, splat); + vhi = Q6_Vw_vmpyoacc_VwVwVh_s1_sat_shift(vhi, av, splat); + loi = (unsigned int*)&vlow; + hii = (int*)&vhi; + + /* a[0] * b[1] */ + t1 += (loi[0] | ((int64_t)hii[0] << 31)); + + /* a[1] * b[1] */ + t2 += (loi[1] | ((int64_t)hii[1] << 31)); + + /* a[2] * b[1] */ + t3 += (loi[2] | ((int64_t)hii[2] << 31)); + + /* a[3] * b[1] */ + t4 += (loi[3] | ((int64_t)hii[3] << 31)); + + /* a[4] * b[1] */ + t5 += (loi[4] | ((int64_t)hii[4] << 31)); + + /* a[5] * b[1] */ + t6 += (loi[5] | ((int64_t)hii[5] << 31)); + + /* a[6] * b[1] */ + t7 += (loi[6] | ((int64_t)hii[6] << 31)); + + /* a[7] * b[1] */ + t8 += (loi[7] | ((int64_t)hii[7] << 31)); + + /* a[8] * b[1] */ + t9 += (loi[8] | ((int64_t)hii[8] << 31)); + + /* a[9] * b[1] */ + t10 = (loi[9] | ((int64_t)hii[9] << 31)); + + /* a[*] * b[2] */ + splat = Q6_V_vsplat_R(b[2]); + vlow = Q6_Vw_vmpyieo_VhVh(av, splat); + vlow = Q6_Vw_vmpyieacc_VwVwVuh(vlow, av, splat); + vhi = Q6_Vw_vmpye_VwVuh(av, splat); + vhi = Q6_Vw_vmpyoacc_VwVwVh_s1_sat_shift(vhi, av, splat); + loi = (unsigned int*)&vlow; + hii = (int*)&vhi; + + + /* a[0] * b[2] */ + t2 += (loi[0] | ((int64_t)hii[0] << 31)); + + /* a[1] * b[2] */ + t3 += (loi[1] | ((int64_t)hii[1] << 31)); + + /* a[2] * b[2] */ + t4 += (loi[2] | ((int64_t)hii[2] << 31)); + + /* a[3] * b[2] */ + t5 += (loi[3] | ((int64_t)hii[3] << 31)); + + /* a[4] * b[2] */ + t6 += (loi[4] | ((int64_t)hii[4] << 31)); + + /* a[5] * b[2] */ + t7 += (loi[5] | ((int64_t)hii[5] << 31)); + + /* a[6] * b[2] */ + t8 += (loi[6] | ((int64_t)hii[6] << 31)); + + /* a[7] * b[2] */ + t9 += (loi[7] | ((int64_t)hii[7] << 31)); + + /* a[8] * b[2] */ + t10 += (loi[8] | ((int64_t)hii[8] << 31)); + + /* a[9] * b[2] */ + t11 = (loi[9] | ((int64_t)hii[9] << 31)); + + + /* a[*] * b[3] */ + splat = Q6_V_vsplat_R(b[3]); + vlow = Q6_Vw_vmpyieo_VhVh(av, splat); + vlow = Q6_Vw_vmpyieacc_VwVwVuh(vlow, av, splat); + vhi = Q6_Vw_vmpye_VwVuh(av, splat); + vhi = Q6_Vw_vmpyoacc_VwVwVh_s1_sat_shift(vhi, av, splat); + loi = (unsigned int*)&vlow; + hii = (int*)&vhi; + + + /* a[0] * b[3] */ + t3 += (loi[0] | ((int64_t)hii[0] << 31)); + + /* a[1] * b[3] */ + t4 += (loi[1] | ((int64_t)hii[1] << 31)); + + /* a[2] * b[3] */ + t5 += (loi[2] | ((int64_t)hii[2] << 31)); + + /* a[3] * b[3] */ + t6 += (loi[3] | ((int64_t)hii[3] << 31)); + + /* a[4] * b[3] */ + t7 += (loi[4] | ((int64_t)hii[4] << 31)); + + /* a[5] * b[3] */ + t8 += (loi[5] | ((int64_t)hii[5] << 31)); + + /* a[6] * b[3] */ + t9 += (loi[6] | ((int64_t)hii[6] << 31)); + + /* a[7] * b[3] */ + t10 += (loi[7] | ((int64_t)hii[7] << 31)); + + /* a[8] * b[3] */ + t11 += (loi[8] | ((int64_t)hii[8] << 31)); + + /* a[9] * b[3] */ + t12 = (loi[9] | ((int64_t)hii[9] << 31)); + + + /* a[*] * b[4] */ + splat = Q6_V_vsplat_R(b[4]); + vlow = Q6_Vw_vmpyieo_VhVh(av, splat); + vlow = Q6_Vw_vmpyieacc_VwVwVuh(vlow, av, splat); + vhi = Q6_Vw_vmpye_VwVuh(av, splat); + vhi = Q6_Vw_vmpyoacc_VwVwVh_s1_sat_shift(vhi, av, splat); + loi = (unsigned int*)&vlow; + hii = (int*)&vhi; + + + /* a[0] * b[4] */ + t4 += (loi[0] | ((int64_t)hii[0] << 31)); + + /* a[1] * b[4] */ + t5 += (loi[1] | ((int64_t)hii[1] << 31)); + + /* a[2] * b[4] */ + t6 += (loi[2] | ((int64_t)hii[2] << 31)); + + /* a[3] * b[4] */ + t7 += (loi[3] | ((int64_t)hii[3] << 31)); + + /* a[4] * b[4] */ + t8 += (loi[4] | ((int64_t)hii[4] << 31)); + + /* a[5] * b[4] */ + t9 += (loi[5] | ((int64_t)hii[5] << 31)); + + /* a[6] * b[4] */ + t10 += (loi[6] | ((int64_t)hii[6] << 31)); + + /* a[7] * b[4] */ + t11 += (loi[7] | ((int64_t)hii[7] << 31)); + + /* a[8] * b[4] */ + t12 += (loi[8] | ((int64_t)hii[8] << 31)); + + /* a[9] * b[4] */ + t13 = (loi[9] | ((int64_t)hii[9] << 31)); + + + /* a[*] * b[5] */ + splat = Q6_V_vsplat_R(b[5]); + vlow = Q6_Vw_vmpyieo_VhVh(av, splat); + vlow = Q6_Vw_vmpyieacc_VwVwVuh(vlow, av, splat); + vhi = Q6_Vw_vmpye_VwVuh(av, splat); + vhi = Q6_Vw_vmpyoacc_VwVwVh_s1_sat_shift(vhi, av, splat); + loi = (unsigned int*)&vlow; + hii = (int*)&vhi; + + + /* a[0] * b[5] */ + t5 += (loi[0] | ((int64_t)hii[0] << 31)); + + /* a[1] * b[5] */ + t6 += (loi[1] | ((int64_t)hii[1] << 31)); + + /* a[2] * b[5] */ + t7 += (loi[2] | ((int64_t)hii[2] << 31)); + + /* a[3] * b[5] */ + t8 += (loi[3] | ((int64_t)hii[3] << 31)); + + /* a[4] * b[5] */ + t9 += (loi[4] | ((int64_t)hii[4] << 31)); + + /* a[5] * b[5] */ + t10 += (loi[5] | ((int64_t)hii[5] << 31)); + + /* a[6] * b[5] */ + t11 += (loi[6] | ((int64_t)hii[6] << 31)); + + /* a[7] * b[5] */ + t12 += (loi[7] | ((int64_t)hii[7] << 31)); + + /* a[8] * b[5] */ + t13 += (loi[8] | ((int64_t)hii[8] << 31)); + + /* a[9] * b[5] */ + t14 = (loi[9] | ((int64_t)hii[9] << 31)); + + + /* a[*] * b[6] */ + splat = Q6_V_vsplat_R(b[6]); + vlow = Q6_Vw_vmpyieo_VhVh(av, splat); + vlow = Q6_Vw_vmpyieacc_VwVwVuh(vlow, av, splat); + vhi = Q6_Vw_vmpye_VwVuh(av, splat); + vhi = Q6_Vw_vmpyoacc_VwVwVh_s1_sat_shift(vhi, av, splat); + loi = (unsigned int*)&vlow; + hii = (int*)&vhi; + + + /* a[0] * b[6] */ + t6 += (loi[0] | ((int64_t)hii[0] << 31)); + + /* a[1] * b[6] */ + t7 += (loi[1] | ((int64_t)hii[1] << 31)); + + /* a[2] * b[6] */ + t8 += (loi[2] | ((int64_t)hii[2] << 31)); + + /* a[3] * b[6] */ + t9 += (loi[3] | ((int64_t)hii[3] << 31)); + + /* a[4] * b[6] */ + t10 += (loi[4] | ((int64_t)hii[4] << 31)); + + /* a[5] * b[6] */ + t11 += (loi[5] | ((int64_t)hii[5] << 31)); + + /* a[6] * b[6] */ + t12 += (loi[6] | ((int64_t)hii[6] << 31)); + + /* a[7] * b[6] */ + t13 += (loi[7] | ((int64_t)hii[7] << 31)); + + /* a[8] * b[6] */ + t14 += (loi[8] | ((int64_t)hii[8] << 31)); + + /* a[9] * b[6] */ + t15 = (loi[9] | ((int64_t)hii[9] << 31)); + + + + /* a[*] * b[7] */ + splat = Q6_V_vsplat_R(b[7]); + vlow = Q6_Vw_vmpyieo_VhVh(av, splat); + vlow = Q6_Vw_vmpyieacc_VwVwVuh(vlow, av, splat); + vhi = Q6_Vw_vmpye_VwVuh(av, splat); + vhi = Q6_Vw_vmpyoacc_VwVwVh_s1_sat_shift(vhi, av, splat); + loi = (unsigned int*)&vlow; + hii = (int*)&vhi; + + + /* a[0] * b[7] */ + t7 += (loi[0] | ((int64_t)hii[0] << 31)); + + /* a[1] * b[7] */ + t8 += (loi[1] | ((int64_t)hii[1] << 31)); + + /* a[2] * b[7] */ + t9 += (loi[2] | ((int64_t)hii[2] << 31)); + + /* a[3] * b[7] */ + t10 += (loi[3] | ((int64_t)hii[3] << 31)); + + /* a[4] * b[7] */ + t11 += (loi[4] | ((int64_t)hii[4] << 31)); + + /* a[5] * b[7] */ + t12 += (loi[5] | ((int64_t)hii[5] << 31)); + + /* a[6] * b[7] */ + t13 += (loi[6] | ((int64_t)hii[6] << 31)); + + /* a[7] * b[7] */ + t14 += (loi[7] | ((int64_t)hii[7] << 31)); + + /* a[8] * b[7] */ + t15 += (loi[8] | ((int64_t)hii[8] << 31)); + + /* a[9] * b[7] */ + t16 = (loi[9] | ((int64_t)hii[9] << 31)); + + + /* a[*] * b[8] */ + splat = Q6_V_vsplat_R(b[8]); + vlow = Q6_Vw_vmpyieo_VhVh(av, splat); + vlow = Q6_Vw_vmpyieacc_VwVwVuh(vlow, av, splat); + vhi = Q6_Vw_vmpye_VwVuh(av, splat); + vhi = Q6_Vw_vmpyoacc_VwVwVh_s1_sat_shift(vhi, av, splat); + loi = (unsigned int*)&vlow; + hii = (int*)&vhi; + + + /* a[0] * b[8] */ + t8 += (loi[0] | ((int64_t)hii[0] << 31)); + + /* a[1] * b[8] */ + t9 += (loi[1] | ((int64_t)hii[1] << 31)); + + /* a[2] * b[8] */ + t10 += (loi[2] | ((int64_t)hii[2] << 31)); + + /* a[3] * b[8] */ + t11 += (loi[3] | ((int64_t)hii[3] << 31)); + + /* a[4] * b[8] */ + t12 += (loi[4] | ((int64_t)hii[4] << 31)); + + /* a[5] * b[8] */ + t13 += (loi[5] | ((int64_t)hii[5] << 31)); + + /* a[6] * b[8] */ + t14 += (loi[6] | ((int64_t)hii[6] << 31)); + + /* a[7] * b[8] */ + t15 += (loi[7] | ((int64_t)hii[7] << 31)); + + /* a[8] * b[8] */ + t16 += (loi[8] | ((int64_t)hii[8] << 31)); + + /* a[9] * b[8] */ + t17 = (loi[9] | ((int64_t)hii[9] << 31)); + + + /* a[*] * b[9] */ + splat = Q6_V_vsplat_R(b[9]); + vlow = Q6_Vw_vmpyieo_VhVh(av, splat); + vlow = Q6_Vw_vmpyieacc_VwVwVuh(vlow, av, splat); + vhi = Q6_Vw_vmpye_VwVuh(av, splat); + vhi = Q6_Vw_vmpyoacc_VwVwVh_s1_sat_shift(vhi, av, splat); + loi = (unsigned int*)&vlow; + hii = (int*)&vhi; + + + /* a[0] * b[9] */ + t9 += (loi[0] | ((int64_t)hii[0] << 31)); + + /* a[1] * b[9] */ + t10 += (loi[1] | ((int64_t)hii[1] << 31)); + + /* a[2] * b[9] */ + t11 += (loi[2] | ((int64_t)hii[2] << 31)); + + /* a[3] * b[9] */ + t12 += (loi[3] | ((int64_t)hii[3] << 31)); + + /* a[4] * b[9] */ + t13 += (loi[4] | ((int64_t)hii[4] << 31)); + + /* a[5] * b[9] */ + t14 += (loi[5] | ((int64_t)hii[5] << 31)); + + /* a[6] * b[9] */ + t15 += (loi[6] | ((int64_t)hii[6] << 31)); + + /* a[7] * b[9] */ + t16 += (loi[7] | ((int64_t)hii[7] << 31)); + + /* a[8] * b[9] */ + t17 += (loi[8] | ((int64_t)hii[8] << 31)); + + /* a[9] * b[9] */ + t18 = (loi[9] | ((int64_t)hii[9] << 31)); + + 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 +} + + +/* 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, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_256_mul_10(r, a, b); + sp_256_mont_reduce_10(r, m, mp); +} + + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a) +{ + int64_t t0 = Q6_P_mpy_RR(a[0], a[0]); + int64_t t1 = Q6_P_mpy_RR(a[0], a[1]) * 2; + int64_t t2 = Q6_P_mpy_RR(a[0], a[2]) * 2 + + Q6_P_mpy_RR(a[1], a[1]); + int64_t t3 = (Q6_P_mpy_RR(a[0], a[3]) + + Q6_P_mpy_RR(a[1], a[2])) * 2; + int64_t t4 = (Q6_P_mpy_RR(a[ 0], a[ 4]) + + Q6_P_mpy_RR(a[ 1], a[ 3])) * 2 + + Q6_P_mpy_RR(a[ 2], a[ 2]); + int64_t t5 = (Q6_P_mpy_RR(a[ 0], a[ 5]) + + Q6_P_mpy_RR(a[ 1], a[ 4]) + + Q6_P_mpy_RR(a[ 2], a[ 3])) * 2; + int64_t t6 = (Q6_P_mpy_RR(a[ 0], a[ 6]) + + Q6_P_mpy_RR(a[ 1], a[ 5]) + + Q6_P_mpy_RR(a[ 2], a[ 4])) * 2 + + Q6_P_mpy_RR(a[ 3], a[ 3]); + int64_t t7 = (Q6_P_mpy_RR(a[ 0], a[ 7]) + + Q6_P_mpy_RR(a[ 1], a[ 6]) + + Q6_P_mpy_RR(a[ 2], a[ 5]) + + Q6_P_mpy_RR(a[ 3], a[ 4])) * 2; + int64_t t8 = (Q6_P_mpy_RR(a[ 0], a[ 8]) + + Q6_P_mpy_RR(a[ 1], a[ 7]) + + Q6_P_mpy_RR(a[ 2], a[ 6]) + + Q6_P_mpy_RR(a[ 3], a[ 5])) * 2 + + Q6_P_mpy_RR(a[ 4], a[ 4]); + int64_t t9 = (Q6_P_mpy_RR(a[ 0], a[ 9]) + + Q6_P_mpy_RR(a[ 1], a[ 8]) + + Q6_P_mpy_RR(a[ 2], a[ 7]) + + Q6_P_mpy_RR(a[ 3], a[ 6]) + + Q6_P_mpy_RR(a[ 4], a[ 5])) * 2; + int64_t t10 = (Q6_P_mpy_RR(a[ 1], a[ 9]) + + Q6_P_mpy_RR(a[ 2], a[ 8]) + + Q6_P_mpy_RR(a[ 3], a[ 7]) + + Q6_P_mpy_RR(a[ 4], a[ 6])) * 2 + + Q6_P_mpy_RR(a[ 5], a[ 5]); + int64_t t11 = (Q6_P_mpy_RR(a[ 2], a[ 9]) + + Q6_P_mpy_RR(a[ 3], a[ 8]) + + Q6_P_mpy_RR(a[ 4], a[ 7]) + + Q6_P_mpy_RR(a[ 5], a[ 6])) * 2; + int64_t t12 = (Q6_P_mpy_RR(a[ 3], a[ 9]) + + Q6_P_mpy_RR(a[ 4], a[ 8]) + + Q6_P_mpy_RR(a[ 5], a[ 7])) * 2 + + Q6_P_mpy_RR(a[ 6], a[ 6]); + int64_t t13 = (Q6_P_mpy_RR(a[ 4], a[ 9]) + + Q6_P_mpy_RR(a[ 5], a[ 8]) + + Q6_P_mpy_RR(a[ 6], a[ 7])) * 2; + int64_t t14 = (Q6_P_mpy_RR(a[ 5], a[ 9]) + + Q6_P_mpy_RR(a[ 6], a[ 8])) * 2 + + Q6_P_mpy_RR(a[ 7], a[ 7]); + int64_t t15 =( Q6_P_mpy_RR(a[ 6], a[ 9]) + + Q6_P_mpy_RR(a[ 7], a[ 8])) * 2; + int64_t t16 = Q6_P_mpy_RR(a[ 7], a[ 9]) * 2 + + Q6_P_mpy_RR(a[ 8], a[ 8]); + int64_t t17 = Q6_P_mpy_RR(a[ 8], a[ 9]) * 2; + int64_t t18 = Q6_P_mpy_RR(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; +} + + +/* 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_256_sqr_10(r, a); + sp_256_mont_reduce_10(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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, const sp_digit* a, int n, + const 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); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint32_t p256_mod_2[8] = { + 0xfffffffdU,0xffffffffU,0xffffffffU,0x00000000U,0x00000000U,0x00000000U, + 0x00000001U,0xffffffffU +}; +#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, const 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 + Q6_P_mpy_RR(2, 10); + sp_digit* t3 = td + Q6_P_mpy_RR(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, const sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + Q6_P_mpy_RR(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) / 2U); + 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_digit)1 : (sp_digit)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) / 2U); + 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_digit)1 : (sp_digit)0)); + sp_256_norm_10(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ +#if 0 + r[ 0] = Q6_R_add_RR(a[0], b[0]); + r[ 1] = Q6_R_add_RR(a[1], b[1]); + r[ 2] = Q6_R_add_RR(a[2], b[2]); + r[ 3] = Q6_R_add_RR(a[3], b[3]); + r[ 4] = Q6_R_add_RR(a[4], b[4]); + r[ 5] = Q6_R_add_RR(a[5], b[5]); + r[ 6] = Q6_R_add_RR(a[6], b[6]); + r[ 7] = Q6_R_add_RR(a[7], b[7]); + r[ 8] = Q6_R_add_RR(a[8], b[8]); + r[ 9] = Q6_R_add_RR(a[9], b[9]); +#endif +#if 1 + __asm__ __volatile__ ( + "{ r1 = memw(%[a]+#0) \n" + " r2 = memw(%[b]+#0) }\n" + "{ r3 = memw(%[a]+#4) \n" + " r19 = add(r1,r2) \n" + " r4 = memw(%[b]+#4) }\n" + "{ r5 = memw(%[a]+#8) \n" + " r20 = add(r3,r4) \n" + " r6 = memw(%[b]+#8) }\n" + "{ memw(%[r]+#0) = r19 }\n" + "{ r7 = memw(%[a]+#12) \n" + " r21 = add(r5,r6) \n" + " r8 = memw(%[b]+#12) }\n" + "{ memw(%[r]+#4) = r20 }\n" + "{ r9 = memw(%[a]+#16) \n" + " r22 = add(r7,r8) \n" + " r10 = memw(%[b]+#16) }\n" + "{ memw(%[r]+#8) = r21 }\n" + "{ r11 = memw(%[a]+#20) \n" + " r23 = add(r9,r10) \n" + " r12 = memw(%[b]+#20) }\n" + "{ memw(%[r]+#12) = r22 }\n" + "{ r13 = memw(%[a]+#24) \n" + " r24 = add(r11,r12) \n" + " r14 = memw(%[b]+#24) }\n" + "{ memw(%[r]+#16) = r23 }\n" + "{ r15 = memw(%[a]+#28) \n" + " r25 = add(r13,r14) \n" + " r16 = memw(%[b]+#28) }\n" + "{ memw(%[r]+#20) = r24 }\n" + "{ r17 = memw(%[a]+#32) \n" + " r26 = add(r15,r16) \n" + " r18 = memw(%[b]+#32) }\n" + "{ memw(%[r]+#24) = r25 }\n" + "{ r5 = memw(%[a]+#36) \n" + " r19 = add(r17,r18) \n" + " r6 = memw(%[b]+#36) }\n" + "{ memw(%[r]+#28) = r26 }\n" + "{ r20 = add(r5,r6) \n" + " memw(%[r]+#32) = r19 }\n" + "{ memw(%[r]+#36) = r20 }\n" + : [r] "+r" (r) + : [a] "r"(a), [b] "r"(b) + : "memory", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26" + ); +#endif + return 0; +} + + +/* 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, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)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_digit)1 : (sp_digit)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, const sp_digit* a, const sp_digit* m) +{ + (void)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_digit)1 : (sp_digit)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, const sp_digit* a, const sp_digit* m) +{ + (void)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_digit)1 : (sp_digit)0)); + sp_256_norm_10(r); + (void)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_digit)1 : (sp_digit)0)); + sp_256_norm_10(r); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ +#if 0 + r[ 0] = Q6_R_sub_RR(a[0], b[0]); + r[ 1] = Q6_R_sub_RR(a[1], b[1]); + r[ 2] = Q6_R_sub_RR(a[2], b[2]); + r[ 3] = Q6_R_sub_RR(a[3], b[3]); + r[ 4] = Q6_R_sub_RR(a[4], b[4]); + r[ 5] = Q6_R_sub_RR(a[5], b[5]); + r[ 6] = Q6_R_sub_RR(a[6], b[6]); + r[ 7] = Q6_R_sub_RR(a[7], b[7]); + r[ 8] = Q6_R_sub_RR(a[8], b[8]); + r[ 9] = Q6_R_sub_RR(a[9], b[9]); +#endif +#if 1 + __asm__ __volatile__ ( + "{ r1 = memw(%[a]+#0) \n" + " r2 = memw(%[b]+#0) }\n" + "{ r3 = memw(%[a]+#4) \n" + " r19 = sub(r1,r2) \n" + " r4 = memw(%[b]+#4) }\n" + "{ r5 = memw(%[a]+#8) \n" + " r20 = sub(r3,r4) \n" + " r6 = memw(%[b]+#8) }\n" + "{ memw(%[r]+#0) = r19 }\n" + "{ r7 = memw(%[a]+#12) \n" + " r21 = sub(r5,r6) \n" + " r8 = memw(%[b]+#12) }\n" + "{ memw(%[r]+#4) = r20 }\n" + "{ r9 = memw(%[a]+#16) \n" + " r22 = sub(r7,r8) \n" + " r10 = memw(%[b]+#16) }\n" + "{ memw(%[r]+#8) = r21 }\n" + "{ r11 = memw(%[a]+#20) \n" + " r23 = sub(r9,r10) \n" + " r12 = memw(%[b]+#20) }\n" + "{ memw(%[r]+#12) = r22 }\n" + "{ r13 = memw(%[a]+#24) \n" + " r24 = sub(r11,r12) \n" + " r14 = memw(%[b]+#24) }\n" + "{ memw(%[r]+#16) = r23 }\n" + "{ r15 = memw(%[a]+#28) \n" + " r25 = sub(r13,r14) \n" + " r16 = memw(%[b]+#28) }\n" + "{ memw(%[r]+#20) = r24 }\n" + "{ r17 = memw(%[a]+#32) \n" + " r26 = sub(r15,r16) \n" + " r18 = memw(%[b]+#32) }\n" + "{ memw(%[r]+#24) = r25 }\n" + "{ r5 = memw(%[a]+#36) \n" + " r19 = sub(r17,r18) \n" + " r6 = memw(%[b]+#36) }\n" + "{ memw(%[r]+#28) = r26 }\n" + "{ r20 = sub(r5,r6) \n" + " memw(%[r]+#32) = r19 }\n" + "{ memw(%[r]+#36) = r20 }\n" + : [r] "+r" (r) + : [a] "r"(a), [b] "r"(b) + : "memory", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26" + ); +#endif + return 0; +} + +/* 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] = Q6_R_add_RR(a[ 0], Q6_R_and_RR(b[ 0], m)); + r[ 1] = Q6_R_add_RR(a[ 1], Q6_R_and_RR(b[ 1], m)); + r[ 2] = Q6_R_add_RR(a[ 2], Q6_R_and_RR(b[ 2], m)); + r[ 3] = Q6_R_add_RR(a[ 3], Q6_R_and_RR(b[ 3], m)); + r[ 4] = Q6_R_add_RR(a[ 4], Q6_R_and_RR(b[ 4], m)); + r[ 5] = Q6_R_add_RR(a[ 5], Q6_R_and_RR(b[ 5], m)); + r[ 6] = Q6_R_add_RR(a[ 6], Q6_R_and_RR(b[ 6], m)); + r[ 7] = Q6_R_add_RR(a[ 7], Q6_R_and_RR(b[ 7], m)); + r[ 8] = Q6_R_add_RR(a[ 8], Q6_R_and_RR(b[ 8], m)); + r[ 9] = Q6_R_add_RR(a[ 9], Q6_R_and_RR(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, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + (void)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. + */ +SP_NOINLINE static void sp_256_rshift1_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) | Q6_R_and_RR((a[1] << 25), 0x3ffffff)); + r[1] = ((a[1] >> 1) | Q6_R_and_RR((a[2] << 25), 0x3ffffff)); + r[2] = ((a[2] >> 1) | Q6_R_and_RR((a[3] << 25), 0x3ffffff)); + r[3] = ((a[3] >> 1) | Q6_R_and_RR((a[4] << 25), 0x3ffffff)); + r[4] = ((a[4] >> 1) | Q6_R_and_RR((a[5] << 25), 0x3ffffff)); + r[5] = ((a[5] >> 1) | Q6_R_and_RR((a[6] << 25), 0x3ffffff)); + r[6] = ((a[6] >> 1) | Q6_R_and_RR((a[7] << 25), 0x3ffffff)); + r[7] = ((a[7] >> 1) | Q6_R_and_RR((a[8] << 25), 0x3ffffff)); + r[8] = ((a[8] >> 1) | Q6_R_and_RR((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, const sp_digit* a, const sp_digit* m) +{ + sp_256_cond_add_10(r, a, m, 0 - (a[0] & 1)); + sp_256_norm_10(r); + sp_256_rshift1_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, const sp_point* p, sp_digit* t) +{ + sp_point* rp[2]; + 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; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinity. */ + 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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_10(sp_point* r, const sp_point* p, const sp_point* q, + sp_digit* t) +{ + const sp_point* ap[2]; + sp_point* rp[2]; + 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) { + const sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)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))) != 0) { + sp_256_proj_point_dbl_10(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point)); + 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, const sp_point* g, const 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 != 0) { + 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_ECC); + } + if (td != NULL) { + XMEMSET(td, 0, sizeof(sp_point) * 3); + XFREE(td, NULL, DYNAMIC_TYPE_ECC); + } + + 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, const sp_point* g, const 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 != 0) { + 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] __attribute__((aligned(128))); + sp_digit y[10] __attribute__((aligned(128))); +} 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, const sp_point* g, const 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 */ + (void)sp_256_mod_mul_norm_10(t[1].x, g->x, p256_mod); + (void)sp_256_mod_mul_norm_10(t[1].y, g->y, p256_mod); + (void)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 != 0) { + 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, const sp_point* p, int n, + sp_digit* t) +{ + sp_point* rp[2]; + 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; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point)); + 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-- > 0) { + /* 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 != 0) { + /* 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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_10(sp_point* r, const sp_point* p, + const sp_point* q, sp_digit* t) +{ + const sp_point* ap[2]; + sp_point* rp[2]; + 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 */ + (void)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))) != 0) { + sp_256_proj_point_dbl_10(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point)); + 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 Temporary 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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_10(const 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[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)); + + 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)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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)); + } + } + } + + 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, const sp_point* g, + const sp_table_entry* table, const 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 = !y; + 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 = !y; + sp_256_proj_point_add_qz1_10(rt, rt, p, t); + } + + if (map != 0) { + 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] __attribute__((aligned(128))); + sp_digit y[10] __attribute__((aligned(128))); + sp_table_entry table[256] __attribute__((aligned(128))); + 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(const 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, const sp_point* g, const 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 + +#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, const 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 const 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 */ + { { 0x0a9143c,0x1cc3506,0x360179e,0x3f17fb6,0x075ba95,0x1d88944, + 0x3b732b7,0x15719e7,0x376a537,0x0062417 }, + { 0x295560a,0x094d5f3,0x245cddf,0x392e867,0x18b4ab8,0x3487cc9, + 0x288688d,0x176174b,0x3182588,0x0215c7f } }, + /* 2 */ + { { 0x147519a,0x2218090,0x32f0202,0x2b09acd,0x0d0981e,0x1e17af2, + 0x14a7caa,0x163a6a7,0x10ddbdf,0x03654f1 }, + { 0x1590f8f,0x0d8733f,0x09179d6,0x1ad139b,0x372e962,0x0bad933, + 0x1961102,0x223cdff,0x37e9eb2,0x0218fae } }, + /* 3 */ + { { 0x0db6485,0x1ad88d7,0x2f97785,0x288bc28,0x3808f0e,0x3df8c02, + 0x28d9544,0x20280f9,0x055b5ff,0x00001d8 }, + { 0x38d2010,0x13ae6e0,0x308a763,0x2ecc90d,0x254014f,0x10a9981, + 0x247d398,0x0fb8383,0x3613437,0x020c21d } }, + /* 4 */ + { { 0x2a0d2bb,0x08bf145,0x34994f9,0x1b06988,0x30d5cc1,0x1f18b22, + 0x01cf3a5,0x199fe49,0x161fd1b,0x00bd79a }, + { 0x1a01797,0x171c2fd,0x21925c1,0x1358255,0x23d20b4,0x1c7f6d4, + 0x111b370,0x03dec12,0x1168d6f,0x03d923e } }, + /* 5 */ + { { 0x137bbbc,0x19a11f8,0x0bec9e5,0x27a29a8,0x3e43446,0x275cd18, + 0x0427617,0x00056c7,0x285133d,0x016af80 }, + { 0x04c7dab,0x2a0df30,0x0c0792a,0x1310c98,0x3573d9f,0x239b30d, + 0x1315627,0x1ce0c32,0x25b6b6f,0x0252edc } }, + /* 6 */ + { { 0x20f141c,0x26d23dc,0x3c74bbf,0x334b7d6,0x06199b3,0x0441171, + 0x3f61294,0x313bf70,0x3cb2f7d,0x03375ae }, + { 0x2f436fd,0x19c02fa,0x26becca,0x1b6e64c,0x26f647f,0x053c948, + 0x0fa7920,0x397d830,0x2bd4bda,0x028d86f } }, + /* 7 */ + { { 0x17c13c7,0x2895616,0x03e128a,0x17d42df,0x1c38d63,0x0f02747, + 0x039aecf,0x0a4b01c,0x209c4b5,0x02e84b2 }, + { 0x1f91dfd,0x023e916,0x07fb9e4,0x19b3ba8,0x13af43b,0x35e02ca, + 0x0eb0899,0x3bd2c7b,0x19d701f,0x014faee } }, + /* 8 */ + { { 0x0e63d34,0x1fb8c6c,0x0fab4fe,0x1caa795,0x0f46005,0x179ed69, + 0x093334d,0x120c701,0x39206d5,0x021627e }, + { 0x183553a,0x03d7319,0x09e5aa7,0x12b8959,0x2087909,0x0011194, + 0x1045071,0x0713f32,0x16d0254,0x03aec1a } }, + /* 9 */ + { { 0x01647c5,0x1b2856b,0x1799461,0x11f133d,0x0b8127d,0x1937eeb, + 0x266aa37,0x1f68f71,0x0cbd1b2,0x03aca08 }, + { 0x287e008,0x1be361a,0x38f3940,0x276488d,0x2d87dfa,0x0333b2c, + 0x2d2e428,0x368755b,0x09b55a7,0x007ca0a } }, + /* 10 */ + { { 0x389da99,0x2a8300e,0x0022abb,0x27ae0a1,0x0a6f2d7,0x207017a, + 0x047862b,0x1358c9e,0x35905e5,0x00cde92 }, + { 0x1f7794a,0x1d40348,0x3f613c6,0x2ddf5b5,0x0207005,0x133f5ba, + 0x1a37810,0x3ef5829,0x0d5f4c2,0x0035978 } }, + /* 11 */ + { { 0x1275d38,0x026efad,0x2358d9d,0x1142f82,0x14268a7,0x1cfac99, + 0x362ff49,0x288cbc1,0x24252f4,0x0308f68 }, + { 0x394520c,0x06e13c2,0x178e5da,0x18ec16f,0x1096667,0x134a7a8, + 0x0dcb869,0x33fc4e9,0x38cc790,0x006778e } }, + /* 12 */ + { { 0x2c5fe04,0x29c5b09,0x1bdb183,0x02ceee8,0x03b28de,0x132dc4b, + 0x32c586a,0x32ff5d0,0x3d491fc,0x038d372 }, + { 0x2a58403,0x2351aea,0x3a53b40,0x21a0ba5,0x39a6974,0x1aaaa2b, + 0x3901273,0x03dfe78,0x3447b4e,0x039d907 } }, + /* 13 */ + { { 0x364ba59,0x14e5077,0x02fc7d7,0x3b02c09,0x1d33f10,0x0560616, + 0x06dfc6a,0x15efd3c,0x357052a,0x01284b7 }, + { 0x039dbd0,0x18ce3e5,0x3e1fbfa,0x352f794,0x0d3c24b,0x07c6cc5, + 0x1e4ffa2,0x3a91bf5,0x293bb5b,0x01abd6a } }, + /* 14 */ + { { 0x0c91999,0x02da644,0x0491da1,0x100a960,0x00a24b4,0x2330824, + 0x0094b4b,0x1004cf8,0x35a66a4,0x017f8d1 }, + { 0x13e7b4b,0x232af7e,0x391ab0f,0x069f08f,0x3292b50,0x3479898, + 0x2889aec,0x2a4590b,0x308ecfe,0x02d5138 } }, + /* 15 */ + { { 0x2ddfdce,0x231ba45,0x39e6647,0x19be245,0x12c3291,0x35399f8, + 0x0d6e764,0x3082d3a,0x2bda6b0,0x0382dac }, + { 0x37efb57,0x04b7cae,0x00070d3,0x379e431,0x01aac0d,0x1e6f251, + 0x0336ad6,0x0ddd3e4,0x3de25a6,0x01c7008 } }, + /* 16 */ + { { 0x3e20925,0x230912f,0x286762a,0x30e3f73,0x391c19a,0x34e1c18, + 0x16a5d5d,0x093d96a,0x3d421d3,0x0187561 }, + { 0x37173ea,0x19ce8a8,0x0b65e87,0x0214dde,0x2238480,0x16ead0f, + 0x38441e0,0x3bef843,0x2124621,0x03e847f } }, + /* 17 */ + { { 0x0b19ffd,0x247cacb,0x3c231c8,0x16ec648,0x201ba8d,0x2b172a3, + 0x103d678,0x2fb72db,0x04c1f13,0x0161bac }, + { 0x3e8ed09,0x171b949,0x2de20c3,0x0f06067,0x21e81a3,0x1b194be, + 0x0fd6c05,0x13c449e,0x0087086,0x006756b } }, + /* 18 */ + { { 0x09a4e1f,0x27d604c,0x00741e9,0x06fa49c,0x0ab7de7,0x3f4a348, + 0x25ef0be,0x158fc9a,0x33f7f9c,0x039f001 }, + { 0x2f59f76,0x3598e83,0x30501f6,0x15083f2,0x0669b3b,0x29980b5, + 0x0c1f7a7,0x0f02b02,0x0fec65b,0x0382141 } }, + /* 19 */ + { { 0x031b3ca,0x23da368,0x2d66f09,0x27b9b69,0x06d1cab,0x13c91ba, + 0x3d81fa9,0x25ad16f,0x0825b09,0x01e3c06 }, + { 0x225787f,0x3bf790e,0x2c9bb7e,0x0347732,0x28016f8,0x0d6ff0d, + 0x2a4877b,0x1d1e833,0x3b87e94,0x010e9dc } }, + /* 20 */ + { { 0x2b533d5,0x1ddcd34,0x1dc0625,0x3da86f7,0x3673b8a,0x1e7b0a4, + 0x3e7c9aa,0x19ac55d,0x251c3b2,0x02edb79 }, + { 0x25259b3,0x24c0ead,0x3480e7e,0x34f40e9,0x3d6a0af,0x2cf3f09, + 0x2c83d19,0x2e66f16,0x19a5d18,0x0182d18 } }, + /* 21 */ + { { 0x2e5aa1c,0x28e3846,0x3658bd6,0x0ad279c,0x1b8b765,0x397e1fb, + 0x130014e,0x3ff342c,0x3b2aeeb,0x02743c9 }, + { 0x2730a55,0x0918c5e,0x083aca9,0x0bf76ef,0x19c955b,0x300669c, + 0x01dfe0a,0x312341f,0x26d356e,0x0091295 } }, + /* 22 */ + { { 0x2cf1f96,0x00e52ba,0x271c6db,0x2a40930,0x19f2122,0x0b2f4ee, + 0x26ac1b8,0x3bda498,0x0873581,0x0117963 }, + { 0x38f9dbc,0x3d1e768,0x2040d3f,0x11ba222,0x3a8aaf1,0x1b82fb5, + 0x1adfb24,0x2de9251,0x21cc1e4,0x0301038 } }, + /* 23 */ + { { 0x38117b6,0x2bc001b,0x1433847,0x3fdce8d,0x3651969,0x3651d7a, + 0x2b35761,0x1bb1d20,0x097682c,0x00737d7 }, + { 0x1f04839,0x1dd6d04,0x16987db,0x3d12378,0x17dbeac,0x1c2cc86, + 0x121dd1b,0x3fcf6ca,0x1f8a92d,0x00119d5 } }, + /* 24 */ + { { 0x0e8ffcd,0x2b174af,0x1a82cc8,0x22cbf98,0x30d53c4,0x080b5b1, + 0x3161727,0x297cfdb,0x2113b83,0x0011b97 }, + { 0x0007f01,0x23fd936,0x3183e7b,0x0496bd0,0x07fb1ef,0x178680f, + 0x1c5ea63,0x0016c11,0x2c3303d,0x01b8041 } }, + /* 25 */ + { { 0x0dd73b1,0x1cd6122,0x10d948c,0x23e657b,0x3767070,0x15a8aad, + 0x385ea8c,0x33c7ce0,0x0ede901,0x0110965 }, + { 0x2d4b65b,0x2a8b244,0x0c37f8f,0x0ee5b24,0x394c234,0x3a5e347, + 0x26e4a15,0x39a3b4c,0x2514c2e,0x029e5be } }, + /* 26 */ + { { 0x23addd7,0x3ed8120,0x13b3359,0x20f959a,0x09e2a61,0x32fcf20, + 0x05b78e3,0x19ba7e2,0x1a9c697,0x0392b4b }, + { 0x2048a61,0x3dfd0a3,0x19a0357,0x233024b,0x3082d19,0x00fb63b, + 0x3a1af4c,0x1450ff0,0x046c37b,0x0317a50 } }, + /* 27 */ + { { 0x3e75f9e,0x294e30a,0x3a78476,0x3a32c48,0x36fd1a9,0x0427012, + 0x1e4df0b,0x11d1f61,0x1afdb46,0x018ca0f }, + { 0x2f2df15,0x0a33dee,0x27f4ce7,0x1542b66,0x3e592c4,0x20d2f30, + 0x3226ade,0x2a4e3ea,0x1ab1981,0x01a2f46 } }, + /* 28 */ + { { 0x087d659,0x3ab5446,0x305ac08,0x3d2cd64,0x33374d5,0x3f9d3f8, + 0x186981c,0x37f5a5a,0x2f53c6f,0x01254a4 }, + { 0x2cec896,0x1e32786,0x04844a8,0x043b16d,0x3d964b2,0x1935829, + 0x16f7e26,0x1a0dd9a,0x30d2603,0x003b1d4 } }, + /* 29 */ + { { 0x12687bb,0x04e816b,0x21fa2da,0x1abccb8,0x3a1f83b,0x375181e, + 0x0f5ef51,0x0fc2ce4,0x3a66486,0x003d881 }, + { 0x3138233,0x1f8eec3,0x2718bd6,0x1b09caa,0x2dd66b9,0x1bb222b, + 0x1004072,0x1b73e3b,0x07208ed,0x03fc36c } }, + /* 30 */ + { { 0x095d553,0x3e84053,0x0a8a749,0x3f575a0,0x3a44052,0x3ced59b, + 0x3b4317f,0x03a8c60,0x13c8874,0x00c4ed4 }, + { 0x0d11549,0x0b8ab02,0x221cb40,0x02ed37b,0x2071ee1,0x1fc8c83, + 0x3987dd4,0x27e049a,0x0f986f1,0x00b4eaf } }, + /* 31 */ + { { 0x15581a2,0x2214060,0x11af4c2,0x1598c88,0x19a0a6d,0x32acba6, + 0x3a7a0f0,0x2337c66,0x210ded9,0x0300dbe }, + { 0x1fbd009,0x3822eb0,0x181629a,0x2401b45,0x30b68b1,0x2e78363, + 0x2b32779,0x006530b,0x2c4b6d4,0x029aca8 } }, + /* 32 */ + { { 0x13549cf,0x0f943db,0x265ed43,0x1bfeb35,0x06f3369,0x3847f2d, + 0x1bfdacc,0x26181a5,0x252af7c,0x02043b8 }, + { 0x159bb2c,0x143f85c,0x357b654,0x2f9d62c,0x2f7dfbe,0x1a7fa9c, + 0x057e74d,0x05d14ac,0x17a9273,0x035215c } }, + /* 33 */ + { { 0x0cb5a98,0x106a2bc,0x10bf117,0x24c7cc4,0x3d3da8f,0x2ce0ab7, + 0x14e2cba,0x1813866,0x1a72f9a,0x01a9811 }, + { 0x2b2411d,0x3034fe8,0x16e0170,0x0f9443a,0x0be0eb8,0x2196cf3, + 0x0c9f738,0x15e40ef,0x0faf9e1,0x034f917 } }, + /* 34 */ + { { 0x03f7669,0x3da6efa,0x3d6bce1,0x209ca1d,0x109f8ae,0x09109e3, + 0x08ae543,0x3067255,0x1dee3c2,0x0081dd5 }, + { 0x3ef1945,0x358765b,0x28c387b,0x3bec4b4,0x218813c,0x0b7d92a, + 0x3cd1d67,0x2c0367e,0x2e57154,0x0123717 } }, + /* 35 */ + { { 0x3e5a199,0x1e42ffd,0x0bb7123,0x33e6273,0x1e0efb8,0x294671e, + 0x3a2bfe0,0x3d11709,0x2eddff6,0x03cbec2 }, + { 0x0b5025f,0x0255d7c,0x1f2241c,0x35d03ea,0x0550543,0x202fef4, + 0x23c8ad3,0x354963e,0x015db28,0x0284fa4 } }, + /* 36 */ + { { 0x2b65cbc,0x1e8d428,0x0226f9f,0x1c8a919,0x10b04b9,0x08fc1e8, + 0x1ce241e,0x149bc99,0x2b01497,0x00afc35 }, + { 0x3216fb7,0x1374fd2,0x226ad3d,0x19fef76,0x0f7d7b8,0x1c21417, + 0x37b83f6,0x3a27eba,0x25a162f,0x010aa52 } }, + /* 37 */ + { { 0x2adf191,0x1ab42fa,0x28d7584,0x2409689,0x20f8a48,0x253707d, + 0x2030504,0x378f7a1,0x169c65e,0x00b0b76 }, + { 0x3849c17,0x085c764,0x10dd6d0,0x2e87689,0x1460488,0x30e9521, + 0x10c7063,0x1b6f120,0x21f42c5,0x03d0dfe } }, + /* 38 */ + { { 0x20f7dab,0x035c512,0x29ac6aa,0x24c5ddb,0x20f0497,0x17ce5e1, + 0x00a050f,0x1eaa14b,0x3335470,0x02abd16 }, + { 0x18d364a,0x0df0cf0,0x316585e,0x018f925,0x0d40b9b,0x17b1511, + 0x1716811,0x1caf3d0,0x10df4f2,0x0337d8c } }, + /* 39 */ + { { 0x2a8b7ef,0x0f188e3,0x2287747,0x06216f0,0x008e935,0x2f6a38d, + 0x1567722,0x0bfc906,0x0bada9e,0x03c3402 }, + { 0x014d3b1,0x099c749,0x2a76291,0x216c067,0x3b37549,0x14ef2f6, + 0x21b96d4,0x1ee2d71,0x2f5ca88,0x016f570 } }, + /* 40 */ + { { 0x09a3154,0x3d1a7bd,0x2e9aef0,0x255b8ac,0x03e85a5,0x2a492a7, + 0x2aec1ea,0x11c6516,0x3c8a09e,0x02a84b7 }, + { 0x1f69f1d,0x09c89d3,0x1e7326f,0x0b28bfd,0x0e0e4c8,0x1ea7751, + 0x18ce73b,0x2a406e7,0x273e48c,0x01b00db } }, + /* 41 */ + { { 0x36e3138,0x2b84a83,0x345a5cf,0x00096b4,0x16966ef,0x159caf1, + 0x13c64b4,0x2f89226,0x25896af,0x00a4bfd }, + { 0x2213402,0x1435117,0x09fed52,0x09d0e4b,0x0f6580e,0x2871cba, + 0x3b397fd,0x1c9d825,0x090311b,0x0191383 } }, + /* 42 */ + { { 0x07153f0,0x1087869,0x18c9e1e,0x1e64810,0x2b86c3b,0x0175d9c, + 0x3dce877,0x269de4e,0x393cab7,0x03c96b9 }, + { 0x1869d0c,0x06528db,0x02641f3,0x209261b,0x29d55c8,0x25ba517, + 0x3b5ea30,0x028f927,0x25313db,0x00e6e39 } }, + /* 43 */ + { { 0x2fd2e59,0x150802d,0x098f377,0x19a4957,0x135e2c0,0x38a95ce, + 0x1ab21a0,0x36c1b67,0x32f0f19,0x00e448b }, + { 0x3cad53c,0x3387800,0x17e3cfb,0x03f9970,0x3225b2c,0x2a84e1d, + 0x3af1d29,0x3fe35ca,0x2f8ce80,0x0237a02 } }, + /* 44 */ + { { 0x07bbb76,0x3aa3648,0x2758afb,0x1f085e0,0x1921c7e,0x3010dac, + 0x22b74b1,0x230137e,0x1062e36,0x021c652 }, + { 0x3993df5,0x24a2ee8,0x126ab5f,0x2d7cecf,0x0639d75,0x16d5414, + 0x1aa78a8,0x3f78404,0x26a5b74,0x03f0c57 } }, + /* 45 */ + { { 0x0d6ecfa,0x3f506ba,0x3f86561,0x3d86bb1,0x15f8c44,0x2491d07, + 0x052a7b4,0x2422261,0x3adee38,0x039b529 }, + { 0x193c75d,0x14bb451,0x1162605,0x293749c,0x370a70d,0x2e8b1f6, + 0x2ede937,0x2b95f4a,0x39a9be2,0x00d77eb } }, + /* 46 */ + { { 0x2736636,0x15bf36a,0x2b7e6b9,0x25eb8b2,0x209f51d,0x3cd2659, + 0x10bf410,0x034afec,0x3d71c83,0x0076971 }, + { 0x0ce6825,0x07920cf,0x3c3b5c4,0x23fe55c,0x015ad11,0x08c0dae, + 0x0552c7f,0x2e75a8a,0x0fddbf4,0x01c1df0 } }, + /* 47 */ + { { 0x2b9661c,0x0ffe351,0x3d71bf6,0x1ac34b3,0x3a1dfd3,0x211fe3d, + 0x33e140a,0x3f9100d,0x32ee50e,0x014ea18 }, + { 0x16d8051,0x1bfda1a,0x068a097,0x2571d3d,0x1daec0c,0x39389af, + 0x194dc35,0x3f3058a,0x36d34e1,0x000a329 } }, + /* 48 */ + { { 0x09877ee,0x351f73f,0x0002d11,0x0420074,0x2c8b362,0x130982d, + 0x02c1175,0x3c11b40,0x0d86962,0x001305f }, + { 0x0daddf5,0x2f4252c,0x15c06d9,0x1d49339,0x1bea235,0x0b680ed, + 0x3356e67,0x1d1d198,0x1e9fed9,0x03dee93 } }, + /* 49 */ + { { 0x3e1263f,0x2fe8d3a,0x3ce6d0d,0x0d5c6b9,0x3557637,0x0a9bd48, + 0x0405538,0x0710749,0x2005213,0x038c7e5 }, + { 0x26b6ec6,0x2e485ba,0x3c44d1b,0x0b9cf0b,0x037a1d1,0x27428a5, + 0x0e7eac8,0x351ef04,0x259ce34,0x02a8e98 } }, + /* 50 */ + { { 0x2f3dcd3,0x3e77d4d,0x3360fbc,0x1434afd,0x36ceded,0x3d413d6, + 0x1710fad,0x36bb924,0x1627e79,0x008e637 }, + { 0x109569e,0x1c168db,0x3769cf4,0x2ed4527,0x0ea0619,0x17d80d3, + 0x1c03773,0x18843fe,0x1b21c04,0x015c5fd } }, + /* 51 */ + { { 0x1dd895e,0x08a7248,0x04519fe,0x001030a,0x18e5185,0x358dfb3, + 0x13d2391,0x0a37be8,0x0560e3c,0x019828b }, + { 0x27fcbd0,0x2a22bb5,0x30969cc,0x1e03aa7,0x1c84724,0x0ba4ad3, + 0x32f4817,0x0914cca,0x14c4f52,0x01893b9 } }, + /* 52 */ + { { 0x097eccc,0x1273936,0x00aa095,0x364fe62,0x04d49d1,0x10e9f08, + 0x3c24230,0x3ef01c8,0x2fb92bd,0x013ce4a }, + { 0x1e44fd9,0x27e3e9f,0x2156696,0x3915ecc,0x0b66cfb,0x1a3af0f, + 0x2fa8033,0x0e6736c,0x177ccdb,0x0228f9e } }, + /* 53 */ + { { 0x2c4b125,0x06207c1,0x0a8cdde,0x003db8f,0x1ae34e3,0x31e84fa, + 0x2999de5,0x11013bd,0x02370c2,0x00e2234 }, + { 0x0f91081,0x200d591,0x1504762,0x1857c05,0x23d9fcf,0x0cb34db, + 0x27edc86,0x08cd860,0x2471810,0x029798b } }, + /* 54 */ + { { 0x3acd6c8,0x097b8cb,0x3c661a8,0x15152f2,0x1699c63,0x237e64c, + 0x23edf79,0x16b7033,0x0e6466a,0x00b11da }, + { 0x0a64bc9,0x1bfe324,0x1f5cb34,0x08391de,0x0630a60,0x3017a21, + 0x09d064b,0x14a8365,0x041f9e6,0x01ed799 } }, + /* 55 */ + { { 0x128444a,0x2508b07,0x2a39216,0x362f84d,0x2e996c5,0x2c31ff3, + 0x07afe5f,0x1d1288e,0x3cb0c8d,0x02e2bdc }, + { 0x38b86fd,0x3a0ea8c,0x1cff5fd,0x1629629,0x3fee3f1,0x02b250c, + 0x2e8f6f2,0x0225727,0x15f7f3f,0x0280d8e } }, + /* 56 */ + { { 0x10f7770,0x0f1aee8,0x0e248c7,0x20684a8,0x3a6f16d,0x06f0ae7, + 0x0df6825,0x2d4cc40,0x301875f,0x012f8da }, + { 0x3b56dbb,0x1821ba7,0x24f8922,0x22c1f9e,0x0306fef,0x1b54bc8, + 0x2ccc056,0x00303ba,0x2871bdc,0x0232f26 } }, + /* 57 */ + { { 0x0dac4ab,0x0625730,0x3112e13,0x101c4bf,0x3a874a4,0x2873b95, + 0x32ae7c6,0x0d7e18c,0x13e0c08,0x01139d5 }, + { 0x334002d,0x00fffdd,0x025c6d5,0x22c2cd1,0x19d35cb,0x3a1ce2d, + 0x3702760,0x3f06257,0x03a5eb8,0x011c29a } }, + /* 58 */ + { { 0x0513482,0x1d87724,0x276a81b,0x0a807a4,0x3028720,0x339cc20, + 0x2441ee0,0x31bbf36,0x290c63d,0x0059041 }, + { 0x106a2ed,0x0d2819b,0x100bf50,0x114626c,0x1dd4d77,0x2e08632, + 0x14ae72a,0x2ed3f64,0x1fd7abc,0x035cd1e } }, + /* 59 */ + { { 0x2d4c6e5,0x3bec596,0x104d7ed,0x23d6c1b,0x0262cf0,0x15d72c5, + 0x2d5bb18,0x199ac4b,0x1e30771,0x020591a }, + { 0x21e291e,0x2e75e55,0x1661d7a,0x08b0778,0x3eb9daf,0x0d78144, + 0x1827eb1,0x0fe73d2,0x123f0dd,0x0028db7 } }, + /* 60 */ + { { 0x1d5533c,0x34cb1d0,0x228f098,0x27a1a11,0x17c5f5a,0x0d26f44, + 0x2228ade,0x2c460e6,0x3d6fdba,0x038cc77 }, + { 0x3cc6ed8,0x02ada1a,0x260e510,0x2f7bde8,0x37160c3,0x33a1435, + 0x23d9a7b,0x0ce2641,0x02a492e,0x034ed1e } }, + /* 61 */ + { { 0x3821f90,0x26dba3c,0x3aada14,0x3b59bad,0x292edd9,0x2804c45, + 0x3669531,0x296f42e,0x35a4c86,0x01ca049 }, + { 0x3ff47e5,0x2163df4,0x2441503,0x2f18405,0x15e1616,0x37f66ec, + 0x30f11a7,0x141658a,0x27ece14,0x00b018b } }, + /* 62 */ + { { 0x159ac2e,0x3e65bc0,0x2713a76,0x0db2f6c,0x3281e77,0x2391811, + 0x16d2880,0x1fbc4ab,0x1f92c4e,0x00a0a8d }, + { 0x0ce5cd2,0x152c7b0,0x02299c3,0x3244de7,0x2cf99ef,0x3a0b047, + 0x2caf383,0x0aaf664,0x113554d,0x031c735 } }, + /* 63 */ + { { 0x1b578f4,0x177a702,0x3a7a488,0x1638ebf,0x31884e2,0x2460bc7, + 0x36b1b75,0x3ce8e3d,0x340cf47,0x03143d9 }, + { 0x34b68ea,0x12b7ccd,0x1fe2a9c,0x08da659,0x0a406f3,0x1694c14, + 0x06a2228,0x16370be,0x3a72129,0x02e7b2c } }, + /* 64 */ + { { 0x0f8b16a,0x21043bd,0x266a56f,0x3fb11ec,0x197241a,0x36721f0, + 0x006b8e6,0x2ac6c29,0x202cd42,0x0200fcf }, + { 0x0dbec69,0x0c26a01,0x105f7f0,0x3dceeeb,0x3a83b85,0x363865f, + 0x097273a,0x2b70718,0x00e5067,0x03025d1 } }, + /* 65 */ + { { 0x379ab34,0x295bcb0,0x38d1846,0x22e1077,0x3a8ee06,0x1db1a3b, + 0x3144591,0x07cc080,0x2d5915f,0x03c6bcc }, + { 0x175bd50,0x0dd4c57,0x27bc99c,0x2ebdcbd,0x3837cff,0x235dc8f, + 0x13a4184,0x0722c18,0x130e2d4,0x008f43c } }, + /* 66 */ + { { 0x01500d9,0x2adbb7d,0x2da8857,0x397f2fa,0x10d890a,0x25c9654, + 0x3e86488,0x3eb754b,0x1d6c0a3,0x02c0a23 }, + { 0x10bcb08,0x083cc19,0x2e16853,0x04da575,0x271af63,0x2626a9d, + 0x3520a7b,0x32348c7,0x24ff408,0x03ff4dc } }, + /* 67 */ + { { 0x058e6cb,0x1a3992d,0x1d28539,0x080c5e9,0x2992dad,0x2a9d7d5, + 0x14ae0b7,0x09b7ce0,0x34ad78c,0x03d5643 }, + { 0x30ba55a,0x092f4f3,0x0bae0fc,0x12831de,0x20fc472,0x20ed9d2, + 0x29864f6,0x1288073,0x254f6f7,0x00635b6 } }, + /* 68 */ + { { 0x1be5a2b,0x0f88975,0x33c6ed9,0x20d64d3,0x06fe799,0x0989bff, + 0x1409262,0x085a90c,0x0d97990,0x0142eed }, + { 0x17ec63e,0x06471b9,0x0db2378,0x1006077,0x265422c,0x08db83d, + 0x28099b0,0x1270d06,0x11801fe,0x00ac400 } }, + /* 69 */ + { { 0x3391593,0x22d7166,0x30fcfc6,0x2896609,0x3c385f5,0x066b72e, + 0x04f3aad,0x2b831c5,0x19983fb,0x0375562 }, + { 0x0b82ff4,0x222e39d,0x34c993b,0x101c79c,0x2d2e03c,0x0f00c8a, + 0x3a9eaf4,0x1810669,0x151149d,0x039b931 } }, + /* 70 */ + { { 0x29af288,0x1956ec7,0x293155f,0x193deb6,0x1647e1a,0x2ca0839, + 0x297e4bc,0x15bfd0d,0x1b107ed,0x0147803 }, + { 0x31c327e,0x05a6e1d,0x02ad43d,0x02d2a5b,0x129cdb2,0x37ad1de, + 0x3d51f53,0x245df01,0x2414982,0x0388bd0 } }, + /* 71 */ + { { 0x35f1abb,0x17a3d18,0x0874cd4,0x2d5a14e,0x17edc0c,0x16a00d3, + 0x072c1fb,0x1232725,0x33d52dc,0x03dc24d }, + { 0x0af30d6,0x259aeea,0x369c401,0x12bc4de,0x295bf5f,0x0d8711f, + 0x26162a9,0x16c44e5,0x288e727,0x02f54b4 } }, + /* 72 */ + { { 0x05fa877,0x1571ea7,0x3d48ab1,0x1c9f4e8,0x017dad6,0x0f46276, + 0x343f9e7,0x1de990f,0x0e4c8aa,0x028343e }, + { 0x094f92d,0x3abf633,0x1b3a0bb,0x2f83137,0x0d818c8,0x20bae85, + 0x0c65f8b,0x1a8008b,0x0c7946d,0x0295b1e } }, + /* 73 */ + { { 0x1d09529,0x08e46c3,0x1fcf296,0x298f6b7,0x1803e0e,0x2d6fd20, + 0x37351f5,0x0d9e8b1,0x1f8731a,0x0362fbf }, + { 0x00157f4,0x06750bf,0x2650ab9,0x35ffb23,0x2f51cae,0x0b522c2, + 0x39cb400,0x191e337,0x0a5ce9f,0x021529a } }, + /* 74 */ + { { 0x3506ea5,0x17d9ed8,0x0d66dc3,0x22693f8,0x19286c4,0x3a57353, + 0x101d3bf,0x1aa54fc,0x20b9884,0x0172b3a }, + { 0x0eac44d,0x37d8327,0x1c3aa90,0x3d0d534,0x23db29a,0x3576eaf, + 0x1d3de8a,0x3bea423,0x11235e4,0x039260b } }, + /* 75 */ + { { 0x34cd55e,0x01288b0,0x1132231,0x2cc9a03,0x358695b,0x3e87650, + 0x345afa1,0x01267ec,0x3f616b2,0x02011ad }, + { 0x0e7d098,0x0d6078e,0x0b70b53,0x237d1bc,0x0d7f61e,0x132de31, + 0x1ea9ea4,0x2bd54c3,0x27b9082,0x03ac5f2 } }, + /* 76 */ + { { 0x2a145b9,0x06d661d,0x31ec175,0x03f06f1,0x3a5cf6b,0x249c56e, + 0x2035653,0x384c74f,0x0bafab5,0x0025ec0 }, + { 0x25f69e1,0x1b23a55,0x1199aa6,0x16ad6f9,0x077e8f7,0x293f661, + 0x33ba11d,0x3327980,0x07bafdb,0x03e571d } }, + /* 77 */ + { { 0x2bae45e,0x3c074ef,0x2955558,0x3c312f1,0x2a8ebe9,0x2f193f1, + 0x3705b1d,0x360deba,0x01e566e,0x00d4498 }, + { 0x21161cd,0x1bc787e,0x2f87933,0x3553197,0x1328ab8,0x093c879, + 0x17eee27,0x2adad1d,0x1236068,0x003be5c } }, + /* 78 */ + { { 0x0ca4226,0x2633dd5,0x2c8e025,0x0e3e190,0x05eede1,0x1a385e4, + 0x163f744,0x2f25522,0x1333b4f,0x03f05b6 }, + { 0x3c800ca,0x1becc79,0x2daabe9,0x0c499e2,0x1138063,0x3fcfa2d, + 0x2244976,0x1e85cf5,0x2f1b95d,0x0053292 } }, + /* 79 */ + { { 0x12f81d5,0x1dc6eaf,0x11967a4,0x1a407df,0x31a5f9d,0x2b67241, + 0x18bef7c,0x08c7762,0x063f59c,0x01015ec }, + { 0x1c05c0a,0x360bfa2,0x1f85bff,0x1bc7703,0x3e4911c,0x0d685b6, + 0x2fccaea,0x02c4cef,0x164f133,0x0070ed7 } }, + /* 80 */ + { { 0x0ec21fe,0x052ffa0,0x3e825fe,0x1ab0956,0x3f6ce11,0x3d29759, + 0x3c5a072,0x18ebe62,0x148db7e,0x03eb49c }, + { 0x1ab05b3,0x02dab0a,0x1ae690c,0x0f13894,0x137a9a8,0x0aab79f, + 0x3dc875c,0x06a1029,0x1e39f0e,0x01dce1f } }, + /* 81 */ + { { 0x16c0dd7,0x3b31269,0x2c741e9,0x3611821,0x2a5cffc,0x1416bb3, + 0x3a1408f,0x311fa3d,0x1c0bef0,0x02cdee1 }, + { 0x00e6a8f,0x1adb933,0x0f23359,0x2fdace2,0x2fd6d4b,0x0e73bd3, + 0x2453fac,0x0a356ae,0x2c8f9f6,0x02704d6 } }, + /* 82 */ + { { 0x0e35743,0x28c80a1,0x0def32a,0x2c6168f,0x1320d6a,0x37c6606, + 0x21b1761,0x2147ee0,0x21fc433,0x015c84d }, + { 0x1fc9168,0x36cda9c,0x003c1f0,0x1cd7971,0x15f98ba,0x1ef363d, + 0x0ca87e3,0x046f7d9,0x3c9e6bb,0x0372eb0 } }, + /* 83 */ + { { 0x118cbe2,0x3665a11,0x304ef01,0x062727a,0x3d242fc,0x11ffbaf, + 0x3663c7e,0x1a189c9,0x09e2d62,0x02e3072 }, + { 0x0e1d569,0x162f772,0x0cd051a,0x322df62,0x3563809,0x047cc7a, + 0x027fd9f,0x08b509b,0x3da2f94,0x01748ee } }, + /* 84 */ + { { 0x1c8f8be,0x31ca525,0x22bf0a1,0x200efcd,0x02961c4,0x3d8f52b, + 0x018403d,0x3a40279,0x1cb91ec,0x030427e }, + { 0x0945705,0x0257416,0x05c0c2d,0x25b77ae,0x3b9083d,0x2901126, + 0x292b8d7,0x07b8611,0x04f2eee,0x026f0cd } }, + /* 85 */ + { { 0x2913074,0x2b8d590,0x02b10d5,0x09d2295,0x255491b,0x0c41cca, + 0x1ca665b,0x133051a,0x1525f1a,0x00a5647 }, + { 0x04f983f,0x3d6daee,0x04e1e76,0x1067d7e,0x1be7eef,0x02ea862, + 0x00d4968,0x0ccb048,0x11f18ef,0x018dd95 } }, + /* 86 */ + { { 0x22976cc,0x17c5395,0x2c38bda,0x3983bc4,0x222bca3,0x332a614, + 0x3a30646,0x261eaef,0x1c808e2,0x02f6de7 }, + { 0x306a772,0x32d7272,0x2dcefd2,0x2abf94d,0x038f475,0x30ad76e, + 0x23e0227,0x3052b0a,0x001add3,0x023ba18 } }, + /* 87 */ + { { 0x0ade873,0x25a6069,0x248ccbe,0x13713ee,0x17ee9aa,0x28152e9, + 0x2e28995,0x2a92cb3,0x17a6f77,0x024b947 }, + { 0x190a34d,0x2ebea1c,0x1ed1948,0x16fdaf4,0x0d698f7,0x32bc451, + 0x0ee6e30,0x2aaab40,0x06f0a56,0x01460be } }, + /* 88 */ + { { 0x24cc99c,0x1884b1e,0x1ca1fba,0x1a0f9b6,0x2ff609b,0x2b26316, + 0x3b27cb5,0x29bc976,0x35d4073,0x024772a }, + { 0x3575a70,0x1b30f57,0x07fa01b,0x0e5be36,0x20cb361,0x26605cd, + 0x1d4e8c8,0x13cac59,0x2db9797,0x005e833 } }, + /* 89 */ + { { 0x36c8d3a,0x1878a81,0x124b388,0x0e4843e,0x1701aad,0x0ea0d76, + 0x10eae41,0x37d0653,0x36c7f4c,0x00ba338 }, + { 0x37a862b,0x1cf6ac0,0x08fa912,0x2dd8393,0x101ba9b,0x0eebcb7, + 0x2453883,0x1a3cfe5,0x2cb34f6,0x03d3331 } }, + /* 90 */ + { { 0x1f79687,0x3d4973c,0x281544e,0x2564bbe,0x17c5954,0x171e34a, + 0x231741a,0x3cf2784,0x0889a0d,0x02b036d }, + { 0x301747f,0x3f1c477,0x1f1386b,0x163bc5f,0x1592b93,0x332daed, + 0x080e4f5,0x1d28b96,0x26194c9,0x0256992 } }, + /* 91 */ + { { 0x15a4c93,0x07bf6b0,0x114172c,0x1ce0961,0x140269b,0x1b2c2eb, + 0x0dfb1c1,0x019ddaa,0x0ba2921,0x008c795 }, + { 0x2e6d2dc,0x37e45e2,0x2918a70,0x0fce444,0x34d6aa6,0x396dc88, + 0x27726b5,0x0c787d8,0x032d8a7,0x02ac2f8 } }, + /* 92 */ + { { 0x1131f2d,0x2b43a63,0x3101097,0x38cec13,0x0637f09,0x17a69d2, + 0x086196d,0x299e46b,0x0802cf6,0x03c6f32 }, + { 0x0daacb4,0x1a4503a,0x100925c,0x15583d9,0x23c4e40,0x1de4de9, + 0x1cc8fc4,0x2c9c564,0x0695aeb,0x02145a5 } }, + /* 93 */ + { { 0x1dcf593,0x17050fc,0x3e3bde3,0x0a6c062,0x178202b,0x2f7674f, + 0x0dadc29,0x15763a7,0x1d2daad,0x023d9f6 }, + { 0x081ea5f,0x045959d,0x190c841,0x3a78d31,0x0e7d2dd,0x1414fea, + 0x1d43f40,0x22d77ff,0x2b9c072,0x03e115c } }, + /* 94 */ + { { 0x3af71c9,0x29e9c65,0x25655e1,0x111e9cd,0x3a14494,0x3875418, + 0x34ae070,0x0b06686,0x310616b,0x03b7b89 }, + { 0x1734121,0x00d3d44,0x29f0b2f,0x1552897,0x31cac6e,0x1030bb3, + 0x0148f3a,0x35fd237,0x29b44eb,0x027f49f } }, + /* 95 */ + { { 0x2e2cb16,0x1d962bd,0x19b63cc,0x0b3f964,0x3e3eb7d,0x1a35560, + 0x0c58161,0x3ce1d6a,0x3b6958f,0x029030b }, + { 0x2dcc158,0x3b1583f,0x30568c9,0x31957c8,0x27ad804,0x28c1f84, + 0x3967049,0x37b3f64,0x3b87dc6,0x0266f26 } }, + /* 96 */ + { { 0x27dafc6,0x2548764,0x0d1984a,0x1a57027,0x252c1fb,0x24d9b77, + 0x1581a0f,0x1f99276,0x10ba16d,0x026af88 }, + { 0x0915220,0x2be1292,0x16c6480,0x1a93760,0x2fa7317,0x1a07296, + 0x1539871,0x112c31f,0x25787f3,0x01e2070 } }, + /* 97 */ + { { 0x0bcf3ff,0x266d478,0x34f6933,0x31449fd,0x00d02cb,0x340765a, + 0x3465a2d,0x225023e,0x319a30e,0x00579b8 }, + { 0x20e05f4,0x35b834f,0x0404646,0x3710d62,0x3fad7bd,0x13e1434, + 0x21c7d1c,0x1cb3af9,0x2cf1911,0x003957e } }, + /* 98 */ + { { 0x0787564,0x36601be,0x1ce67e9,0x084c7a1,0x21a3317,0x2067a35, + 0x0158cab,0x195ddac,0x1766fe9,0x035cf42 }, + { 0x2b7206e,0x20d0947,0x3b42424,0x03f1862,0x0a51929,0x38c2948, + 0x0bb8595,0x2942d77,0x3748f15,0x0249428 } }, + /* 99 */ + { { 0x2577410,0x3c23e2f,0x28c6caf,0x00d41de,0x0fd408a,0x30298e9, + 0x363289e,0x2302fc7,0x082c1cc,0x01dd050 }, + { 0x30991cd,0x103e9ba,0x029605a,0x19927f7,0x0c1ca08,0x0c93f50, + 0x28a3c7b,0x082e4e9,0x34d12eb,0x0232c13 } }, + /* 100 */ + { { 0x106171c,0x0b4155a,0x0c3fb1c,0x336c090,0x19073e9,0x2241a10, + 0x0e6b4fd,0x0ed476e,0x1ef4712,0x039390a }, + { 0x0ec36f4,0x3754f0e,0x2a270b8,0x007fd2d,0x0f9d2dc,0x1e6a692, + 0x066e078,0x1954974,0x2ff3c6e,0x00def28 } }, + /* 101 */ + { { 0x3562470,0x0b8f1f7,0x0ac94cd,0x28b0259,0x244f272,0x031e4ef, + 0x2d5df98,0x2c8a9f1,0x2dc3002,0x016644f }, + { 0x350592a,0x0e6a0d5,0x1e027a1,0x2039e0f,0x399e01d,0x2817593, + 0x0c0375e,0x3889b3e,0x24ab013,0x010de1b } }, + /* 102 */ + { { 0x256b5a6,0x0ac3b67,0x28f9ff3,0x29b67f1,0x30750d9,0x25e11a9, + 0x15e8455,0x279ebb0,0x298b7e7,0x0218e32 }, + { 0x2fc24b2,0x2b82582,0x28f22f5,0x2bd36b3,0x305398e,0x3b2e9e3, + 0x365dd0a,0x29bc0ed,0x36a7b3a,0x007b374 } }, + /* 103 */ + { { 0x05ff2f3,0x2b3589b,0x29785d3,0x300a1ce,0x0a2d516,0x0844355, + 0x14c9fad,0x3ccb6b6,0x385d459,0x0361743 }, + { 0x0b11da3,0x002e344,0x18c49f7,0x0c29e0c,0x1d2c22c,0x08237b3, + 0x2988f49,0x0f18955,0x1c3b4ed,0x02813c6 } }, + /* 104 */ + { { 0x17f93bd,0x249323b,0x11f6087,0x174e4bd,0x3cb64ac,0x086dc6b, + 0x2e330a8,0x142c1f2,0x2ea5c09,0x024acbb }, + { 0x1b6e235,0x3132521,0x00f085a,0x2a4a4db,0x1ab2ca4,0x0142224, + 0x3aa6b3e,0x09db203,0x2215834,0x007b9e0 } }, + /* 105 */ + { { 0x23e79f7,0x28b8039,0x1906a60,0x2cbce67,0x1f590e7,0x181f027, + 0x21054a6,0x3854240,0x2d857a6,0x03cfcb3 }, + { 0x10d9b55,0x1443cfc,0x2648200,0x2b36190,0x09d2fcf,0x22f439f, + 0x231aa7e,0x3884395,0x0543da3,0x003d5a9 } }, + /* 106 */ + { { 0x043e0df,0x06ffe84,0x3e6d5b2,0x3327001,0x26c74b6,0x12a145e, + 0x256ec0d,0x3898c69,0x3411969,0x02f63c5 }, + { 0x2b7494a,0x2eee1af,0x38388a9,0x1bd17ce,0x21567d4,0x13969e6, + 0x3a12a7a,0x3e8277d,0x03530cc,0x00b4687 } }, + /* 107 */ + { { 0x06508da,0x38e04d4,0x15a7192,0x312875e,0x3336180,0x2a6512c, + 0x1b59497,0x2e91b37,0x25eb91f,0x02841e9 }, + { 0x394d639,0x0747143,0x37d7e6d,0x1d62962,0x08b4af3,0x34df287, + 0x3c5584b,0x26bc869,0x20af87a,0x0060f5d } }, + /* 108 */ + { { 0x1de59a4,0x1a5c443,0x2f8729d,0x01c3a2f,0x0f1ad8d,0x3cbaf9e, + 0x1b49634,0x35d508a,0x39dc269,0x0075105 }, + { 0x390d30e,0x37033e0,0x110cb32,0x14c37a0,0x20a3b27,0x2f00ce6, + 0x2f1dc52,0x34988c6,0x0c29606,0x01dc7e7 } }, + /* 109 */ + { { 0x1040739,0x24f9de1,0x2939999,0x2e6009a,0x244539d,0x17e3f09, + 0x00f6f2f,0x1c63b3d,0x2310362,0x019109e }, + { 0x1428aa8,0x3cb61e1,0x09a84f4,0x0ffafed,0x07b7adc,0x08f406b, + 0x1b2c6df,0x035b480,0x3496ae9,0x012766d } }, + /* 110 */ + { { 0x35d1099,0x2362f10,0x1a08cc7,0x13a3a34,0x12adbcd,0x32da290, + 0x02e2a02,0x151140b,0x01b3f60,0x0240df6 }, + { 0x34c7b61,0x2eb09c1,0x172e7cd,0x2ad5eff,0x2fe2031,0x25b54d4, + 0x0cec965,0x18e7187,0x26a7cc0,0x00230f7 } }, + /* 111 */ + { { 0x2d552ab,0x374083d,0x01f120f,0x2601736,0x156baff,0x04d44a4, + 0x3b7c3e9,0x1acbc1b,0x0424579,0x031a425 }, + { 0x1231bd1,0x0eba710,0x020517b,0x21d7316,0x21eac6e,0x275a848, + 0x0837abf,0x0eb0082,0x302cafe,0x00fe8f6 } }, + /* 112 */ + { { 0x1058880,0x28f9941,0x03f2d75,0x3bd90e5,0x17da365,0x2ac9249, + 0x07861cf,0x023fd05,0x1b0fdb8,0x031712f }, + { 0x272b56b,0x04f8d2c,0x043a735,0x25446e4,0x1c8327e,0x221125a, + 0x0ce37df,0x2dad7f6,0x39446c2,0x00b55b6 } }, + /* 113 */ + { { 0x346ac6b,0x05e0bff,0x2425246,0x0981e8b,0x1d19f79,0x2692378, + 0x3ea3c40,0x2e90beb,0x19de503,0x003d5af }, + { 0x05cda49,0x353b44d,0x299d137,0x3f205bc,0x2821158,0x3ad0d00, + 0x06a54aa,0x2d7c79f,0x39d1173,0x01000ee } }, + /* 114 */ + { { 0x0803387,0x3a06268,0x14043b8,0x3d4e72f,0x1ece115,0x0a1dfc8, + 0x17208dd,0x0be790a,0x122a07f,0x014dd95 }, + { 0x0a4182d,0x202886a,0x1f79a49,0x1e8c867,0x0a2bbd0,0x28668b5, + 0x0d0a2e1,0x115259d,0x3586c5d,0x01e815b } }, + /* 115 */ + { { 0x18a2a47,0x2c95627,0x2773646,0x1230f7c,0x15b5829,0x2fc354e, + 0x2c000ea,0x099d547,0x2f17a1a,0x01df520 }, + { 0x3853948,0x06f6561,0x3feeb8a,0x2f5b3ef,0x3a6f817,0x01a0791, + 0x2ec0578,0x2c392ad,0x12b2b38,0x0104540 } }, + /* 116 */ + { { 0x1e28ced,0x0fc3d1b,0x2c473c7,0x1826c4f,0x21d5da7,0x39718e4, + 0x38ce9e6,0x0251986,0x172fbea,0x0337c11 }, + { 0x053c3b0,0x0f162db,0x043c1cb,0x04111ee,0x297fe3c,0x32e5e03, + 0x2b8ae12,0x0c427ec,0x1da9738,0x03b9c0f } }, + /* 117 */ + { { 0x357e43a,0x054503f,0x11b8345,0x34ec6e0,0x2d44660,0x3d0ae61, + 0x3b5dff8,0x33884ac,0x09da162,0x00a82b6 }, + { 0x3c277ba,0x129a51a,0x027664e,0x1530507,0x0c788c9,0x2afd89d, + 0x1aa64cc,0x1196450,0x367ac2b,0x0358b42 } }, + /* 118 */ + { { 0x0054ac4,0x1761ecb,0x378839c,0x167c9f7,0x2570058,0x0604a35, + 0x37cbf3b,0x0909bb7,0x3f2991c,0x02ce688 }, + { 0x0b16ae5,0x212857c,0x351b952,0x2c684db,0x30c6a05,0x09c01e0, + 0x23c137f,0x1331475,0x092c067,0x0013b40 } }, + /* 119 */ + { { 0x2e90393,0x0617466,0x24e61f4,0x0a528f5,0x03047b4,0x2153f05, + 0x0001a69,0x30e1eb8,0x3c10177,0x0282a47 }, + { 0x22c831e,0x28fc06b,0x3e16ff0,0x208adc9,0x0bb76ae,0x28c1d6d, + 0x12c8a15,0x031063c,0x1889ed2,0x002133e } }, + /* 120 */ + { { 0x0a6becf,0x14277bf,0x3328d98,0x201f7fe,0x12fceae,0x1de3a2e, + 0x0a15c44,0x3ddf976,0x1b273ab,0x0355e55 }, + { 0x1b5d4f1,0x369e78c,0x3a1c210,0x12cf3e9,0x3aa52f0,0x309f082, + 0x112089d,0x107c753,0x24202d1,0x023853a } }, + /* 121 */ + { { 0x2897042,0x140d17c,0x2c4aeed,0x07d0d00,0x18d0533,0x22f7ec8, + 0x19c194c,0x3456323,0x2372aa4,0x0165f86 }, + { 0x30bd68c,0x1fb06b3,0x0945032,0x372ac09,0x06d4be0,0x27f8fa1, + 0x1c8d7ac,0x137a96e,0x236199b,0x0328fc0 } }, + /* 122 */ + { { 0x170bd20,0x2842d58,0x1de7592,0x3c5b4fd,0x20ea897,0x12cab78, + 0x363ff14,0x01f928c,0x17e309c,0x02f79ff }, + { 0x0f5432c,0x2edb4ae,0x044b516,0x32f810d,0x2210dc1,0x23e56d6, + 0x301e6ff,0x34660f6,0x10e0a7d,0x02d88eb } }, + /* 123 */ + { { 0x0c7b65b,0x2f59d58,0x2289a75,0x2408e92,0x1ab8c55,0x1ec99e5, + 0x220fd0d,0x04defe0,0x24658ec,0x035aa8b }, + { 0x138bb85,0x2f002d4,0x295c10a,0x08760ce,0x28c31d1,0x1c0a8cb, + 0x0ff00b1,0x144eac9,0x2e02dcc,0x0044598 } }, + /* 124 */ + { { 0x3b42b87,0x050057b,0x0dff781,0x1c06db1,0x1bd9f5d,0x1f5f04a, + 0x2cccd7a,0x143e19b,0x1cb94b7,0x036cfb8 }, + { 0x34837cf,0x3cf6c3c,0x0d4fb26,0x22ee55e,0x1e7eed1,0x315995f, + 0x2cdf937,0x1a96574,0x0425220,0x0221a99 } }, + /* 125 */ + { { 0x1b569ea,0x0d33ed9,0x19c13c2,0x107dc84,0x2200111,0x0569867, + 0x2dc85da,0x05ef22e,0x0eb018a,0x029c33d }, + { 0x04a6a65,0x3e5eba3,0x378f224,0x09c04d0,0x036e5cf,0x3df8258, + 0x3a609e4,0x1eddef8,0x2abd174,0x02a91dc } }, + /* 126 */ + { { 0x2a60cc0,0x1d84c5e,0x115f676,0x1840da0,0x2c79163,0x2f06ed6, + 0x198bb4b,0x3e5d37b,0x1dc30fa,0x018469b }, + { 0x15ee47a,0x1e32f30,0x16a530e,0x2093836,0x02e8962,0x3767b62, + 0x335adf3,0x27220db,0x2f81642,0x0173ffe } }, + /* 127 */ + { { 0x37a99cd,0x1533fe6,0x05a1c0d,0x27610f1,0x17bf3b9,0x0b1ce78, + 0x0a908f6,0x265300e,0x3237dc1,0x01b969a }, + { 0x3a5db77,0x2d15382,0x0d63ef8,0x1feb3d8,0x0b7b880,0x19820de, + 0x11c0c67,0x2af3396,0x38d242d,0x0120688 } }, + /* 128 */ + { { 0x1d0b34a,0x05ef00d,0x00a7e34,0x1ae0c9f,0x1440b38,0x300d8b4, + 0x37262da,0x3e50e3e,0x14ce0cd,0x00b1044 }, + { 0x195a0b1,0x173bc6b,0x03622ba,0x2a19f55,0x1c09b37,0x07921b2, + 0x16cdd20,0x24a5c9b,0x2bf42ff,0x00811de } }, + /* 129 */ + { { 0x0d65dbf,0x145cf06,0x1ad82f7,0x038ce7b,0x077bf94,0x33c4007, + 0x22d26bd,0x25ad9c0,0x09ac773,0x02b1990 }, + { 0x2261cc3,0x2ecdbf1,0x3e908b0,0x3246439,0x0213f7b,0x1179b04, + 0x01cebaa,0x0be1595,0x175cc12,0x033a39a } }, + /* 130 */ + { { 0x00a67d2,0x086d06f,0x248a0f1,0x0291134,0x362d476,0x166d1cd, + 0x044f1d6,0x2d2a038,0x365250b,0x0023f78 }, + { 0x08bf287,0x3b0f6a1,0x1d6eace,0x20b4cda,0x2c2a621,0x0912520, + 0x02dfdc9,0x1b35cd6,0x3d2565d,0x00bdf8b } }, + /* 131 */ + { { 0x3770fa7,0x2e4b6f0,0x03f9ae4,0x170de41,0x1095e8d,0x1dd845c, + 0x334e9d1,0x00ab953,0x12e9077,0x03196fa }, + { 0x2fd0a40,0x228c0fd,0x384b275,0x38ef339,0x3e7d822,0x3e5d9ef, + 0x24f5854,0x0ece9eb,0x247d119,0x012ffe3 } }, + /* 132 */ + { { 0x0ff1480,0x07487c0,0x1b16cd4,0x1f41d53,0x22ab8fb,0x2f83cfa, + 0x01d2efb,0x259f6b2,0x2e65772,0x00f9392 }, + { 0x05303e6,0x23cdb4f,0x23977e1,0x12e4898,0x03bd999,0x0c930f0, + 0x170e261,0x180a27b,0x2fd58ec,0x014e22b } }, + /* 133 */ + { { 0x25d7713,0x0c5fad7,0x09daad1,0x3b9d779,0x109b985,0x1d3ec98, + 0x35bc4fc,0x2f838cb,0x0d14f75,0x0173e42 }, + { 0x2657b12,0x10d4423,0x19e6760,0x296e5bb,0x2bfd421,0x25c3330, + 0x29f51f8,0x0338838,0x24060f0,0x029a62e } }, + /* 134 */ + { { 0x3748fec,0x2c5a1bb,0x2cf973d,0x289fa74,0x3e6e755,0x38997bf, + 0x0b6544c,0x2b6358c,0x38a7aeb,0x02c50bb }, + { 0x3d5770a,0x06be7c5,0x012fad3,0x19cb2cd,0x266af3b,0x3ccd677, + 0x160d1bd,0x141d5af,0x2965851,0x034625a } }, + /* 135 */ + { { 0x3c41c08,0x255eacc,0x22e1ec5,0x2b151a3,0x087de94,0x311cbdb, + 0x016b73a,0x368e462,0x20b7981,0x0099ec3 }, + { 0x262b988,0x1539763,0x21e76e5,0x15445b4,0x1d8ddc7,0x34a9be6, + 0x10faf03,0x24e4d18,0x07aa111,0x02d538a } }, + /* 136 */ + { { 0x38a876b,0x048ad45,0x04b40a0,0x3fc2144,0x251ff96,0x13ca7dd, + 0x0b31ab1,0x3539814,0x28b5f87,0x0212aec }, + { 0x270790a,0x350e7e0,0x346bd5e,0x276178f,0x22d6cb5,0x3078884, + 0x355c1b6,0x15901d7,0x3671765,0x03950db } }, + /* 137 */ + { { 0x286e8d5,0x2409788,0x13be53f,0x2d21911,0x0353c95,0x10238e8, + 0x32f5bde,0x3a67b60,0x28b5b9c,0x001013d }, + { 0x381e8e5,0x0cef7a9,0x2f5bcad,0x06058f0,0x33cdf50,0x04672a8, + 0x1769600,0x31c055d,0x3df0ac1,0x00e9098 } }, + /* 138 */ + { { 0x2eb596d,0x197b326,0x12b4c29,0x39c08f2,0x101ea03,0x3804e58, + 0x04b4b62,0x28d9d1c,0x13f905e,0x0032a3f }, + { 0x11b2b61,0x08e9095,0x0d06925,0x270e43f,0x21eb7a8,0x0e4a98f, + 0x31d2be0,0x030cf9f,0x2644ddb,0x025b728 } }, + /* 139 */ + { { 0x07510af,0x2ed0e8e,0x2a01203,0x2a2a68d,0x0846fea,0x3e540de, + 0x3a57702,0x1677348,0x2123aad,0x010d8f8 }, + { 0x0246a47,0x0e871d0,0x124dca4,0x34b9577,0x2b362b8,0x363ebe5, + 0x3086045,0x26313e6,0x15cd8bb,0x0210384 } }, + /* 140 */ + { { 0x023e8a7,0x0817884,0x3a0bf12,0x3376371,0x3c808a8,0x18e9777, + 0x12a2721,0x35b538a,0x2bd30de,0x017835a }, + { 0x0fc0f64,0x1c8709f,0x2d8807a,0x0743957,0x242eec0,0x347e76c, + 0x27bef91,0x289689a,0x0f42945,0x01f7a92 } }, + /* 141 */ + { { 0x1060a81,0x3dbc739,0x1615abd,0x1cbe3e5,0x3e79f9c,0x1ab09a2, + 0x136c540,0x05b473f,0x2beebfd,0x02af0a8 }, + { 0x3e2eac7,0x19be474,0x04668ac,0x18f4b74,0x36f10ba,0x0a0b4c6, + 0x10e3770,0x3bf059e,0x3946c7e,0x013a8d4 } }, + /* 142 */ + { { 0x266309d,0x28be354,0x1a3eed8,0x3020651,0x10a51c6,0x1e31770, + 0x0af45a5,0x3ff0f3b,0x2891c94,0x00e9db9 }, + { 0x17b0d0f,0x33a291f,0x0a5f9aa,0x25a3d61,0x2963ace,0x39a5fef, + 0x230c724,0x1919146,0x10a465e,0x02084a8 } }, + /* 143 */ + { { 0x3ab8caa,0x31870f3,0x2390ef7,0x2103850,0x218eb8e,0x3a5ccf2, + 0x1dff677,0x2c59334,0x371599c,0x02a9f2a }, + { 0x0837bd1,0x3249cef,0x35d702f,0x3430dab,0x1c06407,0x108f692, + 0x221292f,0x05f0c5d,0x073fe06,0x01038e0 } }, + /* 144 */ + { { 0x3bf9b7c,0x2020929,0x30d0f4f,0x080fef8,0x3365d23,0x1f3e738, + 0x3e53209,0x1549afe,0x300b305,0x038d811 }, + { 0x0c6c2c7,0x2e6445b,0x3ee64dc,0x022e932,0x0726837,0x0deb67b, + 0x1ed4346,0x3857f73,0x277a3de,0x01950b5 } }, + /* 145 */ + { { 0x36c377a,0x0adb41e,0x08be3f3,0x11e40d1,0x36cb038,0x036a2bd, + 0x3dd3a82,0x1bc875b,0x2ee09bb,0x02994d2 }, + { 0x035facf,0x05e0344,0x07e630a,0x0ce772d,0x335e55a,0x111fce4, + 0x250fe1c,0x3bc89ba,0x32fdc9a,0x03cf2d9 } }, + /* 146 */ + { { 0x355fd83,0x1c67f8e,0x1d10eb3,0x1b21d77,0x0e0d7a4,0x173a9e1, + 0x2c9fa90,0x1c39cce,0x22eaae8,0x01f2bea }, + { 0x153b338,0x0534107,0x26c69b8,0x283be1f,0x3e0acc0,0x059cac3, + 0x13d1081,0x148bbee,0x3c1b9bd,0x002aac4 } }, + /* 147 */ + { { 0x2681297,0x3389e34,0x146addc,0x2c6d425,0x2cb350e,0x1986abc, + 0x0431737,0x04ba4b7,0x2028470,0x012e469 }, + { 0x2f8ddcf,0x3c4255c,0x1af4dcf,0x07a6a44,0x208ebf6,0x0dc90c3, + 0x34360ac,0x072ad23,0x0537232,0x01254d3 } }, + /* 148 */ + { { 0x07b7e9d,0x3df5c7c,0x116f83d,0x28c4f35,0x3a478ef,0x3011fb8, + 0x2f264b6,0x317b9e3,0x04fd65a,0x032bd1b }, + { 0x2aa8266,0x3431de4,0x04bba04,0x19a44da,0x0edf454,0x392c5ac, + 0x265168a,0x1dc3d5b,0x25704c6,0x00533a7 } }, + /* 149 */ + { { 0x25e8f91,0x1178fa5,0x2492994,0x2eb2c3c,0x0d3aca1,0x0322828, + 0x1cc70f9,0x269c74c,0x0a53e4c,0x006edc2 }, + { 0x18bdd7a,0x2a79a55,0x26b1d5c,0x0200628,0x0734a05,0x3273c7b, + 0x13aa714,0x0040ac2,0x2f2da30,0x03e7449 } }, + /* 150 */ + { { 0x3f9563e,0x2f29eab,0x14a0749,0x3fad264,0x1dd077a,0x3d7c59c, + 0x3a0311b,0x331a789,0x0b9729e,0x0201ebf }, + { 0x1b08b77,0x2a4cdf2,0x3e387f8,0x21510f1,0x286c3a7,0x1dbf62e, + 0x3afa594,0x3363217,0x0d16568,0x01d46b7 } }, + /* 151 */ + { { 0x0715c0d,0x28e2d04,0x17f78ae,0x1c63dda,0x1d113ea,0x0fefc1b, + 0x1eab149,0x1d0fd99,0x0682537,0x00a7b11 }, + { 0x10bebbc,0x11c672d,0x14223d9,0x2ff9141,0x1399ee5,0x34b7b6c, + 0x0d5b3a8,0x01df643,0x0e392a4,0x03fe4dc } }, + /* 152 */ + { { 0x2b75b65,0x0b5a6f1,0x11c559a,0x3549999,0x24188f8,0x37a75f4, + 0x29f33e3,0x34068a2,0x38ba2a9,0x025dd91 }, + { 0x29af2c7,0x0988b64,0x0923885,0x1b539a4,0x1334f5d,0x226947a, + 0x2cc7e5a,0x20beb39,0x13fac2f,0x01d298c } }, + /* 153 */ + { { 0x35f079c,0x137f76d,0x2fbbb2f,0x254638d,0x185b07c,0x1f34db7, + 0x2cfcf0e,0x218f46d,0x2150ff4,0x02add6f }, + { 0x33fc9b7,0x0d9f005,0x0fd081b,0x0834965,0x2b90a74,0x102448d, + 0x3dbf03c,0x167d857,0x02e0b44,0x013afab } }, + /* 154 */ + { { 0x09f2c53,0x317f9d7,0x1411eb6,0x0463aba,0x0d25220,0x256b176, + 0x087633f,0x2bff322,0x07b2c1b,0x037e662 }, + { 0x10aaecb,0x23bb4a1,0x2272bb7,0x06c075a,0x09d4918,0x0736f2b, + 0x0dd511b,0x101625e,0x0a7779f,0x009ec10 } }, + /* 155 */ + { { 0x33b2eb2,0x0176dfd,0x2118904,0x022386c,0x2e0df85,0x2588c9f, + 0x1b71525,0x28fd540,0x137e4cf,0x02ce4f7 }, + { 0x3d75165,0x0c39ecf,0x3554a12,0x30af34c,0x2d66344,0x3ded408, + 0x36f1be0,0x0d065b0,0x012d046,0x0025623 } }, + /* 156 */ + { { 0x2601c3b,0x1824fc0,0x335fe08,0x3e33d70,0x0fb0252,0x252bfca, + 0x1cf2808,0x1922e55,0x1a9db9f,0x020721e }, + { 0x2f56c51,0x39a1f31,0x218c040,0x1a4fc5d,0x3fed471,0x0164d4e, + 0x388a419,0x06f1113,0x0f55fc1,0x03e8352 } }, + /* 157 */ + { { 0x1608e4d,0x3872778,0x022cbc6,0x044d60a,0x3010dda,0x15fb0b5, + 0x37ddc11,0x19f5bda,0x156b6a3,0x023a838 }, + { 0x383b3b4,0x1380bc8,0x353ca35,0x250fc07,0x169966b,0x3780f29, + 0x36632b2,0x2d6b13f,0x124fa00,0x00fd6ae } }, + /* 158 */ + { { 0x1739efb,0x2ec3656,0x2c0d337,0x3d39faf,0x1c751b0,0x04699f4, + 0x252dd64,0x095b8b6,0x0872b74,0x022f1da }, + { 0x2d3d253,0x38edca0,0x379fa5b,0x287d635,0x3a9f679,0x059d9ee, + 0x0ac168e,0x3cd3e87,0x19060fc,0x02ce1bc } }, + /* 159 */ + { { 0x3edcfc2,0x0f04d4b,0x2f0d31f,0x1898be2,0x25396bf,0x15ca230, + 0x02b4eae,0x2713668,0x0f71b06,0x0132d18 }, + { 0x38095ea,0x1ed34d6,0x3603ae6,0x165bf01,0x192bbf8,0x1852859, + 0x075f66b,0x1488f85,0x10895ef,0x014b035 } }, + /* 160 */ + { { 0x1339848,0x3084385,0x0c8d231,0x3a1c1de,0x0e87a28,0x255b85c, + 0x1de6616,0x2702e74,0x1382bb0,0x012b0f2 }, + { 0x198987d,0x381545a,0x34d619b,0x312b827,0x18b2376,0x28fe4cf, + 0x20b7651,0x017d077,0x0c7e397,0x00e0365 } }, + /* 161 */ + { { 0x1542e75,0x0d56aa0,0x39b701a,0x287b806,0x396c724,0x0935c21, + 0x3a29776,0x0debdac,0x171de26,0x00b38f8 }, + { 0x1d5bc1a,0x3fad27d,0x22b5cfe,0x1f89ddf,0x0a65560,0x144dd5b, + 0x2aac2f9,0x139353f,0x0520b62,0x00b9b36 } }, + /* 162 */ + { { 0x031c31d,0x16552e3,0x1a0c368,0x0016fc8,0x168533d,0x171e7b2, + 0x17626e7,0x275502f,0x14742c6,0x03285dd }, + { 0x2d2dbb2,0x3b6bffd,0x1d18cc6,0x2f45d2a,0x0fd0d8c,0x2915e3a, + 0x1e8793a,0x0b39a1d,0x3139cab,0x02a5da9 } }, + /* 163 */ + { { 0x3fb353d,0x147c6e4,0x3a720a6,0x22d5ff3,0x1d75cab,0x06c54a0, + 0x08cfa73,0x12666aa,0x3170a1f,0x021c829 }, + { 0x13e1b90,0x3a34dda,0x1fc38c3,0x02c5bdb,0x2d345dc,0x14aa1d0, + 0x28d00ab,0x224f23a,0x329c769,0x025c67b } }, + /* 164 */ + { { 0x0e35909,0x3bb6356,0x0116820,0x370cf77,0x29366d8,0x3881409, + 0x3999d06,0x013075f,0x176e157,0x02941ca }, + { 0x0e70b2e,0x28dfab1,0x2a8a002,0x15da242,0x084dcf6,0x116ca97, + 0x31bf186,0x1dc9735,0x09df7b7,0x0264e27 } }, + /* 165 */ + { { 0x2da7a4b,0x3023c9e,0x1366238,0x00ff4e2,0x03abe9d,0x19bd44b, + 0x272e897,0x20b91ad,0x2aa202c,0x02a2201 }, + { 0x380184e,0x08112b4,0x0b85660,0x31049aa,0x3a8cb78,0x36113c5, + 0x1670c0a,0x373f9e7,0x3fb4738,0x00010ef } }, + /* 166 */ + { { 0x2d5192e,0x26d770d,0x32af8d5,0x34d1642,0x1acf885,0x05805e0, + 0x166d0a1,0x1219a0d,0x301ba6c,0x014bcfb }, + { 0x2dcb64d,0x19cca83,0x379f398,0x08e01a0,0x10a482c,0x0103cc2, + 0x0be5fa7,0x1f9d45b,0x1899ef2,0x00ca5af } }, + /* 167 */ + { { 0x14d81d7,0x2aea251,0x1b3c476,0x3bd47ae,0x29eade7,0x0715e61, + 0x1a21cd8,0x1c7a586,0x2bfaee5,0x00ee43f }, + { 0x096f7cb,0x0c08f95,0x1bc4939,0x361fed4,0x255be41,0x26fad73, + 0x31dd489,0x02c600f,0x29d9f81,0x01ba201 } }, + /* 168 */ + { { 0x03ea1db,0x1eac46d,0x1292ce3,0x2a54967,0x20a7ff1,0x3e13c61, + 0x1b02218,0x2b44e14,0x3eadefa,0x029c88a }, + { 0x30a9144,0x31e3b0a,0x19c5a2a,0x147cbe9,0x05a0240,0x051f38e, + 0x11eca56,0x31a4247,0x123bc2a,0x02fa535 } }, + /* 169 */ + { { 0x3226ce7,0x1251782,0x0b7072f,0x11e59fa,0x2b8afd7,0x169b18f, + 0x2a46f18,0x31d9bb7,0x2fe9be8,0x01de0b7 }, + { 0x1b38626,0x34aa90f,0x3ad1760,0x21ddbd9,0x3460ae7,0x1126736, + 0x1b86fc5,0x0b92cd0,0x167a289,0x000e0e1 } }, + /* 170 */ + { { 0x1ec1a0f,0x36bbf5e,0x1c972d8,0x3f73ace,0x13bbcd6,0x23d86a5, + 0x175ffc5,0x2d083d5,0x2c4adf7,0x036f661 }, + { 0x1f39eb7,0x2a20505,0x176c81a,0x3d6e636,0x16ee2fc,0x3cbdc5f, + 0x25475dc,0x2ef4151,0x3c46860,0x0238934 } }, + /* 171 */ + { { 0x2587390,0x3639526,0x0588749,0x13c32fb,0x212bb19,0x09660f1, + 0x207da4b,0x2bf211b,0x1c4407b,0x01506a6 }, + { 0x24c8842,0x105a498,0x05ffdb2,0x0ab61b0,0x26044c1,0x3dff3d8, + 0x1d14b44,0x0d74716,0x049f57d,0x030024b } }, + /* 172 */ + { { 0x32e61ef,0x31d70f7,0x35cad3c,0x320b86c,0x07e8841,0x027ca7d, + 0x2d30d19,0x2513718,0x2347286,0x01d7901 }, + { 0x3c237d0,0x107f16e,0x01c9e7d,0x3c3b13c,0x0c9537b,0x20af54d, + 0x051a162,0x2161a47,0x258c784,0x016df2d } }, + /* 173 */ + { { 0x228ead1,0x29c2122,0x07f6964,0x023f4ed,0x1802dc5,0x19f96ce, + 0x24bfd17,0x25e866b,0x2ba8df0,0x01eb84f }, + { 0x2dd384e,0x05bbe3a,0x3f06fd2,0x366dacb,0x30361a2,0x2f36d7c, + 0x0b98784,0x38ff481,0x074e2a8,0x01e1f60 } }, + /* 174 */ + { { 0x17fbb1c,0x0975add,0x1debc5e,0x2cb2880,0x3e47bdd,0x3488cff, + 0x15e9a36,0x2121129,0x0199ef2,0x017088a }, + { 0x0315250,0x352a162,0x17c1773,0x0ae09c2,0x321b21a,0x3bd74cf, + 0x3c4ea1d,0x3cac2ad,0x3abbaf0,0x039174d } }, + /* 175 */ + { { 0x0511c8a,0x3c78d0a,0x2cd3d2d,0x322f729,0x3ebb229,0x09f0e69, + 0x0a71a76,0x2e74d5e,0x12284df,0x03b5ef0 }, + { 0x3dea561,0x0a9b7e4,0x0ed1cf2,0x237523c,0x05443f1,0x2eb48fa, + 0x3861405,0x1b49f62,0x0c945ca,0x02ab25f } }, + /* 176 */ + { { 0x16bd00a,0x13a9d28,0x3cc1eb5,0x2b7d702,0x2d839e9,0x3e6ff01, + 0x2bb7f11,0x3713824,0x3b31163,0x00c63e5 }, + { 0x30d7138,0x0316fb0,0x0220ecc,0x08eaf0c,0x244e8df,0x0088d81, + 0x37972fb,0x3fd34ae,0x2a19a84,0x03e907e } }, + /* 177 */ + { { 0x2642269,0x0b65d29,0x03bd440,0x33a6ede,0x3c81814,0x2507982, + 0x0d38e47,0x3a788e6,0x32c1d26,0x00e2eda }, + { 0x2577f87,0x392895a,0x3e1cc64,0x14f7047,0x08b52d2,0x08a01ca, + 0x336abf6,0x00697fc,0x105ce76,0x0253742 } }, + /* 178 */ + { { 0x293f92a,0x33df737,0x3315156,0x32e26d7,0x0a01333,0x26579d4, + 0x004df9c,0x0aba409,0x067d25c,0x02481de }, + { 0x3f39d44,0x1c78042,0x13d7e24,0x0825aed,0x35f2c90,0x3270f63, + 0x04b7b35,0x3ad4531,0x28bd29b,0x0207a10 } }, + /* 179 */ + { { 0x077199f,0x270aeb1,0x0dd96dd,0x3b9ad7b,0x28cb8ee,0x3903f43, + 0x37db3fe,0x292c62b,0x362dbbf,0x006e52a }, + { 0x247f143,0x0362cf3,0x216344f,0x3f18fd1,0x351e623,0x31664e0, + 0x0f270fc,0x243bbc6,0x2280555,0x001a8e3 } }, + /* 180 */ + { { 0x3355b49,0x2c04e6c,0x399b2e5,0x182d3af,0x020e265,0x09a7cf7, + 0x0ffa6bd,0x353e302,0x02083d9,0x029ecdb }, + { 0x33e8830,0x0570e86,0x1c0b64d,0x386a27e,0x0d5fcea,0x0b45a4c, + 0x2ee4a2e,0x0a8833f,0x2b4a282,0x02f9531 } }, + /* 181 */ + { { 0x191167c,0x36cf7e3,0x225ed6c,0x1e79e99,0x0517c3f,0x11ab1fd, + 0x05648f3,0x08aedc4,0x1abeae0,0x02fcc29 }, + { 0x3828a68,0x1e16fa4,0x30368e7,0x0c9fcfb,0x25161c3,0x24851ac, + 0x1b5feb5,0x344eb84,0x0de2732,0x0347208 } }, + /* 182 */ + { { 0x038b363,0x384d1e4,0x2519043,0x151ac17,0x158c11f,0x009b2b4, + 0x257abe6,0x2368d3f,0x3ed68a1,0x02df45e }, + { 0x29c2559,0x2962478,0x3d8444c,0x1d96fff,0x04f7a03,0x1391a52, + 0x0de4af7,0x3319126,0x15e6412,0x00e65ff } }, + /* 183 */ + { { 0x3d61507,0x1d1a0a2,0x0d2af20,0x354d299,0x329e132,0x2a28578, + 0x2ddfb08,0x04fa3ff,0x1293c6c,0x003bae2 }, + { 0x3e259f8,0x1a68fa9,0x3e67e9b,0x39b44f9,0x1ce1db7,0x347e9a1, + 0x3318f6a,0x2dbbc9d,0x2f8c922,0x008a245 } }, + /* 184 */ + { { 0x212ab5b,0x2b896c2,0x0136959,0x07e55ef,0x0cc1117,0x05b8ac3, + 0x18429ed,0x025fa01,0x11d6e93,0x03b016b }, + { 0x03f3708,0x2e96fab,0x1d77157,0x0d4c2d6,0x131baf9,0x0608d39, + 0x3552371,0x06cdd1e,0x1567ff1,0x01f4c50 } }, + /* 185 */ + { { 0x2dfefab,0x270173d,0x37077bd,0x1a372cd,0x1be2f22,0x28e2ee5, + 0x3ead973,0x35e8f94,0x2fc9bc1,0x03a7399 }, + { 0x36a02a1,0x2855d9b,0x00ed75a,0x37d8398,0x138c087,0x233706e, + 0x147f346,0x01947e2,0x3017228,0x0365942 } }, + /* 186 */ + { { 0x2057e60,0x2d31296,0x25e4504,0x2fa37bc,0x1cbccc3,0x1f0732f, + 0x3532081,0x2de8a98,0x19a804e,0x005359a }, + { 0x31f411a,0x2a10576,0x369c2c8,0x02fe035,0x109fbaf,0x30bddeb, + 0x1eef901,0x1662ad3,0x0410d43,0x01bd31a } }, + /* 187 */ + { { 0x2c24a96,0x1b7d3a5,0x19a3872,0x217f2f6,0x2534dbc,0x2cab8c2, + 0x066ef28,0x26aecf1,0x0fd6118,0x01310d4 }, + { 0x055b8da,0x1fdc5be,0x38a1296,0x25118f0,0x341a423,0x2ba4cd0, + 0x3e1413e,0x062d70d,0x2425a31,0x029c9b4 } }, + /* 188 */ + { { 0x08c1086,0x1acfba5,0x22e1dae,0x0f72f4e,0x3f1de50,0x0f408bc, + 0x35ed3f0,0x3ce48fc,0x282cc6c,0x004d8e7 }, + { 0x1afaa86,0x24e3ef3,0x22589ac,0x3ec9952,0x1f45bc5,0x14144ca, + 0x23b26e4,0x0d68c65,0x1e1c1a3,0x032a4d9 } }, + /* 189 */ + { { 0x03b2d20,0x16b1d53,0x241b361,0x05e4138,0x1742a54,0x32741c7, + 0x0521c4c,0x1ca96c2,0x034970b,0x02738a7 }, + { 0x13e0ad6,0x207dcdb,0x034c8cc,0x27bcbe1,0x18060da,0x33a18b6, + 0x2d1d1a6,0x2be60d7,0x3d7ab42,0x012312a } }, + /* 190 */ + { { 0x0c7485a,0x06c3310,0x0dbfd22,0x2ef949d,0x0ead455,0x098f4ba, + 0x3c76989,0x0cf2d24,0x032f67b,0x01e005f }, + { 0x30cb5ee,0x0d5da64,0x0ed2b9d,0x2503102,0x1c0d14e,0x1cbc693, + 0x37bf552,0x07013e2,0x054de5c,0x014f341 } }, + /* 191 */ + { { 0x128ccac,0x1617e97,0x346ebcd,0x158016d,0x25f823e,0x34048ea, + 0x39f0a1c,0x3ea3df1,0x1c1d3d7,0x03ba919 }, + { 0x151803b,0x01967c1,0x2f70781,0x27df39a,0x06c0b59,0x24a239c, + 0x15a7702,0x2464d06,0x2a47ae6,0x006db90 } }, + /* 192 */ + { { 0x27d04c3,0x024df3d,0x38112e8,0x38a27ba,0x01e312b,0x0965358, + 0x35d8879,0x2f4f55a,0x214187f,0x0008936 }, + { 0x05fe36f,0x2ee18c3,0x1f5f87a,0x1813bd4,0x0580f3c,0x0ed0a7b, + 0x0fb1bfb,0x3fcce59,0x2f042bf,0x01820e3 } }, + /* 193 */ + { { 0x20bbe99,0x32cbc9f,0x39ee432,0x3cc12a8,0x37bda44,0x3ea4e40, + 0x097c7a9,0x0590d7d,0x2022d33,0x018dbac }, + { 0x3ae00aa,0x3439864,0x2d2ffcf,0x3f8c6b9,0x0875a00,0x3e4e407, + 0x3658a29,0x22eb3d0,0x2b63921,0x022113b } }, + /* 194 */ + { { 0x33bae58,0x05c749a,0x1f3e114,0x1c45f8e,0x27db3df,0x06a3ab6, + 0x37bc7f8,0x1e27b34,0x3dc51fb,0x009eea0 }, + { 0x3f54de5,0x3d0e7fe,0x1a71a7d,0x02ed7f8,0x0727703,0x2ca5e92, + 0x2e8e35d,0x292ad0b,0x13487f3,0x02b6d8b } }, + /* 195 */ + { { 0x175df2a,0x05a28a8,0x32e99b1,0x13d8630,0x2082aa0,0x11ac245, + 0x24f2e71,0x322cb27,0x17675e7,0x02e643f }, + { 0x1f37313,0x2765ad3,0x0789082,0x1e742d0,0x11c2055,0x2021dc4, + 0x09ae4a7,0x346359b,0x2f94d10,0x0205c1f } }, + /* 196 */ + { { 0x3d6ff96,0x1f2ac80,0x336097d,0x3f03610,0x35b851b,0x010b6d2, + 0x0823c4d,0x2a9709a,0x2ead5a8,0x00de4b6 }, + { 0x01afa0b,0x0621965,0x3671528,0x1050b60,0x3f3e9e7,0x2f93829, + 0x0825275,0x006e85f,0x35e94b0,0x016af58 } }, + /* 197 */ + { { 0x2c4927c,0x3ea1382,0x0f23727,0x0d69f23,0x3e38860,0x2b72837, + 0x3cd5ea4,0x2d84292,0x321846a,0x016656f }, + { 0x29dfa33,0x3e182e0,0x018be90,0x2ba563f,0x2caafe2,0x218c0d9, + 0x3baf447,0x1047a6c,0x0a2d483,0x01130cb } }, + /* 198 */ + { { 0x00ed80c,0x2a5fc79,0x0a82a74,0x2c4c74b,0x15f938c,0x30b5ab6, + 0x32124b7,0x295314f,0x2fb8082,0x007c858 }, + { 0x20b173e,0x19f315c,0x12f97e4,0x198217c,0x040e8a6,0x3275977, + 0x2bc20e4,0x01f2633,0x02bc3e9,0x023c750 } }, + /* 199 */ + { { 0x3c4058a,0x24be73e,0x16704f5,0x2d8a4bd,0x3b15e14,0x3076315, + 0x1cfe37b,0x36fe715,0x343926e,0x02c6603 }, + { 0x2c76b09,0x0cf824c,0x3f7898c,0x274cec1,0x11df527,0x18eed18, + 0x08ead48,0x23915bc,0x19b3744,0x00a0a2b } }, + /* 200 */ + { { 0x0cf4ac5,0x1c8b131,0x0afb696,0x0ff7799,0x2f5ac1a,0x022420c, + 0x11baa2e,0x2ce4015,0x1275a14,0x0125cfc }, + { 0x22eac5d,0x360cd4c,0x3568e59,0x3d42f66,0x35e07ee,0x09620e4, + 0x36720fa,0x22b1eac,0x2d0db16,0x01b6b23 } }, + /* 201 */ + { { 0x1a835ef,0x1516bbb,0x2d51f7b,0x3487443,0x14aa113,0x0dd06c2, + 0x1a65e01,0x379300d,0x35920b9,0x012c8fb }, + { 0x04c7341,0x2eda00f,0x3c37e82,0x1b4fd62,0x0d45770,0x1478fba, + 0x127863a,0x26939cd,0x134ddf4,0x01375c5 } }, + /* 202 */ + { { 0x1476cd9,0x1119ca5,0x325bbf9,0x0bf8c69,0x0648d07,0x312d9f8, + 0x01c8b8f,0x136ec51,0x0002f4a,0x03f4c5c }, + { 0x195d0e1,0x10ffd22,0x29aa1cb,0x3443bdc,0x276e695,0x05e6260, + 0x15f9764,0x3cd9783,0x18c9569,0x0053eb1 } }, + /* 203 */ + { { 0x312ae18,0x280197c,0x3fc9ad9,0x303f324,0x251958d,0x29f4a11, + 0x2142408,0x3694366,0x25136ab,0x03b5f1d }, + { 0x1d4abbc,0x1c3c689,0x13ea462,0x3cfc684,0x39b5dd8,0x2d4654b, + 0x09b0755,0x27d4f18,0x3f74d2e,0x03fbf2d } }, + /* 204 */ + { { 0x2119185,0x2525eae,0x1ba4bd0,0x0c2ab11,0x1d54e8c,0x294845e, + 0x2479dea,0x3602d24,0x17e87e0,0x0060069 }, + { 0x0afffb0,0x34fe37f,0x1240073,0x02eb895,0x06cf33c,0x2d7f7ef, + 0x1d763b5,0x04191e0,0x11e1ead,0x027e3f0 } }, + /* 205 */ + { { 0x269544c,0x0e85c57,0x3813158,0x19fc12d,0x20eaf85,0x1e2930c, + 0x22a8fd2,0x1a6a478,0x09d3d3a,0x02a74e0 }, + { 0x1a2da3b,0x30b0b16,0x0847936,0x3d86257,0x138ccbc,0x0f5421a, + 0x25244e6,0x23bdd79,0x1aee117,0x00c01ae } }, + /* 206 */ + { { 0x1eead28,0x07cac32,0x1fbc0bb,0x17627d3,0x17eef63,0x0b3a24e, + 0x0757fdb,0x3dd841d,0x3d745f8,0x002ae17 }, + { 0x25b4549,0x29f24cf,0x2f21ecd,0x1725e48,0x04be2bb,0x10ee010, + 0x1a1274b,0x10b0898,0x27511e9,0x02c48b5 } }, + /* 207 */ + { { 0x2a5ae7a,0x181ef99,0x0be33be,0x3e9dab7,0x101e703,0x3adb971, + 0x1043014,0x2ebb2be,0x1c1097d,0x027d667 }, + { 0x3f250ed,0x16dc603,0x20dc6d7,0x1d0d268,0x38eb915,0x02c89e8, + 0x1605a41,0x12de109,0x0e08a29,0x01f554a } }, + /* 208 */ + { { 0x0c26def,0x163d988,0x2d1ef0f,0x3a960ac,0x1025585,0x0738e20, + 0x27d79b0,0x05cc3ef,0x201303f,0x00a333a }, + { 0x1644ba5,0x2af345e,0x30b8d1d,0x3a01bff,0x31fc643,0x1acf85e, + 0x0a76fc6,0x04efe98,0x348a1d0,0x03062eb } }, + /* 209 */ + { { 0x1c4216d,0x18e3217,0x02ac34e,0x19c8185,0x200c010,0x17d4192, + 0x13a1719,0x165af51,0x09db7a9,0x0277be0 }, + { 0x3ab8d2c,0x2190b99,0x22b641e,0x0cd88de,0x3b42404,0x1310862, + 0x106a6d6,0x23395f5,0x0b06880,0x000d5fe } }, + /* 210 */ + { { 0x0d2cc88,0x36f9913,0x339d8e9,0x237c2e3,0x0cc61c2,0x34c2832, + 0x309874c,0x2621d28,0x2dd1b48,0x0392806 }, + { 0x17cd8f9,0x07bab3d,0x0c482ed,0x0faf565,0x31b767d,0x2f4bde1, + 0x295c717,0x330c29c,0x179ce10,0x0119b5f } }, + /* 211 */ + { { 0x1ada2c7,0x0c624a7,0x227d47d,0x30e3e6a,0x14fa0a6,0x0829678, + 0x24fd288,0x2b46a43,0x122451e,0x0319ca9 }, + { 0x186b655,0x01f3217,0x0af1306,0x0efe6b5,0x2f0235d,0x1c45ca9, + 0x2086805,0x1d44e66,0x0faf2a6,0x0178f59 } }, + /* 212 */ + { { 0x33b4416,0x10431e6,0x2d99aa6,0x217aac9,0x0cd8fcf,0x2d95a9d, + 0x3ff74ad,0x10bf17a,0x295eb8e,0x01b229e }, + { 0x02a63bd,0x182e9ec,0x004710c,0x00e2e3c,0x06b2f23,0x04b642c, + 0x2c37383,0x32a4631,0x022ad82,0x00d22b9 } }, + /* 213 */ + { { 0x0cda2fb,0x1d198d7,0x26d27f4,0x286381c,0x022acca,0x24ac7c8, + 0x2df7824,0x0b4ba16,0x1e0d9ef,0x03041d3 }, + { 0x29a65b3,0x0f3912b,0x151bfcf,0x2b0175c,0x0fd71e4,0x39aa5e2, + 0x311f50c,0x13ff351,0x3dbc9e5,0x03eeb7e } }, + /* 214 */ + { { 0x0a99363,0x0fc7348,0x2775171,0x23db3c8,0x2b91565,0x134d66c, + 0x0175cd2,0x1bf365a,0x2b48371,0x02dfe5d }, + { 0x16dbf74,0x2389357,0x2f36575,0x3f5c70e,0x38d23ba,0x090f7f8, + 0x3477600,0x3201523,0x32ecafc,0x03d3506 } }, + /* 215 */ + { { 0x1abd48d,0x073ca3f,0x38a451f,0x0d8cb01,0x1ce81be,0x05c51ba, + 0x0e29741,0x03c41ab,0x0eae016,0x0060209 }, + { 0x2e58358,0x1da62d9,0x2358038,0x14b39b2,0x1635687,0x39079b1, + 0x380e345,0x1b49608,0x23983cf,0x019f97d } }, + /* 216 */ + { { 0x34899ef,0x332e373,0x04c0f89,0x3c27aed,0x1949015,0x09663b2, + 0x2f9276b,0x07f1951,0x09a04c1,0x027fbde }, + { 0x3d2a071,0x19fb3d4,0x1b096d3,0x1fe9146,0x3b10e1a,0x0478bbb, + 0x2b3fb06,0x1388329,0x181a99c,0x02f2030 } }, + /* 217 */ + { { 0x1eb82e6,0x14dbe39,0x3920972,0x31fd5b2,0x21a484f,0x02d7697, + 0x0e21715,0x37c431e,0x2629f8c,0x01249c3 }, + { 0x26b50ad,0x26deefa,0x0ffc1a3,0x30688e2,0x39a0284,0x041c65e, + 0x03eb178,0x0bdfd50,0x2f96137,0x034bb94 } }, + /* 218 */ + { { 0x0e0362a,0x334a162,0x194dd37,0x29e3e97,0x2442fa8,0x10d2949, + 0x3836e5a,0x2dccebf,0x0bee5ab,0x037ed1e }, + { 0x33eede6,0x3c739d9,0x2f04a91,0x350ad6c,0x3a5390a,0x14c368b, + 0x26f7bf5,0x11ce979,0x0b408df,0x0366850 } }, + /* 219 */ + { { 0x28ea498,0x0886d5b,0x2e090e0,0x0a4d58f,0x2623478,0x0d74ab7, + 0x2b83913,0x12c6b81,0x18d623f,0x01d8301 }, + { 0x198aa79,0x26d6330,0x3a7f0b8,0x34bc1ea,0x2f74890,0x378955a, + 0x204110f,0x0102538,0x02d8f19,0x01c5066 } }, + /* 220 */ + { { 0x14b0f45,0x2838cd3,0x14e16f0,0x0e0e4aa,0x2d9280b,0x0f18757, + 0x3324c6b,0x1391ceb,0x1ce89d5,0x00ebe74 }, + { 0x0930371,0x3de6048,0x3097fd8,0x1308705,0x3eda266,0x3108c26, + 0x1545dcd,0x1f7583a,0x1c37395,0x02c7e05 } }, + /* 221 */ + { { 0x1fec44a,0x2a9e3a2,0x0caf84f,0x11cf2a9,0x0c8c2ae,0x06da989, + 0x1c807dc,0x3c149a4,0x1141543,0x02906bb }, + { 0x15ffe04,0x0d4e65f,0x2e20424,0x37d896d,0x18bacb2,0x1e05ddd, + 0x1660be8,0x183be17,0x1dd86fb,0x035ba70 } }, + /* 222 */ + { { 0x2853264,0x0ba5fb1,0x0a0b3aa,0x2df88c1,0x2771533,0x23aba6f, + 0x112bb7b,0x3e3086e,0x210ae9b,0x027271b }, + { 0x030b74c,0x0269678,0x1e90a23,0x135a98c,0x24ed749,0x126de7c, + 0x344b23a,0x186da27,0x19640fa,0x0159af5 } }, + /* 223 */ + { { 0x18061f3,0x3004630,0x3c70066,0x34df20f,0x1190b25,0x1c9cc91, + 0x1fc8e02,0x0d17bc1,0x390f525,0x033cb1c }, + { 0x0eb30cf,0x2f3ad04,0x303aa09,0x2e835dd,0x1cfd2eb,0x143fc95, + 0x02c43a1,0x025e7a1,0x3558aa2,0x000bd45 } }, + /* 224 */ + { { 0x1db7d07,0x3bde52b,0x1500396,0x1089115,0x20b4fc7,0x1e2a8f3, + 0x3f8eacc,0x365f7eb,0x1a5e8d4,0x0053a6b }, + { 0x37079e2,0x120284b,0x000edaa,0x33792c2,0x145baa3,0x20e055f, + 0x365e2d7,0x26ba005,0x3ab8e9d,0x0282b53 } }, + /* 225 */ + { { 0x2653618,0x2dd8852,0x2a5f0bf,0x0f0c7aa,0x2187281,0x1252757, + 0x13e7374,0x3b47855,0x0b86e56,0x02f354c }, + { 0x2e9c47b,0x2fa14cc,0x19ab169,0x3fad401,0x0dc2776,0x24afeed, + 0x3a97611,0x0d07736,0x3cf6979,0x02424a0 } }, + /* 226 */ + { { 0x2e81a13,0x000c91d,0x123967b,0x265885c,0x29bee1a,0x0cb8675, + 0x2d361bd,0x1526823,0x3c9ace1,0x00d7bad }, + { 0x24e5bdc,0x02b969f,0x2c6e128,0x34edb3b,0x12dcd2c,0x3899af0, + 0x24224c6,0x3a1914b,0x0f4448a,0x026a2cb } }, + /* 227 */ + { { 0x1d03b59,0x1c6fc82,0x32abf64,0x28ed96b,0x1c90e62,0x2f57bb2, + 0x3ff168e,0x04de7fd,0x0f4d449,0x01af6d8 }, + { 0x255bc30,0x2bfaf22,0x3fe0dad,0x0584025,0x1c79ead,0x3078ef7, + 0x2197414,0x022a50b,0x0fd94ba,0x0007b0f } }, + /* 228 */ + { { 0x09485c2,0x09dfaf7,0x10c7ba6,0x1e48bec,0x248cc9a,0x028a362, + 0x21d60f7,0x193d93d,0x1c04754,0x0346b2c }, + { 0x2f36612,0x240ac49,0x0d8bd26,0x13b8186,0x259c3a4,0x020d5fb, + 0x38a8133,0x09b0937,0x39d4056,0x01f7341 } }, + /* 229 */ + { { 0x05a4b48,0x1f534fc,0x07725ce,0x148dc8c,0x2adcd29,0x04aa456, + 0x0f79718,0x066e346,0x189377d,0x002fd4d }, + { 0x068ea73,0x336569b,0x184d35e,0x32a08e9,0x3c7f3bb,0x11ce9c8, + 0x3674c6f,0x21bf27e,0x0d9e166,0x034a2f9 } }, + /* 230 */ + { { 0x0fa8e4b,0x2e6418e,0x18fc5d2,0x1ba24ff,0x0559f18,0x0dbedbf, + 0x2de2aa4,0x22338e9,0x3aa510f,0x035d801 }, + { 0x23a4988,0x02aad94,0x02732d1,0x111d374,0x0b455cf,0x0d01c9e, + 0x067082a,0x2ec05fd,0x368b303,0x03cad4b } }, + /* 231 */ + { { 0x035b4ca,0x1fabea6,0x1cbc0d5,0x3f2ed9a,0x02d2232,0x1990c66, + 0x2eb680c,0x3b4ea3b,0x18ecc5a,0x03636fa }, + { 0x1a02709,0x26f8ff1,0x1fa8cba,0x397d6e8,0x230be68,0x043aa14, + 0x3d43cdf,0x25c17fa,0x3a3ee55,0x0380564 } }, + /* 232 */ + { { 0x275a0a6,0x16bd43a,0x0033d3e,0x2b15e16,0x2512226,0x005d901, + 0x26d50fd,0x3bc19bf,0x3b1aeb8,0x02bfb01 }, + { 0x0bb0a31,0x26559e0,0x1aae7fb,0x330dcc2,0x16f1af3,0x06afce2, + 0x13a15a0,0x2ff7645,0x3546e2d,0x029c6e4 } }, + /* 233 */ + { { 0x0f593d2,0x384b806,0x122bbf8,0x0a281e0,0x1d1a904,0x2e93cab, + 0x0505db0,0x08f6454,0x05c6285,0x014e880 }, + { 0x3f2b935,0x22d8e79,0x161a07c,0x16b060a,0x02bff97,0x146328b, + 0x3ceea77,0x238f61a,0x19b3d58,0x02fd1f4 } }, + /* 234 */ + { { 0x17665d5,0x259e9f7,0x0de5672,0x15cbcbd,0x34e3030,0x035240f, + 0x0005ae8,0x286d851,0x07f39c9,0x000070b }, + { 0x1efc6d6,0x2a0051a,0x2724143,0x2a9ef1e,0x0c810bd,0x1e05429, + 0x25670ba,0x2e66d7d,0x0e786ff,0x03f6b7e } }, + /* 235 */ + { { 0x3c00785,0x232e23f,0x2b67fd3,0x244ed23,0x077fa75,0x3cda3ef, + 0x14d055b,0x0f25011,0x24d5aa4,0x00ea0e3 }, + { 0x297bb9a,0x198ca4f,0x14d9561,0x18d1076,0x39eb933,0x2b6caa0, + 0x1591a60,0x0768d45,0x257873e,0x00f36e0 } }, + /* 236 */ + { { 0x1e77eab,0x0502a5f,0x0109137,0x0350592,0x3f7e1c5,0x3ac7437, + 0x2dcad2c,0x1fee9d8,0x089f1f5,0x0169833 }, + { 0x0d45673,0x0d8e090,0x065580b,0x065644f,0x11b82be,0x3592dd0, + 0x3284b8d,0x23f0015,0x16fdbfd,0x0248bfd } }, + /* 237 */ + { { 0x1a129a1,0x1977bb2,0x0e041b2,0x15f30a1,0x0a5b1ce,0x3afef8f, + 0x380c46c,0x3358810,0x27df6c5,0x01ca466 }, + { 0x3b90f9a,0x3d14ea3,0x031b298,0x02e2390,0x2d719c0,0x25bc615, + 0x2c0e777,0x0226b8c,0x3803624,0x0179e45 } }, + /* 238 */ + { { 0x363cdfb,0x1bb155f,0x24fd5c1,0x1c7c72b,0x28e6a35,0x18165f2, + 0x226bea5,0x0beaff3,0x371e24c,0x0138294 }, + { 0x1765357,0x29034e9,0x22b4276,0x11035ce,0x23c89af,0x074468c, + 0x3370ae4,0x013bae3,0x018d566,0x03d7fde } }, + /* 239 */ + { { 0x209df21,0x0f8ff86,0x0e47fbf,0x23b99ba,0x126d5d2,0x2722405, + 0x16bd0a2,0x1799082,0x0e9533f,0x039077c }, + { 0x3ba9e3f,0x3f6902c,0x1895305,0x3ac9813,0x3f2340c,0x3c0d9f1, + 0x26e1927,0x0557c21,0x16eac4f,0x023b75f } }, + /* 240 */ + { { 0x3fc8ff3,0x0770382,0x342fc9a,0x0afa4db,0x314efd8,0x328e07b, + 0x016f7cc,0x3ba599c,0x1caed8a,0x0050cb0 }, + { 0x0b23c26,0x2120a5c,0x3273ec6,0x1cc1cd6,0x2a64fe8,0x2bbc3d6, + 0x09f6e5e,0x34b1b8e,0x00b5ac8,0x032bbd2 } }, + /* 241 */ + { { 0x1315922,0x1725e1d,0x0ca5524,0x1c4c18f,0x3d82951,0x193bcb2, + 0x0e60d0b,0x388dbcf,0x37e8efa,0x0342e85 }, + { 0x1b3af60,0x26ba3ec,0x220e53a,0x394f4b6,0x01a796a,0x3e7bbca, + 0x163605d,0x2b85807,0x17c1c54,0x03cc725 } }, + /* 242 */ + { { 0x1cc4597,0x1635492,0x2028c0f,0x2c2eb82,0x2dc5015,0x0d2a052, + 0x05fc557,0x1f0ebbf,0x0cb96e1,0x0004d01 }, + { 0x1a824bf,0x3896172,0x2ed7b29,0x178007a,0x0d59318,0x07bda2b, + 0x2ee6826,0x0f9b235,0x04b9193,0x01bcddf } }, + /* 243 */ + { { 0x0333fd2,0x0eeb46a,0x15b89f9,0x00968aa,0x2a89302,0x2bdd6b3, + 0x1e5037e,0x2541884,0x24ed2d0,0x01b6e8f }, + { 0x04399cd,0x3be6334,0x3adea48,0x1bb9adc,0x31811c6,0x05fb2bc, + 0x360752c,0x3d29dcb,0x3423bec,0x03c4f3c } }, + /* 244 */ + { { 0x119e2eb,0x2e7b02a,0x0f68cee,0x257d8b0,0x183a9a1,0x2ae88a6, + 0x3a3bb67,0x2eb4f3e,0x1a9274b,0x0320fea }, + { 0x2fa1ce0,0x346c2d8,0x2fbf0d7,0x3d4d063,0x0e58b60,0x09c1bc1, + 0x28ef9e5,0x09a0efe,0x0f45d70,0x02d275c } }, + /* 245 */ + { { 0x2d5513b,0x31d443e,0x1e2d914,0x3b2c5d4,0x105f32e,0x27ee756, + 0x050418d,0x3c73db6,0x1bb0c30,0x01673eb }, + { 0x1cb7fd6,0x1eb08d5,0x26a3e16,0x2e20810,0x0249367,0x029e219, + 0x2ec58c9,0x12d9fab,0x362354a,0x016eafc } }, + /* 246 */ + { { 0x2424865,0x260747b,0x177f37c,0x1e3cb95,0x08b0028,0x2783016, + 0x2970f1b,0x323c1c0,0x2a79026,0x0186231 }, + { 0x0f244da,0x26866f4,0x087306f,0x173ec20,0x31ecced,0x3c84d8d, + 0x070f9b9,0x2e764d5,0x075df50,0x0264ff9 } }, + /* 247 */ + { { 0x32c3609,0x0c737e6,0x14ea68e,0x300b11b,0x184eb19,0x29dd440, + 0x09ec1a9,0x185adeb,0x0664c80,0x0207dd9 }, + { 0x1fbe978,0x30a969d,0x33561d7,0x34fc60e,0x36743fe,0x00774af, + 0x0d1f045,0x018360e,0x12a5fe9,0x01592a0 } }, + /* 248 */ + { { 0x2817d1d,0x2993d3e,0x2e0f7a5,0x112faa0,0x255f968,0x355fe6a, + 0x3f5a0fc,0x075b2d7,0x3cf00e5,0x0089afc }, + { 0x32833cf,0x06a7e4b,0x09a8d6d,0x1693d3e,0x320a0a3,0x3cfdfdd, + 0x136c498,0x1e0d845,0x347ff25,0x01a1de7 } }, + /* 249 */ + { { 0x3043d08,0x030705c,0x20fa79b,0x1d07f00,0x0a54467,0x29b49b4, + 0x367e289,0x0b82f4d,0x0d1eb09,0x025ef2c }, + { 0x32ed3c3,0x1baaa3c,0x3c482ab,0x146ca06,0x3c8a4f1,0x3e85e3c, + 0x1bf4f3b,0x1195534,0x3e80a78,0x02a1cbf } }, + /* 250 */ + { { 0x32b2086,0x2de4d68,0x3486b1a,0x03a0583,0x2e1eb71,0x2dab9af, + 0x10cd913,0x28daa6f,0x3fcb732,0x000a04a }, + { 0x3605318,0x3f5f2b3,0x2d1da63,0x143f7f5,0x1646e5d,0x040b586, + 0x1683982,0x25abe87,0x0c9fe53,0x001ce47 } }, + /* 251 */ + { { 0x380d02b,0x055fc22,0x3f7fc50,0x3458a1d,0x26b8333,0x23550ab, + 0x0a1af87,0x0a821eb,0x2dc7e6d,0x00d574a }, + { 0x07386e1,0x3ccd68a,0x3275b41,0x253e390,0x2fd272a,0x1e6627a, + 0x2ca2cde,0x0e9e4a1,0x1e37c2a,0x00f70ac } }, + /* 252 */ + { { 0x0581352,0x2748701,0x02bed68,0x094dd9e,0x30a00c8,0x3fb5c07, + 0x3bd5909,0x211ac80,0x1103ccd,0x0311e1a }, + { 0x0c768ed,0x29dc209,0x36575db,0x009a107,0x272feea,0x2b33383, + 0x313ed56,0x134c9cc,0x168d5bb,0x033310a } }, + /* 253 */ + { { 0x17620b9,0x143784f,0x256a94e,0x229664a,0x1d89a5c,0x1d521f2, + 0x0076406,0x1c73f70,0x342aa48,0x03851fa }, + { 0x0f3ae46,0x2ad3bab,0x0fbe274,0x3ed40d4,0x2fd4936,0x232103a, + 0x2afe474,0x25b8f7c,0x047080e,0x008e6b0 } }, + /* 254 */ + { { 0x3fee8d4,0x347cd4a,0x0fec481,0x33fe9ec,0x0ce80b5,0x33a6bcf, + 0x1c4c9e2,0x3967441,0x1a3f5f7,0x03157e8 }, + { 0x257c227,0x1bc53a0,0x200b318,0x0fcd0af,0x2c5b165,0x2a413ec, + 0x2fc998a,0x2da6426,0x19cd4f4,0x0025336 } }, + /* 255 */ + { { 0x303beba,0x2072135,0x32918a9,0x140cb3a,0x08631d1,0x0ef527b, + 0x05f2c9e,0x2b4ce91,0x0b642ab,0x02e428c }, + { 0x0a5abf9,0x15013ed,0x3603b46,0x30dd76d,0x3004750,0x28d7627, + 0x1a42ccc,0x093ddbe,0x39a1b79,0x00067e2 } }, +}; + +/* 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, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_10(r, &p256_base, p256_table, + k, map, heap); +} + +#endif + + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#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. + */ +SP_NOINLINE static void sp_256_mul_d_10(sp_digit* r, const sp_digit* a, + 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] = Q6_P_mpy_RR(tb, a[0]); + t[ 1] = Q6_P_mpy_RR(tb, a[1]); + t[ 2] = Q6_P_mpy_RR(tb, a[2]); + t[ 3] = Q6_P_mpy_RR(tb, a[3]); + t[ 4] = Q6_P_mpy_RR(tb, a[4]); + t[ 5] = Q6_P_mpy_RR(tb, a[5]); + t[ 6] = Q6_P_mpy_RR(tb, a[6]); + t[ 7] = Q6_P_mpy_RR(tb, a[7]); + t[ 8] = Q6_P_mpy_RR(tb, a[8]); + t[ 9] = Q6_P_mpy_RR(tb, a[9]); + r[ 0] = Q6_R_and_RR(t[ 0], 0x3ffffff); + r[ 1] = (sp_digit)(t[ 0] >> 26) + Q6_R_and_RR(t[ 1], 0x3ffffff); + r[ 2] = (sp_digit)(t[ 1] >> 26) + Q6_R_and_RR(t[ 2], 0x3ffffff); + r[ 3] = (sp_digit)(t[ 2] >> 26) + Q6_R_and_RR(t[ 3], 0x3ffffff); + r[ 4] = (sp_digit)(t[ 3] >> 26) + Q6_R_and_RR(t[ 4], 0x3ffffff); + r[ 5] = (sp_digit)(t[ 4] >> 26) + Q6_R_and_RR(t[ 5], 0x3ffffff); + r[ 6] = (sp_digit)(t[ 5] >> 26) + Q6_R_and_RR(t[ 6], 0x3ffffff); + r[ 7] = (sp_digit)(t[ 6] >> 26) + Q6_R_and_RR(t[ 7], 0x3ffffff); + r[ 8] = (sp_digit)(t[ 7] >> 26) + Q6_R_and_RR(t[ 8], 0x3ffffff); + r[ 9] = (sp_digit)(t[ 8] >> 26) + Q6_R_and_RR(t[ 9], 0x3ffffff); + r[10] = (sp_digit)(t[ 9] >> 26); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_256_div_word_10(sp_digit d1, sp_digit d0, + sp_digit dv) +{ + sp_digit d, r, t, dv; + int64_t t0, t1; + + /* dv has 14 bits. */ + dv = (div >> 12) + 1; + /* All 26 bits from d1 and top 5 bits from d0. */ + d = (d1 << 5) | (d0 >> 21); + r = d / dv; + d -= r * dv; + /* Up to 17 bits in r */ + /* Next 9 bits from d0. */ + d <<= 9; + r <<= 9; + d |= (d0 >> 12) & ((1 << 9) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 26 bits in r */ + + /* Handle rounding error with dv - top part */ + t0 = ((int64_t)d1 << 26) + d0; + t1 = (int64_t)r * dv; + t1 = t0 - t1; + t = (sp_digit)(t1 >> 12) / dv; + r += t; + + /* Handle rounding error with dv - bottom 32 bits */ + t1 = (sp_digit)t0 - (r * dv); + t = (sp_digit)t1 / dv; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* 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 Number 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(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit dv, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[20], t2d[10 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 10 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t1 = td; + t2 = td + 2 * 10; +#else + t1 = t1d; + t2 = t2d; +#endif + + dv = d[9]; + XMEMCPY(t1, a, sizeof(*t1) * 2U * 10U); + for (i=9; i>=0; i--) { + t1[10 + i] += t1[10 + i - 1] >> 26; + t1[10 + i - 1] = Q6_R_and_RR(t1[10 + i - 1], 0x3ffffff); +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[10 + i]; + d1 <<= 26; + d1 += t1[10 + i - 1]; + r1 = (sp_digit)(d1 / dv); +#else + r1 = sp_256_div_word_10(t1[10 + i], t1[10 + i - 1], dv); +#endif + + sp_256_mul_d_10(t2, d, r1); + (void)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] = Q6_R_and_RR(t1[10 + i - 1], 0x3ffffff); + r1 = (((-t1[10 + i]) << 26) - t1[10 + i - 1]) / dv; + r1++; + sp_256_mul_d_10(t2, d, r1); + (void)sp_256_add_10(&t1[i], &t1[i], t2); + t1[10 + i] += t1[10 + i - 1] >> 26; + t1[10 + i - 1] = Q6_R_and_RR(t1[10 + i - 1], 0x3ffffff); + } + t1[10 - 1] += t1[10 - 2] >> 26; + t1[10 - 2] &= 0x3ffffff; + d1 = t1[10 - 1]; + r1 = (sp_digit)(d1 / dv); + + sp_256_mul_d_10(t2, d, r1); + (void)sp_256_sub_10(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2U * 10U); + 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) ? + (sp_digit)1 : (sp_digit)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, const sp_digit* a, const 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] = { + 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU,0xffffffffU,0xffffffffU, + 0x00000000U,0xffffffffU +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint32_t p256_order_low[4] = { + 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU +}; +#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, const sp_digit* a, const sp_digit* b) +{ + sp_256_mul_10(r, a, b); + sp_256_mont_reduce_order_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, const sp_digit* a) +{ + sp_256_sqr_10(r, a); + sp_256_mont_reduce_order_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, const 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_int_digit)1 << (i % 32))) != 0) { + sp_256_mont_mul_order_10(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 10U); +#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 (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + 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 (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + 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 (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + 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 (((sp_digit)p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) { + 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 */ +} + +#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ + +#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 wolfSSL_DSP_ECC_Verify_256(remote_handle64 h, int32 *u1, int hashLen, int32* r, int rSz, int32* s, int sSz, + int32* x, int xSz, int32* y, int ySz, int32* z, int zSz, int* res) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit u2d[2*10] __attribute__((aligned(128))); + sp_digit tmpd[2*10 * 5] __attribute__((aligned(128))); + sp_point p1d; + sp_point p2d; +#endif + sp_digit* u2 = NULL; + sp_digit* tmp = NULL; + sp_point* p1; + sp_point* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + void* heap = NULL; + + (void)h; + (void)hashLen; + + err = sp_ecc_point_new(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_ecc_point_new(heap, p2d, p2); + } + + if (err == MP_OKAY) { + u2 = u2d; + tmp = tmpd; + + XMEMCPY(u2, r, 40); + XMEMCPY(p2->x, x, 40); + XMEMCPY(p2->y, y, 40); + XMEMCPY(p2->z, z, 40); + + 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); + { + + 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); + } + + err = sp_256_ecc_mulmod_base_10(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_10(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + 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. */ + XMEMCPY(u2, r, 40); + 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 = (int)(sp_256_cmp_10(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + XMEMCPY(u2, r, 40); + carry = sp_256_add_10(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + 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 = (int)(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; +} + +/** Free the Fixed Point cache */ +void wc_ecc_fp_free(void) +{ +} + + +AEEResult wolfSSL_open(const char *uri, remote_handle64 *handle) +{ + void *tptr; + /* can be any value or ignored, rpc layer doesn't care + * also ok + * *handle = 0; + * *handle = 0xdeadc0de; + */ + tptr = (void *)malloc(1); + *handle = (remote_handle64)tptr; + return 0; +} + +AEEResult wolfSSL_close(remote_handle64 handle) +{ + if (handle) + free((void*)handle); + return 0; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 10 * 5]; + sp_point pd; + sp_point qd; +#endif + sp_digit* tmp; + sp_point* p; + sp_point* q = NULL; + int err; + + err = sp_ecc_point_new(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_ecc_point_new(NULL, qd, q); + } +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 10, pX); + sp_256_from_mp(p->y, 10, pY); + sp_256_from_mp(p->z, 10, pZ); + sp_256_from_mp(q->x, 10, qX); + sp_256_from_mp(q->y, 10, qY); + sp_256_from_mp(q->z, 10, qZ); + + sp_256_proj_point_add_10(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_ecc_point_free(q, 0, NULL); + sp_ecc_point_free(p, 0, NULL); + + return err; +} + + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 10 * 2]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 10, pX); + sp_256_from_mp(p->y, 10, pY); + sp_256_from_mp(p->z, 10, pZ); + + sp_256_proj_point_dbl_10(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 10 * 4]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 10, pX); + sp_256_from_mp(p->y, 10, pY); + sp_256_from_mp(p->z, 10, pZ); + + sp_256_map_10(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, pZ); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_10(sp_digit* y) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit t1d[2 * 10]; + sp_digit t2d[2 * 10]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t1 = d + 0 * 10; + t2 = d + 2 * 10; +#else + t1 = t1d; + t2 = t2d; +#endif + + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_10(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_10(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_10(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_10(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_10(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_10(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_10(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_10(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_10(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_10(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_10(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit xd[2 * 10]; + sp_digit yd[2 * 10]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + x = d + 0 * 10; + y = d + 2 * 10; +#else + x = xd; + y = yd; +#endif + + sp_256_from_mp(x, 10, xm); + err = sp_256_mod_mul_norm_10(x, x, p256_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_10(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_10(y, y, x, p256_mod); + sp_256_mont_sub_10(y, y, x, p256_mod); + sp_256_mont_sub_10(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_10(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_10(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_10(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 10, 0, 10U * sizeof(sp_digit)); + sp_256_mont_reduce_10(y, p256_mod, p256_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_256_mont_sub_10(y, p256_mod, y, p256_mod); + } + + err = sp_256_to_mp(y, ym); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_DSP */ +#endif /* WOLFSSL_HAVE_SP_ECC */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_int.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_int.c new file mode 100644 index 000000000..0db891b98 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_int.c @@ -0,0 +1,2203 @@ +/* sp_int.c + * + * Copyright (C) 2006-2020 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 +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* SP Build Options: + * WOLFSSL_HAVE_SP_RSA: Enable SP RSA support + * WOLFSSL_HAVE_SP_DH: Enable SP DH support + * WOLFSSL_HAVE_SP_ECC: Enable SP ECC support + * WOLFSSL_SP_MATH: Use only single precision math and algorithms it supports (no fastmath tfm.c or normal integer.c) + * WOLFSSL_SP_SMALL: Use smaller version of code and avoid large stack variables + * WOLFSSL_SP_NO_MALLOC: Always use stack, no heap XMALLOC/XFREE allowed + * WOLFSSL_SP_NO_3072: Disable RSA/DH 3072-bit support + * WOLFSSL_SP_NO_2048: Disable RSA/DH 2048-bit support + * WOLFSSL_SP_4096: Enable RSA/RH 4096-bit support + * WOLFSSL_SP_384 Enable ECC 384-bit SECP384R1 support + * WOLFSSL_SP_NO_256 Disable ECC 256-bit SECP256R1 support + * WOLFSSL_SP_CACHE_RESISTANT Enable cache resistantant code + * WOLFSSL_SP_ASM Enable assembly speedups (detect platform) + * WOLFSSL_SP_X86_64_ASM Enable Intel x86 assembly speedups like AVX/AVX2 + * WOLFSSL_SP_ARM32_ASM Enable Aarch32 assembly speedups + * WOLFSSL_SP_ARM64_ASM Enable Aarch64 assembly speedups + * WOLFSSL_SP_ARM_CORTEX_M_ASM Enable Cortex-M assembly speedups + * WOLFSSL_SP_ARM_THUMB_ASM Enable ARM Thumb assembly speedups (used with -mthumb) + */ + +#ifdef WOLFSSL_SP_MATH + +#include + +#if defined(WOLFSSL_HAVE_SP_DH) || defined(WOLFSSL_HAVE_SP_RSA) + +WOLFSSL_LOCAL int sp_ModExp_1024(sp_int* base, sp_int* exp, sp_int* mod, + sp_int* res); +WOLFSSL_LOCAL int sp_ModExp_1536(sp_int* base, sp_int* exp, sp_int* mod, + sp_int* res); +WOLFSSL_LOCAL int sp_ModExp_2048(sp_int* base, sp_int* exp, sp_int* mod, + sp_int* res); +WOLFSSL_LOCAL int sp_ModExp_3072(sp_int* base, sp_int* exp, sp_int* mod, + sp_int* res); +WOLFSSL_LOCAL int sp_ModExp_4096(sp_int* base, sp_int* exp, sp_int* mod, + sp_int* res); + +#endif + +int sp_get_digit_count(sp_int *a) +{ + int ret; + if (!a) + ret = 0; + else + ret = a->used; + return ret; +} + +/* Initialize the big number to be zero. + * + * a SP integer. + * returns MP_OKAY always. + */ +int sp_init(sp_int* a) +{ + a->used = 0; + a->size = SP_INT_DIGITS; + + return MP_OKAY; +} + +#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) || (!defined(NO_DH) || defined(HAVE_ECC)) +/* Initialize up to six big numbers to be zero. + * + * a SP integer. + * b SP integer. + * c SP integer. + * d SP integer. + * e SP integer. + * f SP integer. + * returns MP_OKAY always. + */ +int sp_init_multi(sp_int* a, sp_int* b, sp_int* c, sp_int* d, sp_int* e, + sp_int* f) +{ + if (a != NULL) { + a->used = 0; + a->size = SP_INT_DIGITS; + } + if (b != NULL) { + b->used = 0; + b->size = SP_INT_DIGITS; + } + if (c != NULL) { + c->used = 0; + c->size = SP_INT_DIGITS; + } + if (d != NULL) { + d->used = 0; + d->size = SP_INT_DIGITS; + } + if (e != NULL) { + e->used = 0; + e->size = SP_INT_DIGITS; + } + if (f != NULL) { + f->used = 0; + f->size = SP_INT_DIGITS; + } + + return MP_OKAY; +} +#endif + +/* Clear the data from the big number and set to zero. + * + * a SP integer. + */ +void sp_clear(sp_int* a) +{ + if (a != NULL) { + int i; + + for (i=0; iused; i++) + a->dp[i] = 0; + a->used = 0; + } +} + +/* Calculate the number of 8-bit values required to represent the big number. + * + * a SP integer. + * returns the count. + */ +int sp_unsigned_bin_size(sp_int* a) +{ + int size = sp_count_bits(a); + return (size + 7) / 8; +} + +/* Convert a number as an array of bytes in big-endian format to a big number. + * + * a SP integer. + * in Array of bytes. + * inSz Number of data bytes in array. + * returns BAD_FUNC_ARG when the number is too big to fit in an SP and + MP_OKAY otherwise. + */ +int sp_read_unsigned_bin(sp_int* a, const byte* in, int inSz) +{ + int err = MP_OKAY; + int i, j = 0, k; + + if (inSz > SP_INT_DIGITS * (int)sizeof(a->dp[0])) { + err = MP_VAL; + } + + if (err == MP_OKAY) { + for (i = inSz-1; i >= (SP_WORD_SIZE/8); i -= (SP_WORD_SIZE/8), j++) { + a->dp[j] = (((sp_int_digit)in[i-0]) << (0*8)) + | (((sp_int_digit)in[i-1]) << (1*8)) + | (((sp_int_digit)in[i-2]) << (2*8)) + | (((sp_int_digit)in[i-3]) << (3*8)); + #if SP_WORD_SIZE == 64 + a->dp[j] |= (((sp_int_digit)in[i-4]) << (4*8)) + | (((sp_int_digit)in[i-5]) << (5*8)) + | (((sp_int_digit)in[i-6]) << (6*8)) + | (((sp_int_digit)in[i-7]) << (7*8)); + #endif + } + if (i >= 0) { + a->dp[j] = 0; + for (k = 0; k <= i; k++) { + a->dp[j] <<= 8; + a->dp[j] |= in[k]; + } + } + a->used = j + 1; + } + + sp_clamp(a); + + return err; +} + +#ifdef HAVE_ECC +/* Convert a number as string in big-endian format to a big number. + * Only supports base-16 (hexadecimal). + * Negative values not supported. + * + * a SP integer. + * in NUL terminated string. + * radix Number of values in a digit. + * returns BAD_FUNC_ARG when radix not supported or value is negative, MP_VAL + * when a character is not valid and MP_OKAY otherwise. + */ +int sp_read_radix(sp_int* a, const char* in, int radix) +{ + int err = MP_OKAY; + int i, j = 0, k = 0; + char ch; + + if ((radix != 16) || (*in == '-')) { + err = BAD_FUNC_ARG; + } + + while (*in == '0') { + in++; + } + + if (err == MP_OKAY) { + a->dp[0] = 0; + for (i = (int)(XSTRLEN(in) - 1); i >= 0; i--) { + ch = in[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 { + err = MP_VAL; + break; + } + + a->dp[k] |= ((sp_int_digit)ch) << j; + j += 4; + if (k >= SP_INT_DIGITS - 1) { + err = MP_VAL; + break; + } + if (j == DIGIT_BIT) + a->dp[++k] = 0; + j &= SP_WORD_SIZE - 1; + } + } + + if (err == MP_OKAY) { + a->used = k + 1; + if (a->dp[k] == 0) + a->used--; + + for (k++; k < a->size; k++) + a->dp[k] = 0; + + sp_clamp(a); + } + + return err; +} +#endif + +/* Compare two big numbers. + * + * a SP integer. + * b SP integer. + * returns MP_GT if a is greater than b, MP_LT if a is less than b and MP_EQ + * when a equals b. + */ +int sp_cmp(sp_int* a, sp_int* b) +{ + int ret = MP_EQ; + int i; + + if (a->used > b->used) + ret = MP_GT; + else if (a->used < b->used) + ret = MP_LT; + else { + for (i = a->used - 1; i >= 0; i--) { + if (a->dp[i] > b->dp[i]) { + ret = MP_GT; + break; + } + else if (a->dp[i] < b->dp[i]) { + ret = MP_LT; + break; + } + } + } + return ret; +} + +/* Count the number of bits in the big number. + * + * a SP integer. + * returns the number of bits. + */ +int sp_count_bits(sp_int* a) +{ + int r = 0; + sp_int_digit d; + + r = a->used - 1; + while (r >= 0 && a->dp[r] == 0) + r--; + if (r < 0) + r = 0; + else { + d = a->dp[r]; + r *= SP_WORD_SIZE; + if (d >= (1L << (SP_WORD_SIZE / 2))) { + r += SP_WORD_SIZE; + while ((d & (1UL << (SP_WORD_SIZE - 1))) == 0) { + r--; + d <<= 1; + } + } + else { + while (d != 0) { + r++; + d >>= 1; + } + } + } + + return r; +} + +/* Determine if the most significant byte of the encoded big number as the top + * bit set. + * + * a SP integer. + * returns 1 when the top bit is set and 0 otherwise. + */ +int sp_leading_bit(sp_int* a) +{ + int bit = 0; + sp_int_digit d; + + if (a->used > 0) { + d = a->dp[a->used - 1]; + while (d > (sp_int_digit)0xff) + d >>= 8; + bit = (int)(d >> 7); + } + + return bit; +} + +#if !defined(NO_DH) || defined(HAVE_ECC) || defined(WC_RSA_BLINDING) || \ + !defined(WOLFSSL_RSA_VERIFY_ONLY) +/* Convert the big number to an array of bytes in big-endian format. + * The array must be large enough for encoded number - use mp_unsigned_bin_size + * to calculate the number of bytes required. + * + * a SP integer. + * out Array to put encoding into. + * returns MP_OKAY always. + */ +int sp_to_unsigned_bin(sp_int* a, byte* out) +{ + int i, j, b; + sp_int_digit d; + + j = sp_unsigned_bin_size(a) - 1; + for (i=0; j>=0; i++) { + d = a->dp[i]; + for (b = 0; b < SP_WORD_SIZE / 8; b++) { + out[j] = d; + if (--j < 0) { + break; + } + d >>= 8; + } + } + + return MP_OKAY; +} +#endif + +/* Convert the big number to an array of bytes in big-endian format. + * The array must be large enough for encoded number - use mp_unsigned_bin_size + * to calculate the number of bytes required. + * Front-pads the output array with zeros make number the size of the array. + * + * a SP integer. + * out Array to put encoding into. + * outSz Size of the array. + * returns MP_OKAY always. + */ +int sp_to_unsigned_bin_len(sp_int* a, byte* out, int outSz) +{ + int i, j, b; + + j = outSz - 1; + for (i=0; j>=0; i++) { + for (b = 0; b < SP_WORD_SIZE; b += 8) { + out[j--] = a->dp[i] >> b; + if (j < 0) + break; + } + } + + return MP_OKAY; +} + +#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) || (!defined(NO_DH) || defined(HAVE_ECC)) +/* Ensure the data in the big number is zeroed. + * + * a SP integer. + */ +void sp_forcezero(sp_int* a) +{ + ForceZero(a->dp, a->used * sizeof(sp_int_digit)); + a->used = 0; +} +#endif + +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) || (!defined(NO_DH) || defined(HAVE_ECC)) +/* Copy value of big number a into r. + * + * a SP integer. + * r SP integer. + * returns MP_OKAY always. + */ +int sp_copy(sp_int* a, sp_int* r) +{ + if (a != r) { + XMEMCPY(r->dp, a->dp, a->used * sizeof(sp_int_digit)); + r->used = a->used; + } + return MP_OKAY; +} + +/* creates "a" then copies b into it */ +int sp_init_copy (sp_int * a, sp_int * b) +{ + int err; + if ((err = sp_init(a)) == MP_OKAY) { + if((err = sp_copy (b, a)) != MP_OKAY) { + sp_clear(a); + } + } + return err; +} +#endif + +/* Set the big number to be the value of the digit. + * + * a SP integer. + * d Digit to be set. + * returns MP_OKAY always. + */ +int sp_set(sp_int* a, sp_int_digit d) +{ + if (d == 0) { + a->dp[0] = d; + a->used = 0; + } + else { + a->dp[0] = d; + a->used = 1; + } + return MP_OKAY; +} + +/* Recalculate the number of digits used. + * + * a SP integer. + */ +void sp_clamp(sp_int* a) +{ + int i; + + for (i = a->used - 1; i >= 0 && a->dp[i] == 0; i--) { + } + a->used = i + 1; +} + +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) || (!defined(NO_DH) || defined(HAVE_ECC)) +/* Grow big number to be able to hold l digits. + * This function does nothing as the number of digits is fixed. + * + * a SP integer. + * l Number of digits. + * returns MP_MEM if the number of digits requested is more than available and + * MP_OKAY otherwise. + */ +int sp_grow(sp_int* a, int l) +{ + int err = MP_OKAY; + + if (l > a->size) + err = MP_MEM; + + return err; +} + +/* Sub a one digit number from the big number. + * + * a SP integer. + * d Digit to subtract. + * r SP integer - result. + * returns MP_OKAY always. + */ +int sp_sub_d(sp_int* a, sp_int_digit d, sp_int* r) +{ + int i = 0; + sp_int_digit t; + + r->used = a->used; + t = a->dp[0] - d; + if (t > a->dp[0]) { + for (++i; i < a->used; i++) { + r->dp[i] = a->dp[i] - 1; + if (r->dp[i] != (sp_int_digit)-1) + break; + } + } + r->dp[0] = t; + if (r != a) { + for (++i; i < a->used; i++) + r->dp[i] = a->dp[i]; + } + sp_clamp(r); + + return MP_OKAY; +} +#endif + +/* Compare a one digit number with a big number. + * + * a SP integer. + * d Digit to compare with. + * returns MP_GT if a is greater than d, MP_LT if a is less than d and MP_EQ + * when a equals d. + */ +int sp_cmp_d(sp_int *a, sp_int_digit d) +{ + int ret = MP_EQ; + + /* special case for zero*/ + if (a->used == 0) { + if (d == 0) + ret = MP_EQ; + else + ret = MP_LT; + } + else if (a->used > 1) + ret = MP_GT; + else { + /* compare the only digit of a to d */ + if (a->dp[0] > d) + ret = MP_GT; + else if (a->dp[0] < d) + ret = MP_LT; + } + + return ret; +} + +#if !defined(NO_DH) || defined(HAVE_ECC) || !defined(WOLFSSL_RSA_VERIFY_ONLY) +/* Left shift the number by number of bits. + * Bits may be larger than the word size. + * + * a SP integer. + * n Number of bits to shift. + * returns MP_OKAY always. + */ +static int sp_lshb(sp_int* a, int n) +{ + int i; + + if (n >= SP_WORD_SIZE) { + sp_lshd(a, n / SP_WORD_SIZE); + n %= SP_WORD_SIZE; + } + + if (n != 0) { + a->dp[a->used] = 0; + for (i = a->used - 1; i >= 0; i--) { + a->dp[i+1] |= a->dp[i] >> (SP_WORD_SIZE - n); + a->dp[i] = a->dp[i] << n; + } + if (a->dp[a->used] != 0) + a->used++; + } + + return MP_OKAY; +} + +/* Subtract two large numbers into result: r = a - b + * a must be greater than b. + * + * a SP integer. + * b SP integer. + * r SP integer. + * returns MP_OKAY always. + */ +int sp_sub(sp_int* a, sp_int* b, sp_int* r) +{ + int i; + sp_int_digit c = 0; + sp_int_digit t; + + for (i = 0; i < a->used && i < b->used; i++) { + t = a->dp[i] - b->dp[i] - c; + if (c == 0) + c = t > a->dp[i]; + else + c = t >= a->dp[i]; + r->dp[i] = t; + } + for (; i < a->used; i++) { + r->dp[i] = a->dp[i] - c; + c &= (r->dp[i] == (sp_int_digit)-1); + } + r->used = i; + sp_clamp(r); + + return MP_OKAY; +} + +/* Shift a right by n bits into r: r = a >> n + * + * a SP integer operand. + * n Number of bits to shift. + * r SP integer result. + */ +void sp_rshb(sp_int* a, int n, sp_int* r) +{ + int i; + int j; + + for (i = n / SP_WORD_SIZE, j = 0; i < a->used-1; i++, j++) + r->dp[i] = (a->dp[j] >> n) | (a->dp[j+1] << (SP_WORD_SIZE - n)); + r->dp[i] = a->dp[j] >> n; + r->used = j + 1; + sp_clamp(r); +} + +/* Multiply a by digit n and put result into r shifting up o digits. + * r = (a * n) << (o * SP_WORD_SIZE) + * + * a SP integer to be multiplied. + * n Number to multiply by. + * r SP integer result. + * o Number of digits to move result up by. + */ +static void _sp_mul_d(sp_int* a, sp_int_digit n, sp_int* r, int o) +{ + int i; + sp_int_word t = 0; + + for (i = 0; i < o; i++) + r->dp[i] = 0; + + for (i = 0; i < a->used; i++) { + t += (sp_int_word)n * a->dp[i]; + r->dp[i + o] = (sp_int_digit)t; + t >>= SP_WORD_SIZE; + } + + r->dp[i+o] = (sp_int_digit)t; + r->used = i+o+1; + sp_clamp(r); +} + +/* Divide a by d and return the quotient in r and the remainder in rem. + * r = a / d; rem = a % d + * + * a SP integer to be divided. + * d SP integer to divide by. + * r SP integer of quotient. + * rem SP integer of remainder. + * returns MP_VAL when d is 0, MP_MEM when dynamic memory allocation fails and + * MP_OKAY otherwise. + */ +static int sp_div(sp_int* a, sp_int* d, sp_int* r, sp_int* rem) +{ + int err = MP_OKAY; + int ret; + int done = 0; + int i; + int s; +#ifndef WOLFSSL_SP_DIV_32 + sp_int_word w = 0; +#endif + sp_int_digit dt; + sp_int_digit t; +#ifdef WOLFSSL_SMALL_STACK + sp_int* sa = NULL; + sp_int* sd; + sp_int* tr; + sp_int* trial; +#else + sp_int sa[1]; + sp_int sd[1]; + sp_int tr[1]; + sp_int trial[1]; +#endif + + if (sp_iszero(d)) + err = MP_VAL; + + ret = sp_cmp(a, d); + if (ret == MP_LT) { + if (rem != NULL) { + sp_copy(a, rem); + } + if (r != NULL) { + sp_set(r, 0); + } + done = 1; + } + else if (ret == MP_EQ) { + if (rem != NULL) { + sp_set(rem, 0); + } + if (r != NULL) { + sp_set(r, 1); + } + done = 1; + } + else if (sp_count_bits(a) == sp_count_bits(d)) { + /* a is greater than d but same bit length */ + if (rem != NULL) { + sp_sub(a, d, rem); + } + if (r != NULL) { + sp_set(r, 1); + } + done = 1; + } + +#ifdef WOLFSSL_SMALL_STACK + if (!done && err == MP_OKAY) { + sa = (sp_int*)XMALLOC(sizeof(sp_int) * 4, NULL, DYNAMIC_TYPE_BIGINT); + if (sa == NULL) { + err = MP_MEM; + } + } +#endif + + if (!done && err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + sd = &sa[1]; + tr = &sa[2]; + trial = &sa[3]; +#endif + + sp_init(sa); + sp_init(sd); + sp_init(tr); + sp_init(trial); + + s = sp_count_bits(d); + s = SP_WORD_SIZE - (s % SP_WORD_SIZE); + sp_copy(a, sa); + if (s != SP_WORD_SIZE) { + sp_lshb(sa, s); + sp_copy(d, sd); + sp_lshb(sd, s); + d = sd; + } + + tr->used = sa->used - d->used + 1; + sp_clear(tr); + tr->used = sa->used - d->used + 1; + dt = d->dp[d->used-1]; +#ifndef WOLFSSL_SP_DIV_32 + for (i = sa->used - 1; i >= d->used; ) { + if (sa->dp[i] > dt) { + t = (sp_int_digit)-1; + } + else { + w = ((sp_int_word)sa->dp[i] << SP_WORD_SIZE) | sa->dp[i-1]; + w /= dt; + if (w > (sp_int_digit)-1) { + t = (sp_int_digit)-1; + } + else { + t = (sp_int_digit)w; + } + } + + if (t > 0) { + _sp_mul_d(d, t, trial, i - d->used); + while (sp_cmp(trial, sa) == MP_GT) { + t--; + _sp_mul_d(d, t, trial, i - d->used); + } + sp_sub(sa, trial, sa); + tr->dp[i - d->used] += t; + if (tr->dp[i - d->used] < t) + tr->dp[i + 1 - d->used]++; + } + i = sa->used - 1; + } +#else + { + sp_int_digit div = (dt >> (SP_WORD_SIZE / 2)) + 1; + for (i = sa->used - 1; i >= d->used; ) { + t = sa->dp[i] / div; + if ((t > 0) && (t << (SP_WORD_SIZE / 2) == 0)) + t = (sp_int_digit)-1; + t <<= SP_WORD_SIZE / 2; + if (t == 0) { + t = sa->dp[i] << (SP_WORD_SIZE / 2); + t += sa->dp[i-1] >> (SP_WORD_SIZE / 2); + t /= div; + } + + if (t > 0) { + _sp_mul_d(d, t, trial, i - d->used); + while (sp_cmp(trial, sa) == MP_GT) { + t--; + _sp_mul_d(d, t, trial, i - d->used); + } + sp_sub(sa, trial, sa); + tr->dp[i - d->used] += t; + if (tr->dp[i - d->used] < t) + tr->dp[i + 1 - d->used]++; + } + i = sa->used - 1; + } + + while (sp_cmp(sa, d) != MP_LT) { + sp_sub(sa, d, sa); + sp_add_d(tr, 1, tr); + } + } +#endif + + sp_clamp(tr); + + if (rem != NULL) { + if (s != SP_WORD_SIZE) + sp_rshb(sa, s, sa); + sp_copy(sa, rem); + } + if (r != NULL) + sp_copy(tr, r); + } + +#ifdef WOLFSSL_SMALL_STACK + if (sa != NULL) + XFREE(sa, NULL, DYNAMIC_TYPE_BIGINT); +#endif + + return err; +} + + +#ifndef FREESCALE_LTC_TFM +/* Calculate the remainder of dividing a by m: r = a mod m. + * + * a SP integer. + * m SP integer. + * r SP integer. + * returns MP_VAL when m is 0 and MP_OKAY otherwise. + */ +int sp_mod(sp_int* a, sp_int* m, sp_int* r) +{ + return sp_div(a, m, NULL, r); +} +#endif +#endif + +/* Clear all data in the big number and sets value to zero. + * + * a SP integer. + */ +void sp_zero(sp_int* a) +{ + XMEMSET(a->dp, 0, a->size * sizeof(*a->dp)); + a->used = 0; +} + +/* Add a one digit number to the big number. + * + * a SP integer. + * d Digit to add. + * r SP integer - result. + * returns MP_OKAY always. + */ +int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r) +{ + int i = 0; + + r->used = a->used; + if (a->used == 0) { + r->used = 1; + } + r->dp[0] = a->dp[0] + d; + if (r->dp[i] < a->dp[i]) { + for (; i < a->used; i++) { + r->dp[i] = a->dp[i] + 1; + if (r->dp[i] != 0) + break; + } + + if (i == a->used) { + r->used++; + r->dp[i] = 1; + } + } + for (; i < a->used; i++) + r->dp[i] = a->dp[i]; + + return MP_OKAY; +} + +#if !defined(NO_DH) || defined(HAVE_ECC) || defined(WC_RSA_BLINDING) || \ + !defined(WOLFSSL_RSA_VERIFY_ONLY) +/* Left shift the big number by a number of digits. + * WIll chop off digits overflowing maximum size. + * + * a SP integer. + * s Number of digits to shift. + * returns MP_OKAY always. + */ +int sp_lshd(sp_int* a, int s) +{ + if (a->used + s > a->size) + a->used = a->size - s; + + XMEMMOVE(a->dp + s, a->dp, a->used * sizeof(sp_int_digit)); + a->used += s; + XMEMSET(a->dp, 0, s * sizeof(sp_int_digit)); + sp_clamp(a); + + return MP_OKAY; +} +#endif + +#if !defined(NO_PWDBASED) || defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) +/* Add two large numbers into result: r = a + b + * + * a SP integer. + * b SP integer. + * r SP integer. + * returns MP_OKAY always. + */ +int sp_add(sp_int* a, sp_int* b, sp_int* r) +{ + int i; + sp_int_digit c = 0; + sp_int_digit t; + + for (i = 0; i < a->used && i < b->used; i++) { + t = a->dp[i] + b->dp[i] + c; + if (c == 0) + c = t < a->dp[i]; + else + c = t <= a->dp[i]; + r->dp[i] = t; + } + for (; i < a->used; i++) { + r->dp[i] = a->dp[i] + c; + c = (a->dp[i] != 0) && (r->dp[i] == 0); + } + for (; i < b->used; i++) { + r->dp[i] = b->dp[i] + c; + c = (b->dp[i] != 0) && (r->dp[i] == 0); + } + r->dp[i] = c; + r->used = (int)(i + c); + + return MP_OKAY; +} +#endif /* !NO_PWDBASED || WOLFSSL_KEY_GEN || !NO_DH */ + +#ifndef NO_RSA +/* Set a number into the big number. + * + * a SP integer. + * b Value to set. + * returns MP_OKAY always. + */ +int sp_set_int(sp_int* a, unsigned long b) +{ + if (b == 0) { + a->used = 0; + a->dp[0] = 0; + } + else { + a->used = 1; + a->dp[0] = (sp_int_digit)b; + } + + return MP_OKAY; +} +#endif /* !NO_RSA */ + +#ifdef WC_MP_TO_RADIX +/* Hex string characters. */ +static const char sp_hex_char[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +/* Put the hex string version, big-endian, of a in str. + * + * a SP integer. + * str Hex string is stored here. + * returns MP_OKAY always. + */ +int sp_tohex(sp_int* a, char* str) +{ + int i, j; + + /* quick out if its zero */ + if (sp_iszero(a) == MP_YES) { + *str++ = '0'; + *str = '\0'; + } + else { + i = a->used - 1; + for (j = SP_WORD_SIZE - 4; j >= 0; j -= 4) { + if (((a->dp[i] >> j) & 0xf) != 0) + break; + } + for (; j >= 0; j -= 4) + *(str++) = sp_hex_char[(a->dp[i] >> j) & 0xf]; + for (--i; i >= 0; i--) { + for (j = SP_WORD_SIZE - 4; j >= 0; j -= 4) + *(str++) = sp_hex_char[(a->dp[i] >> j) & 0xf]; + } + *str = '\0'; + } + + return MP_OKAY; +} +#endif /* WC_MP_TO_RADIX */ + +#if defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) && !defined(WC_NO_RNG) +/* Set a bit of a: a |= 1 << i + * The field 'used' is updated in a. + * + * a SP integer to modify. + * i Index of bit to set. + * returns MP_OKAY always. + */ +int sp_set_bit(sp_int* a, int i) +{ + int ret = MP_OKAY; + + if ((a == NULL) || (i / SP_WORD_SIZE >= SP_INT_DIGITS)) { + ret = BAD_FUNC_ARG; + } + else { + a->dp[i/SP_WORD_SIZE] |= (sp_int_digit)1 << (i % SP_WORD_SIZE); + if (a->used <= i / SP_WORD_SIZE) + a->used = (i / SP_WORD_SIZE) + 1; + } + return ret; +} + +/* Exponentiate 2 to the power of e: a = 2^e + * This is done by setting the 'e'th bit. + * + * a SP integer. + * e Exponent. + * returns MP_OKAY always. + */ +int sp_2expt(sp_int* a, int e) +{ + sp_zero(a); + return sp_set_bit(a, e); +} + +/* Generate a random prime for RSA only. + * + * r SP integer + * len Number of bytes to prime. + * rng Random number generator. + * heap Unused + * returns MP_OKAY on success and MP_VAL when length is not supported or random + * number genrator fails. + */ +int sp_rand_prime(sp_int* r, int len, WC_RNG* rng, void* heap) +{ + static const int USE_BBS = 1; + int err = 0, type; + int isPrime = MP_NO; + + (void)heap; + + /* get type */ + if (len < 0) { + type = USE_BBS; + len = -len; + } + else { + type = 0; + } + +#if defined(WOLFSSL_HAVE_SP_DH) && defined(WOLFSSL_KEY_GEN) + if (len == 32) { + } + else +#endif + /* Generate RSA primes that are half the modulus length. */ +#ifndef WOLFSSL_SP_NO_3072 + if (len != 128 && len != 192) +#else + if (len != 128) +#endif + { + err = MP_VAL; + } + + r->used = len / (SP_WORD_SIZE / 8); + + /* Assume the candidate is probably prime and then test until + * it is proven composite. */ + while (err == 0 && isPrime == MP_NO) { +#ifdef SHOW_GEN + printf("."); + fflush(stdout); +#endif + /* generate value */ + err = wc_RNG_GenerateBlock(rng, (byte*)r->dp, len); + if (err != 0) { + err = MP_VAL; + break; + } + + /* munge bits */ + ((byte*)r->dp)[len-1] |= 0x80 | 0x40; + r->dp[0] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); + + /* test */ + /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance + * of a 1024-bit candidate being a false positive, when it is our + * prime candidate. (Note 4.49 of Handbook of Applied Cryptography.) + * Using 8 because we've always used 8 */ + sp_prime_is_prime_ex(r, 8, &isPrime, rng); + } + + return err; +} + +/* Multiply a by b and store in r: r = a * b + * + * a SP integer to multiply. + * b SP integer to multiply. + * r SP integer result. + * returns MP_OKAY always. + */ +int sp_mul(sp_int* a, sp_int* b, sp_int* r) +{ + int err = MP_OKAY; + int i; +#ifdef WOLFSSL_SMALL_STACK + sp_int* t = NULL; + sp_int* tr; +#else + sp_int t[1]; + sp_int tr[1]; +#endif + + if (a->used + b->used > SP_INT_DIGITS) + err = MP_VAL; + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + t = (sp_int*)XMALLOC(sizeof(sp_int) * 2, NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) + err = MP_MEM; + else + tr = &t[1]; + } +#endif + + if (err == MP_OKAY) { + sp_init(t); + sp_init(tr); + + for (i = 0; i < b->used; i++) { + _sp_mul_d(a, b->dp[i], t, i); + sp_add(tr, t, tr); + } + sp_copy(tr, r); + } + +#ifdef WOLFSSL_SMALL_STACK + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + + return err; +} + +/* Square a mod m and store in r: r = (a * a) mod m + * + * a SP integer to square. + * m SP integer modulus. + * r SP integer result. + * returns MP_VAL when m is 0, MP_MEM when dynamic memory allocation fails, + * BAD_FUNC_ARG when a is to big and MP_OKAY otherwise. + */ +static int sp_sqrmod(sp_int* a, sp_int* m, sp_int* r) +{ + int err = MP_OKAY; + + if (a->used * 2 > SP_INT_DIGITS) + err = MP_VAL; + + if (err == MP_OKAY) + err = sp_mul(a, a, r); + if (err == MP_OKAY) + err = sp_mod(r, m, r); + + return err; +} + +#if defined(WOLFSSL_HAVE_SP_DH) || defined(WOLFSSL_KEY_GEN) +/* Multiply a by b mod m and store in r: r = (a * b) mod m + * + * a SP integer to multiply. + * b SP integer to multiply. + * m SP integer modulus. + * r SP integer result. + * returns MP_VAL when m is 0, MP_MEM when dynamic memory allocation fails and + * MP_OKAY otherwise. + */ +int sp_mulmod(sp_int* a, sp_int* b, sp_int* m, sp_int* r) +{ + int err = MP_OKAY; +#ifdef WOLFSSL_SMALL_STACK + sp_int* t = NULL; +#else + sp_int t[1]; +#endif + + if (a->used + b->used > SP_INT_DIGITS) + err = MP_VAL; + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + t = (sp_int*)XMALLOC(sizeof(sp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) { + err = MP_MEM; + } + } +#endif + if (err == MP_OKAY) { + err = sp_mul(a, b, t); + } + if (err == MP_OKAY) { + err = sp_mod(t, m, r); + } + +#ifdef WOLFSSL_SMALL_STACK + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return err; +} +#endif + +/* Calculate a modulo the digit d into r: r = a mod d + * + * a SP integer to square. + * d SP integer digit, modulus. + * r SP integer digit, result. + * returns MP_VAL when d is 0 and MP_OKAY otherwise. + */ +static int sp_mod_d(sp_int* a, const sp_int_digit d, sp_int_digit* r) +{ + int err = MP_OKAY; + int i; + sp_int_word w = 0; + sp_int_digit t; + + if (d == 0) + err = MP_VAL; + + if (err == MP_OKAY) { + for (i = a->used - 1; i >= 0; i--) { + w = (w << SP_WORD_SIZE) | a->dp[i]; + t = (sp_int_digit)(w / d); + w -= (sp_int_word)t * d; + } + + *r = (sp_int_digit)w; + } + + return err; +} + +/* Calculates the Greatest Common Denominator (GCD) of a and b into r. + * + * a SP integer operand. + * b SP integer operand. + * r SP integer result. + * returns MP_MEM when dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_gcd(sp_int* a, sp_int* b, sp_int* r) +{ + int err = MP_OKAY; +#ifdef WOLFSSL_SMALL_STACK + sp_int* u = NULL; + sp_int* v; + sp_int* t; +#else + sp_int u[1], v[1], t[1]; +#endif + + if (sp_iszero(a)) + sp_copy(b, r); + else if (sp_iszero(b)) + sp_copy(a, r); + else { +#ifdef WOLFSSL_SMALL_STACK + u = (sp_int*)XMALLOC(sizeof(sp_int) * 3, NULL, DYNAMIC_TYPE_BIGINT); + if (u == NULL) + err = MP_MEM; + else { + v = &u[1]; + t = &u[2]; + } +#endif + + if (err == MP_OKAY) { + sp_init(u); + sp_init(v); + sp_init(t); + + if (sp_cmp(a, b) != MP_LT) { + sp_copy(b, u); + /* First iteration - u = a, v = b */ + if (b->used == 1) { + err = sp_mod_d(a, b->dp[0], &v->dp[0]); + if (err == MP_OKAY) + v->used = (v->dp[0] != 0); + } + else + err = sp_mod(a, b, v); + } + else { + sp_copy(a, u); + /* First iteration - u = b, v = a */ + if (a->used == 1) { + err = sp_mod_d(b, a->dp[0], &v->dp[0]); + if (err == MP_OKAY) + v->used = (v->dp[0] != 0); + } + else + err = sp_mod(b, a, v); + } + } + + if (err == MP_OKAY) { + while (!sp_iszero(v)) { + if (v->used == 1) { + sp_mod_d(u, v->dp[0], &t->dp[0]); + t->used = (t->dp[0] != 0); + } + else + sp_mod(u, v, t); + sp_copy(v, u); + sp_copy(t, v); + } + sp_copy(u, r); + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (u != NULL) + XFREE(u, NULL, DYNAMIC_TYPE_BIGINT); +#endif + + return err; +} + +/* Divides a by 2 and stores in r: r = a >> 1 + * + * a SP integer to divide. + * r SP integer result. + * returns MP_OKAY always. + */ +static int sp_div_2(sp_int* a, sp_int* r) +{ + int i; + + for (i = 0; i < a->used-1; i++) + r->dp[i] = (a->dp[i] >> 1) | (a->dp[i+1] << (SP_WORD_SIZE - 1)); + r->dp[i] = a->dp[i] >> 1; + r->used = i + 1; + sp_clamp(r); + + return MP_OKAY; +} + + +/* Calculates the multiplicative inverse in the field. + * + * a SP integer to invert. + * m SP integer that is the modulus of the field. + * r SP integer result. + * returns MP_VAL when a or m is 0, MP_MEM when dynamic memory allocation fails + * and MP_OKAY otherwise. + */ +int sp_invmod(sp_int* a, sp_int* m, sp_int* r) +{ + int err = MP_OKAY; +#ifdef WOLFSSL_SMALL_STACK + sp_int* u = NULL; + sp_int* v; + sp_int* b; + sp_int* c; +#else + sp_int u[1], v[1], b[1], c[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + u = (sp_int*)XMALLOC(sizeof(sp_int) * 4, NULL, DYNAMIC_TYPE_BIGINT); + if (u == NULL) { + err = MP_MEM; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + v = &u[1]; + b = &u[2]; + c = &u[3]; +#endif + sp_init(v); + + if (sp_cmp(a, m) != MP_LT) { + err = sp_mod(a, m, v); + a = v; + } + } + + /* 0 != n*m + 1 (+ve m), r*a mod 0 is always 0 (never 1) */ + if ((err == MP_OKAY) && (sp_iszero(a) || sp_iszero(m))) { + err = MP_VAL; + } + /* r*2*x != n*2*y + 1 */ + if ((err == MP_OKAY) && sp_iseven(a) && sp_iseven(m)) { + err = MP_VAL; + } + + /* 1*1 = 0*m + 1 */ + if ((err == MP_OKAY) && sp_isone(a)) { + sp_set(r, 1); + } + else if (err != MP_OKAY) { + } + else if (sp_iseven(m)) { + /* a^-1 mod m = m + (1 - m*(m^-1 % a)) / a + * = m - (m*(m^-1 % a) - 1) / a + */ + err = sp_invmod(m, a, r); + if (err == MP_OKAY) { + err = sp_mul(r, m, r); + } + if (err == MP_OKAY) { + sp_sub_d(r, 1, r); + sp_div(r, a, r, NULL); + sp_sub(m, r, r); + } + } + else { + if (err == MP_OKAY) { + sp_init(u); + sp_init(b); + sp_init(c); + + sp_copy(m, u); + sp_copy(a, v); + sp_zero(b); + sp_set(c, 1); + + while (!sp_isone(v) && !sp_iszero(u)) { + if (sp_iseven(u)) { + sp_div_2(u, u); + if (sp_isodd(b)) { + sp_add(b, m, b); + } + sp_div_2(b, b); + } + else if (sp_iseven(v)) { + sp_div_2(v, v); + if (sp_isodd(c)) { + sp_add(c, m, c); + } + sp_div_2(c, c); + } + else if (sp_cmp(u, v) != MP_LT) { + sp_sub(u, v, u); + if (sp_cmp(b, c) == MP_LT) { + sp_add(b, m, b); + } + sp_sub(b, c, b); + } + else { + sp_sub(v, u, v); + if (sp_cmp(c, b) == MP_LT) { + sp_add(c, m, c); + } + sp_sub(c, b, c); + } + } + if (sp_iszero(u)) { + err = MP_VAL; + } + else { + sp_copy(c, r); + } + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (u != NULL) { + XFREE(u, NULL, DYNAMIC_TYPE_BIGINT); + } +#endif + + return err; +} + +/* Calculates the Lowest Common Multiple (LCM) of a and b and stores in r. + * + * a SP integer operand. + * b SP integer operand. + * r SP integer result. + * returns MP_MEM when dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_lcm(sp_int* a, sp_int* b, sp_int* r) +{ + int err = MP_OKAY; +#ifndef WOLFSSL_SMALL_STACK + sp_int t[2]; +#else + sp_int *t = NULL; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (sp_int*)XMALLOC(sizeof(sp_int) * 2, NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) { + err = MP_MEM; + } +#endif + + if (err == MP_OKAY) { + sp_init(&t[0]); + sp_init(&t[1]); + err = sp_gcd(a, b, &t[0]); + if (err == MP_OKAY) { + if (sp_cmp(a, b) == MP_GT) { + err = sp_div(a, &t[0], &t[1], NULL); + if (err == MP_OKAY) + err = sp_mul(b, &t[1], r); + } + else { + err = sp_div(b, &t[0], &t[1], NULL); + if (err == MP_OKAY) + err = sp_mul(a, &t[1], r); + } + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return err; +} + +/* Exponentiates b to the power of e modulo m into r: r = b ^ e mod m + * + * b SP integer base. + * e SP integer exponent. + * m SP integer modulus. + * r SP integer result. + * returns MP_VAL when m is not 1024, 2048, 1536 or 3072 bits and otherwise + * MP_OKAY. + */ +int sp_exptmod(sp_int* b, sp_int* e, sp_int* m, sp_int* r) +{ + int err = MP_OKAY; + int done = 0; + int mBits = sp_count_bits(m); + int bBits = sp_count_bits(b); + int eBits = sp_count_bits(e); + + if (sp_iszero(m)) { + err = MP_VAL; + } + else if (sp_isone(m)) { + sp_set(r, 0); + done = 1; + } + else if (sp_iszero(e)) { + sp_set(r, 1); + done = 1; + } + else if (sp_iszero(b)) { + sp_set(r, 0); + done = 1; + } + else if (m->used * 2 > SP_INT_DIGITS) { + err = BAD_FUNC_ARG; + } + + if (!done && (err == MP_OKAY)) { +#ifndef WOLFSSL_SP_NO_2048 + if ((mBits == 1024) && sp_isodd(m) && (bBits <= 1024) && + (eBits <= 1024)) { + err = sp_ModExp_1024(b, e, m, r); + done = 1; + } + else if ((mBits == 2048) && sp_isodd(m) && (bBits <= 2048) && + (eBits <= 2048)) { + err = sp_ModExp_2048(b, e, m, r); + done = 1; + } + else +#endif +#ifndef WOLFSSL_SP_NO_3072 + if ((mBits == 1536) && sp_isodd(m) && (bBits <= 1536) && + (eBits <= 1536)) { + err = sp_ModExp_1536(b, e, m, r); + done = 1; + } + else if ((mBits == 3072) && sp_isodd(m) && (bBits <= 3072) && + (eBits <= 3072)) { + err = sp_ModExp_3072(b, e, m, r); + done = 1; + } + else +#endif +#ifdef WOLFSSL_SP_NO_4096 + if ((mBits == 4096) && sp_isodd(m) && (bBits <= 4096) && + (eBits <= 4096)) { + err = sp_ModExp_4096(b, e, m, r); + done = 1; + } + else +#endif + { + } + } +#if defined(WOLFSSL_HAVE_SP_DH) && defined(WOLFSSL_KEY_GEN) + if (!done && (err == MP_OKAY)) { + int i; + + #ifdef WOLFSSL_SMALL_STACK + sp_int* t = NULL; + #else + sp_int t[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + if (!done && (err == MP_OKAY)) { + t = (sp_int*)XMALLOC(sizeof(sp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) { + err = MP_MEM; + } + } + #endif + if (!done && (err == MP_OKAY)) { + sp_init(t); + + if (sp_cmp(b, m) != MP_LT) { + err = sp_mod(b, m, t); + if (err == MP_OKAY && sp_iszero(t)) { + sp_set(r, 0); + done = 1; + } + } + else { + sp_copy(b, t); + } + + if (!done && (err == MP_OKAY)) { + for (i = eBits-2; err == MP_OKAY && i >= 0; i--) { + err = sp_sqrmod(t, m, t); + if (err == MP_OKAY && (e->dp[i / SP_WORD_SIZE] >> + (i % SP_WORD_SIZE)) & 1) { + err = sp_mulmod(t, b, m, t); + } + } + } + } + if (!done && (err == MP_OKAY)) { + sp_copy(t, r); + } + + #ifdef WOLFSSL_SMALL_STACK + if (t != NULL) { + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); + } + #endif + } +#else + if (!done && (err == MP_OKAY)) { + err = MP_VAL; + } +#endif + + (void)mBits; + (void)bBits; + (void)eBits; + + return err; +} + + +/* Number of entries in array of number of least significant zero bits. */ +#define SP_LNZ_CNT 16 +/* Number of bits the array checks. */ +#define SP_LNZ_BITS 4 +/* Mask to apply to check with array. */ +#define SP_LNZ_MASK 0xf +/* Number of least significant zero bits in first SP_LNZ_CNT numbers. */ +static const int lnz[SP_LNZ_CNT] = { + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +/* Count the number of least significant zero bits. + * + * a Number to check + * returns the count of least significant zero bits. + */ +static int sp_cnt_lsb(sp_int* a) +{ + int i, j; + int cnt = 0; + int bc = 0; + + if (!sp_iszero(a)) { + for (i = 0; i < a->used && a->dp[i] == 0; i++, cnt += SP_WORD_SIZE) { + } + + for (j = 0; j < SP_WORD_SIZE; j += SP_LNZ_BITS) { + bc = lnz[(a->dp[i] >> j) & SP_LNZ_MASK]; + if (bc != 4) { + bc += cnt + j; + break; + } + } + } + + return bc; +} + +/* Miller-Rabin test of "a" to the base of "b" as described in + * HAC pp. 139 Algorithm 4.24 + * + * Sets result to 0 if definitely composite or 1 if probably prime. + * Randomly the chance of error is no more than 1/4 and often + * very much lower. + * + * a SP integer to check. + * b SP integer small prime. + * result Whether a is likely prime: MP_YES or MP_NO. + * n1 SP integer operand. + * y SP integer operand. + * r SP integer operand. + * returns MP_VAL when a is not 1024, 2048, 1536 or 3072 and MP_OKAY otherwise. + */ +static int sp_prime_miller_rabin_ex(sp_int * a, sp_int * b, int *result, + sp_int *n1, sp_int *y, sp_int *r) +{ + int s, j; + int err = MP_OKAY; + + /* default */ + *result = MP_NO; + + /* ensure b > 1 */ + if (sp_cmp_d(b, 1) == MP_GT) { + /* get n1 = a - 1 */ + sp_copy(a, n1); + sp_sub_d(n1, 1, n1); + /* set 2**s * r = n1 */ + sp_copy(n1, r); + + /* count the number of least significant bits + * which are zero + */ + s = sp_cnt_lsb(r); + + /* now divide n - 1 by 2**s */ + sp_rshb(r, s, r); + + /* compute y = b**r mod a */ + sp_zero(y); + + err = sp_exptmod(b, r, a, y); + + if (err == MP_OKAY) { + /* probably prime until shown otherwise */ + *result = MP_YES; + + /* if y != 1 and y != n1 do */ + if (sp_cmp_d(y, 1) != MP_EQ && sp_cmp(y, n1) != MP_EQ) { + j = 1; + /* while j <= s-1 and y != n1 */ + while ((j <= (s - 1)) && sp_cmp(y, n1) != MP_EQ) { + sp_sqrmod(y, a, y); + + /* if y == 1 then composite */ + if (sp_cmp_d(y, 1) == MP_EQ) { + *result = MP_NO; + break; + } + ++j; + } + + /* if y != n1 then composite */ + if (*result == MP_YES && sp_cmp(y, n1) != MP_EQ) + *result = MP_NO; + } + } + } + + return err; +} + +/* Miller-Rabin test of "a" to the base of "b" as described in + * HAC pp. 139 Algorithm 4.24 + * + * Sets result to 0 if definitely composite or 1 if probably prime. + * Randomly the chance of error is no more than 1/4 and often + * very much lower. + * + * a SP integer to check. + * b SP integer small prime. + * result Whether a is likely prime: MP_YES or MP_NO. + * returns MP_MEM when dynamic memory allocation fails, MP_VAL when a is not + * 1024, 2048, 1536 or 3072 and MP_OKAY otherwise. + */ +static int sp_prime_miller_rabin(sp_int * a, sp_int * b, int *result) +{ + int err = MP_OKAY; +#ifndef WOLFSSL_SMALL_STACK + sp_int n1[1], y[1], r[1]; +#else + sp_int *n1 = NULL, *y, *r; +#endif + +#ifdef WOLFSSL_SMALL_STACK + n1 = (sp_int*)XMALLOC(sizeof(sp_int) * 3, NULL, DYNAMIC_TYPE_BIGINT); + if (n1 == NULL) + err = MP_MEM; + else { + y = &n1[1]; + r = &n1[2]; + } +#endif + + if (err == MP_OKAY) { + sp_init(n1); + sp_init(y); + sp_init(r); + + err = sp_prime_miller_rabin_ex(a, b, result, n1, y, r); + + sp_clear(n1); + sp_clear(y); + sp_clear(r); + } + +#ifdef WOLFSSL_SMALL_STACK + if (n1 != NULL) + XFREE(n1, NULL, DYNAMIC_TYPE_BIGINT); +#endif + + return err; +} + +/* Number of pre-computed primes. First n primes. */ +#define SP_PRIME_SIZE 256 + +/* a few primes */ +static const sp_int_digit primes[SP_PRIME_SIZE] = { + 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, + 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, + 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, + 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083, + 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, + 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, + 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, + 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, + + 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, + 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, + 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, + 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, + 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, + 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, + 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, + 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, + + 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, + 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, + 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, + 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, + 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, + 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, + 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, + 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, + + 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, + 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, + 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, + 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, + 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, + 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, + 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, + 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 +}; + + +/* Check whether a is prime. + * Checks against a number of small primes and does t iterations of + * Miller-Rabin. + * + * a SP integer to check. + * t Number of iterations of Muller-Rabin to perform. + * result MP_YES when prime. + * MP_NO when not prime. + * returns MP_VAL when t is out of range, MP_MEM when dynamic memory allocation + * fails and otherwise MP_OKAY. + */ +int sp_prime_is_prime(sp_int *a, int t, int* result) +{ + int err = MP_OKAY; + int i; + int haveRes = 0; +#ifndef WOLFSSL_SMALL_STACK + sp_int b[1]; +#else + sp_int *b = NULL; +#endif + sp_int_digit d; + + if (t <= 0 || t > SP_PRIME_SIZE) { + *result = MP_NO; + err = MP_VAL; + } + + if (sp_isone(a)) { + *result = MP_NO; + return MP_OKAY; + } + + if (err == MP_OKAY && a->used == 1) { + /* check against primes table */ + for (i = 0; i < SP_PRIME_SIZE; i++) { + if (sp_cmp_d(a, primes[i]) == MP_EQ) { + *result = MP_YES; + haveRes = 1; + break; + } + } + } + + if (err == MP_OKAY && !haveRes) { + /* do trial division */ + for (i = 0; i < SP_PRIME_SIZE; i++) { + err = sp_mod_d(a, primes[i], &d); + if (err != MP_OKAY || d == 0) { + *result = MP_NO; + haveRes = 1; + break; + } + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY && !haveRes) { + b = (sp_int*)XMALLOC(sizeof(sp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (b == NULL) + err = MP_MEM; + } +#endif + + if (err == MP_OKAY && !haveRes) { + /* now do 't' miller rabins */ + sp_init(b); + for (i = 0; i < t; i++) { + sp_set(b, primes[i]); + err = sp_prime_miller_rabin(a, b, result); + if (err != MP_OKAY || *result == MP_NO) + break; + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (b != NULL) + XFREE(b, NULL, DYNAMIC_TYPE_BIGINT); +#endif + + return err; +} + +/* Check whether a is prime. + * Checks against a number of small primes and does t iterations of + * Miller-Rabin. + * + * a SP integer to check. + * t Number of iterations of Muller-Rabin to perform. + * result MP_YES when prime. + * MP_NO when not prime. + * rng Random number generator. + * returns MP_VAL when t is out of range, MP_MEM when dynamic memory allocation + * fails and otherwise MP_OKAY. + */ +int sp_prime_is_prime_ex(sp_int* a, int t, int* result, WC_RNG* rng) +{ + int err = MP_OKAY; + int ret = MP_YES; + int haveRes = 0; + int i; +#ifndef WC_NO_RNG + #ifndef WOLFSSL_SMALL_STACK + sp_int b[1], c[1], n1[1], y[1], r[1]; + #else + sp_int *b = NULL, *c = NULL, *n1 = NULL, *y = NULL, *r = NULL; + #endif + word32 baseSz; +#endif + + if (a == NULL || result == NULL || rng == NULL) + err = MP_VAL; + + if (sp_isone(a)) { + *result = MP_NO; + return MP_OKAY; + } + + if (err == MP_OKAY && a->used == 1) { + /* check against primes table */ + for (i = 0; i < SP_PRIME_SIZE; i++) { + if (sp_cmp_d(a, primes[i]) == MP_EQ) { + ret = MP_YES; + haveRes = 1; + break; + } + } + } + + if (err == MP_OKAY && !haveRes) { + sp_int_digit d; + + /* do trial division */ + for (i = 0; i < SP_PRIME_SIZE; i++) { + err = sp_mod_d(a, primes[i], &d); + if (err != MP_OKAY || d == 0) { + ret = MP_NO; + haveRes = 1; + break; + } + } + } + +#ifndef WC_NO_RNG + /* now do a miller rabin with up to t random numbers, this should + * give a (1/4)^t chance of a false prime. */ + #ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY && !haveRes) { + b = (sp_int*)XMALLOC(sizeof(sp_int) * 5, NULL, DYNAMIC_TYPE_BIGINT); + if (b == NULL) { + err = MP_MEM; + } + else { + c = &b[1]; n1 = &b[2]; y= &b[3]; r = &b[4]; + } + } + #endif + + if (err == MP_OKAY && !haveRes) { + sp_init(b); + sp_init(c); + sp_init(n1); + sp_init(y); + sp_init(r); + + err = sp_sub_d(a, 2, c); + } + + if (err == MP_OKAY && !haveRes) { + baseSz = (sp_count_bits(a) + 7) / 8; + + while (t > 0) { + err = wc_RNG_GenerateBlock(rng, (byte*)b->dp, baseSz); + if (err != MP_OKAY) + break; + b->used = a->used; + + if (sp_cmp_d(b, 2) != MP_GT || sp_cmp(b, c) != MP_LT) + continue; + + err = sp_prime_miller_rabin_ex(a, b, &ret, n1, y, r); + if (err != MP_OKAY || ret == MP_NO) + break; + + t--; + } + + sp_clear(n1); + sp_clear(y); + sp_clear(r); + sp_clear(b); + sp_clear(c); + } + + #ifdef WOLFSSL_SMALL_STACK + if (b != NULL) + XFREE(b, NULL, DYNAMIC_TYPE_BIGINT); + #endif +#else + (void)t; +#endif /* !WC_NO_RNG */ + + *result = ret; + return err; +} + +#ifndef NO_DH +int sp_exch(sp_int* a, sp_int* b) +{ + int err = MP_OKAY; +#ifndef WOLFSSL_SMALL_STACK + sp_int t[1]; +#else + sp_int *t = NULL; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (sp_int*)XMALLOC(sizeof(sp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) + err = MP_MEM; +#endif + + if (err == MP_OKAY) { + *t = *a; + *a = *b; + *b = *t; + } + +#ifdef WOLFSSL_SMALL_STACK + if (t != NULL) + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return MP_OKAY; +} +#endif +#endif + +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) +/* Multiply a by digit n and put result into r. r = a * n + * + * a SP integer to be multiplied. + * n Number to multiply by. + * r SP integer result. + * returns MP_OKAY always. + */ +int sp_mul_d(sp_int* a, sp_int_digit n, sp_int* r) +{ + _sp_mul_d(a, n, r, 0); + return MP_OKAY; +} +#endif + +/* Returns the run time settings. + * + * returns the settings value. + */ +word32 CheckRunTimeSettings(void) +{ + return CTC_SETTINGS; +} + +#endif /* WOLFSSL_SP_MATH */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_x86_64.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_x86_64.c new file mode 100644 index 000000000..3e49d2022 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_x86_64.c @@ -0,0 +1,29555 @@ +/* sp.c + * + * Copyright (C) 2006-2020 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 +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifdef WOLFSSL_SP_X86_64_ASM +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +extern void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n); +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +extern void sp_2048_to_bin(sp_digit* r, byte* a); +extern void sp_2048_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_2048_sqr_16(sp_digit* r, const sp_digit* a); +extern void sp_2048_mul_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_2048_sqr_avx2_16(sp_digit* r, const sp_digit* a); +extern sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b); +extern sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b); + +extern sp_digit sp_2048_dbl_16(sp_digit* r, const sp_digit* a); +extern void sp_2048_sqr_32(sp_digit* r, const sp_digit* a); + +#ifdef HAVE_INTEL_AVX2 +extern void sp_2048_mul_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit* b); +#endif /* HAVE_INTEL_AVX2 */ + +#ifdef HAVE_INTEL_AVX2 +extern void sp_2048_sqr_avx2_32(sp_digit* r, const sp_digit* a); +#endif /* HAVE_INTEL_AVX2 */ + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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; +} + +extern void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, sp_digit b); +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +extern sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b); +/* 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 single precision number. + */ +static void sp_2048_mont_norm_16(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 16); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_16(r, m); +} + +extern sp_digit sp_2048_cond_sub_16(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_2048_mont_reduce_16(sp_digit* a, const sp_digit* m, sp_digit mp); +/* 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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_16(r, a); + sp_2048_mont_reduce_16(r, m, mp); +} + +extern sp_digit sp_2048_cond_sub_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_2048_mul_d_16(sp_digit* r, const sp_digit* a, sp_digit b); +extern void sp_2048_mul_d_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit b); +/* 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 WC_INLINE sp_digit div_2048_word_16(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + 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_16(sp_digit* r, const 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 +} + +extern int64_t sp_2048_cmp_16(const sp_digit* a, const sp_digit* b); +/* 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 WC_INLINE int sp_2048_div_16(const sp_digit* a, const 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); + r1 = sp_2048_cmp_16(&t1[16], d) >= 0; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_cond_sub_avx2_16(&t1[16], &t1[16], d, (sp_digit)0 - r1); + else +#endif + sp_2048_cond_sub_16(&t1[16], &t1[16], d, (sp_digit)0 - r1); + 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; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_cond_sub_avx2_16(r, t1, d, (sp_digit)0 - r1); + else +#endif + sp_2048_cond_sub_16(r, t1, d, (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 WC_INLINE int sp_2048_mod_16(sp_digit* r, const sp_digit* a, const 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][32]; + sp_digit rt[32]; +#else + sp_digit* t[32]; + sp_digit* rt; + 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) * 33 * 32, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 32; + rt = td + 1024; +#endif + norm = t[0]; + + 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--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 5) == 0) { + c -= 5; + } + else { + c -= bits % 5; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 16); + for (; i>=0 || c>=5; ) { + if (c >= 5) { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + else if (c == 0) { + n = e[i--]; + y = (int)(n >> 59); + n <<= 5; + c = 59; + } + else { + y = (int)(n >> 59); + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + + sp_2048_sqr_16(rt, r); + sp_2048_mont_reduce_16(rt, m, mp); + sp_2048_sqr_16(r, rt); + sp_2048_mont_reduce_16(r, m, mp); + sp_2048_sqr_16(rt, r); + sp_2048_mont_reduce_16(rt, m, mp); + sp_2048_sqr_16(r, rt); + sp_2048_mont_reduce_16(r, m, mp); + sp_2048_sqr_16(rt, r); + sp_2048_mont_reduce_16(rt, m, mp); + + sp_2048_mul_16(r, rt, t[y]); + sp_2048_mont_reduce_16(r, 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; +} + +extern void sp_2048_mont_reduce_avx2_16(sp_digit* a, const sp_digit* m, sp_digit mp); +#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. + */ +static void sp_2048_mont_mul_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_2048_mul_avx2_16(r, a, b); + sp_2048_mont_reduce_avx2_16(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_avx2_16(r, a); + sp_2048_mont_reduce_avx2_16(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][32]; + sp_digit rt[32]; +#else + sp_digit* t[32]; + sp_digit* rt; + 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) * 33 * 32, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 32; + rt = td + 1024; +#endif + norm = t[0]; + + 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--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 5) == 0) { + c -= 5; + } + else { + c -= bits % 5; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 16); + for (; i>=0 || c>=5; ) { + if (c >= 5) { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + else if (c == 0) { + n = e[i--]; + y = (int)(n >> 59); + n <<= 5; + c = 59; + } + else { + y = (int)(n >> 59); + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + + sp_2048_sqr_avx2_16(rt, r); + sp_2048_mont_reduce_avx2_16(rt, m, mp); + sp_2048_sqr_avx2_16(r, rt); + sp_2048_mont_reduce_avx2_16(r, m, mp); + sp_2048_sqr_avx2_16(rt, r); + sp_2048_mont_reduce_avx2_16(rt, m, mp); + sp_2048_sqr_avx2_16(r, rt); + sp_2048_mont_reduce_avx2_16(r, m, mp); + sp_2048_sqr_avx2_16(rt, r); + sp_2048_mont_reduce_avx2_16(rt, m, mp); + + sp_2048_mul_avx2_16(r, rt, t[y]); + sp_2048_mont_reduce_avx2_16(r, 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_avx2_16(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* HAVE_INTEL_AVX2 */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* 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 single precision number. + */ +static void sp_2048_mont_norm_32(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 32); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_32(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +extern sp_digit sp_2048_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, sp_digit mp); +/* 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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_32(r, a); + sp_2048_mont_reduce_32(r, m, mp); +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +extern sp_digit sp_2048_cond_sub_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_2048_mul_d_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit b); +/* 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 WC_INLINE sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + 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, const 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 +} + +extern int64_t sp_2048_cmp_32(const sp_digit* a, const sp_digit* b); +/* 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 WC_INLINE int sp_2048_div_32(const sp_digit* a, const 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); + r1 = sp_2048_cmp_32(&t1[32], d) >= 0; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_cond_sub_avx2_32(&t1[32], &t1[32], d, (sp_digit)0 - r1); + else +#endif + sp_2048_cond_sub_32(&t1[32], &t1[32], d, (sp_digit)0 - r1); + 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; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_cond_sub_avx2_32(r, t1, d, (sp_digit)0 - r1); + else +#endif + sp_2048_cond_sub_32(r, t1, d, (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 WC_INLINE int sp_2048_mod_32(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_32(a, m, NULL, r); +} + +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +extern sp_digit sp_2048_sub_32(sp_digit* r, const sp_digit* a, const sp_digit* b); +/* 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 WC_INLINE int sp_2048_div_32_cond(const sp_digit* a, const 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--) { + if (t1[i + 32] != d[i]) + break; + } + if (t1[i + 32] >= d[i]) { + sp_2048_sub_in_place_32(&t1[32], d); + } + 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); + } + } + + for (i = 31; i > 0; i--) { + if (t1[i] != d[i]) + break; + } + if (t1[i] >= d[i]) { + sp_2048_sub_32(r, t1, d); + } + else { + XMEMCPY(r, t1, sizeof(*t1) * 32); + } + + 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 WC_INLINE int sp_2048_mod_32_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_2048_div_32_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][64]; + sp_digit rt[64]; +#else + sp_digit* t[32]; + sp_digit* rt; + 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) * 33 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 64; + rt = td + 2048; +#endif + norm = t[0]; + + 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--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 5) == 0) { + c -= 5; + } + else { + c -= bits % 5; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c >= 5) { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + else if (c == 0) { + n = e[i--]; + y = (int)(n >> 59); + n <<= 5; + c = 59; + } + else { + y = (int)(n >> 59); + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + + sp_2048_sqr_32(rt, r); + sp_2048_mont_reduce_32(rt, m, mp); + sp_2048_sqr_32(r, rt); + sp_2048_mont_reduce_32(r, m, mp); + sp_2048_sqr_32(rt, r); + sp_2048_mont_reduce_32(rt, m, mp); + sp_2048_sqr_32(r, rt); + sp_2048_mont_reduce_32(r, m, mp); + sp_2048_sqr_32(rt, r); + sp_2048_mont_reduce_32(rt, m, mp); + + sp_2048_mul_32(r, rt, t[y]); + sp_2048_mont_reduce_32(r, 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 /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +extern void sp_2048_mont_reduce_avx2_32(sp_digit* a, const sp_digit* m, sp_digit mp); +#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. + */ +static void sp_2048_mont_mul_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_2048_mul_avx2_32(r, a, b); + sp_2048_mont_reduce_avx2_32(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_avx2_32(r, a); + sp_2048_mont_reduce_avx2_32(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) +#ifdef HAVE_INTEL_AVX2 +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][64]; + sp_digit rt[64]; +#else + sp_digit* t[32]; + sp_digit* rt; + 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) * 33 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 64; + rt = td + 2048; +#endif + norm = t[0]; + + 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--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 5) == 0) { + c -= 5; + } + else { + c -= bits % 5; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c >= 5) { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + else if (c == 0) { + n = e[i--]; + y = (int)(n >> 59); + n <<= 5; + c = 59; + } + else { + y = (int)(n >> 59); + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + + sp_2048_sqr_avx2_32(rt, r); + sp_2048_mont_reduce_avx2_32(rt, m, mp); + sp_2048_sqr_avx2_32(r, rt); + sp_2048_mont_reduce_avx2_32(r, m, mp); + sp_2048_sqr_avx2_32(rt, r); + sp_2048_mont_reduce_avx2_32(rt, m, mp); + sp_2048_sqr_avx2_32(r, rt); + sp_2048_mont_reduce_avx2_32(r, m, mp); + sp_2048_sqr_avx2_32(rt, r); + sp_2048_mont_reduce_avx2_32(rt, m, mp); + + sp_2048_mul_avx2_32(r, rt, t[y]); + sp_2048_mont_reduce_avx2_32(r, 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_avx2_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* HAVE_INTEL_AVX2 */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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)) || defined(WOLFSSL_SP_NO_MALLOC) + 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 = 0; + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 5, NULL, + DYNAMIC_TYPE_RSA); + 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 = em->dp[0]; +#else + e = em->dp[0]; + if (em->used > 1) + e |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_2048_from_mp(m, 32, mm); + + if (e == 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 >> 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 >> 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 >> 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +/* 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 a[64], d[32], m[32]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; +#endif + sp_digit* r; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 256U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 2048) { + err = MP_READ_E; + } + if (inLen > 256U) { + err = MP_READ_E; + } + if (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 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + a = d + 32; + m = a + 64; +#endif + r = a; + + sp_2048_from_bin(a, 32, in, inLen); + sp_2048_from_mp(d, 32, dm); + sp_2048_from_mp(m, 32, mm); + err = sp_2048_mod_exp_32(r, a, d, 2048, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 32); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(d, 0, sizeof(sp_digit) * 32); +#endif + + return err; +} + +#else +extern sp_digit sp_2048_cond_add_16(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern sp_digit sp_2048_cond_add_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +/* 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)) || defined(WOLFSSL_SP_NO_MALLOC) + 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* 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 11, NULL, + DYNAMIC_TYPE_RSA); + 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; + + r = t + 32; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; +#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); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + c += sp_2048_cond_add_avx2_16(tmpa, tmpa, p, c); + sp_2048_cond_add_avx2_16(tmpa, tmpa, p, c); + } + else +#endif + { + c += sp_2048_cond_add_16(tmpa, tmpa, p, c); + sp_2048_cond_add_16(tmpa, tmpa, p, c); + } + + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 16 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#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 /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 32); + r->used = 32; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 64 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && 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 = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048 || expBits > 2048 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_mp(e, 32, exp); + 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, expBits, m, 0); + else +#endif + err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH +#ifdef HAVE_FFDHE_2048 +extern void sp_2048_lshift_32(sp_digit* r, const sp_digit* a, int n); +#ifdef HAVE_INTEL_AVX2 +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_avx2_32(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[64]; + sp_digit td[33]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 97, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 64; +#else + norm = nd; + tmp = td; +#endif + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 6) == 0) { + c -= 6; + } + else { + c -= bits % 6; + } + y = (int)(n >> c); + n <<= 64 - c; + sp_2048_lshift_32(r, norm, y); + for (; i>=0 || c>=6; ) { + if (c == 0) { + n = e[i--]; + y = (int)(n >> 58); + n <<= 6; + c = 58; + } + else if (c < 6) { + y = (int)(n >> 58); + n = e[i--]; + c = 6 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 58) & 0x3f; + n <<= 6; + c -= 6; + } + + 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_sqr_avx2_32(r, r, m, mp); + + sp_2048_lshift_32(r, r, y); + sp_2048_mul_d_avx2_32(tmp, norm, r[32]); + r[32] = 0; + o = sp_2048_add_32(r, r, tmp); + sp_2048_cond_sub_avx2_32(r, r, m, (sp_digit)0 - o); + } + + 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_avx2_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* HAVE_INTEL_AVX2 */ + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_32(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[64]; + sp_digit td[33]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 97, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 64; +#else + norm = nd; + tmp = td; +#endif + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 6) == 0) { + c -= 6; + } + else { + c -= bits % 6; + } + y = (int)(n >> c); + n <<= 64 - c; + sp_2048_lshift_32(r, norm, y); + for (; i>=0 || c>=6; ) { + if (c == 0) { + n = e[i--]; + y = (int)(n >> 58); + n <<= 6; + c = 58; + } + else if (c < 6) { + y = (int)(n >> 58); + n = e[i--]; + c = 6 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 58) & 0x3f; + n <<= 6; + c -= 6; + } + + 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_sqr_32(r, r, m, mp); + + sp_2048_lshift_32(r, r, y); + sp_2048_mul_d_32(tmp, norm, r[32]); + r[32] = 0; + o = sp_2048_add_32(r, r, tmp); + sp_2048_cond_sub_32(r, r, m, (sp_digit)0 - o); + } + + 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 /* HAVE_FFDHE_2048 */ + +/* 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. + * returns 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_FFDHE_2048 + if (base->used == 1 && base->dp[0] == 2 && m[31] == (sp_digit)-1) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_2048_mod_exp_2_avx2_32(r, e, expLen * 8, m); + else +#endif + err = sp_2048_mod_exp_2_32(r, e, expLen * 8, m); + } + else + #endif + { +#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 +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[32], e[16], m[16]; + sp_digit* r = b; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024 || expBits > 1024 || + mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 16, base); + sp_2048_from_mp(e, 16, exp); + sp_2048_from_mp(m, 16, mod); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_2048_mod_exp_avx2_16(r, b, e, expBits, m, 0); + else +#endif + err = sp_2048_mod_exp_16(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 16, 0, sizeof(*r) * 16); + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +extern void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n); +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +extern void sp_3072_to_bin(sp_digit* r, byte* a); +extern void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_3072_sqr_12(sp_digit* r, const sp_digit* a); +extern void sp_3072_mul_avx2_12(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_3072_sqr_avx2_12(sp_digit* r, const sp_digit* a); +extern sp_digit sp_3072_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern sp_digit sp_3072_sub_in_place_24(sp_digit* a, const sp_digit* b); +extern sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_3072_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* b); + +extern sp_digit sp_3072_dbl_12(sp_digit* r, const sp_digit* a); +extern void sp_3072_sqr_24(sp_digit* r, const sp_digit* a); + +#ifdef HAVE_INTEL_AVX2 +extern void sp_3072_mul_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* b); +#endif /* HAVE_INTEL_AVX2 */ + +#ifdef HAVE_INTEL_AVX2 +extern void sp_3072_sqr_avx2_24(sp_digit* r, const sp_digit* a); +#endif /* HAVE_INTEL_AVX2 */ + +extern sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b); +extern sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b); + +extern sp_digit sp_3072_dbl_24(sp_digit* r, const sp_digit* a); +extern void sp_3072_sqr_48(sp_digit* r, const sp_digit* a); + +#ifdef HAVE_INTEL_AVX2 +extern void sp_3072_mul_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit* b); +#endif /* HAVE_INTEL_AVX2 */ + +#ifdef HAVE_INTEL_AVX2 +extern void sp_3072_sqr_avx2_48(sp_digit* r, const sp_digit* a); +#endif /* HAVE_INTEL_AVX2 */ + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* 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(const 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; +} + +extern void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, sp_digit b); +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* 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 single precision number. + */ +static void sp_3072_mont_norm_24(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 24); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_24(r, m); +} + +extern sp_digit sp_3072_cond_sub_24(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_3072_mont_reduce_24(sp_digit* a, const sp_digit* m, sp_digit mp); +/* 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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_24(r, a); + sp_3072_mont_reduce_24(r, m, mp); +} + +extern sp_digit sp_3072_cond_sub_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_3072_mul_d_24(sp_digit* r, const sp_digit* a, sp_digit b); +extern void sp_3072_mul_d_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit b); +/* 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 WC_INLINE sp_digit div_3072_word_24(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + 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_24(sp_digit* r, const 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 +} + +extern int64_t sp_3072_cmp_24(const sp_digit* a, const sp_digit* b); +/* 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 WC_INLINE int sp_3072_div_24(const sp_digit* a, const 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); + r1 = sp_3072_cmp_24(&t1[24], d) >= 0; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_cond_sub_avx2_24(&t1[24], &t1[24], d, (sp_digit)0 - r1); + else +#endif + sp_3072_cond_sub_24(&t1[24], &t1[24], d, (sp_digit)0 - r1); + 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; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_cond_sub_avx2_24(r, t1, d, (sp_digit)0 - r1); + else +#endif + sp_3072_cond_sub_24(r, t1, d, (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 WC_INLINE int sp_3072_mod_24(sp_digit* r, const sp_digit* a, const 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][48]; + sp_digit rt[48]; +#else + sp_digit* t[32]; + sp_digit* rt; + 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) * 33 * 48, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 48; + rt = td + 1536; +#endif + norm = t[0]; + + 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--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 5) == 0) { + c -= 5; + } + else { + c -= bits % 5; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 24); + for (; i>=0 || c>=5; ) { + if (c >= 5) { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + else if (c == 0) { + n = e[i--]; + y = (int)(n >> 59); + n <<= 5; + c = 59; + } + else { + y = (int)(n >> 59); + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + + sp_3072_sqr_24(rt, r); + sp_3072_mont_reduce_24(rt, m, mp); + sp_3072_sqr_24(r, rt); + sp_3072_mont_reduce_24(r, m, mp); + sp_3072_sqr_24(rt, r); + sp_3072_mont_reduce_24(rt, m, mp); + sp_3072_sqr_24(r, rt); + sp_3072_mont_reduce_24(r, m, mp); + sp_3072_sqr_24(rt, r); + sp_3072_mont_reduce_24(rt, m, mp); + + sp_3072_mul_24(r, rt, t[y]); + sp_3072_mont_reduce_24(r, 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; +} + +extern void sp_3072_mont_reduce_avx2_24(sp_digit* a, const sp_digit* m, sp_digit mp); +#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. + */ +static void sp_3072_mont_mul_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_3072_mul_avx2_24(r, a, b); + sp_3072_mont_reduce_avx2_24(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_avx2_24(r, a); + sp_3072_mont_reduce_avx2_24(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][48]; + sp_digit rt[48]; +#else + sp_digit* t[32]; + sp_digit* rt; + 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) * 33 * 48, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 48; + rt = td + 1536; +#endif + norm = t[0]; + + 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--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 5) == 0) { + c -= 5; + } + else { + c -= bits % 5; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 24); + for (; i>=0 || c>=5; ) { + if (c >= 5) { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + else if (c == 0) { + n = e[i--]; + y = (int)(n >> 59); + n <<= 5; + c = 59; + } + else { + y = (int)(n >> 59); + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + + sp_3072_sqr_avx2_24(rt, r); + sp_3072_mont_reduce_avx2_24(rt, m, mp); + sp_3072_sqr_avx2_24(r, rt); + sp_3072_mont_reduce_avx2_24(r, m, mp); + sp_3072_sqr_avx2_24(rt, r); + sp_3072_mont_reduce_avx2_24(rt, m, mp); + sp_3072_sqr_avx2_24(r, rt); + sp_3072_mont_reduce_avx2_24(r, m, mp); + sp_3072_sqr_avx2_24(rt, r); + sp_3072_mont_reduce_avx2_24(rt, m, mp); + + sp_3072_mul_avx2_24(r, rt, t[y]); + sp_3072_mont_reduce_avx2_24(r, 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_avx2_24(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* HAVE_INTEL_AVX2 */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* 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 single precision number. + */ +static void sp_3072_mont_norm_48(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 48); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_48(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +extern sp_digit sp_3072_cond_sub_48(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, sp_digit mp); +/* 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, const sp_digit* a, const sp_digit* b, + const 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_48(r, a); + sp_3072_mont_reduce_48(r, m, mp); +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +extern sp_digit sp_3072_cond_sub_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_3072_mul_d_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit b); +/* 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 WC_INLINE sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + 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, const 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 +} + +extern int64_t sp_3072_cmp_48(const sp_digit* a, const sp_digit* b); +/* 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 WC_INLINE int sp_3072_div_48(const sp_digit* a, const 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); + r1 = sp_3072_cmp_48(&t1[48], d) >= 0; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_cond_sub_avx2_48(&t1[48], &t1[48], d, (sp_digit)0 - r1); + else +#endif + sp_3072_cond_sub_48(&t1[48], &t1[48], d, (sp_digit)0 - r1); + 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; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_cond_sub_avx2_48(r, t1, d, (sp_digit)0 - r1); + else +#endif + sp_3072_cond_sub_48(r, t1, d, (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 WC_INLINE int sp_3072_mod_48(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_48(a, m, NULL, r); +} + +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +extern sp_digit sp_3072_sub_48(sp_digit* r, const sp_digit* a, const sp_digit* b); +/* 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 WC_INLINE int sp_3072_div_48_cond(const sp_digit* a, const 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--) { + if (t1[i + 48] != d[i]) + break; + } + if (t1[i + 48] >= d[i]) { + sp_3072_sub_in_place_48(&t1[48], d); + } + 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); + } + } + + for (i = 47; i > 0; i--) { + if (t1[i] != d[i]) + break; + } + if (t1[i] >= d[i]) { + sp_3072_sub_48(r, t1, d); + } + else { + XMEMCPY(r, t1, sizeof(*t1) * 48); + } + + 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 WC_INLINE int sp_3072_mod_48_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_3072_div_48_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][96]; + sp_digit rt[96]; +#else + sp_digit* t[32]; + sp_digit* rt; + 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) * 33 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 96; + rt = td + 3072; +#endif + norm = t[0]; + + 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--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 5) == 0) { + c -= 5; + } + else { + c -= bits % 5; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c >= 5) { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + else if (c == 0) { + n = e[i--]; + y = (int)(n >> 59); + n <<= 5; + c = 59; + } + else { + y = (int)(n >> 59); + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + + sp_3072_sqr_48(rt, r); + sp_3072_mont_reduce_48(rt, m, mp); + sp_3072_sqr_48(r, rt); + sp_3072_mont_reduce_48(r, m, mp); + sp_3072_sqr_48(rt, r); + sp_3072_mont_reduce_48(rt, m, mp); + sp_3072_sqr_48(r, rt); + sp_3072_mont_reduce_48(r, m, mp); + sp_3072_sqr_48(rt, r); + sp_3072_mont_reduce_48(rt, m, mp); + + sp_3072_mul_48(r, rt, t[y]); + sp_3072_mont_reduce_48(r, 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 /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +extern void sp_3072_mont_reduce_avx2_48(sp_digit* a, const sp_digit* m, sp_digit mp); +#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. + */ +static void sp_3072_mont_mul_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_3072_mul_avx2_48(r, a, b); + sp_3072_mont_reduce_avx2_48(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* 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, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_avx2_48(r, a); + sp_3072_mont_reduce_avx2_48(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) +#ifdef HAVE_INTEL_AVX2 +/* 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, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][96]; + sp_digit rt[96]; +#else + sp_digit* t[32]; + sp_digit* rt; + 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) * 33 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 96; + rt = td + 3072; +#endif + norm = t[0]; + + 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--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 5) == 0) { + c -= 5; + } + else { + c -= bits % 5; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c >= 5) { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + else if (c == 0) { + n = e[i--]; + y = (int)(n >> 59); + n <<= 5; + c = 59; + } + else { + y = (int)(n >> 59); + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + + sp_3072_sqr_avx2_48(rt, r); + sp_3072_mont_reduce_avx2_48(rt, m, mp); + sp_3072_sqr_avx2_48(r, rt); + sp_3072_mont_reduce_avx2_48(r, m, mp); + sp_3072_sqr_avx2_48(rt, r); + sp_3072_mont_reduce_avx2_48(rt, m, mp); + sp_3072_sqr_avx2_48(r, rt); + sp_3072_mont_reduce_avx2_48(r, m, mp); + sp_3072_sqr_avx2_48(rt, r); + sp_3072_mont_reduce_avx2_48(rt, m, mp); + + sp_3072_mul_avx2_48(r, rt, t[y]); + sp_3072_mont_reduce_avx2_48(r, 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_avx2_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* HAVE_INTEL_AVX2 */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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)) || defined(WOLFSSL_SP_NO_MALLOC) + 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 = 0; + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 5, NULL, + DYNAMIC_TYPE_RSA); + 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 = em->dp[0]; +#else + e = em->dp[0]; + if (em->used > 1) + e |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_3072_from_mp(m, 48, mm); + + if (e == 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 >> 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 >> 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 >> 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +/* 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 a[96], d[48], m[48]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; +#endif + sp_digit* r; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 384U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 3072) { + err = MP_READ_E; + } + if (inLen > 384U) { + err = MP_READ_E; + } + if (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 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + a = d + 48; + m = a + 96; +#endif + r = a; + + sp_3072_from_bin(a, 48, in, inLen); + sp_3072_from_mp(d, 48, dm); + sp_3072_from_mp(m, 48, mm); + err = sp_3072_mod_exp_48(r, a, d, 3072, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 48); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(d, 0, sizeof(sp_digit) * 48); +#endif + + return err; +} + +#else +extern sp_digit sp_3072_cond_add_24(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern sp_digit sp_3072_cond_add_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +/* 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)) || defined(WOLFSSL_SP_NO_MALLOC) + 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* 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 24 * 11, NULL, + DYNAMIC_TYPE_RSA); + 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; + + r = t + 48; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; +#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); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + c += sp_3072_cond_add_avx2_24(tmpa, tmpa, p, c); + sp_3072_cond_add_avx2_24(tmpa, tmpa, p, c); + } + else +#endif + { + c += sp_3072_cond_add_24(tmpa, tmpa, p, c); + sp_3072_cond_add_24(tmpa, tmpa, p, c); + } + + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 24 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#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 /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 48); + r->used = 48; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 48; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 64 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 48; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && 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 = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072 || expBits > 3072 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_mp(e, 48, exp); + 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, expBits, m, 0); + else +#endif + err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH +#ifdef HAVE_FFDHE_3072 +extern void sp_3072_lshift_48(sp_digit* r, const sp_digit* a, int n); +#ifdef HAVE_INTEL_AVX2 +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_avx2_48(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[96]; + sp_digit td[49]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 145, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 96; +#else + norm = nd; + tmp = td; +#endif + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 6) == 0) { + c -= 6; + } + else { + c -= bits % 6; + } + y = (int)(n >> c); + n <<= 64 - c; + sp_3072_lshift_48(r, norm, y); + for (; i>=0 || c>=6; ) { + if (c == 0) { + n = e[i--]; + y = (int)(n >> 58); + n <<= 6; + c = 58; + } + else if (c < 6) { + y = (int)(n >> 58); + n = e[i--]; + c = 6 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 58) & 0x3f; + n <<= 6; + c -= 6; + } + + 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_sqr_avx2_48(r, r, m, mp); + + sp_3072_lshift_48(r, r, y); + sp_3072_mul_d_avx2_48(tmp, norm, r[48]); + r[48] = 0; + o = sp_3072_add_48(r, r, tmp); + sp_3072_cond_sub_avx2_48(r, r, m, (sp_digit)0 - o); + } + + 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_avx2_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* HAVE_INTEL_AVX2 */ + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_2_48(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[96]; + sp_digit td[49]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 145, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 96; +#else + norm = nd; + tmp = td; +#endif + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 6) == 0) { + c -= 6; + } + else { + c -= bits % 6; + } + y = (int)(n >> c); + n <<= 64 - c; + sp_3072_lshift_48(r, norm, y); + for (; i>=0 || c>=6; ) { + if (c == 0) { + n = e[i--]; + y = (int)(n >> 58); + n <<= 6; + c = 58; + } + else if (c < 6) { + y = (int)(n >> 58); + n = e[i--]; + c = 6 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 58) & 0x3f; + n <<= 6; + c -= 6; + } + + 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_sqr_48(r, r, m, mp); + + sp_3072_lshift_48(r, r, y); + sp_3072_mul_d_48(tmp, norm, r[48]); + r[48] = 0; + o = sp_3072_add_48(r, r, tmp); + sp_3072_cond_sub_48(r, r, m, (sp_digit)0 - o); + } + + 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 /* HAVE_FFDHE_3072 */ + +/* 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. + * returns 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_FFDHE_3072 + if (base->used == 1 && base->dp[0] == 2 && m[47] == (sp_digit)-1) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_3072_mod_exp_2_avx2_48(r, e, expLen * 8, m); + else +#endif + err = sp_3072_mod_exp_2_48(r, e, expLen * 8, m); + } + else + #endif + { +#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 +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[48], e[24], m[24]; + sp_digit* r = b; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536 || expBits > 1536 || + mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 24, base); + sp_3072_from_mp(e, 24, exp); + sp_3072_from_mp(m, 24, mod); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_3072_mod_exp_avx2_24(r, b, e, expBits, m, 0); + else +#endif + err = sp_3072_mod_exp_24(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 24, 0, sizeof(*r) * 24); + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#ifdef WOLFSSL_SP_4096 +extern void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n); +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +extern void sp_4096_to_bin(sp_digit* r, byte* a); +extern sp_digit sp_4096_sub_in_place_64(sp_digit* a, const sp_digit* b); +extern sp_digit sp_4096_add_64(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_4096_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b); + +extern sp_digit sp_2048_dbl_32(sp_digit* r, const sp_digit* a); +extern void sp_4096_sqr_64(sp_digit* r, const sp_digit* a); + +#ifdef HAVE_INTEL_AVX2 +extern void sp_4096_mul_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* b); +#endif /* HAVE_INTEL_AVX2 */ + +#ifdef HAVE_INTEL_AVX2 +extern void sp_4096_sqr_avx2_64(sp_digit* r, const sp_digit* a); +#endif /* HAVE_INTEL_AVX2 */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_4096_mont_setup(const 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; +} + +extern void sp_4096_mul_d_64(sp_digit* r, const sp_digit* a, sp_digit b); +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 4096 bits, just need to subtract. + * + * r A single precision number. + * m A single precision number. + */ +static void sp_4096_mont_norm_64(sp_digit* r, const sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 64); + + /* r = 2^n mod m */ + sp_4096_sub_in_place_64(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +extern sp_digit sp_4096_cond_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_4096_mont_reduce_64(sp_digit* a, const sp_digit* m, sp_digit mp); +/* 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_4096_mont_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_4096_mul_64(r, a, b); + sp_4096_mont_reduce_64(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_4096_mont_sqr_64(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_4096_sqr_64(r, a); + sp_4096_mont_reduce_64(r, m, mp); +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +extern sp_digit sp_4096_cond_sub_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_4096_mul_d_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit b); +/* 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 WC_INLINE sp_digit div_4096_word_64(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + 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_4096_mask_64(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<64; 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; + } +#endif +} + +extern int64_t sp_4096_cmp_64(const sp_digit* a, const sp_digit* b); +/* 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 WC_INLINE int sp_4096_div_64(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + r1 = sp_4096_cmp_64(&t1[64], d) >= 0; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_4096_cond_sub_avx2_64(&t1[64], &t1[64], d, (sp_digit)0 - r1); + else +#endif + sp_4096_cond_sub_64(&t1[64], &t1[64], d, (sp_digit)0 - r1); + for (i=63; i>=0; i--) { + r1 = div_4096_word_64(t1[64 + i], t1[64 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_4096_mul_d_avx2_64(t2, d, r1); + else +#endif + sp_4096_mul_d_64(t2, d, r1); + t1[64 + i] += sp_4096_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + sp_4096_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_4096_add_64(&t1[i], &t1[i], t2); + sp_4096_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_4096_add_64(&t1[i], &t1[i], t2); + } + + r1 = sp_4096_cmp_64(t1, d) >= 0; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_4096_cond_sub_avx2_64(r, t1, d, (sp_digit)0 - r1); + else +#endif + sp_4096_cond_sub_64(r, t1, d, (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 WC_INLINE int sp_4096_mod_64(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_64(a, m, NULL, r); +} + +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +extern sp_digit sp_4096_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b); +/* 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 WC_INLINE int sp_4096_div_64_cond(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i = 63; i > 0; i--) { + if (t1[i + 64] != d[i]) + break; + } + if (t1[i + 64] >= d[i]) { + sp_4096_sub_in_place_64(&t1[64], d); + } + for (i=63; i>=0; i--) { + r1 = div_4096_word_64(t1[64 + i], t1[64 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_4096_mul_d_avx2_64(t2, d, r1); + else +#endif + sp_4096_mul_d_64(t2, d, r1); + t1[64 + i] += sp_4096_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + if (t1[64 + i] != 0) { + t1[64 + i] += sp_4096_add_64(&t1[i], &t1[i], d); + if (t1[64 + i] != 0) + t1[64 + i] += sp_4096_add_64(&t1[i], &t1[i], d); + } + } + + for (i = 63; i > 0; i--) { + if (t1[i] != d[i]) + break; + } + if (t1[i] >= d[i]) { + sp_4096_sub_64(r, t1, d); + } + else { + XMEMCPY(r, t1, sizeof(*t1) * 64); + } + + 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 WC_INLINE int sp_4096_mod_64_cond(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_4096_div_64_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || 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_4096_mod_exp_64(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][128]; + sp_digit rt[128]; +#else + sp_digit* t[32]; + sp_digit* rt; + 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) * 33 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 128; + rt = td + 4096; +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64); + if (reduceA) { + err = sp_4096_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) + err = sp_4096_mod_64(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_4096_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_64(t[10], t[ 5], m, mp); + sp_4096_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_64(t[12], t[ 6], m, mp); + sp_4096_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_64(t[14], t[ 7], m, mp); + sp_4096_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + sp_4096_mont_sqr_64(t[16], t[ 8], m, mp); + sp_4096_mont_mul_64(t[17], t[ 9], t[ 8], m, mp); + sp_4096_mont_sqr_64(t[18], t[ 9], m, mp); + sp_4096_mont_mul_64(t[19], t[10], t[ 9], m, mp); + sp_4096_mont_sqr_64(t[20], t[10], m, mp); + sp_4096_mont_mul_64(t[21], t[11], t[10], m, mp); + sp_4096_mont_sqr_64(t[22], t[11], m, mp); + sp_4096_mont_mul_64(t[23], t[12], t[11], m, mp); + sp_4096_mont_sqr_64(t[24], t[12], m, mp); + sp_4096_mont_mul_64(t[25], t[13], t[12], m, mp); + sp_4096_mont_sqr_64(t[26], t[13], m, mp); + sp_4096_mont_mul_64(t[27], t[14], t[13], m, mp); + sp_4096_mont_sqr_64(t[28], t[14], m, mp); + sp_4096_mont_mul_64(t[29], t[15], t[14], m, mp); + sp_4096_mont_sqr_64(t[30], t[15], m, mp); + sp_4096_mont_mul_64(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 5) == 0) { + c -= 5; + } + else { + c -= bits % 5; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=5; ) { + if (c >= 5) { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + else if (c == 0) { + n = e[i--]; + y = (int)(n >> 59); + n <<= 5; + c = 59; + } + else { + y = (int)(n >> 59); + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + + sp_4096_sqr_64(rt, r); + sp_4096_mont_reduce_64(rt, m, mp); + sp_4096_sqr_64(r, rt); + sp_4096_mont_reduce_64(r, m, mp); + sp_4096_sqr_64(rt, r); + sp_4096_mont_reduce_64(rt, m, mp); + sp_4096_sqr_64(r, rt); + sp_4096_mont_reduce_64(r, m, mp); + sp_4096_sqr_64(rt, r); + sp_4096_mont_reduce_64(rt, m, mp); + + sp_4096_mul_64(r, rt, t[y]); + sp_4096_mont_reduce_64(r, m, mp); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_4096_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_4096_cmp_64(r, m) >= 0); + sp_4096_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +extern void sp_4096_mont_reduce_avx2_64(sp_digit* a, const sp_digit* m, sp_digit mp); +#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. + */ +static void sp_4096_mont_mul_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_4096_mul_avx2_64(r, a, b); + sp_4096_mont_reduce_avx2_64(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* 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_4096_mont_sqr_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_4096_sqr_avx2_64(r, a); + sp_4096_mont_reduce_avx2_64(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) +#ifdef HAVE_INTEL_AVX2 +/* 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_4096_mod_exp_avx2_64(sp_digit* r, const sp_digit* a, const sp_digit* e, + int bits, const sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][128]; + sp_digit rt[128]; +#else + sp_digit* t[32]; + sp_digit* rt; + 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) * 33 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + for (i=0; i<32; i++) + t[i] = td + i * 128; + rt = td + 4096; +#endif + norm = t[0]; + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64); + if (reduceA) { + err = sp_4096_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) + err = sp_4096_mod_64(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_4096_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_4096_mont_sqr_avx2_64(t[ 2], t[ 1], m, mp); + sp_4096_mont_mul_avx2_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_4096_mont_sqr_avx2_64(t[ 4], t[ 2], m, mp); + sp_4096_mont_mul_avx2_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_4096_mont_sqr_avx2_64(t[ 6], t[ 3], m, mp); + sp_4096_mont_mul_avx2_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_4096_mont_sqr_avx2_64(t[ 8], t[ 4], m, mp); + sp_4096_mont_mul_avx2_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_4096_mont_sqr_avx2_64(t[10], t[ 5], m, mp); + sp_4096_mont_mul_avx2_64(t[11], t[ 6], t[ 5], m, mp); + sp_4096_mont_sqr_avx2_64(t[12], t[ 6], m, mp); + sp_4096_mont_mul_avx2_64(t[13], t[ 7], t[ 6], m, mp); + sp_4096_mont_sqr_avx2_64(t[14], t[ 7], m, mp); + sp_4096_mont_mul_avx2_64(t[15], t[ 8], t[ 7], m, mp); + sp_4096_mont_sqr_avx2_64(t[16], t[ 8], m, mp); + sp_4096_mont_mul_avx2_64(t[17], t[ 9], t[ 8], m, mp); + sp_4096_mont_sqr_avx2_64(t[18], t[ 9], m, mp); + sp_4096_mont_mul_avx2_64(t[19], t[10], t[ 9], m, mp); + sp_4096_mont_sqr_avx2_64(t[20], t[10], m, mp); + sp_4096_mont_mul_avx2_64(t[21], t[11], t[10], m, mp); + sp_4096_mont_sqr_avx2_64(t[22], t[11], m, mp); + sp_4096_mont_mul_avx2_64(t[23], t[12], t[11], m, mp); + sp_4096_mont_sqr_avx2_64(t[24], t[12], m, mp); + sp_4096_mont_mul_avx2_64(t[25], t[13], t[12], m, mp); + sp_4096_mont_sqr_avx2_64(t[26], t[13], m, mp); + sp_4096_mont_mul_avx2_64(t[27], t[14], t[13], m, mp); + sp_4096_mont_sqr_avx2_64(t[28], t[14], m, mp); + sp_4096_mont_mul_avx2_64(t[29], t[15], t[14], m, mp); + sp_4096_mont_sqr_avx2_64(t[30], t[15], m, mp); + sp_4096_mont_mul_avx2_64(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 5) == 0) { + c -= 5; + } + else { + c -= bits % 5; + } + y = (int)(n >> c); + n <<= 64 - c; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=5; ) { + if (c >= 5) { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + else if (c == 0) { + n = e[i--]; + y = (int)(n >> 59); + n <<= 5; + c = 59; + } + else { + y = (int)(n >> 59); + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + + sp_4096_sqr_avx2_64(rt, r); + sp_4096_mont_reduce_avx2_64(rt, m, mp); + sp_4096_sqr_avx2_64(r, rt); + sp_4096_mont_reduce_avx2_64(r, m, mp); + sp_4096_sqr_avx2_64(rt, r); + sp_4096_mont_reduce_avx2_64(rt, m, mp); + sp_4096_sqr_avx2_64(r, rt); + sp_4096_mont_reduce_avx2_64(r, m, mp); + sp_4096_sqr_avx2_64(rt, r); + sp_4096_mont_reduce_avx2_64(rt, m, mp); + + sp_4096_mul_avx2_64(r, rt, t[y]); + sp_4096_mont_reduce_avx2_64(r, m, mp); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_4096_mont_reduce_avx2_64(r, m, mp); + + mask = 0 - (sp_4096_cmp_64(r, m) >= 0); + sp_4096_cond_sub_avx2_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* HAVE_INTEL_AVX2 */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || 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 512 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_4096(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit ad[128], md[64], rd[128]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e = 0; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (*outLen < 512) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 64 || inLen > 512 || + mp_count_bits(mm) != 4096)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 64 * 2; + m = r + 64 * 2; + ah = a + 64; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 64; +#endif + + if (err == MP_OKAY) { + sp_4096_from_bin(ah, 64, in, inLen); +#if DIGIT_BIT >= 64 + e = em->dp[0]; +#else + e = em->dp[0]; + if (em->used > 1) + e |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_4096_from_mp(m, 64, mm); + + if (e == 0x3) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + if (err == MP_OKAY) { + sp_4096_sqr_avx2_64(r, ah); + err = sp_4096_mod_64_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_4096_mul_avx2_64(r, ah, r); + err = sp_4096_mod_64_cond(r, r, m); + } + } + else +#endif + { + if (err == MP_OKAY) { + sp_4096_sqr_64(r, ah); + err = sp_4096_mod_64_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_4096_mul_64(r, ah, r); + err = sp_4096_mod_64_cond(r, r, m); + } + } + } + else { + int i; + sp_digit mp; + + sp_4096_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 64); + err = sp_4096_mod_64_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=63; i>=0; i--) { + if (e >> i) { + break; + } + } + + XMEMCPY(r, a, sizeof(sp_digit) * 64); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + for (i--; i>=0; i--) { + sp_4096_mont_sqr_avx2_64(r, r, m, mp); + if (((e >> i) & 1) == 1) { + sp_4096_mont_mul_avx2_64(r, r, a, m, mp); + } + } + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_4096_mont_reduce_avx2_64(r, m, mp); + } + else +#endif + { + for (i--; i>=0; i--) { + sp_4096_mont_sqr_64(r, r, m, mp); + if (((e >> i) & 1) == 1) { + sp_4096_mont_mul_64(r, r, a, m, mp); + } + } + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_4096_mont_reduce_64(r, m, mp); + } + + for (i = 63; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_4096_sub_in_place_64(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +/* 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 512 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_4096(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 a[128], d[64], m[64]; +#else + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; +#endif + sp_digit* r; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 512U) { + err = MP_TO_E; + } + if (err == MP_OKAY) { + if (mp_count_bits(dm) > 4096) { + err = MP_READ_E; + } + if (inLen > 512U) { + err = MP_READ_E; + } + if (mp_count_bits(mm) != 4096) { + err = MP_READ_E; + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + a = d + 64; + m = a + 128; +#endif + r = a; + + sp_4096_from_bin(a, 64, in, inLen); + sp_4096_from_mp(d, 64, dm); + sp_4096_from_mp(m, 64, mm); + err = sp_4096_mod_exp_64(r, a, d, 4096, m, 0); + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 64); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(d, 0, sizeof(sp_digit) * 64); +#endif + + return err; +} + +#else +extern sp_digit sp_4096_cond_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern sp_digit sp_4096_cond_add_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +/* 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 512 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_4096(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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit ad[64 * 2]; + sp_digit pd[32], qd[32], dpd[32]; + sp_digit tmpad[64], tmpbd[64]; +#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* 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 < 512) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 512 || mp_count_bits(mm) != 4096)) + err = MP_READ_E; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 64 * 2; + q = p + 32; + qi = dq = dp = q + 32; + tmpa = qi + 32; + tmpb = tmpa + 64; + + r = t + 64; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; +#endif + + if (err == MP_OKAY) { + sp_4096_from_bin(a, 64, in, inLen); + sp_4096_from_mp(p, 32, pm); + sp_4096_from_mp(q, 32, qm); + sp_4096_from_mp(dp, 32, dpm); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_2048_mod_exp_avx2_32(tmpa, a, dp, 2048, p, 1); + else +#endif + err = sp_2048_mod_exp_32(tmpa, a, dp, 2048, p, 1); + } + if (err == MP_OKAY) { + sp_4096_from_mp(dq, 32, dqm); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_2048_mod_exp_avx2_32(tmpb, a, dq, 2048, q, 1); + else +#endif + err = sp_2048_mod_exp_32(tmpb, a, dq, 2048, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_32(tmpa, tmpb); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + c += sp_4096_cond_add_avx2_32(tmpa, tmpa, p, c); + sp_4096_cond_add_avx2_32(tmpa, tmpa, p, c); + } + else +#endif + { + c += sp_4096_cond_add_32(tmpa, tmpa, p, c); + sp_4096_cond_add_32(tmpa, tmpa, p, c); + } + + sp_2048_from_mp(qi, 32, qim); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_2048_mul_avx2_32(tmpa, tmpa, qi); + } + else +#endif + { + sp_2048_mul_32(tmpa, tmpa, qi); + } + err = sp_2048_mod_32(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_32(tmpa, q, tmpa); + } + else +#endif + { + sp_2048_mul_32(tmpa, q, tmpa); + } + XMEMSET(&tmpb[32], 0, sizeof(sp_digit) * 32); + sp_4096_add_64(r, tmpb, tmpa); + + sp_4096_to_bin(r, out); + *outLen = 512; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#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 /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_4096_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 64); + r->used = 64; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 64 - s; + } + r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && 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 = (4096 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returns 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 4096 || expBits > 4096 || + mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 64, base); + sp_4096_from_mp(e, 64, exp); + sp_4096_from_mp(m, 64, mod); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_4096_mod_exp_avx2_64(r, b, e, expBits, m, 0); + else +#endif + err = sp_4096_mod_exp_64(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_4096_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH +#ifdef HAVE_FFDHE_4096 +extern void sp_4096_lshift_64(sp_digit* r, const sp_digit* a, int n); +#ifdef HAVE_INTEL_AVX2 +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_4096_mod_exp_2_avx2_64(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[128]; + sp_digit td[65]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 193, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 128; +#else + norm = nd; + tmp = td; +#endif + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_64(norm, m); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 6) == 0) { + c -= 6; + } + else { + c -= bits % 6; + } + y = (int)(n >> c); + n <<= 64 - c; + sp_4096_lshift_64(r, norm, y); + for (; i>=0 || c>=6; ) { + if (c == 0) { + n = e[i--]; + y = (int)(n >> 58); + n <<= 6; + c = 58; + } + else if (c < 6) { + y = (int)(n >> 58); + n = e[i--]; + c = 6 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 58) & 0x3f; + n <<= 6; + c -= 6; + } + + sp_4096_mont_sqr_avx2_64(r, r, m, mp); + sp_4096_mont_sqr_avx2_64(r, r, m, mp); + sp_4096_mont_sqr_avx2_64(r, r, m, mp); + sp_4096_mont_sqr_avx2_64(r, r, m, mp); + sp_4096_mont_sqr_avx2_64(r, r, m, mp); + sp_4096_mont_sqr_avx2_64(r, r, m, mp); + + sp_4096_lshift_64(r, r, y); + sp_4096_mul_d_avx2_64(tmp, norm, r[64]); + r[64] = 0; + o = sp_4096_add_64(r, r, tmp); + sp_4096_cond_sub_avx2_64(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_4096_mont_reduce_avx2_64(r, m, mp); + + mask = 0 - (sp_4096_cmp_64(r, m) >= 0); + sp_4096_cond_sub_avx2_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* HAVE_INTEL_AVX2 */ + +/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m) + * + * r A single precision number that is the result of the operation. + * 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_4096_mod_exp_2_64(sp_digit* r, const sp_digit* e, int bits, + const sp_digit* m) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit nd[128]; + sp_digit td[65]; +#else + sp_digit* td; +#endif + sp_digit* norm; + sp_digit* tmp; + sp_digit mp = 1; + sp_digit n, o; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 193, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + norm = td; + tmp = td + 128; +#else + norm = nd; + tmp = td; +#endif + + sp_4096_mont_setup(m, &mp); + sp_4096_mont_norm_64(norm, m); + + i = (bits - 1) / 64; + n = e[i--]; + c = bits & 63; + if (c == 0) { + c = 64; + } + if ((bits % 6) == 0) { + c -= 6; + } + else { + c -= bits % 6; + } + y = (int)(n >> c); + n <<= 64 - c; + sp_4096_lshift_64(r, norm, y); + for (; i>=0 || c>=6; ) { + if (c == 0) { + n = e[i--]; + y = (int)(n >> 58); + n <<= 6; + c = 58; + } + else if (c < 6) { + y = (int)(n >> 58); + n = e[i--]; + c = 6 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 58) & 0x3f; + n <<= 6; + c -= 6; + } + + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + sp_4096_mont_sqr_64(r, r, m, mp); + + sp_4096_lshift_64(r, r, y); + sp_4096_mul_d_64(tmp, norm, r[64]); + r[64] = 0; + o = sp_4096_add_64(r, r, tmp); + sp_4096_cond_sub_64(r, r, m, (sp_digit)0 - o); + } + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_4096_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_4096_cmp_64(r, m) >= 0); + sp_4096_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +#endif /* HAVE_FFDHE_4096 */ + +/* 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 512 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returns 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_4096(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; + word32 i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (mp_count_bits(base) > 4096 || expLen > 512 || + mp_count_bits(mod) != 4096) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_4096_from_mp(b, 64, base); + sp_4096_from_bin(e, 64, exp, expLen); + sp_4096_from_mp(m, 64, mod); + + #ifdef HAVE_FFDHE_4096 + if (base->used == 1 && base->dp[0] == 2 && m[63] == (sp_digit)-1) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_4096_mod_exp_2_avx2_64(r, e, expLen * 8, m); + else +#endif + err = sp_4096_mod_exp_2_64(r, e, expLen * 8, m); + } + else + #endif + { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_4096_mod_exp_avx2_64(r, b, e, expLen * 8, m, 0); + else +#endif + err = sp_4096_mod_exp_64(r, b, e, expLen * 8, m, 0); + } + } + + if (err == MP_OKAY) { + sp_4096_to_bin(r, out); + *outLen = 512; + for (i=0; i<512 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +#endif +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* WOLFSSL_SP_4096 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point_256 { + sp_digit x[2 * 4]; + sp_digit y[2 * 4]; + sp_digit z[2 * 4]; + int infinity; +} sp_point_256; + +/* The modulus (prime) of the curve P256. */ +static const sp_digit p256_mod[4] = { + 0xffffffffffffffffL,0x00000000ffffffffL,0x0000000000000000L, + 0xffffffff00000001L +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static const sp_digit p256_norm_mod[4] = { + 0x0000000000000001L,0xffffffff00000000L,0xffffffffffffffffL, + 0x00000000fffffffeL +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static const 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 const sp_digit p256_order[4] = { + 0xf3b9cac2fc632551L,0xbce6faada7179e84L,0xffffffffffffffffL, + 0xffffffff00000000L +}; +#endif +/* The order of the curve P256 minus 2. */ +static const 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 const 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 const sp_digit p256_mp_order = 0xccd1c8aaee00bc4fL; +#endif +#ifdef WOLFSSL_SP_SMALL +/* The base point of curve P256. */ +static const sp_point_256 p256_base = { + /* X ordinate */ + { + 0xf4a13945d898c296L,0x77037d812deb33a0L,0xf8bce6e563a440f2L, + 0x6b17d1f2e12c4247L, + 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0xcbb6406837bf51f5L,0x2bce33576b315eceL,0x8ee7eb4a7c0f9e16L, + 0x4fe342e2fe1a7f9bL, + 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x0000000000000001L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L, + 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#endif /* WOLFSSL_SP_SMALL */ +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p256_b[4] = { + 0x3bce3c3e27d2604bL,0x651d06b0cc53b0f6L,0xb3ebbd55769886bcL, + 0x5ac635d8aa3a93e7L +}; +#endif + +static int sp_256_point_new_ex_4(void* heap, sp_point_256* sp, sp_point_256** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_256_point_new_4(heap, sp, p) sp_256_point_new_ex_4((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_256_point_new_4(heap, sp, p) sp_256_point_new_ex_4((heap), &(sp), &(p)) +#endif + + +static void sp_256_point_free_4(sp_point_256* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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, const sp_digit* a, const 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. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_256. + * + * p Point of type sp_point_256 (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_4(sp_point_256* p, const 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(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always 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] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(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 != 32 && 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_256 to type ecc_point. + * + * p Point of type sp_point_256. + * 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(const sp_point_256* 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; +} + +extern void sp_256_cond_copy_4(sp_digit* r, const sp_digit* a, sp_digit m); +extern void sp_256_mont_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m, sp_digit mp); +extern void sp_256_mont_sqr_4(sp_digit* r, const sp_digit* a, const sp_digit* m, sp_digit mp); +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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, const sp_digit* a, int n, + const 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); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint64_t p256_mod_minus_2[4] = { + 0xfffffffffffffffdU,0x00000000ffffffffU,0x0000000000000000U, + 0xffffffff00000001U +}; +#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, const 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_minus_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* t1 = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + /* 0x2 */ + sp_256_mont_sqr_4(t1, a, p256_mod, p256_mp_mod); + /* 0x3 */ + sp_256_mont_mul_4(t2, t1, a, p256_mod, p256_mp_mod); + /* 0xc */ + sp_256_mont_sqr_n_4(t1, t2, 2, p256_mod, p256_mp_mod); + /* 0xd */ + sp_256_mont_mul_4(t3, t1, a, p256_mod, p256_mp_mod); + /* 0xf */ + sp_256_mont_mul_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xf0 */ + sp_256_mont_sqr_n_4(t1, t2, 4, p256_mod, p256_mp_mod); + /* 0xfd */ + sp_256_mont_mul_4(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xff */ + sp_256_mont_mul_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xff00 */ + sp_256_mont_sqr_n_4(t1, t2, 8, p256_mod, p256_mp_mod); + /* 0xfffd */ + sp_256_mont_mul_4(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffff */ + sp_256_mont_mul_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffff0000 */ + sp_256_mont_sqr_n_4(t1, t2, 16, p256_mod, p256_mp_mod); + /* 0xfffffffd */ + sp_256_mont_mul_4(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffffffff */ + sp_256_mont_mul_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000000 */ + sp_256_mont_sqr_n_4(t1, t2, 32, p256_mod, p256_mp_mod); + /* 0xffffffffffffffff */ + sp_256_mont_mul_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000001 */ + sp_256_mont_mul_4(r, t1, a, p256_mod, p256_mp_mod); + /* 0xffffffff000000010000000000000000000000000000000000000000 */ + sp_256_mont_sqr_n_4(r, r, 160, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff */ + sp_256_mont_mul_4(r, r, t2, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */ + sp_256_mont_sqr_n_4(r, r, 32, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */ + sp_256_mont_mul_4(r, r, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +extern int64_t sp_256_cmp_4(const sp_digit* a, const sp_digit* b); +/* Normalize the values in each word to 64. + * + * a Array of sp_digit to normalize. + */ +#define sp_256_norm_4(a) + +extern sp_digit sp_256_cond_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b); +#define sp_256_mont_reduce_order_4 sp_256_mont_reduce_4 + +extern void sp_256_mont_reduce_4(sp_digit* a, const sp_digit* m, sp_digit mp); +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_4(sp_point_256* r, const sp_point_256* 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) / 2U); + 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_digit)1 : (sp_digit)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) / 2U); + 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_digit)1 : (sp_digit)0)); + sp_256_norm_4(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +extern void sp_256_mont_add_4(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m); +extern void sp_256_mont_dbl_4(const sp_digit* r, const sp_digit* a, const sp_digit* m); +extern void sp_256_mont_tpl_4(sp_digit* r, const sp_digit* a, const sp_digit* m); +extern void sp_256_mont_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m); +extern void sp_256_div2_4(sp_digit* r, const sp_digit* a, const sp_digit* m); +/* 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_256* r, const sp_point_256* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_4(t1, p->z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_4(z, p->y, p->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, p->x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_4(t1, p->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, p->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, p->x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_sqr_4(x, 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_256* p, int n, 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; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* 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); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* 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(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(b, t1, 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(t2, b, p256_mod); + sp_256_mont_sub_4(x, x, t2, 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(t1, t1, p256_mod, p256_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_256_mont_mul_4(w, w, t1, 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, t1, p256_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* 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(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(b, t1, 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(t2, b, p256_mod); + sp_256_mont_sub_4(x, x, t2, 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(t1, t1, 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, t1, p256_mod); +#endif + /* 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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, + sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + 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) { + const sp_point_256* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)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))) != 0) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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_256* r, const sp_point_256* 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_256 { + /* Index into pre-computation table. */ + uint8_t i; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode_256; + +/* The index into pre-computation table to use. */ +static const 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 const 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 perform. + */ +static void sp_256_ecc_recode_6_4(const sp_digit* k, ecc_recode_256* 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 coordinates. + * + * 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_256* r, const sp_point_256* g, + const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td[33]; + sp_point_256 rtd, pd; + sp_digit tmpd[2 * 4 * 6]; +#endif + sp_point_256* t; + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_256 v[43]; + int err; + + (void)heap; + + err = sp_256_point_new_4(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_256_point_new_4(heap, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 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_256)); + for (--i; i>=0; i--) { + sp_256_proj_point_dbl_n_4(rt, 6, tmp); + + XMEMCPY(p, &t[v[i].i], sizeof(sp_point_256)); + 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 != 0) { + sp_256_map_4(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + sp_256_point_free_4(p, 0, heap); + sp_256_point_free_4(rt, 0, heap); + + return err; +} + +#ifdef HAVE_INTEL_AVX2 +extern void sp_256_mont_mul_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit* b, const sp_digit* m, sp_digit mp); +extern void sp_256_mont_sqr_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit* m, sp_digit mp); +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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, const sp_digit* a, int n, + const 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 || HAVE_COMP_KEY */ + +/* 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, const 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_minus_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* t1 = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + /* 0x2 */ + sp_256_mont_sqr_avx2_4(t1, a, p256_mod, p256_mp_mod); + /* 0x3 */ + sp_256_mont_mul_avx2_4(t2, t1, a, p256_mod, p256_mp_mod); + /* 0xc */ + sp_256_mont_sqr_n_avx2_4(t1, t2, 2, p256_mod, p256_mp_mod); + /* 0xd */ + sp_256_mont_mul_avx2_4(t3, t1, a, p256_mod, p256_mp_mod); + /* 0xf */ + sp_256_mont_mul_avx2_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xf0 */ + sp_256_mont_sqr_n_avx2_4(t1, t2, 4, p256_mod, p256_mp_mod); + /* 0xfd */ + sp_256_mont_mul_avx2_4(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xff */ + sp_256_mont_mul_avx2_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xff00 */ + sp_256_mont_sqr_n_avx2_4(t1, t2, 8, p256_mod, p256_mp_mod); + /* 0xfffd */ + sp_256_mont_mul_avx2_4(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffff */ + sp_256_mont_mul_avx2_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffff0000 */ + sp_256_mont_sqr_n_avx2_4(t1, t2, 16, p256_mod, p256_mp_mod); + /* 0xfffffffd */ + sp_256_mont_mul_avx2_4(t3, t3, t1, p256_mod, p256_mp_mod); + /* 0xffffffff */ + sp_256_mont_mul_avx2_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000000 */ + sp_256_mont_sqr_n_avx2_4(t1, t2, 32, p256_mod, p256_mp_mod); + /* 0xffffffffffffffff */ + sp_256_mont_mul_avx2_4(t2, t2, t1, p256_mod, p256_mp_mod); + /* 0xffffffff00000001 */ + sp_256_mont_mul_avx2_4(r, t1, a, p256_mod, p256_mp_mod); + /* 0xffffffff000000010000000000000000000000000000000000000000 */ + sp_256_mont_sqr_n_avx2_4(r, r, 160, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff */ + sp_256_mont_mul_avx2_4(r, r, t2, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */ + sp_256_mont_sqr_n_avx2_4(r, r, 32, p256_mod, p256_mp_mod); + /* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */ + sp_256_mont_mul_avx2_4(r, r, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_avx2_4(sp_point_256* r, const sp_point_256* 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) / 2U); + 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_digit)1 : (sp_digit)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) / 2U); + 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_digit)1 : (sp_digit)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_256* r, const sp_point_256* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_avx2_4(t1, p->z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_avx2_4(z, p->y, p->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, p->x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_4(t1, p->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, p->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, p->x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_sqr_avx2_4(x, 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_256* p, int n, 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; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* 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); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* 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(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(b, t1, 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(t2, b, p256_mod); + sp_256_mont_sub_4(x, x, t2, 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(t1, t1, p256_mod, p256_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_256_mont_mul_avx2_4(w, w, t1, 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, t1, p256_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* 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(t1, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(b, t1, 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(t2, b, p256_mod); + sp_256_mont_sub_4(x, x, t2, 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(t1, t1, 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, t1, p256_mod); +#endif + /* Y = Y/2 */ + sp_256_div2_4(y, y, p256_mod); +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_avx2_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, + sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + 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) { + const sp_point_256* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)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))) != 0) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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_256* r, const sp_point_256* 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 coordinates. + * + * 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_256* r, const sp_point_256* g, + const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td[33]; + sp_point_256 rtd, pd; + sp_digit tmpd[2 * 4 * 6]; +#endif + sp_point_256* t; + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_256 v[43]; + int err; + + (void)heap; + + err = sp_256_point_new_4(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_256_point_new_4(heap, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 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_256)); + for (--i; i>=0; i--) { + sp_256_proj_point_dbl_n_avx2_4(rt, 6, tmp); + + XMEMCPY(p, &t[v[i].i], sizeof(sp_point_256)); + 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 != 0) { + sp_256_map_avx2_4(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + sp_256_point_free_4(p, 0, heap); + sp_256_point_free_4(rt, 0, heap); + + return err; +} + +#endif /* HAVE_INTEL_AVX2 */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_256 { + sp_digit x[4]; + sp_digit y[4]; +} sp_table_entry_256; + +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +/* 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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_4(sp_point_256* r, const sp_point_256* p, + const sp_point_256* q, sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + 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 */ + (void)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))) != 0) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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 Temporary data. + */ +static void sp_256_proj_to_affine_4(sp_point_256* 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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_4(const sp_point_256* a, + sp_table_entry_256* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td, s1d, s2d; +#endif + sp_point_256* t; + sp_point_256* s1 = NULL; + sp_point_256* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_256_point_new_4(heap, td, t); + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_256_point_new_4(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_256)); + /* 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)); + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_4(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)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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)); + } + } + } + + sp_256_point_free_4(s2, 0, heap); + sp_256_point_free_4(s1, 0, heap); + sp_256_point_free_4( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit td[2 * 4 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_256_point_new_4(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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 = !y; + 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 = !y; + sp_256_proj_point_add_qz1_4(rt, rt, p, t); + } + + if (map != 0) { + sp_256_map_4(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(p, 0, heap); + sp_256_point_free_4(rt, 0, heap); + + return err; +} + +#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_256_t { + sp_digit x[4]; + sp_digit y[4]; + sp_table_entry_256 table[256]; + uint32_t cnt; + int set; +} sp_cache_256_t; + +static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_256_last = -1; +static THREAD_LS_T int sp_cache_256_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_256 = 0; + static wolfSSL_Mutex sp_cache_256_lock; +#endif + +static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_256_inited == 0) { + for (i=0; ix, sp_cache_256[i].x) & + sp_256_cmp_equal_4(g->y, sp_cache_256[i].y)) { + sp_cache_256[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_256_last + 1) % FP_ENTRIES; + for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_256[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_256_last) { + least = sp_cache_256[0].cnt; + for (j=1; jx, sizeof(sp_cache_256[i].x)); + XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y)); + sp_cache_256[i].set = 1; + sp_cache_256[i].cnt = 1; + } + + *cache = &sp_cache_256[i]; + sp_cache_256_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 coordinates. + * + * 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_256* r, const sp_point_256* g, const 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_256_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_256 == 0) { + wc_InitMutex(&sp_cache_256_lock); + initCacheMutex_256 = 1; + } + if (wc_LockMutex(&sp_cache_256_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_256(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_256_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 +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +/* 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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_avx2_4(sp_point_256* r, const sp_point_256* p, + const sp_point_256* q, sp_digit* t) +{ + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + 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 */ + (void)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))) != 0) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_256)); + 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 Temporary data. + */ +static void sp_256_proj_to_affine_avx2_4(sp_point_256* 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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_avx2_4(const sp_point_256* a, + sp_table_entry_256* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 td, s1d, s2d; +#endif + sp_point_256* t; + sp_point_256* s1 = NULL; + sp_point_256* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_256_point_new_4(heap, td, t); + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_256_point_new_4(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_256)); + /* 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)); + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_avx2_4(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)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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)); + } + } + } + + sp_256_point_free_4(s2, 0, heap); + sp_256_point_free_4(s1, 0, heap); + sp_256_point_free_4( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit td[2 * 4 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_256_point_new_4(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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 = !y; + 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 = !y; + sp_256_proj_point_add_qz1_avx2_4(rt, rt, p, t); + } + + if (map != 0) { + sp_256_map_avx2_4(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(p, 0, heap); + sp_256_point_free_4(rt, 0, heap); + + return err; +} + +#endif /* FP_ECC || 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 coordinates. + * + * 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_256* r, const sp_point_256* g, const 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_256_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_256 == 0) { + wc_InitMutex(&sp_cache_256_lock); + initCacheMutex_256 = 1; + } + if (wc_LockMutex(&sp_cache_256_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_256(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_256_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 coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[4]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_256_point_new_4(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static const sp_table_entry_256 p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x79e730d418a9143cL,0x75ba95fc5fedb601L,0x79fb732b77622510L, + 0x18905f76a53755c6L }, + { 0xddf25357ce95560aL,0x8b4ab8e4ba19e45cL,0xd2e88688dd21f325L, + 0x8571ff1825885d85L } }, + /* 2 */ + { { 0x202886024147519aL,0xd0981eac26b372f0L,0xa9d4a7caa785ebc8L, + 0xd953c50ddbdf58e9L }, + { 0x9d6361ccfd590f8fL,0x72e9626b44e6c917L,0x7fd9611022eb64cfL, + 0x863ebb7e9eb288f3L } }, + /* 3 */ + { { 0x7856b6235cdb6485L,0x808f0ea22f0a2f97L,0x3e68d9544f7e300bL, + 0x00076055b5ff80a0L }, + { 0x7634eb9b838d2010L,0x54014fbb3243708aL,0xe0e47d39842a6606L, + 0x8308776134373ee0L } }, + /* 4 */ + { { 0x4f922fc516a0d2bbL,0x0d5cc16c1a623499L,0x9241cf3a57c62c8bL, + 0x2f5e6961fd1b667fL }, + { 0x5c15c70bf5a01797L,0x3d20b44d60956192L,0x04911b37071fdb52L, + 0xf648f9168d6f0f7bL } }, + /* 5 */ + { { 0x9e566847e137bbbcL,0xe434469e8a6a0becL,0xb1c4276179d73463L, + 0x5abe0285133d0015L }, + { 0x92aa837cc04c7dabL,0x573d9f4c43260c07L,0x0c93156278e6cc37L, + 0x94bb725b6b6f7383L } }, + /* 6 */ + { { 0xbbf9b48f720f141cL,0x6199b3cd2df5bc74L,0xdc3f6129411045c4L, + 0xcdd6bbcb2f7dc4efL }, + { 0xcca6700beaf436fdL,0x6f647f6db99326beL,0x0c0fa792014f2522L, + 0xa361bebd4bdae5f6L } }, + /* 7 */ + { { 0x28aa2558597c13c7L,0xc38d635f50b7c3e1L,0x07039aecf3c09d1dL, + 0xba12ca09c4b5292cL }, + { 0x9e408fa459f91dfdL,0x3af43b66ceea07fbL,0x1eceb0899d780b29L, + 0x53ebb99d701fef4bL } }, + /* 8 */ + { { 0x4fe7ee31b0e63d34L,0xf4600572a9e54fabL,0xc0493334d5e7b5a4L, + 0x8589fb9206d54831L }, + { 0xaa70f5cc6583553aL,0x0879094ae25649e5L,0xcc90450710044652L, + 0xebb0696d02541c4fL } }, + /* 9 */ + { { 0x4616ca15ac1647c5L,0xb8127d47c4cf5799L,0xdc666aa3764dfbacL, + 0xeb2820cbd1b27da3L }, + { 0x9406f8d86a87e008L,0xd87dfa9d922378f3L,0x56ed2e4280ccecb2L, + 0x1f28289b55a7da1dL } }, + /* 10 */ + { { 0xabbaa0c03b89da99L,0xa6f2d79eb8284022L,0x27847862b81c05e8L, + 0x337a4b5905e54d63L }, + { 0x3c67500d21f7794aL,0x207005b77d6d7f61L,0x0a5a378104cfd6e8L, + 0x0d65e0d5f4c2fbd6L } }, + /* 11 */ + { { 0xd9d09bbeb5275d38L,0x4268a7450be0a358L,0xf0762ff4973eb265L, + 0xc23da24252f4a232L }, + { 0x5da1b84f0b94520cL,0x09666763b05bd78eL,0x3a4dcb8694d29ea1L, + 0x19de3b8cc790cff1L } }, + /* 12 */ + { { 0x183a716c26c5fe04L,0x3b28de0b3bba1bdbL,0x7432c586a4cb712cL, + 0xe34dcbd491fccbfdL }, + { 0xb408d46baaa58403L,0x9a69748682e97a53L,0x9e39012736aaa8afL, + 0xe7641f447b4e0f7fL } }, + /* 13 */ + { { 0x7d753941df64ba59L,0xd33f10ec0b0242fcL,0x4f06dfc6a1581859L, + 0x4a12df57052a57bfL }, + { 0xbfa6338f9439dbd0L,0xd3c24bd4bde53e1fL,0xfd5e4ffa21f1b314L, + 0x6af5aa93bb5bea46L } }, + /* 14 */ + { { 0xda10b69910c91999L,0x0a24b4402a580491L,0x3e0094b4b8cc2090L, + 0x5fe3475a66a44013L }, + { 0xb0f8cabdf93e7b4bL,0x292b501a7c23f91aL,0x42e889aecd1e6263L, + 0xb544e308ecfea916L } }, + /* 15 */ + { { 0x6478c6e916ddfdceL,0x2c329166f89179e6L,0x4e8d6e764d4e67e1L, + 0xe0b6b2bda6b0c20bL }, + { 0x0d312df2bb7efb57L,0x1aac0dde790c4007L,0xf90336ad679bc944L, + 0x71c023de25a63774L } }, + /* 16 */ + { { 0x62a8c244bfe20925L,0x91c19ac38fdce867L,0x5a96a5d5dd387063L, + 0x61d587d421d324f6L }, + { 0xe87673a2a37173eaL,0x2384800853778b65L,0x10f8441e05bab43eL, + 0xfa11fe124621efbeL } }, + /* 17 */ + { { 0x1c891f2b2cb19ffdL,0x01ba8d5bb1923c23L,0xb6d03d678ac5ca8eL, + 0x586eb04c1f13bedcL }, + { 0x0c35c6e527e8ed09L,0x1e81a33c1819ede2L,0x278fd6c056c652faL, + 0x19d5ac0870864f11L } }, + /* 18 */ + { { 0x1e99f581309a4e1fL,0xab7de71be9270074L,0x26a5ef0befd28d20L, + 0xe7c0073f7f9c563fL }, + { 0x1f6d663a0ef59f76L,0x669b3b5420fcb050L,0xc08c1f7a7a6602d4L, + 0xe08504fec65b3c0aL } }, + /* 19 */ + { { 0xf098f68da031b3caL,0x6d1cab9ee6da6d66L,0x5bfd81fa94f246e8L, + 0x78f018825b0996b4L }, + { 0xb7eefde43a25787fL,0x8016f80d1dccac9bL,0x0cea4877b35bfc36L, + 0x43a773b87e94747aL } }, + /* 20 */ + { { 0x62577734d2b533d5L,0x673b8af6a1bdddc0L,0x577e7c9aa79ec293L, + 0xbb6de651c3b266b1L }, + { 0xe7e9303ab65259b3L,0xd6a0afd3d03a7480L,0xc5ac83d19b3cfc27L, + 0x60b4619a5d18b99bL } }, + /* 21 */ + { { 0xbd6a38e11ae5aa1cL,0xb8b7652b49e73658L,0x0b130014ee5f87edL, + 0x9d0f27b2aeebffcdL }, + { 0xca9246317a730a55L,0x9c955b2fddbbc83aL,0x07c1dfe0ac019a71L, + 0x244a566d356ec48dL } }, + /* 22 */ + { { 0x6db0394aeacf1f96L,0x9f2122a9024c271cL,0x2626ac1b82cbd3b9L, + 0x45e58c873581ef69L }, + { 0xd3ff479da38f9dbcL,0xa8aaf146e888a040L,0x945adfb246e0bed7L, + 0xc040e21cc1e4b7a4L } }, + /* 23 */ + { { 0x847af0006f8117b6L,0x651969ff73a35433L,0x482b35761d9475ebL, + 0x1cdf5c97682c6ec7L }, + { 0x7db775b411f04839L,0x7dbeacf448de1698L,0xb2921dd1b70b3219L, + 0x046755f8a92dff3dL } }, + /* 24 */ + { { 0xcc8ac5d2bce8ffcdL,0x0d53c48b2fe61a82L,0xf6f161727202d6c7L, + 0x046e5e113b83a5f3L }, + { 0xe7b8ff64d8007f01L,0x7fb1ef125af43183L,0x045c5ea635e1a03cL, + 0x6e0106c3303d005bL } }, + /* 25 */ + { { 0x48c7358488dd73b1L,0x7670708f995ed0d9L,0x38385ea8c56a2ab7L, + 0x442594ede901cf1fL }, + { 0xf8faa2c912d4b65bL,0x94c2343b96c90c37L,0xd326e4a15e978d1fL, + 0xa796fa514c2ee68eL } }, + /* 26 */ + { { 0x359fb604823addd7L,0x9e2a6183e56693b3L,0xf885b78e3cbf3c80L, + 0xe4ad2da9c69766e9L }, + { 0x357f7f428e048a61L,0x082d198cc092d9a0L,0xfc3a1af4c03ed8efL, + 0xc5e94046c37b5143L } }, + /* 27 */ + { { 0x476a538c2be75f9eL,0x6fd1a9e8cb123a78L,0xd85e4df0b109c04bL, + 0x63283dafdb464747L }, + { 0xce728cf7baf2df15L,0xe592c4550ad9a7f4L,0xfab226ade834bcc3L, + 0x68bd19ab1981a938L } }, + /* 28 */ + { { 0xc08ead511887d659L,0x3374d5f4b359305aL,0x96986981cfe74fe3L, + 0x495292f53c6fdfd6L }, + { 0x4a878c9e1acec896L,0xd964b210ec5b4484L,0x6696f7e2664d60a7L, + 0x0ec7530d26036837L } }, + /* 29 */ + { { 0x2da13a05ad2687bbL,0xa1f83b6af32e21faL,0x390f5ef51dd4607bL, + 0x0f6207a664863f0bL }, + { 0xbd67e3bb0f138233L,0xdd66b96c272aa718L,0x8ed0040726ec88aeL, + 0xff0db07208ed6dcfL } }, + /* 30 */ + { { 0x749fa1014c95d553L,0xa44052fd5d680a8aL,0x183b4317ff3b566fL, + 0x313b513c88740ea3L }, + { 0xb402e2ac08d11549L,0x071ee10bb4dee21cL,0x26b987dd47f2320eL, + 0x2d3abcf986f19f81L } }, + /* 31 */ + { { 0x4c288501815581a2L,0x9a0a6d56632211afL,0x19ba7a0f0cab2e99L, + 0xc036fa10ded98cdfL }, + { 0x29ae08bac1fbd009L,0x0b68b19006d15816L,0xc2eb32779b9e0d8fL, + 0xa6b2a2c4b6d40194L } }, + /* 32 */ + { { 0xd433e50f6d3549cfL,0x6f33696ffacd665eL,0x695bfdacce11fcb4L, + 0x810ee252af7c9860L }, + { 0x65450fe17159bb2cL,0xf7dfbebe758b357bL,0x2b057e74d69fea72L, + 0xd485717a92731745L } }, + /* 33 */ + { { 0x11741a8af0cb5a98L,0xd3da8f931f3110bfL,0x1994e2cbab382adfL, + 0x6a6045a72f9a604eL }, + { 0x170c0d3fa2b2411dL,0xbe0eb83e510e96e0L,0x3bcc9f738865b3ccL, + 0xd3e45cfaf9e15790L } }, + /* 34 */ + { { 0xce1f69bbe83f7669L,0x09f8ae8272877d6bL,0x9548ae543244278dL, + 0x207755dee3c2c19cL }, + { 0x87bd61d96fef1945L,0x18813cefb12d28c3L,0x9fbcd1d672df64aaL, + 0x48dc5ee57154b00dL } }, + /* 35 */ + { { 0x123790bff7e5a199L,0xe0efb8cf989ccbb7L,0xc27a2bfe0a519c79L, + 0xf2fb0aeddff6f445L }, + { 0x41c09575f0b5025fL,0x550543d740fa9f22L,0x8fa3c8ad380bfbd0L, + 0xa13e9015db28d525L } }, + /* 36 */ + { { 0xf9f7a350a2b65cbcL,0x0b04b9722a464226L,0x265ce241e23f07a1L, + 0x2bf0d6b01497526fL }, + { 0xd3d4dd3f4b216fb7L,0xf7d7b867fbdda26aL,0xaeb7b83f6708505cL, + 0x42a94a5a162fe89fL } }, + /* 37 */ + { { 0x5846ad0beaadf191L,0x0f8a489025a268d7L,0xe8603050494dc1f6L, + 0x2c2dd969c65ede3dL }, + { 0x6d02171d93849c17L,0x460488ba1da250ddL,0x4810c7063c3a5485L, + 0xf437fa1f42c56dbcL } }, + /* 38 */ + { { 0x6aa0d7144a0f7dabL,0x0f0497931776e9acL,0x52c0a050f5f39786L, + 0xaaf45b3354707aa8L }, + { 0x85e37c33c18d364aL,0xd40b9b063e497165L,0xf417168115ec5444L, + 0xcdf6310df4f272bcL } }, + /* 39 */ + { { 0x7473c6238ea8b7efL,0x08e9351885bc2287L,0x419567722bda8e34L, + 0xf0d008bada9e2ff2L }, + { 0x2912671d2414d3b1L,0xb3754985b019ea76L,0x5c61b96d453bcbdbL, + 0x5bd5c2f5ca887b8bL } }, + /* 40 */ + { { 0xef0f469ef49a3154L,0x3e85a5956e2b2e9aL,0x45aaec1eaa924a9cL, + 0xaa12dfc8a09e4719L }, + { 0x26f272274df69f1dL,0xe0e4c82ca2ff5e73L,0xb9d8ce73b7a9dd44L, + 0x6c036e73e48ca901L } }, + /* 41 */ + { { 0x5cfae12a0f6e3138L,0x6966ef0025ad345aL,0x8993c64b45672bc5L, + 0x292ff65896afbe24L }, + { 0xd5250d445e213402L,0xf6580e274392c9feL,0x097b397fda1c72e8L, + 0x644e0c90311b7276L } }, + /* 42 */ + { { 0xe1e421e1a47153f0L,0xb86c3b79920418c9L,0x93bdce87705d7672L, + 0xf25ae793cab79a77L }, + { 0x1f3194a36d869d0cL,0x9d55c8824986c264L,0x49fb5ea3096e945eL, + 0x39b8e65313db0a3eL } }, + /* 43 */ + { { 0x37754200b6fd2e59L,0x35e2c0669255c98fL,0xd9dab21a0e2a5739L, + 0x39122f2f0f19db06L }, + { 0xcfbce1e003cad53cL,0x225b2c0fe65c17e3L,0x72baf1d29aa13877L, + 0x8de80af8ce80ff8dL } }, + /* 44 */ + { { 0xafbea8d9207bbb76L,0x921c7e7c21782758L,0xdfa2b74b1c0436b1L, + 0x871949062e368c04L }, + { 0xb5f928bba3993df5L,0x639d75b5f3b3d26aL,0x011aa78a85b55050L, + 0xfc315e6a5b74fde1L } }, + /* 45 */ + { { 0x561fd41ae8d6ecfaL,0x5f8c44f61aec7f86L,0x98452a7b4924741dL, + 0xe6d4a7adee389088L }, + { 0x60552ed14593c75dL,0x70a70da4dd271162L,0xd2aede937ba2c7dbL, + 0x35dfaf9a9be2ae57L } }, + /* 46 */ + { { 0x6b956fcdaa736636L,0x09f51d97ae2cab7eL,0xfb10bf410f349966L, + 0x1da5c7d71c830d2bL }, + { 0x5c41e4833cce6825L,0x15ad118ff9573c3bL,0xa28552c7f23036b8L, + 0x7077c0fddbf4b9d6L } }, + /* 47 */ + { { 0xbf63ff8d46b9661cL,0xa1dfd36b0d2cfd71L,0x0373e140a847f8f7L, + 0x53a8632ee50efe44L }, + { 0x0976ff68696d8051L,0xdaec0c95c74f468aL,0x62994dc35e4e26bdL, + 0x028ca76d34e1fcc1L } }, + /* 48 */ + { { 0xd11d47dcfc9877eeL,0xc8b36210801d0002L,0xd002c11754c260b6L, + 0x04c17cd86962f046L }, + { 0x6d9bd094b0daddf5L,0xbea2357524ce55c0L,0x663356e672da03b5L, + 0xf7ba4de9fed97474L } }, + /* 49 */ + { { 0xd0dbfa34ebe1263fL,0x5576373571ae7ce6L,0xd244055382a6f523L, + 0xe31f960052131c41L }, + { 0xd1bb9216ea6b6ec6L,0x37a1d12e73c2fc44L,0xc10e7eac89d0a294L, + 0xaa3a6259ce34d47bL } }, + /* 50 */ + { { 0xfbcf9df536f3dcd3L,0x6ceded50d2bf7360L,0x491710fadf504f5bL, + 0x2398dd627e79daeeL }, + { 0xcf4705a36d09569eL,0xea0619bb5149f769L,0xff9c037735f6034cL, + 0x5717f5b21c046210L } }, + /* 51 */ + { { 0x9fe229c921dd895eL,0x8e51850040c28451L,0xfa13d2391d637ecdL, + 0x660a2c560e3c28deL }, + { 0x9cca88aed67fcbd0L,0xc84724780ea9f096L,0x32b2f48172e92b4dL, + 0x624ee54c4f522453L } }, + /* 52 */ + { { 0x09549ce4d897ecccL,0x4d49d1d93f9880aaL,0x723c2423043a7c20L, + 0x4f392afb92bdfbc0L }, + { 0x6969f8fa7de44fd9L,0xb66cfbe457b32156L,0xdb2fa803368ebc3cL, + 0x8a3e7977ccdb399cL } }, + /* 53 */ + { { 0xdde1881f06c4b125L,0xae34e300f6e3ca8cL,0xef6999de5c7a13e9L, + 0x3888d02370c24404L }, + { 0x7628035644f91081L,0x3d9fcf615f015504L,0x1827edc8632cd36eL, + 0xa5e62e4718102336L } }, + /* 54 */ + { { 0x1a825ee32facd6c8L,0x699c635454bcbc66L,0x0ce3edf798df9931L, + 0x2c4768e6466a5adcL }, + { 0xb346ff8c90a64bc9L,0x630a6020e4779f5cL,0xd949d064bc05e884L, + 0x7b5e6441f9e652a0L } }, + /* 55 */ + { { 0x2169422c1d28444aL,0xe996c5d8be136a39L,0x2387afe5fb0c7fceL, + 0xb8af73cb0c8d744aL }, + { 0x5fde83aa338b86fdL,0xfee3f158a58a5cffL,0xc9ee8f6f20ac9433L, + 0xa036395f7f3f0895L } }, + /* 56 */ + { { 0x8c73c6bba10f7770L,0xa6f16d81a12a0e24L,0x100df68251bc2b9fL, + 0x4be36b01875fb533L }, + { 0x9226086e9fb56dbbL,0x306fef8b07e7a4f8L,0xeeaccc0566d52f20L, + 0x8cbc9a871bdc00c0L } }, + /* 57 */ + { { 0xe131895cc0dac4abL,0xa874a440712ff112L,0x6332ae7c6a1cee57L, + 0x44e7553e0c0835f8L }, + { 0x6d503fff7734002dL,0x9d35cb8b0b34425cL,0x95f702760e8738b5L, + 0x470a683a5eb8fc18L } }, + /* 58 */ + { { 0x81b761dc90513482L,0x0287202a01e9276aL,0xcda441ee0ce73083L, + 0x16410690c63dc6efL }, + { 0xf5034a066d06a2edL,0xdd4d7745189b100bL,0xd914ae72ab8218c9L, + 0xd73479fd7abcbb4fL } }, + /* 59 */ + { { 0x7edefb165ad4c6e5L,0x262cf08f5b06d04dL,0x12ed5bb18575cb14L, + 0x816469e30771666bL }, + { 0xd7ab9d79561e291eL,0xeb9daf22c1de1661L,0xf49827eb135e0513L, + 0x0a36dd23f0dd3f9cL } }, + /* 60 */ + { { 0x098d32c741d5533cL,0x7c5f5a9e8684628fL,0x39a228ade349bd11L, + 0xe331dfd6fdbab118L }, + { 0x5100ab686bcc6ed8L,0x7160c3bdef7a260eL,0x9063d9a7bce850d7L, + 0xd3b4782a492e3389L } }, + /* 61 */ + { { 0xa149b6e8f3821f90L,0x92edd9ed66eb7aadL,0x0bb669531a013116L, + 0x7281275a4c86a5bdL }, + { 0x503858f7d3ff47e5L,0x5e1616bc61016441L,0x62b0f11a7dfd9bb1L, + 0x2c062e7ece145059L } }, + /* 62 */ + { { 0xa76f996f0159ac2eL,0x281e7736cbdb2713L,0x2ad6d28808e46047L, + 0x282a35f92c4e7ef1L }, + { 0x9c354b1ec0ce5cd2L,0xcf99efc91379c229L,0x992caf383e82c11eL, + 0xc71cd513554d2abdL } }, + /* 63 */ + { { 0x4885de9c09b578f4L,0x1884e258e3affa7aL,0x8f76b1b759182f1fL, + 0xc50f6740cf47f3a3L }, + { 0xa9c4adf3374b68eaL,0xa406f32369965fe2L,0x2f86a22285a53050L, + 0xb9ecb3a7212958dcL } }, + /* 64 */ + { { 0x56f8410ef4f8b16aL,0x97241afec47b266aL,0x0a406b8e6d9c87c1L, + 0x803f3e02cd42ab1bL }, + { 0x7f0309a804dbec69L,0xa83b85f73bbad05fL,0xc6097273ad8e197fL, + 0xc097440e5067adc1L } }, + /* 65 */ + { { 0x846a56f2c379ab34L,0xa8ee068b841df8d1L,0x20314459176c68efL, + 0xf1af32d5915f1f30L }, + { 0x99c375315d75bd50L,0x837cffbaf72f67bcL,0x0613a41848d7723fL, + 0x23d0f130e2d41c8bL } }, + /* 66 */ + { { 0x857ab6edf41500d9L,0x0d890ae5fcbeada8L,0x52fe864889725951L, + 0xb0288dd6c0a3faddL }, + { 0x85320f30650bcb08L,0x71af6313695d6e16L,0x31f520a7b989aa76L, + 0xffd3724ff408c8d2L } }, + /* 67 */ + { { 0x53968e64b458e6cbL,0x992dad20317a5d28L,0x3814ae0b7aa75f56L, + 0xf5590f4ad78c26dfL }, + { 0x0fc24bd3cf0ba55aL,0x0fc4724a0c778baeL,0x1ce9864f683b674aL, + 0x18d6da54f6f74a20L } }, + /* 68 */ + { { 0xed93e225d5be5a2bL,0x6fe799835934f3c6L,0x4314092622626ffcL, + 0x50bbb4d97990216aL }, + { 0x378191c6e57ec63eL,0x65422c40181dcdb2L,0x41a8099b0236e0f6L, + 0x2b10011801fe49c3L } }, + /* 69 */ + { { 0xfc68b5c59b391593L,0xc385f5a2598270fcL,0x7144f3aad19adcbbL, + 0xdd55899983fbae0cL }, + { 0x93b88b8e74b82ff4L,0xd2e03c4071e734c9L,0x9a7a9eaf43c0322aL, + 0xe6e4c551149d6041L } }, + /* 70 */ + { { 0x55f655bb1e9af288L,0x647e1a64f7ada931L,0x43697e4bcb2820e5L, + 0x51e00db107ed56ffL }, + { 0x43d169b8771c327eL,0x29cdb20b4a96c2adL,0xc07d51f53deb4779L, + 0xe22f424149829177L } }, + /* 71 */ + { { 0xcd45e8f4635f1abbL,0x7edc0cb568538874L,0xc9472c1fb5a8034dL, + 0xf709373d52dc48c9L }, + { 0x401966bba8af30d6L,0x95bf5f4af137b69cL,0x3966162a9361c47eL, + 0xbd52d288e7275b11L } }, + /* 72 */ + { { 0xab155c7a9c5fa877L,0x17dad6727d3a3d48L,0x43f43f9e73d189d8L, + 0xa0d0f8e4c8aa77a6L }, + { 0x0bbeafd8cc94f92dL,0xd818c8be0c4ddb3aL,0x22cc65f8b82eba14L, + 0xa56c78c7946d6a00L } }, + /* 73 */ + { { 0x2962391b0dd09529L,0x803e0ea63daddfcfL,0x2c77351f5b5bf481L, + 0xd8befdf8731a367aL }, + { 0xab919d42fc0157f4L,0xf51caed7fec8e650L,0xcdf9cb4002d48b0aL, + 0x854a68a5ce9f6478L } }, + /* 74 */ + { { 0xdc35f67b63506ea5L,0x9286c489a4fe0d66L,0x3f101d3bfe95cd4dL, + 0x5cacea0b98846a95L }, + { 0xa90df60c9ceac44dL,0x3db29af4354d1c3aL,0x08dd3de8ad5dbabeL, + 0xe4982d1235e4efa9L } }, + /* 75 */ + { { 0x23104a22c34cd55eL,0x58695bb32680d132L,0xfb345afa1fa1d943L, + 0x8046b7f616b20499L }, + { 0xb533581e38e7d098L,0xd7f61e8df46f0b70L,0x30dea9ea44cb78c4L, + 0xeb17ca7b9082af55L } }, + /* 76 */ + { { 0x1751b59876a145b9L,0xa5cf6b0fc1bc71ecL,0xd3e03565392715bbL, + 0x097b00bafab5e131L }, + { 0xaa66c8e9565f69e1L,0x77e8f75ab5be5199L,0x6033ba11da4fd984L, + 0xf95c747bafdbcc9eL } }, + /* 77 */ + { { 0x558f01d3bebae45eL,0xa8ebe9f0c4bc6955L,0xaeb705b1dbc64fc6L, + 0x3512601e566ed837L }, + { 0x9336f1e1fa1161cdL,0x328ab8d54c65ef87L,0x4757eee2724f21e5L, + 0x0ef971236068ab6bL } }, + /* 78 */ + { { 0x02598cf754ca4226L,0x5eede138f8642c8eL,0x48963f74468e1790L, + 0xfc16d9333b4fbc95L }, + { 0xbe96fb31e7c800caL,0x138063312678adaaL,0x3d6244976ff3e8b5L, + 0x14ca4af1b95d7a17L } }, + /* 79 */ + { { 0x7a4771babd2f81d5L,0x1a5f9d6901f7d196L,0xd898bef7cad9c907L, + 0x4057b063f59c231dL }, + { 0xbffd82fe89c05c0aL,0xe4911c6f1dc0df85L,0x3befccaea35a16dbL, + 0x1c3b5d64f1330b13L } }, + /* 80 */ + { { 0x5fe14bfe80ec21feL,0xf6ce116ac255be82L,0x98bc5a072f4a5d67L, + 0xfad27148db7e63afL }, + { 0x90c0b6ac29ab05b3L,0x37a9a83c4e251ae6L,0x0a7dc875c2aade7dL, + 0x77387de39f0e1a84L } }, + /* 81 */ + { { 0x1e9ecc49a56c0dd7L,0xa5cffcd846086c74L,0x8f7a1408f505aeceL, + 0xb37b85c0bef0c47eL }, + { 0x3596b6e4cc0e6a8fL,0xfd6d4bbf6b388f23L,0xaba453fac39cef4eL, + 0x9c135ac8f9f628d5L } }, + /* 82 */ + { { 0x32aa320284e35743L,0x320d6ab185a3cdefL,0xb821b1761df19819L, + 0x5721361fc433851fL }, + { 0x1f0db36a71fc9168L,0x5f98ba735e5c403cL,0xf64ca87e37bcd8f5L, + 0xdcbac3c9e6bb11bdL } }, + /* 83 */ + { { 0xf01d99684518cbe2L,0xd242fc189c9eb04eL,0x727663c7e47feebfL, + 0xb8c1c89e2d626862L }, + { 0x51a58bddc8e1d569L,0x563809c8b7d88cd0L,0x26c27fd9f11f31ebL, + 0x5d23bbda2f9422d4L } }, + /* 84 */ + { { 0x0a1c729495c8f8beL,0x2961c4803bf362bfL,0x9e418403df63d4acL, + 0xc109f9cb91ece900L }, + { 0xc2d095d058945705L,0xb9083d96ddeb85c0L,0x84692b8d7a40449bL, + 0x9bc3344f2eee1ee1L } }, + /* 85 */ + { { 0x0d5ae35642913074L,0x55491b2748a542b1L,0x469ca665b310732aL, + 0x29591d525f1a4cc1L }, + { 0xe76f5b6bb84f983fL,0xbe7eef419f5f84e1L,0x1200d49680baa189L, + 0x6376551f18ef332cL } }, + /* 86 */ + { { 0xbda5f14e562976ccL,0x22bca3e60ef12c38L,0xbbfa30646cca9852L, + 0xbdb79dc808e2987aL }, + { 0xfd2cb5c9cb06a772L,0x38f475aafe536dceL,0xc2a3e0227c2b5db8L, + 0x8ee86001add3c14aL } }, + /* 87 */ + { { 0xcbe96981a4ade873L,0x7ee9aa4dc4fba48cL,0x2cee28995a054ba5L, + 0x92e51d7a6f77aa4bL }, + { 0x948bafa87190a34dL,0xd698f75bf6bd1ed1L,0xd00ee6e30caf1144L, + 0x5182f86f0a56aaaaL } }, + /* 88 */ + { { 0xfba6212c7a4cc99cL,0xff609b683e6d9ca1L,0x5dbb27cb5ac98c5aL, + 0x91dcab5d4073a6f2L }, + { 0x01b6cc3d5f575a70L,0x0cb361396f8d87faL,0x165d4e8c89981736L, + 0x17a0cedb97974f2bL } }, + /* 89 */ + { { 0x38861e2a076c8d3aL,0x701aad39210f924bL,0x94d0eae413a835d9L, + 0x2e8ce36c7f4cdf41L }, + { 0x91273dab037a862bL,0x01ba9bb760e4c8faL,0xf964538833baf2ddL, + 0xf4ccc6cb34f668f3L } }, + /* 90 */ + { { 0x44ef525cf1f79687L,0x7c59549592efa815L,0xe1231741a5c78d29L, + 0xac0db4889a0df3c9L }, + { 0x86bfc711df01747fL,0x592b9358ef17df13L,0xe5880e4f5ccb6bb5L, + 0x95a64a6194c974a2L } }, + /* 91 */ + { { 0x72c1efdac15a4c93L,0x40269b7382585141L,0x6a8dfb1c16cb0badL, + 0x231e54ba29210677L }, + { 0xa70df9178ae6d2dcL,0x4d6aa63f39112918L,0xf627726b5e5b7223L, + 0xab0be032d8a731e1L } }, + /* 92 */ + { { 0x097ad0e98d131f2dL,0x637f09e33b04f101L,0x1ac86196d5e9a748L, + 0xf1bcc8802cf6a679L }, + { 0x25c69140e8daacb4L,0x3c4e405560f65009L,0x591cc8fc477937a6L, + 0x851694695aebb271L } }, + /* 93 */ + { { 0xde35c143f1dcf593L,0x78202b29b018be3bL,0xe9cdadc29bdd9d3dL, + 0x8f67d9d2daad55d8L }, + { 0x841116567481ea5fL,0xe7d2dde9e34c590cL,0xffdd43f405053fa8L, + 0xf84572b9c0728b5dL } }, + /* 94 */ + { { 0x5e1a7a7197af71c9L,0xa14494447a736565L,0xa1b4ae070e1d5063L, + 0xedee2710616b2c19L }, + { 0xb2f034f511734121L,0x1cac6e554a25e9f0L,0x8dc148f3a40c2ecfL, + 0x9fd27e9b44ebd7f4L } }, + /* 95 */ + { { 0x3cc7658af6e2cb16L,0xe3eb7d2cfe5919b6L,0x5a8c5816168d5583L, + 0xa40c2fb6958ff387L }, + { 0x8c9ec560fedcc158L,0x7ad804c655f23056L,0xd93967049a307e12L, + 0x99bc9bb87dc6decfL } }, + /* 96 */ + { { 0x84a9521d927dafc6L,0x52c1fb695c09cd19L,0x9d9581a0f9366ddeL, + 0x9abe210ba16d7e64L }, + { 0x480af84a48915220L,0xfa73176a4dd816c6L,0xc7d539871681ca5aL, + 0x7881c25787f344b0L } }, + /* 97 */ + { { 0x93399b51e0bcf3ffL,0x0d02cbc5127f74f6L,0x8fb465a2dd01d968L, + 0x15e6e319a30e8940L }, + { 0x646d6e0d3e0e05f4L,0xfad7bddc43588404L,0xbe61c7d1c4f850d3L, + 0x0e55facf191172ceL } }, + /* 98 */ + { { 0x7e9d9806f8787564L,0x1a33172131e85ce6L,0x6b0158cab819e8d6L, + 0xd73d09766fe96577L }, + { 0x424834251eb7206eL,0xa519290fc618bb42L,0x5dcbb8595e30a520L, + 0x9250a3748f15a50bL } }, + /* 99 */ + { { 0xcaff08f8be577410L,0xfd408a035077a8c6L,0xf1f63289ec0a63a4L, + 0x77414082c1cc8c0bL }, + { 0x05a40fa6eb0991cdL,0xc1ca086649fdc296L,0x3a68a3c7b324fd40L, + 0x8cb04f4d12eb20b9L } }, + /* 100 */ + { { 0xb1c2d0556906171cL,0x9073e9cdb0240c3fL,0xdb8e6b4fd8906841L, + 0xe4e429ef47123b51L }, + { 0x0b8dd53c38ec36f4L,0xf9d2dc01ff4b6a27L,0x5d066e07879a9a48L, + 0x37bca2ff3c6e6552L } }, + /* 101 */ + { { 0x4cd2e3c7df562470L,0x44f272a2c0964ac9L,0x7c6d5df980c793beL, + 0x59913edc3002b22aL }, + { 0x7a139a835750592aL,0x99e01d80e783de02L,0xcf8c0375ea05d64fL, + 0x43786e4ab013e226L } }, + /* 102 */ + { { 0xff32b0ed9e56b5a6L,0x0750d9a6d9fc68f9L,0xec15e845597846a7L, + 0x8638ca98b7e79e7aL }, + { 0x2f5ae0960afc24b2L,0x05398eaf4dace8f2L,0x3b765dd0aecba78fL, + 0x1ecdd36a7b3aa6f0L } }, + /* 103 */ + { { 0x5d3acd626c5ff2f3L,0xa2d516c02873a978L,0xad94c9fad2110d54L, + 0xd85d0f85d459f32dL }, + { 0x9f700b8d10b11da3L,0xd2c22c30a78318c4L,0x556988f49208decdL, + 0xa04f19c3b4ed3c62L } }, + /* 104 */ + { { 0x087924c8ed7f93bdL,0xcb64ac5d392f51f6L,0x7cae330a821b71afL, + 0x92b2eeea5c0950b0L }, + { 0x85ac4c9485b6e235L,0xab2ca4a92936c0f0L,0x80faa6b3e0508891L, + 0x1ee782215834276cL } }, + /* 105 */ + { { 0xa60a2e00e63e79f7L,0xf590e7b2f399d906L,0x9021054a6607c09dL, + 0xf3f2ced857a6e150L }, + { 0x200510f3f10d9b55L,0x9d2fcfacd8642648L,0xe5631aa7e8bd0e7cL, + 0x0f56a4543da3e210L } }, + /* 106 */ + { { 0x5b21bffa1043e0dfL,0x6c74b6cc9c007e6dL,0x1a656ec0d4a8517aL, + 0xbd8f17411969e263L }, + { 0x8a9bbb86beb7494aL,0x1567d46f45f3b838L,0xdf7a12a7a4e5a79aL, + 0x2d1a1c3530ccfa09L } }, + /* 107 */ + { { 0x192e3813506508daL,0x336180c4a1d795a7L,0xcddb59497a9944b3L, + 0xa107a65eb91fba46L }, + { 0xe6d1d1c50f94d639L,0x8b4af3758a58b7d7L,0x1a7c5584bd37ca1cL, + 0x183d760af87a9af2L } }, + /* 108 */ + { { 0x29d697110dde59a4L,0xf1ad8d070e8bef87L,0x229b49634f2ebe78L, + 0x1d44179dc269d754L }, + { 0xb32dc0cf8390d30eL,0x0a3b27530de8110cL,0x31af1dc52bc0339aL, + 0x771f9cc29606d262L } }, + /* 109 */ + { { 0x99993e7785040739L,0x44539db98026a939L,0xcf40f6f2f5f8fc26L, + 0x64427a310362718eL }, + { 0x4f4f2d8785428aa8L,0x7b7adc3febfb49a8L,0x201b2c6df23d01acL, + 0x49d9b7496ae90d6dL } }, + /* 110 */ + { { 0xcc78d8bc435d1099L,0x2adbcd4e8e8d1a08L,0x02c2e2a02cb68a41L, + 0x9037d81b3f605445L }, + { 0x7cdbac27074c7b61L,0xfe2031ab57bfd72eL,0x61ccec96596d5352L, + 0x08c3de6a7cc0639cL } }, + /* 111 */ + { { 0x20fdd020f6d552abL,0x56baff9805cd81f1L,0x06fb7c3e91351291L, + 0xc690944245796b2fL }, + { 0x17b3ae9c41231bd1L,0x1eac6e875cc58205L,0x208837abf9d6a122L, + 0x3fa3db02cafe3ac0L } }, + /* 112 */ + { { 0xd75a3e6505058880L,0x7da365ef643943f2L,0x4147861cfab24925L, + 0xc5c4bdb0fdb808ffL }, + { 0x73513e34b272b56bL,0xc8327e9511b9043aL,0xfd8ce37df8844969L, + 0x2d56db9446c2b6b5L } }, + /* 113 */ + { { 0x2461782fff46ac6bL,0xd19f792607a2e425L,0xfafea3c409a48de1L, + 0x0f56bd9de503ba42L }, + { 0x137d4ed1345cda49L,0x821158fc816f299dL,0xe7c6a54aaeb43402L, + 0x4003bb9d1173b5f1L } }, + /* 114 */ + { { 0x3b8e8189a0803387L,0xece115f539cbd404L,0x4297208dd2877f21L, + 0x53765522a07f2f9eL }, + { 0xa4980a21a8a4182dL,0xa2bbd07a3219df79L,0x674d0a2e1a19a2d4L, + 0x7a056f586c5d4549L } }, + /* 115 */ + { { 0x646b25589d8a2a47L,0x5b582948c3df2773L,0x51ec000eabf0d539L, + 0x77d482f17a1a2675L }, + { 0xb8a1bd9587853948L,0xa6f817bd6cfbffeeL,0xab6ec05780681e47L, + 0x4115012b2b38b0e4L } }, + /* 116 */ + { { 0x3c73f0f46de28cedL,0x1d5da7609b13ec47L,0x61b8ce9e6e5c6392L, + 0xcdf04572fbea0946L }, + { 0x1cb3c58b6c53c3b0L,0x97fe3c10447b843cL,0xfb2b8ae12cb9780eL, + 0xee703dda97383109L } }, + /* 117 */ + { { 0x34515140ff57e43aL,0xd44660d3b1b811b8L,0x2b3b5dff8f42b986L, + 0x2a0ad89da162ce21L }, + { 0x64e4a6946bc277baL,0xc788c954c141c276L,0x141aa64ccabf6274L, + 0xd62d0b67ac2b4659L } }, + /* 118 */ + { { 0x39c5d87b2c054ac4L,0x57005859f27df788L,0xedf7cbf3b18128d6L, + 0xb39a23f2991c2426L }, + { 0x95284a15f0b16ae5L,0x0c6a05b1a136f51bL,0x1d63c137f2700783L, + 0x04ed0092c0674cc5L } }, + /* 119 */ + { { 0x1f4185d19ae90393L,0x3047b4294a3d64e6L,0xae0001a69854fc14L, + 0xa0a91fc10177c387L }, + { 0xff0a3f01ae2c831eL,0xbb76ae822b727e16L,0x8f12c8a15a3075b4L, + 0x084cf9889ed20c41L } }, + /* 120 */ + { { 0xd98509defca6becfL,0x2fceae807dffb328L,0x5d8a15c44778e8b9L, + 0xd57955b273abf77eL }, + { 0x210da79e31b5d4f1L,0xaa52f04b3cfa7a1cL,0xd4d12089dc27c20bL, + 0x8e14ea4202d141f1L } }, + /* 121 */ + { { 0xeed50345f2897042L,0x8d05331f43402c4aL,0xc8d9c194c8bdfb21L, + 0x597e1a372aa4d158L }, + { 0x0327ec1acf0bd68cL,0x6d4be0dcab024945L,0x5b9c8d7ac9fe3e84L, + 0xca3f0236199b4deaL } }, + /* 122 */ + { { 0x592a10b56170bd20L,0x0ea897f16d3f5de7L,0xa3363ff144b2ade2L, + 0xbde7fd7e309c07e4L }, + { 0x516bb6d2b8f5432cL,0x210dc1cbe043444bL,0x3db01e6ff8f95b5aL, + 0xb623ad0e0a7dd198L } }, + /* 123 */ + { { 0xa75bd67560c7b65bL,0xab8c559023a4a289L,0xf8220fd0d7b26795L, + 0xd6aa2e4658ec137bL }, + { 0x10abc00b5138bb85L,0x8c31d121d833a95cL,0xb24ff00b1702a32eL, + 0x111662e02dcc513aL } }, + /* 124 */ + { { 0x78114015efb42b87L,0xbd9f5d701b6c4dffL,0x66ecccd7a7d7c129L, + 0xdb3ee1cb94b750f8L }, + { 0xb26f3db0f34837cfL,0xe7eed18bb9578d4fL,0x5d2cdf937c56657dL, + 0x886a644252206a59L } }, + /* 125 */ + { { 0x3c234cfb65b569eaL,0x20011141f72119c1L,0x8badc85da15a619eL, + 0xa70cf4eb018a17bcL }, + { 0x224f97ae8c4a6a65L,0x36e5cf270134378fL,0xbe3a609e4f7e0960L, + 0xaa4772abd1747b77L } }, + /* 126 */ + { { 0x676761317aa60cc0L,0xc79163610368115fL,0xded98bb4bbc1bb5aL, + 0x611a6ddc30faf974L }, + { 0x30e78cbcc15ee47aL,0x2e8962824e0d96a5L,0x36f35adf3dd9ed88L, + 0x5cfffaf816429c88L } }, + /* 127 */ + { { 0xc0d54cff9b7a99cdL,0x7bf3b99d843c45a1L,0x038a908f62c739e1L, + 0x6e5a6b237dc1994cL }, + { 0xef8b454e0ba5db77L,0xb7b8807facf60d63L,0xe591c0c676608378L, + 0x481a238d242dabccL } }, + /* 128 */ + { { 0xe3417bc035d0b34aL,0x440b386b8327c0a7L,0x8fb7262dac0362d1L, + 0x2c41114ce0cdf943L }, + { 0x2ba5cef1ad95a0b1L,0xc09b37a867d54362L,0x26d6cdd201e486c9L, + 0x20477abf42ff9297L } }, + /* 129 */ + { { 0x2f75173c18d65dbfL,0x77bf940e339edad8L,0x7022d26bdcf1001cL, + 0xac66409ac77396b6L }, + { 0x8b0bb36fc6261cc3L,0x213f7bc9190e7e90L,0x6541cebaa45e6c10L, + 0xce8e6975cc122f85L } }, + /* 130 */ + { { 0x0f121b41bc0a67d2L,0x62d4760a444d248aL,0x0e044f1d659b4737L, + 0x08fde365250bb4a8L }, + { 0xaceec3da848bf287L,0xc2a62182d3369d6eL,0x3582dfdc92449482L, + 0x2f7e2fd2565d6cd7L } }, + /* 131 */ + { { 0xae4b92dbc3770fa7L,0x095e8d5c379043f9L,0x54f34e9d17761171L, + 0xc65be92e907702aeL }, + { 0x2758a303f6fd0a40L,0xe7d822e3bcce784bL,0x7ae4f5854f9767bfL, + 0x4bff8e47d1193b3aL } }, + /* 132 */ + { { 0xcd41d21f00ff1480L,0x2ab8fb7d0754db16L,0xac81d2efbbe0f3eaL, + 0x3e4e4ae65772967dL }, + { 0x7e18f36d3c5303e6L,0x3bd9994b92262397L,0x9ed70e261324c3c0L, + 0x5388aefd58ec6028L } }, + /* 133 */ + { { 0xad1317eb5e5d7713L,0x09b985ee75de49daL,0x32f5bc4fc74fb261L, + 0x5cf908d14f75be0eL }, + { 0x760435108e657b12L,0xbfd421a5b96ed9e6L,0x0e29f51f8970ccc2L, + 0xa698ba4060f00ce2L } }, + /* 134 */ + { { 0x73db1686ef748fecL,0xe6e755a27e9d2cf9L,0x630b6544ce265effL, + 0xb142ef8a7aebad8dL }, + { 0xad31af9f17d5770aL,0x66af3b672cb3412fL,0x6bd60d1bdf3359deL, + 0xd1896a9658515075L } }, + /* 135 */ + { { 0xec5957ab33c41c08L,0x87de94ac5468e2e1L,0x18816b73ac472f6cL, + 0x267b0e0b7981da39L }, + { 0x6e554e5d8e62b988L,0xd8ddc755116d21e7L,0x4610faf03d2a6f99L, + 0xb54e287aa1119393L } }, + /* 136 */ + { { 0x0a0122b5178a876bL,0x51ff96ff085104b4L,0x050b31ab14f29f76L, + 0x84abb28b5f87d4e6L }, + { 0xd5ed439f8270790aL,0x2d6cb59d85e3f46bL,0x75f55c1b6c1e2212L, + 0xe5436f6717655640L } }, + /* 137 */ + { { 0x53f9025e2286e8d5L,0x353c95b4864453beL,0xd832f5bde408e3a0L, + 0x0404f68b5b9ce99eL }, + { 0xcad33bdea781e8e5L,0x3cdf5018163c2f5bL,0x575769600119caa3L, + 0x3a4263df0ac1c701L } }, + /* 138 */ + { { 0xc2965ecc9aeb596dL,0x01ea03e7023c92b4L,0x4704b4b62e013961L, + 0x0ca8fd3f905ea367L }, + { 0x92523a42551b2b61L,0x1eb7a89c390fcd06L,0xe7f1d2be0392a63eL, + 0x96dca2644ddb0c33L } }, + /* 139 */ + { { 0x203bb43a387510afL,0x846feaa8a9a36a01L,0xd23a57702f950378L, + 0x4363e2123aad59dcL }, + { 0xca43a1c740246a47L,0xb362b8d2e55dd24dL,0xf9b086045d8faf96L, + 0x840e115cd8bb98c4L } }, + /* 140 */ + { { 0xf12205e21023e8a7L,0xc808a8cdd8dc7a0bL,0xe292a272163a5ddfL, + 0x5e0d6abd30ded6d4L }, + { 0x07a721c27cfc0f64L,0x42eec01d0e55ed88L,0x26a7bef91d1f9db2L, + 0x7dea48f42945a25aL } }, + /* 141 */ + { { 0xabdf6f1ce5060a81L,0xe79f9c72f8f95615L,0xcfd36c5406ac268bL, + 0xabc2a2beebfd16d1L }, + { 0x8ac66f91d3e2eac7L,0x6f10ba63d2dd0466L,0x6790e3770282d31bL, + 0x4ea353946c7eefc1L } }, + /* 142 */ + { { 0xed8a2f8d5266309dL,0x0a51c6c081945a3eL,0xcecaf45a578c5dc1L, + 0x3a76e6891c94ffc3L }, + { 0x9aace8a47d7b0d0fL,0x963ace968f584a5fL,0x51a30c724e697fbeL, + 0x8212a10a465e6464L } }, + /* 143 */ + { { 0xef7c61c3cfab8caaL,0x18eb8e840e142390L,0xcd1dff677e9733caL, + 0xaa7cab71599cb164L }, + { 0x02fc9273bc837bd1L,0xc06407d0c36af5d7L,0x17621292f423da49L, + 0x40e38073fe0617c3L } }, + /* 144 */ + { { 0xf4f80824a7bf9b7cL,0x365d23203fbe30d0L,0xbfbe532097cf9ce3L, + 0xe3604700b3055526L }, + { 0x4dcb99116cc6c2c7L,0x72683708ba4cbee6L,0xdcded434637ad9ecL, + 0x6542d677a3dee15fL } }, + /* 145 */ + { { 0x3f32b6d07b6c377aL,0x6cb03847903448beL,0xd6fdd3a820da8af7L, + 0xa6534aee09bb6f21L }, + { 0x30a1780d1035facfL,0x35e55a339dcb47e6L,0x6ea50fe1c447f393L, + 0xf3cb672fdc9aef22L } }, + /* 146 */ + { { 0xeb3719fe3b55fd83L,0xe0d7a46c875ddd10L,0x33ac9fa905cea784L, + 0x7cafaa2eaae870e7L }, + { 0x9b814d041d53b338L,0xe0acc0a0ef87e6c6L,0xfb93d10811672b0fL, + 0x0aab13c1b9bd522eL } }, + /* 147 */ + { { 0xddcce278d2681297L,0xcb350eb1b509546aL,0x2dc431737661aaf2L, + 0x4b91a602847012e9L }, + { 0xdcff109572f8ddcfL,0x08ebf61e9a911af4L,0x48f4360ac372430eL, + 0x49534c5372321cabL } }, + /* 148 */ + { { 0x83df7d71f07b7e9dL,0xa478efa313cd516fL,0x78ef264b6c047ee3L, + 0xcaf46c4fd65ac5eeL }, + { 0xa04d0c7792aa8266L,0xedf45466913684bbL,0x56e65168ae4b16b0L, + 0x14ce9e5704c6770fL } }, + /* 149 */ + { { 0x99445e3e965e8f91L,0xd3aca1bacb0f2492L,0xd31cc70f90c8a0a0L, + 0x1bb708a53e4c9a71L }, + { 0xd5ca9e69558bdd7aL,0x734a0508018a26b1L,0xb093aa714c9cf1ecL, + 0xf9d126f2da300102L } }, + /* 150 */ + { { 0x749bca7aaff9563eL,0xdd077afeb49914a0L,0xe27a0311bf5f1671L, + 0x807afcb9729ecc69L }, + { 0x7f8a9337c9b08b77L,0x86c3a785443c7e38L,0x85fafa59476fd8baL, + 0x751adcd16568cd8cL } }, + /* 151 */ + { { 0x8aea38b410715c0dL,0xd113ea718f7697f7L,0x665eab1493fbf06dL, + 0x29ec44682537743fL }, + { 0x3d94719cb50bebbcL,0x399ee5bfe4505422L,0x90cd5b3a8d2dedb1L, + 0xff9370e392a4077dL } }, + /* 152 */ + { { 0x59a2d69bc6b75b65L,0x4188f8d5266651c5L,0x28a9f33e3de9d7d2L, + 0x9776478ba2a9d01aL }, + { 0x8852622d929af2c7L,0x334f5d6d4e690923L,0xce6cc7e5a89a51e9L, + 0x74a6313fac2f82faL } }, + /* 153 */ + { { 0xb2f4dfddb75f079cL,0x85b07c9518e36fbbL,0x1b6cfcf0e7cd36ddL, + 0xab75be150ff4863dL }, + { 0x81b367c0173fc9b7L,0xb90a7420d2594fd0L,0x15fdbf03c4091236L, + 0x4ebeac2e0b4459f6L } }, + /* 154 */ + { { 0xeb6c5fe75c9f2c53L,0xd25220118eae9411L,0xc8887633f95ac5d8L, + 0xdf99887b2c1baffcL }, + { 0xbb78eed2850aaecbL,0x9d49181b01d6a272L,0x978dd511b1cdbcacL, + 0x27b040a7779f4058L } }, + /* 155 */ + { { 0x90405db7f73b2eb2L,0xe0df85088e1b2118L,0x501b71525962327eL, + 0xb393dd37e4cfa3f5L }, + { 0xa1230e7b3fd75165L,0xd66344c2bcd33554L,0x6c36f1be0f7b5022L, + 0x09588c12d0463419L } }, + /* 156 */ + { { 0xe086093f02601c3bL,0xfb0252f8cf5c335fL,0x955cf280894aff28L, + 0x81c879a9db9f648bL }, + { 0x040e687cc6f56c51L,0xfed471693f17618cL,0x44f88a419059353bL, + 0xfa0d48f55fc11bc4L } }, + /* 157 */ + { { 0xbc6e1c9de1608e4dL,0x010dda113582822cL,0xf6b7ddc1157ec2d7L, + 0x8ea0e156b6a367d6L }, + { 0xa354e02f2383b3b4L,0x69966b943f01f53cL,0x4ff6632b2de03ca5L, + 0x3f5ab924fa00b5acL } }, + /* 158 */ + { { 0x337bb0d959739efbL,0xc751b0f4e7ebec0dL,0x2da52dd6411a67d1L, + 0x8bc768872b74256eL }, + { 0xa5be3b7282d3d253L,0xa9f679a1f58d779fL,0xa1cac168e16767bbL, + 0xb386f19060fcf34fL } }, + /* 159 */ + { { 0x31f3c1352fedcfc2L,0x5396bf6262f8af0dL,0x9a02b4eae57288c2L, + 0x4cb460f71b069c4dL }, + { 0xae67b4d35b8095eaL,0x92bbf8596fc07603L,0xe1475f66b614a165L, + 0x52c0d50895ef5223L } }, + /* 160 */ + { { 0x231c210e15339848L,0xe87a28e870778c8dL,0x9d1de6616956e170L, + 0x4ac3c9382bb09c0bL }, + { 0x19be05516998987dL,0x8b2376c4ae09f4d6L,0x1de0b7651a3f933dL, + 0x380d94c7e39705f4L } }, + /* 161 */ + { { 0x01a355aa81542e75L,0x96c724a1ee01b9b7L,0x6b3a2977624d7087L, + 0x2ce3e171de2637afL }, + { 0xcfefeb49f5d5bc1aL,0xa655607e2777e2b5L,0x4feaac2f9513756cL, + 0x2e6cd8520b624e4dL } }, + /* 162 */ + { { 0x3685954b8c31c31dL,0x68533d005bf21a0cL,0x0bd7626e75c79ec9L, + 0xca17754742c69d54L }, + { 0xcc6edafff6d2dbb2L,0xfd0d8cbd174a9d18L,0x875e8793aa4578e8L, + 0xa976a7139cab2ce6L } }, + /* 163 */ + { { 0x0a651f1b93fb353dL,0xd75cab8b57fcfa72L,0xaa88cfa731b15281L, + 0x8720a7170a1f4999L }, + { 0x8c3e8d37693e1b90L,0xd345dc0b16f6dfc3L,0x8ea8d00ab52a8742L, + 0x9719ef29c769893cL } }, + /* 164 */ + { { 0x820eed8d58e35909L,0x9366d8dc33ddc116L,0xd7f999d06e205026L, + 0xa5072976e15704c1L }, + { 0x002a37eac4e70b2eL,0x84dcf6576890aa8aL,0xcd71bf18645b2a5cL, + 0x99389c9df7b77725L } }, + /* 165 */ + { { 0x238c08f27ada7a4bL,0x3abe9d03fd389366L,0x6b672e89766f512cL, + 0xa88806aa202c82e4L }, + { 0x6602044ad380184eL,0xa8cb78c4126a8b85L,0x79d670c0ad844f17L, + 0x0043bffb4738dcfeL } }, + /* 166 */ + { { 0x8d59b5dc36d5192eL,0xacf885d34590b2afL,0x83566d0a11601781L, + 0x52f3ef01ba6c4866L }, + { 0x3986732a0edcb64dL,0x0a482c238068379fL,0x16cbe5fa7040f309L, + 0x3296bd899ef27e75L } }, + /* 167 */ + { { 0x476aba89454d81d7L,0x9eade7ef51eb9b3cL,0x619a21cd81c57986L, + 0x3b90febfaee571e9L }, + { 0x9393023e5496f7cbL,0x55be41d87fb51bc4L,0x03f1dd4899beb5ceL, + 0x6e88069d9f810b18L } }, + /* 168 */ + { { 0xce37ab11b43ea1dbL,0x0a7ff1a95259d292L,0x851b02218f84f186L, + 0xa7222beadefaad13L }, + { 0xa2ac78ec2b0a9144L,0x5a024051f2fa59c5L,0x91d1eca56147ce38L, + 0xbe94d523bc2ac690L } }, + /* 169 */ + { { 0x72f4945e0b226ce7L,0xb8afd747967e8b70L,0xedea46f185a6c63eL, + 0x7782defe9be8c766L }, + { 0x760d2aa43db38626L,0x460ae78776f67ad1L,0x341b86fc54499cdbL, + 0x03838567a2892e4bL } }, + /* 170 */ + { { 0x2d8daefd79ec1a0fL,0x3bbcd6fdceb39c97L,0xf5575ffc58f61a95L, + 0xdbd986c4adf7b420L }, + { 0x81aa881415f39eb7L,0x6ee2fcf5b98d976cL,0x5465475dcf2f717dL, + 0x8e24d3c46860bbd0L } }, + /* 171 */ + { { 0x749d8e549a587390L,0x12bb194f0cbec588L,0x46e07da4b25983c6L, + 0x541a99c4407bafc8L }, + { 0xdb241692624c8842L,0x6044c12ad86c05ffL,0xc59d14b44f7fcf62L, + 0xc0092c49f57d35d1L } }, + /* 172 */ + { { 0xd3cc75c3df2e61efL,0x7e8841c82e1b35caL,0xc62d30d1909f29f4L, + 0x75e406347286944dL }, + { 0xe7d41fc5bbc237d0L,0xc9537bf0ec4f01c9L,0x91c51a16282bd534L, + 0x5b7cb658c7848586L } }, + /* 173 */ + { { 0x964a70848a28ead1L,0x802dc508fd3b47f6L,0x9ae4bfd1767e5b39L, + 0x7ae13eba8df097a1L }, + { 0xfd216ef8eadd384eL,0x0361a2d9b6b2ff06L,0x204b98784bcdb5f3L, + 0x787d8074e2a8e3fdL } }, + /* 174 */ + { { 0xc5e25d6b757fbb1cL,0xe47bddb2ca201debL,0x4a55e9a36d2233ffL, + 0x5c2228199ef28484L }, + { 0x773d4a8588315250L,0x21b21a2b827097c1L,0xab7c4ea1def5d33fL, + 0xe45d37abbaf0f2b0L } }, + /* 175 */ + { { 0xd2df1e3428511c8aL,0xebb229c8bdca6cd3L,0x578a71a7627c39a7L, + 0xed7bc12284dfb9d3L }, + { 0xcf22a6df93dea561L,0x5443f18dd48f0ed1L,0xd8b861405bad23e8L, + 0xaac97cc945ca6d27L } }, + /* 176 */ + { { 0xeb54ea74a16bd00aL,0xd839e9adf5c0bcc1L,0x092bb7f11f9bfc06L, + 0x318f97b31163dc4eL }, + { 0xecc0c5bec30d7138L,0x44e8df23abc30220L,0x2bb7972fb0223606L, + 0xfa41faa19a84ff4dL } }, + /* 177 */ + { { 0x4402d974a6642269L,0xc81814ce9bb783bdL,0x398d38e47941e60bL, + 0x38bb6b2c1d26e9e2L }, + { 0xc64e4a256a577f87L,0x8b52d253dc11fe1cL,0xff336abf62280728L, + 0x94dd0905ce7601a5L } }, + /* 178 */ + { { 0x156cf7dcde93f92aL,0xa01333cb89b5f315L,0x02404df9c995e750L, + 0x92077867d25c2ae9L }, + { 0xe2471e010bf39d44L,0x5f2c902096bb53d7L,0x4c44b7b35c9c3d8fL, + 0x81e8428bd29beb51L } }, + /* 179 */ + { { 0x6dd9c2bac477199fL,0x8cb8eeee6b5ecdd9L,0x8af7db3fee40fd0eL, + 0x1b94ab62dbbfa4b1L }, + { 0x44f0d8b3ce47f143L,0x51e623fc63f46163L,0xf18f270fcc599383L, + 0x06a38e28055590eeL } }, + /* 180 */ + { { 0x2e5b0139b3355b49L,0x20e26560b4ebf99bL,0xc08ffa6bd269f3dcL, + 0xa7b36c2083d9d4f8L }, + { 0x64d15c3a1b3e8830L,0xd5fceae1a89f9c0bL,0xcfeee4a2e2d16930L, + 0xbe54c6b4a2822a20L } }, + /* 181 */ + { { 0xd6cdb3df8d91167cL,0x517c3f79e7a6625eL,0x7105648f346ac7f4L, + 0xbf30a5abeae022bbL }, + { 0x8e7785be93828a68L,0x5161c3327f3ef036L,0xe11b5feb592146b2L, + 0xd1c820de2732d13aL } }, + /* 182 */ + { { 0x043e13479038b363L,0x58c11f546b05e519L,0x4fe57abe6026cad1L, + 0xb7d17bed68a18da3L }, + { 0x44ca5891e29c2559L,0x4f7a03765bfffd84L,0x498de4af74e46948L, + 0x3997fd5e6412cc64L } }, + /* 183 */ + { { 0xf20746828bd61507L,0x29e132d534a64d2aL,0xffeddfb08a8a15e3L, + 0x0eeb89293c6c13e8L }, + { 0xe9b69a3ea7e259f8L,0xce1db7e6d13e7e67L,0x277318f6ad1fa685L, + 0x228916f8c922b6efL } }, + /* 184 */ + { { 0x959ae25b0a12ab5bL,0xcc11171f957bc136L,0x8058429ed16e2b0cL, + 0xec05ad1d6e93097eL }, + { 0x157ba5beac3f3708L,0x31baf93530b59d77L,0x47b55237118234e5L, + 0x7d3141567ff11b37L } }, + /* 185 */ + { { 0x7bd9c05cf6dfefabL,0xbe2f2268dcb37707L,0xe53ead973a38bb95L, + 0xe9ce66fc9bc1d7a3L }, + { 0x75aa15766f6a02a1L,0x38c087df60e600edL,0xf8947f3468cdc1b9L, + 0xd9650b0172280651L } }, + /* 186 */ + { { 0x504b4c4a5a057e60L,0xcbccc3be8def25e4L,0xa635320817c1ccbdL, + 0x14d6699a804eb7a2L }, + { 0x2c8a8415db1f411aL,0x09fbaf0bf80d769cL,0xb4deef901c2f77adL, + 0x6f4c68410d43598aL } }, + /* 187 */ + { { 0x8726df4e96c24a96L,0x534dbc85fcbd99a3L,0x3c466ef28b2ae30aL, + 0x4c4350fd61189abbL }, + { 0x2967f716f855b8daL,0x41a42394463c38a1L,0xc37e1413eae93343L, + 0xa726d2425a3118b5L } }, + /* 188 */ + { { 0xdae6b3ee948c1086L,0xf1de503dcbd3a2e1L,0x3f35ed3f03d022f3L, + 0x13639e82cc6cf392L }, + { 0x9ac938fbcdafaa86L,0xf45bc5fb2654a258L,0x1963b26e45051329L, + 0xca9365e1c1a335a3L } }, + /* 189 */ + { { 0x3615ac754c3b2d20L,0x742a5417904e241bL,0xb08521c4cc9d071dL, + 0x9ce29c34970b72a5L }, + { 0x8cc81f736d3e0ad6L,0x8060da9ef2f8434cL,0x35ed1d1a6ce862d9L, + 0x48c4abd7ab42af98L } }, + /* 190 */ + { { 0xd221b0cc40c7485aL,0xead455bbe5274dbfL,0x493c76989263d2e8L, + 0x78017c32f67b33cbL }, + { 0xb9d35769930cb5eeL,0xc0d14e940c408ed2L,0xf8b7bf55272f1a4dL, + 0x53cd0454de5c1c04L } }, + /* 191 */ + { { 0xbcd585fa5d28ccacL,0x5f823e56005b746eL,0x7c79f0a1cd0123aaL, + 0xeea465c1d3d7fa8fL }, + { 0x7810659f0551803bL,0x6c0b599f7ce6af70L,0x4195a77029288e70L, + 0x1b6e42a47ae69193L } }, + /* 192 */ + { { 0x2e80937cf67d04c3L,0x1e312be289eeb811L,0x56b5d88792594d60L, + 0x0224da14187fbd3dL }, + { 0x87abb8630c5fe36fL,0x580f3c604ef51f5fL,0x964fb1bfb3b429ecL, + 0x60838ef042bfff33L } }, + /* 193 */ + { { 0x432cb2f27e0bbe99L,0x7bda44f304aa39eeL,0x5f497c7a9fa93903L, + 0x636eb2022d331643L }, + { 0xfcfd0e6193ae00aaL,0x875a00fe31ae6d2fL,0xf43658a29f93901cL, + 0x8844eeb639218bacL } }, + /* 194 */ + { { 0x114171d26b3bae58L,0x7db3df7117e39f3eL,0xcd37bc7f81a8eadaL, + 0x27ba83dc51fb789eL }, + { 0xa7df439ffbf54de5L,0x7277030bb5fe1a71L,0x42ee8e35db297a48L, + 0xadb62d3487f3a4abL } }, + /* 195 */ + { { 0x9b1168a2a175df2aL,0x082aa04f618c32e9L,0xc9e4f2e7146b0916L, + 0xb990fd7675e7c8b2L }, + { 0x0829d96b4df37313L,0x1c205579d0b40789L,0x66c9ae4a78087711L, + 0x81707ef94d10d18dL } }, + /* 196 */ + { { 0x97d7cab203d6ff96L,0x5b851bfc0d843360L,0x268823c4d042db4bL, + 0x3792daead5a8aa5cL }, + { 0x52818865941afa0bL,0xf3e9e74142d83671L,0x17c825275be4e0a7L, + 0x5abd635e94b001baL } }, + /* 197 */ + { { 0x727fa84e0ac4927cL,0xe3886035a7c8cf23L,0xa4bcd5ea4adca0dfL, + 0x5995bf21846ab610L }, + { 0xe90f860b829dfa33L,0xcaafe2ae958fc18bL,0x9b3baf4478630366L, + 0x44c32ca2d483411eL } }, + /* 198 */ + { { 0xa74a97f1e40ed80cL,0x5f938cb131d2ca82L,0x53f2124b7c2d6ad9L, + 0x1f2162fb8082a54cL }, + { 0x7e467cc5720b173eL,0x40e8a666085f12f9L,0x8cebc20e4c9d65dcL, + 0x8f1d402bc3e907c9L } }, + /* 199 */ + { { 0x4f592f9cfbc4058aL,0xb15e14b6292f5670L,0xc55cfe37bc1d8c57L, + 0xb1980f43926edbf9L }, + { 0x98c33e0932c76b09L,0x1df5279d33b07f78L,0x6f08ead4863bb461L, + 0x2828ad9b37448e45L } }, + /* 200 */ + { { 0x696722c4c4cf4ac5L,0xf5ac1a3fdde64afbL,0x0551baa2e0890832L, + 0x4973f1275a14b390L }, + { 0xe59d8335322eac5dL,0x5e07eef50bd9b568L,0xab36720fa2588393L, + 0x6dac8ed0db168ac7L } }, + /* 201 */ + { { 0xf7b545aeeda835efL,0x4aa113d21d10ed51L,0x035a65e013741b09L, + 0x4b23ef5920b9de4cL }, + { 0xe82bb6803c4c7341L,0xd457706d3f58bc37L,0x73527863a51e3ee8L, + 0x4dd71534ddf49a4eL } }, + /* 202 */ + { { 0xbf94467295476cd9L,0x648d072fe31a725bL,0x1441c8b8fc4b67e0L, + 0xfd3170002f4a4dbbL }, + { 0x1cb43ff48995d0e1L,0x76e695d10ef729aaL,0xe0d5f97641798982L, + 0x14fac58c9569f365L } }, + /* 203 */ + { { 0xad9a0065f312ae18L,0x51958dc0fcc93fc9L,0xd9a142408a7d2846L, + 0xed7c765136abda50L }, + { 0x46270f1a25d4abbcL,0x9b5dd8f3f1a113eaL,0xc609b0755b51952fL, + 0xfefcb7f74d2e9f53L } }, + /* 204 */ + { { 0xbd09497aba119185L,0xd54e8c30aac45ba4L,0x492479deaa521179L, + 0x1801a57e87e0d80bL }, + { 0x073d3f8dfcafffb0L,0x6cf33c0bae255240L,0x781d763b5b5fdfbcL, + 0x9f8fc11e1ead1064L } }, + /* 205 */ + { { 0x1583a1715e69544cL,0x0eaf8567f04b7813L,0x1e22a8fd278a4c32L, + 0xa9d3809d3d3a69a9L }, + { 0x936c2c2c59a2da3bL,0x38ccbcf61895c847L,0x5e65244e63d50869L, + 0x3006b9aee1178ef7L } }, + /* 206 */ + { { 0x0bb1f2b0c9eead28L,0x7eef635d89f4dfbcL,0x074757fdb2ce8939L, + 0x0ab85fd745f8f761L }, + { 0xecda7c933e5b4549L,0x4be2bb5c97922f21L,0x261a1274b43b8040L, + 0xb122d67511e942c2L } }, + /* 207 */ + { { 0x3be607be66a5ae7aL,0x01e703fa76adcbe3L,0xaf9043014eb6e5c5L, + 0x9f599dc1097dbaecL }, + { 0x6d75b7180ff250edL,0x8eb91574349a20dcL,0x425605a410b227a3L, + 0x7d5528e08a294b78L } }, + /* 208 */ + { { 0xf0f58f6620c26defL,0x025585ea582b2d1eL,0xfbe7d79b01ce3881L, + 0x28ccea01303f1730L }, + { 0xd1dabcd179644ba5L,0x1fc643e806fff0b8L,0xa60a76fc66b3e17bL, + 0xc18baf48a1d013bfL } }, + /* 209 */ + { { 0x34e638c85dc4216dL,0x00c01067206142acL,0xd453a17195f5064aL, + 0x9def809db7a9596bL }, + { 0x41e8642e67ab8d2cL,0xb42404336237a2b6L,0x7d506a6d64c4218bL, + 0x0357f8b068808ce5L } }, + /* 210 */ + { { 0x8e9dbe644cd2cc88L,0xcc61c28df0b8f39dL,0x4a309874cd30a0c8L, + 0xe4a01add1b489887L }, + { 0x2ed1eeacf57cd8f9L,0x1b767d3ebd594c48L,0xa7295c717bd2f787L, + 0x466d7d79ce10cc30L } }, + /* 211 */ + { { 0x47d318929dada2c7L,0x4fa0a6c38f9aa27dL,0x90e4fd28820a59e1L, + 0xc672a522451ead1aL }, + { 0x30607cc85d86b655L,0xf0235d3bf9ad4af1L,0x99a08680571172a6L, + 0x5e3d64faf2a67513L } }, + /* 212 */ + { { 0xaa6410c79b3b4416L,0xcd8fcf85eab26d99L,0x5ebff74adb656a74L, + 0x6c8a7a95eb8e42fcL }, + { 0x10c60ba7b02a63bdL,0x6b2f23038b8f0047L,0x8c6c3738312d90b0L, + 0x348ae422ad82ca91L } }, + /* 213 */ + { { 0x7f4746635ccda2fbL,0x22accaa18e0726d2L,0x85adf782492b1f20L, + 0xc1074de0d9ef2d2eL }, + { 0xfcf3ce44ae9a65b3L,0xfd71e4ac05d7151bL,0xd4711f50ce6a9788L, + 0xfbadfbdbc9e54ffcL } }, + /* 214 */ + { { 0x1713f1cd20a99363L,0xb915658f6cf22775L,0x968175cd24d359b2L, + 0xb7f976b483716fcdL }, + { 0x5758e24d5d6dbf74L,0x8d23bafd71c3af36L,0x48f477600243dfe3L, + 0xf4d41b2ecafcc805L } }, + /* 215 */ + { { 0x51f1cf28fdabd48dL,0xce81be3632c078a4L,0x6ace2974117146e9L, + 0x180824eae0160f10L }, + { 0x0387698b66e58358L,0x63568752ce6ca358L,0x82380e345e41e6c5L, + 0x67e5f63983cf6d25L } }, + /* 216 */ + { { 0xf89ccb8dcf4899efL,0x949015f09ebb44c0L,0x546f9276b2598ec9L, + 0x9fef789a04c11fc6L }, + { 0x6d367ecf53d2a071L,0xb10e1a7fa4519b09L,0xca6b3fb0611e2eefL, + 0xbc80c181a99c4e20L } }, + /* 217 */ + { { 0x972536f8e5eb82e6L,0x1a484fc7f56cb920L,0xc78e217150b5da5eL, + 0x49270e629f8cdf10L }, + { 0x1a39b7bbea6b50adL,0x9a0284c1a2388ffcL,0x5403eb178107197bL, + 0xd2ee52f961372f7fL } }, + /* 218 */ + { { 0xd37cd28588e0362aL,0x442fa8a78fa5d94dL,0xaff836e5a434a526L, + 0xdfb478bee5abb733L }, + { 0xa91f1ce7673eede6L,0xa5390ad42b5b2f04L,0x5e66f7bf5530da2fL, + 0xd9a140b408df473aL } }, + /* 219 */ + { { 0x0e0221b56e8ea498L,0x623478293563ee09L,0xe06b8391335d2adeL, + 0x760c058d623f4b1aL }, + { 0x0b89b58cc198aa79L,0xf74890d2f07aba7fL,0x4e204110fde2556aL, + 0x7141982d8f190409L } }, + /* 220 */ + { { 0x6f0a0e334d4b0f45L,0xd9280b38392a94e1L,0x3af324c6b3c61d5eL, + 0x3af9d1ce89d54e47L }, + { 0xfd8f798120930371L,0xeda2664c21c17097L,0x0e9545dcdc42309bL, + 0xb1f815c373957dd6L } }, + /* 221 */ + { { 0x84faa78e89fec44aL,0xc8c2ae473caa4cafL,0x691c807dc1b6a624L, + 0xa41aed141543f052L }, + { 0x424353997d5ffe04L,0x8bacb2df625b6e20L,0x85d660be87817775L, + 0xd6e9c1dd86fb60efL } }, + /* 222 */ + { { 0x3aa2e97ec6853264L,0x771533b7e2304a0bL,0x1b912bb7b8eae9beL, + 0x9c9c6e10ae9bf8c2L }, + { 0xa2309a59e030b74cL,0x4ed7494d6a631e90L,0x89f44b23a49b79f2L, + 0x566bd59640fa61b6L } }, + /* 223 */ + { { 0x066c0118c18061f3L,0x190b25d37c83fc70L,0xf05fc8e027273245L, + 0xcf2c7390f525345eL }, + { 0xa09bceb410eb30cfL,0xcfd2ebba0d77703aL,0xe842c43a150ff255L, + 0x02f517558aa20979L } }, + /* 224 */ + { { 0x396ef794addb7d07L,0x0b4fc74224455500L,0xfaff8eacc78aa3ceL, + 0x14e9ada5e8d4d97dL }, + { 0xdaa480a12f7079e2L,0x45baa3cde4b0800eL,0x01765e2d7838157dL, + 0xa0ad4fab8e9d9ae8L } }, + /* 225 */ + { { 0x0bfb76214a653618L,0x1872813c31eaaa5fL,0x1553e73744949d5eL, + 0xbcd530b86e56ed1eL }, + { 0x169be85332e9c47bL,0xdc2776feb50059abL,0xcdba9761192bfbb4L, + 0x909283cf6979341dL } }, + /* 226 */ + { { 0x67b0032476e81a13L,0x9bee1a9962171239L,0x08ed361bd32e19d6L, + 0x35eeb7c9ace1549aL }, + { 0x1280ae5a7e4e5bdcL,0x2dcd2cd3b6ceec6eL,0x52e4224c6e266bc1L, + 0x9a8b2cf4448ae864L } }, + /* 227 */ + { { 0xf6471bf209d03b59L,0xc90e62a3b65af2abL,0xff7ff168ebd5eec9L, + 0x6bdb60f4d4491379L }, + { 0xdadafebc8a55bc30L,0xc79ead1610097fe0L,0x42e197414c1e3bddL, + 0x01ec3cfd94ba08a9L } }, + /* 228 */ + { { 0xba6277ebdc9485c2L,0x48cc9a7922fb10c7L,0x4f61d60f70a28d8aL, + 0xd1acb1c0475464f6L }, + { 0xd26902b126f36612L,0x59c3a44ee0618d8bL,0x4df8a813308357eeL, + 0x7dcd079d405626c2L } }, + /* 229 */ + { { 0x5ce7d4d3f05a4b48L,0xadcd295237230772L,0xd18f7971812a915aL, + 0x0bf53589377d19b8L }, + { 0x35ecd95a6c68ea73L,0xc7f3bbca823a584dL,0x9fb674c6f473a723L, + 0xd28be4d9e16686fcL } }, + /* 230 */ + { { 0x5d2b990638fa8e4bL,0x559f186e893fd8fcL,0x3a6de2aa436fb6fcL, + 0xd76007aa510f88ceL }, + { 0x2d10aab6523a4988L,0xb455cf4474dd0273L,0x7f467082a3407278L, + 0xf2b52f68b303bb01L } }, + /* 231 */ + { { 0x0d57eafa9835b4caL,0x2d2232fcbb669cbcL,0x8eeeb680c6643198L, + 0xd8dbe98ecc5aed3aL }, + { 0xcba9be3fc5a02709L,0x30be68e5f5ba1fa8L,0xfebd43cdf10ea852L, + 0xe01593a3ee559705L } }, + /* 232 */ + { { 0xd3e5af50ea75a0a6L,0x512226ac57858033L,0x6fe6d50fd0176406L, + 0xafec07b1aeb8ef06L }, + { 0x7fb9956780bb0a31L,0x6f1af3cc37309aaeL,0x9153a15a01abf389L, + 0xa71b93546e2dbfddL } }, + /* 233 */ + { { 0xbf8e12e018f593d2L,0xd1a90428a078122bL,0x150505db0ba4f2adL, + 0x53a2005c628523d9L }, + { 0x07c8b639e7f2b935L,0x2bff975ac182961aL,0x86bceea77518ca2cL, + 0xbf47d19b3d588e3dL } }, + /* 234 */ + { { 0x672967a7dd7665d5L,0x4e3030572f2f4de5L,0x144005ae80d4903fL, + 0x001c2c7f39c9a1b6L }, + { 0x143a801469efc6d6L,0xc810bdaa7bc7a724L,0x5f65670ba78150a4L, + 0xfdadf8e786ffb99bL } }, + /* 235 */ + { { 0xfd38cb88ffc00785L,0x77fa75913b48eb67L,0x0454d055bf368fbcL, + 0x3a838e4d5aa43c94L }, + { 0x561663293e97bb9aL,0x9eb93363441d94d9L,0x515591a60adb2a83L, + 0x3cdb8257873e1da3L } }, + /* 236 */ + { { 0x137140a97de77eabL,0xf7e1c50d41648109L,0x762dcad2ceb1d0dfL, + 0x5a60cc89f1f57fbaL }, + { 0x80b3638240d45673L,0x1b82be195913c655L,0x057284b8dd64b741L, + 0x922ff56fdbfd8fc0L } }, + /* 237 */ + { { 0x1b265deec9a129a1L,0xa5b1ce57cc284e04L,0x04380c46cebfbe3cL, + 0x72919a7df6c5cd62L }, + { 0x298f453a8fb90f9aL,0xd719c00b88e4031bL,0xe32c0e77796f1856L, + 0x5e7917803624089aL } }, + /* 238 */ + { { 0x5c16ec557f63cdfbL,0x8e6a3571f1cae4fdL,0xfce26bea560597caL, + 0x4e0a5371e24c2fabL }, + { 0x276a40d3a5765357L,0x3c89af440d73a2b4L,0xb8f370ae41d11a32L, + 0xf5ff7818d56604eeL } }, + /* 239 */ + { { 0xfbf3e3fe1a09df21L,0x26d5d28ee66e8e47L,0x2096bd0a29c89015L, + 0xe41df0e9533f5e64L }, + { 0x305fda40b3ba9e3fL,0xf2340ceb2604d895L,0x0866e1927f0367c7L, + 0x8edd7d6eac4f155fL } }, + /* 240 */ + { { 0xc9a1dc0e0bfc8ff3L,0x14efd82be936f42fL,0x67016f7ccca381efL, + 0x1432c1caed8aee96L }, + { 0xec68482970b23c26L,0xa64fe8730735b273L,0xe389f6e5eaef0f5aL, + 0xcaef480b5ac8d2c6L } }, + /* 241 */ + { { 0x5245c97875315922L,0xd82951713063cca5L,0xf3ce60d0b64ef2cbL, + 0xd0ba177e8efae236L }, + { 0x53a9ae8fb1b3af60L,0x1a796ae53d2da20eL,0x01d63605df9eef28L, + 0xf31c957c1c54ae16L } }, + /* 242 */ + { { 0xc0f58d5249cc4597L,0xdc5015b0bae0a028L,0xefc5fc55734a814aL, + 0x013404cb96e17c3aL }, + { 0xb29e2585c9a824bfL,0xd593185e001eaed7L,0x8d6ee68261ef68acL, + 0x6f377c4b91933e6cL } }, + /* 243 */ + { { 0x9f93bad1a8333fd2L,0xa89302025a2a95b8L,0x211e5037eaf75aceL, + 0x6dba3e4ed2d09506L }, + { 0xa48ef98cd04399cdL,0x1811c66ee6b73adeL,0x72f60752c17ecaf3L, + 0xf13cf3423becf4a7L } }, + /* 244 */ + { { 0xceeb9ec0a919e2ebL,0x83a9a195f62c0f68L,0xcfba3bb67aba2299L, + 0xc83fa9a9274bbad3L }, + { 0x0d7d1b0b62fa1ce0L,0xe58b60f53418efbfL,0xbfa8ef9e52706f04L, + 0xb49d70f45d702683L } }, + /* 245 */ + { { 0x914c7510fad5513bL,0x05f32eecb1751e2dL,0x6d850418d9fb9d59L, + 0x59cfadbb0c30f1cfL }, + { 0xe167ac2355cb7fd6L,0x249367b8820426a3L,0xeaeec58c90a78864L, + 0x5babf362354a4b67L } }, + /* 246 */ + { { 0x37c981d1ee424865L,0x8b002878f2e5577fL,0x702970f1b9e0c058L, + 0x6188c6a79026c8f0L }, + { 0x06f9a19bd0f244daL,0x1ecced5cfb080873L,0x35470f9b9f213637L, + 0x993fe475df50b9d9L } }, + /* 247 */ + { { 0x68e31cdf9b2c3609L,0x84eb19c02c46d4eaL,0x7ac9ec1a9a775101L, + 0x81f764664c80616bL }, + { 0x1d7c2a5a75fbe978L,0x6743fed3f183b356L,0x838d1f04501dd2bfL, + 0x564a812a5fe9060dL } }, + /* 248 */ + { { 0x7a5a64f4fa817d1dL,0x55f96844bea82e0fL,0xb5ff5a0fcd57f9aaL, + 0x226bf3cf00e51d6cL }, + { 0xd6d1a9f92f2833cfL,0x20a0a35a4f4f89a8L,0x11536c498f3f7f77L, + 0x68779f47ff257836L } }, + /* 249 */ + { { 0x79b0c1c173043d08L,0xa54467741fc020faL,0xd3767e289a6d26d0L, + 0x97bcb0d1eb092e0bL }, + { 0x2ab6eaa8f32ed3c3L,0xc8a4f151b281bc48L,0x4d1bf4f3bfa178f3L, + 0xa872ffe80a784655L } }, + /* 250 */ + { { 0xb1ab7935a32b2086L,0xe1eb710e8160f486L,0x9bd0cd913b6ae6beL, + 0x02812bfcb732a36aL }, + { 0xa63fd7cacf605318L,0x646e5d50fdfd6d1dL,0xa1d683982102d619L, + 0x07391cc9fe5396afL } }, + /* 251 */ + { { 0xc50157f08b80d02bL,0x6b8333d162877f7fL,0x7aca1af878d542aeL, + 0x355d2adc7e6d2a08L }, + { 0xb41f335a287386e1L,0xfd272a94f8e43275L,0x286ca2cde79989eaL, + 0x3dc2b1e37c2a3a79L } }, + /* 252 */ + { { 0xd689d21c04581352L,0x0a00c825376782beL,0x203bd5909fed701fL, + 0xc47869103ccd846bL }, + { 0x5dba770824c768edL,0x72feea026841f657L,0x73313ed56accce0eL, + 0xccc42968d5bb4d32L } }, + /* 253 */ + { { 0x94e50de13d7620b9L,0xd89a5c8a5992a56aL,0xdc007640675487c9L, + 0xe147eb42aa4871cfL }, + { 0x274ab4eeacf3ae46L,0xfd4936fb50350fbeL,0xdf2afe4748c840eaL, + 0x239ac047080e96e3L } }, + /* 254 */ + { { 0x481d1f352bfee8d4L,0xce80b5cffa7b0fecL,0x105c4c9e2ce9af3cL, + 0xc55fa1a3f5f7e59dL }, + { 0x3186f14e8257c227L,0xc5b1653f342be00bL,0x09afc998aa904fb2L, + 0x094cd99cd4f4b699L } }, + /* 255 */ + { { 0x8a981c84d703bebaL,0x8631d15032ceb291L,0xa445f2c9e3bd49ecL, + 0xb90a30b642abad33L }, + { 0xb465404fb4a5abf9L,0x004750c375db7603L,0x6f9a42ccca35d89fL, + 0x019f8b9a1b7924f7L } }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_4(r, &p256_base, p256_table, + k, map, heap); +} + +#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 coordinates. + * + * 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_256* r, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_avx2_4(r, &p256_base, p256_table, + k, map, heap); +} + +#endif /* HAVE_INTEL_AVX2 */ +#else /* WOLFSSL_SP_SMALL */ +/* The index into pre-computation table to use. */ +static const uint8_t recode_index_4_7[130] = { + 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, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, + 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, + 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 const uint8_t recode_neg_4_7[130] = { + 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, 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, + 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 perform. + */ +static void sp_256_ecc_recode_7_4(const sp_digit* k, ecc_recode_256* 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<37; i++) { + y = n; + if (o + 7 < 64) { + y &= 0x7f; + n >>= 7; + o += 7; + } + else if (o + 7 == 64) { + n >>= 7; + if (++j < 4) + n = k[j]; + o = 0; + } + else if (++j < 4) { + n = k[j]; + y |= (n << (64 - o)) & 0x7f; + o -= 57; + n >>= o; + } + + y += carry; + v[i].i = recode_index_4_7[y]; + v[i].neg = recode_neg_4_7[y]; + carry = (y >> 7) + v[i].neg; + } +} + +static const sp_table_entry_256 p256_table[2405] = { + /* 0 << 0 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 0 */ + { { 0x79e730d418a9143cL,0x75ba95fc5fedb601L,0x79fb732b77622510L, + 0x18905f76a53755c6L }, + { 0xddf25357ce95560aL,0x8b4ab8e4ba19e45cL,0xd2e88688dd21f325L, + 0x8571ff1825885d85L } }, + /* 2 << 0 */ + { { 0x850046d410ddd64dL,0xaa6ae3c1a433827dL,0x732205038d1490d9L, + 0xf6bb32e43dcf3a3bL }, + { 0x2f3648d361bee1a5L,0x152cd7cbeb236ff8L,0x19a8fb0e92042dbeL, + 0x78c577510a5b8a3bL } }, + /* 3 << 0 */ + { { 0xffac3f904eebc127L,0xb027f84a087d81fbL,0x66ad77dd87cbbc98L, + 0x26936a3fb6ff747eL }, + { 0xb04c5c1fc983a7ebL,0x583e47ad0861fe1aL,0x788208311a2ee98eL, + 0xd5f06a29e587cc07L } }, + /* 4 << 0 */ + { { 0x74b0b50d46918dccL,0x4650a6edc623c173L,0x0cdaacace8100af2L, + 0x577362f541b0176bL }, + { 0x2d96f24ce4cbaba6L,0x17628471fad6f447L,0x6b6c36dee5ddd22eL, + 0x84b14c394c5ab863L } }, + /* 5 << 0 */ + { { 0xbe1b8aaec45c61f5L,0x90ec649a94b9537dL,0x941cb5aad076c20cL, + 0xc9079605890523c8L }, + { 0xeb309b4ae7ba4f10L,0x73c568efe5eb882bL,0x3540a9877e7a1f68L, + 0x73a076bb2dd1e916L } }, + /* 6 << 0 */ + { { 0x403947373e77664aL,0x55ae744f346cee3eL,0xd50a961a5b17a3adL, + 0x13074b5954213673L }, + { 0x93d36220d377e44bL,0x299c2b53adff14b5L,0xf424d44cef639f11L, + 0xa4c9916d4a07f75fL } }, + /* 7 << 0 */ + { { 0x0746354ea0173b4fL,0x2bd20213d23c00f7L,0xf43eaab50c23bb08L, + 0x13ba5119c3123e03L }, + { 0x2847d0303f5b9d4dL,0x6742f2f25da67bddL,0xef933bdc77c94195L, + 0xeaedd9156e240867L } }, + /* 8 << 0 */ + { { 0x27f14cd19499a78fL,0x462ab5c56f9b3455L,0x8f90f02af02cfc6bL, + 0xb763891eb265230dL }, + { 0xf59da3a9532d4977L,0x21e3327dcf9eba15L,0x123c7b84be60bbf0L, + 0x56ec12f27706df76L } }, + /* 9 << 0 */ + { { 0x75c96e8f264e20e8L,0xabe6bfed59a7a841L,0x2cc09c0444c8eb00L, + 0xe05b3080f0c4e16bL }, + { 0x1eb7777aa45f3314L,0x56af7bedce5d45e3L,0x2b6e019a88b12f1aL, + 0x086659cdfd835f9bL } }, + /* 10 << 0 */ + { { 0x2c18dbd19dc21ec8L,0x98f9868a0fcf8139L,0x737d2cd648250b49L, + 0xcc61c94724b3428fL }, + { 0x0c2b407880dd9e76L,0xc43a8991383fbe08L,0x5f7d2d65779be5d2L, + 0x78719a54eb3b4ab5L } }, + /* 11 << 0 */ + { { 0xea7d260a6245e404L,0x9de407956e7fdfe0L,0x1ff3a4158dac1ab5L, + 0x3e7090f1649c9073L }, + { 0x1a7685612b944e88L,0x250f939ee57f61c8L,0x0c0daa891ead643dL, + 0x68930023e125b88eL } }, + /* 12 << 0 */ + { { 0x04b71aa7d2697768L,0xabdedef5ca345a33L,0x2409d29dee37385eL, + 0x4ee1df77cb83e156L }, + { 0x0cac12d91cbb5b43L,0x170ed2f6ca895637L,0x28228cfa8ade6d66L, + 0x7ff57c9553238acaL } }, + /* 13 << 0 */ + { { 0xccc425634b2ed709L,0x0e356769856fd30dL,0xbcbcd43f559e9811L, + 0x738477ac5395b759L }, + { 0x35752b90c00ee17fL,0x68748390742ed2e3L,0x7cd06422bd1f5bc1L, + 0xfbc08769c9e7b797L } }, + /* 14 << 0 */ + { { 0xa242a35bb0cf664aL,0x126e48f77f9707e3L,0x1717bf54c6832660L, + 0xfaae7332fd12c72eL }, + { 0x27b52db7995d586bL,0xbe29569e832237c2L,0xe8e4193e2a65e7dbL, + 0x152706dc2eaa1bbbL } }, + /* 15 << 0 */ + { { 0x72bcd8b7bc60055bL,0x03cc23ee56e27e4bL,0xee337424e4819370L, + 0xe2aa0e430ad3da09L }, + { 0x40b8524f6383c45dL,0xd766355442a41b25L,0x64efa6de778a4797L, + 0x2042170a7079adf4L } }, + /* 16 << 0 */ + { { 0x808b0b650bc6fb80L,0x5882e0753ffe2e6bL,0xd5ef2f7c2c83f549L, + 0x54d63c809103b723L }, + { 0xf2f11bd652a23f9bL,0x3670c3194b0b6587L,0x55c4623bb1580e9eL, + 0x64edf7b201efe220L } }, + /* 17 << 0 */ + { { 0x97091dcbd53c5c9dL,0xf17624b6ac0a177bL,0xb0f139752cfe2dffL, + 0xc1a35c0a6c7a574eL }, + { 0x227d314693e79987L,0x0575bf30e89cb80eL,0x2f4e247f0d1883bbL, + 0xebd512263274c3d0L } }, + /* 18 << 0 */ + { { 0x5f3e51c856ada97aL,0x4afc964d8f8b403eL,0xa6f247ab412e2979L, + 0x675abd1b6f80ebdaL }, + { 0x66a2bd725e485a1dL,0x4b2a5caf8f4f0b3cL,0x2626927f1b847bbaL, + 0x6c6fc7d90502394dL } }, + /* 19 << 0 */ + { { 0xfea912baa5659ae8L,0x68363aba25e1a16eL,0xb8842277752c41acL, + 0xfe545c282897c3fcL }, + { 0x2d36e9e7dc4c696bL,0x5806244afba977c5L,0x85665e9be39508c1L, + 0xf720ee256d12597bL } }, + /* 20 << 0 */ + { { 0x8a979129d2337a31L,0x5916868f0f862bdcL,0x048099d95dd283baL, + 0xe2d1eeb6fe5bfb4eL }, + { 0x82ef1c417884005dL,0xa2d4ec17ffffcbaeL,0x9161c53f8aa95e66L, + 0x5ee104e1c5fee0d0L } }, + /* 21 << 0 */ + { { 0x562e4cecc135b208L,0x74e1b2654783f47dL,0x6d2a506c5a3f3b30L, + 0xecead9f4c16762fcL }, + { 0xf29dd4b2e286e5b9L,0x1b0fadc083bb3c61L,0x7a75023e7fac29a4L, + 0xc086d5f1c9477fa3L } }, + /* 22 << 0 */ + { { 0x0fc611352f6f3076L,0xc99ffa23e3912a9aL,0x6a0b0685d2f8ba3dL, + 0xfdc777e8e93358a4L }, + { 0x94a787bb35415f04L,0x640c2d6a4d23fea4L,0x9de917da153a35b5L, + 0x793e8d075d5cd074L } }, + /* 23 << 0 */ + { { 0xf4f876532de45068L,0x37c7a7e89e2e1f6eL,0xd0825fa2a3584069L, + 0xaf2cea7c1727bf42L }, + { 0x0360a4fb9e4785a9L,0xe5fda49c27299f4aL,0x48068e1371ac2f71L, + 0x83d0687b9077666fL } }, + /* 24 << 0 */ + { { 0x6d3883b215d02819L,0x6d0d755040dd9a35L,0x61d7cbf91d2b469fL, + 0xf97b232f2efc3115L }, + { 0xa551d750b24bcbc7L,0x11ea494988a1e356L,0x7669f03193cb7501L, + 0x595dc55eca737b8aL } }, + /* 25 << 0 */ + { { 0xa4a319acd837879fL,0x6fc1b49eed6b67b0L,0xe395993332f1f3afL, + 0x966742eb65432a2eL }, + { 0x4b8dc9feb4966228L,0x96cc631243f43950L,0x12068859c9b731eeL, + 0x7b948dc356f79968L } }, + /* 26 << 0 */ + { { 0x61e4ad32ed1f8008L,0xe6c9267ad8b17538L,0x1ac7c5eb857ff6fbL, + 0x994baaa855f2fb10L }, + { 0x84cf14e11d248018L,0x5a39898b628ac508L,0x14fde97b5fa944f5L, + 0xed178030d12e5ac7L } }, + /* 27 << 0 */ + { { 0x042c2af497e2feb4L,0xd36a42d7aebf7313L,0x49d2c9eb084ffdd7L, + 0x9f8aa54b2ef7c76aL }, + { 0x9200b7ba09895e70L,0x3bd0c66fddb7fb58L,0x2d97d10878eb4cbbL, + 0x2d431068d84bde31L } }, + /* 28 << 0 */ + { { 0x4b523eb7172ccd1fL,0x7323cb2830a6a892L,0x97082ec0cfe153ebL, + 0xe97f6b6af2aadb97L }, + { 0x1d3d393ed1a83da1L,0xa6a7f9c7804b2a68L,0x4a688b482d0cb71eL, + 0xa9b4cc5f40585278L } }, + /* 29 << 0 */ + { { 0x5e5db46acb66e132L,0xf1be963a0d925880L,0x944a70270317b9e2L, + 0xe266f95948603d48L }, + { 0x98db66735c208899L,0x90472447a2fb18a3L,0x8a966939777c619fL, + 0x3798142a2a3be21bL } }, + /* 30 << 0 */ + { { 0xb4241cb13298b343L,0xa3a14e49b44f65a1L,0xc5f4d6cd3ac77acdL, + 0xd0288cb552b6fc3cL }, + { 0xd5cc8c2f1c040abcL,0xb675511e06bf9b4aL,0xd667da379b3aa441L, + 0x460d45ce51601f72L } }, + /* 31 << 0 */ + { { 0xe2f73c696755ff89L,0xdd3cf7e7473017e6L,0x8ef5689d3cf7600dL, + 0x948dc4f8b1fc87b4L }, + { 0xd9e9fe814ea53299L,0x2d921ca298eb6028L,0xfaecedfd0c9803fcL, + 0xf38ae8914d7b4745L } }, + /* 32 << 0 */ + { { 0xd8c5fccfc5e3a3d8L,0xbefd904c4079dfbfL,0xbc6d6a58fead0197L, + 0x39227077695532a4L }, + { 0x09e23e6ddbef42f5L,0x7e449b64480a9908L,0x7b969c1aad9a2e40L, + 0x6231d7929591c2a4L } }, + /* 33 << 0 */ + { { 0x871514560f664534L,0x85ceae7c4b68f103L,0xac09c4ae65578ab9L, + 0x33ec6868f044b10cL }, + { 0x6ac4832b3a8ec1f1L,0x5509d1285847d5efL,0xf909604f763f1574L, + 0xb16c4303c32f63c4L } }, + /* 34 << 0 */ + { { 0xb6ab20147ca23cd3L,0xcaa7a5c6a391849dL,0x5b0673a375678d94L, + 0xc982ddd4dd303e64L }, + { 0xfd7b000b5db6f971L,0xbba2cb1f6f876f92L,0xc77332a33c569426L, + 0xa159100c570d74f8L } }, + /* 35 << 0 */ + { { 0xfd16847fdec67ef5L,0x742ee464233e76b7L,0x0b8e4134efc2b4c8L, + 0xca640b8642a3e521L }, + { 0x653a01908ceb6aa9L,0x313c300c547852d5L,0x24e4ab126b237af7L, + 0x2ba901628bb47af8L } }, + /* 36 << 0 */ + { { 0x3d5e58d6a8219bb7L,0xc691d0bd1b06c57fL,0x0ae4cb10d257576eL, + 0x3569656cd54a3dc3L }, + { 0xe5ebaebd94cda03aL,0x934e82d3162bfe13L,0x450ac0bae251a0c6L, + 0x480b9e11dd6da526L } }, + /* 37 << 0 */ + { { 0x00467bc58cce08b5L,0xb636458c7f178d55L,0xc5748baea677d806L, + 0x2763a387dfa394ebL }, + { 0xa12b448a7d3cebb6L,0xe7adda3e6f20d850L,0xf63ebce51558462cL, + 0x58b36143620088a8L } }, + /* 38 << 0 */ + { { 0x8a2cc3ca4d63c0eeL,0x512331170fe948ceL,0x7463fd85222ef33bL, + 0xadf0c7dc7c603d6cL }, + { 0x0ec32d3bfe7765e5L,0xccaab359bf380409L,0xbdaa84d68e59319cL, + 0xd9a4c2809c80c34dL } }, + /* 39 << 0 */ + { { 0xa9d89488a059c142L,0x6f5ae714ff0b9346L,0x068f237d16fb3664L, + 0x5853e4c4363186acL }, + { 0xe2d87d2363c52f98L,0x2ec4a76681828876L,0x47b864fae14e7b1cL, + 0x0c0bc0e569192408L } }, + /* 40 << 0 */ + { { 0xe4d7681db82e9f3eL,0x83200f0bdf25e13cL,0x8909984c66f27280L, + 0x462d7b0075f73227L }, + { 0xd90ba188f2651798L,0x74c6e18c36ab1c34L,0xab256ea35ef54359L, + 0x03466612d1aa702fL } }, + /* 41 << 0 */ + { { 0x624d60492ed22e91L,0x6fdfe0b56f072822L,0xeeca111539ce2271L, + 0x98100a4fdb01614fL }, + { 0xb6b0daa2a35c628fL,0xb6f94d2ec87e9a47L,0xc67732591d57d9ceL, + 0xf70bfeec03884a7bL } }, + /* 42 << 0 */ + { { 0x5fb35ccfed2bad01L,0xa155cbe31da6a5c7L,0xc2e2594c30a92f8fL, + 0x649c89ce5bfafe43L }, + { 0xd158667de9ff257aL,0x9b359611f32c50aeL,0x4b00b20b906014cfL, + 0xf3a8cfe389bc7d3dL } }, + /* 43 << 0 */ + { { 0x4ff23ffd248a7d06L,0x80c5bfb4878873faL,0xb7d9ad9005745981L, + 0x179c85db3db01994L }, + { 0xba41b06261a6966cL,0x4d82d052eadce5a8L,0x9e91cd3ba5e6a318L, + 0x47795f4f95b2dda0L } }, + /* 44 << 0 */ + { { 0xecfd7c1fd55a897cL,0x009194abb29110fbL,0x5f0e2046e381d3b0L, + 0x5f3425f6a98dd291L }, + { 0xbfa06687730d50daL,0x0423446c4b083b7fL,0x397a247dd69d3417L, + 0xeb629f90387ba42aL } }, + /* 45 << 0 */ + { { 0x1ee426ccd5cd79bfL,0x0032940b946c6e18L,0x1b1e8ae057477f58L, + 0xe94f7d346d823278L }, + { 0xc747cb96782ba21aL,0xc5254469f72b33a5L,0x772ef6dec7f80c81L, + 0xd73acbfe2cd9e6b5L } }, + /* 46 << 0 */ + { { 0x4075b5b149ee90d9L,0x785c339aa06e9ebaL,0xa1030d5babf825e0L, + 0xcec684c3a42931dcL }, + { 0x42ab62c9c1586e63L,0x45431d665ab43f2bL,0x57c8b2c055f7835dL, + 0x033da338c1b7f865L } }, + /* 47 << 0 */ + { { 0x283c7513caa76097L,0x0a624fa936c83906L,0x6b20afec715af2c7L, + 0x4b969974eba78bfdL }, + { 0x220755ccd921d60eL,0x9b944e107baeca13L,0x04819d515ded93d4L, + 0x9bbff86e6dddfd27L } }, + /* 48 << 0 */ + { { 0x6b34413077adc612L,0xa7496529bbd803a0L,0x1a1baaa76d8805bdL, + 0xc8403902470343adL }, + { 0x39f59f66175adff1L,0x0b26d7fbb7d8c5b7L,0xa875f5ce529d75e3L, + 0x85efc7e941325cc2L } }, + /* 49 << 0 */ + { { 0x21950b421ff6acd3L,0xffe7048453dc6909L,0xff4cd0b228766127L, + 0xabdbe6084fb7db2bL }, + { 0x837c92285e1109e8L,0x26147d27f4645b5aL,0x4d78f592f7818ed8L, + 0xd394077ef247fa36L } }, + /* 50 << 0 */ + { { 0x0fb9c2d0488c171aL,0xa78bfbaa13685278L,0xedfbe268d5b1fa6aL, + 0x0dceb8db2b7eaba7L }, + { 0xbf9e80899ae2b710L,0xefde7ae6a4449c96L,0x43b7716bcc143a46L, + 0xd7d34194c3628c13L } }, + /* 51 << 0 */ + { { 0x508cec1c3b3f64c9L,0xe20bc0ba1e5edf3fL,0xda1deb852f4318d4L, + 0xd20ebe0d5c3fa443L }, + { 0x370b4ea773241ea3L,0x61f1511c5e1a5f65L,0x99a5e23d82681c62L, + 0xd731e383a2f54c2dL } }, + /* 52 << 0 */ + { { 0x2692f36e83445904L,0x2e0ec469af45f9c0L,0x905a3201c67528b7L, + 0x88f77f34d0e5e542L }, + { 0xf67a8d295864687cL,0x23b92eae22df3562L,0x5c27014b9bbec39eL, + 0x7ef2f2269c0f0f8dL } }, + /* 53 << 0 */ + { { 0x97359638546c4d8dL,0x5f9c3fc492f24679L,0x912e8beda8c8acd9L, + 0xec3a318d306634b0L }, + { 0x80167f41c31cb264L,0x3db82f6f522113f2L,0xb155bcd2dcafe197L, + 0xfba1da5943465283L } }, + /* 54 << 0 */ + { { 0xa0425b8eb212cf53L,0x4f2e512ef8557c5fL,0xc1286ff925c4d56cL, + 0xbb8a0feaee26c851L }, + { 0xc28f70d2e7d6107eL,0x7ee0c444e76265aaL,0x3df277a41d1936b1L, + 0x1a556e3fea9595ebL } }, + /* 55 << 0 */ + { { 0x258bbbf9e7305683L,0x31eea5bf07ef5be6L,0x0deb0e4a46c814c1L, + 0x5cee8449a7b730ddL }, + { 0xeab495c5a0182bdeL,0xee759f879e27a6b4L,0xc2cf6a6880e518caL, + 0x25e8013ff14cf3f4L } }, + /* 56 << 0 */ + { { 0x8fc441407e8d7a14L,0xbb1ff3ca9556f36aL,0x6a84438514600044L, + 0xba3f0c4a7451ae63L }, + { 0xdfcac25b1f9af32aL,0x01e0db86b1f2214bL,0x4e9a5bc2a4b596acL, + 0x83927681026c2c08L } }, + /* 57 << 0 */ + { { 0x3ec832e77acaca28L,0x1bfeea57c7385b29L,0x068212e3fd1eaf38L, + 0xc13298306acf8cccL }, + { 0xb909f2db2aac9e59L,0x5748060db661782aL,0xc5ab2632c79b7a01L, + 0xda44c6c600017626L } }, + /* 58 << 0 */ + { { 0xf26c00e8a7ea82f0L,0x99cac80de4299aafL,0xd66fe3b67ed78be1L, + 0x305f725f648d02cdL }, + { 0x33ed1bc4623fb21bL,0xfa70533e7a6319adL,0x17ab562dbe5ffb3eL, + 0x0637499456674741L } }, + /* 59 << 0 */ + { { 0x69d44ed65c46aa8eL,0x2100d5d3a8d063d1L,0xcb9727eaa2d17c36L, + 0x4c2bab1b8add53b7L }, + { 0xa084e90c15426704L,0x778afcd3a837ebeaL,0x6651f7017ce477f8L, + 0xa062499846fb7a8bL } }, + /* 60 << 0 */ + { { 0xdc1e6828ed8a6e19L,0x33fc23364189d9c7L,0x026f8fe2671c39bcL, + 0xd40c4ccdbc6f9915L }, + { 0xafa135bbf80e75caL,0x12c651a022adff2cL,0xc40a04bd4f51ad96L, + 0x04820109bbe4e832L } }, + /* 61 << 0 */ + { { 0x3667eb1a7f4c04ccL,0x59556621a9404f84L,0x71cdf6537eceb50aL, + 0x994a44a69b8335faL }, + { 0xd7faf819dbeb9b69L,0x473c5680eed4350dL,0xb6658466da44bba2L, + 0x0d1bc780872bdbf3L } }, + /* 62 << 0 */ + { { 0xe535f175a1962f91L,0x6ed7e061ed58f5a7L,0x177aa4c02089a233L, + 0x0dbcb03ae539b413L }, + { 0xe3dc424ebb32e38eL,0x6472e5ef6806701eL,0xdd47ff98814be9eeL, + 0x6b60cfff35ace009L } }, + /* 63 << 0 */ + { { 0xb8d3d9319ff91fe5L,0x039c4800f0518eedL,0x95c376329182cb26L, + 0x0763a43482fc568dL }, + { 0x707c04d5383e76baL,0xac98b930824e8197L,0x92bf7c8f91230de0L, + 0x90876a0140959b70L } }, + /* 64 << 0 */ + { { 0xdb6d96f305968b80L,0x380a0913089f73b9L,0x7da70b83c2c61e01L, + 0x95fb8394569b38c7L }, + { 0x9a3c651280edfe2fL,0x8f726bb98faeaf82L,0x8010a4a078424bf8L, + 0x296720440e844970L } }, + /* 0 << 7 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 7 */ + { { 0x63c5cb817a2ad62aL,0x7ef2b6b9ac62ff54L,0x3749bba4b3ad9db5L, + 0xad311f2c46d5a617L }, + { 0xb77a8087c2ff3b6dL,0xb46feaf3367834ffL,0xf8aa266d75d6b138L, + 0xfa38d320ec008188L } }, + /* 2 << 7 */ + { { 0x486d8ffa696946fcL,0x50fbc6d8b9cba56dL,0x7e3d423e90f35a15L, + 0x7c3da195c0dd962cL }, + { 0xe673fdb03cfd5d8bL,0x0704b7c2889dfca5L,0xf6ce581ff52305aaL, + 0x399d49eb914d5e53L } }, + /* 3 << 7 */ + { { 0x380a496d6ec293cdL,0x733dbda78e7051f5L,0x037e388db849140aL, + 0xee4b32b05946dbf6L }, + { 0xb1c4fda9cae368d1L,0x5001a7b0fdb0b2f3L,0x6df593742e3ac46eL, + 0x4af675f239b3e656L } }, + /* 4 << 7 */ + { { 0x44e3811039949296L,0x5b63827b361db1b5L,0x3e5323ed206eaff5L, + 0x942370d2c21f4290L }, + { 0xf2caaf2ee0d985a1L,0x192cc64b7239846dL,0x7c0b8f47ae6312f8L, + 0x7dc61f9196620108L } }, + /* 5 << 7 */ + { { 0xb830fb5bc2da7de9L,0xd0e643df0ff8d3beL,0x31ee77ba188a9641L, + 0x4e8aa3aabcf6d502L }, + { 0xf9fb65329a49110fL,0xd18317f62dd6b220L,0x7e3ced4152c3ea5aL, + 0x0d296a147d579c4aL } }, + /* 6 << 7 */ + { { 0x35d6a53eed4c3717L,0x9f8240cf3d0ed2a3L,0x8c0d4d05e5543aa5L, + 0x45d5bbfbdd33b4b4L }, + { 0xfa04cc73137fd28eL,0x862ac6efc73b3ffdL,0x403ff9f531f51ef2L, + 0x34d5e0fcbc73f5a2L } }, + /* 7 << 7 */ + { { 0xf252682008913f4fL,0xea20ed61eac93d95L,0x51ed38b46ca6b26cL, + 0x8662dcbcea4327b0L }, + { 0x6daf295c725d2aaaL,0xbad2752f8e52dcdaL,0x2210e7210b17daccL, + 0xa37f7912d51e8232L } }, + /* 8 << 7 */ + { { 0x4f7081e144cc3addL,0xd5ffa1d687be82cfL,0x89890b6c0edd6472L, + 0xada26e1a3ed17863L }, + { 0x276f271563483caaL,0xe6924cd92f6077fdL,0x05a7fe980a466e3cL, + 0xf1c794b0b1902d1fL } }, + /* 9 << 7 */ + { { 0xe521368882a8042cL,0xd931cfafcd278298L,0x069a0ae0f597a740L, + 0x0adbb3f3eb59107cL }, + { 0x983e951e5eaa8eb8L,0xe663a8b511b48e78L,0x1631cc0d8a03f2c5L, + 0x7577c11e11e271e2L } }, + /* 10 << 7 */ + { { 0x33b2385c08369a90L,0x2990c59b190eb4f8L,0x819a6145c68eac80L, + 0x7a786d622ec4a014L }, + { 0x33faadbe20ac3a8dL,0x31a217815aba2d30L,0x209d2742dba4f565L, + 0xdb2ce9e355aa0fbbL } }, + /* 11 << 7 */ + { { 0x8cef334b168984dfL,0xe81dce1733879638L,0xf6e6949c263720f0L, + 0x5c56feaff593cbecL }, + { 0x8bff5601fde58c84L,0x74e241172eccb314L,0xbcf01b614c9a8a78L, + 0xa233e35e544c9868L } }, + /* 12 << 7 */ + { { 0xb3156bf38bd7aff1L,0x1b5ee4cb1d81b146L,0x7ba1ac41d628a915L, + 0x8f3a8f9cfd89699eL }, + { 0x7329b9c9a0748be7L,0x1d391c95a92e621fL,0xe51e6b214d10a837L, + 0xd255f53a4947b435L } }, + /* 13 << 7 */ + { { 0x07669e04f1788ee3L,0xc14f27afa86938a2L,0x8b47a334e93a01c0L, + 0xff627438d9366808L }, + { 0x7a0985d8ca2a5965L,0x3d9a5542d6e9b9b3L,0xc23eb80b4cf972e8L, + 0x5c1c33bb4fdf72fdL } }, + /* 14 << 7 */ + { { 0x0c4a58d474a86108L,0xf8048a8fee4c5d90L,0xe3c7c924e86d4c80L, + 0x28c889de056a1e60L }, + { 0x57e2662eb214a040L,0xe8c48e9837e10347L,0x8774286280ac748aL, + 0xf1c24022186b06f2L } }, + /* 15 << 7 */ + { { 0xac2dd4c35f74040aL,0x409aeb71fceac957L,0x4fbad78255c4ec23L, + 0xb359ed618a7b76ecL }, + { 0x12744926ed6f4a60L,0xe21e8d7f4b912de3L,0xe2575a59fc705a59L, + 0x72f1d4deed2dbc0eL } }, + /* 16 << 7 */ + { { 0x3d2b24b9eb7926b8L,0xbff88cb3cdbe5509L,0xd0f399afe4dd640bL, + 0x3c5fe1302f76ed45L }, + { 0x6f3562f43764fb3dL,0x7b5af3183151b62dL,0xd5bd0bc7d79ce5f3L, + 0xfdaf6b20ec66890fL } }, + /* 17 << 7 */ + { { 0x735c67ec6063540cL,0x50b259c2e5f9cb8fL,0xb8734f9a3f99c6abL, + 0xf8cc13d5a3a7bc85L }, + { 0x80c1b305c5217659L,0xfe5364d44ec12a54L,0xbd87045e681345feL, + 0x7f8efeb1582f897fL } }, + /* 18 << 7 */ + { { 0xe8cbf1e5d5923359L,0xdb0cea9d539b9fb0L,0x0c5b34cf49859b98L, + 0x5e583c56a4403cc6L }, + { 0x11fc1a2dd48185b7L,0xc93fbc7e6e521787L,0x47e7a05805105b8bL, + 0x7b4d4d58db8260c8L } }, + /* 19 << 7 */ + { { 0xe33930b046eb842aL,0x8e844a9a7bdae56dL,0x34ef3a9e13f7fdfcL, + 0xb3768f82636ca176L }, + { 0x2821f4e04e09e61cL,0x414dc3a1a0c7cddcL,0xd537943754945fcdL, + 0x151b6eefb3555ff1L } }, + /* 20 << 7 */ + { { 0xb31bd6136339c083L,0x39ff8155dfb64701L,0x7c3388d2e29604abL, + 0x1e19084ba6b10442L }, + { 0x17cf54c0eccd47efL,0x896933854a5dfb30L,0x69d023fb47daf9f6L, + 0x9222840b7d91d959L } }, + /* 21 << 7 */ + { { 0x439108f5803bac62L,0x0b7dd91d379bd45fL,0xd651e827ca63c581L, + 0x5c5d75f6509c104fL }, + { 0x7d5fc7381f2dc308L,0x20faa7bfd98454beL,0x95374beea517b031L, + 0xf036b9b1642692acL } }, + /* 22 << 7 */ + { { 0xc510610939842194L,0xb7e2353e49d05295L,0xfc8c1d5cefb42ee0L, + 0xe04884eb08ce811cL }, + { 0xf1f75d817419f40eL,0x5b0ac162a995c241L,0x120921bbc4c55646L, + 0x713520c28d33cf97L } }, + /* 23 << 7 */ + { { 0xb4a65a5ce98c5100L,0x6cec871d2ddd0f5aL,0x251f0b7f9ba2e78bL, + 0x224a8434ce3a2a5fL }, + { 0x26827f6125f5c46fL,0x6a22bedc48545ec0L,0x25ae5fa0b1bb5cdcL, + 0xd693682ffcb9b98fL } }, + /* 24 << 7 */ + { { 0x32027fe891e5d7d3L,0xf14b7d1773a07678L,0xf88497b3c0dfdd61L, + 0xf7c2eec02a8c4f48L }, + { 0xaa5573f43756e621L,0xc013a2401825b948L,0x1c03b34563878572L, + 0xa0472bea653a4184L } }, + /* 25 << 7 */ + { { 0xf4222e270ac69a80L,0x34096d25f51e54f6L,0x00a648cb8fffa591L, + 0x4e87acdc69b6527fL }, + { 0x0575e037e285ccb4L,0x188089e450ddcf52L,0xaa96c9a8870ff719L, + 0x74a56cd81fc7e369L } }, + /* 26 << 7 */ + { { 0x41d04ee21726931aL,0x0bbbb2c83660ecfdL,0xa6ef6de524818e18L, + 0xe421cc51e7d57887L }, + { 0xf127d208bea87be6L,0x16a475d3b1cdd682L,0x9db1b684439b63f7L, + 0x5359b3dbf0f113b6L } }, + /* 27 << 7 */ + { { 0xdfccf1de8bf06e31L,0x1fdf8f44dd383901L,0x10775cad5017e7d2L, + 0xdfc3a59758d11eefL }, + { 0x6ec9c8a0b1ecff10L,0xee6ed6cc28400549L,0xb5ad7bae1b4f8d73L, + 0x61b4f11de00aaab9L } }, + /* 28 << 7 */ + { { 0x7b32d69bd4eff2d7L,0x88ae67714288b60fL,0x159461b437a1e723L, + 0x1f3d4789570aae8cL }, + { 0x869118c07f9871daL,0x35fbda78f635e278L,0x738f3641e1541dacL, + 0x6794b13ac0dae45fL } }, + /* 29 << 7 */ + { { 0x065064ac09cc0917L,0x27c53729c68540fdL,0x0d2d4c8eef227671L, + 0xd23a9f80a1785a04L }, + { 0x98c5952852650359L,0xfa09ad0174a1acadL,0x082d5a290b55bf5cL, + 0xa40f1c67419b8084L } }, + /* 30 << 7 */ + { { 0x3a5c752edcc18770L,0x4baf1f2f8825c3a5L,0xebd63f7421b153edL, + 0xa2383e47b2f64723L }, + { 0xe7bf620a2646d19aL,0x56cb44ec03c83ffdL,0xaf7267c94f6be9f1L, + 0x8b2dfd7bc06bb5e9L } }, + /* 31 << 7 */ + { { 0xb87072f2a672c5c7L,0xeacb11c80d53c5e2L,0x22dac29dff435932L, + 0x37bdb99d4408693cL }, + { 0xf6e62fb62899c20fL,0x3535d512447ece24L,0xfbdc6b88ff577ce3L, + 0x726693bd190575f2L } }, + /* 32 << 7 */ + { { 0x6772b0e5ab4b35a2L,0x1d8b6001f5eeaacfL,0x728f7ce4795b9580L, + 0x4a20ed2a41fb81daL }, + { 0x9f685cd44fec01e6L,0x3ed7ddcca7ff50adL,0x460fd2640c2d97fdL, + 0x3a241426eb82f4f9L } }, + /* 33 << 7 */ + { { 0x17d1df2c6a8ea820L,0xb2b50d3bf22cc254L,0x03856cbab7291426L, + 0x87fd26ae04f5ee39L }, + { 0x9cb696cc02bee4baL,0x5312180406820fd6L,0xa5dfc2690212e985L, + 0x666f7ffa160f9a09L } }, + /* 34 << 7 */ + { { 0xc503cd33bccd9617L,0x365dede4ba7730a3L,0x798c63555ddb0786L, + 0xa6c3200efc9cd3bcL }, + { 0x060ffb2ce5e35efdL,0x99a4e25b5555a1c1L,0x11d95375f70b3751L, + 0x0a57354a160e1bf6L } }, + /* 35 << 7 */ + { { 0xecb3ae4bf8e4b065L,0x07a834c42e53022bL,0x1cd300b38692ed96L, + 0x16a6f79261ee14ecL }, + { 0x8f1063c66a8649edL,0xfbcdfcfe869f3e14L,0x2cfb97c100a7b3ecL, + 0xcea49b3c7130c2f1L } }, + /* 36 << 7 */ + { { 0x462d044fe9d96488L,0x4b53d52e8182a0c1L,0x84b6ddd30391e9e9L, + 0x80ab7b48b1741a09L }, + { 0xec0e15d427d3317fL,0x8dfc1ddb1a64671eL,0x93cc5d5fd49c5b92L, + 0xc995d53d3674a331L } }, + /* 37 << 7 */ + { { 0x302e41ec090090aeL,0x2278a0ccedb06830L,0x1d025932fbc99690L, + 0x0c32fbd2b80d68daL }, + { 0xd79146daf341a6c1L,0xae0ba1391bef68a0L,0xc6b8a5638d774b3aL, + 0x1cf307bd880ba4d7L } }, + /* 38 << 7 */ + { { 0xc033bdc719803511L,0xa9f97b3b8888c3beL,0x3d68aebc85c6d05eL, + 0xc3b88a9d193919ebL }, + { 0x2d300748c48b0ee3L,0x7506bc7c07a746c1L,0xfc48437c6e6d57f3L, + 0x5bd71587cfeaa91aL } }, + /* 39 << 7 */ + { { 0xa4ed0408c1bc5225L,0xd0b946db2719226dL,0x109ecd62758d2d43L, + 0x75c8485a2751759bL }, + { 0xb0b75f499ce4177aL,0x4fa61a1e79c10c3dL,0xc062d300a167fcd7L, + 0x4df3874c750f0fa8L } }, + /* 40 << 7 */ + { { 0x29ae2cf983dfedc9L,0xf84371348d87631aL,0xaf5717117429c8d2L, + 0x18d15867146d9272L }, + { 0x83053ecf69769bb7L,0xc55eb856c479ab82L,0x5ef7791c21b0f4b2L, + 0xaa5956ba3d491525L } }, + /* 41 << 7 */ + { { 0x407a96c29fe20ebaL,0xf27168bbe52a5ad3L,0x43b60ab3bf1d9d89L, + 0xe45c51ef710e727aL }, + { 0xdfca5276099b4221L,0x8dc6407c2557a159L,0x0ead833591035895L, + 0x0a9db9579c55dc32L } }, + /* 42 << 7 */ + { { 0xe40736d3df61bc76L,0x13a619c03f778cdbL,0x6dd921a4c56ea28fL, + 0x76a524332fa647b4L }, + { 0x23591891ac5bdc5dL,0xff4a1a72bac7dc01L,0x9905e26162df8453L, + 0x3ac045dfe63b265fL } }, + /* 43 << 7 */ + { { 0x8a3f341bad53dba7L,0x8ec269cc837b625aL,0xd71a27823ae31189L, + 0x8fb4f9a355e96120L }, + { 0x804af823ff9875cfL,0x23224f575d442a9bL,0x1c4d3b9eecc62679L, + 0x91da22fba0e7ddb1L } }, + /* 44 << 7 */ + { { 0xa370324d6c04a661L,0x9710d3b65e376d17L,0xed8c98f03044e357L, + 0xc364ebbe6422701cL }, + { 0x347f5d517733d61cL,0xd55644b9cea826c3L,0x80c6e0ad55a25548L, + 0x0aa7641d844220a7L } }, + /* 45 << 7 */ + { { 0x1438ec8131810660L,0x9dfa6507de4b4043L,0x10b515d8cc3e0273L, + 0x1b6066dd28d8cfb2L }, + { 0xd3b045919c9efebdL,0x425d4bdfa21c1ff4L,0x5fe5af19d57607d3L, + 0xbbf773f754481084L } }, + /* 46 << 7 */ + { { 0x8435bd6994b03ed1L,0xd9ad1de3634cc546L,0x2cf423fc00e420caL, + 0xeed26d80a03096ddL }, + { 0xd7f60be7a4db09d2L,0xf47f569d960622f7L,0xe5925fd77296c729L, + 0xeff2db2626ca2715L } }, + /* 47 << 7 */ + { { 0xa6fcd014b913e759L,0x53da47868ff4de93L,0x14616d79c32068e1L, + 0xb187d664ccdf352eL }, + { 0xf7afb6501dc90b59L,0x8170e9437daa1b26L,0xc8e3bdd8700c0a84L, + 0x6e8d345f6482bdfaL } }, + /* 48 << 7 */ + { { 0x84cfbfa1c5c5ea50L,0xd3baf14c67960681L,0x263984030dd50942L, + 0xe4b7839c4716a663L }, + { 0xd5f1f794e7de6dc0L,0x5cd0f4d4622aa7ceL,0x5295f3f159acfeecL, + 0x8d933552953e0607L } }, + /* 49 << 7 */ + { { 0xc7db8ec5776c5722L,0xdc467e622b5f290cL,0xd4297e704ff425a9L, + 0x4be924c10cf7bb72L }, + { 0x0d5dc5aea1892131L,0x8bf8a8e3a705c992L,0x73a0b0647a305ac5L, + 0x00c9ca4e9a8c77a8L } }, + /* 50 << 7 */ + { { 0x5dfee80f83774bddL,0x6313160285734485L,0xa1b524ae914a69a9L, + 0xebc2ffafd4e300d7L }, + { 0x52c93db77cfa46a5L,0x71e6161f21653b50L,0x3574fc57a4bc580aL, + 0xc09015dde1bc1253L } }, + /* 51 << 7 */ + { { 0x4b7b47b2d174d7aaL,0x4072d8e8f3a15d04L,0xeeb7d47fd6fa07edL, + 0x6f2b9ff9edbdafb1L }, + { 0x18c516153760fe8aL,0x7a96e6bff06c6c13L,0x4d7a04100ea2d071L, + 0xa1914e9b0be2a5ceL } }, + /* 52 << 7 */ + { { 0x5726e357d8a3c5cfL,0x1197ecc32abb2b13L,0x6c0d7f7f31ae88ddL, + 0x15b20d1afdbb3efeL }, + { 0xcd06aa2670584039L,0x2277c969a7dc9747L,0xbca695877855d815L, + 0x899ea2385188b32aL } }, + /* 53 << 7 */ + { { 0x37d9228b760c1c9dL,0xc7efbb119b5c18daL,0x7f0d1bc819f6dbc5L, + 0x4875384b07e6905bL }, + { 0xc7c50baa3ba8cd86L,0xb0ce40fbc2905de0L,0x708406737a231952L, + 0xa912a262cf43de26L } }, + /* 54 << 7 */ + { { 0x9c38ddcceb5b76c1L,0x746f528526fc0ab4L,0x52a63a50d62c269fL, + 0x60049c5599458621L }, + { 0xe7f48f823c2f7c9eL,0x6bd99043917d5cf3L,0xeb1317a88701f469L, + 0xbd3fe2ed9a449fe0L } }, + /* 55 << 7 */ + { { 0x421e79ca12ef3d36L,0x9ee3c36c3e7ea5deL,0xe48198b5cdff36f7L, + 0xaff4f967c6b82228L }, + { 0x15e19dd0c47adb7eL,0x45699b23032e7dfaL,0x40680c8b1fae026aL, + 0x5a347a48550dbf4dL } }, + /* 56 << 7 */ + { { 0xe652533b3cef0d7dL,0xd94f7b182bbb4381L,0x838752be0e80f500L, + 0x8e6e24889e9c9bfbL }, + { 0xc975169716caca6aL,0x866c49d838531ad9L,0xc917e2397151ade1L, + 0x2d016ec16037c407L } }, + /* 57 << 7 */ + { { 0xa407ccc900eac3f9L,0x835f6280e2ed4748L,0xcc54c3471cc98e0dL, + 0x0e969937dcb572ebL }, + { 0x1b16c8e88f30c9cbL,0xa606ae75373c4661L,0x47aa689b35502cabL, + 0xf89014ae4d9bb64fL } }, + /* 58 << 7 */ + { { 0x202f6a9c31c71f7bL,0x01f95aa3296ffe5cL,0x5fc0601453cec3a3L, + 0xeb9912375f498a45L }, + { 0xae9a935e5d91ba87L,0xc6ac62810b564a19L,0x8a8fe81c3bd44e69L, + 0x7c8b467f9dd11d45L } }, + /* 59 << 7 */ + { { 0xf772251fea5b8e69L,0xaeecb3bdc5b75fbcL,0x1aca3331887ff0e5L, + 0xbe5d49ff19f0a131L }, + { 0x582c13aae5c8646fL,0xdbaa12e820e19980L,0x8f40f31af7abbd94L, + 0x1f13f5a81dfc7663L } }, + /* 60 << 7 */ + { { 0x5d81f1eeaceb4fc0L,0x362560025e6f0f42L,0x4b67d6d7751370c8L, + 0x2608b69803e80589L }, + { 0xcfc0d2fc05268301L,0xa6943d3940309212L,0x192a90c21fd0e1c2L, + 0xb209f11337f1dc76L } }, + /* 61 << 7 */ + { { 0xefcc5e0697bf1298L,0xcbdb6730219d639eL,0xd009c116b81e8c6fL, + 0xa3ffdde31a7ce2e5L }, + { 0xc53fbaaaa914d3baL,0x836d500f88df85eeL,0xd98dc71b66ee0751L, + 0x5a3d7005714516fdL } }, + /* 62 << 7 */ + { { 0x21d3634d39eedbbaL,0x35cd2e680455a46dL,0xc8cafe65f9d7eb0cL, + 0xbda3ce9e00cefb3eL }, + { 0xddc17a602c9cf7a4L,0x01572ee47bcb8773L,0xa92b2b018c7548dfL, + 0x732fd309a84600e3L } }, + /* 63 << 7 */ + { { 0xe22109c716543a40L,0x9acafd36fede3c6cL,0xfb2068526824e614L, + 0x2a4544a9da25dca0L }, + { 0x2598526291d60b06L,0x281b7be928753545L,0xec667b1a90f13b27L, + 0x33a83aff940e2eb4L } }, + /* 64 << 7 */ + { { 0x80009862d5d721d5L,0x0c3357a35bd3a182L,0x27f3a83b7aa2cda4L, + 0xb58ae74ef6f83085L }, + { 0x2a911a812e6dad6bL,0xde286051f43d6c5bL,0x4bdccc41f996c4d8L, + 0xe7312ec00ae1e24eL } }, + /* 0 << 14 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 14 */ + { { 0xf8d112e76e6485b3L,0x4d3e24db771c52f8L,0x48e3ee41684a2f6dL, + 0x7161957d21d95551L }, + { 0x19631283cdb12a6cL,0xbf3fa8822e50e164L,0xf6254b633166cc73L, + 0x3aefa7aeaee8cc38L } }, + /* 2 << 14 */ + { { 0x79b0fe623b36f9fdL,0x26543b23fde19fc0L,0x136e64a0958482efL, + 0x23f637719b095825L }, + { 0x14cfd596b6a1142eL,0x5ea6aac6335aac0bL,0x86a0e8bdf3081dd5L, + 0x5fb89d79003dc12aL } }, + /* 3 << 14 */ + { { 0xf615c33af72e34d4L,0x0bd9ea40110eec35L,0x1c12bc5bc1dea34eL, + 0x686584c949ae4699L }, + { 0x13ad95d38c97b942L,0x4609561a4e5c7562L,0x9e94a4aef2737f89L, + 0xf57594c6371c78b6L } }, + /* 4 << 14 */ + { { 0x0f0165fce3779ee3L,0xe00e7f9dbd495d9eL,0x1fa4efa220284e7aL, + 0x4564bade47ac6219L }, + { 0x90e6312ac4708e8eL,0x4f5725fba71e9adfL,0xe95f55ae3d684b9fL, + 0x47f7ccb11e94b415L } }, + /* 5 << 14 */ + { { 0x7322851b8d946581L,0xf0d13133bdf4a012L,0xa3510f696584dae0L, + 0x03a7c1713c9f6c6dL }, + { 0x5be97f38e475381aL,0xca1ba42285823334L,0xf83cc5c70be17ddaL, + 0x158b14940b918c0fL } }, + /* 6 << 14 */ + { { 0xda3a77e5522e6b69L,0x69c908c3bbcd6c18L,0x1f1b9e48d924fd56L, + 0x37c64e36aa4bb3f7L }, + { 0x5a4fdbdfee478d7dL,0xba75c8bc0193f7a0L,0x84bc1e8456cd16dfL, + 0x1fb08f0846fad151L } }, + /* 7 << 14 */ + { { 0x8a7cabf9842e9f30L,0xa331d4bf5eab83afL,0xd272cfba017f2a6aL, + 0x27560abc83aba0e3L }, + { 0x94b833870e3a6b75L,0x25c6aea26b9f50f5L,0x803d691db5fdf6d0L, + 0x03b77509e6333514L } }, + /* 8 << 14 */ + { { 0x3617890361a341c1L,0x3604dc600cfd6142L,0x022295eb8533316cL, + 0x3dbde4ac44af2922L }, + { 0x898afc5d1c7eef69L,0x58896805d14f4fa1L,0x05002160203c21caL, + 0x6f0d1f3040ef730bL } }, + /* 9 << 14 */ + { { 0x8e8c44d4196224f8L,0x75a4ab95374d079dL,0x79085ecc7d48f123L, + 0x56f04d311bf65ad8L }, + { 0xe220bf1cbda602b2L,0x73ee1742f9612c69L,0x76008fc8084fd06bL, + 0x4000ef9ff11380d1L } }, + /* 10 << 14 */ + { { 0x48201b4b12cfe297L,0x3eee129c292f74e5L,0xe1fe114ec9e874e8L, + 0x899b055c92c5fc41L }, + { 0x4e477a643a39c8cfL,0x82f09efe78963cc9L,0x6fd3fd8fd333f863L, + 0x85132b2adc949c63L } }, + /* 11 << 14 */ + { { 0x7e06a3ab516eb17bL,0x73bec06fd2c7372bL,0xe4f74f55ba896da6L, + 0xbb4afef88e9eb40fL }, + { 0x2d75bec8e61d66b0L,0x02bda4b4ef29300bL,0x8bbaa8de026baa5aL, + 0xff54befda07f4440L } }, + /* 12 << 14 */ + { { 0xbd9b8b1dbe7a2af3L,0xec51caa94fb74a72L,0xb9937a4b63879697L, + 0x7c9a9d20ec2687d5L }, + { 0x1773e44f6ef5f014L,0x8abcf412e90c6900L,0x387bd0228142161eL, + 0x50393755fcb6ff2aL } }, + /* 13 << 14 */ + { { 0x9813fd56ed6def63L,0x53cf64827d53106cL,0x991a35bd431f7ac1L, + 0xf1e274dd63e65fafL }, + { 0xf63ffa3c44cc7880L,0x411a426b7c256981L,0xb698b9fd93a420e0L, + 0x89fdddc0ae53f8feL } }, + /* 14 << 14 */ + { { 0x766e072232398baaL,0x205fee425cfca031L,0xa49f53417a029cf2L, + 0xa88c68b84023890dL }, + { 0xbc2750417337aaa8L,0x9ed364ad0eb384f4L,0xe0816f8529aba92fL, + 0x2e9e194104e38a88L } }, + /* 15 << 14 */ + { { 0x57eef44a3dafd2d5L,0x35d1fae597ed98d8L,0x50628c092307f9b1L, + 0x09d84aaed6cba5c6L }, + { 0x67071bc788aaa691L,0x2dea57a9afe6cb03L,0xdfe11bb43d78ac01L, + 0x7286418c7fd7aa51L } }, + /* 16 << 14 */ + { { 0xfabf770977f7195aL,0x8ec86167adeb838fL,0xea1285a8bb4f012dL, + 0xd68835039a3eab3fL }, + { 0xee5d24f8309004c2L,0xa96e4b7613ffe95eL,0x0cdffe12bd223ea4L, + 0x8f5c2ee5b6739a53L } }, + /* 17 << 14 */ + { { 0x5cb4aaa5dd968198L,0xfa131c5272413a6cL,0x53d46a909536d903L, + 0xb270f0d348606d8eL }, + { 0x518c7564a053a3bcL,0x088254b71a86caefL,0xb3ba8cb40ab5efd0L, + 0x5c59900e4605945dL } }, + /* 18 << 14 */ + { { 0xecace1dda1887395L,0x40960f36932a65deL,0x9611ff5c3aa95529L, + 0xc58215b07c1e5a36L }, + { 0xd48c9b58f0e1a524L,0xb406856bf590dfb8L,0xc7605e049cd95662L, + 0x0dd036eea33ecf82L } }, + /* 19 << 14 */ + { { 0xa50171acc33156b3L,0xf09d24ea4a80172eL,0x4e1f72c676dc8eefL, + 0xe60caadc5e3d44eeL }, + { 0x006ef8a6979b1d8fL,0x60908a1c97788d26L,0x6e08f95b266feec0L, + 0x618427c222e8c94eL } }, + /* 20 << 14 */ + { { 0x3d61333959145a65L,0xcd9bc368fa406337L,0x82d11be32d8a52a0L, + 0xf6877b2797a1c590L }, + { 0x837a819bf5cbdb25L,0x2a4fd1d8de090249L,0x622a7de774990e5fL, + 0x840fa5a07945511bL } }, + /* 21 << 14 */ + { { 0x30b974be6558842dL,0x70df8c6417f3d0a6L,0x7c8035207542e46dL, + 0x7251fe7fe4ecc823L }, + { 0xe59134cb5e9aac9aL,0x11bb0934f0045d71L,0x53e5d9b5dbcb1d4eL, + 0x8d97a90592defc91L } }, + /* 22 << 14 */ + { { 0xfe2893277946d3f9L,0xe132bd2407472273L,0xeeeb510c1eb6ae86L, + 0x777708c5f0595067L }, + { 0x18e2c8cd1297029eL,0x2c61095cbbf9305eL,0xe466c2586b85d6d9L, + 0x8ac06c36da1ea530L } }, + /* 23 << 14 */ + { { 0xa365dc39a1304668L,0xe4a9c88507f89606L,0x65a4898facc7228dL, + 0x3e2347ff84ca8303L }, + { 0xa5f6fb77ea7d23a3L,0x2fac257d672a71cdL,0x6908bef87e6a44d3L, + 0x8ff87566891d3d7aL } }, + /* 24 << 14 */ + { { 0xe58e90b36b0cf82eL,0x6438d2462615b5e7L,0x07b1f8fc669c145aL, + 0xb0d8b2da36f1e1cbL }, + { 0x54d5dadbd9184c4dL,0x3dbb18d5f93d9976L,0x0a3e0f56d1147d47L, + 0x2afa8c8da0a48609L } }, + /* 25 << 14 */ + { { 0x275353e8bc36742cL,0x898f427eeea0ed90L,0x26f4947e3e477b00L, + 0x8ad8848a308741e3L }, + { 0x6c703c38d74a2a46L,0x5e3e05a99ba17ba2L,0xc1fa6f664ab9a9e4L, + 0x474a2d9a3841d6ecL } }, + /* 26 << 14 */ + { { 0x871239ad653ae326L,0x14bcf72aa74cbb43L,0x8737650e20d4c083L, + 0x3df86536110ed4afL }, + { 0xd2d86fe7b53ca555L,0x688cb00dabd5d538L,0xcf81bda31ad38468L, + 0x7ccfe3ccf01167b6L } }, + /* 27 << 14 */ + { { 0xcf4f47e06c4c1fe6L,0x557e1f1a298bbb79L,0xf93b974f30d45a14L, + 0x174a1d2d0baf97c4L }, + { 0x7a003b30c51fbf53L,0xd8940991ee68b225L,0x5b0aa7b71c0f4173L, + 0x975797c9a20a7153L } }, + /* 28 << 14 */ + { { 0x26e08c07e3533d77L,0xd7222e6a2e341c99L,0x9d60ec3d8d2dc4edL, + 0xbdfe0d8f7c476cf8L }, + { 0x1fe59ab61d056605L,0xa9ea9df686a8551fL,0x8489941e47fb8d8cL, + 0xfeb874eb4a7f1b10L } }, + /* 29 << 14 */ + { { 0xfe5fea867ee0d98fL,0x201ad34bdbf61864L,0x45d8fe4737c031d4L, + 0xd5f49fae795f0822L }, + { 0xdb0fb291c7f4a40cL,0x2e69d9c1730ddd92L,0x754e105449d76987L, + 0x8a24911d7662db87L } }, + /* 30 << 14 */ + { { 0x61fc181060a71676L,0xe852d1a8f66a8ad1L,0x172bbd656417231eL, + 0x0d6de7bd3babb11fL }, + { 0x6fde6f88c8e347f8L,0x1c5875479bd99cc3L,0x78e54ed034076950L, + 0x97f0f334796e83baL } }, + /* 31 << 14 */ + { { 0xe4dbe1ce4924867aL,0xbd5f51b060b84917L,0x375300403cb09a79L, + 0xdb3fe0f8ff1743d8L }, + { 0xed7894d8556fa9dbL,0xfa26216923412fbfL,0x563be0dbba7b9291L, + 0x6ca8b8c00c9fb234L } }, + /* 32 << 14 */ + { { 0xed406aa9bd763802L,0xc21486a065303da1L,0x61ae291ec7e62ec4L, + 0x622a0492df99333eL }, + { 0x7fd80c9dbb7a8ee0L,0xdc2ed3bc6c01aedbL,0x35c35a1208be74ecL, + 0xd540cb1a469f671fL } }, + /* 33 << 14 */ + { { 0xd16ced4ecf84f6c7L,0x8561fb9c2d090f43L,0x7e693d796f239db4L, + 0xa736f92877bd0d94L }, + { 0x07b4d9292c1950eeL,0xda17754356dc11b3L,0xa5dfbbaa7a6a878eL, + 0x1c70cb294decb08aL } }, + /* 34 << 14 */ + { { 0xfba28c8b6f0f7c50L,0xa8eba2b8854dcc6dL,0x5ff8e89a36b78642L, + 0x070c1c8ef6873adfL }, + { 0xbbd3c3716484d2e4L,0xfb78318f0d414129L,0x2621a39c6ad93b0bL, + 0x979d74c2a9e917f7L } }, + /* 35 << 14 */ + { { 0xfc19564761fb0428L,0x4d78954abee624d4L,0xb94896e0b8ae86fdL, + 0x6667ac0cc91c8b13L }, + { 0x9f18051243bcf832L,0xfbadf8b7a0010137L,0xc69b4089b3ba8aa7L, + 0xfac4bacde687ce85L } }, + /* 36 << 14 */ + { { 0x9164088d977eab40L,0x51f4c5b62760b390L,0xd238238f340dd553L, + 0x358566c3db1d31c9L }, + { 0x3a5ad69e5068f5ffL,0xf31435fcdaff6b06L,0xae549a5bd6debff0L, + 0x59e5f0b775e01331L } }, + /* 37 << 14 */ + { { 0x5d492fb898559acfL,0x96018c2e4db79b50L,0x55f4a48f609f66aaL, + 0x1943b3af4900a14fL }, + { 0xc22496df15a40d39L,0xb2a446844c20f7c5L,0x76a35afa3b98404cL, + 0xbec75725ff5d1b77L } }, + /* 38 << 14 */ + { { 0xb67aa163bea06444L,0x27e95bb2f724b6f2L,0x3c20e3e9d238c8abL, + 0x1213754eddd6ae17L }, + { 0x8c431020716e0f74L,0x6679c82effc095c2L,0x2eb3adf4d0ac2932L, + 0x2cc970d301bb7a76L } }, + /* 39 << 14 */ + { { 0x70c71f2f740f0e66L,0x545c616b2b6b23ccL,0x4528cfcbb40a8bd7L, + 0xff8396332ab27722L }, + { 0x049127d9025ac99aL,0xd314d4a02b63e33bL,0xc8c310e728d84519L, + 0x0fcb8983b3bc84baL } }, + /* 40 << 14 */ + { { 0x2cc5226138634818L,0x501814f4b44c2e0bL,0xf7e181aa54dfdba3L, + 0xcfd58ff0e759718cL }, + { 0xf90cdb14d3b507a8L,0x57bd478ec50bdad8L,0x29c197e250e5f9aaL, + 0x4db6eef8e40bc855L } }, + /* 41 << 14 */ + { { 0x2cc8f21ad1fc0654L,0xc71cc96381269d73L,0xecfbb204077f49f9L, + 0xdde92571ca56b793L }, + { 0x9abed6a3f97ad8f7L,0xe6c19d3f924de3bdL,0x8dce92f4a140a800L, + 0x85f44d1e1337af07L } }, + /* 42 << 14 */ + { { 0x5953c08b09d64c52L,0xa1b5e49ff5df9749L,0x336a8fb852735f7dL, + 0xb332b6db9add676bL }, + { 0x558b88a0b4511aa4L,0x09788752dbd5cc55L,0x16b43b9cd8cd52bdL, + 0x7f0bc5a0c2a2696bL } }, + /* 43 << 14 */ + { { 0x146e12d4c11f61efL,0x9ce107543a83e79eL,0x08ec73d96cbfca15L, + 0x09ff29ad5b49653fL }, + { 0xe31b72bde7da946eL,0xebf9eb3bee80a4f2L,0xd1aabd0817598ce4L, + 0x18b5fef453f37e80L } }, + /* 44 << 14 */ + { { 0xd5d5cdd35958cd79L,0x3580a1b51d373114L,0xa36e4c91fa935726L, + 0xa38c534def20d760L }, + { 0x7088e40a2ff5845bL,0xe5bb40bdbd78177fL,0x4f06a7a8857f9920L, + 0xe3cc3e50e968f05dL } }, + /* 45 << 14 */ + { { 0x1d68b7fee5682d26L,0x5206f76faec7f87cL,0x41110530041951abL, + 0x58ec52c1d4b5a71aL }, + { 0xf3488f990f75cf9aL,0xf411951fba82d0d5L,0x27ee75be618895abL, + 0xeae060d46d8aab14L } }, + /* 46 << 14 */ + { { 0x9ae1df737fb54dc2L,0x1f3e391b25963649L,0x242ec32afe055081L, + 0x5bd450ef8491c9bdL }, + { 0x367efc67981eb389L,0xed7e19283a0550d5L,0x362e776bab3ce75cL, + 0xe890e3081f24c523L } }, + /* 47 << 14 */ + { { 0xb961b682feccef76L,0x8b8e11f58bba6d92L,0x8f2ccc4c2b2375c4L, + 0x0d7f7a52e2f86cfaL }, + { 0xfd94d30a9efe5633L,0x2d8d246b5451f934L,0x2234c6e3244e6a00L, + 0xde2b5b0dddec8c50L } }, + /* 48 << 14 */ + { { 0x2ce53c5abf776f5bL,0x6f72407160357b05L,0xb259371771bf3f7aL, + 0x87d2501c440c4a9fL }, + { 0x440552e187b05340L,0xb7bf7cc821624c32L,0x4155a6ce22facddbL, + 0x5a4228cb889837efL } }, + /* 49 << 14 */ + { { 0xef87d6d6fd4fd671L,0xa233687ec2daa10eL,0x7562224403c0eb96L, + 0x7632d1848bf19be6L }, + { 0x05d0f8e940735ff4L,0x3a3e6e13c00931f1L,0x31ccde6adafe3f18L, + 0xf381366acfe51207L } }, + /* 50 << 14 */ + { { 0x24c222a960167d92L,0x62f9d6f87529f18cL,0x412397c00353b114L, + 0x334d89dcef808043L }, + { 0xd9ec63ba2a4383ceL,0xcec8e9375cf92ba0L,0xfb8b4288c8be74c0L, + 0x67d6912f105d4391L } }, + /* 51 << 14 */ + { { 0x7b996c461b913149L,0x36aae2ef3a4e02daL,0xb68aa003972de594L, + 0x284ec70d4ec6d545L }, + { 0xf3d2b2d061391d54L,0x69c5d5d6fe114e92L,0xbe0f00b5b4482dffL, + 0xe1596fa5f5bf33c5L } }, + /* 52 << 14 */ + { { 0x10595b5696a71cbaL,0x944938b2fdcadeb7L,0xa282da4cfccd8471L, + 0x98ec05f30d37bfe1L }, + { 0xe171ce1b0698304aL,0x2d69144421bdf79bL,0xd0cd3b741b21dec1L, + 0x712ecd8b16a15f71L } }, + /* 53 << 14 */ + { { 0x8d4c00a700fd56e1L,0x02ec9692f9527c18L,0x21c449374a3e42e1L, + 0x9176fbab1392ae0aL }, + { 0x8726f1ba44b7b618L,0xb4d7aae9f1de491cL,0xf91df7b907b582c0L, + 0x7e116c30ef60aa3aL } }, + /* 54 << 14 */ + { { 0x99270f81466265d7L,0xb15b6fe24df7adf0L,0xfe33b2d3f9738f7fL, + 0x48553ab9d6d70f95L }, + { 0x2cc72ac8c21e94dbL,0x795ac38dbdc0bbeeL,0x0a1be4492e40478fL, + 0x81bd3394052bde55L } }, + /* 55 << 14 */ + { { 0x63c8dbe956b3c4f2L,0x017a99cf904177ccL,0x947bbddb4d010fc1L, + 0xacf9b00bbb2c9b21L }, + { 0x2970bc8d47173611L,0x1a4cbe08ac7d756fL,0x06d9f4aa67d541a2L, + 0xa3e8b68959c2cf44L } }, + /* 56 << 14 */ + { { 0xaad066da4d88f1ddL,0xc604f1657ad35deaL,0x7edc07204478ca67L, + 0xa10dfae0ba02ce06L }, + { 0xeceb1c76af36f4e4L,0x994b2292af3f8f48L,0xbf9ed77b77c8a68cL, + 0x74f544ea51744c9dL } }, + /* 57 << 14 */ + { { 0x82d05bb98113a757L,0x4ef2d2b48a9885e4L,0x1e332be51aa7865fL, + 0x22b76b18290d1a52L }, + { 0x308a231044351683L,0x9d861896a3f22840L,0x5959ddcd841ed947L, + 0x0def0c94154b73bfL } }, + /* 58 << 14 */ + { { 0xf01054174c7c15e0L,0x539bfb023a277c32L,0xe699268ef9dccf5fL, + 0x9f5796a50247a3bdL }, + { 0x8b839de84f157269L,0xc825c1e57a30196bL,0x6ef0aabcdc8a5a91L, + 0xf4a8ce6c498b7fe6L } }, + /* 59 << 14 */ + { { 0x1cce35a770cbac78L,0x83488e9bf6b23958L,0x0341a070d76cb011L, + 0xda6c9d06ae1b2658L }, + { 0xb701fb30dd648c52L,0x994ca02c52fb9fd1L,0x069331176f563086L, + 0x3d2b810017856babL } }, + /* 60 << 14 */ + { { 0xe89f48c85963a46eL,0x658ab875a99e61c7L,0x6e296f874b8517b4L, + 0x36c4fcdcfc1bc656L }, + { 0xde5227a1a3906defL,0x9fe95f5762418945L,0x20c91e81fdd96cdeL, + 0x5adbe47eda4480deL } }, + /* 61 << 14 */ + { { 0xa009370f396de2b6L,0x98583d4bf0ecc7bdL,0xf44f6b57e51d0672L, + 0x03d6b078556b1984L }, + { 0x27dbdd93b0b64912L,0x9b3a343415687b09L,0x0dba646151ec20a9L, + 0xec93db7fff28187cL } }, + /* 62 << 14 */ + { { 0x00ff8c2466e48bddL,0x2514f2f911ccd78eL,0xeba11f4fe1250603L, + 0x8a22cd41243fa156L }, + { 0xa4e58df4b283e4c6L,0x78c298598b39783fL,0x5235aee2a5259809L, + 0xc16284b50e0227ddL } }, + /* 63 << 14 */ + { { 0xa5f579161338830dL,0x6d4b8a6bd2123fcaL,0x236ea68af9c546f8L, + 0xc1d36873fa608d36L }, + { 0xcd76e4958d436d13L,0xd4d9c2218fb080afL,0x665c1728e8ad3fb5L, + 0xcf1ebe4db3d572e0L } }, + /* 64 << 14 */ + { { 0xa7a8746a584c5e20L,0x267e4ea1b9dc7035L,0x593a15cfb9548c9bL, + 0x5e6e21354bd012f3L }, + { 0xdf31cc6a8c8f936eL,0x8af84d04b5c241dcL,0x63990a6f345efb86L, + 0x6fef4e61b9b962cbL } }, + /* 0 << 21 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 21 */ + { { 0xf6368f0925722608L,0x131260db131cf5c6L,0x40eb353bfab4f7acL, + 0x85c7888037eee829L }, + { 0x4c1581ffc3bdf24eL,0x5bff75cbf5c3c5a8L,0x35e8c83fa14e6f40L, + 0xb81d1c0f0295e0caL } }, + /* 2 << 21 */ + { { 0xfcde7cc8f43a730fL,0xe89b6f3c33ab590eL,0xc823f529ad03240bL, + 0x82b79afe98bea5dbL }, + { 0x568f2856962fe5deL,0x0c590adb60c591f3L,0x1fc74a144a28a858L, + 0x3b662498b3203f4cL } }, + /* 3 << 21 */ + { { 0x91e3cf0d6c39765aL,0xa2db3acdac3cca0bL,0x288f2f08cb953b50L, + 0x2414582ccf43cf1aL }, + { 0x8dec8bbc60eee9a8L,0x54c79f02729aa042L,0xd81cd5ec6532f5d5L, + 0xa672303acf82e15fL } }, + /* 4 << 21 */ + { { 0x376aafa8719c0563L,0xcd8ad2dcbc5fc79fL,0x303fdb9fcb750cd3L, + 0x14ff052f4418b08eL }, + { 0xf75084cf3e2d6520L,0x7ebdf0f8144ed509L,0xf43bf0f2d3f25b98L, + 0x86ad71cfa354d837L } }, + /* 5 << 21 */ + { { 0xb827fe9226f43572L,0xdfd3ab5b5d824758L,0x315dd23a539094c1L, + 0x85c0e37a66623d68L }, + { 0x575c79727be19ae0L,0x616a3396df0d36b5L,0xa1ebb3c826b1ff7eL, + 0x635b9485140ad453L } }, + /* 6 << 21 */ + { { 0x92bf3cdada430c0bL,0x4702850e3a96dac6L,0xc91cf0a515ac326aL, + 0x95de4f49ab8c25e4L }, + { 0xb01bad09e265c17cL,0x24e45464087b3881L,0xd43e583ce1fac5caL, + 0xe17cb3186ead97a6L } }, + /* 7 << 21 */ + { { 0x6cc3924374dcec46L,0x33cfc02d54c2b73fL,0x82917844f26cd99cL, + 0x8819dd95d1773f89L }, + { 0x09572aa60871f427L,0x8e0cf365f6f01c34L,0x7fa52988bff1f5afL, + 0x4eb357eae75e8e50L } }, + /* 8 << 21 */ + { { 0xd9d0c8c4868af75dL,0xd7325cff45c8c7eaL,0xab471996cc81ecb0L, + 0xff5d55f3611824edL }, + { 0xbe3145411977a0eeL,0x5085c4c5722038c6L,0x2d5335bff94bb495L, + 0x894ad8a6c8e2a082L } }, + /* 9 << 21 */ + { { 0x5c3e2341ada35438L,0xf4a9fc89049b8c4eL,0xbeeb355a9f17cf34L, + 0x3f311e0e6c91fe10L }, + { 0xc2d2003892ab9891L,0x257bdcc13e8ce9a9L,0x1b2d978988c53beeL, + 0x927ce89acdba143aL } }, + /* 10 << 21 */ + { { 0xb0a32cca523db280L,0x5c889f8a50d43783L,0x503e04b34897d16fL, + 0x8cdb6e7808f5f2e8L }, + { 0x6ab91cf0179c8e74L,0xd8874e5248211d60L,0xf948d4d5ea851200L, + 0x4076d41ee6f9840aL } }, + /* 11 << 21 */ + { { 0xc20e263c47b517eaL,0x79a448fd30685e5eL,0xe55f6f78f90631a0L, + 0x88a790b1a79e6346L }, + { 0x62160c7d80969fe8L,0x54f92fd441491bb9L,0xa6645c235c957526L, + 0xf44cc5aebea3ce7bL } }, + /* 12 << 21 */ + { { 0xf76283278b1e68b7L,0xc731ad7a303f29d3L,0xfe5a9ca957d03ecbL, + 0x96c0d50c41bc97a7L }, + { 0xc4669fe79b4f7f24L,0xfdd781d83d9967efL,0x7892c7c35d2c208dL, + 0x8bf64f7cae545cb3L } }, + /* 13 << 21 */ + { { 0xc01f862c467be912L,0xf4c85ee9c73d30ccL,0x1fa6f4be6ab83ec7L, + 0xa07a3c1c4e3e3cf9L }, + { 0x87f8ef450c00beb3L,0x30e2c2b3000d4c3eL,0x1aa00b94fe08bf5bL, + 0x32c133aa9224ef52L } }, + /* 14 << 21 */ + { { 0x38df16bb32e5685dL,0x68a9e06958e6f544L,0x495aaff7cdc5ebc6L, + 0xf894a645378b135fL }, + { 0xf316350a09e27ecfL,0xeced201e58f7179dL,0x2eec273ce97861baL, + 0x47ec2caed693be2eL } }, + /* 15 << 21 */ + { { 0xfa4c97c4f68367ceL,0xe4f47d0bbe5a5755L,0x17de815db298a979L, + 0xd7eca659c177dc7dL }, + { 0x20fdbb7149ded0a3L,0x4cb2aad4fb34d3c5L,0x2cf31d2860858a33L, + 0x3b6873efa24aa40fL } }, + /* 16 << 21 */ + { { 0x540234b22c11bb37L,0x2d0366dded4c74a3L,0xf9a968daeec5f25dL, + 0x3660106867b63142L }, + { 0x07cd6d2c68d7b6d4L,0xa8f74f090c842942L,0xe27514047768b1eeL, + 0x4b5f7e89fe62aee4L } }, + /* 17 << 21 */ + { { 0xc6a7717789070d26L,0xa1f28e4edd1c8bc7L,0xea5f4f06469e1f17L, + 0x78fc242afbdb78e0L }, + { 0xc9c7c5928b0588f1L,0xb6b7a0fd1535921eL,0xcc5bdb91bde5ae35L, + 0xb42c485e12ff1864L } }, + /* 18 << 21 */ + { { 0xa1113e13dbab98aaL,0xde9d469ba17b1024L,0x23f48b37c0462d3aL, + 0x3752e5377c5c078dL }, + { 0xe3a86add15544eb9L,0xf013aea780fba279L,0x8b5bb76cf22001b5L, + 0xe617ba14f02891abL } }, + /* 19 << 21 */ + { { 0xd39182a6936219d3L,0x5ce1f194ae51cb19L,0xc78f8598bf07a74cL, + 0x6d7158f222cbf1bcL }, + { 0x3b846b21e300ce18L,0x35fba6302d11275dL,0x5fe25c36a0239b9bL, + 0xd8beb35ddf05d940L } }, + /* 20 << 21 */ + { { 0x4db02bb01f7e320dL,0x0641c3646da320eaL,0x6d95fa5d821389a3L, + 0x926997488fcd8e3dL }, + { 0x316fef17ceb6c143L,0x67fcb841d933762bL,0xbb837e35118b17f8L, + 0x4b92552f9fd24821L } }, + /* 21 << 21 */ + { { 0xae6bc70e46aca793L,0x1cf0b0e4e579311bL,0x8dc631be5802f716L, + 0x099bdc6fbddbee4dL }, + { 0xcc352bb20caf8b05L,0xf74d505a72d63df2L,0xb9876d4b91c4f408L, + 0x1ce184739e229b2dL } }, + /* 22 << 21 */ + { { 0x4950759783abdb4aL,0x850fbcb6dee84b18L,0x6325236e609e67dcL, + 0x04d831d99336c6d8L }, + { 0x8deaae3bfa12d45dL,0xe425f8ce4746e246L,0x8004c17524f5f31eL, + 0xaca16d8fad62c3b7L } }, + /* 23 << 21 */ + { { 0x0dc15a6a9152f934L,0xf1235e5ded0e12c1L,0xc33c06ecda477dacL, + 0x76be8732b2ea0006L }, + { 0xcf3f78310c0cd313L,0x3c524553a614260dL,0x31a756f8cab22d15L, + 0x03ee10d177827a20L } }, + /* 24 << 21 */ + { { 0xd1e059b21994ef20L,0x2a653b69638ae318L,0x70d5eb582f699010L, + 0x279739f709f5f84aL }, + { 0x5da4663c8b799336L,0xfdfdf14d203c37ebL,0x32d8a9dca1dbfb2dL, + 0xab40cff077d48f9bL } }, + /* 25 << 21 */ + { { 0xc018b383d20b42d5L,0xf9a810ef9f78845fL,0x40af3753bdba9df0L, + 0xb90bdcfc131dfdf9L }, + { 0x18720591f01ab782L,0xc823f2116af12a88L,0xa51b80f30dc14401L, + 0xde248f77fb2dfbe3L } }, + /* 26 << 21 */ + { { 0xef5a44e50cafe751L,0x73997c9cd4dcd221L,0x32fd86d1de854024L, + 0xd5b53adca09b84bbL }, + { 0x008d7a11dcedd8d1L,0x406bd1c874b32c84L,0x5d4472ff05dde8b1L, + 0x2e25f2cdfce2b32fL } }, + /* 27 << 21 */ + { { 0xbec0dd5e29dfc254L,0x4455fcf62b98b267L,0x0b4d43a5c72df2adL, + 0xea70e6be48a75397L }, + { 0x2aad61695820f3bfL,0xf410d2dd9e37f68fL,0x70fb7dba7be5ac83L, + 0x636bb64536ec3eecL } }, + /* 28 << 21 */ + { { 0x27104ea39754e21cL,0xbc87a3e68d63c373L,0x483351d74109db9aL, + 0x0fa724e360134da7L }, + { 0x9ff44c29b0720b16L,0x2dd0cf1306aceeadL,0x5942758ce26929a6L, + 0x96c5db92b766a92bL } }, + /* 29 << 21 */ + { { 0xcec7d4c05f18395eL,0xd3f227441f80d032L,0x7a68b37acb86075bL, + 0x074764ddafef92dbL }, + { 0xded1e9507bc7f389L,0xc580c850b9756460L,0xaeeec2a47da48157L, + 0x3f0b4e7f82c587b3L } }, + /* 30 << 21 */ + { { 0x231c6de8a9f19c53L,0x5717bd736974e34eL,0xd9e1d216f1508fa9L, + 0x9f112361dadaa124L }, + { 0x80145e31823b7348L,0x4dd8f0d5ac634069L,0xe3d82fc72297c258L, + 0x276fcfee9cee7431L } }, + /* 31 << 21 */ + { { 0x8eb61b5e2bc0aea9L,0x4f668fd5de329431L,0x03a32ab138e4b87eL, + 0xe137451773d0ef0bL }, + { 0x1a46f7e6853ac983L,0xc3bdf42e68e78a57L,0xacf207852ea96dd1L, + 0xa10649b9f1638460L } }, + /* 32 << 21 */ + { { 0xf2369f0b879fbbedL,0x0ff0ae86da9d1869L,0x5251d75956766f45L, + 0x4984d8c02be8d0fcL }, + { 0x7ecc95a6d21008f0L,0x29bd54a03a1a1c49L,0xab9828c5d26c50f3L, + 0x32c0087c51d0d251L } }, + /* 33 << 21 */ + { { 0x9bac3ce60c1cdb26L,0xcd94d947557ca205L,0x1b1bd5989db1fdcdL, + 0x0eda0108a3d8b149L }, + { 0x9506661056152fccL,0xc2f037e6e7192b33L,0xdeffb41ac92e05a4L, + 0x1105f6c2c2f6c62eL } }, + /* 34 << 21 */ + { { 0x68e735008733913cL,0xcce861633f3adc40L,0xf407a94238a278e9L, + 0xd13c1b9d2ab21292L }, + { 0x93ed7ec71c74cf5cL,0x8887dc48f1a4c1b4L,0x3830ff304b3a11f1L, + 0x358c5a3c58937cb6L } }, + /* 35 << 21 */ + { { 0x027dc40489022829L,0x40e939773b798f79L,0x90ad333738be6eadL, + 0x9c23f6bcf34c0a5dL }, + { 0xd1711a35fbffd8bbL,0x60fcfb491949d3ddL,0x09c8ef4b7825d93aL, + 0x24233cffa0a8c968L } }, + /* 36 << 21 */ + { { 0x67ade46ce6d982afL,0xebb6bf3ee7544d7cL,0xd6b9ba763d8bd087L, + 0x46fe382d4dc61280L }, + { 0xbd39a7e8b5bdbd75L,0xab381331b8f228feL,0x0709a77cce1c4300L, + 0x6a247e56f337ceacL } }, + /* 37 << 21 */ + { { 0x8f34f21b636288beL,0x9dfdca74c8a7c305L,0x6decfd1bea919e04L, + 0xcdf2688d8e1991f8L }, + { 0xe607df44d0f8a67eL,0xd985df4b0b58d010L,0x57f834c50c24f8f4L, + 0xe976ef56a0bf01aeL } }, + /* 38 << 21 */ + { { 0x536395aca1c32373L,0x351027aa734c0a13L,0xd2f1b5d65e6bd5bcL, + 0x2b539e24223debedL }, + { 0xd4994cec0eaa1d71L,0x2a83381d661dcf65L,0x5f1aed2f7b54c740L, + 0x0bea3fa5d6dda5eeL } }, + /* 39 << 21 */ + { { 0x9d4fb68436cc6134L,0x8eb9bbf3c0a443ddL,0xfc500e2e383b7d2aL, + 0x7aad621c5b775257L }, + { 0x69284d740a8f7cc0L,0xe820c2ce07562d65L,0xbf9531b9499758eeL, + 0x73e95ca56ee0cc2dL } }, + /* 40 << 21 */ + { { 0xf61790abfbaf50a5L,0xdf55e76b684e0750L,0xec516da7f176b005L, + 0x575553bb7a2dddc7L }, + { 0x37c87ca3553afa73L,0x315f3ffc4d55c251L,0xe846442aaf3e5d35L, + 0x61b911496495ff28L } }, + /* 41 << 21 */ + { { 0x23cc95d3fa326dc3L,0x1df4da1f18fc2ceaL,0x24bf9adcd0a37d59L, + 0xb6710053320d6e1eL }, + { 0x96f9667e618344d1L,0xcc7ce042a06445afL,0xa02d8514d68dbc3aL, + 0x4ea109e4280b5a5bL } }, + /* 42 << 21 */ + { { 0x5741a7acb40961bfL,0x4ada59376aa56bfaL,0x7feb914502b765d1L, + 0x561e97bee6ad1582L }, + { 0xbbc4a5b6da3982f5L,0x0c2659edb546f468L,0xb8e7e6aa59612d20L, + 0xd83dfe20ac19e8e0L } }, + /* 43 << 21 */ + { { 0x8530c45fb835398cL,0x6106a8bfb38a41c2L,0x21e8f9a635f5dcdbL, + 0x39707137cae498edL }, + { 0x70c23834d8249f00L,0x9f14b58fab2537a0L,0xd043c3655f61c0c2L, + 0xdc5926d609a194a7L } }, + /* 44 << 21 */ + { { 0xddec03398e77738aL,0xd07a63effba46426L,0x2e58e79cee7f6e86L, + 0xe59b0459ff32d241L }, + { 0xc5ec84e520fa0338L,0x97939ac8eaff5aceL,0x0310a4e3b4a38313L, + 0x9115fba28f9d9885L } }, + /* 45 << 21 */ + { { 0x8dd710c25fadf8c3L,0x66be38a2ce19c0e2L,0xd42a279c4cfe5022L, + 0x597bb5300e24e1b8L }, + { 0x3cde86b7c153ca7fL,0xa8d30fb3707d63bdL,0xac905f92bd60d21eL, + 0x98e7ffb67b9a54abL } }, + /* 46 << 21 */ + { { 0xd7147df8e9726a30L,0xb5e216ffafce3533L,0xb550b7992ff1ec40L, + 0x6b613b87a1e953fdL }, + { 0x87b88dba792d5610L,0x2ee1270aa190fbe1L,0x02f4e2dc2ef581daL, + 0x016530e4eff82a95L } }, + /* 47 << 21 */ + { { 0xcbb93dfd8fd6ee89L,0x16d3d98646848fffL,0x600eff241da47adfL, + 0x1b9754a00ad47a71L }, + { 0x8f9266df70c33b98L,0xaadc87aedf34186eL,0x0d2ce8e14ad24132L, + 0x8a47cbfc19946ebaL } }, + /* 48 << 21 */ + { { 0x47feeb6662b5f3afL,0xcefab5610abb3734L,0x449de60e19f35cb1L, + 0x39f8db14157f0eb9L }, + { 0xffaecc5b3c61bfd6L,0xa5a4d41d41216703L,0x7f8fabed224e1cc2L, + 0x0d5a8186871ad953L } }, + /* 49 << 21 */ + { { 0xf10774f7d22da9a9L,0x45b8a678cc8a9b0dL,0xd9c2e722bdc32cffL, + 0xbf71b5f5337202a5L }, + { 0x95c57f2f69fc4db9L,0xb6dad34c765d01e1L,0x7e0bd13fcb904635L, + 0x61751253763a588cL } }, + /* 50 << 21 */ + { { 0xd85c299781af2c2dL,0xc0f7d9c481b9d7daL,0x838a34ae08533e8dL, + 0x15c4cb08311d8311L }, + { 0x97f832858e121e14L,0xeea7dc1e85000a5fL,0x0c6059b65d256274L, + 0xec9beaceb95075c0L } }, + /* 51 << 21 */ + { { 0x173daad71df97828L,0xbf851cb5a8937877L,0xb083c59401646f3cL, + 0x3bad30cf50c6d352L }, + { 0xfeb2b202496bbceaL,0x3cf9fd4f18a1e8baL,0xd26de7ff1c066029L, + 0x39c81e9e4e9ed4f8L } }, + /* 52 << 21 */ + { { 0xd8be0cb97b390d35L,0x01df2bbd964aab27L,0x3e8c1a65c3ef64f8L, + 0x567291d1716ed1ddL }, + { 0x95499c6c5f5406d3L,0x71fdda395ba8e23fL,0xcfeb320ed5096eceL, + 0xbe7ba92bca66dd16L } }, + /* 53 << 21 */ + { { 0x4608d36bc6fb5a7dL,0xe3eea15a6d2dd0e0L,0x75b0a3eb8f97a36aL, + 0xf59814cc1c83de1eL }, + { 0x56c9c5b01c33c23fL,0xa96c1da46faa4136L,0x46bf2074de316551L, + 0x3b866e7b1f756c8fL } }, + /* 54 << 21 */ + { { 0x727727d81495ed6bL,0xb2394243b682dce7L,0x8ab8454e758610f3L, + 0xc243ce84857d72a4L }, + { 0x7b320d71dbbf370fL,0xff9afa3778e0f7caL,0x0119d1e0ea7b523fL, + 0xb997f8cb058c7d42L } }, + /* 55 << 21 */ + { { 0x285bcd2a37bbb184L,0x51dcec49a45d1fa6L,0x6ade3b64e29634cbL, + 0x080c94a726b86ef1L }, + { 0xba583db12283fbe3L,0x902bddc85a9315edL,0x07c1ccb386964becL, + 0x78f4eacfb6258301L } }, + /* 56 << 21 */ + { { 0x4bdf3a4956f90823L,0xba0f5080741d777bL,0x091d71c3f38bf760L, + 0x9633d50f9b625b02L }, + { 0x03ecb743b8c9de61L,0xb47512545de74720L,0x9f9defc974ce1cb2L, + 0x774a4f6a00bd32efL } }, + /* 57 << 21 */ + { { 0xaca385f773848f22L,0x53dad716f3f8558eL,0xab7b34b093c471f9L, + 0xf530e06919644bc7L }, + { 0x3d9fb1ffdd59d31aL,0x4382e0df08daa795L,0x165c6f4bd5cc88d7L, + 0xeaa392d54a18c900L } }, + /* 58 << 21 */ + { { 0x94203c67648024eeL,0x188763f28c2fabcdL,0xa80f87acbbaec835L, + 0x632c96e0f29d8d54L }, + { 0x29b0a60e4c00a95eL,0x2ef17f40e011e9faL,0xf6c0e1d115b77223L, + 0xaaec2c6214b04e32L } }, + /* 59 << 21 */ + { { 0xd35688d83d84e58cL,0x2af5094c958571dbL,0x4fff7e19760682a6L, + 0x4cb27077e39a407cL }, + { 0x0f59c5474ff0e321L,0x169f34a61b34c8ffL,0x2bff109652bc1ba7L, + 0xa25423b783583544L } }, + /* 60 << 21 */ + { { 0x5d55d5d50ac8b782L,0xff6622ec2db3c892L,0x48fce7416b8bb642L, + 0x31d6998c69d7e3dcL }, + { 0xdbaf8004cadcaed0L,0x801b0142d81d053cL,0x94b189fc59630ec6L, + 0x120e9934af762c8eL } }, + /* 61 << 21 */ + { { 0x53a29aa4fdc6a404L,0x19d8e01ea1909948L,0x3cfcabf1d7e89681L, + 0x3321a50d4e132d37L }, + { 0xd0496863e9a86111L,0x8c0cde6106a3bc65L,0xaf866c49fc9f8eefL, + 0x2066350eff7f5141L } }, + /* 62 << 21 */ + { { 0x4f8a4689e56ddfbdL,0xea1b0c07fe32983aL,0x2b317462873cb8cbL, + 0x658deddc2d93229fL }, + { 0x65efaf4d0f64ef58L,0xfe43287d730cc7a8L,0xaebc0c723d047d70L, + 0x92efa539d92d26c9L } }, + /* 63 << 21 */ + { { 0x06e7845794b56526L,0x415cb80f0961002dL,0x89e5c56576dcb10fL, + 0x8bbb6982ff9259feL }, + { 0x4fe8795b9abc2668L,0xb5d4f5341e678fb1L,0x6601f3be7b7da2b9L, + 0x98da59e2a13d6805L } }, + /* 64 << 21 */ + { { 0x190d8ea601799a52L,0xa20cec41b86d2952L,0x3062ffb27fff2a7cL, + 0x741b32e579f19d37L }, + { 0xf80d81814eb57d47L,0x7a2d0ed416aef06bL,0x09735fb01cecb588L, + 0x1641caaac6061f5bL } }, + /* 0 << 28 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 28 */ + { { 0x7f99824f20151427L,0x206828b692430206L,0xaa9097d7e1112357L, + 0xacf9a2f209e414ecL }, + { 0xdbdac9da27915356L,0x7e0734b7001efee3L,0x54fab5bbd2b288e2L, + 0x4c630fc4f62dd09cL } }, + /* 2 << 28 */ + { { 0x8537107a1ac2703bL,0xb49258d86bc857b5L,0x57df14debcdaccd1L, + 0x24ab68d7c4ae8529L }, + { 0x7ed8b5d4734e59d0L,0x5f8740c8c495cc80L,0x84aedd5a291db9b3L, + 0x80b360f84fb995beL } }, + /* 3 << 28 */ + { { 0xae915f5d5fa067d1L,0x4134b57f9668960cL,0xbd3656d6a48edaacL, + 0xdac1e3e4fc1d7436L }, + { 0x674ff869d81fbb26L,0x449ed3ecb26c33d4L,0x85138705d94203e8L, + 0xccde538bbeeb6f4aL } }, + /* 4 << 28 */ + { { 0x55d5c68da61a76faL,0x598b441dca1554dcL,0xd39923b9773b279cL, + 0x33331d3c36bf9efcL }, + { 0x2d4c848e298de399L,0xcfdb8e77a1a27f56L,0x94c855ea57b8ab70L, + 0xdcdb9dae6f7879baL } }, + /* 5 << 28 */ + { { 0x7bdff8c2019f2a59L,0xb3ce5bb3cb4fbc74L,0xea907f688a9173ddL, + 0x6cd3d0d395a75439L }, + { 0x92ecc4d6efed021cL,0x09a9f9b06a77339aL,0x87ca6b157188c64aL, + 0x10c2996844899158L } }, + /* 6 << 28 */ + { { 0x5859a229ed6e82efL,0x16f338e365ebaf4eL,0x0cd313875ead67aeL, + 0x1c73d22854ef0bb4L }, + { 0x4cb5513174a5c8c7L,0x01cd29707f69ad6aL,0xa04d00dde966f87eL, + 0xd96fe4470b7b0321L } }, + /* 7 << 28 */ + { { 0x342ac06e88fbd381L,0x02cd4a845c35a493L,0xe8fa89de54f1bbcdL, + 0x341d63672575ed4cL }, + { 0xebe357fbd238202bL,0x600b4d1aa984ead9L,0xc35c9f4452436ea0L, + 0x96fe0a39a370751bL } }, + /* 8 << 28 */ + { { 0x4c4f07367f636a38L,0x9f943fb70e76d5cbL,0xb03510baa8b68b8bL, + 0xc246780a9ed07a1fL }, + { 0x3c0514156d549fc2L,0xc2953f31607781caL,0x955e2c69d8d95413L, + 0xb300fadc7bd282e3L } }, + /* 9 << 28 */ + { { 0x81fe7b5087e9189fL,0xdb17375cf42dda27L,0x22f7d896cf0a5904L, + 0xa0e57c5aebe348e6L }, + { 0xa61011d3f40e3c80L,0xb11893218db705c5L,0x4ed9309e50fedec3L, + 0xdcf14a104d6d5c1dL } }, + /* 10 << 28 */ + { { 0x056c265b55691342L,0xe8e0850491049dc7L,0x131329f5c9bae20aL, + 0x96c8b3e8d9dccdb4L }, + { 0x8c5ff838fb4ee6b4L,0xfc5a9aeb41e8ccf0L,0x7417b764fae050c6L, + 0x0953c3d700452080L } }, + /* 11 << 28 */ + { { 0x2137268238dfe7e8L,0xea417e152bb79d4bL,0x59641f1c76e7cf2dL, + 0x271e3059ea0bcfccL }, + { 0x624c7dfd7253ecbdL,0x2f552e254fca6186L,0xcbf84ecd4d866e9cL, + 0x73967709f68d4610L } }, + /* 12 << 28 */ + { { 0xa14b1163c27901b4L,0xfd9236e0899b8bf3L,0x42b091eccbc6da0aL, + 0xbb1dac6f5ad1d297L }, + { 0x80e61d53a91cf76eL,0x4110a412d31f1ee7L,0x2d87c3ba13efcf77L, + 0x1f374bb4df450d76L } }, + /* 13 << 28 */ + { { 0x5e78e2f20d188dabL,0xe3968ed0f4b885efL,0x46c0568e7314570fL, + 0x3161633801170521L }, + { 0x18e1e7e24f0c8afeL,0x4caa75ffdeea78daL,0x82db67f27c5d8a51L, + 0x36a44d866f505370L } }, + /* 14 << 28 */ + { { 0xd72c5bda0333974fL,0x5db516ae27a70146L,0x34705281210ef921L, + 0xbff17a8f0c9c38e5L }, + { 0x78f4814e12476da1L,0xc1e1661333c16980L,0x9e5b386f424d4bcaL, + 0x4c274e87c85740deL } }, + /* 15 << 28 */ + { { 0xb6a9b88d6c2f5226L,0x14d1b944550d7ca8L,0x580c85fc1fc41709L, + 0xc1da368b54c6d519L }, + { 0x2b0785ced5113cf7L,0x0670f6335a34708fL,0x46e2376715cc3f88L, + 0x1b480cfa50c72c8fL } }, + /* 16 << 28 */ + { { 0x202886024147519aL,0xd0981eac26b372f0L,0xa9d4a7caa785ebc8L, + 0xd953c50ddbdf58e9L }, + { 0x9d6361ccfd590f8fL,0x72e9626b44e6c917L,0x7fd9611022eb64cfL, + 0x863ebb7e9eb288f3L } }, + /* 17 << 28 */ + { { 0x6e6ab7616aca8ee7L,0x97d10b39d7b40358L,0x1687d3771e5feb0dL, + 0xc83e50e48265a27aL }, + { 0x8f75a9fec954b313L,0xcc2e8f47310d1f61L,0xf5ba81c56557d0e0L, + 0x25f9680c3eaf6207L } }, + /* 18 << 28 */ + { { 0xf95c66094354080bL,0x5225bfa57bf2fe1cL,0xc5c004e25c7d98faL, + 0x3561bf1c019aaf60L }, + { 0x5e6f9f17ba151474L,0xdec2f934b04f6ecaL,0x64e368a1269acb1eL, + 0x1332d9e40cdda493L } }, + /* 19 << 28 */ + { { 0x60d6cf69df23de05L,0x66d17da2009339a0L,0x9fcac9850a693923L, + 0xbcf057fced7c6a6dL }, + { 0xc3c5c8c5f0b5662cL,0x25318dd8dcba4f24L,0x60e8cb75082b69ffL, + 0x7c23b3ee1e728c01L } }, + /* 20 << 28 */ + { { 0x15e10a0a097e4403L,0xcb3d0a8619854665L,0x88d8e211d67d4826L, + 0xb39af66e0b9d2839L }, + { 0xa5f94588bd475ca8L,0xe06b7966c077b80bL,0xfedb1485da27c26cL, + 0xd290d33afe0fd5e0L } }, + /* 21 << 28 */ + { { 0xa40bcc47f34fb0faL,0xb4760cc81fb1ab09L,0x8fca0993a273bfe3L, + 0x13e4fe07f70b213cL }, + { 0x3bcdb992fdb05163L,0x8c484b110c2b19b6L,0x1acb815faaf2e3e2L, + 0xc6905935b89ff1b4L } }, + /* 22 << 28 */ + { { 0xb2ad6f9d586e74e1L,0x488883ad67b80484L,0x758aa2c7369c3ddbL, + 0x8ab74e699f9afd31L }, + { 0x10fc2d285e21beb1L,0x3484518a318c42f9L,0x377427dc53cf40c3L, + 0x9de0781a391bc1d9L } }, + /* 23 << 28 */ + { { 0x8faee858693807e1L,0xa38653274e81ccc7L,0x02c30ff26f835b84L, + 0xb604437b0d3d38d4L }, + { 0xb3fc8a985ca1823dL,0xb82f7ec903be0324L,0xee36d761cf684a33L, + 0x5a01df0e9f29bf7dL } }, + /* 24 << 28 */ + { { 0x686202f31306583dL,0x05b10da0437c622eL,0xbf9aaa0f076a7bc8L, + 0x25e94efb8f8f4e43L }, + { 0x8a35c9b7fa3dc26dL,0xe0e5fb9396ff03c5L,0xa77e3843ebc394ceL, + 0xcede65958361de60L } }, + /* 25 << 28 */ + { { 0xd27c22f6a1993545L,0xab01cc3624d671baL,0x63fa2877a169c28eL, + 0x925ef9042eb08376L }, + { 0x3b2fa3cf53aa0b32L,0xb27beb5b71c49d7aL,0xb60e1834d105e27fL, + 0xd60897884f68570dL } }, + /* 26 << 28 */ + { { 0x23094ce0d6fbc2acL,0x738037a1815ff551L,0xda73b1bb6bef119cL, + 0xdcf6c430eef506baL }, + { 0x00e4fe7be3ef104aL,0xebdd9a2c0a065628L,0x853a81c38792043eL, + 0x22ad6eceb3b59108L } }, + /* 27 << 28 */ + { { 0x9fb813c039cd297dL,0x8ec7e16e05bda5d9L,0x2834797c0d104b96L, + 0xcc11a2e77c511510L }, + { 0x96ca5a5396ee6380L,0x054c8655cea38742L,0xb5946852d54dfa7dL, + 0x97c422e71f4ab207L } }, + /* 28 << 28 */ + { { 0xbf9075090c22b540L,0x2cde42aab7c267d4L,0xba18f9ed5ab0d693L, + 0x3ba62aa66e4660d9L }, + { 0xb24bf97bab9ea96aL,0x5d039642e3b60e32L,0x4e6a45067c4d9bd5L, + 0x666c5b9e7ed4a6a4L } }, + /* 29 << 28 */ + { { 0xfa3fdcd98edbd7ccL,0x4660bb87c6ccd753L,0x9ae9082021e6b64fL, + 0x8a56a713b36bfb3fL }, + { 0xabfce0965726d47fL,0x9eed01b20b1a9a7fL,0x30e9cad44eb74a37L, + 0x7b2524cc53e9666dL } }, + /* 30 << 28 */ + { { 0x6a29683b8f4b002fL,0xc2200d7a41f4fc20L,0xcf3af47a3a338accL, + 0x6539a4fbe7128975L }, + { 0xcec31c14c33c7fcfL,0x7eb6799bc7be322bL,0x119ef4e96646f623L, + 0x7b7a26a554d7299bL } }, + /* 31 << 28 */ + { { 0xcb37f08d403f46f2L,0x94b8fc431a0ec0c7L,0xbb8514e3c332142fL, + 0xf3ed2c33e80d2a7aL }, + { 0x8d2080afb639126cL,0xf7b6be60e3553adeL,0x3950aa9f1c7e2b09L, + 0x847ff9586410f02bL } }, + /* 32 << 28 */ + { { 0x877b7cf5678a31b0L,0xd50301ae3998b620L,0x734257c5c00fb396L, + 0xf9fb18a004e672a6L }, + { 0xff8bd8ebe8758851L,0x1e64e4c65d99ba44L,0x4b8eaedf7dfd93b7L, + 0xba2f2a9804e76b8cL } }, + /* 33 << 28 */ + { { 0x7d790cbae8053433L,0xc8e725a03d2c9585L,0x58c5c476cdd8f5edL, + 0xd106b952efa9fe1dL }, + { 0x3c5c775b0eff13a9L,0x242442bae057b930L,0xe9f458d4c9b70cbdL, + 0x69b71448a3cdb89aL } }, + /* 34 << 28 */ + { { 0x41ee46f60e2ed742L,0x573f104540067493L,0xb1e154ff9d54c304L, + 0x2ad0436a8d3a7502L }, + { 0xee4aaa2d431a8121L,0xcd38b3ab886f11edL,0x57d49ea6034a0eb7L, + 0xd2b773bdf7e85e58L } }, + /* 35 << 28 */ + { { 0x4a559ac49b5c1f14L,0xc444be1a3e54df2bL,0x13aad704eda41891L, + 0xcd927bec5eb5c788L }, + { 0xeb3c8516e48c8a34L,0x1b7ac8124b546669L,0x1815f896594df8ecL, + 0x87c6a79c79227865L } }, + /* 36 << 28 */ + { { 0xae02a2f09b56ddbdL,0x1339b5ac8a2f1cf3L,0xf2b569c7839dff0dL, + 0xb0b9e864fee9a43dL }, + { 0x4ff8ca4177bb064eL,0x145a2812fd249f63L,0x3ab7beacf86f689aL, + 0x9bafec2701d35f5eL } }, + /* 37 << 28 */ + { { 0x28054c654265aa91L,0xa4b18304035efe42L,0x6887b0e69639dec7L, + 0xf4b8f6ad3d52aea5L }, + { 0xfb9293cc971a8a13L,0x3f159e5d4c934d07L,0x2c50e9b109acbc29L, + 0x08eb65e67154d129L } }, + /* 38 << 28 */ + { { 0x4feff58930b75c3eL,0x0bb82fe294491c93L,0xd8ac377a89af62bbL, + 0xd7b514909685e49fL }, + { 0xabca9a7b04497f19L,0x1b35ed0a1a7ad13fL,0x6b601e213ec86ed6L, + 0xda91fcb9ce0c76f1L } }, + /* 39 << 28 */ + { { 0x9e28507bd7ab27e1L,0x7c19a55563945b7bL,0x6b43f0a1aafc9827L, + 0x443b4fbd3aa55b91L }, + { 0x962b2e656962c88fL,0x139da8d4ce0db0caL,0xb93f05dd1b8d6c4fL, + 0x779cdff7180b9824L } }, + /* 40 << 28 */ + { { 0xbba23fddae57c7b7L,0x345342f21b932522L,0xfd9c80fe556d4aa3L, + 0xa03907ba6525bb61L }, + { 0x38b010e1ff218933L,0xc066b654aa52117bL,0x8e14192094f2e6eaL, + 0x66a27dca0d32f2b2L } }, + /* 41 << 28 */ + { { 0x69c7f993048b3717L,0xbf5a989ab178ae1cL,0x49fa9058564f1d6bL, + 0x27ec6e15d31fde4eL }, + { 0x4cce03737276e7fcL,0x64086d7989d6bf02L,0x5a72f0464ccdd979L, + 0x909c356647775631L } }, + /* 42 << 28 */ + { { 0x1c07bc6b75dd7125L,0xb4c6bc9787a0428dL,0x507ece52fdeb6b9dL, + 0xfca56512b2c95432L }, + { 0x15d97181d0e8bd06L,0x384dd317c6bb46eaL,0x5441ea203952b624L, + 0xbcf70dee4e7dc2fbL } }, + /* 43 << 28 */ + { { 0x372b016e6628e8c3L,0x07a0d667b60a7522L,0xcf05751b0a344ee2L, + 0x0ec09a48118bdeecL }, + { 0x6e4b3d4ed83dce46L,0x43a6316d99d2fc6eL,0xa99d898956cf044cL, + 0x7c7f4454ae3e5fb7L } }, + /* 44 << 28 */ + { { 0xb2e6b121fbabbe92L,0x281850fbe1330076L,0x093581ec97890015L, + 0x69b1dded75ff77f5L }, + { 0x7cf0b18fab105105L,0x953ced31a89ccfefL,0x3151f85feb914009L, + 0x3c9f1b8788ed48adL } }, + /* 45 << 28 */ + { { 0xc9aba1a14a7eadcbL,0x928e7501522e71cfL,0xeaede7273a2e4f83L, + 0x467e10d11ce3bbd3L }, + { 0xf3442ac3b955dcf0L,0xba96307dd3d5e527L,0xf763a10efd77f474L, + 0x5d744bd06a6e1ff0L } }, + /* 46 << 28 */ + { { 0xd287282aa777899eL,0xe20eda8fd03f3cdeL,0x6a7e75bb50b07d31L, + 0x0b7e2a946f379de4L }, + { 0x31cb64ad19f593cfL,0x7b1a9e4f1e76ef1dL,0xe18c9c9db62d609cL, + 0x439bad6de779a650L } }, + /* 47 << 28 */ + { { 0x219d9066e032f144L,0x1db632b8e8b2ec6aL,0xff0d0fd4fda12f78L, + 0x56fb4c2d2a25d265L }, + { 0x5f4e2ee1255a03f1L,0x61cd6af2e96af176L,0xe0317ba8d068bc97L, + 0x927d6bab264b988eL } }, + /* 48 << 28 */ + { { 0xa18f07e0e90fb21eL,0x00fd2b80bba7fca1L,0x20387f2795cd67b5L, + 0x5b89a4e7d39707f7L }, + { 0x8f83ad3f894407ceL,0xa0025b946c226132L,0xc79563c7f906c13bL, + 0x5f548f314e7bb025L } }, + /* 49 << 28 */ + { { 0x2b4c6b8feac6d113L,0xa67e3f9c0e813c76L,0x3982717c3fe1f4b9L, + 0x5886581926d8050eL }, + { 0x99f3640cf7f06f20L,0xdc6102162a66ebc2L,0x52f2c175767a1e08L, + 0x05660e1a5999871bL } }, + /* 50 << 28 */ + { { 0x6b0f17626d3c4693L,0xf0e7d62737ed7beaL,0xc51758c7b75b226dL, + 0x40a886281f91613bL }, + { 0x889dbaa7bbb38ce0L,0xe0404b65bddcad81L,0xfebccd3a8bc9671fL, + 0xfbf9a357ee1f5375L } }, + /* 51 << 28 */ + { { 0x5dc169b028f33398L,0xb07ec11d72e90f65L,0xae7f3b4afaab1eb1L, + 0xd970195e5f17538aL }, + { 0x52b05cbe0181e640L,0xf5debd622643313dL,0x761481545df31f82L, + 0x23e03b333a9e13c5L } }, + /* 52 << 28 */ + { { 0xff7589494fde0c1fL,0xbf8a1abee5b6ec20L,0x702278fb87e1db6cL, + 0xc447ad7a35ed658fL }, + { 0x48d4aa3803d0ccf2L,0x80acb338819a7c03L,0x9bc7c89e6e17ceccL, + 0x46736b8b03be1d82L } }, + /* 53 << 28 */ + { { 0xd65d7b60c0432f96L,0xddebe7a3deb5442fL,0x79a253077dff69a2L, + 0x37a56d9402cf3122L }, + { 0x8bab8aedf2350d0aL,0x13c3f276037b0d9aL,0xc664957c44c65caeL, + 0x88b44089c2e71a88L } }, + /* 54 << 28 */ + { { 0xdb88e5a35cb02664L,0x5d4c0bf18686c72eL,0xea3d9b62a682d53eL, + 0x9b605ef40b2ad431L }, + { 0x71bac202c69645d0L,0xa115f03a6a1b66e7L,0xfe2c563a158f4dc4L, + 0xf715b3a04d12a78cL } }, + /* 55 << 28 */ + { { 0x8f7f0a48d413213aL,0x2035806dc04becdbL,0xecd34a995d8587f5L, + 0x4d8c30799f6d3a71L }, + { 0x1b2a2a678d95a8f6L,0xc58c9d7df2110d0dL,0xdeee81d5cf8fba3fL, + 0xa42be3c00c7cdf68L } }, + /* 56 << 28 */ + { { 0x2126f742d43b5eaaL,0x054a0766dfa59b85L,0x9d0d5e36126bfd45L, + 0xa1f8fbd7384f8a8fL }, + { 0x317680f5d563fcccL,0x48ca5055f280a928L,0xe00b81b227b578cfL, + 0x10aad9182994a514L } }, + /* 57 << 28 */ + { { 0xd9e07b62b7bdc953L,0x9f0f6ff25bc086ddL,0x09d1ccff655eee77L, + 0x45475f795bef7df1L }, + { 0x3faa28fa86f702ccL,0x92e609050f021f07L,0xe9e629687f8fa8c6L, + 0xbd71419af036ea2cL } }, + /* 58 << 28 */ + { { 0x171ee1cc6028da9aL,0x5352fe1ac251f573L,0xf8ff236e3fa997f4L, + 0xd831b6c9a5749d5fL }, + { 0x7c872e1de350e2c2L,0xc56240d91e0ce403L,0xf9deb0776974f5cbL, + 0x7d50ba87961c3728L } }, + /* 59 << 28 */ + { { 0xd6f894265a3a2518L,0xcf817799c6303d43L,0x510a0471619e5696L, + 0xab049ff63a5e307bL }, + { 0xe4cdf9b0feb13ec7L,0xd5e971179d8ff90cL,0xf6f64d069afa96afL, + 0x00d0bf5e9d2012a2L } }, + /* 60 << 28 */ + { { 0xe63f301f358bcdc0L,0x07689e990a9d47f8L,0x1f689e2f4f43d43aL, + 0x4d542a1690920904L }, + { 0xaea293d59ca0a707L,0xd061fe458ac68065L,0x1033bf1b0090008cL, + 0x29749558c08a6db6L } }, + /* 61 << 28 */ + { { 0x74b5fc59c1d5d034L,0xf712e9f667e215e0L,0xfd520cbd860200e6L, + 0x0229acb43ea22588L }, + { 0x9cd1e14cfff0c82eL,0x87684b6259c69e73L,0xda85e61c96ccb989L, + 0x2d5dbb02a3d06493L } }, + /* 62 << 28 */ + { { 0xf22ad33ae86b173cL,0xe8e41ea5a79ff0e3L,0x01d2d725dd0d0c10L, + 0x31f39088032d28f9L }, + { 0x7b3f71e17829839eL,0x0cf691b44502ae58L,0xef658dbdbefc6115L, + 0xa5cd6ee5b3ab5314L } }, + /* 63 << 28 */ + { { 0x206c8d7b5f1d2347L,0x794645ba4cc2253aL,0xd517d8ff58389e08L, + 0x4fa20dee9f847288L }, + { 0xeba072d8d797770aL,0x7360c91dbf429e26L,0x7200a3b380af8279L, + 0x6a1c915082dadce3L } }, + /* 64 << 28 */ + { { 0x0ee6d3a7c35d8794L,0x042e65580356bae5L,0x9f59698d643322fdL, + 0x9379ae1550a61967L }, + { 0x64b9ae62fcc9981eL,0xaed3d6316d2934c6L,0x2454b3025e4e65ebL, + 0xab09f647f9950428L } }, + /* 0 << 35 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 35 */ + { { 0xb2083a1222248accL,0x1f6ec0ef3264e366L,0x5659b7045afdee28L, + 0x7a823a40e6430bb5L }, + { 0x24592a04e1900a79L,0xcde09d4ac9ee6576L,0x52b6463f4b5ea54aL, + 0x1efe9ed3d3ca65a7L } }, + /* 2 << 35 */ + { { 0xe27a6dbe305406ddL,0x8eb7dc7fdd5d1957L,0xf54a6876387d4d8fL, + 0x9c479409c7762de4L }, + { 0xbe4d5b5d99b30778L,0x25380c566e793682L,0x602d37f3dac740e3L, + 0x140deabe1566e4aeL } }, + /* 3 << 35 */ + { { 0x4481d067afd32acfL,0xd8f0fccae1f71ccfL,0xd208dd0cb596f2daL, + 0xd049d7309aad93f9L }, + { 0xc79f263d42ab580eL,0x09411bb123f707b4L,0x8cfde1ff835e0edaL, + 0x7270749090f03402L } }, + /* 4 << 35 */ + { { 0xeaee6126c49a861eL,0x024f3b65e14f0d06L,0x51a3f1e8c69bfc17L, + 0xc3c3a8e9a7686381L }, + { 0x3400752cb103d4c8L,0x02bc46139218b36bL,0xc67f75eb7651504aL, + 0xd6848b56d02aebfaL } }, + /* 5 << 35 */ + { { 0xbd9802e6c30fa92bL,0x5a70d96d9a552784L,0x9085c4ea3f83169bL, + 0xfa9423bb06908228L }, + { 0x2ffebe12fe97a5b9L,0x85da604971b99118L,0x9cbc2f7f63178846L, + 0xfd96bc709153218eL } }, + /* 6 << 35 */ + { { 0x958381db1782269bL,0xae34bf792597e550L,0xbb5c60645f385153L, + 0x6f0e96afe3088048L }, + { 0xbf6a021577884456L,0xb3b5688c69310ea7L,0x17c9429504fad2deL, + 0xe020f0e517896d4dL } }, + /* 7 << 35 */ + { { 0x730ba0ab0976505fL,0x567f6813095e2ec5L,0x470620106331ab71L, + 0x72cfa97741d22b9fL }, + { 0x33e55ead8a2373daL,0xa8d0d5f47ba45a68L,0xba1d8f9c03029d15L, + 0x8f34f1ccfc55b9f3L } }, + /* 8 << 35 */ + { { 0xcca4428dbbe5a1a9L,0x8187fd5f3126bd67L,0x0036973a48105826L, + 0xa39b6663b8bd61a0L }, + { 0x6d42deef2d65a808L,0x4969044f94636b19L,0xf611ee47dd5d564cL, + 0x7b2f3a49d2873077L } }, + /* 9 << 35 */ + { { 0x94157d45300eb294L,0x2b2a656e169c1494L,0xc000dd76d3a47aa9L, + 0xa2864e4fa6243ea4L }, + { 0x82716c47db89842eL,0x12dfd7d761479fb7L,0x3b9a2c56e0b2f6dcL, + 0x46be862ad7f85d67L } }, + /* 10 << 35 */ + { { 0x03b0d8dd0f82b214L,0x460c34f9f103cbc6L,0xf32e5c0318d79e19L, + 0x8b8888baa84117f8L }, + { 0x8f3c37dcc0722677L,0x10d21be91c1c0f27L,0xd47c8468e0f7a0c6L, + 0x9bf02213adecc0e0L } }, + /* 11 << 35 */ + { { 0x0baa7d1242b48b99L,0x1bcb665d48424096L,0x8b847cd6ebfb5cfbL, + 0x87c2ae569ad4d10dL }, + { 0xf1cbb1220de36726L,0xe7043c683fdfbd21L,0x4bd0826a4e79d460L, + 0x11f5e5984bd1a2cbL } }, + /* 12 << 35 */ + { { 0x97554160b7fe7b6eL,0x7d16189a400a3fb2L,0xd73e9beae328ca1eL, + 0x0dd04b97e793d8ccL }, + { 0xa9c83c9b506db8ccL,0x5cd47aaecf38814cL,0x26fc430db64b45e6L, + 0x079b5499d818ea84L } }, + /* 13 << 35 */ + { { 0xebb01102c1c24a3bL,0xca24e5681c161c1aL,0x103eea6936f00a4aL, + 0x9ad76ee876176c7bL }, + { 0x97451fc2538e0ff7L,0x94f898096604b3b0L,0x6311436e3249cfd7L, + 0x27b4a7bd41224f69L } }, + /* 14 << 35 */ + { { 0x03b5d21ae0ac2941L,0x279b0254c2d31937L,0x3307c052cac992d0L, + 0x6aa7cb92efa8b1f3L }, + { 0x5a1825800d37c7a5L,0x13380c37342d5422L,0x92ac2d66d5d2ef92L, + 0x035a70c9030c63c6L } }, + /* 15 << 35 */ + { { 0xc16025dd4ce4f152L,0x1f419a71f9df7c06L,0x6d5b221491e4bb14L, + 0xfc43c6cc839fb4ceL }, + { 0x49f06591925d6b2dL,0x4b37d9d362186598L,0x8c54a971d01b1629L, + 0xe1a9c29f51d50e05L } }, + /* 16 << 35 */ + { { 0x5109b78571ba1861L,0x48b22d5cd0c8f93dL,0xe8fa84a78633bb93L, + 0x53fba6ba5aebbd08L }, + { 0x7ff27df3e5eea7d8L,0x521c879668ca7158L,0xb9d5133bce6f1a05L, + 0x2d50cd53fd0ebee4L } }, + /* 17 << 35 */ + { { 0xc82115d6c5a3ef16L,0x993eff9dba079221L,0xe4da2c5e4b5da81cL, + 0x9a89dbdb8033fd85L }, + { 0x60819ebf2b892891L,0x53902b215d14a4d5L,0x6ac35051d7fda421L, + 0xcc6ab88561c83284L } }, + /* 18 << 35 */ + { { 0x14eba133f74cff17L,0x240aaa03ecb813f2L,0xcfbb65406f665beeL, + 0x084b1fe4a425ad73L }, + { 0x009d5d16d081f6a6L,0x35304fe8eef82c90L,0xf20346d5aa9eaa22L, + 0x0ada9f07ac1c91e3L } }, + /* 19 << 35 */ + { { 0xa6e21678968a6144L,0x54c1f77c07b31a1eL,0xd6bb787e5781fbe1L, + 0x61bd2ee0e31f1c4aL }, + { 0xf25aa1e9781105fcL,0x9cf2971f7b2f8e80L,0x26d15412cdff919bL, + 0x01db4ebe34bc896eL } }, + /* 20 << 35 */ + { { 0x7d9b3e23b40df1cfL,0x5933737394e971b4L,0xbf57bd14669cf921L, + 0x865daedf0c1a1064L }, + { 0x3eb70bd383279125L,0xbc3d5b9f34ecdaabL,0x91e3ed7e5f755cafL, + 0x49699f54d41e6f02L } }, + /* 21 << 35 */ + { { 0x185770e1d4a7a15bL,0x08f3587aeaac87e7L,0x352018db473133eaL, + 0x674ce71904fd30fcL }, + { 0x7b8d9835088b3e0eL,0x7a0356a95d0d47a1L,0x9d9e76596474a3c4L, + 0x61ea48a7ff66966cL } }, + /* 22 << 35 */ + { { 0x304177580f3e4834L,0xfdbb21c217a9afcbL,0x756fa17f2f9a67b3L, + 0x2a6b2421a245c1a8L }, + { 0x64be27944af02291L,0xade465c62a5804feL,0x8dffbd39a6f08fd7L, + 0xc4efa84caa14403bL } }, + /* 23 << 35 */ + { { 0xa1b91b2a442b0f5cL,0xb748e317cf997736L,0x8d1b62bfcee90e16L, + 0x907ae2710b2078c0L }, + { 0xdf31534b0c9bcdddL,0x043fb05439adce83L,0x99031043d826846aL, + 0x61a9c0d6b144f393L } }, + /* 24 << 35 */ + { { 0xdab4804647718427L,0xdf17ff9b6e830f8bL,0x408d7ee8e49a1347L, + 0x6ac71e2391c1d4aeL }, + { 0xc8cbb9fd1defd73cL,0x19840657bbbbfec5L,0x39db1cb59e7ef8eaL, + 0x78aa829664105f30L } }, + /* 25 << 35 */ + { { 0xa3d9b7f0a3738c29L,0x0a2f235abc3250a3L,0x55e506f6445e4cafL, + 0x0974f73d33475f7aL }, + { 0xd37dbba35ba2f5a8L,0x542c6e636af40066L,0x26d99b53c5d73e2cL, + 0x06060d7d6c3ca33eL } }, + /* 26 << 35 */ + { { 0xcdbef1c2065fef4aL,0x77e60f7dfd5b92e3L,0xd7c549f026708350L, + 0x201b3ad034f121bfL }, + { 0x5fcac2a10334fc14L,0x8a9a9e09344552f6L,0x7dd8a1d397653082L, + 0x5fc0738f79d4f289L } }, + /* 27 << 35 */ + { { 0x787d244d17d2d8c3L,0xeffc634570830684L,0x5ddb96dde4f73ae5L, + 0x8efb14b1172549a5L }, + { 0x6eb73eee2245ae7aL,0xbca4061eea11f13eL,0xb577421d30b01f5dL, + 0xaa688b24782e152cL } }, + /* 28 << 35 */ + { { 0x67608e71bd3502baL,0x4ef41f24b4de75a0L,0xb08dde5efd6125e5L, + 0xde484825a409543fL }, + { 0x1f198d9865cc2295L,0x428a37716e0edfa2L,0x4f9697a2adf35fc7L, + 0x01a43c79f7cac3c7L } }, + /* 29 << 35 */ + { { 0xb05d70590fd3659aL,0x8927f30cbb7f2d9aL,0x4023d1ac8cf984d3L, + 0x32125ed302897a45L }, + { 0xfb572dad3d414205L,0x73000ef2e3fa82a9L,0x4c0868e9f10a5581L, + 0x5b61fc676b0b3ca5L } }, + /* 30 << 35 */ + { { 0xc1258d5b7cae440cL,0x21c08b41402b7531L,0xf61a8955de932321L, + 0x3568faf82d1408afL }, + { 0x71b15e999ecf965bL,0xf14ed248e917276fL,0xc6f4caa1820cf9e2L, + 0x681b20b218d83c7eL } }, + /* 31 << 35 */ + { { 0x6cde738dc6c01120L,0x71db0813ae70e0dbL,0x95fc064474afe18cL, + 0x34619053129e2be7L }, + { 0x80615ceadb2a3b15L,0x0a49a19edb4c7073L,0x0e1b84c88fd2d367L, + 0xd74bf462033fb8aaL } }, + /* 32 << 35 */ + { { 0x889f6d65533ef217L,0x7158c7e4c3ca2e87L,0xfb670dfbdc2b4167L, + 0x75910a01844c257fL }, + { 0xf336bf07cf88577dL,0x22245250e45e2aceL,0x2ed92e8d7ca23d85L, + 0x29f8be4c2b812f58L } }, + /* 33 << 35 */ + { { 0xdd9ebaa7076fe12bL,0x3f2400cbae1537f9L,0x1aa9352817bdfb46L, + 0xc0f9843067883b41L }, + { 0x5590ede10170911dL,0x7562f5bb34d4b17fL,0xe1fa1df21826b8d2L, + 0xb40b796a6bd80d59L } }, + /* 34 << 35 */ + { { 0xd65bf1973467ba92L,0x8c9b46dbf70954b0L,0x97c8a0f30e78f15dL, + 0xa8f3a69a85a4c961L }, + { 0x4242660f61e4ce9bL,0xbf06aab36ea6790cL,0xc6706f8eec986416L, + 0x9e56dec19a9fc225L } }, + /* 35 << 35 */ + { { 0x527c46f49a9898d9L,0xd799e77b5633cdefL,0x24eacc167d9e4297L, + 0xabb61cea6b1cb734L }, + { 0xbee2e8a7f778443cL,0x3bb42bf129de2fe6L,0xcbed86a13003bb6fL, + 0xd3918e6cd781cdf6L } }, + /* 36 << 35 */ + { { 0x4bee32719a5103f1L,0x5243efc6f50eac06L,0xb8e122cb6adcc119L, + 0x1b7faa84c0b80a08L }, + { 0x32c3d1bd6dfcd08cL,0x129dec4e0be427deL,0x98ab679c1d263c83L, + 0xafc83cb7cef64effL } }, + /* 37 << 35 */ + { { 0x85eb60882fa6be76L,0x892585fb1328cbfeL,0xc154d3edcf618ddaL, + 0xc44f601b3abaf26eL }, + { 0x7bf57d0b2be1fdfdL,0xa833bd2d21137feeL,0x9353af362db591a8L, + 0xc76f26dc5562a056L } }, + /* 38 << 35 */ + { { 0x1d87e47d3fdf5a51L,0x7afb5f9355c9cab0L,0x91bbf58f89e0586eL, + 0x7c72c0180d843709L }, + { 0xa9a5aafb99b5c3dcL,0xa48a0f1d3844aeb0L,0x7178b7ddb667e482L, + 0x453985e96e23a59aL } }, + /* 39 << 35 */ + { { 0x4a54c86001b25dd8L,0x0dd37f48fb897c8aL,0x5f8aa6100ea90cd9L, + 0xc8892c6816d5830dL }, + { 0xeb4befc0ef514ca5L,0x478eb679e72c9ee6L,0x9bca20dadbc40d5fL, + 0xf015de21dde4f64aL } }, + /* 40 << 35 */ + { { 0xaa6a4de0eaf4b8a5L,0x68cfd9ca4bc60e32L,0x668a4b017fd15e70L, + 0xd9f0694af27dc09dL }, + { 0xf6c3cad5ba708bcdL,0x5cd2ba695bb95c2aL,0xaa28c1d333c0a58fL, + 0x23e274e3abc77870L } }, + /* 41 << 35 */ + { { 0x44c3692ddfd20a4aL,0x091c5fd381a66653L,0x6c0bb69109a0757dL, + 0x9072e8b9667343eaL }, + { 0x31d40eb080848becL,0x95bd480a79fd36ccL,0x01a77c6165ed43f5L, + 0xafccd1272e0d40bfL } }, + /* 42 << 35 */ + { { 0xeccfc82d1cc1884bL,0xc85ac2015d4753b4L,0xc7a6caac658e099fL, + 0xcf46369e04b27390L }, + { 0xe2e7d049506467eaL,0x481b63a237cdecccL,0x4029abd8ed80143aL, + 0x28bfe3c7bcb00b88L } }, + /* 43 << 35 */ + { { 0x3bec10090643d84aL,0x885f3668abd11041L,0xdb02432cf83a34d6L, + 0x32f7b360719ceebeL }, + { 0xf06c7837dad1fe7aL,0x60a157a95441a0b0L,0x704970e9e2d47550L, + 0xcd2bd553271b9020L } }, + /* 44 << 35 */ + { { 0xff57f82f33e24a0bL,0x9cbee23ff2565079L,0x16353427eb5f5825L, + 0x276feec4e948d662L }, + { 0xd1b62bc6da10032bL,0x718351ddf0e72a53L,0x934520762420e7baL, + 0x96368fff3a00118dL } }, + /* 45 << 35 */ + { { 0x00ce2d26150a49e4L,0x0c28b6363f04706bL,0xbad65a4658b196d0L, + 0x6c8455fcec9f8b7cL }, + { 0xe90c895f2d71867eL,0x5c0be31bedf9f38cL,0x2a37a15ed8f6ec04L, + 0x239639e78cd85251L } }, + /* 46 << 35 */ + { { 0xd89753159c7c4c6bL,0x603aa3c0d7409af7L,0xb8d53d0c007132fbL, + 0x68d12af7a6849238L }, + { 0xbe0607e7bf5d9279L,0x9aa50055aada74ceL,0xe81079cbba7e8ccbL, + 0x610c71d1a5f4ff5eL } }, + /* 47 << 35 */ + { { 0x9e2ee1a75aa07093L,0xca84004ba75da47cL,0x074d39513de75401L, + 0xf938f756bb311592L }, + { 0x9619761800a43421L,0x39a2536207bc78c8L,0x278f710a0a171276L, + 0xb28446ea8d1a8f08L } }, + /* 48 << 35 */ + { { 0x184781bfe3b6a661L,0x7751cb1de6d279f7L,0xf8ff95d6c59eb662L, + 0x186d90b758d3dea7L }, + { 0x0e4bb6c1dfb4f754L,0x5c5cf56b2b2801dcL,0xc561e4521f54564dL, + 0xb4fb8c60f0dd7f13L } }, + /* 49 << 35 */ + { { 0xf884963033ff98c7L,0x9619fffacf17769cL,0xf8090bf61bfdd80aL, + 0x14d9a149422cfe63L }, + { 0xb354c3606f6df9eaL,0xdbcf770d218f17eaL,0x207db7c879eb3480L, + 0x213dbda8559b6a26L } }, + /* 50 << 35 */ + { { 0xac4c200b29fc81b3L,0xebc3e09f171d87c1L,0x917995301481aa9eL, + 0x051b92e192e114faL }, + { 0xdf8f92e9ecb5537fL,0x44b1b2cc290c7483L,0xa711455a2adeb016L, + 0x964b685681a10c2cL } }, + /* 51 << 35 */ + { { 0x4f159d99cec03623L,0x05532225ef3271eaL,0xb231bea3c5ee4849L, + 0x57a54f507094f103L }, + { 0x3e2d421d9598b352L,0xe865a49c67412ab4L,0xd2998a251cc3a912L, + 0x5d0928080c74d65dL } }, + /* 52 << 35 */ + { { 0x73f459084088567aL,0xeb6b280e1f214a61L,0x8c9adc34caf0c13dL, + 0x39d12938f561fb80L }, + { 0xb2dc3a5ebc6edfb4L,0x7485b1b1fe4d210eL,0x062e0400e186ae72L, + 0x91e32d5c6eeb3b88L } }, + /* 53 << 35 */ + { { 0x6df574d74be59224L,0xebc88ccc716d55f3L,0x26c2e6d0cad6ed33L, + 0xc6e21e7d0d3e8b10L }, + { 0x2cc5840e5bcc36bbL,0x9292445e7da74f69L,0x8be8d3214e5193a8L, + 0x3ec236298df06413L } }, + /* 54 << 35 */ + { { 0xc7e9ae85b134defaL,0x6073b1d01bb2d475L,0xb9ad615e2863c00dL, + 0x9e29493d525f4ac4L }, + { 0xc32b1dea4e9acf4fL,0x3e1f01c8a50db88dL,0xb05d70ea04da916cL, + 0x714b0d0ad865803eL } }, + /* 55 << 35 */ + { { 0x4bd493fc9920cb5eL,0x5b44b1f792c7a3acL,0xa2a77293bcec9235L, + 0x5ee06e87cd378553L }, + { 0xceff8173da621607L,0x2bb03e4c99f5d290L,0x2945106aa6f734acL, + 0xb5056604d25c4732L } }, + /* 56 << 35 */ + { { 0x5945920ce079afeeL,0x686e17a06789831fL,0x5966bee8b74a5ae5L, + 0x38a673a21e258d46L }, + { 0xbd1cc1f283141c95L,0x3b2ecf4f0e96e486L,0xcd3aa89674e5fc78L, + 0x415ec10c2482fa7aL } }, + /* 57 << 35 */ + { { 0x1523441980503380L,0x513d917ad314b392L,0xb0b52f4e63caecaeL, + 0x07bf22ad2dc7780bL }, + { 0xe761e8a1e4306839L,0x1b3be9625dd7feaaL,0x4fe728de74c778f1L, + 0xf1fa0bda5e0070f6L } }, + /* 58 << 35 */ + { { 0x85205a316ec3f510L,0x2c7e4a14d2980475L,0xde3c19c06f30ebfdL, + 0xdb1c1f38d4b7e644L }, + { 0xfe291a755dce364aL,0xb7b22a3c058f5be3L,0x2cd2c30237fea38cL, + 0x2930967a2e17be17L } }, + /* 59 << 35 */ + { { 0x87f009de0c061c65L,0xcb014aacedc6ed44L,0x49bd1cb43bafb1ebL, + 0x81bd8b5c282d3688L }, + { 0x1cdab87ef01a17afL,0x21f37ac4e710063bL,0x5a6c567642fc8193L, + 0xf4753e7056a6015cL } }, + /* 60 << 35 */ + { { 0x020f795ea15b0a44L,0x8f37c8d78958a958L,0x63b7e89ba4b675b5L, + 0xb4fb0c0c0fc31aeaL }, + { 0xed95e639a7ff1f2eL,0x9880f5a3619614fbL,0xdeb6ff02947151abL, + 0x5bc5118ca868dcdbL } }, + /* 61 << 35 */ + { { 0xd8da20554c20cea5L,0xcac2776e14c4d69aL,0xcccb22c1622d599bL, + 0xa4ddb65368a9bb50L }, + { 0x2c4ff1511b4941b4L,0xe1ff19b46efba588L,0x35034363c48345e0L, + 0x45542e3d1e29dfc4L } }, + /* 62 << 35 */ + { { 0xf197cb91349f7aedL,0x3b2b5a008fca8420L,0x7c175ee823aaf6d8L, + 0x54dcf42135af32b6L }, + { 0x0ba1430727d6561eL,0x879d5ee4d175b1e2L,0xc7c4367399807db5L, + 0x77a544559cd55bcdL } }, + /* 63 << 35 */ + { { 0xe6c2ff130105c072L,0x18f7a99f8dda7da4L,0x4c3018200e2d35c1L, + 0x06a53ca0d9cc6c82L }, + { 0xaa21cc1ef1aa1d9eL,0x324143344a75b1e8L,0x2a6d13280ebe9fdcL, + 0x16bd173f98a4755aL } }, + /* 64 << 35 */ + { { 0xfbb9b2452133ffd9L,0x39a8b2f1830f1a20L,0x484bc97dd5a1f52aL, + 0xd6aebf56a40eddf8L }, + { 0x32257acb76ccdac6L,0xaf4d36ec1586ff27L,0x8eaa8863f8de7dd1L, + 0x0045d5cf88647c16L } }, + /* 0 << 42 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 42 */ + { { 0xa6f3d574c005979dL,0xc2072b426a40e350L,0xfca5c1568de2ecf9L, + 0xa8c8bf5ba515344eL }, + { 0x97aee555114df14aL,0xd4374a4dfdc5ec6bL,0x754cc28f2ca85418L, + 0x71cb9e27d3c41f78L } }, + /* 2 << 42 */ + { { 0x8910507903605c39L,0xf0843d9ea142c96cL,0xf374493416923684L, + 0x732caa2ffa0a2893L }, + { 0xb2e8c27061160170L,0xc32788cc437fbaa3L,0x39cd818ea6eda3acL, + 0xe2e942399e2b2e07L } }, + /* 3 << 42 */ + { { 0x6967d39b0260e52aL,0xd42585cc90653325L,0x0d9bd60521ca7954L, + 0x4fa2087781ed57b3L }, + { 0x60c1eff8e34a0bbeL,0x56b0040c84f6ef64L,0x28be2b24b1af8483L, + 0xb2278163f5531614L } }, + /* 4 << 42 */ + { { 0x8df275455922ac1cL,0xa7b3ef5ca52b3f63L,0x8e77b21471de57c4L, + 0x31682c10834c008bL }, + { 0xc76824f04bd55d31L,0xb6d1c08617b61c71L,0x31db0903c2a5089dL, + 0x9c092172184e5d3fL } }, + /* 5 << 42 */ + { { 0xdd7ced5bc00cc638L,0x1a2015eb61278fc2L,0x2e8e52886a37f8d6L, + 0xc457786fe79933adL }, + { 0xb3fe4cce2c51211aL,0xad9b10b224c20498L,0x90d87a4fd28db5e5L, + 0x698cd1053aca2fc3L } }, + /* 6 << 42 */ + { { 0x4f112d07e91b536dL,0xceb982f29eba09d6L,0x3c157b2c197c396fL, + 0xe23c2d417b66eb24L }, + { 0x480c57d93f330d37L,0xb3a4c8a179108debL,0x702388decb199ce5L, + 0x0b019211b944a8d4L } }, + /* 7 << 42 */ + { { 0x24f2a692840bb336L,0x7c353bdca669fa7bL,0xda20d6fcdec9c300L, + 0x625fbe2fa13a4f17L }, + { 0xa2b1b61adbc17328L,0x008965bfa9515621L,0x49690939c620ff46L, + 0x182dd27d8717e91cL } }, + /* 8 << 42 */ + { { 0x5ace5035ea6c3997L,0x54259aaac2610befL,0xef18bb3f3c80dd39L, + 0x6910b95b5fc3fa39L }, + { 0xfce2f51043e09aeeL,0xced56c9fa7675665L,0x10e265acd872db61L, + 0x6982812eae9fce69L } }, + /* 9 << 42 */ + { { 0x29be11c6ce800998L,0x72bb1752b90360d9L,0x2c1931975a4ad590L, + 0x2ba2f5489fc1dbc0L }, + { 0x7fe4eebbe490ebe0L,0x12a0a4cd7fae11c0L,0x7197cf81e903ba37L, + 0xcf7d4aa8de1c6dd8L } }, + /* 10 << 42 */ + { { 0x92af6bf43fd5684cL,0x2b26eecf80360aa1L,0xbd960f3000546a82L, + 0x407b3c43f59ad8feL }, + { 0x86cae5fe249c82baL,0x9e0faec72463744cL,0x87f551e894916272L, + 0x033f93446ceb0615L } }, + /* 11 << 42 */ + { { 0x1e5eb0d18be82e84L,0x89967f0e7a582fefL,0xbcf687d5a6e921faL, + 0xdfee4cf3d37a09baL }, + { 0x94f06965b493c465L,0x638b9a1c7635c030L,0x7666786466f05e9fL, + 0xccaf6808c04da725L } }, + /* 12 << 42 */ + { { 0xca2eb690768fccfcL,0xf402d37db835b362L,0x0efac0d0e2fdfcceL, + 0xefc9cdefb638d990L }, + { 0x2af12b72d1669a8bL,0x33c536bc5774ccbdL,0x30b21909fb34870eL, + 0xc38fa2f77df25acaL } }, + /* 13 << 42 */ + { { 0x74c5f02bbf81f3f5L,0x0525a5aeaf7e4581L,0x88d2aaba433c54aeL, + 0xed9775db806a56c5L }, + { 0xd320738ac0edb37dL,0x25fdb6ee66cc1f51L,0xac661d1710600d76L, + 0x931ec1f3bdd1ed76L } }, + /* 14 << 42 */ + { { 0x65c11d6219ee43f1L,0x5cd57c3e60829d97L,0xd26c91a3984be6e8L, + 0xf08d93098b0c53bdL }, + { 0x94bc9e5bc016e4eaL,0xd391683911d43d2bL,0x886c5ad773701155L, + 0xe037762620b00715L } }, + /* 15 << 42 */ + { { 0x7f01c9ecaa80ba59L,0x3083411a68538e51L,0x970370f1e88128afL, + 0x625cc3db91dec14bL }, + { 0xfef9666c01ac3107L,0xb2a8d577d5057ac3L,0xb0f2629992be5df7L, + 0xf579c8e500353924L } }, + /* 16 << 42 */ + { { 0xb8fa3d931341ed7aL,0x4223272ca7b59d49L,0x3dcb194783b8c4a4L, + 0x4e413c01ed1302e4L }, + { 0x6d999127e17e44ceL,0xee86bf7533b3adfbL,0xf6902fe625aa96caL, + 0xb73540e4e5aae47dL } }, + /* 17 << 42 */ + { { 0x32801d7b1b4a158cL,0xe571c99e27e2a369L,0x40cb76c010d9f197L, + 0xc308c2893167c0aeL }, + { 0xa6ef9dd3eb7958f2L,0xa7226dfc300879b1L,0x6cd0b3627edf0636L, + 0x4efbce6c7bc37eedL } }, + /* 18 << 42 */ + { { 0x75f92a058d699021L,0x586d4c79772566e3L,0x378ca5f1761ad23aL, + 0x650d86fc1465a8acL }, + { 0x7a4ed457842ba251L,0x6b65e3e642234933L,0xaf1543b731aad657L, + 0xa4cefe98cbfec369L } }, + /* 19 << 42 */ + { { 0xb587da909f47befbL,0x6562e9fb41312d13L,0xa691ea59eff1cefeL, + 0xcc30477a05fc4cf6L }, + { 0xa16324610b0ffd3dL,0xa1f16f3b5b355956L,0x5b148d534224ec24L, + 0xdc834e7bf977012aL } }, + /* 20 << 42 */ + { { 0x7bfc5e75b2c69dbcL,0x3aa77a2903c3da6cL,0xde0df03cca910271L, + 0xcbd5ca4a7806dc55L }, + { 0xe1ca58076db476cbL,0xfde15d625f37a31eL,0xf49af520f41af416L, + 0x96c5c5b17d342db5L } }, + /* 21 << 42 */ + { { 0x155c43b7eb4ceb9bL,0x2e9930104e77371aL,0x1d2987da675d43afL, + 0xef2bc1c08599fd72L }, + { 0x96894b7b9342f6b2L,0x201eadf27c8e71f0L,0xf3479d9f4a1f3efcL, + 0xe0f8a742702a9704L } }, + /* 22 << 42 */ + { { 0xeafd44b6b3eba40cL,0xf9739f29c1c1e0d0L,0x0091471a619d505eL, + 0xc15f9c969d7c263eL }, + { 0x5be4728583afbe33L,0xa3b6d6af04f1e092L,0xe76526b9751a9d11L, + 0x2ec5b26d9a4ae4d2L } }, + /* 23 << 42 */ + { { 0xeb66f4d902f6fb8dL,0x4063c56196912164L,0xeb7050c180ef3000L, + 0x288d1c33eaa5b3f0L }, + { 0xe87c68d607806fd8L,0xb2f7f9d54bbbf50fL,0x25972f3aac8d6627L, + 0xf854777410e8c13bL } }, + /* 24 << 42 */ + { { 0xcc50ef6c872b4a60L,0xab2a34a44613521bL,0x39c5c190983e15d1L, + 0x61dde5df59905512L }, + { 0xe417f6219f2275f3L,0x0750c8b6451d894bL,0x75b04ab978b0bdaaL, + 0x3bfd9fd4458589bdL } }, + /* 25 << 42 */ + { { 0xf1013e30ee9120b6L,0x2b51af9323a4743eL,0xea96ffae48d14d9eL, + 0x71dc0dbe698a1d32L }, + { 0x914962d20180cca4L,0x1ae60677c3568963L,0x8cf227b1437bc444L, + 0xc650c83bc9962c7aL } }, + /* 26 << 42 */ + { { 0x23c2c7ddfe7ccfc4L,0xf925c89d1b929d48L,0x4460f74b06783c33L, + 0xac2c8d49a590475aL }, + { 0xfb40b407b807bba0L,0x9d1e362d69ff8f3aL,0xa33e9681cbef64a4L, + 0x67ece5fa332fb4b2L } }, + /* 27 << 42 */ + { { 0x6900a99b739f10e3L,0xc3341ca9ff525925L,0xee18a626a9e2d041L, + 0xa5a8368529580dddL }, + { 0xf3470c819d7de3cdL,0xedf025862062cf9cL,0xf43522fac010edb0L, + 0x3031413513a4b1aeL } }, + /* 28 << 42 */ + { { 0xc792e02adb22b94bL,0x993d8ae9a1eaa45bL,0x8aad6cd3cd1e1c63L, + 0x89529ca7c5ce688aL }, + { 0x2ccee3aae572a253L,0xe02b643802a21efbL,0xa7091b6ec9430358L, + 0x06d1b1fa9d7db504L } }, + /* 29 << 42 */ + { { 0x58846d32c4744733L,0x40517c71379f9e34L,0x2f65655f130ef6caL, + 0x526e4488f1f3503fL }, + { 0x8467bd177ee4a976L,0x1d9dc913921363d1L,0xd8d24c33b069e041L, + 0x5eb5da0a2cdf7f51L } }, + /* 30 << 42 */ + { { 0x1c0f3cb1197b994fL,0x3c95a6c52843eae9L,0x7766ffc9a6097ea5L, + 0x7bea4093d723b867L }, + { 0xb48e1f734db378f9L,0x70025b00e37b77acL,0x943dc8e7af24ad46L, + 0xb98a15ac16d00a85L } }, + /* 31 << 42 */ + { { 0x3adc38ba2743b004L,0xb1c7f4f7334415eeL,0xea43df8f1e62d05aL, + 0x326189059d76a3b6L }, + { 0x2fbd0bb5a23a0f46L,0x5bc971db6a01918cL,0x7801d94ab4743f94L, + 0xb94df65e676ae22bL } }, + /* 32 << 42 */ + { { 0xaafcbfabaf95894cL,0x7b9bdc07276b2241L,0xeaf983625bdda48bL, + 0x5977faf2a3fcb4dfL }, + { 0xbed042ef052c4b5bL,0x9fe87f71067591f0L,0xc89c73ca22f24ec7L, + 0x7d37fa9ee64a9f1bL } }, + /* 33 << 42 */ + { { 0x2710841a15562627L,0x2c01a613c243b034L,0x1d135c562bc68609L, + 0xc2ca17158b03f1f6L }, + { 0xc9966c2d3eb81d82L,0xc02abf4a8f6df13eL,0x77b34bd78f72b43bL, + 0xaff6218f360c82b0L } }, + /* 34 << 42 */ + { { 0x0aa5726c8d55b9d2L,0xdc0adbe999e9bffbL,0x9097549cefb9e72aL, + 0x167557129dfb3111L }, + { 0xdd8bf984f26847f9L,0xbcb8e387dfb30cb7L,0xc1fd32a75171ef9cL, + 0x977f3fc7389b363fL } }, + /* 35 << 42 */ + { { 0x116eaf2bf4babda0L,0xfeab68bdf7113c8eL,0xd1e3f064b7def526L, + 0x1ac30885e0b3fa02L }, + { 0x1c5a6e7b40142d9dL,0x839b560330921c0bL,0x48f301fa36a116a3L, + 0x380e1107cfd9ee6dL } }, + /* 36 << 42 */ + { { 0x7945ead858854be1L,0x4111c12ecbd4d49dL,0xece3b1ec3a29c2efL, + 0x6356d4048d3616f5L }, + { 0x9f0d6a8f594d320eL,0x0989316df651ccd2L,0x6c32117a0f8fdde4L, + 0x9abe5cc5a26a9bbcL } }, + /* 37 << 42 */ + { { 0xcff560fb9723f671L,0x21b2a12d7f3d593cL,0xe4cb18da24ba0696L, + 0x186e2220c3543384L }, + { 0x722f64e088312c29L,0x94282a9917dc7752L,0x62467bbf5a85ee89L, + 0xf435c650f10076a0L } }, + /* 38 << 42 */ + { { 0xc9ff153943b3a50bL,0x7132130c1a53efbcL,0x31bfe063f7b0c5b7L, + 0xb0179a7d4ea994ccL }, + { 0x12d064b3c85f455bL,0x472593288f6e0062L,0xf64e590bb875d6d9L, + 0x22dd6225ad92bcc7L } }, + /* 39 << 42 */ + { { 0xb658038eb9c3bd6dL,0x00cdb0d6fbba27c8L,0x0c6813371062c45dL, + 0xd8515b8c2d33407dL }, + { 0xcb8f699e8cbb5ecfL,0x8c4347f8c608d7d8L,0x2c11850abb3e00dbL, + 0x20a8dafdecb49d19L } }, + /* 40 << 42 */ + { { 0xbd78148045ee2f40L,0x75e354af416b60cfL,0xde0b58a18d49a8c4L, + 0xe40e94e2fa359536L }, + { 0xbd4fa59f62accd76L,0x05cf466a8c762837L,0xb5abda99448c277bL, + 0x5a9e01bf48b13740L } }, + /* 41 << 42 */ + { { 0x9d457798326aad8dL,0xbdef4954c396f7e7L,0x6fb274a2c253e292L, + 0x2800bf0a1cfe53e7L }, + { 0x22426d3144438fd4L,0xef2339235e259f9aL,0x4188503c03f66264L, + 0x9e5e7f137f9fdfabL } }, + /* 42 << 42 */ + { { 0x565eb76c5fcc1abaL,0xea63254859b5bff8L,0x5587c087aab6d3faL, + 0x92b639ea6ce39c1bL }, + { 0x0706e782953b135cL,0x7308912e425268efL,0x599e92c7090e7469L, + 0x83b90f529bc35e75L } }, + /* 43 << 42 */ + { { 0x4750b3d0244975b3L,0xf3a4435811965d72L,0x179c67749c8dc751L, + 0xff18cdfed23d9ff0L }, + { 0xc40138332028e247L,0x96e280e2f3bfbc79L,0xf60417bdd0880a84L, + 0x263c9f3d2a568151L } }, + /* 44 << 42 */ + { { 0x36be15b32d2ce811L,0x846dc0c2f8291d21L,0x5cfa0ecb789fcfdbL, + 0x45a0beedd7535b9aL }, + { 0xec8e9f0796d69af1L,0x31a7c5b8599ab6dcL,0xd36d45eff9e2e09fL, + 0x3cf49ef1dcee954bL } }, + /* 45 << 42 */ + { { 0x6be34cf3086cff9bL,0x88dbd49139a3360fL,0x1e96b8cc0dbfbd1dL, + 0xc1e5f7bfcb7e2552L }, + { 0x0547b21428819d98L,0xc770dd9c7aea9dcbL,0xaef0d4c7041d68c8L, + 0xcc2b981813cb9ba8L } }, + /* 46 << 42 */ + { { 0x7fc7bc76fe86c607L,0x6b7b9337502a9a95L,0x1948dc27d14dab63L, + 0x249dd198dae047beL }, + { 0xe8356584a981a202L,0x3531dd183a893387L,0x1be11f90c85c7209L, + 0x93d2fe1ee2a52b5aL } }, + /* 47 << 42 */ + { { 0x8225bfe2ec6d6b97L,0x9cf6d6f4bd0aa5deL,0x911459cb54779f5fL, + 0x5649cddb86aeb1f3L }, + { 0x321335793f26ce5aL,0xc289a102550f431eL,0x559dcfda73b84c6fL, + 0x84973819ee3ac4d7L } }, + /* 48 << 42 */ + { { 0xb51e55e6f2606a82L,0xe25f706190f2fb57L,0xacef6c2ab1a4e37cL, + 0x864e359d5dcf2706L }, + { 0x479e6b187ce57316L,0x2cab25003a96b23dL,0xed4898628ef16df7L, + 0x2056538cef3758b5L } }, + /* 49 << 42 */ + { { 0xa7df865ef15d3101L,0x80c5533a61b553d7L,0x366e19974ed14294L, + 0x6620741fb3c0bcd6L }, + { 0x21d1d9c4edc45418L,0x005b859ec1cc4a9dL,0xdf01f630a1c462f0L, + 0x15d06cf3f26820c7L } }, + /* 50 << 42 */ + { { 0x9f7f24ee3484be47L,0x2ff33e964a0c902fL,0x00bdf4575a0bc453L, + 0x2378dfaf1aa238dbL }, + { 0x272420ec856720f2L,0x2ad9d95b96797291L,0xd1242cc6768a1558L, + 0x2e287f8b5cc86aa8L } }, + /* 51 << 42 */ + { { 0x796873d0990cecaaL,0xade55f81675d4080L,0x2645eea321f0cd84L, + 0x7a1efa0fb4e17d02L }, + { 0xf6858420037cc061L,0x682e05f0d5d43e12L,0x59c3699427218710L, + 0x85cbba4d3f7cd2fcL } }, + /* 52 << 42 */ + { { 0x726f97297a3cd22aL,0x9f8cd5dc4a628397L,0x17b93ab9c23165edL, + 0xff5f5dbf122823d4L }, + { 0xc1e4e4b5654a446dL,0xd1a9496f677257baL,0x6387ba94de766a56L, + 0x23608bc8521ec74aL } }, + /* 53 << 42 */ + { { 0x16a522d76688c4d4L,0x9d6b428207373abdL,0xa62f07acb42efaa3L, + 0xf73e00f7e3b90180L }, + { 0x36175fec49421c3eL,0xc4e44f9b3dcf2678L,0x76df436b7220f09fL, + 0x172755fb3aa8b6cfL } }, + /* 54 << 42 */ + { { 0xbab89d57446139ccL,0x0a0a6e025fe0208fL,0xcdbb63e211e5d399L, + 0x33ecaa12a8977f0bL }, + { 0x59598b21f7c42664L,0xb3e91b32ab65d08aL,0x035822eef4502526L, + 0x1dcf0176720a82a9L } }, + /* 55 << 42 */ + { { 0x50f8598f3d589e02L,0xdf0478ffb1d63d2cL,0x8b8068bd1571cd07L, + 0x30c3aa4fd79670cdL }, + { 0x25e8fd4b941ade7fL,0x3d1debdc32790011L,0x65b6dcbd3a3f9ff0L, + 0x282736a4793de69cL } }, + /* 56 << 42 */ + { { 0xef69a0c3d41d3bd3L,0xb533b8c907a26bdeL,0xe2801d97db2edf9fL, + 0xdc4a8269e1877af0L }, + { 0x6c1c58513d590dbeL,0x84632f6bee4e9357L,0xd36d36b779b33374L, + 0xb46833e39bbca2e6L } }, + /* 57 << 42 */ + { { 0x37893913f7fc0586L,0x385315f766bf4719L,0x72c56293b31855dcL, + 0xd1416d4e849061feL }, + { 0xbeb3ab7851047213L,0x447f6e61f040c996L,0xd06d310d638b1d0cL, + 0xe28a413fbad1522eL } }, + /* 58 << 42 */ + { { 0x685a76cb82003f86L,0x610d07f70bcdbca3L,0x6ff660219ca4c455L, + 0x7df39b87cea10eecL }, + { 0xb9255f96e22db218L,0x8cc6d9eb08a34c44L,0xcd4ffb86859f9276L, + 0x8fa15eb250d07335L } }, + /* 59 << 42 */ + { { 0xdf553845cf2c24b5L,0x89f66a9f52f9c3baL,0x8f22b5b9e4a7ceb3L, + 0xaffef8090e134686L }, + { 0x3e53e1c68eb8fac2L,0x93c1e4eb28aec98eL,0xb6b91ec532a43bcbL, + 0x2dbfa947b2d74a51L } }, + /* 60 << 42 */ + { { 0xe065d190ca84bad7L,0xfb13919fad58e65cL,0x3c41718bf1cb6e31L, + 0x688969f006d05c3fL }, + { 0xd4f94ce721264d45L,0xfdfb65e97367532bL,0x5b1be8b10945a39dL, + 0x229f789c2b8baf3bL } }, + /* 61 << 42 */ + { { 0xd8f41f3e6f49f15dL,0x678ce828907f0792L,0xc69ace82fca6e867L, + 0x106451aed01dcc89L }, + { 0x1bb4f7f019fc32d2L,0x64633dfcb00c52d2L,0x8f13549aad9ea445L, + 0x99a3bf50fb323705L } }, + /* 62 << 42 */ + { { 0x0c9625a2534d4dbcL,0x45b8f1d1c2a2fea3L,0x76ec21a1a530fc1aL, + 0x4bac9c2a9e5bd734L }, + { 0x5996d76a7b4e3587L,0x0045cdee1182d9e3L,0x1aee24b91207f13dL, + 0x66452e9797345a41L } }, + /* 63 << 42 */ + { { 0x16e5b0549f950cd0L,0x9cc72fb1d7fdd075L,0x6edd61e766249663L, + 0xde4caa4df043cccbL }, + { 0x11b1f57a55c7ac17L,0x779cbd441a85e24dL,0x78030f86e46081e7L, + 0xfd4a60328e20f643L } }, + /* 64 << 42 */ + { { 0xcc7a64880a750c0fL,0x39bacfe34e548e83L,0x3d418c760c110f05L, + 0x3e4daa4cb1f11588L }, + { 0x2733e7b55ffc69ffL,0x46f147bc92053127L,0x885b2434d722df94L, + 0x6a444f65e6fc6b7cL } }, + /* 0 << 49 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 49 */ + { { 0x7a1a465ac3f16ea8L,0x115a461db2f1d11cL,0x4767dd956c68a172L, + 0x3392f2ebd13a4698L }, + { 0xc7a99ccde526cdc7L,0x8e537fdc22292b81L,0x76d8cf69a6d39198L, + 0xffc5ff432446852dL } }, + /* 2 << 49 */ + { { 0x97b14f7ea90567e6L,0x513257b7b6ae5cb7L,0x85454a3c9f10903dL, + 0xd8d2c9ad69bc3724L }, + { 0x38da93246b29cb44L,0xb540a21d77c8cbacL,0x9bbfe43501918e42L, + 0xfffa707a56c3614eL } }, + /* 3 << 49 */ + { { 0x0ce4e3f1d4e353b7L,0x062d8a14ef46b0a0L,0x6408d5ab574b73fdL, + 0xbc41d1c9d3273ffdL }, + { 0x3538e1e76be77800L,0x71fe8b37c5655031L,0x1cd916216b9b331aL, + 0xad825d0bbb388f73L } }, + /* 4 << 49 */ + { { 0x56c2e05b1cb76219L,0x0ec0bf9171567e7eL,0xe7076f8661c4c910L, + 0xd67b085bbabc04d9L }, + { 0x9fb904595e93a96aL,0x7526c1eafbdc249aL,0x0d44d367ecdd0bb7L, + 0x953999179dc0d695L } }, + /* 5 << 49 */ + { { 0x61360ee99e240d18L,0x057cdcacb4b94466L,0xe7667cd12fe5325cL, + 0x1fa297b521974e3bL }, + { 0xfa4081e7db083d76L,0x31993be6f206bd15L,0x8949269b14c19f8cL, + 0x21468d72a9d92357L } }, + /* 6 << 49 */ + { { 0x2ccbc583a4c506ecL,0x957ed188d1acfe97L,0x8baed83312f1aea2L, + 0xef2a6cb48325362dL }, + { 0x130dde428e195c43L,0xc842025a0e6050c6L,0x2da972a708686a5dL, + 0xb52999a1e508b4a8L } }, + /* 7 << 49 */ + { { 0xd9f090b910a5a8bdL,0xca91d249096864daL,0x8e6a93be3f67dbc1L, + 0xacae6fbaf5f4764cL }, + { 0x1563c6e0d21411a0L,0x28fa787fda0a4ad8L,0xd524491c908c8030L, + 0x1257ba0e4c795f07L } }, + /* 8 << 49 */ + { { 0x83f49167ceca9754L,0x426d2cf64b7939a0L,0x2555e355723fd0bfL, + 0xa96e6d06c4f144e2L }, + { 0x4768a8dd87880e61L,0x15543815e508e4d5L,0x09d7e772b1b65e15L, + 0x63439dd6ac302fa0L } }, + /* 9 << 49 */ + { { 0xb93f802fc14e35c2L,0x71735b7c4341333cL,0x03a2510416d4f362L, + 0x3f4d069bbf433c8eL }, + { 0x0d83ae01f78f5a7cL,0x50a8ffbe7c4eed07L,0xc74f890676e10f83L, + 0x7d0809669ddaf8e1L } }, + /* 10 << 49 */ + { { 0xb11df8e1698e04ccL,0x877be203169005c8L,0x32749e8c4f3c6179L, + 0x2dbc9d0a7853fc05L }, + { 0x187d4f939454d937L,0xe682ce9db4800e1bL,0xa9129ad8165e68e8L, + 0x0fe29735be7f785bL } }, + /* 11 << 49 */ + { { 0x5303f40c5b9e02b7L,0xa37c969235ee04e8L,0x5f46cc2034d6632bL, + 0x55ef72b296ac545bL }, + { 0xabec5c1f7b91b062L,0x0a79e1c7bb33e821L,0xbb04b4283a9f4117L, + 0x0de1f28ffd2a475aL } }, + /* 12 << 49 */ + { { 0x31019ccf3a4434b4L,0xa34581111a7954dcL,0xa9dac80de34972a7L, + 0xb043d05474f6b8ddL }, + { 0x021c319e11137b1aL,0x00a754ceed5cc03fL,0x0aa2c794cbea5ad4L, + 0x093e67f470c015b6L } }, + /* 13 << 49 */ + { { 0x72cdfee9c97e3f6bL,0xc10bcab4b6da7461L,0x3b02d2fcb59806b9L, + 0x85185e89a1de6f47L }, + { 0x39e6931f0eb6c4d4L,0x4d4440bdd4fa5b04L,0x5418786e34be7eb8L, + 0x6380e5219d7259bcL } }, + /* 14 << 49 */ + { { 0x20ac0351d598d710L,0x272c4166cb3a4da4L,0xdb82fe1aca71de1fL, + 0x746e79f2d8f54b0fL }, + { 0x6e7fc7364b573e9bL,0x75d03f46fd4b5040L,0x5c1cc36d0b98d87bL, + 0x513ba3f11f472da1L } }, + /* 15 << 49 */ + { { 0x79d0af26abb177ddL,0xf82ab5687891d564L,0x2b6768a972232173L, + 0xefbb3bb08c1f6619L }, + { 0xb29c11dba6d18358L,0x519e2797b0916d3aL,0xd4dc18f09188e290L, + 0x648e86e398b0ca7fL } }, + /* 16 << 49 */ + { { 0x859d3145983c38b5L,0xb14f176c637abc8bL,0x2793fb9dcaff7be6L, + 0xebe5a55f35a66a5aL }, + { 0x7cec1dcd9f87dc59L,0x7c595cd3fbdbf560L,0x5b543b2226eb3257L, + 0x69080646c4c935fdL } }, + /* 17 << 49 */ + { { 0x7f2e440381e9ede3L,0x243c3894caf6df0aL,0x7c605bb11c073b11L, + 0xcd06a541ba6a4a62L }, + { 0x2916894949d4e2e5L,0x33649d074af66880L,0xbfc0c885e9a85035L, + 0xb4e52113fc410f4bL } }, + /* 18 << 49 */ + { { 0xdca3b70678a6513bL,0x92ea4a2a9edb1943L,0x02642216db6e2dd8L, + 0x9b45d0b49fd57894L }, + { 0x114e70dbc69d11aeL,0x1477dd194c57595fL,0xbc2208b4ec77c272L, + 0x95c5b4d7db68f59cL } }, + /* 19 << 49 */ + { { 0xb8c4fc6342e532b7L,0x386ba4229ae35290L,0xfb5dda42d201ecbcL, + 0x2353dc8ba0e38fd6L }, + { 0x9a0b85ea68f7e978L,0x96ec56822ad6d11fL,0x5e279d6ce5f6886dL, + 0xd3fe03cd3cb1914dL } }, + /* 20 << 49 */ + { { 0xfe541fa47ea67c77L,0x952bd2afe3ea810cL,0x791fef568d01d374L, + 0xa3a1c6210f11336eL }, + { 0x5ad0d5a9c7ec6d79L,0xff7038af3225c342L,0x003c6689bc69601bL, + 0x25059bc745e8747dL } }, + /* 21 << 49 */ + { { 0xfa4965b2f2086fbfL,0xf6840ea686916078L,0xd7ac762070081d6cL, + 0xe600da31b5328645L }, + { 0x01916f63529b8a80L,0xe80e48582d7d6f3eL,0x29eb0fe8d664ca7cL, + 0xf017637be7b43b0cL } }, + /* 22 << 49 */ + { { 0x9a75c80676cb2566L,0x8f76acb1b24892d9L,0x7ae7b9cc1f08fe45L, + 0x19ef73296a4907d8L }, + { 0x2db4ab715f228bf0L,0xf3cdea39817032d7L,0x0b1f482edcabe3c0L, + 0x3baf76b4bb86325cL } }, + /* 23 << 49 */ + { { 0xd49065e010089465L,0x3bab5d298e77c596L,0x7636c3a6193dbd95L, + 0xdef5d294b246e499L }, + { 0xb22c58b9286b2475L,0xa0b93939cd80862bL,0x3002c83af0992388L, + 0x6de01f9beacbe14cL } }, + /* 24 << 49 */ + { { 0x6aac688eadd70482L,0x708de92a7b4a4e8aL,0x75b6dd73758a6eefL, + 0xea4bf352725b3c43L }, + { 0x10041f2c87912868L,0xb1b1be95ef09297aL,0x19ae23c5a9f3860aL, + 0xc4f0f839515dcf4bL } }, + /* 25 << 49 */ + { { 0x3c7ecca397f6306aL,0x744c44ae68a3a4b0L,0x69cd13a0b3a1d8a2L, + 0x7cad0a1e5256b578L }, + { 0xea653fcd33791d9eL,0x9cc2a05d74b2e05fL,0x73b391dcfd7affa2L, + 0xddb7091eb6b05442L } }, + /* 26 << 49 */ + { { 0xc71e27bf8538a5c6L,0x195c63dd89abff17L,0xfd3152851b71e3daL, + 0x9cbdfda7fa680fa0L }, + { 0x9db876ca849d7eabL,0xebe2764b3c273271L,0x663357e3f208dceaL, + 0x8c5bd833565b1b70L } }, + /* 27 << 49 */ + { { 0xccc3b4f59837fc0dL,0x9b641ba8a79cf00fL,0x7428243ddfdf3990L, + 0x83a594c4020786b1L }, + { 0xb712451a526c4502L,0x9d39438e6adb3f93L,0xfdb261e3e9ff0ccdL, + 0x80344e3ce07af4c3L } }, + /* 28 << 49 */ + { { 0x75900d7c2fa4f126L,0x08a3b8655c99a232L,0x2478b6bfdb25e0c3L, + 0x482cc2c271db2edfL }, + { 0x37df7e645f321bb8L,0x8a93821b9a8005b4L,0x3fa2f10ccc8c1958L, + 0x0d3322182c269d0aL } }, + /* 29 << 49 */ + { { 0x20ab8119e246b0e6L,0xb39781e4d349fd17L,0xd293231eb31aa100L, + 0x4b779c97bb032168L }, + { 0x4b3f19e1c8470500L,0x45b7efe90c4c869dL,0xdb84f38aa1a6bbccL, + 0x3b59cb15b2fddbc1L } }, + /* 30 << 49 */ + { { 0xba5514df3fd165e8L,0x499fd6a9061f8811L,0x72cd1fe0bfef9f00L, + 0x120a4bb979ad7e8aL }, + { 0xf2ffd0955f4a5ac5L,0xcfd174f195a7a2f0L,0xd42301ba9d17baf1L, + 0xd2fa487a77f22089L } }, + /* 31 << 49 */ + { { 0x9cb09efeb1dc77e1L,0xe956693921c99682L,0x8c5469016c6067bbL, + 0xfd37857461c24456L }, + { 0x2b6a6cbe81796b33L,0x62d550f658e87f8bL,0x1b763e1c7f1b01b4L, + 0x4b93cfea1b1b5e12L } }, + /* 32 << 49 */ + { { 0xb93452381d531696L,0x57201c0088cdde69L,0xdde922519a86afc7L, + 0xe3043895bd35cea8L }, + { 0x7608c1e18555970dL,0x8267dfa92535935eL,0xd4c60a57322ea38bL, + 0xe0bf7977804ef8b5L } }, + /* 33 << 49 */ + { { 0x1a0dab28c06fece4L,0xd405991e94e7b49dL,0xc542b6d2706dab28L, + 0xcb228da3a91618fbL }, + { 0x224e4164107d1ceaL,0xeb9fdab3d0f5d8f1L,0xc02ba3860d6e41cdL, + 0x676a72c59b1f7146L } }, + /* 34 << 49 */ + { { 0xffd6dd984d6cb00bL,0xcef9c5cade2e8d7cL,0xa1bbf5d7641c7936L, + 0x1b95b230ee8f772eL }, + { 0xf765a92ee8ac25b1L,0xceb04cfc3a18b7c6L,0x27944cef0acc8966L, + 0xcbb3c957434c1004L } }, + /* 35 << 49 */ + { { 0x9c9971a1a43ff93cL,0x5bc2db17a1e358a9L,0x45b4862ea8d9bc82L, + 0x70ebfbfb2201e052L }, + { 0xafdf64c792871591L,0xea5bcae6b42d0219L,0xde536c552ad8f03cL, + 0xcd6c3f4da76aa33cL } }, + /* 36 << 49 */ + { { 0xbeb5f6230bca6de3L,0xdd20dd99b1e706fdL,0x90b3ff9dac9059d4L, + 0x2d7b29027ccccc4eL }, + { 0x8a090a59ce98840fL,0xa5d947e08410680aL,0x49ae346a923379a5L, + 0x7dbc84f9b28a3156L } }, + /* 37 << 49 */ + { { 0xfd40d91654a1aff2L,0xabf318ba3a78fb9bL,0x50152ed83029f95eL, + 0x9fc1dd77c58ad7faL }, + { 0x5fa5791513595c17L,0xb95046688f62b3a9L,0x907b5b24ff3055b0L, + 0x2e995e359a84f125L } }, + /* 38 << 49 */ + { { 0x87dacf697e9bbcfbL,0x95d0c1d6e86d96e3L,0x65726e3c2d95a75cL, + 0x2c3c9001acd27f21L }, + { 0x1deab5616c973f57L,0x108b7e2ca5221643L,0x5fee9859c4ef79d4L, + 0xbd62b88a40d4b8c6L } }, + /* 39 << 49 */ + { { 0xb4dd29c4197c75d6L,0x266a6df2b7076febL,0x9512d0ea4bf2df11L, + 0x1320c24f6b0cc9ecL }, + { 0x6bb1e0e101a59596L,0x8317c5bbeff9aaacL,0x65bb405e385aa6c9L, + 0x613439c18f07988fL } }, + /* 40 << 49 */ + { { 0xd730049f16a66e91L,0xe97f2820fa1b0e0dL,0x4131e003304c28eaL, + 0x820ab732526bac62L }, + { 0xb2ac9ef928714423L,0x54ecfffaadb10cb2L,0x8781476ef886a4ccL, + 0x4b2c87b5db2f8d49L } }, + /* 41 << 49 */ + { { 0xe857cd200a44295dL,0x707d7d2158c6b044L,0xae8521f9f596757cL, + 0x87448f0367b2b714L }, + { 0x13a9bc455ebcd58dL,0x79bcced99122d3c1L,0x3c6442479e076642L, + 0x0cf227782df4767dL } }, + /* 42 << 49 */ + { { 0x5e61aee471d444b6L,0x211236bfc5084a1dL,0x7e15bc9a4fd3eaf6L, + 0x68df2c34ab622bf5L }, + { 0x9e674f0f59bf4f36L,0xf883669bd7f34d73L,0xc48ac1b831497b1dL, + 0x323b925d5106703bL } }, + /* 43 << 49 */ + { { 0x22156f4274082008L,0xeffc521ac8482bcbL,0x5c6831bf12173479L, + 0xcaa2528fc4739490L }, + { 0x84d2102a8f1b3c4dL,0xcf64dfc12d9bec0dL,0x433febad78a546efL, + 0x1f621ec37b73cef1L } }, + /* 44 << 49 */ + { { 0x6aecd62737338615L,0x162082ab01d8edf6L,0x833a811919e86b66L, + 0x6023a251d299b5dbL }, + { 0xf5bb0c3abbf04b89L,0x6735eb69ae749a44L,0xd0e058c54713de3bL, + 0xfdf2593e2c3d4ccdL } }, + /* 45 << 49 */ + { { 0x1b8f414efdd23667L,0xdd52aacafa2015eeL,0x3e31b517bd9625ffL, + 0x5ec9322d8db5918cL }, + { 0xbc73ac85a96f5294L,0x82aa5bf361a0666aL,0x49755810bf08ac42L, + 0xd21cdfd5891cedfcL } }, + /* 46 << 49 */ + { { 0x918cb57b67f8be10L,0x365d1a7c56ffa726L,0x2435c5046532de93L, + 0xc0fc5e102674cd02L }, + { 0x6e51fcf89cbbb142L,0x1d436e5aafc50692L,0x766bffff3fbcae22L, + 0x3148c2fdfd55d3b8L } }, + /* 47 << 49 */ + { { 0x52c7fdc9233222faL,0x89ff1092e419fb6bL,0x3cd6db9925254977L, + 0x2e85a1611cf12ca7L }, + { 0xadd2547cdc810bc9L,0xea3f458f9d257c22L,0x642c1fbe27d6b19bL, + 0xed07e6b5140481a6L } }, + /* 48 << 49 */ + { { 0x6ada1d4286d2e0f8L,0xe59201220e8a9fd5L,0x02c936af708c1b49L, + 0x60f30fee2b4bfaffL }, + { 0x6637ad06858e6a61L,0xce4c77673fd374d0L,0x39d54b2d7188defbL, + 0xa8c9d250f56a6b66L } }, + /* 49 << 49 */ + { { 0x58fc0f5eb24fe1dcL,0x9eaf9dee6b73f24cL,0xa90d588b33650705L, + 0xde5b62c5af2ec729L }, + { 0x5c72cfaed3c2b36eL,0x868c19d5034435daL,0x88605f93e17ee145L, + 0xaa60c4ee77a5d5b1L } }, + /* 50 << 49 */ + { { 0xbcf5bfd23b60c472L,0xaf4ef13ceb1d3049L,0x373f44fce13895c9L, + 0xf29b382f0cbc9822L }, + { 0x1bfcb85373efaef6L,0xcf56ac9ca8c96f40L,0xd7adf1097a191e24L, + 0x98035f44bf8a8dc2L } }, + /* 51 << 49 */ + { { 0xf40a71b91e750c84L,0xc57f7b0c5dc6c469L,0x49a0e79c6fbc19c1L, + 0x6b0f5889a48ebdb8L }, + { 0x5d3fd084a07c4e9fL,0xc3830111ab27de14L,0x0e4929fe33e08dccL, + 0xf4a5ad2440bb73a3L } }, + /* 52 << 49 */ + { { 0xde86c2bf490f97caL,0x288f09c667a1ce18L,0x364bb8861844478dL, + 0x7840fa42ceedb040L }, + { 0x1269fdd25a631b37L,0x94761f1ea47c8b7dL,0xfc0c2e17481c6266L, + 0x85e16ea23daa5fa7L } }, + /* 53 << 49 */ + { { 0xccd8603392491048L,0x0c2f6963f4d402d7L,0x6336f7dfdf6a865cL, + 0x0a2a463cb5c02a87L }, + { 0xb0e29be7bf2f12eeL,0xf0a2200266bad988L,0x27f87e039123c1d7L, + 0x21669c55328a8c98L } }, + /* 54 << 49 */ + { { 0x186b980392f14529L,0xd3d056cc63954df3L,0x2f03fd58175a46f6L, + 0x63e34ebe11558558L }, + { 0xe13fedee5b80cfa5L,0xe872a120d401dbd1L,0x52657616e8a9d667L, + 0xbc8da4b6e08d6693L } }, + /* 55 << 49 */ + { { 0x370fb9bb1b703e75L,0x6773b186d4338363L,0x18dad378ecef7bffL, + 0xaac787ed995677daL }, + { 0x4801ea8b0437164bL,0xf430ad2073fe795eL,0xb164154d8ee5eb73L, + 0x0884ecd8108f7c0eL } }, + /* 56 << 49 */ + { { 0x0e6ec0965f520698L,0x640631fe44f7b8d9L,0x92fd34fca35a68b9L, + 0x9c5a4b664d40cf4eL }, + { 0x949454bf80b6783dL,0x80e701fe3a320a10L,0x8d1a564a1a0a39b2L, + 0x1436d53d320587dbL } }, + /* 57 << 49 */ + { { 0xf5096e6d6556c362L,0xbc23a3c0e2455d7eL,0x3a7aee54807230f9L, + 0x9ba1cfa622ae82fdL }, + { 0x833a057a99c5d706L,0x8be85f4b842315c9L,0xd083179a66a72f12L, + 0x2fc77d5dcdcc73cdL } }, + /* 58 << 49 */ + { { 0x22b88a805616ee30L,0xfb09548fe7ab1083L,0x8ad6ab0d511270cdL, + 0x61f6c57a6924d9abL }, + { 0xa0f7bf7290aecb08L,0x849f87c90df784a4L,0x27c79c15cfaf1d03L, + 0xbbf9f675c463faceL } }, + /* 59 << 49 */ + { { 0x91502c65765ba543L,0x18ce3cac42ea60ddL,0xe5cee6ac6e43ecb3L, + 0x63e4e91068f2aeebL }, + { 0x26234fa3c85932eeL,0x96883e8b4c90c44dL,0x29b9e738a18a50f6L, + 0xbfc62b2a3f0420dfL } }, + /* 60 << 49 */ + { { 0xd22a7d906d3e1fa9L,0x17115618fe05b8a3L,0x2a0c9926bb2b9c01L, + 0xc739fcc6e07e76a2L }, + { 0x540e9157165e439aL,0x06353a626a9063d8L,0x84d9559461e927a3L, + 0x013b9b26e2e0be7fL } }, + /* 61 << 49 */ + { { 0x4feaec3b973497f1L,0x15c0f94e093ebc2dL,0x6af5f22733af0583L, + 0x0c2af206c61f3340L }, + { 0xd25dbdf14457397cL,0x2e8ed017cabcbae0L,0xe3010938c2815306L, + 0xbaa99337e8c6cd68L } }, + /* 62 << 49 */ + { { 0x085131823b0ec7deL,0x1e1b822b58df05dfL,0x5c14842fa5c3b683L, + 0x98fe977e3eba34ceL }, + { 0xfd2316c20d5e8873L,0xe48d839abd0d427dL,0x495b2218623fc961L, + 0x24ee56e7b46fba5eL } }, + /* 63 << 49 */ + { { 0x9184a55b91e4de58L,0xa7488ca5dfdea288L,0xa723862ea8dcc943L, + 0x92d762b2849dc0fcL }, + { 0x3c444a12091ff4a9L,0x581113fa0cada274L,0xb9de0a4530d8eae2L, + 0x5e0fcd85df6b41eaL } }, + /* 64 << 49 */ + { { 0x6233ea68c094dbb5L,0xb77d062ed968d410L,0x3e719bbc58b3002dL, + 0x68e7dd3d3dc49d58L }, + { 0x8d825740013a5e58L,0x213117473c9e3c1bL,0x0cb0a2a77c99b6abL, + 0x5c48a3b3c2f888f2L } }, + /* 0 << 56 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 56 */ + { { 0xc7913e91991724f3L,0x5eda799c39cbd686L,0xddb595c763d4fc1eL, + 0x6b63b80bac4fed54L }, + { 0x6ea0fc697e5fb516L,0x737708bad0f1c964L,0x9628745f11a92ca5L, + 0x61f379589a86967aL } }, + /* 2 << 56 */ + { { 0x9af39b2caa665072L,0x78322fa4efd324efL,0x3d153394c327bd31L, + 0x81d5f2713129dab0L }, + { 0xc72e0c42f48027f5L,0xaa40cdbc8536e717L,0xf45a657a2d369d0fL, + 0xb03bbfc4ea7f74e6L } }, + /* 3 << 56 */ + { { 0x46a8c4180d738dedL,0x6f1a5bb0e0de5729L,0xf10230b98ba81675L, + 0x32c6f30c112b33d4L }, + { 0x7559129dd8fffb62L,0x6a281b47b459bf05L,0x77c1bd3afa3b6776L, + 0x0709b3807829973aL } }, + /* 4 << 56 */ + { { 0x8c26b232a3326505L,0x38d69272ee1d41bfL,0x0459453effe32afaL, + 0xce8143ad7cb3ea87L }, + { 0x932ec1fa7e6ab666L,0x6cd2d23022286264L,0x459a46fe6736f8edL, + 0x50bf0d009eca85bbL } }, + /* 5 << 56 */ + { { 0x0b825852877a21ecL,0x300414a70f537a94L,0x3f1cba4021a9a6a2L, + 0x50824eee76943c00L }, + { 0xa0dbfcecf83cba5dL,0xf953814893b4f3c0L,0x6174416248f24dd7L, + 0x5322d64de4fb09ddL } }, + /* 6 << 56 */ + { { 0x574473843d9325f3L,0xa9bef2d0f371cb84L,0x77d2188ba61e36c5L, + 0xbbd6a7d7c602df72L }, + { 0xba3aa9028f61bc0bL,0xf49085ed6ed0b6a1L,0x8bc625d6ae6e8298L, + 0x832b0b1da2e9c01dL } }, + /* 7 << 56 */ + { { 0xa337c447f1f0ced1L,0x800cc7939492dd2bL,0x4b93151dbea08efaL, + 0x820cf3f8de0a741eL }, + { 0xff1982dc1c0f7d13L,0xef92196084dde6caL,0x1ad7d97245f96ee3L, + 0x319c8dbe29dea0c7L } }, + /* 8 << 56 */ + { { 0xd3ea38717b82b99bL,0x75922d4d470eb624L,0x8f66ec543b95d466L, + 0x66e673ccbee1e346L }, + { 0x6afe67c4b5f2b89aL,0x3de9c1e6290e5cd3L,0x8c278bb6310a2adaL, + 0x420fa3840bdb323bL } }, + /* 9 << 56 */ + { { 0x0ae1d63b0eb919b0L,0xd74ee51da74b9620L,0x395458d0a674290cL, + 0x324c930f4620a510L }, + { 0x2d1f4d19fbac27d4L,0x4086e8ca9bedeeacL,0x0cdd211b9b679ab8L, + 0x5970167d7090fec4L } }, + /* 10 << 56 */ + { { 0x3420f2c9faf1fc63L,0x616d333a328c8bb4L,0x7d65364c57f1fe4aL, + 0x9343e87755e5c73aL }, + { 0x5795176be970e78cL,0xa36ccebf60533627L,0xfc7c738009cdfc1bL, + 0xb39a2afeb3fec326L } }, + /* 11 << 56 */ + { { 0xb7ff1ba16224408aL,0xcc856e92247cfc5eL,0x01f102e7c18bc493L, + 0x4613ab742091c727L }, + { 0xaa25e89cc420bf2bL,0x00a5317690337ec2L,0xd2be9f437d025fc7L, + 0x3316fb856e6fe3dcL } }, + /* 12 << 56 */ + { { 0x27520af59ac50814L,0xfdf95e789a8e4223L,0xb7e7df2a56bec5a0L, + 0xf7022f7ddf159e5dL }, + { 0x93eeeab1cac1fe8fL,0x8040188c37451168L,0x7ee8aa8ad967dce6L, + 0xfa0e79e73abc9299L } }, + /* 13 << 56 */ + { { 0x67332cfc2064cfd1L,0x339c31deb0651934L,0x719b28d52a3bcbeaL, + 0xee74c82b9d6ae5c6L }, + { 0x0927d05ebaf28ee6L,0x82cecf2c9d719028L,0x0b0d353eddb30289L, + 0xfe4bb977fddb2e29L } }, + /* 14 << 56 */ + { { 0xbb5bb990640bfd9eL,0xd226e27782f62108L,0x4bf0098502ffdd56L, + 0x7756758a2ca1b1b5L }, + { 0xc32b62a35285fe91L,0xedbc546a8c9cd140L,0x1e47a013af5cb008L, + 0xbca7e720073ce8f2L } }, + /* 15 << 56 */ + { { 0xe10b2ab817a91caeL,0xb89aab6508e27f63L,0x7b3074a7dba3ddf9L, + 0x1c20ce09330c2972L }, + { 0x6b9917b45fcf7e33L,0xe6793743945ceb42L,0x18fc22155c633d19L, + 0xad1adb3cc7485474L } }, + /* 16 << 56 */ + { { 0x646f96796424c49bL,0xf888dfe867c241c9L,0xe12d4b9324f68b49L, + 0x9a6b62d8a571df20L }, + { 0x81b4b26d179483cbL,0x666f96329511fae2L,0xd281b3e4d53aa51fL, + 0x7f96a7657f3dbd16L } }, + /* 17 << 56 */ + { { 0xa7f8b5bf074a30ceL,0xd7f52107005a32e6L,0x6f9e090750237ed4L, + 0x2f21da478096fa2bL }, + { 0xf3e19cb4eec863a0L,0xd18f77fd9527620aL,0x9505c81c407c1cf8L, + 0x9998db4e1b6ec284L } }, + /* 18 << 56 */ + { { 0x7e3389e5c247d44dL,0x125071413f4f3d80L,0xd4ba01104a78a6c7L, + 0x312874a0767720beL }, + { 0xded059a675944370L,0xd6123d903b2c0bddL,0xa56b717b51c108e3L, + 0x9bb7940e070623e9L } }, + /* 19 << 56 */ + { { 0x794e2d5984ac066cL,0xf5954a92e68c69a0L,0x28c524584fd99dccL, + 0x60e639fcb1012517L }, + { 0xc2e601257de79248L,0xe9ef6404f12fc6d7L,0x4c4f28082a3b5d32L, + 0x865ad32ec768eb8aL } }, + /* 20 << 56 */ + { { 0xac02331b13fb70b6L,0x037b44c195599b27L,0x1a860fc460bd082cL, + 0xa2e25745c980cd01L }, + { 0xee3387a81da0263eL,0x931bfb952d10f3d6L,0x5b687270a1f24a32L, + 0xf140e65dca494b86L } }, + /* 21 << 56 */ + { { 0x4f4ddf91b2f1ac7aL,0xf99eaabb760fee27L,0x57f4008a49c228e5L, + 0x090be4401cf713bbL }, + { 0xac91fbe45004f022L,0xd838c2c2569e1af6L,0xd6c7d20b0f1daaa5L, + 0xaa063ac11bbb02c0L } }, + /* 22 << 56 */ + { { 0x0938a42259558a78L,0x5343c6698435da2fL,0x96f67b18034410dcL, + 0x7cc1e42484510804L }, + { 0x86a1543f16dfbb7dL,0x921fa9425b5bd592L,0x9dcccb6eb33dd03cL, + 0x8581ddd9b843f51eL } }, + /* 23 << 56 */ + { { 0x54935fcb81d73c9eL,0x6d07e9790a5e97abL,0x4dc7b30acf3a6babL, + 0x147ab1f3170bee11L }, + { 0x0aaf8e3d9fafdee4L,0xfab3dbcb538a8b95L,0x405df4b36ef13871L, + 0xf1f4e9cb088d5a49L } }, + /* 24 << 56 */ + { { 0x9bcd24d366b33f1dL,0x3b97b8205ce445c0L,0xe2926549ba93ff61L, + 0xd9c341ce4dafe616L }, + { 0xfb30a76e16efb6f3L,0xdf24b8ca605b953cL,0x8bd52afec2fffb9fL, + 0xbbac5ff7e19d0b96L } }, + /* 25 << 56 */ + { { 0x43c01b87459afccdL,0x6bd45143b7432652L,0x8473453055b5d78eL, + 0x81088fdb1554ba7dL }, + { 0xada0a52c1e269375L,0xf9f037c42dc5ec10L,0xc066060794bfbc11L, + 0xc0a630bbc9c40d2fL } }, + /* 26 << 56 */ + { { 0x5efc797eab64c31eL,0xffdb1dab74507144L,0xf61242871ca6790cL, + 0xe9609d81e69bf1bfL }, + { 0xdb89859500d24fc9L,0x9c750333e51fb417L,0x51830a91fef7bbdeL, + 0x0ce67dc8945f585cL } }, + /* 27 << 56 */ + { { 0x9a730ed44763eb50L,0x24a0e221c1ab0d66L,0x643b6393648748f3L, + 0x1982daa16d3c6291L }, + { 0x6f00a9f78bbc5549L,0x7a1783e17f36384eL,0xe8346323de977f50L, + 0x91ab688db245502aL } }, + /* 28 << 56 */ + { { 0x331ab6b56d0bdd66L,0x0a6ef32e64b71229L,0x1028150efe7c352fL, + 0x27e04350ce7b39d3L }, + { 0x2a3c8acdc1070c82L,0xfb2034d380c9feefL,0x2d729621709f3729L, + 0x8df290bf62cb4549L } }, + /* 29 << 56 */ + { { 0x02f99f33fc2e4326L,0x3b30076d5eddf032L,0xbb21f8cf0c652fb5L, + 0x314fb49eed91cf7bL }, + { 0xa013eca52f700750L,0x2b9e3c23712a4575L,0xe5355557af30fbb0L, + 0x1ada35167c77e771L } }, + /* 30 << 56 */ + { { 0x45f6ecb27b135670L,0xe85d19df7cfc202eL,0x0f1b50c758d1be9fL, + 0x5ebf2c0aead2e344L }, + { 0x1531fe4eabc199c9L,0xc703259256bab0aeL,0x16ab2e486c1fec54L, + 0x0f87fda804280188L } }, + /* 31 << 56 */ + { { 0xdc9f46fc609e4a74L,0x2a44a143ba667f91L,0xbc3d8b95b4d83436L, + 0xa01e4bd0c7bd2958L }, + { 0x7b18293273483c90L,0xa79c6aa1a7c7b598L,0xbf3983c6eaaac07eL, + 0x8f18181e96e0d4e6L } }, + /* 32 << 56 */ + { { 0x8553d37c051af62bL,0xe9a998eb0bf94496L,0xe0844f9fb0d59aa1L, + 0x983fd558e6afb813L }, + { 0x9670c0ca65d69804L,0x732b22de6ea5ff2dL,0xd7640ba95fd8623bL, + 0x9f619163a6351782L } }, + /* 33 << 56 */ + { { 0x0bfc27eeacee5043L,0xae419e732eb10f02L,0x19c028d18943fb05L, + 0x71f01cf7ff13aa2aL }, + { 0x7790737e8887a132L,0x6751330966318410L,0x9819e8a37ddb795eL, + 0xfecb8ef5dad100b2L } }, + /* 34 << 56 */ + { { 0x59f74a223021926aL,0xb7c28a496f9b4c1cL,0xed1a733f912ad0abL, + 0x42a910af01a5659cL }, + { 0x3842c6e07bd68cabL,0x2b57fa3876d70ac8L,0x8a6707a83c53aaebL, + 0x62c1c51065b4db18L } }, + /* 35 << 56 */ + { { 0x8de2c1fbb2d09dc7L,0xc3dfed12266bd23bL,0x927d039bd5b27db6L, + 0x2fb2f0f1103243daL }, + { 0xf855a07b80be7399L,0xed9327ce1f9f27a8L,0xa0bd99c7729bdef7L, + 0x2b67125e28250d88L } }, + /* 36 << 56 */ + { { 0x784b26e88670ced7L,0xe3dfe41fc31bd3b4L,0x9e353a06bcc85cbcL, + 0x302e290960178a9dL }, + { 0x860abf11a6eac16eL,0x76447000aa2b3aacL,0x46ff9d19850afdabL, + 0x35bdd6a5fdb2d4c1L } }, + /* 37 << 56 */ + { { 0xe82594b07e5c9ce9L,0x0f379e5320af346eL,0x608b31e3bc65ad4aL, + 0x710c6b12267c4826L }, + { 0x51c966f971954cf1L,0xb1cec7930d0aa215L,0x1f15598986bd23a8L, + 0xae2ff99cf9452e86L } }, + /* 38 << 56 */ + { { 0xd8dd953c340ceaa2L,0x263552752e2e9333L,0x15d4e5f98586f06dL, + 0xd6bf94a8f7cab546L }, + { 0x33c59a0ab76a9af0L,0x52740ab3ba095af7L,0xc444de8a24389ca0L, + 0xcc6f9863706da0cbL } }, + /* 39 << 56 */ + { { 0xb5a741a76b2515cfL,0x71c416019585c749L,0x78350d4fe683de97L, + 0x31d6152463d0b5f5L }, + { 0x7a0cc5e1fbce090bL,0xaac927edfbcb2a5bL,0xe920de4920d84c35L, + 0x8c06a0b622b4de26L } }, + /* 40 << 56 */ + { { 0xd34dd58bafe7ddf3L,0x55851fedc1e6e55bL,0xd1395616960696e7L, + 0x940304b25f22705fL }, + { 0x6f43f861b0a2a860L,0xcf1212820e7cc981L,0x121862120ab64a96L, + 0x09215b9ab789383cL } }, + /* 41 << 56 */ + { { 0x311eb30537387c09L,0xc5832fcef03ee760L,0x30358f5832f7ea19L, + 0xe01d3c3491d53551L }, + { 0x1ca5ee41da48ea80L,0x34e71e8ecf4fa4c1L,0x312abd257af1e1c7L, + 0xe3afcdeb2153f4a5L } }, + /* 42 << 56 */ + { { 0x9d5c84d700235e9aL,0x0308d3f48c4c836fL,0xc0a66b0489332de5L, + 0x610dd39989e566efL }, + { 0xf8eea460d1ac1635L,0x84cbb3fb20a2c0dfL,0x40afb488e74a48c5L, + 0x29738198d326b150L } }, + /* 43 << 56 */ + { { 0x2a17747fa6d74081L,0x60ea4c0555a26214L,0x53514bb41f88c5feL, + 0xedd645677e83426cL }, + { 0xd5d6cbec96460b25L,0xa12fd0ce68dc115eL,0xc5bc3ed2697840eaL, + 0x969876a8a6331e31L } }, + /* 44 << 56 */ + { { 0x60c36217472ff580L,0xf42297054ad41393L,0x4bd99ef0a03b8b92L, + 0x501c7317c144f4f6L }, + { 0x159009b318464945L,0x6d5e594c74c5c6beL,0x2d587011321a3660L, + 0xd1e184b13898d022L } }, + /* 45 << 56 */ + { { 0x5ba047524c6a7e04L,0x47fa1e2b45550b65L,0x9419daf048c0a9a5L, + 0x663629537c243236L }, + { 0xcd0744b15cb12a88L,0x561b6f9a2b646188L,0x599415a566c2c0c0L, + 0xbe3f08590f83f09aL } }, + /* 46 << 56 */ + { { 0x9141c5beb92041b8L,0x01ae38c726477d0dL,0xca8b71f3d12c7a94L, + 0xfab5b31f765c70dbL }, + { 0x76ae7492487443e9L,0x8595a310990d1349L,0xf8dbeda87d460a37L, + 0x7f7ad0821e45a38fL } }, + /* 47 << 56 */ + { { 0xed1d4db61059705aL,0xa3dd492ae6b9c697L,0x4b92ee3a6eb38bd5L, + 0xbab2609d67cc0bb7L }, + { 0x7fc4fe896e70ee82L,0xeff2c56e13e6b7e3L,0x9b18959e34d26fcaL, + 0x2517ab66889d6b45L } }, + /* 48 << 56 */ + { { 0xf167b4e0bdefdd4fL,0x69958465f366e401L,0x5aa368aba73bbec0L, + 0x121487097b240c21L }, + { 0x378c323318969006L,0xcb4d73cee1fe53d1L,0x5f50a80e130c4361L, + 0xd67f59517ef5212bL } }, + /* 49 << 56 */ + { { 0xf145e21e9e70c72eL,0xb2e52e295566d2fbL,0x44eaba4a032397f5L, + 0x5e56937b7e31a7deL }, + { 0x68dcf517456c61e1L,0xbc2e954aa8b0a388L,0xe3552fa760a8b755L, + 0x03442dae73ad0cdeL } }, + /* 50 << 56 */ + { { 0x37ffe747ceb26210L,0x983545e8787baef9L,0x8b8c853586a3de31L, + 0xc621dbcbfacd46dbL }, + { 0x82e442e959266fbbL,0xa3514c37339d471cL,0x3a11b77162cdad96L, + 0xf0cb3b3cecf9bdf0L } }, + /* 51 << 56 */ + { { 0x3fcbdbce478e2135L,0x7547b5cfbda35342L,0xa97e81f18a677af6L, + 0xc8c2bf8328817987L }, + { 0xdf07eaaf45580985L,0xc68d1f05c93b45cbL,0x106aa2fec77b4cacL, + 0x4c1d8afc04a7ae86L } }, + /* 52 << 56 */ + { { 0xdb41c3fd9eb45ab2L,0x5b234b5bd4b22e74L,0xda253decf215958aL, + 0x67e0606ea04edfa0L }, + { 0xabbbf070ef751b11L,0xf352f175f6f06dceL,0xdfc4b6af6839f6b4L, + 0x53ddf9a89959848eL } }, + /* 53 << 56 */ + { { 0xda49c379c21520b0L,0x90864ff0dbd5d1b6L,0x2f055d235f49c7f7L, + 0xe51e4e6aa796b2d8L }, + { 0xc361a67f5c9dc340L,0x5ad53c37bca7c620L,0xda1d658832c756d0L, + 0xad60d9118bb67e13L } }, + /* 54 << 56 */ + { { 0xd6c47bdf0eeec8c6L,0x4a27fec1078a1821L,0x081f7415c3099524L, + 0x8effdf0b82cd8060L }, + { 0xdb70ec1c65842df8L,0x8821b358d319a901L,0x72ee56eede42b529L, + 0x5bb39592236e4286L } }, + /* 55 << 56 */ + { { 0xd1183316fd6f7140L,0xf9fadb5bbd8e81f7L,0x701d5e0c5a02d962L, + 0xfdee4dbf1b601324L }, + { 0xbed1740735d7620eL,0x04e3c2c3f48c0012L,0x9ee29da73455449aL, + 0x562cdef491a836c4L } }, + /* 56 << 56 */ + { { 0x8f682a5f47701097L,0x617125d8ff88d0c2L,0x948fda2457bb86ddL, + 0x348abb8f289f7286L }, + { 0xeb10eab599d94bbdL,0xd51ba28e4684d160L,0xabe0e51c30c8f41aL, + 0x66588b4513254f4aL } }, + /* 57 << 56 */ + { { 0x147ebf01fad097a5L,0x49883ea8610e815dL,0xe44d60ba8a11de56L, + 0xa970de6e827a7a6dL }, + { 0x2be414245e17fc19L,0xd833c65701214057L,0x1375813b363e723fL, + 0x6820bb88e6a52e9bL } }, + /* 58 << 56 */ + { { 0x7e7f6970d875d56aL,0xd6a0a9ac51fbf6bfL,0x54ba8790a3083c12L, + 0xebaeb23d6ae7eb64L }, + { 0xa8685c3ab99a907aL,0xf1e74550026bf40bL,0x7b73a027c802cd9eL, + 0x9a8a927c4fef4635L } }, + /* 59 << 56 */ + { { 0xe1b6f60c08191224L,0xc4126ebbde4ec091L,0xe1dff4dc4ae38d84L, + 0xde3f57db4f2ef985L }, + { 0x34964337d446a1ddL,0x7bf217a0859e77f6L,0x8ff105278e1d13f5L, + 0xa304ef0374eeae27L } }, + /* 60 << 56 */ + { { 0xfc6f5e47d19dfa5aL,0xdb007de37fad982bL,0x28205ad1613715f5L, + 0x251e67297889529eL }, + { 0x727051841ae98e78L,0xf818537d271cac32L,0xc8a15b7eb7f410f5L, + 0xc474356f81f62393L } }, + /* 61 << 56 */ + { { 0x92dbdc5ac242316bL,0xabe060acdbf4aff5L,0x6e8c38fe909a8ec6L, + 0x43e514e56116cb94L }, + { 0x2078fa3807d784f9L,0x1161a880f4b5b357L,0x5283ce7913adea3dL, + 0x0756c3e6cc6a910bL } }, + /* 62 << 56 */ + { { 0x60bcfe01aaa79697L,0x04a73b2956391db1L,0xdd8dad47189b45a0L, + 0xbfac0dd048d5b8d9L }, + { 0x34ab3af57d3d2ec2L,0x6fa2fc2d207bd3afL,0x9ff4009266550dedL, + 0x719b3e871fd5b913L } }, + /* 63 << 56 */ + { { 0xa573a4966d17fbc7L,0x0cd1a70a73d2b24eL,0x34e2c5cab2676937L, + 0xe7050b06bf669f21L }, + { 0xfbe948b61ede9046L,0xa053005197662659L,0x58cbd4edf10124c5L, + 0xde2646e4dd6c06c8L } }, + /* 64 << 56 */ + { { 0x332f81088cad38c0L,0x471b7e906bd68ae2L,0x56ac3fb20d8e27a3L, + 0xb54660db136b4b0dL }, + { 0x123a1e11a6fd8de4L,0x44dbffeaa37799efL,0x4540b977ce6ac17cL, + 0x495173a8af60acefL } }, + /* 0 << 63 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 63 */ + { { 0x9ebb284d391c2a82L,0xbcdd4863158308e8L,0x006f16ec83f1edcaL, + 0xa13e2c37695dc6c8L }, + { 0x2ab756f04a057a87L,0xa8765500a6b48f98L,0x4252face68651c44L, + 0xa52b540be1765e02L } }, + /* 2 << 63 */ + { { 0x4f922fc516a0d2bbL,0x0d5cc16c1a623499L,0x9241cf3a57c62c8bL, + 0x2f5e6961fd1b667fL }, + { 0x5c15c70bf5a01797L,0x3d20b44d60956192L,0x04911b37071fdb52L, + 0xf648f9168d6f0f7bL } }, + /* 3 << 63 */ + { { 0x6dc1acafe60b7cf7L,0x25860a5084a9d869L,0x56fc6f09e7ba8ac4L, + 0x828c5bd06148d29eL }, + { 0xac6b435edc55ae5fL,0xa527f56cc0117411L,0x94d5045efd24342cL, + 0x2c4c0a3570b67c0dL } }, + /* 4 << 63 */ + { { 0x027cc8b8fac61d9aL,0x7d25e062e3c6fe8aL,0xe08805bfe5bff503L, + 0x13271e6c6ff632f7L }, + { 0x55dca6c0232f76a5L,0x8957c32d701ef426L,0xee728bcba10a5178L, + 0x5ea60411b62c5173L } }, + /* 5 << 63 */ + { { 0xfc4e964ed0b8892bL,0x9ea176839301bb74L,0x6265c5aefcc48626L, + 0xe60cf82ebb3e9102L }, + { 0x57adf797d4df5531L,0x235b59a18deeefe2L,0x60adcf583f306eb1L, + 0x105c27533d09492dL } }, + /* 6 << 63 */ + { { 0x4090914bb5def996L,0x1cb69c83233dd1e7L,0xc1e9c1d39b3d5e76L, + 0x1f3338edfccf6012L }, + { 0xb1e95d0d2f5378a8L,0xacf4c2c72f00cd21L,0x6e984240eb5fe290L, + 0xd66c038d248088aeL } }, + /* 7 << 63 */ + { { 0x804d264af94d70cfL,0xbdb802ef7314bf7eL,0x8fb54de24333ed02L, + 0x740461e0285635d9L }, + { 0x4113b2c8365e9383L,0xea762c833fdef652L,0x4eec6e2e47b956c1L, + 0xa3d814be65620fa4L } }, + /* 8 << 63 */ + { { 0x9ad5462bb4d8bc50L,0x181c0b16a9195770L,0xebd4fe1c78412a68L, + 0xae0341bcc0dff48cL }, + { 0xb6bc45cf7003e866L,0xf11a6dea8a24a41bL,0x5407151ad04c24c2L, + 0x62c9d27dda5b7b68L } }, + /* 9 << 63 */ + { { 0x2e96423588cceff6L,0x8594c54f8b07ed69L,0x1578e73cc84d0d0dL, + 0x7b4e1055ff532868L }, + { 0xa348c0d5b5ec995aL,0xbf4b9d5514289a54L,0x9ba155a658fbd777L, + 0x186ed7a81a84491dL } }, + /* 10 << 63 */ + { { 0xd4992b30614c0900L,0xda98d121bd00c24bL,0x7f534dc87ec4bfa1L, + 0x4a5ff67437dc34bcL }, + { 0x68c196b81d7ea1d7L,0x38cf289380a6d208L,0xfd56cd09e3cbbd6eL, + 0xec72e27e4205a5b6L } }, + /* 11 << 63 */ + { { 0x15ea68f5a44f77f7L,0x7aa5f9fdb43c52bcL,0x86ff676f94f0e609L, + 0xa4cde9632e2d432bL }, + { 0x8cafa0c0eee470afL,0x84137d0e8a3f5ec8L,0xebb40411faa31231L, + 0xa239c13f6f7f7ccfL } }, + /* 12 << 63 */ + { { 0x32865719a8afd30bL,0x867983288a826dceL,0xdf04e891c4a8fbe0L, + 0xbb6b6e1bebf56ad3L }, + { 0x0a695b11471f1ff0L,0xd76c3389be15baf0L,0x018edb95be96c43eL, + 0xf2beaaf490794158L } }, + /* 13 << 63 */ + { { 0x152db09ec3076a27L,0x5e82908ee416545dL,0xa2c41272356d6f2eL, + 0xdc9c964231fd74e1L }, + { 0x66ceb88d519bf615L,0xe29ecd7605a2274eL,0x3a0473c4bf5e2fa0L, + 0x6b6eb67164284e67L } }, + /* 14 << 63 */ + { { 0xe8b97932b88756ddL,0xed4e8652f17e3e61L,0xc2dd14993ee1c4a4L, + 0xc0aaee17597f8c0eL }, + { 0x15c4edb96c168af3L,0x6563c7bfb39ae875L,0xadfadb6f20adb436L, + 0xad55e8c99a042ac0L } }, + /* 15 << 63 */ + { { 0x975a1ed8b76da1f5L,0x10dfa466a58acb94L,0x8dd7f7e3ac060282L, + 0x6813e66a572a051eL }, + { 0xb4ccae1e350cb901L,0xb653d65650cb7822L,0x42484710dfab3b87L, + 0xcd7ee5379b670fd0L } }, + /* 16 << 63 */ + { { 0x0a50b12e523b8bf6L,0x8009eb5b8f910c1bL,0xf535af824a167588L, + 0x0f835f9cfb2a2abdL }, + { 0xf59b29312afceb62L,0xc797df2a169d383fL,0xeb3f5fb066ac02b0L, + 0x029d4c6fdaa2d0caL } }, + /* 17 << 63 */ + { { 0xd4059bc1afab4bc5L,0x833f5c6f56783247L,0xb53466308d2d3605L, + 0x83387891d34d8433L }, + { 0xd973b30fadd9419aL,0xbcca1099afe3fce8L,0x081783150809aac6L, + 0x01b7f21a540f0f11L } }, + /* 18 << 63 */ + { { 0x65c29219909523c8L,0xa62f648fa3a1c741L,0x88598d4f60c9e55aL, + 0xbce9141b0e4f347aL }, + { 0x9af97d8435f9b988L,0x0210da62320475b6L,0x3c076e229191476cL, + 0x7520dbd944fc7834L } }, + /* 19 << 63 */ + { { 0x6a6b2cfec1ab1bbdL,0xef8a65bedc650938L,0x72855540805d7bc4L, + 0xda389396ed11fdfdL }, + { 0xa9d5bd3674660876L,0x11d67c54b45dff35L,0x6af7d148a4f5da94L, + 0xbb8d4c3fc0bbeb31L } }, + /* 20 << 63 */ + { { 0x87a7ebd1e0a1b12aL,0x1e4ef88d770ba95fL,0x8c33345cdc2ae9cbL, + 0xcecf127601cc8403L }, + { 0x687c012e1b39b80fL,0xfd90d0ad35c33ba4L,0xa3ef5a675c9661c2L, + 0x368fc88ee017429eL } }, + /* 21 << 63 */ + { { 0xd30c6761196a2fa2L,0x931b9817bd5b312eL,0xba01000c72f54a31L, + 0xa203d2c866eaa541L }, + { 0xf2abdee098939db3L,0xe37d6c2c3e606c02L,0xf2921574521ff643L, + 0x2781b3c4d7e2fca3L } }, + /* 22 << 63 */ + { { 0x664300b07850ec06L,0xac5a38b97d3a10cfL,0x9233188de34ab39dL, + 0xe77057e45072cbb9L }, + { 0xbcf0c042b59e78dfL,0x4cfc91e81d97de52L,0x4661a26c3ee0ca4aL, + 0x5620a4c1fb8507bcL } }, + /* 23 << 63 */ + { { 0x4b44d4aa049f842cL,0xceabc5d51540e82bL,0x306710fd15c6f156L, + 0xbe5ae52b63db1d72L }, + { 0x06f1e7e6334957f1L,0x57e388f031144a70L,0xfb69bb2fdf96447bL, + 0x0f78ebd373e38a12L } }, + /* 24 << 63 */ + { { 0xb82226052b7ce542L,0xe6d4ce997472bde1L,0x53e16ebe09d2f4daL, + 0x180ff42e53b92b2eL }, + { 0xc59bcc022c34a1c6L,0x3803d6f9422c46c2L,0x18aff74f5c14a8a2L, + 0x55aebf8010a08b28L } }, + /* 25 << 63 */ + { { 0x66097d587135593fL,0x32e6eff72be570cdL,0x584e6a102a8c860dL, + 0xcd185890a2eb4163L }, + { 0x7ceae99d6d97e134L,0xd42c6b70dd8447ceL,0x59ddbb4ab8c50273L, + 0x03c612df3cf34e1eL } }, + /* 26 << 63 */ + { { 0x84b9ca1504b6c5a0L,0x35216f3918f0e3a3L,0x3ec2d2bcbd986c00L, + 0x8bf546d9d19228feL }, + { 0xd1c655a44cd623c3L,0x366ce718502b8e5aL,0x2cfc84b4eea0bfe7L, + 0xe01d5ceecf443e8eL } }, + /* 27 << 63 */ + { { 0x8ec045d9036520f8L,0xdfb3c3d192d40e98L,0x0bac4ccecc559a04L, + 0x35eccae5240ea6b1L }, + { 0x180b32dbf8a5a0acL,0x547972a5eb699700L,0xa3765801ca26bca0L, + 0x57e09d0ea647f25aL } }, + /* 28 << 63 */ + { { 0xb956970e2fdd23ccL,0xb80288bc5682e971L,0xe6e6d91e9ae86ebcL, + 0x0564c83f8c9f1939L }, + { 0x551932a239560368L,0xe893752b049c28e2L,0x0b03cee5a6a158c3L, + 0xe12d656b04964263L } }, + /* 29 << 63 */ + { { 0x4b47554e63e3bc1dL,0xc719b6a245044ff7L,0x4f24d30ae48daa07L, + 0xa3f37556c8c1edc3L }, + { 0x9a47bf760700d360L,0xbb1a1824822ae4e2L,0x22e275a389f1fb4cL, + 0x72b1aa239968c5f5L } }, + /* 30 << 63 */ + { { 0xa75feacabe063f64L,0x9b392f43bce47a09L,0xd42415091ad07acaL, + 0x4b0c591b8d26cd0fL }, + { 0x2d42ddfd92f1169aL,0x63aeb1ac4cbf2392L,0x1de9e8770691a2afL, + 0xebe79af7d98021daL } }, + /* 31 << 63 */ + { { 0xcfdf2a4e40e50acfL,0xf0a98ad7af01d665L,0xefb640bf1831be1fL, + 0x6fe8bd2f80e9ada0L }, + { 0x94c103a16cafbc91L,0x170f87598308e08cL,0x5de2d2ab9780ff4fL, + 0x666466bc45b201f2L } }, + /* 32 << 63 */ + { { 0x58af2010f5b343bcL,0x0f2e400af2f142feL,0x3483bfdea85f4bdfL, + 0xf0b1d09303bfeaa9L }, + { 0x2ea01b95c7081603L,0xe943e4c93dba1097L,0x47be92adb438f3a6L, + 0x00bb7742e5bf6636L } }, + /* 33 << 63 */ + { { 0x136b7083824297b4L,0x9d0e55805584455fL,0xab48cedcf1c7d69eL, + 0x53a9e4812a256e76L }, + { 0x0402b0e065eb2413L,0xdadbbb848fc407a7L,0xa65cd5a48d7f5492L, + 0x21d4429374bae294L } }, + /* 34 << 63 */ + { { 0x66917ce63b5f1cc4L,0x37ae52eace872e62L,0xbb087b722905f244L, + 0x120770861e6af74fL }, + { 0x4b644e491058edeaL,0x827510e3b638ca1dL,0x8cf2b7046038591cL, + 0xffc8b47afe635063L } }, + /* 35 << 63 */ + { { 0x3ae220e61b4d5e63L,0xbd8647429d961b4bL,0x610c107e9bd16bedL, + 0x4270352a1127147bL }, + { 0x7d17ffe664cfc50eL,0x50dee01a1e36cb42L,0x068a762235dc5f9aL, + 0x9a08d536df53f62cL } }, + /* 36 << 63 */ + { { 0x4ed714576be5f7deL,0xd93006f8c2263c9eL,0xe073694ccacacb36L, + 0x2ff7a5b43ae118abL }, + { 0x3cce53f1cd871236L,0xf156a39dc2aa6d52L,0x9cc5f271b198d76dL, + 0xbc615b6f81383d39L } }, + /* 37 << 63 */ + { { 0xa54538e8de3eee6bL,0x58c77538ab910d91L,0x31e5bdbc58d278bdL, + 0x3cde4adfb963acaeL }, + { 0xb1881fd25302169cL,0x8ca60fa0a989ed8bL,0xa1999458ff96a0eeL, + 0xc1141f03ac6c283dL } }, + /* 38 << 63 */ + { { 0x7677408d6dfafed3L,0x33a0165339661588L,0x3c9c15ec0b726fa0L, + 0x090cfd936c9b56daL }, + { 0xe34f4baea3c40af5L,0x3469eadbd21129f1L,0xcc51674a1e207ce8L, + 0x1e293b24c83b1ef9L } }, + /* 39 << 63 */ + { { 0x17173d131e6c0bb4L,0x1900469590776d35L,0xe7980e346de6f922L, + 0x873554cbf4dd9a22L }, + { 0x0316c627cbf18a51L,0x4d93651b3032c081L,0x207f27713946834dL, + 0x2c08d7b430cdbf80L } }, + /* 40 << 63 */ + { { 0x137a4fb486df2a61L,0xa1ed9c07ecf7b4a2L,0xb2e460e27bd042ffL, + 0xb7f5e2fa5f62f5ecL }, + { 0x7aa6ec6bcc2423b7L,0x75ce0a7fba63eea7L,0x67a45fb1f250a6e1L, + 0x93bc919ce53cdc9fL } }, + /* 41 << 63 */ + { { 0x9271f56f871942dfL,0x2372ff6f7859ad66L,0x5f4c2b9633cb1a78L, + 0xe3e291015838aa83L }, + { 0xa7ed1611e4e8110cL,0x2a2d70d5330198ceL,0xbdf132e86720efe0L, + 0xe61a896266a471bfL } }, + /* 42 << 63 */ + { { 0x796d3a85825808bdL,0x51dc3cb73fd6e902L,0x643c768a916219d1L, + 0x36cd7685a2ad7d32L }, + { 0xe3db9d05b22922a4L,0x6494c87edba29660L,0xf0ac91dfbcd2ebc7L, + 0x4deb57a045107f8dL } }, + /* 43 << 63 */ + { { 0x42271f59c3d12a73L,0x5f71687ca5c2c51dL,0xcb1f50c605797bcbL, + 0x29ed0ed9d6d34eb0L }, + { 0xe5fe5b474683c2ebL,0x4956eeb597447c46L,0x5b163a4371207167L, + 0x93fa2fed0248c5efL } }, + /* 44 << 63 */ + { { 0x67930af231f63950L,0xa77797c114caa2c9L,0x526e80ee27ac7e62L, + 0xe1e6e62658b28aecL }, + { 0x636178b0b3c9fef0L,0xaf7752e06d5f90beL,0x94ecaf18eece51cfL, + 0x2864d0edca806e1fL } }, + /* 45 << 63 */ + { { 0x6de2e38397c69134L,0x5a42c316eb291293L,0xc77792196a60bae0L, + 0xa24de3466b7599d1L }, + { 0x49d374aab75d4941L,0x989005862d501ff0L,0x9f16d40eeb7974cfL, + 0x1033860bcdd8c115L } }, + /* 46 << 63 */ + { { 0xb6c69ac82094cec3L,0x9976fb88403b770cL,0x1dea026c4859590dL, + 0xb6acbb468562d1fdL }, + { 0x7cd6c46144569d85L,0xc3190a3697f0891dL,0xc6f5319548d5a17dL, + 0x7d919966d749abc8L } }, + /* 47 << 63 */ + { { 0x65104837dd1c8a20L,0x7e5410c82f683419L,0x958c3ca8be94022eL, + 0x605c31976145dac2L }, + { 0x3fc0750101683d54L,0x1d7127c5595b1234L,0x10b8f87c9481277fL, + 0x677db2a8e65a1adbL } }, + /* 48 << 63 */ + { { 0xec2fccaaddce3345L,0x2a6811b7012a4350L,0x96760ff1ac598bdcL, + 0x054d652ad1bf4128L }, + { 0x0a1151d492a21005L,0xad7f397133110fdfL,0x8c95928c1960100fL, + 0x6c91c8257bf03362L } }, + /* 49 << 63 */ + { { 0xc8c8b2a2ce309f06L,0xfdb27b59ca27204bL,0xd223eaa50848e32eL, + 0xb93e4b2ee7bfaf1eL }, + { 0xc5308ae644aa3dedL,0x317a666ac015d573L,0xc888ce231a979707L, + 0xf141c1e60d5c4958L } }, + /* 50 << 63 */ + { { 0xb53b7de561906373L,0x858dbadeeb999595L,0x8cbb47b2a59e5c36L, + 0x660318b3dcf4e842L }, + { 0xbd161ccd12ba4b7aL,0xf399daabf8c8282aL,0x1587633aeeb2130dL, + 0xa465311ada38dd7dL } }, + /* 51 << 63 */ + { { 0x5f75eec864d3779bL,0x3c5d0476ad64c171L,0x874103712a914428L, + 0x8096a89190e2fc29L }, + { 0xd3d2ae9d23b3ebc2L,0x90bdd6dba580cfd6L,0x52dbb7f3c5b01f6cL, + 0xe68eded4e102a2dcL } }, + /* 52 << 63 */ + { { 0x17785b7799eb6df0L,0x26c3cc517386b779L,0x345ed9886417a48eL, + 0xe990b4e407d6ef31L }, + { 0x0f456b7e2586abbaL,0x239ca6a559c96e9aL,0xe327459ce2eb4206L, + 0x3a4c3313a002b90aL } }, + /* 53 << 63 */ + { { 0x2a114806f6a3f6fbL,0xad5cad2f85c251ddL,0x92c1f613f5a784d3L, + 0xec7bfacf349766d5L }, + { 0x04b3cd333e23cb3bL,0x3979fe84c5a64b2dL,0x192e27207e589106L, + 0xa60c43d1a15b527fL } }, + /* 54 << 63 */ + { { 0x2dae9082be7cf3a6L,0xcc86ba92bc967274L,0xf28a2ce8aea0a8a9L, + 0x404ca6d96ee988b3L }, + { 0xfd7e9c5d005921b8L,0xf56297f144e79bf9L,0xa163b4600d75ddc2L, + 0x30b23616a1f2be87L } }, + /* 55 << 63 */ + { { 0x4b070d21bfe50e2bL,0x7ef8cfd0e1bfede1L,0xadba00112aac4ae0L, + 0x2a3e7d01b9ebd033L }, + { 0x995277ece38d9d1cL,0xb500249e9c5d2de3L,0x8912b820f13ca8c9L, + 0xc8798114877793afL } }, + /* 56 << 63 */ + { { 0x19e6125dec3f1decL,0x07b1f040911178daL,0xd93ededa904a6738L, + 0x55187a5a0bebedcdL }, + { 0xf7d04722eb329d41L,0xf449099ef170b391L,0xfd317a69ca99f828L, + 0x50c3db2b34a4976dL } }, + /* 57 << 63 */ + { { 0xe9ba77843757b392L,0x326caefdaa3ca05aL,0x78e5293bf1e593d4L, + 0x7842a9370d98fd13L }, + { 0xe694bf965f96b10dL,0x373a9df606a8cd05L,0x997d1e51e8f0c7fcL, + 0x1d01979063fd972eL } }, + /* 58 << 63 */ + { { 0x0064d8585499fb32L,0x7b67bad977a8aeb7L,0x1d3eb9772d08eec5L, + 0x5fc047a6cbabae1dL }, + { 0x0577d159e54a64bbL,0x8862201bc43497e4L,0xad6b4e282ce0608dL, + 0x8b687b7d0b167aacL } }, + /* 59 << 63 */ + { { 0x6ed4d3678b2ecfa9L,0x24dfe62da90c3c38L,0xa1862e103fe5c42bL, + 0x1ca73dcad5732a9fL }, + { 0x35f038b776bb87adL,0x674976abf242b81fL,0x4f2bde7eb0fd90cdL, + 0x6efc172ea7fdf092L } }, + /* 60 << 63 */ + { { 0x3806b69b92222f1fL,0x5a2459ca6cf7ae70L,0x6789f69ca85217eeL, + 0x5f232b5ee3dc85acL }, + { 0x660e3ec548e9e516L,0x124b4e473197eb31L,0x10a0cb13aafcca23L, + 0x7bd63ba48213224fL } }, + /* 61 << 63 */ + { { 0xaffad7cc290a7f4fL,0x6b409c9e0286b461L,0x58ab809fffa407afL, + 0xc3122eedc68ac073L }, + { 0x17bf9e504ef24d7eL,0x5d9297943e2a5811L,0x519bc86702902e01L, + 0x76bba5da39c8a851L } }, + /* 62 << 63 */ + { { 0xe9f9669cda94951eL,0x4b6af58d66b8d418L,0xfa32107417d426a4L, + 0xc78e66a99dde6027L }, + { 0x0516c0834a53b964L,0xfc659d38ff602330L,0x0ab55e5c58c5c897L, + 0x985099b2838bc5dfL } }, + /* 63 << 63 */ + { { 0x061d9efcc52fc238L,0x712b27286ac1da3fL,0xfb6581499283fe08L, + 0x4954ac94b8aaa2f7L }, + { 0x85c0ada47fb2e74fL,0xee8ba98eb89926b0L,0xe4f9d37d23d1af5bL, + 0x14ccdbf9ba9b015eL } }, + /* 64 << 63 */ + { { 0xb674481b7bfe7178L,0x4e1debae65405868L,0x061b2821c48c867dL, + 0x69c15b35513b30eaL }, + { 0x3b4a166636871088L,0xe5e29f5d1220b1ffL,0x4b82bb35233d9f4dL, + 0x4e07633318cdc675L } }, + /* 0 << 70 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 70 */ + { { 0x0d53f5c7a3e6fcedL,0xe8cbbdd5f45fbdebL,0xf85c01df13339a70L, + 0x0ff71880142ceb81L }, + { 0x4c4e8774bd70437aL,0x5fb32891ba0bda6aL,0x1cdbebd2f18bd26eL, + 0x2f9526f103a9d522L } }, + /* 2 << 70 */ + { { 0x40ce305192c4d684L,0x8b04d7257612efcdL,0xb9dcda366f9cae20L, + 0x0edc4d24f058856cL }, + { 0x64f2e6bf85427900L,0x3de81295dc09dfeaL,0xd41b4487379bf26cL, + 0x50b62c6d6df135a9L } }, + /* 3 << 70 */ + { { 0xd4f8e3b4c72dfe67L,0xc416b0f690e19fdfL,0x18b9098d4c13bd35L, + 0xac11118a15b8cb9eL }, + { 0xf598a318f0062841L,0xbfe0602f89f356f4L,0x7ae3637e30177a0cL, + 0x3409774761136537L } }, + /* 4 << 70 */ + { { 0x0db2fb5ed005832aL,0x5f5efd3b91042e4fL,0x8c4ffdc6ed70f8caL, + 0xe4645d0bb52da9ccL }, + { 0x9596f58bc9001d1fL,0x52c8f0bc4e117205L,0xfd4aa0d2e398a084L, + 0x815bfe3a104f49deL } }, + /* 5 << 70 */ + { { 0x97e5443f23885e5fL,0xf72f8f99e8433aabL,0xbd00b154e4d4e604L, + 0xd0b35e6ae5e173ffL }, + { 0x57b2a0489164722dL,0x3e3c665b88761ec8L,0x6bdd13973da83832L, + 0x3c8b1a1e73dafe3bL } }, + /* 6 << 70 */ + { { 0x4497ace654317cacL,0xbe600ab9521771b3L,0xb42e409eb0dfe8b8L, + 0x386a67d73942310fL }, + { 0x25548d8d4431cc28L,0xa7cff142985dc524L,0x4d60f5a193c4be32L, + 0x83ebd5c8d071c6e1L } }, + /* 7 << 70 */ + { { 0xba3a80a7b1fd2b0bL,0x9b3ad3965bec33e8L,0xb3868d6179743fb3L, + 0xcfd169fcfdb462faL }, + { 0xd3b499d79ce0a6afL,0x55dc1cf1e42d3ff8L,0x04fb9e6cc6c3e1b2L, + 0x47e6961d6f69a474L } }, + /* 8 << 70 */ + { { 0x54eb3acce548b37bL,0xb38e754284d40549L,0x8c3daa517b341b4fL, + 0x2f6928ec690bf7faL }, + { 0x0496b32386ce6c41L,0x01be1c5510adadcdL,0xc04e67e74bb5faf9L, + 0x3cbaf678e15c9985L } }, + /* 9 << 70 */ + { { 0x8cd1214550ca4247L,0xba1aa47ae7dd30aaL,0x2f81ddf1e58fee24L, + 0x03452936eec9b0e8L }, + { 0x8bdc3b81243aea96L,0x9a2919af15c3d0e5L,0x9ea640ec10948361L, + 0x5ac86d5b6e0bcccfL } }, + /* 10 << 70 */ + { { 0xf892d918c36cf440L,0xaed3e837c939719cL,0xb07b08d2c0218b64L, + 0x6f1bcbbace9790ddL }, + { 0x4a84d6ed60919b8eL,0xd89007918ac1f9ebL,0xf84941aa0dd5daefL, + 0xb22fe40a67fd62c5L } }, + /* 11 << 70 */ + { { 0x97e15ba2157f2db3L,0xbda2fc8f8e28ca9cL,0x5d050da437b9f454L, + 0x3d57eb572379d72eL }, + { 0xe9b5eba2fb5ee997L,0x01648ca2e11538caL,0x32bb76f6f6327974L, + 0x338f14b8ff3f4bb7L } }, + /* 12 << 70 */ + { { 0x524d226ad7ab9a2dL,0x9c00090d7dfae958L,0x0ba5f5398751d8c2L, + 0x8afcbcdd3ab8262dL }, + { 0x57392729e99d043bL,0xef51263baebc943aL,0x9feace9320862935L, + 0x639efc03b06c817bL } }, + /* 13 << 70 */ + { { 0x1fe054b366b4be7aL,0x3f25a9de84a37a1eL,0xf39ef1ad78d75cd9L, + 0xd7b58f495062c1b5L }, + { 0x6f74f9a9ff563436L,0xf718ff29e8af51e7L,0x5234d31315e97fecL, + 0xb6a8e2b1292f1c0aL } }, + /* 14 << 70 */ + { { 0xa7f53aa8327720c1L,0x956ca322ba092cc8L,0x8f03d64a28746c4dL, + 0x51fe178266d0d392L }, + { 0xd19b34db3c832c80L,0x60dccc5c6da2e3b4L,0x245dd62e0a104cccL, + 0xa7ab1de1620b21fdL } }, + /* 15 << 70 */ + { { 0xb293ae0b3893d123L,0xf7b75783b15ee71cL,0x5aa3c61442a9468bL, + 0xd686123cdb15d744L }, + { 0x8c616891a7ab4116L,0x6fcd72c8a4e6a459L,0xac21911077e5fad7L, + 0xfb6a20e7704fa46bL } }, + /* 16 << 70 */ + { { 0xe839be7d341d81dcL,0xcddb688932148379L,0xda6211a1f7026eadL, + 0xf3b2575ff4d1cc5eL }, + { 0x40cfc8f6a7a73ae6L,0x83879a5e61d5b483L,0xc5acb1ed41a50ebcL, + 0x59a60cc83c07d8faL } }, + /* 17 << 70 */ + { { 0x1b73bdceb1876262L,0x2b0d79f012af4ee9L,0x8bcf3b0bd46e1d07L, + 0x17d6af9de45d152fL }, + { 0x735204616d736451L,0x43cbbd9756b0bf5aL,0xb0833a5bd5999b9dL, + 0x702614f0eb72e398L } }, + /* 18 << 70 */ + { { 0x0aadf01a59c3e9f8L,0x40200e77ce6b3d16L,0xda22bdd3deddafadL, + 0x76dedaf4310d72e1L }, + { 0x49ef807c4bc2e88fL,0x6ba81291146dd5a5L,0xa1a4077a7d8d59e9L, + 0x87b6a2e7802db349L } }, + /* 19 << 70 */ + { { 0xd56799971b4e598eL,0xf499ef1f06fe4b1dL,0x3978d3aefcb267c5L, + 0xb582b557235786d0L }, + { 0x32b3b2ca1715cb07L,0x4c3de6a28480241dL,0x63b5ffedcb571ecdL, + 0xeaf53900ed2fe9a9L } }, + /* 20 << 70 */ + { { 0xdec98d4ac3b81990L,0x1cb837229e0cc8feL,0xfe0b0491d2b427b9L, + 0x0f2386ace983a66cL }, + { 0x930c4d1eb3291213L,0xa2f82b2e59a62ae4L,0x77233853f93e89e3L, + 0x7f8063ac11777c7fL } }, + /* 21 << 70 */ + { { 0xff0eb56759ad2877L,0x6f4546429865c754L,0xe6fe701a236e9a84L, + 0xc586ef1606e40fc3L }, + { 0x3f62b6e024bafad9L,0xc8b42bd264da906aL,0xc98e1eb4da3276a0L, + 0x30d0e5fc06cbf852L } }, + /* 22 << 70 */ + { { 0x1b6b2ae1e8b4dfd4L,0xd754d5c78301cbacL,0x66097629112a39acL, + 0xf86b599993ba4ab9L }, + { 0x26c9dea799f9d581L,0x0473b1a8c2fafeaaL,0x1469af553b2505a5L, + 0x227d16d7d6a43323L } }, + /* 23 << 70 */ + { { 0x3316f73cad3d97f9L,0x52bf3bb51f137455L,0x953eafeb09954e7cL, + 0xa721dfeddd732411L }, + { 0xb4929821141d4579L,0x3411321caa3bd435L,0xafb355aa17fa6015L, + 0xb4e7ef4a18e42f0eL } }, + /* 24 << 70 */ + { { 0x604ac97c59371000L,0xe1c48c707f759c18L,0x3f62ecc5a5db6b65L, + 0x0a78b17338a21495L }, + { 0x6be1819dbcc8ad94L,0x70dc04f6d89c3400L,0x462557b4a6b4840aL, + 0x544c6ade60bd21c0L } }, + /* 25 << 70 */ + { { 0x6a00f24e907a544bL,0xa7520dcb313da210L,0xfe939b7511e4994bL, + 0x918b6ba6bc275d70L }, + { 0xd3e5e0fc644be892L,0x707a9816fdaf6c42L,0x60145567f15c13feL, + 0x4818ebaae130a54aL } }, + /* 26 << 70 */ + { { 0x28aad3ad58d2f767L,0xdc5267fdd7e7c773L,0x4919cc88c3afcc98L, + 0xaa2e6ab02db8cd4bL }, + { 0xd46fec04d0c63eaaL,0xa1cb92c519ffa832L,0x678dd178e43a631fL, + 0xfb5ae1cd3dc788b3L } }, + /* 27 << 70 */ + { { 0x68b4fb906e77de04L,0x7992bcf0f06dbb97L,0x896e6a13c417c01dL, + 0x8d96332cb956be01L }, + { 0x902fc93a413aa2b9L,0x99a4d915fc98c8a5L,0x52c29407565f1137L, + 0x4072690f21e4f281L } }, + /* 28 << 70 */ + { { 0x36e607cf02ff6072L,0xa47d2ca98ad98cdcL,0xbf471d1ef5f56609L, + 0xbcf86623f264ada0L }, + { 0xb70c0687aa9e5cb6L,0xc98124f217401c6cL,0x8189635fd4a61435L, + 0xd28fb8afa9d98ea6L } }, + /* 29 << 70 */ + { { 0xb9a67c2a40c251f8L,0x88cd5d87a2da44beL,0x437deb96e09b5423L, + 0x150467db64287dc1L }, + { 0xe161debbcdabb839L,0xa79e9742f1839a3eL,0xbb8dd3c2652d202bL, + 0x7b3e67f7e9f97d96L } }, + /* 30 << 70 */ + { { 0x5aa5d78fb1cb6ac9L,0xffa13e8eca1d0d45L,0x369295dd2ba5bf95L, + 0xd68bd1f839aff05eL }, + { 0xaf0d86f926d783f2L,0x543a59b3fc3aafc1L,0x3fcf81d27b7da97cL, + 0xc990a056d25dee46L } }, + /* 31 << 70 */ + { { 0x3e6775b8519cce2cL,0xfc9af71fae13d863L,0x774a4a6f47c1605cL, + 0x46ba42452fd205e8L }, + { 0xa06feea4d3fd524dL,0x1e7246416de1acc2L,0xf53816f1334e2b42L, + 0x49e5918e922f0024L } }, + /* 32 << 70 */ + { { 0x439530b665c7322dL,0xcf12cc01b3c1b3fbL,0xc70b01860172f685L, + 0xb915ee221b58391dL }, + { 0x9afdf03ba317db24L,0x87dec65917b8ffc4L,0x7f46597be4d3d050L, + 0x80a1c1ed006500e7L } }, + /* 33 << 70 */ + { { 0x84902a9678bf030eL,0xfb5e9c9a50560148L,0x6dae0a9263362426L, + 0xdcaeecf4a9e30c40L }, + { 0xc0d887bb518d0c6bL,0x99181152cb985b9dL,0xad186898ef7bc381L, + 0x18168ffb9ee46201L } }, + /* 34 << 70 */ + { { 0x9a04cdaa2502753cL,0xbb279e2651407c41L,0xeacb03aaf23564e5L, + 0x1833658271e61016L }, + { 0x8684b8c4eb809877L,0xb336e18dea0e672eL,0xefb601f034ee5867L, + 0x2733edbe1341cfd1L } }, + /* 35 << 70 */ + { { 0xb15e809a26025c3cL,0xe6e981a69350df88L,0x923762378502fd8eL, + 0x4791f2160c12be9bL }, + { 0xb725678925f02425L,0xec8631947a974443L,0x7c0ce882fb41cc52L, + 0xc266ff7ef25c07f2L } }, + /* 36 << 70 */ + { { 0x3d4da8c3017025f3L,0xefcf628cfb9579b4L,0x5c4d00161f3716ecL, + 0x9c27ebc46801116eL }, + { 0x5eba0ea11da1767eL,0xfe15145247004c57L,0x3ace6df68c2373b7L, + 0x75c3dffe5dbc37acL } }, + /* 37 << 70 */ + { { 0x3dc32a73ddc925fcL,0xb679c8412f65ee0bL,0x715a3295451cbfebL, + 0xd9889768f76e9a29L }, + { 0xec20ce7fb28ad247L,0xe99146c400894d79L,0x71457d7c9f5e3ea7L, + 0x097b266238030031L } }, + /* 38 << 70 */ + { { 0xdb7f6ae6cf9f82a8L,0x319decb9438f473aL,0xa63ab386283856c3L, + 0x13e3172fb06a361bL }, + { 0x2959f8dc7d5a006cL,0x2dbc27c675fba752L,0xc1227ab287c22c9eL, + 0x06f61f7571a268b2L } }, + /* 39 << 70 */ + { { 0x1b6bb97104779ce2L,0xaca838120aadcb1dL,0x297ae0bcaeaab2d5L, + 0xa5c14ee75bfb9f13L }, + { 0xaa00c583f17a62c7L,0x39eb962c173759f6L,0x1eeba1d486c9a88fL, + 0x0ab6c37adf016c5eL } }, + /* 40 << 70 */ + { { 0xa2a147dba28a0749L,0x246c20d6ee519165L,0x5068d1b1d3810715L, + 0xb1e7018c748160b9L }, + { 0x03f5b1faf380ff62L,0xef7fb1ddf3cb2c1eL,0xeab539a8fc91a7daL, + 0x83ddb707f3f9b561L } }, + /* 41 << 70 */ + { { 0xc550e211fe7df7a4L,0xa7cd07f2063f6f40L,0xb0de36352976879cL, + 0xb5f83f85e55741daL }, + { 0x4ea9d25ef3d8ac3dL,0x6fe2066f62819f02L,0x4ab2b9c2cef4a564L, + 0x1e155d965ffa2de3L } }, + /* 42 << 70 */ + { { 0x0eb0a19bc3a72d00L,0x4037665b8513c31bL,0x2fb2b6bf04c64637L, + 0x45c34d6e08cdc639L }, + { 0x56f1e10ff01fd796L,0x4dfb8101fe3667b8L,0xe0eda2539021d0c0L, + 0x7a94e9ff8a06c6abL } }, + /* 43 << 70 */ + { { 0x2d3bb0d9bb9aa882L,0xea20e4e5ec05fd10L,0xed7eeb5f1a1ca64eL, + 0x2fa6b43cc6327cbdL }, + { 0xb577e3cf3aa91121L,0x8c6bd5ea3a34079bL,0xd7e5ba3960e02fc0L, + 0xf16dd2c390141bf8L } }, + /* 44 << 70 */ + { { 0xb57276d980101b98L,0x760883fdb82f0f66L,0x89d7de754bc3eff3L, + 0x03b606435dc2ab40L }, + { 0xcd6e53dfe05beeacL,0xf2f1e862bc3325cdL,0xdd0f7921774f03c3L, + 0x97ca72214552cc1bL } }, + /* 45 << 70 */ + { { 0x5a0d6afe1cd19f72L,0xa20915dcf183fbebL,0x9fda4b40832c403cL, + 0x32738eddbe425442L }, + { 0x469a1df6b5eccf1aL,0x4b5aff4228bbe1f0L,0x31359d7f570dfc93L, + 0xa18be235f0088628L } }, + /* 46 << 70 */ + { { 0xa5b30fbab00ed3a9L,0x34c6137473cdf8beL,0x2c5c5f46abc56797L, + 0x5cecf93db82a8ae2L }, + { 0x7d3dbe41a968fbf0L,0xd23d45831a5c7f3dL,0xf28f69a0c087a9c7L, + 0xc2d75471474471caL } }, + /* 47 << 70 */ + { { 0x36ec9f4a4eb732ecL,0x6c943bbdb1ca6bedL,0xd64535e1f2457892L, + 0x8b84a8eaf7e2ac06L }, + { 0xe0936cd32499dd5fL,0x12053d7e0ed04e57L,0x4bdd0076e4305d9dL, + 0x34a527b91f67f0a2L } }, + /* 48 << 70 */ + { { 0xe79a4af09cec46eaL,0xb15347a1658b9bc7L,0x6bd2796f35af2f75L, + 0xac9579904051c435L }, + { 0x2669dda3c33a655dL,0x5d503c2e88514aa3L,0xdfa113373753dd41L, + 0x3f0546730b754f78L } }, + /* 49 << 70 */ + { { 0xbf185677496125bdL,0xfb0023c83775006cL,0xfa0f072f3a037899L, + 0x4222b6eb0e4aea57L }, + { 0x3dde5e767866d25aL,0xb6eb04f84837aa6fL,0x5315591a2cf1cdb8L, + 0x6dfb4f412d4e683cL } }, + /* 50 << 70 */ + { { 0x7e923ea448ee1f3aL,0x9604d9f705a2afd5L,0xbe1d4a3340ea4948L, + 0x5b45f1f4b44cbd2fL }, + { 0x5faf83764acc757eL,0xa7cf9ab863d68ff7L,0x8ad62f69df0e404bL, + 0xd65f33c212bdafdfL } }, + /* 51 << 70 */ + { { 0xc365de15a377b14eL,0x6bf5463b8e39f60cL,0x62030d2d2ce68148L, + 0xd95867efe6f843a8L }, + { 0xd39a0244ef5ab017L,0x0bd2d8c14ab55d12L,0xc9503db341639169L, + 0x2d4e25b0f7660c8aL } }, + /* 52 << 70 */ + { { 0x760cb3b5e224c5d7L,0xfa3baf8c68616919L,0x9fbca1138d142552L, + 0x1ab18bf17669ebf5L }, + { 0x55e6f53e9bdf25ddL,0x04cc0bf3cb6cd154L,0x595bef4995e89080L, + 0xfe9459a8104a9ac1L } }, + /* 53 << 70 */ + { { 0xad2d89cacce9bb32L,0xddea65e1f7de8285L,0x62ed8c35b351bd4bL, + 0x4150ff360c0e19a7L }, + { 0x86e3c801345f4e47L,0x3bf21f71203a266cL,0x7ae110d4855b1f13L, + 0x5d6aaf6a07262517L } }, + /* 54 << 70 */ + { { 0x1e0f12e1813d28f1L,0x6000e11d7ad7a523L,0xc7d8deefc744a17bL, + 0x1e990b4814c05a00L }, + { 0x68fddaee93e976d5L,0x696241d146610d63L,0xb204e7c3893dda88L, + 0x8bccfa656a3a6946L } }, + /* 55 << 70 */ + { { 0xb59425b4c5cd1411L,0x701b4042ff3658b1L,0xe3e56bca4784cf93L, + 0x27de5f158fe68d60L }, + { 0x4ab9cfcef8d53f19L,0xddb10311a40a730dL,0x6fa73cd14eee0a8aL, + 0xfd5487485249719dL } }, + /* 56 << 70 */ + { { 0x49d66316a8123ef0L,0x73c32db4e7f95438L,0x2e2ed2090d9e7854L, + 0xf98a93299d9f0507L }, + { 0xc5d33cf60c6aa20aL,0x9a32ba1475279bb2L,0x7e3202cb774a7307L, + 0x64ed4bc4e8c42dbdL } }, + /* 57 << 70 */ + { { 0xc20f1a06d4caed0dL,0xb8021407171d22b3L,0xd426ca04d13268d7L, + 0x9237700725f4d126L }, + { 0x4204cbc371f21a85L,0x18461b7af82369baL,0xc0c07d313fc858f9L, + 0x5deb5a50e2bab569L } }, + /* 58 << 70 */ + { { 0xd5959d46d5eea89eL,0xfdff842408437f4bL,0xf21071e43cfe254fL, + 0x7241769695468321L }, + { 0x5d8288b9102cae3eL,0x2d143e3df1965dffL,0x00c9a376a078d847L, + 0x6fc0da3126028731L } }, + /* 59 << 70 */ + { { 0xa2baeadfe45083a2L,0x66bc72185e5b4bcdL,0x2c826442d04b8e7fL, + 0xc19f54516c4b586bL }, + { 0x60182c495b7eeed5L,0xd9954ecd7aa9dfa1L,0xa403a8ecc73884adL, + 0x7fb17de29bb39041L } }, + /* 60 << 70 */ + { { 0x694b64c5abb020e8L,0x3d18c18419c4eec7L,0x9c4673ef1c4793e5L, + 0xc7b8aeb5056092e6L }, + { 0x3aa1ca43f0f8c16bL,0x224ed5ecd679b2f6L,0x0d56eeaf55a205c9L, + 0xbfe115ba4b8e028bL } }, + /* 61 << 70 */ + { { 0x97e608493927f4feL,0xf91fbf94759aa7c5L,0x985af7696be90a51L, + 0xc1277b7878ccb823L }, + { 0x395b656ee7a75952L,0x00df7de0928da5f5L,0x09c231754ca4454fL, + 0x4ec971f47aa2d3c1L } }, + /* 62 << 70 */ + { { 0x45c3c507e75d9cccL,0x63b7be8a3dc90306L,0x37e09c665db44bdcL, + 0x50d60da16841c6a2L }, + { 0x6f9b65ee08df1b12L,0x387348797ff089dfL,0x9c331a663fe8013dL, + 0x017f5de95f42fcc8L } }, + /* 63 << 70 */ + { { 0x43077866e8e57567L,0xc9f781cef9fcdb18L,0x38131dda9b12e174L, + 0x25d84aa38a03752aL }, + { 0x45e09e094d0c0ce2L,0x1564008b92bebba5L,0xf7e8ad31a87284c7L, + 0xb7c4b46c97e7bbaaL } }, + /* 64 << 70 */ + { { 0x3e22a7b397acf4ecL,0x0426c4005ea8b640L,0x5e3295a64e969285L, + 0x22aabc59a6a45670L }, + { 0xb929714c5f5942bcL,0x9a6168bdfa3182edL,0x2216a665104152baL, + 0x46908d03b6926368L } }, + /* 0 << 77 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 77 */ + { { 0xa9f5d8745a1251fbL,0x967747a8c72725c7L,0x195c33e531ffe89eL, + 0x609d210fe964935eL }, + { 0xcafd6ca82fe12227L,0xaf9b5b960426469dL,0x2e9ee04c5693183cL, + 0x1084a333c8146fefL } }, + /* 2 << 77 */ + { { 0x96649933aed1d1f7L,0x566eaff350563090L,0x345057f0ad2e39cfL, + 0x148ff65b1f832124L }, + { 0x042e89d4cf94cf0dL,0x319bec84520c58b3L,0x2a2676265361aa0dL, + 0xc86fa3028fbc87adL } }, + /* 3 << 77 */ + { { 0xfc83d2ab5c8b06d5L,0xb1a785a2fe4eac46L,0xb99315bc846f7779L, + 0xcf31d816ef9ea505L }, + { 0x2391fe6a15d7dc85L,0x2f132b04b4016b33L,0x29547fe3181cb4c7L, + 0xdb66d8a6650155a1L } }, + /* 4 << 77 */ + { { 0x6b66d7e1adc1696fL,0x98ebe5930acd72d0L,0x65f24550cc1b7435L, + 0xce231393b4b9a5ecL }, + { 0x234a22d4db067df9L,0x98dda095caff9b00L,0x1bbc75a06100c9c1L, + 0x1560a9c8939cf695L } }, + /* 5 << 77 */ + { { 0xcf006d3e99e0925fL,0x2dd74a966322375aL,0xc58b446ab56af5baL, + 0x50292683e0b9b4f1L }, + { 0xe2c34cb41aeaffa3L,0x8b17203f9b9587c1L,0x6d559207ead1350cL, + 0x2b66a215fb7f9604L } }, + /* 6 << 77 */ + { { 0x0850325efe51bf74L,0x9c4f579e5e460094L,0x5c87b92a76da2f25L, + 0x889de4e06febef33L }, + { 0x6900ec06646083ceL,0xbe2a0335bfe12773L,0xadd1da35c5344110L, + 0x757568b7b802cd20L } }, + /* 7 << 77 */ + { { 0x7555977900f7e6c8L,0x38e8b94f0facd2f0L,0xfea1f3af03fde375L, + 0x5e11a1d875881dfcL }, + { 0xb3a6b02ec1e2f2efL,0x193d2bbbc605a6c5L,0x325ffeee339a0b2dL, + 0x27b6a7249e0c8846L } }, + /* 8 << 77 */ + { { 0xe4050f1cf1c367caL,0x9bc85a9bc90fbc7dL,0xa373c4a2e1a11032L, + 0xb64232b7ad0393a9L }, + { 0xf5577eb0167dad29L,0x1604f30194b78ab2L,0x0baa94afe829348bL, + 0x77fbd8dd41654342L } }, + /* 9 << 77 */ + { { 0xdab50ea5b964e39aL,0xd4c29e3cd0d3c76eL,0x80dae67c56d11964L, + 0x7307a8bfe5ffcc2fL }, + { 0x65bbc1aa91708c3bL,0xa151e62c28bf0eebL,0x6cb533816fa34db7L, + 0x5139e05ca29403a8L } }, + /* 10 << 77 */ + { { 0x6ff651b494a7cd2eL,0x5671ffd10699336cL,0x6f5fd2cc979a896aL, + 0x11e893a8d8148cefL }, + { 0x988906a165cf7b10L,0x81b67178c50d8485L,0x7c0deb358a35b3deL, + 0x423ac855c1d29799L } }, + /* 11 << 77 */ + { { 0xaf580d87dac50b74L,0x28b2b89f5869734cL,0x99a3b936874e28fbL, + 0xbb2c919025f3f73aL }, + { 0x199f691884a9d5b7L,0x7ebe23257e770374L,0xf442e1070738efe2L, + 0xcf9f3f56cf9082d2L } }, + /* 12 << 77 */ + { { 0x719f69e109618708L,0xcc9e8364c183f9b1L,0xec203a95366a21afL, + 0x6aec5d6d068b141fL }, + { 0xee2df78a994f04e9L,0xb39ccae8271245b0L,0xb875a4a997e43f4fL, + 0x507dfe11db2cea98L } }, + /* 13 << 77 */ + { { 0x4fbf81cb489b03e9L,0xdb86ec5b6ec414faL,0xfad444f9f51b3ae5L, + 0xca7d33d61914e3feL }, + { 0xa9c32f5c0ae6c4d0L,0xa9ca1d1e73969568L,0x98043c311aa7467eL, + 0xe832e75ce21b5ac6L } }, + /* 14 << 77 */ + { { 0x314b7aea5232123dL,0x08307c8c65ae86dbL,0x06e7165caa4668edL, + 0xb170458bb4d3ec39L }, + { 0x4d2e3ec6c19bb986L,0xc5f34846ae0304edL,0x917695a06c9f9722L, + 0x6c7f73174cab1c0aL } }, + /* 15 << 77 */ + { { 0x6295940e9d6d2e8bL,0xd318b8c1549f7c97L,0x2245320497713885L, + 0x468d834ba8a440feL }, + { 0xd81fe5b2bfba796eL,0x152364db6d71f116L,0xbb8c7c59b5b66e53L, + 0x0b12c61b2641a192L } }, + /* 16 << 77 */ + { { 0x31f14802fcf0a7fdL,0x42fd07895488b01eL,0x71d78d6d9952b498L, + 0x8eb572d907ac5201L }, + { 0xe0a2a44c4d194a88L,0xd2b63fd9ba017e66L,0x78efc6c8f888aefcL, + 0xb76f6bda4a881a11L } }, + /* 17 << 77 */ + { { 0x187f314bb46c2397L,0x004cf5665ded2819L,0xa9ea570438764d34L, + 0xbba4521778084709L }, + { 0x064745711171121eL,0xad7b7eb1e7c9b671L,0xdacfbc40730f7507L, + 0x178cd8c6c7ad7bd1L } }, + /* 18 << 77 */ + { { 0xbf0be101b2a67238L,0x3556d367af9c14f2L,0x104b7831a5662075L, + 0x58ca59bb79d9e60aL }, + { 0x4bc45392a569a73bL,0x517a52e85698f6c9L,0x85643da5aeadd755L, + 0x1aed0cd52a581b84L } }, + /* 19 << 77 */ + { { 0xb9b4ff8480af1372L,0x244c3113f1ba5d1fL,0x2a5dacbef5f98d31L, + 0x2c3323e84375bc2aL }, + { 0x17a3ab4a5594b1ddL,0xa1928bfbceb4797eL,0xe83af245e4886a19L, + 0x8979d54672b5a74aL } }, + /* 20 << 77 */ + { { 0xa0f726bc19f9e967L,0xd9d03152e8fbbf4eL,0xcfd6f51db7707d40L, + 0x633084d963f6e6e0L }, + { 0xedcd9cdc55667eafL,0x73b7f92b2e44d56fL,0xfb2e39b64e962b14L, + 0x7d408f6ef671fcbfL } }, + /* 21 << 77 */ + { { 0xcc634ddc164a89bbL,0x74a42bb23ef3bd05L,0x1280dbb2428decbbL, + 0x6103f6bb402c8596L }, + { 0xfa2bf581355a5752L,0x562f96a800946674L,0x4e4ca16d6da0223bL, + 0xfe47819f28d3aa25L } }, + /* 22 << 77 */ + { { 0x9eea3075f8dfcf8aL,0xa284f0aa95669825L,0xb3fca250867d3fd8L, + 0x20757b5f269d691eL }, + { 0xf2c2402093b8a5deL,0xd3f93359ebc06da6L,0x1178293eb2739c33L, + 0xd2a3e770bcd686e5L } }, + /* 23 << 77 */ + { { 0xa76f49f4cd941534L,0x0d37406be3c71c0eL,0x172d93973b97f7e3L, + 0xec17e239bd7fd0deL }, + { 0xe32905516f496ba2L,0x6a69317236ad50e7L,0xc4e539a283e7eff5L, + 0x752737e718e1b4cfL } }, + /* 24 << 77 */ + { { 0xa2f7932c68af43eeL,0x5502468e703d00bdL,0xe5dc978f2fb061f5L, + 0xc9a1904a28c815adL }, + { 0xd3af538d470c56a4L,0x159abc5f193d8cedL,0x2a37245f20108ef3L, + 0xfa17081e223f7178L } }, + /* 25 << 77 */ + { { 0x27b0fb2b10c8c0f5L,0x2102c3ea40650547L,0x594564df8ac3bfa7L, + 0x98102033509dad96L }, + { 0x6989643ff1d18a13L,0x35eebd91d7fc5af0L,0x078d096afaeaafd8L, + 0xb7a89341def3de98L } }, + /* 26 << 77 */ + { { 0x2a206e8decf2a73aL,0x066a63978e551994L,0x3a6a088ab98d53a2L, + 0x0ce7c67c2d1124aaL }, + { 0x48cec671759a113cL,0xe3b373d34f6f67faL,0x5455d479fd36727bL, + 0xe5a428eea13c0d81L } }, + /* 27 << 77 */ + { { 0xb853dbc81c86682bL,0xb78d2727b8d02b2aL,0xaaf69bed8ebc329aL, + 0xdb6b40b3293b2148L }, + { 0xe42ea77db8c4961fL,0xb1a12f7c20e5e0abL,0xa0ec527479e8b05eL, + 0x68027391fab60a80L } }, + /* 28 << 77 */ + { { 0x6bfeea5f16b1bd5eL,0xf957e4204de30ad3L,0xcbaf664e6a353b9eL, + 0x5c87331226d14febL }, + { 0x4e87f98cb65f57cbL,0xdb60a6215e0cdd41L,0x67c16865a6881440L, + 0x1093ef1a46ab52aaL } }, + /* 29 << 77 */ + { { 0xc095afb53f4ece64L,0x6a6bb02e7604551aL,0x55d44b4e0b26b8cdL, + 0xe5f9a999f971268aL }, + { 0xc08ec42511a7de84L,0x83568095fda469ddL,0x737bfba16c6c90a2L, + 0x1cb9c4a0be229831L } }, + /* 30 << 77 */ + { { 0x93bccbbabb2eec64L,0xa0c23b64da03adbeL,0x5f7aa00ae0e86ac4L, + 0x470b941efc1401e6L }, + { 0x5ad8d6799df43574L,0x4ccfb8a90f65d810L,0x1bce80e3aa7fbd81L, + 0x273291ad9508d20aL } }, + /* 31 << 77 */ + { { 0xf5c4b46b42a92806L,0x810684eca86ab44aL,0x4591640bca0bc9f8L, + 0xb5efcdfc5c4b6054L }, + { 0x16fc89076e9edd12L,0xe29d0b50d4d792f9L,0xa45fd01c9b03116dL, + 0x85035235c81765a4L } }, + /* 32 << 77 */ + { { 0x1fe2a9b2b4b4b67cL,0xc1d10df0e8020604L,0x9d64abfcbc8058d8L, + 0x8943b9b2712a0fbbL }, + { 0x90eed9143b3def04L,0x85ab3aa24ce775ffL,0x605fd4ca7bbc9040L, + 0x8b34a564e2c75dfbL } }, + /* 33 << 77 */ + { { 0x41ffc94a10358560L,0x2d8a50729e5c28aaL,0xe915a0fc4cc7eb15L, + 0xe9efab058f6d0f5dL }, + { 0xdbab47a9d19e9b91L,0x8cfed7450276154cL,0x154357ae2cfede0dL, + 0x520630df19f5a4efL } }, + /* 34 << 77 */ + { { 0x25759f7ce382360fL,0xb6db05c988bf5857L,0x2917d61d6c58d46cL, + 0x14f8e491fd20cb7aL }, + { 0xb68a727a11c20340L,0x0386f86faf7ccbb6L,0x5c8bc6ccfee09a20L, + 0x7d76ff4abb7eea35L } }, + /* 35 << 77 */ + { { 0xa7bdebe7db15be7aL,0x67a08054d89f0302L,0x56bf0ea9c1193364L, + 0xc824446762837ebeL }, + { 0x32bd8e8b20d841b8L,0x127a0548dbb8a54fL,0x83dd4ca663b20236L, + 0x87714718203491faL } }, + /* 36 << 77 */ + { { 0x4dabcaaaaa8a5288L,0x91cc0c8aaf23a1c9L,0x34c72c6a3f220e0cL, + 0xbcc20bdf1232144aL }, + { 0x6e2f42daa20ede1bL,0xc441f00c74a00515L,0xbf46a5b6734b8c4bL, + 0x574095037b56c9a4L } }, + /* 37 << 77 */ + { { 0x9f735261e4585d45L,0x9231faed6734e642L,0x1158a176be70ee6cL, + 0x35f1068d7c3501bfL }, + { 0x6beef900a2d26115L,0x649406f2ef0afee3L,0x3f43a60abc2420a1L, + 0x509002a7d5aee4acL } }, + /* 38 << 77 */ + { { 0xb46836a53ff3571bL,0x24f98b78837927c1L,0x6254256a4533c716L, + 0xf27abb0bd07ee196L }, + { 0xd7cf64fc5c6d5bfdL,0x6915c751f0cd7a77L,0xd9f590128798f534L, + 0x772b0da8f81d8b5fL } }, + /* 39 << 77 */ + { { 0x1244260c2e03fa69L,0x36cf0e3a3be1a374L,0x6e7c1633ef06b960L, + 0xa71a4c55671f90f6L }, + { 0x7a94125133c673dbL,0xc0bea51073e8c131L,0x61a8a699d4f6c734L, + 0x25e78c88341ed001L } }, + /* 40 << 77 */ + { { 0x5c18acf88e2f7d90L,0xfdbf33d777be32cdL,0x0a085cd7d2eb5ee9L, + 0x2d702cfbb3201115L }, + { 0xb6e0ebdb85c88ce8L,0x23a3ce3c1e01d617L,0x3041618e567333acL, + 0x9dd0fd8f157edb6bL } }, + /* 41 << 77 */ + { { 0x27f74702b57872b8L,0x2ef26b4f657d5fe1L,0x95426f0a57cf3d40L, + 0x847e2ad165a6067aL }, + { 0xd474d9a009996a74L,0x16a56acd2a26115cL,0x02a615c3d16f4d43L, + 0xcc3fc965aadb85b7L } }, + /* 42 << 77 */ + { { 0x386bda73ce07d1b0L,0xd82910c258ad4178L,0x124f82cfcd2617f4L, + 0xcc2f5e8def691770L }, + { 0x82702550b8c30cccL,0x7b856aea1a8e575aL,0xbb822fefb1ab9459L, + 0x085928bcec24e38eL } }, + /* 43 << 77 */ + { { 0x5d0402ecba8f4b4dL,0xc07cd4ba00b4d58bL,0x5d8dffd529227e7aL, + 0x61d44d0c31bf386fL }, + { 0xe486dc2b135e6f4dL,0x680962ebe79410efL,0xa61bd343f10088b5L, + 0x6aa76076e2e28686L } }, + /* 44 << 77 */ + { { 0x80463d118fb98871L,0xcb26f5c3bbc76affL,0xd4ab8eddfbe03614L, + 0xc8eb579bc0cf2deeL }, + { 0xcc004c15c93bae41L,0x46fbae5d3aeca3b2L,0x671235cf0f1e9ab1L, + 0xadfba9349ec285c1L } }, + /* 45 << 77 */ + { { 0x88ded013f216c980L,0xc8ac4fb8f79e0bc1L,0xa29b89c6fb97a237L, + 0xb697b7809922d8e7L }, + { 0x3142c639ddb945b5L,0x447b06c7e094c3a9L,0xcdcb364272266c90L, + 0x633aad08a9385046L } }, + /* 46 << 77 */ + { { 0xa36c936bb57c6477L,0x871f8b64e94dbcc6L,0x28d0fb62a591a67bL, + 0x9d40e081c1d926f5L }, + { 0x3111eaf6f2d84b5aL,0x228993f9a565b644L,0x0ccbf5922c83188bL, + 0xf87b30ab3df3e197L } }, + /* 47 << 77 */ + { { 0xb8658b317642bca8L,0x1a032d7f52800f17L,0x051dcae579bf9445L, + 0xeba6b8ee54a2e253L }, + { 0x5c8b9cadd4485692L,0x84bda40e8986e9beL,0xd16d16a42f0db448L, + 0x8ec80050a14d4188L } }, + /* 48 << 77 */ + { { 0xb2b2610798fa7aaaL,0x41209ee4f073aa4eL,0xf1570359f2d6b19bL, + 0xcbe6868cfc577cafL }, + { 0x186c4bdc32c04dd3L,0xa6c35faecfeee397L,0xb4a1b312f086c0cfL, + 0xe0a5ccc6d9461fe2L } }, + /* 49 << 77 */ + { { 0xc32278aa1536189fL,0x1126c55fba6df571L,0x0f71a602b194560eL, + 0x8b2d7405324bd6e1L }, + { 0x8481939e3738be71L,0xb5090b1a1a4d97a9L,0x116c65a3f05ba915L, + 0x21863ad3aae448aaL } }, + /* 50 << 77 */ + { { 0xd24e2679a7aae5d3L,0x7076013d0de5c1c4L,0x2d50f8babb05b629L, + 0x73c1abe26e66efbbL }, + { 0xefd4b422f2488af7L,0xe4105d02663ba575L,0x7eb60a8b53a69457L, + 0x62210008c945973bL } }, + /* 51 << 77 */ + { { 0xfb25547877a50ec6L,0xbf0392f70a37a72cL,0xa0a7a19c4be18e7aL, + 0x90d8ea1625b1e0afL }, + { 0x7582a293ef953f57L,0x90a64d05bdc5465aL,0xca79c497e2510717L, + 0x560dbb7c18cb641fL } }, + /* 52 << 77 */ + { { 0x1d8e32864b66abfbL,0xd26f52e559030900L,0x1ee3f6435584941aL, + 0x6d3b3730569f5958L }, + { 0x9ff2a62f4789dba5L,0x91fcb81572b5c9b7L,0xf446cb7d6c8f9a0eL, + 0x48f625c139b7ecb5L } }, + /* 53 << 77 */ + { { 0xbabae8011c6219b8L,0xe7a562d928ac2f23L,0xe1b4873226e20588L, + 0x06ee1cad775af051L }, + { 0xda29ae43faff79f7L,0xc141a412652ee9e0L,0x1e127f6f195f4bd0L, + 0x29c6ab4f072f34f8L } }, + /* 54 << 77 */ + { { 0x7b7c147730448112L,0x82b51af1e4a38656L,0x2bf2028a2f315010L, + 0xc9a4a01f6ea88cd4L }, + { 0xf63e95d8257e5818L,0xdd8efa10b4519b16L,0xed8973e00da910bfL, + 0xed49d0775c0fe4a9L } }, + /* 55 << 77 */ + { { 0xac3aac5eb7caee1eL,0x1033898da7f4da57L,0x42145c0e5c6669b9L, + 0x42daa688c1aa2aa0L }, + { 0x629cc15c1a1d885aL,0x25572ec0f4b76817L,0x8312e4359c8f8f28L, + 0x8107f8cd81965490L } }, + /* 56 << 77 */ + { { 0x516ff3a36fa6110cL,0x74fb1eb1fb93561fL,0x6c0c90478457522bL, + 0xcfd321046bb8bdc6L }, + { 0x2d6884a2cc80ad57L,0x7c27fc3586a9b637L,0x3461baedadf4e8cdL, + 0x1d56251a617242f0L } }, + /* 57 << 77 */ + { { 0x0b80d209c955bef4L,0xdf02cad206adb047L,0xf0d7cb915ec74feeL, + 0xd25033751111ba44L }, + { 0x9671755edf53cb36L,0x54dcb6123368551bL,0x66d69aacc8a025a4L, + 0x6be946c6e77ef445L } }, + /* 58 << 77 */ + { { 0x719946d1a995e094L,0x65e848f6e51e04d8L,0xe62f33006a1e3113L, + 0x1541c7c1501de503L }, + { 0x4daac9faf4acfadeL,0x0e58589744cd0b71L,0x544fd8690a51cd77L, + 0x60fc20ed0031016dL } }, + /* 59 << 77 */ + { { 0x58b404eca4276867L,0x46f6c3cc34f34993L,0x477ca007c636e5bdL, + 0x8018f5e57c458b47L }, + { 0xa1202270e47b668fL,0xcef48ccdee14f203L,0x23f98bae62ff9b4dL, + 0x55acc035c589edddL } }, + /* 60 << 77 */ + { { 0x3fe712af64db4444L,0x19e9d634becdd480L,0xe08bc047a930978aL, + 0x2dbf24eca1280733L }, + { 0x3c0ae38c2cd706b2L,0x5b012a5b359017b9L,0x3943c38c72e0f5aeL, + 0x786167ea57176fa3L } }, + /* 61 << 77 */ + { { 0xe5f9897d594881dcL,0x6b5efad8cfb820c1L,0xb2179093d55018deL, + 0x39ad7d320bac56ceL }, + { 0xb55122e02cfc0e81L,0x117c4661f6d89daaL,0x362d01e1cb64fa09L, + 0x6a309b4e3e9c4dddL } }, + /* 62 << 77 */ + { { 0xfa979fb7abea49b1L,0xb4b1d27d10e2c6c5L,0xbd61c2c423afde7aL, + 0xeb6614f89786d358L }, + { 0x4a5d816b7f6f7459L,0xe431a44f09360e7bL,0x8c27a032c309914cL, + 0xcea5d68acaede3d8L } }, + /* 63 << 77 */ + { { 0x3668f6653a0a3f95L,0x893694167ceba27bL,0x89981fade4728fe9L, + 0x7102c8a08a093562L }, + { 0xbb80310e235d21c8L,0x505e55d1befb7f7bL,0xa0a9081112958a67L, + 0xd67e106a4d851fefL } }, + /* 64 << 77 */ + { { 0xb84011a9431dd80eL,0xeb7c7cca73306cd9L,0x20fadd29d1b3b730L, + 0x83858b5bfe37b3d3L }, + { 0xbf4cd193b6251d5cL,0x1cca1fd31352d952L,0xc66157a490fbc051L, + 0x7990a63889b98636L } }, + /* 0 << 84 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 84 */ + { { 0xe5aa692a87dec0e1L,0x010ded8df7b39d00L,0x7b1b80c854cfa0b5L, + 0x66beb876a0f8ea28L }, + { 0x50d7f5313476cd0eL,0xa63d0e65b08d3949L,0x1a09eea953479fc6L, + 0x82ae9891f499e742L } }, + /* 2 << 84 */ + { { 0xab58b9105ca7d866L,0x582967e23adb3b34L,0x89ae4447cceac0bcL, + 0x919c667c7bf56af5L }, + { 0x9aec17b160f5dcd7L,0xec697b9fddcaadbcL,0x0b98f341463467f5L, + 0xb187f1f7a967132fL } }, + /* 3 << 84 */ + { { 0x90fe7a1d214aeb18L,0x1506af3c741432f7L,0xbb5565f9e591a0c4L, + 0x10d41a77b44f1bc3L }, + { 0xa09d65e4a84bde96L,0x42f060d8f20a6a1cL,0x652a3bfdf27f9ce7L, + 0xb6bdb65c3b3d739fL } }, + /* 4 << 84 */ + { { 0xeb5ddcb6ec7fae9fL,0x995f2714efb66e5aL,0xdee95d8e69445d52L, + 0x1b6c2d4609e27620L }, + { 0x32621c318129d716L,0xb03909f10958c1aaL,0x8c468ef91af4af63L, + 0x162c429ffba5cdf6L } }, + /* 5 << 84 */ + { { 0x2f682343753b9371L,0x29cab45a5f1f9cd7L,0x571623abb245db96L, + 0xc507db093fd79999L }, + { 0x4e2ef652af036c32L,0x86f0cc7805018e5cL,0xc10a73d4ab8be350L, + 0x6519b3977e826327L } }, + /* 6 << 84 */ + { { 0xe8cb5eef9c053df7L,0x8de25b37b300ea6fL,0xdb03fa92c849cffbL, + 0x242e43a7e84169bbL }, + { 0xe4fa51f4dd6f958eL,0x6925a77ff4445a8dL,0xe6e72a50e90d8949L, + 0xc66648e32b1f6390L } }, + /* 7 << 84 */ + { { 0xb2ab1957173e460cL,0x1bbbce7530704590L,0xc0a90dbddb1c7162L, + 0x505e399e15cdd65dL }, + { 0x68434dcb57797ab7L,0x60ad35ba6a2ca8e8L,0x4bfdb1e0de3336c1L, + 0xbbef99ebd8b39015L } }, + /* 8 << 84 */ + { { 0x6c3b96f31711ebecL,0x2da40f1fce98fdc4L,0xb99774d357b4411fL, + 0x87c8bdf415b65bb6L }, + { 0xda3a89e3c2eef12dL,0xde95bb9b3c7471f3L,0x600f225bd812c594L, + 0x54907c5d2b75a56bL } }, + /* 9 << 84 */ + { { 0xa93cc5f08db60e35L,0x743e3cd6fa833319L,0x7dad5c41f81683c9L, + 0x70c1e7d99c34107eL }, + { 0x0edc4a39a6be0907L,0x36d4703586d0b7d3L,0x8c76da03272bfa60L, + 0x0b4a07ea0f08a414L } }, + /* 10 << 84 */ + { { 0x699e4d2945c1dd53L,0xcadc5898231debb5L,0xdf49fcc7a77f00e0L, + 0x93057bbfa73e5a0eL }, + { 0x2f8b7ecd027a4cd1L,0x114734b3c614011aL,0xe7a01db767677c68L, + 0x89d9be5e7e273f4fL } }, + /* 11 << 84 */ + { { 0xd225cb2e089808efL,0xf1f7a27dd59e4107L,0x53afc7618211b9c9L, + 0x0361bc67e6819159L }, + { 0x2a865d0b7f071426L,0x6a3c1810e7072567L,0x3e3bca1e0d6bcabdL, + 0xa1b02bc1408591bcL } }, + /* 12 << 84 */ + { { 0xe0deee5931fba239L,0xf47424d398bd91d1L,0x0f8886f4071a3c1dL, + 0x3f7d41e8a819233bL }, + { 0x708623c2cf6eb998L,0x86bb49af609a287fL,0x942bb24963c90762L, + 0x0ef6eea555a9654bL } }, + /* 13 << 84 */ + { { 0x5f6d2d7236f5defeL,0xfa9922dc56f99176L,0x6c8c5ecef78ce0c7L, + 0x7b44589dbe09b55eL }, + { 0xe11b3bca9ea83770L,0xd7fa2c7f2ab71547L,0x2a3dd6fa2a1ddcc0L, + 0x09acb4305a7b7707L } }, + /* 14 << 84 */ + { { 0x4add4a2e649d4e57L,0xcd53a2b01917526eL,0xc526233020b44ac4L, + 0x4028746abaa2c31dL }, + { 0x5131839064291d4cL,0xbf48f151ee5ad909L,0xcce57f597b185681L, + 0x7c3ac1b04854d442L } }, + /* 15 << 84 */ + { { 0x65587dc3c093c171L,0xae7acb2424f42b65L,0x5a338adb955996cbL, + 0xc8e656756051f91bL }, + { 0x66711fba28b8d0b1L,0x15d74137b6c10a90L,0x70cdd7eb3a232a80L, + 0xc9e2f07f6191ed24L } }, + /* 16 << 84 */ + { { 0xa80d1db6f79588c0L,0xfa52fc69b55768ccL,0x0b4df1ae7f54438aL, + 0x0cadd1a7f9b46a4fL }, + { 0xb40ea6b31803dd6fL,0x488e4fa555eaae35L,0x9f047d55382e4e16L, + 0xc9b5b7e02f6e0c98L } }, + /* 17 << 84 */ + { { 0x6b1bd2d395762649L,0xa9604ee7c7aea3f6L,0x3646ff276dc6f896L, + 0x9bf0e7f52860bad1L }, + { 0x2d92c8217cb44b92L,0xa2f5ce63aea9c182L,0xd0a2afb19154a5fdL, + 0x482e474c95801da6L } }, + /* 18 << 84 */ + { { 0xc19972d0b611c24bL,0x1d468e6560a8f351L,0xeb7580697bcf6421L, + 0xec9dd0ee88fbc491L }, + { 0x5b59d2bf956c2e32L,0x73dc6864dcddf94eL,0xfd5e2321bcee7665L, + 0xa7b4f8ef5e9a06c4L } }, + /* 19 << 84 */ + { { 0xfba918dd7280f855L,0xbbaac2608baec688L,0xa3b3f00f33400f42L, + 0x3d2dba2966f2e6e4L }, + { 0xb6f71a9498509375L,0x8f33031fcea423ccL,0x009b8dd04807e6fbL, + 0x5163cfe55cdb954cL } }, + /* 20 << 84 */ + { { 0x03cc8f17cf41c6e8L,0xf1f03c2a037b925cL,0xc39c19cc66d2427cL, + 0x823d24ba7b6c18e4L }, + { 0x32ef9013901f0b4fL,0x684360f1f8941c2eL,0x0ebaff522c28092eL, + 0x7891e4e3256c932fL } }, + /* 21 << 84 */ + { { 0x51264319ac445e3dL,0x553432e78ea74381L,0xe6eeaa6967e9c50aL, + 0x27ced28462e628c7L }, + { 0x3f96d3757a4afa57L,0xde0a14c3e484c150L,0x364a24eb38bd9923L, + 0x1df18da0e5177422L } }, + /* 22 << 84 */ + { { 0x174e8f82d8d38a9bL,0x2e97c600e7de1391L,0xc5709850a1c175ddL, + 0x969041a032ae5035L }, + { 0xcbfd533b76a2086bL,0xd6bba71bd7c2e8feL,0xb2d58ee6099dfb67L, + 0x3a8b342d064a85d9L } }, + /* 23 << 84 */ + { { 0x3bc07649522f9be3L,0x690c075bdf1f49a8L,0x80e1aee83854ec42L, + 0x2a7dbf4417689dc7L }, + { 0xc004fc0e3faf4078L,0xb2f02e9edf11862cL,0xf10a5e0fa0a1b7b3L, + 0x30aca6238936ec80L } }, + /* 24 << 84 */ + { { 0xf83cbf0502f40d9aL,0x4681c4682c318a4dL,0x985756180e9c2674L, + 0xbe79d0461847092eL }, + { 0xaf1e480a78bd01e0L,0x6dd359e472a51db9L,0x62ce3821e3afbab6L, + 0xc5cee5b617733199L } }, + /* 25 << 84 */ + { { 0xe08b30d46ffd9fbbL,0x6e5bc69936c610b7L,0xf343cff29ce262cfL, + 0xca2e4e3568b914c1L }, + { 0x011d64c016de36c5L,0xe0b10fdd42e2b829L,0x789429816685aaf8L, + 0xe7511708230ede97L } }, + /* 26 << 84 */ + { { 0x671ed8fc3b922bf8L,0xe4d8c0a04c29b133L,0x87eb12393b6e99c4L, + 0xaff3974c8793bebaL }, + { 0x037494052c18df9bL,0xc5c3a29391007139L,0x6a77234fe37a0b95L, + 0x02c29a21b661c96bL } }, + /* 27 << 84 */ + { { 0xc3aaf1d6141ecf61L,0x9195509e3bb22f53L,0x2959740422d51357L, + 0x1b083822537bed60L }, + { 0xcd7d6e35e07289f0L,0x1f94c48c6dd86effL,0xc8bb1f82eb0f9cfaL, + 0x9ee0b7e61b2eb97dL } }, + /* 28 << 84 */ + { { 0x5a52fe2e34d74e31L,0xa352c3103bf79ab6L,0x97ff6c5aabfeeb8fL, + 0xbfbe8feff5c97305L }, + { 0xd6081ce6a7904608L,0x1f812f3ac4fca249L,0x9b24bc9ab9e5e200L, + 0x91022c6738012ee8L } }, + /* 29 << 84 */ + { { 0xe83d9c5d30a713a1L,0x4876e3f084ef0f93L,0xc9777029c1fbf928L, + 0xef7a6bb3bce7d2a4L }, + { 0xb8067228dfa2a659L,0xd5cd3398d877a48fL,0xbea4fd8f025d0f3fL, + 0xd67d2e352eae7c2bL } }, + /* 30 << 84 */ + { { 0x184de7d7cc5f4394L,0xb5551b5c4536e142L,0x2e89b212d34aa60aL, + 0x14a96feaf50051d5L }, + { 0x4e21ef740d12bb0bL,0xc522f02060b9677eL,0x8b12e4672df7731dL, + 0x39f803827b326d31L } }, + /* 31 << 84 */ + { { 0xdfb8630c39024a94L,0xaacb96a897319452L,0xd68a3961eda3867cL, + 0x0c58e2b077c4ffcaL }, + { 0x3d545d634da919faL,0xef79b69af15e2289L,0x54bc3d3d808bab10L, + 0xc8ab300745f82c37L } }, + /* 32 << 84 */ + { { 0xc12738b67c4a658aL,0xb3c4763940e72182L,0x3b77be468798e44fL, + 0xdc047df217a7f85fL }, + { 0x2439d4c55e59d92dL,0xcedca475e8e64d8dL,0xa724cd0d87ca9b16L, + 0x35e4fd59a5540dfeL } }, + /* 33 << 84 */ + { { 0xf8c1ff18e4bcf6b1L,0x856d6285295018faL,0x433f665c3263c949L, + 0xa6a76dd6a1f21409L }, + { 0x17d32334cc7b4f79L,0xa1d0312206720e4aL,0xadb6661d81d9bed5L, + 0xf0d6fb0211db15d1L } }, + /* 34 << 84 */ + { { 0x7fd11ad51fb747d2L,0xab50f9593033762bL,0x2a7e711bfbefaf5aL, + 0xc73932783fef2bbfL }, + { 0xe29fa2440df6f9beL,0x9092757b71efd215L,0xee60e3114f3d6fd9L, + 0x338542d40acfb78bL } }, + /* 35 << 84 */ + { { 0x44a23f0838961a0fL,0x1426eade986987caL,0x36e6ee2e4a863cc6L, + 0x48059420628b8b79L }, + { 0x30303ad87396e1deL,0x5c8bdc4838c5aad1L,0x3e40e11f5c8f5066L, + 0xabd6e7688d246bbdL } }, + /* 36 << 84 */ + { { 0x68aa40bb23330a01L,0xd23f5ee4c34eafa0L,0x3bbee3155de02c21L, + 0x18dd4397d1d8dd06L }, + { 0x3ba1939a122d7b44L,0xe6d3b40aa33870d6L,0x8e620f701c4fe3f8L, + 0xf6bba1a5d3a50cbfL } }, + /* 37 << 84 */ + { { 0x4a78bde5cfc0aee0L,0x847edc46c08c50bdL,0xbaa2439cad63c9b2L, + 0xceb4a72810fc2acbL }, + { 0xa419e40e26da033dL,0x6cc3889d03e02683L,0x1cd28559fdccf725L, + 0x0fd7e0f18d13d208L } }, + /* 38 << 84 */ + { { 0x01b9733b1f0df9d4L,0x8cc2c5f3a2b5e4f3L,0x43053bfa3a304fd4L, + 0x8e87665c0a9f1aa7L }, + { 0x087f29ecd73dc965L,0x15ace4553e9023dbL,0x2370e3092bce28b4L, + 0xf9723442b6b1e84aL } }, + /* 39 << 84 */ + { { 0xbeee662eb72d9f26L,0xb19396def0e47109L,0x85b1fa73e13289d0L, + 0x436cf77e54e58e32L }, + { 0x0ec833b3e990ef77L,0x7373e3ed1b11fc25L,0xbe0eda870fc332ceL, + 0xced049708d7ea856L } }, + /* 40 << 84 */ + { { 0xf85ff7857e977ca0L,0xb66ee8dadfdd5d2bL,0xf5e37950905af461L, + 0x587b9090966d487cL }, + { 0x6a198a1b32ba0127L,0xa7720e07141615acL,0xa23f3499996ef2f2L, + 0xef5f64b4470bcb3dL } }, + /* 41 << 84 */ + { { 0xa526a96292b8c559L,0x0c14aac069740a0fL,0x0d41a9e3a6bdc0a5L, + 0x97d521069c48aef4L }, + { 0xcf16bd303e7c253bL,0xcc834b1a47fdedc1L,0x7362c6e5373aab2eL, + 0x264ed85ec5f590ffL } }, + /* 42 << 84 */ + { { 0x7a46d9c066d41870L,0xa50c20b14787ba09L,0x185e7e51e3d44635L, + 0xb3b3e08031e2d8dcL }, + { 0xbed1e558a179e9d9L,0x2daa3f7974a76781L,0x4372baf23a40864fL, + 0x46900c544fe75cb5L } }, + /* 43 << 84 */ + { { 0xb95f171ef76765d0L,0x4ad726d295c87502L,0x2ec769da4d7c99bdL, + 0x5e2ddd19c36cdfa8L }, + { 0xc22117fca93e6deaL,0xe8a2583b93771123L,0xbe2f6089fa08a3a2L, + 0x4809d5ed8f0e1112L } }, + /* 44 << 84 */ + { { 0x3b414aa3da7a095eL,0x9049acf126f5aaddL,0x78d46a4d6be8b84aL, + 0xd66b1963b732b9b3L }, + { 0x5c2ac2a0de6e9555L,0xcf52d098b5bd8770L,0x15a15fa60fd28921L, + 0x56ccb81e8b27536dL } }, + /* 45 << 84 */ + { { 0x0f0d8ab89f4ccbb8L,0xed5f44d2db221729L,0x4314198800bed10cL, + 0xc94348a41d735b8bL }, + { 0x79f3e9c429ef8479L,0x4c13a4e3614c693fL,0x32c9af568e143a14L, + 0xbc517799e29ac5c4L } }, + /* 46 << 84 */ + { { 0x05e179922774856fL,0x6e52fb056c1bf55fL,0xaeda4225e4f19e16L, + 0x70f4728aaf5ccb26L }, + { 0x5d2118d1b2947f22L,0xc827ea16281d6fb9L,0x8412328d8cf0eabdL, + 0x45ee9fb203ef9dcfL } }, + /* 47 << 84 */ + { { 0x8e700421bb937d63L,0xdf8ff2d5cc4b37a6L,0xa4c0d5b25ced7b68L, + 0x6537c1efc7308f59L }, + { 0x25ce6a263b37f8e8L,0x170e9a9bdeebc6ceL,0xdd0379528728d72cL, + 0x445b0e55850154bcL } }, + /* 48 << 84 */ + { { 0x4b7d0e0683a7337bL,0x1e3416d4ffecf249L,0x24840eff66a2b71fL, + 0xd0d9a50ab37cc26dL }, + { 0xe21981506fe28ef7L,0x3cc5ef1623324c7fL,0x220f3455769b5263L, + 0xe2ade2f1a10bf475L } }, + /* 49 << 84 */ + { { 0x28cd20fa458d3671L,0x1549722c2dc4847bL,0x6dd01e55591941e3L, + 0x0e6fbcea27128ccbL }, + { 0xae1a1e6b3bef0262L,0xfa8c472c8f54e103L,0x7539c0a872c052ecL, + 0xd7b273695a3490e9L } }, + /* 50 << 84 */ + { { 0x143fe1f171684349L,0x36b4722e32e19b97L,0xdc05922790980affL, + 0x175c9c889e13d674L }, + { 0xa7de5b226e6bfdb1L,0x5ea5b7b2bedb4b46L,0xd5570191d34a6e44L, + 0xfcf60d2ea24ff7e6L } }, + /* 51 << 84 */ + { { 0x614a392d677819e1L,0x7be74c7eaa5a29e8L,0xab50fece63c85f3fL, + 0xaca2e2a946cab337L }, + { 0x7f700388122a6fe3L,0xdb69f703882a04a8L,0x9a77935dcf7aed57L, + 0xdf16207c8d91c86fL } }, + /* 52 << 84 */ + { { 0x2fca49ab63ed9998L,0xa3125c44a77ddf96L,0x05dd8a8624344072L, + 0xa023dda2fec3fb56L }, + { 0x421b41fc0c743032L,0x4f2120c15e438639L,0xfb7cae51c83c1b07L, + 0xb2370caacac2171aL } }, + /* 53 << 84 */ + { { 0x2eb2d9626cc820fbL,0x59feee5cb85a44bfL,0x94620fca5b6598f0L, + 0x6b922cae7e314051L }, + { 0xff8745ad106bed4eL,0x546e71f5dfa1e9abL,0x935c1e481ec29487L, + 0x9509216c4d936530L } }, + /* 54 << 84 */ + { { 0xc7ca306785c9a2dbL,0xd6ae51526be8606fL,0x09dbcae6e14c651dL, + 0xc9536e239bc32f96L }, + { 0xa90535a934521b03L,0xf39c526c878756ffL,0x383172ec8aedf03cL, + 0x20a8075eefe0c034L } }, + /* 55 << 84 */ + { { 0xf22f9c6264026422L,0x8dd1078024b9d076L,0x944c742a3bef2950L, + 0x55b9502e88a2b00bL }, + { 0xa59e14b486a09817L,0xa39dd3ac47bb4071L,0x55137f663be0592fL, + 0x07fcafd4c9e63f5bL } }, + /* 56 << 84 */ + { { 0x963652ee346eb226L,0x7dfab085ec2facb7L,0x273bf2b8691add26L, + 0x30d74540f2b46c44L }, + { 0x05e8e73ef2c2d065L,0xff9b8a00d42eeac9L,0x2fcbd20597209d22L, + 0xeb740ffade14ea2cL } }, + /* 57 << 84 */ + { { 0xc71ff913a8aef518L,0x7bfc74bbfff4cfa2L,0x1716680cb6b36048L, + 0x121b2cce9ef79af1L }, + { 0xbff3c836a01eb3d3L,0x50eb1c6a5f79077bL,0xa48c32d6a004bbcfL, + 0x47a593167d64f61dL } }, + /* 58 << 84 */ + { { 0x6068147f93102016L,0x12c5f65494d12576L,0xefb071a7c9bc6b91L, + 0x7c2da0c56e23ea95L }, + { 0xf4fd45b6d4a1dd5dL,0x3e7ad9b69122b13cL,0x342ca118e6f57a48L, + 0x1c2e94a706f8288fL } }, + /* 59 << 84 */ + { { 0x99e68f075a97d231L,0x7c80de974d838758L,0xbce0f5d005872727L, + 0xbe5d95c219c4d016L }, + { 0x921d5cb19c2492eeL,0x42192dc1404d6fb3L,0x4c84dcd132f988d3L, + 0xde26d61fa17b8e85L } }, + /* 60 << 84 */ + { { 0xc466dcb6137c7408L,0x9a38d7b636a266daL,0x7ef5cb0683bebf1bL, + 0xe5cdcbbf0fd014e3L }, + { 0x30aa376df65965a0L,0x60fe88c2ebb3e95eL,0x33fd0b6166ee6f20L, + 0x8827dcdb3f41f0a0L } }, + /* 61 << 84 */ + { { 0xbf8a9d240c56c690L,0x40265dadddb7641dL,0x522b05bf3a6b662bL, + 0x466d1dfeb1478c9bL }, + { 0xaa6169621484469bL,0x0db6054902df8f9fL,0xc37bca023cb8bf51L, + 0x5effe34621371ce8L } }, + /* 62 << 84 */ + { { 0xe8f65264ff112c32L,0x8a9c736d7b971fb2L,0xa4f194707b75080dL, + 0xfc3f2c5a8839c59bL }, + { 0x1d6c777e5aeb49c2L,0xf3db034dda1addfeL,0xd76fee5a5535affcL, + 0x0853ac70b92251fdL } }, + /* 63 << 84 */ + { { 0x37e3d5948b2a29d5L,0x28f1f4574de00ddbL,0x8083c1b5f42c328bL, + 0xd8ef1d8fe493c73bL }, + { 0x96fb626041dc61bdL,0xf74e8a9d27ee2f8aL,0x7c605a802c946a5dL, + 0xeed48d653839ccfdL } }, + /* 64 << 84 */ + { { 0x9894344f3a29467aL,0xde81e949c51eba6dL,0xdaea066ba5e5c2f2L, + 0x3fc8a61408c8c7b3L }, + { 0x7adff88f06d0de9fL,0xbbc11cf53b75ce0aL,0x9fbb7accfbbc87d5L, + 0xa1458e267badfde2L } }, + /* 0 << 91 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 91 */ + { { 0x1cb43668e039c256L,0x5f26fb8b7c17fd5dL,0xeee426af79aa062bL, + 0x072002d0d78fbf04L }, + { 0x4c9ca237e84fb7e3L,0xb401d8a10c82133dL,0xaaa525926d7e4181L, + 0xe943083373dbb152L } }, + /* 2 << 91 */ + { { 0xf92dda31be24319aL,0x03f7d28be095a8e7L,0xa52fe84098782185L, + 0x276ddafe29c24dbcL }, + { 0x80cd54961d7a64ebL,0xe43608897f1dbe42L,0x2f81a8778438d2d5L, + 0x7e4d52a885169036L } }, + /* 3 << 91 */ + { { 0x19e3d5b11d59715dL,0xc7eaa762d788983eL,0xe5a730b0abf1f248L, + 0xfbab8084fae3fd83L }, + { 0x65e50d2153765b2fL,0xbdd4e083fa127f3dL,0x9cf3c074397b1b10L, + 0x59f8090cb1b59fd3L } }, + /* 4 << 91 */ + { { 0x7b15fd9d615faa8fL,0x8fa1eb40968554edL,0x7bb4447e7aa44882L, + 0x2bb2d0d1029fff32L }, + { 0x075e2a646caa6d2fL,0x8eb879de22e7351bL,0xbcd5624e9a506c62L, + 0x218eaef0a87e24dcL } }, + /* 5 << 91 */ + { { 0x37e5684744ddfa35L,0x9ccfc5c5dab3f747L,0x9ac1df3f1ee96cf4L, + 0x0c0571a13b480b8fL }, + { 0x2fbeb3d54b3a7b3cL,0x35c036695dcdbb99L,0x52a0f5dcb2415b3aL, + 0xd57759b44413ed9aL } }, + /* 6 << 91 */ + { { 0x1fe647d83d30a2c5L,0x0857f77ef78a81dcL,0x11d5a334131a4a9bL, + 0xc0a94af929d393f5L }, + { 0xbc3a5c0bdaa6ec1aL,0xba9fe49388d2d7edL,0xbb4335b4bb614797L, + 0x991c4d6872f83533L } }, + /* 7 << 91 */ + { { 0x53258c28d2f01cb3L,0x93d6eaa3d75db0b1L,0x419a2b0de87d0db4L, + 0xa1e48f03d8fe8493L }, + { 0xf747faf6c508b23aL,0xf137571a35d53549L,0x9f5e58e2fcf9b838L, + 0xc7186ceea7fd3cf5L } }, + /* 8 << 91 */ + { { 0x77b868cee978a1d3L,0xe3a68b337ab92d04L,0x5102979487a5b862L, + 0x5f0606c33a61d41dL }, + { 0x2814be276f9326f1L,0x2f521c14c6fe3c2eL,0x17464d7dacdf7351L, + 0x10f5f9d3777f7e44L } }, + /* 9 << 91 */ + { { 0xce8e616b269fb37dL,0xaaf738047de62de5L,0xaba111754fdd4153L, + 0x515759ba3770b49bL }, + { 0x8b09ebf8aa423a61L,0x592245a1cd41fb92L,0x1cba8ec19b4c8936L, + 0xa87e91e3af36710eL } }, + /* 10 << 91 */ + { { 0x1fd84ce43d34a2e3L,0xee3759ceb43b5d61L,0x895bc78c619186c7L, + 0xf19c3809cbb9725aL }, + { 0xc0be21aade744b1fL,0xa7d222b060f8056bL,0x74be6157b23efe11L, + 0x6fab2b4f0cd68253L } }, + /* 11 << 91 */ + { { 0xad33ea5f4bf1d725L,0x9c1d8ee24f6c950fL,0x544ee78aa377af06L, + 0x54f489bb94a113e1L }, + { 0x8f11d634992fb7e8L,0x0169a7aaa2a44347L,0x1d49d4af95020e00L, + 0x95945722e08e120bL } }, + /* 12 << 91 */ + { { 0xb6e33878a4d32282L,0xe36e029d48020ae7L,0xe05847fb37a9b750L, + 0xf876812cb29e3819L }, + { 0x84ad138ed23a17f0L,0x6d7b4480f0b3950eL,0xdfa8aef42fd67ae0L, + 0x8d3eea2452333af6L } }, + /* 13 << 91 */ + { { 0x0d052075b15d5accL,0xc6d9c79fbd815bc4L,0x8dcafd88dfa36cf2L, + 0x908ccbe238aa9070L }, + { 0x638722c4ba35afceL,0x5a3da8b0fd6abf0bL,0x2dce252cc9c335c1L, + 0x84e7f0de65aa799bL } }, + /* 14 << 91 */ + { { 0x2101a522b99a72cbL,0x06de6e6787618016L,0x5ff8c7cde6f3653eL, + 0x0a821ab5c7a6754aL }, + { 0x7e3fa52b7cb0b5a2L,0xa7fb121cc9048790L,0x1a72502006ce053aL, + 0xb490a31f04e929b0L } }, + /* 15 << 91 */ + { { 0xe17be47d62dd61adL,0x781a961c6be01371L,0x1063bfd3dae3cbbaL, + 0x356474067f73c9baL }, + { 0xf50e957b2736a129L,0xa6313702ed13f256L,0x9436ee653a19fcc5L, + 0xcf2bdb29e7a4c8b6L } }, + /* 16 << 91 */ + { { 0xb06b1244c5f95cd8L,0xda8c8af0f4ab95f4L,0x1bae59c2b9e5836dL, + 0x07d51e7e3acffffcL }, + { 0x01e15e6ac2ccbcdaL,0x3bc1923f8528c3e0L,0x43324577a49fead4L, + 0x61a1b8842aa7a711L } }, + /* 17 << 91 */ + { { 0xf9a86e08700230efL,0x0af585a1bd19adf8L,0x7645f361f55ad8f2L, + 0x6e67622346c3614cL }, + { 0x23cb257c4e774d3fL,0x82a38513ac102d1bL,0x9bcddd887b126aa5L, + 0xe716998beefd3ee4L } }, + /* 18 << 91 */ + { { 0x4239d571fb167583L,0xdd011c78d16c8f8aL,0x271c289569a27519L, + 0x9ce0a3b7d2d64b6aL }, + { 0x8c977289d5ec6738L,0xa3b49f9a8840ef6bL,0x808c14c99a453419L, + 0x5c00295b0cf0a2d5L } }, + /* 19 << 91 */ + { { 0x524414fb1d4bcc76L,0xb07691d2459a88f1L,0x77f43263f70d110fL, + 0x64ada5e0b7abf9f3L }, + { 0xafd0f94e5b544cf5L,0xb4a13a15fd2713feL,0xb99b7d6e250c74f4L, + 0x097f2f7320324e45L } }, + /* 20 << 91 */ + { { 0x994b37d8affa8208L,0xc3c31b0bdc29aafcL,0x3da746517a3a607fL, + 0xd8e1b8c1fe6955d6L }, + { 0x716e1815c8418682L,0x541d487f7dc91d97L,0x48a04669c6996982L, + 0xf39cab1583a6502eL } }, + /* 21 << 91 */ + { { 0x025801a0e68db055L,0xf3569758ba3338d5L,0xb0c8c0aaee2afa84L, + 0x4f6985d3fb6562d1L }, + { 0x351f1f15132ed17aL,0x510ed0b4c04365feL,0xa3f98138e5b1f066L, + 0xbc9d95d632df03dcL } }, + /* 22 << 91 */ + { { 0xa83ccf6e19abd09eL,0x0b4097c14ff17edbL,0x58a5c478d64a06ceL, + 0x2ddcc3fd544a58fdL }, + { 0xd449503d9e8153b8L,0x3324fd027774179bL,0xaf5d47c8dbd9120cL, + 0xeb86016234fa94dbL } }, + /* 23 << 91 */ + { { 0x5817bdd1972f07f4L,0xe5579e2ed27bbcebL,0x86847a1f5f11e5a6L, + 0xb39ed2557c3cf048L }, + { 0xe1076417a2f62e55L,0x6b9ab38f1bcf82a2L,0x4bb7c3197aeb29f9L, + 0xf6d17da317227a46L } }, + /* 24 << 91 */ + { { 0xab53ddbd0f968c00L,0xa03da7ec000c880bL,0x7b2396246a9ad24dL, + 0x612c040101ec60d0L }, + { 0x70d10493109f5df1L,0xfbda403080af7550L,0x30b93f95c6b9a9b3L, + 0x0c74ec71007d9418L } }, + /* 25 << 91 */ + { { 0x941755646edb951fL,0x5f4a9d787f22c282L,0xb7870895b38d1196L, + 0xbc593df3a228ce7cL }, + { 0xc78c5bd46af3641aL,0x7802200b3d9b3dccL,0x0dc73f328be33304L, + 0x847ed87d61ffb79aL } }, + /* 26 << 91 */ + { { 0xf85c974e6d671192L,0x1e14100ade16f60fL,0x45cb0d5a95c38797L, + 0x18923bba9b022da4L }, + { 0xef2be899bbe7e86eL,0x4a1510ee216067bfL,0xd98c815484d5ce3eL, + 0x1af777f0f92a2b90L } }, + /* 27 << 91 */ + { { 0x9fbcb4004ef65724L,0x3e04a4c93c0ca6feL,0xfb3e2cb555002994L, + 0x1f3a93c55363ecabL }, + { 0x1fe00efe3923555bL,0x744bedd91e1751eaL,0x3fb2db596ab69357L, + 0x8dbd7365f5e6618bL } }, + /* 28 << 91 */ + { { 0x99d53099df1ea40eL,0xb3f24a0b57d61e64L,0xd088a198596eb812L, + 0x22c8361b5762940bL }, + { 0x66f01f97f9c0d95cL,0x884611728e43cdaeL,0x11599a7fb72b15c3L, + 0x135a7536420d95ccL } }, + /* 29 << 91 */ + { { 0x2dcdf0f75f7ae2f6L,0x15fc6e1dd7fa6da2L,0x81ca829ad1d441b6L, + 0x84c10cf804a106b6L }, + { 0xa9b26c95a73fbbd0L,0x7f24e0cb4d8f6ee8L,0x48b459371e25a043L, + 0xf8a74fca036f3dfeL } }, + /* 30 << 91 */ + { { 0x1ed46585c9f84296L,0x7fbaa8fb3bc278b0L,0xa8e96cd46c4fcbd0L, + 0x940a120273b60a5fL }, + { 0x34aae12055a4aec8L,0x550e9a74dbd742f0L,0x794456d7228c68abL, + 0x492f8868a4e25ec6L } }, + /* 31 << 91 */ + { { 0x682915adb2d8f398L,0xf13b51cc5b84c953L,0xcda90ab85bb917d6L, + 0x4b6155604ea3dee1L }, + { 0x578b4e850a52c1c8L,0xeab1a69520b75fc4L,0x60c14f3caa0bb3c6L, + 0x220f448ab8216094L } }, + /* 32 << 91 */ + { { 0x4fe7ee31b0e63d34L,0xf4600572a9e54fabL,0xc0493334d5e7b5a4L, + 0x8589fb9206d54831L }, + { 0xaa70f5cc6583553aL,0x0879094ae25649e5L,0xcc90450710044652L, + 0xebb0696d02541c4fL } }, + /* 33 << 91 */ + { { 0x5a171fdeb9718710L,0x38f1bed8f374a9f5L,0xc8c582e1ba39bdc1L, + 0xfc457b0a908cc0ceL }, + { 0x9a187fd4883841e2L,0x8ec25b3938725381L,0x2553ed0596f84395L, + 0x095c76616f6c6897L } }, + /* 34 << 91 */ + { { 0x917ac85c4bdc5610L,0xb2885fe4179eb301L,0x5fc655478b78bdccL, + 0x4a9fc893e59e4699L }, + { 0xbb7ff0cd3ce299afL,0x195be9b3adf38b20L,0x6a929c87d38ddb8fL, + 0x55fcc99cb21a51b9L } }, + /* 35 << 91 */ + { { 0x2b695b4c721a4593L,0xed1e9a15768eaac2L,0xfb63d71c7489f914L, + 0xf98ba31c78118910L }, + { 0x802913739b128eb4L,0x7801214ed448af4aL,0xdbd2e22b55418dd3L, + 0xeffb3c0dd3998242L } }, + /* 36 << 91 */ + { { 0xdfa6077cc7bf3827L,0xf2165bcb47f8238fL,0xfe37cf688564d554L, + 0xe5f825c40a81fb98L }, + { 0x43cc4f67ffed4d6fL,0xbc609578b50a34b0L,0x8aa8fcf95041faf1L, + 0x5659f053651773b6L } }, + /* 37 << 91 */ + { { 0xe87582c36044d63bL,0xa60894090cdb0ca0L,0x8c993e0fbfb2bcf6L, + 0xfc64a71945985cfcL }, + { 0x15c4da8083dbedbaL,0x804ae1122be67df7L,0xda4c9658a23defdeL, + 0x12002ddd5156e0d3L } }, + /* 38 << 91 */ + { { 0xe68eae895dd21b96L,0x8b99f28bcf44624dL,0x0ae008081ec8897aL, + 0xdd0a93036712f76eL }, + { 0x962375224e233de4L,0x192445b12b36a8a5L,0xabf9ff74023993d9L, + 0x21f37bf42aad4a8fL } }, + /* 39 << 91 */ + { { 0x340a4349f8bd2bbdL,0x1d902cd94868195dL,0x3d27bbf1e5fdb6f1L, + 0x7a5ab088124f9f1cL }, + { 0xc466ab06f7a09e03L,0x2f8a197731f2c123L,0xda355dc7041b6657L, + 0xcb840d128ece2a7cL } }, + /* 40 << 91 */ + { { 0xb600ad9f7db32675L,0x78fea13307a06f1bL,0x5d032269b31f6094L, + 0x07753ef583ec37aaL }, + { 0x03485aed9c0bea78L,0x41bb3989bc3f4524L,0x09403761697f726dL, + 0x6109beb3df394820L } }, + /* 41 << 91 */ + { { 0x804111ea3b6d1145L,0xb6271ea9a8582654L,0x619615e624e66562L, + 0xa2554945d7b6ad9cL }, + { 0xd9c4985e99bfe35fL,0x9770ccc07b51cdf6L,0x7c32701392881832L, + 0x8777d45f286b26d1L } }, + /* 42 << 91 */ + { { 0x9bbeda22d847999dL,0x03aa33b6c3525d32L,0x4b7b96d428a959a1L, + 0xbb3786e531e5d234L }, + { 0xaeb5d3ce6961f247L,0x20aa85af02f93d3fL,0x9cd1ad3dd7a7ae4fL, + 0xbf6688f0781adaa8L } }, + /* 43 << 91 */ + { { 0xb1b40e867469ceadL,0x1904c524309fca48L,0x9b7312af4b54bbc7L, + 0xbe24bf8f593affa2L }, + { 0xbe5e0790bd98764bL,0xa0f45f17a26e299eL,0x4af0d2c26b8fe4c7L, + 0xef170db18ae8a3e6L } }, + /* 44 << 91 */ + { { 0x0e8d61a029e0ccc1L,0xcd53e87e60ad36caL,0x328c6623c8173822L, + 0x7ee1767da496be55L }, + { 0x89f13259648945afL,0x9e45a5fd25c8009cL,0xaf2febd91f61ab8cL, + 0x43f6bc868a275385L } }, + /* 45 << 91 */ + { { 0x87792348f2142e79L,0x17d89259c6e6238aL,0x7536d2f64a839d9bL, + 0x1f428fce76a1fbdcL }, + { 0x1c1096010db06dfeL,0xbfc16bc150a3a3ccL,0xf9cbd9ec9b30f41bL, + 0x5b5da0d600138cceL } }, + /* 46 << 91 */ + { { 0xec1d0a4856ef96a7L,0xb47eb848982bf842L,0x66deae32ec3f700dL, + 0x4e43c42caa1181e0L }, + { 0xa1d72a31d1a4aa2aL,0x440d4668c004f3ceL,0x0d6a2d3b45fe8a7aL, + 0x820e52e2fb128365L } }, + /* 47 << 91 */ + { { 0x29ac5fcf25e51b09L,0x180cd2bf2023d159L,0xa9892171a1ebf90eL, + 0xf97c4c877c132181L }, + { 0x9f1dc724c03dbb7eL,0xae043765018cbbe4L,0xfb0b2a360767d153L, + 0xa8e2f4d6249cbaebL } }, + /* 48 << 91 */ + { { 0x172a5247d95ea168L,0x1758fada2970764aL,0xac803a511d978169L, + 0x299cfe2ede77e01bL }, + { 0x652a1e17b0a98927L,0x2e26e1d120014495L,0x7ae0af9f7175b56aL, + 0xc2e22a80d64b9f95L } }, + /* 49 << 91 */ + { { 0x4d0ff9fbd90a060aL,0x496a27dbbaf38085L,0x32305401da776bcfL, + 0xb8cdcef6725f209eL }, + { 0x61ba0f37436a0bbaL,0x263fa10876860049L,0x92beb98eda3542cfL, + 0xa2d4d14ad5849538L } }, + /* 50 << 91 */ + { { 0x989b9d6812e9a1bcL,0x61d9075c5f6e3268L,0x352c6aa999ace638L, + 0xde4e4a55920f43ffL }, + { 0xe5e4144ad673c017L,0x667417ae6f6e05eaL,0x613416aedcd1bd56L, + 0x5eb3620186693711L } }, + /* 51 << 91 */ + { { 0x2d7bc5043a1aa914L,0x175a129976dc5975L,0xe900e0f23fc8125cL, + 0x569ef68c11198875L }, + { 0x9012db6363a113b4L,0xe3bd3f5698835766L,0xa5c94a5276412deaL, + 0xad9e2a09aa735e5cL } }, + /* 52 << 91 */ + { { 0x405a984c508b65e9L,0xbde4a1d16df1a0d1L,0x1a9433a1dfba80daL, + 0xe9192ff99440ad2eL }, + { 0x9f6496965099fe92L,0x25ddb65c0b27a54aL,0x178279ddc590da61L, + 0x5479a999fbde681aL } }, + /* 53 << 91 */ + { { 0xd0e84e05013fe162L,0xbe11dc92632d471bL,0xdf0b0c45fc0e089fL, + 0x04fb15b04c144025L }, + { 0xa61d5fc213c99927L,0xa033e9e03de2eb35L,0xf8185d5cb8dacbb4L, + 0x9a88e2658644549dL } }, + /* 54 << 91 */ + { { 0xf717af6254671ff6L,0x4bd4241b5fa58603L,0x06fba40be67773c0L, + 0xc1d933d26a2847e9L }, + { 0xf4f5acf3689e2c70L,0x92aab0e746bafd31L,0x798d76aa3473f6e5L, + 0xcc6641db93141934L } }, + /* 55 << 91 */ + { { 0xcae27757d31e535eL,0x04cc43b687c2ee11L,0x8d1f96752e029ffaL, + 0xc2150672e4cc7a2cL }, + { 0x3b03c1e08d68b013L,0xa9d6816fedf298f3L,0x1bfbb529a2804464L, + 0x95a52fae5db22125L } }, + /* 56 << 91 */ + { { 0x55b321600e1cb64eL,0x004828f67e7fc9feL,0x13394b821bb0fb93L, + 0xb6293a2d35f1a920L }, + { 0xde35ef21d145d2d9L,0xbe6225b3bb8fa603L,0x00fc8f6b32cf252dL, + 0xa28e52e6117cf8c2L } }, + /* 57 << 91 */ + { { 0x9d1dc89b4c371e6dL,0xcebe067536ef0f28L,0x5de05d09a4292f81L, + 0xa8303593353e3083L }, + { 0xa1715b0a7e37a9bbL,0x8c56f61e2b8faec3L,0x5250743133c9b102L, + 0x0130cefca44431f0L } }, + /* 58 << 91 */ + { { 0x56039fa0bd865cfbL,0x4b03e578bc5f1dd7L,0x40edf2e4babe7224L, + 0xc752496d3a1988f6L }, + { 0xd1572d3b564beb6bL,0x0db1d11039a1c608L,0x568d193416f60126L, + 0x05ae9668f354af33L } }, + /* 59 << 91 */ + { { 0x19de6d37c92544f2L,0xcc084353a35837d5L,0xcbb6869c1a514eceL, + 0xb633e7282e1d1066L }, + { 0xf15dd69f936c581cL,0x96e7b8ce7439c4f9L,0x5e676f482e448a5bL, + 0xb2ca7d5bfd916bbbL } }, + /* 60 << 91 */ + { { 0xd55a2541f5024025L,0x47bc5769e4c2d937L,0x7d31b92a0362189fL, + 0x83f3086eef7816f9L }, + { 0xf9f46d94b587579aL,0xec2d22d830e76c5fL,0x27d57461b000ffcfL, + 0xbb7e65f9364ffc2cL } }, + /* 61 << 91 */ + { { 0x7c7c94776652a220L,0x61618f89d696c981L,0x5021701d89effff3L, + 0xf2c8ff8e7c314163L }, + { 0x2da413ad8efb4d3eL,0x937b5adfce176d95L,0x22867d342a67d51cL, + 0x262b9b1018eb3ac9L } }, + /* 62 << 91 */ + { { 0x4e314fe4c43ff28bL,0x764766276a664e7aL,0x3e90e40bb7a565c2L, + 0x8588993ac1acf831L }, + { 0xd7b501d68f938829L,0x996627ee3edd7d4cL,0x37d44a6290cd34c7L, + 0xa8327499f3833e8dL } }, + /* 63 << 91 */ + { { 0x2e18917d4bf50353L,0x85dd726b556765fbL,0x54fe65d693d5ab66L, + 0x3ddbaced915c25feL }, + { 0xa799d9a412f22e85L,0xe2a248676d06f6bcL,0xf4f1ee5643ca1637L, + 0xfda2828b61ece30aL } }, + /* 64 << 91 */ + { { 0x758c1a3ea2dee7a6L,0xdcde2f3c734b2284L,0xaba445d24eaba6adL, + 0x35aaf66876cee0a7L }, + { 0x7e0b04a9e5aa049aL,0xe74083ad91103e84L,0xbeb183ce40afecc3L, + 0x6b89de9fea043f7aL } }, + /* 0 << 98 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 98 */ + { { 0x0e299d23fe67ba66L,0x9145076093cf2f34L,0xf45b5ea997fcf913L, + 0x5be008438bd7dddaL }, + { 0x358c3e05d53ff04dL,0xbf7ccdc35de91ef7L,0xad684dbfb69ec1a0L, + 0x367e7cf2801fd997L } }, + /* 2 << 98 */ + { { 0x0ca1f3b7b0dc8595L,0x27de46089f1d9f2eL,0x1af3bf39badd82a7L, + 0x79356a7965862448L }, + { 0xc0602345f5f9a052L,0x1a8b0f89139a42f9L,0xb53eee42844d40fcL, + 0x93b0bfe54e5b6368L } }, + /* 3 << 98 */ + { { 0x5434dd02c024789cL,0x90dca9ea41b57bfcL,0x8aa898e2243398dfL, + 0xf607c834894a94bbL }, + { 0xbb07be97c2c99b76L,0x6576ba6718c29302L,0x3d79efcce703a88cL, + 0xf259ced7b6a0d106L } }, + /* 4 << 98 */ + { { 0x0f893a5dc8de610bL,0xe8c515fb67e223ceL,0x7774bfa64ead6dc5L, + 0x89d20f95925c728fL }, + { 0x7a1e0966098583ceL,0xa2eedb9493f2a7d7L,0x1b2820974c304d4aL, + 0x0842e3dac077282dL } }, + /* 5 << 98 */ + { { 0xe4d972a33b9e2d7bL,0x7cc60b27c48218ffL,0x8fc7083884149d91L, + 0x5c04346f2f461eccL }, + { 0xebe9fdf2614650a9L,0x5e35b537c1f666acL,0x645613d188babc83L, + 0x88cace3ac5e1c93eL } }, + /* 6 << 98 */ + { { 0x209ca3753de92e23L,0xccb03cc85fbbb6e3L,0xccb90f03d7b1487eL, + 0xfa9c2a38c710941fL }, + { 0x756c38236724ceedL,0x3a902258192d0323L,0xb150e519ea5e038eL, + 0xdcba2865c7427591L } }, + /* 7 << 98 */ + { { 0xe549237f78890732L,0xc443bef953fcb4d9L,0x9884d8a6eb3480d6L, + 0x8a35b6a13048b186L }, + { 0xb4e4471665e9a90aL,0x45bf380d653006c0L,0x8f3f820d4fe9ae3bL, + 0x244a35a0979a3b71L } }, + /* 8 << 98 */ + { { 0xa1010e9d74cd06ffL,0x9c17c7dfaca3eeacL,0x74c86cd38063aa2bL, + 0x8595c4b3734614ffL }, + { 0xa3de00ca990f62ccL,0xd9bed213ca0c3be5L,0x7886078adf8ce9f5L, + 0xddb27ce35cd44444L } }, + /* 9 << 98 */ + { { 0xed374a6658926dddL,0x138b2d49908015b8L,0x886c6579de1f7ab8L, + 0x888b9aa0c3020b7aL }, + { 0xd3ec034e3a96e355L,0xba65b0b8f30fbe9aL,0x064c8e50ff21367aL, + 0x1f508ea40b04b46eL } }, + /* 10 << 98 */ + { { 0x98561a49747c866cL,0xbbb1e5fe0518a062L,0x20ff4e8becdc3608L, + 0x7f55cded20184027L }, + { 0x8d73ec95f38c85f0L,0x5b589fdf8bc3b8c3L,0xbe95dd980f12b66fL, + 0xf5bd1a090e338e01L } }, + /* 11 << 98 */ + { { 0x65163ae55e915918L,0x6158d6d986f8a46bL,0x8466b538eeebf99cL, + 0xca8761f6bca477efL }, + { 0xaf3449c29ebbc601L,0xef3b0f41e0c3ae2fL,0xaa6c577d5de63752L, + 0xe916660164682a51L } }, + /* 12 << 98 */ + { { 0x5a3097befc15aa1eL,0x40d12548b54b0745L,0x5bad4706519a5f12L, + 0xed03f717a439dee6L }, + { 0x0794bb6c4a02c499L,0xf725083dcffe71d2L,0x2cad75190f3adcafL, + 0x7f68ea1c43729310L } }, + /* 13 << 98 */ + { { 0xe747c8c7b7ffd977L,0xec104c3580761a22L,0x8395ebaf5a3ffb83L, + 0xfb3261f4e4b63db7L }, + { 0x53544960d883e544L,0x13520d708cc2eeb8L,0x08f6337bd3d65f99L, + 0x83997db2781cf95bL } }, + /* 14 << 98 */ + { { 0xce6ff1060dbd2c01L,0x4f8eea6b1f9ce934L,0x546f7c4b0e993921L, + 0x6236a3245e753fc7L }, + { 0x65a41f84a16022e9L,0x0c18d87843d1dbb2L,0x73c556402d4cef9cL, + 0xa042810870444c74L } }, + /* 15 << 98 */ + { { 0x68e4f15e9afdfb3cL,0x49a561435bdfb6dfL,0xa9bc1bd45f823d97L, + 0xbceb5970ea111c2aL }, + { 0x366b455fb269bbc4L,0x7cd85e1ee9bc5d62L,0xc743c41c4f18b086L, + 0xa4b4099095294fb9L } }, + /* 16 << 98 */ + { { 0x9c7c581d26ee8382L,0xcf17dcc5359d638eL,0xee8273abb728ae3dL, + 0x1d112926f821f047L }, + { 0x1149847750491a74L,0x687fa761fde0dfb9L,0x2c2580227ea435abL, + 0x6b8bdb9491ce7e3fL } }, + /* 17 << 98 */ + { { 0x4c5b5dc93bf834aaL,0x043718194f6c7e4bL,0xc284e00a3736bcadL, + 0x0d88111821ae8f8dL }, + { 0xf9cf0f82f48c8e33L,0xa11fd075a1bf40dbL,0xdceab0dedc2733e5L, + 0xc560a8b58e986bd7L } }, + /* 18 << 98 */ + { { 0x48dd1fe23929d097L,0x3885b29092f188f1L,0x0f2ae613da6fcdacL, + 0x9054303eb662a46cL }, + { 0xb6871e440738042aL,0x98e6a977bdaf6449L,0xd8bc0650d1c9df1bL, + 0xef3d645136e098f9L } }, + /* 19 << 98 */ + { { 0x03fbae82b6d72d28L,0x77ca9db1f5d84080L,0x8a112cffa58efc1cL, + 0x518d761cc564cb4aL }, + { 0x69b5740ef0d1b5ceL,0x717039cce9eb1785L,0x3fe29f9022f53382L, + 0x8e54ba566bc7c95cL } }, + /* 20 << 98 */ + { { 0x9c806d8af7f91d0fL,0x3b61b0f1a82a5728L,0x4640032d94d76754L, + 0x273eb5de47d834c6L }, + { 0x2988abf77b4e4d53L,0xb7ce66bfde401777L,0x9fba6b32715071b3L, + 0x82413c24ad3a1a98L } }, + /* 21 << 98 */ + { { 0x5b7fc8c4e0e8ad93L,0xb5679aee5fab868dL,0xb1f9d2fa2b3946f3L, + 0x458897dc5685b50aL }, + { 0x1e98c93089d0caf3L,0x39564c5f78642e92L,0x1b77729a0dbdaf18L, + 0xf9170722579e82e6L } }, + /* 22 << 98 */ + { { 0x680c0317e4515fa5L,0xf85cff84fb0c790fL,0xc7a82aab6d2e0765L, + 0x7446bca935c82b32L }, + { 0x5de607aa6d63184fL,0x7c1a46a8262803a6L,0xd218313daebe8035L, + 0x92113ffdc73c51f8L } }, + /* 23 << 98 */ + { { 0x4b38e08312e7e46cL,0x69d0a37a56126bd5L,0xfb3f324b73c07e04L, + 0xa0c22f678fda7267L }, + { 0x8f2c00514d2c7d8fL,0xbc45ced3cbe2cae5L,0xe1c6cf07a8f0f277L, + 0xbc3923121eb99a98L } }, + /* 24 << 98 */ + { { 0x75537b7e3cc8ac85L,0x8d725f57dd02753bL,0xfd05ff64b737df2fL, + 0x55fe8712f6d2531dL }, + { 0x57ce04a96ab6b01cL,0x69a02a897cd93724L,0x4f82ac35cf86699bL, + 0x8242d3ad9cb4b232L } }, + /* 25 << 98 */ + { { 0x713d0f65d62105e5L,0xbb222bfa2d29be61L,0xf2f9a79e6cfbef09L, + 0xfc24d8d3d5d6782fL }, + { 0x5db77085d4129967L,0xdb81c3ccdc3c2a43L,0x9d655fc005d8d9a3L, + 0x3f5d057a54298026L } }, + /* 26 << 98 */ + { { 0x1157f56d88c54694L,0xb26baba59b09573eL,0x2cab03b022adffd1L, + 0x60a412c8dd69f383L }, + { 0xed76e98b54b25039L,0xd4ee67d3687e714dL,0x877396487b00b594L, + 0xce419775c9ef709bL } }, + /* 27 << 98 */ + { { 0x40f76f851c203a40L,0x30d352d6eafd8f91L,0xaf196d3d95578dd2L, + 0xea4bb3d777cc3f3dL }, + { 0x42a5bd03b98e782bL,0xac958c400624920dL,0xb838134cfc56fcc8L, + 0x86ec4ccf89572e5eL } }, + /* 28 << 98 */ + { { 0x69c435269be47be0L,0x323b7dd8cb28fea1L,0xfa5538ba3a6c67e5L, + 0xef921d701d378e46L }, + { 0xf92961fc3c4b880eL,0x3f6f914e98940a67L,0xa990eb0afef0ff39L, + 0xa6c2920ff0eeff9cL } }, + /* 29 << 98 */ + { { 0xca80416651b8d9a3L,0x42531bc90ffb0db1L,0x72ce4718aa82e7ceL, + 0x6e199913df574741L }, + { 0xd5f1b13dd5d36946L,0x8255dc65f68f0194L,0xdc9df4cd8710d230L, + 0x3453c20f138c1988L } }, + /* 30 << 98 */ + { { 0x9af98dc089a6ef01L,0x4dbcc3f09857df85L,0x348056015c1ad924L, + 0x40448da5d0493046L }, + { 0xf629926d4ee343e2L,0x6343f1bd90e8a301L,0xefc9349140815b3fL, + 0xf882a423de8f66fbL } }, + /* 31 << 98 */ + { { 0x3a12d5f4e7db9f57L,0x7dfba38a3c384c27L,0x7a904bfd6fc660b1L, + 0xeb6c5db32773b21cL }, + { 0xc350ee661cdfe049L,0x9baac0ce44540f29L,0xbc57b6aba5ec6aadL, + 0x167ce8c30a7c1baaL } }, + /* 32 << 98 */ + { { 0xb23a03a553fb2b56L,0x6ce141e74e057f78L,0x796525c389e490d9L, + 0x0bc95725a31a7e75L }, + { 0x1ec567911220fd06L,0x716e3a3c408b0bd6L,0x31cd6bf7e8ebeba9L, + 0xa7326ca6bee6b670L } }, + /* 33 << 98 */ + { { 0x3d9f851ccd090c43L,0x561e8f13f12c3988L,0x50490b6a904b7be4L, + 0x61690ce10410737bL }, + { 0x299e9a370f009052L,0x258758f0f026092eL,0x9fa255f3fdfcdc0fL, + 0xdbc9fb1fc0e1bcd2L } }, + /* 34 << 98 */ + { { 0x35f9dd6e24651840L,0xdca45a84a5c59abcL,0x103d396fecca4938L, + 0x4532da0ab97b3f29L }, + { 0xc4135ea51999a6bfL,0x3aa9505a5e6bf2eeL,0xf77cef063f5be093L, + 0x97d1a0f8a943152eL } }, + /* 35 << 98 */ + { { 0x2cb0ebba2e1c21ddL,0xf41b29fc2c6797c4L,0xc6e17321b300101fL, + 0x4422b0e9d0d79a89L }, + { 0x49e4901c92f1bfc4L,0x06ab1f8fe1e10ed9L,0x84d35577db2926b8L, + 0xca349d39356e8ec2L } }, + /* 36 << 98 */ + { { 0x70b63d32343bf1a9L,0x8fd3bd2837d1a6b1L,0x0454879c316865b4L, + 0xee959ff6c458efa2L }, + { 0x0461dcf89706dc3fL,0x737db0e2164e4b2eL,0x092626802f8843c8L, + 0x54498bbc7745e6f6L } }, + /* 37 << 98 */ + { { 0x359473faa29e24afL,0xfcc3c45470aa87a1L,0xfd2c4bf500573aceL, + 0xb65b514e28dd1965L }, + { 0xe46ae7cf2193e393L,0x60e9a4e1f5444d97L,0xe7594e9600ff38edL, + 0x43d84d2f0a0e0f02L } }, + /* 38 << 98 */ + { { 0x8b6db141ee398a21L,0xb88a56aee3bcc5beL,0x0a1aa52f373460eaL, + 0x20da1a56160bb19bL }, + { 0xfb54999d65bf0384L,0x71a14d245d5a180eL,0xbc44db7b21737b04L, + 0xd84fcb1801dd8e92L } }, + /* 39 << 98 */ + { { 0x80de937bfa44b479L,0x535054995c98fd4fL,0x1edb12ab28f08727L, + 0x4c58b582a5f3ef53L }, + { 0xbfb236d88327f246L,0xc3a3bfaa4d7df320L,0xecd96c59b96024f2L, + 0xfc293a537f4e0433L } }, + /* 40 << 98 */ + { { 0x5341352b5acf6e10L,0xc50343fdafe652c3L,0x4af3792d18577a7fL, + 0xe1a4c617af16823dL }, + { 0x9b26d0cd33425d0aL,0x306399ed9b7bc47fL,0x2a792f33706bb20bL, + 0x3121961498111055L } }, + /* 41 << 98 */ + { { 0x864ec06487f5d28bL,0x11392d91962277fdL,0xb5aa7942bb6aed5fL, + 0x080094dc47e799d9L }, + { 0x4afa588c208ba19bL,0xd3e7570f8512f284L,0xcbae64e602f5799aL, + 0xdeebe7ef514b9492L } }, + /* 42 << 98 */ + { { 0x30300f98e5c298ffL,0x17f561be3678361fL,0xf52ff31298cb9a16L, + 0x6233c3bc5562d490L }, + { 0x7bfa15a192e3a2cbL,0x961bcfd1e6365119L,0x3bdd29bf2c8c53b1L, + 0x739704df822844baL } }, + /* 43 << 98 */ + { { 0x7dacfb587e7b754bL,0x23360791a806c9b9L,0xe7eb88c923504452L, + 0x2983e996852c1783L }, + { 0xdd4ae529958d881dL,0x026bae03262c7b3cL,0x3a6f9193960b52d1L, + 0xd0980f9092696cfbL } }, + /* 44 << 98 */ + { { 0x4c1f428cd5f30851L,0x94dfed272a4f6630L,0x4df53772fc5d48a4L, + 0xdd2d5a2f933260ceL }, + { 0x574115bdd44cc7a5L,0x4ba6b20dbd12533aL,0x30e93cb8243057c9L, + 0x794c486a14de320eL } }, + /* 45 << 98 */ + { { 0xe925d4cef21496e4L,0xf951d198ec696331L,0x9810e2de3e8d812fL, + 0xd0a47259389294abL }, + { 0x513ba2b50e3bab66L,0x462caff5abad306fL,0xe2dc6d59af04c49eL, + 0x1aeb8750e0b84b0bL } }, + /* 46 << 98 */ + { { 0xc034f12f2f7d0ca2L,0x6d2e8128e06acf2fL,0x801f4f8321facc2fL, + 0xa1170c03f40ef607L }, + { 0xfe0a1d4f7805a99cL,0xbde56a36cc26aba5L,0x5b1629d035531f40L, + 0xac212c2b9afa6108L } }, + /* 47 << 98 */ + { { 0x30a06bf315697be5L,0x6f0545dc2c63c7c1L,0x5d8cb8427ccdadafL, + 0xd52e379bac7015bbL }, + { 0xc4f56147f462c23eL,0xd44a429846bc24b0L,0xbc73d23ae2856d4fL, + 0x61cedd8c0832bcdfL } }, + /* 48 << 98 */ + { { 0x6095355699f241d7L,0xee4adbd7001a349dL,0x0b35bf6aaa89e491L, + 0x7f0076f4136f7546L }, + { 0xd19a18ba9264da3dL,0x6eb2d2cd62a7a28bL,0xcdba941f8761c971L, + 0x1550518ba3be4a5dL } }, + /* 49 << 98 */ + { { 0xd0e8e2f057d0b70cL,0xeea8612ecd133ba3L,0x814670f044416aecL, + 0x424db6c330775061L }, + { 0xd96039d116213fd1L,0xc61e7fa518a3478fL,0xa805bdcccb0c5021L, + 0xbdd6f3a80cc616ddL } }, + /* 50 << 98 */ + { { 0x060096675d97f7e2L,0x31db0fc1af0bf4b6L,0x23680ed45491627aL, + 0xb99a3c667d741fb1L }, + { 0xe9bb5f5536b1ff92L,0x29738577512b388dL,0xdb8a2ce750fcf263L, + 0x385346d46c4f7b47L } }, + /* 51 << 98 */ + { { 0xbe86c5ef31631f9eL,0xbf91da2103a57a29L,0xc3b1f7967b23f821L, + 0x0f7d00d2770db354L }, + { 0x8ffc6c3bd8fe79daL,0xcc5e8c40d525c996L,0x4640991dcfff632aL, + 0x64d97e8c67112528L } }, + /* 52 << 98 */ + { { 0xc232d97302f1cd1eL,0xce87eacb1dd212a4L,0x6e4c8c73e69802f7L, + 0x12ef02901fffddbdL }, + { 0x941ec74e1bcea6e2L,0xd0b540243cb92cbbL,0x809fb9d47e8f9d05L, + 0x3bf16159f2992aaeL } }, + /* 53 << 98 */ + { { 0xad40f279f8a7a838L,0x11aea63105615660L,0xbf52e6f1a01f6fa1L, + 0xef0469953dc2aec9L }, + { 0x785dbec9d8080711L,0xe1aec60a9fdedf76L,0xece797b5fa21c126L, + 0xc66e898f05e52732L } }, + /* 54 << 98 */ + { { 0x39bb69c408811fdbL,0x8bfe1ef82fc7f082L,0xc8e7a393174f4138L, + 0xfba8ad1dd58d1f98L }, + { 0xbc21d0cebfd2fd5bL,0x0b839a826ee60d61L,0xaacf7658afd22253L, + 0xb526bed8aae396b3L } }, + /* 55 << 98 */ + { { 0xccc1bbc238564464L,0x9e3ff9478c45bc73L,0xcde9bca358188a78L, + 0x138b8ee0d73bf8f7L }, + { 0x5c7e234c4123c489L,0x66e69368fa643297L,0x0629eeee39a15fa3L, + 0x95fab881a9e2a927L } }, + /* 56 << 98 */ + { { 0xb2497007eafbb1e1L,0xd75c9ce6e75b7a93L,0x3558352defb68d78L, + 0xa2f26699223f6396L }, + { 0xeb911ecfe469b17aL,0x62545779e72d3ec2L,0x8ea47de782cb113fL, + 0xebe4b0864e1fa98dL } }, + /* 57 << 98 */ + { { 0xec2d5ed78cdfedb1L,0xa535c077fe211a74L,0x9678109b11d244c5L, + 0xf17c8bfbbe299a76L }, + { 0xb651412efb11fbc4L,0xea0b548294ab3f65L,0xd8dffd950cf78243L, + 0x2e719e57ce0361d4L } }, + /* 58 << 98 */ + { { 0x9007f085304ddc5bL,0x095e8c6d4daba2eaL,0x5a33cdb43f9d28a9L, + 0x85b95cd8e2283003L }, + { 0xbcd6c819b9744733L,0x29c5f538fc7f5783L,0x6c49b2fad59038e4L, + 0x68349cc13bbe1018L } }, + /* 59 << 98 */ + { { 0xcc490c1d21830ee5L,0x36f9c4eee9bfa297L,0x58fd729448de1a94L, + 0xaadb13a84e8f2cdcL }, + { 0x515eaaa081313dbaL,0xc76bb468c2152dd8L,0x357f8d75a653dbf8L, + 0xe4d8c4d1b14ac143L } }, + /* 60 << 98 */ + { { 0xbdb8e675b055cb40L,0x898f8e7b977b5167L,0xecc65651b82fb863L, + 0x565448146d88f01fL }, + { 0xb0928e95263a75a9L,0xcfb6836f1a22fcdaL,0x651d14db3f3bd37cL, + 0x1d3837fbb6ad4664L } }, + /* 61 << 98 */ + { { 0x7c5fb538ff4f94abL,0x7243c7126d7fb8f2L,0xef13d60ca85c5287L, + 0x18cfb7c74bb8dd1bL }, + { 0x82f9bfe672908219L,0x35c4592b9d5144abL,0x52734f379cf4b42fL, + 0x6bac55e78c60ddc4L } }, + /* 62 << 98 */ + { { 0xb5cd811e94dea0f6L,0x259ecae4e18cc1a3L,0x6a0e836e15e660f8L, + 0x6c639ea60e02bff2L }, + { 0x8721b8cb7e1026fdL,0x9e73b50b63261942L,0xb8c7097477f01da3L, + 0x1839e6a68268f57fL } }, + /* 63 << 98 */ + { { 0x571b94155150b805L,0x1892389ef92c7097L,0x8d69c18e4a084b95L, + 0x7014c512be5b495cL }, + { 0x4780db361b07523cL,0x2f6219ce2c1c64faL,0xc38b81b0602c105aL, + 0xab4f4f205dc8e360L } }, + /* 64 << 98 */ + { { 0x20d3c982cf7d62d2L,0x1f36e29d23ba8150L,0x48ae0bf092763f9eL, + 0x7a527e6b1d3a7007L }, + { 0xb4a89097581a85e3L,0x1f1a520fdc158be5L,0xf98db37d167d726eL, + 0x8802786e1113e862L } }, + /* 0 << 105 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 105 */ + { { 0xefb2149e36f09ab0L,0x03f163ca4a10bb5bL,0xd029704506e20998L, + 0x56f0af001b5a3babL }, + { 0x7af4cfec70880e0dL,0x7332a66fbe3d913fL,0x32e6c84a7eceb4bdL, + 0xedc4a79a9c228f55L } }, + /* 2 << 105 */ + { { 0xc37c7dd0c55c4496L,0xa6a9635725bbabd2L,0x5b7e63f2add7f363L, + 0x9dce37822e73f1dfL }, + { 0xe1e5a16ab2b91f71L,0xe44898235ba0163cL,0xf2759c32f6e515adL, + 0xa5e2f1f88615eecfL } }, + /* 3 << 105 */ + { { 0x74519be7abded551L,0x03d358b8c8b74410L,0x4d00b10b0e10d9a9L, + 0x6392b0b128da52b7L }, + { 0x6744a2980b75c904L,0xc305b0aea8f7f96cL,0x042e421d182cf932L, + 0xf6fc5d509e4636caL } }, + /* 4 << 105 */ + { { 0x795847c9d64cc78cL,0x6c50621b9b6cb27bL,0x07099bf8df8022abL, + 0x48f862ebc04eda1dL }, + { 0xd12732ede1603c16L,0x19a80e0f5c9a9450L,0xe2257f54b429b4fcL, + 0x66d3b2c645460515L } }, + /* 5 << 105 */ + { { 0x6ca4f87e822e37beL,0x73f237b4253bda4eL,0xf747f3a241190aebL, + 0xf06fa36f804cf284L }, + { 0x0a6bbb6efc621c12L,0x5d624b6440b80ec6L,0x4b0724257ba556f3L, + 0x7fa0c3543e2d20a8L } }, + /* 6 << 105 */ + { { 0xe921fa31e3229d41L,0xa929c65294531bd4L,0x84156027a6d38209L, + 0xf3d69f736bdb97bdL }, + { 0x8906d19a16833631L,0x68a34c2e03d51be3L,0xcb59583b0e511cd8L, + 0x99ce6bfdfdc132a8L } }, + /* 7 << 105 */ + { { 0x3facdaaaffcdb463L,0x658bbc1a34a38b08L,0x12a801f8f1a9078dL, + 0x1567bcf96ab855deL }, + { 0xe08498e03572359bL,0xcf0353e58659e68bL,0xbb86e9c87d23807cL, + 0xbc08728d2198e8a2L } }, + /* 8 << 105 */ + { { 0x8de2b7bc453cadd6L,0x203900a7bc0bc1f8L,0xbcd86e47a6abd3afL, + 0x911cac128502effbL }, + { 0x2d550242ec965469L,0x0e9f769229e0017eL,0x633f078f65979885L, + 0xfb87d4494cf751efL } }, + /* 9 << 105 */ + { { 0xe1790e4bfc25419aL,0x364672034bff3cfdL,0xc8db638625b6e83fL, + 0x6cc69f236cad6fd2L }, + { 0x0219e45a6bc68bb9L,0xe43d79b6297f7334L,0x7d445368465dc97cL, + 0x4b9eea322a0b949aL } }, + /* 10 << 105 */ + { { 0x1b96c6ba6102d021L,0xeaafac782f4461eaL,0xd4b85c41c49f19a8L, + 0x275c28e4cf538875L }, + { 0x35451a9ddd2e54e0L,0x6991adb50605618bL,0x5b8b4bcd7b36cd24L, + 0x372a4f8c56f37216L } }, + /* 11 << 105 */ + { { 0xc890bd73a6a5da60L,0x6f083da0dc4c9ff0L,0xf4e14d94f0536e57L, + 0xf9ee1edaaaec8243L }, + { 0x571241ec8bdcf8e7L,0xa5db82710b041e26L,0x9a0b9a99e3fff040L, + 0xcaaf21dd7c271202L } }, + /* 12 << 105 */ + { { 0xb4e2b2e14f0dd2e8L,0xe77e7c4f0a377ac7L,0x69202c3f0d7a2198L, + 0xf759b7ff28200eb8L }, + { 0xc87526eddcfe314eL,0xeb84c52453d5cf99L,0xb1b52ace515138b6L, + 0x5aa7ff8c23fca3f4L } }, + /* 13 << 105 */ + { { 0xff0b13c3b9791a26L,0x960022dacdd58b16L,0xdbd55c9257aad2deL, + 0x3baaaaa3f30fe619L }, + { 0x9a4b23460d881efdL,0x506416c046325e2aL,0x91381e76035c18d4L, + 0xb3bb68bef27817b0L } }, + /* 14 << 105 */ + { { 0x15bfb8bf5116f937L,0x7c64a586c1268943L,0x71e25cc38419a2c8L, + 0x9fd6b0c48335f463L }, + { 0x4bf0ba3ce8ee0e0eL,0x6f6fba60298c21faL,0x57d57b39ae66bee0L, + 0x292d513022672544L } }, + /* 15 << 105 */ + { { 0xf451105dbab093b3L,0x012f59b902839986L,0x8a9158023474a89cL, + 0x048c919c2de03e97L }, + { 0xc476a2b591071cd5L,0x791ed89a034970a5L,0x89bd9042e1b7994bL, + 0x8eaf5179a1057ffdL } }, + /* 16 << 105 */ + { { 0x6066e2a2d551ee10L,0x87a8f1d8727e09a6L,0x00d08bab2c01148dL, + 0x6da8e4f1424f33feL }, + { 0x466d17f0cf9a4e71L,0xff5020103bf5cb19L,0xdccf97d8d062ecc0L, + 0x80c0d9af81d80ac4L } }, + /* 17 << 105 */ + { { 0xe87771d8033f2876L,0xb0186ec67d5cc3dbL,0x58e8bb803bc9bc1dL, + 0x4d1395cc6f6ef60eL }, + { 0xa73c62d6186244a0L,0x918e5f23110a5b53L,0xed4878ca741b7eabL, + 0x3038d71adbe03e51L } }, + /* 18 << 105 */ + { { 0x840204b7a93c3246L,0x21ab6069a0b9b4cdL,0xf5fa6e2bb1d64218L, + 0x1de6ad0ef3d56191L }, + { 0x570aaa88ff1929c7L,0xc6df4c6b640e87b5L,0xde8a74f2c65f0cccL, + 0x8b972fd5e6f6cc01L } }, + /* 19 << 105 */ + { { 0x3fff36b60b846531L,0xba7e45e610a5e475L,0x84a1d10e4145b6c5L, + 0xf1f7f91a5e046d9dL }, + { 0x0317a69244de90d7L,0x951a1d4af199c15eL,0x91f78046c9d73debL, + 0x74c82828fab8224fL } }, + /* 20 << 105 */ + { { 0xaa6778fce7560b90L,0xb4073e61a7e824ceL,0xff0d693cd642eba8L, + 0x7ce2e57a5dccef38L }, + { 0x89c2c7891df1ad46L,0x83a06922098346fdL,0x2d715d72da2fc177L, + 0x7b6dd71d85b6cf1dL } }, + /* 21 << 105 */ + { { 0xc60a6d0a73fa9cb0L,0xedd3992e328bf5a9L,0xc380ddd0832c8c82L, + 0xd182d410a2a0bf50L }, + { 0x7d9d7438d9a528dbL,0xe8b1a0e9caf53994L,0xddd6e5fe0e19987cL, + 0xacb8df03190b059dL } }, + /* 22 << 105 */ + { { 0x53703a328300129fL,0x1f63766268c43bfdL,0xbcbd191300e54051L, + 0x812fcc627bf5a8c5L }, + { 0x3f969d5f29fb85daL,0x72f4e00a694759e8L,0x426b6e52790726b7L, + 0x617bbc873bdbb209L } }, + /* 23 << 105 */ + { { 0x511f8bb997aee317L,0x812a4096e81536a8L,0x137dfe593ac09b9bL, + 0x0682238fba8c9a7aL }, + { 0x7072ead6aeccb4bdL,0x6a34e9aa692ba633L,0xc82eaec26fff9d33L, + 0xfb7535121d4d2b62L } }, + /* 24 << 105 */ + { { 0x1a0445ff1d7aadabL,0x65d38260d5f6a67cL,0x6e62fb0891cfb26fL, + 0xef1e0fa55c7d91d6L }, + { 0x47e7c7ba33db72cdL,0x017cbc09fa7c74b2L,0x3c931590f50a503cL, + 0xcac54f60616baa42L } }, + /* 25 << 105 */ + { { 0x9b6cd380b2369f0fL,0x97d3a70d23c76151L,0x5f9dd6fc9862a9c6L, + 0x044c4ab212312f51L }, + { 0x035ea0fd834a2ddcL,0x49e6b862cc7b826dL,0xb03d688362fce490L, + 0x62f2497ab37e36e9L } }, + /* 26 << 105 */ + { { 0x04b005b6c6458293L,0x36bb5276e8d10af7L,0xacf2dc138ee617b8L, + 0x470d2d35b004b3d4L }, + { 0x06790832feeb1b77L,0x2bb75c3985657f9cL,0xd70bd4edc0f60004L, + 0xfe797ecc219b018bL } }, + /* 27 << 105 */ + { { 0x9b5bec2a753aebccL,0xdaf9f3dcc939eca5L,0xd6bc6833d095ad09L, + 0x98abdd51daa4d2fcL }, + { 0xd9840a318d168be5L,0xcf7c10e02325a23cL,0xa5c02aa07e6ecfafL, + 0x2462e7e6b5bfdf18L } }, + /* 28 << 105 */ + { { 0xab2d8a8ba0cc3f12L,0x68dd485dbc672a29L,0x72039752596f2cd3L, + 0x5d3eea67a0cf3d8dL }, + { 0x810a1a81e6602671L,0x8f144a4014026c0cL,0xbc753a6d76b50f85L, + 0xc4dc21e8645cd4a4L } }, + /* 29 << 105 */ + { { 0xc5262dea521d0378L,0x802b8e0e05011c6fL,0x1ba19cbb0b4c19eaL, + 0x21db64b5ebf0aaecL }, + { 0x1f394ee970342f9dL,0x93a10aee1bc44a14L,0xa7eed31b3efd0baaL, + 0x6e7c824e1d154e65L } }, + /* 30 << 105 */ + { { 0xee23fa819966e7eeL,0x64ec4aa805b7920dL,0x2d44462d2d90aad4L, + 0xf44dd195df277ad5L }, + { 0x8d6471f1bb46b6a1L,0x1e65d313fd885090L,0x33a800f513a977b4L, + 0xaca9d7210797e1efL } }, + /* 31 << 105 */ + { { 0x9a5a85a0fcff6a17L,0x9970a3f31eca7ceeL,0xbb9f0d6bc9504be3L, + 0xe0c504beadd24ee2L }, + { 0x7e09d95677fcc2f4L,0xef1a522765bb5fc4L,0x145d4fb18b9286aaL, + 0x66fd0c5d6649028bL } }, + /* 32 << 105 */ + { { 0x98857ceb1bf4581cL,0xe635e186aca7b166L,0x278ddd22659722acL, + 0xa0903c4c1db68007L }, + { 0x366e458948f21402L,0x31b49c14b96abda2L,0x329c4b09e0403190L, + 0x97197ca3d29f43feL } }, + /* 33 << 105 */ + { { 0x8073dd1e274983d8L,0xda1a3bde55717c8fL,0xfd3d4da20361f9d1L, + 0x1332d0814c7de1ceL }, + { 0x9b7ef7a3aa6d0e10L,0x17db2e73f54f1c4aL,0xaf3dffae4cd35567L, + 0xaaa2f406e56f4e71L } }, + /* 34 << 105 */ + { { 0x8966759e7ace3fc7L,0x9594eacf45a8d8c6L,0x8de3bd8b91834e0eL, + 0xafe4ca53548c0421L }, + { 0xfdd7e856e6ee81c6L,0x8f671beb6b891a3aL,0xf7a58f2bfae63829L, + 0x9ab186fb9c11ac9fL } }, + /* 35 << 105 */ + { { 0x8d6eb36910b5be76L,0x046b7739fb040bcdL,0xccb4529fcb73de88L, + 0x1df0fefccf26be03L }, + { 0xad7757a6bcfcd027L,0xa8786c75bb3165caL,0xe9db1e347e99a4d9L, + 0x99ee86dfb06c504bL } }, + /* 36 << 105 */ + { { 0x5b7c2dddc15c9f0aL,0xdf87a7344295989eL,0x59ece47c03d08fdaL, + 0xb074d3ddad5fc702L }, + { 0x2040790351a03776L,0x2bb1f77b2a608007L,0x25c58f4fe1153185L, + 0xe6df62f6766e6447L } }, + /* 37 << 105 */ + { { 0xefb3d1beed51275aL,0x5de47dc72f0f483fL,0x7932d98e97c2bedfL, + 0xd5c119270219f8a1L }, + { 0x9d751200a73a294eL,0x5f88434a9dc20172L,0xd28d9fd3a26f506aL, + 0xa890cd319d1dcd48L } }, + /* 38 << 105 */ + { { 0x0aebaec170f4d3b4L,0xfd1a13690ffc8d00L,0xb9d9c24057d57838L, + 0x45929d2668bac361L }, + { 0x5a2cd06025b15ca6L,0x4b3c83e16e474446L,0x1aac7578ee1e5134L, + 0xa418f5d6c91e2f41L } }, + /* 39 << 105 */ + { { 0x6936fc8a213ed68bL,0x860ae7ed510a5224L,0x63660335def09b53L, + 0x641b2897cd79c98dL }, + { 0x29bd38e101110f35L,0x79c26f42648b1937L,0x64dae5199d9164f4L, + 0xd85a23100265c273L } }, + /* 40 << 105 */ + { { 0x7173dd5d4b07e2b1L,0xd144c4cb8d9ea221L,0xe8b04ea41105ab14L, + 0x92dda542fe80d8f1L }, + { 0xe9982fa8cf03dce6L,0x8b5ea9651a22cffcL,0xf7f4ea7f3fad88c4L, + 0x62db773e6a5ba95cL } }, + /* 41 << 105 */ + { { 0xd20f02fb93f24567L,0xfd46c69a315257caL,0x0ac74cc78bcab987L, + 0x46f31c015ceca2f5L }, + { 0x40aedb59888b219eL,0xe50ecc37e1fccd02L,0x1bcd9dad911f816cL, + 0x583cc1ec8db9b00cL } }, + /* 42 << 105 */ + { { 0xf3cd2e66a483bf11L,0xfa08a6f5b1b2c169L,0xf375e2454be9fa28L, + 0x99a7ffec5b6d011fL }, + { 0x6a3ebddbc4ae62daL,0x6cea00ae374aef5dL,0xab5fb98d9d4d05bcL, + 0x7cba1423d560f252L } }, + /* 43 << 105 */ + { { 0x49b2cc21208490deL,0x1ca66ec3bcfb2879L,0x7f1166b71b6fb16fL, + 0xfff63e0865fe5db3L }, + { 0xb8345abe8b2610beL,0xb732ed8039de3df4L,0x0e24ed50211c32b4L, + 0xd10d8a69848ff27dL } }, + /* 44 << 105 */ + { { 0xc1074398ed4de248L,0xd7cedace10488927L,0xa4aa6bf885673e13L, + 0xb46bae916daf30afL }, + { 0x07088472fcef7ad8L,0x61151608d4b35e97L,0xbcfe8f26dde29986L, + 0xeb84c4c7d5a34c79L } }, + /* 45 << 105 */ + { { 0xc1eec55c164e1214L,0x891be86da147bb03L,0x9fab4d100ba96835L, + 0xbf01e9b8a5c1ae9fL }, + { 0x6b4de139b186ebc0L,0xd5c74c2685b91bcaL,0x5086a99cc2d93854L, + 0xeed62a7ba7a9dfbcL } }, + /* 46 << 105 */ + { { 0x8778ed6f76b7618aL,0xbff750a503b66062L,0x4cb7be22b65186dbL, + 0x369dfbf0cc3a6d13L }, + { 0xc7dab26c7191a321L,0x9edac3f940ed718eL,0xbc142b36d0cfd183L, + 0xc8af82f67c991693L } }, + /* 47 << 105 */ + { { 0xb3d1e4d897ce0b2aL,0xe6d7c87fc3a55cdfL,0x35846b9568b81afeL, + 0x018d12afd3c239d8L }, + { 0x2b2c620801206e15L,0xe0e42453a3b882c6L,0x854470a3a50162d5L, + 0x081574787017a62aL } }, + /* 48 << 105 */ + { { 0x18bd3fb4820357c7L,0x992039ae6f1458adL,0x9a1df3c525b44aa1L, + 0x2d780357ed3d5281L }, + { 0x58cf7e4dc77ad4d4L,0xd49a7998f9df4fc4L,0x4465a8b51d71205eL, + 0xa0ee0ea6649254aaL } }, + /* 49 << 105 */ + { { 0x4b5eeecfab7bd771L,0x6c87307335c262b9L,0xdc5bd6483c9d61e7L, + 0x233d6d54321460d2L }, + { 0xd20c5626fc195bccL,0x2544595804d78b63L,0xe03fcb3d17ec8ef3L, + 0x54b690d146b8f781L } }, + /* 50 << 105 */ + { { 0x82fa2c8a21230646L,0xf51aabb9084f418cL,0xff4fbec11a30ba43L, + 0x6a5acf73743c9df7L }, + { 0x1da2b357d635b4d5L,0xc3de68ddecd5c1daL,0xa689080bd61af0ddL, + 0xdea5938ad665bf99L } }, + /* 51 << 105 */ + { { 0x0231d71afe637294L,0x01968aa6a5a81cd8L,0x11252d50048e63b5L, + 0xc446bc526ca007e9L }, + { 0xef8c50a696d6134bL,0x9361fbf59e09a05cL,0xf17f85a6dca3291aL, + 0xb178d548ff251a21L } }, + /* 52 << 105 */ + { { 0x87f6374ba4df3915L,0x566ce1bf2fd5d608L,0x425cba4d7de35102L, + 0x6b745f8f58c5d5e2L }, + { 0x88402af663122edfL,0x3190f9ed3b989a89L,0x4ad3d387ebba3156L, + 0xef385ad9c7c469a5L } }, + /* 53 << 105 */ + { { 0xb08281de3f642c29L,0x20be0888910ffb88L,0xf353dd4ad5292546L, + 0x3f1627de8377a262L }, + { 0xa5faa013eefcd638L,0x8f3bf62674cc77c3L,0x32618f65a348f55eL, + 0x5787c0dc9fefeb9eL } }, + /* 54 << 105 */ + { { 0xf1673aa2d9a23e44L,0x88dfa9934e10690dL,0x1ced1b362bf91108L, + 0x9193ceca3af48649L }, + { 0xfb34327d2d738fc5L,0x6697b037975fee6cL,0x2f485da0c04079a5L, + 0x2cdf57352feaa1acL } }, + /* 55 << 105 */ + { { 0x76944420bd55659eL,0x7973e32b4376090cL,0x86bb4fe1163b591aL, + 0x10441aedc196f0caL }, + { 0x3b431f4a045ad915L,0x6c11b437a4afacb1L,0x30b0c7db71fdbbd8L, + 0xb642931feda65acdL } }, + /* 56 << 105 */ + { { 0x4baae6e89c92b235L,0xa73bbd0e6b3993a1L,0xd06d60ec693dd031L, + 0x03cab91b7156881cL }, + { 0xd615862f1db3574bL,0x485b018564bb061aL,0x27434988a0181e06L, + 0x2cd61ad4c1c0c757L } }, + /* 57 << 105 */ + { { 0x3effed5a2ff9f403L,0x8dc98d8b62239029L,0x2206021e1f17b70dL, + 0xafbec0cabf510015L }, + { 0x9fed716480130dfaL,0x306dc2b58a02dcf5L,0x48f06620feb10fc0L, + 0x78d1e1d55a57cf51L } }, + /* 58 << 105 */ + { { 0xadef8c5a192ef710L,0x88afbd4b3b7431f9L,0x7e1f740764250c9eL, + 0x6e31318db58bec07L }, + { 0xfd4fc4b824f89b4eL,0x65a5dd8848c36a2aL,0x4f1eccfff024baa7L, + 0x22a21cf2cba94650L } }, + /* 59 << 105 */ + { { 0x95d29dee42a554f7L,0x828983a5002ec4baL,0x8112a1f78badb73dL, + 0x79ea8897a27c1839L }, + { 0x8969a5a7d065fd83L,0xf49af791b262a0bcL,0xfcdea8b6af2b5127L, + 0x10e913e1564c2dbcL } }, + /* 60 << 105 */ + { { 0x51239d14bc21ef51L,0xe51c3ceb4ce57292L,0x795ff06847bbcc3bL, + 0x86b46e1ebd7e11e6L }, + { 0x0ea6ba2380041ef4L,0xd72fe5056262342eL,0x8abc6dfd31d294d4L, + 0xbbe017a21278c2c9L } }, + /* 61 << 105 */ + { { 0xb1fcfa09b389328aL,0x322fbc62d01771b5L,0x04c0d06360b045bfL, + 0xdb652edc10e52d01L }, + { 0x50ef932c03ec6627L,0xde1b3b2dc1ee50e3L,0x5ab7bdc5dc37a90dL, + 0xfea6721331e33a96L } }, + /* 62 << 105 */ + { { 0x6482b5cb4f2999aaL,0x38476cc6b8cbf0ddL,0x93ebfacb173405bbL, + 0x15cdafe7e52369ecL }, + { 0xd42d5ba4d935b7dbL,0x648b60041c99a4cdL,0x785101bda3b5545bL, + 0x4bf2c38a9dd67fafL } }, + /* 63 << 105 */ + { { 0xb1aadc634442449cL,0xe0e9921a33ad4fb8L,0x5c552313aa686d82L, + 0xdee635fa465d866cL }, + { 0xbc3c224a18ee6e8aL,0xeed748a6ed42e02fL,0xe70f930ad474cd08L, + 0x774ea6ecfff24adfL } }, + /* 64 << 105 */ + { { 0x03e2de1cf3480d4aL,0xf0d8edc7bc8acf1aL,0xf23e330368295a9cL, + 0xfadd5f68c546a97dL }, + { 0x895597ad96f8acb1L,0xbddd49d5671bdae2L,0x16fcd52821dd43f4L, + 0xa5a454126619141aL } }, + /* 0 << 112 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 112 */ + { { 0x8ce9b6bfc360e25aL,0xe6425195075a1a78L,0x9dc756a8481732f4L, + 0x83c0440f5432b57aL }, + { 0xc670b3f1d720281fL,0x2205910ed135e051L,0xded14b0edb052be7L, + 0x697b3d27c568ea39L } }, + /* 2 << 112 */ + { { 0x2e599b9afb3ff9edL,0x28c2e0ab17f6515cL,0x1cbee4fd474da449L, + 0x071279a44f364452L }, + { 0x97abff6601fbe855L,0x3ee394e85fda51c4L,0x190385f667597c0bL, + 0x6e9fccc6a27ee34bL } }, + /* 3 << 112 */ + { { 0x0b89de9314092ebbL,0xf17256bd428e240cL,0xcf89a7f393d2f064L, + 0x4f57841ee1ed3b14L }, + { 0x4ee14405e708d855L,0x856aae7203f1c3d0L,0xc8e5424fbdd7eed5L, + 0x3333e4ef73ab4270L } }, + /* 4 << 112 */ + { { 0x3bc77adedda492f8L,0xc11a3aea78297205L,0x5e89a3e734931b4cL, + 0x17512e2e9f5694bbL }, + { 0x5dc349f3177bf8b6L,0x232ea4ba08c7ff3eL,0x9c4f9d16f511145dL, + 0xccf109a333b379c3L } }, + /* 5 << 112 */ + { { 0xe75e7a88a1f25897L,0x7ac6961fa1b5d4d8L,0xe3e1077308f3ed5cL, + 0x208a54ec0a892dfbL }, + { 0xbe826e1978660710L,0x0cf70a97237df2c8L,0x418a7340ed704da5L, + 0xa3eeb9a908ca33fdL } }, + /* 6 << 112 */ + { { 0x49d96233169bca96L,0x04d286d42da6aafbL,0xc09606eca0c2fa94L, + 0x8869d0d523ff0fb3L }, + { 0xa99937e5d0150d65L,0xa92e2503240c14c9L,0x656bf945108e2d49L, + 0x152a733aa2f59e2bL } }, + /* 7 << 112 */ + { { 0xb4323d588434a920L,0xc0af8e93622103c5L,0x667518ef938dbf9aL, + 0xa184307383a9cdf2L }, + { 0x350a94aa5447ab80L,0xe5e5a325c75a3d61L,0x74ba507f68411a9eL, + 0x10581fc1594f70c5L } }, + /* 8 << 112 */ + { { 0x60e2857080eb24a9L,0x7bedfb4d488e0cfdL,0x721ebbd7c259cdb8L, + 0x0b0da855bc6390a9L }, + { 0x2b4d04dbde314c70L,0xcdbf1fbc6c32e846L,0x33833eabb162fc9eL, + 0x9939b48bb0dd3ab7L } }, + /* 9 << 112 */ + { { 0x5aaa98a7cb0c9c8cL,0x75105f3081c4375cL,0xceee50575ef1c90fL, + 0xb31e065fc23a17bfL }, + { 0x5364d275d4b6d45aL,0xd363f3ad62ec8996L,0xb5d212394391c65bL, + 0x84564765ebb41b47L } }, + /* 10 << 112 */ + { { 0x20d18ecc37107c78L,0xacff3b6b570c2a66L,0x22f975d99bd0d845L, + 0xef0a0c46ba178fa0L }, + { 0x1a41965176b6028eL,0xc49ec674248612d4L,0x5b6ac4f27338af55L, + 0x06145e627bee5a36L } }, + /* 11 << 112 */ + { { 0x33e95d07e75746b5L,0x1c1e1f6dc40c78beL,0x967833ef222ff8e2L, + 0x4bedcf6ab49180adL }, + { 0x6b37e9c13d7a4c8aL,0x2748887c6ddfe760L,0xf7055123aa3a5bbcL, + 0x954ff2257bbb8e74L } }, + /* 12 << 112 */ + { { 0xc42b8ab197c3dfb9L,0x55a549b0cf168154L,0xad6748e7c1b50692L, + 0x2775780f6fc5cbcbL }, + { 0x4eab80b8e1c9d7c8L,0x8c69dae13fdbcd56L,0x47e6b4fb9969eaceL, + 0x002f1085a705cb5aL } }, + /* 13 << 112 */ + { { 0x4e23ca446d3fea55L,0xb4ae9c86f4810568L,0x47bfb91b2a62f27dL, + 0x60deb4c9d9bac28cL }, + { 0xa892d8947de6c34cL,0x4ee682594494587dL,0x914ee14e1a3f8a5bL, + 0xbb113eaa28700385L } }, + /* 14 << 112 */ + { { 0x81ca03b92115b4c9L,0x7c163d388908cad1L,0xc912a118aa18179aL, + 0xe09ed750886e3081L }, + { 0xa676e3fa26f516caL,0x753cacf78e732f91L,0x51592aea833da8b4L, + 0xc626f42f4cbea8aaL } }, + /* 15 << 112 */ + { { 0xef9dc899a7b56eafL,0x00c0e52c34ef7316L,0x5b1e4e24fe818a86L, + 0x9d31e20dc538be47L }, + { 0x22eb932d3ed68974L,0xe44bbc087c4e87c4L,0x4121086e0dde9aefL, + 0x8e6b9cff134f4345L } }, + /* 16 << 112 */ + { { 0x96892c1f711b0eb9L,0xb905f2c8780ab954L,0xace26309a20792dbL, + 0xec8ac9b30684e126L }, + { 0x486ad8b6b40a2447L,0x60121fc19fe3fb24L,0x5626fccf1a8e3b3fL, + 0x4e5686226ad1f394L } }, + /* 17 << 112 */ + { { 0xda7aae0d196aa5a1L,0xe0df8c771041b5fbL,0x451465d926b318b7L, + 0xc29b6e557ab136e9L }, + { 0x2c2ab48b71148463L,0xb5738de364454a76L,0x54ccf9a05a03abe4L, + 0x377c02960427d58eL } }, + /* 18 << 112 */ + { { 0x73f5f0b92bb39c1fL,0x14373f2ce608d8c5L,0xdcbfd31400fbb805L, + 0xdf18fb2083afdcfbL }, + { 0x81a57f4242b3523fL,0xe958532d87f650fbL,0xaa8dc8b68b0a7d7cL, + 0x1b75dfb7150166beL } }, + /* 19 << 112 */ + { { 0x90e4f7c92d7d1413L,0x67e2d6b59834f597L,0x4fd4f4f9a808c3e8L, + 0xaf8237e0d5281ec1L }, + { 0x25ab5fdc84687ceeL,0xc5ded6b1a5b26c09L,0x8e4a5aecc8ea7650L, + 0x23b73e5c14cc417fL } }, + /* 20 << 112 */ + { { 0x2bfb43183037bf52L,0xb61e6db578c725d7L,0x8efd4060bbb3e5d7L, + 0x2e014701dbac488eL }, + { 0xac75cf9a360aa449L,0xb70cfd0579634d08L,0xa591536dfffb15efL, + 0xb2c37582d07c106cL } }, + /* 21 << 112 */ + { { 0xb4293fdcf50225f9L,0xc52e175cb0e12b03L,0xf649c3bad0a8bf64L, + 0x745a8fefeb8ae3c6L }, + { 0x30d7e5a358321bc3L,0xb1732be70bc4df48L,0x1f217993e9ea5058L, + 0xf7a71cde3e4fd745L } }, + /* 22 << 112 */ + { { 0x86cc533e894c5bbbL,0x6915c7d969d83082L,0xa6aa2d055815c244L, + 0xaeeee59249b22ce5L }, + { 0x89e39d1378135486L,0x3a275c1f16b76f2fL,0xdb6bcc1be036e8f5L, + 0x4df69b215e4709f5L } }, + /* 23 << 112 */ + { { 0xa188b2502d0f39aaL,0x622118bb15a85947L,0x2ebf520ffde0f4faL, + 0xa40e9f294860e539L }, + { 0x7b6a51eb22b57f0fL,0x849a33b97e80644aL,0x50e5d16f1cf095feL, + 0xd754b54eec55f002L } }, + /* 24 << 112 */ + { { 0x5cfbbb22236f4a98L,0x0b0c59e9066800bbL,0x4ac69a8f5a9a7774L, + 0x2b33f804d6bec948L }, + { 0xb372929532e6c466L,0x68956d0f4e599c73L,0xa47a249f155c31ccL, + 0x24d80f0de1ce284eL } }, + /* 25 << 112 */ + { { 0xcd821dfb988baf01L,0xe6331a7ddbb16647L,0x1eb8ad33094cb960L, + 0x593cca38c91bbca5L }, + { 0x384aac8d26567456L,0x40fa0309c04b6490L,0x97834cd6dab6c8f6L, + 0x68a7318d3f91e55fL } }, + /* 26 << 112 */ + { { 0xa00fd04efc4d3157L,0xb56f8ab22bf3bdeaL,0x014f56484fa57172L, + 0x948c5860450abdb3L }, + { 0x342b5df00ebd4f08L,0x3e5168cd0e82938eL,0x7aedc1ceb0df5dd0L, + 0x6bbbc6d9e5732516L } }, + /* 27 << 112 */ + { { 0xc7bfd486605daaa6L,0x46fd72b7bb9a6c9eL,0xe4847fb1a124fb89L, + 0x75959cbda2d8ffbcL }, + { 0x42579f65c8a588eeL,0x368c92e6b80b499dL,0xea4ef6cd999a5df1L, + 0xaa73bb7f936fe604L } }, + /* 28 << 112 */ + { { 0xf347a70d6457d188L,0x86eda86b8b7a388bL,0xb7cdff060ccd6013L, + 0xbeb1b6c7d0053fb2L }, + { 0x0b02238799240a9fL,0x1bbb384f776189b2L,0x8695e71e9066193aL, + 0x2eb5009706ffac7eL } }, + /* 29 << 112 */ + { { 0x0654a9c04a7d2caaL,0x6f3fb3d1a5aaa290L,0x835db041ff476e8fL, + 0x540b8b0bc42295e4L }, + { 0xa5c73ac905e214f5L,0x9a74075a56a0b638L,0x2e4b1090ce9e680bL, + 0x57a5b4796b8d9afaL } }, + /* 30 << 112 */ + { { 0x0dca48e726bfe65cL,0x097e391c7290c307L,0x683c462e6669e72eL, + 0xf505be1e062559acL }, + { 0x5fbe3ea1e3a3035aL,0x6431ebf69cd50da8L,0xfd169d5c1f6407f2L, + 0x8d838a9560fce6b8L } }, + /* 31 << 112 */ + { { 0x2a2bfa7f650006f0L,0xdfd7dad350c0fbb2L,0x92452495ccf9ad96L, + 0x183bf494d95635f9L }, + { 0x02d5df434a7bd989L,0x505385cca5431095L,0xdd98e67dfd43f53eL, + 0xd61e1a6c500c34a9L } }, + /* 32 << 112 */ + { { 0x5a4b46c64a8a3d62L,0x8469c4d0247743d2L,0x2bb3a13d88f7e433L, + 0x62b23a1001be5849L }, + { 0xe83596b4a63d1a4cL,0x454e7fea7d183f3eL,0x643fce6117afb01cL, + 0x4e65e5e61c4c3638L } }, + /* 33 << 112 */ + { { 0x41d85ea1ef74c45bL,0x2cfbfa66ae328506L,0x98b078f53ada7da9L, + 0xd985fe37ec752fbbL }, + { 0xeece68fe5a0148b4L,0x6f9a55c72d78136dL,0x232dccc4d2b729ceL, + 0xa27e0dfd90aafbc4L } }, + /* 34 << 112 */ + { { 0x9647445212b4603eL,0xa876c5516b706d14L,0xdf145fcf69a9d412L, + 0xe2ab75b72d479c34L }, + { 0x12df9a761a23ff97L,0xc61389925d359d10L,0x6e51c7aefa835f22L, + 0x69a79cb1c0fcc4d9L } }, + /* 35 << 112 */ + { { 0xf57f350d594cc7e1L,0x3079ca633350ab79L,0x226fb6149aff594aL, + 0x35afec026d59a62bL }, + { 0x9bee46f406ed2c6eL,0x58da17357d939a57L,0x44c504028fd1797eL, + 0xd8853e7c5ccea6caL } }, + /* 36 << 112 */ + { { 0x4065508da35fcd5fL,0x8965df8c495ccaebL,0x0f2da85012e1a962L, + 0xee471b94c1cf1cc4L }, + { 0xcef19bc80a08fb75L,0x704958f581de3591L,0x2867f8b23aef4f88L, + 0x8d749384ea9f9a5fL } }, + /* 37 << 112 */ + { { 0x1b3855378c9049f4L,0x5be948f37b92d8b6L,0xd96f725db6e2bd6bL, + 0x37a222bc958c454dL }, + { 0xe7c61abb8809bf61L,0x46f07fbc1346f18dL,0xfb567a7ae87c0d1cL, + 0x84a461c87ef3d07aL } }, + /* 38 << 112 */ + { { 0x0a5adce6d9278d98L,0x24d948139dfc73e1L,0x4f3528b6054321c3L, + 0x2e03fdde692ea706L }, + { 0x10e6061947b533c0L,0x1a8bc73f2ca3c055L,0xae58d4b21bb62b8fL, + 0xb2045a73584a24e3L } }, + /* 39 << 112 */ + { { 0x3ab3d5afbd76e195L,0x478dd1ad6938a810L,0x6ffab3936ee3d5cbL, + 0xdfb693db22b361e4L }, + { 0xf969449651dbf1a7L,0xcab4b4ef08a2e762L,0xe8c92f25d39bba9aL, + 0x850e61bcf1464d96L } }, + /* 40 << 112 */ + { { 0xb7e830e3dc09508bL,0xfaf6d2cf74317655L,0x72606cebdf690355L, + 0x48bb92b3d0c3ded6L }, + { 0x65b754845c7cf892L,0xf6cd7ac9d5d5f01fL,0xc2c30a5996401d69L, + 0x91268650ed921878L } }, + /* 41 << 112 */ + { { 0x380bf913b78c558fL,0x43c0baebc8afdaa9L,0x377f61d554f169d3L, + 0xf8da07e3ae5ff20bL }, + { 0xb676c49da8a90ea8L,0x81c1ff2b83a29b21L,0x383297ac2ad8d276L, + 0x3001122fba89f982L } }, + /* 42 << 112 */ + { { 0xe1d794be6718e448L,0x246c14827c3e6e13L,0x56646ef85d26b5efL, + 0x80f5091e88069cddL }, + { 0xc5992e2f724bdd38L,0x02e915b48471e8c7L,0x96ff320a0d0ff2a9L, + 0xbf8864874384d1a0L } }, + /* 43 << 112 */ + { { 0xbbe1e6a6c93f72d6L,0xd5f75d12cad800eaL,0xfa40a09fe7acf117L, + 0x32c8cdd57581a355L }, + { 0x742219927023c499L,0xa8afe5d738ec3901L,0x5691afcba90e83f0L, + 0x41bcaa030b8f8eacL } }, + /* 44 << 112 */ + { { 0xe38b5ff98d2668d5L,0x0715281a7ad81965L,0x1bc8fc7c03c6ce11L, + 0xcbbee6e28b650436L }, + { 0x06b00fe80cdb9808L,0x17d6e066fe3ed315L,0x2e9d38c64d0b5018L, + 0xab8bfd56844dcaefL } }, + /* 45 << 112 */ + { { 0x42894a59513aed8bL,0xf77f3b6d314bd07aL,0xbbdecb8f8e42b582L, + 0xf10e2fa8d2390fe6L }, + { 0xefb9502262a2f201L,0x4d59ea5050ee32b0L,0xd87f77286da789a8L, + 0xcf98a2cff79492c4L } }, + /* 46 << 112 */ + { { 0xf9577239720943c2L,0xba044cf53990b9d0L,0x5aa8e82395f2884aL, + 0x834de6ed0278a0afL }, + { 0xc8e1ee9a5f25bd12L,0x9259ceaa6f7ab271L,0x7e6d97a277d00b76L, + 0x5c0c6eeaa437832aL } }, + /* 47 << 112 */ + { { 0x5232c20f5606b81dL,0xabd7b3750d991ee5L,0x4d2bfe358632d951L, + 0x78f8514698ed9364L }, + { 0x951873f0f30c3282L,0x0da8ac80a789230bL,0x3ac7789c5398967fL, + 0xa69b8f7fbdda0fb5L } }, + /* 48 << 112 */ + { { 0xe5db77176add8545L,0x1b71cb6672c49b66L,0xd856073968421d77L, + 0x03840fe883e3afeaL }, + { 0xb391dad51ec69977L,0xae243fb9307f6726L,0xc88ac87be8ca160cL, + 0x5174cced4ce355f4L } }, + /* 49 << 112 */ + { { 0x98a35966e58ba37dL,0xfdcc8da27817335dL,0x5b75283083fbc7bfL, + 0x68e419d4d9c96984L }, + { 0x409a39f402a40380L,0x88940faf1fe977bcL,0xc640a94b8f8edea6L, + 0x1e22cd17ed11547dL } }, + /* 50 << 112 */ + { { 0xe28568ce59ffc3e2L,0x60aa1b55c1dee4e7L,0xc67497c8837cb363L, + 0x06fb438a105a2bf2L }, + { 0x30357ec4500d8e20L,0x1ad9095d0670db10L,0x7f589a05c73b7cfdL, + 0xf544607d880d6d28L } }, + /* 51 << 112 */ + { { 0x17ba93b1a20ef103L,0xad8591306ba6577bL,0x65c91cf66fa214a0L, + 0xd7d49c6c27990da5L }, + { 0xecd9ec8d20bb569dL,0xbd4b2502eeffbc33L,0x2056ca5a6bed0467L, + 0x7916a1f75b63728cL } }, + /* 52 << 112 */ + { { 0xd4f9497d53a4f566L,0x8973466497b56810L,0xf8e1da740494a621L, + 0x82546a938d011c68L }, + { 0x1f3acb19c61ac162L,0x52f8fa9cabad0d3eL,0x15356523b4b7ea43L, + 0x5a16ad61ae608125L } }, + /* 53 << 112 */ + { { 0xb0bcb87f4faed184L,0x5f236b1d5029f45fL,0xd42c76070bc6b1fcL, + 0xc644324e68aefce3L }, + { 0x8e191d595c5d8446L,0xc020807713ae1979L,0xadcaee553ba59cc7L, + 0x20ed6d6ba2cb81baL } }, + /* 54 << 112 */ + { { 0x0952ba19b6efcffcL,0x60f12d6897c0b87cL,0x4ee2c7c49caa30bcL, + 0x767238b797fbff4eL }, + { 0xebc73921501b5d92L,0x3279e3dfc2a37737L,0x9fc12bc86d197543L, + 0xfa94dc6f0a40db4eL } }, + /* 55 << 112 */ + { { 0x7392b41a530ccbbdL,0x87c82146ea823525L,0xa52f984c05d98d0cL, + 0x2ae57d735ef6974cL }, + { 0x9377f7bf3042a6ddL,0xb1a007c019647a64L,0xfaa9079a0cca9767L, + 0x3d81a25bf68f72d5L } }, + /* 56 << 112 */ + { { 0x752067f8ff81578eL,0x786221509045447dL,0xc0c22fcf0505aa6fL, + 0x1030f0a66bed1c77L }, + { 0x31f29f151f0bd739L,0x2d7989c7e6debe85L,0x5c070e728e677e98L, + 0x0a817bd306e81fd5L } }, + /* 57 << 112 */ + { { 0xc110d830b0f2ac95L,0x48d0995aab20e64eL,0x0f3e00e17729cd9aL, + 0x2a570c20dd556946L }, + { 0x912dbcfd4e86214dL,0x2d014ee2cf615498L,0x55e2b1e63530d76eL, + 0xc5135ae4fd0fd6d1L } }, + /* 58 << 112 */ + { { 0x0066273ad4f3049fL,0xbb8e9893e7087477L,0x2dba1ddb14c6e5fdL, + 0xdba3788651f57e6cL }, + { 0x5aaee0a65a72f2cfL,0x1208bfbf7bea5642L,0xf5c6aa3b67872c37L, + 0xd726e08343f93224L } }, + /* 59 << 112 */ + { { 0x1854daa5061f1658L,0xc0016df1df0cd2b3L,0xc2a3f23e833d50deL, + 0x73b681d2bbbd3017L }, + { 0x2f046dc43ac343c0L,0x9c847e7d85716421L,0xe1e13c910917eed4L, + 0x3fc9eebd63a1b9c6L } }, + /* 60 << 112 */ + { { 0x0f816a727fe02299L,0x6335ccc2294f3319L,0x3820179f4745c5beL, + 0xe647b782922f066eL }, + { 0xc22e49de02cafb8aL,0x299bc2fffcc2ecccL,0x9a8feea26e0e8282L, + 0xa627278bfe893205L } }, + /* 61 << 112 */ + { { 0xa7e197337933e47bL,0xf4ff6b132e766402L,0xa4d8be0a98440d9fL, + 0x658f5c2f38938808L }, + { 0x90b75677c95b3b3eL,0xfa0442693137b6ffL,0x077b039b43c47c29L, + 0xcca95dd38a6445b2L } }, + /* 62 << 112 */ + { { 0x0b498ba42333fc4cL,0x274f8e68f736a1b1L,0x6ca348fd5f1d4b2eL, + 0x24d3be78a8f10199L }, + { 0x8535f858ca14f530L,0xa6e7f1635b982e51L,0x847c851236e1bf62L, + 0xf6a7c58e03448418L } }, + /* 63 << 112 */ + { { 0x583f3703f9374ab6L,0x864f91956e564145L,0x33bc3f4822526d50L, + 0x9f323c801262a496L }, + { 0xaa97a7ae3f046a9aL,0x70da183edf8a039aL,0x5b68f71c52aa0ba6L, + 0x9be0fe5121459c2dL } }, + /* 64 << 112 */ + { { 0xc1e17eb6cbc613e5L,0x33131d55497ea61cL,0x2f69d39eaf7eded5L, + 0x73c2f434de6af11bL }, + { 0x4ca52493a4a375faL,0x5f06787cb833c5c2L,0x814e091f3e6e71cfL, + 0x76451f578b746666L } }, + /* 0 << 119 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 119 */ + { { 0x80f9bdef694db7e0L,0xedca8787b9fcddc6L,0x51981c3403b8dce1L, + 0x4274dcf170e10ba1L }, + { 0xf72743b86def6d1aL,0xd25b1670ebdb1866L,0xc4491e8c050c6f58L, + 0x2be2b2ab87fbd7f5L } }, + /* 2 << 119 */ + { { 0x3e0e5c9dd111f8ecL,0xbcc33f8db7c4e760L,0x702f9a91bd392a51L, + 0x7da4a795c132e92dL }, + { 0x1a0b0ae30bb1151bL,0x54febac802e32251L,0xea3a5082694e9e78L, + 0xe58ffec1e4fe40b8L } }, + /* 3 << 119 */ + { { 0xf85592fcd1e0cf9eL,0xdea75f0dc0e7b2e8L,0xc04215cfc135584eL, + 0x174fc7272f57092aL }, + { 0xe7277877eb930beaL,0x504caccb5eb02a5aL,0xf9fe08f7f5241b9bL, + 0xe7fb62f48d5ca954L } }, + /* 4 << 119 */ + { { 0xfbb8349d29c4120bL,0x9f94391fc0d0d915L,0xc4074fa75410ba51L, + 0xa66adbf6150a5911L }, + { 0xc164543c34bfca38L,0xe0f27560b9e1ccfcL,0x99da0f53e820219cL, + 0xe8234498c6b4997aL } }, + /* 5 << 119 */ + { { 0xcfb88b769d4c5423L,0x9e56eb10b0521c49L,0x418e0b5ebe8700a1L, + 0x00cbaad6f93cb58aL }, + { 0xe923fbded92a5e67L,0xca4979ac1f347f11L,0x89162d856bc0585bL, + 0xdd6254afac3c70e3L } }, + /* 6 << 119 */ + { { 0x7b23c513516e19e4L,0x56e2e847c5c4d593L,0x9f727d735ce71ef6L, + 0x5b6304a6f79a44c5L }, + { 0x6638a7363ab7e433L,0x1adea470fe742f83L,0xe054b8545b7fc19fL, + 0xf935381aba1d0698L } }, + /* 7 << 119 */ + { { 0x546eab2d799e9a74L,0x96239e0ea949f729L,0xca274c6b7090055aL, + 0x835142c39020c9b0L }, + { 0xa405667aa2e8807fL,0x29f2c0851aa3d39eL,0xcc555d6442fc72f5L, + 0xe856e0e7fbeacb3cL } }, + /* 8 << 119 */ + { { 0xb5504f9d918e4936L,0x65035ef6b2513982L,0x0553a0c26f4d9cb9L, + 0x6cb10d56bea85509L }, + { 0x48d957b7a242da11L,0x16a4d3dd672b7268L,0x3d7e637c8502a96bL, + 0x27c7032b730d463bL } }, + /* 9 << 119 */ + { { 0xbdc02b18e4136a14L,0xbacf969d678e32bfL,0xc98d89a3dd9c3c03L, + 0x7b92420a23becc4fL }, + { 0xd4b41f78c64d565cL,0x9f969d0010f28295L,0xec7f7f76b13d051aL, + 0x08945e1ea92da585L } }, + /* 10 << 119 */ + { { 0x55366b7d5846426fL,0xe7d09e89247d441dL,0x510b404d736fbf48L, + 0x7fa003d0e784bd7dL }, + { 0x25f7614f17fd9596L,0x49e0e0a135cb98dbL,0x2c65957b2e83a76aL, + 0x5d40da8dcddbe0f8L } }, + /* 11 << 119 */ + { { 0xf2b8c405050bad24L,0x8918426dc2aa4823L,0x2aeab3dda38365a7L, + 0x720317177c91b690L }, + { 0x8b00d69960a94120L,0x478a255de99eaeecL,0xbf656a5f6f60aafdL, + 0xdfd7cb755dee77b3L } }, + /* 12 << 119 */ + { { 0x37f68bb4a595939dL,0x0355647928740217L,0x8e740e7c84ad7612L, + 0xd89bc8439044695fL }, + { 0xf7f3da5d85a9184dL,0x562563bb9fc0b074L,0x06d2e6aaf88a888eL, + 0x612d8643161fbe7cL } }, + /* 13 << 119 */ + { { 0x465edba7f64085e7L,0xb230f30429aa8511L,0x53388426cda2d188L, + 0x908857354b666649L }, + { 0x6f02ff9a652f54f6L,0x65c822945fae2bf0L,0x7816ade062f5eee3L, + 0xdcdbdf43fcc56d70L } }, + /* 14 << 119 */ + { { 0x9fb3bba354530bb2L,0xbde3ef77cb0869eaL,0x89bc90460b431163L, + 0x4d03d7d2e4819a35L }, + { 0x33ae4f9e43b6a782L,0x216db3079c88a686L,0x91dd88e000ffedd9L, + 0xb280da9f12bd4840L } }, + /* 15 << 119 */ + { { 0x32a7cb8a1635e741L,0xfe14008a78be02a7L,0x3fafb3341b7ae030L, + 0x7fd508e75add0ce9L }, + { 0x72c83219d607ad51L,0x0f229c0a8d40964aL,0x1be2c3361c878da2L, + 0xe0c96742eab2ab86L } }, + /* 16 << 119 */ + { { 0x458f86913e538cd7L,0xa7001f6c8e08ad53L,0x52b8c6e6bf5d15ffL, + 0x548234a4011215ddL }, + { 0xff5a9d2d3d5b4045L,0xb0ffeeb64a904190L,0x55a3aca448607f8bL, + 0x8cbd665c30a0672aL } }, + /* 17 << 119 */ + { { 0x87f834e042583068L,0x02da2aebf3f6e683L,0x6b763e5d05c12248L, + 0x7230378f65a8aefcL }, + { 0x93bd80b571e8e5caL,0x53ab041cb3b62524L,0x1b8605136c9c552eL, + 0xe84d402cd5524e66L } }, + /* 18 << 119 */ + { { 0xa37f3573f37f5937L,0xeb0f6c7dd1e4fca5L,0x2965a554ac8ab0fcL, + 0x17fbf56c274676acL }, + { 0x2e2f6bd9acf7d720L,0x41fc8f8810224766L,0x517a14b385d53befL, + 0xdae327a57d76a7d1L } }, + /* 19 << 119 */ + { { 0x6ad0a065c4818267L,0x33aa189b37c1bbc1L,0x64970b5227392a92L, + 0x21699a1c2d1535eaL }, + { 0xcd20779cc2d7a7fdL,0xe318605999c83cf2L,0x9b69440b72c0b8c7L, + 0xa81497d77b9e0e4dL } }, + /* 20 << 119 */ + { { 0x515d5c891f5f82dcL,0x9a7f67d76361079eL,0xa8da81e311a35330L, + 0xe44990c44b18be1bL }, + { 0xc7d5ed95af103e59L,0xece8aba78dac9261L,0xbe82b0999394b8d3L, + 0x6830f09a16adfe83L } }, + /* 21 << 119 */ + { { 0x250a29b488172d01L,0x8b20bd65caff9e02L,0xb8a7661ee8a6329aL, + 0x4520304dd3fce920L }, + { 0xae45da1f2b47f7efL,0xe07f52885bffc540L,0xf79970093464f874L, + 0x2244c2cda6fa1f38L } }, + /* 22 << 119 */ + { { 0x43c41ac194d7d9b1L,0x5bafdd82c82e7f17L,0xdf0614c15fda0fcaL, + 0x74b043a7a8ae37adL }, + { 0x3ba6afa19e71734cL,0x15d5437e9c450f2eL,0x4a5883fe67e242b1L, + 0x5143bdc22c1953c2L } }, + /* 23 << 119 */ + { { 0x542b8b53fc5e8920L,0x363bf9a89a9cee08L,0x02375f10c3486e08L, + 0x2037543b8c5e70d2L }, + { 0x7109bccc625640b4L,0xcbc1051e8bc62c3bL,0xf8455fed803f26eaL, + 0x6badceabeb372424L } }, + /* 24 << 119 */ + { { 0xa2a9ce7c6b53f5f9L,0x642465951b176d99L,0xb1298d36b95c081bL, + 0x53505bb81d9a9ee6L }, + { 0x3f6f9e61f2ba70b0L,0xd07e16c98afad453L,0x9f1694bbe7eb4a6aL, + 0xdfebced93cb0bc8eL } }, + /* 25 << 119 */ + { { 0x92d3dcdc53868c8bL,0x174311a2386107a6L,0x4109e07c689b4e64L, + 0x30e4587f2df3dcb6L }, + { 0x841aea310811b3b2L,0x6144d41d0cce43eaL,0x464c45812a9a7803L, + 0xd03d371f3e158930L } }, + /* 26 << 119 */ + { { 0xc676d7f2b1f3390bL,0x9f7a1b8ca5b61272L,0x4ebebfc9c2e127a9L, + 0x4602500c5dd997bfL }, + { 0x7f09771c4711230fL,0x058eb37c020f09c1L,0xab693d4bfee5e38bL, + 0x9289eb1f4653cbc0L } }, + /* 27 << 119 */ + { { 0xbecf46abd51b9cf5L,0xd2aa9c029f0121afL,0x36aaf7d2e90dc274L, + 0x909e4ea048b95a3cL }, + { 0xe6b704966f32dbdbL,0x672188a08b030b3eL,0xeeffe5b3cfb617e2L, + 0x87e947de7c82709eL } }, + /* 28 << 119 */ + { { 0xa44d2b391770f5a7L,0xe4d4d7910e44eb82L,0x42e69d1e3f69712aL, + 0xbf11c4d6ac6a820eL }, + { 0xb5e7f3e542c4224cL,0xd6b4e81c449d941cL,0x5d72bd165450e878L, + 0x6a61e28aee25ac54L } }, + /* 29 << 119 */ + { { 0x33272094e6f1cd95L,0x7512f30d0d18673fL,0x32f7a4ca5afc1464L, + 0x2f0956566bbb977bL }, + { 0x586f47caa8226200L,0x02c868ad1ac07369L,0x4ef2b845c613acbeL, + 0x43d7563e0386054cL } }, + /* 30 << 119 */ + { { 0x54da9dc7ab952578L,0xb5423df226e84d0bL,0xa8b64eeb9b872042L, + 0xac2057825990f6dfL }, + { 0x4ff696eb21f4c77aL,0x1a79c3e4aab273afL,0x29bc922e9436b3f1L, + 0xff807ef8d6d9a27aL } }, + /* 31 << 119 */ + { { 0x82acea3d778f22a0L,0xfb10b2e85b5e7469L,0xc0b169802818ee7dL, + 0x011afff4c91c1a2fL }, + { 0x95a6d126ad124418L,0x31c081a5e72e295fL,0x36bb283af2f4db75L, + 0xd115540f7acef462L } }, + /* 32 << 119 */ + { { 0xc7f3a8f833f6746cL,0x21e46f65fea990caL,0x915fd5c5caddb0a9L, + 0xbd41f01678614555L }, + { 0x346f4434426ffb58L,0x8055943614dbc204L,0xf3dd20fe5a969b7fL, + 0x9d59e956e899a39aL } }, + /* 33 << 119 */ + { { 0xf1b0971c8ad4cf4bL,0x034488602ffb8fb8L,0xf071ac3c65340ba4L, + 0x408d0596b27fd758L }, + { 0xe7c78ea498c364b0L,0xa4aac4a5051e8ab5L,0xb9e1d560485d9002L, + 0x9acd518a88844455L } }, + /* 34 << 119 */ + { { 0xe4ca688fd06f56c0L,0xa48af70ddf027972L,0x691f0f045e9a609dL, + 0xa9dd82cdee61270eL }, + { 0x8903ca63a0ef18d3L,0x9fb7ee353d6ca3bdL,0xa7b4a09cabf47d03L, + 0x4cdada011c67de8eL } }, + /* 35 << 119 */ + { { 0x520037499355a244L,0xe77fd2b64f2151a9L,0x695d6cf666b4efcbL, + 0xc5a0cacfda2cfe25L }, + { 0x104efe5cef811865L,0xf52813e89ea5cc3dL,0x855683dc40b58dbcL, + 0x0338ecde175fcb11L } }, + /* 36 << 119 */ + { { 0xf9a0563774921592L,0xb4f1261db9bb9d31L,0x551429b74e9c5459L, + 0xbe182e6f6ea71f53L }, + { 0xd3a3b07cdfc50573L,0x9ba1afda62be8d44L,0x9bcfd2cb52ab65d3L, + 0xdf11d547a9571802L } }, + /* 37 << 119 */ + { { 0x099403ee02a2404aL,0x497406f421088a71L,0x994794095004ae71L, + 0xbdb42078a812c362L }, + { 0x2b72a30fd8828442L,0x283add27fcb5ed1cL,0xf7c0e20066a40015L, + 0x3e3be64108b295efL } }, + /* 38 << 119 */ + { { 0xac127dc1e038a675L,0x729deff38c5c6320L,0xb7df8fd4a90d2c53L, + 0x9b74b0ec681e7cd3L }, + { 0x5cb5a623dab407e5L,0xcdbd361576b340c6L,0xa184415a7d28392cL, + 0xc184c1d8e96f7830L } }, + /* 39 << 119 */ + { { 0xc3204f1981d3a80fL,0xfde0c841c8e02432L,0x78203b3e8149e0c1L, + 0x5904bdbb08053a73L }, + { 0x30fc1dd1101b6805L,0x43c223bc49aa6d49L,0x9ed671417a174087L, + 0x311469a0d5997008L } }, + /* 40 << 119 */ + { { 0xb189b6845e43fc61L,0xf3282375e0d3ab57L,0x4fa34b67b1181da8L, + 0x621ed0b299ee52b8L }, + { 0x9b178de1ad990676L,0xd51de67b56d54065L,0x2a2c27c47538c201L, + 0x33856ec838a40f5cL } }, + /* 41 << 119 */ + { { 0x2522fc15be6cdcdeL,0x1e603f339f0c6f89L,0x7994edc3103e30a6L, + 0x033a00db220c853eL }, + { 0xd3cfa409f7bb7fd7L,0x70f8781e462d18f6L,0xbbd82980687fe295L, + 0x6eef4c32595669f3L } }, + /* 42 << 119 */ + { { 0x86a9303b2f7e85c3L,0x5fce462171988f9bL,0x5b935bf6c138acb5L, + 0x30ea7d6725661212L }, + { 0xef1eb5f4e51ab9a2L,0x0587c98aae067c78L,0xb3ce1b3c77ca9ca6L, + 0x2a553d4d54b5f057L } }, + /* 43 << 119 */ + { { 0xc78982364da29ec2L,0xdbdd5d13b9c57316L,0xc57d6e6b2cd80d47L, + 0x80b460cffe9e7391L }, + { 0x98648cabf963c31eL,0x67f9f633cc4d32fdL,0x0af42a9dfdf7c687L, + 0x55f292a30b015ea7L } }, + /* 44 << 119 */ + { { 0x89e468b2cd21ab3dL,0xe504f022c393d392L,0xab21e1d4a5013af9L, + 0xe3283f78c2c28acbL }, + { 0xf38b35f6226bf99fL,0xe83542740e291e69L,0x61673a15b20c162dL, + 0xc101dc75b04fbdbeL } }, + /* 45 << 119 */ + { { 0x8323b4c2255bd617L,0x6c9696936c2a9154L,0xc6e6586062679387L, + 0x8e01db0cb8c88e23L }, + { 0x33c42873893a5559L,0x7630f04b47a3e149L,0xb5d80805ddcf35f8L, + 0x582ca08077dfe732L } }, + /* 46 << 119 */ + { { 0x2c7156e10b1894a0L,0x92034001d81c68c0L,0xed225d00c8b115b5L, + 0x237f9c2283b907f2L }, + { 0x0ea2f32f4470e2c0L,0xb725f7c158be4e95L,0x0f1dcafab1ae5463L, + 0x59ed51871ba2fc04L } }, + /* 47 << 119 */ + { { 0xf6e0f316d0115d4dL,0x5180b12fd3691599L,0x157e32c9527f0a41L, + 0x7b0b081da8e0ecc0L }, + { 0x6dbaaa8abf4f0dd0L,0x99b289c74d252696L,0x79b7755edbf864feL, + 0x6974e2b176cad3abL } }, + /* 48 << 119 */ + { { 0x35dbbee206ddd657L,0xe7cbdd112ff3a96dL,0x88381968076be758L, + 0x2d737e7208c91f5dL }, + { 0x5f83ab6286ec3776L,0x98aa649d945fa7a1L,0xf477ec3772ef0933L, + 0x66f52b1e098c17b1L } }, + /* 49 << 119 */ + { { 0x9eec58fbd803738bL,0x91aaade7e4e86aa4L,0x6b1ae617a5b51492L, + 0x63272121bbc45974L }, + { 0x7e0e28f0862c5129L,0x0a8f79a93321a4a0L,0xe26d16645041c88fL, + 0x0571b80553233e3aL } }, + /* 50 << 119 */ + { { 0xd1b0ccdec9520711L,0x55a9e4ed3c8b84bfL,0x9426bd39a1fef314L, + 0x4f5f638e6eb93f2bL }, + { 0xba2a1ed32bf9341bL,0xd63c13214d42d5a9L,0xd2964a89316dc7c5L, + 0xd1759606ca511851L } }, + /* 51 << 119 */ + { { 0xd8a9201ff9e6ed35L,0xb7b5ee456736925aL,0x0a83fbbc99581af7L, + 0x3076bc4064eeb051L }, + { 0x5511c98c02dec312L,0x270de898238dcb78L,0x2cf4cf9c539c08c9L, + 0xa70cb65e38d3b06eL } }, + /* 52 << 119 */ + { { 0xb12ec10ecfe57bbdL,0x82c7b65635a0c2b5L,0xddc7d5cd161c67bdL, + 0xe32e8985ae3a32ccL }, + { 0x7aba9444d11a5529L,0xe964ed022427fa1aL,0x1528392d24a1770aL, + 0xa152ce2c12c72fcdL } }, + /* 53 << 119 */ + { { 0x714553a48ec07649L,0x18b4c290459dd453L,0xea32b7147b64b110L, + 0xb871bfa52e6f07a2L }, + { 0xb67112e59e2e3c9bL,0xfbf250e544aa90f6L,0xf77aedb8bd539006L, + 0x3b0cdf9ad172a66fL } }, + /* 54 << 119 */ + { { 0xedf69feaf8c51187L,0x05bb67ec741e4da7L,0x47df0f3208114345L, + 0x56facb07bb9792b1L }, + { 0xf3e007e98f6229e4L,0x62d103f4526fba0fL,0x4f33bef7b0339d79L, + 0x9841357bb59bfec1L } }, + /* 55 << 119 */ + { { 0xfa8dbb59c34e6705L,0xc3c7180b7fdaa84cL,0xf95872fca4108537L, + 0x8750cc3b932a3e5aL }, + { 0xb61cc69db7275d7dL,0xffa0168b2e59b2e9L,0xca032abc6ecbb493L, + 0x1d86dbd32c9082d8L } }, + /* 56 << 119 */ + { { 0xae1e0b67e28ef5baL,0x2c9a4699cb18e169L,0x0ecd0e331e6bbd20L, + 0x571b360eaf5e81d2L }, + { 0xcd9fea58101c1d45L,0x6651788e18880452L,0xa99726351f8dd446L, + 0x44bed022e37281d0L } }, + /* 57 << 119 */ + { { 0x094b2b2d33da525dL,0xf193678e13144fd8L,0xb8ab5ba4f4c1061dL, + 0x4343b5fadccbe0f4L }, + { 0xa870237163812713L,0x47bf6d2df7611d93L,0x46729b8cbd21e1d7L, + 0x7484d4e0d629e77dL } }, + /* 58 << 119 */ + { { 0x830e6eea60dbac1fL,0x23d8c484da06a2f7L,0x896714b050ca535bL, + 0xdc8d3644ebd97a9bL }, + { 0x106ef9fab12177b4L,0xf79bf464534d5d9cL,0x2537a349a6ab360bL, + 0xc7c54253a00c744fL } }, + /* 59 << 119 */ + { { 0xb3c7a047e5911a76L,0x61ffa5c8647f1ee7L,0x15aed36f8f56ab42L, + 0x6a0d41b0a3ff9ac9L }, + { 0x68f469f5cc30d357L,0xbe9adf816b72be96L,0x1cd926fe903ad461L, + 0x7e89e38fcaca441bL } }, + /* 60 << 119 */ + { { 0xf0f82de5facf69d4L,0x363b7e764775344cL,0x6894f312b2e36d04L, + 0x3c6cb4fe11d1c9a5L }, + { 0x85d9c3394008e1f2L,0x5e9a85ea249f326cL,0xdc35c60a678c5e06L, + 0xc08b944f9f86fba9L } }, + /* 61 << 119 */ + { { 0xde40c02c89f71f0fL,0xad8f3e31ff3da3c0L,0x3ea5096b42125dedL, + 0x13879cbfa7379183L }, + { 0x6f4714a56b306a0bL,0x359c2ea667646c5eL,0xfacf894307726368L, + 0x07a5893565ff431eL } }, + /* 62 << 119 */ + { { 0x24d661d168754ab0L,0x801fce1d6f429a76L,0xc068a85fa58ce769L, + 0xedc35c545d5eca2bL }, + { 0xea31276fa3f660d1L,0xa0184ebeb8fc7167L,0x0f20f21a1d8db0aeL, + 0xd96d095f56c35e12L } }, + /* 63 << 119 */ + { { 0xedf402b5f8c2a25bL,0x1bb772b9059204b6L,0x50cbeae219b4e34cL, + 0x93109d803fa0845aL }, + { 0x54f7ccf78ef59fb5L,0x3b438fe288070963L,0x9e28c65931f3ba9bL, + 0x9cc31b46ead9da92L } }, + /* 64 << 119 */ + { { 0x3c2f0ba9b733aa5fL,0xdece47cbf05af235L,0xf8e3f715a2ac82a5L, + 0xc97ba6412203f18aL }, + { 0xc3af550409c11060L,0x56ea2c0546af512dL,0xfac28daff3f28146L, + 0x87fab43a959ef494L } }, + /* 0 << 126 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 126 */ + { { 0x09891641d4c5105fL,0x1ae80f8e6d7fbd65L,0x9d67225fbee6bdb0L, + 0x3b433b597fc4d860L }, + { 0x44e66db693e85638L,0xf7b59252e3e9862fL,0xdb785157665c32ecL, + 0x702fefd7ae362f50L } }, + /* 2 << 126 */ + { { 0x3754475d0fefb0c3L,0xd48fb56b46d7c35dL,0xa070b633363798a4L, + 0xae89f3d28fdb98e6L }, + { 0x970b89c86363d14cL,0x8981752167abd27dL,0x9bf7d47444d5a021L, + 0xb3083bafcac72aeeL } }, + /* 3 << 126 */ + { { 0x389741debe949a44L,0x638e9388546a4fa5L,0x3fe6419ca0047bdcL, + 0x7047f648aaea57caL }, + { 0x54e48a9041fbab17L,0xda8e0b28576bdba2L,0xe807eebcc72afddcL, + 0x07d3336df42577bfL } }, + /* 4 << 126 */ + { { 0x62a8c244bfe20925L,0x91c19ac38fdce867L,0x5a96a5d5dd387063L, + 0x61d587d421d324f6L }, + { 0xe87673a2a37173eaL,0x2384800853778b65L,0x10f8441e05bab43eL, + 0xfa11fe124621efbeL } }, + /* 5 << 126 */ + { { 0x047b772e81685d7bL,0x23f27d81bf34a976L,0xc27608e2915f48efL, + 0x3b0b43faa521d5c3L }, + { 0x7613fb2663ca7284L,0x7f5729b41d4db837L,0x87b14898583b526bL, + 0x00b732a6bbadd3d1L } }, + /* 6 << 126 */ + { { 0x8e02f4262048e396L,0x436b50b6383d9de4L,0xf78d3481471e85adL, + 0x8b01ea6ad005c8d6L }, + { 0xd3c7afee97015c07L,0x46cdf1a94e3ba2aeL,0x7a42e50183d3a1d2L, + 0xd54b5268b541dff4L } }, + /* 7 << 126 */ + { { 0x3f24cf304e23e9bcL,0x4387f816126e3624L,0x26a46a033b0b6d61L, + 0xaf1bc8458b2d777cL }, + { 0x25c401ba527de79cL,0x0e1346d44261bbb6L,0x4b96c44b287b4bc7L, + 0x658493c75254562fL } }, + /* 8 << 126 */ + { { 0x23f949feb8a24a20L,0x17ebfed1f52ca53fL,0x9b691bbebcfb4853L, + 0x5617ff6b6278a05dL }, + { 0x241b34c5e3c99ebdL,0xfc64242e1784156aL,0x4206482f695d67dfL, + 0xb967ce0eee27c011L } }, + /* 9 << 126 */ + { { 0x65db375121c80b5dL,0x2e7a563ca31ecca0L,0xe56ffc4e5238a07eL, + 0x3d6c296632ced854L }, + { 0xe99d7d1aaf70b885L,0xafc3bad92d686459L,0x9c78bf460cc8ba5bL, + 0x5a43951918955aa3L } }, + /* 10 << 126 */ + { { 0xf8b517a85fe4e314L,0xe60234d0fcb8906fL,0xffe542acf2061b23L, + 0x287e191f6b4cb59cL }, + { 0x21857ddc09d877d8L,0x1c23478c14678941L,0xbbf0c056b6e05ea4L, + 0x82da4b53b01594feL } }, + /* 11 << 126 */ + { { 0xf7526791fadb8608L,0x049e832d7b74cdf6L,0xa43581ccc2b90a34L, + 0x73639eb89360b10cL }, + { 0x4fba331fe1e4a71bL,0x6ffd6b938072f919L,0x6e53271c65679032L, + 0x67206444f14272ceL } }, + /* 12 << 126 */ + { { 0xc0f734a3b2335834L,0x9526205a90ef6860L,0xcb8be71704e2bb0dL, + 0x2418871e02f383faL }, + { 0xd71776814082c157L,0xcc914ad029c20073L,0xf186c1ebe587e728L, + 0x6fdb3c2261bcd5fdL } }, + /* 13 << 126 */ + { { 0x30d014a6f2f9f8e9L,0x963ece234fec49d2L,0x862025c59605a8d9L, + 0x3987444519f8929aL }, + { 0x01b6ff6512bf476aL,0x598a64d809cf7d91L,0xd7ec774993be56caL, + 0x10899785cbb33615L } }, + /* 14 << 126 */ + { { 0xb8a092fd02eee3adL,0xa86b3d3530145270L,0x323d98c68512b675L, + 0x4b8bc78562ebb40fL }, + { 0x7d301f54413f9cdeL,0xa5e4fb4f2bab5664L,0x1d2b252d1cbfec23L, + 0xfcd576bbe177120dL } }, + /* 15 << 126 */ + { { 0x04427d3e83731a34L,0x2bb9028eed836e8eL,0xb36acff8b612ca7cL, + 0xb88fe5efd3d9c73aL }, + { 0xbe2a6bc6edea4eb3L,0x43b93133488eec77L,0xf41ff566b17106e1L, + 0x469e9172654efa32L } }, + /* 16 << 126 */ + { { 0xb4480f0441c23fa3L,0xb4712eb0c1989a2eL,0x3ccbba0f93a29ca7L, + 0x6e205c14d619428cL }, + { 0x90db7957b3641686L,0x0432691d45ac8b4eL,0x07a759acf64e0350L, + 0x0514d89c9c972517L } }, + /* 17 << 126 */ + { { 0x1701147fa8e67fc3L,0x9e2e0b8bab2085beL,0xd5651824ac284e57L, + 0x890d432574893664L }, + { 0x8a7c5e6ec55e68a3L,0xbf12e90b4339c85aL,0x31846b85f922b655L, + 0x9a54ce4d0bf4d700L } }, + /* 18 << 126 */ + { { 0xd7f4e83af1a14295L,0x916f955cb285d4f9L,0xe57bb0e099ffdabaL, + 0x28a43034eab0d152L }, + { 0x0a36ffa2b8a9cef8L,0x5517407eb9ec051aL,0x9c796096ea68e672L, + 0x853db5fbfb3c77fbL } }, + /* 19 << 126 */ + { { 0x21474ba9e864a51aL,0x6c2676996e8a1b8bL,0x7c82362694120a28L, + 0xe61e9a488383a5dbL }, + { 0x7dd750039f84216dL,0xab020d07ad43cd85L,0x9437ae48da12c659L, + 0x6449c2ebe65452adL } }, + /* 20 << 126 */ + { { 0xcc7c4c1c2cf9d7c1L,0x1320886aee95e5abL,0xbb7b9056beae170cL, + 0xc8a5b250dbc0d662L }, + { 0x4ed81432c11d2303L,0x7da669121f03769fL,0x3ac7a5fd84539828L, + 0x14dada943bccdd02L } }, + /* 21 << 126 */ + { { 0x8b84c3217ef6b0d1L,0x52a9477a7c933f22L,0x5ef6728afd440b82L, + 0x5c3bd8596ce4bd5eL }, + { 0x918b80f5f22c2d3eL,0x368d5040b7bb6cc5L,0xb66142a12695a11cL, + 0x60ac583aeb19ea70L } }, + /* 22 << 126 */ + { { 0x317cbb980eab2437L,0x8cc08c555e2654c8L,0xfe2d6520e6d8307fL, + 0xe9f147f357428993L }, + { 0x5f9c7d14d2fd6cf1L,0xa3ecd0642d4fcbb0L,0xad83fef08e7341f7L, + 0x643f23a03a63115cL } }, + /* 23 << 126 */ + { { 0xd38a78abe65ab743L,0xbf7c75b135edc89cL,0x3dd8752e530df568L, + 0xf85c4a76e308c682L }, + { 0x4c9955b2e68acf37L,0xa544df3dab32af85L,0x4b8ec3f5a25cf493L, + 0x4d8f27641a622febL } }, + /* 24 << 126 */ + { { 0x7bb4f7aaf0dcbc49L,0x7de551f970bbb45bL,0xcfd0f3e49f2ca2e5L, + 0xece587091f5c76efL }, + { 0x32920edd167d79aeL,0x039df8a2fa7d7ec1L,0xf46206c0bb30af91L, + 0x1ff5e2f522676b59L } }, + /* 25 << 126 */ + { { 0x11f4a0396ea51d66L,0x506c1445807d7a26L,0x60da5705755a9b24L, + 0x8fc8cc321f1a319eL }, + { 0x83642d4d9433d67dL,0x7fa5cb8f6a7dd296L,0x576591db9b7bde07L, + 0x13173d25419716fbL } }, + /* 26 << 126 */ + { { 0xea30599dd5b340ffL,0xfc6b5297b0fe76c5L,0x1c6968c8ab8f5adcL, + 0xf723c7f5901c928dL }, + { 0x4203c3219773d402L,0xdf7c6aa31b51dd47L,0x3d49e37a552be23cL, + 0x57febee80b5a6e87L } }, + /* 27 << 126 */ + { { 0xc5ecbee47bd8e739L,0x79d44994ae63bf75L,0x168bd00f38fb8923L, + 0x75d48ee4d0533130L }, + { 0x554f77aadb5cdf33L,0x3396e8963c696769L,0x2fdddbf2d3fd674eL, + 0xbbb8f6ee99d0e3e5L } }, + /* 28 << 126 */ + { { 0x51b90651cbae2f70L,0xefc4bc0593aaa8ebL,0x8ecd8689dd1df499L, + 0x1aee99a822f367a5L }, + { 0x95d485b9ae8274c5L,0x6c14d4457d30b39cL,0xbafea90bbcc1ef81L, + 0x7c5f317aa459a2edL } }, + /* 29 << 126 */ + { { 0x012110754ef44227L,0xa17bed6edc20f496L,0x0cdfe424819853cdL, + 0x13793298f71e2ce7L }, + { 0x3c1f3078dbbe307bL,0x6dd1c20e76ee9936L,0x23ee4b57423caa20L, + 0x4ac3793b8efb840eL } }, + /* 30 << 126 */ + { { 0x934438ebed1f8ca0L,0x3e5466584ebb25a2L,0xc415af0ec069896fL, + 0xc13eddb09a5aa43dL }, + { 0x7a04204fd49eb8f6L,0xd0d5bdfcd74f1670L,0x3697e28656fc0558L, + 0x1020737101cebadeL } }, + /* 31 << 126 */ + { { 0x5f87e6900647a82bL,0x908e0ed48f40054fL,0xa9f633d479853803L, + 0x8ed13c9a4a28b252L }, + { 0x3e2ef6761f460f64L,0x53930b9b36d06336L,0x347073ac8fc4979bL, + 0x84380e0e5ecd5597L } }, + /* 32 << 126 */ + { { 0xe3b22c6bc4fe3c39L,0xba4a81536c7bebdfL,0xf23ab6b725693459L, + 0x53bc377014922b11L }, + { 0x4645c8ab5afc60dbL,0xaa02235520b9f2a3L,0x52a2954cce0fc507L, + 0x8c2731bb7ce1c2e7L } }, + /* 33 << 126 */ + { { 0xf39608ab18a0339dL,0xac7a658d3735436cL,0xb22c2b07cd992b4fL, + 0x4e83daecf40dcfd4L }, + { 0x8a34c7be2f39ea3eL,0xef0c005fb0a56d2eL,0x62731f6a6edd8038L, + 0x5721d7404e3cb075L } }, + /* 34 << 126 */ + { { 0x1ea41511fbeeee1bL,0xd1ef5e73ef1d0c05L,0x42feefd173c07d35L, + 0xe530a00a8a329493L }, + { 0x5d55b7fef15ebfb0L,0x549de03cd322491aL,0xf7b5f602745b3237L, + 0x3632a3a21ab6e2b6L } }, + /* 35 << 126 */ + { { 0x0d3bba890ef59f78L,0x0dfc6443c9e52b9aL,0x1dc7969972631447L, + 0xef033917b3be20b1L }, + { 0x0c92735db1383948L,0xc1fc29a2c0dd7d7dL,0x6485b697403ed068L, + 0x13bfaab3aac93bdcL } }, + /* 36 << 126 */ + { { 0x410dc6a90deeaf52L,0xb003fb024c641c15L,0x1384978c5bc504c4L, + 0x37640487864a6a77L }, + { 0x05991bc6222a77daL,0x62260a575e47eb11L,0xc7af6613f21b432cL, + 0x22f3acc9ab4953e9L } }, + /* 37 << 126 */ + { { 0x529349228e41d155L,0x4d0245683ac059efL,0xb02017554d884411L, + 0xce8055cfa59a178fL }, + { 0xcd77d1aff6204549L,0xa0a00a3ec7066759L,0x471071ef0272c229L, + 0x009bcf6bd3c4b6b0L } }, + /* 38 << 126 */ + { { 0x2a2638a822305177L,0xd51d59df41645bbfL,0xa81142fdc0a7a3c0L, + 0xa17eca6d4c7063eeL }, + { 0x0bb887ed60d9dcecL,0xd6d28e5120ad2455L,0xebed6308a67102baL, + 0x042c31148bffa408L } }, + /* 39 << 126 */ + { { 0xfd099ac58aa68e30L,0x7a6a3d7c1483513eL,0xffcc6b75ba2d8f0cL, + 0x54dacf961e78b954L }, + { 0xf645696fa4a9af89L,0x3a41194006ac98ecL,0x41b8b3f622a67a20L, + 0x2d0b1e0f99dec626L } }, + /* 40 << 126 */ + { { 0x27c8919240be34e8L,0xc7162b3791907f35L,0x90188ec1a956702bL, + 0xca132f7ddf93769cL }, + { 0x3ece44f90e2025b4L,0x67aaec690c62f14cL,0xad74141822e3cc11L, + 0xcf9b75c37ff9a50eL } }, + /* 41 << 126 */ + { { 0x02fa2b164d348272L,0xbd99d61a9959d56dL,0xbc4f19db18762916L, + 0xcc7cce5049c1ac80L }, + { 0x4d59ebaad846bd83L,0x8775a9dca9202849L,0x07ec4ae16e1f4ca9L, + 0x27eb5875ba893f11L } }, + /* 42 << 126 */ + { { 0x00284d51662cc565L,0x82353a6b0db4138dL,0xd9c7aaaaaa32a594L, + 0xf5528b5ea5669c47L }, + { 0xf32202312f23c5ffL,0xe3e8147a6affa3a1L,0xfb423d5c202ddda0L, + 0x3d6414ac6b871bd4L } }, + /* 43 << 126 */ + { { 0x586f82e1a51a168aL,0xb712c67148ae5448L,0x9a2e4bd176233eb8L, + 0x0188223a78811ca9L }, + { 0x553c5e21f7c18de1L,0x7682e451b27bb286L,0x3ed036b30e51e929L, + 0xf487211bec9cb34fL } }, + /* 44 << 126 */ + { { 0x0d0942770c24efc8L,0x0349fd04bef737a4L,0x6d1c9dd2514cdd28L, + 0x29c135ff30da9521L }, + { 0xea6e4508f78b0b6fL,0x176f5dd2678c143cL,0x081484184be21e65L, + 0x27f7525ce7df38c4L } }, + /* 45 << 126 */ + { { 0x1fb70e09748ab1a4L,0x9cba50a05efe4433L,0x7846c7a615f75af2L, + 0x2a7c2c575ee73ea8L }, + { 0x42e566a43f0a449aL,0x45474c3bad90fc3dL,0x7447be3d8b61d057L, + 0x3e9d1cf13a4ec092L } }, + /* 46 << 126 */ + { { 0x1603e453f380a6e6L,0x0b86e4319b1437c2L,0x7a4173f2ef29610aL, + 0x8fa729a7f03d57f7L }, + { 0x3e186f6e6c9c217eL,0xbe1d307991919524L,0x92a62a70153d4fb1L, + 0x32ed3e34d68c2f71L } }, + /* 47 << 126 */ + { { 0xd785027f9eb1a8b7L,0xbc37eb77c5b22fe8L,0x466b34f0b9d6a191L, + 0x008a89af9a05f816L }, + { 0x19b028fb7d42c10aL,0x7fe8c92f49b3f6b8L,0x58907cc0a5a0ade3L, + 0xb3154f51559d1a7cL } }, + /* 48 << 126 */ + { { 0x5066efb6d9790ed6L,0xa77a0cbca6aa793bL,0x1a915f3c223e042eL, + 0x1c5def0469c5874bL }, + { 0x0e83007873b6c1daL,0x55cf85d2fcd8557aL,0x0f7c7c760460f3b1L, + 0x87052acb46e58063L } }, + /* 49 << 126 */ + { { 0x09212b80907eae66L,0x3cb068e04d721c89L,0xa87941aedd45ac1cL, + 0xde8d5c0d0daa0dbbL }, + { 0xda421fdce3502e6eL,0xc89442014d89a084L,0x7307ba5ef0c24bfbL, + 0xda212beb20bde0efL } }, + /* 50 << 126 */ + { { 0xea2da24bf82ce682L,0x058d381607f71fe4L,0x35a024625ffad8deL, + 0xcd7b05dcaadcefabL }, + { 0xd442f8ed1d9f54ecL,0x8be3d618b2d3b5caL,0xe2220ed0e06b2ce2L, + 0x82699a5f1b0da4c0L } }, + /* 51 << 126 */ + { { 0x3ff106f571c0c3a7L,0x8f580f5a0d34180cL,0x4ebb120e22d7d375L, + 0x5e5782cce9513675L }, + { 0x2275580c99c82a70L,0xe8359fbf15ea8c4cL,0x53b48db87b415e70L, + 0xaacf2240100c6014L } }, + /* 52 << 126 */ + { { 0x9faaccf5e4652f1dL,0xbd6fdd2ad56157b2L,0xa4f4fb1f6261ec50L, + 0x244e55ad476bcd52L }, + { 0x881c9305047d320bL,0x1ca983d56181263fL,0x354e9a44278fb8eeL, + 0xad2dbc0f396e4964L } }, + /* 53 << 126 */ + { { 0x723f3aa29268b3deL,0x0d1ca29ae6e0609aL,0x794866aa6cf44252L, + 0x0b59f3e301af87edL }, + { 0xe234e5ff7f4a6c51L,0xa8768fd261dc2f7eL,0xdafc73320a94d81fL, + 0xd7f8428206938ce1L } }, + /* 54 << 126 */ + { { 0xae0b3c0e0546063eL,0x7fbadcb25d61abc6L,0xd5d7a2c9369ac400L, + 0xa5978d09ae67d10cL }, + { 0x290f211e4f85eaacL,0xe61e2ad1facac681L,0xae125225388384cdL, + 0xa7fb68e9ccfde30fL } }, + /* 55 << 126 */ + { { 0x7a59b9363daed4c2L,0x80a9aa402606f789L,0xb40c1ea5f6a6d90aL, + 0x948364d3514d5885L }, + { 0x062ebc6070985182L,0xa6db5b0e33310895L,0x64a12175e329c2f5L, + 0xc5f25bd290ea237eL } }, + /* 56 << 126 */ + { { 0x7915c5242d0a4c23L,0xeb5d26e46bb3cc52L,0x369a9116c09e2c92L, + 0x0c527f92cf182cf8L }, + { 0x9e5919382aede0acL,0xb29222086cc34939L,0x3c9d896299a34361L, + 0x3c81836dc1905fe6L } }, + /* 57 << 126 */ + { { 0x4bfeb57fa001ec5aL,0xe993f5bba0dc5dbaL,0x47884109724a1380L, + 0x8a0369ab32fe9a04L }, + { 0xea068d608c927db8L,0xbf5f37cf94655741L,0x47d402a204b6c7eaL, + 0x4551c2956af259cbL } }, + /* 58 << 126 */ + { { 0x698b71e7ed77ee8bL,0xbddf7bd0f309d5c7L,0x6201c22c34e780caL, + 0xab04f7d84c295ef4L }, + { 0x1c9472944313a8ceL,0xe532e4ac92ca4cfeL,0x89738f80d0a7a97aL, + 0xec088c88a580fd5bL } }, + /* 59 << 126 */ + { { 0x612b1ecc42ce9e51L,0x8f9840fdb25fdd2aL,0x3cda78c001e7f839L, + 0x546b3d3aece05480L }, + { 0x271719a980d30916L,0x45497107584c20c4L,0xaf8f94785bc78608L, + 0x28c7d484277e2a4cL } }, + /* 60 << 126 */ + { { 0xfce0176788a2ffe4L,0xdc506a3528e169a5L,0x0ea108617af9c93aL, + 0x1ed2436103fa0e08L }, + { 0x96eaaa92a3d694e7L,0xc0f43b4def50bc74L,0xce6aa58c64114db4L, + 0x8218e8ea7c000fd4L } }, + /* 61 << 126 */ + { { 0xac815dfb185f8844L,0xcd7e90cb1557abfbL,0x23d16655afbfecdfL, + 0x80f3271f085cac4aL }, + { 0x7fc39aa7d0e62f47L,0x88d519d1460a48e5L,0x59559ac4d28f101eL, + 0x7981d9e9ca9ae816L } }, + /* 62 << 126 */ + { { 0x5c38652c9ac38203L,0x86eaf87f57657fe5L,0x568fc472e21f5416L, + 0x2afff39ce7e597b5L }, + { 0x3adbbb07256d4eabL,0x225986928285ab89L,0x35f8112a041caefeL, + 0x95df02e3a5064c8bL } }, + /* 63 << 126 */ + { { 0x4d63356ec7004bf3L,0x230a08f4db83c7deL,0xca27b2708709a7b7L, + 0x0d1c4cc4cb9abd2dL }, + { 0x8a0bc66e7550fee8L,0x369cd4c79cf7247eL,0x75562e8492b5b7e7L, + 0x8fed0da05802af7bL } }, + /* 64 << 126 */ + { { 0x6a7091c2e48fb889L,0x26882c137b8a9d06L,0xa24986631b82a0e2L, + 0x844ed7363518152dL }, + { 0x282f476fd86e27c7L,0xa04edaca04afefdcL,0x8b256ebc6119e34dL, + 0x56a413e90787d78bL } }, + /* 0 << 133 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 133 */ + { { 0x82ee061d5a74be50L,0xe41781c4dea16ff5L,0xe0b0c81e99bfc8a2L, + 0x624f4d690b547e2dL }, + { 0x3a83545dbdcc9ae4L,0x2573dbb6409b1e8eL,0x482960c4a6c93539L, + 0xf01059ad5ae18798L } }, + /* 2 << 133 */ + { { 0x715c9f973112795fL,0xe8244437984e6ee1L,0x55cb4858ecb66bcdL, + 0x7c136735abaffbeeL }, + { 0x546615955dbec38eL,0x51c0782c388ad153L,0x9ba4c53ac6e0952fL, + 0x27e6782a1b21dfa8L } }, + /* 3 << 133 */ + { { 0x682f903d4ed2dbc2L,0x0eba59c87c3b2d83L,0x8e9dc84d9c7e9335L, + 0x5f9b21b00eb226d7L }, + { 0xe33bd394af267baeL,0xaa86cc25be2e15aeL,0x4f0bf67d6a8ec500L, + 0x5846aa44f9630658L } }, + /* 4 << 133 */ + { { 0xfeb09740e2c2bf15L,0x627a2205a9e99704L,0xec8d73d0c2fbc565L, + 0x223eed8fc20c8de8L }, + { 0x1ee32583a8363b49L,0x1a0b6cb9c9c2b0a6L,0x49f7c3d290dbc85cL, + 0xa8dfbb971ef4c1acL } }, + /* 5 << 133 */ + { { 0xafb34d4c65c7c2abL,0x1d4610e7e2c5ea84L,0x893f6d1b973c4ab5L, + 0xa3cdd7e9945ba5c4L }, + { 0x60514983064417eeL,0x1459b23cad6bdf2bL,0x23b2c3415cf726c3L, + 0x3a82963532d6354aL } }, + /* 6 << 133 */ + { { 0x294f901fab192c18L,0xec5fcbfe7030164fL,0xe2e2fcb7e2246ba6L, + 0x1e7c88b3221a1a0cL }, + { 0x72c7dd93c92d88c5L,0x41c2148e1106fb59L,0x547dd4f5a0f60f14L, + 0xed9b52b263960f31L } }, + /* 7 << 133 */ + { { 0x6c8349ebb0a5b358L,0xb154c5c29e7e2ed6L,0xcad5eccfeda462dbL, + 0xf2d6dbe42de66b69L }, + { 0x426aedf38665e5b2L,0x488a85137b7f5723L,0x15cc43b38bcbb386L, + 0x27ad0af3d791d879L } }, + /* 8 << 133 */ + { { 0xc16c236e846e364fL,0x7f33527cdea50ca0L,0xc48107750926b86dL, + 0x6c2a36090598e70cL }, + { 0xa6755e52f024e924L,0xe0fa07a49db4afcaL,0x15c3ce7d66831790L, + 0x5b4ef350a6cbb0d6L } }, + /* 9 << 133 */ + { { 0x2c4aafc4b6205969L,0x42563f02f6c7854fL,0x016aced51d983b48L, + 0xfeb356d899949755L }, + { 0x8c2a2c81d1a39bd7L,0x8f44340fe6934ae9L,0x148cf91c447904daL, + 0x7340185f0f51a926L } }, + /* 10 << 133 */ + { { 0x2f8f00fb7409ab46L,0x057e78e680e289b2L,0x03e5022ca888e5d1L, + 0x3c87111a9dede4e2L }, + { 0x5b9b0e1c7809460bL,0xe751c85271c9abc7L,0x8b944e28c7cc1dc9L, + 0x4f201ffa1d3cfa08L } }, + /* 11 << 133 */ + { { 0x02fc905c3e6721ceL,0xd52d70dad0b3674cL,0x5dc2e5ca18810da4L, + 0xa984b2735c69dd99L }, + { 0x63b9252784de5ca4L,0x2f1c9872c852dec4L,0x18b03593c2e3de09L, + 0x19d70b019813dc2fL } }, + /* 12 << 133 */ + { { 0x42806b2da6dc1d29L,0xd3030009f871e144L,0xa1feb333aaf49276L, + 0xb5583b9ec70bc04bL }, + { 0x1db0be7895695f20L,0xfc84181189d012b5L,0x6409f27205f61643L, + 0x40d34174d5883128L } }, + /* 13 << 133 */ + { { 0xd79196f567419833L,0x6059e252863b7b08L,0x84da18171c56700cL, + 0x5758ee56b28d3ec4L }, + { 0x7da2771d013b0ea6L,0xfddf524b54c5e9b9L,0x7df4faf824305d80L, + 0x58f5c1bf3a97763fL } }, + /* 14 << 133 */ + { { 0xa5af37f17c696042L,0xd4cba22c4a2538deL,0x211cb9959ea42600L, + 0xcd105f417b069889L }, + { 0xb1e1cf19ddb81e74L,0x472f2d895157b8caL,0x086fb008ee9db885L, + 0x365cd5700f26d131L } }, + /* 15 << 133 */ + { { 0x284b02bba2be7053L,0xdcbbf7c67ab9a6d6L,0x4425559c20f7a530L, + 0x961f2dfa188767c8L }, + { 0xe2fd943570dc80c4L,0x104d6b63f0784120L,0x7f592bc153567122L, + 0xf6bc1246f688ad77L } }, + /* 16 << 133 */ + { { 0x05214c050f15dde9L,0xa47a76a80d5f2b82L,0xbb254d3062e82b62L, + 0x11a05fe03ec955eeL }, + { 0x7eaff46e9d529b36L,0x55ab13018f9e3df6L,0xc463e37199317698L, + 0xfd251438ccda47adL } }, + /* 17 << 133 */ + { { 0xca9c354723d695eaL,0x48ce626e16e589b5L,0x6b5b64c7b187d086L, + 0xd02e1794b2207948L }, + { 0x8b58e98f7198111dL,0x90ca6305dcf9c3ccL,0x5691fe72f34089b0L, + 0x60941af1fc7c80ffL } }, + /* 18 << 133 */ + { { 0xa09bc0a222eb51e5L,0xc0bb7244aa9cf09aL,0x36a8077f80159f06L, + 0x8b5c989edddc560eL }, + { 0x19d2f316512e1f43L,0x02eac554ad08ff62L,0x012ab84c07d20b4eL, + 0x37d1e115d6d4e4e1L } }, + /* 19 << 133 */ + { { 0xb6443e1aab7b19a8L,0xf08d067edef8cd45L,0x63adf3e9685e03daL, + 0xcf15a10e4792b916L }, + { 0xf44bcce5b738a425L,0xebe131d59636b2fdL,0x940688417850d605L, + 0x09684eaab40d749dL } }, + /* 20 << 133 */ + { { 0x8c3c669c72ba075bL,0x89f78b55ba469015L,0x5706aade3e9f8ba8L, + 0x6d8bd565b32d7ed7L }, + { 0x25f4e63b805f08d6L,0x7f48200dc3bcc1b5L,0x4e801968b025d847L, + 0x74afac0487cbe0a8L } }, + /* 21 << 133 */ + { { 0x43ed2c2b7e63d690L,0xefb6bbf00223cdb8L,0x4fec3cae2884d3feL, + 0x065ecce6d75e25a4L }, + { 0x6c2294ce69f79071L,0x0d9a8e5f044b8666L,0x5009f23817b69d8fL, + 0x3c29f8fec5dfdaf7L } }, + /* 22 << 133 */ + { { 0x9067528febae68c4L,0x5b38563230c5ba21L,0x540df1191fdd1aecL, + 0xcf37825bcfba4c78L }, + { 0x77eff980beb11454L,0x40a1a99160c1b066L,0xe8018980f889a1c7L, + 0xb9c52ae976c24be0L } }, + /* 23 << 133 */ + { { 0x05fbbcce45650ef4L,0xae000f108aa29ac7L,0x884b71724f04c470L, + 0x7cd4fde219bb5c25L }, + { 0x6477b22ae8840869L,0xa88688595fbd0686L,0xf23cc02e1116dfbaL, + 0x76cd563fd87d7776L } }, + /* 24 << 133 */ + { { 0xe2a37598a9d82abfL,0x5f188ccbe6c170f5L,0x816822005066b087L, + 0xda22c212c7155adaL }, + { 0x151e5d3afbddb479L,0x4b606b846d715b99L,0x4a73b54bf997cb2eL, + 0x9a1bfe433ecd8b66L } }, + /* 25 << 133 */ + { { 0x1c3128092a67d48aL,0xcd6a671e031fa9e2L,0xbec3312a0e43a34aL, + 0x1d93563955ef47d3L }, + { 0x5ea024898fea73eaL,0x8247b364a035afb2L,0xb58300a65265b54cL, + 0x3286662f722c7148L } }, + /* 26 << 133 */ + { { 0xb77fd76bb4ec4c20L,0xf0a12fa70f3fe3fdL,0xf845bbf541d8c7e8L, + 0xe4d969ca5ec10aa8L }, + { 0x4c0053b743e232a3L,0xdc7a3fac37f8a45aL,0x3c4261c520d81c8fL, + 0xfd4b3453b00eab00L } }, + /* 27 << 133 */ + { { 0x76d48f86d36e3062L,0x626c5277a143ff02L,0x538174deaf76f42eL, + 0x2267aa866407ceacL }, + { 0xfad7635172e572d5L,0xab861af7ba7330ebL,0xa0a1c8c7418d8657L, + 0x988821cb20289a52L } }, + /* 28 << 133 */ + { { 0x79732522cccc18adL,0xaadf3f8df1a6e027L,0xf7382c9317c2354dL, + 0x5ce1680cd818b689L }, + { 0x359ebbfcd9ecbee9L,0x4330689c1cae62acL,0xb55ce5b4c51ac38aL, + 0x7921dfeafe238ee8L } }, + /* 29 << 133 */ + { { 0x3972bef8271d1ca5L,0x3e423bc7e8aabd18L,0x57b09f3f44a3e5e3L, + 0x5da886ae7b444d66L }, + { 0x68206634a9964375L,0x356a2fa3699cd0ffL,0xaf0faa24dba515e9L, + 0x536e1f5cb321d79aL } }, + /* 30 << 133 */ + { { 0xd3b9913a5c04e4eaL,0xd549dcfed6f11513L,0xee227bf579fd1d94L, + 0x9f35afeeb43f2c67L }, + { 0xd2638d24f1314f53L,0x62baf948cabcd822L,0x5542de294ef48db0L, + 0xb3eb6a04fc5f6bb2L } }, + /* 31 << 133 */ + { { 0x23c110ae1208e16aL,0x1a4d15b5f8363e24L,0x30716844164be00bL, + 0xa8e24824f6f4690dL }, + { 0x548773a290b170cfL,0xa1bef33142f191f4L,0x70f418d09247aa97L, + 0xea06028e48be9147L } }, + /* 32 << 133 */ + { { 0xe13122f3dbfb894eL,0xbe9b79f6ce274b18L,0x85a49de5ca58aadfL, + 0x2495775811487351L }, + { 0x111def61bb939099L,0x1d6a974a26d13694L,0x4474b4ced3fc253bL, + 0x3a1485e64c5db15eL } }, + /* 33 << 133 */ + { { 0xe79667b4147c15b4L,0xe34f553b7bc61301L,0x032b80f817094381L, + 0x55d8bafd723eaa21L }, + { 0x5a987995f1c0e74eL,0x5a9b292eebba289cL,0x413cd4b2eb4c8251L, + 0x98b5d243d162db0aL } }, + /* 34 << 133 */ + { { 0xbb47bf6668342520L,0x08d68949baa862d1L,0x11f349c7e906abcdL, + 0x454ce985ed7bf00eL }, + { 0xacab5c9eb55b803bL,0xb03468ea31e3c16dL,0x5c24213dd273bf12L, + 0x211538eb71587887L } }, + /* 35 << 133 */ + { { 0x198e4a2f731dea2dL,0xd5856cf274ed7b2aL,0x86a632eb13a664feL, + 0x932cd909bda41291L }, + { 0x850e95d4c0c4ddc0L,0xc0f422f8347fc2c9L,0xe68cbec486076bcbL, + 0xf9e7c0c0cd6cd286L } }, + /* 36 << 133 */ + { { 0x65994ddb0f5f27caL,0xe85461fba80d59ffL,0xff05481a66601023L, + 0xc665427afc9ebbfbL }, + { 0xb0571a697587fd52L,0x935289f88d49efceL,0x61becc60ea420688L, + 0xb22639d913a786afL } }, + /* 37 << 133 */ + { { 0x1a8e6220361ecf90L,0x001f23e025506463L,0xe4ae9b5d0a5c2b79L, + 0xebc9cdadd8149db5L }, + { 0xb33164a1934aa728L,0x750eb00eae9b60f3L,0x5a91615b9b9cfbfdL, + 0x97015cbfef45f7f6L } }, + /* 38 << 133 */ + { { 0xb462c4a5bf5151dfL,0x21adcc41b07118f2L,0xd60c545b043fa42cL, + 0xfc21aa54e96be1abL }, + { 0xe84bc32f4e51ea80L,0x3dae45f0259b5d8dL,0xbb73c7ebc38f1b5eL, + 0xe405a74ae8ae617dL } }, + /* 39 << 133 */ + { { 0xbb1ae9c69f1c56bdL,0x8c176b9849f196a4L,0xc448f3116875092bL, + 0xb5afe3de9f976033L }, + { 0xa8dafd49145813e5L,0x687fc4d9e2b34226L,0xf2dfc92d4c7ff57fL, + 0x004e3fc1401f1b46L } }, + /* 40 << 133 */ + { { 0x5afddab61430c9abL,0x0bdd41d32238e997L,0xf0947430418042aeL, + 0x71f9addacdddc4cbL }, + { 0x7090c016c52dd907L,0xd9bdf44d29e2047fL,0xe6f1fe801b1011a6L, + 0xb63accbcd9acdc78L } }, + /* 41 << 133 */ + { { 0xcfc7e2351272a95bL,0x0c667717a6276ac8L,0x3c0d3709e2d7eef7L, + 0x5add2b069a685b3eL }, + { 0x363ad32d14ea5d65L,0xf8e01f068d7dd506L,0xc9ea221375b4aac6L, + 0xed2a2bf90d353466L } }, + /* 42 << 133 */ + { { 0x439d79b5e9d3a7c3L,0x8e0ee5a681b7f34bL,0xcf3dacf51dc4ba75L, + 0x1d3d1773eb3310c7L }, + { 0xa8e671127747ae83L,0x31f43160197d6b40L,0x0521cceecd961400L, + 0x67246f11f6535768L } }, + /* 43 << 133 */ + { { 0x702fcc5aef0c3133L,0x247cc45d7e16693bL,0xfd484e49c729b749L, + 0x522cef7db218320fL }, + { 0xe56ef40559ab93b3L,0x225fba119f181071L,0x33bd659515330ed0L, + 0xc4be69d51ddb32f7L } }, + /* 44 << 133 */ + { { 0x264c76680448087cL,0xac30903f71432daeL,0x3851b26600f9bf47L, + 0x400ed3116cdd6d03L }, + { 0x045e79fef8fd2424L,0xfdfd974afa6da98bL,0x45c9f6410c1e673aL, + 0x76f2e7335b2c5168L } }, + /* 45 << 133 */ + { { 0x1adaebb52a601753L,0xb286514cc57c2d49L,0xd87696701e0bfd24L, + 0x950c547e04478922L }, + { 0xd1d41969e5d32bfeL,0x30bc1472750d6c3eL,0x8f3679fee0e27f3aL, + 0x8f64a7dca4a6ee0cL } }, + /* 46 << 133 */ + { { 0x2fe59937633dfb1fL,0xea82c395977f2547L,0xcbdfdf1a661ea646L, + 0xc7ccc591b9085451L }, + { 0x8217796281761e13L,0xda57596f9196885cL,0xbc17e84928ffbd70L, + 0x1e6e0a412671d36fL } }, + /* 47 << 133 */ + { { 0x61ae872c4152fcf5L,0x441c87b09e77e754L,0xd0799dd5a34dff09L, + 0x766b4e4488a6b171L }, + { 0xdc06a51211f1c792L,0xea02ae934be35c3eL,0xe5ca4d6de90c469eL, + 0x4df4368e56e4ff5cL } }, + /* 48 << 133 */ + { { 0x7817acab4baef62eL,0x9f5a2202a85b91e8L,0x9666ebe66ce57610L, + 0x32ad31f3f73bfe03L }, + { 0x628330a425bcf4d6L,0xea950593515056e6L,0x59811c89e1332156L, + 0xc89cf1fe8c11b2d7L } }, + /* 49 << 133 */ + { { 0x75b6391304e60cc0L,0xce811e8d4625d375L,0x030e43fc2d26e562L, + 0xfbb30b4b608d36a0L }, + { 0x634ff82c48528118L,0x7c6fe085cd285911L,0x7f2830c099358f28L, + 0x2e60a95e665e6c09L } }, + /* 50 << 133 */ + { { 0x08407d3d9b785dbfL,0x530889aba759bce7L,0xf228e0e652f61239L, + 0x2b6d14616879be3cL }, + { 0xe6902c0451a7bbf7L,0x30ad99f076f24a64L,0x66d9317a98bc6da0L, + 0xf4f877f3cb596ac0L } }, + /* 51 << 133 */ + { { 0xb05ff62d4c44f119L,0x4555f536e9b77416L,0xc7c0d0598caed63bL, + 0x0cd2b7cec358b2a9L }, + { 0x3f33287b46945fa3L,0xf8785b20d67c8791L,0xc54a7a619637bd08L, + 0x54d4598c18be79d7L } }, + /* 52 << 133 */ + { { 0x889e5acbc46d7ce1L,0x9a515bb78b085877L,0xfac1a03d0b7a5050L, + 0x7d3e738af2926035L }, + { 0x861cc2ce2a6cb0ebL,0x6f2e29558f7adc79L,0x61c4d45133016376L, + 0xd9fd2c805ad59090L } }, + /* 53 << 133 */ + { { 0xe5a83738b2b836a1L,0x855b41a07c0d6622L,0x186fe3177cc19af1L, + 0x6465c1fffdd99acbL }, + { 0x46e5c23f6974b99eL,0x75a7cf8ba2717cbeL,0x4d2ebc3f062be658L, + 0x094b44475f209c98L } }, + /* 54 << 133 */ + { { 0x4af285edb940cb5aL,0x6706d7927cc82f10L,0xc8c8776c030526faL, + 0xfa8e6f76a0da9140L }, + { 0x77ea9d34591ee4f0L,0x5f46e33740274166L,0x1bdf98bbea671457L, + 0xd7c08b46862a1fe2L } }, + /* 55 << 133 */ + { { 0x46cc303c1c08ad63L,0x995434404c845e7bL,0x1b8fbdb548f36bf7L, + 0x5b82c3928c8273a7L }, + { 0x08f712c4928435d5L,0x071cf0f179330380L,0xc74c2d24a8da054aL, + 0xcb0e720143c46b5cL } }, + /* 56 << 133 */ + { { 0x0ad7337ac0b7eff3L,0x8552225ec5e48b3cL,0xe6f78b0c73f13a5fL, + 0x5e70062e82349cbeL }, + { 0x6b8d5048e7073969L,0x392d2a29c33cb3d2L,0xee4f727c4ecaa20fL, + 0xa068c99e2ccde707L } }, + /* 57 << 133 */ + { { 0xfcd5651fb87a2913L,0xea3e3c153cc252f0L,0x777d92df3b6cd3e4L, + 0x7a414143c5a732e7L }, + { 0xa895951aa71ff493L,0xfe980c92bbd37cf6L,0x45bd5e64decfeeffL, + 0x910dc2a9a44c43e9L } }, + /* 58 << 133 */ + { { 0xcb403f26cca9f54dL,0x928bbdfb9303f6dbL,0x3c37951ea9eee67cL, + 0x3bd61a52f79961c3L }, + { 0x09a238e6395c9a79L,0x6940ca2d61eb352dL,0x7d1e5c5ec1875631L, + 0x1e19742c1e1b20d1L } }, + /* 59 << 133 */ + { { 0x4633d90823fc2e6eL,0xa76e29a908959149L,0x61069d9c84ed7da5L, + 0x0baa11cf5dbcad51L }, + { 0xd01eec64961849daL,0x93b75f1faf3d8c28L,0x57bc4f9f1ca2ee44L, + 0x5a26322d00e00558L } }, + /* 60 << 133 */ + { { 0x1888d65861a023efL,0x1d72aab4b9e5246eL,0xa9a26348e5563ec0L, + 0xa0971963c3439a43L }, + { 0x567dd54badb9b5b7L,0x73fac1a1c45a524bL,0x8fe97ef7fe38e608L, + 0x608748d23f384f48L } }, + /* 61 << 133 */ + { { 0xb0571794c486094fL,0x869254a38bf3a8d6L,0x148a8dd1310b0e25L, + 0x99ab9f3f9aa3f7d8L }, + { 0x0927c68a6706c02eL,0x22b5e76c69790e6cL,0x6c3252606c71376cL, + 0x53a5769009ef6657L } }, + /* 62 << 133 */ + { { 0x8d63f852edffcf3aL,0xb4d2ed043c0a6f55L,0xdb3aa8de12519b9eL, + 0x5d38e9c41e0a569aL }, + { 0x871528bf303747e2L,0xa208e77cf5b5c18dL,0x9d129c88ca6bf923L, + 0xbcbf197fbf02839fL } }, + /* 63 << 133 */ + { { 0x9b9bf03027323194L,0x3b055a8b339ca59dL,0xb46b23120f669520L, + 0x19789f1f497e5f24L }, + { 0x9c499468aaf01801L,0x72ee11908b69d59cL,0x8bd39595acf4c079L, + 0x3ee11ece8e0cd048L } }, + /* 64 << 133 */ + { { 0xebde86ec1ed66f18L,0x225d906bd61fce43L,0x5cab07d6e8bed74dL, + 0x16e4617f27855ab7L }, + { 0x6568aaddb2fbc3ddL,0xedb5484f8aeddf5bL,0x878f20e86dcf2fadL, + 0x3516497c615f5699L } }, + /* 0 << 140 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 140 */ + { { 0xef0a3fecfa181e69L,0x9ea02f8130d69a98L,0xb2e9cf8e66eab95dL, + 0x520f2beb24720021L }, + { 0x621c540a1df84361L,0x1203772171fa6d5dL,0x6e3c7b510ff5f6ffL, + 0x817a069babb2bef3L } }, + /* 2 << 140 */ + { { 0x83572fb6b294cda6L,0x6ce9bf75b9039f34L,0x20e012f0095cbb21L, + 0xa0aecc1bd063f0daL }, + { 0x57c21c3af02909e5L,0xc7d59ecf48ce9cdcL,0x2732b8448ae336f8L, + 0x056e37233f4f85f4L } }, + /* 3 << 140 */ + { { 0x8a10b53189e800caL,0x50fe0c17145208fdL,0x9e43c0d3b714ba37L, + 0x427d200e34189accL }, + { 0x05dee24fe616e2c0L,0x9c25f4c8ee1854c1L,0x4d3222a58f342a73L, + 0x0807804fa027c952L } }, + /* 4 << 140 */ + { { 0xc222653a4f0d56f3L,0x961e4047ca28b805L,0x2c03f8b04a73434bL, + 0x4c966787ab712a19L }, + { 0xcc196c42864fee42L,0xc1be93da5b0ece5cL,0xa87d9f22c131c159L, + 0x2bb6d593dce45655L } }, + /* 5 << 140 */ + { { 0x22c49ec9b809b7ceL,0x8a41486be2c72c2cL,0x813b9420fea0bf36L, + 0xb3d36ee9a66dac69L }, + { 0x6fddc08a328cc987L,0x0a3bcd2c3a326461L,0x7103c49dd810dbbaL, + 0xf9d81a284b78a4c4L } }, + /* 6 << 140 */ + { { 0x3de865ade4d55941L,0xdedafa5e30384087L,0x6f414abb4ef18b9bL, + 0x9ee9ea42faee5268L }, + { 0x260faa1637a55a4aL,0xeb19a514015f93b9L,0x51d7ebd29e9c3598L, + 0x523fc56d1932178eL } }, + /* 7 << 140 */ + { { 0x501d070cb98fe684L,0xd60fbe9a124a1458L,0xa45761c892bc6b3fL, + 0xf5384858fe6f27cbL }, + { 0x4b0271f7b59e763bL,0x3d4606a95b5a8e5eL,0x1eda5d9b05a48292L, + 0xda7731d0e6fec446L } }, + /* 8 << 140 */ + { { 0xa3e3369390d45871L,0xe976404006166d8dL,0xb5c3368289a90403L, + 0x4bd1798372f1d637L }, + { 0xa616679ed5d2c53aL,0x5ec4bcd8fdcf3b87L,0xae6d7613b66a694eL, + 0x7460fc76e3fc27e5L } }, + /* 9 << 140 */ + { { 0x70469b8295caabeeL,0xde024ca5889501e3L,0x6bdadc06076ed265L, + 0x0cb1236b5a0ef8b2L }, + { 0x4065ddbf0972ebf9L,0xf1dd387522aca432L,0xa88b97cf744aff76L, + 0xd1359afdfe8e3d24L } }, + /* 10 << 140 */ + { { 0x52a3ba2b91502cf3L,0x2c3832a8084db75dL,0x04a12dddde30b1c9L, + 0x7802eabce31fd60cL }, + { 0x33707327a37fddabL,0x65d6f2abfaafa973L,0x3525c5b811e6f91aL, + 0x76aeb0c95f46530bL } }, + /* 11 << 140 */ + { { 0xe8815ff62f93a675L,0xa6ec968405f48679L,0x6dcbb556358ae884L, + 0x0af61472e19e3873L }, + { 0x72334372a5f696beL,0xc65e57ea6f22fb70L,0x268da30c946cea90L, + 0x136a8a8765681b2aL } }, + /* 12 << 140 */ + { { 0xad5e81dc0f9f44d4L,0xf09a69602c46585aL,0xd1649164c447d1b1L, + 0x3b4b36c8879dc8b1L }, + { 0x20d4177b3b6b234cL,0x096a25051730d9d0L,0x0611b9b8ef80531dL, + 0xba904b3b64bb495dL } }, + /* 13 << 140 */ + { { 0x1192d9d493a3147aL,0x9f30a5dc9a565545L,0x90b1f9cb6ef07212L, + 0x299585460d87fc13L }, + { 0xd3323effc17db9baL,0xcb18548ccb1644a8L,0x18a306d44f49ffbcL, + 0x28d658f14c2e8684L } }, + /* 14 << 140 */ + { { 0x44ba60cda99f8c71L,0x67b7abdb4bf742ffL,0x66310f9c914b3f99L, + 0xae430a32f412c161L }, + { 0x1e6776d388ace52fL,0x4bc0fa2452d7067dL,0x03c286aa8f07cd1bL, + 0x4cb8f38ca985b2c1L } }, + /* 15 << 140 */ + { { 0x83ccbe808c3bff36L,0x005a0bd25263e575L,0x460d7dda259bdcd1L, + 0x4a1c5642fa5cab6bL }, + { 0x2b7bdbb99fe4fc88L,0x09418e28cc97bbb5L,0xd8274fb4a12321aeL, + 0xb137007d5c87b64eL } }, + /* 16 << 140 */ + { { 0x80531fe1c63c4962L,0x50541e89981fdb25L,0xdc1291a1fd4c2b6bL, + 0xc0693a17a6df4fcaL }, + { 0xb2c4604e0117f203L,0x245f19630a99b8d0L,0xaedc20aac6212c44L, + 0xb1ed4e56520f52a8L } }, + /* 17 << 140 */ + { { 0xfe48f575f8547be3L,0x0a7033cda9e45f98L,0x4b45d3a918c50100L, + 0xb2a6cd6aa61d41daL }, + { 0x60bbb4f557933c6bL,0xa7538ebd2b0d7ffcL,0x9ea3ab8d8cd626b6L, + 0x8273a4843601625aL } }, + /* 18 << 140 */ + { { 0x888598450168e508L,0x8cbc9bb299a94abdL,0x713ac792fab0a671L, + 0xa3995b196c9ebffcL }, + { 0xe711668e1239e152L,0x56892558bbb8dff4L,0x8bfc7dabdbf17963L, + 0x5b59fe5ab3de1253L } }, + /* 19 << 140 */ + { { 0x7e3320eb34a9f7aeL,0xe5e8cf72d751efe4L,0x7ea003bcd9be2f37L, + 0xc0f551a0b6c08ef7L }, + { 0x56606268038f6725L,0x1dd38e356d92d3b6L,0x07dfce7cc3cbd686L, + 0x4e549e04651c5da8L } }, + /* 20 << 140 */ + { { 0x4058f93b08b19340L,0xc2fae6f4cac6d89dL,0x4bad8a8c8f159cc7L, + 0x0ddba4b3cb0b601cL }, + { 0xda4fc7b51dd95f8cL,0x1d163cd7cea5c255L,0x30707d06274a8c4cL, + 0x79d9e0082802e9ceL } }, + /* 21 << 140 */ + { { 0x02a29ebfe6ddd505L,0x37064e74b50bed1aL,0x3f6bae65a7327d57L, + 0x3846f5f1f83920bcL }, + { 0x87c3749160df1b9bL,0x4cfb28952d1da29fL,0x10a478ca4ed1743cL, + 0x390c60303edd47c6L } }, + /* 22 << 140 */ + { { 0x8f3e53128c0a78deL,0xccd02bda1e85df70L,0xd6c75c03a61b6582L, + 0x0762921cfc0eebd1L }, + { 0xd34d0823d85010c0L,0xd73aaacb0044cf1fL,0xfb4159bba3b5e78aL, + 0x2287c7f7e5826f3fL } }, + /* 23 << 140 */ + { { 0x4aeaf742580b1a01L,0xf080415d60423b79L,0xe12622cda7dea144L, + 0x49ea499659d62472L }, + { 0xb42991ef571f3913L,0x0610f214f5b25a8aL,0x47adc58530b79e8fL, + 0xf90e3df607a065a2L } }, + /* 24 << 140 */ + { { 0x5d0a5deb43e2e034L,0x53fb5a34444024aaL,0xa8628c686b0c9f7fL, + 0x9c69c29cac563656L }, + { 0x5a231febbace47b6L,0xbdce02899ea5a2ecL,0x05da1fac9463853eL, + 0x96812c52509e78aaL } }, + /* 25 << 140 */ + { { 0xd3fb577157151692L,0xeb2721f8d98e1c44L,0xc050608732399be1L, + 0xda5a5511d979d8b8L }, + { 0x737ed55dc6f56780L,0xe20d30040dc7a7f4L,0x02ce7301f5941a03L, + 0x91ef5215ed30f83aL } }, + /* 26 << 140 */ + { { 0x28727fc14092d85fL,0x72d223c65c49e41aL,0xa7cf30a2ba6a4d81L, + 0x7c086209b030d87dL }, + { 0x04844c7dfc588b09L,0x728cd4995874bbb0L,0xcc1281eee84c0495L, + 0x0769b5baec31958fL } }, + /* 27 << 140 */ + { { 0x665c228bf99c2471L,0xf2d8a11b191eb110L,0x4594f494d36d7024L, + 0x482ded8bcdcb25a1L }, + { 0xc958a9d8dadd4885L,0x7004477ef1d2b547L,0x0a45f6ef2a0af550L, + 0x4fc739d62f8d6351L } }, + /* 28 << 140 */ + { { 0x75cdaf27786f08a9L,0x8700bb2642c2737fL,0x855a71411c4e2670L, + 0x810188c115076fefL }, + { 0xc251d0c9abcd3297L,0xae4c8967f48108ebL,0xbd146de718ceed30L, + 0xf9d4f07ac986bcedL } }, + /* 29 << 140 */ + { { 0x5ad98ed583fa1e08L,0x7780d33ebeabd1fbL,0xe330513c903b1196L, + 0xba11de9ea47bc8c4L }, + { 0x684334da02c2d064L,0x7ecf360da48de23bL,0x57a1b4740a9089d8L, + 0xf28fa439ff36734cL } }, + /* 30 << 140 */ + { { 0xf2a482cbea4570b3L,0xee65d68ba5ebcee9L,0x988d0036b9694cd5L, + 0x53edd0e937885d32L }, + { 0xe37e3307beb9bc6dL,0xe9abb9079f5c6768L,0x4396ccd551f2160fL, + 0x2500888c47336da6L } }, + /* 31 << 140 */ + { { 0x383f9ed9926fce43L,0x809dd1c704da2930L,0x30f6f5968a4cb227L, + 0x0d700c7f73a56b38L }, + { 0x1825ea33ab64a065L,0xaab9b7351338df80L,0x1516100d9b63f57fL, + 0x2574395a27a6a634L } }, + /* 32 << 140 */ + { { 0xb5560fb6700a1acdL,0xe823fd73fd999681L,0xda915d1f6cb4e1baL, + 0x0d0301186ebe00a3L }, + { 0x744fb0c989fca8cdL,0x970d01dbf9da0e0bL,0x0ad8c5647931d76fL, + 0xb15737bff659b96aL } }, + /* 33 << 140 */ + { { 0xdc9933e8a8b484e7L,0xb2fdbdf97a26dec7L,0x2349e9a49f1f0136L, + 0x7860368e70fddddbL }, + { 0xd93d2c1cf9ad3e18L,0x6d6c5f17689f4e79L,0x7a544d91b24ff1b6L, + 0x3e12a5ebfe16cd8cL } }, + /* 34 << 140 */ + { { 0x543574e9a56b872fL,0xa1ad550cfcf68ea2L,0x689e37d23f560ef7L, + 0x8c54b9cac9d47a8bL }, + { 0x46d40a4a088ac342L,0xec450c7c1576c6d0L,0xb589e31c1f9689e9L, + 0xdacf2602b8781718L } }, + /* 35 << 140 */ + { { 0xa89237c6c8cb6b42L,0x1326fc93b96ef381L,0x55d56c6db5f07825L, + 0xacba2eea7449e22dL }, + { 0x74e0887a633c3000L,0xcb6cd172d7cbcf71L,0x309e81dec36cf1beL, + 0x07a18a6d60ae399bL } }, + /* 36 << 140 */ + { { 0xb36c26799edce57eL,0x52b892f4df001d41L,0xd884ae5d16a1f2c6L, + 0x9b329424efcc370aL }, + { 0x3120daf2bd2e21dfL,0x55298d2d02470a99L,0x0b78af6ca05db32eL, + 0x5c76a331601f5636L } }, + /* 37 << 140 */ + { { 0xaae861fff8a4f29cL,0x70dc9240d68f8d49L,0x960e649f81b1321cL, + 0x3d2c801b8792e4ceL }, + { 0xf479f77242521876L,0x0bed93bc416c79b1L,0xa67fbc05263e5bc9L, + 0x01e8e630521db049L } }, + /* 38 << 140 */ + { { 0x76f26738c6f3431eL,0xe609cb02e3267541L,0xb10cff2d818c877cL, + 0x1f0e75ce786a13cbL }, + { 0xf4fdca641158544dL,0x5d777e896cb71ed0L,0x3c233737a9aa4755L, + 0x7b453192e527ab40L } }, + /* 39 << 140 */ + { { 0xdb59f68839f05ffeL,0x8f4f4be06d82574eL,0xcce3450cee292d1bL, + 0xaa448a1261ccd086L }, + { 0xabce91b3f7914967L,0x4537f09b1908a5edL,0xa812421ef51042e7L, + 0xfaf5cebcec0b3a34L } }, + /* 40 << 140 */ + { { 0x730ffd874ca6b39aL,0x70fb72ed02efd342L,0xeb4735f9d75c8edbL, + 0xc11f2157c278aa51L }, + { 0xc459f635bf3bfebfL,0x3a1ff0b46bd9601fL,0xc9d12823c420cb73L, + 0x3e9af3e23c2915a3L } }, + /* 41 << 140 */ + { { 0xe0c82c72b41c3440L,0x175239e5e3039a5fL,0xe1084b8a558795a3L, + 0x328d0a1dd01e5c60L }, + { 0x0a495f2ed3788a04L,0x25d8ff1666c11a9fL,0xf5155f059ed692d6L, + 0x954fa1074f425fe4L } }, + /* 42 << 140 */ + { { 0xd16aabf2e98aaa99L,0x90cd8ba096b0f88aL,0x957f4782c154026aL, + 0x54ee073452af56d2L }, + { 0xbcf89e5445b4147aL,0x3d102f219a52816cL,0x6808517e39b62e77L, + 0x92e2542169169ad8L } }, + /* 43 << 140 */ + { { 0xd721d871bb608558L,0x60e4ebaef6d4ff9bL,0x0ba1081941f2763eL, + 0xca2e45be51ee3247L }, + { 0x66d172ec2bfd7a5fL,0x528a8f2f74d0b12dL,0xe17f1e38dabe70dcL, + 0x1d5d73169f93983cL } }, + /* 44 << 140 */ + { { 0x51b2184adf423e31L,0xcb417291aedb1a10L,0x2054ca93625bcab9L, + 0x54396860a98998f0L }, + { 0x4e53f6c4a54ae57eL,0x0ffeb590ee648e9dL,0xfbbdaadc6afaf6bcL, + 0xf88ae796aa3bfb8aL } }, + /* 45 << 140 */ + { { 0x209f1d44d2359ed9L,0xac68dd03f3544ce2L,0xf378da47fd51e569L, + 0xe1abd8602cc80097L }, + { 0x23ca18d9343b6e3aL,0x480797e8b40a1baeL,0xd1f0c717533f3e67L, + 0x4489697006e6cdfcL } }, + /* 46 << 140 */ + { { 0x8ca2105552a82e8dL,0xb2caf78578460cdcL,0x4c1b7b62e9037178L, + 0xefc09d2cdb514b58L }, + { 0x5f2df9ee9113be5cL,0x2fbda78fb3f9271cL,0xe09a81af8f83fc54L, + 0x06b138668afb5141L } }, + /* 47 << 140 */ + { { 0x38f6480f43e3865dL,0x72dd77a81ddf47d9L,0xf2a8e9714c205ff7L, + 0x46d449d89d088ad8L }, + { 0x926619ea185d706fL,0xe47e02ebc7dd7f62L,0xe7f120a78cbc2031L, + 0xc18bef00998d4ac9L } }, + /* 48 << 140 */ + { { 0x18f37a9c6bdf22daL,0xefbc432f90dc82dfL,0xc52cef8e5d703651L, + 0x82887ba0d99881a5L }, + { 0x7cec9ddab920ec1dL,0xd0d7e8c3ec3e8d3bL,0x445bc3954ca88747L, + 0xedeaa2e09fd53535L } }, + /* 49 << 140 */ + { { 0x461b1d936cc87475L,0xd92a52e26d2383bdL,0xfabccb59d7903546L, + 0x6111a7613d14b112L }, + { 0x0ae584feb3d5f612L,0x5ea69b8d60e828ecL,0x6c07898554087030L, + 0x649cab04ac4821feL } }, + /* 50 << 140 */ + { { 0x25ecedcf8bdce214L,0xb5622f7286af7361L,0x0e1227aa7038b9e2L, + 0xd0efb273ac20fa77L }, + { 0x817ff88b79df975bL,0x856bf2861999503eL,0xb4d5351f5038ec46L, + 0x740a52c5fc42af6eL } }, + /* 51 << 140 */ + { { 0x2e38bb152cbb1a3fL,0xc3eb99fe17a83429L,0xca4fcbf1dd66bb74L, + 0x880784d6cde5e8fcL }, + { 0xddc84c1cb4e7a0beL,0x8780510dbd15a72fL,0x44bcf1af81ec30e1L, + 0x141e50a80a61073eL } }, + /* 52 << 140 */ + { { 0x0d95571847be87aeL,0x68a61417f76a4372L,0xf57e7e87c607c3d3L, + 0x043afaf85252f332L }, + { 0xcc14e1211552a4d2L,0xb6dee692bb4d4ab4L,0xb6ab74c8a03816a4L, + 0x84001ae46f394a29L } }, + /* 53 << 140 */ + { { 0x5bed8344d795fb45L,0x57326e7db79f55a5L,0xc9533ce04accdffcL, + 0x53473caf3993fa04L }, + { 0x7906eb93a13df4c8L,0xa73e51f697cbe46fL,0xd1ab3ae10ae4ccf8L, + 0x256145088a5b3dbcL } }, + /* 54 << 140 */ + { { 0x61eff96211a71b27L,0xdf71412b6bb7fa39L,0xb31ba6b82bd7f3efL, + 0xb0b9c41569180d29L }, + { 0xeec14552014cdde5L,0x702c624b227b4bbbL,0x2b15e8c2d3e988f3L, + 0xee3bcc6da4f7fd04L } }, + /* 55 << 140 */ + { { 0x9d00822a42ac6c85L,0x2db0cea61df9f2b7L,0xd7cad2ab42de1e58L, + 0x346ed5262d6fbb61L }, + { 0xb39629951a2faf09L,0x2fa8a5807c25612eL,0x30ae04da7cf56490L, + 0x756629080eea3961L } }, + /* 56 << 140 */ + { { 0x3609f5c53d080847L,0xcb081d395241d4f6L,0xb4fb381077961a63L, + 0xc20c59842abb66fcL }, + { 0x3d40aa7cf902f245L,0x9cb127364e536b1eL,0x5eda24da99b3134fL, + 0xafbd9c695cd011afL } }, + /* 57 << 140 */ + { { 0x9a16e30ac7088c7dL,0x5ab657103207389fL,0x1b09547fe7407a53L, + 0x2322f9d74fdc6eabL }, + { 0xc0f2f22d7430de4dL,0x19382696e68ca9a9L,0x17f1eff1918e5868L, + 0xe3b5b635586f4204L } }, + /* 58 << 140 */ + { { 0x146ef9803fbc4341L,0x359f2c805b5eed4eL,0x9f35744e7482e41dL, + 0x9a9ac3ecf3b224c2L }, + { 0x9161a6fe91fc50aeL,0x89ccc66bc613fa7cL,0x89268b14c732f15aL, + 0x7cd6f4e2b467ed03L } }, + /* 59 << 140 */ + { { 0xfbf79869ce56b40eL,0xf93e094cc02dde98L,0xefe0c3a8edee2cd7L, + 0x90f3ffc0b268fd42L }, + { 0x81a7fd5608241aedL,0x95ab7ad800b1afe8L,0x401270563e310d52L, + 0xd3ffdeb109d9fc43L } }, + /* 60 << 140 */ + { { 0xc8f85c91d11a8594L,0x2e74d25831cf6db8L,0x829c7ca302b5dfd0L, + 0xe389cfbe69143c86L }, + { 0xd01b6405941768d8L,0x4510399503bf825dL,0xcc4ee16656cd17e2L, + 0xbea3c283ba037e79L } }, + /* 61 << 140 */ + { { 0x4e1ac06ed9a47520L,0xfbfe18aaaf852404L,0x5615f8e28087648aL, + 0x7301e47eb9d150d9L }, + { 0x79f9f9ddb299b977L,0x76697a7ba5b78314L,0x10d674687d7c90e7L, + 0x7afffe03937210b5L } }, + /* 62 << 140 */ + { { 0x5aef3e4b28c22ceeL,0xefb0ecd809fd55aeL,0x4cea71320d2a5d6aL, + 0x9cfb5fa101db6357L }, + { 0x395e0b57f36e1ac5L,0x008fa9ad36cafb7dL,0x8f6cdf705308c4dbL, + 0x51527a3795ed2477L } }, + /* 63 << 140 */ + { { 0xba0dee305bd21311L,0x6ed41b22909c90d7L,0xc5f6b7587c8696d3L, + 0x0db8eaa83ce83a80L }, + { 0xd297fe37b24b4b6fL,0xfe58afe8522d1f0dL,0x973587368c98dbd9L, + 0x6bc226ca9454a527L } }, + /* 64 << 140 */ + { { 0xa12b384ece53c2d0L,0x779d897d5e4606daL,0xa53e47b073ec12b0L, + 0x462dbbba5756f1adL }, + { 0x69fe09f2cafe37b6L,0x273d1ebfecce2e17L,0x8ac1d5383cf607fdL, + 0x8035f7ff12e10c25L } }, + /* 0 << 147 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 147 */ + { { 0x854d34c77e6c5520L,0xc27df9efdcb9ea58L,0x405f2369d686666dL, + 0x29d1febf0417aa85L }, + { 0x9846819e93470afeL,0x3e6a9669e2a27f9eL,0x24d008a2e31e6504L, + 0xdba7cecf9cb7680aL } }, + /* 2 << 147 */ + { { 0xecaff541338d6e43L,0x56f7dd734541d5ccL,0xb5d426de96bc88caL, + 0x48d94f6b9ed3a2c3L }, + { 0x6354a3bb2ef8279cL,0xd575465b0b1867f2L,0xef99b0ff95225151L, + 0xf3e19d88f94500d8L } }, + /* 3 << 147 */ + { { 0x92a83268e32dd620L,0x913ec99f627849a2L,0xedd8fdfa2c378882L, + 0xaf96f33eee6f8cfeL }, + { 0xc06737e5dc3fa8a5L,0x236bb531b0b03a1dL,0x33e59f2989f037b0L, + 0x13f9b5a7d9a12a53L } }, + /* 4 << 147 */ + { { 0x0d0df6ce51efb310L,0xcb5b2eb4958df5beL,0xd6459e2936158e59L, + 0x82aae2b91466e336L }, + { 0xfb658a39411aa636L,0x7152ecc5d4c0a933L,0xf10c758a49f026b7L, + 0xf4837f97cb09311fL } }, + /* 5 << 147 */ + { { 0xddfb02c4c753c45fL,0x18ca81b6f9c840feL,0x846fd09ab0f8a3e6L, + 0xb1162adde7733dbcL }, + { 0x7070ad20236e3ab6L,0xf88cdaf5b2a56326L,0x05fc8719997cbc7aL, + 0x442cd4524b665272L } }, + /* 6 << 147 */ + { { 0x7807f364b71698f5L,0x6ba418d29f7b605eL,0xfd20b00fa03b2cbbL, + 0x883eca37da54386fL }, + { 0xff0be43ff3437f24L,0xe910b432a48bb33cL,0x4963a128329df765L, + 0xac1dd556be2fe6f7L } }, + /* 7 << 147 */ + { { 0x557610f924a0a3fcL,0x38e17bf4e881c3f9L,0x6ba84fafed0dac99L, + 0xd4a222c359eeb918L }, + { 0xc79c1dbe13f542b6L,0x1fc65e0de425d457L,0xeffb754f1debb779L, + 0x638d8fd09e08af60L } }, + /* 8 << 147 */ + { { 0x994f523a626332d5L,0x7bc388335561bb44L,0x005ed4b03d845ea2L, + 0xd39d3ee1c2a1f08aL }, + { 0x6561fdd3e7676b0dL,0x620e35fffb706017L,0x36ce424ff264f9a8L, + 0xc4c3419fda2681f7L } }, + /* 9 << 147 */ + { { 0xfb6afd2f69beb6e8L,0x3a50b9936d700d03L,0xc840b2ad0c83a14fL, + 0x573207be54085befL }, + { 0x5af882e309fe7e5bL,0x957678a43b40a7e1L,0x172d4bdd543056e2L, + 0x9c1b26b40df13c0aL } }, + /* 10 << 147 */ + { { 0x1c30861cf405ff06L,0xebac86bd486e828bL,0xe791a971636933fcL, + 0x50e7c2be7aeee947L }, + { 0xc3d4a095fa90d767L,0xae60eb7be670ab7bL,0x17633a64397b056dL, + 0x93a21f33105012aaL } }, + /* 11 << 147 */ + { { 0x663c370babb88643L,0x91df36d722e21599L,0x183ba8358b761671L, + 0x381eea1d728f3bf1L }, + { 0xb9b2f1ba39966e6cL,0x7c464a28e7295492L,0x0fd5f70a09b26b7fL, + 0xa9aba1f9fbe009dfL } }, + /* 12 << 147 */ + { { 0x857c1f22369b87adL,0x3c00e5d932fca556L,0x1ad74cab90b06466L, + 0xa7112386550faaf2L }, + { 0x7435e1986d9bd5f5L,0x2dcc7e3859c3463fL,0xdc7df748ca7bd4b2L, + 0x13cd4c089dec2f31L } }, + /* 13 << 147 */ + { { 0x0d3b5df8e3237710L,0x0dadb26ecbd2f7b0L,0x9f5966abe4aa082bL, + 0x666ec8de350e966eL }, + { 0x1bfd1ed5ee524216L,0xcd93c59b41dab0b6L,0x658a8435d186d6baL, + 0x1b7d34d2159d1195L } }, + /* 14 << 147 */ + { { 0x5936e46022caf46bL,0x6a45dd8f9a96fe4fL,0xf7925434b98f474eL, + 0x414104120053ef15L }, + { 0x71cf8d1241de97bfL,0xb8547b61bd80bef4L,0xb47d3970c4db0037L, + 0xf1bcd328fef20dffL } }, + /* 15 << 147 */ + { { 0x31a92e0910caad67L,0x1f5919605531a1e1L,0x3bb852e05f4fc840L, + 0x63e297ca93a72c6cL }, + { 0x3c2b0b2e49abad67L,0x6ec405fced3db0d9L,0xdc14a5307fef1d40L, + 0xccd19846280896fcL } }, + /* 16 << 147 */ + { { 0x00f831769bb81648L,0xd69eb485653120d0L,0xd17d75f44ccabc62L, + 0x34a07f82b749fcb1L }, + { 0x2c3af787bbfb5554L,0xb06ed4d062e283f8L,0x5722889fa19213a0L, + 0x162b085edcf3c7b4L } }, + /* 17 << 147 */ + { { 0xbcaecb31e0dd3ecaL,0xc6237fbce52f13a5L,0xcc2b6b0327bac297L, + 0x2ae1cac5b917f54aL }, + { 0x474807d47845ae4fL,0xfec7dd92ce5972e0L,0xc3bd25411d7915bbL, + 0x66f85dc4d94907caL } }, + /* 18 << 147 */ + { { 0xd981b888bdbcf0caL,0xd75f5da6df279e9fL,0x128bbf247054e934L, + 0x3c6ff6e581db134bL }, + { 0x795b7cf4047d26e4L,0xf370f7b85049ec37L,0xc6712d4dced945afL, + 0xdf30b5ec095642bcL } }, + /* 19 << 147 */ + { { 0x9b034c624896246eL,0x5652c016ee90bbd1L,0xeb38636f87fedb73L, + 0x5e32f8470135a613L }, + { 0x0703b312cf933c83L,0xd05bb76e1a7f47e6L,0x825e4f0c949c2415L, + 0x569e56227250d6f8L } }, + /* 20 << 147 */ + { { 0xbbe9eb3a6568013eL,0x8dbd203f22f243fcL,0x9dbd7694b342734aL, + 0x8f6d12f846afa984L }, + { 0xb98610a2c9eade29L,0xbab4f32347dd0f18L,0x5779737b671c0d46L, + 0x10b6a7c6d3e0a42aL } }, + /* 21 << 147 */ + { { 0xfb19ddf33035b41cL,0xd336343f99c45895L,0x61fe493854c857e5L, + 0xc4d506beae4e57d5L }, + { 0x3cd8c8cbbbc33f75L,0x7281f08a9262c77dL,0x083f4ea6f11a2823L, + 0x8895041e9fba2e33L } }, + /* 22 << 147 */ + { { 0xfcdfea499c438edfL,0x7678dcc391edba44L,0xf07b3b87e2ba50f0L, + 0xc13888ef43948c1bL }, + { 0xc2135ad41140af42L,0x8e5104f3926ed1a7L,0xf24430cb88f6695fL, + 0x0ce0637b6d73c120L } }, + /* 23 << 147 */ + { { 0xb2db01e6fe631e8fL,0x1c5563d7d7bdd24bL,0x8daea3ba369ad44fL, + 0x000c81b68187a9f9L }, + { 0x5f48a951aae1fd9aL,0xe35626c78d5aed8aL,0x209527630498c622L, + 0x76d17634773aa504L } }, + /* 24 << 147 */ + { { 0x36d90ddaeb300f7aL,0x9dcf7dfcedb5e801L,0x645cb26874d5244cL, + 0xa127ee79348e3aa2L }, + { 0x488acc53575f1dbbL,0x95037e8580e6161eL,0x57e59283292650d0L, + 0xabe67d9914938216L } }, + /* 25 << 147 */ + { { 0x3c7f944b3f8e1065L,0xed908cb6330e8924L,0x08ee8fd56f530136L, + 0x2227b7d5d7ffc169L }, + { 0x4f55c893b5cd6dd5L,0x82225e11a62796e8L,0x5c6cead1cb18e12cL, + 0x4381ae0c84f5a51aL } }, + /* 26 << 147 */ + { { 0x345913d37fafa4c8L,0x3d9180820491aac0L,0x9347871f3e69264cL, + 0xbea9dd3cb4f4f0cdL }, + { 0xbda5d0673eadd3e7L,0x0033c1b80573bcd8L,0x255893795da2486cL, + 0xcb89ee5b86abbee7L } }, + /* 27 << 147 */ + { { 0x8fe0a8f322532e5dL,0xb6410ff0727dfc4cL,0x619b9d58226726dbL, + 0x5ec256697a2b2dc7L }, + { 0xaf4d2e064c3beb01L,0x852123d07acea556L,0x0e9470faf783487aL, + 0x75a7ea045664b3ebL } }, + /* 28 << 147 */ + { { 0x4ad78f356798e4baL,0x9214e6e5c7d0e091L,0xc420b488b1290403L, + 0x64049e0afc295749L }, + { 0x03ef5af13ae9841fL,0xdbe4ca19b0b662a6L,0x46845c5ffa453458L, + 0xf8dabf1910b66722L } }, + /* 29 << 147 */ + { { 0xb650f0aacce2793bL,0x71db851ec5ec47c1L,0x3eb78f3e3b234fa9L, + 0xb0c60f35fc0106ceL }, + { 0x05427121774eadbdL,0x25367fafce323863L,0x7541b5c9cd086976L, + 0x4ff069e2dc507ad1L } }, + /* 30 << 147 */ + { { 0x741452568776e667L,0x6e76142cb23c6bb5L,0xdbf307121b3a8a87L, + 0x60e7363e98450836L }, + { 0x5741450eb7366d80L,0xe4ee14ca4837dbdfL,0xa765eb9b69d4316fL, + 0x04548dca8ef43825L } }, + /* 31 << 147 */ + { { 0x9c9f4e4c5ae888ebL,0x733abb5156e9ac99L,0xdaad3c20ba6ac029L, + 0x9b8dd3d32ba3e38eL }, + { 0xa9bb4c920bc5d11aL,0xf20127a79c5f88a3L,0x4f52b06e161d3cb8L, + 0x26c1ff096afaf0a6L } }, + /* 32 << 147 */ + { { 0x32670d2f7189e71fL,0xc64387485ecf91e7L,0x15758e57db757a21L, + 0x427d09f8290a9ce5L }, + { 0x846a308f38384a7aL,0xaac3acb4b0732b99L,0x9e94100917845819L, + 0x95cba111a7ce5e03L } }, + /* 33 << 147 */ + { { 0x6f3d4f7fb00009c4L,0xb8396c278ff28b5fL,0xb1a9ae431c97975dL, + 0x9d7ba8afe5d9fed5L }, + { 0x338cf09f34f485b6L,0xbc0ddacc64122516L,0xa450da1205d471feL, + 0x4c3a6250628dd8c9L } }, + /* 34 << 147 */ + { { 0x69c7d103d1295837L,0xa2893e503807eb2fL,0xd6e1e1debdb41491L, + 0xc630745b5e138235L }, + { 0xc892109e48661ae1L,0x8d17e7ebea2b2674L,0x00ec0f87c328d6b5L, + 0x6d858645f079ff9eL } }, + /* 35 << 147 */ + { { 0x6cdf243e19115eadL,0x1ce1393e4bac4fcfL,0x2c960ed09c29f25bL, + 0x59be4d8e9d388a05L }, + { 0x0d46e06cd0def72bL,0xb923db5de0342748L,0xf7d3aacd936d4a3dL, + 0x558519cc0b0b099eL } }, + /* 36 << 147 */ + { { 0x3ea8ebf8827097efL,0x259353dbd054f55dL,0x84c89abc6d2ed089L, + 0x5c548b698e096a7cL }, + { 0xd587f616994b995dL,0x4d1531f6a5845601L,0x792ab31e451fd9f0L, + 0xc8b57bb265adf6caL } }, + /* 37 << 147 */ + { { 0x68440fcb1cd5ad73L,0xb9c860e66144da4fL,0x2ab286aa8462beb8L, + 0xcc6b8fffef46797fL }, + { 0xac820da420c8a471L,0x69ae05a177ff7fafL,0xb9163f39bfb5da77L, + 0xbd03e5902c73ab7aL } }, + /* 38 << 147 */ + { { 0x7e862b5eb2940d9eL,0x3c663d864b9af564L,0xd8309031bde3033dL, + 0x298231b2d42c5bc6L }, + { 0x42090d2c552ad093L,0xa4799d1cff854695L,0x0a88b5d6d31f0d00L, + 0xf8b40825a2f26b46L } }, + /* 39 << 147 */ + { { 0xec29b1edf1bd7218L,0xd491c53b4b24c86eL,0xd2fe588f3395ea65L, + 0x6f3764f74456ef15L }, + { 0xdb43116dcdc34800L,0xcdbcd456c1e33955L,0xefdb554074ab286bL, + 0x948c7a51d18c5d7cL } }, + /* 40 << 147 */ + { { 0xeb81aa377378058eL,0x41c746a104411154L,0xa10c73bcfb828ac7L, + 0x6439be919d972b29L }, + { 0x4bf3b4b043a2fbadL,0x39e6dadf82b5e840L,0x4f7164086397bd4cL, + 0x0f7de5687f1eeccbL } }, + /* 41 << 147 */ + { { 0x5865c5a1d2ffbfc1L,0xf74211fa4ccb6451L,0x66368a88c0b32558L, + 0x5b539dc29ad7812eL }, + { 0x579483d02f3af6f6L,0x5213207899934eceL,0x50b9650fdcc9e983L, + 0xca989ec9aee42b8aL } }, + /* 42 << 147 */ + { { 0x6a44c829d6f62f99L,0x8f06a3094c2a7c0cL,0x4ea2b3a098a0cb0aL, + 0x5c547b70beee8364L }, + { 0x461d40e1682afe11L,0x9e0fc77a7b41c0a8L,0x79e4aefde20d5d36L, + 0x2916e52032dd9f63L } }, + /* 43 << 147 */ + { { 0xf59e52e83f883fafL,0x396f96392b868d35L,0xc902a9df4ca19881L, + 0x0fc96822db2401a6L }, + { 0x4123758766f1c68dL,0x10fc6de3fb476c0dL,0xf8b6b579841f5d90L, + 0x2ba8446cfa24f44aL } }, + /* 44 << 147 */ + { { 0xa237b920ef4a9975L,0x60bb60042330435fL,0xd6f4ab5acfb7e7b5L, + 0xb2ac509783435391L }, + { 0xf036ee2fb0d1ea67L,0xae779a6a74c56230L,0x59bff8c8ab838ae6L, + 0xcd83ca999b38e6f0L } }, + /* 45 << 147 */ + { { 0xbb27bef5e33deed3L,0xe6356f6f001892a8L,0xbf3be6cc7adfbd3eL, + 0xaecbc81c33d1ac9dL }, + { 0xe4feb909e6e861dcL,0x90a247a453f5f801L,0x01c50acb27346e57L, + 0xce29242e461acc1bL } }, + /* 46 << 147 */ + { { 0x04dd214a2f998a91L,0x271ee9b1d4baf27bL,0x7e3027d1e8c26722L, + 0x21d1645c1820dce5L }, + { 0x086f242c7501779cL,0xf0061407fa0e8009L,0xf23ce47760187129L, + 0x05bbdedb0fde9bd0L } }, + /* 47 << 147 */ + { { 0x682f483225d98473L,0xf207fe855c658427L,0xb6fdd7ba4166ffa1L, + 0x0c3140569eed799dL }, + { 0x0db8048f4107e28fL,0x74ed387141216840L,0x74489f8f56a3c06eL, + 0x1e1c005b12777134L } }, + /* 48 << 147 */ + { { 0xdb332a73f37ec3c3L,0xc65259bddd59eba0L,0x2291709cdb4d3257L, + 0x9a793b25bd389390L }, + { 0xf39fe34be43756f0L,0x2f76bdce9afb56c9L,0x9f37867a61208b27L, + 0xea1d4307089972c3L } }, + /* 49 << 147 */ + { { 0x8c5953308bdf623aL,0x5f5accda8441fb7dL,0xfafa941832ddfd95L, + 0x6ad40c5a0fde9be7L }, + { 0x43faba89aeca8709L,0xc64a7cf12c248a9dL,0x1662025272637a76L, + 0xaee1c79122b8d1bbL } }, + /* 50 << 147 */ + { { 0xf0f798fd21a843b2L,0x56e4ed4d8d005cb1L,0x355f77801f0d8abeL, + 0x197b04cf34522326L }, + { 0x41f9b31ffd42c13fL,0x5ef7feb2b40f933dL,0x27326f425d60bad4L, + 0x027ecdb28c92cf89L } }, + /* 51 << 147 */ + { { 0x04aae4d14e3352feL,0x08414d2f73591b90L,0x5ed6124eb7da7d60L, + 0xb985b9314d13d4ecL }, + { 0xa592d3ab96bf36f9L,0x012dbed5bbdf51dfL,0xa57963c0df6c177dL, + 0x010ec86987ca29cfL } }, + /* 52 << 147 */ + { { 0xba1700f6bf926dffL,0x7c9fdbd1f4bf6bc2L,0xdc18dc8f64da11f5L, + 0xa6074b7ad938ae75L }, + { 0x14270066e84f44a4L,0x99998d38d27b954eL,0xc1be8ab2b4f38e9aL, + 0x8bb55bbf15c01016L } }, + /* 53 << 147 */ + { { 0xf73472b40ea2ab30L,0xd365a340f73d68ddL,0xc01a716819c2e1ebL, + 0x32f49e3734061719L }, + { 0xb73c57f101d8b4d6L,0x03c8423c26b47700L,0x321d0bc8a4d8826aL, + 0x6004213c4bc0e638L } }, + /* 54 << 147 */ + { { 0xf78c64a1c1c06681L,0x16e0a16fef018e50L,0x31cbdf91db42b2b3L, + 0xf8f4ffcee0d36f58L }, + { 0xcdcc71cd4cc5e3e0L,0xd55c7cfaa129e3e0L,0xccdb6ba00fb2cbf1L, + 0x6aba0005c4bce3cbL } }, + /* 55 << 147 */ + { { 0x501cdb30d232cfc4L,0x9ddcf12ed58a3cefL,0x02d2cf9c87e09149L, + 0xdc5d7ec72c976257L }, + { 0x6447986e0b50d7ddL,0x88fdbaf7807f112aL,0x58c9822ab00ae9f6L, + 0x6abfb9506d3d27e0L } }, + /* 56 << 147 */ + { { 0xd0a744878a429f4fL,0x0649712bdb516609L,0xb826ba57e769b5dfL, + 0x82335df21fc7aaf2L }, + { 0x2389f0675c93d995L,0x59ac367a68677be6L,0xa77985ff21d9951bL, + 0x038956fb85011cceL } }, + /* 57 << 147 */ + { { 0x608e48cbbb734e37L,0xc08c0bf22be5b26fL,0x17bbdd3bf9b1a0d9L, + 0xeac7d89810483319L }, + { 0xc95c4bafbc1a6deaL,0xfdd0e2bf172aafdbL,0x40373cbc8235c41aL, + 0x14303f21fb6f41d5L } }, + /* 58 << 147 */ + { { 0xba0636210408f237L,0xcad3b09aecd2d1edL,0x4667855a52abb6a2L, + 0xba9157dcaa8b417bL }, + { 0xfe7f35074f013efbL,0x1b112c4baa38c4a2L,0xa1406a609ba64345L, + 0xe53cba336993c80bL } }, + /* 59 << 147 */ + { { 0x45466063ded40d23L,0x3d5f1f4d54908e25L,0x9ebefe62403c3c31L, + 0x274ea0b50672a624L }, + { 0xff818d99451d1b71L,0x80e826438f79cf79L,0xa165df1373ce37f5L, + 0xa744ef4ffe3a21fdL } }, + /* 60 << 147 */ + { { 0x73f1e7f5cf551396L,0xc616898e868c676bL,0x671c28c78c442c36L, + 0xcfe5e5585e0a317dL }, + { 0x1242d8187051f476L,0x56fad2a614f03442L,0x262068bc0a44d0f6L, + 0xdfa2cd6ece6edf4eL } }, + /* 61 << 147 */ + { { 0x0f43813ad15d1517L,0x61214cb2377d44f5L,0xd399aa29c639b35fL, + 0x42136d7154c51c19L }, + { 0x9774711b08417221L,0x0a5546b352545a57L,0x80624c411150582dL, + 0x9ec5c418fbc555bcL } }, + /* 62 << 147 */ + { { 0x2c87dcad771849f1L,0xb0c932c501d7bf6fL,0x6aa5cd3e89116eb2L, + 0xd378c25a51ca7bd3L }, + { 0xc612a0da9e6e3e31L,0x0417a54db68ad5d0L,0x00451e4a22c6edb8L, + 0x9fbfe019b42827ceL } }, + /* 63 << 147 */ + { { 0x2fa92505ba9384a2L,0x21b8596e64ad69c1L,0x8f4fcc49983b35a6L, + 0xde09376072754672L }, + { 0x2f14ccc8f7bffe6dL,0x27566bff5d94263dL,0xb5b4e9c62df3ec30L, + 0x94f1d7d53e6ea6baL } }, + /* 64 << 147 */ + { { 0x97b7851aaaca5e9bL,0x518aa52156713b97L,0x3357e8c7150a61f6L, + 0x7842e7e2ec2c2b69L }, + { 0x8dffaf656868a548L,0xd963bd82e068fc81L,0x64da5c8b65917733L, + 0x927090ff7b247328L } }, + /* 0 << 154 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 154 */ + { { 0x214bc9a7d298c241L,0xe3b697ba56807cfdL,0xef1c78024564eadbL, + 0xdde8cdcfb48149c5L }, + { 0x946bf0a75a4d2604L,0x27154d7f6c1538afL,0x95cc9230de5b1fccL, + 0xd88519e966864f82L } }, + /* 2 << 154 */ + { { 0xb828dd1a7cb1282cL,0xa08d7626be46973aL,0x6baf8d40e708d6b2L, + 0x72571fa14daeb3f3L }, + { 0x85b1732ff22dfd98L,0x87ab01a70087108dL,0xaaaafea85988207aL, + 0xccc832f869f00755L } }, + /* 3 << 154 */ + { { 0x964d950e36ff3bf0L,0x8ad20f6ff0b34638L,0x4d9177b3b5d7585fL, + 0xcf839760ef3f019fL }, + { 0x582fc5b38288c545L,0x2f8e4e9b13116bd1L,0xf91e1b2f332120efL, + 0xcf5687242a17dd23L } }, + /* 4 << 154 */ + { { 0x488f1185ca8d9d1aL,0xadf2c77dd987ded2L,0x5f3039f060c46124L, + 0xe5d70b7571e095f4L }, + { 0x82d586506260e70fL,0x39d75ea7f750d105L,0x8cf3d0b175bac364L, + 0xf3a7564d21d01329L } }, + /* 5 << 154 */ + { { 0x182f04cd2f52d2a7L,0x4fde149ae2df565aL,0xb80c5eeca79fb2f7L, + 0xab491d7b22ddc897L }, + { 0x99d76c18c6312c7fL,0xca0d5f3d6aa41a57L,0x71207325d15363a0L, + 0xe82aa265beb252c2L } }, + /* 6 << 154 */ + { { 0x94ab4700ec3128c2L,0x6c76d8628e383f49L,0xdc36b150c03024ebL, + 0xfb43947753daac69L }, + { 0xfc68764a8dc79623L,0x5b86995db440fbb2L,0xd66879bfccc5ee0dL, + 0x0522894295aa8bd3L } }, + /* 7 << 154 */ + { { 0xb51a40a51e6a75c1L,0x24327c760ea7d817L,0x0663018207774597L, + 0xd6fdbec397fa7164L }, + { 0x20c99dfb13c90f48L,0xd6ac5273686ef263L,0xc6a50bdcfef64eebL, + 0xcd87b28186fdfc32L } }, + /* 8 << 154 */ + { { 0xb24aa43e3fcd3efcL,0xdd26c034b8088e9aL,0xa5ef4dc9bd3d46eaL, + 0xa2f99d588a4c6a6fL }, + { 0xddabd3552f1da46cL,0x72c3f8ce1afacdd1L,0xd90c4eee92d40578L, + 0xd28bb41fca623b94L } }, + /* 9 << 154 */ + { { 0x50fc0711745edc11L,0x9dd9ad7d3dc87558L,0xce6931fbb49d1e64L, + 0x6c77a0a2c98bd0f9L }, + { 0x62b9a6296baf7cb1L,0xcf065f91ccf72d22L,0x7203cce979639071L, + 0x09ae4885f9cb732fL } }, + /* 10 << 154 */ + { { 0x5e7c3becee8314f3L,0x1c068aeddbea298fL,0x08d381f17c80acecL, + 0x03b56be8e330495bL }, + { 0xaeffb8f29222882dL,0x95ff38f6c4af8bf7L,0x50e32d351fc57d8cL, + 0x6635be5217b444f0L } }, + /* 11 << 154 */ + { { 0x04d15276a5177900L,0x4e1dbb47f6858752L,0x5b475622c615796cL, + 0xa6fa0387691867bfL }, + { 0xed7f5d562844c6d0L,0xc633cf9b03a2477dL,0xf6be5c402d3721d6L, + 0xaf312eb7e9fd68e6L } }, + /* 12 << 154 */ + { { 0x242792d2e7417ce1L,0xff42bc71970ee7f5L,0x1ff4dc6d5c67a41eL, + 0x77709b7b20882a58L }, + { 0x3554731dbe217f2cL,0x2af2a8cd5bb72177L,0x58eee769591dd059L, + 0xbb2930c94bba6477L } }, + /* 13 << 154 */ + { { 0x863ee0477d930cfcL,0x4c262ad1396fd1f4L,0xf4765bc8039af7e1L, + 0x2519834b5ba104f6L }, + { 0x7cd61b4cd105f961L,0xa5415da5d63bca54L,0x778280a088a1f17cL, + 0xc49689492329512cL } }, + /* 14 << 154 */ + { { 0x174a9126cecdaa7aL,0xfc8c7e0e0b13247bL,0x29c110d23484c1c4L, + 0xf8eb8757831dfc3bL }, + { 0x022f0212c0067452L,0x3f6f69ee7b9b926cL,0x09032da0ef42daf4L, + 0x79f00ade83f80de4L } }, + /* 15 << 154 */ + { { 0x6210db7181236c97L,0x74f7685b3ee0781fL,0x4df7da7ba3e41372L, + 0x2aae38b1b1a1553eL }, + { 0x1688e222f6dd9d1bL,0x576954485b8b6487L,0x478d21274b2edeaaL, + 0xb2818fa51e85956aL } }, + /* 16 << 154 */ + { { 0x1e6adddaf176f2c0L,0x01ca4604e2572658L,0x0a404ded85342ffbL, + 0x8cf60f96441838d6L }, + { 0x9bbc691cc9071c4aL,0xfd58874434442803L,0x97101c85809c0d81L, + 0xa7fb754c8c456f7fL } }, + /* 17 << 154 */ + { { 0xc95f3c5cd51805e1L,0xab4ccd39b299dca8L,0x3e03d20b47eaf500L, + 0xfa3165c1d7b80893L }, + { 0x005e8b54e160e552L,0xdc4972ba9019d11fL,0x21a6972e0c9a4a7aL, + 0xa52c258f37840fd7L } }, + /* 18 << 154 */ + { { 0xf8559ff4c1e99d81L,0x08e1a7d6a3c617c0L,0xb398fd43248c6ba7L, + 0x6ffedd91d1283794L }, + { 0x8a6a59d2d629d208L,0xa9d141d53490530eL,0x42f6fc1838505989L, + 0x09bf250d479d94eeL } }, + /* 19 << 154 */ + { { 0x223ad3b1b3822790L,0x6c5926c093b8971cL,0x609efc7e75f7fa62L, + 0x45d66a6d1ec2d989L }, + { 0x4422d663987d2792L,0x4a73caad3eb31d2bL,0xf06c2ac1a32cb9e6L, + 0xd9445c5f91aeba84L } }, + /* 20 << 154 */ + { { 0x6af7a1d5af71013fL,0xe68216e50bedc946L,0xf4cba30bd27370a0L, + 0x7981afbf870421ccL }, + { 0x02496a679449f0e1L,0x86cfc4be0a47edaeL,0x3073c936b1feca22L, + 0xf569461203f8f8fbL } }, + /* 21 << 154 */ + { { 0xd063b723901515eaL,0x4c6c77a5749cf038L,0x6361e360ab9e5059L, + 0x596cf171a76a37c0L }, + { 0x800f53fa6530ae7aL,0x0f5e631e0792a7a6L,0x5cc29c24efdb81c9L, + 0xa269e8683f9c40baL } }, + /* 22 << 154 */ + { { 0xec14f9e12cb7191eL,0x78ea1bd8e5b08ea6L,0x3c65aa9b46332bb9L, + 0x84cc22b3bf80ce25L }, + { 0x0098e9e9d49d5bf1L,0xcd4ec1c619087da4L,0x3c9d07c5aef6e357L, + 0x839a02689f8f64b8L } }, + /* 23 << 154 */ + { { 0xc5e9eb62c6d8607fL,0x759689f56aa995e4L,0x70464669bbb48317L, + 0x921474bfe402417dL }, + { 0xcabe135b2a354c8cL,0xd51e52d2812fa4b5L,0xec74109653311fe8L, + 0x4f774535b864514bL } }, + /* 24 << 154 */ + { { 0xbcadd6715bde48f8L,0xc97038732189bc7dL,0x5d45299ec709ee8aL, + 0xd1287ee2845aaff8L }, + { 0x7d1f8874db1dbf1fL,0xea46588b990c88d6L,0x60ba649a84368313L, + 0xd5fdcbce60d543aeL } }, + /* 25 << 154 */ + { { 0x90b46d43810d5ab0L,0x6739d8f904d7e5ccL,0x021c1a580d337c33L, + 0x00a6116268e67c40L }, + { 0x95ef413b379f0a1fL,0xfe126605e9e2ab95L,0x67578b852f5f199cL, + 0xf5c003292cb84913L } }, + /* 26 << 154 */ + { { 0xf795643037577dd8L,0x83b82af429c5fe88L,0x9c1bea26cdbdc132L, + 0x589fa0869c04339eL }, + { 0x033e9538b13799dfL,0x85fa8b21d295d034L,0xdf17f73fbd9ddccaL, + 0xf32bd122ddb66334L } }, + /* 27 << 154 */ + { { 0x55ef88a7858b044cL,0x1f0d69c25aa9e397L,0x55fd9cc340d85559L, + 0xc774df727785ddb2L }, + { 0x5dcce9f6d3bd2e1cL,0xeb30da20a85dfed0L,0x5ed7f5bbd3ed09c4L, + 0x7d42a35c82a9c1bdL } }, + /* 28 << 154 */ + { { 0xcf3de9959890272dL,0x75f3432a3e713a10L,0x5e13479fe28227b8L, + 0xb8561ea9fefacdc8L }, + { 0xa6a297a08332aafdL,0x9b0d8bb573809b62L,0xd2fa1cfd0c63036fL, + 0x7a16eb55bd64bda8L } }, + /* 29 << 154 */ + { { 0x3f5cf5f678e62ddcL,0x2267c45407fd752bL,0x5e361b6b5e437bbeL, + 0x95c595018354e075L }, + { 0xec725f85f2b254d9L,0x844b617d2cb52b4eL,0xed8554f5cf425fb5L, + 0xab67703e2af9f312L } }, + /* 30 << 154 */ + { { 0x4cc34ec13cf48283L,0xb09daa259c8a705eL,0xd1e9d0d05b7d4f84L, + 0x4df6ef64db38929dL }, + { 0xe16b0763aa21ba46L,0xc6b1d178a293f8fbL,0x0ff5b602d520aabfL, + 0x94d671bdc339397aL } }, + /* 31 << 154 */ + { { 0x7c7d98cf4f5792faL,0x7c5e0d6711215261L,0x9b19a631a7c5a6d4L, + 0xc8511a627a45274dL }, + { 0x0c16621ca5a60d99L,0xf7fbab88cf5e48cbL,0xab1e6ca2f7ddee08L, + 0x83bd08cee7867f3cL } }, + /* 32 << 154 */ + { { 0xf7e48e8a2ac13e27L,0x4494f6df4eb1a9f5L,0xedbf84eb981f0a62L, + 0x49badc32536438f0L }, + { 0x50bea541004f7571L,0xbac67d10df1c94eeL,0x253d73a1b727bc31L, + 0xb3d01cf230686e28L } }, + /* 33 << 154 */ + { { 0x51b77b1b55fd0b8bL,0xa099d183feec3173L,0x202b1fb7670e72b7L, + 0xadc88b33a8e1635fL }, + { 0x34e8216af989d905L,0xc2e68d2029b58d01L,0x11f81c926fe55a93L, + 0x15f1462a8f296f40L } }, + /* 34 << 154 */ + { { 0x1915d375ea3d62f2L,0xa17765a301c8977dL,0x7559710ae47b26f6L, + 0xe0bd29c8535077a5L }, + { 0x615f976d08d84858L,0x370dfe8569ced5c1L,0xbbc7503ca734fa56L, + 0xfbb9f1ec91ac4574L } }, + /* 35 << 154 */ + { { 0x95d7ec53060dd7efL,0xeef2dacd6e657979L,0x54511af3e2a08235L, + 0x1e324aa41f4aea3dL }, + { 0x550e7e71e6e67671L,0xbccd5190bf52faf7L,0xf880d316223cc62aL, + 0x0d402c7e2b32eb5dL } }, + /* 36 << 154 */ + { { 0xa40bc039306a5a3bL,0x4e0a41fd96783a1bL,0xa1e8d39a0253cdd4L, + 0x6480be26c7388638L }, + { 0xee365e1d2285f382L,0x188d8d8fec0b5c36L,0x34ef1a481f0f4d82L, + 0x1a8f43e1a487d29aL } }, + /* 37 << 154 */ + { { 0x8168226d77aefb3aL,0xf69a751e1e72c253L,0x8e04359ae9594df1L, + 0x475ffd7dd14c0467L }, + { 0xb5a2c2b13844e95cL,0x85caf647dd12ef94L,0x1ecd2a9ff1063d00L, + 0x1dd2e22923843311L } }, + /* 38 << 154 */ + { { 0x38f0e09d73d17244L,0x3ede77468fc653f1L,0xae4459f5dc20e21cL, + 0x00db2ffa6a8599eaL }, + { 0x11682c3930cfd905L,0x4934d074a5c112a6L,0xbdf063c5568bfe95L, + 0x779a440a016c441aL } }, + /* 39 << 154 */ + { { 0x0c23f21897d6fbdcL,0xd3a5cd87e0776aacL,0xcee37f72d712e8dbL, + 0xfb28c70d26f74e8dL }, + { 0xffe0c728b61301a0L,0xa6282168d3724354L,0x7ff4cb00768ffedcL, + 0xc51b308803b02de9L } }, + /* 40 << 154 */ + { { 0xa5a8147c3902dda5L,0x35d2f706fe6973b4L,0x5ac2efcfc257457eL, + 0x933f48d48700611bL }, + { 0xc365af884912beb2L,0x7f5a4de6162edf94L,0xc646ba7c0c32f34bL, + 0x632c6af3b2091074L } }, + /* 41 << 154 */ + { { 0x58d4f2e3753e43a9L,0x70e1d21724d4e23fL,0xb24bf729afede6a6L, + 0x7f4a94d8710c8b60L }, + { 0xaad90a968d4faa6aL,0xd9ed0b32b066b690L,0x52fcd37b78b6dbfdL, + 0x0b64615e8bd2b431L } }, + /* 42 << 154 */ + { { 0x228e2048cfb9fad5L,0xbeaa386d240b76bdL,0x2d6681c890dad7bcL, + 0x3e553fc306d38f5eL }, + { 0xf27cdb9b9d5f9750L,0x3e85c52ad28c5b0eL,0x190795af5247c39bL, + 0x547831ebbddd6828L } }, + /* 43 << 154 */ + { { 0xf327a2274a82f424L,0x36919c787e47f89dL,0xe478391943c7392cL, + 0xf101b9aa2316fefeL }, + { 0xbcdc9e9c1c5009d2L,0xfb55ea139cd18345L,0xf5b5e231a3ce77c7L, + 0xde6b4527d2f2cb3dL } }, + /* 44 << 154 */ + { { 0x10f6a3339bb26f5fL,0x1e85db8e044d85b6L,0xc3697a0894197e54L, + 0x65e18cc0a7cb4ea8L }, + { 0xa38c4f50a471fe6eL,0xf031747a2f13439cL,0x53c4a6bac007318bL, + 0xa8da3ee51deccb3dL } }, + /* 45 << 154 */ + { { 0x0555b31c558216b1L,0x90c7810c2f79e6c2L,0x9b669f4dfe8eed3cL, + 0x70398ec8e0fac126L }, + { 0xa96a449ef701b235L,0x0ceecdb3eb94f395L,0x285fc368d0cb7431L, + 0x0d37bb5216a18c64L } }, + /* 46 << 154 */ + { { 0x05110d38b880d2ddL,0xa60f177b65930d57L,0x7da34a67f36235f5L, + 0x47f5e17c183816b9L }, + { 0xc7664b57db394af4L,0x39ba215d7036f789L,0x46d2ca0e2f27b472L, + 0xc42647eef73a84b7L } }, + /* 47 << 154 */ + { { 0x44bc754564488f1dL,0xaa922708f4cf85d5L,0x721a01d553e4df63L, + 0x649c0c515db46cedL }, + { 0x6bf0d64e3cffcb6cL,0xe3bf93fe50f71d96L,0x75044558bcc194a0L, + 0x16ae33726afdc554L } }, + /* 48 << 154 */ + { { 0xbfc01adf5ca48f3fL,0x64352f06e22a9b84L,0xcee54da1c1099e4aL, + 0xbbda54e8fa1b89c0L }, + { 0x166a3df56f6e55fbL,0x1ca44a2420176f88L,0x936afd88dfb7b5ffL, + 0xe34c24378611d4a0L } }, + /* 49 << 154 */ + { { 0x7effbb7586142103L,0x6704ba1b1f34fc4dL,0x7c2a468f10c1b122L, + 0x36b3a6108c6aace9L }, + { 0xabfcc0a775a0d050L,0x066f91973ce33e32L,0xce905ef429fe09beL, + 0x89ee25baa8376351L } }, + /* 50 << 154 */ + { { 0x2a3ede22fd29dc76L,0x7fd32ed936f17260L,0x0cadcf68284b4126L, + 0x63422f08a7951fc8L }, + { 0x562b24f40807e199L,0xfe9ce5d122ad4490L,0xc2f51b100db2b1b4L, + 0xeb3613ffe4541d0dL } }, + /* 51 << 154 */ + { { 0xbd2c4a052680813bL,0x527aa55d561b08d6L,0xa9f8a40ea7205558L, + 0xe3eea56f243d0becL }, + { 0x7b853817a0ff58b3L,0xb67d3f651a69e627L,0x0b76bbb9a869b5d6L, + 0xa3afeb82546723edL } }, + /* 52 << 154 */ + { { 0x5f24416d3e554892L,0x8413b53d430e2a45L,0x99c56aee9032a2a0L, + 0x09432bf6eec367b1L }, + { 0x552850c6daf0ecc1L,0x49ebce555bc92048L,0xdfb66ba654811307L, + 0x1b84f7976f298597L } }, + /* 53 << 154 */ + { { 0x795904818d1d7a0dL,0xd9fabe033a6fa556L,0xa40f9c59ba9e5d35L, + 0xcb1771c1f6247577L }, + { 0x542a47cae9a6312bL,0xa34b3560552dd8c5L,0xfdf94de00d794716L, + 0xd46124a99c623094L } }, + /* 54 << 154 */ + { { 0x56b7435d68afe8b4L,0x27f205406c0d8ea1L,0x12b77e1473186898L, + 0xdbc3dd467479490fL }, + { 0x951a9842c03b0c05L,0x8b1b3bb37921bc96L,0xa573b3462b202e0aL, + 0x77e4665d47254d56L } }, + /* 55 << 154 */ + { { 0x08b70dfcd23e3984L,0xab86e8bcebd14236L,0xaa3e07f857114ba7L, + 0x5ac71689ab0ef4f2L }, + { 0x88fca3840139d9afL,0x72733f8876644af0L,0xf122f72a65d74f4aL, + 0x13931577a5626c7aL } }, + /* 56 << 154 */ + { { 0xd5b5d9eb70f8d5a4L,0x375adde7d7bbb228L,0x31e88b860c1c0b32L, + 0xd1f568c4173edbaaL }, + { 0x1592fc835459df02L,0x2beac0fb0fcd9a7eL,0xb0a6fdb81b473b0aL, + 0xe3224c6f0fe8fc48L } }, + /* 57 << 154 */ + { { 0x680bd00ee87edf5bL,0x30385f0220e77cf5L,0xe9ab98c04d42d1b2L, + 0x72d191d2d3816d77L }, + { 0x1564daca0917d9e5L,0x394eab591f8fed7fL,0xa209aa8d7fbb3896L, + 0x5564f3b9be6ac98eL } }, + /* 58 << 154 */ + { { 0xead21d05d73654efL,0x68d1a9c413d78d74L,0x61e017086d4973a0L, + 0x83da350046e6d32aL }, + { 0x6a3dfca468ae0118L,0xa1b9a4c9d02da069L,0x0b2ff9c7ebab8302L, + 0x98af07c3944ba436L } }, + /* 59 << 154 */ + { { 0x85997326995f0f9fL,0x467fade071b58bc6L,0x47e4495abd625a2bL, + 0xfdd2d01d33c3b8cdL }, + { 0x2c38ae28c693f9faL,0x48622329348f7999L,0x97bf738e2161f583L, + 0x15ee2fa7565e8cc9L } }, + /* 60 << 154 */ + { { 0xa1a5c8455777e189L,0xcc10bee0456f2829L,0x8ad95c56da762bd5L, + 0x152e2214e9d91da8L }, + { 0x975b0e727cb23c74L,0xfd5d7670a90c66dfL,0xb5b5b8ad225ffc53L, + 0xab6dff73faded2aeL } }, + /* 61 << 154 */ + { { 0xebd567816f4cbe9dL,0x0ed8b2496a574bd7L,0x41c246fe81a881faL, + 0x91564805c3db9c70L }, + { 0xd7c12b085b862809L,0x1facd1f155858d7bL,0x7693747caf09e92aL, + 0x3b69dcba189a425fL } }, + /* 62 << 154 */ + { { 0x0be28e9f967365efL,0x57300eb2e801f5c9L,0x93b8ac6ad583352fL, + 0xa2cf1f89cd05b2b7L }, + { 0x7c0c9b744dcc40ccL,0xfee38c45ada523fbL,0xb49a4dec1099cc4dL, + 0x325c377f69f069c6L } }, + /* 63 << 154 */ + { { 0xe12458ce476cc9ffL,0x580e0b6cc6d4cb63L,0xd561c8b79072289bL, + 0x0377f264a619e6daL }, + { 0x2668536288e591a5L,0xa453a7bd7523ca2bL,0x8a9536d2c1df4533L, + 0xc8e50f2fbe972f79L } }, + /* 64 << 154 */ + { { 0xd433e50f6d3549cfL,0x6f33696ffacd665eL,0x695bfdacce11fcb4L, + 0x810ee252af7c9860L }, + { 0x65450fe17159bb2cL,0xf7dfbebe758b357bL,0x2b057e74d69fea72L, + 0xd485717a92731745L } }, + /* 0 << 161 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 161 */ + { { 0x896c42e8ee36860cL,0xdaf04dfd4113c22dL,0x1adbb7b744104213L, + 0xe5fd5fa11fd394eaL }, + { 0x68235d941a4e0551L,0x6772cfbe18d10151L,0x276071e309984523L, + 0xe4e879de5a56ba98L } }, + /* 2 << 161 */ + { { 0xaaafafb0285b9491L,0x01a0be881e4c705eL,0xff1d4f5d2ad9caabL, + 0x6e349a4ac37a233fL }, + { 0xcf1c12464a1c6a16L,0xd99e6b6629383260L,0xea3d43665f6d5471L, + 0x36974d04ff8cc89bL } }, + /* 3 << 161 */ + { { 0xc26c49a1cfe89d80L,0xb42c026dda9c8371L,0xca6c013adad066d2L, + 0xfb8f722856a4f3eeL }, + { 0x08b579ecd850935bL,0x34c1a74cd631e1b3L,0xcb5fe596ac198534L, + 0x39ff21f6e1f24f25L } }, + /* 4 << 161 */ + { { 0x27f29e148f929057L,0x7a64ae06c0c853dfL,0x256cd18358e9c5ceL, + 0x9d9cce82ded092a5L }, + { 0xcc6e59796e93b7c7L,0xe1e4709231bb9e27L,0xb70b3083aa9e29a0L, + 0xbf181a753785e644L } }, + /* 5 << 161 */ + { { 0xf53f2c658ead09f7L,0x1335e1d59780d14dL,0x69cc20e0cd1b66bcL, + 0x9b670a37bbe0bfc8L }, + { 0xce53dc8128efbeedL,0x0c74e77c8326a6e5L,0x3604e0d2b88e9a63L, + 0xbab38fca13dc2248L } }, + /* 6 << 161 */ + { { 0x8ed6e8c85c0a3f1eL,0xbcad24927c87c37fL,0xfdfb62bb9ee3b78dL, + 0xeba8e477cbceba46L }, + { 0x37d38cb0eeaede4bL,0x0bc498e87976deb6L,0xb2944c046b6147fbL, + 0x8b123f35f71f9609L } }, + /* 7 << 161 */ + { { 0xa155dcc7de79dc24L,0xf1168a32558f69cdL,0xbac215950d1850dfL, + 0x15c8295bb204c848L }, + { 0xf661aa367d8184ffL,0xc396228e30447bdbL,0x11cd5143bde4a59eL, + 0xe3a26e3b6beab5e6L } }, + /* 8 << 161 */ + { { 0xd3b3a13f1402b9d0L,0x573441c32c7bc863L,0x4b301ec4578c3e6eL, + 0xc26fc9c40adaf57eL }, + { 0x96e71bfd7493cea3L,0xd05d4b3f1af81456L,0xdaca2a8a6a8c608fL, + 0x53ef07f60725b276L } }, + /* 9 << 161 */ + { { 0x07a5fbd27824fc56L,0x3467521813289077L,0x5bf69fd5e0c48349L, + 0xa613ddd3b6aa7875L }, + { 0x7f78c19c5450d866L,0x46f4409c8f84a481L,0x9f1d192890fce239L, + 0x016c4168b2ce44b9L } }, + /* 10 << 161 */ + { { 0xbae023f0c7435978L,0xb152c88820e30e19L,0x9c241645e3fa6fafL, + 0x735d95c184823e60L }, + { 0x0319757303955317L,0x0b4b02a9f03b4995L,0x076bf55970274600L, + 0x32c5cc53aaf57508L } }, + /* 11 << 161 */ + { { 0xe8af6d1f60624129L,0xb7bc5d649a5e2b5eL,0x3814b0485f082d72L, + 0x76f267f2ce19677aL }, + { 0x626c630fb36eed93L,0x55230cd73bf56803L,0x78837949ce2736a0L, + 0x0d792d60aa6c55f1L } }, + /* 12 << 161 */ + { { 0x0318dbfdd5c7c5d2L,0xb38f8da7072b342dL,0x3569bddc7b8de38aL, + 0xf25b5887a1c94842L }, + { 0xb2d5b2842946ad60L,0x854f29ade9d1707eL,0xaa5159dc2c6a4509L, + 0x899f94c057189837L } }, + /* 13 << 161 */ + { { 0xcf6adc51f4a55b03L,0x261762de35e3b2d5L,0x4cc4301204827b51L, + 0xcd22a113c6021442L }, + { 0xce2fd61a247c9569L,0x59a50973d152becaL,0x6c835a1163a716d4L, + 0xc26455ed187dedcfL } }, + /* 14 << 161 */ + { { 0x27f536e049ce89e7L,0x18908539cc890cb5L,0x308909abd83c2aa1L, + 0xecd3142b1ab73bd3L }, + { 0x6a85bf59b3f5ab84L,0x3c320a68f2bea4c6L,0xad8dc5386da4541fL, + 0xeaf34eb0b7c41186L } }, + /* 15 << 161 */ + { { 0x1c780129977c97c4L,0x5ff9beebc57eb9faL,0xa24d0524c822c478L, + 0xfd8eec2a461cd415L }, + { 0xfbde194ef027458cL,0xb4ff53191d1be115L,0x63f874d94866d6f4L, + 0x35c75015b21ad0c9L } }, + /* 16 << 161 */ + { { 0xa6b5c9d646ac49d2L,0x42c77c0b83137aa9L,0x24d000fc68225a38L, + 0x0f63cfc82fe1e907L }, + { 0x22d1b01bc6441f95L,0x7d38f719ec8e448fL,0x9b33fa5f787fb1baL, + 0x94dcfda1190158dfL } }, + /* 17 << 161 */ + { { 0xc47cb3395f6d4a09L,0x6b4f355cee52b826L,0x3d100f5df51b930aL, + 0xf4512fac9f668f69L }, + { 0x546781d5206c4c74L,0xd021d4d4cb4d2e48L,0x494a54c2ca085c2dL, + 0xf1dbaca4520850a8L } }, + /* 18 << 161 */ + { { 0x63c79326490a1acaL,0xcb64dd9c41526b02L,0xbb772591a2979258L, + 0x3f58297048d97846L }, + { 0xd66b70d17c213ba7L,0xc28febb5e8a0ced4L,0x6b911831c10338c1L, + 0x0d54e389bf0126f3L } }, + /* 19 << 161 */ + { { 0x7048d4604af206eeL,0x786c88f677e97cb9L,0xd4375ae1ac64802eL, + 0x469bcfe1d53ec11cL }, + { 0xfc9b340d47062230L,0xe743bb57c5b4a3acL,0xfe00b4aa59ef45acL, + 0x29a4ef2359edf188L } }, + /* 20 << 161 */ + { { 0x40242efeb483689bL,0x2575d3f6513ac262L,0xf30037c80ca6db72L, + 0xc9fcce8298864be2L }, + { 0x84a112ff0149362dL,0x95e575821c4ae971L,0x1fa4b1a8945cf86cL, + 0x4525a7340b024a2fL } }, + /* 21 << 161 */ + { { 0xe76c8b628f338360L,0x483ff59328edf32bL,0x67e8e90a298b1aecL, + 0x9caab338736d9a21L }, + { 0x5c09d2fd66892709L,0x2496b4dcb55a1d41L,0x93f5fb1ae24a4394L, + 0x08c750496fa8f6c1L } }, + /* 22 << 161 */ + { { 0xcaead1c2c905d85fL,0xe9d7f7900733ae57L,0x24c9a65cf07cdd94L, + 0x7389359ca4b55931L }, + { 0xf58709b7367e45f7L,0x1f203067cb7e7adcL,0x82444bffc7b72818L, + 0x07303b35baac8033L } }, + /* 23 << 161 */ + { { 0x1e1ee4e4d13b7ea1L,0xe6489b24e0e74180L,0xa5f2c6107e70ef70L, + 0xa1655412bdd10894L }, + { 0x555ebefb7af4194eL,0x533c1c3c8e89bd9cL,0x735b9b5789895856L, + 0x15fb3cd2567f5c15L } }, + /* 24 << 161 */ + { { 0x057fed45526f09fdL,0xe8a4f10c8128240aL,0x9332efc4ff2bfd8dL, + 0x214e77a0bd35aa31L }, + { 0x32896d7314faa40eL,0x767867ec01e5f186L,0xc9adf8f117a1813eL, + 0xcb6cda7854741795L } }, + /* 25 << 161 */ + { { 0xb7521b6d349d51aaL,0xf56b5a9ee3c7b8e9L,0xc6f1e5c932a096dfL, + 0x083667c4a3635024L }, + { 0x365ea13518087f2fL,0xf1b8eaacd136e45dL,0xc8a0e48473aec989L, + 0xd75a324b142c9259L } }, + /* 26 << 161 */ + { { 0xb7b4d00101dae185L,0x45434e0b9b7a94bcL,0xf54339affbd8cb0bL, + 0xdcc4569ee98ef49eL }, + { 0x7789318a09a51299L,0x81b4d206b2b025d8L,0xf64aa418fae85792L, + 0x3e50258facd7baf7L } }, + /* 27 << 161 */ + { { 0xdce84cdb2996864bL,0xa2e670891f485fa4L,0xb28b2bb6534c6a5aL, + 0x31a7ec6bc94b9d39L }, + { 0x1d217766d6bc20daL,0x4acdb5ec86761190L,0x6872632873701063L, + 0x4d24ee7c2128c29bL } }, + /* 28 << 161 */ + { { 0xc072ebd3a19fd868L,0x612e481cdb8ddd3bL,0xb4e1d7541a64d852L, + 0x00ef95acc4c6c4abL }, + { 0x1536d2edaa0a6c46L,0x6129408643774790L,0x54af25e8343fda10L, + 0x9ff9d98dfd25d6f2L } }, + /* 29 << 161 */ + { { 0x0746af7c468b8835L,0x977a31cb730ecea7L,0xa5096b80c2cf4a81L, + 0xaa9868336458c37aL }, + { 0x6af29bf3a6bd9d34L,0x6a62fe9b33c5d854L,0x50e6c304b7133b5eL, + 0x04b601597d6e6848L } }, + /* 30 << 161 */ + { { 0x4cd296df5579bea4L,0x10e35ac85ceedaf1L,0x04c4c5fde3bcc5b1L, + 0x95f9ee8a89412cf9L }, + { 0x2c9459ee82b6eb0fL,0x2e84576595c2aaddL,0x774a84aed327fcfeL, + 0xd8c937220368d476L } }, + /* 31 << 161 */ + { { 0x0dbd5748f83e8a3bL,0xa579aa968d2495f3L,0x535996a0ae496e9bL, + 0x07afbfe9b7f9bcc2L }, + { 0x3ac1dc6d5b7bd293L,0x3b592cff7022323dL,0xba0deb989c0a3e76L, + 0x18e78e9f4b197acbL } }, + /* 32 << 161 */ + { { 0x211cde10296c36efL,0x7ee8967282c4da77L,0xb617d270a57836daL, + 0xf0cd9c319cb7560bL }, + { 0x01fdcbf7e455fe90L,0x3fb53cbb7e7334f3L,0x781e2ea44e7de4ecL, + 0x8adab3ad0b384fd0L } }, + /* 33 << 161 */ + { { 0x129eee2f53d64829L,0x7a471e17a261492bL,0xe4f9adb9e4cb4a2cL, + 0x3d359f6f97ba2c2dL }, + { 0x346c67860aacd697L,0x92b444c375c2f8a8L,0xc79fa117d85df44eL, + 0x56782372398ddf31L } }, + /* 34 << 161 */ + { { 0x60e690f2bbbab3b8L,0x4851f8ae8b04816bL,0xc72046ab9c92e4d2L, + 0x518c74a17cf3136bL }, + { 0xff4eb50af9877d4cL,0x14578d90a919cabbL,0x8218f8c4ac5eb2b6L, + 0xa3ccc547542016e4L } }, + /* 35 << 161 */ + { { 0x025bf48e327f8349L,0xf3e97346f43cb641L,0xdc2bafdf500f1085L, + 0x571678762f063055L }, + { 0x5bd914b9411925a6L,0x7c078d48a1123de5L,0xee6bf835182b165dL, + 0xb11b5e5bba519727L } }, + /* 36 << 161 */ + { { 0xe33ea76c1eea7b85L,0x2352b46192d4f85eL,0xf101d334afe115bbL, + 0xfabc1294889175a3L }, + { 0x7f6bcdc05233f925L,0xe0a802dbe77fec55L,0xbdb47b758069b659L, + 0x1c5e12def98fbd74L } }, + /* 37 << 161 */ + { { 0x869c58c64b8457eeL,0xa5360f694f7ea9f7L,0xe576c09ff460b38fL, + 0x6b70d54822b7fb36L }, + { 0x3fd237f13bfae315L,0x33797852cbdff369L,0x97df25f525b516f9L, + 0x46f388f2ba38ad2dL } }, + /* 38 << 161 */ + { { 0x656c465889d8ddbbL,0x8830b26e70f38ee8L,0x4320fd5cde1212b0L, + 0xc34f30cfe4a2edb2L }, + { 0xabb131a356ab64b8L,0x7f77f0ccd99c5d26L,0x66856a37bf981d94L, + 0x19e76d09738bd76eL } }, + /* 39 << 161 */ + { { 0xe76c8ac396238f39L,0xc0a482bea830b366L,0xb7b8eaff0b4eb499L, + 0x8ecd83bc4bfb4865L }, + { 0x971b2cb7a2f3776fL,0xb42176a4f4b88adfL,0xb9617df5be1fa446L, + 0x8b32d508cd031bd2L } }, + /* 40 << 161 */ + { { 0x1c6bd47d53b618c0L,0xc424f46c6a227923L,0x7303ffdedd92d964L, + 0xe971287871b5abf2L }, + { 0x8f48a632f815561dL,0x85f48ff5d3c055d1L,0x222a14277525684fL, + 0xd0d841a067360cc3L } }, + /* 41 << 161 */ + { { 0x4245a9260b9267c6L,0xc78913f1cf07f863L,0xaa844c8e4d0d9e24L, + 0xa42ad5223d5f9017L }, + { 0xbd371749a2c989d5L,0x928292dfe1f5e78eL,0x493b383e0a1ea6daL, + 0x5136fd8d13aee529L } }, + /* 42 << 161 */ + { { 0x860c44b1f2c34a99L,0x3b00aca4bf5855acL,0xabf6aaa0faaf37beL, + 0x65f436822a53ec08L }, + { 0x1d9a5801a11b12e1L,0x78a7ab2ce20ed475L,0x0de1067e9a41e0d5L, + 0x30473f5f305023eaL } }, + /* 43 << 161 */ + { { 0xdd3ae09d169c7d97L,0x5cd5baa4cfaef9cdL,0x5cd7440b65a44803L, + 0xdc13966a47f364deL }, + { 0x077b2be82b8357c1L,0x0cb1b4c5e9d57c2aL,0x7a4ceb3205ff363eL, + 0xf310fa4dca35a9efL } }, + /* 44 << 161 */ + { { 0xdbb7b352f97f68c6L,0x0c773b500b02cf58L,0xea2e48213c1f96d9L, + 0xffb357b0eee01815L }, + { 0xb9c924cde0f28039L,0x0b36c95a46a3fbe4L,0x1faaaea45e46db6cL, + 0xcae575c31928aaffL } }, + /* 45 << 161 */ + { { 0x7f671302a70dab86L,0xfcbd12a971c58cfcL,0xcbef9acfbee0cb92L, + 0x573da0b9f8c1b583L }, + { 0x4752fcfe0d41d550L,0xe7eec0e32155cffeL,0x0fc39fcb545ae248L, + 0x522cb8d18065f44eL } }, + /* 46 << 161 */ + { { 0x263c962a70cbb96cL,0xe034362abcd124a9L,0xf120db283c2ae58dL, + 0xb9a38d49fef6d507L }, + { 0xb1fd2a821ff140fdL,0xbd162f3020aee7e0L,0x4e17a5d4cb251949L, + 0x2aebcb834f7e1c3dL } }, + /* 47 << 161 */ + { { 0x608eb25f937b0527L,0xf42e1e47eb7d9997L,0xeba699c4b8a53a29L, + 0x1f921c71e091b536L }, + { 0xcce29e7b5b26bbd5L,0x7a8ef5ed3b61a680L,0xe5ef8043ba1f1c7eL, + 0x16ea821718158ddaL } }, + /* 48 << 161 */ + { { 0x01778a2b599ff0f9L,0x68a923d78104fc6bL,0x5bfa44dfda694ff3L, + 0x4f7199dbf7667f12L }, + { 0xc06d8ff6e46f2a79L,0x08b5deade9f8131dL,0x02519a59abb4ce7cL, + 0xc4f710bcb42aec3eL } }, + /* 49 << 161 */ + { { 0x3d77b05778bde41aL,0x6474bf80b4186b5aL,0x048b3f6788c65741L, + 0xc64519de03c7c154L }, + { 0xdf0738460edfcc4fL,0x319aa73748f1aa6bL,0x8b9f8a02ca909f77L, + 0x902581397580bfefL } }, + /* 50 << 161 */ + { { 0xd8bfd3cac0c22719L,0xc60209e4c9ca151eL,0x7a744ab5d9a1a69cL, + 0x6de5048b14937f8fL }, + { 0x171938d8e115ac04L,0x7df709401c6b16d2L,0xa6aeb6637f8e94e7L, + 0xc130388e2a2cf094L } }, + /* 51 << 161 */ + { { 0x1850be8477f54e6eL,0x9f258a7265d60fe5L,0xff7ff0c06c9146d6L, + 0x039aaf90e63a830bL }, + { 0x38f27a739460342fL,0x4703148c3f795f8aL,0x1bb5467b9681a97eL, + 0x00931ba5ecaeb594L } }, + /* 52 << 161 */ + { { 0xcdb6719d786f337cL,0xd9c01cd2e704397dL,0x0f4a3f20555c2fefL, + 0x004525097c0af223L }, + { 0x54a5804784db8e76L,0x3bacf1aa93c8aa06L,0x11ca957cf7919422L, + 0x5064105378cdaa40L } }, + /* 53 << 161 */ + { { 0x7a3038749f7144aeL,0x170c963f43d4acfdL,0x5e14814958ddd3efL, + 0xa7bde5829e72dba8L }, + { 0x0769da8b6fa68750L,0xfa64e532572e0249L,0xfcaadf9d2619ad31L, + 0x87882daaa7b349cdL } }, + /* 54 << 161 */ + { { 0x9f6eb7316c67a775L,0xcb10471aefc5d0b1L,0xb433750ce1b806b2L, + 0x19c5714d57b1ae7eL }, + { 0xc0dc8b7bed03fd3fL,0xdd03344f31bc194eL,0xa66c52a78c6320b5L, + 0x8bc82ce3d0b6fd93L } }, + /* 55 << 161 */ + { { 0xf8e13501b35f1341L,0xe53156dd25a43e42L,0xd3adf27e4daeb85cL, + 0xb81d8379bbeddeb5L }, + { 0x1b0b546e2e435867L,0x9020eb94eba5dd60L,0x37d911618210cb9dL, + 0x4c596b315c91f1cfL } }, + /* 56 << 161 */ + { { 0xb228a90f0e0b040dL,0xbaf02d8245ff897fL,0x2aac79e600fa6122L, + 0x248288178e36f557L }, + { 0xb9521d31113ec356L,0x9e48861e15eff1f8L,0x2aa1d412e0d41715L, + 0x71f8620353f131b8L } }, + /* 57 << 161 */ + { { 0xf60da8da3fd19408L,0x4aa716dc278d9d99L,0x394531f7a8c51c90L, + 0xb560b0e8f59db51cL }, + { 0xa28fc992fa34bdadL,0xf024fa149cd4f8bdL,0x5cf530f723a9d0d3L, + 0x615ca193e28c9b56L } }, + /* 58 << 161 */ + { { 0x6d2a483d6f73c51eL,0xa4cb2412ea0dc2ddL,0x50663c411eb917ffL, + 0x3d3a74cfeade299eL }, + { 0x29b3990f4a7a9202L,0xa9bccf59a7b15c3dL,0x66a3ccdca5df9208L, + 0x48027c1443f2f929L } }, + /* 59 << 161 */ + { { 0xd385377c40b557f0L,0xe001c366cd684660L,0x1b18ed6be2183a27L, + 0x879738d863210329L }, + { 0xa687c74bbda94882L,0xd1bbcc48a684b299L,0xaf6f1112863b3724L, + 0x6943d1b42c8ce9f8L } }, + /* 60 << 161 */ + { { 0xe044a3bb098cafb4L,0x27ed231060d48cafL,0x542b56753a31b84dL, + 0xcbf3dd50fcddbed7L }, + { 0x25031f1641b1d830L,0xa7ec851dcb0c1e27L,0xac1c8fe0b5ae75dbL, + 0xb24c755708c52120L } }, + /* 61 << 161 */ + { { 0x57f811dc1d4636c3L,0xf8436526681a9939L,0x1f6bc6d99c81adb3L, + 0x840f8ac35b7d80d4L }, + { 0x731a9811f4387f1aL,0x7c501cd3b5156880L,0xa5ca4a07dfe68867L, + 0xf123d8f05fcea120L } }, + /* 62 << 161 */ + { { 0x1fbb0e71d607039eL,0x2b70e215cd3a4546L,0x32d2f01d53324091L, + 0xb796ff08180ab19bL }, + { 0x32d87a863c57c4aaL,0x2aed9cafb7c49a27L,0x9fb35eac31630d98L, + 0x338e8cdf5c3e20a3L } }, + /* 63 << 161 */ + { { 0x80f1618266cde8dbL,0x4e1599802d72fd36L,0xd7b8f13b9b6e5072L, + 0xf52139073b7b5dc1L }, + { 0x4d431f1d8ce4396eL,0x37a1a680a7ed2142L,0xbf375696d01aaf6bL, + 0xaa1c0c54e63aab66L } }, + /* 64 << 161 */ + { { 0x3014368b4ed80940L,0x67e6d0567a6fceddL,0x7c208c49ca97579fL, + 0xfe3d7a81a23597f6L }, + { 0x5e2032027e096ae2L,0xb1f3e1e724b39366L,0x26da26f32fdcdffcL, + 0x79422f1d6097be83L } }, + /* 0 << 168 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 168 */ + { { 0x263a2cfb9db3b381L,0x9c3a2deed4df0a4bL,0x728d06e97d04e61fL, + 0x8b1adfbc42449325L }, + { 0x6ec1d9397e053a1bL,0xee2be5c766daf707L,0x80ba1e14810ac7abL, + 0xdd2ae778f530f174L } }, + /* 2 << 168 */ + { { 0x0435d97a205b9d8bL,0x6eb8f064056756d4L,0xd5e88a8bb6f8210eL, + 0x070ef12dec9fd9eaL }, + { 0x4d8495053bcc876aL,0x12a75338a7404ce3L,0xd22b49e1b8a1db5eL, + 0xec1f205114bfa5adL } }, + /* 3 << 168 */ + { { 0xadbaeb79b6828f36L,0x9d7a025801bd5b9eL,0xeda01e0d1e844b0cL, + 0x4b625175887edfc9L }, + { 0x14109fdd9669b621L,0x88a2ca56f6f87b98L,0xfe2eb788170df6bcL, + 0x0cea06f4ffa473f9L } }, + /* 4 << 168 */ + { { 0x43ed81b5c4e83d33L,0xd9f358795efd488bL,0x164a620f9deb4d0fL, + 0xc6927bdbac6a7394L }, + { 0x45c28df79f9e0f03L,0x2868661efcd7e1a9L,0x7cf4e8d0ffa348f1L, + 0x6bd4c284398538e0L } }, + /* 5 << 168 */ + { { 0x2618a091289a8619L,0xef796e606671b173L,0x664e46e59090c632L, + 0xa38062d41e66f8fbL }, + { 0x6c744a200573274eL,0xd07b67e4a9271394L,0x391223b26bdc0e20L, + 0xbe2d93f1eb0a05a7L } }, + /* 6 << 168 */ + { { 0xf23e2e533f36d141L,0xe84bb3d44dfca442L,0xb804a48d6b7c023aL, + 0x1e16a8fa76431c3bL }, + { 0x1b5452adddd472e0L,0x7d405ee70d1ee127L,0x50fc6f1dffa27599L, + 0x351ac53cbf391b35L } }, + /* 7 << 168 */ + { { 0x7efa14b84444896bL,0x64974d2ff94027fbL,0xefdcd0e8de84487dL, + 0x8c45b2602b48989bL }, + { 0xa8fcbbc2d8463487L,0xd1b2b3f73fbc476cL,0x21d005b7c8f443c0L, + 0x518f2e6740c0139cL } }, + /* 8 << 168 */ + { { 0x56036e8c06d75fc1L,0x2dcf7bb73249a89fL,0x81dd1d3de245e7ddL, + 0xf578dc4bebd6e2a7L }, + { 0x4c028903df2ce7a0L,0xaee362889c39afacL,0xdc847c31146404abL, + 0x6304c0d8a4e97818L } }, + /* 9 << 168 */ + { { 0xae51dca2a91f6791L,0x2abe41909baa9efcL,0xd9d2e2f4559c7ac1L, + 0xe82f4b51fc9f773aL }, + { 0xa77130274073e81cL,0xc0276facfbb596fcL,0x1d819fc9a684f70cL, + 0x29b47fddc9f7b1e0L } }, + /* 10 << 168 */ + { { 0x358de103459b1940L,0xec881c595b013e93L,0x51574c9349532ad3L, + 0x2db1d445b37b46deL }, + { 0xc6445b87df239fd8L,0xc718af75151d24eeL,0xaea1c4a4f43c6259L, + 0x40c0e5d770be02f7L } }, + /* 11 << 168 */ + { { 0x6a4590f4721b33f2L,0x2124f1fbfedf04eaL,0xf8e53cde9745efe7L, + 0xe7e1043265f046d9L }, + { 0xc3fca28ee4d0c7e6L,0x847e339a87253b1bL,0x9b5953483743e643L, + 0xcb6a0a0b4fd12fc5L } }, + /* 12 << 168 */ + { { 0xfb6836c327d02dccL,0x5ad009827a68bcc2L,0x1b24b44c005e912dL, + 0xcc83d20f811fdcfeL }, + { 0x36527ec1666fba0cL,0x6994819714754635L,0xfcdcb1a8556da9c2L, + 0xa593426781a732b2L } }, + /* 13 << 168 */ + { { 0xec1214eda714181dL,0x609ac13b6067b341L,0xff4b4c97a545df1fL, + 0xa124050134d2076bL }, + { 0x6efa0c231409ca97L,0x254cc1a820638c43L,0xd4e363afdcfb46cdL, + 0x62c2adc303942a27L } }, + /* 14 << 168 */ + { { 0xc67b9df056e46483L,0xa55abb2063736356L,0xab93c098c551bc52L, + 0x382b49f9b15fe64bL }, + { 0x9ec221ad4dff8d47L,0x79caf615437df4d6L,0x5f13dc64bb456509L, + 0xe4c589d9191f0714L } }, + /* 15 << 168 */ + { { 0x27b6a8ab3fd40e09L,0xe455842e77313ea9L,0x8b51d1e21f55988bL, + 0x5716dd73062bbbfcL }, + { 0x633c11e54e8bf3deL,0x9a0e77b61b85be3bL,0x565107290911cca6L, + 0x27e76495efa6590fL } }, + /* 16 << 168 */ + { { 0xe4ac8b33070d3aabL,0x2643672b9a2cd5e5L,0x52eff79b1cfc9173L, + 0x665ca49b90a7c13fL }, + { 0x5a8dda59b3efb998L,0x8a5b922d052f1341L,0xae9ebbab3cf9a530L, + 0x35986e7bf56da4d7L } }, + /* 17 << 168 */ + { { 0x3a636b5cff3513ccL,0xbb0cf8ba3198f7ddL,0xb8d4052241f16f86L, + 0x760575d8de13a7bfL }, + { 0x36f74e169f7aa181L,0x163a3ecff509ed1cL,0x6aead61f3c40a491L, + 0x158c95fcdfe8fcaaL } }, + /* 18 << 168 */ + { { 0xa3991b6e13cda46fL,0x79482415342faed0L,0xf3ba5bde666b5970L, + 0x1d52e6bcb26ab6ddL }, + { 0x768ba1e78608dd3dL,0x4930db2aea076586L,0xd9575714e7dc1afaL, + 0x1fc7bf7df7c58817L } }, + /* 19 << 168 */ + { { 0x6b47accdd9eee96cL,0x0ca277fbe58cec37L,0x113fe413e702c42aL, + 0xdd1764eec47cbe51L }, + { 0x041e7cde7b3ed739L,0x50cb74595ce9e1c0L,0x355685132925b212L, + 0x7cff95c4001b081cL } }, + /* 20 << 168 */ + { { 0x63ee4cbd8088b454L,0xdb7f32f79a9e0c8aL,0xb377d4186b2447cbL, + 0xe3e982aad370219bL }, + { 0x06ccc1e4c2a2a593L,0x72c368650773f24fL,0xa13b4da795859423L, + 0x8bbf1d3375040c8fL } }, + /* 21 << 168 */ + { { 0x726f0973da50c991L,0x48afcd5b822d6ee2L,0xe5fc718b20fd7771L, + 0xb9e8e77dfd0807a1L }, + { 0x7f5e0f4499a7703dL,0x6972930e618e36f3L,0x2b7c77b823807bbeL, + 0xe5b82405cb27ff50L } }, + /* 22 << 168 */ + { { 0xba8b8be3bd379062L,0xd64b7a1d2dce4a92L,0x040a73c5b2952e37L, + 0x0a9e252ed438aecaL }, + { 0xdd43956bc39d3bcbL,0x1a31ca00b32b2d63L,0xd67133b85c417a18L, + 0xd08e47902ef442c8L } }, + /* 23 << 168 */ + { { 0x98cb1ae9255c0980L,0x4bd863812b4a739fL,0x5a5c31e11e4a45a1L, + 0x1e5d55fe9cb0db2fL }, + { 0x74661b068ff5cc29L,0x026b389f0eb8a4f4L,0x536b21a458848c24L, + 0x2e5bf8ec81dc72b0L } }, + /* 24 << 168 */ + { { 0x03c187d0ad886aacL,0x5c16878ab771b645L,0xb07dfc6fc74045abL, + 0x2c6360bf7800caedL }, + { 0x24295bb5b9c972a3L,0xc9e6f88e7c9a6dbaL,0x90ffbf2492a79aa6L, + 0xde29d50a41c26ac2L } }, + /* 25 << 168 */ + { { 0x9f0af483d309cbe6L,0x5b020d8ae0bced4fL,0x606e986db38023e3L, + 0xad8f2c9d1abc6933L }, + { 0x19292e1de7400e93L,0xfe3e18a952be5e4dL,0xe8e9771d2e0680bfL, + 0x8c5bec98c54db063L } }, + /* 26 << 168 */ + { { 0x2af9662a74a55d1fL,0xe3fbf28f046f66d8L,0xa3a72ab4d4dc4794L, + 0x09779f455c7c2dd8L }, + { 0xd893bdafc3d19d8dL,0xd5a7509457d6a6dfL,0x8cf8fef9952e6255L, + 0x3da67cfbda9a8affL } }, + /* 27 << 168 */ + { { 0x4c23f62a2c160dcdL,0x34e6c5e38f90eaefL,0x35865519a9a65d5aL, + 0x07c48aae8fd38a3dL }, + { 0xb7e7aeda50068527L,0x2c09ef231c90936aL,0x31ecfeb6e879324cL, + 0xa0871f6bfb0ec938L } }, + /* 28 << 168 */ + { { 0xb1f0fb68d84d835dL,0xc90caf39861dc1e6L,0x12e5b0467594f8d7L, + 0x26897ae265012b92L }, + { 0xbcf68a08a4d6755dL,0x403ee41c0991fbdaL,0x733e343e3bbf17e8L, + 0xd2c7980d679b3d65L } }, + /* 29 << 168 */ + { { 0x33056232d2e11305L,0x966be492f3c07a6fL,0x6a8878ffbb15509dL, + 0xff2211010a9b59a4L }, + { 0x6c9f564aabe30129L,0xc6f2c940336e64cfL,0x0fe752628b0c8022L, + 0xbe0267e96ae8db87L } }, + /* 30 << 168 */ + { { 0x22e192f193bc042bL,0xf085b534b237c458L,0xa0d192bd832c4168L, + 0x7a76e9e3bdf6271dL }, + { 0x52a882fab88911b5L,0xc85345e4b4db0eb5L,0xa3be02a681a7c3ffL, + 0x51889c8cf0ec0469L } }, + /* 31 << 168 */ + { { 0x9d031369a5e829e5L,0xcbb4c6fc1607aa41L,0x75ac59a6241d84c1L, + 0xc043f2bf8829e0eeL }, + { 0x82a38f758ea5e185L,0x8bda40b9d87cbd9fL,0x9e65e75e2d8fc601L, + 0x3d515f74a35690b3L } }, + /* 32 << 168 */ + { { 0x534acf4fda79e5acL,0x68b83b3a8630215fL,0x5c748b2ed085756eL, + 0xb0317258e5d37cb2L }, + { 0x6735841ac5ccc2c4L,0x7d7dc96b3d9d5069L,0xa147e410fd1754bdL, + 0x65296e94d399ddd5L } }, + /* 33 << 168 */ + { { 0xf6b5b2d0bc8fa5bcL,0x8a5ead67500c277bL,0x214625e6dfa08a5dL, + 0x51fdfedc959cf047L }, + { 0x6bc9430b289fca32L,0xe36ff0cf9d9bdc3fL,0x2fe187cb58ea0edeL, + 0xed66af205a900b3fL } }, + /* 34 << 168 */ + { { 0x00e0968b5fa9f4d6L,0x2d4066ce37a362e7L,0xa99a9748bd07e772L, + 0x710989c006a4f1d0L }, + { 0xd5dedf35ce40cbd8L,0xab55c5f01743293dL,0x766f11448aa24e2cL, + 0x94d874f8605fbcb4L } }, + /* 35 << 168 */ + { { 0xa365f0e8a518001bL,0xee605eb69d04ef0fL,0x5a3915cdba8d4d25L, + 0x44c0e1b8b5113472L }, + { 0xcbb024e88b6740dcL,0x89087a53ee1d4f0cL,0xa88fa05c1fc4e372L, + 0x8bf395cbaf8b3af2L } }, + /* 36 << 168 */ + { { 0x1e71c9a1deb8568bL,0xa35daea080fb3d32L,0xe8b6f2662cf8fb81L, + 0x6d51afe89490696aL }, + { 0x81beac6e51803a19L,0xe3d24b7f86219080L,0x727cfd9ddf6f463cL, + 0x8c6865ca72284ee8L } }, + /* 37 << 168 */ + { { 0x32c88b7db743f4efL,0x3793909be7d11dceL,0xd398f9222ff2ebe8L, + 0x2c70ca44e5e49796L }, + { 0xdf4d9929cb1131b1L,0x7826f29825888e79L,0x4d3a112cf1d8740aL, + 0x00384cb6270afa8bL } }, + /* 38 << 168 */ + { { 0xcb64125b3ab48095L,0x3451c25662d05106L,0xd73d577da4955845L, + 0x39570c16bf9f4433L }, + { 0xd7dfaad3adecf263L,0xf1c3d8d1dc76e102L,0x5e774a5854c6a836L, + 0xdad4b6723e92d47bL } }, + /* 39 << 168 */ + { { 0xbe7e990ff0d796a0L,0x5fc62478df0e8b02L,0x8aae8bf4030c00adL, + 0x3d2db93b9004ba0fL }, + { 0xe48c8a79d85d5ddcL,0xe907caa76bb07f34L,0x58db343aa39eaed5L, + 0x0ea6e007adaf5724L } }, + /* 40 << 168 */ + { { 0xe00df169d23233f3L,0x3e32279677cb637fL,0x1f897c0e1da0cf6cL, + 0xa651f5d831d6bbddL }, + { 0xdd61af191a230c76L,0xbd527272cdaa5e4aL,0xca753636d0abcd7eL, + 0x78bdd37c370bd8dcL } }, + /* 41 << 168 */ + { { 0xc23916c217cd93feL,0x65b97a4ddadce6e2L,0xe04ed4eb174e42f8L, + 0x1491ccaabb21480aL }, + { 0x145a828023196332L,0x3c3862d7587b479aL,0x9f4a88a301dcd0edL, + 0x4da2b7ef3ea12f1fL } }, + /* 42 << 168 */ + { { 0xf8e7ae33b126e48eL,0x404a0b32f494e237L,0x9beac474c55acadbL, + 0x4ee5cf3bcbec9fd9L }, + { 0x336b33b97df3c8c3L,0xbd905fe3b76808fdL,0x8f436981aa45c16aL, + 0x255c5bfa3dd27b62L } }, + /* 43 << 168 */ + { { 0x71965cbfc3dd9b4dL,0xce23edbffc068a87L,0xb78d4725745b029bL, + 0x74610713cefdd9bdL }, + { 0x7116f75f1266bf52L,0x0204672218e49bb6L,0xdf43df9f3d6f19e3L, + 0xef1bc7d0e685cb2fL } }, + /* 44 << 168 */ + { { 0xcddb27c17078c432L,0xe1961b9cb77fedb7L,0x1edc2f5cc2290570L, + 0x2c3fefca19cbd886L }, + { 0xcf880a36c2af389aL,0x96c610fdbda71ceaL,0xf03977a932aa8463L, + 0x8eb7763f8586d90aL } }, + /* 45 << 168 */ + { { 0x3f3424542a296e77L,0xc871868342837a35L,0x7dc710906a09c731L, + 0x54778ffb51b816dbL }, + { 0x6b33bfecaf06defdL,0xfe3c105f8592b70bL,0xf937fda461da6114L, + 0x3c13e6514c266ad7L } }, + /* 46 << 168 */ + { { 0xe363a829855938e8L,0x2eeb5d9e9de54b72L,0xbeb93b0e20ccfab9L, + 0x3dffbb5f25e61a25L }, + { 0x7f655e431acc093dL,0x0cb6cc3d3964ce61L,0x6ab283a1e5e9b460L, + 0x55d787c5a1c7e72dL } }, + /* 47 << 168 */ + { { 0x4d2efd47deadbf02L,0x11e80219ac459068L,0x810c762671f311f0L, + 0xfa17ef8d4ab6ef53L }, + { 0xaf47fd2593e43bffL,0x5cb5ff3f0be40632L,0x546871068ee61da3L, + 0x7764196eb08afd0fL } }, + /* 48 << 168 */ + { { 0x831ab3edf0290a8fL,0xcae81966cb47c387L,0xaad7dece184efb4fL, + 0xdcfc53b34749110eL }, + { 0x6698f23c4cb632f9L,0xc42a1ad6b91f8067L,0xb116a81d6284180aL, + 0xebedf5f8e901326fL } }, + /* 49 << 168 */ + { { 0xf2274c9f97e3e044L,0x4201852011d09fc9L,0x56a65f17d18e6e23L, + 0x2ea61e2a352b683cL }, + { 0x27d291bc575eaa94L,0x9e7bc721b8ff522dL,0x5f7268bfa7f04d6fL, + 0x5868c73faba41748L } }, + /* 50 << 168 */ + { { 0x9f85c2db7be0eeadL,0x511e7842ff719135L,0x5a06b1e9c5ea90d7L, + 0x0c19e28326fab631L }, + { 0x8af8f0cfe9206c55L,0x89389cb43553c06aL,0x39dbed97f65f8004L, + 0x0621b037c508991dL } }, + /* 51 << 168 */ + { { 0x1c52e63596e78cc4L,0x5385c8b20c06b4a8L,0xd84ddfdbb0e87d03L, + 0xc49dfb66934bafadL }, + { 0x7071e17059f70772L,0x3a073a843a1db56bL,0x034949033b8af190L, + 0x7d882de3d32920f0L } }, + /* 52 << 168 */ + { { 0x91633f0ab2cf8940L,0x72b0b1786f948f51L,0x2d28dc30782653c8L, + 0x88829849db903a05L }, + { 0xb8095d0c6a19d2bbL,0x4b9e7f0c86f782cbL,0x7af739882d907064L, + 0xd12be0fe8b32643cL } }, + /* 53 << 168 */ + { { 0x358ed23d0e165dc3L,0x3d47ce624e2378ceL,0x7e2bb0b9feb8a087L, + 0x3246e8aee29e10b9L }, + { 0x459f4ec703ce2b4dL,0xe9b4ca1bbbc077cfL,0x2613b4f20e9940c1L, + 0xfc598bb9047d1eb1L } }, + /* 54 << 168 */ + { { 0x9744c62b45036099L,0xa9dee742167c65d8L,0x0c511525dabe1943L, + 0xda11055493c6c624L }, + { 0xae00a52c651a3be2L,0xcda5111d884449a6L,0x063c06f4ff33bed1L, + 0x73baaf9a0d3d76b4L } }, + /* 55 << 168 */ + { { 0x52fb0c9d7fc63668L,0x6886c9dd0c039cdeL,0x602bd59955b22351L, + 0xb00cab02360c7c13L }, + { 0x8cb616bc81b69442L,0x41486700b55c3ceeL,0x71093281f49ba278L, + 0xad956d9c64a50710L } }, + /* 56 << 168 */ + { { 0x9561f28b638a7e81L,0x54155cdf5980ddc3L,0xb2db4a96d26f247aL, + 0x9d774e4e4787d100L }, + { 0x1a9e6e2e078637d2L,0x1c363e2d5e0ae06aL,0x7493483ee9cfa354L, + 0x76843cb37f74b98dL } }, + /* 57 << 168 */ + { { 0xbaca6591d4b66947L,0xb452ce9804460a8cL,0x6830d24643768f55L, + 0xf4197ed87dff12dfL }, + { 0x6521b472400dd0f7L,0x59f5ca8f4b1e7093L,0x6feff11b080338aeL, + 0x0ada31f6a29ca3c6L } }, + /* 58 << 168 */ + { { 0x24794eb694a2c215L,0xd83a43ab05a57ab4L,0x264a543a2a6f89feL, + 0x2c2a3868dd5ec7c2L }, + { 0xd33739408439d9b2L,0x715ea6720acd1f11L,0x42c1d235e7e6cc19L, + 0x81ce6e96b990585cL } }, + /* 59 << 168 */ + { { 0x04e5dfe0d809c7bdL,0xd7b2580c8f1050abL,0x6d91ad78d8a4176fL, + 0x0af556ee4e2e897cL }, + { 0x162a8b73921de0acL,0x52ac9c227ea78400L,0xee2a4eeaefce2174L, + 0xbe61844e6d637f79L } }, + /* 60 << 168 */ + { { 0x0491f1bc789a283bL,0x72d3ac3d880836f4L,0xaa1c5ea388e5402dL, + 0x1b192421d5cc473dL }, + { 0x5c0b99989dc84cacL,0xb0a8482d9c6e75b8L,0x639961d03a191ce2L, + 0xda3bc8656d837930L } }, + /* 61 << 168 */ + { { 0xca990653056e6f8fL,0x84861c4164d133a7L,0x8b403276746abe40L, + 0xb7b4d51aebf8e303L }, + { 0x05b43211220a255dL,0xc997152c02419e6eL,0x76ff47b6630c2feaL, + 0x50518677281fdadeL } }, + /* 62 << 168 */ + { { 0x3283b8bacf902b0bL,0x8d4b4eb537db303bL,0xcc89f42d755011bcL, + 0xb43d74bbdd09d19bL }, + { 0x65746bc98adba350L,0x364eaf8cb51c1927L,0x13c7659610ad72ecL, + 0x30045121f8d40c20L } }, + /* 63 << 168 */ + { { 0x6d2d99b7ea7b979bL,0xcd78cd74e6fb3bcdL,0x11e45a9e86cffbfeL, + 0x78a61cf4637024f6L }, + { 0xd06bc8723d502295L,0xf1376854458cb288L,0xb9db26a1342f8586L, + 0xf33effcf4beee09eL } }, + /* 64 << 168 */ + { { 0xd7e0c4cdb30cfb3aL,0x6d09b8c16c9db4c8L,0x40ba1a4207c8d9dfL, + 0x6fd495f71c52c66dL }, + { 0xfb0e169f275264daL,0x80c2b746e57d8362L,0xedd987f749ad7222L, + 0xfdc229af4398ec7bL } }, + /* 0 << 175 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 175 */ + { { 0xb0d1ed8452666a58L,0x4bcb6e00e6a9c3c2L,0x3c57411c26906408L, + 0xcfc2075513556400L }, + { 0xa08b1c505294dba3L,0xa30ba2868b7dd31eL,0xd70ba90e991eca74L, + 0x094e142ce762c2b9L } }, + /* 2 << 175 */ + { { 0xb81d783e979f3925L,0x1efd130aaf4c89a7L,0x525c2144fd1bf7faL, + 0x4b2969041b265a9eL }, + { 0xed8e9634b9db65b6L,0x35c82e3203599d8aL,0xdaa7a54f403563f3L, + 0x9df088ad022c38abL } }, + /* 3 << 175 */ + { { 0xe5cfb066bb3fd30aL,0x429169daeff0354eL,0x809cf8523524e36cL, + 0x136f4fb30155be1dL }, + { 0x4826af011fbba712L,0x6ef0f0b4506ba1a1L,0xd9928b3177aea73eL, + 0xe2bf6af25eaa244eL } }, + /* 4 << 175 */ + { { 0x8d084f124237b64bL,0x688ebe99e3ecfd07L,0x57b8a70cf6845dd8L, + 0x808fc59c5da4a325L }, + { 0xa9032b2ba3585862L,0xb66825d5edf29386L,0xb5a5a8db431ec29bL, + 0xbb143a983a1e8dc8L } }, + /* 5 << 175 */ + { { 0x35ee94ce12ae381bL,0x3a7f176c86ccda90L,0xc63a657e4606eacaL, + 0x9ae5a38043cd04dfL }, + { 0x9bec8d15ed251b46L,0x1f5d6d30caca5e64L,0x347b3b359ff20f07L, + 0x4d65f034f7e4b286L } }, + /* 6 << 175 */ + { { 0x9e93ba24f111661eL,0xedced484b105eb04L,0x96dc9ba1f424b578L, + 0xbf8f66b7e83e9069L }, + { 0x872d4df4d7ed8216L,0xbf07f3778e2cbecfL,0x4281d89998e73754L, + 0xfec85fbb8aab8708L } }, + /* 7 << 175 */ + { { 0x9a3c0deea5ba5b0bL,0xe6a116ce42d05299L,0xae9775fee9b02d42L, + 0x72b05200a1545cb6L }, + { 0xbc506f7d31a3b4eaL,0xe58930788bbd9b32L,0xc8bc5f37e4b12a97L, + 0x6b000c064a73b671L } }, + /* 8 << 175 */ + { { 0x13b5bf22765fa7d0L,0x59805bf01d6a5370L,0x67a5e29d4280db98L, + 0x4f53916f776b1ce3L }, + { 0x714ff61f33ddf626L,0x4206238ea085d103L,0x1c50d4b7e5809ee3L, + 0x999f450d85f8eb1dL } }, + /* 9 << 175 */ + { { 0x658a6051e4c79e9bL,0x1394cb73c66a9feaL,0x27f31ed5c6be7b23L, + 0xf4c88f365aa6f8feL }, + { 0x0fb0721f4aaa499eL,0x68b3a7d5e3fb2a6bL,0xa788097d3a92851dL, + 0x060e7f8ae96f4913L } }, + /* 10 << 175 */ + { { 0x82eebe731a3a93bcL,0x42bbf465a21adc1aL,0xc10b6fa4ef030efdL, + 0x247aa4c787b097bbL }, + { 0x8b8dc632f60c77daL,0x6ffbc26ac223523eL,0xa4f6ff11344579cfL, + 0x5825653c980250f6L } }, + /* 11 << 175 */ + { { 0xb2dd097ebc1aa2b9L,0x0788939337a0333aL,0x1cf55e7137a0db38L, + 0x2648487f792c1613L }, + { 0xdad013363fcef261L,0x6239c81d0eabf129L,0x8ee761de9d276be2L, + 0x406a7a341eda6ad3L } }, + /* 12 << 175 */ + { { 0x4bf367ba4a493b31L,0x54f20a529bf7f026L,0xb696e0629795914bL, + 0xcddab96d8bf236acL }, + { 0x4ff2c70aed25ea13L,0xfa1d09eb81cbbbe7L,0x88fc8c87468544c5L, + 0x847a670d696b3317L } }, + /* 13 << 175 */ + { { 0xf133421e64bcb626L,0xaea638c826dee0b5L,0xd6e7680bb310346cL, + 0xe06f4097d5d4ced3L }, + { 0x099614527512a30bL,0xf3d867fde589a59aL,0x2e73254f52d0c180L, + 0x9063d8a3333c74acL } }, + /* 14 << 175 */ + { { 0xeda6c595d314e7bcL,0x2ee7464b467899edL,0x1cef423c0a1ed5d3L, + 0x217e76ea69cc7613L }, + { 0x27ccce1fe7cda917L,0x12d8016b8a893f16L,0xbcd6de849fc74f6bL, + 0xfa5817e2f3144e61L } }, + /* 15 << 175 */ + { { 0x1f3541640821ee4cL,0x1583eab40bc61992L,0x7490caf61d72879fL, + 0x998ad9f3f76ae7b2L }, + { 0x1e181950a41157f7L,0xa9d7e1e6e8da3a7eL,0x963784eb8426b95fL, + 0x0ee4ed6e542e2a10L } }, + /* 16 << 175 */ + { { 0xb79d4cc5ac751e7bL,0x93f96472fd4211bdL,0x8c72d3d2c8de4fc6L, + 0x7b69cbf5df44f064L }, + { 0x3da90ca2f4bf94e1L,0x1a5325f8f12894e2L,0x0a437f6c7917d60bL, + 0x9be7048696c9cb5dL } }, + /* 17 << 175 */ + { { 0xb4d880bfe1dc5c05L,0xd738addaeebeeb57L,0x6f0119d3df0fe6a3L, + 0x5c686e5566eaaf5aL }, + { 0x9cb10b50dfd0b7ecL,0xbdd0264b6a497c21L,0xfc0935148c546c96L, + 0x58a947fa79dbf42aL } }, + /* 18 << 175 */ + { { 0xc0b48d4e49ccd6d7L,0xff8fb02c88bd5580L,0xc75235e907d473b2L, + 0x4fab1ac5a2188af3L }, + { 0x030fa3bc97576ec0L,0xe8c946e80b7e7d2fL,0x40a5c9cc70305600L, + 0x6d8260a9c8b013b4L } }, + /* 19 << 175 */ + { { 0x0368304f70bba85cL,0xad090da1a4a0d311L,0x7170e8702415eec1L, + 0xbfba35fe8461ea47L }, + { 0x6279019ac1e91938L,0xa47638f31afc415fL,0x36c65cbbbcba0e0fL, + 0x02160efb034e2c48L } }, + /* 20 << 175 */ + { { 0xe6c51073615cd9e4L,0x498ec047f1243c06L,0x3e5a8809b17b3d8cL, + 0x5cd99e610cc565f1L }, + { 0x81e312df7851dafeL,0xf156f5baa79061e2L,0x80d62b71880c590eL, + 0xbec9746f0a39faa1L } }, + /* 21 << 175 */ + { { 0x1d98a9c1c8ed1f7aL,0x09e43bb5a81d5ff2L,0xd5f00f680da0794aL, + 0x412050d9661aa836L }, + { 0xa89f7c4e90747e40L,0x6dc05ebbb62a3686L,0xdf4de847308e3353L, + 0x53868fbb9fb53bb9L } }, + /* 22 << 175 */ + { { 0x2b09d2c3cfdcf7ddL,0x41a9fce3723fcab4L,0x73d905f707f57ca3L, + 0x080f9fb1ac8e1555L }, + { 0x7c088e849ba7a531L,0x07d35586ed9a147fL,0x602846abaf48c336L, + 0x7320fd320ccf0e79L } }, + /* 23 << 175 */ + { { 0xaa780798b18bd1ffL,0x52c2e300afdd2905L,0xf27ea3d6434267cdL, + 0x8b96d16d15605b5fL }, + { 0x7bb310494b45706bL,0xe7f58b8e743d25f8L,0xe9b5e45b87f30076L, + 0xd19448d65d053d5aL } }, + /* 24 << 175 */ + { { 0x1ecc8cb9d3210a04L,0x6bc7d463dafb5269L,0x3e59b10a67c3489fL, + 0x1769788c65641e1bL }, + { 0x8a53b82dbd6cb838L,0x7066d6e6236d5f22L,0x03aa1c616908536eL, + 0xc971da0d66ae9809L } }, + /* 25 << 175 */ + { { 0x01b3a86bc49a2facL,0x3b8420c03092e77aL,0x020573007d6fb556L, + 0x6941b2a1bff40a87L }, + { 0x140b63080658ff2aL,0x878043633424ab36L,0x0253bd515751e299L, + 0xc75bcd76449c3e3aL } }, + /* 26 << 175 */ + { { 0x92eb40907f8f875dL,0x9c9d754e56c26bbfL,0x158cea618110bbe7L, + 0x62a6b802745f91eaL }, + { 0xa79c41aac6e7394bL,0x445b6a83ad57ef10L,0x0c5277eb6ea6f40cL, + 0x319fe96b88633365L } }, + /* 27 << 175 */ + { { 0x0b0fc61f385f63cbL,0x41250c8422bdd127L,0x67d153f109e942c2L, + 0x60920d08c021ad5dL }, + { 0x229f5746724d81a5L,0xb7ffb8925bba3299L,0x518c51a1de413032L, + 0x2a9bfe773c2fd94cL } }, + /* 28 << 175 */ + { { 0xcbcde2393191f4fdL,0x43093e16d3d6ada1L,0x184579f358769606L, + 0x2c94a8b3d236625cL }, + { 0x6922b9c05c437d8eL,0x3d4ae423d8d9f3c8L,0xf72c31c12e7090a2L, + 0x4ac3f5f3d76a55bdL } }, + /* 29 << 175 */ + { { 0x342508fc6b6af991L,0x0d5271001b5cebbdL,0xb84740d0dd440dd7L, + 0x748ef841780162fdL }, + { 0xa8dbfe0edfc6fafbL,0xeadfdf05f7300f27L,0x7d06555ffeba4ec9L, + 0x12c56f839e25fa97L } }, + /* 30 << 175 */ + { { 0x77f84203d39b8c34L,0xed8b1be63125eddbL,0x5bbf2441f6e39dc5L, + 0xb00f6ee66a5d678aL }, + { 0xba456ecf57d0ea99L,0xdcae0f5817e06c43L,0x01643de40f5b4baaL, + 0x2c324341d161b9beL } }, + /* 31 << 175 */ + { { 0x80177f55e126d468L,0xed325f1f76748e09L,0x6116004acfa9bdc2L, + 0x2d8607e63a9fb468L }, + { 0x0e573e276009d660L,0x3a525d2e8d10c5a1L,0xd26cb45c3b9009a0L, + 0xb6b0cdc0de9d7448L } }, + /* 32 << 175 */ + { { 0x949c9976e1337c26L,0x6faadebdd73d68e5L,0x9e158614f1b768d9L, + 0x22dfa5579cc4f069L }, + { 0xccd6da17be93c6d6L,0x24866c61a504f5b9L,0x2121353c8d694da1L, + 0x1c6ca5800140b8c6L } }, + /* 33 << 175 */ + { { 0xc245ad8ce964021eL,0xb83bffba032b82b3L,0xfaa220c647ef9898L, + 0x7e8d3ac6982c948aL }, + { 0x1faa2091bc2d124aL,0xbd54c3dd05b15ff4L,0x386bf3abc87c6fb7L, + 0xfb2b0563fdeb6f66L } }, + /* 34 << 175 */ + { { 0x4e77c5575b45afb4L,0xe9ded649efb8912dL,0x7ec9bbf542f6e557L, + 0x2570dfff62671f00L }, + { 0x2b3bfb7888e084bdL,0xa024b238f37fe5b4L,0x44e7dc0495649aeeL, + 0x498ca2555e7ec1d8L } }, + /* 35 << 175 */ + { { 0x3bc766eaaaa07e86L,0x0db6facbf3608586L,0xbadd2549bdc259c8L, + 0x95af3c6e041c649fL }, + { 0xb36a928c02e30afbL,0x9b5356ad008a88b8L,0x4b67a5f1cf1d9e9dL, + 0xc6542e47a5d8d8ceL } }, + /* 36 << 175 */ + { { 0x73061fe87adfb6ccL,0xcc826fd398678141L,0x00e758b13c80515aL, + 0x6afe324741485083L }, + { 0x0fcb08b9b6ae8a75L,0xb8cf388d4acf51e1L,0x344a55606961b9d6L, + 0x1a6778b86a97fd0cL } }, + /* 37 << 175 */ + { { 0xd840fdc1ecc4c7e3L,0xde9fe47d16db68ccL,0xe95f89dea3e216aaL, + 0x84f1a6a49594a8beL }, + { 0x7ddc7d725a7b162bL,0xc5cfda19adc817a3L,0x80a5d35078b58d46L, + 0x93365b1382978f19L } }, + /* 38 << 175 */ + { { 0x2e44d22526a1fc90L,0x0d6d10d24d70705dL,0xd94b6b10d70c45f4L, + 0x0f201022b216c079L }, + { 0xcec966c5658fde41L,0xa8d2bc7d7e27601dL,0xbfcce3e1ff230be7L, + 0x3394ff6b0033ffb5L } }, + /* 39 << 175 */ + { { 0xd890c5098132c9afL,0xaac4b0eb361e7868L,0x5194ded3e82d15aaL, + 0x4550bd2e23ae6b7dL }, + { 0x3fda318eea5399d4L,0xd989bffa91638b80L,0x5ea124d0a14aa12dL, + 0x1fb1b8993667b944L } }, + /* 40 << 175 */ + { { 0x95ec796944c44d6aL,0x91df144a57e86137L,0x915fd62073adac44L, + 0x8f01732d59a83801L }, + { 0xec579d253aa0a633L,0x06de5e7cc9d6d59cL,0xc132f958b1ef8010L, + 0x29476f96e65c1a02L } }, + /* 41 << 175 */ + { { 0x336a77c0d34c3565L,0xef1105b21b9f1e9eL,0x63e6d08bf9e08002L, + 0x9aff2f21c613809eL }, + { 0xb5754f853a80e75dL,0xde71853e6bbda681L,0x86f041df8197fd7aL, + 0x8b332e08127817faL } }, + /* 42 << 175 */ + { { 0x05d99be8b9c20cdaL,0x89f7aad5d5cd0c98L,0x7ef936fe5bb94183L, + 0x92ca0753b05cd7f2L }, + { 0x9d65db1174a1e035L,0x02628cc813eaea92L,0xf2d9e24249e4fbf2L, + 0x94fdfd9be384f8b7L } }, + /* 43 << 175 */ + { { 0x65f5605463428c6bL,0x2f7205b290b409a5L,0xf778bb78ff45ae11L, + 0xa13045bec5ee53b2L }, + { 0xe00a14ff03ef77feL,0x689cd59fffef8befL,0x3578f0ed1e9ade22L, + 0xe99f3ec06268b6a8L } }, + /* 44 << 175 */ + { { 0xa2057d91ea1b3c3eL,0x2d1a7053b8823a4aL,0xabbb336a2cca451eL, + 0xcd2466e32218bb5dL }, + { 0x3ac1f42fc8cb762dL,0x7e312aae7690211fL,0xebb9bd7345d07450L, + 0x207c4b8246c2213fL } }, + /* 45 << 175 */ + { { 0x99d425c1375913ecL,0x94e45e9667908220L,0xc08f3087cd67dbf6L, + 0xa5670fbec0887056L }, + { 0x6717b64a66f5b8fcL,0xd5a56aea786fec28L,0xa8c3f55fc0ff4952L, + 0xa77fefae457ac49bL } }, + /* 46 << 175 */ + { { 0x29882d7c98379d44L,0xd000bdfb509edc8aL,0xc6f95979e66fe464L, + 0x504a6115fa61bde0L }, + { 0x56b3b871effea31aL,0x2d3de26df0c21a54L,0x21dbff31834753bfL, + 0xe67ecf4969269d86L } }, + /* 47 << 175 */ + { { 0x7a176952151fe690L,0x035158047f2adb5fL,0xee794b15d1b62a8dL, + 0xf004ceecaae454e6L }, + { 0x0897ea7cf0386facL,0x3b62ff12d1fca751L,0x154181df1b7a04ecL, + 0x2008e04afb5847ecL } }, + /* 48 << 175 */ + { { 0xd147148e41dbd772L,0x2b419f7322942654L,0x669f30d3e9c544f7L, + 0x52a2c223c8540149L }, + { 0x5da9ee14634dfb02L,0x5f074ff0f47869f3L,0x74ee878da3933accL, + 0xe65106514fe35ed1L } }, + /* 49 << 175 */ + { { 0xb3eb9482f1012e7aL,0x51013cc0a8a566aeL,0xdd5e924347c00d3bL, + 0x7fde089d946bb0e5L }, + { 0x030754fec731b4b3L,0x12a136a499fda062L,0x7c1064b85a1a35bcL, + 0xbf1f5763446c84efL } }, + /* 50 << 175 */ + { { 0xed29a56da16d4b34L,0x7fba9d09dca21c4fL,0x66d7ac006d8de486L, + 0x6006198773a2a5e1L }, + { 0x8b400f869da28ff0L,0x3133f70843c4599cL,0x9911c9b8ee28cb0dL, + 0xcd7e28748e0af61dL } }, + /* 51 << 175 */ + { { 0x5a85f0f272ed91fcL,0x85214f319cd4a373L,0x881fe5be1925253cL, + 0xd8dc98e091e8bc76L }, + { 0x7120affe585cc3a2L,0x724952ed735bf97aL,0x5581e7dc3eb34581L, + 0x5cbff4f2e52ee57dL } }, + /* 52 << 175 */ + { { 0x8d320a0e87d8cc7bL,0x9beaa7f3f1d280d0L,0x7a0b95719beec704L, + 0x9126332e5b7f0057L }, + { 0x01fbc1b48ed3bd6dL,0x35bb2c12d945eb24L,0x6404694e9a8ae255L, + 0xb6092eec8d6abfb3L } }, + /* 53 << 175 */ + { { 0x4d76143fcc058865L,0x7b0a5af26e249922L,0x8aef94406a50d353L, + 0xe11e4bcc64f0e07aL }, + { 0x4472993aa14a90faL,0x7706e20cba0c51d4L,0xf403292f1532672dL, + 0x52573bfa21829382L } }, + /* 54 << 175 */ + { { 0x6a7bb6a93b5bdb83L,0x08da65c0a4a72318L,0xc58d22aa63eb065fL, + 0x1717596c1b15d685L }, + { 0x112df0d0b266d88bL,0xf688ae975941945aL,0x487386e37c292cacL, + 0x42f3b50d57d6985cL } }, + /* 55 << 175 */ + { { 0x6da4f9986a90fc34L,0xc8f257d365ca8a8dL,0xc2feabca6951f762L, + 0xe1bc81d074c323acL }, + { 0x1bc68f67251a2a12L,0x10d86587be8a70dcL,0xd648af7ff0f84d2eL, + 0xf0aa9ebc6a43ac92L } }, + /* 56 << 175 */ + { { 0x69e3be0427596893L,0xb6bb02a645bf452bL,0x0875c11af4c698c8L, + 0x6652b5c7bece3794L }, + { 0x7b3755fd4f5c0499L,0x6ea16558b5532b38L,0xd1c69889a2e96ef7L, + 0x9c773c3a61ed8f48L } }, + /* 57 << 175 */ + { { 0x2b653a409b323abcL,0xe26605e1f0e1d791L,0x45d410644a87157aL, + 0x8f9a78b7cbbce616L }, + { 0xcf1e44aac407edddL,0x81ddd1d8a35b964fL,0x473e339efd083999L, + 0x6c94bdde8e796802L } }, + /* 58 << 175 */ + { { 0x5a304ada8545d185L,0x82ae44ea738bb8cbL,0x628a35e3df87e10eL, + 0xd3624f3da15b9fe3L }, + { 0xcc44209b14be4254L,0x7d0efcbcbdbc2ea5L,0x1f60336204c37bbeL, + 0x21f363f556a5852cL } }, + /* 59 << 175 */ + { { 0xa1503d1ca8501550L,0x2251e0e1d8ab10bbL,0xde129c966961c51cL, + 0x1f7246a481910f68L }, + { 0x2eb744ee5f2591f2L,0x3c47d33f5e627157L,0x4d6d62c922f3bd68L, + 0x6120a64bcb8df856L } }, + /* 60 << 175 */ + { { 0x3a9ac6c07b5d07dfL,0xa92b95587ef39783L,0xe128a134ab3a9b4fL, + 0x41c18807b1252f05L }, + { 0xfc7ed08980ba9b1cL,0xac8dc6dec532a9ddL,0xbf829cef55246809L, + 0x101b784f5b4ee80fL } }, + /* 61 << 175 */ + { { 0xc09945bbb6f11603L,0x57b09dbe41d2801eL,0xfba5202fa97534a8L, + 0x7fd8ae5fc17b9614L }, + { 0xa50ba66678308435L,0x9572f77cd3868c4dL,0x0cef7bfd2dd7aab0L, + 0xe7958e082c7c79ffL } }, + /* 62 << 175 */ + { { 0x81262e4225346689L,0x716da290b07c7004L,0x35f911eab7950ee3L, + 0x6fd72969261d21b5L }, + { 0x5238980308b640d3L,0x5b0026ee887f12a1L,0x20e21660742e9311L, + 0x0ef6d5415ff77ff7L } }, + /* 63 << 175 */ + { { 0x969127f0f9c41135L,0xf21d60c968a64993L,0x656e5d0ce541875cL, + 0xf1e0f84ea1d3c233L }, + { 0x9bcca35906002d60L,0xbe2da60c06191552L,0x5da8bbae61181ec3L, + 0x9f04b82365806f19L } }, + /* 64 << 175 */ + { { 0xf1604a7dd4b79bb8L,0xaee806fb52c878c8L,0x34144f118d47b8e8L, + 0x72edf52b949f9054L }, + { 0xebfca84e2127015aL,0x9051d0c09cb7cef3L,0x86e8fe58296deec8L, + 0x33b2818841010d74L } }, + /* 0 << 182 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 182 */ + { { 0x01079383171b445fL,0x9bcf21e38131ad4cL,0x8cdfe205c93987e8L, + 0xe63f4152c92e8c8fL }, + { 0x729462a930add43dL,0x62ebb143c980f05aL,0x4f3954e53b06e968L, + 0xfe1d75ad242cf6b1L } }, + /* 2 << 182 */ + { { 0x5f95c6c7af8685c8L,0xd4c1c8ce2f8f01aaL,0xc44bbe322574692aL, + 0xb8003478d4a4a068L }, + { 0x7c8fc6e52eca3cdbL,0xea1db16bec04d399L,0xb05bc82e8f2bc5cfL, + 0x763d517ff44793d2L } }, + /* 3 << 182 */ + { { 0x4451c1b808bd98d0L,0x644b1cd46575f240L,0x6907eb337375d270L, + 0x56c8bebdfa2286bdL }, + { 0xc713d2acc4632b46L,0x17da427aafd60242L,0x313065b7c95c7546L, + 0xf8239898bf17a3deL } }, + /* 4 << 182 */ + { { 0xf3b7963f4c830320L,0x842c7aa0903203e3L,0xaf22ca0ae7327afbL, + 0x38e13092967609b6L }, + { 0x73b8fb62757558f1L,0x3cc3e831f7eca8c1L,0xe4174474f6331627L, + 0xa77989cac3c40234L } }, + /* 5 << 182 */ + { { 0xe5fd17a144a081e0L,0xd797fb7db70e296aL,0x2b472b30481f719cL, + 0x0e632a98fe6f8c52L }, + { 0x89ccd116c5f0c284L,0xf51088af2d987c62L,0x2a2bccda4c2de6cfL, + 0x810f9efef679f0f9L } }, + /* 6 << 182 */ + { { 0xb0f394b97ffe4b3eL,0x0b691d21e5fa5d21L,0xb0bd77479dfbbc75L, + 0xd2830fdafaf78b00L }, + { 0xf78c249c52434f57L,0x4b1f754598096dabL,0x73bf6f948ff8c0b3L, + 0x34aef03d454e134cL } }, + /* 7 << 182 */ + { { 0xf8d151f4b7ac7ec5L,0xd6ceb95ae50da7d5L,0xa1b492b0dc3a0eb8L, + 0x75157b69b3dd2863L }, + { 0xe2c4c74ec5413d62L,0xbe329ff7bc5fc4c7L,0x835a2aea60fa9ddaL, + 0xf117f5ad7445cb87L } }, + /* 8 << 182 */ + { { 0xae8317f4b0166f7aL,0xfbd3e3f7ceec74e6L,0xfdb516ace0874bfdL, + 0x3d846019c681f3a3L }, + { 0x0b12ee5c7c1620b0L,0xba68b4dd2b63c501L,0xac03cd326668c51eL, + 0x2a6279f74e0bcb5bL } }, + /* 9 << 182 */ + { { 0x17bd69b06ae85c10L,0x729469791dfdd3a6L,0xd9a032682c078becL, + 0x41c6a658bfd68a52L }, + { 0xcdea10240e023900L,0xbaeec121b10d144dL,0x5a600e74058ab8dcL, + 0x1333af21bb89ccddL } }, + /* 10 << 182 */ + { { 0xdf25eae03aaba1f1L,0x2cada16e3b7144cfL,0x657ee27d71ab98bcL, + 0x99088b4c7a6fc96eL }, + { 0x05d5c0a03549dbd4L,0x42cbdf8ff158c3acL,0x3fb6b3b087edd685L, + 0x22071cf686f064d0L } }, + /* 11 << 182 */ + { { 0xd2d6721fff2811e5L,0xdb81b703fe7fae8cL,0x3cfb74efd3f1f7bbL, + 0x0cdbcd7616cdeb5dL }, + { 0x4f39642a566a808cL,0x02b74454340064d6L,0xfabbadca0528fa6fL, + 0xe4c3074cd3fc0bb6L } }, + /* 12 << 182 */ + { { 0xb32cb8b0b796d219L,0xc3e95f4f34741dd9L,0x8721212568edf6f5L, + 0x7a03aee4a2b9cb8eL }, + { 0x0cd3c376f53a89aaL,0x0d8af9b1948a28dcL,0xcf86a3f4902ab04fL, + 0x8aacb62a7f42002dL } }, + /* 13 << 182 */ + { { 0x106985ebf62ffd52L,0xe670b54e5797bf10L,0x4b405209c5e30aefL, + 0x12c97a204365b5e9L }, + { 0x104646ce1fe32093L,0x13cb4ff63907a8c9L,0x8b9f30d1d46e726bL, + 0xe1985e21aba0f499L } }, + /* 14 << 182 */ + { { 0xc573dea910a230cdL,0x24f46a93cd30f947L,0xf2623fcfabe2010aL, + 0x3f278cb273f00e4fL }, + { 0xed55c67d50b920ebL,0xf1cb9a2d8e760571L,0x7c50d1090895b709L, + 0x4207cf07190d4369L } }, + /* 15 << 182 */ + { { 0x3b027e81c4127fe1L,0xa9f8b9ad3ae9c566L,0x5ab10851acbfbba5L, + 0xa747d648569556f5L }, + { 0xcc172b5c2ba97bf7L,0x15e0f77dbcfa3324L,0xa345b7977686279dL, + 0x5a723480e38003d3L } }, + /* 16 << 182 */ + { { 0xfd8e139f8f5fcda8L,0xf3e558c4bdee5bfdL,0xd76cbaf4e33f9f77L, + 0x3a4c97a471771969L }, + { 0xda27e84bf6dce6a7L,0xff373d9613e6c2d1L,0xf115193cd759a6e9L, + 0x3f9b702563d2262cL } }, + /* 17 << 182 */ + { { 0xd9764a31317cd062L,0x30779d8e199f8332L,0xd807410616b11b0bL, + 0x7917ab9f78aeaed8L }, + { 0xb67a9cbe28fb1d8eL,0x2e313563136eda33L,0x010b7069a371a86cL, + 0x44d90fa26744e6b7L } }, + /* 18 << 182 */ + { { 0x68190867d6b3e243L,0x9fe6cd9d59048c48L,0xb900b02895731538L, + 0xa012062f32cae04fL }, + { 0x8107c8bc9399d082L,0x47e8c54a41df12e2L,0x14ba5117b6ef3f73L, + 0x22260bea81362f0bL } }, + /* 19 << 182 */ + { { 0x90ea261e1a18cc20L,0x2192999f2321d636L,0xef64d314e311b6a0L, + 0xd7401e4c3b54a1f5L }, + { 0x190199836fbca2baL,0x46ad32938fbffc4bL,0xa142d3f63786bf40L, + 0xeb5cbc26b67039fcL } }, + /* 20 << 182 */ + { { 0x9cb0ae6c252bd479L,0x05e0f88a12b5848fL,0x78f6d2b2a5c97663L, + 0x6f6e149bc162225cL }, + { 0xe602235cde601a89L,0xd17bbe98f373be1fL,0xcaf49a5ba8471827L, + 0x7e1a0a8518aaa116L } }, + /* 21 << 182 */ + { { 0x6c833196270580c3L,0x1e233839f1c98a14L,0x67b2f7b4ae34e0a5L, + 0x47ac8745d8ce7289L }, + { 0x2b74779a100dd467L,0x274a43374ee50d09L,0x603dcf1383608bc9L, + 0xcd9da6c3c89e8388L } }, + /* 22 << 182 */ + { { 0x2660199f355116acL,0xcc38bb59b6d18eedL,0x3075f31f2f4bc071L, + 0x9774457f265dc57eL }, + { 0x06a6a9c8c6db88bbL,0x6429d07f4ec98e04L,0x8d05e57b05ecaa8bL, + 0x20f140b17872ea7bL } }, + /* 23 << 182 */ + { { 0xdf8c0f09ca494693L,0x48d3a020f252e909L,0x4c5c29af57b14b12L, + 0x7e6fa37dbf47ad1cL }, + { 0x66e7b50649a0c938L,0xb72c0d486be5f41fL,0x6a6242b8b2359412L, + 0xcd35c7748e859480L } }, + /* 24 << 182 */ + { { 0x12536fea87baa627L,0x58c1fec1f72aa680L,0x6c29b637601e5dc9L, + 0x9e3c3c1cde9e01b9L }, + { 0xefc8127b2bcfe0b0L,0x351071022a12f50dL,0x6ccd6cb14879b397L, + 0xf792f804f8a82f21L } }, + /* 25 << 182 */ + { { 0x509d4804a9b46402L,0xedddf85dc10f0850L,0x928410dc4b6208aaL, + 0xf6229c46391012dcL }, + { 0xc5a7c41e7727b9b6L,0x289e4e4baa444842L,0x049ba1d9e9a947eaL, + 0x44f9e47f83c8debcL } }, + /* 26 << 182 */ + { { 0xfa77a1fe611f8b8eL,0xfd2e416af518f427L,0xc5fffa70114ebac3L, + 0xfe57c4e95d89697bL }, + { 0xfdd053acb1aaf613L,0x31df210fea585a45L,0x318cc10e24985034L, + 0x1a38efd15f1d6130L } }, + /* 27 << 182 */ + { { 0xbf86f2370b1e9e21L,0xb258514d1dbe88aaL,0x1e38a58890c1baf9L, + 0x2936a01ebdb9b692L }, + { 0xd576de986dd5b20cL,0xb586bf7170f98ecfL,0xcccf0f12c42d2fd7L, + 0x8717e61cfb35bd7bL } }, + /* 28 << 182 */ + { { 0x8b1e572235e6fc06L,0x3477728f0b3e13d5L,0x150c294daa8a7372L, + 0xc0291d433bfa528aL }, + { 0xc6c8bc67cec5a196L,0xdeeb31e45c2e8a7cL,0xba93e244fb6e1c51L, + 0xb9f8b71b2e28e156L } }, + /* 29 << 182 */ + { { 0xce65a287968a2ab9L,0xe3c5ce6946bbcb1fL,0xf8c835b9e7ae3f30L, + 0x16bbee26ff72b82bL }, + { 0x665e2017fd42cd22L,0x1e139970f8b1d2a0L,0x125cda2979204932L, + 0x7aee94a549c3bee5L } }, + /* 30 << 182 */ + { { 0x68c7016089821a66L,0xf7c376788f981669L,0xd90829fc48cc3645L, + 0x346af049d70addfcL }, + { 0x2057b232370bf29cL,0xf90c73ce42e650eeL,0xe03386eaa126ab90L, + 0x0e266e7e975a087bL } }, + /* 31 << 182 */ + { { 0x80578eb90fca65d9L,0x7e2989ea16af45b8L,0x7438212dcac75a4eL, + 0x38c7ca394fef36b8L }, + { 0x8650c494d402676aL,0x26ab5a66f72c7c48L,0x4e6cb426ce3a464eL, + 0xf8f998962b72f841L } }, + /* 32 << 182 */ + { { 0x8c3184911a335cc8L,0x563459ba6a5913e4L,0x1b920d61c7b32919L, + 0x805ab8b6a02425adL }, + { 0x2ac512da8d006086L,0x6ca4846abcf5c0fdL,0xafea51d8ac2138d7L, + 0xcb647545344cd443L } }, + /* 33 << 182 */ + { { 0x0429ee8fbd7d9040L,0xee66a2de819b9c96L,0x54f9ec25dea7d744L, + 0x2ffea642671721bbL }, + { 0x4f19dbd1114344eaL,0x04304536fd0dbc8bL,0x014b50aa29ec7f91L, + 0xb5fc22febb06014dL } }, + /* 34 << 182 */ + { { 0x60d963a91ee682e0L,0xdf48abc0fe85c727L,0x0cadba132e707c2dL, + 0xde608d3aa645aeffL }, + { 0x05f1c28bedafd883L,0x3c362edebd94de1fL,0x8dd0629d13593e41L, + 0x0a5e736f766d6eafL } }, + /* 35 << 182 */ + { { 0xbfa92311f68cf9d1L,0xa4f9ef87c1797556L,0x10d75a1f5601c209L, + 0x651c374c09b07361L }, + { 0x49950b5888b5ceadL,0x0ef000586fa9dbaaL,0xf51ddc264e15f33aL, + 0x1f8b5ca62ef46140L } }, + /* 36 << 182 */ + { { 0x343ac0a3ee9523f0L,0xbb75eab2975ea978L,0x1bccf332107387f4L, + 0x790f92599ab0062eL }, + { 0xf1a363ad1e4f6a5fL,0x06e08b8462519a50L,0x609151877265f1eeL, + 0x6a80ca3493ae985eL } }, + /* 37 << 182 */ + { { 0x81b29768aaba4864L,0xb13cabf28d52a7d6L,0xb5c363488ead03f1L, + 0xc932ad9581c7c1c0L }, + { 0x5452708ecae1e27bL,0x9dac42691b0df648L,0x233e3f0cdfcdb8bcL, + 0xe6ceccdfec540174L } }, + /* 38 << 182 */ + { { 0xbd0d845e95081181L,0xcc8a7920699355d5L,0x111c0f6dc3b375a8L, + 0xfd95bc6bfd51e0dcL }, + { 0x4a106a266888523aL,0x4d142bd6cb01a06dL,0x79bfd289adb9b397L, + 0x0bdbfb94e9863914L } }, + /* 39 << 182 */ + { { 0x29d8a2291660f6a6L,0x7f6abcd6551c042dL,0x13039deb0ac3ffe8L, + 0xa01be628ec8523fbL }, + { 0x6ea341030ca1c328L,0xc74114bdb903928eL,0x8aa4ff4e9e9144b0L, + 0x7064091f7f9a4b17L } }, + /* 40 << 182 */ + { { 0xa3f4f521e447f2c4L,0x81b8da7a604291f0L,0xd680bc467d5926deL, + 0x84f21fd534a1202fL }, + { 0x1d1e31814e9df3d8L,0x1ca4861a39ab8d34L,0x809ddeec5b19aa4aL, + 0x59f72f7e4d329366L } }, + /* 41 << 182 */ + { { 0xa2f93f41386d5087L,0x40bf739cdd67d64fL,0xb449420566702158L, + 0xc33c65be73b1e178L }, + { 0xcdcd657c38ca6153L,0x97f4519adc791976L,0xcc7c7f29cd6e1f39L, + 0x38de9cfb7e3c3932L } }, + /* 42 << 182 */ + { { 0xe448eba37b793f85L,0xe9f8dbf9f067e914L,0xc0390266f114ae87L, + 0x39ed75a7cd6a8e2aL }, + { 0xadb148487ffba390L,0x67f8cb8b6af9bc09L,0x322c38489c7476dbL, + 0xa320fecf52a538d6L } }, + /* 43 << 182 */ + { { 0xe0493002b2aced2bL,0xdfba1809616bd430L,0x531c4644c331be70L, + 0xbc04d32e90d2e450L }, + { 0x1805a0d10f9f142dL,0x2c44a0c547ee5a23L,0x31875a433989b4e3L, + 0x6b1949fd0c063481L } }, + /* 44 << 182 */ + { { 0x2dfb9e08be0f4492L,0x3ff0da03e9d5e517L,0x03dbe9a1f79466a8L, + 0x0b87bcd015ea9932L }, + { 0xeb64fc83ab1f58abL,0x6d9598da817edc8aL,0x699cff661d3b67e5L, + 0x645c0f2992635853L } }, + /* 45 << 182 */ + { { 0x253cdd82eabaf21cL,0x82b9602a2241659eL,0x2cae07ec2d9f7091L, + 0xbe4c720c8b48cd9bL }, + { 0x6ce5bc036f08d6c9L,0x36e8a997af10bf40L,0x83422d213e10ff12L, + 0x7b26d3ebbcc12494L } }, + /* 46 << 182 */ + { { 0xb240d2d0c9469ad6L,0xc4a11b4d30afa05bL,0x4b604acedd6ba286L, + 0x184866003ee2864cL }, + { 0x5869d6ba8d9ce5beL,0x0d8f68c5ff4bfb0dL,0xb69f210b5700cf73L, + 0x61f6653a6d37c135L } }, + /* 47 << 182 */ + { { 0xff3d432b5aff5a48L,0x0d81c4b972ba3a69L,0xee879ae9fa1899efL, + 0xbac7e2a02d6acafdL }, + { 0xd6d93f6c1c664399L,0x4c288de15bcb135dL,0x83031dab9dab7cbfL, + 0xfe23feb03abbf5f0L } }, + /* 48 << 182 */ + { { 0x9f1b2466cdedca85L,0x140bb7101a09538cL,0xac8ae8515e11115dL, + 0x0d63ff676f03f59eL }, + { 0x755e55517d234afbL,0x61c2db4e7e208fc1L,0xaa9859cef28a4b5dL, + 0xbdd6d4fc34af030fL } }, + /* 49 << 182 */ + { { 0xd1c4a26d3be01cb1L,0x9ba14ffc243aa07cL,0xf95cd3a9b2503502L, + 0xe379bc067d2a93abL }, + { 0x3efc18e9d4ca8d68L,0x083558ec80bb412aL,0xd903b9409645a968L, + 0xa499f0b69ba6054fL } }, + /* 50 << 182 */ + { { 0x208b573cb8349abeL,0x3baab3e530b4fc1cL,0x87e978bacb524990L, + 0x3524194eccdf0e80L }, + { 0x627117257d4bcc42L,0xe90a3d9bb90109baL,0x3b1bdd571323e1e0L, + 0xb78e9bd55eae1599L } }, + /* 51 << 182 */ + { { 0x0794b7469e03d278L,0x80178605d70e6297L,0x171792f899c97855L, + 0x11b393eef5a86b5cL }, + { 0x48ef6582d8884f27L,0xbd44737abf19ba5fL,0x8698de4ca42062c6L, + 0x8975eb8061ce9c54L } }, + /* 52 << 182 */ + { { 0xd50e57c7d7fe71f3L,0x15342190bc97ce38L,0x51bda2de4df07b63L, + 0xba12aeae200eb87dL }, + { 0xabe135d2a9b4f8f6L,0x04619d65fad6d99cL,0x4a6683a77994937cL, + 0x7a778c8b6f94f09aL } }, + /* 53 << 182 */ + { { 0x8c50862320a71b89L,0x241a2aed1c229165L,0x352be595aaf83a99L, + 0x9fbfee7f1562bac8L }, + { 0xeaf658b95c4017e3L,0x1dc7f9e015120b86L,0xd84f13dd4c034d6fL, + 0x283dd737eaea3038L } }, + /* 54 << 182 */ + { { 0x197f2609cd85d6a2L,0x6ebbc345fae60177L,0xb80f031b4e12fedeL, + 0xde55d0c207a2186bL }, + { 0x1fb3e37f24dcdd5aL,0x8d602da57ed191fbL,0x108fb05676023e0dL, + 0x70178c71459c20c0L } }, + /* 55 << 182 */ + { { 0xfad5a3863fe54cf0L,0xa4a3ec4f02bbb475L,0x1aa5ec20919d94d7L, + 0x5d3b63b5a81e4ab3L }, + { 0x7fa733d85ad3d2afL,0xfbc586ddd1ac7a37L,0x282925de40779614L, + 0xfe0ffffbe74a242aL } }, + /* 56 << 182 */ + { { 0x3f39e67f906151e5L,0xcea27f5f55e10649L,0xdca1d4e1c17cf7b7L, + 0x0c326d122fe2362dL }, + { 0x05f7ac337dd35df3L,0x0c3b7639c396dbdfL,0x0912f5ac03b7db1cL, + 0x9dea4b705c9ed4a9L } }, + /* 57 << 182 */ + { { 0x475e6e53aae3f639L,0xfaba0e7cfc278bacL,0x16f9e2219490375fL, + 0xaebf9746a5a7ed0aL }, + { 0x45f9af3ff41ad5d6L,0x03c4623cb2e99224L,0x82c5bb5cb3cf56aaL, + 0x6431181934567ed3L } }, + /* 58 << 182 */ + { { 0xec57f2118be489acL,0x2821895db9a1104bL,0x610dc8756064e007L, + 0x8e526f3f5b20d0feL }, + { 0x6e71ca775b645aeeL,0x3d1dcb9f800e10ffL,0x36b51162189cf6deL, + 0x2c5a3e306bb17353L } }, + /* 59 << 182 */ + { { 0xc186cd3e2a6c6fbfL,0xa74516fa4bf97906L,0x5b4b8f4b279d6901L, + 0x0c4e57b42b573743L }, + { 0x75fdb229b6e386b6L,0xb46793fd99deac27L,0xeeec47eacf712629L, + 0xe965f3c4cbc3b2ddL } }, + /* 60 << 182 */ + { { 0x8dd1fb83425c6559L,0x7fc00ee60af06fdaL,0xe98c922533d956dfL, + 0x0f1ef3354fbdc8a2L }, + { 0x2abb5145b79b8ea2L,0x40fd2945bdbff288L,0x6a814ac4d7185db7L, + 0xc4329d6fc084609aL } }, + /* 61 << 182 */ + { { 0xc9ba7b52ed1be45dL,0x891dd20de4cd2c74L,0x5a4d4a7f824139b1L, + 0x66c17716b873c710L }, + { 0x5e5bc1412843c4e0L,0xd5ac4817b97eb5bfL,0xc0f8af54450c95c7L, + 0xc91b3fa0318406c5L } }, + /* 62 << 182 */ + { { 0x360c340aab9d97f8L,0xfb57bd0790a2d611L,0x4339ae3ca6a6f7e5L, + 0x9c1fcd2a2feb8a10L }, + { 0x972bcca9c7ea7432L,0x1b0b924c308076f6L,0x80b2814a2a5b4ca5L, + 0x2f78f55b61ef3b29L } }, + /* 63 << 182 */ + { { 0xf838744ac18a414fL,0xc611eaae903d0a86L,0x94dabc162a453f55L, + 0xe6f2e3da14efb279L }, + { 0x5b7a60179320dc3cL,0x692e382f8df6b5a4L,0x3f5e15e02d40fa90L, + 0xc87883ae643dd318L } }, + /* 64 << 182 */ + { { 0x511053e453544774L,0x834d0ecc3adba2bcL,0x4215d7f7bae371f5L, + 0xfcfd57bf6c8663bcL }, + { 0xded2383dd6901b1dL,0x3b49fbb4b5587dc3L,0xfd44a08d07625f62L, + 0x3ee4d65b9de9b762L } }, + /* 0 << 189 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 189 */ + { { 0x64e5137d0d63d1faL,0x658fc05202a9d89fL,0x4889487450436309L, + 0xe9ae30f8d598da61L }, + { 0x2ed710d1818baf91L,0xe27e9e068b6a0c20L,0x1e28dcfb1c1a6b44L, + 0x883acb64d6ac57dcL } }, + /* 2 << 189 */ + { { 0x8735728dc2c6ff70L,0x79d6122fc5dc2235L,0x23f5d00319e277f9L, + 0x7ee84e25dded8cc7L }, + { 0x91a8afb063cd880aL,0x3f3ea7c63574af60L,0x0cfcdc8402de7f42L, + 0x62d0792fb31aa152L } }, + /* 3 << 189 */ + { { 0x8e1b4e438a5807ceL,0xad283893e4109a7eL,0xc30cc9cbafd59ddaL, + 0xf65f36c63d8d8093L }, + { 0xdf31469ea60d32b2L,0xee93df4b3e8191c8L,0x9c1017c5355bdeb5L, + 0xd26231858616aa28L } }, + /* 4 << 189 */ + { { 0xb02c83f9dec31a21L,0x988c8b236ad9d573L,0x53e983aea57be365L, + 0xe968734d646f834eL }, + { 0x9137ea8f5da6309bL,0x10f3a624c1f1ce16L,0x782a9ea2ca440921L, + 0xdf94739e5b46f1b5L } }, + /* 5 << 189 */ + { { 0x9f9be006cce85c9bL,0x360e70d6a4c7c2d3L,0x2cd5beeaaefa1e60L, + 0x64cf63c08c3d2b6dL }, + { 0xfb107fa3e1cf6f90L,0xb7e937c6d5e044e6L,0x74e8ca78ce34db9fL, + 0x4f8b36c13e210bd0L } }, + /* 6 << 189 */ + { { 0x1df165a434a35ea8L,0x3418e0f74d4412f6L,0x5af1f8af518836c3L, + 0x42ceef4d130e1965L }, + { 0x5560ca0b543a1957L,0xc33761e5886cb123L,0x66624b1ffe98ed30L, + 0xf772f4bf1090997dL } }, + /* 7 << 189 */ + { { 0xf4e540bb4885d410L,0x7287f8109ba5f8d7L,0x22d0d865de98dfb1L, + 0x49ff51a1bcfbb8a3L }, + { 0xb6b6fa536bc3012eL,0x3d31fd72170d541dL,0x8018724f4b0f4966L, + 0x79e7399f87dbde07L } }, + /* 8 << 189 */ + { { 0x56f8410ef4f8b16aL,0x97241afec47b266aL,0x0a406b8e6d9c87c1L, + 0x803f3e02cd42ab1bL }, + { 0x7f0309a804dbec69L,0xa83b85f73bbad05fL,0xc6097273ad8e197fL, + 0xc097440e5067adc1L } }, + /* 9 << 189 */ + { { 0x730eafb63524ff16L,0xd7f9b51e823fc6ceL,0x27bd0d32443e4ac0L, + 0x40c59ad94d66f217L }, + { 0x6c33136f17c387a4L,0x5043b8d5eb86804dL,0x74970312675a73c9L, + 0x838fdb31f16669b6L } }, + /* 10 << 189 */ + { { 0xc507b6dd418e7dddL,0x39888d93472f19d6L,0x7eae26be0c27eb4dL, + 0x17b53ed3fbabb884L }, + { 0xfc27021b2b01ae4fL,0x88462e87cf488682L,0xbee096ec215e2d87L, + 0xeb2fea9ad242e29bL } }, + /* 11 << 189 */ + { { 0x5d985b5fb821fc28L,0x89d2e197dc1e2ad2L,0x55b566b89030ba62L, + 0xe3fd41b54f41b1c6L }, + { 0xb738ac2eb9a96d61L,0x7f8567ca369443f4L,0x8698622df803a440L, + 0x2b5862368fe2f4dcL } }, + /* 12 << 189 */ + { { 0xbbcc00c756b95bceL,0x5ec03906616da680L,0x79162ee672214252L, + 0x43132b6386a892d2L }, + { 0x4bdd3ff22f3263bfL,0xd5b3733c9cd0a142L,0x592eaa8244415ccbL, + 0x663e89248d5474eaL } }, + /* 13 << 189 */ + { { 0x8058a25e5236344eL,0x82e8df9dbda76ee6L,0xdcf6efd811cc3d22L, + 0x00089cda3b4ab529L }, + { 0x91d3a071bd38a3dbL,0x4ea97fc0ef72b925L,0x0c9fc15bea3edf75L, + 0x5a6297cda4348ed3L } }, + /* 14 << 189 */ + { { 0x0d38ab35ce7c42d4L,0x9fd493ef82feab10L,0x46056b6d82111b45L, + 0xda11dae173efc5c3L }, + { 0xdc7402785545a7fbL,0xbdb2601c40d507e6L,0x121dfeeb7066fa58L, + 0x214369a839ae8c2aL } }, + /* 15 << 189 */ + { { 0x195709cb06e0956cL,0x4c9d254f010cd34bL,0xf51e13f70471a532L, + 0xe19d67911e73054dL }, + { 0xf702a628db5c7be3L,0xc7141218b24dde05L,0xdc18233cf29b2e2eL, + 0x3a6bd1e885342dbaL } }, + /* 16 << 189 */ + { { 0x3f747fa0b311898cL,0xe2a272e4cd0eac65L,0x4bba5851f914d0bcL, + 0x7a1a9660c4a43ee3L }, + { 0xe5a367cea1c8cde9L,0x9d958ba97271abe3L,0xf3ff7eb63d1615cdL, + 0xa2280dcef5ae20b0L } }, + /* 17 << 189 */ + { { 0x56dba5c1cf640147L,0xea5a2e3d5e83d118L,0x04cd6b6dda24c511L, + 0x1c0f4671e854d214L }, + { 0x91a6b7a969565381L,0xdc966240decf1f5bL,0x1b22d21cfcf5d009L, + 0x2a05f6419021dbd5L } }, + /* 18 << 189 */ + { { 0x8c0ed566d4312483L,0x5179a95d643e216fL,0xcc185fec17044493L, + 0xb306333954991a21L }, + { 0xd801ecdb0081a726L,0x0149b0c64fa89bbbL,0xafe9065a4391b6b9L, + 0xedc92786d633f3a3L } }, + /* 19 << 189 */ + { { 0xe408c24aae6a8e13L,0x85833fde9f3897abL,0x43800e7ed81a0715L, + 0xde08e346b44ffc5fL }, + { 0x7094184ccdeff2e0L,0x49f9387b165eaed1L,0x635d6129777c468aL, + 0x8c0dcfd1538c2dd8L } }, + /* 20 << 189 */ + { { 0xd6d9d9e37a6a308bL,0x623758304c2767d3L,0x874a8bc6f38cbeb6L, + 0xd94d3f1accb6fd9eL }, + { 0x92a9735bba21f248L,0x272ad0e56cd1efb0L,0x7437b69c05b03284L, + 0xe7f047026948c225L } }, + /* 21 << 189 */ + { { 0x8a56c04acba2ececL,0x0c181270e3a73e41L,0x6cb34e9d03e93725L, + 0xf77c8713496521a9L }, + { 0x94569183fa7f9f90L,0xf2e7aa4c8c9707adL,0xced2c9ba26c1c9a3L, + 0x9109fe9640197507L } }, + /* 22 << 189 */ + { { 0x9ae868a9e9adfe1cL,0x3984403d314e39bbL,0xb5875720f2fe378fL, + 0x33f901e0ba44a628L }, + { 0xea1125fe3652438cL,0xae9ec4e69dd1f20bL,0x1e740d9ebebf7fbdL, + 0x6dbd3ddc42dbe79cL } }, + /* 23 << 189 */ + { { 0x62082aecedd36776L,0xf612c478e9859039L,0xa493b201032f7065L, + 0xebd4d8f24ff9b211L }, + { 0x3f23a0aaaac4cb32L,0xea3aadb715ed4005L,0xacf17ea4afa27e63L, + 0x56125c1ac11fd66cL } }, + /* 24 << 189 */ + { { 0x266344a43794f8dcL,0xdcca923a483c5c36L,0x2d6b6bbf3f9d10a0L, + 0xb320c5ca81d9bdf3L }, + { 0x620e28ff47b50a95L,0x933e3b01cef03371L,0xf081bf8599100153L, + 0x183be9a0c3a8c8d6L } }, + /* 25 << 189 */ + { { 0x4e3ddc5ad6bbe24dL,0xc6c7463053843795L,0x78193dd765ec2d4cL, + 0xb8df26cccd3c89b2L }, + { 0x98dbe3995a483f8dL,0x72d8a9577dd3313aL,0x65087294ab0bd375L, + 0xfcd892487c259d16L } }, + /* 26 << 189 */ + { { 0x8a9443d77613aa81L,0x8010080085fe6584L,0x70fc4dbc7fb10288L, + 0xf58280d3e86beee8L }, + { 0x14fdd82f7c978c38L,0xdf1204c10de44d7bL,0xa08a1c844160252fL, + 0x591554cac17646a5L } }, + /* 27 << 189 */ + { { 0x214a37d6a05bd525L,0x48d5f09b07957b3cL,0x0247cdcbd7109bc9L, + 0x40f9e4bb30599ce7L }, + { 0xc325fa03f46ad2ecL,0x00f766cfc3e3f9eeL,0xab556668d43a4577L, + 0x68d30a613ee03b93L } }, + /* 28 << 189 */ + { { 0x7ddc81ea77b46a08L,0xcf5a6477c7480699L,0x43a8cb346633f683L, + 0x1b867e6b92363c60L }, + { 0x439211141f60558eL,0xcdbcdd632f41450eL,0x7fc04601cc630e8bL, + 0xea7c66d597038b43L } }, + /* 29 << 189 */ + { { 0x7259b8a504e99fd8L,0x98a8dd124785549aL,0x0e459a7c840552e1L, + 0xcdfcf4d04bb0909eL }, + { 0x34a86db253758da7L,0xe643bb83eac997e1L,0x96400bd7530c5b7eL, + 0x9f97af87b41c8b52L } }, + /* 30 << 189 */ + { { 0x34fc8820fbeee3f9L,0x93e5349049091afdL,0x764b9be59a31f35cL, + 0x71f3786457e3d924L }, + { 0x02fb34e0943aa75eL,0xa18c9c58ab8ff6e4L,0x080f31b133cf0d19L, + 0x5c9682db083518a7L } }, + /* 31 << 189 */ + { { 0x873d4ca6b709c3deL,0x64a842623575b8f0L,0x6275da1f020154bbL, + 0x97678caad17cf1abL }, + { 0x8779795f951a95c3L,0xdd35b16350fccc08L,0x3270962733d8f031L, + 0x3c5ab10a498dd85cL } }, + /* 32 << 189 */ + { { 0xb6c185c341dca566L,0x7de7fedad8622aa3L,0x99e84d92901b6dfbL, + 0x30a02b0e7c4ad288L }, + { 0xc7c81daa2fd3cf36L,0xd1319547df89e59fL,0xb2be8184cd496733L, + 0xd5f449eb93d3412bL } }, + /* 33 << 189 */ + { { 0x7ea41b1b25fe531dL,0xf97974326a1d5646L,0x86067f722bde501aL, + 0xf91481c00c85e89cL }, + { 0xca8ee465f8b05bc6L,0x1844e1cf02e83cdaL,0xca82114ab4dbe33bL, + 0x0f9f87694eabfde2L } }, + /* 34 << 189 */ + { { 0x4936b1c038b27fe2L,0x63b6359baba402dfL,0x40c0ea2f656bdbabL, + 0x9c992a896580c39cL }, + { 0x600e8f152a60aed1L,0xeb089ca4e0bf49dfL,0x9c233d7d2d42d99aL, + 0x648d3f954c6bc2faL } }, + /* 35 << 189 */ + { { 0xdcc383a8e1add3f3L,0xf42c0c6a4f64a348L,0x2abd176f0030dbdbL, + 0x4de501a37d6c215eL }, + { 0x4a107c1f4b9a64bcL,0xa77f0ad32496cd59L,0xfb78ac627688dffbL, + 0x7025a2ca67937d8eL } }, + /* 36 << 189 */ + { { 0xfde8b2d1d1a8f4e7L,0xf5b3da477354927cL,0xe48606a3d9205735L, + 0xac477cc6e177b917L }, + { 0xfb1f73d2a883239aL,0xe12572f6cc8b8357L,0x9d355e9cfb1f4f86L, + 0x89b795f8d9f3ec6eL } }, + /* 37 << 189 */ + { { 0x27be56f1b54398dcL,0x1890efd73fedeed5L,0x62f77f1f9c6d0140L, + 0x7ef0e314596f0ee4L }, + { 0x50ca6631cc61dab3L,0x4a39801df4866e4fL,0x66c8d032ae363b39L, + 0x22c591e52ead66aaL } }, + /* 38 << 189 */ + { { 0x954ba308de02a53eL,0x2a6c060fd389f357L,0xe6cfcde8fbf40b66L, + 0x8e02fc56c6340ce1L }, + { 0xe495779573adb4baL,0x7b86122ca7b03805L,0x63f835120c8e6fa6L, + 0x83660ea0057d7804L } }, + /* 39 << 189 */ + { { 0xbad7910521ba473cL,0xb6c50beeded5389dL,0xee2caf4daa7c9bc0L, + 0xd97b8de48c4e98a7L }, + { 0xa9f63e70ab3bbddbL,0x3898aabf2597815aL,0x7659af89ac15b3d9L, + 0xedf7725b703ce784L } }, + /* 40 << 189 */ + { { 0x25470fabe085116bL,0x04a4337587285310L,0x4e39187ee2bfd52fL, + 0x36166b447d9ebc74L }, + { 0x92ad433cfd4b322cL,0x726aa817ba79ab51L,0xf96eacd8c1db15ebL, + 0xfaf71e910476be63L } }, + /* 41 << 189 */ + { { 0xdd69a640641fad98L,0xb799591829622559L,0x03c6daa5de4199dcL, + 0x92cadc97ad545eb4L }, + { 0x1028238b256534e4L,0x73e80ce68595409aL,0x690d4c66d05dc59bL, + 0xc95f7b8f981dee80L } }, + /* 42 << 189 */ + { { 0xf4337014d856ac25L,0x441bd9ddac524dcaL,0x640b3d855f0499f5L, + 0x39cf84a9d5fda182L }, + { 0x04e7b055b2aa95a0L,0x29e33f0a0ddf1860L,0x082e74b5423f6b43L, + 0x217edeb90aaa2b0fL } }, + /* 43 << 189 */ + { { 0x58b83f3583cbea55L,0xc485ee4dbc185d70L,0x833ff03b1e5f6992L, + 0xb5b9b9cccf0c0dd5L }, + { 0x7caaee8e4e9e8a50L,0x462e907b6269dafdL,0x6ed5cee9fbe791c6L, + 0x68ca3259ed430790L } }, + /* 44 << 189 */ + { { 0x2b72bdf213b5ba88L,0x60294c8a35ef0ac4L,0x9c3230ed19b99b08L, + 0x560fff176c2589aaL }, + { 0x552b8487d6770374L,0xa373202d9a56f685L,0xd3e7f90745f175d9L, + 0x3c2f315fd080d810L } }, + /* 45 << 189 */ + { { 0x1130e9dd7b9520e8L,0xc078f9e20af037b5L,0x38cd2ec71e9c104cL, + 0x0f684368c472fe92L }, + { 0xd3f1b5ed6247e7efL,0xb32d33a9396dfe21L,0x46f59cf44a9aa2c2L, + 0x69cd5168ff0f7e41L } }, + /* 46 << 189 */ + { { 0x3f59da0f4b3234daL,0xcf0b0235b4579ebeL,0x6d1cbb256d2476c7L, + 0x4f0837e69dc30f08L }, + { 0x9a4075bb906f6e98L,0x253bb434c761e7d1L,0xde2e645f6e73af10L, + 0xb89a40600c5f131cL } }, + /* 47 << 189 */ + { { 0xd12840c5b8cc037fL,0x3d093a5b7405bb47L,0x6202c253206348b8L, + 0xbf5d57fcc55a3ca7L }, + { 0x89f6c90c8c3bef48L,0x23ac76235a0a960aL,0xdfbd3d6b552b42abL, + 0x3ef22458132061f6L } }, + /* 48 << 189 */ + { { 0xd74e9bdac97e6516L,0x88779360c230f49eL,0xa6ec1de31e74ea49L, + 0x581dcee53fb645a2L }, + { 0xbaef23918f483f14L,0x6d2dddfcd137d13bL,0x54cde50ed2743a42L, + 0x89a34fc5e4d97e67L } }, + /* 49 << 189 */ + { { 0x13f1f5b312e08ce5L,0xa80540b8a7f0b2caL,0x854bcf7701982805L, + 0xb8653ffd233bea04L }, + { 0x8e7b878702b0b4c9L,0x2675261f9acb170aL,0x061a9d90930c14e5L, + 0xb59b30e0def0abeaL } }, + /* 50 << 189 */ + { { 0x1dc19ea60200ec7dL,0xb6f4a3f90bce132bL,0xb8d5de90f13e27e0L, + 0xbaee5ef01fade16fL }, + { 0x6f406aaae4c6cf38L,0xab4cfe06d1369815L,0x0dcffe87efd550c6L, + 0x9d4f59c775ff7d39L } }, + /* 51 << 189 */ + { { 0xb02553b151deb6adL,0x812399a4b1877749L,0xce90f71fca6006e1L, + 0xc32363a6b02b6e77L }, + { 0x02284fbedc36c64dL,0x86c81e31a7e1ae61L,0x2576c7e5b909d94aL, + 0x8b6f7d02818b2bb0L } }, + /* 52 << 189 */ + { { 0xeca3ed0756faa38aL,0xa3790e6c9305bb54L,0xd784eeda7bc73061L, + 0xbd56d3696dd50614L }, + { 0xd6575949229a8aa9L,0xdcca8f474595ec28L,0x814305c106ab4fe6L, + 0xc8c3976824f43f16L } }, + /* 53 << 189 */ + { { 0xe2a45f36523f2b36L,0x995c6493920d93bbL,0xf8afdab790f1632bL, + 0x79ebbecd1c295954L }, + { 0xc7bb3ddb79592f48L,0x67216a7b5f88e998L,0xd91f098bbc01193eL, + 0xf7d928a5b1db83fcL } }, + /* 54 << 189 */ + { { 0x55e38417e991f600L,0x2a91113e2981a934L,0xcbc9d64806b13bdeL, + 0xb011b6ac0755ff44L }, + { 0x6f4cb518045ec613L,0x522d2d31c2f5930aL,0x5acae1af382e65deL, + 0x5764306727bc966fL } }, + /* 55 << 189 */ + { { 0x5e12705d1c7193f0L,0xf0f32f473be8858eL,0x785c3d7d96c6dfc7L, + 0xd75b4a20bf31795dL }, + { 0x91acf17b342659d4L,0xe596ea3444f0378fL,0x4515708fce52129dL, + 0x17387e1e79f2f585L } }, + /* 56 << 189 */ + { { 0x72cfd2e949dee168L,0x1ae052233e2af239L,0x009e75be1d94066aL, + 0x6cca31c738abf413L }, + { 0xb50bd61d9bc49908L,0x4a9b4a8cf5e2bc1eL,0xeb6cc5f7946f83acL, + 0x27da93fcebffab28L } }, + /* 57 << 189 */ + { { 0xea314c964821c8c5L,0x8de49deda83c15f4L,0x7a64cf207af33004L, + 0x45f1bfebc9627e10L }, + { 0x878b062654b9df60L,0x5e4fdc3ca95c0b33L,0xe54a37cac2035d8eL, + 0x9087cda980f20b8cL } }, + /* 58 << 189 */ + { { 0x36f61c238319ade4L,0x766f287ade8cfdf8L,0x48821948346f3705L, + 0x49a7b85316e4f4a2L }, + { 0xb9b3f8a75cedadfdL,0x8f5628158db2a815L,0xc0b7d55401f68f95L, + 0x12971e27688a208eL } }, + /* 59 << 189 */ + { { 0xc9f8b696d0ff34fcL,0x20824de21222718cL,0x7213cf9f0c95284dL, + 0xe2ad741bdc158240L }, + { 0x0ee3a6df54043ccfL,0x16ff479bd84412b3L,0xf6c74ee0dfc98af0L, + 0xa78a169f52fcd2fbL } }, + /* 60 << 189 */ + { { 0xd8ae874699c930e9L,0x1d33e85849e117a5L,0x7581fcb46624759fL, + 0xde50644f5bedc01dL }, + { 0xbeec5d00caf3155eL,0x672d66acbc73e75fL,0x86b9d8c6270b01dbL, + 0xd249ef8350f55b79L } }, + /* 61 << 189 */ + { { 0x6131d6d473978fe3L,0xcc4e4542754b00a1L,0x4e05df0557dfcfe9L, + 0x94b29cdd51ef6bf0L }, + { 0xe4530cff9bc7edf2L,0x8ac236fdd3da65f3L,0x0faf7d5fc8eb0b48L, + 0x4d2de14c660eb039L } }, + /* 62 << 189 */ + { { 0xc006bba760430e54L,0x10a2d0d6da3289abL,0x9c037a5dd7979c59L, + 0x04d1f3d3a116d944L }, + { 0x9ff224738a0983cdL,0x28e25b38c883cabbL,0xe968dba547a58995L, + 0x2c80b505774eebdfL } }, + /* 63 << 189 */ + { { 0xee763b714a953bebL,0x502e223f1642e7f6L,0x6fe4b64161d5e722L, + 0x9d37c5b0dbef5316L }, + { 0x0115ed70f8330bc7L,0x139850e675a72789L,0x27d7faecffceccc2L, + 0x3016a8604fd9f7f6L } }, + /* 64 << 189 */ + { { 0xc492ec644cd8f64cL,0x58a2d790279d7b51L,0x0ced1fc51fc75256L, + 0x3e658aed8f433017L }, + { 0x0b61942e05da59ebL,0xba3d60a30ddc3722L,0x7c311cd1742e7f87L, + 0x6473ffeef6b01b6eL } }, + /* 0 << 196 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 196 */ + { { 0x8303604f692ac542L,0xf079ffe1227b91d3L,0x19f63e6315aaf9bdL, + 0xf99ee565f1f344fbL }, + { 0x8a1d661fd6219199L,0x8c883bc6d48ce41cL,0x1065118f3c74d904L, + 0x713889ee0faf8b1bL } }, + /* 2 << 196 */ + { { 0x972b3f8f81a1b3beL,0x4f3ce145ce2764a0L,0xe2d0f1cc28c4f5f7L, + 0xdeee0c0dc7f3985bL }, + { 0x7df4adc0d39e25c3L,0x40619820c467a080L,0x440ebc9361cf5a58L, + 0x527729a6422ad600L } }, + /* 3 << 196 */ + { { 0xca6c0937b1b76ba6L,0x1a2eab854d2026dcL,0xb1715e1519d9ae0aL, + 0xf1ad9199bac4a026L }, + { 0x35b3dfb807ea7b0eL,0xedf5496f3ed9eb89L,0x8932e5ff2d6d08abL, + 0xf314874e25bd2731L } }, + /* 4 << 196 */ + { { 0xefb26a753f73f449L,0x1d1c94f88d44fc79L,0x49f0fbc53bc0dc4dL, + 0xb747ea0b3698a0d0L }, + { 0x5218c3fe228d291eL,0x35b804b543c129d6L,0xfac859b8d1acc516L, + 0x6c10697d95d6e668L } }, + /* 5 << 196 */ + { { 0xc38e438f0876fd4eL,0x45f0c30783d2f383L,0x203cc2ecb10934cbL, + 0x6a8f24392c9d46eeL }, + { 0xf16b431b65ccde7bL,0x41e2cd1827e76a6fL,0xb9c8cf8f4e3484d7L, + 0x64426efd8315244aL } }, + /* 6 << 196 */ + { { 0x1c0a8e44fc94dea3L,0x34c8cdbfdad6a0b0L,0x919c384004113cefL, + 0xfd32fba415490ffaL }, + { 0x58d190f6795dcfb7L,0xfef01b0383588bafL,0x9e6d1d63ca1fc1c0L, + 0x53173f96f0a41ac9L } }, + /* 7 << 196 */ + { { 0x2b1d402aba16f73bL,0x2fb310148cf9b9fcL,0x2d51e60e446ef7bfL, + 0xc731021bb91e1745L }, + { 0x9d3b47244fee99d4L,0x4bca48b6fac5c1eaL,0x70f5f514bbea9af7L, + 0x751f55a5974c283aL } }, + /* 8 << 196 */ + { { 0x6e30251acb452fdbL,0x31ee696550f30650L,0xb0b3e508933548d9L, + 0xb8949a4ff4b0ef5bL }, + { 0x208b83263c88f3bdL,0xab147c30db1d9989L,0xed6515fd44d4df03L, + 0x17a12f75e72eb0c5L } }, + /* 9 << 196 */ + { { 0x3b59796d36cf69dbL,0x1219eee956670c18L,0xfe3341f77a070d8eL, + 0x9b70130ba327f90cL }, + { 0x36a324620ae18e0eL,0x2021a62346c0a638L,0x251b5817c62eb0d4L, + 0x87bfbcdf4c762293L } }, + /* 10 << 196 */ + { { 0xf78ab505cdd61d64L,0x8c7a53fcc8c18857L,0xa653ce6f16147515L, + 0x9c923aa5ea7d52d5L }, + { 0xc24709cb5c18871fL,0x7d53bec873b3cc74L,0x59264afffdd1d4c4L, + 0x5555917e240da582L } }, + /* 11 << 196 */ + { { 0xcae8bbda548f5a0eL,0x1910eaba3bbfbbe1L,0xae5796857677afc3L, + 0x49ea61f173ff0b5cL }, + { 0x786554784f7c3922L,0x95d337cd20c68eefL,0x68f1e1e5df779ab9L, + 0x14b491b0b5cf69a8L } }, + /* 12 << 196 */ + { { 0x7a6cbbe028e3fe89L,0xe7e1fee4c5aac0ebL,0x7f47eda5697e5140L, + 0x4f450137b454921fL }, + { 0xdb625f8495cd8185L,0x74be0ba1cdb2e583L,0xaee4fd7cdd5e6de4L, + 0x4251437de8101739L } }, + /* 13 << 196 */ + { { 0x686d72a0ac620366L,0x4be3fb9cb6d59344L,0x6e8b44e7a1eb75b9L, + 0x84e39da391a5c10cL }, + { 0x37cc1490b38f0409L,0x029519432c2ade82L,0x9b6887831190a2d8L, + 0x25627d14231182baL } }, + /* 14 << 196 */ + { { 0x6eb550aa658a6d87L,0x1405aaa7cf9c7325L,0xd147142e5c8748c9L, + 0x7f637e4f53ede0e0L }, + { 0xf8ca277614ffad2cL,0xe58fb1bdbafb6791L,0x17158c23bf8f93fcL, + 0x7f15b3730a4a4655L } }, + /* 15 << 196 */ + { { 0x39d4add2d842ca72L,0xa71e43913ed96305L,0x5bb09cbe6700be14L, + 0x68d69d54d8befcf6L }, + { 0xa45f536737183bcfL,0x7152b7bb3370dff7L,0xcf887baabf12525bL, + 0xe7ac7bddd6d1e3cdL } }, + /* 16 << 196 */ + { { 0x25914f7881fdad90L,0xcf638f560d2cf6abL,0xb90bc03fcc054de5L, + 0x932811a718b06350L }, + { 0x2f00b3309bbd11ffL,0x76108a6fb4044974L,0x801bb9e0a851d266L, + 0x0dd099bebf8990c1L } }, + /* 17 << 196 */ + { { 0x58c5aaaaabe32986L,0x0fe9dd2a50d59c27L,0x84951ff48d307305L, + 0x6c23f82986529b78L }, + { 0x50bb22180b136a79L,0x7e2174de77a20996L,0x6f00a4b9c0bb4da6L, + 0x89a25a17efdde8daL } }, + /* 18 << 196 */ + { { 0xf728a27ec11ee01dL,0xf900553ae5f10dfbL,0x189a83c802ec893cL, + 0x3ca5bdc123f66d77L }, + { 0x9878153797eada9fL,0x59c50ab310256230L,0x346042d9323c69b3L, + 0x1b715a6d2c460449L } }, + /* 19 << 196 */ + { { 0xa41dd4766ae06e0bL,0xcdd7888e9d42e25fL,0x0f395f7456b25a20L, + 0xeadfe0ae8700e27eL }, + { 0xb09d52a969950093L,0x3525d9cb327f8d40L,0xb8235a9467df886aL, + 0x77e4b0dd035faec2L } }, + /* 20 << 196 */ + { { 0x115eb20a517d7061L,0x77fe34336c2df683L,0x6870ddc7cdc6fc67L, + 0xb16105880b87de83L }, + { 0x343584cad9c4ddbeL,0xb3164f1c3d754be2L,0x0731ed3ac1e6c894L, + 0x26327dec4f6b904cL } }, + /* 21 << 196 */ + { { 0x9d49c6de97b5cd32L,0x40835daeb5eceecdL,0xc66350edd9ded7feL, + 0x8aeebb5c7a678804L }, + { 0x51d42fb75b8ee9ecL,0xd7a17bdd8e3ca118L,0x40d7511a2ef4400eL, + 0xc48990ac875a66f4L } }, + /* 22 << 196 */ + { { 0x8de07d2a2199e347L,0xbee755562a39e051L,0x56918786916e51dcL, + 0xeb1913134a2d89ecL }, + { 0x6679610d37d341edL,0x434fbb4156d51c2bL,0xe54b7ee7d7492dbaL, + 0xaa33a79a59021493L } }, + /* 23 << 196 */ + { { 0x49fc5054e4bd6d3dL,0x09540f045ab551d0L,0x8acc90854942d3a6L, + 0x231af02f2d28323bL }, + { 0x93458cac0992c163L,0x1fef8e71888e3bb4L,0x27578da5be8c268cL, + 0xcc8be792e805ec00L } }, + /* 24 << 196 */ + { { 0x29267baec61c3855L,0xebff429d58c1fd3bL,0x22d886c08c0b93b8L, + 0xca5e00b22ddb8953L }, + { 0xcf330117c3fed8b7L,0xd49ac6fa819c01f6L,0x6ddaa6bd3c0fbd54L, + 0x917430688049a2cfL } }, + /* 25 << 196 */ + { { 0xd67f981eaff2ef81L,0xc3654d352818ae80L,0x81d050441b2aa892L, + 0x2db067bf3d099328L }, + { 0xe7c79e86703dcc97L,0xe66f9b37e133e215L,0xcdf119a6e39a7a5cL, + 0x47c60de3876f1b61L } }, + /* 26 << 196 */ + { { 0x6e405939d860f1b2L,0x3e9a1dbcf5ed4d4aL,0x3f23619ec9b6bcbdL, + 0x5ee790cf734e4497L }, + { 0xf0a834b15bdaf9bbL,0x02cedda74ca295f0L,0x4619aa2bcb8e378cL, + 0xe5613244cc987ea4L } }, + /* 27 << 196 */ + { { 0x0bc022cc76b23a50L,0x4a2793ad0a6c21ceL,0x3832878089cac3f5L, + 0x29176f1bcba26d56L }, + { 0x062961874f6f59ebL,0x86e9bca98bdc658eL,0x2ca9c4d357e30402L, + 0x5438b216516a09bbL } }, + /* 28 << 196 */ + { { 0x0a6a063c7672765aL,0x37a3ce640547b9bfL,0x42c099c898b1a633L, + 0xb5ab800d05ee6961L }, + { 0xf1963f5911a5acd6L,0xbaee615746201063L,0x36d9a649a596210aL, + 0xaed043631ba7138cL } }, + /* 29 << 196 */ + { { 0xcf817d1ca4a82b76L,0x5586960ef3806be9L,0x7ab67c8909dc6bb5L, + 0x52ace7a0114fe7ebL }, + { 0xcd987618cbbc9b70L,0x4f06fd5a604ca5e1L,0x90af14ca6dbde133L, + 0x1afe4322948a3264L } }, + /* 30 << 196 */ + { { 0xa70d2ca6c44b2c6cL,0xab7267990ef87dfeL,0x310f64dc2e696377L, + 0x49b42e684c8126a0L }, + { 0x0ea444c3cea0b176L,0x53a8ddf7cb269182L,0xf3e674ebbbba9dcbL, + 0x0d2878a8d8669d33L } }, + /* 31 << 196 */ + { { 0x04b935d5d019b6a3L,0xbb5cf88e406f1e46L,0xa1912d165b57c111L, + 0x9803fc2119ebfd78L }, + { 0x4f231c9ec07764a9L,0xd93286eeb75bd055L,0x83a9457d8ee6c9deL, + 0x046959156087ec90L } }, + /* 32 << 196 */ + { { 0x14c6dd8a58d6cd46L,0x9cb633b58e6634d2L,0xc1305047f81bc328L, + 0x12ede0e226a177e5L }, + { 0x332cca62065a6f4fL,0xc3a47ecd67be487bL,0x741eb1870f47ed1cL, + 0x99e66e58e7598b14L } }, + /* 33 << 196 */ + { { 0x6f0544ca63d0ff12L,0xe5efc784b610a05fL,0xf72917b17cad7b47L, + 0x3ff6ea20f2cac0c0L }, + { 0xcc23791bf21db8b7L,0x7dac70b1d7d93565L,0x682cda1d694bdaadL, + 0xeb88bb8c1023516dL } }, + /* 34 << 196 */ + { { 0xc4c634b4dfdbeb1bL,0x22f5ca72b4ee4deaL,0x1045a368e6524821L, + 0xed9e8a3f052b18b2L }, + { 0x9b7f2cb1b961f49aL,0x7fee2ec17b009670L,0x350d875422507a6dL, + 0x561bd7114db55f1dL } }, + /* 35 << 196 */ + { { 0x4c189ccc320bbcafL,0x568434cfdf1de48cL,0x6af1b00e0fa8f128L, + 0xf0ba9d028907583cL }, + { 0x735a400432ff9f60L,0x3dd8e4b6c25dcf33L,0xf2230f1642c74cefL, + 0xd8117623013fa8adL } }, + /* 36 << 196 */ + { { 0x36822876f51fe76eL,0x8a6811cc11d62589L,0xc3fc7e6546225718L, + 0xb7df2c9fc82fdbcdL }, + { 0x3b1d4e52dd7b205bL,0xb695947847a2e414L,0x05e4d793efa91148L, + 0xb47ed446fd2e9675L } }, + /* 37 << 196 */ + { { 0x1a7098b904c9d9bfL,0x661e28811b793048L,0xb1a16966b01ee461L, + 0xbc5213082954746fL }, + { 0xc909a0fc2477de50L,0xd80bb41c7dbd51efL,0xa85be7ec53294905L, + 0x6d465b1883958f97L } }, + /* 38 << 196 */ + { { 0x16f6f330fb6840fdL,0xfaaeb2143401e6c8L,0xaf83d30fccb5b4f8L, + 0x22885739266dec4bL }, + { 0x51b4367c7bc467dfL,0x926562e3d842d27aL,0xdfcb66140fea14a6L, + 0xeb394daef2734cd9L } }, + /* 39 << 196 */ + { { 0x3eeae5d211c0be98L,0xb1e6ed11814e8165L,0x191086bce52bce1cL, + 0x14b74cc6a75a04daL }, + { 0x63cf11868c060985L,0x071047de2dbd7f7cL,0x4e433b8bce0942caL, + 0xecbac447d8fec61dL } }, + /* 40 << 196 */ + { { 0x8f0ed0e2ebf3232fL,0xfff80f9ec52a2eddL,0xad9ab43375b55fdbL, + 0x73ca7820e42e0c11L }, + { 0x6dace0a0e6251b46L,0x89bc6b5c4c0d932dL,0x3438cd77095da19aL, + 0x2f24a9398d48bdfbL } }, + /* 41 << 196 */ + { { 0x99b47e46766561b7L,0x736600e60ed0322aL,0x06a47cb1638e1865L, + 0x927c1c2dcb136000L }, + { 0x295423370cc5df69L,0x99b37c0209d649a9L,0xc5f0043c6aefdb27L, + 0x6cdd99871be95c27L } }, + /* 42 << 196 */ + { { 0x69850931390420d2L,0x299c40ac0983efa4L,0x3a05e778af39aeadL, + 0x8427440843a45193L }, + { 0x6bcd0fb991a711a0L,0x461592c89f52ab17L,0xb49302b4da3c6ed6L, + 0xc51fddc7330d7067L } }, + /* 43 << 196 */ + { { 0x94babeb6da50d531L,0x521b840da6a7b9daL,0x5305151e404bdc89L, + 0x1bcde201d0d07449L }, + { 0xf427a78b3b76a59aL,0xf84841ce07791a1bL,0xebd314bebf91ed1cL, + 0x8e61d34cbf172943L } }, + /* 44 << 196 */ + { { 0x1d5dc4515541b892L,0xb186ee41fc9d9e54L,0x9d9f345ed5bf610dL, + 0x3e7ba65df6acca9fL }, + { 0x9dda787aa8369486L,0x09f9dab78eb5ba53L,0x5afb2033d6481bc3L, + 0x76f4ce30afa62104L } }, + /* 45 << 196 */ + { { 0xa8fa00cff4f066b5L,0x89ab5143461dafc2L,0x44339ed7a3389998L, + 0x2ff862f1bc214903L }, + { 0x2c88f985b05556e3L,0xcd96058e3467081eL,0x7d6a4176edc637eaL, + 0xe1743d0936a5acdcL } }, + /* 46 << 196 */ + { { 0x66fd72e27eb37726L,0xf7fa264e1481a037L,0x9fbd3bde45f4aa79L, + 0xed1e0147767c3e22L }, + { 0x7621f97982e7abe2L,0x19eedc7245f633f8L,0xe69b155e6137bf3aL, + 0xa0ad13ce414ee94eL } }, + /* 47 << 196 */ + { { 0x93e3d5241c0e651aL,0xab1a6e2a02ce227eL,0xe7af17974ab27ecaL, + 0x245446debd444f39L }, + { 0x59e22a2156c07613L,0x43deafcef4275498L,0x10834ccb67fd0946L, + 0xa75841e547406edfL } }, + /* 48 << 196 */ + { { 0xebd6a6777b0ac93dL,0xa6e37b0d78f5e0d7L,0x2516c09676f5492bL, + 0x1e4bf8889ac05f3aL }, + { 0xcdb42ce04df0ba2bL,0x935d5cfd5062341bL,0x8a30333382acac20L, + 0x429438c45198b00eL } }, + /* 49 << 196 */ + { { 0x1d083bc9049d33faL,0x58b82dda946f67ffL,0xac3e2db867a1d6a3L, + 0x62e6bead1798aac8L }, + { 0xfc85980fde46c58cL,0xa7f6937969c8d7beL,0x23557927837b35ecL, + 0x06a933d8e0790c0cL } }, + /* 50 << 196 */ + { { 0x827c0e9b077ff55dL,0x53977798bb26e680L,0x595308741d9cb54fL, + 0xcca3f4494aac53efL }, + { 0x11dc5c87a07eda0fL,0xc138bccffd6400c8L,0x549680d313e5da72L, + 0xc93eed824540617eL } }, + /* 51 << 196 */ + { { 0xfd3db1574d0b75c0L,0x9716eb426386075bL,0x0639605c817b2c16L, + 0x09915109f1e4f201L }, + { 0x35c9a9285cca6c3bL,0xb25f7d1a3505c900L,0xeb9f7d20630480c4L, + 0xc3c7b8c62a1a501cL } }, + /* 52 << 196 */ + { { 0x3f99183c5a1f8e24L,0xfdb118fa9dd255f0L,0xb9b18b90c27f62a6L, + 0xe8f732f7396ec191L }, + { 0x524a2d910be786abL,0x5d32adef0ac5a0f5L,0x9b53d4d69725f694L, + 0x032a76c60510ba89L } }, + /* 53 << 196 */ + { { 0x840391a3ebeb1544L,0x44b7b88c3ed73ac3L,0xd24bae7a256cb8b3L, + 0x7ceb151ae394cb12L }, + { 0xbd6b66d05bc1e6a8L,0xec70cecb090f07bfL,0x270644ed7d937589L, + 0xee9e1a3d5f1dccfeL } }, + /* 54 << 196 */ + { { 0xb0d40a84745b98d2L,0xda429a212556ed40L,0xf676eced85148cb9L, + 0x5a22d40cded18936L }, + { 0x3bc4b9e570e8a4ceL,0xbfd1445b9eae0379L,0xf23f2c0c1a0bd47eL, + 0xa9c0bb31e1845531L } }, + /* 55 << 196 */ + { { 0x9ddc4d600a4c3f6bL,0xbdfaad792c15ef44L,0xce55a2367f484accL, + 0x08653ca7055b1f15L }, + { 0x2efa8724538873a3L,0x09299e5dace1c7e7L,0x07afab66ade332baL, + 0x9be1fdf692dd71b7L } }, + /* 56 << 196 */ + { { 0xa49b5d595758b11cL,0x0b852893c8654f40L,0xb63ef6f452379447L, + 0xd4957d29105e690cL }, + { 0x7d484363646559b0L,0xf4a8273c49788a8eL,0xee406cb834ce54a9L, + 0x1e1c260ff86fda9bL } }, + /* 57 << 196 */ + { { 0xe150e228cf6a4a81L,0x1fa3b6a31b488772L,0x1e6ff110c5a9c15bL, + 0xc6133b918ad6aa47L }, + { 0x8ac5d55c9dffa978L,0xba1d1c1d5f3965f2L,0xf969f4e07732b52fL, + 0xfceecdb5a5172a07L } }, + /* 58 << 196 */ + { { 0xb0120a5f10f2b8f5L,0xc83a6cdf5c4c2f63L,0x4d47a491f8f9c213L, + 0xd9e1cce5d3f1bbd5L }, + { 0x0d91bc7caba7e372L,0xfcdc74c8dfd1a2dbL,0x05efa800374618e5L, + 0x1121696915a7925eL } }, + /* 59 << 196 */ + { { 0xd4c89823f6021c5dL,0x880d5e84eff14423L,0x6523bc5a6dcd1396L, + 0xd1acfdfc113c978bL }, + { 0xb0c164e8bbb66840L,0xf7f4301e72b58459L,0xc29ad4a6a638e8ecL, + 0xf5ab896146b78699L } }, + /* 60 << 196 */ + { { 0x9dbd79740e954750L,0x0121de8864f9d2c6L,0x2e597b42d985232eL, + 0x55b6c3c553451777L }, + { 0xbb53e547519cb9fbL,0xf134019f8428600dL,0x5a473176e081791aL, + 0x2f3e226335fb0c08L } }, + /* 61 << 196 */ + { { 0xb28c301773d273b0L,0xccd210767721ef9aL,0x054cc292b650dc39L, + 0x662246de6188045eL }, + { 0x904b52fa6b83c0d1L,0xa72df26797e9cd46L,0x886b43cd899725e4L, + 0x2b651688d849ff22L } }, + /* 62 << 196 */ + { { 0x60479b7902f34533L,0x5e354c140c77c148L,0xb4bb7581a8537c78L, + 0x188043d7efe1495fL }, + { 0x9ba12f428c1d5026L,0x2e0c8a2693d4aaabL,0xbdba7b8baa57c450L, + 0x140c9ad69bbdafefL } }, + /* 63 << 196 */ + { { 0x2067aa4225ac0f18L,0xf7b1295b04d1fbf3L,0x14829111a4b04824L, + 0x2ce3f19233bd5e91L }, + { 0x9c7a1d558f2e1b72L,0xfe932286302aa243L,0x497ca7b4d4be9554L, + 0xb8e821b8e0547a6eL } }, + /* 64 << 196 */ + { { 0xfb2838be67e573e0L,0x05891db94084c44bL,0x9131137396c1c2c5L, + 0x6aebfa3fd958444bL }, + { 0xac9cdce9e56e55c1L,0x7148ced32caa46d0L,0x2e10c7efb61fe8ebL, + 0x9fd835daff97cf4dL } }, + /* 0 << 203 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 203 */ + { { 0xa36da109081e9387L,0xfb9780d78c935828L,0xd5940332e540b015L, + 0xc9d7b51be0f466faL }, + { 0xfaadcd41d6d9f671L,0xba6c1e28b1a2ac17L,0x066a7833ed201e5fL, + 0x19d99719f90f462bL } }, + /* 2 << 203 */ + { { 0xf431f462060b5f61L,0xa56f46b47bd057c2L,0x348dca6c47e1bf65L, + 0x9a38783e41bcf1ffL }, + { 0x7a5d33a9da710718L,0x5a7799872e0aeaf6L,0xca87314d2d29d187L, + 0xfa0edc3ec687d733L } }, + /* 3 << 203 */ + { { 0x9df336216a31e09bL,0xde89e44dc1350e35L,0x292148714ca0cf52L, + 0xdf3796720b88a538L }, + { 0xc92a510a2591d61bL,0x79aa87d7585b447bL,0xf67db604e5287f77L, + 0x1697c8bf5efe7a80L } }, + /* 4 << 203 */ + { { 0x1c894849cb198ac7L,0xa884a93d0f264665L,0x2da964ef9b200678L, + 0x3c351b87009834e6L }, + { 0xafb2ef9fe2c4b44bL,0x580f6c473326790cL,0xb84805210b02264aL, + 0x8ba6f9e242a194e2L } }, + /* 5 << 203 */ + { { 0xfc87975f8fb54738L,0x3516078827c3ead3L,0x834116d2b74a085aL, + 0x53c99a73a62fe996L }, + { 0x87585be05b81c51bL,0x925bafa8be0852b7L,0x76a4fafda84d19a7L, + 0x39a45982585206d4L } }, + /* 6 << 203 */ + { { 0x499b6ab65eb03c0eL,0xf19b795472bc3fdeL,0xa86b5b9c6e3a80d2L, + 0xe43775086d42819fL }, + { 0xc1663650bb3ee8a3L,0x75eb14fcb132075fL,0xa8ccc9067ad834f6L, + 0xea6a2474e6e92ffdL } }, + /* 7 << 203 */ + { { 0x9d72fd950f8d6758L,0xcb84e101408c07ddL,0xb9114bfda5e23221L, + 0x358b5fe2e94e742cL }, + { 0x1c0577ec95f40e75L,0xf01554513d73f3d6L,0x9d55cd67bd1b9b66L, + 0x63e86e78af8d63c7L } }, + /* 8 << 203 */ + { { 0x39d934abd3c095f1L,0x04b261bee4b76d71L,0x1d2e6970e73e6984L, + 0x879fb23b5e5fcb11L }, + { 0x11506c72dfd75490L,0x3a97d08561bcf1c1L,0x43201d82bf5e7007L, + 0x7f0ac52f798232a7L } }, + /* 9 << 203 */ + { { 0x2715cbc46eb564d4L,0x8d6c752c9e570e29L,0xf80247c89ef5fd5dL, + 0xc3c66b46d53eb514L }, + { 0x9666b4010f87de56L,0xce62c06fc6c603b5L,0xae7b4c607e4fc942L, + 0x38ac0b77663a9c19L } }, + /* 10 << 203 */ + { { 0xcb4d20ee4b049136L,0x8b63bf12356a4613L,0x1221aef670e08128L, + 0xe62d8c514acb6b16L }, + { 0x71f64a67379e7896L,0xb25237a2cafd7fa5L,0xf077bd983841ba6aL, + 0xc4ac02443cd16e7eL } }, + /* 11 << 203 */ + { { 0x548ba86921fea4caL,0xd36d0817f3dfdac1L,0x09d8d71ff4685fafL, + 0x8eff66bec52c459aL }, + { 0x182faee70b57235eL,0xee3c39b10106712bL,0x5107331fc0fcdcb0L, + 0x669fb9dca51054baL } }, + /* 12 << 203 */ + { { 0xb25101fb319d7682L,0xb02931290a982feeL,0x51c1c9b90261b344L, + 0x0e008c5bbfd371faL }, + { 0xd866dd1c0278ca33L,0x666f76a6e5aa53b1L,0xe5cfb7796013a2cfL, + 0x1d3a1aada3521836L } }, + /* 13 << 203 */ + { { 0xcedd253173faa485L,0xc8ee6c4fc0a76878L,0xddbccfc92a11667dL, + 0x1a418ea91c2f695aL }, + { 0xdb11bd9251f73971L,0x3e4b3c82da2ed89fL,0x9a44f3f4e73e0319L, + 0xd1e3de0f303431afL } }, + /* 14 << 203 */ + { { 0x3c5604ff50f75f9cL,0x1d8eddf37e752b22L,0x0ef074dd3c9a1118L, + 0xd0ffc172ccb86d7bL }, + { 0xabd1ece3037d90f2L,0xe3f307d66055856cL,0x422f93287e4c6dafL, + 0x902aac66334879a0L } }, + /* 15 << 203 */ + { { 0xb6a1e7bf94cdfadeL,0x6c97e1ed7fc6d634L,0x662ad24da2fb63f8L, + 0xf81be1b9a5928405L }, + { 0x86d765e4d14b4206L,0xbecc2e0e8fa0db65L,0xa28838e0b17fc76cL, + 0xe49a602ae37cf24eL } }, + /* 16 << 203 */ + { { 0x76b4131a567193ecL,0xaf3c305ae5f6e70bL,0x9587bd39031eebddL, + 0x5709def871bbe831L }, + { 0x570599830eb2b669L,0x4d80ce1b875b7029L,0x838a7da80364ac16L, + 0x2f431d23be1c83abL } }, + /* 17 << 203 */ + { { 0xe56812a6f9294dd3L,0xb448d01f9b4b0d77L,0xf3ae606104e8305cL, + 0x2bead64594d8c63eL }, + { 0x0a85434d84fd8b07L,0x537b983ff7a9dee5L,0xedcc5f18ef55bd85L, + 0x2041af6221c6cf8bL } }, + /* 18 << 203 */ + { { 0x8e52874cb940c71eL,0x211935a9db5f4b3aL,0x94350492301b1dc3L, + 0x33d2646d29958620L }, + { 0x16b0d64bef911404L,0x9d1f25ea9a3c5ef4L,0x20f200eb4a352c78L, + 0x43929f2c4bd0b428L } }, + /* 19 << 203 */ + { { 0xa5656667c7196e29L,0x7992c2f09391be48L,0xaaa97cbd9ee0cd6eL, + 0x51b0310c3dc8c9bfL }, + { 0x237f8acfdd9f22cbL,0xbb1d81a1b585d584L,0x8d5d85f58c416388L, + 0x0d6e5a5a42fe474fL } }, + /* 20 << 203 */ + { { 0xe781276638235d4eL,0x1c62bd67496e3298L,0x8378660c3f175bc8L, + 0x4d04e18917afdd4dL }, + { 0x32a8160185a8068cL,0xdb58e4e192b29a85L,0xe8a65b86c70d8a3bL, + 0x5f0e6f4e98a0403bL } }, + /* 21 << 203 */ + { { 0x0812968469ed2370L,0x34dc30bd0871ee26L,0x3a5ce9487c9c5b05L, + 0x7d487b8043a90c87L }, + { 0x4089ba37dd0e7179L,0x45f80191b4041811L,0x1c3e105898747ba5L, + 0x98c4e13a6e1ae592L } }, + /* 22 << 203 */ + { { 0xd44636e6e82c9f9eL,0x711db87cc33a1043L,0x6f431263aa8aec05L, + 0x43ff120d2744a4aaL }, + { 0xd3bd892fae77779bL,0xf0fe0cc98cdc9f82L,0xca5f7fe6f1c5b1bcL, + 0xcc63a68244929a72L } }, + /* 23 << 203 */ + { { 0xc7eaba0c09dbe19aL,0x2f3585ad6b5c73c2L,0x8ab8924b0ae50c30L, + 0x17fcd27a638b30baL }, + { 0xaf414d3410b3d5a5L,0x09c107d22a9accf1L,0x15dac49f946a6242L, + 0xaec3df2ad707d642L } }, + /* 24 << 203 */ + { { 0x2c2492b73f894ae0L,0xf59df3e5b75f18ceL,0x7cb740d28f53cad0L, + 0x3eb585fbc4f01294L }, + { 0x17da0c8632c7f717L,0xeb8c795baf943f4cL,0x4ee23fb5f67c51d2L, + 0xef18757568889949L } }, + /* 25 << 203 */ + { { 0xa6b4bdb20389168bL,0xc4ecd258ea577d03L,0x3a63782b55743082L, + 0x6f678f4cc72f08cdL }, + { 0x553511cf65e58dd8L,0xd53b4e3ed402c0cdL,0x37de3e29a037c14cL, + 0x86b6c516c05712aaL } }, + /* 26 << 203 */ + { { 0x2834da3eb38dff6fL,0xbe012c52ea636be8L,0x292d238c61dd37f8L, + 0x0e54523f8f8142dbL }, + { 0xe31eb436036a05d8L,0x83e3cdff1e93c0ffL,0x3fd2fe0f50821ddfL, + 0xc8e19b0dff9eb33bL } }, + /* 27 << 203 */ + { { 0xc8cc943fb569a5feL,0xad0090d4d4342d75L,0x82090b4bcaeca000L, + 0xca39687f1bd410ebL }, + { 0xe7bb0df765959d77L,0x39d782189c964999L,0xd87f62e8b2415451L, + 0xe5efb774bed76108L } }, + /* 28 << 203 */ + { { 0x3ea011a4e822f0d0L,0xbc647ad15a8704f8L,0xbb315b3550c6820fL, + 0x863dec3db7e76becL }, + { 0x01ff5d3af017bfc7L,0x20054439976b8229L,0x067fca370bbd0d3bL, + 0xf63dde647f5e3d0fL } }, + /* 29 << 203 */ + { { 0x22dbefb32a4c94e9L,0xafbff0fe96f8278aL,0x80aea0b13503793dL, + 0xb22380295f06cd29L }, + { 0x65703e578ec3fecaL,0x06c38314393e7053L,0xa0b751eb7c6734c4L, + 0xd2e8a435c59f0f1eL } }, + /* 30 << 203 */ + { { 0x147d90525e9ca895L,0x2f4dd31e972072dfL,0xa16fda8ee6c6755cL, + 0xc66826ffcf196558L }, + { 0x1f1a76a30cf43895L,0xa9d604e083c3097bL,0xe190830966390e0eL, + 0xa50bf753b3c85effL } }, + /* 31 << 203 */ + { { 0x0696bddef6a70251L,0x548b801b3c6ab16aL,0x37fcf704a4d08762L, + 0x090b3defdff76c4eL }, + { 0x87e8cb8969cb9158L,0x44a90744995ece43L,0xf85395f40ad9fbf5L, + 0x49b0f6c54fb0c82dL } }, + /* 32 << 203 */ + { { 0x75d9bc15adf7cccfL,0x81a3e5d6dfa1e1b0L,0x8c39e444249bc17eL, + 0xf37dccb28ea7fd43L }, + { 0xda654873907fba12L,0x35daa6da4a372904L,0x0564cfc66283a6c5L, + 0xd09fa4f64a9395bfL } }, + /* 33 << 203 */ + { { 0x688e9ec9aeb19a36L,0xd913f1cec7bfbfb4L,0x797b9a3c61c2faa6L, + 0x2f979bec6a0a9c12L }, + { 0xb5969d0f359679ecL,0xebcf523d079b0460L,0xfd6b000810fab870L, + 0x3f2edcda9373a39cL } }, + /* 34 << 203 */ + { { 0x0d64f9a76f568431L,0xf848c27c02f8898cL,0xf418ade1260b5bd5L, + 0xc1f3e3236973dee8L }, + { 0x46e9319c26c185ddL,0x6d85b7d8546f0ac4L,0x427965f2247f9d57L, + 0xb519b636b0035f48L } }, + /* 35 << 203 */ + { { 0x6b6163a9ab87d59cL,0xff9f58c339caaa11L,0x4ac39cde3177387bL, + 0x5f6557c2873e77f9L }, + { 0x6750400636a83041L,0x9b1c96ca75ef196cL,0xf34283deb08c7940L, + 0x7ea096441128c316L } }, + /* 36 << 203 */ + { { 0xb510b3b56aa39dffL,0x59b43da29f8e4d8cL,0xa8ce31fd9e4c4b9fL, + 0x0e20be26c1303c01L }, + { 0x18187182e8ee47c9L,0xd9687cdb7db98101L,0x7a520e4da1e14ff6L, + 0x429808ba8836d572L } }, + /* 37 << 203 */ + { { 0xa37ca60d4944b663L,0xf901f7a9a3f91ae5L,0xe4e3e76e9e36e3b1L, + 0x9aa219cf29d93250L }, + { 0x347fe275056a2512L,0xa4d643d9de65d95cL,0x9669d396699fc3edL, + 0xb598dee2cf8c6bbeL } }, + /* 38 << 203 */ + { { 0x682ac1e5dda9e5c6L,0x4e0d3c72caa9fc95L,0x17faaade772bea44L, + 0x5ef8428cab0009c8L }, + { 0xcc4ce47a460ff016L,0xda6d12bf725281cbL,0x44c678480223aad2L, + 0x6e342afa36256e28L } }, + /* 39 << 203 */ + { { 0x1400bb0b93a37c04L,0x62b1bc9bdd10bd96L,0x7251adeb0dac46b7L, + 0x7d33b92e7be4ef51L }, + { 0x28b2a94be61fa29aL,0x4b2be13f06422233L,0x36d6d062330d8d37L, + 0x5ef80e1eb28ca005L } }, + /* 40 << 203 */ + { { 0x174d46996d16768eL,0x9fc4ff6a628bf217L,0x77705a94154e490dL, + 0x9d96dd288d2d997aL }, + { 0x77e2d9d8ce5d72c4L,0x9d06c5a4c11c714fL,0x02aa513679e4a03eL, + 0x1386b3c2030ff28bL } }, + /* 41 << 203 */ + { { 0xfe82e8a6fb283f61L,0x7df203e5f3abc3fbL,0xeec7c3513a4d3622L, + 0xf7d17dbfdf762761L }, + { 0xc3956e44522055f0L,0xde3012db8fa748dbL,0xca9fcb63bf1dcc14L, + 0xa56d9dcfbe4e2f3aL } }, + /* 42 << 203 */ + { { 0xb86186b68bcec9c2L,0x7cf24df9680b9f06L,0xc46b45eac0d29281L, + 0xfff42bc507b10e12L }, + { 0x12263c404d289427L,0x3d5f1899b4848ec4L,0x11f97010d040800cL, + 0xb4c5f529300feb20L } }, + /* 43 << 203 */ + { { 0xcc543f8fde94fdcbL,0xe96af739c7c2f05eL,0xaa5e0036882692e1L, + 0x09c75b68950d4ae9L }, + { 0x62f63df2b5932a7aL,0x2658252ede0979adL,0x2a19343fb5e69631L, + 0x718c7501525b666bL } }, + /* 44 << 203 */ + { { 0x26a42d69ea40dc3aL,0xdc84ad22aecc018fL,0x25c36c7b3270f04aL, + 0x46ba6d4750fa72edL }, + { 0x6c37d1c593e58a8eL,0xa2394731120c088cL,0xc3be4263cb6e86daL, + 0x2c417d367126d038L } }, + /* 45 << 203 */ + { { 0x5b70f9c58b6f8efaL,0x671a2faa37718536L,0xd3ced3c6b539c92bL, + 0xe56f1bd9a31203c2L }, + { 0x8b096ec49ff3c8ebL,0x2deae43243491ceaL,0x2465c6eb17943794L, + 0x5d267e6620586843L } }, + /* 46 << 203 */ + { { 0x9d3d116db07159d0L,0xae07a67fc1896210L,0x8fc84d87bb961579L, + 0x30009e491c1f8dd6L }, + { 0x8a8caf22e3132819L,0xcffa197cf23ab4ffL,0x58103a44205dd687L, + 0x57b796c30ded67a2L } }, + /* 47 << 203 */ + { { 0x0b9c3a6ca1779ad7L,0xa33cfe2e357c09c5L,0x2ea293153db4a57eL, + 0x919596958ebeb52eL }, + { 0x118db9a6e546c879L,0x8e996df46295c8d6L,0xdd99048455ec806bL, + 0x24f291ca165c1035L } }, + /* 48 << 203 */ + { { 0xcca523bb440e2229L,0x324673a273ef4d04L,0xaf3adf343e11ec39L, + 0x6136d7f1dc5968d3L }, + { 0x7a7b2899b053a927L,0x3eaa2661ae067ecdL,0x8549b9c802779cd9L, + 0x061d7940c53385eaL } }, + /* 49 << 203 */ + { { 0x3e0ba883f06d18bdL,0x4ba6de53b2700843L,0xb966b668591a9e4dL, + 0x93f675677f4fa0edL }, + { 0x5a02711b4347237bL,0xbc041e2fe794608eL,0x55af10f570f73d8cL, + 0xd2d4d4f7bb7564f7L } }, + /* 50 << 203 */ + { { 0xd7d27a89b3e93ce7L,0xf7b5a8755d3a2c1bL,0xb29e68a0255b218aL, + 0xb533837e8af76754L }, + { 0xd1b05a73579fab2eL,0xb41055a1ecd74385L,0xb2369274445e9115L, + 0x2972a7c4f520274eL } }, + /* 51 << 203 */ + { { 0x6c08334ef678e68aL,0x4e4160f099b057edL,0x3cfe11b852ccb69aL, + 0x2fd1823a21c8f772L }, + { 0xdf7f072f3298f055L,0x8c0566f9fec74a6eL,0xe549e0195bb4d041L, + 0x7c3930ba9208d850L } }, + /* 52 << 203 */ + { { 0xe07141fcaaa2902bL,0x539ad799e4f69ad3L,0xa6453f94813f9ffdL, + 0xc58d3c48375bc2f7L }, + { 0xb3326fad5dc64e96L,0x3aafcaa9b240e354L,0x1d1b0903aca1e7a9L, + 0x4ceb97671211b8a0L } }, + /* 53 << 203 */ + { { 0xeca83e49e32a858eL,0x4c32892eae907badL,0xd5b42ab62eb9b494L, + 0x7fde3ee21eabae1bL }, + { 0x13b5ab09caf54957L,0xbfb028bee5f5d5d5L,0x928a06502003e2c0L, + 0x90793aac67476843L } }, + /* 54 << 203 */ + { { 0x5e942e79c81710a0L,0x557e4a3627ccadd4L,0x72a2bc564bcf6d0cL, + 0x09ee5f4326d7b80cL }, + { 0x6b70dbe9d4292f19L,0x56f74c2663f16b18L,0xc23db0f735fbb42aL, + 0xb606bdf66ae10040L } }, + /* 55 << 203 */ + { { 0x1eb15d4d044573acL,0x7dc3cf86556b0ba4L,0x97af9a33c60df6f7L, + 0x0b1ef85ca716ce8cL }, + { 0x2922f884c96958beL,0x7c32fa9435690963L,0x2d7f667ceaa00061L, + 0xeaaf7c173547365cL } }, + /* 56 << 203 */ + { { 0x1eb4de4687032d58L,0xc54f3d835e2c79e0L,0x07818df45d04ef23L, + 0x55faa9c8673d41b4L }, + { 0xced64f6f89b95355L,0x4860d2eab7415c84L,0x5fdb9bd2050ebad3L, + 0xdb53e0cc6685a5bfL } }, + /* 57 << 203 */ + { { 0xb830c0319feb6593L,0xdd87f3106accff17L,0x2303ebab9f555c10L, + 0x94603695287e7065L }, + { 0xf88311c32e83358cL,0x508dd9b4eefb0178L,0x7ca237062dba8652L, + 0x62aac5a30047abe5L } }, + /* 58 << 203 */ + { { 0x9a61d2a08b1ea7b3L,0xd495ab63ae8b1485L,0x38740f8487052f99L, + 0x178ebe5bb2974eeaL }, + { 0x030bbcca5b36d17fL,0xb5e4cce3aaf86eeaL,0xb51a022068f8e9e0L, + 0xa434879609eb3e75L } }, + /* 59 << 203 */ + { { 0xbe592309eef1a752L,0x5d7162d76f2aa1edL,0xaebfb5ed0f007dd2L, + 0x255e14b2c89edd22L }, + { 0xba85e0720303b697L,0xc5d17e25f05720ffL,0x02b58d6e5128ebb6L, + 0x2c80242dd754e113L } }, + /* 60 << 203 */ + { { 0x919fca5fabfae1caL,0x937afaac1a21459bL,0x9e0ca91c1f66a4d2L, + 0x194cc7f323ec1331L }, + { 0xad25143a8aa11690L,0xbe40ad8d09b59e08L,0x37d60d9be750860aL, + 0x6c53b008c6bf434cL } }, + /* 61 << 203 */ + { { 0xb572415d1356eb80L,0xb8bf9da39578ded8L,0x22658e365e8fb38bL, + 0x9b70ce225af8cb22L }, + { 0x7c00018a829a8180L,0x84329f93b81ed295L,0x7c343ea25f3cea83L, + 0x38f8655f67586536L } }, + /* 62 << 203 */ + { { 0xa661a0d01d3ec517L,0x98744652512321aeL,0x084ca591eca92598L, + 0xa9bb9dc91dcb3febL }, + { 0x14c5435578b4c240L,0x5ed62a3b610cafdcL,0x07512f371b38846bL, + 0x571bb70ab0e38161L } }, + /* 63 << 203 */ + { { 0xb556b95b2da705d2L,0x3ef8ada6b1a08f98L,0x85302ca7ddecfbe5L, + 0x0e530573943105cdL }, + { 0x60554d5521a9255dL,0x63a32fa1f2f3802aL,0x35c8c5b0cd477875L, + 0x97f458ea6ad42da1L } }, + /* 64 << 203 */ + { { 0x832d7080eb6b242dL,0xd30bd0233b71e246L,0x7027991bbe31139dL, + 0x68797e91462e4e53L }, + { 0x423fe20a6b4e185aL,0x82f2c67e42d9b707L,0x25c817684cf7811bL, + 0xbd53005e045bb95dL } }, + /* 0 << 210 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 210 */ + { { 0xe5f649be9d8e68fdL,0xdb0f05331b044320L,0xf6fde9b3e0c33398L, + 0x92f4209b66c8cfaeL }, + { 0xe9d1afcc1a739d4bL,0x09aea75fa28ab8deL,0x14375fb5eac6f1d0L, + 0x6420b560708f7aa5L } }, + /* 2 << 210 */ + { { 0x9eae499c6254dc41L,0x7e2939247a837e7eL,0x74aec08c090524a7L, + 0xf82b92198d6f55f2L }, + { 0x493c962e1402cec5L,0x9f17ca17fa2f30e7L,0xbcd783e8e9b879cbL, + 0xea3d8c145a6f145fL } }, + /* 3 << 210 */ + { { 0xdede15e75e0dee6eL,0x74f24872dc628aa2L,0xd3e9c4fe7861bb93L, + 0x56d4822a6187b2e0L }, + { 0xb66417cfc59826f9L,0xca2609692408169eL,0xedf69d06c79ef885L, + 0x00031f8adc7d138fL } }, + /* 4 << 210 */ + { { 0x103c46e60ebcf726L,0x4482b8316231470eL,0x6f6dfaca487c2109L, + 0x2e0ace9762e666efL }, + { 0x3246a9d31f8d1f42L,0x1b1e83f1574944d2L,0x13dfa63aa57f334bL, + 0x0cf8daed9f025d81L } }, + /* 5 << 210 */ + { { 0x30d78ea800ee11c1L,0xeb053cd4b5e3dd75L,0x9b65b13ed58c43c5L, + 0xc3ad49bdbd151663L }, + { 0x99fd8e41b6427990L,0x12cf15bd707eae1eL,0x29ad4f1b1aabb71eL, + 0x5143e74d07545d0eL } }, + /* 6 << 210 */ + { { 0x30266336c88bdee1L,0x25f293065876767cL,0x9c078571c6731996L, + 0xc88690b2ed552951L }, + { 0x274f2c2d852705b4L,0xb0bf8d444e09552dL,0x7628beeb986575d1L, + 0x407be2387f864651L } }, + /* 7 << 210 */ + { { 0x0e5e3049a639fc6bL,0xe75c35d986003625L,0x0cf35bd85dcc1646L, + 0x8bcaced26c26273aL }, + { 0xe22ecf1db5536742L,0x013dd8971a9e068bL,0x17f411cb8a7909c5L, + 0x5757ac98861dd506L } }, + /* 8 << 210 */ + { { 0x85de1f0d1e935abbL,0xdefd10b4154de37aL,0xb8d9e392369cebb5L, + 0x54d5ef9b761324beL }, + { 0x4d6341ba74f17e26L,0xc0a0e3c878c1dde4L,0xa6d7758187d918fdL, + 0x6687601502ca3a13L } }, + /* 9 << 210 */ + { { 0xc7313e9cf36658f0L,0xc433ef1c71f8057eL,0x853262461b6a835aL, + 0xc8f053987c86394cL }, + { 0xff398cdfe983c4a1L,0xbf5e816203b7b931L,0x93193c46b7b9045bL, + 0x1e4ebf5da4a6e46bL } }, + /* 10 << 210 */ + { { 0xf9942a6043a24fe7L,0x29c1191effb3492bL,0x9f662449902fde05L, + 0xc792a7ac6713c32dL }, + { 0x2fd88ad8b737982cL,0x7e3a0319a21e60e3L,0x09b0de447383591aL, + 0x6df141ee8310a456L } }, + /* 11 << 210 */ + { { 0xaec1a039e6d6f471L,0x14b2ba0f1198d12eL,0xebc1a1603aeee5acL, + 0x401f4836e0b964ceL }, + { 0x2ee437964fd03f66L,0x3fdb4e49dd8f3f12L,0x6ef267f629380f18L, + 0x3e8e96708da64d16L } }, + /* 12 << 210 */ + { { 0xbc19180c207674f1L,0x112e09a733ae8fdbL,0x996675546aaeb71eL, + 0x79432af1e101b1c7L }, + { 0xd5eb558fde2ddec6L,0x81392d1f5357753fL,0xa7a76b973ae1158aL, + 0x416fbbff4a899991L } }, + /* 13 << 210 */ + { { 0x9e65fdfd0d4a9dcfL,0x7bc29e48944ddf12L,0xbc1a92d93c856866L, + 0x273c69056e98dfe2L }, + { 0x69fce418cdfaa6b8L,0x606bd8235061c69fL,0x42d495a06af75e27L, + 0x8ed3d5056d873a1fL } }, + /* 14 << 210 */ + { { 0xaf5528416ab25b6aL,0xc6c0ffc72b1a4523L,0xab18827b21c99e03L, + 0x060e86489034691bL }, + { 0x5207f90f93c7f398L,0x9f4a96cb82f8d10bL,0xdd71cd793ad0f9e3L, + 0x84f435d2fc3a54f5L } }, + /* 15 << 210 */ + { { 0x4b03c55b8e33787fL,0xef42f975a6384673L,0xff7304f75051b9f0L, + 0x18aca1dc741c87c2L }, + { 0x56f120a72d4bfe80L,0xfd823b3d053e732cL,0x11bccfe47537ca16L, + 0xdf6c9c741b5a996bL } }, + /* 16 << 210 */ + { { 0xee7332c7904fc3faL,0x14a23f45c7e3636aL,0xc38659c3f091d9aaL, + 0x4a995e5db12d8540L }, + { 0x20a53becf3a5598aL,0x56534b17b1eaa995L,0x9ed3dca4bf04e03cL, + 0x716c563ad8d56268L } }, + /* 17 << 210 */ + { { 0x27ba77a41d6178e7L,0xe4c80c4068a1ff8eL,0x750110990a13f63dL, + 0x7bf33521a61d46f3L }, + { 0x0aff218e10b365bbL,0x810218040fd7ea75L,0x05a3fd8aa4b3a925L, + 0xb829e75f9b3db4e6L } }, + /* 18 << 210 */ + { { 0x6bdc75a54d53e5fbL,0x04a5dc02d52717e3L,0x86af502fe9a42ec2L, + 0x8867e8fb2630e382L }, + { 0xbf845c6ebec9889bL,0x54f491f2cb47c98dL,0xa3091fba790c2a12L, + 0xd7f6fd78c20f708bL } }, + /* 19 << 210 */ + { { 0xa569ac30acde5e17L,0xd0f996d06852b4d7L,0xe51d4bb54609ae54L, + 0x3fa37d170daed061L }, + { 0x62a8868434b8fb41L,0x99a2acbd9efb64f1L,0xb75c1a5e6448e1f2L, + 0xfa99951a42b5a069L } }, + /* 20 << 210 */ + { { 0x6d956e892f3b26e7L,0xf4709860da875247L,0x3ad151792482dda3L, + 0xd64110e3017d82f0L }, + { 0x14928d2cfad414e4L,0x2b155f582ed02b24L,0x481a141bcb821bf1L, + 0x12e3c7704f81f5daL } }, + /* 21 << 210 */ + { { 0xe49c5de59fff8381L,0x110532325bbec894L,0xa0d051cc454d88c4L, + 0x4f6db89c1f8e531bL }, + { 0x34fe3fd6ca563a44L,0x7f5c221558da8ab9L,0x8445016d9474f0a1L, + 0x17d34d61cb7d8a0aL } }, + /* 22 << 210 */ + { { 0x8e9d39101c474019L,0xcaff2629d52ceefbL,0xf9cf3e32c1622c2bL, + 0xd4b95e3ce9071a05L }, + { 0xfbbca61f1594438cL,0x1eb6e6a604aadedfL,0x853027f468e14940L, + 0x221d322adfabda9cL } }, + /* 23 << 210 */ + { { 0xed8ea9f6b7cb179aL,0xdc7b764db7934dccL,0xfcb139405e09180dL, + 0x6629a6bfb47dc2ddL }, + { 0xbfc55e4e9f5a915eL,0xb1db9d376204441eL,0xf82d68cf930c5f53L, + 0x17d3a142cbb605b1L } }, + /* 24 << 210 */ + { { 0xdd5944ea308780f2L,0xdc8de7613845f5e4L,0x6beaba7d7624d7a3L, + 0x1e709afd304df11eL }, + { 0x9536437602170456L,0xbf204b3ac8f94b64L,0x4e53af7c5680ca68L, + 0x0526074ae0c67574L } }, + /* 25 << 210 */ + { { 0x95d8cef8ecd92af6L,0xe6b9fa7a6cd1745aL,0x3d546d3da325c3e4L, + 0x1f57691d9ae93aaeL }, + { 0xe891f3fe9d2e1a33L,0xd430093fac063d35L,0xeda59b125513a327L, + 0xdc2134f35536f18fL } }, + /* 26 << 210 */ + { { 0xaa51fe2c5c210286L,0x3f68aaee1cab658cL,0x5a23a00bf9357292L, + 0x9a626f397efdabedL }, + { 0xfe2b3bf3199d78e3L,0xb7a2af7771bbc345L,0x3d19827a1e59802cL, + 0x823bbc15b487a51cL } }, + /* 27 << 210 */ + { { 0x856139f299d0a422L,0x9ac3df65f456c6fbL,0xaddf65c6701f8bd6L, + 0x149f321e3758df87L }, + { 0xb1ecf714721b7ebaL,0xe17df09831a3312aL,0xdb2fd6ecd5c4d581L, + 0xfd02996f8fcea1b3L } }, + /* 28 << 210 */ + { { 0xe29fa63e7882f14fL,0xc9f6dc3507c6cadcL,0x46f22d6fb882bed0L, + 0x1a45755bd118e52cL }, + { 0x9f2c7c277c4608cfL,0x7ccbdf32568012c2L,0xfcb0aedd61729b0eL, + 0x7ca2ca9ef7d75dbfL } }, + /* 29 << 210 */ + { { 0xf58fecb16f640f62L,0xe274b92b39f51946L,0x7f4dfc046288af44L, + 0x0a91f32aeac329e5L }, + { 0x43ad274bd6aaba31L,0x719a16400f6884f9L,0x685d29f6daf91e20L, + 0x5ec1cc3327e49d52L } }, + /* 30 << 210 */ + { { 0x38f4de963b54a059L,0x0e0015e5efbcfdb3L,0x177d23d94dbb8da6L, + 0x98724aa297a617adL }, + { 0x30f0885bfdb6558eL,0xf9f7a28ac7899a96L,0xd2ae8ac8872dc112L, + 0xfa0642ca73c3c459L } }, + /* 31 << 210 */ + { { 0x15296981e7dfc8d6L,0x67cd44501fb5b94aL,0x0ec71cf10eddfd37L, + 0xc7e5eeb39a8eddc7L }, + { 0x02ac8e3d81d95028L,0x0088f17270b0e35dL,0xec041fabe1881fe3L, + 0x62cf71b8d99e7faaL } }, + /* 32 << 210 */ + { { 0x5043dea7e0f222c2L,0x309d42ac72e65142L,0x94fe9ddd9216cd30L, + 0xd6539c7d0f87feecL }, + { 0x03c5a57c432ac7d7L,0x72692cf0327fda10L,0xec28c85f280698deL, + 0x2331fb467ec283b1L } }, + /* 33 << 210 */ + { { 0xd34bfa322867e633L,0x78709a820a9cc815L,0xb7fe6964875e2fa5L, + 0x25cc064f9e98bfb5L }, + { 0x9eb0151c493a65c5L,0x5fb5d94153182464L,0x69e6f130f04618e2L, + 0xa8ecec22f89c8ab6L } }, + /* 34 << 210 */ + { { 0xcd6ac88bb96209bdL,0x65fa8cdbb3e1c9e0L,0xa47d22f54a8d8eacL, + 0x83895cdf8d33f963L }, + { 0xa8adca59b56cd3d1L,0x10c8350bdaf38232L,0x2b161fb3a5080a9fL, + 0xbe7f5c643af65b3aL } }, + /* 35 << 210 */ + { { 0x2c75403997403a11L,0x94626cf7121b96afL,0x431de7c46a983ec2L, + 0x3780dd3a52cc3df7L }, + { 0xe28a0e462baf8e3bL,0xabe68aad51d299aeL,0x603eb8f9647a2408L, + 0x14c61ed65c750981L } }, + /* 36 << 210 */ + { { 0x88b34414c53352e7L,0x5a34889c1337d46eL,0x612c1560f95f2bc8L, + 0x8a3f8441d4807a3aL }, + { 0x680d9e975224da68L,0x60cd6e88c3eb00e9L,0x3875a98e9a6bc375L, + 0xdc80f9244fd554c2L } }, + /* 37 << 210 */ + { { 0x6c4b34156ac77407L,0xa1e5ea8f25420681L,0x541bfa144607a458L, + 0x5dbc7e7a96d7fbf9L }, + { 0x646a851b31590a47L,0x039e85ba15ee6df8L,0xd19fa231d7b43fc0L, + 0x84bc8be8299a0e04L } }, + /* 38 << 210 */ + { { 0x2b9d2936f20df03aL,0x240543828608d472L,0x76b6ba049149202aL, + 0xb21c38313670e7b7L }, + { 0xddd93059d6fdee10L,0x9da47ad378488e71L,0x99cc1dfda0fcfb25L, + 0x42abde1064696954L } }, + /* 39 << 210 */ + { { 0x14cc15fc17eab9feL,0xd6e863e4d3e70972L,0x29a7765c6432112cL, + 0x886600015b0774d8L }, + { 0x3729175a2c088eaeL,0x13afbcae8230b8d4L,0x44768151915f4379L, + 0xf086431ad8d22812L } }, + /* 40 << 210 */ + { { 0x37461955c298b974L,0x905fb5f0f8711e04L,0x787abf3afe969d18L, + 0x392167c26f6a494eL }, + { 0xfc7a0d2d28c511daL,0xf127c7dcb66a262dL,0xf9c4bb95fd63fdf0L, + 0x900165893913ef46L } }, + /* 41 << 210 */ + { { 0x74d2a73c11aa600dL,0x2f5379bd9fb5ab52L,0xe49e53a47fb70068L, + 0x68dd39e5404aa9a7L }, + { 0xb9b0cf572ecaa9c3L,0xba0e103be824826bL,0x60c2198b4631a3c4L, + 0xc5ff84abfa8966a2L } }, + /* 42 << 210 */ + { { 0x2d6ebe22ac95aff8L,0x1c9bb6dbb5a46d09L,0x419062da53ee4f8dL, + 0x7b9042d0bb97efefL }, + { 0x0f87f080830cf6bdL,0x4861d19a6ec8a6c6L,0xd3a0daa1202f01aaL, + 0xb0111674f25afbd5L } }, + /* 43 << 210 */ + { { 0x6d00d6cf1afb20d9L,0x1369500040671bc5L,0x913ab0dc2485ea9bL, + 0x1f2bed069eef61acL }, + { 0x850c82176d799e20L,0x93415f373271c2deL,0x5afb06e96c4f5910L, + 0x688a52dfc4e9e421L } }, + /* 44 << 210 */ + { { 0x30495ba3e2a9a6dbL,0x4601303d58f9268bL,0xbe3b0dad7eb0f04fL, + 0x4ea472504456936dL }, + { 0x8caf8798d33fd3e7L,0x1ccd8a89eb433708L,0x9effe3e887fd50adL, + 0xbe240a566b29c4dfL } }, + /* 45 << 210 */ + { { 0xec4ffd98ca0e7ebdL,0xf586783ae748616eL,0xa5b00d8fc77baa99L, + 0x0acada29b4f34c9cL }, + { 0x36dad67d0fe723acL,0x1d8e53a539c36c1eL,0xe4dd342d1f4bea41L, + 0x64fd5e35ebc9e4e0L } }, + /* 46 << 210 */ + { { 0x96f01f9057908805L,0xb5b9ea3d5ed480ddL,0x366c5dc23efd2dd0L, + 0xed2fe3056e9dfa27L }, + { 0x4575e8926e9197e2L,0x11719c09ab502a5dL,0x264c7bece81f213fL, + 0x741b924155f5c457L } }, + /* 47 << 210 */ + { { 0x78ac7b6849a5f4f4L,0xf91d70a29fc45b7dL,0x39b05544b0f5f355L, + 0x11f06bceeef930d9L }, + { 0xdb84d25d038d05e1L,0x04838ee5bacc1d51L,0x9da3ce869e8ee00bL, + 0xc3412057c36eda1fL } }, + /* 48 << 210 */ + { { 0xae80b91364d9c2f4L,0x7468bac3a010a8ffL,0xdfd2003737359d41L, + 0x1a0f5ab815efeaccL }, + { 0x7c25ad2f659d0ce0L,0x4011bcbb6785cff1L,0x128b99127e2192c7L, + 0xa549d8e113ccb0e8L } }, + /* 49 << 210 */ + { { 0x805588d8c85438b1L,0x5680332dbc25cb27L,0xdcd1bc961a4bfdf4L, + 0x779ff428706f6566L }, + { 0x8bbee998f059987aL,0xf6ce8cf2cc686de7L,0xf8ad3c4a953cfdb2L, + 0xd1d426d92205da36L } }, + /* 50 << 210 */ + { { 0xb3c0f13fc781a241L,0x3e89360ed75362a8L,0xccd05863c8a91184L, + 0x9bd0c9b7efa8a7f4L }, + { 0x97ee4d538a912a4bL,0xde5e15f8bcf518fdL,0x6a055bf8c467e1e0L, + 0x10be4b4b1587e256L } }, + /* 51 << 210 */ + { { 0xd90c14f2668621c9L,0xd5518f51ab9c92c1L,0x8e6a0100d6d47b3cL, + 0xcbe980dd66716175L }, + { 0x500d3f10ddd83683L,0x3b6cb35d99cac73cL,0x53730c8b6083d550L, + 0xcf159767df0a1987L } }, + /* 52 << 210 */ + { { 0x84bfcf5343ad73b3L,0x1b528c204f035a94L,0x4294edf733eeac69L, + 0xb6283e83817f3240L }, + { 0xc3fdc9590a5f25b1L,0xefaf8aa55844ee22L,0xde269ba5dbdde4deL, + 0xe3347160c56133bfL } }, + /* 53 << 210 */ + { { 0xc11842198d9ea9f8L,0x090de5dbf3fc1ab5L,0x404c37b10bf22cdaL, + 0x7de20ec8f5618894L }, + { 0x754c588eecdaecabL,0x6ca4b0ed88342743L,0x76f08bddf4a938ecL, + 0xd182de8991493ccbL } }, + /* 54 << 210 */ + { { 0xd652c53ec8a4186aL,0xb3e878db946d8e33L,0x088453c05f37663cL, + 0x5cd9daaab407748bL }, + { 0xa1f5197f586d5e72L,0x47500be8c443ca59L,0x78ef35b2e2652424L, + 0x09c5d26f6dd7767dL } }, + /* 55 << 210 */ + { { 0x7175a79aa74d3f7bL,0x0428fd8dcf5ea459L,0x511cb97ca5d1746dL, + 0x36363939e71d1278L }, + { 0xcf2df95510350bf4L,0xb381743960aae782L,0xa748c0e43e688809L, + 0x98021fbfd7a5a006L } }, + /* 56 << 210 */ + { { 0x9076a70c0e367a98L,0xbea1bc150f62b7c2L,0x2645a68c30fe0343L, + 0xacaffa78699dc14fL }, + { 0xf4469964457bf9c4L,0x0db6407b0d2ead83L,0x68d56cadb2c6f3ebL, + 0x3b512e73f376356cL } }, + /* 57 << 210 */ + { { 0xe43b0e1ffce10408L,0x89ddc0035a5e257dL,0xb0ae0d120362e5b3L, + 0x07f983c7b0519161L }, + { 0xc2e94d155d5231e7L,0xcff22aed0b4f9513L,0xb02588dd6ad0b0b5L, + 0xb967d1ac11d0dcd5L } }, + /* 58 << 210 */ + { { 0x8dac6bc6cf777b6cL,0x0062bdbd4c6d1959L,0x53da71b50ef5cc85L, + 0x07012c7d4006f14fL }, + { 0x4617f962ac47800dL,0x53365f2bc102ed75L,0xb422efcb4ab8c9d3L, + 0x195cb26b34af31c9L } }, + /* 59 << 210 */ + { { 0x3a926e2905f2c4ceL,0xbd2bdecb9856966cL,0x5d16ab3a85527015L, + 0x9f81609e4486c231L }, + { 0xd8b96b2cda350002L,0xbd054690fa1b7d36L,0xdc90ebf5e71d79bcL, + 0xf241b6f908964e4eL } }, + /* 60 << 210 */ + { { 0x7c8386432fe3cd4cL,0xe0f33acbb4bc633cL,0xb4a9ecec3d139f1fL, + 0x05ce69cddc4a1f49L }, + { 0xa19d1b16f5f98aafL,0x45bb71d66f23e0efL,0x33789fcd46cdfdd3L, + 0x9b8e2978cee040caL } }, + /* 61 << 210 */ + { { 0x9c69b246ae0a6828L,0xba533d247078d5aaL,0x7a2e42c07bb4fbdbL, + 0xcfb4879a7035385cL }, + { 0x8c3dd30b3281705bL,0x7e361c6c404fe081L,0x7b21649c3f604edfL, + 0x5dbf6a3fe52ffe47L } }, + /* 62 << 210 */ + { { 0xc41b7c234b54d9bfL,0x1374e6813511c3d9L,0x1863bf16c1b2b758L, + 0x90e785071e9e6a96L }, + { 0xab4bf98d5d86f174L,0xd74e0bd385e96fe4L,0x8afde39fcac5d344L, + 0x90946dbcbd91b847L } }, + /* 63 << 210 */ + { { 0xf5b42358fe1a838cL,0x05aae6c5620ac9d8L,0x8e193bd8a1ce5a0bL, + 0x8f7105714dabfd72L }, + { 0x8d8fdd48182caaacL,0x8c4aeefa040745cfL,0x73c6c30af3b93e6dL, + 0x991241f316f42011L } }, + /* 64 << 210 */ + { { 0xa0158eeae457a477L,0xd19857dbee6ddc05L,0xb326522418c41671L, + 0x3ffdfc7e3c2c0d58L }, + { 0x3a3a525426ee7cdaL,0x341b0869df02c3a8L,0xa023bf42723bbfc8L, + 0x3d15002a14452691L } }, + /* 0 << 217 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 217 */ + { { 0x5ef7324c85edfa30L,0x2597655487d4f3daL,0x352f5bc0dcb50c86L, + 0x8f6927b04832a96cL }, + { 0xd08ee1ba55f2f94cL,0x6a996f99344b45faL,0xe133cb8da8aa455dL, + 0x5d0721ec758dc1f7L } }, + /* 2 << 217 */ + { { 0x6ba7a92079e5fb67L,0xe1331feb70aa725eL,0x5080ccf57df5d837L, + 0xe4cae01d7ff72e21L }, + { 0xd9243ee60412a77dL,0x06ff7cacdf449025L,0xbe75f7cd23ef5a31L, + 0xbc9578220ddef7a8L } }, + /* 3 << 217 */ + { { 0x8cf7230cb0ce1c55L,0x5b534d050bbfb607L,0xee1ef1130e16363bL, + 0x27e0aa7ab4999e82L }, + { 0xce1dac2d79362c41L,0x67920c9091bb6cb0L,0x1e648d632223df24L, + 0x0f7d9eefe32e8f28L } }, + /* 4 << 217 */ + { { 0x6943f39afa833834L,0x22951722a6328562L,0x81d63dd54170fc10L, + 0x9f5fa58faecc2e6dL }, + { 0xb66c8725e77d9a3bL,0x11235cea6384ebe0L,0x06a8c1185845e24aL, + 0x0137b286ebd093b1L } }, + /* 5 << 217 */ + { { 0xc589e1ce44ace150L,0xe0f8d3d94381e97cL,0x59e99b1162c5a4b8L, + 0x90d262f7fd0ec9f9L }, + { 0xfbc854c9283e13c9L,0x2d04fde7aedc7085L,0x057d776547dcbecbL, + 0x8dbdf5919a76fa5fL } }, + /* 6 << 217 */ + { { 0xd01506950de1e578L,0x2e1463e7e9f72bc6L,0xffa684411b39eca5L, + 0x673c85307c037f2fL }, + { 0xd0d6a600747f91daL,0xb08d43e1c9cb78e9L,0x0fc0c64427b5cef5L, + 0x5c1d160aa60a2fd6L } }, + /* 7 << 217 */ + { { 0xf98cae5328c8e13bL,0x375f10c4b2eddcd1L,0xd4eb8b7f5cce06adL, + 0xb4669f4580a2e1efL }, + { 0xd593f9d05bbd8699L,0x5528a4c9e7976d13L,0x3923e0951c7e28d3L, + 0xb92937903f6bb577L } }, + /* 8 << 217 */ + { { 0xdb567d6ac42bd6d2L,0x6df86468bb1f96aeL,0x0efe5b1a4843b28eL, + 0x961bbb056379b240L }, + { 0xb6caf5f070a6a26bL,0x70686c0d328e6e39L,0x80da06cf895fc8d3L, + 0x804d8810b363fdc9L } }, + /* 9 << 217 */ + { { 0xbe22877b207f1670L,0x9b0dd1884e615291L,0x625ae8dc97a3c2bfL, + 0x08584ef7439b86e8L }, + { 0xde7190a5dcd898ffL,0x26286c402058ee3dL,0x3db0b2175f87b1c1L, + 0xcc334771102a6db5L } }, + /* 10 << 217 */ + { { 0xd99de9542f770fb1L,0x97c1c6204cd7535eL,0xd3b6c4483f09cefcL, + 0xd725af155a63b4f8L }, + { 0x0c95d24fc01e20ecL,0xdfd374949ae7121fL,0x7d6ddb72ec77b7ecL, + 0xfe079d3b0353a4aeL } }, + /* 11 << 217 */ + { { 0x3066e70a2e6ac8d2L,0x9c6b5a43106e5c05L,0x52d3c6f5ede59b8cL, + 0x30d6a5c3fccec9aeL }, + { 0xedec7c224fc0a9efL,0x190ff08395c16cedL,0xbe12ec8f94de0fdeL, + 0x0d131ab8852d3433L } }, + /* 12 << 217 */ + { { 0x42ace07e85701291L,0x94793ed9194061a8L,0x30e83ed6d7f4a485L, + 0x9eec7269f9eeff4dL }, + { 0x90acba590c9d8005L,0x5feca4581e79b9d1L,0x8fbe54271d506a1eL, + 0xa32b2c8e2439cfa7L } }, + /* 13 << 217 */ + { { 0x1671c17373dd0b4eL,0x37a2821444a054c6L,0x81760a1b4e8b53f1L, + 0xa6c04224f9f93b9eL }, + { 0x18784b34cf671e3cL,0x81bbecd2cda9b994L,0x38831979b2ab3848L, + 0xef54feb7f2e03c2dL } }, + /* 14 << 217 */ + { { 0xcf197ca7fb8088faL,0x014272474ddc96c5L,0xa2d2550a30777176L, + 0x534698984d0cf71dL }, + { 0x6ce937b83a2aaac6L,0xe9f91dc35af38d9bL,0x2598ad83c8bf2899L, + 0x8e706ac9b5536c16L } }, + /* 15 << 217 */ + { { 0x40dc7495f688dc98L,0x26490cd7124c4afcL,0xe651ec841f18775cL, + 0x393ea6c3b4fdaf4aL }, + { 0x1e1f33437f338e0dL,0x39fb832b6053e7b5L,0x46e702da619e14d5L, + 0x859cacd1cdeef6e0L } }, + /* 16 << 217 */ + { { 0x63b99ce74462007dL,0xb8ab48a54cb5f5b7L,0x9ec673d2f55edde7L, + 0xd1567f748cfaefdaL }, + { 0x46381b6b0887bcecL,0x694497cee178f3c2L,0x5e6525e31e6266cbL, + 0x5931de26697d6413L } }, + /* 17 << 217 */ + { { 0x87f8df7c0e58d493L,0xb1ae5ed058b73f12L,0xc368f784dea0c34dL, + 0x9bd0a120859a91a0L }, + { 0xb00d88b7cc863c68L,0x3a1cc11e3d1f4d65L,0xea38e0e70aa85593L, + 0x37f13e987dc4aee8L } }, + /* 18 << 217 */ + { { 0x10d38667bc947badL,0x738e07ce2a36ee2eL,0xc93470cdc577fcacL, + 0xdee1b6162782470dL }, + { 0x36a25e672e793d12L,0xd6aa6caee0f186daL,0x474d0fd980e07af7L, + 0xf7cdc47dba8a5cd4L } }, + /* 19 << 217 */ + { { 0x28af6d9dab15247fL,0x7c789c10493a537fL,0x7ac9b11023a334e7L, + 0x0236ac0912c9c277L }, + { 0xa7e5bd251d7a5144L,0x098b9c2af13ec4ecL,0x3639dacad3f0abcaL, + 0x642da81aa23960f9L } }, + /* 20 << 217 */ + { { 0x7d2e5c054f7269b1L,0xfcf30777e287c385L,0x10edc84ff2a46f21L, + 0x354417574f43fa36L }, + { 0xf1327899fd703431L,0xa438d7a616dd587aL,0x65c34c57e9c8352dL, + 0xa728edab5cc5a24eL } }, + /* 21 << 217 */ + { { 0xaed78abc42531689L,0x0a51a0e8010963efL,0x5776fa0ad717d9b3L, + 0xf356c2397dd3428bL }, + { 0x29903fff8d3a3dacL,0x409597fa3d94491fL,0x4cd7a5ffbf4a56a4L, + 0xe50964748adab462L } }, + /* 22 << 217 */ + { { 0xa97b51265c3427b0L,0x6401405cd282c9bdL,0x3629f8d7222c5c45L, + 0xb1c02c16e8d50aedL }, + { 0xbea2ed75d9635bc9L,0x226790c76e24552fL,0x3c33f2a365f1d066L, + 0x2a43463e6dfccc2eL } }, + /* 23 << 217 */ + { { 0x8cc3453adb483761L,0xe7cc608565d5672bL,0x277ed6cbde3efc87L, + 0x19f2f36869234eafL }, + { 0x9aaf43175c0b800bL,0x1f1e7c898b6da6e2L,0x6cfb4715b94ec75eL, + 0xd590dd5f453118c2L } }, + /* 24 << 217 */ + { { 0x14e49da11f17a34cL,0x5420ab39235a1456L,0xb76372412f50363bL, + 0x7b15d623c3fabb6eL }, + { 0xa0ef40b1e274e49cL,0x5cf5074496b1860aL,0xd6583fbf66afe5a4L, + 0x44240510f47e3e9aL } }, + /* 25 << 217 */ + { { 0x9925434311b2d595L,0xf1367499eec8df57L,0x3cb12c613e73dd05L, + 0xd248c0337dac102aL }, + { 0xcf154f13a77739f5L,0xbf4288cb23d2af42L,0xaa64c9b632e4a1cfL, + 0xee8c07a8c8a208f3L } }, + /* 26 << 217 */ + { { 0xe10d49996fe8393fL,0x0f809a3fe91f3a32L,0x61096d1c802f63c8L, + 0x289e146257750d3dL }, + { 0xed06167e9889feeaL,0xd5c9c0e2e0993909L,0x46fca0d856508ac6L, + 0x918260474f1b8e83L } }, + /* 27 << 217 */ + { { 0x4f2c877a9a4a2751L,0x71bd0072cae6feadL,0x38df8dcc06aa1941L, + 0x5a074b4c63beeaa8L }, + { 0xd6d65934c1cec8edL,0xa6ecb49eaabc03bdL,0xaade91c2de8a8415L, + 0xcfb0efdf691136e0L } }, + /* 28 << 217 */ + { { 0x11af45ee23ab3495L,0xa132df880b77463dL,0x8923c15c815d06f4L, + 0xc3ceb3f50d61a436L }, + { 0xaf52291de88fb1daL,0xea0579741da12179L,0xb0d7218cd2fef720L, + 0x6c0899c98e1d8845L } }, + /* 29 << 217 */ + { { 0x98157504752ddad7L,0xd60bd74fa1a68a97L,0x7047a3a9f658fb99L, + 0x1f5d86d65f8511e4L }, + { 0xb8a4bc424b5a6d88L,0x69eb2c331abefa7dL,0x95bf39e813c9c510L, + 0xf571960ad48aab43L } }, + /* 30 << 217 */ + { { 0x7e8cfbcf704e23c6L,0xc71b7d2228aaa65bL,0xa041b2bd245e3c83L, + 0x69b98834d21854ffL }, + { 0x89d227a3963bfeecL,0x99947aaade7da7cbL,0x1d9ee9dbee68a9b1L, + 0x0a08f003698ec368L } }, + /* 31 << 217 */ + { { 0xe9ea409478ef2487L,0xc8d2d41502cfec26L,0xc52f9a6eb7dcf328L, + 0x0ed489e385b6a937L }, + { 0x9b94986bbef3366eL,0x0de59c70edddddb8L,0xffdb748ceadddbe2L, + 0x9b9784bb8266ea40L } }, + /* 32 << 217 */ + { { 0x142b55021a93507aL,0xb4cd11878d3c06cfL,0xdf70e76a91ec3f40L, + 0x484e81ad4e7553c2L }, + { 0x830f87b5272e9d6eL,0xea1c93e5c6ff514aL,0x67cc2adcc4192a8eL, + 0xc77e27e242f4535aL } }, + /* 33 << 217 */ + { { 0x9cdbab36d2b713c5L,0x86274ea0cf7b0cd3L,0x784680f309af826bL, + 0xbfcc837a0c72dea3L }, + { 0xa8bdfe9dd6529b73L,0x708aa22863a88002L,0x6c7a9a54c91d45b9L, + 0xdf1a38bbfd004f56L } }, + /* 34 << 217 */ + { { 0x2e8c9a26b8bad853L,0x2d52cea33723eae7L,0x054d6d8156ca2830L, + 0xa3317d149a8dc411L }, + { 0xa08662fefd4ddedaL,0xed2a153ab55d792bL,0x7035c16abfc6e944L, + 0xb6bc583400171cf3L } }, + /* 35 << 217 */ + { { 0xe27152b383d102b6L,0xfe695a470646b848L,0xa5bb09d8916e6d37L, + 0xb4269d640d17015eL }, + { 0x8d8156a10a1d2285L,0xfeef6c5146d26d72L,0x9dac57c84c5434a7L, + 0x0282e5be59d39e31L } }, + /* 36 << 217 */ + { { 0xedfff181721c486dL,0x301baf10bc58824eL,0x8136a6aa00570031L, + 0x55aaf78c1cddde68L }, + { 0x2682937159c63952L,0x3a3bd2748bc25bafL,0xecdf8657b7e52dc3L, + 0x2dd8c087fd78e6c8L } }, + /* 37 << 217 */ + { { 0x20553274f5531461L,0x8b4a12815d95499bL,0xe2c8763a1a80f9d2L, + 0xd1dbe32b4ddec758L }, + { 0xaf12210d30c34169L,0xba74a95378baa533L,0x3d133c6ea438f254L, + 0xa431531a201bef5bL } }, + /* 38 << 217 */ + { { 0x15295e22f669d7ecL,0xca374f64357fb515L,0x8a8406ffeaa3fdb3L, + 0x106ae448df3f2da8L }, + { 0x8f9b0a9033c8e9a1L,0x234645e271ad5885L,0x3d0832241c0aed14L, + 0xf10a7d3e7a942d46L } }, + /* 39 << 217 */ + { { 0x7c11deee40d5c9beL,0xb2bae7ffba84ed98L,0x93e97139aad58dddL, + 0x3d8727963f6d1fa3L }, + { 0x483aca818569ff13L,0x8b89a5fb9a600f72L,0x4cbc27c3c06f2b86L, + 0x2213071363ad9c0bL } }, + /* 40 << 217 */ + { { 0xb5358b1e48ac2840L,0x18311294ecba9477L,0xda58f990a6946b43L, + 0x3098baf99ab41819L }, + { 0x66c4c1584198da52L,0xab4fc17c146bfd1bL,0x2f0a4c3cbf36a908L, + 0x2ae9e34b58cf7838L } }, + /* 41 << 217 */ + { { 0xf411529e3fa11b1fL,0x21e43677974af2b4L,0x7c20958ec230793bL, + 0x710ea88516e840f3L }, + { 0xfc0b21fcc5dc67cfL,0x08d5164788405718L,0xd955c21fcfe49eb7L, + 0x9722a5d556dd4a1fL } }, + /* 42 << 217 */ + { { 0xc9ef50e2c861baa5L,0xc0c21a5d9505ac3eL,0xaf6b9a338b7c063fL, + 0xc63703392f4779c1L }, + { 0x22df99c7638167c3L,0xfe6ffe76795db30cL,0x2b822d33a4854989L, + 0xfef031dd30563aa5L } }, + /* 43 << 217 */ + { { 0x16b09f82d57c667fL,0xc70312cecc0b76f1L,0xbf04a9e6c9118aecL, + 0x82fcb4193409d133L }, + { 0x1a8ab385ab45d44dL,0xfba07222617b83a3L,0xb05f50dd58e81b52L, + 0x1d8db55321ce5affL } }, + /* 44 << 217 */ + { { 0x3097b8d4e344a873L,0x7d8d116dfe36d53eL,0x6db22f587875e750L, + 0x2dc5e37343e144eaL }, + { 0xc05f32e6e799eb95L,0xe9e5f4df6899e6ecL,0xbdc3bd681fab23d5L, + 0xb72b8ab773af60e6L } }, + /* 45 << 217 */ + { { 0x8db27ae02cecc84aL,0x600016d87bdb871cL,0x42a44b13d7c46f58L, + 0xb8919727c3a77d39L }, + { 0xcfc6bbbddafd6088L,0x1a7401466bd20d39L,0x8c747abd98c41072L, + 0x4c91e765bdf68ea1L } }, + /* 46 << 217 */ + { { 0x7c95e5ca08819a78L,0xcf48b729c9587921L,0x091c7c5fdebbcc7dL, + 0x6f287404f0e05149L }, + { 0xf83b5ac226cd44ecL,0x88ae32a6cfea250eL,0x6ac5047a1d06ebc5L, + 0xc7e550b4d434f781L } }, + /* 47 << 217 */ + { { 0x61ab1cf25c727bd2L,0x2e4badb11cf915b0L,0x1b4dadecf69d3920L, + 0xe61b1ca6f14c1dfeL }, + { 0x90b479ccbd6bd51fL,0x8024e4018045ec30L,0xcab29ca325ef0e62L, + 0x4f2e941649e4ebc0L } }, + /* 48 << 217 */ + { { 0x45eb40ec0ccced58L,0x25cd4b9c0da44f98L,0x43e06458871812c6L, + 0x99f80d5516cef651L }, + { 0x571340c9ce6dc153L,0x138d5117d8665521L,0xacdb45bc4e07014dL, + 0x2f34bb3884b60b91L } }, + /* 49 << 217 */ + { { 0xf44a4fd22ae8921eL,0xb039288e892ba1e2L,0x9da50174b1c180b2L, + 0x6b70ab661693dc87L }, + { 0x7e9babc9e7057481L,0x4581ddef9c80dc41L,0x0c890da951294682L, + 0x0b5629d33f4736e5L } }, + /* 50 << 217 */ + { { 0x2340c79eb06f5b41L,0xa42e84ce4e243469L,0xf9a20135045a71a9L, + 0xefbfb415d27b6fb6L }, + { 0x25ebea239d33cd6fL,0x9caedb88aa6c0af8L,0x53dc7e9ad9ce6f96L, + 0x3897f9fd51e0b15aL } }, + /* 51 << 217 */ + { { 0xf51cb1f88e5d788eL,0x1aec7ba8e1d490eeL,0x265991e0cc58cb3cL, + 0x9f306e8c9fc3ad31L }, + { 0x5fed006e5040a0acL,0xca9d5043fb476f2eL,0xa19c06e8beea7a23L, + 0xd28658010edabb63L } }, + /* 52 << 217 */ + { { 0xdb92293f6967469aL,0x2894d8398d8a8ed8L,0x87c9e406bbc77122L, + 0x8671c6f12ea3a26aL }, + { 0xe42df8d6d7de9853L,0x2e3ce346b1f2bcc7L,0xda601dfc899d50cfL, + 0xbfc913defb1b598fL } }, + /* 53 << 217 */ + { { 0x81c4909fe61f7908L,0x192e304f9bbc7b29L,0xc3ed8738c104b338L, + 0xedbe9e47783f5d61L }, + { 0x0c06e9be2db30660L,0xda3e613fc0eb7d8eL,0xd8fa3e97322e096eL, + 0xfebd91e8d336e247L } }, + /* 54 << 217 */ + { { 0x8f13ccc4df655a49L,0xa9e00dfc5eb20210L,0x84631d0fc656b6eaL, + 0x93a058cdd8c0d947L }, + { 0x6846904a67bd3448L,0x4a3d4e1af394fd5cL,0xc102c1a5db225f52L, + 0xe3455bbafc4f5e9aL } }, + /* 55 << 217 */ + { { 0x6b36985b4b9ad1ceL,0xa98185365bb7f793L,0x6c25e1d048b1a416L, + 0x1381dd533c81bee7L }, + { 0xd2a30d617a4a7620L,0xc841292639b8944cL,0x3c1c6fbe7a97c33aL, + 0x941e541d938664e7L } }, + /* 56 << 217 */ + { { 0x417499e84a34f239L,0x15fdb83cb90402d5L,0xb75f46bf433aa832L, + 0xb61e15af63215db1L }, + { 0xaabe59d4a127f89aL,0x5d541e0c07e816daL,0xaaba0659a618b692L, + 0x5532773317266026L } }, + /* 57 << 217 */ + { { 0xaf53a0fc95f57552L,0x329476506cacb0c9L,0x253ff58dc821be01L, + 0xb0309531a06f1146L }, + { 0x59bbbdf505c2e54dL,0x158f27ad26e8dd22L,0xcc5b7ffb397e1e53L, + 0xae03f65b7fc1e50dL } }, + /* 58 << 217 */ + { { 0xa9784ebd9c95f0f9L,0x5ed9deb224640771L,0x31244af7035561c4L, + 0x87332f3a7ee857deL }, + { 0x09e16e9e2b9e0d88L,0x52d910f456a06049L,0x507ed477a9592f48L, + 0x85cb917b2365d678L } }, + /* 59 << 217 */ + { { 0xf8511c934c8998d1L,0x2186a3f1730ea58fL,0x50189626b2029db0L, + 0x9137a6d902ceb75aL }, + { 0x2fe17f37748bc82cL,0x87c2e93180469f8cL,0x850f71cdbf891aa2L, + 0x0ca1b89b75ec3d8dL } }, + /* 60 << 217 */ + { { 0x516c43aa5e1cd3cdL,0x893978089a887c28L,0x0059c699ddea1f9fL, + 0x7737d6fa8e6868f7L }, + { 0x6d93746a60f1524bL,0x36985e55ba052aa7L,0x41b1d322ed923ea5L, + 0x3429759f25852a11L } }, + /* 61 << 217 */ + { { 0xbeca6ec3092e9f41L,0x3a238c6662256bbdL,0xd82958ea70ad487dL, + 0x4ac8aaf965610d93L }, + { 0x3fa101b15e4ccab0L,0x9bf430f29de14bfbL,0xa10f5cc66531899dL, + 0x590005fbea8ce17dL } }, + /* 62 << 217 */ + { { 0xc437912f24544cb6L,0x9987b71ad79ac2e3L,0x13e3d9ddc058a212L, + 0x00075aacd2de9606L }, + { 0x80ab508b6cac8369L,0x87842be7f54f6c89L,0xa7ad663d6bc532a4L, + 0x67813de778a91bc8L } }, + /* 63 << 217 */ + { { 0x5dcb61cec3427239L,0x5f3c7cf0c56934d9L,0xc079e0fbe3191591L, + 0xe40896bdb01aada7L }, + { 0x8d4667910492d25fL,0x8aeb30c9e7408276L,0xe94374959287aaccL, + 0x23d4708d79fe03d4L } }, + /* 64 << 217 */ + { { 0x8cda9cf2d0c05199L,0x502fbc22fae78454L,0xc0bda9dff572a182L, + 0x5f9b71b86158b372L }, + { 0xe0f33a592b82dd07L,0x763027359523032eL,0x7fe1a721c4505a32L, + 0x7b6e3e82f796409fL } }, + /* 0 << 224 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 224 */ + { { 0xe3417bc035d0b34aL,0x440b386b8327c0a7L,0x8fb7262dac0362d1L, + 0x2c41114ce0cdf943L }, + { 0x2ba5cef1ad95a0b1L,0xc09b37a867d54362L,0x26d6cdd201e486c9L, + 0x20477abf42ff9297L } }, + /* 2 << 224 */ + { { 0xa004dcb3292a9287L,0xddc15cf677b092c7L,0x083a8464806c0605L, + 0x4a68df703db997b0L }, + { 0x9c134e4505bf7dd0L,0xa4e63d398ccf7f8cL,0xa6e6517f41b5f8afL, + 0xaa8b9342ad7bc1ccL } }, + /* 3 << 224 */ + { { 0x126f35b51e706ad9L,0xb99cebb4c3a9ebdfL,0xa75389afbf608d90L, + 0x76113c4fc6c89858L }, + { 0x80de8eb097e2b5aaL,0x7e1022cc63b91304L,0x3bdab6056ccc066cL, + 0x33cbb144b2edf900L } }, + /* 4 << 224 */ + { { 0xc41764717af715d2L,0xe2f7f594d0134a96L,0x2c1873efa41ec956L, + 0xe4e7b4f677821304L }, + { 0xe5c8ff9788d5374aL,0x2b915e6380823d5bL,0xea6bc755b2ee8fe2L, + 0x6657624ce7112651L } }, + /* 5 << 224 */ + { { 0x157af101dace5acaL,0xc4fdbcf211a6a267L,0xdaddf340c49c8609L, + 0x97e49f52e9604a65L }, + { 0x9be8e790937e2ad5L,0x846e2508326e17f1L,0x3f38007a0bbbc0dcL, + 0xcf03603fb11e16d6L } }, + /* 6 << 224 */ + { { 0xd6f800e07442f1d5L,0x475607d166e0e3abL,0x82807f16b7c64047L, + 0x8858e1e3a749883dL }, + { 0x5859120b8231ee10L,0x1b80e7eb638a1eceL,0xcb72525ac6aa73a4L, + 0xa7cdea3d844423acL } }, + /* 7 << 224 */ + { { 0x5ed0c007f8ae7c38L,0x6db07a5c3d740192L,0xbe5e9c2a5fe36db3L, + 0xd5b9d57a76e95046L }, + { 0x54ac32e78eba20f2L,0xef11ca8f71b9a352L,0x305e373eff98a658L, + 0xffe5a100823eb667L } }, + /* 8 << 224 */ + { { 0x57477b11e51732d2L,0xdfd6eb282538fc0eL,0x5c43b0cc3b39eec5L, + 0x6af12778cb36cc57L }, + { 0x70b0852d06c425aeL,0x6df92f8c5c221b9bL,0x6c8d4f9ece826d9cL, + 0xf59aba7bb49359c3L } }, + /* 9 << 224 */ + { { 0x5c8ed8d5da64309dL,0x61a6de5691b30704L,0xd6b52f6a2f9b5808L, + 0x0eee419498c958a7L }, + { 0xcddd9aab771e4caaL,0x83965dfd78bc21beL,0x02affce3b3b504f5L, + 0x30847a21561c8291L } }, + /* 10 << 224 */ + { { 0xd2eb2cf152bfda05L,0xe0e4c4e96197b98cL,0x1d35076cf8a1726fL, + 0x6c06085b2db11e3dL }, + { 0x15c0c4d74463ba14L,0x9d292f830030238cL,0x1311ee8b3727536dL, + 0xfeea86efbeaedc1eL } }, + /* 11 << 224 */ + { { 0xb9d18cd366131e2eL,0xf31d974f80fe2682L,0xb6e49e0fe4160289L, + 0x7c48ec0b08e92799L }, + { 0x818111d8d1989aa7L,0xb34fa0aaebf926f9L,0xdb5fe2f5a245474aL, + 0xf80a6ebb3c7ca756L } }, + /* 12 << 224 */ + { { 0xa7f96054afa05dd8L,0x26dfcf21fcaf119eL,0xe20ef2e30564bb59L, + 0xef4dca5061cb02b8L }, + { 0xcda7838a65d30672L,0x8b08d534fd657e86L,0x4c5b439546d595c8L, + 0x39b58725425cb836L } }, + /* 13 << 224 */ + { { 0x8ea610593de9abe3L,0x404348819cdc03beL,0x9b261245cfedce8cL, + 0x78c318b4cf5234a1L }, + { 0x510bcf16fde24c99L,0x2a77cb75a2c2ff5dL,0x9c895c2b27960fb4L, + 0xd30ce975b0eda42bL } }, + /* 14 << 224 */ + { { 0xfda853931a62cc26L,0x23c69b9650c0e052L,0xa227df15bfc633f3L, + 0x2ac788481bae7d48L }, + { 0x487878f9187d073dL,0x6c2be919967f807dL,0x765861d8336e6d8fL, + 0x88b8974cce528a43L } }, + /* 15 << 224 */ + { { 0x09521177ff57d051L,0x2ff38037fb6a1961L,0xfc0aba74a3d76ad4L, + 0x7c76480325a7ec17L }, + { 0x7532d75f48879bc8L,0xea7eacc058ce6bc1L,0xc82176b48e896c16L, + 0x9a30e0b22c750fedL } }, + /* 16 << 224 */ + { { 0xc37e2c2e421d3aa4L,0xf926407ce84fa840L,0x18abc03d1454e41cL, + 0x26605ecd3f7af644L }, + { 0x242341a6d6a5eabfL,0x1edb84f4216b668eL,0xd836edb804010102L, + 0x5b337ce7945e1d8cL } }, + /* 17 << 224 */ + { { 0xd2075c77c055dc14L,0x2a0ffa2581d89cdfL,0x8ce815ea6ffdcbafL, + 0xa3428878fb648867L }, + { 0x277699cf884655fbL,0xfa5b5bd6364d3e41L,0x01f680c6441e1cb7L, + 0x3fd61e66b70a7d67L } }, + /* 18 << 224 */ + { { 0x666ba2dccc78cf66L,0xb30181746fdbff77L,0x8d4dd0db168d4668L, + 0x259455d01dab3a2aL }, + { 0xf58564c5cde3acecL,0x7714192513adb276L,0x527d725d8a303f65L, + 0x55deb6c9e6f38f7bL } }, + /* 19 << 224 */ + { { 0xfd5bb657b1fa70fbL,0xfa07f50fd8073a00L,0xf72e3aa7bca02500L, + 0xf68f895d9975740dL }, + { 0x301120605cae2a6aL,0x01bd721802874842L,0x3d4238917ce47bd3L, + 0xa66663c1789544f6L } }, + /* 20 << 224 */ + { { 0x864d05d73272d838L,0xe22924f9fa6295c5L,0x8189593f6c2fda32L, + 0x330d7189b184b544L }, + { 0x79efa62cbde1f714L,0x35771c94e5cb1a63L,0x2f4826b8641c8332L, + 0x00a894fbc8cee854L } }, + /* 21 << 224 */ + { { 0xb4b9a39b36194d40L,0xe857a7c577612601L,0xf4209dd24ecf2f58L, + 0x82b9e66d5a033487L }, + { 0xc1e36934e4e8b9ddL,0xd2372c9da42377d7L,0x51dc94c70e3ae43bL, + 0x4c57761e04474f6fL } }, + /* 22 << 224 */ + { { 0xdcdacd0a1058a318L,0x369cf3f578053a9aL,0xc6c3de5031c68de2L, + 0x4653a5763c4b6d9fL }, + { 0x1688dd5aaa4e5c97L,0x5be80aa1b7ab3c74L,0x70cefe7cbc65c283L, + 0x57f95f1306867091L } }, + /* 23 << 224 */ + { { 0xa39114e24415503bL,0xc08ff7c64cbb17e9L,0x1eff674dd7dec966L, + 0x6d4690af53376f63L }, + { 0xff6fe32eea74237bL,0xc436d17ecd57508eL,0x15aa28e1edcc40feL, + 0x0d769c04581bbb44L } }, + /* 24 << 224 */ + { { 0xc240b6de34eaacdaL,0xd9e116e82ba0f1deL,0xcbe45ec779438e55L, + 0x91787c9d96f752d7L }, + { 0x897f532bf129ac2fL,0xd307b7c85a36e22cL,0x91940675749fb8f3L, + 0xd14f95d0157fdb28L } }, + /* 25 << 224 */ + { { 0xfe51d0296ae55043L,0x8931e98f44a87de1L,0xe57f1cc609e4fee2L, + 0x0d063b674e072d92L }, + { 0x70a998b9ed0e4316L,0xe74a736b306aca46L,0xecf0fbf24fda97c7L, + 0xa40f65cb3e178d93L } }, + /* 26 << 224 */ + { { 0x1625360416df4285L,0xb0c9babbd0c56ae2L,0x73032b19cfc5cfc3L, + 0xe497e5c309752056L }, + { 0x12096bb4164bda96L,0x1ee42419a0b74da1L,0x8fc36243403826baL, + 0x0c8f0069dc09e660L } }, + /* 27 << 224 */ + { { 0x8667e981c27253c9L,0x05a6aefb92b36a45L,0xa62c4b369cb7bb46L, + 0x8394f37511f7027bL }, + { 0x747bc79c5f109d0fL,0xcad88a765b8cc60aL,0x80c5a66b58f09e68L, + 0xe753d451f6127eacL } }, + /* 28 << 224 */ + { { 0xc44b74a15b0ec6f5L,0x47989fe45289b2b8L,0x745f848458d6fc73L, + 0xec362a6ff61c70abL }, + { 0x070c98a7b3a8ad41L,0x73a20fc07b63db51L,0xed2c2173f44c35f4L, + 0x8a56149d9acc9dcaL } }, + /* 29 << 224 */ + { { 0x98f178819ac6e0f4L,0x360fdeafa413b5edL,0x0625b8f4a300b0fdL, + 0xf1f4d76a5b3222d3L }, + { 0x9d6f5109587f76b8L,0x8b4ee08d2317fdb5L,0x88089bb78c68b095L, + 0x95570e9a5808d9b9L } }, + /* 30 << 224 */ + { { 0xa395c36f35d33ae7L,0x200ea12350bb5a94L,0x20c789bd0bafe84bL, + 0x243ef52d0919276aL }, + { 0x3934c577e23ae233L,0xb93807afa460d1ecL,0xb72a53b1f8fa76a4L, + 0xd8914cb0c3ca4491L } }, + /* 31 << 224 */ + { { 0x2e1284943fb42622L,0x3b2700ac500907d5L,0xf370fb091a95ec63L, + 0xf8f30be231b6dfbdL }, + { 0xf2b2f8d269e55f15L,0x1fead851cc1323e9L,0xfa366010d9e5eef6L, + 0x64d487b0e316107eL } }, + /* 32 << 224 */ + { { 0x4c076b86d23ddc82L,0x03fd344c7e0143f0L,0xa95362ff317af2c5L, + 0x0add3db7e18b7a4fL }, + { 0x9c673e3f8260e01bL,0xfbeb49e554a1cc91L,0x91351bf292f2e433L, + 0xc755e7ec851141ebL } }, + /* 33 << 224 */ + { { 0xc9a9513929607745L,0x0ca07420a26f2b28L,0xcb2790e74bc6f9ddL, + 0x345bbb58adcaffc0L }, + { 0xc65ea38cbe0f27a2L,0x67c24d7c641fcb56L,0x2c25f0a7a9e2c757L, + 0x93f5cdb016f16c49L } }, + /* 34 << 224 */ + { { 0x2ca5a9d7c5ee30a1L,0xd1593635b909b729L,0x804ce9f3dadeff48L, + 0xec464751b07c30c3L }, + { 0x89d65ff39e49af6aL,0xf2d6238a6f3d01bcL,0x1095561e0bced843L, + 0x51789e12c8a13fd8L } }, + /* 35 << 224 */ + { { 0xd633f929763231dfL,0x46df9f7de7cbddefL,0x01c889c0cb265da8L, + 0xfce1ad10af4336d2L }, + { 0x8d110df6fc6a0a7eL,0xdd431b986da425dcL,0xcdc4aeab1834aabeL, + 0x84deb1248439b7fcL } }, + /* 36 << 224 */ + { { 0x8796f1693c2a5998L,0x9b9247b47947190dL,0x55b9d9a511597014L, + 0x7e9dd70d7b1566eeL }, + { 0x94ad78f7cbcd5e64L,0x0359ac179bd4c032L,0x3b11baaf7cc222aeL, + 0xa6a6e284ba78e812L } }, + /* 37 << 224 */ + { { 0x8392053f24cea1a0L,0xc97bce4a33621491L,0x7eb1db3435399ee9L, + 0x473f78efece81ad1L }, + { 0x41d72fe0f63d3d0dL,0xe620b880afab62fcL,0x92096bc993158383L, + 0x41a213578f896f6cL } }, + /* 38 << 224 */ + { { 0x1b5ee2fac7dcfcabL,0x650acfde9546e007L,0xc081b749b1b02e07L, + 0xda9e41a0f9eca03dL }, + { 0x013ba727175a54abL,0xca0cd190ea5d8d10L,0x85ea52c095fd96a9L, + 0x2c591b9fbc5c3940L } }, + /* 39 << 224 */ + { { 0x6fb4d4e42bad4d5fL,0xfa4c3590fef0059bL,0x6a10218af5122294L, + 0x9a78a81aa85751d1L }, + { 0x04f20579a98e84e7L,0xfe1242c04997e5b5L,0xe77a273bca21e1e4L, + 0xfcc8b1ef9411939dL } }, + /* 40 << 224 */ + { { 0xe20ea30292d0487aL,0x1442dbec294b91feL,0x1f7a4afebb6b0e8fL, + 0x1700ef746889c318L }, + { 0xf5bbffc370f1fc62L,0x3b31d4b669c79ccaL,0xe8bc2aaba7f6340dL, + 0xb0b08ab4a725e10aL } }, + /* 41 << 224 */ + { { 0x44f05701ae340050L,0xba4b30161cf0c569L,0x5aa29f83fbe19a51L, + 0x1b9ed428b71d752eL }, + { 0x1666e54eeb4819f5L,0x616cdfed9e18b75bL,0x112ed5be3ee27b0bL, + 0xfbf2831944c7de4dL } }, + /* 42 << 224 */ + { { 0xd685ec85e0e60d84L,0x68037e301db7ee78L,0x5b65bdcd003c4d6eL, + 0x33e7363a93e29a6aL }, + { 0x995b3a6108d0756cL,0xd727f85c2faf134bL,0xfac6edf71d337823L, + 0x99b9aa500439b8b4L } }, + /* 43 << 224 */ + { { 0x722eb104e2b4e075L,0x49987295437c4926L,0xb1e4c0e446a9b82dL, + 0xd0cb319757a006f5L }, + { 0xf3de0f7dd7808c56L,0xb5c54d8f51f89772L,0x500a114aadbd31aaL, + 0x9afaaaa6295f6cabL } }, + /* 44 << 224 */ + { { 0x94705e2104cf667aL,0xfc2a811b9d3935d7L,0x560b02806d09267cL, + 0xf19ed119f780e53bL }, + { 0xf0227c09067b6269L,0x967b85335caef599L,0x155b924368efeebcL, + 0xcd6d34f5c497bae6L } }, + /* 45 << 224 */ + { { 0x1dd8d5d36cceb370L,0x2aeac579a78d7bf9L,0x5d65017d70b67a62L, + 0x70c8e44f17c53f67L }, + { 0xd1fc095086a34d09L,0xe0fca256e7134907L,0xe24fa29c80fdd315L, + 0x2c4acd03d87499adL } }, + /* 46 << 224 */ + { { 0xbaaf75173b5a9ba6L,0xb9cbe1f612e51a51L,0xd88edae35e154897L, + 0xe4309c3c77b66ca0L }, + { 0xf5555805f67f3746L,0x85fc37baa36401ffL,0xdf86e2cad9499a53L, + 0x6270b2a3ecbc955bL } }, + /* 47 << 224 */ + { { 0xafae64f5974ad33bL,0x04d85977fe7b2df1L,0x2a3db3ff4ab03f73L, + 0x0b87878a8702740aL }, + { 0x6d263f015a061732L,0xc25430cea32a1901L,0xf7ebab3ddb155018L, + 0x3a86f69363a9b78eL } }, + /* 48 << 224 */ + { { 0x349ae368da9f3804L,0x470f07fea164349cL,0xd52f4cc98562baa5L, + 0xc74a9e862b290df3L }, + { 0xd3a1aa3543471a24L,0x239446beb8194511L,0xbec2dd0081dcd44dL, + 0xca3d7f0fc42ac82dL } }, + /* 49 << 224 */ + { { 0x1f3db085fdaf4520L,0xbb6d3e804549daf2L,0xf5969d8a19ad5c42L, + 0x7052b13ddbfd1511L }, + { 0x11890d1b682b9060L,0xa71d3883ac34452cL,0xa438055b783805b4L, + 0x432412774725b23eL } }, + /* 50 << 224 */ + { { 0xf20cf96e4901bbedL,0x6419c710f432a2bbL,0x57a0fbb9dfa9cd7dL, + 0x589111e400daa249L }, + { 0x19809a337b60554eL,0xea5f8887ede283a4L,0x2d713802503bfd35L, + 0x151bb0af585d2a53L } }, + /* 51 << 224 */ + { { 0x40b08f7443b30ca8L,0xe10b5bbad9934583L,0xe8a546d6b51110adL, + 0x1dd50e6628e0b6c5L }, + { 0x292e9d54cff2b821L,0x3882555d47281760L,0x134838f83724d6e3L, + 0xf2c679e022ddcda1L } }, + /* 52 << 224 */ + { { 0x40ee88156d2a5768L,0x7f227bd21c1e7e2dL,0x487ba134d04ff443L, + 0x76e2ff3dc614e54bL }, + { 0x36b88d6fa3177ec7L,0xbf731d512328fff5L,0x758caea249ba158eL, + 0x5ab8ff4c02938188L } }, + /* 53 << 224 */ + { { 0x33e1605635edc56dL,0x5a69d3497e940d79L,0x6c4fd00103866dcbL, + 0x20a38f574893cdefL }, + { 0xfbf3e790fac3a15bL,0x6ed7ea2e7a4f8e6bL,0xa663eb4fbc3aca86L, + 0x22061ea5080d53f7L } }, + /* 54 << 224 */ + { { 0x2480dfe6f546783fL,0xd38bc6da5a0a641eL,0xfb093cd12ede8965L, + 0x89654db4acb455cfL }, + { 0x413cbf9a26e1adeeL,0x291f3764373294d4L,0x00797257648083feL, + 0x25f504d3208cc341L } }, + /* 55 << 224 */ + { { 0x635a8e5ec3a0ee43L,0x70aaebca679898ffL,0x9ee9f5475dc63d56L, + 0xce987966ffb34d00L }, + { 0xf9f86b195e26310aL,0x9e435484382a8ca8L,0x253bcb81c2352fe4L, + 0xa4eac8b04474b571L } }, + /* 56 << 224 */ + { { 0xc1b97512c1ad8cf8L,0x193b4e9e99e0b697L,0x939d271601e85df0L, + 0x4fb265b3cd44eafdL }, + { 0x321e7dcde51e1ae2L,0x8e3a8ca6e3d8b096L,0x8de46cb052604998L, + 0x91099ad839072aa7L } }, + /* 57 << 224 */ + { { 0x2617f91c93aa96b8L,0x0fc8716b7fca2e13L,0xa7106f5e95328723L, + 0xd1c9c40b262e6522L }, + { 0xb9bafe8642b7c094L,0x1873439d1543c021L,0xe1baa5de5cbefd5dL, + 0xa363fc5e521e8affL } }, + /* 58 << 224 */ + { { 0xefe6320df862eaacL,0x14419c6322c647dcL,0x0e06707c4e46d428L, + 0xcb6c834f4a178f8fL }, + { 0x0f993a45d30f917cL,0xd4c4b0499879afeeL,0xb6142a1e70500063L, + 0x7c9b41c3a5d9d605L } }, + /* 59 << 224 */ + { { 0xbc00fc2f2f8ba2c7L,0x0966eb2f7c67aa28L,0x13f7b5165a786972L, + 0x3bfb75578a2fbba0L }, + { 0x131c4f235a2b9620L,0xbff3ed276faf46beL,0x9b4473d17e172323L, + 0x421e8878339f6246L } }, + /* 60 << 224 */ + { { 0x0fa8587a25a41632L,0xc0814124a35b6c93L,0x2b18a9f559ebb8dbL, + 0x264e335776edb29cL }, + { 0xaf245ccdc87c51e2L,0x16b3015b501e6214L,0xbb31c5600a3882ceL, + 0x6961bb94fec11e04L } }, + /* 61 << 224 */ + { { 0x3b825b8deff7a3a0L,0xbec33738b1df7326L,0x68ad747c99604a1fL, + 0xd154c9349a3bd499L }, + { 0xac33506f1cc7a906L,0x73bb53926c560e8fL,0x6428fcbe263e3944L, + 0xc11828d51c387434L } }, + /* 62 << 224 */ + { { 0x3cd04be13e4b12ffL,0xc3aad9f92d88667cL,0xc52ddcf8248120cfL, + 0x985a892e2a389532L }, + { 0xfbb4b21b3bb85fa0L,0xf95375e08dfc6269L,0xfb4fb06c7ee2aceaL, + 0x6785426e309c4d1fL } }, + /* 63 << 224 */ + { { 0x659b17c8d8ceb147L,0x9b649eeeb70a5554L,0x6b7fa0b5ac6bc634L, + 0xd99fe2c71d6e732fL }, + { 0x30e6e7628d3abba2L,0x18fee6e7a797b799L,0x5c9d360dc696464dL, + 0xe3baeb4827bfde12L } }, + /* 64 << 224 */ + { { 0x2bf5db47f23206d5L,0x2f6d34201d260152L,0x17b876533f8ff89aL, + 0x5157c30c378fa458L }, + { 0x7517c5c52d4fb936L,0xef22f7ace6518cdcL,0xdeb483e6bf847a64L, + 0xf508455892e0fa89L } }, + /* 0 << 231 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 231 */ + { { 0xab9659d8df7304d4L,0xb71bcf1bff210e8eL,0xa9a2438bd73fbd60L, + 0x4595cd1f5d11b4deL }, + { 0x9c0d329a4835859dL,0x4a0f0d2d7dbb6e56L,0xc6038e5edf928a4eL, + 0xc94296218f5ad154L } }, + /* 2 << 231 */ + { { 0x91213462f23f2d92L,0x6cab71bd60b94078L,0x6bdd0a63176cde20L, + 0x54c9b20cee4d54bcL }, + { 0x3cd2d8aa9f2ac02fL,0x03f8e617206eedb0L,0xc7f68e1693086434L, + 0x831469c592dd3db9L } }, + /* 3 << 231 */ + { { 0x8521df248f981354L,0x587e23ec3588a259L,0xcbedf281d7a0992cL, + 0x06930a5538961407L }, + { 0x09320debbe5bbe21L,0xa7ffa5b52491817fL,0xe6c8b4d909065160L, + 0xac4f3992fff6d2a9L } }, + /* 4 << 231 */ + { { 0x7aa7a1583ae9c1bdL,0xe0af6d98e37ce240L,0xe54342d928ab38b4L, + 0xe8b750070a1c98caL }, + { 0xefce86afe02358f2L,0x31b8b856ea921228L,0x052a19120a1c67fcL, + 0xb4069ea4e3aead59L } }, + /* 5 << 231 */ + { { 0x3232d6e27fa03cb3L,0xdb938e5b0fdd7d88L,0x04c1d2cd2ccbfc5dL, + 0xd2f45c12af3a580fL }, + { 0x592620b57883e614L,0x5fd27e68be7c5f26L,0x139e45a91567e1e3L, + 0x2cc71d2d44d8aaafL } }, + /* 6 << 231 */ + { { 0x4a9090cde36d0757L,0xf722d7b1d9a29382L,0xfb7fb04c04b48ddfL, + 0x628ad2a7ebe16f43L }, + { 0xcd3fbfb520226040L,0x6c34ecb15104b6c4L,0x30c0754ec903c188L, + 0xec336b082d23cab0L } }, + /* 7 << 231 */ + { { 0x473d62a21e206ee5L,0xf1e274808c49a633L,0x87ab956ce9f6b2c3L, + 0x61830b4862b606eaL }, + { 0x67cd6846e78e815fL,0xfe40139f4c02082aL,0x52bbbfcb952ec365L, + 0x74c116426b9836abL } }, + /* 8 << 231 */ + { { 0x9f51439e558df019L,0x230da4baac712b27L,0x518919e355185a24L, + 0x4dcefcdd84b78f50L }, + { 0xa7d90fb2a47d4c5aL,0x55ac9abfb30e009eL,0xfd2fc35974eed273L, + 0xb72d824cdbea8fafL } }, + /* 9 << 231 */ + { { 0xce721a744513e2caL,0x0b41861238240b2cL,0x05199968d5baa450L, + 0xeb1757ed2b0e8c25L }, + { 0x6ebc3e283dfac6d5L,0xb2431e2e48a237f5L,0x2acb5e2352f61499L, + 0x5558a2a7e06c936bL } }, + /* 10 << 231 */ + { { 0xd213f923cbb13d1bL,0x98799f425bfb9bfeL,0x1ae8ddc9701144a9L, + 0x0b8b3bb64c5595eeL }, + { 0x0ea9ef2e3ecebb21L,0x17cb6c4b3671f9a7L,0x47ef464f726f1d1fL, + 0x171b94846943a276L } }, + /* 11 << 231 */ + { { 0x51a4ae2d7ef0329cL,0x0850922291c4402aL,0x64a61d35afd45bbcL, + 0x38f096fe3035a851L }, + { 0xc7468b74a1dec027L,0xe8cf10e74fc7dcbaL,0xea35ff40f4a06353L, + 0x0b4c0dfa8b77dd66L } }, + /* 12 << 231 */ + { { 0x779b8552de7e5c19L,0xfab28609c1c0256cL,0x64f58eeeabd4743dL, + 0x4e8ef8387b6cc93bL }, + { 0xee650d264cb1bf3dL,0x4c1f9d0973dedf61L,0xaef7c9d7bfb70cedL, + 0x1ec0507e1641de1eL } }, + /* 13 << 231 */ + { { 0xcd7e5cc7cde45079L,0xde173c9a516ac9e4L,0x517a8494c170315cL, + 0x438fd90591d8e8fbL }, + { 0x5145c506c7d9630bL,0x6457a87bf47d4d75L,0xd31646bf0d9a80e8L, + 0x453add2bcef3aabeL } }, + /* 14 << 231 */ + { { 0xc9941109a607419dL,0xfaa71e62bb6bca80L,0x34158c1307c431f3L, + 0x594abebc992bc47aL }, + { 0x6dfea691eb78399fL,0x48aafb353f42cba4L,0xedcd65af077c04f0L, + 0x1a29a366e884491aL } }, + /* 15 << 231 */ + { { 0x023a40e51c21f2bfL,0xf99a513ca5057aeeL,0xa3fe7e25bcab072eL, + 0x8568d2e140e32bcfL }, + { 0x904594ebd3f69d9fL,0x181a973307affab1L,0xe4d68d76b6e330f4L, + 0x87a6dafbc75a7fc1L } }, + /* 16 << 231 */ + { { 0x549db2b5ef7d9289L,0x2480d4a8197f015aL,0x61d5590bc40493b6L, + 0x3a55b52e6f780331L }, + { 0x40eb8115309eadb0L,0xdea7de5a92e5c625L,0x64d631f0cc6a3d5aL, + 0x9d5e9d7c93e8dd61L } }, + /* 17 << 231 */ + { { 0xf297bef5206d3ffcL,0x23d5e0337d808bd4L,0x4a4f6912d24cf5baL, + 0xe4d8163b09cdaa8aL }, + { 0x0e0de9efd3082e8eL,0x4fe1246c0192f360L,0x1f9001504b8eee0aL, + 0x5219da81f1da391bL } }, + /* 18 << 231 */ + { { 0x7bf6a5c1f7ea25aaL,0xd165e6bffbb07d5fL,0xe353936189e78671L, + 0xa3fcac892bac4219L }, + { 0xdfab6fd4f0baa8abL,0x5a4adac1e2c1c2e5L,0x6cd75e3140d85849L, + 0xce263fea19b39181L } }, + /* 19 << 231 */ + { { 0xcb6803d307032c72L,0x7f40d5ce790968c8L,0xa6de86bddce978f0L, + 0x25547c4f368f751cL }, + { 0xb1e685fd65fb2a9eL,0xce69336f1eb9179cL,0xb15d1c2712504442L, + 0xb7df465cb911a06bL } }, + /* 20 << 231 */ + { { 0xb8d804a3315980cdL,0x693bc492fa3bebf7L,0x3578aeee2253c504L, + 0x158de498cd2474a2L }, + { 0x1331f5c7cfda8368L,0xd2d7bbb378d7177eL,0xdf61133af3c1e46eL, + 0x5836ce7dd30e7be8L } }, + /* 21 << 231 */ + { { 0x83084f1994f834cbL,0xd35653d4429ed782L,0xa542f16f59e58243L, + 0xc2b52f650470a22dL }, + { 0xe3b6221b18f23d96L,0xcb05abac3f5252b4L,0xca00938b87d61402L, + 0x2f186cdd411933e4L } }, + /* 22 << 231 */ + { { 0xe042ece59a29a5c5L,0xb19b3c073b6c8402L,0xc97667c719d92684L, + 0xb5624622ebc66372L }, + { 0x0cb96e653c04fa02L,0x83a7176c8eaa39aaL,0x2033561deaa1633fL, + 0x45a9d0864533df73L } }, + /* 23 << 231 */ + { { 0xe0542c1d3dc090bcL,0x82c996efaa59c167L,0xe3f735e80ee7fc4dL, + 0x7b1793937c35db79L }, + { 0xb6419e25f8c5dbfdL,0x4d9d7a1e1f327b04L,0x979f6f9b298dfca8L, + 0xc7c5dff18de9366aL } }, + /* 24 << 231 */ + { { 0x1b7a588d04c82bddL,0x68005534f8319dfdL,0xde8a55b5d8eb9580L, + 0x5ea886da8d5bca81L }, + { 0xe8530a01252a0b4dL,0x1bffb4fe35eaa0a1L,0x2ad828b1d8e99563L, + 0x7de96ef595f9cd87L } }, + /* 25 << 231 */ + { { 0x4abb2d0cd77d970cL,0x03cfb933d33ef9cbL,0xb0547c018b211fe9L, + 0x2fe64809a56ed1c6L }, + { 0xcb7d5624c2ac98ccL,0x2a1372c01a393e33L,0xc8d1ec1c29660521L, + 0xf3d31b04b37ac3e9L } }, + /* 26 << 231 */ + { { 0xa29ae9df5ece6e7cL,0x0603ac8f0facfb55L,0xcfe85b7adda233a5L, + 0xe618919fbd75f0b8L }, + { 0xf555a3d299bf1603L,0x1f43afc9f184255aL,0xdcdaf341319a3e02L, + 0xd3b117ef03903a39L } }, + /* 27 << 231 */ + { { 0xe095da1365d1d131L,0x86f16367c37ad03eL,0x5f37389e462cd8ddL, + 0xc103fa04d67a60e6L }, + { 0x57c34344f4b478f0L,0xce91edd8e117c98dL,0x001777b0231fc12eL, + 0x11ae47f2b207bccbL } }, + /* 28 << 231 */ + { { 0xd983cf8d20f8a242L,0x7aff5b1df22e1ad8L,0x68fd11d07fc4feb3L, + 0x5d53ae90b0f1c3e1L }, + { 0x50fb7905ec041803L,0x85e3c97714404888L,0x0e67faedac628d8fL, + 0x2e8651506668532cL } }, + /* 29 << 231 */ + { { 0x15acaaa46a67a6b0L,0xf4cdee25b25cec41L,0x49ee565ae4c6701eL, + 0x2a04ca66fc7d63d8L }, + { 0xeb105018ef0543fbL,0xf709a4f5d1b0d81dL,0x5b906ee62915d333L, + 0xf4a8741296f1f0abL } }, + /* 30 << 231 */ + { { 0xb6b82fa74d82f4c2L,0x90725a606804efb3L,0xbc82ec46adc3425eL, + 0xb7b805812787843eL }, + { 0xdf46d91cdd1fc74cL,0xdc1c62cbe783a6c4L,0x59d1b9f31a04cbbaL, + 0xd87f6f7295e40764L } }, + /* 31 << 231 */ + { { 0x02b4cfc1317f4a76L,0x8d2703eb91036bceL,0x98206cc6a5e72a56L, + 0x57be9ed1cf53fb0fL }, + { 0x09374571ef0b17acL,0x74b2655ed9181b38L,0xc8f80ea889935d0eL, + 0xc0d9e94291529936L } }, + /* 32 << 231 */ + { { 0x196860411e84e0e5L,0xa5db84d3aea34c93L,0xf9d5bb197073a732L, + 0xb8d2fe566bcfd7c0L }, + { 0x45775f36f3eb82faL,0x8cb20cccfdff8b58L,0x1659b65f8374c110L, + 0xb8b4a422330c789aL } }, + /* 33 << 231 */ + { { 0x75e3c3ea6fe8208bL,0xbd74b9e4286e78feL,0x0be2e81bd7d93a1aL, + 0x7ed06e27dd0a5aaeL }, + { 0x721f5a586be8b800L,0x428299d1d846db28L,0x95cb8e6b5be88ed3L, + 0xc3186b231c034e11L } }, + /* 34 << 231 */ + { { 0xa6312c9e8977d99bL,0xbe94433183f531e7L,0x8232c0c218d3b1d4L, + 0x617aae8be1247b73L }, + { 0x40153fc4282aec3bL,0xc6063d2ff7b8f823L,0x68f10e583304f94cL, + 0x31efae74ee676346L } }, + /* 35 << 231 */ + { { 0xbadb6c6d40a9b97cL,0x14702c634f666256L,0xdeb954f15184b2e3L, + 0x5184a52694b6ca40L }, + { 0xfff05337003c32eaL,0x5aa374dd205974c7L,0x9a7638544b0dd71aL, + 0x459cd27fdeb947ecL } }, + /* 36 << 231 */ + { { 0xa6e28161459c2b92L,0x2f020fa875ee8ef5L,0xb132ec2d30b06310L, + 0xc3e15899bc6a4530L }, + { 0xdc5f53feaa3f451aL,0x3a3c7f23c2d9acacL,0x2ec2f8926b27e58bL, + 0x68466ee7d742799fL } }, + /* 37 << 231 */ + { { 0x98324dd41fa26613L,0xa2dc6dabbdc29d63L,0xf9675faad712d657L, + 0x813994be21fd8d15L }, + { 0x5ccbb722fd4f7553L,0x5135ff8bf3a36b20L,0x44be28af69559df5L, + 0x40b65bed9d41bf30L } }, + /* 38 << 231 */ + { { 0xd98bf2a43734e520L,0x5e3abbe3209bdcbaL,0x77c76553bc945b35L, + 0x5331c093c6ef14aaL }, + { 0x518ffe2976b60c80L,0x2285593b7ace16f8L,0xab1f64ccbe2b9784L, + 0xe8f2c0d9ab2421b6L } }, + /* 39 << 231 */ + { { 0x617d7174c1df065cL,0xafeeb5ab5f6578faL,0x16ff1329263b54a8L, + 0x45c55808c990dce3L }, + { 0x42eab6c0ecc8c177L,0x799ea9b55982ecaaL,0xf65da244b607ef8eL, + 0x8ab226ce32a3fc2cL } }, + /* 40 << 231 */ + { { 0x745741e57ea973dcL,0x5c00ca7020888f2eL,0x7cdce3cf45fd9cf1L, + 0x8a741ef15507f872L }, + { 0x47c51c2f196b4cecL,0x70d08e43c97ea618L,0x930da15c15b18a2bL, + 0x33b6c6782f610514L } }, + /* 41 << 231 */ + { { 0xc662e4f807ac9794L,0x1eccf050ba06cb79L,0x1ff08623e7d954e5L, + 0x6ef2c5fb24cf71c3L }, + { 0xb2c063d267978453L,0xa0cf37961d654af8L,0x7cb242ea7ebdaa37L, + 0x206e0b10b86747e0L } }, + /* 42 << 231 */ + { { 0x481dae5fd5ecfefcL,0x07084fd8c2bff8fcL,0x8040a01aea324596L, + 0x4c646980d4de4036L }, + { 0x9eb8ab4ed65abfc3L,0xe01cb91f13541ec7L,0x8f029adbfd695012L, + 0x9ae284833c7569ecL } }, + /* 43 << 231 */ + { { 0xa5614c9ea66d80a1L,0x680a3e4475f5f911L,0x0c07b14dceba4fc1L, + 0x891c285ba13071c1L }, + { 0xcac67ceb799ece3cL,0x29b910a941e07e27L,0x66bdb409f2e43123L, + 0x06f8b1377ac9ecbeL } }, + /* 44 << 231 */ + { { 0x5981fafd38547090L,0x19ab8b9f85e3415dL,0xfc28c194c7e31b27L, + 0x843be0aa6fbcbb42L }, + { 0xf3b1ed43a6db836cL,0x2a1330e401a45c05L,0x4f19f3c595c1a377L, + 0xa85f39d044b5ee33L } }, + /* 45 << 231 */ + { { 0x3da18e6d4ae52834L,0x5a403b397423dcb0L,0xbb555e0af2374aefL, + 0x2ad599c41e8ca111L }, + { 0x1b3a2fb9014b3bf8L,0x73092684f66d5007L,0x079f1426c4340102L, + 0x1827cf818fddf4deL } }, + /* 46 << 231 */ + { { 0xc83605f6f10ff927L,0xd387145123739fc6L,0x6d163450cac1c2ccL, + 0x6b521296a2ec1ac5L }, + { 0x0606c4f96e3cb4a5L,0xe47d3f41778abff7L,0x425a8d5ebe8e3a45L, + 0x53ea9e97a6102160L } }, + /* 47 << 231 */ + { { 0x477a106e39cbb688L,0x532401d2f3386d32L,0x8e564f64b1b9b421L, + 0xca9b838881dad33fL }, + { 0xb1422b4e2093913eL,0x533d2f9269bc8112L,0x3fa017beebe7b2c7L, + 0xb2767c4acaf197c6L } }, + /* 48 << 231 */ + { { 0xc925ff87aedbae9fL,0x7daf0eb936880a54L,0x9284ddf59c4d0e71L, + 0x1581cf93316f8cf5L }, + { 0x3eeca8873ac1f452L,0xb417fce9fb6aeffeL,0xa5918046eefb8dc3L, + 0x73d318ac02209400L } }, + /* 49 << 231 */ + { { 0xe800400f728693e5L,0xe87d814b339927edL,0x93e94d3b57ea9910L, + 0xff8a35b62245fb69L }, + { 0x043853d77f200d34L,0x470f1e680f653ce1L,0x81ac05bd59a06379L, + 0xa14052c203930c29L } }, + /* 50 << 231 */ + { { 0x6b72fab526bc2797L,0x13670d1699f16771L,0x001700521e3e48d1L, + 0x978fe401b7adf678L }, + { 0x55ecfb92d41c5dd4L,0x5ff8e247c7b27da5L,0xe7518272013fb606L, + 0x5768d7e52f547a3cL } }, + /* 51 << 231 */ + { { 0xbb24eaa360017a5fL,0x6b18e6e49c64ce9bL,0xc225c655103dde07L, + 0xfc3672ae7592f7eaL }, + { 0x9606ad77d06283a1L,0x542fc650e4d59d99L,0xabb57c492a40e7c2L, + 0xac948f13a8db9f55L } }, + /* 52 << 231 */ + { { 0x6d4c9682b04465c3L,0xe3d062fa6468bd15L,0xa51729ac5f318d7eL, + 0x1fc87df69eb6fc95L }, + { 0x63d146a80591f652L,0xa861b8f7589621aaL,0x59f5f15ace31348cL, + 0x8f663391440da6daL } }, + /* 53 << 231 */ + { { 0xcfa778acb591ffa3L,0x027ca9c54cdfebceL,0xbe8e05a5444ea6b3L, + 0x8aab4e69a78d8254L }, + { 0x2437f04fb474d6b8L,0x6597ffd4045b3855L,0xbb0aea4eca47ecaaL, + 0x568aae8385c7ebfcL } }, + /* 54 << 231 */ + { { 0x0e966e64c73b2383L,0x49eb3447d17d8762L,0xde1078218da05dabL, + 0x443d8baa016b7236L }, + { 0x163b63a5ea7610d6L,0xe47e4185ce1ca979L,0xae648b6580baa132L, + 0xebf53de20e0d5b64L } }, + /* 55 << 231 */ + { { 0x8d3bfcb4d3c8c1caL,0x0d914ef35d04b309L,0x55ef64153de7d395L, + 0xbde1666f26b850e8L }, + { 0xdbe1ca6ed449ab19L,0x8902b322e89a2672L,0xb1674b7edacb7a53L, + 0x8e9faf6ef52523ffL } }, + /* 56 << 231 */ + { { 0x6ba535da9a85788bL,0xd21f03aebd0626d4L,0x099f8c47e873dc64L, + 0xcda8564d018ec97eL }, + { 0x3e8d7a5cde92c68cL,0x78e035a173323cc4L,0x3ef26275f880ff7cL, + 0xa4ee3dff273eedaaL } }, + /* 57 << 231 */ + { { 0x58823507af4e18f8L,0x967ec9b50672f328L,0x9ded19d9559d3186L, + 0x5e2ab3de6cdce39cL }, + { 0xabad6e4d11c226dfL,0xf9783f4387723014L,0x9a49a0cf1a885719L, + 0xfc0c1a5a90da9dbfL } }, + /* 58 << 231 */ + { { 0x8bbaec49571d92acL,0x569e85fe4692517fL,0x8333b014a14ea4afL, + 0x32f2a62f12e5c5adL }, + { 0x98c2ce3a06d89b85L,0xb90741aa2ff77a08L,0x2530defc01f795a2L, + 0xd6e5ba0b84b3c199L } }, + /* 59 << 231 */ + { { 0x7d8e845112e4c936L,0xae419f7dbd0be17bL,0xa583fc8c22262bc9L, + 0x6b842ac791bfe2bdL }, + { 0x33cef4e9440d6827L,0x5f69f4deef81fb14L,0xf16cf6f6234fbb92L, + 0x76ae3fc3d9e7e158L } }, + /* 60 << 231 */ + { { 0x4e89f6c2e9740b33L,0x677bc85d4962d6a1L,0x6c6d8a7f68d10d15L, + 0x5f9a72240257b1cdL }, + { 0x7096b9164ad85961L,0x5f8c47f7e657ab4aL,0xde57d7d0f7461d7eL, + 0x7eb6094d80ce5ee2L } }, + /* 61 << 231 */ + { { 0x0b1e1dfd34190547L,0x8a394f43f05dd150L,0x0a9eb24d97df44e6L, + 0x78ca06bf87675719L }, + { 0x6f0b34626ffeec22L,0x9d91bcea36cdd8fbL,0xac83363ca105be47L, + 0x81ba76c1069710e3L } }, + /* 62 << 231 */ + { { 0x3d1b24cb28c682c6L,0x27f252288612575bL,0xb587c779e8e66e98L, + 0x7b0c03e9405eb1feL }, + { 0xfdf0d03015b548e7L,0xa8be76e038b36af7L,0x4cdab04a4f310c40L, + 0x6287223ef47ecaecL } }, + /* 63 << 231 */ + { { 0x678e60558b399320L,0x61fe3fa6c01e4646L,0xc482866b03261a5eL, + 0xdfcf45b85c2f244aL }, + { 0x8fab9a512f684b43L,0xf796c654c7220a66L,0x1d90707ef5afa58fL, + 0x2c421d974fdbe0deL } }, + /* 64 << 231 */ + { { 0xc4f4cda3af2ebc2fL,0xa0af843dcb4efe24L,0x53b857c19ccd10b1L, + 0xddc9d1eb914d3e04L }, + { 0x7bdec8bb62771debL,0x829277aa91c5aa81L,0x7af18dd6832391aeL, + 0x1740f316c71a84caL } }, + /* 0 << 238 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 238 */ + { { 0x8928e99aeeaf8c49L,0xee7aa73d6e24d728L,0x4c5007c2e72b156cL, + 0x5fcf57c5ed408a1dL }, + { 0x9f719e39b6057604L,0x7d343c01c2868bbfL,0x2cca254b7e103e2dL, + 0xe6eb38a9f131bea2L } }, + /* 2 << 238 */ + { { 0xb33e624f8be762b4L,0x2a9ee4d1058e3413L,0x968e636967d805faL, + 0x9848949b7db8bfd7L }, + { 0x5308d7e5d23a8417L,0x892f3b1df3e29da5L,0xc95c139e3dee471fL, + 0x8631594dd757e089L } }, + /* 3 << 238 */ + { { 0xe0c82a3cde918dccL,0x2e7b599426fdcf4bL,0x82c5024932cb1b2dL, + 0xea613a9d7657ae07L }, + { 0xc2eb5f6cf1fdc9f7L,0xb6eae8b8879fe682L,0x253dfee0591cbc7fL, + 0x000da7133e1290e6L } }, + /* 4 << 238 */ + { { 0x1083e2ea1f095615L,0x0a28ad7714e68c33L,0x6bfc02523d8818beL, + 0xb585113af35850cdL }, + { 0x7d935f0b30df8aa1L,0xaddda07c4ab7e3acL,0x92c34299552f00cbL, + 0xc33ed1de2909df6cL } }, + /* 5 << 238 */ + { { 0x22c2195d80e87766L,0x9e99e6d89ddf4ac0L,0x09642e4e65e74934L, + 0x2610ffa2ff1ff241L }, + { 0x4d1d47d4751c8159L,0x697b4985af3a9363L,0x0318ca4687477c33L, + 0xa90cb5659441eff3L } }, + /* 6 << 238 */ + { { 0x58bb384836f024cbL,0x85be1f7736016168L,0x6c59587cdc7e07f1L, + 0x191be071af1d8f02L }, + { 0xbf169fa5cca5e55cL,0x3864ba3cf7d04eacL,0x915e367f8d7d05dbL, + 0xb48a876da6549e5dL } }, + /* 7 << 238 */ + { { 0xef89c656580e40a2L,0xf194ed8c728068bcL,0x74528045a47990c9L, + 0xf53fc7d75e1a4649L }, + { 0xbec5ae9b78593e7dL,0x2cac4ee341db65d7L,0xa8c1eb2404a3d39bL, + 0x53b7d63403f8f3efL } }, + /* 8 << 238 */ + { { 0x2dc40d483e07113cL,0x6e4a5d397d8b63aeL,0x5582a94b79684c2bL, + 0x932b33d4622da26cL }, + { 0xf534f6510dbbf08dL,0x211d07c964c23a52L,0x0eeece0fee5bdc9bL, + 0xdf178168f7015558L } }, + /* 9 << 238 */ + { { 0xd42946350a712229L,0x93cbe44809273f8cL,0x00b095ef8f13bc83L, + 0xbb7419728798978cL }, + { 0x9d7309a256dbe6e7L,0xe578ec565a5d39ecL,0x3961151b851f9a31L, + 0x2da7715de5709eb4L } }, + /* 10 << 238 */ + { { 0x867f301753dfabf0L,0x728d2078b8e39259L,0x5c75a0cd815d9958L, + 0xf84867a616603be1L }, + { 0xc865b13d70e35b1cL,0x0241446819b03e2cL,0xe46041daac1f3121L, + 0x7c9017ad6f028a7cL } }, + /* 11 << 238 */ + { { 0xabc96de90a482873L,0x4265d6b1b77e54d4L,0x68c38e79a57d88e7L, + 0xd461d7669ce82de3L }, + { 0x817a9ec564a7e489L,0xcc5675cda0def5f2L,0x9a00e785985d494eL, + 0xc626833f1b03514aL } }, + /* 12 << 238 */ + { { 0xabe7905a83cdd60eL,0x50602fb5a1170184L,0x689886cdb023642aL, + 0xd568d090a6e1fb00L }, + { 0x5b1922c70259217fL,0x93831cd9c43141e4L,0xdfca35870c95f86eL, + 0xdec2057a568ae828L } }, + /* 13 << 238 */ + { { 0xc44ea599f98a759aL,0x55a0a7a2f7c23c1dL,0xd5ffb6e694c4f687L, + 0x3563cce212848478L }, + { 0x812b3517e7b1fbe1L,0x8a7dc9794f7338e0L,0x211ecee952d048dbL, + 0x2eea4056c86ea3b8L } }, + /* 14 << 238 */ + { { 0xd8cb68a7ba772b34L,0xe16ed3415f4e2541L,0x9b32f6a60fec14dbL, + 0xeee376f7391698beL }, + { 0xe9a7aa1783674c02L,0x65832f975843022aL,0x29f3a8da5ba4990fL, + 0x79a59c3afb8e3216L } }, + /* 15 << 238 */ + { { 0x9cdc4d2ebd19bb16L,0xc6c7cfd0b3262d86L,0xd4ce14d0969c0b47L, + 0x1fa352b713e56128L }, + { 0x383d55b8973db6d3L,0x71836850e8e5b7bfL,0xc7714596e6bb571fL, + 0x259df31f2d5b2dd2L } }, + /* 16 << 238 */ + { { 0x568f8925913cc16dL,0x18bc5b6de1a26f5aL,0xdfa413bef5f499aeL, + 0xf8835decc3f0ae84L }, + { 0xb6e60bd865a40ab0L,0x65596439194b377eL,0xbcd8562592084a69L, + 0x5ce433b94f23ede0L } }, + /* 17 << 238 */ + { { 0xe8e8f04f6ad65143L,0x11511827d6e14af6L,0x3d390a108295c0c7L, + 0x71e29ee4621eba16L }, + { 0xa588fc0963717b46L,0x02be02fee06ad4a2L,0x931558c604c22b22L, + 0xbb4d4bd612f3c849L } }, + /* 18 << 238 */ + { { 0x54a4f49620efd662L,0x92ba6d20c5952d14L,0x2db8ea1ecc9784c2L, + 0x81cc10ca4b353644L }, + { 0x40b570ad4b4d7f6cL,0x5c9f1d9684a1dcd2L,0x01379f813147e797L, + 0xe5c6097b2bd499f5L } }, + /* 19 << 238 */ + { { 0x40dcafa6328e5e20L,0xf7b5244a54815550L,0xb9a4f11847bfc978L, + 0x0ea0e79fd25825b1L }, + { 0xa50f96eb646c7ecfL,0xeb811493446dea9dL,0x2af04677dfabcf69L, + 0xbe3a068fc713f6e8L } }, + /* 20 << 238 */ + { { 0x860d523d42e06189L,0xbf0779414e3aff13L,0x0b616dcac1b20650L, + 0xe66dd6d12131300dL }, + { 0xd4a0fd67ff99abdeL,0xc9903550c7aac50dL,0x022ecf8b7c46b2d7L, + 0x3333b1e83abf92afL } }, + /* 21 << 238 */ + { { 0x11cc113c6c491c14L,0x0597668880dd3f88L,0xf5b4d9e729d932edL, + 0xe982aad8a2c38b6dL }, + { 0x6f9253478be0dcf0L,0x700080ae65ca53f2L,0xd8131156443ca77fL, + 0xe92d6942ec51f984L } }, + /* 22 << 238 */ + { { 0xd2a08af885dfe9aeL,0xd825d9a54d2a86caL,0x2c53988d39dff020L, + 0xf38b135a430cdc40L }, + { 0x0c918ae062a7150bL,0xf31fd8de0c340e9bL,0xafa0e7ae4dbbf02eL, + 0x5847fb2a5eba6239L } }, + /* 23 << 238 */ + { { 0x6b1647dcdccbac8bL,0xb642aa7806f485c8L,0x873f37657038ecdfL, + 0x2ce5e865fa49d3feL }, + { 0xea223788c98c4400L,0x8104a8cdf1fa5279L,0xbcf7cc7a06becfd7L, + 0x49424316c8f974aeL } }, + /* 24 << 238 */ + { { 0xc0da65e784d6365dL,0xbcb7443f8f759fb8L,0x35c712b17ae81930L, + 0x80428dff4c6e08abL }, + { 0xf19dafefa4faf843L,0xced8538dffa9855fL,0x20ac409cbe3ac7ceL, + 0x358c1fb6882da71eL } }, + /* 25 << 238 */ + { { 0xafa9c0e5fd349961L,0x2b2cfa518421c2fcL,0x2a80db17f3a28d38L, + 0xa8aba5395d138e7eL }, + { 0x52012d1d6e96eb8dL,0x65d8dea0cbaf9622L,0x57735447b264f56cL, + 0xbeebef3f1b6c8da2L } }, + /* 26 << 238 */ + { { 0xfc346d98ce785254L,0xd50e8d72bb64a161L,0xc03567c749794addL, + 0x15a76065752c7ef6L }, + { 0x59f3a222961f23d6L,0x378e443873ecc0b0L,0xc74be4345a82fde4L, + 0xae509af2d8b9cf34L } }, + /* 27 << 238 */ + { { 0x4a61ee46577f44a1L,0xe09b748cb611deebL,0xc0481b2cf5f7b884L, + 0x3562667861acfa6bL }, + { 0x37f4c518bf8d21e6L,0x22d96531b205a76dL,0x37fb85e1954073c0L, + 0xbceafe4f65b3a567L } }, + /* 28 << 238 */ + { { 0xefecdef7be42a582L,0xd3fc608065046be6L,0xc9af13c809e8dba9L, + 0x1e6c9847641491ffL }, + { 0x3b574925d30c31f7L,0xb7eb72baac2a2122L,0x776a0dacef0859e7L, + 0x06fec31421900942L } }, + /* 29 << 238 */ + { { 0x2464bc10f8c22049L,0x9bfbcce7875ebf69L,0xd7a88e2a4336326bL, + 0xda05261c5bc2acfaL }, + { 0xc29f5bdceba7efc8L,0x471237ca25dbbf2eL,0xa72773f22975f127L, + 0xdc744e8e04d0b326L } }, + /* 30 << 238 */ + { { 0x38a7ed16a56edb73L,0x64357e372c007e70L,0xa167d15b5080b400L, + 0x07b4116423de4be1L }, + { 0xb2d91e3274c89883L,0x3c1628212882e7edL,0xad6b36ba7503e482L, + 0x48434e8e0ea34331L } }, + /* 31 << 238 */ + { { 0x79f4f24f2c7ae0b9L,0xc46fbf811939b44aL,0x76fefae856595eb1L, + 0x417b66abcd5f29c7L }, + { 0x5f2332b2c5ceec20L,0xd69661ffe1a1cae2L,0x5ede7e529b0286e6L, + 0x9d062529e276b993L } }, + /* 32 << 238 */ + { { 0x324794b07e50122bL,0xdd744f8b4af07ca5L,0x30a12f08d63fc97bL, + 0x39650f1a76626d9dL }, + { 0x101b47f71fa38477L,0x3d815f19d4dc124fL,0x1569ae95b26eb58aL, + 0xc3cde18895fb1887L } }, + /* 33 << 238 */ + { { 0x54e9f37bf9539a48L,0xb0100e067408c1a5L,0x821d9811ea580cbbL, + 0x8af52d3586e50c56L }, + { 0xdfbd9d47dbbf698bL,0x2961a1ea03dc1c73L,0x203d38f8e76a5df8L, + 0x08a53a686def707aL } }, + /* 34 << 238 */ + { { 0x26eefb481bee45d4L,0xb3cee3463c688036L,0x463c5315c42f2469L, + 0x19d84d2e81378162L }, + { 0x22d7c3c51c4d349fL,0x65965844163d59c5L,0xcf198c56b8abceaeL, + 0x6fb1fb1b628559d5L } }, + /* 35 << 238 */ + { { 0x8bbffd0607bf8fe3L,0x46259c583467734bL,0xd8953cea35f7f0d3L, + 0x1f0bece2d65b0ff1L }, + { 0xf7d5b4b3f3c72914L,0x29e8ea953cb53389L,0x4a365626836b6d46L, + 0xe849f910ea174fdeL } }, + /* 36 << 238 */ + { { 0x7ec62fbbf4737f21L,0xd8dba5ab6209f5acL,0x24b5d7a9a5f9adbeL, + 0x707d28f7a61dc768L }, + { 0x7711460bcaa999eaL,0xba7b174d1c92e4ccL,0x3c4bab6618d4bf2dL, + 0xb8f0c980eb8bd279L } }, + /* 37 << 238 */ + { { 0x024bea9a324b4737L,0xfba9e42332a83bcaL,0x6e635643a232dcedL, + 0x996193672571c8baL }, + { 0xe8c9f35754b7032bL,0xf936b3ba2442d54aL,0x2263f0f08290c65aL, + 0x48989780ee2c7fdbL } }, + /* 38 << 238 */ + { { 0xadc5d55a13d4f95eL,0x737cff85ad9b8500L,0x271c557b8a73f43dL, + 0xbed617a4e18bc476L }, + { 0x662454017dfd8ab2L,0xae7b89ae3a2870aaL,0x1b555f5323a7e545L, + 0x6791e247be057e4cL } }, + /* 39 << 238 */ + { { 0x860136ad324fa34dL,0xea1114474cbeae28L,0x023a4270bedd3299L, + 0x3d5c3a7fc1c35c34L }, + { 0xb0f6db678d0412d2L,0xd92625e2fcdc6b9aL,0x92ae5ccc4e28a982L, + 0xea251c3647a3ce7eL } }, + /* 40 << 238 */ + { { 0x9d658932790691bfL,0xed61058906b736aeL,0x712c2f04c0d63b6eL, + 0x5cf06fd5c63d488fL }, + { 0x97363facd9588e41L,0x1f9bf7622b93257eL,0xa9d1ffc4667acaceL, + 0x1cf4a1aa0a061ecfL } }, + /* 41 << 238 */ + { { 0x40e48a49dc1818d0L,0x0643ff39a3621ab0L,0x5768640ce39ef639L, + 0x1fc099ea04d86854L }, + { 0x9130b9c3eccd28fdL,0xd743cbd27eec54abL,0x052b146fe5b475b6L, + 0x058d9a82900a7d1fL } }, + /* 42 << 238 */ + { { 0x65e0229291262b72L,0x96f924f9bb0edf03L,0x5cfa59c8fe206842L, + 0xf60370045eafa720L }, + { 0x5f30699e18d7dd96L,0x381e8782cbab2495L,0x91669b46dd8be949L, + 0xb40606f526aae8efL } }, + /* 43 << 238 */ + { { 0x2812b839fc6751a4L,0x16196214fba800efL,0x4398d5ca4c1a2875L, + 0x720c00ee653d8349L }, + { 0xc2699eb0d820007cL,0x880ee660a39b5825L,0x70694694471f6984L, + 0xf7d16ea8e3dda99aL } }, + /* 44 << 238 */ + { { 0x28d675b2c0519a23L,0x9ebf94fe4f6952e3L,0xf28bb767a2294a8aL, + 0x85512b4dfe0af3f5L }, + { 0x18958ba899b16a0dL,0x95c2430cba7548a7L,0xb30d1b10a16be615L, + 0xe3ebbb9785bfb74cL } }, + /* 45 << 238 */ + { { 0xa3273cfe18549fdbL,0xf6e200bf4fcdb792L,0x54a76e1883aba56cL, + 0x73ec66f689ef6aa2L }, + { 0x8d17add7d1b9a305L,0xa959c5b9b7ae1b9dL,0x886435226bcc094aL, + 0xcc5616c4d7d429b9L } }, + /* 46 << 238 */ + { { 0xa6dada01e6a33f7cL,0xc6217a079d4e70adL,0xd619a81809c15b7cL, + 0xea06b3290e80c854L }, + { 0x174811cea5f5e7b9L,0x66dfc310787c65f4L,0x4ea7bd693316ab54L, + 0xc12c4acb1dcc0f70L } }, + /* 47 << 238 */ + { { 0xe4308d1a1e407dd9L,0xe8a3587c91afa997L,0xea296c12ab77b7a5L, + 0xb5ad49e4673c0d52L }, + { 0x40f9b2b27006085aL,0xa88ff34087bf6ec2L,0x978603b14e3066a6L, + 0xb3f99fc2b5e486e2L } }, + /* 48 << 238 */ + { { 0x07b53f5eb2e63645L,0xbe57e54784c84232L,0xd779c2167214d5cfL, + 0x617969cd029a3acaL }, + { 0xd17668cd8a7017a0L,0x77b4d19abe9b7ee8L,0x58fd0e939c161776L, + 0xa8c4f4efd5968a72L } }, + /* 49 << 238 */ + { { 0x296071cc67b3de77L,0xae3c0b8e634f7905L,0x67e440c28a7100c9L, + 0xbb8c3c1beb4b9b42L }, + { 0x6d71e8eac51b3583L,0x7591f5af9525e642L,0xf73a2f7b13f509f3L, + 0x618487aa5619ac9bL } }, + /* 50 << 238 */ + { { 0x3a72e5f79d61718aL,0x00413bcc7592d28cL,0x7d9b11d3963c35cfL, + 0x77623bcfb90a46edL }, + { 0xdeef273bdcdd2a50L,0x4a741f9b0601846eL,0x33b89e510ec6e929L, + 0xcb02319f8b7f22cdL } }, + /* 51 << 238 */ + { { 0xbbe1500d084bae24L,0x2f0ae8d7343d2693L,0xacffb5f27cdef811L, + 0xaa0c030a263fb94fL }, + { 0x6eef0d61a0f442deL,0xf92e181727b139d3L,0x1ae6deb70ad8bc28L, + 0xa89e38dcc0514130L } }, + /* 52 << 238 */ + { { 0x81eeb865d2fdca23L,0x5a15ee08cc8ef895L,0x768fa10a01905614L, + 0xeff5b8ef880ee19bL }, + { 0xf0c0cabbcb1c8a0eL,0x2e1ee9cdb8c838f9L,0x0587d8b88a4a14c0L, + 0xf6f278962ff698e5L } }, + /* 53 << 238 */ + { { 0xed38ef1c89ee6256L,0xf44ee1fe6b353b45L,0x9115c0c770e903b3L, + 0xc78ec0a1818f31dfL }, + { 0x6c003324b7dccbc6L,0xd96dd1f3163bbc25L,0x33aa82dd5cedd805L, + 0x123aae4f7f7eb2f1L } }, + /* 54 << 238 */ + { { 0x1723fcf5a26262cdL,0x1f7f4d5d0060ebd5L,0xf19c5c01b2eaa3afL, + 0x2ccb9b149790accfL }, + { 0x1f9c1cad52324aa6L,0x632005267247df54L,0x5732fe42bac96f82L, + 0x52fe771f01a1c384L } }, + /* 55 << 238 */ + { { 0x546ca13db1001684L,0xb56b4eeea1709f75L,0x266545a9d5db8672L, + 0xed971c901e8f3cfbL }, + { 0x4e7d8691e3a07b29L,0x7570d9ece4b696b9L,0xdc5fa0677bc7e9aeL, + 0x68b44cafc82c4844L } }, + /* 56 << 238 */ + { { 0x519d34b3bf44da80L,0x283834f95ab32e66L,0x6e6087976278a000L, + 0x1e62960e627312f6L }, + { 0x9b87b27be6901c55L,0x80e7853824fdbc1fL,0xbbbc09512facc27dL, + 0x06394239ac143b5aL } }, + /* 57 << 238 */ + { { 0x35bb4a40376c1944L,0x7cb6269463da1511L,0xafd29161b7148a3bL, + 0xa6f9d9ed4e2ea2eeL }, + { 0x15dc2ca2880dd212L,0x903c3813a61139a9L,0x2aa7b46d6c0f8785L, + 0x36ce2871901c60ffL } }, + /* 58 << 238 */ + { { 0xc683b028e10d9c12L,0x7573baa2032f33d3L,0x87a9b1f667a31b58L, + 0xfd3ed11af4ffae12L }, + { 0x83dcaa9a0cb2748eL,0x8239f0185d6fdf16L,0xba67b49c72753941L, + 0x2beec455c321cb36L } }, + /* 59 << 238 */ + { { 0x880156063f8b84ceL,0x764170838d38c86fL,0x054f1ca7598953ddL, + 0xc939e1104e8e7429L }, + { 0x9b1ac2b35a914f2fL,0x39e35ed3e74b8f9cL,0xd0debdb2781b2fb0L, + 0x1585638f2d997ba2L } }, + /* 60 << 238 */ + { { 0x9c4b646e9e2fce99L,0x68a210811e80857fL,0x06d54e443643b52aL, + 0xde8d6d630d8eb843L }, + { 0x7032156342146a0aL,0x8ba826f25eaa3622L,0x227a58bd86138787L, + 0x43b6c03c10281d37L } }, + /* 61 << 238 */ + { { 0x6326afbbb54dde39L,0x744e5e8adb6f2d5fL,0x48b2a99acff158e1L, + 0xa93c8fa0ef87918fL }, + { 0x2182f956de058c5cL,0x216235d2936f9e7aL,0xace0c0dbd2e31e67L, + 0xc96449bff23ac3e7L } }, + /* 62 << 238 */ + { { 0x7e9a2874170693bdL,0xa28e14fda45e6335L,0x5757f6b356427344L, + 0x822e4556acf8edf9L }, + { 0x2b7a6ee2e6a285cdL,0x5866f211a9df3af0L,0x40dde2ddf845b844L, + 0x986c3726110e5e49L } }, + /* 63 << 238 */ + { { 0x73680c2af7172277L,0x57b94f0f0cccb244L,0xbdff72672d438ca7L, + 0xbad1ce11cf4663fdL }, + { 0x9813ed9dd8f71caeL,0xf43272a6961fdaa6L,0xbeff0119bd6d1637L, + 0xfebc4f9130361978L } }, + /* 64 << 238 */ + { { 0x02b37a952f41deffL,0x0e44a59ae63b89b7L,0x673257dc143ff951L, + 0x19c02205d752baf4L }, + { 0x46c23069c4b7d692L,0x2e6392c3fd1502acL,0x6057b1a21b220846L, + 0xe51ff9460c1b5b63L } }, + /* 0 << 245 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 245 */ + { { 0x6e85cb51566c5c43L,0xcff9c9193597f046L,0x9354e90c4994d94aL, + 0xe0a393322147927dL }, + { 0x8427fac10dc1eb2bL,0x88cfd8c22ff319faL,0xe2d4e68401965274L, + 0xfa2e067d67aaa746L } }, + /* 2 << 245 */ + { { 0xb6d92a7f3e5f9f11L,0x9afe153ad6cb3b8eL,0x4d1a6dd7ddf800bdL, + 0xf6c13cc0caf17e19L }, + { 0x15f6c58e325fc3eeL,0x71095400a31dc3b2L,0x168e7c07afa3d3e7L, + 0x3f8417a194c7ae2dL } }, + /* 3 << 245 */ + { { 0xec234772813b230dL,0x634d0f5f17344427L,0x11548ab1d77fc56aL, + 0x7fab1750ce06af77L }, + { 0xb62c10a74f7c4f83L,0xa7d2edc4220a67d9L,0x1c404170921209a0L, + 0x0b9815a0face59f0L } }, + /* 4 << 245 */ + { { 0x2842589b319540c3L,0x18490f59a283d6f8L,0xa2731f84daae9fcbL, + 0x3db6d960c3683ba0L }, + { 0xc85c63bb14611069L,0xb19436af0788bf05L,0x905459df347460d2L, + 0x73f6e094e11a7db1L } }, + /* 5 << 245 */ + { { 0xdc7f938eb6357f37L,0xc5d00f792bd8aa62L,0xc878dcb92ca979fcL, + 0x37e83ed9eb023a99L }, + { 0x6b23e2731560bf3dL,0x1086e4591d0fae61L,0x782483169a9414bdL, + 0x1b956bc0f0ea9ea1L } }, + /* 6 << 245 */ + { { 0x7b85bb91c31b9c38L,0x0c5aa90b48ef57b5L,0xdedeb169af3bab6fL, + 0xe610ad732d373685L }, + { 0xf13870df02ba8e15L,0x0337edb68ca7f771L,0xe4acf747b62c036cL, + 0xd921d576b6b94e81L } }, + /* 7 << 245 */ + { { 0xdbc864392c422f7aL,0xfb635362ed348898L,0x83084668c45bfcd1L, + 0xc357c9e32b315e11L }, + { 0xb173b5405b2e5b8cL,0x7e946931e102b9a4L,0x17c890eb7b0fb199L, + 0xec225a83d61b662bL } }, + /* 8 << 245 */ + { { 0xf306a3c8ee3c76cbL,0x3cf11623d32a1f6eL,0xe6d5ab646863e956L, + 0x3b8a4cbe5c005c26L }, + { 0xdcd529a59ce6bb27L,0xc4afaa5204d4b16fL,0xb0624a267923798dL, + 0x85e56df66b307fabL } }, + /* 9 << 245 */ + { { 0x0281893c2bf29698L,0x91fc19a4d7ce7603L,0x75a5dca3ad9a558fL, + 0x40ceb3fa4d50bf77L }, + { 0x1baf6060bc9ba369L,0x927e1037597888c2L,0xd936bf1986a34c07L, + 0xd4cf10c1c34ae980L } }, + /* 10 << 245 */ + { { 0x3a3e5334859dd614L,0x9c475b5b18d0c8eeL,0x63080d1f07cd51d5L, + 0xc9c0d0a6b88b4326L }, + { 0x1ac98691c234296fL,0x2a0a83a494887fb6L,0x565114270cea9cf2L, + 0x5230a6e8a24802f5L } }, + /* 11 << 245 */ + { { 0xf7a2bf0f72e3d5c1L,0x377174464f21439eL,0xfedcbf259ce30334L, + 0xe0030a787ce202f9L }, + { 0x6f2d9ebf1202e9caL,0xe79dde6c75e6e591L,0xf52072aff1dac4f8L, + 0x6c8d087ebb9b404dL } }, + /* 12 << 245 */ + { { 0xad0fc73dbce913afL,0x909e587b458a07cbL,0x1300da84d4f00c8aL, + 0x425cd048b54466acL }, + { 0xb59cb9be90e9d8bfL,0x991616db3e431b0eL,0xd3aa117a531aecffL, + 0x91af92d359f4dc3bL } }, + /* 13 << 245 */ + { { 0x9b1ec292e93fda29L,0x76bb6c17e97d91bcL,0x7509d95faface1e6L, + 0x3653fe47be855ae3L }, + { 0x73180b280f680e75L,0x75eefd1beeb6c26cL,0xa4cdf29fb66d4236L, + 0x2d70a9976b5821d8L } }, + /* 14 << 245 */ + { { 0x7a3ee20720445c36L,0x71d1ac8259877174L,0x0fc539f7949f73e9L, + 0xd05cf3d7982e3081L }, + { 0x8758e20b7b1c7129L,0xffadcc20569e61f2L,0xb05d3a2f59544c2dL, + 0xbe16f5c19fff5e53L } }, + /* 15 << 245 */ + { { 0x73cf65b8aad58135L,0x622c2119037aa5beL,0x79373b3f646fd6a0L, + 0x0e029db50d3978cfL }, + { 0x8bdfc43794fba037L,0xaefbd687620797a6L,0x3fa5382bbd30d38eL, + 0x7627cfbf585d7464L } }, + /* 16 << 245 */ + { { 0xb2330fef4e4ca463L,0xbcef72873566cc63L,0xd161d2cacf780900L, + 0x135dc5395b54827dL }, + { 0x638f052e27bf1bc6L,0x10a224f007dfa06cL,0xe973586d6d3321daL, + 0x8b0c573826152c8fL } }, + /* 17 << 245 */ + { { 0x07ef4f2a34606074L,0x80fe7fe8a0f7047aL,0x3d1a8152e1a0e306L, + 0x32cf43d888da5222L }, + { 0xbf89a95f5f02ffe6L,0x3d9eb9a4806ad3eaL,0x012c17bb79c8e55eL, + 0xfdcd1a7499c81dacL } }, + /* 18 << 245 */ + { { 0x7043178bb9556098L,0x4090a1df801c3886L,0x759800ff9b67b912L, + 0x3e5c0304232620c8L }, + { 0x4b9d3c4b70dceecaL,0xbb2d3c15181f648eL,0xf981d8376e33345cL, + 0xb626289b0cf2297aL } }, + /* 19 << 245 */ + { { 0x766ac6598baebdcfL,0x1a28ae0975df01e5L,0xb71283da375876d8L, + 0x4865a96d607b9800L }, + { 0x25dd1bcd237936b2L,0x332f4f4b60417494L,0xd0923d68370a2147L, + 0x497f5dfbdc842203L } }, + /* 20 << 245 */ + { { 0x9dc74cbd32be5e0fL,0x7475bcb717a01375L,0x438477c950d872b1L, + 0xcec67879ffe1d63dL }, + { 0x9b006014d8578c70L,0xc9ad99a878bb6b8bL,0x6799008e11fb3806L, + 0xcfe81435cd44cab3L } }, + /* 21 << 245 */ + { { 0xa2ee15822f4fb344L,0xb8823450483fa6ebL,0x622d323d652c7749L, + 0xd8474a98beb0a15bL }, + { 0xe43c154d5d1c00d0L,0x7fd581d90e3e7aacL,0x2b44c6192525ddf8L, + 0x67a033ebb8ae9739L } }, + /* 22 << 245 */ + { { 0x113ffec19ef2d2e4L,0x1bf6767ed5a0ea7fL,0x57fff75e03714c0aL, + 0xa23c422e0a23e9eeL }, + { 0xdd5f6b2d540f83afL,0xc2c2c27e55ea46a7L,0xeb6b4246672a1208L, + 0xd13599f7ae634f7aL } }, + /* 23 << 245 */ + { { 0xcf914b5cd7b32c6eL,0x61a5a640eaf61814L,0x8dc3df8b208a1bbbL, + 0xef627fd6b6d79aa5L }, + { 0x44232ffcc4c86bc8L,0xe6f9231b061539feL,0x1d04f25a958b9533L, + 0x180cf93449e8c885L } }, + /* 24 << 245 */ + { { 0x896895959884aaf7L,0xb1959be307b348a6L,0x96250e573c147c87L, + 0xae0efb3add0c61f8L }, + { 0xed00745eca8c325eL,0x3c911696ecff3f70L,0x73acbc65319ad41dL, + 0x7b01a020f0b1c7efL } }, + /* 25 << 245 */ + { { 0xea32b29363a1483fL,0x89eabe717a248f96L,0x9c6231d3343157e5L, + 0x93a375e5df3c546dL }, + { 0xe76e93436a2afe69L,0xc4f89100e166c88eL,0x248efd0d4f872093L, + 0xae0eb3ea8fe0ea61L } }, + /* 26 << 245 */ + { { 0xaf89790d9d79046eL,0x4d650f2d6cee0976L,0xa3935d9a43071ecaL, + 0x66fcd2c9283b0bfeL }, + { 0x0e665eb5696605f1L,0xe77e5d07a54cd38dL,0x90ee050a43d950cfL, + 0x86ddebdad32e69b5L } }, + /* 27 << 245 */ + { { 0x6ad94a3dfddf7415L,0xf7fa13093f6e8d5aL,0xc4831d1de9957f75L, + 0x7de28501d5817447L }, + { 0x6f1d70789e2aeb6bL,0xba2b9ff4f67a53c2L,0x36963767df9defc3L, + 0x479deed30d38022cL } }, + /* 28 << 245 */ + { { 0xd2edb89b3a8631e8L,0x8de855de7a213746L,0xb2056cb7b00c5f11L, + 0xdeaefbd02c9b85e4L }, + { 0x03f39a8dd150892dL,0x37b84686218b7985L,0x36296dd8b7375f1aL, + 0x472cd4b1b78e898eL } }, + /* 29 << 245 */ + { { 0x15dff651e9f05de9L,0xd40450692ce98ba9L,0x8466a7ae9b38024cL, + 0xb910e700e5a6b5efL }, + { 0xae1c56eab3aa8f0dL,0xbab2a5077eee74a6L,0x0dca11e24b4c4620L, + 0xfd896e2e4c47d1f4L } }, + /* 30 << 245 */ + { { 0xeb45ae53308fbd93L,0x46cd5a2e02c36fdaL,0x6a3d4e90baa48385L, + 0xdd55e62e9dbe9960L }, + { 0xa1406aa02a81ede7L,0x6860dd14f9274ea7L,0xcfdcb0c280414f86L, + 0xff410b1022f94327L } }, + /* 31 << 245 */ + { { 0x5a33cc3849ad467bL,0xefb48b6c0a7335f1L,0x14fb54a4b153a360L, + 0x604aa9d2b52469ccL }, + { 0x5e9dc486754e48e9L,0x693cb45537471e8eL,0xfb2fd7cd8d3b37b6L, + 0x63345e16cf09ff07L } }, + /* 32 << 245 */ + { { 0x9910ba6b23a5d896L,0x1fe19e357fe4364eL,0x6e1da8c39a33c677L, + 0x15b4488b29fd9fd0L }, + { 0x1f4392541a1f22bfL,0x920a8a70ab8163e8L,0x3fd1b24907e5658eL, + 0xf2c4f79cb6ec839bL } }, + /* 33 << 245 */ + { { 0x1abbc3d04aa38d1bL,0x3b0db35cb5d9510eL,0x1754ac783e60dec0L, + 0x53272fd7ea099b33L }, + { 0x5fb0494f07a8e107L,0x4a89e1376a8191faL,0xa113b7f63c4ad544L, + 0x88a2e9096cb9897bL } }, + /* 34 << 245 */ + { { 0x17d55de3b44a3f84L,0xacb2f34417c6c690L,0x3208816810232390L, + 0xf2e8a61f6c733bf7L }, + { 0xa774aab69c2d7652L,0xfb5307e3ed95c5bcL,0xa05c73c24981f110L, + 0x1baae31ca39458c9L } }, + /* 35 << 245 */ + { { 0x1def185bcbea62e7L,0xe8ac9eaeeaf63059L,0x098a8cfd9921851cL, + 0xd959c3f13abe2f5bL }, + { 0xa4f1952520e40ae5L,0x320789e307a24aa1L,0x259e69277392b2bcL, + 0x58f6c6671918668bL } }, + /* 36 << 245 */ + { { 0xce1db2bbc55d2d8bL,0x41d58bb7f4f6ca56L,0x7650b6808f877614L, + 0x905e16baf4c349edL }, + { 0xed415140f661acacL,0x3b8784f0cb2270afL,0x3bc280ac8a402cbaL, + 0xd53f71460937921aL } }, + /* 37 << 245 */ + { { 0xc03c8ee5e5681e83L,0x62126105f6ac9e4aL,0x9503a53f936b1a38L, + 0x3d45e2d4782fecbdL }, + { 0x69a5c43976e8ae98L,0xb53b2eebbfb4b00eL,0xf167471272386c89L, + 0x30ca34a24268bce4L } }, + /* 38 << 245 */ + { { 0x7f1ed86c78341730L,0x8ef5beb8b525e248L,0xbbc489fdb74fbf38L, + 0x38a92a0e91a0b382L }, + { 0x7a77ba3f22433ccfL,0xde8362d6a29f05a9L,0x7f6a30ea61189afcL, + 0x693b550559ef114fL } }, + /* 39 << 245 */ + { { 0x50266bc0cd1797a1L,0xea17b47ef4b7af2dL,0xd6c4025c3df9483eL, + 0x8cbb9d9fa37b18c9L }, + { 0x91cbfd9c4d8424cfL,0xdb7048f1ab1c3506L,0x9eaf641f028206a3L, + 0xf986f3f925bdf6ceL } }, + /* 40 << 245 */ + { { 0x262143b5224c08dcL,0x2bbb09b481b50c91L,0xc16ed709aca8c84fL, + 0xa6210d9db2850ca8L }, + { 0x6d8df67a09cb54d6L,0x91eef6e0500919a4L,0x90f613810f132857L, + 0x9acede47f8d5028bL } }, + /* 41 << 245 */ + { { 0x844d1b7190b771c3L,0x563b71e4ba6426beL,0x2efa2e83bdb802ffL, + 0x3410cbabab5b4a41L }, + { 0x555b2d2630da84ddL,0xd0711ae9ee1cc29aL,0xcf3e8c602f547792L, + 0x03d7d5dedc678b35L } }, + /* 42 << 245 */ + { { 0x071a2fa8ced806b8L,0x222e6134697f1478L,0xdc16fd5dabfcdbbfL, + 0x44912ebf121b53b8L }, + { 0xac9436742496c27cL,0x8ea3176c1ffc26b0L,0xb6e224ac13debf2cL, + 0x524cc235f372a832L } }, + /* 43 << 245 */ + { { 0xd706e1d89f6f1b18L,0x2552f00544cce35bL,0x8c8326c2a88e31fcL, + 0xb5468b2cf9552047L }, + { 0xce683e883ff90f2bL,0x77947bdf2f0a5423L,0xd0a1b28bed56e328L, + 0xaee35253c20134acL } }, + /* 44 << 245 */ + { { 0x7e98367d3567962fL,0x379ed61f8188bffbL,0x73bba348faf130a1L, + 0x6c1f75e1904ed734L }, + { 0x189566423b4a79fcL,0xf20bc83d54ef4493L,0x836d425d9111eca1L, + 0xe5b5c318009a8dcfL } }, + /* 45 << 245 */ + { { 0x3360b25d13221bc5L,0x707baad26b3eeaf7L,0xd7279ed8743a95a1L, + 0x7450a875969e809fL }, + { 0x32b6bd53e5d0338fL,0x1e77f7af2b883bbcL,0x90da12cc1063ecd0L, + 0xe2697b58c315be47L } }, + /* 46 << 245 */ + { { 0x2771a5bdda85d534L,0x53e78c1fff980eeaL,0xadf1cf84900385e7L, + 0x7d3b14f6c9387b62L }, + { 0x170e74b0cb8f2bd2L,0x2d50b486827fa993L,0xcdbe8c9af6f32babL, + 0x55e906b0c3b93ab8L } }, + /* 47 << 245 */ + { { 0x747f22fc8fe280d1L,0xcd8e0de5b2e114abL,0x5ab7dbebe10b68b0L, + 0x9dc63a9ca480d4b2L }, + { 0x78d4bc3b4be1495fL,0x25eb3db89359122dL,0x3f8ac05b0809cbdcL, + 0xbf4187bbd37c702fL } }, + /* 48 << 245 */ + { { 0x84cea0691416a6a5L,0x8f860c7943ef881cL,0x41311f8a38038a5dL, + 0xe78c2ec0fc612067L }, + { 0x494d2e815ad73581L,0xb4cc9e0059604097L,0xff558aecf3612cbaL, + 0x35beef7a9e36c39eL } }, + /* 49 << 245 */ + { { 0x1845c7cfdbcf41b9L,0x5703662aaea997c0L,0x8b925afee402f6d8L, + 0xd0a1b1ae4dd72162L }, + { 0x9f47b37503c41c4bL,0xa023829b0391d042L,0x5f5045c3503b8b0aL, + 0x123c268898c010e5L } }, + /* 50 << 245 */ + { { 0x324ec0cc36ba06eeL,0xface31153dd2cc0cL,0xb364f3bef333e91fL, + 0xef8aff7328e832b0L }, + { 0x1e9bad042d05841bL,0x42f0e3df356a21e2L,0xa3270bcb4add627eL, + 0xb09a8158d322e711L } }, + /* 51 << 245 */ + { { 0x86e326a10fee104aL,0xad7788f83703f65dL,0x7e76543047bc4833L, + 0x6cee582b2b9b893aL }, + { 0x9cd2a167e8f55a7bL,0xefbee3c6d9e4190dL,0x33ee7185d40c2e9dL, + 0x844cc9c5a380b548L } }, + /* 52 << 245 */ + { { 0x323f8ecd66926e04L,0x0001e38f8110c1baL,0x8dbcac12fc6a7f07L, + 0xd65e1d580cec0827L }, + { 0xd2cd4141be76ca2dL,0x7895cf5ce892f33aL,0x956d230d367139d2L, + 0xa91abd3ed012c4c1L } }, + /* 53 << 245 */ + { { 0x34fa488387eb36bfL,0xc5f07102914b8fb4L,0x90f0e579adb9c95fL, + 0xfe6ea8cb28888195L }, + { 0x7b9b5065edfa9284L,0x6c510bd22b8c8d65L,0xd7b8ebefcbe8aafdL, + 0xedb3af9896b1da07L } }, + /* 54 << 245 */ + { { 0x28ff779d6295d426L,0x0c4f6ac73fa3ad7bL,0xec44d0548b8e2604L, + 0x9b32a66d8b0050e1L }, + { 0x1f943366f0476ce2L,0x7554d953a602c7b4L,0xbe35aca6524f2809L, + 0xb6881229fd4edbeaL } }, + /* 55 << 245 */ + { { 0xe8cd0c8f508efb63L,0x9eb5b5c86abcefc7L,0xf5621f5fb441ab4fL, + 0x79e6c046b76a2b22L }, + { 0x74a4792ce37a1f69L,0xcbd252cb03542b60L,0x785f65d5b3c20bd3L, + 0x8dea61434fabc60cL } }, + /* 56 << 245 */ + { { 0x45e21446de673629L,0x57f7aa1e703c2d21L,0xa0e99b7f98c868c7L, + 0x4e42f66d8b641676L }, + { 0x602884dc91077896L,0xa0d690cfc2c9885bL,0xfeb4da333b9a5187L, + 0x5f789598153c87eeL } }, + /* 57 << 245 */ + { { 0x2192dd4752b16dbaL,0xdeefc0e63524c1b1L,0x465ea76ee4383693L, + 0x79401711361b8d98L }, + { 0xa5f9ace9f21a15cbL,0x73d26163efee9aebL,0xcca844b3e677016cL, + 0x6c122b0757eaee06L } }, + /* 58 << 245 */ + { { 0xb782dce715f09690L,0x508b9b122dfc0fc9L,0x9015ab4b65d89fc6L, + 0x5e79dab7d6d5bb0fL }, + { 0x64f021f06c775aa2L,0xdf09d8cc37c7eca1L,0x9a761367ef2fa506L, + 0xed4ca4765b81eec6L } }, + /* 59 << 245 */ + { { 0x262ede3610bbb8b5L,0x0737ce830641ada3L,0x4c94288ae9831cccL, + 0x487fc1ce8065e635L }, + { 0xb13d7ab3b8bb3659L,0xdea5df3e855e4120L,0xb9a1857385eb0244L, + 0x1a1b8ea3a7cfe0a3L } }, + /* 60 << 245 */ + { { 0x3b83711967b0867cL,0x8d5e0d089d364520L,0x52dccc1ed930f0e3L, + 0xefbbcec7bf20bbafL }, + { 0x99cffcab0263ad10L,0xd8199e6dfcd18f8aL,0x64e2773fe9f10617L, + 0x0079e8e108704848L } }, + /* 61 << 245 */ + { { 0x1169989f8a342283L,0x8097799ca83012e6L,0xece966cb8a6a9001L, + 0x93b3afef072ac7fcL }, + { 0xe6893a2a2db3d5baL,0x263dc46289bf4fdcL,0x8852dfc9e0396673L, + 0x7ac708953af362b6L } }, + /* 62 << 245 */ + { { 0xbb9cce4d5c2f342bL,0xbf80907ab52d7aaeL,0x97f3d3cd2161bcd0L, + 0xb25b08340962744dL }, + { 0xc5b18ea56c3a1ddaL,0xfe4ec7eb06c92317L,0xb787b890ad1c4afeL, + 0xdccd9a920ede801aL } }, + /* 63 << 245 */ + { { 0x9ac6dddadb58da1fL,0x22bbc12fb8cae6eeL,0xc6f8bced815c4a43L, + 0x8105a92cf96480c7L }, + { 0x0dc3dbf37a859d51L,0xe3ec7ce63041196bL,0xd9f64b250d1067c9L, + 0xf23213213d1f8dd8L } }, + /* 64 << 245 */ + { { 0x8b5c619c76497ee8L,0x5d2b0ac6c717370eL,0x98204cb64fcf68e1L, + 0x0bdec21162bc6792L }, + { 0x6973ccefa63b1011L,0xf9e3fa97e0de1ac5L,0x5efb693e3d0e0c8bL, + 0x037248e9d2d4fcb4L } }, + /* 0 << 252 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 } }, + /* 1 << 252 */ + { { 0x80802dc91ec34f9eL,0xd8772d3533810603L,0x3f06d66c530cb4f3L, + 0x7be5ed0dc475c129L }, + { 0xcb9e3c1931e82b10L,0xc63d2857c9ff6b4cL,0xb92118c692a1b45eL, + 0x0aec44147285bbcaL } }, + /* 2 << 252 */ + { { 0xfc189ae71e29a3efL,0xcbe906f04c93302eL,0xd0107914ceaae10eL, + 0xb7a23f34b68e19f8L }, + { 0xe9d875c2efd2119dL,0x03198c6efcadc9c8L,0x65591bf64da17113L, + 0x3cf0bbf83d443038L } }, + /* 3 << 252 */ + { { 0xae485bb72b724759L,0x945353e1b2d4c63aL,0x82159d07de7d6f2cL, + 0x389caef34ec5b109L }, + { 0x4a8ebb53db65ef14L,0x2dc2cb7edd99de43L,0x816fa3ed83f2405fL, + 0x73429bb9c14208a3L } }, + /* 4 << 252 */ + { { 0xb618d590b01e6e27L,0x047e2ccde180b2dcL,0xd1b299b504aea4a9L, + 0x412c9e1e9fa403a4L }, + { 0x88d28a3679407552L,0x49c50136f332b8e3L,0x3a1b6fcce668de19L, + 0x178851bc75122b97L } }, + /* 5 << 252 */ + { { 0xb1e13752fb85fa4cL,0xd61257ce383c8ce9L,0xd43da670d2f74daeL, + 0xa35aa23fbf846bbbL }, + { 0x5e74235d4421fc83L,0xf6df8ee0c363473bL,0x34d7f52a3c4aa158L, + 0x50d05aab9bc6d22eL } }, + /* 6 << 252 */ + { { 0x8c56e735a64785f4L,0xbc56637b5f29cd07L,0x53b2bb803ee35067L, + 0x50235a0fdc919270L }, + { 0x191ab6d8f2c4aa65L,0xc34758318396023bL,0x80400ba5f0f805baL, + 0x8881065b5ec0f80fL } }, + /* 7 << 252 */ + { { 0xc370e522cc1b5e83L,0xde2d4ad1860b8bfbL,0xad364df067b256dfL, + 0x8f12502ee0138997L }, + { 0x503fa0dc7783920aL,0xe80014adc0bc866aL,0x3f89b744d3064ba6L, + 0x03511dcdcba5dba5L } }, + /* 8 << 252 */ + { { 0x197dd46d95a7b1a2L,0x9c4e7ad63c6341fbL,0x426eca29484c2eceL, + 0x9211e489de7f4f8aL }, + { 0x14997f6ec78ef1f4L,0x2b2c091006574586L,0x17286a6e1c3eede8L, + 0x25f92e470f60e018L } }, + /* 9 << 252 */ + { { 0x805c564631890a36L,0x703ef60057feea5bL,0x389f747caf3c3030L, + 0xe0e5daeb54dd3739L }, + { 0xfe24a4c3c9c9f155L,0x7e4bf176b5393962L,0x37183de2af20bf29L, + 0x4a1bd7b5f95a8c3bL } }, + /* 10 << 252 */ + { { 0xa83b969946191d3dL,0x281fc8dd7b87f257L,0xb18e2c1354107588L, + 0x6372def79b2bafe8L }, + { 0xdaf4bb480d8972caL,0x3f2dd4b756167a3fL,0x1eace32d84310cf4L, + 0xe3bcefafe42700aaL } }, + /* 11 << 252 */ + { { 0x5fe5691ed785e73dL,0xa5db5ab62ea60467L,0x02e23d41dfc6514aL, + 0x35e8048ee03c3665L }, + { 0x3f8b118f1adaa0f8L,0x28ec3b4584ce1a5aL,0xe8cacc6e2c6646b8L, + 0x1343d185dbd0e40fL } }, + /* 12 << 252 */ + { { 0xe5d7f844caaa358cL,0x1a1db7e49924182aL,0xd64cd42d9c875d9aL, + 0xb37b515f042eeec8L }, + { 0x4d4dd4097b165fbeL,0xfc322ed9e206eff3L,0x7dee410259b7e17eL, + 0x55a481c08236ca00L } }, + /* 13 << 252 */ + { { 0x8c885312c23fc975L,0x1571580605d6297bL,0xa078868ef78edd39L, + 0x956b31e003c45e52L }, + { 0x470275d5ff7b33a6L,0xc8d5dc3a0c7e673fL,0x419227b47e2f2598L, + 0x8b37b6344c14a975L } }, + /* 14 << 252 */ + { { 0xd0667ed68b11888cL,0x5e0e8c3e803e25dcL,0x34e5d0dcb987a24aL, + 0x9f40ac3bae920323L }, + { 0x5463de9534e0f63aL,0xa128bf926b6328f9L,0x491ccd7cda64f1b7L, + 0x7ef1ec27c47bde35L } }, + /* 15 << 252 */ + { { 0xa857240fa36a2737L,0x35dc136663621bc1L,0x7a3a6453d4fb6897L, + 0x80f1a439c929319dL }, + { 0xfc18274bf8cb0ba0L,0xb0b537668078c5ebL,0xfb0d49241e01d0efL, + 0x50d7c67d372ab09cL } }, + /* 16 << 252 */ + { { 0xb4e370af3aeac968L,0xe4f7fee9c4b63266L,0xb4acd4c2e3ac5664L, + 0xf8910bd2ceb38cbfL }, + { 0x1c3ae50cc9c0726eL,0x15309569d97b40bfL,0x70884b7ffd5a5a1bL, + 0x3890896aef8314cdL } }, + /* 17 << 252 */ + { { 0x58e1515ca5618c93L,0xe665432b77d942d1L,0xb32181bfb6f767a8L, + 0x753794e83a604110L }, + { 0x09afeb7ce8c0dbccL,0x31e02613598673a3L,0x5d98e5577d46db00L, + 0xfc21fb8c9d985b28L } }, + /* 18 << 252 */ + { { 0xc9040116b0843e0bL,0x53b1b3a869b04531L,0xdd1649f085d7d830L, + 0xbb3bcc87cb7427e8L }, + { 0x77261100c93dce83L,0x7e79da61a1922a2aL,0x587a2b02f3149ce8L, + 0x147e1384de92ec83L } }, + /* 19 << 252 */ + { { 0x484c83d3af077f30L,0xea78f8440658b53aL,0x912076c2027aec53L, + 0xf34714e393c8177dL }, + { 0x37ef5d15c2376c84L,0x8315b6593d1aa783L,0x3a75c484ef852a90L, + 0x0ba0c58a16086bd4L } }, + /* 20 << 252 */ + { { 0x29688d7a529a6d48L,0x9c7f250dc2f19203L,0x123042fb682e2df9L, + 0x2b7587e7ad8121bcL }, + { 0x30fc0233e0182a65L,0xb82ecf87e3e1128aL,0x7168286193fb098fL, + 0x043e21ae85e9e6a7L } }, + /* 21 << 252 */ + { { 0xab5b49d666c834eaL,0x3be43e1847414287L,0xf40fb859219a2a47L, + 0x0e6559e9cc58df3cL }, + { 0xfe1dfe8e0c6615b4L,0x14abc8fd56459d70L,0x7be0fa8e05de0386L, + 0x8e63ef68e9035c7cL } }, + /* 22 << 252 */ + { { 0x116401b453b31e91L,0x0cba7ad44436b4d8L,0x9151f9a0107afd66L, + 0xafaca8d01f0ee4c4L }, + { 0x75fe5c1d9ee9761cL,0x3497a16bf0c0588fL,0x3ee2bebd0304804cL, + 0xa8fb9a60c2c990b9L } }, + /* 23 << 252 */ + { { 0xd14d32fe39251114L,0x36bf25bccac73366L,0xc9562c66dba7495cL, + 0x324d301b46ad348bL }, + { 0x9f46620cd670407eL,0x0ea8d4f1e3733a01L,0xd396d532b0c324e0L, + 0x5b211a0e03c317cdL } }, + /* 24 << 252 */ + { { 0x090d7d205ffe7b37L,0x3b7f3efb1747d2daL,0xa2cb525fb54fc519L, + 0x6e220932f66a971eL }, + { 0xddc160dfb486d440L,0x7fcfec463fe13465L,0x83da7e4e76e4c151L, + 0xd6fa48a1d8d302b5L } }, + /* 25 << 252 */ + { { 0xc6304f265872cd88L,0x806c1d3c278b90a1L,0x3553e725caf0bc1cL, + 0xff59e603bb9d8d5cL }, + { 0xa4550f327a0b85ddL,0xdec5720a93ecc217L,0x0b88b74169d62213L, + 0x7212f2455b365955L } }, + /* 26 << 252 */ + { { 0x20764111b5cae787L,0x13cb7f581dfd3124L,0x2dca77da1175aefbL, + 0xeb75466bffaae775L }, + { 0x74d76f3bdb6cff32L,0x7440f37a61fcda9aL,0x1bb3ac92b525028bL, + 0x20fbf8f7a1975f29L } }, + /* 27 << 252 */ + { { 0x982692e1df83097fL,0x28738f6c554b0800L,0xdc703717a2ce2f2fL, + 0x7913b93c40814194L }, + { 0x049245931fe89636L,0x7b98443ff78834a6L,0x11c6ab015114a5a1L, + 0x60deb383ffba5f4cL } }, + /* 28 << 252 */ + { { 0x4caa54c601a982e6L,0x1dd35e113491cd26L,0x973c315f7cbd6b05L, + 0xcab0077552494724L }, + { 0x04659b1f6565e15aL,0xbf30f5298c8fb026L,0xfc21641ba8a0de37L, + 0xe9c7a366fa5e5114L } }, + /* 29 << 252 */ + { { 0xdb849ca552f03ad8L,0xc7e8dbe9024e35c0L,0xa1a2bbaccfc3c789L, + 0xbf733e7d9c26f262L }, + { 0x882ffbf5b8444823L,0xb7224e886bf8483bL,0x53023b8b65bef640L, + 0xaabfec91d4d5f8cdL } }, + /* 30 << 252 */ + { { 0xa40e1510079ea1bdL,0x1ad9addcd05d5d26L,0xdb3f2eab13e68d4fL, + 0x1cff1ae2640f803fL }, + { 0xe0e7b749d4cee117L,0x8e9f275b4036d909L,0xce34e31d8f4d4c38L, + 0x22b37f69d75130fcL } }, + /* 31 << 252 */ + { { 0x83e0f1fdb4014604L,0xa8ce991989415078L,0x82375b7541792efeL, + 0x4f59bf5c97d4515bL }, + { 0xac4f324f923a277dL,0xd9bc9b7d650f3406L,0xc6fa87d18a39bc51L, + 0x825885305ccc108fL } }, + /* 32 << 252 */ + { { 0x5ced3c9f82e4c634L,0x8efb83143a4464f8L,0xe706381b7a1dca25L, + 0x6cd15a3c5a2a412bL }, + { 0x9347a8fdbfcd8fb5L,0x31db2eef6e54cd22L,0xc4aeb11ef8d8932fL, + 0x11e7c1ed344411afL } }, + /* 33 << 252 */ + { { 0x2653050cdc9a151eL,0x9edbfc083bb0a859L,0x926c81c7fd5691e7L, + 0x9c1b23426f39019aL }, + { 0x64a81c8b7f8474b9L,0x90657c0701761819L,0x390b333155e0375aL, + 0xc676c626b6ebc47dL } }, + /* 34 << 252 */ + { { 0x51623247b7d6dee8L,0x0948d92779659313L,0x99700161e9ab35edL, + 0x06cc32b48ddde408L }, + { 0x6f2fd664061ef338L,0x1606fa02c202e9edL,0x55388bc1929ba99bL, + 0xc4428c5e1e81df69L } }, + /* 35 << 252 */ + { { 0xce2028aef91b0b2aL,0xce870a23f03dfd3fL,0x66ec2c870affe8edL, + 0xb205fb46284d0c00L }, + { 0xbf5dffe744cefa48L,0xb6fc37a8a19876d7L,0xbecfa84c08b72863L, + 0xd7205ff52576374fL } }, + /* 36 << 252 */ + { { 0x80330d328887de41L,0x5de0df0c869ea534L,0x13f427533c56ea17L, + 0xeb1f6069452b1a78L }, + { 0x50474396e30ea15cL,0x575816a1c1494125L,0xbe1ce55bfe6bb38fL, + 0xb901a94896ae30f7L } }, + /* 37 << 252 */ + { { 0xe5af0f08d8fc3548L,0x5010b5d0d73bfd08L,0x993d288053fe655aL, + 0x99f2630b1c1309fdL }, + { 0xd8677bafb4e3b76fL,0x14e51ddcb840784bL,0x326c750cbf0092ceL, + 0xc83d306bf528320fL } }, + /* 38 << 252 */ + { { 0xc445671577d4715cL,0xd30019f96b703235L,0x207ccb2ed669e986L, + 0x57c824aff6dbfc28L }, + { 0xf0eb532fd8f92a23L,0x4a557fd49bb98fd2L,0xa57acea7c1e6199aL, + 0x0c6638208b94b1edL } }, + /* 39 << 252 */ + { { 0x9b42be8ff83a9266L,0xc7741c970101bd45L,0x95770c1107bd9cebL, + 0x1f50250a8b2e0744L }, + { 0xf762eec81477b654L,0xc65b900e15efe59aL,0x88c961489546a897L, + 0x7e8025b3c30b4d7cL } }, + /* 40 << 252 */ + { { 0xae4065ef12045cf9L,0x6fcb2caf9ccce8bdL,0x1fa0ba4ef2cf6525L, + 0xf683125dcb72c312L }, + { 0xa01da4eae312410eL,0x67e286776cd8e830L,0xabd9575298fb3f07L, + 0x05f11e11eef649a5L } }, + /* 41 << 252 */ + { { 0xba47faef9d3472c2L,0x3adff697c77d1345L,0x4761fa04dd15afeeL, + 0x64f1f61ab9e69462L }, + { 0xfa691fab9bfb9093L,0x3df8ae8fa1133dfeL,0xcd5f896758cc710dL, + 0xfbb88d5016c7fe79L } }, + /* 42 << 252 */ + { { 0x8e011b4ce88c50d1L,0x7532e807a8771c4fL,0x64c78a48e2278ee4L, + 0x0b283e833845072aL }, + { 0x98a6f29149e69274L,0xb96e96681868b21cL,0x38f0adc2b1a8908eL, + 0x90afcff71feb829dL } }, + /* 43 << 252 */ + { { 0x9915a383210b0856L,0xa5a80602def04889L,0x800e9af97c64d509L, + 0x81382d0bb8996f6fL }, + { 0x490eba5381927e27L,0x46c63b324af50182L,0x784c5fd9d3ad62ceL, + 0xe4fa1870f8ae8736L } }, + /* 44 << 252 */ + { { 0x4ec9d0bcd7466b25L,0x84ddbe1adb235c65L,0x5e2645ee163c1688L, + 0x570bd00e00eba747L }, + { 0xfa51b629128bfa0fL,0x92fce1bd6c1d3b68L,0x3e7361dcb66778b1L, + 0x9c7d249d5561d2bbL } }, + /* 45 << 252 */ + { { 0xa40b28bf0bbc6229L,0x1c83c05edfd91497L,0x5f9f5154f083df05L, + 0xbac38b3ceee66c9dL }, + { 0xf71db7e3ec0dfcfdL,0xf2ecda8e8b0a8416L,0x52fddd867812aa66L, + 0x2896ef104e6f4272L } }, + /* 46 << 252 */ + { { 0xff27186a0fe9a745L,0x08249fcd49ca70dbL,0x7425a2e6441cac49L, + 0xf4a0885aece5ff57L }, + { 0x6e2cb7317d7ead58L,0xf96cf7d61898d104L,0xafe67c9d4f2c9a89L, + 0x89895a501c7bf5bcL } }, + /* 47 << 252 */ + { { 0xdc7cb8e5573cecfaL,0x66497eaed15f03e6L,0x6bc0de693f084420L, + 0x323b9b36acd532b0L }, + { 0xcfed390a0115a3c1L,0x9414c40b2d65ca0eL,0x641406bd2f530c78L, + 0x29369a44833438f2L } }, + /* 48 << 252 */ + { { 0x996884f5903fa271L,0xe6da0fd2b9da921eL,0xa6f2f2695db01e54L, + 0x1ee3e9bd6876214eL }, + { 0xa26e181ce27a9497L,0x36d254e48e215e04L,0x42f32a6c252cabcaL, + 0x9948148780b57614L } }, + /* 49 << 252 */ + { { 0x4c4dfe6940d9cae1L,0x0586958011a10f09L,0xca287b573491b64bL, + 0x77862d5d3fd4a53bL }, + { 0xbf94856e50349126L,0x2be30bd171c5268fL,0x10393f19cbb650a6L, + 0x639531fe778cf9fdL } }, + /* 50 << 252 */ + { { 0x02556a11b2935359L,0xda38aa96af8c126eL,0x47dbe6c20960167fL, + 0x37bbabb6501901cdL }, + { 0xb6e979e02c947778L,0xd69a51757a1a1dc6L,0xc3ed50959d9faf0cL, + 0x4dd9c0961d5fa5f0L } }, + /* 51 << 252 */ + { { 0xa0c4304d64f16ea8L,0x8b1cac167e718623L,0x0b5765467c67f03eL, + 0x559cf5adcbd88c01L }, + { 0x074877bb0e2af19aL,0x1f717ec1a1228c92L,0x70bcb800326e8920L, + 0xec6e2c5c4f312804L } }, + /* 52 << 252 */ + { { 0x426aea7d3fca4752L,0xf12c09492211f62aL,0x24beecd87be7b6b5L, + 0xb77eaf4c36d7a27dL }, + { 0x154c2781fda78fd3L,0x848a83b0264eeabeL,0x81287ef04ffe2bc4L, + 0x7b6d88c6b6b6fc2aL } }, + /* 53 << 252 */ + { { 0x805fb947ce417d99L,0x4b93dcc38b916cc4L,0x72e65bb321273323L, + 0xbcc1badd6ea9886eL }, + { 0x0e2230114bc5ee85L,0xa561be74c18ee1e4L,0x762fd2d4a6bcf1f1L, + 0x50e6a5a495231489L } }, + /* 54 << 252 */ + { { 0xca96001fa00b500bL,0x5c098cfc5d7dcdf5L,0xa64e2d2e8c446a85L, + 0xbae9bcf1971f3c62L }, + { 0x4ec226838435a2c5L,0x8ceaed6c4bad4643L,0xe9f8fb47ccccf4e3L, + 0xbd4f3fa41ce3b21eL } }, + /* 55 << 252 */ + { { 0xd79fb110a3db3292L,0xe28a37dab536c66aL,0x279ce87b8e49e6a9L, + 0x70ccfe8dfdcec8e3L }, + { 0x2193e4e03ba464b2L,0x0f39d60eaca9a398L,0x7d7932aff82c12abL, + 0xd8ff50ed91e7e0f7L } }, + /* 56 << 252 */ + { { 0xea961058fa28a7e0L,0xc726cf250bf5ec74L,0xe74d55c8db229666L, + 0x0bd9abbfa57f5799L }, + { 0x7479ef074dfc47b3L,0xd9c65fc30c52f91dL,0x8e0283fe36a8bde2L, + 0xa32a8b5e7d4b7280L } }, + /* 57 << 252 */ + { { 0x6a677c6112e83233L,0x0fbb3512dcc9bf28L,0x562e8ea50d780f61L, + 0x0db8b22b1dc4e89cL }, + { 0x0a6fd1fb89be0144L,0x8c77d246ca57113bL,0x4639075dff09c91cL, + 0x5b47b17f5060824cL } }, + /* 58 << 252 */ + { { 0x58aea2b016287b52L,0xa1343520d0cd8eb0L,0x6148b4d0c5d58573L, + 0xdd2b6170291c68aeL }, + { 0xa61b39291da3b3b7L,0x5f946d7908c4ac10L,0x4105d4a57217d583L, + 0x5061da3d25e6de5eL } }, + /* 59 << 252 */ + { { 0x3113940dec1b4991L,0xf12195e136f485aeL,0xa7507fb2731a2ee0L, + 0x95057a8e6e9e196eL }, + { 0xa3c2c9112e130136L,0x97dfbb3633c60d15L,0xcaf3c581b300ee2bL, + 0x77f25d90f4bac8b8L } }, + /* 60 << 252 */ + { { 0xdb1c4f986d840cd6L,0x471d62c0e634288cL,0x8ec2f85ecec8a161L, + 0x41f37cbcfa6f4ae2L }, + { 0x6793a20f4b709985L,0x7a7bd33befa8985bL,0x2c6a3fbd938e6446L, + 0x190426192a8d47c1L } }, + /* 61 << 252 */ + { { 0x16848667cc36975fL,0x02acf1689d5f1dfbL,0x62d41ad4613baa94L, + 0xb56fbb929f684670L }, + { 0xce610d0de9e40569L,0x7b99c65f35489fefL,0x0c88ad1b3df18b97L, + 0x81b7d9be5d0e9edbL } }, + /* 62 << 252 */ + { { 0xd85218c0c716cc0aL,0xf4b5ff9085691c49L,0xa4fd666bce356ac6L, + 0x17c728954b327a7aL }, + { 0xf93d5085da6be7deL,0xff71530e3301d34eL,0x4cd96442d8f448e8L, + 0x9283d3312ed18ffaL } }, + /* 63 << 252 */ + { { 0x4d33dd992a849870L,0xa716964b41576335L,0xff5e3a9b179be0e5L, + 0x5b9d6b1b83b13632L }, + { 0x3b8bd7d4a52f313bL,0xc9dd95a0637a4660L,0x300359620b3e218fL, + 0xce1481a3c7b28a3cL } }, + /* 64 << 252 */ + { { 0xab41b43a43228d83L,0x24ae1c304ad63f99L,0x8e525f1a46a51229L, + 0x14af860fcd26d2b4L }, + { 0xd6baef613f714aa1L,0xf51865adeb78795eL,0xd3e21fcee6a9d694L, + 0x82ceb1dd8a37b527L } }, +}; + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_add_only_4(sp_point_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit tmpd[2 * 4 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_256 v[37]; + int err; + + (void)g; + (void)heap; + + err = sp_256_point_new_4(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_256_point_new_4(heap, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + tmp = tmpd; +#endif + negy = tmp; + + if (err == MP_OKAY) { + sp_256_ecc_recode_7_4(k, v); + + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + i = 36; + XMEMCPY(rt->x, table[i * 65 + v[i].i].x, sizeof(table->x)); + XMEMCPY(rt->y, table[i * 65 + v[i].i].y, sizeof(table->y)); + rt->infinity = !v[i].i; + for (--i; i>=0; i--) { + XMEMCPY(p->x, table[i * 65 + v[i].i].x, sizeof(table->x)); + XMEMCPY(p->y, table[i * 65 + v[i].i].y, sizeof(table->y)); + p->infinity = !v[i].i; + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, 0 - v[i].neg); + sp_256_proj_point_add_qz1_4(rt, rt, p, tmp); + } + if (map != 0) { + sp_256_map_4(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmp, sizeof(sp_digit) * 2 * 4 * 5); +#endif + sp_256_point_free_4(p, 0, heap); + sp_256_point_free_4(rt, 0, heap); + + return MP_OKAY; +} + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_add_only_4(r, NULL, p256_table, + k, map, heap); +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_add_only_avx2_4(sp_point_256* r, const sp_point_256* g, + const sp_table_entry_256* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 rtd; + sp_point_256 pd; + sp_digit tmpd[2 * 4 * 5]; +#endif + sp_point_256* rt; + sp_point_256* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_256 v[37]; + int err; + + (void)g; + (void)heap; + + err = sp_256_point_new_4(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_256_point_new_4(heap, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + tmp = tmpd; +#endif + negy = tmp; + + if (err == MP_OKAY) { + sp_256_ecc_recode_7_4(k, v); + + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + i = 36; + XMEMCPY(rt->x, table[i * 65 + v[i].i].x, sizeof(table->x)); + XMEMCPY(rt->y, table[i * 65 + v[i].i].y, sizeof(table->y)); + rt->infinity = !v[i].i; + for (--i; i>=0; i--) { + XMEMCPY(p->x, table[i * 65 + v[i].i].x, sizeof(table->x)); + XMEMCPY(p->y, table[i * 65 + v[i].i].y, sizeof(table->y)); + p->infinity = !v[i].i; + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, 0 - v[i].neg); + sp_256_proj_point_add_qz1_avx2_4(rt, rt, p, tmp); + } + if (map != 0) { + sp_256_map_avx2_4(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_256)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmp, sizeof(sp_digit) * 2 * 4 * 5); +#endif + sp_256_point_free_4(p, 0, heap); + sp_256_point_free_4(rt, 0, heap); + + return MP_OKAY; +} + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_256* r, const sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_add_only_avx2_4(r, NULL, p256_table, + k, map, heap); +} + +#endif /* HAVE_INTEL_AVX2 */ +#endif /* 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 coordinates. + * + * 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[4]; +#endif + sp_point_256* point; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_256_point_new_4(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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 || HAVE_ECC_VERIFY */ +extern void sp_256_add_one_4(sp_digit* a); +extern void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n); +/* 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, (int)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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[4]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 inf; +#endif +#endif + sp_point_256* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity; +#endif + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + + err = sp_256_point_new_4(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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) == 0) || (sp_256_iszero_4(point->y) == 0)) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_256_point_free_4(infinity, 1, heap); +#endif + sp_256_point_free_4(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +extern void sp_256_to_bin(sp_digit* r, byte* a); +/* 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)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 p; + sp_digit kd[4]; +#endif + sp_point_256* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (*outLen < 32U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +extern sp_digit sp_256_add_4(sp_digit* r, const sp_digit* a, const sp_digit* b); +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +extern void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b); +#ifdef HAVE_INTEL_AVX2 +extern void sp_256_mul_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit* b); +#endif /* HAVE_INTEL_AVX2 */ +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +extern sp_digit sp_256_sub_in_place_4(sp_digit* a, const sp_digit* b); +extern sp_digit sp_256_cond_sub_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_256_mul_d_4(sp_digit* r, const sp_digit* a, sp_digit b); +extern void sp_256_mul_d_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit b); +/* 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 WC_INLINE sp_digit div_256_word_4(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + 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, const 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 WC_INLINE int sp_256_div_4(const sp_digit* a, const 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); + r1 = sp_256_cmp_4(&t1[4], d) >= 0; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_cond_sub_avx2_4(&t1[4], &t1[4], d, (sp_digit)0 - r1); + else +#endif + sp_256_cond_sub_4(&t1[4], &t1[4], d, (sp_digit)0 - r1); + 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; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_cond_sub_avx2_4(r, t1, d, (sp_digit)0 - r1); + else +#endif + sp_256_cond_sub_4(r, t1, d, (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 WC_INLINE int sp_256_mod_4(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_256_div_4(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +extern void sp_256_sqr_4(sp_digit* r, const sp_digit* a); +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint64_t p256_order_minus_2[4] = { + 0xf3b9cac2fc63254fU,0xbce6faada7179e84U,0xffffffffffffffffU, + 0xffffffff00000000U +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint64_t p256_order_low[2] = { + 0xf3b9cac2fc63254fU,0xbce6faada7179e84U +}; +#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, const sp_digit* a, const sp_digit* b) +{ + sp_256_mul_4(r, a, b); + sp_256_mont_reduce_order_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, const sp_digit* a) +{ + sp_256_sqr_4(r, a); + sp_256_mont_reduce_order_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, const 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_minus_2[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + sp_256_mont_mul_order_4(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 4U); +#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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 +extern void sp_256_sqr_avx2_4(sp_digit* r, const sp_digit* a); +#define sp_256_mont_reduce_order_avx2_4 sp_256_mont_reduce_avx2_4 + +extern void sp_256_mont_reduce_avx2_4(sp_digit* a, const sp_digit* m, sp_digit mp); +/* 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, const sp_digit* a, const sp_digit* b) +{ + sp_256_mul_avx2_4(r, a, b); + sp_256_mont_reduce_order_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, const sp_digit* a) +{ + sp_256_sqr_avx2_4(r, a); + sp_256_mont_reduce_order_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, const 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_minus_2[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + sp_256_mont_mul_order_avx2_4(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 4U); +#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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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 (((sp_digit)p256_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + 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, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#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_256 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_256* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int64_t c; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + + err = sp_256_point_new_4(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 4; + x = d + 2 * 4; + k = d + 4 * 4; + r = d + 6 * 4; + tmp = d + 8 * 4; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(e, 4, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 4, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_4(rng, k); + } + else { + sp_256_from_mp(k, 4, km); + mp_zero(km); + } + 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) * 4U); + sp_256_norm_4(r); + c = sp_256_cmp_4(r, p256_order); + sp_256_cond_sub_4(r, r, p256_order, 0L - (sp_digit)(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, 0L - (sp_digit)(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) == 0) { + 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)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 4); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 4U); +#endif + sp_256_point_free_4(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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_256 p1d; + sp_point_256 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p1; + sp_point_256* p2 = NULL; + sp_digit carry; + int64_t c; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_256_point_new_4(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 4; + u2 = d + 2 * 4; + s = d + 4 * 4; + tmp = d + 6 * 4; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 4, hash, (int)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); + if (sp_256_iszero_4(p1->z)) { + if (sp_256_iszero_4(p1->x) && sp_256_iszero_4(p1->y)) { + sp_256_proj_point_dbl_avx2_4(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + } + else +#endif + { + sp_256_proj_point_add_4(p1, p1, p2, tmp); + if (sp_256_iszero_4(p1->z)) { + if (sp_256_iszero_4(p1->x) && sp_256_iszero_4(p1->y)) { + sp_256_proj_point_dbl_4(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + } + + /* (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 = (int)(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 == 0) { + 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 = (int)(sp_256_cmp_4(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_256_point_free_4(p1, 0, heap); + sp_256_point_free_4(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_4(sp_point_256* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*4]; + sp_digit t2d[2*4]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 4; + t2 = d + 2 * 4; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_256_sqr_4(t1, point->y); + (void)sp_256_mod_4(t1, t1, p256_mod); + sp_256_sqr_4(t2, point->x); + (void)sp_256_mod_4(t2, t2, p256_mod); + sp_256_mul_4(t2, t2, point->x); + (void)sp_256_mod_4(t2, t2, p256_mod); + (void)sp_256_sub_4(t2, p256_mod, t2); + sp_256_mont_add_4(t1, t1, t2, p256_mod); + + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_4(t1, p256_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256 pubd; +#endif + sp_point_256* pub; + byte one[1] = { 1 }; + int err; + + err = sp_256_point_new_4(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 4, pX); + sp_256_from_mp(pub->y, 4, pY); + sp_256_from_bin(pub->z, 4, one, (int)sizeof(one)); + + err = sp_256_ecc_is_point_4(pub, NULL); + } + + sp_256_point_free_4(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[4]; + sp_point_256 pubd; + sp_point_256 pd; +#endif + sp_digit* priv = NULL; + sp_point_256* pub; + sp_point_256* p = NULL; + byte one[1] = { 1 }; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_256_point_new_4(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_256_point_new_4(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_256_from_mp(pub->x, 4, pX); + sp_256_from_mp(pub->y, 4, pY); + sp_256_from_bin(pub->z, 4, one, (int)sizeof(one)); + sp_256_from_mp(priv, 4, privm); + + /* Check point at infinitiy. */ + if ((sp_256_iszero_4(pub->x) != 0) && + (sp_256_iszero_4(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_4(pub->x, p256_mod) >= 0 || + sp_256_cmp_4(pub->y, p256_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_4(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_4(p, pub, p256_order, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_4(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_256_iszero_4(p->x) == 0) || + (sp_256_iszero_4(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(p, priv, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_base_4(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_4(p->x, pub->x) != 0 || + sp_256_cmp_4(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(p, 0, heap); + sp_256_point_free_4(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 4 * 5]; + sp_point_256 pd; + sp_point_256 qd; +#endif + sp_digit* tmp; + sp_point_256* p; + sp_point_256* q = NULL; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_256_point_new_4(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_256_point_new_4(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + sp_256_from_mp(q->x, 4, qX); + sp_256_from_mp(q->y, 4, qY); + sp_256_from_mp(q->z, 4, qZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_add_avx2_4(p, p, q, tmp); + else +#endif + sp_256_proj_point_add_4(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(q, 0, NULL); + sp_256_point_free_4(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 4 * 2]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_256_point_new_4(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_dbl_avx2_4(p, p, tmp); + else +#endif + sp_256_proj_point_dbl_4(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 4 * 4]; + sp_point_256 pd; +#endif + sp_digit* tmp; + sp_point_256* p; + int err; + + err = sp_256_point_new_4(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + + sp_256_map_4(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_256_point_free_4(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_4(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 4]; + sp_digit t2d[2 * 4]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 4; + t2 = d + 2 * 4; +#else + t1 = t1d; + t2 = t2d; +#endif + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_avx2_4(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_avx2_4(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_avx2_4(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_avx2_4(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_avx2_4(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_avx2_4(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_avx2_4(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_avx2_4(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_avx2_4(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_avx2_4(y, t1, 94, p256_mod, p256_mp_mod); + } + else +#endif + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_4(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_4(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_4(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_4(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_4(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_4(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_4(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_4(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 4]; + sp_digit yd[2 * 4]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 4; + y = d + 2 * 4; +#else + x = xd; + y = yd; +#endif + + sp_256_from_mp(x, 4, xm); + err = sp_256_mod_mul_norm_4(x, x, p256_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mont_sqr_avx2_4(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(y, y, x, p256_mod, p256_mp_mod); + } + else +#endif + { + sp_256_mont_sqr_4(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_4(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_4(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_4(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 4, 0, 4U * sizeof(sp_digit)); + sp_256_mont_reduce_4(y, p256_mod, p256_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_256_mont_sub_4(y, p256_mod, y, p256_mod); + } + + err = sp_256_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#ifdef WOLFSSL_SP_384 + +/* Point structure to use. */ +typedef struct sp_point_384 { + sp_digit x[2 * 6]; + sp_digit y[2 * 6]; + sp_digit z[2 * 6]; + int infinity; +} sp_point_384; + +/* The modulus (prime) of the curve P384. */ +static const sp_digit p384_mod[6] = { + 0x00000000ffffffffL,0xffffffff00000000L,0xfffffffffffffffeL, + 0xffffffffffffffffL,0xffffffffffffffffL,0xffffffffffffffffL +}; +/* The Montogmery normalizer for modulus of the curve P384. */ +static const sp_digit p384_norm_mod[6] = { + 0xffffffff00000001L,0x00000000ffffffffL,0x0000000000000001L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L +}; +/* The Montogmery multiplier for modulus of the curve P384. */ +static sp_digit p384_mp_mod = 0x0000000100000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P384. */ +static const sp_digit p384_order[6] = { + 0xecec196accc52973L,0x581a0db248b0a77aL,0xc7634d81f4372ddfL, + 0xffffffffffffffffL,0xffffffffffffffffL,0xffffffffffffffffL +}; +#endif +/* The order of the curve P384 minus 2. */ +static const sp_digit p384_order2[6] = { + 0xecec196accc52971L,0x581a0db248b0a77aL,0xc7634d81f4372ddfL, + 0xffffffffffffffffL,0xffffffffffffffffL,0xffffffffffffffffL +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P384. */ +static const sp_digit p384_norm_order[6] = { + 0x1313e695333ad68dL,0xa7e5f24db74f5885L,0x389cb27e0bc8d220L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P384. */ +static sp_digit p384_mp_order = 0x6ed46089e88fdc45l; +#endif +/* The base point of curve P384. */ +static const sp_point_384 p384_base = { + /* X ordinate */ + { + 0x3a545e3872760ab7L,0x5502f25dbf55296cL,0x59f741e082542a38L, + 0x6e1d3b628ba79b98L,0x8eb1c71ef320ad74L,0xaa87ca22be8b0537L, + 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Y ordinate */ + { + 0x7a431d7c90ea0e5fL,0x0a60b1ce1d7e819dL,0xe9da3113b5f0b8c0L, + 0xf8f41dbd289a147cL,0x5d9e98bf9292dc29L,0x3617de4a96262c6fL, + 0L, 0L, 0L, 0L, 0L, 0L + }, + /* Z ordinate */ + { + 0x0000000000000001L,0x0000000000000000L,0x0000000000000000L, + 0x0000000000000000L,0x0000000000000000L,0x0000000000000000L, + 0L, 0L, 0L, 0L, 0L, 0L + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static const sp_digit p384_b[6] = { + 0x2a85c8edd3ec2aefL,0xc656398d8a2ed19dL,0x0314088f5013875aL, + 0x181d9c6efe814112L,0x988e056be3f82d19L,0xb3312fa7e23ee7e4L +}; +#endif + +static int sp_384_point_new_ex_6(void* heap, sp_point_384* sp, sp_point_384** p) +{ + int ret = MP_OKAY; + (void)heap; +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + (void)sp; + *p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC); +#else + *p = sp; +#endif + if (*p == NULL) { + ret = MEMORY_E; + } + return ret; +} + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* Allocate memory for point and return error. */ +#define sp_384_point_new_6(heap, sp, p) sp_384_point_new_ex_6((heap), NULL, &(p)) +#else +/* Set pointer to data and return no error. */ +#define sp_384_point_new_6(heap, sp, p) sp_384_point_new_ex_6((heap), &(sp), &(p)) +#endif + + +static void sp_384_point_free_6(sp_point_384* p, int clear, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) +/* If valid pointer then clear point data if requested and free data. */ + if (p != NULL) { + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } +#else +/* Clear point data if requested. */ + if (clear != 0) { + XMEMSET(p, 0, sizeof(*p)); + } +#endif + (void)heap; +} + +/* 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_384_mod_mul_norm_6(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + int64_t* td; +#else + int64_t td[12]; + int64_t a32d[12]; +#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)) && !defined(WOLFSSL_SP_NO_MALLOC) + td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC); + if (td == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = td; + a32 = td + 12; +#else + t = td; + a32 = a32d; +#endif + + 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; + a32[8] = a[4] & 0xffffffff; + a32[9] = a[4] >> 32; + a32[10] = a[5] & 0xffffffff; + a32[11] = a[5] >> 32; + + /* 1 0 0 0 0 0 0 0 1 1 0 -1 */ + t[0] = 0 + a32[0] + a32[8] + a32[9] - a32[11]; + /* -1 1 0 0 0 0 0 0 -1 0 1 1 */ + t[1] = 0 - a32[0] + a32[1] - a32[8] + a32[10] + a32[11]; + /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */ + t[2] = 0 - a32[1] + a32[2] - a32[9] + a32[11]; + /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */ + t[3] = 0 + a32[0] - a32[2] + a32[3] + a32[8] + a32[9] - a32[10] - a32[11]; + /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */ + t[4] = 0 + a32[0] + a32[1] - a32[3] + a32[4] + a32[8] + 2 * a32[9] + a32[10] - 2 * a32[11]; + /* 0 1 1 0 -1 1 0 0 0 1 2 1 */ + t[5] = 0 + a32[1] + a32[2] - a32[4] + a32[5] + a32[9] + 2 * a32[10] + a32[11]; + /* 0 0 1 1 0 -1 1 0 0 0 1 2 */ + t[6] = 0 + a32[2] + a32[3] - a32[5] + a32[6] + a32[10] + 2 * a32[11]; + /* 0 0 0 1 1 0 -1 1 0 0 0 1 */ + t[7] = 0 + a32[3] + a32[4] - a32[6] + a32[7] + a32[11]; + /* 0 0 0 0 1 1 0 -1 1 0 0 0 */ + t[8] = 0 + a32[4] + a32[5] - a32[7] + a32[8]; + /* 0 0 0 0 0 1 1 0 -1 1 0 0 */ + t[9] = 0 + a32[5] + a32[6] - a32[8] + a32[9]; + /* 0 0 0 0 0 0 1 1 0 -1 1 0 */ + t[10] = 0 + a32[6] + a32[7] - a32[9] + a32[10]; + /* 0 0 0 0 0 0 0 1 1 0 -1 1 */ + t[11] = 0 + a32[7] + a32[8] - a32[10] + a32[11]; + + 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 0xffffffff; + o = t[11] >> 32; t[11] &= 0xffffffff; + t[0] += o; + t[1] -= o; + t[3] += o; + t[4] += 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; + t[8] += t[7] >> 32; t[7] &= 0xffffffff; + t[9] += t[8] >> 32; t[8] &= 0xffffffff; + t[10] += t[9] >> 32; t[9] &= 0xffffffff; + t[11] += t[10] >> 32; t[10] &= 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]; + r[4] = (t[9] << 32) | t[8]; + r[5] = (t[11] << 32) | t[10]; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + 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. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 64 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i] << s); + r[j] &= 0xffffffffffffffffl; + s = 64U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 64U) <= (word32)DIGIT_BIT) { + s += 64U; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= size) { + break; + } + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* Convert a point of type ecc_point to type sp_point_384. + * + * p Point of type sp_point_384 (result). + * pm Point of type ecc_point. + */ +static void sp_384_point_from_ecc_point_6(sp_point_384* p, const 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_384_from_mp(p->x, 6, pm->x); + sp_384_from_mp(p->y, 6, pm->y); + sp_384_from_mp(p->z, 6, 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_384_to_mp(const sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/ +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 6); + r->used = 6; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 6; i++) { + r->dp[j] |= (mp_digit)(a[i] << s); + r->dp[j] &= (1L << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = (mp_digit)(a[i] >> s); + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j++] &= (1L << DIGIT_BIT) - 1; + if (s == SP_WORD_SIZE) { + r->dp[j] = 0; + } + else { + r->dp[j] = (mp_digit)(a[i] >> s); + } + } + s = 64 - s; + } + r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 6; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && 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 = (384 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point_384 to type ecc_point. + * + * p Point of type sp_point_384. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_384_point_to_ecc_point_6(const sp_point_384* p, ecc_point* pm) +{ + int err; + + err = sp_384_to_mp(p->x, pm->x); + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pm->y); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pm->z); + } + + return err; +} + +extern void sp_384_cond_copy_6(sp_digit* r, const sp_digit* a, sp_digit m); +extern void sp_384_mul_6(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern sp_digit sp_384_cond_sub_6(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_384_mont_reduce_6(sp_digit* a, const sp_digit* m, sp_digit mp); +extern void sp_384_mont_reduce_order_6(sp_digit* a, const sp_digit* m, sp_digit mp); +/* 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_384_mont_mul_6(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_384_mul_6(r, a, b); + sp_384_mont_reduce_6(r, m, mp); +} + +extern void sp_384_sqr_6(sp_digit* r, const sp_digit* a); +/* 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_384_mont_sqr_6(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_384_sqr_6(r, a); + sp_384_mont_reduce_6(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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_384_mont_sqr_n_6(sp_digit* r, const sp_digit* a, int n, + const sp_digit* m, sp_digit mp) +{ + sp_384_mont_sqr_6(r, a, m, mp); + for (; n > 1; n--) { + sp_384_mont_sqr_6(r, r, m, mp); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P384 curve. */ +static const uint64_t p384_mod_minus_2[6] = { + 0x00000000fffffffdU,0xffffffff00000000U,0xfffffffffffffffeU, + 0xffffffffffffffffU,0xffffffffffffffffU,0xffffffffffffffffU +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P384 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_384_mont_inv_6(sp_digit* r, const sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 6); + for (i=382; i>=0; i--) { + sp_384_mont_sqr_6(t, t, p384_mod, p384_mp_mod); + if (p384_mod_minus_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_384_mont_mul_6(t, t, a, p384_mod, p384_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 6); +#else + sp_digit* t1 = td; + sp_digit* t2 = td + 2 * 6; + sp_digit* t3 = td + 4 * 6; + sp_digit* t4 = td + 6 * 6; + sp_digit* t5 = td + 8 * 6; + + /* 0x2 */ + sp_384_mont_sqr_6(t1, a, p384_mod, p384_mp_mod); + /* 0x3 */ + sp_384_mont_mul_6(t5, t1, a, p384_mod, p384_mp_mod); + /* 0xc */ + sp_384_mont_sqr_n_6(t1, t5, 2, p384_mod, p384_mp_mod); + /* 0xf */ + sp_384_mont_mul_6(t2, t5, t1, p384_mod, p384_mp_mod); + /* 0x1e */ + sp_384_mont_sqr_6(t1, t2, p384_mod, p384_mp_mod); + /* 0x1f */ + sp_384_mont_mul_6(t4, t1, a, p384_mod, p384_mp_mod); + /* 0x3e0 */ + sp_384_mont_sqr_n_6(t1, t4, 5, p384_mod, p384_mp_mod); + /* 0x3ff */ + sp_384_mont_mul_6(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0x7fe0 */ + sp_384_mont_sqr_n_6(t1, t2, 5, p384_mod, p384_mp_mod); + /* 0x7fff */ + sp_384_mont_mul_6(t4, t4, t1, p384_mod, p384_mp_mod); + /* 0x3fff8000 */ + sp_384_mont_sqr_n_6(t1, t4, 15, p384_mod, p384_mp_mod); + /* 0x3fffffff */ + sp_384_mont_mul_6(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffc */ + sp_384_mont_sqr_n_6(t3, t2, 2, p384_mod, p384_mp_mod); + /* 0xfffffffd */ + sp_384_mont_mul_6(r, t3, a, p384_mod, p384_mp_mod); + /* 0xffffffff */ + sp_384_mont_mul_6(t3, t5, t3, p384_mod, p384_mp_mod); + /* 0xfffffffc0000000 */ + sp_384_mont_sqr_n_6(t1, t2, 30, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff */ + sp_384_mont_mul_6(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_6(t1, t2, 60, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_6(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_6(t1, t2, 120, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_6(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_6(t1, t2, 15, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_6(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */ + sp_384_mont_sqr_n_6(t1, t2, 33, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */ + sp_384_mont_mul_6(t2, t3, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_6(t1, t2, 96, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */ + sp_384_mont_mul_6(r, r, t1, p384_mod, p384_mp_mod); + +#endif /* WOLFSSL_SP_SMALL */ +} + +extern int64_t sp_384_cmp_6(const sp_digit* a, const sp_digit* b); +/* Normalize the values in each word to 64. + * + * a Array of sp_digit to normalize. + */ +#define sp_384_norm_6(a) + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_384_map_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*6; + int64_t n; + + sp_384_mont_inv_6(t1, p->z, t + 2*6); + + sp_384_mont_sqr_6(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t1, t2, t1, p384_mod, p384_mp_mod); + + /* x /= z^2 */ + sp_384_mont_mul_6(r->x, p->x, t2, p384_mod, p384_mp_mod); + XMEMSET(r->x + 6, 0, sizeof(r->x) / 2U); + sp_384_mont_reduce_6(r->x, p384_mod, p384_mp_mod); + /* Reduce x to less than modulus */ + n = sp_384_cmp_6(r->x, p384_mod); + sp_384_cond_sub_6(r->x, r->x, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_6(r->x); + + /* y /= z^3 */ + sp_384_mont_mul_6(r->y, p->y, t1, p384_mod, p384_mp_mod); + XMEMSET(r->y + 6, 0, sizeof(r->y) / 2U); + sp_384_mont_reduce_6(r->y, p384_mod, p384_mp_mod); + /* Reduce y to less than modulus */ + n = sp_384_cmp_6(r->y, p384_mod); + sp_384_cond_sub_6(r->y, r->y, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_6(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +extern sp_digit sp_384_add_6(sp_digit* r, const sp_digit* a, const sp_digit* b); +/* 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_384_mont_add_6(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + sp_digit o; + + o = sp_384_add_6(r, a, b); + sp_384_cond_sub_6(r, r, m, 0 - o); +} + +extern sp_digit sp_384_dbl_6(sp_digit* r, const sp_digit* a); +/* 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_384_mont_dbl_6(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_dbl_6(r, a); + sp_384_cond_sub_6(r, r, m, 0 - o); +} + +/* 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_384_mont_tpl_6(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + sp_digit o; + + o = sp_384_dbl_6(r, a); + sp_384_cond_sub_6(r, r, m, 0 - o); + o = sp_384_add_6(r, r, a); + sp_384_cond_sub_6(r, r, m, 0 - o); +} + +extern sp_digit sp_384_sub_6(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern sp_digit sp_384_cond_add_6(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit 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_384_mont_sub_6(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m) +{ + sp_digit o; + + o = sp_384_sub_6(r, a, b); + sp_384_cond_add_6(r, r, m, o); +} + +extern void sp_384_div2_6(sp_digit* r, const sp_digit* a, const sp_digit* m); +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_dbl_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*6; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_384_mont_sqr_6(t1, p->z, p384_mod, p384_mp_mod); + /* Z = Y * Z */ + sp_384_mont_mul_6(z, p->y, p->z, p384_mod, p384_mp_mod); + /* Z = 2Z */ + sp_384_mont_dbl_6(z, z, p384_mod); + /* T2 = X - T1 */ + sp_384_mont_sub_6(t2, p->x, t1, p384_mod); + /* T1 = X + T1 */ + sp_384_mont_add_6(t1, p->x, t1, p384_mod); + /* T2 = T1 * T2 */ + sp_384_mont_mul_6(t2, t1, t2, p384_mod, p384_mp_mod); + /* T1 = 3T2 */ + sp_384_mont_tpl_6(t1, t2, p384_mod); + /* Y = 2Y */ + sp_384_mont_dbl_6(y, p->y, p384_mod); + /* Y = Y * Y */ + sp_384_mont_sqr_6(y, y, p384_mod, p384_mp_mod); + /* T2 = Y * Y */ + sp_384_mont_sqr_6(t2, y, p384_mod, p384_mp_mod); + /* T2 = T2/2 */ + sp_384_div2_6(t2, t2, p384_mod); + /* Y = Y * X */ + sp_384_mont_mul_6(y, y, p->x, p384_mod, p384_mp_mod); + /* X = T1 * T1 */ + sp_384_mont_sqr_6(x, t1, p384_mod, p384_mp_mod); + /* X = X - Y */ + sp_384_mont_sub_6(x, x, y, p384_mod); + /* X = X - Y */ + sp_384_mont_sub_6(x, x, y, p384_mod); + /* Y = Y - X */ + sp_384_mont_sub_6(y, y, x, p384_mod); + /* Y = Y * T1 */ + sp_384_mont_mul_6(y, y, t1, p384_mod, p384_mp_mod); + /* Y = Y - T2 */ + sp_384_mont_sub_6(y, y, t2, p384_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_384_proj_point_dbl_n_6(sp_point_384* p, int n, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*6; + sp_digit* b = t + 4*6; + sp_digit* t1 = t + 6*6; + sp_digit* t2 = t + 8*6; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_384_mont_dbl_6(y, y, p384_mod); + /* W = Z^4 */ + sp_384_mont_sqr_6(w, z, p384_mod, p384_mp_mod); + sp_384_mont_sqr_6(w, w, p384_mod, p384_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_6(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(t1, t1, w, p384_mod); + sp_384_mont_tpl_6(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_6(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_6(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_6(t2, b, p384_mod); + sp_384_mont_sub_6(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_6(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_6(t1, t1, p384_mod, p384_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_384_mont_mul_6(w, w, t1, p384_mod, p384_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_6(y, b, x, p384_mod); + sp_384_mont_mul_6(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_6(y, y, p384_mod); + sp_384_mont_sub_6(y, y, t1, p384_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_6(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(t1, t1, w, p384_mod); + sp_384_mont_tpl_6(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_6(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_6(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_6(t2, b, p384_mod); + sp_384_mont_sub_6(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_6(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_6(t1, t1, p384_mod, p384_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_6(y, b, x, p384_mod); + sp_384_mont_mul_6(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_6(y, y, p384_mod); + sp_384_mont_sub_6(y, y, t1, p384_mod); +#endif + /* Y = Y/2 */ + sp_384_div2_6(y, y, p384_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_384_cmp_equal_6(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])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_6(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, + sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*6; + sp_digit* t3 = t + 4*6; + sp_digit* t4 = t + 6*6; + sp_digit* t5 = t + 8*6; + 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) { + const sp_point_384* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_384_sub_6(t1, p384_mod, q->y); + sp_384_norm_6(t1); + if ((sp_384_cmp_equal_6(p->x, q->x) & sp_384_cmp_equal_6(p->z, q->z) & + (sp_384_cmp_equal_6(p->y, q->y) | sp_384_cmp_equal_6(p->y, t1))) != 0) { + sp_384_proj_point_dbl_6(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<6; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<6; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<6; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_6(t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t3, t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t1, t1, x, p384_mod, p384_mp_mod); + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_6(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_6(t3, t3, y, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_6(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - U1 */ + sp_384_mont_sub_6(t2, t2, t1, p384_mod); + /* R = S2 - S1 */ + sp_384_mont_sub_6(t4, t4, t3, p384_mod); + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_6(z, z, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_6(x, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_6(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(y, t1, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(x, x, t5, p384_mod); + sp_384_mont_dbl_6(t1, y, p384_mod); + sp_384_mont_sub_6(x, x, t1, p384_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_mul_6(y, y, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t5, t5, t3, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(y, y, t5, p384_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_384_proj_point_dbl_n_store_6(sp_point_384* r, const sp_point_384* p, + int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*6; + sp_digit* b = t + 4*6; + sp_digit* t1 = t + 6*6; + sp_digit* t2 = t + 8*6; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + } + for (i=0; i<6; i++) { + y[i] = p->y[i]; + } + for (i=0; i<6; i++) { + z[i] = p->z[i]; + } + + /* Y = 2*Y */ + sp_384_mont_dbl_6(y, y, p384_mod); + /* W = Z^4 */ + sp_384_mont_sqr_6(w, z, p384_mod, p384_mp_mod); + sp_384_mont_sqr_6(w, w, p384_mod, p384_mp_mod); + for (i=1; i<=n; i++) { + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_6(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(t1, t1, w, p384_mod); + sp_384_mont_tpl_6(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_6(t2, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(b, t2, x, p384_mod, p384_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_384_mont_sqr_6(t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t3, t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t1, t1, x, p384_mod, p384_mp_mod); + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_6(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_6(t3, t3, y, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_6(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - U1 */ + sp_384_mont_sub_6(t2, t2, t1, p384_mod); + /* RS = S2 + S1 */ + sp_384_mont_add_6(t6, t4, t3, p384_mod); + /* R = S2 - S1 */ + sp_384_mont_sub_6(t4, t4, t3, p384_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_384_mont_mul_6(z, z, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(z, z, t2, p384_mod, p384_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_384_mont_sqr_6(x, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_6(xs, t6, p384_mod, p384_mp_mod); + sp_384_mont_sqr_6(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(y, t1, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(x, x, t5, p384_mod); + sp_384_mont_sub_6(xs, xs, t5, p384_mod); + sp_384_mont_dbl_6(t1, y, p384_mod); + sp_384_mont_sub_6(x, x, t1, p384_mod); + sp_384_mont_sub_6(xs, xs, t1, p384_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_384_mont_sub_6(ys, y, xs, p384_mod); + sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_mul_6(y, y, t4, p384_mod, p384_mp_mod); + sp_384_sub_6(t6, p384_mod, t6); + sp_384_mont_mul_6(ys, ys, t6, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t5, t5, t3, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(y, y, t5, p384_mod); + sp_384_mont_sub_6(ys, ys, t5, p384_mod); +} + +/* Structure used to describe recoding of scalar multiplication. */ +typedef struct ecc_recode_384 { + /* Index into pre-computation table. */ + uint8_t i; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode_384; + +/* The index into pre-computation table to use. */ +static const uint8_t recode_index_6_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 const uint8_t recode_neg_6_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 perform. + */ +static void sp_384_ecc_recode_6_6(const sp_digit* k, ecc_recode_384* 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<65; i++) { + y = n; + if (o + 6 < 64) { + y &= 0x3f; + n >>= 6; + o += 6; + } + else if (o + 6 == 64) { + n >>= 6; + if (++j < 6) + n = k[j]; + o = 0; + } + else if (++j < 6) { + n = k[j]; + y |= (n << (64 - o)) & 0x3f; + o -= 58; + n >>= o; + } + + y += carry; + v[i].i = recode_index_6_6[y]; + v[i].neg = recode_neg_6_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 coordinates. + * + * 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_384_ecc_mulmod_win_add_sub_6(sp_point_384* r, const sp_point_384* g, + const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td[33]; + sp_point_384 rtd, pd; + sp_digit tmpd[2 * 6 * 6]; +#endif + sp_point_384* t; + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_384 v[65]; + int err; + + (void)heap; + + err = sp_384_point_new_6(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_384_point_new_6(heap, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 33, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 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_384_mod_mul_norm_6(t[1].x, g->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t[1].y, g->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t[1].z, g->z, p384_mod); + } + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[32] */ + sp_384_proj_point_dbl_n_store_6(t, &t[ 1], 5, 1, tmp); + sp_384_proj_point_add_6(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[ 6], &t[ 3], tmp); + sp_384_proj_point_add_sub_6(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[10], &t[ 5], tmp); + sp_384_proj_point_add_sub_6(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[12], &t[ 6], tmp); + sp_384_proj_point_dbl_6(&t[14], &t[ 7], tmp); + sp_384_proj_point_add_sub_6(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[18], &t[ 9], tmp); + sp_384_proj_point_add_sub_6(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[20], &t[10], tmp); + sp_384_proj_point_dbl_6(&t[22], &t[11], tmp); + sp_384_proj_point_add_sub_6(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[24], &t[12], tmp); + sp_384_proj_point_dbl_6(&t[26], &t[13], tmp); + sp_384_proj_point_add_sub_6(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_384_proj_point_dbl_6(&t[28], &t[14], tmp); + sp_384_proj_point_dbl_6(&t[30], &t[15], tmp); + sp_384_proj_point_add_sub_6(&t[31], &t[29], &t[30], &t[ 1], tmp); + + negy = t[0].y; + + sp_384_ecc_recode_6_6(k, v); + + i = 64; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_384)); + for (--i; i>=0; i--) { + sp_384_proj_point_dbl_n_6(rt, 6, tmp); + + XMEMCPY(p, &t[v[i].i], sizeof(sp_point_384)); + sp_384_sub_6(negy, p384_mod, p->y); + sp_384_cond_copy_6(p->y, negy, (sp_digit)0 - v[i].neg); + sp_384_proj_point_add_6(rt, rt, p, tmp); + } + + if (map != 0) { + sp_384_map_6(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + sp_384_point_free_6(p, 0, heap); + sp_384_point_free_6(rt, 0, heap); + + return err; +} + +#ifdef HAVE_INTEL_AVX2 +#ifdef HAVE_INTEL_AVX2 +extern void sp_384_mul_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit* b); +#define sp_384_mont_reduce_avx2_6 sp_384_mont_reduce_6 +extern void sp_384_mont_reduce_order_avx2_6(sp_digit* a, const sp_digit* m, sp_digit mp); +/* 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_384_mont_mul_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit* b, + const sp_digit* m, sp_digit mp) +{ + sp_384_mul_avx2_6(r, a, b); + sp_384_mont_reduce_avx2_6(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +extern void sp_384_sqr_avx2_6(sp_digit* r, const sp_digit* a); +/* 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_384_mont_sqr_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit* m, + sp_digit mp) +{ + sp_384_sqr_avx2_6(r, a); + sp_384_mont_reduce_avx2_6(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* 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_384_mont_sqr_n_avx2_6(sp_digit* r, const sp_digit* a, int n, + const sp_digit* m, sp_digit mp) +{ + sp_384_mont_sqr_avx2_6(r, a, m, mp); + for (; n > 1; n--) { + sp_384_mont_sqr_avx2_6(r, r, m, mp); + } +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P384 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_384_mont_inv_avx2_6(sp_digit* r, const sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 6); + for (i=382; i>=0; i--) { + sp_384_mont_sqr_avx2_6(t, t, p384_mod, p384_mp_mod); + if (p384_mod_minus_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_384_mont_mul_avx2_6(t, t, a, p384_mod, p384_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 6); +#else + sp_digit* t1 = td; + sp_digit* t2 = td + 2 * 6; + sp_digit* t3 = td + 4 * 6; + sp_digit* t4 = td + 6 * 6; + sp_digit* t5 = td + 8 * 6; + + /* 0x2 */ + sp_384_mont_sqr_avx2_6(t1, a, p384_mod, p384_mp_mod); + /* 0x3 */ + sp_384_mont_mul_avx2_6(t5, t1, a, p384_mod, p384_mp_mod); + /* 0xc */ + sp_384_mont_sqr_n_avx2_6(t1, t5, 2, p384_mod, p384_mp_mod); + /* 0xf */ + sp_384_mont_mul_avx2_6(t2, t5, t1, p384_mod, p384_mp_mod); + /* 0x1e */ + sp_384_mont_sqr_avx2_6(t1, t2, p384_mod, p384_mp_mod); + /* 0x1f */ + sp_384_mont_mul_avx2_6(t4, t1, a, p384_mod, p384_mp_mod); + /* 0x3e0 */ + sp_384_mont_sqr_n_avx2_6(t1, t4, 5, p384_mod, p384_mp_mod); + /* 0x3ff */ + sp_384_mont_mul_avx2_6(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0x7fe0 */ + sp_384_mont_sqr_n_avx2_6(t1, t2, 5, p384_mod, p384_mp_mod); + /* 0x7fff */ + sp_384_mont_mul_avx2_6(t4, t4, t1, p384_mod, p384_mp_mod); + /* 0x3fff8000 */ + sp_384_mont_sqr_n_avx2_6(t1, t4, 15, p384_mod, p384_mp_mod); + /* 0x3fffffff */ + sp_384_mont_mul_avx2_6(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffc */ + sp_384_mont_sqr_n_avx2_6(t3, t2, 2, p384_mod, p384_mp_mod); + /* 0xfffffffd */ + sp_384_mont_mul_avx2_6(r, t3, a, p384_mod, p384_mp_mod); + /* 0xffffffff */ + sp_384_mont_mul_avx2_6(t3, t5, t3, p384_mod, p384_mp_mod); + /* 0xfffffffc0000000 */ + sp_384_mont_sqr_n_avx2_6(t1, t2, 30, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff */ + sp_384_mont_mul_avx2_6(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_avx2_6(t1, t2, 60, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_avx2_6(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_avx2_6(t1, t2, 120, p384_mod, p384_mp_mod); + /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_avx2_6(t2, t2, t1, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_avx2_6(t1, t2, 15, p384_mod, p384_mp_mod); + /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_avx2_6(t2, t4, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */ + sp_384_mont_sqr_n_avx2_6(t1, t2, 33, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */ + sp_384_mont_mul_avx2_6(t2, t3, t1, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_avx2_6(t1, t2, 96, p384_mod, p384_mp_mod); + /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */ + sp_384_mont_mul_avx2_6(r, r, t1, p384_mod, p384_mp_mod); + +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective coordinate point to an affine point. + * + * r Resulting affine coordinate point. + * p Montgomery form projective coordinate point. + * t Temporary ordinate data. + */ +static void sp_384_map_avx2_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*6; + int64_t n; + + sp_384_mont_inv_avx2_6(t1, p->z, t + 2*6); + + sp_384_mont_sqr_avx2_6(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t1, t2, t1, p384_mod, p384_mp_mod); + + /* x /= z^2 */ + sp_384_mont_mul_avx2_6(r->x, p->x, t2, p384_mod, p384_mp_mod); + XMEMSET(r->x + 6, 0, sizeof(r->x) / 2U); + sp_384_mont_reduce_6(r->x, p384_mod, p384_mp_mod); + /* Reduce x to less than modulus */ + n = sp_384_cmp_6(r->x, p384_mod); + sp_384_cond_sub_6(r->x, r->x, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_6(r->x); + + /* y /= z^3 */ + sp_384_mont_mul_avx2_6(r->y, p->y, t1, p384_mod, p384_mp_mod); + XMEMSET(r->y + 6, 0, sizeof(r->y) / 2U); + sp_384_mont_reduce_6(r->y, p384_mod, p384_mp_mod); + /* Reduce y to less than modulus */ + n = sp_384_cmp_6(r->y, p384_mod); + sp_384_cond_sub_6(r->y, r->y, p384_mod, 0 - ((n >= 0) ? + (sp_digit)1 : (sp_digit)0)); + sp_384_norm_6(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_384_proj_point_dbl_avx2_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*6; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = r->x; + y = r->y; + z = r->z; + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_384_mont_sqr_avx2_6(t1, p->z, p384_mod, p384_mp_mod); + /* Z = Y * Z */ + sp_384_mont_mul_avx2_6(z, p->y, p->z, p384_mod, p384_mp_mod); + /* Z = 2Z */ + sp_384_mont_dbl_6(z, z, p384_mod); + /* T2 = X - T1 */ + sp_384_mont_sub_6(t2, p->x, t1, p384_mod); + /* T1 = X + T1 */ + sp_384_mont_add_6(t1, p->x, t1, p384_mod); + /* T2 = T1 * T2 */ + sp_384_mont_mul_avx2_6(t2, t1, t2, p384_mod, p384_mp_mod); + /* T1 = 3T2 */ + sp_384_mont_tpl_6(t1, t2, p384_mod); + /* Y = 2Y */ + sp_384_mont_dbl_6(y, p->y, p384_mod); + /* Y = Y * Y */ + sp_384_mont_sqr_avx2_6(y, y, p384_mod, p384_mp_mod); + /* T2 = Y * Y */ + sp_384_mont_sqr_avx2_6(t2, y, p384_mod, p384_mp_mod); + /* T2 = T2/2 */ + sp_384_div2_6(t2, t2, p384_mod); + /* Y = Y * X */ + sp_384_mont_mul_avx2_6(y, y, p->x, p384_mod, p384_mp_mod); + /* X = T1 * T1 */ + sp_384_mont_sqr_avx2_6(x, t1, p384_mod, p384_mp_mod); + /* X = X - Y */ + sp_384_mont_sub_6(x, x, y, p384_mod); + /* X = X - Y */ + sp_384_mont_sub_6(x, x, y, p384_mod); + /* Y = Y - X */ + sp_384_mont_sub_6(y, y, x, p384_mod); + /* Y = Y * T1 */ + sp_384_mont_mul_avx2_6(y, y, t1, p384_mod, p384_mp_mod); + /* Y = Y - T2 */ + sp_384_mont_sub_6(y, y, t2, p384_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_384_proj_point_dbl_n_avx2_6(sp_point_384* p, int n, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*6; + sp_digit* b = t + 4*6; + sp_digit* t1 = t + 6*6; + sp_digit* t2 = t + 8*6; + sp_digit* x; + sp_digit* y; + sp_digit* z; + + x = p->x; + y = p->y; + z = p->z; + + /* Y = 2*Y */ + sp_384_mont_dbl_6(y, y, p384_mod); + /* W = Z^4 */ + sp_384_mont_sqr_avx2_6(w, z, p384_mod, p384_mp_mod); + sp_384_mont_sqr_avx2_6(w, w, p384_mod, p384_mp_mod); + +#ifndef WOLFSSL_SP_SMALL + while (--n > 0) +#else + while (--n >= 0) +#endif + { + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_avx2_6(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(t1, t1, w, p384_mod); + sp_384_mont_tpl_6(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_avx2_6(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_avx2_6(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_6(t2, b, p384_mod); + sp_384_mont_sub_6(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_avx2_6(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_avx2_6(t1, t1, p384_mod, p384_mp_mod); +#ifdef WOLFSSL_SP_SMALL + if (n != 0) +#endif + { + /* W = W*Y^4 */ + sp_384_mont_mul_avx2_6(w, w, t1, p384_mod, p384_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_6(y, b, x, p384_mod); + sp_384_mont_mul_avx2_6(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_6(y, y, p384_mod); + sp_384_mont_sub_6(y, y, t1, p384_mod); + } +#ifndef WOLFSSL_SP_SMALL + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_avx2_6(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(t1, t1, w, p384_mod); + sp_384_mont_tpl_6(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_avx2_6(t1, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(b, t1, x, p384_mod, p384_mp_mod); + /* X = A^2 - 2B */ + sp_384_mont_sqr_avx2_6(x, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_6(t2, b, p384_mod); + sp_384_mont_sub_6(x, x, t2, p384_mod); + /* Z = Z*Y */ + sp_384_mont_mul_avx2_6(z, z, y, p384_mod, p384_mp_mod); + /* t2 = Y^4 */ + sp_384_mont_sqr_avx2_6(t1, t1, p384_mod, p384_mp_mod); + /* y = 2*A*(B - X) - Y^4 */ + sp_384_mont_sub_6(y, b, x, p384_mod); + sp_384_mont_mul_avx2_6(y, y, a, p384_mod, p384_mp_mod); + sp_384_mont_dbl_6(y, y, p384_mod); + sp_384_mont_sub_6(y, y, t1, p384_mod); +#endif + /* Y = Y/2 */ + sp_384_div2_6(y, y, p384_mod); +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_avx2_6(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, + sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*6; + sp_digit* t3 = t + 4*6; + sp_digit* t4 = t + 6*6; + sp_digit* t5 = t + 8*6; + 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) { + const sp_point_384* a = p; + p = q; + q = a; + } + + /* Check double */ + (void)sp_384_sub_6(t1, p384_mod, q->y); + sp_384_norm_6(t1); + if ((sp_384_cmp_equal_6(p->x, q->x) & sp_384_cmp_equal_6(p->z, q->z) & + (sp_384_cmp_equal_6(p->y, q->y) | sp_384_cmp_equal_6(p->y, t1))) != 0) { + sp_384_proj_point_dbl_6(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<6; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<6; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<6; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_avx2_6(t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t3, t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t1, t1, x, p384_mod, p384_mp_mod); + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_avx2_6(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_avx2_6(t3, t3, y, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_avx2_6(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - U1 */ + sp_384_mont_sub_6(t2, t2, t1, p384_mod); + /* R = S2 - S1 */ + sp_384_mont_sub_6(t4, t4, t3, p384_mod); + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_avx2_6(z, z, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_avx2_6(x, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_avx2_6(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(y, t1, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(x, x, t5, p384_mod); + sp_384_mont_dbl_6(t1, y, p384_mod); + sp_384_mont_sub_6(x, x, t1, p384_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_mul_avx2_6(y, y, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t5, t5, t3, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(y, y, t5, p384_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_384_proj_point_dbl_n_store_avx2_6(sp_point_384* r, const sp_point_384* p, + int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*6; + sp_digit* b = t + 4*6; + sp_digit* t1 = t + 6*6; + sp_digit* t2 = t + 8*6; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + } + for (i=0; i<6; i++) { + y[i] = p->y[i]; + } + for (i=0; i<6; i++) { + z[i] = p->z[i]; + } + + /* Y = 2*Y */ + sp_384_mont_dbl_6(y, y, p384_mod); + /* W = Z^4 */ + sp_384_mont_sqr_avx2_6(w, z, p384_mod, p384_mp_mod); + sp_384_mont_sqr_avx2_6(w, w, p384_mod, p384_mp_mod); + for (i=1; i<=n; i++) { + /* A = 3*(X^2 - W) */ + sp_384_mont_sqr_avx2_6(t1, x, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(t1, t1, w, p384_mod); + sp_384_mont_tpl_6(a, t1, p384_mod); + /* B = X*Y^2 */ + sp_384_mont_sqr_avx2_6(t2, y, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(b, t2, x, p384_mod, p384_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_384_mont_sqr_avx2_6(t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t3, t1, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t1, t1, x, p384_mod, p384_mp_mod); + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_avx2_6(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_avx2_6(t3, t3, y, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_avx2_6(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - U1 */ + sp_384_mont_sub_6(t2, t2, t1, p384_mod); + /* RS = S2 + S1 */ + sp_384_mont_add_6(t6, t4, t3, p384_mod); + /* R = S2 - S1 */ + sp_384_mont_sub_6(t4, t4, t3, p384_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_384_mont_mul_avx2_6(z, z, q->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(z, z, t2, p384_mod, p384_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_384_mont_sqr_avx2_6(x, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_avx2_6(xs, t6, p384_mod, p384_mp_mod); + sp_384_mont_sqr_avx2_6(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(y, t1, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(x, x, t5, p384_mod); + sp_384_mont_sub_6(xs, xs, t5, p384_mod); + sp_384_mont_dbl_6(t1, y, p384_mod); + sp_384_mont_sub_6(x, x, t1, p384_mod); + sp_384_mont_sub_6(xs, xs, t1, p384_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_384_mont_sub_6(ys, y, xs, p384_mod); + sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_mul_avx2_6(y, y, t4, p384_mod, p384_mp_mod); + sp_384_sub_6(t6, p384_mod, t6); + sp_384_mont_mul_avx2_6(ys, ys, t6, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t5, t5, t3, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(y, y, t5, p384_mod); + sp_384_mont_sub_6(ys, ys, t5, p384_mod); +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_win_add_sub_avx2_6(sp_point_384* r, const sp_point_384* g, + const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td[33]; + sp_point_384 rtd, pd; + sp_digit tmpd[2 * 6 * 6]; +#endif + sp_point_384* t; + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_384 v[65]; + int err; + + (void)heap; + + err = sp_384_point_new_6(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_384_point_new_6(heap, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 33, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 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_384_mod_mul_norm_6(t[1].x, g->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t[1].y, g->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t[1].z, g->z, p384_mod); + } + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[32] */ + sp_384_proj_point_dbl_n_store_avx2_6(t, &t[ 1], 5, 1, tmp); + sp_384_proj_point_add_avx2_6(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_384_proj_point_dbl_avx2_6(&t[ 6], &t[ 3], tmp); + sp_384_proj_point_add_sub_avx2_6(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_384_proj_point_dbl_avx2_6(&t[10], &t[ 5], tmp); + sp_384_proj_point_add_sub_avx2_6(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_384_proj_point_dbl_avx2_6(&t[12], &t[ 6], tmp); + sp_384_proj_point_dbl_avx2_6(&t[14], &t[ 7], tmp); + sp_384_proj_point_add_sub_avx2_6(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_384_proj_point_dbl_avx2_6(&t[18], &t[ 9], tmp); + sp_384_proj_point_add_sub_avx2_6(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_384_proj_point_dbl_avx2_6(&t[20], &t[10], tmp); + sp_384_proj_point_dbl_avx2_6(&t[22], &t[11], tmp); + sp_384_proj_point_add_sub_avx2_6(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_384_proj_point_dbl_avx2_6(&t[24], &t[12], tmp); + sp_384_proj_point_dbl_avx2_6(&t[26], &t[13], tmp); + sp_384_proj_point_add_sub_avx2_6(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_384_proj_point_dbl_avx2_6(&t[28], &t[14], tmp); + sp_384_proj_point_dbl_avx2_6(&t[30], &t[15], tmp); + sp_384_proj_point_add_sub_avx2_6(&t[31], &t[29], &t[30], &t[ 1], tmp); + + negy = t[0].y; + + sp_384_ecc_recode_6_6(k, v); + + i = 64; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_384)); + for (--i; i>=0; i--) { + sp_384_proj_point_dbl_n_avx2_6(rt, 6, tmp); + + XMEMCPY(p, &t[v[i].i], sizeof(sp_point_384)); + sp_384_sub_6(negy, p384_mod, p->y); + sp_384_cond_copy_6(p->y, negy, (sp_digit)0 - v[i].neg); + sp_384_proj_point_add_avx2_6(rt, rt, p, tmp); + } + + if (map != 0) { + sp_384_map_avx2_6(r, rt, tmp); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + sp_384_point_free_6(p, 0, heap); + sp_384_point_free_6(rt, 0, heap); + + return err; +} + +#endif /* HAVE_INTEL_AVX2 */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_384 { + sp_digit x[6]; + sp_digit y[6]; +} sp_table_entry_384; + +#ifdef FP_ECC +#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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_qz1_6(sp_point_384* r, const sp_point_384* p, + const sp_point_384* q, sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*6; + sp_digit* t3 = t + 4*6; + sp_digit* t4 = t + 6*6; + sp_digit* t5 = t + 8*6; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_384_sub_6(t1, p384_mod, q->y); + sp_384_norm_6(t1); + if ((sp_384_cmp_equal_6(p->x, q->x) & sp_384_cmp_equal_6(p->z, q->z) & + (sp_384_cmp_equal_6(p->y, q->y) | sp_384_cmp_equal_6(p->y, t1))) != 0) { + sp_384_proj_point_dbl_6(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<6; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<6; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<6; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_6(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_6(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - X1 */ + sp_384_mont_sub_6(t2, t2, x, p384_mod); + /* R = S2 - Y1 */ + sp_384_mont_sub_6(t4, t4, y, p384_mod); + /* Z3 = H*Z1 */ + sp_384_mont_mul_6(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_384_mont_sqr_6(t1, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_6(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t3, x, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(x, t1, t5, p384_mod); + sp_384_mont_dbl_6(t1, t3, p384_mod); + sp_384_mont_sub_6(x, x, t1, p384_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_384_mont_sub_6(t3, t3, x, p384_mod); + sp_384_mont_mul_6(t3, t3, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t5, t5, y, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(y, t3, t5, p384_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_384_proj_to_affine_6(sp_point_384* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 6; + sp_digit* tmp = t + 4 * 6; + + sp_384_mont_inv_6(t1, a->z, tmp); + + sp_384_mont_sqr_6(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(t1, t2, t1, p384_mod, p384_mp_mod); + + sp_384_mont_mul_6(a->x, a->x, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(a->y, a->y, t1, p384_mod, p384_mp_mod); + XMEMCPY(a->z, p384_norm_mod, sizeof(p384_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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_384_gen_stripe_table_6(const sp_point_384* a, + sp_table_entry_384* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td, s1d, s2d; +#endif + sp_point_384* t; + sp_point_384* s1 = NULL; + sp_point_384* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_384_point_new_6(heap, td, t); + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t->x, a->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t->y, a->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t->z, a->z, p384_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_384_proj_to_affine_6(t, tmp); + + XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_384)); + /* 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)); + + for (i=1; i<8; i++) { + sp_384_proj_point_dbl_n_6(t, 48, tmp); + sp_384_proj_to_affine_6(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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_384_proj_point_add_qz1_6(t, s1, s2, tmp); + sp_384_proj_to_affine_6(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_384_point_free_6(s2, 0, heap); + sp_384_point_free_6(s1, 0, heap); + sp_384_point_free_6( 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 coordinates. + * + * 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_384_ecc_mulmod_stripe_6(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 rtd; + sp_point_384 pd; + sp_digit td[2 * 6 * 6]; +#endif + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_384_point_new_6(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + y = 0; + for (j=0,x=47; j<8; j++,x+=48) { + 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 = !y; + for (i=46; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=48) { + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + } + + sp_384_proj_point_dbl_6(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 = !y; + sp_384_proj_point_add_qz1_6(rt, rt, p, t); + } + + if (map != 0) { + sp_384_map_6(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(p, 0, heap); + sp_384_point_free_6(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_384_t { + sp_digit x[6]; + sp_digit y[6]; + sp_table_entry_384 table[256]; + uint32_t cnt; + int set; +} sp_cache_384_t; + +static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_384_last = -1; +static THREAD_LS_T int sp_cache_384_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex_384 = 0; + static wolfSSL_Mutex sp_cache_384_lock; +#endif + +static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_384_inited == 0) { + for (i=0; ix, sp_cache_384[i].x) & + sp_384_cmp_equal_6(g->y, sp_cache_384[i].y)) { + sp_cache_384[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_384_last + 1) % FP_ENTRIES; + for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache_384[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_384_last) { + least = sp_cache_384[0].cnt; + for (j=1; jx, sizeof(sp_cache_384[i].x)); + XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y)); + sp_cache_384[i].set = 1; + sp_cache_384[i].cnt = 1; + } + + *cache = &sp_cache_384[i]; + sp_cache_384_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_6(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_384_ecc_mulmod_win_add_sub_6(r, g, k, map, heap); +#else + sp_digit tmp[2 * 6 * 7]; + sp_cache_384_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_384 == 0) { + wc_InitMutex(&sp_cache_384_lock); + initCacheMutex_384 = 1; + } + if (wc_LockMutex(&sp_cache_384_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_384(g, &cache); + if (cache->cnt == 2) + sp_384_gen_stripe_table_6(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_384_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_384_ecc_mulmod_win_add_sub_6(r, g, k, map, heap); + } + else { + err = sp_384_ecc_mulmod_stripe_6(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#ifdef HAVE_INTEL_AVX2 +#ifdef FP_ECC +#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 First point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_384_proj_point_add_qz1_avx2_6(sp_point_384* r, const sp_point_384* p, + const sp_point_384* q, sp_digit* t) +{ + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*6; + sp_digit* t3 = t + 4*6; + sp_digit* t4 = t + 6*6; + sp_digit* t5 = t + 8*6; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + (void)sp_384_sub_6(t1, p384_mod, q->y); + sp_384_norm_6(t1); + if ((sp_384_cmp_equal_6(p->x, q->x) & sp_384_cmp_equal_6(p->z, q->z) & + (sp_384_cmp_equal_6(p->y, q->y) | sp_384_cmp_equal_6(p->y, t1))) != 0) { + sp_384_proj_point_dbl_6(r, p, t); + } + else { + rp[0] = r; + + /*lint allow cast to different type of pointer*/ + rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(rp[1], 0, sizeof(sp_point_384)); + 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<6; i++) { + r->x[i] = ap[p->infinity]->x[i]; + } + for (i=0; i<6; i++) { + r->y[i] = ap[p->infinity]->y[i]; + } + for (i=0; i<6; i++) { + r->z[i] = ap[p->infinity]->z[i]; + } + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_avx2_6(t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t4, t2, z, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t2, t2, q->x, p384_mod, p384_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_avx2_6(t4, t4, q->y, p384_mod, p384_mp_mod); + /* H = U2 - X1 */ + sp_384_mont_sub_6(t2, t2, x, p384_mod); + /* R = S2 - Y1 */ + sp_384_mont_sub_6(t4, t4, y, p384_mod); + /* Z3 = H*Z1 */ + sp_384_mont_mul_avx2_6(z, z, t2, p384_mod, p384_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_384_mont_sqr_avx2_6(t1, t4, p384_mod, p384_mp_mod); + sp_384_mont_sqr_avx2_6(t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t3, x, t5, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t5, t5, t2, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(x, t1, t5, p384_mod); + sp_384_mont_dbl_6(t1, t3, p384_mod); + sp_384_mont_sub_6(x, x, t1, p384_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_384_mont_sub_6(t3, t3, x, p384_mod); + sp_384_mont_mul_avx2_6(t3, t3, t4, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t5, t5, y, p384_mod, p384_mp_mod); + sp_384_mont_sub_6(y, t3, t5, p384_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temporary data. + */ +static void sp_384_proj_to_affine_avx2_6(sp_point_384* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 6; + sp_digit* tmp = t + 4 * 6; + + sp_384_mont_inv_avx2_6(t1, a->z, tmp); + + sp_384_mont_sqr_avx2_6(t2, t1, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(t1, t2, t1, p384_mod, p384_mp_mod); + + sp_384_mont_mul_avx2_6(a->x, a->x, t2, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(a->y, a->y, t1, p384_mod, p384_mp_mod); + XMEMCPY(a->z, p384_norm_mod, sizeof(p384_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 Temporary data. + * heap Heap to use for allocation. + */ +static int sp_384_gen_stripe_table_avx2_6(const sp_point_384* a, + sp_table_entry_384* table, sp_digit* tmp, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 td, s1d, s2d; +#endif + sp_point_384* t; + sp_point_384* s1 = NULL; + sp_point_384* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_384_point_new_6(heap, td, t); + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, s1d, s1); + } + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, s2d, s2); + } + + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t->x, a->x, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t->y, a->y, p384_mod); + } + if (err == MP_OKAY) { + err = sp_384_mod_mul_norm_6(t->z, a->z, p384_mod); + } + if (err == MP_OKAY) { + t->infinity = 0; + sp_384_proj_to_affine_avx2_6(t, tmp); + + XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry_384)); + /* 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)); + + for (i=1; i<8; i++) { + sp_384_proj_point_dbl_n_avx2_6(t, 48, tmp); + sp_384_proj_to_affine_avx2_6(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + } + + for (i=1; i<8; i++) { + XMEMCPY(s1->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_384_proj_point_add_qz1_avx2_6(t, s1, s2, tmp); + sp_384_proj_to_affine_avx2_6(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + } + } + } + + sp_384_point_free_6(s2, 0, heap); + sp_384_point_free_6(s1, 0, heap); + sp_384_point_free_6( 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 coordinates. + * + * 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_384_ecc_mulmod_stripe_avx2_6(sp_point_384* r, const sp_point_384* g, + const sp_table_entry_384* table, const sp_digit* k, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 rtd; + sp_point_384 pd; + sp_digit td[2 * 6 * 6]; +#endif + sp_point_384* rt; + sp_point_384* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + + err = sp_384_point_new_6(heap, rtd, rt); + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) { + err = MEMORY_E; + } +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod)); + XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod)); + + y = 0; + for (j=0,x=47; j<8; j++,x+=48) { + 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 = !y; + for (i=46; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=48) { + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + } + + sp_384_proj_point_dbl_avx2_6(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 = !y; + sp_384_proj_point_add_qz1_avx2_6(rt, rt, p, t); + } + + if (map != 0) { + sp_384_map_avx2_6(r, rt, t); + } + else { + XMEMCPY(r, rt, sizeof(sp_point_384)); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) { + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(p, 0, heap); + sp_384_point_free_6(rt, 0, heap); + + return err; +} + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_avx2_6(sp_point_384* r, const sp_point_384* g, const sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_384_ecc_mulmod_win_add_sub_avx2_6(r, g, k, map, heap); +#else + sp_digit tmp[2 * 6 * 7]; + sp_cache_384_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex_384 == 0) { + wc_InitMutex(&sp_cache_384_lock); + initCacheMutex_384 = 1; + } + if (wc_LockMutex(&sp_cache_384_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache_384(g, &cache); + if (cache->cnt == 2) + sp_384_gen_stripe_table_avx2_6(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_384_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_384_ecc_mulmod_win_add_sub_avx2_6(r, g, k, map, heap); + } + else { + err = sp_384_ecc_mulmod_stripe_avx2_6(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 coordinates. + * + * 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_384(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[6]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_384_point_new_6(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 6, km); + sp_384_point_from_ecc_point_6(point, gm); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_avx2_6(point, point, k, map, heap); + else +#endif + err = sp_384_ecc_mulmod_6(point, point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_6(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(point, 0, heap); + + return err; +} + +static const sp_table_entry_384 p384_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + /* 1 */ + { { 0x3dd0756649c0b528L,0x20e378e2a0d6ce38L,0x879c3afc541b4d6eL, + 0x6454868459a30effL,0x812ff723614ede2bL,0x4d3aadc2299e1513L }, + { 0x23043dad4b03a4feL,0xa1bfa8bf7bb4a9acL,0x8bade7562e83b050L, + 0xc6c3521968f4ffd9L,0xdd8002263969a840L,0x2b78abc25a15c5e9L } }, + /* 2 */ + { { 0x298647532b0c535bL,0x90dd695370506296L,0x038cd6b4216ab9acL, + 0x3df9b7b7be12d76aL,0x13f4d9785f347bdbL,0x222c5c9c13e94489L }, + { 0x5f8e796f2680dc64L,0x120e7cb758352417L,0x254b5d8ad10740b8L, + 0xc38b8efb5337dee6L,0xf688c2e194f02247L,0x7b5c75f36c25bc4cL } }, + /* 3 */ + { { 0xe26a3cc39edffea5L,0x35bbfd1c37d7e9fcL,0xf0e7700d9bde3ef6L, + 0x0380eb471a538f5aL,0x2e9da8bb05bf9eb3L,0xdbb93c731a460c3eL }, + { 0x37dba260f526b605L,0x95d4978efd785537L,0x24ed793aed72a04aL, + 0x2694837776005b1aL,0x99f557b99e681f82L,0xae5f9557d64954efL } }, + /* 4 */ + { { 0x24480c57f26feef9L,0xc31a26943a0e1240L,0x735002c3273e2bc7L, + 0x8c42e9c53ef1ed4cL,0x028babf67f4948e8L,0x6a502f438a978632L }, + { 0xf5f13a46b74536feL,0x1d218babd8a9f0ebL,0x30f36bcc37232768L, + 0xc5317b31576e8c18L,0xef1d57a69bbcb766L,0x917c4930b3e3d4dcL } }, + /* 5 */ + { { 0x11426e2ee349ddd0L,0x9f117ef99b2fc250L,0xff36b480ec0174a6L, + 0x4f4bde7618458466L,0x2f2edb6d05806049L,0x8adc75d119dfca92L }, + { 0xa619d097b7d5a7ceL,0x874275e5a34411e9L,0x5403e0470da4b4efL, + 0x2ebaafd977901d8fL,0x5e63ebcea747170fL,0x12a369447f9d8036L } }, + /* 6 */ + { { 0x28f9c07a4fc52870L,0xce0b37481a53a961L,0xd550fa180e1828d9L, + 0xa24abaf76adb225aL,0xd11ed0a56e58a348L,0xf3d811e6948acb62L }, + { 0x8618dd774c61ed22L,0x0bb747f980b47c9dL,0x22bf796fde6b8559L, + 0xfdfd1c6d680a21e9L,0xc0db15772af2c9ddL,0xa09379e6c1e90f3dL } }, + /* 7 */ + { { 0x386c66efe085c629L,0x5fc2a461095bc89aL,0x1353d631203f4b41L, + 0x7ca1972b7e4bd8f5L,0xb077380aa7df8ce9L,0xd8a90389ee7e4ea3L }, + { 0x1bc74dc7e7b14461L,0xdc2cb0140c9c4f78L,0x52b4b3a684ef0a10L, + 0xbde6ea5d20327fe2L,0xb71ec435660f9615L,0xeede5a04b8ad8173L } }, + /* 8 */ + { { 0x5584cbb3893b9a2dL,0x820c660b00850c5dL,0x4126d8267df2d43dL, + 0xdd5bbbf00109e801L,0x85b92ee338172f1cL,0x609d4f93f31430d9L }, + { 0x1e059a07eadaf9d6L,0x70e6536c0f125fb0L,0xd6220751560f20e7L, + 0xa59489ae7aaf3a9aL,0x7b70e2f664bae14eL,0x0dd0370176d08249L } }, + /* 9 */ + { { 0x4cc13be88510521fL,0x87315ba9f724cc17L,0xb49d83bb353dc263L, + 0x8b677efe0c279257L,0x510a1c1cc93c9537L,0x33e30cd8a4702c99L }, + { 0xf0ffc89d2208353fL,0x0170fa8dced42b2bL,0x090851ed26e2a5f5L, + 0x81276455ecb52c96L,0x0646c4e17fe1adf4L,0x513f047eb0868eabL } }, + /* 10 */ + { { 0xc07611f4df5bdf53L,0x45d331a758b11a6dL,0x58965daf1c4ee394L, + 0xba8bebe75a5878d1L,0xaecc0a1882dd3025L,0xcf2a3899a923eb8bL }, + { 0xf98c9281d24fd048L,0x841bfb598bbb025dL,0xb8ddf8cec9ab9d53L, + 0x538a4cb67fef044eL,0x092ac21f23236662L,0xa919d3850b66f065L } }, + /* 11 */ + { { 0x3db03b4085d480d8L,0x8cd9f4791b287a7dL,0x8f24dc754a8f3baeL, + 0x482eb8003db41892L,0x38bf9eb39c56e0f5L,0x8b9773209a91dc6fL }, + { 0xa31b05b27209cfc2L,0x4c49bf8505b2db70L,0x56462498d619527bL, + 0x3fe510391fac51baL,0xfb04f55eab4b8342L,0xc07c10dc04c6eabfL } }, + /* 12 */ + { { 0xad22fe4cdb32f048L,0x5f23bf91475ed6dfL,0xa50ce0c0aa66b6cbL, + 0xdf627a89f03405c0L,0x3674837df95e2d6aL,0x081c95b6ba42e64eL }, + { 0xeba3e036e71d6cebL,0xb45bcccf6c6b0271L,0x67b47e630684701dL, + 0x60f8f942e712523fL,0x824234725cd47adcL,0x83027d7987649cbbL } }, + /* 13 */ + { { 0xb3929ea63615b0b8L,0xb41441fda54dac41L,0x8995d556b5b6a368L, + 0xa80d4529167ef05eL,0xf6bcb4a16d25a27fL,0x210d6a4c7bd55b68L }, + { 0xf3804abb25351130L,0x1d2df699903e37ebL,0x5f201efc084c25c8L, + 0x31a28c87a1c68e91L,0x81dad253563f62a5L,0x5dd6de70d6c415d4L } }, + /* 14 */ + { { 0x29f470fd846612ceL,0x986f3eecda18d997L,0x6b84c1612f34af86L, + 0x5ef0a40846ddaf8bL,0x14405a00e49e795fL,0x5f491b16aa2f7a37L }, + { 0xc7f07ae4db41b38dL,0xef7d119e18fbfcaaL,0x3a18e07614443b19L, + 0x4356841a79a19926L,0x91f4a91ce2226fbeL,0xdc77248c3cc88721L } }, + /* 15 */ + { { 0xd570ff1ae4b1ec9dL,0x21d23e0ee7eef706L,0x3cde40f4ca19e086L, + 0x7d6523c4cd4bb270L,0x16c1f06cbf13aa6cL,0x5aa7245ad14c4b60L }, + { 0x37f8146744b74de8L,0x839e7a17620a934eL,0xf74d14e8de8b1aa1L, + 0x8789fa51f30d75e2L,0x09b24052c81c261eL,0x654e267833c565eeL } }, + /* 16 */ + { { 0x378205de2f9fbe67L,0xc4afcb837f728e44L,0xdbcec06c682e00f1L, + 0xf2a145c3114d5423L,0xa01d98747a52463eL,0xfc0935b17d717b0aL }, + { 0x9653bc4fd4d01f95L,0x9aa83ea89560ad34L,0xf77943dcaf8e3f3fL, + 0x70774a10e86fe16eL,0x6b62e6f1bf9ffdcfL,0x8a72f39e588745c9L } }, + /* 17 */ + { { 0x73ade4da2341c342L,0xdd326e54ea704422L,0x336c7d983741cef3L, + 0x1eafa00d59e61549L,0xcd3ed892bd9a3efdL,0x03faf26cc5c6c7e4L }, + { 0x087e2fcf3045f8acL,0x14a65532174f1e73L,0x2cf84f28fe0af9a7L, + 0xddfd7a842cdc935bL,0x4c0f117b6929c895L,0x356572d64c8bcfccL } }, + /* 18 */ + { { 0x7ecbac017d8c1bbaL,0x6058f9c390b0f3d5L,0xaee116e3f6197d0fL, + 0xc4dd70684033b128L,0xf084dba6c209b983L,0x97c7c2cf831dbc4aL }, + { 0x2f4e61ddf96010e8L,0xd97e4e20529faa17L,0x4ee6666069d37f20L, + 0xccc139ed3d366d72L,0x690b6ee213488e0fL,0x7cad1dc5f3a6d533L } }, + /* 19 */ + { { 0x660a9a81da57a41fL,0xe74a0412ec0039b6L,0x42343c6b5e1dad15L, + 0x284f3ff546681d4cL,0xb51087f163749e89L,0x070f23cc6f9f2f13L }, + { 0x542211da5d186e14L,0x84748f37fddb0dffL,0x41a3aab4db1f4180L, + 0x25ed667ba6402d0eL,0x2f2924a902f58355L,0x5844ee7cfa44a689L } }, + /* 20 */ + { { 0xfab086073f3b236fL,0x19e9d41d81e221daL,0xf3f6571e3927b428L, + 0x4348a9337550f1f6L,0x7167b996a85e62f0L,0x62d437597f5452bfL }, + { 0xd85feb9ef2955926L,0x440a561f6df78353L,0x389668ec9ca36b59L, + 0x052bf1a1a22da016L,0xbdfbff72f6093254L,0x94e50f28e22209f3L } }, + /* 21 */ + { { 0x90b2e5b33062e8afL,0xa8572375e8a3d369L,0x3fe1b00b201db7b1L, + 0xe926def0ee651aa2L,0x6542c9beb9b10ad7L,0x098e309ba2fcbe74L }, + { 0x779deeb3fff1d63fL,0x23d0e80a20bfd374L,0x8452bb3b8768f797L, + 0xcf75bb4d1f952856L,0x8fe6b40029ea3faaL,0x12bd3e4081373a53L } }, + /* 22 */ + { { 0xc023780d104cbba5L,0x6207e747fa35dd4cL,0x35c239281ca9b6a3L, + 0x4ff19be897987b10L,0xb8476bbf8022eee8L,0xaa0a4a14d3bbe74dL }, + { 0x20f94331187d4543L,0x3215387079f6e066L,0x83b0f74eac7e82e1L, + 0xa7748ba2828f06abL,0xc5f0298ac26ef35fL,0x0f0c50708e9a7dbdL } }, + /* 23 */ + { { 0x0c5c244cdef029ddL,0x3dabc687850661b8L,0x9992b865fe11d981L, + 0xe9801b8f6274dbadL,0xe54e6319098da242L,0x9929a91a91a53d08L }, + { 0x37bffd7235285887L,0xbc759425f1418102L,0x9280cc35fd2e6e20L, + 0x735c600cfbc42ee5L,0xb7ad28648837619aL,0xa3627231a778c57bL } }, + /* 24 */ + { { 0xae799b5c91361ed8L,0x47d71b756c63366cL,0x54cdd5211b265a6aL, + 0xe0215a5998d77b74L,0x4424d9b7bab29db0L,0x8b0ffacc7fd9e536L }, + { 0x46d85d1237b5d9efL,0x5b106d62bfa91747L,0xed0479f85f99ba2dL, + 0x0e6f39231d104de4L,0x83a84c8425e8983fL,0xa9507e0af8105a70L } }, + /* 25 */ + { { 0xf6c68a6e14cf381cL,0xaf9d27bdc22e31ccL,0x23568d4daa8a5ccbL, + 0xe431eec0e338e4d2L,0xf1a828fe8f52ad1fL,0xdb6a0579e86acd80L }, + { 0x2885672e4507832aL,0x73fc275f887e5289L,0x65f8027805610d08L, + 0x8d9b4554075ff5b0L,0x3a8e8fb109f712b5L,0x39f0ac862ebe9cf2L } }, + /* 26 */ + { { 0xd8fabf784c52edf5L,0xdcd737e5a589ae53L,0x94918bf0d791ab17L, + 0xb5fbd956bcff06c9L,0xf6d3032edca46d45L,0x2cdff7e141a3e486L }, + { 0x6674b3ba61f47ec8L,0x8a882163eef84608L,0xa257c7054c687f90L, + 0xe30cb2edf6cdf227L,0x2c4c64ca7f6ea846L,0x186fa17ccc6bcd3cL } }, + /* 27 */ + { { 0x48a3f5361dfcb91eL,0x83595e13646d358aL,0xbd15827b91128798L, + 0x3ce612b82187757aL,0x873150a161bd7372L,0xf4684530b662f568L }, + { 0x8833950b401896f6L,0xe11cb89a77f3e090L,0xb2f12cac48e7f4a5L, + 0x313dd769f606677eL,0xfdcf08b316579f93L,0x6429cec946b8f22bL } }, + /* 28 */ + { { 0x4984dd54bb75f9a4L,0x4aef06b929d3b570L,0xb5f84ca23d6e4c1eL, + 0x24c61c11b083ef35L,0xce4a7392392ca9ffL,0x865d65176730a800L }, + { 0xca3dfe76722b4a2bL,0x12c04bf97b083e0eL,0x803ce5b51b86b8a5L, + 0x3fc7632d6a7e3e0cL,0xc89970c2c81adbe4L,0x3cbcd3ad120e16b1L } }, + /* 29 */ + { { 0xfbfb4cc7ec30ce93L,0x10ed6c7db72720a2L,0xec675bf747b55500L, + 0x90725903333ff7c3L,0xc7c3973e5075bfc0L,0xb049ecb007acf31bL }, + { 0xb4076eaf4f58839cL,0x101896daa2b05e4fL,0x3f6033b0ab40c66eL, + 0x19ee9eebc8d864baL,0xeb6cf15547bf6d2aL,0x8e5a9663f826477dL } }, + /* 30 */ + { { 0x69e62fddf7fbd5e1L,0x38ecfe5476912b1dL,0x845a3d56d1da3bfbL, + 0x0494950e1c86f0d4L,0x83cadbf93bc36ce8L,0x41fce5724fccc8d1L }, + { 0x05f939c28332c144L,0xb17f248b0871e46eL,0x3d8534e266e8aff6L, + 0x1d06f1dc3b85c629L,0xdb06a32ea3131b73L,0xf295184d8b3f64e5L } }, + /* 31 */ + { { 0xd9653ff736ddc103L,0x25f43e3795ef606fL,0x09e301fcfe06dce8L, + 0x85af234130b6eebfL,0x79b12b530ff56b20L,0x9b4fb499fe9a3c6bL }, + { 0x0154f89251d27ac2L,0xd33167e356ca5389L,0x7828ec1fafc065a6L, + 0x0959a2587f746c9bL,0xb18f1be30c44f837L,0xa7946117c4132fdbL } }, + /* 32 */ + { { 0xc0426b775e3c647bL,0xbfcbd9398cf05348L,0x31d312e3172c0d3dL, + 0x5f49fde6ee754737L,0x895530f06da7ee61L,0xcf281b0ae8b3a5fbL }, + { 0xfd14973541b8a543L,0x41a625a73080dd30L,0xe2baae07653908cfL, + 0xc3d01436ba02a278L,0xa0d0222e7b21b8f8L,0xfdc270e9d7ec1297L } }, + /* 33 */ + { { 0x00873c0cbc7f41d6L,0xd976113e1b7ad641L,0x2a536ff4238443fbL, + 0x030d00e241e62e45L,0x532e98675f545fc6L,0xcd0331088e91208cL }, + { 0xd1a04c999797612cL,0xd4393e02eea674e2L,0xd56fa69ee19742a1L, + 0xdd2ab48085f0590eL,0xa5cefc5248a2243dL,0x48cc67b654383f41L } }, + /* 34 */ + { { 0x4e50430efc14ab48L,0x195b7f4f26706a74L,0x2fe8a228cc881ff6L, + 0xb1b968e2d945013dL,0x936aa5794b92162bL,0x4fb766b7364e754aL }, + { 0x13f93bca31e1ff7fL,0x696eb5cace4f2691L,0xff754bf8a2b09e02L, + 0x58f13c9ce58e3ff8L,0xb757346f1678c0b0L,0xd54200dba86692b3L } }, + /* 35 */ + { { 0x9a030bbd6dda1265L,0xf7b4f3fce89718ddL,0xa6a4931f936065b8L, + 0xbce72d875f72241cL,0x6cbb51cb65775857L,0xc71618154e993675L }, + { 0xe81a0f792ee32189L,0xef2fab26277dc0b2L,0x9e64f6feb71f469fL, + 0xb448ce33dfdaf859L,0x3f5c1c4cbe6b5df1L,0xfb8dfb001de45f7bL } }, + /* 36 */ + { { 0xc7345fa74d5bb921L,0x5c7e04be4d2b667eL,0x47ed3a80282d7a3eL, + 0x5c2777f87e47b2a4L,0x89b3b10008488e2eL,0x9aad77c2b2eb5b45L }, + { 0xd681bca7daac34aeL,0x2452e4e526afb326L,0x0c88792441a1ee14L, + 0x743b04d4c2407adeL,0xcb5e999bfc17a2acL,0x4dca2f824a701a06L } }, + /* 37 */ + { { 0x68e31ca61127bc1aL,0xa3edd59b17ead3beL,0x67b6b645e25f5a15L, + 0x76221794a420e15eL,0x794fd83b4b1e872eL,0x7cab3f03b2dece1bL }, + { 0x7119bf15ca9b3586L,0xa55459244d250bd7L,0x173633eacc6bcf24L, + 0x9bd308c2b1b6f884L,0x3bae06f5447d38c3L,0x54dcc135f341fe1cL } }, + /* 38 */ + { { 0x56d3598d943caf0dL,0xce044ea9225ff133L,0x9edf6a7c563fadeaL, + 0x632eb94473e8dc27L,0x814b467e3190dcabL,0x2d4f4f316dbb1e31L }, + { 0x8d69811ca143b7caL,0x4ec1ac32de7cf950L,0x223ab5fd37b5fe82L, + 0xe82616e49390f1d9L,0xabff4b2075804610L,0x11b9be15875b08f0L } }, + /* 39 */ + { { 0x4ae31a3d3bbe682cL,0xbc7c5d2674eef2ddL,0x92afd10a3c47dd40L, + 0xec7e0a3bc14ab9e1L,0x6a6c3dd1b2e495e4L,0x085ee5e9309bcd85L }, + { 0xf381a9088c2e67fdL,0x32083a80e261eaf2L,0x0fcd6a4996deee15L, + 0xe3b8fb035e524c79L,0x8dc360d91d5b08b9L,0x3a06e2c87f26719fL } }, + /* 40 */ + { { 0x5cd9f5a87237cac0L,0x93f0b59d43586794L,0x4384a764e94f6c4eL, + 0x8304ed2bb62782d3L,0x0b8db8b3cde06015L,0x4336dd535dbe190fL }, + { 0x5744355392ab473aL,0x031c7275be5ed046L,0x3e78678c21909aa4L, + 0x4ab7e04f99202ddbL,0x2648d2066977e635L,0xd427d184093198beL } }, + /* 41 */ + { { 0x822848f50f9b5a31L,0xbb003468baadb62aL,0x233a04723357559cL, + 0x49ef688079aee843L,0xa89867a0aeb9e1e3L,0xc151931b1f6f9a55L }, + { 0xd264eb0bad74251eL,0x37b9b2634abf295eL,0xb600921b04960d10L, + 0x0de53dbc4da77dc0L,0x01d9bab3d2b18697L,0xad54ec7af7156ddfL } }, + /* 42 */ + { { 0x8e74dc3579efdc58L,0x456bd3694ff68ddbL,0x724e74ccd32096a5L, + 0xe41cff42386783d0L,0xa04c7f217c70d8a4L,0x41199d2fe61a19a2L }, + { 0xd389a3e029c05dd2L,0x535f2a6be7e3fda9L,0x26ecf72d7c2b4df8L, + 0x678275f4fe745294L,0x6319c9cc9d23f519L,0x1e05a02d88048fc4L } }, + /* 43 */ + { { 0x75cc8e2ed4d5ffe8L,0xf8bb4896dbea17f2L,0x35059790cee3cb4aL, + 0x4c06ee85a47c6165L,0xf98fff2592935d2fL,0x34c4a57232ffd7c7L }, + { 0xc4b14806ea0376a2L,0x2ea5e7504f115e02L,0x532d76e21e55d7c0L, + 0x68dc9411f31044daL,0x9272e46571b77993L,0xadaa38bb93a8cfd5L } }, + /* 44 */ + { { 0x4bf0c7127d4ed72aL,0xda0e9264ba1f79a3L,0x48c0258bf4c39ea4L, + 0xa5394ed82a715138L,0x4af511cebf06c660L,0xfcebceefec5c37cdL }, + { 0xf23b75aa779ae8c1L,0xdeff59ccad1e606eL,0xf3f526fd22755c82L, + 0x64c5ab44bb32cefdL,0xa96e11a2915bdefdL,0xab19746a1143813eL } }, + /* 45 */ + { { 0x43c78585ec837d7dL,0xca5b6fbcb8ee0ba4L,0x34e924d9d5dbb5eeL, + 0x3f4fa104bb4f1ca5L,0x15458b72398640f7L,0x4231faa9d7f407eaL }, + { 0x53e0661ef96e6896L,0x554e4c69d03b0f9dL,0xd4fcb07b9c7858d1L, + 0x7e95279352cb04faL,0x5f5f15748974e7f7L,0x2e3fa5586b6d57c8L } }, + /* 46 */ + { { 0x42cd48036a9951a8L,0xa8b15b8842792ad0L,0x18e8bcf9abb29a73L, + 0xbfd9a092409933e8L,0x760a3594efb88dc4L,0x1441886340724458L }, + { 0x162a56ee99caedc7L,0x8fb12ecd91d101c9L,0xea671967393202daL, + 0x1aac8c4aa4ccd796L,0x7db050361cf185a8L,0x0c9f86cd8cfd095aL } }, + /* 47 */ + { { 0x9a72814710b2a556L,0x767ca964327b70b2L,0x04ed9e125e3799b7L, + 0x6781d2dc22a3eb2aL,0x5bd116eb0d9450acL,0xeccac1fca7ebe08aL }, + { 0xde68444fdc2d6e94L,0x3621f42935ecf21bL,0x14e2d54329e03a2cL, + 0x53e42cd57d3e7f0aL,0xbba26c0973ed00b9L,0x00297c39c57d2272L } }, + /* 48 */ + { { 0x3aaaab10b8243a7dL,0x6eeef93e8fa58c5bL,0xf866fca39ae7f764L, + 0x64105a2661ab04d3L,0xa3578d8a03945d66L,0xb08cd3e4791b848cL }, + { 0x45edc5f8756d2411L,0xd4a790d9a755128cL,0xc2cf096349e5f6a0L, + 0xc66d267df649beaaL,0x3ce6d9688467039eL,0x50046c6b42f7816fL } }, + /* 49 */ + { { 0x92ae160266425043L,0x1ff66afdf08db890L,0x386f5a7f8f162ce5L, + 0x18d2dea0fcf5598fL,0x78372b3a1a8ca18eL,0xdf0d20eb8cd0e6f7L }, + { 0x7edd5e1d75bb4045L,0x252a47ceb96d94b7L,0xbdb293582c626776L, + 0x853c394340dd1031L,0x9dc9becf7d5f47fdL,0x27c2302fbae4044aL } }, + /* 50 */ + { { 0x2d1d208a8f2d49ceL,0x0d91aa02162df0a2L,0x9c5cce8709a07f65L, + 0xdf07238b84339012L,0x5028e2c8419442cdL,0x2dcbd35872062abaL }, + { 0xb5fbc3cbe4680967L,0x2a7bc6459f92d72cL,0x806c76e1116c369dL, + 0x5c50677a3177e8d8L,0x753739eb4569df57L,0x2d481ef636c3f40bL } }, + /* 51 */ + { { 0x1a2d39fdfea1103eL,0xeaae559295f81b17L,0xdbd0aa18f59b264aL, + 0x90c39c1acb592ee0L,0xdf62f80d9750cca3L,0xda4d8283df97cc6cL }, + { 0x0a6dd3461e201067L,0x1531f85969fb1f6bL,0x4895e5521d60121fL, + 0x0b21aab04c041c91L,0x9d896c46bcc1ccf8L,0xd24da3b33141bde7L } }, + /* 52 */ + { { 0x575a053753b0a354L,0x392ff2f40c6ddcd8L,0x0b8e8cff56157b94L, + 0x073e57bd3b1b80d1L,0x2a75e0f03fedee15L,0x752380e4aa8e6f19L }, + { 0x1f4e227c6558ffe9L,0x3a34861819ec5415L,0xab382d5ef7997085L, + 0x5e6deaffddc46ac2L,0xe5144078fc8d094cL,0xf674fe51f60e37c6L } }, + /* 53 */ + { { 0x6fb87ae5af63408fL,0xa39c36a9cd75a737L,0x7833313fcf4c618dL, + 0xfbcd4482f034c88dL,0x4469a76139b35288L,0x77a711c566b5d9c9L }, + { 0x4a695dc7944f8d65L,0xe6da5f65161aaba8L,0x8654e9c324601669L, + 0xbc8b93f528ae7491L,0x5f1d1e838f5580d8L,0x8ccf9a1acea32cc8L } }, + /* 54 */ + { { 0x28ab110c7196fee2L,0x75799d63874c8945L,0xa262934829aedaddL, + 0x9714cc7b2be88ff4L,0xf71293cfd58d60d6L,0xda6b6cb332a564e9L }, + { 0xf43fddb13dd821c2L,0xf2f2785f90dd323dL,0x91246419048489f8L, + 0x61660f26d24c6749L,0x961d9e8cc803c15cL,0x631c6158faadc4c9L } }, + /* 55 */ + { { 0xacf2ebe0fd752366L,0xb93c340e139be88bL,0x98f664850f20179eL, + 0x14820254ff1da785L,0x5278e2764f85c16eL,0xa246ee457aab1913L }, + { 0x43861eb453763b33L,0xc49f03fc45c0bc0dL,0xafff16bcad6b1ea1L, + 0xce33908b6fd49c99L,0x5c51e9bff7fde8c3L,0x076a7a39ff142c5eL } }, + /* 56 */ + { { 0x04639dfe9e338d10L,0x8ee6996ff42b411bL,0x960461d1a875cef2L, + 0x1057b6d695b4d0baL,0x27639252a906e0bcL,0x2c19f09ae1c20f8aL }, + { 0x5b8fc3f0eef4c43dL,0xe2e1b1a807a84aa9L,0x5f455528835d2bdbL, + 0x0f4aee4d207132ddL,0xe9f8338c3907f675L,0x7a874dc90e0531f0L } }, + /* 57 */ + { { 0x84b22d4597c27050L,0xbd0b8df759e70bf8L,0xb4d6740579738b9bL, + 0x47f4d5f5cd917c4fL,0x9099c4ce13ce6e33L,0x942bfd39521d0f8bL }, + { 0x5028f0f6a43b566dL,0xaf6e866921bff7deL,0x83f6f856c44232cdL, + 0x65680579f915069aL,0xd12095a2ecfecb85L,0xcf7f06aedb01ba16L } }, + /* 58 */ + { { 0x0f56e3c48ef96c80L,0xd521f2b33ddb609cL,0x2be941027dc1450dL, + 0x2d21a07102a91fe2L,0x2e6f74fa1efa37deL,0x9a9a90b8156c28a1L }, + { 0xc54ea9ea9dc7dfcbL,0xc74e66fc2c2c1d62L,0x9f23f96749d3e067L, + 0x1c7c3a4654dd38adL,0xc70058845946cee3L,0x8985636845cc045dL } }, + /* 59 */ + { { 0x29da7cd4fce73946L,0x8f697db523168563L,0x8e235e9ccba92ec6L, + 0x55d4655f9f91d3eaL,0xf3689f23aa50a6cdL,0xdcf21c2621e6a1a0L }, + { 0xcffbc82e61b818bfL,0xc74a2f96da47a243L,0x234e980a8bc1a0cfL, + 0xf35fd6b57929cb6dL,0x81468e12efe17d6cL,0xddea6ae558b2dafbL } }, + /* 60 */ + { { 0x294de8877e787b2eL,0x258acc1f39a9310dL,0x92d9714aac14265dL, + 0x18b5591c708b48a0L,0x27cc6bb0e1abbf71L,0xc0581fa3568307b9L }, + { 0x9e0f58a3f24d4d58L,0xfebe9bb8e0ce2327L,0x91fd6a419d1be702L, + 0x9a7d8a45facac993L,0xabc0a08c9e50d66dL,0x02c342f706498201L } }, + /* 61 */ + { { 0xccd71407157bdbc2L,0x72fa89c6ad0e1605L,0xb1d3da2bb92a015fL, + 0x8ad9e7cda0a3fe56L,0x160edcbd24f06737L,0x79d4db3361275be6L }, + { 0xd3d31fd95f3497c4L,0x8cafeaee04192fb0L,0xe13ca74513a50af3L, + 0x188261678c85aae5L,0xce06cea89eb556ffL,0x2eef1995bdb549f3L } }, + /* 62 */ + { { 0x8ed7d3eb50596edcL,0xaa359362905243a2L,0xa212c2c2a4b6d02bL, + 0x611fd727c4fbec68L,0x8a0b8ff7b84f733dL,0xd85a6b905f0daf0eL }, + { 0x60e899f5d4091cf7L,0x4fef2b672eff2768L,0xc1f195cb10c33964L, + 0x8275d36993626a8fL,0xc77904f40d6c840aL,0x88d8b7fd7a868acdL } }, + /* 63 */ + { { 0x85f237237bd98425L,0xd4463992c70b154eL,0xcbb00ee296687a2eL, + 0x905fdbf7c83214fdL,0x2019d29313593684L,0x0428c393ef51218eL }, + { 0x40c7623f981e909aL,0x925133857be192daL,0x48fe480f4010907eL, + 0xdd7a187c3120b459L,0xc9d7702da1fd8f3cL,0x66e4753be358efc5L } }, + /* 64 */ + { { 0x070d34e116973cf4L,0x20aee08b7e4f34f7L,0x269af9b95eb8ad29L, + 0xdde0a036a6a45ddaL,0xa18b528e63df41e0L,0x03cc71b2a260df2aL }, + { 0x24a6770aa06b1dd7L,0x5bfa9c119d2675d3L,0x73c1e2a196844432L, + 0x3660558d131a6cf0L,0xb0289c832ee79454L,0xa6aefb01c6d8ddcdL } }, + /* 65 */ + { { 0xba1464b401ab5245L,0x9b8d0b6dc48d93ffL,0x939867dc93ad272cL, + 0xbebe085eae9fdc77L,0x73ae5103894ea8bdL,0x740fc89a39ac22e1L }, + { 0x5e28b0a328e23b23L,0x2352722ee13104d0L,0xf4667a18b0a2640dL, + 0xac74a72e49bb37c3L,0x79f734f0e81e183aL,0xbffe5b6c3fd9c0ebL } }, + /* 66 */ + { { 0xb1a358f5c6a2123fL,0x927b2d95fe28df6dL,0x89702753f199d2f9L, + 0x0a73754c1a3f82dcL,0x063d029d777affe1L,0x5439817edae6d34dL }, + { 0xf7979eef6b8b83c4L,0x615cb2149d945682L,0x8f0e4facc5e57eaeL, + 0x042b89b8113047ddL,0x888356dc93f36508L,0xbf008d185fd1f32fL } }, + /* 67 */ + { { 0x8012aa244e8068dbL,0xc72cc641a5729a47L,0x3c33df2c43f0691dL, + 0xfa0573471d92145fL,0xaefc0f2fb97f7946L,0x813d75cb2f8121bfL }, + { 0x05613c724383bba6L,0xa924ce70a4224b3fL,0xe59cecbe5f2179a6L, + 0x78e2e8aa79f62b61L,0x3ac2cc3b53ad8079L,0x55518d71d8f4fa96L } }, + /* 68 */ + { { 0x03cf292200623f3bL,0x095c71115f29ebffL,0x42d7224780aa6823L, + 0x044c7ba17458c0b0L,0xca62f7ef0959ec20L,0x40ae2ab7f8ca929fL }, + { 0xb8c5377aa927b102L,0x398a86a0dc031771L,0x04908f9dc216a406L, + 0xb423a73a918d3300L,0x634b0ff1e0b94739L,0xe29de7252d69f697L } }, + /* 69 */ + { { 0x744d14008435af04L,0x5f255b1dfec192daL,0x1f17dc12336dc542L, + 0x5c90c2a7636a68a8L,0x960c9eb77704ca1eL,0x9de8cf1e6fb3d65aL }, + { 0xc60fee0d511d3d06L,0x466e2313f9eb52c7L,0x743c0f5f206b0914L, + 0x42f55bac2191aa4dL,0xcefc7c8fffebdbc2L,0xd4fa6081e6e8ed1cL } }, + /* 70 */ + { { 0xb5e405d3b0ab9645L,0xaeec7f98d5f1f711L,0x8ad42311585c2a6eL, + 0x045acb9e512c6944L,0xae106c4ea90db1c6L,0xb89f33d5898e6563L }, + { 0x43b07cd97fed2ce4L,0xf9934e17dd815b20L,0x6778d4d50a81a349L, + 0x9e616ade52918061L,0xfa06db06d7e67112L,0x1da23cf188488091L } }, + /* 71 */ + { { 0x821c46b342f2c4b5L,0x931513ef66059e47L,0x7030ae4366f50cd1L, + 0x43b536c943e7b127L,0x006258cf5fca5360L,0xe4e3ee796b557abfL }, + { 0xbb6b390024c8b22fL,0x2eb5e2c1fcbf1054L,0x937b18c9567492afL, + 0xf09432e4acf53957L,0x585f5a9d1dbf3a56L,0xf86751fdbe0887cfL } }, + /* 72 */ + { { 0x157399cb9d10e0b2L,0x1c0d595660dc51b7L,0x1d496b8a1f583090L, + 0x6658bc2688590484L,0x88c08ab703213f28L,0x8d2e0f737ae58de4L }, + { 0x9b79bc95486cfee6L,0x036a26c7e9e5bc57L,0x1ad03601cd8ae97aL, + 0x06907f87ff3a0494L,0x078f4bbf2c7eb584L,0xe3731bf57e8d0a5aL } }, + /* 73 */ + { { 0x72f2282be1cd0abeL,0xd4f9015e87efefa2L,0x9d1898066c3834bdL, + 0x9c8cdcc1b8a29cedL,0x0601b9f4fee82ebcL,0x371052bc7206a756L }, + { 0x76fa109246f32562L,0xdaad534c17351bb4L,0xc3d64c37b3636bb5L, + 0x038a8c5145d54e00L,0x301e618032c09e7cL,0x9764eae795735151L } }, + /* 74 */ + { { 0x8791b19fcbd5256aL,0x4007e0f26ca13a3bL,0x03b794604cf06904L, + 0xb18a9c22b6c17589L,0xa1cb7d7d81d45908L,0x6e13fa9d21bb68f1L }, + { 0x47183c62a71e6e16L,0x5cf0ef8ee18749edL,0x2c9c7f9b2e5ed409L, + 0x042eeacce6e117e1L,0xb86d481613fb5a7fL,0xea1cf0edc9e5feb1L } }, + /* 75 */ + { { 0x6e6573c9cea4cc9bL,0x5417961dafcec8f3L,0x804bf02aa438b6f6L, + 0xb894b03cdcd4ea88L,0xd0f807e93799571fL,0x3466a7f5862156e8L }, + { 0x51e59acd56515664L,0x55b0f93ca3c5eb0bL,0x84a06b026a4279dbL, + 0x5c850579c5fae08eL,0xcf07b8dba663a1a2L,0x49a36bbcf46ffc8dL } }, + /* 76 */ + { { 0xe47f5acc46d93106L,0x65b7ade0aa897c9cL,0x37cf4c9412d7e4beL, + 0xa2ae9b80d4b2caa9L,0x5e7ce09ce60357a3L,0x29f77667c8ecd5f9L }, + { 0xdf6868f5a8a0b1c5L,0x240858cf62978ad8L,0x0f7ac101dc0002a1L, + 0x1d28a9d7ffe9aa05L,0x744984d65b962c97L,0xa8a7c00b3d28c8b2L } }, + /* 77 */ + { { 0x7c58a852ae11a338L,0xa78613f1d1af96e7L,0x7e9767d25355cc73L, + 0x6ba37009792a2de6L,0x7d60f618124386b2L,0xab09b53111157674L }, + { 0x95a0484198eb9dd0L,0xe6c17acc15070328L,0xafc6da45489c6e49L, + 0xab45a60abb211530L,0xc58d65927d7ea933L,0xa3ef3c65095642c6L } }, + /* 78 */ + { { 0x89d420e9df010879L,0x9d25255d39576179L,0x9cdefd50e39513b6L, + 0xe4efe45bd5d1c313L,0xc0149de73f7af771L,0x55a6b4f4340ab06bL }, + { 0xf1325251ebeaf771L,0x2ab44128878d4288L,0xfcd5832e18e05afeL, + 0xef52a348cc1fb62bL,0x2bd08274c1c4792aL,0x345c5846877c6dc7L } }, + /* 79 */ + { { 0xde15ceb0bea65e90L,0x0987f72b2416d99cL,0x44db578dfd863decL, + 0xf617b74bac6a3578L,0x9e62bd7adb48e999L,0x877cae61eab1a1beL }, + { 0x23adddaa3a358610L,0x2fc4d6d1325e2b07L,0x897198f51585754eL, + 0xf741852cb392b584L,0x9927804cb55f7de1L,0xe9e6c4ed1aa8efaeL } }, + /* 80 */ + { { 0x867db63998683186L,0xfb5cf424ddcc4ea9L,0xcc9a7ffed4f0e7bdL, + 0x7c57f71c7a779f7eL,0x90774079d6b25ef2L,0x90eae903b4081680L }, + { 0xdf2aae5e0ee1fcebL,0x3ff1da24e86c1a1fL,0x80f587d6ca193edfL, + 0xa5695523dc9b9d6aL,0x7b84090085920303L,0x1efa4dfcba6dbdefL } }, + /* 81 */ + { { 0xfbd838f9e0540015L,0x2c323946c39077dcL,0x8b1fb9e6ad619124L, + 0x9612440c0ca62ea8L,0x9ad9b52c2dbe00ffL,0xf52abaa1ae197643L }, + { 0xd0e898942cac32adL,0xdfb79e4262a98f91L,0x65452ecf276f55cbL, + 0xdb1ac0d27ad23e12L,0xf68c5f6ade4986f0L,0x389ac37b82ce327dL } }, + /* 82 */ + { { 0x511188b4f8e60f5bL,0x7fe6701548aa2adaL,0xdb333cb8381abca2L, + 0xb15e6d9ddaf3fc97L,0x4b24f6eb36aabc03L,0xc59789df72a748b4L }, + { 0x26fcb8a529cf5279L,0x7a3c6bfc01ad9a6cL,0x866cf88d4b8bac9bL, + 0xf4c899899c80d041L,0xf0a0424170add148L,0x5a02f47945d81a41L } }, + /* 83 */ + { { 0xfa5c877cc1c90202L,0xd099d440f8ac7570L,0x428a5b1bd17881f7L, + 0x61e267db5b2501d7L,0xf889bf04f2e4465bL,0x4da3ae0876aa4cb8L }, + { 0x3ef0fe26e3e66861L,0x5e7729533318b86dL,0xc3c35fbc747396dfL, + 0x5115a29c439ffd37L,0xbfc4bd97b2d70374L,0x088630ea56246b9dL } }, + /* 84 */ + { { 0xcd96866db8a9e8c9L,0xa11963b85bb8091eL,0xc7f90d53045b3cd2L, + 0x755a72b580f36504L,0x46f8b39921d3751cL,0x4bffdc9153c193deL }, + { 0xcd15c049b89554e7L,0x353c6754f7a26be6L,0x79602370bd41d970L, + 0xde16470b12b176c0L,0x56ba117540c8809dL,0xe2db35c3e435fb1eL } }, + /* 85 */ + { { 0xd71e4aab6328e33fL,0x5486782baf8136d1L,0x07a4995f86d57231L, + 0xf1f0a5bd1651a968L,0xa5dc5b2476803b6dL,0x5c587cbc42dda935L }, + { 0x2b6cdb32bae8b4c0L,0x66d1598bb1331138L,0x4a23b2d25d7e9614L, + 0x93e402a674a8c05dL,0x45ac94e6da7ce82eL,0xeb9f8281e463d465L } }, + /* 86 */ + { { 0x34e0f9d1fecf5b9bL,0xa115b12bf206966aL,0x5591cf3b1eaa0534L, + 0x5f0293cbfb1558f9L,0x1c8507a41bc703a5L,0x92e6b81c862c1f81L }, + { 0xcc9ebc66cdaf24e3L,0x68917ecd72fcfc70L,0x6dc9a9308157ba48L, + 0x5d425c08b06ab2b2L,0x362f8ce736e929c4L,0x09f6f57c62e89324L } }, + /* 87 */ + { { 0x1c7d6b78d29375fbL,0xfabd851ee35d1157L,0xf6f62dcd4243ea47L, + 0x1dd924608fe30b0fL,0x08166dfaffc6e709L,0xc6c4c6930881e6a7L }, + { 0x20368f87d6a53fb0L,0x38718e9f9eb4d1f9L,0x03f08acdafd7e790L, + 0x0835eb4472fe2a1cL,0x7e05090388076e5dL,0x538f765ea638e731L } }, + /* 88 */ + { { 0x0e0249d9c2663b4bL,0xe700ab5b47cd38ddL,0xb192559d2c46559fL, + 0x8f9f74a84bcde66dL,0xad1615233e2aced5L,0xc155c0473dd03a5bL }, + { 0x346a87993be454ebL,0x66ee94db83b7dccdL,0x1f6d8378ab9d2abeL, + 0x4a396dd27733f355L,0x419bd40af53553c2L,0xd0ead98d731dd943L } }, + /* 89 */ + { { 0x908e0b0eec142408L,0x98943cb94114b310L,0x03dbf7d81742b1d7L, + 0xd270df6b693412f4L,0xc50654948f69e20cL,0xa76a90c3697e43a1L }, + { 0xe0fa33844624825aL,0x82e48c0b8acc34c2L,0x7b24bd14e9a14f2bL, + 0x4f5dd5e24db30803L,0x0c77a9e7932da0a3L,0x20db90f274c653dcL } }, + /* 90 */ + { { 0x261179b70e6c5fd9L,0xf8bec1236c982eeaL,0x47683338d4957b7eL, + 0xcc47e6640a72f66aL,0xbd54bf6a1bad9350L,0xdfbf4c6af454e95aL }, + { 0x3f7a7afa6907f4faL,0x7311fae0865ca735L,0x24737ab82a496adaL, + 0x13e425f115feb79bL,0xe9e97c50a1b93c21L,0xb26b6eac4ddd3eb5L } }, + /* 91 */ + { { 0x81cab9f52a2e5f2bL,0xf93caf29bf385ac4L,0xf4bf35c3c909963aL, + 0x081e730074c9143cL,0x3ea57fa8c281b4c5L,0xe497905c9b340741L }, + { 0xf556dd8a55ab3cfbL,0xd444b96b518db6adL,0x34f5425a5ef4b955L, + 0xdda7a3acecd26aa3L,0xb57da11bda655e97L,0x02da3effc2024c70L } }, + /* 92 */ + { { 0xe24b00366481d0d9L,0x3740dbe5818fdfe2L,0xc1fc1f45190fda00L, + 0x329c92803cf27fdeL,0x7435cb536934f43eL,0x2b505a5d7884e8feL }, + { 0x6cfcc6a6711adcc9L,0xf034325c531e21e1L,0xa2f4a9679b2a8a99L, + 0x9d5f38423c21bdffL,0xb25c781131b57d66L,0xdb5344d80b8093b9L } }, + /* 93 */ + { { 0x0d72e667ae50a2f5L,0x9b7f8d8ae4a861d1L,0xa129f70f330df1cbL, + 0xe90aa5d7e04fefc3L,0xff561ecbe72c3ae1L,0x0d8fb428cdb955faL }, + { 0xd2235f73d7663784L,0xc05baec67e2c456aL,0xe5c292e42adbfcccL, + 0x4fd17988efb110d5L,0x27e57734d19d49f3L,0x188ac4ce84f679feL } }, + /* 94 */ + { { 0x7ee344cfa796c53eL,0xbbf6074d0868009bL,0x1f1594f7474a1295L, + 0x66776edcac11632dL,0x1862278b04e2fa5aL,0x52665cf2c854a89aL }, + { 0x7e3764648104ab58L,0x167759137204fd6dL,0x86ca06a544ea1199L, + 0xaa3f765b1c9240ddL,0x5f8501a924746149L,0x7b982e30dcd251d7L } }, + /* 95 */ + { { 0xe44e9efcc15f3060L,0x5ad62f2ea87ebbe6L,0x36499d41c79500d4L, + 0xa66d6dc0336fa9d1L,0xf8afc4955afd3b1fL,0x1d8ccb24e5c9822bL }, + { 0x4031422b79d7584bL,0xc54a0580ea3f20ddL,0x3f837c8f958468c5L, + 0x3d82f110fbea7735L,0x679a87787dffe2fcL,0x48eba63b20704803L } }, + /* 96 */ + { { 0x89b10d41df46e2f6L,0x13ab57f819514367L,0x067372b91d469c87L, + 0x0c195afa4f6c5798L,0xea43a12a272c9acfL,0x9dadd8cb678abdacL }, + { 0xcce56c6be182579aL,0x86febadb2d26c2d8L,0x1c668ee12a44745cL, + 0x580acd8698dc047aL,0x5a2b79cc51b9ec2dL,0x007da6084054f6a0L } }, + /* 97 */ + { { 0x9e3ca35217b00dd0L,0x046779cb0e81a7a6L,0xb999fef3d482d871L, + 0xe6f38134d9233fbcL,0x112c3001f48cd0e0L,0x934e75763c6c66aeL }, + { 0xb44d4fc3d73234dcL,0xfcae2062864eafc1L,0x843afe2526bef21aL, + 0x61355107f3b75fdfL,0x8367a5aa794c2e6bL,0x3d2629b18548a372L } }, + /* 98 */ + { { 0x6230618f437cfaf8L,0x5b8742cb2032c299L,0x949f72472293643aL, + 0xb8040f1a09464f79L,0x049462d24f254143L,0xabd6b522366c7e76L }, + { 0x119b392bd5338f55L,0x1a80a9ce01495a0cL,0xf3118ca7f8d7537eL, + 0xb715adc26bf4b762L,0x24506165a8482b6cL,0xd958d7c696a7c84dL } }, + /* 99 */ + { { 0x9ad8aa87bdc21f31L,0xadb3cab48063e58cL,0xefd86283b07dd7b8L, + 0xc7b9b7621be7c6b4L,0x2ef58741015582deL,0xc970c52e299addf3L }, + { 0x78f02e2a22f24d66L,0xefec1d1074cc100aL,0xaf2a6a3909316e1aL, + 0xce7c22055849dd49L,0x9c1fe75c96bffc4cL,0xcad98fd27ba06ec0L } }, + /* 100 */ + { { 0xed76e2d0b648b73eL,0xa9f92ce51cfd285eL,0xa8c86c062ed13de1L, + 0x1d3a574ea5191a93L,0x385cdf8b1ad1b8bfL,0xbbecc28a47d2cfe3L }, + { 0x98d326c069cec548L,0x4f5bc1ddf240a0b2L,0x241a706229057236L, + 0x0fc6e9c5c68294a4L,0x4d04838ba319f17aL,0x8b612cf19ffc1c6fL } }, + /* 101 */ + { { 0x9bb0b5014c3830ebL,0x3d08f83c8ee0d0c5L,0xa4a6264279ba9389L, + 0x5d5d40449cbc2914L,0xae9eb83e074c46f0L,0x63bb758f74ead7d6L }, + { 0x1c40d2eac6bb29e0L,0x95aa2d874b02f41eL,0x9298917553cb199aL, + 0xdd91bafe51584f6dL,0x3715efb931a1aaecL,0xc1b6ae5b46780f9eL } }, + /* 102 */ + { { 0xcded3e4b42772f41L,0x3a700d5d3bcb79d1L,0x4430d50e80feee60L, + 0x444ef1fcf5e5d4bbL,0xc660194fe6e358ffL,0xe68a2f326a91b43cL }, + { 0x5842775c977fe4d2L,0x78fdef5c7e2a41ebL,0x5f3bec02ff8df00eL, + 0xf4b840cd5852525dL,0x0870483a4e6988bdL,0x39499e39cc64b837L } }, + /* 103 */ + { { 0xfc05de80b08df5feL,0x0c12957c63ba0362L,0xea379414d5cf1428L, + 0xc559132a54ef6216L,0x33d5f12fb9e65cf8L,0x09c602781695d663L }, + { 0x3ac1ced461f7a2fbL,0xdd838444d4f5eeb8L,0x82a38c6c8318fcadL, + 0x315be2e5e9f1a864L,0x317b5771442daf47L,0x81b5904a95aa5f9eL } }, + /* 104 */ + { { 0x6b6b1c508b21d232L,0x87f3dbc08c2cba75L,0xa7e74b46ae9f0fafL, + 0x036a0985bb7b8079L,0x4f185b908d974a25L,0x5aa7cef0d9af5ec9L }, + { 0xe0566a7057dcfffcL,0x6ea311dab8453225L,0x72ea1a8d23368aa9L, + 0xed9b208348cd552dL,0xb987967cc80ea435L,0xad735c756c104173L } }, + /* 105 */ + { { 0xaea85ab3cee76ef4L,0x44997444af1d2b93L,0x0851929beacb923fL, + 0xb080b59051e3bc0cL,0xc4ee1d8659be68a2L,0xf00de21964b26cdaL }, + { 0x8d7fb5c0f2e90d4dL,0x00e219a777d9ec64L,0xc4e6febd5d1c491cL, + 0x080e37541a8f4585L,0x4a9b86c848d2af9cL,0x2ed70db6b6679851L } }, + /* 106 */ + { { 0xaee44116586f25cbL,0xf7b6861fa0fcf70fL,0x55d2cd2018a350e8L, + 0x861bf3e592dc286fL,0x9ab18ffa6226aba7L,0xd15827bea9857b03L }, + { 0x26c1f54792e6acefL,0x422c63c8ac1fbac3L,0xa2d8760dfcbfd71dL, + 0x35f6a539b2511224L,0xbaa88fa1048d1a21L,0x49f1abe9ebf999dbL } }, + /* 107 */ + { { 0x16f9f4f4f7492b73L,0xcf28ec1ecb392b1aL,0x45b130d469ca6ffcL, + 0x28ba8d40b72efa58L,0xace987c75ca066f5L,0x3e3992464ad022ebL }, + { 0x63a2d84e752555bbL,0xaaa93b4a9c2ae394L,0xcd80424ec89539caL, + 0x6d6b5a6daa119a99L,0xbd50334c379f2629L,0x899e925eef3cc7d3L } }, + /* 108 */ + { { 0xb7ff3651bf825dc4L,0x0f741cc440b9c462L,0x771ff5a95cc4fb5bL, + 0xcb9e9c9b47fd56feL,0xbdf053db5626c0d3L,0xa97ce675f7e14098L }, + { 0x68afe5a36c934f5eL,0x6cd5e148ccefc46fL,0xc7758570d7a88586L, + 0x49978f5edd558d40L,0xa1d5088a64ae00c1L,0x58f2a720f1d65bb2L } }, + /* 109 */ + { { 0x66fdda4a3e4daedbL,0x38318c1265d1b052L,0x28d910a24c4bbf5cL, + 0x762fe5c478a9cd14L,0x08e5ebaad2cc0aeeL,0xd2cdf257ca0c654cL }, + { 0x48f7c58b08b717d2L,0x3807184a386cd07aL,0x3240f626ae7d0112L, + 0x03e9361bc43917b0L,0xf261a87620aea018L,0x53f556a47e1e6372L } }, + /* 110 */ + { { 0xc84cee562f512a90L,0x24b3c0041b0ea9f1L,0x0ee15d2de26cc1eaL, + 0xd848762cf0c9ef7dL,0x1026e9c5d5341435L,0x8f5b73dcfdb16b31L }, + { 0x1f69bef2d2c75d95L,0x8d33d581be064ddaL,0x8c024c1257ed35e6L, + 0xf8d435f9c309c281L,0xfd295061d6960193L,0x66618d78e9e49541L } }, + /* 111 */ + { { 0x571cfd458ce382deL,0x175806eede900ddeL,0x6184996534aba3b5L, + 0xe899778ade7aec95L,0xe8f00f6eff4aa97fL,0xae971cb5010b0c6dL }, + { 0x1827eebc3af788f1L,0xd46229ffe413fe2dL,0x8a15455b4741c9b4L, + 0x5f02e690f8e424ebL,0x40a1202edae87712L,0x49b3bda264944f6dL } }, + /* 112 */ + { { 0xd63c6067035b2d69L,0xb507150d6bed91b0L,0x1f35f82f7afb39b2L, + 0xb9bd9c0116012b66L,0x00d97960ed0a5f50L,0xed7054512716f7c9L }, + { 0x1576eff4127abdb4L,0x6850d698f01e701cL,0x9fa7d7493fc87e2fL, + 0x0b6bcc6fb0ce3e48L,0xf4fbe1f5f7d8c1c0L,0xcf75230e02719cc6L } }, + /* 113 */ + { { 0x6761d6c2722d94edL,0xd1ec3f213718820eL,0x65a40b7025d0e7c6L, + 0xd67f830ebaf3cf31L,0x633b3807b93ea430L,0x17faa0ea0bc96c69L }, + { 0xe6bf3482df866b98L,0x205c1ee9a9db52d4L,0x51ef9bbdff9ab869L, + 0x3863dad175eeb985L,0xef216c3bd3cf442aL,0x3fb228e3f9c8e321L } }, + /* 114 */ + { { 0x94f9b70c0760ac07L,0xf3c9ccae9d79bf4dL,0x73cea084c5ffc83dL, + 0xef50f943dc49c38eL,0xf467a2aebc9e7330L,0x5ee534b644ea7fbaL }, + { 0x20cb627203609e7fL,0x0984435562fdc9f0L,0xaf5c8e580f1457f7L, + 0xd1f50a6cb4b25941L,0x77cb247c2ec82395L,0xa5f3e1e5da3dca33L } }, + /* 115 */ + { { 0x023489d67d85fa94L,0x0ba405372db9ce47L,0x0fdf7a1faed7aad1L, + 0xa57b0d739a4ccb40L,0x48fcec995b18967cL,0xf30b5b6eb7274d24L }, + { 0x7ccb4773c81c5338L,0xb85639e6a3ed6bd0L,0x7d9df95f1d56eadaL, + 0xe256d57f0a1607adL,0x6da7ffdc957574d6L,0x65f8404601c7a8c4L } }, + /* 116 */ + { { 0x8d45d0cbcba1e7f1L,0xef0a08c002b55f64L,0x771ca31b17e19892L, + 0xe1843ecb4885907eL,0x67797ebc364ce16aL,0x816d2b2d8df4b338L }, + { 0xe870b0e539aa8671L,0x9f0db3e4c102b5f5L,0x342966591720c697L, + 0x0ad4c89e613c0d2aL,0x1af900b2418ddd61L,0xe087ca72d336e20eL } }, + /* 117 */ + { { 0x222831ffaba10079L,0x0dc5f87b6d64fff2L,0x445479073e8cb330L, + 0xe815aaa2702a33fbL,0x338d6b2e5fba3215L,0x0f7535cb79f549c8L }, + { 0x471ecd972ee95923L,0x1e868b37c6d1c09fL,0x2bc7b8ecc666ef4eL, + 0xf5416589808a4bfcL,0xf23e9ee23fbc4d2eL,0x4357236c2d75125bL } }, + /* 118 */ + { { 0xfe176d95ba9cdb1bL,0x45a1ca012f82791eL,0x97654af24de4cca2L, + 0xbdbf9d0e5cc4bcb9L,0xf6a7df50ad97ac0aL,0xc52112b061359fd6L }, + { 0x696d9ce34f05eae3L,0x903adc02e943ac2bL,0xa90753470848be17L, + 0x1e20f1702a3973e5L,0xe1aacc1c6feb67e9L,0x2ca0ac32e16bc6b9L } }, + /* 119 */ + { { 0xffea12e4ef871eb5L,0x94c2f25da8bf0a7aL,0x4d1e4c2a78134eaaL, + 0x11ed16fb0360fb10L,0x4029b6db85fc11beL,0x5e9f7ab7f4d390faL }, + { 0x5076d72f30646612L,0xa0afed1ddda1d0d8L,0x2902225785a1d103L, + 0xcb499e174e276bcdL,0x16d1da7151246c3dL,0xc72d56d3589a0443L } }, + /* 120 */ + { { 0xdf5ffc74dae5bb45L,0x99068c4a261bd6dcL,0xdc0afa7aaa98ec7bL, + 0xedd2ee00f121e96dL,0x163cc7be1414045cL,0xb0b1bbce335af50eL }, + { 0xd440d78501a06293L,0xcdebab7c6552e644L,0x48cb8dbc8c757e46L, + 0x81f9cf783cabe3cbL,0xddd02611b123f59aL,0x3dc7b88eeeb3784dL } }, + /* 121 */ + { { 0xe1b8d398c4741456L,0xa9dfa9026032a121L,0x1cbfc86d1263245bL, + 0xf411c7625244718cL,0x96521d5405b0fc54L,0x1afab46edbaa4985L }, + { 0xa75902ba8674b4adL,0x486b43ad5ad87d12L,0x72b1c73636e0d099L, + 0x39890e07bb6cd6d6L,0x8128999c59bace4eL,0xd8da430b7b535e33L } }, + /* 122 */ + { { 0x39f65642c6b75791L,0x050947a621806bfbL,0x0ca3e3701362ef84L, + 0x9bc60aed8c3d2391L,0x9b488671732e1ddcL,0x12d10d9ea98ee077L }, + { 0xb6f2822d3651b7dcL,0x6345a5ba80abd138L,0x62033262472d3c84L, + 0xd54a1d40acc57527L,0x6ea46b3a424447cbL,0x5bc410572fb1a496L } }, + /* 123 */ + { { 0xe70c57a3a751cd0eL,0x190d8419eba3c7d6L,0xb1c3bee79d47d55aL, + 0xda941266f912c6d8L,0x12e9aacc407a6ad6L,0xd6ce5f116e838911L }, + { 0x063ca97b70e1f2ceL,0xa3e47c728213d434L,0xa016e24184df810aL, + 0x688ad7b0dfd881a4L,0xa37d99fca89bf0adL,0xd8e3f339a23c2d23L } }, + /* 124 */ + { { 0xbdf53163750bed6fL,0x808abc3283e68b0aL,0x85a366275bb08a33L, + 0xf72a3a0f6b0e4abeL,0xf7716d19faf0c6adL,0x22dcc0205379b25fL }, + { 0x7400bf8df9a56e11L,0x6cb8bad756a47f21L,0x7c97176f7a6eb644L, + 0xe8fd84f7d1f5b646L,0x98320a9444ddb054L,0x07071ba31dde86f5L } }, + /* 125 */ + { { 0x6fdfa0e598f8fcb9L,0x89cec8e094d0d70cL,0xa0899397106d20a8L, + 0x915bfb9aba8acc9cL,0x1370c94b5507e01cL,0x83246a608a821ffbL }, + { 0xa8273a9fbe3c378fL,0x7e54478935a25be9L,0x6cfa49724dd929d7L, + 0x987fed9d365bd878L,0x4982ac945c29a7aeL,0x4589a5d75ddd7ec5L } }, + /* 126 */ + { { 0x9fabb174a95540a9L,0x7cfb886f0162c5b0L,0x17be766bea3dee18L, + 0xff7da41fe88e624cL,0xad0b71eb8b919c38L,0x86a522e0f31ff9a9L }, + { 0xbc8e6f72868bc259L,0x6130c6383ccef9e4L,0x09f1f4549a466555L, + 0x8e6c0f0919b2bfb4L,0x945c46c90ca7bb22L,0xacd871684dafb67bL } }, + /* 127 */ + { { 0x090c72ca10c53841L,0xc20ae01b55a4fcedL,0x03f7ebd5e10234adL, + 0xb3f42a6a85892064L,0xbdbc30c0b4a14722L,0x971bc4378ca124ccL }, + { 0x6f79f46d517ff2ffL,0x6a9c96e2ecba947bL,0x5e79f2f462925122L, + 0x30a96bb16a4e91f1L,0x1147c9232d4c72daL,0x65bc311f5811e4dfL } }, + /* 128 */ + { { 0x87c7dd7d139b3239L,0x8b57824e4d833baeL,0xbcbc48789fff0015L, + 0x8ffcef8b909eaf1aL,0x9905f4eef1443a78L,0x020dd4a2e15cbfedL }, + { 0xca2969eca306d695L,0xdf940cadb93caf60L,0x67f7fab787ea6e39L, + 0x0d0ee10ff98c4fe5L,0xc646879ac19cb91eL,0x4b4ea50c7d1d7ab4L } }, + /* 129 */ + { { 0x19e409457a0db57eL,0xe6017cad9a8c9702L,0xdbf739e51be5cff9L, + 0x3646b3cda7a938a2L,0x0451108568350dfcL,0xad3bd6f356e098b5L }, + { 0x935ebabfee2e3e3eL,0xfbd01702473926cbL,0x7c735b029e9fb5aaL, + 0xc52a1b852e3feff0L,0x9199abd3046b405aL,0xe306fcec39039971L } }, + /* 130 */ + { { 0xd6d9aec823e4712cL,0x7ca8376cc3c198eeL,0xe6d8318731bebd8aL, + 0xed57aff3d88bfef3L,0x72a645eecf44edc7L,0xd4e63d0b5cbb1517L }, + { 0x98ce7a1cceee0ecfL,0x8f0126335383ee8eL,0x3b879078a6b455e8L, + 0xcbcd3d96c7658c06L,0x721d6fe70783336aL,0xf21a72635a677136L } }, + /* 131 */ + { { 0x19d8b3cd9586ba11L,0xd9e0aeb28a5c0480L,0xe4261dbf2230ef5cL, + 0x095a9dee02e6bf09L,0x8963723c80dc7784L,0x5c97dbaf145157b1L }, + { 0x97e744344bc4503eL,0x0fb1cb3185a6b370L,0x3e8df2becd205d4bL, + 0x497dd1bcf8f765daL,0x92ef95c76c988a1aL,0x3f924baa64dc4cfaL } }, + /* 132 */ + { { 0x6bf1b8dd7268b448L,0xd4c28ba1efd79b94L,0x2fa1f8c8e4e3551fL, + 0x769e3ad45c9187a9L,0x28843b4d40326c0dL,0xfefc809450d5d669L }, + { 0x30c85bfd90339366L,0x4eeb56f15ccf6c3aL,0x0e72b14928ccd1dcL, + 0x73ee85b5f2ce978eL,0xcdeb2bf33165bb23L,0x8106c9234e410abfL } }, + /* 133 */ + { { 0xc8df01617d02f4eeL,0x8a78154718e21225L,0x4ea895eb6acf9e40L, + 0x8b000cb56e5a633dL,0xf31d86d57e981ffbL,0xf5c8029c4475bc32L }, + { 0x764561ce1b568973L,0x2f809b81a62996ecL,0x9e513d64da085408L, + 0xc27d815de61ce309L,0x0da6ff99272999e0L,0xbd284779fead73f7L } }, + /* 134 */ + { { 0x6033c2f99b1cdf2bL,0x2a99cf06bc5fa151L,0x7d27d25912177b3bL, + 0xb1f15273c4485483L,0x5fd57d81102e2297L,0x3d43e017c7f6acb7L }, + { 0x41a8bb0b3a70eb28L,0x67de2d8e3e80b06bL,0x09245a4170c28de5L, + 0xad7dbcb1a7b26023L,0x70b08a352cbc6c1eL,0xb504fb669b33041fL } }, + /* 135 */ + { { 0xa8e85ab5f97a27c2L,0x6ac5ec8bc10a011bL,0x55745533ffbcf161L, + 0x01780e8565790a60L,0xe451bf8599ee75b0L,0x8907a63b39c29881L }, + { 0x76d46738260189edL,0x284a443647bd35cbL,0xd74e8c4020cab61eL, + 0x6264bf8c416cf20aL,0xfa5a6c955fd820ceL,0xfa7154d0f24bb5fcL } }, + /* 136 */ + { { 0x18482cec9b3f5034L,0x962d445acd9e68fdL,0x266fb1d695746f23L, + 0xc66ade5a58c94a4bL,0xdbbda826ed68a5b6L,0x05664a4d7ab0d6aeL }, + { 0xbcd4fe51025e32fcL,0x61a5aebfa96df252L,0xd88a07e231592a31L, + 0x5d9d94de98905517L,0x96bb40105fd440e7L,0x1b0c47a2e807db4cL } }, + /* 137 */ + { { 0x5c2a6ac808223878L,0xba08c269e65a5558L,0xd22b1b9b9bbc27fdL, + 0x919171bf72b9607dL,0x9ab455f9e588dc58L,0x6d54916e23662d93L }, + { 0x8da8e9383b1de0c1L,0xa84d186a804f278fL,0xbf4988ccd3461695L, + 0xf5eae3bee10eb0cbL,0x1ff8b68fbf2a66edL,0xa68daf67c305b570L } }, + /* 138 */ + { { 0xc1004cff44b2e045L,0x91b5e1364b1c05d4L,0x53ae409088a48a07L, + 0x73fb2995ea11bb1aL,0x320485703d93a4eaL,0xcce45de83bfc8a5fL }, + { 0xaff4a97ec2b3106eL,0x9069c630b6848b4fL,0xeda837a6ed76241cL, + 0x8a0daf136cc3f6cfL,0x199d049d3da018a8L,0xf867c6b1d9093ba3L } }, + /* 139 */ + { { 0xe4d42a5656527296L,0xae26c73dce71178dL,0x70a0adac6c251664L, + 0x813483ae5dc0ae1dL,0x7574eacddaab2dafL,0xc56b52dcc2d55f4fL }, + { 0x872bc16795f32923L,0x4be175815bdd2a89L,0x9b57f1e7a7699f00L, + 0x5fcd9c723ac2de02L,0x83af3ba192377739L,0xa64d4e2bfc50b97fL } }, + /* 140 */ + { { 0x2172dae20e552b40L,0x62f49725d34d52e8L,0x7930ee4007958f98L, + 0x56da2a90751fdd74L,0xf1192834f53e48c3L,0x34d2ac268e53c343L }, + { 0x1073c21813111286L,0x201dac14da9d9827L,0xec2c29dbee95d378L, + 0x9316f1191f3ee0b1L,0x7890c9f0544ce71cL,0xd77138af27612127L } }, + /* 141 */ + { { 0x78045e6d3b4ad1cdL,0xcd86b94e4aa49bc1L,0x57e51f1dfd677a16L, + 0xd9290935fa613697L,0x7a3f959334f4d893L,0x8c9c248b5d5fcf9bL }, + { 0x9f23a4826f70d4e9L,0x1727345463190ae9L,0x4bdd7c135b081a48L, + 0x1e2de38928d65271L,0x0bbaaa25e5841d1fL,0xc4c18a79746772e5L } }, + /* 142 */ + { { 0x10ee2681593375acL,0x4f3288be7dd5e113L,0x9a97b2fb240f3538L, + 0xfa11089f1de6b1e2L,0x516da5621351bc58L,0x573b61192dfa85b5L }, + { 0x89e966836cba7df5L,0xf299be158c28ab40L,0xe91c9348ad43fcbfL, + 0xe9bbc7cc9a1cefb3L,0xc8add876738b2775L,0x6e3b1f2e775eaa01L } }, + /* 143 */ + { { 0x0365a888b677788bL,0x634ae8c43fd6173cL,0x304987619e498dbeL, + 0x08c43e6dc8f779abL,0x068ae3844c09aca9L,0x2380c70b2018d170L }, + { 0xcf77fbc3a297c5ecL,0xdacbc853ca457948L,0x3690de04336bec7eL, + 0x26bbac6414eec461L,0xd1c23c7e1f713abfL,0xf08bbfcde6fd569eL } }, + /* 144 */ + { { 0x5f8163f484770ee3L,0x0e0c7f94744a1706L,0x9c8f05f7e1b2d46dL, + 0x417eafe7d01fd99aL,0x2ba15df511440e5bL,0xdc5c552a91a6fbcfL }, + { 0x86271d74a270f721L,0x32c0a075a004485bL,0x9d1a87e38defa075L, + 0xb590a7acbf0d20feL,0x430c41c28feda1f5L,0x454d287958f6ec24L } }, + /* 145 */ + { { 0x52b7a6357c525435L,0x3d9ef57f37c4bdbcL,0x2bb93e9edffcc475L, + 0xf7b8ba987710f3beL,0x42ee86da21b727deL,0x55ac3f192e490d01L }, + { 0x487e3a6ec0c1c390L,0x036fb345446cde7bL,0x089eb276496ae951L, + 0xedfed4d971ed1234L,0x661b0dd5900f0b46L,0x11bd6f1b8582f0d3L } }, + /* 146 */ + { { 0x5cf9350f076bc9d1L,0x15d903becf3cd2c3L,0x21cfc8c225af031cL, + 0xe0ad32488b1cc657L,0xdd9fb96370014e87L,0xf0f3a5a1297f1658L }, + { 0xbb908fbaf1f703aaL,0x2f9cc4202f6760baL,0x00ceec6666a38b51L, + 0x4deda33005d645daL,0xb9cf5c72f7de3394L,0xaeef65021ad4c906L } }, + /* 147 */ + { { 0x0583c8b17a19045dL,0xae7c3102d052824cL,0x2a234979ff6cfa58L, + 0xfe9dffc962c733c0L,0x3a7fa2509c0c4b09L,0x516437bb4fe21805L }, + { 0x9454e3d5c2a23ddbL,0x0726d887289c104eL,0x8977d9184fd15243L, + 0xc559e73f6d7790baL,0x8fd3e87d465af85fL,0xa2615c745feee46bL } }, + /* 148 */ + { { 0xc8d607a84335167dL,0x8b42d804e0f5c887L,0x5f9f13df398d11f9L, + 0x5aaa508720740c67L,0x83da9a6aa3d9234bL,0xbd3a5c4e2a54bad1L }, + { 0xdd13914c2db0f658L,0x29dcb66e5a3f373aL,0xbfd62df55245a72bL, + 0x19d1802391e40847L,0xd9df74dbb136b1aeL,0x72a06b6b3f93bc5bL } }, + /* 149 */ + { { 0x6da19ec3ad19d96fL,0xb342daa4fb2a4099L,0x0e61633a662271eaL, + 0x3bcece81ce8c054bL,0x7cc8e0618bd62dc6L,0xae189e19ee578d8bL }, + { 0x73e7a25ddced1eedL,0xc1257f0a7875d3abL,0x2cb2d5a21cfef026L, + 0xd98ef39bb1fdf61cL,0xcd8e6f6924e83e6cL,0xd71e7076c7b7088bL } }, + /* 150 */ + { { 0x339368309d4245bfL,0x22d962172ac2953bL,0xb3bf5a8256c3c3cdL, + 0x50c9be910d0699e8L,0xec0944638f366459L,0x6c056dba513b7c35L }, + { 0x687a6a83045ab0e3L,0x8d40b57f445c9295L,0x0f345048a16f5954L, + 0x64b5c6393d8f0a87L,0x106353a29f71c5e2L,0xdd58b475874f0dd4L } }, + /* 151 */ + { { 0x67ec084f62230c72L,0xf14f6cca481385e3L,0xf58bb4074cda7774L, + 0xe15011b1aa2dbb6bL,0xd488369d0c035ab1L,0xef83c24a8245f2fdL }, + { 0xfb57328f9fdc2538L,0x79808293191fe46aL,0xe28f5c4432ede548L, + 0x1b3cda99ea1a022cL,0x39e639b73df2ec7fL,0x77b6272b760e9a18L } }, + /* 152 */ + { { 0x2b1d51bda65d56d5L,0x3a9b71f97ea696e0L,0x95250ecc9904f4c4L, + 0x8bc4d6ebe75774b7L,0x0e343f8aeaeeb9aaL,0xc473c1d1930e04cbL }, + { 0x282321b1064cd8aeL,0xf4b4371e5562221cL,0xc1cc81ecd1bf1221L, + 0xa52a07a9e2c8082fL,0x350d8e59ba64a958L,0x29e4f3de6fb32c9aL } }, + /* 153 */ + { { 0x0aa9d56cba89aaa5L,0xf0208ac0c4c6059eL,0x7400d9c6bd6ddca4L, + 0xb384e475f2c2f74aL,0x4c1061fcb1562dd3L,0x3924e2482e153b8dL }, + { 0xf38b8d98849808abL,0x29bf3260a491aa36L,0x85159ada88220edeL, + 0x8b47915bbe5bc422L,0xa934d72ed7300967L,0xc4f303982e515d0dL } }, + /* 154 */ + { { 0xe3e9ee421b1de38bL,0xa124e25a42636760L,0x90bf73c090165b1aL, + 0x21802a34146434c5L,0x54aa83f22e1fa109L,0x1d4bd03ced9c51e9L }, + { 0xc2d96a38798751e6L,0xed27235f8c3507f5L,0xb5fb80e2c8c24f88L, + 0xf873eefad37f4f78L,0x7229fd74f224ba96L,0x9dcd91999edd7149L } }, + /* 155 */ + { { 0xee9f81a64e94f22aL,0xe5609892f71ec341L,0x6c818ddda998284eL, + 0x9fd472953b54b098L,0x47a6ac030e8a7cc9L,0xde684e5eb207a382L }, + { 0x4bdd1ecd2b6b956bL,0x09084414f01b3583L,0xe2f80b3255233b14L, + 0x5a0fec54ef5ebc5eL,0x74cf25e6bf8b29a2L,0x1c757fa07f29e014L } }, + /* 156 */ + { { 0x1bcb5c4aeb0fdfe4L,0xd7c649b3f0899367L,0xaef68e3f05bc083bL, + 0x57a06e46a78aa607L,0xa2136ecc21223a44L,0x89bd648452f5a50bL }, + { 0x724411b94455f15aL,0x23dfa97008a9c0fdL,0x7b0da4d16db63befL, + 0x6f8a7ec1fb162443L,0xc1ac9ceee98284fbL,0x085a582b33566022L } }, + /* 157 */ + { { 0x15cb61f9ec1f138aL,0x11c9a230668f0c28L,0xac829729df93f38fL, + 0xcef256984048848dL,0x3f686da02bba8fbfL,0xed5fea78111c619aL }, + { 0x9b4f73bcd6d1c833L,0x5095160686e7bf80L,0xa2a73508042b1d51L, + 0x9ef6ea495fb89ec2L,0xf1008ce95ef8b892L,0x78a7e6849ae8568bL } }, + /* 158 */ + { { 0x3fe83a7c10470cd8L,0x92734682f86df000L,0xb5dac06bda9409b5L, + 0x1e7a966094939c5fL,0xdec6c1505cc116dcL,0x1a52b40866bac8ccL }, + { 0x5303a3656e864045L,0x45eae72a9139efc1L,0x83bec6466f31d54fL, + 0x2fb4a86f6e958a6dL,0x6760718e4ff44030L,0x008117e3e91ae0dfL } }, + /* 159 */ + { { 0x5d5833ba384310a2L,0xbdfb4edc1fd6c9fcL,0xb9a4f102849c4fb8L, + 0xe5fb239a581c1e1fL,0xba44b2e7d0a9746dL,0x78f7b7683bd942b9L }, + { 0x076c8ca1c87607aeL,0x82b23c2ed5caaa7eL,0x6a581f392763e461L, + 0xca8a5e4a3886df11L,0xc87e90cf264e7f22L,0x04f74870215cfcfcL } }, + /* 160 */ + { { 0x5285d116141d161cL,0x67cd2e0e93c4ed17L,0x12c62a647c36187eL, + 0xf5329539ed2584caL,0xc4c777c442fbbd69L,0x107de7761bdfc50aL }, + { 0x9976dcc5e96beebdL,0xbe2aff95a865a151L,0x0e0a9da19d8872afL, + 0x5e357a3da63c17ccL,0xd31fdfd8e15cc67cL,0xc44bbefd7970c6d8L } }, + /* 161 */ + { { 0x703f83e24c0c62f1L,0x9b1e28ee4e195572L,0x6a82858bfe26ccedL, + 0xd381c84bc43638faL,0x94f72867a5ba43d8L,0x3b4a783d10b82743L }, + { 0xee1ad7b57576451eL,0xc3d0b59714b6b5c8L,0x3dc30954fcacc1b8L, + 0x55df110e472c9d7bL,0x97c86ed702f8a328L,0xd043341388dc098fL } }, + /* 162 */ + { { 0x1a60d1522ca8f2feL,0x61640948491bd41fL,0x6dae29a558dfe035L, + 0x9a615bea278e4863L,0xbbdb44779ad7c8e5L,0x1c7066302ceac2fcL }, + { 0x5e2b54c699699b4bL,0xb509ca6d239e17e8L,0x728165feea063a82L, + 0x6b5e609db6a22e02L,0x12813905b26ee1dfL,0x07b9f722439491faL } }, + /* 163 */ + { { 0x1592ec1448ff4e49L,0x3e4e9f176d644129L,0x7acf82881156acc0L, + 0x5aa34ba8bb092b0bL,0xcd0f90227d38393dL,0x416724ddea4f8187L }, + { 0x3c4e641cc0139e73L,0xe0fe46cf91e4d87dL,0xedb3c792cab61f8aL, + 0x4cb46de4d3868753L,0xe449c21d20f1098aL,0x5e5fd059f5b8ea6eL } }, + /* 164 */ + { { 0x7fcadd4675856031L,0x89c7a4cdeaf2fbd0L,0x1af523ce7a87c480L, + 0xe5fc109561d9ae90L,0x3fb5864fbcdb95f5L,0xbeb5188ebb5b2c7dL }, + { 0x3d1563c33ae65825L,0x116854c40e57d641L,0x11f73d341942ebd3L, + 0x24dc5904c06955b3L,0x8a0d4c83995a0a62L,0xfb26b86d5d577b7dL } }, + /* 165 */ + { { 0xc53108e7c686ae17L,0x9090d739d1c1da56L,0x4583b0139aec50aeL, + 0xdd9a088ba49a6ab2L,0x28192eeaf382f850L,0xcc8df756f5fe910eL }, + { 0x877823a39cab7630L,0x64984a9afb8e7fc1L,0x5448ef9c364bfc16L, + 0xbbb4f871c44e2a9aL,0x901a41ab435c95e9L,0xc6c23e5faaa50a06L } }, + /* 166 */ + { { 0xb78016c19034d8ddL,0x856bb44b0b13e79bL,0x85c6409ab3241a05L, + 0x8d2fe19a2d78ed21L,0xdcc7c26d726eddf2L,0x3ccaff5f25104f04L }, + { 0x397d7edc6b21f843L,0xda88e4dde975de4cL,0x5273d3964f5ab69eL, + 0x537680e39aae6cc0L,0xf749cce53e6f9461L,0x021ddbd9957bffd3L } }, + /* 167 */ + { { 0x7b64585f777233cfL,0xfe6771f60942a6f0L,0x636aba7adfe6eef0L, + 0x63bbeb5686038029L,0xacee5842de8fcf36L,0x48d9aa99d4a20524L }, + { 0xcff7a74c0da5e57aL,0xc232593ce549d6c9L,0x68504bccf0f2287bL, + 0x6d7d098dbc8360b5L,0xeac5f1495b402f41L,0x61936f11b87d1bf1L } }, + /* 168 */ + { { 0xaa9da167b8153a9dL,0xa49fe3ac9e83ecf0L,0x14c18f8e1b661384L, + 0x61c24dab38434de1L,0x3d973c3a283dae96L,0xc99baa0182754fc9L }, + { 0x477d198f4c26b1e3L,0x12e8e186a7516202L,0x386e52f6362addfaL, + 0x31e8f695c3962853L,0xdec2af136aaedb60L,0xfcfdb4c629cf74acL } }, + /* 169 */ + { { 0x6b3ee958cca40298L,0xc3878153f2f5d195L,0x0c565630ed2eae5bL, + 0xd089b37e3a697cf2L,0xc2ed2ac7ad5029eaL,0x7e5cdfad0f0dda6aL }, + { 0xf98426dfd9b86202L,0xed1960b14335e054L,0x1fdb02463f14639eL, + 0x17f709c30db6c670L,0xbfc687ae773421e1L,0x13fefc4a26c1a8acL } }, + /* 170 */ + { { 0xe361a1987ffa0a5fL,0xf4b26102c63fe109L,0x264acbc56c74e111L, + 0x4af445fa77abebafL,0x448c4fdd24cddb75L,0x0b13157d44506eeaL }, + { 0x22a6b15972e9993dL,0x2c3c57e485e5ecbeL,0xa673560bfd83e1a1L, + 0x6be23f82c3b8c83bL,0x40b13a9640bbe38eL,0x66eea033ad17399bL } }, + /* 171 */ + { { 0x49fc6e95b4c6c693L,0xefc735de36af7d38L,0xe053343d35fe42fcL, + 0xf0aa427c6a9ab7c3L,0xc79f04364a0fcb24L,0x1628724393ebbc50L }, + { 0x5c3d6bd016927e1eL,0x40158ed2673b984cL,0xa7f86fc84cd48b9aL, + 0x1643eda660ea282dL,0x45b393eae2a1beedL,0x664c839e19571a94L } }, + /* 172 */ + { { 0x5774575027eeaf94L,0x2875c925ea99e1e7L,0xc127e7ba5086adeaL, + 0x765252a086fe424fL,0x1143cc6c2b6c0281L,0xc9bb2989d671312dL }, + { 0x880c337c51acb0a5L,0xa3710915d3c60f78L,0x496113c09262b6edL, + 0x5d25d9f89ce48182L,0x53b6ad72b3813586L,0x0ea3bebc4c0e159cL } }, + /* 173 */ + { { 0xcaba450ac5e49beaL,0x684e54157c05da59L,0xa2e9cab9de7ac36cL, + 0x4ca79b5f2e6f957bL,0xef7b024709b817b1L,0xeb3049907d89df0fL }, + { 0x508f730746fe5096L,0x695810e82e04eaafL,0x88ef1bd93512f76cL, + 0x776613513ebca06bL,0xf7d4863accf158b7L,0xb2a81e4494ee57daL } }, + /* 174 */ + { { 0xff288e5b6d53e6baL,0xa90de1a914484ea2L,0x2fadb60ced33c8ecL, + 0x579d6ef328b66a40L,0x4f2dd6ddec24372dL,0xe9e33fc91d66ec7dL }, + { 0x110899d2039eab6eL,0xa31a667a3e97bb5eL,0x6200166dcfdce68eL, + 0xbe83ebae5137d54bL,0x085f7d874800acdfL,0xcf4ab1330c6f8c86L } }, + /* 175 */ + { { 0x03f65845931e08fbL,0x6438551e1506e2c0L,0x5791f0dc9c36961fL, + 0x68107b29e3dcc916L,0x83242374f495d2caL,0xd8cfb6636ee5895bL }, + { 0x525e0f16a0349b1bL,0x33cd2c6c4a0fab86L,0x46c12ee82af8dda9L, + 0x7cc424ba71e97ad3L,0x69766ddf37621eb0L,0x95565f56a5f0d390L } }, + /* 176 */ + { { 0xe0e7bbf21a0f5e94L,0xf771e1151d82d327L,0x10033e3dceb111faL, + 0xd269744dd3426638L,0xbdf2d9da00d01ef6L,0x1cb80c71a049ceafL }, + { 0x17f183289e21c677L,0x6452af0519c8f98bL,0x35b9c5f780b67997L, + 0x5c2e1cbe40f8f3d4L,0x43f9165666d667caL,0x9faaa059cf9d6e79L } }, + /* 177 */ + { { 0x8ad246180a078fe6L,0xf6cc73e6464fd1ddL,0x4d2ce34dc3e37448L, + 0x624950c5e3271b5fL,0x62910f5eefc5af72L,0x8b585bf8aa132bc6L }, + { 0x11723985a839327fL,0x34e2d27d4aac252fL,0x402f59ef6296cc4eL, + 0x00ae055c47053de9L,0xfc22a97228b4f09bL,0xa9e86264fa0c180eL } }, + /* 178 */ + { { 0x0b7b6224bc310eccL,0x8a1a74f167fa14edL,0x87dd09607214395cL, + 0xdf1b3d09f5c91128L,0x39ff23c686b264a8L,0xdc2d49d03e58d4c5L }, + { 0x2152b7d3a9d6f501L,0xf4c32e24c04094f7L,0xc6366596d938990fL, + 0x084d078f94fb207fL,0xfd99f1d7328594cbL,0x36defa64cb2d96b3L } }, + /* 179 */ + { { 0x4619b78113ed7cbeL,0x95e500159784bd0eL,0x2a32251c2c7705feL, + 0xa376af995f0dd083L,0x55425c6c0361a45bL,0x812d2cef1f291e7bL }, + { 0xccf581a05fd94972L,0x26e20e39e56dc383L,0x0093685d63dbfbf0L, + 0x1fc164cc36b8c575L,0xb9c5ab81390ef5e7L,0x40086beb26908c66L } }, + /* 180 */ + { { 0xe5e54f7937e3c115L,0x69b8ee8cc1445a8aL,0x79aedff2b7659709L, + 0xe288e1631b46fbe6L,0xdb4844f0d18d7bb7L,0xe0ea23d048aa6424L }, + { 0x714c0e4ef3d80a73L,0x87a0aa9e3bd64f98L,0x8844b8a82ec63080L, + 0xe0ac9c30255d81a3L,0x86151237455397fcL,0x0b9794642f820155L } }, + /* 181 */ + { { 0x127a255a4ae03080L,0x232306b4580a89fbL,0x04e8cd6a6416f539L, + 0xaeb70dee13b02a0eL,0xa3038cf84c09684aL,0xa710ec3c28e433eeL }, + { 0x77a72567681b1f7dL,0x86fbce952fc28170L,0xd3408683f5735ac8L, + 0x3a324e2a6bd68e93L,0x7ec74353c027d155L,0xab60354cd4427177L } }, + /* 182 */ + { { 0x32a5342aef4c209dL,0x2ba7527408d62704L,0x4bb4af6fc825d5feL, + 0x1c3919ced28e7ff1L,0x1dfc2fdcde0340f6L,0xc6580baf29f33ba9L }, + { 0xae121e7541d442cbL,0x4c7727fd3a4724e4L,0xe556d6a4524f3474L, + 0x87e13cc7785642a2L,0x182efbb1a17845fdL,0xdcec0cf14e144857L } }, + /* 183 */ + { { 0x1cb89541e9539819L,0xc8cb3b4f9d94dbf1L,0x1d353f63417da578L, + 0xb7a697fb8053a09eL,0x8d841731c35d8b78L,0x85748d6fb656a7a9L }, + { 0x1fd03947c1859c5dL,0x6ce965c1535d22a2L,0x1966a13e0ca3aadcL, + 0x9802e41d4fb14effL,0xa9048cbb76dd3fcdL,0x89b182b5e9455bbaL } }, + /* 184 */ + { { 0xd777ad6a43360710L,0x841287ef55e9936bL,0xbaf5c67004a21b24L, + 0xf2c0725f35ad86f1L,0x338fa650c707e72eL,0x2bf8ed2ed8883e52L }, + { 0xb0212cf4b56e0d6aL,0x50537e126843290cL,0xd8b184a198b3dc6fL, + 0xd2be9a350210b722L,0x407406db559781eeL,0x5a78d5910bc18534L } }, + /* 185 */ + { { 0x4d57aa2ad748b02cL,0xbe5b3451a12b3b95L,0xadca7a4564711258L, + 0x597e091a322153dbL,0xf327100632eb1eabL,0xbd9adcba2873f301L }, + { 0xd1dc79d138543f7fL,0x00022092921b1fefL,0x86db3ef51e5df8edL, + 0x888cae049e6b944aL,0x71bd29ec791a32b4L,0xd3516206a6d1c13eL } }, + /* 186 */ + { { 0x2ef6b95255924f43L,0xd2f401ae4f9de8d5L,0xfc73e8d7adc68042L, + 0x627ea70c0d9d1bb4L,0xc3bb3e3ebbf35679L,0x7e8a254ad882dee4L }, + { 0x08906f50b5924407L,0xf14a0e61a1ad444aL,0xaa0efa2165f3738eL, + 0xd60c7dd6ae71f161L,0x9e8390faf175894dL,0xd115cd20149f4c00L } }, + /* 187 */ + { { 0x2f2e2c1da52abf77L,0xc2a0dca554232568L,0xed423ea254966dccL, + 0xe48c93c7cd0dd039L,0x1e54a225176405c7L,0x1efb5b1670d58f2eL }, + { 0xa751f9d994fb1471L,0xfdb31e1f67d2941dL,0xa6c74eb253733698L, + 0xd3155d1189a0f64aL,0x4414cfe4a4b8d2b6L,0x8d5a4be8f7a8e9e3L } }, + /* 188 */ + { { 0x5c96b4d452669e98L,0x4547f9228fd42a03L,0xcf5c1319d285174eL, + 0x805cd1ae064bffa0L,0x50e8bc4f246d27e7L,0xf89ef98fd5781e11L }, + { 0xb4ff95f6dee0b63fL,0xad850047222663a4L,0x026918604d23ce9cL, + 0x3e5309ce50019f59L,0x27e6f72269a508aeL,0xe9376652267ba52cL } }, + /* 189 */ + { { 0xa04d289cc0368708L,0xc458872f5e306e1dL,0x76fa23de33112feaL, + 0x718e39746efde42eL,0xf0c98cdc1d206091L,0x5fa3ca6214a71987L }, + { 0xeee8188bdcaa9f2aL,0x312cc732589a860dL,0xf9808dd6c63aeb1fL, + 0x70fd43db4ea62b53L,0x2c2bfe34890b6e97L,0x105f863cfa426aa6L } }, + /* 190 */ + { { 0x0b29795db38059adL,0x5686b77e90647ea0L,0xeff0470edb473a3eL, + 0x278d2340f9b6d1e2L,0xebbff95bbd594ec7L,0xf4b72334d3a7f23dL }, + { 0x2a285980a5a83f0bL,0x0786c41a9716a8b3L,0x138901bd22511812L, + 0xd1b55221e2fede6eL,0x0806e264df4eb590L,0x6c4c897e762e462eL } }, + /* 191 */ + { { 0xd10b905fb4b41d9dL,0x826ca4664523a65bL,0x535bbd13b699fa37L, + 0x5b9933d773bc8f90L,0x9332d61fcd2118adL,0x158c693ed4a65fd0L }, + { 0x4ddfb2a8e6806e63L,0xe31ed3ecb5de651bL,0xf9460e51819bc69aL, + 0x6229c0d62c76b1f8L,0xbb78f231901970a3L,0x31f3820f9cee72b8L } }, + /* 192 */ + { { 0xe931caf2c09e1c72L,0x0715f29812990cf4L,0x33aad81d943262d8L, + 0x5d292b7a73048d3fL,0xb152aaa4dc7415f6L,0xc3d10fd90fd19587L }, + { 0xf76b35c575ddadd0L,0x9f5f4a511e7b694cL,0x2f1ab7ebc0663025L, + 0x01c9cc87920260b0L,0xc4b1f61a05d39da6L,0x6dcd76c4eb4a9c4eL } }, + /* 193 */ + { { 0x0ba0916ffdc83f01L,0x354c8b449553e4f9L,0xa6cc511affc5e622L, + 0xb954726ae95be787L,0xcb04811575b41a62L,0xfa2ae6cdebfde989L }, + { 0x6376bbc70f24659aL,0x13a999fd4c289c43L,0xc7134184ec9abd8bL, + 0x28c02bf6a789ab04L,0xff841ebcd3e526ecL,0x442b191e640893a8L } }, + /* 194 */ + { { 0x4cac6c62fa2b6e20L,0x97f29e9bf6d69861L,0x228ab1dbbc96d12dL, + 0x6eb913275e8e108dL,0xd4b3d4d140771245L,0x61b20623ca8a803aL }, + { 0x2c2f3b41a6a560b1L,0x879e1d403859fcf4L,0x7cdb5145024dbfc3L, + 0x55d08f153bfa5315L,0x2f57d773aa93823aL,0xa97f259cc6a2c9a2L } }, + /* 195 */ + { { 0xc306317be58edbbbL,0x25ade51c79dfdf13L,0x6b5beaf116d83dd6L, + 0xe8038a441dd8f925L,0x7f00143cb2a87b6bL,0xa885d00df5b438deL }, + { 0xe9f76790cf9e48bdL,0xf0bdf9f0a5162768L,0x0436709fad7b57cbL, + 0x7e151c12f7c15db7L,0x3514f0225d90ee3bL,0x2e84e8032c361a8dL } }, + /* 196 */ + { { 0x2277607d563ec8d8L,0xa661811fe3934cb7L,0x3ca72e7af58fd5deL, + 0x7989da0462294c6aL,0x88b3708bf6bbefe9L,0x0d524cf753ed7c82L }, + { 0x69f699ca2f30c073L,0xf0fa264b9dc1dcf3L,0x44ca456805f0aaf6L, + 0x0f5b23c7d19b9bafL,0x39193f41eabd1107L,0x9e3e10ad2a7c9b83L } }, + /* 197 */ + { { 0xa90824f0d4ae972fL,0x43eef02bc6e846e7L,0x7e46061229d2160aL, + 0x29a178acfe604e91L,0x23056f044eb184b2L,0x4fcad55feb54cdf4L }, + { 0xa0ff96f3ae728d15L,0x8a2680c6c6a00331L,0x5f84cae07ee52556L, + 0x5e462c3ac5a65dadL,0x5d2b81dfe2d23f4fL,0x6e47301bc5b1eb07L } }, + /* 198 */ + { { 0x77411d68af8219b9L,0xcb883ce651b1907aL,0x25c87e57101383b5L, + 0x9c7d9859982f970dL,0xaa6abca5118305d2L,0x725fed2f9013a5dbL }, + { 0x487cdbafababd109L,0xc0f8cf5687586528L,0xa02591e68ad58254L, + 0xc071b1d1debbd526L,0x927dfe8b961e7e31L,0x55f895f99263dfe1L } }, + /* 199 */ + { { 0xf899b00db175645bL,0x51f3a627b65b4b92L,0xa2f3ac8db67399efL, + 0xe717867fe400bc20L,0x42cc90201967b952L,0x3d5967513ecd1de1L }, + { 0xd41ebcdedb979775L,0x99ba61bc6a2e7e88L,0x039149a5321504f2L, + 0xe7dc231427ba2fadL,0x9f556308b57d8368L,0x2b6d16c957da80a7L } }, + /* 200 */ + { { 0x84af5e76279ad982L,0x9bb4c92d9c8b81a6L,0xd79ad44e0e698e67L, + 0xe8be9048265fc167L,0xf135f7e60c3a4cccL,0xa0a10d38b8863a33L }, + { 0xe197247cd386efd9L,0x0eefd3f9b52346c2L,0xc22415f978607bc8L, + 0xa2a8f862508674ceL,0xa72ad09ec8c9d607L,0xcd9f0ede50fa764fL } }, + /* 201 */ + { { 0x063391c7d1a46d4dL,0x2df51c119eb01693L,0xc5849800849e83deL, + 0x48fd09aa8ad08382L,0xa405d873aa742736L,0xee49e61ee1f9600cL }, + { 0xd76676be48c76f73L,0xd9c100f601274b2aL,0x110bb67c83f8718dL, + 0xec85a42002fc0d73L,0xc0449e1e744656adL,0x28ce737637d9939bL } }, + /* 202 */ + { { 0x97e9af7244544ac7L,0xf2c658d5ba010426L,0x732dec39fb3adfbdL, + 0xd12faf91a2df0b07L,0x8ac267252171e208L,0xf820cdc85b24fa54L }, + { 0x307a6eea94f4cf77L,0x18c783d2944a33c6L,0x4b939d4c0b741ac5L, + 0x1d7acd153ffbb6e4L,0x06a248587a255e44L,0x14fbc494ce336d50L } }, + /* 203 */ + { { 0x9b920c0c51584e3cL,0xc7733c59f7e54027L,0xe24ce13988422bbeL, + 0x11ada812523bd6abL,0xde068800b88e6defL,0x7b872671fe8c582dL }, + { 0x4e746f287de53510L,0x492f8b99f7971968L,0x1ec80bc77d928ac2L, + 0xb3913e48432eb1b5L,0xad08486632028f6eL,0x122bb8358fc2f38bL } }, + /* 204 */ + { { 0x0a9f3b1e3b0b29c3L,0x837b64324fa44151L,0xb9905c9217b28ea7L, + 0xf39bc93798451750L,0xcd383c24ce8b6da1L,0x299f57db010620b2L }, + { 0x7b6ac39658afdce3L,0xa15206b33d05ef47L,0xa0ae37e2b9bb02ffL, + 0x107760ab9db3964cL,0xe29de9a067954beaL,0x446a1ad8431c3f82L } }, + /* 205 */ + { { 0xc6fecea05c6b8195L,0xd744a7c5f49e71b9L,0xa8e96acc177a7ae7L, + 0x1a05746c358773a7L,0xa416214637567369L,0xaa0217f787d1c971L }, + { 0x61e9d15877fd3226L,0x0f6f2304e4f600beL,0xa9c4cebc7a6dff07L, + 0xd15afa0109f12a24L,0x2bbadb228c863ee9L,0xa28290e4e5eb8c78L } }, + /* 206 */ + { { 0x55b87fa03e9de330L,0x12b26066195c145bL,0xe08536e0a920bef0L, + 0x7bff6f2c4d195adcL,0x7f319e9d945f4187L,0xf9848863f892ce47L }, + { 0xd0efc1d34fe37657L,0x3c58de825cf0e45aL,0x626ad21a8b0ccbbeL, + 0xd2a31208af952fc5L,0x81791995eb437357L,0x5f19d30f98e95d4fL } }, + /* 207 */ + { { 0x72e83d9a0e6865bbL,0x22f5af3bf63456a6L,0x409e9c73463c8d9eL, + 0x40e9e578dfe6970eL,0x876b6efa711b91caL,0x895512cf942625a3L }, + { 0x84c8eda8cb4e462bL,0x84c0154a4412e7c8L,0x04325db1ceb7b71fL, + 0x1537dde366f70877L,0xf3a093991992b9acL,0xa7316606d498ae77L } }, + /* 208 */ + { { 0x13990d2fcad260f5L,0x76c3be29eec0e8c0L,0x7dc5bee00f7bd7d5L, + 0x9be167d2efebda4bL,0xcce3dde69122b87eL,0x75a28b0982b5415cL }, + { 0xf6810bcde84607a6L,0xc6d581286f4dbf0dL,0xfead577d1b4dafebL, + 0x9bc440b2066b28ebL,0x53f1da978b17e84bL,0x0459504bcda9a575L } }, + /* 209 */ + { { 0x13e39a02329e5836L,0x2c9e7d51f717269dL,0xc5ac58d6f26c963bL, + 0x3b0c6c4379967bf5L,0x60bbea3f55908d9dL,0xd84811e7f07c9ad1L }, + { 0xfe7609a75bd20e4aL,0xe4325dd20a70baa8L,0x3711f370b3600386L, + 0x97f9562fd0924302L,0x040dc0c34acc4436L,0xfd6d725cde79cdd4L } }, + /* 210 */ + { { 0xb3efd0e3cf13eafbL,0x21009cbb5aa0ae5fL,0xe480c55379022279L, + 0x755cf334b2fc9a6dL,0x8564a5bf07096ae7L,0xddd649d0bd238139L }, + { 0xd0de10b18a045041L,0x6e05b413c957d572L,0x5c5ff8064e0fb25cL, + 0xd933179b641162fbL,0x42d48485e57439f9L,0x70c5bd0a8a8d72aaL } }, + /* 211 */ + { { 0xa767173897bdf646L,0xaa1485b4ab329f7cL,0xce3e11d6f8f25fdfL, + 0x76a3fc7ec6221824L,0x045f281ff3924740L,0x24557d4e96d13a9aL }, + { 0x875c804bdd4c27cdL,0x11c5f0f40f5c7feaL,0xac8c880bdc55ff7eL, + 0x2acddec51103f101L,0x38341a21f99faa89L,0xc7b67a2cce9d6b57L } }, + /* 212 */ + { { 0x9a0d724f8e357586L,0x1d7f4ff5df648da0L,0x9c3e6c9bfdee62a5L, + 0x0499cef00389b372L,0xe904050d98eab879L,0xe8eef1b66c051617L }, + { 0xebf5bfebc37e3ca9L,0x7c5e946da4e0b91dL,0x790973142c4bea28L, + 0x81f6c109ee67b2b7L,0xaf237d9bdafc5edeL,0xd2e602012abb04c7L } }, + /* 213 */ + { { 0x6156060c8a4f57bfL,0xf9758696ff11182aL,0x8336773c6296ef00L, + 0x9c054bceff666899L,0xd6a11611719cd11cL,0x9824a641dbe1acfaL }, + { 0x0b7b7a5fba89fd01L,0xf8d3b809889f79d8L,0xc5e1ea08f578285cL, + 0x7ac74536ae6d8288L,0x5d37a2007521ef5fL,0x5ecc4184b260a25dL } }, + /* 214 */ + { { 0xddcebb19a708c8d3L,0xe63ed04fc63f81ecL,0xd045f5a011873f95L, + 0x3b5ad54479f276d5L,0x81272a3d425ae5b3L,0x8bfeb50110ce1605L }, + { 0x4233809c888228bfL,0x4bd82acfb2aff7dfL,0x9c68f1800cbd4a7fL, + 0xfcd771246b44323dL,0x60c0fcf6891db957L,0xcfbb4d8904da8f7fL } }, + /* 215 */ + { { 0x9a6a5df93b26139aL,0x3e076a83b2cc7eb8L,0x47a8e82d5a964bcdL, + 0x8a4e2a39b9278d6bL,0x93506c98e4443549L,0x06497a8ff1e0d566L }, + { 0x3dee8d992b1efa05L,0x2da63ca845393e33L,0xa4af7277cf0579adL, + 0xaf4b46393236d8eaL,0x6ccad95b32b617f5L,0xce76d8b8b88bb124L } }, + /* 216 */ + { { 0x63d2537a083843dcL,0x89eb35141e4153b4L,0x5175ebc4ea9afc94L, + 0x7a6525808ed1aed7L,0x67295611d85e8297L,0x8dd2d68bb584b73dL }, + { 0x237139e60133c3a4L,0x9de838ab4bd278eaL,0xe829b072c062fcd9L, + 0x70730d4f63ba8706L,0x6080483fd3cd05ecL,0x872ab5b80c85f84dL } }, + /* 217 */ + { { 0xfc0776d3999d4d49L,0xa3eb59deec3f45e7L,0xbc990e440dae1fc1L, + 0x33596b1ea15371ffL,0xd447dcb29bc7ab25L,0xcd5b63e935979582L }, + { 0xae3366fa77d1ff11L,0x59f28f05edee6903L,0x6f43fed1a4433bf2L, + 0x15409c9bdf9ce00eL,0x21b5cdedaca9c5dcL,0xf9f3359582d7bdb4L } }, + /* 218 */ + { { 0x959443789422c792L,0x239ea923c958b8bfL,0x4b61a247df076541L, + 0x4d29ce85bb9fc544L,0x9a692a670b424559L,0x6e0ca5a00e486900L }, + { 0x6b79a78285b3beceL,0x41f35e39c61f9892L,0xff82099aae747f82L, + 0x58c8ae3fd0ca59d6L,0x4ac930e299406b5fL,0x2ce04eb99df24243L } }, + /* 219 */ + { { 0x4366b9941ac37b82L,0xff0c728d25b04d83L,0x1f55136119c47b7cL, + 0xdbf2d5edbeff13e7L,0xf78efd51e12a683dL,0x82cd85b9989cf9c4L }, + { 0xe23c6db6e0cb5d37L,0x818aeebd72ee1a15L,0x8212aafd28771b14L, + 0x7bc221d91def817dL,0xdac403a29445c51fL,0x711b051712c3746bL } }, + /* 220 */ + { { 0x0ed9ed485ea99eccL,0xf799500db8cab5e1L,0xa8ec87dcb570cbdcL, + 0x52cfb2c2d35dfaecL,0x8d31fae26e4d80a4L,0xe6a37dc9dcdeabe5L }, + { 0x5d365a341deca452L,0x09a5f8a50d68b44eL,0x59238ea5a60744b1L, + 0xf2fedc0dbb4249e9L,0xe395c74ea909b2e3L,0xe156d1a539388250L } }, + /* 221 */ + { { 0xd796b3d047181ae9L,0xbaf44ba844197808L,0xe693309434cf3facL, + 0x41aa6adec3bd5c46L,0x4fda75d8eed947c6L,0xacd9d4129ea5a525L }, + { 0x65cc55a3d430301bL,0x3c9a5bcf7b52ea49L,0x22d319cf159507f0L, + 0x2ee0b9b5de74a8ddL,0x20c26a1e877ac2b6L,0x387d73da92e7c314L } }, + /* 222 */ + { { 0x13c4833e8cd3fdacL,0x76fcd473332e5b8eL,0xff671b4be2fe1fd3L, + 0x4d734e8b5d98d8ecL,0xb1ead3c6514bbc11L,0xd14ca8587b390494L }, + { 0x95a443af5d2d37e9L,0x73c6ea7300464622L,0xa44aeb4b15755044L, + 0xba3f8575fab58feeL,0x9779dbc9dc680a6fL,0xe1ee5f5a7b37ddfcL } }, + /* 223 */ + { { 0xcd0b464812d29f46L,0x93295b0b0ed53137L,0xbfe2609480bef6c9L, + 0xa656578854248b00L,0x69c43fca80e7f9c4L,0x2190837bbe141ea1L }, + { 0x875e159aa1b26cfbL,0x90ca9f877affe852L,0x15e6550d92ca598eL, + 0xe3e0945d1938ad11L,0xef7636bb366ef937L,0xb6034d0bb39869e5L } }, + /* 224 */ + { { 0x4d255e3026d8356eL,0xf83666edd314626fL,0x421ddf61d0c8ed64L, + 0x96e473c526677b61L,0xdad4af7e9e9b18b3L,0xfceffd4aa9393f75L }, + { 0x843138a111c731d5L,0x05bcb3a1b2f141d9L,0x20e1fa95617b7671L, + 0xbefce81288ccec7bL,0x582073dc90f1b568L,0xf572261a1f055cb7L } }, + /* 225 */ + { { 0xf314827736973088L,0xc008e70886a9f980L,0x1b795947e046c261L, + 0xdf1e6a7dca76bca0L,0xabafd88671acddf0L,0xff7054d91364d8f4L }, + { 0x2cf63547e2260594L,0x468a5372d73b277eL,0xc7419e24ef9bd35eL, + 0x2b4a1c2024043cc3L,0xa28f047a890b39cdL,0xdca2cea146f9a2e3L } }, + /* 226 */ + { { 0xab78873653277538L,0xa734e225cf697738L,0x66ee1d1e6b22e2c1L, + 0x2c615389ebe1d212L,0xf36cad4002bb0766L,0x120885c33e64f207L }, + { 0x59e77d5690fbfec2L,0xf9e781aad7a574aeL,0x801410b05d045e53L, + 0xd3b5f0aaa91b5f0eL,0xb3d1df007fbb3521L,0x11c4b33ec72bee9aL } }, + /* 227 */ + { { 0xd32b983283c3a7f3L,0x8083abcf88d8a354L,0xdeb1640450f4ec5aL, + 0x18d747f0641e2907L,0x4e8978aef1bbf03eL,0x932447dc88a0cd89L }, + { 0x561e0febcf3d5897L,0xfc3a682f13600e6dL,0xc78b9d73d16a6b73L, + 0xe713feded29bf580L,0x0a22522308d69e5cL,0x3a924a571ff7fda4L } }, + /* 228 */ + { { 0xfb64554cb4093beeL,0xa6d65a25a58c6ec0L,0x4126994d43d0ed37L, + 0xa5689a5155152d44L,0xb8e5ea8c284caa8dL,0x33f05d4fd1f25538L }, + { 0xe0fdfe091b615d6eL,0x2ded7e8f705507daL,0xdd5631e517bbcc80L, + 0x4f87453e267fd11fL,0xc6da723fff89d62dL,0x55cbcae2e3cda21dL } }, + /* 229 */ + { { 0x336bc94e6b4e84f3L,0x728630314ef72c35L,0x6d85fdeeeeb57f99L, + 0x7f4e3272a42ece1bL,0x7f86cbb536f0320aL,0xf09b6a2b923331e6L }, + { 0x21d3ecf156778435L,0x2977ba998323b2d2L,0x6a1b57fb1704bc0fL, + 0xd777cf8b389f048aL,0x9ce2174fac6b42cdL,0x404e2bff09e6c55aL } }, + /* 230 */ + { { 0x9b9b135e204c5ddbL,0x9dbfe0443eff550eL,0x35eab4bfec3be0f6L, + 0x8b4c3f0d0a43e56fL,0x4c1c66730e73f9b3L,0x92ed38bd2c78c905L }, + { 0xc7003f6aa386e27cL,0xb9c4f46faced8507L,0xea024ec859df5464L, + 0x4af96152429572eaL,0x279cd5e2e1fc1194L,0xaa376a03281e358cL } }, + /* 231 */ + { { 0x078592233cdbc95cL,0xaae1aa6aef2e337aL,0xc040108d472a8544L, + 0x80c853e68d037b7dL,0xd221315c8c7eee24L,0x195d38568ee47752L }, + { 0xd4b1ba03dacd7fbeL,0x4b5ac61ed3e0c52bL,0x68d3c0526aab7b52L, + 0xf0d7248c660e3feaL,0xafdb3f893145efb4L,0xa73fd9a38f40936dL } }, + /* 232 */ + { { 0x891b9ef3bb1b17ceL,0x14023667c6127f31L,0x12b2e58d305521fdL, + 0x3a47e449e3508088L,0xe49fc84bff751507L,0x4023f7225310d16eL }, + { 0xa608e5edb73399faL,0xf12632d8d532aa3eL,0x13a2758e845e8415L, + 0xae4b6f851fc2d861L,0x3879f5b1339d02f2L,0x446d22a680d99ebdL } }, + /* 233 */ + { { 0x0f5023024be164f1L,0x8d09d2d688b81920L,0x514056f1984aceffL, + 0xa5c4ddf075e9e80dL,0x38cb47e6df496a93L,0x899e1d6b38df6bf7L }, + { 0x69e87e88b59eb2a6L,0x280d9d639b47f38bL,0x599411ea3654e955L, + 0xcf8dd4fd969aa581L,0xff5c2baf530742a7L,0xa43915361a373085L } }, + /* 234 */ + { { 0x6ace72a3a8a4bdd2L,0xc656cdd1b68ef702L,0xd4a33e7e90c4dad8L, + 0x4aece08a9d951c50L,0xea8005ae085d68e6L,0xfdd7a7d76f7502b8L }, + { 0xce6fb0a698d6fa45L,0x228f86721104eb8cL,0xd23d8787da09d7dcL, + 0x5521428b2ae93065L,0x95faba3dea56c366L,0xedbe50390a88aca5L } }, + /* 235 */ + { { 0xd64da0adbfb26c82L,0xe5d70b3c952c2f9cL,0xf5e8f365f7e77f68L, + 0x7234e00208f2d695L,0xfaf900eed12e7be6L,0x27dc69344acf734eL }, + { 0x80e4ff5ec260a46aL,0x7da5ebce2dc31c28L,0x485c5d73ca69f552L, + 0xcdfb6b2969cc84c2L,0x031c5afeed6d4ecaL,0xc7bbf4c822247637L } }, + /* 236 */ + { { 0x9d5b72c749fe01b2L,0x34785186793a91b8L,0xa3ba3c54cf460438L, + 0x73e8e43d3ab21b6fL,0x50cde8e0be57b8abL,0x6488b3a7dd204264L }, + { 0xa9e398b3dddc4582L,0x1698c1a95bec46feL,0x7f1446ef156d3843L, + 0x3fd25dd8770329a2L,0x05b1221a2c710668L,0x65b2dc2aa72ee6cfL } }, + /* 237 */ + { { 0x21a885f7cd021d63L,0x3f344b15fea61f08L,0xad5ba6ddc5cf73e6L, + 0x154d0d8f227a8b23L,0x9b74373cdc559311L,0x4feab71598620fa1L }, + { 0x5098938e7d9ec924L,0x84d54a5e6d47e550L,0x1a2d1bdc1b617506L, + 0x99fe1782615868a4L,0x171da7803005a924L,0xa70bf5ed7d8f79b6L } }, + /* 238 */ + { { 0x0bc1250dfe2216c5L,0x2c37e2507601b351L,0xb6300175d6f06b7eL, + 0x4dde8ca18bfeb9b7L,0x4f210432b82f843dL,0x8d70e2f9b1ac0afdL }, + { 0x25c73b78aae91abbL,0x0230dca3863028f2L,0x8b923ecfe5cf30b7L, + 0xed754ec25506f265L,0x8e41b88c729a5e39L,0xee67cec2babf889bL } }, + /* 239 */ + { { 0xe183acf51be46c65L,0x9789538fe7565d7aL,0x87873391d9627b4eL, + 0xbf4ac4c19f1d9187L,0x5db99f634691f5c8L,0xa68df80374a1fb98L }, + { 0x3c448ed1bf92b5faL,0xa098c8413e0bdc32L,0x8e74cd5579bf016cL, + 0x5df0d09c115e244dL,0x9418ad013410b66eL,0x8b6124cb17a02130L } }, + /* 240 */ + { { 0x425ec3afc26e3392L,0xc07f8470a1722e00L,0xdcc28190e2356b43L, + 0x4ed97dffb1ef59a6L,0xc22b3ad1c63028c1L,0x070723c268c18988L }, + { 0x70da302f4cf49e7dL,0xc5e87c933f12a522L,0x74acdd1d18594148L, + 0xad5f73abca74124cL,0xe72e4a3ed69fd478L,0x615938687b117cc3L } }, + /* 241 */ + { { 0x7b7b9577a9aa0486L,0x6e41fb35a063d557L,0xb017d5c7da9047d7L, + 0x8c74828068a87ba9L,0xab45fa5cdf08ad93L,0xcd9fb2174c288a28L }, + { 0x595446425747843dL,0x34d64c6ca56111e3L,0x12e47ea14bfce8d5L, + 0x17740e056169267fL,0x5c49438eeed03fb5L,0x9da30add4fc3f513L } }, + /* 242 */ + { { 0xc4e85282ccfa5200L,0x2707608f6a19b13dL,0xdcb9a53df5726e2fL, + 0x612407c9e9427de5L,0x3e5a17e1d54d582aL,0xb99877de655ae118L }, + { 0x6f0e972b015254deL,0x92a56db1f0a6f7c5L,0xd297e4e1a656f8b2L, + 0x99fe0052ad981983L,0xd3652d2f07cfed84L,0xc784352e843c1738L } }, + /* 243 */ + { { 0x6ee90af07e9b2d8aL,0xac8d701857cf1964L,0xf6ed903171f28efcL, + 0x7f70d5a96812b20eL,0x27b557f4f1c61eeeL,0xf1c9bd57c6263758L }, + { 0x5cf7d0142a1a6194L,0xdd614e0b1890ab84L,0x3ef9de100e93c2a6L, + 0xf98cf575e0cd91c5L,0x504ec0c614befc32L,0xd0513a666279d68cL } }, + /* 244 */ + { { 0xa8eadbada859fb6aL,0xcf8346e7db283666L,0x7b35e61a3e22e355L, + 0x293ece2c99639c6bL,0xfa0162e256f241c8L,0xd2e6c7b9bf7a1ddaL }, + { 0xd0de625340075e63L,0x2405aa61f9ec8286L,0x2237830a8fe45494L, + 0x4fd01ac7364e9c8cL,0x4d9c3d21904ba750L,0xd589be14af1b520bL } }, + /* 245 */ + { { 0x13576a4f4662e53bL,0x35ec2f51f9077676L,0x66297d1397c0af97L, + 0xed3201fe9e598b58L,0x49bc752a5e70f604L,0xb54af535bb12d951L }, + { 0x36ea4c2b212c1c76L,0x18f5bbc7eb250dfdL,0xa0d466cc9a0a1a46L, + 0x52564da4dac2d917L,0x206559f48e95fab5L,0x7487c1909ca67a33L } }, + /* 246 */ + { { 0x75abfe37dde98e9cL,0x99b90b262a411199L,0x1b410996dcdb1f7cL, + 0xab346f118b3b5675L,0x04852193f1f8ae1eL,0x1ec4d2276b8b98c1L }, + { 0xba3bc92645452baaL,0x387d1858acc4a572L,0x9478eff6e51f171eL, + 0xf357077d931e1c00L,0xffee77cde54c8ca8L,0xfb4892ff551dc9a4L } }, + /* 247 */ + { { 0x5b1bdad02db8dff8L,0xd462f4fd5a2285a2L,0x1d6aad8eda00b461L, + 0x43fbefcf41306d1bL,0x428e86f36a13fe19L,0xc8b2f11817f89404L }, + { 0x762528aaf0d51afbL,0xa3e2fea4549b1d06L,0x86fad8f2ea3ddf66L, + 0x0d9ccc4b4fbdd206L,0xcde97d4cc189ff5aL,0xc36793d6199f19a6L } }, + /* 248 */ + { { 0xea38909b51b85197L,0xffb17dd0b4c92895L,0x0eb0878b1ddb3f3fL, + 0xb05d28ffc57cf0f2L,0xd8bde2e71abd57e2L,0x7f2be28dc40c1b20L }, + { 0x6554dca2299a2d48L,0x5130ba2e8377982dL,0x8863205f1071971aL, + 0x15ee62827cf2825dL,0xd4b6c57f03748f2bL,0xa9e3f4da430385a0L } }, + /* 249 */ + { { 0x33eb7cec83fbc9c6L,0x24a311c74541777eL,0xc81377f74f0767fcL, + 0x12adae364ab702daL,0xb7fcb6db2a779696L,0x4a6fb28401cea6adL }, + { 0x5e8b1d2acdfc73deL,0xd0efae8d1b02fd32L,0x3f99c190d81d8519L, + 0x3c18f7fafc808971L,0x41f713e751b7ae7bL,0x0a4b3435f07fc3f8L } }, + /* 250 */ + { { 0x7dda3c4c019b7d2eL,0x631c8d1ad4dc4b89L,0x5489cd6e1cdb313cL, + 0xd44aed104c07bb06L,0x8f97e13a75f000d1L,0x0e9ee64fdda5df4dL }, + { 0xeaa99f3b3e346910L,0x622f6921fa294ad7L,0x22aaa20d0d0b2fe9L, + 0x4fed2f991e5881baL,0x9af3b2d6c1571802L,0x919e67a8dc7ee17cL } }, + /* 251 */ + { { 0xc724fe4c76250533L,0x8a2080e57d817ef8L,0xa2afb0f4172c9751L, + 0x9b10cdeb17c0702eL,0xbf3975e3c9b7e3e9L,0x206117df1cd0cdc5L }, + { 0xfb049e61be05ebd5L,0xeb0bb55c16c782c0L,0x13a331b8ab7fed09L, + 0xf6c58b1d632863f0L,0x6264ef6e4d3b6195L,0x92c51b639a53f116L } }, + /* 252 */ + { { 0xa57c7bc8288b364dL,0x4a562e087b41e5c4L,0x699d21c6698a9a11L, + 0xa4ed9581f3f849b9L,0xa223eef39eb726baL,0x13159c23cc2884f9L }, + { 0x73931e583a3f4963L,0x965003890ada6a81L,0x3ee8a1c65ab2950bL, + 0xeedf4949775fab52L,0x63d652e14f2671b6L,0xfed4491c3c4e2f55L } }, + /* 253 */ + { { 0x335eadc3f4eb453eL,0x5ff74b63cadd1a5bL,0x6933d0d75d84a91aL, + 0x9ca3eeb9b49ba337L,0x1f6faccec04c15b8L,0x4ef19326dc09a7e4L }, + { 0x53d2d3243dca3233L,0x0ee40590a2259d4bL,0x18c22edb5546f002L, + 0x9242980109ea6b71L,0xaada0addb0e91e61L,0x5fe53ef499963c50L } }, + /* 254 */ + { { 0x372dd06b90c28c65L,0x1765242c119ce47dL,0xc041fb806b22fc82L, + 0x667edf07b0a7ccc1L,0xc79599e71261beceL,0xbc69d9ba19cff22aL }, + { 0x009d77cd13c06819L,0x635a66aee282b79dL,0x4edac4a6225b1be8L, + 0x57d4f4e4524008f9L,0xee299ac5b056af84L,0xcc38444c3a0bc386L } }, + /* 255 */ + { { 0x490643b1cd4c2356L,0x740a4851750547beL,0x643eaf29d4944c04L, + 0xba572479299a98a0L,0x48b29f16ee05fdf9L,0x33fb4f61089b2d7bL }, + { 0x86704902a950f955L,0x97e1034dfedc3ddfL,0x211320b605fbb6a2L, + 0x23d7b93f432299bbL,0x1fe1a0578590e4a3L,0x8e1d0586f58c0ce6L } }, +}; + +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_6(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + return sp_384_ecc_mulmod_stripe_6(r, &p384_base, p384_table, + k, map, heap); +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384_ecc_mulmod_base_avx2_6(sp_point_384* r, const sp_digit* k, + int map, void* heap) +{ + return sp_384_ecc_mulmod_stripe_avx2_6(r, &p384_base, p384_table, + k, map, heap); +} + +#endif /* HAVE_INTEL_AVX2 */ +/* Multiply the base point of P384 by the scalar and return the result. + * If map is true then convert result to affine coordinates. + * + * 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_384(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[6]; +#endif + sp_point_384* point; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_384_point_new_6(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(k, 6, km); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_base_avx2_6(point, k, map, heap); + else +#endif + err = sp_384_ecc_mulmod_base_6(point, k, map, heap); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_6(point, r); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* 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_384_iszero_6(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +extern void sp_384_add_one_6(sp_digit* a); +extern void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n); +/* 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_384_ecc_gen_k_6(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[48]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_384_from_bin(k, 6, buf, (int)sizeof(buf)); + if (sp_384_cmp_6(k, p384_order2) < 0) { + sp_384_add_one_6(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_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[6]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 inf; +#endif +#endif + sp_point_384* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity; +#endif + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + + err = sp_384_point_new_6(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, inf, infinity); + } +#endif +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) { + err = MEMORY_E; + } + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + err = sp_384_ecc_gen_k_6(rng, k); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_base_avx2_6(point, k, 1, NULL); + else +#endif + err = sp_384_ecc_mulmod_base_6(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_384_ecc_mulmod_avx2_6(infinity, point, p384_order, 1, + NULL); + } + else +#endif + err = sp_384_ecc_mulmod_6(infinity, point, p384_order, 1, NULL); + } + if (err == MP_OKAY) { + if ((sp_384_iszero_6(point->x) == 0) || (sp_384_iszero_6(point->y) == 0)) { + err = ECC_INF_E; + } + } +#endif + + if (err == MP_OKAY) { + err = sp_384_to_mp(k, priv); + } + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_6(point, pub); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_384_point_free_6(infinity, 1, heap); +#endif + sp_384_point_free_6(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +extern void sp_384_to_bin(sp_digit* r, byte* a); +/* 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_384(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 p; + sp_digit kd[6]; +#endif + sp_point_384* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (*outLen < 48U) { + err = BUFFER_E; + } + + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, p, point); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(k, 6, priv); + sp_384_point_from_ecc_point_6(point, pub); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_avx2_6(point, point, k, 1, heap); + else +#endif + err = sp_384_ecc_mulmod_6(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_384_to_bin(point->x, out); + *outLen = 48; + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (k != NULL) { + XFREE(k, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(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) +extern sp_digit sp_384_sub_in_place_6(sp_digit* a, const sp_digit* b); +extern sp_digit sp_384_cond_sub_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit* b, sp_digit m); +extern void sp_384_mul_d_6(sp_digit* r, const sp_digit* a, sp_digit b); +extern void sp_384_mul_d_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit b); +/* 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 WC_INLINE sp_digit div_384_word_6(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + 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_384_mask_6(sp_digit* r, const sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<6; 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; + r[4] = a[4] & m; + r[5] = a[5] & 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 WC_INLINE int sp_384_div_6(const sp_digit* a, const sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[12], t2[7]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[5]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 6); + r1 = sp_384_cmp_6(&t1[6], d) >= 0; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_cond_sub_avx2_6(&t1[6], &t1[6], d, (sp_digit)0 - r1); + else +#endif + sp_384_cond_sub_6(&t1[6], &t1[6], d, (sp_digit)0 - r1); + for (i=5; i>=0; i--) { + r1 = div_384_word_6(t1[6 + i], t1[6 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_mul_d_avx2_6(t2, d, r1); + else +#endif + sp_384_mul_d_6(t2, d, r1); + t1[6 + i] += sp_384_sub_in_place_6(&t1[i], t2); + t1[6 + i] -= t2[6]; + sp_384_mask_6(t2, d, t1[6 + i]); + t1[6 + i] += sp_384_add_6(&t1[i], &t1[i], t2); + sp_384_mask_6(t2, d, t1[6 + i]); + t1[6 + i] += sp_384_add_6(&t1[i], &t1[i], t2); + } + + r1 = sp_384_cmp_6(t1, d) >= 0; +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_cond_sub_avx2_6(r, t1, d, (sp_digit)0 - r1); + else +#endif + sp_384_cond_sub_6(r, t1, d, (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 WC_INLINE int sp_384_mod_6(sp_digit* r, const sp_digit* a, const sp_digit* m) +{ + return sp_384_div_6(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P384 curve. */ +static const uint64_t p384_order_minus_2[6] = { + 0xecec196accc52971U,0x581a0db248b0a77aU,0xc7634d81f4372ddfU, + 0xffffffffffffffffU,0xffffffffffffffffU,0xffffffffffffffffU +}; +#else +/* The low half of the order-2 of the P384 curve. */ +static const uint64_t p384_order_low[3] = { + 0xecec196accc52971U,0x581a0db248b0a77aU,0xc7634d81f4372ddfU + +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P384 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_384_mont_mul_order_6(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_384_mul_6(r, a, b); + sp_384_mont_reduce_order_6(r, p384_order, p384_mp_order); +} + +/* Square number mod the order of P384 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_order_6(sp_digit* r, const sp_digit* a) +{ + sp_384_sqr_6(r, a); + sp_384_mont_reduce_order_6(r, p384_order, p384_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P384 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_n_order_6(sp_digit* r, const sp_digit* a, int n) +{ + int i; + + sp_384_mont_sqr_order_6(r, a); + for (i=1; i=0; i--) { + sp_384_mont_sqr_order_6(t, t); + if ((p384_order_minus_2[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + sp_384_mont_mul_order_6(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 6U); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 6; + sp_digit* t3 = td + 4 * 6; + int i; + + /* t = a^2 */ + sp_384_mont_sqr_order_6(t, a); + /* t = a^3 = t * a */ + sp_384_mont_mul_order_6(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_384_mont_sqr_n_order_6(t2, t, 2); + /* t = a^f = t2 * t */ + sp_384_mont_mul_order_6(t, t2, t); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_384_mont_sqr_n_order_6(t2, t, 4); + /* t = a^ff = t2 * t */ + sp_384_mont_mul_order_6(t, t2, t); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_384_mont_sqr_n_order_6(t2, t, 8); + /* t3= a^ffff = t2 * t */ + sp_384_mont_mul_order_6(t3, t2, t); + /* t2= a^ffff0000 = t3 ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_6(t2, t3, 16); + /* t = a^ffffffff = t2 * t3 */ + sp_384_mont_mul_order_6(t, t2, t3); + /* t2= a^ffffffff0000 = t ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_6(t2, t, 16); + /* t = a^ffffffffffff = t2 * t3 */ + sp_384_mont_mul_order_6(t, t2, t3); + /* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */ + sp_384_mont_sqr_n_order_6(t2, t, 48); + /* t= a^fffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_6(t, t2, t); + /* t2= a^ffffffffffffffffffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_order_6(t2, t, 96); + /* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_6(t2, t2, t); + for (i=191; i>=1; i--) { + sp_384_mont_sqr_order_6(t2, t2); + if (((sp_digit)p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + sp_384_mont_mul_order_6(t2, t2, a); + } + } + sp_384_mont_sqr_order_6(t2, t2); + sp_384_mont_mul_order_6(r, t2, a); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply two number mod the order of P384 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_384_mont_mul_order_avx2_6(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_384_mul_avx2_6(r, a, b); + sp_384_mont_reduce_order_avx2_6(r, p384_order, p384_mp_order); +} + +/* Square number mod the order of P384 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_order_avx2_6(sp_digit* r, const sp_digit* a) +{ + sp_384_sqr_avx2_6(r, a); + sp_384_mont_reduce_order_avx2_6(r, p384_order, p384_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P384 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_384_mont_sqr_n_order_avx2_6(sp_digit* r, const sp_digit* a, int n) +{ + int i; + + sp_384_mont_sqr_order_avx2_6(r, a); + for (i=1; i=0; i--) { + sp_384_mont_sqr_order_avx2_6(t, t); + if ((p384_order_minus_2[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + sp_384_mont_mul_order_avx2_6(t, t, a); + } + } + XMEMCPY(r, t, sizeof(sp_digit) * 6U); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 6; + sp_digit* t3 = td + 4 * 6; + int i; + + /* t = a^2 */ + sp_384_mont_sqr_order_avx2_6(t, a); + /* t = a^3 = t * a */ + sp_384_mont_mul_order_avx2_6(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_384_mont_sqr_n_order_avx2_6(t2, t, 2); + /* t = a^f = t2 * t */ + sp_384_mont_mul_order_avx2_6(t, t2, t); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_384_mont_sqr_n_order_avx2_6(t2, t, 4); + /* t = a^ff = t2 * t */ + sp_384_mont_mul_order_avx2_6(t, t2, t); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_384_mont_sqr_n_order_avx2_6(t2, t, 8); + /* t3= a^ffff = t2 * t */ + sp_384_mont_mul_order_avx2_6(t3, t2, t); + /* t2= a^ffff0000 = t3 ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_avx2_6(t2, t3, 16); + /* t = a^ffffffff = t2 * t3 */ + sp_384_mont_mul_order_avx2_6(t, t2, t3); + /* t2= a^ffffffff0000 = t ^ 2 ^ 16 */ + sp_384_mont_sqr_n_order_avx2_6(t2, t, 16); + /* t = a^ffffffffffff = t2 * t3 */ + sp_384_mont_mul_order_avx2_6(t, t2, t3); + /* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */ + sp_384_mont_sqr_n_order_avx2_6(t2, t, 48); + /* t= a^fffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_avx2_6(t, t2, t); + /* t2= a^ffffffffffffffffffffffff000000000000000000000000 */ + sp_384_mont_sqr_n_order_avx2_6(t2, t, 96); + /* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */ + sp_384_mont_mul_order_avx2_6(t2, t2, t); + for (i=191; i>=1; i--) { + sp_384_mont_sqr_order_avx2_6(t2, t2); + if (((sp_digit)p384_order_low[i / 64] & ((sp_int_digit)1 << (i % 64))) != 0) { + sp_384_mont_mul_order_avx2_6(t2, t2, a); + } + } + sp_384_mont_sqr_order_avx2_6(t2, t2); + sp_384_mont_mul_order_avx2_6(r, t2, a); +#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, 384 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 384 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_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit ed[2*6]; + sp_digit xd[2*6]; + sp_digit kd[2*6]; + sp_digit rd[2*6]; + sp_digit td[3 * 2*6]; + sp_point_384 p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point_384* point = NULL; + sp_digit carry; + sp_digit* s = NULL; + sp_digit* kInv = NULL; + int err = MP_OKAY; + int64_t c; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + + err = sp_384_point_new_6(heap, p, point); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 6, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + e = d + 0 * 6; + x = d + 2 * 6; + k = d + 4 * 6; + r = d + 6 * 6; + tmp = d + 8 * 6; +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(e, 6, hash, (int)hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_384_from_mp(x, 6, priv); + + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_6(rng, k); + } + else { + sp_384_from_mp(k, 6, km); + mp_zero(km); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_base_avx2_6(point, k, 1, heap); + else +#endif + err = sp_384_ecc_mulmod_base_6(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 6U); + sp_384_norm_6(r); + c = sp_384_cmp_6(r, p384_order); + sp_384_cond_sub_6(r, r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(r); + + /* Conv k to Montgomery form (mod order) */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_mul_avx2_6(k, k, p384_norm_order); + else +#endif + sp_384_mul_6(k, k, p384_norm_order); + err = sp_384_mod_6(k, k, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_6(k); + /* kInv = 1/k mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_mont_inv_order_avx2_6(kInv, k, tmp); + else +#endif + sp_384_mont_inv_order_6(kInv, k, tmp); + sp_384_norm_6(kInv); + + /* s = r * x + e */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_mul_avx2_6(x, x, r); + else +#endif + sp_384_mul_6(x, x, r); + err = sp_384_mod_6(x, x, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_6(x); + carry = sp_384_add_6(s, e, x); + sp_384_cond_sub_6(s, s, p384_order, 0 - carry); + sp_384_norm_6(s); + c = sp_384_cmp_6(s, p384_order); + sp_384_cond_sub_6(s, s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(s); + + /* s = s * k^-1 mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_mont_mul_order_avx2_6(s, s, kInv); + else +#endif + sp_384_mont_mul_order_6(s, s, kInv); + sp_384_norm_6(s); + + /* Check that signature is usable. */ + if (sp_384_iszero_6(s) == 0) { + break; + } + } + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 6); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(x, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(k, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(r, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3U * 2U * 6U); +#endif + sp_384_point_free_6(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, 384) + * 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 384 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_384(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)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit u1d[2*6]; + sp_digit u2d[2*6]; + sp_digit sd[2*6]; + sp_digit tmpd[2*6 * 5]; + sp_point_384 p1d; + sp_point_384 p2d; +#endif + sp_digit* u1 = NULL; + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p1; + sp_point_384* p2 = NULL; + sp_digit carry; + int64_t c; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_384_point_new_6(heap, p1d, p1); + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, p2d, p2); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 6, heap, + DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + u1 = d + 0 * 6; + u2 = d + 2 * 6; + s = d + 4 * 6; + tmp = d + 6 * 6; +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 6, hash, (int)hashLen); + sp_384_from_mp(u2, 6, r); + sp_384_from_mp(s, 6, sm); + sp_384_from_mp(p2->x, 6, pX); + sp_384_from_mp(p2->y, 6, pY); + sp_384_from_mp(p2->z, 6, pZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_384_mul_avx2_6(s, s, p384_norm_order); + } + else +#endif + { + sp_384_mul_6(s, s, p384_norm_order); + } + err = sp_384_mod_6(s, s, p384_order); + } + if (err == MP_OKAY) { + sp_384_norm_6(s); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_384_mont_inv_order_avx2_6(s, s, tmp); + sp_384_mont_mul_order_avx2_6(u1, u1, s); + sp_384_mont_mul_order_avx2_6(u2, u2, s); + } + else +#endif + { + sp_384_mont_inv_order_6(s, s, tmp); + sp_384_mont_mul_order_6(u1, u1, s); + sp_384_mont_mul_order_6(u2, u2, s); + } + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_base_avx2_6(p1, u1, 0, heap); + else +#endif + err = sp_384_ecc_mulmod_base_6(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_384_ecc_mulmod_avx2_6(p2, p2, u2, 0, heap); + else +#endif + err = sp_384_ecc_mulmod_6(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_384_proj_point_add_avx2_6(p1, p1, p2, tmp); + if (sp_384_iszero_6(p1->z)) { + if (sp_384_iszero_6(p1->x) && sp_384_iszero_6(p1->y)) { + sp_384_proj_point_dbl_avx2_6(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + } + else +#endif + { + sp_384_proj_point_add_6(p1, p1, p2, tmp); + if (sp_384_iszero_6(p1->z)) { + if (sp_384_iszero_6(p1->x) && sp_384_iszero_6(p1->y)) { + sp_384_proj_point_dbl_6(p1, p2, tmp); + } + else { + /* Y ordinate is not used from here - don't set. */ + p1->x[0] = 0; + p1->x[1] = 0; + p1->x[2] = 0; + p1->x[3] = 0; + p1->x[4] = 0; + p1->x[5] = 0; + XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + } + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 6, r); + err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_6(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_6(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 6, r); + carry = sp_384_add_6(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_6(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_6(u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_6(p1->x, u1) == 0); + } + } + } + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_384_point_free_6(p1, 0, heap); + sp_384_point_free_6(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_384_ecc_is_point_6(sp_point_384* point, void* heap) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d = NULL; +#else + sp_digit t1d[2*6]; + sp_digit t2d[2*6]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 4, heap, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 6; + t2 = d + 2 * 6; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + sp_384_sqr_6(t1, point->y); + (void)sp_384_mod_6(t1, t1, p384_mod); + sp_384_sqr_6(t2, point->x); + (void)sp_384_mod_6(t2, t2, p384_mod); + sp_384_mul_6(t2, t2, point->x); + (void)sp_384_mod_6(t2, t2, p384_mod); + (void)sp_384_sub_6(t2, p384_mod, t2); + sp_384_mont_add_6(t1, t1, t2, p384_mod); + + sp_384_mont_add_6(t1, t1, point->x, p384_mod); + sp_384_mont_add_6(t1, t1, point->x, p384_mod); + sp_384_mont_add_6(t1, t1, point->x, p384_mod); + + if (sp_384_cmp_6(t1, p384_b) != 0) { + err = MP_VAL; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_384(mp_int* pX, mp_int* pY) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384 pubd; +#endif + sp_point_384* pub; + byte one[1] = { 1 }; + int err; + + err = sp_384_point_new_6(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_384_from_mp(pub->x, 6, pX); + sp_384_from_mp(pub->y, 6, pY); + sp_384_from_bin(pub->z, 6, one, (int)sizeof(one)); + + err = sp_384_ecc_is_point_6(pub, NULL); + } + + sp_384_point_free_6(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit privd[6]; + sp_point_384 pubd; + sp_point_384 pd; +#endif + sp_digit* priv = NULL; + sp_point_384* pub; + sp_point_384* p = NULL; + byte one[1] = { 1 }; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_384_point_new_6(heap, pubd, pub); + if (err == MP_OKAY) { + err = sp_384_point_new_6(heap, pd, p); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) { + err = MEMORY_E; + } + } +#endif + + if (err == MP_OKAY) { +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + priv = privd; +#endif + + sp_384_from_mp(pub->x, 6, pX); + sp_384_from_mp(pub->y, 6, pY); + sp_384_from_bin(pub->z, 6, one, (int)sizeof(one)); + sp_384_from_mp(priv, 6, privm); + + /* Check point at infinitiy. */ + if ((sp_384_iszero_6(pub->x) != 0) && + (sp_384_iszero_6(pub->y) != 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_384_cmp_6(pub->x, p384_mod) >= 0 || + sp_384_cmp_6(pub->y, p384_mod) >= 0) { + err = ECC_OUT_OF_RANGE_E; + } + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_384_ecc_is_point_6(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_avx2_6(p, pub, p384_order, 1, heap); + else +#endif + err = sp_384_ecc_mulmod_6(p, pub, p384_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if ((sp_384_iszero_6(p->x) == 0) || + (sp_384_iszero_6(p->y) == 0)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_base_avx2_6(p, priv, 1, heap); + else +#endif + err = sp_384_ecc_mulmod_base_6(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_384_cmp_6(p->x, pub->x) != 0 || + sp_384_cmp_6(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (priv != NULL) { + XFREE(priv, heap, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(p, 0, heap); + sp_384_point_free_6(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 6 * 5]; + sp_point_384 pd; + sp_point_384 qd; +#endif + sp_digit* tmp; + sp_point_384* p; + sp_point_384* q = NULL; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_384_point_new_6(NULL, pd, p); + if (err == MP_OKAY) { + err = sp_384_point_new_6(NULL, qd, q); + } +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 6, pX); + sp_384_from_mp(p->y, 6, pY); + sp_384_from_mp(p->z, 6, pZ); + sp_384_from_mp(q->x, 6, qX); + sp_384_from_mp(q->y, 6, qY); + sp_384_from_mp(q->z, 6, qZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_proj_point_add_avx2_6(p, p, q, tmp); + else +#endif + sp_384_proj_point_add_6(p, p, q, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(q, 0, NULL); + sp_384_point_free_6(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 6 * 2]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_384_point_new_6(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 6, pX); + sp_384_from_mp(p->y, 6, pY); + sp_384_from_mp(p->z, 6, pZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_proj_point_dbl_avx2_6(p, p, tmp); + else +#endif + sp_384_proj_point_dbl_6(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, rX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, rY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, rZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if (!defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK)) || defined(WOLFSSL_SP_NO_MALLOC) + sp_digit tmpd[2 * 6 * 6]; + sp_point_384 pd; +#endif + sp_digit* tmp; + sp_point_384* p; + int err; + + err = sp_384_point_new_6(NULL, pd, p); +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 6 * 6, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) { + err = MEMORY_E; + } + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_384_from_mp(p->x, 6, pX); + sp_384_from_mp(p->y, 6, pY); + sp_384_from_mp(p->z, 6, pZ); + + sp_384_map_6(p, p, tmp); + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(p->x, pX); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->y, pY); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(p->z, pZ); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } +#endif + sp_384_point_free_6(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_384_mont_sqrt_6(sp_digit* y) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit t1d[2 * 6]; + sp_digit t2d[2 * 6]; + sp_digit t3d[2 * 6]; + sp_digit t4d[2 * 6]; + sp_digit t5d[2 * 6]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 6, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + t1 = d + 0 * 6; + t2 = d + 2 * 6; + t3 = d + 4 * 6; + t4 = d + 6 * 6; + t5 = d + 8 * 6; +#else + t1 = t1d; + t2 = t2d; + t3 = t3d; + t4 = t4d; + t5 = t5d; +#endif + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + /* t2 = y ^ 0x2 */ + sp_384_mont_sqr_avx2_6(t2, y, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3 */ + sp_384_mont_mul_avx2_6(t1, t2, y, p384_mod, p384_mp_mod); + /* t5 = y ^ 0xc */ + sp_384_mont_sqr_n_avx2_6(t5, t1, 2, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xf */ + sp_384_mont_mul_avx2_6(t1, t1, t5, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x1e */ + sp_384_mont_sqr_avx2_6(t2, t1, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x1f */ + sp_384_mont_mul_avx2_6(t3, t2, y, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3e0 */ + sp_384_mont_sqr_n_avx2_6(t2, t3, 5, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3ff */ + sp_384_mont_mul_avx2_6(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fe0 */ + sp_384_mont_sqr_n_avx2_6(t2, t1, 5, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x7fff */ + sp_384_mont_mul_avx2_6(t3, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fff800 */ + sp_384_mont_sqr_n_avx2_6(t2, t3, 15, p384_mod, p384_mp_mod); + /* t4 = y ^ 0x3ffffff */ + sp_384_mont_mul_avx2_6(t4, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffc000000 */ + sp_384_mont_sqr_n_avx2_6(t2, t4, 30, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffff */ + sp_384_mont_mul_avx2_6(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_avx2_6(t2, t1, 60, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_avx2_6(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_avx2_6(t2, t1, 120, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_avx2_6(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_avx2_6(t2, t1, 15, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_avx2_6(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */ + sp_384_mont_sqr_n_avx2_6(t2, t1, 31, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */ + sp_384_mont_mul_avx2_6(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */ + sp_384_mont_sqr_n_avx2_6(t2, t1, 4, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */ + sp_384_mont_mul_avx2_6(t1, t5, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */ + sp_384_mont_sqr_n_avx2_6(t2, t1, 62, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */ + sp_384_mont_mul_avx2_6(t1, y, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */ + sp_384_mont_sqr_n_avx2_6(y, t1, 30, p384_mod, p384_mp_mod); + } + else +#endif + { + /* t2 = y ^ 0x2 */ + sp_384_mont_sqr_6(t2, y, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3 */ + sp_384_mont_mul_6(t1, t2, y, p384_mod, p384_mp_mod); + /* t5 = y ^ 0xc */ + sp_384_mont_sqr_n_6(t5, t1, 2, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xf */ + sp_384_mont_mul_6(t1, t1, t5, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x1e */ + sp_384_mont_sqr_6(t2, t1, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x1f */ + sp_384_mont_mul_6(t3, t2, y, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3e0 */ + sp_384_mont_sqr_n_6(t2, t3, 5, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3ff */ + sp_384_mont_mul_6(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fe0 */ + sp_384_mont_sqr_n_6(t2, t1, 5, p384_mod, p384_mp_mod); + /* t3 = y ^ 0x7fff */ + sp_384_mont_mul_6(t3, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fff800 */ + sp_384_mont_sqr_n_6(t2, t3, 15, p384_mod, p384_mp_mod); + /* t4 = y ^ 0x3ffffff */ + sp_384_mont_mul_6(t4, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffc000000 */ + sp_384_mont_sqr_n_6(t2, t4, 30, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffff */ + sp_384_mont_mul_6(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffff000000000000000 */ + sp_384_mont_sqr_n_6(t2, t1, 60, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffff */ + sp_384_mont_mul_6(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */ + sp_384_mont_sqr_n_6(t2, t1, 120, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_6(t1, t1, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */ + sp_384_mont_sqr_n_6(t2, t1, 15, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */ + sp_384_mont_mul_6(t1, t3, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */ + sp_384_mont_sqr_n_6(t2, t1, 31, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */ + sp_384_mont_mul_6(t1, t4, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */ + sp_384_mont_sqr_n_6(t2, t1, 4, p384_mod, p384_mp_mod); + /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */ + sp_384_mont_mul_6(t1, t5, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */ + sp_384_mont_sqr_n_6(t2, t1, 62, p384_mod, p384_mp_mod); + /* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */ + sp_384_mont_mul_6(t1, y, t2, p384_mod, p384_mp_mod); + /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */ + sp_384_mont_sqr_n_6(y, t1, 30, p384_mod, p384_mp_mod); + } + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} + + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym) +{ +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* d; +#else + sp_digit xd[2 * 6]; + sp_digit yd[2 * 6]; +#endif + sp_digit* x = NULL; + sp_digit* y = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 6, NULL, DYNAMIC_TYPE_ECC); + if (d == NULL) { + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + x = d + 0 * 6; + y = d + 2 * 6; +#else + x = xd; + y = yd; +#endif + + sp_384_from_mp(x, 6, xm); + err = sp_384_mod_mul_norm_6(x, x, p384_mod); + } + if (err == MP_OKAY) { + /* y = x^3 */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_384_mont_sqr_avx2_6(y, x, p384_mod, p384_mp_mod); + sp_384_mont_mul_avx2_6(y, y, x, p384_mod, p384_mp_mod); + } + else +#endif + { + sp_384_mont_sqr_6(y, x, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(y, y, x, p384_mod, p384_mp_mod); + } + /* y = x^3 - 3x */ + sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_sub_6(y, y, x, p384_mod); + sp_384_mont_sub_6(y, y, x, p384_mod); + /* y = x^3 - 3x + b */ + err = sp_384_mod_mul_norm_6(x, p384_b, p384_mod); + } + if (err == MP_OKAY) { + sp_384_mont_add_6(y, y, x, p384_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_384_mont_sqrt_6(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 6, 0, 6U * sizeof(sp_digit)); + sp_384_mont_reduce_6(y, p384_mod, p384_mp_mod); + if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) { + sp_384_mont_sub_6(y, p384_mod, y, p384_mod); + } + + err = sp_384_to_mp(y, ym); + } + +#if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC) + if (d != NULL) { + XFREE(d, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +} +#endif +#endif /* WOLFSSL_SP_384 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_SP_X86_64_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_x86_64_asm.S b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_x86_64_asm.S new file mode 100644 index 000000000..c6941f1f0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/sp_x86_64_asm.S @@ -0,0 +1,41830 @@ +/* sp_x86_64_asm + * + * Copyright (C) 2006-2020 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 + */ + +#define HAVE_INTEL_AVX2 +#ifndef WOLFSSL_SP_NO_2048 +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +#ifndef __APPLE__ +.globl sp_2048_from_bin +.type sp_2048_from_bin,@function +.align 16 +sp_2048_from_bin: +#else +.globl _sp_2048_from_bin +.p2align 4 +_sp_2048_from_bin: +#endif /* __APPLE__ */ + movq %rdx, %r9 + movq %rdi, %r10 + addq %rcx, %r9 + addq $256, %r10 + xorq %r11, %r11 + jmp L_2048_from_bin_64_end +L_2048_from_bin_64_start: + subq $64, %r9 + movbeq 56(%r9), %rax + movbeq 48(%r9), %r8 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movbeq 40(%r9), %rax + movbeq 32(%r9), %r8 + movq %rax, 16(%rdi) + movq %r8, 24(%rdi) + movbeq 24(%r9), %rax + movbeq 16(%r9), %r8 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movbeq 8(%r9), %rax + movbeq (%r9), %r8 + movq %rax, 48(%rdi) + movq %r8, 56(%rdi) + addq $64, %rdi + subq $64, %rcx +L_2048_from_bin_64_end: + cmpq $63, %rcx + jg L_2048_from_bin_64_start + jmp L_2048_from_bin_8_end +L_2048_from_bin_8_start: + subq $8, %r9 + movbeq (%r9), %rax + movq %rax, (%rdi) + addq $8, %rdi + subq $8, %rcx +L_2048_from_bin_8_end: + cmpq $7, %rcx + jg L_2048_from_bin_8_start + cmpq %r11, %rcx + je L_2048_from_bin_hi_end + movq %r11, %r8 + movq %r11, %rax +L_2048_from_bin_hi_start: + movb (%rdx), %al + shlq $8, %r8 + incq %rdx + addq %rax, %r8 + decq %rcx + jg L_2048_from_bin_hi_start + movq %r8, (%rdi) + addq $8, %rdi +L_2048_from_bin_hi_end: + cmpq %r10, %rdi + je L_2048_from_bin_zero_end +L_2048_from_bin_zero_start: + movq %r11, (%rdi) + addq $8, %rdi + cmpq %r10, %rdi + jl L_2048_from_bin_zero_start +L_2048_from_bin_zero_end: + repz retq +#ifndef __APPLE__ +.size sp_2048_from_bin,.-sp_2048_from_bin +#endif /* __APPLE__ */ +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 256 + * + * r A single precision integer. + * a Byte array. + */ +#ifndef __APPLE__ +.globl sp_2048_to_bin +.type sp_2048_to_bin,@function +.align 16 +sp_2048_to_bin: +#else +.globl _sp_2048_to_bin +.p2align 4 +_sp_2048_to_bin: +#endif /* __APPLE__ */ + movbeq 248(%rdi), %rdx + movbeq 240(%rdi), %rax + movq %rdx, (%rsi) + movq %rax, 8(%rsi) + movbeq 232(%rdi), %rdx + movbeq 224(%rdi), %rax + movq %rdx, 16(%rsi) + movq %rax, 24(%rsi) + movbeq 216(%rdi), %rdx + movbeq 208(%rdi), %rax + movq %rdx, 32(%rsi) + movq %rax, 40(%rsi) + movbeq 200(%rdi), %rdx + movbeq 192(%rdi), %rax + movq %rdx, 48(%rsi) + movq %rax, 56(%rsi) + movbeq 184(%rdi), %rdx + movbeq 176(%rdi), %rax + movq %rdx, 64(%rsi) + movq %rax, 72(%rsi) + movbeq 168(%rdi), %rdx + movbeq 160(%rdi), %rax + movq %rdx, 80(%rsi) + movq %rax, 88(%rsi) + movbeq 152(%rdi), %rdx + movbeq 144(%rdi), %rax + movq %rdx, 96(%rsi) + movq %rax, 104(%rsi) + movbeq 136(%rdi), %rdx + movbeq 128(%rdi), %rax + movq %rdx, 112(%rsi) + movq %rax, 120(%rsi) + movbeq 120(%rdi), %rdx + movbeq 112(%rdi), %rax + movq %rdx, 128(%rsi) + movq %rax, 136(%rsi) + movbeq 104(%rdi), %rdx + movbeq 96(%rdi), %rax + movq %rdx, 144(%rsi) + movq %rax, 152(%rsi) + movbeq 88(%rdi), %rdx + movbeq 80(%rdi), %rax + movq %rdx, 160(%rsi) + movq %rax, 168(%rsi) + movbeq 72(%rdi), %rdx + movbeq 64(%rdi), %rax + movq %rdx, 176(%rsi) + movq %rax, 184(%rsi) + movbeq 56(%rdi), %rdx + movbeq 48(%rdi), %rax + movq %rdx, 192(%rsi) + movq %rax, 200(%rsi) + movbeq 40(%rdi), %rdx + movbeq 32(%rdi), %rax + movq %rdx, 208(%rsi) + movq %rax, 216(%rsi) + movbeq 24(%rdi), %rdx + movbeq 16(%rdi), %rax + movq %rdx, 224(%rsi) + movq %rax, 232(%rsi) + movbeq 8(%rdi), %rdx + movbeq (%rdi), %rax + movq %rdx, 240(%rsi) + movq %rax, 248(%rsi) + repz retq +#ifndef __APPLE__ +.size sp_2048_to_bin,.-sp_2048_to_bin +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_16 +.type sp_2048_mul_16,@function +.align 16 +sp_2048_mul_16: +#else +.globl _sp_2048_mul_16 +.p2align 4 +_sp_2048_mul_16: +#endif /* __APPLE__ */ + movq %rdx, %rcx + subq $128, %rsp + # A[0] * B[0] + movq (%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + movq %rax, (%rsp) + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[0] + movq (%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 8(%rsp) + # A[0] * B[2] + movq 16(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[1] + movq 8(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[0] + movq (%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 16(%rsp) + # A[0] * B[3] + movq 24(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[2] + movq 16(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[1] + movq 8(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[0] + movq (%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 24(%rsp) + # A[0] * B[4] + movq 32(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[3] + movq 24(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[2] + movq 16(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[1] + movq 8(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[0] + movq (%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 32(%rsp) + # A[0] * B[5] + movq 40(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[4] + movq 32(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[3] + movq 24(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[2] + movq 16(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[1] + movq 8(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[0] + movq (%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 40(%rsp) + # A[0] * B[6] + movq 48(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[5] + movq 40(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[4] + movq 32(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[3] + movq 24(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[2] + movq 16(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[1] + movq 8(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[0] + movq (%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 48(%rsp) + # A[0] * B[7] + movq 56(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[6] + movq 48(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[5] + movq 40(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[4] + movq 32(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[3] + movq 24(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[2] + movq 16(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[1] + movq 8(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[0] + movq (%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 56(%rsp) + # A[0] * B[8] + movq 64(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[7] + movq 56(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[6] + movq 48(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[5] + movq 40(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[4] + movq 32(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[3] + movq 24(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[2] + movq 16(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[1] + movq 8(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[0] + movq (%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 64(%rsp) + # A[0] * B[9] + movq 72(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[8] + movq 64(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[7] + movq 56(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[6] + movq 48(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[5] + movq 40(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[4] + movq 32(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[3] + movq 24(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[2] + movq 16(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[1] + movq 8(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[0] + movq (%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 72(%rsp) + # A[0] * B[10] + movq 80(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[9] + movq 72(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[8] + movq 64(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[7] + movq 56(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[6] + movq 48(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[5] + movq 40(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[4] + movq 32(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[3] + movq 24(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[2] + movq 16(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[1] + movq 8(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[0] + movq (%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 80(%rsp) + # A[0] * B[11] + movq 88(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[10] + movq 80(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[9] + movq 72(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[8] + movq 64(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[7] + movq 56(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[6] + movq 48(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[5] + movq 40(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[4] + movq 32(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[3] + movq 24(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[2] + movq 16(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[1] + movq 8(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[0] + movq (%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 88(%rsp) + # A[0] * B[12] + movq 96(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[11] + movq 88(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[10] + movq 80(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[9] + movq 72(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[8] + movq 64(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[7] + movq 56(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[6] + movq 48(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[5] + movq 40(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[4] + movq 32(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[3] + movq 24(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[2] + movq 16(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[1] + movq 8(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[0] + movq (%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 96(%rsp) + # A[0] * B[13] + movq 104(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[12] + movq 96(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[11] + movq 88(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[10] + movq 80(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[9] + movq 72(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[8] + movq 64(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[7] + movq 56(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[6] + movq 48(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[5] + movq 40(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[4] + movq 32(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[3] + movq 24(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[2] + movq 16(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[1] + movq 8(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[0] + movq (%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 104(%rsp) + # A[0] * B[14] + movq 112(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[13] + movq 104(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[12] + movq 96(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[11] + movq 88(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[10] + movq 80(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[9] + movq 72(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[8] + movq 64(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[7] + movq 56(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[6] + movq 48(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[5] + movq 40(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[4] + movq 32(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[3] + movq 24(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[2] + movq 16(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[1] + movq 8(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[0] + movq (%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 112(%rsp) + # A[0] * B[15] + movq 120(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[14] + movq 112(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[13] + movq 104(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[12] + movq 96(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[11] + movq 88(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[10] + movq 80(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[9] + movq 72(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[8] + movq 64(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[7] + movq 56(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[6] + movq 48(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[5] + movq 40(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[4] + movq 32(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[3] + movq 24(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[2] + movq 16(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[1] + movq 8(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[0] + movq (%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 120(%rsp) + # A[1] * B[15] + movq 120(%rcx), %rax + mulq 8(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[14] + movq 112(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[13] + movq 104(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[12] + movq 96(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[11] + movq 88(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[10] + movq 80(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[9] + movq 72(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[8] + movq 64(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[7] + movq 56(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[6] + movq 48(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[5] + movq 40(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[4] + movq 32(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[3] + movq 24(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[2] + movq 16(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[1] + movq 8(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 128(%rdi) + # A[2] * B[15] + movq 120(%rcx), %rax + mulq 16(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[14] + movq 112(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[13] + movq 104(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[12] + movq 96(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[11] + movq 88(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[10] + movq 80(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[9] + movq 72(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[8] + movq 64(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[7] + movq 56(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[6] + movq 48(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[5] + movq 40(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[4] + movq 32(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[3] + movq 24(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[2] + movq 16(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 136(%rdi) + # A[3] * B[15] + movq 120(%rcx), %rax + mulq 24(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[14] + movq 112(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[13] + movq 104(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[12] + movq 96(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[11] + movq 88(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[10] + movq 80(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[9] + movq 72(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[8] + movq 64(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[7] + movq 56(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[6] + movq 48(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[5] + movq 40(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[4] + movq 32(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[3] + movq 24(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 144(%rdi) + # A[4] * B[15] + movq 120(%rcx), %rax + mulq 32(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[14] + movq 112(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[13] + movq 104(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[12] + movq 96(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[11] + movq 88(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[10] + movq 80(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[9] + movq 72(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[8] + movq 64(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[7] + movq 56(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[6] + movq 48(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[5] + movq 40(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[4] + movq 32(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 152(%rdi) + # A[5] * B[15] + movq 120(%rcx), %rax + mulq 40(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[14] + movq 112(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[13] + movq 104(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[12] + movq 96(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[11] + movq 88(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[10] + movq 80(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[9] + movq 72(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[8] + movq 64(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[7] + movq 56(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[6] + movq 48(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[5] + movq 40(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 160(%rdi) + # A[6] * B[15] + movq 120(%rcx), %rax + mulq 48(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[14] + movq 112(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[13] + movq 104(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[12] + movq 96(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[11] + movq 88(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[10] + movq 80(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[9] + movq 72(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[8] + movq 64(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[7] + movq 56(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[6] + movq 48(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 168(%rdi) + # A[7] * B[15] + movq 120(%rcx), %rax + mulq 56(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[14] + movq 112(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[13] + movq 104(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[12] + movq 96(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[11] + movq 88(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[10] + movq 80(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[9] + movq 72(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[8] + movq 64(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[7] + movq 56(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 176(%rdi) + # A[8] * B[15] + movq 120(%rcx), %rax + mulq 64(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[14] + movq 112(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[13] + movq 104(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[12] + movq 96(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[11] + movq 88(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[10] + movq 80(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[9] + movq 72(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[8] + movq 64(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 184(%rdi) + # A[9] * B[15] + movq 120(%rcx), %rax + mulq 72(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[14] + movq 112(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[13] + movq 104(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[12] + movq 96(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[11] + movq 88(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[10] + movq 80(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[9] + movq 72(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 192(%rdi) + # A[10] * B[15] + movq 120(%rcx), %rax + mulq 80(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[14] + movq 112(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[13] + movq 104(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[12] + movq 96(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[11] + movq 88(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[10] + movq 80(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 200(%rdi) + # A[11] * B[15] + movq 120(%rcx), %rax + mulq 88(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[14] + movq 112(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[13] + movq 104(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[12] + movq 96(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[11] + movq 88(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 208(%rdi) + # A[12] * B[15] + movq 120(%rcx), %rax + mulq 96(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[14] + movq 112(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[13] + movq 104(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[12] + movq 96(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 216(%rdi) + # A[13] * B[15] + movq 120(%rcx), %rax + mulq 104(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[14] + movq 112(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[13] + movq 104(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 224(%rdi) + # A[14] * B[15] + movq 120(%rcx), %rax + mulq 112(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[14] + movq 112(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 232(%rdi) + # A[15] * B[15] + movq 120(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r8 + movq 24(%rsp), %r9 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rsp), %rax + movq 40(%rsp), %rdx + movq 48(%rsp), %r8 + movq 56(%rsp), %r9 + movq %rax, 32(%rdi) + movq %rdx, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rsp), %rax + movq 72(%rsp), %rdx + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq %rax, 64(%rdi) + movq %rdx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rsp), %rax + movq 104(%rsp), %rdx + movq 112(%rsp), %r8 + movq 120(%rsp), %r9 + movq %rax, 96(%rdi) + movq %rdx, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + addq $128, %rsp + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_16,.-sp_2048_mul_16 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_sqr_16 +.type sp_2048_sqr_16,@function +.align 16 +sp_2048_sqr_16: +#else +.globl _sp_2048_sqr_16 +.p2align 4 +_sp_2048_sqr_16: +#endif /* __APPLE__ */ + push %r12 + subq $128, %rsp + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + xorq %r9, %r9 + movq %rax, (%rsp) + movq %rdx, %r8 + # A[0] * A[1] + movq 8(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 8(%rsp) + # A[0] * A[2] + movq 16(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 16(%rsp) + # A[0] * A[3] + movq 24(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * A[2] + movq 16(%rsi), %rax + mulq 8(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 24(%rsp) + # A[0] * A[4] + movq 32(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[1] * A[3] + movq 24(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 32(%rsp) + # A[0] * A[5] + movq 40(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[4] + movq 32(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[3] + movq 24(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 40(%rsp) + # A[0] * A[6] + movq 48(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[5] + movq 40(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[4] + movq 32(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 48(%rsp) + # A[0] * A[7] + movq 56(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[6] + movq 48(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[5] + movq 40(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[4] + movq 32(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 56(%rsp) + # A[0] * A[8] + movq 64(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[7] + movq 56(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[6] + movq 48(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[5] + movq 40(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[4] + movq 32(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 64(%rsp) + # A[0] * A[9] + movq 72(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[8] + movq 64(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[7] + movq 56(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[6] + movq 48(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[5] + movq 40(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 72(%rsp) + # A[0] * A[10] + movq 80(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[9] + movq 72(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[8] + movq 64(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[7] + movq 56(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[6] + movq 48(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[5] + movq 40(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 80(%rsp) + # A[0] * A[11] + movq 88(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[10] + movq 80(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[9] + movq 72(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[8] + movq 64(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[7] + movq 56(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[6] + movq 48(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 88(%rsp) + # A[0] * A[12] + movq 96(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[11] + movq 88(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[10] + movq 80(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[9] + movq 72(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[8] + movq 64(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[7] + movq 56(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[6] + movq 48(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 96(%rsp) + # A[0] * A[13] + movq 104(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[12] + movq 96(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[11] + movq 88(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[10] + movq 80(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[9] + movq 72(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[8] + movq 64(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[7] + movq 56(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 104(%rsp) + # A[0] * A[14] + movq 112(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[13] + movq 104(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[12] + movq 96(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[11] + movq 88(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[10] + movq 80(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[9] + movq 72(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[8] + movq 64(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[7] + movq 56(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 112(%rsp) + # A[0] * A[15] + movq 120(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[14] + movq 112(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[13] + movq 104(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[12] + movq 96(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[11] + movq 88(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[10] + movq 80(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[9] + movq 72(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[8] + movq 64(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 120(%rsp) + # A[1] * A[15] + movq 120(%rsi), %rax + mulq 8(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[2] * A[14] + movq 112(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[13] + movq 104(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[12] + movq 96(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[11] + movq 88(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[10] + movq 80(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[9] + movq 72(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[8] + movq 64(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 128(%rdi) + # A[2] * A[15] + movq 120(%rsi), %rax + mulq 16(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[3] * A[14] + movq 112(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[13] + movq 104(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[12] + movq 96(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[11] + movq 88(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[10] + movq 80(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[9] + movq 72(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 136(%rdi) + # A[3] * A[15] + movq 120(%rsi), %rax + mulq 24(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[4] * A[14] + movq 112(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[13] + movq 104(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[12] + movq 96(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[11] + movq 88(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[10] + movq 80(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[9] + movq 72(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 144(%rdi) + # A[4] * A[15] + movq 120(%rsi), %rax + mulq 32(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[5] * A[14] + movq 112(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[13] + movq 104(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[12] + movq 96(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[11] + movq 88(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[10] + movq 80(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 152(%rdi) + # A[5] * A[15] + movq 120(%rsi), %rax + mulq 40(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[6] * A[14] + movq 112(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[13] + movq 104(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[12] + movq 96(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[11] + movq 88(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[10] + movq 80(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 160(%rdi) + # A[6] * A[15] + movq 120(%rsi), %rax + mulq 48(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[7] * A[14] + movq 112(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[13] + movq 104(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[12] + movq 96(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[11] + movq 88(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 168(%rdi) + # A[7] * A[15] + movq 120(%rsi), %rax + mulq 56(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[8] * A[14] + movq 112(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[13] + movq 104(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[12] + movq 96(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[11] + movq 88(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 176(%rdi) + # A[8] * A[15] + movq 120(%rsi), %rax + mulq 64(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[9] * A[14] + movq 112(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[13] + movq 104(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[12] + movq 96(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 184(%rdi) + # A[9] * A[15] + movq 120(%rsi), %rax + mulq 72(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[10] * A[14] + movq 112(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[13] + movq 104(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[12] + movq 96(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 192(%rdi) + # A[10] * A[15] + movq 120(%rsi), %rax + mulq 80(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[11] * A[14] + movq 112(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[13] + movq 104(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 200(%rdi) + # A[11] * A[15] + movq 120(%rsi), %rax + mulq 88(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[12] * A[14] + movq 112(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[13] * A[13] + movq 104(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 208(%rdi) + # A[12] * A[15] + movq 120(%rsi), %rax + mulq 96(%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * A[14] + movq 112(%rsi), %rax + mulq 104(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 216(%rdi) + # A[13] * A[15] + movq 120(%rsi), %rax + mulq 104(%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[14] * A[14] + movq 112(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 224(%rdi) + # A[14] * A[15] + movq 120(%rsi), %rax + mulq 112(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 232(%rdi) + # A[15] * A[15] + movq 120(%rsi), %rax + mulq %rax + addq %rax, %rcx + adcq %rdx, %r8 + movq %rcx, 240(%rdi) + movq %r8, 248(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 32(%rsp), %rax + movq 40(%rsp), %rdx + movq 48(%rsp), %r10 + movq 56(%rsp), %r11 + movq %rax, 32(%rdi) + movq %rdx, 40(%rdi) + movq %r10, 48(%rdi) + movq %r11, 56(%rdi) + movq 64(%rsp), %rax + movq 72(%rsp), %rdx + movq 80(%rsp), %r10 + movq 88(%rsp), %r11 + movq %rax, 64(%rdi) + movq %rdx, 72(%rdi) + movq %r10, 80(%rdi) + movq %r11, 88(%rdi) + movq 96(%rsp), %rax + movq 104(%rsp), %rdx + movq 112(%rsp), %r10 + movq 120(%rsp), %r11 + movq %rax, 96(%rdi) + movq %rdx, 104(%rdi) + movq %r10, 112(%rdi) + movq %r11, 120(%rdi) + addq $128, %rsp + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_2048_sqr_16,.-sp_2048_sqr_16 +#endif /* __APPLE__ */ +#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. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_avx2_16 +.type sp_2048_mul_avx2_16,@function +.align 16 +sp_2048_mul_avx2_16: +#else +.globl _sp_2048_mul_avx2_16 +.p2align 4 +_sp_2048_mul_avx2_16: +#endif /* __APPLE__ */ + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + movq %rdx, %rbp + subq $128, %rsp + cmpq %rdi, %rsi + movq %rsp, %rbx + cmovne %rdi, %rbx + cmpq %rdi, %rbp + cmove %rsp, %rbx + xorq %r14, %r14 + movq (%rsi), %rdx + # A[0] * B[0] + mulx (%rbp), %r8, %r9 + # A[0] * B[1] + mulx 8(%rbp), %rax, %r10 + movq %r8, (%rbx) + adcxq %rax, %r9 + # A[0] * B[2] + mulx 16(%rbp), %rax, %r11 + movq %r9, 8(%rbx) + adcxq %rax, %r10 + # A[0] * B[3] + mulx 24(%rbp), %rax, %r12 + movq %r10, 16(%rbx) + adcxq %rax, %r11 + movq %r11, 24(%rbx) + # A[0] * B[4] + mulx 32(%rbp), %rax, %r8 + adcxq %rax, %r12 + # A[0] * B[5] + mulx 40(%rbp), %rax, %r9 + movq %r12, 32(%rbx) + adcxq %rax, %r8 + # A[0] * B[6] + mulx 48(%rbp), %rax, %r10 + movq %r8, 40(%rbx) + adcxq %rax, %r9 + # A[0] * B[7] + mulx 56(%rbp), %rax, %r11 + movq %r9, 48(%rbx) + adcxq %rax, %r10 + movq %r10, 56(%rbx) + # A[0] * B[8] + mulx 64(%rbp), %rax, %r12 + adcxq %rax, %r11 + # A[0] * B[9] + mulx 72(%rbp), %rax, %r8 + movq %r11, 64(%rbx) + adcxq %rax, %r12 + # A[0] * B[10] + mulx 80(%rbp), %rax, %r9 + movq %r12, 72(%rbx) + adcxq %rax, %r8 + # A[0] * B[11] + mulx 88(%rbp), %rax, %r10 + movq %r8, 80(%rbx) + adcxq %rax, %r9 + movq %r9, 88(%rbx) + # A[0] * B[12] + mulx 96(%rbp), %rax, %r11 + adcxq %rax, %r10 + # A[0] * B[13] + mulx 104(%rbp), %rax, %r12 + movq %r10, 96(%rbx) + adcxq %rax, %r11 + # A[0] * B[14] + mulx 112(%rbp), %rax, %r8 + movq %r11, 104(%rbx) + adcxq %rax, %r12 + # A[0] * B[15] + mulx 120(%rbp), %rax, %r9 + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adcxq %r14, %r9 + movq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 120(%rbx) + movq %r9, 128(%rdi) + movq 8(%rsi), %rdx + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %r11 + movq 32(%rbx), %r12 + movq 40(%rbx), %r8 + # A[1] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 8(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[1] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 16(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[1] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 24(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 32(%rbx) + movq 48(%rbx), %r9 + movq 56(%rbx), %r10 + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + # A[1] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 40(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 48(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[1] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 56(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 64(%rbx) + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + # A[1] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[1] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rbx) + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq 128(%rdi), %r9 + # A[1] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[1] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[1] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, 128(%rdi) + movq %r10, 136(%rdi) + movq 16(%rsi), %rdx + movq 16(%rbx), %r10 + movq 24(%rbx), %r11 + movq 32(%rbx), %r12 + movq 40(%rbx), %r8 + movq 48(%rbx), %r9 + # A[2] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 16(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[2] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 24(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[2] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 32(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 40(%rbx) + movq 56(%rbx), %r10 + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + # A[2] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 48(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 56(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[2] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 64(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 72(%rbx) + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + # A[2] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[2] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 104(%rbx) + movq 120(%rbx), %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[2] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[2] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[2] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 136(%rdi) + movq %r11, 144(%rdi) + movq 24(%rsi), %rdx + movq 24(%rbx), %r11 + movq 32(%rbx), %r12 + movq 40(%rbx), %r8 + movq 48(%rbx), %r9 + movq 56(%rbx), %r10 + # A[3] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 24(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[3] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 32(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 40(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 48(%rbx) + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + # A[3] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 56(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 64(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[3] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 80(%rbx) + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + # A[3] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 112(%rbx) + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + # A[3] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 144(%rdi) + movq %r12, 152(%rdi) + movq 32(%rsi), %rdx + movq 32(%rbx), %r12 + movq 40(%rbx), %r8 + movq 48(%rbx), %r9 + movq 56(%rbx), %r10 + movq 64(%rbx), %r11 + # A[4] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, 32(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, 40(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[4] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 48(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 56(%rbx) + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + # A[4] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, 64(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 88(%rbx) + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq 128(%rdi), %r9 + # A[4] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[4] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rbx) + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + # A[4] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[4] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[4] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 152(%rdi) + movq %r8, 160(%rdi) + movq 40(%rsi), %rdx + movq 40(%rbx), %r8 + movq 48(%rbx), %r9 + movq 56(%rbx), %r10 + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + # A[5] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 40(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, 48(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[5] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 56(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 64(%rbx) + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + # A[5] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[5] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rbx) + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[5] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[5] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[5] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rdi) + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + # A[5] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[5] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[5] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[5] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 160(%rdi) + movq %r9, 168(%rdi) + movq 48(%rsi), %rdx + movq 48(%rbx), %r9 + movq 56(%rbx), %r10 + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + # A[6] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 48(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 56(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[6] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 64(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 72(%rbx) + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + # A[6] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 104(%rbx) + movq 120(%rbx), %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + # A[6] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[6] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 136(%rdi) + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + # A[6] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[6] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[6] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, 168(%rdi) + movq %r10, 176(%rdi) + movq 56(%rsi), %rdx + movq 56(%rbx), %r10 + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + # A[7] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 56(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[7] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 64(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[7] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 80(%rbx) + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + # A[7] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[7] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 112(%rbx) + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + # A[7] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[7] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 144(%rdi) + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + # A[7] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[7] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[7] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 176(%rdi) + movq %r11, 184(%rdi) + movq 64(%rsi), %rdx + movq 64(%rbx), %r11 + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + # A[8] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 64(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[8] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 88(%rbx) + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq 128(%rdi), %r9 + # A[8] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[8] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rbx) + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + # A[8] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 152(%rdi) + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + # A[8] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 176(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 184(%rdi) + movq %r12, 192(%rdi) + movq 72(%rsi), %rdx + movq 72(%rbx), %r12 + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + # A[9] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, 72(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rbx) + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[9] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[9] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rdi) + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + # A[9] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[9] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[9] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 160(%rdi) + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + movq 192(%rdi), %r12 + # A[9] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[9] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, 176(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[9] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, 184(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 192(%rdi) + movq %r8, 200(%rdi) + movq 80(%rsi), %rdx + movq 80(%rbx), %r8 + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + # A[10] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 80(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 104(%rbx) + movq 120(%rbx), %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + # A[10] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[10] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 136(%rdi) + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + # A[10] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[10] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[10] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 168(%rdi) + movq 184(%rdi), %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + # A[10] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, 176(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[10] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, 184(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[10] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 200(%rdi) + movq %r9, 208(%rdi) + movq 88(%rsi), %rdx + movq 88(%rbx), %r9 + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + # A[11] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 88(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[11] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[11] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 112(%rbx) + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + # A[11] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[11] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 144(%rdi) + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + # A[11] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[11] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 176(%rdi) + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + # A[11] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[11] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 184(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[11] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, 208(%rdi) + movq %r10, 216(%rdi) + movq 96(%rsi), %rdx + movq 96(%rbx), %r10 + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq 128(%rdi), %r9 + # A[12] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 96(%rbx) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[12] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[12] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rbx) + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + # A[12] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[12] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 152(%rdi) + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + movq 192(%rdi), %r12 + # A[12] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 176(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 184(%rdi) + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + # A[12] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[12] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 216(%rdi) + movq %r11, 224(%rdi) + movq 104(%rsi), %rdx + movq 104(%rbx), %r11 + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[13] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 104(%rbx) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[13] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rdi) + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + # A[13] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[13] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 160(%rdi) + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + # A[13] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 176(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 184(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 192(%rdi) + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + # A[13] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 224(%rdi) + movq %r12, 232(%rdi) + movq 112(%rsi), %rdx + movq 112(%rbx), %r12 + movq 120(%rbx), %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + # A[14] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, 112(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 136(%rdi) + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + # A[14] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[14] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 168(%rdi) + movq 184(%rdi), %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + # A[14] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 176(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[14] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, 184(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 200(%rdi) + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + # A[14] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[14] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 232(%rdi) + movq %r8, 240(%rdi) + movq 120(%rsi), %rdx + movq 120(%rbx), %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + # A[15] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 120(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 144(%rdi) + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + # A[15] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[15] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 176(%rdi) + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + # A[15] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[15] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, 184(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[15] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 208(%rdi) + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + # A[15] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[15] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[15] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + cmpq %rdi, %rsi + je L_start_2048_mul_avx2_16 + cmpq %rdi, %rbp + jne L_end_2048_mul_avx2_16 +L_start_2048_mul_avx2_16: + vmovdqu (%rbx), %xmm0 + vmovups %xmm0, (%rdi) + vmovdqu 16(%rbx), %xmm0 + vmovups %xmm0, 16(%rdi) + vmovdqu 32(%rbx), %xmm0 + vmovups %xmm0, 32(%rdi) + vmovdqu 48(%rbx), %xmm0 + vmovups %xmm0, 48(%rdi) + vmovdqu 64(%rbx), %xmm0 + vmovups %xmm0, 64(%rdi) + vmovdqu 80(%rbx), %xmm0 + vmovups %xmm0, 80(%rdi) + vmovdqu 96(%rbx), %xmm0 + vmovups %xmm0, 96(%rdi) + vmovdqu 112(%rbx), %xmm0 + vmovups %xmm0, 112(%rdi) +L_end_2048_mul_avx2_16: + addq $128, %rsp + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_avx2_16,.-sp_2048_mul_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_sqr_avx2_16 +.type sp_2048_sqr_avx2_16,@function +.align 16 +sp_2048_sqr_avx2_16: +#else +.globl _sp_2048_sqr_avx2_16 +.p2align 4 +_sp_2048_sqr_avx2_16: +#endif /* __APPLE__ */ + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + subq $128, %rsp + cmpq %rdi, %rsi + movq %rsp, %rbp + cmovne %rdi, %rbp + xorq %r11, %r11 + # Diagonal 1 + xorq %r10, %r10 + # A[1] x A[0] + movq (%rsi), %rdx + mulxq 8(%rsi), %r8, %r9 + # A[2] x A[0] + mulxq 16(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 8(%rbp) + movq %r9, 16(%rbp) + movq %r11, %r8 + movq %r11, %r9 + # A[3] x A[0] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[4] x A[0] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 24(%rbp) + movq %r8, 32(%rbp) + movq %r11, %r10 + movq %r11, %r8 + # A[5] x A[0] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] x A[0] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 40(%rbp) + movq %r10, 48(%rbp) + movq %r11, %r9 + movq %r11, %r10 + # A[7] x A[0] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] x A[0] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 56(%rbp) + movq %r9, 64(%rbp) + movq %r11, %r8 + movq %r11, %r9 + # A[9] x A[0] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[10] x A[0] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 72(%rbp) + movq %r8, 80(%rbp) + movq %r11, %r10 + movq %r11, %r8 + # A[11] x A[0] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] x A[0] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 88(%rbp) + movq %r10, %r13 + movq %r11, %r9 + movq %r11, %r10 + # A[13] x A[0] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[0] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, %r14 + movq %r9, %r15 + movq %r11, %r8 + # A[15] x A[0] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, %rbx + # Carry + adcxq %r11, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 128(%rdi) + # Diagonal 2 + movq 24(%rbp), %r8 + movq 32(%rbp), %r9 + movq 40(%rbp), %r10 + # A[2] x A[1] + movq 8(%rsi), %rdx + mulxq 16(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] x A[1] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 24(%rbp) + movq %r9, 32(%rbp) + movq 48(%rbp), %r8 + movq 56(%rbp), %r9 + # A[4] x A[1] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[5] x A[1] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 40(%rbp) + movq %r8, 48(%rbp) + movq 64(%rbp), %r10 + movq 72(%rbp), %r8 + # A[6] x A[1] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] x A[1] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 56(%rbp) + movq %r10, 64(%rbp) + movq 80(%rbp), %r9 + movq 88(%rbp), %r10 + # A[8] x A[1] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] x A[1] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 72(%rbp) + movq %r9, 80(%rbp) + # No load %r13 - %r8 + # No load %r14 - %r9 + # A[10] x A[1] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r13 + # A[11] x A[1] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + movq %r10, 88(%rbp) + # No store %r13 + # No load %r15 - %r10 + # No load %rbx - %r8 + # A[12] x A[1] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[13] x A[1] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r14 + # No store %r15 + movq 128(%rdi), %r9 + movq %r11, %r10 + # A[14] x A[1] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r9 + # A[15] x A[1] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # No store %rbx + movq %r9, 128(%rdi) + movq %r11, %r8 + # A[15] x A[2] + movq 16(%rsi), %rdx + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 136(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 144(%rdi) + # Diagonal 3 + movq 40(%rbp), %r8 + movq 48(%rbp), %r9 + movq 56(%rbp), %r10 + # A[3] x A[2] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] x A[2] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 40(%rbp) + movq %r9, 48(%rbp) + movq 64(%rbp), %r8 + movq 72(%rbp), %r9 + # A[5] x A[2] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[6] x A[2] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 56(%rbp) + movq %r8, 64(%rbp) + movq 80(%rbp), %r10 + movq 88(%rbp), %r8 + # A[7] x A[2] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] x A[2] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 72(%rbp) + movq %r10, 80(%rbp) + # No load %r13 - %r9 + # No load %r14 - %r10 + # A[9] x A[2] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r13 + # A[10] x A[2] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + movq %r8, 88(%rbp) + # No store %r13 + # No load %r15 - %r8 + # No load %rbx - %r9 + # A[11] x A[2] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[12] x A[2] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r14 + # No store %r15 + movq 128(%rdi), %r10 + movq 136(%rdi), %r8 + # A[13] x A[2] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r10 + # A[14] x A[2] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # No store %rbx + movq %r10, 128(%rdi) + movq 144(%rdi), %r9 + movq %r11, %r10 + # A[14] x A[3] + movq 112(%rsi), %rdx + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[4] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 136(%rdi) + movq %r9, 144(%rdi) + movq %r11, %r8 + # A[14] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 152(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 160(%rdi) + # Diagonal 4 + movq 56(%rbp), %r8 + movq 64(%rbp), %r9 + movq 72(%rbp), %r10 + # A[4] x A[3] + movq 24(%rsi), %rdx + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] x A[3] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 56(%rbp) + movq %r9, 64(%rbp) + movq 80(%rbp), %r8 + movq 88(%rbp), %r9 + # A[6] x A[3] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[7] x A[3] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 72(%rbp) + movq %r8, 80(%rbp) + # No load %r13 - %r10 + # No load %r14 - %r8 + # A[8] x A[3] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r13 + # A[9] x A[3] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + movq %r9, 88(%rbp) + # No store %r13 + # No load %r15 - %r9 + # No load %rbx - %r10 + # A[10] x A[3] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[11] x A[3] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r14 + # No store %r15 + movq 128(%rdi), %r8 + movq 136(%rdi), %r9 + # A[12] x A[3] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r8 + # A[13] x A[3] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # No store %rbx + movq %r8, 128(%rdi) + movq 144(%rdi), %r10 + movq 152(%rdi), %r8 + # A[13] x A[4] + movq 104(%rsi), %rdx + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 136(%rdi) + movq %r10, 144(%rdi) + movq 160(%rdi), %r9 + movq %r11, %r10 + # A[13] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 152(%rdi) + movq %r9, 160(%rdi) + movq %r11, %r8 + # A[13] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 168(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 176(%rdi) + # Diagonal 5 + movq 72(%rbp), %r8 + movq 80(%rbp), %r9 + movq 88(%rbp), %r10 + # A[5] x A[4] + movq 32(%rsi), %rdx + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] x A[4] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 72(%rbp) + movq %r9, 80(%rbp) + # No load %r13 - %r8 + # No load %r14 - %r9 + # A[7] x A[4] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r13 + # A[8] x A[4] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + movq %r10, 88(%rbp) + # No store %r13 + # No load %r15 - %r10 + # No load %rbx - %r8 + # A[9] x A[4] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[10] x A[4] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r14 + # No store %r15 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[11] x A[4] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r9 + # A[12] x A[4] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # No store %rbx + movq %r9, 128(%rdi) + movq 144(%rdi), %r8 + movq 152(%rdi), %r9 + # A[12] x A[5] + movq 96(%rsi), %rdx + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[12] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 136(%rdi) + movq %r8, 144(%rdi) + movq 160(%rdi), %r10 + movq 168(%rdi), %r8 + # A[12] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 152(%rdi) + movq %r10, 160(%rdi) + movq 176(%rdi), %r9 + movq %r11, %r10 + # A[12] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 168(%rdi) + movq %r9, 176(%rdi) + movq %r11, %r8 + # A[12] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 184(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 192(%rdi) + # Diagonal 6 + movq 88(%rbp), %r8 + # No load %r13 - %r9 + # No load %r14 - %r10 + # A[6] x A[5] + movq 40(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r13 + # A[7] x A[5] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + movq %r8, 88(%rbp) + # No store %r13 + # No load %r15 - %r8 + # No load %rbx - %r9 + # A[8] x A[5] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[9] x A[5] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r14 + # No store %r15 + movq 128(%rdi), %r10 + movq 136(%rdi), %r8 + # A[10] x A[5] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r10 + # A[11] x A[5] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # No store %rbx + movq %r10, 128(%rdi) + movq 144(%rdi), %r9 + movq 152(%rdi), %r10 + # A[11] x A[6] + movq 88(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 136(%rdi) + movq %r9, 144(%rdi) + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + # A[11] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[11] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 152(%rdi) + movq %r8, 160(%rdi) + movq 176(%rdi), %r10 + movq 184(%rdi), %r8 + # A[11] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] x A[9] + movq 104(%rsi), %rdx + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 168(%rdi) + movq %r10, 176(%rdi) + movq 192(%rdi), %r9 + movq %r11, %r10 + # A[13] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 184(%rdi) + movq %r9, 192(%rdi) + movq %r11, %r8 + # A[13] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 200(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 208(%rdi) + # Diagonal 7 + # No load %r14 - %r8 + # No load %r15 - %r9 + # No load %rbx - %r10 + # A[7] x A[6] + movq 48(%rsi), %rdx + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[8] x A[6] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r14 + # No store %r15 + movq 128(%rdi), %r8 + movq 136(%rdi), %r9 + # A[9] x A[6] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r8 + # A[10] x A[6] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # No store %rbx + movq %r8, 128(%rdi) + movq 144(%rdi), %r10 + movq 152(%rdi), %r8 + # A[10] x A[7] + movq 80(%rsi), %rdx + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 136(%rdi) + movq %r10, 144(%rdi) + movq 160(%rdi), %r9 + movq 168(%rdi), %r10 + # A[10] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[6] + movq 112(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 152(%rdi) + movq %r9, 160(%rdi) + movq 176(%rdi), %r8 + movq 184(%rdi), %r9 + # A[14] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[14] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 168(%rdi) + movq %r8, 176(%rdi) + movq 192(%rdi), %r10 + movq 200(%rdi), %r8 + # A[14] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 184(%rdi) + movq %r10, 192(%rdi) + movq 208(%rdi), %r9 + movq %r11, %r10 + # A[14] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 200(%rdi) + movq %r9, 208(%rdi) + movq %r11, %r8 + # A[14] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 216(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 224(%rdi) + # Diagonal 8 + # No load %rbx - %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[8] x A[7] + movq 56(%rsi), %rdx + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r9 + # A[9] x A[7] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # No store %rbx + movq %r9, 128(%rdi) + movq 144(%rdi), %r8 + movq 152(%rdi), %r9 + # A[9] x A[8] + movq 64(%rsi), %rdx + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[15] x A[3] + movq 120(%rsi), %rdx + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 136(%rdi) + movq %r8, 144(%rdi) + movq 160(%rdi), %r10 + movq 168(%rdi), %r8 + # A[15] x A[4] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 152(%rdi) + movq %r10, 160(%rdi) + movq 176(%rdi), %r9 + movq 184(%rdi), %r10 + # A[15] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 168(%rdi) + movq %r9, 176(%rdi) + movq 192(%rdi), %r8 + movq 200(%rdi), %r9 + # A[15] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[15] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 184(%rdi) + movq %r8, 192(%rdi) + movq 208(%rdi), %r10 + movq 216(%rdi), %r8 + # A[15] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r9, 200(%rdi) + movq %r10, 208(%rdi) + movq 224(%rdi), %r9 + movq %r11, %r10 + # A[15] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 216(%rdi) + movq %r9, 224(%rdi) + movq %r11, %r8 + # A[15] x A[14] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 232(%rdi) + # Carry + adcxq %r12, %r8 + movq %r11, %r12 + adcxq %r11, %r12 + adoxq %r11, %r12 + movq %r8, 240(%rdi) + movq %r12, 248(%rdi) + # Double and Add in A[i] x A[i] + movq 8(%rbp), %r9 + # A[0] x A[0] + movq (%rsi), %rdx + mulxq %rdx, %rax, %rcx + movq %rax, (%rbp) + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r9, 8(%rbp) + movq 16(%rbp), %r8 + movq 24(%rbp), %r9 + # A[1] x A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 16(%rbp) + movq %r9, 24(%rbp) + movq 32(%rbp), %r8 + movq 40(%rbp), %r9 + # A[2] x A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 32(%rbp) + movq %r9, 40(%rbp) + movq 48(%rbp), %r8 + movq 56(%rbp), %r9 + # A[3] x A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 48(%rbp) + movq %r9, 56(%rbp) + movq 64(%rbp), %r8 + movq 72(%rbp), %r9 + # A[4] x A[4] + movq 32(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 64(%rbp) + movq %r9, 72(%rbp) + movq 80(%rbp), %r8 + movq 88(%rbp), %r9 + # A[5] x A[5] + movq 40(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 80(%rbp) + movq %r9, 88(%rbp) + # A[6] x A[6] + movq 48(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r13, %r13 + adoxq %r14, %r14 + adcxq %rax, %r13 + adcxq %rcx, %r14 + # A[7] x A[7] + movq 56(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r15, %r15 + adoxq %rbx, %rbx + adcxq %rax, %r15 + adcxq %rcx, %rbx + movq 128(%rdi), %r8 + movq 136(%rdi), %r9 + # A[8] x A[8] + movq 64(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 128(%rdi) + movq %r9, 136(%rdi) + movq 144(%rdi), %r8 + movq 152(%rdi), %r9 + # A[9] x A[9] + movq 72(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 144(%rdi) + movq %r9, 152(%rdi) + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + # A[10] x A[10] + movq 80(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 160(%rdi) + movq %r9, 168(%rdi) + movq 176(%rdi), %r8 + movq 184(%rdi), %r9 + # A[11] x A[11] + movq 88(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 176(%rdi) + movq %r9, 184(%rdi) + movq 192(%rdi), %r8 + movq 200(%rdi), %r9 + # A[12] x A[12] + movq 96(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 192(%rdi) + movq %r9, 200(%rdi) + movq 208(%rdi), %r8 + movq 216(%rdi), %r9 + # A[13] x A[13] + movq 104(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 208(%rdi) + movq %r9, 216(%rdi) + movq 224(%rdi), %r8 + movq 232(%rdi), %r9 + # A[14] x A[14] + movq 112(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 224(%rdi) + movq %r9, 232(%rdi) + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + # A[15] x A[15] + movq 120(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + movq %r13, 96(%rdi) + movq %r14, 104(%rdi) + movq %r15, 112(%rdi) + movq %rbx, 120(%rdi) + cmpq %rdi, %rsi + jne L_end_2048_sqr_avx2_16 + vmovdqu (%rbp), %xmm0 + vmovups %xmm0, (%rdi) + vmovdqu 16(%rbp), %xmm0 + vmovups %xmm0, 16(%rdi) + vmovdqu 32(%rbp), %xmm0 + vmovups %xmm0, 32(%rdi) + vmovdqu 48(%rbp), %xmm0 + vmovups %xmm0, 48(%rdi) + vmovdqu 64(%rbp), %xmm0 + vmovups %xmm0, 64(%rdi) + vmovdqu 80(%rbp), %xmm0 + vmovups %xmm0, 80(%rdi) +L_end_2048_sqr_avx2_16: + addq $128, %rsp + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + repz retq +#ifndef __APPLE__ +.size sp_2048_sqr_avx2_16,.-sp_2048_sqr_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_add_16 +.type sp_2048_add_16,@function +.align 16 +sp_2048_add_16: +#else +.globl _sp_2048_add_16 +.p2align 4 +_sp_2048_add_16: +#endif /* __APPLE__ */ + # Add + movq (%rsi), %rcx + xorq %rax, %rax + addq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + adcq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + adcq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + adcq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + adcq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + adcq 40(%rdx), %r8 + movq 48(%rsi), %rcx + movq %r8, 40(%rdi) + adcq 48(%rdx), %rcx + movq 56(%rsi), %r8 + movq %rcx, 48(%rdi) + adcq 56(%rdx), %r8 + movq 64(%rsi), %rcx + movq %r8, 56(%rdi) + adcq 64(%rdx), %rcx + movq 72(%rsi), %r8 + movq %rcx, 64(%rdi) + adcq 72(%rdx), %r8 + movq 80(%rsi), %rcx + movq %r8, 72(%rdi) + adcq 80(%rdx), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%rdi) + adcq 88(%rdx), %r8 + movq 96(%rsi), %rcx + movq %r8, 88(%rdi) + adcq 96(%rdx), %rcx + movq 104(%rsi), %r8 + movq %rcx, 96(%rdi) + adcq 104(%rdx), %r8 + movq 112(%rsi), %rcx + movq %r8, 104(%rdi) + adcq 112(%rdx), %rcx + movq 120(%rsi), %r8 + movq %rcx, 112(%rdi) + adcq 120(%rdx), %r8 + movq %r8, 120(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_add_16,.-sp_2048_add_16 +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_sub_in_place_32 +.type sp_2048_sub_in_place_32,@function +.align 16 +sp_2048_sub_in_place_32: +#else +.globl _sp_2048_sub_in_place_32 +.p2align 4 +_sp_2048_sub_in_place_32: +#endif /* __APPLE__ */ + movq (%rdi), %rdx + xorq %rax, %rax + subq (%rsi), %rdx + movq 8(%rdi), %rcx + movq %rdx, (%rdi) + sbbq 8(%rsi), %rcx + movq 16(%rdi), %rdx + movq %rcx, 8(%rdi) + sbbq 16(%rsi), %rdx + movq 24(%rdi), %rcx + movq %rdx, 16(%rdi) + sbbq 24(%rsi), %rcx + movq 32(%rdi), %rdx + movq %rcx, 24(%rdi) + sbbq 32(%rsi), %rdx + movq 40(%rdi), %rcx + movq %rdx, 32(%rdi) + sbbq 40(%rsi), %rcx + movq 48(%rdi), %rdx + movq %rcx, 40(%rdi) + sbbq 48(%rsi), %rdx + movq 56(%rdi), %rcx + movq %rdx, 48(%rdi) + sbbq 56(%rsi), %rcx + movq 64(%rdi), %rdx + movq %rcx, 56(%rdi) + sbbq 64(%rsi), %rdx + movq 72(%rdi), %rcx + movq %rdx, 64(%rdi) + sbbq 72(%rsi), %rcx + movq 80(%rdi), %rdx + movq %rcx, 72(%rdi) + sbbq 80(%rsi), %rdx + movq 88(%rdi), %rcx + movq %rdx, 80(%rdi) + sbbq 88(%rsi), %rcx + movq 96(%rdi), %rdx + movq %rcx, 88(%rdi) + sbbq 96(%rsi), %rdx + movq 104(%rdi), %rcx + movq %rdx, 96(%rdi) + sbbq 104(%rsi), %rcx + movq 112(%rdi), %rdx + movq %rcx, 104(%rdi) + sbbq 112(%rsi), %rdx + movq 120(%rdi), %rcx + movq %rdx, 112(%rdi) + sbbq 120(%rsi), %rcx + movq 128(%rdi), %rdx + movq %rcx, 120(%rdi) + sbbq 128(%rsi), %rdx + movq 136(%rdi), %rcx + movq %rdx, 128(%rdi) + sbbq 136(%rsi), %rcx + movq 144(%rdi), %rdx + movq %rcx, 136(%rdi) + sbbq 144(%rsi), %rdx + movq 152(%rdi), %rcx + movq %rdx, 144(%rdi) + sbbq 152(%rsi), %rcx + movq 160(%rdi), %rdx + movq %rcx, 152(%rdi) + sbbq 160(%rsi), %rdx + movq 168(%rdi), %rcx + movq %rdx, 160(%rdi) + sbbq 168(%rsi), %rcx + movq 176(%rdi), %rdx + movq %rcx, 168(%rdi) + sbbq 176(%rsi), %rdx + movq 184(%rdi), %rcx + movq %rdx, 176(%rdi) + sbbq 184(%rsi), %rcx + movq 192(%rdi), %rdx + movq %rcx, 184(%rdi) + sbbq 192(%rsi), %rdx + movq 200(%rdi), %rcx + movq %rdx, 192(%rdi) + sbbq 200(%rsi), %rcx + movq 208(%rdi), %rdx + movq %rcx, 200(%rdi) + sbbq 208(%rsi), %rdx + movq 216(%rdi), %rcx + movq %rdx, 208(%rdi) + sbbq 216(%rsi), %rcx + movq 224(%rdi), %rdx + movq %rcx, 216(%rdi) + sbbq 224(%rsi), %rdx + movq 232(%rdi), %rcx + movq %rdx, 224(%rdi) + sbbq 232(%rsi), %rcx + movq 240(%rdi), %rdx + movq %rcx, 232(%rdi) + sbbq 240(%rsi), %rdx + movq 248(%rdi), %rcx + movq %rdx, 240(%rdi) + sbbq 248(%rsi), %rcx + movq %rcx, 248(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_sub_in_place_32,.-sp_2048_sub_in_place_32 +#endif /* __APPLE__ */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_add_32 +.type sp_2048_add_32,@function +.align 16 +sp_2048_add_32: +#else +.globl _sp_2048_add_32 +.p2align 4 +_sp_2048_add_32: +#endif /* __APPLE__ */ + # Add + movq (%rsi), %rcx + xorq %rax, %rax + addq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + adcq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + adcq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + adcq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + adcq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + adcq 40(%rdx), %r8 + movq 48(%rsi), %rcx + movq %r8, 40(%rdi) + adcq 48(%rdx), %rcx + movq 56(%rsi), %r8 + movq %rcx, 48(%rdi) + adcq 56(%rdx), %r8 + movq 64(%rsi), %rcx + movq %r8, 56(%rdi) + adcq 64(%rdx), %rcx + movq 72(%rsi), %r8 + movq %rcx, 64(%rdi) + adcq 72(%rdx), %r8 + movq 80(%rsi), %rcx + movq %r8, 72(%rdi) + adcq 80(%rdx), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%rdi) + adcq 88(%rdx), %r8 + movq 96(%rsi), %rcx + movq %r8, 88(%rdi) + adcq 96(%rdx), %rcx + movq 104(%rsi), %r8 + movq %rcx, 96(%rdi) + adcq 104(%rdx), %r8 + movq 112(%rsi), %rcx + movq %r8, 104(%rdi) + adcq 112(%rdx), %rcx + movq 120(%rsi), %r8 + movq %rcx, 112(%rdi) + adcq 120(%rdx), %r8 + movq 128(%rsi), %rcx + movq %r8, 120(%rdi) + adcq 128(%rdx), %rcx + movq 136(%rsi), %r8 + movq %rcx, 128(%rdi) + adcq 136(%rdx), %r8 + movq 144(%rsi), %rcx + movq %r8, 136(%rdi) + adcq 144(%rdx), %rcx + movq 152(%rsi), %r8 + movq %rcx, 144(%rdi) + adcq 152(%rdx), %r8 + movq 160(%rsi), %rcx + movq %r8, 152(%rdi) + adcq 160(%rdx), %rcx + movq 168(%rsi), %r8 + movq %rcx, 160(%rdi) + adcq 168(%rdx), %r8 + movq 176(%rsi), %rcx + movq %r8, 168(%rdi) + adcq 176(%rdx), %rcx + movq 184(%rsi), %r8 + movq %rcx, 176(%rdi) + adcq 184(%rdx), %r8 + movq 192(%rsi), %rcx + movq %r8, 184(%rdi) + adcq 192(%rdx), %rcx + movq 200(%rsi), %r8 + movq %rcx, 192(%rdi) + adcq 200(%rdx), %r8 + movq 208(%rsi), %rcx + movq %r8, 200(%rdi) + adcq 208(%rdx), %rcx + movq 216(%rsi), %r8 + movq %rcx, 208(%rdi) + adcq 216(%rdx), %r8 + movq 224(%rsi), %rcx + movq %r8, 216(%rdi) + adcq 224(%rdx), %rcx + movq 232(%rsi), %r8 + movq %rcx, 224(%rdi) + adcq 232(%rdx), %r8 + movq 240(%rsi), %rcx + movq %r8, 232(%rdi) + adcq 240(%rdx), %rcx + movq 248(%rsi), %r8 + movq %rcx, 240(%rdi) + adcq 248(%rdx), %r8 + movq %r8, 248(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_add_32,.-sp_2048_add_32 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_32 +.type sp_2048_mul_32,@function +.align 16 +sp_2048_mul_32: +#else +.globl _sp_2048_mul_32 +.p2align 4 +_sp_2048_mul_32: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + subq $808, %rsp + movq %rdi, 768(%rsp) + movq %rsi, 776(%rsp) + movq %rdx, 784(%rsp) + leaq 512(%rsp), %r10 + leaq 128(%rsi), %r12 + # Add + movq (%rsi), %rax + xorq %r13, %r13 + addq (%r12), %rax + movq 8(%rsi), %rcx + movq %rax, (%r10) + adcq 8(%r12), %rcx + movq 16(%rsi), %r8 + movq %rcx, 8(%r10) + adcq 16(%r12), %r8 + movq 24(%rsi), %rax + movq %r8, 16(%r10) + adcq 24(%r12), %rax + movq 32(%rsi), %rcx + movq %rax, 24(%r10) + adcq 32(%r12), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%r10) + adcq 40(%r12), %r8 + movq 48(%rsi), %rax + movq %r8, 40(%r10) + adcq 48(%r12), %rax + movq 56(%rsi), %rcx + movq %rax, 48(%r10) + adcq 56(%r12), %rcx + movq 64(%rsi), %r8 + movq %rcx, 56(%r10) + adcq 64(%r12), %r8 + movq 72(%rsi), %rax + movq %r8, 64(%r10) + adcq 72(%r12), %rax + movq 80(%rsi), %rcx + movq %rax, 72(%r10) + adcq 80(%r12), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%r10) + adcq 88(%r12), %r8 + movq 96(%rsi), %rax + movq %r8, 88(%r10) + adcq 96(%r12), %rax + movq 104(%rsi), %rcx + movq %rax, 96(%r10) + adcq 104(%r12), %rcx + movq 112(%rsi), %r8 + movq %rcx, 104(%r10) + adcq 112(%r12), %r8 + movq 120(%rsi), %rax + movq %r8, 112(%r10) + adcq 120(%r12), %rax + movq %rax, 120(%r10) + adcq $0, %r13 + movq %r13, 792(%rsp) + leaq 640(%rsp), %r11 + leaq 128(%rdx), %r12 + # Add + movq (%rdx), %rax + xorq %r14, %r14 + addq (%r12), %rax + movq 8(%rdx), %rcx + movq %rax, (%r11) + adcq 8(%r12), %rcx + movq 16(%rdx), %r8 + movq %rcx, 8(%r11) + adcq 16(%r12), %r8 + movq 24(%rdx), %rax + movq %r8, 16(%r11) + adcq 24(%r12), %rax + movq 32(%rdx), %rcx + movq %rax, 24(%r11) + adcq 32(%r12), %rcx + movq 40(%rdx), %r8 + movq %rcx, 32(%r11) + adcq 40(%r12), %r8 + movq 48(%rdx), %rax + movq %r8, 40(%r11) + adcq 48(%r12), %rax + movq 56(%rdx), %rcx + movq %rax, 48(%r11) + adcq 56(%r12), %rcx + movq 64(%rdx), %r8 + movq %rcx, 56(%r11) + adcq 64(%r12), %r8 + movq 72(%rdx), %rax + movq %r8, 64(%r11) + adcq 72(%r12), %rax + movq 80(%rdx), %rcx + movq %rax, 72(%r11) + adcq 80(%r12), %rcx + movq 88(%rdx), %r8 + movq %rcx, 80(%r11) + adcq 88(%r12), %r8 + movq 96(%rdx), %rax + movq %r8, 88(%r11) + adcq 96(%r12), %rax + movq 104(%rdx), %rcx + movq %rax, 96(%r11) + adcq 104(%r12), %rcx + movq 112(%rdx), %r8 + movq %rcx, 104(%r11) + adcq 112(%r12), %r8 + movq 120(%rdx), %rax + movq %r8, 112(%r11) + adcq 120(%r12), %rax + movq %rax, 120(%r11) + adcq $0, %r14 + movq %r14, 800(%rsp) + movq %r11, %rdx + movq %r10, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_2048_mul_16@plt +#else + callq _sp_2048_mul_16 +#endif /* __APPLE__ */ + movq 784(%rsp), %rdx + movq 776(%rsp), %rsi + leaq 256(%rsp), %rdi + addq $128, %rdx + addq $128, %rsi +#ifndef __APPLE__ + callq sp_2048_mul_16@plt +#else + callq _sp_2048_mul_16 +#endif /* __APPLE__ */ + movq 784(%rsp), %rdx + movq 776(%rsp), %rsi + movq 768(%rsp), %rdi +#ifndef __APPLE__ + callq sp_2048_mul_16@plt +#else + callq _sp_2048_mul_16 +#endif /* __APPLE__ */ + movq 792(%rsp), %r13 + movq 800(%rsp), %r14 + movq 768(%rsp), %r15 + movq %r13, %r9 + leaq 512(%rsp), %r10 + leaq 640(%rsp), %r11 + andq %r14, %r9 + negq %r13 + negq %r14 + addq $256, %r15 + movq (%r10), %rax + movq (%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, (%r10) + movq %rcx, (%r11) + movq 8(%r10), %rax + movq 8(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 8(%r10) + movq %rcx, 8(%r11) + movq 16(%r10), %rax + movq 16(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 16(%r10) + movq %rcx, 16(%r11) + movq 24(%r10), %rax + movq 24(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 24(%r10) + movq %rcx, 24(%r11) + movq 32(%r10), %rax + movq 32(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 32(%r10) + movq %rcx, 32(%r11) + movq 40(%r10), %rax + movq 40(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 40(%r10) + movq %rcx, 40(%r11) + movq 48(%r10), %rax + movq 48(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 48(%r10) + movq %rcx, 48(%r11) + movq 56(%r10), %rax + movq 56(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 56(%r10) + movq %rcx, 56(%r11) + movq 64(%r10), %rax + movq 64(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 64(%r10) + movq %rcx, 64(%r11) + movq 72(%r10), %rax + movq 72(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 72(%r10) + movq %rcx, 72(%r11) + movq 80(%r10), %rax + movq 80(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 80(%r10) + movq %rcx, 80(%r11) + movq 88(%r10), %rax + movq 88(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 88(%r10) + movq %rcx, 88(%r11) + movq 96(%r10), %rax + movq 96(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 96(%r10) + movq %rcx, 96(%r11) + movq 104(%r10), %rax + movq 104(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 104(%r10) + movq %rcx, 104(%r11) + movq 112(%r10), %rax + movq 112(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 112(%r10) + movq %rcx, 112(%r11) + movq 120(%r10), %rax + movq 120(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 120(%r10) + movq %rcx, 120(%r11) + movq (%r10), %rax + addq (%r11), %rax + movq 8(%r10), %rcx + movq %rax, (%r15) + adcq 8(%r11), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r15) + adcq 16(%r11), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r15) + adcq 24(%r11), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r15) + adcq 32(%r11), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r15) + adcq 40(%r11), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r15) + adcq 48(%r11), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r15) + adcq 56(%r11), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r15) + adcq 64(%r11), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r15) + adcq 72(%r11), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r15) + adcq 80(%r11), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r15) + adcq 88(%r11), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r15) + adcq 96(%r11), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r15) + adcq 104(%r11), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r15) + adcq 112(%r11), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r15) + adcq 120(%r11), %rax + movq %rax, 120(%r15) + adcq $0, %r9 + leaq 256(%rsp), %r11 + movq %rsp, %r10 + movq (%r10), %rax + subq (%r11), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%r11), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%r11), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%r11), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%r11), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%r11), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%r11), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%r11), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%r11), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%r11), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%r11), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%r11), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%r11), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%r11), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%r11), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%r11), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%r11), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%r11), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%r11), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%r11), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%r11), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%r11), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%r11), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%r11), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r10) + sbbq 192(%r11), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r10) + sbbq 200(%r11), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r10) + sbbq 208(%r11), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r10) + sbbq 216(%r11), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r10) + sbbq 224(%r11), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r10) + sbbq 232(%r11), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r10) + sbbq 240(%r11), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r10) + sbbq 248(%r11), %rcx + movq %rcx, 248(%r10) + sbbq $0, %r9 + movq (%r10), %rax + subq (%rdi), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%rdi), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%rdi), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%rdi), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%rdi), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%rdi), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%rdi), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%rdi), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%rdi), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%rdi), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%rdi), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%rdi), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%rdi), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%rdi), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%rdi), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%rdi), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%rdi), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%rdi), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%rdi), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%rdi), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%rdi), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%rdi), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%rdi), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%rdi), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r10) + sbbq 192(%rdi), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r10) + sbbq 200(%rdi), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r10) + sbbq 208(%rdi), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r10) + sbbq 216(%rdi), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r10) + sbbq 224(%rdi), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r10) + sbbq 232(%rdi), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r10) + sbbq 240(%rdi), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r10) + sbbq 248(%rdi), %rcx + movq %rcx, 248(%r10) + sbbq $0, %r9 + subq $128, %r15 + # Add + movq (%r15), %rax + addq (%r10), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r10), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r10), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r10), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r10), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r10), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r10), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r10), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r10), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r10), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r10), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r10), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r10), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r10), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r10), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r10), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r10), %rcx + movq 136(%r15), %r8 + movq %rcx, 128(%r15) + adcq 136(%r10), %r8 + movq 144(%r15), %rax + movq %r8, 136(%r15) + adcq 144(%r10), %rax + movq 152(%r15), %rcx + movq %rax, 144(%r15) + adcq 152(%r10), %rcx + movq 160(%r15), %r8 + movq %rcx, 152(%r15) + adcq 160(%r10), %r8 + movq 168(%r15), %rax + movq %r8, 160(%r15) + adcq 168(%r10), %rax + movq 176(%r15), %rcx + movq %rax, 168(%r15) + adcq 176(%r10), %rcx + movq 184(%r15), %r8 + movq %rcx, 176(%r15) + adcq 184(%r10), %r8 + movq 192(%r15), %rax + movq %r8, 184(%r15) + adcq 192(%r10), %rax + movq 200(%r15), %rcx + movq %rax, 192(%r15) + adcq 200(%r10), %rcx + movq 208(%r15), %r8 + movq %rcx, 200(%r15) + adcq 208(%r10), %r8 + movq 216(%r15), %rax + movq %r8, 208(%r15) + adcq 216(%r10), %rax + movq 224(%r15), %rcx + movq %rax, 216(%r15) + adcq 224(%r10), %rcx + movq 232(%r15), %r8 + movq %rcx, 224(%r15) + adcq 232(%r10), %r8 + movq 240(%r15), %rax + movq %r8, 232(%r15) + adcq 240(%r10), %rax + movq 248(%r15), %rcx + movq %rax, 240(%r15) + adcq 248(%r10), %rcx + movq %rcx, 248(%r15) + adcq $0, %r9 + movq %r9, 384(%rdi) + addq $128, %r15 + # Add + movq (%r15), %rax + xorq %r9, %r9 + addq (%r11), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r11), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r11), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r11), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r11), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r11), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r11), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r11), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r11), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r11), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r11), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r11), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r11), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r11), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r11), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r11), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r11), %rcx + movq %rcx, 128(%r15) + adcq $0, %r9 + # Add to zero + movq 136(%r11), %rax + adcq $0, %rax + movq 144(%r11), %rcx + movq %rax, 136(%r15) + adcq $0, %rcx + movq 152(%r11), %r8 + movq %rcx, 144(%r15) + adcq $0, %r8 + movq 160(%r11), %rax + movq %r8, 152(%r15) + adcq $0, %rax + movq 168(%r11), %rcx + movq %rax, 160(%r15) + adcq $0, %rcx + movq 176(%r11), %r8 + movq %rcx, 168(%r15) + adcq $0, %r8 + movq 184(%r11), %rax + movq %r8, 176(%r15) + adcq $0, %rax + movq 192(%r11), %rcx + movq %rax, 184(%r15) + adcq $0, %rcx + movq 200(%r11), %r8 + movq %rcx, 192(%r15) + adcq $0, %r8 + movq 208(%r11), %rax + movq %r8, 200(%r15) + adcq $0, %rax + movq 216(%r11), %rcx + movq %rax, 208(%r15) + adcq $0, %rcx + movq 224(%r11), %r8 + movq %rcx, 216(%r15) + adcq $0, %r8 + movq 232(%r11), %rax + movq %r8, 224(%r15) + adcq $0, %rax + movq 240(%r11), %rcx + movq %rax, 232(%r15) + adcq $0, %rcx + movq 248(%r11), %r8 + movq %rcx, 240(%r15) + adcq $0, %r8 + movq %r8, 248(%r15) + addq $808, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_32,.-sp_2048_mul_32 +#endif /* __APPLE__ */ +/* Add a to a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_dbl_16 +.type sp_2048_dbl_16,@function +.align 16 +sp_2048_dbl_16: +#else +.globl _sp_2048_dbl_16 +.p2align 4 +_sp_2048_dbl_16: +#endif /* __APPLE__ */ + movq (%rsi), %rdx + xorq %rax, %rax + addq %rdx, %rdx + movq 8(%rsi), %rcx + movq %rdx, (%rdi) + adcq %rcx, %rcx + movq 16(%rsi), %rdx + movq %rcx, 8(%rdi) + adcq %rdx, %rdx + movq 24(%rsi), %rcx + movq %rdx, 16(%rdi) + adcq %rcx, %rcx + movq 32(%rsi), %rdx + movq %rcx, 24(%rdi) + adcq %rdx, %rdx + movq 40(%rsi), %rcx + movq %rdx, 32(%rdi) + adcq %rcx, %rcx + movq 48(%rsi), %rdx + movq %rcx, 40(%rdi) + adcq %rdx, %rdx + movq 56(%rsi), %rcx + movq %rdx, 48(%rdi) + adcq %rcx, %rcx + movq 64(%rsi), %rdx + movq %rcx, 56(%rdi) + adcq %rdx, %rdx + movq 72(%rsi), %rcx + movq %rdx, 64(%rdi) + adcq %rcx, %rcx + movq 80(%rsi), %rdx + movq %rcx, 72(%rdi) + adcq %rdx, %rdx + movq 88(%rsi), %rcx + movq %rdx, 80(%rdi) + adcq %rcx, %rcx + movq 96(%rsi), %rdx + movq %rcx, 88(%rdi) + adcq %rdx, %rdx + movq 104(%rsi), %rcx + movq %rdx, 96(%rdi) + adcq %rcx, %rcx + movq 112(%rsi), %rdx + movq %rcx, 104(%rdi) + adcq %rdx, %rdx + movq 120(%rsi), %rcx + movq %rdx, 112(%rdi) + adcq %rcx, %rcx + movq %rcx, 120(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_dbl_16,.-sp_2048_dbl_16 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_sqr_32 +.type sp_2048_sqr_32,@function +.align 16 +sp_2048_sqr_32: +#else +.globl _sp_2048_sqr_32 +.p2align 4 +_sp_2048_sqr_32: +#endif /* __APPLE__ */ + subq $664, %rsp + movq %rdi, 640(%rsp) + movq %rsi, 648(%rsp) + leaq 512(%rsp), %r8 + leaq 128(%rsi), %r9 + # Add + movq (%rsi), %rdx + xorq %rcx, %rcx + addq (%r9), %rdx + movq 8(%rsi), %rax + movq %rdx, (%r8) + adcq 8(%r9), %rax + movq 16(%rsi), %rdx + movq %rax, 8(%r8) + adcq 16(%r9), %rdx + movq 24(%rsi), %rax + movq %rdx, 16(%r8) + adcq 24(%r9), %rax + movq 32(%rsi), %rdx + movq %rax, 24(%r8) + adcq 32(%r9), %rdx + movq 40(%rsi), %rax + movq %rdx, 32(%r8) + adcq 40(%r9), %rax + movq 48(%rsi), %rdx + movq %rax, 40(%r8) + adcq 48(%r9), %rdx + movq 56(%rsi), %rax + movq %rdx, 48(%r8) + adcq 56(%r9), %rax + movq 64(%rsi), %rdx + movq %rax, 56(%r8) + adcq 64(%r9), %rdx + movq 72(%rsi), %rax + movq %rdx, 64(%r8) + adcq 72(%r9), %rax + movq 80(%rsi), %rdx + movq %rax, 72(%r8) + adcq 80(%r9), %rdx + movq 88(%rsi), %rax + movq %rdx, 80(%r8) + adcq 88(%r9), %rax + movq 96(%rsi), %rdx + movq %rax, 88(%r8) + adcq 96(%r9), %rdx + movq 104(%rsi), %rax + movq %rdx, 96(%r8) + adcq 104(%r9), %rax + movq 112(%rsi), %rdx + movq %rax, 104(%r8) + adcq 112(%r9), %rdx + movq 120(%rsi), %rax + movq %rdx, 112(%r8) + adcq 120(%r9), %rax + movq %rax, 120(%r8) + adcq $0, %rcx + movq %rcx, 656(%rsp) + movq %r8, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_2048_sqr_16@plt +#else + callq _sp_2048_sqr_16 +#endif /* __APPLE__ */ + movq 648(%rsp), %rsi + leaq 256(%rsp), %rdi + addq $128, %rsi +#ifndef __APPLE__ + callq sp_2048_sqr_16@plt +#else + callq _sp_2048_sqr_16 +#endif /* __APPLE__ */ + movq 648(%rsp), %rsi + movq 640(%rsp), %rdi +#ifndef __APPLE__ + callq sp_2048_sqr_16@plt +#else + callq _sp_2048_sqr_16 +#endif /* __APPLE__ */ + movq 656(%rsp), %r10 + leaq 512(%rsp), %r8 + movq %r10, %rcx + negq %r10 + movq (%r8), %rdx + movq 8(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 256(%rdi) + movq %rax, 264(%rdi) + movq 16(%r8), %rdx + movq 24(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 272(%rdi) + movq %rax, 280(%rdi) + movq 32(%r8), %rdx + movq 40(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 288(%rdi) + movq %rax, 296(%rdi) + movq 48(%r8), %rdx + movq 56(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 304(%rdi) + movq %rax, 312(%rdi) + movq 64(%r8), %rdx + movq 72(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 320(%rdi) + movq %rax, 328(%rdi) + movq 80(%r8), %rdx + movq 88(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 336(%rdi) + movq %rax, 344(%rdi) + movq 96(%r8), %rdx + movq 104(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 352(%rdi) + movq %rax, 360(%rdi) + movq 112(%r8), %rdx + movq 120(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 368(%rdi) + movq %rax, 376(%rdi) + movq 256(%rdi), %rdx + addq %rdx, %rdx + movq 264(%rdi), %rax + movq %rdx, 256(%rdi) + adcq %rax, %rax + movq 272(%rdi), %rdx + movq %rax, 264(%rdi) + adcq %rdx, %rdx + movq 280(%rdi), %rax + movq %rdx, 272(%rdi) + adcq %rax, %rax + movq 288(%rdi), %rdx + movq %rax, 280(%rdi) + adcq %rdx, %rdx + movq 296(%rdi), %rax + movq %rdx, 288(%rdi) + adcq %rax, %rax + movq 304(%rdi), %rdx + movq %rax, 296(%rdi) + adcq %rdx, %rdx + movq 312(%rdi), %rax + movq %rdx, 304(%rdi) + adcq %rax, %rax + movq 320(%rdi), %rdx + movq %rax, 312(%rdi) + adcq %rdx, %rdx + movq 328(%rdi), %rax + movq %rdx, 320(%rdi) + adcq %rax, %rax + movq 336(%rdi), %rdx + movq %rax, 328(%rdi) + adcq %rdx, %rdx + movq 344(%rdi), %rax + movq %rdx, 336(%rdi) + adcq %rax, %rax + movq 352(%rdi), %rdx + movq %rax, 344(%rdi) + adcq %rdx, %rdx + movq 360(%rdi), %rax + movq %rdx, 352(%rdi) + adcq %rax, %rax + movq 368(%rdi), %rdx + movq %rax, 360(%rdi) + adcq %rdx, %rdx + movq 376(%rdi), %rax + movq %rdx, 368(%rdi) + adcq %rax, %rax + movq %rax, 376(%rdi) + adcq $0, %rcx + leaq 256(%rsp), %rsi + movq %rsp, %r8 + movq (%r8), %rdx + subq (%rsi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rsi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rsi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rsi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rsi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rsi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rsi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rsi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rsi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rsi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rsi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rsi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rsi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rsi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rsi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rsi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rsi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rsi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rsi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rsi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rsi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rsi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rsi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rsi), %rax + movq 192(%r8), %rdx + movq %rax, 184(%r8) + sbbq 192(%rsi), %rdx + movq 200(%r8), %rax + movq %rdx, 192(%r8) + sbbq 200(%rsi), %rax + movq 208(%r8), %rdx + movq %rax, 200(%r8) + sbbq 208(%rsi), %rdx + movq 216(%r8), %rax + movq %rdx, 208(%r8) + sbbq 216(%rsi), %rax + movq 224(%r8), %rdx + movq %rax, 216(%r8) + sbbq 224(%rsi), %rdx + movq 232(%r8), %rax + movq %rdx, 224(%r8) + sbbq 232(%rsi), %rax + movq 240(%r8), %rdx + movq %rax, 232(%r8) + sbbq 240(%rsi), %rdx + movq 248(%r8), %rax + movq %rdx, 240(%r8) + sbbq 248(%rsi), %rax + movq %rax, 248(%r8) + sbbq $0, %rcx + movq (%r8), %rdx + subq (%rdi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rdi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rdi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rdi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rdi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rdi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rdi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rdi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rdi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rdi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rdi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rdi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rdi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rdi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rdi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rdi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rdi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rdi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rdi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rdi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rdi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rdi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rdi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rdi), %rax + movq 192(%r8), %rdx + movq %rax, 184(%r8) + sbbq 192(%rdi), %rdx + movq 200(%r8), %rax + movq %rdx, 192(%r8) + sbbq 200(%rdi), %rax + movq 208(%r8), %rdx + movq %rax, 200(%r8) + sbbq 208(%rdi), %rdx + movq 216(%r8), %rax + movq %rdx, 208(%r8) + sbbq 216(%rdi), %rax + movq 224(%r8), %rdx + movq %rax, 216(%r8) + sbbq 224(%rdi), %rdx + movq 232(%r8), %rax + movq %rdx, 224(%r8) + sbbq 232(%rdi), %rax + movq 240(%r8), %rdx + movq %rax, 232(%r8) + sbbq 240(%rdi), %rdx + movq 248(%r8), %rax + movq %rdx, 240(%r8) + sbbq 248(%rdi), %rax + movq %rax, 248(%r8) + sbbq $0, %rcx + # Add in place + movq 128(%rdi), %rdx + addq (%r8), %rdx + movq 136(%rdi), %rax + movq %rdx, 128(%rdi) + adcq 8(%r8), %rax + movq 144(%rdi), %rdx + movq %rax, 136(%rdi) + adcq 16(%r8), %rdx + movq 152(%rdi), %rax + movq %rdx, 144(%rdi) + adcq 24(%r8), %rax + movq 160(%rdi), %rdx + movq %rax, 152(%rdi) + adcq 32(%r8), %rdx + movq 168(%rdi), %rax + movq %rdx, 160(%rdi) + adcq 40(%r8), %rax + movq 176(%rdi), %rdx + movq %rax, 168(%rdi) + adcq 48(%r8), %rdx + movq 184(%rdi), %rax + movq %rdx, 176(%rdi) + adcq 56(%r8), %rax + movq 192(%rdi), %rdx + movq %rax, 184(%rdi) + adcq 64(%r8), %rdx + movq 200(%rdi), %rax + movq %rdx, 192(%rdi) + adcq 72(%r8), %rax + movq 208(%rdi), %rdx + movq %rax, 200(%rdi) + adcq 80(%r8), %rdx + movq 216(%rdi), %rax + movq %rdx, 208(%rdi) + adcq 88(%r8), %rax + movq 224(%rdi), %rdx + movq %rax, 216(%rdi) + adcq 96(%r8), %rdx + movq 232(%rdi), %rax + movq %rdx, 224(%rdi) + adcq 104(%r8), %rax + movq 240(%rdi), %rdx + movq %rax, 232(%rdi) + adcq 112(%r8), %rdx + movq 248(%rdi), %rax + movq %rdx, 240(%rdi) + adcq 120(%r8), %rax + movq 256(%rdi), %rdx + movq %rax, 248(%rdi) + adcq 128(%r8), %rdx + movq 264(%rdi), %rax + movq %rdx, 256(%rdi) + adcq 136(%r8), %rax + movq 272(%rdi), %rdx + movq %rax, 264(%rdi) + adcq 144(%r8), %rdx + movq 280(%rdi), %rax + movq %rdx, 272(%rdi) + adcq 152(%r8), %rax + movq 288(%rdi), %rdx + movq %rax, 280(%rdi) + adcq 160(%r8), %rdx + movq 296(%rdi), %rax + movq %rdx, 288(%rdi) + adcq 168(%r8), %rax + movq 304(%rdi), %rdx + movq %rax, 296(%rdi) + adcq 176(%r8), %rdx + movq 312(%rdi), %rax + movq %rdx, 304(%rdi) + adcq 184(%r8), %rax + movq 320(%rdi), %rdx + movq %rax, 312(%rdi) + adcq 192(%r8), %rdx + movq 328(%rdi), %rax + movq %rdx, 320(%rdi) + adcq 200(%r8), %rax + movq 336(%rdi), %rdx + movq %rax, 328(%rdi) + adcq 208(%r8), %rdx + movq 344(%rdi), %rax + movq %rdx, 336(%rdi) + adcq 216(%r8), %rax + movq 352(%rdi), %rdx + movq %rax, 344(%rdi) + adcq 224(%r8), %rdx + movq 360(%rdi), %rax + movq %rdx, 352(%rdi) + adcq 232(%r8), %rax + movq 368(%rdi), %rdx + movq %rax, 360(%rdi) + adcq 240(%r8), %rdx + movq 376(%rdi), %rax + movq %rdx, 368(%rdi) + adcq 248(%r8), %rax + movq %rax, 376(%rdi) + adcq $0, %rcx + movq %rcx, 384(%rdi) + # Add in place + movq 256(%rdi), %rdx + xorq %rcx, %rcx + addq (%rsi), %rdx + movq 264(%rdi), %rax + movq %rdx, 256(%rdi) + adcq 8(%rsi), %rax + movq 272(%rdi), %rdx + movq %rax, 264(%rdi) + adcq 16(%rsi), %rdx + movq 280(%rdi), %rax + movq %rdx, 272(%rdi) + adcq 24(%rsi), %rax + movq 288(%rdi), %rdx + movq %rax, 280(%rdi) + adcq 32(%rsi), %rdx + movq 296(%rdi), %rax + movq %rdx, 288(%rdi) + adcq 40(%rsi), %rax + movq 304(%rdi), %rdx + movq %rax, 296(%rdi) + adcq 48(%rsi), %rdx + movq 312(%rdi), %rax + movq %rdx, 304(%rdi) + adcq 56(%rsi), %rax + movq 320(%rdi), %rdx + movq %rax, 312(%rdi) + adcq 64(%rsi), %rdx + movq 328(%rdi), %rax + movq %rdx, 320(%rdi) + adcq 72(%rsi), %rax + movq 336(%rdi), %rdx + movq %rax, 328(%rdi) + adcq 80(%rsi), %rdx + movq 344(%rdi), %rax + movq %rdx, 336(%rdi) + adcq 88(%rsi), %rax + movq 352(%rdi), %rdx + movq %rax, 344(%rdi) + adcq 96(%rsi), %rdx + movq 360(%rdi), %rax + movq %rdx, 352(%rdi) + adcq 104(%rsi), %rax + movq 368(%rdi), %rdx + movq %rax, 360(%rdi) + adcq 112(%rsi), %rdx + movq 376(%rdi), %rax + movq %rdx, 368(%rdi) + adcq 120(%rsi), %rax + movq 384(%rdi), %rdx + movq %rax, 376(%rdi) + adcq 128(%rsi), %rdx + movq %rdx, 384(%rdi) + adcq $0, %rcx + # Add to zero + movq 136(%rsi), %rdx + adcq $0, %rdx + movq 144(%rsi), %rax + movq %rdx, 392(%rdi) + adcq $0, %rax + movq 152(%rsi), %rdx + movq %rax, 400(%rdi) + adcq $0, %rdx + movq 160(%rsi), %rax + movq %rdx, 408(%rdi) + adcq $0, %rax + movq 168(%rsi), %rdx + movq %rax, 416(%rdi) + adcq $0, %rdx + movq 176(%rsi), %rax + movq %rdx, 424(%rdi) + adcq $0, %rax + movq 184(%rsi), %rdx + movq %rax, 432(%rdi) + adcq $0, %rdx + movq 192(%rsi), %rax + movq %rdx, 440(%rdi) + adcq $0, %rax + movq 200(%rsi), %rdx + movq %rax, 448(%rdi) + adcq $0, %rdx + movq 208(%rsi), %rax + movq %rdx, 456(%rdi) + adcq $0, %rax + movq 216(%rsi), %rdx + movq %rax, 464(%rdi) + adcq $0, %rdx + movq 224(%rsi), %rax + movq %rdx, 472(%rdi) + adcq $0, %rax + movq 232(%rsi), %rdx + movq %rax, 480(%rdi) + adcq $0, %rdx + movq 240(%rsi), %rax + movq %rdx, 488(%rdi) + adcq $0, %rax + movq 248(%rsi), %rdx + movq %rax, 496(%rdi) + adcq $0, %rdx + movq %rdx, 504(%rdi) + addq $664, %rsp + repz retq +#ifndef __APPLE__ +.size sp_2048_sqr_32,.-sp_2048_sqr_32 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_avx2_32 +.type sp_2048_mul_avx2_32,@function +.align 16 +sp_2048_mul_avx2_32: +#else +.globl _sp_2048_mul_avx2_32 +.p2align 4 +_sp_2048_mul_avx2_32: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + subq $808, %rsp + movq %rdi, 768(%rsp) + movq %rsi, 776(%rsp) + movq %rdx, 784(%rsp) + leaq 512(%rsp), %r10 + leaq 128(%rsi), %r12 + # Add + movq (%rsi), %rax + xorq %r13, %r13 + addq (%r12), %rax + movq 8(%rsi), %rcx + movq %rax, (%r10) + adcq 8(%r12), %rcx + movq 16(%rsi), %r8 + movq %rcx, 8(%r10) + adcq 16(%r12), %r8 + movq 24(%rsi), %rax + movq %r8, 16(%r10) + adcq 24(%r12), %rax + movq 32(%rsi), %rcx + movq %rax, 24(%r10) + adcq 32(%r12), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%r10) + adcq 40(%r12), %r8 + movq 48(%rsi), %rax + movq %r8, 40(%r10) + adcq 48(%r12), %rax + movq 56(%rsi), %rcx + movq %rax, 48(%r10) + adcq 56(%r12), %rcx + movq 64(%rsi), %r8 + movq %rcx, 56(%r10) + adcq 64(%r12), %r8 + movq 72(%rsi), %rax + movq %r8, 64(%r10) + adcq 72(%r12), %rax + movq 80(%rsi), %rcx + movq %rax, 72(%r10) + adcq 80(%r12), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%r10) + adcq 88(%r12), %r8 + movq 96(%rsi), %rax + movq %r8, 88(%r10) + adcq 96(%r12), %rax + movq 104(%rsi), %rcx + movq %rax, 96(%r10) + adcq 104(%r12), %rcx + movq 112(%rsi), %r8 + movq %rcx, 104(%r10) + adcq 112(%r12), %r8 + movq 120(%rsi), %rax + movq %r8, 112(%r10) + adcq 120(%r12), %rax + movq %rax, 120(%r10) + adcq $0, %r13 + movq %r13, 792(%rsp) + leaq 640(%rsp), %r11 + leaq 128(%rdx), %r12 + # Add + movq (%rdx), %rax + xorq %r14, %r14 + addq (%r12), %rax + movq 8(%rdx), %rcx + movq %rax, (%r11) + adcq 8(%r12), %rcx + movq 16(%rdx), %r8 + movq %rcx, 8(%r11) + adcq 16(%r12), %r8 + movq 24(%rdx), %rax + movq %r8, 16(%r11) + adcq 24(%r12), %rax + movq 32(%rdx), %rcx + movq %rax, 24(%r11) + adcq 32(%r12), %rcx + movq 40(%rdx), %r8 + movq %rcx, 32(%r11) + adcq 40(%r12), %r8 + movq 48(%rdx), %rax + movq %r8, 40(%r11) + adcq 48(%r12), %rax + movq 56(%rdx), %rcx + movq %rax, 48(%r11) + adcq 56(%r12), %rcx + movq 64(%rdx), %r8 + movq %rcx, 56(%r11) + adcq 64(%r12), %r8 + movq 72(%rdx), %rax + movq %r8, 64(%r11) + adcq 72(%r12), %rax + movq 80(%rdx), %rcx + movq %rax, 72(%r11) + adcq 80(%r12), %rcx + movq 88(%rdx), %r8 + movq %rcx, 80(%r11) + adcq 88(%r12), %r8 + movq 96(%rdx), %rax + movq %r8, 88(%r11) + adcq 96(%r12), %rax + movq 104(%rdx), %rcx + movq %rax, 96(%r11) + adcq 104(%r12), %rcx + movq 112(%rdx), %r8 + movq %rcx, 104(%r11) + adcq 112(%r12), %r8 + movq 120(%rdx), %rax + movq %r8, 112(%r11) + adcq 120(%r12), %rax + movq %rax, 120(%r11) + adcq $0, %r14 + movq %r14, 800(%rsp) + movq %r11, %rdx + movq %r10, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_2048_mul_avx2_16@plt +#else + callq _sp_2048_mul_avx2_16 +#endif /* __APPLE__ */ + movq 784(%rsp), %rdx + movq 776(%rsp), %rsi + leaq 256(%rsp), %rdi + addq $128, %rdx + addq $128, %rsi +#ifndef __APPLE__ + callq sp_2048_mul_avx2_16@plt +#else + callq _sp_2048_mul_avx2_16 +#endif /* __APPLE__ */ + movq 784(%rsp), %rdx + movq 776(%rsp), %rsi + movq 768(%rsp), %rdi +#ifndef __APPLE__ + callq sp_2048_mul_avx2_16@plt +#else + callq _sp_2048_mul_avx2_16 +#endif /* __APPLE__ */ + movq 792(%rsp), %r13 + movq 800(%rsp), %r14 + movq 768(%rsp), %r15 + movq %r13, %r9 + leaq 512(%rsp), %r10 + leaq 640(%rsp), %r11 + andq %r14, %r9 + negq %r13 + negq %r14 + addq $256, %r15 + movq (%r10), %rax + movq (%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + addq %rcx, %rax + movq 8(%r10), %rcx + movq 8(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, (%r15) + adcq %r8, %rcx + movq 16(%r10), %r8 + movq 16(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 8(%r15) + adcq %rax, %r8 + movq 24(%r10), %rax + movq 24(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 16(%r15) + adcq %rcx, %rax + movq 32(%r10), %rcx + movq 32(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 24(%r15) + adcq %r8, %rcx + movq 40(%r10), %r8 + movq 40(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 32(%r15) + adcq %rax, %r8 + movq 48(%r10), %rax + movq 48(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 40(%r15) + adcq %rcx, %rax + movq 56(%r10), %rcx + movq 56(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 48(%r15) + adcq %r8, %rcx + movq 64(%r10), %r8 + movq 64(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 56(%r15) + adcq %rax, %r8 + movq 72(%r10), %rax + movq 72(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 64(%r15) + adcq %rcx, %rax + movq 80(%r10), %rcx + movq 80(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 72(%r15) + adcq %r8, %rcx + movq 88(%r10), %r8 + movq 88(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 80(%r15) + adcq %rax, %r8 + movq 96(%r10), %rax + movq 96(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 88(%r15) + adcq %rcx, %rax + movq 104(%r10), %rcx + movq 104(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 96(%r15) + adcq %r8, %rcx + movq 112(%r10), %r8 + movq 112(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 104(%r15) + adcq %rax, %r8 + movq 120(%r10), %rax + movq 120(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 112(%r15) + adcq %rcx, %rax + movq %rax, 120(%r15) + adcq $0, %r9 + leaq 256(%rsp), %r11 + movq %rsp, %r10 + movq (%r10), %rax + subq (%r11), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%r11), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%r11), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%r11), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%r11), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%r11), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%r11), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%r11), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%r11), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%r11), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%r11), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%r11), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%r11), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%r11), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%r11), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%r11), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%r11), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%r11), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%r11), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%r11), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%r11), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%r11), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%r11), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%r11), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r10) + sbbq 192(%r11), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r10) + sbbq 200(%r11), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r10) + sbbq 208(%r11), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r10) + sbbq 216(%r11), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r10) + sbbq 224(%r11), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r10) + sbbq 232(%r11), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r10) + sbbq 240(%r11), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r10) + sbbq 248(%r11), %rcx + movq %rcx, 248(%r10) + sbbq $0, %r9 + movq (%r10), %rax + subq (%rdi), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%rdi), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%rdi), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%rdi), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%rdi), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%rdi), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%rdi), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%rdi), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%rdi), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%rdi), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%rdi), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%rdi), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%rdi), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%rdi), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%rdi), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%rdi), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%rdi), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%rdi), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%rdi), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%rdi), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%rdi), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%rdi), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%rdi), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%rdi), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r10) + sbbq 192(%rdi), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r10) + sbbq 200(%rdi), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r10) + sbbq 208(%rdi), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r10) + sbbq 216(%rdi), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r10) + sbbq 224(%rdi), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r10) + sbbq 232(%rdi), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r10) + sbbq 240(%rdi), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r10) + sbbq 248(%rdi), %rcx + movq %rcx, 248(%r10) + sbbq $0, %r9 + subq $128, %r15 + # Add + movq (%r15), %rax + addq (%r10), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r10), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r10), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r10), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r10), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r10), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r10), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r10), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r10), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r10), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r10), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r10), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r10), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r10), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r10), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r10), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r10), %rcx + movq 136(%r15), %r8 + movq %rcx, 128(%r15) + adcq 136(%r10), %r8 + movq 144(%r15), %rax + movq %r8, 136(%r15) + adcq 144(%r10), %rax + movq 152(%r15), %rcx + movq %rax, 144(%r15) + adcq 152(%r10), %rcx + movq 160(%r15), %r8 + movq %rcx, 152(%r15) + adcq 160(%r10), %r8 + movq 168(%r15), %rax + movq %r8, 160(%r15) + adcq 168(%r10), %rax + movq 176(%r15), %rcx + movq %rax, 168(%r15) + adcq 176(%r10), %rcx + movq 184(%r15), %r8 + movq %rcx, 176(%r15) + adcq 184(%r10), %r8 + movq 192(%r15), %rax + movq %r8, 184(%r15) + adcq 192(%r10), %rax + movq 200(%r15), %rcx + movq %rax, 192(%r15) + adcq 200(%r10), %rcx + movq 208(%r15), %r8 + movq %rcx, 200(%r15) + adcq 208(%r10), %r8 + movq 216(%r15), %rax + movq %r8, 208(%r15) + adcq 216(%r10), %rax + movq 224(%r15), %rcx + movq %rax, 216(%r15) + adcq 224(%r10), %rcx + movq 232(%r15), %r8 + movq %rcx, 224(%r15) + adcq 232(%r10), %r8 + movq 240(%r15), %rax + movq %r8, 232(%r15) + adcq 240(%r10), %rax + movq 248(%r15), %rcx + movq %rax, 240(%r15) + adcq 248(%r10), %rcx + movq %rcx, 248(%r15) + adcq $0, %r9 + movq %r9, 384(%rdi) + addq $128, %r15 + # Add + movq (%r15), %rax + xorq %r9, %r9 + addq (%r11), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r11), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r11), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r11), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r11), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r11), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r11), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r11), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r11), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r11), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r11), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r11), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r11), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r11), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r11), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r11), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r11), %rcx + movq %rcx, 128(%r15) + adcq $0, %r9 + # Add to zero + movq 136(%r11), %rax + adcq $0, %rax + movq 144(%r11), %rcx + movq %rax, 136(%r15) + adcq $0, %rcx + movq 152(%r11), %r8 + movq %rcx, 144(%r15) + adcq $0, %r8 + movq 160(%r11), %rax + movq %r8, 152(%r15) + adcq $0, %rax + movq 168(%r11), %rcx + movq %rax, 160(%r15) + adcq $0, %rcx + movq 176(%r11), %r8 + movq %rcx, 168(%r15) + adcq $0, %r8 + movq 184(%r11), %rax + movq %r8, 176(%r15) + adcq $0, %rax + movq 192(%r11), %rcx + movq %rax, 184(%r15) + adcq $0, %rcx + movq 200(%r11), %r8 + movq %rcx, 192(%r15) + adcq $0, %r8 + movq 208(%r11), %rax + movq %r8, 200(%r15) + adcq $0, %rax + movq 216(%r11), %rcx + movq %rax, 208(%r15) + adcq $0, %rcx + movq 224(%r11), %r8 + movq %rcx, 216(%r15) + adcq $0, %r8 + movq 232(%r11), %rax + movq %r8, 224(%r15) + adcq $0, %rax + movq 240(%r11), %rcx + movq %rax, 232(%r15) + adcq $0, %rcx + movq 248(%r11), %r8 + movq %rcx, 240(%r15) + adcq $0, %r8 + movq %r8, 248(%r15) + addq $808, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_avx2_32,.-sp_2048_mul_avx2_32 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_sqr_avx2_32 +.type sp_2048_sqr_avx2_32,@function +.align 16 +sp_2048_sqr_avx2_32: +#else +.globl _sp_2048_sqr_avx2_32 +.p2align 4 +_sp_2048_sqr_avx2_32: +#endif /* __APPLE__ */ + subq $664, %rsp + movq %rdi, 640(%rsp) + movq %rsi, 648(%rsp) + leaq 512(%rsp), %r8 + leaq 128(%rsi), %r9 + # Add + movq (%rsi), %rdx + xorq %rcx, %rcx + addq (%r9), %rdx + movq 8(%rsi), %rax + movq %rdx, (%r8) + adcq 8(%r9), %rax + movq 16(%rsi), %rdx + movq %rax, 8(%r8) + adcq 16(%r9), %rdx + movq 24(%rsi), %rax + movq %rdx, 16(%r8) + adcq 24(%r9), %rax + movq 32(%rsi), %rdx + movq %rax, 24(%r8) + adcq 32(%r9), %rdx + movq 40(%rsi), %rax + movq %rdx, 32(%r8) + adcq 40(%r9), %rax + movq 48(%rsi), %rdx + movq %rax, 40(%r8) + adcq 48(%r9), %rdx + movq 56(%rsi), %rax + movq %rdx, 48(%r8) + adcq 56(%r9), %rax + movq 64(%rsi), %rdx + movq %rax, 56(%r8) + adcq 64(%r9), %rdx + movq 72(%rsi), %rax + movq %rdx, 64(%r8) + adcq 72(%r9), %rax + movq 80(%rsi), %rdx + movq %rax, 72(%r8) + adcq 80(%r9), %rdx + movq 88(%rsi), %rax + movq %rdx, 80(%r8) + adcq 88(%r9), %rax + movq 96(%rsi), %rdx + movq %rax, 88(%r8) + adcq 96(%r9), %rdx + movq 104(%rsi), %rax + movq %rdx, 96(%r8) + adcq 104(%r9), %rax + movq 112(%rsi), %rdx + movq %rax, 104(%r8) + adcq 112(%r9), %rdx + movq 120(%rsi), %rax + movq %rdx, 112(%r8) + adcq 120(%r9), %rax + movq %rax, 120(%r8) + adcq $0, %rcx + movq %rcx, 656(%rsp) + movq %r8, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_2048_sqr_avx2_16@plt +#else + callq _sp_2048_sqr_avx2_16 +#endif /* __APPLE__ */ + movq 648(%rsp), %rsi + leaq 256(%rsp), %rdi + addq $128, %rsi +#ifndef __APPLE__ + callq sp_2048_sqr_avx2_16@plt +#else + callq _sp_2048_sqr_avx2_16 +#endif /* __APPLE__ */ + movq 648(%rsp), %rsi + movq 640(%rsp), %rdi +#ifndef __APPLE__ + callq sp_2048_sqr_avx2_16@plt +#else + callq _sp_2048_sqr_avx2_16 +#endif /* __APPLE__ */ + movq 656(%rsp), %r10 + leaq 512(%rsp), %r8 + movq %r10, %rcx + negq %r10 + movq (%r8), %rdx + pextq %r10, %rdx, %rdx + addq %rdx, %rdx + movq 8(%r8), %rax + movq %rdx, 256(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 16(%r8), %rdx + movq %rax, 264(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 24(%r8), %rax + movq %rdx, 272(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 32(%r8), %rdx + movq %rax, 280(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 40(%r8), %rax + movq %rdx, 288(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 48(%r8), %rdx + movq %rax, 296(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 56(%r8), %rax + movq %rdx, 304(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 64(%r8), %rdx + movq %rax, 312(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 72(%r8), %rax + movq %rdx, 320(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 80(%r8), %rdx + movq %rax, 328(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 88(%r8), %rax + movq %rdx, 336(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 96(%r8), %rdx + movq %rax, 344(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 104(%r8), %rax + movq %rdx, 352(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 112(%r8), %rdx + movq %rax, 360(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 120(%r8), %rax + movq %rdx, 368(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq %rax, 376(%rdi) + adcq $0, %rcx + leaq 256(%rsp), %rsi + movq %rsp, %r8 + movq (%r8), %rdx + subq (%rsi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rsi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rsi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rsi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rsi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rsi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rsi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rsi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rsi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rsi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rsi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rsi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rsi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rsi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rsi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rsi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rsi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rsi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rsi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rsi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rsi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rsi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rsi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rsi), %rax + movq 192(%r8), %rdx + movq %rax, 184(%r8) + sbbq 192(%rsi), %rdx + movq 200(%r8), %rax + movq %rdx, 192(%r8) + sbbq 200(%rsi), %rax + movq 208(%r8), %rdx + movq %rax, 200(%r8) + sbbq 208(%rsi), %rdx + movq 216(%r8), %rax + movq %rdx, 208(%r8) + sbbq 216(%rsi), %rax + movq 224(%r8), %rdx + movq %rax, 216(%r8) + sbbq 224(%rsi), %rdx + movq 232(%r8), %rax + movq %rdx, 224(%r8) + sbbq 232(%rsi), %rax + movq 240(%r8), %rdx + movq %rax, 232(%r8) + sbbq 240(%rsi), %rdx + movq 248(%r8), %rax + movq %rdx, 240(%r8) + sbbq 248(%rsi), %rax + movq %rax, 248(%r8) + sbbq $0, %rcx + movq (%r8), %rdx + subq (%rdi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rdi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rdi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rdi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rdi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rdi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rdi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rdi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rdi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rdi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rdi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rdi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rdi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rdi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rdi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rdi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rdi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rdi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rdi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rdi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rdi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rdi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rdi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rdi), %rax + movq 192(%r8), %rdx + movq %rax, 184(%r8) + sbbq 192(%rdi), %rdx + movq 200(%r8), %rax + movq %rdx, 192(%r8) + sbbq 200(%rdi), %rax + movq 208(%r8), %rdx + movq %rax, 200(%r8) + sbbq 208(%rdi), %rdx + movq 216(%r8), %rax + movq %rdx, 208(%r8) + sbbq 216(%rdi), %rax + movq 224(%r8), %rdx + movq %rax, 216(%r8) + sbbq 224(%rdi), %rdx + movq 232(%r8), %rax + movq %rdx, 224(%r8) + sbbq 232(%rdi), %rax + movq 240(%r8), %rdx + movq %rax, 232(%r8) + sbbq 240(%rdi), %rdx + movq 248(%r8), %rax + movq %rdx, 240(%r8) + sbbq 248(%rdi), %rax + movq %rax, 248(%r8) + sbbq $0, %rcx + # Add in place + movq 128(%rdi), %rdx + addq (%r8), %rdx + movq 136(%rdi), %rax + movq %rdx, 128(%rdi) + adcq 8(%r8), %rax + movq 144(%rdi), %rdx + movq %rax, 136(%rdi) + adcq 16(%r8), %rdx + movq 152(%rdi), %rax + movq %rdx, 144(%rdi) + adcq 24(%r8), %rax + movq 160(%rdi), %rdx + movq %rax, 152(%rdi) + adcq 32(%r8), %rdx + movq 168(%rdi), %rax + movq %rdx, 160(%rdi) + adcq 40(%r8), %rax + movq 176(%rdi), %rdx + movq %rax, 168(%rdi) + adcq 48(%r8), %rdx + movq 184(%rdi), %rax + movq %rdx, 176(%rdi) + adcq 56(%r8), %rax + movq 192(%rdi), %rdx + movq %rax, 184(%rdi) + adcq 64(%r8), %rdx + movq 200(%rdi), %rax + movq %rdx, 192(%rdi) + adcq 72(%r8), %rax + movq 208(%rdi), %rdx + movq %rax, 200(%rdi) + adcq 80(%r8), %rdx + movq 216(%rdi), %rax + movq %rdx, 208(%rdi) + adcq 88(%r8), %rax + movq 224(%rdi), %rdx + movq %rax, 216(%rdi) + adcq 96(%r8), %rdx + movq 232(%rdi), %rax + movq %rdx, 224(%rdi) + adcq 104(%r8), %rax + movq 240(%rdi), %rdx + movq %rax, 232(%rdi) + adcq 112(%r8), %rdx + movq 248(%rdi), %rax + movq %rdx, 240(%rdi) + adcq 120(%r8), %rax + movq 256(%rdi), %rdx + movq %rax, 248(%rdi) + adcq 128(%r8), %rdx + movq 264(%rdi), %rax + movq %rdx, 256(%rdi) + adcq 136(%r8), %rax + movq 272(%rdi), %rdx + movq %rax, 264(%rdi) + adcq 144(%r8), %rdx + movq 280(%rdi), %rax + movq %rdx, 272(%rdi) + adcq 152(%r8), %rax + movq 288(%rdi), %rdx + movq %rax, 280(%rdi) + adcq 160(%r8), %rdx + movq 296(%rdi), %rax + movq %rdx, 288(%rdi) + adcq 168(%r8), %rax + movq 304(%rdi), %rdx + movq %rax, 296(%rdi) + adcq 176(%r8), %rdx + movq 312(%rdi), %rax + movq %rdx, 304(%rdi) + adcq 184(%r8), %rax + movq 320(%rdi), %rdx + movq %rax, 312(%rdi) + adcq 192(%r8), %rdx + movq 328(%rdi), %rax + movq %rdx, 320(%rdi) + adcq 200(%r8), %rax + movq 336(%rdi), %rdx + movq %rax, 328(%rdi) + adcq 208(%r8), %rdx + movq 344(%rdi), %rax + movq %rdx, 336(%rdi) + adcq 216(%r8), %rax + movq 352(%rdi), %rdx + movq %rax, 344(%rdi) + adcq 224(%r8), %rdx + movq 360(%rdi), %rax + movq %rdx, 352(%rdi) + adcq 232(%r8), %rax + movq 368(%rdi), %rdx + movq %rax, 360(%rdi) + adcq 240(%r8), %rdx + movq 376(%rdi), %rax + movq %rdx, 368(%rdi) + adcq 248(%r8), %rax + movq %rax, 376(%rdi) + adcq $0, %rcx + movq %rcx, 384(%rdi) + # Add in place + movq 256(%rdi), %rdx + xorq %rcx, %rcx + addq (%rsi), %rdx + movq 264(%rdi), %rax + movq %rdx, 256(%rdi) + adcq 8(%rsi), %rax + movq 272(%rdi), %rdx + movq %rax, 264(%rdi) + adcq 16(%rsi), %rdx + movq 280(%rdi), %rax + movq %rdx, 272(%rdi) + adcq 24(%rsi), %rax + movq 288(%rdi), %rdx + movq %rax, 280(%rdi) + adcq 32(%rsi), %rdx + movq 296(%rdi), %rax + movq %rdx, 288(%rdi) + adcq 40(%rsi), %rax + movq 304(%rdi), %rdx + movq %rax, 296(%rdi) + adcq 48(%rsi), %rdx + movq 312(%rdi), %rax + movq %rdx, 304(%rdi) + adcq 56(%rsi), %rax + movq 320(%rdi), %rdx + movq %rax, 312(%rdi) + adcq 64(%rsi), %rdx + movq 328(%rdi), %rax + movq %rdx, 320(%rdi) + adcq 72(%rsi), %rax + movq 336(%rdi), %rdx + movq %rax, 328(%rdi) + adcq 80(%rsi), %rdx + movq 344(%rdi), %rax + movq %rdx, 336(%rdi) + adcq 88(%rsi), %rax + movq 352(%rdi), %rdx + movq %rax, 344(%rdi) + adcq 96(%rsi), %rdx + movq 360(%rdi), %rax + movq %rdx, 352(%rdi) + adcq 104(%rsi), %rax + movq 368(%rdi), %rdx + movq %rax, 360(%rdi) + adcq 112(%rsi), %rdx + movq 376(%rdi), %rax + movq %rdx, 368(%rdi) + adcq 120(%rsi), %rax + movq 384(%rdi), %rdx + movq %rax, 376(%rdi) + adcq 128(%rsi), %rdx + movq %rdx, 384(%rdi) + adcq $0, %rcx + # Add to zero + movq 136(%rsi), %rdx + adcq $0, %rdx + movq 144(%rsi), %rax + movq %rdx, 392(%rdi) + adcq $0, %rax + movq 152(%rsi), %rdx + movq %rax, 400(%rdi) + adcq $0, %rdx + movq 160(%rsi), %rax + movq %rdx, 408(%rdi) + adcq $0, %rax + movq 168(%rsi), %rdx + movq %rax, 416(%rdi) + adcq $0, %rdx + movq 176(%rsi), %rax + movq %rdx, 424(%rdi) + adcq $0, %rax + movq 184(%rsi), %rdx + movq %rax, 432(%rdi) + adcq $0, %rdx + movq 192(%rsi), %rax + movq %rdx, 440(%rdi) + adcq $0, %rax + movq 200(%rsi), %rdx + movq %rax, 448(%rdi) + adcq $0, %rdx + movq 208(%rsi), %rax + movq %rdx, 456(%rdi) + adcq $0, %rax + movq 216(%rsi), %rdx + movq %rax, 464(%rdi) + adcq $0, %rdx + movq 224(%rsi), %rax + movq %rdx, 472(%rdi) + adcq $0, %rax + movq 232(%rsi), %rdx + movq %rax, 480(%rdi) + adcq $0, %rdx + movq 240(%rsi), %rax + movq %rdx, 488(%rdi) + adcq $0, %rax + movq 248(%rsi), %rdx + movq %rax, 496(%rdi) + adcq $0, %rdx + movq %rdx, 504(%rdi) + addq $664, %rsp + repz retq +#ifndef __APPLE__ +.size sp_2048_sqr_avx2_32,.-sp_2048_sqr_avx2_32 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_d_32 +.type sp_2048_mul_d_32,@function +.align 16 +sp_2048_mul_d_32: +#else +.globl _sp_2048_mul_d_32 +.p2align 4 +_sp_2048_mul_d_32: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 24(%rsi) + addq %rax, %r8 + movq %r8, 24(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 32(%rsi) + addq %rax, %r9 + movq %r9, 32(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 40(%rsi) + addq %rax, %r10 + movq %r10, 40(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 48(%rsi) + addq %rax, %r8 + movq %r8, 48(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 56(%rsi) + addq %rax, %r9 + movq %r9, 56(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 64(%rsi) + addq %rax, %r10 + movq %r10, 64(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 72(%rsi) + addq %rax, %r8 + movq %r8, 72(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 80(%rsi) + addq %rax, %r9 + movq %r9, 80(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 88(%rsi) + addq %rax, %r10 + movq %r10, 88(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 96(%rsi) + addq %rax, %r8 + movq %r8, 96(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 104(%rsi) + addq %rax, %r9 + movq %r9, 104(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 112(%rsi) + addq %rax, %r10 + movq %r10, 112(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 120(%rsi) + addq %rax, %r8 + movq %r8, 120(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 128(%rsi) + addq %rax, %r9 + movq %r9, 128(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 136(%rsi) + addq %rax, %r10 + movq %r10, 136(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 144(%rsi) + addq %rax, %r8 + movq %r8, 144(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 152(%rsi) + addq %rax, %r9 + movq %r9, 152(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 160(%rsi) + addq %rax, %r10 + movq %r10, 160(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 168(%rsi) + addq %rax, %r8 + movq %r8, 168(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 176(%rsi) + addq %rax, %r9 + movq %r9, 176(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 184(%rsi) + addq %rax, %r10 + movq %r10, 184(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[24] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 192(%rsi) + addq %rax, %r8 + movq %r8, 192(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[25] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 200(%rsi) + addq %rax, %r9 + movq %r9, 200(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[26] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 208(%rsi) + addq %rax, %r10 + movq %r10, 208(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[27] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 216(%rsi) + addq %rax, %r8 + movq %r8, 216(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[28] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 224(%rsi) + addq %rax, %r9 + movq %r9, 224(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[29] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 232(%rsi) + addq %rax, %r10 + movq %r10, 232(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[30] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 240(%rsi) + addq %rax, %r8 + movq %r8, 240(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[31] * B + movq %rcx, %rax + mulq 248(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + movq %r9, 248(%rdi) + movq %r10, 256(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_d_32,.-sp_2048_mul_d_32 +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_sub_in_place_16 +.type sp_2048_sub_in_place_16,@function +.align 16 +sp_2048_sub_in_place_16: +#else +.globl _sp_2048_sub_in_place_16 +.p2align 4 +_sp_2048_sub_in_place_16: +#endif /* __APPLE__ */ + movq (%rdi), %rdx + xorq %rax, %rax + subq (%rsi), %rdx + movq 8(%rdi), %rcx + movq %rdx, (%rdi) + sbbq 8(%rsi), %rcx + movq 16(%rdi), %rdx + movq %rcx, 8(%rdi) + sbbq 16(%rsi), %rdx + movq 24(%rdi), %rcx + movq %rdx, 16(%rdi) + sbbq 24(%rsi), %rcx + movq 32(%rdi), %rdx + movq %rcx, 24(%rdi) + sbbq 32(%rsi), %rdx + movq 40(%rdi), %rcx + movq %rdx, 32(%rdi) + sbbq 40(%rsi), %rcx + movq 48(%rdi), %rdx + movq %rcx, 40(%rdi) + sbbq 48(%rsi), %rdx + movq 56(%rdi), %rcx + movq %rdx, 48(%rdi) + sbbq 56(%rsi), %rcx + movq 64(%rdi), %rdx + movq %rcx, 56(%rdi) + sbbq 64(%rsi), %rdx + movq 72(%rdi), %rcx + movq %rdx, 64(%rdi) + sbbq 72(%rsi), %rcx + movq 80(%rdi), %rdx + movq %rcx, 72(%rdi) + sbbq 80(%rsi), %rdx + movq 88(%rdi), %rcx + movq %rdx, 80(%rdi) + sbbq 88(%rsi), %rcx + movq 96(%rdi), %rdx + movq %rcx, 88(%rdi) + sbbq 96(%rsi), %rdx + movq 104(%rdi), %rcx + movq %rdx, 96(%rdi) + sbbq 104(%rsi), %rcx + movq 112(%rdi), %rdx + movq %rcx, 104(%rdi) + sbbq 112(%rsi), %rdx + movq 120(%rdi), %rcx + movq %rdx, 112(%rdi) + sbbq 120(%rsi), %rcx + movq %rcx, 120(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_sub_in_place_16,.-sp_2048_sub_in_place_16 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_cond_sub_16 +.type sp_2048_cond_sub_16,@function +.align 16 +sp_2048_cond_sub_16: +#else +.globl _sp_2048_cond_sub_16 +.p2align 4 +_sp_2048_cond_sub_16: +#endif /* __APPLE__ */ + subq $128, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + subq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + sbbq $0, %rax + addq $128, %rsp + repz retq +#ifndef __APPLE__ +.size sp_2048_cond_sub_16,.-sp_2048_cond_sub_16 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_mont_reduce_16 +.type sp_2048_mont_reduce_16,@function +.align 16 +sp_2048_mont_reduce_16: +#else +.globl _sp_2048_mont_reduce_16 +.p2align 4 +_sp_2048_mont_reduce_16: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rcx + xorq %r15, %r15 + # i = 16 + movq $16, %r8 + movq (%rdi), %r13 + movq 8(%rdi), %r14 +L_mont_loop_16: + # mu = a[i] * mp + movq %r13, %r11 + imulq %rcx, %r11 + # a[i+0] += m[0] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq (%rsi) + addq %rax, %r13 + adcq %rdx, %r10 + # a[i+1] += m[1] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 8(%rsi) + movq %r14, %r13 + addq %rax, %r13 + adcq %rdx, %r9 + addq %r10, %r13 + adcq $0, %r9 + # a[i+2] += m[2] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 16(%rsi) + movq 16(%rdi), %r14 + addq %rax, %r14 + adcq %rdx, %r10 + addq %r9, %r14 + adcq $0, %r10 + # a[i+3] += m[3] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 24(%rsi) + movq 24(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 24(%rdi) + adcq $0, %r9 + # a[i+4] += m[4] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 32(%rsi) + movq 32(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 32(%rdi) + adcq $0, %r10 + # a[i+5] += m[5] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 40(%rsi) + movq 40(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 40(%rdi) + adcq $0, %r9 + # a[i+6] += m[6] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 48(%rsi) + movq 48(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 48(%rdi) + adcq $0, %r10 + # a[i+7] += m[7] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 56(%rsi) + movq 56(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 56(%rdi) + adcq $0, %r9 + # a[i+8] += m[8] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 64(%rsi) + movq 64(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 64(%rdi) + adcq $0, %r10 + # a[i+9] += m[9] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 72(%rsi) + movq 72(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 72(%rdi) + adcq $0, %r9 + # a[i+10] += m[10] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 80(%rsi) + movq 80(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 80(%rdi) + adcq $0, %r10 + # a[i+11] += m[11] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 88(%rsi) + movq 88(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 88(%rdi) + adcq $0, %r9 + # a[i+12] += m[12] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 96(%rsi) + movq 96(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 96(%rdi) + adcq $0, %r10 + # a[i+13] += m[13] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 104(%rsi) + movq 104(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 104(%rdi) + adcq $0, %r9 + # a[i+14] += m[14] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 112(%rsi) + movq 112(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 112(%rdi) + adcq $0, %r10 + # a[i+15] += m[15] * mu + movq %r11, %rax + mulq 120(%rsi) + movq 120(%rdi), %r12 + addq %rax, %r10 + adcq %r15, %rdx + movq $0, %r15 + adcq $0, %r15 + addq %r10, %r12 + movq %r12, 120(%rdi) + adcq %rdx, 128(%rdi) + adcq $0, %r15 + # i -= 1 + addq $8, %rdi + decq %r8 + jnz L_mont_loop_16 + movq %r13, (%rdi) + movq %r14, 8(%rdi) + negq %r15 + movq %r15, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + subq $128, %rdi +#ifndef __APPLE__ + callq sp_2048_cond_sub_16@plt +#else + callq _sp_2048_cond_sub_16 +#endif /* __APPLE__ */ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_2048_mont_reduce_16,.-sp_2048_mont_reduce_16 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_cond_sub_avx2_16 +.type sp_2048_cond_sub_avx2_16,@function +.align 16 +sp_2048_cond_sub_avx2_16: +#else +.globl _sp_2048_cond_sub_avx2_16 +.p2align 4 +_sp_2048_cond_sub_avx2_16: +#endif /* __APPLE__ */ + movq $0, %rax + movq (%rdx), %r10 + movq (%rsi), %r8 + pextq %rcx, %r10, %r10 + subq %r10, %r8 + movq 8(%rdx), %r10 + movq 8(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, (%rdi) + sbbq %r10, %r9 + movq 16(%rdx), %r8 + movq 16(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 8(%rdi) + sbbq %r8, %r10 + movq 24(%rdx), %r9 + movq 24(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 16(%rdi) + sbbq %r9, %r8 + movq 32(%rdx), %r10 + movq 32(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 24(%rdi) + sbbq %r10, %r9 + movq 40(%rdx), %r8 + movq 40(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 32(%rdi) + sbbq %r8, %r10 + movq 48(%rdx), %r9 + movq 48(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 40(%rdi) + sbbq %r9, %r8 + movq 56(%rdx), %r10 + movq 56(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 48(%rdi) + sbbq %r10, %r9 + movq 64(%rdx), %r8 + movq 64(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 56(%rdi) + sbbq %r8, %r10 + movq 72(%rdx), %r9 + movq 72(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 64(%rdi) + sbbq %r9, %r8 + movq 80(%rdx), %r10 + movq 80(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 72(%rdi) + sbbq %r10, %r9 + movq 88(%rdx), %r8 + movq 88(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 80(%rdi) + sbbq %r8, %r10 + movq 96(%rdx), %r9 + movq 96(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 88(%rdi) + sbbq %r9, %r8 + movq 104(%rdx), %r10 + movq 104(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 96(%rdi) + sbbq %r10, %r9 + movq 112(%rdx), %r8 + movq 112(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 104(%rdi) + sbbq %r8, %r10 + movq 120(%rdx), %r9 + movq 120(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 112(%rdi) + sbbq %r9, %r8 + movq %r8, 120(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_cond_sub_avx2_16,.-sp_2048_cond_sub_avx2_16 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_d_16 +.type sp_2048_mul_d_16,@function +.align 16 +sp_2048_mul_d_16: +#else +.globl _sp_2048_mul_d_16 +.p2align 4 +_sp_2048_mul_d_16: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 24(%rsi) + addq %rax, %r8 + movq %r8, 24(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 32(%rsi) + addq %rax, %r9 + movq %r9, 32(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 40(%rsi) + addq %rax, %r10 + movq %r10, 40(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 48(%rsi) + addq %rax, %r8 + movq %r8, 48(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 56(%rsi) + addq %rax, %r9 + movq %r9, 56(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 64(%rsi) + addq %rax, %r10 + movq %r10, 64(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 72(%rsi) + addq %rax, %r8 + movq %r8, 72(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 80(%rsi) + addq %rax, %r9 + movq %r9, 80(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 88(%rsi) + addq %rax, %r10 + movq %r10, 88(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 96(%rsi) + addq %rax, %r8 + movq %r8, 96(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 104(%rsi) + addq %rax, %r9 + movq %r9, 104(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 112(%rsi) + addq %rax, %r10 + movq %r10, 112(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B + movq %rcx, %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 120(%rdi) + movq %r9, 128(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_d_16,.-sp_2048_mul_d_16 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_d_avx2_16 +.type sp_2048_mul_d_avx2_16,@function +.align 16 +sp_2048_mul_d_avx2_16: +#else +.globl _sp_2048_mul_d_avx2_16 +.p2align 4 +_sp_2048_mul_d_avx2_16: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 8(%rdi) + adoxq %r8, %r9 + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 16(%rdi) + adoxq %r8, %r10 + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 24(%rdi) + adoxq %r8, %r9 + # A[4] * B + mulxq 32(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 32(%rdi) + adoxq %r8, %r10 + # A[5] * B + mulxq 40(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 40(%rdi) + adoxq %r8, %r9 + # A[6] * B + mulxq 48(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 48(%rdi) + adoxq %r8, %r10 + # A[7] * B + mulxq 56(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 56(%rdi) + adoxq %r8, %r9 + # A[8] * B + mulxq 64(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 64(%rdi) + adoxq %r8, %r10 + # A[9] * B + mulxq 72(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 72(%rdi) + adoxq %r8, %r9 + # A[10] * B + mulxq 80(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 80(%rdi) + adoxq %r8, %r10 + # A[11] * B + mulxq 88(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 88(%rdi) + adoxq %r8, %r9 + # A[12] * B + mulxq 96(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 96(%rdi) + adoxq %r8, %r10 + # A[13] * B + mulxq 104(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 104(%rdi) + adoxq %r8, %r9 + # A[14] * B + mulxq 112(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 112(%rdi) + adoxq %r8, %r10 + # A[15] * B + mulxq 120(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 120(%rdi) + movq %r9, 128(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_d_avx2_16,.-sp_2048_mul_d_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_cmp_16 +.type sp_2048_cmp_16,@function +.align 16 +sp_2048_cmp_16: +#else +.globl _sp_2048_cmp_16 +.p2align 4 +_sp_2048_cmp_16: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $1, %r8 + movq 120(%rdi), %r9 + movq 120(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 112(%rdi), %r9 + movq 112(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 104(%rdi), %r9 + movq 104(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 96(%rdi), %r9 + movq 96(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 88(%rdi), %r9 + movq 88(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 80(%rdi), %r9 + movq 80(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 72(%rdi), %r9 + movq 72(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 64(%rdi), %r9 + movq 64(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 56(%rdi), %r9 + movq 56(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 48(%rdi), %r9 + movq 48(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 40(%rdi), %r9 + movq 40(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 32(%rdi), %r9 + movq 32(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_cmp_16,.-sp_2048_cmp_16 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_mont_reduce_avx2_16 +.type sp_2048_mont_reduce_avx2_16,@function +.align 16 +sp_2048_mont_reduce_avx2_16: +#else +.globl _sp_2048_mont_reduce_avx2_16 +.p2align 4 +_sp_2048_mont_reduce_avx2_16: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + movq %rdx, %r8 + xorq %r14, %r14 + # i = 16 + movq $16, %r9 + movq (%rdi), %r13 + addq $64, %rdi + xorq %r12, %r12 +L_mont_loop_avx2_16: + # mu = a[i] * mp + movq %r13, %rdx + movq %r13, %r10 + imulq %r8, %rdx + xorq %r12, %r12 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rax, %rcx + movq -56(%rdi), %r13 + adcxq %rax, %r10 + adoxq %rcx, %r13 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rax, %rcx + movq -48(%rdi), %r10 + adcxq %rax, %r13 + adoxq %rcx, %r10 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rax, %rcx + movq -40(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -48(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rax, %rcx + movq -32(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -40(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rax, %rcx + movq -24(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -32(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rax, %rcx + movq -16(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -24(%rdi) + # a[i+6] += m[6] * mu + mulxq 48(%rsi), %rax, %rcx + movq -8(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -16(%rdi) + # a[i+7] += m[7] * mu + mulxq 56(%rsi), %rax, %rcx + movq (%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -8(%rdi) + # a[i+8] += m[8] * mu + mulxq 64(%rsi), %rax, %rcx + movq 8(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, (%rdi) + # a[i+9] += m[9] * mu + mulxq 72(%rsi), %rax, %rcx + movq 16(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 8(%rdi) + # a[i+10] += m[10] * mu + mulxq 80(%rsi), %rax, %rcx + movq 24(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 16(%rdi) + # a[i+11] += m[11] * mu + mulxq 88(%rsi), %rax, %rcx + movq 32(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 24(%rdi) + # a[i+12] += m[12] * mu + mulxq 96(%rsi), %rax, %rcx + movq 40(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 32(%rdi) + # a[i+13] += m[13] * mu + mulxq 104(%rsi), %rax, %rcx + movq 48(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 40(%rdi) + # a[i+14] += m[14] * mu + mulxq 112(%rsi), %rax, %rcx + movq 56(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 48(%rdi) + # a[i+15] += m[15] * mu + mulxq 120(%rsi), %rax, %rcx + movq 64(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 56(%rdi) + adcxq %r14, %r10 + movq %r10, 64(%rdi) + movq %r12, %r14 + adoxq %r12, %r14 + adcxq %r12, %r14 + # mu = a[i] * mp + movq %r13, %rdx + movq %r13, %r10 + imulq %r8, %rdx + xorq %r12, %r12 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rax, %rcx + movq -48(%rdi), %r13 + adcxq %rax, %r10 + adoxq %rcx, %r13 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rax, %rcx + movq -40(%rdi), %r10 + adcxq %rax, %r13 + adoxq %rcx, %r10 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rax, %rcx + movq -32(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -40(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rax, %rcx + movq -24(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -32(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rax, %rcx + movq -16(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -24(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rax, %rcx + movq -8(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -16(%rdi) + # a[i+6] += m[6] * mu + mulxq 48(%rsi), %rax, %rcx + movq (%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -8(%rdi) + # a[i+7] += m[7] * mu + mulxq 56(%rsi), %rax, %rcx + movq 8(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, (%rdi) + # a[i+8] += m[8] * mu + mulxq 64(%rsi), %rax, %rcx + movq 16(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 8(%rdi) + # a[i+9] += m[9] * mu + mulxq 72(%rsi), %rax, %rcx + movq 24(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 16(%rdi) + # a[i+10] += m[10] * mu + mulxq 80(%rsi), %rax, %rcx + movq 32(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 24(%rdi) + # a[i+11] += m[11] * mu + mulxq 88(%rsi), %rax, %rcx + movq 40(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 32(%rdi) + # a[i+12] += m[12] * mu + mulxq 96(%rsi), %rax, %rcx + movq 48(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 40(%rdi) + # a[i+13] += m[13] * mu + mulxq 104(%rsi), %rax, %rcx + movq 56(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 48(%rdi) + # a[i+14] += m[14] * mu + mulxq 112(%rsi), %rax, %rcx + movq 64(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 56(%rdi) + # a[i+15] += m[15] * mu + mulxq 120(%rsi), %rax, %rcx + movq 72(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 64(%rdi) + adcxq %r14, %r10 + movq %r10, 72(%rdi) + movq %r12, %r14 + adoxq %r12, %r14 + adcxq %r12, %r14 + # a += 2 + addq $16, %rdi + # i -= 2 + subq $2, %r9 + jnz L_mont_loop_avx2_16 + subq $64, %rdi + negq %r14 + movq %rdi, %r8 + subq $128, %rdi + movq (%rsi), %rcx + movq %r13, %rdx + pextq %r14, %rcx, %rcx + subq %rcx, %rdx + movq 8(%rsi), %rcx + movq 8(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, (%rdi) + sbbq %rcx, %rax + movq 16(%rsi), %rdx + movq 16(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 8(%rdi) + sbbq %rdx, %rcx + movq 24(%rsi), %rax + movq 24(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 16(%rdi) + sbbq %rax, %rdx + movq 32(%rsi), %rcx + movq 32(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 24(%rdi) + sbbq %rcx, %rax + movq 40(%rsi), %rdx + movq 40(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 32(%rdi) + sbbq %rdx, %rcx + movq 48(%rsi), %rax + movq 48(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 40(%rdi) + sbbq %rax, %rdx + movq 56(%rsi), %rcx + movq 56(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 48(%rdi) + sbbq %rcx, %rax + movq 64(%rsi), %rdx + movq 64(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 56(%rdi) + sbbq %rdx, %rcx + movq 72(%rsi), %rax + movq 72(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 64(%rdi) + sbbq %rax, %rdx + movq 80(%rsi), %rcx + movq 80(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 72(%rdi) + sbbq %rcx, %rax + movq 88(%rsi), %rdx + movq 88(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 80(%rdi) + sbbq %rdx, %rcx + movq 96(%rsi), %rax + movq 96(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 88(%rdi) + sbbq %rax, %rdx + movq 104(%rsi), %rcx + movq 104(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 96(%rdi) + sbbq %rcx, %rax + movq 112(%rsi), %rdx + movq 112(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 104(%rdi) + sbbq %rdx, %rcx + movq 120(%rsi), %rax + movq 120(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 112(%rdi) + sbbq %rax, %rdx + movq %rdx, 120(%rdi) + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_2048_mont_reduce_avx2_16,.-sp_2048_mont_reduce_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_cond_sub_32 +.type sp_2048_cond_sub_32,@function +.align 16 +sp_2048_cond_sub_32: +#else +.globl _sp_2048_cond_sub_32 +.p2align 4 +_sp_2048_cond_sub_32: +#endif /* __APPLE__ */ + subq $256, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq 128(%rdx), %r8 + movq 136(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 128(%rsp) + movq %r9, 136(%rsp) + movq 144(%rdx), %r8 + movq 152(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 144(%rsp) + movq %r9, 152(%rsp) + movq 160(%rdx), %r8 + movq 168(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r9, 168(%rsp) + movq 176(%rdx), %r8 + movq 184(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 176(%rsp) + movq %r9, 184(%rsp) + movq 192(%rdx), %r8 + movq 200(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 192(%rsp) + movq %r9, 200(%rsp) + movq 208(%rdx), %r8 + movq 216(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 208(%rsp) + movq %r9, 216(%rsp) + movq 224(%rdx), %r8 + movq 232(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 224(%rsp) + movq %r9, 232(%rsp) + movq 240(%rdx), %r8 + movq 248(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 240(%rsp) + movq %r9, 248(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + subq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 112(%rdi) + movq 128(%rsi), %r8 + movq 128(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 120(%rdi) + movq 136(%rsi), %r9 + movq 136(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 128(%rdi) + movq 144(%rsi), %r8 + movq 144(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 136(%rdi) + movq 152(%rsi), %r9 + movq 152(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 144(%rdi) + movq 160(%rsi), %r8 + movq 160(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 152(%rdi) + movq 168(%rsi), %r9 + movq 168(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 160(%rdi) + movq 176(%rsi), %r8 + movq 176(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 168(%rdi) + movq 184(%rsi), %r9 + movq 184(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 176(%rdi) + movq 192(%rsi), %r8 + movq 192(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 184(%rdi) + movq 200(%rsi), %r9 + movq 200(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 192(%rdi) + movq 208(%rsi), %r8 + movq 208(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 200(%rdi) + movq 216(%rsi), %r9 + movq 216(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 208(%rdi) + movq 224(%rsi), %r8 + movq 224(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 216(%rdi) + movq 232(%rsi), %r9 + movq 232(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 224(%rdi) + movq 240(%rsi), %r8 + movq 240(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 232(%rdi) + movq 248(%rsi), %r9 + movq 248(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + sbbq $0, %rax + addq $256, %rsp + repz retq +#ifndef __APPLE__ +.size sp_2048_cond_sub_32,.-sp_2048_cond_sub_32 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_mont_reduce_32 +.type sp_2048_mont_reduce_32,@function +.align 16 +sp_2048_mont_reduce_32: +#else +.globl _sp_2048_mont_reduce_32 +.p2align 4 +_sp_2048_mont_reduce_32: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rcx + xorq %r15, %r15 + # i = 32 + movq $32, %r8 + movq (%rdi), %r13 + movq 8(%rdi), %r14 +L_mont_loop_32: + # mu = a[i] * mp + movq %r13, %r11 + imulq %rcx, %r11 + # a[i+0] += m[0] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq (%rsi) + addq %rax, %r13 + adcq %rdx, %r10 + # a[i+1] += m[1] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 8(%rsi) + movq %r14, %r13 + addq %rax, %r13 + adcq %rdx, %r9 + addq %r10, %r13 + adcq $0, %r9 + # a[i+2] += m[2] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 16(%rsi) + movq 16(%rdi), %r14 + addq %rax, %r14 + adcq %rdx, %r10 + addq %r9, %r14 + adcq $0, %r10 + # a[i+3] += m[3] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 24(%rsi) + movq 24(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 24(%rdi) + adcq $0, %r9 + # a[i+4] += m[4] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 32(%rsi) + movq 32(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 32(%rdi) + adcq $0, %r10 + # a[i+5] += m[5] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 40(%rsi) + movq 40(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 40(%rdi) + adcq $0, %r9 + # a[i+6] += m[6] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 48(%rsi) + movq 48(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 48(%rdi) + adcq $0, %r10 + # a[i+7] += m[7] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 56(%rsi) + movq 56(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 56(%rdi) + adcq $0, %r9 + # a[i+8] += m[8] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 64(%rsi) + movq 64(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 64(%rdi) + adcq $0, %r10 + # a[i+9] += m[9] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 72(%rsi) + movq 72(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 72(%rdi) + adcq $0, %r9 + # a[i+10] += m[10] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 80(%rsi) + movq 80(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 80(%rdi) + adcq $0, %r10 + # a[i+11] += m[11] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 88(%rsi) + movq 88(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 88(%rdi) + adcq $0, %r9 + # a[i+12] += m[12] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 96(%rsi) + movq 96(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 96(%rdi) + adcq $0, %r10 + # a[i+13] += m[13] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 104(%rsi) + movq 104(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 104(%rdi) + adcq $0, %r9 + # a[i+14] += m[14] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 112(%rsi) + movq 112(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 112(%rdi) + adcq $0, %r10 + # a[i+15] += m[15] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 120(%rsi) + movq 120(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 120(%rdi) + adcq $0, %r9 + # a[i+16] += m[16] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 128(%rsi) + movq 128(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 128(%rdi) + adcq $0, %r10 + # a[i+17] += m[17] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 136(%rsi) + movq 136(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 136(%rdi) + adcq $0, %r9 + # a[i+18] += m[18] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 144(%rsi) + movq 144(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 144(%rdi) + adcq $0, %r10 + # a[i+19] += m[19] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 152(%rsi) + movq 152(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 152(%rdi) + adcq $0, %r9 + # a[i+20] += m[20] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 160(%rsi) + movq 160(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 160(%rdi) + adcq $0, %r10 + # a[i+21] += m[21] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 168(%rsi) + movq 168(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 168(%rdi) + adcq $0, %r9 + # a[i+22] += m[22] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 176(%rsi) + movq 176(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 176(%rdi) + adcq $0, %r10 + # a[i+23] += m[23] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 184(%rsi) + movq 184(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 184(%rdi) + adcq $0, %r9 + # a[i+24] += m[24] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 192(%rsi) + movq 192(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 192(%rdi) + adcq $0, %r10 + # a[i+25] += m[25] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 200(%rsi) + movq 200(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 200(%rdi) + adcq $0, %r9 + # a[i+26] += m[26] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 208(%rsi) + movq 208(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 208(%rdi) + adcq $0, %r10 + # a[i+27] += m[27] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 216(%rsi) + movq 216(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 216(%rdi) + adcq $0, %r9 + # a[i+28] += m[28] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 224(%rsi) + movq 224(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 224(%rdi) + adcq $0, %r10 + # a[i+29] += m[29] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 232(%rsi) + movq 232(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 232(%rdi) + adcq $0, %r9 + # a[i+30] += m[30] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 240(%rsi) + movq 240(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 240(%rdi) + adcq $0, %r10 + # a[i+31] += m[31] * mu + movq %r11, %rax + mulq 248(%rsi) + movq 248(%rdi), %r12 + addq %rax, %r10 + adcq %r15, %rdx + movq $0, %r15 + adcq $0, %r15 + addq %r10, %r12 + movq %r12, 248(%rdi) + adcq %rdx, 256(%rdi) + adcq $0, %r15 + # i -= 1 + addq $8, %rdi + decq %r8 + jnz L_mont_loop_32 + movq %r13, (%rdi) + movq %r14, 8(%rdi) + negq %r15 + movq %r15, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + subq $256, %rdi +#ifndef __APPLE__ + callq sp_2048_cond_sub_32@plt +#else + callq _sp_2048_cond_sub_32 +#endif /* __APPLE__ */ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_2048_mont_reduce_32,.-sp_2048_mont_reduce_32 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_cond_sub_avx2_32 +.type sp_2048_cond_sub_avx2_32,@function +.align 16 +sp_2048_cond_sub_avx2_32: +#else +.globl _sp_2048_cond_sub_avx2_32 +.p2align 4 +_sp_2048_cond_sub_avx2_32: +#endif /* __APPLE__ */ + movq $0, %rax + movq (%rdx), %r10 + movq (%rsi), %r8 + pextq %rcx, %r10, %r10 + subq %r10, %r8 + movq 8(%rdx), %r10 + movq 8(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, (%rdi) + sbbq %r10, %r9 + movq 16(%rdx), %r8 + movq 16(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 8(%rdi) + sbbq %r8, %r10 + movq 24(%rdx), %r9 + movq 24(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 16(%rdi) + sbbq %r9, %r8 + movq 32(%rdx), %r10 + movq 32(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 24(%rdi) + sbbq %r10, %r9 + movq 40(%rdx), %r8 + movq 40(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 32(%rdi) + sbbq %r8, %r10 + movq 48(%rdx), %r9 + movq 48(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 40(%rdi) + sbbq %r9, %r8 + movq 56(%rdx), %r10 + movq 56(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 48(%rdi) + sbbq %r10, %r9 + movq 64(%rdx), %r8 + movq 64(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 56(%rdi) + sbbq %r8, %r10 + movq 72(%rdx), %r9 + movq 72(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 64(%rdi) + sbbq %r9, %r8 + movq 80(%rdx), %r10 + movq 80(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 72(%rdi) + sbbq %r10, %r9 + movq 88(%rdx), %r8 + movq 88(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 80(%rdi) + sbbq %r8, %r10 + movq 96(%rdx), %r9 + movq 96(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 88(%rdi) + sbbq %r9, %r8 + movq 104(%rdx), %r10 + movq 104(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 96(%rdi) + sbbq %r10, %r9 + movq 112(%rdx), %r8 + movq 112(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 104(%rdi) + sbbq %r8, %r10 + movq 120(%rdx), %r9 + movq 120(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 112(%rdi) + sbbq %r9, %r8 + movq 128(%rdx), %r10 + movq 128(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 120(%rdi) + sbbq %r10, %r9 + movq 136(%rdx), %r8 + movq 136(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 128(%rdi) + sbbq %r8, %r10 + movq 144(%rdx), %r9 + movq 144(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 136(%rdi) + sbbq %r9, %r8 + movq 152(%rdx), %r10 + movq 152(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 144(%rdi) + sbbq %r10, %r9 + movq 160(%rdx), %r8 + movq 160(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 152(%rdi) + sbbq %r8, %r10 + movq 168(%rdx), %r9 + movq 168(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 160(%rdi) + sbbq %r9, %r8 + movq 176(%rdx), %r10 + movq 176(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 168(%rdi) + sbbq %r10, %r9 + movq 184(%rdx), %r8 + movq 184(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 176(%rdi) + sbbq %r8, %r10 + movq 192(%rdx), %r9 + movq 192(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 184(%rdi) + sbbq %r9, %r8 + movq 200(%rdx), %r10 + movq 200(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 192(%rdi) + sbbq %r10, %r9 + movq 208(%rdx), %r8 + movq 208(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 200(%rdi) + sbbq %r8, %r10 + movq 216(%rdx), %r9 + movq 216(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 208(%rdi) + sbbq %r9, %r8 + movq 224(%rdx), %r10 + movq 224(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 216(%rdi) + sbbq %r10, %r9 + movq 232(%rdx), %r8 + movq 232(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 224(%rdi) + sbbq %r8, %r10 + movq 240(%rdx), %r9 + movq 240(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 232(%rdi) + sbbq %r9, %r8 + movq 248(%rdx), %r10 + movq 248(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 240(%rdi) + sbbq %r10, %r9 + movq %r9, 248(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_cond_sub_avx2_32,.-sp_2048_cond_sub_avx2_32 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_d_avx2_32 +.type sp_2048_mul_d_avx2_32,@function +.align 16 +sp_2048_mul_d_avx2_32: +#else +.globl _sp_2048_mul_d_avx2_32 +.p2align 4 +_sp_2048_mul_d_avx2_32: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 8(%rdi) + adoxq %r8, %r9 + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 16(%rdi) + adoxq %r8, %r10 + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 24(%rdi) + adoxq %r8, %r9 + # A[4] * B + mulxq 32(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 32(%rdi) + adoxq %r8, %r10 + # A[5] * B + mulxq 40(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 40(%rdi) + adoxq %r8, %r9 + # A[6] * B + mulxq 48(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 48(%rdi) + adoxq %r8, %r10 + # A[7] * B + mulxq 56(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 56(%rdi) + adoxq %r8, %r9 + # A[8] * B + mulxq 64(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 64(%rdi) + adoxq %r8, %r10 + # A[9] * B + mulxq 72(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 72(%rdi) + adoxq %r8, %r9 + # A[10] * B + mulxq 80(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 80(%rdi) + adoxq %r8, %r10 + # A[11] * B + mulxq 88(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 88(%rdi) + adoxq %r8, %r9 + # A[12] * B + mulxq 96(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 96(%rdi) + adoxq %r8, %r10 + # A[13] * B + mulxq 104(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 104(%rdi) + adoxq %r8, %r9 + # A[14] * B + mulxq 112(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 112(%rdi) + adoxq %r8, %r10 + # A[15] * B + mulxq 120(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 120(%rdi) + adoxq %r8, %r9 + # A[16] * B + mulxq 128(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 128(%rdi) + adoxq %r8, %r10 + # A[17] * B + mulxq 136(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 136(%rdi) + adoxq %r8, %r9 + # A[18] * B + mulxq 144(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 144(%rdi) + adoxq %r8, %r10 + # A[19] * B + mulxq 152(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 152(%rdi) + adoxq %r8, %r9 + # A[20] * B + mulxq 160(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 160(%rdi) + adoxq %r8, %r10 + # A[21] * B + mulxq 168(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 168(%rdi) + adoxq %r8, %r9 + # A[22] * B + mulxq 176(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 176(%rdi) + adoxq %r8, %r10 + # A[23] * B + mulxq 184(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 184(%rdi) + adoxq %r8, %r9 + # A[24] * B + mulxq 192(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 192(%rdi) + adoxq %r8, %r10 + # A[25] * B + mulxq 200(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 200(%rdi) + adoxq %r8, %r9 + # A[26] * B + mulxq 208(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 208(%rdi) + adoxq %r8, %r10 + # A[27] * B + mulxq 216(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 216(%rdi) + adoxq %r8, %r9 + # A[28] * B + mulxq 224(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 224(%rdi) + adoxq %r8, %r10 + # A[29] * B + mulxq 232(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 232(%rdi) + adoxq %r8, %r9 + # A[30] * B + mulxq 240(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 240(%rdi) + adoxq %r8, %r10 + # A[31] * B + mulxq 248(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 248(%rdi) + movq %r9, 256(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_d_avx2_32,.-sp_2048_mul_d_avx2_32 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_cmp_32 +.type sp_2048_cmp_32,@function +.align 16 +sp_2048_cmp_32: +#else +.globl _sp_2048_cmp_32 +.p2align 4 +_sp_2048_cmp_32: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $1, %r8 + movq 248(%rdi), %r9 + movq 248(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 240(%rdi), %r9 + movq 240(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 232(%rdi), %r9 + movq 232(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 224(%rdi), %r9 + movq 224(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 216(%rdi), %r9 + movq 216(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 208(%rdi), %r9 + movq 208(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 200(%rdi), %r9 + movq 200(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 192(%rdi), %r9 + movq 192(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 184(%rdi), %r9 + movq 184(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 176(%rdi), %r9 + movq 176(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 168(%rdi), %r9 + movq 168(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 160(%rdi), %r9 + movq 160(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 152(%rdi), %r9 + movq 152(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 144(%rdi), %r9 + movq 144(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 136(%rdi), %r9 + movq 136(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 128(%rdi), %r9 + movq 128(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 120(%rdi), %r9 + movq 120(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 112(%rdi), %r9 + movq 112(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 104(%rdi), %r9 + movq 104(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 96(%rdi), %r9 + movq 96(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 88(%rdi), %r9 + movq 88(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 80(%rdi), %r9 + movq 80(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 72(%rdi), %r9 + movq 72(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 64(%rdi), %r9 + movq 64(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 56(%rdi), %r9 + movq 56(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 48(%rdi), %r9 + movq 48(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 40(%rdi), %r9 + movq 40(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 32(%rdi), %r9 + movq 32(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_cmp_32,.-sp_2048_cmp_32 +#endif /* __APPLE__ */ +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_sub_32 +.type sp_2048_sub_32,@function +.align 16 +sp_2048_sub_32: +#else +.globl _sp_2048_sub_32 +.p2align 4 +_sp_2048_sub_32: +#endif /* __APPLE__ */ + movq (%rsi), %rcx + xorq %rax, %rax + subq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + sbbq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + sbbq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + sbbq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + sbbq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + sbbq 40(%rdx), %r8 + movq 48(%rsi), %rcx + movq %r8, 40(%rdi) + sbbq 48(%rdx), %rcx + movq 56(%rsi), %r8 + movq %rcx, 48(%rdi) + sbbq 56(%rdx), %r8 + movq 64(%rsi), %rcx + movq %r8, 56(%rdi) + sbbq 64(%rdx), %rcx + movq 72(%rsi), %r8 + movq %rcx, 64(%rdi) + sbbq 72(%rdx), %r8 + movq 80(%rsi), %rcx + movq %r8, 72(%rdi) + sbbq 80(%rdx), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%rdi) + sbbq 88(%rdx), %r8 + movq 96(%rsi), %rcx + movq %r8, 88(%rdi) + sbbq 96(%rdx), %rcx + movq 104(%rsi), %r8 + movq %rcx, 96(%rdi) + sbbq 104(%rdx), %r8 + movq 112(%rsi), %rcx + movq %r8, 104(%rdi) + sbbq 112(%rdx), %rcx + movq 120(%rsi), %r8 + movq %rcx, 112(%rdi) + sbbq 120(%rdx), %r8 + movq 128(%rsi), %rcx + movq %r8, 120(%rdi) + sbbq 128(%rdx), %rcx + movq 136(%rsi), %r8 + movq %rcx, 128(%rdi) + sbbq 136(%rdx), %r8 + movq 144(%rsi), %rcx + movq %r8, 136(%rdi) + sbbq 144(%rdx), %rcx + movq 152(%rsi), %r8 + movq %rcx, 144(%rdi) + sbbq 152(%rdx), %r8 + movq 160(%rsi), %rcx + movq %r8, 152(%rdi) + sbbq 160(%rdx), %rcx + movq 168(%rsi), %r8 + movq %rcx, 160(%rdi) + sbbq 168(%rdx), %r8 + movq 176(%rsi), %rcx + movq %r8, 168(%rdi) + sbbq 176(%rdx), %rcx + movq 184(%rsi), %r8 + movq %rcx, 176(%rdi) + sbbq 184(%rdx), %r8 + movq 192(%rsi), %rcx + movq %r8, 184(%rdi) + sbbq 192(%rdx), %rcx + movq 200(%rsi), %r8 + movq %rcx, 192(%rdi) + sbbq 200(%rdx), %r8 + movq 208(%rsi), %rcx + movq %r8, 200(%rdi) + sbbq 208(%rdx), %rcx + movq 216(%rsi), %r8 + movq %rcx, 208(%rdi) + sbbq 216(%rdx), %r8 + movq 224(%rsi), %rcx + movq %r8, 216(%rdi) + sbbq 224(%rdx), %rcx + movq 232(%rsi), %r8 + movq %rcx, 224(%rdi) + sbbq 232(%rdx), %r8 + movq 240(%rsi), %rcx + movq %r8, 232(%rdi) + sbbq 240(%rdx), %rcx + movq 248(%rsi), %r8 + movq %rcx, 240(%rdi) + sbbq 248(%rdx), %r8 + movq %r8, 248(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_sub_32,.-sp_2048_sub_32 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_mont_reduce_avx2_32 +.type sp_2048_mont_reduce_avx2_32,@function +.align 16 +sp_2048_mont_reduce_avx2_32: +#else +.globl _sp_2048_mont_reduce_avx2_32 +.p2align 4 +_sp_2048_mont_reduce_avx2_32: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + movq %rdx, %r8 + xorq %r14, %r14 + # i = 32 + movq $32, %r9 + movq (%rdi), %r13 + addq $128, %rdi + xorq %r12, %r12 +L_mont_loop_avx2_32: + # mu = a[i] * mp + movq %r13, %rdx + movq %r13, %r10 + imulq %r8, %rdx + xorq %r12, %r12 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rax, %rcx + movq -120(%rdi), %r13 + adcxq %rax, %r10 + adoxq %rcx, %r13 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rax, %rcx + movq -112(%rdi), %r10 + adcxq %rax, %r13 + adoxq %rcx, %r10 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rax, %rcx + movq -104(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -112(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rax, %rcx + movq -96(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -104(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rax, %rcx + movq -88(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -96(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rax, %rcx + movq -80(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -88(%rdi) + # a[i+6] += m[6] * mu + mulxq 48(%rsi), %rax, %rcx + movq -72(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -80(%rdi) + # a[i+7] += m[7] * mu + mulxq 56(%rsi), %rax, %rcx + movq -64(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -72(%rdi) + # a[i+8] += m[8] * mu + mulxq 64(%rsi), %rax, %rcx + movq -56(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -64(%rdi) + # a[i+9] += m[9] * mu + mulxq 72(%rsi), %rax, %rcx + movq -48(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -56(%rdi) + # a[i+10] += m[10] * mu + mulxq 80(%rsi), %rax, %rcx + movq -40(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -48(%rdi) + # a[i+11] += m[11] * mu + mulxq 88(%rsi), %rax, %rcx + movq -32(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -40(%rdi) + # a[i+12] += m[12] * mu + mulxq 96(%rsi), %rax, %rcx + movq -24(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -32(%rdi) + # a[i+13] += m[13] * mu + mulxq 104(%rsi), %rax, %rcx + movq -16(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -24(%rdi) + # a[i+14] += m[14] * mu + mulxq 112(%rsi), %rax, %rcx + movq -8(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -16(%rdi) + # a[i+15] += m[15] * mu + mulxq 120(%rsi), %rax, %rcx + movq (%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -8(%rdi) + # a[i+16] += m[16] * mu + mulxq 128(%rsi), %rax, %rcx + movq 8(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, (%rdi) + # a[i+17] += m[17] * mu + mulxq 136(%rsi), %rax, %rcx + movq 16(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 8(%rdi) + # a[i+18] += m[18] * mu + mulxq 144(%rsi), %rax, %rcx + movq 24(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 16(%rdi) + # a[i+19] += m[19] * mu + mulxq 152(%rsi), %rax, %rcx + movq 32(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 24(%rdi) + # a[i+20] += m[20] * mu + mulxq 160(%rsi), %rax, %rcx + movq 40(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 32(%rdi) + # a[i+21] += m[21] * mu + mulxq 168(%rsi), %rax, %rcx + movq 48(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 40(%rdi) + # a[i+22] += m[22] * mu + mulxq 176(%rsi), %rax, %rcx + movq 56(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 48(%rdi) + # a[i+23] += m[23] * mu + mulxq 184(%rsi), %rax, %rcx + movq 64(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 56(%rdi) + # a[i+24] += m[24] * mu + mulxq 192(%rsi), %rax, %rcx + movq 72(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 64(%rdi) + # a[i+25] += m[25] * mu + mulxq 200(%rsi), %rax, %rcx + movq 80(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 72(%rdi) + # a[i+26] += m[26] * mu + mulxq 208(%rsi), %rax, %rcx + movq 88(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 80(%rdi) + # a[i+27] += m[27] * mu + mulxq 216(%rsi), %rax, %rcx + movq 96(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 88(%rdi) + # a[i+28] += m[28] * mu + mulxq 224(%rsi), %rax, %rcx + movq 104(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rdi) + # a[i+29] += m[29] * mu + mulxq 232(%rsi), %rax, %rcx + movq 112(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 104(%rdi) + # a[i+30] += m[30] * mu + mulxq 240(%rsi), %rax, %rcx + movq 120(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 112(%rdi) + # a[i+31] += m[31] * mu + mulxq 248(%rsi), %rax, %rcx + movq 128(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 120(%rdi) + adcxq %r14, %r10 + movq %r10, 128(%rdi) + movq %r12, %r14 + adoxq %r12, %r14 + adcxq %r12, %r14 + # a += 1 + addq $8, %rdi + # i -= 1 + subq $1, %r9 + jnz L_mont_loop_avx2_32 + subq $128, %rdi + negq %r14 + movq %rdi, %r8 + subq $256, %rdi + movq (%rsi), %rcx + movq %r13, %rdx + pextq %r14, %rcx, %rcx + subq %rcx, %rdx + movq 8(%rsi), %rcx + movq 8(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, (%rdi) + sbbq %rcx, %rax + movq 16(%rsi), %rdx + movq 16(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 8(%rdi) + sbbq %rdx, %rcx + movq 24(%rsi), %rax + movq 24(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 16(%rdi) + sbbq %rax, %rdx + movq 32(%rsi), %rcx + movq 32(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 24(%rdi) + sbbq %rcx, %rax + movq 40(%rsi), %rdx + movq 40(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 32(%rdi) + sbbq %rdx, %rcx + movq 48(%rsi), %rax + movq 48(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 40(%rdi) + sbbq %rax, %rdx + movq 56(%rsi), %rcx + movq 56(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 48(%rdi) + sbbq %rcx, %rax + movq 64(%rsi), %rdx + movq 64(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 56(%rdi) + sbbq %rdx, %rcx + movq 72(%rsi), %rax + movq 72(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 64(%rdi) + sbbq %rax, %rdx + movq 80(%rsi), %rcx + movq 80(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 72(%rdi) + sbbq %rcx, %rax + movq 88(%rsi), %rdx + movq 88(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 80(%rdi) + sbbq %rdx, %rcx + movq 96(%rsi), %rax + movq 96(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 88(%rdi) + sbbq %rax, %rdx + movq 104(%rsi), %rcx + movq 104(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 96(%rdi) + sbbq %rcx, %rax + movq 112(%rsi), %rdx + movq 112(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 104(%rdi) + sbbq %rdx, %rcx + movq 120(%rsi), %rax + movq 120(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 112(%rdi) + sbbq %rax, %rdx + movq 128(%rsi), %rcx + movq 128(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 120(%rdi) + sbbq %rcx, %rax + movq 136(%rsi), %rdx + movq 136(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 128(%rdi) + sbbq %rdx, %rcx + movq 144(%rsi), %rax + movq 144(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 136(%rdi) + sbbq %rax, %rdx + movq 152(%rsi), %rcx + movq 152(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 144(%rdi) + sbbq %rcx, %rax + movq 160(%rsi), %rdx + movq 160(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 152(%rdi) + sbbq %rdx, %rcx + movq 168(%rsi), %rax + movq 168(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 160(%rdi) + sbbq %rax, %rdx + movq 176(%rsi), %rcx + movq 176(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 168(%rdi) + sbbq %rcx, %rax + movq 184(%rsi), %rdx + movq 184(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 176(%rdi) + sbbq %rdx, %rcx + movq 192(%rsi), %rax + movq 192(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 184(%rdi) + sbbq %rax, %rdx + movq 200(%rsi), %rcx + movq 200(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 192(%rdi) + sbbq %rcx, %rax + movq 208(%rsi), %rdx + movq 208(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 200(%rdi) + sbbq %rdx, %rcx + movq 216(%rsi), %rax + movq 216(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 208(%rdi) + sbbq %rax, %rdx + movq 224(%rsi), %rcx + movq 224(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 216(%rdi) + sbbq %rcx, %rax + movq 232(%rsi), %rdx + movq 232(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 224(%rdi) + sbbq %rdx, %rcx + movq 240(%rsi), %rax + movq 240(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 232(%rdi) + sbbq %rax, %rdx + movq 248(%rsi), %rcx + movq 248(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 240(%rdi) + sbbq %rcx, %rax + movq %rax, 248(%rdi) + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_2048_mont_reduce_avx2_32,.-sp_2048_mont_reduce_avx2_32 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_cond_add_16 +.type sp_2048_cond_add_16,@function +.align 16 +sp_2048_cond_add_16: +#else +.globl _sp_2048_cond_add_16 +.p2align 4 +_sp_2048_cond_add_16: +#endif /* __APPLE__ */ + subq $128, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + addq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + adcq $0, %rax + addq $128, %rsp + repz retq +#ifndef __APPLE__ +.size sp_2048_cond_add_16,.-sp_2048_cond_add_16 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_2048_cond_add_avx2_16 +.type sp_2048_cond_add_avx2_16,@function +.align 16 +sp_2048_cond_add_avx2_16: +#else +.globl _sp_2048_cond_add_avx2_16 +.p2align 4 +_sp_2048_cond_add_avx2_16: +#endif /* __APPLE__ */ + movq $0, %rax + movq (%rdx), %r10 + movq (%rsi), %r8 + pextq %rcx, %r10, %r10 + addq %r10, %r8 + movq 8(%rdx), %r10 + movq 8(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, (%rdi) + adcq %r10, %r9 + movq 16(%rdx), %r8 + movq 16(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 8(%rdi) + adcq %r8, %r10 + movq 24(%rdx), %r9 + movq 24(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 16(%rdi) + adcq %r9, %r8 + movq 32(%rdx), %r10 + movq 32(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 24(%rdi) + adcq %r10, %r9 + movq 40(%rdx), %r8 + movq 40(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 32(%rdi) + adcq %r8, %r10 + movq 48(%rdx), %r9 + movq 48(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 40(%rdi) + adcq %r9, %r8 + movq 56(%rdx), %r10 + movq 56(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 48(%rdi) + adcq %r10, %r9 + movq 64(%rdx), %r8 + movq 64(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 56(%rdi) + adcq %r8, %r10 + movq 72(%rdx), %r9 + movq 72(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 64(%rdi) + adcq %r9, %r8 + movq 80(%rdx), %r10 + movq 80(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 72(%rdi) + adcq %r10, %r9 + movq 88(%rdx), %r8 + movq 88(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 80(%rdi) + adcq %r8, %r10 + movq 96(%rdx), %r9 + movq 96(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 88(%rdi) + adcq %r9, %r8 + movq 104(%rdx), %r10 + movq 104(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 96(%rdi) + adcq %r10, %r9 + movq 112(%rdx), %r8 + movq 112(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 104(%rdi) + adcq %r8, %r10 + movq 120(%rdx), %r9 + movq 120(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 112(%rdi) + adcq %r9, %r8 + movq %r8, 120(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_cond_add_avx2_16,.-sp_2048_cond_add_avx2_16 +#endif /* __APPLE__ */ +/* Shift number left by n bit. (r = a << n) + * + * r Result of left shift by n. + * a Number to shift. + * n Amoutnt o shift. + */ +#ifndef __APPLE__ +.globl sp_2048_lshift_32 +.type sp_2048_lshift_32,@function +.align 16 +sp_2048_lshift_32: +#else +.globl _sp_2048_lshift_32 +.p2align 4 +_sp_2048_lshift_32: +#endif /* __APPLE__ */ + movq %rdx, %rcx + movq $0, %r10 + movq 216(%rsi), %r11 + movq 224(%rsi), %rdx + movq 232(%rsi), %rax + movq 240(%rsi), %r8 + movq 248(%rsi), %r9 + shldq %cl, %r9, %r10 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 224(%rdi) + movq %rax, 232(%rdi) + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + movq %r10, 256(%rdi) + movq 184(%rsi), %r9 + movq 192(%rsi), %rdx + movq 200(%rsi), %rax + movq 208(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 192(%rdi) + movq %rax, 200(%rdi) + movq %r8, 208(%rdi) + movq %r11, 216(%rdi) + movq 152(%rsi), %r11 + movq 160(%rsi), %rdx + movq 168(%rsi), %rax + movq 176(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 160(%rdi) + movq %rax, 168(%rdi) + movq %r8, 176(%rdi) + movq %r9, 184(%rdi) + movq 120(%rsi), %r9 + movq 128(%rsi), %rdx + movq 136(%rsi), %rax + movq 144(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 128(%rdi) + movq %rax, 136(%rdi) + movq %r8, 144(%rdi) + movq %r11, 152(%rdi) + movq 88(%rsi), %r11 + movq 96(%rsi), %rdx + movq 104(%rsi), %rax + movq 112(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 96(%rdi) + movq %rax, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + movq 56(%rsi), %r9 + movq 64(%rsi), %rdx + movq 72(%rsi), %rax + movq 80(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 64(%rdi) + movq %rax, 72(%rdi) + movq %r8, 80(%rdi) + movq %r11, 88(%rdi) + movq 24(%rsi), %r11 + movq 32(%rsi), %rdx + movq 40(%rsi), %rax + movq 48(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 32(%rdi) + movq %rax, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shlq %cl, %rdx + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %r8, 16(%rdi) + movq %r11, 24(%rdi) + repz retq +#endif /* !WOLFSSL_SP_NO_2048 */ +#endif /* !WOLFSSL_SP_NO_2048 */ +#ifndef WOLFSSL_SP_NO_3072 +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +#ifndef __APPLE__ +.globl sp_3072_from_bin +.type sp_3072_from_bin,@function +.align 16 +sp_3072_from_bin: +#else +.globl _sp_3072_from_bin +.p2align 4 +_sp_3072_from_bin: +#endif /* __APPLE__ */ + movq %rdx, %r9 + movq %rdi, %r10 + addq %rcx, %r9 + addq $384, %r10 + xorq %r11, %r11 + jmp L_3072_from_bin_64_end +L_3072_from_bin_64_start: + subq $64, %r9 + movbeq 56(%r9), %rax + movbeq 48(%r9), %r8 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movbeq 40(%r9), %rax + movbeq 32(%r9), %r8 + movq %rax, 16(%rdi) + movq %r8, 24(%rdi) + movbeq 24(%r9), %rax + movbeq 16(%r9), %r8 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movbeq 8(%r9), %rax + movbeq (%r9), %r8 + movq %rax, 48(%rdi) + movq %r8, 56(%rdi) + addq $64, %rdi + subq $64, %rcx +L_3072_from_bin_64_end: + cmpq $63, %rcx + jg L_3072_from_bin_64_start + jmp L_3072_from_bin_8_end +L_3072_from_bin_8_start: + subq $8, %r9 + movbeq (%r9), %rax + movq %rax, (%rdi) + addq $8, %rdi + subq $8, %rcx +L_3072_from_bin_8_end: + cmpq $7, %rcx + jg L_3072_from_bin_8_start + cmpq %r11, %rcx + je L_3072_from_bin_hi_end + movq %r11, %r8 + movq %r11, %rax +L_3072_from_bin_hi_start: + movb (%rdx), %al + shlq $8, %r8 + incq %rdx + addq %rax, %r8 + decq %rcx + jg L_3072_from_bin_hi_start + movq %r8, (%rdi) + addq $8, %rdi +L_3072_from_bin_hi_end: + cmpq %r10, %rdi + je L_3072_from_bin_zero_end +L_3072_from_bin_zero_start: + movq %r11, (%rdi) + addq $8, %rdi + cmpq %r10, %rdi + jl L_3072_from_bin_zero_start +L_3072_from_bin_zero_end: + repz retq +#ifndef __APPLE__ +.size sp_3072_from_bin,.-sp_3072_from_bin +#endif /* __APPLE__ */ +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 384 + * + * r A single precision integer. + * a Byte array. + */ +#ifndef __APPLE__ +.globl sp_3072_to_bin +.type sp_3072_to_bin,@function +.align 16 +sp_3072_to_bin: +#else +.globl _sp_3072_to_bin +.p2align 4 +_sp_3072_to_bin: +#endif /* __APPLE__ */ + movbeq 376(%rdi), %rdx + movbeq 368(%rdi), %rax + movq %rdx, (%rsi) + movq %rax, 8(%rsi) + movbeq 360(%rdi), %rdx + movbeq 352(%rdi), %rax + movq %rdx, 16(%rsi) + movq %rax, 24(%rsi) + movbeq 344(%rdi), %rdx + movbeq 336(%rdi), %rax + movq %rdx, 32(%rsi) + movq %rax, 40(%rsi) + movbeq 328(%rdi), %rdx + movbeq 320(%rdi), %rax + movq %rdx, 48(%rsi) + movq %rax, 56(%rsi) + movbeq 312(%rdi), %rdx + movbeq 304(%rdi), %rax + movq %rdx, 64(%rsi) + movq %rax, 72(%rsi) + movbeq 296(%rdi), %rdx + movbeq 288(%rdi), %rax + movq %rdx, 80(%rsi) + movq %rax, 88(%rsi) + movbeq 280(%rdi), %rdx + movbeq 272(%rdi), %rax + movq %rdx, 96(%rsi) + movq %rax, 104(%rsi) + movbeq 264(%rdi), %rdx + movbeq 256(%rdi), %rax + movq %rdx, 112(%rsi) + movq %rax, 120(%rsi) + movbeq 248(%rdi), %rdx + movbeq 240(%rdi), %rax + movq %rdx, 128(%rsi) + movq %rax, 136(%rsi) + movbeq 232(%rdi), %rdx + movbeq 224(%rdi), %rax + movq %rdx, 144(%rsi) + movq %rax, 152(%rsi) + movbeq 216(%rdi), %rdx + movbeq 208(%rdi), %rax + movq %rdx, 160(%rsi) + movq %rax, 168(%rsi) + movbeq 200(%rdi), %rdx + movbeq 192(%rdi), %rax + movq %rdx, 176(%rsi) + movq %rax, 184(%rsi) + movbeq 184(%rdi), %rdx + movbeq 176(%rdi), %rax + movq %rdx, 192(%rsi) + movq %rax, 200(%rsi) + movbeq 168(%rdi), %rdx + movbeq 160(%rdi), %rax + movq %rdx, 208(%rsi) + movq %rax, 216(%rsi) + movbeq 152(%rdi), %rdx + movbeq 144(%rdi), %rax + movq %rdx, 224(%rsi) + movq %rax, 232(%rsi) + movbeq 136(%rdi), %rdx + movbeq 128(%rdi), %rax + movq %rdx, 240(%rsi) + movq %rax, 248(%rsi) + movbeq 120(%rdi), %rdx + movbeq 112(%rdi), %rax + movq %rdx, 256(%rsi) + movq %rax, 264(%rsi) + movbeq 104(%rdi), %rdx + movbeq 96(%rdi), %rax + movq %rdx, 272(%rsi) + movq %rax, 280(%rsi) + movbeq 88(%rdi), %rdx + movbeq 80(%rdi), %rax + movq %rdx, 288(%rsi) + movq %rax, 296(%rsi) + movbeq 72(%rdi), %rdx + movbeq 64(%rdi), %rax + movq %rdx, 304(%rsi) + movq %rax, 312(%rsi) + movbeq 56(%rdi), %rdx + movbeq 48(%rdi), %rax + movq %rdx, 320(%rsi) + movq %rax, 328(%rsi) + movbeq 40(%rdi), %rdx + movbeq 32(%rdi), %rax + movq %rdx, 336(%rsi) + movq %rax, 344(%rsi) + movbeq 24(%rdi), %rdx + movbeq 16(%rdi), %rax + movq %rdx, 352(%rsi) + movq %rax, 360(%rsi) + movbeq 8(%rdi), %rdx + movbeq (%rdi), %rax + movq %rdx, 368(%rsi) + movq %rax, 376(%rsi) + repz retq +#ifndef __APPLE__ +.size sp_3072_to_bin,.-sp_3072_to_bin +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_12 +.type sp_3072_mul_12,@function +.align 16 +sp_3072_mul_12: +#else +.globl _sp_3072_mul_12 +.p2align 4 +_sp_3072_mul_12: +#endif /* __APPLE__ */ + movq %rdx, %rcx + subq $96, %rsp + # A[0] * B[0] + movq (%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + movq %rax, (%rsp) + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[0] + movq (%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 8(%rsp) + # A[0] * B[2] + movq 16(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[1] + movq 8(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[0] + movq (%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 16(%rsp) + # A[0] * B[3] + movq 24(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[2] + movq 16(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[1] + movq 8(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[0] + movq (%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 24(%rsp) + # A[0] * B[4] + movq 32(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[3] + movq 24(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[2] + movq 16(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[1] + movq 8(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[0] + movq (%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 32(%rsp) + # A[0] * B[5] + movq 40(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[4] + movq 32(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[3] + movq 24(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[2] + movq 16(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[1] + movq 8(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[0] + movq (%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 40(%rsp) + # A[0] * B[6] + movq 48(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[5] + movq 40(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[4] + movq 32(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[3] + movq 24(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[2] + movq 16(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[1] + movq 8(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[0] + movq (%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 48(%rsp) + # A[0] * B[7] + movq 56(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[6] + movq 48(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[5] + movq 40(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[4] + movq 32(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[3] + movq 24(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[2] + movq 16(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[1] + movq 8(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[0] + movq (%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 56(%rsp) + # A[0] * B[8] + movq 64(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[7] + movq 56(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[6] + movq 48(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[5] + movq 40(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[4] + movq 32(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[3] + movq 24(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[2] + movq 16(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[1] + movq 8(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[0] + movq (%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 64(%rsp) + # A[0] * B[9] + movq 72(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[8] + movq 64(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[7] + movq 56(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[6] + movq 48(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[5] + movq 40(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[4] + movq 32(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[3] + movq 24(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[2] + movq 16(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[1] + movq 8(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[0] + movq (%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 72(%rsp) + # A[0] * B[10] + movq 80(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[9] + movq 72(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[8] + movq 64(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[7] + movq 56(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[6] + movq 48(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[5] + movq 40(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[4] + movq 32(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[3] + movq 24(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[2] + movq 16(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[1] + movq 8(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[0] + movq (%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 80(%rsp) + # A[0] * B[11] + movq 88(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[10] + movq 80(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[9] + movq 72(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[8] + movq 64(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[7] + movq 56(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[6] + movq 48(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[5] + movq 40(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[4] + movq 32(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[3] + movq 24(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[2] + movq 16(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[1] + movq 8(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[0] + movq (%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 88(%rsp) + # A[1] * B[11] + movq 88(%rcx), %rax + mulq 8(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[10] + movq 80(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[9] + movq 72(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[8] + movq 64(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[7] + movq 56(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[6] + movq 48(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[5] + movq 40(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[4] + movq 32(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[3] + movq 24(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[2] + movq 16(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[1] + movq 8(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 96(%rdi) + # A[2] * B[11] + movq 88(%rcx), %rax + mulq 16(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[10] + movq 80(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[9] + movq 72(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[8] + movq 64(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[7] + movq 56(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[6] + movq 48(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[5] + movq 40(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[4] + movq 32(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[3] + movq 24(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[2] + movq 16(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 104(%rdi) + # A[3] * B[11] + movq 88(%rcx), %rax + mulq 24(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[10] + movq 80(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[9] + movq 72(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[8] + movq 64(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[7] + movq 56(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[6] + movq 48(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[5] + movq 40(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[4] + movq 32(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[3] + movq 24(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 112(%rdi) + # A[4] * B[11] + movq 88(%rcx), %rax + mulq 32(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[10] + movq 80(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[9] + movq 72(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[8] + movq 64(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[7] + movq 56(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[6] + movq 48(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[5] + movq 40(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[4] + movq 32(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 120(%rdi) + # A[5] * B[11] + movq 88(%rcx), %rax + mulq 40(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[10] + movq 80(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[9] + movq 72(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[8] + movq 64(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[7] + movq 56(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[6] + movq 48(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[5] + movq 40(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 128(%rdi) + # A[6] * B[11] + movq 88(%rcx), %rax + mulq 48(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[10] + movq 80(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[9] + movq 72(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[8] + movq 64(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[7] + movq 56(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[6] + movq 48(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 136(%rdi) + # A[7] * B[11] + movq 88(%rcx), %rax + mulq 56(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[10] + movq 80(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[9] + movq 72(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[8] + movq 64(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[7] + movq 56(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 144(%rdi) + # A[8] * B[11] + movq 88(%rcx), %rax + mulq 64(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[10] + movq 80(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[9] + movq 72(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[8] + movq 64(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 152(%rdi) + # A[9] * B[11] + movq 88(%rcx), %rax + mulq 72(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[10] + movq 80(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[9] + movq 72(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 160(%rdi) + # A[10] * B[11] + movq 88(%rcx), %rax + mulq 80(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[10] + movq 80(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 168(%rdi) + # A[11] * B[11] + movq 88(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + movq %r9, 176(%rdi) + movq %r10, 184(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r8 + movq 24(%rsp), %r9 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rsp), %rax + movq 40(%rsp), %rdx + movq 48(%rsp), %r8 + movq 56(%rsp), %r9 + movq %rax, 32(%rdi) + movq %rdx, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rsp), %rax + movq 72(%rsp), %rdx + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq %rax, 64(%rdi) + movq %rdx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + addq $96, %rsp + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_12,.-sp_3072_mul_12 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sqr_12 +.type sp_3072_sqr_12,@function +.align 16 +sp_3072_sqr_12: +#else +.globl _sp_3072_sqr_12 +.p2align 4 +_sp_3072_sqr_12: +#endif /* __APPLE__ */ + push %r12 + subq $96, %rsp + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + xorq %r9, %r9 + movq %rax, (%rsp) + movq %rdx, %r8 + # A[0] * A[1] + movq 8(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 8(%rsp) + # A[0] * A[2] + movq 16(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 16(%rsp) + # A[0] * A[3] + movq 24(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * A[2] + movq 16(%rsi), %rax + mulq 8(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 24(%rsp) + # A[0] * A[4] + movq 32(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[1] * A[3] + movq 24(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 32(%rsp) + # A[0] * A[5] + movq 40(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[4] + movq 32(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[3] + movq 24(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 40(%rsp) + # A[0] * A[6] + movq 48(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[5] + movq 40(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[4] + movq 32(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 48(%rsp) + # A[0] * A[7] + movq 56(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[6] + movq 48(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[5] + movq 40(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[4] + movq 32(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 56(%rsp) + # A[0] * A[8] + movq 64(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[7] + movq 56(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[6] + movq 48(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[5] + movq 40(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[4] + movq 32(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 64(%rsp) + # A[0] * A[9] + movq 72(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[8] + movq 64(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[7] + movq 56(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[6] + movq 48(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[5] + movq 40(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 72(%rsp) + # A[0] * A[10] + movq 80(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[9] + movq 72(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[8] + movq 64(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[7] + movq 56(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[6] + movq 48(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[5] + movq 40(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 80(%rsp) + # A[0] * A[11] + movq 88(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[10] + movq 80(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[9] + movq 72(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[8] + movq 64(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[7] + movq 56(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[6] + movq 48(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 88(%rsp) + # A[1] * A[11] + movq 88(%rsi), %rax + mulq 8(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[2] * A[10] + movq 80(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[9] + movq 72(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[8] + movq 64(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[7] + movq 56(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[6] + movq 48(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 96(%rdi) + # A[2] * A[11] + movq 88(%rsi), %rax + mulq 16(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[3] * A[10] + movq 80(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[9] + movq 72(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[8] + movq 64(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[7] + movq 56(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 104(%rdi) + # A[3] * A[11] + movq 88(%rsi), %rax + mulq 24(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[4] * A[10] + movq 80(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[9] + movq 72(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[8] + movq 64(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[7] + movq 56(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 112(%rdi) + # A[4] * A[11] + movq 88(%rsi), %rax + mulq 32(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[5] * A[10] + movq 80(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[9] + movq 72(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[8] + movq 64(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 120(%rdi) + # A[5] * A[11] + movq 88(%rsi), %rax + mulq 40(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[6] * A[10] + movq 80(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[9] + movq 72(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[8] + movq 64(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 128(%rdi) + # A[6] * A[11] + movq 88(%rsi), %rax + mulq 48(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[7] * A[10] + movq 80(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[9] + movq 72(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 136(%rdi) + # A[7] * A[11] + movq 88(%rsi), %rax + mulq 56(%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * A[10] + movq 80(%rsi), %rax + mulq 64(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * A[9] + movq 72(%rsi), %rax + mulq %rax + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 144(%rdi) + # A[8] * A[11] + movq 88(%rsi), %rax + mulq 64(%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[9] * A[10] + movq 80(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 152(%rdi) + # A[9] * A[11] + movq 88(%rsi), %rax + mulq 72(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[10] * A[10] + movq 80(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 160(%rdi) + # A[10] * A[11] + movq 88(%rsi), %rax + mulq 80(%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 168(%rdi) + # A[11] * A[11] + movq 88(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 176(%rdi) + movq %r9, 184(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 32(%rsp), %rax + movq 40(%rsp), %rdx + movq 48(%rsp), %r10 + movq 56(%rsp), %r11 + movq %rax, 32(%rdi) + movq %rdx, 40(%rdi) + movq %r10, 48(%rdi) + movq %r11, 56(%rdi) + movq 64(%rsp), %rax + movq 72(%rsp), %rdx + movq 80(%rsp), %r10 + movq 88(%rsp), %r11 + movq %rax, 64(%rdi) + movq %rdx, 72(%rdi) + movq %r10, 80(%rdi) + movq %r11, 88(%rdi) + addq $96, %rsp + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_sqr_12,.-sp_3072_sqr_12 +#endif /* __APPLE__ */ +#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. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_avx2_12 +.type sp_3072_mul_avx2_12,@function +.align 16 +sp_3072_mul_avx2_12: +#else +.globl _sp_3072_mul_avx2_12 +.p2align 4 +_sp_3072_mul_avx2_12: +#endif /* __APPLE__ */ + push %rbx + push %rbp + push %r12 + movq %rdx, %rbp + subq $96, %rsp + cmpq %rdi, %rsi + movq %rsp, %rbx + cmovne %rdi, %rbx + cmpq %rdi, %rbp + cmove %rsp, %rbx + xorq %r12, %r12 + movq (%rsi), %rdx + # A[0] * B[0] + mulx (%rbp), %r8, %r9 + # A[0] * B[1] + mulx 8(%rbp), %rax, %r10 + movq %r8, (%rbx) + adcxq %rax, %r9 + movq %r9, 8(%rbx) + # A[0] * B[2] + mulx 16(%rbp), %rax, %r8 + adcxq %rax, %r10 + # A[0] * B[3] + mulx 24(%rbp), %rax, %r9 + movq %r10, 16(%rbx) + adcxq %rax, %r8 + movq %r8, 24(%rbx) + # A[0] * B[4] + mulx 32(%rbp), %rax, %r10 + adcxq %rax, %r9 + # A[0] * B[5] + mulx 40(%rbp), %rax, %r8 + movq %r9, 32(%rbx) + adcxq %rax, %r10 + movq %r10, 40(%rbx) + # A[0] * B[6] + mulx 48(%rbp), %rax, %r9 + adcxq %rax, %r8 + # A[0] * B[7] + mulx 56(%rbp), %rax, %r10 + movq %r8, 48(%rbx) + adcxq %rax, %r9 + movq %r9, 56(%rbx) + # A[0] * B[8] + mulx 64(%rbp), %rax, %r8 + adcxq %rax, %r10 + # A[0] * B[9] + mulx 72(%rbp), %rax, %r9 + movq %r10, 64(%rbx) + adcxq %rax, %r8 + movq %r8, 72(%rbx) + # A[0] * B[10] + mulx 80(%rbp), %rax, %r10 + adcxq %rax, %r9 + # A[0] * B[11] + mulx 88(%rbp), %rax, %r8 + movq %r9, 80(%rbx) + adcxq %rax, %r10 + adcxq %r12, %r8 + movq %r12, %r11 + adcxq %r12, %r11 + movq %r10, 88(%rbx) + movq %r8, 96(%rdi) + movq 8(%rsi), %rdx + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %r8 + # A[1] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 8(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 16(%rbx) + movq 32(%rbx), %r9 + movq 40(%rbx), %r10 + # A[1] * B[2] + mulx 16(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 24(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 32(%rbx) + movq 48(%rbx), %r8 + movq 56(%rbx), %r9 + # A[1] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[1] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 40(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 48(%rbx) + movq 64(%rbx), %r10 + movq 72(%rbx), %r8 + # A[1] * B[6] + mulx 48(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 56(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 64(%rbx) + movq 80(%rbx), %r9 + movq 88(%rbx), %r10 + # A[1] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 72(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 80(%rbx) + movq 96(%rdi), %r8 + # A[1] * B[10] + mulx 80(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[1] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 88(%rbx) + movq %r12, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r11, %r9 + movq %r12, %r11 + adoxq %r12, %r11 + adcxq %r12, %r11 + movq %r8, 96(%rdi) + movq %r9, 104(%rdi) + movq 16(%rsi), %rdx + movq 16(%rbx), %r10 + movq 24(%rbx), %r8 + movq 32(%rbx), %r9 + # A[2] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[2] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 16(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 24(%rbx) + movq 40(%rbx), %r10 + movq 48(%rbx), %r8 + # A[2] * B[2] + mulx 16(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 32(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 40(%rbx) + movq 56(%rbx), %r9 + movq 64(%rbx), %r10 + # A[2] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[2] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 48(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 56(%rbx) + movq 72(%rbx), %r8 + movq 80(%rbx), %r9 + # A[2] * B[6] + mulx 48(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[2] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 64(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 72(%rbx) + movq 88(%rbx), %r10 + movq 96(%rdi), %r8 + # A[2] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 80(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 88(%rbx) + movq 104(%rdi), %r9 + # A[2] * B[10] + mulx 80(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[2] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 96(%rdi) + movq %r12, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r11, %r10 + movq %r12, %r11 + adoxq %r12, %r11 + adcxq %r12, %r11 + movq %r9, 104(%rdi) + movq %r10, 112(%rdi) + movq 24(%rsi), %rdx + movq 24(%rbx), %r8 + movq 32(%rbx), %r9 + movq 40(%rbx), %r10 + # A[3] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 24(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 32(%rbx) + movq 48(%rbx), %r8 + movq 56(%rbx), %r9 + # A[3] * B[2] + mulx 16(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[3] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 40(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 48(%rbx) + movq 64(%rbx), %r10 + movq 72(%rbx), %r8 + # A[3] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 56(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 64(%rbx) + movq 80(%rbx), %r9 + movq 88(%rbx), %r10 + # A[3] * B[6] + mulx 48(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 72(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 80(%rbx) + movq 96(%rdi), %r8 + movq 104(%rdi), %r9 + # A[3] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[3] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 88(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 96(%rdi) + movq 112(%rdi), %r10 + # A[3] * B[10] + mulx 80(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 104(%rdi) + movq %r12, %r8 + adcxq %rax, %r10 + adoxq %rcx, %r8 + adcxq %r11, %r8 + movq %r12, %r11 + adoxq %r12, %r11 + adcxq %r12, %r11 + movq %r10, 112(%rdi) + movq %r8, 120(%rdi) + movq 32(%rsi), %rdx + movq 32(%rbx), %r9 + movq 40(%rbx), %r10 + movq 48(%rbx), %r8 + # A[4] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[4] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 32(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 40(%rbx) + movq 56(%rbx), %r9 + movq 64(%rbx), %r10 + # A[4] * B[2] + mulx 16(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 48(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 56(%rbx) + movq 72(%rbx), %r8 + movq 80(%rbx), %r9 + # A[4] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[4] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 64(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 72(%rbx) + movq 88(%rbx), %r10 + movq 96(%rdi), %r8 + # A[4] * B[6] + mulx 48(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[4] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 80(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 88(%rbx) + movq 104(%rdi), %r9 + movq 112(%rdi), %r10 + # A[4] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 96(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 104(%rdi) + movq 120(%rdi), %r8 + # A[4] * B[10] + mulx 80(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[4] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 112(%rdi) + movq %r12, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r11, %r9 + movq %r12, %r11 + adoxq %r12, %r11 + adcxq %r12, %r11 + movq %r8, 120(%rdi) + movq %r9, 128(%rdi) + movq 40(%rsi), %rdx + movq 40(%rbx), %r10 + movq 48(%rbx), %r8 + movq 56(%rbx), %r9 + # A[5] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[5] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 40(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 48(%rbx) + movq 64(%rbx), %r10 + movq 72(%rbx), %r8 + # A[5] * B[2] + mulx 16(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 56(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 64(%rbx) + movq 80(%rbx), %r9 + movq 88(%rbx), %r10 + # A[5] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 72(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 80(%rbx) + movq 96(%rdi), %r8 + movq 104(%rdi), %r9 + # A[5] * B[6] + mulx 48(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[5] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 88(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 96(%rdi) + movq 112(%rdi), %r10 + movq 120(%rdi), %r8 + # A[5] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 104(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 112(%rdi) + movq 128(%rdi), %r9 + # A[5] * B[10] + mulx 80(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 120(%rdi) + movq %r12, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r11, %r10 + movq %r12, %r11 + adoxq %r12, %r11 + adcxq %r12, %r11 + movq %r9, 128(%rdi) + movq %r10, 136(%rdi) + movq 48(%rsi), %rdx + movq 48(%rbx), %r8 + movq 56(%rbx), %r9 + movq 64(%rbx), %r10 + # A[6] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 48(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 56(%rbx) + movq 72(%rbx), %r8 + movq 80(%rbx), %r9 + # A[6] * B[2] + mulx 16(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[6] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 64(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 72(%rbx) + movq 88(%rbx), %r10 + movq 96(%rdi), %r8 + # A[6] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 80(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 88(%rbx) + movq 104(%rdi), %r9 + movq 112(%rdi), %r10 + # A[6] * B[6] + mulx 48(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 96(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 104(%rdi) + movq 120(%rdi), %r8 + movq 128(%rdi), %r9 + # A[6] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[6] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 112(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rdi) + movq 136(%rdi), %r10 + # A[6] * B[10] + mulx 80(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + movq %r12, %r8 + adcxq %rax, %r10 + adoxq %rcx, %r8 + adcxq %r11, %r8 + movq %r12, %r11 + adoxq %r12, %r11 + adcxq %r12, %r11 + movq %r10, 136(%rdi) + movq %r8, 144(%rdi) + movq 56(%rsi), %rdx + movq 56(%rbx), %r9 + movq 64(%rbx), %r10 + movq 72(%rbx), %r8 + # A[7] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 56(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 64(%rbx) + movq 80(%rbx), %r9 + movq 88(%rbx), %r10 + # A[7] * B[2] + mulx 16(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[7] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 72(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 80(%rbx) + movq 96(%rdi), %r8 + movq 104(%rdi), %r9 + # A[7] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[7] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 88(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 96(%rdi) + movq 112(%rdi), %r10 + movq 120(%rdi), %r8 + # A[7] * B[6] + mulx 48(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 104(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 112(%rdi) + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[7] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[7] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 120(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rdi) + movq 144(%rdi), %r8 + # A[7] * B[10] + mulx 80(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[7] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + movq %r12, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r11, %r9 + movq %r12, %r11 + adoxq %r12, %r11 + adcxq %r12, %r11 + movq %r8, 144(%rdi) + movq %r9, 152(%rdi) + movq 64(%rsi), %rdx + movq 64(%rbx), %r10 + movq 72(%rbx), %r8 + movq 80(%rbx), %r9 + # A[8] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[8] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 64(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 72(%rbx) + movq 88(%rbx), %r10 + movq 96(%rdi), %r8 + # A[8] * B[2] + mulx 16(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 80(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 88(%rbx) + movq 104(%rdi), %r9 + movq 112(%rdi), %r10 + # A[8] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 96(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 104(%rdi) + movq 120(%rdi), %r8 + movq 128(%rdi), %r9 + # A[8] * B[6] + mulx 48(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[8] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 112(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rdi) + movq 136(%rdi), %r10 + movq 144(%rdi), %r8 + # A[8] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 136(%rdi) + movq 152(%rdi), %r9 + # A[8] * B[10] + mulx 80(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 144(%rdi) + movq %r12, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r11, %r10 + movq %r12, %r11 + adoxq %r12, %r11 + adcxq %r12, %r11 + movq %r9, 152(%rdi) + movq %r10, 160(%rdi) + movq 72(%rsi), %rdx + movq 72(%rbx), %r8 + movq 80(%rbx), %r9 + movq 88(%rbx), %r10 + # A[9] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 72(%rbx) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 80(%rbx) + movq 96(%rdi), %r8 + movq 104(%rdi), %r9 + # A[9] * B[2] + mulx 16(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[9] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 88(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 96(%rdi) + movq 112(%rdi), %r10 + movq 120(%rdi), %r8 + # A[9] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 104(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 112(%rdi) + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[9] * B[6] + mulx 48(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 120(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rdi) + movq 144(%rdi), %r8 + movq 152(%rdi), %r9 + # A[9] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[9] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 144(%rdi) + movq 160(%rdi), %r10 + # A[9] * B[10] + mulx 80(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 152(%rdi) + movq %r12, %r8 + adcxq %rax, %r10 + adoxq %rcx, %r8 + adcxq %r11, %r8 + movq %r12, %r11 + adoxq %r12, %r11 + adcxq %r12, %r11 + movq %r10, 160(%rdi) + movq %r8, 168(%rdi) + movq 80(%rsi), %rdx + movq 80(%rbx), %r9 + movq 88(%rbx), %r10 + movq 96(%rdi), %r8 + # A[10] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 80(%rbx) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 88(%rbx) + movq 104(%rdi), %r9 + movq 112(%rdi), %r10 + # A[10] * B[2] + mulx 16(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 96(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 104(%rdi) + movq 120(%rdi), %r8 + movq 128(%rdi), %r9 + # A[10] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[10] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 112(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rdi) + movq 136(%rdi), %r10 + movq 144(%rdi), %r8 + # A[10] * B[6] + mulx 48(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 136(%rdi) + movq 152(%rdi), %r9 + movq 160(%rdi), %r10 + # A[10] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 144(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 152(%rdi) + movq 168(%rdi), %r8 + # A[10] * B[10] + mulx 80(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[10] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 160(%rdi) + movq %r12, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r11, %r9 + movq %r12, %r11 + adoxq %r12, %r11 + adcxq %r12, %r11 + movq %r8, 168(%rdi) + movq %r9, 176(%rdi) + movq 88(%rsi), %rdx + movq 88(%rbx), %r10 + movq 96(%rdi), %r8 + movq 104(%rdi), %r9 + # A[11] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[11] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 88(%rbx) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 96(%rdi) + movq 112(%rdi), %r10 + movq 120(%rdi), %r8 + # A[11] * B[2] + mulx 16(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 104(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 112(%rdi) + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[11] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 120(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rdi) + movq 144(%rdi), %r8 + movq 152(%rdi), %r9 + # A[11] * B[6] + mulx 48(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r8 + # A[11] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 144(%rdi) + movq 160(%rdi), %r10 + movq 168(%rdi), %r8 + # A[11] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 152(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r8 + movq %r10, 160(%rdi) + movq 176(%rdi), %r9 + # A[11] * B[10] + mulx 80(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 168(%rdi) + movq %r12, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r11, %r10 + movq %r9, 176(%rdi) + movq %r10, 184(%rdi) + cmpq %rdi, %rsi + je L_start_3072_mul_avx2_12 + cmpq %rdi, %rbp + jne L_end_3072_mul_avx2_12 +L_start_3072_mul_avx2_12: + vmovdqu (%rbx), %xmm0 + vmovups %xmm0, (%rdi) + vmovdqu 16(%rbx), %xmm0 + vmovups %xmm0, 16(%rdi) + vmovdqu 32(%rbx), %xmm0 + vmovups %xmm0, 32(%rdi) + vmovdqu 48(%rbx), %xmm0 + vmovups %xmm0, 48(%rdi) + vmovdqu 64(%rbx), %xmm0 + vmovups %xmm0, 64(%rdi) + vmovdqu 80(%rbx), %xmm0 + vmovups %xmm0, 80(%rdi) +L_end_3072_mul_avx2_12: + addq $96, %rsp + pop %r12 + pop %rbp + pop %rbx + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_avx2_12,.-sp_3072_mul_avx2_12 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sqr_avx2_12 +.type sp_3072_sqr_avx2_12,@function +.align 16 +sp_3072_sqr_avx2_12: +#else +.globl _sp_3072_sqr_avx2_12 +.p2align 4 +_sp_3072_sqr_avx2_12: +#endif /* __APPLE__ */ + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + subq $96, %rsp + cmpq %rdi, %rsi + movq %rsp, %rbp + cmovne %rdi, %rbp + xorq %r10, %r10 + # Diagonal 1 + # A[1] x A[0] + movq (%rsi), %rdx + mulxq 8(%rsi), %r8, %r9 + movq %r8, 8(%rbp) + movq %r10, %r8 + # A[2] x A[0] + mulxq 16(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 16(%rbp) + movq %r10, %r9 + # A[3] x A[0] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 24(%rbp) + movq %r10, %r8 + # A[4] x A[0] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 32(%rbp) + movq %r10, %r9 + # A[5] x A[0] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 40(%rbp) + movq %r10, %r8 + # A[6] x A[0] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 48(%rbp) + movq %r10, %r9 + # A[7] x A[0] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, %r12 + movq %r10, %r8 + # A[8] x A[0] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, %r13 + movq %r10, %r9 + # A[9] x A[0] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, %r14 + movq %r10, %r8 + # A[10] x A[0] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, %r15 + movq %r10, %r9 + # A[11] x A[0] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, %rbx + # Carry + adcxq %r10, %r9 + movq %r10, %r11 + adcxq %r10, %r11 + adoxq %r10, %r11 + movq %r9, 96(%rdi) + # Diagonal 2 + movq 24(%rbp), %r9 + movq 32(%rbp), %r8 + # A[2] x A[1] + movq 8(%rsi), %rdx + mulxq 16(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 24(%rbp) + movq 40(%rbp), %r9 + # A[3] x A[1] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 32(%rbp) + movq 48(%rbp), %r8 + # A[4] x A[1] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 40(%rbp) + # No load %r12 - %r9 + # A[5] x A[1] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r12 + movq %r8, 48(%rbp) + # No load %r13 - %r8 + # A[6] x A[1] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r13 + # No store %r12 + # No load %r14 - %r9 + # A[7] x A[1] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + # No store %r13 + # No load %r15 - %r8 + # A[8] x A[1] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # No store %r14 + # No load %rbx - %r9 + # A[9] x A[1] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r15 + movq 96(%rdi), %r8 + # A[10] x A[1] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r8 + # No store %rbx + movq %r10, %r9 + # A[11] x A[1] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 96(%rdi) + movq %r10, %r8 + # A[11] x A[2] + movq 16(%rsi), %rdx + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 104(%rdi) + # Carry + adcxq %r11, %r8 + movq %r10, %r11 + adcxq %r10, %r11 + adoxq %r10, %r11 + movq %r8, 112(%rdi) + # Diagonal 3 + movq 40(%rbp), %r8 + movq 48(%rbp), %r9 + # A[3] x A[2] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 40(%rbp) + # No load %r12 - %r8 + # A[4] x A[2] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r12 + movq %r9, 48(%rbp) + # No load %r13 - %r9 + # A[5] x A[2] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r13 + # No store %r12 + # No load %r14 - %r8 + # A[6] x A[2] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + # No store %r13 + # No load %r15 - %r9 + # A[7] x A[2] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # No store %r14 + # No load %rbx - %r8 + # A[8] x A[2] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r15 + movq 96(%rdi), %r9 + # A[9] x A[2] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r9 + # No store %rbx + movq 104(%rdi), %r8 + # A[10] x A[2] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 96(%rdi) + movq 112(%rdi), %r9 + # A[10] x A[3] + movq 80(%rsi), %rdx + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 104(%rdi) + movq %r10, %r8 + # A[10] x A[4] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 112(%rdi) + movq %r10, %r9 + # A[10] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rdi) + # Carry + adcxq %r11, %r9 + movq %r10, %r11 + adcxq %r10, %r11 + adoxq %r10, %r11 + movq %r9, 128(%rdi) + # Diagonal 4 + # No load %r12 - %r9 + # No load %r13 - %r8 + # A[4] x A[3] + movq 24(%rsi), %rdx + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r13 + # No store %r12 + # No load %r14 - %r9 + # A[5] x A[3] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + # No store %r13 + # No load %r15 - %r8 + # A[6] x A[3] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # No store %r14 + # No load %rbx - %r9 + # A[7] x A[3] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r15 + movq 96(%rdi), %r8 + # A[8] x A[3] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r8 + # No store %rbx + movq 104(%rdi), %r9 + # A[9] x A[3] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 96(%rdi) + movq 112(%rdi), %r8 + # A[9] x A[4] + movq 72(%rsi), %rdx + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 104(%rdi) + movq 120(%rdi), %r9 + # A[9] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 112(%rdi) + movq 128(%rdi), %r8 + # A[9] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 120(%rdi) + movq %r10, %r9 + # A[9] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 128(%rdi) + movq %r10, %r8 + # A[9] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 136(%rdi) + # Carry + adcxq %r11, %r8 + movq %r10, %r11 + adcxq %r10, %r11 + adoxq %r10, %r11 + movq %r8, 144(%rdi) + # Diagonal 5 + # No load %r14 - %r8 + # No load %r15 - %r9 + # A[5] x A[4] + movq 32(%rsi), %rdx + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # No store %r14 + # No load %rbx - %r8 + # A[6] x A[4] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r15 + adoxq %rcx, %rbx + # No store %r15 + movq 96(%rdi), %r9 + # A[7] x A[4] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r9 + # No store %rbx + movq 104(%rdi), %r8 + # A[8] x A[4] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 96(%rdi) + movq 112(%rdi), %r9 + # A[8] x A[5] + movq 64(%rsi), %rdx + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 104(%rdi) + movq 120(%rdi), %r8 + # A[8] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 112(%rdi) + movq 128(%rdi), %r9 + # A[8] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rdi) + movq 136(%rdi), %r8 + # A[10] x A[6] + movq 80(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 128(%rdi) + movq 144(%rdi), %r9 + # A[10] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 136(%rdi) + movq %r10, %r8 + # A[10] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 144(%rdi) + movq %r10, %r9 + # A[10] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 152(%rdi) + # Carry + adcxq %r11, %r9 + movq %r10, %r11 + adcxq %r10, %r11 + adoxq %r10, %r11 + movq %r9, 160(%rdi) + # Diagonal 6 + # No load %rbx - %r9 + movq 96(%rdi), %r8 + # A[6] x A[5] + movq 40(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %rbx + adoxq %rcx, %r8 + # No store %rbx + movq 104(%rdi), %r9 + # A[7] x A[5] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 96(%rdi) + movq 112(%rdi), %r8 + # A[7] x A[6] + movq 48(%rsi), %rdx + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 104(%rdi) + movq 120(%rdi), %r9 + # A[11] x A[3] + movq 88(%rsi), %rdx + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 112(%rdi) + movq 128(%rdi), %r8 + # A[11] x A[4] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 120(%rdi) + movq 136(%rdi), %r9 + # A[11] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 128(%rdi) + movq 144(%rdi), %r8 + # A[11] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 136(%rdi) + movq 152(%rdi), %r9 + # A[11] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 144(%rdi) + movq 160(%rdi), %r8 + # A[11] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 152(%rdi) + movq %r10, %r9 + # A[11] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 160(%rdi) + movq %r10, %r8 + # A[11] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r8 + movq %r9, 168(%rdi) + # Carry + adcxq %r11, %r8 + movq %r10, %r11 + adcxq %r10, %r11 + adoxq %r10, %r11 + movq %r8, 176(%rdi) + movq %r11, 184(%rdi) + # Double and Add in A[i] x A[i] + movq 8(%rbp), %r9 + # A[0] x A[0] + movq (%rsi), %rdx + mulxq %rdx, %rax, %rcx + movq %rax, (%rbp) + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r9, 8(%rbp) + movq 16(%rbp), %r8 + movq 24(%rbp), %r9 + # A[1] x A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 16(%rbp) + movq %r9, 24(%rbp) + movq 32(%rbp), %r8 + movq 40(%rbp), %r9 + # A[2] x A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 32(%rbp) + movq %r9, 40(%rbp) + movq 48(%rbp), %r8 + # A[3] x A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r12, %r12 + adcxq %rax, %r8 + adcxq %rcx, %r12 + movq %r8, 48(%rbp) + # A[4] x A[4] + movq 32(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r13, %r13 + adoxq %r14, %r14 + adcxq %rax, %r13 + adcxq %rcx, %r14 + # A[5] x A[5] + movq 40(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r15, %r15 + adoxq %rbx, %rbx + adcxq %rax, %r15 + adcxq %rcx, %rbx + movq 96(%rdi), %r8 + movq 104(%rdi), %r9 + # A[6] x A[6] + movq 48(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 96(%rdi) + movq %r9, 104(%rdi) + movq 112(%rdi), %r8 + movq 120(%rdi), %r9 + # A[7] x A[7] + movq 56(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + movq 128(%rdi), %r8 + movq 136(%rdi), %r9 + # A[8] x A[8] + movq 64(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 128(%rdi) + movq %r9, 136(%rdi) + movq 144(%rdi), %r8 + movq 152(%rdi), %r9 + # A[9] x A[9] + movq 72(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 144(%rdi) + movq %r9, 152(%rdi) + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + # A[10] x A[10] + movq 80(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 160(%rdi) + movq %r9, 168(%rdi) + movq 176(%rdi), %r8 + movq 184(%rdi), %r9 + # A[11] x A[11] + movq 88(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adoxq %r9, %r9 + adcxq %rax, %r8 + adcxq %rcx, %r9 + movq %r8, 176(%rdi) + movq %r9, 184(%rdi) + movq %r12, 56(%rdi) + movq %r13, 64(%rdi) + movq %r14, 72(%rdi) + movq %r15, 80(%rdi) + movq %rbx, 88(%rdi) + cmpq %rdi, %rsi + jne L_end_3072_sqr_avx2_12 + vmovdqu (%rbp), %xmm0 + vmovups %xmm0, (%rdi) + vmovdqu 16(%rbp), %xmm0 + vmovups %xmm0, 16(%rdi) + vmovdqu 32(%rbp), %xmm0 + vmovups %xmm0, 32(%rdi) + movq 48(%rbp), %rax + movq %rax, 48(%rdi) +L_end_3072_sqr_avx2_12: + addq $96, %rsp + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + repz retq +#ifndef __APPLE__ +.size sp_3072_sqr_avx2_12,.-sp_3072_sqr_avx2_12 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_add_12 +.type sp_3072_add_12,@function +.align 16 +sp_3072_add_12: +#else +.globl _sp_3072_add_12 +.p2align 4 +_sp_3072_add_12: +#endif /* __APPLE__ */ + # Add + movq (%rsi), %rcx + xorq %rax, %rax + addq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + adcq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + adcq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + adcq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + adcq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + adcq 40(%rdx), %r8 + movq 48(%rsi), %rcx + movq %r8, 40(%rdi) + adcq 48(%rdx), %rcx + movq 56(%rsi), %r8 + movq %rcx, 48(%rdi) + adcq 56(%rdx), %r8 + movq 64(%rsi), %rcx + movq %r8, 56(%rdi) + adcq 64(%rdx), %rcx + movq 72(%rsi), %r8 + movq %rcx, 64(%rdi) + adcq 72(%rdx), %r8 + movq 80(%rsi), %rcx + movq %r8, 72(%rdi) + adcq 80(%rdx), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%rdi) + adcq 88(%rdx), %r8 + movq %r8, 88(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_add_12,.-sp_3072_add_12 +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sub_in_place_24 +.type sp_3072_sub_in_place_24,@function +.align 16 +sp_3072_sub_in_place_24: +#else +.globl _sp_3072_sub_in_place_24 +.p2align 4 +_sp_3072_sub_in_place_24: +#endif /* __APPLE__ */ + movq (%rdi), %rdx + xorq %rax, %rax + subq (%rsi), %rdx + movq 8(%rdi), %rcx + movq %rdx, (%rdi) + sbbq 8(%rsi), %rcx + movq 16(%rdi), %rdx + movq %rcx, 8(%rdi) + sbbq 16(%rsi), %rdx + movq 24(%rdi), %rcx + movq %rdx, 16(%rdi) + sbbq 24(%rsi), %rcx + movq 32(%rdi), %rdx + movq %rcx, 24(%rdi) + sbbq 32(%rsi), %rdx + movq 40(%rdi), %rcx + movq %rdx, 32(%rdi) + sbbq 40(%rsi), %rcx + movq 48(%rdi), %rdx + movq %rcx, 40(%rdi) + sbbq 48(%rsi), %rdx + movq 56(%rdi), %rcx + movq %rdx, 48(%rdi) + sbbq 56(%rsi), %rcx + movq 64(%rdi), %rdx + movq %rcx, 56(%rdi) + sbbq 64(%rsi), %rdx + movq 72(%rdi), %rcx + movq %rdx, 64(%rdi) + sbbq 72(%rsi), %rcx + movq 80(%rdi), %rdx + movq %rcx, 72(%rdi) + sbbq 80(%rsi), %rdx + movq 88(%rdi), %rcx + movq %rdx, 80(%rdi) + sbbq 88(%rsi), %rcx + movq 96(%rdi), %rdx + movq %rcx, 88(%rdi) + sbbq 96(%rsi), %rdx + movq 104(%rdi), %rcx + movq %rdx, 96(%rdi) + sbbq 104(%rsi), %rcx + movq 112(%rdi), %rdx + movq %rcx, 104(%rdi) + sbbq 112(%rsi), %rdx + movq 120(%rdi), %rcx + movq %rdx, 112(%rdi) + sbbq 120(%rsi), %rcx + movq 128(%rdi), %rdx + movq %rcx, 120(%rdi) + sbbq 128(%rsi), %rdx + movq 136(%rdi), %rcx + movq %rdx, 128(%rdi) + sbbq 136(%rsi), %rcx + movq 144(%rdi), %rdx + movq %rcx, 136(%rdi) + sbbq 144(%rsi), %rdx + movq 152(%rdi), %rcx + movq %rdx, 144(%rdi) + sbbq 152(%rsi), %rcx + movq 160(%rdi), %rdx + movq %rcx, 152(%rdi) + sbbq 160(%rsi), %rdx + movq 168(%rdi), %rcx + movq %rdx, 160(%rdi) + sbbq 168(%rsi), %rcx + movq 176(%rdi), %rdx + movq %rcx, 168(%rdi) + sbbq 176(%rsi), %rdx + movq 184(%rdi), %rcx + movq %rdx, 176(%rdi) + sbbq 184(%rsi), %rcx + movq %rcx, 184(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_sub_in_place_24,.-sp_3072_sub_in_place_24 +#endif /* __APPLE__ */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_add_24 +.type sp_3072_add_24,@function +.align 16 +sp_3072_add_24: +#else +.globl _sp_3072_add_24 +.p2align 4 +_sp_3072_add_24: +#endif /* __APPLE__ */ + # Add + movq (%rsi), %rcx + xorq %rax, %rax + addq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + adcq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + adcq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + adcq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + adcq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + adcq 40(%rdx), %r8 + movq 48(%rsi), %rcx + movq %r8, 40(%rdi) + adcq 48(%rdx), %rcx + movq 56(%rsi), %r8 + movq %rcx, 48(%rdi) + adcq 56(%rdx), %r8 + movq 64(%rsi), %rcx + movq %r8, 56(%rdi) + adcq 64(%rdx), %rcx + movq 72(%rsi), %r8 + movq %rcx, 64(%rdi) + adcq 72(%rdx), %r8 + movq 80(%rsi), %rcx + movq %r8, 72(%rdi) + adcq 80(%rdx), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%rdi) + adcq 88(%rdx), %r8 + movq 96(%rsi), %rcx + movq %r8, 88(%rdi) + adcq 96(%rdx), %rcx + movq 104(%rsi), %r8 + movq %rcx, 96(%rdi) + adcq 104(%rdx), %r8 + movq 112(%rsi), %rcx + movq %r8, 104(%rdi) + adcq 112(%rdx), %rcx + movq 120(%rsi), %r8 + movq %rcx, 112(%rdi) + adcq 120(%rdx), %r8 + movq 128(%rsi), %rcx + movq %r8, 120(%rdi) + adcq 128(%rdx), %rcx + movq 136(%rsi), %r8 + movq %rcx, 128(%rdi) + adcq 136(%rdx), %r8 + movq 144(%rsi), %rcx + movq %r8, 136(%rdi) + adcq 144(%rdx), %rcx + movq 152(%rsi), %r8 + movq %rcx, 144(%rdi) + adcq 152(%rdx), %r8 + movq 160(%rsi), %rcx + movq %r8, 152(%rdi) + adcq 160(%rdx), %rcx + movq 168(%rsi), %r8 + movq %rcx, 160(%rdi) + adcq 168(%rdx), %r8 + movq 176(%rsi), %rcx + movq %r8, 168(%rdi) + adcq 176(%rdx), %rcx + movq 184(%rsi), %r8 + movq %rcx, 176(%rdi) + adcq 184(%rdx), %r8 + movq %r8, 184(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_add_24,.-sp_3072_add_24 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_24 +.type sp_3072_mul_24,@function +.align 16 +sp_3072_mul_24: +#else +.globl _sp_3072_mul_24 +.p2align 4 +_sp_3072_mul_24: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + subq $616, %rsp + movq %rdi, 576(%rsp) + movq %rsi, 584(%rsp) + movq %rdx, 592(%rsp) + leaq 384(%rsp), %r10 + leaq 96(%rsi), %r12 + # Add + movq (%rsi), %rax + xorq %r13, %r13 + addq (%r12), %rax + movq 8(%rsi), %rcx + movq %rax, (%r10) + adcq 8(%r12), %rcx + movq 16(%rsi), %r8 + movq %rcx, 8(%r10) + adcq 16(%r12), %r8 + movq 24(%rsi), %rax + movq %r8, 16(%r10) + adcq 24(%r12), %rax + movq 32(%rsi), %rcx + movq %rax, 24(%r10) + adcq 32(%r12), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%r10) + adcq 40(%r12), %r8 + movq 48(%rsi), %rax + movq %r8, 40(%r10) + adcq 48(%r12), %rax + movq 56(%rsi), %rcx + movq %rax, 48(%r10) + adcq 56(%r12), %rcx + movq 64(%rsi), %r8 + movq %rcx, 56(%r10) + adcq 64(%r12), %r8 + movq 72(%rsi), %rax + movq %r8, 64(%r10) + adcq 72(%r12), %rax + movq 80(%rsi), %rcx + movq %rax, 72(%r10) + adcq 80(%r12), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%r10) + adcq 88(%r12), %r8 + movq %r8, 88(%r10) + adcq $0, %r13 + movq %r13, 600(%rsp) + leaq 480(%rsp), %r11 + leaq 96(%rdx), %r12 + # Add + movq (%rdx), %rax + xorq %r14, %r14 + addq (%r12), %rax + movq 8(%rdx), %rcx + movq %rax, (%r11) + adcq 8(%r12), %rcx + movq 16(%rdx), %r8 + movq %rcx, 8(%r11) + adcq 16(%r12), %r8 + movq 24(%rdx), %rax + movq %r8, 16(%r11) + adcq 24(%r12), %rax + movq 32(%rdx), %rcx + movq %rax, 24(%r11) + adcq 32(%r12), %rcx + movq 40(%rdx), %r8 + movq %rcx, 32(%r11) + adcq 40(%r12), %r8 + movq 48(%rdx), %rax + movq %r8, 40(%r11) + adcq 48(%r12), %rax + movq 56(%rdx), %rcx + movq %rax, 48(%r11) + adcq 56(%r12), %rcx + movq 64(%rdx), %r8 + movq %rcx, 56(%r11) + adcq 64(%r12), %r8 + movq 72(%rdx), %rax + movq %r8, 64(%r11) + adcq 72(%r12), %rax + movq 80(%rdx), %rcx + movq %rax, 72(%r11) + adcq 80(%r12), %rcx + movq 88(%rdx), %r8 + movq %rcx, 80(%r11) + adcq 88(%r12), %r8 + movq %r8, 88(%r11) + adcq $0, %r14 + movq %r14, 608(%rsp) + movq %r11, %rdx + movq %r10, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_3072_mul_12@plt +#else + callq _sp_3072_mul_12 +#endif /* __APPLE__ */ + movq 592(%rsp), %rdx + movq 584(%rsp), %rsi + leaq 192(%rsp), %rdi + addq $96, %rdx + addq $96, %rsi +#ifndef __APPLE__ + callq sp_3072_mul_12@plt +#else + callq _sp_3072_mul_12 +#endif /* __APPLE__ */ + movq 592(%rsp), %rdx + movq 584(%rsp), %rsi + movq 576(%rsp), %rdi +#ifndef __APPLE__ + callq sp_3072_mul_12@plt +#else + callq _sp_3072_mul_12 +#endif /* __APPLE__ */ + movq 600(%rsp), %r13 + movq 608(%rsp), %r14 + movq 576(%rsp), %r15 + movq %r13, %r9 + leaq 384(%rsp), %r10 + leaq 480(%rsp), %r11 + andq %r14, %r9 + negq %r13 + negq %r14 + addq $192, %r15 + movq (%r10), %rax + movq (%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, (%r10) + movq %rcx, (%r11) + movq 8(%r10), %rax + movq 8(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 8(%r10) + movq %rcx, 8(%r11) + movq 16(%r10), %rax + movq 16(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 16(%r10) + movq %rcx, 16(%r11) + movq 24(%r10), %rax + movq 24(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 24(%r10) + movq %rcx, 24(%r11) + movq 32(%r10), %rax + movq 32(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 32(%r10) + movq %rcx, 32(%r11) + movq 40(%r10), %rax + movq 40(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 40(%r10) + movq %rcx, 40(%r11) + movq 48(%r10), %rax + movq 48(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 48(%r10) + movq %rcx, 48(%r11) + movq 56(%r10), %rax + movq 56(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 56(%r10) + movq %rcx, 56(%r11) + movq 64(%r10), %rax + movq 64(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 64(%r10) + movq %rcx, 64(%r11) + movq 72(%r10), %rax + movq 72(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 72(%r10) + movq %rcx, 72(%r11) + movq 80(%r10), %rax + movq 80(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 80(%r10) + movq %rcx, 80(%r11) + movq 88(%r10), %rax + movq 88(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 88(%r10) + movq %rcx, 88(%r11) + movq (%r10), %rax + addq (%r11), %rax + movq 8(%r10), %rcx + movq %rax, (%r15) + adcq 8(%r11), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r15) + adcq 16(%r11), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r15) + adcq 24(%r11), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r15) + adcq 32(%r11), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r15) + adcq 40(%r11), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r15) + adcq 48(%r11), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r15) + adcq 56(%r11), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r15) + adcq 64(%r11), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r15) + adcq 72(%r11), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r15) + adcq 80(%r11), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r15) + adcq 88(%r11), %r8 + movq %r8, 88(%r15) + adcq $0, %r9 + leaq 192(%rsp), %r11 + movq %rsp, %r10 + movq (%r10), %rax + subq (%r11), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%r11), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%r11), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%r11), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%r11), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%r11), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%r11), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%r11), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%r11), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%r11), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%r11), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%r11), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%r11), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%r11), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%r11), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%r11), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%r11), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%r11), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%r11), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%r11), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%r11), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%r11), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%r11), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%r11), %r8 + movq %r8, 184(%r10) + sbbq $0, %r9 + movq (%r10), %rax + subq (%rdi), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%rdi), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%rdi), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%rdi), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%rdi), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%rdi), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%rdi), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%rdi), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%rdi), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%rdi), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%rdi), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%rdi), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%rdi), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%rdi), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%rdi), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%rdi), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%rdi), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%rdi), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%rdi), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%rdi), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%rdi), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%rdi), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%rdi), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%rdi), %r8 + movq %r8, 184(%r10) + sbbq $0, %r9 + subq $96, %r15 + # Add + movq (%r15), %rax + addq (%r10), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r10), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r10), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r10), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r10), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r10), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r10), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r10), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r10), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r10), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r10), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r10), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r10), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r10), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r10), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r10), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r10), %rcx + movq 136(%r15), %r8 + movq %rcx, 128(%r15) + adcq 136(%r10), %r8 + movq 144(%r15), %rax + movq %r8, 136(%r15) + adcq 144(%r10), %rax + movq 152(%r15), %rcx + movq %rax, 144(%r15) + adcq 152(%r10), %rcx + movq 160(%r15), %r8 + movq %rcx, 152(%r15) + adcq 160(%r10), %r8 + movq 168(%r15), %rax + movq %r8, 160(%r15) + adcq 168(%r10), %rax + movq 176(%r15), %rcx + movq %rax, 168(%r15) + adcq 176(%r10), %rcx + movq 184(%r15), %r8 + movq %rcx, 176(%r15) + adcq 184(%r10), %r8 + movq %r8, 184(%r15) + adcq $0, %r9 + movq %r9, 288(%rdi) + addq $96, %r15 + # Add + movq (%r15), %rax + addq (%r11), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r11), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r11), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r11), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r11), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r11), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r11), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r11), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r11), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r11), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r11), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r11), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r11), %rax + movq %rax, 96(%r15) + # Add to zero + movq 104(%r11), %rax + adcq $0, %rax + movq 112(%r11), %rcx + movq %rax, 104(%r15) + adcq $0, %rcx + movq 120(%r11), %r8 + movq %rcx, 112(%r15) + adcq $0, %r8 + movq 128(%r11), %rax + movq %r8, 120(%r15) + adcq $0, %rax + movq 136(%r11), %rcx + movq %rax, 128(%r15) + adcq $0, %rcx + movq 144(%r11), %r8 + movq %rcx, 136(%r15) + adcq $0, %r8 + movq 152(%r11), %rax + movq %r8, 144(%r15) + adcq $0, %rax + movq 160(%r11), %rcx + movq %rax, 152(%r15) + adcq $0, %rcx + movq 168(%r11), %r8 + movq %rcx, 160(%r15) + adcq $0, %r8 + movq 176(%r11), %rax + movq %r8, 168(%r15) + adcq $0, %rax + movq 184(%r11), %rcx + movq %rax, 176(%r15) + adcq $0, %rcx + movq %rcx, 184(%r15) + addq $616, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_24,.-sp_3072_mul_24 +#endif /* __APPLE__ */ +/* Add a to a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_dbl_12 +.type sp_3072_dbl_12,@function +.align 16 +sp_3072_dbl_12: +#else +.globl _sp_3072_dbl_12 +.p2align 4 +_sp_3072_dbl_12: +#endif /* __APPLE__ */ + movq (%rsi), %rdx + xorq %rax, %rax + addq %rdx, %rdx + movq 8(%rsi), %rcx + movq %rdx, (%rdi) + adcq %rcx, %rcx + movq 16(%rsi), %rdx + movq %rcx, 8(%rdi) + adcq %rdx, %rdx + movq 24(%rsi), %rcx + movq %rdx, 16(%rdi) + adcq %rcx, %rcx + movq 32(%rsi), %rdx + movq %rcx, 24(%rdi) + adcq %rdx, %rdx + movq 40(%rsi), %rcx + movq %rdx, 32(%rdi) + adcq %rcx, %rcx + movq 48(%rsi), %rdx + movq %rcx, 40(%rdi) + adcq %rdx, %rdx + movq 56(%rsi), %rcx + movq %rdx, 48(%rdi) + adcq %rcx, %rcx + movq 64(%rsi), %rdx + movq %rcx, 56(%rdi) + adcq %rdx, %rdx + movq 72(%rsi), %rcx + movq %rdx, 64(%rdi) + adcq %rcx, %rcx + movq 80(%rsi), %rdx + movq %rcx, 72(%rdi) + adcq %rdx, %rdx + movq 88(%rsi), %rcx + movq %rdx, 80(%rdi) + adcq %rcx, %rcx + movq %rcx, 88(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_dbl_12,.-sp_3072_dbl_12 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sqr_24 +.type sp_3072_sqr_24,@function +.align 16 +sp_3072_sqr_24: +#else +.globl _sp_3072_sqr_24 +.p2align 4 +_sp_3072_sqr_24: +#endif /* __APPLE__ */ + subq $504, %rsp + movq %rdi, 480(%rsp) + movq %rsi, 488(%rsp) + leaq 384(%rsp), %r8 + leaq 96(%rsi), %r9 + # Add + movq (%rsi), %rdx + xorq %rcx, %rcx + addq (%r9), %rdx + movq 8(%rsi), %rax + movq %rdx, (%r8) + adcq 8(%r9), %rax + movq 16(%rsi), %rdx + movq %rax, 8(%r8) + adcq 16(%r9), %rdx + movq 24(%rsi), %rax + movq %rdx, 16(%r8) + adcq 24(%r9), %rax + movq 32(%rsi), %rdx + movq %rax, 24(%r8) + adcq 32(%r9), %rdx + movq 40(%rsi), %rax + movq %rdx, 32(%r8) + adcq 40(%r9), %rax + movq 48(%rsi), %rdx + movq %rax, 40(%r8) + adcq 48(%r9), %rdx + movq 56(%rsi), %rax + movq %rdx, 48(%r8) + adcq 56(%r9), %rax + movq 64(%rsi), %rdx + movq %rax, 56(%r8) + adcq 64(%r9), %rdx + movq 72(%rsi), %rax + movq %rdx, 64(%r8) + adcq 72(%r9), %rax + movq 80(%rsi), %rdx + movq %rax, 72(%r8) + adcq 80(%r9), %rdx + movq 88(%rsi), %rax + movq %rdx, 80(%r8) + adcq 88(%r9), %rax + movq %rax, 88(%r8) + adcq $0, %rcx + movq %rcx, 496(%rsp) + movq %r8, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_3072_sqr_12@plt +#else + callq _sp_3072_sqr_12 +#endif /* __APPLE__ */ + movq 488(%rsp), %rsi + leaq 192(%rsp), %rdi + addq $96, %rsi +#ifndef __APPLE__ + callq sp_3072_sqr_12@plt +#else + callq _sp_3072_sqr_12 +#endif /* __APPLE__ */ + movq 488(%rsp), %rsi + movq 480(%rsp), %rdi +#ifndef __APPLE__ + callq sp_3072_sqr_12@plt +#else + callq _sp_3072_sqr_12 +#endif /* __APPLE__ */ + movq 496(%rsp), %r10 + movq %rdi, %r9 + leaq 384(%rsp), %r8 + movq %r10, %rcx + negq %r10 + addq $192, %r9 + movq (%r8), %rdx + movq 8(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, (%r9) + movq %rax, 8(%r9) + movq 16(%r8), %rdx + movq 24(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 16(%r9) + movq %rax, 24(%r9) + movq 32(%r8), %rdx + movq 40(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 32(%r9) + movq %rax, 40(%r9) + movq 48(%r8), %rdx + movq 56(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 48(%r9) + movq %rax, 56(%r9) + movq 64(%r8), %rdx + movq 72(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 64(%r9) + movq %rax, 72(%r9) + movq 80(%r8), %rdx + movq 88(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 80(%r9) + movq %rax, 88(%r9) + movq (%r9), %rdx + addq %rdx, %rdx + movq 8(%r9), %rax + movq %rdx, (%r9) + adcq %rax, %rax + movq 16(%r9), %rdx + movq %rax, 8(%r9) + adcq %rdx, %rdx + movq 24(%r9), %rax + movq %rdx, 16(%r9) + adcq %rax, %rax + movq 32(%r9), %rdx + movq %rax, 24(%r9) + adcq %rdx, %rdx + movq 40(%r9), %rax + movq %rdx, 32(%r9) + adcq %rax, %rax + movq 48(%r9), %rdx + movq %rax, 40(%r9) + adcq %rdx, %rdx + movq 56(%r9), %rax + movq %rdx, 48(%r9) + adcq %rax, %rax + movq 64(%r9), %rdx + movq %rax, 56(%r9) + adcq %rdx, %rdx + movq 72(%r9), %rax + movq %rdx, 64(%r9) + adcq %rax, %rax + movq 80(%r9), %rdx + movq %rax, 72(%r9) + adcq %rdx, %rdx + movq 88(%r9), %rax + movq %rdx, 80(%r9) + adcq %rax, %rax + movq %rax, 88(%r9) + adcq $0, %rcx + leaq 192(%rsp), %rsi + movq %rsp, %r8 + movq (%r8), %rdx + subq (%rsi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rsi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rsi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rsi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rsi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rsi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rsi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rsi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rsi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rsi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rsi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rsi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rsi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rsi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rsi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rsi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rsi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rsi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rsi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rsi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rsi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rsi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rsi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rsi), %rax + movq %rax, 184(%r8) + sbbq $0, %rcx + movq (%r8), %rdx + subq (%rdi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rdi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rdi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rdi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rdi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rdi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rdi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rdi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rdi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rdi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rdi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rdi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rdi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rdi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rdi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rdi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rdi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rdi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rdi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rdi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rdi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rdi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rdi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rdi), %rax + movq %rax, 184(%r8) + sbbq $0, %rcx + subq $96, %r9 + # Add in place + movq (%r9), %rdx + addq (%r8), %rdx + movq 8(%r9), %rax + movq %rdx, (%r9) + adcq 8(%r8), %rax + movq 16(%r9), %rdx + movq %rax, 8(%r9) + adcq 16(%r8), %rdx + movq 24(%r9), %rax + movq %rdx, 16(%r9) + adcq 24(%r8), %rax + movq 32(%r9), %rdx + movq %rax, 24(%r9) + adcq 32(%r8), %rdx + movq 40(%r9), %rax + movq %rdx, 32(%r9) + adcq 40(%r8), %rax + movq 48(%r9), %rdx + movq %rax, 40(%r9) + adcq 48(%r8), %rdx + movq 56(%r9), %rax + movq %rdx, 48(%r9) + adcq 56(%r8), %rax + movq 64(%r9), %rdx + movq %rax, 56(%r9) + adcq 64(%r8), %rdx + movq 72(%r9), %rax + movq %rdx, 64(%r9) + adcq 72(%r8), %rax + movq 80(%r9), %rdx + movq %rax, 72(%r9) + adcq 80(%r8), %rdx + movq 88(%r9), %rax + movq %rdx, 80(%r9) + adcq 88(%r8), %rax + movq 96(%r9), %rdx + movq %rax, 88(%r9) + adcq 96(%r8), %rdx + movq 104(%r9), %rax + movq %rdx, 96(%r9) + adcq 104(%r8), %rax + movq 112(%r9), %rdx + movq %rax, 104(%r9) + adcq 112(%r8), %rdx + movq 120(%r9), %rax + movq %rdx, 112(%r9) + adcq 120(%r8), %rax + movq 128(%r9), %rdx + movq %rax, 120(%r9) + adcq 128(%r8), %rdx + movq 136(%r9), %rax + movq %rdx, 128(%r9) + adcq 136(%r8), %rax + movq 144(%r9), %rdx + movq %rax, 136(%r9) + adcq 144(%r8), %rdx + movq 152(%r9), %rax + movq %rdx, 144(%r9) + adcq 152(%r8), %rax + movq 160(%r9), %rdx + movq %rax, 152(%r9) + adcq 160(%r8), %rdx + movq 168(%r9), %rax + movq %rdx, 160(%r9) + adcq 168(%r8), %rax + movq 176(%r9), %rdx + movq %rax, 168(%r9) + adcq 176(%r8), %rdx + movq 184(%r9), %rax + movq %rdx, 176(%r9) + adcq 184(%r8), %rax + movq %rax, 184(%r9) + adcq $0, %rcx + movq %rcx, 288(%rdi) + # Add in place + movq 96(%r9), %rdx + addq (%rsi), %rdx + movq 104(%r9), %rax + movq %rdx, 96(%r9) + adcq 8(%rsi), %rax + movq 112(%r9), %rdx + movq %rax, 104(%r9) + adcq 16(%rsi), %rdx + movq 120(%r9), %rax + movq %rdx, 112(%r9) + adcq 24(%rsi), %rax + movq 128(%r9), %rdx + movq %rax, 120(%r9) + adcq 32(%rsi), %rdx + movq 136(%r9), %rax + movq %rdx, 128(%r9) + adcq 40(%rsi), %rax + movq 144(%r9), %rdx + movq %rax, 136(%r9) + adcq 48(%rsi), %rdx + movq 152(%r9), %rax + movq %rdx, 144(%r9) + adcq 56(%rsi), %rax + movq 160(%r9), %rdx + movq %rax, 152(%r9) + adcq 64(%rsi), %rdx + movq 168(%r9), %rax + movq %rdx, 160(%r9) + adcq 72(%rsi), %rax + movq 176(%r9), %rdx + movq %rax, 168(%r9) + adcq 80(%rsi), %rdx + movq 184(%r9), %rax + movq %rdx, 176(%r9) + adcq 88(%rsi), %rax + movq 192(%r9), %rdx + movq %rax, 184(%r9) + adcq 96(%rsi), %rdx + movq %rdx, 192(%r9) + # Add to zero + movq 104(%rsi), %rdx + adcq $0, %rdx + movq 112(%rsi), %rax + movq %rdx, 200(%r9) + adcq $0, %rax + movq 120(%rsi), %rdx + movq %rax, 208(%r9) + adcq $0, %rdx + movq 128(%rsi), %rax + movq %rdx, 216(%r9) + adcq $0, %rax + movq 136(%rsi), %rdx + movq %rax, 224(%r9) + adcq $0, %rdx + movq 144(%rsi), %rax + movq %rdx, 232(%r9) + adcq $0, %rax + movq 152(%rsi), %rdx + movq %rax, 240(%r9) + adcq $0, %rdx + movq 160(%rsi), %rax + movq %rdx, 248(%r9) + adcq $0, %rax + movq 168(%rsi), %rdx + movq %rax, 256(%r9) + adcq $0, %rdx + movq 176(%rsi), %rax + movq %rdx, 264(%r9) + adcq $0, %rax + movq 184(%rsi), %rdx + movq %rax, 272(%r9) + adcq $0, %rdx + movq %rdx, 280(%r9) + addq $504, %rsp + repz retq +#ifndef __APPLE__ +.size sp_3072_sqr_24,.-sp_3072_sqr_24 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_avx2_24 +.type sp_3072_mul_avx2_24,@function +.align 16 +sp_3072_mul_avx2_24: +#else +.globl _sp_3072_mul_avx2_24 +.p2align 4 +_sp_3072_mul_avx2_24: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + subq $616, %rsp + movq %rdi, 576(%rsp) + movq %rsi, 584(%rsp) + movq %rdx, 592(%rsp) + leaq 384(%rsp), %r10 + leaq 96(%rsi), %r12 + # Add + movq (%rsi), %rax + xorq %r13, %r13 + addq (%r12), %rax + movq 8(%rsi), %rcx + movq %rax, (%r10) + adcq 8(%r12), %rcx + movq 16(%rsi), %r8 + movq %rcx, 8(%r10) + adcq 16(%r12), %r8 + movq 24(%rsi), %rax + movq %r8, 16(%r10) + adcq 24(%r12), %rax + movq 32(%rsi), %rcx + movq %rax, 24(%r10) + adcq 32(%r12), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%r10) + adcq 40(%r12), %r8 + movq 48(%rsi), %rax + movq %r8, 40(%r10) + adcq 48(%r12), %rax + movq 56(%rsi), %rcx + movq %rax, 48(%r10) + adcq 56(%r12), %rcx + movq 64(%rsi), %r8 + movq %rcx, 56(%r10) + adcq 64(%r12), %r8 + movq 72(%rsi), %rax + movq %r8, 64(%r10) + adcq 72(%r12), %rax + movq 80(%rsi), %rcx + movq %rax, 72(%r10) + adcq 80(%r12), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%r10) + adcq 88(%r12), %r8 + movq %r8, 88(%r10) + adcq $0, %r13 + movq %r13, 600(%rsp) + leaq 480(%rsp), %r11 + leaq 96(%rdx), %r12 + # Add + movq (%rdx), %rax + xorq %r14, %r14 + addq (%r12), %rax + movq 8(%rdx), %rcx + movq %rax, (%r11) + adcq 8(%r12), %rcx + movq 16(%rdx), %r8 + movq %rcx, 8(%r11) + adcq 16(%r12), %r8 + movq 24(%rdx), %rax + movq %r8, 16(%r11) + adcq 24(%r12), %rax + movq 32(%rdx), %rcx + movq %rax, 24(%r11) + adcq 32(%r12), %rcx + movq 40(%rdx), %r8 + movq %rcx, 32(%r11) + adcq 40(%r12), %r8 + movq 48(%rdx), %rax + movq %r8, 40(%r11) + adcq 48(%r12), %rax + movq 56(%rdx), %rcx + movq %rax, 48(%r11) + adcq 56(%r12), %rcx + movq 64(%rdx), %r8 + movq %rcx, 56(%r11) + adcq 64(%r12), %r8 + movq 72(%rdx), %rax + movq %r8, 64(%r11) + adcq 72(%r12), %rax + movq 80(%rdx), %rcx + movq %rax, 72(%r11) + adcq 80(%r12), %rcx + movq 88(%rdx), %r8 + movq %rcx, 80(%r11) + adcq 88(%r12), %r8 + movq %r8, 88(%r11) + adcq $0, %r14 + movq %r14, 608(%rsp) + movq %r11, %rdx + movq %r10, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_3072_mul_avx2_12@plt +#else + callq _sp_3072_mul_avx2_12 +#endif /* __APPLE__ */ + movq 592(%rsp), %rdx + movq 584(%rsp), %rsi + leaq 192(%rsp), %rdi + addq $96, %rdx + addq $96, %rsi +#ifndef __APPLE__ + callq sp_3072_mul_avx2_12@plt +#else + callq _sp_3072_mul_avx2_12 +#endif /* __APPLE__ */ + movq 592(%rsp), %rdx + movq 584(%rsp), %rsi + movq 576(%rsp), %rdi +#ifndef __APPLE__ + callq sp_3072_mul_avx2_12@plt +#else + callq _sp_3072_mul_avx2_12 +#endif /* __APPLE__ */ + movq 600(%rsp), %r13 + movq 608(%rsp), %r14 + movq 576(%rsp), %r15 + movq %r13, %r9 + leaq 384(%rsp), %r10 + leaq 480(%rsp), %r11 + andq %r14, %r9 + negq %r13 + negq %r14 + addq $192, %r15 + movq (%r10), %rax + movq (%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + addq %rcx, %rax + movq 8(%r10), %rcx + movq 8(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, (%r15) + adcq %r8, %rcx + movq 16(%r10), %r8 + movq 16(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 8(%r15) + adcq %rax, %r8 + movq 24(%r10), %rax + movq 24(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 16(%r15) + adcq %rcx, %rax + movq 32(%r10), %rcx + movq 32(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 24(%r15) + adcq %r8, %rcx + movq 40(%r10), %r8 + movq 40(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 32(%r15) + adcq %rax, %r8 + movq 48(%r10), %rax + movq 48(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 40(%r15) + adcq %rcx, %rax + movq 56(%r10), %rcx + movq 56(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 48(%r15) + adcq %r8, %rcx + movq 64(%r10), %r8 + movq 64(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 56(%r15) + adcq %rax, %r8 + movq 72(%r10), %rax + movq 72(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 64(%r15) + adcq %rcx, %rax + movq 80(%r10), %rcx + movq 80(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 72(%r15) + adcq %r8, %rcx + movq 88(%r10), %r8 + movq 88(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 80(%r15) + adcq %rax, %r8 + movq %r8, 88(%r15) + adcq $0, %r9 + leaq 192(%rsp), %r11 + movq %rsp, %r10 + movq (%r10), %rax + subq (%r11), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%r11), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%r11), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%r11), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%r11), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%r11), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%r11), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%r11), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%r11), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%r11), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%r11), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%r11), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%r11), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%r11), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%r11), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%r11), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%r11), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%r11), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%r11), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%r11), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%r11), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%r11), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%r11), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%r11), %r8 + movq %r8, 184(%r10) + sbbq $0, %r9 + movq (%r10), %rax + subq (%rdi), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%rdi), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%rdi), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%rdi), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%rdi), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%rdi), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%rdi), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%rdi), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%rdi), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%rdi), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%rdi), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%rdi), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%rdi), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%rdi), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%rdi), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%rdi), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%rdi), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%rdi), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%rdi), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%rdi), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%rdi), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%rdi), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%rdi), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%rdi), %r8 + movq %r8, 184(%r10) + sbbq $0, %r9 + subq $96, %r15 + # Add + movq (%r15), %rax + addq (%r10), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r10), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r10), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r10), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r10), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r10), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r10), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r10), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r10), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r10), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r10), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r10), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r10), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r10), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r10), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r10), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r10), %rcx + movq 136(%r15), %r8 + movq %rcx, 128(%r15) + adcq 136(%r10), %r8 + movq 144(%r15), %rax + movq %r8, 136(%r15) + adcq 144(%r10), %rax + movq 152(%r15), %rcx + movq %rax, 144(%r15) + adcq 152(%r10), %rcx + movq 160(%r15), %r8 + movq %rcx, 152(%r15) + adcq 160(%r10), %r8 + movq 168(%r15), %rax + movq %r8, 160(%r15) + adcq 168(%r10), %rax + movq 176(%r15), %rcx + movq %rax, 168(%r15) + adcq 176(%r10), %rcx + movq 184(%r15), %r8 + movq %rcx, 176(%r15) + adcq 184(%r10), %r8 + movq %r8, 184(%r15) + adcq $0, %r9 + movq %r9, 288(%rdi) + addq $96, %r15 + # Add + movq (%r15), %rax + addq (%r11), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r11), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r11), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r11), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r11), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r11), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r11), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r11), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r11), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r11), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r11), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r11), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r11), %rax + movq %rax, 96(%r15) + # Add to zero + movq 104(%r11), %rax + adcq $0, %rax + movq 112(%r11), %rcx + movq %rax, 104(%r15) + adcq $0, %rcx + movq 120(%r11), %r8 + movq %rcx, 112(%r15) + adcq $0, %r8 + movq 128(%r11), %rax + movq %r8, 120(%r15) + adcq $0, %rax + movq 136(%r11), %rcx + movq %rax, 128(%r15) + adcq $0, %rcx + movq 144(%r11), %r8 + movq %rcx, 136(%r15) + adcq $0, %r8 + movq 152(%r11), %rax + movq %r8, 144(%r15) + adcq $0, %rax + movq 160(%r11), %rcx + movq %rax, 152(%r15) + adcq $0, %rcx + movq 168(%r11), %r8 + movq %rcx, 160(%r15) + adcq $0, %r8 + movq 176(%r11), %rax + movq %r8, 168(%r15) + adcq $0, %rax + movq 184(%r11), %rcx + movq %rax, 176(%r15) + adcq $0, %rcx + movq %rcx, 184(%r15) + addq $616, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_avx2_24,.-sp_3072_mul_avx2_24 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sqr_avx2_24 +.type sp_3072_sqr_avx2_24,@function +.align 16 +sp_3072_sqr_avx2_24: +#else +.globl _sp_3072_sqr_avx2_24 +.p2align 4 +_sp_3072_sqr_avx2_24: +#endif /* __APPLE__ */ + subq $504, %rsp + movq %rdi, 480(%rsp) + movq %rsi, 488(%rsp) + leaq 384(%rsp), %r8 + leaq 96(%rsi), %r9 + # Add + movq (%rsi), %rdx + xorq %rcx, %rcx + addq (%r9), %rdx + movq 8(%rsi), %rax + movq %rdx, (%r8) + adcq 8(%r9), %rax + movq 16(%rsi), %rdx + movq %rax, 8(%r8) + adcq 16(%r9), %rdx + movq 24(%rsi), %rax + movq %rdx, 16(%r8) + adcq 24(%r9), %rax + movq 32(%rsi), %rdx + movq %rax, 24(%r8) + adcq 32(%r9), %rdx + movq 40(%rsi), %rax + movq %rdx, 32(%r8) + adcq 40(%r9), %rax + movq 48(%rsi), %rdx + movq %rax, 40(%r8) + adcq 48(%r9), %rdx + movq 56(%rsi), %rax + movq %rdx, 48(%r8) + adcq 56(%r9), %rax + movq 64(%rsi), %rdx + movq %rax, 56(%r8) + adcq 64(%r9), %rdx + movq 72(%rsi), %rax + movq %rdx, 64(%r8) + adcq 72(%r9), %rax + movq 80(%rsi), %rdx + movq %rax, 72(%r8) + adcq 80(%r9), %rdx + movq 88(%rsi), %rax + movq %rdx, 80(%r8) + adcq 88(%r9), %rax + movq %rax, 88(%r8) + adcq $0, %rcx + movq %rcx, 496(%rsp) + movq %r8, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_3072_sqr_avx2_12@plt +#else + callq _sp_3072_sqr_avx2_12 +#endif /* __APPLE__ */ + movq 488(%rsp), %rsi + leaq 192(%rsp), %rdi + addq $96, %rsi +#ifndef __APPLE__ + callq sp_3072_sqr_avx2_12@plt +#else + callq _sp_3072_sqr_avx2_12 +#endif /* __APPLE__ */ + movq 488(%rsp), %rsi + movq 480(%rsp), %rdi +#ifndef __APPLE__ + callq sp_3072_sqr_avx2_12@plt +#else + callq _sp_3072_sqr_avx2_12 +#endif /* __APPLE__ */ + movq 496(%rsp), %r10 + movq %rdi, %r9 + leaq 384(%rsp), %r8 + movq %r10, %rcx + negq %r10 + addq $192, %r9 + movq (%r8), %rdx + pextq %r10, %rdx, %rdx + addq %rdx, %rdx + movq 8(%r8), %rax + movq %rdx, (%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 16(%r8), %rdx + movq %rax, 8(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 32(%r8), %rdx + movq %rax, 24(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 48(%r8), %rdx + movq %rax, 40(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 64(%r8), %rdx + movq %rax, 56(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 80(%r8), %rdx + movq %rax, 72(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq %rax, 88(%r9) + adcq $0, %rcx + leaq 192(%rsp), %rsi + movq %rsp, %r8 + movq (%r8), %rdx + subq (%rsi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rsi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rsi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rsi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rsi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rsi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rsi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rsi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rsi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rsi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rsi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rsi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rsi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rsi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rsi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rsi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rsi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rsi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rsi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rsi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rsi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rsi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rsi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rsi), %rax + movq %rax, 184(%r8) + sbbq $0, %rcx + movq (%r8), %rdx + subq (%rdi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rdi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rdi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rdi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rdi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rdi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rdi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rdi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rdi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rdi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rdi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rdi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rdi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rdi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rdi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rdi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rdi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rdi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rdi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rdi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rdi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rdi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rdi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rdi), %rax + movq %rax, 184(%r8) + sbbq $0, %rcx + subq $96, %r9 + # Add in place + movq (%r9), %rdx + addq (%r8), %rdx + movq 8(%r9), %rax + movq %rdx, (%r9) + adcq 8(%r8), %rax + movq 16(%r9), %rdx + movq %rax, 8(%r9) + adcq 16(%r8), %rdx + movq 24(%r9), %rax + movq %rdx, 16(%r9) + adcq 24(%r8), %rax + movq 32(%r9), %rdx + movq %rax, 24(%r9) + adcq 32(%r8), %rdx + movq 40(%r9), %rax + movq %rdx, 32(%r9) + adcq 40(%r8), %rax + movq 48(%r9), %rdx + movq %rax, 40(%r9) + adcq 48(%r8), %rdx + movq 56(%r9), %rax + movq %rdx, 48(%r9) + adcq 56(%r8), %rax + movq 64(%r9), %rdx + movq %rax, 56(%r9) + adcq 64(%r8), %rdx + movq 72(%r9), %rax + movq %rdx, 64(%r9) + adcq 72(%r8), %rax + movq 80(%r9), %rdx + movq %rax, 72(%r9) + adcq 80(%r8), %rdx + movq 88(%r9), %rax + movq %rdx, 80(%r9) + adcq 88(%r8), %rax + movq 96(%r9), %rdx + movq %rax, 88(%r9) + adcq 96(%r8), %rdx + movq 104(%r9), %rax + movq %rdx, 96(%r9) + adcq 104(%r8), %rax + movq 112(%r9), %rdx + movq %rax, 104(%r9) + adcq 112(%r8), %rdx + movq 120(%r9), %rax + movq %rdx, 112(%r9) + adcq 120(%r8), %rax + movq 128(%r9), %rdx + movq %rax, 120(%r9) + adcq 128(%r8), %rdx + movq 136(%r9), %rax + movq %rdx, 128(%r9) + adcq 136(%r8), %rax + movq 144(%r9), %rdx + movq %rax, 136(%r9) + adcq 144(%r8), %rdx + movq 152(%r9), %rax + movq %rdx, 144(%r9) + adcq 152(%r8), %rax + movq 160(%r9), %rdx + movq %rax, 152(%r9) + adcq 160(%r8), %rdx + movq 168(%r9), %rax + movq %rdx, 160(%r9) + adcq 168(%r8), %rax + movq 176(%r9), %rdx + movq %rax, 168(%r9) + adcq 176(%r8), %rdx + movq 184(%r9), %rax + movq %rdx, 176(%r9) + adcq 184(%r8), %rax + movq %rax, 184(%r9) + adcq $0, %rcx + movq %rcx, 288(%rdi) + # Add in place + movq 96(%r9), %rdx + addq (%rsi), %rdx + movq 104(%r9), %rax + movq %rdx, 96(%r9) + adcq 8(%rsi), %rax + movq 112(%r9), %rdx + movq %rax, 104(%r9) + adcq 16(%rsi), %rdx + movq 120(%r9), %rax + movq %rdx, 112(%r9) + adcq 24(%rsi), %rax + movq 128(%r9), %rdx + movq %rax, 120(%r9) + adcq 32(%rsi), %rdx + movq 136(%r9), %rax + movq %rdx, 128(%r9) + adcq 40(%rsi), %rax + movq 144(%r9), %rdx + movq %rax, 136(%r9) + adcq 48(%rsi), %rdx + movq 152(%r9), %rax + movq %rdx, 144(%r9) + adcq 56(%rsi), %rax + movq 160(%r9), %rdx + movq %rax, 152(%r9) + adcq 64(%rsi), %rdx + movq 168(%r9), %rax + movq %rdx, 160(%r9) + adcq 72(%rsi), %rax + movq 176(%r9), %rdx + movq %rax, 168(%r9) + adcq 80(%rsi), %rdx + movq 184(%r9), %rax + movq %rdx, 176(%r9) + adcq 88(%rsi), %rax + movq 192(%r9), %rdx + movq %rax, 184(%r9) + adcq 96(%rsi), %rdx + movq %rdx, 192(%r9) + # Add to zero + movq 104(%rsi), %rdx + adcq $0, %rdx + movq 112(%rsi), %rax + movq %rdx, 200(%r9) + adcq $0, %rax + movq 120(%rsi), %rdx + movq %rax, 208(%r9) + adcq $0, %rdx + movq 128(%rsi), %rax + movq %rdx, 216(%r9) + adcq $0, %rax + movq 136(%rsi), %rdx + movq %rax, 224(%r9) + adcq $0, %rdx + movq 144(%rsi), %rax + movq %rdx, 232(%r9) + adcq $0, %rax + movq 152(%rsi), %rdx + movq %rax, 240(%r9) + adcq $0, %rdx + movq 160(%rsi), %rax + movq %rdx, 248(%r9) + adcq $0, %rax + movq 168(%rsi), %rdx + movq %rax, 256(%r9) + adcq $0, %rdx + movq 176(%rsi), %rax + movq %rdx, 264(%r9) + adcq $0, %rax + movq 184(%rsi), %rdx + movq %rax, 272(%r9) + adcq $0, %rdx + movq %rdx, 280(%r9) + addq $504, %rsp + repz retq +#ifndef __APPLE__ +.size sp_3072_sqr_avx2_24,.-sp_3072_sqr_avx2_24 +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sub_in_place_48 +.type sp_3072_sub_in_place_48,@function +.align 16 +sp_3072_sub_in_place_48: +#else +.globl _sp_3072_sub_in_place_48 +.p2align 4 +_sp_3072_sub_in_place_48: +#endif /* __APPLE__ */ + movq (%rdi), %rdx + xorq %rax, %rax + subq (%rsi), %rdx + movq 8(%rdi), %rcx + movq %rdx, (%rdi) + sbbq 8(%rsi), %rcx + movq 16(%rdi), %rdx + movq %rcx, 8(%rdi) + sbbq 16(%rsi), %rdx + movq 24(%rdi), %rcx + movq %rdx, 16(%rdi) + sbbq 24(%rsi), %rcx + movq 32(%rdi), %rdx + movq %rcx, 24(%rdi) + sbbq 32(%rsi), %rdx + movq 40(%rdi), %rcx + movq %rdx, 32(%rdi) + sbbq 40(%rsi), %rcx + movq 48(%rdi), %rdx + movq %rcx, 40(%rdi) + sbbq 48(%rsi), %rdx + movq 56(%rdi), %rcx + movq %rdx, 48(%rdi) + sbbq 56(%rsi), %rcx + movq 64(%rdi), %rdx + movq %rcx, 56(%rdi) + sbbq 64(%rsi), %rdx + movq 72(%rdi), %rcx + movq %rdx, 64(%rdi) + sbbq 72(%rsi), %rcx + movq 80(%rdi), %rdx + movq %rcx, 72(%rdi) + sbbq 80(%rsi), %rdx + movq 88(%rdi), %rcx + movq %rdx, 80(%rdi) + sbbq 88(%rsi), %rcx + movq 96(%rdi), %rdx + movq %rcx, 88(%rdi) + sbbq 96(%rsi), %rdx + movq 104(%rdi), %rcx + movq %rdx, 96(%rdi) + sbbq 104(%rsi), %rcx + movq 112(%rdi), %rdx + movq %rcx, 104(%rdi) + sbbq 112(%rsi), %rdx + movq 120(%rdi), %rcx + movq %rdx, 112(%rdi) + sbbq 120(%rsi), %rcx + movq 128(%rdi), %rdx + movq %rcx, 120(%rdi) + sbbq 128(%rsi), %rdx + movq 136(%rdi), %rcx + movq %rdx, 128(%rdi) + sbbq 136(%rsi), %rcx + movq 144(%rdi), %rdx + movq %rcx, 136(%rdi) + sbbq 144(%rsi), %rdx + movq 152(%rdi), %rcx + movq %rdx, 144(%rdi) + sbbq 152(%rsi), %rcx + movq 160(%rdi), %rdx + movq %rcx, 152(%rdi) + sbbq 160(%rsi), %rdx + movq 168(%rdi), %rcx + movq %rdx, 160(%rdi) + sbbq 168(%rsi), %rcx + movq 176(%rdi), %rdx + movq %rcx, 168(%rdi) + sbbq 176(%rsi), %rdx + movq 184(%rdi), %rcx + movq %rdx, 176(%rdi) + sbbq 184(%rsi), %rcx + movq 192(%rdi), %rdx + movq %rcx, 184(%rdi) + sbbq 192(%rsi), %rdx + movq 200(%rdi), %rcx + movq %rdx, 192(%rdi) + sbbq 200(%rsi), %rcx + movq 208(%rdi), %rdx + movq %rcx, 200(%rdi) + sbbq 208(%rsi), %rdx + movq 216(%rdi), %rcx + movq %rdx, 208(%rdi) + sbbq 216(%rsi), %rcx + movq 224(%rdi), %rdx + movq %rcx, 216(%rdi) + sbbq 224(%rsi), %rdx + movq 232(%rdi), %rcx + movq %rdx, 224(%rdi) + sbbq 232(%rsi), %rcx + movq 240(%rdi), %rdx + movq %rcx, 232(%rdi) + sbbq 240(%rsi), %rdx + movq 248(%rdi), %rcx + movq %rdx, 240(%rdi) + sbbq 248(%rsi), %rcx + movq 256(%rdi), %rdx + movq %rcx, 248(%rdi) + sbbq 256(%rsi), %rdx + movq 264(%rdi), %rcx + movq %rdx, 256(%rdi) + sbbq 264(%rsi), %rcx + movq 272(%rdi), %rdx + movq %rcx, 264(%rdi) + sbbq 272(%rsi), %rdx + movq 280(%rdi), %rcx + movq %rdx, 272(%rdi) + sbbq 280(%rsi), %rcx + movq 288(%rdi), %rdx + movq %rcx, 280(%rdi) + sbbq 288(%rsi), %rdx + movq 296(%rdi), %rcx + movq %rdx, 288(%rdi) + sbbq 296(%rsi), %rcx + movq 304(%rdi), %rdx + movq %rcx, 296(%rdi) + sbbq 304(%rsi), %rdx + movq 312(%rdi), %rcx + movq %rdx, 304(%rdi) + sbbq 312(%rsi), %rcx + movq 320(%rdi), %rdx + movq %rcx, 312(%rdi) + sbbq 320(%rsi), %rdx + movq 328(%rdi), %rcx + movq %rdx, 320(%rdi) + sbbq 328(%rsi), %rcx + movq 336(%rdi), %rdx + movq %rcx, 328(%rdi) + sbbq 336(%rsi), %rdx + movq 344(%rdi), %rcx + movq %rdx, 336(%rdi) + sbbq 344(%rsi), %rcx + movq 352(%rdi), %rdx + movq %rcx, 344(%rdi) + sbbq 352(%rsi), %rdx + movq 360(%rdi), %rcx + movq %rdx, 352(%rdi) + sbbq 360(%rsi), %rcx + movq 368(%rdi), %rdx + movq %rcx, 360(%rdi) + sbbq 368(%rsi), %rdx + movq 376(%rdi), %rcx + movq %rdx, 368(%rdi) + sbbq 376(%rsi), %rcx + movq %rcx, 376(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_sub_in_place_48,.-sp_3072_sub_in_place_48 +#endif /* __APPLE__ */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_add_48 +.type sp_3072_add_48,@function +.align 16 +sp_3072_add_48: +#else +.globl _sp_3072_add_48 +.p2align 4 +_sp_3072_add_48: +#endif /* __APPLE__ */ + # Add + movq (%rsi), %rcx + xorq %rax, %rax + addq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + adcq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + adcq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + adcq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + adcq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + adcq 40(%rdx), %r8 + movq 48(%rsi), %rcx + movq %r8, 40(%rdi) + adcq 48(%rdx), %rcx + movq 56(%rsi), %r8 + movq %rcx, 48(%rdi) + adcq 56(%rdx), %r8 + movq 64(%rsi), %rcx + movq %r8, 56(%rdi) + adcq 64(%rdx), %rcx + movq 72(%rsi), %r8 + movq %rcx, 64(%rdi) + adcq 72(%rdx), %r8 + movq 80(%rsi), %rcx + movq %r8, 72(%rdi) + adcq 80(%rdx), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%rdi) + adcq 88(%rdx), %r8 + movq 96(%rsi), %rcx + movq %r8, 88(%rdi) + adcq 96(%rdx), %rcx + movq 104(%rsi), %r8 + movq %rcx, 96(%rdi) + adcq 104(%rdx), %r8 + movq 112(%rsi), %rcx + movq %r8, 104(%rdi) + adcq 112(%rdx), %rcx + movq 120(%rsi), %r8 + movq %rcx, 112(%rdi) + adcq 120(%rdx), %r8 + movq 128(%rsi), %rcx + movq %r8, 120(%rdi) + adcq 128(%rdx), %rcx + movq 136(%rsi), %r8 + movq %rcx, 128(%rdi) + adcq 136(%rdx), %r8 + movq 144(%rsi), %rcx + movq %r8, 136(%rdi) + adcq 144(%rdx), %rcx + movq 152(%rsi), %r8 + movq %rcx, 144(%rdi) + adcq 152(%rdx), %r8 + movq 160(%rsi), %rcx + movq %r8, 152(%rdi) + adcq 160(%rdx), %rcx + movq 168(%rsi), %r8 + movq %rcx, 160(%rdi) + adcq 168(%rdx), %r8 + movq 176(%rsi), %rcx + movq %r8, 168(%rdi) + adcq 176(%rdx), %rcx + movq 184(%rsi), %r8 + movq %rcx, 176(%rdi) + adcq 184(%rdx), %r8 + movq 192(%rsi), %rcx + movq %r8, 184(%rdi) + adcq 192(%rdx), %rcx + movq 200(%rsi), %r8 + movq %rcx, 192(%rdi) + adcq 200(%rdx), %r8 + movq 208(%rsi), %rcx + movq %r8, 200(%rdi) + adcq 208(%rdx), %rcx + movq 216(%rsi), %r8 + movq %rcx, 208(%rdi) + adcq 216(%rdx), %r8 + movq 224(%rsi), %rcx + movq %r8, 216(%rdi) + adcq 224(%rdx), %rcx + movq 232(%rsi), %r8 + movq %rcx, 224(%rdi) + adcq 232(%rdx), %r8 + movq 240(%rsi), %rcx + movq %r8, 232(%rdi) + adcq 240(%rdx), %rcx + movq 248(%rsi), %r8 + movq %rcx, 240(%rdi) + adcq 248(%rdx), %r8 + movq 256(%rsi), %rcx + movq %r8, 248(%rdi) + adcq 256(%rdx), %rcx + movq 264(%rsi), %r8 + movq %rcx, 256(%rdi) + adcq 264(%rdx), %r8 + movq 272(%rsi), %rcx + movq %r8, 264(%rdi) + adcq 272(%rdx), %rcx + movq 280(%rsi), %r8 + movq %rcx, 272(%rdi) + adcq 280(%rdx), %r8 + movq 288(%rsi), %rcx + movq %r8, 280(%rdi) + adcq 288(%rdx), %rcx + movq 296(%rsi), %r8 + movq %rcx, 288(%rdi) + adcq 296(%rdx), %r8 + movq 304(%rsi), %rcx + movq %r8, 296(%rdi) + adcq 304(%rdx), %rcx + movq 312(%rsi), %r8 + movq %rcx, 304(%rdi) + adcq 312(%rdx), %r8 + movq 320(%rsi), %rcx + movq %r8, 312(%rdi) + adcq 320(%rdx), %rcx + movq 328(%rsi), %r8 + movq %rcx, 320(%rdi) + adcq 328(%rdx), %r8 + movq 336(%rsi), %rcx + movq %r8, 328(%rdi) + adcq 336(%rdx), %rcx + movq 344(%rsi), %r8 + movq %rcx, 336(%rdi) + adcq 344(%rdx), %r8 + movq 352(%rsi), %rcx + movq %r8, 344(%rdi) + adcq 352(%rdx), %rcx + movq 360(%rsi), %r8 + movq %rcx, 352(%rdi) + adcq 360(%rdx), %r8 + movq 368(%rsi), %rcx + movq %r8, 360(%rdi) + adcq 368(%rdx), %rcx + movq 376(%rsi), %r8 + movq %rcx, 368(%rdi) + adcq 376(%rdx), %r8 + movq %r8, 376(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_add_48,.-sp_3072_add_48 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_48 +.type sp_3072_mul_48,@function +.align 16 +sp_3072_mul_48: +#else +.globl _sp_3072_mul_48 +.p2align 4 +_sp_3072_mul_48: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + subq $1192, %rsp + movq %rdi, 1152(%rsp) + movq %rsi, 1160(%rsp) + movq %rdx, 1168(%rsp) + leaq 768(%rsp), %r10 + leaq 192(%rsi), %r12 + # Add + movq (%rsi), %rax + xorq %r13, %r13 + addq (%r12), %rax + movq 8(%rsi), %rcx + movq %rax, (%r10) + adcq 8(%r12), %rcx + movq 16(%rsi), %r8 + movq %rcx, 8(%r10) + adcq 16(%r12), %r8 + movq 24(%rsi), %rax + movq %r8, 16(%r10) + adcq 24(%r12), %rax + movq 32(%rsi), %rcx + movq %rax, 24(%r10) + adcq 32(%r12), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%r10) + adcq 40(%r12), %r8 + movq 48(%rsi), %rax + movq %r8, 40(%r10) + adcq 48(%r12), %rax + movq 56(%rsi), %rcx + movq %rax, 48(%r10) + adcq 56(%r12), %rcx + movq 64(%rsi), %r8 + movq %rcx, 56(%r10) + adcq 64(%r12), %r8 + movq 72(%rsi), %rax + movq %r8, 64(%r10) + adcq 72(%r12), %rax + movq 80(%rsi), %rcx + movq %rax, 72(%r10) + adcq 80(%r12), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%r10) + adcq 88(%r12), %r8 + movq 96(%rsi), %rax + movq %r8, 88(%r10) + adcq 96(%r12), %rax + movq 104(%rsi), %rcx + movq %rax, 96(%r10) + adcq 104(%r12), %rcx + movq 112(%rsi), %r8 + movq %rcx, 104(%r10) + adcq 112(%r12), %r8 + movq 120(%rsi), %rax + movq %r8, 112(%r10) + adcq 120(%r12), %rax + movq 128(%rsi), %rcx + movq %rax, 120(%r10) + adcq 128(%r12), %rcx + movq 136(%rsi), %r8 + movq %rcx, 128(%r10) + adcq 136(%r12), %r8 + movq 144(%rsi), %rax + movq %r8, 136(%r10) + adcq 144(%r12), %rax + movq 152(%rsi), %rcx + movq %rax, 144(%r10) + adcq 152(%r12), %rcx + movq 160(%rsi), %r8 + movq %rcx, 152(%r10) + adcq 160(%r12), %r8 + movq 168(%rsi), %rax + movq %r8, 160(%r10) + adcq 168(%r12), %rax + movq 176(%rsi), %rcx + movq %rax, 168(%r10) + adcq 176(%r12), %rcx + movq 184(%rsi), %r8 + movq %rcx, 176(%r10) + adcq 184(%r12), %r8 + movq %r8, 184(%r10) + adcq $0, %r13 + movq %r13, 1176(%rsp) + leaq 960(%rsp), %r11 + leaq 192(%rdx), %r12 + # Add + movq (%rdx), %rax + xorq %r14, %r14 + addq (%r12), %rax + movq 8(%rdx), %rcx + movq %rax, (%r11) + adcq 8(%r12), %rcx + movq 16(%rdx), %r8 + movq %rcx, 8(%r11) + adcq 16(%r12), %r8 + movq 24(%rdx), %rax + movq %r8, 16(%r11) + adcq 24(%r12), %rax + movq 32(%rdx), %rcx + movq %rax, 24(%r11) + adcq 32(%r12), %rcx + movq 40(%rdx), %r8 + movq %rcx, 32(%r11) + adcq 40(%r12), %r8 + movq 48(%rdx), %rax + movq %r8, 40(%r11) + adcq 48(%r12), %rax + movq 56(%rdx), %rcx + movq %rax, 48(%r11) + adcq 56(%r12), %rcx + movq 64(%rdx), %r8 + movq %rcx, 56(%r11) + adcq 64(%r12), %r8 + movq 72(%rdx), %rax + movq %r8, 64(%r11) + adcq 72(%r12), %rax + movq 80(%rdx), %rcx + movq %rax, 72(%r11) + adcq 80(%r12), %rcx + movq 88(%rdx), %r8 + movq %rcx, 80(%r11) + adcq 88(%r12), %r8 + movq 96(%rdx), %rax + movq %r8, 88(%r11) + adcq 96(%r12), %rax + movq 104(%rdx), %rcx + movq %rax, 96(%r11) + adcq 104(%r12), %rcx + movq 112(%rdx), %r8 + movq %rcx, 104(%r11) + adcq 112(%r12), %r8 + movq 120(%rdx), %rax + movq %r8, 112(%r11) + adcq 120(%r12), %rax + movq 128(%rdx), %rcx + movq %rax, 120(%r11) + adcq 128(%r12), %rcx + movq 136(%rdx), %r8 + movq %rcx, 128(%r11) + adcq 136(%r12), %r8 + movq 144(%rdx), %rax + movq %r8, 136(%r11) + adcq 144(%r12), %rax + movq 152(%rdx), %rcx + movq %rax, 144(%r11) + adcq 152(%r12), %rcx + movq 160(%rdx), %r8 + movq %rcx, 152(%r11) + adcq 160(%r12), %r8 + movq 168(%rdx), %rax + movq %r8, 160(%r11) + adcq 168(%r12), %rax + movq 176(%rdx), %rcx + movq %rax, 168(%r11) + adcq 176(%r12), %rcx + movq 184(%rdx), %r8 + movq %rcx, 176(%r11) + adcq 184(%r12), %r8 + movq %r8, 184(%r11) + adcq $0, %r14 + movq %r14, 1184(%rsp) + movq %r11, %rdx + movq %r10, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_3072_mul_24@plt +#else + callq _sp_3072_mul_24 +#endif /* __APPLE__ */ + movq 1168(%rsp), %rdx + movq 1160(%rsp), %rsi + leaq 384(%rsp), %rdi + addq $192, %rdx + addq $192, %rsi +#ifndef __APPLE__ + callq sp_3072_mul_24@plt +#else + callq _sp_3072_mul_24 +#endif /* __APPLE__ */ + movq 1168(%rsp), %rdx + movq 1160(%rsp), %rsi + movq 1152(%rsp), %rdi +#ifndef __APPLE__ + callq sp_3072_mul_24@plt +#else + callq _sp_3072_mul_24 +#endif /* __APPLE__ */ + movq 1176(%rsp), %r13 + movq 1184(%rsp), %r14 + movq 1152(%rsp), %r15 + movq %r13, %r9 + leaq 768(%rsp), %r10 + leaq 960(%rsp), %r11 + andq %r14, %r9 + negq %r13 + negq %r14 + addq $384, %r15 + movq (%r10), %rax + movq (%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, (%r10) + movq %rcx, (%r11) + movq 8(%r10), %rax + movq 8(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 8(%r10) + movq %rcx, 8(%r11) + movq 16(%r10), %rax + movq 16(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 16(%r10) + movq %rcx, 16(%r11) + movq 24(%r10), %rax + movq 24(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 24(%r10) + movq %rcx, 24(%r11) + movq 32(%r10), %rax + movq 32(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 32(%r10) + movq %rcx, 32(%r11) + movq 40(%r10), %rax + movq 40(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 40(%r10) + movq %rcx, 40(%r11) + movq 48(%r10), %rax + movq 48(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 48(%r10) + movq %rcx, 48(%r11) + movq 56(%r10), %rax + movq 56(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 56(%r10) + movq %rcx, 56(%r11) + movq 64(%r10), %rax + movq 64(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 64(%r10) + movq %rcx, 64(%r11) + movq 72(%r10), %rax + movq 72(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 72(%r10) + movq %rcx, 72(%r11) + movq 80(%r10), %rax + movq 80(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 80(%r10) + movq %rcx, 80(%r11) + movq 88(%r10), %rax + movq 88(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 88(%r10) + movq %rcx, 88(%r11) + movq 96(%r10), %rax + movq 96(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 96(%r10) + movq %rcx, 96(%r11) + movq 104(%r10), %rax + movq 104(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 104(%r10) + movq %rcx, 104(%r11) + movq 112(%r10), %rax + movq 112(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 112(%r10) + movq %rcx, 112(%r11) + movq 120(%r10), %rax + movq 120(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 120(%r10) + movq %rcx, 120(%r11) + movq 128(%r10), %rax + movq 128(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 128(%r10) + movq %rcx, 128(%r11) + movq 136(%r10), %rax + movq 136(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 136(%r10) + movq %rcx, 136(%r11) + movq 144(%r10), %rax + movq 144(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 144(%r10) + movq %rcx, 144(%r11) + movq 152(%r10), %rax + movq 152(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 152(%r10) + movq %rcx, 152(%r11) + movq 160(%r10), %rax + movq 160(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 160(%r10) + movq %rcx, 160(%r11) + movq 168(%r10), %rax + movq 168(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 168(%r10) + movq %rcx, 168(%r11) + movq 176(%r10), %rax + movq 176(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 176(%r10) + movq %rcx, 176(%r11) + movq 184(%r10), %rax + movq 184(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 184(%r10) + movq %rcx, 184(%r11) + movq (%r10), %rax + addq (%r11), %rax + movq 8(%r10), %rcx + movq %rax, (%r15) + adcq 8(%r11), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r15) + adcq 16(%r11), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r15) + adcq 24(%r11), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r15) + adcq 32(%r11), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r15) + adcq 40(%r11), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r15) + adcq 48(%r11), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r15) + adcq 56(%r11), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r15) + adcq 64(%r11), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r15) + adcq 72(%r11), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r15) + adcq 80(%r11), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r15) + adcq 88(%r11), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r15) + adcq 96(%r11), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r15) + adcq 104(%r11), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r15) + adcq 112(%r11), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r15) + adcq 120(%r11), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r15) + adcq 128(%r11), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r15) + adcq 136(%r11), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r15) + adcq 144(%r11), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r15) + adcq 152(%r11), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r15) + adcq 160(%r11), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r15) + adcq 168(%r11), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r15) + adcq 176(%r11), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r15) + adcq 184(%r11), %r8 + movq %r8, 184(%r15) + adcq $0, %r9 + leaq 384(%rsp), %r11 + movq %rsp, %r10 + movq (%r10), %rax + subq (%r11), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%r11), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%r11), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%r11), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%r11), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%r11), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%r11), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%r11), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%r11), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%r11), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%r11), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%r11), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%r11), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%r11), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%r11), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%r11), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%r11), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%r11), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%r11), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%r11), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%r11), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%r11), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%r11), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%r11), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r10) + sbbq 192(%r11), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r10) + sbbq 200(%r11), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r10) + sbbq 208(%r11), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r10) + sbbq 216(%r11), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r10) + sbbq 224(%r11), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r10) + sbbq 232(%r11), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r10) + sbbq 240(%r11), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r10) + sbbq 248(%r11), %rcx + movq 256(%r10), %r8 + movq %rcx, 248(%r10) + sbbq 256(%r11), %r8 + movq 264(%r10), %rax + movq %r8, 256(%r10) + sbbq 264(%r11), %rax + movq 272(%r10), %rcx + movq %rax, 264(%r10) + sbbq 272(%r11), %rcx + movq 280(%r10), %r8 + movq %rcx, 272(%r10) + sbbq 280(%r11), %r8 + movq 288(%r10), %rax + movq %r8, 280(%r10) + sbbq 288(%r11), %rax + movq 296(%r10), %rcx + movq %rax, 288(%r10) + sbbq 296(%r11), %rcx + movq 304(%r10), %r8 + movq %rcx, 296(%r10) + sbbq 304(%r11), %r8 + movq 312(%r10), %rax + movq %r8, 304(%r10) + sbbq 312(%r11), %rax + movq 320(%r10), %rcx + movq %rax, 312(%r10) + sbbq 320(%r11), %rcx + movq 328(%r10), %r8 + movq %rcx, 320(%r10) + sbbq 328(%r11), %r8 + movq 336(%r10), %rax + movq %r8, 328(%r10) + sbbq 336(%r11), %rax + movq 344(%r10), %rcx + movq %rax, 336(%r10) + sbbq 344(%r11), %rcx + movq 352(%r10), %r8 + movq %rcx, 344(%r10) + sbbq 352(%r11), %r8 + movq 360(%r10), %rax + movq %r8, 352(%r10) + sbbq 360(%r11), %rax + movq 368(%r10), %rcx + movq %rax, 360(%r10) + sbbq 368(%r11), %rcx + movq 376(%r10), %r8 + movq %rcx, 368(%r10) + sbbq 376(%r11), %r8 + movq %r8, 376(%r10) + sbbq $0, %r9 + movq (%r10), %rax + subq (%rdi), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%rdi), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%rdi), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%rdi), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%rdi), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%rdi), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%rdi), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%rdi), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%rdi), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%rdi), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%rdi), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%rdi), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%rdi), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%rdi), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%rdi), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%rdi), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%rdi), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%rdi), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%rdi), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%rdi), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%rdi), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%rdi), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%rdi), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%rdi), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r10) + sbbq 192(%rdi), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r10) + sbbq 200(%rdi), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r10) + sbbq 208(%rdi), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r10) + sbbq 216(%rdi), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r10) + sbbq 224(%rdi), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r10) + sbbq 232(%rdi), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r10) + sbbq 240(%rdi), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r10) + sbbq 248(%rdi), %rcx + movq 256(%r10), %r8 + movq %rcx, 248(%r10) + sbbq 256(%rdi), %r8 + movq 264(%r10), %rax + movq %r8, 256(%r10) + sbbq 264(%rdi), %rax + movq 272(%r10), %rcx + movq %rax, 264(%r10) + sbbq 272(%rdi), %rcx + movq 280(%r10), %r8 + movq %rcx, 272(%r10) + sbbq 280(%rdi), %r8 + movq 288(%r10), %rax + movq %r8, 280(%r10) + sbbq 288(%rdi), %rax + movq 296(%r10), %rcx + movq %rax, 288(%r10) + sbbq 296(%rdi), %rcx + movq 304(%r10), %r8 + movq %rcx, 296(%r10) + sbbq 304(%rdi), %r8 + movq 312(%r10), %rax + movq %r8, 304(%r10) + sbbq 312(%rdi), %rax + movq 320(%r10), %rcx + movq %rax, 312(%r10) + sbbq 320(%rdi), %rcx + movq 328(%r10), %r8 + movq %rcx, 320(%r10) + sbbq 328(%rdi), %r8 + movq 336(%r10), %rax + movq %r8, 328(%r10) + sbbq 336(%rdi), %rax + movq 344(%r10), %rcx + movq %rax, 336(%r10) + sbbq 344(%rdi), %rcx + movq 352(%r10), %r8 + movq %rcx, 344(%r10) + sbbq 352(%rdi), %r8 + movq 360(%r10), %rax + movq %r8, 352(%r10) + sbbq 360(%rdi), %rax + movq 368(%r10), %rcx + movq %rax, 360(%r10) + sbbq 368(%rdi), %rcx + movq 376(%r10), %r8 + movq %rcx, 368(%r10) + sbbq 376(%rdi), %r8 + movq %r8, 376(%r10) + sbbq $0, %r9 + subq $192, %r15 + # Add + movq (%r15), %rax + addq (%r10), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r10), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r10), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r10), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r10), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r10), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r10), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r10), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r10), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r10), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r10), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r10), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r10), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r10), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r10), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r10), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r10), %rcx + movq 136(%r15), %r8 + movq %rcx, 128(%r15) + adcq 136(%r10), %r8 + movq 144(%r15), %rax + movq %r8, 136(%r15) + adcq 144(%r10), %rax + movq 152(%r15), %rcx + movq %rax, 144(%r15) + adcq 152(%r10), %rcx + movq 160(%r15), %r8 + movq %rcx, 152(%r15) + adcq 160(%r10), %r8 + movq 168(%r15), %rax + movq %r8, 160(%r15) + adcq 168(%r10), %rax + movq 176(%r15), %rcx + movq %rax, 168(%r15) + adcq 176(%r10), %rcx + movq 184(%r15), %r8 + movq %rcx, 176(%r15) + adcq 184(%r10), %r8 + movq 192(%r15), %rax + movq %r8, 184(%r15) + adcq 192(%r10), %rax + movq 200(%r15), %rcx + movq %rax, 192(%r15) + adcq 200(%r10), %rcx + movq 208(%r15), %r8 + movq %rcx, 200(%r15) + adcq 208(%r10), %r8 + movq 216(%r15), %rax + movq %r8, 208(%r15) + adcq 216(%r10), %rax + movq 224(%r15), %rcx + movq %rax, 216(%r15) + adcq 224(%r10), %rcx + movq 232(%r15), %r8 + movq %rcx, 224(%r15) + adcq 232(%r10), %r8 + movq 240(%r15), %rax + movq %r8, 232(%r15) + adcq 240(%r10), %rax + movq 248(%r15), %rcx + movq %rax, 240(%r15) + adcq 248(%r10), %rcx + movq 256(%r15), %r8 + movq %rcx, 248(%r15) + adcq 256(%r10), %r8 + movq 264(%r15), %rax + movq %r8, 256(%r15) + adcq 264(%r10), %rax + movq 272(%r15), %rcx + movq %rax, 264(%r15) + adcq 272(%r10), %rcx + movq 280(%r15), %r8 + movq %rcx, 272(%r15) + adcq 280(%r10), %r8 + movq 288(%r15), %rax + movq %r8, 280(%r15) + adcq 288(%r10), %rax + movq 296(%r15), %rcx + movq %rax, 288(%r15) + adcq 296(%r10), %rcx + movq 304(%r15), %r8 + movq %rcx, 296(%r15) + adcq 304(%r10), %r8 + movq 312(%r15), %rax + movq %r8, 304(%r15) + adcq 312(%r10), %rax + movq 320(%r15), %rcx + movq %rax, 312(%r15) + adcq 320(%r10), %rcx + movq 328(%r15), %r8 + movq %rcx, 320(%r15) + adcq 328(%r10), %r8 + movq 336(%r15), %rax + movq %r8, 328(%r15) + adcq 336(%r10), %rax + movq 344(%r15), %rcx + movq %rax, 336(%r15) + adcq 344(%r10), %rcx + movq 352(%r15), %r8 + movq %rcx, 344(%r15) + adcq 352(%r10), %r8 + movq 360(%r15), %rax + movq %r8, 352(%r15) + adcq 360(%r10), %rax + movq 368(%r15), %rcx + movq %rax, 360(%r15) + adcq 368(%r10), %rcx + movq 376(%r15), %r8 + movq %rcx, 368(%r15) + adcq 376(%r10), %r8 + movq %r8, 376(%r15) + adcq $0, %r9 + movq %r9, 576(%rdi) + addq $192, %r15 + # Add + movq (%r15), %rax + addq (%r11), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r11), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r11), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r11), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r11), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r11), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r11), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r11), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r11), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r11), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r11), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r11), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r11), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r11), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r11), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r11), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r11), %rcx + movq 136(%r15), %r8 + movq %rcx, 128(%r15) + adcq 136(%r11), %r8 + movq 144(%r15), %rax + movq %r8, 136(%r15) + adcq 144(%r11), %rax + movq 152(%r15), %rcx + movq %rax, 144(%r15) + adcq 152(%r11), %rcx + movq 160(%r15), %r8 + movq %rcx, 152(%r15) + adcq 160(%r11), %r8 + movq 168(%r15), %rax + movq %r8, 160(%r15) + adcq 168(%r11), %rax + movq 176(%r15), %rcx + movq %rax, 168(%r15) + adcq 176(%r11), %rcx + movq 184(%r15), %r8 + movq %rcx, 176(%r15) + adcq 184(%r11), %r8 + movq 192(%r15), %rax + movq %r8, 184(%r15) + adcq 192(%r11), %rax + movq %rax, 192(%r15) + # Add to zero + movq 200(%r11), %rax + adcq $0, %rax + movq 208(%r11), %rcx + movq %rax, 200(%r15) + adcq $0, %rcx + movq 216(%r11), %r8 + movq %rcx, 208(%r15) + adcq $0, %r8 + movq 224(%r11), %rax + movq %r8, 216(%r15) + adcq $0, %rax + movq 232(%r11), %rcx + movq %rax, 224(%r15) + adcq $0, %rcx + movq 240(%r11), %r8 + movq %rcx, 232(%r15) + adcq $0, %r8 + movq 248(%r11), %rax + movq %r8, 240(%r15) + adcq $0, %rax + movq 256(%r11), %rcx + movq %rax, 248(%r15) + adcq $0, %rcx + movq 264(%r11), %r8 + movq %rcx, 256(%r15) + adcq $0, %r8 + movq 272(%r11), %rax + movq %r8, 264(%r15) + adcq $0, %rax + movq 280(%r11), %rcx + movq %rax, 272(%r15) + adcq $0, %rcx + movq 288(%r11), %r8 + movq %rcx, 280(%r15) + adcq $0, %r8 + movq 296(%r11), %rax + movq %r8, 288(%r15) + adcq $0, %rax + movq 304(%r11), %rcx + movq %rax, 296(%r15) + adcq $0, %rcx + movq 312(%r11), %r8 + movq %rcx, 304(%r15) + adcq $0, %r8 + movq 320(%r11), %rax + movq %r8, 312(%r15) + adcq $0, %rax + movq 328(%r11), %rcx + movq %rax, 320(%r15) + adcq $0, %rcx + movq 336(%r11), %r8 + movq %rcx, 328(%r15) + adcq $0, %r8 + movq 344(%r11), %rax + movq %r8, 336(%r15) + adcq $0, %rax + movq 352(%r11), %rcx + movq %rax, 344(%r15) + adcq $0, %rcx + movq 360(%r11), %r8 + movq %rcx, 352(%r15) + adcq $0, %r8 + movq 368(%r11), %rax + movq %r8, 360(%r15) + adcq $0, %rax + movq 376(%r11), %rcx + movq %rax, 368(%r15) + adcq $0, %rcx + movq %rcx, 376(%r15) + addq $1192, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_48,.-sp_3072_mul_48 +#endif /* __APPLE__ */ +/* Add a to a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_dbl_24 +.type sp_3072_dbl_24,@function +.align 16 +sp_3072_dbl_24: +#else +.globl _sp_3072_dbl_24 +.p2align 4 +_sp_3072_dbl_24: +#endif /* __APPLE__ */ + movq (%rsi), %rdx + xorq %rax, %rax + addq %rdx, %rdx + movq 8(%rsi), %rcx + movq %rdx, (%rdi) + adcq %rcx, %rcx + movq 16(%rsi), %rdx + movq %rcx, 8(%rdi) + adcq %rdx, %rdx + movq 24(%rsi), %rcx + movq %rdx, 16(%rdi) + adcq %rcx, %rcx + movq 32(%rsi), %rdx + movq %rcx, 24(%rdi) + adcq %rdx, %rdx + movq 40(%rsi), %rcx + movq %rdx, 32(%rdi) + adcq %rcx, %rcx + movq 48(%rsi), %rdx + movq %rcx, 40(%rdi) + adcq %rdx, %rdx + movq 56(%rsi), %rcx + movq %rdx, 48(%rdi) + adcq %rcx, %rcx + movq 64(%rsi), %rdx + movq %rcx, 56(%rdi) + adcq %rdx, %rdx + movq 72(%rsi), %rcx + movq %rdx, 64(%rdi) + adcq %rcx, %rcx + movq 80(%rsi), %rdx + movq %rcx, 72(%rdi) + adcq %rdx, %rdx + movq 88(%rsi), %rcx + movq %rdx, 80(%rdi) + adcq %rcx, %rcx + movq 96(%rsi), %rdx + movq %rcx, 88(%rdi) + adcq %rdx, %rdx + movq 104(%rsi), %rcx + movq %rdx, 96(%rdi) + adcq %rcx, %rcx + movq 112(%rsi), %rdx + movq %rcx, 104(%rdi) + adcq %rdx, %rdx + movq 120(%rsi), %rcx + movq %rdx, 112(%rdi) + adcq %rcx, %rcx + movq 128(%rsi), %rdx + movq %rcx, 120(%rdi) + adcq %rdx, %rdx + movq 136(%rsi), %rcx + movq %rdx, 128(%rdi) + adcq %rcx, %rcx + movq 144(%rsi), %rdx + movq %rcx, 136(%rdi) + adcq %rdx, %rdx + movq 152(%rsi), %rcx + movq %rdx, 144(%rdi) + adcq %rcx, %rcx + movq 160(%rsi), %rdx + movq %rcx, 152(%rdi) + adcq %rdx, %rdx + movq 168(%rsi), %rcx + movq %rdx, 160(%rdi) + adcq %rcx, %rcx + movq 176(%rsi), %rdx + movq %rcx, 168(%rdi) + adcq %rdx, %rdx + movq 184(%rsi), %rcx + movq %rdx, 176(%rdi) + adcq %rcx, %rcx + movq %rcx, 184(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_dbl_24,.-sp_3072_dbl_24 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sqr_48 +.type sp_3072_sqr_48,@function +.align 16 +sp_3072_sqr_48: +#else +.globl _sp_3072_sqr_48 +.p2align 4 +_sp_3072_sqr_48: +#endif /* __APPLE__ */ + subq $984, %rsp + movq %rdi, 960(%rsp) + movq %rsi, 968(%rsp) + leaq 768(%rsp), %r8 + leaq 192(%rsi), %r9 + # Add + movq (%rsi), %rdx + xorq %rcx, %rcx + addq (%r9), %rdx + movq 8(%rsi), %rax + movq %rdx, (%r8) + adcq 8(%r9), %rax + movq 16(%rsi), %rdx + movq %rax, 8(%r8) + adcq 16(%r9), %rdx + movq 24(%rsi), %rax + movq %rdx, 16(%r8) + adcq 24(%r9), %rax + movq 32(%rsi), %rdx + movq %rax, 24(%r8) + adcq 32(%r9), %rdx + movq 40(%rsi), %rax + movq %rdx, 32(%r8) + adcq 40(%r9), %rax + movq 48(%rsi), %rdx + movq %rax, 40(%r8) + adcq 48(%r9), %rdx + movq 56(%rsi), %rax + movq %rdx, 48(%r8) + adcq 56(%r9), %rax + movq 64(%rsi), %rdx + movq %rax, 56(%r8) + adcq 64(%r9), %rdx + movq 72(%rsi), %rax + movq %rdx, 64(%r8) + adcq 72(%r9), %rax + movq 80(%rsi), %rdx + movq %rax, 72(%r8) + adcq 80(%r9), %rdx + movq 88(%rsi), %rax + movq %rdx, 80(%r8) + adcq 88(%r9), %rax + movq 96(%rsi), %rdx + movq %rax, 88(%r8) + adcq 96(%r9), %rdx + movq 104(%rsi), %rax + movq %rdx, 96(%r8) + adcq 104(%r9), %rax + movq 112(%rsi), %rdx + movq %rax, 104(%r8) + adcq 112(%r9), %rdx + movq 120(%rsi), %rax + movq %rdx, 112(%r8) + adcq 120(%r9), %rax + movq 128(%rsi), %rdx + movq %rax, 120(%r8) + adcq 128(%r9), %rdx + movq 136(%rsi), %rax + movq %rdx, 128(%r8) + adcq 136(%r9), %rax + movq 144(%rsi), %rdx + movq %rax, 136(%r8) + adcq 144(%r9), %rdx + movq 152(%rsi), %rax + movq %rdx, 144(%r8) + adcq 152(%r9), %rax + movq 160(%rsi), %rdx + movq %rax, 152(%r8) + adcq 160(%r9), %rdx + movq 168(%rsi), %rax + movq %rdx, 160(%r8) + adcq 168(%r9), %rax + movq 176(%rsi), %rdx + movq %rax, 168(%r8) + adcq 176(%r9), %rdx + movq 184(%rsi), %rax + movq %rdx, 176(%r8) + adcq 184(%r9), %rax + movq %rax, 184(%r8) + adcq $0, %rcx + movq %rcx, 976(%rsp) + movq %r8, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_3072_sqr_24@plt +#else + callq _sp_3072_sqr_24 +#endif /* __APPLE__ */ + movq 968(%rsp), %rsi + leaq 384(%rsp), %rdi + addq $192, %rsi +#ifndef __APPLE__ + callq sp_3072_sqr_24@plt +#else + callq _sp_3072_sqr_24 +#endif /* __APPLE__ */ + movq 968(%rsp), %rsi + movq 960(%rsp), %rdi +#ifndef __APPLE__ + callq sp_3072_sqr_24@plt +#else + callq _sp_3072_sqr_24 +#endif /* __APPLE__ */ + movq 976(%rsp), %r10 + movq %rdi, %r9 + leaq 768(%rsp), %r8 + movq %r10, %rcx + negq %r10 + addq $384, %r9 + movq (%r8), %rdx + movq 8(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, (%r9) + movq %rax, 8(%r9) + movq 16(%r8), %rdx + movq 24(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 16(%r9) + movq %rax, 24(%r9) + movq 32(%r8), %rdx + movq 40(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 32(%r9) + movq %rax, 40(%r9) + movq 48(%r8), %rdx + movq 56(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 48(%r9) + movq %rax, 56(%r9) + movq 64(%r8), %rdx + movq 72(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 64(%r9) + movq %rax, 72(%r9) + movq 80(%r8), %rdx + movq 88(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 80(%r9) + movq %rax, 88(%r9) + movq 96(%r8), %rdx + movq 104(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 96(%r9) + movq %rax, 104(%r9) + movq 112(%r8), %rdx + movq 120(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 112(%r9) + movq %rax, 120(%r9) + movq 128(%r8), %rdx + movq 136(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 128(%r9) + movq %rax, 136(%r9) + movq 144(%r8), %rdx + movq 152(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 144(%r9) + movq %rax, 152(%r9) + movq 160(%r8), %rdx + movq 168(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 160(%r9) + movq %rax, 168(%r9) + movq 176(%r8), %rdx + movq 184(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 176(%r9) + movq %rax, 184(%r9) + movq (%r9), %rdx + addq %rdx, %rdx + movq 8(%r9), %rax + movq %rdx, (%r9) + adcq %rax, %rax + movq 16(%r9), %rdx + movq %rax, 8(%r9) + adcq %rdx, %rdx + movq 24(%r9), %rax + movq %rdx, 16(%r9) + adcq %rax, %rax + movq 32(%r9), %rdx + movq %rax, 24(%r9) + adcq %rdx, %rdx + movq 40(%r9), %rax + movq %rdx, 32(%r9) + adcq %rax, %rax + movq 48(%r9), %rdx + movq %rax, 40(%r9) + adcq %rdx, %rdx + movq 56(%r9), %rax + movq %rdx, 48(%r9) + adcq %rax, %rax + movq 64(%r9), %rdx + movq %rax, 56(%r9) + adcq %rdx, %rdx + movq 72(%r9), %rax + movq %rdx, 64(%r9) + adcq %rax, %rax + movq 80(%r9), %rdx + movq %rax, 72(%r9) + adcq %rdx, %rdx + movq 88(%r9), %rax + movq %rdx, 80(%r9) + adcq %rax, %rax + movq 96(%r9), %rdx + movq %rax, 88(%r9) + adcq %rdx, %rdx + movq 104(%r9), %rax + movq %rdx, 96(%r9) + adcq %rax, %rax + movq 112(%r9), %rdx + movq %rax, 104(%r9) + adcq %rdx, %rdx + movq 120(%r9), %rax + movq %rdx, 112(%r9) + adcq %rax, %rax + movq 128(%r9), %rdx + movq %rax, 120(%r9) + adcq %rdx, %rdx + movq 136(%r9), %rax + movq %rdx, 128(%r9) + adcq %rax, %rax + movq 144(%r9), %rdx + movq %rax, 136(%r9) + adcq %rdx, %rdx + movq 152(%r9), %rax + movq %rdx, 144(%r9) + adcq %rax, %rax + movq 160(%r9), %rdx + movq %rax, 152(%r9) + adcq %rdx, %rdx + movq 168(%r9), %rax + movq %rdx, 160(%r9) + adcq %rax, %rax + movq 176(%r9), %rdx + movq %rax, 168(%r9) + adcq %rdx, %rdx + movq 184(%r9), %rax + movq %rdx, 176(%r9) + adcq %rax, %rax + movq %rax, 184(%r9) + adcq $0, %rcx + leaq 384(%rsp), %rsi + movq %rsp, %r8 + movq (%r8), %rdx + subq (%rsi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rsi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rsi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rsi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rsi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rsi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rsi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rsi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rsi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rsi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rsi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rsi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rsi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rsi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rsi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rsi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rsi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rsi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rsi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rsi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rsi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rsi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rsi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rsi), %rax + movq 192(%r8), %rdx + movq %rax, 184(%r8) + sbbq 192(%rsi), %rdx + movq 200(%r8), %rax + movq %rdx, 192(%r8) + sbbq 200(%rsi), %rax + movq 208(%r8), %rdx + movq %rax, 200(%r8) + sbbq 208(%rsi), %rdx + movq 216(%r8), %rax + movq %rdx, 208(%r8) + sbbq 216(%rsi), %rax + movq 224(%r8), %rdx + movq %rax, 216(%r8) + sbbq 224(%rsi), %rdx + movq 232(%r8), %rax + movq %rdx, 224(%r8) + sbbq 232(%rsi), %rax + movq 240(%r8), %rdx + movq %rax, 232(%r8) + sbbq 240(%rsi), %rdx + movq 248(%r8), %rax + movq %rdx, 240(%r8) + sbbq 248(%rsi), %rax + movq 256(%r8), %rdx + movq %rax, 248(%r8) + sbbq 256(%rsi), %rdx + movq 264(%r8), %rax + movq %rdx, 256(%r8) + sbbq 264(%rsi), %rax + movq 272(%r8), %rdx + movq %rax, 264(%r8) + sbbq 272(%rsi), %rdx + movq 280(%r8), %rax + movq %rdx, 272(%r8) + sbbq 280(%rsi), %rax + movq 288(%r8), %rdx + movq %rax, 280(%r8) + sbbq 288(%rsi), %rdx + movq 296(%r8), %rax + movq %rdx, 288(%r8) + sbbq 296(%rsi), %rax + movq 304(%r8), %rdx + movq %rax, 296(%r8) + sbbq 304(%rsi), %rdx + movq 312(%r8), %rax + movq %rdx, 304(%r8) + sbbq 312(%rsi), %rax + movq 320(%r8), %rdx + movq %rax, 312(%r8) + sbbq 320(%rsi), %rdx + movq 328(%r8), %rax + movq %rdx, 320(%r8) + sbbq 328(%rsi), %rax + movq 336(%r8), %rdx + movq %rax, 328(%r8) + sbbq 336(%rsi), %rdx + movq 344(%r8), %rax + movq %rdx, 336(%r8) + sbbq 344(%rsi), %rax + movq 352(%r8), %rdx + movq %rax, 344(%r8) + sbbq 352(%rsi), %rdx + movq 360(%r8), %rax + movq %rdx, 352(%r8) + sbbq 360(%rsi), %rax + movq 368(%r8), %rdx + movq %rax, 360(%r8) + sbbq 368(%rsi), %rdx + movq 376(%r8), %rax + movq %rdx, 368(%r8) + sbbq 376(%rsi), %rax + movq %rax, 376(%r8) + sbbq $0, %rcx + movq (%r8), %rdx + subq (%rdi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rdi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rdi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rdi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rdi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rdi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rdi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rdi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rdi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rdi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rdi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rdi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rdi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rdi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rdi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rdi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rdi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rdi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rdi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rdi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rdi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rdi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rdi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rdi), %rax + movq 192(%r8), %rdx + movq %rax, 184(%r8) + sbbq 192(%rdi), %rdx + movq 200(%r8), %rax + movq %rdx, 192(%r8) + sbbq 200(%rdi), %rax + movq 208(%r8), %rdx + movq %rax, 200(%r8) + sbbq 208(%rdi), %rdx + movq 216(%r8), %rax + movq %rdx, 208(%r8) + sbbq 216(%rdi), %rax + movq 224(%r8), %rdx + movq %rax, 216(%r8) + sbbq 224(%rdi), %rdx + movq 232(%r8), %rax + movq %rdx, 224(%r8) + sbbq 232(%rdi), %rax + movq 240(%r8), %rdx + movq %rax, 232(%r8) + sbbq 240(%rdi), %rdx + movq 248(%r8), %rax + movq %rdx, 240(%r8) + sbbq 248(%rdi), %rax + movq 256(%r8), %rdx + movq %rax, 248(%r8) + sbbq 256(%rdi), %rdx + movq 264(%r8), %rax + movq %rdx, 256(%r8) + sbbq 264(%rdi), %rax + movq 272(%r8), %rdx + movq %rax, 264(%r8) + sbbq 272(%rdi), %rdx + movq 280(%r8), %rax + movq %rdx, 272(%r8) + sbbq 280(%rdi), %rax + movq 288(%r8), %rdx + movq %rax, 280(%r8) + sbbq 288(%rdi), %rdx + movq 296(%r8), %rax + movq %rdx, 288(%r8) + sbbq 296(%rdi), %rax + movq 304(%r8), %rdx + movq %rax, 296(%r8) + sbbq 304(%rdi), %rdx + movq 312(%r8), %rax + movq %rdx, 304(%r8) + sbbq 312(%rdi), %rax + movq 320(%r8), %rdx + movq %rax, 312(%r8) + sbbq 320(%rdi), %rdx + movq 328(%r8), %rax + movq %rdx, 320(%r8) + sbbq 328(%rdi), %rax + movq 336(%r8), %rdx + movq %rax, 328(%r8) + sbbq 336(%rdi), %rdx + movq 344(%r8), %rax + movq %rdx, 336(%r8) + sbbq 344(%rdi), %rax + movq 352(%r8), %rdx + movq %rax, 344(%r8) + sbbq 352(%rdi), %rdx + movq 360(%r8), %rax + movq %rdx, 352(%r8) + sbbq 360(%rdi), %rax + movq 368(%r8), %rdx + movq %rax, 360(%r8) + sbbq 368(%rdi), %rdx + movq 376(%r8), %rax + movq %rdx, 368(%r8) + sbbq 376(%rdi), %rax + movq %rax, 376(%r8) + sbbq $0, %rcx + subq $192, %r9 + # Add in place + movq (%r9), %rdx + addq (%r8), %rdx + movq 8(%r9), %rax + movq %rdx, (%r9) + adcq 8(%r8), %rax + movq 16(%r9), %rdx + movq %rax, 8(%r9) + adcq 16(%r8), %rdx + movq 24(%r9), %rax + movq %rdx, 16(%r9) + adcq 24(%r8), %rax + movq 32(%r9), %rdx + movq %rax, 24(%r9) + adcq 32(%r8), %rdx + movq 40(%r9), %rax + movq %rdx, 32(%r9) + adcq 40(%r8), %rax + movq 48(%r9), %rdx + movq %rax, 40(%r9) + adcq 48(%r8), %rdx + movq 56(%r9), %rax + movq %rdx, 48(%r9) + adcq 56(%r8), %rax + movq 64(%r9), %rdx + movq %rax, 56(%r9) + adcq 64(%r8), %rdx + movq 72(%r9), %rax + movq %rdx, 64(%r9) + adcq 72(%r8), %rax + movq 80(%r9), %rdx + movq %rax, 72(%r9) + adcq 80(%r8), %rdx + movq 88(%r9), %rax + movq %rdx, 80(%r9) + adcq 88(%r8), %rax + movq 96(%r9), %rdx + movq %rax, 88(%r9) + adcq 96(%r8), %rdx + movq 104(%r9), %rax + movq %rdx, 96(%r9) + adcq 104(%r8), %rax + movq 112(%r9), %rdx + movq %rax, 104(%r9) + adcq 112(%r8), %rdx + movq 120(%r9), %rax + movq %rdx, 112(%r9) + adcq 120(%r8), %rax + movq 128(%r9), %rdx + movq %rax, 120(%r9) + adcq 128(%r8), %rdx + movq 136(%r9), %rax + movq %rdx, 128(%r9) + adcq 136(%r8), %rax + movq 144(%r9), %rdx + movq %rax, 136(%r9) + adcq 144(%r8), %rdx + movq 152(%r9), %rax + movq %rdx, 144(%r9) + adcq 152(%r8), %rax + movq 160(%r9), %rdx + movq %rax, 152(%r9) + adcq 160(%r8), %rdx + movq 168(%r9), %rax + movq %rdx, 160(%r9) + adcq 168(%r8), %rax + movq 176(%r9), %rdx + movq %rax, 168(%r9) + adcq 176(%r8), %rdx + movq 184(%r9), %rax + movq %rdx, 176(%r9) + adcq 184(%r8), %rax + movq 192(%r9), %rdx + movq %rax, 184(%r9) + adcq 192(%r8), %rdx + movq 200(%r9), %rax + movq %rdx, 192(%r9) + adcq 200(%r8), %rax + movq 208(%r9), %rdx + movq %rax, 200(%r9) + adcq 208(%r8), %rdx + movq 216(%r9), %rax + movq %rdx, 208(%r9) + adcq 216(%r8), %rax + movq 224(%r9), %rdx + movq %rax, 216(%r9) + adcq 224(%r8), %rdx + movq 232(%r9), %rax + movq %rdx, 224(%r9) + adcq 232(%r8), %rax + movq 240(%r9), %rdx + movq %rax, 232(%r9) + adcq 240(%r8), %rdx + movq 248(%r9), %rax + movq %rdx, 240(%r9) + adcq 248(%r8), %rax + movq 256(%r9), %rdx + movq %rax, 248(%r9) + adcq 256(%r8), %rdx + movq 264(%r9), %rax + movq %rdx, 256(%r9) + adcq 264(%r8), %rax + movq 272(%r9), %rdx + movq %rax, 264(%r9) + adcq 272(%r8), %rdx + movq 280(%r9), %rax + movq %rdx, 272(%r9) + adcq 280(%r8), %rax + movq 288(%r9), %rdx + movq %rax, 280(%r9) + adcq 288(%r8), %rdx + movq 296(%r9), %rax + movq %rdx, 288(%r9) + adcq 296(%r8), %rax + movq 304(%r9), %rdx + movq %rax, 296(%r9) + adcq 304(%r8), %rdx + movq 312(%r9), %rax + movq %rdx, 304(%r9) + adcq 312(%r8), %rax + movq 320(%r9), %rdx + movq %rax, 312(%r9) + adcq 320(%r8), %rdx + movq 328(%r9), %rax + movq %rdx, 320(%r9) + adcq 328(%r8), %rax + movq 336(%r9), %rdx + movq %rax, 328(%r9) + adcq 336(%r8), %rdx + movq 344(%r9), %rax + movq %rdx, 336(%r9) + adcq 344(%r8), %rax + movq 352(%r9), %rdx + movq %rax, 344(%r9) + adcq 352(%r8), %rdx + movq 360(%r9), %rax + movq %rdx, 352(%r9) + adcq 360(%r8), %rax + movq 368(%r9), %rdx + movq %rax, 360(%r9) + adcq 368(%r8), %rdx + movq 376(%r9), %rax + movq %rdx, 368(%r9) + adcq 376(%r8), %rax + movq %rax, 376(%r9) + adcq $0, %rcx + movq %rcx, 576(%rdi) + # Add in place + movq 192(%r9), %rdx + addq (%rsi), %rdx + movq 200(%r9), %rax + movq %rdx, 192(%r9) + adcq 8(%rsi), %rax + movq 208(%r9), %rdx + movq %rax, 200(%r9) + adcq 16(%rsi), %rdx + movq 216(%r9), %rax + movq %rdx, 208(%r9) + adcq 24(%rsi), %rax + movq 224(%r9), %rdx + movq %rax, 216(%r9) + adcq 32(%rsi), %rdx + movq 232(%r9), %rax + movq %rdx, 224(%r9) + adcq 40(%rsi), %rax + movq 240(%r9), %rdx + movq %rax, 232(%r9) + adcq 48(%rsi), %rdx + movq 248(%r9), %rax + movq %rdx, 240(%r9) + adcq 56(%rsi), %rax + movq 256(%r9), %rdx + movq %rax, 248(%r9) + adcq 64(%rsi), %rdx + movq 264(%r9), %rax + movq %rdx, 256(%r9) + adcq 72(%rsi), %rax + movq 272(%r9), %rdx + movq %rax, 264(%r9) + adcq 80(%rsi), %rdx + movq 280(%r9), %rax + movq %rdx, 272(%r9) + adcq 88(%rsi), %rax + movq 288(%r9), %rdx + movq %rax, 280(%r9) + adcq 96(%rsi), %rdx + movq 296(%r9), %rax + movq %rdx, 288(%r9) + adcq 104(%rsi), %rax + movq 304(%r9), %rdx + movq %rax, 296(%r9) + adcq 112(%rsi), %rdx + movq 312(%r9), %rax + movq %rdx, 304(%r9) + adcq 120(%rsi), %rax + movq 320(%r9), %rdx + movq %rax, 312(%r9) + adcq 128(%rsi), %rdx + movq 328(%r9), %rax + movq %rdx, 320(%r9) + adcq 136(%rsi), %rax + movq 336(%r9), %rdx + movq %rax, 328(%r9) + adcq 144(%rsi), %rdx + movq 344(%r9), %rax + movq %rdx, 336(%r9) + adcq 152(%rsi), %rax + movq 352(%r9), %rdx + movq %rax, 344(%r9) + adcq 160(%rsi), %rdx + movq 360(%r9), %rax + movq %rdx, 352(%r9) + adcq 168(%rsi), %rax + movq 368(%r9), %rdx + movq %rax, 360(%r9) + adcq 176(%rsi), %rdx + movq 376(%r9), %rax + movq %rdx, 368(%r9) + adcq 184(%rsi), %rax + movq 384(%r9), %rdx + movq %rax, 376(%r9) + adcq 192(%rsi), %rdx + movq %rdx, 384(%r9) + # Add to zero + movq 200(%rsi), %rdx + adcq $0, %rdx + movq 208(%rsi), %rax + movq %rdx, 392(%r9) + adcq $0, %rax + movq 216(%rsi), %rdx + movq %rax, 400(%r9) + adcq $0, %rdx + movq 224(%rsi), %rax + movq %rdx, 408(%r9) + adcq $0, %rax + movq 232(%rsi), %rdx + movq %rax, 416(%r9) + adcq $0, %rdx + movq 240(%rsi), %rax + movq %rdx, 424(%r9) + adcq $0, %rax + movq 248(%rsi), %rdx + movq %rax, 432(%r9) + adcq $0, %rdx + movq 256(%rsi), %rax + movq %rdx, 440(%r9) + adcq $0, %rax + movq 264(%rsi), %rdx + movq %rax, 448(%r9) + adcq $0, %rdx + movq 272(%rsi), %rax + movq %rdx, 456(%r9) + adcq $0, %rax + movq 280(%rsi), %rdx + movq %rax, 464(%r9) + adcq $0, %rdx + movq 288(%rsi), %rax + movq %rdx, 472(%r9) + adcq $0, %rax + movq 296(%rsi), %rdx + movq %rax, 480(%r9) + adcq $0, %rdx + movq 304(%rsi), %rax + movq %rdx, 488(%r9) + adcq $0, %rax + movq 312(%rsi), %rdx + movq %rax, 496(%r9) + adcq $0, %rdx + movq 320(%rsi), %rax + movq %rdx, 504(%r9) + adcq $0, %rax + movq 328(%rsi), %rdx + movq %rax, 512(%r9) + adcq $0, %rdx + movq 336(%rsi), %rax + movq %rdx, 520(%r9) + adcq $0, %rax + movq 344(%rsi), %rdx + movq %rax, 528(%r9) + adcq $0, %rdx + movq 352(%rsi), %rax + movq %rdx, 536(%r9) + adcq $0, %rax + movq 360(%rsi), %rdx + movq %rax, 544(%r9) + adcq $0, %rdx + movq 368(%rsi), %rax + movq %rdx, 552(%r9) + adcq $0, %rax + movq 376(%rsi), %rdx + movq %rax, 560(%r9) + adcq $0, %rdx + movq %rdx, 568(%r9) + addq $984, %rsp + repz retq +#ifndef __APPLE__ +.size sp_3072_sqr_48,.-sp_3072_sqr_48 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_avx2_48 +.type sp_3072_mul_avx2_48,@function +.align 16 +sp_3072_mul_avx2_48: +#else +.globl _sp_3072_mul_avx2_48 +.p2align 4 +_sp_3072_mul_avx2_48: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + subq $1192, %rsp + movq %rdi, 1152(%rsp) + movq %rsi, 1160(%rsp) + movq %rdx, 1168(%rsp) + leaq 768(%rsp), %r10 + leaq 192(%rsi), %r12 + # Add + movq (%rsi), %rax + xorq %r13, %r13 + addq (%r12), %rax + movq 8(%rsi), %rcx + movq %rax, (%r10) + adcq 8(%r12), %rcx + movq 16(%rsi), %r8 + movq %rcx, 8(%r10) + adcq 16(%r12), %r8 + movq 24(%rsi), %rax + movq %r8, 16(%r10) + adcq 24(%r12), %rax + movq 32(%rsi), %rcx + movq %rax, 24(%r10) + adcq 32(%r12), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%r10) + adcq 40(%r12), %r8 + movq 48(%rsi), %rax + movq %r8, 40(%r10) + adcq 48(%r12), %rax + movq 56(%rsi), %rcx + movq %rax, 48(%r10) + adcq 56(%r12), %rcx + movq 64(%rsi), %r8 + movq %rcx, 56(%r10) + adcq 64(%r12), %r8 + movq 72(%rsi), %rax + movq %r8, 64(%r10) + adcq 72(%r12), %rax + movq 80(%rsi), %rcx + movq %rax, 72(%r10) + adcq 80(%r12), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%r10) + adcq 88(%r12), %r8 + movq 96(%rsi), %rax + movq %r8, 88(%r10) + adcq 96(%r12), %rax + movq 104(%rsi), %rcx + movq %rax, 96(%r10) + adcq 104(%r12), %rcx + movq 112(%rsi), %r8 + movq %rcx, 104(%r10) + adcq 112(%r12), %r8 + movq 120(%rsi), %rax + movq %r8, 112(%r10) + adcq 120(%r12), %rax + movq 128(%rsi), %rcx + movq %rax, 120(%r10) + adcq 128(%r12), %rcx + movq 136(%rsi), %r8 + movq %rcx, 128(%r10) + adcq 136(%r12), %r8 + movq 144(%rsi), %rax + movq %r8, 136(%r10) + adcq 144(%r12), %rax + movq 152(%rsi), %rcx + movq %rax, 144(%r10) + adcq 152(%r12), %rcx + movq 160(%rsi), %r8 + movq %rcx, 152(%r10) + adcq 160(%r12), %r8 + movq 168(%rsi), %rax + movq %r8, 160(%r10) + adcq 168(%r12), %rax + movq 176(%rsi), %rcx + movq %rax, 168(%r10) + adcq 176(%r12), %rcx + movq 184(%rsi), %r8 + movq %rcx, 176(%r10) + adcq 184(%r12), %r8 + movq %r8, 184(%r10) + adcq $0, %r13 + movq %r13, 1176(%rsp) + leaq 960(%rsp), %r11 + leaq 192(%rdx), %r12 + # Add + movq (%rdx), %rax + xorq %r14, %r14 + addq (%r12), %rax + movq 8(%rdx), %rcx + movq %rax, (%r11) + adcq 8(%r12), %rcx + movq 16(%rdx), %r8 + movq %rcx, 8(%r11) + adcq 16(%r12), %r8 + movq 24(%rdx), %rax + movq %r8, 16(%r11) + adcq 24(%r12), %rax + movq 32(%rdx), %rcx + movq %rax, 24(%r11) + adcq 32(%r12), %rcx + movq 40(%rdx), %r8 + movq %rcx, 32(%r11) + adcq 40(%r12), %r8 + movq 48(%rdx), %rax + movq %r8, 40(%r11) + adcq 48(%r12), %rax + movq 56(%rdx), %rcx + movq %rax, 48(%r11) + adcq 56(%r12), %rcx + movq 64(%rdx), %r8 + movq %rcx, 56(%r11) + adcq 64(%r12), %r8 + movq 72(%rdx), %rax + movq %r8, 64(%r11) + adcq 72(%r12), %rax + movq 80(%rdx), %rcx + movq %rax, 72(%r11) + adcq 80(%r12), %rcx + movq 88(%rdx), %r8 + movq %rcx, 80(%r11) + adcq 88(%r12), %r8 + movq 96(%rdx), %rax + movq %r8, 88(%r11) + adcq 96(%r12), %rax + movq 104(%rdx), %rcx + movq %rax, 96(%r11) + adcq 104(%r12), %rcx + movq 112(%rdx), %r8 + movq %rcx, 104(%r11) + adcq 112(%r12), %r8 + movq 120(%rdx), %rax + movq %r8, 112(%r11) + adcq 120(%r12), %rax + movq 128(%rdx), %rcx + movq %rax, 120(%r11) + adcq 128(%r12), %rcx + movq 136(%rdx), %r8 + movq %rcx, 128(%r11) + adcq 136(%r12), %r8 + movq 144(%rdx), %rax + movq %r8, 136(%r11) + adcq 144(%r12), %rax + movq 152(%rdx), %rcx + movq %rax, 144(%r11) + adcq 152(%r12), %rcx + movq 160(%rdx), %r8 + movq %rcx, 152(%r11) + adcq 160(%r12), %r8 + movq 168(%rdx), %rax + movq %r8, 160(%r11) + adcq 168(%r12), %rax + movq 176(%rdx), %rcx + movq %rax, 168(%r11) + adcq 176(%r12), %rcx + movq 184(%rdx), %r8 + movq %rcx, 176(%r11) + adcq 184(%r12), %r8 + movq %r8, 184(%r11) + adcq $0, %r14 + movq %r14, 1184(%rsp) + movq %r11, %rdx + movq %r10, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_3072_mul_avx2_24@plt +#else + callq _sp_3072_mul_avx2_24 +#endif /* __APPLE__ */ + movq 1168(%rsp), %rdx + movq 1160(%rsp), %rsi + leaq 384(%rsp), %rdi + addq $192, %rdx + addq $192, %rsi +#ifndef __APPLE__ + callq sp_3072_mul_avx2_24@plt +#else + callq _sp_3072_mul_avx2_24 +#endif /* __APPLE__ */ + movq 1168(%rsp), %rdx + movq 1160(%rsp), %rsi + movq 1152(%rsp), %rdi +#ifndef __APPLE__ + callq sp_3072_mul_avx2_24@plt +#else + callq _sp_3072_mul_avx2_24 +#endif /* __APPLE__ */ + movq 1176(%rsp), %r13 + movq 1184(%rsp), %r14 + movq 1152(%rsp), %r15 + movq %r13, %r9 + leaq 768(%rsp), %r10 + leaq 960(%rsp), %r11 + andq %r14, %r9 + negq %r13 + negq %r14 + addq $384, %r15 + movq (%r10), %rax + movq (%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + addq %rcx, %rax + movq 8(%r10), %rcx + movq 8(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, (%r15) + adcq %r8, %rcx + movq 16(%r10), %r8 + movq 16(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 8(%r15) + adcq %rax, %r8 + movq 24(%r10), %rax + movq 24(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 16(%r15) + adcq %rcx, %rax + movq 32(%r10), %rcx + movq 32(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 24(%r15) + adcq %r8, %rcx + movq 40(%r10), %r8 + movq 40(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 32(%r15) + adcq %rax, %r8 + movq 48(%r10), %rax + movq 48(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 40(%r15) + adcq %rcx, %rax + movq 56(%r10), %rcx + movq 56(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 48(%r15) + adcq %r8, %rcx + movq 64(%r10), %r8 + movq 64(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 56(%r15) + adcq %rax, %r8 + movq 72(%r10), %rax + movq 72(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 64(%r15) + adcq %rcx, %rax + movq 80(%r10), %rcx + movq 80(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 72(%r15) + adcq %r8, %rcx + movq 88(%r10), %r8 + movq 88(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 80(%r15) + adcq %rax, %r8 + movq 96(%r10), %rax + movq 96(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 88(%r15) + adcq %rcx, %rax + movq 104(%r10), %rcx + movq 104(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 96(%r15) + adcq %r8, %rcx + movq 112(%r10), %r8 + movq 112(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 104(%r15) + adcq %rax, %r8 + movq 120(%r10), %rax + movq 120(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 112(%r15) + adcq %rcx, %rax + movq 128(%r10), %rcx + movq 128(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 120(%r15) + adcq %r8, %rcx + movq 136(%r10), %r8 + movq 136(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 128(%r15) + adcq %rax, %r8 + movq 144(%r10), %rax + movq 144(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 136(%r15) + adcq %rcx, %rax + movq 152(%r10), %rcx + movq 152(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 144(%r15) + adcq %r8, %rcx + movq 160(%r10), %r8 + movq 160(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 152(%r15) + adcq %rax, %r8 + movq 168(%r10), %rax + movq 168(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 160(%r15) + adcq %rcx, %rax + movq 176(%r10), %rcx + movq 176(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 168(%r15) + adcq %r8, %rcx + movq 184(%r10), %r8 + movq 184(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 176(%r15) + adcq %rax, %r8 + movq %r8, 184(%r15) + adcq $0, %r9 + leaq 384(%rsp), %r11 + movq %rsp, %r10 + movq (%r10), %rax + subq (%r11), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%r11), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%r11), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%r11), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%r11), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%r11), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%r11), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%r11), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%r11), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%r11), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%r11), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%r11), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%r11), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%r11), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%r11), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%r11), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%r11), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%r11), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%r11), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%r11), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%r11), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%r11), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%r11), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%r11), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r10) + sbbq 192(%r11), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r10) + sbbq 200(%r11), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r10) + sbbq 208(%r11), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r10) + sbbq 216(%r11), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r10) + sbbq 224(%r11), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r10) + sbbq 232(%r11), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r10) + sbbq 240(%r11), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r10) + sbbq 248(%r11), %rcx + movq 256(%r10), %r8 + movq %rcx, 248(%r10) + sbbq 256(%r11), %r8 + movq 264(%r10), %rax + movq %r8, 256(%r10) + sbbq 264(%r11), %rax + movq 272(%r10), %rcx + movq %rax, 264(%r10) + sbbq 272(%r11), %rcx + movq 280(%r10), %r8 + movq %rcx, 272(%r10) + sbbq 280(%r11), %r8 + movq 288(%r10), %rax + movq %r8, 280(%r10) + sbbq 288(%r11), %rax + movq 296(%r10), %rcx + movq %rax, 288(%r10) + sbbq 296(%r11), %rcx + movq 304(%r10), %r8 + movq %rcx, 296(%r10) + sbbq 304(%r11), %r8 + movq 312(%r10), %rax + movq %r8, 304(%r10) + sbbq 312(%r11), %rax + movq 320(%r10), %rcx + movq %rax, 312(%r10) + sbbq 320(%r11), %rcx + movq 328(%r10), %r8 + movq %rcx, 320(%r10) + sbbq 328(%r11), %r8 + movq 336(%r10), %rax + movq %r8, 328(%r10) + sbbq 336(%r11), %rax + movq 344(%r10), %rcx + movq %rax, 336(%r10) + sbbq 344(%r11), %rcx + movq 352(%r10), %r8 + movq %rcx, 344(%r10) + sbbq 352(%r11), %r8 + movq 360(%r10), %rax + movq %r8, 352(%r10) + sbbq 360(%r11), %rax + movq 368(%r10), %rcx + movq %rax, 360(%r10) + sbbq 368(%r11), %rcx + movq 376(%r10), %r8 + movq %rcx, 368(%r10) + sbbq 376(%r11), %r8 + movq %r8, 376(%r10) + sbbq $0, %r9 + movq (%r10), %rax + subq (%rdi), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%rdi), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%rdi), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%rdi), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%rdi), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%rdi), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%rdi), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%rdi), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%rdi), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%rdi), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%rdi), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%rdi), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%rdi), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%rdi), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%rdi), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%rdi), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%rdi), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%rdi), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%rdi), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%rdi), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%rdi), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%rdi), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%rdi), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%rdi), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r10) + sbbq 192(%rdi), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r10) + sbbq 200(%rdi), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r10) + sbbq 208(%rdi), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r10) + sbbq 216(%rdi), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r10) + sbbq 224(%rdi), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r10) + sbbq 232(%rdi), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r10) + sbbq 240(%rdi), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r10) + sbbq 248(%rdi), %rcx + movq 256(%r10), %r8 + movq %rcx, 248(%r10) + sbbq 256(%rdi), %r8 + movq 264(%r10), %rax + movq %r8, 256(%r10) + sbbq 264(%rdi), %rax + movq 272(%r10), %rcx + movq %rax, 264(%r10) + sbbq 272(%rdi), %rcx + movq 280(%r10), %r8 + movq %rcx, 272(%r10) + sbbq 280(%rdi), %r8 + movq 288(%r10), %rax + movq %r8, 280(%r10) + sbbq 288(%rdi), %rax + movq 296(%r10), %rcx + movq %rax, 288(%r10) + sbbq 296(%rdi), %rcx + movq 304(%r10), %r8 + movq %rcx, 296(%r10) + sbbq 304(%rdi), %r8 + movq 312(%r10), %rax + movq %r8, 304(%r10) + sbbq 312(%rdi), %rax + movq 320(%r10), %rcx + movq %rax, 312(%r10) + sbbq 320(%rdi), %rcx + movq 328(%r10), %r8 + movq %rcx, 320(%r10) + sbbq 328(%rdi), %r8 + movq 336(%r10), %rax + movq %r8, 328(%r10) + sbbq 336(%rdi), %rax + movq 344(%r10), %rcx + movq %rax, 336(%r10) + sbbq 344(%rdi), %rcx + movq 352(%r10), %r8 + movq %rcx, 344(%r10) + sbbq 352(%rdi), %r8 + movq 360(%r10), %rax + movq %r8, 352(%r10) + sbbq 360(%rdi), %rax + movq 368(%r10), %rcx + movq %rax, 360(%r10) + sbbq 368(%rdi), %rcx + movq 376(%r10), %r8 + movq %rcx, 368(%r10) + sbbq 376(%rdi), %r8 + movq %r8, 376(%r10) + sbbq $0, %r9 + subq $192, %r15 + # Add + movq (%r15), %rax + addq (%r10), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r10), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r10), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r10), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r10), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r10), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r10), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r10), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r10), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r10), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r10), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r10), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r10), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r10), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r10), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r10), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r10), %rcx + movq 136(%r15), %r8 + movq %rcx, 128(%r15) + adcq 136(%r10), %r8 + movq 144(%r15), %rax + movq %r8, 136(%r15) + adcq 144(%r10), %rax + movq 152(%r15), %rcx + movq %rax, 144(%r15) + adcq 152(%r10), %rcx + movq 160(%r15), %r8 + movq %rcx, 152(%r15) + adcq 160(%r10), %r8 + movq 168(%r15), %rax + movq %r8, 160(%r15) + adcq 168(%r10), %rax + movq 176(%r15), %rcx + movq %rax, 168(%r15) + adcq 176(%r10), %rcx + movq 184(%r15), %r8 + movq %rcx, 176(%r15) + adcq 184(%r10), %r8 + movq 192(%r15), %rax + movq %r8, 184(%r15) + adcq 192(%r10), %rax + movq 200(%r15), %rcx + movq %rax, 192(%r15) + adcq 200(%r10), %rcx + movq 208(%r15), %r8 + movq %rcx, 200(%r15) + adcq 208(%r10), %r8 + movq 216(%r15), %rax + movq %r8, 208(%r15) + adcq 216(%r10), %rax + movq 224(%r15), %rcx + movq %rax, 216(%r15) + adcq 224(%r10), %rcx + movq 232(%r15), %r8 + movq %rcx, 224(%r15) + adcq 232(%r10), %r8 + movq 240(%r15), %rax + movq %r8, 232(%r15) + adcq 240(%r10), %rax + movq 248(%r15), %rcx + movq %rax, 240(%r15) + adcq 248(%r10), %rcx + movq 256(%r15), %r8 + movq %rcx, 248(%r15) + adcq 256(%r10), %r8 + movq 264(%r15), %rax + movq %r8, 256(%r15) + adcq 264(%r10), %rax + movq 272(%r15), %rcx + movq %rax, 264(%r15) + adcq 272(%r10), %rcx + movq 280(%r15), %r8 + movq %rcx, 272(%r15) + adcq 280(%r10), %r8 + movq 288(%r15), %rax + movq %r8, 280(%r15) + adcq 288(%r10), %rax + movq 296(%r15), %rcx + movq %rax, 288(%r15) + adcq 296(%r10), %rcx + movq 304(%r15), %r8 + movq %rcx, 296(%r15) + adcq 304(%r10), %r8 + movq 312(%r15), %rax + movq %r8, 304(%r15) + adcq 312(%r10), %rax + movq 320(%r15), %rcx + movq %rax, 312(%r15) + adcq 320(%r10), %rcx + movq 328(%r15), %r8 + movq %rcx, 320(%r15) + adcq 328(%r10), %r8 + movq 336(%r15), %rax + movq %r8, 328(%r15) + adcq 336(%r10), %rax + movq 344(%r15), %rcx + movq %rax, 336(%r15) + adcq 344(%r10), %rcx + movq 352(%r15), %r8 + movq %rcx, 344(%r15) + adcq 352(%r10), %r8 + movq 360(%r15), %rax + movq %r8, 352(%r15) + adcq 360(%r10), %rax + movq 368(%r15), %rcx + movq %rax, 360(%r15) + adcq 368(%r10), %rcx + movq 376(%r15), %r8 + movq %rcx, 368(%r15) + adcq 376(%r10), %r8 + movq %r8, 376(%r15) + adcq $0, %r9 + movq %r9, 576(%rdi) + addq $192, %r15 + # Add + movq (%r15), %rax + addq (%r11), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r11), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r11), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r11), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r11), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r11), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r11), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r11), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r11), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r11), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r11), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r11), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r11), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r11), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r11), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r11), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r11), %rcx + movq 136(%r15), %r8 + movq %rcx, 128(%r15) + adcq 136(%r11), %r8 + movq 144(%r15), %rax + movq %r8, 136(%r15) + adcq 144(%r11), %rax + movq 152(%r15), %rcx + movq %rax, 144(%r15) + adcq 152(%r11), %rcx + movq 160(%r15), %r8 + movq %rcx, 152(%r15) + adcq 160(%r11), %r8 + movq 168(%r15), %rax + movq %r8, 160(%r15) + adcq 168(%r11), %rax + movq 176(%r15), %rcx + movq %rax, 168(%r15) + adcq 176(%r11), %rcx + movq 184(%r15), %r8 + movq %rcx, 176(%r15) + adcq 184(%r11), %r8 + movq 192(%r15), %rax + movq %r8, 184(%r15) + adcq 192(%r11), %rax + movq %rax, 192(%r15) + # Add to zero + movq 200(%r11), %rax + adcq $0, %rax + movq 208(%r11), %rcx + movq %rax, 200(%r15) + adcq $0, %rcx + movq 216(%r11), %r8 + movq %rcx, 208(%r15) + adcq $0, %r8 + movq 224(%r11), %rax + movq %r8, 216(%r15) + adcq $0, %rax + movq 232(%r11), %rcx + movq %rax, 224(%r15) + adcq $0, %rcx + movq 240(%r11), %r8 + movq %rcx, 232(%r15) + adcq $0, %r8 + movq 248(%r11), %rax + movq %r8, 240(%r15) + adcq $0, %rax + movq 256(%r11), %rcx + movq %rax, 248(%r15) + adcq $0, %rcx + movq 264(%r11), %r8 + movq %rcx, 256(%r15) + adcq $0, %r8 + movq 272(%r11), %rax + movq %r8, 264(%r15) + adcq $0, %rax + movq 280(%r11), %rcx + movq %rax, 272(%r15) + adcq $0, %rcx + movq 288(%r11), %r8 + movq %rcx, 280(%r15) + adcq $0, %r8 + movq 296(%r11), %rax + movq %r8, 288(%r15) + adcq $0, %rax + movq 304(%r11), %rcx + movq %rax, 296(%r15) + adcq $0, %rcx + movq 312(%r11), %r8 + movq %rcx, 304(%r15) + adcq $0, %r8 + movq 320(%r11), %rax + movq %r8, 312(%r15) + adcq $0, %rax + movq 328(%r11), %rcx + movq %rax, 320(%r15) + adcq $0, %rcx + movq 336(%r11), %r8 + movq %rcx, 328(%r15) + adcq $0, %r8 + movq 344(%r11), %rax + movq %r8, 336(%r15) + adcq $0, %rax + movq 352(%r11), %rcx + movq %rax, 344(%r15) + adcq $0, %rcx + movq 360(%r11), %r8 + movq %rcx, 352(%r15) + adcq $0, %r8 + movq 368(%r11), %rax + movq %r8, 360(%r15) + adcq $0, %rax + movq 376(%r11), %rcx + movq %rax, 368(%r15) + adcq $0, %rcx + movq %rcx, 376(%r15) + addq $1192, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_avx2_48,.-sp_3072_mul_avx2_48 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sqr_avx2_48 +.type sp_3072_sqr_avx2_48,@function +.align 16 +sp_3072_sqr_avx2_48: +#else +.globl _sp_3072_sqr_avx2_48 +.p2align 4 +_sp_3072_sqr_avx2_48: +#endif /* __APPLE__ */ + subq $984, %rsp + movq %rdi, 960(%rsp) + movq %rsi, 968(%rsp) + leaq 768(%rsp), %r8 + leaq 192(%rsi), %r9 + # Add + movq (%rsi), %rdx + xorq %rcx, %rcx + addq (%r9), %rdx + movq 8(%rsi), %rax + movq %rdx, (%r8) + adcq 8(%r9), %rax + movq 16(%rsi), %rdx + movq %rax, 8(%r8) + adcq 16(%r9), %rdx + movq 24(%rsi), %rax + movq %rdx, 16(%r8) + adcq 24(%r9), %rax + movq 32(%rsi), %rdx + movq %rax, 24(%r8) + adcq 32(%r9), %rdx + movq 40(%rsi), %rax + movq %rdx, 32(%r8) + adcq 40(%r9), %rax + movq 48(%rsi), %rdx + movq %rax, 40(%r8) + adcq 48(%r9), %rdx + movq 56(%rsi), %rax + movq %rdx, 48(%r8) + adcq 56(%r9), %rax + movq 64(%rsi), %rdx + movq %rax, 56(%r8) + adcq 64(%r9), %rdx + movq 72(%rsi), %rax + movq %rdx, 64(%r8) + adcq 72(%r9), %rax + movq 80(%rsi), %rdx + movq %rax, 72(%r8) + adcq 80(%r9), %rdx + movq 88(%rsi), %rax + movq %rdx, 80(%r8) + adcq 88(%r9), %rax + movq 96(%rsi), %rdx + movq %rax, 88(%r8) + adcq 96(%r9), %rdx + movq 104(%rsi), %rax + movq %rdx, 96(%r8) + adcq 104(%r9), %rax + movq 112(%rsi), %rdx + movq %rax, 104(%r8) + adcq 112(%r9), %rdx + movq 120(%rsi), %rax + movq %rdx, 112(%r8) + adcq 120(%r9), %rax + movq 128(%rsi), %rdx + movq %rax, 120(%r8) + adcq 128(%r9), %rdx + movq 136(%rsi), %rax + movq %rdx, 128(%r8) + adcq 136(%r9), %rax + movq 144(%rsi), %rdx + movq %rax, 136(%r8) + adcq 144(%r9), %rdx + movq 152(%rsi), %rax + movq %rdx, 144(%r8) + adcq 152(%r9), %rax + movq 160(%rsi), %rdx + movq %rax, 152(%r8) + adcq 160(%r9), %rdx + movq 168(%rsi), %rax + movq %rdx, 160(%r8) + adcq 168(%r9), %rax + movq 176(%rsi), %rdx + movq %rax, 168(%r8) + adcq 176(%r9), %rdx + movq 184(%rsi), %rax + movq %rdx, 176(%r8) + adcq 184(%r9), %rax + movq %rax, 184(%r8) + adcq $0, %rcx + movq %rcx, 976(%rsp) + movq %r8, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_3072_sqr_avx2_24@plt +#else + callq _sp_3072_sqr_avx2_24 +#endif /* __APPLE__ */ + movq 968(%rsp), %rsi + leaq 384(%rsp), %rdi + addq $192, %rsi +#ifndef __APPLE__ + callq sp_3072_sqr_avx2_24@plt +#else + callq _sp_3072_sqr_avx2_24 +#endif /* __APPLE__ */ + movq 968(%rsp), %rsi + movq 960(%rsp), %rdi +#ifndef __APPLE__ + callq sp_3072_sqr_avx2_24@plt +#else + callq _sp_3072_sqr_avx2_24 +#endif /* __APPLE__ */ + movq 976(%rsp), %r10 + movq %rdi, %r9 + leaq 768(%rsp), %r8 + movq %r10, %rcx + negq %r10 + addq $384, %r9 + movq (%r8), %rdx + pextq %r10, %rdx, %rdx + addq %rdx, %rdx + movq 8(%r8), %rax + movq %rdx, (%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 16(%r8), %rdx + movq %rax, 8(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 32(%r8), %rdx + movq %rax, 24(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 48(%r8), %rdx + movq %rax, 40(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 64(%r8), %rdx + movq %rax, 56(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 80(%r8), %rdx + movq %rax, 72(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 96(%r8), %rdx + movq %rax, 88(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 112(%r8), %rdx + movq %rax, 104(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 128(%r8), %rdx + movq %rax, 120(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 144(%r8), %rdx + movq %rax, 136(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 160(%r8), %rdx + movq %rax, 152(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 176(%r8), %rdx + movq %rax, 168(%r9) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r9) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq %rax, 184(%r9) + adcq $0, %rcx + leaq 384(%rsp), %rsi + movq %rsp, %r8 + movq (%r8), %rdx + subq (%rsi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rsi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rsi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rsi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rsi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rsi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rsi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rsi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rsi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rsi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rsi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rsi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rsi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rsi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rsi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rsi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rsi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rsi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rsi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rsi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rsi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rsi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rsi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rsi), %rax + movq 192(%r8), %rdx + movq %rax, 184(%r8) + sbbq 192(%rsi), %rdx + movq 200(%r8), %rax + movq %rdx, 192(%r8) + sbbq 200(%rsi), %rax + movq 208(%r8), %rdx + movq %rax, 200(%r8) + sbbq 208(%rsi), %rdx + movq 216(%r8), %rax + movq %rdx, 208(%r8) + sbbq 216(%rsi), %rax + movq 224(%r8), %rdx + movq %rax, 216(%r8) + sbbq 224(%rsi), %rdx + movq 232(%r8), %rax + movq %rdx, 224(%r8) + sbbq 232(%rsi), %rax + movq 240(%r8), %rdx + movq %rax, 232(%r8) + sbbq 240(%rsi), %rdx + movq 248(%r8), %rax + movq %rdx, 240(%r8) + sbbq 248(%rsi), %rax + movq 256(%r8), %rdx + movq %rax, 248(%r8) + sbbq 256(%rsi), %rdx + movq 264(%r8), %rax + movq %rdx, 256(%r8) + sbbq 264(%rsi), %rax + movq 272(%r8), %rdx + movq %rax, 264(%r8) + sbbq 272(%rsi), %rdx + movq 280(%r8), %rax + movq %rdx, 272(%r8) + sbbq 280(%rsi), %rax + movq 288(%r8), %rdx + movq %rax, 280(%r8) + sbbq 288(%rsi), %rdx + movq 296(%r8), %rax + movq %rdx, 288(%r8) + sbbq 296(%rsi), %rax + movq 304(%r8), %rdx + movq %rax, 296(%r8) + sbbq 304(%rsi), %rdx + movq 312(%r8), %rax + movq %rdx, 304(%r8) + sbbq 312(%rsi), %rax + movq 320(%r8), %rdx + movq %rax, 312(%r8) + sbbq 320(%rsi), %rdx + movq 328(%r8), %rax + movq %rdx, 320(%r8) + sbbq 328(%rsi), %rax + movq 336(%r8), %rdx + movq %rax, 328(%r8) + sbbq 336(%rsi), %rdx + movq 344(%r8), %rax + movq %rdx, 336(%r8) + sbbq 344(%rsi), %rax + movq 352(%r8), %rdx + movq %rax, 344(%r8) + sbbq 352(%rsi), %rdx + movq 360(%r8), %rax + movq %rdx, 352(%r8) + sbbq 360(%rsi), %rax + movq 368(%r8), %rdx + movq %rax, 360(%r8) + sbbq 368(%rsi), %rdx + movq 376(%r8), %rax + movq %rdx, 368(%r8) + sbbq 376(%rsi), %rax + movq %rax, 376(%r8) + sbbq $0, %rcx + movq (%r8), %rdx + subq (%rdi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rdi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rdi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rdi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rdi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rdi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rdi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rdi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rdi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rdi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rdi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rdi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rdi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rdi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rdi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rdi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rdi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rdi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rdi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rdi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rdi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rdi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rdi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rdi), %rax + movq 192(%r8), %rdx + movq %rax, 184(%r8) + sbbq 192(%rdi), %rdx + movq 200(%r8), %rax + movq %rdx, 192(%r8) + sbbq 200(%rdi), %rax + movq 208(%r8), %rdx + movq %rax, 200(%r8) + sbbq 208(%rdi), %rdx + movq 216(%r8), %rax + movq %rdx, 208(%r8) + sbbq 216(%rdi), %rax + movq 224(%r8), %rdx + movq %rax, 216(%r8) + sbbq 224(%rdi), %rdx + movq 232(%r8), %rax + movq %rdx, 224(%r8) + sbbq 232(%rdi), %rax + movq 240(%r8), %rdx + movq %rax, 232(%r8) + sbbq 240(%rdi), %rdx + movq 248(%r8), %rax + movq %rdx, 240(%r8) + sbbq 248(%rdi), %rax + movq 256(%r8), %rdx + movq %rax, 248(%r8) + sbbq 256(%rdi), %rdx + movq 264(%r8), %rax + movq %rdx, 256(%r8) + sbbq 264(%rdi), %rax + movq 272(%r8), %rdx + movq %rax, 264(%r8) + sbbq 272(%rdi), %rdx + movq 280(%r8), %rax + movq %rdx, 272(%r8) + sbbq 280(%rdi), %rax + movq 288(%r8), %rdx + movq %rax, 280(%r8) + sbbq 288(%rdi), %rdx + movq 296(%r8), %rax + movq %rdx, 288(%r8) + sbbq 296(%rdi), %rax + movq 304(%r8), %rdx + movq %rax, 296(%r8) + sbbq 304(%rdi), %rdx + movq 312(%r8), %rax + movq %rdx, 304(%r8) + sbbq 312(%rdi), %rax + movq 320(%r8), %rdx + movq %rax, 312(%r8) + sbbq 320(%rdi), %rdx + movq 328(%r8), %rax + movq %rdx, 320(%r8) + sbbq 328(%rdi), %rax + movq 336(%r8), %rdx + movq %rax, 328(%r8) + sbbq 336(%rdi), %rdx + movq 344(%r8), %rax + movq %rdx, 336(%r8) + sbbq 344(%rdi), %rax + movq 352(%r8), %rdx + movq %rax, 344(%r8) + sbbq 352(%rdi), %rdx + movq 360(%r8), %rax + movq %rdx, 352(%r8) + sbbq 360(%rdi), %rax + movq 368(%r8), %rdx + movq %rax, 360(%r8) + sbbq 368(%rdi), %rdx + movq 376(%r8), %rax + movq %rdx, 368(%r8) + sbbq 376(%rdi), %rax + movq %rax, 376(%r8) + sbbq $0, %rcx + subq $192, %r9 + # Add in place + movq (%r9), %rdx + addq (%r8), %rdx + movq 8(%r9), %rax + movq %rdx, (%r9) + adcq 8(%r8), %rax + movq 16(%r9), %rdx + movq %rax, 8(%r9) + adcq 16(%r8), %rdx + movq 24(%r9), %rax + movq %rdx, 16(%r9) + adcq 24(%r8), %rax + movq 32(%r9), %rdx + movq %rax, 24(%r9) + adcq 32(%r8), %rdx + movq 40(%r9), %rax + movq %rdx, 32(%r9) + adcq 40(%r8), %rax + movq 48(%r9), %rdx + movq %rax, 40(%r9) + adcq 48(%r8), %rdx + movq 56(%r9), %rax + movq %rdx, 48(%r9) + adcq 56(%r8), %rax + movq 64(%r9), %rdx + movq %rax, 56(%r9) + adcq 64(%r8), %rdx + movq 72(%r9), %rax + movq %rdx, 64(%r9) + adcq 72(%r8), %rax + movq 80(%r9), %rdx + movq %rax, 72(%r9) + adcq 80(%r8), %rdx + movq 88(%r9), %rax + movq %rdx, 80(%r9) + adcq 88(%r8), %rax + movq 96(%r9), %rdx + movq %rax, 88(%r9) + adcq 96(%r8), %rdx + movq 104(%r9), %rax + movq %rdx, 96(%r9) + adcq 104(%r8), %rax + movq 112(%r9), %rdx + movq %rax, 104(%r9) + adcq 112(%r8), %rdx + movq 120(%r9), %rax + movq %rdx, 112(%r9) + adcq 120(%r8), %rax + movq 128(%r9), %rdx + movq %rax, 120(%r9) + adcq 128(%r8), %rdx + movq 136(%r9), %rax + movq %rdx, 128(%r9) + adcq 136(%r8), %rax + movq 144(%r9), %rdx + movq %rax, 136(%r9) + adcq 144(%r8), %rdx + movq 152(%r9), %rax + movq %rdx, 144(%r9) + adcq 152(%r8), %rax + movq 160(%r9), %rdx + movq %rax, 152(%r9) + adcq 160(%r8), %rdx + movq 168(%r9), %rax + movq %rdx, 160(%r9) + adcq 168(%r8), %rax + movq 176(%r9), %rdx + movq %rax, 168(%r9) + adcq 176(%r8), %rdx + movq 184(%r9), %rax + movq %rdx, 176(%r9) + adcq 184(%r8), %rax + movq 192(%r9), %rdx + movq %rax, 184(%r9) + adcq 192(%r8), %rdx + movq 200(%r9), %rax + movq %rdx, 192(%r9) + adcq 200(%r8), %rax + movq 208(%r9), %rdx + movq %rax, 200(%r9) + adcq 208(%r8), %rdx + movq 216(%r9), %rax + movq %rdx, 208(%r9) + adcq 216(%r8), %rax + movq 224(%r9), %rdx + movq %rax, 216(%r9) + adcq 224(%r8), %rdx + movq 232(%r9), %rax + movq %rdx, 224(%r9) + adcq 232(%r8), %rax + movq 240(%r9), %rdx + movq %rax, 232(%r9) + adcq 240(%r8), %rdx + movq 248(%r9), %rax + movq %rdx, 240(%r9) + adcq 248(%r8), %rax + movq 256(%r9), %rdx + movq %rax, 248(%r9) + adcq 256(%r8), %rdx + movq 264(%r9), %rax + movq %rdx, 256(%r9) + adcq 264(%r8), %rax + movq 272(%r9), %rdx + movq %rax, 264(%r9) + adcq 272(%r8), %rdx + movq 280(%r9), %rax + movq %rdx, 272(%r9) + adcq 280(%r8), %rax + movq 288(%r9), %rdx + movq %rax, 280(%r9) + adcq 288(%r8), %rdx + movq 296(%r9), %rax + movq %rdx, 288(%r9) + adcq 296(%r8), %rax + movq 304(%r9), %rdx + movq %rax, 296(%r9) + adcq 304(%r8), %rdx + movq 312(%r9), %rax + movq %rdx, 304(%r9) + adcq 312(%r8), %rax + movq 320(%r9), %rdx + movq %rax, 312(%r9) + adcq 320(%r8), %rdx + movq 328(%r9), %rax + movq %rdx, 320(%r9) + adcq 328(%r8), %rax + movq 336(%r9), %rdx + movq %rax, 328(%r9) + adcq 336(%r8), %rdx + movq 344(%r9), %rax + movq %rdx, 336(%r9) + adcq 344(%r8), %rax + movq 352(%r9), %rdx + movq %rax, 344(%r9) + adcq 352(%r8), %rdx + movq 360(%r9), %rax + movq %rdx, 352(%r9) + adcq 360(%r8), %rax + movq 368(%r9), %rdx + movq %rax, 360(%r9) + adcq 368(%r8), %rdx + movq 376(%r9), %rax + movq %rdx, 368(%r9) + adcq 376(%r8), %rax + movq %rax, 376(%r9) + adcq $0, %rcx + movq %rcx, 576(%rdi) + # Add in place + movq 192(%r9), %rdx + addq (%rsi), %rdx + movq 200(%r9), %rax + movq %rdx, 192(%r9) + adcq 8(%rsi), %rax + movq 208(%r9), %rdx + movq %rax, 200(%r9) + adcq 16(%rsi), %rdx + movq 216(%r9), %rax + movq %rdx, 208(%r9) + adcq 24(%rsi), %rax + movq 224(%r9), %rdx + movq %rax, 216(%r9) + adcq 32(%rsi), %rdx + movq 232(%r9), %rax + movq %rdx, 224(%r9) + adcq 40(%rsi), %rax + movq 240(%r9), %rdx + movq %rax, 232(%r9) + adcq 48(%rsi), %rdx + movq 248(%r9), %rax + movq %rdx, 240(%r9) + adcq 56(%rsi), %rax + movq 256(%r9), %rdx + movq %rax, 248(%r9) + adcq 64(%rsi), %rdx + movq 264(%r9), %rax + movq %rdx, 256(%r9) + adcq 72(%rsi), %rax + movq 272(%r9), %rdx + movq %rax, 264(%r9) + adcq 80(%rsi), %rdx + movq 280(%r9), %rax + movq %rdx, 272(%r9) + adcq 88(%rsi), %rax + movq 288(%r9), %rdx + movq %rax, 280(%r9) + adcq 96(%rsi), %rdx + movq 296(%r9), %rax + movq %rdx, 288(%r9) + adcq 104(%rsi), %rax + movq 304(%r9), %rdx + movq %rax, 296(%r9) + adcq 112(%rsi), %rdx + movq 312(%r9), %rax + movq %rdx, 304(%r9) + adcq 120(%rsi), %rax + movq 320(%r9), %rdx + movq %rax, 312(%r9) + adcq 128(%rsi), %rdx + movq 328(%r9), %rax + movq %rdx, 320(%r9) + adcq 136(%rsi), %rax + movq 336(%r9), %rdx + movq %rax, 328(%r9) + adcq 144(%rsi), %rdx + movq 344(%r9), %rax + movq %rdx, 336(%r9) + adcq 152(%rsi), %rax + movq 352(%r9), %rdx + movq %rax, 344(%r9) + adcq 160(%rsi), %rdx + movq 360(%r9), %rax + movq %rdx, 352(%r9) + adcq 168(%rsi), %rax + movq 368(%r9), %rdx + movq %rax, 360(%r9) + adcq 176(%rsi), %rdx + movq 376(%r9), %rax + movq %rdx, 368(%r9) + adcq 184(%rsi), %rax + movq 384(%r9), %rdx + movq %rax, 376(%r9) + adcq 192(%rsi), %rdx + movq %rdx, 384(%r9) + # Add to zero + movq 200(%rsi), %rdx + adcq $0, %rdx + movq 208(%rsi), %rax + movq %rdx, 392(%r9) + adcq $0, %rax + movq 216(%rsi), %rdx + movq %rax, 400(%r9) + adcq $0, %rdx + movq 224(%rsi), %rax + movq %rdx, 408(%r9) + adcq $0, %rax + movq 232(%rsi), %rdx + movq %rax, 416(%r9) + adcq $0, %rdx + movq 240(%rsi), %rax + movq %rdx, 424(%r9) + adcq $0, %rax + movq 248(%rsi), %rdx + movq %rax, 432(%r9) + adcq $0, %rdx + movq 256(%rsi), %rax + movq %rdx, 440(%r9) + adcq $0, %rax + movq 264(%rsi), %rdx + movq %rax, 448(%r9) + adcq $0, %rdx + movq 272(%rsi), %rax + movq %rdx, 456(%r9) + adcq $0, %rax + movq 280(%rsi), %rdx + movq %rax, 464(%r9) + adcq $0, %rdx + movq 288(%rsi), %rax + movq %rdx, 472(%r9) + adcq $0, %rax + movq 296(%rsi), %rdx + movq %rax, 480(%r9) + adcq $0, %rdx + movq 304(%rsi), %rax + movq %rdx, 488(%r9) + adcq $0, %rax + movq 312(%rsi), %rdx + movq %rax, 496(%r9) + adcq $0, %rdx + movq 320(%rsi), %rax + movq %rdx, 504(%r9) + adcq $0, %rax + movq 328(%rsi), %rdx + movq %rax, 512(%r9) + adcq $0, %rdx + movq 336(%rsi), %rax + movq %rdx, 520(%r9) + adcq $0, %rax + movq 344(%rsi), %rdx + movq %rax, 528(%r9) + adcq $0, %rdx + movq 352(%rsi), %rax + movq %rdx, 536(%r9) + adcq $0, %rax + movq 360(%rsi), %rdx + movq %rax, 544(%r9) + adcq $0, %rdx + movq 368(%rsi), %rax + movq %rdx, 552(%r9) + adcq $0, %rax + movq 376(%rsi), %rdx + movq %rax, 560(%r9) + adcq $0, %rdx + movq %rdx, 568(%r9) + addq $984, %rsp + repz retq +#ifndef __APPLE__ +.size sp_3072_sqr_avx2_48,.-sp_3072_sqr_avx2_48 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_d_48 +.type sp_3072_mul_d_48,@function +.align 16 +sp_3072_mul_d_48: +#else +.globl _sp_3072_mul_d_48 +.p2align 4 +_sp_3072_mul_d_48: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 24(%rsi) + addq %rax, %r8 + movq %r8, 24(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 32(%rsi) + addq %rax, %r9 + movq %r9, 32(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 40(%rsi) + addq %rax, %r10 + movq %r10, 40(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 48(%rsi) + addq %rax, %r8 + movq %r8, 48(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 56(%rsi) + addq %rax, %r9 + movq %r9, 56(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 64(%rsi) + addq %rax, %r10 + movq %r10, 64(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 72(%rsi) + addq %rax, %r8 + movq %r8, 72(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 80(%rsi) + addq %rax, %r9 + movq %r9, 80(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 88(%rsi) + addq %rax, %r10 + movq %r10, 88(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 96(%rsi) + addq %rax, %r8 + movq %r8, 96(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 104(%rsi) + addq %rax, %r9 + movq %r9, 104(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 112(%rsi) + addq %rax, %r10 + movq %r10, 112(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 120(%rsi) + addq %rax, %r8 + movq %r8, 120(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 128(%rsi) + addq %rax, %r9 + movq %r9, 128(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 136(%rsi) + addq %rax, %r10 + movq %r10, 136(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 144(%rsi) + addq %rax, %r8 + movq %r8, 144(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 152(%rsi) + addq %rax, %r9 + movq %r9, 152(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 160(%rsi) + addq %rax, %r10 + movq %r10, 160(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 168(%rsi) + addq %rax, %r8 + movq %r8, 168(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 176(%rsi) + addq %rax, %r9 + movq %r9, 176(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 184(%rsi) + addq %rax, %r10 + movq %r10, 184(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[24] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 192(%rsi) + addq %rax, %r8 + movq %r8, 192(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[25] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 200(%rsi) + addq %rax, %r9 + movq %r9, 200(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[26] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 208(%rsi) + addq %rax, %r10 + movq %r10, 208(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[27] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 216(%rsi) + addq %rax, %r8 + movq %r8, 216(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[28] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 224(%rsi) + addq %rax, %r9 + movq %r9, 224(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[29] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 232(%rsi) + addq %rax, %r10 + movq %r10, 232(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[30] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 240(%rsi) + addq %rax, %r8 + movq %r8, 240(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[31] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 248(%rsi) + addq %rax, %r9 + movq %r9, 248(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[32] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 256(%rsi) + addq %rax, %r10 + movq %r10, 256(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[33] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 264(%rsi) + addq %rax, %r8 + movq %r8, 264(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[34] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 272(%rsi) + addq %rax, %r9 + movq %r9, 272(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[35] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 280(%rsi) + addq %rax, %r10 + movq %r10, 280(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[36] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 288(%rsi) + addq %rax, %r8 + movq %r8, 288(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[37] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 296(%rsi) + addq %rax, %r9 + movq %r9, 296(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[38] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 304(%rsi) + addq %rax, %r10 + movq %r10, 304(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[39] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 312(%rsi) + addq %rax, %r8 + movq %r8, 312(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[40] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 320(%rsi) + addq %rax, %r9 + movq %r9, 320(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[41] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 328(%rsi) + addq %rax, %r10 + movq %r10, 328(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[42] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 336(%rsi) + addq %rax, %r8 + movq %r8, 336(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[43] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 344(%rsi) + addq %rax, %r9 + movq %r9, 344(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[44] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 352(%rsi) + addq %rax, %r10 + movq %r10, 352(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[45] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 360(%rsi) + addq %rax, %r8 + movq %r8, 360(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[46] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 368(%rsi) + addq %rax, %r9 + movq %r9, 368(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[47] * B + movq %rcx, %rax + mulq 376(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + movq %r10, 376(%rdi) + movq %r8, 384(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_d_48,.-sp_3072_mul_d_48 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_cond_sub_24 +.type sp_3072_cond_sub_24,@function +.align 16 +sp_3072_cond_sub_24: +#else +.globl _sp_3072_cond_sub_24 +.p2align 4 +_sp_3072_cond_sub_24: +#endif /* __APPLE__ */ + subq $192, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq 128(%rdx), %r8 + movq 136(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 128(%rsp) + movq %r9, 136(%rsp) + movq 144(%rdx), %r8 + movq 152(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 144(%rsp) + movq %r9, 152(%rsp) + movq 160(%rdx), %r8 + movq 168(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r9, 168(%rsp) + movq 176(%rdx), %r8 + movq 184(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 176(%rsp) + movq %r9, 184(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + subq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 112(%rdi) + movq 128(%rsi), %r8 + movq 128(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 120(%rdi) + movq 136(%rsi), %r9 + movq 136(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 128(%rdi) + movq 144(%rsi), %r8 + movq 144(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 136(%rdi) + movq 152(%rsi), %r9 + movq 152(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 144(%rdi) + movq 160(%rsi), %r8 + movq 160(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 152(%rdi) + movq 168(%rsi), %r9 + movq 168(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 160(%rdi) + movq 176(%rsi), %r8 + movq 176(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 168(%rdi) + movq 184(%rsi), %r9 + movq 184(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 176(%rdi) + movq %r9, 184(%rdi) + sbbq $0, %rax + addq $192, %rsp + repz retq +#ifndef __APPLE__ +.size sp_3072_cond_sub_24,.-sp_3072_cond_sub_24 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_mont_reduce_24 +.type sp_3072_mont_reduce_24,@function +.align 16 +sp_3072_mont_reduce_24: +#else +.globl _sp_3072_mont_reduce_24 +.p2align 4 +_sp_3072_mont_reduce_24: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rcx + xorq %r15, %r15 + # i = 24 + movq $24, %r8 + movq (%rdi), %r13 + movq 8(%rdi), %r14 +L_mont_loop_24: + # mu = a[i] * mp + movq %r13, %r11 + imulq %rcx, %r11 + # a[i+0] += m[0] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq (%rsi) + addq %rax, %r13 + adcq %rdx, %r10 + # a[i+1] += m[1] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 8(%rsi) + movq %r14, %r13 + addq %rax, %r13 + adcq %rdx, %r9 + addq %r10, %r13 + adcq $0, %r9 + # a[i+2] += m[2] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 16(%rsi) + movq 16(%rdi), %r14 + addq %rax, %r14 + adcq %rdx, %r10 + addq %r9, %r14 + adcq $0, %r10 + # a[i+3] += m[3] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 24(%rsi) + movq 24(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 24(%rdi) + adcq $0, %r9 + # a[i+4] += m[4] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 32(%rsi) + movq 32(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 32(%rdi) + adcq $0, %r10 + # a[i+5] += m[5] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 40(%rsi) + movq 40(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 40(%rdi) + adcq $0, %r9 + # a[i+6] += m[6] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 48(%rsi) + movq 48(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 48(%rdi) + adcq $0, %r10 + # a[i+7] += m[7] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 56(%rsi) + movq 56(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 56(%rdi) + adcq $0, %r9 + # a[i+8] += m[8] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 64(%rsi) + movq 64(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 64(%rdi) + adcq $0, %r10 + # a[i+9] += m[9] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 72(%rsi) + movq 72(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 72(%rdi) + adcq $0, %r9 + # a[i+10] += m[10] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 80(%rsi) + movq 80(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 80(%rdi) + adcq $0, %r10 + # a[i+11] += m[11] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 88(%rsi) + movq 88(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 88(%rdi) + adcq $0, %r9 + # a[i+12] += m[12] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 96(%rsi) + movq 96(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 96(%rdi) + adcq $0, %r10 + # a[i+13] += m[13] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 104(%rsi) + movq 104(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 104(%rdi) + adcq $0, %r9 + # a[i+14] += m[14] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 112(%rsi) + movq 112(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 112(%rdi) + adcq $0, %r10 + # a[i+15] += m[15] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 120(%rsi) + movq 120(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 120(%rdi) + adcq $0, %r9 + # a[i+16] += m[16] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 128(%rsi) + movq 128(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 128(%rdi) + adcq $0, %r10 + # a[i+17] += m[17] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 136(%rsi) + movq 136(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 136(%rdi) + adcq $0, %r9 + # a[i+18] += m[18] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 144(%rsi) + movq 144(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 144(%rdi) + adcq $0, %r10 + # a[i+19] += m[19] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 152(%rsi) + movq 152(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 152(%rdi) + adcq $0, %r9 + # a[i+20] += m[20] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 160(%rsi) + movq 160(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 160(%rdi) + adcq $0, %r10 + # a[i+21] += m[21] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 168(%rsi) + movq 168(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 168(%rdi) + adcq $0, %r9 + # a[i+22] += m[22] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 176(%rsi) + movq 176(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 176(%rdi) + adcq $0, %r10 + # a[i+23] += m[23] * mu + movq %r11, %rax + mulq 184(%rsi) + movq 184(%rdi), %r12 + addq %rax, %r10 + adcq %r15, %rdx + movq $0, %r15 + adcq $0, %r15 + addq %r10, %r12 + movq %r12, 184(%rdi) + adcq %rdx, 192(%rdi) + adcq $0, %r15 + # i -= 1 + addq $8, %rdi + decq %r8 + jnz L_mont_loop_24 + movq %r13, (%rdi) + movq %r14, 8(%rdi) + negq %r15 + movq %r15, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + subq $192, %rdi +#ifndef __APPLE__ + callq sp_3072_cond_sub_24@plt +#else + callq _sp_3072_cond_sub_24 +#endif /* __APPLE__ */ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_mont_reduce_24,.-sp_3072_mont_reduce_24 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_cond_sub_avx2_24 +.type sp_3072_cond_sub_avx2_24,@function +.align 16 +sp_3072_cond_sub_avx2_24: +#else +.globl _sp_3072_cond_sub_avx2_24 +.p2align 4 +_sp_3072_cond_sub_avx2_24: +#endif /* __APPLE__ */ + movq $0, %rax + movq (%rdx), %r10 + movq (%rsi), %r8 + pextq %rcx, %r10, %r10 + subq %r10, %r8 + movq 8(%rdx), %r10 + movq 8(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, (%rdi) + sbbq %r10, %r9 + movq 16(%rdx), %r8 + movq 16(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 8(%rdi) + sbbq %r8, %r10 + movq 24(%rdx), %r9 + movq 24(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 16(%rdi) + sbbq %r9, %r8 + movq 32(%rdx), %r10 + movq 32(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 24(%rdi) + sbbq %r10, %r9 + movq 40(%rdx), %r8 + movq 40(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 32(%rdi) + sbbq %r8, %r10 + movq 48(%rdx), %r9 + movq 48(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 40(%rdi) + sbbq %r9, %r8 + movq 56(%rdx), %r10 + movq 56(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 48(%rdi) + sbbq %r10, %r9 + movq 64(%rdx), %r8 + movq 64(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 56(%rdi) + sbbq %r8, %r10 + movq 72(%rdx), %r9 + movq 72(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 64(%rdi) + sbbq %r9, %r8 + movq 80(%rdx), %r10 + movq 80(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 72(%rdi) + sbbq %r10, %r9 + movq 88(%rdx), %r8 + movq 88(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 80(%rdi) + sbbq %r8, %r10 + movq 96(%rdx), %r9 + movq 96(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 88(%rdi) + sbbq %r9, %r8 + movq 104(%rdx), %r10 + movq 104(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 96(%rdi) + sbbq %r10, %r9 + movq 112(%rdx), %r8 + movq 112(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 104(%rdi) + sbbq %r8, %r10 + movq 120(%rdx), %r9 + movq 120(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 112(%rdi) + sbbq %r9, %r8 + movq 128(%rdx), %r10 + movq 128(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 120(%rdi) + sbbq %r10, %r9 + movq 136(%rdx), %r8 + movq 136(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 128(%rdi) + sbbq %r8, %r10 + movq 144(%rdx), %r9 + movq 144(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 136(%rdi) + sbbq %r9, %r8 + movq 152(%rdx), %r10 + movq 152(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 144(%rdi) + sbbq %r10, %r9 + movq 160(%rdx), %r8 + movq 160(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 152(%rdi) + sbbq %r8, %r10 + movq 168(%rdx), %r9 + movq 168(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 160(%rdi) + sbbq %r9, %r8 + movq 176(%rdx), %r10 + movq 176(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 168(%rdi) + sbbq %r10, %r9 + movq 184(%rdx), %r8 + movq 184(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 176(%rdi) + sbbq %r8, %r10 + movq %r10, 184(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_cond_sub_avx2_24,.-sp_3072_cond_sub_avx2_24 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_d_24 +.type sp_3072_mul_d_24,@function +.align 16 +sp_3072_mul_d_24: +#else +.globl _sp_3072_mul_d_24 +.p2align 4 +_sp_3072_mul_d_24: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 24(%rsi) + addq %rax, %r8 + movq %r8, 24(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 32(%rsi) + addq %rax, %r9 + movq %r9, 32(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 40(%rsi) + addq %rax, %r10 + movq %r10, 40(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 48(%rsi) + addq %rax, %r8 + movq %r8, 48(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 56(%rsi) + addq %rax, %r9 + movq %r9, 56(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 64(%rsi) + addq %rax, %r10 + movq %r10, 64(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 72(%rsi) + addq %rax, %r8 + movq %r8, 72(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 80(%rsi) + addq %rax, %r9 + movq %r9, 80(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 88(%rsi) + addq %rax, %r10 + movq %r10, 88(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 96(%rsi) + addq %rax, %r8 + movq %r8, 96(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 104(%rsi) + addq %rax, %r9 + movq %r9, 104(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 112(%rsi) + addq %rax, %r10 + movq %r10, 112(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 120(%rsi) + addq %rax, %r8 + movq %r8, 120(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 128(%rsi) + addq %rax, %r9 + movq %r9, 128(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 136(%rsi) + addq %rax, %r10 + movq %r10, 136(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 144(%rsi) + addq %rax, %r8 + movq %r8, 144(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 152(%rsi) + addq %rax, %r9 + movq %r9, 152(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 160(%rsi) + addq %rax, %r10 + movq %r10, 160(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 168(%rsi) + addq %rax, %r8 + movq %r8, 168(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 176(%rsi) + addq %rax, %r9 + movq %r9, 176(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B + movq %rcx, %rax + mulq 184(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + movq %r10, 184(%rdi) + movq %r8, 192(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_d_24,.-sp_3072_mul_d_24 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_d_avx2_24 +.type sp_3072_mul_d_avx2_24,@function +.align 16 +sp_3072_mul_d_avx2_24: +#else +.globl _sp_3072_mul_d_avx2_24 +.p2align 4 +_sp_3072_mul_d_avx2_24: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 8(%rdi) + adoxq %r8, %r9 + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 16(%rdi) + adoxq %r8, %r10 + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 24(%rdi) + adoxq %r8, %r9 + # A[4] * B + mulxq 32(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 32(%rdi) + adoxq %r8, %r10 + # A[5] * B + mulxq 40(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 40(%rdi) + adoxq %r8, %r9 + # A[6] * B + mulxq 48(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 48(%rdi) + adoxq %r8, %r10 + # A[7] * B + mulxq 56(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 56(%rdi) + adoxq %r8, %r9 + # A[8] * B + mulxq 64(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 64(%rdi) + adoxq %r8, %r10 + # A[9] * B + mulxq 72(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 72(%rdi) + adoxq %r8, %r9 + # A[10] * B + mulxq 80(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 80(%rdi) + adoxq %r8, %r10 + # A[11] * B + mulxq 88(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 88(%rdi) + adoxq %r8, %r9 + # A[12] * B + mulxq 96(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 96(%rdi) + adoxq %r8, %r10 + # A[13] * B + mulxq 104(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 104(%rdi) + adoxq %r8, %r9 + # A[14] * B + mulxq 112(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 112(%rdi) + adoxq %r8, %r10 + # A[15] * B + mulxq 120(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 120(%rdi) + adoxq %r8, %r9 + # A[16] * B + mulxq 128(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 128(%rdi) + adoxq %r8, %r10 + # A[17] * B + mulxq 136(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 136(%rdi) + adoxq %r8, %r9 + # A[18] * B + mulxq 144(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 144(%rdi) + adoxq %r8, %r10 + # A[19] * B + mulxq 152(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 152(%rdi) + adoxq %r8, %r9 + # A[20] * B + mulxq 160(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 160(%rdi) + adoxq %r8, %r10 + # A[21] * B + mulxq 168(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 168(%rdi) + adoxq %r8, %r9 + # A[22] * B + mulxq 176(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 176(%rdi) + adoxq %r8, %r10 + # A[23] * B + mulxq 184(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 184(%rdi) + movq %r9, 192(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_d_avx2_24,.-sp_3072_mul_d_avx2_24 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_cmp_24 +.type sp_3072_cmp_24,@function +.align 16 +sp_3072_cmp_24: +#else +.globl _sp_3072_cmp_24 +.p2align 4 +_sp_3072_cmp_24: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $1, %r8 + movq 184(%rdi), %r9 + movq 184(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 176(%rdi), %r9 + movq 176(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 168(%rdi), %r9 + movq 168(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 160(%rdi), %r9 + movq 160(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 152(%rdi), %r9 + movq 152(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 144(%rdi), %r9 + movq 144(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 136(%rdi), %r9 + movq 136(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 128(%rdi), %r9 + movq 128(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 120(%rdi), %r9 + movq 120(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 112(%rdi), %r9 + movq 112(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 104(%rdi), %r9 + movq 104(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 96(%rdi), %r9 + movq 96(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 88(%rdi), %r9 + movq 88(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 80(%rdi), %r9 + movq 80(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 72(%rdi), %r9 + movq 72(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 64(%rdi), %r9 + movq 64(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 56(%rdi), %r9 + movq 56(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 48(%rdi), %r9 + movq 48(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 40(%rdi), %r9 + movq 40(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 32(%rdi), %r9 + movq 32(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_cmp_24,.-sp_3072_cmp_24 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_mont_reduce_avx2_24 +.type sp_3072_mont_reduce_avx2_24,@function +.align 16 +sp_3072_mont_reduce_avx2_24: +#else +.globl _sp_3072_mont_reduce_avx2_24 +.p2align 4 +_sp_3072_mont_reduce_avx2_24: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + movq %rdx, %r8 + xorq %r14, %r14 + # i = 24 + movq $24, %r9 + movq (%rdi), %r13 + addq $96, %rdi + xorq %r12, %r12 +L_mont_loop_avx2_24: + # mu = a[i] * mp + movq %r13, %rdx + movq %r13, %r10 + imulq %r8, %rdx + xorq %r12, %r12 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rax, %rcx + movq -88(%rdi), %r13 + adcxq %rax, %r10 + adoxq %rcx, %r13 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rax, %rcx + movq -80(%rdi), %r10 + adcxq %rax, %r13 + adoxq %rcx, %r10 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rax, %rcx + movq -72(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -80(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rax, %rcx + movq -64(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -72(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rax, %rcx + movq -56(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -64(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rax, %rcx + movq -48(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -56(%rdi) + # a[i+6] += m[6] * mu + mulxq 48(%rsi), %rax, %rcx + movq -40(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -48(%rdi) + # a[i+7] += m[7] * mu + mulxq 56(%rsi), %rax, %rcx + movq -32(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -40(%rdi) + # a[i+8] += m[8] * mu + mulxq 64(%rsi), %rax, %rcx + movq -24(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -32(%rdi) + # a[i+9] += m[9] * mu + mulxq 72(%rsi), %rax, %rcx + movq -16(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -24(%rdi) + # a[i+10] += m[10] * mu + mulxq 80(%rsi), %rax, %rcx + movq -8(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -16(%rdi) + # a[i+11] += m[11] * mu + mulxq 88(%rsi), %rax, %rcx + movq (%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -8(%rdi) + # a[i+12] += m[12] * mu + mulxq 96(%rsi), %rax, %rcx + movq 8(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, (%rdi) + # a[i+13] += m[13] * mu + mulxq 104(%rsi), %rax, %rcx + movq 16(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 8(%rdi) + # a[i+14] += m[14] * mu + mulxq 112(%rsi), %rax, %rcx + movq 24(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 16(%rdi) + # a[i+15] += m[15] * mu + mulxq 120(%rsi), %rax, %rcx + movq 32(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 24(%rdi) + # a[i+16] += m[16] * mu + mulxq 128(%rsi), %rax, %rcx + movq 40(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 32(%rdi) + # a[i+17] += m[17] * mu + mulxq 136(%rsi), %rax, %rcx + movq 48(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 40(%rdi) + # a[i+18] += m[18] * mu + mulxq 144(%rsi), %rax, %rcx + movq 56(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 48(%rdi) + # a[i+19] += m[19] * mu + mulxq 152(%rsi), %rax, %rcx + movq 64(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 56(%rdi) + # a[i+20] += m[20] * mu + mulxq 160(%rsi), %rax, %rcx + movq 72(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 64(%rdi) + # a[i+21] += m[21] * mu + mulxq 168(%rsi), %rax, %rcx + movq 80(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 72(%rdi) + # a[i+22] += m[22] * mu + mulxq 176(%rsi), %rax, %rcx + movq 88(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 80(%rdi) + # a[i+23] += m[23] * mu + mulxq 184(%rsi), %rax, %rcx + movq 96(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 88(%rdi) + adcxq %r14, %r10 + movq %r10, 96(%rdi) + movq %r12, %r14 + adoxq %r12, %r14 + adcxq %r12, %r14 + # a += 1 + addq $8, %rdi + # i -= 1 + subq $1, %r9 + jnz L_mont_loop_avx2_24 + subq $96, %rdi + negq %r14 + movq %rdi, %r8 + subq $192, %rdi + movq (%rsi), %rcx + movq %r13, %rdx + pextq %r14, %rcx, %rcx + subq %rcx, %rdx + movq 8(%rsi), %rcx + movq 8(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, (%rdi) + sbbq %rcx, %rax + movq 16(%rsi), %rdx + movq 16(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 8(%rdi) + sbbq %rdx, %rcx + movq 24(%rsi), %rax + movq 24(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 16(%rdi) + sbbq %rax, %rdx + movq 32(%rsi), %rcx + movq 32(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 24(%rdi) + sbbq %rcx, %rax + movq 40(%rsi), %rdx + movq 40(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 32(%rdi) + sbbq %rdx, %rcx + movq 48(%rsi), %rax + movq 48(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 40(%rdi) + sbbq %rax, %rdx + movq 56(%rsi), %rcx + movq 56(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 48(%rdi) + sbbq %rcx, %rax + movq 64(%rsi), %rdx + movq 64(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 56(%rdi) + sbbq %rdx, %rcx + movq 72(%rsi), %rax + movq 72(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 64(%rdi) + sbbq %rax, %rdx + movq 80(%rsi), %rcx + movq 80(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 72(%rdi) + sbbq %rcx, %rax + movq 88(%rsi), %rdx + movq 88(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 80(%rdi) + sbbq %rdx, %rcx + movq 96(%rsi), %rax + movq 96(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 88(%rdi) + sbbq %rax, %rdx + movq 104(%rsi), %rcx + movq 104(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 96(%rdi) + sbbq %rcx, %rax + movq 112(%rsi), %rdx + movq 112(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 104(%rdi) + sbbq %rdx, %rcx + movq 120(%rsi), %rax + movq 120(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 112(%rdi) + sbbq %rax, %rdx + movq 128(%rsi), %rcx + movq 128(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 120(%rdi) + sbbq %rcx, %rax + movq 136(%rsi), %rdx + movq 136(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 128(%rdi) + sbbq %rdx, %rcx + movq 144(%rsi), %rax + movq 144(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 136(%rdi) + sbbq %rax, %rdx + movq 152(%rsi), %rcx + movq 152(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 144(%rdi) + sbbq %rcx, %rax + movq 160(%rsi), %rdx + movq 160(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 152(%rdi) + sbbq %rdx, %rcx + movq 168(%rsi), %rax + movq 168(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 160(%rdi) + sbbq %rax, %rdx + movq 176(%rsi), %rcx + movq 176(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 168(%rdi) + sbbq %rcx, %rax + movq 184(%rsi), %rdx + movq 184(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 176(%rdi) + sbbq %rdx, %rcx + movq %rcx, 184(%rdi) + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_mont_reduce_avx2_24,.-sp_3072_mont_reduce_avx2_24 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_cond_sub_48 +.type sp_3072_cond_sub_48,@function +.align 16 +sp_3072_cond_sub_48: +#else +.globl _sp_3072_cond_sub_48 +.p2align 4 +_sp_3072_cond_sub_48: +#endif /* __APPLE__ */ + subq $384, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq 128(%rdx), %r8 + movq 136(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 128(%rsp) + movq %r9, 136(%rsp) + movq 144(%rdx), %r8 + movq 152(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 144(%rsp) + movq %r9, 152(%rsp) + movq 160(%rdx), %r8 + movq 168(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r9, 168(%rsp) + movq 176(%rdx), %r8 + movq 184(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 176(%rsp) + movq %r9, 184(%rsp) + movq 192(%rdx), %r8 + movq 200(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 192(%rsp) + movq %r9, 200(%rsp) + movq 208(%rdx), %r8 + movq 216(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 208(%rsp) + movq %r9, 216(%rsp) + movq 224(%rdx), %r8 + movq 232(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 224(%rsp) + movq %r9, 232(%rsp) + movq 240(%rdx), %r8 + movq 248(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 240(%rsp) + movq %r9, 248(%rsp) + movq 256(%rdx), %r8 + movq 264(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 256(%rsp) + movq %r9, 264(%rsp) + movq 272(%rdx), %r8 + movq 280(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 272(%rsp) + movq %r9, 280(%rsp) + movq 288(%rdx), %r8 + movq 296(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 288(%rsp) + movq %r9, 296(%rsp) + movq 304(%rdx), %r8 + movq 312(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 304(%rsp) + movq %r9, 312(%rsp) + movq 320(%rdx), %r8 + movq 328(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 320(%rsp) + movq %r9, 328(%rsp) + movq 336(%rdx), %r8 + movq 344(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 336(%rsp) + movq %r9, 344(%rsp) + movq 352(%rdx), %r8 + movq 360(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 352(%rsp) + movq %r9, 360(%rsp) + movq 368(%rdx), %r8 + movq 376(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 368(%rsp) + movq %r9, 376(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + subq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 112(%rdi) + movq 128(%rsi), %r8 + movq 128(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 120(%rdi) + movq 136(%rsi), %r9 + movq 136(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 128(%rdi) + movq 144(%rsi), %r8 + movq 144(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 136(%rdi) + movq 152(%rsi), %r9 + movq 152(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 144(%rdi) + movq 160(%rsi), %r8 + movq 160(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 152(%rdi) + movq 168(%rsi), %r9 + movq 168(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 160(%rdi) + movq 176(%rsi), %r8 + movq 176(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 168(%rdi) + movq 184(%rsi), %r9 + movq 184(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 176(%rdi) + movq 192(%rsi), %r8 + movq 192(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 184(%rdi) + movq 200(%rsi), %r9 + movq 200(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 192(%rdi) + movq 208(%rsi), %r8 + movq 208(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 200(%rdi) + movq 216(%rsi), %r9 + movq 216(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 208(%rdi) + movq 224(%rsi), %r8 + movq 224(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 216(%rdi) + movq 232(%rsi), %r9 + movq 232(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 224(%rdi) + movq 240(%rsi), %r8 + movq 240(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 232(%rdi) + movq 248(%rsi), %r9 + movq 248(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 240(%rdi) + movq 256(%rsi), %r8 + movq 256(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 248(%rdi) + movq 264(%rsi), %r9 + movq 264(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 256(%rdi) + movq 272(%rsi), %r8 + movq 272(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 264(%rdi) + movq 280(%rsi), %r9 + movq 280(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 272(%rdi) + movq 288(%rsi), %r8 + movq 288(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 280(%rdi) + movq 296(%rsi), %r9 + movq 296(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 288(%rdi) + movq 304(%rsi), %r8 + movq 304(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 296(%rdi) + movq 312(%rsi), %r9 + movq 312(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 304(%rdi) + movq 320(%rsi), %r8 + movq 320(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 312(%rdi) + movq 328(%rsi), %r9 + movq 328(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 320(%rdi) + movq 336(%rsi), %r8 + movq 336(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 328(%rdi) + movq 344(%rsi), %r9 + movq 344(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 336(%rdi) + movq 352(%rsi), %r8 + movq 352(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 344(%rdi) + movq 360(%rsi), %r9 + movq 360(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 352(%rdi) + movq 368(%rsi), %r8 + movq 368(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 360(%rdi) + movq 376(%rsi), %r9 + movq 376(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 368(%rdi) + movq %r9, 376(%rdi) + sbbq $0, %rax + addq $384, %rsp + repz retq +#ifndef __APPLE__ +.size sp_3072_cond_sub_48,.-sp_3072_cond_sub_48 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_mont_reduce_48 +.type sp_3072_mont_reduce_48,@function +.align 16 +sp_3072_mont_reduce_48: +#else +.globl _sp_3072_mont_reduce_48 +.p2align 4 +_sp_3072_mont_reduce_48: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rcx + xorq %r15, %r15 + # i = 48 + movq $48, %r8 + movq (%rdi), %r13 + movq 8(%rdi), %r14 +L_mont_loop_48: + # mu = a[i] * mp + movq %r13, %r11 + imulq %rcx, %r11 + # a[i+0] += m[0] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq (%rsi) + addq %rax, %r13 + adcq %rdx, %r10 + # a[i+1] += m[1] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 8(%rsi) + movq %r14, %r13 + addq %rax, %r13 + adcq %rdx, %r9 + addq %r10, %r13 + adcq $0, %r9 + # a[i+2] += m[2] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 16(%rsi) + movq 16(%rdi), %r14 + addq %rax, %r14 + adcq %rdx, %r10 + addq %r9, %r14 + adcq $0, %r10 + # a[i+3] += m[3] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 24(%rsi) + movq 24(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 24(%rdi) + adcq $0, %r9 + # a[i+4] += m[4] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 32(%rsi) + movq 32(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 32(%rdi) + adcq $0, %r10 + # a[i+5] += m[5] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 40(%rsi) + movq 40(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 40(%rdi) + adcq $0, %r9 + # a[i+6] += m[6] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 48(%rsi) + movq 48(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 48(%rdi) + adcq $0, %r10 + # a[i+7] += m[7] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 56(%rsi) + movq 56(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 56(%rdi) + adcq $0, %r9 + # a[i+8] += m[8] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 64(%rsi) + movq 64(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 64(%rdi) + adcq $0, %r10 + # a[i+9] += m[9] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 72(%rsi) + movq 72(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 72(%rdi) + adcq $0, %r9 + # a[i+10] += m[10] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 80(%rsi) + movq 80(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 80(%rdi) + adcq $0, %r10 + # a[i+11] += m[11] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 88(%rsi) + movq 88(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 88(%rdi) + adcq $0, %r9 + # a[i+12] += m[12] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 96(%rsi) + movq 96(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 96(%rdi) + adcq $0, %r10 + # a[i+13] += m[13] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 104(%rsi) + movq 104(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 104(%rdi) + adcq $0, %r9 + # a[i+14] += m[14] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 112(%rsi) + movq 112(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 112(%rdi) + adcq $0, %r10 + # a[i+15] += m[15] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 120(%rsi) + movq 120(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 120(%rdi) + adcq $0, %r9 + # a[i+16] += m[16] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 128(%rsi) + movq 128(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 128(%rdi) + adcq $0, %r10 + # a[i+17] += m[17] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 136(%rsi) + movq 136(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 136(%rdi) + adcq $0, %r9 + # a[i+18] += m[18] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 144(%rsi) + movq 144(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 144(%rdi) + adcq $0, %r10 + # a[i+19] += m[19] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 152(%rsi) + movq 152(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 152(%rdi) + adcq $0, %r9 + # a[i+20] += m[20] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 160(%rsi) + movq 160(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 160(%rdi) + adcq $0, %r10 + # a[i+21] += m[21] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 168(%rsi) + movq 168(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 168(%rdi) + adcq $0, %r9 + # a[i+22] += m[22] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 176(%rsi) + movq 176(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 176(%rdi) + adcq $0, %r10 + # a[i+23] += m[23] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 184(%rsi) + movq 184(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 184(%rdi) + adcq $0, %r9 + # a[i+24] += m[24] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 192(%rsi) + movq 192(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 192(%rdi) + adcq $0, %r10 + # a[i+25] += m[25] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 200(%rsi) + movq 200(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 200(%rdi) + adcq $0, %r9 + # a[i+26] += m[26] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 208(%rsi) + movq 208(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 208(%rdi) + adcq $0, %r10 + # a[i+27] += m[27] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 216(%rsi) + movq 216(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 216(%rdi) + adcq $0, %r9 + # a[i+28] += m[28] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 224(%rsi) + movq 224(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 224(%rdi) + adcq $0, %r10 + # a[i+29] += m[29] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 232(%rsi) + movq 232(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 232(%rdi) + adcq $0, %r9 + # a[i+30] += m[30] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 240(%rsi) + movq 240(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 240(%rdi) + adcq $0, %r10 + # a[i+31] += m[31] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 248(%rsi) + movq 248(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 248(%rdi) + adcq $0, %r9 + # a[i+32] += m[32] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 256(%rsi) + movq 256(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 256(%rdi) + adcq $0, %r10 + # a[i+33] += m[33] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 264(%rsi) + movq 264(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 264(%rdi) + adcq $0, %r9 + # a[i+34] += m[34] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 272(%rsi) + movq 272(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 272(%rdi) + adcq $0, %r10 + # a[i+35] += m[35] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 280(%rsi) + movq 280(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 280(%rdi) + adcq $0, %r9 + # a[i+36] += m[36] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 288(%rsi) + movq 288(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 288(%rdi) + adcq $0, %r10 + # a[i+37] += m[37] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 296(%rsi) + movq 296(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 296(%rdi) + adcq $0, %r9 + # a[i+38] += m[38] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 304(%rsi) + movq 304(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 304(%rdi) + adcq $0, %r10 + # a[i+39] += m[39] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 312(%rsi) + movq 312(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 312(%rdi) + adcq $0, %r9 + # a[i+40] += m[40] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 320(%rsi) + movq 320(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 320(%rdi) + adcq $0, %r10 + # a[i+41] += m[41] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 328(%rsi) + movq 328(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 328(%rdi) + adcq $0, %r9 + # a[i+42] += m[42] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 336(%rsi) + movq 336(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 336(%rdi) + adcq $0, %r10 + # a[i+43] += m[43] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 344(%rsi) + movq 344(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 344(%rdi) + adcq $0, %r9 + # a[i+44] += m[44] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 352(%rsi) + movq 352(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 352(%rdi) + adcq $0, %r10 + # a[i+45] += m[45] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 360(%rsi) + movq 360(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 360(%rdi) + adcq $0, %r9 + # a[i+46] += m[46] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 368(%rsi) + movq 368(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 368(%rdi) + adcq $0, %r10 + # a[i+47] += m[47] * mu + movq %r11, %rax + mulq 376(%rsi) + movq 376(%rdi), %r12 + addq %rax, %r10 + adcq %r15, %rdx + movq $0, %r15 + adcq $0, %r15 + addq %r10, %r12 + movq %r12, 376(%rdi) + adcq %rdx, 384(%rdi) + adcq $0, %r15 + # i -= 1 + addq $8, %rdi + decq %r8 + jnz L_mont_loop_48 + movq %r13, (%rdi) + movq %r14, 8(%rdi) + negq %r15 + movq %r15, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + subq $384, %rdi +#ifndef __APPLE__ + callq sp_3072_cond_sub_48@plt +#else + callq _sp_3072_cond_sub_48 +#endif /* __APPLE__ */ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_mont_reduce_48,.-sp_3072_mont_reduce_48 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_cond_sub_avx2_48 +.type sp_3072_cond_sub_avx2_48,@function +.align 16 +sp_3072_cond_sub_avx2_48: +#else +.globl _sp_3072_cond_sub_avx2_48 +.p2align 4 +_sp_3072_cond_sub_avx2_48: +#endif /* __APPLE__ */ + movq $0, %rax + movq (%rdx), %r10 + movq (%rsi), %r8 + pextq %rcx, %r10, %r10 + subq %r10, %r8 + movq 8(%rdx), %r10 + movq 8(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, (%rdi) + sbbq %r10, %r9 + movq 16(%rdx), %r8 + movq 16(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 8(%rdi) + sbbq %r8, %r10 + movq 24(%rdx), %r9 + movq 24(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 16(%rdi) + sbbq %r9, %r8 + movq 32(%rdx), %r10 + movq 32(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 24(%rdi) + sbbq %r10, %r9 + movq 40(%rdx), %r8 + movq 40(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 32(%rdi) + sbbq %r8, %r10 + movq 48(%rdx), %r9 + movq 48(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 40(%rdi) + sbbq %r9, %r8 + movq 56(%rdx), %r10 + movq 56(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 48(%rdi) + sbbq %r10, %r9 + movq 64(%rdx), %r8 + movq 64(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 56(%rdi) + sbbq %r8, %r10 + movq 72(%rdx), %r9 + movq 72(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 64(%rdi) + sbbq %r9, %r8 + movq 80(%rdx), %r10 + movq 80(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 72(%rdi) + sbbq %r10, %r9 + movq 88(%rdx), %r8 + movq 88(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 80(%rdi) + sbbq %r8, %r10 + movq 96(%rdx), %r9 + movq 96(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 88(%rdi) + sbbq %r9, %r8 + movq 104(%rdx), %r10 + movq 104(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 96(%rdi) + sbbq %r10, %r9 + movq 112(%rdx), %r8 + movq 112(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 104(%rdi) + sbbq %r8, %r10 + movq 120(%rdx), %r9 + movq 120(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 112(%rdi) + sbbq %r9, %r8 + movq 128(%rdx), %r10 + movq 128(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 120(%rdi) + sbbq %r10, %r9 + movq 136(%rdx), %r8 + movq 136(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 128(%rdi) + sbbq %r8, %r10 + movq 144(%rdx), %r9 + movq 144(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 136(%rdi) + sbbq %r9, %r8 + movq 152(%rdx), %r10 + movq 152(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 144(%rdi) + sbbq %r10, %r9 + movq 160(%rdx), %r8 + movq 160(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 152(%rdi) + sbbq %r8, %r10 + movq 168(%rdx), %r9 + movq 168(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 160(%rdi) + sbbq %r9, %r8 + movq 176(%rdx), %r10 + movq 176(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 168(%rdi) + sbbq %r10, %r9 + movq 184(%rdx), %r8 + movq 184(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 176(%rdi) + sbbq %r8, %r10 + movq 192(%rdx), %r9 + movq 192(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 184(%rdi) + sbbq %r9, %r8 + movq 200(%rdx), %r10 + movq 200(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 192(%rdi) + sbbq %r10, %r9 + movq 208(%rdx), %r8 + movq 208(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 200(%rdi) + sbbq %r8, %r10 + movq 216(%rdx), %r9 + movq 216(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 208(%rdi) + sbbq %r9, %r8 + movq 224(%rdx), %r10 + movq 224(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 216(%rdi) + sbbq %r10, %r9 + movq 232(%rdx), %r8 + movq 232(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 224(%rdi) + sbbq %r8, %r10 + movq 240(%rdx), %r9 + movq 240(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 232(%rdi) + sbbq %r9, %r8 + movq 248(%rdx), %r10 + movq 248(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 240(%rdi) + sbbq %r10, %r9 + movq 256(%rdx), %r8 + movq 256(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 248(%rdi) + sbbq %r8, %r10 + movq 264(%rdx), %r9 + movq 264(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 256(%rdi) + sbbq %r9, %r8 + movq 272(%rdx), %r10 + movq 272(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 264(%rdi) + sbbq %r10, %r9 + movq 280(%rdx), %r8 + movq 280(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 272(%rdi) + sbbq %r8, %r10 + movq 288(%rdx), %r9 + movq 288(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 280(%rdi) + sbbq %r9, %r8 + movq 296(%rdx), %r10 + movq 296(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 288(%rdi) + sbbq %r10, %r9 + movq 304(%rdx), %r8 + movq 304(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 296(%rdi) + sbbq %r8, %r10 + movq 312(%rdx), %r9 + movq 312(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 304(%rdi) + sbbq %r9, %r8 + movq 320(%rdx), %r10 + movq 320(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 312(%rdi) + sbbq %r10, %r9 + movq 328(%rdx), %r8 + movq 328(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 320(%rdi) + sbbq %r8, %r10 + movq 336(%rdx), %r9 + movq 336(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 328(%rdi) + sbbq %r9, %r8 + movq 344(%rdx), %r10 + movq 344(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 336(%rdi) + sbbq %r10, %r9 + movq 352(%rdx), %r8 + movq 352(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 344(%rdi) + sbbq %r8, %r10 + movq 360(%rdx), %r9 + movq 360(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 352(%rdi) + sbbq %r9, %r8 + movq 368(%rdx), %r10 + movq 368(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 360(%rdi) + sbbq %r10, %r9 + movq 376(%rdx), %r8 + movq 376(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 368(%rdi) + sbbq %r8, %r10 + movq %r10, 376(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_cond_sub_avx2_48,.-sp_3072_cond_sub_avx2_48 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_d_avx2_48 +.type sp_3072_mul_d_avx2_48,@function +.align 16 +sp_3072_mul_d_avx2_48: +#else +.globl _sp_3072_mul_d_avx2_48 +.p2align 4 +_sp_3072_mul_d_avx2_48: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 8(%rdi) + adoxq %r8, %r9 + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 16(%rdi) + adoxq %r8, %r10 + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 24(%rdi) + adoxq %r8, %r9 + # A[4] * B + mulxq 32(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 32(%rdi) + adoxq %r8, %r10 + # A[5] * B + mulxq 40(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 40(%rdi) + adoxq %r8, %r9 + # A[6] * B + mulxq 48(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 48(%rdi) + adoxq %r8, %r10 + # A[7] * B + mulxq 56(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 56(%rdi) + adoxq %r8, %r9 + # A[8] * B + mulxq 64(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 64(%rdi) + adoxq %r8, %r10 + # A[9] * B + mulxq 72(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 72(%rdi) + adoxq %r8, %r9 + # A[10] * B + mulxq 80(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 80(%rdi) + adoxq %r8, %r10 + # A[11] * B + mulxq 88(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 88(%rdi) + adoxq %r8, %r9 + # A[12] * B + mulxq 96(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 96(%rdi) + adoxq %r8, %r10 + # A[13] * B + mulxq 104(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 104(%rdi) + adoxq %r8, %r9 + # A[14] * B + mulxq 112(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 112(%rdi) + adoxq %r8, %r10 + # A[15] * B + mulxq 120(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 120(%rdi) + adoxq %r8, %r9 + # A[16] * B + mulxq 128(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 128(%rdi) + adoxq %r8, %r10 + # A[17] * B + mulxq 136(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 136(%rdi) + adoxq %r8, %r9 + # A[18] * B + mulxq 144(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 144(%rdi) + adoxq %r8, %r10 + # A[19] * B + mulxq 152(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 152(%rdi) + adoxq %r8, %r9 + # A[20] * B + mulxq 160(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 160(%rdi) + adoxq %r8, %r10 + # A[21] * B + mulxq 168(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 168(%rdi) + adoxq %r8, %r9 + # A[22] * B + mulxq 176(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 176(%rdi) + adoxq %r8, %r10 + # A[23] * B + mulxq 184(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 184(%rdi) + adoxq %r8, %r9 + # A[24] * B + mulxq 192(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 192(%rdi) + adoxq %r8, %r10 + # A[25] * B + mulxq 200(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 200(%rdi) + adoxq %r8, %r9 + # A[26] * B + mulxq 208(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 208(%rdi) + adoxq %r8, %r10 + # A[27] * B + mulxq 216(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 216(%rdi) + adoxq %r8, %r9 + # A[28] * B + mulxq 224(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 224(%rdi) + adoxq %r8, %r10 + # A[29] * B + mulxq 232(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 232(%rdi) + adoxq %r8, %r9 + # A[30] * B + mulxq 240(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 240(%rdi) + adoxq %r8, %r10 + # A[31] * B + mulxq 248(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 248(%rdi) + adoxq %r8, %r9 + # A[32] * B + mulxq 256(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 256(%rdi) + adoxq %r8, %r10 + # A[33] * B + mulxq 264(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 264(%rdi) + adoxq %r8, %r9 + # A[34] * B + mulxq 272(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 272(%rdi) + adoxq %r8, %r10 + # A[35] * B + mulxq 280(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 280(%rdi) + adoxq %r8, %r9 + # A[36] * B + mulxq 288(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 288(%rdi) + adoxq %r8, %r10 + # A[37] * B + mulxq 296(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 296(%rdi) + adoxq %r8, %r9 + # A[38] * B + mulxq 304(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 304(%rdi) + adoxq %r8, %r10 + # A[39] * B + mulxq 312(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 312(%rdi) + adoxq %r8, %r9 + # A[40] * B + mulxq 320(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 320(%rdi) + adoxq %r8, %r10 + # A[41] * B + mulxq 328(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 328(%rdi) + adoxq %r8, %r9 + # A[42] * B + mulxq 336(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 336(%rdi) + adoxq %r8, %r10 + # A[43] * B + mulxq 344(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 344(%rdi) + adoxq %r8, %r9 + # A[44] * B + mulxq 352(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 352(%rdi) + adoxq %r8, %r10 + # A[45] * B + mulxq 360(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 360(%rdi) + adoxq %r8, %r9 + # A[46] * B + mulxq 368(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 368(%rdi) + adoxq %r8, %r10 + # A[47] * B + mulxq 376(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 376(%rdi) + movq %r9, 384(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_d_avx2_48,.-sp_3072_mul_d_avx2_48 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_cmp_48 +.type sp_3072_cmp_48,@function +.align 16 +sp_3072_cmp_48: +#else +.globl _sp_3072_cmp_48 +.p2align 4 +_sp_3072_cmp_48: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $1, %r8 + movq 376(%rdi), %r9 + movq 376(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 368(%rdi), %r9 + movq 368(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 360(%rdi), %r9 + movq 360(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 352(%rdi), %r9 + movq 352(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 344(%rdi), %r9 + movq 344(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 336(%rdi), %r9 + movq 336(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 328(%rdi), %r9 + movq 328(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 320(%rdi), %r9 + movq 320(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 312(%rdi), %r9 + movq 312(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 304(%rdi), %r9 + movq 304(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 296(%rdi), %r9 + movq 296(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 288(%rdi), %r9 + movq 288(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 280(%rdi), %r9 + movq 280(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 272(%rdi), %r9 + movq 272(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 264(%rdi), %r9 + movq 264(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 256(%rdi), %r9 + movq 256(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 248(%rdi), %r9 + movq 248(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 240(%rdi), %r9 + movq 240(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 232(%rdi), %r9 + movq 232(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 224(%rdi), %r9 + movq 224(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 216(%rdi), %r9 + movq 216(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 208(%rdi), %r9 + movq 208(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 200(%rdi), %r9 + movq 200(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 192(%rdi), %r9 + movq 192(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 184(%rdi), %r9 + movq 184(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 176(%rdi), %r9 + movq 176(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 168(%rdi), %r9 + movq 168(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 160(%rdi), %r9 + movq 160(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 152(%rdi), %r9 + movq 152(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 144(%rdi), %r9 + movq 144(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 136(%rdi), %r9 + movq 136(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 128(%rdi), %r9 + movq 128(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 120(%rdi), %r9 + movq 120(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 112(%rdi), %r9 + movq 112(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 104(%rdi), %r9 + movq 104(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 96(%rdi), %r9 + movq 96(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 88(%rdi), %r9 + movq 88(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 80(%rdi), %r9 + movq 80(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 72(%rdi), %r9 + movq 72(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 64(%rdi), %r9 + movq 64(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 56(%rdi), %r9 + movq 56(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 48(%rdi), %r9 + movq 48(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 40(%rdi), %r9 + movq 40(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 32(%rdi), %r9 + movq 32(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_cmp_48,.-sp_3072_cmp_48 +#endif /* __APPLE__ */ +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sub_48 +.type sp_3072_sub_48,@function +.align 16 +sp_3072_sub_48: +#else +.globl _sp_3072_sub_48 +.p2align 4 +_sp_3072_sub_48: +#endif /* __APPLE__ */ + movq (%rsi), %rcx + xorq %rax, %rax + subq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + sbbq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + sbbq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + sbbq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + sbbq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + sbbq 40(%rdx), %r8 + movq 48(%rsi), %rcx + movq %r8, 40(%rdi) + sbbq 48(%rdx), %rcx + movq 56(%rsi), %r8 + movq %rcx, 48(%rdi) + sbbq 56(%rdx), %r8 + movq 64(%rsi), %rcx + movq %r8, 56(%rdi) + sbbq 64(%rdx), %rcx + movq 72(%rsi), %r8 + movq %rcx, 64(%rdi) + sbbq 72(%rdx), %r8 + movq 80(%rsi), %rcx + movq %r8, 72(%rdi) + sbbq 80(%rdx), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%rdi) + sbbq 88(%rdx), %r8 + movq 96(%rsi), %rcx + movq %r8, 88(%rdi) + sbbq 96(%rdx), %rcx + movq 104(%rsi), %r8 + movq %rcx, 96(%rdi) + sbbq 104(%rdx), %r8 + movq 112(%rsi), %rcx + movq %r8, 104(%rdi) + sbbq 112(%rdx), %rcx + movq 120(%rsi), %r8 + movq %rcx, 112(%rdi) + sbbq 120(%rdx), %r8 + movq 128(%rsi), %rcx + movq %r8, 120(%rdi) + sbbq 128(%rdx), %rcx + movq 136(%rsi), %r8 + movq %rcx, 128(%rdi) + sbbq 136(%rdx), %r8 + movq 144(%rsi), %rcx + movq %r8, 136(%rdi) + sbbq 144(%rdx), %rcx + movq 152(%rsi), %r8 + movq %rcx, 144(%rdi) + sbbq 152(%rdx), %r8 + movq 160(%rsi), %rcx + movq %r8, 152(%rdi) + sbbq 160(%rdx), %rcx + movq 168(%rsi), %r8 + movq %rcx, 160(%rdi) + sbbq 168(%rdx), %r8 + movq 176(%rsi), %rcx + movq %r8, 168(%rdi) + sbbq 176(%rdx), %rcx + movq 184(%rsi), %r8 + movq %rcx, 176(%rdi) + sbbq 184(%rdx), %r8 + movq 192(%rsi), %rcx + movq %r8, 184(%rdi) + sbbq 192(%rdx), %rcx + movq 200(%rsi), %r8 + movq %rcx, 192(%rdi) + sbbq 200(%rdx), %r8 + movq 208(%rsi), %rcx + movq %r8, 200(%rdi) + sbbq 208(%rdx), %rcx + movq 216(%rsi), %r8 + movq %rcx, 208(%rdi) + sbbq 216(%rdx), %r8 + movq 224(%rsi), %rcx + movq %r8, 216(%rdi) + sbbq 224(%rdx), %rcx + movq 232(%rsi), %r8 + movq %rcx, 224(%rdi) + sbbq 232(%rdx), %r8 + movq 240(%rsi), %rcx + movq %r8, 232(%rdi) + sbbq 240(%rdx), %rcx + movq 248(%rsi), %r8 + movq %rcx, 240(%rdi) + sbbq 248(%rdx), %r8 + movq 256(%rsi), %rcx + movq %r8, 248(%rdi) + sbbq 256(%rdx), %rcx + movq 264(%rsi), %r8 + movq %rcx, 256(%rdi) + sbbq 264(%rdx), %r8 + movq 272(%rsi), %rcx + movq %r8, 264(%rdi) + sbbq 272(%rdx), %rcx + movq 280(%rsi), %r8 + movq %rcx, 272(%rdi) + sbbq 280(%rdx), %r8 + movq 288(%rsi), %rcx + movq %r8, 280(%rdi) + sbbq 288(%rdx), %rcx + movq 296(%rsi), %r8 + movq %rcx, 288(%rdi) + sbbq 296(%rdx), %r8 + movq 304(%rsi), %rcx + movq %r8, 296(%rdi) + sbbq 304(%rdx), %rcx + movq 312(%rsi), %r8 + movq %rcx, 304(%rdi) + sbbq 312(%rdx), %r8 + movq 320(%rsi), %rcx + movq %r8, 312(%rdi) + sbbq 320(%rdx), %rcx + movq 328(%rsi), %r8 + movq %rcx, 320(%rdi) + sbbq 328(%rdx), %r8 + movq 336(%rsi), %rcx + movq %r8, 328(%rdi) + sbbq 336(%rdx), %rcx + movq 344(%rsi), %r8 + movq %rcx, 336(%rdi) + sbbq 344(%rdx), %r8 + movq 352(%rsi), %rcx + movq %r8, 344(%rdi) + sbbq 352(%rdx), %rcx + movq 360(%rsi), %r8 + movq %rcx, 352(%rdi) + sbbq 360(%rdx), %r8 + movq 368(%rsi), %rcx + movq %r8, 360(%rdi) + sbbq 368(%rdx), %rcx + movq 376(%rsi), %r8 + movq %rcx, 368(%rdi) + sbbq 376(%rdx), %r8 + movq %r8, 376(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_sub_48,.-sp_3072_sub_48 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_mont_reduce_avx2_48 +.type sp_3072_mont_reduce_avx2_48,@function +.align 16 +sp_3072_mont_reduce_avx2_48: +#else +.globl _sp_3072_mont_reduce_avx2_48 +.p2align 4 +_sp_3072_mont_reduce_avx2_48: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + movq %rdx, %r8 + xorq %r14, %r14 + # i = 48 + movq $48, %r9 + movq (%rdi), %r13 + addq $192, %rdi + xorq %r12, %r12 +L_mont_loop_avx2_48: + # mu = a[i] * mp + movq %r13, %rdx + movq %r13, %r10 + imulq %r8, %rdx + xorq %r12, %r12 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rax, %rcx + movq -184(%rdi), %r13 + adcxq %rax, %r10 + adoxq %rcx, %r13 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rax, %rcx + movq -176(%rdi), %r10 + adcxq %rax, %r13 + adoxq %rcx, %r10 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rax, %rcx + movq -168(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -176(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rax, %rcx + movq -160(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -168(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rax, %rcx + movq -152(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -160(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rax, %rcx + movq -144(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -152(%rdi) + # a[i+6] += m[6] * mu + mulxq 48(%rsi), %rax, %rcx + movq -136(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -144(%rdi) + # a[i+7] += m[7] * mu + mulxq 56(%rsi), %rax, %rcx + movq -128(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -136(%rdi) + # a[i+8] += m[8] * mu + mulxq 64(%rsi), %rax, %rcx + movq -120(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -128(%rdi) + # a[i+9] += m[9] * mu + mulxq 72(%rsi), %rax, %rcx + movq -112(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -120(%rdi) + # a[i+10] += m[10] * mu + mulxq 80(%rsi), %rax, %rcx + movq -104(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -112(%rdi) + # a[i+11] += m[11] * mu + mulxq 88(%rsi), %rax, %rcx + movq -96(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -104(%rdi) + # a[i+12] += m[12] * mu + mulxq 96(%rsi), %rax, %rcx + movq -88(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -96(%rdi) + # a[i+13] += m[13] * mu + mulxq 104(%rsi), %rax, %rcx + movq -80(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -88(%rdi) + # a[i+14] += m[14] * mu + mulxq 112(%rsi), %rax, %rcx + movq -72(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -80(%rdi) + # a[i+15] += m[15] * mu + mulxq 120(%rsi), %rax, %rcx + movq -64(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -72(%rdi) + # a[i+16] += m[16] * mu + mulxq 128(%rsi), %rax, %rcx + movq -56(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -64(%rdi) + # a[i+17] += m[17] * mu + mulxq 136(%rsi), %rax, %rcx + movq -48(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -56(%rdi) + # a[i+18] += m[18] * mu + mulxq 144(%rsi), %rax, %rcx + movq -40(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -48(%rdi) + # a[i+19] += m[19] * mu + mulxq 152(%rsi), %rax, %rcx + movq -32(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -40(%rdi) + # a[i+20] += m[20] * mu + mulxq 160(%rsi), %rax, %rcx + movq -24(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -32(%rdi) + # a[i+21] += m[21] * mu + mulxq 168(%rsi), %rax, %rcx + movq -16(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -24(%rdi) + # a[i+22] += m[22] * mu + mulxq 176(%rsi), %rax, %rcx + movq -8(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -16(%rdi) + # a[i+23] += m[23] * mu + mulxq 184(%rsi), %rax, %rcx + movq (%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -8(%rdi) + # a[i+24] += m[24] * mu + mulxq 192(%rsi), %rax, %rcx + movq 8(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, (%rdi) + # a[i+25] += m[25] * mu + mulxq 200(%rsi), %rax, %rcx + movq 16(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 8(%rdi) + # a[i+26] += m[26] * mu + mulxq 208(%rsi), %rax, %rcx + movq 24(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 16(%rdi) + # a[i+27] += m[27] * mu + mulxq 216(%rsi), %rax, %rcx + movq 32(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 24(%rdi) + # a[i+28] += m[28] * mu + mulxq 224(%rsi), %rax, %rcx + movq 40(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 32(%rdi) + # a[i+29] += m[29] * mu + mulxq 232(%rsi), %rax, %rcx + movq 48(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 40(%rdi) + # a[i+30] += m[30] * mu + mulxq 240(%rsi), %rax, %rcx + movq 56(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 48(%rdi) + # a[i+31] += m[31] * mu + mulxq 248(%rsi), %rax, %rcx + movq 64(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 56(%rdi) + # a[i+32] += m[32] * mu + mulxq 256(%rsi), %rax, %rcx + movq 72(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 64(%rdi) + # a[i+33] += m[33] * mu + mulxq 264(%rsi), %rax, %rcx + movq 80(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 72(%rdi) + # a[i+34] += m[34] * mu + mulxq 272(%rsi), %rax, %rcx + movq 88(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 80(%rdi) + # a[i+35] += m[35] * mu + mulxq 280(%rsi), %rax, %rcx + movq 96(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 88(%rdi) + # a[i+36] += m[36] * mu + mulxq 288(%rsi), %rax, %rcx + movq 104(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rdi) + # a[i+37] += m[37] * mu + mulxq 296(%rsi), %rax, %rcx + movq 112(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 104(%rdi) + # a[i+38] += m[38] * mu + mulxq 304(%rsi), %rax, %rcx + movq 120(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 112(%rdi) + # a[i+39] += m[39] * mu + mulxq 312(%rsi), %rax, %rcx + movq 128(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 120(%rdi) + # a[i+40] += m[40] * mu + mulxq 320(%rsi), %rax, %rcx + movq 136(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 128(%rdi) + # a[i+41] += m[41] * mu + mulxq 328(%rsi), %rax, %rcx + movq 144(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 136(%rdi) + # a[i+42] += m[42] * mu + mulxq 336(%rsi), %rax, %rcx + movq 152(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 144(%rdi) + # a[i+43] += m[43] * mu + mulxq 344(%rsi), %rax, %rcx + movq 160(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 152(%rdi) + # a[i+44] += m[44] * mu + mulxq 352(%rsi), %rax, %rcx + movq 168(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 160(%rdi) + # a[i+45] += m[45] * mu + mulxq 360(%rsi), %rax, %rcx + movq 176(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 168(%rdi) + # a[i+46] += m[46] * mu + mulxq 368(%rsi), %rax, %rcx + movq 184(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 176(%rdi) + # a[i+47] += m[47] * mu + mulxq 376(%rsi), %rax, %rcx + movq 192(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 184(%rdi) + adcxq %r14, %r10 + movq %r10, 192(%rdi) + movq %r12, %r14 + adoxq %r12, %r14 + adcxq %r12, %r14 + # a += 1 + addq $8, %rdi + # i -= 1 + subq $1, %r9 + jnz L_mont_loop_avx2_48 + subq $192, %rdi + negq %r14 + movq %rdi, %r8 + subq $384, %rdi + movq (%rsi), %rcx + movq %r13, %rdx + pextq %r14, %rcx, %rcx + subq %rcx, %rdx + movq 8(%rsi), %rcx + movq 8(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, (%rdi) + sbbq %rcx, %rax + movq 16(%rsi), %rdx + movq 16(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 8(%rdi) + sbbq %rdx, %rcx + movq 24(%rsi), %rax + movq 24(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 16(%rdi) + sbbq %rax, %rdx + movq 32(%rsi), %rcx + movq 32(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 24(%rdi) + sbbq %rcx, %rax + movq 40(%rsi), %rdx + movq 40(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 32(%rdi) + sbbq %rdx, %rcx + movq 48(%rsi), %rax + movq 48(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 40(%rdi) + sbbq %rax, %rdx + movq 56(%rsi), %rcx + movq 56(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 48(%rdi) + sbbq %rcx, %rax + movq 64(%rsi), %rdx + movq 64(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 56(%rdi) + sbbq %rdx, %rcx + movq 72(%rsi), %rax + movq 72(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 64(%rdi) + sbbq %rax, %rdx + movq 80(%rsi), %rcx + movq 80(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 72(%rdi) + sbbq %rcx, %rax + movq 88(%rsi), %rdx + movq 88(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 80(%rdi) + sbbq %rdx, %rcx + movq 96(%rsi), %rax + movq 96(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 88(%rdi) + sbbq %rax, %rdx + movq 104(%rsi), %rcx + movq 104(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 96(%rdi) + sbbq %rcx, %rax + movq 112(%rsi), %rdx + movq 112(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 104(%rdi) + sbbq %rdx, %rcx + movq 120(%rsi), %rax + movq 120(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 112(%rdi) + sbbq %rax, %rdx + movq 128(%rsi), %rcx + movq 128(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 120(%rdi) + sbbq %rcx, %rax + movq 136(%rsi), %rdx + movq 136(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 128(%rdi) + sbbq %rdx, %rcx + movq 144(%rsi), %rax + movq 144(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 136(%rdi) + sbbq %rax, %rdx + movq 152(%rsi), %rcx + movq 152(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 144(%rdi) + sbbq %rcx, %rax + movq 160(%rsi), %rdx + movq 160(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 152(%rdi) + sbbq %rdx, %rcx + movq 168(%rsi), %rax + movq 168(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 160(%rdi) + sbbq %rax, %rdx + movq 176(%rsi), %rcx + movq 176(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 168(%rdi) + sbbq %rcx, %rax + movq 184(%rsi), %rdx + movq 184(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 176(%rdi) + sbbq %rdx, %rcx + movq 192(%rsi), %rax + movq 192(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 184(%rdi) + sbbq %rax, %rdx + movq 200(%rsi), %rcx + movq 200(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 192(%rdi) + sbbq %rcx, %rax + movq 208(%rsi), %rdx + movq 208(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 200(%rdi) + sbbq %rdx, %rcx + movq 216(%rsi), %rax + movq 216(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 208(%rdi) + sbbq %rax, %rdx + movq 224(%rsi), %rcx + movq 224(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 216(%rdi) + sbbq %rcx, %rax + movq 232(%rsi), %rdx + movq 232(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 224(%rdi) + sbbq %rdx, %rcx + movq 240(%rsi), %rax + movq 240(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 232(%rdi) + sbbq %rax, %rdx + movq 248(%rsi), %rcx + movq 248(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 240(%rdi) + sbbq %rcx, %rax + movq 256(%rsi), %rdx + movq 256(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 248(%rdi) + sbbq %rdx, %rcx + movq 264(%rsi), %rax + movq 264(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 256(%rdi) + sbbq %rax, %rdx + movq 272(%rsi), %rcx + movq 272(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 264(%rdi) + sbbq %rcx, %rax + movq 280(%rsi), %rdx + movq 280(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 272(%rdi) + sbbq %rdx, %rcx + movq 288(%rsi), %rax + movq 288(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 280(%rdi) + sbbq %rax, %rdx + movq 296(%rsi), %rcx + movq 296(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 288(%rdi) + sbbq %rcx, %rax + movq 304(%rsi), %rdx + movq 304(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 296(%rdi) + sbbq %rdx, %rcx + movq 312(%rsi), %rax + movq 312(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 304(%rdi) + sbbq %rax, %rdx + movq 320(%rsi), %rcx + movq 320(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 312(%rdi) + sbbq %rcx, %rax + movq 328(%rsi), %rdx + movq 328(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 320(%rdi) + sbbq %rdx, %rcx + movq 336(%rsi), %rax + movq 336(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 328(%rdi) + sbbq %rax, %rdx + movq 344(%rsi), %rcx + movq 344(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 336(%rdi) + sbbq %rcx, %rax + movq 352(%rsi), %rdx + movq 352(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 344(%rdi) + sbbq %rdx, %rcx + movq 360(%rsi), %rax + movq 360(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 352(%rdi) + sbbq %rax, %rdx + movq 368(%rsi), %rcx + movq 368(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 360(%rdi) + sbbq %rcx, %rax + movq 376(%rsi), %rdx + movq 376(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 368(%rdi) + sbbq %rdx, %rcx + movq %rcx, 376(%rdi) + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_mont_reduce_avx2_48,.-sp_3072_mont_reduce_avx2_48 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_cond_add_24 +.type sp_3072_cond_add_24,@function +.align 16 +sp_3072_cond_add_24: +#else +.globl _sp_3072_cond_add_24 +.p2align 4 +_sp_3072_cond_add_24: +#endif /* __APPLE__ */ + subq $192, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq 128(%rdx), %r8 + movq 136(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 128(%rsp) + movq %r9, 136(%rsp) + movq 144(%rdx), %r8 + movq 152(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 144(%rsp) + movq %r9, 152(%rsp) + movq 160(%rdx), %r8 + movq 168(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r9, 168(%rsp) + movq 176(%rdx), %r8 + movq 184(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 176(%rsp) + movq %r9, 184(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + addq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 112(%rdi) + movq 128(%rsi), %r8 + movq 128(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 120(%rdi) + movq 136(%rsi), %r9 + movq 136(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 128(%rdi) + movq 144(%rsi), %r8 + movq 144(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 136(%rdi) + movq 152(%rsi), %r9 + movq 152(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 144(%rdi) + movq 160(%rsi), %r8 + movq 160(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 152(%rdi) + movq 168(%rsi), %r9 + movq 168(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 160(%rdi) + movq 176(%rsi), %r8 + movq 176(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 168(%rdi) + movq 184(%rsi), %r9 + movq 184(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 176(%rdi) + movq %r9, 184(%rdi) + adcq $0, %rax + addq $192, %rsp + repz retq +#ifndef __APPLE__ +.size sp_3072_cond_add_24,.-sp_3072_cond_add_24 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_3072_cond_add_avx2_24 +.type sp_3072_cond_add_avx2_24,@function +.align 16 +sp_3072_cond_add_avx2_24: +#else +.globl _sp_3072_cond_add_avx2_24 +.p2align 4 +_sp_3072_cond_add_avx2_24: +#endif /* __APPLE__ */ + movq $0, %rax + movq (%rdx), %r10 + movq (%rsi), %r8 + pextq %rcx, %r10, %r10 + addq %r10, %r8 + movq 8(%rdx), %r10 + movq 8(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, (%rdi) + adcq %r10, %r9 + movq 16(%rdx), %r8 + movq 16(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 8(%rdi) + adcq %r8, %r10 + movq 24(%rdx), %r9 + movq 24(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 16(%rdi) + adcq %r9, %r8 + movq 32(%rdx), %r10 + movq 32(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 24(%rdi) + adcq %r10, %r9 + movq 40(%rdx), %r8 + movq 40(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 32(%rdi) + adcq %r8, %r10 + movq 48(%rdx), %r9 + movq 48(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 40(%rdi) + adcq %r9, %r8 + movq 56(%rdx), %r10 + movq 56(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 48(%rdi) + adcq %r10, %r9 + movq 64(%rdx), %r8 + movq 64(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 56(%rdi) + adcq %r8, %r10 + movq 72(%rdx), %r9 + movq 72(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 64(%rdi) + adcq %r9, %r8 + movq 80(%rdx), %r10 + movq 80(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 72(%rdi) + adcq %r10, %r9 + movq 88(%rdx), %r8 + movq 88(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 80(%rdi) + adcq %r8, %r10 + movq 96(%rdx), %r9 + movq 96(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 88(%rdi) + adcq %r9, %r8 + movq 104(%rdx), %r10 + movq 104(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 96(%rdi) + adcq %r10, %r9 + movq 112(%rdx), %r8 + movq 112(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 104(%rdi) + adcq %r8, %r10 + movq 120(%rdx), %r9 + movq 120(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 112(%rdi) + adcq %r9, %r8 + movq 128(%rdx), %r10 + movq 128(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 120(%rdi) + adcq %r10, %r9 + movq 136(%rdx), %r8 + movq 136(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 128(%rdi) + adcq %r8, %r10 + movq 144(%rdx), %r9 + movq 144(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 136(%rdi) + adcq %r9, %r8 + movq 152(%rdx), %r10 + movq 152(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 144(%rdi) + adcq %r10, %r9 + movq 160(%rdx), %r8 + movq 160(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 152(%rdi) + adcq %r8, %r10 + movq 168(%rdx), %r9 + movq 168(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 160(%rdi) + adcq %r9, %r8 + movq 176(%rdx), %r10 + movq 176(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 168(%rdi) + adcq %r10, %r9 + movq 184(%rdx), %r8 + movq 184(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 176(%rdi) + adcq %r8, %r10 + movq %r10, 184(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_cond_add_avx2_24,.-sp_3072_cond_add_avx2_24 +#endif /* __APPLE__ */ +/* Shift number left by n bit. (r = a << n) + * + * r Result of left shift by n. + * a Number to shift. + * n Amoutnt o shift. + */ +#ifndef __APPLE__ +.globl sp_3072_lshift_48 +.type sp_3072_lshift_48,@function +.align 16 +sp_3072_lshift_48: +#else +.globl _sp_3072_lshift_48 +.p2align 4 +_sp_3072_lshift_48: +#endif /* __APPLE__ */ + movq %rdx, %rcx + movq $0, %r10 + movq 344(%rsi), %r11 + movq 352(%rsi), %rdx + movq 360(%rsi), %rax + movq 368(%rsi), %r8 + movq 376(%rsi), %r9 + shldq %cl, %r9, %r10 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 352(%rdi) + movq %rax, 360(%rdi) + movq %r8, 368(%rdi) + movq %r9, 376(%rdi) + movq %r10, 384(%rdi) + movq 312(%rsi), %r9 + movq 320(%rsi), %rdx + movq 328(%rsi), %rax + movq 336(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 320(%rdi) + movq %rax, 328(%rdi) + movq %r8, 336(%rdi) + movq %r11, 344(%rdi) + movq 280(%rsi), %r11 + movq 288(%rsi), %rdx + movq 296(%rsi), %rax + movq 304(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 288(%rdi) + movq %rax, 296(%rdi) + movq %r8, 304(%rdi) + movq %r9, 312(%rdi) + movq 248(%rsi), %r9 + movq 256(%rsi), %rdx + movq 264(%rsi), %rax + movq 272(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 256(%rdi) + movq %rax, 264(%rdi) + movq %r8, 272(%rdi) + movq %r11, 280(%rdi) + movq 216(%rsi), %r11 + movq 224(%rsi), %rdx + movq 232(%rsi), %rax + movq 240(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 224(%rdi) + movq %rax, 232(%rdi) + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + movq 184(%rsi), %r9 + movq 192(%rsi), %rdx + movq 200(%rsi), %rax + movq 208(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 192(%rdi) + movq %rax, 200(%rdi) + movq %r8, 208(%rdi) + movq %r11, 216(%rdi) + movq 152(%rsi), %r11 + movq 160(%rsi), %rdx + movq 168(%rsi), %rax + movq 176(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 160(%rdi) + movq %rax, 168(%rdi) + movq %r8, 176(%rdi) + movq %r9, 184(%rdi) + movq 120(%rsi), %r9 + movq 128(%rsi), %rdx + movq 136(%rsi), %rax + movq 144(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 128(%rdi) + movq %rax, 136(%rdi) + movq %r8, 144(%rdi) + movq %r11, 152(%rdi) + movq 88(%rsi), %r11 + movq 96(%rsi), %rdx + movq 104(%rsi), %rax + movq 112(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 96(%rdi) + movq %rax, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + movq 56(%rsi), %r9 + movq 64(%rsi), %rdx + movq 72(%rsi), %rax + movq 80(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 64(%rdi) + movq %rax, 72(%rdi) + movq %r8, 80(%rdi) + movq %r11, 88(%rdi) + movq 24(%rsi), %r11 + movq 32(%rsi), %rdx + movq 40(%rsi), %rax + movq 48(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 32(%rdi) + movq %rax, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shlq %cl, %rdx + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %r8, 16(%rdi) + movq %r11, 24(%rdi) + repz retq +#endif /* !WOLFSSL_SP_NO_3072 */ +#endif /* !WOLFSSL_SP_NO_3072 */ +#ifdef WOLFSSL_SP_4096 +#ifdef WOLFSSL_SP_4096 +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +#ifndef __APPLE__ +.globl sp_4096_from_bin +.type sp_4096_from_bin,@function +.align 16 +sp_4096_from_bin: +#else +.globl _sp_4096_from_bin +.p2align 4 +_sp_4096_from_bin: +#endif /* __APPLE__ */ + movq %rdx, %r9 + movq %rdi, %r10 + addq %rcx, %r9 + addq $512, %r10 + xorq %r11, %r11 + jmp L_4096_from_bin_64_end +L_4096_from_bin_64_start: + subq $64, %r9 + movbeq 56(%r9), %rax + movbeq 48(%r9), %r8 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movbeq 40(%r9), %rax + movbeq 32(%r9), %r8 + movq %rax, 16(%rdi) + movq %r8, 24(%rdi) + movbeq 24(%r9), %rax + movbeq 16(%r9), %r8 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movbeq 8(%r9), %rax + movbeq (%r9), %r8 + movq %rax, 48(%rdi) + movq %r8, 56(%rdi) + addq $64, %rdi + subq $64, %rcx +L_4096_from_bin_64_end: + cmpq $63, %rcx + jg L_4096_from_bin_64_start + jmp L_4096_from_bin_8_end +L_4096_from_bin_8_start: + subq $8, %r9 + movbeq (%r9), %rax + movq %rax, (%rdi) + addq $8, %rdi + subq $8, %rcx +L_4096_from_bin_8_end: + cmpq $7, %rcx + jg L_4096_from_bin_8_start + cmpq %r11, %rcx + je L_4096_from_bin_hi_end + movq %r11, %r8 + movq %r11, %rax +L_4096_from_bin_hi_start: + movb (%rdx), %al + shlq $8, %r8 + incq %rdx + addq %rax, %r8 + decq %rcx + jg L_4096_from_bin_hi_start + movq %r8, (%rdi) + addq $8, %rdi +L_4096_from_bin_hi_end: + cmpq %r10, %rdi + je L_4096_from_bin_zero_end +L_4096_from_bin_zero_start: + movq %r11, (%rdi) + addq $8, %rdi + cmpq %r10, %rdi + jl L_4096_from_bin_zero_start +L_4096_from_bin_zero_end: + repz retq +#ifndef __APPLE__ +.size sp_4096_from_bin,.-sp_4096_from_bin +#endif /* __APPLE__ */ +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 512 + * + * r A single precision integer. + * a Byte array. + */ +#ifndef __APPLE__ +.globl sp_4096_to_bin +.type sp_4096_to_bin,@function +.align 16 +sp_4096_to_bin: +#else +.globl _sp_4096_to_bin +.p2align 4 +_sp_4096_to_bin: +#endif /* __APPLE__ */ + movbeq 504(%rdi), %rdx + movbeq 496(%rdi), %rax + movq %rdx, (%rsi) + movq %rax, 8(%rsi) + movbeq 488(%rdi), %rdx + movbeq 480(%rdi), %rax + movq %rdx, 16(%rsi) + movq %rax, 24(%rsi) + movbeq 472(%rdi), %rdx + movbeq 464(%rdi), %rax + movq %rdx, 32(%rsi) + movq %rax, 40(%rsi) + movbeq 456(%rdi), %rdx + movbeq 448(%rdi), %rax + movq %rdx, 48(%rsi) + movq %rax, 56(%rsi) + movbeq 440(%rdi), %rdx + movbeq 432(%rdi), %rax + movq %rdx, 64(%rsi) + movq %rax, 72(%rsi) + movbeq 424(%rdi), %rdx + movbeq 416(%rdi), %rax + movq %rdx, 80(%rsi) + movq %rax, 88(%rsi) + movbeq 408(%rdi), %rdx + movbeq 400(%rdi), %rax + movq %rdx, 96(%rsi) + movq %rax, 104(%rsi) + movbeq 392(%rdi), %rdx + movbeq 384(%rdi), %rax + movq %rdx, 112(%rsi) + movq %rax, 120(%rsi) + movbeq 376(%rdi), %rdx + movbeq 368(%rdi), %rax + movq %rdx, 128(%rsi) + movq %rax, 136(%rsi) + movbeq 360(%rdi), %rdx + movbeq 352(%rdi), %rax + movq %rdx, 144(%rsi) + movq %rax, 152(%rsi) + movbeq 344(%rdi), %rdx + movbeq 336(%rdi), %rax + movq %rdx, 160(%rsi) + movq %rax, 168(%rsi) + movbeq 328(%rdi), %rdx + movbeq 320(%rdi), %rax + movq %rdx, 176(%rsi) + movq %rax, 184(%rsi) + movbeq 312(%rdi), %rdx + movbeq 304(%rdi), %rax + movq %rdx, 192(%rsi) + movq %rax, 200(%rsi) + movbeq 296(%rdi), %rdx + movbeq 288(%rdi), %rax + movq %rdx, 208(%rsi) + movq %rax, 216(%rsi) + movbeq 280(%rdi), %rdx + movbeq 272(%rdi), %rax + movq %rdx, 224(%rsi) + movq %rax, 232(%rsi) + movbeq 264(%rdi), %rdx + movbeq 256(%rdi), %rax + movq %rdx, 240(%rsi) + movq %rax, 248(%rsi) + movbeq 248(%rdi), %rdx + movbeq 240(%rdi), %rax + movq %rdx, 256(%rsi) + movq %rax, 264(%rsi) + movbeq 232(%rdi), %rdx + movbeq 224(%rdi), %rax + movq %rdx, 272(%rsi) + movq %rax, 280(%rsi) + movbeq 216(%rdi), %rdx + movbeq 208(%rdi), %rax + movq %rdx, 288(%rsi) + movq %rax, 296(%rsi) + movbeq 200(%rdi), %rdx + movbeq 192(%rdi), %rax + movq %rdx, 304(%rsi) + movq %rax, 312(%rsi) + movbeq 184(%rdi), %rdx + movbeq 176(%rdi), %rax + movq %rdx, 320(%rsi) + movq %rax, 328(%rsi) + movbeq 168(%rdi), %rdx + movbeq 160(%rdi), %rax + movq %rdx, 336(%rsi) + movq %rax, 344(%rsi) + movbeq 152(%rdi), %rdx + movbeq 144(%rdi), %rax + movq %rdx, 352(%rsi) + movq %rax, 360(%rsi) + movbeq 136(%rdi), %rdx + movbeq 128(%rdi), %rax + movq %rdx, 368(%rsi) + movq %rax, 376(%rsi) + movbeq 120(%rdi), %rdx + movbeq 112(%rdi), %rax + movq %rdx, 384(%rsi) + movq %rax, 392(%rsi) + movbeq 104(%rdi), %rdx + movbeq 96(%rdi), %rax + movq %rdx, 400(%rsi) + movq %rax, 408(%rsi) + movbeq 88(%rdi), %rdx + movbeq 80(%rdi), %rax + movq %rdx, 416(%rsi) + movq %rax, 424(%rsi) + movbeq 72(%rdi), %rdx + movbeq 64(%rdi), %rax + movq %rdx, 432(%rsi) + movq %rax, 440(%rsi) + movbeq 56(%rdi), %rdx + movbeq 48(%rdi), %rax + movq %rdx, 448(%rsi) + movq %rax, 456(%rsi) + movbeq 40(%rdi), %rdx + movbeq 32(%rdi), %rax + movq %rdx, 464(%rsi) + movq %rax, 472(%rsi) + movbeq 24(%rdi), %rdx + movbeq 16(%rdi), %rax + movq %rdx, 480(%rsi) + movq %rax, 488(%rsi) + movbeq 8(%rdi), %rdx + movbeq (%rdi), %rax + movq %rdx, 496(%rsi) + movq %rax, 504(%rsi) + repz retq +#ifndef __APPLE__ +.size sp_4096_to_bin,.-sp_4096_to_bin +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_4096_sub_in_place_64 +.type sp_4096_sub_in_place_64,@function +.align 16 +sp_4096_sub_in_place_64: +#else +.globl _sp_4096_sub_in_place_64 +.p2align 4 +_sp_4096_sub_in_place_64: +#endif /* __APPLE__ */ + movq (%rdi), %rdx + xorq %rax, %rax + subq (%rsi), %rdx + movq 8(%rdi), %rcx + movq %rdx, (%rdi) + sbbq 8(%rsi), %rcx + movq 16(%rdi), %rdx + movq %rcx, 8(%rdi) + sbbq 16(%rsi), %rdx + movq 24(%rdi), %rcx + movq %rdx, 16(%rdi) + sbbq 24(%rsi), %rcx + movq 32(%rdi), %rdx + movq %rcx, 24(%rdi) + sbbq 32(%rsi), %rdx + movq 40(%rdi), %rcx + movq %rdx, 32(%rdi) + sbbq 40(%rsi), %rcx + movq 48(%rdi), %rdx + movq %rcx, 40(%rdi) + sbbq 48(%rsi), %rdx + movq 56(%rdi), %rcx + movq %rdx, 48(%rdi) + sbbq 56(%rsi), %rcx + movq 64(%rdi), %rdx + movq %rcx, 56(%rdi) + sbbq 64(%rsi), %rdx + movq 72(%rdi), %rcx + movq %rdx, 64(%rdi) + sbbq 72(%rsi), %rcx + movq 80(%rdi), %rdx + movq %rcx, 72(%rdi) + sbbq 80(%rsi), %rdx + movq 88(%rdi), %rcx + movq %rdx, 80(%rdi) + sbbq 88(%rsi), %rcx + movq 96(%rdi), %rdx + movq %rcx, 88(%rdi) + sbbq 96(%rsi), %rdx + movq 104(%rdi), %rcx + movq %rdx, 96(%rdi) + sbbq 104(%rsi), %rcx + movq 112(%rdi), %rdx + movq %rcx, 104(%rdi) + sbbq 112(%rsi), %rdx + movq 120(%rdi), %rcx + movq %rdx, 112(%rdi) + sbbq 120(%rsi), %rcx + movq 128(%rdi), %rdx + movq %rcx, 120(%rdi) + sbbq 128(%rsi), %rdx + movq 136(%rdi), %rcx + movq %rdx, 128(%rdi) + sbbq 136(%rsi), %rcx + movq 144(%rdi), %rdx + movq %rcx, 136(%rdi) + sbbq 144(%rsi), %rdx + movq 152(%rdi), %rcx + movq %rdx, 144(%rdi) + sbbq 152(%rsi), %rcx + movq 160(%rdi), %rdx + movq %rcx, 152(%rdi) + sbbq 160(%rsi), %rdx + movq 168(%rdi), %rcx + movq %rdx, 160(%rdi) + sbbq 168(%rsi), %rcx + movq 176(%rdi), %rdx + movq %rcx, 168(%rdi) + sbbq 176(%rsi), %rdx + movq 184(%rdi), %rcx + movq %rdx, 176(%rdi) + sbbq 184(%rsi), %rcx + movq 192(%rdi), %rdx + movq %rcx, 184(%rdi) + sbbq 192(%rsi), %rdx + movq 200(%rdi), %rcx + movq %rdx, 192(%rdi) + sbbq 200(%rsi), %rcx + movq 208(%rdi), %rdx + movq %rcx, 200(%rdi) + sbbq 208(%rsi), %rdx + movq 216(%rdi), %rcx + movq %rdx, 208(%rdi) + sbbq 216(%rsi), %rcx + movq 224(%rdi), %rdx + movq %rcx, 216(%rdi) + sbbq 224(%rsi), %rdx + movq 232(%rdi), %rcx + movq %rdx, 224(%rdi) + sbbq 232(%rsi), %rcx + movq 240(%rdi), %rdx + movq %rcx, 232(%rdi) + sbbq 240(%rsi), %rdx + movq 248(%rdi), %rcx + movq %rdx, 240(%rdi) + sbbq 248(%rsi), %rcx + movq 256(%rdi), %rdx + movq %rcx, 248(%rdi) + sbbq 256(%rsi), %rdx + movq 264(%rdi), %rcx + movq %rdx, 256(%rdi) + sbbq 264(%rsi), %rcx + movq 272(%rdi), %rdx + movq %rcx, 264(%rdi) + sbbq 272(%rsi), %rdx + movq 280(%rdi), %rcx + movq %rdx, 272(%rdi) + sbbq 280(%rsi), %rcx + movq 288(%rdi), %rdx + movq %rcx, 280(%rdi) + sbbq 288(%rsi), %rdx + movq 296(%rdi), %rcx + movq %rdx, 288(%rdi) + sbbq 296(%rsi), %rcx + movq 304(%rdi), %rdx + movq %rcx, 296(%rdi) + sbbq 304(%rsi), %rdx + movq 312(%rdi), %rcx + movq %rdx, 304(%rdi) + sbbq 312(%rsi), %rcx + movq 320(%rdi), %rdx + movq %rcx, 312(%rdi) + sbbq 320(%rsi), %rdx + movq 328(%rdi), %rcx + movq %rdx, 320(%rdi) + sbbq 328(%rsi), %rcx + movq 336(%rdi), %rdx + movq %rcx, 328(%rdi) + sbbq 336(%rsi), %rdx + movq 344(%rdi), %rcx + movq %rdx, 336(%rdi) + sbbq 344(%rsi), %rcx + movq 352(%rdi), %rdx + movq %rcx, 344(%rdi) + sbbq 352(%rsi), %rdx + movq 360(%rdi), %rcx + movq %rdx, 352(%rdi) + sbbq 360(%rsi), %rcx + movq 368(%rdi), %rdx + movq %rcx, 360(%rdi) + sbbq 368(%rsi), %rdx + movq 376(%rdi), %rcx + movq %rdx, 368(%rdi) + sbbq 376(%rsi), %rcx + movq 384(%rdi), %rdx + movq %rcx, 376(%rdi) + sbbq 384(%rsi), %rdx + movq 392(%rdi), %rcx + movq %rdx, 384(%rdi) + sbbq 392(%rsi), %rcx + movq 400(%rdi), %rdx + movq %rcx, 392(%rdi) + sbbq 400(%rsi), %rdx + movq 408(%rdi), %rcx + movq %rdx, 400(%rdi) + sbbq 408(%rsi), %rcx + movq 416(%rdi), %rdx + movq %rcx, 408(%rdi) + sbbq 416(%rsi), %rdx + movq 424(%rdi), %rcx + movq %rdx, 416(%rdi) + sbbq 424(%rsi), %rcx + movq 432(%rdi), %rdx + movq %rcx, 424(%rdi) + sbbq 432(%rsi), %rdx + movq 440(%rdi), %rcx + movq %rdx, 432(%rdi) + sbbq 440(%rsi), %rcx + movq 448(%rdi), %rdx + movq %rcx, 440(%rdi) + sbbq 448(%rsi), %rdx + movq 456(%rdi), %rcx + movq %rdx, 448(%rdi) + sbbq 456(%rsi), %rcx + movq 464(%rdi), %rdx + movq %rcx, 456(%rdi) + sbbq 464(%rsi), %rdx + movq 472(%rdi), %rcx + movq %rdx, 464(%rdi) + sbbq 472(%rsi), %rcx + movq 480(%rdi), %rdx + movq %rcx, 472(%rdi) + sbbq 480(%rsi), %rdx + movq 488(%rdi), %rcx + movq %rdx, 480(%rdi) + sbbq 488(%rsi), %rcx + movq 496(%rdi), %rdx + movq %rcx, 488(%rdi) + sbbq 496(%rsi), %rdx + movq 504(%rdi), %rcx + movq %rdx, 496(%rdi) + sbbq 504(%rsi), %rcx + movq %rcx, 504(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_4096_sub_in_place_64,.-sp_4096_sub_in_place_64 +#endif /* __APPLE__ */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_4096_add_64 +.type sp_4096_add_64,@function +.align 16 +sp_4096_add_64: +#else +.globl _sp_4096_add_64 +.p2align 4 +_sp_4096_add_64: +#endif /* __APPLE__ */ + # Add + movq (%rsi), %rcx + xorq %rax, %rax + addq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + adcq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + adcq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + adcq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + adcq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + adcq 40(%rdx), %r8 + movq 48(%rsi), %rcx + movq %r8, 40(%rdi) + adcq 48(%rdx), %rcx + movq 56(%rsi), %r8 + movq %rcx, 48(%rdi) + adcq 56(%rdx), %r8 + movq 64(%rsi), %rcx + movq %r8, 56(%rdi) + adcq 64(%rdx), %rcx + movq 72(%rsi), %r8 + movq %rcx, 64(%rdi) + adcq 72(%rdx), %r8 + movq 80(%rsi), %rcx + movq %r8, 72(%rdi) + adcq 80(%rdx), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%rdi) + adcq 88(%rdx), %r8 + movq 96(%rsi), %rcx + movq %r8, 88(%rdi) + adcq 96(%rdx), %rcx + movq 104(%rsi), %r8 + movq %rcx, 96(%rdi) + adcq 104(%rdx), %r8 + movq 112(%rsi), %rcx + movq %r8, 104(%rdi) + adcq 112(%rdx), %rcx + movq 120(%rsi), %r8 + movq %rcx, 112(%rdi) + adcq 120(%rdx), %r8 + movq 128(%rsi), %rcx + movq %r8, 120(%rdi) + adcq 128(%rdx), %rcx + movq 136(%rsi), %r8 + movq %rcx, 128(%rdi) + adcq 136(%rdx), %r8 + movq 144(%rsi), %rcx + movq %r8, 136(%rdi) + adcq 144(%rdx), %rcx + movq 152(%rsi), %r8 + movq %rcx, 144(%rdi) + adcq 152(%rdx), %r8 + movq 160(%rsi), %rcx + movq %r8, 152(%rdi) + adcq 160(%rdx), %rcx + movq 168(%rsi), %r8 + movq %rcx, 160(%rdi) + adcq 168(%rdx), %r8 + movq 176(%rsi), %rcx + movq %r8, 168(%rdi) + adcq 176(%rdx), %rcx + movq 184(%rsi), %r8 + movq %rcx, 176(%rdi) + adcq 184(%rdx), %r8 + movq 192(%rsi), %rcx + movq %r8, 184(%rdi) + adcq 192(%rdx), %rcx + movq 200(%rsi), %r8 + movq %rcx, 192(%rdi) + adcq 200(%rdx), %r8 + movq 208(%rsi), %rcx + movq %r8, 200(%rdi) + adcq 208(%rdx), %rcx + movq 216(%rsi), %r8 + movq %rcx, 208(%rdi) + adcq 216(%rdx), %r8 + movq 224(%rsi), %rcx + movq %r8, 216(%rdi) + adcq 224(%rdx), %rcx + movq 232(%rsi), %r8 + movq %rcx, 224(%rdi) + adcq 232(%rdx), %r8 + movq 240(%rsi), %rcx + movq %r8, 232(%rdi) + adcq 240(%rdx), %rcx + movq 248(%rsi), %r8 + movq %rcx, 240(%rdi) + adcq 248(%rdx), %r8 + movq 256(%rsi), %rcx + movq %r8, 248(%rdi) + adcq 256(%rdx), %rcx + movq 264(%rsi), %r8 + movq %rcx, 256(%rdi) + adcq 264(%rdx), %r8 + movq 272(%rsi), %rcx + movq %r8, 264(%rdi) + adcq 272(%rdx), %rcx + movq 280(%rsi), %r8 + movq %rcx, 272(%rdi) + adcq 280(%rdx), %r8 + movq 288(%rsi), %rcx + movq %r8, 280(%rdi) + adcq 288(%rdx), %rcx + movq 296(%rsi), %r8 + movq %rcx, 288(%rdi) + adcq 296(%rdx), %r8 + movq 304(%rsi), %rcx + movq %r8, 296(%rdi) + adcq 304(%rdx), %rcx + movq 312(%rsi), %r8 + movq %rcx, 304(%rdi) + adcq 312(%rdx), %r8 + movq 320(%rsi), %rcx + movq %r8, 312(%rdi) + adcq 320(%rdx), %rcx + movq 328(%rsi), %r8 + movq %rcx, 320(%rdi) + adcq 328(%rdx), %r8 + movq 336(%rsi), %rcx + movq %r8, 328(%rdi) + adcq 336(%rdx), %rcx + movq 344(%rsi), %r8 + movq %rcx, 336(%rdi) + adcq 344(%rdx), %r8 + movq 352(%rsi), %rcx + movq %r8, 344(%rdi) + adcq 352(%rdx), %rcx + movq 360(%rsi), %r8 + movq %rcx, 352(%rdi) + adcq 360(%rdx), %r8 + movq 368(%rsi), %rcx + movq %r8, 360(%rdi) + adcq 368(%rdx), %rcx + movq 376(%rsi), %r8 + movq %rcx, 368(%rdi) + adcq 376(%rdx), %r8 + movq 384(%rsi), %rcx + movq %r8, 376(%rdi) + adcq 384(%rdx), %rcx + movq 392(%rsi), %r8 + movq %rcx, 384(%rdi) + adcq 392(%rdx), %r8 + movq 400(%rsi), %rcx + movq %r8, 392(%rdi) + adcq 400(%rdx), %rcx + movq 408(%rsi), %r8 + movq %rcx, 400(%rdi) + adcq 408(%rdx), %r8 + movq 416(%rsi), %rcx + movq %r8, 408(%rdi) + adcq 416(%rdx), %rcx + movq 424(%rsi), %r8 + movq %rcx, 416(%rdi) + adcq 424(%rdx), %r8 + movq 432(%rsi), %rcx + movq %r8, 424(%rdi) + adcq 432(%rdx), %rcx + movq 440(%rsi), %r8 + movq %rcx, 432(%rdi) + adcq 440(%rdx), %r8 + movq 448(%rsi), %rcx + movq %r8, 440(%rdi) + adcq 448(%rdx), %rcx + movq 456(%rsi), %r8 + movq %rcx, 448(%rdi) + adcq 456(%rdx), %r8 + movq 464(%rsi), %rcx + movq %r8, 456(%rdi) + adcq 464(%rdx), %rcx + movq 472(%rsi), %r8 + movq %rcx, 464(%rdi) + adcq 472(%rdx), %r8 + movq 480(%rsi), %rcx + movq %r8, 472(%rdi) + adcq 480(%rdx), %rcx + movq 488(%rsi), %r8 + movq %rcx, 480(%rdi) + adcq 488(%rdx), %r8 + movq 496(%rsi), %rcx + movq %r8, 488(%rdi) + adcq 496(%rdx), %rcx + movq 504(%rsi), %r8 + movq %rcx, 496(%rdi) + adcq 504(%rdx), %r8 + movq %r8, 504(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_4096_add_64,.-sp_4096_add_64 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_4096_mul_64 +.type sp_4096_mul_64,@function +.align 16 +sp_4096_mul_64: +#else +.globl _sp_4096_mul_64 +.p2align 4 +_sp_4096_mul_64: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + subq $1576, %rsp + movq %rdi, 1536(%rsp) + movq %rsi, 1544(%rsp) + movq %rdx, 1552(%rsp) + leaq 1024(%rsp), %r10 + leaq 256(%rsi), %r12 + # Add + movq (%rsi), %rax + xorq %r13, %r13 + addq (%r12), %rax + movq 8(%rsi), %rcx + movq %rax, (%r10) + adcq 8(%r12), %rcx + movq 16(%rsi), %r8 + movq %rcx, 8(%r10) + adcq 16(%r12), %r8 + movq 24(%rsi), %rax + movq %r8, 16(%r10) + adcq 24(%r12), %rax + movq 32(%rsi), %rcx + movq %rax, 24(%r10) + adcq 32(%r12), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%r10) + adcq 40(%r12), %r8 + movq 48(%rsi), %rax + movq %r8, 40(%r10) + adcq 48(%r12), %rax + movq 56(%rsi), %rcx + movq %rax, 48(%r10) + adcq 56(%r12), %rcx + movq 64(%rsi), %r8 + movq %rcx, 56(%r10) + adcq 64(%r12), %r8 + movq 72(%rsi), %rax + movq %r8, 64(%r10) + adcq 72(%r12), %rax + movq 80(%rsi), %rcx + movq %rax, 72(%r10) + adcq 80(%r12), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%r10) + adcq 88(%r12), %r8 + movq 96(%rsi), %rax + movq %r8, 88(%r10) + adcq 96(%r12), %rax + movq 104(%rsi), %rcx + movq %rax, 96(%r10) + adcq 104(%r12), %rcx + movq 112(%rsi), %r8 + movq %rcx, 104(%r10) + adcq 112(%r12), %r8 + movq 120(%rsi), %rax + movq %r8, 112(%r10) + adcq 120(%r12), %rax + movq 128(%rsi), %rcx + movq %rax, 120(%r10) + adcq 128(%r12), %rcx + movq 136(%rsi), %r8 + movq %rcx, 128(%r10) + adcq 136(%r12), %r8 + movq 144(%rsi), %rax + movq %r8, 136(%r10) + adcq 144(%r12), %rax + movq 152(%rsi), %rcx + movq %rax, 144(%r10) + adcq 152(%r12), %rcx + movq 160(%rsi), %r8 + movq %rcx, 152(%r10) + adcq 160(%r12), %r8 + movq 168(%rsi), %rax + movq %r8, 160(%r10) + adcq 168(%r12), %rax + movq 176(%rsi), %rcx + movq %rax, 168(%r10) + adcq 176(%r12), %rcx + movq 184(%rsi), %r8 + movq %rcx, 176(%r10) + adcq 184(%r12), %r8 + movq 192(%rsi), %rax + movq %r8, 184(%r10) + adcq 192(%r12), %rax + movq 200(%rsi), %rcx + movq %rax, 192(%r10) + adcq 200(%r12), %rcx + movq 208(%rsi), %r8 + movq %rcx, 200(%r10) + adcq 208(%r12), %r8 + movq 216(%rsi), %rax + movq %r8, 208(%r10) + adcq 216(%r12), %rax + movq 224(%rsi), %rcx + movq %rax, 216(%r10) + adcq 224(%r12), %rcx + movq 232(%rsi), %r8 + movq %rcx, 224(%r10) + adcq 232(%r12), %r8 + movq 240(%rsi), %rax + movq %r8, 232(%r10) + adcq 240(%r12), %rax + movq 248(%rsi), %rcx + movq %rax, 240(%r10) + adcq 248(%r12), %rcx + movq %rcx, 248(%r10) + adcq $0, %r13 + movq %r13, 1560(%rsp) + leaq 1280(%rsp), %r11 + leaq 256(%rdx), %r12 + # Add + movq (%rdx), %rax + xorq %r14, %r14 + addq (%r12), %rax + movq 8(%rdx), %rcx + movq %rax, (%r11) + adcq 8(%r12), %rcx + movq 16(%rdx), %r8 + movq %rcx, 8(%r11) + adcq 16(%r12), %r8 + movq 24(%rdx), %rax + movq %r8, 16(%r11) + adcq 24(%r12), %rax + movq 32(%rdx), %rcx + movq %rax, 24(%r11) + adcq 32(%r12), %rcx + movq 40(%rdx), %r8 + movq %rcx, 32(%r11) + adcq 40(%r12), %r8 + movq 48(%rdx), %rax + movq %r8, 40(%r11) + adcq 48(%r12), %rax + movq 56(%rdx), %rcx + movq %rax, 48(%r11) + adcq 56(%r12), %rcx + movq 64(%rdx), %r8 + movq %rcx, 56(%r11) + adcq 64(%r12), %r8 + movq 72(%rdx), %rax + movq %r8, 64(%r11) + adcq 72(%r12), %rax + movq 80(%rdx), %rcx + movq %rax, 72(%r11) + adcq 80(%r12), %rcx + movq 88(%rdx), %r8 + movq %rcx, 80(%r11) + adcq 88(%r12), %r8 + movq 96(%rdx), %rax + movq %r8, 88(%r11) + adcq 96(%r12), %rax + movq 104(%rdx), %rcx + movq %rax, 96(%r11) + adcq 104(%r12), %rcx + movq 112(%rdx), %r8 + movq %rcx, 104(%r11) + adcq 112(%r12), %r8 + movq 120(%rdx), %rax + movq %r8, 112(%r11) + adcq 120(%r12), %rax + movq 128(%rdx), %rcx + movq %rax, 120(%r11) + adcq 128(%r12), %rcx + movq 136(%rdx), %r8 + movq %rcx, 128(%r11) + adcq 136(%r12), %r8 + movq 144(%rdx), %rax + movq %r8, 136(%r11) + adcq 144(%r12), %rax + movq 152(%rdx), %rcx + movq %rax, 144(%r11) + adcq 152(%r12), %rcx + movq 160(%rdx), %r8 + movq %rcx, 152(%r11) + adcq 160(%r12), %r8 + movq 168(%rdx), %rax + movq %r8, 160(%r11) + adcq 168(%r12), %rax + movq 176(%rdx), %rcx + movq %rax, 168(%r11) + adcq 176(%r12), %rcx + movq 184(%rdx), %r8 + movq %rcx, 176(%r11) + adcq 184(%r12), %r8 + movq 192(%rdx), %rax + movq %r8, 184(%r11) + adcq 192(%r12), %rax + movq 200(%rdx), %rcx + movq %rax, 192(%r11) + adcq 200(%r12), %rcx + movq 208(%rdx), %r8 + movq %rcx, 200(%r11) + adcq 208(%r12), %r8 + movq 216(%rdx), %rax + movq %r8, 208(%r11) + adcq 216(%r12), %rax + movq 224(%rdx), %rcx + movq %rax, 216(%r11) + adcq 224(%r12), %rcx + movq 232(%rdx), %r8 + movq %rcx, 224(%r11) + adcq 232(%r12), %r8 + movq 240(%rdx), %rax + movq %r8, 232(%r11) + adcq 240(%r12), %rax + movq 248(%rdx), %rcx + movq %rax, 240(%r11) + adcq 248(%r12), %rcx + movq %rcx, 248(%r11) + adcq $0, %r14 + movq %r14, 1568(%rsp) + movq %r11, %rdx + movq %r10, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_2048_mul_32@plt +#else + callq _sp_2048_mul_32 +#endif /* __APPLE__ */ + movq 1552(%rsp), %rdx + movq 1544(%rsp), %rsi + leaq 512(%rsp), %rdi + addq $256, %rdx + addq $256, %rsi +#ifndef __APPLE__ + callq sp_2048_mul_32@plt +#else + callq _sp_2048_mul_32 +#endif /* __APPLE__ */ + movq 1552(%rsp), %rdx + movq 1544(%rsp), %rsi + movq 1536(%rsp), %rdi +#ifndef __APPLE__ + callq sp_2048_mul_32@plt +#else + callq _sp_2048_mul_32 +#endif /* __APPLE__ */ + movq 1560(%rsp), %r13 + movq 1568(%rsp), %r14 + movq 1536(%rsp), %r15 + movq %r13, %r9 + leaq 1024(%rsp), %r10 + leaq 1280(%rsp), %r11 + andq %r14, %r9 + negq %r13 + negq %r14 + addq $512, %r15 + movq (%r10), %rax + movq (%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, (%r10) + movq %rcx, (%r11) + movq 8(%r10), %rax + movq 8(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 8(%r10) + movq %rcx, 8(%r11) + movq 16(%r10), %rax + movq 16(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 16(%r10) + movq %rcx, 16(%r11) + movq 24(%r10), %rax + movq 24(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 24(%r10) + movq %rcx, 24(%r11) + movq 32(%r10), %rax + movq 32(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 32(%r10) + movq %rcx, 32(%r11) + movq 40(%r10), %rax + movq 40(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 40(%r10) + movq %rcx, 40(%r11) + movq 48(%r10), %rax + movq 48(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 48(%r10) + movq %rcx, 48(%r11) + movq 56(%r10), %rax + movq 56(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 56(%r10) + movq %rcx, 56(%r11) + movq 64(%r10), %rax + movq 64(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 64(%r10) + movq %rcx, 64(%r11) + movq 72(%r10), %rax + movq 72(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 72(%r10) + movq %rcx, 72(%r11) + movq 80(%r10), %rax + movq 80(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 80(%r10) + movq %rcx, 80(%r11) + movq 88(%r10), %rax + movq 88(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 88(%r10) + movq %rcx, 88(%r11) + movq 96(%r10), %rax + movq 96(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 96(%r10) + movq %rcx, 96(%r11) + movq 104(%r10), %rax + movq 104(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 104(%r10) + movq %rcx, 104(%r11) + movq 112(%r10), %rax + movq 112(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 112(%r10) + movq %rcx, 112(%r11) + movq 120(%r10), %rax + movq 120(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 120(%r10) + movq %rcx, 120(%r11) + movq 128(%r10), %rax + movq 128(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 128(%r10) + movq %rcx, 128(%r11) + movq 136(%r10), %rax + movq 136(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 136(%r10) + movq %rcx, 136(%r11) + movq 144(%r10), %rax + movq 144(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 144(%r10) + movq %rcx, 144(%r11) + movq 152(%r10), %rax + movq 152(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 152(%r10) + movq %rcx, 152(%r11) + movq 160(%r10), %rax + movq 160(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 160(%r10) + movq %rcx, 160(%r11) + movq 168(%r10), %rax + movq 168(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 168(%r10) + movq %rcx, 168(%r11) + movq 176(%r10), %rax + movq 176(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 176(%r10) + movq %rcx, 176(%r11) + movq 184(%r10), %rax + movq 184(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 184(%r10) + movq %rcx, 184(%r11) + movq 192(%r10), %rax + movq 192(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 192(%r10) + movq %rcx, 192(%r11) + movq 200(%r10), %rax + movq 200(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 200(%r10) + movq %rcx, 200(%r11) + movq 208(%r10), %rax + movq 208(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 208(%r10) + movq %rcx, 208(%r11) + movq 216(%r10), %rax + movq 216(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 216(%r10) + movq %rcx, 216(%r11) + movq 224(%r10), %rax + movq 224(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 224(%r10) + movq %rcx, 224(%r11) + movq 232(%r10), %rax + movq 232(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 232(%r10) + movq %rcx, 232(%r11) + movq 240(%r10), %rax + movq 240(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 240(%r10) + movq %rcx, 240(%r11) + movq 248(%r10), %rax + movq 248(%r11), %rcx + andq %r14, %rax + andq %r13, %rcx + movq %rax, 248(%r10) + movq %rcx, 248(%r11) + movq (%r10), %rax + addq (%r11), %rax + movq 8(%r10), %rcx + movq %rax, (%r15) + adcq 8(%r11), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r15) + adcq 16(%r11), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r15) + adcq 24(%r11), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r15) + adcq 32(%r11), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r15) + adcq 40(%r11), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r15) + adcq 48(%r11), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r15) + adcq 56(%r11), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r15) + adcq 64(%r11), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r15) + adcq 72(%r11), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r15) + adcq 80(%r11), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r15) + adcq 88(%r11), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r15) + adcq 96(%r11), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r15) + adcq 104(%r11), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r15) + adcq 112(%r11), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r15) + adcq 120(%r11), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r15) + adcq 128(%r11), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r15) + adcq 136(%r11), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r15) + adcq 144(%r11), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r15) + adcq 152(%r11), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r15) + adcq 160(%r11), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r15) + adcq 168(%r11), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r15) + adcq 176(%r11), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r15) + adcq 184(%r11), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r15) + adcq 192(%r11), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r15) + adcq 200(%r11), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r15) + adcq 208(%r11), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r15) + adcq 216(%r11), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r15) + adcq 224(%r11), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r15) + adcq 232(%r11), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r15) + adcq 240(%r11), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r15) + adcq 248(%r11), %rcx + movq %rcx, 248(%r15) + adcq $0, %r9 + leaq 512(%rsp), %r11 + movq %rsp, %r10 + movq (%r10), %rax + subq (%r11), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%r11), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%r11), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%r11), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%r11), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%r11), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%r11), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%r11), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%r11), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%r11), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%r11), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%r11), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%r11), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%r11), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%r11), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%r11), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%r11), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%r11), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%r11), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%r11), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%r11), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%r11), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%r11), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%r11), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r10) + sbbq 192(%r11), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r10) + sbbq 200(%r11), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r10) + sbbq 208(%r11), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r10) + sbbq 216(%r11), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r10) + sbbq 224(%r11), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r10) + sbbq 232(%r11), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r10) + sbbq 240(%r11), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r10) + sbbq 248(%r11), %rcx + movq 256(%r10), %r8 + movq %rcx, 248(%r10) + sbbq 256(%r11), %r8 + movq 264(%r10), %rax + movq %r8, 256(%r10) + sbbq 264(%r11), %rax + movq 272(%r10), %rcx + movq %rax, 264(%r10) + sbbq 272(%r11), %rcx + movq 280(%r10), %r8 + movq %rcx, 272(%r10) + sbbq 280(%r11), %r8 + movq 288(%r10), %rax + movq %r8, 280(%r10) + sbbq 288(%r11), %rax + movq 296(%r10), %rcx + movq %rax, 288(%r10) + sbbq 296(%r11), %rcx + movq 304(%r10), %r8 + movq %rcx, 296(%r10) + sbbq 304(%r11), %r8 + movq 312(%r10), %rax + movq %r8, 304(%r10) + sbbq 312(%r11), %rax + movq 320(%r10), %rcx + movq %rax, 312(%r10) + sbbq 320(%r11), %rcx + movq 328(%r10), %r8 + movq %rcx, 320(%r10) + sbbq 328(%r11), %r8 + movq 336(%r10), %rax + movq %r8, 328(%r10) + sbbq 336(%r11), %rax + movq 344(%r10), %rcx + movq %rax, 336(%r10) + sbbq 344(%r11), %rcx + movq 352(%r10), %r8 + movq %rcx, 344(%r10) + sbbq 352(%r11), %r8 + movq 360(%r10), %rax + movq %r8, 352(%r10) + sbbq 360(%r11), %rax + movq 368(%r10), %rcx + movq %rax, 360(%r10) + sbbq 368(%r11), %rcx + movq 376(%r10), %r8 + movq %rcx, 368(%r10) + sbbq 376(%r11), %r8 + movq 384(%r10), %rax + movq %r8, 376(%r10) + sbbq 384(%r11), %rax + movq 392(%r10), %rcx + movq %rax, 384(%r10) + sbbq 392(%r11), %rcx + movq 400(%r10), %r8 + movq %rcx, 392(%r10) + sbbq 400(%r11), %r8 + movq 408(%r10), %rax + movq %r8, 400(%r10) + sbbq 408(%r11), %rax + movq 416(%r10), %rcx + movq %rax, 408(%r10) + sbbq 416(%r11), %rcx + movq 424(%r10), %r8 + movq %rcx, 416(%r10) + sbbq 424(%r11), %r8 + movq 432(%r10), %rax + movq %r8, 424(%r10) + sbbq 432(%r11), %rax + movq 440(%r10), %rcx + movq %rax, 432(%r10) + sbbq 440(%r11), %rcx + movq 448(%r10), %r8 + movq %rcx, 440(%r10) + sbbq 448(%r11), %r8 + movq 456(%r10), %rax + movq %r8, 448(%r10) + sbbq 456(%r11), %rax + movq 464(%r10), %rcx + movq %rax, 456(%r10) + sbbq 464(%r11), %rcx + movq 472(%r10), %r8 + movq %rcx, 464(%r10) + sbbq 472(%r11), %r8 + movq 480(%r10), %rax + movq %r8, 472(%r10) + sbbq 480(%r11), %rax + movq 488(%r10), %rcx + movq %rax, 480(%r10) + sbbq 488(%r11), %rcx + movq 496(%r10), %r8 + movq %rcx, 488(%r10) + sbbq 496(%r11), %r8 + movq 504(%r10), %rax + movq %r8, 496(%r10) + sbbq 504(%r11), %rax + movq %rax, 504(%r10) + sbbq $0, %r9 + movq (%r10), %rax + subq (%rdi), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%rdi), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%rdi), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%rdi), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%rdi), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%rdi), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%rdi), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%rdi), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%rdi), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%rdi), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%rdi), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%rdi), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%rdi), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%rdi), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%rdi), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%rdi), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%rdi), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%rdi), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%rdi), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%rdi), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%rdi), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%rdi), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%rdi), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%rdi), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r10) + sbbq 192(%rdi), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r10) + sbbq 200(%rdi), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r10) + sbbq 208(%rdi), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r10) + sbbq 216(%rdi), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r10) + sbbq 224(%rdi), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r10) + sbbq 232(%rdi), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r10) + sbbq 240(%rdi), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r10) + sbbq 248(%rdi), %rcx + movq 256(%r10), %r8 + movq %rcx, 248(%r10) + sbbq 256(%rdi), %r8 + movq 264(%r10), %rax + movq %r8, 256(%r10) + sbbq 264(%rdi), %rax + movq 272(%r10), %rcx + movq %rax, 264(%r10) + sbbq 272(%rdi), %rcx + movq 280(%r10), %r8 + movq %rcx, 272(%r10) + sbbq 280(%rdi), %r8 + movq 288(%r10), %rax + movq %r8, 280(%r10) + sbbq 288(%rdi), %rax + movq 296(%r10), %rcx + movq %rax, 288(%r10) + sbbq 296(%rdi), %rcx + movq 304(%r10), %r8 + movq %rcx, 296(%r10) + sbbq 304(%rdi), %r8 + movq 312(%r10), %rax + movq %r8, 304(%r10) + sbbq 312(%rdi), %rax + movq 320(%r10), %rcx + movq %rax, 312(%r10) + sbbq 320(%rdi), %rcx + movq 328(%r10), %r8 + movq %rcx, 320(%r10) + sbbq 328(%rdi), %r8 + movq 336(%r10), %rax + movq %r8, 328(%r10) + sbbq 336(%rdi), %rax + movq 344(%r10), %rcx + movq %rax, 336(%r10) + sbbq 344(%rdi), %rcx + movq 352(%r10), %r8 + movq %rcx, 344(%r10) + sbbq 352(%rdi), %r8 + movq 360(%r10), %rax + movq %r8, 352(%r10) + sbbq 360(%rdi), %rax + movq 368(%r10), %rcx + movq %rax, 360(%r10) + sbbq 368(%rdi), %rcx + movq 376(%r10), %r8 + movq %rcx, 368(%r10) + sbbq 376(%rdi), %r8 + movq 384(%r10), %rax + movq %r8, 376(%r10) + sbbq 384(%rdi), %rax + movq 392(%r10), %rcx + movq %rax, 384(%r10) + sbbq 392(%rdi), %rcx + movq 400(%r10), %r8 + movq %rcx, 392(%r10) + sbbq 400(%rdi), %r8 + movq 408(%r10), %rax + movq %r8, 400(%r10) + sbbq 408(%rdi), %rax + movq 416(%r10), %rcx + movq %rax, 408(%r10) + sbbq 416(%rdi), %rcx + movq 424(%r10), %r8 + movq %rcx, 416(%r10) + sbbq 424(%rdi), %r8 + movq 432(%r10), %rax + movq %r8, 424(%r10) + sbbq 432(%rdi), %rax + movq 440(%r10), %rcx + movq %rax, 432(%r10) + sbbq 440(%rdi), %rcx + movq 448(%r10), %r8 + movq %rcx, 440(%r10) + sbbq 448(%rdi), %r8 + movq 456(%r10), %rax + movq %r8, 448(%r10) + sbbq 456(%rdi), %rax + movq 464(%r10), %rcx + movq %rax, 456(%r10) + sbbq 464(%rdi), %rcx + movq 472(%r10), %r8 + movq %rcx, 464(%r10) + sbbq 472(%rdi), %r8 + movq 480(%r10), %rax + movq %r8, 472(%r10) + sbbq 480(%rdi), %rax + movq 488(%r10), %rcx + movq %rax, 480(%r10) + sbbq 488(%rdi), %rcx + movq 496(%r10), %r8 + movq %rcx, 488(%r10) + sbbq 496(%rdi), %r8 + movq 504(%r10), %rax + movq %r8, 496(%r10) + sbbq 504(%rdi), %rax + movq %rax, 504(%r10) + sbbq $0, %r9 + subq $256, %r15 + # Add + movq (%r15), %rax + addq (%r10), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r10), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r10), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r10), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r10), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r10), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r10), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r10), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r10), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r10), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r10), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r10), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r10), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r10), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r10), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r10), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r10), %rcx + movq 136(%r15), %r8 + movq %rcx, 128(%r15) + adcq 136(%r10), %r8 + movq 144(%r15), %rax + movq %r8, 136(%r15) + adcq 144(%r10), %rax + movq 152(%r15), %rcx + movq %rax, 144(%r15) + adcq 152(%r10), %rcx + movq 160(%r15), %r8 + movq %rcx, 152(%r15) + adcq 160(%r10), %r8 + movq 168(%r15), %rax + movq %r8, 160(%r15) + adcq 168(%r10), %rax + movq 176(%r15), %rcx + movq %rax, 168(%r15) + adcq 176(%r10), %rcx + movq 184(%r15), %r8 + movq %rcx, 176(%r15) + adcq 184(%r10), %r8 + movq 192(%r15), %rax + movq %r8, 184(%r15) + adcq 192(%r10), %rax + movq 200(%r15), %rcx + movq %rax, 192(%r15) + adcq 200(%r10), %rcx + movq 208(%r15), %r8 + movq %rcx, 200(%r15) + adcq 208(%r10), %r8 + movq 216(%r15), %rax + movq %r8, 208(%r15) + adcq 216(%r10), %rax + movq 224(%r15), %rcx + movq %rax, 216(%r15) + adcq 224(%r10), %rcx + movq 232(%r15), %r8 + movq %rcx, 224(%r15) + adcq 232(%r10), %r8 + movq 240(%r15), %rax + movq %r8, 232(%r15) + adcq 240(%r10), %rax + movq 248(%r15), %rcx + movq %rax, 240(%r15) + adcq 248(%r10), %rcx + movq 256(%r15), %r8 + movq %rcx, 248(%r15) + adcq 256(%r10), %r8 + movq 264(%r15), %rax + movq %r8, 256(%r15) + adcq 264(%r10), %rax + movq 272(%r15), %rcx + movq %rax, 264(%r15) + adcq 272(%r10), %rcx + movq 280(%r15), %r8 + movq %rcx, 272(%r15) + adcq 280(%r10), %r8 + movq 288(%r15), %rax + movq %r8, 280(%r15) + adcq 288(%r10), %rax + movq 296(%r15), %rcx + movq %rax, 288(%r15) + adcq 296(%r10), %rcx + movq 304(%r15), %r8 + movq %rcx, 296(%r15) + adcq 304(%r10), %r8 + movq 312(%r15), %rax + movq %r8, 304(%r15) + adcq 312(%r10), %rax + movq 320(%r15), %rcx + movq %rax, 312(%r15) + adcq 320(%r10), %rcx + movq 328(%r15), %r8 + movq %rcx, 320(%r15) + adcq 328(%r10), %r8 + movq 336(%r15), %rax + movq %r8, 328(%r15) + adcq 336(%r10), %rax + movq 344(%r15), %rcx + movq %rax, 336(%r15) + adcq 344(%r10), %rcx + movq 352(%r15), %r8 + movq %rcx, 344(%r15) + adcq 352(%r10), %r8 + movq 360(%r15), %rax + movq %r8, 352(%r15) + adcq 360(%r10), %rax + movq 368(%r15), %rcx + movq %rax, 360(%r15) + adcq 368(%r10), %rcx + movq 376(%r15), %r8 + movq %rcx, 368(%r15) + adcq 376(%r10), %r8 + movq 384(%r15), %rax + movq %r8, 376(%r15) + adcq 384(%r10), %rax + movq 392(%r15), %rcx + movq %rax, 384(%r15) + adcq 392(%r10), %rcx + movq 400(%r15), %r8 + movq %rcx, 392(%r15) + adcq 400(%r10), %r8 + movq 408(%r15), %rax + movq %r8, 400(%r15) + adcq 408(%r10), %rax + movq 416(%r15), %rcx + movq %rax, 408(%r15) + adcq 416(%r10), %rcx + movq 424(%r15), %r8 + movq %rcx, 416(%r15) + adcq 424(%r10), %r8 + movq 432(%r15), %rax + movq %r8, 424(%r15) + adcq 432(%r10), %rax + movq 440(%r15), %rcx + movq %rax, 432(%r15) + adcq 440(%r10), %rcx + movq 448(%r15), %r8 + movq %rcx, 440(%r15) + adcq 448(%r10), %r8 + movq 456(%r15), %rax + movq %r8, 448(%r15) + adcq 456(%r10), %rax + movq 464(%r15), %rcx + movq %rax, 456(%r15) + adcq 464(%r10), %rcx + movq 472(%r15), %r8 + movq %rcx, 464(%r15) + adcq 472(%r10), %r8 + movq 480(%r15), %rax + movq %r8, 472(%r15) + adcq 480(%r10), %rax + movq 488(%r15), %rcx + movq %rax, 480(%r15) + adcq 488(%r10), %rcx + movq 496(%r15), %r8 + movq %rcx, 488(%r15) + adcq 496(%r10), %r8 + movq 504(%r15), %rax + movq %r8, 496(%r15) + adcq 504(%r10), %rax + movq %rax, 504(%r15) + adcq $0, %r9 + movq %r9, 768(%rdi) + addq $256, %r15 + # Add + movq (%r15), %rax + xorq %r9, %r9 + addq (%r11), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r11), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r11), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r11), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r11), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r11), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r11), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r11), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r11), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r11), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r11), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r11), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r11), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r11), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r11), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r11), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r11), %rcx + movq 136(%r15), %r8 + movq %rcx, 128(%r15) + adcq 136(%r11), %r8 + movq 144(%r15), %rax + movq %r8, 136(%r15) + adcq 144(%r11), %rax + movq 152(%r15), %rcx + movq %rax, 144(%r15) + adcq 152(%r11), %rcx + movq 160(%r15), %r8 + movq %rcx, 152(%r15) + adcq 160(%r11), %r8 + movq 168(%r15), %rax + movq %r8, 160(%r15) + adcq 168(%r11), %rax + movq 176(%r15), %rcx + movq %rax, 168(%r15) + adcq 176(%r11), %rcx + movq 184(%r15), %r8 + movq %rcx, 176(%r15) + adcq 184(%r11), %r8 + movq 192(%r15), %rax + movq %r8, 184(%r15) + adcq 192(%r11), %rax + movq 200(%r15), %rcx + movq %rax, 192(%r15) + adcq 200(%r11), %rcx + movq 208(%r15), %r8 + movq %rcx, 200(%r15) + adcq 208(%r11), %r8 + movq 216(%r15), %rax + movq %r8, 208(%r15) + adcq 216(%r11), %rax + movq 224(%r15), %rcx + movq %rax, 216(%r15) + adcq 224(%r11), %rcx + movq 232(%r15), %r8 + movq %rcx, 224(%r15) + adcq 232(%r11), %r8 + movq 240(%r15), %rax + movq %r8, 232(%r15) + adcq 240(%r11), %rax + movq 248(%r15), %rcx + movq %rax, 240(%r15) + adcq 248(%r11), %rcx + movq 256(%r15), %r8 + movq %rcx, 248(%r15) + adcq 256(%r11), %r8 + movq %r8, 256(%r15) + adcq $0, %r9 + # Add to zero + movq 264(%r11), %rax + adcq $0, %rax + movq 272(%r11), %rcx + movq %rax, 264(%r15) + adcq $0, %rcx + movq 280(%r11), %r8 + movq %rcx, 272(%r15) + adcq $0, %r8 + movq 288(%r11), %rax + movq %r8, 280(%r15) + adcq $0, %rax + movq 296(%r11), %rcx + movq %rax, 288(%r15) + adcq $0, %rcx + movq 304(%r11), %r8 + movq %rcx, 296(%r15) + adcq $0, %r8 + movq 312(%r11), %rax + movq %r8, 304(%r15) + adcq $0, %rax + movq 320(%r11), %rcx + movq %rax, 312(%r15) + adcq $0, %rcx + movq 328(%r11), %r8 + movq %rcx, 320(%r15) + adcq $0, %r8 + movq 336(%r11), %rax + movq %r8, 328(%r15) + adcq $0, %rax + movq 344(%r11), %rcx + movq %rax, 336(%r15) + adcq $0, %rcx + movq 352(%r11), %r8 + movq %rcx, 344(%r15) + adcq $0, %r8 + movq 360(%r11), %rax + movq %r8, 352(%r15) + adcq $0, %rax + movq 368(%r11), %rcx + movq %rax, 360(%r15) + adcq $0, %rcx + movq 376(%r11), %r8 + movq %rcx, 368(%r15) + adcq $0, %r8 + movq 384(%r11), %rax + movq %r8, 376(%r15) + adcq $0, %rax + movq 392(%r11), %rcx + movq %rax, 384(%r15) + adcq $0, %rcx + movq 400(%r11), %r8 + movq %rcx, 392(%r15) + adcq $0, %r8 + movq 408(%r11), %rax + movq %r8, 400(%r15) + adcq $0, %rax + movq 416(%r11), %rcx + movq %rax, 408(%r15) + adcq $0, %rcx + movq 424(%r11), %r8 + movq %rcx, 416(%r15) + adcq $0, %r8 + movq 432(%r11), %rax + movq %r8, 424(%r15) + adcq $0, %rax + movq 440(%r11), %rcx + movq %rax, 432(%r15) + adcq $0, %rcx + movq 448(%r11), %r8 + movq %rcx, 440(%r15) + adcq $0, %r8 + movq 456(%r11), %rax + movq %r8, 448(%r15) + adcq $0, %rax + movq 464(%r11), %rcx + movq %rax, 456(%r15) + adcq $0, %rcx + movq 472(%r11), %r8 + movq %rcx, 464(%r15) + adcq $0, %r8 + movq 480(%r11), %rax + movq %r8, 472(%r15) + adcq $0, %rax + movq 488(%r11), %rcx + movq %rax, 480(%r15) + adcq $0, %rcx + movq 496(%r11), %r8 + movq %rcx, 488(%r15) + adcq $0, %r8 + movq 504(%r11), %rax + movq %r8, 496(%r15) + adcq $0, %rax + movq %rax, 504(%r15) + addq $1576, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_4096_mul_64,.-sp_4096_mul_64 +#endif /* __APPLE__ */ +/* Add a to a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_dbl_32 +.type sp_2048_dbl_32,@function +.align 16 +sp_2048_dbl_32: +#else +.globl _sp_2048_dbl_32 +.p2align 4 +_sp_2048_dbl_32: +#endif /* __APPLE__ */ + movq (%rsi), %rdx + xorq %rax, %rax + addq %rdx, %rdx + movq 8(%rsi), %rcx + movq %rdx, (%rdi) + adcq %rcx, %rcx + movq 16(%rsi), %rdx + movq %rcx, 8(%rdi) + adcq %rdx, %rdx + movq 24(%rsi), %rcx + movq %rdx, 16(%rdi) + adcq %rcx, %rcx + movq 32(%rsi), %rdx + movq %rcx, 24(%rdi) + adcq %rdx, %rdx + movq 40(%rsi), %rcx + movq %rdx, 32(%rdi) + adcq %rcx, %rcx + movq 48(%rsi), %rdx + movq %rcx, 40(%rdi) + adcq %rdx, %rdx + movq 56(%rsi), %rcx + movq %rdx, 48(%rdi) + adcq %rcx, %rcx + movq 64(%rsi), %rdx + movq %rcx, 56(%rdi) + adcq %rdx, %rdx + movq 72(%rsi), %rcx + movq %rdx, 64(%rdi) + adcq %rcx, %rcx + movq 80(%rsi), %rdx + movq %rcx, 72(%rdi) + adcq %rdx, %rdx + movq 88(%rsi), %rcx + movq %rdx, 80(%rdi) + adcq %rcx, %rcx + movq 96(%rsi), %rdx + movq %rcx, 88(%rdi) + adcq %rdx, %rdx + movq 104(%rsi), %rcx + movq %rdx, 96(%rdi) + adcq %rcx, %rcx + movq 112(%rsi), %rdx + movq %rcx, 104(%rdi) + adcq %rdx, %rdx + movq 120(%rsi), %rcx + movq %rdx, 112(%rdi) + adcq %rcx, %rcx + movq 128(%rsi), %rdx + movq %rcx, 120(%rdi) + adcq %rdx, %rdx + movq 136(%rsi), %rcx + movq %rdx, 128(%rdi) + adcq %rcx, %rcx + movq 144(%rsi), %rdx + movq %rcx, 136(%rdi) + adcq %rdx, %rdx + movq 152(%rsi), %rcx + movq %rdx, 144(%rdi) + adcq %rcx, %rcx + movq 160(%rsi), %rdx + movq %rcx, 152(%rdi) + adcq %rdx, %rdx + movq 168(%rsi), %rcx + movq %rdx, 160(%rdi) + adcq %rcx, %rcx + movq 176(%rsi), %rdx + movq %rcx, 168(%rdi) + adcq %rdx, %rdx + movq 184(%rsi), %rcx + movq %rdx, 176(%rdi) + adcq %rcx, %rcx + movq 192(%rsi), %rdx + movq %rcx, 184(%rdi) + adcq %rdx, %rdx + movq 200(%rsi), %rcx + movq %rdx, 192(%rdi) + adcq %rcx, %rcx + movq 208(%rsi), %rdx + movq %rcx, 200(%rdi) + adcq %rdx, %rdx + movq 216(%rsi), %rcx + movq %rdx, 208(%rdi) + adcq %rcx, %rcx + movq 224(%rsi), %rdx + movq %rcx, 216(%rdi) + adcq %rdx, %rdx + movq 232(%rsi), %rcx + movq %rdx, 224(%rdi) + adcq %rcx, %rcx + movq 240(%rsi), %rdx + movq %rcx, 232(%rdi) + adcq %rdx, %rdx + movq 248(%rsi), %rcx + movq %rdx, 240(%rdi) + adcq %rcx, %rcx + movq %rcx, 248(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_dbl_32,.-sp_2048_dbl_32 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_4096_sqr_64 +.type sp_4096_sqr_64,@function +.align 16 +sp_4096_sqr_64: +#else +.globl _sp_4096_sqr_64 +.p2align 4 +_sp_4096_sqr_64: +#endif /* __APPLE__ */ + subq $1304, %rsp + movq %rdi, 1280(%rsp) + movq %rsi, 1288(%rsp) + leaq 1024(%rsp), %r8 + leaq 256(%rsi), %r9 + # Add + movq (%rsi), %rdx + xorq %rcx, %rcx + addq (%r9), %rdx + movq 8(%rsi), %rax + movq %rdx, (%r8) + adcq 8(%r9), %rax + movq 16(%rsi), %rdx + movq %rax, 8(%r8) + adcq 16(%r9), %rdx + movq 24(%rsi), %rax + movq %rdx, 16(%r8) + adcq 24(%r9), %rax + movq 32(%rsi), %rdx + movq %rax, 24(%r8) + adcq 32(%r9), %rdx + movq 40(%rsi), %rax + movq %rdx, 32(%r8) + adcq 40(%r9), %rax + movq 48(%rsi), %rdx + movq %rax, 40(%r8) + adcq 48(%r9), %rdx + movq 56(%rsi), %rax + movq %rdx, 48(%r8) + adcq 56(%r9), %rax + movq 64(%rsi), %rdx + movq %rax, 56(%r8) + adcq 64(%r9), %rdx + movq 72(%rsi), %rax + movq %rdx, 64(%r8) + adcq 72(%r9), %rax + movq 80(%rsi), %rdx + movq %rax, 72(%r8) + adcq 80(%r9), %rdx + movq 88(%rsi), %rax + movq %rdx, 80(%r8) + adcq 88(%r9), %rax + movq 96(%rsi), %rdx + movq %rax, 88(%r8) + adcq 96(%r9), %rdx + movq 104(%rsi), %rax + movq %rdx, 96(%r8) + adcq 104(%r9), %rax + movq 112(%rsi), %rdx + movq %rax, 104(%r8) + adcq 112(%r9), %rdx + movq 120(%rsi), %rax + movq %rdx, 112(%r8) + adcq 120(%r9), %rax + movq 128(%rsi), %rdx + movq %rax, 120(%r8) + adcq 128(%r9), %rdx + movq 136(%rsi), %rax + movq %rdx, 128(%r8) + adcq 136(%r9), %rax + movq 144(%rsi), %rdx + movq %rax, 136(%r8) + adcq 144(%r9), %rdx + movq 152(%rsi), %rax + movq %rdx, 144(%r8) + adcq 152(%r9), %rax + movq 160(%rsi), %rdx + movq %rax, 152(%r8) + adcq 160(%r9), %rdx + movq 168(%rsi), %rax + movq %rdx, 160(%r8) + adcq 168(%r9), %rax + movq 176(%rsi), %rdx + movq %rax, 168(%r8) + adcq 176(%r9), %rdx + movq 184(%rsi), %rax + movq %rdx, 176(%r8) + adcq 184(%r9), %rax + movq 192(%rsi), %rdx + movq %rax, 184(%r8) + adcq 192(%r9), %rdx + movq 200(%rsi), %rax + movq %rdx, 192(%r8) + adcq 200(%r9), %rax + movq 208(%rsi), %rdx + movq %rax, 200(%r8) + adcq 208(%r9), %rdx + movq 216(%rsi), %rax + movq %rdx, 208(%r8) + adcq 216(%r9), %rax + movq 224(%rsi), %rdx + movq %rax, 216(%r8) + adcq 224(%r9), %rdx + movq 232(%rsi), %rax + movq %rdx, 224(%r8) + adcq 232(%r9), %rax + movq 240(%rsi), %rdx + movq %rax, 232(%r8) + adcq 240(%r9), %rdx + movq 248(%rsi), %rax + movq %rdx, 240(%r8) + adcq 248(%r9), %rax + movq %rax, 248(%r8) + adcq $0, %rcx + movq %rcx, 1296(%rsp) + movq %r8, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_2048_sqr_32@plt +#else + callq _sp_2048_sqr_32 +#endif /* __APPLE__ */ + movq 1288(%rsp), %rsi + leaq 512(%rsp), %rdi + addq $256, %rsi +#ifndef __APPLE__ + callq sp_2048_sqr_32@plt +#else + callq _sp_2048_sqr_32 +#endif /* __APPLE__ */ + movq 1288(%rsp), %rsi + movq 1280(%rsp), %rdi +#ifndef __APPLE__ + callq sp_2048_sqr_32@plt +#else + callq _sp_2048_sqr_32 +#endif /* __APPLE__ */ + movq 1296(%rsp), %r10 + leaq 1024(%rsp), %r8 + movq %r10, %rcx + negq %r10 + movq (%r8), %rdx + movq 8(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 512(%rdi) + movq %rax, 520(%rdi) + movq 16(%r8), %rdx + movq 24(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 528(%rdi) + movq %rax, 536(%rdi) + movq 32(%r8), %rdx + movq 40(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 544(%rdi) + movq %rax, 552(%rdi) + movq 48(%r8), %rdx + movq 56(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 560(%rdi) + movq %rax, 568(%rdi) + movq 64(%r8), %rdx + movq 72(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 576(%rdi) + movq %rax, 584(%rdi) + movq 80(%r8), %rdx + movq 88(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 592(%rdi) + movq %rax, 600(%rdi) + movq 96(%r8), %rdx + movq 104(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 608(%rdi) + movq %rax, 616(%rdi) + movq 112(%r8), %rdx + movq 120(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 624(%rdi) + movq %rax, 632(%rdi) + movq 128(%r8), %rdx + movq 136(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 640(%rdi) + movq %rax, 648(%rdi) + movq 144(%r8), %rdx + movq 152(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 656(%rdi) + movq %rax, 664(%rdi) + movq 160(%r8), %rdx + movq 168(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 672(%rdi) + movq %rax, 680(%rdi) + movq 176(%r8), %rdx + movq 184(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 688(%rdi) + movq %rax, 696(%rdi) + movq 192(%r8), %rdx + movq 200(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 704(%rdi) + movq %rax, 712(%rdi) + movq 208(%r8), %rdx + movq 216(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 720(%rdi) + movq %rax, 728(%rdi) + movq 224(%r8), %rdx + movq 232(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 736(%rdi) + movq %rax, 744(%rdi) + movq 240(%r8), %rdx + movq 248(%r8), %rax + andq %r10, %rdx + andq %r10, %rax + movq %rdx, 752(%rdi) + movq %rax, 760(%rdi) + movq 512(%rdi), %rdx + addq %rdx, %rdx + movq 520(%rdi), %rax + movq %rdx, 512(%rdi) + adcq %rax, %rax + movq 528(%rdi), %rdx + movq %rax, 520(%rdi) + adcq %rdx, %rdx + movq 536(%rdi), %rax + movq %rdx, 528(%rdi) + adcq %rax, %rax + movq 544(%rdi), %rdx + movq %rax, 536(%rdi) + adcq %rdx, %rdx + movq 552(%rdi), %rax + movq %rdx, 544(%rdi) + adcq %rax, %rax + movq 560(%rdi), %rdx + movq %rax, 552(%rdi) + adcq %rdx, %rdx + movq 568(%rdi), %rax + movq %rdx, 560(%rdi) + adcq %rax, %rax + movq 576(%rdi), %rdx + movq %rax, 568(%rdi) + adcq %rdx, %rdx + movq 584(%rdi), %rax + movq %rdx, 576(%rdi) + adcq %rax, %rax + movq 592(%rdi), %rdx + movq %rax, 584(%rdi) + adcq %rdx, %rdx + movq 600(%rdi), %rax + movq %rdx, 592(%rdi) + adcq %rax, %rax + movq 608(%rdi), %rdx + movq %rax, 600(%rdi) + adcq %rdx, %rdx + movq 616(%rdi), %rax + movq %rdx, 608(%rdi) + adcq %rax, %rax + movq 624(%rdi), %rdx + movq %rax, 616(%rdi) + adcq %rdx, %rdx + movq 632(%rdi), %rax + movq %rdx, 624(%rdi) + adcq %rax, %rax + movq 640(%rdi), %rdx + movq %rax, 632(%rdi) + adcq %rdx, %rdx + movq 648(%rdi), %rax + movq %rdx, 640(%rdi) + adcq %rax, %rax + movq 656(%rdi), %rdx + movq %rax, 648(%rdi) + adcq %rdx, %rdx + movq 664(%rdi), %rax + movq %rdx, 656(%rdi) + adcq %rax, %rax + movq 672(%rdi), %rdx + movq %rax, 664(%rdi) + adcq %rdx, %rdx + movq 680(%rdi), %rax + movq %rdx, 672(%rdi) + adcq %rax, %rax + movq 688(%rdi), %rdx + movq %rax, 680(%rdi) + adcq %rdx, %rdx + movq 696(%rdi), %rax + movq %rdx, 688(%rdi) + adcq %rax, %rax + movq 704(%rdi), %rdx + movq %rax, 696(%rdi) + adcq %rdx, %rdx + movq 712(%rdi), %rax + movq %rdx, 704(%rdi) + adcq %rax, %rax + movq 720(%rdi), %rdx + movq %rax, 712(%rdi) + adcq %rdx, %rdx + movq 728(%rdi), %rax + movq %rdx, 720(%rdi) + adcq %rax, %rax + movq 736(%rdi), %rdx + movq %rax, 728(%rdi) + adcq %rdx, %rdx + movq 744(%rdi), %rax + movq %rdx, 736(%rdi) + adcq %rax, %rax + movq 752(%rdi), %rdx + movq %rax, 744(%rdi) + adcq %rdx, %rdx + movq 760(%rdi), %rax + movq %rdx, 752(%rdi) + adcq %rax, %rax + movq %rax, 760(%rdi) + adcq $0, %rcx + leaq 512(%rsp), %rsi + movq %rsp, %r8 + movq (%r8), %rdx + subq (%rsi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rsi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rsi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rsi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rsi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rsi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rsi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rsi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rsi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rsi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rsi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rsi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rsi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rsi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rsi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rsi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rsi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rsi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rsi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rsi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rsi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rsi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rsi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rsi), %rax + movq 192(%r8), %rdx + movq %rax, 184(%r8) + sbbq 192(%rsi), %rdx + movq 200(%r8), %rax + movq %rdx, 192(%r8) + sbbq 200(%rsi), %rax + movq 208(%r8), %rdx + movq %rax, 200(%r8) + sbbq 208(%rsi), %rdx + movq 216(%r8), %rax + movq %rdx, 208(%r8) + sbbq 216(%rsi), %rax + movq 224(%r8), %rdx + movq %rax, 216(%r8) + sbbq 224(%rsi), %rdx + movq 232(%r8), %rax + movq %rdx, 224(%r8) + sbbq 232(%rsi), %rax + movq 240(%r8), %rdx + movq %rax, 232(%r8) + sbbq 240(%rsi), %rdx + movq 248(%r8), %rax + movq %rdx, 240(%r8) + sbbq 248(%rsi), %rax + movq 256(%r8), %rdx + movq %rax, 248(%r8) + sbbq 256(%rsi), %rdx + movq 264(%r8), %rax + movq %rdx, 256(%r8) + sbbq 264(%rsi), %rax + movq 272(%r8), %rdx + movq %rax, 264(%r8) + sbbq 272(%rsi), %rdx + movq 280(%r8), %rax + movq %rdx, 272(%r8) + sbbq 280(%rsi), %rax + movq 288(%r8), %rdx + movq %rax, 280(%r8) + sbbq 288(%rsi), %rdx + movq 296(%r8), %rax + movq %rdx, 288(%r8) + sbbq 296(%rsi), %rax + movq 304(%r8), %rdx + movq %rax, 296(%r8) + sbbq 304(%rsi), %rdx + movq 312(%r8), %rax + movq %rdx, 304(%r8) + sbbq 312(%rsi), %rax + movq 320(%r8), %rdx + movq %rax, 312(%r8) + sbbq 320(%rsi), %rdx + movq 328(%r8), %rax + movq %rdx, 320(%r8) + sbbq 328(%rsi), %rax + movq 336(%r8), %rdx + movq %rax, 328(%r8) + sbbq 336(%rsi), %rdx + movq 344(%r8), %rax + movq %rdx, 336(%r8) + sbbq 344(%rsi), %rax + movq 352(%r8), %rdx + movq %rax, 344(%r8) + sbbq 352(%rsi), %rdx + movq 360(%r8), %rax + movq %rdx, 352(%r8) + sbbq 360(%rsi), %rax + movq 368(%r8), %rdx + movq %rax, 360(%r8) + sbbq 368(%rsi), %rdx + movq 376(%r8), %rax + movq %rdx, 368(%r8) + sbbq 376(%rsi), %rax + movq 384(%r8), %rdx + movq %rax, 376(%r8) + sbbq 384(%rsi), %rdx + movq 392(%r8), %rax + movq %rdx, 384(%r8) + sbbq 392(%rsi), %rax + movq 400(%r8), %rdx + movq %rax, 392(%r8) + sbbq 400(%rsi), %rdx + movq 408(%r8), %rax + movq %rdx, 400(%r8) + sbbq 408(%rsi), %rax + movq 416(%r8), %rdx + movq %rax, 408(%r8) + sbbq 416(%rsi), %rdx + movq 424(%r8), %rax + movq %rdx, 416(%r8) + sbbq 424(%rsi), %rax + movq 432(%r8), %rdx + movq %rax, 424(%r8) + sbbq 432(%rsi), %rdx + movq 440(%r8), %rax + movq %rdx, 432(%r8) + sbbq 440(%rsi), %rax + movq 448(%r8), %rdx + movq %rax, 440(%r8) + sbbq 448(%rsi), %rdx + movq 456(%r8), %rax + movq %rdx, 448(%r8) + sbbq 456(%rsi), %rax + movq 464(%r8), %rdx + movq %rax, 456(%r8) + sbbq 464(%rsi), %rdx + movq 472(%r8), %rax + movq %rdx, 464(%r8) + sbbq 472(%rsi), %rax + movq 480(%r8), %rdx + movq %rax, 472(%r8) + sbbq 480(%rsi), %rdx + movq 488(%r8), %rax + movq %rdx, 480(%r8) + sbbq 488(%rsi), %rax + movq 496(%r8), %rdx + movq %rax, 488(%r8) + sbbq 496(%rsi), %rdx + movq 504(%r8), %rax + movq %rdx, 496(%r8) + sbbq 504(%rsi), %rax + movq %rax, 504(%r8) + sbbq $0, %rcx + movq (%r8), %rdx + subq (%rdi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rdi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rdi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rdi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rdi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rdi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rdi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rdi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rdi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rdi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rdi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rdi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rdi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rdi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rdi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rdi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rdi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rdi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rdi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rdi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rdi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rdi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rdi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rdi), %rax + movq 192(%r8), %rdx + movq %rax, 184(%r8) + sbbq 192(%rdi), %rdx + movq 200(%r8), %rax + movq %rdx, 192(%r8) + sbbq 200(%rdi), %rax + movq 208(%r8), %rdx + movq %rax, 200(%r8) + sbbq 208(%rdi), %rdx + movq 216(%r8), %rax + movq %rdx, 208(%r8) + sbbq 216(%rdi), %rax + movq 224(%r8), %rdx + movq %rax, 216(%r8) + sbbq 224(%rdi), %rdx + movq 232(%r8), %rax + movq %rdx, 224(%r8) + sbbq 232(%rdi), %rax + movq 240(%r8), %rdx + movq %rax, 232(%r8) + sbbq 240(%rdi), %rdx + movq 248(%r8), %rax + movq %rdx, 240(%r8) + sbbq 248(%rdi), %rax + movq 256(%r8), %rdx + movq %rax, 248(%r8) + sbbq 256(%rdi), %rdx + movq 264(%r8), %rax + movq %rdx, 256(%r8) + sbbq 264(%rdi), %rax + movq 272(%r8), %rdx + movq %rax, 264(%r8) + sbbq 272(%rdi), %rdx + movq 280(%r8), %rax + movq %rdx, 272(%r8) + sbbq 280(%rdi), %rax + movq 288(%r8), %rdx + movq %rax, 280(%r8) + sbbq 288(%rdi), %rdx + movq 296(%r8), %rax + movq %rdx, 288(%r8) + sbbq 296(%rdi), %rax + movq 304(%r8), %rdx + movq %rax, 296(%r8) + sbbq 304(%rdi), %rdx + movq 312(%r8), %rax + movq %rdx, 304(%r8) + sbbq 312(%rdi), %rax + movq 320(%r8), %rdx + movq %rax, 312(%r8) + sbbq 320(%rdi), %rdx + movq 328(%r8), %rax + movq %rdx, 320(%r8) + sbbq 328(%rdi), %rax + movq 336(%r8), %rdx + movq %rax, 328(%r8) + sbbq 336(%rdi), %rdx + movq 344(%r8), %rax + movq %rdx, 336(%r8) + sbbq 344(%rdi), %rax + movq 352(%r8), %rdx + movq %rax, 344(%r8) + sbbq 352(%rdi), %rdx + movq 360(%r8), %rax + movq %rdx, 352(%r8) + sbbq 360(%rdi), %rax + movq 368(%r8), %rdx + movq %rax, 360(%r8) + sbbq 368(%rdi), %rdx + movq 376(%r8), %rax + movq %rdx, 368(%r8) + sbbq 376(%rdi), %rax + movq 384(%r8), %rdx + movq %rax, 376(%r8) + sbbq 384(%rdi), %rdx + movq 392(%r8), %rax + movq %rdx, 384(%r8) + sbbq 392(%rdi), %rax + movq 400(%r8), %rdx + movq %rax, 392(%r8) + sbbq 400(%rdi), %rdx + movq 408(%r8), %rax + movq %rdx, 400(%r8) + sbbq 408(%rdi), %rax + movq 416(%r8), %rdx + movq %rax, 408(%r8) + sbbq 416(%rdi), %rdx + movq 424(%r8), %rax + movq %rdx, 416(%r8) + sbbq 424(%rdi), %rax + movq 432(%r8), %rdx + movq %rax, 424(%r8) + sbbq 432(%rdi), %rdx + movq 440(%r8), %rax + movq %rdx, 432(%r8) + sbbq 440(%rdi), %rax + movq 448(%r8), %rdx + movq %rax, 440(%r8) + sbbq 448(%rdi), %rdx + movq 456(%r8), %rax + movq %rdx, 448(%r8) + sbbq 456(%rdi), %rax + movq 464(%r8), %rdx + movq %rax, 456(%r8) + sbbq 464(%rdi), %rdx + movq 472(%r8), %rax + movq %rdx, 464(%r8) + sbbq 472(%rdi), %rax + movq 480(%r8), %rdx + movq %rax, 472(%r8) + sbbq 480(%rdi), %rdx + movq 488(%r8), %rax + movq %rdx, 480(%r8) + sbbq 488(%rdi), %rax + movq 496(%r8), %rdx + movq %rax, 488(%r8) + sbbq 496(%rdi), %rdx + movq 504(%r8), %rax + movq %rdx, 496(%r8) + sbbq 504(%rdi), %rax + movq %rax, 504(%r8) + sbbq $0, %rcx + # Add in place + movq 256(%rdi), %rdx + addq (%r8), %rdx + movq 264(%rdi), %rax + movq %rdx, 256(%rdi) + adcq 8(%r8), %rax + movq 272(%rdi), %rdx + movq %rax, 264(%rdi) + adcq 16(%r8), %rdx + movq 280(%rdi), %rax + movq %rdx, 272(%rdi) + adcq 24(%r8), %rax + movq 288(%rdi), %rdx + movq %rax, 280(%rdi) + adcq 32(%r8), %rdx + movq 296(%rdi), %rax + movq %rdx, 288(%rdi) + adcq 40(%r8), %rax + movq 304(%rdi), %rdx + movq %rax, 296(%rdi) + adcq 48(%r8), %rdx + movq 312(%rdi), %rax + movq %rdx, 304(%rdi) + adcq 56(%r8), %rax + movq 320(%rdi), %rdx + movq %rax, 312(%rdi) + adcq 64(%r8), %rdx + movq 328(%rdi), %rax + movq %rdx, 320(%rdi) + adcq 72(%r8), %rax + movq 336(%rdi), %rdx + movq %rax, 328(%rdi) + adcq 80(%r8), %rdx + movq 344(%rdi), %rax + movq %rdx, 336(%rdi) + adcq 88(%r8), %rax + movq 352(%rdi), %rdx + movq %rax, 344(%rdi) + adcq 96(%r8), %rdx + movq 360(%rdi), %rax + movq %rdx, 352(%rdi) + adcq 104(%r8), %rax + movq 368(%rdi), %rdx + movq %rax, 360(%rdi) + adcq 112(%r8), %rdx + movq 376(%rdi), %rax + movq %rdx, 368(%rdi) + adcq 120(%r8), %rax + movq 384(%rdi), %rdx + movq %rax, 376(%rdi) + adcq 128(%r8), %rdx + movq 392(%rdi), %rax + movq %rdx, 384(%rdi) + adcq 136(%r8), %rax + movq 400(%rdi), %rdx + movq %rax, 392(%rdi) + adcq 144(%r8), %rdx + movq 408(%rdi), %rax + movq %rdx, 400(%rdi) + adcq 152(%r8), %rax + movq 416(%rdi), %rdx + movq %rax, 408(%rdi) + adcq 160(%r8), %rdx + movq 424(%rdi), %rax + movq %rdx, 416(%rdi) + adcq 168(%r8), %rax + movq 432(%rdi), %rdx + movq %rax, 424(%rdi) + adcq 176(%r8), %rdx + movq 440(%rdi), %rax + movq %rdx, 432(%rdi) + adcq 184(%r8), %rax + movq 448(%rdi), %rdx + movq %rax, 440(%rdi) + adcq 192(%r8), %rdx + movq 456(%rdi), %rax + movq %rdx, 448(%rdi) + adcq 200(%r8), %rax + movq 464(%rdi), %rdx + movq %rax, 456(%rdi) + adcq 208(%r8), %rdx + movq 472(%rdi), %rax + movq %rdx, 464(%rdi) + adcq 216(%r8), %rax + movq 480(%rdi), %rdx + movq %rax, 472(%rdi) + adcq 224(%r8), %rdx + movq 488(%rdi), %rax + movq %rdx, 480(%rdi) + adcq 232(%r8), %rax + movq 496(%rdi), %rdx + movq %rax, 488(%rdi) + adcq 240(%r8), %rdx + movq 504(%rdi), %rax + movq %rdx, 496(%rdi) + adcq 248(%r8), %rax + movq 512(%rdi), %rdx + movq %rax, 504(%rdi) + adcq 256(%r8), %rdx + movq 520(%rdi), %rax + movq %rdx, 512(%rdi) + adcq 264(%r8), %rax + movq 528(%rdi), %rdx + movq %rax, 520(%rdi) + adcq 272(%r8), %rdx + movq 536(%rdi), %rax + movq %rdx, 528(%rdi) + adcq 280(%r8), %rax + movq 544(%rdi), %rdx + movq %rax, 536(%rdi) + adcq 288(%r8), %rdx + movq 552(%rdi), %rax + movq %rdx, 544(%rdi) + adcq 296(%r8), %rax + movq 560(%rdi), %rdx + movq %rax, 552(%rdi) + adcq 304(%r8), %rdx + movq 568(%rdi), %rax + movq %rdx, 560(%rdi) + adcq 312(%r8), %rax + movq 576(%rdi), %rdx + movq %rax, 568(%rdi) + adcq 320(%r8), %rdx + movq 584(%rdi), %rax + movq %rdx, 576(%rdi) + adcq 328(%r8), %rax + movq 592(%rdi), %rdx + movq %rax, 584(%rdi) + adcq 336(%r8), %rdx + movq 600(%rdi), %rax + movq %rdx, 592(%rdi) + adcq 344(%r8), %rax + movq 608(%rdi), %rdx + movq %rax, 600(%rdi) + adcq 352(%r8), %rdx + movq 616(%rdi), %rax + movq %rdx, 608(%rdi) + adcq 360(%r8), %rax + movq 624(%rdi), %rdx + movq %rax, 616(%rdi) + adcq 368(%r8), %rdx + movq 632(%rdi), %rax + movq %rdx, 624(%rdi) + adcq 376(%r8), %rax + movq 640(%rdi), %rdx + movq %rax, 632(%rdi) + adcq 384(%r8), %rdx + movq 648(%rdi), %rax + movq %rdx, 640(%rdi) + adcq 392(%r8), %rax + movq 656(%rdi), %rdx + movq %rax, 648(%rdi) + adcq 400(%r8), %rdx + movq 664(%rdi), %rax + movq %rdx, 656(%rdi) + adcq 408(%r8), %rax + movq 672(%rdi), %rdx + movq %rax, 664(%rdi) + adcq 416(%r8), %rdx + movq 680(%rdi), %rax + movq %rdx, 672(%rdi) + adcq 424(%r8), %rax + movq 688(%rdi), %rdx + movq %rax, 680(%rdi) + adcq 432(%r8), %rdx + movq 696(%rdi), %rax + movq %rdx, 688(%rdi) + adcq 440(%r8), %rax + movq 704(%rdi), %rdx + movq %rax, 696(%rdi) + adcq 448(%r8), %rdx + movq 712(%rdi), %rax + movq %rdx, 704(%rdi) + adcq 456(%r8), %rax + movq 720(%rdi), %rdx + movq %rax, 712(%rdi) + adcq 464(%r8), %rdx + movq 728(%rdi), %rax + movq %rdx, 720(%rdi) + adcq 472(%r8), %rax + movq 736(%rdi), %rdx + movq %rax, 728(%rdi) + adcq 480(%r8), %rdx + movq 744(%rdi), %rax + movq %rdx, 736(%rdi) + adcq 488(%r8), %rax + movq 752(%rdi), %rdx + movq %rax, 744(%rdi) + adcq 496(%r8), %rdx + movq 760(%rdi), %rax + movq %rdx, 752(%rdi) + adcq 504(%r8), %rax + movq %rax, 760(%rdi) + adcq $0, %rcx + movq %rcx, 768(%rdi) + # Add in place + movq 512(%rdi), %rdx + xorq %rcx, %rcx + addq (%rsi), %rdx + movq 520(%rdi), %rax + movq %rdx, 512(%rdi) + adcq 8(%rsi), %rax + movq 528(%rdi), %rdx + movq %rax, 520(%rdi) + adcq 16(%rsi), %rdx + movq 536(%rdi), %rax + movq %rdx, 528(%rdi) + adcq 24(%rsi), %rax + movq 544(%rdi), %rdx + movq %rax, 536(%rdi) + adcq 32(%rsi), %rdx + movq 552(%rdi), %rax + movq %rdx, 544(%rdi) + adcq 40(%rsi), %rax + movq 560(%rdi), %rdx + movq %rax, 552(%rdi) + adcq 48(%rsi), %rdx + movq 568(%rdi), %rax + movq %rdx, 560(%rdi) + adcq 56(%rsi), %rax + movq 576(%rdi), %rdx + movq %rax, 568(%rdi) + adcq 64(%rsi), %rdx + movq 584(%rdi), %rax + movq %rdx, 576(%rdi) + adcq 72(%rsi), %rax + movq 592(%rdi), %rdx + movq %rax, 584(%rdi) + adcq 80(%rsi), %rdx + movq 600(%rdi), %rax + movq %rdx, 592(%rdi) + adcq 88(%rsi), %rax + movq 608(%rdi), %rdx + movq %rax, 600(%rdi) + adcq 96(%rsi), %rdx + movq 616(%rdi), %rax + movq %rdx, 608(%rdi) + adcq 104(%rsi), %rax + movq 624(%rdi), %rdx + movq %rax, 616(%rdi) + adcq 112(%rsi), %rdx + movq 632(%rdi), %rax + movq %rdx, 624(%rdi) + adcq 120(%rsi), %rax + movq 640(%rdi), %rdx + movq %rax, 632(%rdi) + adcq 128(%rsi), %rdx + movq 648(%rdi), %rax + movq %rdx, 640(%rdi) + adcq 136(%rsi), %rax + movq 656(%rdi), %rdx + movq %rax, 648(%rdi) + adcq 144(%rsi), %rdx + movq 664(%rdi), %rax + movq %rdx, 656(%rdi) + adcq 152(%rsi), %rax + movq 672(%rdi), %rdx + movq %rax, 664(%rdi) + adcq 160(%rsi), %rdx + movq 680(%rdi), %rax + movq %rdx, 672(%rdi) + adcq 168(%rsi), %rax + movq 688(%rdi), %rdx + movq %rax, 680(%rdi) + adcq 176(%rsi), %rdx + movq 696(%rdi), %rax + movq %rdx, 688(%rdi) + adcq 184(%rsi), %rax + movq 704(%rdi), %rdx + movq %rax, 696(%rdi) + adcq 192(%rsi), %rdx + movq 712(%rdi), %rax + movq %rdx, 704(%rdi) + adcq 200(%rsi), %rax + movq 720(%rdi), %rdx + movq %rax, 712(%rdi) + adcq 208(%rsi), %rdx + movq 728(%rdi), %rax + movq %rdx, 720(%rdi) + adcq 216(%rsi), %rax + movq 736(%rdi), %rdx + movq %rax, 728(%rdi) + adcq 224(%rsi), %rdx + movq 744(%rdi), %rax + movq %rdx, 736(%rdi) + adcq 232(%rsi), %rax + movq 752(%rdi), %rdx + movq %rax, 744(%rdi) + adcq 240(%rsi), %rdx + movq 760(%rdi), %rax + movq %rdx, 752(%rdi) + adcq 248(%rsi), %rax + movq 768(%rdi), %rdx + movq %rax, 760(%rdi) + adcq 256(%rsi), %rdx + movq %rdx, 768(%rdi) + adcq $0, %rcx + # Add to zero + movq 264(%rsi), %rdx + adcq $0, %rdx + movq 272(%rsi), %rax + movq %rdx, 776(%rdi) + adcq $0, %rax + movq 280(%rsi), %rdx + movq %rax, 784(%rdi) + adcq $0, %rdx + movq 288(%rsi), %rax + movq %rdx, 792(%rdi) + adcq $0, %rax + movq 296(%rsi), %rdx + movq %rax, 800(%rdi) + adcq $0, %rdx + movq 304(%rsi), %rax + movq %rdx, 808(%rdi) + adcq $0, %rax + movq 312(%rsi), %rdx + movq %rax, 816(%rdi) + adcq $0, %rdx + movq 320(%rsi), %rax + movq %rdx, 824(%rdi) + adcq $0, %rax + movq 328(%rsi), %rdx + movq %rax, 832(%rdi) + adcq $0, %rdx + movq 336(%rsi), %rax + movq %rdx, 840(%rdi) + adcq $0, %rax + movq 344(%rsi), %rdx + movq %rax, 848(%rdi) + adcq $0, %rdx + movq 352(%rsi), %rax + movq %rdx, 856(%rdi) + adcq $0, %rax + movq 360(%rsi), %rdx + movq %rax, 864(%rdi) + adcq $0, %rdx + movq 368(%rsi), %rax + movq %rdx, 872(%rdi) + adcq $0, %rax + movq 376(%rsi), %rdx + movq %rax, 880(%rdi) + adcq $0, %rdx + movq 384(%rsi), %rax + movq %rdx, 888(%rdi) + adcq $0, %rax + movq 392(%rsi), %rdx + movq %rax, 896(%rdi) + adcq $0, %rdx + movq 400(%rsi), %rax + movq %rdx, 904(%rdi) + adcq $0, %rax + movq 408(%rsi), %rdx + movq %rax, 912(%rdi) + adcq $0, %rdx + movq 416(%rsi), %rax + movq %rdx, 920(%rdi) + adcq $0, %rax + movq 424(%rsi), %rdx + movq %rax, 928(%rdi) + adcq $0, %rdx + movq 432(%rsi), %rax + movq %rdx, 936(%rdi) + adcq $0, %rax + movq 440(%rsi), %rdx + movq %rax, 944(%rdi) + adcq $0, %rdx + movq 448(%rsi), %rax + movq %rdx, 952(%rdi) + adcq $0, %rax + movq 456(%rsi), %rdx + movq %rax, 960(%rdi) + adcq $0, %rdx + movq 464(%rsi), %rax + movq %rdx, 968(%rdi) + adcq $0, %rax + movq 472(%rsi), %rdx + movq %rax, 976(%rdi) + adcq $0, %rdx + movq 480(%rsi), %rax + movq %rdx, 984(%rdi) + adcq $0, %rax + movq 488(%rsi), %rdx + movq %rax, 992(%rdi) + adcq $0, %rdx + movq 496(%rsi), %rax + movq %rdx, 1000(%rdi) + adcq $0, %rax + movq 504(%rsi), %rdx + movq %rax, 1008(%rdi) + adcq $0, %rdx + movq %rdx, 1016(%rdi) + addq $1304, %rsp + repz retq +#ifndef __APPLE__ +.size sp_4096_sqr_64,.-sp_4096_sqr_64 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_4096_mul_avx2_64 +.type sp_4096_mul_avx2_64,@function +.align 16 +sp_4096_mul_avx2_64: +#else +.globl _sp_4096_mul_avx2_64 +.p2align 4 +_sp_4096_mul_avx2_64: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + subq $1576, %rsp + movq %rdi, 1536(%rsp) + movq %rsi, 1544(%rsp) + movq %rdx, 1552(%rsp) + leaq 1024(%rsp), %r10 + leaq 256(%rsi), %r12 + # Add + movq (%rsi), %rax + xorq %r13, %r13 + addq (%r12), %rax + movq 8(%rsi), %rcx + movq %rax, (%r10) + adcq 8(%r12), %rcx + movq 16(%rsi), %r8 + movq %rcx, 8(%r10) + adcq 16(%r12), %r8 + movq 24(%rsi), %rax + movq %r8, 16(%r10) + adcq 24(%r12), %rax + movq 32(%rsi), %rcx + movq %rax, 24(%r10) + adcq 32(%r12), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%r10) + adcq 40(%r12), %r8 + movq 48(%rsi), %rax + movq %r8, 40(%r10) + adcq 48(%r12), %rax + movq 56(%rsi), %rcx + movq %rax, 48(%r10) + adcq 56(%r12), %rcx + movq 64(%rsi), %r8 + movq %rcx, 56(%r10) + adcq 64(%r12), %r8 + movq 72(%rsi), %rax + movq %r8, 64(%r10) + adcq 72(%r12), %rax + movq 80(%rsi), %rcx + movq %rax, 72(%r10) + adcq 80(%r12), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%r10) + adcq 88(%r12), %r8 + movq 96(%rsi), %rax + movq %r8, 88(%r10) + adcq 96(%r12), %rax + movq 104(%rsi), %rcx + movq %rax, 96(%r10) + adcq 104(%r12), %rcx + movq 112(%rsi), %r8 + movq %rcx, 104(%r10) + adcq 112(%r12), %r8 + movq 120(%rsi), %rax + movq %r8, 112(%r10) + adcq 120(%r12), %rax + movq 128(%rsi), %rcx + movq %rax, 120(%r10) + adcq 128(%r12), %rcx + movq 136(%rsi), %r8 + movq %rcx, 128(%r10) + adcq 136(%r12), %r8 + movq 144(%rsi), %rax + movq %r8, 136(%r10) + adcq 144(%r12), %rax + movq 152(%rsi), %rcx + movq %rax, 144(%r10) + adcq 152(%r12), %rcx + movq 160(%rsi), %r8 + movq %rcx, 152(%r10) + adcq 160(%r12), %r8 + movq 168(%rsi), %rax + movq %r8, 160(%r10) + adcq 168(%r12), %rax + movq 176(%rsi), %rcx + movq %rax, 168(%r10) + adcq 176(%r12), %rcx + movq 184(%rsi), %r8 + movq %rcx, 176(%r10) + adcq 184(%r12), %r8 + movq 192(%rsi), %rax + movq %r8, 184(%r10) + adcq 192(%r12), %rax + movq 200(%rsi), %rcx + movq %rax, 192(%r10) + adcq 200(%r12), %rcx + movq 208(%rsi), %r8 + movq %rcx, 200(%r10) + adcq 208(%r12), %r8 + movq 216(%rsi), %rax + movq %r8, 208(%r10) + adcq 216(%r12), %rax + movq 224(%rsi), %rcx + movq %rax, 216(%r10) + adcq 224(%r12), %rcx + movq 232(%rsi), %r8 + movq %rcx, 224(%r10) + adcq 232(%r12), %r8 + movq 240(%rsi), %rax + movq %r8, 232(%r10) + adcq 240(%r12), %rax + movq 248(%rsi), %rcx + movq %rax, 240(%r10) + adcq 248(%r12), %rcx + movq %rcx, 248(%r10) + adcq $0, %r13 + movq %r13, 1560(%rsp) + leaq 1280(%rsp), %r11 + leaq 256(%rdx), %r12 + # Add + movq (%rdx), %rax + xorq %r14, %r14 + addq (%r12), %rax + movq 8(%rdx), %rcx + movq %rax, (%r11) + adcq 8(%r12), %rcx + movq 16(%rdx), %r8 + movq %rcx, 8(%r11) + adcq 16(%r12), %r8 + movq 24(%rdx), %rax + movq %r8, 16(%r11) + adcq 24(%r12), %rax + movq 32(%rdx), %rcx + movq %rax, 24(%r11) + adcq 32(%r12), %rcx + movq 40(%rdx), %r8 + movq %rcx, 32(%r11) + adcq 40(%r12), %r8 + movq 48(%rdx), %rax + movq %r8, 40(%r11) + adcq 48(%r12), %rax + movq 56(%rdx), %rcx + movq %rax, 48(%r11) + adcq 56(%r12), %rcx + movq 64(%rdx), %r8 + movq %rcx, 56(%r11) + adcq 64(%r12), %r8 + movq 72(%rdx), %rax + movq %r8, 64(%r11) + adcq 72(%r12), %rax + movq 80(%rdx), %rcx + movq %rax, 72(%r11) + adcq 80(%r12), %rcx + movq 88(%rdx), %r8 + movq %rcx, 80(%r11) + adcq 88(%r12), %r8 + movq 96(%rdx), %rax + movq %r8, 88(%r11) + adcq 96(%r12), %rax + movq 104(%rdx), %rcx + movq %rax, 96(%r11) + adcq 104(%r12), %rcx + movq 112(%rdx), %r8 + movq %rcx, 104(%r11) + adcq 112(%r12), %r8 + movq 120(%rdx), %rax + movq %r8, 112(%r11) + adcq 120(%r12), %rax + movq 128(%rdx), %rcx + movq %rax, 120(%r11) + adcq 128(%r12), %rcx + movq 136(%rdx), %r8 + movq %rcx, 128(%r11) + adcq 136(%r12), %r8 + movq 144(%rdx), %rax + movq %r8, 136(%r11) + adcq 144(%r12), %rax + movq 152(%rdx), %rcx + movq %rax, 144(%r11) + adcq 152(%r12), %rcx + movq 160(%rdx), %r8 + movq %rcx, 152(%r11) + adcq 160(%r12), %r8 + movq 168(%rdx), %rax + movq %r8, 160(%r11) + adcq 168(%r12), %rax + movq 176(%rdx), %rcx + movq %rax, 168(%r11) + adcq 176(%r12), %rcx + movq 184(%rdx), %r8 + movq %rcx, 176(%r11) + adcq 184(%r12), %r8 + movq 192(%rdx), %rax + movq %r8, 184(%r11) + adcq 192(%r12), %rax + movq 200(%rdx), %rcx + movq %rax, 192(%r11) + adcq 200(%r12), %rcx + movq 208(%rdx), %r8 + movq %rcx, 200(%r11) + adcq 208(%r12), %r8 + movq 216(%rdx), %rax + movq %r8, 208(%r11) + adcq 216(%r12), %rax + movq 224(%rdx), %rcx + movq %rax, 216(%r11) + adcq 224(%r12), %rcx + movq 232(%rdx), %r8 + movq %rcx, 224(%r11) + adcq 232(%r12), %r8 + movq 240(%rdx), %rax + movq %r8, 232(%r11) + adcq 240(%r12), %rax + movq 248(%rdx), %rcx + movq %rax, 240(%r11) + adcq 248(%r12), %rcx + movq %rcx, 248(%r11) + adcq $0, %r14 + movq %r14, 1568(%rsp) + movq %r11, %rdx + movq %r10, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_2048_mul_avx2_32@plt +#else + callq _sp_2048_mul_avx2_32 +#endif /* __APPLE__ */ + movq 1552(%rsp), %rdx + movq 1544(%rsp), %rsi + leaq 512(%rsp), %rdi + addq $256, %rdx + addq $256, %rsi +#ifndef __APPLE__ + callq sp_2048_mul_avx2_32@plt +#else + callq _sp_2048_mul_avx2_32 +#endif /* __APPLE__ */ + movq 1552(%rsp), %rdx + movq 1544(%rsp), %rsi + movq 1536(%rsp), %rdi +#ifndef __APPLE__ + callq sp_2048_mul_avx2_32@plt +#else + callq _sp_2048_mul_avx2_32 +#endif /* __APPLE__ */ + movq 1560(%rsp), %r13 + movq 1568(%rsp), %r14 + movq 1536(%rsp), %r15 + movq %r13, %r9 + leaq 1024(%rsp), %r10 + leaq 1280(%rsp), %r11 + andq %r14, %r9 + negq %r13 + negq %r14 + addq $512, %r15 + movq (%r10), %rax + movq (%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + addq %rcx, %rax + movq 8(%r10), %rcx + movq 8(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, (%r15) + adcq %r8, %rcx + movq 16(%r10), %r8 + movq 16(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 8(%r15) + adcq %rax, %r8 + movq 24(%r10), %rax + movq 24(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 16(%r15) + adcq %rcx, %rax + movq 32(%r10), %rcx + movq 32(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 24(%r15) + adcq %r8, %rcx + movq 40(%r10), %r8 + movq 40(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 32(%r15) + adcq %rax, %r8 + movq 48(%r10), %rax + movq 48(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 40(%r15) + adcq %rcx, %rax + movq 56(%r10), %rcx + movq 56(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 48(%r15) + adcq %r8, %rcx + movq 64(%r10), %r8 + movq 64(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 56(%r15) + adcq %rax, %r8 + movq 72(%r10), %rax + movq 72(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 64(%r15) + adcq %rcx, %rax + movq 80(%r10), %rcx + movq 80(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 72(%r15) + adcq %r8, %rcx + movq 88(%r10), %r8 + movq 88(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 80(%r15) + adcq %rax, %r8 + movq 96(%r10), %rax + movq 96(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 88(%r15) + adcq %rcx, %rax + movq 104(%r10), %rcx + movq 104(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 96(%r15) + adcq %r8, %rcx + movq 112(%r10), %r8 + movq 112(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 104(%r15) + adcq %rax, %r8 + movq 120(%r10), %rax + movq 120(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 112(%r15) + adcq %rcx, %rax + movq 128(%r10), %rcx + movq 128(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 120(%r15) + adcq %r8, %rcx + movq 136(%r10), %r8 + movq 136(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 128(%r15) + adcq %rax, %r8 + movq 144(%r10), %rax + movq 144(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 136(%r15) + adcq %rcx, %rax + movq 152(%r10), %rcx + movq 152(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 144(%r15) + adcq %r8, %rcx + movq 160(%r10), %r8 + movq 160(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 152(%r15) + adcq %rax, %r8 + movq 168(%r10), %rax + movq 168(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 160(%r15) + adcq %rcx, %rax + movq 176(%r10), %rcx + movq 176(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 168(%r15) + adcq %r8, %rcx + movq 184(%r10), %r8 + movq 184(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 176(%r15) + adcq %rax, %r8 + movq 192(%r10), %rax + movq 192(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 184(%r15) + adcq %rcx, %rax + movq 200(%r10), %rcx + movq 200(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 192(%r15) + adcq %r8, %rcx + movq 208(%r10), %r8 + movq 208(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 200(%r15) + adcq %rax, %r8 + movq 216(%r10), %rax + movq 216(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 208(%r15) + adcq %rcx, %rax + movq 224(%r10), %rcx + movq 224(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 216(%r15) + adcq %r8, %rcx + movq 232(%r10), %r8 + movq 232(%r11), %rax + pextq %r14, %r8, %r8 + pextq %r13, %rax, %rax + movq %rcx, 224(%r15) + adcq %rax, %r8 + movq 240(%r10), %rax + movq 240(%r11), %rcx + pextq %r14, %rax, %rax + pextq %r13, %rcx, %rcx + movq %r8, 232(%r15) + adcq %rcx, %rax + movq 248(%r10), %rcx + movq 248(%r11), %r8 + pextq %r14, %rcx, %rcx + pextq %r13, %r8, %r8 + movq %rax, 240(%r15) + adcq %r8, %rcx + movq %rcx, 248(%r15) + adcq $0, %r9 + leaq 512(%rsp), %r11 + movq %rsp, %r10 + movq (%r10), %rax + subq (%r11), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%r11), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%r11), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%r11), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%r11), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%r11), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%r11), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%r11), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%r11), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%r11), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%r11), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%r11), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%r11), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%r11), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%r11), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%r11), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%r11), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%r11), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%r11), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%r11), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%r11), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%r11), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%r11), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%r11), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r10) + sbbq 192(%r11), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r10) + sbbq 200(%r11), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r10) + sbbq 208(%r11), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r10) + sbbq 216(%r11), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r10) + sbbq 224(%r11), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r10) + sbbq 232(%r11), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r10) + sbbq 240(%r11), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r10) + sbbq 248(%r11), %rcx + movq 256(%r10), %r8 + movq %rcx, 248(%r10) + sbbq 256(%r11), %r8 + movq 264(%r10), %rax + movq %r8, 256(%r10) + sbbq 264(%r11), %rax + movq 272(%r10), %rcx + movq %rax, 264(%r10) + sbbq 272(%r11), %rcx + movq 280(%r10), %r8 + movq %rcx, 272(%r10) + sbbq 280(%r11), %r8 + movq 288(%r10), %rax + movq %r8, 280(%r10) + sbbq 288(%r11), %rax + movq 296(%r10), %rcx + movq %rax, 288(%r10) + sbbq 296(%r11), %rcx + movq 304(%r10), %r8 + movq %rcx, 296(%r10) + sbbq 304(%r11), %r8 + movq 312(%r10), %rax + movq %r8, 304(%r10) + sbbq 312(%r11), %rax + movq 320(%r10), %rcx + movq %rax, 312(%r10) + sbbq 320(%r11), %rcx + movq 328(%r10), %r8 + movq %rcx, 320(%r10) + sbbq 328(%r11), %r8 + movq 336(%r10), %rax + movq %r8, 328(%r10) + sbbq 336(%r11), %rax + movq 344(%r10), %rcx + movq %rax, 336(%r10) + sbbq 344(%r11), %rcx + movq 352(%r10), %r8 + movq %rcx, 344(%r10) + sbbq 352(%r11), %r8 + movq 360(%r10), %rax + movq %r8, 352(%r10) + sbbq 360(%r11), %rax + movq 368(%r10), %rcx + movq %rax, 360(%r10) + sbbq 368(%r11), %rcx + movq 376(%r10), %r8 + movq %rcx, 368(%r10) + sbbq 376(%r11), %r8 + movq 384(%r10), %rax + movq %r8, 376(%r10) + sbbq 384(%r11), %rax + movq 392(%r10), %rcx + movq %rax, 384(%r10) + sbbq 392(%r11), %rcx + movq 400(%r10), %r8 + movq %rcx, 392(%r10) + sbbq 400(%r11), %r8 + movq 408(%r10), %rax + movq %r8, 400(%r10) + sbbq 408(%r11), %rax + movq 416(%r10), %rcx + movq %rax, 408(%r10) + sbbq 416(%r11), %rcx + movq 424(%r10), %r8 + movq %rcx, 416(%r10) + sbbq 424(%r11), %r8 + movq 432(%r10), %rax + movq %r8, 424(%r10) + sbbq 432(%r11), %rax + movq 440(%r10), %rcx + movq %rax, 432(%r10) + sbbq 440(%r11), %rcx + movq 448(%r10), %r8 + movq %rcx, 440(%r10) + sbbq 448(%r11), %r8 + movq 456(%r10), %rax + movq %r8, 448(%r10) + sbbq 456(%r11), %rax + movq 464(%r10), %rcx + movq %rax, 456(%r10) + sbbq 464(%r11), %rcx + movq 472(%r10), %r8 + movq %rcx, 464(%r10) + sbbq 472(%r11), %r8 + movq 480(%r10), %rax + movq %r8, 472(%r10) + sbbq 480(%r11), %rax + movq 488(%r10), %rcx + movq %rax, 480(%r10) + sbbq 488(%r11), %rcx + movq 496(%r10), %r8 + movq %rcx, 488(%r10) + sbbq 496(%r11), %r8 + movq 504(%r10), %rax + movq %r8, 496(%r10) + sbbq 504(%r11), %rax + movq %rax, 504(%r10) + sbbq $0, %r9 + movq (%r10), %rax + subq (%rdi), %rax + movq 8(%r10), %rcx + movq %rax, (%r10) + sbbq 8(%rdi), %rcx + movq 16(%r10), %r8 + movq %rcx, 8(%r10) + sbbq 16(%rdi), %r8 + movq 24(%r10), %rax + movq %r8, 16(%r10) + sbbq 24(%rdi), %rax + movq 32(%r10), %rcx + movq %rax, 24(%r10) + sbbq 32(%rdi), %rcx + movq 40(%r10), %r8 + movq %rcx, 32(%r10) + sbbq 40(%rdi), %r8 + movq 48(%r10), %rax + movq %r8, 40(%r10) + sbbq 48(%rdi), %rax + movq 56(%r10), %rcx + movq %rax, 48(%r10) + sbbq 56(%rdi), %rcx + movq 64(%r10), %r8 + movq %rcx, 56(%r10) + sbbq 64(%rdi), %r8 + movq 72(%r10), %rax + movq %r8, 64(%r10) + sbbq 72(%rdi), %rax + movq 80(%r10), %rcx + movq %rax, 72(%r10) + sbbq 80(%rdi), %rcx + movq 88(%r10), %r8 + movq %rcx, 80(%r10) + sbbq 88(%rdi), %r8 + movq 96(%r10), %rax + movq %r8, 88(%r10) + sbbq 96(%rdi), %rax + movq 104(%r10), %rcx + movq %rax, 96(%r10) + sbbq 104(%rdi), %rcx + movq 112(%r10), %r8 + movq %rcx, 104(%r10) + sbbq 112(%rdi), %r8 + movq 120(%r10), %rax + movq %r8, 112(%r10) + sbbq 120(%rdi), %rax + movq 128(%r10), %rcx + movq %rax, 120(%r10) + sbbq 128(%rdi), %rcx + movq 136(%r10), %r8 + movq %rcx, 128(%r10) + sbbq 136(%rdi), %r8 + movq 144(%r10), %rax + movq %r8, 136(%r10) + sbbq 144(%rdi), %rax + movq 152(%r10), %rcx + movq %rax, 144(%r10) + sbbq 152(%rdi), %rcx + movq 160(%r10), %r8 + movq %rcx, 152(%r10) + sbbq 160(%rdi), %r8 + movq 168(%r10), %rax + movq %r8, 160(%r10) + sbbq 168(%rdi), %rax + movq 176(%r10), %rcx + movq %rax, 168(%r10) + sbbq 176(%rdi), %rcx + movq 184(%r10), %r8 + movq %rcx, 176(%r10) + sbbq 184(%rdi), %r8 + movq 192(%r10), %rax + movq %r8, 184(%r10) + sbbq 192(%rdi), %rax + movq 200(%r10), %rcx + movq %rax, 192(%r10) + sbbq 200(%rdi), %rcx + movq 208(%r10), %r8 + movq %rcx, 200(%r10) + sbbq 208(%rdi), %r8 + movq 216(%r10), %rax + movq %r8, 208(%r10) + sbbq 216(%rdi), %rax + movq 224(%r10), %rcx + movq %rax, 216(%r10) + sbbq 224(%rdi), %rcx + movq 232(%r10), %r8 + movq %rcx, 224(%r10) + sbbq 232(%rdi), %r8 + movq 240(%r10), %rax + movq %r8, 232(%r10) + sbbq 240(%rdi), %rax + movq 248(%r10), %rcx + movq %rax, 240(%r10) + sbbq 248(%rdi), %rcx + movq 256(%r10), %r8 + movq %rcx, 248(%r10) + sbbq 256(%rdi), %r8 + movq 264(%r10), %rax + movq %r8, 256(%r10) + sbbq 264(%rdi), %rax + movq 272(%r10), %rcx + movq %rax, 264(%r10) + sbbq 272(%rdi), %rcx + movq 280(%r10), %r8 + movq %rcx, 272(%r10) + sbbq 280(%rdi), %r8 + movq 288(%r10), %rax + movq %r8, 280(%r10) + sbbq 288(%rdi), %rax + movq 296(%r10), %rcx + movq %rax, 288(%r10) + sbbq 296(%rdi), %rcx + movq 304(%r10), %r8 + movq %rcx, 296(%r10) + sbbq 304(%rdi), %r8 + movq 312(%r10), %rax + movq %r8, 304(%r10) + sbbq 312(%rdi), %rax + movq 320(%r10), %rcx + movq %rax, 312(%r10) + sbbq 320(%rdi), %rcx + movq 328(%r10), %r8 + movq %rcx, 320(%r10) + sbbq 328(%rdi), %r8 + movq 336(%r10), %rax + movq %r8, 328(%r10) + sbbq 336(%rdi), %rax + movq 344(%r10), %rcx + movq %rax, 336(%r10) + sbbq 344(%rdi), %rcx + movq 352(%r10), %r8 + movq %rcx, 344(%r10) + sbbq 352(%rdi), %r8 + movq 360(%r10), %rax + movq %r8, 352(%r10) + sbbq 360(%rdi), %rax + movq 368(%r10), %rcx + movq %rax, 360(%r10) + sbbq 368(%rdi), %rcx + movq 376(%r10), %r8 + movq %rcx, 368(%r10) + sbbq 376(%rdi), %r8 + movq 384(%r10), %rax + movq %r8, 376(%r10) + sbbq 384(%rdi), %rax + movq 392(%r10), %rcx + movq %rax, 384(%r10) + sbbq 392(%rdi), %rcx + movq 400(%r10), %r8 + movq %rcx, 392(%r10) + sbbq 400(%rdi), %r8 + movq 408(%r10), %rax + movq %r8, 400(%r10) + sbbq 408(%rdi), %rax + movq 416(%r10), %rcx + movq %rax, 408(%r10) + sbbq 416(%rdi), %rcx + movq 424(%r10), %r8 + movq %rcx, 416(%r10) + sbbq 424(%rdi), %r8 + movq 432(%r10), %rax + movq %r8, 424(%r10) + sbbq 432(%rdi), %rax + movq 440(%r10), %rcx + movq %rax, 432(%r10) + sbbq 440(%rdi), %rcx + movq 448(%r10), %r8 + movq %rcx, 440(%r10) + sbbq 448(%rdi), %r8 + movq 456(%r10), %rax + movq %r8, 448(%r10) + sbbq 456(%rdi), %rax + movq 464(%r10), %rcx + movq %rax, 456(%r10) + sbbq 464(%rdi), %rcx + movq 472(%r10), %r8 + movq %rcx, 464(%r10) + sbbq 472(%rdi), %r8 + movq 480(%r10), %rax + movq %r8, 472(%r10) + sbbq 480(%rdi), %rax + movq 488(%r10), %rcx + movq %rax, 480(%r10) + sbbq 488(%rdi), %rcx + movq 496(%r10), %r8 + movq %rcx, 488(%r10) + sbbq 496(%rdi), %r8 + movq 504(%r10), %rax + movq %r8, 496(%r10) + sbbq 504(%rdi), %rax + movq %rax, 504(%r10) + sbbq $0, %r9 + subq $256, %r15 + # Add + movq (%r15), %rax + addq (%r10), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r10), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r10), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r10), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r10), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r10), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r10), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r10), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r10), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r10), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r10), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r10), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r10), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r10), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r10), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r10), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r10), %rcx + movq 136(%r15), %r8 + movq %rcx, 128(%r15) + adcq 136(%r10), %r8 + movq 144(%r15), %rax + movq %r8, 136(%r15) + adcq 144(%r10), %rax + movq 152(%r15), %rcx + movq %rax, 144(%r15) + adcq 152(%r10), %rcx + movq 160(%r15), %r8 + movq %rcx, 152(%r15) + adcq 160(%r10), %r8 + movq 168(%r15), %rax + movq %r8, 160(%r15) + adcq 168(%r10), %rax + movq 176(%r15), %rcx + movq %rax, 168(%r15) + adcq 176(%r10), %rcx + movq 184(%r15), %r8 + movq %rcx, 176(%r15) + adcq 184(%r10), %r8 + movq 192(%r15), %rax + movq %r8, 184(%r15) + adcq 192(%r10), %rax + movq 200(%r15), %rcx + movq %rax, 192(%r15) + adcq 200(%r10), %rcx + movq 208(%r15), %r8 + movq %rcx, 200(%r15) + adcq 208(%r10), %r8 + movq 216(%r15), %rax + movq %r8, 208(%r15) + adcq 216(%r10), %rax + movq 224(%r15), %rcx + movq %rax, 216(%r15) + adcq 224(%r10), %rcx + movq 232(%r15), %r8 + movq %rcx, 224(%r15) + adcq 232(%r10), %r8 + movq 240(%r15), %rax + movq %r8, 232(%r15) + adcq 240(%r10), %rax + movq 248(%r15), %rcx + movq %rax, 240(%r15) + adcq 248(%r10), %rcx + movq 256(%r15), %r8 + movq %rcx, 248(%r15) + adcq 256(%r10), %r8 + movq 264(%r15), %rax + movq %r8, 256(%r15) + adcq 264(%r10), %rax + movq 272(%r15), %rcx + movq %rax, 264(%r15) + adcq 272(%r10), %rcx + movq 280(%r15), %r8 + movq %rcx, 272(%r15) + adcq 280(%r10), %r8 + movq 288(%r15), %rax + movq %r8, 280(%r15) + adcq 288(%r10), %rax + movq 296(%r15), %rcx + movq %rax, 288(%r15) + adcq 296(%r10), %rcx + movq 304(%r15), %r8 + movq %rcx, 296(%r15) + adcq 304(%r10), %r8 + movq 312(%r15), %rax + movq %r8, 304(%r15) + adcq 312(%r10), %rax + movq 320(%r15), %rcx + movq %rax, 312(%r15) + adcq 320(%r10), %rcx + movq 328(%r15), %r8 + movq %rcx, 320(%r15) + adcq 328(%r10), %r8 + movq 336(%r15), %rax + movq %r8, 328(%r15) + adcq 336(%r10), %rax + movq 344(%r15), %rcx + movq %rax, 336(%r15) + adcq 344(%r10), %rcx + movq 352(%r15), %r8 + movq %rcx, 344(%r15) + adcq 352(%r10), %r8 + movq 360(%r15), %rax + movq %r8, 352(%r15) + adcq 360(%r10), %rax + movq 368(%r15), %rcx + movq %rax, 360(%r15) + adcq 368(%r10), %rcx + movq 376(%r15), %r8 + movq %rcx, 368(%r15) + adcq 376(%r10), %r8 + movq 384(%r15), %rax + movq %r8, 376(%r15) + adcq 384(%r10), %rax + movq 392(%r15), %rcx + movq %rax, 384(%r15) + adcq 392(%r10), %rcx + movq 400(%r15), %r8 + movq %rcx, 392(%r15) + adcq 400(%r10), %r8 + movq 408(%r15), %rax + movq %r8, 400(%r15) + adcq 408(%r10), %rax + movq 416(%r15), %rcx + movq %rax, 408(%r15) + adcq 416(%r10), %rcx + movq 424(%r15), %r8 + movq %rcx, 416(%r15) + adcq 424(%r10), %r8 + movq 432(%r15), %rax + movq %r8, 424(%r15) + adcq 432(%r10), %rax + movq 440(%r15), %rcx + movq %rax, 432(%r15) + adcq 440(%r10), %rcx + movq 448(%r15), %r8 + movq %rcx, 440(%r15) + adcq 448(%r10), %r8 + movq 456(%r15), %rax + movq %r8, 448(%r15) + adcq 456(%r10), %rax + movq 464(%r15), %rcx + movq %rax, 456(%r15) + adcq 464(%r10), %rcx + movq 472(%r15), %r8 + movq %rcx, 464(%r15) + adcq 472(%r10), %r8 + movq 480(%r15), %rax + movq %r8, 472(%r15) + adcq 480(%r10), %rax + movq 488(%r15), %rcx + movq %rax, 480(%r15) + adcq 488(%r10), %rcx + movq 496(%r15), %r8 + movq %rcx, 488(%r15) + adcq 496(%r10), %r8 + movq 504(%r15), %rax + movq %r8, 496(%r15) + adcq 504(%r10), %rax + movq %rax, 504(%r15) + adcq $0, %r9 + movq %r9, 768(%rdi) + addq $256, %r15 + # Add + movq (%r15), %rax + xorq %r9, %r9 + addq (%r11), %rax + movq 8(%r15), %rcx + movq %rax, (%r15) + adcq 8(%r11), %rcx + movq 16(%r15), %r8 + movq %rcx, 8(%r15) + adcq 16(%r11), %r8 + movq 24(%r15), %rax + movq %r8, 16(%r15) + adcq 24(%r11), %rax + movq 32(%r15), %rcx + movq %rax, 24(%r15) + adcq 32(%r11), %rcx + movq 40(%r15), %r8 + movq %rcx, 32(%r15) + adcq 40(%r11), %r8 + movq 48(%r15), %rax + movq %r8, 40(%r15) + adcq 48(%r11), %rax + movq 56(%r15), %rcx + movq %rax, 48(%r15) + adcq 56(%r11), %rcx + movq 64(%r15), %r8 + movq %rcx, 56(%r15) + adcq 64(%r11), %r8 + movq 72(%r15), %rax + movq %r8, 64(%r15) + adcq 72(%r11), %rax + movq 80(%r15), %rcx + movq %rax, 72(%r15) + adcq 80(%r11), %rcx + movq 88(%r15), %r8 + movq %rcx, 80(%r15) + adcq 88(%r11), %r8 + movq 96(%r15), %rax + movq %r8, 88(%r15) + adcq 96(%r11), %rax + movq 104(%r15), %rcx + movq %rax, 96(%r15) + adcq 104(%r11), %rcx + movq 112(%r15), %r8 + movq %rcx, 104(%r15) + adcq 112(%r11), %r8 + movq 120(%r15), %rax + movq %r8, 112(%r15) + adcq 120(%r11), %rax + movq 128(%r15), %rcx + movq %rax, 120(%r15) + adcq 128(%r11), %rcx + movq 136(%r15), %r8 + movq %rcx, 128(%r15) + adcq 136(%r11), %r8 + movq 144(%r15), %rax + movq %r8, 136(%r15) + adcq 144(%r11), %rax + movq 152(%r15), %rcx + movq %rax, 144(%r15) + adcq 152(%r11), %rcx + movq 160(%r15), %r8 + movq %rcx, 152(%r15) + adcq 160(%r11), %r8 + movq 168(%r15), %rax + movq %r8, 160(%r15) + adcq 168(%r11), %rax + movq 176(%r15), %rcx + movq %rax, 168(%r15) + adcq 176(%r11), %rcx + movq 184(%r15), %r8 + movq %rcx, 176(%r15) + adcq 184(%r11), %r8 + movq 192(%r15), %rax + movq %r8, 184(%r15) + adcq 192(%r11), %rax + movq 200(%r15), %rcx + movq %rax, 192(%r15) + adcq 200(%r11), %rcx + movq 208(%r15), %r8 + movq %rcx, 200(%r15) + adcq 208(%r11), %r8 + movq 216(%r15), %rax + movq %r8, 208(%r15) + adcq 216(%r11), %rax + movq 224(%r15), %rcx + movq %rax, 216(%r15) + adcq 224(%r11), %rcx + movq 232(%r15), %r8 + movq %rcx, 224(%r15) + adcq 232(%r11), %r8 + movq 240(%r15), %rax + movq %r8, 232(%r15) + adcq 240(%r11), %rax + movq 248(%r15), %rcx + movq %rax, 240(%r15) + adcq 248(%r11), %rcx + movq 256(%r15), %r8 + movq %rcx, 248(%r15) + adcq 256(%r11), %r8 + movq %r8, 256(%r15) + adcq $0, %r9 + # Add to zero + movq 264(%r11), %rax + adcq $0, %rax + movq 272(%r11), %rcx + movq %rax, 264(%r15) + adcq $0, %rcx + movq 280(%r11), %r8 + movq %rcx, 272(%r15) + adcq $0, %r8 + movq 288(%r11), %rax + movq %r8, 280(%r15) + adcq $0, %rax + movq 296(%r11), %rcx + movq %rax, 288(%r15) + adcq $0, %rcx + movq 304(%r11), %r8 + movq %rcx, 296(%r15) + adcq $0, %r8 + movq 312(%r11), %rax + movq %r8, 304(%r15) + adcq $0, %rax + movq 320(%r11), %rcx + movq %rax, 312(%r15) + adcq $0, %rcx + movq 328(%r11), %r8 + movq %rcx, 320(%r15) + adcq $0, %r8 + movq 336(%r11), %rax + movq %r8, 328(%r15) + adcq $0, %rax + movq 344(%r11), %rcx + movq %rax, 336(%r15) + adcq $0, %rcx + movq 352(%r11), %r8 + movq %rcx, 344(%r15) + adcq $0, %r8 + movq 360(%r11), %rax + movq %r8, 352(%r15) + adcq $0, %rax + movq 368(%r11), %rcx + movq %rax, 360(%r15) + adcq $0, %rcx + movq 376(%r11), %r8 + movq %rcx, 368(%r15) + adcq $0, %r8 + movq 384(%r11), %rax + movq %r8, 376(%r15) + adcq $0, %rax + movq 392(%r11), %rcx + movq %rax, 384(%r15) + adcq $0, %rcx + movq 400(%r11), %r8 + movq %rcx, 392(%r15) + adcq $0, %r8 + movq 408(%r11), %rax + movq %r8, 400(%r15) + adcq $0, %rax + movq 416(%r11), %rcx + movq %rax, 408(%r15) + adcq $0, %rcx + movq 424(%r11), %r8 + movq %rcx, 416(%r15) + adcq $0, %r8 + movq 432(%r11), %rax + movq %r8, 424(%r15) + adcq $0, %rax + movq 440(%r11), %rcx + movq %rax, 432(%r15) + adcq $0, %rcx + movq 448(%r11), %r8 + movq %rcx, 440(%r15) + adcq $0, %r8 + movq 456(%r11), %rax + movq %r8, 448(%r15) + adcq $0, %rax + movq 464(%r11), %rcx + movq %rax, 456(%r15) + adcq $0, %rcx + movq 472(%r11), %r8 + movq %rcx, 464(%r15) + adcq $0, %r8 + movq 480(%r11), %rax + movq %r8, 472(%r15) + adcq $0, %rax + movq 488(%r11), %rcx + movq %rax, 480(%r15) + adcq $0, %rcx + movq 496(%r11), %r8 + movq %rcx, 488(%r15) + adcq $0, %r8 + movq 504(%r11), %rax + movq %r8, 496(%r15) + adcq $0, %rax + movq %rax, 504(%r15) + addq $1576, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_4096_mul_avx2_64,.-sp_4096_mul_avx2_64 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_4096_sqr_avx2_64 +.type sp_4096_sqr_avx2_64,@function +.align 16 +sp_4096_sqr_avx2_64: +#else +.globl _sp_4096_sqr_avx2_64 +.p2align 4 +_sp_4096_sqr_avx2_64: +#endif /* __APPLE__ */ + subq $1304, %rsp + movq %rdi, 1280(%rsp) + movq %rsi, 1288(%rsp) + leaq 1024(%rsp), %r8 + leaq 256(%rsi), %r9 + # Add + movq (%rsi), %rdx + xorq %rcx, %rcx + addq (%r9), %rdx + movq 8(%rsi), %rax + movq %rdx, (%r8) + adcq 8(%r9), %rax + movq 16(%rsi), %rdx + movq %rax, 8(%r8) + adcq 16(%r9), %rdx + movq 24(%rsi), %rax + movq %rdx, 16(%r8) + adcq 24(%r9), %rax + movq 32(%rsi), %rdx + movq %rax, 24(%r8) + adcq 32(%r9), %rdx + movq 40(%rsi), %rax + movq %rdx, 32(%r8) + adcq 40(%r9), %rax + movq 48(%rsi), %rdx + movq %rax, 40(%r8) + adcq 48(%r9), %rdx + movq 56(%rsi), %rax + movq %rdx, 48(%r8) + adcq 56(%r9), %rax + movq 64(%rsi), %rdx + movq %rax, 56(%r8) + adcq 64(%r9), %rdx + movq 72(%rsi), %rax + movq %rdx, 64(%r8) + adcq 72(%r9), %rax + movq 80(%rsi), %rdx + movq %rax, 72(%r8) + adcq 80(%r9), %rdx + movq 88(%rsi), %rax + movq %rdx, 80(%r8) + adcq 88(%r9), %rax + movq 96(%rsi), %rdx + movq %rax, 88(%r8) + adcq 96(%r9), %rdx + movq 104(%rsi), %rax + movq %rdx, 96(%r8) + adcq 104(%r9), %rax + movq 112(%rsi), %rdx + movq %rax, 104(%r8) + adcq 112(%r9), %rdx + movq 120(%rsi), %rax + movq %rdx, 112(%r8) + adcq 120(%r9), %rax + movq 128(%rsi), %rdx + movq %rax, 120(%r8) + adcq 128(%r9), %rdx + movq 136(%rsi), %rax + movq %rdx, 128(%r8) + adcq 136(%r9), %rax + movq 144(%rsi), %rdx + movq %rax, 136(%r8) + adcq 144(%r9), %rdx + movq 152(%rsi), %rax + movq %rdx, 144(%r8) + adcq 152(%r9), %rax + movq 160(%rsi), %rdx + movq %rax, 152(%r8) + adcq 160(%r9), %rdx + movq 168(%rsi), %rax + movq %rdx, 160(%r8) + adcq 168(%r9), %rax + movq 176(%rsi), %rdx + movq %rax, 168(%r8) + adcq 176(%r9), %rdx + movq 184(%rsi), %rax + movq %rdx, 176(%r8) + adcq 184(%r9), %rax + movq 192(%rsi), %rdx + movq %rax, 184(%r8) + adcq 192(%r9), %rdx + movq 200(%rsi), %rax + movq %rdx, 192(%r8) + adcq 200(%r9), %rax + movq 208(%rsi), %rdx + movq %rax, 200(%r8) + adcq 208(%r9), %rdx + movq 216(%rsi), %rax + movq %rdx, 208(%r8) + adcq 216(%r9), %rax + movq 224(%rsi), %rdx + movq %rax, 216(%r8) + adcq 224(%r9), %rdx + movq 232(%rsi), %rax + movq %rdx, 224(%r8) + adcq 232(%r9), %rax + movq 240(%rsi), %rdx + movq %rax, 232(%r8) + adcq 240(%r9), %rdx + movq 248(%rsi), %rax + movq %rdx, 240(%r8) + adcq 248(%r9), %rax + movq %rax, 248(%r8) + adcq $0, %rcx + movq %rcx, 1296(%rsp) + movq %r8, %rsi + movq %rsp, %rdi +#ifndef __APPLE__ + callq sp_2048_sqr_avx2_32@plt +#else + callq _sp_2048_sqr_avx2_32 +#endif /* __APPLE__ */ + movq 1288(%rsp), %rsi + leaq 512(%rsp), %rdi + addq $256, %rsi +#ifndef __APPLE__ + callq sp_2048_sqr_avx2_32@plt +#else + callq _sp_2048_sqr_avx2_32 +#endif /* __APPLE__ */ + movq 1288(%rsp), %rsi + movq 1280(%rsp), %rdi +#ifndef __APPLE__ + callq sp_2048_sqr_avx2_32@plt +#else + callq _sp_2048_sqr_avx2_32 +#endif /* __APPLE__ */ + movq 1296(%rsp), %r10 + leaq 1024(%rsp), %r8 + movq %r10, %rcx + negq %r10 + movq (%r8), %rdx + pextq %r10, %rdx, %rdx + addq %rdx, %rdx + movq 8(%r8), %rax + movq %rdx, 512(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 16(%r8), %rdx + movq %rax, 520(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 24(%r8), %rax + movq %rdx, 528(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 32(%r8), %rdx + movq %rax, 536(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 40(%r8), %rax + movq %rdx, 544(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 48(%r8), %rdx + movq %rax, 552(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 56(%r8), %rax + movq %rdx, 560(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 64(%r8), %rdx + movq %rax, 568(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 72(%r8), %rax + movq %rdx, 576(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 80(%r8), %rdx + movq %rax, 584(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 88(%r8), %rax + movq %rdx, 592(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 96(%r8), %rdx + movq %rax, 600(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 104(%r8), %rax + movq %rdx, 608(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 112(%r8), %rdx + movq %rax, 616(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 120(%r8), %rax + movq %rdx, 624(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 128(%r8), %rdx + movq %rax, 632(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 136(%r8), %rax + movq %rdx, 640(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 144(%r8), %rdx + movq %rax, 648(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 152(%r8), %rax + movq %rdx, 656(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 160(%r8), %rdx + movq %rax, 664(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 168(%r8), %rax + movq %rdx, 672(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 176(%r8), %rdx + movq %rax, 680(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 184(%r8), %rax + movq %rdx, 688(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 192(%r8), %rdx + movq %rax, 696(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 200(%r8), %rax + movq %rdx, 704(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 208(%r8), %rdx + movq %rax, 712(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 216(%r8), %rax + movq %rdx, 720(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 224(%r8), %rdx + movq %rax, 728(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 232(%r8), %rax + movq %rdx, 736(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq 240(%r8), %rdx + movq %rax, 744(%rdi) + pextq %r10, %rdx, %rdx + adcq %rdx, %rdx + movq 248(%r8), %rax + movq %rdx, 752(%rdi) + pextq %r10, %rax, %rax + adcq %rax, %rax + movq %rax, 760(%rdi) + adcq $0, %rcx + leaq 512(%rsp), %rsi + movq %rsp, %r8 + movq (%r8), %rdx + subq (%rsi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rsi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rsi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rsi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rsi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rsi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rsi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rsi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rsi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rsi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rsi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rsi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rsi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rsi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rsi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rsi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rsi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rsi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rsi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rsi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rsi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rsi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rsi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rsi), %rax + movq 192(%r8), %rdx + movq %rax, 184(%r8) + sbbq 192(%rsi), %rdx + movq 200(%r8), %rax + movq %rdx, 192(%r8) + sbbq 200(%rsi), %rax + movq 208(%r8), %rdx + movq %rax, 200(%r8) + sbbq 208(%rsi), %rdx + movq 216(%r8), %rax + movq %rdx, 208(%r8) + sbbq 216(%rsi), %rax + movq 224(%r8), %rdx + movq %rax, 216(%r8) + sbbq 224(%rsi), %rdx + movq 232(%r8), %rax + movq %rdx, 224(%r8) + sbbq 232(%rsi), %rax + movq 240(%r8), %rdx + movq %rax, 232(%r8) + sbbq 240(%rsi), %rdx + movq 248(%r8), %rax + movq %rdx, 240(%r8) + sbbq 248(%rsi), %rax + movq 256(%r8), %rdx + movq %rax, 248(%r8) + sbbq 256(%rsi), %rdx + movq 264(%r8), %rax + movq %rdx, 256(%r8) + sbbq 264(%rsi), %rax + movq 272(%r8), %rdx + movq %rax, 264(%r8) + sbbq 272(%rsi), %rdx + movq 280(%r8), %rax + movq %rdx, 272(%r8) + sbbq 280(%rsi), %rax + movq 288(%r8), %rdx + movq %rax, 280(%r8) + sbbq 288(%rsi), %rdx + movq 296(%r8), %rax + movq %rdx, 288(%r8) + sbbq 296(%rsi), %rax + movq 304(%r8), %rdx + movq %rax, 296(%r8) + sbbq 304(%rsi), %rdx + movq 312(%r8), %rax + movq %rdx, 304(%r8) + sbbq 312(%rsi), %rax + movq 320(%r8), %rdx + movq %rax, 312(%r8) + sbbq 320(%rsi), %rdx + movq 328(%r8), %rax + movq %rdx, 320(%r8) + sbbq 328(%rsi), %rax + movq 336(%r8), %rdx + movq %rax, 328(%r8) + sbbq 336(%rsi), %rdx + movq 344(%r8), %rax + movq %rdx, 336(%r8) + sbbq 344(%rsi), %rax + movq 352(%r8), %rdx + movq %rax, 344(%r8) + sbbq 352(%rsi), %rdx + movq 360(%r8), %rax + movq %rdx, 352(%r8) + sbbq 360(%rsi), %rax + movq 368(%r8), %rdx + movq %rax, 360(%r8) + sbbq 368(%rsi), %rdx + movq 376(%r8), %rax + movq %rdx, 368(%r8) + sbbq 376(%rsi), %rax + movq 384(%r8), %rdx + movq %rax, 376(%r8) + sbbq 384(%rsi), %rdx + movq 392(%r8), %rax + movq %rdx, 384(%r8) + sbbq 392(%rsi), %rax + movq 400(%r8), %rdx + movq %rax, 392(%r8) + sbbq 400(%rsi), %rdx + movq 408(%r8), %rax + movq %rdx, 400(%r8) + sbbq 408(%rsi), %rax + movq 416(%r8), %rdx + movq %rax, 408(%r8) + sbbq 416(%rsi), %rdx + movq 424(%r8), %rax + movq %rdx, 416(%r8) + sbbq 424(%rsi), %rax + movq 432(%r8), %rdx + movq %rax, 424(%r8) + sbbq 432(%rsi), %rdx + movq 440(%r8), %rax + movq %rdx, 432(%r8) + sbbq 440(%rsi), %rax + movq 448(%r8), %rdx + movq %rax, 440(%r8) + sbbq 448(%rsi), %rdx + movq 456(%r8), %rax + movq %rdx, 448(%r8) + sbbq 456(%rsi), %rax + movq 464(%r8), %rdx + movq %rax, 456(%r8) + sbbq 464(%rsi), %rdx + movq 472(%r8), %rax + movq %rdx, 464(%r8) + sbbq 472(%rsi), %rax + movq 480(%r8), %rdx + movq %rax, 472(%r8) + sbbq 480(%rsi), %rdx + movq 488(%r8), %rax + movq %rdx, 480(%r8) + sbbq 488(%rsi), %rax + movq 496(%r8), %rdx + movq %rax, 488(%r8) + sbbq 496(%rsi), %rdx + movq 504(%r8), %rax + movq %rdx, 496(%r8) + sbbq 504(%rsi), %rax + movq %rax, 504(%r8) + sbbq $0, %rcx + movq (%r8), %rdx + subq (%rdi), %rdx + movq 8(%r8), %rax + movq %rdx, (%r8) + sbbq 8(%rdi), %rax + movq 16(%r8), %rdx + movq %rax, 8(%r8) + sbbq 16(%rdi), %rdx + movq 24(%r8), %rax + movq %rdx, 16(%r8) + sbbq 24(%rdi), %rax + movq 32(%r8), %rdx + movq %rax, 24(%r8) + sbbq 32(%rdi), %rdx + movq 40(%r8), %rax + movq %rdx, 32(%r8) + sbbq 40(%rdi), %rax + movq 48(%r8), %rdx + movq %rax, 40(%r8) + sbbq 48(%rdi), %rdx + movq 56(%r8), %rax + movq %rdx, 48(%r8) + sbbq 56(%rdi), %rax + movq 64(%r8), %rdx + movq %rax, 56(%r8) + sbbq 64(%rdi), %rdx + movq 72(%r8), %rax + movq %rdx, 64(%r8) + sbbq 72(%rdi), %rax + movq 80(%r8), %rdx + movq %rax, 72(%r8) + sbbq 80(%rdi), %rdx + movq 88(%r8), %rax + movq %rdx, 80(%r8) + sbbq 88(%rdi), %rax + movq 96(%r8), %rdx + movq %rax, 88(%r8) + sbbq 96(%rdi), %rdx + movq 104(%r8), %rax + movq %rdx, 96(%r8) + sbbq 104(%rdi), %rax + movq 112(%r8), %rdx + movq %rax, 104(%r8) + sbbq 112(%rdi), %rdx + movq 120(%r8), %rax + movq %rdx, 112(%r8) + sbbq 120(%rdi), %rax + movq 128(%r8), %rdx + movq %rax, 120(%r8) + sbbq 128(%rdi), %rdx + movq 136(%r8), %rax + movq %rdx, 128(%r8) + sbbq 136(%rdi), %rax + movq 144(%r8), %rdx + movq %rax, 136(%r8) + sbbq 144(%rdi), %rdx + movq 152(%r8), %rax + movq %rdx, 144(%r8) + sbbq 152(%rdi), %rax + movq 160(%r8), %rdx + movq %rax, 152(%r8) + sbbq 160(%rdi), %rdx + movq 168(%r8), %rax + movq %rdx, 160(%r8) + sbbq 168(%rdi), %rax + movq 176(%r8), %rdx + movq %rax, 168(%r8) + sbbq 176(%rdi), %rdx + movq 184(%r8), %rax + movq %rdx, 176(%r8) + sbbq 184(%rdi), %rax + movq 192(%r8), %rdx + movq %rax, 184(%r8) + sbbq 192(%rdi), %rdx + movq 200(%r8), %rax + movq %rdx, 192(%r8) + sbbq 200(%rdi), %rax + movq 208(%r8), %rdx + movq %rax, 200(%r8) + sbbq 208(%rdi), %rdx + movq 216(%r8), %rax + movq %rdx, 208(%r8) + sbbq 216(%rdi), %rax + movq 224(%r8), %rdx + movq %rax, 216(%r8) + sbbq 224(%rdi), %rdx + movq 232(%r8), %rax + movq %rdx, 224(%r8) + sbbq 232(%rdi), %rax + movq 240(%r8), %rdx + movq %rax, 232(%r8) + sbbq 240(%rdi), %rdx + movq 248(%r8), %rax + movq %rdx, 240(%r8) + sbbq 248(%rdi), %rax + movq 256(%r8), %rdx + movq %rax, 248(%r8) + sbbq 256(%rdi), %rdx + movq 264(%r8), %rax + movq %rdx, 256(%r8) + sbbq 264(%rdi), %rax + movq 272(%r8), %rdx + movq %rax, 264(%r8) + sbbq 272(%rdi), %rdx + movq 280(%r8), %rax + movq %rdx, 272(%r8) + sbbq 280(%rdi), %rax + movq 288(%r8), %rdx + movq %rax, 280(%r8) + sbbq 288(%rdi), %rdx + movq 296(%r8), %rax + movq %rdx, 288(%r8) + sbbq 296(%rdi), %rax + movq 304(%r8), %rdx + movq %rax, 296(%r8) + sbbq 304(%rdi), %rdx + movq 312(%r8), %rax + movq %rdx, 304(%r8) + sbbq 312(%rdi), %rax + movq 320(%r8), %rdx + movq %rax, 312(%r8) + sbbq 320(%rdi), %rdx + movq 328(%r8), %rax + movq %rdx, 320(%r8) + sbbq 328(%rdi), %rax + movq 336(%r8), %rdx + movq %rax, 328(%r8) + sbbq 336(%rdi), %rdx + movq 344(%r8), %rax + movq %rdx, 336(%r8) + sbbq 344(%rdi), %rax + movq 352(%r8), %rdx + movq %rax, 344(%r8) + sbbq 352(%rdi), %rdx + movq 360(%r8), %rax + movq %rdx, 352(%r8) + sbbq 360(%rdi), %rax + movq 368(%r8), %rdx + movq %rax, 360(%r8) + sbbq 368(%rdi), %rdx + movq 376(%r8), %rax + movq %rdx, 368(%r8) + sbbq 376(%rdi), %rax + movq 384(%r8), %rdx + movq %rax, 376(%r8) + sbbq 384(%rdi), %rdx + movq 392(%r8), %rax + movq %rdx, 384(%r8) + sbbq 392(%rdi), %rax + movq 400(%r8), %rdx + movq %rax, 392(%r8) + sbbq 400(%rdi), %rdx + movq 408(%r8), %rax + movq %rdx, 400(%r8) + sbbq 408(%rdi), %rax + movq 416(%r8), %rdx + movq %rax, 408(%r8) + sbbq 416(%rdi), %rdx + movq 424(%r8), %rax + movq %rdx, 416(%r8) + sbbq 424(%rdi), %rax + movq 432(%r8), %rdx + movq %rax, 424(%r8) + sbbq 432(%rdi), %rdx + movq 440(%r8), %rax + movq %rdx, 432(%r8) + sbbq 440(%rdi), %rax + movq 448(%r8), %rdx + movq %rax, 440(%r8) + sbbq 448(%rdi), %rdx + movq 456(%r8), %rax + movq %rdx, 448(%r8) + sbbq 456(%rdi), %rax + movq 464(%r8), %rdx + movq %rax, 456(%r8) + sbbq 464(%rdi), %rdx + movq 472(%r8), %rax + movq %rdx, 464(%r8) + sbbq 472(%rdi), %rax + movq 480(%r8), %rdx + movq %rax, 472(%r8) + sbbq 480(%rdi), %rdx + movq 488(%r8), %rax + movq %rdx, 480(%r8) + sbbq 488(%rdi), %rax + movq 496(%r8), %rdx + movq %rax, 488(%r8) + sbbq 496(%rdi), %rdx + movq 504(%r8), %rax + movq %rdx, 496(%r8) + sbbq 504(%rdi), %rax + movq %rax, 504(%r8) + sbbq $0, %rcx + # Add in place + movq 256(%rdi), %rdx + addq (%r8), %rdx + movq 264(%rdi), %rax + movq %rdx, 256(%rdi) + adcq 8(%r8), %rax + movq 272(%rdi), %rdx + movq %rax, 264(%rdi) + adcq 16(%r8), %rdx + movq 280(%rdi), %rax + movq %rdx, 272(%rdi) + adcq 24(%r8), %rax + movq 288(%rdi), %rdx + movq %rax, 280(%rdi) + adcq 32(%r8), %rdx + movq 296(%rdi), %rax + movq %rdx, 288(%rdi) + adcq 40(%r8), %rax + movq 304(%rdi), %rdx + movq %rax, 296(%rdi) + adcq 48(%r8), %rdx + movq 312(%rdi), %rax + movq %rdx, 304(%rdi) + adcq 56(%r8), %rax + movq 320(%rdi), %rdx + movq %rax, 312(%rdi) + adcq 64(%r8), %rdx + movq 328(%rdi), %rax + movq %rdx, 320(%rdi) + adcq 72(%r8), %rax + movq 336(%rdi), %rdx + movq %rax, 328(%rdi) + adcq 80(%r8), %rdx + movq 344(%rdi), %rax + movq %rdx, 336(%rdi) + adcq 88(%r8), %rax + movq 352(%rdi), %rdx + movq %rax, 344(%rdi) + adcq 96(%r8), %rdx + movq 360(%rdi), %rax + movq %rdx, 352(%rdi) + adcq 104(%r8), %rax + movq 368(%rdi), %rdx + movq %rax, 360(%rdi) + adcq 112(%r8), %rdx + movq 376(%rdi), %rax + movq %rdx, 368(%rdi) + adcq 120(%r8), %rax + movq 384(%rdi), %rdx + movq %rax, 376(%rdi) + adcq 128(%r8), %rdx + movq 392(%rdi), %rax + movq %rdx, 384(%rdi) + adcq 136(%r8), %rax + movq 400(%rdi), %rdx + movq %rax, 392(%rdi) + adcq 144(%r8), %rdx + movq 408(%rdi), %rax + movq %rdx, 400(%rdi) + adcq 152(%r8), %rax + movq 416(%rdi), %rdx + movq %rax, 408(%rdi) + adcq 160(%r8), %rdx + movq 424(%rdi), %rax + movq %rdx, 416(%rdi) + adcq 168(%r8), %rax + movq 432(%rdi), %rdx + movq %rax, 424(%rdi) + adcq 176(%r8), %rdx + movq 440(%rdi), %rax + movq %rdx, 432(%rdi) + adcq 184(%r8), %rax + movq 448(%rdi), %rdx + movq %rax, 440(%rdi) + adcq 192(%r8), %rdx + movq 456(%rdi), %rax + movq %rdx, 448(%rdi) + adcq 200(%r8), %rax + movq 464(%rdi), %rdx + movq %rax, 456(%rdi) + adcq 208(%r8), %rdx + movq 472(%rdi), %rax + movq %rdx, 464(%rdi) + adcq 216(%r8), %rax + movq 480(%rdi), %rdx + movq %rax, 472(%rdi) + adcq 224(%r8), %rdx + movq 488(%rdi), %rax + movq %rdx, 480(%rdi) + adcq 232(%r8), %rax + movq 496(%rdi), %rdx + movq %rax, 488(%rdi) + adcq 240(%r8), %rdx + movq 504(%rdi), %rax + movq %rdx, 496(%rdi) + adcq 248(%r8), %rax + movq 512(%rdi), %rdx + movq %rax, 504(%rdi) + adcq 256(%r8), %rdx + movq 520(%rdi), %rax + movq %rdx, 512(%rdi) + adcq 264(%r8), %rax + movq 528(%rdi), %rdx + movq %rax, 520(%rdi) + adcq 272(%r8), %rdx + movq 536(%rdi), %rax + movq %rdx, 528(%rdi) + adcq 280(%r8), %rax + movq 544(%rdi), %rdx + movq %rax, 536(%rdi) + adcq 288(%r8), %rdx + movq 552(%rdi), %rax + movq %rdx, 544(%rdi) + adcq 296(%r8), %rax + movq 560(%rdi), %rdx + movq %rax, 552(%rdi) + adcq 304(%r8), %rdx + movq 568(%rdi), %rax + movq %rdx, 560(%rdi) + adcq 312(%r8), %rax + movq 576(%rdi), %rdx + movq %rax, 568(%rdi) + adcq 320(%r8), %rdx + movq 584(%rdi), %rax + movq %rdx, 576(%rdi) + adcq 328(%r8), %rax + movq 592(%rdi), %rdx + movq %rax, 584(%rdi) + adcq 336(%r8), %rdx + movq 600(%rdi), %rax + movq %rdx, 592(%rdi) + adcq 344(%r8), %rax + movq 608(%rdi), %rdx + movq %rax, 600(%rdi) + adcq 352(%r8), %rdx + movq 616(%rdi), %rax + movq %rdx, 608(%rdi) + adcq 360(%r8), %rax + movq 624(%rdi), %rdx + movq %rax, 616(%rdi) + adcq 368(%r8), %rdx + movq 632(%rdi), %rax + movq %rdx, 624(%rdi) + adcq 376(%r8), %rax + movq 640(%rdi), %rdx + movq %rax, 632(%rdi) + adcq 384(%r8), %rdx + movq 648(%rdi), %rax + movq %rdx, 640(%rdi) + adcq 392(%r8), %rax + movq 656(%rdi), %rdx + movq %rax, 648(%rdi) + adcq 400(%r8), %rdx + movq 664(%rdi), %rax + movq %rdx, 656(%rdi) + adcq 408(%r8), %rax + movq 672(%rdi), %rdx + movq %rax, 664(%rdi) + adcq 416(%r8), %rdx + movq 680(%rdi), %rax + movq %rdx, 672(%rdi) + adcq 424(%r8), %rax + movq 688(%rdi), %rdx + movq %rax, 680(%rdi) + adcq 432(%r8), %rdx + movq 696(%rdi), %rax + movq %rdx, 688(%rdi) + adcq 440(%r8), %rax + movq 704(%rdi), %rdx + movq %rax, 696(%rdi) + adcq 448(%r8), %rdx + movq 712(%rdi), %rax + movq %rdx, 704(%rdi) + adcq 456(%r8), %rax + movq 720(%rdi), %rdx + movq %rax, 712(%rdi) + adcq 464(%r8), %rdx + movq 728(%rdi), %rax + movq %rdx, 720(%rdi) + adcq 472(%r8), %rax + movq 736(%rdi), %rdx + movq %rax, 728(%rdi) + adcq 480(%r8), %rdx + movq 744(%rdi), %rax + movq %rdx, 736(%rdi) + adcq 488(%r8), %rax + movq 752(%rdi), %rdx + movq %rax, 744(%rdi) + adcq 496(%r8), %rdx + movq 760(%rdi), %rax + movq %rdx, 752(%rdi) + adcq 504(%r8), %rax + movq %rax, 760(%rdi) + adcq $0, %rcx + movq %rcx, 768(%rdi) + # Add in place + movq 512(%rdi), %rdx + xorq %rcx, %rcx + addq (%rsi), %rdx + movq 520(%rdi), %rax + movq %rdx, 512(%rdi) + adcq 8(%rsi), %rax + movq 528(%rdi), %rdx + movq %rax, 520(%rdi) + adcq 16(%rsi), %rdx + movq 536(%rdi), %rax + movq %rdx, 528(%rdi) + adcq 24(%rsi), %rax + movq 544(%rdi), %rdx + movq %rax, 536(%rdi) + adcq 32(%rsi), %rdx + movq 552(%rdi), %rax + movq %rdx, 544(%rdi) + adcq 40(%rsi), %rax + movq 560(%rdi), %rdx + movq %rax, 552(%rdi) + adcq 48(%rsi), %rdx + movq 568(%rdi), %rax + movq %rdx, 560(%rdi) + adcq 56(%rsi), %rax + movq 576(%rdi), %rdx + movq %rax, 568(%rdi) + adcq 64(%rsi), %rdx + movq 584(%rdi), %rax + movq %rdx, 576(%rdi) + adcq 72(%rsi), %rax + movq 592(%rdi), %rdx + movq %rax, 584(%rdi) + adcq 80(%rsi), %rdx + movq 600(%rdi), %rax + movq %rdx, 592(%rdi) + adcq 88(%rsi), %rax + movq 608(%rdi), %rdx + movq %rax, 600(%rdi) + adcq 96(%rsi), %rdx + movq 616(%rdi), %rax + movq %rdx, 608(%rdi) + adcq 104(%rsi), %rax + movq 624(%rdi), %rdx + movq %rax, 616(%rdi) + adcq 112(%rsi), %rdx + movq 632(%rdi), %rax + movq %rdx, 624(%rdi) + adcq 120(%rsi), %rax + movq 640(%rdi), %rdx + movq %rax, 632(%rdi) + adcq 128(%rsi), %rdx + movq 648(%rdi), %rax + movq %rdx, 640(%rdi) + adcq 136(%rsi), %rax + movq 656(%rdi), %rdx + movq %rax, 648(%rdi) + adcq 144(%rsi), %rdx + movq 664(%rdi), %rax + movq %rdx, 656(%rdi) + adcq 152(%rsi), %rax + movq 672(%rdi), %rdx + movq %rax, 664(%rdi) + adcq 160(%rsi), %rdx + movq 680(%rdi), %rax + movq %rdx, 672(%rdi) + adcq 168(%rsi), %rax + movq 688(%rdi), %rdx + movq %rax, 680(%rdi) + adcq 176(%rsi), %rdx + movq 696(%rdi), %rax + movq %rdx, 688(%rdi) + adcq 184(%rsi), %rax + movq 704(%rdi), %rdx + movq %rax, 696(%rdi) + adcq 192(%rsi), %rdx + movq 712(%rdi), %rax + movq %rdx, 704(%rdi) + adcq 200(%rsi), %rax + movq 720(%rdi), %rdx + movq %rax, 712(%rdi) + adcq 208(%rsi), %rdx + movq 728(%rdi), %rax + movq %rdx, 720(%rdi) + adcq 216(%rsi), %rax + movq 736(%rdi), %rdx + movq %rax, 728(%rdi) + adcq 224(%rsi), %rdx + movq 744(%rdi), %rax + movq %rdx, 736(%rdi) + adcq 232(%rsi), %rax + movq 752(%rdi), %rdx + movq %rax, 744(%rdi) + adcq 240(%rsi), %rdx + movq 760(%rdi), %rax + movq %rdx, 752(%rdi) + adcq 248(%rsi), %rax + movq 768(%rdi), %rdx + movq %rax, 760(%rdi) + adcq 256(%rsi), %rdx + movq %rdx, 768(%rdi) + adcq $0, %rcx + # Add to zero + movq 264(%rsi), %rdx + adcq $0, %rdx + movq 272(%rsi), %rax + movq %rdx, 776(%rdi) + adcq $0, %rax + movq 280(%rsi), %rdx + movq %rax, 784(%rdi) + adcq $0, %rdx + movq 288(%rsi), %rax + movq %rdx, 792(%rdi) + adcq $0, %rax + movq 296(%rsi), %rdx + movq %rax, 800(%rdi) + adcq $0, %rdx + movq 304(%rsi), %rax + movq %rdx, 808(%rdi) + adcq $0, %rax + movq 312(%rsi), %rdx + movq %rax, 816(%rdi) + adcq $0, %rdx + movq 320(%rsi), %rax + movq %rdx, 824(%rdi) + adcq $0, %rax + movq 328(%rsi), %rdx + movq %rax, 832(%rdi) + adcq $0, %rdx + movq 336(%rsi), %rax + movq %rdx, 840(%rdi) + adcq $0, %rax + movq 344(%rsi), %rdx + movq %rax, 848(%rdi) + adcq $0, %rdx + movq 352(%rsi), %rax + movq %rdx, 856(%rdi) + adcq $0, %rax + movq 360(%rsi), %rdx + movq %rax, 864(%rdi) + adcq $0, %rdx + movq 368(%rsi), %rax + movq %rdx, 872(%rdi) + adcq $0, %rax + movq 376(%rsi), %rdx + movq %rax, 880(%rdi) + adcq $0, %rdx + movq 384(%rsi), %rax + movq %rdx, 888(%rdi) + adcq $0, %rax + movq 392(%rsi), %rdx + movq %rax, 896(%rdi) + adcq $0, %rdx + movq 400(%rsi), %rax + movq %rdx, 904(%rdi) + adcq $0, %rax + movq 408(%rsi), %rdx + movq %rax, 912(%rdi) + adcq $0, %rdx + movq 416(%rsi), %rax + movq %rdx, 920(%rdi) + adcq $0, %rax + movq 424(%rsi), %rdx + movq %rax, 928(%rdi) + adcq $0, %rdx + movq 432(%rsi), %rax + movq %rdx, 936(%rdi) + adcq $0, %rax + movq 440(%rsi), %rdx + movq %rax, 944(%rdi) + adcq $0, %rdx + movq 448(%rsi), %rax + movq %rdx, 952(%rdi) + adcq $0, %rax + movq 456(%rsi), %rdx + movq %rax, 960(%rdi) + adcq $0, %rdx + movq 464(%rsi), %rax + movq %rdx, 968(%rdi) + adcq $0, %rax + movq 472(%rsi), %rdx + movq %rax, 976(%rdi) + adcq $0, %rdx + movq 480(%rsi), %rax + movq %rdx, 984(%rdi) + adcq $0, %rax + movq 488(%rsi), %rdx + movq %rax, 992(%rdi) + adcq $0, %rdx + movq 496(%rsi), %rax + movq %rdx, 1000(%rdi) + adcq $0, %rax + movq 504(%rsi), %rdx + movq %rax, 1008(%rdi) + adcq $0, %rdx + movq %rdx, 1016(%rdi) + addq $1304, %rsp + repz retq +#ifndef __APPLE__ +.size sp_4096_sqr_avx2_64,.-sp_4096_sqr_avx2_64 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_4096_mul_d_64 +.type sp_4096_mul_d_64,@function +.align 16 +sp_4096_mul_d_64: +#else +.globl _sp_4096_mul_d_64 +.p2align 4 +_sp_4096_mul_d_64: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 24(%rsi) + addq %rax, %r8 + movq %r8, 24(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 32(%rsi) + addq %rax, %r9 + movq %r9, 32(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 40(%rsi) + addq %rax, %r10 + movq %r10, 40(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 48(%rsi) + addq %rax, %r8 + movq %r8, 48(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 56(%rsi) + addq %rax, %r9 + movq %r9, 56(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 64(%rsi) + addq %rax, %r10 + movq %r10, 64(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 72(%rsi) + addq %rax, %r8 + movq %r8, 72(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 80(%rsi) + addq %rax, %r9 + movq %r9, 80(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 88(%rsi) + addq %rax, %r10 + movq %r10, 88(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 96(%rsi) + addq %rax, %r8 + movq %r8, 96(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 104(%rsi) + addq %rax, %r9 + movq %r9, 104(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 112(%rsi) + addq %rax, %r10 + movq %r10, 112(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 120(%rsi) + addq %rax, %r8 + movq %r8, 120(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 128(%rsi) + addq %rax, %r9 + movq %r9, 128(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 136(%rsi) + addq %rax, %r10 + movq %r10, 136(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 144(%rsi) + addq %rax, %r8 + movq %r8, 144(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 152(%rsi) + addq %rax, %r9 + movq %r9, 152(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 160(%rsi) + addq %rax, %r10 + movq %r10, 160(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 168(%rsi) + addq %rax, %r8 + movq %r8, 168(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 176(%rsi) + addq %rax, %r9 + movq %r9, 176(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 184(%rsi) + addq %rax, %r10 + movq %r10, 184(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[24] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 192(%rsi) + addq %rax, %r8 + movq %r8, 192(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[25] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 200(%rsi) + addq %rax, %r9 + movq %r9, 200(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[26] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 208(%rsi) + addq %rax, %r10 + movq %r10, 208(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[27] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 216(%rsi) + addq %rax, %r8 + movq %r8, 216(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[28] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 224(%rsi) + addq %rax, %r9 + movq %r9, 224(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[29] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 232(%rsi) + addq %rax, %r10 + movq %r10, 232(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[30] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 240(%rsi) + addq %rax, %r8 + movq %r8, 240(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[31] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 248(%rsi) + addq %rax, %r9 + movq %r9, 248(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[32] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 256(%rsi) + addq %rax, %r10 + movq %r10, 256(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[33] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 264(%rsi) + addq %rax, %r8 + movq %r8, 264(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[34] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 272(%rsi) + addq %rax, %r9 + movq %r9, 272(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[35] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 280(%rsi) + addq %rax, %r10 + movq %r10, 280(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[36] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 288(%rsi) + addq %rax, %r8 + movq %r8, 288(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[37] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 296(%rsi) + addq %rax, %r9 + movq %r9, 296(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[38] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 304(%rsi) + addq %rax, %r10 + movq %r10, 304(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[39] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 312(%rsi) + addq %rax, %r8 + movq %r8, 312(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[40] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 320(%rsi) + addq %rax, %r9 + movq %r9, 320(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[41] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 328(%rsi) + addq %rax, %r10 + movq %r10, 328(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[42] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 336(%rsi) + addq %rax, %r8 + movq %r8, 336(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[43] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 344(%rsi) + addq %rax, %r9 + movq %r9, 344(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[44] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 352(%rsi) + addq %rax, %r10 + movq %r10, 352(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[45] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 360(%rsi) + addq %rax, %r8 + movq %r8, 360(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[46] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 368(%rsi) + addq %rax, %r9 + movq %r9, 368(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[47] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 376(%rsi) + addq %rax, %r10 + movq %r10, 376(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[48] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 384(%rsi) + addq %rax, %r8 + movq %r8, 384(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[49] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 392(%rsi) + addq %rax, %r9 + movq %r9, 392(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[50] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 400(%rsi) + addq %rax, %r10 + movq %r10, 400(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[51] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 408(%rsi) + addq %rax, %r8 + movq %r8, 408(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[52] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 416(%rsi) + addq %rax, %r9 + movq %r9, 416(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[53] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 424(%rsi) + addq %rax, %r10 + movq %r10, 424(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[54] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 432(%rsi) + addq %rax, %r8 + movq %r8, 432(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[55] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 440(%rsi) + addq %rax, %r9 + movq %r9, 440(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[56] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 448(%rsi) + addq %rax, %r10 + movq %r10, 448(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[57] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 456(%rsi) + addq %rax, %r8 + movq %r8, 456(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[58] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 464(%rsi) + addq %rax, %r9 + movq %r9, 464(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[59] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 472(%rsi) + addq %rax, %r10 + movq %r10, 472(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[60] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 480(%rsi) + addq %rax, %r8 + movq %r8, 480(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[61] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 488(%rsi) + addq %rax, %r9 + movq %r9, 488(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[62] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 496(%rsi) + addq %rax, %r10 + movq %r10, 496(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[63] * B + movq %rcx, %rax + mulq 504(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 504(%rdi) + movq %r9, 512(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_4096_mul_d_64,.-sp_4096_mul_d_64 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_4096_cond_sub_64 +.type sp_4096_cond_sub_64,@function +.align 16 +sp_4096_cond_sub_64: +#else +.globl _sp_4096_cond_sub_64 +.p2align 4 +_sp_4096_cond_sub_64: +#endif /* __APPLE__ */ + subq $512, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq 128(%rdx), %r8 + movq 136(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 128(%rsp) + movq %r9, 136(%rsp) + movq 144(%rdx), %r8 + movq 152(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 144(%rsp) + movq %r9, 152(%rsp) + movq 160(%rdx), %r8 + movq 168(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r9, 168(%rsp) + movq 176(%rdx), %r8 + movq 184(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 176(%rsp) + movq %r9, 184(%rsp) + movq 192(%rdx), %r8 + movq 200(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 192(%rsp) + movq %r9, 200(%rsp) + movq 208(%rdx), %r8 + movq 216(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 208(%rsp) + movq %r9, 216(%rsp) + movq 224(%rdx), %r8 + movq 232(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 224(%rsp) + movq %r9, 232(%rsp) + movq 240(%rdx), %r8 + movq 248(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 240(%rsp) + movq %r9, 248(%rsp) + movq 256(%rdx), %r8 + movq 264(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 256(%rsp) + movq %r9, 264(%rsp) + movq 272(%rdx), %r8 + movq 280(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 272(%rsp) + movq %r9, 280(%rsp) + movq 288(%rdx), %r8 + movq 296(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 288(%rsp) + movq %r9, 296(%rsp) + movq 304(%rdx), %r8 + movq 312(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 304(%rsp) + movq %r9, 312(%rsp) + movq 320(%rdx), %r8 + movq 328(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 320(%rsp) + movq %r9, 328(%rsp) + movq 336(%rdx), %r8 + movq 344(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 336(%rsp) + movq %r9, 344(%rsp) + movq 352(%rdx), %r8 + movq 360(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 352(%rsp) + movq %r9, 360(%rsp) + movq 368(%rdx), %r8 + movq 376(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 368(%rsp) + movq %r9, 376(%rsp) + movq 384(%rdx), %r8 + movq 392(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 384(%rsp) + movq %r9, 392(%rsp) + movq 400(%rdx), %r8 + movq 408(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 400(%rsp) + movq %r9, 408(%rsp) + movq 416(%rdx), %r8 + movq 424(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 416(%rsp) + movq %r9, 424(%rsp) + movq 432(%rdx), %r8 + movq 440(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 432(%rsp) + movq %r9, 440(%rsp) + movq 448(%rdx), %r8 + movq 456(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 448(%rsp) + movq %r9, 456(%rsp) + movq 464(%rdx), %r8 + movq 472(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 464(%rsp) + movq %r9, 472(%rsp) + movq 480(%rdx), %r8 + movq 488(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 480(%rsp) + movq %r9, 488(%rsp) + movq 496(%rdx), %r8 + movq 504(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 496(%rsp) + movq %r9, 504(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + subq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 112(%rdi) + movq 128(%rsi), %r8 + movq 128(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 120(%rdi) + movq 136(%rsi), %r9 + movq 136(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 128(%rdi) + movq 144(%rsi), %r8 + movq 144(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 136(%rdi) + movq 152(%rsi), %r9 + movq 152(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 144(%rdi) + movq 160(%rsi), %r8 + movq 160(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 152(%rdi) + movq 168(%rsi), %r9 + movq 168(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 160(%rdi) + movq 176(%rsi), %r8 + movq 176(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 168(%rdi) + movq 184(%rsi), %r9 + movq 184(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 176(%rdi) + movq 192(%rsi), %r8 + movq 192(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 184(%rdi) + movq 200(%rsi), %r9 + movq 200(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 192(%rdi) + movq 208(%rsi), %r8 + movq 208(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 200(%rdi) + movq 216(%rsi), %r9 + movq 216(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 208(%rdi) + movq 224(%rsi), %r8 + movq 224(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 216(%rdi) + movq 232(%rsi), %r9 + movq 232(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 224(%rdi) + movq 240(%rsi), %r8 + movq 240(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 232(%rdi) + movq 248(%rsi), %r9 + movq 248(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 240(%rdi) + movq 256(%rsi), %r8 + movq 256(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 248(%rdi) + movq 264(%rsi), %r9 + movq 264(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 256(%rdi) + movq 272(%rsi), %r8 + movq 272(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 264(%rdi) + movq 280(%rsi), %r9 + movq 280(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 272(%rdi) + movq 288(%rsi), %r8 + movq 288(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 280(%rdi) + movq 296(%rsi), %r9 + movq 296(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 288(%rdi) + movq 304(%rsi), %r8 + movq 304(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 296(%rdi) + movq 312(%rsi), %r9 + movq 312(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 304(%rdi) + movq 320(%rsi), %r8 + movq 320(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 312(%rdi) + movq 328(%rsi), %r9 + movq 328(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 320(%rdi) + movq 336(%rsi), %r8 + movq 336(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 328(%rdi) + movq 344(%rsi), %r9 + movq 344(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 336(%rdi) + movq 352(%rsi), %r8 + movq 352(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 344(%rdi) + movq 360(%rsi), %r9 + movq 360(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 352(%rdi) + movq 368(%rsi), %r8 + movq 368(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 360(%rdi) + movq 376(%rsi), %r9 + movq 376(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 368(%rdi) + movq 384(%rsi), %r8 + movq 384(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 376(%rdi) + movq 392(%rsi), %r9 + movq 392(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 384(%rdi) + movq 400(%rsi), %r8 + movq 400(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 392(%rdi) + movq 408(%rsi), %r9 + movq 408(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 400(%rdi) + movq 416(%rsi), %r8 + movq 416(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 408(%rdi) + movq 424(%rsi), %r9 + movq 424(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 416(%rdi) + movq 432(%rsi), %r8 + movq 432(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 424(%rdi) + movq 440(%rsi), %r9 + movq 440(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 432(%rdi) + movq 448(%rsi), %r8 + movq 448(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 440(%rdi) + movq 456(%rsi), %r9 + movq 456(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 448(%rdi) + movq 464(%rsi), %r8 + movq 464(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 456(%rdi) + movq 472(%rsi), %r9 + movq 472(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 464(%rdi) + movq 480(%rsi), %r8 + movq 480(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 472(%rdi) + movq 488(%rsi), %r9 + movq 488(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 480(%rdi) + movq 496(%rsi), %r8 + movq 496(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 488(%rdi) + movq 504(%rsi), %r9 + movq 504(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 496(%rdi) + movq %r9, 504(%rdi) + sbbq $0, %rax + addq $512, %rsp + repz retq +#ifndef __APPLE__ +.size sp_4096_cond_sub_64,.-sp_4096_cond_sub_64 +#endif /* __APPLE__ */ +/* Reduce the number back to 4096 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. + */ +#ifndef __APPLE__ +.globl sp_4096_mont_reduce_64 +.type sp_4096_mont_reduce_64,@function +.align 16 +sp_4096_mont_reduce_64: +#else +.globl _sp_4096_mont_reduce_64 +.p2align 4 +_sp_4096_mont_reduce_64: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rcx + xorq %r15, %r15 + # i = 64 + movq $64, %r8 + movq (%rdi), %r13 + movq 8(%rdi), %r14 +L_mont_loop_64: + # mu = a[i] * mp + movq %r13, %r11 + imulq %rcx, %r11 + # a[i+0] += m[0] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq (%rsi) + addq %rax, %r13 + adcq %rdx, %r10 + # a[i+1] += m[1] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 8(%rsi) + movq %r14, %r13 + addq %rax, %r13 + adcq %rdx, %r9 + addq %r10, %r13 + adcq $0, %r9 + # a[i+2] += m[2] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 16(%rsi) + movq 16(%rdi), %r14 + addq %rax, %r14 + adcq %rdx, %r10 + addq %r9, %r14 + adcq $0, %r10 + # a[i+3] += m[3] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 24(%rsi) + movq 24(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 24(%rdi) + adcq $0, %r9 + # a[i+4] += m[4] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 32(%rsi) + movq 32(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 32(%rdi) + adcq $0, %r10 + # a[i+5] += m[5] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 40(%rsi) + movq 40(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 40(%rdi) + adcq $0, %r9 + # a[i+6] += m[6] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 48(%rsi) + movq 48(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 48(%rdi) + adcq $0, %r10 + # a[i+7] += m[7] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 56(%rsi) + movq 56(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 56(%rdi) + adcq $0, %r9 + # a[i+8] += m[8] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 64(%rsi) + movq 64(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 64(%rdi) + adcq $0, %r10 + # a[i+9] += m[9] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 72(%rsi) + movq 72(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 72(%rdi) + adcq $0, %r9 + # a[i+10] += m[10] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 80(%rsi) + movq 80(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 80(%rdi) + adcq $0, %r10 + # a[i+11] += m[11] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 88(%rsi) + movq 88(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 88(%rdi) + adcq $0, %r9 + # a[i+12] += m[12] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 96(%rsi) + movq 96(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 96(%rdi) + adcq $0, %r10 + # a[i+13] += m[13] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 104(%rsi) + movq 104(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 104(%rdi) + adcq $0, %r9 + # a[i+14] += m[14] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 112(%rsi) + movq 112(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 112(%rdi) + adcq $0, %r10 + # a[i+15] += m[15] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 120(%rsi) + movq 120(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 120(%rdi) + adcq $0, %r9 + # a[i+16] += m[16] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 128(%rsi) + movq 128(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 128(%rdi) + adcq $0, %r10 + # a[i+17] += m[17] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 136(%rsi) + movq 136(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 136(%rdi) + adcq $0, %r9 + # a[i+18] += m[18] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 144(%rsi) + movq 144(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 144(%rdi) + adcq $0, %r10 + # a[i+19] += m[19] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 152(%rsi) + movq 152(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 152(%rdi) + adcq $0, %r9 + # a[i+20] += m[20] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 160(%rsi) + movq 160(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 160(%rdi) + adcq $0, %r10 + # a[i+21] += m[21] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 168(%rsi) + movq 168(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 168(%rdi) + adcq $0, %r9 + # a[i+22] += m[22] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 176(%rsi) + movq 176(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 176(%rdi) + adcq $0, %r10 + # a[i+23] += m[23] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 184(%rsi) + movq 184(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 184(%rdi) + adcq $0, %r9 + # a[i+24] += m[24] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 192(%rsi) + movq 192(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 192(%rdi) + adcq $0, %r10 + # a[i+25] += m[25] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 200(%rsi) + movq 200(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 200(%rdi) + adcq $0, %r9 + # a[i+26] += m[26] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 208(%rsi) + movq 208(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 208(%rdi) + adcq $0, %r10 + # a[i+27] += m[27] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 216(%rsi) + movq 216(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 216(%rdi) + adcq $0, %r9 + # a[i+28] += m[28] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 224(%rsi) + movq 224(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 224(%rdi) + adcq $0, %r10 + # a[i+29] += m[29] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 232(%rsi) + movq 232(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 232(%rdi) + adcq $0, %r9 + # a[i+30] += m[30] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 240(%rsi) + movq 240(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 240(%rdi) + adcq $0, %r10 + # a[i+31] += m[31] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 248(%rsi) + movq 248(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 248(%rdi) + adcq $0, %r9 + # a[i+32] += m[32] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 256(%rsi) + movq 256(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 256(%rdi) + adcq $0, %r10 + # a[i+33] += m[33] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 264(%rsi) + movq 264(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 264(%rdi) + adcq $0, %r9 + # a[i+34] += m[34] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 272(%rsi) + movq 272(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 272(%rdi) + adcq $0, %r10 + # a[i+35] += m[35] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 280(%rsi) + movq 280(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 280(%rdi) + adcq $0, %r9 + # a[i+36] += m[36] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 288(%rsi) + movq 288(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 288(%rdi) + adcq $0, %r10 + # a[i+37] += m[37] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 296(%rsi) + movq 296(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 296(%rdi) + adcq $0, %r9 + # a[i+38] += m[38] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 304(%rsi) + movq 304(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 304(%rdi) + adcq $0, %r10 + # a[i+39] += m[39] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 312(%rsi) + movq 312(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 312(%rdi) + adcq $0, %r9 + # a[i+40] += m[40] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 320(%rsi) + movq 320(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 320(%rdi) + adcq $0, %r10 + # a[i+41] += m[41] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 328(%rsi) + movq 328(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 328(%rdi) + adcq $0, %r9 + # a[i+42] += m[42] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 336(%rsi) + movq 336(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 336(%rdi) + adcq $0, %r10 + # a[i+43] += m[43] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 344(%rsi) + movq 344(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 344(%rdi) + adcq $0, %r9 + # a[i+44] += m[44] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 352(%rsi) + movq 352(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 352(%rdi) + adcq $0, %r10 + # a[i+45] += m[45] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 360(%rsi) + movq 360(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 360(%rdi) + adcq $0, %r9 + # a[i+46] += m[46] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 368(%rsi) + movq 368(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 368(%rdi) + adcq $0, %r10 + # a[i+47] += m[47] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 376(%rsi) + movq 376(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 376(%rdi) + adcq $0, %r9 + # a[i+48] += m[48] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 384(%rsi) + movq 384(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 384(%rdi) + adcq $0, %r10 + # a[i+49] += m[49] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 392(%rsi) + movq 392(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 392(%rdi) + adcq $0, %r9 + # a[i+50] += m[50] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 400(%rsi) + movq 400(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 400(%rdi) + adcq $0, %r10 + # a[i+51] += m[51] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 408(%rsi) + movq 408(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 408(%rdi) + adcq $0, %r9 + # a[i+52] += m[52] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 416(%rsi) + movq 416(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 416(%rdi) + adcq $0, %r10 + # a[i+53] += m[53] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 424(%rsi) + movq 424(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 424(%rdi) + adcq $0, %r9 + # a[i+54] += m[54] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 432(%rsi) + movq 432(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 432(%rdi) + adcq $0, %r10 + # a[i+55] += m[55] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 440(%rsi) + movq 440(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 440(%rdi) + adcq $0, %r9 + # a[i+56] += m[56] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 448(%rsi) + movq 448(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 448(%rdi) + adcq $0, %r10 + # a[i+57] += m[57] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 456(%rsi) + movq 456(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 456(%rdi) + adcq $0, %r9 + # a[i+58] += m[58] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 464(%rsi) + movq 464(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 464(%rdi) + adcq $0, %r10 + # a[i+59] += m[59] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 472(%rsi) + movq 472(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 472(%rdi) + adcq $0, %r9 + # a[i+60] += m[60] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 480(%rsi) + movq 480(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 480(%rdi) + adcq $0, %r10 + # a[i+61] += m[61] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 488(%rsi) + movq 488(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 488(%rdi) + adcq $0, %r9 + # a[i+62] += m[62] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 496(%rsi) + movq 496(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 496(%rdi) + adcq $0, %r10 + # a[i+63] += m[63] * mu + movq %r11, %rax + mulq 504(%rsi) + movq 504(%rdi), %r12 + addq %rax, %r10 + adcq %r15, %rdx + movq $0, %r15 + adcq $0, %r15 + addq %r10, %r12 + movq %r12, 504(%rdi) + adcq %rdx, 512(%rdi) + adcq $0, %r15 + # i -= 1 + addq $8, %rdi + decq %r8 + jnz L_mont_loop_64 + movq %r13, (%rdi) + movq %r14, 8(%rdi) + negq %r15 + movq %r15, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + subq $512, %rdi +#ifndef __APPLE__ + callq sp_4096_cond_sub_64@plt +#else + callq _sp_4096_cond_sub_64 +#endif /* __APPLE__ */ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_4096_mont_reduce_64,.-sp_4096_mont_reduce_64 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_4096_cond_sub_avx2_64 +.type sp_4096_cond_sub_avx2_64,@function +.align 16 +sp_4096_cond_sub_avx2_64: +#else +.globl _sp_4096_cond_sub_avx2_64 +.p2align 4 +_sp_4096_cond_sub_avx2_64: +#endif /* __APPLE__ */ + movq $0, %rax + movq (%rdx), %r10 + movq (%rsi), %r8 + pextq %rcx, %r10, %r10 + subq %r10, %r8 + movq 8(%rdx), %r10 + movq 8(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, (%rdi) + sbbq %r10, %r9 + movq 16(%rdx), %r8 + movq 16(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 8(%rdi) + sbbq %r8, %r10 + movq 24(%rdx), %r9 + movq 24(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 16(%rdi) + sbbq %r9, %r8 + movq 32(%rdx), %r10 + movq 32(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 24(%rdi) + sbbq %r10, %r9 + movq 40(%rdx), %r8 + movq 40(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 32(%rdi) + sbbq %r8, %r10 + movq 48(%rdx), %r9 + movq 48(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 40(%rdi) + sbbq %r9, %r8 + movq 56(%rdx), %r10 + movq 56(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 48(%rdi) + sbbq %r10, %r9 + movq 64(%rdx), %r8 + movq 64(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 56(%rdi) + sbbq %r8, %r10 + movq 72(%rdx), %r9 + movq 72(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 64(%rdi) + sbbq %r9, %r8 + movq 80(%rdx), %r10 + movq 80(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 72(%rdi) + sbbq %r10, %r9 + movq 88(%rdx), %r8 + movq 88(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 80(%rdi) + sbbq %r8, %r10 + movq 96(%rdx), %r9 + movq 96(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 88(%rdi) + sbbq %r9, %r8 + movq 104(%rdx), %r10 + movq 104(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 96(%rdi) + sbbq %r10, %r9 + movq 112(%rdx), %r8 + movq 112(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 104(%rdi) + sbbq %r8, %r10 + movq 120(%rdx), %r9 + movq 120(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 112(%rdi) + sbbq %r9, %r8 + movq 128(%rdx), %r10 + movq 128(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 120(%rdi) + sbbq %r10, %r9 + movq 136(%rdx), %r8 + movq 136(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 128(%rdi) + sbbq %r8, %r10 + movq 144(%rdx), %r9 + movq 144(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 136(%rdi) + sbbq %r9, %r8 + movq 152(%rdx), %r10 + movq 152(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 144(%rdi) + sbbq %r10, %r9 + movq 160(%rdx), %r8 + movq 160(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 152(%rdi) + sbbq %r8, %r10 + movq 168(%rdx), %r9 + movq 168(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 160(%rdi) + sbbq %r9, %r8 + movq 176(%rdx), %r10 + movq 176(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 168(%rdi) + sbbq %r10, %r9 + movq 184(%rdx), %r8 + movq 184(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 176(%rdi) + sbbq %r8, %r10 + movq 192(%rdx), %r9 + movq 192(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 184(%rdi) + sbbq %r9, %r8 + movq 200(%rdx), %r10 + movq 200(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 192(%rdi) + sbbq %r10, %r9 + movq 208(%rdx), %r8 + movq 208(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 200(%rdi) + sbbq %r8, %r10 + movq 216(%rdx), %r9 + movq 216(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 208(%rdi) + sbbq %r9, %r8 + movq 224(%rdx), %r10 + movq 224(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 216(%rdi) + sbbq %r10, %r9 + movq 232(%rdx), %r8 + movq 232(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 224(%rdi) + sbbq %r8, %r10 + movq 240(%rdx), %r9 + movq 240(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 232(%rdi) + sbbq %r9, %r8 + movq 248(%rdx), %r10 + movq 248(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 240(%rdi) + sbbq %r10, %r9 + movq 256(%rdx), %r8 + movq 256(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 248(%rdi) + sbbq %r8, %r10 + movq 264(%rdx), %r9 + movq 264(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 256(%rdi) + sbbq %r9, %r8 + movq 272(%rdx), %r10 + movq 272(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 264(%rdi) + sbbq %r10, %r9 + movq 280(%rdx), %r8 + movq 280(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 272(%rdi) + sbbq %r8, %r10 + movq 288(%rdx), %r9 + movq 288(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 280(%rdi) + sbbq %r9, %r8 + movq 296(%rdx), %r10 + movq 296(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 288(%rdi) + sbbq %r10, %r9 + movq 304(%rdx), %r8 + movq 304(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 296(%rdi) + sbbq %r8, %r10 + movq 312(%rdx), %r9 + movq 312(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 304(%rdi) + sbbq %r9, %r8 + movq 320(%rdx), %r10 + movq 320(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 312(%rdi) + sbbq %r10, %r9 + movq 328(%rdx), %r8 + movq 328(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 320(%rdi) + sbbq %r8, %r10 + movq 336(%rdx), %r9 + movq 336(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 328(%rdi) + sbbq %r9, %r8 + movq 344(%rdx), %r10 + movq 344(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 336(%rdi) + sbbq %r10, %r9 + movq 352(%rdx), %r8 + movq 352(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 344(%rdi) + sbbq %r8, %r10 + movq 360(%rdx), %r9 + movq 360(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 352(%rdi) + sbbq %r9, %r8 + movq 368(%rdx), %r10 + movq 368(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 360(%rdi) + sbbq %r10, %r9 + movq 376(%rdx), %r8 + movq 376(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 368(%rdi) + sbbq %r8, %r10 + movq 384(%rdx), %r9 + movq 384(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 376(%rdi) + sbbq %r9, %r8 + movq 392(%rdx), %r10 + movq 392(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 384(%rdi) + sbbq %r10, %r9 + movq 400(%rdx), %r8 + movq 400(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 392(%rdi) + sbbq %r8, %r10 + movq 408(%rdx), %r9 + movq 408(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 400(%rdi) + sbbq %r9, %r8 + movq 416(%rdx), %r10 + movq 416(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 408(%rdi) + sbbq %r10, %r9 + movq 424(%rdx), %r8 + movq 424(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 416(%rdi) + sbbq %r8, %r10 + movq 432(%rdx), %r9 + movq 432(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 424(%rdi) + sbbq %r9, %r8 + movq 440(%rdx), %r10 + movq 440(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 432(%rdi) + sbbq %r10, %r9 + movq 448(%rdx), %r8 + movq 448(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 440(%rdi) + sbbq %r8, %r10 + movq 456(%rdx), %r9 + movq 456(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 448(%rdi) + sbbq %r9, %r8 + movq 464(%rdx), %r10 + movq 464(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 456(%rdi) + sbbq %r10, %r9 + movq 472(%rdx), %r8 + movq 472(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 464(%rdi) + sbbq %r8, %r10 + movq 480(%rdx), %r9 + movq 480(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 472(%rdi) + sbbq %r9, %r8 + movq 488(%rdx), %r10 + movq 488(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 480(%rdi) + sbbq %r10, %r9 + movq 496(%rdx), %r8 + movq 496(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 488(%rdi) + sbbq %r8, %r10 + movq 504(%rdx), %r9 + movq 504(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 496(%rdi) + sbbq %r9, %r8 + movq %r8, 504(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_4096_cond_sub_avx2_64,.-sp_4096_cond_sub_avx2_64 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* 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. + */ +#ifndef __APPLE__ +.globl sp_4096_mul_d_avx2_64 +.type sp_4096_mul_d_avx2_64,@function +.align 16 +sp_4096_mul_d_avx2_64: +#else +.globl _sp_4096_mul_d_avx2_64 +.p2align 4 +_sp_4096_mul_d_avx2_64: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 8(%rdi) + adoxq %r8, %r9 + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 16(%rdi) + adoxq %r8, %r10 + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 24(%rdi) + adoxq %r8, %r9 + # A[4] * B + mulxq 32(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 32(%rdi) + adoxq %r8, %r10 + # A[5] * B + mulxq 40(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 40(%rdi) + adoxq %r8, %r9 + # A[6] * B + mulxq 48(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 48(%rdi) + adoxq %r8, %r10 + # A[7] * B + mulxq 56(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 56(%rdi) + adoxq %r8, %r9 + # A[8] * B + mulxq 64(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 64(%rdi) + adoxq %r8, %r10 + # A[9] * B + mulxq 72(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 72(%rdi) + adoxq %r8, %r9 + # A[10] * B + mulxq 80(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 80(%rdi) + adoxq %r8, %r10 + # A[11] * B + mulxq 88(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 88(%rdi) + adoxq %r8, %r9 + # A[12] * B + mulxq 96(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 96(%rdi) + adoxq %r8, %r10 + # A[13] * B + mulxq 104(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 104(%rdi) + adoxq %r8, %r9 + # A[14] * B + mulxq 112(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 112(%rdi) + adoxq %r8, %r10 + # A[15] * B + mulxq 120(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 120(%rdi) + adoxq %r8, %r9 + # A[16] * B + mulxq 128(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 128(%rdi) + adoxq %r8, %r10 + # A[17] * B + mulxq 136(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 136(%rdi) + adoxq %r8, %r9 + # A[18] * B + mulxq 144(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 144(%rdi) + adoxq %r8, %r10 + # A[19] * B + mulxq 152(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 152(%rdi) + adoxq %r8, %r9 + # A[20] * B + mulxq 160(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 160(%rdi) + adoxq %r8, %r10 + # A[21] * B + mulxq 168(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 168(%rdi) + adoxq %r8, %r9 + # A[22] * B + mulxq 176(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 176(%rdi) + adoxq %r8, %r10 + # A[23] * B + mulxq 184(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 184(%rdi) + adoxq %r8, %r9 + # A[24] * B + mulxq 192(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 192(%rdi) + adoxq %r8, %r10 + # A[25] * B + mulxq 200(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 200(%rdi) + adoxq %r8, %r9 + # A[26] * B + mulxq 208(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 208(%rdi) + adoxq %r8, %r10 + # A[27] * B + mulxq 216(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 216(%rdi) + adoxq %r8, %r9 + # A[28] * B + mulxq 224(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 224(%rdi) + adoxq %r8, %r10 + # A[29] * B + mulxq 232(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 232(%rdi) + adoxq %r8, %r9 + # A[30] * B + mulxq 240(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 240(%rdi) + adoxq %r8, %r10 + # A[31] * B + mulxq 248(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 248(%rdi) + adoxq %r8, %r9 + # A[32] * B + mulxq 256(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 256(%rdi) + adoxq %r8, %r10 + # A[33] * B + mulxq 264(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 264(%rdi) + adoxq %r8, %r9 + # A[34] * B + mulxq 272(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 272(%rdi) + adoxq %r8, %r10 + # A[35] * B + mulxq 280(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 280(%rdi) + adoxq %r8, %r9 + # A[36] * B + mulxq 288(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 288(%rdi) + adoxq %r8, %r10 + # A[37] * B + mulxq 296(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 296(%rdi) + adoxq %r8, %r9 + # A[38] * B + mulxq 304(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 304(%rdi) + adoxq %r8, %r10 + # A[39] * B + mulxq 312(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 312(%rdi) + adoxq %r8, %r9 + # A[40] * B + mulxq 320(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 320(%rdi) + adoxq %r8, %r10 + # A[41] * B + mulxq 328(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 328(%rdi) + adoxq %r8, %r9 + # A[42] * B + mulxq 336(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 336(%rdi) + adoxq %r8, %r10 + # A[43] * B + mulxq 344(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 344(%rdi) + adoxq %r8, %r9 + # A[44] * B + mulxq 352(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 352(%rdi) + adoxq %r8, %r10 + # A[45] * B + mulxq 360(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 360(%rdi) + adoxq %r8, %r9 + # A[46] * B + mulxq 368(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 368(%rdi) + adoxq %r8, %r10 + # A[47] * B + mulxq 376(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 376(%rdi) + adoxq %r8, %r9 + # A[48] * B + mulxq 384(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 384(%rdi) + adoxq %r8, %r10 + # A[49] * B + mulxq 392(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 392(%rdi) + adoxq %r8, %r9 + # A[50] * B + mulxq 400(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 400(%rdi) + adoxq %r8, %r10 + # A[51] * B + mulxq 408(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 408(%rdi) + adoxq %r8, %r9 + # A[52] * B + mulxq 416(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 416(%rdi) + adoxq %r8, %r10 + # A[53] * B + mulxq 424(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 424(%rdi) + adoxq %r8, %r9 + # A[54] * B + mulxq 432(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 432(%rdi) + adoxq %r8, %r10 + # A[55] * B + mulxq 440(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 440(%rdi) + adoxq %r8, %r9 + # A[56] * B + mulxq 448(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 448(%rdi) + adoxq %r8, %r10 + # A[57] * B + mulxq 456(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 456(%rdi) + adoxq %r8, %r9 + # A[58] * B + mulxq 464(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 464(%rdi) + adoxq %r8, %r10 + # A[59] * B + mulxq 472(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 472(%rdi) + adoxq %r8, %r9 + # A[60] * B + mulxq 480(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 480(%rdi) + adoxq %r8, %r10 + # A[61] * B + mulxq 488(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 488(%rdi) + adoxq %r8, %r9 + # A[62] * B + mulxq 496(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 496(%rdi) + adoxq %r8, %r10 + # A[63] * B + mulxq 504(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 504(%rdi) + movq %r9, 512(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_4096_mul_d_avx2_64,.-sp_4096_mul_d_avx2_64 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_4096_cmp_64 +.type sp_4096_cmp_64,@function +.align 16 +sp_4096_cmp_64: +#else +.globl _sp_4096_cmp_64 +.p2align 4 +_sp_4096_cmp_64: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $1, %r8 + movq 504(%rdi), %r9 + movq 504(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 496(%rdi), %r9 + movq 496(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 488(%rdi), %r9 + movq 488(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 480(%rdi), %r9 + movq 480(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 472(%rdi), %r9 + movq 472(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 464(%rdi), %r9 + movq 464(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 456(%rdi), %r9 + movq 456(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 448(%rdi), %r9 + movq 448(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 440(%rdi), %r9 + movq 440(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 432(%rdi), %r9 + movq 432(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 424(%rdi), %r9 + movq 424(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 416(%rdi), %r9 + movq 416(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 408(%rdi), %r9 + movq 408(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 400(%rdi), %r9 + movq 400(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 392(%rdi), %r9 + movq 392(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 384(%rdi), %r9 + movq 384(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 376(%rdi), %r9 + movq 376(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 368(%rdi), %r9 + movq 368(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 360(%rdi), %r9 + movq 360(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 352(%rdi), %r9 + movq 352(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 344(%rdi), %r9 + movq 344(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 336(%rdi), %r9 + movq 336(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 328(%rdi), %r9 + movq 328(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 320(%rdi), %r9 + movq 320(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 312(%rdi), %r9 + movq 312(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 304(%rdi), %r9 + movq 304(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 296(%rdi), %r9 + movq 296(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 288(%rdi), %r9 + movq 288(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 280(%rdi), %r9 + movq 280(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 272(%rdi), %r9 + movq 272(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 264(%rdi), %r9 + movq 264(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 256(%rdi), %r9 + movq 256(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 248(%rdi), %r9 + movq 248(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 240(%rdi), %r9 + movq 240(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 232(%rdi), %r9 + movq 232(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 224(%rdi), %r9 + movq 224(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 216(%rdi), %r9 + movq 216(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 208(%rdi), %r9 + movq 208(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 200(%rdi), %r9 + movq 200(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 192(%rdi), %r9 + movq 192(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 184(%rdi), %r9 + movq 184(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 176(%rdi), %r9 + movq 176(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 168(%rdi), %r9 + movq 168(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 160(%rdi), %r9 + movq 160(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 152(%rdi), %r9 + movq 152(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 144(%rdi), %r9 + movq 144(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 136(%rdi), %r9 + movq 136(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 128(%rdi), %r9 + movq 128(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 120(%rdi), %r9 + movq 120(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 112(%rdi), %r9 + movq 112(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 104(%rdi), %r9 + movq 104(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 96(%rdi), %r9 + movq 96(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 88(%rdi), %r9 + movq 88(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 80(%rdi), %r9 + movq 80(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 72(%rdi), %r9 + movq 72(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 64(%rdi), %r9 + movq 64(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 56(%rdi), %r9 + movq 56(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 48(%rdi), %r9 + movq 48(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 40(%rdi), %r9 + movq 40(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 32(%rdi), %r9 + movq 32(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_4096_cmp_64,.-sp_4096_cmp_64 +#endif /* __APPLE__ */ +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_4096_sub_64 +.type sp_4096_sub_64,@function +.align 16 +sp_4096_sub_64: +#else +.globl _sp_4096_sub_64 +.p2align 4 +_sp_4096_sub_64: +#endif /* __APPLE__ */ + movq (%rsi), %rcx + xorq %rax, %rax + subq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + sbbq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + sbbq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + sbbq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + sbbq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + sbbq 40(%rdx), %r8 + movq 48(%rsi), %rcx + movq %r8, 40(%rdi) + sbbq 48(%rdx), %rcx + movq 56(%rsi), %r8 + movq %rcx, 48(%rdi) + sbbq 56(%rdx), %r8 + movq 64(%rsi), %rcx + movq %r8, 56(%rdi) + sbbq 64(%rdx), %rcx + movq 72(%rsi), %r8 + movq %rcx, 64(%rdi) + sbbq 72(%rdx), %r8 + movq 80(%rsi), %rcx + movq %r8, 72(%rdi) + sbbq 80(%rdx), %rcx + movq 88(%rsi), %r8 + movq %rcx, 80(%rdi) + sbbq 88(%rdx), %r8 + movq 96(%rsi), %rcx + movq %r8, 88(%rdi) + sbbq 96(%rdx), %rcx + movq 104(%rsi), %r8 + movq %rcx, 96(%rdi) + sbbq 104(%rdx), %r8 + movq 112(%rsi), %rcx + movq %r8, 104(%rdi) + sbbq 112(%rdx), %rcx + movq 120(%rsi), %r8 + movq %rcx, 112(%rdi) + sbbq 120(%rdx), %r8 + movq 128(%rsi), %rcx + movq %r8, 120(%rdi) + sbbq 128(%rdx), %rcx + movq 136(%rsi), %r8 + movq %rcx, 128(%rdi) + sbbq 136(%rdx), %r8 + movq 144(%rsi), %rcx + movq %r8, 136(%rdi) + sbbq 144(%rdx), %rcx + movq 152(%rsi), %r8 + movq %rcx, 144(%rdi) + sbbq 152(%rdx), %r8 + movq 160(%rsi), %rcx + movq %r8, 152(%rdi) + sbbq 160(%rdx), %rcx + movq 168(%rsi), %r8 + movq %rcx, 160(%rdi) + sbbq 168(%rdx), %r8 + movq 176(%rsi), %rcx + movq %r8, 168(%rdi) + sbbq 176(%rdx), %rcx + movq 184(%rsi), %r8 + movq %rcx, 176(%rdi) + sbbq 184(%rdx), %r8 + movq 192(%rsi), %rcx + movq %r8, 184(%rdi) + sbbq 192(%rdx), %rcx + movq 200(%rsi), %r8 + movq %rcx, 192(%rdi) + sbbq 200(%rdx), %r8 + movq 208(%rsi), %rcx + movq %r8, 200(%rdi) + sbbq 208(%rdx), %rcx + movq 216(%rsi), %r8 + movq %rcx, 208(%rdi) + sbbq 216(%rdx), %r8 + movq 224(%rsi), %rcx + movq %r8, 216(%rdi) + sbbq 224(%rdx), %rcx + movq 232(%rsi), %r8 + movq %rcx, 224(%rdi) + sbbq 232(%rdx), %r8 + movq 240(%rsi), %rcx + movq %r8, 232(%rdi) + sbbq 240(%rdx), %rcx + movq 248(%rsi), %r8 + movq %rcx, 240(%rdi) + sbbq 248(%rdx), %r8 + movq 256(%rsi), %rcx + movq %r8, 248(%rdi) + sbbq 256(%rdx), %rcx + movq 264(%rsi), %r8 + movq %rcx, 256(%rdi) + sbbq 264(%rdx), %r8 + movq 272(%rsi), %rcx + movq %r8, 264(%rdi) + sbbq 272(%rdx), %rcx + movq 280(%rsi), %r8 + movq %rcx, 272(%rdi) + sbbq 280(%rdx), %r8 + movq 288(%rsi), %rcx + movq %r8, 280(%rdi) + sbbq 288(%rdx), %rcx + movq 296(%rsi), %r8 + movq %rcx, 288(%rdi) + sbbq 296(%rdx), %r8 + movq 304(%rsi), %rcx + movq %r8, 296(%rdi) + sbbq 304(%rdx), %rcx + movq 312(%rsi), %r8 + movq %rcx, 304(%rdi) + sbbq 312(%rdx), %r8 + movq 320(%rsi), %rcx + movq %r8, 312(%rdi) + sbbq 320(%rdx), %rcx + movq 328(%rsi), %r8 + movq %rcx, 320(%rdi) + sbbq 328(%rdx), %r8 + movq 336(%rsi), %rcx + movq %r8, 328(%rdi) + sbbq 336(%rdx), %rcx + movq 344(%rsi), %r8 + movq %rcx, 336(%rdi) + sbbq 344(%rdx), %r8 + movq 352(%rsi), %rcx + movq %r8, 344(%rdi) + sbbq 352(%rdx), %rcx + movq 360(%rsi), %r8 + movq %rcx, 352(%rdi) + sbbq 360(%rdx), %r8 + movq 368(%rsi), %rcx + movq %r8, 360(%rdi) + sbbq 368(%rdx), %rcx + movq 376(%rsi), %r8 + movq %rcx, 368(%rdi) + sbbq 376(%rdx), %r8 + movq 384(%rsi), %rcx + movq %r8, 376(%rdi) + sbbq 384(%rdx), %rcx + movq 392(%rsi), %r8 + movq %rcx, 384(%rdi) + sbbq 392(%rdx), %r8 + movq 400(%rsi), %rcx + movq %r8, 392(%rdi) + sbbq 400(%rdx), %rcx + movq 408(%rsi), %r8 + movq %rcx, 400(%rdi) + sbbq 408(%rdx), %r8 + movq 416(%rsi), %rcx + movq %r8, 408(%rdi) + sbbq 416(%rdx), %rcx + movq 424(%rsi), %r8 + movq %rcx, 416(%rdi) + sbbq 424(%rdx), %r8 + movq 432(%rsi), %rcx + movq %r8, 424(%rdi) + sbbq 432(%rdx), %rcx + movq 440(%rsi), %r8 + movq %rcx, 432(%rdi) + sbbq 440(%rdx), %r8 + movq 448(%rsi), %rcx + movq %r8, 440(%rdi) + sbbq 448(%rdx), %rcx + movq 456(%rsi), %r8 + movq %rcx, 448(%rdi) + sbbq 456(%rdx), %r8 + movq 464(%rsi), %rcx + movq %r8, 456(%rdi) + sbbq 464(%rdx), %rcx + movq 472(%rsi), %r8 + movq %rcx, 464(%rdi) + sbbq 472(%rdx), %r8 + movq 480(%rsi), %rcx + movq %r8, 472(%rdi) + sbbq 480(%rdx), %rcx + movq 488(%rsi), %r8 + movq %rcx, 480(%rdi) + sbbq 488(%rdx), %r8 + movq 496(%rsi), %rcx + movq %r8, 488(%rdi) + sbbq 496(%rdx), %rcx + movq 504(%rsi), %r8 + movq %rcx, 496(%rdi) + sbbq 504(%rdx), %r8 + movq %r8, 504(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_4096_sub_64,.-sp_4096_sub_64 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Reduce the number back to 4096 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. + */ +#ifndef __APPLE__ +.globl sp_4096_mont_reduce_avx2_64 +.type sp_4096_mont_reduce_avx2_64,@function +.align 16 +sp_4096_mont_reduce_avx2_64: +#else +.globl _sp_4096_mont_reduce_avx2_64 +.p2align 4 +_sp_4096_mont_reduce_avx2_64: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + movq %rdx, %r8 + xorq %r14, %r14 + # i = 64 + movq $64, %r9 + movq (%rdi), %r13 + addq $256, %rdi + xorq %r12, %r12 +L_mont_loop_avx2_64: + # mu = a[i] * mp + movq %r13, %rdx + movq %r13, %r10 + imulq %r8, %rdx + xorq %r12, %r12 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rax, %rcx + movq -248(%rdi), %r13 + adcxq %rax, %r10 + adoxq %rcx, %r13 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rax, %rcx + movq -240(%rdi), %r10 + adcxq %rax, %r13 + adoxq %rcx, %r10 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rax, %rcx + movq -232(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -240(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rax, %rcx + movq -224(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -232(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rax, %rcx + movq -216(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -224(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rax, %rcx + movq -208(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -216(%rdi) + # a[i+6] += m[6] * mu + mulxq 48(%rsi), %rax, %rcx + movq -200(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -208(%rdi) + # a[i+7] += m[7] * mu + mulxq 56(%rsi), %rax, %rcx + movq -192(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -200(%rdi) + # a[i+8] += m[8] * mu + mulxq 64(%rsi), %rax, %rcx + movq -184(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -192(%rdi) + # a[i+9] += m[9] * mu + mulxq 72(%rsi), %rax, %rcx + movq -176(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -184(%rdi) + # a[i+10] += m[10] * mu + mulxq 80(%rsi), %rax, %rcx + movq -168(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -176(%rdi) + # a[i+11] += m[11] * mu + mulxq 88(%rsi), %rax, %rcx + movq -160(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -168(%rdi) + # a[i+12] += m[12] * mu + mulxq 96(%rsi), %rax, %rcx + movq -152(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -160(%rdi) + # a[i+13] += m[13] * mu + mulxq 104(%rsi), %rax, %rcx + movq -144(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -152(%rdi) + # a[i+14] += m[14] * mu + mulxq 112(%rsi), %rax, %rcx + movq -136(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -144(%rdi) + # a[i+15] += m[15] * mu + mulxq 120(%rsi), %rax, %rcx + movq -128(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -136(%rdi) + # a[i+16] += m[16] * mu + mulxq 128(%rsi), %rax, %rcx + movq -120(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -128(%rdi) + # a[i+17] += m[17] * mu + mulxq 136(%rsi), %rax, %rcx + movq -112(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -120(%rdi) + # a[i+18] += m[18] * mu + mulxq 144(%rsi), %rax, %rcx + movq -104(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -112(%rdi) + # a[i+19] += m[19] * mu + mulxq 152(%rsi), %rax, %rcx + movq -96(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -104(%rdi) + # a[i+20] += m[20] * mu + mulxq 160(%rsi), %rax, %rcx + movq -88(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -96(%rdi) + # a[i+21] += m[21] * mu + mulxq 168(%rsi), %rax, %rcx + movq -80(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -88(%rdi) + # a[i+22] += m[22] * mu + mulxq 176(%rsi), %rax, %rcx + movq -72(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -80(%rdi) + # a[i+23] += m[23] * mu + mulxq 184(%rsi), %rax, %rcx + movq -64(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -72(%rdi) + # a[i+24] += m[24] * mu + mulxq 192(%rsi), %rax, %rcx + movq -56(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -64(%rdi) + # a[i+25] += m[25] * mu + mulxq 200(%rsi), %rax, %rcx + movq -48(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -56(%rdi) + # a[i+26] += m[26] * mu + mulxq 208(%rsi), %rax, %rcx + movq -40(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -48(%rdi) + # a[i+27] += m[27] * mu + mulxq 216(%rsi), %rax, %rcx + movq -32(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -40(%rdi) + # a[i+28] += m[28] * mu + mulxq 224(%rsi), %rax, %rcx + movq -24(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -32(%rdi) + # a[i+29] += m[29] * mu + mulxq 232(%rsi), %rax, %rcx + movq -16(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -24(%rdi) + # a[i+30] += m[30] * mu + mulxq 240(%rsi), %rax, %rcx + movq -8(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, -16(%rdi) + # a[i+31] += m[31] * mu + mulxq 248(%rsi), %rax, %rcx + movq (%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, -8(%rdi) + # a[i+32] += m[32] * mu + mulxq 256(%rsi), %rax, %rcx + movq 8(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, (%rdi) + # a[i+33] += m[33] * mu + mulxq 264(%rsi), %rax, %rcx + movq 16(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 8(%rdi) + # a[i+34] += m[34] * mu + mulxq 272(%rsi), %rax, %rcx + movq 24(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 16(%rdi) + # a[i+35] += m[35] * mu + mulxq 280(%rsi), %rax, %rcx + movq 32(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 24(%rdi) + # a[i+36] += m[36] * mu + mulxq 288(%rsi), %rax, %rcx + movq 40(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 32(%rdi) + # a[i+37] += m[37] * mu + mulxq 296(%rsi), %rax, %rcx + movq 48(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 40(%rdi) + # a[i+38] += m[38] * mu + mulxq 304(%rsi), %rax, %rcx + movq 56(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 48(%rdi) + # a[i+39] += m[39] * mu + mulxq 312(%rsi), %rax, %rcx + movq 64(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 56(%rdi) + # a[i+40] += m[40] * mu + mulxq 320(%rsi), %rax, %rcx + movq 72(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 64(%rdi) + # a[i+41] += m[41] * mu + mulxq 328(%rsi), %rax, %rcx + movq 80(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 72(%rdi) + # a[i+42] += m[42] * mu + mulxq 336(%rsi), %rax, %rcx + movq 88(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 80(%rdi) + # a[i+43] += m[43] * mu + mulxq 344(%rsi), %rax, %rcx + movq 96(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 88(%rdi) + # a[i+44] += m[44] * mu + mulxq 352(%rsi), %rax, %rcx + movq 104(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rdi) + # a[i+45] += m[45] * mu + mulxq 360(%rsi), %rax, %rcx + movq 112(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 104(%rdi) + # a[i+46] += m[46] * mu + mulxq 368(%rsi), %rax, %rcx + movq 120(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 112(%rdi) + # a[i+47] += m[47] * mu + mulxq 376(%rsi), %rax, %rcx + movq 128(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 120(%rdi) + # a[i+48] += m[48] * mu + mulxq 384(%rsi), %rax, %rcx + movq 136(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 128(%rdi) + # a[i+49] += m[49] * mu + mulxq 392(%rsi), %rax, %rcx + movq 144(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 136(%rdi) + # a[i+50] += m[50] * mu + mulxq 400(%rsi), %rax, %rcx + movq 152(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 144(%rdi) + # a[i+51] += m[51] * mu + mulxq 408(%rsi), %rax, %rcx + movq 160(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 152(%rdi) + # a[i+52] += m[52] * mu + mulxq 416(%rsi), %rax, %rcx + movq 168(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 160(%rdi) + # a[i+53] += m[53] * mu + mulxq 424(%rsi), %rax, %rcx + movq 176(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 168(%rdi) + # a[i+54] += m[54] * mu + mulxq 432(%rsi), %rax, %rcx + movq 184(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 176(%rdi) + # a[i+55] += m[55] * mu + mulxq 440(%rsi), %rax, %rcx + movq 192(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 184(%rdi) + # a[i+56] += m[56] * mu + mulxq 448(%rsi), %rax, %rcx + movq 200(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 192(%rdi) + # a[i+57] += m[57] * mu + mulxq 456(%rsi), %rax, %rcx + movq 208(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 200(%rdi) + # a[i+58] += m[58] * mu + mulxq 464(%rsi), %rax, %rcx + movq 216(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 208(%rdi) + # a[i+59] += m[59] * mu + mulxq 472(%rsi), %rax, %rcx + movq 224(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 216(%rdi) + # a[i+60] += m[60] * mu + mulxq 480(%rsi), %rax, %rcx + movq 232(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 224(%rdi) + # a[i+61] += m[61] * mu + mulxq 488(%rsi), %rax, %rcx + movq 240(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 232(%rdi) + # a[i+62] += m[62] * mu + mulxq 496(%rsi), %rax, %rcx + movq 248(%rdi), %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 240(%rdi) + # a[i+63] += m[63] * mu + mulxq 504(%rsi), %rax, %rcx + movq 256(%rdi), %r10 + adcxq %rax, %r11 + adoxq %rcx, %r10 + movq %r11, 248(%rdi) + adcxq %r14, %r10 + movq %r10, 256(%rdi) + movq %r12, %r14 + adoxq %r12, %r14 + adcxq %r12, %r14 + # a += 1 + addq $8, %rdi + # i -= 1 + subq $1, %r9 + jnz L_mont_loop_avx2_64 + subq $256, %rdi + negq %r14 + movq %rdi, %r8 + subq $512, %rdi + movq (%rsi), %rcx + movq %r13, %rdx + pextq %r14, %rcx, %rcx + subq %rcx, %rdx + movq 8(%rsi), %rcx + movq 8(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, (%rdi) + sbbq %rcx, %rax + movq 16(%rsi), %rdx + movq 16(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 8(%rdi) + sbbq %rdx, %rcx + movq 24(%rsi), %rax + movq 24(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 16(%rdi) + sbbq %rax, %rdx + movq 32(%rsi), %rcx + movq 32(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 24(%rdi) + sbbq %rcx, %rax + movq 40(%rsi), %rdx + movq 40(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 32(%rdi) + sbbq %rdx, %rcx + movq 48(%rsi), %rax + movq 48(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 40(%rdi) + sbbq %rax, %rdx + movq 56(%rsi), %rcx + movq 56(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 48(%rdi) + sbbq %rcx, %rax + movq 64(%rsi), %rdx + movq 64(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 56(%rdi) + sbbq %rdx, %rcx + movq 72(%rsi), %rax + movq 72(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 64(%rdi) + sbbq %rax, %rdx + movq 80(%rsi), %rcx + movq 80(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 72(%rdi) + sbbq %rcx, %rax + movq 88(%rsi), %rdx + movq 88(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 80(%rdi) + sbbq %rdx, %rcx + movq 96(%rsi), %rax + movq 96(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 88(%rdi) + sbbq %rax, %rdx + movq 104(%rsi), %rcx + movq 104(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 96(%rdi) + sbbq %rcx, %rax + movq 112(%rsi), %rdx + movq 112(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 104(%rdi) + sbbq %rdx, %rcx + movq 120(%rsi), %rax + movq 120(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 112(%rdi) + sbbq %rax, %rdx + movq 128(%rsi), %rcx + movq 128(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 120(%rdi) + sbbq %rcx, %rax + movq 136(%rsi), %rdx + movq 136(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 128(%rdi) + sbbq %rdx, %rcx + movq 144(%rsi), %rax + movq 144(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 136(%rdi) + sbbq %rax, %rdx + movq 152(%rsi), %rcx + movq 152(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 144(%rdi) + sbbq %rcx, %rax + movq 160(%rsi), %rdx + movq 160(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 152(%rdi) + sbbq %rdx, %rcx + movq 168(%rsi), %rax + movq 168(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 160(%rdi) + sbbq %rax, %rdx + movq 176(%rsi), %rcx + movq 176(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 168(%rdi) + sbbq %rcx, %rax + movq 184(%rsi), %rdx + movq 184(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 176(%rdi) + sbbq %rdx, %rcx + movq 192(%rsi), %rax + movq 192(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 184(%rdi) + sbbq %rax, %rdx + movq 200(%rsi), %rcx + movq 200(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 192(%rdi) + sbbq %rcx, %rax + movq 208(%rsi), %rdx + movq 208(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 200(%rdi) + sbbq %rdx, %rcx + movq 216(%rsi), %rax + movq 216(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 208(%rdi) + sbbq %rax, %rdx + movq 224(%rsi), %rcx + movq 224(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 216(%rdi) + sbbq %rcx, %rax + movq 232(%rsi), %rdx + movq 232(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 224(%rdi) + sbbq %rdx, %rcx + movq 240(%rsi), %rax + movq 240(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 232(%rdi) + sbbq %rax, %rdx + movq 248(%rsi), %rcx + movq 248(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 240(%rdi) + sbbq %rcx, %rax + movq 256(%rsi), %rdx + movq 256(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 248(%rdi) + sbbq %rdx, %rcx + movq 264(%rsi), %rax + movq 264(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 256(%rdi) + sbbq %rax, %rdx + movq 272(%rsi), %rcx + movq 272(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 264(%rdi) + sbbq %rcx, %rax + movq 280(%rsi), %rdx + movq 280(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 272(%rdi) + sbbq %rdx, %rcx + movq 288(%rsi), %rax + movq 288(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 280(%rdi) + sbbq %rax, %rdx + movq 296(%rsi), %rcx + movq 296(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 288(%rdi) + sbbq %rcx, %rax + movq 304(%rsi), %rdx + movq 304(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 296(%rdi) + sbbq %rdx, %rcx + movq 312(%rsi), %rax + movq 312(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 304(%rdi) + sbbq %rax, %rdx + movq 320(%rsi), %rcx + movq 320(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 312(%rdi) + sbbq %rcx, %rax + movq 328(%rsi), %rdx + movq 328(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 320(%rdi) + sbbq %rdx, %rcx + movq 336(%rsi), %rax + movq 336(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 328(%rdi) + sbbq %rax, %rdx + movq 344(%rsi), %rcx + movq 344(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 336(%rdi) + sbbq %rcx, %rax + movq 352(%rsi), %rdx + movq 352(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 344(%rdi) + sbbq %rdx, %rcx + movq 360(%rsi), %rax + movq 360(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 352(%rdi) + sbbq %rax, %rdx + movq 368(%rsi), %rcx + movq 368(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 360(%rdi) + sbbq %rcx, %rax + movq 376(%rsi), %rdx + movq 376(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 368(%rdi) + sbbq %rdx, %rcx + movq 384(%rsi), %rax + movq 384(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 376(%rdi) + sbbq %rax, %rdx + movq 392(%rsi), %rcx + movq 392(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 384(%rdi) + sbbq %rcx, %rax + movq 400(%rsi), %rdx + movq 400(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 392(%rdi) + sbbq %rdx, %rcx + movq 408(%rsi), %rax + movq 408(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 400(%rdi) + sbbq %rax, %rdx + movq 416(%rsi), %rcx + movq 416(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 408(%rdi) + sbbq %rcx, %rax + movq 424(%rsi), %rdx + movq 424(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 416(%rdi) + sbbq %rdx, %rcx + movq 432(%rsi), %rax + movq 432(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 424(%rdi) + sbbq %rax, %rdx + movq 440(%rsi), %rcx + movq 440(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 432(%rdi) + sbbq %rcx, %rax + movq 448(%rsi), %rdx + movq 448(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 440(%rdi) + sbbq %rdx, %rcx + movq 456(%rsi), %rax + movq 456(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 448(%rdi) + sbbq %rax, %rdx + movq 464(%rsi), %rcx + movq 464(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 456(%rdi) + sbbq %rcx, %rax + movq 472(%rsi), %rdx + movq 472(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 464(%rdi) + sbbq %rdx, %rcx + movq 480(%rsi), %rax + movq 480(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 472(%rdi) + sbbq %rax, %rdx + movq 488(%rsi), %rcx + movq 488(%r8), %rax + pextq %r14, %rcx, %rcx + movq %rdx, 480(%rdi) + sbbq %rcx, %rax + movq 496(%rsi), %rdx + movq 496(%r8), %rcx + pextq %r14, %rdx, %rdx + movq %rax, 488(%rdi) + sbbq %rdx, %rcx + movq 504(%rsi), %rax + movq 504(%r8), %rdx + pextq %r14, %rax, %rax + movq %rcx, 496(%rdi) + sbbq %rax, %rdx + movq %rdx, 504(%rdi) + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_4096_mont_reduce_avx2_64,.-sp_4096_mont_reduce_avx2_64 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_4096_cond_add_32 +.type sp_4096_cond_add_32,@function +.align 16 +sp_4096_cond_add_32: +#else +.globl _sp_4096_cond_add_32 +.p2align 4 +_sp_4096_cond_add_32: +#endif /* __APPLE__ */ + subq $256, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq 128(%rdx), %r8 + movq 136(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 128(%rsp) + movq %r9, 136(%rsp) + movq 144(%rdx), %r8 + movq 152(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 144(%rsp) + movq %r9, 152(%rsp) + movq 160(%rdx), %r8 + movq 168(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r9, 168(%rsp) + movq 176(%rdx), %r8 + movq 184(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 176(%rsp) + movq %r9, 184(%rsp) + movq 192(%rdx), %r8 + movq 200(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 192(%rsp) + movq %r9, 200(%rsp) + movq 208(%rdx), %r8 + movq 216(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 208(%rsp) + movq %r9, 216(%rsp) + movq 224(%rdx), %r8 + movq 232(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 224(%rsp) + movq %r9, 232(%rsp) + movq 240(%rdx), %r8 + movq 248(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 240(%rsp) + movq %r9, 248(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + addq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 112(%rdi) + movq 128(%rsi), %r8 + movq 128(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 120(%rdi) + movq 136(%rsi), %r9 + movq 136(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 128(%rdi) + movq 144(%rsi), %r8 + movq 144(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 136(%rdi) + movq 152(%rsi), %r9 + movq 152(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 144(%rdi) + movq 160(%rsi), %r8 + movq 160(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 152(%rdi) + movq 168(%rsi), %r9 + movq 168(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 160(%rdi) + movq 176(%rsi), %r8 + movq 176(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 168(%rdi) + movq 184(%rsi), %r9 + movq 184(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 176(%rdi) + movq 192(%rsi), %r8 + movq 192(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 184(%rdi) + movq 200(%rsi), %r9 + movq 200(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 192(%rdi) + movq 208(%rsi), %r8 + movq 208(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 200(%rdi) + movq 216(%rsi), %r9 + movq 216(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 208(%rdi) + movq 224(%rsi), %r8 + movq 224(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 216(%rdi) + movq 232(%rsi), %r9 + movq 232(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 224(%rdi) + movq 240(%rsi), %r8 + movq 240(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 232(%rdi) + movq 248(%rsi), %r9 + movq 248(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + adcq $0, %rax + addq $256, %rsp + repz retq +#ifndef __APPLE__ +.size sp_4096_cond_add_32,.-sp_4096_cond_add_32 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_4096_cond_add_avx2_32 +.type sp_4096_cond_add_avx2_32,@function +.align 16 +sp_4096_cond_add_avx2_32: +#else +.globl _sp_4096_cond_add_avx2_32 +.p2align 4 +_sp_4096_cond_add_avx2_32: +#endif /* __APPLE__ */ + movq $0, %rax + movq (%rdx), %r10 + movq (%rsi), %r8 + pextq %rcx, %r10, %r10 + addq %r10, %r8 + movq 8(%rdx), %r10 + movq 8(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, (%rdi) + adcq %r10, %r9 + movq 16(%rdx), %r8 + movq 16(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 8(%rdi) + adcq %r8, %r10 + movq 24(%rdx), %r9 + movq 24(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 16(%rdi) + adcq %r9, %r8 + movq 32(%rdx), %r10 + movq 32(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 24(%rdi) + adcq %r10, %r9 + movq 40(%rdx), %r8 + movq 40(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 32(%rdi) + adcq %r8, %r10 + movq 48(%rdx), %r9 + movq 48(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 40(%rdi) + adcq %r9, %r8 + movq 56(%rdx), %r10 + movq 56(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 48(%rdi) + adcq %r10, %r9 + movq 64(%rdx), %r8 + movq 64(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 56(%rdi) + adcq %r8, %r10 + movq 72(%rdx), %r9 + movq 72(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 64(%rdi) + adcq %r9, %r8 + movq 80(%rdx), %r10 + movq 80(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 72(%rdi) + adcq %r10, %r9 + movq 88(%rdx), %r8 + movq 88(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 80(%rdi) + adcq %r8, %r10 + movq 96(%rdx), %r9 + movq 96(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 88(%rdi) + adcq %r9, %r8 + movq 104(%rdx), %r10 + movq 104(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 96(%rdi) + adcq %r10, %r9 + movq 112(%rdx), %r8 + movq 112(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 104(%rdi) + adcq %r8, %r10 + movq 120(%rdx), %r9 + movq 120(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 112(%rdi) + adcq %r9, %r8 + movq 128(%rdx), %r10 + movq 128(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 120(%rdi) + adcq %r10, %r9 + movq 136(%rdx), %r8 + movq 136(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 128(%rdi) + adcq %r8, %r10 + movq 144(%rdx), %r9 + movq 144(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 136(%rdi) + adcq %r9, %r8 + movq 152(%rdx), %r10 + movq 152(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 144(%rdi) + adcq %r10, %r9 + movq 160(%rdx), %r8 + movq 160(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 152(%rdi) + adcq %r8, %r10 + movq 168(%rdx), %r9 + movq 168(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 160(%rdi) + adcq %r9, %r8 + movq 176(%rdx), %r10 + movq 176(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 168(%rdi) + adcq %r10, %r9 + movq 184(%rdx), %r8 + movq 184(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 176(%rdi) + adcq %r8, %r10 + movq 192(%rdx), %r9 + movq 192(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 184(%rdi) + adcq %r9, %r8 + movq 200(%rdx), %r10 + movq 200(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 192(%rdi) + adcq %r10, %r9 + movq 208(%rdx), %r8 + movq 208(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 200(%rdi) + adcq %r8, %r10 + movq 216(%rdx), %r9 + movq 216(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 208(%rdi) + adcq %r9, %r8 + movq 224(%rdx), %r10 + movq 224(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 216(%rdi) + adcq %r10, %r9 + movq 232(%rdx), %r8 + movq 232(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 224(%rdi) + adcq %r8, %r10 + movq 240(%rdx), %r9 + movq 240(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 232(%rdi) + adcq %r9, %r8 + movq 248(%rdx), %r10 + movq 248(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 240(%rdi) + adcq %r10, %r9 + movq %r9, 248(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_4096_cond_add_avx2_32,.-sp_4096_cond_add_avx2_32 +#endif /* __APPLE__ */ +/* Shift number left by n bit. (r = a << n) + * + * r Result of left shift by n. + * a Number to shift. + * n Amoutnt o shift. + */ +#ifndef __APPLE__ +.globl sp_4096_lshift_64 +.type sp_4096_lshift_64,@function +.align 16 +sp_4096_lshift_64: +#else +.globl _sp_4096_lshift_64 +.p2align 4 +_sp_4096_lshift_64: +#endif /* __APPLE__ */ + movq %rdx, %rcx + movq $0, %r10 + movq 472(%rsi), %r11 + movq 480(%rsi), %rdx + movq 488(%rsi), %rax + movq 496(%rsi), %r8 + movq 504(%rsi), %r9 + shldq %cl, %r9, %r10 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 480(%rdi) + movq %rax, 488(%rdi) + movq %r8, 496(%rdi) + movq %r9, 504(%rdi) + movq %r10, 512(%rdi) + movq 440(%rsi), %r9 + movq 448(%rsi), %rdx + movq 456(%rsi), %rax + movq 464(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 448(%rdi) + movq %rax, 456(%rdi) + movq %r8, 464(%rdi) + movq %r11, 472(%rdi) + movq 408(%rsi), %r11 + movq 416(%rsi), %rdx + movq 424(%rsi), %rax + movq 432(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 416(%rdi) + movq %rax, 424(%rdi) + movq %r8, 432(%rdi) + movq %r9, 440(%rdi) + movq 376(%rsi), %r9 + movq 384(%rsi), %rdx + movq 392(%rsi), %rax + movq 400(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 384(%rdi) + movq %rax, 392(%rdi) + movq %r8, 400(%rdi) + movq %r11, 408(%rdi) + movq 344(%rsi), %r11 + movq 352(%rsi), %rdx + movq 360(%rsi), %rax + movq 368(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 352(%rdi) + movq %rax, 360(%rdi) + movq %r8, 368(%rdi) + movq %r9, 376(%rdi) + movq 312(%rsi), %r9 + movq 320(%rsi), %rdx + movq 328(%rsi), %rax + movq 336(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 320(%rdi) + movq %rax, 328(%rdi) + movq %r8, 336(%rdi) + movq %r11, 344(%rdi) + movq 280(%rsi), %r11 + movq 288(%rsi), %rdx + movq 296(%rsi), %rax + movq 304(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 288(%rdi) + movq %rax, 296(%rdi) + movq %r8, 304(%rdi) + movq %r9, 312(%rdi) + movq 248(%rsi), %r9 + movq 256(%rsi), %rdx + movq 264(%rsi), %rax + movq 272(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 256(%rdi) + movq %rax, 264(%rdi) + movq %r8, 272(%rdi) + movq %r11, 280(%rdi) + movq 216(%rsi), %r11 + movq 224(%rsi), %rdx + movq 232(%rsi), %rax + movq 240(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 224(%rdi) + movq %rax, 232(%rdi) + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + movq 184(%rsi), %r9 + movq 192(%rsi), %rdx + movq 200(%rsi), %rax + movq 208(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 192(%rdi) + movq %rax, 200(%rdi) + movq %r8, 208(%rdi) + movq %r11, 216(%rdi) + movq 152(%rsi), %r11 + movq 160(%rsi), %rdx + movq 168(%rsi), %rax + movq 176(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 160(%rdi) + movq %rax, 168(%rdi) + movq %r8, 176(%rdi) + movq %r9, 184(%rdi) + movq 120(%rsi), %r9 + movq 128(%rsi), %rdx + movq 136(%rsi), %rax + movq 144(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 128(%rdi) + movq %rax, 136(%rdi) + movq %r8, 144(%rdi) + movq %r11, 152(%rdi) + movq 88(%rsi), %r11 + movq 96(%rsi), %rdx + movq 104(%rsi), %rax + movq 112(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 96(%rdi) + movq %rax, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + movq 56(%rsi), %r9 + movq 64(%rsi), %rdx + movq 72(%rsi), %rax + movq 80(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r9, %rdx + movq %rdx, 64(%rdi) + movq %rax, 72(%rdi) + movq %r8, 80(%rdi) + movq %r11, 88(%rdi) + movq 24(%rsi), %r11 + movq 32(%rsi), %rdx + movq 40(%rsi), %rax + movq 48(%rsi), %r8 + shldq %cl, %r8, %r9 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shldq %cl, %r11, %rdx + movq %rdx, 32(%rdi) + movq %rax, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %r8 + shldq %cl, %r8, %r11 + shldq %cl, %rax, %r8 + shldq %cl, %rdx, %rax + shlq %cl, %rdx + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %r8, 16(%rdi) + movq %r11, 24(%rdi) + repz retq +#endif /* WOLFSSL_SP_4096 */ +#endif /* WOLFSSL_SP_4096 */ +#ifndef WOLFSSL_SP_NO_256 +/* Conditionally copy a into r 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. + */ +#ifndef __APPLE__ +.globl sp_256_cond_copy_4 +.type sp_256_cond_copy_4,@function +.align 16 +sp_256_cond_copy_4: +#else +.globl _sp_256_cond_copy_4 +.p2align 4 +_sp_256_cond_copy_4: +#endif /* __APPLE__ */ + movq (%rdi), %rax + movq 8(%rdi), %rcx + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 + xorq (%rsi), %rax + xorq 8(%rsi), %rcx + xorq 16(%rsi), %r8 + xorq 24(%rsi), %r9 + andq %rdx, %rax + andq %rdx, %rcx + andq %rdx, %r8 + andq %rdx, %r9 + xorq %rax, (%rdi) + xorq %rcx, 8(%rdi) + xorq %r8, 16(%rdi) + xorq %r9, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_cond_copy_4,.-sp_256_cond_copy_4 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_256_mont_mul_4 +.type sp_256_mont_mul_4,@function +.align 16 +sp_256_mont_mul_4: +#else +.globl _sp_256_mont_mul_4 +.p2align 4 +_sp_256_mont_mul_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + movq %rdx, %r8 + # A[0] * B[0] + movq (%r8), %rax + mulq (%rsi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * B[1] + movq 8(%r8), %rax + mulq (%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[0] + movq (%r8), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[0] * B[2] + movq 16(%r8), %rax + mulq (%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * B[1] + movq 8(%r8), %rax + mulq 8(%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0, %r13 + # A[2] * B[0] + movq (%r8), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0, %r13 + # A[0] * B[3] + movq 24(%r8), %rax + mulq (%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0, %r14 + # A[1] * B[2] + movq 16(%r8), %rax + mulq 8(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0, %r14 + # A[2] * B[1] + movq 8(%r8), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0, %r14 + # A[3] * B[0] + movq (%r8), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0, %r14 + # A[1] * B[3] + movq 24(%r8), %rax + mulq 8(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0, %r15 + # A[2] * B[2] + movq 16(%r8), %rax + mulq 16(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0, %r15 + # A[3] * B[1] + movq 8(%r8), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0, %r15 + # A[2] * B[3] + movq 24(%r8), %rax + mulq 16(%rsi) + xorq %rbx, %rbx + addq %rax, %r14 + adcq %rdx, %r15 + adcq $0, %rbx + # A[3] * B[2] + movq 16(%r8), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + adcq $0, %rbx + # A[3] * B[3] + movq 24(%r8), %rax + mulq 24(%rsi) + addq %rax, %r15 + adcq %rdx, %rbx + # Start Reduction + # mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192 + # - a[0] << 32 << 192 + # + (a[0] * 2) << 192 + movq %r9, %rax + movq %r12, %rdx + addq %r9, %rdx + movq %r10, %rsi + addq %r9, %rdx + movq %r11, %r8 + # a[0]-a[2] << 32 + shlq $32, %r9 + shldq $32, %rsi, %r11 + shldq $32, %rax, %r10 + # - a[0] << 32 << 192 + subq %r9, %rdx + # + a[0]-a[2] << 32 << 64 + addq %r9, %rsi + adcq %r10, %r8 + adcq %r11, %rdx + # a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu + # a += mu << 256 + xorq %r9, %r9 + addq %rax, %r13 + adcq %rsi, %r14 + adcq %r8, %r15 + adcq %rdx, %rbx + sbbq $0, %r9 + # a += mu << 192 + addq %rax, %r12 + adcq %rsi, %r13 + adcq %r8, %r14 + adcq %rdx, %r15 + adcq $0, %rbx + sbbq $0, %r9 + # mu <<= 32 + movq %rdx, %rcx + shldq $32, %r8, %rdx + shldq $32, %rsi, %r8 + shldq $32, %rax, %rsi + shrq $32, %rcx + shlq $32, %rax + # a += (mu << 32) << 64 + addq %r8, %r12 + adcq %rdx, %r13 + adcq %rcx, %r14 + adcq $0, %r15 + adcq $0, %rbx + sbbq $0, %r9 + # a -= (mu << 32) << 192 + subq %rax, %r12 + sbbq %rsi, %r13 + sbbq %r8, %r14 + sbbq %rdx, %r15 + sbbq %rcx, %rbx + adcq $0, %r9 + movq $4294967295, %rax + movq $18446744069414584321, %rsi + # mask m and sub from result if overflow + # m[0] = -1 & mask = mask + andq %r9, %rax + # m[2] = 0 & mask = 0 + andq %r9, %rsi + subq %r9, %r13 + sbbq %rax, %r14 + sbbq $0, %r15 + sbbq %rsi, %rbx + movq %r13, (%rdi) + movq %r14, 8(%rdi) + movq %r15, 16(%rdi) + movq %rbx, 24(%rdi) + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_mont_mul_4,.-sp_256_mont_mul_4 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_256_mont_sqr_4 +.type sp_256_mont_sqr_4,@function +.align 16 +sp_256_mont_sqr_4: +#else +.globl _sp_256_mont_sqr_4 +.p2align 4 +_sp_256_mont_sqr_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r10 + movq %rdx, %r11 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r13, %r13 + addq %rax, %r12 + adcq %rdx, %r13 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0, %r14 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r15, %r15 + addq %rax, %r14 + adcq %rdx, %r15 + # Double + xorq %rbx, %rbx + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq %r15, %r15 + adcq $0, %rbx + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %rax + movq %rdx, %rdx + movq %rax, %r9 + movq %rdx, %r8 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + movq %rax, %rax + movq %rdx, %rdx + addq %r8, %r10 + adcq %rax, %r11 + adcq $0, %rdx + movq %rdx, %r8 + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + movq %rax, %rax + movq %rdx, %rdx + addq %r8, %r12 + adcq %rax, %r13 + adcq $0, %rdx + movq %rdx, %r8 + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r15 + adcq %rdx, %rbx + addq %r8, %r14 + adcq $0, %r15 + adcq $0, %rbx + # Start Reduction + # mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192 + # - a[0] << 32 << 192 + # + (a[0] * 2) << 192 + movq %r9, %rax + movq %r12, %rdx + addq %r9, %rdx + movq %r10, %rsi + addq %r9, %rdx + movq %r11, %r8 + # a[0]-a[2] << 32 + shlq $32, %r9 + shldq $32, %rsi, %r11 + shldq $32, %rax, %r10 + # - a[0] << 32 << 192 + subq %r9, %rdx + # + a[0]-a[2] << 32 << 64 + addq %r9, %rsi + adcq %r10, %r8 + adcq %r11, %rdx + # a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu + # a += mu << 256 + xorq %r9, %r9 + addq %rax, %r13 + adcq %rsi, %r14 + adcq %r8, %r15 + adcq %rdx, %rbx + sbbq $0, %r9 + # a += mu << 192 + addq %rax, %r12 + adcq %rsi, %r13 + adcq %r8, %r14 + adcq %rdx, %r15 + adcq $0, %rbx + sbbq $0, %r9 + # mu <<= 32 + movq %rdx, %rcx + shldq $32, %r8, %rdx + shldq $32, %rsi, %r8 + shldq $32, %rax, %rsi + shrq $32, %rcx + shlq $32, %rax + # a += (mu << 32) << 64 + addq %r8, %r12 + adcq %rdx, %r13 + adcq %rcx, %r14 + adcq $0, %r15 + adcq $0, %rbx + sbbq $0, %r9 + # a -= (mu << 32) << 192 + subq %rax, %r12 + sbbq %rsi, %r13 + sbbq %r8, %r14 + sbbq %rdx, %r15 + sbbq %rcx, %rbx + adcq $0, %r9 + movq $4294967295, %rax + movq $18446744069414584321, %rsi + # mask m and sub from result if overflow + # m[0] = -1 & mask = mask + andq %r9, %rax + # m[2] = 0 & mask = 0 + andq %r9, %rsi + subq %r9, %r13 + sbbq %rax, %r14 + sbbq $0, %r15 + sbbq %rsi, %rbx + movq %r13, (%rdi) + movq %r14, 8(%rdi) + movq %r15, 16(%rdi) + movq %rbx, 24(%rdi) + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_mont_sqr_4,.-sp_256_mont_sqr_4 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_256_cmp_4 +.type sp_256_cmp_4,@function +.align 16 +sp_256_cmp_4: +#else +.globl _sp_256_cmp_4 +.p2align 4 +_sp_256_cmp_4: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $1, %r8 + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_256_cmp_4,.-sp_256_cmp_4 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_256_cond_sub_4 +.type sp_256_cond_sub_4,@function +.align 16 +sp_256_cond_sub_4: +#else +.globl _sp_256_cond_sub_4 +.p2align 4 +_sp_256_cond_sub_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq $0, %rax + movq (%rdx), %r12 + movq 8(%rdx), %r13 + movq 16(%rdx), %r14 + movq 24(%rdx), %r15 + andq %rcx, %r12 + andq %rcx, %r13 + andq %rcx, %r14 + andq %rcx, %r15 + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq %r12, %r8 + sbbq %r13, %r9 + sbbq %r14, %r10 + sbbq %r15, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + sbbq $0, %rax + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_cond_sub_4,.-sp_256_cond_sub_4 +#endif /* __APPLE__ */ +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_256_sub_4 +.type sp_256_sub_4,@function +.align 16 +sp_256_sub_4: +#else +.globl _sp_256_sub_4 +.p2align 4 +_sp_256_sub_4: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rsi), %rcx + movq 8(%rsi), %r8 + movq 16(%rsi), %r9 + movq 24(%rsi), %r10 + subq (%rdx), %rcx + sbbq 8(%rdx), %r8 + sbbq 16(%rdx), %r9 + sbbq 24(%rdx), %r10 + movq %rcx, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_256_sub_4,.-sp_256_sub_4 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_256_mont_reduce_4 +.type sp_256_mont_reduce_4,@function +.align 16 +sp_256_mont_reduce_4: +#else +.globl _sp_256_mont_reduce_4 +.p2align 4 +_sp_256_mont_reduce_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rcx + # i = 0 + xorq %r14, %r14 + movq $4, %r8 + movq %rdi, %r13 +L_mont_loop_4: + # mu = a[i] * mp + movq (%r13), %r12 + imulq %rcx, %r12 + # a[i+0] += m[0] * mu + movq (%rsi), %rax + movq 8(%rsi), %r10 + mulq %r12 + movq (%r13), %r15 + addq %rax, %r15 + movq %rdx, %r9 + movq %r15, (%r13) + adcq $0, %r9 + # a[i+1] += m[1] * mu + movq %r10, %rax + mulq %r12 + movq 16(%rsi), %r10 + movq 8(%r13), %r15 + addq %r9, %rax + movq %rdx, %r11 + adcq $0, %r11 + addq %rax, %r15 + movq %r15, 8(%r13) + adcq $0, %r11 + # a[i+2] += m[2] * mu + movq %r10, %rax + mulq %r12 + movq 24(%rsi), %r10 + movq 16(%r13), %r15 + addq %r11, %rax + movq %rdx, %r9 + adcq $0, %r9 + addq %rax, %r15 + movq %r15, 16(%r13) + adcq $0, %r9 + # a[i+3] += m[3] * mu + movq %r10, %rax + mulq %r12 + movq 24(%r13), %r15 + addq %r9, %rax + adcq %r14, %rdx + movq $0, %r14 + adcq $0, %r14 + addq %rax, %r15 + movq %r15, 24(%r13) + adcq %rdx, 32(%r13) + adcq $0, %r14 + # i += 1 + addq $8, %r13 + decq %r8 + jnz L_mont_loop_4 + xorq %rax, %rax + movq 32(%rdi), %rdx + movq 40(%rdi), %r8 + movq 48(%rdi), %r15 + movq 56(%rdi), %r9 + subq %r14, %rax + movq (%rsi), %r10 + movq 8(%rsi), %r11 + movq 16(%rsi), %r12 + movq 24(%rsi), %r13 + andq %rax, %r10 + andq %rax, %r11 + andq %rax, %r12 + andq %rax, %r13 + subq %r10, %rdx + sbbq %r11, %r8 + sbbq %r12, %r15 + sbbq %r13, %r9 + movq %rdx, (%rdi) + movq %r8, 8(%rdi) + movq %r15, 16(%rdi) + movq %r9, 24(%rdi) + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_mont_reduce_4,.-sp_256_mont_reduce_4 +#endif /* __APPLE__ */ +/* 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). + */ +#ifndef __APPLE__ +.globl sp_256_mont_add_4 +.type sp_256_mont_add_4,@function +.align 16 +sp_256_mont_add_4: +#else +.globl _sp_256_mont_add_4 +.p2align 4 +_sp_256_mont_add_4: +#endif /* __APPLE__ */ + movq (%rsi), %rax + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + movq $4294967295, %r10 + movq $18446744069414584321, %r11 + addq (%rdx), %rax + adcq 8(%rdx), %rcx + adcq 16(%rdx), %r8 + movq $0, %rsi + adcq 24(%rdx), %r9 + sbbq $0, %rsi + andq %rsi, %r10 + andq %rsi, %r11 + subq %rsi, %rax + sbbq %r10, %rcx + movq %rax, (%rdi) + sbbq $0, %r8 + movq %rcx, 8(%rdi) + sbbq %r11, %r9 + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_mont_add_4,.-sp_256_mont_add_4 +#endif /* __APPLE__ */ +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.globl sp_256_mont_dbl_4 +.type sp_256_mont_dbl_4,@function +.align 16 +sp_256_mont_dbl_4: +#else +.globl _sp_256_mont_dbl_4 +.p2align 4 +_sp_256_mont_dbl_4: +#endif /* __APPLE__ */ + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + movq $4294967295, %r9 + movq $18446744069414584321, %r10 + addq %rdx, %rdx + adcq %rax, %rax + adcq %rcx, %rcx + movq $0, %r11 + adcq %r8, %r8 + sbbq $0, %r11 + andq %r11, %r9 + andq %r11, %r10 + subq %r11, %rdx + sbbq %r9, %rax + movq %rdx, (%rdi) + sbbq $0, %rcx + movq %rax, 8(%rdi) + sbbq %r10, %r8 + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_mont_dbl_4,.-sp_256_mont_dbl_4 +#endif /* __APPLE__ */ +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.globl sp_256_mont_tpl_4 +.type sp_256_mont_tpl_4,@function +.align 16 +sp_256_mont_tpl_4: +#else +.globl _sp_256_mont_tpl_4 +.p2align 4 +_sp_256_mont_tpl_4: +#endif /* __APPLE__ */ + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + movq $4294967295, %r9 + movq $18446744069414584321, %r10 + addq %rdx, %rdx + adcq %rax, %rax + adcq %rcx, %rcx + movq $0, %r11 + adcq %r8, %r8 + sbbq $0, %r11 + andq %r11, %r9 + andq %r11, %r10 + subq %r11, %rdx + sbbq %r9, %rax + sbbq $0, %rcx + sbbq %r10, %r8 + movq $4294967295, %r9 + movq $18446744069414584321, %r10 + addq (%rsi), %rdx + adcq 8(%rsi), %rax + adcq 16(%rsi), %rcx + movq $0, %r11 + adcq 24(%rsi), %r8 + sbbq $0, %r11 + andq %r11, %r9 + andq %r11, %r10 + subq %r11, %rdx + sbbq %r9, %rax + movq %rdx, (%rdi) + sbbq $0, %rcx + movq %rax, 8(%rdi) + sbbq %r10, %r8 + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_mont_tpl_4,.-sp_256_mont_tpl_4 +#endif /* __APPLE__ */ +/* 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). + */ +#ifndef __APPLE__ +.globl sp_256_mont_sub_4 +.type sp_256_mont_sub_4,@function +.align 16 +sp_256_mont_sub_4: +#else +.globl _sp_256_mont_sub_4 +.p2align 4 +_sp_256_mont_sub_4: +#endif /* __APPLE__ */ + movq (%rsi), %rax + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + movq $4294967295, %r10 + movq $18446744069414584321, %r11 + subq (%rdx), %rax + sbbq 8(%rdx), %rcx + sbbq 16(%rdx), %r8 + movq $0, %rsi + sbbq 24(%rdx), %r9 + sbbq $0, %rsi + andq %rsi, %r10 + andq %rsi, %r11 + addq %rsi, %rax + adcq %r10, %rcx + movq %rax, (%rdi) + adcq $0, %r8 + movq %rcx, 8(%rdi) + adcq %r11, %r9 + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_mont_sub_4,.-sp_256_mont_sub_4 +#endif /* __APPLE__ */ +/* 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). + */ +#ifndef __APPLE__ +.globl sp_256_div2_4 +.type sp_256_div2_4,@function +.align 16 +sp_256_div2_4: +#else +.globl _sp_256_div2_4 +.p2align 4 +_sp_256_div2_4: +#endif /* __APPLE__ */ + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + movq $4294967295, %r9 + movq $18446744069414584321, %r10 + movq %rdx, %r11 + andq $1, %r11 + negq %r11 + andq %r11, %r9 + andq %r11, %r10 + addq %r11, %rdx + adcq %r9, %rax + adcq $0, %rcx + adcq %r10, %r8 + movq $0, %r11 + adcq $0, %r11 + shrdq $1, %rax, %rdx + shrdq $1, %rcx, %rax + shrdq $1, %r8, %rcx + shrdq $1, %r11, %r8 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_div2_4,.-sp_256_div2_4 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_256_mont_mul_avx2_4 +.type sp_256_mont_mul_avx2_4,@function +.align 16 +sp_256_mont_mul_avx2_4: +#else +.globl _sp_256_mont_mul_avx2_4 +.p2align 4 +_sp_256_mont_mul_avx2_4: +#endif /* __APPLE__ */ + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rbp + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rax, %rcx + xorq %r15, %r15 + adcxq %rax, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rcx, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rsi), %rax, %rcx + adoxq %rax, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rax, %r14 + adoxq %rcx, %r10 + adcxq %rax, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rsi), %rax, %rcx + adcxq %r14, %r12 + adoxq %rax, %r11 + adcxq %r15, %r13 + adoxq %rcx, %r12 + # A[0] * B[2] + mulxq (%rsi), %rax, %rcx + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rax, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rsi), %rdx, %rax + adcxq %rcx, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rax, %r11 + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rsi), %rdx, %rax + adcxq %rcx, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rax, %r13 + mulxq 24(%rsi), %rax, %rcx + adoxq %r15, %r14 + adcxq %rax, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rax + adcxq %rcx, %r15 + xorq %rcx, %rcx + adcxq %rdx, %r11 + # A[3] * B[0] + movq 24(%rsi), %rdx + adcxq %rax, %r12 + mulxq (%rbp), %rbx, %rax + adoxq %rbx, %r11 + adoxq %rax, %r12 + # A[3] * B[2] + mulxq 16(%rbp), %rdx, %rax + adcxq %rdx, %r13 + # A[2] * B[3] + movq 24(%rbp), %rdx + adcxq %rax, %r14 + mulxq 16(%rsi), %rax, %rdx + adcxq %rcx, %r15 + adoxq %rax, %r13 + adoxq %rdx, %r14 + adoxq %rcx, %r15 + # Start Reduction + # mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192 + # - a[0] << 32 << 192 + # + (a[0] * 2) << 192 + movq %r8, %rax + movq %r11, %rdx + addq %r8, %rdx + movq %r9, %rsi + addq %r8, %rdx + movq %r10, %rbp + # a[0]-a[2] << 32 + shlq $32, %r8 + shldq $32, %rsi, %r10 + shldq $32, %rax, %r9 + # - a[0] << 32 << 192 + subq %r8, %rdx + # + a[0]-a[2] << 32 << 64 + addq %r8, %rsi + adcq %r9, %rbp + adcq %r10, %rdx + # a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu + # a += mu << 256 + xorq %r8, %r8 + addq %rax, %r12 + adcq %rsi, %r13 + adcq %rbp, %r14 + adcq %rdx, %r15 + sbbq $0, %r8 + # a += mu << 192 + addq %rax, %r11 + adcq %rsi, %r12 + adcq %rbp, %r13 + adcq %rdx, %r14 + adcq $0, %r15 + sbbq $0, %r8 + # mu <<= 32 + movq %rdx, %rcx + shldq $32, %rbp, %rdx + shldq $32, %rsi, %rbp + shldq $32, %rax, %rsi + shrq $32, %rcx + shlq $32, %rax + # a += (mu << 32) << 64 + addq %rbp, %r11 + adcq %rdx, %r12 + adcq %rcx, %r13 + adcq $0, %r14 + adcq $0, %r15 + sbbq $0, %r8 + # a -= (mu << 32) << 192 + subq %rax, %r11 + sbbq %rsi, %r12 + sbbq %rbp, %r13 + sbbq %rdx, %r14 + sbbq %rcx, %r15 + adcq $0, %r8 + movq $4294967295, %rax + movq $18446744069414584321, %rsi + # mask m and sub from result if overflow + # m[0] = -1 & mask = mask + andq %r8, %rax + # m[2] = 0 & mask = 0 + andq %r8, %rsi + subq %r8, %r12 + sbbq %rax, %r13 + sbbq $0, %r14 + sbbq %rsi, %r15 + movq %r12, (%rdi) + movq %r13, 8(%rdi) + movq %r14, 16(%rdi) + movq %r15, 24(%rdi) + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + repz retq +#ifndef __APPLE__ +.size sp_256_mont_mul_avx2_4,.-sp_256_mont_mul_avx2_4 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_256_mont_sqr_avx2_4 +.type sp_256_mont_sqr_avx2_4,@function +.align 16 +sp_256_mont_sqr_avx2_4: +#else +.globl _sp_256_mont_sqr_avx2_4 +.p2align 4 +_sp_256_mont_sqr_avx2_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + # A[0] * A[1] + movq (%rsi), %rdx + movq 16(%rsi), %r15 + mulxq 8(%rsi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rsi), %r11, %r12 + # A[2] * A[1] + movq %r15, %rdx + mulxq 8(%rsi), %rcx, %rbx + # A[2] * A[3] + mulxq 24(%rsi), %r13, %r14 + xorq %r15, %r15 + adoxq %rcx, %r11 + adoxq %rbx, %r12 + # A[2] * A[0] + mulxq (%rsi), %rcx, %rbx + # A[1] * A[3] + movq 8(%rsi), %rdx + adoxq %r15, %r13 + mulxq 24(%rsi), %rax, %r8 + adcxq %rcx, %r10 + adoxq %r15, %r14 + adcxq %rbx, %r11 + adcxq %rax, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rsi), %rdx + mulxq %rdx, %r8, %rax + adcxq %r9, %r9 + adcxq %r10, %r10 + adoxq %rax, %r9 + # A[1] * A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r12, %r12 + adoxq %rbx, %r11 + adcxq %r13, %r13 + adoxq %rax, %r12 + adcxq %r14, %r14 + # A[3] * A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rbx + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rax, %r14 + adoxq %rbx, %r15 + # Start Reduction + # mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192 + # - a[0] << 32 << 192 + # + (a[0] * 2) << 192 + movq %r8, %rax + movq %r11, %rdx + addq %r8, %rdx + movq %r9, %rsi + addq %r8, %rdx + movq %r10, %rcx + # a[0]-a[2] << 32 + shlq $32, %r8 + shldq $32, %rsi, %r10 + shldq $32, %rax, %r9 + # - a[0] << 32 << 192 + subq %r8, %rdx + # + a[0]-a[2] << 32 << 64 + addq %r8, %rsi + adcq %r9, %rcx + adcq %r10, %rdx + # a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu + # a += mu << 256 + xorq %r8, %r8 + addq %rax, %r12 + adcq %rsi, %r13 + adcq %rcx, %r14 + adcq %rdx, %r15 + sbbq $0, %r8 + # a += mu << 192 + addq %rax, %r11 + adcq %rsi, %r12 + adcq %rcx, %r13 + adcq %rdx, %r14 + adcq $0, %r15 + sbbq $0, %r8 + # mu <<= 32 + movq %rdx, %rbx + shldq $32, %rcx, %rdx + shldq $32, %rsi, %rcx + shldq $32, %rax, %rsi + shrq $32, %rbx + shlq $32, %rax + # a += (mu << 32) << 64 + addq %rcx, %r11 + adcq %rdx, %r12 + adcq %rbx, %r13 + adcq $0, %r14 + adcq $0, %r15 + sbbq $0, %r8 + # a -= (mu << 32) << 192 + subq %rax, %r11 + sbbq %rsi, %r12 + sbbq %rcx, %r13 + sbbq %rdx, %r14 + sbbq %rbx, %r15 + adcq $0, %r8 + movq $4294967295, %rax + movq $18446744069414584321, %rsi + # mask m and sub from result if overflow + # m[0] = -1 & mask = mask + andq %r8, %rax + # m[2] = 0 & mask = 0 + andq %r8, %rsi + subq %r8, %r12 + sbbq %rax, %r13 + sbbq $0, %r14 + sbbq %rsi, %r15 + movq %r12, (%rdi) + movq %r13, 8(%rdi) + movq %r14, 16(%rdi) + movq %r15, 24(%rdi) + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_mont_sqr_avx2_4,.-sp_256_mont_sqr_avx2_4 +#endif /* __APPLE__ */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_256_add_one_4 +.type sp_256_add_one_4,@function +.align 16 +sp_256_add_one_4: +#else +.globl _sp_256_add_one_4 +.p2align 4 +_sp_256_add_one_4: +#endif /* __APPLE__ */ + addq $1, (%rdi) + adcq $0, 8(%rdi) + adcq $0, 16(%rdi) + adcq $0, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_add_one_4,.-sp_256_add_one_4 +#endif /* __APPLE__ */ +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +#ifndef __APPLE__ +.globl sp_256_from_bin +.type sp_256_from_bin,@function +.align 16 +sp_256_from_bin: +#else +.globl _sp_256_from_bin +.p2align 4 +_sp_256_from_bin: +#endif /* __APPLE__ */ + movq %rdx, %r9 + movq %rdi, %r10 + addq %rcx, %r9 + addq $32, %r10 + xorq %r11, %r11 + jmp L_256_from_bin_64_end +L_256_from_bin_64_start: + subq $64, %r9 + movbeq 56(%r9), %rax + movbeq 48(%r9), %r8 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movbeq 40(%r9), %rax + movbeq 32(%r9), %r8 + movq %rax, 16(%rdi) + movq %r8, 24(%rdi) + movbeq 24(%r9), %rax + movbeq 16(%r9), %r8 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movbeq 8(%r9), %rax + movbeq (%r9), %r8 + movq %rax, 48(%rdi) + movq %r8, 56(%rdi) + addq $64, %rdi + subq $64, %rcx +L_256_from_bin_64_end: + cmpq $63, %rcx + jg L_256_from_bin_64_start + jmp L_256_from_bin_8_end +L_256_from_bin_8_start: + subq $8, %r9 + movbeq (%r9), %rax + movq %rax, (%rdi) + addq $8, %rdi + subq $8, %rcx +L_256_from_bin_8_end: + cmpq $7, %rcx + jg L_256_from_bin_8_start + cmpq %r11, %rcx + je L_256_from_bin_hi_end + movq %r11, %r8 + movq %r11, %rax +L_256_from_bin_hi_start: + movb (%rdx), %al + shlq $8, %r8 + incq %rdx + addq %rax, %r8 + decq %rcx + jg L_256_from_bin_hi_start + movq %r8, (%rdi) + addq $8, %rdi +L_256_from_bin_hi_end: + cmpq %r10, %rdi + je L_256_from_bin_zero_end +L_256_from_bin_zero_start: + movq %r11, (%rdi) + addq $8, %rdi + cmpq %r10, %rdi + jl L_256_from_bin_zero_start +L_256_from_bin_zero_end: + repz retq +#ifndef __APPLE__ +.size sp_256_from_bin,.-sp_256_from_bin +#endif /* __APPLE__ */ +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 32 + * + * r A single precision integer. + * a Byte array. + */ +#ifndef __APPLE__ +.globl sp_256_to_bin +.type sp_256_to_bin,@function +.align 16 +sp_256_to_bin: +#else +.globl _sp_256_to_bin +.p2align 4 +_sp_256_to_bin: +#endif /* __APPLE__ */ + movbeq 24(%rdi), %rdx + movbeq 16(%rdi), %rax + movq %rdx, (%rsi) + movq %rax, 8(%rsi) + movbeq 8(%rdi), %rdx + movbeq (%rdi), %rax + movq %rdx, 16(%rsi) + movq %rax, 24(%rsi) + repz retq +#ifndef __APPLE__ +.size sp_256_to_bin,.-sp_256_to_bin +#endif /* __APPLE__ */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_256_add_4 +.type sp_256_add_4,@function +.align 16 +sp_256_add_4: +#else +.globl _sp_256_add_4 +.p2align 4 +_sp_256_add_4: +#endif /* __APPLE__ */ + # Add + movq (%rsi), %rcx + xorq %rax, %rax + addq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + adcq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + adcq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + adcq 24(%rdx), %r8 + movq %r8, 24(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_256_add_4,.-sp_256_add_4 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_256_mul_4 +.type sp_256_mul_4,@function +.align 16 +sp_256_mul_4: +#else +.globl _sp_256_mul_4 +.p2align 4 +_sp_256_mul_4: +#endif /* __APPLE__ */ + movq %rdx, %rcx + subq $32, %rsp + # A[0] * B[0] + movq (%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + movq %rax, (%rsp) + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[0] + movq (%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 8(%rsp) + # A[0] * B[2] + movq 16(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[1] + movq 8(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[0] + movq (%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 16(%rsp) + # A[0] * B[3] + movq 24(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[2] + movq 16(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[1] + movq 8(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[0] + movq (%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 24(%rsp) + # A[1] * B[3] + movq 24(%rcx), %rax + mulq 8(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[2] + movq 16(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[1] + movq 8(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 32(%rdi) + # A[2] * B[3] + movq 24(%rcx), %rax + mulq 16(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[2] + movq 16(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 40(%rdi) + # A[3] * B[3] + movq 24(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r8 + movq 24(%rsp), %r9 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + addq $32, %rsp + repz retq +#ifndef __APPLE__ +.size sp_256_mul_4,.-sp_256_mul_4 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r Result of multiplication. + * a First number to multiply. + * b Second number to multiply. + */ +#ifndef __APPLE__ +.globl sp_256_mul_avx2_4 +.type sp_256_mul_avx2_4,@function +.align 16 +sp_256_mul_avx2_4: +#else +.globl _sp_256_mul_avx2_4 +.p2align 4 +_sp_256_mul_avx2_4: +#endif /* __APPLE__ */ + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rbp + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rax, %rcx + xorq %r15, %r15 + adcxq %rax, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rcx, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rsi), %rax, %rcx + adoxq %rax, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rax, %r14 + adoxq %rcx, %r10 + adcxq %rax, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rsi), %rax, %rcx + adcxq %r14, %r12 + adoxq %rax, %r11 + adcxq %r15, %r13 + adoxq %rcx, %r12 + # A[0] * B[2] + mulxq (%rsi), %rax, %rcx + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rax, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rsi), %rdx, %rax + adcxq %rcx, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rax, %r11 + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rsi), %rdx, %rax + adcxq %rcx, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rax, %r13 + mulxq 24(%rsi), %rax, %rcx + adoxq %r15, %r14 + adcxq %rax, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rax + adcxq %rcx, %r15 + xorq %rcx, %rcx + adcxq %rdx, %r11 + # A[3] * B[0] + movq 24(%rsi), %rdx + adcxq %rax, %r12 + mulxq (%rbp), %rbx, %rax + adoxq %rbx, %r11 + adoxq %rax, %r12 + # A[3] * B[2] + mulxq 16(%rbp), %rdx, %rax + adcxq %rdx, %r13 + # A[2] * B[3] + movq 24(%rbp), %rdx + adcxq %rax, %r14 + mulxq 16(%rsi), %rax, %rdx + adcxq %rcx, %r15 + adoxq %rax, %r13 + adoxq %rdx, %r14 + adoxq %rcx, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + repz retq +#ifndef __APPLE__ +.size sp_256_mul_avx2_4,.-sp_256_mul_avx2_4 +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_256_sub_in_place_4 +.type sp_256_sub_in_place_4,@function +.align 16 +sp_256_sub_in_place_4: +#else +.globl _sp_256_sub_in_place_4 +.p2align 4 +_sp_256_sub_in_place_4: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rsi), %rdx + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + subq %rdx, (%rdi) + sbbq %rcx, 8(%rdi) + sbbq %r8, 16(%rdi) + sbbq %r9, 24(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_256_sub_in_place_4,.-sp_256_sub_in_place_4 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_256_cond_sub_avx2_4 +.type sp_256_cond_sub_avx2_4,@function +.align 16 +sp_256_cond_sub_avx2_4: +#else +.globl _sp_256_cond_sub_avx2_4 +.p2align 4 +_sp_256_cond_sub_avx2_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq $0, %rax + movq (%rdx), %r12 + movq 8(%rdx), %r13 + movq 16(%rdx), %r14 + movq 24(%rdx), %r15 + andq %rcx, %r12 + andq %rcx, %r13 + andq %rcx, %r14 + andq %rcx, %r15 + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq %r12, %r8 + sbbq %r13, %r9 + sbbq %r14, %r10 + sbbq %r15, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + sbbq $0, %rax + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_cond_sub_avx2_4,.-sp_256_cond_sub_avx2_4 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_256_mul_d_4 +.type sp_256_mul_d_4,@function +.align 16 +sp_256_mul_d_4: +#else +.globl _sp_256_mul_d_4 +.p2align 4 +_sp_256_mul_d_4: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B + movq %rcx, %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 24(%rdi) + movq %r9, 32(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_mul_d_4,.-sp_256_mul_d_4 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* 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. + */ +#ifndef __APPLE__ +.globl sp_256_mul_d_avx2_4 +.type sp_256_mul_d_avx2_4,@function +.align 16 +sp_256_mul_d_avx2_4: +#else +.globl _sp_256_mul_d_avx2_4 +.p2align 4 +_sp_256_mul_d_avx2_4: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 8(%rdi) + adoxq %r8, %r9 + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 16(%rdi) + adoxq %r8, %r10 + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 24(%rdi) + movq %r9, 32(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_mul_d_avx2_4,.-sp_256_mul_d_avx2_4 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_256_sqr_4 +.type sp_256_sqr_4,@function +.align 16 +sp_256_sqr_4: +#else +.globl _sp_256_sqr_4 +.p2align 4 +_sp_256_sqr_4: +#endif /* __APPLE__ */ + push %r12 + subq $32, %rsp + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + xorq %r9, %r9 + movq %rax, (%rsp) + movq %rdx, %r8 + # A[0] * A[1] + movq 8(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 8(%rsp) + # A[0] * A[2] + movq 16(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 16(%rsp) + # A[0] * A[3] + movq 24(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * A[2] + movq 16(%rsi), %rax + mulq 8(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 24(%rsp) + # A[1] * A[3] + movq 24(%rsi), %rax + mulq 8(%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 32(%rdi) + # A[2] * A[3] + movq 24(%rsi), %rax + mulq 16(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 40(%rdi) + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %rcx + adcq %rdx, %r8 + movq %rcx, 48(%rdi) + movq %r8, 56(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $32, %rsp + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_sqr_4,.-sp_256_sqr_4 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r Result of squaring. + * a Number to square in Montogmery form. + */ +#ifndef __APPLE__ +.globl sp_256_sqr_avx2_4 +.type sp_256_sqr_avx2_4,@function +.align 16 +sp_256_sqr_avx2_4: +#else +.globl _sp_256_sqr_avx2_4 +.p2align 4 +_sp_256_sqr_avx2_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + # A[0] * A[1] + movq (%rsi), %rdx + movq 16(%rsi), %r15 + mulxq 8(%rsi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rsi), %r11, %r12 + # A[2] * A[1] + movq %r15, %rdx + mulxq 8(%rsi), %rcx, %rbx + # A[2] * A[3] + mulxq 24(%rsi), %r13, %r14 + xorq %r15, %r15 + adoxq %rcx, %r11 + adoxq %rbx, %r12 + # A[2] * A[0] + mulxq (%rsi), %rcx, %rbx + # A[1] * A[3] + movq 8(%rsi), %rdx + adoxq %r15, %r13 + mulxq 24(%rsi), %rax, %r8 + adcxq %rcx, %r10 + adoxq %r15, %r14 + adcxq %rbx, %r11 + adcxq %rax, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rsi), %rdx + mulxq %rdx, %r8, %rax + adcxq %r9, %r9 + adcxq %r10, %r10 + adoxq %rax, %r9 + # A[1] * A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r12, %r12 + adoxq %rbx, %r11 + adcxq %r13, %r13 + adoxq %rax, %r12 + adcxq %r14, %r14 + # A[3] * A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rbx + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rax, %r14 + adoxq %rbx, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_sqr_avx2_4,.-sp_256_sqr_avx2_4 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* 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. + */ +#ifndef __APPLE__ +.globl sp_256_mont_reduce_avx2_4 +.type sp_256_mont_reduce_avx2_4,@function +.align 16 +sp_256_mont_reduce_avx2_4: +#else +.globl _sp_256_mont_reduce_avx2_4 +.p2align 4 +_sp_256_mont_reduce_avx2_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + movq %rdx, %rax + movq (%rdi), %r12 + movq 8(%rdi), %r13 + movq 16(%rdi), %r14 + movq 24(%rdi), %r15 + xorq %r11, %r11 + xorq %r10, %r10 + # a[0-4] += m[0-3] * mu = m[0-3] * (a[0] * mp) + movq 32(%rdi), %rbx + # mu = a[0] * mp + movq %r12, %rdx + mulxq %rax, %rdx, %rcx + # a[0] += m[0] * mu + mulx (%rsi), %r8, %r9 + adcxq %r8, %r12 + # a[1] += m[1] * mu + mulx 8(%rsi), %r8, %rcx + adoxq %r9, %r13 + adcxq %r8, %r13 + # a[2] += m[2] * mu + mulx 16(%rsi), %r8, %r9 + adoxq %rcx, %r14 + adcxq %r8, %r14 + # a[3] += m[3] * mu + mulx 24(%rsi), %r8, %rcx + adoxq %r9, %r15 + adcxq %r8, %r15 + # a[4] += carry + adoxq %rcx, %rbx + adcxq %r10, %rbx + # carry + adoxq %r10, %r11 + adcxq %r10, %r11 + # a[1-5] += m[0-3] * mu = m[0-3] * (a[1] * mp) + movq 40(%rdi), %r12 + # mu = a[1] * mp + movq %r13, %rdx + mulxq %rax, %rdx, %rcx + # a[1] += m[0] * mu + mulx (%rsi), %r8, %r9 + adcxq %r8, %r13 + # a[2] += m[1] * mu + mulx 8(%rsi), %r8, %rcx + adoxq %r9, %r14 + adcxq %r8, %r14 + # a[3] += m[2] * mu + mulx 16(%rsi), %r8, %r9 + adoxq %rcx, %r15 + adcxq %r8, %r15 + # a[4] += m[3] * mu + mulx 24(%rsi), %r8, %rcx + adoxq %r9, %rbx + adcxq %r8, %rbx + # a[5] += carry + adoxq %rcx, %r12 + adcxq %r11, %r12 + movq %r10, %r11 + # carry + adoxq %r10, %r11 + adcxq %r10, %r11 + # a[2-6] += m[0-3] * mu = m[0-3] * (a[2] * mp) + movq 48(%rdi), %r13 + # mu = a[2] * mp + movq %r14, %rdx + mulxq %rax, %rdx, %rcx + # a[2] += m[0] * mu + mulx (%rsi), %r8, %r9 + adcxq %r8, %r14 + # a[3] += m[1] * mu + mulx 8(%rsi), %r8, %rcx + adoxq %r9, %r15 + adcxq %r8, %r15 + # a[4] += m[2] * mu + mulx 16(%rsi), %r8, %r9 + adoxq %rcx, %rbx + adcxq %r8, %rbx + # a[5] += m[3] * mu + mulx 24(%rsi), %r8, %rcx + adoxq %r9, %r12 + adcxq %r8, %r12 + # a[6] += carry + adoxq %rcx, %r13 + adcxq %r11, %r13 + movq %r10, %r11 + # carry + adoxq %r10, %r11 + adcxq %r10, %r11 + # a[3-7] += m[0-3] * mu = m[0-3] * (a[3] * mp) + movq 56(%rdi), %r14 + # mu = a[3] * mp + movq %r15, %rdx + mulxq %rax, %rdx, %rcx + # a[3] += m[0] * mu + mulx (%rsi), %r8, %r9 + adcxq %r8, %r15 + # a[4] += m[1] * mu + mulx 8(%rsi), %r8, %rcx + adoxq %r9, %rbx + adcxq %r8, %rbx + # a[5] += m[2] * mu + mulx 16(%rsi), %r8, %r9 + adoxq %rcx, %r12 + adcxq %r8, %r12 + # a[6] += m[3] * mu + mulx 24(%rsi), %r8, %rcx + adoxq %r9, %r13 + adcxq %r8, %r13 + # a[7] += carry + adoxq %rcx, %r14 + adcxq %r11, %r14 + movq %r10, %r11 + # carry + adoxq %r10, %r11 + adcxq %r10, %r11 + # Subtract mod if carry + negq %r11 + movq $17562291160714782033, %r8 + movq $13611842547513532036, %r9 + movq $18446744069414584320, %rdx + andq %r11, %r8 + andq %r11, %r9 + andq %r11, %rdx + subq %r8, %rbx + sbbq %r9, %r12 + sbbq %r11, %r13 + sbbq %rdx, %r14 + movq %rbx, (%rdi) + movq %r12, 8(%rdi) + movq %r13, 16(%rdi) + movq %r14, 24(%rdi) + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_mont_reduce_avx2_4,.-sp_256_mont_reduce_avx2_4 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#endif /* !WOLFSSL_SP_NO_256 */ +#ifdef WOLFSSL_SP_384 +/* Conditionally copy a into r 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. + */ +#ifndef __APPLE__ +.globl sp_384_cond_copy_6 +.type sp_384_cond_copy_6,@function +.align 16 +sp_384_cond_copy_6: +#else +.globl _sp_384_cond_copy_6 +.p2align 4 +_sp_384_cond_copy_6: +#endif /* __APPLE__ */ + movq (%rdi), %rax + movq 8(%rdi), %rcx + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 + movq 32(%rdi), %r10 + movq 40(%rdi), %r11 + xorq (%rsi), %rax + xorq 8(%rsi), %rcx + xorq 16(%rsi), %r8 + xorq 24(%rsi), %r9 + xorq 32(%rsi), %r10 + xorq 40(%rsi), %r11 + andq %rdx, %rax + andq %rdx, %rcx + andq %rdx, %r8 + andq %rdx, %r9 + andq %rdx, %r10 + andq %rdx, %r11 + xorq %rax, (%rdi) + xorq %rcx, 8(%rdi) + xorq %r8, 16(%rdi) + xorq %r9, 24(%rdi) + xorq %r10, 32(%rdi) + xorq %r11, 40(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_384_cond_copy_6,.-sp_384_cond_copy_6 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_384_mul_6 +.type sp_384_mul_6,@function +.align 16 +sp_384_mul_6: +#else +.globl _sp_384_mul_6 +.p2align 4 +_sp_384_mul_6: +#endif /* __APPLE__ */ + movq %rdx, %rcx + subq $48, %rsp + # A[0] * B[0] + movq (%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + movq %rax, (%rsp) + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[0] + movq (%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 8(%rsp) + # A[0] * B[2] + movq 16(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[1] + movq 8(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[0] + movq (%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 16(%rsp) + # A[0] * B[3] + movq 24(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[2] + movq 16(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[1] + movq 8(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[0] + movq (%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 24(%rsp) + # A[0] * B[4] + movq 32(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[3] + movq 24(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[2] + movq 16(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[1] + movq 8(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[0] + movq (%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 32(%rsp) + # A[0] * B[5] + movq 40(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[4] + movq 32(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[3] + movq 24(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[2] + movq 16(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[1] + movq 8(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[0] + movq (%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 40(%rsp) + # A[1] * B[5] + movq 40(%rcx), %rax + mulq 8(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[4] + movq 32(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[3] + movq 24(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[2] + movq 16(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[1] + movq 8(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 48(%rdi) + # A[2] * B[5] + movq 40(%rcx), %rax + mulq 16(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[4] + movq 32(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[3] + movq 24(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[2] + movq 16(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 56(%rdi) + # A[3] * B[5] + movq 40(%rcx), %rax + mulq 24(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[4] + movq 32(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[3] + movq 24(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 64(%rdi) + # A[4] * B[5] + movq 40(%rcx), %rax + mulq 32(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[4] + movq 32(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 72(%rdi) + # A[5] * B[5] + movq 40(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + movq %r9, 80(%rdi) + movq %r10, 88(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r8 + movq 24(%rsp), %r9 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rsp), %rax + movq 40(%rsp), %rdx + movq %rax, 32(%rdi) + movq %rdx, 40(%rdi) + addq $48, %rsp + repz retq +#ifndef __APPLE__ +.size sp_384_mul_6,.-sp_384_mul_6 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_384_cond_sub_6 +.type sp_384_cond_sub_6,@function +.align 16 +sp_384_cond_sub_6: +#else +.globl _sp_384_cond_sub_6 +.p2align 4 +_sp_384_cond_sub_6: +#endif /* __APPLE__ */ + subq $48, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + subq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + sbbq $0, %rax + addq $48, %rsp + repz retq +#ifndef __APPLE__ +.size sp_384_cond_sub_6,.-sp_384_cond_sub_6 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Reduce the number back to 384 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. + */ +#ifndef __APPLE__ +.globl sp_384_mont_reduce_6 +.type sp_384_mont_reduce_6,@function +.align 16 +sp_384_mont_reduce_6: +#else +.globl _sp_384_mont_reduce_6 +.p2align 4 +_sp_384_mont_reduce_6: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + push %rbp + movq (%rdi), %r11 + movq 8(%rdi), %r12 + movq 16(%rdi), %r13 + movq 24(%rdi), %r14 + movq 32(%rdi), %r15 + movq 40(%rdi), %rsi + xorq %r10, %r10 + # a[0-7] += m[0-5] * mu[0..1] = m[0-5] * (a[0..1] * mp) + movq 48(%rdi), %rbx + movq 56(%rdi), %rbp + movq %r11, %rdx + movq %r12, %rax + shldq $32, %rdx, %rax + shlq $32, %rdx + addq %r11, %rdx + adcq %r12, %rax + addq %r11, %rax + movq %rdx, %rcx + movq %rax, %r8 + movq %rax, %r9 + shldq $32, %rcx, %r8 + shlq $32, %rcx + shrq $32, %r9 + addq %rcx, %r11 + adcq %r8, %r12 + adcq %r9, %r13 + adcq $0, %r14 + adcq $0, %r15 + adcq $0, %rsi + adcq %rdx, %rbx + adcq %rax, %rbp + adcq $0, %r10 + addq %rax, %rcx + adcq %rdx, %r8 + adcq %rax, %r9 + movq $0, %rax + adcq $0, %rax + subq %r8, %r13 + sbbq %r9, %r14 + sbbq %rax, %r15 + sbbq $0, %rsi + sbbq $0, %rbx + sbbq $0, %rbp + sbbq $0, %r10 + # a[2-9] += m[0-5] * mu[0..1] = m[0-5] * (a[2..3] * mp) + movq 64(%rdi), %r11 + movq 72(%rdi), %r12 + movq %r13, %rdx + movq %r14, %rax + shldq $32, %rdx, %rax + shlq $32, %rdx + addq %r13, %rdx + adcq %r14, %rax + addq %r13, %rax + movq %rdx, %rcx + movq %rax, %r8 + movq %rax, %r9 + shldq $32, %rcx, %r8 + shlq $32, %rcx + shrq $32, %r9 + addq %r10, %r11 + adcq $0, %r12 + movq $0, %r10 + adcq $0, %r10 + addq %rcx, %r13 + adcq %r8, %r14 + adcq %r9, %r15 + adcq $0, %rsi + adcq $0, %rbx + adcq $0, %rbp + adcq %rdx, %r11 + adcq %rax, %r12 + adcq $0, %r10 + addq %rax, %rcx + adcq %rdx, %r8 + adcq %rax, %r9 + movq $0, %rax + adcq $0, %rax + subq %r8, %r15 + sbbq %r9, %rsi + sbbq %rax, %rbx + sbbq $0, %rbp + sbbq $0, %r11 + sbbq $0, %r12 + sbbq $0, %r10 + # a[4-11] += m[0-5] * mu[0..1] = m[0-5] * (a[4..5] * mp) + movq 80(%rdi), %r13 + movq 88(%rdi), %r14 + movq %r15, %rdx + movq %rsi, %rax + shldq $32, %rdx, %rax + shlq $32, %rdx + addq %r15, %rdx + adcq %rsi, %rax + addq %r15, %rax + movq %rdx, %rcx + movq %rax, %r8 + movq %rax, %r9 + shldq $32, %rcx, %r8 + shlq $32, %rcx + shrq $32, %r9 + addq %r10, %r13 + adcq $0, %r14 + movq $0, %r10 + adcq $0, %r10 + addq %rcx, %r15 + adcq %r8, %rsi + adcq %r9, %rbx + adcq $0, %rbp + adcq $0, %r11 + adcq $0, %r12 + adcq %rdx, %r13 + adcq %rax, %r14 + adcq $0, %r10 + addq %rax, %rcx + adcq %rdx, %r8 + adcq %rax, %r9 + movq $0, %rax + adcq $0, %rax + subq %r8, %rbx + sbbq %r9, %rbp + sbbq %rax, %r11 + sbbq $0, %r12 + sbbq $0, %r13 + sbbq $0, %r14 + sbbq $0, %r10 + # Subtract mod if carry + negq %r10 + movq $18446744073709551614, %r9 + movq %r10, %rcx + movq %r10, %r8 + shrq $32, %rcx + shlq $32, %r8 + andq %r10, %r9 + subq %rcx, %rbx + sbbq %r8, %rbp + sbbq %r9, %r11 + sbbq %r10, %r12 + sbbq %r10, %r13 + sbbq %r10, %r14 + movq %rbx, (%rdi) + movq %rbp, 8(%rdi) + movq %r11, 16(%rdi) + movq %r12, 24(%rdi) + movq %r13, 32(%rdi) + movq %r14, 40(%rdi) + pop %rbp + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_384_mont_reduce_6,.-sp_384_mont_reduce_6 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Reduce the number back to 384 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. + */ +#ifndef __APPLE__ +.globl sp_384_mont_reduce_order_6 +.type sp_384_mont_reduce_order_6,@function +.align 16 +sp_384_mont_reduce_order_6: +#else +.globl _sp_384_mont_reduce_order_6 +.p2align 4 +_sp_384_mont_reduce_order_6: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rcx + xorq %r15, %r15 + # i = 6 + movq $6, %r8 + movq (%rdi), %r13 + movq 8(%rdi), %r14 +L_mont_loop_order_6: + # mu = a[i] * mp + movq %r13, %r11 + imulq %rcx, %r11 + # a[i+0] += m[0] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq (%rsi) + addq %rax, %r13 + adcq %rdx, %r10 + # a[i+1] += m[1] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 8(%rsi) + movq %r14, %r13 + addq %rax, %r13 + adcq %rdx, %r9 + addq %r10, %r13 + adcq $0, %r9 + # a[i+2] += m[2] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 16(%rsi) + movq 16(%rdi), %r14 + addq %rax, %r14 + adcq %rdx, %r10 + addq %r9, %r14 + adcq $0, %r10 + # a[i+3] += m[3] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 24(%rsi) + movq 24(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 24(%rdi) + adcq $0, %r9 + # a[i+4] += m[4] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 32(%rsi) + movq 32(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 32(%rdi) + adcq $0, %r10 + # a[i+5] += m[5] * mu + movq %r11, %rax + mulq 40(%rsi) + movq 40(%rdi), %r12 + addq %rax, %r10 + adcq %r15, %rdx + movq $0, %r15 + adcq $0, %r15 + addq %r10, %r12 + movq %r12, 40(%rdi) + adcq %rdx, 48(%rdi) + adcq $0, %r15 + # i -= 1 + addq $8, %rdi + decq %r8 + jnz L_mont_loop_order_6 + movq %r13, (%rdi) + movq %r14, 8(%rdi) + negq %r15 + movq %r15, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + subq $48, %rdi +#ifndef __APPLE__ + callq sp_384_cond_sub_6@plt +#else + callq _sp_384_cond_sub_6 +#endif /* __APPLE__ */ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_384_mont_reduce_order_6,.-sp_384_mont_reduce_order_6 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_384_sqr_6 +.type sp_384_sqr_6,@function +.align 16 +sp_384_sqr_6: +#else +.globl _sp_384_sqr_6 +.p2align 4 +_sp_384_sqr_6: +#endif /* __APPLE__ */ + push %r12 + subq $48, %rsp + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + xorq %r9, %r9 + movq %rax, (%rsp) + movq %rdx, %r8 + # A[0] * A[1] + movq 8(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 8(%rsp) + # A[0] * A[2] + movq 16(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 16(%rsp) + # A[0] * A[3] + movq 24(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * A[2] + movq 16(%rsi), %rax + mulq 8(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 24(%rsp) + # A[0] * A[4] + movq 32(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[1] * A[3] + movq 24(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 32(%rsp) + # A[0] * A[5] + movq 40(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[4] + movq 32(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[3] + movq 24(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 40(%rsp) + # A[1] * A[5] + movq 40(%rsi), %rax + mulq 8(%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * A[4] + movq 32(%rsi), %rax + mulq 16(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 48(%rdi) + # A[2] * A[5] + movq 40(%rsi), %rax + mulq 16(%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[3] * A[4] + movq 32(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 56(%rdi) + # A[3] * A[5] + movq 40(%rsi), %rax + mulq 24(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[4] * A[4] + movq 32(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 64(%rdi) + # A[4] * A[5] + movq 40(%rsi), %rax + mulq 32(%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 72(%rdi) + # A[5] * A[5] + movq 40(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 32(%rsp), %rax + movq 40(%rsp), %rdx + movq %rax, 32(%rdi) + movq %rdx, 40(%rdi) + addq $48, %rsp + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_384_sqr_6,.-sp_384_sqr_6 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_384_cmp_6 +.type sp_384_cmp_6,@function +.align 16 +sp_384_cmp_6: +#else +.globl _sp_384_cmp_6 +.p2align 4 +_sp_384_cmp_6: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $1, %r8 + movq 40(%rdi), %r9 + movq 40(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 32(%rdi), %r9 + movq 32(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_384_cmp_6,.-sp_384_cmp_6 +#endif /* __APPLE__ */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_384_add_6 +.type sp_384_add_6,@function +.align 16 +sp_384_add_6: +#else +.globl _sp_384_add_6 +.p2align 4 +_sp_384_add_6: +#endif /* __APPLE__ */ + # Add + movq (%rsi), %rcx + xorq %rax, %rax + addq (%rdx), %rcx + movq 8(%rsi), %r8 + movq %rcx, (%rdi) + adcq 8(%rdx), %r8 + movq 16(%rsi), %rcx + movq %r8, 8(%rdi) + adcq 16(%rdx), %rcx + movq 24(%rsi), %r8 + movq %rcx, 16(%rdi) + adcq 24(%rdx), %r8 + movq 32(%rsi), %rcx + movq %r8, 24(%rdi) + adcq 32(%rdx), %rcx + movq 40(%rsi), %r8 + movq %rcx, 32(%rdi) + adcq 40(%rdx), %r8 + movq %r8, 40(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_384_add_6,.-sp_384_add_6 +#endif /* __APPLE__ */ +/* Add a to a into r. (r = a + a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_384_dbl_6 +.type sp_384_dbl_6,@function +.align 16 +sp_384_dbl_6: +#else +.globl _sp_384_dbl_6 +.p2align 4 +_sp_384_dbl_6: +#endif /* __APPLE__ */ + movq (%rsi), %rdx + xorq %rax, %rax + addq %rdx, %rdx + movq 8(%rsi), %rcx + movq %rdx, (%rdi) + adcq %rcx, %rcx + movq 16(%rsi), %rdx + movq %rcx, 8(%rdi) + adcq %rdx, %rdx + movq 24(%rsi), %rcx + movq %rdx, 16(%rdi) + adcq %rcx, %rcx + movq 32(%rsi), %rdx + movq %rcx, 24(%rdi) + adcq %rdx, %rdx + movq 40(%rsi), %rcx + movq %rdx, 32(%rdi) + adcq %rcx, %rcx + movq %rcx, 40(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_384_dbl_6,.-sp_384_dbl_6 +#endif /* __APPLE__ */ +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_384_sub_6 +.type sp_384_sub_6,@function +.align 16 +sp_384_sub_6: +#else +.globl _sp_384_sub_6 +.p2align 4 +_sp_384_sub_6: +#endif /* __APPLE__ */ + push %r12 + xorq %rax, %rax + movq (%rsi), %rcx + movq 8(%rsi), %r8 + movq 16(%rsi), %r9 + movq 24(%rsi), %r10 + movq 32(%rsi), %r11 + movq 40(%rsi), %r12 + subq (%rdx), %rcx + sbbq 8(%rdx), %r8 + sbbq 16(%rdx), %r9 + sbbq 24(%rdx), %r10 + sbbq 32(%rdx), %r11 + sbbq 40(%rdx), %r12 + movq %rcx, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + movq %r11, 32(%rdi) + movq %r12, 40(%rdi) + sbbq $0, %rax + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_384_sub_6,.-sp_384_sub_6 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_384_cond_add_6 +.type sp_384_cond_add_6,@function +.align 16 +sp_384_cond_add_6: +#else +.globl _sp_384_cond_add_6 +.p2align 4 +_sp_384_cond_add_6: +#endif /* __APPLE__ */ + subq $48, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + addq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + adcq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + adcq %rdx, %r9 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + adcq $0, %rax + addq $48, %rsp + repz retq +#ifndef __APPLE__ +.size sp_384_cond_add_6,.-sp_384_cond_add_6 +#endif /* __APPLE__ */ +/* 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). + */ +#ifndef __APPLE__ +.globl sp_384_div2_6 +.type sp_384_div2_6,@function +.align 16 +sp_384_div2_6: +#else +.globl _sp_384_div2_6 +.p2align 4 +_sp_384_div2_6: +#endif /* __APPLE__ */ + subq $48, %rsp + movq (%rsi), %rax + movq %rax, %r11 + andq $1, %r11 + negq %r11 + xorq %r10, %r10 + movq (%rdx), %r8 + andq %r11, %r8 + movq %r8, (%rsp) + movq 8(%rdx), %r8 + andq %r11, %r8 + movq %r8, 8(%rsp) + movq 16(%rdx), %r8 + andq %r11, %r8 + movq %r8, 16(%rsp) + movq 24(%rdx), %r8 + andq %r11, %r8 + movq %r8, 24(%rsp) + movq 32(%rdx), %r8 + andq %r11, %r8 + movq %r8, 32(%rsp) + movq 40(%rdx), %r8 + andq %r11, %r8 + movq %r8, 40(%rsp) + addq %rax, (%rsp) + movq 8(%rsi), %rax + adcq %rax, 8(%rsp) + movq 16(%rsi), %rax + adcq %rax, 16(%rsp) + movq 24(%rsi), %rax + adcq %rax, 24(%rsp) + movq 32(%rsi), %rax + adcq %rax, 32(%rsp) + movq 40(%rsi), %rax + adcq %rax, 40(%rsp) + adcq $0, %r10 + movq (%rsp), %rax + movq 8(%rsp), %rcx + shrdq $1, %rcx, %rax + movq %rax, (%rdi) + movq 16(%rsp), %rax + shrdq $1, %rax, %rcx + movq %rcx, 8(%rdi) + movq 24(%rsp), %rcx + shrdq $1, %rcx, %rax + movq %rax, 16(%rdi) + movq 32(%rsp), %rax + shrdq $1, %rax, %rcx + movq %rcx, 24(%rdi) + movq 40(%rsp), %rcx + shrdq $1, %rcx, %rax + movq %rax, 32(%rdi) + shrdq $1, %r10, %rcx + movq %rcx, 40(%rdi) + addq $48, %rsp + repz retq +#ifndef __APPLE__ +.size sp_384_div2_6,.-sp_384_div2_6 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r Result of multiplication. + * a First number to multiply. + * b Second number to multiply. + */ +#ifndef __APPLE__ +.globl sp_384_mul_avx2_6 +.type sp_384_mul_avx2_6,@function +.align 16 +sp_384_mul_avx2_6: +#else +.globl _sp_384_mul_avx2_6 +.p2align 4 +_sp_384_mul_avx2_6: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + movq %rdx, %rax + subq $40, %rsp + xorq %rbx, %rbx + movq (%rsi), %rdx + # A[0] * B[0] + mulxq (%rax), %r9, %r10 + # A[0] * B[1] + mulxq 8(%rax), %rcx, %r11 + adcxq %rcx, %r10 + # A[0] * B[2] + mulxq 16(%rax), %rcx, %r12 + adcxq %rcx, %r11 + # A[0] * B[3] + mulxq 24(%rax), %rcx, %r13 + adcxq %rcx, %r12 + # A[0] * B[4] + mulxq 32(%rax), %rcx, %r14 + adcxq %rcx, %r13 + # A[0] * B[5] + mulxq 40(%rax), %rcx, %r15 + adcxq %rcx, %r14 + adcxq %rbx, %r15 + movq %r9, (%rsp) + movq $0, %r9 + adcxq %rbx, %r9 + xorq %rbx, %rbx + movq 8(%rsi), %rdx + # A[1] * B[0] + mulxq (%rax), %rcx, %r8 + adcxq %rcx, %r10 + adoxq %r8, %r11 + # A[1] * B[1] + mulxq 8(%rax), %rcx, %r8 + adcxq %rcx, %r11 + adoxq %r8, %r12 + # A[1] * B[2] + mulxq 16(%rax), %rcx, %r8 + adcxq %rcx, %r12 + adoxq %r8, %r13 + # A[1] * B[3] + mulxq 24(%rax), %rcx, %r8 + adcxq %rcx, %r13 + adoxq %r8, %r14 + # A[1] * B[4] + mulxq 32(%rax), %rcx, %r8 + adcxq %rcx, %r14 + adoxq %r8, %r15 + # A[1] * B[5] + mulxq 40(%rax), %rcx, %r8 + adcxq %rcx, %r15 + adoxq %r8, %r9 + adcxq %rbx, %r9 + movq %r10, 8(%rsp) + movq $0, %r10 + adcxq %rbx, %r10 + adoxq %rbx, %r10 + xorq %rbx, %rbx + movq 16(%rsi), %rdx + # A[2] * B[0] + mulxq (%rax), %rcx, %r8 + adcxq %rcx, %r11 + adoxq %r8, %r12 + # A[2] * B[1] + mulxq 8(%rax), %rcx, %r8 + adcxq %rcx, %r12 + adoxq %r8, %r13 + # A[2] * B[2] + mulxq 16(%rax), %rcx, %r8 + adcxq %rcx, %r13 + adoxq %r8, %r14 + # A[2] * B[3] + mulxq 24(%rax), %rcx, %r8 + adcxq %rcx, %r14 + adoxq %r8, %r15 + # A[2] * B[4] + mulxq 32(%rax), %rcx, %r8 + adcxq %rcx, %r15 + adoxq %r8, %r9 + # A[2] * B[5] + mulxq 40(%rax), %rcx, %r8 + adcxq %rcx, %r9 + adoxq %r8, %r10 + adcxq %rbx, %r10 + movq %r11, 16(%rsp) + movq $0, %r11 + adcxq %rbx, %r11 + adoxq %rbx, %r11 + xorq %rbx, %rbx + movq 24(%rsi), %rdx + # A[3] * B[0] + mulxq (%rax), %rcx, %r8 + adcxq %rcx, %r12 + adoxq %r8, %r13 + # A[3] * B[1] + mulxq 8(%rax), %rcx, %r8 + adcxq %rcx, %r13 + adoxq %r8, %r14 + # A[3] * B[2] + mulxq 16(%rax), %rcx, %r8 + adcxq %rcx, %r14 + adoxq %r8, %r15 + # A[3] * B[3] + mulxq 24(%rax), %rcx, %r8 + adcxq %rcx, %r15 + adoxq %r8, %r9 + # A[3] * B[4] + mulxq 32(%rax), %rcx, %r8 + adcxq %rcx, %r9 + adoxq %r8, %r10 + # A[3] * B[5] + mulxq 40(%rax), %rcx, %r8 + adcxq %rcx, %r10 + adoxq %r8, %r11 + adcxq %rbx, %r11 + movq %r12, 24(%rsp) + movq $0, %r12 + adcxq %rbx, %r12 + adoxq %rbx, %r12 + xorq %rbx, %rbx + movq 32(%rsi), %rdx + # A[4] * B[0] + mulxq (%rax), %rcx, %r8 + adcxq %rcx, %r13 + adoxq %r8, %r14 + # A[4] * B[1] + mulxq 8(%rax), %rcx, %r8 + adcxq %rcx, %r14 + adoxq %r8, %r15 + # A[4] * B[2] + mulxq 16(%rax), %rcx, %r8 + adcxq %rcx, %r15 + adoxq %r8, %r9 + # A[4] * B[3] + mulxq 24(%rax), %rcx, %r8 + adcxq %rcx, %r9 + adoxq %r8, %r10 + # A[4] * B[4] + mulxq 32(%rax), %rcx, %r8 + adcxq %rcx, %r10 + adoxq %r8, %r11 + # A[4] * B[5] + mulxq 40(%rax), %rcx, %r8 + adcxq %rcx, %r11 + adoxq %r8, %r12 + adcxq %rbx, %r12 + movq %r13, 32(%rsp) + movq 40(%rsi), %rdx + # A[5] * B[0] + mulxq (%rax), %rcx, %r8 + adcxq %rcx, %r14 + adoxq %r8, %r15 + # A[5] * B[1] + mulxq 8(%rax), %rcx, %r8 + adcxq %rcx, %r15 + adoxq %r8, %r9 + # A[5] * B[2] + mulxq 16(%rax), %rcx, %r8 + adcxq %rcx, %r9 + adoxq %r8, %r10 + # A[5] * B[3] + mulxq 24(%rax), %rcx, %r8 + adcxq %rcx, %r10 + adoxq %r8, %r11 + # A[5] * B[4] + mulxq 32(%rax), %rcx, %r8 + adcxq %rcx, %r11 + adoxq %r8, %r12 + # A[5] * B[5] + mulxq 40(%rax), %rcx, %r13 + adcxq %rcx, %r12 + adoxq %rbx, %r13 + adcxq %rbx, %r13 + movq %r14, 40(%rdi) + movq %r15, 48(%rdi) + movq %r9, 56(%rdi) + movq %r10, 64(%rdi) + movq %r11, 72(%rdi) + movq %r12, 80(%rdi) + movq %r13, 88(%rdi) + movq (%rsp), %r9 + movq 8(%rsp), %r10 + movq 16(%rsp), %r11 + movq 24(%rsp), %r12 + movq 32(%rsp), %r13 + movq %r9, (%rdi) + movq %r10, 8(%rdi) + movq %r11, 16(%rdi) + movq %r12, 24(%rdi) + movq %r13, 32(%rdi) + addq $40, %rsp + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_384_mul_avx2_6,.-sp_384_mul_avx2_6 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Reduce the number back to 384 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. + */ +#ifndef __APPLE__ +.globl sp_384_mont_reduce_order_avx2_6 +.type sp_384_mont_reduce_order_avx2_6,@function +.align 16 +sp_384_mont_reduce_order_avx2_6: +#else +.globl _sp_384_mont_reduce_order_avx2_6 +.p2align 4 +_sp_384_mont_reduce_order_avx2_6: +#endif /* __APPLE__ */ + push %r12 + push %r13 + movq %rdx, %rax + xorq %r13, %r13 + movq (%rdi), %r12 + xorq %r11, %r11 +L_mont_loop_order_avx2_6: + # mu = a[i] * mp + movq %r12, %rdx + movq %r12, %r9 + imulq %rax, %rdx + xorq %r11, %r11 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rcx, %r8 + movq 8(%rdi), %r12 + adcxq %rcx, %r9 + adoxq %r8, %r12 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rcx, %r8 + movq 16(%rdi), %r9 + adcxq %rcx, %r12 + adoxq %r8, %r9 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rcx, %r8 + movq 24(%rdi), %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 16(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rcx, %r8 + movq 32(%rdi), %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 24(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rcx, %r8 + movq 40(%rdi), %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 32(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rcx, %r8 + movq 48(%rdi), %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 40(%rdi) + adcxq %r13, %r9 + movq %r9, 48(%rdi) + movq %r11, %r13 + adoxq %r11, %r13 + adcxq %r11, %r13 + # mu = a[i] * mp + movq %r12, %rdx + movq %r12, %r9 + imulq %rax, %rdx + xorq %r11, %r11 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rcx, %r8 + movq 16(%rdi), %r12 + adcxq %rcx, %r9 + adoxq %r8, %r12 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rcx, %r8 + movq 24(%rdi), %r9 + adcxq %rcx, %r12 + adoxq %r8, %r9 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rcx, %r8 + movq 32(%rdi), %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 24(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rcx, %r8 + movq 40(%rdi), %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 32(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rcx, %r8 + movq 48(%rdi), %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 40(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rcx, %r8 + movq 56(%rdi), %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 48(%rdi) + adcxq %r13, %r9 + movq %r9, 56(%rdi) + movq %r11, %r13 + adoxq %r11, %r13 + adcxq %r11, %r13 + # mu = a[i] * mp + movq %r12, %rdx + movq %r12, %r9 + imulq %rax, %rdx + xorq %r11, %r11 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rcx, %r8 + movq 24(%rdi), %r12 + adcxq %rcx, %r9 + adoxq %r8, %r12 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rcx, %r8 + movq 32(%rdi), %r9 + adcxq %rcx, %r12 + adoxq %r8, %r9 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rcx, %r8 + movq 40(%rdi), %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 32(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rcx, %r8 + movq 48(%rdi), %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 40(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rcx, %r8 + movq 56(%rdi), %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 48(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rcx, %r8 + movq 64(%rdi), %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 56(%rdi) + adcxq %r13, %r9 + movq %r9, 64(%rdi) + movq %r11, %r13 + adoxq %r11, %r13 + adcxq %r11, %r13 + # mu = a[i] * mp + movq %r12, %rdx + movq %r12, %r9 + imulq %rax, %rdx + xorq %r11, %r11 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rcx, %r8 + movq 32(%rdi), %r12 + adcxq %rcx, %r9 + adoxq %r8, %r12 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rcx, %r8 + movq 40(%rdi), %r9 + adcxq %rcx, %r12 + adoxq %r8, %r9 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rcx, %r8 + movq 48(%rdi), %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 40(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rcx, %r8 + movq 56(%rdi), %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 48(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rcx, %r8 + movq 64(%rdi), %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 56(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rcx, %r8 + movq 72(%rdi), %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 64(%rdi) + adcxq %r13, %r9 + movq %r9, 72(%rdi) + movq %r11, %r13 + adoxq %r11, %r13 + adcxq %r11, %r13 + # mu = a[i] * mp + movq %r12, %rdx + movq %r12, %r9 + imulq %rax, %rdx + xorq %r11, %r11 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rcx, %r8 + movq 40(%rdi), %r12 + adcxq %rcx, %r9 + adoxq %r8, %r12 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rcx, %r8 + movq 48(%rdi), %r9 + adcxq %rcx, %r12 + adoxq %r8, %r9 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rcx, %r8 + movq 56(%rdi), %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 48(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rcx, %r8 + movq 64(%rdi), %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 56(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rcx, %r8 + movq 72(%rdi), %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 64(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rcx, %r8 + movq 80(%rdi), %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 72(%rdi) + adcxq %r13, %r9 + movq %r9, 80(%rdi) + movq %r11, %r13 + adoxq %r11, %r13 + adcxq %r11, %r13 + # mu = a[i] * mp + movq %r12, %rdx + movq %r12, %r9 + imulq %rax, %rdx + xorq %r11, %r11 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rcx, %r8 + movq 48(%rdi), %r12 + adcxq %rcx, %r9 + adoxq %r8, %r12 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rcx, %r8 + movq 56(%rdi), %r9 + adcxq %rcx, %r12 + adoxq %r8, %r9 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rcx, %r8 + movq 64(%rdi), %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 56(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rcx, %r8 + movq 72(%rdi), %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 64(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rcx, %r8 + movq 80(%rdi), %r10 + adcxq %rcx, %r9 + adoxq %r8, %r10 + movq %r9, 72(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rcx, %r8 + movq 88(%rdi), %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + movq %r10, 80(%rdi) + adcxq %r13, %r9 + movq %r9, 88(%rdi) + movq %r11, %r13 + adoxq %r11, %r13 + adcxq %r11, %r13 + negq %r13 + movq %rdi, %rax + addq $48, %rdi + movq (%rsi), %r8 + movq %r12, %rdx + pextq %r13, %r8, %r8 + subq %r8, %rdx + movq 8(%rsi), %r8 + movq 8(%rdi), %rcx + pextq %r13, %r8, %r8 + movq %rdx, (%rax) + sbbq %r8, %rcx + movq 16(%rsi), %rdx + movq 16(%rdi), %r8 + pextq %r13, %rdx, %rdx + movq %rcx, 8(%rax) + sbbq %rdx, %r8 + movq 24(%rsi), %rcx + movq 24(%rdi), %rdx + pextq %r13, %rcx, %rcx + movq %r8, 16(%rax) + sbbq %rcx, %rdx + movq 32(%rsi), %r8 + movq 32(%rdi), %rcx + pextq %r13, %r8, %r8 + movq %rdx, 24(%rax) + sbbq %r8, %rcx + movq 40(%rsi), %rdx + movq 40(%rdi), %r8 + pextq %r13, %rdx, %rdx + movq %rcx, 32(%rax) + sbbq %rdx, %r8 + movq %r8, 40(%rax) + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_384_mont_reduce_order_avx2_6,.-sp_384_mont_reduce_order_avx2_6 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Square a and put result in r. (r = a * a) + * + * r Result of squaring. + * a Number to square in Montogmery form. + */ +#ifndef __APPLE__ +.globl sp_384_sqr_avx2_6 +.type sp_384_sqr_avx2_6,@function +.align 16 +sp_384_sqr_avx2_6: +#else +.globl _sp_384_sqr_avx2_6 +.p2align 4 +_sp_384_sqr_avx2_6: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + push %rbp + push %rdi + xorq %rdi, %rdi + movq (%rsi), %rdx + movq 8(%rsi), %r15 + movq 16(%rsi), %rbx + movq 24(%rsi), %rbp + # Diagonal 0 + # A[1] * A[0] + mulxq 8(%rsi), %r8, %r9 + # A[2] * A[0] + mulxq 16(%rsi), %rax, %r10 + adcxq %rax, %r9 + # A[3] * A[0] + mulxq 24(%rsi), %rax, %r11 + adcxq %rax, %r10 + # A[4] * A[0] + mulxq 32(%rsi), %rax, %r12 + adcxq %rax, %r11 + # A[5] * A[0] + mulxq 40(%rsi), %rax, %r13 + adcxq %rax, %r12 + adcxq %rdi, %r13 + # Diagonal 1 + movq %r15, %rdx + # A[2] * A[1] + mulxq 16(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * A[1] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * A[1] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r13 + # A[5] * A[1] + mulxq 40(%rsi), %rax, %r14 + adcxq %rax, %r13 + adoxq %rdi, %r14 + movq %rbx, %rdx + # A[5] * A[2] + mulxq 40(%rsi), %rax, %r15 + adcxq %rax, %r14 + adoxq %rdi, %r15 + adcxq %rdi, %r15 + adcxq %rdi, %rbx + # Diagonal 2 + # A[3] * A[2] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r13 + # A[4] * A[2] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r13 + adoxq %rcx, %r14 + movq %rbp, %rdx + # A[4] * A[3] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r14 + adoxq %rcx, %r15 + # A[5] * A[3] + mulxq 40(%rsi), %rax, %rbx + adcxq %rax, %r15 + adoxq %rdi, %rbx + movq 32(%rsi), %rdx + # A[5] * A[4] + mulxq 40(%rsi), %rax, %rbp + adcxq %rax, %rbx + adoxq %rdi, %rbp + adcxq %rdi, %rbp + adcxq %rdi, %rdi + # Doubling previous result as we add in square words results + # A[0] * A[0] + movq (%rsi), %rdx + mulxq %rdx, %rax, %rcx + pop %rdx + movq %rax, (%rdx) + adoxq %r8, %r8 + push %rdx + adcxq %rcx, %r8 + # A[1] * A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r9, %r9 + adcxq %rax, %r9 + adoxq %r10, %r10 + adcxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r11, %r11 + adcxq %rax, %r11 + adoxq %r12, %r12 + adcxq %rcx, %r12 + # A[3] * A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r13, %r13 + adcxq %rax, %r13 + adoxq %r14, %r14 + adcxq %rcx, %r14 + # A[4] * A[4] + movq 32(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r15, %r15 + adcxq %rax, %r15 + adoxq %rbx, %rbx + adcxq %rcx, %rbx + # A[5] * A[5] + movq 40(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %rbp, %rbp + adcxq %rax, %rbp + adcxq %rdi, %rcx + movq $0, %rax + adoxq %rax, %rcx + pop %rdi + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + movq %r11, 32(%rdi) + movq %r12, 40(%rdi) + movq %r13, 48(%rdi) + movq %r14, 56(%rdi) + movq %r15, 64(%rdi) + movq %rbx, 72(%rdi) + movq %rbp, 80(%rdi) + movq %rcx, 88(%rdi) + pop %rbp + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_384_sqr_avx2_6,.-sp_384_sqr_avx2_6 +#endif /* __APPLE__ */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_384_add_one_6 +.type sp_384_add_one_6,@function +.align 16 +sp_384_add_one_6: +#else +.globl _sp_384_add_one_6 +.p2align 4 +_sp_384_add_one_6: +#endif /* __APPLE__ */ + addq $1, (%rdi) + adcq $0, 8(%rdi) + adcq $0, 16(%rdi) + adcq $0, 24(%rdi) + adcq $0, 32(%rdi) + adcq $0, 40(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_384_add_one_6,.-sp_384_add_one_6 +#endif /* __APPLE__ */ +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +#ifndef __APPLE__ +.globl sp_384_from_bin +.type sp_384_from_bin,@function +.align 16 +sp_384_from_bin: +#else +.globl _sp_384_from_bin +.p2align 4 +_sp_384_from_bin: +#endif /* __APPLE__ */ + movq %rdx, %r9 + movq %rdi, %r10 + addq %rcx, %r9 + addq $48, %r10 + xorq %r11, %r11 + jmp L_384_from_bin_64_end +L_384_from_bin_64_start: + subq $64, %r9 + movbeq 56(%r9), %rax + movbeq 48(%r9), %r8 + movq %rax, (%rdi) + movq %r8, 8(%rdi) + movbeq 40(%r9), %rax + movbeq 32(%r9), %r8 + movq %rax, 16(%rdi) + movq %r8, 24(%rdi) + movbeq 24(%r9), %rax + movbeq 16(%r9), %r8 + movq %rax, 32(%rdi) + movq %r8, 40(%rdi) + movbeq 8(%r9), %rax + movbeq (%r9), %r8 + movq %rax, 48(%rdi) + movq %r8, 56(%rdi) + addq $64, %rdi + subq $64, %rcx +L_384_from_bin_64_end: + cmpq $63, %rcx + jg L_384_from_bin_64_start + jmp L_384_from_bin_8_end +L_384_from_bin_8_start: + subq $8, %r9 + movbeq (%r9), %rax + movq %rax, (%rdi) + addq $8, %rdi + subq $8, %rcx +L_384_from_bin_8_end: + cmpq $7, %rcx + jg L_384_from_bin_8_start + cmpq %r11, %rcx + je L_384_from_bin_hi_end + movq %r11, %r8 + movq %r11, %rax +L_384_from_bin_hi_start: + movb (%rdx), %al + shlq $8, %r8 + incq %rdx + addq %rax, %r8 + decq %rcx + jg L_384_from_bin_hi_start + movq %r8, (%rdi) + addq $8, %rdi +L_384_from_bin_hi_end: + cmpq %r10, %rdi + je L_384_from_bin_zero_end +L_384_from_bin_zero_start: + movq %r11, (%rdi) + addq $8, %rdi + cmpq %r10, %rdi + jl L_384_from_bin_zero_start +L_384_from_bin_zero_end: + repz retq +#ifndef __APPLE__ +.size sp_384_from_bin,.-sp_384_from_bin +#endif /* __APPLE__ */ +/* Write r as big endian to byte array. + * Fixed length number of bytes written: 48 + * + * r A single precision integer. + * a Byte array. + */ +#ifndef __APPLE__ +.globl sp_384_to_bin +.type sp_384_to_bin,@function +.align 16 +sp_384_to_bin: +#else +.globl _sp_384_to_bin +.p2align 4 +_sp_384_to_bin: +#endif /* __APPLE__ */ + movbeq 40(%rdi), %rdx + movbeq 32(%rdi), %rax + movq %rdx, (%rsi) + movq %rax, 8(%rsi) + movbeq 24(%rdi), %rdx + movbeq 16(%rdi), %rax + movq %rdx, 16(%rsi) + movq %rax, 24(%rsi) + movbeq 8(%rdi), %rdx + movbeq (%rdi), %rax + movq %rdx, 32(%rsi) + movq %rax, 40(%rsi) + repz retq +#ifndef __APPLE__ +.size sp_384_to_bin,.-sp_384_to_bin +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_384_sub_in_place_6 +.type sp_384_sub_in_place_6,@function +.align 16 +sp_384_sub_in_place_6: +#else +.globl _sp_384_sub_in_place_6 +.p2align 4 +_sp_384_sub_in_place_6: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rsi), %rdx + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + movq 32(%rsi), %r10 + movq 40(%rsi), %r11 + subq %rdx, (%rdi) + sbbq %rcx, 8(%rdi) + sbbq %r8, 16(%rdi) + sbbq %r9, 24(%rdi) + sbbq %r10, 32(%rdi) + sbbq %r11, 40(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_384_sub_in_place_6,.-sp_384_sub_in_place_6 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_384_cond_sub_avx2_6 +.type sp_384_cond_sub_avx2_6,@function +.align 16 +sp_384_cond_sub_avx2_6: +#else +.globl _sp_384_cond_sub_avx2_6 +.p2align 4 +_sp_384_cond_sub_avx2_6: +#endif /* __APPLE__ */ + movq $0, %rax + movq (%rdx), %r10 + movq (%rsi), %r8 + pextq %rcx, %r10, %r10 + subq %r10, %r8 + movq 8(%rdx), %r10 + movq 8(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, (%rdi) + sbbq %r10, %r9 + movq 16(%rdx), %r8 + movq 16(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 8(%rdi) + sbbq %r8, %r10 + movq 24(%rdx), %r9 + movq 24(%rsi), %r8 + pextq %rcx, %r9, %r9 + movq %r10, 16(%rdi) + sbbq %r9, %r8 + movq 32(%rdx), %r10 + movq 32(%rsi), %r9 + pextq %rcx, %r10, %r10 + movq %r8, 24(%rdi) + sbbq %r10, %r9 + movq 40(%rdx), %r8 + movq 40(%rsi), %r10 + pextq %rcx, %r8, %r8 + movq %r9, 32(%rdi) + sbbq %r8, %r10 + movq %r10, 40(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_384_cond_sub_avx2_6,.-sp_384_cond_sub_avx2_6 +#endif /* __APPLE__ */ +/* 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. + */ +#ifndef __APPLE__ +.globl sp_384_mul_d_6 +.type sp_384_mul_d_6,@function +.align 16 +sp_384_mul_d_6: +#else +.globl _sp_384_mul_d_6 +.p2align 4 +_sp_384_mul_d_6: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 24(%rsi) + addq %rax, %r8 + movq %r8, 24(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 32(%rsi) + addq %rax, %r9 + movq %r9, 32(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B + movq %rcx, %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + movq %r10, 40(%rdi) + movq %r8, 48(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_384_mul_d_6,.-sp_384_mul_d_6 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* 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. + */ +#ifndef __APPLE__ +.globl sp_384_mul_d_avx2_6 +.type sp_384_mul_d_avx2_6,@function +.align 16 +sp_384_mul_d_avx2_6: +#else +.globl _sp_384_mul_d_avx2_6 +.p2align 4 +_sp_384_mul_d_avx2_6: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 8(%rdi) + adoxq %r8, %r9 + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 16(%rdi) + adoxq %r8, %r10 + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 24(%rdi) + adoxq %r8, %r9 + # A[4] * B + mulxq 32(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 32(%rdi) + adoxq %r8, %r10 + # A[5] * B + mulxq 40(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 40(%rdi) + movq %r9, 48(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_384_mul_d_avx2_6,.-sp_384_mul_d_avx2_6 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#endif /* WOLFSSL_SP_384 */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/srp.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/srp.c new file mode 100644 index 000000000..cf5eff19a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/srp.c @@ -0,0 +1,756 @@ +/* srp.c + * + * Copyright (C) 2006-2020 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 WOLFCRYPT_HAVE_SRP + +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/** Computes the session key using the Mask Generation Function 1. */ +static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size); + +static int SrpHashInit(SrpHash* hash, SrpType type) +{ + hash->type = type; + + switch (type) { + case SRP_TYPE_SHA: + #ifndef NO_SHA + return wc_InitSha(&hash->data.sha); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA256: + #ifndef NO_SHA256 + return wc_InitSha256(&hash->data.sha256); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + return wc_InitSha384(&hash->data.sha384); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + return wc_InitSha512(&hash->data.sha512); + #else + return BAD_FUNC_ARG; + #endif + + default: + return BAD_FUNC_ARG; + } +} + +static int SrpHashUpdate(SrpHash* hash, const byte* data, word32 size) +{ + switch (hash->type) { + case SRP_TYPE_SHA: + #ifndef NO_SHA + return wc_ShaUpdate(&hash->data.sha, data, size); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA256: + #ifndef NO_SHA256 + return wc_Sha256Update(&hash->data.sha256, data, size); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + return wc_Sha384Update(&hash->data.sha384, data, size); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + return wc_Sha512Update(&hash->data.sha512, data, size); + #else + return BAD_FUNC_ARG; + #endif + + default: + return BAD_FUNC_ARG; + } +} + +static int SrpHashFinal(SrpHash* hash, byte* digest) +{ + switch (hash->type) { + case SRP_TYPE_SHA: + #ifndef NO_SHA + return wc_ShaFinal(&hash->data.sha, digest); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA256: + #ifndef NO_SHA256 + return wc_Sha256Final(&hash->data.sha256, digest); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + return wc_Sha384Final(&hash->data.sha384, digest); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + return wc_Sha512Final(&hash->data.sha512, digest); + #else + return BAD_FUNC_ARG; + #endif + + default: + return BAD_FUNC_ARG; + } +} + +static word32 SrpHashSize(SrpType type) +{ + switch (type) { + case SRP_TYPE_SHA: + #ifndef NO_SHA + return WC_SHA_DIGEST_SIZE; + #else + return 0; + #endif + + case SRP_TYPE_SHA256: + #ifndef NO_SHA256 + return WC_SHA256_DIGEST_SIZE; + #else + return 0; + #endif + + case SRP_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + return WC_SHA384_DIGEST_SIZE; + #else + return 0; + #endif + + case SRP_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + return WC_SHA512_DIGEST_SIZE; + #else + return 0; + #endif + + default: + return 0; + } +} + +int wc_SrpInit(Srp* srp, SrpType type, SrpSide side) +{ + int r; + + /* validating params */ + + if (!srp) + return BAD_FUNC_ARG; + + if (side != SRP_CLIENT_SIDE && side != SRP_SERVER_SIDE) + return BAD_FUNC_ARG; + + switch (type) { + case SRP_TYPE_SHA: + #ifdef NO_SHA + return NOT_COMPILED_IN; + #else + break; /* OK */ + #endif + + case SRP_TYPE_SHA256: + #ifdef NO_SHA256 + return NOT_COMPILED_IN; + #else + break; /* OK */ + #endif + + case SRP_TYPE_SHA384: + #ifndef WOLFSSL_SHA384 + return NOT_COMPILED_IN; + #else + break; /* OK */ + #endif + + case SRP_TYPE_SHA512: + #ifndef WOLFSSL_SHA512 + return NOT_COMPILED_IN; + #else + break; /* OK */ + #endif + + default: + return BAD_FUNC_ARG; + } + + /* initializing variables */ + + XMEMSET(srp, 0, sizeof(Srp)); + + if ((r = SrpHashInit(&srp->client_proof, type)) != 0) + return r; + + if ((r = SrpHashInit(&srp->server_proof, type)) != 0) + return r; + + if ((r = mp_init_multi(&srp->N, &srp->g, &srp->auth, + &srp->priv, 0, 0)) != 0) + return r; + + srp->side = side; srp->type = type; + srp->salt = NULL; srp->saltSz = 0; + srp->user = NULL; srp->userSz = 0; + srp->key = NULL; srp->keySz = 0; + + srp->keyGenFunc_cb = wc_SrpSetKey; + + /* default heap hint to NULL or test value */ +#ifdef WOLFSSL_HEAP_TEST + srp->heap = (void*)WOLFSSL_HEAP_TEST; +#else + srp->heap = NULL; +#endif + + return 0; +} + +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); + } + if (srp->user) { + ForceZero(srp->user, srp->userSz); + XFREE(srp->user, srp->heap, DYNAMIC_TYPE_SRP); + } + if (srp->key) { + ForceZero(srp->key, srp->keySz); + XFREE(srp->key, srp->heap, DYNAMIC_TYPE_SRP); + } + + ForceZero(srp, sizeof(Srp)); + } +} + +int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size) +{ + if (!srp || !username) + return BAD_FUNC_ARG; + + srp->user = (byte*)XMALLOC(size, srp->heap, DYNAMIC_TYPE_SRP); + if (srp->user == NULL) + return MEMORY_E; + + srp->userSz = size; + XMEMCPY(srp->user, username, srp->userSz); + + return 0; +} + +int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, + const byte* g, word32 gSz, + const byte* salt, word32 saltSz) +{ + SrpHash hash; + byte digest1[SRP_MAX_DIGEST_SIZE]; + byte digest2[SRP_MAX_DIGEST_SIZE]; + byte pad = 0; + int i, r; + int j = 0; + + if (!srp || !N || !g || !salt || nSz < gSz) + return BAD_FUNC_ARG; + + if (!srp->user) + return SRP_CALL_ORDER_E; + + /* Set N */ + if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) + return MP_READ_E; + + if (mp_count_bits(&srp->N) < SRP_MODULUS_MIN_BITS) + return BAD_FUNC_ARG; + + /* Set g */ + if (mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) + return MP_READ_E; + + if (mp_cmp(&srp->N, &srp->g) != MP_GT) + return BAD_FUNC_ARG; + + /* Set salt */ + if (srp->salt) { + ForceZero(srp->salt, srp->saltSz); + XFREE(srp->salt, srp->heap, DYNAMIC_TYPE_SRP); + } + + srp->salt = (byte*)XMALLOC(saltSz, srp->heap, DYNAMIC_TYPE_SRP); + if (srp->salt == NULL) + return MEMORY_E; + + XMEMCPY(srp->salt, salt, saltSz); + srp->saltSz = saltSz; + + /* 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++) { + if (!r) r = SrpHashUpdate(&hash, &pad, 1); + } + if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); + if (!r) r = SrpHashFinal(&hash, srp->k); + + /* update client proof */ + + /* digest1 = H(N) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); + if (!r) r = SrpHashFinal(&hash, digest1); + + /* digest2 = H(g) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); + if (!r) r = SrpHashFinal(&hash, digest2); + + /* digest1 = H(N) ^ H(g) */ + if (r == 0) { + for (i = 0, j = SrpHashSize(srp->type); i < j; i++) + digest1[i] ^= digest2[i]; + } + + /* digest2 = H(user) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); + if (!r) r = SrpHashFinal(&hash, digest2); + + /* client proof = H( H(N) ^ H(g) | H(user) | salt) */ + if (!r) r = SrpHashUpdate(&srp->client_proof, digest1, j); + if (!r) r = SrpHashUpdate(&srp->client_proof, digest2, j); + if (!r) r = SrpHashUpdate(&srp->client_proof, salt, saltSz); + + return r; +} + +int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) +{ + SrpHash hash; + byte digest[SRP_MAX_DIGEST_SIZE]; + word32 digestSz; + int r; + + if (!srp || !password || srp->side != SRP_CLIENT_SIDE) + return BAD_FUNC_ARG; + + if (!srp->salt) + return SRP_CALL_ORDER_E; + + digestSz = SrpHashSize(srp->type); + + /* digest = H(username | ':' | password) */ + r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); + if (!r) r = SrpHashUpdate(&hash, (const byte*) ":", 1); + if (!r) r = SrpHashUpdate(&hash, password, size); + if (!r) r = SrpHashFinal(&hash, digest); + + /* digest = H(salt | H(username | ':' | password)) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, srp->salt, srp->saltSz); + if (!r) r = SrpHashUpdate(&hash, digest, digestSz); + if (!r) r = SrpHashFinal(&hash, digest); + + /* Set x (private key) */ + if (!r) r = mp_read_unsigned_bin(&srp->auth, digest, digestSz); + + ForceZero(digest, SRP_MAX_DIGEST_SIZE); + + return r; +} + +int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size) +{ + mp_int v; + int r; + + if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE) + return BAD_FUNC_ARG; + + if (mp_iszero(&srp->auth) == MP_YES) + return SRP_CALL_ORDER_E; + + r = mp_init(&v); + if (r != MP_OKAY) + return MP_INIT_E; + + /* v = g ^ x % N */ + if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &v); + if (!r) r = *size < (word32)mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY; + if (!r) r = mp_to_unsigned_bin(&v, verifier); + if (!r) *size = mp_unsigned_bin_size(&v); + + mp_clear(&v); + + return r; +} + +int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size) +{ + if (!srp || !verifier || srp->side != SRP_SERVER_SIDE) + return BAD_FUNC_ARG; + + return mp_read_unsigned_bin(&srp->auth, verifier, size); +} + +int wc_SrpSetPrivate(Srp* srp, const byte* priv, word32 size) +{ + mp_int p; + int r; + + if (!srp || !priv || !size) + return BAD_FUNC_ARG; + + if (mp_iszero(&srp->auth) == MP_YES) + return SRP_CALL_ORDER_E; + + r = mp_init(&p); + if (r != MP_OKAY) + return MP_INIT_E; + if (!r) r = mp_read_unsigned_bin(&p, priv, size); + if (!r) r = mp_mod(&p, &srp->N, &srp->priv); + if (!r) r = mp_iszero(&srp->priv) == MP_YES ? SRP_BAD_KEY_E : 0; + + mp_clear(&p); + + return r; +} + +/** Generates random data using wolfcrypt RNG. */ +static int wc_SrpGenPrivate(Srp* srp, byte* priv, word32 size) +{ + WC_RNG rng; + int r = wc_InitRng(&rng); + + if (!r) r = wc_RNG_GenerateBlock(&rng, priv, size); + if (!r) r = wc_SrpSetPrivate(srp, priv, size); + if (!r) wc_FreeRng(&rng); + + return r; +} + +int wc_SrpGetPublic(Srp* srp, byte* pub, word32* size) +{ + mp_int pubkey; + word32 modulusSz; + int r; + + if (!srp || !pub || !size) + return BAD_FUNC_ARG; + + if (mp_iszero(&srp->auth) == MP_YES) + return SRP_CALL_ORDER_E; + + modulusSz = mp_unsigned_bin_size(&srp->N); + if (*size < modulusSz) + return BUFFER_E; + + r = mp_init(&pubkey); + if (r != MP_OKAY) + return MP_INIT_E; + + /* priv = random() */ + if (mp_iszero(&srp->priv) == MP_YES) + r = wc_SrpGenPrivate(srp, pub, SRP_PRIVATE_KEY_MIN_BITS / 8); + + /* client side: A = g ^ a % N */ + if (srp->side == SRP_CLIENT_SIDE) { + if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); + + /* server side: B = (k * v + (g ^ b % N)) % N */ + } else { + mp_int i, j; + + if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) { + if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type)); + if (!r) r = mp_iszero(&i) == MP_YES ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); + if (!r) r = mp_mulmod(&i, &srp->auth, &srp->N, &j); + if (!r) r = mp_add(&j, &pubkey, &i); + if (!r) r = mp_mod(&i, &srp->N, &pubkey); + + mp_clear(&i); mp_clear(&j); + } + } + + /* extract public key to buffer */ + XMEMSET(pub, 0, modulusSz); + if (!r) r = mp_to_unsigned_bin(&pubkey, pub); + if (!r) *size = mp_unsigned_bin_size(&pubkey); + mp_clear(&pubkey); + + return r; +} + +static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) +{ + SrpHash hash; + byte digest[SRP_MAX_DIGEST_SIZE]; + word32 i, j, digestSz = SrpHashSize(srp->type); + 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; + + srp->keySz = 2 * digestSz; + + for (i = j = 0; j < srp->keySz; i++) { + counter[0] = (i >> 24) & 0xFF; + counter[1] = (i >> 16) & 0xFF; + counter[2] = (i >> 8) & 0xFF; + counter[3] = i & 0xFF; + + r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, secret, size); + if (!r) r = SrpHashUpdate(&hash, counter, 4); + + if (j + digestSz > srp->keySz) { + if (!r) r = SrpHashFinal(&hash, digest); + XMEMCPY(srp->key + j, digest, srp->keySz - j); + j = srp->keySz; + } + else { + if (!r) r = SrpHashFinal(&hash, srp->key + j); + j += digestSz; + } + } + + ForceZero(digest, sizeof(digest)); + ForceZero(&hash, sizeof(SrpHash)); + + return r; +} + +int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, + byte* serverPubKey, word32 serverPubKeySz) +{ + SrpHash hash; + byte *secret; + byte digest[SRP_MAX_DIGEST_SIZE]; + word32 i, secretSz, digestSz; + mp_int u, s, temp1, temp2; + byte pad = 0; + int r; + + /* validating params */ + + if (!srp || !clientPubKey || clientPubKeySz == 0 + || !serverPubKey || serverPubKeySz == 0) + return BAD_FUNC_ARG; + + if (mp_iszero(&srp->priv) == MP_YES) + return SRP_CALL_ORDER_E; + + /* initializing variables */ + + if ((r = SrpHashInit(&hash, srp->type)) != 0) + return r; + + digestSz = SrpHashSize(srp->type); + secretSz = mp_unsigned_bin_size(&srp->N); + + if ((secret = (byte*)XMALLOC(secretSz, srp->heap, DYNAMIC_TYPE_SRP)) ==NULL) + return MEMORY_E; + + if ((r = mp_init_multi(&u, &s, &temp1, &temp2, 0, 0)) != MP_OKAY) { + XFREE(secret, srp->heap, DYNAMIC_TYPE_SRP); + return r; + } + + /* building u (random scrambling parameter) */ + + /* H(A) */ + for (i = 0; !r && i < secretSz - clientPubKeySz; i++) + r = SrpHashUpdate(&hash, &pad, 1); + if (!r) r = SrpHashUpdate(&hash, clientPubKey, clientPubKeySz); + + /* H(A | B) */ + for (i = 0; !r && i < secretSz - serverPubKeySz; i++) + r = SrpHashUpdate(&hash, &pad, 1); + if (!r) r = SrpHashUpdate(&hash, serverPubKey, serverPubKeySz); + + /* set u */ + if (!r) r = SrpHashFinal(&hash, digest); + if (!r) r = mp_read_unsigned_bin(&u, digest, SrpHashSize(srp->type)); + + /* building s (secret) */ + + if (!r && srp->side == SRP_CLIENT_SIDE) { + + /* temp1 = B - k * v; rejects k == 0, B == 0 and B >= N. */ + r = mp_read_unsigned_bin(&temp1, srp->k, digestSz); + if (!r) r = mp_iszero(&temp1) == MP_YES ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &temp2); + if (!r) r = mp_mulmod(&temp1, &temp2, &srp->N, &s); + if (!r) r = mp_read_unsigned_bin(&temp2, serverPubKey, serverPubKeySz); + if (!r) r = mp_iszero(&temp2) == MP_YES ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_cmp(&temp2, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_sub(&temp2, &s, &temp1); + + /* temp2 = a + u * x */ + if (!r) r = mp_mulmod(&u, &srp->auth, &srp->N, &s); + if (!r) r = mp_add(&srp->priv, &s, &temp2); + + /* secret = temp1 ^ temp2 % N */ + if (!r) r = mp_exptmod(&temp1, &temp2, &srp->N, &s); + + } else if (!r && srp->side == SRP_SERVER_SIDE) { + /* temp1 = v ^ u % N */ + r = mp_exptmod(&srp->auth, &u, &srp->N, &temp1); + + /* temp2 = A * temp1 % N; rejects A == 0, A >= N */ + if (!r) r = mp_read_unsigned_bin(&s, clientPubKey, clientPubKeySz); + if (!r) r = mp_iszero(&s) == MP_YES ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_cmp(&s, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_mulmod(&s, &temp1, &srp->N, &temp2); + + /* rejects A * v ^ u % N >= 1, A * v ^ u % N == -1 % N */ + if (!r) r = mp_read_unsigned_bin(&temp1, (const byte*)"\001", 1); + if (!r) r = mp_cmp(&temp2, &temp1) != MP_GT ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_sub(&srp->N, &temp1, &s); + if (!r) r = mp_cmp(&temp2, &s) == MP_EQ ? SRP_BAD_KEY_E : 0; + + /* secret = temp2 * b % N */ + if (!r) r = mp_exptmod(&temp2, &srp->priv, &srp->N, &s); + } + + /* building session key from secret */ + + if (!r) r = mp_to_unsigned_bin(&s, secret); + if (!r) r = srp->keyGenFunc_cb(srp, secret, mp_unsigned_bin_size(&s)); + + /* updating client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ + + if (!r) r = SrpHashUpdate(&srp->client_proof, clientPubKey, clientPubKeySz); + if (!r) r = SrpHashUpdate(&srp->client_proof, serverPubKey, serverPubKeySz); + if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, srp->keySz); + + /* updating server proof = H(A) */ + + if (!r) r = SrpHashUpdate(&srp->server_proof, clientPubKey, clientPubKeySz); + + XFREE(secret, srp->heap, DYNAMIC_TYPE_SRP); + mp_clear(&u); mp_clear(&s); mp_clear(&temp1); mp_clear(&temp2); + + return r; +} + +int wc_SrpGetProof(Srp* srp, byte* proof, word32* size) +{ + int r; + + if (!srp || !proof || !size) + return BAD_FUNC_ARG; + + if (*size < SrpHashSize(srp->type)) + return BUFFER_E; + + if ((r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE + ? &srp->client_proof + : &srp->server_proof, proof)) != 0) + return r; + + *size = SrpHashSize(srp->type); + + if (srp->side == SRP_CLIENT_SIDE) { + /* server proof = H( A | client proof | K) */ + if (!r) r = SrpHashUpdate(&srp->server_proof, proof, *size); + if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz); + } + + return r; +} + +int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size) +{ + byte digest[SRP_MAX_DIGEST_SIZE]; + int r; + + if (!srp || !proof) + return BAD_FUNC_ARG; + + if (size != SrpHashSize(srp->type)) + return BUFFER_E; + + r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE ? &srp->server_proof + : &srp->client_proof, digest); + + if (srp->side == SRP_SERVER_SIDE) { + /* server proof = H( A | client proof | K) */ + if (!r) r = SrpHashUpdate(&srp->server_proof, proof, size); + if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz); + } + + if (!r && XMEMCMP(proof, digest, size) != 0) + r = SRP_VERIFY_E; + + return r; +} + +#endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/tfm.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/tfm.c index 2c1e86c31..61b31f0e1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/tfm.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/tfm.c @@ -1,8 +1,8 @@ /* tfm.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,18 +16,19 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* * Based on public domain TomsFastMath 0.10 by Tom St Denis, tomstdenis@iahu.ca, * http://math.libtomcrypt.com */ /** - * Edited by Moisés Guimarães (moisesguimaraesm@gmail.com) - * to fit CyaSSL's needs. + * Edited by Moises Guimaraes (moises@wolfssl.com) + * to fit wolfSSL's needs. */ #ifdef HAVE_CONFIG_H @@ -36,19 +37,62 @@ /* in case user set USE_FAST_MATH there */ #include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif #ifdef USE_FAST_MATH +#include #include #include /* will define asm MACROS or C ones */ +#include /* common functions */ + +#if defined(FREESCALE_LTC_TFM) + #include +#endif +#ifdef WOLFSSL_DEBUG_MATH + #include +#endif + +#ifdef USE_WINDOWS_API + #pragma warning(disable:4127) + /* Disables the warning: + * 4127: conditional expression is constant + * in this file. + */ +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifdef __cplusplus + extern "C" { +#endif +WOLFSSL_LOCAL int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +#ifdef __cplusplus + } /* extern "C" */ +#endif +#endif +#ifndef WOLFSSL_SP_MATH /* math settings check */ word32 CheckRunTimeSettings(void) { return CTC_SETTINGS; } - +#endif /* math settings size check */ word32 CheckRunTimeFastMath(void) @@ -92,12 +136,12 @@ void fp_add(fp_int *a, fp_int *b, fp_int *c) void s_fp_add(fp_int *a, fp_int *b, fp_int *c) { int x, y, oldused; - register fp_word t; + fp_word t; y = MAX(a->used, b->used); oldused = MIN(c->used, FP_SIZE); /* help static analysis w/ largest size */ c->used = y; - + t = 0; for (x = 0; x < y; x++) { t += ((fp_word)a->dp[x]) + ((fp_word)b->dp[x]); @@ -110,6 +154,8 @@ void s_fp_add(fp_int *a, fp_int *b, fp_int *c) } c->used = x; + + /* zero any excess digits on the destination that we didn't write to */ for (; x < oldused; x++) { c->dp[x] = 0; } @@ -171,6 +217,8 @@ void s_fp_sub(fp_int *a, fp_int *b, fp_int *c) c->dp[x] = (fp_digit)t; t = (t >> DIGIT_BIT)&1; } + + /* zero any excess digits on the destination that we didn't write to */ for (; x < oldused; x++) { c->dp[x] = 0; } @@ -178,149 +226,166 @@ void s_fp_sub(fp_int *a, fp_int *b, fp_int *c) } /* c = a * b */ -void fp_mul(fp_int *A, fp_int *B, fp_int *C) +int fp_mul(fp_int *A, fp_int *B, fp_int *C) { - int y, yy; + int ret = 0; + int y, yy, oldused; + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + ret = esp_mp_mul(A, B, C); + if(ret != -2) return ret; +#endif + + oldused = C->used; y = MAX(A->used, B->used); yy = MIN(A->used, B->used); /* call generic if we're out of range */ if (y + yy > FP_SIZE) { - fp_mul_comba(A, B, C); - return ; + ret = fp_mul_comba(A, B, C); + goto clean; } /* pick a comba (unrolled 4/8/16/32 x or rolled) based on the size - of the largest input. We also want to avoid doing excess mults if the + of the largest input. We also want to avoid doing excess mults if the inputs are not close to the next power of two. That is, for example, - if say y=17 then we would do (32-17)^2 = 225 unneeded multiplications + if say y=17 then we would do (32-17)^2 = 225 unneeded multiplications */ -#ifdef TFM_MUL3 +#if defined(TFM_MUL3) && FP_SIZE >= 6 if (y <= 3) { - fp_mul_comba3(A,B,C); - return; + ret = fp_mul_comba3(A,B,C); + goto clean; } #endif -#ifdef TFM_MUL4 +#if defined(TFM_MUL4) && FP_SIZE >= 8 if (y == 4) { - fp_mul_comba4(A,B,C); - return; + ret = fp_mul_comba4(A,B,C); + goto clean; } #endif -#ifdef TFM_MUL6 +#if defined(TFM_MUL6) && FP_SIZE >= 12 if (y <= 6) { - fp_mul_comba6(A,B,C); - return; + ret = fp_mul_comba6(A,B,C); + goto clean; } #endif -#ifdef TFM_MUL7 +#if defined(TFM_MUL7) && FP_SIZE >= 14 if (y == 7) { - fp_mul_comba7(A,B,C); - return; + ret = fp_mul_comba7(A,B,C); + goto clean; } #endif -#ifdef TFM_MUL8 +#if defined(TFM_MUL8) && FP_SIZE >= 16 if (y == 8) { - fp_mul_comba8(A,B,C); - return; + ret = fp_mul_comba8(A,B,C); + goto clean; } #endif -#ifdef TFM_MUL9 +#if defined(TFM_MUL9) && FP_SIZE >= 18 if (y == 9) { - fp_mul_comba9(A,B,C); - return; + ret = fp_mul_comba9(A,B,C); + goto clean; } #endif -#ifdef TFM_MUL12 +#if defined(TFM_MUL12) && FP_SIZE >= 24 if (y <= 12) { - fp_mul_comba12(A,B,C); - return; + ret = fp_mul_comba12(A,B,C); + goto clean; } #endif -#ifdef TFM_MUL17 +#if defined(TFM_MUL17) && FP_SIZE >= 34 if (y <= 17) { - fp_mul_comba17(A,B,C); - return; + ret = fp_mul_comba17(A,B,C); + goto clean; } #endif -#ifdef TFM_SMALL_SET +#if defined(TFM_SMALL_SET) && FP_SIZE >= 32 if (y <= 16) { - fp_mul_comba_small(A,B,C); - return; + ret = fp_mul_comba_small(A,B,C); + goto clean; } -#endif -#if defined(TFM_MUL20) +#endif +#if defined(TFM_MUL20) && FP_SIZE >= 40 if (y <= 20) { - fp_mul_comba20(A,B,C); - return; + ret = fp_mul_comba20(A,B,C); + goto clean; } #endif -#if defined(TFM_MUL24) +#if defined(TFM_MUL24) && FP_SIZE >= 48 if (yy >= 16 && y <= 24) { - fp_mul_comba24(A,B,C); - return; + ret = fp_mul_comba24(A,B,C); + goto clean; } #endif -#if defined(TFM_MUL28) +#if defined(TFM_MUL28) && FP_SIZE >= 56 if (yy >= 20 && y <= 28) { - fp_mul_comba28(A,B,C); - return; + ret = fp_mul_comba28(A,B,C); + goto clean; } #endif -#if defined(TFM_MUL32) +#if defined(TFM_MUL32) && FP_SIZE >= 64 if (yy >= 24 && y <= 32) { - fp_mul_comba32(A,B,C); - return; + ret = fp_mul_comba32(A,B,C); + goto clean; } #endif -#if defined(TFM_MUL48) +#if defined(TFM_MUL48) && FP_SIZE >= 96 if (yy >= 40 && y <= 48) { - fp_mul_comba48(A,B,C); - return; - } -#endif -#if defined(TFM_MUL64) - if (yy >= 56 && y <= 64) { - fp_mul_comba64(A,B,C); - return; + ret = fp_mul_comba48(A,B,C); + goto clean; } #endif - fp_mul_comba(A,B,C); +#if defined(TFM_MUL64) && FP_SIZE >= 128 + if (yy >= 56 && y <= 64) { + ret = fp_mul_comba64(A,B,C); + goto clean; + } +#endif + ret = fp_mul_comba(A,B,C); + +clean: + /* zero any excess digits on the destination that we didn't write to */ + for (y = C->used; y >= 0 && y < oldused; y++) { + C->dp[y] = 0; + } + + return ret; } void fp_mul_2(fp_int * a, fp_int * b) { int x, oldused; - + oldused = b->used; b->used = a->used; { - register fp_digit r, rr, *tmpa, *tmpb; + fp_digit r, rr, *tmpa, *tmpb; /* alias for source */ tmpa = a->dp; - + /* alias for dest */ tmpb = b->dp; /* carry */ r = 0; for (x = 0; x < a->used; x++) { - - /* get what will be the *next* carry bit from the - * MSB of the current digit + + /* get what will be the *next* carry bit from the + * MSB of the current digit */ rr = *tmpa >> ((fp_digit)(DIGIT_BIT - 1)); - + /* now shift up this digit, add in the carry [from the previous] */ *tmpb++ = ((*tmpa++ << ((fp_digit)1)) | r); - - /* copy the carry that would be from the source - * digit into the next iteration + + /* copy the carry that would be from the source + * digit into the next iteration */ r = rr; } @@ -332,9 +397,7 @@ void fp_mul_2(fp_int * a, fp_int * b) ++(b->used); } - /* now zero any excess digits on the destination - * that we didn't write to - */ + /* zero any excess digits on the destination that we didn't write to */ tmpb = b->dp + b->used; for (x = b->used; x < oldused; x++) { *tmpb++ = 0; @@ -362,7 +425,10 @@ void fp_mul_d(fp_int *a, fp_digit b, fp_int *c) c->dp[c->used++] = (fp_digit) w; ++x; } - for (; x < oldused; x++) { + + /* zero any excess digits on the destination that we didn't write to */ + /* also checking FP_SIZE here for static analysis */ + for (; x < oldused && x < FP_SIZE; x++) { c->dp[x] = 0; } fp_clamp(c); @@ -385,7 +451,7 @@ void fp_mul_2d(fp_int *a, int b, fp_int *c) /* shift the digits */ if (b != 0) { - carry = 0; + carry = 0; shift = DIGIT_BIT - b; for (x = 0; x < c->used; x++) { carrytmp = c->dp[x] >> shift; @@ -403,24 +469,37 @@ void fp_mul_2d(fp_int *a, int b, fp_int *c) /* generic PxQ multiplier */ #if defined(HAVE_INTEL_MULX) -INLINE static void fp_mul_comba_mulx(fp_int *A, fp_int *B, fp_int *C) +WC_INLINE static int fp_mul_comba_mulx(fp_int *A, fp_int *B, fp_int *C) -{ +{ int ix, iy, iz, pa; - fp_int tmp, *dst; + fp_int *dst; +#ifndef WOLFSSL_SMALL_STACK + fp_int tmp[1]; +#else + fp_int *tmp; +#endif + + /* Variables used but not seen by cppcheck. */ + (void)ix; (void)iy; (void)iz; + +#ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (tmp == NULL) + return FP_MEM; +#endif /* get size of output and trim */ pa = A->used + B->used; if (pa >= FP_SIZE) { pa = FP_SIZE-1; } - - if (A == C || B == C) { - fp_init(&tmp); - dst = &tmp; - } else { - fp_zero(C); - dst = C; + + /* Always take branch to use tmp variable. This avoids a cache attack for + * determining if C equals A */ + if (1) { + fp_init(tmp); + dst = tmp; } TFM_INTEL_MUL_COMBA(A, B, dst) ; @@ -428,45 +507,62 @@ INLINE static void fp_mul_comba_mulx(fp_int *A, fp_int *B, fp_int *C) dst->used = pa; dst->sign = A->sign ^ B->sign; fp_clamp(dst); - fp_copy(dst, C); + fp_copy(dst, C); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT); +#endif + + return FP_OKAY; } #endif -void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C) +int fp_mul_comba(fp_int *A, fp_int *B, fp_int *C) { + int ret = 0; int ix, iy, iz, tx, ty, pa; fp_digit c0, c1, c2, *tmpx, *tmpy; - fp_int tmp, *dst; + fp_int *dst; +#ifndef WOLFSSL_SMALL_STACK + fp_int tmp[1]; +#else + fp_int *tmp; +#endif - IF_HAVE_INTEL_MULX(fp_mul_comba_mulx(A, B, C), return) ; + IF_HAVE_INTEL_MULX(ret = fp_mul_comba_mulx(A, B, C), return ret) ; + +#ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (tmp == NULL) + return FP_MEM; +#endif COMBA_START; COMBA_CLEAR; - + /* get size of output and trim */ pa = A->used + B->used; if (pa >= FP_SIZE) { pa = FP_SIZE-1; } - if (A == C || B == C) { - fp_init(&tmp); - dst = &tmp; - } else { - fp_zero(C); - dst = C; + /* Always take branch to use tmp variable. This avoids a cache attack for + * determining if C equals A */ + if (1) { + fp_init(tmp); + dst = tmp; } for (ix = 0; ix < pa; ix++) { /* get offsets into the two bignums */ - ty = MIN(ix, B->used-1); + ty = MIN(ix, (B->used > 0 ? B->used - 1 : 0)); tx = ix - ty; /* setup temp aliases */ tmpx = A->dp + tx; tmpy = B->dp + ty; - /* this is the number of times the loop will iterrate, essentially its + /* this is the number of times the loop will iterate, essentially its while (tx++ < a->used && ty-- >= 0) { ... } */ iy = MIN(A->used-tx, ty+1); @@ -474,8 +570,9 @@ void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C) /* execute loop */ COMBA_FORWARD; for (iz = 0; iz < iy; ++iz) { - /* TAO change COMBA_ADD back to MULADD */ - MULADD(*tmpx++, *tmpy--); + fp_digit _tmpx = *tmpx++; + fp_digit _tmpy = *tmpy--; + MULADD(_tmpx, _tmpy); } /* store term */ @@ -487,16 +584,28 @@ void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C) dst->sign = A->sign ^ B->sign; fp_clamp(dst); fp_copy(dst, C); + + /* Variables used but not seen by cppcheck. */ + (void)c0; (void)c1; (void)c2; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return ret; } /* a/b => cb + d == a */ int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d) { - fp_int q, x, y, t1, t2; int n, t, i, norm, neg; +#ifndef WOLFSSL_SMALL_STACK + fp_int q[1], x[1], y[1], t1[1], t2[1]; +#else + fp_int *q, *x, *y, *t1, *t2; +#endif /* is divisor zero ? */ - if (fp_iszero (b) == 1) { + if (fp_iszero (b) == FP_YES) { return FP_VAL; } @@ -504,131 +613,140 @@ int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d) if (fp_cmp_mag (a, b) == FP_LT) { if (d != NULL) { fp_copy (a, d); - } + } if (c != NULL) { fp_zero (c); } return FP_OKAY; } - fp_init(&q); - q.used = a->used + 2; +#ifdef WOLFSSL_SMALL_STACK + q = (fp_int*)XMALLOC(sizeof(fp_int) * 5, NULL, DYNAMIC_TYPE_BIGINT); + if (q == NULL) { + return FP_MEM; + } + x = &q[1]; y = &q[2]; t1 = &q[3]; t2 = &q[4]; +#endif - fp_init(&t1); - fp_init(&t2); - fp_init_copy(&x, a); - fp_init_copy(&y, b); + fp_init(q); + q->used = a->used + 2; + + fp_init(t1); + fp_init(t2); + fp_init_copy(x, a); + fp_init_copy(y, b); /* fix the sign */ neg = (a->sign == b->sign) ? FP_ZPOS : FP_NEG; - x.sign = y.sign = FP_ZPOS; + x->sign = y->sign = FP_ZPOS; /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ - norm = fp_count_bits(&y) % DIGIT_BIT; + norm = fp_count_bits(y) % DIGIT_BIT; if (norm < (int)(DIGIT_BIT-1)) { norm = (DIGIT_BIT-1) - norm; - fp_mul_2d (&x, norm, &x); - fp_mul_2d (&y, norm, &y); + fp_mul_2d (x, norm, x); + fp_mul_2d (y, norm, y); } else { norm = 0; } /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ - n = x.used - 1; - t = y.used - 1; + n = x->used - 1; + t = y->used - 1; /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ - fp_lshd (&y, n - t); /* y = y*b**{n-t} */ + fp_lshd (y, n - t); /* y = y*b**{n-t} */ - while (fp_cmp (&x, &y) != FP_LT) { - ++(q.dp[n - t]); - fp_sub (&x, &y, &x); + while (fp_cmp (x, y) != FP_LT) { + ++(q->dp[n - t]); + fp_sub (x, y, x); } /* reset y by shifting it back down */ - fp_rshd (&y, n - t); + fp_rshd (y, n - t); /* step 3. for i from n down to (t + 1) */ for (i = n; i >= (t + 1); i--) { - if (i > x.used) { + if (i > x->used) { continue; } - /* step 3.1 if xi == yt then set q{i-t-1} to b-1, + /* step 3.1 if xi == yt then set q{i-t-1} to b-1, * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ - if (x.dp[i] == y.dp[t]) { - q.dp[i - t - 1] = (fp_digit) ((((fp_word)1) << DIGIT_BIT) - 1); + if (x->dp[i] == y->dp[t]) { + q->dp[i - t - 1] = (fp_digit) ((((fp_word)1) << DIGIT_BIT) - 1); } else { fp_word tmp; - tmp = ((fp_word) x.dp[i]) << ((fp_word) DIGIT_BIT); - tmp |= ((fp_word) x.dp[i - 1]); - tmp /= ((fp_word)y.dp[t]); - q.dp[i - t - 1] = (fp_digit) (tmp); + tmp = ((fp_word) x->dp[i]) << ((fp_word) DIGIT_BIT); + tmp |= ((fp_word) x->dp[i - 1]); + tmp /= ((fp_word)y->dp[t]); + q->dp[i - t - 1] = (fp_digit) (tmp); } - /* while (q{i-t-1} * (yt * b + y{t-1})) > - xi * b**2 + xi-1 * b + xi-2 - - do q{i-t-1} -= 1; + /* while (q{i-t-1} * (yt * b + y{t-1})) > + xi * b**2 + xi-1 * b + xi-2 + + do q{i-t-1} -= 1; */ - q.dp[i - t - 1] = (q.dp[i - t - 1] + 1); + q->dp[i - t - 1] = (q->dp[i - t - 1] + 1); do { - q.dp[i - t - 1] = (q.dp[i - t - 1] - 1); + q->dp[i - t - 1] = (q->dp[i - t - 1] - 1); /* find left hand */ - fp_zero (&t1); - t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; - t1.dp[1] = y.dp[t]; - t1.used = 2; - fp_mul_d (&t1, q.dp[i - t - 1], &t1); + fp_zero (t1); + t1->dp[0] = (t - 1 < 0) ? 0 : y->dp[t - 1]; + t1->dp[1] = y->dp[t]; + t1->used = 2; + fp_mul_d (t1, q->dp[i - t - 1], t1); /* find right hand */ - t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; - t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; - t2.dp[2] = x.dp[i]; - t2.used = 3; - } while (fp_cmp_mag(&t1, &t2) == FP_GT); + t2->dp[0] = (i - 2 < 0) ? 0 : x->dp[i - 2]; + t2->dp[1] = (i - 1 < 0) ? 0 : x->dp[i - 1]; + t2->dp[2] = x->dp[i]; + t2->used = 3; + } while (fp_cmp_mag(t1, t2) == FP_GT); /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ - fp_mul_d (&y, q.dp[i - t - 1], &t1); - fp_lshd (&t1, i - t - 1); - fp_sub (&x, &t1, &x); + fp_mul_d (y, q->dp[i - t - 1], t1); + fp_lshd (t1, i - t - 1); + fp_sub (x, t1, x); /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ - if (x.sign == FP_NEG) { - fp_copy (&y, &t1); - fp_lshd (&t1, i - t - 1); - fp_add (&x, &t1, &x); - q.dp[i - t - 1] = q.dp[i - t - 1] - 1; + if (x->sign == FP_NEG) { + fp_copy (y, t1); + fp_lshd (t1, i - t - 1); + fp_add (x, t1, x); + q->dp[i - t - 1] = q->dp[i - t - 1] - 1; } } - /* now q is the quotient and x is the remainder - * [which we have to normalize] + /* now q is the quotient and x is the remainder + * [which we have to normalize] */ - + /* get sign before writing to c */ - x.sign = x.used == 0 ? FP_ZPOS : a->sign; + x->sign = x->used == 0 ? FP_ZPOS : a->sign; if (c != NULL) { - fp_clamp (&q); - fp_copy (&q, c); + fp_clamp (q); + fp_copy (q, c); c->sign = neg; } if (d != NULL) { - fp_div_2d (&x, norm, &x, NULL); + fp_div_2d (x, norm, x, NULL); -/* the following is a kludge, essentially we were seeing the right remainder but - with excess digits that should have been zero - */ - for (i = b->used; i < x.used; i++) { - x.dp[i] = 0; + /* zero any excess digits on the destination that we didn't write to */ + for (i = b->used; i < x->used; i++) { + x->dp[i] = 0; } - fp_clamp(&x); - fp_copy (&x, d); + fp_clamp(x); + fp_copy (x, d); } +#ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_BIGINT); +#endif return FP_OKAY; } @@ -640,7 +758,7 @@ void fp_div_2(fp_int * a, fp_int * b) oldused = b->used; b->used = a->used; { - register fp_digit r, rr, *tmpa, *tmpb; + fp_digit r, rr, *tmpa, *tmpb; /* source alias */ tmpa = a->dp + b->used - 1; @@ -661,7 +779,7 @@ void fp_div_2(fp_int * a, fp_int * b) r = rr; } - /* zero excess digits */ + /* zero any excess digits on the destination that we didn't write to */ tmpb = b->dp + b->used; for (x = b->used; x < oldused; x++) { *tmpb++ = 0; @@ -675,7 +793,6 @@ void fp_div_2(fp_int * a, fp_int * b) void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d) { int D; - fp_int t; /* if the shift count is <= 0 then we do no work */ if (b <= 0) { @@ -686,11 +803,9 @@ void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d) return; } - fp_init(&t); - - /* get the remainder */ - if (d != NULL) { - fp_mod_2d (a, b, &t); + /* get the remainder before a is changed in calculating c */ + if (a == c && d != NULL) { + fp_mod_2d (a, b, d); } /* copy */ @@ -706,28 +821,45 @@ void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d) if (D != 0) { fp_rshb(c, D); } - fp_clamp (c); - if (d != NULL) { - fp_copy (&t, d); + + /* get the remainder if a is not changed in calculating c */ + if (a != c && d != NULL) { + fp_mod_2d (a, b, d); } + + fp_clamp (c); } /* c = a mod b, 0 <= c < b */ int fp_mod(fp_int *a, fp_int *b, fp_int *c) { - fp_int t; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif int err; - fp_init(&t); - if ((err = fp_div(a, b, NULL, &t)) != FP_OKAY) { - return err; - } - if (t.sign != b->sign) { - fp_add(&t, b, c); - } else { - fp_copy(&t, c); +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) + return FP_MEM; +#endif + + fp_init(t); + err = fp_div(a, b, NULL, t); + if (err == FP_OKAY) { + if (t->sign != b->sign) { + fp_add(t, b, c); + } else { + fp_copy(t, c); + } } - return FP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return err; } /* c = a mod 2**d */ @@ -743,7 +875,7 @@ void fp_mod_2d(fp_int *a, int b, fp_int *c) /* get copy of input */ fp_copy(a, c); - + /* if 2**d is larger than we just return */ if (b >= (DIGIT_BIT * a->used)) { return; @@ -760,218 +892,690 @@ void fp_mod_2d(fp_int *a, int b, fp_int *c) static int fp_invmod_slow (fp_int * a, fp_int * b, fp_int * c) { - fp_int x, y, u, v, A, B, C, D; - int res; +#ifndef WOLFSSL_SMALL_STACK + fp_int x[1], y[1], u[1], v[1], A[1], B[1], C[1], D[1]; +#else + fp_int *x, *y, *u, *v, *A, *B, *C, *D; +#endif + int err; /* b cannot be negative */ - if (b->sign == FP_NEG || fp_iszero(b) == 1) { + if (b->sign == FP_NEG || fp_iszero(b) == FP_YES) { + return FP_VAL; + } + if (fp_iszero(a) == FP_YES) { return FP_VAL; } +#ifdef WOLFSSL_SMALL_STACK + x = (fp_int*)XMALLOC(sizeof(fp_int) * 8, NULL, DYNAMIC_TYPE_BIGINT); + if (x == NULL) { + return FP_MEM; + } + y = &x[1]; u = &x[2]; v = &x[3]; A = &x[4]; B = &x[5]; C = &x[6]; D = &x[7]; +#endif + /* init temps */ - fp_init(&x); fp_init(&y); - fp_init(&u); fp_init(&v); - fp_init(&A); fp_init(&B); - fp_init(&C); fp_init(&D); + fp_init(x); fp_init(y); + fp_init(u); fp_init(v); + fp_init(A); fp_init(B); + fp_init(C); fp_init(D); /* x = a, y = b */ - if ((res = fp_mod(a, b, &x)) != FP_OKAY) { - return res; + if ((err = fp_mod(a, b, x)) != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; } - fp_copy(b, &y); + fp_copy(b, y); /* 2. [modified] if x,y are both even then return an error! */ - if (fp_iseven (&x) == 1 && fp_iseven (&y) == 1) { + if (fp_iseven(x) == FP_YES && fp_iseven(y) == FP_YES) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif return FP_VAL; } /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ - fp_copy (&x, &u); - fp_copy (&y, &v); - fp_set (&A, 1); - fp_set (&D, 1); + fp_copy (x, u); + fp_copy (y, v); + fp_set (A, 1); + fp_set (D, 1); top: /* 4. while u is even do */ - while (fp_iseven (&u) == 1) { + while (fp_iseven (u) == FP_YES) { /* 4.1 u = u/2 */ - fp_div_2 (&u, &u); + fp_div_2 (u, u); /* 4.2 if A or B is odd then */ - if (fp_isodd (&A) == 1 || fp_isodd (&B) == 1) { + if (fp_isodd (A) == FP_YES || fp_isodd (B) == FP_YES) { /* A = (A+y)/2, B = (B-x)/2 */ - fp_add (&A, &y, &A); - fp_sub (&B, &x, &B); + fp_add (A, y, A); + fp_sub (B, x, B); } /* A = A/2, B = B/2 */ - fp_div_2 (&A, &A); - fp_div_2 (&B, &B); + fp_div_2 (A, A); + fp_div_2 (B, B); } /* 5. while v is even do */ - while (fp_iseven (&v) == 1) { + while (fp_iseven (v) == FP_YES) { /* 5.1 v = v/2 */ - fp_div_2 (&v, &v); + fp_div_2 (v, v); /* 5.2 if C or D is odd then */ - if (fp_isodd (&C) == 1 || fp_isodd (&D) == 1) { + if (fp_isodd (C) == FP_YES || fp_isodd (D) == FP_YES) { /* C = (C+y)/2, D = (D-x)/2 */ - fp_add (&C, &y, &C); - fp_sub (&D, &x, &D); + fp_add (C, y, C); + fp_sub (D, x, D); } /* C = C/2, D = D/2 */ - fp_div_2 (&C, &C); - fp_div_2 (&D, &D); + fp_div_2 (C, C); + fp_div_2 (D, D); } /* 6. if u >= v then */ - if (fp_cmp (&u, &v) != FP_LT) { + if (fp_cmp (u, v) != FP_LT) { /* u = u - v, A = A - C, B = B - D */ - fp_sub (&u, &v, &u); - fp_sub (&A, &C, &A); - fp_sub (&B, &D, &B); + fp_sub (u, v, u); + fp_sub (A, C, A); + fp_sub (B, D, B); } else { /* v - v - u, C = C - A, D = D - B */ - fp_sub (&v, &u, &v); - fp_sub (&C, &A, &C); - fp_sub (&D, &B, &D); + fp_sub (v, u, v); + fp_sub (C, A, C); + fp_sub (D, B, D); } /* if not zero goto step 4 */ - if (fp_iszero (&u) == 0) + if (fp_iszero (u) == FP_NO) goto top; /* now a = C, b = D, gcd == g*v */ /* if v != 1 then there is no inverse */ - if (fp_cmp_d (&v, 1) != FP_EQ) { + if (fp_cmp_d (v, 1) != FP_EQ) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif return FP_VAL; } /* if its too low */ - while (fp_cmp_d(&C, 0) == FP_LT) { - fp_add(&C, b, &C); + while (fp_cmp_d(C, 0) == FP_LT) { + fp_add(C, b, C); } - + /* too big */ - while (fp_cmp_mag(&C, b) != FP_LT) { - fp_sub(&C, b, &C); + while (fp_cmp_mag(C, b) != FP_LT) { + fp_sub(C, b, C); } - + /* C is now the inverse */ - fp_copy(&C, c); + fp_copy(C, c); +#ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); +#endif return FP_OKAY; } - /* c = 1/a (mod b) for odd b only */ int fp_invmod(fp_int *a, fp_int *b, fp_int *c) { - fp_int x, y, u, v, B, D; - int neg, loop_check = 0; +#ifndef WOLFSSL_SMALL_STACK + fp_int x[1], y[1], u[1], v[1], B[1], D[1]; +#else + fp_int *x, *y, *u, *v, *B, *D; +#endif + int neg; + int err; + + if (b->sign == FP_NEG || fp_iszero(b) == FP_YES) { + return FP_VAL; + } + + /* [modified] sanity check on "a" */ + if (fp_iszero(a) == FP_YES) { + return FP_VAL; /* can not divide by 0 here */ + } /* 2. [modified] b must be odd */ - if (fp_iseven (b) == FP_YES) { + if (fp_iseven(b) == FP_YES) { return fp_invmod_slow(a,b,c); } +#ifdef WOLFSSL_SMALL_STACK + x = (fp_int*)XMALLOC(sizeof(fp_int) * 6, NULL, DYNAMIC_TYPE_BIGINT); + if (x == NULL) { + return FP_MEM; + } + y = &x[1]; u = &x[2]; v = &x[3]; B = &x[4]; D = &x[5]; +#endif + /* init all our temps */ - fp_init(&x); fp_init(&y); - fp_init(&u); fp_init(&v); - fp_init(&B); fp_init(&D); + fp_init(x); fp_init(y); + fp_init(u); fp_init(v); + fp_init(B); fp_init(D); + + if (fp_cmp(a, b) != MP_LT) { + err = mp_mod(a, b, y); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } + a = y; + } + + if (fp_iszero(a) == FP_YES) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return FP_VAL; + } /* x == modulus, y == value to invert */ - fp_copy(b, &x); + fp_copy(b, x); /* we need y = |a| */ - fp_abs(a, &y); + fp_abs(a, y); /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ - fp_copy(&x, &u); - fp_copy(&y, &v); - fp_set (&D, 1); + fp_copy(x, u); + fp_copy(y, v); + fp_set (D, 1); top: /* 4. while u is even do */ - while (fp_iseven (&u) == FP_YES) { + while (fp_iseven (u) == FP_YES) { /* 4.1 u = u/2 */ - fp_div_2 (&u, &u); + fp_div_2 (u, u); /* 4.2 if B is odd then */ - if (fp_isodd (&B) == FP_YES) { - fp_sub (&B, &x, &B); + if (fp_isodd (B) == FP_YES) { + fp_sub (B, x, B); } /* B = B/2 */ - fp_div_2 (&B, &B); + fp_div_2 (B, B); } /* 5. while v is even do */ - while (fp_iseven (&v) == FP_YES) { + while (fp_iseven (v) == FP_YES) { /* 5.1 v = v/2 */ - fp_div_2 (&v, &v); + fp_div_2 (v, v); /* 5.2 if D is odd then */ - if (fp_isodd (&D) == FP_YES) { + if (fp_isodd (D) == FP_YES) { /* D = (D-x)/2 */ - fp_sub (&D, &x, &D); + fp_sub (D, x, D); } /* D = D/2 */ - fp_div_2 (&D, &D); + fp_div_2 (D, D); } /* 6. if u >= v then */ - if (fp_cmp (&u, &v) != FP_LT) { + if (fp_cmp (u, v) != FP_LT) { /* u = u - v, B = B - D */ - fp_sub (&u, &v, &u); - fp_sub (&B, &D, &B); + fp_sub (u, v, u); + fp_sub (B, D, B); } else { /* v - v - u, D = D - B */ - fp_sub (&v, &u, &v); - fp_sub (&D, &B, &D); + fp_sub (v, u, v); + fp_sub (D, B, D); } /* if not zero goto step 4 */ - if (fp_iszero (&u) == FP_NO) { - if (++loop_check > 1024) /* bad input */ - return FP_VAL; + if (fp_iszero (u) == FP_NO) { goto top; } /* now a = C, b = D, gcd == g*v */ /* if v != 1 then there is no inverse */ - if (fp_cmp_d (&v, 1) != FP_EQ) { + if (fp_cmp_d (v, 1) != FP_EQ) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif return FP_VAL; } /* b is now the inverse */ neg = a->sign; - while (D.sign == FP_NEG) { - fp_add (&D, b, &D); + while (D->sign == FP_NEG) { + fp_add (D, b, D); } - fp_copy (&D, c); + /* too big */ + while (fp_cmp_mag(D, b) != FP_LT) { + fp_sub(D, b, D); + } + fp_copy (D, c); c->sign = neg; +#ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return FP_OKAY; +} + +#define CT_INV_MOD_PRE_CNT 8 + +/* modulus (b) must be greater than 2 and a prime */ +int fp_invmod_mont_ct(fp_int *a, fp_int *b, fp_int *c, fp_digit mp) +{ + int i, j; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1], e[1]; + fp_int pre[CT_INV_MOD_PRE_CNT]; +#else + fp_int* t; + fp_int* e; + fp_int* pre; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int) * (2 + CT_INV_MOD_PRE_CNT), NULL, + DYNAMIC_TYPE_BIGINT); + if (t == NULL) + return FP_MEM; + e = t + 1; + pre = t + 2; +#endif + + fp_init(t); + fp_init(e); + + fp_init(&pre[0]); + fp_copy(a, &pre[0]); + for (i = 1; i < CT_INV_MOD_PRE_CNT; i++) { + fp_init(&pre[i]); + fp_sqr(&pre[i-1], &pre[i]); + fp_montgomery_reduce(&pre[i], b, mp); + fp_mul(&pre[i], a, &pre[i]); + fp_montgomery_reduce(&pre[i], b, mp); + } + + fp_sub_d(b, 2, e); + /* Highest bit is always set. */ + for (i = fp_count_bits(e)-2, j = 1; i >= 0; i--, j++) { + if (!fp_is_bit_set(e, i) || j == CT_INV_MOD_PRE_CNT) + break; + } + fp_copy(&pre[j-1], t); + for (j = 0; i >= 0; i--) { + int set = fp_is_bit_set(e, i); + + if ((j == CT_INV_MOD_PRE_CNT) || (!set && j > 0)) { + fp_mul(t, &pre[j-1], t); + fp_montgomery_reduce(t, b, mp); + j = 0; + } + fp_sqr(t, t); + fp_montgomery_reduce(t, b, mp); + j += set; + } + if (j > 0) { + fp_mul(t, &pre[j-1], c); + fp_montgomery_reduce(c, b, mp); + } + else + fp_copy(t, c); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif return FP_OKAY; } /* d = a * b (mod c) */ int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) { - fp_int tmp; - fp_init(&tmp); - fp_mul(a, b, &tmp); - return fp_mod(&tmp, c, d); + int err; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) + return FP_MEM; +#endif + + fp_init(t); + err = fp_mul(a, b, t); + if (err == FP_OKAY) { + #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 + #endif + { + err = fp_mod(t, c, d); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return err; +} + +/* d = a - b (mod c) */ +int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) +{ + int err; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) + return FP_MEM; +#endif + + 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 +#endif + { + err = fp_mod(t, c, d); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return err; +} + +/* d = a + b (mod c) */ +int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) +{ + int err; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) + return FP_MEM; +#endif + + 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 +#endif + { + err = fp_mod(t, c, d); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return err; } #ifdef TFM_TIMING_RESISTANT -/* timing resistant montgomery ladder based exptmod +#ifdef WC_RSA_NONBLOCK - Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder", Cryptographic Hardware and Embedded Systems, CHES 2002 -*/ -static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) +#ifdef WC_RSA_NONBLOCK_TIME + /* User can override the check-time at build-time using the + * FP_EXPTMOD_NB_CHECKTIME macro to define your own function */ + #ifndef FP_EXPTMOD_NB_CHECKTIME + /* instruction count for each type of operation */ + /* array lookup is using TFM_EXPTMOD_NB_* states */ + static const word32 exptModNbInst[TFM_EXPTMOD_NB_COUNT] = { + #ifdef TFM_PPC32 + #ifdef _DEBUG + 11098, 8701, 3971, 178394, 858093, 1040, 822, 178056, 181574, 90883, 184339, 236813 + #else + 7050, 2554, 3187, 43178, 200422, 384, 275, 43024, 43550, 30450, 46270, 61376 + #endif + #elif defined(TFM_X86_64) + #ifdef _DEBUG + 954, 2377, 858, 19027, 90840, 287, 407, 20140, 7874, 11385, 8005, 6151 + #else + 765, 1007, 771, 5216, 34993, 248, 193, 4975, 4201, 3947, 4275, 3811 + #endif + #else /* software only fast math */ + #ifdef _DEBUG + 798, 2245, 802, 16657, 66920, 352, 186, 16997, 16145, 12789, 16742, 15006 + #else + 775, 1084, 783, 4692, 37510, 207, 183, 4374, 4392, 3097, 4442, 4079 + #endif + #endif + }; + + static int fp_exptmod_nb_checktime(exptModNb_t* nb) + { + word32 totalInst; + + /* if no max time has been set then stop (do not block) */ + if (nb->maxBlockInst == 0 || nb->state >= TFM_EXPTMOD_NB_COUNT) { + return TFM_EXPTMOD_NB_STOP; + } + + /* if instruction table not set then use maxBlockInst as simple counter */ + if (exptModNbInst[nb->state] == 0) { + if (++nb->totalInst < nb->maxBlockInst) + return TFM_EXPTMOD_NB_CONTINUE; + + nb->totalInst = 0; /* reset counter */ + return TFM_EXPTMOD_NB_STOP; + } + + /* get total instruction count including next operation */ + totalInst = nb->totalInst + exptModNbInst[nb->state]; + /* if the next operation can completed within the maximum then continue */ + if (totalInst <= nb->maxBlockInst) { + return TFM_EXPTMOD_NB_CONTINUE; + } + + return TFM_EXPTMOD_NB_STOP; + } + #define FP_EXPTMOD_NB_CHECKTIME(nb) fp_exptmod_nb_checktime((nb)) + #endif /* !FP_EXPTMOD_NB_CHECKTIME */ +#endif /* WC_RSA_NONBLOCK_TIME */ + +/* non-blocking version of timing resistant fp_exptmod function */ +/* supports cache resistance */ +int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y) { + int err, ret = FP_WOULDBLOCK; + + if (nb == NULL) + return FP_VAL; + +#ifdef WC_RSA_NONBLOCK_TIME + nb->totalInst = 0; + do { + nb->totalInst += exptModNbInst[nb->state]; +#endif + + switch (nb->state) { + case TFM_EXPTMOD_NB_INIT: + /* now setup montgomery */ + if ((err = fp_montgomery_setup(P, &nb->mp)) != FP_OKAY) { + nb->state = TFM_EXPTMOD_NB_INIT; + return err; + } + + /* init ints */ + fp_init(&nb->R[0]); + fp_init(&nb->R[1]); + #ifndef WC_NO_CACHE_RESISTANT + fp_init(&nb->R[2]); + #endif + nb->state = TFM_EXPTMOD_NB_MONT; + break; + + case TFM_EXPTMOD_NB_MONT: + /* mod m -> R[0] */ + fp_montgomery_calc_normalization(&nb->R[0], P); + + nb->state = TFM_EXPTMOD_NB_MONT_RED; + break; + + case TFM_EXPTMOD_NB_MONT_RED: + /* reduce G -> R[1] */ + if (fp_cmp_mag(P, G) != FP_GT) { + /* G > P so we reduce it first */ + fp_mod(G, P, &nb->R[1]); + } else { + fp_copy(G, &nb->R[1]); + } + + nb->state = TFM_EXPTMOD_NB_MONT_MUL; + break; + + case TFM_EXPTMOD_NB_MONT_MUL: + /* G (R[1]) * m (R[0]) */ + err = fp_mul(&nb->R[1], &nb->R[0], &nb->R[1]); + if (err != FP_OKAY) { + nb->state = TFM_EXPTMOD_NB_INIT; + return err; + } + + nb->state = TFM_EXPTMOD_NB_MONT_MOD; + break; + + case TFM_EXPTMOD_NB_MONT_MOD: + /* mod m */ + err = fp_div(&nb->R[1], P, NULL, &nb->R[1]); + if (err != FP_OKAY) { + nb->state = TFM_EXPTMOD_NB_INIT; + return err; + } + + nb->state = TFM_EXPTMOD_NB_MONT_MODCHK; + break; + + case TFM_EXPTMOD_NB_MONT_MODCHK: + /* m matches sign of (G * R mod m) */ + if (nb->R[1].sign != P->sign) { + fp_add(&nb->R[1], P, &nb->R[1]); + } + + /* set initial mode and bit cnt */ + nb->bitcnt = 1; + nb->buf = 0; + nb->digidx = X->used - 1; + + nb->state = TFM_EXPTMOD_NB_NEXT; + break; + + case TFM_EXPTMOD_NB_NEXT: + /* grab next digit as required */ + if (--nb->bitcnt == 0) { + /* if nb->digidx == -1 we are out of digits so break */ + if (nb->digidx == -1) { + nb->state = TFM_EXPTMOD_NB_RED; + break; + } + /* read next digit and reset nb->bitcnt */ + nb->buf = X->dp[nb->digidx--]; + nb->bitcnt = (int)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + nb->y = (int)(nb->buf >> (DIGIT_BIT - 1)) & 1; + nb->buf <<= (fp_digit)1; + nb->state = TFM_EXPTMOD_NB_MUL; + FALL_THROUGH; + + case TFM_EXPTMOD_NB_MUL: + fp_mul(&nb->R[0], &nb->R[1], &nb->R[nb->y^1]); + nb->state = TFM_EXPTMOD_NB_MUL_RED; + break; + + case TFM_EXPTMOD_NB_MUL_RED: + fp_montgomery_reduce(&nb->R[nb->y^1], P, nb->mp); + nb->state = TFM_EXPTMOD_NB_SQR; + break; + + case TFM_EXPTMOD_NB_SQR: + #ifdef WC_NO_CACHE_RESISTANT + fp_sqr(&nb->R[nb->y], &nb->R[nb->y]); + #else + fp_copy((fp_int*) ( ((wolfssl_word)&nb->R[0] & wc_off_on_addr[nb->y^1]) + + ((wolfssl_word)&nb->R[1] & wc_off_on_addr[nb->y]) ), + &nb->R[2]); + fp_sqr(&nb->R[2], &nb->R[2]); + #endif /* WC_NO_CACHE_RESISTANT */ + + nb->state = TFM_EXPTMOD_NB_SQR_RED; + break; + + case TFM_EXPTMOD_NB_SQR_RED: + #ifdef WC_NO_CACHE_RESISTANT + fp_montgomery_reduce(&nb->R[nb->y], P, nb->mp); + #else + fp_montgomery_reduce(&nb->R[2], P, nb->mp); + fp_copy(&nb->R[2], + (fp_int*) ( ((wolfssl_word)&nb->R[0] & wc_off_on_addr[nb->y^1]) + + ((wolfssl_word)&nb->R[1] & wc_off_on_addr[nb->y]) ) ); + #endif /* WC_NO_CACHE_RESISTANT */ + + nb->state = TFM_EXPTMOD_NB_NEXT; + break; + + case TFM_EXPTMOD_NB_RED: + /* final reduce */ + fp_montgomery_reduce(&nb->R[0], P, nb->mp); + fp_copy(&nb->R[0], Y); + + nb->state = TFM_EXPTMOD_NB_INIT; + ret = FP_OKAY; + break; + } /* switch */ + +#ifdef WC_RSA_NONBLOCK_TIME + /* determine if maximum blocking time has been reached */ + } while (ret == FP_WOULDBLOCK && + FP_EXPTMOD_NB_CHECKTIME(nb) == TFM_EXPTMOD_NB_CONTINUE); +#endif + + return ret; +} + +#endif /* WC_RSA_NONBLOCK */ + + +/* 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 +*/ +static int _fp_exptmod_ct(fp_int * G, fp_int * X, int digits, fp_int * P, + fp_int * Y) +{ +#ifndef WOLFSSL_SMALL_STACK +#ifdef WC_NO_CACHE_RESISTANT fp_int R[2]; +#else + fp_int R[3]; /* need a temp for cache resistance */ +#endif +#else + fp_int *R; +#endif fp_digit buf, mp; int err, bitcnt, digidx, y; @@ -980,9 +1584,21 @@ static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) return err; } - fp_init(&R[0]); - fp_init(&R[1]); - +#ifdef WOLFSSL_SMALL_STACK +#ifndef WC_NO_CACHE_RESISTANT + R = (fp_int*)XMALLOC(sizeof(fp_int) * 3, NULL, DYNAMIC_TYPE_BIGINT); +#else + R = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_BIGINT); +#endif + if (R == NULL) + return FP_MEM; +#endif + fp_init(&R[0]); + fp_init(&R[1]); +#ifndef WC_NO_CACHE_RESISTANT + fp_init(&R[2]); +#endif + /* now we need R mod m */ fp_montgomery_calc_normalization (&R[0], P); @@ -998,11 +1614,11 @@ static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) /* for j = t-1 downto 0 do r_!k = R0*R1; r_k = r_k^2 */ - + /* set initial mode and bit cnt */ bitcnt = 1; buf = 0; - digidx = X->used - 1; + digidx = digits - 1; for (;;) { /* grab next digit as required */ @@ -1021,23 +1637,80 @@ static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) buf <<= (fp_digit)1; /* do ops */ - fp_mul(&R[0], &R[1], &R[y^1]); fp_montgomery_reduce(&R[y^1], P, mp); - fp_sqr(&R[y], &R[y]); fp_montgomery_reduce(&R[y], P, mp); + err = fp_mul(&R[0], &R[1], &R[y^1]); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } + err = fp_montgomery_reduce(&R[y^1], P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } + +#ifdef WC_NO_CACHE_RESISTANT + err = fp_sqr(&R[y], &R[y]); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } + err = fp_montgomery_reduce(&R[y], P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } +#else + /* instead of using R[y] for sqr, which leaks key bit to cache monitor, + * use R[2] as temp, make sure address calc is constant, keep + * &R[0] and &R[1] in cache */ + fp_copy((fp_int*) ( ((wolfssl_word)&R[0] & wc_off_on_addr[y^1]) + + ((wolfssl_word)&R[1] & wc_off_on_addr[y]) ), + &R[2]); + err = fp_sqr(&R[2], &R[2]); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } + err = fp_montgomery_reduce(&R[2], P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } + fp_copy(&R[2], + (fp_int*) ( ((wolfssl_word)&R[0] & wc_off_on_addr[y^1]) + + ((wolfssl_word)&R[1] & wc_off_on_addr[y]) ) ); +#endif /* WC_NO_CACHE_RESISTANT */ } - fp_montgomery_reduce(&R[0], P, mp); + err = fp_montgomery_reduce(&R[0], P, mp); fp_copy(&R[0], Y); - return FP_OKAY; -} +#ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return err; +} -#else +#endif /* TFM_TIMING_RESISTANT */ -/* y = g**x (mod b) +/* y = g**x (mod b) * Some restrictions... x must be positive and < b */ -static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) +static int _fp_exptmod_nct(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) { - fp_int M[64], res; + fp_int *res; + fp_int *M; fp_digit buf, mp; int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; @@ -1053,28 +1726,37 @@ static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) winsize = 5; } else { winsize = 6; - } - - /* init M array */ - XMEMSET(M, 0, sizeof(M)); + } /* now setup montgomery */ if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) { return err; } + /* only allocate space for what's needed for window plus res */ + M = (fp_int*)XMALLOC(sizeof(fp_int)*((1 << winsize) + 1), NULL, + DYNAMIC_TYPE_BIGINT); + if (M == NULL) { + return FP_MEM; + } + res = &M[1 << winsize]; + + /* init M array */ + for(x = 0; x < (1 << winsize); x++) + fp_init(&M[x]); + /* setup result */ - fp_init(&res); + fp_init(res); /* create M table * * The M table contains powers of the input base, e.g. M[x] = G^x mod P * - * The first half of the table is not computed though accept for M[0] and M[1] + * The first half of the table is not computed though except for M[0] and M[1] */ /* now we need R mod m */ - fp_montgomery_calc_normalization (&res, P); + fp_montgomery_calc_normalization (res, P); /* now set M[1] to G * R mod m */ if (fp_cmp_mag(P, G) != FP_GT) { @@ -1083,24 +1765,37 @@ static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) } else { fp_copy(G, &M[1]); } - fp_mulmod (&M[1], &res, P, &M[1]); + fp_mulmod (&M[1], res, P, &M[1]); - /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ + /* compute the value at M[1<<(winsize-1)] by + * squaring M[1] (winsize-1) times */ fp_copy (&M[1], &M[1 << (winsize - 1)]); for (x = 0; x < (winsize - 1); x++) { fp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)]); - fp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp); + err = fp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } } /* create upper table */ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { - fp_mul(&M[x - 1], &M[1], &M[x]); - fp_montgomery_reduce(&M[x], P, mp); + err = fp_mul(&M[x - 1], &M[1], &M[x]); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } + err = fp_montgomery_reduce(&M[x], P, mp); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } } /* set initial mode and bit cnt */ mode = 0; - bitcnt = 1; + bitcnt = (x % DIGIT_BIT) + 1; buf = 0; digidx = X->used - 1; bitcpy = 0; @@ -1133,8 +1828,16 @@ static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) /* if the bit is zero and mode == 1 then we square */ if (mode == 1 && y == 0) { - fp_sqr(&res, &res); - fp_montgomery_reduce(&res, P, mp); + err = fp_sqr(res, res); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } + fp_montgomery_reduce(res, P, mp); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } continue; } @@ -1146,13 +1849,29 @@ static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) /* ok window is filled so square as required and multiply */ /* square first */ for (x = 0; x < winsize; x++) { - fp_sqr(&res, &res); - fp_montgomery_reduce(&res, P, mp); + err = fp_sqr(res, res); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } + err = fp_montgomery_reduce(res, P, mp); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } } /* then multiply */ - fp_mul(&res, &M[bitbuf], &res); - fp_montgomery_reduce(&res, P, mp); + err = fp_mul(res, &M[bitbuf], res); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } + err = fp_montgomery_reduce(res, P, mp); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } /* empty window and reset */ bitcpy = 0; @@ -1165,15 +1884,31 @@ static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) if (mode == 2 && bitcpy > 0) { /* square then multiply if the bit is set */ for (x = 0; x < bitcpy; x++) { - fp_sqr(&res, &res); - fp_montgomery_reduce(&res, P, mp); + err = fp_sqr(res, res); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } + err = fp_montgomery_reduce(res, P, mp); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } /* get next bit of the window */ bitbuf <<= 1; if ((bitbuf & (1 << winsize)) != 0) { /* then multiply */ - fp_mul(&res, &M[1], &res); - fp_montgomery_reduce(&res, P, mp); + err = fp_mul(res, &M[1], res); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } + err = fp_montgomery_reduce(res, P, mp); + if (err != FP_OKAY) { + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; + } } } } @@ -1184,45 +1919,553 @@ static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) * to reduce one more time to cancel out the factor * of R. */ - fp_montgomery_reduce(&res, P, mp); + err = fp_montgomery_reduce(res, P, mp); /* swap res with Y */ - fp_copy (&res, Y); - return FP_OKAY; + fp_copy (res, Y); + + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); + return err; } + +#ifdef TFM_TIMING_RESISTANT +#if DIGIT_BIT <= 16 + #define WINSIZE 2 +#elif DIGIT_BIT <= 32 + #define WINSIZE 3 +#elif DIGIT_BIT <= 64 + #define WINSIZE 4 +#elif DIGIT_BIT <= 128 + #define WINSIZE 5 #endif +/* y = 2**x (mod b) + * Some restrictions... x must be positive and < b + */ +static int _fp_exptmod_base_2(fp_int * X, int digits, fp_int * P, + fp_int * Y) +{ + fp_digit buf, mp; + int err, bitbuf, bitcpy, bitcnt, digidx, x, y; +#ifdef WOLFSSL_SMALL_STACK + fp_int *res; + fp_int *tmp; +#else + fp_int res[1]; + fp_int tmp[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + res = (fp_int*)XMALLOC(2*sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (res == NULL) { + return FP_MEM; + } + tmp = &res[1]; +#endif + + /* now setup montgomery */ + if ((err = fp_montgomery_setup(P, &mp)) != FP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; + } + + /* setup result */ + fp_init(res); + fp_init(tmp); + + fp_mul_2d(P, 1 << WINSIZE, tmp); + + /* now we need R mod m */ + fp_montgomery_calc_normalization(res, P); + + /* Get the top bits left over after taking WINSIZE bits starting at the + * least-significant. + */ + digidx = digits - 1; + bitcpy = (digits * DIGIT_BIT) % WINSIZE; + if (bitcpy > 0) { + bitcnt = (int)DIGIT_BIT - bitcpy; + buf = X->dp[digidx--]; + bitbuf = (int)(buf >> bitcnt); + /* Multiply montgomery representation of 1 by 2 ^ top */ + fp_mul_2d(res, bitbuf, res); + fp_add(res, tmp, res); + err = fp_mod(res, P, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + /* Move out bits used */ + buf <<= bitcpy; + bitcnt++; + } + else { + bitcnt = 1; + buf = 0; + } + + /* empty window and reset */ + bitbuf = 0; + bitcpy = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (int)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= (fp_digit)1; + /* add bit to the window */ + bitbuf |= (y << (WINSIZE - ++bitcpy)); + + if (bitcpy == WINSIZE) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < WINSIZE; x++) { + err = fp_sqr(res, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + err = fp_montgomery_reduce(res, P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + } + + /* then multiply by 2^bitbuf */ + fp_mul_2d(res, bitbuf, res); + /* Add in value to make mod operation take same time */ + fp_add(res, tmp, res); + err = fp_mod(res, P, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + } + } + + /* fixup result if Montgomery reduction is used + * recall that any value in a Montgomery system is + * actually multiplied by R mod n. So we have + * to reduce one more time to cancel out the factor + * of R. + */ + err = fp_montgomery_reduce(res, P, mp); + + /* swap res with Y */ + fp_copy(res, Y); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; +} + +#undef WINSIZE +#else +#if DIGIT_BIT < 16 + #define WINSIZE 3 +#elif DIGIT_BIT < 32 + #define WINSIZE 4 +#elif DIGIT_BIT < 64 + #define WINSIZE 5 +#elif DIGIT_BIT < 128 + #define WINSIZE 6 +#elif DIGIT_BIT == 128 + #define WINSIZE 7 +#endif + +/* y = 2**x (mod b) + * Some restrictions... x must be positive and < b + */ +static int _fp_exptmod_base_2(fp_int * X, int digits, fp_int * P, + fp_int * Y) +{ + fp_digit buf, mp; + int err, bitbuf, bitcpy, bitcnt, digidx, x, y; +#ifdef WOLFSSL_SMALL_STACK + fp_int *res; +#else + fp_int res[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + res = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (res == NULL) { + return FP_MEM; + } +#endif + + /* now setup montgomery */ + if ((err = fp_montgomery_setup(P, &mp)) != FP_OKAY) { + return err; + } + + /* setup result */ + fp_init(res); + + /* now we need R mod m */ + fp_montgomery_calc_normalization(res, P); + + /* Get the top bits left over after taking WINSIZE bits starting at the + * least-significant. + */ + digidx = digits - 1; + bitcpy = (digits * DIGIT_BIT) % WINSIZE; + if (bitcpy > 0) { + bitcnt = (int)DIGIT_BIT - bitcpy; + buf = X->dp[digidx--]; + bitbuf = (int)(buf >> bitcnt); + /* Multiply montgomery representation of 1 by 2 ^ top */ + fp_mul_2d(res, bitbuf, res); + err = fp_mod(res, P, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + /* Move out bits used */ + buf <<= bitcpy; + bitcnt++; + } + else { + bitcnt = 1; + buf = 0; + } + + /* empty window and reset */ + bitbuf = 0; + bitcpy = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (int)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= (fp_digit)1; + /* add bit to the window */ + bitbuf |= (y << (WINSIZE - ++bitcpy)); + + if (bitcpy == WINSIZE) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < WINSIZE; x++) { + err = fp_sqr(res, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + err = fp_montgomery_reduce(res, P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + } + + /* then multiply by 2^bitbuf */ + fp_mul_2d(res, bitbuf, res); + err = fp_mod(res, P, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + } + } + + /* fixup result if Montgomery reduction is used + * recall that any value in a Montgomery system is + * actually multiplied by R mod n. So we have + * to reduce one more time to cancel out the factor + * of R. + */ + err = fp_montgomery_reduce(res, P, mp); + + /* swap res with Y */ + fp_copy(res, Y); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; +} + +#undef WINSIZE +#endif + + int fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) { + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + int x = fp_count_bits (X); +#endif + + /* handle modulus of zero and prevent overflows */ + if (fp_iszero(P) || (P->used > (FP_SIZE/2))) { + return FP_VAL; + } + if (fp_isone(P)) { + fp_set(Y, 0); + return FP_OKAY; + } + if (fp_iszero(X)) { + fp_set(Y, 1); + return FP_OKAY; + } + if (fp_iszero(G)) { + fp_set(Y, 0); + return FP_OKAY; + } + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + if(x > EPS_RSA_EXPT_XBTIS) { + return esp_mp_exptmod(G, X, x, P, Y); + } +#endif + + if (X->sign == FP_NEG) { +#ifndef POSITIVE_EXP_ONLY /* reduce stack if assume no negatives */ + int err; + #ifndef WOLFSSL_SMALL_STACK + fp_int tmp[2]; + #else + fp_int *tmp; + #endif + + #ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_BIGINT); + if (tmp == NULL) + return FP_MEM; + #endif + + /* yes, copy G and invmod it */ + fp_init_copy(&tmp[0], G); + fp_init_copy(&tmp[1], P); + tmp[1].sign = FP_ZPOS; + err = fp_invmod(&tmp[0], &tmp[1], &tmp[0]); + if (err == FP_OKAY) { + fp_copy(X, &tmp[1]); + tmp[1].sign = FP_ZPOS; +#ifdef TFM_TIMING_RESISTANT + err = _fp_exptmod_ct(&tmp[0], &tmp[1], tmp[1].used, P, Y); +#else + err = _fp_exptmod_nct(&tmp[0], &tmp[1], P, Y); +#endif + if (P->sign == FP_NEG) { + fp_add(Y, P, Y); + } + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; +#else + return FP_VAL; +#endif + } + else if (G->used == 1 && G->dp[0] == 2) { + return _fp_exptmod_base_2(X, X->used, P, Y); + } + else { + /* Positive exponent so just exptmod */ +#ifdef TFM_TIMING_RESISTANT + return _fp_exptmod_ct(G, X, X->used, P, Y); +#else + return _fp_exptmod_nct(G, X, P, Y); +#endif + } +} + +int fp_exptmod_ex(fp_int * G, fp_int * X, int digits, fp_int * P, fp_int * Y) +{ + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + int x = fp_count_bits (X); +#endif + + if (fp_iszero(G)) { + fp_set(G, 0); + return FP_OKAY; + } + /* prevent overflows */ if (P->used > (FP_SIZE/2)) { return FP_VAL; } +#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + if(x > EPS_RSA_EXPT_XBTIS) { + return esp_mp_exptmod(G, X, x, P, Y); + } +#endif + if (X->sign == FP_NEG) { #ifndef POSITIVE_EXP_ONLY /* reduce stack if assume no negatives */ int err; - fp_int tmp; + #ifndef WOLFSSL_SMALL_STACK + fp_int tmp[2]; + #else + fp_int *tmp; + #endif + + #ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return FP_MEM; + #endif /* yes, copy G and invmod it */ - fp_copy(G, &tmp); - if ((err = fp_invmod(&tmp, P, &tmp)) != FP_OKAY) { - return err; - } - X->sign = FP_ZPOS; - err = _fp_exptmod(&tmp, X, P, Y); - if (X != Y) { - X->sign = FP_NEG; + fp_init_copy(&tmp[0], G); + fp_init_copy(&tmp[1], P); + tmp[1].sign = FP_ZPOS; + err = fp_invmod(&tmp[0], &tmp[1], &tmp[0]); + if (err == FP_OKAY) { + X->sign = FP_ZPOS; +#ifdef TFM_TIMING_RESISTANT + err = _fp_exptmod_ct(&tmp[0], X, digits, P, Y); +#else + err = _fp_exptmod_nct(&tmp[0], X, P, Y); + (void)digits; +#endif + if (X != Y) { + X->sign = FP_NEG; + } + if (P->sign == FP_NEG) { + fp_add(Y, P, Y); + } } + #ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT); + #endif return err; #else return FP_VAL; -#endif +#endif } else { /* Positive exponent so just exptmod */ - return _fp_exptmod(G, X, P, Y); +#ifdef TFM_TIMING_RESISTANT + return _fp_exptmod_ct(G, X, digits, P, Y); +#else + return _fp_exptmod_nct(G, X, P, Y); +#endif + } +} + +int fp_exptmod_nct(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) +{ +#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + int x = fp_count_bits (X); +#endif + + if (fp_iszero(G)) { + fp_set(G, 0); + return FP_OKAY; + } + + /* prevent overflows */ + if (P->used > (FP_SIZE/2)) { + return FP_VAL; + } + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + if(x > EPS_RSA_EXPT_XBTIS) { + return esp_mp_exptmod(G, X, x, P, Y); + } +#endif + + if (X->sign == FP_NEG) { +#ifndef POSITIVE_EXP_ONLY /* reduce stack if assume no negatives */ + int err; + #ifndef WOLFSSL_SMALL_STACK + fp_int tmp[2]; + #else + fp_int *tmp; + #endif + + #ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return FP_MEM; + #endif + + /* yes, copy G and invmod it */ + fp_init_copy(&tmp[0], G); + fp_init_copy(&tmp[1], P); + tmp[1].sign = FP_ZPOS; + err = fp_invmod(&tmp[0], &tmp[1], &tmp[0]); + if (err == FP_OKAY) { + X->sign = FP_ZPOS; + err = _fp_exptmod_nct(&tmp[0], X, P, Y); + if (X != Y) { + X->sign = FP_NEG; + } + if (P->sign == FP_NEG) { + fp_add(Y, P, Y); + } + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; +#else + return FP_VAL; +#endif + } + else { + /* Positive exponent so just exptmod */ + return _fp_exptmod_nct(G, X, P, Y); } } @@ -1234,13 +2477,13 @@ void fp_2expt(fp_int *a, int b) /* zero a as per default */ fp_zero (a); - if (b < 0) { + if (b < 0) { return; } z = b / DIGIT_BIT; if (z >= FP_SIZE) { - return; + return; } /* set the used count of where the bit will go */ @@ -1251,118 +2494,141 @@ void fp_2expt(fp_int *a, int b) } /* b = a*a */ -void fp_sqr(fp_int *A, fp_int *B) +int fp_sqr(fp_int *A, fp_int *B) { - int y = A->used; + int err; + int y, oldused; + + oldused = B->used; + y = A->used; /* call generic if we're out of range */ if (y + y > FP_SIZE) { - fp_sqr_comba(A, B); - return ; + err = fp_sqr_comba(A, B); + goto clean; } -#if defined(TFM_SQR3) +#if defined(TFM_SQR3) && FP_SIZE >= 6 if (y <= 3) { - fp_sqr_comba3(A,B); - return; + err = fp_sqr_comba3(A,B); + goto clean; } #endif -#if defined(TFM_SQR4) +#if defined(TFM_SQR4) && FP_SIZE >= 8 if (y == 4) { - fp_sqr_comba4(A,B); - return; + err = fp_sqr_comba4(A,B); + goto clean; } #endif -#if defined(TFM_SQR6) +#if defined(TFM_SQR6) && FP_SIZE >= 12 if (y <= 6) { - fp_sqr_comba6(A,B); - return; + err = fp_sqr_comba6(A,B); + goto clean; } #endif -#if defined(TFM_SQR7) +#if defined(TFM_SQR7) && FP_SIZE >= 14 if (y == 7) { - fp_sqr_comba7(A,B); - return; + err = fp_sqr_comba7(A,B); + goto clean; } #endif -#if defined(TFM_SQR8) +#if defined(TFM_SQR8) && FP_SIZE >= 16 if (y == 8) { - fp_sqr_comba8(A,B); - return; + err = fp_sqr_comba8(A,B); + goto clean; } #endif -#if defined(TFM_SQR9) +#if defined(TFM_SQR9) && FP_SIZE >= 18 if (y == 9) { - fp_sqr_comba9(A,B); - return; + err = fp_sqr_comba9(A,B); + goto clean; } #endif -#if defined(TFM_SQR12) +#if defined(TFM_SQR12) && FP_SIZE >= 24 if (y <= 12) { - fp_sqr_comba12(A,B); - return; + err = fp_sqr_comba12(A,B); + goto clean; } #endif -#if defined(TFM_SQR17) +#if defined(TFM_SQR17) && FP_SIZE >= 34 if (y <= 17) { - fp_sqr_comba17(A,B); - return; + err = fp_sqr_comba17(A,B); + goto clean; } #endif #if defined(TFM_SMALL_SET) if (y <= 16) { - fp_sqr_comba_small(A,B); - return; + err = fp_sqr_comba_small(A,B); + goto clean; } #endif -#if defined(TFM_SQR20) +#if defined(TFM_SQR20) && FP_SIZE >= 40 if (y <= 20) { - fp_sqr_comba20(A,B); - return; + err = fp_sqr_comba20(A,B); + goto clean; } #endif -#if defined(TFM_SQR24) +#if defined(TFM_SQR24) && FP_SIZE >= 48 if (y <= 24) { - fp_sqr_comba24(A,B); - return; + err = fp_sqr_comba24(A,B); + goto clean; } #endif -#if defined(TFM_SQR28) +#if defined(TFM_SQR28) && FP_SIZE >= 56 if (y <= 28) { - fp_sqr_comba28(A,B); - return; + err = fp_sqr_comba28(A,B); + goto clean; } #endif -#if defined(TFM_SQR32) +#if defined(TFM_SQR32) && FP_SIZE >= 64 if (y <= 32) { - fp_sqr_comba32(A,B); - return; + err = fp_sqr_comba32(A,B); + goto clean; } #endif -#if defined(TFM_SQR48) +#if defined(TFM_SQR48) && FP_SIZE >= 96 if (y <= 48) { - fp_sqr_comba48(A,B); - return; + err = fp_sqr_comba48(A,B); + goto clean; } #endif -#if defined(TFM_SQR64) +#if defined(TFM_SQR64) && FP_SIZE >= 128 if (y <= 64) { - fp_sqr_comba64(A,B); - return; + err = fp_sqr_comba64(A,B); + goto clean; } #endif - fp_sqr_comba(A, B); + err = fp_sqr_comba(A, B); + +clean: + /* zero any excess digits on the destination that we didn't write to */ + for (y = B->used; y >= 0 && y < oldused; y++) { + B->dp[y] = 0; + } + + return err; } /* generic comba squarer */ -void fp_sqr_comba(fp_int *A, fp_int *B) +int fp_sqr_comba(fp_int *A, fp_int *B) { int pa, ix, iz; fp_digit c0, c1, c2; - fp_int tmp, *dst; #ifdef TFM_ISO fp_word tt; -#endif +#endif + fp_int *dst; +#ifndef WOLFSSL_SMALL_STACK + fp_int tmp[1]; +#else + fp_int *tmp; +#endif + +#ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (tmp == NULL) + return FP_MEM; +#endif /* get size of output and trim */ pa = A->used + A->used; @@ -1375,14 +2641,14 @@ void fp_sqr_comba(fp_int *A, fp_int *B) COMBA_CLEAR; if (A == B) { - fp_init(&tmp); - dst = &tmp; + fp_init(tmp); + dst = tmp; } else { fp_zero(B); dst = B; } - for (ix = 0; ix < pa; ix++) { + for (ix = 0; ix < pa; ix++) { int tx, ty, iy; fp_digit *tmpy, *tmpx; @@ -1394,14 +2660,14 @@ void fp_sqr_comba(fp_int *A, fp_int *B) tmpx = A->dp + tx; tmpy = A->dp + ty; - /* this is the number of times the loop will iterrate, + /* this is the number of times the loop will iterate, while (tx++ < a->used && ty-- >= 0) { ... } */ iy = MIN(A->used-tx, ty+1); - /* now for squaring tx can never equal ty - * we halve the distance since they approach - * at a rate of 2x and we have to round because + /* now for squaring tx can never equal ty + * we halve the distance since they approach + * at a rate of 2x and we have to round because * odd cases need to be executed */ iy = MIN(iy, (ty-tx+1)>>1); @@ -1432,6 +2698,17 @@ void fp_sqr_comba(fp_int *A, fp_int *B) if (dst != B) { fp_copy(dst, B); } + + /* Variables used but not seen by cppcheck. */ + (void)c0; (void)c1; (void)c2; +#ifdef TFM_ISO + (void)tt; +#endif + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return FP_OKAY; } int fp_cmp(fp_int *a, fp_int *b) @@ -1454,6 +2731,10 @@ int fp_cmp(fp_int *a, fp_int *b) /* compare against a single digit */ int fp_cmp_d(fp_int *a, fp_digit b) { + /* special case for zero*/ + if (a->used == 0 && b == 0) + return FP_EQ; + /* compare based on sign */ if ((b && a->used == 0) || a->sign == FP_NEG) { return FP_LT; @@ -1495,7 +2776,7 @@ int fp_cmp_mag(fp_int *a, fp_int *b) return FP_EQ; } -/* setups the montgomery reduction */ +/* sets up the montgomery reduction */ int fp_montgomery_setup(fp_int *a, fp_digit *rho) { fp_digit x, b; @@ -1562,39 +2843,46 @@ void fp_montgomery_calc_normalization(fp_int *a, fp_int *b) #endif #ifdef HAVE_INTEL_MULX -static inline void innermul8_mulx(fp_digit *c_mulx, fp_digit *cy_mulx, fp_digit *tmpm, fp_digit mu) +static WC_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 ; } /* computes x/R == x (mod N) via Montgomery Reduction */ -static void fp_montgomery_reduce_mulx(fp_int *a, fp_int *m, fp_digit mp) +static int fp_montgomery_reduce_mulx(fp_int *a, fp_int *m, fp_digit mp) { - fp_digit c[FP_SIZE], *_c, *tmpm, mu = 0; +#ifndef WOLFSSL_SMALL_STACK + fp_digit c[FP_SIZE+1]; +#else + fp_digit *c; +#endif + fp_digit *_c, *tmpm, mu = 0; int oldused, x, y, pa; /* bail if too large */ if (m->used > (FP_SIZE/2)) { (void)mu; /* shut up compiler */ - return; + return FP_OKAY; } #ifdef TFM_SMALL_MONT_SET if (m->used <= 16) { - fp_montgomery_reduce_small(a, m, mp); - return; + return fp_montgomery_reduce_small(a, m, mp); } #endif +#ifdef WOLFSSL_SMALL_STACK + /* only allocate space for what's needed for window plus res */ + c = (fp_digit*)XMALLOC(sizeof(fp_digit)*(FP_SIZE + 1), NULL, DYNAMIC_TYPE_BIGINT); + if (c == NULL) { + return FP_MEM; + } +#endif /* now zero the buff */ - XMEMSET(c, 0, sizeof c); + XMEMSET(c, 0, sizeof(fp_digit)*(FP_SIZE + 1)); pa = m->used; /* copy the input */ @@ -1625,7 +2913,7 @@ static void fp_montgomery_reduce_mulx(fp_int *a, fp_int *m, fp_digit mp) PROPCARRY; ++_c; } - } + } /* now copy out */ _c = c + pa; @@ -1634,7 +2922,8 @@ static void fp_montgomery_reduce_mulx(fp_int *a, fp_int *m, fp_digit mp) *tmpm++ = *_c++; } - for (; x < oldused; x++) { + /* zero any excess digits on the destination that we didn't write to */ + for (; x < oldused; x++) { *tmpm++ = 0; } @@ -1642,38 +2931,55 @@ static void fp_montgomery_reduce_mulx(fp_int *a, fp_int *m, fp_digit mp) a->used = pa+1; fp_clamp(a); - + /* if A >= m then A = A - m */ if (fp_cmp_mag (a, m) != FP_LT) { s_fp_sub (a, m, a); } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(c, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return FP_OKAY; } #endif /* computes x/R == x (mod N) via Montgomery Reduction */ -void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) +int fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) { - fp_digit c[FP_SIZE], *_c, *tmpm, mu = 0; - int oldused, x, y, pa; +#ifndef WOLFSSL_SMALL_STACK + fp_digit c[FP_SIZE+1]; +#else + fp_digit *c; +#endif + fp_digit *_c, *tmpm, mu = 0; + int oldused, x, y, pa, err = 0; - IF_HAVE_INTEL_MULX(fp_montgomery_reduce_mulx(a, m, mp), return) ; + IF_HAVE_INTEL_MULX(err = fp_montgomery_reduce_mulx(a, m, mp), return err) ; + (void)err; /* bail if too large */ if (m->used > (FP_SIZE/2)) { (void)mu; /* shut up compiler */ - return; + return FP_OKAY; } #ifdef TFM_SMALL_MONT_SET if (m->used <= 16) { - fp_montgomery_reduce_small(a, m, mp); - return; + return fp_montgomery_reduce_small(a, m, mp); } #endif +#ifdef WOLFSSL_SMALL_STACK + /* only allocate space for what's needed for window plus res */ + c = (fp_digit*)XMALLOC(sizeof(fp_digit)*(FP_SIZE + 1), NULL, DYNAMIC_TYPE_BIGINT); + if (c == NULL) { + return FP_MEM; + } +#endif /* now zero the buff */ - XMEMSET(c, 0, sizeof c); + XMEMSET(c, 0, sizeof(fp_digit)*(FP_SIZE + 1)); pa = m->used; /* copy the input */ @@ -1690,13 +2996,13 @@ void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) _c = c + x; tmpm = m->dp; y = 0; - #if (defined(TFM_SSE2) || defined(TFM_X86_64)) +#if defined(INNERMUL8) for (; y < (pa & ~7); y += 8) { INNERMUL8 ; _c += 8; tmpm += 8; } - #endif +#endif for (; y < pa; y++) { INNERMUL; ++_c; @@ -1706,7 +3012,7 @@ void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) PROPCARRY; ++_c; } - } + } /* now copy out */ _c = c + pa; @@ -1715,7 +3021,8 @@ void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) *tmpm++ = *_c++; } - for (; x < oldused; x++) { + /* zero any excess digits on the destination that we didn't write to */ + for (; x < oldused; x++) { *tmpm++ = 0; } @@ -1723,21 +3030,40 @@ void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) a->used = pa+1; fp_clamp(a); - + /* if A >= m then A = A - m */ if (fp_cmp_mag (a, m) != FP_LT) { s_fp_sub (a, m, a); } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(c, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return FP_OKAY; } -void fp_read_unsigned_bin(fp_int *a, unsigned char *b, int c) +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)) && defined(FP_32BIT) +#if (defined(LITTLE_ENDIAN_ORDER) || defined(BIG_ENDIAN_ORDER)) && \ + defined(FP_32BIT) /* But not for both simultaneously */ #if defined(LITTLE_ENDIAN_ORDER) && defined(BIG_ENDIAN_ORDER) #error Both LITTLE_ENDIAN_ORDER and BIG_ENDIAN_ORDER defined. @@ -1745,11 +3071,6 @@ void fp_read_unsigned_bin(fp_int *a, 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 @@ -1757,12 +3078,12 @@ void fp_read_unsigned_bin(fp_int *a, unsigned char *b, int c) /* Use Duff's device to unroll the loop. */ int idx = (c - 1) & ~3; switch (c % 4) { - case 0: do { pd[idx+0] = *b++; - case 3: pd[idx+1] = *b++; - case 2: pd[idx+2] = *b++; - case 1: pd[idx+3] = *b++; + case 0: do { pd[idx+0] = *b++; // fallthrough + case 3: pd[idx+1] = *b++; // fallthrough + case 2: pd[idx+2] = *b++; // fallthrough + case 1: pd[idx+3] = *b++; // fallthrough idx -= 4; - } while ((c -= 4) > 0); + } while ((c -= 4) > 0); } } #else @@ -1776,25 +3097,108 @@ void fp_read_unsigned_bin(fp_int *a, 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); } -void fp_to_unsigned_bin(fp_int *a, unsigned char *b) +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 +} + +int fp_to_unsigned_bin(fp_int *a, unsigned char *b) { int x; - fp_int t; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif - fp_init_copy(&t, a); +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) + return FP_MEM; +#endif - x = 0; - while (fp_iszero (&t) == FP_NO) { - b[x++] = (unsigned char) (t.dp[0] & 255); - fp_div_2d (&t, 8, &t, NULL); + fp_init_copy(t, a); + + x = fp_to_unsigned_bin_at_pos(0, t, b); + fp_reverse (b, x); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return FP_OKAY; +} + +int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c) +{ +#if DIGIT_BIT == 64 || DIGIT_BIT == 32 + int i, j, x; + + for (x=c-1,j=0,i=0; x >= 0; x--) { + b[x] = (unsigned char)(a->dp[i] >> j); + j += 8; + i += j == DIGIT_BIT; + j &= DIGIT_BIT - 1; + } + + return FP_OKAY; +#else + int x; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) + return FP_MEM; +#endif + + fp_init_copy(t, a); + + for (x = 0; x < c; x++) { + b[x] = (unsigned char) (t->dp[0] & 255); + fp_div_2d (t, 8, t, NULL); } fp_reverse (b, x); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return FP_OKAY; +#endif } int fp_unsigned_bin_size(fp_int *a) @@ -1810,6 +3214,77 @@ 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) +{ + fp_digit i; + + if (b > FP_MAX_BITS) + return 0; + else + i = b/DIGIT_BIT; + + if ((fp_digit)a->used < i) + return 0; + + return (int)((a->dp[i] >> b%DIGIT_BIT) & (fp_digit)1); +} + +/* set the b bit of a */ +int fp_set_bit (fp_int * a, fp_digit b) +{ + fp_digit i; + + if (b > FP_MAX_BITS) + return 0; + else + i = b/DIGIT_BIT; + + /* set the used count of where the bit will go if required */ + if (a->used < (int)(i+1)) + a->used = (int)(i+1); + + /* put the single bit in its place */ + a->dp[i] |= ((fp_digit)1) << (b % DIGIT_BIT); + + return MP_OKAY; +} + int fp_count_bits (fp_int * a) { int r; @@ -1829,6 +3304,7 @@ int fp_count_bits (fp_int * a) ++r; q >>= ((fp_digit) 1); } + return r; } @@ -1853,36 +3329,38 @@ 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]; - } - - /* zero lower digits */ - for (; y >= 0; y--) { - a->dp[y] = 0; - } + /* move digits */ + for (; y >= x; y--) { + a->dp[y] = a->dp[y-x]; + } - /* clamp digits */ - fp_clamp(a); + /* zero lower digits */ + for (; y >= 0; y--) { + a->dp[y] = 0; + } + + /* clamp digits */ + fp_clamp(a); } /* right shift by bit count */ void fp_rshb(fp_int *c, int x) { - register fp_digit *tmpc, mask, shift; + fp_digit *tmpc, mask, shift; fp_digit r, rr; fp_digit D = x; + if (fp_iszero(c)) return; + /* mask */ mask = (((fp_digit)1) << D) - 1; @@ -1905,6 +3383,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); } @@ -1927,7 +3408,7 @@ void fp_rshd(fp_int *a, int x) for (; y < a->used; y++) { a->dp[y] = 0; } - + /* decrement count */ a->used -= x; fp_clamp(a); @@ -1952,16 +3433,40 @@ void fp_reverse (unsigned char *s, int len) /* c = a - b */ -void fp_sub_d(fp_int *a, fp_digit b, fp_int *c) +int fp_sub_d(fp_int *a, fp_digit b, fp_int *c) { - fp_int tmp; - fp_init(&tmp); - fp_set(&tmp, b); - fp_sub(a, &tmp, c); +#ifndef WOLFSSL_SMALL_STACK + fp_int tmp[1]; +#else + fp_int *tmp; +#endif + +#ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (tmp == NULL) + return FP_MEM; +#endif + + 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 +#endif + { + fp_sub(a, tmp, c); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return FP_OKAY; } -/* CyaSSL callers from normal lib */ +/* wolfSSL callers from normal lib */ /* init a new mp_int */ int mp_init (mp_int * a) @@ -1971,30 +3476,92 @@ int mp_init (mp_int * a) return MP_OKAY; } -#ifdef ALT_ECC_SIZE 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; 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; +#else + size = FP_SIZE; #endif + XMEMSET(a->dp, 0, size * sizeof(fp_digit)); +} + +void fp_clear(fp_int *a) +{ + int size; + a->used = 0; + a->sign = FP_ZPOS; +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#else + size = FP_SIZE; +#endif + XMEMSET(a->dp, 0, size * sizeof(fp_digit)); + fp_free(a); +} + +void fp_forcezero (mp_int * a) +{ + int size; + a->used = 0; + a->sign = FP_ZPOS; +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#else + size = FP_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 */ -int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, mp_int* f) +int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, + mp_int* e, mp_int* f) { if (a) fp_init(a); @@ -2027,40 +3594,103 @@ 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 fp_mul(a, b, c); +} + +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); + #if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + int A = fp_count_bits (a); + int B = fp_count_bits (b); + + if( A >= ESP_RSA_MULM_BITS && B >= ESP_RSA_MULM_BITS) + return esp_mp_mulmod(a, b, c, d); + else + #endif + return fp_mulmod(a, b, c, d); +} + +/* d = a - b (mod c) */ +int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) +{ + return fp_submod(a, b, c, d); +} + +/* d = a + b (mod c) */ +int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) +{ + return fp_addmod(a, b, c, 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); } +/* hac 14.61, pp608 */ +int mp_invmod_mont_ct (mp_int * a, mp_int * b, mp_int * c, mp_digit mp) +{ + return fp_invmod_mont_ct(a, b, c, mp); +} + /* this is a shell function that calls either the normal or Montgomery * exptmod functions. Originally the call to the montgomery code was - * embedded in the normal function but that wasted alot of stack space + * 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 { return fp_exptmod(G, X, P, Y); } +int mp_exptmod_ex (mp_int * G, mp_int * X, int digits, mp_int * P, mp_int * Y) +{ + return fp_exptmod_ex(G, X, digits, P, Y); +} + +int mp_exptmod_nct (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +{ + return fp_exptmod_nct(G, X, P, Y); +} + + /* compare two ints (signed)*/ int mp_cmp (mp_int * a, mp_int * b) { @@ -2079,35 +3709,85 @@ 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) { - fp_to_unsigned_bin(a,b); - return MP_OKAY; + return fp_to_unsigned_bin(a,b); } +int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c) +{ + return fp_to_unsigned_bin_len(a, b, c); +} /* reads a unsigned char array, assumes the msb is stored first [big endian] */ int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) { - fp_read_unsigned_bin(a, (unsigned char *)b, c); + fp_read_unsigned_bin(a, b, c); return MP_OKAY; } int mp_sub_d(fp_int *a, fp_digit b, fp_int *c) { - fp_sub_d(a, b, c); + return fp_sub_d(a, b, c); +} + +int mp_mul_2d(fp_int *a, int b, fp_int *c) +{ + fp_mul_2d(a, b, c); + return MP_OKAY; +} + +int mp_2expt(fp_int* a, int b) +{ + fp_2expt(a, b); return MP_OKAY; } - -#ifdef ALT_ECC_SIZE -void fp_copy(fp_int *a, fp_int* b) +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); + return MP_OKAY; +} + +void fp_copy(fp_int *a, fp_int *b) +{ + /* if source and destination are different */ if (a != b) { +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + /* verify a will fit in b */ + if (b->size >= a->used) { + int x, oldused; + oldused = b->used; + b->used = a->used; + b->sign = a->sign; + + 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 >= 0 && x < oldused; x++) { + b->dp[x] = 0; + } + } + else { + /* TODO: Handle error case */ + } +#else + /* all dp's are same size, so do straight copy */ b->used = a->used; b->sign = a->sign; - XMEMCPY(b->dp, a->dp, a->used * sizeof(fp_digit)); + XMEMCPY(b->dp, a->dp, FP_SIZE * sizeof(fp_digit)); +#endif } } @@ -2118,67 +3798,98 @@ void fp_init_copy(fp_int *a, fp_int* b) fp_copy(b, a); } } -#endif -/* fast math conversion */ +/* fast math wrappers */ int mp_copy(fp_int* a, fp_int* b) { fp_copy(a, b); return MP_OKAY; } - -/* fast math conversion */ int mp_isodd(mp_int* a) { return fp_isodd(a); } - -/* fast math conversion */ int mp_iszero(mp_int* a) { return fp_iszero(a); } - -/* fast math conversion */ int mp_count_bits (mp_int* a) { return fp_count_bits(a); } - int mp_leading_bit (mp_int* a) { return fp_leading_bit(a); } - -/* fast math conversion */ void mp_rshb (mp_int* a, int x) { fp_rshb(a, x); } - -/* fast math wrappers */ -int mp_set_int(fp_int *a, fp_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; } +int mp_is_bit_set (mp_int *a, mp_digit b) +{ + return fp_is_bit_set(a, b); +} -#if defined(WOLFSSL_KEY_GEN) || defined (HAVE_ECC) +int mp_set_bit(mp_int *a, mp_digit b) +{ + return fp_set_bit(a, b); +} + +#if defined(WOLFSSL_KEY_GEN) || defined (HAVE_ECC) || !defined(NO_DH) || \ + !defined(NO_DSA) || !defined(NO_RSA) /* c = a * a (mod b) */ int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c) { - fp_int tmp; - fp_init(&tmp); - fp_sqr(a, &tmp); - return fp_mod(&tmp, b, c); + int err; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) + return FP_MEM; +#endif + + fp_init(t); + err = fp_sqr(a, t); + if (err == FP_OKAY) { + #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 + #endif + { + err = fp_mod(t, b, c); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return err; } /* fast math conversion */ @@ -2197,7 +3908,37 @@ int mp_montgomery_calc_normalization(mp_int *a, mp_int *b) #endif /* WOLFSSL_KEYGEN || HAVE_ECC */ -#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) +#if defined(WC_MP_TO_RADIX) || !defined(NO_DH) || !defined(NO_DSA) || \ + !defined(NO_RSA) + +#ifdef WOLFSSL_KEY_GEN +/* swap the elements of two integers, for cases where you can't simply swap the + * mp_int pointers around + */ +static int fp_exch (fp_int * a, fp_int * b) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) + return FP_MEM; +#endif + + *t = *a; + *a = *b; + *b = *t; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return FP_OKAY; +} +#endif static const int lnz[16] = { 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 @@ -2210,12 +3951,12 @@ int fp_cnt_lsb(fp_int *a) fp_digit q, qq; /* easy out */ - if (fp_iszero(a) == 1) { + if (fp_iszero(a) == FP_YES) { return 0; } /* scan lower digits until non-zero */ - for (x = 0; x < a->used && a->dp[x] == 0; x++); + for (x = 0; x < a->used && a->dp[x] == 0; x++) {} q = a->dp[x]; x *= DIGIT_BIT; @@ -2231,30 +3972,32 @@ int fp_cnt_lsb(fp_int *a) } - - static int s_is_power_of_two(fp_digit b, int *p) { int x; /* fast return if no power of two */ if ((b==0) || (b & (b-1))) { - return 0; + return FP_NO; } for (x = 0; x < DIGIT_BIT; x++) { if (b == (((fp_digit)1)< cb + d == a */ static int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d) { - fp_int q; +#ifndef WOLFSSL_SMALL_STACK + fp_int q[1]; +#else + fp_int *q; +#endif fp_word w; fp_digit t; int ix; @@ -2265,7 +4008,7 @@ static int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d) } /* quick outs */ - if (b == 1 || fp_iszero(a) == 1) { + if (b == 1 || fp_iszero(a) == FP_YES) { if (d != NULL) { *d = 0; } @@ -2276,7 +4019,7 @@ static int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d) } /* power of two ? */ - if (s_is_power_of_two(b, &ix) == 1) { + if (s_is_power_of_two(b, &ix) == FP_YES) { if (d != NULL) { *d = a->dp[0] & ((((fp_digit)1)<used; - q.sign = a->sign; +#ifdef WOLFSSL_SMALL_STACK + q = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (q == NULL) + return FP_MEM; +#endif + + fp_init(q); + + if (c != NULL) { + q->used = a->used; + q->sign = a->sign; + } + w = 0; for (ix = a->used - 1; ix >= 0; ix--) { w = (w << ((fp_word)DIGIT_BIT)) | ((fp_word)a->dp[ix]); - + if (w >= b) { t = (fp_digit)(w / b); w -= ((fp_word)t) * ((fp_word)b); } else { t = 0; } - q.dp[ix] = (fp_digit)t; + if (c != NULL) + q->dp[ix] = (fp_digit)t; } - + if (d != NULL) { *d = (fp_digit)w; } - + if (c != NULL) { - fp_clamp(&q); - fp_copy(&q, c); + fp_clamp(q); + fp_copy(q, c); } - + +#ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_BIGINT); +#endif return FP_OKAY; } @@ -2328,101 +4083,148 @@ int mp_mod_d(fp_int *a, fp_digit b, fp_digit *c) return fp_mod_d(a, b, c); } -#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ - -#ifdef WOLFSSL_KEY_GEN - -void fp_gcd(fp_int *a, fp_int *b, fp_int *c); -void fp_lcm(fp_int *a, fp_int *b, fp_int *c); -int fp_isprime(fp_int *a); - -int mp_gcd(fp_int *a, fp_int *b, fp_int *c) -{ - fp_gcd(a, b, c); - return MP_OKAY; -} +#endif /* WC_MP_TO_RADIX || !NO_DH || !NO_DSA || !NO_RSA */ -int mp_lcm(fp_int *a, fp_int *b, fp_int *c) -{ - fp_lcm(a, b, c); - return MP_OKAY; -} +#if !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) || \ + defined(WOLFSSL_KEY_GEN) + +static int fp_isprime_ex(fp_int *a, int t, int* result); int mp_prime_is_prime(mp_int* a, int t, int* result) { - (void)t; - *result = fp_isprime(a); - return MP_OKAY; + return fp_isprime_ex(a, t, result); } -/* Miller-Rabin test of "a" to the base of "b" as described in +/* Miller-Rabin test of "a" to the base of "b" as described in * HAC pp. 139 Algorithm 4.24 * * Sets result to 0 if definitely composite or 1 if probably prime. - * Randomly the chance of error is no more than 1/4 and often + * Randomly the chance of error is no more than 1/4 and often * very much lower. */ -static void fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result) +static int fp_prime_miller_rabin_ex(fp_int * a, fp_int * b, int *result, + fp_int *n1, fp_int *y, fp_int *r) { - fp_int n1, y, r; - int s, j; + int s, j; + int err; /* default */ *result = FP_NO; /* ensure b > 1 */ if (fp_cmp_d(b, 1) != FP_GT) { - return; - } + return FP_OKAY; + } /* get n1 = a - 1 */ - fp_init_copy(&n1, a); - fp_sub_d(&n1, 1, &n1); + fp_copy(a, n1); + err = fp_sub_d(n1, 1, n1); + if (err != FP_OKAY) { + return err; + } /* set 2**s * r = n1 */ - fp_init_copy(&r, &n1); + fp_copy(n1, r); /* count the number of least significant bits * which are zero */ - s = fp_cnt_lsb(&r); + s = fp_cnt_lsb(r); /* now divide n - 1 by 2**s */ - fp_div_2d (&r, s, &r, NULL); + fp_div_2d (r, s, r, NULL); /* compute y = b**r mod a */ - fp_init(&y); - fp_exptmod(b, &r, a, &y); + fp_zero(y); +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 + if (fp_count_bits(a) == 1024) + sp_ModExp_1024(b, r, a, y); + else if (fp_count_bits(a) == 2048) + sp_ModExp_2048(b, r, a, y); + else +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (fp_count_bits(a) == 1536) + sp_ModExp_1536(b, r, a, y); + else if (fp_count_bits(a) == 3072) + sp_ModExp_3072(b, r, a, y); + else +#endif +#ifdef WOLFSSL_SP_4096 + if (fp_count_bits(a) == 4096) + sp_ModExp_4096(b, r, a, y); + else +#endif +#endif + fp_exptmod(b, r, a, y); /* if y != 1 and y != n1 do */ - if (fp_cmp_d (&y, 1) != FP_EQ && fp_cmp (&y, &n1) != FP_EQ) { + if (fp_cmp_d (y, 1) != FP_EQ && fp_cmp (y, n1) != FP_EQ) { j = 1; /* while j <= s-1 and y != n1 */ - while ((j <= (s - 1)) && fp_cmp (&y, &n1) != FP_EQ) { - fp_sqrmod (&y, a, &y); + while ((j <= (s - 1)) && fp_cmp (y, n1) != FP_EQ) { + fp_sqrmod (y, a, y); /* if y == 1 then composite */ - if (fp_cmp_d (&y, 1) == FP_EQ) { - return; + if (fp_cmp_d (y, 1) == FP_EQ) { + return FP_OKAY; } ++j; } /* if y != n1 then composite */ - if (fp_cmp (&y, &n1) != FP_EQ) { - return; + if (fp_cmp (y, n1) != FP_EQ) { + return FP_OKAY; } } /* probably prime now */ *result = FP_YES; + + return FP_OKAY; +} + +static int fp_prime_miller_rabin(fp_int * a, fp_int * b, int *result) +{ + int err; +#ifndef WOLFSSL_SMALL_STACK + fp_int n1[1], y[1], r[1]; +#else + fp_int *n1, *y, *r; +#endif + +#ifdef WOLFSSL_SMALL_STACK + n1 = (fp_int*)XMALLOC(sizeof(fp_int) * 3, NULL, DYNAMIC_TYPE_BIGINT); + if (n1 == NULL) { + return FP_MEM; + } + y = &n1[1]; r = &n1[2]; +#endif + + fp_init(n1); + fp_init(y); + fp_init(r); + + err = fp_prime_miller_rabin_ex(a, b, result, n1, y, r); + + fp_clear(n1); + fp_clear(y); + fp_clear(r); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(n1, NULL, DYNAMIC_TYPE_BIGINT); +#endif + + return err; } /* a few primes */ -static const fp_digit primes[256] = { +static const fp_digit primes[FP_PRIME_SIZE] = { 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, @@ -2460,104 +4262,427 @@ static const fp_digit primes[256] = { 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 }; -int fp_isprime(fp_int *a) +int fp_isprime_ex(fp_int *a, int t, int* result) { - fp_int b; - fp_digit d = 0; +#ifndef WOLFSSL_SMALL_STACK + fp_int b[1]; +#else + fp_int *b; +#endif + fp_digit d; int r, res; - /* do trial division */ - for (r = 0; r < 256; r++) { - fp_mod_d(a, primes[r], &d); - if (d == 0) { - return FP_NO; + if (t <= 0 || t > FP_PRIME_SIZE) { + *result = FP_NO; + return FP_VAL; + } + + if (fp_isone(a)) { + *result = FP_NO; + return FP_OKAY; + } + + /* check against primes table */ + for (r = 0; r < FP_PRIME_SIZE; r++) { + if (fp_cmp_d(a, primes[r]) == FP_EQ) { + *result = FP_YES; + return FP_OKAY; } } - /* now do 8 miller rabins */ - fp_init(&b); - for (r = 0; r < 8; r++) { - fp_set(&b, primes[r]); - fp_prime_miller_rabin(a, &b, &res); - if (res == FP_NO) { - return FP_NO; + /* do trial division */ + for (r = 0; r < FP_PRIME_SIZE; r++) { + res = fp_mod_d(a, primes[r], &d); + if (res != MP_OKAY || d == 0) { + *result = FP_NO; + return FP_OKAY; } } - return FP_YES; + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (b == NULL) + return FP_MEM; +#endif + /* now do 't' miller rabins */ + fp_init(b); + for (r = 0; r < t; r++) { + fp_set(b, primes[r]); + fp_prime_miller_rabin(a, b, &res); + if (res == FP_NO) { + *result = FP_NO; + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return FP_OKAY; + } + } + *result = FP_YES; +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return FP_OKAY; } -/* c = [a, b] */ -void fp_lcm(fp_int *a, fp_int *b, fp_int *c) +int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) { - fp_int t1, t2; + int ret = FP_YES; + fp_digit d; + int i; - fp_init(&t1); - fp_init(&t2); - fp_gcd(a, b, &t1); - if (fp_cmp_mag(a, b) == FP_GT) { - fp_div(a, &t1, &t2, NULL); - fp_mul(b, &t2, c); - } else { - fp_div(b, &t1, &t2, NULL); - fp_mul(a, &t2, c); - } + if (a == NULL || result == NULL || rng == NULL) + return FP_VAL; + + if (fp_isone(a)) { + *result = FP_NO; + return FP_OKAY; + } + + /* check against primes table */ + for (i = 0; i < FP_PRIME_SIZE; i++) { + if (fp_cmp_d(a, primes[i]) == FP_EQ) { + *result = FP_YES; + return FP_OKAY; + } + } + + /* do trial division */ + for (i = 0; i < FP_PRIME_SIZE; i++) { + if (fp_mod_d(a, primes[i], &d) == MP_OKAY) { + if (d == 0) { + *result = FP_NO; + return FP_OKAY; + } + } + else + return FP_VAL; + } + +#ifndef WC_NO_RNG + /* now do a miller rabin with up to t random numbers, this should + * give a (1/4)^t chance of a false prime. */ + { + #ifndef WOLFSSL_SMALL_STACK + fp_int b[1], c[1], n1[1], y[1], r[1]; + byte base[FP_MAX_PRIME_SIZE]; + #else + fp_int *b, *c, *n1, *y, *r; + byte* base; + #endif + word32 baseSz; + int err; + + baseSz = fp_count_bits(a); + /* The base size is the number of bits / 8. One is added if the number + * of bits isn't an even 8. */ + baseSz = (baseSz / 8) + ((baseSz % 8) ? 1 : 0); + + #ifndef WOLFSSL_SMALL_STACK + if (baseSz > sizeof(base)) + return FP_MEM; + #else + base = (byte*)XMALLOC(baseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (base == NULL) + return FP_MEM; + + b = (fp_int*)XMALLOC(sizeof(fp_int) * 5, NULL, DYNAMIC_TYPE_BIGINT); + if (b == NULL) { + return FP_MEM; + } + c = &b[1]; n1 = &b[2]; y= &b[3]; r = &b[4]; + #endif + + fp_init(b); + fp_init(c); + fp_init(n1); + fp_init(y); + fp_init(r); + + err = fp_sub_d(a, 2, c); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_BIGINT); + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + while (t > 0) { + if ((err = wc_RNG_GenerateBlock(rng, base, baseSz)) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_BIGINT); + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + + fp_read_unsigned_bin(b, base, baseSz); + if (fp_cmp_d(b, 2) != FP_GT || fp_cmp(b, c) != FP_LT) { + continue; + } + + fp_prime_miller_rabin_ex(a, b, &ret, n1, y, r); + if (ret == FP_NO) + break; + fp_zero(b); + t--; + } + + fp_clear(n1); + fp_clear(y); + fp_clear(r); + fp_clear(b); + fp_clear(c); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_BIGINT); + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } +#else + (void)t; +#endif /* !WC_NO_RNG */ + + *result = ret; + return FP_OKAY; +} +#endif /* !NO_RSA || !NO_DSA || !NO_DH || WOLFSSL_KEY_GEN */ + + +#ifdef WOLFSSL_KEY_GEN + +static int fp_gcd(fp_int *a, fp_int *b, fp_int *c); +static int fp_lcm(fp_int *a, fp_int *b, fp_int *c); +static int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap); + +int mp_gcd(fp_int *a, fp_int *b, fp_int *c) +{ + return fp_gcd(a, b, c); +} + + +int mp_lcm(fp_int *a, fp_int *b, fp_int *c) +{ + return fp_lcm(a, b, c); +} + +int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap) +{ + int err; + + err = fp_randprime(N, len, rng, heap); + switch(err) { + case FP_VAL: + return MP_VAL; + case FP_MEM: + return MP_MEM; + default: + break; + } + + return MP_OKAY; +} + +int mp_exch (mp_int * a, mp_int * b) +{ + return fp_exch(a, b); +} + + + +int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap) +{ + static const int USE_BBS = 1; + int err, type; + int isPrime = FP_YES; + /* Assume the candidate is probably prime and then test until + * it is proven composite. */ + byte* buf; + + (void)heap; + + /* get type */ + if (len < 0) { + type = USE_BBS; + len = -len; + } else { + type = 0; + } + + /* allow sizes between 2 and 512 bytes for a prime size */ + if (len < 2 || len > 512) { + return FP_VAL; + } + + /* allocate buffer to work with */ + buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + return FP_MEM; + } + XMEMSET(buf, 0, len); + + do { +#ifdef SHOW_GEN + printf("."); + fflush(stdout); +#endif + /* generate value */ + err = wc_RNG_GenerateBlock(rng, buf, len); + if (err != 0) { + XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER); + return FP_VAL; + } + + /* munge bits */ + buf[0] |= 0x80 | 0x40; + buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); + + /* load value */ + fp_read_unsigned_bin(N, buf, len); + + /* test */ + /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance + * of a 1024-bit candidate being a false positive, when it is our + * prime candidate. (Note 4.49 of Handbook of Applied Cryptography.) + * Using 8 because we've always used 8 */ + mp_prime_is_prime_ex(N, 8, &isPrime, rng); + } while (isPrime == FP_NO); + + XMEMSET(buf, 0, len); + XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER); + + return FP_OKAY; +} + +/* c = [a, b] */ +int fp_lcm(fp_int *a, fp_int *b, fp_int *c) +{ + int err; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[2]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) { + return FP_MEM; + } +#endif + + fp_init(&t[0]); + fp_init(&t[1]); + err = fp_gcd(a, b, &t[0]); + if (err == FP_OKAY) { + if (fp_cmp_mag(a, b) == FP_GT) { + err = fp_div(a, &t[0], &t[1], NULL); + if (err == FP_OKAY) + err = fp_mul(b, &t[1], c); + } else { + err = fp_div(b, &t[0], &t[1], NULL); + if (err == FP_OKAY) + err = fp_mul(a, &t[1], c); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return err; } /* c = (a, b) */ -void fp_gcd(fp_int *a, fp_int *b, fp_int *c) +int fp_gcd(fp_int *a, fp_int *b, fp_int *c) { - fp_int u, v, r; +#ifndef WOLFSSL_SMALL_STACK + fp_int u[1], v[1], r[1]; +#else + fp_int *u, *v, *r; +#endif /* either zero than gcd is the largest */ - if (fp_iszero (a) == 1 && fp_iszero (b) == 0) { + if (fp_iszero (a) == FP_YES && fp_iszero (b) == FP_NO) { fp_abs (b, c); - return; + return FP_OKAY; } - if (fp_iszero (a) == 0 && fp_iszero (b) == 1) { + if (fp_iszero (a) == FP_NO && fp_iszero (b) == FP_YES) { fp_abs (a, c); - return; + return FP_OKAY; } /* optimized. At this point if a == 0 then * b must equal zero too */ - if (fp_iszero (a) == 1) { + if (fp_iszero (a) == FP_YES) { fp_zero(c); - return; + return FP_OKAY; } +#ifdef WOLFSSL_SMALL_STACK + u = (fp_int*)XMALLOC(sizeof(fp_int) * 3, NULL, DYNAMIC_TYPE_BIGINT); + if (u == NULL) { + return FP_MEM; + } + v = &u[1]; r = &u[2]; +#endif + /* sort inputs */ if (fp_cmp_mag(a, b) != FP_LT) { - fp_init_copy(&u, a); - fp_init_copy(&v, b); + fp_init_copy(u, a); + fp_init_copy(v, b); } else { - fp_init_copy(&u, b); - fp_init_copy(&v, a); + fp_init_copy(u, b); + fp_init_copy(v, a); } - - fp_init(&r); - while (fp_iszero(&v) == FP_NO) { - fp_mod(&u, &v, &r); - fp_copy(&v, &u); - fp_copy(&r, &v); + + u->sign = FP_ZPOS; + v->sign = FP_ZPOS; + + fp_init(r); + while (fp_iszero(v) == FP_NO) { + fp_mod(u, v, r); + fp_copy(v, u); + fp_copy(r, v); } - fp_copy(&u, c); + fp_copy(u, c); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(u, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return FP_OKAY; } #endif /* WOLFSSL_KEY_GEN */ -#if defined(HAVE_ECC) || !defined(NO_PWDBASED) +#if defined(HAVE_ECC) || !defined(NO_PWDBASED) || defined(OPENSSL_EXTRA) || \ + defined(WC_RSA_BLINDING) || !defined(NO_DSA) || \ + (!defined(NO_RSA) && !defined(NO_RSA_BOUNDS_CHECK)) /* c = a + b */ void fp_add_d(fp_int *a, fp_digit b, fp_int *c) { +#ifndef WOLFSSL_SMALL_STACK fp_int tmp; fp_init(&tmp); fp_set(&tmp, b); - fp_add(a,&tmp,c); + fp_add(a, &tmp, c); +#else + int i; + fp_word t = b; + + fp_copy(a, c); + for (i = 0; t != 0 && i < FP_SIZE && i < c->used; i++) { + t += c->dp[i]; + c->dp[i] = (fp_digit)t; + t >>= DIGIT_BIT; + } + if (i == c->used && i < FP_SIZE && t != 0) { + c->dp[i] = t; + c->used++; + } +#endif } /* external compatibility */ @@ -2567,19 +4692,78 @@ int mp_add_d(fp_int *a, fp_digit b, fp_int *c) return MP_OKAY; } -#endif /* HAVE_ECC || !NO_PWDBASED */ +#endif /* HAVE_ECC || !NO_PWDBASED || OPENSSL_EXTRA || WC_RSA_BLINDING || + !NO_DSA || (!NO_RSA && !NO_RSA_BOUNDS_CHECK) */ -#ifdef HAVE_ECC +#if !defined(NO_DSA) || defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || \ + defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) || \ + defined(DEBUG_WOLFSSL) || defined(OPENSSL_EXTRA) || defined(WC_MP_TO_RADIX) /* chars used in radix conversions */ -static const char *fp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +static wcchar fp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz+/"; +#endif + +#if !defined(NO_DSA) || defined(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; char ch; + /* 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; @@ -2595,16 +4779,13 @@ static int fp_read_radix(fp_int *a, const char *str, int radix) neg = FP_ZPOS; } - /* set the integer to the default of zero */ - fp_zero (a); - /* process each digit of the string */ while (*str) { - /* if the radix < 36 the conversion is case insensitive + /* 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] */ - ch = (char) ((radix < 36) ? XTOUPPER((unsigned char)*str) : *str); + ch = (char)((radix <= 36) ? XTOUPPER((unsigned char)*str) : *str); for (y = 0; y < 64; y++) { if (ch == fp_s_rmap[y]) { break; @@ -2637,24 +4818,20 @@ 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); -} +#endif /* !defined(NO_DSA) || defined(HAVE_ECC) */ + +#ifdef HAVE_ECC /* fast math conversion */ int mp_sqr(fp_int *A, fp_int *B) { - fp_sqr(A, B); - return MP_OKAY; + return fp_sqr(A, B); } - + /* fast math conversion */ int mp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) { - fp_montgomery_reduce(a, m, mp); - return MP_OKAY; + return fp_montgomery_reduce(a, m, mp); } @@ -2677,25 +4854,215 @@ int mp_init_copy(fp_int * a, fp_int * b) return MP_OKAY; } - #ifdef HAVE_COMP_KEY int mp_cnt_lsb(fp_int* a) { - fp_cnt_lsb(a); - return MP_OKAY; -} - -int mp_div_2d(fp_int* a, int b, fp_int* c, fp_int* d) -{ - fp_div_2d(a, b, c, d); - return MP_OKAY; + return fp_cnt_lsb(a); } #endif /* HAVE_COMP_KEY */ - #endif /* HAVE_ECC */ -#endif /* USE_FAST_MATH */ +#if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DSA) || \ + defined(WOLFSSL_KEY_GEN) +/* fast math conversion */ +int mp_set(fp_int *a, fp_digit b) +{ + fp_set(a,b); + return MP_OKAY; +} +#endif +#ifdef WC_MP_TO_RADIX + +/* returns size of ASCII representation */ +int mp_radix_size (mp_int *a, int radix, int *size) +{ + int res, digs; + fp_digit d; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + + *size = 0; + + /* special case for binary */ + if (radix == 2) { + *size = fp_count_bits (a) + (a->sign == FP_NEG ? 1 : 0) + 1; + return FP_YES; + } + + /* make sure the radix is in range */ + if (radix < 2 || radix > 64) { + return FP_VAL; + } + + if (fp_iszero(a) == MP_YES) { + *size = 2; + return FP_OKAY; + } + + /* digs is the digit count */ + digs = 0; + + /* if it's negative add one for the sign */ + if (a->sign == FP_NEG) { + ++digs; + } + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) + return FP_MEM; +#endif + + /* init a copy of the input */ + fp_init_copy (t, a); + + /* force temp to positive */ + t->sign = FP_ZPOS; + + /* fetch out all of the digits */ + while (fp_iszero (t) == FP_NO) { + if ((res = fp_div_d (t, (mp_digit) radix, t, &d)) != FP_OKAY) { + fp_zero (t); + #ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return res; + } + ++digs; + } + fp_zero (t); + + /* return digs + 1, the 1 is for the NULL byte that would be required. */ + *size = digs + 1; +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return FP_OKAY; +} + +/* stores a bignum as a ASCII string in a given radix (2..64) */ +int mp_toradix (mp_int *a, char *str, int radix) +{ + int res, digs; + fp_digit d; + char *_s = str; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + + /* check range of the radix */ + if (radix < 2 || radix > 64) { + return FP_VAL; + } + + /* quick out if its zero */ + if (fp_iszero(a) == FP_YES) { + *str++ = '0'; + *str = '\0'; + return FP_OKAY; + } + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (t == NULL) + return FP_MEM; +#endif + + /* init a copy of the input */ + fp_init_copy (t, a); + + /* if it is negative output a - */ + if (t->sign == FP_NEG) { + ++_s; + *str++ = '-'; + t->sign = FP_ZPOS; + } + + digs = 0; + while (fp_iszero (t) == FP_NO) { + if ((res = fp_div_d (t, (fp_digit) radix, t, &d)) != FP_OKAY) { + fp_zero (t); + #ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return res; + } + *str++ = fp_s_rmap[d]; + ++digs; + } +#ifndef WC_DISABLE_RADIX_ZERO_PAD + /* For hexadecimal output, add zero padding when number of digits is odd */ + if ((digs & 1) && (radix == 16)) { + *str++ = fp_s_rmap[0]; + ++digs; + } +#endif + /* reverse the digits of the string. In this case _s points + * to the first digit [excluding the sign] of the number] + */ + fp_reverse ((unsigned char *)_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + + fp_zero (t); +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return FP_OKAY; +} + +#ifdef WOLFSSL_DEBUG_MATH +void mp_dump(const char* desc, mp_int* a, byte verbose) +{ + char buffer[FP_SIZE * sizeof(fp_digit) * 2]; + int size; + +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#else + size = FP_SIZE; +#endif + + printf("%s: ptr=%p, used=%d, sign=%d, size=%d, fpd=%d\n", + desc, a, a->used, a->sign, size, (int)sizeof(fp_digit)); + + mp_tohex(a, buffer); + printf(" %s\n ", buffer); + + if (verbose) { + int i; + for(i=0; idp) + i)); + } + printf("\n"); + } +} +#endif /* WOLFSSL_DEBUG_MATH */ + +#endif /* WC_MP_TO_RADIX */ + + +int mp_abs(mp_int* a, mp_int* b) +{ + fp_abs(a, b); + return FP_OKAY; +} + + +int mp_lshd (mp_int * a, int b) +{ + fp_lshd(a, b); + return FP_OKAY; +} + +#endif /* USE_FAST_MATH */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_dsp.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_dsp.c new file mode 100644 index 000000000..594ad0489 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_dsp.c @@ -0,0 +1,327 @@ +/* wc_dsp.c + * + * Copyright (C) 2006-2020 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 +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_DSP) +#include "remote.h" +#include "rpcmem.h" +static wolfSSL_DSP_Handle_cb handle_function = NULL; +static remote_handle64 defaultHandle; +static wolfSSL_Mutex handle_mutex; /* mutex for access to single default handle */ + +#define WOLFSSL_HANDLE_DONE 1 +#define WOLFSSL_HANDLE_GET 0 + +/* callback function for setting the default handle in single threaded + * use cases */ +static int default_handle_cb(remote_handle64 *handle, int finished, void *ctx) +{ + (void)ctx; + if (finished == WOLFSSL_HANDLE_DONE) { + if (wc_UnLockMutex(&handle_mutex) != 0) { + WOLFSSL_MSG("Unlock handle mutex failed"); + return -1; + } + } + else { + if (wc_LockMutex(&handle_mutex) != 0) { + WOLFSSL_MSG("Lock handle mutex failed"); + return -1; + } + *handle = defaultHandle; + } + return 0; +} + + +/* Set global callback for getting handle to use + * return 0 on success */ +int wolfSSL_SetHandleCb(wolfSSL_DSP_Handle_cb in) +{ + handle_function = in; + return 0; +} + + +/* returns 1 if global handle callback is set and 0 if not */ +int wolfSSL_GetHandleCbSet() +{ + return (handle_function != NULL)? 1: 0; +} + + +/* Local function for setting up default handle + * returns 0 on success */ +int wolfSSL_InitHandle() +{ + char *sp_URI_value; + int ret; + + sp_URI_value = wolfSSL_URI "&_dom=adsp"; + ret = wolfSSL_open(sp_URI_value, &defaultHandle); + if (ret != 0) { + WOLFSSL_MSG("Unable to open aDSP?"); + return -1; + } + wolfSSL_SetHandleCb(default_handle_cb); + ret = wc_InitMutex(&handle_mutex); + if (ret != 0) { + WOLFSSL_MSG("Unable to init handle mutex"); + return -1; + } + return 0; +} + + +/* internal function that closes default handle and frees mutex */ +void wolfSSL_CleanupHandle() +{ + wolfSSL_close(defaultHandle); + wc_FreeMutex(&handle_mutex); +} +#if defined(WOLFSSL_HAVE_SP_ECC) + +/* ecc conversion from sp_c32.c */ +#include + + +#ifndef WOLFSSL_SP_NO_256 + +#ifdef HAVE_ECC_VERIFY +/* Read big endian unsigned byte array into r. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a Byte array. + * n Number of bytes in array to read. + */ +static void int_256_from_bin(int32* r, int size, const byte* a, int n) +{ + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= (((int32)a[i]) << s); + if (s >= 18U) { + r[j] &= 0x3ffffff; + s = 26U - s; + if (j + 1 >= size) { + break; + } + r[++j] = (int32)a[i] >> s; + s = 8U - s; + } + else { + s += 8U; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * size Maximum number of bytes to convert + * a A multi-precision integer. + */ +static void int_256_from_mp(int32* r, int size, const mp_int* a) +{ +#if DIGIT_BIT == 26 + int j; + + XMEMCPY(r, a->dp, sizeof(int32) * a->used); + + for (j = a->used; j < size; j++) { + r[j] = 0; + } +#elif DIGIT_BIT > 26 + int i, j = 0; + word32 s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((int32)a->dp[i] << s); + r[j] &= 0x3ffffff; + s = 26U - s; + if (j + 1 >= size) { + break; + } + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (int32)(a->dp[i] >> s); /*lint !e9033*/ + while ((s + 26U) <= (word32)DIGIT_BIT) { + s += 26U; + r[j] &= 0x3ffffff; + if (j + 1 >= size) { + break; + } + if (s < (word32)DIGIT_BIT) { + /* lint allow cast of mismatch word32 and mp_digit */ + r[++j] = (int32)(a->dp[i] >> s); /*lint !e9033*/ + } + else { + r[++j] = 0L; + } + } + s = (word32)DIGIT_BIT - s; + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < size; i++) { + r[j] |= ((int32)a->dp[i]) << s; + if (s + DIGIT_BIT >= 26) { + r[j] &= 0x3ffffff; + if (j + 1 >= size) { + break; + } + s = 26 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else { + s += DIGIT_BIT; + } + } + + for (j++; j < size; j++) { + r[j] = 0; + } +#endif +} + +/* 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_dsp_ecc_verify_256(remote_handle64 handleIn, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int ret; + remote_handle64 handle = handleIn; + +#if 0 + /* calling to alloc memory on the ION using these settings slowed the performance down slightly */ + int32 *x = (int32*)rpcmem_alloc(RPCMEM_HEAP_ID_SYSTEM, RPCMEM_DEFAULT_FLAGS, 10*sizeof(int)); + int32 *y = (int32*)rpcmem_alloc(RPCMEM_HEAP_ID_SYSTEM, RPCMEM_DEFAULT_FLAGS, 10*sizeof(int)); + int32 *z = (int32*)rpcmem_alloc(RPCMEM_HEAP_ID_SYSTEM, RPCMEM_DEFAULT_FLAGS, 10*sizeof(int)); + int32 *s = (int32*)rpcmem_alloc(RPCMEM_HEAP_ID_SYSTEM, RPCMEM_DEFAULT_FLAGS, 10*sizeof(int)); + int32 *u1 = (int32*)rpcmem_alloc(RPCMEM_HEAP_ID_SYSTEM, RPCMEM_DEFAULT_FLAGS, 10*sizeof(int)); + int32 *u2 = (int32*)rpcmem_alloc(RPCMEM_HEAP_ID_SYSTEM, RPCMEM_DEFAULT_FLAGS, 10*sizeof(int)); +#endif + int32 x[10] __attribute__((aligned(128))); + int32 y[10] __attribute__((aligned(128))); + int32 z[10] __attribute__((aligned(128))); + int32 s[10] __attribute__((aligned(128))); + int32 u1[10] __attribute__((aligned(128))); + int32 u2[10] __attribute__((aligned(128))); + + if (hashLen > 32U) { + hashLen = 32U; + } + + int_256_from_bin(u1, 10, hash, (int)hashLen); + int_256_from_mp(u2, 10, r); + int_256_from_mp(s, 10, sm); + int_256_from_mp(x, 10, pX); + int_256_from_mp(y, 10, pY); + int_256_from_mp(z, 10, pZ); + + if (handle_function != NULL) { + handle_function(&handle, WOLFSSL_HANDLE_GET, NULL); + } + + *res = 0; + ret = wolfSSL_DSP_ECC_Verify_256(handle, u1, 10, u2, 10, s, 10, x, 10, y, 10, z, 10, res); + + if (handle_function != NULL) { + handle_function(&handle, WOLFSSL_HANDLE_DONE, NULL); + } +#if 0 + rpcmem_free(x); + rpcmem_free(y); + rpcmem_free(z); + rpcmem_free(s); + rpcmem_free(u1); + rpcmem_free(u2); +#endif + return ret; +} + + +/* Used to assign a handle to an ecc_key structure. + * returns 0 on success */ +int wc_ecc_set_handle(ecc_key* key, remote_handle64 handle) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + key->handle = handle; + return 0; +} +#endif /* HAVE_ECC_VERIFY */ +#endif /* !WOLFSSL_SP_NO_256 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_DSP */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_encrypt.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_encrypt.c new file mode 100644 index 000000000..39dbeec5a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_encrypt.c @@ -0,0 +1,660 @@ +/* wc_encrypt.c + * + * Copyright (C) 2006-2020 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if !defined(NO_AES) && defined(HAVE_AES_CBC) +#ifdef HAVE_AES_DECRYPT +int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, + const byte* key, word32 keySz, const byte* iv) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Aes* aes = NULL; +#else + 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_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); +#endif + + return ret; +} +#endif /* HAVE_AES_DECRYPT */ + +int wc_AesCbcEncryptWithKey(byte* out, const byte* in, word32 inSz, + const byte* key, word32 keySz, const byte* iv) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Aes* aes; +#else + Aes aes[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (aes == NULL) + return MEMORY_E; +#endif + + 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); +#endif + + return ret; +} +#endif /* !NO_AES && HAVE_AES_CBC */ + + +#if !defined(NO_DES3) && !defined(WOLFSSL_TI_CRYPT) +int wc_Des_CbcEncryptWithKey(byte* out, const byte* in, word32 sz, + const byte* key, const byte* iv) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Des* des; +#else + Des des[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + des = (Des*)XMALLOC(sizeof(Des), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (des == NULL) + return MEMORY_E; +#endif + + ret = wc_Des_SetKey(des, key, iv, DES_ENCRYPTION); + if (ret == 0) + ret = wc_Des_CbcEncrypt(des, out, in, sz); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(des, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +int wc_Des_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, + const byte* key, const byte* iv) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Des* des; +#else + Des des[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + des = (Des*)XMALLOC(sizeof(Des), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (des == NULL) + return MEMORY_E; +#endif + + ret = wc_Des_SetKey(des, key, iv, DES_DECRYPTION); + if (ret == 0) + ret = wc_Des_CbcDecrypt(des, out, in, sz); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(des, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +int wc_Des3_CbcEncryptWithKey(byte* out, const byte* in, word32 sz, + const byte* key, const byte* iv) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Des3* des3; +#else + Des3 des3[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + des3 = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (des3 == NULL) + return MEMORY_E; +#endif + + 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); +#endif + + return ret; +} + + +int wc_Des3_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, + const byte* key, const byte* iv) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Des3* des3; +#else + Des3 des3[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + des3 = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (des3 == NULL) + return MEMORY_E; +#endif + + 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); +#endif + + return ret; +} + +#endif /* !NO_DES3 */ + + +#ifdef WOLFSSL_ENCRYPTED_KEYS + +int wc_BufferKeyDecrypt(EncryptedInfo* info, byte* der, word32 derSz, + const byte* password, int passwordSz, int hashType) +{ + int ret = NOT_COMPILED_IN; +#ifdef WOLFSSL_SMALL_STACK + byte* key = NULL; +#else + byte key[WC_MAX_SYM_KEY_SIZE]; +#endif + + (void)derSz; + (void)passwordSz; + (void)hashType; + + if (der == NULL || password == NULL || info == NULL || info->keySz == 0) { + return BAD_FUNC_ARG; + } + + /* use file's salt for key derivation, hex decode first */ + if (Base16_Decode(info->iv, info->ivSz, info->iv, &info->ivSz) != 0) { + return BUFFER_E; + } + if (info->ivSz < PKCS5_SALT_SZ) + return BUFFER_E; + +#ifdef WOLFSSL_SMALL_STACK + key = (byte*)XMALLOC(WC_MAX_SYM_KEY_SIZE, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); + if (key == NULL) { + return MEMORY_E; + } +#endif + + (void)XMEMSET(key, 0, WC_MAX_SYM_KEY_SIZE); + +#ifndef NO_PWDBASED + if ((ret = wc_PBKDF1(key, password, passwordSz, info->iv, PKCS5_SALT_SZ, 1, + info->keySz, hashType)) != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); +#endif + return ret; + } +#endif + +#ifndef NO_DES3 + if (info->cipherType == WC_CIPHER_DES) + ret = wc_Des_CbcDecryptWithKey(der, der, derSz, key, info->iv); + if (info->cipherType == WC_CIPHER_DES3) + ret = wc_Des3_CbcDecryptWithKey(der, der, derSz, key, info->iv); +#endif /* NO_DES3 */ +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(HAVE_AES_DECRYPT) + if (info->cipherType == WC_CIPHER_AES_CBC) + ret = wc_AesCbcDecryptWithKey(der, der, derSz, key, info->keySz, + info->iv); +#endif /* !NO_AES && HAVE_AES_CBC && HAVE_AES_DECRYPT */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); +#endif + + return ret; +} + +int wc_BufferKeyEncrypt(EncryptedInfo* info, byte* der, word32 derSz, + const byte* password, int passwordSz, int hashType) +{ + int ret = NOT_COMPILED_IN; +#ifdef WOLFSSL_SMALL_STACK + byte* key = NULL; +#else + byte key[WC_MAX_SYM_KEY_SIZE]; +#endif + + (void)derSz; + (void)passwordSz; + (void)hashType; + + if (der == NULL || password == NULL || info == NULL || info->keySz == 0 || + info->ivSz < PKCS5_SALT_SZ) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + key = (byte*)XMALLOC(WC_MAX_SYM_KEY_SIZE, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); + if (key == NULL) { + return MEMORY_E; + } +#endif /* WOLFSSL_SMALL_STACK */ + + (void)XMEMSET(key, 0, WC_MAX_SYM_KEY_SIZE); + +#ifndef NO_PWDBASED + if ((ret = wc_PBKDF1(key, password, passwordSz, info->iv, PKCS5_SALT_SZ, 1, + info->keySz, hashType)) != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); +#endif + return ret; + } +#endif + +#ifndef NO_DES3 + if (info->cipherType == WC_CIPHER_DES) + ret = wc_Des_CbcEncryptWithKey(der, der, derSz, key, info->iv); + if (info->cipherType == WC_CIPHER_DES3) + ret = wc_Des3_CbcEncryptWithKey(der, der, derSz, key, info->iv); +#endif /* NO_DES3 */ +#if !defined(NO_AES) && defined(HAVE_AES_CBC) + if (info->cipherType == WC_CIPHER_AES_CBC) + ret = wc_AesCbcEncryptWithKey(der, der, derSz, key, info->keySz, + info->iv); +#endif /* !NO_AES && HAVE_AES_CBC */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); +#endif + + return ret; +} + +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + + +#if !defined(NO_PWDBASED) && !defined(NO_ASN) + +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) +/* Decrypt/Encrypt input in place from parameters based on id + * + * returns a negative value on fail case + */ +int wc_CryptKey(const char* password, int passwordSz, byte* salt, + int saltSz, int iterations, int id, byte* input, + int length, int version, byte* cbcIv, int enc, int shaOid) +{ + int typeH; + int derivedLen = 0; + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* key; +#else + byte key[MAX_KEY_SIZE]; +#endif + + (void)input; + (void)length; + (void)enc; + + WOLFSSL_ENTER("wc_CryptKey"); + + switch (id) { + #ifndef NO_DES3 + #ifndef NO_MD5 + case PBE_MD5_DES: + typeH = WC_MD5; + derivedLen = 16; /* may need iv for v1.5 */ + break; + #endif + #ifndef NO_SHA + case PBE_SHA1_DES: + typeH = WC_SHA; + derivedLen = 16; /* may need iv for v1.5 */ + break; + + case PBE_SHA1_DES3: + switch(shaOid) { + case HMAC_SHA256_OID: + typeH = WC_SHA256; + derivedLen = 32; + break; + default: + typeH = WC_SHA; + derivedLen = 32; /* may need iv for v1.5 */ + break; + } + break; + #endif /* !NO_SHA */ + #endif /* !NO_DES3 */ + #if !defined(NO_SHA) && !defined(NO_RC4) + case PBE_SHA1_RC4_128: + typeH = WC_SHA; + derivedLen = 16; + break; + #endif + #if defined(WOLFSSL_AES_256) + case PBE_AES256_CBC: + switch(shaOid) { + case HMAC_SHA256_OID: + typeH = WC_SHA256; + derivedLen = 32; + break; + #ifndef NO_SHA + default: + typeH = WC_SHA; + derivedLen = 32; + break; + #endif + } + break; + #endif /* WOLFSSL_AES_256 && !NO_SHA */ + #if defined(WOLFSSL_AES_128) + case PBE_AES128_CBC: + switch(shaOid) { + case HMAC_SHA256_OID: + typeH = WC_SHA256; + derivedLen = 16; + break; + #ifndef NO_SHA + default: + typeH = WC_SHA; + derivedLen = 16; + break; + #endif + } + break; + #endif /* WOLFSSL_AES_128 && !NO_SHA */ + default: + WOLFSSL_MSG("Unknown/Unsupported encrypt/decrypt id"); + (void)shaOid; + return ALGO_ID_E; + } + +#ifdef WOLFSSL_SMALL_STACK + key = (byte*)XMALLOC(MAX_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) + return MEMORY_E; +#endif + + if (version == PKCS5v2) + ret = wc_PBKDF2(key, (byte*)password, passwordSz, + salt, saltSz, iterations, derivedLen, typeH); +#ifndef NO_SHA + else if (version == PKCS5) + ret = wc_PBKDF1(key, (byte*)password, passwordSz, + salt, saltSz, iterations, derivedLen, typeH); +#endif +#ifdef HAVE_PKCS12 + else if (version == PKCS12v1) { + int i, idx = 0; + byte unicodePasswd[MAX_UNICODE_SZ]; + + if ( (passwordSz * 2 + 2) > (int)sizeof(unicodePasswd)) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return UNICODE_SIZE_E; + } + + for (i = 0; i < passwordSz; i++) { + unicodePasswd[idx++] = 0x00; + unicodePasswd[idx++] = (byte)password[i]; + } + /* add trailing NULL */ + unicodePasswd[idx++] = 0x00; + unicodePasswd[idx++] = 0x00; + + ret = wc_PKCS12_PBKDF(key, unicodePasswd, idx, salt, saltSz, + iterations, derivedLen, typeH, 1); + if (id != PBE_SHA1_RC4_128) + ret += wc_PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt, saltSz, + iterations, 8, typeH, 2); + } +#endif /* HAVE_PKCS12 */ + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + WOLFSSL_MSG("Unknown/Unsupported PKCS version"); + return ALGO_ID_E; + } + + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + switch (id) { +#ifndef NO_DES3 + #if !defined(NO_SHA) || !defined(NO_MD5) + case PBE_MD5_DES: + case PBE_SHA1_DES: + { + Des des; + byte* desIv = key + 8; + + if (version == PKCS5v2 || version == PKCS12v1) + desIv = cbcIv; + + if (enc) { + ret = wc_Des_SetKey(&des, key, desIv, DES_ENCRYPTION); + } + else { + ret = wc_Des_SetKey(&des, key, desIv, DES_DECRYPTION); + } + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (enc) { + wc_Des_CbcEncrypt(&des, input, input, length); + } + else { + wc_Des_CbcDecrypt(&des, input, input, length); + } + break; + } + #endif /* !NO_SHA || !NO_MD5 */ + + #ifndef NO_SHA + case PBE_SHA1_DES3: + { + Des3 des; + byte* desIv = key + 24; + + if (version == PKCS5v2 || version == PKCS12v1) + desIv = cbcIv; + + ret = wc_Des3Init(&des, NULL, INVALID_DEVID); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + if (enc) { + ret = wc_Des3_SetKey(&des, key, desIv, DES_ENCRYPTION); + } + else { + ret = wc_Des3_SetKey(&des, key, desIv, DES_DECRYPTION); + } + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + if (enc) { + ret = wc_Des3_CbcEncrypt(&des, input, input, length); + } + else { + ret = wc_Des3_CbcDecrypt(&des, input, input, length); + } + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + break; + } + #endif /* !NO_SHA */ +#endif +#if !defined(NO_RC4) && !defined(NO_SHA) + case PBE_SHA1_RC4_128: + { + Arc4 dec; + + wc_Arc4SetKey(&dec, key, derivedLen); + wc_Arc4Process(&dec, input, input, length); + break; + } +#endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_256 + case PBE_AES256_CBC: + case PBE_AES128_CBC: + { + Aes aes; + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + if (enc) { + ret = wc_AesSetKey(&aes, key, derivedLen, cbcIv, + AES_ENCRYPTION); + } + else { + ret = wc_AesSetKey(&aes, key, derivedLen, cbcIv, + AES_DECRYPTION); + } + } + if (ret == 0) { + if (enc) + ret = wc_AesCbcEncrypt(&aes, input, input, length); + else + ret = wc_AesCbcDecrypt(&aes, input, input, length); + } + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + ForceZero(&aes, sizeof(Aes)); + break; + } + #endif /* WOLFSSL_AES_256 */ +#endif /* !NO_AES && HAVE_AES_CBC */ + + default: +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + WOLFSSL_MSG("Unknown/Unsupported encrypt/decryption algorithm"); + return ALGO_ID_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_PKCS8 || HAVE_PKCS12 */ +#endif /* !NO_PWDBASED */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_pkcs11.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_pkcs11.c new file mode 100644 index 000000000..cac0a0fcc --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_pkcs11.c @@ -0,0 +1,2546 @@ +/* wc_pkcs11.c + * + * Copyright (C) 2006-2020 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 3 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 HAVE_PKCS11 + +#include + +#include +#include +#include +#include +#ifndef NO_RSA + #include +#endif +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#define MAX_EC_PARAM_LEN 16 + +#if defined(NO_PKCS11_RSA) && !defined(NO_RSA) + #define NO_RSA +#endif +#if defined(NO_PKCS11_ECC) && defined(HAVE_ECC) + #undef HAVE_ECC +#endif +#if defined(NO_PKCS11_AES) && !defined(NO_AES) + #define NO_AES +#endif +#if defined(NO_PKCS11_AESGCM) && defined(HAVE_AESGCM) + #undef HAVE_AESGCM +#endif +#if defined(NO_PKCS11_AESCBC) && defined(HAVE_AES_CBC) + #undef HAVE_AES_CBC +#endif +#if defined(NO_PKCS11_HMAC) && !defined(NO_HMAC) + #define NO_HMAC +#endif +#if defined(NO_PKCS11_RNG) && !defined(WC_NO_RNG) + #define WC_NO_RNG +#endif + + +#if defined(HAVE_ECC) && !defined(NO_PKCS11_ECDH) +static CK_BBOOL ckFalse = CK_FALSE; +#endif +#if !defined(NO_RSA) || defined(HAVE_ECC) || (!defined(NO_AES) && \ + (defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || !defined(NO_HMAC) +static CK_BBOOL ckTrue = CK_TRUE; +#endif + +#ifndef NO_RSA +static CK_KEY_TYPE rsaKeyType = CKK_RSA; +#endif +#ifdef HAVE_ECC +static CK_KEY_TYPE ecKeyType = CKK_EC; +#endif +#if !defined(NO_RSA) || defined(HAVE_ECC) +static CK_OBJECT_CLASS pubKeyClass = CKO_PUBLIC_KEY; +static CK_OBJECT_CLASS privKeyClass = CKO_PRIVATE_KEY; +#endif +#if (!defined(NO_AES) && (defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || \ + !defined(NO_HMAC) || (defined(HAVE_ECC) && !defined(NO_PKCS11_ECDH)) +static CK_OBJECT_CLASS secretKeyClass = CKO_SECRET_KEY; +#endif + +/** + * Load library, get function list and initialize PKCS#11. + * + * @param dev [in] Device object. + * @param library [in] Library name including path. + * @return BAD_FUNC_ARG when dev or library are NULL pointers. + * BAD_PATH_ERROR when dynamic library cannot be opened. + * WC_INIT_E when the initialization PKCS#11 fails. + * WC_HW_E when unable to get PKCS#11 function list. + * 0 on success. + */ +int wc_Pkcs11_Initialize(Pkcs11Dev* dev, const char* library, void* heap) +{ + int ret = 0; + void* func; + CK_C_INITIALIZE_ARGS args; + + if (dev == NULL || library == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + dev->heap = heap; + dev->dlHandle = dlopen(library, RTLD_NOW | RTLD_LOCAL); + if (dev->dlHandle == NULL) { + WOLFSSL_MSG(dlerror()); + ret = BAD_PATH_ERROR; + } + } + + if (ret == 0) { + dev->func = NULL; + func = dlsym(dev->dlHandle, "C_GetFunctionList"); + if (func == NULL) + ret = WC_HW_E; + } + if (ret == 0) { + if (((CK_C_GetFunctionList)func)(&dev->func) != CKR_OK) + ret = WC_HW_E; + } + + if (ret == 0) { + XMEMSET(&args, 0x00, sizeof(args)); + args.flags = CKF_OS_LOCKING_OK; + if (dev->func->C_Initialize(&args) != CKR_OK) + ret = WC_INIT_E; + } + + if (ret != 0) + wc_Pkcs11_Finalize(dev); + + return ret; +} + +/** + * Close the Pkcs#11 library. + * + * @param dev [in] Device object. + */ +void wc_Pkcs11_Finalize(Pkcs11Dev* dev) +{ + if (dev != NULL && dev->dlHandle != NULL) { + if (dev->func != NULL) { + dev->func->C_Finalize(NULL); + dev->func = NULL; + } + dlclose(dev->dlHandle); + dev->dlHandle = NULL; + } +} + +/** + * Set up a token for use. + * + * @param token [in] Token object. + * @param dev [in] PKCS#11 device object. + * @param slotId [in] Slot number of the token.
+ * Passing -1 uses the first available slot. + * @param tokenName [in] Name of token to initialize. + * @param userPin [in] PIN to use to login as user. + * @param userPinSz [in] Number of bytes in PIN. + * @return BAD_FUNC_ARG when token, dev and/or tokenName is NULL. + * WC_INIT_E when initializing token fails. + * WC_HW_E when another PKCS#11 library call fails. + * -1 when no slot available. + * 0 on success. + */ +int wc_Pkcs11Token_Init(Pkcs11Token* token, Pkcs11Dev* dev, int slotId, + const char* tokenName, const unsigned char* userPin, int userPinSz) +{ + int ret = 0; + CK_RV rv; + CK_SLOT_ID* slot = NULL; + CK_ULONG slotCnt = 0; + + if (token == NULL || dev == NULL || tokenName == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + if (slotId < 0) { + /* Use first available slot with a token. */ + rv = dev->func->C_GetSlotList(CK_TRUE, NULL, &slotCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + if (ret == 0) { + slot = (CK_SLOT_ID*)XMALLOC(slotCnt * sizeof(*slot), dev->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (slot == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + rv = dev->func->C_GetSlotList(CK_TRUE, slot, &slotCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + if (slotCnt > 0) + slotId = (int)slot[0]; + else + ret = WC_HW_E; + } + } + } + if (ret == 0) { + token->func = dev->func; + token->slotId = (CK_SLOT_ID)slotId; + token->handle = NULL_PTR; + token->userPin = (CK_UTF8CHAR_PTR)userPin; + token->userPinSz = (CK_ULONG)userPinSz; + } + + if (slot != NULL) + XFREE(slot, dev->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +/** + * Finalize token. + * Closes all sessions on token. + * + * @param token [in] Token object. + */ +void wc_Pkcs11Token_Final(Pkcs11Token* token) +{ + if (token != NULL && token->func != NULL) { + token->func->C_CloseAllSessions(token->slotId); + token->handle = NULL_PTR; + ForceZero(token->userPin, (word32)token->userPinSz); + } +} + +/** + * Open a session on a token. + * + * @param token [in] Token object. + * @param session [in] Session object. + * @param readWrite [in] Boolean indicating to open session for Read/Write. + * @return BAD_FUNC_ARG when token or session is NULL. + * WC_HW_E when opening the session fails. + * 0 on success. + */ +static int Pkcs11OpenSession(Pkcs11Token* token, Pkcs11Session* session, + int readWrite) +{ + int ret = 0; + CK_RV rv; + + if (token == NULL || session == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + if (token->handle != NULL_PTR) + session->handle = token->handle; + else { + /* Create a new session. */ + CK_FLAGS flags = CKF_SERIAL_SESSION; + + if (readWrite) + flags |= CKF_RW_SESSION; + + rv = token->func->C_OpenSession(token->slotId, flags, + (CK_VOID_PTR)NULL, (CK_NOTIFY)NULL, + &session->handle); + if (rv != CKR_OK) + ret = WC_HW_E; + if (ret == 0 && token->userPin != NULL) { + rv = token->func->C_Login(session->handle, CKU_USER, + token->userPin, token->userPinSz); + if (rv != CKR_OK) + ret = WC_HW_E; + } + } + } + if (ret == 0) { + session->func = token->func; + session->slotId = token->slotId; + } + + return ret; +} + +/** + * Close a session on a token. + * Won't close a session created externally. + * + * @param token [in] Token object. + * @param session [in] Session object. + */ +static void Pkcs11CloseSession(Pkcs11Token* token, Pkcs11Session* session) +{ + if (token != NULL && session != NULL && token->handle != session->handle) { + if (token->userPin != NULL) + session->func->C_Logout(session->handle); + session->func->C_CloseSession(session->handle); + } +} + +/** + * Open a session on the token to be used for all operations. + * + * @param token [in] Token object. + * @param readWrite [in] Boolean indicating to open session for Read/Write. + * @return BAD_FUNC_ARG when token is NULL. + * WC_HW_E when opening the session fails. + * 0 on success. + */ +int wc_Pkcs11Token_Open(Pkcs11Token* token, int readWrite) +{ + int ret = 0; + Pkcs11Session session; + + if (token == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + ret = Pkcs11OpenSession(token, &session, readWrite); + token->handle = session.handle; + } + + return ret; +} + +/** + * Close the token's session. + * All object, like keys, will be destroyed. + * + * @param token [in] Token object. + */ +void wc_Pkcs11Token_Close(Pkcs11Token* token) +{ + Pkcs11Session session; + + if (token != NULL) { + session.func = token->func; + session.handle = token->handle; + token->handle = NULL_PTR; + Pkcs11CloseSession(token, &session); + } +} + + +#if (!defined(NO_AES) && (defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || \ + !defined(NO_HMAC) +static int Pkcs11CreateSecretKey(CK_OBJECT_HANDLE* key, Pkcs11Session* session, + CK_KEY_TYPE keyType, unsigned char* data, + int len, unsigned char* id, int idLen) +{ + int ret = 0; + CK_RV rv; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_VALUE, NULL, 0 }, + { CKA_ID, id, (CK_ULONG)idLen } + }; + int keyTmplCnt = 4; + + WOLFSSL_MSG("PKCS#11: Create Secret Key"); + + /* Set the modulus and public exponent data. */ + keyTemplate[3].pValue = data; + keyTemplate[3].ulValueLen = (CK_ULONG)len; + + if (idLen > 0) + keyTmplCnt++; + + /* Create an object containing key data for device to use. */ + rv = session->func->C_CreateObject(session->handle, keyTemplate, keyTmplCnt, + key); + if (rv != CKR_OK) + ret = WC_HW_E; + + return ret; +} +#endif + +#ifndef NO_RSA +/** + * Create a PKCS#11 object containing the RSA private key data. + * + * @param privateKey [out] Henadle to private key object. + * @param session [in] Session object. + * @param rsaKey [in] RSA key with private key data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11CreateRsaPrivateKey(CK_OBJECT_HANDLE* privateKey, + Pkcs11Session* session, + RsaKey* rsaKey) +{ + int ret = 0; + CK_RV rv; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &privKeyClass, sizeof(privKeyClass) }, + { CKA_KEY_TYPE, &rsaKeyType, sizeof(rsaKeyType) }, + { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_MODULUS, NULL, 0 }, + { CKA_PRIVATE_EXPONENT, NULL, 0 }, + { CKA_PRIME_1, NULL, 0 }, + { CKA_PRIME_2, NULL, 0 }, + { CKA_EXPONENT_1, NULL, 0 }, + { CKA_EXPONENT_2, NULL, 0 }, + { CKA_COEFFICIENT, NULL, 0 }, + { CKA_PUBLIC_EXPONENT, NULL, 0 } + }; + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); + + /* Set the modulus and private key data. */ + keyTemplate[ 3].pValue = rsaKey->n.raw.buf; + keyTemplate[ 3].ulValueLen = rsaKey->n.raw.len; + keyTemplate[ 4].pValue = rsaKey->d.raw.buf; + keyTemplate[ 4].ulValueLen = rsaKey->d.raw.len; + keyTemplate[ 5].pValue = rsaKey->p.raw.buf; + keyTemplate[ 5].ulValueLen = rsaKey->p.raw.len; + keyTemplate[ 6].pValue = rsaKey->q.raw.buf; + keyTemplate[ 6].ulValueLen = rsaKey->q.raw.len; + keyTemplate[ 7].pValue = rsaKey->dP.raw.buf; + keyTemplate[ 7].ulValueLen = rsaKey->dP.raw.len; + keyTemplate[ 8].pValue = rsaKey->dQ.raw.buf; + keyTemplate[ 8].ulValueLen = rsaKey->dQ.raw.len; + keyTemplate[ 9].pValue = rsaKey->u.raw.buf; + keyTemplate[ 9].ulValueLen = rsaKey->u.raw.len; + keyTemplate[10].pValue = rsaKey->e.raw.buf; + keyTemplate[10].ulValueLen = rsaKey->e.raw.len; + + rv = session->func->C_CreateObject(session->handle, keyTemplate, keyTmplCnt, + privateKey); + if (rv != CKR_OK) + ret = WC_HW_E; + + return ret; +} +#endif + +#ifdef HAVE_ECC +/** + * Set the ECC parameters into the template. + * + * @param key [in] ECC key. + * @param tmpl [in] PKCS#11 template. + * @param idx [in] Index of template to put parameters into. + * @return NOT_COMPILE_IN when the EC parameters are not known. + * 0 on success. + */ +static int Pkcs11EccSetParams(ecc_key* key, CK_ATTRIBUTE* tmpl, int idx) +{ + int ret = 0; + + if (key->dp != NULL && key->dp->oid != NULL) { + unsigned char* derParams = tmpl[idx].pValue; + /* ASN.1 encoding: OBJ + ecc parameters OID */ + tmpl[idx].ulValueLen = key->dp->oidSz + 2; + derParams[0] = ASN_OBJECT_ID; + derParams[1] = key->dp->oidSz; + XMEMCPY(derParams + 2, key->dp->oid, key->dp->oidSz); + } + else + ret = NOT_COMPILED_IN; + + return ret; +} + +/** + * Create a PKCS#11 object containing the ECC private key data. + * + * @param privateKey [out] Henadle to private key object. + * @param session [in] Session object. + * @param private_key [in] ECC private key. + * @param operation [in] Cryptographic operation key is to be used for. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11CreateEccPrivateKey(CK_OBJECT_HANDLE* privateKey, + Pkcs11Session* session, + ecc_key* private_key, + CK_ATTRIBUTE_TYPE operation) +{ + int ret = 0; + CK_RV rv; + CK_UTF8CHAR params[MAX_EC_PARAM_LEN]; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &privKeyClass, sizeof(privKeyClass) }, + { CKA_KEY_TYPE, &ecKeyType, sizeof(ecKeyType) }, + { operation, &ckTrue, sizeof(ckTrue) }, + { CKA_EC_PARAMS, params, 0 }, + { CKA_VALUE, NULL, 0 } + }; + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); + + ret = Pkcs11EccSetParams(private_key, keyTemplate, 3); + if (ret == 0) { + keyTemplate[4].pValue = private_key->k.raw.buf; + keyTemplate[4].ulValueLen = private_key->k.raw.len; + + rv = session->func->C_CreateObject(session->handle, keyTemplate, + keyTmplCnt, privateKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + return ret; +} +#endif + +#if !defined(NO_RSA) || defined(HAVE_ECC) || (!defined(NO_AES) && \ + (defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || !defined(NO_HMAC) +/** + * Check if mechanism is available in session on token. + * + * @param session [in] Session object. + * @param mech [in] Mechanism to look for. + * @return NOT_COMPILED_IN when mechanism not available. + * 0 when mechanism is available. + */ +static int Pkcs11MechAvail(Pkcs11Session* session, CK_MECHANISM_TYPE mech) +{ + int ret = 0; + CK_RV rv; + CK_MECHANISM_INFO mechInfo; + + rv = session->func->C_GetMechanismInfo(session->slotId, mech, &mechInfo); + if (rv != CKR_OK) + ret = NOT_COMPILED_IN; + + return ret; +} +#endif + +#ifndef NO_HMAC +/** + * Return the mechanism type and key type for the digest type when using HMAC. + * + * @param macType [in] Digest type - e.g. WC_SHA256. + * @param mechType [in] Mechanism type - e.g. CKM_SHA256_HMAC. + * @param keyType [in] Key type - e.g. CKK_SHA256_HMAC. + * @return NOT_COMPILED_IN if the digest algorithm isn't recognised. + * 0 otherwise. + */ +static int Pkcs11HmacTypes(int macType, int* mechType, int* keyType) +{ + int ret = 0; + + switch (macType) + { + #ifndef NO_MD5 + case WC_MD5: + *mechType = CKM_MD5_HMAC; + *keyType = CKK_MD5_HMAC; + break; + #endif + #ifndef NO_SHA + case WC_SHA: + *mechType = CKM_SHA_1_HMAC; + *keyType = CKK_SHA_1_HMAC; + break; + #endif + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + *mechType = CKM_SHA224_HMAC; + *keyType = CKK_SHA224_HMAC; + break; + #endif + #ifndef NO_SHA256 + case WC_SHA256: + *mechType = CKM_SHA256_HMAC; + *keyType = CKK_SHA256_HMAC; + break; + #endif + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + *mechType = CKM_SHA384_HMAC; + *keyType = CKK_SHA384_HMAC; + break; + #endif + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + *mechType = CKM_SHA512_HMAC; + *keyType = CKK_SHA512_HMAC; + break; + #endif + default: + ret = NOT_COMPILED_IN; + break; + } + + return ret; +} +#endif + +/** + * Store the private key on the token in the session. + * + * @param token [in] Token to store private key on. + * @param type [in] Key type. + * @param clear [in] Clear out the private data from software key. + * @param key [in] Key type specific object. + * @return NOT_COMPILED_IN when mechanism not available. + * 0 on success. + */ +int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key) +{ + int ret = 0; + Pkcs11Session session; + CK_OBJECT_HANDLE privKey = NULL_PTR; + + ret = Pkcs11OpenSession(token, &session, 1); + if (ret == 0) { + switch (type) { + #if !defined(NO_AES) && defined(HAVE_AESGCM) + case PKCS11_KEY_TYPE_AES_GCM: { + Aes* aes = (Aes*)key; + + ret = Pkcs11MechAvail(&session, CKM_AES_GCM); + if (ret == 0) { + ret = Pkcs11CreateSecretKey(&privKey, &session, CKK_AES, + (unsigned char*)aes->devKey, + aes->keylen, + (unsigned char*)aes->id, + aes->idLen); + } + if (ret == 0 && clear) + ForceZero(aes->devKey, aes->keylen); + break; + } + #endif + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + case PKCS11_KEY_TYPE_AES_CBC: { + Aes* aes = (Aes*)key; + + ret = Pkcs11MechAvail(&session, CKM_AES_CBC); + if (ret == 0) { + ret = Pkcs11CreateSecretKey(&privKey, &session, CKK_AES, + (unsigned char*)aes->devKey, + aes->keylen, + (unsigned char*)aes->id, + aes->idLen); + } + if (ret == 0 && clear) + ForceZero(aes->devKey, aes->keylen); + break; + } + #endif + #ifndef NO_HMAC + case PKCS11_KEY_TYPE_HMAC: { + Hmac* hmac = (Hmac*)key; + int mechType; + int keyType; + + ret = Pkcs11HmacTypes(hmac->macType, &mechType, &keyType); + if (ret == NOT_COMPILED_IN) + break; + + if (ret == 0) + ret = Pkcs11MechAvail(&session, mechType); + if (ret == 0) { + ret = Pkcs11CreateSecretKey(&privKey, &session, keyType, + (unsigned char*)hmac->keyRaw, + hmac->keyLen, + (unsigned char*)hmac->id, + hmac->idLen); + if (ret == WC_HW_E) { + ret = Pkcs11CreateSecretKey(&privKey, &session, + CKK_GENERIC_SECRET, + (unsigned char*)hmac->keyRaw, + hmac->keyLen, + (unsigned char*)hmac->id, + hmac->idLen); + } + } + break; + } + #endif + #ifndef NO_RSA + case PKCS11_KEY_TYPE_RSA: { + RsaKey* rsaKey = (RsaKey*)key; + + ret = Pkcs11MechAvail(&session, CKM_RSA_X_509); + if (ret == 0) + ret = Pkcs11CreateRsaPrivateKey(&privKey, &session, rsaKey); + if (ret == 0 && clear) { + mp_forcezero(&rsaKey->u); + mp_forcezero(&rsaKey->dQ); + mp_forcezero(&rsaKey->dP); + mp_forcezero(&rsaKey->q); + mp_forcezero(&rsaKey->p); + mp_forcezero(&rsaKey->d); + } + break; + } + #endif + #ifdef HAVE_ECC + case PKCS11_KEY_TYPE_EC: { + ecc_key* eccKey = (ecc_key*)key; + int ret2 = NOT_COMPILED_IN; + + #ifndef NO_PKCS11_ECDH + /* Try ECDH mechanism first. */ + ret = Pkcs11MechAvail(&session, CKM_ECDH1_DERIVE); + if (ret == 0) { + ret = Pkcs11CreateEccPrivateKey(&privKey, &session, eccKey, + CKA_DERIVE); + } + #endif + if (ret == 0 || ret == NOT_COMPILED_IN) { + /* Try ECDSA mechanism next. */ + ret2 = Pkcs11MechAvail(&session, CKM_ECDSA); + if (ret2 == 0) { + ret2 = Pkcs11CreateEccPrivateKey(&privKey, &session, + eccKey, CKA_SIGN); + } + /* OK for this to fail if set for ECDH. */ + if (ret == NOT_COMPILED_IN) + ret = ret2; + } + if (ret == 0 && clear) + mp_forcezero(&eccKey->k); + break; + } + #endif + default: + ret = NOT_COMPILED_IN; + break; + } + + Pkcs11CloseSession(token, &session); + } + + (void)privKey; + (void)clear; + (void)key; + + return ret; +} + +#if !defined(NO_RSA) || defined(HAVE_ECC) || (!defined(NO_AES) && \ + (defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || !defined(NO_HMAC) +/** + * Find the PKCS#11 object containing the RSA public or private key data with + * the modulus specified. + * + * @param key [out] Henadle to key object. + * @param keyClass [in] Public or private key class. + * @param keyType [in] Type of key. + * @param session [in] Session object. + * @param id [in] Identifier set against a key. + * @param idLen [in] Length of identifier. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11FindKeyById(CK_OBJECT_HANDLE* key, CK_OBJECT_CLASS keyClass, + CK_KEY_TYPE keyType, Pkcs11Session* session, + byte* id, int idLen) +{ + int ret = 0; + CK_RV rv; + CK_ULONG count; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &keyClass, sizeof(keyClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_ID, id, (CK_ULONG)idLen } + }; + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); + + WOLFSSL_MSG("PKCS#11: Find Key By Id"); + + rv = session->func->C_FindObjectsInit(session->handle, keyTemplate, + keyTmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + if (ret == 0) { + rv = session->func->C_FindObjects(session->handle, key, 1, &count); + if (rv != CKR_OK) + ret = WC_HW_E; + rv = session->func->C_FindObjectsFinal(session->handle); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0 && count == 0) + ret = WC_HW_E; + + return ret; +} +#endif + +#ifndef NO_RSA +/** + * Find the PKCS#11 object containing the RSA public or private key data with + * the modulus specified. + * + * @param key [out] Henadle to key object. + * @param keyClass [in] Public or private key class. + * @param session [in] Session object. + * @param rsaKey [in] RSA key with modulus to search on. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11FindRsaKey(CK_OBJECT_HANDLE* key, CK_OBJECT_CLASS keyClass, + Pkcs11Session* session, RsaKey* rsaKey) +{ + int ret = 0; + CK_RV rv; + CK_ULONG count; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &keyClass, sizeof(keyClass) }, + { CKA_KEY_TYPE, &rsaKeyType, sizeof(rsaKeyType) }, + { CKA_MODULUS, NULL, 0 }, + }; + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); + + /* Set the modulus. */ + keyTemplate[2].pValue = rsaKey->n.raw.buf; + keyTemplate[2].ulValueLen = rsaKey->n.raw.len; + + rv = session->func->C_FindObjectsInit(session->handle, keyTemplate, + keyTmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + if (ret == 0) { + rv = session->func->C_FindObjects(session->handle, key, 1, &count); + if (rv != CKR_OK) + ret = WC_HW_E; + rv = session->func->C_FindObjectsFinal(session->handle); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + return ret; +} + +/** + * Exponentiate the input with the public part of the RSA key. + * Used in public encrypt and decrypt. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11RsaPublic(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + CK_MECHANISM mech; + CK_ULONG outLen; + CK_OBJECT_HANDLE publicKey = NULL_PTR; + int sessionKey = 0; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &pubKeyClass, sizeof(pubKeyClass) }, + { CKA_KEY_TYPE, &rsaKeyType, sizeof(rsaKeyType) }, + { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_MODULUS, NULL, 0 }, + { CKA_PUBLIC_EXPONENT, NULL, 0 } + }; + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); + + WOLFSSL_MSG("PKCS#11: RSA Public Key Operation"); + + if (info->pk.rsa.outLen == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if ((sessionKey = !mp_iszero(&info->pk.rsa.key->e))) { + /* Set the modulus and public exponent data. */ + keyTemplate[3].pValue = info->pk.rsa.key->n.raw.buf; + keyTemplate[3].ulValueLen = info->pk.rsa.key->n.raw.len; + keyTemplate[4].pValue = info->pk.rsa.key->e.raw.buf; + keyTemplate[4].ulValueLen = info->pk.rsa.key->e.raw.len; + + /* Create an object containing public key data for device to use. */ + rv = session->func->C_CreateObject(session->handle, keyTemplate, + keyTmplCnt, &publicKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + else { + ret = Pkcs11FindKeyById(&publicKey, CKO_PUBLIC_KEY, CKK_RSA, + session, info->pk.rsa.key->id, + info->pk.rsa.key->idLen); + } + } + + if (ret == 0) { + /* Raw RSA encrypt/decrypt operation. */ + mech.mechanism = CKM_RSA_X_509; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_EncryptInit(session->handle, &mech, publicKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = (CK_ULONG)*info->pk.rsa.outLen; + rv = session->func->C_Encrypt(session->handle, + (CK_BYTE_PTR)info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) + *info->pk.rsa.outLen = (word32)outLen; + + if (sessionKey) + session->func->C_DestroyObject(session->handle, publicKey); + + return ret; +} + +/** + * Exponentiate the input with the private part of the RSA key. + * Used in private encrypt and decrypt. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11RsaPrivate(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + CK_MECHANISM mech; + CK_ULONG outLen; + CK_OBJECT_HANDLE privateKey = NULL_PTR; + int sessionKey = 0; + + WOLFSSL_MSG("PKCS#11: RSA Private Key Operation"); + + if (info->pk.rsa.outLen == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if ((sessionKey = !mp_iszero(&info->pk.rsa.key->d))) { + ret = Pkcs11CreateRsaPrivateKey(&privateKey, session, + info->pk.rsa.key); + } + else if (info->pk.rsa.key->idLen > 0) { + ret = Pkcs11FindKeyById(&privateKey, CKO_PRIVATE_KEY, CKK_RSA, + session, info->pk.rsa.key->id, + info->pk.rsa.key->idLen); + } + else { + ret = Pkcs11FindRsaKey(&privateKey, CKO_PRIVATE_KEY, session, + info->pk.rsa.key); + } + } + + if (ret == 0) { + /* Raw RSA encrypt/decrypt operation. */ + mech.mechanism = CKM_RSA_X_509; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_DecryptInit(session->handle, &mech, privateKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = (CK_ULONG)*info->pk.rsa.outLen; + rv = session->func->C_Decrypt(session->handle, + (CK_BYTE_PTR)info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) + *info->pk.rsa.outLen = (word32)outLen; + + if (sessionKey) + session->func->C_DestroyObject(session->handle, privateKey); + + return ret; +} + +/** + * Perform an RSA operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11Rsa(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + CK_MECHANISM_INFO mechInfo; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_RSA_X_509, + &mechInfo); + if (rv != CKR_OK) + ret = NOT_COMPILED_IN; + + if (ret == 0) { + if (info->pk.rsa.type == RSA_PUBLIC_ENCRYPT || + info->pk.rsa.type == RSA_PUBLIC_DECRYPT) { + if ((mechInfo.flags & CKF_ENCRYPT) == 0) + ret = NOT_COMPILED_IN; + else + ret = Pkcs11RsaPublic(session, info); + } + else if (info->pk.rsa.type == RSA_PRIVATE_ENCRYPT || + info->pk.rsa.type == RSA_PRIVATE_DECRYPT) { + if ((mechInfo.flags & CKF_DECRYPT) == 0) + ret = NOT_COMPILED_IN; + else + ret = Pkcs11RsaPrivate(session, info); + } + else + ret = NOT_COMPILED_IN; + } + + return ret; +} + +#ifdef WOLFSSL_KEY_GEN +/** + * Get the RSA public key data from the PKCS#11 object. + * + * @param key [in] RSA key to put the data into. + * @param session [in] Session object. + * @param pubkey [in] Public key object. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11GetRsaPublicKey(RsaKey* key, Pkcs11Session* session, + CK_OBJECT_HANDLE pubKey) +{ + int ret = 0; + unsigned char* mod = NULL; + unsigned char* exp = NULL; + int modSz, expSz; + CK_ATTRIBUTE tmpl[] = { + { CKA_MODULUS, NULL_PTR, 0 }, + { CKA_PUBLIC_EXPONENT, NULL_PTR, 0 } + }; + CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); + CK_RV rv; + + rv = session->func->C_GetAttributeValue(session->handle, pubKey, tmpl, + tmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + + if (ret == 0) { + modSz = tmpl[0].ulValueLen; + expSz = tmpl[1].ulValueLen; + mod = (unsigned char*)XMALLOC(modSz, key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (mod == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + exp = (unsigned char*)XMALLOC(expSz, key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (exp == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + tmpl[0].pValue = mod; + tmpl[1].pValue = exp; + + rv = session->func->C_GetAttributeValue(session->handle, pubKey, + tmpl, tmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) + ret = wc_RsaPublicKeyDecodeRaw(mod, modSz, exp, expSz, key); + + if (exp != NULL) + XFREE(exp, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mod != NULL) + XFREE(mod, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +/** + * Perform an RSA key generation operation. + * The private key data stays on the device. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11RsaKeyGen(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + RsaKey* key = info->pk.rsakg.key; + CK_RV rv; + CK_ULONG bits = info->pk.rsakg.size; + CK_OBJECT_HANDLE pubKey = NULL_PTR, privKey = NULL_PTR; + CK_MECHANISM mech; + static CK_BYTE pub_exp[] = { 0x01, 0x00, 0x01, 0x00 }; + CK_ATTRIBUTE pubKeyTmpl[] = { + { CKA_MODULUS_BITS, &bits, sizeof(bits) }, + { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + { CKA_PUBLIC_EXPONENT, &pub_exp, sizeof(pub_exp) } + }; + CK_ULONG pubTmplCnt = sizeof(pubKeyTmpl)/sizeof(*pubKeyTmpl); + CK_ATTRIBUTE privKeyTmpl[] = { + {CKA_DECRYPT, &ckTrue, sizeof(ckTrue) }, + {CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + {CKA_ID, NULL, 0 } + }; + int privTmplCnt = 2; + int i; + + ret = Pkcs11MechAvail(session, CKM_RSA_PKCS_KEY_PAIR_GEN); + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: RSA Key Generation Operation"); + + /* Most commonly used public exponent value (array initialized). */ + if (info->pk.rsakg.e != WC_RSA_EXPONENT) { + for (i = 0; i < (int)sizeof(pub_exp); i++) + pub_exp[i] = (info->pk.rsakg.e >> (8 * i)) & 0xff; + } + for (i = (int)sizeof(pub_exp) - 1; pub_exp[i] == 0; i--) { + } + pubKeyTmpl[3].ulValueLen = i + 1; + + if (key->idLen != 0) { + privKeyTmpl[privTmplCnt].pValue = key->id; + privKeyTmpl[privTmplCnt].ulValueLen = key->idLen; + privTmplCnt++; + } + + mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_GenerateKeyPair(session->handle, &mech, + pubKeyTmpl, pubTmplCnt, + privKeyTmpl, privTmplCnt, + &pubKey, &privKey); + if (rv != CKR_OK) + ret = -1; + } + + if (ret == 0) + ret = Pkcs11GetRsaPublicKey(key, session, pubKey); + + if (pubKey != NULL_PTR) + ret = session->func->C_DestroyObject(session->handle, pubKey); + if (ret != 0 && privKey != NULL_PTR) + ret = session->func->C_DestroyObject(session->handle, privKey); + + return ret; +} +#endif /* WOLFSSL_KEY_GEN */ +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +/** + * Find the PKCS#11 object containing the ECC public or private key data with + * the modulus specified. + * + * @param key [out] Henadle to key object. + * @param keyClass [in] Public or private key class. + * @param session [in] Session object. + * @param eccKey [in] ECC key with parameters. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11FindEccKey(CK_OBJECT_HANDLE* key, CK_OBJECT_CLASS keyClass, + Pkcs11Session* session, ecc_key* eccKey) +{ + int ret = 0; + int i; + unsigned char* ecPoint = NULL; + word32 len = 0; + CK_RV rv; + CK_ULONG count; + CK_UTF8CHAR params[MAX_EC_PARAM_LEN]; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &keyClass, sizeof(keyClass) }, + { CKA_KEY_TYPE, &ecKeyType, sizeof(ecKeyType) }, + { CKA_EC_PARAMS, params, 0 }, + { CKA_EC_POINT, NULL, 0 }, + }; + CK_ULONG attrCnt = 3; + + ret = Pkcs11EccSetParams(eccKey, keyTemplate, 2); + if (ret == 0 && keyClass == CKO_PUBLIC_KEY) { + /* ASN1 encoded: OCT + uncompressed point */ + len = 3 + 1 + 2 * eccKey->dp->size; + ecPoint = (unsigned char*)XMALLOC(len, eccKey->heap, DYNAMIC_TYPE_ECC); + if (ecPoint == NULL) + ret = MEMORY_E; + } + if (ret == 0 && keyClass == CKO_PUBLIC_KEY) { + len -= 3; + i = 0; + ecPoint[i++] = ASN_OCTET_STRING; + if (len >= ASN_LONG_LENGTH) + ecPoint[i++] = (ASN_LONG_LENGTH | 1); + ecPoint[i++] = len; + ret = wc_ecc_export_x963(eccKey, ecPoint + i, &len); + } + if (ret == 0 && keyClass == CKO_PUBLIC_KEY) { + keyTemplate[3].pValue = ecPoint; + keyTemplate[3].ulValueLen = len + i; + attrCnt++; + } + if (ret == 0) { + rv = session->func->C_FindObjectsInit(session->handle, keyTemplate, + attrCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + rv = session->func->C_FindObjects(session->handle, key, 1, &count); + if (rv != CKR_OK) + ret = WC_HW_E; + rv = session->func->C_FindObjectsFinal(session->handle); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (ecPoint != NULL) + XFREE(ecPoint, eccKey->heap, DYNAMIC_TYPE_ECC); + + return ret; +} + +/** + * Create a PKCS#11 object containing the ECC public key data. + * Encode the public key as an OCTET_STRING of the encoded point. + * + * @param publicKey [out] Henadle to public key object. + * @param session [in] Session object. + * @param public_key [in] ECC public key. + * @param operation [in] Cryptographic operation key is to be used for. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11CreateEccPublicKey(CK_OBJECT_HANDLE* publicKey, + Pkcs11Session* session, + ecc_key* public_key, + CK_ATTRIBUTE_TYPE operation) +{ + int ret = 0; + int i; + unsigned char* ecPoint = NULL; + word32 len; + CK_RV rv; + CK_UTF8CHAR params[MAX_EC_PARAM_LEN]; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &pubKeyClass, sizeof(pubKeyClass) }, + { CKA_KEY_TYPE, &ecKeyType, sizeof(ecKeyType) }, + { operation, &ckTrue, sizeof(ckTrue) }, + { CKA_EC_PARAMS, params, 0 }, + { CKA_EC_POINT, NULL, 0 } + }; + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); + + ret = Pkcs11EccSetParams(public_key, keyTemplate, 3); + if (ret == 0) { + /* ASN1 encoded: OCT + uncompressed point */ + len = 3 + 1 + 2 * public_key->dp->size; + ecPoint = (unsigned char*)XMALLOC(len, public_key->heap, + DYNAMIC_TYPE_ECC); + if (ecPoint == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + len -= 3; + i = 0; + ecPoint[i++] = ASN_OCTET_STRING; + if (len >= ASN_LONG_LENGTH) + ecPoint[i++] = ASN_LONG_LENGTH | 1; + ecPoint[i++] = len; + ret = wc_ecc_export_x963(public_key, ecPoint + i, &len); + } + if (ret == 0) { + keyTemplate[4].pValue = ecPoint; + keyTemplate[4].ulValueLen = len + i; + + rv = session->func->C_CreateObject(session->handle, keyTemplate, + keyTmplCnt, publicKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (ecPoint != NULL) + XFREE(ecPoint, public_key->heap, DYNAMIC_TYPE_ECC); + + return ret; +} + +#ifndef NO_PKCS11_EC_KEYGEN +/** + * Gets the public key data from the PKCS#11 object and puts into the ECC key. + * + * @param key [in] ECC public key. + * @param session [in] Session object. + * @param pubKey [in] ECC public key PKCS#11 object. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11GetEccPublicKey(ecc_key* key, Pkcs11Session* session, + CK_OBJECT_HANDLE pubKey) +{ + int ret = 0; + word32 i = 0; + int curveIdx; + unsigned char* point = NULL; + int pointSz; + byte tag; + CK_RV rv; + CK_ATTRIBUTE tmpl[] = { + { CKA_EC_POINT, NULL_PTR, 0 }, + }; + CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); + + rv = session->func->C_GetAttributeValue(session->handle, pubKey, tmpl, + tmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + + if (ret == 0) { + pointSz = (int)tmpl[0].ulValueLen; + point = (unsigned char*)XMALLOC(pointSz, key->heap, DYNAMIC_TYPE_ECC); + if (point == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + tmpl[0].pValue = point; + + rv = session->func->C_GetAttributeValue(session->handle, pubKey, + tmpl, tmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + /* Make sure the data is big enough for ASN.1: OCT + uncompressed point */ + if (ret == 0 && pointSz < key->dp->size * 2 + 1 + 2) + ret = ASN_PARSE_E; + /* Step over the OCTET_STRING wrapper. */ + if (ret == 0 && GetASNTag(point, &i, &tag, pointSz) != 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + if (ret == 0 && point[i] >= ASN_LONG_LENGTH) { + if (point[i++] != (ASN_LONG_LENGTH | 1)) + ret = ASN_PARSE_E; + else if (pointSz < key->dp->size * 2 + 1 + 3) + ret = ASN_PARSE_E; + } + if (ret == 0 && point[i++] != key->dp->size * 2 + 1) + ret = ASN_PARSE_E; + + if (ret == 0) { + curveIdx = wc_ecc_get_curve_idx(key->dp->id); + ret = wc_ecc_import_point_der(point + i, pointSz - i, curveIdx, + &key->pubkey); + } + + if (point != NULL) + XFREE(point, key->heap, DYNAMIC_TYPE_ECC); + + return ret; +} + +/** + * Perform an ECC key generation operation. + * The private key data stays on the device. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11EcKeyGen(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + ecc_key* key = info->pk.eckg.key; + CK_RV rv; + CK_OBJECT_HANDLE pubKey = NULL_PTR, privKey = NULL_PTR; + CK_MECHANISM mech; + CK_UTF8CHAR params[MAX_EC_PARAM_LEN]; + CK_ATTRIBUTE pubKeyTmpl[] = { + { CKA_EC_PARAMS, params, 0 }, + { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + }; + int pubTmplCnt = sizeof(pubKeyTmpl)/sizeof(*pubKeyTmpl); + CK_ATTRIBUTE privKeyTmpl[] = { + { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + { CKA_DERIVE, &ckTrue, sizeof(ckTrue) }, + { CKA_ID, NULL, 0 }, + }; + int privTmplCnt = 3; + + ret = Pkcs11MechAvail(session, CKM_EC_KEY_PAIR_GEN); + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: EC Key Generation Operation"); + + ret = Pkcs11EccSetParams(key, pubKeyTmpl, 0); + } + if (ret == 0) { + if (key->idLen != 0) { + privKeyTmpl[privTmplCnt].pValue = key->id; + privKeyTmpl[privTmplCnt].ulValueLen = key->idLen; + privTmplCnt++; + } + + mech.mechanism = CKM_EC_KEY_PAIR_GEN; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_GenerateKeyPair(session->handle, &mech, + pubKeyTmpl, pubTmplCnt, + privKeyTmpl, privTmplCnt, + &pubKey, &privKey); + if (rv != CKR_OK) + ret = -1; + } + + if (ret == 0) + ret = Pkcs11GetEccPublicKey(key, session, pubKey); + + if (pubKey != NULL_PTR) + session->func->C_DestroyObject(session->handle, pubKey); + if (ret != 0 && privKey != NULL_PTR) + session->func->C_DestroyObject(session->handle, privKey); + + return ret; +} +#endif + +#ifndef NO_PKCS11_ECDH +/** + * Extracts the secret key data from the PKCS#11 object. + * + * @param session [in] Session object. + * @param secret [in] PKCS#11 object with the secret key data. + * @param out [in] Buffer to hold secret data. + * @param outLen [in,out] On in, length of buffer. + * On out, the length of data in buffer. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11ExtractSecret(Pkcs11Session* session, CK_OBJECT_HANDLE secret, + byte* out, word32* outLen) +{ + int ret = 0; + CK_ATTRIBUTE tmpl[] = { + {CKA_VALUE, NULL_PTR, 0} + }; + CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); + CK_RV rv; + + rv = session->func->C_GetAttributeValue(session->handle, secret, tmpl, + tmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + if (ret == 0) { + if (tmpl[0].ulValueLen > *outLen) + ret = BUFFER_E; + } + if (ret == 0) { + tmpl[0].pValue = out; + rv = session->func->C_GetAttributeValue(session->handle, secret, + tmpl, tmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + *outLen = (word32)tmpl[0].ulValueLen; + } + + return ret; +} + +/** + * Performs the ECDH secret generation operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + int sessionKey = 0; + unsigned char* point = NULL; + word32 pointLen; + CK_RV rv; + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; + CK_MECHANISM mech; + CK_ECDH1_DERIVE_PARAMS params; + CK_OBJECT_HANDLE privateKey = NULL_PTR; + CK_OBJECT_HANDLE secret = CK_INVALID_HANDLE; + CK_ULONG secSz; + CK_ATTRIBUTE tmpl[] = { + { CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_PRIVATE, &ckFalse, sizeof(ckFalse) }, + { CKA_SENSITIVE, &ckFalse, sizeof(ckFalse) }, + { CKA_EXTRACTABLE, &ckTrue, sizeof(ckTrue) }, + { CKA_VALUE_LEN, &secSz, sizeof(secSz) } + }; + CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); + + ret = Pkcs11MechAvail(session, CKM_ECDH1_DERIVE); + if (ret == 0 && info->pk.ecdh.outlen == NULL) { + ret = BAD_FUNC_ARG; + } + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: EC Key Derivation Operation"); + + + if ((sessionKey = !mp_iszero(&info->pk.ecdh.private_key->k))) + ret = Pkcs11CreateEccPrivateKey(&privateKey, session, + info->pk.ecdh.private_key, CKA_DERIVE); + else if (info->pk.ecdh.private_key->idLen > 0) { + ret = Pkcs11FindKeyById(&privateKey, CKO_PRIVATE_KEY, CKK_EC, + session, info->pk.ecdh.private_key->id, + info->pk.ecdh.private_key->idLen); + } + else { + ret = Pkcs11FindEccKey(&privateKey, CKO_PRIVATE_KEY, session, + info->pk.ecdh.public_key); + } + } + if (ret == 0) { + ret = wc_ecc_export_x963(info->pk.ecdh.public_key, NULL, &pointLen); + if (ret == LENGTH_ONLY_E) { + point = (unsigned char*)XMALLOC(pointLen, + info->pk.ecdh.public_key->heap, + DYNAMIC_TYPE_ECC_BUFFER); + ret = wc_ecc_export_x963(info->pk.ecdh.public_key, point, + &pointLen); + } + } + + if (ret == 0) { + secSz = *info->pk.ecdh.outlen; + if (secSz > (CK_ULONG)info->pk.ecdh.private_key->dp->size) + secSz = info->pk.ecdh.private_key->dp->size; + + params.kdf = CKD_NULL; + params.pSharedData = NULL; + params.ulSharedDataLen = 0; + params.pPublicData = point; + params.ulPublicDataLen = pointLen; + + mech.mechanism = CKM_ECDH1_DERIVE; + mech.ulParameterLen = sizeof(params); + mech.pParameter = ¶ms; + + rv = session->func->C_DeriveKey(session->handle, &mech, privateKey, + tmpl, tmplCnt, &secret); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (ret == 0) { + ret = Pkcs11ExtractSecret(session, secret, info->pk.ecdh.out, + info->pk.ecdh.outlen); + } + + if (sessionKey) + session->func->C_DestroyObject(session->handle, privateKey); + + if (point != NULL) + XFREE(point, info->pk.ecdh.public_key->heap, DYNAMIC_TYPE_ECC_BUFFER); + + return ret; +} +#endif + +/** + * Encode, in place, the ECDSA signature. + * Two fixed width values into ASN.1 DER encoded SEQ { INT, INT } + * + * @param sig [in,out] Signature data. + * @param sz [in] Size of original signature data. + * @return Length of the ASN.1 DER enencoded signature. + */ +static word32 Pkcs11ECDSASig_Encode(byte* sig, word32 sz) +{ + word32 rHigh, sHigh, seqLen; + word32 rStart = 0, sStart = 0; + word32 sigSz, rSz, rLen, sSz, sLen; + word32 i; + + /* Find first byte of data in r and s. */ + while (rStart < sz - 1 && sig[rStart] == 0x00) + rStart++; + while (sStart < sz - 1 && sig[sz + sStart] == 0x00) + sStart++; + /* Check if 0 needs to be prepended to make integer a positive number. */ + rHigh = sig[rStart] >> 7; + sHigh = sig[sz + sStart] >> 7; + /* Calculate length of integer to put into ASN.1 encoding. */ + rLen = sz - rStart; + sLen = sz - sStart; + /* r and s: INT (2 bytes) + [ 0x00 ] + integer */ + rSz = 2 + rHigh + rLen; + sSz = 2 + sHigh + sLen; + /* Calculate the complete ASN.1 DER encoded size. */ + sigSz = rSz + sSz; + if (sigSz >= ASN_LONG_LENGTH) + seqLen = 3; + else + seqLen = 2; + + /* Move s and then r integers into their final places. */ + XMEMMOVE(sig + seqLen + rSz + (sSz - sLen), sig + sz + sStart, sLen); + XMEMMOVE(sig + seqLen + (rSz - rLen), sig + rStart, rLen); + + /* Put the ASN.1 DER encoding around data. */ + i = 0; + sig[i++] = ASN_CONSTRUCTED | ASN_SEQUENCE; + if (seqLen == 3) + sig[i++] = ASN_LONG_LENGTH | 0x01; + sig[i++] = sigSz; + sig[i++] = ASN_INTEGER; + sig[i++] = rHigh + (sz - rStart); + if (rHigh) + sig[i++] = 0x00; + i += sz - rStart; + sig[i++] = ASN_INTEGER; + sig[i++] = sHigh + (sz - sStart); + if (sHigh) + sig[i] = 0x00; + + return seqLen + sigSz; +} + +/** + * Decode the ECDSA signature. + * ASN.1 DER encode SEQ { INT, INT } converted to two fixed with values. + * + * @param in [in] ASN.1 DER encoded signature. + * @param inSz [in] Size of ASN.1 signature. + * @param sig [in] Output buffer. + * @param sz [in] Size of output buffer. + * @return ASN_PARSE_E when the ASN.1 encoding is invalid. + * 0 on success. + */ +static int Pkcs11ECDSASig_Decode(const byte* in, word32 inSz, byte* sig, + word32 sz) +{ + int ret = 0; + word32 i = 0; + byte tag; + int len, seqLen = 2; + + /* Make sure zeros in place when decoding short integers. */ + XMEMSET(sig, 0, sz * 2); + + /* Check min data for: SEQ + INT. */ + if (inSz < 5) + ret = ASN_PARSE_E; + /* Check SEQ */ + if (ret == 0 && in[i++] != (ASN_CONSTRUCTED | ASN_SEQUENCE)) + ret = ASN_PARSE_E; + if (ret == 0 && in[i] >= ASN_LONG_LENGTH) { + if (in[i] != (ASN_LONG_LENGTH | 0x01)) + ret = ASN_PARSE_E; + else { + i++; + seqLen++; + } + } + if (ret == 0 && in[i++] != inSz - seqLen) + ret = ASN_PARSE_E; + + /* Check INT */ + if (ret == 0 && GetASNTag(in, &i, &tag, inSz) != 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != ASN_INTEGER) + ret = ASN_PARSE_E; + if (ret == 0 && (len = in[i++]) > sz + 1) + ret = ASN_PARSE_E; + /* Check there is space for INT data */ + if (ret == 0 && i + len > inSz) + ret = ASN_PARSE_E; + if (ret == 0) { + /* Skip leading zero */ + if (in[i] == 0x00) { + i++; + len--; + } + /* Copy r into sig. */ + XMEMCPY(sig + sz - len, in + i, len); + i += len; + } + + /* Check min data for: INT. */ + if (ret == 0 && i + 2 > inSz) + ret = ASN_PARSE_E; + /* Check INT */ + if (ret == 0 && GetASNTag(in, &i, &tag, inSz) != 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != ASN_INTEGER) + ret = ASN_PARSE_E; + if (ret == 0 && (len = in[i++]) > sz + 1) + ret = ASN_PARSE_E; + /* Check there is space for INT data */ + if (ret == 0 && i + len > inSz) + ret = ASN_PARSE_E; + if (ret == 0) { + /* Skip leading zero */ + if (in[i] == 0x00) { + i++; + len--; + } + /* Copy s into sig. */ + XMEMCPY(sig + sz + sz - len, in + i, len); + } + + return ret; +} + +/** + * Get the parameters from the private key on the device. + * + * @param session [in] Session object. + * @param privKey [in] PKCS #11 object handle of private key.. + * @param key [in] Ecc key to set parameters against. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11GetEccParams(Pkcs11Session* session, CK_OBJECT_HANDLE privKey, + ecc_key* key) +{ + int ret = 0; + int curveId; + CK_RV rv; + byte oid[16]; + CK_ATTRIBUTE template[] = { + { CKA_EC_PARAMS, (CK_VOID_PTR)oid, sizeof(oid) } + }; + + rv = session->func->C_GetAttributeValue(session->handle, privKey, template, + 1); + if (rv != CKR_OK) + ret = WC_HW_E; + if (ret == 0) { + /* PKCS #11 wraps the OID in ASN.1 */ + curveId = wc_ecc_get_curve_id_from_oid(oid + 2, + (word32)template[0].ulValueLen - 2); + if (curveId == ECC_CURVE_INVALID) + ret = WC_HW_E; + } + if (ret == 0) + ret = wc_ecc_set_curve(key, 0, curveId); + + return ret; +} + +/** + * Performs the ECDSA signing operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11ECDSA_Sign(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + int sessionKey = 0; + word32 sz; + CK_RV rv; + CK_ULONG outLen; + CK_MECHANISM mech; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE privateKey = NULL_PTR; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_ECDSA, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_SIGN) == 0) + ret = NOT_COMPILED_IN; + + if (ret == 0 && info->pk.eccsign.outlen == NULL) { + ret = BAD_FUNC_ARG; + } + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: EC Signing Operation"); + + if ((sessionKey = !mp_iszero(&info->pk.eccsign.key->k))) + ret = Pkcs11CreateEccPrivateKey(&privateKey, session, + info->pk.eccsign.key, CKA_SIGN); + else if (info->pk.eccsign.key->idLen > 0) { + ret = Pkcs11FindKeyById(&privateKey, CKO_PRIVATE_KEY, CKK_EC, + session, info->pk.eccsign.key->id, + info->pk.eccsign.key->idLen); + if (ret == 0 && info->pk.eccsign.key->dp == NULL) { + ret = Pkcs11GetEccParams(session, privateKey, + info->pk.eccsign.key); + } + } + else { + ret = Pkcs11FindEccKey(&privateKey, CKO_PRIVATE_KEY, session, + info->pk.eccsign.key); + } + } + + if (ret == 0) { + sz = info->pk.eccsign.key->dp->size; + /* Maximum encoded size is two ordinates + 8 bytes of ASN.1. */ + if (*info->pk.eccsign.outlen < (word32)wc_ecc_sig_size_calc(sz)) + ret = BUFFER_E; + } + + if (ret == 0) { + mech.mechanism = CKM_ECDSA; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_SignInit(session->handle, &mech, privateKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (ret == 0) { + outLen = *info->pk.eccsign.outlen; + rv = session->func->C_Sign(session->handle, + (CK_BYTE_PTR)info->pk.eccsign.in, + info->pk.eccsign.inlen, info->pk.eccsign.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (ret == 0) { + *info->pk.eccsign.outlen = Pkcs11ECDSASig_Encode(info->pk.eccsign.out, + sz); + } + + if (sessionKey) + session->func->C_DestroyObject(session->handle, privateKey); + + return ret; +} + +/** + * Performs the ECDSA verification operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11ECDSA_Verify(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + CK_MECHANISM mech; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE publicKey = NULL_PTR; + unsigned char* sig = NULL; + word32 sz = info->pk.eccverify.key->dp->size; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_ECDSA, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_VERIFY) == 0) + ret = NOT_COMPILED_IN; + + if (ret == 0 && info->pk.eccverify.res == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: EC Verification Operation"); + + ret = Pkcs11CreateEccPublicKey(&publicKey, session, + info->pk.eccverify.key, CKA_VERIFY); + } + + if (ret == 0) { + sig = XMALLOC(sz * 2, info->pk.eccverify.key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (sig == NULL) + ret = MEMORY_E; + } + + if (ret == 0) { + ret = Pkcs11ECDSASig_Decode(info->pk.eccverify.sig, + info->pk.eccverify.siglen, sig, sz); + } + if (ret == 0) { + mech.mechanism = CKM_ECDSA; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_VerifyInit(session->handle, &mech, publicKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (ret == 0) { + *info->pk.eccverify.res = 0; + rv = session->func->C_Verify(session->handle, + (CK_BYTE_PTR)info->pk.eccverify.hash, + info->pk.eccverify.hashlen, + (CK_BYTE_PTR)sig, sz * 2); + if (rv == CKR_SIGNATURE_INVALID) { + } + else if (rv != CKR_OK) + ret = WC_HW_E; + else + *info->pk.eccverify.res = 1; + } + + if (publicKey != NULL_PTR) + session->func->C_DestroyObject(session->handle, publicKey); + + if (sig != NULL) + XFREE(sig, info->pk.eccverify.key->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif + +#if !defined(NO_AES) && defined(HAVE_AESGCM) +/** + * Performs the AES-GCM encryption operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11AesGcmEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + Aes* aes = info->cipher.aesgcm_enc.aes; + CK_GCM_PARAMS params; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE key = NULL_PTR; + CK_MECHANISM mech; + CK_ULONG outLen; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_GCM, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_ENCRYPT) == 0) + ret = NOT_COMPILED_IN; + + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: AES-GCM Encryption Operation"); + } + + /* Create a private key object or find by id. */ + if (ret == 0 && aes->idLen == 0) { + ret = Pkcs11CreateSecretKey(&key, session, CKK_AES, + (unsigned char*)aes->devKey, aes->keylen, + NULL, 0); + + } + else if (ret == 0) { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_AES, session, aes->id, + aes->idLen); + } + + if (ret == 0) { + params.pIv = (CK_BYTE_PTR)info->cipher.aesgcm_enc.iv; + params.ulIvLen = info->cipher.aesgcm_enc.ivSz; + params.pAAD = (CK_BYTE_PTR)info->cipher.aesgcm_enc.authIn; + params.ulAADLen = info->cipher.aesgcm_enc.authInSz; + params.ulTagBits = info->cipher.aesgcm_enc.authTagSz * 8; + + mech.mechanism = CKM_AES_GCM; + mech.ulParameterLen = sizeof(params); + mech.pParameter = ¶ms; + + rv = session->func->C_EncryptInit(session->handle, &mech, key); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = info->cipher.aesgcm_enc.sz; + rv = session->func->C_EncryptUpdate(session->handle, + (CK_BYTE_PTR)info->cipher.aesgcm_enc.in, + info->cipher.aesgcm_enc.sz, + info->cipher.aesgcm_enc.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + /* Authentication tag comes out in final block. */ + outLen = info->cipher.aesgcm_enc.authTagSz; + rv = session->func->C_EncryptFinal(session->handle, + info->cipher.aesgcm_enc.authTag, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (aes->idLen == 0 && key != NULL_PTR) + session->func->C_DestroyObject(session->handle, key); + + return ret; +} + +/** + * Performs the AES-GCM decryption operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11AesGcmDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + Aes* aes = info->cipher.aesgcm_enc.aes; + CK_GCM_PARAMS params; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE key = NULL_PTR; + CK_MECHANISM mech; + CK_ULONG outLen; + word32 len; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_GCM, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_DECRYPT) == 0) + ret = NOT_COMPILED_IN; + + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: AES-GCM Decryption Operation"); + } + + /* Create a private key object or find by id. */ + if (ret == 0 && aes->idLen == 0) { + ret = Pkcs11CreateSecretKey(&key, session, CKK_AES, + (unsigned char*)aes->devKey, aes->keylen, + NULL, 0); + } + else if (ret == 0) { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_AES, session, aes->id, + aes->idLen); + } + + if (ret == 0) { + params.pIv = (CK_BYTE_PTR)info->cipher.aesgcm_dec.iv; + params.ulIvLen = info->cipher.aesgcm_dec.ivSz; + params.pAAD = (CK_BYTE_PTR)info->cipher.aesgcm_dec.authIn; + params.ulAADLen = info->cipher.aesgcm_dec.authInSz; + params.ulTagBits = info->cipher.aesgcm_dec.authTagSz * 8; + + mech.mechanism = CKM_AES_GCM; + mech.ulParameterLen = sizeof(params); + mech.pParameter = ¶ms; + + rv = session->func->C_DecryptInit(session->handle, &mech, key); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = len = info->cipher.aesgcm_dec.sz; + rv = session->func->C_DecryptUpdate(session->handle, + (CK_BYTE_PTR)info->cipher.aesgcm_dec.in, + info->cipher.aesgcm_dec.sz, + info->cipher.aesgcm_dec.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + /* Put authentication tag in as encrypted data. */ + outLen = len = (len + info->cipher.aesgcm_dec.authTagSz - + (word32)outLen); + rv = session->func->C_DecryptUpdate(session->handle, + (CK_BYTE_PTR)info->cipher.aesgcm_dec.authTag, + info->cipher.aesgcm_dec.authTagSz, + info->cipher.aesgcm_dec.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = len = (len - (word32)outLen); + /* Decrypted data comes out now. */ + rv = session->func->C_DecryptFinal(session->handle, + info->cipher.aesgcm_dec.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (aes->idLen == 0 && key != NULL_PTR) + session->func->C_DestroyObject(session->handle, key); + + return ret; +} +#endif + +#if !defined(NO_AES) && defined(HAVE_AES_CBC) +/** + * Performs the AES-CBC encryption operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11AesCbcEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + Aes* aes = info->cipher.aescbc.aes; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE key = NULL_PTR; + CK_MECHANISM mech; + CK_ULONG outLen; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_CBC, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_ENCRYPT) == 0) + ret = NOT_COMPILED_IN; + + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: AES-CBC Encryption Operation"); + } + + /* Create a private key object or find by id. */ + if (ret == 0 && aes->idLen == 0) { + ret = Pkcs11CreateSecretKey(&key, session, CKK_AES, + (unsigned char*)aes->devKey, aes->keylen, + NULL, 0); + + } + else if (ret == 0) { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_AES, session, aes->id, + aes->idLen); + } + + if (ret == 0) { + mech.mechanism = CKM_AES_CBC; + mech.ulParameterLen = AES_BLOCK_SIZE; + mech.pParameter = (CK_BYTE_PTR)info->cipher.aescbc.aes->reg; + + rv = session->func->C_EncryptInit(session->handle, &mech, key); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = info->cipher.aescbc.sz; + rv = session->func->C_Encrypt(session->handle, + (CK_BYTE_PTR)info->cipher.aescbc.in, + info->cipher.aescbc.sz, + info->cipher.aescbc.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (aes->idLen == 0 && key != NULL_PTR) + session->func->C_DestroyObject(session->handle, key); + + return ret; +} + +/** + * Performs the AES-CBC decryption operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11AesCbcDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + Aes* aes = info->cipher.aescbc.aes; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE key = NULL_PTR; + CK_MECHANISM mech; + CK_ULONG outLen; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_CBC, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_DECRYPT) == 0) + ret = NOT_COMPILED_IN; + + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: AES-CBC Decryption Operation"); + } + + /* Create a private key object or find by id. */ + if (ret == 0 && aes->idLen == 0) { + ret = Pkcs11CreateSecretKey(&key, session, CKK_AES, + (unsigned char*)aes->devKey, aes->keylen, + NULL, 0); + } + else if (ret == 0) { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_AES, session, aes->id, + aes->idLen); + } + + if (ret == 0) { + mech.mechanism = CKM_AES_CBC; + mech.ulParameterLen = AES_BLOCK_SIZE; + mech.pParameter = (CK_BYTE_PTR)info->cipher.aescbc.aes->reg; + + rv = session->func->C_DecryptInit(session->handle, &mech, key); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = info->cipher.aescbc.sz; + rv = session->func->C_DecryptUpdate(session->handle, + (CK_BYTE_PTR)info->cipher.aescbc.in, + info->cipher.aescbc.sz, + info->cipher.aescbc.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (aes->idLen == 0 && key != NULL_PTR) + session->func->C_DestroyObject(session->handle, key); + + return ret; +} +#endif + +#ifndef NO_HMAC +/** + * Updates or calculates the HMAC of the data. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11Hmac(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + Hmac* hmac = info->hmac.hmac; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE key = NULL_PTR; + CK_MECHANISM mech; + CK_ULONG outLen; + int mechType; + int keyType; + + if (hmac->innerHashKeyed == WC_HMAC_INNER_HASH_KEYED_SW) + ret = NOT_COMPILED_IN; + + if (ret == 0) + ret = Pkcs11HmacTypes(info->hmac.macType, &mechType, &keyType); + if (ret == 0) { + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, mechType, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_SIGN) == 0) + ret = NOT_COMPILED_IN; + } + + /* Check whether key been used to initialized. */ + if (ret == 0 && !hmac->innerHashKeyed) { + WOLFSSL_MSG("PKCS#11: HMAC Init"); + + /* Check device supports key length. */ + if (mechInfo.ulMaxKeySize > 0 && + (hmac->keyLen < mechInfo.ulMinKeySize || + hmac->keyLen > mechInfo.ulMaxKeySize)) { + WOLFSSL_MSG("PKCS#11: Key Length not supported"); + ret = NOT_COMPILED_IN; + } + + /* Create a private key object or find by id. */ + if (ret == 0 && hmac->idLen == 0) { + ret = Pkcs11CreateSecretKey(&key, session, keyType, + (unsigned char*)hmac->keyRaw, hmac->keyLen, + NULL, 0); + if (ret == WC_HW_E) { + ret = Pkcs11CreateSecretKey(&key, session, CKK_GENERIC_SECRET, + (unsigned char*)hmac->keyRaw, hmac->keyLen, + NULL, 0); + } + + } + else if (ret == 0) { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, keyType, session, + hmac->id, hmac->idLen); + if (ret == WC_HW_E) { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, + CKK_GENERIC_SECRET, session, hmac->id, + hmac->idLen); + } + } + + /* Initialize HMAC operation */ + if (ret == 0) { + mech.mechanism = mechType; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_SignInit(session->handle, &mech, key); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + /* Don't imitialize HMAC again if this succeeded */ + if (ret == 0) + hmac->innerHashKeyed = WC_HMAC_INNER_HASH_KEYED_DEV; + } + /* Update the HMAC if input data passed in. */ + if (ret == 0 && info->hmac.inSz > 0) { + WOLFSSL_MSG("PKCS#11: HMAC Update"); + + rv = session->func->C_SignUpdate(session->handle, + (CK_BYTE_PTR)info->hmac.in, + info->hmac.inSz); + /* Some algorithm implementations only support C_Sign. */ + if (rv == CKR_MECHANISM_INVALID) { + WOLFSSL_MSG("PKCS#11: HMAC Update/Final not supported"); + ret = NOT_COMPILED_IN; + /* Allow software implementation to set key. */ + hmac->innerHashKeyed = 0; + } + else if (rv != CKR_OK) + ret = WC_HW_E; + } + /* Calculate the HMAC result if output buffer specified. */ + if (ret == 0 && info->hmac.digest != NULL) { + WOLFSSL_MSG("PKCS#11: HMAC Final"); + + outLen = WC_MAX_DIGEST_SIZE; + rv = session->func->C_SignFinal(session->handle, + (CK_BYTE_PTR)info->hmac.digest, + &outLen); + /* Some algorithm implementations only support C_Sign. */ + if (rv != CKR_OK) + ret = WC_HW_E; + else + hmac->innerHashKeyed = 0; + } + + if (hmac->idLen == 0 && key != NULL_PTR) + session->func->C_DestroyObject(session->handle, key); + + return ret; +} +#endif + +#ifndef WC_NO_RNG +#ifndef HAVE_HASHDRBG +/** + * Performs random number generation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11RandomBlock(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + + rv = session->func->C_GenerateRandom(session->handle, info->rng.out, + info->rng.sz); + if (rv != CKR_OK) + ret = WC_HW_E; + return ret; +} +#endif + +/** + * Generates entropy (seed) data. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11RandomSeed(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + + rv = session->func->C_GenerateRandom(session->handle, info->seed.seed, + info->seed.sz); + if (rv != CKR_OK) + ret = WC_HW_E; + return ret; +} +#endif + +/** + * Perform a cryptographic operation using PKCS#11 device. + * + * @param devId [in] Device identifier. + * @param info [in] Cryptographic operation data. + * @param ctx [in] Context data for device - the token object. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) +{ + int ret = 0; + Pkcs11Token* token = (Pkcs11Token*)ctx; + Pkcs11Session session; + int readWrite = 0; + + if (devId <= INVALID_DEVID || info == NULL || ctx == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + ret = Pkcs11OpenSession(token, &session, readWrite); + if (ret == 0) { + if (info->algo_type == WC_ALGO_TYPE_PK) { +#if !defined(NO_RSA) || defined(HAVE_ECC) + switch (info->pk.type) { + #ifndef NO_RSA + case WC_PK_TYPE_RSA: + ret = Pkcs11Rsa(&session, info); + break; + #ifdef WOLFSSL_KEY_GEN + case WC_PK_TYPE_RSA_KEYGEN: + ret = Pkcs11RsaKeyGen(&session, info); + break; + #endif + #endif + #ifdef HAVE_ECC + #ifndef NO_PKCS11_EC_KEYGEN + case WC_PK_TYPE_EC_KEYGEN: + ret = Pkcs11EcKeyGen(&session, info); + break; + #endif + #ifndef NO_PKCS11_ECDH + case WC_PK_TYPE_ECDH: + ret = Pkcs11ECDH(&session, info); + break; + #endif + case WC_PK_TYPE_ECDSA_SIGN: + ret = Pkcs11ECDSA_Sign(&session, info); + break; + case WC_PK_TYPE_ECDSA_VERIFY: + ret = Pkcs11ECDSA_Verify(&session, info); + break; + #endif + default: + ret = NOT_COMPILED_IN; + break; + } +#else + ret = NOT_COMPILED_IN; +#endif /* !NO_RSA || HAVE_ECC */ + } + else if (info->algo_type == WC_ALGO_TYPE_CIPHER) { + #ifndef NO_AES + switch (info->cipher.type) { + #ifdef HAVE_AESGCM + case WC_CIPHER_AES_GCM: + if (info->cipher.enc) + ret = Pkcs11AesGcmEncrypt(&session, info); + else + ret = Pkcs11AesGcmDecrypt(&session, info); + break; + #endif + #ifdef HAVE_AES_CBC + case WC_CIPHER_AES_CBC: + if (info->cipher.enc) + ret = Pkcs11AesCbcEncrypt(&session, info); + else + ret = Pkcs11AesCbcDecrypt(&session, info); + break; + #endif + } + #else + ret = NOT_COMPILED_IN; + #endif + } + else if (info->algo_type == WC_ALGO_TYPE_HMAC) { + #ifndef NO_HMAC + ret = Pkcs11Hmac(&session, info); + #else + ret = NOT_COMPILED_IN; + #endif + } + else if (info->algo_type == WC_ALGO_TYPE_RNG) { + #if !defined(WC_NO_RNG) && !defined(HAVE_HASHDRBG) + ret = Pkcs11RandomBlock(&session, info); + #else + ret = NOT_COMPILED_IN; + #endif + } + else if (info->algo_type == WC_ALGO_TYPE_SEED) { + #ifndef WC_NO_RNG + ret = Pkcs11RandomSeed(&session, info); + #else + ret = NOT_COMPILED_IN; + #endif + } + else + ret = NOT_COMPILED_IN; + + Pkcs11CloseSession(token, &session); + } + } + + return ret; +} + +#endif /* HAVE_PKCS11 */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_port.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_port.c index 419033751..087807b71 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_port.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wc_port.c @@ -1,8 +1,8 @@ /* port.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif @@ -26,631 +27,2250 @@ #include #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 + #include + #include +#endif + +#ifdef FREESCALE_LTC_TFM + #include +#endif + +#if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) + #include +#endif +#if defined(WOLFSSL_RENESAS_TSIP) + #include +#endif +#if defined(WOLFSSL_STSAFEA100) + #include +#endif + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + #include +#endif + +#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) + #include + #include +#endif + +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6_CAAM_BLOB) + #include +#endif + +#ifdef WOLF_CRYPTO_CB + #include +#endif + +#ifdef HAVE_INTEL_QA_SYNC + #include +#endif + +#ifdef HAVE_CAVIUM_OCTEON_SYNC + #include +#endif + +#ifdef WOLFSSL_SCE + #include "hal_data.h" +#endif + +#if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD) + #include "rpcmem.h" +#endif #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ #pragma warning(disable: 4996) #endif +/* prevent multiple mutex initializations */ +static volatile int initRefCount = 0; + +/* Used to initialize state for wolfcrypt + return 0 on success + */ +int wolfCrypt_Init(void) +{ + int ret = 0; + + if (initRefCount == 0) { + WOLFSSL_ENTER("wolfCrypt_Init"); + + #ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST + { + word32 rngMallocFail; + time_t seed = time(NULL); + srand((word32)seed); + rngMallocFail = rand() % 2000; /* max 2000 */ + printf("\n--- RNG MALLOC FAIL AT %d---\n", rngMallocFail); + wolfSSL_SetMemFailCount(rngMallocFail); + } + #endif + + #ifdef WOLF_CRYPTO_CB + wc_CryptoCb_Init(); + #endif + + #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_RENESAS_TSIP_CRYPT) + ret = tsip_Open( ); + if( ret != TSIP_SUCCESS ) { + WOLFSSL_MSG("RENESAS TSIP Open failed"); + /* not return 1 since WOLFSSL_SUCCESS=1*/ + ret = -1;/* FATAL ERROR */ + return ret; + } + #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 */ + 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 */ + #ifdef HAVE_FAST_RSA + WOLFSSL_MSG("Attempting to use optimized IPP Library"); + if ((ret = ippInit()) != ippStsNoErr) { + /* possible to get a CPU feature support status on optimized IPP + library but still use default library and see competitive speeds */ + WOLFSSL_MSG("Warning when trying to set up optimization"); + 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) + ret = ksdk_port_init(); + if (ret != 0) { + WOLFSSL_MSG("KSDK port init failed"); + return ret; + } + #endif + + #if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) + ret = atmel_init(); + if (ret != 0) { + WOLFSSL_MSG("CryptoAuthLib init failed"); + return ret; + } + #endif + #if defined(WOLFSSL_CRYPTOCELL) + /* enable and initialize the ARM CryptoCell 3xx runtime library */ + ret = cc310_Init(); + if (ret != 0) { + WOLFSSL_MSG("CRYPTOCELL init failed"); + return ret; + } + #endif + #if defined(WOLFSSL_STSAFEA100) + stsafe_interface_init(); + #endif + + #ifdef WOLFSSL_ARMASM + WOLFSSL_MSG("Using ARM hardware acceleration"); + #endif + + #ifdef WOLFSSL_AFALG + WOLFSSL_MSG("Using AF_ALG for crypto acceleration"); + #endif + + #if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA) + wolfSSL_EVP_init(); + #endif + + #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + if ((ret = wc_LoggingInit()) != 0) { + WOLFSSL_MSG("Error creating logging mutex"); + return ret; + } + #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 + +#ifdef WOLFSSL_SCE + ret = (int)WOLFSSL_SCE_GSCE_HANDLE.p_api->open( + WOLFSSL_SCE_GSCE_HANDLE.p_ctrl, WOLFSSL_SCE_GSCE_HANDLE.p_cfg); + if (ret == SSP_ERR_CRYPTO_SCE_ALREADY_OPEN) { + WOLFSSL_MSG("SCE already open"); + ret = 0; + } + if (ret != SSP_SUCCESS) { + WOLFSSL_MSG("Error opening SCE"); + return -1; /* FATAL_ERROR */ + } +#endif + +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6_CAAM_BLOB) + if ((ret = wc_caamInit()) != 0) { + return ret; + } +#endif + +#if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD) + if ((ret = wolfSSL_InitHandle()) != 0) { + return ret; + } + rpcmem_init(); +#endif + } + initRefCount++; + + return ret; +} +/* return success value is the same as wolfCrypt_Init */ +int wolfCrypt_Cleanup(void) +{ + int ret = 0; + + initRefCount--; + if (initRefCount < 0) + initRefCount = 0; + + if (initRefCount == 0) { + 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 + #ifdef WOLFSSL_SCE + WOLFSSL_SCE_GSCE_HANDLE.p_api->close(WOLFSSL_SCE_GSCE_HANDLE.p_ctrl); + #endif + #if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6_CAAM_BLOB) + wc_caamFree(); + #endif + #if defined(WOLFSSL_CRYPTOCELL) + cc310_Free(); + #endif + #if defined(WOLFSSL_RENESAS_TSIP_CRYPT) + tsip_Close(); + #endif + #if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD) + rpcmem_deinit(); + wolfSSL_CleanupHandle(); + #endif + } + + return ret; +} + +#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) && \ + !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) + +/* File Handling Helpers */ +/* returns 0 if file found, WC_READDIR_NOFILE if no files or negative error */ +int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) +{ + int ret = WC_READDIR_NOFILE; /* default to no files found */ + int pathLen = 0; + int dnameLen = 0; + + if (name) + *name = NULL; + + if (ctx == NULL || path == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(ctx->name, 0, MAX_FILENAME_SZ); + pathLen = (int)XSTRLEN(path); + +#ifdef USE_WINDOWS_API + if (pathLen > MAX_FILENAME_SZ - 3) + return BAD_PATH_ERROR; + + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ - 3); + XSTRNCPY(ctx->name + pathLen, "\\*", MAX_FILENAME_SZ - pathLen); + + 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)) { + dnameLen = (int)XSTRLEN(ctx->FindFileData.cFileName); + + if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) { + return BAD_PATH_ERROR; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '\\'; + XSTRNCPY(ctx->name + pathLen + 1, + ctx->FindFileData.cFileName, + MAX_FILENAME_SZ - pathLen - 1); + if (name) + *name = ctx->name; + return 0; + } + } while (FindNextFileA(ctx->hFind, &ctx->FindFileData)); +#elif defined(WOLFSSL_ZEPHYR) + if (fs_opendir(&ctx->dir, path) != 0) { + WOLFSSL_MSG("opendir path verify locations failed"); + return BAD_PATH_ERROR; + } + ctx->dirp = &ctx->dir; + + while ((fs_readdir(&ctx->dir, &ctx->entry)) != 0) { + dnameLen = (int)XSTRLEN(ctx->entry.name); + + if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { + ret = BAD_PATH_ERROR; + break; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '/'; + + /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because + * of earlier check it is known that dnameLen is less than + * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ + XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1); + if (fs_stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } else if (ctx->s.type == FS_DIR_ENTRY_FILE) { + if (name) + *name = ctx->name; + return 0; + } + } +#elif defined(WOLFSSL_TELIT_M2MB) + ctx->dir = m2mb_fs_opendir((const CHAR*)path); + if (ctx->dir == NULL) { + WOLFSSL_MSG("opendir path verify locations failed"); + return BAD_PATH_ERROR; + } + + while ((ctx->entry = m2mb_fs_readdir(ctx->dir)) != NULL) { + dnameLen = (int)XSTRLEN(ctx->entry->d_name); + + if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { + ret = BAD_PATH_ERROR; + break; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '/'; + + /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because + * of earlier check it is known that dnameLen is less than + * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ + XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); + + if (m2mb_fs_stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } + else if (ctx->s.st_mode & M2MB_S_IFREG) { + if (name) + *name = ctx->name; + return 0; + } + } +#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) { + dnameLen = (int)XSTRLEN(ctx->entry->d_name); + + if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { + ret = BAD_PATH_ERROR; + break; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '/'; + + /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because + * of earlier check it is known that dnameLen is less than + * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ + XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); + if (stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } else if (S_ISREG(ctx->s.st_mode)) { + if (name) + *name = ctx->name; + return 0; + } + } +#endif + wc_ReadDirClose(ctx); + + return ret; +} + +/* returns 0 if file found, WC_READDIR_NOFILE if no more files */ +int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name) +{ + int ret = WC_READDIR_NOFILE; /* default to no file found */ + int pathLen = 0; + int dnameLen = 0; + + if (name) + *name = NULL; + + if (ctx == NULL || path == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(ctx->name, 0, MAX_FILENAME_SZ); + pathLen = (int)XSTRLEN(path); + +#ifdef USE_WINDOWS_API + while (FindNextFileA(ctx->hFind, &ctx->FindFileData)) { + if (!(ctx->FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + dnameLen = (int)XSTRLEN(ctx->FindFileData.cFileName); + + if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) { + return BAD_PATH_ERROR; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '\\'; + XSTRNCPY(ctx->name + pathLen + 1, + ctx->FindFileData.cFileName, + MAX_FILENAME_SZ - pathLen - 1); + if (name) + *name = ctx->name; + return 0; + } + } +#elif defined(WOLFSSL_ZEPHYR) + while ((fs_readdir(&ctx->dir, &ctx->entry)) != 0) { + dnameLen = (int)XSTRLEN(ctx->entry.name); + + if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { + ret = BAD_PATH_ERROR; + break; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '/'; + /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because + * of earlier check it is known that dnameLen is less than + * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */ + XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1); + + if (fs_stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } else if (ctx->s.type == FS_DIR_ENTRY_FILE) { + if (name) + *name = ctx->name; + return 0; + } + } +#elif defined(WOLFSSL_TELIT_M2MB) + while ((ctx->entry = m2mb_fs_readdir(ctx->dir)) != NULL) { + dnameLen = (int)XSTRLEN(ctx->entry->d_name); + + if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { + ret = BAD_PATH_ERROR; + break; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '/'; + + /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because + * of earlier check it is known that dnameLen is less than + * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ + XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); + + if (m2mb_fs_stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } + else if (ctx->s.st_mode & M2MB_S_IFREG) { + if (name) + *name = ctx->name; + return 0; + } + } +#else + while ((ctx->entry = readdir(ctx->dir)) != NULL) { + dnameLen = (int)XSTRLEN(ctx->entry->d_name); + + if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { + ret = BAD_PATH_ERROR; + break; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '/'; + /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because + * of earlier check it is known that dnameLen is less than + * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */ + XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); + + if (stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } else if (S_ISREG(ctx->s.st_mode)) { + 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; + } +#elif defined(WOLFSSL_ZEPHYR) + if (ctx->dirp) { + fs_closedir(ctx->dirp); + ctx->dirp = NULL; + } +#elif defined(WOLFSSL_TELIT_M2MB) + if (ctx->dir) { + m2mb_fs_closedir(ctx->dir); + ctx->dir = NULL; + } +#else + if (ctx->dir) { + closedir(ctx->dir); + ctx->dir = NULL; + } +#endif +} + +#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ + +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_ZEPHYR) +XFILE z_fs_open(const char* filename, const char* perm) +{ + XFILE file; + + file = XMALLOC(sizeof(*file), NULL, DYNAMIC_TYPE_FILE); + if (file != NULL) { + if (fs_open(file, filename) != 0) { + XFREE(file, NULL, DYNAMIC_TYPE_FILE); + file = NULL; + } + } + + return file; +} + +int z_fs_close(XFILE file) +{ + int ret; + + if (file == NULL) + return -1; + ret = (fs_close(file) == 0) ? 0 : -1; + + XFREE(file, NULL, DYNAMIC_TYPE_FILE); + + return ret; +} + +#endif /* !NO_FILESYSTEM && !WOLFSSL_ZEPHYR */ + + +wolfSSL_Mutex* wc_InitAndAllocMutex(void) +{ + wolfSSL_Mutex* m = (wolfSSL_Mutex*) XMALLOC(sizeof(wolfSSL_Mutex), NULL, + DYNAMIC_TYPE_MUTEX); + 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 */ + +#ifdef USE_WOLF_STRSEP +char* wc_strsep(char **stringp, const char *delim) +{ + char *s, *tok; + const char *spanp; + + /* null check */ + if (stringp == NULL || *stringp == NULL) + return NULL; + + s = *stringp; + for (tok = s; *tok; ++tok) { + for (spanp = delim; *spanp; ++spanp) { + /* found delimiter */ + if (*tok == *spanp) { + *tok = '\0'; /* replace delim with null term */ + *stringp = tok + 1; /* return past delim */ + return s; + } + } + } + + *stringp = NULL; + return s; +} +#endif /* USE_WOLF_STRSEP */ + +#if WOLFSSL_CRYPT_HW_MUTEX +/* Mutex for protection of cryptography hardware */ +static wolfSSL_Mutex wcCryptHwMutex; +static int wcCryptHwMutexInit = 0; + +int wolfSSL_CryptHwMutexInit(void) { + int ret = 0; + if(wcCryptHwMutexInit == 0) { + ret = wc_InitMutex(&wcCryptHwMutex); + if(ret == 0) { + wcCryptHwMutexInit = 1; + } + } + return ret; +} + +int wolfSSL_CryptHwMutexLock(void) { + int ret = BAD_MUTEX_E; + + /* Make sure HW Mutex has been initialized */ + wolfSSL_CryptHwMutexInit(); + + if(wcCryptHwMutexInit) { + ret = wc_LockMutex(&wcCryptHwMutex); + } + return ret; +} + +int wolfSSL_CryptHwMutexUnLock(void) { + int ret = BAD_MUTEX_E; + + if(wcCryptHwMutexInit) { + ret = wc_UnLockMutex(&wcCryptHwMutex); + } + return ret; +} +#endif /* WOLFSSL_CRYPT_HW_MUTEX */ + + +/* ---------------------------------------------------------------------------*/ +/* Mutex Ports */ +/* ---------------------------------------------------------------------------*/ +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + static mutex_cb* compat_mutex_cb = NULL; + + /* Function that locks or unlocks a mutex based on the flag passed in. + * + * flag lock or unlock i.e. CRYPTO_LOCK + * type the type of lock to unlock or lock + * file name of the file calling + * line the line number from file calling + */ + int wc_LockMutex_ex(int flag, int type, const char* file, int line) + { + if (compat_mutex_cb != NULL) { + compat_mutex_cb(flag, type, file, line); + return 0; + } + else { + WOLFSSL_MSG("Mutex call back function not set. Call wc_SetMutexCb"); + return BAD_STATE_E; + } + } + + + /* Set the callback function to use for locking/unlocking mutex + * + * cb callback function to use + */ + int wc_SetMutexCb(mutex_cb* cb) + { + compat_mutex_cb = cb; + return 0; + } +#endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) */ #ifdef SINGLE_THREADED -int 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 FreeMutex(wolfSSL_Mutex *m) -{ - (void)m; - return 0; -} + int wc_LockMutex(wolfSSL_Mutex *m) + { + (void)m; + return 0; + } -int LockMutex(wolfSSL_Mutex *m) -{ - (void)m; - return 0; -} + int wc_UnLockMutex(wolfSSL_Mutex *m) + { + (void)m; + return 0; + } + +#elif defined(FREERTOS) || defined(FREERTOS_TCP) || \ + defined(FREESCALE_FREE_RTOS) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + int iReturn; + + *m = ( wolfSSL_Mutex ) xSemaphoreCreateMutex(); + if( *m != NULL ) + iReturn = 0; + else + iReturn = BAD_MUTEX_E; + + 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 UnLockMutex(wolfSSL_Mutex *m) -{ - (void)m; - return 0; -} + int wc_FreeMutex(wolfSSL_Mutex* m) + { + DeleteCriticalSection(m); + return 0; + } -#else /* MULTI_THREAD */ - #if defined(FREERTOS) + int wc_LockMutex(wolfSSL_Mutex* m) + { + EnterCriticalSection(m); + return 0; + } - int InitMutex(wolfSSL_Mutex* m) - { - int iReturn; - *m = ( wolfSSL_Mutex ) xSemaphoreCreateMutex(); - if( *m != NULL ) - iReturn = 0; - else - iReturn = BAD_MUTEX_E; + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + LeaveCriticalSection(m); + return 0; + } - return iReturn; - } +#elif defined(WOLFSSL_PTHREADS) - int FreeMutex(wolfSSL_Mutex* m) - { - vSemaphoreDelete( *m ); + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_init(m, 0) == 0) return 0; - } + else + return BAD_MUTEX_E; + } - int 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 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 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 FreeMutex(wolfSSL_Mutex* m) - { - (void)m; - return 0; - } +#elif defined(WOLFSSL_VXWORKS) - int LockMutex(wolfSSL_Mutex* m) - { - /* Assume an infinite block */ - xSemaphoreTake(m->mutex, portMAX_DELAY); - return 0; - } - - int UnLockMutex(wolfSSL_Mutex* m) - { - xSemaphoreGive(m->mutex); - return 0; - } - - - #elif defined(USE_WINDOWS_API) - - int InitMutex(wolfSSL_Mutex* m) - { - InitializeCriticalSection(m); - return 0; - } - - - int FreeMutex(wolfSSL_Mutex* m) - { - DeleteCriticalSection(m); - return 0; - } - - - int LockMutex(wolfSSL_Mutex* m) - { - EnterCriticalSection(m); - return 0; - } - - - int UnLockMutex(wolfSSL_Mutex* m) - { - LeaveCriticalSection(m); - return 0; - } - - #elif defined(WOLFSSL_PTHREADS) - - int InitMutex(wolfSSL_Mutex* m) - { - if (pthread_mutex_init(m, 0) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - - int FreeMutex(wolfSSL_Mutex* m) - { - if (pthread_mutex_destroy(m) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - - int LockMutex(wolfSSL_Mutex* m) - { - if (pthread_mutex_lock(m) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - - int UnLockMutex(wolfSSL_Mutex* m) - { - if (pthread_mutex_unlock(m) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - #elif defined(THREADX) - - int InitMutex(wolfSSL_Mutex* m) - { - if (tx_mutex_create(m, "wolfSSL Mutex", TX_NO_INHERIT) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - - int FreeMutex(wolfSSL_Mutex* m) - { - if (tx_mutex_delete(m) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - - int LockMutex(wolfSSL_Mutex* m) - { - if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - - int UnLockMutex(wolfSSL_Mutex* m) - { - if (tx_mutex_put(m) == 0) - return 0; - else - return BAD_MUTEX_E; - } - - #elif defined(MICRIUM) - - int 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 FreeMutex(wolfSSL_Mutex* m) - { - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - if (NetSecure_OS_FreeMutex(m) == 0) - return 0; - else - return BAD_MUTEX_E; - #else - return 0; - #endif - } - - - int LockMutex(wolfSSL_Mutex* m) - { - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - if (NetSecure_OS_LockMutex(m) == 0) - return 0; - else - return BAD_MUTEX_E; - #else - return 0; - #endif - } - - - int UnLockMutex(wolfSSL_Mutex* m) - { - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - if (NetSecure_OS_UnLockMutex(m) == 0) - return 0; - else - return BAD_MUTEX_E; - #else - return 0; - #endif - - } - - #elif defined(EBSNET) - - int InitMutex(wolfSSL_Mutex* m) - { - if (rtp_sig_mutex_alloc(m, "wolfSSL Mutex") == -1) - return BAD_MUTEX_E; - else + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (m) { + if ((*m = semMCreate(0)) != SEM_ID_NULL) return 0; } + return BAD_MUTEX_E; + } - int FreeMutex(wolfSSL_Mutex* m) - { - rtp_sig_mutex_free(*m); - return 0; - } - int LockMutex(wolfSSL_Mutex* m) - { - if (rtp_sig_mutex_claim_timed(*m, RTIP_INF) == 0) + int wc_FreeMutex(wolfSSL_Mutex* m) + { + if (m) { + if (semDelete(*m) == OK) return 0; - else - return BAD_MUTEX_E; } + return BAD_MUTEX_E; + } - int UnLockMutex(wolfSSL_Mutex* m) - { - rtp_sig_mutex_release(*m); - return 0; - } - #elif defined(FREESCALE_MQX) - - int InitMutex(wolfSSL_Mutex* m) - { - if (_mutex_init(m, NULL) == MQX_EOK) + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (m) { + if (semTake(*m, WAIT_FOREVER) == OK) return 0; - else - return BAD_MUTEX_E; } + return BAD_MUTEX_E; + } - int FreeMutex(wolfSSL_Mutex* m) - { - if (_mutex_destroy(m) == MQX_EOK) + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + if (m) { + if (semGive(*m) == OK) return 0; - else - return BAD_MUTEX_E; } + return BAD_MUTEX_E; + } - int LockMutex(wolfSSL_Mutex* m) - { - if (_mutex_lock(m) == MQX_EOK) +#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(WOLFSSL_DEOS) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + mutexStatus mutStat; + /* + The empty string "" denotes an anonymous mutex, so objects do not cause name collisions. + `protectWolfSSLTemp` in an XML configuration element template describing a mutex. + */ + if (m) { + mutStat = createMutex("", "protectWolfSSLTemp", m); + if (mutStat == mutexSuccess) return 0; - else - return BAD_MUTEX_E; - } - - int UnLockMutex(wolfSSL_Mutex* m) - { - if (_mutex_unlock(m) == MQX_EOK) - return 0; - else - return BAD_MUTEX_E; - } - - #elif defined (WOLFSSL_TIRTOS) - - int InitMutex(wolfSSL_Mutex* m) - { - Semaphore_Params params; - - Semaphore_Params_init(¶ms); - params.mode = Semaphore_Mode_BINARY; - - *m = Semaphore_create(1, ¶ms, NULL); - - return 0; - } - - int FreeMutex(wolfSSL_Mutex* m) - { - Semaphore_delete(m); - - return 0; - } - - int LockMutex(wolfSSL_Mutex* m) - { - Semaphore_pend(*m, BIOS_WAIT_FOREVER); - - return 0; - } - - int UnLockMutex(wolfSSL_Mutex* m) - { - Semaphore_post(*m); - - return 0; - } - - #elif defined(WOLFSSL_uITRON4) - #include "kernel.h" - int 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 != NULL ) - iReturn = 0; - else - iReturn = BAD_MUTEX_E; - - return iReturn; - } - - int FreeMutex(wolfSSL_Mutex* m) - { - del_sem( m->id ); - return 0; - } - - int LockMutex(wolfSSL_Mutex* m) - { - wai_sem(m->id); - return 0; - } - - int 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; + else{ + WOLFSSL_MSG("wc_InitMutex failed"); + return mutStat; } } + return BAD_MUTEX_E; + } - 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_FreeMutex(wolfSSL_Mutex* m) + { + mutexStatus mutStat; + if (m) { + mutStat = deleteMutex(*m); + if (mutStat == mutexSuccess) + return 0; + else{ + WOLFSSL_MSG("wc_FreeMutex failed"); + return mutStat; } } + return BAD_MUTEX_E; + } - void *uITRON4_realloc(void *p, size_t sz) { - ER ercd; - void *newp ; - if(p) { - ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp); + int wc_LockMutex(wolfSSL_Mutex* m) + { + mutexStatus mutStat; + if (m) { + mutStat = lockMutex(*m); + if (mutStat == mutexSuccess) + return 0; + else{ + WOLFSSL_MSG("wc_LockMutex failed"); + return mutStat; + } + } + return BAD_MUTEX_E; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + mutexStatus mutStat; + if (m) { + mutStat = unlockMutex(*m); + if (mutStat== mutexSuccess) + return 0; + else{ + WOLFSSL_MSG("wc_UnLockMutex failed"); + return mutStat; + } + } + return BAD_MUTEX_E; + } + +#elif defined(MICRIUM) + + 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; + + OSMutexDel(m, OS_OPT_DEL_ALWAYS, &err); + + 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; + } + + int ebsnet_fseek(int a, long b, int c) + { + int retval; + + retval = vf_lseek(a, b, c); + if (retval > 0) + retval = 0; + else + retval = -1; + + return(retval); + } + +#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) + + 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 = NULL; + 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); + if (ercd == E_OK) { + XMEMCPY(newp, p, sz); + ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); if (ercd == E_OK) { - memcpy(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 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 FreeMutex(wolfSSL_Mutex* m) - { - tk_del_sem( m->id ); + void *uTKernel_malloc(unsigned int sz) { + ER ercd; + void *p = NULL; + ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p, TMO_FEVR); + if (ercd == E_OK) { + return p; + } else { return 0; } + } - int LockMutex(wolfSSL_Mutex* m) - { - tk_wai_sem(m->id, 1, TMO_FEVR); - return 0; - } - - int 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) { - memcpy(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 ; + 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; + } + + 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(WOLFSSL_DEOS) + +time_t deos_time(time_t* timer) +{ + const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds(); + uint32_t *systemTickPtr = systemTickPointer(); + + if (timer != NULL) + *timer = *systemTickPtr/systemTickTimeInHz; + + #if defined(CURRENT_UNIX_TIMESTAMP) + /* CURRENT_UNIX_TIMESTAMP is seconds since Jan 01 1970. (UTC) */ + return (time_t) *systemTickPtr/systemTickTimeInHz + CURRENT_UNIX_TIMESTAMP; + #else + return (time_t) *systemTickPtr/systemTickTimeInHz; + #endif +} +#endif /* WOLFSSL_DEOS */ + +#if defined(MICRIUM) + +time_t micrium_time(time_t* timer) +{ + CLK_TS_SEC sec; + + Clk_GetTS_Unix(&sec); + + if (timer != NULL) + *timer = 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) && defined(USER_TIME) + +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); + } + else { + WOLFSSL_MSG("Unable to initialize RTC"); + } + } + + if (timer != NULL) + *timer = sec; + + return sec; +} + +#endif /* WOLFSSL_XILINX */ + +#if defined(WOLFSSL_ZEPHYR) + +time_t z_time(time_t * timer) +{ + struct timespec ts; + + if (clock_gettime(CLOCK_REALTIME, &ts) == 0) + if (timer != NULL) + *timer = ts.tv_sec; + + return ts.tv_sec; +} + +#endif /* WOLFSSL_ZEPHYR */ + + +#if defined(WOLFSSL_WICED) + #ifndef WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME + #error Please define WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME at build time. + #endif /* WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME */ + +time_t wiced_pseudo_unix_epoch_time(time_t * timer) +{ + time_t epoch_time; + /* The time() function return uptime on WICED platform. */ + epoch_time = time(NULL) + WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME; + + if (timer != NULL) { + *timer = epoch_time; + } + return epoch_time; +} +#endif /* WOLFSSL_WICED */ + +#ifdef WOLFSSL_TELIT_M2MB + time_t m2mb_xtime(time_t * timer) + { + time_t myTime = 0; + INT32 fd = m2mb_rtc_open("/dev/rtc0", 0); + if (fd != -1) { + M2MB_RTC_TIMEVAL_T timeval; + + m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval); + + myTime = timeval.sec; + + m2mb_rtc_close(fd); + } + return myTime; + } + #ifdef WOLFSSL_TLS13 + time_t m2mb_xtime_ms(time_t * timer) + { + time_t myTime = 0; + INT32 fd = m2mb_rtc_open("/dev/rtc0", 0); + if (fd != -1) { + M2MB_RTC_TIMEVAL_T timeval; + + m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval); + + myTime = timeval.sec + timeval.msec; + + m2mb_rtc_close(fd); + } + return myTime; + } + #endif /* WOLFSSL_TLS13 */ + #ifndef NO_CRYPT_BENCHMARK + double m2mb_xtime_bench(int reset) + { + double myTime = 0; + INT32 fd = m2mb_rtc_open("/dev/rtc0", 0); + if (fd != -1) { + M2MB_RTC_TIMEVAL_T timeval; + + m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval); + + myTime = (double)timeval.sec + ((double)timeval.msec / 1000); + + m2mb_rtc_close(fd); + } + return myTime; + } + #endif /* !NO_CRYPT_BENCHMARK */ +#endif /* WOLFSSL_TELIT_M2MB */ + +#endif /* !NO_ASN_TIME */ + +#ifndef WOLFSSL_LEANPSK +char* mystrnstr(const char* s1, const char* s2, unsigned int n) +{ + unsigned int s2_len = (unsigned int)XSTRLEN(s2); + + if (s2_len == 0) + return (char*)s1; + + while (n >= s2_len && s1[0]) { + if (s1[0] == s2[0]) + if (XMEMCMP(s1, s2, s2_len) == 0) + return (char*)s1; + s1++; + n--; + } + + return NULL; +} +#endif + +/* custom memory wrappers */ +#ifdef WOLFSSL_NUCLEUS_1_2 + + /* system memory pool */ + extern NU_MEMORY_POOL System_Memory; + + void* nucleus_malloc(unsigned long size, void* heap, int type) + { + STATUS status; + void* stack_ptr; + + status = NU_Allocate_Memory(&System_Memory, &stack_ptr, size, + NU_NO_SUSPEND); + if (status == NU_SUCCESS) { + return 0; + } else { + return stack_ptr; + } + } + + void* nucleus_realloc(void* ptr, unsigned long size, void* heap, int type) + { + DM_HEADER* old_header; + word32 old_size, copy_size; + void* new_mem; + + /* if ptr is NULL, behave like malloc */ + new_mem = nucleus_malloc(size, NULL, 0); + if (new_mem == 0 || ptr == 0) { + return new_mem; + } + + /* calculate old memory block size */ + /* mem pointers stored in block headers (ref dm_defs.h) */ + old_header = (DM_HEADER*) ((byte*)ptr - DM_OVERHEAD); + old_size = (byte*)old_header->dm_next_memory - (byte*)ptr; + + /* copy old to new */ + if (old_size < size) { + copy_size = old_size; + } else { + copy_size = size; + } + XMEMCPY(new_mem, ptr, copy_size); + + /* free old */ + nucleus_free(ptr, NULL, 0); + + return new_mem; + } + + void nucleus_free(void* ptr, void* heap, int type) + { + if (ptr != NULL) + NU_Deallocate_Memory(ptr); + } + +#endif /* WOLFSSL_NUCLEUS_1_2 */ + +#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) #include /* initialize and Mutex for TI Crypt Engine */ #include /* md5, sha1, sha224, sha256 */ #endif + +#if defined(WOLFSSL_CRYPTOCELL) + #define WOLFSSL_CRYPTOCELL_C + #include /* CC310, RTC and RNG */ + #if !defined(NO_SHA256) + #define WOLFSSL_CRYPTOCELL_HASH_C + #include /* sha256 */ + #endif +#endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfcrypt_first.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfcrypt_first.c new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfcrypt_last.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfcrypt_last.c new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfevent.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfevent.c new file mode 100644 index 000000000..20848cddc --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfevent.c @@ -0,0 +1,283 @@ +/* wolfevent.c + * + * Copyright (C) 2006-2020 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 HAVE_WOLF_EVENT + +#include +#include +#include + +#include + + +int wolfEvent_Init(WOLF_EVENT* event, WOLF_EVENT_TYPE type, void* context) +{ + if (event == NULL) { + return BAD_FUNC_ARG; + } + + if (event->state == WOLF_EVENT_STATE_PENDING) { + WOLFSSL_MSG("Event already pending!"); + return BAD_COND_E; + } + + XMEMSET(event, 0, sizeof(WOLF_EVENT)); + event->type = type; + event->context = context; + + return 0; +} + +int wolfEvent_Poll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags) +{ + int ret = BAD_COND_E; + + /* Check hardware */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (event->type >= WOLF_EVENT_TYPE_ASYNC_FIRST && + event->type <= WOLF_EVENT_TYPE_ASYNC_LAST) + { + ret = wolfAsync_EventPoll(event, flags); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +int wolfEventQueue_Init(WOLF_EVENT_QUEUE* queue) +{ + int ret = 0; + + if (queue == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(queue, 0, sizeof(WOLF_EVENT_QUEUE)); +#ifndef SINGLE_THREADED + ret = wc_InitMutex(&queue->lock); +#endif + return ret; +} + + +int wolfEventQueue_Push(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) +{ + int ret; + + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + if ((ret = wc_LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + ret = wolfEventQueue_Add(queue, event); + +#ifndef SINGLE_THREADED + wc_UnLockMutex(&queue->lock); +#endif + + return ret; +} + +int wolfEventQueue_Pop(WOLF_EVENT_QUEUE* queue, WOLF_EVENT** event) +{ + int ret = 0; + + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + /* In single threaded mode "event_queue.lock" doesn't exist */ + if ((ret = wc_LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + /* Pop first item off queue */ + *event = queue->head; + ret = wolfEventQueue_Remove(queue, *event); + +#ifndef SINGLE_THREADED + wc_UnLockMutex(&queue->lock); +#endif + + 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) +{ + int ret = 0; + + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + + if (event == queue->head && event == queue->tail) { + queue->head = NULL; + queue->tail = NULL; + } + else if (event == queue->head) { + queue->head = event->next; + queue->head->prev = NULL; + } + else if (event == queue->tail) { + queue->tail = event->prev; + queue->tail->next = NULL; + } + else { + WOLF_EVENT* next = event->next; + WOLF_EVENT* prev = event->prev; + next->prev = prev; + prev->next = next; + } + queue->count--; + + return ret; +} + +int wolfEventQueue_Poll(WOLF_EVENT_QUEUE* queue, void* context_filter, + WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags, int* eventCount) +{ + WOLF_EVENT* event; + int ret = 0, count = 0; + + if (queue == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + /* In single threaded mode "event_queue.lock" doesn't exist */ + if ((ret = wc_LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + /* itterate event queue */ + for (event = queue->head; event != NULL; event = event->next) + { + /* optional filter based on context */ + if (context_filter == NULL || event->context == context_filter) { + + /* poll event */ + ret = wolfEvent_Poll(event, flags); + if (ret < 0) break; /* exit for */ + + /* If event is done then process */ + if (event->state == WOLF_EVENT_STATE_DONE) { + /* remove from queue */ + ret = wolfEventQueue_Remove(queue, event); + if (ret < 0) break; /* exit for */ + + /* return pointer in 'events' arg */ + if (events) { + events[count] = event; /* return pointer */ + } + count++; + + /* check to make sure our event list isn't full */ + if (events && count >= maxEvents) { + break; /* exit for */ + } + } + } + } + +#ifndef SINGLE_THREADED + wc_UnLockMutex(&queue->lock); +#endif + + /* return number of properly populated events */ + if (eventCount) { + *eventCount = count; + } + + return ret; +} + +int wolfEventQueue_Count(WOLF_EVENT_QUEUE* queue) +{ + int ret; + + if (queue == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + /* In single threaded mode "event_queue.lock" doesn't exist */ + if ((ret = wc_LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + ret = queue->count; + +#ifndef SINGLE_THREADED + wc_UnLockMutex(&queue->lock); +#endif + + return ret; +} + +void wolfEventQueue_Free(WOLF_EVENT_QUEUE* queue) +{ + if (queue) { + #ifndef SINGLE_THREADED + wc_FreeMutex(&queue->lock); + #endif + } +} + +#endif /* HAVE_WOLF_EVENT */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfmath.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfmath.c new file mode 100644 index 000000000..0c17a0a27 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/wolfmath.c @@ -0,0 +1,381 @@ +/* wolfmath.c + * + * Copyright (C) 2006-2020 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 + */ + + +/* common functions for either math library */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +/* in case user set USE_FAST_MATH there */ +#include + +#include + +#include +#include + +#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 + + +#if !defined(WOLFSSL_SP_MATH) +int get_digit_count(mp_int* a) +{ + if (a == NULL) + return 0; + + return a->used; +} +#endif + +mp_digit get_digit(mp_int* a, int n) +{ + if (a == NULL) + return 0; + + return (n >= a->used || n < 0) ? 0 : a->dp[n]; +} + +/* Conditionally copy a into b. Performed in constant time. + * + * a MP integer to copy. + * copy On 1, copy a into b. on 0 leave b unchanged. + * b MP integer to copy into. + * returns BAD_FUNC_ARG when a or b is NULL, MEMORY_E when growing b fails and + * MP_OKAY otherwise. + */ +int mp_cond_copy(mp_int* a, int copy, mp_int* b) +{ + int err = MP_OKAY; + int i; + mp_digit mask = (mp_digit)0 - copy; + + if (a == NULL || b == NULL) + err = BAD_FUNC_ARG; + + /* Ensure b has enough space to copy a into */ + if (err == MP_OKAY) + err = mp_grow(b, a->used + 1); + if (err == MP_OKAY) { + /* When mask 0, b is unchanged2 + * When mask all set, b ^ b ^ a = a + */ + /* Conditionaly copy all digits and then number of used diigits. + * get_digit() returns 0 when index greater than available digit. + */ + for (i = 0; i < a->used; i++) { + b->dp[i] ^= (get_digit(a, i) ^ get_digit(b, i)) & mask; + } + for (; i < b->used; i++) { + b->dp[i] ^= (get_digit(a, i) ^ get_digit(b, i)) & mask; + } + b->used ^= (a->used ^ b->used) & (int)mask; + } + + return err; +} + +#ifndef WC_NO_RNG +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 = 0; + int cnt = digits * sizeof(mp_digit); +#if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH) + int i; +#endif + + if (rng == NULL) { + ret = MISSING_RNG_E; + } + else if (a == NULL) { + ret = BAD_FUNC_ARG; + } + +#if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH) + /* allocate space for digits */ + if (ret == MP_OKAY) { + ret = mp_set_bit(a, digits * DIGIT_BIT - 1); + } +#else +#if defined(WOLFSSL_SP_MATH) + if ((ret == MP_OKAY) && (digits > SP_INT_DIGITS)) +#else + if ((ret == MP_OKAY) && (digits > FP_SIZE)) +#endif + { + ret = BAD_FUNC_ARG; + } + if (ret == MP_OKAY) { + a->used = digits; + } +#endif + /* fill the data with random bytes */ + if (ret == MP_OKAY) { + ret = wc_RNG_GenerateBlock(rng, (byte*)a->dp, cnt); + } + if (ret == MP_OKAY) { +#if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH) + /* Mask down each digit to only bits used */ + for (i = 0; i < a->used; i++) { + a->dp[i] &= MP_MASK; + } +#endif + /* ensure top digit is not zero */ + while ((ret == MP_OKAY) && (a->dp[a->used - 1] == 0)) { + ret = get_rand_digit(rng, &a->dp[a->used - 1]); +#if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH) + a->dp[a->used - 1] &= MP_MASK; +#endif + } + } + + return ret; +} +#endif /* WC_RSA_BLINDING */ +#endif + +/* export an mp_int as unsigned char or hex string + * encType is WC_TYPE_UNSIGNED_BIN or WC_TYPE_HEX_STR + * return MP_OKAY on success */ +int wc_export_int(mp_int* mp, byte* buf, word32* len, word32 keySz, + int encType) +{ + int err; + + if (mp == NULL) + return BAD_FUNC_ARG; + + /* check buffer size */ + if (*len < keySz) { + *len = keySz; + return BUFFER_E; + } + + *len = keySz; + XMEMSET(buf, 0, *len); + + if (encType == WC_TYPE_HEX_STR) { + #ifdef WC_MP_TO_RADIX + err = mp_tohex(mp, (char*)buf); + #else + err = NOT_COMPILED_IN; + #endif + } + else { + err = mp_to_unsigned_bin(mp, buf + (keySz - mp_unsigned_bin_size(mp))); + } + + return err; +} + + +#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; + } +} + +/* sz: make sure the buffer is at least that size and zero padded. + * A `sz == 0` will use the size of `src`. + * The calulcates sz is stored into dst->len in `wc_bigint_alloc`. + */ +int wc_mp_to_bigint_sz(mp_int* src, WC_BIGINT* dst, word32 sz) +{ + int err; + word32 x, y; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + /* get size of source */ + x = mp_unsigned_bin_size(src); + if (sz < x) + sz = x; + + /* make sure destination is allocated and large enough */ + err = wc_bigint_alloc(dst, sz); + if (err == MP_OKAY) { + + /* leading zero pad */ + y = sz - x; + XMEMSET(dst->buf, 0, y); + + /* export src as unsigned bin to destination buf */ + err = mp_to_unsigned_bin(src, dst->buf + y); + } + + return err; +} + +int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst) +{ + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + return wc_mp_to_bigint_sz(src, dst, 0); +} + +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/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/README.md b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/README.md new file mode 100644 index 000000000..bcf877f9a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/README.md @@ -0,0 +1,60 @@ +# wolfCrypt Test + +Tool for performing cryptographic algorithm testing. + +## Example Output + +Run on Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz. + +```sh +./configure --enable-intelasm --enable-aesni --enable-sp --enable-sp-asm && make + +./wolfcrypt/test/testwolfcrypt +------------------------------------------------------------------------------ + wolfSSL version 4.0.0 +------------------------------------------------------------------------------ +error test passed! +MEMORY test passed! +base64 test passed! +asn test passed! +MD5 test passed! +SHA test passed! +SHA-224 test passed! +SHA-256 test passed! +SHA-384 test passed! +SHA-512 test passed! +SHA-3 test passed! +Hash test passed! +HMAC-MD5 test passed! +HMAC-SHA test passed! +HMAC-SHA224 test passed! +HMAC-SHA256 test passed! +HMAC-SHA384 test passed! +HMAC-SHA512 test passed! +HMAC-SHA3 test passed! +GMAC test passed! +Chacha test passed! +POLY1305 test passed! +ChaCha20-Poly1305 AEAD test passed! +AES test passed! +AES192 test passed! +AES256 test passed! +AES-GCM test passed! +RANDOM test passed! +RSA test passed! +DH test passed! +ECC test passed! +logging test passed! +mutex test passed! +memcb test passed! +Test complete +``` + + +## Windows Visual Studio + +For building wolfCrypt test project in Visual Studio open the `test.sln`. For newer Visual Studio version it may prompt for a one-way upgrade. Then you may have to right-click on the solution and choose `Retarget solution` to update the project files for your Visual Studio version. + +If you see an error about `rc.exe` then you'll need to update the "Target Platform Version". You can do this by right-clicking on the test project -> General -> "Target Platform Version" and changing to 8.1 (needs to match the wolfssl library project). + +This solution includes the wolfSSL library project at `wolfssl.vcxproj` and will compile the library, then the test project. diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/include.am b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/include.am index 950d7c601..b2fc302c1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/include.am @@ -1,11 +1,18 @@ # vim:ft=automake # All paths should be given relative to the root +if BUILD_WOLFCRYPT_TESTS +noinst_PROGRAMS+= wolfcrypt/test/testwolfcrypt +if BUILD_CRYPTONLY +check_PROGRAMS+= wolfcrypt/test/testwolfcrypt +endif noinst_PROGRAMS+= wolfcrypt/test/testwolfcrypt wolfcrypt_test_testwolfcrypt_SOURCES = wolfcrypt/test/test.c -wolfcrypt_test_testwolfcrypt_LDADD = src/libwolfssl.la +wolfcrypt_test_testwolfcrypt_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) wolfcrypt_test_testwolfcrypt_DEPENDENCIES = src/libwolfssl.la noinst_HEADERS += wolfcrypt/test/test.h +endif EXTRA_DIST += wolfcrypt/test/test.sln EXTRA_DIST += wolfcrypt/test/test.vcproj +EXTRA_DIST += wolfcrypt/test/README.md DISTCLEANFILES+= wolfcrypt/test/.libs/testwolfcrypt diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.c index cf5dbe56e..399a29b75 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.c +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.c @@ -1,8 +1,8 @@ /* test.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,22 +16,111 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifdef HAVE_CONFIG_H #include #endif -#include - -#ifdef XMALLOC_USER - #include /* we're using malloc / free direct here */ +#ifndef WOLFSSL_USER_SETTINGS + #include #endif +#include +#include +#include #ifndef NO_CRYPT_TEST -#ifdef WOLFSSL_TEST_CERT +/* 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 USE_FLAT_TEST_H + #include "test.h" +#else + #include "wolfcrypt/test/test.h" +#endif + +/* printf mappings */ +#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #include + #include + /* see wc_port.h for fio.h and nio.h includes */ +#elif defined(FREESCALE_KSDK_BM) + #include "fsl_debug_console.h" + #undef printf + #define printf PRINTF +#elif defined(WOLFSSL_APACHE_MYNEWT) + #include + #include + #include "sysinit/sysinit.h" + #include "os/os.h" + #ifdef ARCH_sim + #include "mcu/mcu_sim.h" + #endif + #include "os/os_time.h" +#elif defined(WOLFSSL_ESPIDF) + #include + #include +#elif defined(WOLFSSL_ZEPHYR) + #include + + #define printf printk +#elif defined(MICRIUM) + #include + void BSP_Ser_Printf (CPU_CHAR* format, ...); + #undef printf + #define printf BSP_Ser_Printf +#elif defined(WOLFSSL_PB) + #include + int wolfssl_pb_print(const char*, ...); + #undef printf + #define printf wolfssl_pb_print +#elif defined(WOLFSSL_TELIT_M2MB) + #include "wolfssl/wolfcrypt/wc_port.h" /* for m2mb headers */ + #include "m2m_log.h" /* for M2M_LOG_INFO - not standard API */ + /* remap printf */ + #undef printf + #define printf M2M_LOG_INFO + /* OS requires occasional sleep() */ + #ifndef TEST_SLEEP_MS + #define TEST_SLEEP_MS 50 + #endif + #define TEST_SLEEP() m2mb_os_taskSleep(M2MB_OS_MS2TICKS(TEST_SLEEP_MS)) + /* don't use file system for these tests, since ./certs dir isn't loaded */ + #undef NO_FILESYSTEM + #define NO_FILESYSTEM +#elif defined(THREADX) && !defined(WOLFSSL_WICED) && !defined(THREADX_NO_DC_PRINTF) + /* since just testing, use THREADX log printf instead */ + int dc_log_printf(char*, ...); + #undef printf + #define printf dc_log_printf +#else + #ifdef XMALLOC_USER + #include /* we're using malloc / free direct here */ + #endif + #ifndef STRING_USER + #include + #endif + + /* enable way for customer to override test/bench printf */ + #ifdef XPRINTF + #undef printf + #define printf XPRINTF + #endif +#endif + +#include +#include +#include +#include +#if defined(WOLFSSL_TEST_CERT) || defined(ASN_BER_TO_DER) #include #else #include @@ -43,16 +132,25 @@ #include #include #include -#include +#if defined(WC_NO_RNG) + #include +#else + #include +#endif #include +#include #include #include #include +#include +#include #include #include #include #include #include +#include +#include #include #include #include @@ -69,9 +167,18 @@ #ifdef HAVE_ED25519 #include #endif -#ifdef HAVE_BLAKE2 +#ifdef HAVE_CURVE448 + #include +#endif +#ifdef HAVE_ED448 + #include +#endif +#if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) #include #endif +#ifdef WOLFSSL_SHA3 + #include +#endif #ifdef HAVE_LIBZ #include #endif @@ -81,6 +188,27 @@ #ifdef HAVE_FIPS #include #endif +#ifdef HAVE_SELFTEST + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + #include +#endif +#ifdef WOLFSSL_IMX6_CAAM_BLOB + #include +#endif +#ifdef WOLF_CRYPTO_CB + #include + #ifdef HAVE_INTEL_QA_SYNC + #include + #endif + #ifdef HAVE_CAVIUM_OCTEON_SYNC + #include + #endif +#endif #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ @@ -88,59 +216,57 @@ #endif #ifdef OPENSSL_EXTRA + #ifndef WOLFCRYPT_ONLY #include + #endif #include #include + #include #include #endif - -#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 */ - #if defined(WOLFSSL_MDK_ARM) - #include "cert_data.h" - /* use certs_test.c for initial data, so other - commands can share the data. */ - #else - #include +#if defined(NO_FILESYSTEM) + #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ + !defined(USE_CERT_BUFFERS_3072) && !defined(USE_CERT_BUFFERS_4096) + #define USE_CERT_BUFFERS_2048 + #endif + #if !defined(USE_CERT_BUFFERS_256) + #define USE_CERT_BUFFERS_256 #endif #endif -#if defined(WOLFSSL_MDK_ARM) - #include - #include - extern FILE * wolfSSL_fopen(const char *fname, const char *mode) ; - #define fopen wolfSSL_fopen +#if defined(WOLFSSL_CERT_GEN) && (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) + #define ENABLE_ECC384_CERT_GEN_TEST #endif +#include + #ifdef HAVE_NTRU - #include "ntru_crypto.h" -#endif -#ifdef HAVE_CAVIUM - #include "cavium_sysdep.h" - #include "cavium_common.h" - #include "cavium_ioctl.h" + #include "libntruencrypt/ntru_crypto.h" #endif -#ifdef FREESCALE_MQX - #include - #include - #include +#ifdef WOLFSSL_STATIC_MEMORY + static WOLFSSL_HEAP_HINT* HEAP_HINT; #else - #include + #define HEAP_HINT NULL +#endif /* WOLFSSL_STATIC_MEMORY */ + +/* these cases do not have intermediate hashing support */ +#if (defined(WOLFSSL_AFALG_XILINX_SHA3) && !defined(WOLFSSL_AFALG_HASH_KEEP)) \ + && !defined(WOLFSSL_XILINX_CRYPT) + #define NO_INTM_HASH_TEST #endif - -#ifdef THREADX - /* since just testing, use THREADX log printf instead */ - int dc_log_printf(char*, ...); - #undef printf - #define printf dc_log_printf +#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_MULTI_ATTRIB) +static void initDefaultName(void); #endif -#include "wolfcrypt/test/test.h" +/* for async devices */ +static int devId = INVALID_DEVID; +#ifdef HAVE_WNR + const char* wnrConfigFile = "wnr-example.conf"; +#endif typedef struct testVector { const char* input; @@ -149,20 +275,30 @@ typedef struct testVector { size_t outLen; } testVector; +int error_test(void); +int base64_test(void); +int base16_test(void); +int asn_test(void); int md2_test(void); int md5_test(void); int md4_test(void); int sha_test(void); +int sha224_test(void); int sha256_test(void); int sha512_test(void); int sha384_test(void); +int sha3_test(void); +int shake256_test(void); +int hash_test(void); int hmac_md5_test(void); int hmac_sha_test(void); +int hmac_sha224_test(void); int hmac_sha256_test(void); int hmac_sha384_test(void); int hmac_sha512_test(void); -int hmac_blake2b_test(void); +int hmac_sha3_test(void); int hkdf_test(void); +int x963kdf_test(void); int arc4_test(void); int hc128_test(void); int rabbit_test(void); @@ -171,26 +307,49 @@ 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 aesofb_test(void); +int cmac_test(void); int poly1305_test(void); int aesgcm_test(void); +int aesgcm_default_test(void); int gmac_test(void); int aesccm_test(void); +int aeskeywrap_test(void); int camellia_test(void); +int rsa_no_pad_test(void); int rsa_test(void); int dh_test(void); int dsa_test(void); +int srp_test(void); +#ifndef WC_NO_RNG int random_test(void); +#endif /* WC_NO_RNG */ int pwdbased_test(void); int ripemd_test(void); +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) int openssl_test(void); /* test mini api */ + +int openssl_pkey_test(void); +int openssl_pkey0_test(void); +int openssl_pkey1_test(void); +int openSSL_evpMD_test(void); +int openssl_evpSig_test(void); +#endif + int pbkdf1_test(void); int pkcs12_test(void); int pbkdf2_test(void); +int scrypt_test(void); #ifdef HAVE_ECC int ecc_test(void); #ifdef HAVE_ECC_ENCRYPT int ecc_encrypt_test(void); #endif + #ifdef USE_CERT_BUFFERS_256 + int ecc_test_buffers(void); + #endif #endif #ifdef HAVE_CURVE25519 int curve25519_test(void); @@ -198,36 +357,104 @@ int pbkdf2_test(void); #ifdef HAVE_ED25519 int ed25519_test(void); #endif +#ifdef HAVE_CURVE448 + int curve448_test(void); +#endif +#ifdef HAVE_ED448 + int ed448_test(void); +#endif #ifdef HAVE_BLAKE2 int blake2b_test(void); #endif +#ifdef HAVE_BLAKE2S + int blake2s_test(void); +#endif #ifdef HAVE_LIBZ int compress_test(void); #endif #ifdef HAVE_PKCS7 - int pkcs7enveloped_test(void); + #ifndef NO_PKCS7_ENCRYPTED_DATA + int pkcs7encrypted_test(void); + #endif + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + int pkcs7compressed_test(void); + #endif int pkcs7signed_test(void); + int pkcs7enveloped_test(void); + #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + int pkcs7authenveloped_test(void); + #endif + #ifndef NO_AES + int pkcs7callback_test(byte* cert, word32 certSz, byte* key, + word32 keySz); + #endif +#endif +#if !defined(NO_ASN_TIME) && !defined(NO_RSA) && defined(WOLFSSL_TEST_CERT) && \ + !defined(NO_FILESYSTEM) +int cert_test(void); +#endif +#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) && \ + !defined(NO_FILESYSTEM) +int certext_test(void); +#endif +#if defined(WOLFSSL_CERT_GEN_CACHE) && defined(WOLFSSL_TEST_CERT) && \ + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) +int decodedCertCache_test(void); +#endif +#ifdef HAVE_IDEA +int idea_test(void); +#endif +int memory_test(void); +#ifdef HAVE_VALGRIND +int mp_test(void); +#endif +#if defined(WOLFSSL_PUBLIC_MP) && defined(WOLFSSL_KEY_GEN) +int prime_test(void); +#endif +#ifdef ASN_BER_TO_DER +int berder_test(void); +#endif +int logging_test(void); +int mutex_test(void); +#if defined(USE_WOLFSSL_MEMORY) && !defined(FREERTOS) +int memcb_test(void); +#endif +#ifdef WOLFSSL_IMX6_CAAM_BLOB +int blob_test(void); #endif +#ifdef WOLF_CRYPTO_CB +int cryptocb_test(void); +#endif +#ifdef WOLFSSL_CERT_PIV +int certpiv_test(void); +#endif -/* General big buffer size for many tests. */ +/* General big buffer size for many tests. */ #define FOURK_BUF 4096 -static int err_sys(const char* msg, int es) +#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); - return -1; /* error state */ + + 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 @@ -245,90 +472,268 @@ static void myFipsCb(int ok, int err, const char* hash) #endif /* HAVE_FIPS */ +#ifdef WOLFSSL_STATIC_MEMORY + #ifdef BENCH_EMBEDDED + static byte gTestMemory[14000]; + #elif defined(WOLFSSL_CERT_EXT) + static byte gTestMemory[140000]; + #elif defined(USE_FAST_MATH) && !defined(ALT_ECC_SIZE) + static byte gTestMemory[160000]; + #else + static byte gTestMemory[80000]; + #endif +#endif -int wolfcrypt_test(void* args) +#ifdef WOLFSSL_PB +int wolfssl_pb_print(const char* msg, ...) { - int ret = 0; + int ret; + va_list args; + char tmpBuf[80]; - ((func_args*)args)->return_code = -1; /* error state */ + va_start(args, msg); + ret = vsprint(tmpBuf, msg, args); + va_end(args); + + fnDumpStringToSystemLog(tmpBuf); + + return ret; +} +#endif /* WOLFSSL_PB */ + +/* optional macro to add sleep between tests */ +#ifdef TEST_SLEEP + #include /* for var args */ + static WC_INLINE void test_pass(const char* fmt, ...) + { + va_list args; + va_start(args, fmt); + printf(fmt, args); + va_end(args); + TEST_SLEEP(); + } +#else + /* redirect to printf */ + #define test_pass printf + /* stub the sleep macro */ + #define TEST_SLEEP() +#endif + +#ifdef HAVE_STACK_SIZE +THREAD_RETURN WOLFSSL_THREAD wolfcrypt_test(void* args) +#else +int wolfcrypt_test(void* args) +#endif +{ + int ret; + + printf("------------------------------------------------------------------------------\n"); + printf(" wolfSSL version %s\n", LIBWOLFSSL_VERSION_STRING); + printf("------------------------------------------------------------------------------\n"); + + if (args) + ((func_args*)args)->return_code = -1; /* error state */ + +#ifdef WOLFSSL_STATIC_MEMORY + if (wc_LoadStaticMemory(&HEAP_HINT, gTestMemory, sizeof(gTestMemory), + WOLFMEM_GENERAL, 1) != 0) { + printf("unable to load static memory"); + return(EXIT_FAILURE); + } +#endif + +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) + wolfSSL_Debugging_ON(); +#endif + +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + wc_SetLoggingHeap(HEAP_HINT); +#endif #ifdef HAVE_FIPS wolfCrypt_SetCb_fips(myFipsCb); #endif #if !defined(NO_BIG_INT) - if (CheckCtcSettings() != 1) - return err_sys("Build vs runtime math mismatch\n", -1234); + if (CheckCtcSettings() != 1) { + printf("Sizeof mismatch (build) %x != (run) %x\n", + CTC_SETTINGS, CheckRunTimeSettings()); + 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 */ +#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_MULTI_ATTRIB) +initDefaultName(); +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevOpen(&devId); + if (ret < 0) { + printf("Async device open failed\nRunning without async\n"); + } +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifdef WOLF_CRYPTO_CB +#ifdef HAVE_INTEL_QA_SYNC + devId = wc_CryptoCb_InitIntelQa(); + if (INVALID_DEVID == devId) { + printf("Couldn't init the Intel QA\n"); + } +#endif +#ifdef HAVE_CAVIUM_OCTEON_SYNC + devId = wc_CryptoCb_InitOcteon(); + if (INVALID_DEVID == devId) { + printf("Couldn't init the Cavium Octeon\n"); + } +#endif +#endif + +#ifdef HAVE_SELFTEST + if ( (ret = wolfCrypt_SelfTest()) != 0) + return err_sys("CAVP selftest failed!\n", ret); + else + test_pass("CAVP selftest passed!\n"); +#endif + + if ( (ret = error_test()) != 0) + return err_sys("error test failed!\n", ret); + else + test_pass("error test passed!\n"); + + if ( (ret = memory_test()) != 0) + return err_sys("MEMORY test failed!\n", ret); + else + test_pass("MEMORY test passed!\n"); + +#ifndef NO_CODING + if ( (ret = base64_test()) != 0) + return err_sys("base64 test failed!\n", ret); + else + test_pass("base64 test passed!\n"); +#ifdef WOLFSSL_BASE16 + if ( (ret = base16_test()) != 0) + return err_sys("base16 test failed!\n", ret); + else + test_pass("base16 test passed!\n"); +#endif +#endif /* !NO_CODING */ + +#ifndef NO_ASN + if ( (ret = asn_test()) != 0) + return err_sys("asn test failed!\n", ret); + else + test_pass("asn test passed!\n"); +#endif + +#ifndef WC_NO_RNG + if ( (ret = random_test()) != 0) + return err_sys("RANDOM test failed!\n", ret); + else + test_pass("RANDOM test passed!\n"); +#endif /* WC_NO_RNG */ #ifndef NO_MD5 if ( (ret = md5_test()) != 0) return err_sys("MD5 test failed!\n", ret); else - printf( "MD5 test passed!\n"); + test_pass("MD5 test passed!\n"); #endif #ifdef WOLFSSL_MD2 if ( (ret = md2_test()) != 0) return err_sys("MD2 test failed!\n", ret); else - printf( "MD2 test passed!\n"); + test_pass("MD2 test passed!\n"); #endif #ifndef NO_MD4 if ( (ret = md4_test()) != 0) return err_sys("MD4 test failed!\n", ret); else - printf( "MD4 test passed!\n"); + test_pass("MD4 test passed!\n"); #endif #ifndef NO_SHA if ( (ret = sha_test()) != 0) return err_sys("SHA test failed!\n", ret); else - printf( "SHA test passed!\n"); + test_pass("SHA test passed!\n"); +#endif + +#ifdef WOLFSSL_SHA224 + if ( (ret = sha224_test()) != 0) + return err_sys("SHA-224 test failed!\n", ret); + else + test_pass("SHA-224 test passed!\n"); #endif #ifndef NO_SHA256 if ( (ret = sha256_test()) != 0) return err_sys("SHA-256 test failed!\n", ret); else - printf( "SHA-256 test passed!\n"); + test_pass("SHA-256 test passed!\n"); #endif #ifdef WOLFSSL_SHA384 if ( (ret = sha384_test()) != 0) return err_sys("SHA-384 test failed!\n", ret); else - printf( "SHA-384 test passed!\n"); + test_pass("SHA-384 test passed!\n"); #endif #ifdef WOLFSSL_SHA512 if ( (ret = sha512_test()) != 0) return err_sys("SHA-512 test failed!\n", ret); else - printf( "SHA-512 test passed!\n"); + test_pass("SHA-512 test passed!\n"); #endif +#ifdef WOLFSSL_SHA3 + if ( (ret = sha3_test()) != 0) + return err_sys("SHA-3 test failed!\n", ret); + else + test_pass("SHA-3 test passed!\n"); +#endif + +#ifdef WOLFSSL_SHAKE256 + if ( (ret = shake256_test()) != 0) + return err_sys("SHAKE256 test failed!\n", ret); + else + test_pass("SHAKE256 test passed!\n"); +#endif + + if ( (ret = hash_test()) != 0) + return err_sys("Hash test failed!\n", ret); + else + test_pass("Hash test passed!\n"); + #ifdef WOLFSSL_RIPEMD if ( (ret = ripemd_test()) != 0) return err_sys("RIPEMD test failed!\n", ret); else - printf( "RIPEMD test passed!\n"); + test_pass("RIPEMD test passed!\n"); #endif #ifdef HAVE_BLAKE2 if ( (ret = blake2b_test()) != 0) return err_sys("BLAKE2b test failed!\n", ret); else - printf( "BLAKE2b test passed!\n"); + test_pass("BLAKE2b test passed!\n"); +#endif +#ifdef HAVE_BLAKE2S + if ( (ret = blake2s_test()) != 0) + return err_sys("BLAKE2s test failed!\n", ret); + else + test_pass("BLAKE2s test passed!\n"); #endif #ifndef NO_HMAC @@ -336,134 +741,185 @@ int wolfcrypt_test(void* args) if ( (ret = hmac_md5_test()) != 0) return err_sys("HMAC-MD5 test failed!\n", ret); else - printf( "HMAC-MD5 test passed!\n"); + test_pass("HMAC-MD5 test passed!\n"); #endif #ifndef NO_SHA if ( (ret = hmac_sha_test()) != 0) return err_sys("HMAC-SHA test failed!\n", ret); else - printf( "HMAC-SHA test passed!\n"); + test_pass("HMAC-SHA test passed!\n"); + #endif + + #ifdef WOLFSSL_SHA224 + if ( (ret = hmac_sha224_test()) != 0) + return err_sys("HMAC-SHA224 test failed!\n", ret); + else + test_pass("HMAC-SHA224 test passed!\n"); #endif #ifndef NO_SHA256 if ( (ret = hmac_sha256_test()) != 0) return err_sys("HMAC-SHA256 test failed!\n", ret); else - printf( "HMAC-SHA256 test passed!\n"); + test_pass("HMAC-SHA256 test passed!\n"); #endif #ifdef WOLFSSL_SHA384 if ( (ret = hmac_sha384_test()) != 0) return err_sys("HMAC-SHA384 test failed!\n", ret); else - printf( "HMAC-SHA384 test passed!\n"); + test_pass("HMAC-SHA384 test passed!\n"); #endif #ifdef WOLFSSL_SHA512 if ( (ret = hmac_sha512_test()) != 0) return err_sys("HMAC-SHA512 test failed!\n", ret); else - printf( "HMAC-SHA512 test passed!\n"); + test_pass("HMAC-SHA512 test passed!\n"); #endif - #ifdef HAVE_BLAKE2 - if ( (ret = hmac_blake2b_test()) != 0) - return err_sys("HMAC-BLAKE2 test failed!\n", ret); + #if !defined(NO_HMAC) && defined(WOLFSSL_SHA3) && \ + !defined(WOLFSSL_NOSHA3_224) && !defined(WOLFSSL_NOSHA3_256) && \ + !defined(WOLFSSL_NOSHA3_384) && !defined(WOLFSSL_NOSHA3_512) + if ( (ret = hmac_sha3_test()) != 0) + return err_sys("HMAC-SHA3 test failed!\n", ret); else - printf( "HMAC-BLAKE2 test passed!\n"); + test_pass("HMAC-SHA3 test passed!\n"); #endif #ifdef HAVE_HKDF if ( (ret = hkdf_test()) != 0) return err_sys("HMAC-KDF test failed!\n", ret); else - printf( "HMAC-KDF test passed!\n"); + test_pass("HMAC-KDF test passed!\n"); #endif +#endif /* !NO_HMAC */ +#if defined(HAVE_X963_KDF) && defined(HAVE_ECC) + if ( (ret = x963kdf_test()) != 0) + return err_sys("X963-KDF test failed!\n", ret); + else + test_pass("X963-KDF test passed!\n"); #endif -#ifdef HAVE_AESGCM +#if defined(HAVE_AESGCM) && defined(WOLFSSL_AES_128) && \ + !defined(WOLFSSL_AFALG_XILINX_AES) && !defined(WOLFSSL_XILINX_CRYPT) if ( (ret = gmac_test()) != 0) - return err_sys("GMAC test passed!\n", ret); + return err_sys("GMAC test failed!\n", ret); else - printf( "GMAC test passed!\n"); + test_pass("GMAC test passed!\n"); #endif #ifndef NO_RC4 if ( (ret = arc4_test()) != 0) return err_sys("ARC4 test failed!\n", ret); else - printf( "ARC4 test passed!\n"); + test_pass("ARC4 test passed!\n"); #endif #ifndef NO_HC128 if ( (ret = hc128_test()) != 0) return err_sys("HC-128 test failed!\n", ret); else - printf( "HC-128 test passed!\n"); + test_pass("HC-128 test passed!\n"); #endif #ifndef NO_RABBIT if ( (ret = rabbit_test()) != 0) return err_sys("Rabbit test failed!\n", ret); else - printf( "Rabbit test passed!\n"); + test_pass("Rabbit test passed!\n"); #endif #ifdef HAVE_CHACHA if ( (ret = chacha_test()) != 0) return err_sys("Chacha test failed!\n", ret); else - printf( "Chacha test passed!\n"); + test_pass("Chacha test passed!\n"); #endif #ifdef HAVE_POLY1305 if ( (ret = poly1305_test()) != 0) return err_sys("POLY1305 test failed!\n", ret); else - printf( "POLY1305 test passed!\n"); + test_pass("POLY1305 test passed!\n"); #endif #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) if ( (ret = chacha20_poly1305_aead_test()) != 0) return err_sys("ChaCha20-Poly1305 AEAD test failed!\n", ret); else - printf( "ChaCha20-Poly1305 AEAD test passed!\n"); + test_pass("ChaCha20-Poly1305 AEAD test passed!\n"); #endif #ifndef NO_DES3 if ( (ret = des_test()) != 0) return err_sys("DES test failed!\n", ret); else - printf( "DES test passed!\n"); + test_pass("DES test passed!\n"); #endif #ifndef NO_DES3 if ( (ret = des3_test()) != 0) return err_sys("DES3 test failed!\n", ret); else - printf( "DES3 test passed!\n"); + test_pass("DES3 test passed!\n"); #endif #ifndef NO_AES if ( (ret = aes_test()) != 0) return err_sys("AES test failed!\n", ret); else - printf( "AES test passed!\n"); + test_pass("AES test passed!\n"); -#ifdef HAVE_AESGCM - if ( (ret = aesgcm_test()) != 0) - return err_sys("AES-GCM test failed!\n", ret); +#ifdef WOLFSSL_AES_192 + if ( (ret = aes192_test()) != 0) + return err_sys("AES192 test failed!\n", ret); else - printf( "AES-GCM test passed!\n"); + test_pass("AES192 test passed!\n"); #endif -#ifdef HAVE_AESCCM +#ifdef WOLFSSL_AES_256 + if ( (ret = aes256_test()) != 0) + return err_sys("AES256 test failed!\n", ret); + else + test_pass("AES256 test passed!\n"); +#endif + +#ifdef WOLFSSL_AES_OFB + if ( (ret = aesofb_test()) != 0) + return err_sys("AES-OFB test failed!\n", ret); + else + test_pass("AESOFB test passed!\n"); +#endif + +#ifdef HAVE_AESGCM + #if !defined(WOLFSSL_AFALG) && !defined(WOLFSSL_DEVCRYPTO) + if ( (ret = aesgcm_test()) != 0) + return err_sys("AES-GCM test failed!\n", ret); + #endif + #if !defined(WOLFSSL_AFALG_XILINX_AES) && !defined(WOLFSSL_XILINX_CRYPT) && \ + !(defined(WOLF_CRYPTO_CB) && \ + (defined(HAVE_INTEL_QA_SYNC) || defined(HAVE_CAVIUM_OCTEON_SYNC))) + if ((ret = aesgcm_default_test()) != 0) { + return err_sys("AES-GCM test failed!\n", ret); + } + #endif + test_pass("AES-GCM test passed!\n"); +#endif + +#if defined(HAVE_AESCCM) && defined(WOLFSSL_AES_128) if ( (ret = aesccm_test()) != 0) return err_sys("AES-CCM test failed!\n", ret); else - printf( "AES-CCM test passed!\n"); + test_pass("AES-CCM test passed!\n"); +#endif +#ifdef HAVE_AES_KEYWRAP + if ( (ret = aeskeywrap_test()) != 0) + return err_sys("AES Key Wrap test failed!\n", ret); + else + test_pass("AES Key Wrap test passed!\n"); #endif #endif @@ -471,159 +927,675 @@ int wolfcrypt_test(void* args) if ( (ret = camellia_test()) != 0) return err_sys("CAMELLIA test failed!\n", ret); else - printf( "CAMELLIA test passed!\n"); + test_pass("CAMELLIA test passed!\n"); #endif - if ( (ret = random_test()) != 0) - return err_sys("RANDOM test failed!\n", ret); +#ifdef HAVE_IDEA + if ( (ret = idea_test()) != 0) + return err_sys("IDEA test failed!\n", ret); else - printf( "RANDOM test passed!\n"); + test_pass("IDEA test passed!\n"); +#endif #ifndef NO_RSA + #ifdef WC_RSA_NO_PADDING + if ( (ret = rsa_no_pad_test()) != 0) + return err_sys("RSA NOPAD test failed!\n", ret); + else + test_pass("RSA NOPAD test passed!\n"); + #endif if ( (ret = rsa_test()) != 0) return err_sys("RSA test failed!\n", ret); else - printf( "RSA test passed!\n"); + test_pass("RSA test passed!\n"); #endif #ifndef NO_DH if ( (ret = dh_test()) != 0) return err_sys("DH test failed!\n", ret); else - printf( "DH test passed!\n"); + test_pass("DH test passed!\n"); #endif #ifndef NO_DSA if ( (ret = dsa_test()) != 0) return err_sys("DSA test failed!\n", ret); else - printf( "DSA test passed!\n"); + test_pass("DSA test passed!\n"); +#endif + +#ifdef WOLFCRYPT_HAVE_SRP + if ( (ret = srp_test()) != 0) + return err_sys("SRP test failed!\n", ret); + else + test_pass("SRP test passed!\n"); #endif #ifndef NO_PWDBASED if ( (ret = pwdbased_test()) != 0) return err_sys("PWDBASED test failed!\n", ret); else - printf( "PWDBASED test passed!\n"); + test_pass("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 - printf( "OPENSSL test passed!\n"); + test_pass("OPENSSL test passed!\n"); + + if ( (ret = openSSL_evpMD_test()) != 0) + return err_sys("OPENSSL (EVP MD) test failed!\n", ret); + else + test_pass("OPENSSL (EVP MD) passed!\n"); + + if ( (ret = openssl_pkey0_test()) != 0) + return err_sys("OPENSSL (PKEY0) test failed!\n", ret); + else + test_pass("OPENSSL (PKEY0) passed!\n"); + + if ( (ret = openssl_pkey1_test()) != 0) + return err_sys("OPENSSL (PKEY1) test failed!\n", ret); + else + test_pass("OPENSSL (PKEY1) passed!\n"); + + if ( (ret = openssl_evpSig_test()) != 0) + return err_sys("OPENSSL (EVP Sign/Verify) test failed!\n", ret); + else + test_pass("OPENSSL (EVP Sign/Verify) passed!\n"); + #endif #ifdef HAVE_ECC if ( (ret = ecc_test()) != 0) return err_sys("ECC test failed!\n", ret); else - printf( "ECC test passed!\n"); - #ifdef HAVE_ECC_ENCRYPT + test_pass("ECC test passed!\n"); + #if defined(HAVE_ECC_ENCRYPT) && defined(WOLFSSL_AES_128) if ( (ret = ecc_encrypt_test()) != 0) return err_sys("ECC Enc test failed!\n", ret); else - printf( "ECC Enc test passed!\n"); + test_pass("ECC Enc test passed!\n"); #endif + #ifdef USE_CERT_BUFFERS_256 + if ( (ret = ecc_test_buffers()) != 0) + return err_sys("ECC buffer test failed!\n", ret); + else + test_pass("ECC buffer test passed!\n"); + #endif +#endif + +#if !defined(NO_ASN_TIME) && !defined(NO_RSA) && defined(WOLFSSL_TEST_CERT) && \ + !defined(NO_FILESYSTEM) + if ( (ret = cert_test()) != 0) + return err_sys("CERT test failed!\n", ret); + else + test_pass("CERT test passed!\n"); +#endif + +#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) && \ + !defined(NO_FILESYSTEM) + if ( (ret = certext_test()) != 0) + return err_sys("CERT EXT test failed!\n", ret); + else + test_pass("CERT EXT test passed!\n"); +#endif + +#if defined(WOLFSSL_CERT_GEN_CACHE) && defined(WOLFSSL_TEST_CERT) && \ + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) + if ( (ret = decodedCertCache_test()) != 0) + return err_sys("DECODED CERT CACHE test failed!\n", ret); + else + test_pass("DECODED CERT CACHE test passed!\n"); #endif #ifdef HAVE_CURVE25519 if ( (ret = curve25519_test()) != 0) return err_sys("CURVE25519 test failed!\n", ret); else - printf( "CURVE25519 test passed!\n"); + test_pass("CURVE25519 test passed!\n"); #endif #ifdef HAVE_ED25519 if ( (ret = ed25519_test()) != 0) return err_sys("ED25519 test failed!\n", ret); else - printf( "ED25519 test passed!\n"); + test_pass("ED25519 test passed!\n"); +#endif + +#ifdef HAVE_CURVE448 + if ( (ret = curve448_test()) != 0) + return err_sys("CURVE448 test failed!\n", ret); + else + test_pass("CURVE448 test passed!\n"); +#endif + +#ifdef HAVE_ED448 + if ( (ret = ed448_test()) != 0) + return err_sys("ED448 test failed!\n", ret); + else + test_pass("ED448 test passed!\n"); +#endif + +#if defined(WOLFSSL_CMAC) && !defined(NO_AES) + if ( (ret = cmac_test()) != 0) + return err_sys("CMAC test failed!\n", ret); + else + test_pass("CMAC test passed!\n"); #endif #ifdef HAVE_LIBZ if ( (ret = compress_test()) != 0) return err_sys("COMPRESS test failed!\n", ret); else - printf( "COMPRESS test passed!\n"); + test_pass("COMPRESS test passed!\n"); #endif #ifdef HAVE_PKCS7 - if ( (ret = pkcs7enveloped_test()) != 0) - return err_sys("PKCS7enveloped test failed!\n", ret); - else - printf( "PKCS7enveloped test passed!\n"); - + #ifndef NO_PKCS7_ENCRYPTED_DATA + if ( (ret = pkcs7encrypted_test()) != 0) + return err_sys("PKCS7encrypted test failed!\n", ret); + else + test_pass("PKCS7encrypted test passed!\n"); + #endif + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + if ( (ret = pkcs7compressed_test()) != 0) + return err_sys("PKCS7compressed test failed!\n", ret); + else + test_pass("PKCS7compressed test passed!\n"); + #endif if ( (ret = pkcs7signed_test()) != 0) - return err_sys("PKCS7signed test failed!\n", ret); + return err_sys("PKCS7signed test failed!\n", ret); else - printf( "PKCS7signed test passed!\n"); + test_pass("PKCS7signed test passed!\n"); + + if ( (ret = pkcs7enveloped_test()) != 0) + return err_sys("PKCS7enveloped test failed!\n", ret); + else + test_pass("PKCS7enveloped test passed!\n"); + + #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + if ( (ret = pkcs7authenveloped_test()) != 0) + return err_sys("PKCS7authenveloped test failed!\n", ret); + else + test_pass("PKCS7authenveloped test passed!\n"); + #endif #endif - ((func_args*)args)->return_code = ret; +#ifdef HAVE_VALGRIND + if ( (ret = mp_test()) != 0) + return err_sys("mp test failed!\n", ret); + else + test_pass("mp test passed!\n"); +#endif - return ret; +#if defined(WOLFSSL_PUBLIC_MP) && defined(WOLFSSL_KEY_GEN) + if ( (ret = prime_test()) != 0) + return err_sys("prime test failed!\n", ret); + else + test_pass("prime test passed!\n"); +#endif + +#if defined(ASN_BER_TO_DER) && \ + (defined(WOLFSSL_TEST_CERT) || defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL)) + if ( (ret = berder_test()) != 0) + return err_sys("ber-der test failed!\n", ret); + else + test_pass("ber-der test passed!\n"); +#endif + + if ( (ret = logging_test()) != 0) + return err_sys("logging test failed!\n", ret); + else + test_pass("logging test passed!\n"); + + if ( (ret = mutex_test()) != 0) + return err_sys("mutex test failed!\n", ret); + else + test_pass("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 + test_pass("memcb test passed!\n"); +#endif + +#ifdef WOLFSSL_IMX6_CAAM_BLOB + if ( (ret = blob_test()) != 0) + return err_sys("blob test failed!\n", ret); + else + test_pass("blob test passed!\n"); +#endif + +#if defined(WOLF_CRYPTO_CB) && \ + !(defined(HAVE_INTEL_QAT_SYNC) || defined(HAVE_CAVIUM_OCTEON_SYNC)) + if ( (ret = cryptocb_test()) != 0) + return err_sys("crypto callback test failed!\n", ret); + else + test_pass("crypto callback test passed!\n"); +#endif + +#ifdef WOLFSSL_CERT_PIV + if ( (ret = certpiv_test()) != 0) + return err_sys("cert piv test failed!\n", ret); + else + test_pass("cert piv test passed!\n"); +#endif + +#ifdef WOLF_CRYPTO_CB +#ifdef HAVE_INTEL_QA_SYNC + wc_CryptoCb_CleanupIntelQa(&devId); +#endif +#ifdef HAVE_CAVIUM_OCTEON_SYNC + wc_CryptoCb_CleanupOcteon(&devId); +#endif +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + + /* cleanup the thread if fixed point cache is enabled and have thread local */ +#if defined(HAVE_THREAD_LS) && defined(HAVE_ECC) && defined(FP_ECC) + wc_ecc_fp_free(); +#endif + + if (args) + ((func_args*)args)->return_code = ret; + + test_pass("Test complete\n"); + + EXIT_TEST(ret); } #ifndef NO_MAIN_DRIVER -#ifdef HAVE_CAVIUM - -static int OpenNitroxDevice(int dma_mode,int dev_id) -{ - 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); - - return CspInitialize(dma_mode, dev_id); -} - -#endif /* HAVE_CAVIUM */ - /* so overall tests can pull in test function */ - +#ifdef WOLFSSL_ESPIDF + void app_main( ) +#else int main(int argc, char** argv) +#endif { - + int ret; func_args args; +#ifdef WOLFSSL_ESPIDF + /* set dummy wallclock time. */ + struct timeval utctime; + struct timezone tz; + utctime.tv_sec = 1521725159; /* dummy time: 2018-03-22T13:25:59+00:00 */ + utctime.tv_usec = 0; + tz.tz_minuteswest = 0; + tz.tz_dsttime = 0; + settimeofday(&utctime, &tz); +#endif +#ifdef WOLFSSL_APACHE_MYNEWT + #ifdef ARCH_sim + mcu_sim_parse_args(argc, argv); + #endif + sysinit(); - -#ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) { - err_sys("Cavium OpenNitroxDevice failed", -1236); - return -1236; - } -#endif /* HAVE_CAVIUM */ - - args.argc = argc; - args.argv = argv; - - wolfcrypt_test(&args); - -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); + /* set dummy wallclock time. */ + struct os_timeval utctime; + struct os_timezone tz; + utctime.tv_sec = 1521725159; /* dummy time: 2018-03-22T13:25:59+00:00 */ + utctime.tv_usec = 0; + tz.tz_minuteswest = 0; + tz.tz_dsttime = 0; + os_settimeofday(&utctime, &tz); #endif +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) { + err_sys("Whitewood netRandom global config failed", -1001); + return -1002; + } +#endif +#ifndef WOLFSSL_ESPIDF + args.argc = argc; + args.argv = argv; +#endif + if ((ret = wolfCrypt_Init()) != 0) { + printf("wolfCrypt_Init failed %d\n", ret); + err_sys("Error with wolfCrypt_Init!\n", -1003); + } + + #ifdef HAVE_STACK_SIZE + StackSizeCheck(&args, wolfcrypt_test); + #else + wolfcrypt_test(&args); + #endif + + if ((ret = wolfCrypt_Cleanup()) != 0) { + printf("wolfCrypt_Cleanup failed %d\n", ret); + err_sys("Error with wolfCrypt_Cleanup!\n", -1004); + } + +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context", -1005); +#endif /* HAVE_WNR */ +#ifndef WOLFSSL_ESPIDF return args.return_code; +#endif } #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; + XFILE derFile; + + derFile = XFOPEN(fileDer, "wb"); + if (!derFile) { + return errBase + 0; + } + ret = (int)XFWRITE(der, 1, derSz, derFile); + XFCLOSE(derFile); + if (ret != derSz) { + return errBase + 1; + } +#endif + + if (pem && filePem) { + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + XFILE pemFile; + #endif + #ifdef WOLFSSL_DER_TO_PEM + pemSz = wc_DerToPem(der, derSz, pem, pemSz, pemType); + if (pemSz < 0) { + return errBase + 2; + } + #endif + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + pemFile = XFOPEN(filePem, "wb"); + if (!pemFile) { + return errBase + 3; + } + ret = (int)XFWRITE(pem, 1, pemSz, pemFile); + XFCLOSE(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, + -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; + if (XSTRLEN(errStr) >= WOLFSSL_MAX_ERROR_SZ) + return -1105; + } + else { + j++; + if (XSTRNCMP(errStr, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1106; + if (XSTRNCMP(out, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1107; + } + } + + /* 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 -1108; + if (XSTRNCMP(out, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1109; +#endif + + return 0; +} + +#ifndef NO_CODING + +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; +#ifdef WOLFSSL_BASE64_ENCODE + byte data[3]; + word32 dataLen; + byte longData[79] = { 0 }; + const byte symbols[] = "+/A="; +#endif + const byte badSmall[] = "AAA Gdj="; + const byte badLarge[] = "AAA~Gdj="; + const byte badEOL[] = "A+Gd AA"; + 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; + } + +#ifdef WOLFSSL_BASE64_ENCODE + /* 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; +#endif + + return 0; +} + +#ifdef WOLFSSL_BASE16 +int base16_test(void) +{ + int ret; + const byte testData[] = "SomeDataToEncode\n"; + const byte encodedTestData[] = "536F6D6544617461546F456E636F64650A00"; + byte encoded[40]; + word32 encodedLen; + byte plain[40]; + word32 len; + + /* length returned includes null termination */ + encodedLen = sizeof(encoded); + ret = Base16_Encode(testData, sizeof(testData), encoded, &encodedLen); + if (ret != 0) + return -1300; + + len = (word32)XSTRLEN((char*)encoded); + if (len != encodedLen - 1) + return -1301; + + len = sizeof(plain); + ret = Base16_Decode(encoded, encodedLen - 1, plain, &len); + if (ret != 0) + return -1302; + + if (len != sizeof(testData) || XMEMCMP(testData, plain, len) != 0) + return -1303; + + if (encodedLen != sizeof(encodedTestData) || + XMEMCMP(encoded, encodedTestData, encodedLen) != 0) { + return -1304; + } + + return 0; +} +#endif /* WOLFSSL_BASE16 */ +#endif /* !NO_CODING */ + +#ifndef NO_ASN +int asn_test(void) +{ + int ret; + /* ASN1 encoded date buffer */ + const byte dateBuf[] = {0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x31, 0x31, + 0x32, 0x30, 0x30, 0x37, 0x33, 0x37, 0x5a}; + byte format; + int length; + const byte* datePart; +#ifndef NO_ASN_TIME + struct tm timearg; + time_t now; +#endif + + ret = wc_GetDateInfo(dateBuf, (int)sizeof(dateBuf), &datePart, &format, + &length); + if (ret != 0) + return -1400; + +#ifndef NO_ASN_TIME + /* Parameter Validation tests. */ + if (wc_GetTime(NULL, sizeof(now)) != BAD_FUNC_ARG) + return -1401; + if (wc_GetTime(&now, 0) != BUFFER_E) + return -1402; + + now = 0; + if (wc_GetTime(&now, sizeof(now)) != 0) { + return -1403; + } + if (now == 0) { + printf("RTC/Time not set!\n"); + return -1404; + } + + ret = wc_GetDateAsCalendarTime(datePart, length, format, &timearg); + if (ret != 0) + return -1405; +#endif /* !NO_ASN_TIME */ + + return 0; +} +#endif /* !NO_ASN */ #ifdef WOLFSSL_MD2 -int md2_test() +int md2_test(void) { Md2 md2; byte hash[MD2_DIGEST_SIZE]; @@ -635,45 +1607,45 @@ int md2_test() a.input = ""; a.output = "\x83\x50\xe5\xa3\xe2\x4c\x15\x3d\xf2\x27\x5c\x9f\x80\x69" "\x27\x73"; - a.inLen = strlen(a.input); + a.inLen = XSTRLEN(a.input); a.outLen = MD2_DIGEST_SIZE; b.input = "a"; b.output = "\x32\xec\x01\xec\x4a\x6d\xac\x72\xc0\xab\x96\xfb\x34\xc0" "\xb5\xd1"; - b.inLen = strlen(b.input); + b.inLen = XSTRLEN(b.input); b.outLen = MD2_DIGEST_SIZE; c.input = "abc"; c.output = "\xda\x85\x3b\x0d\x3f\x88\xd9\x9b\x30\x28\x3a\x69\xe6\xde" "\xd6\xbb"; - c.inLen = strlen(c.input); + c.inLen = XSTRLEN(c.input); c.outLen = MD2_DIGEST_SIZE; d.input = "message digest"; d.output = "\xab\x4f\x49\x6b\xfb\x2a\x53\x0b\x21\x9f\xf3\x30\x31\xfe" "\x06\xb0"; - d.inLen = strlen(d.input); + d.inLen = XSTRLEN(d.input); d.outLen = MD2_DIGEST_SIZE; e.input = "abcdefghijklmnopqrstuvwxyz"; e.output = "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47" "\x94\x0b"; - e.inLen = strlen(e.input); + e.inLen = XSTRLEN(e.input); e.outLen = MD2_DIGEST_SIZE; f.input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345" "6789"; f.output = "\xda\x33\xde\xf2\xa4\x2d\xf1\x39\x75\x35\x28\x46\xc3\x03" "\x38\xcd"; - f.inLen = strlen(f.input); + f.inLen = XSTRLEN(f.input); f.outLen = MD2_DIGEST_SIZE; g.input = "1234567890123456789012345678901234567890123456789012345678" "9012345678901234567890"; g.output = "\xd5\x97\x6f\x79\xd8\x3d\x3a\x0d\xc9\x80\x6c\x3c\x66\xf3" "\xef\xd8"; - g.inLen = strlen(g.input); + g.inLen = XSTRLEN(g.input); g.outLen = MD2_DIGEST_SIZE; test_md2[0] = a; @@ -690,8 +1662,8 @@ int md2_test() wc_Md2Update(&md2, (byte*)test_md2[i].input, (word32)test_md2[i].inLen); wc_Md2Final(&md2, hash); - if (memcmp(hash, test_md2[i].output, MD2_DIGEST_SIZE) != 0) - return -155 - i; + if (XMEMCMP(hash, test_md2[i].output, MD2_DIGEST_SIZE) != 0) + return -1500 - i; } return 0; @@ -701,62 +1673,126 @@ 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, md5Copy; + 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" + 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 = WC_MD5_DIGEST_SIZE; + + b.input = "abc"; + b.output = "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f" "\x72"; - a.inLen = strlen(a.input); - a.outLen = MD5_DIGEST_SIZE; + b.inLen = XSTRLEN(b.input); + b.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" + c.input = "message digest"; + c.output = "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61" "\xd0"; - b.inLen = strlen(b.input); - b.outLen = MD5_DIGEST_SIZE; + c.inLen = XSTRLEN(c.input); + c.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" + d.input = "abcdefghijklmnopqrstuvwxyz"; + d.output = "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1" "\x3b"; - c.inLen = strlen(c.input); - c.outLen = MD5_DIGEST_SIZE; + d.inLen = XSTRLEN(d.input); + d.outLen = WC_MD5_DIGEST_SIZE; - d.input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345" + e.input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345" "6789"; - d.output = "\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d" + e.output = "\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d" "\x9f"; - d.inLen = strlen(d.input); - d.outLen = MD5_DIGEST_SIZE; + e.inLen = XSTRLEN(e.input); + e.outLen = WC_MD5_DIGEST_SIZE; - e.input = "1234567890123456789012345678901234567890123456789012345678" + f.input = "1234567890123456789012345678901234567890123456789012345678" "9012345678901234567890"; - e.output = "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6" + f.output = "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6" "\x7a"; - e.inLen = strlen(e.input); - e.outLen = MD5_DIGEST_SIZE; + 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); - - for (i = 0; i < times; ++i) { - wc_Md5Update(&md5, (byte*)test_md5[i].input, (word32)test_md5[i].inLen); - wc_Md5Final(&md5, hash); - - if (memcmp(hash, test_md5[i].output, MD5_DIGEST_SIZE) != 0) - return -5 - i; + ret = wc_InitMd5_ex(&md5, HEAP_HINT, devId); + if (ret != 0) + return -1600; + ret = wc_InitMd5_ex(&md5Copy, HEAP_HINT, devId); + if (ret != 0) { + wc_Md5Free(&md5); + return -1601; } - return 0; + for (i = 0; i < times; ++i) { + ret = wc_Md5Update(&md5, (byte*)test_md5[i].input, + (word32)test_md5[i].inLen); + if (ret != 0) + ERROR_OUT(-1602 - i, exit); + + ret = wc_Md5GetHash(&md5, hashcopy); + if (ret != 0) + ERROR_OUT(-1603 - i, exit); + + ret = wc_Md5Copy(&md5, &md5Copy); + if (ret != 0) + ERROR_OUT(-1604 - i, exit); + + ret = wc_Md5Final(&md5, hash); + if (ret != 0) + ERROR_OUT(-1605 - i, exit); + + wc_Md5Free(&md5Copy); + + if (XMEMCMP(hash, test_md5[i].output, WC_MD5_DIGEST_SIZE) != 0) + ERROR_OUT(-1606 - i, exit); + + if (XMEMCMP(hash, hashcopy, WC_MD5_DIGEST_SIZE) != 0) + ERROR_OUT(-1607 - i, exit); + } + + /* 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(-1608, exit); + } + ret = wc_Md5Final(&md5, hash); + if (ret != 0) + ERROR_OUT(-1609, exit); + if (XMEMCMP(hash, large_digest, WC_MD5_DIGEST_SIZE) != 0) + ERROR_OUT(-1610, exit); + } /* END LARGE HASH TEST */ + +exit: + + wc_Md5Free(&md5); + wc_Md5Free(&md5Copy); + + return ret; } #endif /* NO_MD5 */ @@ -775,45 +1811,45 @@ int md4_test(void) a.input = ""; a.output = "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89" "\xc0"; - a.inLen = strlen(a.input); + a.inLen = XSTRLEN(a.input); a.outLen = MD4_DIGEST_SIZE; b.input = "a"; b.output = "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb" "\x24"; - b.inLen = strlen(b.input); + b.inLen = XSTRLEN(b.input); b.outLen = MD4_DIGEST_SIZE; c.input = "abc"; c.output = "\xa4\x48\x01\x7a\xaf\x21\xd8\x52\x5f\xc1\x0a\xe8\x7a\xa6\x72" "\x9d"; - c.inLen = strlen(c.input); + c.inLen = XSTRLEN(c.input); c.outLen = MD4_DIGEST_SIZE; d.input = "message digest"; d.output = "\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01" "\x4b"; - d.inLen = strlen(d.input); + d.inLen = XSTRLEN(d.input); d.outLen = MD4_DIGEST_SIZE; e.input = "abcdefghijklmnopqrstuvwxyz"; e.output = "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd\xee\xa8\xed\x63\xdf\x41\x2d" "\xa9"; - e.inLen = strlen(e.input); + e.inLen = XSTRLEN(e.input); e.outLen = MD4_DIGEST_SIZE; f.input = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345" "6789"; f.output = "\x04\x3f\x85\x82\xf2\x41\xdb\x35\x1c\xe6\x27\xe1\x53\xe7\xf0" "\xe4"; - f.inLen = strlen(f.input); + f.inLen = XSTRLEN(f.input); f.outLen = MD4_DIGEST_SIZE; g.input = "1234567890123456789012345678901234567890123456789012345678" "9012345678901234567890"; g.output = "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19\x9c\x3e\x7b\x16\x4f\xcc\x05" "\x36"; - g.inLen = strlen(g.input); + g.inLen = XSTRLEN(g.input); g.outLen = MD4_DIGEST_SIZE; test_md4[0] = a; @@ -830,8 +1866,8 @@ int md4_test(void) wc_Md4Update(&md4, (byte*)test_md4[i].input, (word32)test_md4[i].inLen); wc_Md4Final(&md4, hash); - if (memcmp(hash, test_md4[i].output, MD4_DIGEST_SIZE) != 0) - return -205 - i; + if (XMEMCMP(hash, test_md4[i].output, MD4_DIGEST_SIZE) != 0) + return -1700 - i; } return 0; @@ -843,59 +1879,125 @@ 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, shaCopy; + 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" + 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 = WC_SHA_DIGEST_SIZE; + + 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"; - a.inLen = strlen(a.input); - a.outLen = SHA_DIGEST_SIZE; + b.inLen = XSTRLEN(b.input); + b.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" + 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"; - b.inLen = strlen(b.input); - b.outLen = 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.inLen = strlen(c.input); - c.outLen = SHA_DIGEST_SIZE; + c.inLen = XSTRLEN(c.input); + 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 = strlen(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; - - for (i = 0; i < times; ++i) { - wc_ShaUpdate(&sha, (byte*)test_sha[i].input, (word32)test_sha[i].inLen); - wc_ShaFinal(&sha, hash); - - if (memcmp(hash, test_sha[i].output, SHA_DIGEST_SIZE) != 0) - return -10 - i; + return -1800; + ret = wc_InitSha_ex(&shaCopy, HEAP_HINT, devId); + if (ret != 0) { + wc_ShaFree(&sha); + return -1801; } - return 0; + for (i = 0; i < times; ++i) { + ret = wc_ShaUpdate(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); + if (ret != 0) + ERROR_OUT(-1802 - i, exit); + ret = wc_ShaGetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-1803 - i, exit); + ret = wc_ShaCopy(&sha, &shaCopy); + if (ret != 0) + ERROR_OUT(-1804 - i, exit); + ret = wc_ShaFinal(&sha, hash); + if (ret != 0) + ERROR_OUT(-1805 - i, exit); + wc_ShaFree(&shaCopy); + + if (XMEMCMP(hash, test_sha[i].output, WC_SHA_DIGEST_SIZE) != 0) + ERROR_OUT(-1806 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA_DIGEST_SIZE) != 0) + ERROR_OUT(-1807 - i, exit); + } + + /* BEGIN LARGE HASH TEST */ { + byte large_input[1024]; +#ifdef WOLFSSL_RENESAS_TSIP + const char* large_digest = + "\x1d\x6a\x5a\xf6\xe5\x7c\x86\xce\x7f\x7c\xaf\xd5\xdb\x08\xcd\x59" + "\x15\x8c\x6d\xb6"; +#else + const char* large_digest = + "\x8b\x77\x02\x48\x39\xe8\xdb\xd3\x9a\xf4\x05\x24\x66\x12\x2d\x9e" + "\xc5\xd9\x0a\xac"; +#endif + for (i = 0; i < (int)sizeof(large_input); i++) { + large_input[i] = (byte)(i & 0xFF); + } +#ifdef WOLFSSL_RENESAS_TSIP + times = 20; +#else + times = 100; +#endif +#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(-1808, exit); + } + ret = wc_ShaFinal(&sha, hash); + if (ret != 0) + ERROR_OUT(-1809, exit); + if (XMEMCMP(hash, large_digest, WC_SHA_DIGEST_SIZE) != 0) + ERROR_OUT(-1810, exit); + } /* END LARGE HASH TEST */ + +exit: + + wc_ShaFree(&sha); + wc_ShaFree(&shaCopy); + + return ret; } #endif /* NO_SHA */ @@ -904,6 +2006,7 @@ int sha_test(void) int ripemd_test(void) { RipeMd ripemd; + int ret; byte hash[RIPEMD_DIGEST_SIZE]; testVector a, b, c, d; @@ -913,26 +2016,26 @@ int ripemd_test(void) 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 = strlen(a.input); + a.inLen = XSTRLEN(a.input); a.outLen = RIPEMD_DIGEST_SIZE; b.input = "message digest"; b.output = "\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8\x81\xb1\x23\xa8" "\x5f\xfa\x21\x59\x5f\x36"; - b.inLen = strlen(b.input); + b.inLen = XSTRLEN(b.input); b.outLen = RIPEMD_DIGEST_SIZE; c.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; c.output = "\x12\xa0\x53\x38\x4a\x9c\x0c\x88\xe4\x05\xa0\x6c\x27\xdc" "\xf4\x9a\xda\x62\xeb\x2b"; - c.inLen = strlen(c.input); + c.inLen = XSTRLEN(c.input); c.outLen = RIPEMD_DIGEST_SIZE; d.input = "12345678901234567890123456789012345678901234567890123456" "789012345678901234567890"; d.output = "\x9b\x75\x2e\x45\x57\x3d\x4b\x39\xf4\xdb\xd3\x32\x3c\xab" "\x82\xbf\x63\x32\x6b\xfb"; - d.inLen = strlen(d.input); + d.inLen = XSTRLEN(d.input); d.outLen = RIPEMD_DIGEST_SIZE; test_ripemd[0] = a; @@ -940,15 +2043,25 @@ int ripemd_test(void) test_ripemd[2] = c; test_ripemd[3] = d; - wc_InitRipeMd(&ripemd); + ret = wc_InitRipeMd(&ripemd); + if (ret != 0) { + return -1900; + } 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 -1901 - i; + } - if (memcmp(hash, test_ripemd[i].output, RIPEMD_DIGEST_SIZE) != 0) - return -10 - i; + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret != 0) { + return -1911 - i; + } + + if (XMEMCMP(hash, test_ripemd[i].output, RIPEMD_DIGEST_SIZE) != 0) + return -1921 - i; } return 0; @@ -959,9 +2072,9 @@ int ripemd_test(void) #ifdef HAVE_BLAKE2 -#define BLAKE2_TESTS 3 +#define BLAKE2B_TESTS 3 -static const byte blake2b_vec[BLAKE2_TESTS][BLAKE2B_OUTBYTES] = +static const byte blake2b_vec[BLAKE2B_TESTS][BLAKE2B_OUTBYTES] = { { 0x78, 0x6A, 0x02, 0xF7, 0x42, 0x01, 0x59, 0x03, @@ -1007,21 +2120,21 @@ int blake2b_test(void) for (i = 0; i < (int)sizeof(input); i++) input[i] = (byte)i; - for (i = 0; i < BLAKE2_TESTS; i++) { + for (i = 0; i < BLAKE2B_TESTS; i++) { ret = wc_InitBlake2b(&b2b, 64); if (ret != 0) - return -4002; + return -2000 - i; ret = wc_Blake2bUpdate(&b2b, input, i); if (ret != 0) - return -4003; + return -2010 - 1; ret = wc_Blake2bFinal(&b2b, digest, 64); if (ret != 0) - return -4004; + return -2020 - i; - if (memcmp(digest, blake2b_vec[i], 64) != 0) { - return -300 - i; + if (XMEMCMP(digest, blake2b_vec[i], 64) != 0) { + return -2030 - i; } } @@ -1029,52 +2142,252 @@ int blake2b_test(void) } #endif /* HAVE_BLAKE2 */ +#ifdef HAVE_BLAKE2S + + +#define BLAKE2S_TESTS 3 + +static const byte blake2s_vec[BLAKE2S_TESTS][BLAKE2S_OUTBYTES] = +{ + { + 0x69, 0x21, 0x7a, 0x30, 0x79, 0x90, 0x80, 0x94, + 0xe1, 0x11, 0x21, 0xd0, 0x42, 0x35, 0x4a, 0x7c, + 0x1f, 0x55, 0xb6, 0x48, 0x2c, 0xa1, 0xa5, 0x1e, + 0x1b, 0x25, 0x0d, 0xfd, 0x1e, 0xd0, 0xee, 0xf9, + }, + { + 0xe3, 0x4d, 0x74, 0xdb, 0xaf, 0x4f, 0xf4, 0xc6, + 0xab, 0xd8, 0x71, 0xcc, 0x22, 0x04, 0x51, 0xd2, + 0xea, 0x26, 0x48, 0x84, 0x6c, 0x77, 0x57, 0xfb, + 0xaa, 0xc8, 0x2f, 0xe5, 0x1a, 0xd6, 0x4b, 0xea, + }, + { + 0xdd, 0xad, 0x9a, 0xb1, 0x5d, 0xac, 0x45, 0x49, + 0xba, 0x42, 0xf4, 0x9d, 0x26, 0x24, 0x96, 0xbe, + 0xf6, 0xc0, 0xba, 0xe1, 0xdd, 0x34, 0x2a, 0x88, + 0x08, 0xf8, 0xea, 0x26, 0x7c, 0x6e, 0x21, 0x0c, + } +}; + + + +int blake2s_test(void) +{ + Blake2s b2s; + byte digest[32]; + byte input[64]; + int i, ret; + + for (i = 0; i < (int)sizeof(input); i++) + input[i] = (byte)i; + + for (i = 0; i < BLAKE2S_TESTS; i++) { + ret = wc_InitBlake2s(&b2s, 32); + if (ret != 0) + return -2100 - i; + + ret = wc_Blake2sUpdate(&b2s, input, i); + if (ret != 0) + return -2110 - 1; + + ret = wc_Blake2sFinal(&b2s, digest, 32); + if (ret != 0) + return -2120 - i; + + if (XMEMCMP(digest, blake2s_vec[i], 32) != 0) { + return -2130 - i; + } + } + + return 0; +} +#endif /* HAVE_BLAKE2S */ + + +#ifdef WOLFSSL_SHA224 +int sha224_test(void) +{ + wc_Sha224 sha, shaCopy; + byte hash[WC_SHA224_DIGEST_SIZE]; + byte hashcopy[WC_SHA224_DIGEST_SIZE]; + int ret = 0; + + testVector a, b, c; + testVector test_sha[3]; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + 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 = WC_SHA224_DIGEST_SIZE; + + 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 = 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_ex(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2200; + ret = wc_InitSha224_ex(&shaCopy, HEAP_HINT, devId); + if (ret != 0) { + wc_Sha224Free(&sha); + return -2201; + } + + for (i = 0; i < times; ++i) { + ret = wc_Sha224Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); + if (ret != 0) + ERROR_OUT(-2202 - i, exit); + ret = wc_Sha224GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2203 - i, exit); + ret = wc_Sha224Copy(&sha, &shaCopy); + if (ret != 0) + ERROR_OUT(-2204 - i, exit); + ret = wc_Sha224Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2205 - i, exit); + wc_Sha224Free(&shaCopy); + + if (XMEMCMP(hash, test_sha[i].output, WC_SHA224_DIGEST_SIZE) != 0) + ERROR_OUT(-2206 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA224_DIGEST_SIZE) != 0) + ERROR_OUT(-2207 - i, exit); + } + +exit: + wc_Sha224Free(&sha); + wc_Sha224Free(&shaCopy); + + return ret; +} +#endif + #ifndef NO_SHA256 int sha256_test(void) { - Sha256 sha; - byte hash[SHA256_DIGEST_SIZE]; + wc_Sha256 sha, shaCopy; + 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 = strlen(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 = strlen(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; - - for (i = 0; i < times; ++i) { - ret = wc_Sha256Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); - if (ret != 0) - return -4006; - ret = wc_Sha256Final(&sha, hash); - if (ret != 0) - return -4007; - - if (memcmp(hash, test_sha[i].output, SHA256_DIGEST_SIZE) != 0) - return -10 - i; + return -2300; + ret = wc_InitSha256_ex(&shaCopy, HEAP_HINT, devId); + if (ret != 0) { + wc_Sha256Free(&sha); + return -2301; } - return 0; + for (i = 0; i < times; ++i) { + ret = wc_Sha256Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); + if (ret != 0) { + ERROR_OUT(-2302 - i, exit); + } + ret = wc_Sha256GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2303 - i, exit); + ret = wc_Sha256Copy(&sha, &shaCopy); + if (ret != 0) + ERROR_OUT(-2304 - i, exit); + ret = wc_Sha256Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2305 - i, exit); + wc_Sha256Free(&shaCopy); + + if (XMEMCMP(hash, test_sha[i].output, WC_SHA256_DIGEST_SIZE) != 0) + ERROR_OUT(-2306 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA256_DIGEST_SIZE) != 0) + ERROR_OUT(-2307 - i, exit); + } + + /* BEGIN LARGE HASH TEST */ { + byte large_input[1024]; +#ifdef WOLFSSL_RENESAS_TSIP_CRYPT + const char* large_digest = + "\xa4\x75\x9e\x7a\xa2\x03\x38\x32\x88\x66\xa2\xea\x17\xea\xf8\xc7" + "\xfe\x4e\xc6\xbb\xe3\xbb\x71\xce\xe7\xdf\x7c\x04\x61\xb3\xc2\x2f"; +#else + 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"; +#endif + for (i = 0; i < (int)sizeof(large_input); i++) { + large_input[i] = (byte)(i & 0xFF); + } +#ifdef WOLFSSL_RENESAS_TSIP + times = 20; +#else + times = 100; +#endif +#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(-2308, exit); + } + ret = wc_Sha256Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2309, exit); + if (XMEMCMP(hash, large_digest, WC_SHA256_DIGEST_SIZE) != 0) + ERROR_OUT(-2310, exit); + } /* END LARGE HASH TEST */ + +exit: + + wc_Sha256Free(&sha); + wc_Sha256Free(&shaCopy); + + return ret; } #endif @@ -1082,54 +2395,108 @@ int sha256_test(void) #ifdef WOLFSSL_SHA512 int sha512_test(void) { - Sha512 sha; - byte hash[SHA512_DIGEST_SIZE]; - int ret; + wc_Sha512 sha, shaCopy; + 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 = strlen(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 = strlen(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; - - for (i = 0; i < times; ++i) { - ret = wc_Sha512Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); - if (ret != 0) - return -4010; - - ret = wc_Sha512Final(&sha, hash); - if (ret != 0) - return -4011; - - if (memcmp(hash, test_sha[i].output, SHA512_DIGEST_SIZE) != 0) - return -10 - i; + return -2400; + ret = wc_InitSha512_ex(&shaCopy, HEAP_HINT, devId); + if (ret != 0) { + wc_Sha512Free(&sha); + return -2401; } - return 0; + for (i = 0; i < times; ++i) { + ret = wc_Sha512Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); + if (ret != 0) + ERROR_OUT(-2402 - i, exit); + ret = wc_Sha512GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2403 - i, exit); + ret = wc_Sha512Copy(&sha, &shaCopy); + if (ret != 0) + ERROR_OUT(-2404 - i, exit); + ret = wc_Sha512Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2405 - i, exit); + wc_Sha512Free(&shaCopy); + + if (XMEMCMP(hash, test_sha[i].output, WC_SHA512_DIGEST_SIZE) != 0) + ERROR_OUT(-2406 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA512_DIGEST_SIZE) != 0) + ERROR_OUT(-2407 - i, exit); + } + + /* 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(-2408, exit); + } + ret = wc_Sha512Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2409, exit); + if (XMEMCMP(hash, large_digest, WC_SHA512_DIGEST_SIZE) != 0) + ERROR_OUT(-2410, exit); + } /* END LARGE HASH TEST */ + +exit: + wc_Sha512Free(&sha); + wc_Sha512Free(&shaCopy); + + return ret; } #endif @@ -1137,61 +2504,971 @@ int sha512_test(void) #ifdef WOLFSSL_SHA384 int sha384_test(void) { - Sha384 sha; - byte hash[SHA384_DIGEST_SIZE]; - int ret; + wc_Sha384 sha, shaCopy; + 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 = strlen(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 = strlen(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; - - for (i = 0; i < times; ++i) { - ret = wc_Sha384Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); - if (ret != 0) - return -4013; - - ret = wc_Sha384Final(&sha, hash); - if (ret != 0) - return -4014; - - if (memcmp(hash, test_sha[i].output, SHA384_DIGEST_SIZE) != 0) - return -10 - i; + return -2500; + ret = wc_InitSha384_ex(&shaCopy, HEAP_HINT, devId); + if (ret != 0) { + wc_Sha384Free(&sha); + return -2501; } - return 0; + for (i = 0; i < times; ++i) { + ret = wc_Sha384Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); + if (ret != 0) + ERROR_OUT(-2502 - i, exit); + ret = wc_Sha384GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2503 - i, exit); + ret = wc_Sha384Copy(&sha, &shaCopy); + if (ret != 0) + ERROR_OUT(-2504 - i, exit); + ret = wc_Sha384Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2505 - i, exit); + wc_Sha384Free(&shaCopy); + + if (XMEMCMP(hash, test_sha[i].output, WC_SHA384_DIGEST_SIZE) != 0) + ERROR_OUT(-2506 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA384_DIGEST_SIZE) != 0) + ERROR_OUT(-2507 - i, exit); + } + + /* 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(-2508, exit); + } + ret = wc_Sha384Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2509, exit); + if (XMEMCMP(hash, large_digest, WC_SHA384_DIGEST_SIZE) != 0) + ERROR_OUT(-2510, exit); + } /* END LARGE HASH TEST */ + +exit: + + wc_Sha384Free(&sha); + wc_Sha384Free(&shaCopy); + + return ret; } #endif /* WOLFSSL_SHA384 */ +#ifdef WOLFSSL_SHA3 +#ifndef WOLFSSL_NOSHA3_224 +static int sha3_224_test(void) +{ + wc_Sha3 sha; + byte hash[WC_SHA3_224_DIGEST_SIZE]; + byte hashcopy[WC_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 = WC_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 = WC_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 = WC_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 -2600; + + 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(-2601 - i, exit); + ret = wc_Sha3_224_GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2602 - i, exit); + ret = wc_Sha3_224_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2603 - i, exit); + + if (XMEMCMP(hash, test_sha[i].output, WC_SHA3_224_DIGEST_SIZE) != 0) + ERROR_OUT(-2604 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA3_224_DIGEST_SIZE) != 0) + ERROR_OUT(-2605 - 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(-2606, exit); + } + ret = wc_Sha3_224_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2607, exit); + if (XMEMCMP(hash, large_digest, WC_SHA3_224_DIGEST_SIZE) != 0) + ERROR_OUT(-2608, 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) +{ + wc_Sha3 sha; + byte hash[WC_SHA3_256_DIGEST_SIZE]; + byte hashcopy[WC_SHA3_256_DIGEST_SIZE]; + + testVector a, b, c; + testVector test_sha[3]; + int ret = 0; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + 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"; + +#if defined(WOLFSSL_HASH_FLAGS) && !defined(WOLFSSL_ASYNC_CRYPT) + /* test vector with hash of empty string */ + const char* Keccak256EmptyOut = + "\xc5\xd2\x46\x01\x86\xf7\x23\x3c\x92\x7e\x7d\xb2\xdc\xc7\x03\xc0" + "\xe5\x00\xb6\x53\xca\x82\x27\x3b\x7b\xfa\xd8\x04\x5d\x85\xa4\x70"; +#endif + + 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 = WC_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 = WC_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 = WC_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 -2700; + + 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(-2701 - i, exit); + ret = wc_Sha3_256_GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2702 - i, exit); + ret = wc_Sha3_256_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2703 - i, exit); + + if (XMEMCMP(hash, test_sha[i].output, WC_SHA3_256_DIGEST_SIZE) != 0) + ERROR_OUT(-2704 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA3_256_DIGEST_SIZE) != 0) + ERROR_OUT(-2705 - i, exit); + } + + /* BEGIN LARGE HASH TEST */ { + 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(-2706, exit); + } + ret = wc_Sha3_256_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2707, exit); + if (XMEMCMP(hash, large_digest, WC_SHA3_256_DIGEST_SIZE) != 0) + ERROR_OUT(-2708, exit); + } /* END LARGE HASH TEST */ + + /* this is a software only variant of SHA3 not supported by external hardware devices */ +#if defined(WOLFSSL_HASH_FLAGS) && !defined(WOLFSSL_ASYNC_CRYPT) + /* Test for Keccak256 */ + ret = wc_Sha3_SetFlags(&sha, WC_HASH_SHA3_KECCAK256); + if (ret != 0) { + ERROR_OUT(-2709, exit); + } + ret = wc_Sha3_256_Update(&sha, (byte*)"", 0); + if (ret != 0) { + ERROR_OUT(-2710, exit); + } + ret = wc_Sha3_256_Final(&sha, hash); + if (ret != 0) { + ERROR_OUT(-2711, exit); + } + if (XMEMCMP(hash, Keccak256EmptyOut, WC_SHA3_256_DIGEST_SIZE) != 0) { + ERROR_OUT(-2712, exit); + } +#endif /* WOLFSSL_HASH_FLAGS && !WOLFSSL_ASYNC_CRYPT */ + +exit: + wc_Sha3_256_Free(&sha); + + return ret; +} +#endif /* WOLFSSL_NOSHA3_256 */ + +#ifndef WOLFSSL_NOSHA3_384 +static int sha3_384_test(void) +{ + wc_Sha3 sha; + byte hash[WC_SHA3_384_DIGEST_SIZE]; +#ifndef NO_INTM_HASH_TEST + byte hashcopy[WC_SHA3_384_DIGEST_SIZE]; +#endif + + 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 = WC_SHA3_384_DIGEST_SIZE; + +#if defined(WOLFSSL_AFALG_XILINX_SHA3) || defined(WOLFSSL_XILINX_CRYPT) + /* NIST test vector with a length that is a multiple of 4 */ + b.input = "\x7d\x80\xb1\x60\xc4\xb5\x36\xa3\xbe\xb7\x99\x80\x59\x93\x44" + "\x04\x7c\x5f\x82\xa1\xdf\xc3\xee\xd4"; + b.output = "\x04\x1c\xc5\x86\x1b\xa3\x34\x56\x3c\x61\xd4\xef\x97\x10\xd4" + "\x89\x6c\x31\x1c\x92\xed\xbe\x0d\x7c\xd5\x3e\x80\x3b\xf2\xf4" + "\xeb\x60\x57\x23\x55\x70\x77\x0c\xe8\x7c\x55\x20\xd7\xec\x14" + "\x19\x87\x22"; + b.inLen = XSTRLEN(b.input); + b.outLen = WC_SHA3_384_DIGEST_SIZE; +#else + 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 = WC_SHA3_384_DIGEST_SIZE; +#endif + 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 = WC_SHA3_384_DIGEST_SIZE; + +#ifdef WOLFSSL_XILINX_CRYPT + test_sha[0] = b; /* hardware acc. can not handle "" string */ +#else + test_sha[0] = a; +#endif + test_sha[1] = b; + test_sha[2] = c; + + ret = wc_InitSha3_384(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2800; + + 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(-2801 - i, exit); + #ifndef NO_INTM_HASH_TEST + ret = wc_Sha3_384_GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2802 - i, exit); + #endif + ret = wc_Sha3_384_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2803 - i, exit); + + if (XMEMCMP(hash, test_sha[i].output, WC_SHA3_384_DIGEST_SIZE) != 0) + ERROR_OUT(-2804 - i, exit); + #ifndef NO_INTM_HASH_TEST + if (XMEMCMP(hash, hashcopy, WC_SHA3_384_DIGEST_SIZE) != 0) + ERROR_OUT(-2805 - i, exit); + #endif + } + + /* 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(-2806, exit); + } + ret = wc_Sha3_384_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2807, exit); + if (XMEMCMP(hash, large_digest, WC_SHA3_384_DIGEST_SIZE) != 0) + ERROR_OUT(-2808, 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) +{ + wc_Sha3 sha; + byte hash[WC_SHA3_512_DIGEST_SIZE]; + byte hashcopy[WC_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 = WC_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 = WC_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 = WC_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 -2900; + + 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(-2901 - i, exit); + ret = wc_Sha3_512_GetHash(&sha, hashcopy); + if (ret != 0) + ERROR_OUT(-2902 - i, exit); + ret = wc_Sha3_512_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2903 - i, exit); + + if (XMEMCMP(hash, test_sha[i].output, WC_SHA3_512_DIGEST_SIZE) != 0) + ERROR_OUT(-2904 - i, exit); + if (XMEMCMP(hash, hashcopy, WC_SHA3_512_DIGEST_SIZE) != 0) + ERROR_OUT(-2905 - 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(-2906, exit); + } + ret = wc_Sha3_512_Final(&sha, hash); + if (ret != 0) + ERROR_OUT(-2907, exit); + if (XMEMCMP(hash, large_digest, WC_SHA3_512_DIGEST_SIZE) != 0) + ERROR_OUT(-2908, exit); + } /* END LARGE HASH TEST */ + +exit: + wc_Sha3_512_Free(&sha); + + return ret; +} +#endif /* WOLFSSL_NOSHA3_512 */ + +int sha3_test(void) +{ + int ret; + + (void)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 /* WOLFSSL_SHA3 */ + +#ifdef WOLFSSL_SHAKE256 +int shake256_test(void) +{ +#ifndef WOLFSSL_NO_SHAKE256 + wc_Shake sha; + byte hash[114]; + + testVector a, b, c; + testVector test_sha[3]; + int ret = 0; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + byte large_input[1024]; + const char* large_digest = + "\x90\x32\x4a\xcc\xd1\xdf\xb8\x0b\x79\x1f\xb8\xc8\x5b\x54\xc8\xe7" + "\x45\xf5\x60\x6b\x38\x26\xb2\x0a\xee\x38\x01\xf3\xd9\xfa\x96\x9f" + "\x6a\xd7\x15\xdf\xb6\xc2\xf4\x20\x33\x44\x55\xe8\x2a\x09\x2b\x68" + "\x2e\x18\x65\x5e\x65\x93\x28\xbc\xb1\x9e\xe2\xb1\x92\xea\x98\xac" + "\x21\xef\x4c\xe1\xb4\xb7\xbe\x81\x5c\x1d\xd3\xb7\x17\xe5\xbb\xc5" + "\x8c\x68\xb7\xfb\xac\x55\x8a\x9b\x4d\x91\xe4\x9f\x72\xbb\x6e\x38" + "\xaf\x21\x7d\x21\xaa\x98\x4e\x75\xc4\xb4\x1c\x7c\x50\x45\x54\xf9" + "\xea\x26"; + + a.input = ""; + a.output = "\x46\xb9\xdd\x2b\x0b\xa8\x8d\x13\x23\x3b\x3f\xeb\x74\x3e\xeb" + "\x24\x3f\xcd\x52\xea\x62\xb8\x1b\x82\xb5\x0c\x27\x64\x6e\xd5" + "\x76\x2f\xd7\x5d\xc4\xdd\xd8\xc0\xf2\x00\xcb\x05\x01\x9d\x67" + "\xb5\x92\xf6\xfc\x82\x1c\x49\x47\x9a\xb4\x86\x40\x29\x2e\xac" + "\xb3\xb7\xc4\xbe\x14\x1e\x96\x61\x6f\xb1\x39\x57\x69\x2c\xc7" + "\xed\xd0\xb4\x5a\xe3\xdc\x07\x22\x3c\x8e\x92\x93\x7b\xef\x84" + "\xbc\x0e\xab\x86\x28\x53\x34\x9e\xc7\x55\x46\xf5\x8f\xb7\xc2" + "\x77\x5c\x38\x46\x2c\x50\x10\xd8\x46"; + a.inLen = XSTRLEN(a.input); + a.outLen = sizeof(hash); + + b.input = "abc"; + b.output = "\x48\x33\x66\x60\x13\x60\xa8\x77\x1c\x68\x63\x08\x0c\xc4\x11" + "\x4d\x8d\xb4\x45\x30\xf8\xf1\xe1\xee\x4f\x94\xea\x37\xe7\x8b" + "\x57\x39\xd5\xa1\x5b\xef\x18\x6a\x53\x86\xc7\x57\x44\xc0\x52" + "\x7e\x1f\xaa\x9f\x87\x26\xe4\x62\xa1\x2a\x4f\xeb\x06\xbd\x88" + "\x01\xe7\x51\xe4\x13\x85\x14\x12\x04\xf3\x29\x97\x9f\xd3\x04" + "\x7a\x13\xc5\x65\x77\x24\xad\xa6\x4d\x24\x70\x15\x7b\x3c\xdc" + "\x28\x86\x20\x94\x4d\x78\xdb\xcd\xdb\xd9\x12\x99\x3f\x09\x13" + "\xf1\x64\xfb\x2c\xe9\x51\x31\xa2\xd0"; + b.inLen = XSTRLEN(b.input); + b.outLen = sizeof(hash); + + c.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + c.output = "\x4d\x8c\x2d\xd2\x43\x5a\x01\x28\xee\xfb\xb8\xc3\x6f\x6f\x87" + "\x13\x3a\x79\x11\xe1\x8d\x97\x9e\xe1\xae\x6b\xe5\xd4\xfd\x2e" + "\x33\x29\x40\xd8\x68\x8a\x4e\x6a\x59\xaa\x80\x60\xf1\xf9\xbc" + "\x99\x6c\x05\xac\xa3\xc6\x96\xa8\xb6\x62\x79\xdc\x67\x2c\x74" + "\x0b\xb2\x24\xec\x37\xa9\x2b\x65\xdb\x05\x39\xc0\x20\x34\x55" + "\xf5\x1d\x97\xcc\xe4\xcf\xc4\x91\x27\xd7\x26\x0a\xfc\x67\x3a" + "\xf2\x08\xba\xf1\x9b\xe2\x12\x33\xf3\xde\xbe\x78\xd0\x67\x60" + "\xcf\xa5\x51\xee\x1e\x07\x91\x41\xd4"; + c.inLen = XSTRLEN(c.input); + c.outLen = sizeof(hash); + + test_sha[0] = a; + test_sha[1] = b; + test_sha[2] = c; + + ret = wc_InitShake256(&sha, HEAP_HINT, devId); + if (ret != 0) + return -3100; + + for (i = 0; i < times; ++i) { + ret = wc_Shake256_Update(&sha, (byte*)test_sha[i].input, + (word32)test_sha[i].inLen); + if (ret != 0) + ERROR_OUT(-3101 - i, exit); + ret = wc_Shake256_Final(&sha, hash, (word32)test_sha[i].outLen); + if (ret != 0) + ERROR_OUT(-3102 - i, exit); + + if (XMEMCMP(hash, test_sha[i].output, test_sha[i].outLen) != 0) + ERROR_OUT(-3103 - i, exit); + } + + /* BEGIN LARGE HASH TEST */ { + 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_Shake256_Update(&sha, (byte*)large_input, + (word32)sizeof(large_input)); + if (ret != 0) + ERROR_OUT(-3104, exit); + } + ret = wc_Shake256_Final(&sha, hash, (word32)sizeof(hash)); + if (ret != 0) + ERROR_OUT(-3105, exit); + if (XMEMCMP(hash, large_digest, sizeof(hash)) != 0) + ERROR_OUT(-3106, exit); + } /* END LARGE HASH TEST */ + +exit: + wc_Shake256_Free(&sha); + + return ret; +#else + return 0; +#endif +} +#endif + + +int hash_test(void) +{ + wc_HashAlg hash; + int ret, exp_ret; + int i, j; + int digestSz; + byte data[] = "0123456789abcdef0123456789abcdef0123456"; + byte out[WC_MAX_DIGEST_SIZE]; + byte hashOut[WC_MAX_DIGEST_SIZE]; +#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) + enum wc_HashType hashType; +#endif + 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, + WC_HASH_TYPE_SHA3_224, + WC_HASH_TYPE_SHA3_256, + WC_HASH_TYPE_SHA3_384, + WC_HASH_TYPE_SHA3_512 }; + 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 +#if !defined(WOLFSSL_SHA3) || defined(WOLFSSL_NOSHA3_224) + WC_HASH_TYPE_SHA3_224, +#endif +#if !defined(WOLFSSL_SHA3) || defined(WOLFSSL_NOSHA3_256) + WC_HASH_TYPE_SHA3_256, +#endif +#if !defined(WOLFSSL_SHA3) || defined(WOLFSSL_NOSHA3_384) + WC_HASH_TYPE_SHA3_384, +#endif +#if !defined(WOLFSSL_SHA3) || defined(WOLFSSL_NOSHA3_512) + WC_HASH_TYPE_SHA3_512, +#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 }; + enum wc_HashType typesHashBad[] = { WC_HASH_TYPE_MD2, WC_HASH_TYPE_MD4, + WC_HASH_TYPE_BLAKE2B, + WC_HASH_TYPE_NONE }; + + /* Parameter Validation testing. */ + ret = wc_HashInit(NULL, WC_HASH_TYPE_SHA256); + if (ret != BAD_FUNC_ARG) + return -3200; + ret = wc_HashUpdate(NULL, WC_HASH_TYPE_SHA256, NULL, sizeof(data)); + if (ret != BAD_FUNC_ARG) + return -3201; + ret = wc_HashUpdate(&hash, WC_HASH_TYPE_SHA256, NULL, sizeof(data)); + if (ret != BAD_FUNC_ARG) + return -3202; + ret = wc_HashUpdate(NULL, WC_HASH_TYPE_SHA256, data, sizeof(data)); + if (ret != BAD_FUNC_ARG) + return -3203; + ret = wc_HashFinal(NULL, WC_HASH_TYPE_SHA256, NULL); + if (ret != BAD_FUNC_ARG) + return -3204; + ret = wc_HashFinal(&hash, WC_HASH_TYPE_SHA256, NULL); + if (ret != BAD_FUNC_ARG) + return -3205; + ret = wc_HashFinal(NULL, WC_HASH_TYPE_SHA256, out); + if (ret != BAD_FUNC_ARG) + return -3206; + + /* 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 -3207 - i; + ret = wc_HashUpdate(&hash, typesBad[i], data, sizeof(data)); + if (ret != BAD_FUNC_ARG) + return -3217 - i; + ret = wc_HashFinal(&hash, typesBad[i], out); + if (ret != BAD_FUNC_ARG) + return -3227 - i; + wc_HashFree(&hash, typesBad[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 -3237 - i; + ret = wc_HashUpdate(&hash, typesGood[i], data, sizeof(data)); + if (ret != exp_ret) + return -3247 - i; + ret = wc_HashFinal(&hash, typesGood[i], out); + if (ret != exp_ret) + return -3257 - i; + wc_HashFree(&hash, typesGood[i]); + + digestSz = wc_HashGetDigestSize(typesGood[i]); + if (exp_ret < 0 && digestSz != exp_ret) + return -3267 - i; + if (exp_ret == 0 && digestSz < 0) + return -3277 - i; + if (exp_ret == 0) { + ret = wc_Hash(typesGood[i], data, sizeof(data), hashOut, + digestSz - 1); + if (ret != BUFFER_E) + return -3287 - i; + } + ret = wc_Hash(typesGood[i], data, sizeof(data), hashOut, digestSz); + if (ret != exp_ret) + return -3297 - i; + if (exp_ret == 0 && XMEMCMP(out, hashOut, digestSz) != 0) + return -3307 -i; + + ret = wc_HashGetBlockSize(typesGood[i]); + if (exp_ret < 0 && ret != exp_ret) + return -3308 - i; + if (exp_ret == 0 && ret < 0) + return -3318 - 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 -3328 - i; + } + + hashType = wc_OidGetHash(ret); + if (exp_ret < 0 && ret != exp_ret) + return -3338 - i; + if (exp_ret == 0 && hashType != typesGood[i]) + return -3348 - i; +#endif /* !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) */ + } + + for (i = 0; i < (int)(sizeof(typesHashBad)/sizeof(*typesHashBad)); i++) { + ret = wc_Hash(typesHashBad[i], data, sizeof(data), out, sizeof(out)); + if (ret != BAD_FUNC_ARG && ret != BUFFER_E) + return -3358 - i; + } + +#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 -3368; +#else + if (ret != HASH_TYPE_E) + return -3369; +#endif + hashType = wc_OidGetHash(646); /* Md2h */ +#ifdef WOLFSSL_MD2 + if (hashType != WC_HASH_TYPE_MD2) + return -3370; +#else + if (hashType != WC_HASH_TYPE_NONE) + return -3371; +#endif + + ret = wc_HashGetOID(WC_HASH_TYPE_MD5_SHA); +#ifndef NO_MD5 + if (ret == HASH_TYPE_E || ret == BAD_FUNC_ARG) + return -3372; +#else + if (ret != HASH_TYPE_E) + return -3373; +#endif + ret = wc_HashGetOID(WC_HASH_TYPE_MD4); + if (ret != BAD_FUNC_ARG) + return -3374; + ret = wc_HashGetOID(WC_HASH_TYPE_NONE); + if (ret != BAD_FUNC_ARG) + return -3375; + + hashType = wc_OidGetHash(0); + if (hashType != WC_HASH_TYPE_NONE) + return -3376; +#endif /* !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) */ + + ret = wc_HashGetBlockSize(WC_HASH_TYPE_MD2); +#ifdef WOLFSSL_MD2 + if (ret == HASH_TYPE_E || ret == BAD_FUNC_ARG) + return -3377; +#else + if (ret != HASH_TYPE_E) + return -3378; +#endif + ret = wc_HashGetDigestSize(WC_HASH_TYPE_MD2); +#ifdef WOLFSSL_MD2 + if (ret == HASH_TYPE_E || ret == BAD_FUNC_ARG) + return -3379; +#else + if (ret != HASH_TYPE_E) + return -3380; +#endif + + ret = wc_HashGetBlockSize(WC_HASH_TYPE_MD4); +#ifndef NO_MD4 + if (ret == HASH_TYPE_E || ret == BAD_FUNC_ARG) + return -3381; +#else + if (ret != HASH_TYPE_E) + return -3382; +#endif + ret = wc_HashGetDigestSize(WC_HASH_TYPE_MD4); +#ifndef NO_MD4 + if (ret == HASH_TYPE_E || ret == BAD_FUNC_ARG) + return -3383; +#else + if (ret != HASH_TYPE_E) + return -3384; +#endif + ret = wc_HashGetBlockSize(WC_HASH_TYPE_MD5_SHA); +#if !defined(NO_MD5) && !defined(NO_SHA) + if (ret == HASH_TYPE_E || ret == BAD_FUNC_ARG) + return -3385; +#else + if (ret != HASH_TYPE_E) + return -3386; +#endif + + ret = wc_HashGetBlockSize(WC_HASH_TYPE_BLAKE2B); +#if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) + if (ret == HASH_TYPE_E || ret == BAD_FUNC_ARG) + return -3387; +#else + if (ret != HASH_TYPE_E) + return -3388; +#endif + ret = wc_HashGetDigestSize(WC_HASH_TYPE_BLAKE2B); +#if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) + if (ret == HASH_TYPE_E || ret == BAD_FUNC_ARG) + return -3389; +#else + if (ret != HASH_TYPE_E) + return -3390; +#endif + + ret = wc_HashGetBlockSize(WC_HASH_TYPE_NONE); + if (ret != BAD_FUNC_ARG) + return -3391; + ret = wc_HashGetDigestSize(WC_HASH_TYPE_NONE); + if (ret != BAD_FUNC_ARG) + return -3392; + +#ifndef NO_CERTS +#if defined(WOLFSSL_MD2) && !defined(HAVE_SELFTEST) + ret = wc_GetCTC_HashOID(MD2); + if (ret == 0) + return -3393; +#endif +#ifndef NO_MD5 + ret = wc_GetCTC_HashOID(WC_MD5); + if (ret == 0) + return -3394; +#endif +#ifndef NO_SHA + ret = wc_GetCTC_HashOID(WC_SHA); + if (ret == 0) + return -3395; +#endif +#ifdef WOLFSSL_SHA224 + ret = wc_GetCTC_HashOID(WC_SHA224); + if (ret == 0) + return -3396; +#endif +#ifndef NO_SHA256 + ret = wc_GetCTC_HashOID(WC_SHA256); + if (ret == 0) + return -3397; +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_GetCTC_HashOID(WC_SHA384); + if (ret == 0) + return -3398; +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_GetCTC_HashOID(WC_SHA512); + if (ret == 0) + return -3399; +#endif + ret = wc_GetCTC_HashOID(-1); + if (ret != 0) + return -3400; +#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[]= { @@ -1209,14 +3486,14 @@ int hmac_md5_test(void) a.input = "Hi There"; a.output = "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc" "\x9d"; - a.inLen = strlen(a.input); - a.outLen = MD5_DIGEST_SIZE; + a.inLen = XSTRLEN(a.input); + 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 = strlen(b.input); - b.outLen = MD5_DIGEST_SIZE; + b.inLen = XSTRLEN(b.input); + 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" @@ -1224,40 +3501,47 @@ int hmac_md5_test(void) "\xDD\xDD\xDD\xDD\xDD\xDD"; c.output = "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3" "\xf6"; - c.inLen = strlen(c.input); - c.outLen = MD5_DIGEST_SIZE; + c.inLen = XSTRLEN(c.input); + c.outLen = WC_MD5_DIGEST_SIZE; test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; for (i = 0; i < times; ++i) { -#if defined(HAVE_FIPS) || defined(HAVE_CAVIUM) - if (i == 1) + #if defined(HAVE_FIPS) || defined(HAVE_CAVIUM) + if (i == 1) { continue; /* cavium can't handle short keys, fips not allowed */ -#endif -#ifdef HAVE_CAVIUM - if (wc_HmacInitCavium(&hmac, CAVIUM_DEV_ID) != 0) - return -20009; -#endif - ret = wc_HmacSetKey(&hmac, MD5, (byte*)keys[i], (word32)strlen(keys[i])); + } + #endif + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) { + return -3500; + } + + ret = wc_HmacSetKey(&hmac, WC_MD5, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4015; + return -3501; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4016; + return -3502; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4017; + return -3503; - if (memcmp(hash, test_hmac[i].output, MD5_DIGEST_SIZE) != 0) - return -20 - i; -#ifdef HAVE_CAVIUM - wc_HmacFreeCavium(&hmac); -#endif + if (XMEMCMP(hash, test_hmac[i].output, WC_MD5_DIGEST_SIZE) != 0) + return -3504 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(WC_MD5) != WC_MD5_DIGEST_SIZE) + return -3514; +#endif + return 0; } #endif /* NO_HMAC && NO_MD5 */ @@ -1266,7 +3550,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[]= { @@ -1286,14 +3570,14 @@ int hmac_sha_test(void) 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 = strlen(a.input); - a.outLen = SHA_DIGEST_SIZE; + a.inLen = XSTRLEN(a.input); + 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 = strlen(b.input); - b.outLen = SHA_DIGEST_SIZE; + b.inLen = XSTRLEN(b.input); + 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" @@ -1301,8 +3585,8 @@ int hmac_sha_test(void) "\xDD\xDD\xDD\xDD\xDD\xDD"; c.output = "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b" "\x4f\x63\xf1\x75\xd3"; - c.inLen = strlen(c.input); - c.outLen = SHA_DIGEST_SIZE; + c.inLen = XSTRLEN(c.input); + c.outLen = WC_SHA_DIGEST_SIZE; test_hmac[0] = a; test_hmac[1] = b; @@ -1313,28 +3597,128 @@ int hmac_sha_test(void) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif -#ifdef HAVE_CAVIUM - if (wc_HmacInitCavium(&hmac, CAVIUM_DEV_ID) != 0) - return -20010; -#endif - ret = wc_HmacSetKey(&hmac, SHA, (byte*)keys[i], (word32)strlen(keys[i])); + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -3600; + + ret = wc_HmacSetKey(&hmac, WC_SHA, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4018; + return -3601; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4019; + return -3602; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4020; + return -3603; - if (memcmp(hash, test_hmac[i].output, SHA_DIGEST_SIZE) != 0) - return -20 - i; -#ifdef HAVE_CAVIUM - wc_HmacFreeCavium(&hmac); -#endif + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA_DIGEST_SIZE) != 0) + return -3604 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(WC_SHA) != WC_SHA_DIGEST_SIZE) + return -3614; +#endif + + return 0; +} +#endif + + +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA224) +int hmac_sha224_test(void) +{ + Hmac hmac; + byte hash[WC_SHA224_DIGEST_SIZE]; + + const char* keys[]= + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "Jefe", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA", + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + }; + + testVector a, b, c, d; + testVector test_hmac[4]; + + int ret; + int times = sizeof(test_hmac) / sizeof(testVector), i; + + 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 = 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 = 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" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD"; + 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 = WC_SHA224_DIGEST_SIZE; + + d.input = "Big Key Input"; + d.output = "\xe7\x4e\x2b\x8a\xa9\xf0\x37\x2f\xed\xae\x70\x0c\x49\x47\xf1" + "\x46\x54\xa7\x32\x6b\x55\x01\x87\xd2\xc8\x02\x0e\x3a"; + d.inLen = XSTRLEN(d.input); + d.outLen = WC_SHA224_DIGEST_SIZE; + + test_hmac[0] = a; + test_hmac[1] = b; + test_hmac[2] = c; + test_hmac[3] = d; + + 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 + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -3700; + + ret = wc_HmacSetKey(&hmac, WC_SHA224, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); + if (ret != 0) + return -3701; + ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, + (word32)test_hmac[i].inLen); + if (ret != 0) + return -3702; + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) + return -3703; + + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA224_DIGEST_SIZE) != 0) + return -3704 - i; + + wc_HmacFree(&hmac); + } + +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(WC_SHA224) != WC_SHA224_DIGEST_SIZE) + return -3714; +#endif + return 0; } #endif @@ -1344,7 +3728,7 @@ int hmac_sha_test(void) int hmac_sha256_test(void) { Hmac hmac; - byte hash[SHA256_DIGEST_SIZE]; + byte hash[WC_SHA256_DIGEST_SIZE]; const char* keys[]= { @@ -1352,11 +3736,13 @@ int hmac_sha256_test(void) "\x0b\x0b\x0b", "Jefe", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA" + "\xAA\xAA\xAA", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA", }; - testVector a, b, c; - testVector test_hmac[3]; + testVector a, b, c, d; + testVector test_hmac[4]; int ret; int times = sizeof(test_hmac) / sizeof(testVector), i; @@ -1365,15 +3751,15 @@ int hmac_sha256_test(void) 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 = strlen(a.input); - a.outLen = SHA256_DIGEST_SIZE; + a.inLen = XSTRLEN(a.input); + 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 = strlen(b.input); - b.outLen = SHA256_DIGEST_SIZE; + b.inLen = XSTRLEN(b.input); + 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" @@ -1382,121 +3768,62 @@ int hmac_sha256_test(void) c.output = "\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81" "\xa7\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5" "\x65\xfe"; - c.inLen = strlen(c.input); - c.outLen = SHA256_DIGEST_SIZE; + c.inLen = XSTRLEN(c.input); + c.outLen = WC_SHA256_DIGEST_SIZE; + + d.input = 0; + d.output = "\x86\xe5\x4f\xd4\x48\x72\x5d\x7e\x5d\xcf\xe2\x23\x53\xc8\x28" + "\xaf\x48\x78\x1e\xb4\x8c\xae\x81\x06\xa7\xe1\xd4\x98\x94\x9f" + "\x3e\x46"; + d.inLen = 0; + d.outLen = WC_SHA256_DIGEST_SIZE; test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; + test_hmac[3] = d; 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 -#ifdef HAVE_CAVIUM - if (wc_HmacInitCavium(&hmac, CAVIUM_DEV_ID) != 0) - return -20011; +#if defined(HAVE_INTEL_QA) || defined(HAVE_CAVIUM) + if (i == 3) + continue; /* QuickAssist can't handle empty HMAC */ #endif - ret = wc_HmacSetKey(&hmac, SHA256, (byte*)keys[i],(word32)strlen(keys[i])); + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -3800 - i; + + ret = wc_HmacSetKey(&hmac, WC_SHA256, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4021; - ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, - (word32)test_hmac[i].inLen); - if (ret != 0) - return -4022; + return -3810 - i; + if (test_hmac[i].input != NULL) { + ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, + (word32)test_hmac[i].inLen); + if (ret != 0) + return -3820 - i; + } ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4023; + return -3830 - i; - if (memcmp(hash, test_hmac[i].output, SHA256_DIGEST_SIZE) != 0) - return -20 - i; -#ifdef HAVE_CAVIUM - wc_HmacFreeCavium(&hmac); -#endif + if (XMEMCMP(hash, test_hmac[i].output, WC_SHA256_DIGEST_SIZE) != 0) + return -3840 - i; + + wc_HmacFree(&hmac); } - return 0; -} +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(WC_SHA256) != WC_SHA256_DIGEST_SIZE) + return -3850; + if (wc_HmacSizeByType(20) != BAD_FUNC_ARG) + return -3851; #endif - - -#if !defined(NO_HMAC) && defined(HAVE_BLAKE2) -int hmac_blake2b_test(void) -{ - Hmac hmac; - byte hash[BLAKE2B_256]; - - const char* keys[]= - { - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b", - "Jefe", - "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA" - }; - - testVector a, b, c; - testVector test_hmac[3]; - - int ret; - int times = sizeof(test_hmac) / sizeof(testVector), i; - - a.input = "Hi There"; - a.output = "\x72\x93\x0d\xdd\xf5\xf7\xe1\x78\x38\x07\x44\x18\x0b\x3f\x51" - "\x37\x25\xb5\x82\xc2\x08\x83\x2f\x1c\x99\xfd\x03\xa0\x16\x75" - "\xac\xfd"; - a.inLen = strlen(a.input); - a.outLen = BLAKE2B_256; - - b.input = "what do ya want for nothing?"; - b.output = "\x3d\x20\x50\x71\x05\xc0\x8c\x0c\x38\x44\x1e\xf7\xf9\xd1\x67" - "\x21\xff\x64\xf5\x94\x00\xcf\xf9\x75\x41\xda\x88\x61\x9d\x7c" - "\xda\x2b"; - b.inLen = strlen(b.input); - b.outLen = BLAKE2B_256; - - 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" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD"; - c.output = "\xda\xfe\x2a\x24\xfc\xe7\xea\x36\x34\xbe\x41\x92\xc7\x11\xa7" - "\x00\xae\x53\x9c\x11\x9c\x80\x74\x55\x22\x25\x4a\xb9\x55\xd3" - "\x0f\x87"; - c.inLen = strlen(c.input); - c.outLen = BLAKE2B_256; - - test_hmac[0] = a; - test_hmac[1] = b; - test_hmac[2] = c; - - 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 -#ifdef HAVE_CAVIUM - if (wc_HmacInitCavium(&hmac, CAVIUM_DEV_ID) != 0) - return -20011; -#endif - ret = wc_HmacSetKey(&hmac, BLAKE2B_ID, (byte*)keys[i], - (word32)strlen(keys[i])); - if (ret != 0) - return -4024; - ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, - (word32)test_hmac[i].inLen); - if (ret != 0) - return -4025; - ret = wc_HmacFinal(&hmac, hash); - if (ret != 0) - return -4026; - - if (memcmp(hash, test_hmac[i].output, BLAKE2B_256) != 0) - return -20 - i; -#ifdef HAVE_CAVIUM - wc_HmacFreeCavium(&hmac); -#endif - } + if (wolfSSL_GetHmacMaxSize() != WC_MAX_DIGEST_SIZE) + return -3852; return 0; } @@ -1507,7 +3834,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[]= { @@ -1515,11 +3842,20 @@ int hmac_sha384_test(void) "\x0b\x0b\x0b", "Jefe", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA" + "\xAA\xAA\xAA", + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" }; - testVector a, b, c; - testVector test_hmac[3]; + testVector a, b, c, d; + testVector test_hmac[4]; int ret; int times = sizeof(test_hmac) / sizeof(testVector), i; @@ -1529,16 +3865,16 @@ int hmac_sha384_test(void) "\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 = strlen(a.input); - a.outLen = SHA384_DIGEST_SIZE; + a.inLen = XSTRLEN(a.input); + 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" "\x1b\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22" "\x44\x5e\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa" "\xb2\x16\x49"; - b.inLen = strlen(b.input); - b.outLen = SHA384_DIGEST_SIZE; + b.inLen = XSTRLEN(b.input); + 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" @@ -1548,33 +3884,54 @@ int hmac_sha384_test(void) "\x6f\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66" "\x14\x4b\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01" "\xa3\x4f\x27"; - c.inLen = strlen(c.input); - c.outLen = SHA384_DIGEST_SIZE; + c.inLen = XSTRLEN(c.input); + c.outLen = WC_SHA384_DIGEST_SIZE; + + d.input = "Big Key Input"; + d.output = "\xd2\x3d\x29\x6e\xf5\x1e\x23\x23\x49\x18\xb3\xbf\x4c\x38\x7b" + "\x31\x21\x17\xbb\x09\x73\x27\xf8\x12\x9d\xe9\xc6\x5d\xf9\x54" + "\xd6\x38\x5a\x68\x53\x14\xee\xe0\xa6\x4f\x36\x7e\xb2\xf3\x1a" + "\x57\x41\x69"; + d.inLen = XSTRLEN(d.input); + d.outLen = WC_SHA384_DIGEST_SIZE; test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; + test_hmac[3] = d; 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)strlen(keys[i])); + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -3900; + + ret = wc_HmacSetKey(&hmac, WC_SHA384, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4027; + return -3901; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4028; + return -3902; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4029; + return -3903; - if (memcmp(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 -3904 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(WC_SHA384) != WC_SHA384_DIGEST_SIZE) + return -3914; +#endif + return 0; } #endif @@ -1584,7 +3941,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[]= { @@ -1592,11 +3949,20 @@ int hmac_sha512_test(void) "\x0b\x0b\x0b", "Jefe", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA" + "\xAA\xAA\xAA", + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" }; - testVector a, b, c; - testVector test_hmac[3]; + testVector a, b, c, d; + testVector test_hmac[4]; int ret; int times = sizeof(test_hmac) / sizeof(testVector), i; @@ -1607,8 +3973,8 @@ int hmac_sha512_test(void) "\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae" "\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20" "\x3a\x12\x68\x54"; - a.inLen = strlen(a.input); - a.outLen = SHA512_DIGEST_SIZE; + a.inLen = XSTRLEN(a.input); + 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" @@ -1616,8 +3982,8 @@ int hmac_sha512_test(void) "\x05\x54\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8" "\xf0\xe6\xfd\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a" "\x38\xbc\xe7\x37"; - b.inLen = strlen(b.input); - b.outLen = SHA512_DIGEST_SIZE; + b.inLen = XSTRLEN(b.input); + 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" @@ -1628,31 +3994,227 @@ int hmac_sha512_test(void) "\x9d\x39\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e" "\x67\xc8\x07\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59" "\xe1\x32\x92\xfb"; - c.inLen = strlen(c.input); - c.outLen = SHA512_DIGEST_SIZE; + c.inLen = XSTRLEN(c.input); + c.outLen = WC_SHA512_DIGEST_SIZE; + + d.input = "Big Key Input"; + d.output = "\x3f\xa9\xc9\xe1\xbd\xbb\x04\x55\x1f\xef\xcc\x92\x33\x08\xeb" + "\xcf\xc1\x9a\x5b\x5b\xc0\x7c\x86\x84\xae\x8c\x40\xaf\xb1\x27" + "\x87\x38\x92\x04\xa8\xed\xd7\xd7\x07\xa9\x85\xa0\xc2\xcd\x30" + "\xc0\x56\x14\x49\xbc\x2f\x69\x15\x6a\x97\xd8\x79\x2f\xb3\x3b" + "\x1e\x18\xfe\xfa"; + d.inLen = XSTRLEN(d.input); + d.outLen = WC_SHA512_DIGEST_SIZE; test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; + test_hmac[3] = d; for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) continue; /* fips not allowed */ #endif - ret = wc_HmacSetKey(&hmac, SHA512, (byte*)keys[i],(word32)strlen(keys[i])); + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -4000; + + ret = wc_HmacSetKey(&hmac, WC_SHA512, (byte*)keys[i], + (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4030; + return -4001; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4031; + return -4002; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4032; + return -4003; - if (memcmp(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 -4004 - i; + + wc_HmacFree(&hmac); + } + +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(WC_SHA512) != WC_SHA512_DIGEST_SIZE) + return -4014; +#endif + + return 0; +} +#endif + + +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA3) && \ + !defined(WOLFSSL_NOSHA3_224) && !defined(WOLFSSL_NOSHA3_256) && \ + !defined(WOLFSSL_NOSHA3_384) && !defined(WOLFSSL_NOSHA3_512) +int hmac_sha3_test(void) +{ + Hmac hmac; + byte hash[WC_SHA3_512_DIGEST_SIZE]; + + const char* key[4] = + { + "Jefe", + + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + }; + + const char* input[4] = + { + "what do ya want for nothing?", + + "Hi There", + + "\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\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + + "Big Key Input" + }; + + const int hashType[4] = + { + WC_SHA3_224, WC_SHA3_256, WC_SHA3_384, WC_SHA3_512 + }; + + const int hashSz[4] = + { + WC_SHA3_224_DIGEST_SIZE, WC_SHA3_256_DIGEST_SIZE, + WC_SHA3_384_DIGEST_SIZE, WC_SHA3_512_DIGEST_SIZE + }; + + const char* output[16] = + { + /* key = jefe, input = what do ya want for nothing? */ + /* HMAC-SHA3-224 */ + "\x7f\xdb\x8d\xd8\x8b\xd2\xf6\x0d\x1b\x79\x86\x34\xad\x38\x68\x11" + "\xc2\xcf\xc8\x5b\xfa\xf5\xd5\x2b\xba\xce\x5e\x66", + /* HMAC-SHA3-256 */ + "\xc7\xd4\x07\x2e\x78\x88\x77\xae\x35\x96\xbb\xb0\xda\x73\xb8\x87" + "\xc9\x17\x1f\x93\x09\x5b\x29\x4a\xe8\x57\xfb\xe2\x64\x5e\x1b\xa5", + /* HMAC-SHA3-384 */ + "\xf1\x10\x1f\x8c\xbf\x97\x66\xfd\x67\x64\xd2\xed\x61\x90\x3f\x21" + "\xca\x9b\x18\xf5\x7c\xf3\xe1\xa2\x3c\xa1\x35\x08\xa9\x32\x43\xce" + "\x48\xc0\x45\xdc\x00\x7f\x26\xa2\x1b\x3f\x5e\x0e\x9d\xf4\xc2\x0a", + /* HMAC-SHA3-512 */ + "\x5a\x4b\xfe\xab\x61\x66\x42\x7c\x7a\x36\x47\xb7\x47\x29\x2b\x83" + "\x84\x53\x7c\xdb\x89\xaf\xb3\xbf\x56\x65\xe4\xc5\xe7\x09\x35\x0b" + "\x28\x7b\xae\xc9\x21\xfd\x7c\xa0\xee\x7a\x0c\x31\xd0\x22\xa9\x5e" + "\x1f\xc9\x2b\xa9\xd7\x7d\xf8\x83\x96\x02\x75\xbe\xb4\xe6\x20\x24", + + /* key = 0b..., input = Hi There */ + /* HMAC-SHA3-224 */ + "\x3b\x16\x54\x6b\xbc\x7b\xe2\x70\x6a\x03\x1d\xca\xfd\x56\x37\x3d" + "\x98\x84\x36\x76\x41\xd8\xc5\x9a\xf3\xc8\x60\xf7", + /* HMAC-SHA3-256 */ + "\xba\x85\x19\x23\x10\xdf\xfa\x96\xe2\xa3\xa4\x0e\x69\x77\x43\x51" + "\x14\x0b\xb7\x18\x5e\x12\x02\xcd\xcc\x91\x75\x89\xf9\x5e\x16\xbb", + /* HMAC-SHA3-384 */ + "\x68\xd2\xdc\xf7\xfd\x4d\xdd\x0a\x22\x40\xc8\xa4\x37\x30\x5f\x61" + "\xfb\x73\x34\xcf\xb5\xd0\x22\x6e\x1b\xc2\x7d\xc1\x0a\x2e\x72\x3a" + "\x20\xd3\x70\xb4\x77\x43\x13\x0e\x26\xac\x7e\x3d\x53\x28\x86\xbd", + /* HMAC-SHA3-512 */ + "\xeb\x3f\xbd\x4b\x2e\xaa\xb8\xf5\xc5\x04\xbd\x3a\x41\x46\x5a\xac" + "\xec\x15\x77\x0a\x7c\xab\xac\x53\x1e\x48\x2f\x86\x0b\x5e\xc7\xba" + "\x47\xcc\xb2\xc6\xf2\xaf\xce\x8f\x88\xd2\x2b\x6d\xc6\x13\x80\xf2" + "\x3a\x66\x8f\xd3\x88\x8b\xb8\x05\x37\xc0\xa0\xb8\x64\x07\x68\x9e", + + /* key = aa..., output = dd... */ + /* HMAC-SHA3-224 */ + "\x67\x6c\xfc\x7d\x16\x15\x36\x38\x78\x03\x90\x69\x2b\xe1\x42\xd2" + "\xdf\x7c\xe9\x24\xb9\x09\xc0\xc0\x8d\xbf\xdc\x1a", + /* HMAC-SHA3-256 */ + "\x84\xec\x79\x12\x4a\x27\x10\x78\x65\xce\xdd\x8b\xd8\x2d\xa9\x96" + "\x5e\x5e\xd8\xc3\x7b\x0a\xc9\x80\x05\xa7\xf3\x9e\xd5\x8a\x42\x07", + /* HMAC-SHA3-384 */ + "\x27\x5c\xd0\xe6\x61\xbb\x8b\x15\x1c\x64\xd2\x88\xf1\xf7\x82\xfb" + "\x91\xa8\xab\xd5\x68\x58\xd7\x2b\xab\xb2\xd4\x76\xf0\x45\x83\x73" + "\xb4\x1b\x6a\xb5\xbf\x17\x4b\xec\x42\x2e\x53\xfc\x31\x35\xac\x6e", + /* HMAC-SHA3-512 */ + "\x30\x9e\x99\xf9\xec\x07\x5e\xc6\xc6\xd4\x75\xed\xa1\x18\x06\x87" + "\xfc\xf1\x53\x11\x95\x80\x2a\x99\xb5\x67\x74\x49\xa8\x62\x51\x82" + "\x85\x1c\xb3\x32\xaf\xb6\xa8\x9c\x41\x13\x25\xfb\xcb\xcd\x42\xaf" + "\xcb\x7b\x6e\x5a\xab\x7e\xa4\x2c\x66\x0f\x97\xfd\x85\x84\xbf\x03", + + /* key = big key, input = Big Key Input */ + /* HMAC-SHA3-224 */ + "\x29\xe0\x5e\x46\xc4\xa4\x5e\x46\x74\xbf\xd7\x2d\x1a\xd8\x66\xdb" + "\x2d\x0d\x10\x4e\x2b\xfa\xad\x53\x7d\x15\x69\x8b", + /* HMAC-SHA3-256 */ + "\xb5\x5b\x8d\x64\xb6\x9c\x21\xd0\xbf\x20\x5c\xa2\xf7\xb9\xb1\x4e" + "\x88\x21\x61\x2c\x66\xc3\x91\xae\x6c\x95\x16\x85\x83\xe6\xf4\x9b", + /* HMAC-SHA3-384 */ + "\xaa\x91\xb3\xa6\x2f\x56\xa1\xbe\x8c\x3e\x74\x38\xdb\x58\xd9\xd3" + "\x34\xde\xa0\x60\x6d\x8d\x46\xe0\xec\xa9\xf6\x06\x35\x14\xe6\xed" + "\x83\xe6\x7c\x77\x24\x6c\x11\xb5\x90\x82\xb5\x75\xda\x7b\x83\x2d", + /* HMAC-SHA3-512 */ + "\x1c\xc3\xa9\x24\x4a\x4a\x3f\xbd\xc7\x20\x00\x16\x9b\x79\x47\x03" + "\x78\x75\x2c\xb5\xf1\x2e\x62\x7c\xbe\xef\x4e\x8f\x0b\x11\x2b\x32" + "\xa0\xee\xc9\xd0\x4d\x64\x64\x0b\x37\xf4\xdd\x66\xf7\x8b\xb3\xad" + "\x52\x52\x6b\x65\x12\xde\x0d\x7c\xc0\x8b\x60\x01\x6c\x37\xd7\xa8" + + }; + + int i = 0, iMax = sizeof(input) / sizeof(input[0]), + j, jMax = sizeof(hashType) / sizeof(hashType[0]), + ret; + +#ifdef HAVE_FIPS + /* FIPS requires a minimum length for HMAC keys, and "Jefe" is too + * short. Skip it in FIPS builds. */ + i = 1; +#endif + for (; i < iMax; i++) { + for (j = 0; j < jMax; j++) { + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -4100; + + ret = wc_HmacSetKey(&hmac, hashType[j], (byte*)key[i], + (word32)XSTRLEN(key[i])); + if (ret != 0) + return -4101; + ret = wc_HmacUpdate(&hmac, (byte*)input[i], + (word32)XSTRLEN(input[i])); + if (ret != 0) + return -4102; + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) + return -4103; + if (XMEMCMP(hash, output[(i*jMax) + j], hashSz[j]) != 0) + return -4104; + + wc_HmacFree(&hmac); + + if (i > 0) + continue; + + #ifndef HAVE_FIPS + ret = wc_HmacSizeByType(hashType[j]); + if (ret != hashSz[j]) + return -4105; + #endif + } } return 0; @@ -1707,16 +4269,14 @@ int arc4_test(void) for (i = 0; i < times; ++i) { Arc4 enc; Arc4 dec; - int keylen = 8; /* strlen with key 0x00 not good */ + int keylen = 8; /* XSTRLEN with key 0x00 not good */ if (i == 3) keylen = 4; -#ifdef HAVE_CAVIUM - if (wc_Arc4InitCavium(&enc, CAVIUM_DEV_ID) != 0) - return -20001; - if (wc_Arc4InitCavium(&dec, CAVIUM_DEV_ID) != 0) - return -20002; -#endif + if (wc_Arc4Init(&enc, HEAP_HINT, devId) != 0) + return -4200; + if (wc_Arc4Init(&dec, HEAP_HINT, devId) != 0) + return -4201; wc_Arc4SetKey(&enc, (byte*)keys[i], keylen); wc_Arc4SetKey(&dec, (byte*)keys[i], keylen); @@ -1725,16 +4285,14 @@ int arc4_test(void) (word32)test_arc4[i].outLen); wc_Arc4Process(&dec, plain, cipher, (word32)test_arc4[i].outLen); - if (memcmp(plain, test_arc4[i].input, test_arc4[i].outLen)) - return -20 - i; + if (XMEMCMP(plain, test_arc4[i].input, test_arc4[i].outLen)) + return -4202 - i; - if (memcmp(cipher, test_arc4[i].output, test_arc4[i].outLen)) - return -20 - 5 - i; + if (XMEMCMP(cipher, test_arc4[i].output, test_arc4[i].outLen)) + return -4212 - i; -#ifdef HAVE_CAVIUM - wc_Arc4FreeCavium(&enc); - wc_Arc4FreeCavium(&dec); -#endif + wc_Arc4Free(&enc); + wc_Arc4Free(&dec); } return 0; @@ -1800,22 +4358,28 @@ int hc128_test(void) HC128 dec; /* align keys/ivs in plain/cipher buffers */ - memcpy(plain, keys[i], 16); - memcpy(cipher, ivs[i], 16); + XMEMCPY(plain, keys[i], 16); + XMEMCPY(cipher, ivs[i], 16); wc_Hc128_SetKey(&enc, plain, cipher); wc_Hc128_SetKey(&dec, plain, cipher); /* align input */ - memcpy(plain, test_hc128[i].input, test_hc128[i].outLen); - wc_Hc128_Process(&enc, cipher, plain, (word32)test_hc128[i].outLen); - wc_Hc128_Process(&dec, plain, cipher, (word32)test_hc128[i].outLen); + XMEMCPY(plain, test_hc128[i].input, test_hc128[i].outLen); + if (wc_Hc128_Process(&enc, cipher, plain, + (word32)test_hc128[i].outLen) != 0) { + return -4300; + } + if (wc_Hc128_Process(&dec, plain, cipher, + (word32)test_hc128[i].outLen) != 0) { + return -4301; + } - if (memcmp(plain, test_hc128[i].input, test_hc128[i].outLen)) - return -120 - i; + if (XMEMCMP(plain, test_hc128[i].input, test_hc128[i].outLen)) + return -4302 - i; - if (memcmp(cipher, test_hc128[i].output, test_hc128[i].outLen)) - return -120 - 5 - i; + if (XMEMCMP(cipher, test_hc128[i].output, test_hc128[i].outLen)) + return -4312 - i; } #endif /* HAVE_HC128 */ @@ -1873,9 +4437,9 @@ int rabbit_test(void) byte* iv; /* align keys/ivs in plain/cipher buffers */ - memcpy(plain, keys[i], 16); + XMEMCPY(plain, keys[i], 16); if (ivs[i]) { - memcpy(cipher, ivs[i], 8); + XMEMCPY(cipher, ivs[i], 8); iv = cipher; } else iv = NULL; @@ -1883,15 +4447,15 @@ int rabbit_test(void) wc_RabbitSetKey(&dec, plain, iv); /* align input */ - memcpy(plain, test_rabbit[i].input, test_rabbit[i].outLen); + XMEMCPY(plain, test_rabbit[i].input, test_rabbit[i].outLen); wc_RabbitProcess(&enc, cipher, plain, (word32)test_rabbit[i].outLen); wc_RabbitProcess(&dec, plain, cipher, (word32)test_rabbit[i].outLen); - if (memcmp(plain, test_rabbit[i].input, test_rabbit[i].outLen)) - return -130 - i; + if (XMEMCMP(plain, test_rabbit[i].input, test_rabbit[i].outLen)) + return -4400 - i; - if (memcmp(cipher, test_rabbit[i].output, test_rabbit[i].outLen)) - return -130 - 5 - i; + if (XMEMCMP(cipher, test_rabbit[i].output, test_rabbit[i].outLen)) + return -4410 - i; } return 0; @@ -1904,10 +4468,12 @@ int chacha_test(void) { ChaCha enc; ChaCha dec; - byte cipher[32]; - byte plain[32]; + byte cipher[128]; + byte plain[128]; + byte sliver[64]; byte input[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - word32 keySz; + word32 keySz = 32; + int ret = 0; int i; int times = 4; @@ -1945,14 +4511,138 @@ int chacha_test(void) const byte* keys[] = {key1, key2, key3, key4}; - static const byte ivs1[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - static const byte ivs2[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - static const byte ivs3[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}; - static const byte ivs4[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + static const byte ivs1[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + static const byte ivs2[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + static const byte ivs3[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00}; + static const byte ivs4[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; const byte* ivs[] = {ivs1, ivs2, ivs3, ivs4}; +#ifndef BENCH_EMBEDDED + static const byte cipher_big_result[] = { + 0x06, 0xa6, 0x5d, 0x31, 0x21, 0x6c, 0xdb, 0x37, 0x48, 0x7c, 0x01, 0x9d, + 0x72, 0xdf, 0x0a, 0x5b, 0x64, 0x74, 0x20, 0xba, 0x9e, 0xe0, 0x26, 0x7a, + 0xbf, 0xdf, 0x83, 0x34, 0x3b, 0x4f, 0x94, 0x3f, 0x37, 0x89, 0xaf, 0x00, + 0xdf, 0x0f, 0x2e, 0x75, 0x16, 0x41, 0xf6, 0x7a, 0x86, 0x94, 0x9d, 0x32, + 0x56, 0xf0, 0x79, 0x71, 0x68, 0x6f, 0xa6, 0x6b, 0xc6, 0x59, 0x49, 0xf6, + 0x10, 0x34, 0x03, 0x03, 0x16, 0x53, 0x9a, 0x98, 0x2a, 0x46, 0xde, 0x17, + 0x06, 0x65, 0x70, 0xca, 0x0a, 0x1f, 0xab, 0x80, 0x26, 0x96, 0x3f, 0x3e, + 0x7a, 0x3c, 0xa8, 0x87, 0xbb, 0x65, 0xdd, 0x5e, 0x07, 0x7b, 0x34, 0xe0, + 0x56, 0xda, 0x32, 0x13, 0x30, 0xc9, 0x0c, 0xd7, 0xba, 0xe4, 0x1f, 0xa6, + 0x91, 0x4f, 0x72, 0x9f, 0xd9, 0x5c, 0x62, 0x7d, 0xa6, 0xc2, 0xbc, 0x87, + 0xae, 0x64, 0x11, 0x94, 0x3b, 0xbc, 0x6c, 0x23, 0xbd, 0x7d, 0x00, 0xb4, + 0x99, 0xf2, 0x68, 0xb5, 0x59, 0x70, 0x93, 0xad, 0x69, 0xd0, 0xb1, 0x28, + 0x70, 0x92, 0xeb, 0xec, 0x39, 0x80, 0x82, 0xde, 0x44, 0xe2, 0x8a, 0x26, + 0xb3, 0xe9, 0x45, 0xcf, 0x83, 0x76, 0x9f, 0x6a, 0xa0, 0x46, 0x4a, 0x3d, + 0x26, 0x56, 0xaf, 0x49, 0x41, 0x26, 0x1b, 0x6a, 0x41, 0x37, 0x65, 0x91, + 0x72, 0xc4, 0xe7, 0x3c, 0x17, 0x31, 0xae, 0x2e, 0x2b, 0x31, 0x45, 0xe4, + 0x93, 0xd3, 0x10, 0xaa, 0xc5, 0x62, 0xd5, 0x11, 0x4b, 0x57, 0x1d, 0xad, + 0x48, 0x06, 0xd0, 0x0d, 0x98, 0xa5, 0xc6, 0x5b, 0xd0, 0x9e, 0x22, 0xc0, + 0x00, 0x32, 0x5a, 0xf5, 0x1c, 0x89, 0x6d, 0x54, 0x97, 0x55, 0x6b, 0x46, + 0xc5, 0xc7, 0xc4, 0x48, 0x9c, 0xbf, 0x47, 0xdc, 0x03, 0xc4, 0x1b, 0xcb, + 0x65, 0xa6, 0x91, 0x9d, 0x6d, 0xf1, 0xb0, 0x7a, 0x4d, 0x3b, 0x03, 0x95, + 0xf4, 0x8b, 0x0b, 0xae, 0x39, 0xff, 0x3f, 0xf6, 0xc0, 0x14, 0x18, 0x8a, + 0xe5, 0x19, 0xbd, 0xc1, 0xb4, 0x05, 0x4e, 0x29, 0x2f, 0x0b, 0x33, 0x76, + 0x28, 0x16, 0xa4, 0xa6, 0x93, 0x04, 0xb5, 0x55, 0x6b, 0x89, 0x3d, 0xa5, + 0x0f, 0xd3, 0xad, 0xfa, 0xd9, 0xfd, 0x05, 0x5d, 0x48, 0x94, 0x25, 0x5a, + 0x2c, 0x9a, 0x94, 0x80, 0xb0, 0xe7, 0xcb, 0x4d, 0x77, 0xbf, 0xca, 0xd8, + 0x55, 0x48, 0xbd, 0x66, 0xb1, 0x85, 0x81, 0xb1, 0x37, 0x79, 0xab, 0x52, + 0x08, 0x14, 0x12, 0xac, 0xcd, 0x45, 0x4d, 0x53, 0x6b, 0xca, 0x96, 0xc7, + 0x3b, 0x2f, 0x73, 0xb1, 0x5a, 0x23, 0xbd, 0x65, 0xd5, 0xea, 0x17, 0xb3, + 0xdc, 0xa1, 0x17, 0x1b, 0x2d, 0xb3, 0x9c, 0xd0, 0xdb, 0x41, 0x77, 0xef, + 0x93, 0x20, 0x52, 0x3e, 0x9d, 0xf5, 0xbf, 0x33, 0xf7, 0x52, 0xc1, 0x90, + 0xa0, 0x15, 0x17, 0xce, 0xf7, 0xf7, 0xd0, 0x3a, 0x3b, 0xd1, 0x72, 0x56, + 0x31, 0x81, 0xae, 0x60, 0xab, 0x40, 0xc1, 0xd1, 0x28, 0x77, 0x53, 0xac, + 0x9f, 0x11, 0x0a, 0x88, 0x36, 0x4b, 0xda, 0x57, 0xa7, 0x28, 0x5c, 0x85, + 0xd3, 0x85, 0x9b, 0x79, 0xad, 0x05, 0x1c, 0x37, 0x14, 0x5e, 0x0d, 0xd0, + 0x23, 0x03, 0x42, 0x1d, 0x48, 0x5d, 0xc5, 0x3c, 0x5a, 0x08, 0xa9, 0x0d, + 0x6e, 0x82, 0x7c, 0x2e, 0x3c, 0x41, 0xcc, 0x96, 0x8e, 0xad, 0xee, 0x2a, + 0x61, 0x0b, 0x16, 0x0f, 0xa9, 0x24, 0x40, 0x85, 0xbc, 0x9f, 0x28, 0x8d, + 0xe6, 0x68, 0x4d, 0x8f, 0x30, 0x48, 0xd9, 0x73, 0x73, 0x6c, 0x9a, 0x7f, + 0x67, 0xf7, 0xde, 0x4c, 0x0a, 0x8b, 0xe4, 0xb3, 0x08, 0x2a, 0x52, 0xda, + 0x54, 0xee, 0xcd, 0xb5, 0x62, 0x4a, 0x26, 0x20, 0xfb, 0x40, 0xbb, 0x39, + 0x3a, 0x0f, 0x09, 0xe8, 0x00, 0xd1, 0x24, 0x97, 0x60, 0xe9, 0x83, 0x83, + 0xfe, 0x9f, 0x9c, 0x15, 0xcf, 0x69, 0x03, 0x9f, 0x03, 0xe1, 0xe8, 0x6e, + 0xbd, 0x87, 0x58, 0x68, 0xee, 0xec, 0xd8, 0x29, 0x46, 0x23, 0x49, 0x92, + 0x72, 0x95, 0x5b, 0x49, 0xca, 0xe0, 0x45, 0x59, 0xb2, 0xca, 0xf4, 0xfc, + 0xb7, 0x59, 0x37, 0x49, 0x28, 0xbc, 0xf3, 0xd7, 0x61, 0xbc, 0x4b, 0xf3, + 0xa9, 0x4b, 0x2f, 0x05, 0xa8, 0x01, 0xa5, 0xdc, 0x00, 0x6e, 0x01, 0xb6, + 0x45, 0x3c, 0xd5, 0x49, 0x7d, 0x5c, 0x25, 0xe8, 0x31, 0x87, 0xb2, 0xb9, + 0xbf, 0xb3, 0x01, 0x62, 0x0c, 0xd0, 0x48, 0x77, 0xa2, 0x34, 0x0f, 0x16, + 0x22, 0x28, 0xee, 0x54, 0x08, 0x93, 0x3b, 0xe4, 0xde, 0x7e, 0x63, 0xf7, + 0x97, 0x16, 0x5d, 0x71, 0x58, 0xc2, 0x2e, 0xf2, 0x36, 0xa6, 0x12, 0x65, + 0x94, 0x17, 0xac, 0x66, 0x23, 0x7e, 0xc6, 0x72, 0x79, 0x24, 0xce, 0x8f, + 0x55, 0x19, 0x97, 0x44, 0xfc, 0x55, 0xec, 0x85, 0x26, 0x27, 0xdb, 0x38, + 0xb1, 0x42, 0x0a, 0xdd, 0x05, 0x99, 0x28, 0xeb, 0x03, 0x6c, 0x9a, 0xe9, + 0x17, 0xf6, 0x2c, 0xb0, 0xfe, 0xe7, 0xa4, 0xa7, 0x31, 0xda, 0x4d, 0xb0, + 0x29, 0xdb, 0xdd, 0x8d, 0x12, 0x13, 0x9c, 0xb4, 0xcc, 0x83, 0x97, 0xfb, + 0x1a, 0xdc, 0x08, 0xd6, 0x30, 0x62, 0xe8, 0xeb, 0x8b, 0x61, 0xcb, 0x1d, + 0x06, 0xe3, 0xa5, 0x4d, 0x35, 0xdb, 0x59, 0xa8, 0x2d, 0x87, 0x27, 0x44, + 0x6f, 0xc0, 0x38, 0x97, 0xe4, 0x85, 0x00, 0x02, 0x09, 0xf6, 0x69, 0x3a, + 0xcf, 0x08, 0x1b, 0x21, 0xbb, 0x79, 0xb1, 0xa1, 0x34, 0x09, 0xe0, 0x80, + 0xca, 0xb0, 0x78, 0x8a, 0x11, 0x97, 0xd4, 0x07, 0xbe, 0x1b, 0x6a, 0x5d, + 0xdb, 0xd6, 0x1f, 0x76, 0x6b, 0x16, 0xf0, 0x58, 0x84, 0x5f, 0x59, 0xce, + 0x62, 0x34, 0xc3, 0xdf, 0x94, 0xb8, 0x2f, 0x84, 0x68, 0xf0, 0xb8, 0x51, + 0xd9, 0x6d, 0x8e, 0x4a, 0x1d, 0xe6, 0x5c, 0xd8, 0x86, 0x25, 0xe3, 0x24, + 0xfd, 0x21, 0x61, 0x13, 0x48, 0x3e, 0xf6, 0x7d, 0xa6, 0x71, 0x9b, 0xd2, + 0x6e, 0xe6, 0xd2, 0x08, 0x94, 0x62, 0x6c, 0x98, 0xfe, 0x2f, 0x9c, 0x88, + 0x7e, 0x78, 0x15, 0x02, 0x00, 0xf0, 0xba, 0x24, 0x91, 0xf2, 0xdc, 0x47, + 0x51, 0x4d, 0x15, 0x5e, 0x91, 0x5f, 0x57, 0x5b, 0x1d, 0x35, 0x24, 0x45, + 0x75, 0x9b, 0x88, 0x75, 0xf1, 0x2f, 0x85, 0xe7, 0x89, 0xd1, 0x01, 0xb4, + 0xc8, 0x18, 0xb7, 0x97, 0xef, 0x4b, 0x90, 0xf4, 0xbf, 0x10, 0x27, 0x3c, + 0x60, 0xff, 0xc4, 0x94, 0x20, 0x2f, 0x93, 0x4b, 0x4d, 0xe3, 0x80, 0xf7, + 0x2c, 0x71, 0xd9, 0xe3, 0x68, 0xb4, 0x77, 0x2b, 0xc7, 0x0d, 0x39, 0x92, + 0xef, 0x91, 0x0d, 0xb2, 0x11, 0x50, 0x0e, 0xe8, 0xad, 0x3b, 0xf6, 0xb5, + 0xc6, 0x14, 0x4d, 0x33, 0x53, 0xa7, 0x60, 0x15, 0xc7, 0x27, 0x51, 0xdc, + 0x54, 0x29, 0xa7, 0x0d, 0x6a, 0x7b, 0x72, 0x13, 0xad, 0x7d, 0x41, 0x19, + 0x4e, 0x42, 0x49, 0xcc, 0x42, 0xe4, 0xbd, 0x99, 0x13, 0xd9, 0x7f, 0xf3, + 0x38, 0xa4, 0xb6, 0x33, 0xed, 0x07, 0x48, 0x7e, 0x8e, 0x82, 0xfe, 0x3a, + 0x9d, 0x75, 0x93, 0xba, 0x25, 0x4e, 0x37, 0x3c, 0x0c, 0xd5, 0x69, 0xa9, + 0x2d, 0x9e, 0xfd, 0xe8, 0xbb, 0xf5, 0x0c, 0xe2, 0x86, 0xb9, 0x5e, 0x6f, + 0x28, 0xe4, 0x19, 0xb3, 0x0b, 0xa4, 0x86, 0xd7, 0x24, 0xd0, 0xb8, 0x89, + 0x7b, 0x76, 0xec, 0x05, 0x10, 0x5b, 0x68, 0xe9, 0x58, 0x66, 0xa3, 0xc5, + 0xb6, 0x63, 0x20, 0x0e, 0x0e, 0xea, 0x3d, 0x61, 0x5e, 0xda, 0x3d, 0x3c, + 0xf9, 0xfd, 0xed, 0xa9, 0xdb, 0x52, 0x94, 0x8a, 0x00, 0xca, 0x3c, 0x8d, + 0x66, 0x8f, 0xb0, 0xf0, 0x5a, 0xca, 0x3f, 0x63, 0x71, 0xbf, 0xca, 0x99, + 0x37, 0x9b, 0x75, 0x97, 0x89, 0x10, 0x6e, 0xcf, 0xf2, 0xf5, 0xe3, 0xd5, + 0x45, 0x9b, 0xad, 0x10, 0x71, 0x6c, 0x5f, 0x6f, 0x7f, 0x22, 0x77, 0x18, + 0x2f, 0xf9, 0x99, 0xc5, 0x69, 0x58, 0x03, 0x12, 0x86, 0x82, 0x3e, 0xbf, + 0xc2, 0x12, 0x35, 0x43, 0xa3, 0xd9, 0x18, 0x4f, 0x41, 0x11, 0x6b, 0xf3, + 0x67, 0xaf, 0x3d, 0x78, 0xe4, 0x22, 0x2d, 0xb3, 0x48, 0x43, 0x31, 0x1d, + 0xef, 0xa8, 0xba, 0x49, 0x8e, 0xa9, 0xa7, 0xb6, 0x18, 0x77, 0x84, 0xca, + 0xbd, 0xa2, 0x02, 0x1b, 0x6a, 0xf8, 0x5f, 0xda, 0xff, 0xcf, 0x01, 0x6a, + 0x86, 0x69, 0xa9, 0xe9, 0xcb, 0x60, 0x1e, 0x15, 0xdc, 0x8f, 0x5d, 0x39, + 0xb5, 0xce, 0x55, 0x5f, 0x47, 0x97, 0xb1, 0x19, 0x6e, 0x21, 0xd6, 0x13, + 0x39, 0xb2, 0x24, 0xe0, 0x62, 0x82, 0x9f, 0xed, 0x12, 0x81, 0xed, 0xee, + 0xab, 0xd0, 0x2f, 0x19, 0x89, 0x3f, 0x57, 0x2e, 0xc2, 0xe2, 0x67, 0xe8, + 0xae, 0x03, 0x56, 0xba, 0xd4, 0xd0, 0xa4, 0x89, 0x03, 0x06, 0x5b, 0xcc, + 0xf2, 0x22, 0xb8, 0x0e, 0x76, 0x79, 0x4a, 0x42, 0x1d, 0x37, 0x51, 0x5a, + 0xaa, 0x46, 0x6c, 0x2a, 0xdd, 0x66, 0xfe, 0xc6, 0x68, 0xc3, 0x38, 0xa2, + 0xae, 0x5b, 0x98, 0x24, 0x5d, 0x43, 0x05, 0x82, 0x38, 0x12, 0xd3, 0xd1, + 0x75, 0x2d, 0x4f, 0x61, 0xbd, 0xb9, 0x10, 0x87, 0x44, 0x2a, 0x78, 0x07, + 0xff, 0xf4, 0x0f, 0xa1, 0xf3, 0x68, 0x9f, 0xbe, 0xae, 0xa2, 0x91, 0xf0, + 0xc7, 0x55, 0x7a, 0x52, 0xd5, 0xa3, 0x8d, 0x6f, 0xe4, 0x90, 0x5c, 0xf3, + 0x5f, 0xce, 0x3d, 0x23, 0xf9, 0x8e, 0xae, 0x14, 0xfb, 0x82, 0x9a, 0xa3, + 0x04, 0x5f, 0xbf, 0xad, 0x3e, 0xf2, 0x97, 0x0a, 0x60, 0x40, 0x70, 0x19, + 0x72, 0xad, 0x66, 0xfb, 0x78, 0x1b, 0x84, 0x6c, 0x98, 0xbc, 0x8c, 0xf8, + 0x4f, 0xcb, 0xb5, 0xf6, 0xaf, 0x7a, 0xb7, 0x93, 0xef, 0x67, 0x48, 0x02, + 0x2c, 0xcb, 0xe6, 0x77, 0x0f, 0x7b, 0xc1, 0xee, 0xc5, 0xb6, 0x2d, 0x7e, + 0x62, 0xa0, 0xc0, 0xa7, 0xa5, 0x80, 0x31, 0x92, 0x50, 0xa1, 0x28, 0x22, + 0x95, 0x03, 0x17, 0xd1, 0x0f, 0xf6, 0x08, 0xe5, 0xec + }; +#define CHACHA_BIG_TEST_SIZE 1305 +#ifndef WOLFSSL_SMALL_STACK + byte cipher_big[CHACHA_BIG_TEST_SIZE] = {0}; + byte plain_big[CHACHA_BIG_TEST_SIZE] = {0}; + byte input_big[CHACHA_BIG_TEST_SIZE] = {0}; +#else + byte* cipher_big; + byte* plain_big; + byte* input_big; +#endif /* WOLFSSL_SMALL_STACK */ + int block_size; +#endif /* BENCH_EMBEDDED */ byte a[] = {0x76,0xb8,0xe0,0xad,0xa0,0xf1,0x3d,0x90}; byte b[] = {0x45,0x40,0xf0,0x5a,0x9f,0x1f,0xb2,0x96}; @@ -1966,6 +4656,29 @@ int chacha_test(void) test_chacha[2] = c; test_chacha[3] = d; +#ifndef BENCH_EMBEDDED +#ifdef WOLFSSL_SMALL_STACK + cipher_big = (byte*)XMALLOC(CHACHA_BIG_TEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cipher_big == NULL) { + return MEMORY_E; + } + plain_big = (byte*)XMALLOC(CHACHA_BIG_TEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (plain_big == NULL) { + return MEMORY_E; + } + input_big = (byte*)XMALLOC(CHACHA_BIG_TEST_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (input_big == NULL) { + return MEMORY_E; + } + XMEMSET(cipher_big, 0, CHACHA_BIG_TEST_SIZE); + XMEMSET(plain_big, 0, CHACHA_BIG_TEST_SIZE); + XMEMSET(input_big, 0, CHACHA_BIG_TEST_SIZE); +#endif /* WOLFSSL_SMALL_STACK */ +#endif /* BENCH_EMBEDDED */ + for (i = 0; i < times; ++i) { if (i < 3) { keySz = 32; @@ -1978,23 +4691,115 @@ int chacha_test(void) XMEMSET(cipher, 0, 32); XMEMCPY(cipher + 4, ivs[i], 8); - wc_Chacha_SetKey(&enc, keys[i], keySz); - wc_Chacha_SetKey(&dec, keys[i], keySz); + ret |= wc_Chacha_SetKey(&enc, keys[i], keySz); + ret |= wc_Chacha_SetKey(&dec, keys[i], keySz); + if (ret != 0) + return ret; - wc_Chacha_SetIV(&enc, cipher, 0); - wc_Chacha_SetIV(&dec, cipher, 0); + ret |= wc_Chacha_SetIV(&enc, cipher, 0); + ret |= wc_Chacha_SetIV(&dec, cipher, 0); + if (ret != 0) + return ret; XMEMCPY(plain, input, 8); - wc_Chacha_Process(&enc, cipher, plain, (word32)8); - wc_Chacha_Process(&dec, plain, cipher, (word32)8); + ret |= wc_Chacha_Process(&enc, cipher, plain, (word32)8); + ret |= wc_Chacha_Process(&dec, plain, cipher, (word32)8); + if (ret != 0) + return ret; - if (memcmp(test_chacha[i], cipher, 8)) - return -130 - 5 - i; + if (XMEMCMP(test_chacha[i], cipher, 8)) + return -4500 - i; - if (memcmp(plain, input, 8)) - return -130 - i; + if (XMEMCMP(plain, input, 8)) + return -4510 - i; } + /* test of starting at a different counter + encrypts all of the information and decrypts starting at 2nd chunk */ + XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(sliver, 1, sizeof(sliver)); /* set as 1's to not match plain */ + XMEMSET(cipher, 0, sizeof(cipher)); + XMEMCPY(cipher + 4, ivs[0], 8); + + ret |= wc_Chacha_SetKey(&enc, keys[0], keySz); + ret |= wc_Chacha_SetKey(&dec, keys[0], keySz); + if (ret != 0) + return ret; + + ret |= wc_Chacha_SetIV(&enc, cipher, 0); + ret |= wc_Chacha_SetIV(&dec, cipher, 1); + if (ret != 0) + return ret; + + ret |= wc_Chacha_Process(&enc, cipher, plain, sizeof(plain)); + ret |= wc_Chacha_Process(&dec, sliver, cipher + 64, sizeof(sliver)); + if (ret != 0) + return ret; + + if (XMEMCMP(plain + 64, sliver, 64)) + return -4520; + +#ifndef BENCH_EMBEDDED + /* test of encrypting more data */ + keySz = 32; + + ret |= wc_Chacha_SetKey(&enc, keys[0], keySz); + ret |= wc_Chacha_SetKey(&dec, keys[0], keySz); + if (ret != 0) + return ret; + + ret |= wc_Chacha_SetIV(&enc, ivs[2], 0); + ret |= wc_Chacha_SetIV(&dec, ivs[2], 0); + if (ret != 0) + return ret; + + ret |= wc_Chacha_Process(&enc, cipher_big, plain_big, CHACHA_BIG_TEST_SIZE); + ret |= wc_Chacha_Process(&dec, plain_big, cipher_big, + CHACHA_BIG_TEST_SIZE); + if (ret != 0) + return ret; + + if (XMEMCMP(plain_big, input_big, CHACHA_BIG_TEST_SIZE)) + return -4521; + + if (XMEMCMP(cipher_big, cipher_big_result, CHACHA_BIG_TEST_SIZE)) + return -4522; + + for (i = 0; i < 18; ++i) { + /* this will test all paths */ + // block sizes: 1 2 3 4 7 8 15 16 31 32 63 64 127 128 255 256 511 512 + block_size = (2 << (i%9)) - (i<9?1:0); + keySz = 32; + + ret |= wc_Chacha_SetKey(&enc, keys[0], keySz); + ret |= wc_Chacha_SetKey(&dec, keys[0], keySz); + if (ret != 0) + return ret; + + ret |= wc_Chacha_SetIV(&enc, ivs[2], 0); + ret |= wc_Chacha_SetIV(&dec, ivs[2], 0); + if (ret != 0) + return ret; + + ret |= wc_Chacha_Process(&enc, cipher_big, plain_big, block_size); + ret |= wc_Chacha_Process(&dec, plain_big, cipher_big, block_size); + if (ret != 0) + return ret; + + if (XMEMCMP(plain_big, input_big, block_size)) + return -4523-i; + + if (XMEMCMP(cipher_big, cipher_big_result, block_size)) + return -4524-i; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(cipher_big, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(plain_big, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(input_big, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif /* WOLFSSL_SMALL_STACK */ +#endif /* BENCH_EMBEDDED */ + return 0; } #endif /* HAVE_CHACHA */ @@ -2008,7 +4813,7 @@ int poly1305_test(void) byte tag[16]; Poly1305 enc; - const byte msg[] = + static const byte msg1[] = { 0x43,0x72,0x79,0x70,0x74,0x6f,0x67,0x72, 0x61,0x70,0x68,0x69,0x63,0x20,0x46,0x6f, @@ -2017,13 +4822,13 @@ int poly1305_test(void) 0x75,0x70 }; - const byte msg2[] = + static const byte msg2[] = { 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x77,0x6f,0x72, 0x6c,0x64,0x21 }; - const byte msg3[] = + static const byte msg3[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, @@ -2031,61 +4836,181 @@ int poly1305_test(void) 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - const byte correct[] = + static const byte msg4[] = + { + 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 + }; + + static const byte msg5[] = + { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + }; + + static const byte msg6[] = + { + 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, + 0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94, + 0x1a,0x71,0xde,0x0a,0x9e,0x06,0x0b,0x29, + 0xa9,0xe2,0xb5,0xa7,0x36,0xee,0x62,0xd6, + 0x3d,0xbe,0xa4,0x5e,0x8c,0xa9,0x67,0x12, + 0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94, + 0x05,0xd6,0xa5,0xb6,0x7e,0xcd,0x3b,0x36, + 0x92,0xdd,0xbd,0x7f,0x2d,0x77,0x8b,0x8c, + 0x7b,0x86,0xaf,0xbc,0x53,0xef,0x7e,0xc2, + 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 + }; + + byte additional[] = + { + 0x50,0x51,0x52,0x53,0xc0,0xc1,0xc2,0xc3, + 0xc4,0xc5,0xc6,0xc7 + }; + + 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 - }; - const byte correct2[] = + static const byte correct2[] = { 0xa6,0xf7,0x45,0x00,0x8f,0x81,0xc9,0x16, 0xa2,0x0d,0xcc,0x74,0xee,0xf2,0xb2,0xf0 }; - const byte correct3[] = + static const byte correct3[] = { 0x49,0xec,0x78,0x09,0x0e,0x48,0x1e,0xc6, 0xc2,0x6b,0x33,0xb9,0x1c,0xcc,0x03,0x07 }; - const byte key[] = { + static const byte correct4[] = + { + 0x1a,0xe1,0x0b,0x59,0x4f,0x09,0xe2,0x6a, + 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 correct6[] = + { + 0xea,0x11,0x5c,0x4f,0xd0,0xc0,0x10,0xae, + 0xf7,0xdf,0xda,0x77,0xa2,0xe9,0xaf,0xca + }; + + static const byte key[] = { 0x85,0xd6,0xbe,0x78,0x57,0x55,0x6d,0x33, 0x7f,0x44,0x52,0xfe,0x42,0xd5,0x06,0xa8, 0x01,0x03,0x80,0x8a,0xfb,0x0d,0xb2,0xfd, 0x4a,0xbf,0xf6,0xaf,0x41,0x49,0xf5,0x1b }; - const byte key2[] = { + static const byte key2[] = { 0x74,0x68,0x69,0x73,0x20,0x69,0x73,0x20, 0x33,0x32,0x2d,0x62,0x79,0x74,0x65,0x20, 0x6b,0x65,0x79,0x20,0x66,0x6f,0x72,0x20, 0x50,0x6f,0x6c,0x79,0x31,0x33,0x30,0x35 }; - 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 key4[] = { + 0x7b,0xac,0x2b,0x25,0x2d,0xb4,0x47,0xaf, + 0x09,0xb6,0x7a,0x55,0xa4,0xe9,0x55,0x84, + 0x0a,0xe1,0xd6,0x73,0x10,0x75,0xd9,0xeb, + 0x2a,0x93,0x75,0x78,0x3e,0xd5,0x53,0xff + }; - for (i = 0; i < 3; i++) { + 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 + }; + + const byte* msgs[] = {NULL, msg1, msg2, msg3, msg5, msg6}; + word32 szm[] = {0, sizeof(msg1), sizeof(msg2), + sizeof(msg3), sizeof(msg5), sizeof(msg6)}; + const byte* keys[] = {key, key, key2, key2, key5, key}; + const byte* tests[] = {correct0, correct1, correct2, correct3, correct5, + correct6}; + + for (i = 0; i < 6; i++) { ret = wc_Poly1305SetKey(&enc, keys[i], 32); if (ret != 0) - return -1001; + return -4600 - i; ret = wc_Poly1305Update(&enc, msgs[i], szm[i]); if (ret != 0) - return -1005; + return -4610 - i; ret = wc_Poly1305Final(&enc, tag); if (ret != 0) - return -60; + return -4620 - i; - if (memcmp(tag, tests[i], sizeof(tag))) - return -61; + if (XMEMCMP(tag, tests[i], sizeof(tag))) + return -4630 - 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 -4640; + + ret = wc_Poly1305_MAC(&enc, additional, sizeof(additional), + (byte*)msg4, sizeof(msg4), tag, sizeof(tag)); + if (ret != 0) + return -4641; + + if (XMEMCMP(tag, correct4, sizeof(tag))) + return -4642; + + /* Check fail of TLS MAC function if altering additional data */ + XMEMSET(tag, 0, sizeof(tag)); + additional[0]++; + ret = wc_Poly1305_MAC(&enc, additional, sizeof(additional), + (byte*)msg4, sizeof(msg4), tag, sizeof(tag)); + if (ret != 0) + return -4643; + + if (XMEMCMP(tag, correct4, sizeof(tag)) == 0) + return -4644; + + return 0; } #endif /* HAVE_POLY1305 */ @@ -2254,95 +5179,350 @@ int chacha20_poly1305_aead_test(void) 0x39, 0x23, 0x36, 0xfe, 0xa1, 0x85, 0x1f, 0x38 }; - byte generatedCiphertext[272]; - byte generatedPlaintext[272]; + byte generatedCiphertext[265]; /* max plaintext2/cipher2 */ + byte generatedPlaintext[265]; /* max plaintext2/cipher2 */ byte generatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]; int err; + ChaChaPoly_Aead aead; + +#if !defined(USE_INTEL_CHACHA_SPEEDUP) && !defined(WOLFSSL_ARMASM) + #define TEST_SMALL_CHACHA_CHUNKS 32 +#else + #define TEST_SMALL_CHACHA_CHUNKS 64 +#endif + #ifdef TEST_SMALL_CHACHA_CHUNKS + word32 testLen; + #endif + XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext)); XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag)); XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext)); - /* Test #1 */ + /* Parameter Validation testing */ + /* Encrypt */ + err = wc_ChaCha20Poly1305_Encrypt(NULL, iv1, aad1, sizeof(aad1), plaintext1, + sizeof(plaintext1), generatedCiphertext, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -4700; + err = wc_ChaCha20Poly1305_Encrypt(key1, NULL, aad1, sizeof(aad1), + plaintext1, sizeof(plaintext1), generatedCiphertext, + generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -4701; + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), NULL, + sizeof(plaintext1), generatedCiphertext, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -4702; + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), plaintext1, + sizeof(plaintext1), NULL, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -4703; + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), plaintext1, + sizeof(plaintext1), generatedCiphertext, NULL); + if (err != BAD_FUNC_ARG) + return -4704; + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), plaintext1, + 0, generatedCiphertext, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -4705; + /* Decrypt */ + err = wc_ChaCha20Poly1305_Decrypt(NULL, iv2, aad2, sizeof(aad2), cipher2, + sizeof(cipher2), authTag2, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -4706; + err = wc_ChaCha20Poly1305_Decrypt(key2, NULL, aad2, sizeof(aad2), cipher2, + sizeof(cipher2), authTag2, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -4707; + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), NULL, + sizeof(cipher2), authTag2, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -4708; + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), cipher2, + sizeof(cipher2), NULL, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -4709; + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), cipher2, + sizeof(cipher2), authTag2, NULL); + if (err != BAD_FUNC_ARG) + return -4710; + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), cipher2, + 0, authTag2, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -4711; + + /* 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 -4712; } - - if (XMEMCMP(generatedAuthTag, authTag1, sizeof(authTag1))) - { - return -1065; + if (XMEMCMP(generatedAuthTag, authTag1, sizeof(authTag1))) { + return -4713; } /* -- Verify decryption works */ - err = wc_ChaCha20Poly1305_Decrypt(key1, iv1, 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 -4714; } + XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext)); XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag)); XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext)); /* Test #2 */ - err = wc_ChaCha20Poly1305_Encrypt(key2, iv2, 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 -4715; } - - if (XMEMCMP(generatedAuthTag, authTag2, sizeof(authTag2))) - { - return -1068; + if (XMEMCMP(generatedAuthTag, authTag2, sizeof(authTag2))) { + return -4716; } /* -- Verify decryption works */ - err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, 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 -4717; + } + + + /* AEAD init/update/final */ + err = wc_ChaCha20Poly1305_Init(NULL, key1, iv1, + CHACHA20_POLY1305_AEAD_DECRYPT); + if (err != BAD_FUNC_ARG) + return -4718; + err = wc_ChaCha20Poly1305_Init(&aead, NULL, iv1, + CHACHA20_POLY1305_AEAD_DECRYPT); + if (err != BAD_FUNC_ARG) + return -4719; + err = wc_ChaCha20Poly1305_Init(&aead, key1, NULL, + CHACHA20_POLY1305_AEAD_DECRYPT); + if (err != BAD_FUNC_ARG) + return -4720; + err = wc_ChaCha20Poly1305_UpdateAad(NULL, aad1, sizeof(aad1)); + if (err != BAD_FUNC_ARG) + return -4721; + err = wc_ChaCha20Poly1305_UpdateAad(&aead, NULL, sizeof(aad1)); + if (err != BAD_FUNC_ARG) + return -4722; + err = wc_ChaCha20Poly1305_UpdateData(NULL, generatedPlaintext, + generatedPlaintext, sizeof(plaintext1)); + if (err != BAD_FUNC_ARG) + return -4723; + err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedPlaintext, NULL, + sizeof(plaintext1)); + if (err != BAD_FUNC_ARG) + return -4724; + err = wc_ChaCha20Poly1305_UpdateData(&aead, NULL, generatedPlaintext, + sizeof(plaintext1)); + if (err != BAD_FUNC_ARG) + return -4725; + err = wc_ChaCha20Poly1305_Final(NULL, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -4726; + err = wc_ChaCha20Poly1305_Final(&aead, NULL); + if (err != BAD_FUNC_ARG) + return -4727; + + /* AEAD init/update/final - state tests */ + aead.state = CHACHA20_POLY1305_STATE_INIT; + err = wc_ChaCha20Poly1305_UpdateAad(&aead, aad1, sizeof(aad1)); + if (err != BAD_STATE_E) + return -4728; + aead.state = CHACHA20_POLY1305_STATE_DATA; + err = wc_ChaCha20Poly1305_UpdateAad(&aead, aad1, sizeof(aad1)); + if (err != BAD_STATE_E) + return -4729; + aead.state = CHACHA20_POLY1305_STATE_INIT; + err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedPlaintext, + generatedPlaintext, sizeof(plaintext1)); + if (err != BAD_STATE_E) + return -4730; + aead.state = CHACHA20_POLY1305_STATE_INIT; + err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag); + if (err != BAD_STATE_E) + return -4731; + aead.state = CHACHA20_POLY1305_STATE_READY; + err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag); + if (err != BAD_STATE_E) + return -4732; + + XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext)); + XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag)); + XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext)); + + /* Test 1 - Encrypt */ + err = wc_ChaCha20Poly1305_Init(&aead, key1, iv1, + CHACHA20_POLY1305_AEAD_ENCRYPT); + if (err != 0) + return -4733; + err = wc_ChaCha20Poly1305_UpdateAad(&aead, aad1, sizeof(aad1)); + if (err != 0) + return -4734; +#ifdef TEST_SMALL_CHACHA_CHUNKS + /* test doing data in smaller chunks */ + for (testLen=0; testLen TEST_SMALL_CHACHA_CHUNKS) + dataLen = TEST_SMALL_CHACHA_CHUNKS; + err = wc_ChaCha20Poly1305_UpdateData(&aead, &plaintext1[testLen], + &generatedCiphertext[testLen], dataLen); + if (err != 0) + return -4735; + testLen += dataLen; + } +#else + err = wc_ChaCha20Poly1305_UpdateData(&aead, plaintext1, + generatedCiphertext, sizeof(plaintext1)); +#endif + err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag); + if (err != 0) + return -4736; + err = wc_ChaCha20Poly1305_CheckTag(generatedAuthTag, authTag1); + if (err != 0) + return -4737; + if (XMEMCMP(generatedCiphertext, cipher1, sizeof(cipher1))) { + return -4738; + } + + /* Test 1 - Decrypt */ + err = wc_ChaCha20Poly1305_Init(&aead, key1, iv1, + CHACHA20_POLY1305_AEAD_DECRYPT); + if (err != 0) + return -4739; + err = wc_ChaCha20Poly1305_UpdateAad(&aead, aad1, sizeof(aad1)); + if (err != 0) + return -4740; +#ifdef TEST_SMALL_CHACHA_CHUNKS + /* test doing data in smaller chunks */ + for (testLen=0; testLen TEST_SMALL_CHACHA_CHUNKS) + dataLen = TEST_SMALL_CHACHA_CHUNKS; + err = wc_ChaCha20Poly1305_UpdateData(&aead, + &generatedCiphertext[testLen], &generatedPlaintext[testLen], + dataLen); + if (err != 0) + return -4741; + testLen += dataLen; + } +#else + err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedCiphertext, + generatedPlaintext, sizeof(cipher1)); +#endif + err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag); + if (err != 0) + return -4742; + err = wc_ChaCha20Poly1305_CheckTag(generatedAuthTag, authTag1); + if (err != 0) + return -4743; + if (XMEMCMP(generatedPlaintext, plaintext1, sizeof(plaintext1))) { + return -4744; + } + + XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext)); + XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag)); + XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext)); + + /* Test 2 - Encrypt */ + err = wc_ChaCha20Poly1305_Init(&aead, key2, iv2, + CHACHA20_POLY1305_AEAD_ENCRYPT); + if (err != 0) + return -4745; + err = wc_ChaCha20Poly1305_UpdateAad(&aead, aad2, sizeof(aad2)); + if (err != 0) + return -4746; +#ifdef TEST_SMALL_CHACHA_CHUNKS + /* test doing data in smaller chunks */ + for (testLen=0; testLen TEST_SMALL_CHACHA_CHUNKS) + dataLen = TEST_SMALL_CHACHA_CHUNKS; + err = wc_ChaCha20Poly1305_UpdateData(&aead, &plaintext2[testLen], + &generatedCiphertext[testLen], dataLen); + if (err != 0) + return -4747; + testLen += dataLen; + } +#else + err = wc_ChaCha20Poly1305_UpdateData(&aead, plaintext2, generatedCiphertext, + sizeof(plaintext2)); +#endif + err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag); + if (err != 0) + return -4748; + err = wc_ChaCha20Poly1305_CheckTag(generatedAuthTag, authTag2); + if (err != 0) + return -4749; + if (XMEMCMP(generatedCiphertext, cipher2, sizeof(cipher2))) { + return -4750; + } + + /* Test 2 - Decrypt */ + err = wc_ChaCha20Poly1305_Init(&aead, key2, iv2, + CHACHA20_POLY1305_AEAD_DECRYPT); + if (err != 0) + return -4751; + err = wc_ChaCha20Poly1305_UpdateAad(&aead, aad2, sizeof(aad2)); + if (err != 0) + return -4752; +#ifdef TEST_SMALL_CHACHA_CHUNKS + /* test doing data in smaller chunks */ + for (testLen=0; testLen TEST_SMALL_CHACHA_CHUNKS) + dataLen = TEST_SMALL_CHACHA_CHUNKS; + err = wc_ChaCha20Poly1305_UpdateData(&aead, + &generatedCiphertext[testLen], &generatedPlaintext[testLen], + dataLen); + if (err != 0) + return -4753; + testLen += dataLen; + } +#else + err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedCiphertext, + generatedPlaintext, sizeof(cipher2)); +#endif + err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag); + if (err != 0) + return -4754; + err = wc_ChaCha20Poly1305_CheckTag(generatedAuthTag, authTag2); + if (err != 0) + return -4755; + if (XMEMCMP(generatedPlaintext, plaintext2, sizeof(plaintext2))) { + return -4756; } return err; @@ -2386,19 +5566,57 @@ int des_test(void) ret = wc_Des_SetKey(&enc, key, iv, DES_ENCRYPTION); if (ret != 0) - return -31; + return -4800; + + ret = wc_Des_CbcEncrypt(&enc, cipher, vector, sizeof(vector)); + if (ret != 0) + return -4801; - wc_Des_CbcEncrypt(&enc, cipher, vector, sizeof(vector)); ret = wc_Des_SetKey(&dec, key, iv, DES_DECRYPTION); if (ret != 0) - return -32; - wc_Des_CbcDecrypt(&dec, plain, cipher, sizeof(cipher)); + return -4802; - if (memcmp(plain, vector, sizeof(plain))) - return -33; + ret = wc_Des_CbcDecrypt(&dec, plain, cipher, sizeof(cipher)); + if (ret != 0) + return -4803; - if (memcmp(cipher, verify, sizeof(cipher))) - return -34; + if (XMEMCMP(plain, vector, sizeof(plain))) + return -4804; + + if (XMEMCMP(cipher, verify, sizeof(cipher))) + return -4805; + + ret = wc_Des_CbcEncryptWithKey(cipher, vector, sizeof(vector), key, iv); + if (ret != 0) + return -4806; + +#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_SHA) + { + EncryptedInfo info; + XMEMSET(&info, 0, sizeof(EncryptedInfo)); + XMEMCPY(info.iv, iv, sizeof(iv)); + info.ivSz = sizeof(iv); + info.keySz = sizeof(key); + info.cipherType = WC_CIPHER_DES; + + ret = wc_BufferKeyEncrypt(&info, cipher, sizeof(cipher), key, + sizeof(key), WC_HASH_TYPE_SHA); + if (ret != 0) + return -4807; + + /* Test invalid info ptr */ + ret = wc_BufferKeyEncrypt(NULL, cipher, sizeof(cipher), key, + sizeof(key), WC_HASH_TYPE_SHA); + if (ret != BAD_FUNC_ARG) + return -4808; + + /* Test invalid hash type */ + ret = wc_BufferKeyEncrypt(&info, cipher, sizeof(cipher), key, + sizeof(key), WC_HASH_TYPE_NONE); + if (ret == 0) + return -4809; + } +#endif return 0; } @@ -2444,46 +5662,1852 @@ int des3_test(void) int ret; -#ifdef HAVE_CAVIUM - if (wc_Des3_InitCavium(&enc, CAVIUM_DEV_ID) != 0) - return -20005; - if (wc_Des3_InitCavium(&dec, CAVIUM_DEV_ID) != 0) - return -20006; -#endif + if (wc_Des3Init(&enc, HEAP_HINT, devId) != 0) + return -4900; + if (wc_Des3Init(&dec, HEAP_HINT, devId) != 0) + return -4901; + ret = wc_Des3_SetKey(&enc, key3, iv3, DES_ENCRYPTION); if (ret != 0) - return -31; + return -4902; ret = wc_Des3_SetKey(&dec, key3, iv3, DES_DECRYPTION); if (ret != 0) - return -32; + return -4903; ret = wc_Des3_CbcEncrypt(&enc, cipher, vector, sizeof(vector)); - if (ret != 0) - return -33; - ret = wc_Des3_CbcDecrypt(&dec, plain, cipher, sizeof(cipher)); - if (ret != 0) - return -34; - - if (memcmp(plain, vector, sizeof(plain))) - return -35; - - if (memcmp(cipher, verify3, sizeof(cipher))) - return -36; - -#ifdef HAVE_CAVIUM - wc_Des3_FreeCavium(&enc); - wc_Des3_FreeCavium(&dec); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); #endif + if (ret != 0) + return -4904; + 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 -4905; + + if (XMEMCMP(plain, vector, sizeof(plain))) + return -4906; + + if (XMEMCMP(cipher, verify3, sizeof(cipher))) + return -4907; + +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) + /* test the same vectors with using compatibility layer */ + { + DES_key_schedule ks1; + DES_key_schedule ks2; + DES_key_schedule ks3; + DES_cblock iv4; + + XMEMCPY(ks1, key3, sizeof(DES_key_schedule)); + XMEMCPY(ks2, key3 + 8, sizeof(DES_key_schedule)); + XMEMCPY(ks3, key3 + 16, sizeof(DES_key_schedule)); + XMEMCPY(iv4, iv3, sizeof(DES_cblock)); + + XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(cipher, 0, sizeof(cipher)); + + DES_ede3_cbc_encrypt(vector, cipher, sizeof(vector), &ks1, &ks2, &ks3, + &iv4, DES_ENCRYPT); + DES_ede3_cbc_encrypt(cipher, plain, sizeof(cipher), &ks1, &ks2, &ks3, + &iv4, DES_DECRYPT); + + if (XMEMCMP(plain, vector, sizeof(plain))) + return -4908; + + if (XMEMCMP(cipher, verify3, sizeof(cipher))) + return -4909; + } +#endif /* OPENSSL_EXTRA */ + + wc_Des3Free(&enc); + wc_Des3Free(&dec); + +#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_SHA) + { + EncryptedInfo info; + XMEMSET(&info, 0, sizeof(EncryptedInfo)); + XMEMCPY(info.iv, iv3, sizeof(iv3)); + info.ivSz = sizeof(iv3); + info.keySz = sizeof(key3); + info.cipherType = WC_CIPHER_DES3; + + ret = wc_BufferKeyEncrypt(&info, cipher, sizeof(cipher), key3, + sizeof(key3), WC_HASH_TYPE_SHA); + if (ret != 0) + return -4910; + } +#endif + return 0; } #endif /* NO_DES */ #ifndef NO_AES + +#if defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_CFB) +#if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) +/* pass in the function, key, iv, plain text and expected and this function + * tests that the encryption and decryption is successful */ +static int EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, + const byte* iv, const byte* plain, int plainSz, + const byte* expected, int expectedSz) +{ + EVP_CIPHER_CTX ctx; + int idx, ret = 0, cipherSz; + byte* cipher; + + cipher = (byte*)XMALLOC(plainSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipher == NULL) { + return -4911; + } + + /* test encrypt */ + EVP_CIPHER_CTX_init(&ctx); + if (EVP_CipherInit(&ctx, type, key, iv, 1) == 0) { + ret = -4912; + goto EVP_TEST_END; + } + + if (EVP_CipherUpdate(&ctx, cipher, &idx, plain, expectedSz) == 0) { + ret = -4913; + goto EVP_TEST_END; + } + + cipherSz = idx; + if (EVP_CipherFinal(&ctx, cipher + cipherSz, &idx) == 0) { + ret = -4914; + goto EVP_TEST_END; + } + cipherSz += idx; + + if (XMEMCMP(cipher, expected, plainSz)) { + ret = -4915; + goto EVP_TEST_END; + } + + /* test decrypt */ + EVP_CIPHER_CTX_init(&ctx); + if (EVP_CipherInit(&ctx, type, key, iv, 0) == 0) { + ret = -4916; + goto EVP_TEST_END; + } + + if (EVP_CipherUpdate(&ctx, cipher, &idx, cipher, expectedSz) == 0) { + ret = -4917; + goto EVP_TEST_END; + } + + cipherSz = idx; + if (EVP_CipherFinal(&ctx, cipher + cipherSz, &idx) == 0) { + ret = -4918; + goto EVP_TEST_END; + } + cipherSz += idx; + + if ((expectedSz != cipherSz) || XMEMCMP(plain, cipher, plainSz)) { + ret = -4919; + goto EVP_TEST_END; + } + +EVP_TEST_END: + XFREE(cipher, NULL, DYNAMIC_TYPE_TMP_BUFFER); + (void)cipherSz; + return ret; +} +#endif /* OPENSSL_EXTRA */ +#endif /* WOLFSSL_AES_OFB || WOLFSSL_AES_CFB */ + +#ifdef WOLFSSL_AES_OFB + /* test vector from https://csrc.nist.gov/Projects/cryptographic-algorithm-validation-program/Block-Ciphers */ + int aesofb_test(void) + { + #ifdef WOLFSSL_AES_256 + const byte key1[] = + { + 0xc4,0xc7,0xfa,0xd6,0x53,0x5c,0xb8,0x71, + 0x4a,0x5c,0x40,0x77,0x9a,0x8b,0xa1,0xd2, + 0x53,0x3e,0x23,0xb4,0xb2,0x58,0x73,0x2a, + 0x5b,0x78,0x01,0xf4,0xe3,0x71,0xa7,0x94 + }; + const byte iv1[] = + { + 0x5e,0xb9,0x33,0x13,0xb8,0x71,0xff,0x16, + 0xb9,0x8a,0x9b,0xcb,0x43,0x33,0x0d,0x6f + }; + const byte plain1[] = + { + 0x6d,0x0b,0xb0,0x79,0x63,0x84,0x71,0xe9, + 0x39,0xd4,0x53,0x14,0x86,0xc1,0x4c,0x25, + 0x9a,0xee,0xc6,0xf3,0xc0,0x0d,0xfd,0xd6, + 0xc0,0x50,0xa8,0xba,0xa8,0x20,0xdb,0x71, + 0xcc,0x12,0x2c,0x4e,0x0c,0x17,0x15,0xef, + 0x55,0xf3,0x99,0x5a,0x6b,0xf0,0x2a,0x4c + }; + const byte cipher1[] = + { + 0x0f,0x54,0x61,0x71,0x59,0xd0,0x3f,0xfc, + 0x1b,0xfa,0xfb,0x60,0x29,0x30,0xd7,0x00, + 0xf4,0xa4,0xa8,0xe6,0xdd,0x93,0x94,0x46, + 0x64,0xd2,0x19,0xc4,0xc5,0x4d,0xde,0x1b, + 0x04,0x53,0xe1,0x73,0xf5,0x18,0x74,0xae, + 0xfd,0x64,0xa2,0xe1,0xe2,0x76,0x13,0xb0 + }; + #endif /* WOLFSSL_AES_256 */ + + + #ifdef WOLFSSL_AES_128 + const byte key2[] = + { + 0x10,0xa5,0x88,0x69,0xd7,0x4b,0xe5,0xa3, + 0x74,0xcf,0x86,0x7c,0xfb,0x47,0x38,0x59 + }; + const byte iv2[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; + const byte plain2[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; + const byte cipher2[] = + { + 0x6d,0x25,0x1e,0x69,0x44,0xb0,0x51,0xe0, + 0x4e,0xaa,0x6f,0xb4,0xdb,0xf7,0x84,0x65 + }; + #endif /* WOLFSSL_AES_128 */ + + + #ifdef WOLFSSL_AES_192 + const byte key3[] = { + 0xd0,0x77,0xa0,0x3b,0xd8,0xa3,0x89,0x73, + 0x92,0x8c,0xca,0xfe,0x4a,0x9d,0x2f,0x45, + 0x51,0x30,0xbd,0x0a,0xf5,0xae,0x46,0xa9 + }; + const byte iv3[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; + const byte cipher3[] = + { + 0xab,0xc7,0x86,0xfb,0x1e,0xdb,0x50,0x45, + 0x80,0xc4,0xd8,0x82,0xef,0x29,0xa0,0xc7 + }; + const byte plain3[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; + #endif /* WOLFSSL_AES_192 */ + + Aes enc; + byte cipher[AES_BLOCK_SIZE * 4]; + #ifdef HAVE_AES_DECRYPT + Aes dec; + byte plain [AES_BLOCK_SIZE * 4]; + #endif + int ret = 0; + + (void)enc; + #ifdef HAVE_AES_DECRYPT + (void)dec; + #endif + +#ifdef WOLFSSL_AES_128 + /* 128 key size test */ + #ifdef OPENSSL_EXTRA + ret = EVP_test(EVP_aes_128_ofb(), key2, iv2, plain2, sizeof(plain2), + cipher2, sizeof(cipher2)); + if (ret != 0) { + return ret; + } + #endif + + ret = wc_AesSetKey(&enc, key2, sizeof(key2), iv2, AES_ENCRYPTION); + if (ret != 0) + return -4920; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key2, sizeof(key2), iv2, AES_ENCRYPTION); + if (ret != 0) + return -4921; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesOfbEncrypt(&enc, cipher, plain2, AES_BLOCK_SIZE); + if (ret != 0) + return -4922; + + if (XMEMCMP(cipher, cipher2, AES_BLOCK_SIZE)) + return -4923; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesOfbDecrypt(&dec, plain, cipher2, AES_BLOCK_SIZE); + if (ret != 0) + return -4924; + + if (XMEMCMP(plain, plain2, AES_BLOCK_SIZE)) + return -4925; + #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_128 */ + +#ifdef WOLFSSL_AES_192 + /* 192 key size test */ + #ifdef OPENSSL_EXTRA + ret = EVP_test(EVP_aes_192_ofb(), key3, iv3, plain3, sizeof(plain3), + cipher3, sizeof(cipher3)); + if (ret != 0) { + return ret; + } + #endif + + ret = wc_AesSetKey(&enc, key3, sizeof(key3), iv3, AES_ENCRYPTION); + if (ret != 0) + return -4926; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key3, sizeof(key3), iv3, AES_ENCRYPTION); + if (ret != 0) + return -4927; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesOfbEncrypt(&enc, cipher, plain3, AES_BLOCK_SIZE); + if (ret != 0) + return -4928; + + if (XMEMCMP(cipher, cipher3, AES_BLOCK_SIZE)) + return -4929; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesOfbDecrypt(&dec, plain, cipher3, AES_BLOCK_SIZE); + if (ret != 0) + return -4930; + + if (XMEMCMP(plain, plain3, AES_BLOCK_SIZE)) + return -4931; + #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_192 */ + +#ifdef WOLFSSL_AES_256 + /* 256 key size test */ + #ifdef OPENSSL_EXTRA + ret = EVP_test(EVP_aes_256_ofb(), key1, iv1, plain1, sizeof(plain1), + cipher1, sizeof(cipher1)); + if (ret != 0) { + return ret; + } + #endif + + ret = wc_AesSetKey(&enc, key1, sizeof(key1), iv1, AES_ENCRYPTION); + if (ret != 0) + return -4932; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key1, sizeof(key1), iv1, AES_ENCRYPTION); + if (ret != 0) + return -4933; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesOfbEncrypt(&enc, cipher, plain1, AES_BLOCK_SIZE); + if (ret != 0) + return -4934; + + if (XMEMCMP(cipher, cipher1, AES_BLOCK_SIZE)) + return -4935; + + ret = wc_AesOfbEncrypt(&enc, cipher + AES_BLOCK_SIZE, + plain1 + AES_BLOCK_SIZE, AES_BLOCK_SIZE); + if (ret != 0) + return -4936; + + if (XMEMCMP(cipher + AES_BLOCK_SIZE, cipher1 + AES_BLOCK_SIZE, + AES_BLOCK_SIZE)) + return -4937; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesOfbDecrypt(&dec, plain, cipher1, AES_BLOCK_SIZE); + if (ret != 0) + return -4938; + + if (XMEMCMP(plain, plain1, AES_BLOCK_SIZE)) + return -4939; + + ret = wc_AesOfbDecrypt(&dec, plain + AES_BLOCK_SIZE, + cipher1 + AES_BLOCK_SIZE, AES_BLOCK_SIZE); + if (ret != 0) + return -4940; + + if (XMEMCMP(plain + AES_BLOCK_SIZE, plain1 + AES_BLOCK_SIZE, + AES_BLOCK_SIZE)) + return -4941; + #endif /* HAVE_AES_DECRYPT */ + + /* multiple blocks at once */ + ret = wc_AesSetKey(&enc, key1, sizeof(key1), iv1, AES_ENCRYPTION); + if (ret != 0) + return -4942; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key1, sizeof(key1), iv1, AES_ENCRYPTION); + if (ret != 0) + return -4943; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesOfbEncrypt(&enc, cipher, plain1, AES_BLOCK_SIZE * 3); + if (ret != 0) + return -4944; + + if (XMEMCMP(cipher, cipher1, AES_BLOCK_SIZE * 3)) + return -4945; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesOfbDecrypt(&dec, plain, cipher1, AES_BLOCK_SIZE * 3); + if (ret != 0) + return -4946; + + if (XMEMCMP(plain, plain1, AES_BLOCK_SIZE * 3)) + return -4947; + #endif /* HAVE_AES_DECRYPT */ + + /* inline decrypt/encrypt*/ + ret = wc_AesSetKey(&enc, key1, sizeof(key1), iv1, AES_ENCRYPTION); + if (ret != 0) + return -4948; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key1, sizeof(key1), iv1, AES_ENCRYPTION); + if (ret != 0) + return -4949; + #endif + + XMEMCPY(cipher, plain1, AES_BLOCK_SIZE * 2); + ret = wc_AesOfbEncrypt(&enc, cipher, cipher, AES_BLOCK_SIZE * 2); + if (ret != 0) + return -4950; + + if (XMEMCMP(cipher, cipher1, AES_BLOCK_SIZE * 2)) + return -4951; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesOfbDecrypt(&dec, cipher, cipher, AES_BLOCK_SIZE * 2); + if (ret != 0) + return -4952; + + if (XMEMCMP(cipher, plain1, AES_BLOCK_SIZE * 2)) + return -4953; + #endif /* HAVE_AES_DECRYPT */ + + /* 256 key size test leftover support */ + ret = wc_AesSetKey(&enc, key1, sizeof(key1), iv1, AES_ENCRYPTION); + if (ret != 0) + return -4954; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key1, sizeof(key1), iv1, AES_ENCRYPTION); + if (ret != 0) + return -4955; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesOfbEncrypt(&enc, cipher, plain1, 3); + if (ret != 0) + return -4956; + + if (XMEMCMP(cipher, cipher1, 3)) + return -4957; + + ret = wc_AesOfbEncrypt(&enc, cipher + 3, plain1 + 3, AES_BLOCK_SIZE); + if (ret != 0) + return -4958; + + if (XMEMCMP(cipher + 3, cipher1 + 3, AES_BLOCK_SIZE)) + return -4959; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesOfbDecrypt(&dec, plain, cipher1, 6); + if (ret != 0) + return -4960; + + if (XMEMCMP(plain, plain1, 6)) + return -4961; + + ret = wc_AesOfbDecrypt(&dec, plain + 6, cipher1 + 6, AES_BLOCK_SIZE); + if (ret != 0) + return -4962; + + if (XMEMCMP(plain + 6, plain1 + 6, AES_BLOCK_SIZE)) + return -4963; + #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_256 */ + + return 0; + } +#endif /* WOLFSSL_AES_OFB */ + +#if defined(WOLFSSL_AES_CFB) + /* Test cases from NIST SP 800-38A, Recommendation for Block Cipher Modes of Operation Methods an*/ + static int aescfb_test(void) + { + Aes enc; + byte cipher[AES_BLOCK_SIZE * 4]; + #ifdef HAVE_AES_DECRYPT + Aes dec; + byte plain [AES_BLOCK_SIZE * 4]; + #endif + int ret = 0; + + const byte iv[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + }; + +#ifdef WOLFSSL_AES_128 + const byte key1[] = + { + 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, + 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c + }; + + const byte cipher1[] = + { + 0x3b,0x3f,0xd9,0x2e,0xb7,0x2d,0xad,0x20, + 0x33,0x34,0x49,0xf8,0xe8,0x3c,0xfb,0x4a, + 0xc8,0xa6,0x45,0x37,0xa0,0xb3,0xa9,0x3f, + 0xcd,0xe3,0xcd,0xad,0x9f,0x1c,0xe5,0x8b, + 0x26,0x75,0x1f,0x67,0xa3,0xcb,0xb1,0x40, + 0xb1,0x80,0x8c,0xf1,0x87,0xa4,0xf4,0xdf + }; + + const byte msg1[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef + }; +#endif /* WOLFSSL_AES_128 */ + +#ifdef WOLFSSL_AES_192 + /* 192 size key test */ + const byte key2[] = + { + 0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0x52, + 0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5, + 0x62,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b + }; + + const byte cipher2[] = + { + 0xcd,0xc8,0x0d,0x6f,0xdd,0xf1,0x8c,0xab, + 0x34,0xc2,0x59,0x09,0xc9,0x9a,0x41,0x74, + 0x67,0xce,0x7f,0x7f,0x81,0x17,0x36,0x21, + 0x96,0x1a,0x2b,0x70,0x17,0x1d,0x3d,0x7a, + 0x2e,0x1e,0x8a,0x1d,0xd5,0x9b,0x88,0xb1, + 0xc8,0xe6,0x0f,0xed,0x1e,0xfa,0xc4,0xc9, + 0xc0,0x5f,0x9f,0x9c,0xa9,0x83,0x4f,0xa0, + 0x42,0xae,0x8f,0xba,0x58,0x4b,0x09,0xff + }; + + const byte msg2[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; +#endif /* WOLFSSL_AES_192 */ + +#ifdef WOLFSSL_AES_256 + /* 256 size key simple test */ + const byte key3[] = + { + 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe, + 0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, + 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7, + 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 + }; + + const byte cipher3[] = + { + 0xdc,0x7e,0x84,0xbf,0xda,0x79,0x16,0x4b, + 0x7e,0xcd,0x84,0x86,0x98,0x5d,0x38,0x60, + 0x39,0xff,0xed,0x14,0x3b,0x28,0xb1,0xc8, + 0x32,0x11,0x3c,0x63,0x31,0xe5,0x40,0x7b, + 0xdf,0x10,0x13,0x24,0x15,0xe5,0x4b,0x92, + 0xa1,0x3e,0xd0,0xa8,0x26,0x7a,0xe2,0xf9, + 0x75,0xa3,0x85,0x74,0x1a,0xb9,0xce,0xf8, + 0x20,0x31,0x62,0x3d,0x55,0xb1,0xe4,0x71 + }; + + const byte msg3[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; +#endif /* WOLFSSL_AES_256 */ + + + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) + return -4964; +#ifdef HAVE_AES_DECRYPT + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -4965; +#endif + +#ifdef WOLFSSL_AES_128 + /* 128 key tests */ + #if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + ret = EVP_test(EVP_aes_128_cfb128(), key1, iv, msg1, sizeof(msg1), + cipher1, sizeof(cipher1)); + if (ret != 0) { + return ret; + } + #endif + + ret = wc_AesSetKey(&enc, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -4966; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -4967; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfbEncrypt(&enc, cipher, msg1, AES_BLOCK_SIZE * 2); + if (ret != 0) + return -4968; + + if (XMEMCMP(cipher, cipher1, AES_BLOCK_SIZE * 2)) + return -4969; + + /* test restarting encryption process */ + ret = wc_AesCfbEncrypt(&enc, cipher + (AES_BLOCK_SIZE * 2), + msg1 + (AES_BLOCK_SIZE * 2), AES_BLOCK_SIZE); + if (ret != 0) + return -4970; + + if (XMEMCMP(cipher + (AES_BLOCK_SIZE * 2), + cipher1 + (AES_BLOCK_SIZE * 2), AES_BLOCK_SIZE)) + return -4971; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesCfbDecrypt(&dec, plain, cipher, AES_BLOCK_SIZE * 3); + if (ret != 0) + return -4972; + + if (XMEMCMP(plain, msg1, AES_BLOCK_SIZE * 3)) + return -4973; + #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_128 */ + +#ifdef WOLFSSL_AES_192 + /* 192 key size test */ + #if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + ret = EVP_test(EVP_aes_192_cfb128(), key2, iv, msg2, sizeof(msg2), + cipher2, sizeof(cipher2)); + if (ret != 0) { + return ret; + } + #endif + + ret = wc_AesSetKey(&enc, key2, sizeof(key2), iv, AES_ENCRYPTION); + if (ret != 0) + return -4974; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key2, sizeof(key2), iv, AES_ENCRYPTION); + if (ret != 0) + return -4975; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfbEncrypt(&enc, cipher, msg2, AES_BLOCK_SIZE * 4); + if (ret != 0) + return -4976; + + if (XMEMCMP(cipher, cipher2, AES_BLOCK_SIZE * 4)) + return -4977; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesCfbDecrypt(&dec, plain, cipher, AES_BLOCK_SIZE * 4); + if (ret != 0) + return -4978; + + if (XMEMCMP(plain, msg2, AES_BLOCK_SIZE * 4)) + return -4979; + #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_192 */ + +#ifdef WOLFSSL_AES_256 + /* 256 key size test */ + #if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + ret = EVP_test(EVP_aes_256_cfb128(), key3, iv, msg3, sizeof(msg3), + cipher3, sizeof(cipher3)); + if (ret != 0) { + return ret; + } + #endif + ret = wc_AesSetKey(&enc, key3, sizeof(key3), iv, AES_ENCRYPTION); + if (ret != 0) + return -4980; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key3, sizeof(key3), iv, AES_ENCRYPTION); + if (ret != 0) + return -4981; + #endif + + /* test with data left overs, magic lengths are checking near edges */ + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfbEncrypt(&enc, cipher, msg3, 4); + if (ret != 0) + return -4982; + + if (XMEMCMP(cipher, cipher3, 4)) + return -4983; + + ret = wc_AesCfbEncrypt(&enc, cipher + 4, msg3 + 4, 27); + if (ret != 0) + return -4984; + + if (XMEMCMP(cipher + 4, cipher3 + 4, 27)) + return -4985; + + ret = wc_AesCfbEncrypt(&enc, cipher + 31, msg3 + 31, + (AES_BLOCK_SIZE * 4) - 31); + if (ret != 0) + return -4986; + + if (XMEMCMP(cipher, cipher3, AES_BLOCK_SIZE * 4)) + return -4987; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesCfbDecrypt(&dec, plain, cipher, 4); + if (ret != 0) + return -4988; + + if (XMEMCMP(plain, msg3, 4)) + return -4989; + + ret = wc_AesCfbDecrypt(&dec, plain + 4, cipher + 4, 4); + if (ret != 0) + return -4990; + + ret = wc_AesCfbDecrypt(&dec, plain + 8, cipher + 8, 23); + if (ret != 0) + return -4991; + + if (XMEMCMP(plain + 4, msg3 + 4, 27)) + return -4992; + + ret = wc_AesCfbDecrypt(&dec, plain + 31, cipher + 31, + (AES_BLOCK_SIZE * 4) - 31); + if (ret != 0) + return -4993; + + if (XMEMCMP(plain, msg3, AES_BLOCK_SIZE * 4)) + return -4994; + #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_256 */ + + return ret; + } + +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + static int aescfb1_test(void) + { + Aes enc; + byte cipher[AES_BLOCK_SIZE]; + #ifdef HAVE_AES_DECRYPT + Aes dec; + byte plain [AES_BLOCK_SIZE]; + #endif + int ret = 0; + +#ifdef WOLFSSL_AES_128 + const byte iv[] = { + 0x4d,0xbb,0xdc,0xaa,0x59,0xf3,0x63,0xc9, + 0x2a,0x3b,0x98,0x43,0xad,0x20,0xe2,0xb7 + }; + + const byte key1[] = + { + 0xcd,0xef,0x9d,0x06,0x61,0xba,0xe4,0x73, + 0x8d,0x1a,0x58,0xa2,0xa6,0x22,0x8b,0x66 + }; + + const byte cipher1[] = + { + 0x00 + }; + + const byte msg1[] = + { + 0xC0 + }; +#endif /* WOLFSSL_AES_128 */ +#ifdef WOLFSSL_AES_192 + const byte iv2[] = { + 0x57,0xc6,0x89,0x7c,0x99,0x52,0x28,0x13, + 0xbf,0x67,0x9c,0xe1,0x13,0x70,0xaf,0x5e + }; + + const byte key2[] = + { + 0xba,0xa1,0x58,0xa1,0x6b,0x50,0x4a,0x10, + 0x8e,0xd4,0x33,0x2e,0xe7,0xf2,0x9b,0xf6, + 0xd1,0xac,0x46,0xa8,0xde,0x5a,0xfe,0x7a + }; + + const byte cipher2[] = + { + 0x30 + }; + + const byte msg2[] = + { + 0x80 + }; +#endif /* WOLFSSL_AES_192 */ +#ifdef WOLFSSL_AES_256 + const byte iv3[] = { + 0x63,0x2e,0x9f,0x83,0x1f,0xa3,0x80,0x5e, + 0x52,0x02,0xbc,0xe0,0x6d,0x04,0xf9,0xa0 + }; + + const byte key3[] = + { + 0xf6,0xfa,0xe4,0xf1,0x5d,0x91,0xfc,0x50, + 0x88,0x78,0x4f,0x84,0xa5,0x37,0x12,0x7e, + 0x32,0x63,0x55,0x9c,0x62,0x73,0x88,0x20, + 0xc2,0xcf,0x3d,0xe1,0x1c,0x2a,0x30,0x40 + }; + + const byte cipher3[] = + { + 0xF7, 0x00 + }; + + const byte msg3[] = + { + 0x41, 0xC0 + }; +#endif /* WOLFSSL_AES_256 */ + + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) + return -4995; +#ifdef HAVE_AES_DECRYPT + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -4996; +#endif + +#ifdef WOLFSSL_AES_128 + /* 128 key tests */ + ret = wc_AesSetKey(&enc, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -4997; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -4998; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfb1Encrypt(&enc, cipher, msg1, 2); + if (ret != 0) + return -4999; + + if (cipher[0] != cipher1[0]) + return -5000; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesCfb1Decrypt(&dec, plain, cipher, 2); + if (ret != 0) + return -5001; + + if (plain[0] != msg1[0]) + return -5002; + #endif /* HAVE_AES_DECRYPT */ + + #ifdef OPENSSL_EXTRA + ret = wc_AesSetKey(&enc, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -5003; + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfb1Encrypt(&enc, cipher, msg1, + sizeof(msg1) * WOLFSSL_BIT_SIZE); + if (ret != 0) + return -5004; + + ret = EVP_test(EVP_aes_128_cfb1(), key1, iv, msg1, sizeof(msg1), + cipher, sizeof(msg1)); + if (ret != 0) { + return ret; + } + #endif +#endif /* WOLFSSL_AES_128 */ +#ifdef WOLFSSL_AES_192 + /* 192 key tests */ + ret = wc_AesSetKey(&enc, key2, sizeof(key2), iv2, AES_ENCRYPTION); + if (ret != 0) + return -5005; + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfb1Encrypt(&enc, cipher, msg2, 4); + if (ret != 0) + return -5006; + if (XMEMCMP(cipher, cipher2, sizeof(cipher2)) != 0) + return -5007; + + #ifdef OPENSSL_EXTRA + ret = wc_AesSetKey(&enc, key2, sizeof(key2), iv2, AES_ENCRYPTION); + if (ret != 0) + return -5008; + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfb1Encrypt(&enc, cipher, msg2, + sizeof(msg2) * WOLFSSL_BIT_SIZE); + if (ret != 0) + return -5009; + + ret = EVP_test(EVP_aes_192_cfb1(), key2, iv2, msg2, sizeof(msg2), + cipher, sizeof(msg2)); + if (ret != 0) { + return ret; + } + #endif +#endif /* WOLFSSL_AES_192 */ + +#ifdef WOLFSSL_AES_256 + /* 256 key tests */ + ret = wc_AesSetKey(&enc, key3, sizeof(key3), iv3, AES_ENCRYPTION); + if (ret != 0) + return -5010; + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfb1Encrypt(&enc, cipher, msg3, 10); + if (ret != 0) + return -5011; + if (XMEMCMP(cipher, cipher3, sizeof(cipher3)) != 0) + return -5012; + + #ifdef OPENSSL_EXTRA + ret = wc_AesSetKey(&enc, key3, sizeof(key3), iv3, AES_ENCRYPTION); + if (ret != 0) + return -5013; + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfb1Encrypt(&enc, cipher, msg3, + sizeof(msg3) * WOLFSSL_BIT_SIZE); + if (ret != 0) + return -5014; + + ret = EVP_test(EVP_aes_256_cfb1(), key3, iv3, msg3, sizeof(msg3), + cipher, sizeof(msg3)); + if (ret != 0) { + return ret; + } + #endif +#endif /* WOLFSSL_AES_256 */ + return ret; + } + + static int aescfb8_test(void) + { + Aes enc; + byte cipher[AES_BLOCK_SIZE]; + #ifdef HAVE_AES_DECRYPT + Aes dec; + byte plain [AES_BLOCK_SIZE]; + #endif + int ret = 0; + +#ifdef WOLFSSL_AES_128 + const byte iv[] = { + 0xf4,0x75,0xc6,0x49,0x91,0xb2,0x0e,0xae, + 0xe1,0x83,0xa2,0x26,0x29,0xe2,0x1e,0x22 + }; + + const byte key1[] = + { + 0xc8,0xfe,0x9b,0xf7,0x7b,0x93,0x0f,0x46, + 0xd2,0x07,0x8b,0x8c,0x0e,0x65,0x7c,0xd4 + }; + + const byte cipher1[] = + { + 0xd2,0x76,0x91 + }; + + const byte msg1[] = + { + 0xc9,0x06,0x35 + }; +#endif /* WOLFSSL_AES_128 */ +#ifdef WOLFSSL_AES_192 + const byte iv2[] = { + 0x0a,0x02,0x84,0x6b,0x62,0xab,0xb6,0x93, + 0xef,0x31,0xd7,0x54,0x84,0x2e,0xed,0x29 + }; + + const byte key2[] = + { + 0xba,0xf0,0x8b,0x76,0x31,0x7a,0x65,0xc5, + 0xf0,0x7a,0xe6,0xf5,0x7e,0xb0,0xe6,0x54, + 0x88,0x65,0x93,0x24,0xd2,0x97,0x09,0xe3 + }; + + const byte cipher2[] = + { + 0x72,0x9c,0x0b,0x6d,0xeb,0x75,0xfa,0x6e, + 0xb5,0xe8 + }; + + const byte msg2[] = + { + 0x98,0x95,0x93,0x24,0x02,0x39,0x3d,0xc3, + 0x3a,0x60 + }; +#endif +#ifdef WOLFSSL_AES_256 + const byte iv3[] = { + 0x33,0x8c,0x55,0x2f,0xf1,0xec,0xa1,0x44, + 0x08,0xe0,0x5d,0x8c,0xf9,0xf3,0xb3,0x1b + }; + + const byte key3[] = + { + 0x06,0x48,0x74,0x09,0x2f,0x7a,0x13,0xcc, + 0x44,0x62,0x24,0x7a,0xd4,0x23,0xd0,0xe9, + 0x6e,0xdf,0x42,0xe8,0xb6,0x7a,0x5a,0x23, + 0xb7,0xa0,0xa6,0x47,0x7b,0x09,0x8e,0x66 + }; + + const byte cipher3[] = + { + 0x1c,0xff,0x95 + }; + + const byte msg3[] = + { + 0xb9,0x74,0xfa + }; +#endif + + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) + return -5015; +#ifdef HAVE_AES_DECRYPT + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -5016; +#endif + +#ifdef WOLFSSL_AES_128 + /* 128 key tests */ + #ifdef OPENSSL_EXTRA + ret = EVP_test(EVP_aes_128_cfb8(), key1, iv, msg1, sizeof(msg1), + cipher1, sizeof(cipher1)); + if (ret != 0) { + return ret; + } + #endif + ret = wc_AesSetKey(&enc, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -5017; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -5018; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfb8Encrypt(&enc, cipher, msg1, sizeof(msg1)); + if (ret != 0) + return -5019; + + if (XMEMCMP(cipher, cipher1, sizeof(cipher1)) != 0) + return -5020; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesCfb8Decrypt(&dec, plain, cipher, sizeof(msg1)); + if (ret != 0) + return -5021; + + if (XMEMCMP(plain, msg1, sizeof(msg1)) != 0) + return -5022; + #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_128 */ +#ifdef WOLFSSL_AES_192 + /* 192 key tests */ + ret = wc_AesSetKey(&enc, key2, sizeof(key2), iv2, AES_ENCRYPTION); + if (ret != 0) + return -5023; + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfb8Encrypt(&enc, cipher, msg2, sizeof(msg2)); + if (ret != 0) + return -5024; + if (XMEMCMP(cipher, cipher2, sizeof(msg2)) != 0) + return -5025; +#ifdef OPENSSL_EXTRA + ret = EVP_test(EVP_aes_192_cfb8(), key2, iv2, msg2, sizeof(msg2), + cipher2, sizeof(msg2)); + if (ret != 0) { + return ret; + } +#endif + +#endif /* WOLFSSL_AES_192 */ + +#ifdef WOLFSSL_AES_256 + /* 256 key tests */ + ret = wc_AesSetKey(&enc, key3, sizeof(key3), iv3, AES_ENCRYPTION); + if (ret != 0) + return -5026; + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfb8Encrypt(&enc, cipher, msg3, sizeof(msg3)); + if (ret != 0) + return -5027; + if (XMEMCMP(cipher, cipher3, sizeof(cipher3)) != 0) + return -5028; + + #ifdef OPENSSL_EXTRA + ret = EVP_test(EVP_aes_256_cfb8(), key3, iv3, msg3, sizeof(msg3), + cipher3, sizeof(msg3)); + if (ret != 0) { + return ret; + } + #endif +#endif /* WOLFSSL_AES_256 */ + + return ret; + } +#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ +#endif /* WOLFSSL_AES_CFB */ + + +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 + +#if !defined(HAVE_FIPS) || \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + /* w/ FIPS v1 (cert 2425) wc_AesInit just returns 0 always as it's not + * supported with that FIPS version */ + ret = wc_AesInit(NULL, HEAP_HINT, devId); + if (ret != BAD_FUNC_ARG) + return -5100; +#endif + + ret = wc_AesInit(&aes, HEAP_HINT, devId); + /* 0 check OK for FIPSv1 */ + if (ret != 0) + return -5101; + +#ifndef HAVE_FIPS + /* Parameter Validation testing. */ + ret = wc_AesGetKeySize(NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -5102; + ret = wc_AesGetKeySize(&aes, NULL); + if (ret != BAD_FUNC_ARG) + return -5103; + ret = wc_AesGetKeySize(NULL, &keySize); + if (ret != BAD_FUNC_ARG) + return -5104; + /* Crashes in FIPS */ + ret = wc_AesSetKey(NULL, key16, sizeof(key16), iv, AES_ENCRYPTION); + if (ret != BAD_FUNC_ARG) + return -5105; +#endif + /* NULL IV indicates to use all zeros IV. */ + ret = wc_AesSetKey(&aes, key16, sizeof(key16), NULL, AES_ENCRYPTION); +#ifdef WOLFSSL_AES_128 + if (ret != 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5106; + ret = wc_AesSetKey(&aes, key32, sizeof(key32) - 1, iv, AES_ENCRYPTION); + if (ret != BAD_FUNC_ARG) + return -5107; +/* CryptoCell handles rounds internally */ +#if !defined(HAVE_FIPS) && !defined(WOLFSSL_CRYPTOCELL) + /* Force invalid rounds */ + aes.rounds = 16; + ret = wc_AesGetKeySize(&aes, &keySize); + if (ret != BAD_FUNC_ARG) + return -5108; +#endif + + ret = wc_AesSetKey(&aes, key16, sizeof(key16), iv, AES_ENCRYPTION); +#ifdef WOLFSSL_AES_128 + if (ret != 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5109; +#if !defined(HAVE_FIPS) && defined(WOLFSSL_AES_128) + ret = wc_AesGetKeySize(&aes, &keySize); + if (ret != 0 || keySize != sizeof(key16)) + return -5110; +#endif + + ret = wc_AesSetKey(&aes, key24, sizeof(key24), iv, AES_ENCRYPTION); +#ifdef WOLFSSL_AES_192 + if (ret != 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5111; +#if !defined(HAVE_FIPS) && defined(WOLFSSL_AES_192) + ret = wc_AesGetKeySize(&aes, &keySize); + if (ret != 0 || keySize != sizeof(key24)) + return -5112; +#endif + + ret = wc_AesSetKey(&aes, key32, sizeof(key32), iv, AES_ENCRYPTION); +#ifdef WOLFSSL_AES_256 + if (ret != 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5113; +#if !defined(HAVE_FIPS) && defined(WOLFSSL_AES_256) + ret = wc_AesGetKeySize(&aes, &keySize); + if (ret != 0 || keySize != sizeof(key32)) + return -5114; +#endif + + return 0; +} + +#if defined(WOLFSSL_AES_XTS) +/* test vectors from http://csrc.nist.gov/groups/STM/cavp/block-cipher-modes.html */ +#ifdef WOLFSSL_AES_128 +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 + }; + +#ifdef OPENSSL_EXTRA + ret = EVP_test(EVP_aes_128_xts(), k2, i2, p2, sizeof(p2), c2, sizeof(c2)); + if (ret != 0) { + printf("EVP_aes_128_xts failed!\n"); + return ret; + } +#endif + + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k2, sizeof(k2), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -5200; + + 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 -5201; + if (XMEMCMP(c2, buf, sizeof(c2))) + return -5202; + + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -5203; + 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 -5204; + if (XMEMCMP(c1, buf, AES_BLOCK_SIZE)) + return -5205; + + /* 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 -5206; + 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 -5207; + 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 -5208; + if (XMEMCMP(pp, buf, sizeof(pp))) + return -5209; + + /* 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 -5210; + if (XMEMCMP(p1, buf, AES_BLOCK_SIZE)) + return -5211; + + /* 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 -5212; + if (XMEMCMP(p2, buf, sizeof(p2)) == 0) /* fail case with wrong key */ + return -5213; + + /* set correct key and retest */ + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k2, sizeof(k2), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -5214; + 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 -5215; + if (XMEMCMP(p2, buf, sizeof(p2))) + return -5216; + wc_AesXtsFree(&aes); + + return ret; +} +#endif /* WOLFSSL_AES_128 */ + + +#ifdef WOLFSSL_AES_256 +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 + }; + +#ifdef OPENSSL_EXTRA + ret = EVP_test(EVP_aes_256_xts(), k2, i2, p2, sizeof(p2), c2, sizeof(c2)); + if (ret != 0) { + printf("EVP_aes_256_xts failed\n"); + return ret; + } +#endif + + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k2, sizeof(k2), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -5300; + 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 -5301; + if (XMEMCMP(c2, buf, sizeof(c2))) + return -5302; + + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -5303; + 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 -5304; + if (XMEMCMP(c1, buf, AES_BLOCK_SIZE)) + return -5305; + + /* 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 -5306; + 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 -5307; + 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 -5308; + if (XMEMCMP(pp, buf, sizeof(pp))) + return -5309; + + /* 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 -5310; + if (XMEMCMP(p1, buf, AES_BLOCK_SIZE)) + return -5311; + + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k2, sizeof(k2), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -5312; + 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 -5313; + if (XMEMCMP(p2, buf, sizeof(p2))) + return -5314; + wc_AesXtsFree(&aes); + + return ret; +} +#endif /* WOLFSSL_AES_256 */ + + +#if defined(WOLFSSL_AES_128) && defined(WOLFSSL_AES_256) +/* 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 -5400; + 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 -5401; + if (XMEMCMP(c1, buf, AES_BLOCK_SIZE)) + return -5402; + + /* decrypt test */ + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -5403; + 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 -5404; + if (XMEMCMP(p1, buf, AES_BLOCK_SIZE)) + return -5405; + 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 -5406; + 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 -5407; + if (XMEMCMP(c2, buf, sizeof(c2))) + return -5408; + + /* decrypt test */ + XMEMSET(buf, 0, sizeof(buf)); + if (wc_AesXtsSetKey(&aes, k2, sizeof(k2), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -5409; + 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 -5410; + if (XMEMCMP(p2, buf, sizeof(p2))) + return -5411; + wc_AesXtsFree(&aes); + + return ret; +} +#endif /* WOLFSSL_AES_128 && WOLFSSL_AES_256 */ + + +#ifdef WOLFSSL_AES_128 +/* 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 -5500; + if (wc_AesXtsSetKey(&aes, NULL, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) == 0) + return -5501; + + /* encryption operations */ + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_ENCRYPTION, + HEAP_HINT, devId) != 0) + return -5502; + 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 -5503; + + 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 -5504; + wc_AesXtsFree(&aes); + + /* decryption operations */ + if (wc_AesXtsSetKey(&aes, k1, sizeof(k1), AES_DECRYPTION, + HEAP_HINT, devId) != 0) + return -5505; + 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 -5506; + + 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 -5507; + wc_AesXtsFree(&aes); + + return 0; +} +#endif /* WOLFSSL_AES_128 */ +#endif /* WOLFSSL_AES_XTS */ + +#if defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) +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 */ + + XMEMSET(cipher, 0, AES_BLOCK_SIZE); + XMEMSET(plain, 0, AES_BLOCK_SIZE); + + /* Parameter Validation testing. */ + ret = wc_AesCbcEncryptWithKey(cipher, msg, AES_BLOCK_SIZE, key, 17, NULL); + if (ret != BAD_FUNC_ARG) + return -5600; +#ifdef HAVE_AES_DECRYPT + ret = wc_AesCbcDecryptWithKey(plain, cipher, AES_BLOCK_SIZE, key, 17, NULL); + if (ret != BAD_FUNC_ARG) + return -5601; +#endif + + ret = wc_AesCbcEncryptWithKey(cipher, msg, AES_BLOCK_SIZE, key, + AES_BLOCK_SIZE, iv); + if (ret != 0) + return -5602; +#ifdef HAVE_AES_DECRYPT + ret = wc_AesCbcDecryptWithKey(plain, cipher, AES_BLOCK_SIZE, key, + AES_BLOCK_SIZE, iv); + if (ret != 0) + return -5603; + if (XMEMCMP(plain, msg, AES_BLOCK_SIZE) != 0) + return -5604; +#endif /* HAVE_AES_DECRYPT */ + + (void)plain; + return 0; +} +#endif + int aes_test(void) { +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_COUNTER) Aes enc; + byte cipher[AES_BLOCK_SIZE * 4]; +#if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_COUNTER) Aes dec; + byte plain [AES_BLOCK_SIZE * 4]; +#endif +#endif /* HAVE_AES_CBC || WOLFSSL_AES_COUNTER */ + int ret = 0; +#ifdef HAVE_AES_CBC +#ifdef WOLFSSL_AES_128 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, @@ -2499,47 +7523,228 @@ int aes_test(void) byte key[] = "0123456789abcdef "; /* align */ byte iv[] = "1234567890abcdef "; /* align */ - byte cipher[AES_BLOCK_SIZE * 4]; - byte plain [AES_BLOCK_SIZE * 4]; - int ret; - -#ifdef HAVE_CAVIUM - if (wc_AesInitCavium(&enc, CAVIUM_DEV_ID) != 0) - return -20003; - if (wc_AesInitCavium(&dec, CAVIUM_DEV_ID) != 0) - return -20004; + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) + return -5700; +#if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_COUNTER) + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -5701; #endif ret = wc_AesSetKey(&enc, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); if (ret != 0) - return -1001; + return -5702; +#if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_COUNTER) ret = wc_AesSetKey(&dec, key, AES_BLOCK_SIZE, iv, AES_DECRYPTION); if (ret != 0) - return -1002; - - ret = wc_AesCbcEncrypt(&enc, cipher, msg, AES_BLOCK_SIZE); - if (ret != 0) - return -1005; - ret = wc_AesCbcDecrypt(&dec, plain, cipher, AES_BLOCK_SIZE); - if (ret != 0) - return -1006; - - if (memcmp(plain, msg, AES_BLOCK_SIZE)) - return -60; - - if (memcmp(cipher, verify, AES_BLOCK_SIZE)) - return -61; - -#ifdef HAVE_CAVIUM - wc_AesFreeCavium(&enc); - wc_AesFreeCavium(&dec); + return -5703; #endif + + XMEMSET(cipher, 0, AES_BLOCK_SIZE * 4); + 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 -5704; +#ifdef HAVE_AES_DECRYPT + XMEMSET(plain, 0, AES_BLOCK_SIZE * 4); + 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 -5705; + + if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) + return -5706; +#endif /* HAVE_AES_DECRYPT */ + if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) + return -5707; +#endif /* WOLFSSL_AES_128 */ + +#if defined(WOLFSSL_AESNI) && defined(HAVE_AES_DECRYPT) + { + const byte bigMsg[] = { + /* "All work and no play makes Jack a dull boy. " */ + 0x41,0x6c,0x6c,0x20,0x77,0x6f,0x72,0x6b, + 0x20,0x61,0x6e,0x64,0x20,0x6e,0x6f,0x20, + 0x70,0x6c,0x61,0x79,0x20,0x6d,0x61,0x6b, + 0x65,0x73,0x20,0x4a,0x61,0x63,0x6b,0x20, + 0x61,0x20,0x64,0x75,0x6c,0x6c,0x20,0x62, + 0x6f,0x79,0x2e,0x20,0x41,0x6c,0x6c,0x20, + 0x77,0x6f,0x72,0x6b,0x20,0x61,0x6e,0x64, + 0x20,0x6e,0x6f,0x20,0x70,0x6c,0x61,0x79, + 0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x4a, + 0x61,0x63,0x6b,0x20,0x61,0x20,0x64,0x75, + 0x6c,0x6c,0x20,0x62,0x6f,0x79,0x2e,0x20, + 0x41,0x6c,0x6c,0x20,0x77,0x6f,0x72,0x6b, + 0x20,0x61,0x6e,0x64,0x20,0x6e,0x6f,0x20, + 0x70,0x6c,0x61,0x79,0x20,0x6d,0x61,0x6b, + 0x65,0x73,0x20,0x4a,0x61,0x63,0x6b,0x20, + 0x61,0x20,0x64,0x75,0x6c,0x6c,0x20,0x62, + 0x6f,0x79,0x2e,0x20,0x41,0x6c,0x6c,0x20, + 0x77,0x6f,0x72,0x6b,0x20,0x61,0x6e,0x64, + 0x20,0x6e,0x6f,0x20,0x70,0x6c,0x61,0x79, + 0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x4a, + 0x61,0x63,0x6b,0x20,0x61,0x20,0x64,0x75, + 0x6c,0x6c,0x20,0x62,0x6f,0x79,0x2e,0x20, + 0x41,0x6c,0x6c,0x20,0x77,0x6f,0x72,0x6b, + 0x20,0x61,0x6e,0x64,0x20,0x6e,0x6f,0x20, + 0x70,0x6c,0x61,0x79,0x20,0x6d,0x61,0x6b, + 0x65,0x73,0x20,0x4a,0x61,0x63,0x6b,0x20, + 0x61,0x20,0x64,0x75,0x6c,0x6c,0x20,0x62, + 0x6f,0x79,0x2e,0x20,0x41,0x6c,0x6c,0x20, + 0x77,0x6f,0x72,0x6b,0x20,0x61,0x6e,0x64, + 0x20,0x6e,0x6f,0x20,0x70,0x6c,0x61,0x79, + 0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x4a, + 0x61,0x63,0x6b,0x20,0x61,0x20,0x64,0x75, + 0x6c,0x6c,0x20,0x62,0x6f,0x79,0x2e,0x20, + 0x41,0x6c,0x6c,0x20,0x77,0x6f,0x72,0x6b, + 0x20,0x61,0x6e,0x64,0x20,0x6e,0x6f,0x20, + 0x70,0x6c,0x61,0x79,0x20,0x6d,0x61,0x6b, + 0x65,0x73,0x20,0x4a,0x61,0x63,0x6b,0x20, + 0x61,0x20,0x64,0x75,0x6c,0x6c,0x20,0x62, + 0x6f,0x79,0x2e,0x20,0x41,0x6c,0x6c,0x20, + 0x77,0x6f,0x72,0x6b,0x20,0x61,0x6e,0x64, + 0x20,0x6e,0x6f,0x20,0x70,0x6c,0x61,0x79, + 0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x4a, + 0x61,0x63,0x6b,0x20,0x61,0x20,0x64,0x75, + 0x6c,0x6c,0x20,0x62,0x6f,0x79,0x2e,0x20, + 0x41,0x6c,0x6c,0x20,0x77,0x6f,0x72,0x6b, + 0x20,0x61,0x6e,0x64,0x20,0x6e,0x6f,0x20, + 0x70,0x6c,0x61,0x79,0x20,0x6d,0x61,0x6b, + 0x65,0x73,0x20,0x4a,0x61,0x63,0x6b,0x20 + }; + const byte bigKey[] = "0123456789abcdeffedcba9876543210"; + byte bigCipher[sizeof(bigMsg)]; + byte bigPlain[sizeof(bigMsg)]; + word32 keySz, msgSz; + + /* Iterate from one AES_BLOCK_SIZE of bigMsg through the whole + * message by AES_BLOCK_SIZE for each size of AES key. */ + for (keySz = 16; keySz <= 32; keySz += 8) { + for (msgSz = AES_BLOCK_SIZE; + msgSz <= sizeof(bigMsg); + msgSz += AES_BLOCK_SIZE) { + + XMEMSET(bigCipher, 0, sizeof(bigCipher)); + XMEMSET(bigPlain, 0, sizeof(bigPlain)); + ret = wc_AesSetKey(&enc, bigKey, keySz, iv, AES_ENCRYPTION); + if (ret != 0) + return -5708; + ret = wc_AesSetKey(&dec, bigKey, keySz, iv, AES_DECRYPTION); + if (ret != 0) + return -5709; + + 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 -5710; + + 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 -5711; + + if (XMEMCMP(bigPlain, bigMsg, msgSz)) + return -5712; + } + } + } +#endif /* WOLFSSL_AESNI && HAVE_AES_DECRYPT */ + + /* Test of AES IV state with encrypt/decrypt */ +#ifdef WOLFSSL_AES_128 + { + /* Test Vector from "NIST Special Publication 800-38A, 2001 Edition" + * https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38a.pdf + */ + const byte msg2[] = + { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 + }; + + const byte verify2[] = + { + 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, + 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, + 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2 + }; + byte key2[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c + }; + byte iv2[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + + + ret = wc_AesSetKey(&enc, key2, sizeof(key2), iv2, AES_ENCRYPTION); + if (ret != 0) + return -5713; + XMEMSET(cipher, 0, AES_BLOCK_SIZE * 2); + ret = wc_AesCbcEncrypt(&enc, cipher, msg2, AES_BLOCK_SIZE); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); + #endif + if (ret != 0) + return -5714; + if (XMEMCMP(cipher, verify2, AES_BLOCK_SIZE)) + return -5715; + + ret = wc_AesCbcEncrypt(&enc, cipher + AES_BLOCK_SIZE, + msg2 + AES_BLOCK_SIZE, AES_BLOCK_SIZE); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); + #endif + if (ret != 0) + return -5716; + if (XMEMCMP(cipher + AES_BLOCK_SIZE, verify2 + AES_BLOCK_SIZE, + AES_BLOCK_SIZE)) + return -5717; + + #if defined(HAVE_AES_DECRYPT) + ret = wc_AesSetKey(&dec, key2, sizeof(key2), iv2, AES_DECRYPTION); + if (ret != 0) + return -5718; + XMEMSET(plain, 0, AES_BLOCK_SIZE * 2); + ret = wc_AesCbcDecrypt(&dec, plain, verify2, AES_BLOCK_SIZE); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &dec.asyncDev, WC_ASYNC_FLAG_NONE); + #endif + if (ret != 0) + return -5719; + if (XMEMCMP(plain, msg2, AES_BLOCK_SIZE)) + return -5720; + + ret = wc_AesCbcDecrypt(&dec, plain + AES_BLOCK_SIZE, + verify2 + AES_BLOCK_SIZE, AES_BLOCK_SIZE); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &dec.asyncDev, WC_ASYNC_FLAG_NONE); + #endif + if (ret != 0) + return -5721; + if (XMEMCMP(plain + AES_BLOCK_SIZE, msg2 + AES_BLOCK_SIZE, + AES_BLOCK_SIZE)) + return -5722; + + #endif /* HAVE_AES_DECRYPT */ + } +#endif /* WOLFSSL_AES_128 */ +#endif /* HAVE_AES_CBC */ + #ifdef WOLFSSL_AES_COUNTER { - const byte ctrKey[] = - { - 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, - 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c - }; + /* test vectors from "Recommendation for Block Cipher Modes of + * Operation" NIST Special Publication 800-38A */ const byte ctrIv[] = { @@ -2547,7 +7752,6 @@ int aes_test(void) 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff }; - const byte ctrPlain[] = { 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, @@ -2560,7 +7764,20 @@ int aes_test(void) 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 }; - const byte ctrCipher[] = +#ifdef WOLFSSL_AES_128 + const byte oddCipher[] = + { + 0xb9,0xd7,0xcb,0x08,0xb0,0xe1,0x7b,0xa0, + 0xc2 + }; + + const byte ctr128Key[] = + { + 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, + 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c + }; + + const byte ctr128Cipher[] = { 0x87,0x4d,0x61,0x91,0xb6,0x20,0xe3,0x26, 0x1b,0xef,0x68,0x64,0x99,0x0d,0xb6,0xce, @@ -2571,53 +7788,163 @@ int aes_test(void) 0x1e,0x03,0x1d,0xda,0x2f,0xbe,0x03,0xd1, 0x79,0x21,0x70,0xa0,0xf3,0x00,0x9c,0xee }; +#endif /* WOLFSSL_AES_128 */ - const byte oddCipher[] = +#ifdef WOLFSSL_AES_192 + const byte ctr192Key[] = { - 0xb9,0xd7,0xcb,0x08,0xb0,0xe1,0x7b,0xa0, - 0xc2 + 0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0x52, + 0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5, + 0x62,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b }; - wc_AesSetKeyDirect(&enc, ctrKey, AES_BLOCK_SIZE, ctrIv, AES_ENCRYPTION); + const byte ctr192Cipher[] = + { + 0x1a,0xbc,0x93,0x24,0x17,0x52,0x1c,0xa2, + 0x4f,0x2b,0x04,0x59,0xfe,0x7e,0x6e,0x0b, + 0x09,0x03,0x39,0xec,0x0a,0xa6,0xfa,0xef, + 0xd5,0xcc,0xc2,0xc6,0xf4,0xce,0x8e,0x94, + 0x1e,0x36,0xb2,0x6b,0xd1,0xeb,0xc6,0x70, + 0xd1,0xbd,0x1d,0x66,0x56,0x20,0xab,0xf7, + 0x4f,0x78,0xa7,0xf6,0xd2,0x98,0x09,0x58, + 0x5a,0x97,0xda,0xec,0x58,0xc6,0xb0,0x50 + }; +#endif +#ifdef WOLFSSL_AES_256 + const byte ctr256Key[] = + { + 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe, + 0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, + 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7, + 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 + }; + + const byte ctr256Cipher[] = + { + 0x60,0x1e,0xc3,0x13,0x77,0x57,0x89,0xa5, + 0xb7,0xa7,0xf5,0x04,0xbb,0xf3,0xd2,0x28, + 0xf4,0x43,0xe3,0xca,0x4d,0x62,0xb5,0x9a, + 0xca,0x84,0xe9,0x90,0xca,0xca,0xf5,0xc5, + 0x2b,0x09,0x30,0xda,0xa2,0x3d,0xe9,0x4c, + 0xe8,0x70,0x17,0xba,0x2d,0x84,0x98,0x8d, + 0xdf,0xc9,0xc5,0x8d,0xb6,0x7a,0xad,0xa6, + 0x13,0xc2,0xdd,0x08,0x45,0x79,0x41,0xa6 + }; +#endif + +#ifdef WOLFSSL_AES_128 + wc_AesSetKeyDirect(&enc, ctr128Key, sizeof(ctr128Key), + ctrIv, AES_ENCRYPTION); /* Ctr only uses encrypt, even on key setup */ - wc_AesSetKeyDirect(&dec, ctrKey, AES_BLOCK_SIZE, ctrIv, AES_ENCRYPTION); + wc_AesSetKeyDirect(&dec, ctr128Key, sizeof(ctr128Key), + ctrIv, AES_ENCRYPTION); - wc_AesCtrEncrypt(&enc, cipher, ctrPlain, AES_BLOCK_SIZE*4); - wc_AesCtrEncrypt(&dec, plain, cipher, AES_BLOCK_SIZE*4); + ret = wc_AesCtrEncrypt(&enc, cipher, ctrPlain, sizeof(ctrPlain)); + if (ret != 0) { + return -5723; + } + ret = wc_AesCtrEncrypt(&dec, plain, cipher, sizeof(ctrPlain)); + if (ret != 0) { + return -5724; + } + if (XMEMCMP(plain, ctrPlain, sizeof(ctrPlain))) + return -5725; - if (memcmp(plain, ctrPlain, AES_BLOCK_SIZE*4)) - return -66; - - if (memcmp(cipher, ctrCipher, AES_BLOCK_SIZE*4)) - return -67; + if (XMEMCMP(cipher, ctr128Cipher, sizeof(ctr128Cipher))) + return -5726; /* let's try with just 9 bytes, non block size test */ - wc_AesSetKeyDirect(&enc, ctrKey, AES_BLOCK_SIZE, ctrIv, AES_ENCRYPTION); + wc_AesSetKeyDirect(&enc, ctr128Key, AES_BLOCK_SIZE, + ctrIv, AES_ENCRYPTION); /* Ctr only uses encrypt, even on key setup */ - wc_AesSetKeyDirect(&dec, ctrKey, AES_BLOCK_SIZE, ctrIv, AES_ENCRYPTION); + wc_AesSetKeyDirect(&dec, ctr128Key, AES_BLOCK_SIZE, + ctrIv, AES_ENCRYPTION); - wc_AesCtrEncrypt(&enc, cipher, ctrPlain, 9); - wc_AesCtrEncrypt(&dec, plain, cipher, 9); + ret = wc_AesCtrEncrypt(&enc, cipher, ctrPlain, sizeof(oddCipher)); + if (ret != 0) { + return -5727; + } + ret = wc_AesCtrEncrypt(&dec, plain, cipher, sizeof(oddCipher)); + if (ret != 0) { + return -5728; + } - if (memcmp(plain, ctrPlain, 9)) - return -68; + if (XMEMCMP(plain, ctrPlain, sizeof(oddCipher))) + return -5729; - if (memcmp(cipher, ctrCipher, 9)) - return -69; + if (XMEMCMP(cipher, ctr128Cipher, sizeof(oddCipher))) + return -5730; /* and an additional 9 bytes to reuse tmp left buffer */ - wc_AesCtrEncrypt(&enc, cipher, ctrPlain, 9); - wc_AesCtrEncrypt(&dec, plain, cipher, 9); + ret = wc_AesCtrEncrypt(&enc, cipher, ctrPlain, sizeof(oddCipher)); + if (ret != 0) { + return -5731; + } + ret = wc_AesCtrEncrypt(&dec, plain, cipher, sizeof(oddCipher)); + if (ret != 0) { + return -5732; + } - if (memcmp(plain, ctrPlain, 9)) - return -70; + if (XMEMCMP(plain, ctrPlain, sizeof(oddCipher))) + return -5733; - if (memcmp(cipher, oddCipher, 9)) - return -71; + if (XMEMCMP(cipher, oddCipher, sizeof(oddCipher))) + return -5734; +#endif /* WOLFSSL_AES_128 */ + +#ifdef WOLFSSL_AES_192 + /* 192 bit key */ + wc_AesSetKeyDirect(&enc, ctr192Key, sizeof(ctr192Key), + ctrIv, AES_ENCRYPTION); + /* Ctr only uses encrypt, even on key setup */ + wc_AesSetKeyDirect(&dec, ctr192Key, sizeof(ctr192Key), + ctrIv, AES_ENCRYPTION); + + XMEMSET(plain, 0, sizeof(plain)); + ret = wc_AesCtrEncrypt(&enc, plain, ctr192Cipher, sizeof(ctr192Cipher)); + if (ret != 0) { + return -5735; + } + + if (XMEMCMP(plain, ctrPlain, sizeof(ctr192Cipher))) + return -5736; + + ret = wc_AesCtrEncrypt(&dec, cipher, ctrPlain, sizeof(ctrPlain)); + if (ret != 0) { + return -5737; + } + if (XMEMCMP(ctr192Cipher, cipher, sizeof(ctr192Cipher))) + return -5738; +#endif /* WOLFSSL_AES_192 */ + +#ifdef WOLFSSL_AES_256 + /* 256 bit key */ + wc_AesSetKeyDirect(&enc, ctr256Key, sizeof(ctr256Key), + ctrIv, AES_ENCRYPTION); + /* Ctr only uses encrypt, even on key setup */ + wc_AesSetKeyDirect(&dec, ctr256Key, sizeof(ctr256Key), + ctrIv, AES_ENCRYPTION); + + XMEMSET(plain, 0, sizeof(plain)); + ret = wc_AesCtrEncrypt(&enc, plain, ctr256Cipher, sizeof(ctr256Cipher)); + if (ret != 0) { + return -5739; + } + + if (XMEMCMP(plain, ctrPlain, sizeof(ctrPlain))) + return -5740; + + ret = wc_AesCtrEncrypt(&dec, cipher, ctrPlain, sizeof(ctrPlain)); + if (ret != 0) { + return -5741; + } + if (XMEMCMP(ctr256Cipher, cipher, sizeof(ctr256Cipher))) + return -5742; +#endif /* WOLFSSL_AES_256 */ } #endif /* WOLFSSL_AES_COUNTER */ -#if defined(WOLFSSL_AESNI) && defined(WOLFSSL_AES_DIRECT) +#if defined(WOLFSSL_AES_DIRECT) && defined(WOLFSSL_AES_256) { const byte niPlain[] = { @@ -2642,48 +7969,444 @@ 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 -5743; wc_AesEncryptDirect(&enc, cipher, niPlain); if (XMEMCMP(cipher, niCipher, AES_BLOCK_SIZE) != 0) - return -20006; + return -5744; XMEMSET(plain, 0, AES_BLOCK_SIZE); ret = wc_AesSetKey(&dec, niKey, sizeof(niKey), plain, AES_DECRYPTION); if (ret != 0) - return -1004; + return -5745; wc_AesDecryptDirect(&dec, plain, niCipher); if (XMEMCMP(plain, niPlain, AES_BLOCK_SIZE) != 0) - return -20007; + return -5746; } -#endif /* WOLFSSL_AESNI && WOLFSSL_AES_DIRECT */ +#endif /* WOLFSSL_AES_DIRECT && WOLFSSL_AES_256 */ + + ret = aes_key_size_test(); + if (ret != 0) + return ret; + +#if defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) + ret = aes_cbc_test(); + if (ret != 0) + return ret; +#endif + +#if defined(WOLFSSL_AES_XTS) + #ifdef WOLFSSL_AES_128 + ret = aes_xts_128_test(); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_AES_256 + ret = aes_xts_256_test(); + if (ret != 0) + return ret; + #endif + #if defined(WOLFSSL_AES_128) && defined(WOLFSSL_AES_256) + ret = aes_xts_sector_test(); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_AES_128 + ret = aes_xts_args_test(); + if (ret != 0) + return ret; + #endif +#endif + +#if defined(WOLFSSL_AES_CFB) + ret = aescfb_test(); + if (ret != 0) + return ret; +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + ret = aescfb1_test(); + if (ret != 0) + return ret; + + ret = aescfb8_test(); + if (ret != 0) + return ret; +#endif +#endif + + +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_COUNTER) + wc_AesFree(&enc); + (void)cipher; +#if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_COUNTER) + wc_AesFree(&dec); + (void)plain; +#endif +#endif + + return ret; +} + +#ifdef WOLFSSL_AES_192 +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 -5800; +#ifdef HAVE_AES_DECRYPT + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -5801; +#endif + + ret = wc_AesSetKey(&enc, key, (int) sizeof(key), iv, AES_ENCRYPTION); + if (ret != 0) + return -5802; +#ifdef HAVE_AES_DECRYPT + ret = wc_AesSetKey(&dec, key, (int) sizeof(key), iv, AES_DECRYPTION); + if (ret != 0) + return -5803; +#endif + + XMEMSET(cipher, 0, AES_BLOCK_SIZE); + 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 -5804; +#ifdef HAVE_AES_DECRYPT + XMEMSET(plain, 0, AES_BLOCK_SIZE); + 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 -5805; + if (XMEMCMP(plain, msg, (int) sizeof(plain))) { + return -5806; + } +#endif + + if (XMEMCMP(cipher, verify, (int) sizeof(cipher))) + return -5807; + + wc_AesFree(&enc); +#ifdef HAVE_AES_DECRYPT + wc_AesFree(&dec); +#endif + +#endif /* HAVE_AES_CBC */ + + return ret; +} +#endif /* WOLFSSL_AES_192 */ + +#ifdef WOLFSSL_AES_256 +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 -5900; +#ifdef HAVE_AES_DECRYPT + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -5901; +#endif + + ret = wc_AesSetKey(&enc, key, (int) sizeof(key), iv, AES_ENCRYPTION); + if (ret != 0) + return -5902; +#ifdef HAVE_AES_DECRYPT + ret = wc_AesSetKey(&dec, key, (int) sizeof(key), iv, AES_DECRYPTION); + if (ret != 0) + return -5903; +#endif + + XMEMSET(cipher, 0, AES_BLOCK_SIZE); + 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 -5904; +#ifdef HAVE_AES_DECRYPT + XMEMSET(plain, 0, AES_BLOCK_SIZE); + 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 -5905; + if (XMEMCMP(plain, msg, (int) sizeof(plain))) { + return -5906; + } +#endif + + if (XMEMCMP(cipher, verify, (int) sizeof(cipher))) + return -5907; + + wc_AesFree(&enc); +#ifdef HAVE_AES_DECRYPT + wc_AesFree(&dec); +#endif + +#endif /* HAVE_AES_CBC */ + + return ret; +} +#endif /* WOLFSSL_AES_256 */ + + +#ifdef HAVE_AESGCM + +static int aesgcm_default_test_helper(byte* key, int keySz, byte* iv, int ivSz, + byte* plain, int plainSz, byte* cipher, int cipherSz, + byte* aad, int aadSz, byte* tag, int tagSz) +{ + Aes enc; + Aes dec; + + byte resultT[AES_BLOCK_SIZE]; + byte resultP[AES_BLOCK_SIZE * 3]; + byte resultC[AES_BLOCK_SIZE * 3]; + int result; + + XMEMSET(resultT, 0, sizeof(resultT)); + XMEMSET(resultC, 0, sizeof(resultC)); + XMEMSET(resultP, 0, sizeof(resultP)); + + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) { + return -5908; + } + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) { + return -5909; + } + + result = wc_AesGcmSetKey(&enc, key, keySz); + if (result != 0) + return -5910; + + /* AES-GCM encrypt and decrypt both use AES encrypt internally */ + result = wc_AesGcmEncrypt(&enc, resultC, plain, plainSz, iv, ivSz, + resultT, tagSz, aad, aadSz); + +#if defined(WOLFSSL_ASYNC_CRYPT) + result = wc_AsyncWait(result, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (result != 0) + return -5911; + if (cipher != NULL) { + if (XMEMCMP(cipher, resultC, cipherSz)) + return -5912; + } + if (XMEMCMP(tag, resultT, tagSz)) + return -5913; + + wc_AesFree(&enc); + +#ifdef HAVE_AES_DECRYPT + result = wc_AesGcmSetKey(&dec, key, keySz); + if (result != 0) + return -5914; + + result = wc_AesGcmDecrypt(&dec, resultP, resultC, cipherSz, + iv, ivSz, resultT, tagSz, aad, aadSz); +#if defined(WOLFSSL_ASYNC_CRYPT) + result = wc_AsyncWait(result, &dec.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (result != 0) + return -5915; + if (plain != NULL) { + if (XMEMCMP(plain, resultP, plainSz)) + return -5916; + } + + wc_AesFree(&dec); +#endif /* HAVE_AES_DECRYPT */ return 0; } -#ifdef HAVE_AESGCM + +/* tests that only use 12 byte IV and 16 or less byte AAD + * test vectors are from NIST SP 800-38D + * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES*/ +int aesgcm_default_test(void) +{ + byte key1[] = { + 0x29, 0x8e, 0xfa, 0x1c, 0xcf, 0x29, 0xcf, 0x62, + 0xae, 0x68, 0x24, 0xbf, 0xc1, 0x95, 0x57, 0xfc + }; + + byte iv1[] = { + 0x6f, 0x58, 0xa9, 0x3f, 0xe1, 0xd2, 0x07, 0xfa, + 0xe4, 0xed, 0x2f, 0x6d + }; + + ALIGN64 byte plain1[] = { + 0xcc, 0x38, 0xbc, 0xcd, 0x6b, 0xc5, 0x36, 0xad, + 0x91, 0x9b, 0x13, 0x95, 0xf5, 0xd6, 0x38, 0x01, + 0xf9, 0x9f, 0x80, 0x68, 0xd6, 0x5c, 0xa5, 0xac, + 0x63, 0x87, 0x2d, 0xaf, 0x16, 0xb9, 0x39, 0x01 + }; + + byte aad1[] = { + 0x02, 0x1f, 0xaf, 0xd2, 0x38, 0x46, 0x39, 0x73, + 0xff, 0xe8, 0x02, 0x56, 0xe5, 0xb1, 0xc6, 0xb1 + }; + + ALIGN64 byte cipher1[] = { + 0xdf, 0xce, 0x4e, 0x9c, 0xd2, 0x91, 0x10, 0x3d, + 0x7f, 0xe4, 0xe6, 0x33, 0x51, 0xd9, 0xe7, 0x9d, + 0x3d, 0xfd, 0x39, 0x1e, 0x32, 0x67, 0x10, 0x46, + 0x58, 0x21, 0x2d, 0xa9, 0x65, 0x21, 0xb7, 0xdb + }; + + byte tag1[] = { + 0x54, 0x24, 0x65, 0xef, 0x59, 0x93, 0x16, 0xf7, + 0x3a, 0x7a, 0x56, 0x05, 0x09, 0xa2, 0xd9, 0xf2 + }; + + byte key2[] = { + 0x01, 0x6d, 0xbb, 0x38, 0xda, 0xa7, 0x6d, 0xfe, + 0x7d, 0xa3, 0x84, 0xeb, 0xf1, 0x24, 0x03, 0x64 + }; + + byte iv2[] = { + 0x07, 0x93, 0xef, 0x3a, 0xda, 0x78, 0x2f, 0x78, + 0xc9, 0x8a, 0xff, 0xe3 + }; + + ALIGN64 byte plain2[] = { + 0x4b, 0x34, 0xa9, 0xec, 0x57, 0x63, 0x52, 0x4b, + 0x19, 0x1d, 0x56, 0x16, 0xc5, 0x47, 0xf6, 0xb7 + }; + + ALIGN64 byte cipher2[] = { + 0x60, 0x9a, 0xa3, 0xf4, 0x54, 0x1b, 0xc0, 0xfe, + 0x99, 0x31, 0xda, 0xad, 0x2e, 0xe1, 0x5d, 0x0c + }; + + byte tag2[] = { + 0x33, 0xaf, 0xec, 0x59, 0xc4, 0x5b, 0xaf, 0x68, + 0x9a, 0x5e, 0x1b, 0x13, 0xae, 0x42, 0x36, 0x19 + }; + + byte key3[] = { + 0xb0, 0x1e, 0x45, 0xcc, 0x30, 0x88, 0xaa, 0xba, + 0x9f, 0xa4, 0x3d, 0x81, 0xd4, 0x81, 0x82, 0x3f + }; + + byte iv3[] = { + 0x5a, 0x2c, 0x4a, 0x66, 0x46, 0x87, 0x13, 0x45, + 0x6a, 0x4b, 0xd5, 0xe1 + }; + + byte tag3[] = { + 0x01, 0x42, 0x80, 0xf9, 0x44, 0xf5, 0x3c, 0x68, + 0x11, 0x64, 0xb2, 0xff + }; + + int ret; + ret = aesgcm_default_test_helper(key1, sizeof(key1), iv1, sizeof(iv1), + plain1, sizeof(plain1), cipher1, sizeof(cipher1), + aad1, sizeof(aad1), tag1, sizeof(tag1)); + if (ret != 0) { + return ret; + } + ret = aesgcm_default_test_helper(key2, sizeof(key2), iv2, sizeof(iv2), + plain2, sizeof(plain2), cipher2, sizeof(cipher2), + NULL, 0, tag2, sizeof(tag2)); + if (ret != 0) { + return ret; + } + ret = aesgcm_default_test_helper(key3, sizeof(key3), iv3, sizeof(iv3), + NULL, 0, NULL, 0, + NULL, 0, tag3, sizeof(tag3)); + if (ret != 0) { + return ret; + } + + return 0; +} + int aesgcm_test(void) { Aes enc; + Aes dec; /* * This is Test Case 16 from the document Galois/ * Counter Mode of Operation (GCM) by McGrew and * Viega. */ - const byte k[] = - { - 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, - 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 - }; - - const byte iv[] = - { - 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, - 0xde, 0xca, 0xf8, 0x88 - }; - const byte p[] = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, @@ -2696,14 +8419,31 @@ int aesgcm_test(void) 0xba, 0x63, 0x7b, 0x39 }; +#if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_256) const byte a[] = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2 }; +#endif - const byte c[] = +#ifdef WOLFSSL_AES_256 + const byte k1[] = + { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 + }; + + const byte iv1[] = + { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 + }; + + const byte c1[] = { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, @@ -2714,42 +8454,478 @@ int aesgcm_test(void) 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62 }; +#endif /* WOLFSSL_AES_256 */ - const byte t[] = + const byte t1[] = { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }; - byte t2[sizeof(t)]; - byte p2[sizeof(c)]; - byte c2[sizeof(p)]; + /* FIPS, QAT and PIC32MZ HW Crypto only support 12-byte IV */ +#if !defined(HAVE_FIPS) && \ + !defined(WOLFSSL_PIC32MZ_CRYPT) && \ + !defined(FREESCALE_LTC) && !defined(FREESCALE_MMCAU) && \ + !defined(WOLFSSL_XILINX_CRYPT) && !defined(WOLFSSL_AFALG_XILINX_AES) && \ + !(defined(WOLF_CRYPTO_CB) && \ + (defined(HAVE_INTEL_QA_SYNC) || defined(HAVE_CAVIUM_OCTEON_SYNC))) - int result; + #define ENABLE_NON_12BYTE_IV_TEST +#ifdef WOLFSSL_AES_192 + /* Test Case 12, uses same plaintext and AAD data. */ + const byte k2[] = + { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c + }; - memset(t2, 0, sizeof(t2)); - memset(c2, 0, sizeof(c2)); - memset(p2, 0, sizeof(p2)); + const byte iv2[] = + { + 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, + 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, + 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, + 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, + 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, + 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, + 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, + 0xa6, 0x37, 0xb3, 0x9b + }; - wc_AesGcmSetKey(&enc, k, sizeof(k)); - /* AES-GCM encrypt and decrypt both use AES encrypt internally */ - wc_AesGcmEncrypt(&enc, c2, p, sizeof(c2), iv, sizeof(iv), - t2, sizeof(t2), a, sizeof(a)); - if (memcmp(c, c2, sizeof(c2))) - return -68; - if (memcmp(t, t2, sizeof(t2))) - return -69; + const byte c2[] = + { + 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, + 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, + 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, + 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, + 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, + 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, + 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, + 0xe9, 0xb7, 0x37, 0x3b + }; - result = wc_AesGcmDecrypt(&enc, p2, c2, sizeof(p2), iv, sizeof(iv), - t2, sizeof(t2), a, sizeof(a)); + const byte t2[] = + { + 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, + 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 + }; +#endif /* WOLFSSL_AES_192 */ +#ifdef WOLFSSL_AES_128 + /* The following is an interesting test case from the example + * FIPS test vectors for AES-GCM. IVlen = 1 byte */ + const byte p3[] = + { + 0x57, 0xce, 0x45, 0x1f, 0xa5, 0xe2, 0x35, 0xa5, + 0x8e, 0x1a, 0xa2, 0x3b, 0x77, 0xcb, 0xaf, 0xe2 + }; + + const byte k3[] = + { + 0xbb, 0x01, 0xd7, 0x03, 0x81, 0x1c, 0x10, 0x1a, + 0x35, 0xe0, 0xff, 0xd2, 0x91, 0xba, 0xf2, 0x4b + }; + + const byte iv3[] = + { + 0xca + }; + + const byte c3[] = + { + 0x6b, 0x5f, 0xb3, 0x9d, 0xc1, 0xc5, 0x7a, 0x4f, + 0xf3, 0x51, 0x4d, 0xc2, 0xd5, 0xf0, 0xd0, 0x07 + }; + + const byte a3[] = + { + 0x40, 0xfc, 0xdc, 0xd7, 0x4a, 0xd7, 0x8b, 0xf1, + 0x3e, 0x7c, 0x60, 0x55, 0x50, 0x51, 0xdd, 0x54 + }; + + const byte t3[] = + { + 0x06, 0x90, 0xed, 0x01, 0x34, 0xdd, 0xc6, 0x95, + 0x31, 0x2e, 0x2a, 0xf9, 0x57, 0x7a, 0x1e, 0xa6 + }; +#endif /* WOLFSSL_AES_128 */ +#ifdef WOLFSSL_AES_256 + int ivlen; +#endif +#endif + + byte resultT[sizeof(t1)]; + byte resultP[sizeof(p) + AES_BLOCK_SIZE]; + byte resultC[sizeof(p) + AES_BLOCK_SIZE]; + int result; +#ifdef WOLFSSL_AES_256 + int alen; + #if !defined(WOLFSSL_AFALG_XILINX_AES) && !defined(WOLFSSL_XILINX_CRYPT) + int plen; + #endif +#endif + +#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 + AES_BLOCK_SIZE]; + 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 + + (void)result; + + XMEMSET(resultT, 0, sizeof(resultT)); + XMEMSET(resultC, 0, sizeof(resultC)); + XMEMSET(resultP, 0, sizeof(resultP)); + + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) { + return -6100; + } + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) { + return -6101; + } + +#ifdef WOLFSSL_AES_256 + result = wc_AesGcmSetKey(&enc, k1, sizeof(k1)); if (result != 0) - return -70; - if (memcmp(p, p2, sizeof(p2))) - return -71; + return -6102; + + /* AES-GCM encrypt and decrypt both use AES encrypt internally */ + 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 -6103; + if (XMEMCMP(c1, resultC, sizeof(c1))) + return -6104; + if (XMEMCMP(t1, resultT, sizeof(resultT))) + return -6105; + +#ifdef HAVE_AES_DECRYPT + result = wc_AesGcmSetKey(&dec, k1, sizeof(k1)); + if (result != 0) + return -6106; + + result = wc_AesGcmDecrypt(&dec, resultP, resultC, sizeof(c1), + iv1, sizeof(iv1), resultT, sizeof(resultT), a, sizeof(a)); +#if defined(WOLFSSL_ASYNC_CRYPT) + result = wc_AsyncWait(result, &dec.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (result != 0) + return -6107; + if (XMEMCMP(p, resultP, sizeof(p))) + return -6108; +#endif /* HAVE_AES_DECRYPT */ + + /* Large buffer test */ +#ifdef BENCH_AESGCM_LARGE + /* setup test buffer */ + for (alen=0; alen= 2)) + /* Test encrypt with internally generated IV */ +#if defined(WOLFSSL_AES_256) && !(defined(WC_NO_RNG) || defined(HAVE_SELFTEST)) \ + && !(defined(WOLF_CRYPTO_CB) && defined(HAVE_CAVIUM_OCTEON_SYNC)) + { + WC_RNG rng; + byte randIV[12]; + + result = wc_InitRng(&rng); + if (result != 0) + return -6135; + + XMEMSET(randIV, 0, sizeof(randIV)); + XMEMSET(resultT, 0, sizeof(resultT)); + XMEMSET(resultC, 0, sizeof(resultC)); + XMEMSET(resultP, 0, sizeof(resultP)); + + wc_AesGcmSetKey(&enc, k1, sizeof(k1)); + result = wc_AesGcmSetIV(&enc, sizeof(randIV), NULL, 0, &rng); + if (result != 0) + return -6136; + + result = wc_AesGcmEncrypt_ex(&enc, + resultC, p, sizeof(p), + randIV, sizeof(randIV), + 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 -6137; + + /* Check the IV has been set. */ + { + word32 i, ivSum = 0; + + for (i = 0; i < sizeof(randIV); i++) + ivSum += randIV[i]; + if (ivSum == 0) + return -6138; + } + +#ifdef HAVE_AES_DECRYPT + wc_AesGcmSetKey(&dec, k1, sizeof(k1)); + result = wc_AesGcmSetIV(&dec, sizeof(randIV), NULL, 0, &rng); + if (result != 0) + return -6139; + + result = wc_AesGcmDecrypt(&dec, + resultP, resultC, sizeof(c1), + randIV, sizeof(randIV), + resultT, sizeof(resultT), + a, sizeof(a)); +#if defined(WOLFSSL_ASYNC_CRYPT) + result = wc_AsyncWait(result, &dec.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (result != 0) + return -6140; + if (XMEMCMP(p, resultP, sizeof(p))) + return -6141; +#endif /* HAVE_AES_DECRYPT */ + + wc_FreeRng(&rng); + } +#endif /* WOLFSSL_AES_256 && !(WC_NO_RNG || HAVE_SELFTEST) */ +#endif /* HAVE_FIPS_VERSION >= 2 */ + + wc_AesFree(&enc); + wc_AesFree(&dec); return 0; } +#ifdef WOLFSSL_AES_128 int gmac_test(void) { Gmac gmac; @@ -2775,6 +8951,10 @@ int gmac_test(void) 0xaa, 0x10, 0xf1, 0x6d, 0x22, 0x7d, 0xc4, 0x1b }; +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + /* FIPS builds only allow 16-byte auth tags. */ + /* This sample uses a 15-byte auth tag. */ const byte k2[] = { 0x40, 0xf7, 0xec, 0xb2, 0x52, 0x6d, 0xaa, 0xd4, @@ -2795,52 +8975,74 @@ int gmac_test(void) 0xc6, 0x81, 0x79, 0x8e, 0x3d, 0xda, 0xb0, 0x9f, 0x8d, 0x83, 0xb0, 0xbb, 0x14, 0xb6, 0x91 }; - - const byte k3[] = - { - 0xb8, 0xe4, 0x9a, 0x5e, 0x37, 0xf9, 0x98, 0x2b, - 0xb9, 0x6d, 0xd0, 0xc9, 0xb6, 0xab, 0x26, 0xac - }; - const byte iv3[] = - { - 0xe4, 0x4a, 0x42, 0x18, 0x8c, 0xae, 0x94, 0x92, - 0x6a, 0x9c, 0x26, 0xb0 - }; - const byte a3[] = - { - 0x9d, 0xb9, 0x61, 0x68, 0xa6, 0x76, 0x7a, 0x31, - 0xf8, 0x29, 0xe4, 0x72, 0x61, 0x68, 0x3f, 0x8a - }; - const byte t3[] = - { - 0x23, 0xe2, 0x9f, 0x66, 0xe4, 0xc6, 0x52, 0x48 - }; +#endif byte tag[16]; - memset(tag, 0, sizeof(tag)); + XMEMSET(&gmac, 0, sizeof(Gmac)); /* clear context */ + (void)wc_AesInit((Aes*)&gmac, HEAP_HINT, INVALID_DEVID); /* Make sure devId updated */ + XMEMSET(tag, 0, sizeof(tag)); wc_GmacSetKey(&gmac, k1, sizeof(k1)); wc_GmacUpdate(&gmac, iv1, sizeof(iv1), a1, sizeof(a1), tag, sizeof(t1)); - if (memcmp(t1, tag, sizeof(t1)) != 0) - return -126; + if (XMEMCMP(t1, tag, sizeof(t1)) != 0) + return -6200; - memset(tag, 0, sizeof(tag)); +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + XMEMSET(tag, 0, sizeof(tag)); wc_GmacSetKey(&gmac, k2, sizeof(k2)); wc_GmacUpdate(&gmac, iv2, sizeof(iv2), a2, sizeof(a2), tag, sizeof(t2)); - if (memcmp(t2, tag, sizeof(t2)) != 0) - return -127; + if (XMEMCMP(t2, tag, sizeof(t2)) != 0) + return -6201; - memset(tag, 0, sizeof(tag)); - wc_GmacSetKey(&gmac, k3, sizeof(k3)); - wc_GmacUpdate(&gmac, iv3, sizeof(iv3), a3, sizeof(a3), tag, sizeof(t3)); - if (memcmp(t3, tag, sizeof(t3)) != 0) - return -128; +#if !(defined(WC_NO_RNG) || defined(HAVE_SELFTEST)) + { + const byte badT[] = + { + 0xde, 0xad, 0xbe, 0xef, 0x17, 0x2e, 0xd0, 0x43, + 0xaa, 0x10, 0xf1, 0x6d, 0x22, 0x7d, 0xc4, 0x1b + }; + + WC_RNG rng; + byte iv[12]; + + #ifndef HAVE_FIPS + if (wc_InitRng_ex(&rng, HEAP_HINT, devId) != 0) + return -6202; + #else + if (wc_InitRng(&rng) != 0) + return -6203; + #endif + + if (wc_GmacVerify(k1, sizeof(k1), iv1, sizeof(iv1), a1, sizeof(a1), + t1, sizeof(t1)) != 0) + return -6204; + if (wc_GmacVerify(k1, sizeof(k1), iv1, sizeof(iv1), a1, sizeof(a1), + badT, sizeof(badT)) != AES_GCM_AUTH_E) + return -6205; + if (wc_GmacVerify(k2, sizeof(k2), iv2, sizeof(iv2), a2, sizeof(a2), + t2, sizeof(t2)) != 0) + return -6206; + + XMEMSET(tag, 0, sizeof(tag)); + XMEMSET(iv, 0, sizeof(iv)); + if (wc_Gmac(k1, sizeof(k1), iv, sizeof(iv), a1, sizeof(a1), + tag, sizeof(tag), &rng) != 0) + return -6207; + if (wc_GmacVerify(k1, sizeof(k1), iv, sizeof(iv), a1, sizeof(a1), + tag, sizeof(tag)) != 0) + return -6208; + wc_FreeRng(&rng); + } +#endif /* WC_NO_RNG HAVE_SELFTEST */ +#endif /* HAVE_FIPS */ return 0; } +#endif /* WOLFSSL_AES_128 */ #endif /* HAVE_AESGCM */ -#ifdef HAVE_AESCCM +#if defined(HAVE_AESCCM) && defined(WOLFSSL_AES_128) int aesccm_test(void) { Aes enc; @@ -2887,45 +9089,280 @@ int aesccm_test(void) byte t2[sizeof(t)]; byte p2[sizeof(p)]; byte c2[sizeof(c)]; + byte iv2[sizeof(iv)]; int result; - memset(t2, 0, sizeof(t2)); - memset(c2, 0, sizeof(c2)); - memset(p2, 0, sizeof(p2)); + XMEMSET(&enc, 0, sizeof(Aes)); /* clear context */ + XMEMSET(t2, 0, sizeof(t2)); + XMEMSET(c2, 0, sizeof(c2)); + XMEMSET(p2, 0, sizeof(p2)); + + result = wc_AesCcmSetKey(&enc, k, sizeof(k)); + if (result != 0) + return -6300; - wc_AesCcmSetKey(&enc, k, sizeof(k)); /* AES-CCM encrypt and decrypt both use AES encrypt internally */ - wc_AesCcmEncrypt(&enc, c2, p, sizeof(c2), iv, sizeof(iv), + result = wc_AesCcmEncrypt(&enc, c2, p, sizeof(c2), iv, sizeof(iv), t2, sizeof(t2), a, sizeof(a)); - if (memcmp(c, c2, sizeof(c2))) - return -107; - if (memcmp(t, t2, sizeof(t2))) - return -108; + if (result != 0) + return -6301; + if (XMEMCMP(c, c2, sizeof(c2))) + return -6302; + if (XMEMCMP(t, t2, sizeof(t2))) + return -6303; result = wc_AesCcmDecrypt(&enc, p2, c2, sizeof(p2), iv, sizeof(iv), t2, sizeof(t2), a, sizeof(a)); if (result != 0) - return -109; - if (memcmp(p, p2, sizeof(p2))) - return -110; + return -6304; + if (XMEMCMP(p, p2, sizeof(p2))) + return -6305; /* Test the authentication failure */ t2[0]++; /* Corrupt the authentication tag. */ result = wc_AesCcmDecrypt(&enc, p2, c, sizeof(p2), iv, sizeof(iv), t2, sizeof(t2), a, sizeof(a)); if (result == 0) - return -111; + return -6306; /* Clear c2 to compare against p2. p2 should be set to zero in case of * authentication fail. */ - memset(c2, 0, sizeof(c2)); - if (memcmp(p2, c2, sizeof(p2))) - return -112; + XMEMSET(c2, 0, sizeof(c2)); + if (XMEMCMP(p2, c2, sizeof(p2))) + return -6307; + + XMEMSET(&enc, 0, sizeof(Aes)); /* clear context */ + XMEMSET(t2, 0, sizeof(t2)); + XMEMSET(c2, 0, sizeof(c2)); + XMEMSET(p2, 0, sizeof(p2)); + XMEMSET(iv2, 0, sizeof(iv2)); + +#ifndef HAVE_SELFTEST + /* selftest build does not have wc_AesCcmSetNonce() or + * wc_AesCcmEncrypt_ex() */ + if (wc_AesCcmSetKey(&enc, k, sizeof(k)) != 0) + return -6308; + + if (wc_AesCcmSetNonce(&enc, iv, sizeof(iv)) != 0) + return -6309; + if (wc_AesCcmEncrypt_ex(&enc, c2, p, sizeof(c2), iv2, sizeof(iv2), + t2, sizeof(t2), a, sizeof(a)) != 0) + return -6310; + if (XMEMCMP(iv, iv2, sizeof(iv2))) + return -6311; + if (XMEMCMP(c, c2, sizeof(c2))) + return -6312; + if (XMEMCMP(t, t2, sizeof(t2))) + return -6313; +#endif return 0; } -#endif /* HAVE_AESCCM */ +#endif /* HAVE_AESCCM WOLFSSL_AES_128 */ + + +#ifdef HAVE_AES_KEYWRAP + +#define MAX_KEYWRAP_TEST_OUTLEN 40 +#define MAX_KEYWRAP_TEST_PLAINLEN 32 + +typedef struct keywrapVector { + const byte* kek; + const byte* data; + const byte* verify; + word32 kekLen; + word32 dataLen; + word32 verifyLen; +} keywrapVector; + +int aeskeywrap_test(void) +{ + int wrapSz, plainSz, testSz, i; + + /* test vectors from RFC 3394 (kek, data, verify) */ + +#ifdef WOLFSSL_AES_128 + /* Wrap 128 bits of Key Data with a 128-bit KEK */ + const byte k1[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + + const byte d1[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + + const byte v1[] = { + 0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47, + 0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82, + 0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5 + }; +#endif /* WOLFSSL_AES_128 */ + +#ifdef WOLFSSL_AES_192 + /* Wrap 128 bits of Key Data with a 192-bit KEK */ + const byte k2[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 + }; + + const byte d2[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + + const byte v2[] = { + 0x96, 0x77, 0x8B, 0x25, 0xAE, 0x6C, 0xA4, 0x35, + 0xF9, 0x2B, 0x5B, 0x97, 0xC0, 0x50, 0xAE, 0xD2, + 0x46, 0x8A, 0xB8, 0xA1, 0x7A, 0xD8, 0x4E, 0x5D + }; +#endif + +#ifdef WOLFSSL_AES_256 + /* Wrap 128 bits of Key Data with a 256-bit KEK */ + const byte k3[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F + }; + + const byte d3[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + + const byte v3[] = { + 0x64, 0xE8, 0xC3, 0xF9, 0xCE, 0x0F, 0x5B, 0xA2, + 0x63, 0xE9, 0x77, 0x79, 0x05, 0x81, 0x8A, 0x2A, + 0x93, 0xC8, 0x19, 0x1E, 0x7D, 0x6E, 0x8A, 0xE7 + }; +#endif + +#ifdef WOLFSSL_AES_192 + /* Wrap 192 bits of Key Data with a 192-bit KEK */ + const byte k4[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 + }; + + const byte d4[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + + const byte v4[] = { + 0x03, 0x1D, 0x33, 0x26, 0x4E, 0x15, 0xD3, 0x32, + 0x68, 0xF2, 0x4E, 0xC2, 0x60, 0x74, 0x3E, 0xDC, + 0xE1, 0xC6, 0xC7, 0xDD, 0xEE, 0x72, 0x5A, 0x93, + 0x6B, 0xA8, 0x14, 0x91, 0x5C, 0x67, 0x62, 0xD2 + }; +#endif + +#ifdef WOLFSSL_AES_256 + /* Wrap 192 bits of Key Data with a 256-bit KEK */ + const byte k5[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F + }; + + const byte d5[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + + const byte v5[] = { + 0xA8, 0xF9, 0xBC, 0x16, 0x12, 0xC6, 0x8B, 0x3F, + 0xF6, 0xE6, 0xF4, 0xFB, 0xE3, 0x0E, 0x71, 0xE4, + 0x76, 0x9C, 0x8B, 0x80, 0xA3, 0x2C, 0xB8, 0x95, + 0x8C, 0xD5, 0xD1, 0x7D, 0x6B, 0x25, 0x4D, 0xA1 + }; + + /* Wrap 256 bits of Key Data with a 256-bit KEK */ + const byte k6[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F + }; + + const byte d6[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + + const byte v6[] = { + 0x28, 0xC9, 0xF4, 0x04, 0xC4, 0xB8, 0x10, 0xF4, + 0xCB, 0xCC, 0xB3, 0x5C, 0xFB, 0x87, 0xF8, 0x26, + 0x3F, 0x57, 0x86, 0xE2, 0xD8, 0x0E, 0xD3, 0x26, + 0xCB, 0xC7, 0xF0, 0xE7, 0x1A, 0x99, 0xF4, 0x3B, + 0xFB, 0x98, 0x8B, 0x9B, 0x7A, 0x02, 0xDD, 0x21 + }; +#endif /* WOLFSSL_AES_256 */ + + byte output[MAX_KEYWRAP_TEST_OUTLEN]; + byte plain [MAX_KEYWRAP_TEST_PLAINLEN]; + + const keywrapVector test_wrap[] = + { + #ifdef WOLFSSL_AES_128 + {k1, d1, v1, sizeof(k1), sizeof(d1), sizeof(v1)}, + #endif + #ifdef WOLFSSL_AES_192 + {k2, d2, v2, sizeof(k2), sizeof(d2), sizeof(v2)}, + #endif + #ifdef WOLFSSL_AES_256 + {k3, d3, v3, sizeof(k3), sizeof(d3), sizeof(v3)}, + #endif + #ifdef WOLFSSL_AES_192 + {k4, d4, v4, sizeof(k4), sizeof(d4), sizeof(v4)}, + #endif + #ifdef WOLFSSL_AES_256 + {k5, d5, v5, sizeof(k5), sizeof(d5), sizeof(v5)}, + {k6, d6, v6, sizeof(k6), sizeof(d6), sizeof(v6)} + #endif + }; + testSz = sizeof(test_wrap) / sizeof(keywrapVector); + + XMEMSET(output, 0, sizeof(output)); + XMEMSET(plain, 0, sizeof(plain)); + + for (i = 0; i < testSz; i++) { + + wrapSz = wc_AesKeyWrap(test_wrap[i].kek, test_wrap[i].kekLen, + test_wrap[i].data, test_wrap[i].dataLen, + output, sizeof(output), NULL); + + if ( (wrapSz < 0) || (wrapSz != (int)test_wrap[i].verifyLen) ) + return -6400; + + if (XMEMCMP(output, test_wrap[i].verify, test_wrap[i].verifyLen) != 0) + return -6401; + + plainSz = wc_AesKeyUnWrap((byte*)test_wrap[i].kek, test_wrap[i].kekLen, + output, wrapSz, + plain, sizeof(plain), NULL); + + if ( (plainSz < 0) || (plainSz != (int)test_wrap[i].dataLen) ) + return -6402; + + if (XMEMCMP(plain, test_wrap[i].data, test_wrap[i].dataLen) != 0) + return -6403 - i; + } + + return 0; +} +#endif /* HAVE_AES_KEYWRAP */ #endif /* NO_AES */ @@ -3053,7 +9490,7 @@ int camellia_test(void) byte out[CAMELLIA_BLOCK_SIZE]; Camellia cam; - int i, testsSz; + int i, testsSz, ret; const test_vector_t testVectors[] = { {CAM_ECB_ENC, pte, ive, c1, k1, sizeof(k1), -114}, @@ -3078,25 +9515,31 @@ int camellia_test(void) switch (testVectors[i].type) { case CAM_ECB_ENC: - wc_CamelliaEncryptDirect(&cam, out, testVectors[i].plaintext); - if (memcmp(out, testVectors[i].ciphertext, CAMELLIA_BLOCK_SIZE)) + ret = wc_CamelliaEncryptDirect(&cam, out, + testVectors[i].plaintext); + if (ret != 0 || XMEMCMP(out, testVectors[i].ciphertext, + CAMELLIA_BLOCK_SIZE)) return testVectors[i].errorCode; break; case CAM_ECB_DEC: - wc_CamelliaDecryptDirect(&cam, out, testVectors[i].ciphertext); - if (memcmp(out, testVectors[i].plaintext, CAMELLIA_BLOCK_SIZE)) + ret = wc_CamelliaDecryptDirect(&cam, out, + testVectors[i].ciphertext); + if (ret != 0 || XMEMCMP(out, testVectors[i].plaintext, + CAMELLIA_BLOCK_SIZE)) return testVectors[i].errorCode; break; case CAM_CBC_ENC: - wc_CamelliaCbcEncrypt(&cam, out, testVectors[i].plaintext, + ret = wc_CamelliaCbcEncrypt(&cam, out, testVectors[i].plaintext, CAMELLIA_BLOCK_SIZE); - if (memcmp(out, testVectors[i].ciphertext, CAMELLIA_BLOCK_SIZE)) + if (ret != 0 || XMEMCMP(out, testVectors[i].ciphertext, + CAMELLIA_BLOCK_SIZE)) return testVectors[i].errorCode; break; case CAM_CBC_DEC: - wc_CamelliaCbcDecrypt(&cam, out, testVectors[i].ciphertext, - CAMELLIA_BLOCK_SIZE); - if (memcmp(out, testVectors[i].plaintext, CAMELLIA_BLOCK_SIZE)) + ret = wc_CamelliaCbcDecrypt(&cam, out, + testVectors[i].ciphertext, CAMELLIA_BLOCK_SIZE); + if (ret != 0 || XMEMCMP(out, testVectors[i].plaintext, + CAMELLIA_BLOCK_SIZE)) return testVectors[i].errorCode; break; default: @@ -3105,33 +9548,390 @@ int camellia_test(void) } /* Setting the IV and checking it was actually set. */ - wc_CamelliaSetIV(&cam, ivc); - if (XMEMCMP(cam.reg, ivc, CAMELLIA_BLOCK_SIZE)) - return -1; + ret = wc_CamelliaSetIV(&cam, ivc); + if (ret != 0 || XMEMCMP(cam.reg, ivc, CAMELLIA_BLOCK_SIZE)) + return -6500; /* Setting the IV to NULL should be same as all zeros IV */ if (wc_CamelliaSetIV(&cam, NULL) != 0 || XMEMCMP(cam.reg, ive, CAMELLIA_BLOCK_SIZE)) - return -1; + return -6501; /* First parameter should never be null */ if (wc_CamelliaSetIV(NULL, NULL) == 0) - return -1; + return -6502; /* First parameter should never be null, check it fails */ if (wc_CamelliaSetKey(NULL, k1, sizeof(k1), NULL) == 0) - return -1; + return -6503; /* Key should have a size of 16, 24, or 32 */ if (wc_CamelliaSetKey(&cam, k1, 0, NULL) == 0) - return -1; + return -6504; return 0; } #endif /* HAVE_CAMELLIA */ +#ifdef HAVE_IDEA +int idea_test(void) +{ + int ret; + word16 i, j; -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) + Idea idea; + byte data[IDEA_BLOCK_SIZE]; + + /* Project NESSIE test vectors */ +#define IDEA_NB_TESTS 6 +#define IDEA_NB_TESTS_EXTRA 4 + + const byte v_key[IDEA_NB_TESTS][IDEA_KEY_SIZE] = { + { 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37 }, + { 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57 }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, + 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48 }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, + 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48 }, + }; + + const byte v1_plain[IDEA_NB_TESTS][IDEA_BLOCK_SIZE] = { + { 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37 }, + { 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0xEA, 0x02, 0x47, 0x14, 0xAD, 0x5C, 0x4D, 0x84 }, + { 0xDB, 0x2D, 0x4A, 0x92, 0xAA, 0x68, 0x27, 0x3F }, + { 0xF1, 0x29, 0xA6, 0x60, 0x1E, 0xF6, 0x2A, 0x47 }, + }; + + byte v1_cipher[IDEA_NB_TESTS][IDEA_BLOCK_SIZE] = { + { 0x54, 0xCF, 0x21, 0xE3, 0x89, 0xD8, 0x73, 0xEC }, + { 0x85, 0x52, 0x4D, 0x41, 0x0E, 0xB4, 0x28, 0xAE }, + { 0xF5, 0x26, 0xAB, 0x9A, 0x62, 0xC0, 0xD2, 0x58 }, + { 0xC8, 0xFB, 0x51, 0xD3, 0x51, 0x66, 0x27, 0xA8 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0xEA, 0x02, 0x47, 0x14, 0xAD, 0x5C, 0x4D, 0x84 }, + }; + + byte v1_cipher_100[IDEA_NB_TESTS_EXTRA][IDEA_BLOCK_SIZE] = { + { 0x12, 0x46, 0x2F, 0xD0, 0xFB, 0x3A, 0x63, 0x39 }, + { 0x15, 0x61, 0xE8, 0xC9, 0x04, 0x54, 0x8B, 0xE9 }, + { 0x42, 0x12, 0x2A, 0x94, 0xB0, 0xF6, 0xD2, 0x43 }, + { 0x53, 0x4D, 0xCD, 0x48, 0xDD, 0xD5, 0xF5, 0x9C }, + }; + + byte v1_cipher_1000[IDEA_NB_TESTS_EXTRA][IDEA_BLOCK_SIZE] = { + { 0x44, 0x1B, 0x38, 0x5C, 0x77, 0x29, 0x75, 0x34 }, + { 0xF0, 0x4E, 0x58, 0x88, 0x44, 0x99, 0x22, 0x2D }, + { 0xB3, 0x5F, 0x93, 0x7F, 0x6A, 0xA0, 0xCD, 0x1F }, + { 0x9A, 0xEA, 0x46, 0x8F, 0x42, 0x9B, 0xBA, 0x15 }, + }; + + /* CBC test */ + const char *message = "International Data Encryption Algorithm"; + byte msg_enc[40], msg_dec[40]; + + for (i = 0; i < IDEA_NB_TESTS; i++) { + /* Set encryption key */ + XMEMSET(&idea, 0, sizeof(Idea)); + ret = wc_IdeaSetKey(&idea, v_key[i], IDEA_KEY_SIZE, + NULL, IDEA_ENCRYPTION); + if (ret != 0) { + printf("wc_IdeaSetKey (enc) failed\n"); + return -6600; + } + + /* Data encryption */ + ret = wc_IdeaCipher(&idea, data, v1_plain[i]); + if (ret != 0 || XMEMCMP(&v1_cipher[i], data, IDEA_BLOCK_SIZE)) { + printf("Bad encryption\n"); + return -6601; + } + + /* Set decryption key */ + XMEMSET(&idea, 0, sizeof(Idea)); + ret = wc_IdeaSetKey(&idea, v_key[i], IDEA_KEY_SIZE, + NULL, IDEA_DECRYPTION); + if (ret != 0) { + printf("wc_IdeaSetKey (dec) failed\n"); + return -6602; + } + + /* Data decryption */ + ret = wc_IdeaCipher(&idea, data, data); + if (ret != 0 || XMEMCMP(v1_plain[i], data, IDEA_BLOCK_SIZE)) { + printf("Bad decryption\n"); + return -6603; + } + + /* Set encryption key */ + XMEMSET(&idea, 0, sizeof(Idea)); + ret = wc_IdeaSetKey(&idea, v_key[i], IDEA_KEY_SIZE, + v_key[i], IDEA_ENCRYPTION); + if (ret != 0) { + printf("wc_IdeaSetKey (enc) failed\n"); + return -6604; + } + + XMEMSET(msg_enc, 0, sizeof(msg_enc)); + ret = wc_IdeaCbcEncrypt(&idea, msg_enc, (byte *)message, + (word32)XSTRLEN(message)+1); + if (ret != 0) { + printf("wc_IdeaCbcEncrypt failed\n"); + return -6605; + } + + /* Set decryption key */ + XMEMSET(&idea, 0, sizeof(Idea)); + ret = wc_IdeaSetKey(&idea, v_key[i], IDEA_KEY_SIZE, + v_key[i], IDEA_DECRYPTION); + if (ret != 0) { + printf("wc_IdeaSetKey (dec) failed\n"); + return -6606; + } + + XMEMSET(msg_dec, 0, sizeof(msg_dec)); + ret = wc_IdeaCbcDecrypt(&idea, msg_dec, msg_enc, + (word32)XSTRLEN(message)+1); + if (ret != 0) { + printf("wc_IdeaCbcDecrypt failed\n"); + return -6607; + } + + if (XMEMCMP(message, msg_dec, (word32)XSTRLEN(message))) { + printf("Bad CBC decryption\n"); + return -6608; + } + } + + for (i = 0; i < IDEA_NB_TESTS_EXTRA; i++) { + /* Set encryption key */ + XMEMSET(&idea, 0, sizeof(Idea)); + ret = wc_IdeaSetKey(&idea, v_key[i], IDEA_KEY_SIZE, + NULL, IDEA_ENCRYPTION); + if (ret != 0) { + printf("wc_IdeaSetKey (enc) failed\n"); + return -6609; + } + + /* 100 times data encryption */ + XMEMCPY(data, v1_plain[i], IDEA_BLOCK_SIZE); + for (j = 0; j < 100; j++) { + ret = wc_IdeaCipher(&idea, data, data); + if (ret != 0) { + return -6610; + } + } + + if (XMEMCMP(v1_cipher_100[i], data, IDEA_BLOCK_SIZE)) { + printf("Bad encryption (100 times)\n"); + return -6611; + } + + /* 1000 times data encryption */ + XMEMCPY(data, v1_plain[i], IDEA_BLOCK_SIZE); + for (j = 0; j < 1000; j++) { + ret = wc_IdeaCipher(&idea, data, data); + if (ret != 0) { + return -6612; + } + } + + if (XMEMCMP(v1_cipher_1000[i], data, IDEA_BLOCK_SIZE)) { + printf("Bad encryption (100 times)\n"); + return -6613; + } + } + +#ifndef WC_NO_RNG + /* random test for CBC */ + { + WC_RNG rng; + byte key[IDEA_KEY_SIZE], iv[IDEA_BLOCK_SIZE], + rnd[1000], enc[1000], dec[1000]; + + /* random values */ + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); + #else + ret = wc_InitRng(&rng); + #endif + if (ret != 0) + return -6614; + + for (i = 0; i < 1000; i++) { + /* random key */ + ret = wc_RNG_GenerateBlock(&rng, key, sizeof(key)); + if (ret != 0) + return -6615; + + /* random iv */ + ret = wc_RNG_GenerateBlock(&rng, iv, sizeof(iv)); + if (ret != 0) + return -6616; + + /* random data */ + ret = wc_RNG_GenerateBlock(&rng, rnd, sizeof(rnd)); + if (ret != 0) + return -6617; + + /* Set encryption key */ + XMEMSET(&idea, 0, sizeof(Idea)); + ret = wc_IdeaSetKey(&idea, key, IDEA_KEY_SIZE, iv, IDEA_ENCRYPTION); + if (ret != 0) { + printf("wc_IdeaSetKey (enc) failed\n"); + return -6618; + } + + /* Data encryption */ + XMEMSET(enc, 0, sizeof(enc)); + ret = wc_IdeaCbcEncrypt(&idea, enc, rnd, sizeof(rnd)); + if (ret != 0) { + printf("wc_IdeaCbcEncrypt failed\n"); + return -6619; + } + + /* Set decryption key */ + XMEMSET(&idea, 0, sizeof(Idea)); + ret = wc_IdeaSetKey(&idea, key, IDEA_KEY_SIZE, iv, IDEA_DECRYPTION); + if (ret != 0) { + printf("wc_IdeaSetKey (enc) failed\n"); + return -6620; + } + + /* Data decryption */ + XMEMSET(dec, 0, sizeof(dec)); + ret = wc_IdeaCbcDecrypt(&idea, dec, enc, sizeof(enc)); + if (ret != 0) { + printf("wc_IdeaCbcDecrypt failed\n"); + return -6621; + } + + if (XMEMCMP(rnd, dec, sizeof(rnd))) { + printf("Bad CBC decryption\n"); + return -6622; + } + } + + wc_FreeRng(&rng); + } +#endif /* WC_NO_RNG */ + + return 0; +} +#endif /* HAVE_IDEA */ + + +#ifndef WC_NO_RNG +static int _rng_test(WC_RNG* rng, int errorOffset) +{ + byte block[32]; + int ret, i; + + XMEMSET(block, 0, sizeof(block)); + + ret = wc_RNG_GenerateBlock(rng, block, sizeof(block)); + if (ret != 0) { + ret = -6623; + goto exit; + } + + /* Check for 0's */ + for (i=0; i<(int)sizeof(block); i++) { + if (block[i] == 0) { + ret++; + } + } + /* All zeros count check */ + if (ret >= (int)sizeof(block)) { + ret = -6624; + goto exit; + } + + ret = wc_RNG_GenerateByte(rng, block); + if (ret != 0) { + ret = -6625; + goto exit; + } + + /* Parameter validation testing. */ + ret = wc_RNG_GenerateBlock(NULL, block, sizeof(block)); + if (ret != BAD_FUNC_ARG) { + ret = -6626; + goto exit; + } + ret = wc_RNG_GenerateBlock(rng, NULL, sizeof(block)); + if (ret != BAD_FUNC_ARG) { + ret = -6627; + goto exit; + } + + ret = wc_RNG_GenerateByte(NULL, block); + if (ret != BAD_FUNC_ARG) { + ret = -6628; + goto exit; + } + ret = wc_RNG_GenerateByte(rng, NULL); + if (ret != BAD_FUNC_ARG) { + ret = -6629; + goto exit; + } + + ret = 0; + +exit: + if (ret != 0) + ret += errorOffset; + + return ret; +} + + +static int random_rng_test(void) +{ + WC_RNG localRng; + WC_RNG* rng; + int ret; + + rng = &localRng; + /* Test stack based RNG. */ +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(rng); +#endif + if (ret != 0) return -6700; + + ret = _rng_test(rng, -6300); + + /* Make sure and free RNG */ + wc_FreeRng(rng); + + if (ret != 0) return ret; + +#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + { + byte nonce[8] = { 0 }; + /* Test dynamic RNG. */ + rng = wc_rng_new(nonce, (word32)sizeof(nonce), HEAP_HINT); + if (rng == NULL) return -6701; + + ret = _rng_test(rng, -6310); + + wc_rng_free(rng); + } +#endif + + return ret; +} + +#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) int random_test(void) { @@ -3184,53 +9984,240 @@ 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 -6800; if (XMEMCMP(test1Output, output, sizeof(output)) != 0) - return -40; + return -6801; ret = wc_RNG_HealthTest(1, test2EntropyA, sizeof(test2EntropyA), test2EntropyB, sizeof(test2EntropyB), output, sizeof(output)); if (ret != 0) - return -41; + return -6802; if (XMEMCMP(test2Output, output, sizeof(output)) != 0) - return -42; + return -6803; + /* Basic RNG generate block test */ + if ((ret = random_rng_test()) != 0) + return ret; + + /* Test the seed check function. */ +#if !(defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + { + word32 i, outputSz; + + /* Repeat the same byte over and over. Should fail. */ + outputSz = sizeof(output); + XMEMSET(output, 1, outputSz); + ret = wc_RNG_TestSeed(output, outputSz); + if (ret == 0) + return -6804; + + /* Every byte of the entropy scratch is different, + * entropy is a single byte that shouldn't match. */ + outputSz = (sizeof(word32) * 2) + 1; + for (i = 0; i < outputSz; i++) + output[i] = (byte)i; + ret = wc_RNG_TestSeed(output, outputSz); + if (ret != 0) + return -6805; + + outputSz = sizeof(output); + for (i = 0; i < outputSz; i++) + output[i] = (byte)i; + ret = wc_RNG_TestSeed(output, outputSz); + if (ret != 0) + return -6806; + } +#endif return 0; } -#else /* HAVE_HASHDRBG || NO_RC4 */ +#else int random_test(void) { - RNG rng; - byte block[32]; - int ret; - -#ifdef HAVE_CAVIUM - ret = wc_InitRngCavium(&rng, CAVIUM_DEV_ID); - if (ret != 0) return -2007; -#endif - ret = wc_InitRng(&rng); - if (ret != 0) return -39; - - ret = wc_RNG_GenerateBlock(&rng, block, sizeof(block)); - if (ret != 0) return -40; - - wc_FreeRng(&rng); - - return 0; + /* Basic RNG generate block test */ + return random_rng_test(); } -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK */ +#endif /* WC_NO_RNG */ + +#ifndef MEM_TEST_SZ + #define MEM_TEST_SZ 1024 +#endif + +#if defined(WOLFSSL_STATIC_MEMORY) || !defined(WOLFSSL_NO_MALLOC) +static int simple_mem_test(int sz) +{ + int ret = 0; + byte* b; + int i; + + b = (byte*)XMALLOC(sz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) { + return -6900; + } + /* utilize memory */ + for (i = 0; i < sz; i++) { + b[i] = (byte)i; + } + /* read back and verify */ + for (i = 0; i < sz; i++) { + if (b[i] != (byte)i) { + ret = -6901; + break; + } + } + XFREE(b, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} +#endif + +int memory_test(void) +{ + int ret = 0; +#ifndef USE_FAST_MATH + byte* b = NULL; +#endif +#if defined(COMPLEX_MEM_TEST) || defined(WOLFSSL_STATIC_MEMORY) + int i; +#endif +#ifdef WOLFSSL_STATIC_MEMORY + word32 size[] = { WOLFMEM_BUCKETS }; + word32 dist[] = { WOLFMEM_DIST }; + byte buffer[30000]; /* make large enough to involve many bucket sizes */ + int pad = -(int)((wolfssl_word)buffer) & (WOLFSSL_STATIC_ALIGN - 1); + /* pad to account for if head of buffer is not at set memory + * alignment when tests are ran */ +#endif + +#ifdef WOLFSSL_STATIC_MEMORY + /* check macro settings */ + if (sizeof(size)/sizeof(word32) != WOLFMEM_MAX_BUCKETS) { + return -7000; + } + + if (sizeof(dist)/sizeof(word32) != WOLFMEM_MAX_BUCKETS) { + return -7001; + } + + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + if ((size[i] % WOLFSSL_STATIC_ALIGN) != 0) { + /* each element in array should be divisible by alignment size */ + return -7002; + } + } + + for (i = 1; i < WOLFMEM_MAX_BUCKETS; i++) { + if (size[i - 1] >= size[i]) { + return -7003; /* sizes should be in increasing order */ + } + } + + /* check that padding size returned is possible */ + if (wolfSSL_MemoryPaddingSz() < WOLFSSL_STATIC_ALIGN) { + return -7004; /* no room for wc_Memory struct */ + } + + if (wolfSSL_MemoryPaddingSz() < 0) { + return -7005; + } + + if (wolfSSL_MemoryPaddingSz() % WOLFSSL_STATIC_ALIGN != 0) { + return -7006; /* 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 -7007; /* not aligned! */ + } + + if (ret < 0) { + return -7008; + } + + if ((unsigned int)ret > sizeof(buffer)) { + return -7009; /* did not round down as expected */ + } + + if (ret != wolfSSL_StaticBufferSz(buffer, ret, WOLFMEM_GENERAL)) { + return -7010; /* return 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 -7011; /* did not round down to nearest bucket value */ + } + + ret = wolfSSL_StaticBufferSz(buffer, sizeof(buffer), WOLFMEM_IO_POOL); + if ((ret - pad) < 0) { + return -7012; + } + + if (((ret - pad) % (WOLFMEM_IO_SZ + wolfSSL_MemoryPaddingSz())) != 0) { + return -7013; /* not even chunks of memory for IO size */ + } + + if (((ret - pad) % WOLFSSL_STATIC_ALIGN) != 0) { + return -7014; /* memory not aligned */ + } + + /* check for passing bad or unknown arguments to functions */ + if (wolfSSL_StaticBufferSz(NULL, 1, WOLFMEM_GENERAL) > 0) { + return -7015; + } + + if (wolfSSL_StaticBufferSz(buffer, 1, WOLFMEM_GENERAL) != 0) { + return -7016; /* should round to 0 since struct + bucket will not fit */ + } + + (void)dist; /* avoid static analysis warning of variable not used */ +#endif + +#if defined(WOLFSSL_STATIC_MEMORY) || !defined(WOLFSSL_NO_MALLOC) + /* simple test */ + ret = simple_mem_test(MEM_TEST_SZ); + if (ret != 0) + return ret; +#endif + +#ifdef COMPLEX_MEM_TEST + /* test various size blocks */ + for (i = 1; i < MEM_TEST_SZ; i*=2) { + ret = simple_mem_test(i); + if (ret != 0) + return ret; + } +#endif + +#ifndef USE_FAST_MATH + /* realloc test */ + b = (byte*)XMALLOC(MEM_TEST_SZ, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (b) { + b = (byte*)XREALLOC(b, MEM_TEST_SZ+sizeof(word32), HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + } + if (b == NULL) { + return -7017; + } + XFREE(b, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} #ifdef HAVE_NTRU @@ -3239,7 +10226,7 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out); byte GetEntropy(ENTROPY_CMD cmd, byte* out) { - static RNG rng; + static WC_RNG rng; if (cmd == INIT) return (wc_InitRng(&rng) == 0) ? 1 : 0; @@ -3260,708 +10247,3347 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) #endif /* HAVE_NTRU */ -#ifndef NO_RSA +#ifndef NO_FILESYSTEM + +/* Cert Paths */ +#ifdef FREESCALE_MQX + #define CERT_PREFIX "a:\\" + #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(USE_CERT_BUFFERS_3072) && !defined(USE_CERT_BUFFERS_4096) + #if !defined(NO_RSA) && !defined(NO_ASN) + 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 = CERT_ROOT "client-keyPub.der"; + #endif + #endif /* !NO_RSA && !NO_ASN */ +#endif #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 WOLFSSL_CERT_GEN - static const char* caKeyFile = "a:\\certs\\ca-key.der"; - static const char* caCertFile = "a:\\certs\\ca-cert.pem"; - #ifdef HAVE_ECC - static const char* eccCaKeyFile = "a:\\certs\\ecc-key.der"; - static const char* eccCaCertFile = "a:\\certs\\server-ecc.pem"; + #if !defined(NO_RSA) && !defined(NO_ASN) + #if defined(WOLFSSL_CERT_GEN) || defined(HAVE_PKCS7) + static const char* rsaCaKeyFile = CERT_ROOT "ca-key.der"; + #ifdef WOLFSSL_CERT_GEN + static const char* rsaCaCertFile = CERT_ROOT "ca-cert.pem"; + #endif + #if defined(WOLFSSL_ALT_NAMES) || defined(HAVE_PKCS7) + static const char* rsaCaCertDerFile = CERT_ROOT "ca-cert.der"; + #endif + #ifdef HAVE_PKCS7 + static const char* rsaServerCertDerFile = + CERT_ROOT "server-cert.der"; + static const char* rsaServerKeyDerFile = + CERT_ROOT "server-key.der"; #endif #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 WOLFSSL_CERT_GEN - static char* caKeyFile = "certs/ca-key.der"; - 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"; - static const char* eccCaCertFile = "certs/server-ecc.pem"; - void set_eccCaKeyFile (char * key) { eccCaKeyFile = key ; } - void set_eccCaCertFile(char * cert) { eccCaCertFile = cert ; } + #endif /* !NO_RSA && !NO_ASN */ +#endif /* !USE_CERT_BUFFER_* */ +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ + !defined(USE_CERT_BUFFERS_3072) && !defined(USE_CERT_BUFFERS_4096) && \ + !defined(NO_ASN) + #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) + #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 +#endif +#if !defined(USE_CERT_BUFFERS_256) && !defined(NO_ASN) + #if defined(HAVE_ECC) && defined(WOLFSSL_CERT_GEN) + #ifndef NO_RSA + /* eccKeyPubFile is used in a test that requires RSA. */ + static const char* eccKeyPubFile = CERT_ROOT "ecc-keyPub.der"; + #endif + 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 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"; - static const char* eccCaCertFile = "./certs/server-ecc.pem"; - #endif + #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 + #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 + #ifdef HAVE_ED448 + #ifdef WOLFSSL_TEST_CERT + static const char* serverEd448Cert = + CERT_ROOT "ed448/server-ed448.der"; + static const char* caEd448Cert = CERT_ROOT "ed448/ca-ed448.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) && defined(WOLFSSL_TEST_CERT)) + 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 */ + + +#if defined(WOLFSSL_CERT_GEN) && (!defined(NO_RSA) || defined(HAVE_ECC)) || \ + (defined(WOLFSSL_TEST_CERT) && (defined(HAVE_ED25519) || defined(HAVE_ED448))) +#ifdef WOLFSSL_MULTI_ATTRIB +static CertName certDefaultName; +static void initDefaultName(void) +{ + XMEMCPY(certDefaultName.country, "US", sizeof("US")); + certDefaultName.countryEnc = CTC_PRINTABLE; + XMEMCPY(certDefaultName.state, "Oregon", sizeof("Oregon")); + certDefaultName.stateEnc = CTC_UTF8; + XMEMCPY(certDefaultName.locality, "Portland", sizeof("Portland")); + certDefaultName.localityEnc = CTC_UTF8; + XMEMCPY(certDefaultName.sur, "Test", sizeof("Test")); + certDefaultName.surEnc = CTC_UTF8; + XMEMCPY(certDefaultName.org, "wolfSSL", sizeof("wolfSSL")); + certDefaultName.orgEnc = CTC_UTF8; + XMEMCPY(certDefaultName.unit, "Development", sizeof("Development")); + certDefaultName.unitEnc = CTC_UTF8; + XMEMCPY(certDefaultName.commonName, "www.wolfssl.com", sizeof("www.wolfssl.com")); + certDefaultName.commonNameEnc = CTC_UTF8; + XMEMCPY(certDefaultName.serialDev, "wolfSSL12345", sizeof("wolfSSL12345")); + certDefaultName.serialDevEnc = CTC_PRINTABLE; +#ifdef WOLFSSL_CERT_EXT + XMEMCPY(certDefaultName.busCat, "Private Organization", sizeof("Private Organization")); + certDefaultName.busCatEnc = CTC_UTF8; +#endif + XMEMCPY(certDefaultName.email, "info@wolfssl.com", sizeof("info@wolfssl.com")); + +#ifdef WOLFSSL_TEST_CERT + { + NameAttrib* n; + /* test having additional OUs and setting DC */ + n = &certDefaultName.name[0]; + n->id = ASN_ORGUNIT_NAME; + n->type = CTC_UTF8; + n->sz = sizeof("Development-2"); + XMEMCPY(n->value, "Development-2", sizeof("Development-2")); + + #if CTC_MAX_ATTRIB > 3 + n = &certDefaultName.name[1]; + n->id = ASN_DOMAIN_COMPONENT; + n->type = CTC_UTF8; + n->sz = sizeof("com"); + XMEMCPY(n->value, "com", sizeof("com")); + + n = &certDefaultName.name[2]; + n->id = ASN_DOMAIN_COMPONENT; + n->type = CTC_UTF8; + n->sz = sizeof("wolfssl"); + XMEMCPY(n->value, "wolfssl", sizeof("wolfssl")); + + #endif + } +#endif /* WOLFSSL_TEST_CERT */ +} +#else +static const CertName certDefaultName = { + "US", CTC_PRINTABLE, /* country */ + "Oregon", 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 */ + "wolfSSL12345", CTC_PRINTABLE, /* serial number of device */ +#ifdef WOLFSSL_CERT_EXT + "Private Organization", CTC_UTF8, /* businessCategory */ + "US", CTC_PRINTABLE, /* jurisdiction country */ + "Oregon", CTC_PRINTABLE, /* jurisdiction state */ +#endif + "info@wolfssl.com" /* email */ +}; +#endif /* WOLFSSL_MULTI_ATTRIB */ + +#ifdef WOLFSSL_CERT_EXT + #if ((defined(HAVE_ED25519) || defined(HAVE_ED448)) && \ + defined(WOLFSSL_TEST_CERT)) || defined(HAVE_ECC) + static const char certKeyUsage[] = + "digitalSignature,nonRepudiation"; + #endif + #if (defined(WOLFSSL_CERT_REQ) || defined(HAVE_NTRU)) && !defined(NO_RSA) + 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(NO_RSA) && defined(WOLFSSL_TEST_CERT) && \ + !defined(NO_FILESYSTEM) +static byte minSerial[] = { 0x02, 0x01, 0x01 }; +static byte minName[] = { 0x30, 0x00 }; +static byte nameBad[] = { + 0x30, 0x08, + 0x31, 0x06, + 0x30, 0x04, + 0x06, 0x02, + 0x55, 0x04, +}; +static byte minDates[] = { + 0x30, 0x1e, + 0x17, 0x0d, + 0x31, 0x38, 0x30, 0x34, 0x31, 0x33, 0x31, 0x35, + 0x32, 0x33, 0x31, 0x30, 0x5a, + 0x17, 0x0d, + 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, + 0x32, 0x33, 0x31, 0x30, 0x5a +}; +static byte minPubKey[] = { + 0x30, 0x1b, + 0x30, 0x0d, + 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, + 0x05, 0x00, + 0x03, 0x0b, + 0x00, 0x30, 0x08, + 0x02, 0x01, + 0x03, + 0x02, 0x03, + 0x01, 0x00, 0x01 +}; +static byte minSigAlg[] = { + 0x30, 0x0d, + 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x0b, + 0x05, 0x00 +}; +static byte minSig[] = { + 0x03, 0x01, + 0x00 +}; + +static int add_seq(byte* certData, int offset, byte* data, byte length) +{ + XMEMMOVE(certData + offset + 2, data, length); + certData[offset++] = 0x30; + certData[offset++] = length; + return offset + length; +} +static int add_data(byte* certData, int offset, byte* data, byte length) +{ + XMEMCPY(certData + offset, data, length); + return offset + length; +} + +static int cert_asn1_test(void) +{ + int ret; + int len[3]; + DecodedCert cert; + byte certData[106]; + byte* badCert = NULL; + + len[2] = add_data(certData, 0, minSerial, (byte)sizeof(minSerial)); + len[2] = add_data(certData, len[2], minSigAlg, (byte)sizeof(minSigAlg)); + len[2] = add_data(certData, len[2], minName, (byte)sizeof(minName)); + len[2] = add_data(certData, len[2], minDates, (byte)sizeof(minDates)); + len[2] = add_data(certData, len[2], minName, (byte)sizeof(minName)); + len[2] = add_data(certData, len[2], minPubKey, (byte)sizeof(minPubKey)); + len[1] = add_seq(certData, 0, certData, len[2]); + len[1] = add_data(certData, len[1], minSigAlg, (byte)sizeof(minSigAlg)); + len[1] = add_data(certData, len[1], minSig, (byte)sizeof(minSig)); + len[0] = add_seq(certData, 0, certData, len[1]); + + /* Minimal good certificate */ + InitDecodedCert(&cert, certData, len[0], 0); + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + FreeDecodedCert(&cert); + if (ret != 0) { + ERROR_OUT(-7100, done); + } + + /* Bad issuer name */ + len[2] = add_data(certData, 0, minSerial, (byte)sizeof(minSerial)); + len[2] = add_data(certData, len[2], minSigAlg, (byte)sizeof(minSigAlg)); + len[2] = add_data(certData, len[2], nameBad, (byte)sizeof(nameBad)); + len[1] = add_seq(certData, 0, certData, len[2]); + len[0] = add_seq(certData, 0, certData, len[1]); + /* Put data into allocated buffer to allow access error checking. */ + badCert = (byte*)XMALLOC(len[0], HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XMEMCPY(badCert, certData, len[0]); + InitDecodedCert(&cert, badCert, len[0], 0); + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + FreeDecodedCert(&cert); + if (ret != ASN_PARSE_E) { + ERROR_OUT(-7101, done); + } + XFREE(badCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + badCert = NULL; + ret = 0; + +done: + if (badCert != NULL) + XFREE(badCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + +int cert_test(void) +{ +#if !defined(NO_FILESYSTEM) + DecodedCert cert; + byte* tmp; + size_t bytes; + XFILE file; + int ret; + + tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return -7200; + + /* Certificate with Name Constraints extension. */ +#ifdef FREESCALE_MQX + file = XFOPEN(".\\certs\\test\\cert-ext-nc.der", "rb"); +#else + file = XFOPEN("./certs/test/cert-ext-nc.der", "rb"); +#endif + if (!file) { + ERROR_OUT(-7201, done); + } + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + ERROR_OUT(-7202, done); + } + FreeDecodedCert(&cert); + + /* Certificate with Inhibit Any Policy extension. */ +#ifdef FREESCALE_MQX + file = XFOPEN(".\\certs\\test\\cert-ext-ia.der", "rb"); +#else + file = XFOPEN("./certs/test/cert-ext-ia.der", "rb"); +#endif + if (!file) { + ERROR_OUT(-7203, done); + } + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + ERROR_OUT(-7204, done); + } + FreeDecodedCert(&cert); + + /* Certificate with Netscape Certificate Type extension. */ +#ifdef FREESCALE_MQX + file = XFOPEN(".\\certs\\test\\cert-ext-nct.der", "rb"); +#else + file = XFOPEN("./certs/test/cert-ext-nct.der", "rb"); +#endif + if (!file) { + ERROR_OUT(-7203, done); + } + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); +#ifndef IGNORE_NETSCAPE_CERT_TYPE + if (ret != 0) { + ERROR_OUT(-7204, done); + } +#else + if (ret != ASN_CRIT_EXT_E) { + ERROR_OUT(-7205, done); + } + ret = 0; +#endif + +done: + FreeDecodedCert(&cert); + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#endif /* !NO_FILESYSTEM */ + + if (ret == 0) + ret = cert_asn1_test(); + + return ret; +} +#endif /* WOLFSSL_TEST_CERT */ + +#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) && \ + !defined(NO_FILESYSTEM) +int certext_test(void) +{ + DecodedCert cert; + byte* tmp; + size_t bytes; + XFILE file; + int ret; + + /* created from rsa_test : othercert.der */ + byte skid_rsa[] = "\x33\xD8\x45\x66\xD7\x68\x87\x18\x7E\x54" + "\x0D\x70\x27\x91\xC7\x26\xD7\x85\x65\xC0"; + + /* created from rsa_test : othercert.der */ + byte akid_rsa[] = "\x27\x8E\x67\x11\x74\xC3\x26\x1D\x3F\xED" + "\x33\x63\xB3\xA4\xD8\x1D\x30\xE5\xE8\xD5"; + +#ifdef HAVE_ECC + /* 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" + "\x0D\x70\x27\x91\xC7\x26\xD7\x85\x65\xC0"; + + tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return -7300; + + /* load othercert.der (Cert signed by an authority) */ + file = XFOPEN(otherCertDerFile, "rb"); + if (!file) { + XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + return -7301; + } + + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); + + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) + return -7302; + + /* check the SKID from a RSA certificate */ + if (XMEMCMP(skid_rsa, cert.extSubjKeyId, sizeof(cert.extSubjKeyId))) + return -7303; + + /* check the AKID from an RSA certificate */ + if (XMEMCMP(akid_rsa, cert.extAuthKeyId, sizeof(cert.extAuthKeyId))) + return -7304; + + /* check the Key Usage from an RSA certificate */ + if (!cert.extKeyUsageSet) + return -7305; + + if (cert.extKeyUsage != (KEYUSE_KEY_ENCIPHER|KEYUSE_KEY_AGREE)) + return -7306; + + /* check the CA Basic Constraints from an RSA certificate */ + if (cert.isCA) + return -7307; + +#ifndef WOLFSSL_SEP /* test only if not using SEP policies */ + /* check the Certificate Policies Id */ + if (cert.extCertPoliciesNb != 1) + return -7308; + + if (strncmp(cert.extCertPolicies[0], "2.16.840.1.101.3.4.1.42", 23)) + return -7309; +#endif + + FreeDecodedCert(&cert); + +#ifdef HAVE_ECC + /* load certecc.der (Cert signed by our ECC CA test in ecc_test_cert_gen) */ + file = XFOPEN(certEccDerFile, "rb"); + if (!file) { + XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + return -7310; + } + + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); + + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) + return -7311; + + /* 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 -7312; + + /* check the Key Usage from an ECC certificate */ + if (!cert.extKeyUsageSet) + return -7313; + + if (cert.extKeyUsage != (KEYUSE_DIGITAL_SIG|KEYUSE_CONTENT_COMMIT)) + return -7314; + + /* check the CA Basic Constraints from an ECC certificate */ + if (cert.isCA) + return -7315; + +#ifndef WOLFSSL_SEP /* test only if not using SEP policies */ + /* check the Certificate Policies Id */ + if (cert.extCertPoliciesNb != 2) + return -7316; + + if (strncmp(cert.extCertPolicies[0], "2.4.589440.587.101.2.1.9632587.1", 32)) + return -7317; + + if (strncmp(cert.extCertPolicies[1], "1.2.13025.489.1.113549", 22)) + return -7318; +#endif + + FreeDecodedCert(&cert); +#endif /* HAVE_ECC */ + + /* load cert.der (self signed certificate) */ + file = XFOPEN(certDerFile, "rb"); + if (!file) { + XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + return -7319; + } + + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); + + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) + return -7320; + + /* check the SKID from a CA certificate */ + if (XMEMCMP(kid_ca, cert.extSubjKeyId, sizeof(cert.extSubjKeyId))) + return -7321; + + /* check the AKID from an CA certificate */ + if (XMEMCMP(kid_ca, cert.extAuthKeyId, sizeof(cert.extAuthKeyId))) + return -7322; + + /* check the Key Usage from CA certificate */ + if (!cert.extKeyUsageSet) + return -7323; + + if (cert.extKeyUsage != (KEYUSE_KEY_CERT_SIGN|KEYUSE_CRL_SIGN)) + return -7324; + + /* check the CA Basic Constraints CA certificate */ + if (!cert.isCA) + return -7325; + +#ifndef WOLFSSL_SEP /* test only if not using SEP policies */ + /* check the Certificate Policies Id */ + if (cert.extCertPoliciesNb != 2) + return -7326; + + if (strncmp(cert.extCertPolicies[0], "2.16.840.1.101.3.4.1.42", 23)) + return -7327; + + if (strncmp(cert.extCertPolicies[1], "1.2.840.113549.1.9.16.6.5", 25)) + return -7328; +#endif + + FreeDecodedCert(&cert); + XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + + return 0; +} +#endif /* WOLFSSL_CERT_EXT && WOLFSSL_TEST_CERT */ + +#if defined(WOLFSSL_CERT_GEN_CACHE) && defined(WOLFSSL_TEST_CERT) && \ + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) +int decodedCertCache_test(void) +{ + int ret = 0; + Cert cert; + FILE* file; + byte* der; + word32 derSz; + + derSz = FOURK_BUF; + der = XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) + ret = -7400; + + if (ret == 0) { + /* load cert.der */ + file = XFOPEN(certDerFile, "rb"); + if (file != NULL) { + derSz = XFREAD(der, 1, FOURK_BUF, file); + XFCLOSE(file); + } + else + ret = -7401; + } + + if (ret == 0) { + if (wc_InitCert(&cert)) { + ret = -7402; + } + } + + if (ret == 0) { + ret = wc_SetSubjectBuffer(&cert, der, derSz); + } + + if (ret == 0) { + if(wc_SetSubjectBuffer(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -7403; + } + + if (ret == 0) { + if (wc_SetSubjectRaw(&cert, der, derSz) != 0) + ret = -7404; + } + + if (ret == 0) { + if(wc_SetSubjectRaw(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -7405; + } + + if (ret == 0) { + if(wc_SetIssuerBuffer(&cert, der, derSz) != 0) + ret = -7406; + } + + if (ret == 0) { + if(wc_SetIssuerBuffer(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -7407; + } + + if (ret == 0) { + if(wc_SetIssuerRaw(&cert, der, derSz) != 0) + ret = -7408; + } + + if (ret == 0) { + if(wc_SetIssuerRaw(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -7409; + } + +#ifdef WOLFSSL_ALT_NAMES + if (ret == 0) { + if(wc_SetAltNamesBuffer(&cert, der, derSz) != 0) + ret = -7410; + } + + if (ret == 0) { + if(wc_SetAltNamesBuffer(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -7411; + } + + if (ret == 0) { + if(wc_SetDatesBuffer(&cert, der, derSz) != 0) + ret = -7412; + } + + if (ret == 0) { + if(wc_SetDatesBuffer(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -7413; + } +#endif + + if (ret == 0) { + if(wc_SetAuthKeyIdFromCert(&cert, der, derSz) != 0) + ret = -7414; + } + + if (ret == 0) { + if(wc_SetAuthKeyIdFromCert(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -7415; + } + + wc_SetCert_Free(&cert); + if (ret == 0) { + if(cert.decodedCert != NULL) + ret = -7416; + } + + XFREE(der, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif /* defined(WOLFSSL_CERT_GEN_CACHE) && defined(WOLFSSL_TEST_CERT) && + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) */ + +#define RSA_TEST_BYTES 512 /* up to 4096-bit key */ + +#if !defined(NO_ASN) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +static int rsa_flatten_test(RsaKey* key) +{ + int ret; + byte e[RSA_TEST_BYTES]; + byte n[RSA_TEST_BYTES]; + 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 -7417; + 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 -7418; + 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 -7419; + 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 -7420; + 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 -7421; + ret = wc_RsaFlattenPublicKey(key, e, &eSz, n, &nSz); + if (ret != 0) + return -7422; + 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) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + if (ret != 0) +#else + if (ret != RSA_BUFFER_E) +#endif + return -7423; + 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 -7424; + + return 0; +} +#endif /* NO_ASN */ + +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(NO_ASN) \ + && !defined(WOLFSSL_RSA_VERIFY_ONLY) +static int rsa_export_key_test(RsaKey* key) +{ + int ret; + byte e[3]; + word32 eSz = sizeof(e); + byte n[RSA_TEST_BYTES]; + word32 nSz = sizeof(n); + byte d[RSA_TEST_BYTES]; + word32 dSz = sizeof(d); + byte p[RSA_TEST_BYTES/2]; + word32 pSz = sizeof(p); + byte q[RSA_TEST_BYTES/2]; + word32 qSz = sizeof(q); + word32 zero = 0; + + ret = wc_RsaExportKey(NULL, e, &eSz, n, &nSz, d, &dSz, p, &pSz, q, &qSz); + if (ret != BAD_FUNC_ARG) + return -7425; + ret = wc_RsaExportKey(key, NULL, &eSz, n, &nSz, d, &dSz, p, &pSz, q, &qSz); + if (ret != BAD_FUNC_ARG) + return -7426; + ret = wc_RsaExportKey(key, e, NULL, n, &nSz, d, &dSz, p, &pSz, q, &qSz); + if (ret != BAD_FUNC_ARG) + return -7427; + ret = wc_RsaExportKey(key, e, &eSz, NULL, &nSz, d, &dSz, p, &pSz, q, &qSz); + if (ret != BAD_FUNC_ARG) + return -7428; + ret = wc_RsaExportKey(key, e, &eSz, n, NULL, d, &dSz, p, &pSz, q, &qSz); + if (ret != BAD_FUNC_ARG) + return -7429; + ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, NULL, &dSz, p, &pSz, q, &qSz); + if (ret != BAD_FUNC_ARG) + return -7430; + ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, d, NULL, p, &pSz, q, &qSz); + if (ret != BAD_FUNC_ARG) + return -7431; + ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, d, &dSz, NULL, &pSz, q, &qSz); + if (ret != BAD_FUNC_ARG) + return -7432; + ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, d, &dSz, p, NULL, q, &qSz); + if (ret != BAD_FUNC_ARG) + return -7433; + ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, d, &dSz, p, &pSz, NULL, &qSz); + if (ret != BAD_FUNC_ARG) + return -7434; + ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, d, &dSz, p, &pSz, q, NULL); + if (ret != BAD_FUNC_ARG) + return -7435; + + ret = wc_RsaExportKey(key, e, &zero, n, &nSz, d, &dSz, p, &pSz, q, &qSz); + if (ret != RSA_BUFFER_E) + return -7436; + ret = wc_RsaExportKey(key, e, &eSz, n, &zero, d, &dSz, p, &pSz, q, &qSz); + if (ret != RSA_BUFFER_E) + return -7437; +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, d, &zero, p, &pSz, q, &qSz); + if (ret != RSA_BUFFER_E) + return -7438; + ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, d, &dSz, p, &zero, q, &qSz); + if (ret != RSA_BUFFER_E) + return -7439; + ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, d, &dSz, p, &pSz, q, &zero); + if (ret != RSA_BUFFER_E) + return -7440; +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + + ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, d, &dSz, p, &pSz, q, &qSz); + if (ret != 0) + return -7441; + + return 0; +} +#endif /* !HAVE_FIPS && !USER_RSA && !NO_ASN */ + +#ifndef NO_SIG_WRAPPER +static int rsa_sig_test(RsaKey* key, word32 keyLen, int modLen, WC_RNG* rng) +{ + int ret; + word32 sigSz; + const byte in[] = "Everyone gets Friday off."; + const byte hash[] = { + 0xf2, 0x02, 0x95, 0x65, 0xcb, 0xf6, 0x2a, 0x59, + 0x39, 0x2c, 0x05, 0xff, 0x0e, 0x29, 0xaf, 0xfe, + 0x47, 0x33, 0x8c, 0x99, 0x8d, 0x58, 0x64, 0x83, + 0xa6, 0x58, 0x0a, 0x33, 0x0b, 0x84, 0x5f, 0x5f + }; + const byte hashEnc[] = { + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, + 0x00, 0x04, 0x20, + + 0xf2, 0x02, 0x95, 0x65, 0xcb, 0xf6, 0x2a, 0x59, + 0x39, 0x2c, 0x05, 0xff, 0x0e, 0x29, 0xaf, 0xfe, + 0x47, 0x33, 0x8c, 0x99, 0x8d, 0x58, 0x64, 0x83, + 0xa6, 0x58, 0x0a, 0x33, 0x0b, 0x84, 0x5f, 0x5f + }; + word32 inLen = (word32)XSTRLEN((char*)in); + byte out[RSA_TEST_BYTES]; + + /* Parameter Validation testing. */ + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_NONE, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -7442; + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_RSA, key, 0); + if (ret != BAD_FUNC_ARG) + return -7443; + + 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 -7444; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + 0, out, &sigSz, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -7445; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, NULL, &sigSz, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -7446; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, NULL, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -7447; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, NULL, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -7448; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, key, 0, rng); + if (ret != BAD_FUNC_ARG) + return -7449; + 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_AFALG_XILINX_RSA) + /* blinding / rng handled with hardware acceleration */ + if (ret != 0) +#elif defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + /* 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) +#elif defined(WOLFSSL_RSA_PUBLIC_ONLY) + if (ret != SIG_TYPE_E) +#elif defined(WOLFSSL_CRYPTOCELL) + /* RNG is handled with the cryptocell */ + if (ret != 0) +#else + if (ret != MISSING_RNG_E) +#endif + return -7450; + 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 -7451; + + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, NULL, + inLen, out, (word32)modLen, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -7452; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + 0, out, (word32)modLen, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -7453; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, NULL, (word32)modLen, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -7454; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, 0, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -7455; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, (word32)modLen, NULL, keyLen); + if (ret != BAD_FUNC_ARG) + return -7456; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, (word32)modLen, key, 0); + if (ret != BAD_FUNC_ARG) + return -7457; + +#ifndef HAVE_ECC + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_ECC, key, keyLen); + if (ret != SIG_TYPE_E) + return -7458; +#endif + + /* Use APIs. */ + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_RSA, key, keyLen); + if (ret != modLen) + return -7459; + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_RSA_W_ENC, key, keyLen); + if (ret != modLen) + return -7460; + + sigSz = (word32)ret; +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + XMEMSET(out, 0, sizeof(out)); + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, key, keyLen, rng); + if (ret != 0) + return -7461; + + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, (word32)modLen, key, keyLen); + if (ret != 0) + return -7462; + + sigSz = (word32)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 -7463; + + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA_W_ENC, + in, inLen, out, (word32)modLen, key, keyLen); + if (ret != 0) + return -7464; + + /* 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 -7465; + + /* check hash functions */ + sigSz = (word32)sizeof(out); + ret = wc_SignatureGenerateHash(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, + hash, (int)sizeof(hash), out, &sigSz, key, keyLen, rng); + if (ret != 0) + return -7466; + + ret = wc_SignatureVerifyHash(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, + hash, (int)sizeof(hash), out, (word32)modLen, key, keyLen); + if (ret != 0) + return -7467; + + sigSz = (word32)sizeof(out); + ret = wc_SignatureGenerateHash(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA_W_ENC, + hashEnc, (int)sizeof(hashEnc), out, &sigSz, key, keyLen, rng); + if (ret != 0) + return -7468; + + ret = wc_SignatureVerifyHash(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA_W_ENC, + hashEnc, (int)sizeof(hashEnc), out, (word32)modLen, key, keyLen); + if (ret != 0) + return -7469; +#else + (void)hash; + (void)hashEnc; +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + + return 0; +} +#endif /* !NO_SIG_WRAPPER */ + +#ifdef WC_RSA_NONBLOCK +static int rsa_nb_test(RsaKey* key, const byte* in, word32 inLen, byte* out, + word32 outSz, byte* plain, word32 plainSz, WC_RNG* rng) +{ + int ret = 0, count; + int signSz = 0; + RsaNb nb; + byte* inlinePlain = NULL; + + /* Enable non-blocking RSA mode - provide context */ + ret = wc_RsaSetNonBlock(key, &nb); + if (ret != 0) + return ret; + +#ifdef WC_RSA_NONBLOCK_TIME + /* Enable time based RSA blocking. 8 microseconds max (3.1GHz) */ + ret = wc_RsaSetNonBlockTime(key, 8, 3100); + if (ret != 0) + return ret; +#endif + + count = 0; + do { + ret = wc_RsaSSL_Sign(in, inLen, out, outSz, key, rng); + count++; /* track number of would blocks */ + if (ret == FP_WOULDBLOCK) { + /* do "other" work here */ + } + } while (ret == FP_WOULDBLOCK); + if (ret < 0) { + return ret; + } +#ifdef DEBUG_WOLFSSL + printf("RSA non-block sign: %d times\n", count); +#endif + signSz = ret; + + /* Test non-blocking verify */ + XMEMSET(plain, 0, plainSz); + count = 0; + do { + ret = wc_RsaSSL_Verify(out, (word32)signSz, plain, plainSz, key); + count++; /* track number of would blocks */ + if (ret == FP_WOULDBLOCK) { + /* do "other" work here */ + } + } while (ret == FP_WOULDBLOCK); + if (ret < 0) { + return ret; + } +#ifdef DEBUG_WOLFSSL + printf("RSA non-block verify: %d times\n", count); +#endif + + if (signSz == ret && XMEMCMP(plain, in, (size_t)ret)) { + return SIG_VERIFY_E; + } + + /* Test inline non-blocking verify */ + count = 0; + do { + ret = wc_RsaSSL_VerifyInline(out, (word32)signSz, &inlinePlain, key); + count++; /* track number of would blocks */ + if (ret == FP_WOULDBLOCK) { + /* do "other" work here */ + } + } while (ret == FP_WOULDBLOCK); + if (ret < 0) { + return ret; + } +#ifdef DEBUG_WOLFSSL + printf("RSA non-block inline verify: %d times\n", count); +#endif + + if (signSz == ret && XMEMCMP(inlinePlain, in, (size_t)ret)) { + return SIG_VERIFY_E; + } + + /* Disabling non-block RSA mode */ + ret = wc_RsaSetNonBlock(key, NULL); + + (void)count; + + return 0; +} +#endif + +#if !defined(HAVE_USER_RSA) && !defined(NO_ASN) +static int rsa_decode_test(RsaKey* keyPub) +{ + int ret; + word32 inSz; + word32 inOutIdx; + static const byte n[2] = { 0x00, 0x23 }; + static const byte e[2] = { 0x00, 0x03 }; + static const byte good[] = { 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, + 0x03 }; + static const byte goodAlgId[] = { 0x30, 0x0f, 0x30, 0x0d, 0x06, 0x00, + 0x03, 0x09, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + static const byte goodAlgIdNull[] = { 0x30, 0x11, 0x30, 0x0f, 0x06, 0x00, + 0x05, 0x00, 0x03, 0x09, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, + 0x02, 0x1, 0x03 }; + static const byte badAlgIdNull[] = { 0x30, 0x12, 0x30, 0x10, 0x06, 0x00, + 0x05, 0x01, 0x00, 0x03, 0x09, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, + 0x02, 0x1, 0x03 }; + static const byte badNotBitString[] = { 0x30, 0x0f, 0x30, 0x0d, 0x06, 0x00, + 0x04, 0x09, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + static const byte badBitStringLen[] = { 0x30, 0x0f, 0x30, 0x0d, 0x06, 0x00, + 0x03, 0x0a, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + static const byte badNoSeq[] = { 0x30, 0x0d, 0x30, 0x0b, 0x06, 0x00, 0x03, + 0x07, 0x00, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + static const byte badNoObj[] = { + 0x30, 0x0f, 0x30, 0x0d, 0x05, 0x00, 0x03, 0x09, 0x00, 0x30, 0x06, + 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + static const byte badIntN[] = { 0x30, 0x06, 0x02, 0x05, 0x23, 0x02, 0x1, + 0x03 }; + static const byte badNotIntE[] = { 0x30, 0x06, 0x02, 0x01, 0x23, 0x04, 0x1, + 0x03 }; + static const byte badLength[] = { 0x30, 0x04, 0x02, 0x01, 0x23, 0x02, 0x1, + 0x03 }; + static 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 -7470; + + /* Parameter Validation testing. */ + ret = wc_RsaPublicKeyDecodeRaw(NULL, sizeof(n), e, sizeof(e), keyPub); + if (ret != BAD_FUNC_ARG) { + ret = -7471; + goto done; + } + ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), NULL, sizeof(e), keyPub); + if (ret != BAD_FUNC_ARG) { + ret = -7472; + goto done; + } + ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), e, sizeof(e), NULL); + if (ret != BAD_FUNC_ARG) { + ret = -7473; + goto done; + } + /* TODO: probably should fail when length is -1! */ + ret = wc_RsaPublicKeyDecodeRaw(n, (word32)-1, e, sizeof(e), keyPub); + if (ret != 0) { + ret = -7474; + goto done; + } + wc_FreeRsaKey(keyPub); + ret = wc_InitRsaKey(keyPub, NULL); + if (ret != 0) + return -7475; + ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), e, (word32)-1, keyPub); + if (ret != 0) { + ret = -7476; + goto done; + } + wc_FreeRsaKey(keyPub); + ret = wc_InitRsaKey(keyPub, NULL); + if (ret != 0) + return -7477; + + /* Use API. */ + ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), e, sizeof(e), keyPub); + if (ret != 0) { + ret = -7478; + goto done; + } + wc_FreeRsaKey(keyPub); + ret = wc_InitRsaKey(keyPub, NULL); + if (ret != 0) + return -7479; + + /* Parameter Validation testing. */ + inSz = sizeof(good); + ret = wc_RsaPublicKeyDecode(NULL, &inOutIdx, keyPub, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -7480; + goto done; + } + ret = wc_RsaPublicKeyDecode(good, NULL, keyPub, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -7481; + goto done; + } + ret = wc_RsaPublicKeyDecode(good, &inOutIdx, NULL, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -7482; + goto done; + } + + /* Use good data and offset to bad data. */ + inOutIdx = 2; + inSz = sizeof(good) - inOutIdx; + ret = wc_RsaPublicKeyDecode(good, &inOutIdx, keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -7483; + goto done; + } + inOutIdx = 2; + inSz = sizeof(goodAlgId) - inOutIdx; + ret = wc_RsaPublicKeyDecode(goodAlgId, &inOutIdx, keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -7484; + goto done; + } + inOutIdx = 2; + inSz = sizeof(goodAlgId); + ret = wc_RsaPublicKeyDecode(goodAlgId, &inOutIdx, keyPub, inSz); +#ifndef WOLFSSL_NO_DECODE_EXTRA + if (ret != ASN_PARSE_E) +#else + if (ret != ASN_RSA_KEY_E) +#endif + { + ret = -7485; + 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 = -7486; + goto done; + } + inSz = sizeof(badNotBitString); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badNotBitString, &inOutIdx, keyPub, inSz); + if (ret != ASN_BITSTR_E) { + ret = -7487; + goto done; + } + inSz = sizeof(badBitStringLen); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badBitStringLen, &inOutIdx, keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -7488; + goto done; + } + inSz = sizeof(badNoSeq); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badNoSeq, &inOutIdx, keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -7489; + goto done; + } + inSz = sizeof(badNoObj); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badNoObj, &inOutIdx, keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -7490; + goto done; + } + inSz = sizeof(badIntN); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badIntN, &inOutIdx, keyPub, inSz); + if (ret != ASN_RSA_KEY_E) { + ret = -7491; + goto done; + } + inSz = sizeof(badNotIntE); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badNotIntE, &inOutIdx, keyPub, inSz); + if (ret != ASN_RSA_KEY_E) { + ret = -7492; + 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 = -7493; + goto done; + } + /* TODO: Shouldn't ignore object id's data. */ + wc_FreeRsaKey(keyPub); + ret = wc_InitRsaKey(keyPub, NULL); + if (ret != 0) + return -7494; + + inSz = sizeof(badBitStrNoZero); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badBitStrNoZero, &inOutIdx, keyPub, inSz); + if (ret != ASN_EXPECT_0_E) { + ret = -7495; + goto done; + } + wc_FreeRsaKey(keyPub); + ret = wc_InitRsaKey(keyPub, NULL); + if (ret != 0) + return -7496; + + /* Valid data cases. */ + inSz = sizeof(good); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(good, &inOutIdx, keyPub, inSz); + if (ret != 0) { + ret = -7497; + goto done; + } + if (inOutIdx != inSz) { + ret = -7498; + goto done; + } + wc_FreeRsaKey(keyPub); + ret = wc_InitRsaKey(keyPub, NULL); + if (ret != 0) + return -7499; + + inSz = sizeof(goodAlgId); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(goodAlgId, &inOutIdx, keyPub, inSz); + if (ret != 0) { + ret = -7500; + goto done; + } + if (inOutIdx != inSz) { + ret = -7501; + goto done; + } + wc_FreeRsaKey(keyPub); + ret = wc_InitRsaKey(keyPub, NULL); + if (ret != 0) + return -7502; + + inSz = sizeof(goodAlgIdNull); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(goodAlgIdNull, &inOutIdx, keyPub, inSz); + if (ret != 0) { + ret = -7503; + goto done; + } + if (inOutIdx != inSz) { + ret = -7504; + goto done; + } + +done: + wc_FreeRsaKey(keyPub); + return ret; +} +#endif + +#ifdef WC_RSA_PSS +static int rsa_pss_test(WC_RNG* rng, RsaKey* key) +{ + byte digest[WC_MAX_DIGEST_SIZE]; + int ret = 0; + const char* inStr = "Everyone gets Friday off."; + word32 inLen = (word32)XSTRLEN((char*)inStr); + word32 outSz; + word32 plainSz; + word32 digestSz; + int i, j; +#ifdef RSA_PSS_TEST_WRONG_PARAMS + int k, l; +#endif + int len; + byte* plain; + int mgf[] = { +#ifndef NO_SHA + WC_MGF1SHA1, +#endif +#ifdef WOLFSSL_SHA224 + WC_MGF1SHA224, +#endif + WC_MGF1SHA256, +#ifdef WOLFSSL_SHA384 + WC_MGF1SHA384, +#endif +#ifdef WOLFSSL_SHA512 + WC_MGF1SHA512 +#endif + }; + enum wc_HashType hash[] = { +#ifndef NO_SHA + WC_HASH_TYPE_SHA, +#endif +#ifdef WOLFSSL_SHA224 + WC_HASH_TYPE_SHA224, +#endif + WC_HASH_TYPE_SHA256, +#ifdef WOLFSSL_SHA384 + WC_HASH_TYPE_SHA384, +#endif +#ifdef WOLFSSL_SHA512 + WC_HASH_TYPE_SHA512, +#endif + }; + + DECLARE_VAR_INIT(in, byte, inLen, inStr, HEAP_HINT); + DECLARE_VAR(out, byte, RSA_TEST_BYTES, HEAP_HINT); + DECLARE_VAR(sig, byte, RSA_TEST_BYTES, HEAP_HINT); + + /* Test all combinations of hash and MGF. */ + for (j = 0; j < (int)(sizeof(hash)/sizeof(*hash)); j++) { + /* Calculate hash of message. */ + ret = wc_Hash(hash[j], in, inLen, digest, sizeof(digest)); + if (ret != 0) + ERROR_OUT(-7505, exit_rsa_pss); + digestSz = wc_HashGetDigestSize(hash[j]); + + for (i = 0; i < (int)(sizeof(mgf)/sizeof(*mgf)); i++) { + outSz = RSA_TEST_BYTES; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPSS_Sign_ex(digest, digestSz, out, outSz, + hash[j], mgf[i], -1, key, rng); + } + } while (ret == WC_PENDING_E); + if (ret <= 0) + ERROR_OUT(-7506, exit_rsa_pss); + outSz = ret; + + XMEMCPY(sig, out, outSz); + plain = NULL; + TEST_SLEEP(); + + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPSS_VerifyInline_ex(sig, outSz, &plain, hash[j], + mgf[i], -1, key); + } + } while (ret == WC_PENDING_E); + if (ret <= 0) + ERROR_OUT(-7507, exit_rsa_pss); + plainSz = ret; + TEST_SLEEP(); + +#ifdef HAVE_SELFTEST + ret = wc_RsaPSS_CheckPadding_ex(digest, digestSz, plain, plainSz, + hash[j], -1); +#else + ret = wc_RsaPSS_CheckPadding_ex(digest, digestSz, plain, plainSz, + hash[j], -1, wc_RsaEncryptSize(key)*8); +#endif + if (ret != 0) + ERROR_OUT(-7508, exit_rsa_pss); + +#ifdef RSA_PSS_TEST_WRONG_PARAMS + for (k = 0; k < (int)(sizeof(mgf)/sizeof(*mgf)); k++) { + for (l = 0; l < (int)(sizeof(hash)/sizeof(*hash)); l++) { + if (i == k && j == l) + continue; + + XMEMCPY(sig, out, outSz); + + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPSS_VerifyInline_ex(sig, outSz, + (byte**)&plain, hash[l], mgf[k], -1, key); + } + } while (ret == WC_PENDING_E); + if (ret >= 0) + ERROR_OUT(-7509, exit_rsa_pss); + } + } +#endif + } + } + + /* Test that a salt length of zero works. */ + digestSz = wc_HashGetDigestSize(hash[0]); + outSz = RSA_TEST_BYTES; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPSS_Sign_ex(digest, digestSz, out, outSz, hash[0], + mgf[0], 0, key, rng); + } + } while (ret == WC_PENDING_E); + if (ret <= 0) + ERROR_OUT(-7510, exit_rsa_pss); + outSz = ret; + TEST_SLEEP(); + + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPSS_Verify_ex(out, outSz, sig, outSz, hash[0], mgf[0], + 0, key); + } + } while (ret == WC_PENDING_E); + if (ret <= 0) + ERROR_OUT(-7511, exit_rsa_pss); + plainSz = ret; + TEST_SLEEP(); + + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { +#ifdef HAVE_SELFTEST + ret = wc_RsaPSS_CheckPadding_ex(digest, digestSz, sig, plainSz, + hash[0], 0); +#else + ret = wc_RsaPSS_CheckPadding_ex(digest, digestSz, sig, plainSz, + hash[0], 0, 0); +#endif + } + } while (ret == WC_PENDING_E); + if (ret != 0) + ERROR_OUT(-7512, exit_rsa_pss); + + XMEMCPY(sig, out, outSz); + plain = NULL; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPSS_VerifyInline_ex(sig, outSz, &plain, hash[0], mgf[0], + 0, key); + } + } while (ret == WC_PENDING_E); + if (ret <= 0) + ERROR_OUT(-7513, exit_rsa_pss); + plainSz = ret; + TEST_SLEEP(); + +#ifdef HAVE_SELFTEST + ret = wc_RsaPSS_CheckPadding_ex(digest, digestSz, plain, plainSz, hash[0], + 0); +#else + ret = wc_RsaPSS_CheckPadding_ex(digest, digestSz, plain, plainSz, hash[0], + 0, 0); +#endif + if (ret != 0) + ERROR_OUT(-7514, exit_rsa_pss); + + /* Test bad salt lengths in various APIs. */ + digestSz = wc_HashGetDigestSize(hash[0]); + outSz = RSA_TEST_BYTES; +#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER + len = -2; +#else + len = -3; +#endif + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPSS_Sign_ex(digest, digestSz, out, outSz, hash[0], + mgf[0], len, key, rng); + } + } while (ret == WC_PENDING_E); + if (ret != PSS_SALTLEN_E) + ERROR_OUT(-7515, exit_rsa_pss); + + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPSS_Sign_ex(digest, digestSz, out, outSz, hash[0], + mgf[0], digestSz + 1, key, rng); + } + } while (ret == WC_PENDING_E); + if (ret != PSS_SALTLEN_E) + ERROR_OUT(-7516, exit_rsa_pss); + TEST_SLEEP(); + + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPSS_VerifyInline_ex(sig, outSz, &plain, hash[0], + mgf[0], -2, key); + } + } while (ret == WC_PENDING_E); + if (ret != PSS_SALTLEN_E) + ERROR_OUT(-7517, exit_rsa_pss); + TEST_SLEEP(); + + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPSS_VerifyInline_ex(sig, outSz, &plain, hash[0], mgf[0], + digestSz + 1, key); + } + } while (ret == WC_PENDING_E); + if (ret != PSS_SALTLEN_E) + ERROR_OUT(-7518, exit_rsa_pss); + TEST_SLEEP(); + +#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER + len = -2; +#else + len = -3; +#endif +#ifdef HAVE_SELFTEST + ret = wc_RsaPSS_CheckPadding_ex(digest, digestSz, plain, plainSz, hash[0], + len); +#else + ret = wc_RsaPSS_CheckPadding_ex(digest, digestSz, plain, plainSz, hash[0], + len, 0); +#endif + if (ret != PSS_SALTLEN_E) + ERROR_OUT(-7519, exit_rsa_pss); +#ifndef WOLFSSL_PSS_LONG_SALT + len = digestSz + 1; +#else + len = plainSz - digestSz - 1; +#endif +#ifdef HAVE_SELFTEST + ret = wc_RsaPSS_CheckPadding_ex(digest, digestSz, plain, plainSz, hash[0], + len); +#else + ret = wc_RsaPSS_CheckPadding_ex(digest, digestSz, plain, plainSz, hash[0], + len, 0); +#endif + if (ret != PSS_SALTLEN_E) + ERROR_OUT(-7520, exit_rsa_pss); + + ret = 0; +exit_rsa_pss: + FREE_VAR(sig, HEAP_HINT); + FREE_VAR(in, HEAP_HINT); + FREE_VAR(out, HEAP_HINT); + + return ret; +} +#endif + +#ifdef WC_RSA_NO_PADDING +int rsa_no_pad_test(void) +{ + WC_RNG rng; + RsaKey key; + byte* tmp; + size_t bytes; + int ret; + word32 inLen = 0; + word32 idx = 0; + word32 outSz = RSA_TEST_BYTES; + word32 plainSz = RSA_TEST_BYTES; +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ + !defined(USE_CERT_BUFFERS_3072) && !defined(USE_CERT_BUFFERS_4096) && \ + !defined(NO_FILESYSTEM) + XFILE file; +#endif + DECLARE_VAR(out, byte, RSA_TEST_BYTES, HEAP_HINT); + DECLARE_VAR(plain, byte, RSA_TEST_BYTES, HEAP_HINT); + + /* initialize stack structures */ + XMEMSET(&rng, 0, sizeof(rng)); + XMEMSET(&key, 0, sizeof(key)); +#ifdef USE_CERT_BUFFERS_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) + 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 + 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 + ) { + ERROR_OUT(-7600, exit_rsa_nopadding); + } + +#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(USE_CERT_BUFFERS_3072) + XMEMCPY(tmp, client_key_der_3072, (size_t)sizeof_client_key_der_3072); +#elif defined(USE_CERT_BUFFERS_4096) + XMEMCPY(tmp, client_key_der_4096, (size_t)sizeof_client_key_der_4096); +#elif !defined(NO_FILESYSTEM) + file = XFOPEN(clientKey, "rb"); + if (!file) { + err_sys("can't open ./certs/client-key.der, " + "Please run from wolfSSL home dir", -40); + ERROR_OUT(-7601, exit_rsa_nopadding); + } + + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); +#else + /* No key to use. */ + ERROR_OUT(-7602, exit_rsa_nopadding); +#endif /* USE_CERT_BUFFERS */ + + ret = wc_InitRsaKey_ex(&key, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-7603, exit_rsa_nopadding); + } + ret = wc_RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes); + if (ret != 0) { + ERROR_OUT(-7604, exit_rsa_nopadding); + } + + /* after loading in key use tmp as the test buffer */ + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) { + ERROR_OUT(-7605, exit_rsa_nopadding); + } + +#ifndef WOLFSSL_RSA_VERIFY_ONLY + inLen = wc_RsaEncryptSize(&key); + outSz = inLen; + plainSz = inLen; + XMEMSET(tmp, 7, inLen); + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaDirect(tmp, inLen, out, &outSz, &key, + RSA_PRIVATE_ENCRYPT, &rng); + } + } while (ret == WC_PENDING_E); + if (ret <= 0) { + ERROR_OUT(-7606, exit_rsa_nopadding); + } + + /* encrypted result should not be the same as input */ + if (XMEMCMP(out, tmp, inLen) == 0) { + ERROR_OUT(-7607, exit_rsa_nopadding); + } + TEST_SLEEP(); + + /* decrypt with public key and compare result */ + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaDirect(out, outSz, plain, &plainSz, &key, + RSA_PUBLIC_DECRYPT, &rng); + } + } while (ret == WC_PENDING_E); + if (ret <= 0) { + ERROR_OUT(-7608, exit_rsa_nopadding); + } + + if (XMEMCMP(plain, tmp, inLen) != 0) { + ERROR_OUT(-7609, exit_rsa_nopadding); + } + TEST_SLEEP(); +#endif + +#ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(NULL, &rng); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-7610, exit_rsa_nopadding); + } + + ret = wc_RsaSetRNG(&key, &rng); + if (ret < 0) { + ERROR_OUT(-7611, exit_rsa_nopadding); + } +#endif + + /* test encrypt and decrypt using WC_RSA_NO_PAD */ +#ifndef WOLFSSL_RSA_VERIFY_ONLY + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPublicEncrypt_ex(tmp, inLen, out, (int)outSz, &key, &rng, + WC_RSA_NO_PAD, WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0); + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-7612, exit_rsa_nopadding); + } + TEST_SLEEP(); +#endif /* WOLFSSL_RSA_VERIFY_ONLY */ + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPrivateDecrypt_ex(out, outSz, plain, (int)plainSz, &key, + WC_RSA_NO_PAD, WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0); + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-7613, exit_rsa_nopadding); + } + + if (XMEMCMP(plain, tmp, inLen) != 0) { + ERROR_OUT(-7614, exit_rsa_nopadding); + } + TEST_SLEEP(); +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + + /* test some bad arguments */ + ret = wc_RsaDirect(out, outSz, plain, &plainSz, &key, -1, + &rng); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-7615, exit_rsa_nopadding); + } + + ret = wc_RsaDirect(out, outSz, plain, &plainSz, NULL, RSA_PUBLIC_DECRYPT, + &rng); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-7616, exit_rsa_nopadding); + } + + ret = wc_RsaDirect(out, outSz, NULL, &plainSz, &key, RSA_PUBLIC_DECRYPT, + &rng); + if (ret != LENGTH_ONLY_E || plainSz != inLen) { + ERROR_OUT(-7617, exit_rsa_nopadding); + } + + ret = wc_RsaDirect(out, outSz - 10, plain, &plainSz, &key, + RSA_PUBLIC_DECRYPT, &rng); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-7618, exit_rsa_nopadding); + } + + /* if making it to this point of code without hitting an ERROR_OUT then + * all tests have passed */ + ret = 0; + +exit_rsa_nopadding: + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + FREE_VAR(out, HEAP_HINT); + FREE_VAR(plain, HEAP_HINT); + wc_FreeRsaKey(&key); + wc_FreeRng(&rng); + + return ret; +} +#endif /* WC_RSA_NO_PADDING */ + +#ifdef WOLFSSL_CERT_GEN +static int rsa_certgen_test(RsaKey* key, RsaKey* keypub, WC_RNG* rng, byte* tmp) +{ + RsaKey caKey; + byte* der; + byte* pem = NULL; + int ret; + Cert* myCert = NULL; + int certSz; + size_t bytes3; + word32 idx3 = 0; +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) + XFILE file3; +#endif +#ifdef WOLFSSL_TEST_CERT + DecodedCert decode; +#endif +#if defined(WOLFSSL_ALT_NAMES) && !defined(NO_ASN_TIME) + struct tm beforeTime; + struct tm afterTime; +#endif + const byte mySerial[8] = {1,2,3,4,5,6,7,8}; + + (void)keypub; + + XMEMSET(&caKey, 0, sizeof(caKey)); + + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-7619, exit_rsa); + } + pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + ERROR_OUT(-7620, exit_rsa); + } + myCert = (Cert*)XMALLOC(sizeof(Cert), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (myCert == NULL) { + ERROR_OUT(-7621, exit_rsa); + } + + /* self signed */ + if (wc_InitCert(myCert)) { + ERROR_OUT(-7622, exit_rsa); + } + + 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 + /* add Policies */ + XSTRNCPY(myCert->certPolicies[0], "2.16.840.1.101.3.4.1.42", + CTC_MAX_CERTPOL_SZ); + 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) { + ERROR_OUT(-7623, exit_rsa); + } + + /* add AKID from the Public Key */ + if (wc_SetAuthKeyIdFromPublicKey(myCert, keypub, NULL) != 0) { + ERROR_OUT(-7624, exit_rsa); + } + + /* add Key Usage */ + if (wc_SetKeyUsage(myCert,"cRLSign,keyCertSign") != 0) { + ERROR_OUT(-7625, exit_rsa); + } +#ifdef WOLFSSL_EKU_OID + { + const char unique[] = "2.16.840.1.111111.100.1.10.1"; + if (wc_SetExtKeyUsageOID(myCert, unique, sizeof(unique), 0, + HEAP_HINT) != 0) { + ERROR_OUT(-7626, exit_rsa); + } + } +#endif /* WOLFSSL_EKU_OID */ +#endif /* WOLFSSL_CERT_EXT */ + + 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(-7627, exit_rsa); + } + certSz = ret; + +#ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, HEAP_HINT); + ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) { + FreeDecodedCert(&decode); + ERROR_OUT(-7628, exit_rsa); + } + FreeDecodedCert(&decode); +#endif + + ret = SaveDerAndPem(der, certSz, pem, FOURK_BUF, certDerFile, + certPemFile, CERT_TYPE, -5578); + if (ret != 0) { + goto exit_rsa; + } + + /* Setup Certificate */ + if (wc_InitCert(myCert)) { + ERROR_OUT(-7629, exit_rsa); + } + +#ifdef WOLFSSL_ALT_NAMES + /* Get CA Cert for testing */ + #ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(tmp, ca_cert_der_1024, sizeof_ca_cert_der_1024); + bytes3 = sizeof_ca_cert_der_1024; + #elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(tmp, ca_cert_der_2048, sizeof_ca_cert_der_2048); + bytes3 = sizeof_ca_cert_der_2048; + #else + file3 = XFOPEN(rsaCaCertDerFile, "rb"); + if (!file3) { + ERROR_OUT(-7630, exit_rsa); + } + bytes3 = XFREAD(tmp, 1, FOURK_BUF, file3); + XFCLOSE(file3); + #endif /* USE_CERT_BUFFERS */ + + #if !defined(NO_FILESYSTEM) && !defined(USE_CERT_BUFFERS_1024) && \ + !defined(USE_CERT_BUFFERS_2048) && !defined(NO_ASN) + ret = wc_SetAltNames(myCert, rsaCaCertFile); + if (ret != 0) { + ERROR_OUT(-7631, exit_rsa); + } + #endif + /* get alt names from der */ + ret = wc_SetAltNamesBuffer(myCert, tmp, (int)bytes3); + if (ret != 0) { + ERROR_OUT(-7632, exit_rsa); + } + + /* get dates from der */ + ret = wc_SetDatesBuffer(myCert, tmp, (int)bytes3); + if (ret != 0) { + ERROR_OUT(-7633, exit_rsa); + } + + #ifndef NO_ASN_TIME + ret = wc_GetCertDates(myCert, &beforeTime, &afterTime); + if (ret < 0) { + ERROR_OUT(-7634, exit_rsa); + } + #endif +#endif /* WOLFSSL_ALT_NAMES */ + + /* 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 = XFOPEN(rsaCaKeyFile, "rb"); + if (!file3) { + ERROR_OUT(-7635, exit_rsa); + } + + bytes3 = XFREAD(tmp, 1, FOURK_BUF, file3); + XFCLOSE(file3); +#endif /* USE_CERT_BUFFERS */ + + ret = wc_InitRsaKey(&caKey, HEAP_HINT); + if (ret != 0) { + ERROR_OUT(-7636, exit_rsa); + } + ret = wc_RsaPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes3); + if (ret != 0) { + ERROR_OUT(-7637, 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.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) { + ERROR_OUT(-7638, exit_rsa); + } + + /* 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(-7639, exit_rsa); + } + + /* add Key Usage */ + if (wc_SetKeyUsage(myCert,"keyEncipherment,keyAgreement") != 0) { + ERROR_OUT(-7640, exit_rsa); + } +#endif /* WOLFSSL_CERT_EXT */ + +#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) { + ERROR_OUT(-7641, exit_rsa); + } + + certSz = wc_MakeCert(myCert, der, FOURK_BUF, key, NULL, rng); + if (certSz < 0) { + ERROR_OUT(-7642, exit_rsa); + } + + 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); + if (ret < 0) { + ERROR_OUT(-7643, exit_rsa); + } + certSz = ret; + +#ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, HEAP_HINT); + ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) { + FreeDecodedCert(&decode); + ERROR_OUT(-7644, exit_rsa); + } + FreeDecodedCert(&decode); +#endif + + ret = SaveDerAndPem(der, certSz, pem, FOURK_BUF, otherCertDerFile, + otherCertPemFile, CERT_TYPE, -5598); + if (ret != 0) { + goto exit_rsa; + } + +exit_rsa: + wc_FreeRsaKey(&caKey); + + XFREE(myCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif + +#if !defined(NO_RSA) && defined(HAVE_ECC) && defined(WOLFSSL_CERT_GEN) +/* Make Cert / Sign example for ECC cert and RSA CA */ +static int rsa_ecc_certgen_test(WC_RNG* rng, byte* tmp) +{ + RsaKey caKey; + ecc_key caEccKey; + ecc_key caEccKeyPub; + byte* der; + byte* pem = NULL; + Cert* myCert = NULL; + int certSz; + size_t bytes3; + word32 idx3 = 0; +#if (!defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048)) \ + || !defined(USE_CERT_BUFFERS_256) + XFILE file3; +#endif +#ifdef WOLFSSL_TEST_CERT + DecodedCert decode; +#endif + int ret; + + XMEMSET(&caKey, 0, sizeof(caKey)); + XMEMSET(&caEccKey, 0, sizeof(caEccKey)); + XMEMSET(&caEccKeyPub, 0, sizeof(caEccKeyPub)); + + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-7645, exit_rsa); + } + pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + ERROR_OUT(-7646, exit_rsa); + } + myCert = (Cert*)XMALLOC(sizeof(Cert), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (myCert == NULL) { + ERROR_OUT(-7647, exit_rsa); + } + + /* 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 = XFOPEN(rsaCaKeyFile, "rb"); + if (!file3) { + ERROR_OUT(-7648, exit_rsa); + } + + bytes3 = XFREAD(tmp, 1, FOURK_BUF, file3); + XFCLOSE(file3); +#endif /* USE_CERT_BUFFERS */ + + ret = wc_InitRsaKey(&caKey, HEAP_HINT); + if (ret != 0) { + ERROR_OUT(-7649, exit_rsa); + } + ret = wc_RsaPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes3); + if (ret != 0) { + ERROR_OUT(-7650, exit_rsa); + } + + /* 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 = XFOPEN(eccKeyPubFile, "rb"); + if (!file3) { + ERROR_OUT(-7651, exit_rsa); + } + + bytes3 = XFREAD(tmp, 1, FOURK_BUF, file3); + XFCLOSE(file3); +#endif + + ret = wc_ecc_init_ex(&caEccKeyPub, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-7652, exit_rsa); + } + + idx3 = 0; + ret = wc_EccPublicKeyDecode(tmp, &idx3, &caEccKeyPub, (word32)bytes3); + if (ret != 0) { + ERROR_OUT(-7653, exit_rsa); + } + + /* Setup Certificate */ + if (wc_InitCert(myCert)) { + ERROR_OUT(-7654, 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, NULL, &caEccKeyPub) != 0) { + ERROR_OUT(-7655, exit_rsa); + } + + /* 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(-7656, exit_rsa); + } + + /* add Key Usage */ + if (wc_SetKeyUsage(myCert, certKeyUsage) != 0) { + ERROR_OUT(-7657, exit_rsa); + } +#endif /* WOLFSSL_CERT_EXT */ + +#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) { + ERROR_OUT(-7658, exit_rsa); + } + + certSz = wc_MakeCert(myCert, der, FOURK_BUF, NULL, &caEccKeyPub, rng); + if (certSz < 0) { + ERROR_OUT(-7659, exit_rsa); + } + + 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(-7660, exit_rsa); + } + 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(-7661, exit_rsa); + + } + FreeDecodedCert(&decode); +#endif + + ret = SaveDerAndPem(der, certSz, pem, FOURK_BUF, certEccRsaDerFile, + certEccRsaPemFile, CERT_TYPE, -5616); + if (ret != 0) { + goto exit_rsa; + } + +exit_rsa: + wc_FreeRsaKey(&caKey); + wc_ecc_free(&caEccKey); + wc_ecc_free(&caEccKeyPub); + + XFREE(myCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + myCert = NULL; + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pem = NULL; + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; + + if (ret >= 0) + ret = 0; + return ret; +} +#endif /* !NO_RSA && HAVE_ECC && WOLFSSL_CERT_GEN */ + +#ifdef WOLFSSL_KEY_GEN +static int rsa_keygen_test(WC_RNG* rng) +{ + RsaKey genKey; + int ret; + byte* der = NULL; + byte* pem = NULL; + word32 idx = 0; + int derSz = 0; +#if !defined(WOLFSSL_SP_MATH) && !defined(HAVE_FIPS) + int keySz = 1024; +#else + int keySz = 2048; +#endif + + XMEMSET(&genKey, 0, sizeof(genKey)); + + ret = wc_InitRsaKey_ex(&genKey, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-7662, exit_rsa); + } + + ret = wc_MakeRsaKey(&genKey, keySz, WC_RSA_EXPONENT, rng); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &genKey.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ERROR_OUT(-7663, exit_rsa); + } + TEST_SLEEP(); + + /* If not using old FIPS, or not using FAST or USER RSA... */ + #if !defined(HAVE_FAST_RSA) && !defined(HAVE_USER_RSA) && \ + (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) && \ + !defined(HAVE_SELFTEST) && !defined(HAVE_INTEL_QA) + ret = wc_CheckRsaKey(&genKey); + if (ret != 0) { + ERROR_OUT(-7664, exit_rsa); + } + #endif + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-7665, exit_rsa); + } + pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + ERROR_OUT(-7666, exit_rsa); + } + + derSz = wc_RsaKeyToDer(&genKey, der, FOURK_BUF); + if (derSz < 0) { + ERROR_OUT(-7667, exit_rsa); + } + + ret = SaveDerAndPem(der, derSz, pem, FOURK_BUF, keyDerFile, keyPemFile, + PRIVATEKEY_TYPE, -5555); + if (ret != 0) { + goto exit_rsa; + } + + wc_FreeRsaKey(&genKey); + ret = wc_InitRsaKey(&genKey, HEAP_HINT); + if (ret != 0) { + ERROR_OUT(-7668, exit_rsa); + } + idx = 0; +#if !defined(WOLFSSL_CRYPTOCELL) + /* The private key part of the key gen pairs from cryptocell can't be exported */ + ret = wc_RsaPrivateKeyDecode(der, &idx, &genKey, derSz); + if (ret != 0) { + ERROR_OUT(-7669, exit_rsa); + } +#endif /* WOLFSSL_CRYPTOCELL */ + +exit_rsa: + wc_FreeRsaKey(&genKey); + if (pem != NULL) { + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pem = NULL; + } + if (der != NULL) { + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; + } + + return ret; +} +#endif int rsa_test(void) { - byte* tmp; - size_t bytes; - RsaKey key; - RNG rng; - word32 idx = 0; int ret; - byte in[] = "Everyone gets Friday off."; - word32 inLen = (word32)strlen((char*)in); - byte out[256]; - byte plain[256]; -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) - FILE* file, * file2; + byte* tmp; + byte* der = NULL; + byte* pem = NULL; + size_t bytes; + WC_RNG rng; + RsaKey key; +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_CERT_GEN) + RsaKey keypub; +#endif +#if defined(HAVE_NTRU) + RsaKey caKey; +#endif +#if !defined(NO_ASN) || !defined(WOLFSSL_RSA_PUBLIC_ONLY) \ + || defined(WOLFSSL_PUBLIC_MP) + word32 idx = 0; +#endif +#if (!defined(WOLFSSL_RSA_VERIFY_ONLY) || defined(WOLFSSL_PUBLIC_MP)) && \ + !defined(WC_NO_RSA_OAEP) && !defined(WC_NO_RNG) + 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; +#endif +#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) || defined(WOLFSSL_PUBLIC_MP) + byte* res; +#endif +#ifndef NO_SIG_WRAPPER + int modLen; +#endif +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ + !defined(USE_CERT_BUFFERS_3072) && !defined(USE_CERT_BUFFERS_4096) && \ + !defined(NO_FILESYSTEM) + XFILE file; + XFILE file2; #endif #ifdef WOLFSSL_TEST_CERT DecodedCert cert; #endif - tmp = (byte*)malloc(FOURK_BUF); - if (tmp == NULL) - return -40; +#if (!defined(WOLFSSL_RSA_VERIFY_ONLY) || defined(WOLFSSL_PUBLIC_MP)) && \ + !defined(WC_NO_RSA_OAEP) && !defined(WC_NO_RNG) + 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); +#endif + +#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 +#if defined(HAVE_NTRU) + XMEMSET(&caKey, 0, sizeof(caKey)); +#endif + +#if !defined(HAVE_USER_RSA) && !defined(NO_ASN) + ret = rsa_decode_test(&key); + 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; +#elif defined(USE_CERT_BUFFERS_3072) + bytes = (size_t)sizeof_client_key_der_3072; + if (bytes < (size_t)sizeof_client_cert_der_3072) + bytes = (size_t)sizeof_client_cert_der_3072; +#elif defined(USE_CERT_BUFFERS_4096) + bytes = (size_t)sizeof_client_key_der_4096; + if (bytes < (size_t)sizeof_client_cert_der_4096) + bytes = (size_t)sizeof_client_cert_der_4096; #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 -7700; + } + +#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(USE_CERT_BUFFERS_3072) + XMEMCPY(tmp, client_key_der_3072, (size_t)sizeof_client_key_der_3072); +#elif defined(USE_CERT_BUFFERS_4096) + XMEMCPY(tmp, client_key_der_4096, (size_t)sizeof_client_key_der_4096); +#elif !defined(NO_FILESYSTEM) + file = XFOPEN(clientKey, "rb"); if (!file) { err_sys("can't open ./certs/client-key.der, " "Please run from wolfSSL home dir", -40); - free(tmp); - return -40; + ERROR_OUT(-7701, exit_rsa); } - bytes = fread(tmp, 1, FOURK_BUF, file); - fclose(file); + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); +#else + /* No key to use. */ + ERROR_OUT(-7702, exit_rsa); #endif /* USE_CERT_BUFFERS */ -#ifdef HAVE_CAVIUM - wc_RsaInitCavium(&key, CAVIUM_DEV_ID); -#endif - ret = wc_InitRsaKey(&key, 0); + ret = wc_InitRsaKey_ex(&key, HEAP_HINT, devId); if (ret != 0) { - free(tmp); - return -39; + ERROR_OUT(-7703, exit_rsa); } +#ifndef NO_ASN ret = wc_RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes); if (ret != 0) { - free(tmp); - return -41; + ERROR_OUT(-7704, exit_rsa); } +#ifndef NO_SIG_WRAPPER + modLen = wc_RsaEncryptSize(&key); +#endif +#else + #ifdef USE_CERT_BUFFERS_2048 + ret = mp_read_unsigned_bin(&key.n, &tmp[12], 256); + if (ret != 0) { + ERROR_OUT(-7705, exit_rsa); + } + ret = mp_set_int(&key.e, WC_RSA_EXPONENT); + if (ret != 0) { + ERROR_OUT(-7706, exit_rsa); + } +#ifndef NO_SIG_WRAPPER + modLen = 2048; +#endif + #else + #error Not supported yet! + #endif +#endif + +#ifndef WC_NO_RNG +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else ret = wc_InitRng(&rng); +#endif if (ret != 0) { - free(tmp); - return -42; + ERROR_OUT(-7707, exit_rsa); } - ret = wc_RsaPublicEncrypt(in, inLen, out, sizeof(out), &key, &rng); +#endif + +#ifndef NO_SIG_WRAPPER + ret = rsa_sig_test(&key, sizeof(RsaKey), modLen, &rng); + if (ret != 0) + goto exit_rsa; +#endif + +#ifdef WC_RSA_NONBLOCK + ret = rsa_nb_test(&key, in, inLen, out, outSz, plain, plainSz, &rng); + if (ret != 0) + goto exit_rsa; +#endif + +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + ret = wc_RsaPublicEncrypt(in, inLen, out, outSz, &key, &rng); + } + } while (ret == WC_PENDING_E); if (ret < 0) { - free(tmp); - return -43; + ERROR_OUT(-7708, exit_rsa); } - ret = wc_RsaPrivateDecrypt(out, ret, plain, sizeof(plain), &key); + TEST_SLEEP(); + +#ifdef WC_RSA_BLINDING + { + int tmpret = ret; + ret = wc_RsaSetRNG(&key, &rng); + if (ret < 0) { + ERROR_OUT(-7709, exit_rsa); + } + ret = tmpret; + } +#endif + + idx = (word32)ret; /* save off encrypted length */ + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + ret = wc_RsaPrivateDecrypt(out, idx, plain, plainSz, &key); + } + } while (ret == WC_PENDING_E); if (ret < 0) { - free(tmp); - return -44; + ERROR_OUT(-7710, exit_rsa); } - if (memcmp(plain, in, inLen)) { - free(tmp); - return -45; + + if (XMEMCMP(plain, in, inLen)) { + ERROR_OUT(-7711, exit_rsa); } - ret = wc_RsaSSL_Sign(in, inLen, out, sizeof(out), &key, &rng); + TEST_SLEEP(); + + 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) { - free(tmp); - return -46; + ERROR_OUT(-7712, exit_rsa); } - memset(plain, 0, sizeof(plain)); - ret = wc_RsaSSL_Verify(out, ret, plain, sizeof(plain), &key); + if (ret != (int)inLen) { + ERROR_OUT(-7713, exit_rsa); + } + if (XMEMCMP(res, in, inLen)) { + ERROR_OUT(-7714, exit_rsa); + } + TEST_SLEEP(); + + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + ret = wc_RsaSSL_Sign(in, inLen, out, outSz, &key, &rng); + } + } while (ret == WC_PENDING_E); if (ret < 0) { - free(tmp); - return -47; + ERROR_OUT(-7715, exit_rsa); } - if (memcmp(plain, in, ret)) { - free(tmp); - return -48; + TEST_SLEEP(); + +#elif defined(WOLFSSL_PUBLIC_MP) + (void)outSz; + (void)inLen; + (void)res; + { + byte signature_2048[] = { + 0x07, 0x6f, 0xc9, 0x85, 0x73, 0x9e, 0x21, 0x79, + 0x47, 0xf1, 0xa3, 0xd7, 0xf4, 0x27, 0x29, 0xbe, + 0x99, 0x5d, 0xac, 0xb2, 0x10, 0x3f, 0x95, 0xda, + 0x89, 0x23, 0xb8, 0x96, 0x13, 0x57, 0x72, 0x30, + 0xa1, 0xfe, 0x5a, 0x68, 0x9c, 0x99, 0x9d, 0x1e, + 0x05, 0xa4, 0x80, 0xb0, 0xbb, 0xd9, 0xd9, 0xa1, + 0x69, 0x97, 0x74, 0xb3, 0x41, 0x21, 0x3b, 0x47, + 0xf5, 0x51, 0xb1, 0xfb, 0xc7, 0xaa, 0xcc, 0xdc, + 0xcd, 0x76, 0xa0, 0x28, 0x4d, 0x27, 0x14, 0xa4, + 0xb9, 0x41, 0x68, 0x7c, 0xb3, 0x66, 0xe6, 0x6f, + 0x40, 0x76, 0xe4, 0x12, 0xfd, 0xae, 0x29, 0xb5, + 0x63, 0x60, 0x87, 0xce, 0x49, 0x6b, 0xf3, 0x05, + 0x9a, 0x14, 0xb5, 0xcc, 0xcd, 0xf7, 0x30, 0x95, + 0xd2, 0x72, 0x52, 0x1d, 0x5b, 0x7e, 0xef, 0x4a, + 0x02, 0x96, 0x21, 0x6c, 0x55, 0xa5, 0x15, 0xb1, + 0x57, 0x63, 0x2c, 0xa3, 0x8e, 0x9d, 0x3d, 0x45, + 0xcc, 0xb8, 0xe6, 0xa1, 0xc8, 0x59, 0xcd, 0xf5, + 0xdc, 0x0a, 0x51, 0xb6, 0x9d, 0xfb, 0xf4, 0x6b, + 0xfd, 0x32, 0x71, 0x6e, 0xcf, 0xcb, 0xb3, 0xd9, + 0xe0, 0x4a, 0x77, 0x34, 0xd6, 0x61, 0xf5, 0x7c, + 0xf9, 0xa9, 0xa4, 0xb0, 0x8e, 0x3b, 0xd6, 0x04, + 0xe0, 0xde, 0x2b, 0x5b, 0x5a, 0xbf, 0xd9, 0xef, + 0x8d, 0xa3, 0xf5, 0xb1, 0x67, 0xf3, 0xb9, 0x72, + 0x0a, 0x37, 0x12, 0x35, 0x6c, 0x8e, 0x10, 0x8b, + 0x38, 0x06, 0x16, 0x4b, 0x20, 0x20, 0x13, 0x00, + 0x2e, 0x6d, 0xc2, 0x59, 0x23, 0x67, 0x4a, 0x6d, + 0xa1, 0x46, 0x8b, 0xee, 0xcf, 0x44, 0xb4, 0x3e, + 0x56, 0x75, 0x00, 0x68, 0xb5, 0x7d, 0x0f, 0x20, + 0x79, 0x5d, 0x7f, 0x12, 0x15, 0x32, 0x89, 0x61, + 0x6b, 0x29, 0xb7, 0x52, 0xf5, 0x25, 0xd8, 0x98, + 0xe8, 0x6f, 0xf9, 0x22, 0xb4, 0xbb, 0xe5, 0xff, + 0xd0, 0x92, 0x86, 0x9a, 0x88, 0xa2, 0xaf, 0x6b + }; + ret = sizeof(signature_2048); + XMEMCPY(out, signature_2048, ret); } +#endif + +#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) || defined(WOLFSSL_PUBLIC_MP) + idx = (word32)ret; + XMEMSET(plain, 0, plainSz); + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { +#ifndef WOLFSSL_RSA_VERIFY_INLINE + +#if defined(WOLFSSL_CRYPTOCELL) + /* + Cryptocell requires the input data and signature byte array to verify. + + first argument must be the input data + second argument must be the length of input data + third argument must be the signature byte array or the output from + wc_RsaSSL_Sign() + fourth argument must be the length of the signature byte array + */ + + ret = wc_RsaSSL_Verify(in, inLen, out, outSz, &key); +#else + ret = wc_RsaSSL_Verify(out, idx, plain, plainSz, &key); +#endif /* WOLFSSL_CRYPTOCELL */ +#else + byte* dec = NULL; + ret = wc_RsaSSL_VerifyInline(out, idx, &dec, &key); + if (ret > 0) { + XMEMCPY(plain, dec, ret); + } +#endif + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-7716, exit_rsa); + } + + if (XMEMCMP(plain, in, (size_t)ret)) { + ERROR_OUT(-7717, exit_rsa); + } + TEST_SLEEP(); +#endif + +#ifndef WOLFSSL_RSA_VERIFY_ONLY + #if !defined(WC_NO_RSA_OAEP) && !defined(WC_NO_RNG) + /* OAEP padding testing */ + #if !defined(HAVE_FAST_RSA) && !defined(HAVE_USER_RSA) && \ + (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + #ifndef NO_SHA + XMEMSET(plain, 0, plainSz); + + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + 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) { + ERROR_OUT(-7718, exit_rsa); + } + TEST_SLEEP(); + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + idx = (word32)ret; + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + 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) { + ERROR_OUT(-7719, exit_rsa); + } + + if (XMEMCMP(plain, in, inLen)) { + ERROR_OUT(-7720, exit_rsa); + } + TEST_SLEEP(); + #endif /* NO_SHA */ +#endif + + #ifndef NO_SHA256 + XMEMSET(plain, 0, plainSz); +#ifndef WOLFSSL_RSA_VERIFY_ONLY + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + 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) { + ERROR_OUT(-7721, exit_rsa); + } + TEST_SLEEP(); +#endif /* WOLFSSL_RSA_VERIFY_ONLY */ + + idx = (word32)ret; +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + 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) { + ERROR_OUT(-7722, exit_rsa); + } + + if (XMEMCMP(plain, in, inLen)) { + ERROR_OUT(-7723, exit_rsa); + } + TEST_SLEEP(); +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + 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(-7724, exit_rsa); + } + if (ret != (int)inLen) { + ERROR_OUT(-7725, exit_rsa); + } + if (XMEMCMP(res, in, inLen)) { + ERROR_OUT(-7726, exit_rsa); + } + TEST_SLEEP(); +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + + /* check fails if not using the same optional label */ + XMEMSET(plain, 0, plainSz); +#ifndef WOLFSSL_RSA_VERIFY_ONLY + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + 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) { + ERROR_OUT(-7727, exit_rsa); + } + TEST_SLEEP(); +#endif /* WOLFSSL_RSA_VERIFY_ONLY */ + +/* TODO: investigate why Cavium Nitrox doesn't detect decrypt error here */ +#if !defined(HAVE_CAVIUM) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ + !defined(WOLFSSL_CRYPTOCELL) +/* label is unused in cryptocell so it won't detect decrypt error due to label */ + idx = (word32)ret; + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + 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 */ + ERROR_OUT(-7728, exit_rsa); + } + ret = 0; + TEST_SLEEP(); +#endif /* !HAVE_CAVIUM */ + + /* check using optional label with encrypt/decrypt */ + XMEMSET(plain, 0, plainSz); +#ifndef WOLFSSL_RSA_VERIFY_ONLY + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + 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) { + ERROR_OUT(-7729, exit_rsa); + } + TEST_SLEEP(); +#endif /* WOLFSSL_RSA_VERIFY_ONLY */ + + idx = (word32)ret; +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + 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) { + ERROR_OUT(-7730, exit_rsa); + } + + if (XMEMCMP(plain, in, inLen)) { + ERROR_OUT(-7731, exit_rsa); + } + TEST_SLEEP(); +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + +#ifndef WOLFSSL_RSA_VERIFY_ONLY + #ifndef NO_SHA + /* check fail using mismatch hash algorithms */ + XMEMSET(plain, 0, plainSz); + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + 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) { + ERROR_OUT(-7732, exit_rsa); + } + TEST_SLEEP(); + +/* TODO: investigate why Cavium Nitrox doesn't detect decrypt error here */ +#if !defined(HAVE_CAVIUM) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ + !defined(WOLFSSL_CRYPTOCELL) + idx = (word32)ret; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + 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 */ + ERROR_OUT(-7733, exit_rsa); + } + ret = 0; + TEST_SLEEP(); + #endif /* !HAVE_CAVIUM */ + #endif /* NO_SHA */ +#endif /* WOLFSSL_RSA_VERIFY_ONLY */ +#endif /* NO_SHA256 */ + +#ifdef WOLFSSL_SHA512 + /* Check valid RSA key size is used while using hash length of SHA512 + 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)WC_SHA512_DIGEST_SIZE * 2) + 2) { + XMEMSET(plain, 0, plainSz); + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + 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) { + ERROR_OUT(-7734, exit_rsa); + } + TEST_SLEEP(); + + idx = ret; +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + 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) { + ERROR_OUT(-7735, exit_rsa); + } + + if (XMEMCMP(plain, in, inLen)) { + ERROR_OUT(-7736, exit_rsa); + } + TEST_SLEEP(); +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + } +#endif /* WOLFSSL_SHA512 */ + + /* check using pkcsv15 padding with _ex API */ + XMEMSET(plain, 0, plainSz); + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + 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) { + ERROR_OUT(-7737, exit_rsa); + } + TEST_SLEEP(); + + idx = (word32)ret; +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + 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) { + ERROR_OUT(-7738, exit_rsa); + } + + if (XMEMCMP(plain, in, inLen)) { + ERROR_OUT(-7739, exit_rsa); + } + TEST_SLEEP(); +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + #endif /* !HAVE_FAST_RSA && !HAVE_FIPS */ + #endif /* WC_NO_RSA_OAEP && !WC_NO_RNG */ +#endif /* WOLFSSL_RSA_VERIFY_ONLY */ + +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(NO_ASN) \ + && !defined(WOLFSSL_RSA_VERIFY_ONLY) + ret = rsa_export_key_test(&key); + if (ret != 0) + return ret; +#endif + +#if !defined(NO_ASN) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) + ret = rsa_flatten_test(&key); + if (ret != 0) + return ret; +#endif + #if defined(WOLFSSL_MDK_ARM) - #define sizeof(s) strlen((char *)(s)) + #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 - file2 = fopen(clientCert, "rb"); + XMEMCPY(tmp, client_cert_der_2048, (size_t)sizeof_client_cert_der_2048); + bytes = (size_t)sizeof_client_cert_der_2048; +#elif defined(USE_CERT_BUFFERS_3072) + XMEMCPY(tmp, client_cert_der_3072, (size_t)sizeof_client_cert_der_3072); + bytes = (size_t)sizeof_client_cert_der_3072; +#elif defined(USE_CERT_BUFFERS_4096) + XMEMCPY(tmp, client_cert_der_4096, (size_t)sizeof_client_cert_der_4096); + bytes = (size_t)sizeof_client_cert_der_4096; +#elif !defined(NO_FILESYSTEM) + file2 = XFOPEN(clientCert, "rb"); if (!file2) { - free(tmp); - return -49; + ERROR_OUT(-7740, exit_rsa); } - bytes = fread(tmp, 1, FOURK_BUF, file2); - fclose(file2); + bytes = XFREAD(tmp, 1, FOURK_BUF, file2); + XFCLOSE(file2); +#else + /* No certificate to use. */ + ERROR_OUT(-7741, exit_rsa); #endif #ifdef sizeof - #undef sizeof + #undef sizeof #endif #ifdef WOLFSSL_TEST_CERT InitDecodedCert(&cert, tmp, (word32)bytes, 0); ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); - if (ret != 0) return -491; + if (ret != 0) { + FreeDecodedCert(&cert); + ERROR_OUT(-7742, exit_rsa); + } FreeDecodedCert(&cert); #else (void)bytes; #endif +#ifdef WOLFSSL_CERT_EXT + +#ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(tmp, client_keypub_der_1024, sizeof_client_keypub_der_1024); + bytes = sizeof_client_keypub_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(tmp, client_keypub_der_2048, sizeof_client_keypub_der_2048); + bytes = sizeof_client_keypub_der_2048; +#elif defined(USE_CERT_BUFFERS_3072) + XMEMCPY(tmp, client_keypub_der_3072, sizeof_client_keypub_der_3072); + bytes = sizeof_client_keypub_der_3072; +#elif defined(USE_CERT_BUFFERS_4096) + XMEMCPY(tmp, client_keypub_der_4096, sizeof_client_keypub_der_4096); + bytes = sizeof_client_keypub_der_4096; +#else + file = XFOPEN(clientKeyPub, "rb"); + if (!file) { + err_sys("can't open ./certs/client-keyPub.der, " + "Please run from wolfSSL home dir", -40); + ERROR_OUT(-7743, exit_rsa); + } + + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); +#endif /* USE_CERT_BUFFERS */ + + ret = wc_InitRsaKey(&keypub, HEAP_HINT); + if (ret != 0) { + ERROR_OUT(-7744, exit_rsa); + } + idx = 0; + + ret = wc_RsaPublicKeyDecode(tmp, &idx, &keypub, (word32)bytes); + if (ret != 0) { + ERROR_OUT(-7745, 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, 0); - if (ret != 0) - return -300; - ret = wc_MakeRsaKey(&genKey, 1024, 65537, &rng); - if (ret != 0) - return -301; - - der = (byte*)malloc(FOURK_BUF); - if (der == NULL) { - wc_FreeRsaKey(&genKey); - return -307; - } - pem = (byte*)malloc(FOURK_BUF); - if (pem == NULL) { - free(der); - wc_FreeRsaKey(&genKey); - return -308; - } - - derSz = wc_RsaKeyToDer(&genKey, der, FOURK_BUF); - if (derSz < 0) { - free(der); - free(pem); - return -302; - } - -#ifdef FREESCALE_MQX - keyFile = fopen("a:\\certs\\key.der", "wb"); -#else - keyFile = fopen("./key.der", "wb"); + ret = rsa_keygen_test(&rng); + if (ret != 0) + goto exit_rsa; #endif - if (!keyFile) { - free(der); - free(pem); - wc_FreeRsaKey(&genKey); - return -303; - } - ret = (int)fwrite(der, 1, derSz, keyFile); - fclose(keyFile); - if (ret != derSz) { - free(der); - free(pem); - wc_FreeRsaKey(&genKey); - return -313; - } - - pemSz = wc_DerToPem(der, derSz, pem, FOURK_BUF, PRIVATEKEY_TYPE); - if (pemSz < 0) { - free(der); - free(pem); - wc_FreeRsaKey(&genKey); - return -304; - } - -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\key.pem", "wb"); -#else - pemFile = fopen("./key.pem", "wb"); -#endif - if (!pemFile) { - free(der); - free(pem); - wc_FreeRsaKey(&genKey); - return -305; - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - fclose(pemFile); - if (ret != pemSz) { - free(der); - free(pem); - wc_FreeRsaKey(&genKey); - return -314; - } - - ret = wc_InitRsaKey(&derIn, 0); - if (ret != 0) { - free(der); - free(pem); - wc_FreeRsaKey(&genKey); - return -3060; - } - idx = 0; - ret = wc_RsaPrivateKeyDecode(der, &idx, &derIn, derSz); - if (ret != 0) { - free(der); - free(pem); - wc_FreeRsaKey(&derIn); - wc_FreeRsaKey(&genKey); - return -306; - } - - wc_FreeRsaKey(&derIn); - wc_FreeRsaKey(&genKey); - free(pem); - free(der); - } -#endif /* WOLFSSL_KEY_GEN */ - #ifdef WOLFSSL_CERT_GEN - /* self signed */ - { - Cert myCert; - byte* derCert; - byte* pem; - FILE* derFile; - FILE* pemFile; - int certSz; - int pemSz; -#ifdef WOLFSSL_TEST_CERT - DecodedCert decode; + /* Make Cert / Sign example for RSA cert and RSA CA */ + ret = rsa_certgen_test(&key, &keypub, &rng, tmp); + if (ret != 0) + goto exit_rsa; + +#if !defined(NO_RSA) && defined(HAVE_ECC) + ret = rsa_ecc_certgen_test(&rng, tmp); + if (ret != 0) + goto exit_rsa; #endif - derCert = (byte*)malloc(FOURK_BUF); - if (derCert == NULL) - return -309; - pem = (byte*)malloc(FOURK_BUF); - if (pem == NULL) { - free(derCert); - return -310; - } - - wc_InitCert(&myCert); - - 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); - myCert.isCA = 1; - myCert.sigType = CTC_SHA256wRSA; - - certSz = wc_MakeSelfCert(&myCert, derCert, FOURK_BUF, &key, &rng); - if (certSz < 0) { - free(derCert); - free(pem); - return -401; - } - -#ifdef WOLFSSL_TEST_CERT - InitDecodedCert(&decode, derCert, certSz, 0); - ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); - if (ret != 0) { - free(derCert); - free(pem); - return -402; - } - FreeDecodedCert(&decode); -#endif - -#ifdef FREESCALE_MQX - derFile = fopen("a:\\certs\\cert.der", "wb"); -#else - derFile = fopen("./cert.der", "wb"); -#endif - if (!derFile) { - free(derCert); - free(pem); - return -403; - } - ret = (int)fwrite(derCert, 1, certSz, derFile); - fclose(derFile); - if (ret != certSz) { - free(derCert); - free(pem); - return -414; - } - - pemSz = wc_DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); - if (pemSz < 0) { - free(derCert); - free(pem); - return -404; - } - -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\cert.pem", "wb"); -#else - pemFile = fopen("./cert.pem", "wb"); -#endif - if (!pemFile) { - free(derCert); - free(pem); - return -405; - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - fclose(pemFile); - if (ret != pemSz) { - free(derCert); - free(pem); - return -406; - } - free(pem); - free(derCert); - } - /* CA style */ - { - 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 - DecodedCert decode; -#endif - - derCert = (byte*)malloc(FOURK_BUF); - if (derCert == NULL) - return -311; - pem = (byte*)malloc(FOURK_BUF); - if (pem == NULL) { - free(derCert); - return -312; - } - - file3 = fopen(caKeyFile, "rb"); - - if (!file3) { - free(derCert); - free(pem); - return -412; - } - - bytes3 = fread(tmp, 1, FOURK_BUF, file3); - fclose(file3); - - ret = wc_InitRsaKey(&caKey, 0); - if (ret != 0) { - free(derCert); - free(pem); - return -411; - } - ret = wc_RsaPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes3); - if (ret != 0) { - free(derCert); - free(pem); - wc_FreeRsaKey(&caKey); - return -413; - } - - wc_InitCert(&myCert); - - 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); - - ret = wc_SetIssuer(&myCert, caCertFile); - if (ret < 0) { - free(derCert); - free(pem); - wc_FreeRsaKey(&caKey); - return -405; - } - - certSz = wc_MakeCert(&myCert, derCert, FOURK_BUF, &key, NULL, &rng); - if (certSz < 0) { - free(derCert); - free(pem); - wc_FreeRsaKey(&caKey); - return -407; - } - - certSz = wc_SignCert(myCert.bodySz, myCert.sigType, derCert, FOURK_BUF, - &caKey, NULL, &rng); - if (certSz < 0) { - free(derCert); - free(pem); - wc_FreeRsaKey(&caKey); - return -408; - } - - -#ifdef WOLFSSL_TEST_CERT - InitDecodedCert(&decode, derCert, certSz, 0); - ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); - if (ret != 0) { - free(derCert); - free(pem); - wc_FreeRsaKey(&caKey); - return -409; - } - FreeDecodedCert(&decode); -#endif - -#ifdef FREESCALE_MQX - derFile = fopen("a:\\certs\\othercert.der", "wb"); -#else - derFile = fopen("./othercert.der", "wb"); -#endif - if (!derFile) { - free(derCert); - free(pem); - wc_FreeRsaKey(&caKey); - return -410; - } - ret = (int)fwrite(derCert, 1, certSz, derFile); - fclose(derFile); - if (ret != certSz) { - free(derCert); - free(pem); - wc_FreeRsaKey(&caKey); - return -416; - } - - pemSz = wc_DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); - if (pemSz < 0) { - free(derCert); - free(pem); - wc_FreeRsaKey(&caKey); - return -411; - } - -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\othercert.pem", "wb"); -#else - pemFile = fopen("./othercert.pem", "wb"); -#endif - if (!pemFile) { - free(derCert); - free(pem); - wc_FreeRsaKey(&caKey); - return -412; - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - if (ret != pemSz) { - free(derCert); - free(pem); - wc_FreeRsaKey(&caKey); - return -415; - } - fclose(pemFile); - free(pem); - free(derCert); - wc_FreeRsaKey(&caKey); - } -#ifdef HAVE_ECC - /* ECC CA style */ - { - ecc_key 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 - DecodedCert decode; -#endif - - derCert = (byte*)malloc(FOURK_BUF); - if (derCert == NULL) - return -5311; - pem = (byte*)malloc(FOURK_BUF); - if (pem == NULL) { - free(derCert); - return -5312; - } - - file3 = fopen(eccCaKeyFile, "rb"); - - if (!file3) { - free(derCert); - free(pem); - return -5412; - } - - bytes3 = fread(tmp, 1, FOURK_BUF, file3); - fclose(file3); - - wc_ecc_init(&caKey); - ret = wc_EccPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes3); - if (ret != 0) { - free(derCert); - free(pem); - return -5413; - } - - 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); - - ret = wc_SetIssuer(&myCert, eccCaCertFile); - if (ret < 0) { - free(pem); - free(derCert); - wc_ecc_free(&caKey); - return -5405; - } - - certSz = wc_MakeCert(&myCert, derCert, FOURK_BUF, NULL, &caKey, &rng); - if (certSz < 0) { - free(pem); - free(derCert); - wc_ecc_free(&caKey); - return -5407; - } - - certSz = wc_SignCert(myCert.bodySz, myCert.sigType, derCert, FOURK_BUF, - NULL, &caKey, &rng); - if (certSz < 0) { - free(pem); - free(derCert); - wc_ecc_free(&caKey); - return -5408; - } - -#ifdef WOLFSSL_TEST_CERT - InitDecodedCert(&decode, derCert, certSz, 0); - ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); - if (ret != 0) { - free(pem); - free(derCert); - wc_ecc_free(&caKey); - return -5409; - } - FreeDecodedCert(&decode); -#endif - -#ifdef FREESCALE_MQX - derFile = fopen("a:\\certs\\certecc.der", "wb"); -#else - derFile = fopen("./certecc.der", "wb"); -#endif - if (!derFile) { - free(pem); - free(derCert); - wc_ecc_free(&caKey); - return -5410; - } - ret = (int)fwrite(derCert, 1, certSz, derFile); - fclose(derFile); - if (ret != certSz) { - free(pem); - free(derCert); - wc_ecc_free(&caKey); - return -5414; - } - - pemSz = wc_DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); - if (pemSz < 0) { - free(pem); - free(derCert); - wc_ecc_free(&caKey); - return -5411; - } - -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\certecc.pem", "wb"); -#else - pemFile = fopen("./certecc.pem", "wb"); -#endif - if (!pemFile) { - free(pem); - free(derCert); - wc_ecc_free(&caKey); - return -5412; - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - if (ret != pemSz) { - free(pem); - free(derCert); - wc_ecc_free(&caKey); - return -5415; - } - fclose(pemFile); - free(pem); - free(derCert); - wc_ecc_free(&caKey); - } -#endif /* HAVE_ECC */ #ifdef HAVE_NTRU { - RsaKey caKey; Cert myCert; - byte* derCert; - byte* pem; - FILE* derFile; - FILE* pemFile; - FILE* caFile; - FILE* ntruPrivFile; + #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) + XFILE caFile; + #endif + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + XFILE ntruPrivFile; + #endif int certSz; - int pemSz; - word32 idx3; -#ifdef WOLFSSL_TEST_CERT + word32 idx3 = 0; + #ifdef WOLFSSL_TEST_CERT DecodedCert decode; -#endif - derCert = (byte*)malloc(FOURK_BUF); - if (derCert == NULL) - return -311; - pem = (byte*)malloc(FOURK_BUF); - if (pem == NULL) { - free(derCert); - 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 */ @@ -3973,363 +13599,946 @@ int rsa_test(void) word32 rc = ntru_crypto_drbg_instantiate(112, pers_str, sizeof(pers_str), GetEntropy, &drbg); if (rc != DRBG_OK) { - free(derCert); - free(pem); - return -448; + ERROR_OUT(-7746, exit_rsa); } rc = ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2, &public_key_len, NULL, &private_key_len, NULL); if (rc != NTRU_OK) { - free(derCert); - free(pem); - return -449; + ERROR_OUT(-7747, 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) { - free(derCert); - free(pem); - return -450; + ERROR_OUT(-7748, exit_rsa); } rc = ntru_crypto_drbg_uninstantiate(drbg); - if (rc != NTRU_OK) { - free(derCert); - free(pem); - return -451; + ERROR_OUT(-7749, 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 = XFOPEN(rsaCaKeyFile, "rb"); if (!caFile) { - free(derCert); - free(pem); - return -452; + ERROR_OUT(-7750, exit_rsa); } - bytes = fread(tmp, 1, FOURK_BUF, caFile); - fclose(caFile); + bytes = XFREAD(tmp, 1, FOURK_BUF, caFile); + XFCLOSE(caFile); + #endif /* USE_CERT_BUFFERS */ - ret = wc_InitRsaKey(&caKey, 0); + ret = wc_InitRsaKey(&caKey, HEAP_HINT); if (ret != 0) { - free(derCert); - free(pem); - return -453; + ERROR_OUT(-7751, exit_rsa); } ret = wc_RsaPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes); if (ret != 0) { - free(derCert); - free(pem); - return -454; + ERROR_OUT(-7752, exit_rsa); } - wc_InitCert(&myCert); + if (wc_InitCert(&myCert)) { + ERROR_OUT(-7753, 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; - ret = wc_SetIssuer(&myCert, caCertFile); + #ifdef WOLFSSL_CERT_EXT + /* add SKID from the Public Key */ + if (wc_SetSubjectKeyIdFromNtruPublicKey(&myCert, public_key, + public_key_len) != 0) { + ERROR_OUT(-7754, exit_rsa); + } + + /* 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(-7755, exit_rsa); + } + + /* add Key Usage */ + if (wc_SetKeyUsage(&myCert, certKeyUsage2) != 0) { + ERROR_OUT(-7756, exit_rsa); + } + #endif /* WOLFSSL_CERT_EXT */ + + #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) { - free(derCert); - free(pem); - wc_FreeRsaKey(&caKey); - return -455; + ERROR_OUT(-7757, 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(-7758, exit_rsa); + } + pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + ERROR_OUT(-7759, exit_rsa); + } + + certSz = wc_MakeNtruCert(&myCert, der, FOURK_BUF, public_key, public_key_len, &rng); if (certSz < 0) { - free(derCert); - free(pem); - wc_FreeRsaKey(&caKey); - return -456; + ERROR_OUT(-7760, 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) { - free(derCert); - free(pem); - return -457; + if (ret < 0) { + ERROR_OUT(-7761, exit_rsa); } + certSz = ret; - -#ifdef WOLFSSL_TEST_CERT - InitDecodedCert(&decode, derCert, certSz, 0); + #ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, HEAP_HINT); ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { - free(derCert); - free(pem); - return -458; + FreeDecodedCert(&decode); + ERROR_OUT(-7762, exit_rsa); } FreeDecodedCert(&decode); -#endif - derFile = fopen("./ntru-cert.der", "wb"); - if (!derFile) { - free(derCert); - free(pem); - return -459; - } - ret = (int)fwrite(derCert, 1, certSz, derFile); - fclose(derFile); - if (ret != certSz) { - free(derCert); - free(pem); - return -473; + #endif + + ret = SaveDerAndPem(der, certSz, pem, FOURK_BUF, "./ntru-cert.der", + "./ntru-cert.pem", CERT_TYPE, -5637); + if (ret != 0) { + goto exit_rsa; } - pemSz = wc_DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); - if (pemSz < 0) { - free(derCert); - free(pem); - return -460; - } - - pemFile = fopen("./ntru-cert.pem", "wb"); - if (!pemFile) { - free(derCert); - free(pem); - return -461; - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - fclose(pemFile); - if (ret != pemSz) { - free(derCert); - free(pem); - return -474; - } - - ntruPrivFile = fopen("./ntru-key.raw", "wb"); + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + ntruPrivFile = XFOPEN("./ntru-key.raw", "wb"); if (!ntruPrivFile) { - free(derCert); - free(pem); - return -462; + ERROR_OUT(-7763, exit_rsa); } - ret = (int)fwrite(private_key, 1, private_key_len, ntruPrivFile); - fclose(ntruPrivFile); + ret = (int)XFWRITE(private_key, 1, private_key_len, ntruPrivFile); + XFCLOSE(ntruPrivFile); if (ret != private_key_len) { - free(pem); - free(derCert); - return -475; + ERROR_OUT(-7764, exit_rsa); } - free(pem); - free(derCert); + #endif + + XFREE(pem, 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*)malloc(FOURK_BUF); - if (der == NULL) - return -463; - pem = (byte*)malloc(FOURK_BUF); + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-7765, exit_rsa); + } + pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - free(der); - return -464; + ERROR_OUT(-7766, exit_rsa); } - wc_InitCert(&req); + if (wc_InitCert(&req)) { + ERROR_OUT(-7767, 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); + XSTRNCPY(req.challengePw, "wolf123", CTC_NAME_SIZE); + XMEMCPY(&req.subject, &certDefaultName, sizeof(CertName)); + + #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) { + ERROR_OUT(-7768, exit_rsa); + } + + /* add Key Usage */ + if (wc_SetKeyUsage(&req, certKeyUsage2) != 0) { + ERROR_OUT(-7769, exit_rsa); + } + + /* add Extended Key Usage */ + if (wc_SetExtKeyUsage(&req, "serverAuth,clientAuth,codeSigning," + "emailProtection,timeStamping,OCSPSigning") != 0) { + ERROR_OUT(-7770, exit_rsa); + } + #ifdef WOLFSSL_EKU_OID + { + const char unique[] = "2.16.840.1.111111.100.1.10.1"; + if (wc_SetExtKeyUsageOID(&req, unique, sizeof(unique), 0, + HEAP_HINT) != 0) { + ERROR_OUT(-7771, exit_rsa); + } + } + #endif /* WOLFSSL_EKU_OID */ + #endif /* WOLFSSL_CERT_EXT */ derSz = wc_MakeCertReq(&req, der, FOURK_BUF, &key, NULL); if (derSz < 0) { - free(pem); - free(der); - return -465; + ERROR_OUT(-7772, 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(-7773, exit_rsa); + } + derSz = wc_MakeCertReq(&req, der, FOURK_BUF, &key, NULL); if (derSz < 0) { - free(pem); - free(der); - return -466; + ERROR_OUT(-7774, exit_rsa); + } + #endif /* WOLFSSL_CERT_EXT */ + + 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(-7775, exit_rsa); + } + derSz = ret; + + ret = SaveDerAndPem(der, derSz, pem, FOURK_BUF, certReqDerFile, + certReqPemFile, CERTREQ_TYPE, -5650); + if (ret != 0) { + goto exit_rsa; } - pemSz = wc_DerToPem(der, derSz, pem, FOURK_BUF, CERTREQ_TYPE); - if (pemSz < 0) { - free(pem); - free(der); - return -467; + derSz = wc_MakeCertReq_ex(&req, der, FOURK_BUF, RSA_TYPE, &key); + if (derSz < 0) { + ERROR_OUT(-7776, exit_rsa); } -#ifdef FREESCALE_MQX - reqFile = fopen("a:\\certs\\certreq.der", "wb"); -#else - reqFile = fopen("./certreq.der", "wb"); -#endif - if (!reqFile) { - free(pem); - free(der); - return -468; - } - - ret = (int)fwrite(der, 1, derSz, reqFile); - fclose(reqFile); - if (ret != derSz) { - free(pem); - free(der); - return -471; - } - -#ifdef FREESCALE_MQX - reqFile = fopen("a:\\certs\\certreq.pem", "wb"); -#else - reqFile = fopen("./certreq.pem", "wb"); -#endif - if (!reqFile) { - free(pem); - free(der); - return -469; - } - ret = (int)fwrite(pem, 1, pemSz, reqFile); - fclose(reqFile); - if (ret != pemSz) { - free(pem); - free(der); - return -470; - } - - free(pem); - free(der); + 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 */ - wc_FreeRsaKey(&key); -#ifdef HAVE_CAVIUM - wc_RsaFreeCavium(&key); +#ifdef WC_RSA_PSS + ret = rsa_pss_test(&rng, &key); #endif - free(tmp); + +exit_rsa: + wc_FreeRsaKey(&key); +#ifdef WOLFSSL_CERT_EXT + wc_FreeRsaKey(&keypub); +#endif +#if defined(HAVE_NTRU) + wc_FreeRsaKey(&caKey); +#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 +#endif /* !NO_RSA */ #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_fips_generate_test(WC_RNG *rng) +{ + int ret = 0; + DhKey key; + static byte p[] = { + 0xc5, 0x7c, 0xa2, 0x4f, 0x4b, 0xd6, 0x8c, 0x3c, + 0xda, 0xc7, 0xba, 0xaa, 0xea, 0x2e, 0x5c, 0x1e, + 0x18, 0xb2, 0x7b, 0x8c, 0x55, 0x65, 0x9f, 0xea, + 0xe0, 0xa1, 0x36, 0x53, 0x2b, 0x36, 0xe0, 0x4e, + 0x3e, 0x64, 0xa9, 0xe4, 0xfc, 0x8f, 0x32, 0x62, + 0x97, 0xe4, 0xbe, 0xf7, 0xc1, 0xde, 0x07, 0x5a, + 0x89, 0x28, 0xf3, 0xfe, 0x4f, 0xfe, 0x68, 0xbc, + 0xfb, 0x0a, 0x7c, 0xa4, 0xb3, 0x14, 0x48, 0x89, + 0x9f, 0xaf, 0xb8, 0x43, 0xe2, 0xa0, 0x62, 0x5c, + 0xb4, 0x88, 0x3f, 0x06, 0x50, 0x11, 0xfe, 0x65, + 0x8d, 0x49, 0xd2, 0xf5, 0x4b, 0x74, 0x79, 0xdb, + 0x06, 0x62, 0x92, 0x89, 0xed, 0xda, 0xcb, 0x87, + 0x37, 0x16, 0xd2, 0xa1, 0x7a, 0xe8, 0xde, 0x92, + 0xee, 0x3e, 0x41, 0x4a, 0x91, 0x5e, 0xed, 0xf3, + 0x6c, 0x6b, 0x7e, 0xfd, 0x15, 0x92, 0x18, 0xfc, + 0xa7, 0xac, 0x42, 0x85, 0x57, 0xe9, 0xdc, 0xda, + 0x55, 0xc9, 0x8b, 0x28, 0x9e, 0xc1, 0xc4, 0x46, + 0x4d, 0x88, 0xed, 0x62, 0x8e, 0xdb, 0x3f, 0xb9, + 0xd7, 0xc8, 0xe3, 0xcf, 0xb8, 0x34, 0x2c, 0xd2, + 0x6f, 0x28, 0x06, 0x41, 0xe3, 0x66, 0x8c, 0xfc, + 0x72, 0xff, 0x26, 0x3b, 0x6b, 0x6c, 0x6f, 0x73, + 0xde, 0xf2, 0x90, 0x29, 0xe0, 0x61, 0x32, 0xc4, + 0x12, 0x74, 0x09, 0x52, 0xec, 0xf3, 0x1b, 0xa6, + 0x45, 0x98, 0xac, 0xf9, 0x1c, 0x65, 0x8e, 0x3a, + 0x91, 0x84, 0x4b, 0x23, 0x8a, 0xb2, 0x3c, 0xc9, + 0xfa, 0xea, 0xf1, 0x38, 0xce, 0xd8, 0x05, 0xe0, + 0xfa, 0x44, 0x68, 0x1f, 0xeb, 0xd9, 0x57, 0xb8, + 0x4a, 0x97, 0x5b, 0x88, 0xc5, 0xf1, 0xbb, 0xb0, + 0x49, 0xc3, 0x91, 0x7c, 0xd3, 0x13, 0xb9, 0x47, + 0xbb, 0x91, 0x8f, 0xe5, 0x26, 0x07, 0xab, 0xa9, + 0xc5, 0xd0, 0x3d, 0x95, 0x41, 0x26, 0x92, 0x9d, + 0x13, 0x67, 0xf2, 0x7e, 0x11, 0x88, 0xdc, 0x2d + }; + static byte g[] = { + 0x4a, 0x1a, 0xf3, 0xa4, 0x92, 0xe9, 0xee, 0x74, + 0x6e, 0x57, 0xd5, 0x8c, 0x2c, 0x5b, 0x41, 0x41, + 0x5e, 0xd4, 0x55, 0x19, 0xdc, 0xd9, 0x32, 0x91, + 0xf7, 0xfd, 0xc2, 0x57, 0xff, 0x03, 0x14, 0xdb, + 0xf1, 0xb7, 0x60, 0x0c, 0x43, 0x59, 0x3f, 0xff, + 0xac, 0xf1, 0x80, 0x9a, 0x15, 0x6f, 0xd8, 0x6e, + 0xb7, 0x85, 0x18, 0xc8, 0xec, 0x4e, 0x59, 0x4a, + 0xe2, 0x91, 0x43, 0x4c, 0xeb, 0x95, 0xb6, 0x2e, + 0x9a, 0xea, 0x53, 0x68, 0x80, 0x64, 0x69, 0x40, + 0xf9, 0xec, 0xbd, 0x85, 0x89, 0x26, 0x97, 0x67, + 0xaf, 0xb0, 0xad, 0x00, 0x1b, 0xd4, 0xfd, 0x94, + 0xd3, 0xe9, 0x92, 0xb1, 0xb4, 0xbc, 0x5a, 0xaa, + 0x92, 0x80, 0x89, 0x3b, 0x39, 0x05, 0x6c, 0x22, + 0x26, 0xfe, 0x5a, 0x28, 0x6c, 0x37, 0x50, 0x5a, + 0x38, 0x99, 0xcf, 0xf3, 0xc1, 0x96, 0x45, 0xdc, + 0x01, 0xcb, 0x20, 0x87, 0xa5, 0x00, 0x8c, 0xf5, + 0x4d, 0xc2, 0xef, 0xb8, 0x9b, 0xd1, 0x87, 0xbe, + 0xed, 0xd5, 0x0a, 0x29, 0x15, 0x34, 0x59, 0x4c, + 0x3a, 0x05, 0x22, 0x05, 0x44, 0x4f, 0x9f, 0xc8, + 0x47, 0x12, 0x24, 0x8e, 0xa8, 0x79, 0xe4, 0x67, + 0xba, 0x4d, 0x5b, 0x75, 0x56, 0x95, 0xeb, 0xe8, + 0x8a, 0xfa, 0x8e, 0x01, 0x8c, 0x1b, 0x74, 0x63, + 0xd9, 0x2f, 0xf7, 0xd3, 0x44, 0x8f, 0xa8, 0xf5, + 0xaf, 0x6c, 0x4f, 0xdb, 0xe7, 0xc9, 0x6c, 0x71, + 0x22, 0xa3, 0x1d, 0xf1, 0x40, 0xb2, 0xe0, 0x9a, + 0xb6, 0x72, 0xc9, 0xc0, 0x13, 0x16, 0xa2, 0x4a, + 0xe1, 0x92, 0xc7, 0x54, 0x23, 0xab, 0x9d, 0xa1, + 0xa1, 0xe5, 0x0b, 0xed, 0xba, 0xe8, 0x84, 0x37, + 0xb2, 0xe7, 0xfe, 0x32, 0x8d, 0xfa, 0x1c, 0x53, + 0x77, 0x97, 0xc7, 0xf3, 0x48, 0xc9, 0xdb, 0x2d, + 0x75, 0x52, 0x9d, 0x42, 0x51, 0x78, 0x62, 0x68, + 0x05, 0x45, 0x15, 0xf8, 0xa2, 0x4e, 0xf3, 0x0b + }; + static byte q[] = { + 0xe0, 0x35, 0x37, 0xaf, 0xb2, 0x50, 0x91, 0x8e, + 0xf2, 0x62, 0x2b, 0xd9, 0x9f, 0x6c, 0x11, 0x75, + 0xec, 0x24, 0x5d, 0x78, 0x59, 0xe7, 0x8d, 0xb5, + 0x40, 0x52, 0xed, 0x41 + }; + static byte q0[] = { + 0x00, + 0xe0, 0x35, 0x37, 0xaf, 0xb2, 0x50, 0x91, 0x8e, + 0xf2, 0x62, 0x2b, 0xd9, 0x9f, 0x6c, 0x11, 0x75, + 0xec, 0x24, 0x5d, 0x78, 0x59, 0xe7, 0x8d, 0xb5, + 0x40, 0x52, 0xed, 0x41 + }; + byte priv[256]; + byte pub[256]; + word32 privSz = sizeof(priv); + word32 pubSz = sizeof(pub); + + /* Parameter Validation testing. */ + ret = wc_DhGenerateKeyPair(NULL, rng, priv, &privSz, pub, &pubSz); + if (ret != BAD_FUNC_ARG) + return -7777; + ret = wc_DhGenerateKeyPair(&key, NULL, priv, &privSz, pub, &pubSz); + if (ret != BAD_FUNC_ARG) + return -7778; + ret = wc_DhGenerateKeyPair(&key, rng, NULL, &privSz, pub, &pubSz); + if (ret != BAD_FUNC_ARG) + return -7779; + ret = wc_DhGenerateKeyPair(&key, rng, priv, NULL, pub, &pubSz); + if (ret != BAD_FUNC_ARG) + return -7780; + ret = wc_DhGenerateKeyPair(&key, rng, priv, &privSz, NULL, &pubSz); + if (ret != BAD_FUNC_ARG) + return -7781; + ret = wc_DhGenerateKeyPair(&key, rng, priv, &privSz, pub, NULL); + if (ret != BAD_FUNC_ARG) + return -7782; + + ret = wc_InitDhKey_ex(&key, HEAP_HINT, devId); + if (ret != 0) + return -7783; + + ret = wc_DhSetKey_ex(&key, p, sizeof(p), g, sizeof(g), q0, sizeof(q0)); + if (ret != 0) { + ERROR_OUT(-7784, exit_gen_test); + } + + wc_FreeDhKey(&key); + + ret = wc_InitDhKey_ex(&key, HEAP_HINT, devId); + if (ret != 0) + return -7785; + + ret = wc_DhSetKey_ex(&key, p, sizeof(p), g, sizeof(g), q, sizeof(q)); + if (ret != 0) { + ERROR_OUT(-7786, exit_gen_test); + } + + /* Use API. */ + 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(-7787, exit_gen_test); + } + + ret = wc_DhCheckPubKey_ex(&key, pub, pubSz, q0, sizeof(q0)); + if (ret != 0) { + ERROR_OUT(-7788, exit_gen_test); + } + + wc_FreeDhKey(&key); + ret = wc_InitDhKey_ex(&key, HEAP_HINT, devId); + if (ret != 0) + return -7789; + + ret = wc_DhSetKey(&key, p, sizeof(p), g, sizeof(g)); + if (ret != 0) { + ERROR_OUT(-7790, exit_gen_test); + } + + ret = wc_DhCheckPubKey_ex(&key, pub, pubSz, q, sizeof(q)); + if (ret != 0) { + ERROR_OUT(-7791, exit_gen_test); + } + +#ifndef HAVE_SELFTEST + ret = wc_DhCheckKeyPair(&key, pub, pubSz, priv, privSz); + if (ret != 0) { + ERROR_OUT(-7792, exit_gen_test); + } + + /* Taint the public key so the check fails. */ + pub[0]++; + ret = wc_DhCheckKeyPair(&key, pub, pubSz, priv, privSz); + if (ret != MP_CMP_E) { + ERROR_OUT(-7793, exit_gen_test); + } + +#ifdef WOLFSSL_KEY_GEN + wc_FreeDhKey(&key); + ret = wc_InitDhKey_ex(&key, HEAP_HINT, devId); + if (ret != 0) + return -7794; + + ret = wc_DhGenerateParams(rng, 2048, &key); + if (ret != 0) { + ERROR_OUT(-7795, exit_gen_test); + } + + privSz = sizeof(priv); + pubSz = sizeof(pub); + + 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(-7796, exit_gen_test); + } + +#endif /* WOLFSSL_KEY_GEN */ +#endif /* HAVE_SELFTEST */ + + ret = 0; + +exit_gen_test: + wc_FreeDhKey(&key); + + return ret; +} + +static int dh_generate_test(WC_RNG *rng) +{ + int ret = 0; + DhKey smallKey; + byte p[2] = { 0, 5 }; + byte g[2] = { 0, 2 }; +#ifndef WOLFSSL_SP_MATH +#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); +#endif + + ret = wc_InitDhKey_ex(&smallKey, HEAP_HINT, devId); + if (ret != 0) + return -7797; + + /* Parameter Validation testing. */ + ret = wc_InitDhKey_ex(NULL, HEAP_HINT, devId); + if (ret != BAD_FUNC_ARG) + return -7798; + wc_FreeDhKey(NULL); + + ret = wc_DhSetKey(NULL, p, sizeof(p), g, sizeof(g)); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-7799, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, NULL, sizeof(p), g, sizeof(g)); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-7800, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, p, 0, g, sizeof(g)); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-7801, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, p, sizeof(p), NULL, sizeof(g)); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-7802, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, p, sizeof(p), g, 0); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-7803, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, p, sizeof(p), g, sizeof(g)); + if (ret != 0) { + ERROR_OUT(-7804, exit_gen_test); + } + +#ifndef WOLFSSL_SP_MATH + /* 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 = -7805; + } +#else + (void)rng; + ret = 0; +#endif + +exit_gen_test: + wc_FreeDhKey(&smallKey); + + return ret; +} + +#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) +typedef struct dh_pubvalue_test { + const byte* data; + word32 len; +} dh_pubvalue_test; + +static int dh_test_check_pubvalue(void) +{ + int ret; + word32 i; + const byte prime[] = {0x01, 0x00, 0x01}; + const byte pubValZero[] = { 0x00 }; + const byte pubValZeroLong[] = { 0x00, 0x00, 0x00 }; + const byte pubValOne[] = { 0x01 }; + const byte pubValOneLong[] = { 0x00, 0x00, 0x01 }; + const byte pubValPrimeMinusOne[] = { 0x01, 0x00, 0x00 }; + const byte pubValPrimeLong[] = {0x00, 0x01, 0x00, 0x01}; + const byte pubValPrimePlusOne[] = { 0x01, 0x00, 0x02 }; + const byte pubValTooBig0[] = { 0x02, 0x00, 0x01 }; + const byte pubValTooBig1[] = { 0x01, 0x01, 0x01 }; + const byte pubValTooLong[] = { 0x01, 0x00, 0x00, 0x01 }; + const dh_pubvalue_test dh_pubval_fail[] = { + { prime, sizeof(prime) }, + { pubValZero, sizeof(pubValZero) }, + { pubValZeroLong, sizeof(pubValZeroLong) }, + { pubValOne, sizeof(pubValOne) }, + { pubValOneLong, sizeof(pubValOneLong) }, + { pubValPrimeMinusOne, sizeof(pubValPrimeMinusOne) }, + { pubValPrimeLong, sizeof(pubValPrimeLong) }, + { pubValPrimePlusOne, sizeof(pubValPrimePlusOne) }, + { pubValTooBig0, sizeof(pubValTooBig0) }, + { pubValTooBig1, sizeof(pubValTooBig1) }, + { pubValTooLong, sizeof(pubValTooLong) }, + }; + const byte pubValTwo[] = { 0x02 }; + const byte pubValTwoLong[] = { 0x00, 0x00, 0x02 }; + const byte pubValGood[] = { 0x12, 0x34 }; + const byte pubValGoodLen[] = { 0x00, 0x12, 0x34 }; + const byte pubValGoodLong[] = { 0x00, 0x00, 0x12, 0x34 }; + const dh_pubvalue_test dh_pubval_pass[] = { + { pubValTwo, sizeof(pubValTwo) }, + { pubValTwoLong, sizeof(pubValTwoLong) }, + { pubValGood, sizeof(pubValGood) }, + { pubValGoodLen, sizeof(pubValGoodLen) }, + { pubValGoodLong, sizeof(pubValGoodLong) }, + }; + + for (i = 0; i < sizeof(dh_pubval_fail) / sizeof(*dh_pubval_fail); i++) { + ret = wc_DhCheckPubValue(prime, sizeof(prime), dh_pubval_fail[i].data, + dh_pubval_fail[i].len); + if (ret != MP_VAL) + return -7806 - (int)i; + } + + for (i = 0; i < sizeof(dh_pubval_pass) / sizeof(*dh_pubval_pass); i++) { + ret = wc_DhCheckPubValue(prime, sizeof(prime), dh_pubval_pass[i].data, + dh_pubval_pass[i].len); + if (ret != 0) + return -7816 - (int)i; + } + + return 0; +} +#endif + +#if defined(HAVE_FFDHE) + +#ifdef HAVE_FFDHE_3072 + #define FFDHE_KEY_SIZE (3072/8) +#else + #define FFDHE_KEY_SIZE (2048/8) +#endif + +static int dh_test_ffdhe(WC_RNG *rng, const DhParams* params) +{ + int ret; + word32 privSz, pubSz, privSz2, pubSz2; + byte priv[FFDHE_KEY_SIZE]; + byte pub[FFDHE_KEY_SIZE]; + byte priv2[FFDHE_KEY_SIZE]; + byte pub2[FFDHE_KEY_SIZE]; + byte agree[FFDHE_KEY_SIZE]; + byte agree2[FFDHE_KEY_SIZE]; + word32 agreeSz = (word32)sizeof(agree); + word32 agreeSz2 = (word32)sizeof(agree2); + DhKey key; + DhKey key2; + + XMEMSET(&key, 0, sizeof(DhKey)); + XMEMSET(&key2, 0, sizeof(DhKey)); + + ret = wc_InitDhKey_ex(&key, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-7826, done); + } + ret = wc_InitDhKey_ex(&key2, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-7827, done); + } + + ret = wc_DhSetKey(&key, params->p, params->p_len, params->g, params->g_len); + if (ret != 0) { + ERROR_OUT(-7828, done); + } + + ret = wc_DhSetKey(&key2, params->p, params->p_len, params->g, + params->g_len); + if (ret != 0) { + ERROR_OUT(-7829, done); + } + + 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(-7830, done); + } + + 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(-7831, done); + } + + 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(-7832, 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(-7833, done); + } + + if (agreeSz != agreeSz2 || XMEMCMP(agree, agree2, agreeSz)) { + ERROR_OUT(-7834, done); + } + +done: + wc_FreeDhKey(&key); + wc_FreeDhKey(&key2); + return ret; +} + +#endif /* HAVE_FFDHE */ int dh_test(void) { int ret; word32 bytes; - word32 idx = 0, privSz, pubSz, privSz2, pubSz2, agreeSz, agreeSz2; + word32 idx = 0, privSz, pubSz, privSz2, pubSz2; byte tmp[1024]; +#if !defined(USE_CERT_BUFFERS_3072) && !defined(USE_CERT_BUFFERS_4096) byte priv[256]; byte pub[256]; byte priv2[256]; byte pub2[256]; byte agree[256]; byte agree2[256]; +#else + byte priv[512]; + byte pub[512]; + byte priv2[512]; + byte pub2[512]; + byte agree[512]; + byte agree2[512]; +#endif + word32 agreeSz = (word32)sizeof(agree); + word32 agreeSz2 = (word32)sizeof(agree2); DhKey key; DhKey key2; - RNG rng; + WC_RNG rng; + int keyInit = 0; #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(USE_CERT_BUFFERS_3072) + XMEMCPY(tmp, dh_key_der_3072, (size_t)sizeof_dh_key_der_3072); + bytes = (size_t)sizeof_dh_key_der_3072; +#elif defined(USE_CERT_BUFFERS_4096) + XMEMCPY(tmp, dh_key_der_4096, (size_t)sizeof_dh_key_der_4096); + bytes = (size_t)sizeof_dh_key_der_4096; #elif defined(NO_ASN) /* don't use file, no DER parsing */ -#else - FILE* file = fopen(dhKey, "rb"); - +#elif !defined(NO_FILESYSTEM) + XFILE file = XFOPEN(dhKey, "rb"); if (!file) - return -50; + return -7900; - bytes = (word32) fread(tmp, 1, sizeof(tmp), file); - fclose(file); + bytes = (word32) XFREAD(tmp, 1, sizeof(tmp), file); + XFCLOSE(file); +#else + /* No DH key to use. */ + return -7901; #endif /* USE_CERT_BUFFERS */ (void)idx; (void)tmp; (void)bytes; - wc_InitDhKey(&key); - wc_InitDhKey(&key2); + /* Use API for coverage. */ + ret = wc_InitDhKey(&key); + if (ret != 0) { + ERROR_OUT(-7902, done); + } + wc_FreeDhKey(&key); + + ret = wc_InitDhKey_ex(&key, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-7903, done); + } + keyInit = 1; + ret = wc_InitDhKey_ex(&key2, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-7904, 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(-7905, 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(-7906, done); + } #else ret = wc_DhKeyDecode(tmp, &idx, &key, bytes); - if (ret != 0) - return -51; + if (ret != 0) { + ERROR_OUT(-7907, done); + } idx = 0; ret = wc_DhKeyDecode(tmp, &idx, &key2, bytes); - if (ret != 0) - return -52; + if (ret != 0) { + ERROR_OUT(-7908, 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(-7909, 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(-7910, 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(-7911, done); + } - if (memcmp(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(-7912, 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(-7913, done); + } + + if (agreeSz != agreeSz2 || XMEMCMP(agree, agree2, agreeSz)) { + ERROR_OUT(-7914, done); + } + +#if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + if (wc_DhCheckPrivKey(NULL, NULL, 0) != BAD_FUNC_ARG) + return -7915; + + if (wc_DhCheckPrivKey(&key, priv, privSz) != 0) + return -7916; + + if (wc_DhExportParamsRaw(NULL, NULL, NULL, NULL, NULL, NULL, NULL) != BAD_FUNC_ARG) + return -7917; + { + word32 pSz, qSz, gSz; + if (wc_DhExportParamsRaw(&key, NULL, &pSz, NULL, &qSz, NULL, &gSz) != LENGTH_ONLY_E) + return -7918; + } +#endif + + ret = dh_generate_test(&rng); + if (ret == 0) + ret = dh_fips_generate_test(&rng); +#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + if (ret == 0) + ret = dh_test_check_pubvalue(); +#endif + + /* Specialized code for key gen when using FFDHE-2048 and FFDHE-3072. */ + #ifdef HAVE_FFDHE_2048 + if (ret == 0) { + ret = dh_test_ffdhe(&rng, wc_Dh_ffdhe2048_Get()); + if (ret != 0) + printf("error with FFDHE 2048\n"); + } + #endif + #ifdef HAVE_FFDHE_3072 + if (ret == 0) { + ret = dh_test_ffdhe(&rng, wc_Dh_ffdhe3072_Get()); + if (ret != 0) + printf("error with FFDHE 3072\n"); + } + #endif wc_FreeDhKey(&key); + keyInit = 0; + +#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ + !defined(WOLFSSL_OLD_PRIME_CHECK) + if (ret == 0) { + /* Test Check Key */ + ret = wc_DhSetCheckKey(&key, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g), + NULL, 0, 0, &rng); + keyInit = 1; /* DhSetCheckKey also initializes the key, free it */ + } +#endif + +done: + + if (keyInit) + wc_FreeDhKey(&key); wc_FreeDhKey(&key2); wc_FreeRng(&rng); - return 0; + return ret; } #endif /* NO_DH */ @@ -4337,14 +14546,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; @@ -4352,12 +14553,11 @@ int dsa_test(void) word32 idx = 0; byte tmp[1024]; DsaKey key; - RNG rng; - Sha sha; - byte hash[SHA_DIGEST_SIZE]; + WC_RNG rng; + 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; @@ -4365,66 +14565,1075 @@ int dsa_test(void) XMEMCPY(tmp, dsa_key_der_2048, sizeof_dsa_key_der_2048); bytes = sizeof_dsa_key_der_2048; #else - FILE* file = fopen(dsaKey, "rb"); - + XFILE file = XFOPEN(dsaKey, "rb"); if (!file) - return -60; + return -8000; - bytes = (word32) fread(tmp, 1, sizeof(tmp), file); - fclose(file); + bytes = (word32) XFREAD(tmp, 1, sizeof(tmp), file); + XFCLOSE(file); #endif /* USE_CERT_BUFFERS */ - ret = wc_InitSha(&sha); + ret = wc_InitSha_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4002; + return -8001; wc_ShaUpdate(&sha, tmp, bytes); wc_ShaFinal(&sha, hash); + wc_ShaFree(&sha); + + ret = wc_InitDsaKey(&key); + if (ret != 0) return -8002; - wc_InitDsaKey(&key); ret = wc_DsaPrivateKeyDecode(tmp, &idx, &key, bytes); - if (ret != 0) return -61; + if (ret != 0) return -8003; +#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 -8004; ret = wc_DsaSign(hash, signature, &key, &rng); - if (ret != 0) return -63; + if (ret != 0) return -8005; ret = wc_DsaVerify(hash, signature, &key, &answer); - if (ret != 0) return -64; - if (answer != 1) return -65; + if (ret != 0) return -8006; + if (answer != 1) return -8007; wc_FreeDsaKey(&key); - wc_FreeRng(&rng); +#ifdef WOLFSSL_KEY_GEN + { + byte* der; + byte* pem; + int derSz = 0; + DsaKey derIn; + DsaKey genKey; + + ret = wc_InitDsaKey(&genKey); + if (ret != 0) return -8008; + + ret = wc_MakeDsaParameters(&rng, 1024, &genKey); + if (ret != 0) { + wc_FreeDsaKey(&genKey); + return -8009; + } + + ret = wc_MakeDsaKey(&rng, &genKey); + if (ret != 0) { + wc_FreeDsaKey(&genKey); + return -8010; + } + + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + wc_FreeDsaKey(&genKey); + return -8011; + } + 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 -8012; + } + + 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 -8013; + } + + 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 ret; + } + + 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 -8014; + } + + idx = 0; + ret = wc_DsaPrivateKeyDecode(der, &idx, &derIn, derSz); + if (ret != 0) { + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeDsaKey(&derIn); + wc_FreeDsaKey(&genKey); + return -8015; + } + + wc_FreeDsaKey(&derIn); + wc_FreeDsaKey(&genKey); + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif /* WOLFSSL_KEY_GEN */ + + if (wc_InitDsaKey_h(&key, NULL) != 0) + return -8016; + + wc_FreeRng(&rng); return 0; } #endif /* NO_DSA */ +#ifdef WOLFCRYPT_HAVE_SRP -#ifdef OPENSSL_EXTRA +static int generate_random_salt(byte *buf, word32 size) +{ + int ret = -8017; + WC_RNG rng; + + if(NULL == buf || !size) + return -8018; + + if (buf && size && wc_InitRng_ex(&rng, HEAP_HINT, devId) == 0) { + ret = wc_RNG_GenerateBlock(&rng, (byte *)buf, size); + + wc_FreeRng(&rng); + } + + return ret; +} + +int srp_test(void) +{ + Srp cli, srv; + int r; + + byte clientPubKey[80]; /* A */ + byte serverPubKey[80]; /* B */ + word32 clientPubKeySz = 80; + word32 serverPubKeySz = 80; + byte clientProof[SRP_MAX_DIGEST_SIZE]; /* M1 */ + byte serverProof[SRP_MAX_DIGEST_SIZE]; /* M2 */ + word32 clientProofSz = SRP_MAX_DIGEST_SIZE; + word32 serverProofSz = SRP_MAX_DIGEST_SIZE; + + byte username[] = "user"; + word32 usernameSz = 4; + + byte password[] = "password"; + word32 passwordSz = 8; + + byte N[] = { + 0xC9, 0x4D, 0x67, 0xEB, 0x5B, 0x1A, 0x23, 0x46, 0xE8, 0xAB, 0x42, 0x2F, + 0xC6, 0xA0, 0xED, 0xAE, 0xDA, 0x8C, 0x7F, 0x89, 0x4C, 0x9E, 0xEE, 0xC4, + 0x2F, 0x9E, 0xD2, 0x50, 0xFD, 0x7F, 0x00, 0x46, 0xE5, 0xAF, 0x2C, 0xF7, + 0x3D, 0x6B, 0x2F, 0xA2, 0x6B, 0xB0, 0x80, 0x33, 0xDA, 0x4D, 0xE3, 0x22, + 0xE1, 0x44, 0xE7, 0xA8, 0xE9, 0xB1, 0x2A, 0x0E, 0x46, 0x37, 0xF6, 0x37, + 0x1F, 0x34, 0xA2, 0x07, 0x1C, 0x4B, 0x38, 0x36, 0xCB, 0xEE, 0xAB, 0x15, + 0x03, 0x44, 0x60, 0xFA, 0xA7, 0xAD, 0xF4, 0x83 + }; + + byte g[] = { + 0x02 + }; + + byte salt[10]; + + byte verifier[80]; + word32 v_size = sizeof(verifier); + + /* set as 0's so if second init on srv not called SrpTerm is not on + * garbage values */ + XMEMSET(&srv, 0, sizeof(Srp)); + XMEMSET(&cli, 0, sizeof(Srp)); + + /* generating random salt */ + + r = generate_random_salt(salt, sizeof(salt)); + + /* client knows username and password. */ + /* server knows N, g, salt and verifier. */ + + if (!r) r = wc_SrpInit(&cli, SRP_TYPE_SHA, SRP_CLIENT_SIDE); + if (!r) r = wc_SrpSetUsername(&cli, username, usernameSz); + + /* loading N, g and salt in advance to generate the verifier. */ + + if (!r) r = wc_SrpSetParams(&cli, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt)); + if (!r) r = wc_SrpSetPassword(&cli, password, passwordSz); + if (!r) r = wc_SrpGetVerifier(&cli, verifier, &v_size); + + /* client sends username to server */ + + if (!r) r = wc_SrpInit(&srv, SRP_TYPE_SHA, SRP_SERVER_SIDE); + if (!r) r = wc_SrpSetUsername(&srv, username, usernameSz); + if (!r) r = wc_SrpSetParams(&srv, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt)); + if (!r) r = wc_SrpSetVerifier(&srv, verifier, v_size); + if (!r) r = wc_SrpGetPublic(&srv, serverPubKey, &serverPubKeySz); + + /* server sends N, g, salt and B to client */ + + if (!r) r = wc_SrpGetPublic(&cli, clientPubKey, &clientPubKeySz); + if (!r) r = wc_SrpComputeKey(&cli, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz); + if (!r) r = wc_SrpGetProof(&cli, clientProof, &clientProofSz); + + /* client sends A and M1 to server */ + + if (!r) r = wc_SrpComputeKey(&srv, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz); + if (!r) r = wc_SrpVerifyPeersProof(&srv, clientProof, clientProofSz); + if (!r) r = wc_SrpGetProof(&srv, serverProof, &serverProofSz); + + /* server sends M2 to client */ + + if (!r) r = wc_SrpVerifyPeersProof(&cli, serverProof, serverProofSz); + + wc_SrpTerm(&cli); + wc_SrpTerm(&srv); + + return r; +} + +#endif /* WOLFCRYPT_HAVE_SRP */ + +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) + +#if !defined(NO_AES) && !defined(WOLFCRYPT_ONLY) +static int openssl_aes_test(void) +{ +#ifdef HAVE_AES_CBC +#ifdef WOLFSSL_AES_128 + { + /* EVP_CipherUpdate test */ + const byte cbcPlain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; + + byte key[] = "0123456789abcdef "; /* align */ + byte iv[] = "1234567890abcdef "; /* align */ + + byte cipher[AES_BLOCK_SIZE * 4]; + byte plain [AES_BLOCK_SIZE * 4]; + EVP_CIPHER_CTX en; + EVP_CIPHER_CTX de; + int outlen ; + int total = 0; + int i; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 1) == 0) + return -8200; + if (EVP_CipherUpdate(&en, (byte*)cipher, &outlen, + (byte*)cbcPlain, 9) == 0) + return -8201; + if (outlen != 0) + return -8202; + total += outlen; + + if (EVP_CipherUpdate(&en, (byte*)&cipher[total], &outlen, + (byte*)&cbcPlain[9] , 9) == 0) + return -8203; + if (outlen != 16) + return -8204; + total += outlen; + + if (EVP_CipherFinal(&en, (byte*)&cipher[total], &outlen) == 0) + return -8205; + if (outlen != 16) + return -8206; + total += outlen; + if (total != 32) + return 3408; + + total = 0; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 0) == 0) + return -8207; + + if (EVP_CipherUpdate(&de, (byte*)plain, &outlen, (byte*)cipher, 6) == 0) + return -8208; + if (outlen != 0) + return -8209; + total += outlen; + + if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, + (byte*)&cipher[6], 12) == 0) + return -8210; + if (outlen != 0) + total += outlen; + + if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, + (byte*)&cipher[6+12], 14) == 0) + return -8211; + if (outlen != 16) + return -8212; + total += outlen; + + if (EVP_CipherFinal(&de, (byte*)&plain[total], &outlen) == 0) + return -8213; + if (outlen != 2) + return -8214; + total += outlen; + + if (total != 18) + return 3427; + + if (XMEMCMP(plain, cbcPlain, 18)) + return -8215; + + /* test with encrypting/decrypting more than 16 bytes at once */ + total = 0; + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 1) == 0) + return -8216; + if (EVP_CipherUpdate(&en, (byte*)cipher, &outlen, + (byte*)cbcPlain, 17) == 0) + return -8217; + if (outlen != 16) + return -8218; + total += outlen; + + if (EVP_CipherUpdate(&en, (byte*)&cipher[total], &outlen, + (byte*)&cbcPlain[17] , 1) == 0) + return -8219; + if (outlen != 0) + return -8220; + total += outlen; + + if (EVP_CipherFinal(&en, (byte*)&cipher[total], &outlen) == 0) + return -8221; + if (outlen != 16) + return -8222; + total += outlen; + if (total != 32) + return -8223; + + total = 0; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 0) == 0) + return -8224; + + if (EVP_CipherUpdate(&de, (byte*)plain, &outlen, (byte*)cipher, 17) == 0) + return -8225; + if (outlen != 16) + return -8226; + total += outlen; + + /* final call on non block size should fail */ + if (EVP_CipherFinal(&de, (byte*)&plain[total], &outlen) != 0) + return -8227; + + if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, + (byte*)&cipher[17], 1) == 0) + return -8228; + if (outlen != 0) + total += outlen; + + if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, + (byte*)&cipher[17+1], 14) == 0) + return -8229; + if (outlen != 0) + return -8230; + total += outlen; + + if (EVP_CipherFinal(&de, (byte*)&plain[total], &outlen) == 0) + return -8231; + if (outlen != 2) + return -8232; + total += outlen; + + if (total != 18) + return -8233; + + if (XMEMCMP(plain, cbcPlain, 18)) + return -8234; + + /* test byte by byte decrypt */ + for (i = 0; i < AES_BLOCK_SIZE * 3; i++) { + plain[i] = i; + } + + total = 0; + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 1) == 0) + return -8235; + if (EVP_CipherUpdate(&en, (byte*)cipher, &outlen, + (byte*)plain, AES_BLOCK_SIZE * 3) == 0) + return -8236; + if (outlen != AES_BLOCK_SIZE * 3) + return -8237; + total += outlen; + + if (EVP_CipherFinal(&en, (byte*)&cipher[total], &outlen) == 0) + return -8238; + if (outlen != AES_BLOCK_SIZE) + return -8239; + total += outlen; + if (total != sizeof(plain)) + return -8240; + + total = 0; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 0) == 0) + return -8241; + + for (i = 0; i < AES_BLOCK_SIZE * 4; i++) { + if (EVP_CipherUpdate(&de, (byte*)plain + total, &outlen, + (byte*)cipher + i, 1) == 0) + return -8242; + + if (outlen > 0) { + int j; + + total += outlen; + for (j = 0; j < total; j++) { + if (plain[j] != j) { + return -8243; + } + } + } + } + + if (EVP_CipherFinal(&de, (byte*)&plain[total], &outlen) == 0) + return -8244; + total += outlen; + if (total != AES_BLOCK_SIZE * 3) { + return -8245; + } + for (i = 0; i < AES_BLOCK_SIZE * 3; i++) { + if (plain[i] != i) { + return -8246; + } + } + } + + /* set buffers to be exact size to catch potential over read/write */ + { + /* EVP_CipherUpdate test */ + const byte cbcPlain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; + + byte key[] = "0123456789abcdef "; /* align */ + byte iv[] = "1234567890abcdef "; /* align */ + + #define EVP_TEST_BUF_SZ 18 + #define EVP_TEST_BUF_PAD 32 + byte cipher[EVP_TEST_BUF_SZ]; + byte plain [EVP_TEST_BUF_SZ]; + byte padded[EVP_TEST_BUF_PAD]; + EVP_CIPHER_CTX en; + EVP_CIPHER_CTX de; + int outlen ; + int total = 0; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 1) == 0) + return -8247; + if (EVP_CIPHER_CTX_set_padding(&en, 0) != 1) + return -8248; + if (EVP_CipherUpdate(&en, (byte*)cipher, &outlen, + (byte*)cbcPlain, EVP_TEST_BUF_SZ) == 0) + return -8249; + if (outlen != 16) + return -8250; + total += outlen; + + /* should fail here */ + if (EVP_CipherFinal(&en, (byte*)&cipher[total], &outlen) != 0) + return -8251; + + /* turn padding back on and do successful encrypt */ + total = 0; + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 1) == 0) + return -8252; + if (EVP_CIPHER_CTX_set_padding(&en, 1) != 1) + return -8253; + if (EVP_CipherUpdate(&en, (byte*)padded, &outlen, + (byte*)cbcPlain, EVP_TEST_BUF_SZ) == 0) + return -8254; + if (outlen != 16) + return -8255; + total += outlen; + + if (EVP_CipherFinal(&en, (byte*)&padded[total], &outlen) == 0) + return -8256; + total += outlen; + if (total != 32) + return -8257; + XMEMCPY(cipher, padded, EVP_TEST_BUF_SZ); + + /* test out of bounds read on buffers w/o padding during decryption */ + total = 0; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 0) == 0) + return -8258; + + if (EVP_CIPHER_CTX_set_padding(&de, 0) != 1) + return -8259; + if (EVP_CipherUpdate(&de, (byte*)plain, &outlen, (byte*)cipher, + EVP_TEST_BUF_SZ) == 0) + return -8260; + if (outlen != 16) + return -8261; + total += outlen; + + /* should fail since not using padding */ + if (EVP_CipherFinal(&de, (byte*)&plain[total], &outlen) != 0) + return -8262; + + total = 0; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 0) == 0) + return -8263; + if (EVP_CIPHER_CTX_set_padding(&de, 1) != 1) + return -8264; + if (EVP_CipherUpdate(&de, (byte*)padded, &outlen, (byte*)padded, + EVP_TEST_BUF_PAD) == 0) + return -8265; + if (outlen != 16) + return -8266; + total += outlen; + + if (EVP_CipherFinal(&de, (byte*)&padded[total], &outlen) == 0) + return -8267; + if (XMEMCMP(padded, cbcPlain, EVP_TEST_BUF_SZ)) + return -8268; + } + + { /* evp_cipher test: EVP_aes_128_cbc */ + EVP_CIPHER_CTX ctx; + + 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 + }; + + const byte verify[] = + { + 0x95,0x94,0x92,0x57,0x5f,0x42,0x81,0x53, + 0x2c,0xcc,0x9d,0x46,0x77,0xa2,0x33,0xcb + }; + + byte key[] = "0123456789abcdef "; /* align */ + byte iv[] = "1234567890abcdef "; /* align */ + + byte cipher[AES_BLOCK_SIZE * 4]; + byte plain [AES_BLOCK_SIZE * 4]; + + EVP_CIPHER_CTX_init(&ctx); + if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 1) == 0) + return -8269; + + if (EVP_Cipher(&ctx, cipher, (byte*)msg, 16) == 0) + return -8270; + + if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) + return -8271; + + EVP_CIPHER_CTX_init(&ctx); + if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 0) == 0) + return -8272; + + if (EVP_Cipher(&ctx, plain, cipher, 16) == 0) + return -8273; + + if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) + return -8274; + + + } /* end evp_cipher test: EVP_aes_128_cbc*/ +#endif /* WOLFSSL_AES_128 */ +#endif /* HAVE_AES_CBC */ + +#if defined(HAVE_AES_ECB) && defined(WOLFSSL_AES_256) + { /* evp_cipher test: EVP_aes_256_ecb*/ + EVP_CIPHER_CTX ctx; + const byte msg[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte verify[] = + { + 0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c, + 0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8 + }; + + const 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 cipher[AES_BLOCK_SIZE * 4]; + 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 -8275; + + if (EVP_Cipher(&ctx, cipher, (byte*)msg, 16) == 0) + return -8276; + + if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) + return -8277; + + EVP_CIPHER_CTX_init(&ctx); + if (EVP_CipherInit(&ctx, EVP_aes_256_ecb(), (unsigned char*)key, NULL, 0) == 0) + return -8278; + + if (EVP_Cipher(&ctx, plain, cipher, 16) == 0) + return -8279; + + if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) + return -8280; + + } /* end evp_cipher test */ +#endif /* HAVE_AES_ECB && WOLFSSL_AES_256 */ + +#if defined(WOLFSSL_AES_DIRECT) && defined(WOLFSSL_AES_256) + /* enable HAVE_AES_DECRYPT for AES_encrypt/decrypt */ + { + /* Test: AES_encrypt/decrypt/set Key */ + AES_KEY enc; + #ifdef HAVE_AES_DECRYPT + AES_KEY dec; + #endif + + const byte msg[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte verify[] = + { + 0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c, + 0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8 + }; + + const 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 plain[sizeof(msg)]; + byte cipher[sizeof(msg)]; + + AES_set_encrypt_key(key, sizeof(key)*8, &enc); + AES_set_decrypt_key(key, sizeof(key)*8, &dec); + + AES_encrypt(msg, cipher, &enc); + + #ifdef HAVE_AES_DECRYPT + AES_decrypt(cipher, plain, &dec); + if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) + return -8281; + #endif /* HAVE_AES_DECRYPT */ + + if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) + return -8282; + } +#endif /* WOLFSSL_AES_DIRECT && WOLFSSL_AES_256 */ + +/* EVP_Cipher with EVP_aes_xxx_ctr() */ +#ifdef WOLFSSL_AES_COUNTER + { + byte plainBuff [64]; + byte cipherBuff[64]; + +#ifdef WOLFSSL_AES_128 + const byte ctrKey[] = + { + 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, + 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c + }; + + const byte ctrIv[] = + { + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff + }; + + + const byte ctrPlain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; + + const byte ctrCipher[] = + { + 0x87,0x4d,0x61,0x91,0xb6,0x20,0xe3,0x26, + 0x1b,0xef,0x68,0x64,0x99,0x0d,0xb6,0xce, + 0x98,0x06,0xf6,0x6b,0x79,0x70,0xfd,0xff, + 0x86,0x17,0x18,0x7b,0xb9,0xff,0xfd,0xff, + 0x5a,0xe4,0xdf,0x3e,0xdb,0xd5,0xd3,0x5e, + 0x5b,0x4f,0x09,0x02,0x0d,0xb0,0x3e,0xab, + 0x1e,0x03,0x1d,0xda,0x2f,0xbe,0x03,0xd1, + 0x79,0x21,0x70,0xa0,0xf3,0x00,0x9c,0xee + }; + + const byte oddCipher[] = + { + 0xb9,0xd7,0xcb,0x08,0xb0,0xe1,0x7b,0xa0, + 0xc2 + }; +#endif + + /* test vector from "Recommendation for Block Cipher Modes of Operation" + * NIST Special Publication 800-38A */ +#ifdef WOLFSSL_AES_192 + const byte ctr192Key[] = + { + 0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0x52, + 0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5, + 0x62,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b + }; + + const byte ctr192Iv[] = + { + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff + }; + + + const byte ctr192Plain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte ctr192Cipher[] = + { + 0x1a,0xbc,0x93,0x24,0x17,0x52,0x1c,0xa2, + 0x4f,0x2b,0x04,0x59,0xfe,0x7e,0x6e,0x0b + }; +#endif /* WOLFSSL_AES_192 */ + +#ifdef WOLFSSL_AES_256 + /* test vector from "Recommendation for Block Cipher Modes of Operation" + * NIST Special Publication 800-38A */ + const byte ctr256Key[] = + { + 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe, + 0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, + 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7, + 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 + }; + + const byte ctr256Iv[] = + { + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff + }; + + + const byte ctr256Plain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte ctr256Cipher[] = + { + 0x60,0x1e,0xc3,0x13,0x77,0x57,0x89,0xa5, + 0xb7,0xa7,0xf5,0x04,0xbb,0xf3,0xd2,0x28 + }; +#endif /* WOLFSSL_AES_256 */ + + EVP_CIPHER_CTX en; + EVP_CIPHER_CTX de; +#ifdef WOLFSSL_AES_128 + EVP_CIPHER_CTX *p_en; + EVP_CIPHER_CTX *p_de; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -8283; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, + AES_BLOCK_SIZE*4) == 0) + return -8284; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -8285; + + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, + AES_BLOCK_SIZE*4) == 0) + return -8286; + + if (XMEMCMP(cipherBuff, ctrCipher, AES_BLOCK_SIZE*4)) + return -8287; + if (XMEMCMP(plainBuff, ctrPlain, AES_BLOCK_SIZE*4)) + return -8288; + + p_en = wolfSSL_EVP_CIPHER_CTX_new(); + if (p_en == NULL) + return -8289; + p_de = wolfSSL_EVP_CIPHER_CTX_new(); + if (p_de == NULL) + return -8290; + + if (EVP_CipherInit(p_en, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -8291; + if (EVP_Cipher(p_en, (byte*)cipherBuff, (byte*)ctrPlain, + AES_BLOCK_SIZE*4) == 0) + return -8292; + if (EVP_CipherInit(p_de, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -8293; + + if (EVP_Cipher(p_de, (byte*)plainBuff, (byte*)cipherBuff, + AES_BLOCK_SIZE*4) == 0) + return -8294; + + wolfSSL_EVP_CIPHER_CTX_free(p_en); + wolfSSL_EVP_CIPHER_CTX_free(p_de); + + if (XMEMCMP(cipherBuff, ctrCipher, AES_BLOCK_SIZE*4)) + return -8295; + if (XMEMCMP(plainBuff, ctrPlain, AES_BLOCK_SIZE*4)) + return -8296; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -8297; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, 9) == 0) + return -8298; + + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -8299; + + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, 9) == 0) + return -8300; + + if (XMEMCMP(plainBuff, ctrPlain, 9)) + return -8301; + if (XMEMCMP(cipherBuff, ctrCipher, 9)) + return -8302; + + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, 9) == 0) + return -8303; + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, 9) == 0) + return -8304; + + if (XMEMCMP(plainBuff, ctrPlain, 9)) + return -8305; + if (XMEMCMP(cipherBuff, oddCipher, 9)) + return -8306; +#endif /* WOLFSSL_AES_128 */ + +#ifdef WOLFSSL_AES_192 + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_192_ctr(), + (unsigned char*)ctr192Key, (unsigned char*)ctr192Iv, 0) == 0) + return -8307; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctr192Plain, + AES_BLOCK_SIZE) == 0) + return -8308; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_192_ctr(), + (unsigned char*)ctr192Key, (unsigned char*)ctr192Iv, 0) == 0) + return -8309; + + XMEMSET(plainBuff, 0, sizeof(plainBuff)); + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, + AES_BLOCK_SIZE) == 0) + return -8310; + + if (XMEMCMP(plainBuff, ctr192Plain, sizeof(ctr192Plain))) + return -8311; + if (XMEMCMP(ctr192Cipher, cipherBuff, sizeof(ctr192Cipher))) + return -8312; +#endif /* WOLFSSL_AES_192 */ + +#ifdef WOLFSSL_AES_256 + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_256_ctr(), + (unsigned char*)ctr256Key, (unsigned char*)ctr256Iv, 0) == 0) + return -8313; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctr256Plain, + AES_BLOCK_SIZE) == 0) + return -8314; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_256_ctr(), + (unsigned char*)ctr256Key, (unsigned char*)ctr256Iv, 0) == 0) + return -8315; + + XMEMSET(plainBuff, 0, sizeof(plainBuff)); + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, + AES_BLOCK_SIZE) == 0) + return -8316; + + if (XMEMCMP(plainBuff, ctr256Plain, sizeof(ctr256Plain))) + return -8317; + if (XMEMCMP(ctr256Cipher, cipherBuff, sizeof(ctr256Cipher))) + return -8318; +#endif /* WOLFSSL_AES_256 */ + } +#endif /* HAVE_AES_COUNTER */ + +#if defined(WOLFSSL_AES_CFB) && defined(WOLFSSL_AES_128) + { + AES_KEY enc; + AES_KEY dec; + + const byte setIv[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + }; + + const byte key[] = + { + 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, + 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c + }; + + const byte cipher1[] = + { + 0x3b,0x3f,0xd9,0x2e,0xb7,0x2d,0xad,0x20, + 0x33,0x34,0x49,0xf8,0xe8,0x3c,0xfb,0x4a, + 0xc8,0xa6,0x45,0x37,0xa0,0xb3,0xa9,0x3f, + 0xcd,0xe3,0xcd,0xad,0x9f,0x1c,0xe5,0x8b + }; + + const byte msg[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51 + }; + + byte cipher[AES_BLOCK_SIZE * 2]; + byte iv[AES_BLOCK_SIZE]; /* iv buffer is updeated by API */ + int num = 0; + + XMEMCPY(iv, setIv, sizeof(setIv)); + wolfSSL_AES_set_encrypt_key(key, sizeof(key) * 8, &enc); + wolfSSL_AES_set_encrypt_key(key, sizeof(key) * 8, &dec); + + wolfSSL_AES_cfb128_encrypt(msg, cipher, AES_BLOCK_SIZE - 1, &enc, iv, + &num, AES_ENCRYPT); + + if (XMEMCMP(cipher, cipher1, AES_BLOCK_SIZE - 1)) + return -8319; + + if (num != 15) /* should have used 15 of the 16 bytes */ + return -8320; + + wolfSSL_AES_cfb128_encrypt(msg + AES_BLOCK_SIZE - 1, + cipher + AES_BLOCK_SIZE - 1, AES_BLOCK_SIZE + 1, &enc, iv, + &num, AES_ENCRYPT); + + if (XMEMCMP(cipher, cipher1, AES_BLOCK_SIZE * 2)) + return -8321; + + if (num != 0) + return -8322; + } +#endif /* WOLFSSL_AES_CFB && WOLFSSL_AES_128 */ + return 0; +} + + +#endif /* !defined(NO_AES) && !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 */ + + a.inLen = 0; + b.inLen = c.inLen = d.inLen = e.inLen = f.inLen = a.inLen; (void)a; (void)b; (void)c; + (void)d; (void)e; (void)f; + /* test malloc / free , 10 is an arbitrary amount of memory chosen */ + { + byte* p; + p = (byte*)CRYPTO_malloc(10, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (p == NULL) { + return -8400; + } + XMEMSET(p, 0, 10); + #ifdef WOLFSSL_QT + CRYPTO_free(p); + #else + CRYPTO_free(p, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + #ifndef NO_MD5 a.input = "1234567890123456789012345678901234567890123456789012345678" "9012345678901234567890"; a.output = "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6" "\x7a"; - a.inLen = strlen(a.input); - a.outLen = MD5_DIGEST_SIZE; + a.inLen = XSTRLEN(a.input); + a.outLen = WC_MD5_DIGEST_SIZE; EVP_MD_CTX_init(&md_ctx); EVP_DigestInit(&md_ctx, EVP_md5()); @@ -4432,8 +15641,8 @@ int openssl_test(void) EVP_DigestUpdate(&md_ctx, a.input, (unsigned long)a.inLen); EVP_DigestFinal(&md_ctx, hash, 0); - if (memcmp(hash, a.output, MD5_DIGEST_SIZE) != 0) - return -71; + if (XMEMCMP(hash, a.output, WC_MD5_DIGEST_SIZE) != 0) + return -8401; #endif /* NO_MD5 */ @@ -4444,8 +15653,8 @@ int openssl_test(void) "aaaaaaaaaa"; b.output = "\xAD\x5B\x3F\xDB\xCB\x52\x67\x78\xC2\x83\x9D\x2F\x15\x1E\xA7" "\x53\x99\x5E\x26\xA0"; - b.inLen = strlen(b.input); - b.outLen = SHA_DIGEST_SIZE; + b.inLen = XSTRLEN(b.input); + b.outLen = WC_SHA_DIGEST_SIZE; EVP_MD_CTX_init(&md_ctx); EVP_DigestInit(&md_ctx, EVP_sha1()); @@ -4453,18 +15662,38 @@ int openssl_test(void) EVP_DigestUpdate(&md_ctx, b.input, (unsigned long)b.inLen); EVP_DigestFinal(&md_ctx, hash, 0); - if (memcmp(hash, b.output, SHA_DIGEST_SIZE) != 0) - return -72; + if (XMEMCMP(hash, b.output, WC_SHA_DIGEST_SIZE) != 0) + return -8402; #endif /* NO_SHA */ +#ifdef WOLFSSL_SHA224 + + e.input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" + "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; + 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 = WC_SHA224_DIGEST_SIZE; + + EVP_MD_CTX_init(&md_ctx); + EVP_DigestInit(&md_ctx, EVP_sha224()); + + EVP_DigestUpdate(&md_ctx, e.input, (unsigned long)e.inLen); + EVP_DigestFinal(&md_ctx, hash, 0); + + if (XMEMCMP(hash, e.output, WC_SHA224_DIGEST_SIZE) != 0) + return -8403; + +#endif /* WOLFSSL_SHA224 */ + d.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; d.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"; - d.inLen = strlen(d.input); - d.outLen = SHA256_DIGEST_SIZE; + d.inLen = XSTRLEN(d.input); + d.outLen = WC_SHA256_DIGEST_SIZE; EVP_MD_CTX_init(&md_ctx); EVP_DigestInit(&md_ctx, EVP_sha256()); @@ -4472,8 +15701,8 @@ int openssl_test(void) EVP_DigestUpdate(&md_ctx, d.input, (unsigned long)d.inLen); EVP_DigestFinal(&md_ctx, hash, 0); - if (memcmp(hash, d.output, SHA256_DIGEST_SIZE) != 0) - return -78; + if (XMEMCMP(hash, d.output, WC_SHA256_DIGEST_SIZE) != 0) + return -8404; #ifdef WOLFSSL_SHA384 @@ -4483,8 +15712,8 @@ int openssl_test(void) "\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"; - e.inLen = strlen(e.input); - e.outLen = SHA384_DIGEST_SIZE; + e.inLen = XSTRLEN(e.input); + e.outLen = WC_SHA384_DIGEST_SIZE; EVP_MD_CTX_init(&md_ctx); EVP_DigestInit(&md_ctx, EVP_sha384()); @@ -4492,8 +15721,8 @@ int openssl_test(void) EVP_DigestUpdate(&md_ctx, e.input, (unsigned long)e.inLen); EVP_DigestFinal(&md_ctx, hash, 0); - if (memcmp(hash, e.output, SHA384_DIGEST_SIZE) != 0) - return -79; + if (XMEMCMP(hash, e.output, WC_SHA384_DIGEST_SIZE) != 0) + return -8405; #endif /* WOLFSSL_SHA384 */ @@ -4507,8 +15736,8 @@ int openssl_test(void) "\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"; - f.inLen = strlen(f.input); - f.outLen = SHA512_DIGEST_SIZE; + f.inLen = XSTRLEN(f.input); + f.outLen = WC_SHA512_DIGEST_SIZE; EVP_MD_CTX_init(&md_ctx); EVP_DigestInit(&md_ctx, EVP_sha512()); @@ -4516,27 +15745,103 @@ int openssl_test(void) EVP_DigestUpdate(&md_ctx, f.input, (unsigned long)f.inLen); EVP_DigestFinal(&md_ctx, hash, 0); - if (memcmp(hash, f.output, SHA512_DIGEST_SIZE) != 0) - return -80; + if (XMEMCMP(hash, f.output, WC_SHA512_DIGEST_SIZE) != 0) + return -8406; #endif /* WOLFSSL_SHA512 */ +#ifdef WOLFSSL_SHA3 +#ifndef WOLFSSL_NOSHA3_224 + e.input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" + "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; + e.output = "\x54\x3e\x68\x68\xe1\x66\x6c\x1a\x64\x36\x30\xdf\x77\x36\x7a\xe5\xa6\x2a\x85\x07\x0a\x51\xc1\x4c\xbf\x66\x5c\xbc"; + e.inLen = XSTRLEN(e.input); + e.outLen = WC_SHA3_224_DIGEST_SIZE; + + EVP_MD_CTX_init(&md_ctx); + EVP_DigestInit(&md_ctx, EVP_sha3_224()); + + EVP_DigestUpdate(&md_ctx, e.input, (unsigned long)e.inLen); + EVP_DigestFinal(&md_ctx, hash, 0); + + if (XMEMCMP(hash, e.output, WC_SHA3_224_DIGEST_SIZE) != 0) + return -8407; + +#endif /* WOLFSSL_NOSHA3_224 */ + + +#ifndef WOLFSSL_NOSHA3_256 + d.input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" + "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; + d.output = "\x91\x6f\x60\x61\xfe\x87\x97\x41\xca\x64\x69\xb4\x39\x71\xdf" + "\xdb\x28\xb1\xa3\x2d\xc3\x6c\xb3\x25\x4e\x81\x2b\xe2\x7a\xad" + "\x1d\x18"; + d.inLen = XSTRLEN(d.input); + d.outLen = WC_SHA3_256_DIGEST_SIZE; + + EVP_MD_CTX_init(&md_ctx); + EVP_DigestInit(&md_ctx, EVP_sha3_256()); + + EVP_DigestUpdate(&md_ctx, d.input, (unsigned long)d.inLen); + EVP_DigestFinal(&md_ctx, hash, 0); + + if (XMEMCMP(hash, d.output, WC_SHA3_256_DIGEST_SIZE) != 0) + return -8408; +#endif /* WOLFSSL_NOSHA3_256 */ + + + e.input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" + "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; + e.output = "\x79\x40\x7d\x3b\x59\x16\xb5\x9c\x3e\x30\xb0\x98\x22\x97\x47\x91\xc3\x13\xfb\x9e\xcc\x84\x9e\x40\x6f\x23\x59\x2d\x04\xf6\x25\xdc\x8c\x70\x9b\x98\xb4\x3b\x38\x52\xb3\x37\x21\x61\x79\xaa\x7f\xc7"; + e.inLen = XSTRLEN(e.input); + e.outLen = WC_SHA3_384_DIGEST_SIZE; + + EVP_MD_CTX_init(&md_ctx); + EVP_DigestInit(&md_ctx, EVP_sha3_384()); + + EVP_DigestUpdate(&md_ctx, e.input, (unsigned long)e.inLen); + EVP_DigestFinal(&md_ctx, hash, 0); + + if (XMEMCMP(hash, e.output, WC_SHA3_384_DIGEST_SIZE) != 0) + return -8409; + + + +#ifndef WOLFSSL_NOSHA3_512 + + f.input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" + "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; + f.output = "\xaf\xeb\xb2\xef\x54\x2e\x65\x79\xc5\x0c\xad\x06\xd2\xe5\x78\xf9\xf8\xdd\x68\x81\xd7\xdc\x82\x4d\x26\x36\x0f\xee\xbf\x18\xa4\xfa\x73\xe3\x26\x11\x22\x94\x8e\xfc\xfd\x49\x2e\x74\xe8\x2e\x21\x89\xed\x0f\xb4\x40\xd1\x87\xf3\x82\x27\x0c\xb4\x55\xf2\x1d\xd1\x85"; + f.inLen = XSTRLEN(f.input); + f.outLen = WC_SHA3_512_DIGEST_SIZE; + + EVP_MD_CTX_init(&md_ctx); + EVP_DigestInit(&md_ctx, EVP_sha3_512()); + + EVP_DigestUpdate(&md_ctx, f.input, (unsigned long)f.inLen); + EVP_DigestFinal(&md_ctx, hash, 0); + + if (XMEMCMP(hash, f.output, WC_SHA3_512_DIGEST_SIZE) != 0) + return -8410; + +#endif /* WOLFSSL_NOSHA3_512 */ +#endif /* WOLFSSL_SHA3 */ #ifndef NO_MD5 if (RAND_bytes(hash, sizeof(hash)) != 1) - return -73; + return -8411; 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 = strlen(c.input); - c.outLen = MD5_DIGEST_SIZE; + c.inLen = XSTRLEN(c.input); + c.outLen = WC_MD5_DIGEST_SIZE; HMAC(EVP_md5(), "JefeJefeJefeJefe", 16, (byte*)c.input, (int)c.inLen, hash, 0); - if (memcmp(hash, c.output, MD5_DIGEST_SIZE) != 0) - return -74; + if (XMEMCMP(hash, c.output, WC_MD5_DIGEST_SIZE) != 0) + return -8412; #endif /* NO_MD5 */ @@ -4575,28 +15880,32 @@ int openssl_test(void) DES_cbc_encrypt(vector, cipher, sizeof(vector), &sched, &iv, DES_ENCRYPT); DES_cbc_encrypt(cipher, plain, sizeof(vector), &sched, &iv, DES_DECRYPT); - if (memcmp(plain, vector, sizeof(vector)) != 0) - return -75; + if (XMEMCMP(plain, vector, sizeof(vector)) != 0) + return -8413; - if (memcmp(cipher, verify, sizeof(verify)) != 0) - return -76; + if (XMEMCMP(cipher, verify, sizeof(verify)) != 0) + return -8414; /* 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 (memcmp(cipher, verify, sizeof(verify)) != 0) - return -77; + if (XMEMCMP(cipher, verify, sizeof(verify)) != 0) + return -8415; } /* end des test */ #endif /* NO_DES3 */ -#ifndef NO_AES +#if !defined(NO_AES) && !defined(WOLFCRYPT_ONLY) + if (openssl_aes_test() != 0) { + return -8416; + } - { /* evp_cipher test */ +#if defined(WOLFSSL_AES_128) && defined(HAVE_AES_CBC) + { /* 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, @@ -4607,7 +15916,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 */ @@ -4618,37 +15937,1412 @@ int openssl_test(void) EVP_CIPHER_CTX_init(&ctx); if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 1) == 0) - return -81; + return -8417; - if (EVP_Cipher(&ctx, cipher, (byte*)msg, 16) == 0) - return -82; + if (EVP_CipherUpdate(&ctx, cipher, &idx, (byte*)msg, sizeof(msg)) == 0) + return -8418; - if (memcmp(cipher, verify, AES_BLOCK_SIZE)) - return -83; + cipherSz = idx; + if (EVP_CipherFinal(&ctx, cipher + cipherSz, &idx) == 0) + return -8419; + cipherSz += idx; + + if ((cipherSz != (int)sizeof(verify)) && + XMEMCMP(cipher, verify, cipherSz)) + return -8420; EVP_CIPHER_CTX_init(&ctx); if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 0) == 0) - return -84; + return -8421; + + /* check partial decrypt (not enough padding for full block) */ + if (EVP_CipherUpdate(&ctx, plain, &idx, cipher, 1) == 0) + return -8422; + + plainSz = idx; + if (EVP_CipherFinal(&ctx, plain + plainSz, &idx) != 0) + return -8423; + + EVP_CIPHER_CTX_init(&ctx); + if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 0) == 0) + return -8424; + + if (EVP_CipherUpdate(&ctx, plain, &idx, cipher, cipherSz) == 0) + return -8425; + + plainSz = idx; + if (EVP_CipherFinal(&ctx, plain + plainSz, &idx) == 0) + return -8426; + plainSz += idx; + + if ((plainSz != sizeof(msg)) || XMEMCMP(plain, msg, sizeof(msg))) + return -8427; + + EVP_CIPHER_CTX_init(&ctx); + if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 1) == 0) + return -8428; + + if (EVP_CipherUpdate(&ctx, cipher, &idx, msg, AES_BLOCK_SIZE) == 0) + return -8429; + + cipherSz = idx; + if (EVP_CipherFinal(&ctx, cipher + cipherSz, &idx) == 0) + return -8430; + cipherSz += idx; + + if ((cipherSz != (int)sizeof(verify2)) || + XMEMCMP(cipher, verify2, cipherSz)) + return -8431; + + } /* end evp_cipher test: EVP_aes_128_cbc*/ +#endif /* WOLFSSL_AES_128 && HAVE_AES_CBC */ + +#if defined(HAVE_AES_ECB) && defined(WOLFSSL_AES_256) + { /* evp_cipher test: EVP_aes_256_ecb*/ + EVP_CIPHER_CTX ctx; + const byte msg[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte verify[] = + { + 0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c, + 0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8 + }; + + const 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 cipher[AES_BLOCK_SIZE * 4]; + 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 -8432; + + if (EVP_Cipher(&ctx, cipher, (byte*)msg, 16) == 0) + return -8433; + + if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) + return -8434; + + EVP_CIPHER_CTX_init(&ctx); + if (EVP_CipherInit(&ctx, EVP_aes_256_ecb(), (unsigned char*)key, + NULL, 0) == 0) + return -8435; if (EVP_Cipher(&ctx, plain, cipher, 16) == 0) - return -85; - - if (memcmp(plain, msg, AES_BLOCK_SIZE)) - return -86; + return -8436; + if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) + return -8437; } /* end evp_cipher test */ +#endif /* HAVE_AES_ECB && WOLFSSL_AES_128 */ -#endif /* NO_AES */ +#define OPENSSL_TEST_ERROR (-10000) + +#if defined(WOLFSSL_AES_DIRECT) && defined(WOLFSSL_AES_256) + /* enable HAVE_AES_DECRYPT for AES_encrypt/decrypt */ +{ + + /* Test: AES_encrypt/decrypt/set Key */ + AES_KEY enc; +#ifdef HAVE_AES_DECRYPT + AES_KEY dec; +#endif + + const byte msg[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte verify[] = + { + 0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c, + 0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8 + }; + + const 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 plain[sizeof(msg)]; + byte cipher[sizeof(msg)]; + + printf("openSSL extra test\n") ; + + + AES_set_encrypt_key(key, sizeof(key)*8, &enc); + AES_set_decrypt_key(key, sizeof(key)*8, &dec); + + AES_encrypt(msg, cipher, &enc); + +#ifdef HAVE_AES_DECRYPT + AES_decrypt(cipher, plain, &dec); + if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) + return OPENSSL_TEST_ERROR-60; +#endif /* HAVE_AES_DECRYPT */ + + if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) + return OPENSSL_TEST_ERROR-61; +} + +#endif /* WOLFSSL_AES_DIRECT && WOLFSSL_AES_256 */ + +/* EVP_Cipher with EVP_aes_xxx_ctr() */ +#ifdef WOLFSSL_AES_COUNTER +{ + byte plainBuff [64]; + byte cipherBuff[64]; + +#ifdef WOLFSSL_AES_128 + const byte ctrKey[] = + { + 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, + 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c + }; + + const byte ctrIv[] = + { + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff + }; + + const byte ctrPlain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; + + const byte ctrCipher[] = + { + 0x87,0x4d,0x61,0x91,0xb6,0x20,0xe3,0x26, + 0x1b,0xef,0x68,0x64,0x99,0x0d,0xb6,0xce, + 0x98,0x06,0xf6,0x6b,0x79,0x70,0xfd,0xff, + 0x86,0x17,0x18,0x7b,0xb9,0xff,0xfd,0xff, + 0x5a,0xe4,0xdf,0x3e,0xdb,0xd5,0xd3,0x5e, + 0x5b,0x4f,0x09,0x02,0x0d,0xb0,0x3e,0xab, + 0x1e,0x03,0x1d,0xda,0x2f,0xbe,0x03,0xd1, + 0x79,0x21,0x70,0xa0,0xf3,0x00,0x9c,0xee + }; + + const byte oddCipher[] = + { + 0xb9,0xd7,0xcb,0x08,0xb0,0xe1,0x7b,0xa0, + 0xc2 + }; +#endif /* WOLFSSL_AES_128 */ + +#ifdef WOLFSSL_AES_192 + /* test vector from "Recommendation for Block Cipher Modes of Operation" + * NIST Special Publication 800-38A */ + const byte ctr192Key[] = + { + 0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0x52, + 0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5, + 0x62,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b + }; + + const byte ctr192Iv[] = + { + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff + }; + + + const byte ctr192Plain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte ctr192Cipher[] = + { + 0x1a,0xbc,0x93,0x24,0x17,0x52,0x1c,0xa2, + 0x4f,0x2b,0x04,0x59,0xfe,0x7e,0x6e,0x0b + }; +#endif /* WOLFSSL_AES_192 */ + +#ifdef WOLFSSL_AES_256 + /* test vector from "Recommendation for Block Cipher Modes of Operation" + * NIST Special Publication 800-38A */ + const byte ctr256Key[] = + { + 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe, + 0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, + 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7, + 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 + }; + + const byte ctr256Iv[] = + { + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff + }; + + + const byte ctr256Plain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte ctr256Cipher[] = + { + 0x60,0x1e,0xc3,0x13,0x77,0x57,0x89,0xa5, + 0xb7,0xa7,0xf5,0x04,0xbb,0xf3,0xd2,0x28 + }; +#endif /* WOLFSSL_AES_256 */ + + EVP_CIPHER_CTX en; + EVP_CIPHER_CTX de; +#ifdef WOLFSSL_AES_128 + EVP_CIPHER_CTX *p_en; + EVP_CIPHER_CTX *p_de; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -8438; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, + AES_BLOCK_SIZE*4) == 0) + return -8439; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -8440; + + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, + AES_BLOCK_SIZE*4) == 0) + return -8441; + + if (XMEMCMP(cipherBuff, ctrCipher, AES_BLOCK_SIZE*4)) + return -8442; + if (XMEMCMP(plainBuff, ctrPlain, AES_BLOCK_SIZE*4)) + return -8443; + + p_en = wolfSSL_EVP_CIPHER_CTX_new(); + if(p_en == NULL)return -8444; + p_de = wolfSSL_EVP_CIPHER_CTX_new(); + if(p_de == NULL)return -8445; + + if (EVP_CipherInit(p_en, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -8446; + if (EVP_Cipher(p_en, (byte*)cipherBuff, (byte*)ctrPlain, + AES_BLOCK_SIZE*4) == 0) + return -8447; + if (EVP_CipherInit(p_de, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -8448; + + if (EVP_Cipher(p_de, (byte*)plainBuff, (byte*)cipherBuff, + AES_BLOCK_SIZE*4) == 0) + return -8449; + + wolfSSL_EVP_CIPHER_CTX_free(p_en); + wolfSSL_EVP_CIPHER_CTX_free(p_de); + + if (XMEMCMP(cipherBuff, ctrCipher, AES_BLOCK_SIZE*4)) + return -8450; + if (XMEMCMP(plainBuff, ctrPlain, AES_BLOCK_SIZE*4)) + return -8451; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -8452; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, 9) == 0) + return -8453; + + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -8454; + + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, 9) == 0) + return -8455; + + if (XMEMCMP(plainBuff, ctrPlain, 9)) + return -8456; + if (XMEMCMP(cipherBuff, ctrCipher, 9)) + return -8457; + + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, 9) == 0) + return -8458; + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, 9) == 0) + return -8459; + + if (XMEMCMP(plainBuff, ctrPlain, 9)) + return -8460; + if (XMEMCMP(cipherBuff, oddCipher, 9)) + return -8461; +#endif /* WOLFSSL_AES_128 */ + +#ifdef WOLFSSL_AES_192 + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_192_ctr(), + (unsigned char*)ctr192Key, (unsigned char*)ctr192Iv, 0) == 0) + return -8462; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctr192Plain, + AES_BLOCK_SIZE) == 0) + return -8463; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_192_ctr(), + (unsigned char*)ctr192Key, (unsigned char*)ctr192Iv, 0) == 0) + return -8464; + + XMEMSET(plainBuff, 0, sizeof(plainBuff)); + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, + AES_BLOCK_SIZE) == 0) + return -8465; + + if (XMEMCMP(plainBuff, ctr192Plain, sizeof(ctr192Plain))) + return -8466; + if (XMEMCMP(ctr192Cipher, cipherBuff, sizeof(ctr192Cipher))) + return -8467; +#endif /* WOLFSSL_AES_192 */ + +#ifdef WOLFSSL_AES_256 + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_256_ctr(), + (unsigned char*)ctr256Key, (unsigned char*)ctr256Iv, 0) == 0) + return -8468; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctr256Plain, + AES_BLOCK_SIZE) == 0) + return -8469; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_256_ctr(), + (unsigned char*)ctr256Key, (unsigned char*)ctr256Iv, 0) == 0) + return -8470; + + XMEMSET(plainBuff, 0, sizeof(plainBuff)); + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, + AES_BLOCK_SIZE) == 0) + return -8471; + + if (XMEMCMP(plainBuff, ctr256Plain, sizeof(ctr256Plain))) + return -8472; + if (XMEMCMP(ctr256Cipher, cipherBuff, sizeof(ctr256Cipher))) + return -8473; +#endif /* WOLFSSL_AES_256 */ +} +#endif /* HAVE_AES_COUNTER */ + +#if defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) +{ + /* EVP_CipherUpdate test */ + + + const byte cbcPlain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; + + byte key[] = "0123456789abcdef "; /* align */ + byte iv[] = "1234567890abcdef "; /* align */ + + byte cipher[AES_BLOCK_SIZE * 4]; + byte plain [AES_BLOCK_SIZE * 4]; + EVP_CIPHER_CTX en; + EVP_CIPHER_CTX de; + int outlen ; + int total = 0; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 1) == 0) + return -8474; + /* openSSL compatibility, if(inlen == 0)return 1; */ + if (EVP_CipherUpdate(&en, (byte*)cipher, &outlen, + (byte*)cbcPlain, 0) != 1) + return -8475; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 1) == 0) + return -8476; + if (EVP_CipherUpdate(&en, (byte*)cipher, &outlen, + (byte*)cbcPlain, 9) == 0) + return -8477; + if(outlen != 0) + return -8478; + total += outlen; + + if (EVP_CipherUpdate(&en, (byte*)&cipher[total], &outlen, + (byte*)&cbcPlain[9] , 9) == 0) + return -8479; + if(outlen != 16) + return -8480; + total += outlen; + + if (EVP_CipherFinal(&en, (byte*)&cipher[total], &outlen) == 0) + return -8481; + if(outlen != 16) + return -8482; + total += outlen; + if(total != 32) + return -8483; + + total = 0; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 0) == 0) + return -8484; + + if (EVP_CipherUpdate(&de, (byte*)plain, &outlen, (byte*)cipher, 6) == 0) + return -8485; + if(outlen != 0) + return -8486; + total += outlen; + + if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, + (byte*)&cipher[6], 12) == 0) + return -8487; + if(outlen != 0) + total += outlen; + + if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, + (byte*)&cipher[6+12], 14) == 0) + return -8488; + if(outlen != 16) + return -8489; + total += outlen; + + if (EVP_CipherFinal(&de, (byte*)&plain[total], &outlen) == 0) + return -8490; + if(outlen != 2) + return -8491; + total += outlen; + + if(total != 18) + return -8492; + + if (XMEMCMP(plain, cbcPlain, 18)) + return -8493; + + total = 0; + EVP_CIPHER_CTX_init(&en); + if (EVP_EncryptInit(&en, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv) == 0) + return -8494; + if (EVP_CipherUpdate(&en, (byte*)cipher, &outlen, (byte*)cbcPlain, 9) == 0) + return -8495; + if(outlen != 0) + return -8496; + total += outlen; + + if (EVP_CipherUpdate(&en, (byte*)&cipher[total], &outlen, (byte*)&cbcPlain[9] , 9) == 0) + return -8497; + if(outlen != 16) + return -8498; + total += outlen; + + if (EVP_EncryptFinal(&en, (byte*)&cipher[total], &outlen) == 0) + return -8499; + if(outlen != 16) + return -8500; + total += outlen; + if(total != 32) + return 3438; + + total = 0; + EVP_CIPHER_CTX_init(&de); + if (EVP_DecryptInit(&de, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv) == 0) + return -8501; + + if (EVP_CipherUpdate(&de, (byte*)plain, &outlen, (byte*)cipher, 6) == 0) + return -8502; + if(outlen != 0) + return -8503; + total += outlen; + + if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, (byte*)&cipher[6], 12) == 0) + return -8504; + if(outlen != 0) + total += outlen; + + if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, (byte*)&cipher[6+12], 14) == 0) + return -8505; + if(outlen != 16) + return -8506; + total += outlen; + + if (EVP_DecryptFinal(&de, (byte*)&plain[total], &outlen) == 0) + return -8507; + if(outlen != 2) + return -8508; + total += outlen; + + if(total != 18) + return 3447; + + if (XMEMCMP(plain, cbcPlain, 18)) + return -8509; + + if (EVP_CIPHER_key_length(NULL) != 0) + return -8510; + + if (EVP_CIPHER_key_length(EVP_aes_128_cbc()) != 16) + return -8511; + + if (EVP_CIPHER_CTX_mode(NULL) != 0) + return -8512; + + if (EVP_CIPHER_CTX_mode(&en) != (en.flags & WOLFSSL_EVP_CIPH_MODE)) + return -8513; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit_ex(&en, EVP_aes_128_cbc(), NULL, + (unsigned char*)key, (unsigned char*)iv, 0) == 0) + return -8514; + + EVP_CIPHER_CTX_init(&en); + if (EVP_EncryptInit_ex(&en, EVP_aes_128_cbc(), NULL, + (unsigned char*)key, (unsigned char*)iv) == 0) + return -8515; + + if (wolfSSL_EVP_EncryptFinal_ex(NULL, NULL, NULL) != WOLFSSL_FAILURE) + return -8516; + + if (wolfSSL_EVP_EncryptFinal(NULL, NULL, NULL) != WOLFSSL_FAILURE) + return -8517; + + EVP_CIPHER_CTX_init(&de); + if (EVP_DecryptInit_ex(&de, EVP_aes_128_cbc(), NULL, + (unsigned char*)key, (unsigned char*)iv) == 0) + return -8518; + + if (wolfSSL_EVP_DecryptFinal(NULL, NULL, NULL) != WOLFSSL_FAILURE) + return -8519; + + if (wolfSSL_EVP_DecryptFinal_ex(NULL, NULL, NULL) != WOLFSSL_FAILURE) + return -8520; + + if (EVP_CIPHER_CTX_block_size(NULL) != BAD_FUNC_ARG) + return -8521; + + EVP_CIPHER_CTX_init(&en); + EVP_EncryptInit_ex(&en, EVP_aes_128_cbc(), NULL, + (unsigned char*)key, (unsigned char*)iv); + if (EVP_CIPHER_CTX_block_size(&en) != en.block_size) + return -8522; + + if (EVP_CIPHER_block_size(NULL) != BAD_FUNC_ARG) + return -8523; + + if (EVP_CIPHER_block_size(EVP_aes_128_cbc()) != AES_BLOCK_SIZE) + return -8524; + + if (WOLFSSL_EVP_CIPHER_mode(NULL) != 0) + return -8525; + + if (EVP_CIPHER_flags(EVP_aes_128_cbc()) != WOLFSSL_EVP_CIPH_CBC_MODE) + return -8526; + + EVP_CIPHER_CTX_clear_flags(&en, 0xFFFFFFFF); + EVP_CIPHER_CTX_set_flags(&en, 42); + if (en.flags != 42) + return -8527; + + if (EVP_CIPHER_CTX_set_padding(NULL, 0) != BAD_FUNC_ARG) + return -8528; + if (EVP_CIPHER_CTX_set_padding(&en, 0) != WOLFSSL_SUCCESS) + return -8529; + if (EVP_CIPHER_CTX_set_padding(&en, 1) != WOLFSSL_SUCCESS) + return -8530; + + } +#endif /* WOLFSSL_AES_128 && HAVE_AES_CBC */ +#endif /* ifndef NO_AES */ return 0; } +int openSSL_evpMD_test(void) +{ + int ret = 0; +#if !defined(NO_SHA256) && !defined(NO_SHA) + WOLFSSL_EVP_MD_CTX* ctx; + WOLFSSL_EVP_MD_CTX* ctx2; + + ctx = EVP_MD_CTX_create(); + ctx2 = EVP_MD_CTX_create(); + + ret = EVP_DigestInit(ctx, EVP_sha256()); + if (ret != SSL_SUCCESS) { + ret = -8600; + goto openSSL_evpMD_test_done; + } + + ret = EVP_MD_CTX_copy(ctx2, ctx); + if (ret != SSL_SUCCESS) { + ret = -8601; + goto openSSL_evpMD_test_done; + } + + if (EVP_MD_type(EVP_sha256()) != EVP_MD_CTX_type(ctx2)) { + ret = -8602; + goto openSSL_evpMD_test_done; + } + + ret = EVP_DigestInit(ctx, EVP_sha1()); + if (ret != SSL_SUCCESS) { + ret = -8603; + goto openSSL_evpMD_test_done; + } + + if (EVP_MD_type(EVP_sha256()) != EVP_MD_CTX_type(ctx2)) { + ret = -8604; + goto openSSL_evpMD_test_done; + } + + ret = EVP_MD_CTX_copy_ex(ctx2, ctx); + if (ret != SSL_SUCCESS) { + ret = -8605; + goto openSSL_evpMD_test_done; + } + + if (EVP_MD_type(EVP_sha256()) == EVP_MD_CTX_type(ctx2)) { + ret = -8606; + goto openSSL_evpMD_test_done; + } + + if (EVP_MD_type(EVP_sha1()) != EVP_MD_CTX_type(ctx2)) { + ret = -8607; + goto openSSL_evpMD_test_done; + } + + if (EVP_DigestInit_ex(ctx, EVP_sha1(), NULL) != SSL_SUCCESS) { + ret = -8608; + goto openSSL_evpMD_test_done; + } + + if (EVP_add_digest(NULL) != 0) { + ret = -8609; + goto openSSL_evpMD_test_done; + } + + if (wolfSSL_EVP_add_cipher(NULL) != 0) { + ret = -8610; + goto openSSL_evpMD_test_done; + } + + ret = 0; /* got to success state without jumping to end with a fail */ + +openSSL_evpMD_test_done: + EVP_MD_CTX_destroy(ctx); + EVP_MD_CTX_destroy(ctx2); +#endif /* NO_SHA256 */ + + return ret; +} + +#ifdef DEBUG_SIGN +static void show(const char *title, const char *p, unsigned int s) { + char* i; + printf("%s: ", title); + for (i = p; + i < p + s; + printf("%c", *i), i++); + printf("\n"); +} +#else +#define show(a,b,c) +#endif + +#define FOURK_BUFF 4096 + +#define ERR_BASE_PKEY -5000 +int openssl_pkey0_test(void) +{ + int ret = 0; +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(NO_SHA) + byte* prvTmp; + byte* pubTmp; + int prvBytes; + int pubBytes; + RSA *prvRsa = NULL; + RSA *pubRsa = NULL; + EVP_PKEY *prvPkey = NULL; + EVP_PKEY *pubPkey = NULL; + EVP_PKEY_CTX *enc = NULL; + EVP_PKEY_CTX *dec = NULL; + + byte in[] = "Everyone gets Friday off."; + byte out[256]; + size_t outlen; + size_t keySz; + byte plain[256]; +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) + XFILE keyFile; + XFILE keypubFile; + char cliKey[] = "./certs/client-key.der"; + char cliKeypub[] = "./certs/client-keyPub.der"; + +#endif + + prvTmp = (byte*)XMALLOC(FOURK_BUFF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (prvTmp == NULL) + return ERR_BASE_PKEY-1; + pubTmp = (byte*)XMALLOC(FOURK_BUFF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pubTmp == NULL) { + XFREE(prvTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + return ERR_BASE_PKEY-2; + } + +#ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(prvTmp, client_key_der_1024, sizeof_client_key_der_1024); + prvBytes = sizeof_client_key_der_1024; + XMEMCPY(pubTmp, client_keypub_der_1024, sizeof_client_keypub_der_1024); + pubBytes = sizeof_client_keypub_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(prvTmp, client_key_der_2048, sizeof_client_key_der_2048); + prvBytes = sizeof_client_key_der_2048; + XMEMCPY(pubTmp, client_keypub_der_2048, sizeof_client_keypub_der_2048); + pubBytes = sizeof_client_keypub_der_2048; +#else + keyFile = XFOPEN(cliKey, "rb"); + if (!keyFile) { + XFREE(prvTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pubTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + err_sys("can't open ./certs/client-key.der, " + "Please run from wolfSSL home dir", ERR_BASE_PKEY-3); + return ERR_BASE_PKEY-3; + } + prvBytes = (int)XFREAD(prvTmp, 1, (int)FOURK_BUFF, keyFile); + XFCLOSE(keyFile); + keypubFile = XFOPEN(cliKeypub, "rb"); + if (!keypubFile) { + XFREE(prvTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pubTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + err_sys("can't open ./certs/client-cert.der, " + "Please run from wolfSSL home dir", -4); + return ERR_BASE_PKEY-4; + } + pubBytes = (int)XFREAD(pubTmp, 1, (int)FOURK_BUFF, keypubFile); + XFCLOSE(keypubFile); +#endif /* USE_CERT_BUFFERS */ + + prvRsa = wolfSSL_RSA_new(); + pubRsa = wolfSSL_RSA_new(); + if((prvRsa == NULL) || (pubRsa == NULL)){ + printf("error with RSA_new\n"); + ret = ERR_BASE_PKEY-10; + goto openssl_pkey0_test_done; + } + + ret = wolfSSL_RSA_LoadDer_ex(prvRsa, prvTmp, prvBytes, WOLFSSL_RSA_LOAD_PRIVATE); + if(ret != SSL_SUCCESS){ + printf("error with RSA_LoadDer_ex\n"); + ret = ERR_BASE_PKEY-11; + goto openssl_pkey0_test_done; + } + + ret = wolfSSL_RSA_LoadDer_ex(pubRsa, pubTmp, pubBytes, WOLFSSL_RSA_LOAD_PUBLIC); + if(ret != SSL_SUCCESS){ + printf("error with RSA_LoadDer_ex\n"); + ret = ERR_BASE_PKEY-12; + goto openssl_pkey0_test_done; + } + keySz = (size_t)RSA_size(pubRsa); + + prvPkey = wolfSSL_EVP_PKEY_new(); + pubPkey = wolfSSL_EVP_PKEY_new(); + if((prvPkey == NULL) || (pubPkey == NULL)){ + printf("error with PKEY_new\n"); + ret = ERR_BASE_PKEY-13; + goto openssl_pkey0_test_done; + } + ret = wolfSSL_EVP_PKEY_set1_RSA(prvPkey, prvRsa); + ret += wolfSSL_EVP_PKEY_set1_RSA(pubPkey, pubRsa); + if(ret != 2){ + printf("error with PKEY_set1_RSA\n"); + ret = ERR_BASE_PKEY-14; + goto openssl_pkey0_test_done; + } + + dec = EVP_PKEY_CTX_new(prvPkey, NULL); + enc = EVP_PKEY_CTX_new(pubPkey, NULL); + if((dec == NULL)||(enc==NULL)){ + printf("error with EVP_PKEY_CTX_new\n"); + ret = ERR_BASE_PKEY-15; + goto openssl_pkey0_test_done; + } + + ret = EVP_PKEY_decrypt_init(dec); + if (ret != 1) { + printf("error with decrypt init\n"); + ret = ERR_BASE_PKEY-16; + goto openssl_pkey0_test_done; + } + ret = EVP_PKEY_encrypt_init(enc); + if (ret != 1) { + printf("error with encrypt init\n"); + ret = ERR_BASE_PKEY-17; + goto openssl_pkey0_test_done; + } + XMEMSET(out, 0, sizeof(out)); + ret = EVP_PKEY_encrypt(enc, out, &outlen, in, sizeof(in)); + if (ret != 1) { + printf("error encrypting msg\n"); + ret = ERR_BASE_PKEY-18; + goto openssl_pkey0_test_done; + } + + show("encrypted msg", out, outlen); + + XMEMSET(plain, 0, sizeof(plain)); + ret = EVP_PKEY_decrypt(dec, plain, &outlen, out, keySz); + if (ret != 1) { + printf("error decrypting msg\n"); + ret = ERR_BASE_PKEY-19; + goto openssl_pkey0_test_done; + } + show("decrypted msg", plain, outlen); + + /* RSA_PKCS1_OAEP_PADDING test */ + ret = EVP_PKEY_decrypt_init(dec); + if (ret != 1) { + printf("error with decrypt init\n"); + ret = ERR_BASE_PKEY-30; + goto openssl_pkey0_test_done; + } + ret = EVP_PKEY_encrypt_init(enc); + if (ret != 1) { + printf("error with encrypt init\n"); + ret = ERR_BASE_PKEY-31; + goto openssl_pkey0_test_done; + } + + if (EVP_PKEY_CTX_set_rsa_padding(dec, RSA_PKCS1_PADDING) <= 0) { + printf("first set rsa padding error\n"); + ret = ERR_BASE_PKEY-32; + goto openssl_pkey0_test_done; + } + +#ifndef HAVE_FIPS + if (EVP_PKEY_CTX_set_rsa_padding(dec, RSA_PKCS1_OAEP_PADDING) <= 0){ + printf("second set rsa padding error\n"); + ret = ERR_BASE_PKEY-33; + goto openssl_pkey0_test_done; + } + + if (EVP_PKEY_CTX_set_rsa_padding(enc, RSA_PKCS1_OAEP_PADDING) <= 0) { + printf("third set rsa padding error\n"); + ret = ERR_BASE_PKEY-34; + goto openssl_pkey0_test_done; + } +#endif + + XMEMSET(out, 0, sizeof(out)); + ret = EVP_PKEY_encrypt(enc, out, &outlen, in, sizeof(in)); + if (ret != 1) { + printf("error encrypting msg\n"); + ret = ERR_BASE_PKEY-35; + goto openssl_pkey0_test_done; + } + + show("encrypted msg", out, outlen); + + XMEMSET(plain, 0, sizeof(plain)); + ret = EVP_PKEY_decrypt(dec, plain, &outlen, out, keySz); + if (ret != 1) { + printf("error decrypting msg\n"); + ret = ERR_BASE_PKEY-36; + goto openssl_pkey0_test_done; + } + + show("decrypted msg", plain, outlen); + + ret = 0; /* made it to this point without error then set success */ +openssl_pkey0_test_done: + + wolfSSL_RSA_free(prvRsa); + wolfSSL_RSA_free(pubRsa); + EVP_PKEY_free(pubPkey); + EVP_PKEY_free(prvPkey); + EVP_PKEY_CTX_free(dec); + EVP_PKEY_CTX_free(enc); + XFREE(prvTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pubTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#endif /* NO_RSA */ + + return ret; +} + + +int openssl_pkey1_test(void) +{ + int ret = 0; +#if !defined(NO_FILESYSTEM) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) && \ + !defined(NO_SHA) + EVP_PKEY_CTX* dec = NULL; + EVP_PKEY_CTX* enc = NULL; + EVP_PKEY* pubKey = NULL; + EVP_PKEY* prvKey = NULL; + X509* x509; + + const unsigned char msg[] = "sugar slapped"; + const unsigned char* clikey; + unsigned char tmp[FOURK_BUF]; + long cliKeySz; + unsigned char cipher[RSA_TEST_BYTES]; + unsigned char plain[RSA_TEST_BYTES]; + size_t outlen; + int keyLenBits = 2048; + +#if defined(USE_CERT_BUFFERS_1024) + XMEMCPY(tmp, client_key_der_1024, sizeof_client_key_der_1024); + cliKeySz = (long)sizeof_client_key_der_1024; + + x509 = wolfSSL_X509_load_certificate_buffer(client_cert_der_1024, + sizeof_client_cert_der_1024, SSL_FILETYPE_ASN1); + keyLenBits = 1024; +#elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(tmp, client_key_der_2048, sizeof_client_key_der_2048); + cliKeySz = (long)sizeof_client_key_der_2048; + + x509 = wolfSSL_X509_load_certificate_buffer(client_cert_der_2048, + sizeof_client_cert_der_2048, SSL_FILETYPE_ASN1); +#elif defined(USE_CERT_BUFFERS_3072) + XMEMCPY(tmp, client_key_der_3072, sizeof_client_key_der_3072); + cliKeySz = (long)sizeof_client_key_der_3072; + + x509 = wolfSSL_X509_load_certificate_buffer(client_cert_der_3072, + sizeof_client_cert_der_3072, SSL_FILETYPE_ASN1); + keyLenBits = 3072; +#elif defined(USE_CERT_BUFFERS_4096) + XMEMCPY(tmp, client_key_der_4096, sizeof_client_key_der_4096); + cliKeySz = (long)sizeof_client_key_der_4096; + + x509 = wolfSSL_X509_load_certificate_buffer(client_cert_der_4096, + sizeof_client_cert_der_4096, SSL_FILETYPE_ASN1); + keyLenBits = 4096; +#else + XFILE f; + + f = XFOPEN(clientKey, "rb"); + + if (!f) { + err_sys("can't open ./certs/client-key.der, " + "Please run from wolfSSL home dir", -41); + return -8800; + } + + cliKeySz = (long)XFREAD(tmp, 1, FOURK_BUF, f); + XFCLOSE(f); + + /* using existing wolfSSL api to get public and private key */ + x509 = wolfSSL_X509_load_certificate_file(clientCert, SSL_FILETYPE_ASN1); +#endif /* USE_CERT_BUFFERS */ + clikey = tmp; + + if ((prvKey = EVP_PKEY_new()) == NULL) { + return -8801; + } + EVP_PKEY_free(prvKey); + prvKey = NULL; + + if (x509 == NULL) { + ret = -8802; + goto openssl_pkey1_test_done; + } + + pubKey = X509_get_pubkey(x509); + if (pubKey == NULL) { + ret = -8803; + goto openssl_pkey1_test_done; + } + + prvKey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &clikey, cliKeySz); + if (prvKey == NULL) { + ret = -8804; + goto openssl_pkey1_test_done; + } + + /* phase 2 API to create EVP_PKEY_CTX and encrypt/decrypt */ + if (EVP_PKEY_bits(prvKey) != keyLenBits) { + ret = -8805; + goto openssl_pkey1_test_done; + } + + if (EVP_PKEY_size(prvKey) != keyLenBits/8) { + ret = -8806; + goto openssl_pkey1_test_done; + } + + dec = EVP_PKEY_CTX_new(prvKey, NULL); + enc = EVP_PKEY_CTX_new(pubKey, NULL); + if (dec == NULL || enc == NULL) { + ret = -8807; + goto openssl_pkey1_test_done; + } + + if (EVP_PKEY_decrypt_init(dec) != 1) { + ret = -8808; + goto openssl_pkey1_test_done; + } + + if (EVP_PKEY_encrypt_init(enc) != 1) { + ret = -8809; + goto openssl_pkey1_test_done; + } + + if (EVP_PKEY_CTX_set_rsa_padding(dec, RSA_PKCS1_PADDING) <= 0) { + ret = -8810; + goto openssl_pkey1_test_done; + } + +#ifndef HAVE_FIPS + if (EVP_PKEY_CTX_set_rsa_padding(dec, RSA_PKCS1_OAEP_PADDING) <= 0){ + ret = -8811; + goto openssl_pkey1_test_done; + } + + if (EVP_PKEY_CTX_set_rsa_padding(enc, RSA_PKCS1_OAEP_PADDING) <= 0) { + ret = -8812; + goto openssl_pkey1_test_done; + } +#endif + + XMEMSET(cipher, 0, sizeof(cipher)); + outlen = keyLenBits/8; + if (EVP_PKEY_encrypt(enc, cipher, &outlen, msg, sizeof(msg)) < 0) { + ret = -8813; + goto openssl_pkey1_test_done; + } + + XMEMSET(plain, 0, sizeof(plain)); + if (EVP_PKEY_decrypt(dec, plain, &outlen, cipher, outlen) != 1) { + ret = -8814; + goto openssl_pkey1_test_done; + } + +openssl_pkey1_test_done: + if (pubKey != NULL) { + EVP_PKEY_free(pubKey); + } + if (prvKey != NULL) { + EVP_PKEY_free(prvKey); + } + if (dec != NULL) { + EVP_PKEY_CTX_free(dec); + } + if (enc != NULL) { + EVP_PKEY_CTX_free(enc); + } + if (x509 != NULL) { + X509_free(x509); + } + +#endif + return ret; +} + + +#define ERR_BASE_EVPSIG -5100 + +int openssl_evpSig_test(void) +{ +#if !defined(NO_RSA) && !defined(NO_SHA) && !defined(HAVE_USER_RSA) + byte* prvTmp; + byte* pubTmp; + int prvBytes; + int pubBytes; + RSA *prvRsa; + RSA *pubRsa; + EVP_PKEY *prvPkey; + EVP_PKEY *pubPkey; + + EVP_MD_CTX* sign; + EVP_MD_CTX* verf; + char msg[] = "see spot run"; + unsigned char sig[256]; + unsigned int sigSz; + const void* pt; + unsigned int count; + int ret, ret1, ret2; + + #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) + XFILE keyFile; + XFILE keypubFile; + char cliKey[] = "./certs/client-key.der"; + char cliKeypub[] = "./certs/client-keyPub.der"; + #endif + + prvTmp = (byte*)XMALLOC(FOURK_BUFF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (prvTmp == NULL) + return ERR_BASE_EVPSIG-1; + pubTmp = (byte*)XMALLOC(FOURK_BUFF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pubTmp == NULL) { + XFREE(prvTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return ERR_BASE_EVPSIG-2; + } + +#ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(prvTmp, client_key_der_1024, sizeof_client_key_der_1024); + prvBytes = sizeof_client_key_der_1024; + XMEMCPY(pubTmp, client_keypub_der_1024, sizeof_client_keypub_der_1024); + pubBytes = sizeof_client_keypub_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(prvTmp, client_key_der_2048, sizeof_client_key_der_2048); + prvBytes = sizeof_client_key_der_2048; + XMEMCPY(pubTmp, client_keypub_der_2048, sizeof_client_keypub_der_2048); + pubBytes = sizeof_client_keypub_der_2048; +#else + keyFile = XFOPEN(cliKey, "rb"); + if (!keyFile) { + XFREE(pubTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + XFREE(prvTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + err_sys("can't open ./certs/client-key.der, " + "Please run from wolfSSL home dir", -40); + return ERR_BASE_EVPSIG-3; + } + prvBytes = (int)XFREAD(prvTmp, 1, (int)FOURK_BUFF, keyFile); + XFCLOSE(keyFile); + keypubFile = XFOPEN(cliKeypub, "rb"); + if (!keypubFile) { + XFREE(pubTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + XFREE(prvTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + err_sys("can't open ./certs/client-cert.der, " + "Please run from wolfSSL home dir", -41); + return ERR_BASE_EVPSIG-4; + } + pubBytes = (int)XFREAD(pubTmp, 1, (int)FOURK_BUFF, keypubFile); + XFCLOSE(keypubFile); + #endif /* USE_CERT_BUFFERS */ + + prvRsa = wolfSSL_RSA_new(); + pubRsa = wolfSSL_RSA_new(); + if((prvRsa == NULL) || (pubRsa == NULL)){ + XFREE(pubTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + XFREE(prvTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + err_sys("ERROR with RSA_new", -8900); + return ERR_BASE_EVPSIG-5; + } + + ret1 = wolfSSL_RSA_LoadDer_ex(prvRsa, prvTmp, prvBytes, WOLFSSL_RSA_LOAD_PRIVATE); + ret2 = wolfSSL_RSA_LoadDer_ex(pubRsa, pubTmp, pubBytes, WOLFSSL_RSA_LOAD_PUBLIC); + if((ret1 != SSL_SUCCESS) || (ret2 != SSL_SUCCESS)){ + printf("error with RSA_LoadDer_ex\n"); + return ERR_BASE_EVPSIG-6; + } + + prvPkey = wolfSSL_EVP_PKEY_new(); + pubPkey = wolfSSL_EVP_PKEY_new(); + if((prvPkey == NULL) || (pubPkey == NULL)){ + XFREE(pubTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + XFREE(prvTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + printf("error with KEY_new\n"); + return ERR_BASE_EVPSIG-7; + } + ret1 = wolfSSL_EVP_PKEY_set1_RSA(prvPkey, prvRsa); + ret2 = wolfSSL_EVP_PKEY_set1_RSA(pubPkey, pubRsa); + if((ret1 != 1) || (ret2 != 1)){ + XFREE(pubTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + XFREE(prvTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + printf("error with EVP_PKEY_set1_RSA\n"); + return ERR_BASE_EVPSIG-8; + } + + /****************** sign and verify *******************/ + sign = EVP_MD_CTX_create(); + verf = EVP_MD_CTX_create(); + if((sign == NULL)||(verf == NULL)){ + printf("error with EVP_MD_CTX_create\n"); + return ERR_BASE_EVPSIG-10; + } + + ret = EVP_SignInit(sign, EVP_sha1()); + if(ret != SSL_SUCCESS){ + printf("error with EVP_SignInit\n"); + return ERR_BASE_EVPSIG-11; + } + + count = sizeof(msg); + show("message = ", (char *)msg, count); + + /* sign */ + XMEMSET(sig, 0, sizeof(sig)); + pt = (const void*)msg; + ret1 = EVP_SignUpdate(sign, pt, count); + ret2 = EVP_SignFinal(sign, sig, &sigSz, prvPkey); + if((ret1 != SSL_SUCCESS) || (ret2 != SSL_SUCCESS)){ + printf("error with EVP_MD_CTX_create\n"); + return ERR_BASE_EVPSIG-12; + } + show("signature = ", (char *)sig, sigSz); + + /* verify */ + pt = (const void*)msg; + ret1 = EVP_VerifyInit(verf, EVP_sha1()); + ret2 = EVP_VerifyUpdate(verf, pt, count); + if((ret1 != SSL_SUCCESS) || (ret2 != SSL_SUCCESS)){ + printf("error with EVP_Verify\n"); + return ERR_BASE_EVPSIG-13; + } + if (EVP_VerifyFinal(verf, sig, sigSz, pubPkey) != 1) { + XFREE(pubTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + XFREE(prvTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + printf("error with EVP_VerifyFinal\n"); + return ERR_BASE_EVPSIG-14; + } + + /* expect fail without update */ + EVP_VerifyInit(verf, EVP_sha1()); + if (EVP_VerifyFinal(verf, sig, sigSz, pubPkey) == 1) { + XFREE(pubTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + XFREE(prvTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + printf("EVP_VerifyInit without update not detected\n"); + return ERR_BASE_EVPSIG-15; + } + + XFREE(pubTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + XFREE(prvTmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + EVP_MD_CTX_destroy(sign); + EVP_MD_CTX_destroy(verf); + + wolfSSL_RSA_free(prvRsa); + wolfSSL_RSA_free(pubRsa); + EVP_PKEY_free(pubPkey); + EVP_PKEY_free(prvPkey); + +#endif /* NO_RSA */ + return 0; +} #endif /* OPENSSL_EXTRA */ #ifndef NO_PWDBASED +#ifdef HAVE_SCRYPT +/* Test vectors taken from RFC 7914: scrypt PBKDF - Section 12. */ +int scrypt_test(void) +{ + int ret; + byte derived[64]; + const byte verify1[] = { + 0x77, 0xd6, 0x57, 0x62, 0x38, 0x65, 0x7b, 0x20, + 0x3b, 0x19, 0xca, 0x42, 0xc1, 0x8a, 0x04, 0x97, + 0xf1, 0x6b, 0x48, 0x44, 0xe3, 0x07, 0x4a, 0xe8, + 0xdf, 0xdf, 0xfa, 0x3f, 0xed, 0xe2, 0x14, 0x42, + 0xfc, 0xd0, 0x06, 0x9d, 0xed, 0x09, 0x48, 0xf8, + 0x32, 0x6a, 0x75, 0x3a, 0x0f, 0xc8, 0x1f, 0x17, + 0xe8, 0xd3, 0xe0, 0xfb, 0x2e, 0x0d, 0x36, 0x28, + 0xcf, 0x35, 0xe2, 0x0c, 0x38, 0xd1, 0x89, 0x06 + }; + const byte verify2[] = { + 0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00, + 0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe, + 0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30, + 0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62, + 0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88, + 0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda, + 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, + 0xfd, 0xa8, 0xfb, 0xba, 0x90, 0x4f, 0x8e, 0x3e, + 0xa9, 0xb5, 0x43, 0xf6, 0x54, 0x5d, 0xa1, 0xf2, + 0xd5, 0x43, 0x29, 0x55, 0x61, 0x3f, 0x0f, 0xcf, + 0x62, 0xd4, 0x97, 0x05, 0x24, 0x2a, 0x9a, 0xf9, + 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. + */ + const byte verify4[] = { + 0x21, 0x01, 0xcb, 0x9b, 0x6a, 0x51, 0x1a, 0xae, + 0xad, 0xdb, 0xbe, 0x09, 0xcf, 0x70, 0xf8, 0x81, + 0xec, 0x56, 0x8d, 0x57, 0x4a, 0x2f, 0xfd, 0x4d, + 0xab, 0xe5, 0xee, 0x98, 0x20, 0xad, 0xaa, 0x47, + 0x8e, 0x56, 0xfd, 0x8f, 0x4b, 0xa5, 0xd0, 0x9f, + 0xfa, 0x1c, 0x6d, 0x92, 0x7c, 0x40, 0xf4, 0xc3, + 0x37, 0x30, 0x40, 0x49, 0xe8, 0xa9, 0x52, 0xfb, + 0xcb, 0xf4, 0x5c, 0x6f, 0xa7, 0x7a, 0x41, 0xa4 + }; +#endif + + ret = wc_scrypt(derived, NULL, 0, NULL, 0, 4, 1, 1, sizeof(verify1)); + if (ret != 0) + return -9000; + if (XMEMCMP(derived, verify1, sizeof(verify1)) != 0) + return -9001; + + ret = wc_scrypt(derived, (byte*)"password", 8, (byte*)"NaCl", 4, 10, 8, 16, + sizeof(verify2)); + if (ret != 0) + return -9002; + if (XMEMCMP(derived, verify2, sizeof(verify2)) != 0) + return -9003; + + /* 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 -9004; + if (XMEMCMP(derived, verify3, sizeof(verify3)) != 0) + return -9005; + +#ifdef SCRYPT_TEST_ALL + ret = wc_scrypt(derived, (byte*)"pleaseletmein", 13, + (byte*)"SodiumChloride", 14, 20, 8, 1, sizeof(verify4)); + if (ret != 0) + return -9006; + if (XMEMCMP(derived, verify4, sizeof(verify4)) != 0) + return -9007; +#endif +#endif /* !BENCH_EMBEDDED && !HAVE_INTEL_QA */ + + ret = wc_scrypt_ex(derived, (byte*)"password", 8, (byte*)"NaCl", 4, 1<<10, + 8, 16, sizeof(verify2)); + if (ret != 0) + return -9008; + if (XMEMCMP(derived, verify2, sizeof(verify2)) != 0) + return -9009; + + return 0; +} +#endif + +#ifdef HAVE_PKCS12 int pkcs12_test(void) { const byte passwd[] = { 0x00, 0x73, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x67, @@ -4676,27 +17370,33 @@ 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 -9100; - if ( (ret = memcmp(derived, verify, kLen)) != 0) - return -104; + if ( (ret = XMEMCMP(derived, verify, kLen)) != 0) + return -9101; 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 -9102; - if ( (ret = memcmp(derived, verify2, 24)) != 0) - return -106; + ret = wc_PKCS12_PBKDF_ex(derived, passwd2, sizeof(passwd2), salt2, 8, + iterations, kLen, WC_SHA256, id, HEAP_HINT); + if (ret < 0) + return -9103; + + if ( (ret = XMEMCMP(derived, verify2, 24)) != 0) + return -9104; return 0; } +#endif /* HAVE_PKCS12 */ - +#if defined(HAVE_PBKDF2) && !defined(NO_SHA256) int pbkdf2_test(void) { char passwd[] = "passwordpassword"; @@ -4710,19 +17410,20 @@ int pbkdf2_test(void) 0x2d, 0xd4, 0xf9, 0x37, 0xd4, 0x95, 0x16, 0xa7, 0x2a, 0x9a, 0x21, 0xd1 }; - int ret = wc_PBKDF2(derived, (byte*)passwd, (int)strlen(passwd), salt, 8, - iterations, kLen, SHA256); + int ret = wc_PBKDF2_ex(derived, (byte*)passwd, (int)XSTRLEN(passwd), salt, + (int)sizeof(salt), iterations, kLen, WC_SHA256, HEAP_HINT, devId); if (ret != 0) return ret; - if (memcmp(derived, verify, sizeof(verify)) != 0) - return -102; + if (XMEMCMP(derived, verify, sizeof(verify)) != 0) + return -9200; return 0; + } +#endif /* HAVE_PBKDF2 && !NO_SHA256 */ - -#ifndef NO_SHA +#if defined(HAVE_PBKDF1) && !defined(NO_SHA) int pbkdf1_test(void) { char passwd[] = "password"; @@ -4732,30 +17433,48 @@ int pbkdf1_test(void) byte derived[16]; const byte verify[] = { - 0xDC, 0x19, 0x84, 0x7E, 0x05, 0xC6, 0x4D, 0x2F, 0xAF, 0x10, 0xEB, 0xFB, - 0x4A, 0x3D, 0x2A, 0x20 + 0xDC, 0x19, 0x84, 0x7E, 0x05, 0xC6, 0x4D, 0x2F, + 0xAF, 0x10, 0xEB, 0xFB, 0x4A, 0x3D, 0x2A, 0x20 }; - wc_PBKDF1(derived, (byte*)passwd, (int)strlen(passwd), salt, 8, iterations, - kLen, SHA); + int ret = wc_PBKDF1_ex(derived, kLen, NULL, 0, (byte*)passwd, + (int)XSTRLEN(passwd), salt, (int)sizeof(salt), iterations, WC_SHA, + HEAP_HINT); + if (ret != 0) + return ret; - if (memcmp(derived, verify, sizeof(verify)) != 0) - return -101; + if (XMEMCMP(derived, verify, sizeof(verify)) != 0) + return -9300; return 0; } -#endif - +#endif /* HAVE_PBKDF2 && !NO_SHA */ int pwdbased_test(void) { int ret = 0; -#ifndef NO_SHA - ret += pbkdf1_test(); -#endif - ret += pbkdf2_test(); - return ret + pkcs12_test(); +#if defined(HAVE_PBKDF1) && !defined(NO_SHA) + ret = pbkdf1_test(); + if (ret != 0) + return ret; +#endif +#if defined(HAVE_PBKDF2) && !defined(NO_SHA256) + ret = pbkdf2_test(); + if (ret != 0) + return ret; +#endif +#ifdef HAVE_PKCS12 + ret = pkcs12_test(); + if (ret != 0) + return ret; +#endif +#ifdef HAVE_SCRYPT + ret = scrypt_test(); + if (ret != 0) + return ret; +#endif + return ret; } #endif /* NO_PWDBASED */ @@ -4807,40 +17526,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 -9500; - if (memcmp(okm1, res1, L) != 0) - return -2002; + if (XMEMCMP(okm1, res1, L) != 0) + return -9501; #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 -9502; - if (memcmp(okm1, res2, L) != 0) - return -2004; + if (XMEMCMP(okm1, res2, L) != 0) + return -9503; #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 -9504; - if (memcmp(okm1, res3, L) != 0) - return -2006; + if (XMEMCMP(okm1, res3, L) != 0) + return -9505; #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 -9506; - if (memcmp(okm1, res4, L) != 0) - return -2007; + if (XMEMCMP(okm1, res4, L) != 0) + return -9507; #endif /* HAVE_FIPS */ #endif /* NO_SHA256 */ @@ -4850,279 +17569,2553 @@ int hkdf_test(void) #endif /* HAVE_HKDF */ -#ifdef HAVE_ECC +#if defined(HAVE_ECC) && defined(HAVE_X963_KDF) -typedef struct rawEccVector { - const char* msg; - const char* Qx; - const char* Qy; - const char* d; - const char* R; - const char* S; - const char* curveName; - size_t msgLen; -} rawEccVector; - -int ecc_test(void) +int x963kdf_test(void) { - RNG rng; - byte sharedA[1024]; - byte sharedB[1024]; - byte sig[1024]; - byte digest[20]; - byte exportBuf[1024]; - word32 x, y; - int i, verify, ret; - ecc_key userA, userB, pubKey; + int ret; + byte kek[128]; - ret = wc_InitRng(&rng); - if (ret != 0) - return -1001; +#ifndef NO_SHA + /* SHA-1, COUNT = 0 + * shared secret length: 192 + * SharedInfo length: 0 + * key data length: 128 + */ + const byte Z[] = { + 0x1c, 0x7d, 0x7b, 0x5f, 0x05, 0x97, 0xb0, 0x3d, + 0x06, 0xa0, 0x18, 0x46, 0x6e, 0xd1, 0xa9, 0x3e, + 0x30, 0xed, 0x4b, 0x04, 0xdc, 0x64, 0xcc, 0xdd + }; - wc_ecc_init(&userA); - wc_ecc_init(&userB); - wc_ecc_init(&pubKey); - - ret = wc_ecc_make_key(&rng, 32, &userA); - - if (ret != 0) - return -1014; - - ret = wc_ecc_check_key(&userA); - if (ret != 0) - return -1024; - - ret = wc_ecc_make_key(&rng, 32, &userB); - - if (ret != 0) - return -1002; - - x = sizeof(sharedA); - ret = wc_ecc_shared_secret(&userA, &userB, sharedA, &x); - - if (ret != 0) - return -1015; - - y = sizeof(sharedB); - ret = wc_ecc_shared_secret(&userB, &userA, sharedB, &y); - - if (ret != 0) - return -1003; - - if (y != x) - return -1004; - - if (memcmp(sharedA, sharedB, x)) - return -1005; - - x = sizeof(exportBuf); - ret = wc_ecc_export_x963(&userA, exportBuf, &x); - if (ret != 0) - return -1006; - - ret = wc_ecc_import_x963(exportBuf, x, &pubKey); - - if (ret != 0) - return -1007; - - y = sizeof(sharedB); - ret = wc_ecc_shared_secret(&userB, &pubKey, sharedB, &y); - - if (ret != 0) - return -1008; - - if (memcmp(sharedA, sharedB, y)) - return -1009; - -#ifdef HAVE_COMP_KEY - /* try compressed export / import too */ - x = sizeof(exportBuf); - ret = wc_ecc_export_x963_ex(&userA, exportBuf, &x, 1); - if (ret != 0) - return -1010; - - wc_ecc_free(&pubKey); - wc_ecc_init(&pubKey); - ret = wc_ecc_import_x963(exportBuf, x, &pubKey); - - if (ret != 0) - return -1011; + const byte verify[] = { + 0xbf, 0x71, 0xdf, 0xfd, 0x8f, 0x4d, 0x99, 0x22, + 0x39, 0x36, 0xbe, 0xb4, 0x6f, 0xee, 0x8c, 0xcc + }; #endif - y = sizeof(sharedB); - ret = wc_ecc_shared_secret(&userB, &pubKey, sharedB, &y); +#ifndef NO_SHA256 + /* SHA-256, COUNT = 3 + * shared secret length: 192 + * SharedInfo length: 0 + * key data length: 128 + */ + const byte Z2[] = { + 0xd3, 0x8b, 0xdb, 0xe5, 0xc4, 0xfc, 0x16, 0x4c, + 0xdd, 0x96, 0x7f, 0x63, 0xc0, 0x4f, 0xe0, 0x7b, + 0x60, 0xcd, 0xe8, 0x81, 0xc2, 0x46, 0x43, 0x8c + }; + const byte verify2[] = { + 0x5e, 0x67, 0x4d, 0xb9, 0x71, 0xba, 0xc2, 0x0a, + 0x80, 0xba, 0xd0, 0xd4, 0x51, 0x4d, 0xc4, 0x84 + }; +#endif + +#ifdef WOLFSSL_SHA512 + /* SHA-512, COUNT = 0 + * shared secret length: 192 + * SharedInfo length: 0 + * key data length: 128 + */ + const byte Z3[] = { + 0x87, 0xfc, 0x0d, 0x8c, 0x44, 0x77, 0x48, 0x5b, + 0xb5, 0x74, 0xf5, 0xfc, 0xea, 0x26, 0x4b, 0x30, + 0x88, 0x5d, 0xc8, 0xd9, 0x0a, 0xd8, 0x27, 0x82 + }; + + const byte verify3[] = { + 0x94, 0x76, 0x65, 0xfb, 0xb9, 0x15, 0x21, 0x53, + 0xef, 0x46, 0x02, 0x38, 0x50, 0x6a, 0x02, 0x45 + }; + + /* SHA-512, COUNT = 0 + * shared secret length: 521 + * SharedInfo length: 128 + * key data length: 1024 + */ + const byte Z4[] = { + 0x00, 0xaa, 0x5b, 0xb7, 0x9b, 0x33, 0xe3, 0x89, + 0xfa, 0x58, 0xce, 0xad, 0xc0, 0x47, 0x19, 0x7f, + 0x14, 0xe7, 0x37, 0x12, 0xf4, 0x52, 0xca, 0xa9, + 0xfc, 0x4c, 0x9a, 0xdb, 0x36, 0x93, 0x48, 0xb8, + 0x15, 0x07, 0x39, 0x2f, 0x1a, 0x86, 0xdd, 0xfd, + 0xb7, 0xc4, 0xff, 0x82, 0x31, 0xc4, 0xbd, 0x0f, + 0x44, 0xe4, 0x4a, 0x1b, 0x55, 0xb1, 0x40, 0x47, + 0x47, 0xa9, 0xe2, 0xe7, 0x53, 0xf5, 0x5e, 0xf0, + 0x5a, 0x2d + }; + + const byte info4[] = { + 0xe3, 0xb5, 0xb4, 0xc1, 0xb0, 0xd5, 0xcf, 0x1d, + 0x2b, 0x3a, 0x2f, 0x99, 0x37, 0x89, 0x5d, 0x31 + }; + + const byte verify4[] = { + 0x44, 0x63, 0xf8, 0x69, 0xf3, 0xcc, 0x18, 0x76, + 0x9b, 0x52, 0x26, 0x4b, 0x01, 0x12, 0xb5, 0x85, + 0x8f, 0x7a, 0xd3, 0x2a, 0x5a, 0x2d, 0x96, 0xd8, + 0xcf, 0xfa, 0xbf, 0x7f, 0xa7, 0x33, 0x63, 0x3d, + 0x6e, 0x4d, 0xd2, 0xa5, 0x99, 0xac, 0xce, 0xb3, + 0xea, 0x54, 0xa6, 0x21, 0x7c, 0xe0, 0xb5, 0x0e, + 0xef, 0x4f, 0x6b, 0x40, 0xa5, 0xc3, 0x02, 0x50, + 0xa5, 0xa8, 0xee, 0xee, 0x20, 0x80, 0x02, 0x26, + 0x70, 0x89, 0xdb, 0xf3, 0x51, 0xf3, 0xf5, 0x02, + 0x2a, 0xa9, 0x63, 0x8b, 0xf1, 0xee, 0x41, 0x9d, + 0xea, 0x9c, 0x4f, 0xf7, 0x45, 0xa2, 0x5a, 0xc2, + 0x7b, 0xda, 0x33, 0xca, 0x08, 0xbd, 0x56, 0xdd, + 0x1a, 0x59, 0xb4, 0x10, 0x6c, 0xf2, 0xdb, 0xbc, + 0x0a, 0xb2, 0xaa, 0x8e, 0x2e, 0xfa, 0x7b, 0x17, + 0x90, 0x2d, 0x34, 0x27, 0x69, 0x51, 0xce, 0xcc, + 0xab, 0x87, 0xf9, 0x66, 0x1c, 0x3e, 0x88, 0x16 + }; +#endif + +#ifndef NO_SHA + ret = wc_X963_KDF(WC_HASH_TYPE_SHA, Z, sizeof(Z), NULL, 0, + kek, sizeof(verify)); if (ret != 0) - return -1012; + return -9600; - if (memcmp(sharedA, sharedB, y)) - return -1013; - - /* test DSA sign hash */ - for (i = 0; i < (int)sizeof(digest); i++) - digest[i] = (byte)i; - - x = sizeof(sig); - ret = wc_ecc_sign_hash(digest, sizeof(digest), sig, &x, &rng, &userA); + if (XMEMCMP(verify, kek, sizeof(verify)) != 0) + return -9601; +#endif +#ifndef NO_SHA256 + ret = wc_X963_KDF(WC_HASH_TYPE_SHA256, Z2, sizeof(Z2), NULL, 0, + kek, sizeof(verify2)); if (ret != 0) - return -1014; + return -9602; - verify = 0; - ret = wc_ecc_verify_hash(sig, x, digest, sizeof(digest), &verify, &userA); + if (XMEMCMP(verify2, kek, sizeof(verify2)) != 0) + return -9603; +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_X963_KDF(WC_HASH_TYPE_SHA512, Z3, sizeof(Z3), NULL, 0, + kek, sizeof(verify3)); if (ret != 0) - return -1015; + return -9604; - if (verify != 1) - return -1016; + if (XMEMCMP(verify3, kek, sizeof(verify3)) != 0) + return -9605; - x = sizeof(exportBuf); - ret = wc_ecc_export_private_only(&userA, exportBuf, &x); + ret = wc_X963_KDF(WC_HASH_TYPE_SHA512, Z4, sizeof(Z4), info4, + sizeof(info4), kek, sizeof(verify4)); if (ret != 0) - return -1017; + return -9606; -#if !defined(NO_SHA) && \ - ((defined(HAVE_ECC192) && defined(HAVE_ECC224)) || defined(HAVE_ALL_CURVES)) - { - /* test raw ECC key import */ - Sha sha; - byte hash[SHA_DIGEST_SIZE]; - rawEccVector a, b; - rawEccVector test_ecc[2]; - int times = sizeof(test_ecc) / sizeof(rawEccVector); - - /* first [P-192,SHA-1] vector from FIPS 186-3 NIST vectors */ - a.msg = "\xeb\xf7\x48\xd7\x48\xeb\xbc\xa7\xd2\x9f\xb4\x73\x69\x8a" - "\x6e\x6b\x4f\xb1\x0c\x86\x5d\x4a\xf0\x24\xcc\x39\xae\x3d" - "\xf3\x46\x4b\xa4\xf1\xd6\xd4\x0f\x32\xbf\x96\x18\xa9\x1b" - "\xb5\x98\x6f\xa1\xa2\xaf\x04\x8a\x0e\x14\xdc\x51\xe5\x26" - "\x7e\xb0\x5e\x12\x7d\x68\x9d\x0a\xc6\xf1\xa7\xf1\x56\xce" - "\x06\x63\x16\xb9\x71\xcc\x7a\x11\xd0\xfd\x7a\x20\x93\xe2" - "\x7c\xf2\xd0\x87\x27\xa4\xe6\x74\x8c\xc3\x2f\xd5\x9c\x78" - "\x10\xc5\xb9\x01\x9d\xf2\x1c\xdc\xc0\xbc\xa4\x32\xc0\xa3" - "\xee\xd0\x78\x53\x87\x50\x88\x77\x11\x43\x59\xce\xe4\xa0" - "\x71\xcf"; - a.msgLen = 128; - a.Qx = "07008ea40b08dbe76432096e80a2494c94982d2d5bcf98e6"; - a.Qy = "76fab681d00b414ea636ba215de26d98c41bd7f2e4d65477"; - a.d = "e14f37b3d1374ff8b03f41b9b3fdd2f0ebccf275d660d7f3"; - a.R = "6994d962bdd0d793ffddf855ec5bf2f91a9698b46258a63e"; - a.S = "02ba6465a234903744ab02bc8521405b73cf5fc00e1a9f41"; - a.curveName = "ECC-192"; - - /* first [P-224,SHA-1] vector from FIPS 186-3 NIST vectors */ - b.msg = "\x36\xc8\xb2\x29\x86\x48\x7f\x67\x7c\x18\xd0\x97\x2a\x9e" - "\x20\x47\xb3\xaf\xa5\x9e\xc1\x62\x76\x4e\xc3\x0b\x5b\x69" - "\xe0\x63\x0f\x99\x0d\x4e\x05\xc2\x73\xb0\xe5\xa9\xd4\x28" - "\x27\xb6\x95\xfc\x2d\x64\xd9\x13\x8b\x1c\xf4\xc1\x21\x55" - "\x89\x4c\x42\x13\x21\xa7\xbb\x97\x0b\xdc\xe0\xfb\xf0\xd2" - "\xae\x85\x61\xaa\xd8\x71\x7f\x2e\x46\xdf\xe3\xff\x8d\xea" - "\xb4\xd7\x93\x23\x56\x03\x2c\x15\x13\x0d\x59\x9e\x26\xc1" - "\x0f\x2f\xec\x96\x30\x31\xac\x69\x38\xa1\x8d\x66\x45\x38" - "\xb9\x4d\xac\x55\x34\xef\x7b\x59\x94\x24\xd6\x9b\xe1\xf7" - "\x1c\x20"; - b.msgLen = 128; - b.Qx = "8a4dca35136c4b70e588e23554637ae251077d1365a6ba5db9585de7"; - b.Qy = "ad3dee06de0be8279d4af435d7245f14f3b4f82eb578e519ee0057b1"; - b.d = "97c4b796e1639dd1035b708fc00dc7ba1682cec44a1002a1a820619f"; - b.R = "147b33758321e722a0360a4719738af848449e2c1d08defebc1671a7"; - b.S = "24fc7ed7f1352ca3872aa0916191289e2e04d454935d50fe6af3ad5b"; - b.curveName = "ECC-224"; - - test_ecc[0] = a; - test_ecc[1] = b; - - for (i = 0; i < times; i++) { - - wc_ecc_free(&userA); - wc_ecc_init(&userA); - - memset(sig, 0, sizeof(sig)); - x = sizeof(sig); - - /* calculate SHA-1 hash of message */ - ret = wc_InitSha(&sha); - if (ret != 0) - return -1015 - i; - - wc_ShaUpdate(&sha, (byte*)test_ecc[i].msg, (word32)test_ecc[i].msgLen); - wc_ShaFinal(&sha, hash); - - ret = wc_ecc_import_raw(&userA, test_ecc[i].Qx, test_ecc[i].Qy, - test_ecc[i].d, test_ecc[i].curveName); - if (ret != 0) - return -1017 - i; - - ret = wc_ecc_rs_to_sig(test_ecc[i].R, test_ecc[i].S, sig, &x); - if (ret != 0) - return -1019 - i; - - ret = wc_ecc_verify_hash(sig, x, hash, sizeof(hash), &verify, &userA); - if (ret != 0) - return -1021 - i; - - if (verify != 1) - return -1023 - i; - } - } -#endif /* defined(HAVE_ECC192) && defined(HAVE_ECC256) */ - - -#ifdef WOLFSSL_KEY_GEN - { - int derSz, pemSz; - byte der[FOURK_BUF]; - byte pem[FOURK_BUF]; - FILE* keyFile; - FILE* pemFile; - - derSz = wc_EccKeyToDer(&userB, der, FOURK_BUF); - if (derSz < 0) { - return -1024; - } - - keyFile = fopen("./ecc-key.der", "wb"); - if (!keyFile) { - return -1025; - } - ret = (int)fwrite(der, 1, derSz, keyFile); - fclose(keyFile); - if (ret != derSz) { - return -1026; - } - - pemSz = wc_DerToPem(der, derSz, pem, FOURK_BUF, ECC_PRIVATEKEY_TYPE); - if (pemSz < 0) { - return -1027; - } - - pemFile = fopen("./ecc-key.pem", "wb"); - if (!pemFile) { - return -1028; - } - ret = (int)fwrite(pem, 1, pemSz, pemFile); - fclose(pemFile); - if (ret != pemSz) { - return -1029; - } - } -#endif /* WOLFSSL_KEY_GEN */ - - wc_ecc_free(&pubKey); - wc_ecc_free(&userB); - wc_ecc_free(&userA); - wc_FreeRng(&rng); + if (XMEMCMP(verify4, kek, sizeof(verify4)) != 0) + return -9607; +#endif return 0; } -#ifdef HAVE_ECC_ENCRYPT +#endif /* HAVE_X963_KDF */ + + +#ifdef HAVE_ECC + +#ifdef BENCH_EMBEDDED + #define ECC_SHARED_SIZE 128 +#else + #define ECC_SHARED_SIZE MAX_ECC_BYTES +#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) ||\ + defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) + #define HAVE_ECC_VECTOR_TEST + #endif +#endif + +#ifdef HAVE_ECC_VECTOR_TEST +typedef struct eccVector { + const char* msg; /* SHA-1 Encoded Message */ + const char* Qx; + const char* Qy; + const char* d; /* Private Key */ + const char* R; + const char* S; + const char* curveName; + word32 msgLen; + word32 keySize; +#ifndef NO_ASN + const byte* r; + word32 rSz; + const byte* s; + word32 sSz; +#endif +} eccVector; + +static int ecc_test_vector_item(const eccVector* vector) +{ + int ret = 0, verify = 0; + word32 sigSz; + ecc_key userA; + DECLARE_VAR(sig, byte, ECC_SIG_SIZE, HEAP_HINT); +#if !defined(NO_ASN) && !defined(HAVE_SELFTEST) + word32 sigRawSz; + DECLARE_VAR(sigRaw, byte, ECC_SIG_SIZE, HEAP_HINT); +#endif + + ret = wc_ecc_init_ex(&userA, HEAP_HINT, devId); + if (ret != 0) { + FREE_VAR(sig, HEAP_HINT); + return ret; + } + + ret = wc_ecc_import_raw(&userA, vector->Qx, vector->Qy, + vector->d, vector->curveName); + if (ret != 0) + goto done; + + XMEMSET(sig, 0, ECC_SIG_SIZE); + sigSz = ECC_SIG_SIZE; + ret = wc_ecc_rs_to_sig(vector->R, vector->S, sig, &sigSz); + if (ret != 0) + goto done; + +#if !defined(NO_ASN) && !defined(HAVE_SELFTEST) + XMEMSET(sigRaw, 0, ECC_SIG_SIZE); + sigRawSz = ECC_SIG_SIZE; + ret = wc_ecc_rs_raw_to_sig(vector->r, vector->rSz, vector->s, vector->sSz, + sigRaw, &sigRawSz); + if (ret != 0) + goto done; + + if (sigSz != sigRawSz || XMEMCMP(sig, sigRaw, sigSz) != 0) { + ret = -9608; + goto done; + } +#endif + + 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, sigSz, (byte*)vector->msg, + vector->msgLen, &verify, &userA); + } while (ret == WC_PENDING_E); + if (ret != 0) + goto done; + TEST_SLEEP(); + + if (verify != 1) + ret = -9609; + +done: + wc_ecc_free(&userA); + +#if !defined(NO_ASN) && !defined(HAVE_SELFTEST) + FREE_VAR(sigRaw, HEAP_HINT); +#endif + FREE_VAR(sig, HEAP_HINT); + + return ret; +} + +static int ecc_test_vector(int keySize) +{ + int ret; + eccVector vec; + + XMEMSET(&vec, 0, sizeof(vec)); + vec.keySize = (word32)keySize; + + switch(keySize) { + +#if defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES) + case 14: + return 0; +#endif /* HAVE_ECC112 */ +#if defined(HAVE_ECC128) || defined(HAVE_ALL_CURVES) + case 16: + return 0; +#endif /* HAVE_ECC128 */ +#if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + case 20: + return 0; +#endif /* HAVE_ECC160 */ + +#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + case 24: + /* first [P-192,SHA-1] vector from FIPS 186-3 NIST vectors */ + #if 1 + vec.msg = "\x60\x80\x79\x42\x3f\x12\x42\x1d\xe6\x16\xb7\x49\x3e\xbe\x55\x1c\xf4\xd6\x5b\x92"; + vec.msgLen = 20; + #else + /* This is the raw message prior to SHA-1 */ + vec.msg = + "\xeb\xf7\x48\xd7\x48\xeb\xbc\xa7\xd2\x9f\xb4\x73\x69\x8a\x6e\x6b" + "\x4f\xb1\x0c\x86\x5d\x4a\xf0\x24\xcc\x39\xae\x3d\xf3\x46\x4b\xa4" + "\xf1\xd6\xd4\x0f\x32\xbf\x96\x18\xa9\x1b\xb5\x98\x6f\xa1\xa2\xaf" + "\x04\x8a\x0e\x14\xdc\x51\xe5\x26\x7e\xb0\x5e\x12\x7d\x68\x9d\x0a" + "\xc6\xf1\xa7\xf1\x56\xce\x06\x63\x16\xb9\x71\xcc\x7a\x11\xd0\xfd" + "\x7a\x20\x93\xe2\x7c\xf2\xd0\x87\x27\xa4\xe6\x74\x8c\xc3\x2f\xd5" + "\x9c\x78\x10\xc5\xb9\x01\x9d\xf2\x1c\xdc\xc0\xbc\xa4\x32\xc0\xa3" + "\xee\xd0\x78\x53\x87\x50\x88\x77\x11\x43\x59\xce\xe4\xa0\x71\xcf"; + vec.msgLen = 128; + #endif + vec.Qx = "07008ea40b08dbe76432096e80a2494c94982d2d5bcf98e6"; + vec.Qy = "76fab681d00b414ea636ba215de26d98c41bd7f2e4d65477"; + vec.d = "e14f37b3d1374ff8b03f41b9b3fdd2f0ebccf275d660d7f3"; + vec.R = "6994d962bdd0d793ffddf855ec5bf2f91a9698b46258a63e"; + vec.S = "02ba6465a234903744ab02bc8521405b73cf5fc00e1a9f41"; + vec.curveName = "SECP192R1"; + #ifndef NO_ASN + vec.r = (byte*)"\x69\x94\xd9\x62\xbd\xd0\xd7\x93\xff\xdd\xf8\x55" + "\xec\x5b\xf2\xf9\x1a\x96\x98\xb4\x62\x58\xa6\x3e"; + vec.rSz = 24; + vec.s = (byte*)"\x02\xba\x64\x65\xa2\x34\x90\x37\x44\xab\x02\xbc" + "\x85\x21\x40\x5b\x73\xcf\x5f\xc0\x0e\x1a\x9f\x41"; + vec.sSz = 24; + #endif + break; +#endif /* HAVE_ECC192 */ + +#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + case 28: + /* first [P-224,SHA-1] vector from FIPS 186-3 NIST vectors */ + #if 1 + vec.msg = "\xb9\xa3\xb8\x6d\xb0\xba\x99\xfd\xc6\xd2\x94\x6b\xfe\xbe\x9c\xe8\x3f\x10\x74\xfc"; + vec.msgLen = 20; + #else + /* This is the raw message prior to SHA-1 */ + vec.msg = + "\x36\xc8\xb2\x29\x86\x48\x7f\x67\x7c\x18\xd0\x97\x2a\x9e\x20\x47" + "\xb3\xaf\xa5\x9e\xc1\x62\x76\x4e\xc3\x0b\x5b\x69\xe0\x63\x0f\x99" + "\x0d\x4e\x05\xc2\x73\xb0\xe5\xa9\xd4\x28\x27\xb6\x95\xfc\x2d\x64" + "\xd9\x13\x8b\x1c\xf4\xc1\x21\x55\x89\x4c\x42\x13\x21\xa7\xbb\x97" + "\x0b\xdc\xe0\xfb\xf0\xd2\xae\x85\x61\xaa\xd8\x71\x7f\x2e\x46\xdf" + "\xe3\xff\x8d\xea\xb4\xd7\x93\x23\x56\x03\x2c\x15\x13\x0d\x59\x9e" + "\x26\xc1\x0f\x2f\xec\x96\x30\x31\xac\x69\x38\xa1\x8d\x66\x45\x38" + "\xb9\x4d\xac\x55\x34\xef\x7b\x59\x94\x24\xd6\x9b\xe1\xf7\x1c\x20"; + vec.msgLen = 128; + #endif + vec.Qx = "8a4dca35136c4b70e588e23554637ae251077d1365a6ba5db9585de7"; + vec.Qy = "ad3dee06de0be8279d4af435d7245f14f3b4f82eb578e519ee0057b1"; + vec.d = "97c4b796e1639dd1035b708fc00dc7ba1682cec44a1002a1a820619f"; + vec.R = "147b33758321e722a0360a4719738af848449e2c1d08defebc1671a7"; + vec.S = "24fc7ed7f1352ca3872aa0916191289e2e04d454935d50fe6af3ad5b"; + vec.curveName = "SECP224R1"; + #ifndef NO_ASN + vec.r = (byte*)"\x14\x7b\x33\x75\x83\x21\xe7\x22\xa0\x36\x0a\x47" + "\x19\x73\x8a\xf8\x48\x44\x9e\x2c\x1d\x08\xde\xfe" + "\xbc\x16\x71\xa7"; + vec.rSz = 28; + vec.s = (byte*)"\x24\xfc\x7e\xd7\xf1\x35\x2c\xa3\x87\x2a\xa0\x91" + "\x61\x91\x28\x9e\x2e\x04\xd4\x54\x93\x5d\x50\xfe" + "\x6a\xf3\xad\x5b"; + vec.sSz = 28; + #endif + break; +#endif /* HAVE_ECC224 */ + +#if defined(HAVE_ECC239) || defined(HAVE_ALL_CURVES) + case 30: + return 0; +#endif /* HAVE_ECC239 */ + +#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + case 32: + /* first [P-256,SHA-1] vector from FIPS 186-3 NIST vectors */ + #if 1 + vec.msg = "\xa3\xf9\x1a\xe2\x1b\xa6\xb3\x03\x98\x64\x47\x2f\x18\x41\x44\xc6\xaf\x62\xcd\x0e"; + vec.msgLen = 20; + #else + /* This is the raw message prior to SHA-1 */ + vec.msg = + "\xa2\x4b\x21\x76\x2e\x6e\xdb\x15\x3c\xc1\x14\x38\xdb\x0e\x92\xcd" + "\xf5\x2b\x86\xb0\x6c\xa9\x70\x16\x06\x27\x59\xc7\x0d\x36\xd1\x56" + "\x2c\xc9\x63\x0d\x7f\xc7\xc7\x74\xb2\x8b\x54\xe3\x1e\xf5\x58\x72" + "\xb2\xa6\x5d\xf1\xd7\xec\x26\xde\xbb\x33\xe7\xd9\x27\xef\xcc\xf4" + "\x6b\x63\xde\x52\xa4\xf4\x31\xea\xca\x59\xb0\x5d\x2e\xde\xc4\x84" + "\x5f\xff\xc0\xee\x15\x03\x94\xd6\x1f\x3d\xfe\xcb\xcd\xbf\x6f\x5a" + "\x73\x38\xd0\xbe\x3f\x2a\x77\x34\x51\x98\x3e\xba\xeb\x48\xf6\x73" + "\x8f\xc8\x95\xdf\x35\x7e\x1a\x48\xa6\x53\xbb\x35\x5a\x31\xa1\xb4" + vec.msgLen = 128; + #endif + vec.Qx = "fa2737fb93488d19caef11ae7faf6b7f4bcd67b286e3fc54e8a65c2b74aeccb0"; + vec.Qy = "d4ccd6dae698208aa8c3a6f39e45510d03be09b2f124bfc067856c324f9b4d09"; + vec.d = "be34baa8d040a3b991f9075b56ba292f755b90e4b6dc10dad36715c33cfdac25"; + vec.R = "2b826f5d44e2d0b6de531ad96b51e8f0c56fdfead3c236892e4d84eacfc3b75c"; + vec.S = "a2248b62c03db35a7cd63e8a120a3521a89d3d2f61ff99035a2148ae32e3a248"; + #ifndef NO_ASN + vec.r = (byte*)"\x2b\x82\x6f\x5d\x44\xe2\xd0\xb6\xde\x53\x1a\xd9" + "\x6b\x51\xe8\xf0\xc5\x6f\xdf\xea\xd3\xc2\x36\x89" + "\x2e\x4d\x84\xea\xcf\xc3\xb7\x5c"; + vec.rSz = 32; + vec.s = (byte*)"\xa2\x24\x8b\x62\xc0\x3d\xb3\x5a\x7c\xd6\x3e\x8a" + "\x12\x0a\x35\x21\xa8\x9d\x3d\x2f\x61\xff\x99\x03" + "\x5a\x21\x48\xae\x32\xe3\xa2\x48"; + vec.sSz = 32; + #endif + vec.curveName = "SECP256R1"; + break; +#endif /* !NO_ECC256 */ + +#if defined(HAVE_ECC320) || defined(HAVE_ALL_CURVES) + case 40: + return 0; +#endif /* HAVE_ECC320 */ + +#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + case 48: + /* first [P-384,SHA-1] vector from FIPS 186-3 NIST vectors */ + #if 1 + vec.msg = "\x9b\x9f\x8c\x95\x35\xa5\xca\x26\x60\x5d\xb7\xf2\xfa\x57\x3b\xdf\xc3\x2e\xab\x8b"; + vec.msgLen = 20; + #else + /* This is the raw message prior to SHA-1 */ + vec.msg = + "\xab\xe1\x0a\xce\x13\xe7\xe1\xd9\x18\x6c\x48\xf7\x88\x9d\x51\x47" + "\x3d\x3a\x09\x61\x98\x4b\xc8\x72\xdf\x70\x8e\xcc\x3e\xd3\xb8\x16" + "\x9d\x01\xe3\xd9\x6f\xc4\xf1\xd5\xea\x00\xa0\x36\x92\xbc\xc5\xcf" + "\xfd\x53\x78\x7c\x88\xb9\x34\xaf\x40\x4c\x03\x9d\x32\x89\xb5\xba" + "\xc5\xae\x7d\xb1\x49\x68\x75\xb5\xdc\x73\xc3\x09\xf9\x25\xc1\x3d" + "\x1c\x01\xab\xda\xaf\xeb\xcd\xac\x2c\xee\x43\x39\x39\xce\x8d\x4a" + "\x0a\x5d\x57\xbb\x70\x5f\x3b\xf6\xec\x08\x47\x95\x11\xd4\xb4\xa3" + "\x21\x1f\x61\x64\x9a\xd6\x27\x43\x14\xbf\x0d\x43\x8a\x81\xe0\x60" + vec.msgLen = 128; + #endif + vec.Qx = "e55fee6c49d8d523f5ce7bf9c0425ce4ff650708b7de5cfb095901523979a7f042602db30854735369813b5c3f5ef868"; + vec.Qy = "28f59cc5dc509892a988d38a8e2519de3d0c4fd0fbdb0993e38f18506c17606c5e24249246f1ce94983a5361c5be983e"; + vec.d = "a492ce8fa90084c227e1a32f7974d39e9ff67a7e8705ec3419b35fb607582bebd461e0b1520ac76ec2dd4e9b63ebae71"; + vec.R = "6820b8585204648aed63bdff47f6d9acebdea62944774a7d14f0e14aa0b9a5b99545b2daee6b3c74ebf606667a3f39b7"; + vec.S = "491af1d0cccd56ddd520b233775d0bc6b40a6255cc55207d8e9356741f23c96c14714221078dbd5c17f4fdd89b32a907"; + vec.curveName = "SECP384R1"; + #ifndef NO_ASN + vec.r = (byte*)"\x68\x20\xb8\x58\x52\x04\x64\x8a\xed\x63\xbd\xff" + "\x47\xf6\xd9\xac\xeb\xde\xa6\x29\x44\x77\x4a\x7d" + "\x14\xf0\xe1\x4a\xa0\xb9\xa5\xb9\x95\x45\xb2\xda" + "\xee\x6b\x3c\x74\xeb\xf6\x06\x66\x7a\x3f\x39\xb7"; + vec.rSz = 48; + vec.s = (byte*)"\x49\x1a\xf1\xd0\xcc\xcd\x56\xdd\xd5\x20\xb2\x33" + "\x77\x5d\x0b\xc6\xb4\x0a\x62\x55\xcc\x55\x20\x7d" + "\x8e\x93\x56\x74\x1f\x23\xc9\x6c\x14\x71\x42\x21" + "\x07\x8d\xbd\x5c\x17\xf4\xfd\xd8\x9b\x32\xa9\x07"; + vec.sSz = 48; + #endif + break; +#endif /* HAVE_ECC384 */ + +#if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + case 64: + return 0; +#endif /* HAVE_ECC512 */ + +#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + case 66: + /* first [P-521,SHA-1] vector from FIPS 186-3 NIST vectors */ + #if 1 + vec.msg = "\x1b\xf7\x03\x9c\xca\x23\x94\x27\x3f\x11\xa1\xd4\x8d\xcc\xb4\x46\x6f\x31\x61\xdf"; + vec.msgLen = 20; + #else + /* This is the raw message prior to SHA-1 */ + vec.msg = + "\x50\x3f\x79\x39\x34\x0a\xc7\x23\xcd\x4a\x2f\x4e\x6c\xcc\x27\x33" + "\x38\x3a\xca\x2f\xba\x90\x02\x19\x9d\x9e\x1f\x94\x8b\xe0\x41\x21" + "\x07\xa3\xfd\xd5\x14\xd9\x0c\xd4\xf3\x7c\xc3\xac\x62\xef\x00\x3a" + "\x2d\xb1\xd9\x65\x7a\xb7\x7f\xe7\x55\xbf\x71\xfa\x59\xe4\xd9\x6e" + "\xa7\x2a\xe7\xbf\x9d\xe8\x7d\x79\x34\x3b\xc1\xa4\xbb\x14\x4d\x16" + "\x28\xd1\xe9\xe9\xc8\xed\x80\x8b\x96\x2c\x54\xe5\xf9\x6d\x53\xda" + "\x14\x7a\x96\x38\xf9\x4a\x91\x75\xd8\xed\x61\x05\x5f\x0b\xa5\x73" + "\xa8\x2b\xb7\xe0\x18\xee\xda\xc4\xea\x7b\x36\x2e\xc8\x9c\x38\x2b" + vec.msgLen = 128; + #endif + vec.Qx = "12fbcaeffa6a51f3ee4d3d2b51c5dec6d7c726ca353fc014ea2bf7cfbb9b910d32cbfa6a00fe39b6cdb8946f22775398b2e233c0cf144d78c8a7742b5c7a3bb5d23"; + vec.Qy = "09cdef823dd7bf9a79e8cceacd2e4527c231d0ae5967af0958e931d7ddccf2805a3e618dc3039fec9febbd33052fe4c0fee98f033106064982d88f4e03549d4a64d"; + vec.d = "1bd56bd106118eda246155bd43b42b8e13f0a6e25dd3bb376026fab4dc92b6157bc6dfec2d15dd3d0cf2a39aa68494042af48ba9601118da82c6f2108a3a203ad74"; + vec.R = "0bd117b4807710898f9dd7778056485777668f0e78e6ddf5b000356121eb7a220e9493c7f9a57c077947f89ac45d5acb6661bbcd17abb3faea149ba0aa3bb1521be"; + vec.S = "019cd2c5c3f9870ecdeb9b323abdf3a98cd5e231d85c6ddc5b71ab190739f7f226e6b134ba1d5889ddeb2751dabd97911dff90c34684cdbe7bb669b6c3d22f2480c"; + vec.curveName = "SECP521R1"; + #ifndef NO_ASN + vec.r = (byte*)"\x00\xbd\x11\x7b\x48\x07\x71\x08\x98\xf9\xdd\x77" + "\x78\x05\x64\x85\x77\x76\x68\xf0\xe7\x8e\x6d\xdf" + "\x5b\x00\x03\x56\x12\x1e\xb7\xa2\x20\xe9\x49\x3c" + "\x7f\x9a\x57\xc0\x77\x94\x7f\x89\xac\x45\xd5\xac" + "\xb6\x66\x1b\xbc\xd1\x7a\xbb\x3f\xae\xa1\x49\xba" + "\x0a\xa3\xbb\x15\x21\xbe"; + vec.rSz = 66; + vec.s = (byte*)"\x00\x19\xcd\x2c\x5c\x3f\x98\x70\xec\xde\xb9\xb3" + "\x23\xab\xdf\x3a\x98\xcd\x5e\x23\x1d\x85\xc6\xdd" + "\xc5\xb7\x1a\xb1\x90\x73\x9f\x7f\x22\x6e\x6b\x13" + "\x4b\xa1\xd5\x88\x9d\xde\xb2\x75\x1d\xab\xd9\x79" + "\x11\xdf\xf9\x0c\x34\x68\x4c\xdb\xe7\xbb\x66\x9b" + "\x6c\x3d\x22\xf2\x48\x0c"; + vec.sSz = 66; + #endif + break; +#endif /* HAVE_ECC521 */ + default: + return NOT_COMPILED_IN; /* Invalid key size / Not supported */ + }; /* Switch */ + + ret = ecc_test_vector_item(&vec); + if (ret < 0) { + return ret; + } + + return 0; +} + +#if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K) +static int ecc_test_sign_vectors(WC_RNG* rng) +{ + int ret; + ecc_key key; + byte sig[72]; + word32 sigSz; + unsigned char hash[32] = "test wolfSSL deterministic sign"; + const char* dIUT = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534"; + const char* QIUTx = "ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b230"; + const char* QIUTy = "28af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141"; + const byte k[1] = { 0x02 }; + const byte expSig[71] = { + 0x30, 0x45, 0x02, 0x20, 0x7c, 0xf2, 0x7b, 0x18, + 0x8d, 0x03, 0x4f, 0x7e, 0x8a, 0x52, 0x38, 0x03, + 0x04, 0xb5, 0x1a, 0xc3, 0xc0, 0x89, 0x69, 0xe2, + 0x77, 0xf2, 0x1b, 0x35, 0xa6, 0x0b, 0x48, 0xfc, + 0x47, 0x66, 0x99, 0x78, 0x02, 0x21, 0x00, 0xa8, + 0x43, 0xa0, 0xce, 0x6c, 0x5e, 0x17, 0x8a, 0x53, + 0x4d, 0xaf, 0xd2, 0x95, 0x78, 0x9f, 0x84, 0x4f, + 0x94, 0xb8, 0x75, 0xa3, 0x19, 0xa5, 0xd4, 0xdf, + 0xe1, 0xd4, 0x5e, 0x9d, 0x97, 0xfe, 0x81 + }; + + ret = wc_ecc_init_ex(&key, HEAP_HINT, devId); + if (ret != 0) { + return ret; + } + ret = wc_ecc_import_raw(&key, QIUTx, QIUTy, dIUT, "SECP256R1"); + if (ret != 0) { + goto done; + } + + ret = wc_ecc_sign_set_k(k, sizeof(k), &key); + if (ret != 0) { + goto done; + } + + sigSz = sizeof(sig); + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret == 0) + ret = wc_ecc_sign_hash(hash, sizeof(hash), sig, &sigSz, rng, &key); + } while (ret == WC_PENDING_E); + if (ret != 0) { + goto done; + } + TEST_SLEEP(); + + if (sigSz != sizeof(expSig)) { + ret = -9610; + goto done; + } + if (XMEMCMP(sig, expSig, sigSz) != 0) { + ret = -9611; + goto done; + } + + sigSz = sizeof(sig); + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret == 0) + ret = wc_ecc_sign_hash(hash, sizeof(hash), sig, &sigSz, rng, &key); + } while (ret == WC_PENDING_E); + if (ret != 0) { + goto done; + } + TEST_SLEEP(); + +done: + wc_ecc_free(&key); + return ret; +} +#endif + +#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_ex(&pub_key, HEAP_HINT, devId); + if (ret != 0) + return ret; + ret = wc_ecc_init_ex(&priv_key, HEAP_HINT, devId); + if (ret != 0) { + wc_ecc_free(&pub_key); + return ret; + } + 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); + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &priv_key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret == 0) + ret = wc_ecc_shared_secret(&priv_key, &pub_key, sharedA, &x); + } while (ret == WC_PENDING_E); + if (ret != 0) { + goto done; + } + TEST_SLEEP(); + + /* 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(-9612, 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 + XFILE file; +#endif + + wc_ecc_init_ex(&key, HEAP_HINT, devId); + +#ifdef USE_CERT_BUFFERS_256 + tmp = (byte*)XMALLOC((size_t)sizeof_ecc_key_der_256, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return -9613; + } + exportBuf = (byte*)XMALLOC((size_t)sizeof_ecc_key_der_256, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (exportBuf == NULL) { + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -9614; + } + XMEMCPY(tmp, ecc_key_der_256, (size_t)sizeof_ecc_key_der_256); + tmpSz = (size_t)sizeof_ecc_key_der_256; +#else + tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return -9615; + } + exportBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (exportBuf == NULL) { + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -9616; + } + file = XFOPEN(eccKeyDerFile, "rb"); + if (!file) { + ERROR_OUT(-9617, done); + } + + tmpSz = (word32)XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); +#endif /* USE_CERT_BUFFERS_256 */ + + /* import private only then test with */ + ret = wc_ecc_import_private_key(tmp, tmpSz, NULL, 0, NULL); + if (ret == 0) { + ERROR_OUT(-9618, done); + } + + ret = wc_ecc_import_private_key(NULL, tmpSz, NULL, 0, &key); + if (ret == 0) { + ERROR_OUT(-9619, done); + } + + x = 0; + ret = wc_EccPrivateKeyDecode(tmp, &x, &key, tmpSz); + if (ret != 0) { + ERROR_OUT(-9620, done); + } + +#ifdef HAVE_ECC_KEY_EXPORT + x = FOURK_BUF; + ret = wc_ecc_export_private_only(&key, exportBuf, &x); + if (ret != 0) { + ERROR_OUT(-9621, done); + } + + /* make private only key */ + wc_ecc_free(&key); + wc_ecc_init_ex(&key, HEAP_HINT, devId); + ret = wc_ecc_import_private_key(exportBuf, x, NULL, 0, &key); + if (ret != 0) { + ERROR_OUT(-9622, done); + } + + x = FOURK_BUF; + ret = wc_ecc_export_x963_ex(&key, exportBuf, &x, 0); + if (ret == 0) { + ERROR_OUT(-9623, done); + } + +#endif /* HAVE_ECC_KEY_EXPORT */ + + ret = wc_ecc_make_pub(NULL, NULL); + if (ret == 0) { + ERROR_OUT(-9624, done); + } + TEST_SLEEP(); + + pubPoint = wc_ecc_new_point_h(HEAP_HINT); + if (pubPoint == NULL) { + ERROR_OUT(-9625, done); + } + + ret = wc_ecc_make_pub(&key, pubPoint); + if (ret != 0) { + ERROR_OUT(-9626, done); + } + + TEST_SLEEP(); + +#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(-9627, done); + } +#endif /* HAVE_ECC_KEY_EXPORT */ +#if defined(WOLFSSL_CRYPTOCELL) + /* create a new key since building private key from public key is unsupported */ + ret = wc_ecc_make_key(rng, 32, &key); + if (ret == 0) { + ERROR_OUT(-9628, done); + } +#endif +#ifdef HAVE_ECC_SIGN + tmpSz = FOURK_BUF; + 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_ecc_sign_hash(msg, sizeof(msg), tmp, &tmpSz, rng, &key); + } while (ret == WC_PENDING_E); + if (ret != 0) { + ERROR_OUT(-9629, done); + } + TEST_SLEEP(); + +#ifdef HAVE_ECC_VERIFY + /* try verify with private only key */ + 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_ecc_verify_hash(tmp, tmpSz, msg, sizeof(msg), &verify, &key); + } while (ret == WC_PENDING_E); + if (ret != 0) { + ERROR_OUT(-9630, done); + } + + if (verify != 1) { + ERROR_OUT(-9631, done); + } + TEST_SLEEP(); +#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(-9632, 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(-9633, done); + } + + /* make private only key */ + wc_ecc_free(&key); + wc_ecc_init_ex(&key, HEAP_HINT, devId); + ret = wc_ecc_import_private_key(exportBuf, x, NULL, 0, &key); + if (ret != 0) { + ERROR_OUT(-9634, 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(-9635, done); + } + + /* make public key for shared secret */ + wc_ecc_init_ex(&pub, HEAP_HINT, devId); + ret = wc_ecc_make_key(rng, 32, &pub); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &pub.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ERROR_OUT(-9636, done); + } + TEST_SLEEP(); + + x = FOURK_BUF; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret == 0) { + ret = wc_ecc_shared_secret(&key, &pub, exportBuf, &x); + } + } while (ret == WC_PENDING_E); + wc_ecc_free(&pub); + if (ret != 0) { + ERROR_OUT(-9637, done); + } + TEST_SLEEP(); +#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; +#ifdef HAVE_PKCS8 + word32 pkcs8Sz; +#endif + byte* der; + byte* pem; + ecc_key userA; + + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + return -9638; + } + pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -9639; + } + + 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_NONE); +#endif + if (ret != 0) + goto done; + TEST_SLEEP(); + + ret = wc_ecc_check_key(&userA); + if (ret != 0) + goto done; + TEST_SLEEP(); + + derSz = wc_EccKeyToDer(&userA, der, FOURK_BUF); + if (derSz < 0) { + ERROR_OUT(derSz, done); + } + + ret = SaveDerAndPem(der, derSz, pem, FOURK_BUF, eccCaKeyTempFile, + eccCaKeyPemFile, ECC_PRIVATEKEY_TYPE, -8347); + if (ret != 0) { + goto done; + } + + /* test export of public key */ + derSz = wc_EccPublicKeyToDer(&userA, der, FOURK_BUF, 1); + if (derSz < 0) { + ERROR_OUT(derSz, done); + } + if (derSz == 0) { + ERROR_OUT(-9640, done); + } + + ret = SaveDerAndPem(der, derSz, NULL, 0, eccPubKeyDerFile, + NULL, 0, -8348); + if (ret != 0) { + goto done; + } + +#ifdef HAVE_PKCS8 + /* test export of PKCS#8 unencrypted private key */ + pkcs8Sz = FOURK_BUF; + derSz = wc_EccPrivateKeyToPKCS8(&userA, der, &pkcs8Sz); + if (derSz < 0) { + ERROR_OUT(derSz, done); + } + + if (derSz == 0) { + ERROR_OUT(-9641, done); + } + + ret = SaveDerAndPem(der, derSz, NULL, 0, eccPkcs8KeyDerFile, + NULL, 0, -8349); + if (ret != 0) { + goto done; + } +#endif /* HAVE_PKCS8 */ + +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, const ecc_set_type* dp) +{ +#if defined(HAVE_ECC_DHE) || defined(HAVE_ECC_CDH) + DECLARE_VAR(sharedA, byte, ECC_SHARED_SIZE, HEAP_HINT); + DECLARE_VAR(sharedB, byte, ECC_SHARED_SIZE, HEAP_HINT); +#endif +#ifdef HAVE_ECC_KEY_EXPORT + byte exportBuf[MAX_ECC_BYTES * 2 + 32]; +#endif + word32 x; +#if defined(HAVE_ECC_DHE) || defined(HAVE_ECC_CDH) + word32 y; +#endif +#ifdef HAVE_ECC_SIGN + 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; +#endif /* HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN */ + int ret; + ecc_key userA, userB, pubKey; + int curveSize; + + (void)testVerifyCount; + (void)dp; + (void)x; + + 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_NONE); +#endif + if (ret != 0) + goto done; + TEST_SLEEP(); + + if (wc_ecc_get_curve_idx(curve_id) != -1) { + curveSize = wc_ecc_get_curve_size_from_id(userA.dp->id); + if (curveSize != userA.dp->size) { + ret = -9642; + goto done; + } + } + + ret = wc_ecc_check_key(&userA); + if (ret != 0) + goto done; + TEST_SLEEP(); + + 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_NONE); +#endif + if (ret != 0) + goto done; + TEST_SLEEP(); + + /* only perform the below tests if the key size matches */ + if (dp == NULL && keySize > 0 && wc_ecc_size(&userA) != keySize) { + ret = ECC_CURVE_OID_E; + 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; + } + TEST_SLEEP(); + + 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(-9643, done); + + if (XMEMCMP(sharedA, sharedB, x)) + ERROR_OUT(-9644, done); + TEST_SLEEP(); +#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 = 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; + } + TEST_SLEEP(); + + 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(-9645, done); + + if (XMEMCMP(sharedA, sharedB, x)) + ERROR_OUT(-9646, done); + TEST_SLEEP(); + + /* 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_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 = 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(-9647, done); + TEST_SLEEP(); +#endif /* HAVE_ECC_DHE */ + + #ifdef HAVE_COMP_KEY + /* try compressed export / import too */ + x = sizeof(exportBuf); + ret = wc_ecc_export_x963_ex(&userA, exportBuf, &x, 1); + if (ret != 0) + goto done; + wc_ecc_free(&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 = 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(-9648, done); + TEST_SLEEP(); + #endif /* HAVE_ECC_DHE */ + #endif /* HAVE_COMP_KEY */ + +#endif /* HAVE_ECC_KEY_IMPORT */ +#endif /* HAVE_ECC_KEY_EXPORT */ + +#ifdef HAVE_ECC_SIGN + /* 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)ECC_DIGEST_SIZE; i++) { + digest[i] = 0; + } + + 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; + TEST_SLEEP(); + +#ifdef HAVE_ECC_VERIFY + for (i=0; iidx, &key->pubkey, pub, &pubLen); + if (ret != 0) { + ret = -9734; + goto done; + } + + ret = wc_ecc_import_private_key(priv, privLen, pub, pubLen, &keyImp); + if (ret != 0) { + ret = -9735; + goto done; + } + + wc_ecc_free(&keyImp); + wc_ecc_init_ex(&keyImp, HEAP_HINT, devId); + + ret = wc_ecc_import_raw_ex(&keyImp, qx, qy, d, ECC_SECP256R1); + if (ret != 0) { + ret = -9736; + goto done; + } + + wc_ecc_free(&keyImp); + wc_ecc_init_ex(&keyImp, HEAP_HINT, devId); + + curve_id = wc_ecc_get_curve_id(key->idx); + if (curve_id < 0) { + ret = -9737; + goto done; + } + + /* test import private only */ + ret = wc_ecc_import_private_key_ex(priv, privLen, NULL, 0, &keyImp, + curve_id); + if (ret != 0) { + ret = -9738; + goto done; + } + + wc_ecc_free(&keyImp); + wc_ecc_init_ex(&keyImp, HEAP_HINT, devId); + + /* test export public raw */ + pubLenX = pubLenY = 32; + ret = wc_ecc_export_public_raw(key, pub, &pubLenX, &pub[32], &pubLenY); + if (ret != 0) { + ret = -9739; + goto done; + } + +#ifndef HAVE_SELFTEST + /* test import of public */ + ret = wc_ecc_import_unsigned(&keyImp, pub, &pub[32], NULL, ECC_SECP256R1); + if (ret != 0) { + ret = -9740; + goto done; + } +#endif + + wc_ecc_free(&keyImp); + wc_ecc_init_ex(&keyImp, HEAP_HINT, devId); + + /* test export private and public raw */ + pubLenX = pubLenY = privLen = 32; + ret = wc_ecc_export_private_raw(key, pub, &pubLenX, &pub[32], &pubLenY, + priv, &privLen); + if (ret != 0) { + ret = -9741; + goto done; + } + +#ifndef HAVE_SELFTEST + /* test import of private and public */ + ret = wc_ecc_import_unsigned(&keyImp, pub, &pub[32], priv, ECC_SECP256R1); + if (ret != 0) { + ret = -9742; + goto done; + } +#endif + +done: + wc_ecc_free(&keyImp); + return ret; +} +#endif /* HAVE_ECC_KEY_IMPORT && HAVE_ECC_KEY_EXPORT */ + +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) +#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_ex(&key2, HEAP_HINT, devId); + wc_ecc_init_ex(&key3, HEAP_HINT, devId); + + /* 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 = -9743; + goto done; + } + +done: + wc_ecc_free(&key3); + wc_ecc_free(&key2); + return ret; +} +#endif + +#ifdef HAVE_ECC_DHE +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 -9744; + ret = wc_ecc_shared_secret_ssh(key, NULL, out, &outLen); + if (ret != BAD_FUNC_ARG) + return -9745; + ret = wc_ecc_shared_secret_ssh(key, &key->pubkey, NULL, &outLen); + if (ret != BAD_FUNC_ARG) + return -9746; + ret = wc_ecc_shared_secret_ssh(key, &key->pubkey, out, NULL); + if (ret != BAD_FUNC_ARG) + return -9747; + + /* Use API. */ + 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_ecc_shared_secret_ssh(key, &key->pubkey, out, &outLen); + } while (ret == WC_PENDING_E); + if (ret != 0) + return -9748; + TEST_SLEEP(); + return 0; +} +#endif /* HAVE_ECC_DHE */ +#endif + +static int ecc_def_curve_test(WC_RNG *rng) +{ + int ret; + ecc_key key; + + wc_ecc_init_ex(&key, HEAP_HINT, devId); + + /* Use API */ + ret = wc_ecc_set_flags(NULL, 0); + if (ret != BAD_FUNC_ARG) { + ret = -9749; + goto done; + } + ret = wc_ecc_set_flags(&key, 0); + if (ret != 0) { + ret = -9750; + goto done; + } + + ret = wc_ecc_make_key(rng, 32, &key); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ret = -9751; + goto done; + } + TEST_SLEEP(); + +#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 +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) +#if defined(HAVE_ECC_KEY_IMPORT) && !defined(WOLFSSL_VALIDATE_ECC_IMPORT) + ret = ecc_mulmod_test(&key); + if (ret < 0) + goto done; +#endif +#ifdef HAVE_ECC_DHE + ret = ecc_ssh_test(&key); + if (ret < 0) + goto done; +#endif +#endif /* WOLFSSL_ATECC508A */ +done: + wc_ecc_free(&key); + return ret; +} +#endif /* !NO_ECC256 || HAVE_ALL_CURVES */ + +#ifdef WOLFSSL_CERT_EXT +static int ecc_decode_test(void) +{ + int ret; + word32 inSz; + word32 inOutIdx; + ecc_key key; + + /* SECP256R1 OID: 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 */ + + /* This is ecc_clikeypub_der_256. */ + static const byte good[] = { + 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, 0x55, 0xbf, 0xf4, + 0x0f, 0x44, 0x50, 0x9a, 0x3d, 0xce, 0x9b, 0xb7, 0xf0, 0xc5, + 0x4d, 0xf5, 0x70, 0x7b, 0xd4, 0xec, 0x24, 0x8e, 0x19, 0x80, + 0xec, 0x5a, 0x4c, 0xa2, 0x24, 0x03, 0x62, 0x2c, 0x9b, 0xda, + 0xef, 0xa2, 0x35, 0x12, 0x43, 0x84, 0x76, 0x16, 0xc6, 0x56, + 0x95, 0x06, 0xcc, 0x01, 0xa9, 0xbd, 0xf6, 0x75, 0x1a, 0x42, + 0xf7, 0xbd, 0xa9, 0xb2, 0x36, 0x22, 0x5f, 0xc7, 0x5d, 0x7f, + 0xb4 }; + static const byte badNoObjId[] = { 0x30, 0x08, 0x30, 0x06, 0x03, 0x04, + 0x00, 0x04, 0x01, 0x01 }; + static const byte badOneObjId[] = { 0x30, 0x0a, 0x30, 0x08, 0x06, 0x00, + 0x03, 0x04, 0x00, 0x04, 0x01, 0x01 }; + static const byte badObjId1Len[] = { 0x30, 0x0c, 0x30, 0x0a, 0x06, 0x09, + 0x06, 0x00, 0x03, 0x04, 0x00, 0x04, 0x01, 0x01 }; + static const byte badObj2d1Len[] = { 0x30, 0x0c, 0x30, 0x0a, 0x06, 0x00, + 0x06, 0x07, 0x03, 0x04, 0x00, 0x04, 0x01, 0x01 }; + static const byte badNotBitStr[] = { 0x30, 0x14, 0x30, 0x0b, 0x06, 0x00, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, + 0x04, 0x04, 0x00, 0x04, 0x01, 0x01 }; + static const byte badBitStrLen[] = { 0x30, 0x14, 0x30, 0x0b, 0x06, 0x00, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, + 0x03, 0x05, 0x00, 0x04, 0x01, 0x01 }; + static const byte badNoBitStrZero[] = { 0x30, 0x13, 0x30, 0x0a, 0x06, 0x00, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, + 0x03, 0x03, 0x04, 0x01, 0x01 }; + static const byte badPoint[] = { 0x30, 0x12, 0x30, 0x09, 0x06, 0x00, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, + 0x03, 0x03, 0x00, 0x04, 0x01 }; + + XMEMSET(&key, 0, sizeof(key)); + wc_ecc_init_ex(&key, HEAP_HINT, devId); + + inSz = sizeof(good); + ret = wc_EccPublicKeyDecode(NULL, &inOutIdx, &key, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -9800; + goto done; + } + ret = wc_EccPublicKeyDecode(good, NULL, &key, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -9801; + goto done; + } + ret = wc_EccPublicKeyDecode(good, &inOutIdx, NULL, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -9802; + goto done; + } + ret = wc_EccPublicKeyDecode(good, &inOutIdx, &key, 0); + if (ret != BAD_FUNC_ARG) { + ret = -9803; + 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 = -9804; + goto done; + } + inOutIdx = 4; + inSz = sizeof(good) - inOutIdx; + ret = wc_EccPublicKeyDecode(good, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -9805; + goto done; + } + /* Bad data. */ + inSz = sizeof(badNoObjId); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badNoObjId, &inOutIdx, &key, inSz); + if (ret != ASN_OBJECT_ID_E) { + ret = -9806; + goto done; + } + inSz = sizeof(badOneObjId); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badOneObjId, &inOutIdx, &key, inSz); + if (ret != ASN_OBJECT_ID_E) { + ret = -9807; + goto done; + } + inSz = sizeof(badObjId1Len); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badObjId1Len, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -9808; + goto done; + } + inSz = sizeof(badObj2d1Len); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badObj2d1Len, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -9809; + goto done; + } + inSz = sizeof(badNotBitStr); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badNotBitStr, &inOutIdx, &key, inSz); + if (ret != ASN_BITSTR_E) { + ret = -9810; + goto done; + } + inSz = sizeof(badBitStrLen); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badBitStrLen, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -9811; + goto done; + } + inSz = sizeof(badNoBitStrZero); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badNoBitStrZero, &inOutIdx, &key, inSz); + if (ret != ASN_EXPECT_0_E) { + ret = -9812; + goto done; + } + inSz = sizeof(badPoint); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badPoint, &inOutIdx, &key, inSz); + if (ret != ASN_ECC_KEY_E) { + ret = -9813; + goto done; + } + + inSz = sizeof(good); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(good, &inOutIdx, &key, inSz); + if (ret != 0) { + ret = -9814; + goto done; + } + +done: + wc_ecc_free(&key); + return ret; +} +#endif /* WOLFSSL_CERT_EXT */ + +#ifdef WOLFSSL_CUSTOM_CURVES +static const byte eccKeyExplicitCurve[] = { + 0x30, 0x81, 0xf5, 0x30, 0x81, 0xae, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, + 0x81, 0xa2, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, + 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, + 0xff, 0xfc, 0x2f, 0x30, 0x06, 0x04, 0x01, 0x00, + 0x04, 0x01, 0x07, 0x04, 0x41, 0x04, 0x79, 0xbe, + 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, + 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, + 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, + 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 0x48, 0x3a, + 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, + 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, + 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, + 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8, 0x02, 0x21, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, + 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, + 0x41, 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, + 0x3c, 0x4c, 0xc9, 0x5e, 0x2e, 0xa2, 0x3d, 0x49, + 0xcc, 0x5b, 0xff, 0x4f, 0xc9, 0x2e, 0x1d, 0x4a, + 0xc6, 0x21, 0xf6, 0xf3, 0xe6, 0x0b, 0x4f, 0xa9, + 0x9d, 0x74, 0x99, 0xdd, 0x97, 0xc7, 0x6e, 0xbe, + 0x14, 0x2b, 0x39, 0x9d, 0x63, 0xc7, 0x97, 0x0d, + 0x45, 0x25, 0x40, 0x30, 0x77, 0x05, 0x76, 0x88, + 0x38, 0x96, 0x29, 0x7d, 0x9c, 0xe1, 0x50, 0xbe, + 0xac, 0xf0, 0x1d, 0x86, 0xf4, 0x2f, 0x65, 0x0b +}; + +static int ecc_test_custom_curves(WC_RNG* rng) +{ + int ret; + word32 inOutIdx; + ecc_key key; + + /* test use of custom curve - using BRAINPOOLP256R1 for test */ + #ifndef WOLFSSL_ECC_CURVE_STATIC + const ecc_oid_t ecc_oid_brainpoolp256r1[] = { + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07 + }; + const word32 ecc_oid_brainpoolp256r1_sz = + sizeof(ecc_oid_brainpoolp256r1) / sizeof(ecc_oid_t); + #else + #define ecc_oid_brainpoolp256r1 { \ + 0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07 \ + } + #define ecc_oid_brainpoolp256r1_sz 9 + #endif + const word32 ecc_oid_brainpoolp256r1_sum = 104; + + 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 */ + ecc_oid_brainpoolp256r1_sz, + 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 + + ret = wc_ecc_init_ex(&key, HEAP_HINT, devId); + if (ret != 0) { + return -9815; + } + + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(eccKeyExplicitCurve, &inOutIdx, &key, + sizeof(eccKeyExplicitCurve)); + if (ret != 0) + return -9816; + + wc_ecc_free(&key); + + 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 + XFILE file; +#endif +#ifdef WOLFSSL_TEST_CERT + DecodedCert decode; +#endif + byte* der; + 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(-9817, exit); + } + pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + ERROR_OUT(-9818, 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 = XFOPEN(eccCaKey384File, "rb"); + if (!file) { + ERROR_OUT(-9819, exit); + } + + bytes = XFREAD(der, 1, FOURK_BUF, file); + XFCLOSE(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 = XFOPEN(eccCaKeyFile, "rb"); + if (!file) { + ERROR_OUT(-9820, exit); + } + bytes = XFREAD(der, 1, FOURK_BUF, file); + XFCLOSE(file); +#ifdef ENABLE_ECC384_CERT_GEN_TEST + (void)eccCaKey384File; +#endif +#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(-9821, exit); + } + ret = wc_EccPrivateKeyDecode(der, &idx, &caEccKey, (word32)bytes); + if (ret != 0) { + ERROR_OUT(-9822, exit); + } + + /* Make a public key */ + ret = wc_ecc_init_ex(&certPubKey, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-9823, exit); + } + + ret = wc_ecc_make_key(rng, 32, &certPubKey); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &certPubKey.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ERROR_OUT(-9824, exit); + } + TEST_SLEEP(); + + /* Setup Certificate */ + if (wc_InitCert(&myCert)) { + ERROR_OUT(-9825, 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(-9826, exit); + } + + /* add AKID from the Public Key */ + if (wc_SetAuthKeyIdFromPublicKey(&myCert, NULL, &caEccKey) != 0) { + ERROR_OUT(-9827, exit); + } + + /* add Key Usage */ + if (wc_SetKeyUsage(&myCert, certKeyUsage) != 0) { + ERROR_OUT(-9828, 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); +#ifdef ENABLE_ECC384_CERT_GEN_TEST + (void)eccCaCert384File; +#endif +#endif +#endif /* ENABLE_ECC384_CERT_GEN_TEST */ + if (ret < 0) { + ERROR_OUT(-9829, exit); + } + + certSz = wc_MakeCert(&myCert, der, FOURK_BUF, NULL, &certPubKey, rng); + if (certSz < 0) { + ERROR_OUT(-9830, 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(-9831, exit); + } + certSz = ret; + TEST_SLEEP(); + +#ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, 0); + ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) { + FreeDecodedCert(&decode); + ERROR_OUT(-9832, 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 */ + +#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) +/* Test for the wc_ecc_key_new() and wc_ecc_key_free() functions. */ +static int ecc_test_allocator(WC_RNG* rng) +{ + int ret = 0; + ecc_key* key; + + key = wc_ecc_key_new(HEAP_HINT); + if (key == NULL) { + ERROR_OUT(-9833, exit); + } + + ret = wc_ecc_make_key(rng, 32, key); + if (ret != 0) { + ERROR_OUT(-9834, exit); + } + +exit: + wc_ecc_key_free(key); + return ret; +} +#endif + +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 -9900; + +#if defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 14); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC112 */ +#if defined(HAVE_ECC128) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 16); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC128 */ +#if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 20); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC160 */ +#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 24); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC192 */ +#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 28); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC224 */ +#if defined(HAVE_ECC239) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 30); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC239 */ +#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 32); + 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); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC320 */ +#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 48); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC384 */ +#if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 64); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC512 */ +#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 66); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC521 */ + +#if defined(WOLFSSL_CUSTOM_CURVES) + ret = ecc_test_custom_curves(&rng); + if (ret != 0) { + goto done; + } +#endif + +#if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K) + ret = ecc_test_sign_vectors(&rng); + if (ret != 0) { + printf("ecc_test_sign_vectors failed! %d\n", ret); + 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 +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_STM32_PKA) + ret = ecc_test_make_pub(&rng); + if (ret != 0) { + printf("ecc_test_make_pub failed!: %d\n", ret); + goto done; + } +#else + (void) ecc_test_make_pub;/* for compiler warning */ +#endif +#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 +#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + ret = ecc_test_allocator(&rng); + if (ret != 0) { + printf("ecc_test_allocator failed!: %d\n", ret); + } +#endif + +done: + wc_FreeRng(&rng); + + return ret; +} + +#if defined(HAVE_ECC_ENCRYPT) && defined(WOLFSSL_AES_128) int ecc_encrypt_test(void) { - RNG rng; - int ret; + WC_RNG rng; + int ret = 0; ecc_key userA, userB; byte msg[48]; byte plain[48]; @@ -5130,139 +20123,551 @@ 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 -10000; - 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 = -10001; 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 = -10002; 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 = -10003; goto done; + } /* decrypt msg from A */ ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, NULL); - if (ret != 0) - return -3004; - - if (memcmp(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; - memcpy(cliSalt, tmpSalt, EXCHANGE_SALT_SZ); - - tmpSalt = wc_ecc_ctx_get_own_salt(srvCtx); - if (tmpSalt == NULL) - return -3007; - memcpy(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 (memcmp(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 (memcmp(plain2, msg2, sizeof(msg2)) != 0) - return -3014; - } - - /* cleanup */ - wc_ecc_ctx_free(srvCtx); - wc_ecc_ctx_free(cliCtx); + if (ret != 0) { + ret = -10004; goto done; } + if (XMEMCMP(plain, msg, sizeof(msg)) != 0) { + ret = -10005; 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 = -10006; goto done; + } + + /* get salt to send to peer */ + tmpSalt = wc_ecc_ctx_get_own_salt(cliCtx); + if (tmpSalt == NULL) { + ret = -10007; goto done; + } + XMEMCPY(cliSalt, tmpSalt, EXCHANGE_SALT_SZ); + + tmpSalt = wc_ecc_ctx_get_own_salt(srvCtx); + if (tmpSalt == NULL) { + ret = -10008; 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 = -10009; 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 = -10010; 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(void) { + size_t bytes; + ecc_key cliKey; + ecc_key servKey; + WC_RNG rng; + word32 idx = 0; + int ret; + /* pad our test message to 32 bytes so evenly divisible by AES_BLOCK_SZ */ + byte in[] = "Everyone gets Friday off. ecc p"; + word32 inLen = (word32)XSTRLEN((char*)in); + byte out[256]; + byte plain[256]; + int verify = 0; + word32 x; + + ret = wc_ecc_init_ex(&cliKey, HEAP_HINT, devId); + if (ret != 0) + return -10011; + ret = wc_ecc_init_ex(&servKey, HEAP_HINT, devId); + if (ret != 0) + return -10012; + + 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 -10013; + + idx = 0; + 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 -10014; + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -10015; + +#if defined(HAVE_ECC_ENCRYPT) && defined(HAVE_HKDF) + { + word32 y; + /* test encrypt and decrypt if they're available */ + x = sizeof(out); + ret = wc_ecc_encrypt(&cliKey, &servKey, in, sizeof(in), out, &x, NULL); + if (ret < 0) + return -10016; + + y = sizeof(plain); + ret = wc_ecc_decrypt(&cliKey, &servKey, out, x, plain, &y, NULL); + if (ret < 0) + return -10017; + + if (XMEMCMP(plain, in, inLen)) + return -10018; + } +#endif + + x = sizeof(out); + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &cliKey.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret == 0) + ret = wc_ecc_sign_hash(in, inLen, out, &x, &rng, &cliKey); + } while (ret == WC_PENDING_E); + if (ret < 0) + return -10019; + TEST_SLEEP(); + + XMEMSET(plain, 0, sizeof(plain)); + + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &cliKey.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret == 0) + ret = wc_ecc_verify_hash(out, x, plain, sizeof(plain), &verify, + &cliKey); + } while (ret == WC_PENDING_E); + if (ret < 0) + return -10020; + + if (XMEMCMP(plain, in, (word32)ret)) + return -10021; + TEST_SLEEP(); + +#ifdef WOLFSSL_CERT_EXT + idx = 0; + + bytes = sizeof_ecc_clikeypub_der_256; + + ret = wc_EccPublicKeyDecode(ecc_clikeypub_der_256, &idx, &cliKey, + (word32) bytes); + if (ret != 0) + return -10022; +#endif + + wc_ecc_free(&cliKey); + wc_ecc_free(&servKey); + wc_FreeRng(&rng); + + return 0; +} +#endif /* USE_CERT_BUFFERS_256 */ #endif /* HAVE_ECC */ #ifdef HAVE_CURVE25519 +#if defined(HAVE_CURVE25519_SHARED_SECRET) && \ + defined(HAVE_CURVE25519_KEY_IMPORT) +#ifdef CURVE25519_OVERFLOW_ALL_TESTS +#define X25519_TEST_CNT 5 +#else +#define X25519_TEST_CNT 1 +#endif +static int curve25519_overflow_test(void) +{ + /* secret key for party a */ + byte sa[X25519_TEST_CNT][32] = { + { + 0x8d,0xaf,0x6e,0x7a,0xc1,0xeb,0x8d,0x30, + 0x99,0x86,0xd3,0x90,0x47,0x96,0x21,0x3c, + 0x3a,0x75,0xc0,0x7b,0x75,0x01,0x75,0xa3, + 0x81,0x4b,0xff,0x5a,0xbc,0x96,0x87,0x28 + }, +#ifdef CURVE25519_OVERFLOW_ALL_TESTS + { + 0x9d,0x63,0x5f,0xce,0xe2,0xe8,0xd7,0xfb, + 0x68,0x77,0x0e,0x44,0xd1,0xad,0x87,0x2b, + 0xf4,0x65,0x06,0xb7,0xbb,0xdb,0xbe,0x6e, + 0x02,0x43,0x24,0xc7,0x3d,0x7b,0x88,0x60 + }, + { + 0x63,0xbf,0x76,0xa9,0x73,0xa0,0x09,0xb9, + 0xcc,0xc9,0x4d,0x47,0x2d,0x14,0x0e,0x52, + 0xa3,0x84,0x55,0xb8,0x7c,0xdb,0xce,0xb1, + 0xe4,0x5b,0x8a,0xb9,0x30,0xf1,0xa4,0xa0 + }, + { + 0x63,0xbf,0x76,0xa9,0x73,0xa0,0x09,0xb9, + 0xcc,0xc9,0x4d,0x47,0x2d,0x14,0x0e,0x52, + 0xa3,0x84,0x55,0xb8,0x7c,0xdb,0xce,0xb1, + 0xe4,0x5b,0x8a,0xb9,0x30,0xf1,0xa4,0xa0 + }, + { + 0x63,0xbf,0x76,0xa9,0x73,0xa0,0x09,0xb9, + 0xcc,0xc9,0x4d,0x47,0x2d,0x14,0x0e,0x52, + 0xa3,0x84,0x55,0xb8,0x7c,0xdb,0xce,0xb1, + 0xe4,0x5b,0x8a,0xb9,0x30,0xf1,0xa4,0xa0 + } +#endif + }; + + /* public key for party b */ + byte pb[X25519_TEST_CNT][32] = { + { + 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0 + }, +#ifdef CURVE25519_OVERFLOW_ALL_TESTS + { + /* 0xff first byte in original - invalid! */ + 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0 + }, + { + 0x36,0x1a,0x74,0x87,0x28,0x59,0xe0,0xb6, + 0xe4,0x2b,0x17,0x9b,0x16,0xb0,0x3b,0xf8, + 0xb8,0x9f,0x2a,0x8f,0xc5,0x33,0x68,0x4f, + 0xde,0x4d,0xd8,0x80,0x63,0xe7,0xb4,0x0a + }, + { + 0x00,0x80,0x38,0x59,0x19,0x3a,0x66,0x12, + 0xfd,0xa1,0xec,0x1c,0x40,0x84,0x40,0xbd, + 0x64,0x10,0x8b,0x53,0x81,0x21,0x03,0x2d, + 0x7d,0x33,0xb4,0x01,0x57,0x0d,0xe1,0x89 + }, + { + 0x1d,0xf8,0xf8,0x33,0x89,0x6c,0xb7,0xba, + 0x94,0x73,0xfa,0xc2,0x36,0xac,0xbe,0x49, + 0xaf,0x85,0x3e,0x93,0x5f,0xae,0xb2,0xc0, + 0xc8,0x80,0x8f,0x4a,0xaa,0xd3,0x55,0x2b + } +#endif + }; + + /* expected shared key */ + byte ss[X25519_TEST_CNT][32] = { + { + 0x5c,0x4c,0x85,0x5f,0xfb,0x20,0x38,0xcc, + 0x55,0x16,0x5b,0x8a,0xa7,0xed,0x57,0x6e, + 0x35,0xaa,0x71,0x67,0x85,0x1f,0xb6,0x28, + 0x17,0x07,0x7b,0xda,0x76,0xdd,0xe0,0xb4 + }, +#ifdef CURVE25519_OVERFLOW_ALL_TESTS + { + 0x33,0xf6,0xc1,0x34,0x62,0x92,0x06,0x02, + 0x95,0xdb,0x91,0x4c,0x5d,0x52,0x54,0xc7, + 0xd2,0x5b,0x24,0xb5,0x4f,0x33,0x59,0x79, + 0x9f,0x6d,0x7e,0x4a,0x4c,0x30,0xd6,0x38 + }, + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 + }, + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09 + }, + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10 + } +#endif + }; + + int i; + word32 y; + byte shared[32]; + curve25519_key userA; + + wc_curve25519_init(&userA); + + for (i = 0; i < X25519_TEST_CNT; i++) { + if (wc_curve25519_import_private_raw(sa[i], sizeof(sa[i]), pb[i], + sizeof(pb[i]), &userA) != 0) + return -10100 - i; + + /* test against known test vector */ + XMEMSET(shared, 0, sizeof(shared)); + y = sizeof(shared); + if (wc_curve25519_shared_secret(&userA, &userA, shared, &y) != 0) + return -10110 - i; + + if (XMEMCMP(ss[i], shared, y)) + return -10120 - i; + } + + return 0; +} + +/* Test the wc_curve25519_check_public API. + * + * returns 0 on success and -ve on failure. + */ +static int curve25519_check_public_test(void) +{ + /* Little-endian values that will fail */ + byte fail_le[][CURVE25519_KEYSIZE] = { + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }, + { + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }, + { + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81 + }, + }; + /* Big-endian values that will fail */ + byte fail_be[][CURVE25519_KEYSIZE] = { + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }, + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,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 + }, + { + 0x81,0x00,0x00,0x00,0x00,0x00,0x00,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 + }, + }; + /* Good or valid public value */ + byte good[CURVE25519_KEYSIZE] = { + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 + }; + int i; + + /* Parameter checks */ + /* NULL pointer */ + if (wc_curve25519_check_public(NULL, 0, EC25519_LITTLE_ENDIAN) != + BAD_FUNC_ARG) { + return -10200; + } + if (wc_curve25519_check_public(NULL, 0, EC25519_BIG_ENDIAN) != + BAD_FUNC_ARG) { + return -10201; + } + /* Length of 0 treated differently to other invalid lengths for TLS */ + if (wc_curve25519_check_public(good, 0, EC25519_LITTLE_ENDIAN) != BUFFER_E) + return -10202; + if (wc_curve25519_check_public(good, 0, EC25519_BIG_ENDIAN) != BUFFER_E) + return -10203; + + /* Length not CURVE25519_KEYSIZE */ + for (i = 1; i < CURVE25519_KEYSIZE + 2; i++) { + if (i == CURVE25519_KEYSIZE) + continue; + if (wc_curve25519_check_public(good, i, EC25519_LITTLE_ENDIAN) != + ECC_BAD_ARG_E) { + return -10204 - i; + } + if (wc_curve25519_check_public(good, i, EC25519_BIG_ENDIAN) != + ECC_BAD_ARG_E) { + return -10214 - i; + } + } + + /* Little-endian fail cases */ + for (i = 0; i < (int)(sizeof(fail_le) / sizeof(*fail_le)); i++) { + if (wc_curve25519_check_public(fail_le[i], CURVE25519_KEYSIZE, + EC25519_LITTLE_ENDIAN) == 0) { + return -10224 - i; + } + } + /* Big-endian fail cases */ + for (i = 0; i < (int)(sizeof(fail_be) / sizeof(*fail_be)); i++) { + if (wc_curve25519_check_public(fail_be[i], CURVE25519_KEYSIZE, + EC25519_BIG_ENDIAN) == 0) { + return -10234 - i; + } + } + + /* Check a valid public value works! */ + if (wc_curve25519_check_public(good, CURVE25519_KEYSIZE, + EC25519_LITTLE_ENDIAN) != 0) { + return -10244; + } + if (wc_curve25519_check_public(good, CURVE25519_KEYSIZE, + EC25519_BIG_ENDIAN) != 0) { + return -10245; + } + + return 0; +} + +#endif /* HAVE_CURVE25519_SHARED_SECRET && HAVE_CURVE25519_KEY_IMPORT */ int curve25519_test(void) { - RNG rng; + WC_RNG rng; + int ret; +#ifdef HAVE_CURVE25519_SHARED_SECRET byte sharedA[32]; byte sharedB[32]; + word32 y; +#endif +#ifdef HAVE_CURVE25519_KEY_EXPORT byte exportBuf[32]; - word32 x, y; +#endif + word32 x; curve25519_key userA, userB, pubKey; +#if defined(HAVE_CURVE25519_SHARED_SECRET) && \ + defined(HAVE_CURVE25519_KEY_IMPORT) /* test vectors from https://tools.ietf.org/html/draft-josefsson-tls-curve25519-03 */ @@ -5306,9 +20711,17 @@ int curve25519_test(void) 0x73,0x8B,0x99,0xF0,0x94,0x68,0xB8,0xD6, 0xB8,0x51,0x11,0x84,0xD5,0x34,0x94,0xAB }; +#endif /* HAVE_CURVE25519_SHARED_SECRET */ - if (wc_InitRng(&rng) != 0) - return -1001; + (void)x; + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -10300; wc_curve25519_init(&userA); wc_curve25519_init(&userB); @@ -5316,64 +20729,109 @@ int curve25519_test(void) /* make curve25519 keys */ if (wc_curve25519_make_key(&rng, 32, &userA) != 0) - return -1002; + return -10301; if (wc_curve25519_make_key(&rng, 32, &userB) != 0) - return -1003; + return -10302; +#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 -10303; + y = sizeof(sharedB); if (wc_curve25519_shared_secret(&userB, &userA, sharedB, &y) != 0) - return -1005; + return -10304; /* compare shared secret keys to test they are the same */ if (y != x) - return -1006; + return -10305; if (XMEMCMP(sharedA, sharedB, x)) - return -1007; + return -10306; +#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 -10307; +#ifdef HAVE_CURVE25519_KEY_IMPORT if (wc_curve25519_import_public(exportBuf, x, &pubKey) != 0) - return -1009; + return -10308; +#endif +#endif +#if defined(HAVE_CURVE25519_SHARED_SECRET) && \ + defined(HAVE_CURVE25519_KEY_IMPORT) /* test shared key after importing a public key */ XMEMSET(sharedB, 0, sizeof(sharedB)); + y = sizeof(sharedB); if (wc_curve25519_shared_secret(&userB, &pubKey, sharedB, &y) != 0) - return -1010; + return -10309; if (XMEMCMP(sharedA, sharedB, y)) - return -1011; + return -10310; /* 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 -10311; if (wc_curve25519_import_private_raw(sb, sizeof(sb), pb, sizeof(pb), &userB) != 0) - return -1013; + return -10312; /* 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 -10313; if (XMEMCMP(ss, sharedB, y)) - return -1015; + return -10314; - /* test swaping roles of keys and generating same shared key */ + /* test swapping 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 -10315; if (XMEMCMP(ss, sharedB, y)) - return -1017; + return -10316; + + /* 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 -10317; + + if (wc_curve25519_make_key(&rng, 32, &userB) != 0) + return -10318; + + x = sizeof(sharedA); + if (wc_curve25519_shared_secret(&userA, &userB, sharedA, &x) != 0) + return -10319; + + y = sizeof(sharedB); + if (wc_curve25519_shared_secret(&userB, &userA, sharedB, &y) != 0) + return -10320; + + /* compare shared secret keys to test they are the same */ + if (y != x) + return -10321; + + if (XMEMCMP(sharedA, sharedB, x)) + return -10322; + + ret = curve25519_overflow_test(); + if (ret != 0) + return ret; + ret = curve25519_check_public_test(); + if (ret != 0) + return ret; +#endif /* HAVE_CURVE25519_SHARED_SECRET && HAVE_CURVE25519_KEY_IMPORT */ /* clean up keys when done */ wc_curve25519_free(&pubKey); @@ -5388,337 +20846,812 @@ 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; + XFILE file; + + tmp = XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ERROR_OUT(-10323, 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 = XFOPEN(caEd25519Cert, "rb"); + if (file == NULL) { + ERROR_OUT(-10324, done); + } + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); +#else + /* No certificate to use. */ + ERROR_OUT(-10325, 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(-10326, 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 = XFOPEN(serverEd25519Cert, "rb"); + if (file == NULL) { + ERROR_OUT(-10327, done); + } + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); +#else + /* No certificate to use. */ + ERROR_OUT(-10328, 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(-10329, done); + } + +#ifdef HAVE_ED25519_VERIFY + ret = wc_ed25519_init(&key); + if (ret < 0) { + ERROR_OUT(-10330, done); + } + pubKey = &key; + ret = wc_ed25519_import_public(caCert->publicKey, caCert->pubKeySize, + pubKey); + if (ret < 0) { + ERROR_OUT(-10331, 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(-10332, 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 -10333; + + 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(-10334, done); + } + ret = wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, privKey); + if (ret < 0) { + ERROR_OUT(-10335, done); + } + ret = wc_SetAuthKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, privKey); + if (ret < 0) { + ERROR_OUT(-10336, done); + } +#endif + tmp = XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ERROR_OUT(-10337, done); + } + + cert.sigType = CTC_ED25519; + ret = wc_MakeCert_ex(&cert, tmp, FOURK_BUF, ED25519_TYPE, privKey, &rng); + if (ret < 0) { + ERROR_OUT(-10338, done); + } + ret = wc_SignCert_ex(cert.bodySz, cert.sigType, tmp, FOURK_BUF, + ED25519_TYPE, privKey, &rng); + if (ret < 0) { + ERROR_OUT(-10339, done); + } + + InitDecodedCert(&decode, tmp, ret, HEAP_HINT); + ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); + FreeDecodedCert(&decode); + if (ret != 0) { + ERROR_OUT(-10340, 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 */ + +#if defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_KEY_EXPORT) && \ + defined(HAVE_ED25519_KEY_IMPORT) +static int ed25519ctx_test(void) +{ + byte out[ED25519_SIG_SIZE]; + word32 outlen; +#ifdef HAVE_ED25519_VERIFY + int verify; +#endif /* HAVE_ED25519_VERIFY */ + ed25519_key key; + + static const byte sKeyCtx[] = { + 0x03,0x05,0x33,0x4e,0x38,0x1a,0xf7,0x8f, + 0x14,0x1c,0xb6,0x66,0xf6,0x19,0x9f,0x57, + 0xbc,0x34,0x95,0x33,0x5a,0x25,0x6a,0x95, + 0xbd,0x2a,0x55,0xbf,0x54,0x66,0x63,0xf6 + }; + + static const byte pKeyCtx[] = { + 0xdf,0xc9,0x42,0x5e,0x4f,0x96,0x8f,0x7f, + 0x0c,0x29,0xf0,0x25,0x9c,0xf5,0xf9,0xae, + 0xd6,0x85,0x1c,0x2b,0xb4,0xad,0x8b,0xfb, + 0x86,0x0c,0xfe,0xe0,0xab,0x24,0x82,0x92 + }; + + static const byte sigCtx1[] = { + 0x55,0xa4,0xcc,0x2f,0x70,0xa5,0x4e,0x04, + 0x28,0x8c,0x5f,0x4c,0xd1,0xe4,0x5a,0x7b, + 0xb5,0x20,0xb3,0x62,0x92,0x91,0x18,0x76, + 0xca,0xda,0x73,0x23,0x19,0x8d,0xd8,0x7a, + 0x8b,0x36,0x95,0x0b,0x95,0x13,0x00,0x22, + 0x90,0x7a,0x7f,0xb7,0xc4,0xe9,0xb2,0xd5, + 0xf6,0xcc,0xa6,0x85,0xa5,0x87,0xb4,0xb2, + 0x1f,0x4b,0x88,0x8e,0x4e,0x7e,0xdb,0x0d + }; + + static const byte sigCtx2[] = { + 0xcc,0x5e,0x63,0xa2,0x7e,0x94,0xaf,0xd3, + 0x41,0x83,0x38,0xd2,0x48,0x6f,0xa9,0x2a, + 0xf9,0x91,0x7c,0x2d,0x98,0x9e,0x06,0xe5, + 0x02,0x77,0x72,0x1c,0x34,0x38,0x18,0xb4, + 0x21,0x96,0xbc,0x29,0x2e,0x68,0xf3,0x4d, + 0x85,0x9b,0xbe,0xad,0x17,0x9f,0x54,0x54, + 0x2d,0x4b,0x04,0xdc,0xfb,0xfa,0x4a,0x68, + 0x4e,0x39,0x50,0xfb,0x1c,0xcd,0x8d,0x0d + }; + + static const byte msgCtx[] = { + 0xf7,0x26,0x93,0x6d,0x19,0xc8,0x00,0x49, + 0x4e,0x3f,0xda,0xff,0x20,0xb2,0x76,0xa8 + }; + + static const byte contextCtx[] = { + 0x66,0x6f,0x6f + }; + + outlen = sizeof(out); + XMEMSET(out, 0, sizeof(out)); + + if (wc_ed25519_import_private_key(sKeyCtx, ED25519_KEY_SIZE, pKeyCtx, + sizeof(pKeyCtx), &key) != 0) + return -10400; + + if (wc_ed25519ctx_sign_msg(msgCtx, sizeof(msgCtx), out, &outlen, &key, + contextCtx, sizeof(contextCtx)) != 0) + return -10401; + + if (XMEMCMP(out, sigCtx1, 64)) + return -10402; + +#if defined(HAVE_ED25519_VERIFY) + /* test verify on good msg */ + if (wc_ed25519ctx_verify_msg(out, outlen, msgCtx, sizeof(msgCtx), &verify, + &key, contextCtx, sizeof(contextCtx)) != 0 || + verify != 1) + return -10403; +#endif + + if (wc_ed25519ctx_sign_msg(msgCtx, sizeof(msgCtx), out, &outlen, &key, NULL, + 0) != 0) + return -10404; + + if (XMEMCMP(out, sigCtx2, 64)) + return -10405; + +#if defined(HAVE_ED25519_VERIFY) + /* test verify on good msg */ + if (wc_ed25519ctx_verify_msg(out, outlen, msgCtx, sizeof(msgCtx), &verify, + &key, NULL, 0) != 0 || verify != 1) + return -10406; +#endif + + wc_ed25519_free(&key); + + return 0; +} + +static int ed25519ph_test(void) +{ + byte out[ED25519_SIG_SIZE]; + word32 outlen; +#ifdef HAVE_ED25519_VERIFY + int verify; +#endif /* HAVE_ED25519_VERIFY */ + ed25519_key key; + + static const byte sKeyPh[] = { + 0x83,0x3f,0xe6,0x24,0x09,0x23,0x7b,0x9d, + 0x62,0xec,0x77,0x58,0x75,0x20,0x91,0x1e, + 0x9a,0x75,0x9c,0xec,0x1d,0x19,0x75,0x5b, + 0x7d,0xa9,0x01,0xb9,0x6d,0xca,0x3d,0x42 + }; + + static const byte pKeyPh[] = { + 0xec,0x17,0x2b,0x93,0xad,0x5e,0x56,0x3b, + 0xf4,0x93,0x2c,0x70,0xe1,0x24,0x50,0x34, + 0xc3,0x54,0x67,0xef,0x2e,0xfd,0x4d,0x64, + 0xeb,0xf8,0x19,0x68,0x34,0x67,0xe2,0xbf + }; + + static const byte sigPh1[] = { + 0x98,0xa7,0x02,0x22,0xf0,0xb8,0x12,0x1a, + 0xa9,0xd3,0x0f,0x81,0x3d,0x68,0x3f,0x80, + 0x9e,0x46,0x2b,0x46,0x9c,0x7f,0xf8,0x76, + 0x39,0x49,0x9b,0xb9,0x4e,0x6d,0xae,0x41, + 0x31,0xf8,0x50,0x42,0x46,0x3c,0x2a,0x35, + 0x5a,0x20,0x03,0xd0,0x62,0xad,0xf5,0xaa, + 0xa1,0x0b,0x8c,0x61,0xe6,0x36,0x06,0x2a, + 0xaa,0xd1,0x1c,0x2a,0x26,0x08,0x34,0x06 + }; + + static const byte sigPh2[] = { + 0xe0,0x39,0x70,0x2b,0x4c,0x25,0x95,0xa6, + 0xa5,0x41,0xac,0x85,0x09,0x23,0x6e,0x29, + 0x90,0x47,0x47,0x95,0x33,0x0c,0x9b,0x34, + 0xa7,0x5f,0x58,0xa6,0x60,0x12,0x9e,0x08, + 0xfd,0x73,0x69,0x43,0xfb,0x19,0x43,0xa5, + 0x57,0x20,0xb9,0xe0,0x95,0x7b,0x1e,0xd6, + 0x73,0x48,0x16,0x61,0x9f,0x13,0x88,0xf4, + 0x3f,0x73,0xe6,0xe3,0xba,0xa8,0x1c,0x0e + }; + + static const byte msgPh[] = { + 0x61,0x62,0x63 + }; + + /* SHA-512 hash of msgPh */ + static const byte hashPh[] = { + 0xdd,0xaf,0x35,0xa1,0x93,0x61,0x7a,0xba, + 0xcc,0x41,0x73,0x49,0xae,0x20,0x41,0x31, + 0x12,0xe6,0xfa,0x4e,0x89,0xa9,0x7e,0xa2, + 0x0a,0x9e,0xee,0xe6,0x4b,0x55,0xd3,0x9a, + 0x21,0x92,0x99,0x2a,0x27,0x4f,0xc1,0xa8, + 0x36,0xba,0x3c,0x23,0xa3,0xfe,0xeb,0xbd, + 0x45,0x4d,0x44,0x23,0x64,0x3c,0xe8,0x0e, + 0x2a,0x9a,0xc9,0x4f,0xa5,0x4c,0xa4,0x9f + }; + + static const byte contextPh2[] = { + 0x66,0x6f,0x6f + }; + + outlen = sizeof(out); + XMEMSET(out, 0, sizeof(out)); + + if (wc_ed25519_import_private_key(sKeyPh, ED25519_KEY_SIZE, pKeyPh, + sizeof(pKeyPh), &key) != 0) { + return -10500; + } + + if (wc_ed25519ph_sign_msg(msgPh, sizeof(msgPh), out, &outlen, &key, NULL, + 0) != 0) { + return -10501; + } + + if (XMEMCMP(out, sigPh1, 64)) + return -10502; + +#if defined(HAVE_ED25519_VERIFY) + /* test verify on good msg */ + if (wc_ed25519ph_verify_msg(out, outlen, msgPh, sizeof(msgPh), &verify, + &key, NULL, 0) != 0 || + verify != 1) { + return -10503; + } +#endif + + if (wc_ed25519ph_sign_msg(msgPh, sizeof(msgPh), out, &outlen, &key, + contextPh2, sizeof(contextPh2)) != 0) { + return -10504; + } + + if (XMEMCMP(out, sigPh2, 64)) + return -10505; + +#if defined(HAVE_ED25519_VERIFY) + /* test verify on good msg */ + if (wc_ed25519ph_verify_msg(out, outlen, msgPh, sizeof(msgPh), &verify, + &key, contextPh2, sizeof(contextPh2)) != 0 || + verify != 1) { + return -10506; + } +#endif + + if (wc_ed25519ph_sign_hash(hashPh, sizeof(hashPh), out, &outlen, &key, NULL, + 0) != 0) { + return -10507; + } + + if (XMEMCMP(out, sigPh1, 64)) + return -10508; + +#if defined(HAVE_ED25519_VERIFY) + if (wc_ed25519ph_verify_hash(out, outlen, hashPh, sizeof(hashPh), &verify, + &key, NULL, 0) != 0 || + verify != 1) { + return -10509; + } +#endif + + if (wc_ed25519ph_sign_hash(hashPh, sizeof(hashPh), out, &outlen, &key, + contextPh2, sizeof(contextPh2)) != 0) { + return -10510; + } + + if (XMEMCMP(out, sigPh2, 64)) + return -10511; + +#if defined(HAVE_ED25519_VERIFY) + if (wc_ed25519ph_verify_hash(out, outlen, hashPh, sizeof(hashPh), &verify, + &key, contextPh2, sizeof(contextPh2)) != 0 || + verify != 1) { + return -10512; + } +#endif + + wc_ed25519_free(&key); + + return 0; +} +#endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */ + int ed25519_test(void) { - RNG rng; + int ret; + WC_RNG rng; +#if defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_KEY_EXPORT) &&\ + defined(HAVE_ED25519_KEY_IMPORT) byte out[ED25519_SIG_SIZE]; byte exportPKey[ED25519_KEY_SIZE]; byte exportSKey[ED25519_KEY_SIZE]; - word32 outlen; word32 exportPSz; word32 exportSSz; + int i; + word32 outlen; +#ifdef HAVE_ED25519_VERIFY + int verify; +#endif /* HAVE_ED25519_VERIFY */ +#endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */ word32 keySz, sigSz; - int i, verify; ed25519_key key; ed25519_key key2; +#if defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_KEY_EXPORT) && \ + defined(HAVE_ED25519_KEY_IMPORT) /* test vectors from https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-02 */ - const byte sKey1[] = { - 0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60, - 0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4, - 0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19, - 0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60 + static const byte sKey1[] = { + 0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60, + 0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4, + 0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19, + 0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60 }; - const byte sKey2[] = { - 0x4c,0xcd,0x08,0x9b,0x28,0xff,0x96,0xda, - 0x9d,0xb6,0xc3,0x46,0xec,0x11,0x4e,0x0f, - 0x5b,0x8a,0x31,0x9f,0x35,0xab,0xa6,0x24, - 0xda,0x8c,0xf6,0xed,0x4f,0xb8,0xa6,0xfb + static const byte sKey2[] = { + 0x4c,0xcd,0x08,0x9b,0x28,0xff,0x96,0xda, + 0x9d,0xb6,0xc3,0x46,0xec,0x11,0x4e,0x0f, + 0x5b,0x8a,0x31,0x9f,0x35,0xab,0xa6,0x24, + 0xda,0x8c,0xf6,0xed,0x4f,0xb8,0xa6,0xfb }; - const byte sKey3[] = { - 0xc5,0xaa,0x8d,0xf4,0x3f,0x9f,0x83,0x7b, - 0xed,0xb7,0x44,0x2f,0x31,0xdc,0xb7,0xb1, - 0x66,0xd3,0x85,0x35,0x07,0x6f,0x09,0x4b, - 0x85,0xce,0x3a,0x2e,0x0b,0x44,0x58,0xf7 + static const byte sKey3[] = { + 0xc5,0xaa,0x8d,0xf4,0x3f,0x9f,0x83,0x7b, + 0xed,0xb7,0x44,0x2f,0x31,0xdc,0xb7,0xb1, + 0x66,0xd3,0x85,0x35,0x07,0x6f,0x09,0x4b, + 0x85,0xce,0x3a,0x2e,0x0b,0x44,0x58,0xf7 }; /* uncompressed test */ - const byte sKey4[] = { - 0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60, - 0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4, - 0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19, - 0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60 + static const byte sKey4[] = { + 0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60, + 0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4, + 0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19, + 0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60 }; /* compressed prefix test */ - const byte sKey5[] = { - 0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60, - 0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4, - 0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19, - 0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60 + static const byte sKey5[] = { + 0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60, + 0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4, + 0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19, + 0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60 }; - const byte sKey6[] = { - 0xf5,0xe5,0x76,0x7c,0xf1,0x53,0x31,0x95, - 0x17,0x63,0x0f,0x22,0x68,0x76,0xb8,0x6c, - 0x81,0x60,0xcc,0x58,0x3b,0xc0,0x13,0x74, - 0x4c,0x6b,0xf2,0x55,0xf5,0xcc,0x0e,0xe5 + static const byte sKey6[] = { + 0xf5,0xe5,0x76,0x7c,0xf1,0x53,0x31,0x95, + 0x17,0x63,0x0f,0x22,0x68,0x76,0xb8,0x6c, + 0x81,0x60,0xcc,0x58,0x3b,0xc0,0x13,0x74, + 0x4c,0x6b,0xf2,0x55,0xf5,0xcc,0x0e,0xe5 }; - const byte* sKeys[] = {sKey1, sKey2, sKey3, sKey4, sKey5, sKey6}; + static const byte* sKeys[] = {sKey1, sKey2, sKey3, sKey4, sKey5, sKey6}; - const byte pKey1[] = { - 0xd7,0x5a,0x98,0x01,0x82,0xb1,0x0a,0xb7, - 0xd5,0x4b,0xfe,0xd3,0xc9,0x64,0x07,0x3a, - 0x0e,0xe1,0x72,0xf3,0xda,0xa6,0x23,0x25, - 0xaf,0x02,0x1a,0x68,0xf7,0x07,0x51,0x1a + static const byte pKey1[] = { + 0xd7,0x5a,0x98,0x01,0x82,0xb1,0x0a,0xb7, + 0xd5,0x4b,0xfe,0xd3,0xc9,0x64,0x07,0x3a, + 0x0e,0xe1,0x72,0xf3,0xda,0xa6,0x23,0x25, + 0xaf,0x02,0x1a,0x68,0xf7,0x07,0x51,0x1a }; - const byte pKey2[] = { - 0x3d,0x40,0x17,0xc3,0xe8,0x43,0x89,0x5a, - 0x92,0xb7,0x0a,0xa7,0x4d,0x1b,0x7e,0xbc, + static const byte pKey2[] = { + 0x3d,0x40,0x17,0xc3,0xe8,0x43,0x89,0x5a, + 0x92,0xb7,0x0a,0xa7,0x4d,0x1b,0x7e,0xbc, 0x9c,0x98,0x2c,0xcf,0x2e,0xc4,0x96,0x8c, - 0xc0,0xcd,0x55,0xf1,0x2a,0xf4,0x66,0x0c + 0xc0,0xcd,0x55,0xf1,0x2a,0xf4,0x66,0x0c }; - const byte pKey3[] = { - 0xfc,0x51,0xcd,0x8e,0x62,0x18,0xa1,0xa3, - 0x8d,0xa4,0x7e,0xd0,0x02,0x30,0xf0,0x58, - 0x08,0x16,0xed,0x13,0xba,0x33,0x03,0xac, - 0x5d,0xeb,0x91,0x15,0x48,0x90,0x80,0x25 + static const byte pKey3[] = { + 0xfc,0x51,0xcd,0x8e,0x62,0x18,0xa1,0xa3, + 0x8d,0xa4,0x7e,0xd0,0x02,0x30,0xf0,0x58, + 0x08,0x16,0xed,0x13,0xba,0x33,0x03,0xac, + 0x5d,0xeb,0x91,0x15,0x48,0x90,0x80,0x25 }; /* uncompressed test */ - const byte pKey4[] = { - 0x04,0x55,0xd0,0xe0,0x9a,0x2b,0x9d,0x34, - 0x29,0x22,0x97,0xe0,0x8d,0x60,0xd0,0xf6, - 0x20,0xc5,0x13,0xd4,0x72,0x53,0x18,0x7c, - 0x24,0xb1,0x27,0x86,0xbd,0x77,0x76,0x45, - 0xce,0x1a,0x51,0x07,0xf7,0x68,0x1a,0x02, - 0xaf,0x25,0x23,0xa6,0xda,0xf3,0x72,0xe1, - 0x0e,0x3a,0x07,0x64,0xc9,0xd3,0xfe,0x4b, - 0xd5,0xb7,0x0a,0xb1,0x82,0x01,0x98,0x5a, - 0xd7 + static const byte pKey4[] = { + 0x04,0x55,0xd0,0xe0,0x9a,0x2b,0x9d,0x34, + 0x29,0x22,0x97,0xe0,0x8d,0x60,0xd0,0xf6, + 0x20,0xc5,0x13,0xd4,0x72,0x53,0x18,0x7c, + 0x24,0xb1,0x27,0x86,0xbd,0x77,0x76,0x45, + 0xce,0x1a,0x51,0x07,0xf7,0x68,0x1a,0x02, + 0xaf,0x25,0x23,0xa6,0xda,0xf3,0x72,0xe1, + 0x0e,0x3a,0x07,0x64,0xc9,0xd3,0xfe,0x4b, + 0xd5,0xb7,0x0a,0xb1,0x82,0x01,0x98,0x5a, + 0xd7 }; /* compressed prefix */ - const byte pKey5[] = { - 0x40,0xd7,0x5a,0x98,0x01,0x82,0xb1,0x0a,0xb7, - 0xd5,0x4b,0xfe,0xd3,0xc9,0x64,0x07,0x3a, - 0x0e,0xe1,0x72,0xf3,0xda,0xa6,0x23,0x25, - 0xaf,0x02,0x1a,0x68,0xf7,0x07,0x51,0x1a + static const byte pKey5[] = { + 0x40,0xd7,0x5a,0x98,0x01,0x82,0xb1,0x0a,0xb7, + 0xd5,0x4b,0xfe,0xd3,0xc9,0x64,0x07,0x3a, + 0x0e,0xe1,0x72,0xf3,0xda,0xa6,0x23,0x25, + 0xaf,0x02,0x1a,0x68,0xf7,0x07,0x51,0x1a }; - const byte pKey6[] = { - 0x27,0x81,0x17,0xfc,0x14,0x4c,0x72,0x34, - 0x0f,0x67,0xd0,0xf2,0x31,0x6e,0x83,0x86, - 0xce,0xff,0xbf,0x2b,0x24,0x28,0xc9,0xc5, - 0x1f,0xef,0x7c,0x59,0x7f,0x1d,0x42,0x6e + static const byte pKey6[] = { + 0x27,0x81,0x17,0xfc,0x14,0x4c,0x72,0x34, + 0x0f,0x67,0xd0,0xf2,0x31,0x6e,0x83,0x86, + 0xce,0xff,0xbf,0x2b,0x24,0x28,0xc9,0xc5, + 0x1f,0xef,0x7c,0x59,0x7f,0x1d,0x42,0x6e }; - const byte* pKeys[] = {pKey1, pKey2, pKey3, pKey4, pKey5, pKey6}; - const byte pKeySz[] = {sizeof(pKey1), sizeof(pKey2), sizeof(pKey3), + static const byte* pKeys[] = {pKey1, pKey2, pKey3, pKey4, pKey5, pKey6}; + static const byte pKeySz[] = {sizeof(pKey1), sizeof(pKey2), sizeof(pKey3), sizeof(pKey4), sizeof(pKey5), sizeof(pKey6)}; - const byte sig1[] = { - 0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72, - 0x90,0x86,0xe2,0xcc,0x80,0x6e,0x82,0x8a, - 0x84,0x87,0x7f,0x1e,0xb8,0xe5,0xd9,0x74, - 0xd8,0x73,0xe0,0x65,0x22,0x49,0x01,0x55, - 0x5f,0xb8,0x82,0x15,0x90,0xa3,0x3b,0xac, - 0xc6,0x1e,0x39,0x70,0x1c,0xf9,0xb4,0x6b, - 0xd2,0x5b,0xf5,0xf0,0x59,0x5b,0xbe,0x24, - 0x65,0x51,0x41,0x43,0x8e,0x7a,0x10,0x0b + static const byte sig1[] = { + 0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72, + 0x90,0x86,0xe2,0xcc,0x80,0x6e,0x82,0x8a, + 0x84,0x87,0x7f,0x1e,0xb8,0xe5,0xd9,0x74, + 0xd8,0x73,0xe0,0x65,0x22,0x49,0x01,0x55, + 0x5f,0xb8,0x82,0x15,0x90,0xa3,0x3b,0xac, + 0xc6,0x1e,0x39,0x70,0x1c,0xf9,0xb4,0x6b, + 0xd2,0x5b,0xf5,0xf0,0x59,0x5b,0xbe,0x24, + 0x65,0x51,0x41,0x43,0x8e,0x7a,0x10,0x0b }; - const byte sig2[] = { - 0x92,0xa0,0x09,0xa9,0xf0,0xd4,0xca,0xb8, - 0x72,0x0e,0x82,0x0b,0x5f,0x64,0x25,0x40, - 0xa2,0xb2,0x7b,0x54,0x16,0x50,0x3f,0x8f, - 0xb3,0x76,0x22,0x23,0xeb,0xdb,0x69,0xda, - 0x08,0x5a,0xc1,0xe4,0x3e,0x15,0x99,0x6e, - 0x45,0x8f,0x36,0x13,0xd0,0xf1,0x1d,0x8c, - 0x38,0x7b,0x2e,0xae,0xb4,0x30,0x2a,0xee, - 0xb0,0x0d,0x29,0x16,0x12,0xbb,0x0c,0x00 + static const byte sig2[] = { + 0x92,0xa0,0x09,0xa9,0xf0,0xd4,0xca,0xb8, + 0x72,0x0e,0x82,0x0b,0x5f,0x64,0x25,0x40, + 0xa2,0xb2,0x7b,0x54,0x16,0x50,0x3f,0x8f, + 0xb3,0x76,0x22,0x23,0xeb,0xdb,0x69,0xda, + 0x08,0x5a,0xc1,0xe4,0x3e,0x15,0x99,0x6e, + 0x45,0x8f,0x36,0x13,0xd0,0xf1,0x1d,0x8c, + 0x38,0x7b,0x2e,0xae,0xb4,0x30,0x2a,0xee, + 0xb0,0x0d,0x29,0x16,0x12,0xbb,0x0c,0x00 }; - const byte sig3[] = { - 0x62,0x91,0xd6,0x57,0xde,0xec,0x24,0x02, - 0x48,0x27,0xe6,0x9c,0x3a,0xbe,0x01,0xa3, - 0x0c,0xe5,0x48,0xa2,0x84,0x74,0x3a,0x44, - 0x5e,0x36,0x80,0xd7,0xdb,0x5a,0xc3,0xac, - 0x18,0xff,0x9b,0x53,0x8d,0x16,0xf2,0x90, - 0xae,0x67,0xf7,0x60,0x98,0x4d,0xc6,0x59, - 0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d, - 0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a + static const byte sig3[] = { + 0x62,0x91,0xd6,0x57,0xde,0xec,0x24,0x02, + 0x48,0x27,0xe6,0x9c,0x3a,0xbe,0x01,0xa3, + 0x0c,0xe5,0x48,0xa2,0x84,0x74,0x3a,0x44, + 0x5e,0x36,0x80,0xd7,0xdb,0x5a,0xc3,0xac, + 0x18,0xff,0x9b,0x53,0x8d,0x16,0xf2,0x90, + 0xae,0x67,0xf7,0x60,0x98,0x4d,0xc6,0x59, + 0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d, + 0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a }; /* uncompressed test */ - const byte sig4[] = { - 0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72, - 0x90,0x86,0xe2,0xcc,0x80,0x6e,0x82,0x8a, - 0x84,0x87,0x7f,0x1e,0xb8,0xe5,0xd9,0x74, - 0xd8,0x73,0xe0,0x65,0x22,0x49,0x01,0x55, - 0x5f,0xb8,0x82,0x15,0x90,0xa3,0x3b,0xac, - 0xc6,0x1e,0x39,0x70,0x1c,0xf9,0xb4,0x6b, - 0xd2,0x5b,0xf5,0xf0,0x59,0x5b,0xbe,0x24, - 0x65,0x51,0x41,0x43,0x8e,0x7a,0x10,0x0b + static const byte sig4[] = { + 0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72, + 0x90,0x86,0xe2,0xcc,0x80,0x6e,0x82,0x8a, + 0x84,0x87,0x7f,0x1e,0xb8,0xe5,0xd9,0x74, + 0xd8,0x73,0xe0,0x65,0x22,0x49,0x01,0x55, + 0x5f,0xb8,0x82,0x15,0x90,0xa3,0x3b,0xac, + 0xc6,0x1e,0x39,0x70,0x1c,0xf9,0xb4,0x6b, + 0xd2,0x5b,0xf5,0xf0,0x59,0x5b,0xbe,0x24, + 0x65,0x51,0x41,0x43,0x8e,0x7a,0x10,0x0b }; /* compressed prefix */ - const byte sig5[] = { - 0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72, - 0x90,0x86,0xe2,0xcc,0x80,0x6e,0x82,0x8a, - 0x84,0x87,0x7f,0x1e,0xb8,0xe5,0xd9,0x74, - 0xd8,0x73,0xe0,0x65,0x22,0x49,0x01,0x55, - 0x5f,0xb8,0x82,0x15,0x90,0xa3,0x3b,0xac, - 0xc6,0x1e,0x39,0x70,0x1c,0xf9,0xb4,0x6b, - 0xd2,0x5b,0xf5,0xf0,0x59,0x5b,0xbe,0x24, - 0x65,0x51,0x41,0x43,0x8e,0x7a,0x10,0x0b + static const byte sig5[] = { + 0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72, + 0x90,0x86,0xe2,0xcc,0x80,0x6e,0x82,0x8a, + 0x84,0x87,0x7f,0x1e,0xb8,0xe5,0xd9,0x74, + 0xd8,0x73,0xe0,0x65,0x22,0x49,0x01,0x55, + 0x5f,0xb8,0x82,0x15,0x90,0xa3,0x3b,0xac, + 0xc6,0x1e,0x39,0x70,0x1c,0xf9,0xb4,0x6b, + 0xd2,0x5b,0xf5,0xf0,0x59,0x5b,0xbe,0x24, + 0x65,0x51,0x41,0x43,0x8e,0x7a,0x10,0x0b }; - const byte sig6[] = { - 0x0a,0xab,0x4c,0x90,0x05,0x01,0xb3,0xe2, - 0x4d,0x7c,0xdf,0x46,0x63,0x32,0x6a,0x3a, - 0x87,0xdf,0x5e,0x48,0x43,0xb2,0xcb,0xdb, - 0x67,0xcb,0xf6,0xe4,0x60,0xfe,0xc3,0x50, - 0xaa,0x53,0x71,0xb1,0x50,0x8f,0x9f,0x45, - 0x28,0xec,0xea,0x23,0xc4,0x36,0xd9,0x4b, - 0x5e,0x8f,0xcd,0x4f,0x68,0x1e,0x30,0xa6, - 0xac,0x00,0xa9,0x70,0x4a,0x18,0x8a,0x03 + static const byte sig6[] = { + 0x0a,0xab,0x4c,0x90,0x05,0x01,0xb3,0xe2, + 0x4d,0x7c,0xdf,0x46,0x63,0x32,0x6a,0x3a, + 0x87,0xdf,0x5e,0x48,0x43,0xb2,0xcb,0xdb, + 0x67,0xcb,0xf6,0xe4,0x60,0xfe,0xc3,0x50, + 0xaa,0x53,0x71,0xb1,0x50,0x8f,0x9f,0x45, + 0x28,0xec,0xea,0x23,0xc4,0x36,0xd9,0x4b, + 0x5e,0x8f,0xcd,0x4f,0x68,0x1e,0x30,0xa6, + 0xac,0x00,0xa9,0x70,0x4a,0x18,0x8a,0x03 }; - const byte* sigs[] = {sig1, sig2, sig3, sig4, sig5, sig6}; + static const byte* sigs[] = {sig1, sig2, sig3, sig4, sig5, sig6}; - const byte msg1[] = {}; - const byte msg2[] = {0x72}; - const byte msg3[] = {0xAF,0x82}; + static const byte msg1[] = {0x0 }; + static const byte msg2[] = {0x72}; + static const byte msg3[] = {0xAF,0x82}; /* test of a 1024 byte long message */ - const byte msg4[] = { - 0x08,0xb8,0xb2,0xb7,0x33,0x42,0x42,0x43, - 0x76,0x0f,0xe4,0x26,0xa4,0xb5,0x49,0x08, - 0x63,0x21,0x10,0xa6,0x6c,0x2f,0x65,0x91, - 0xea,0xbd,0x33,0x45,0xe3,0xe4,0xeb,0x98, - 0xfa,0x6e,0x26,0x4b,0xf0,0x9e,0xfe,0x12, - 0xee,0x50,0xf8,0xf5,0x4e,0x9f,0x77,0xb1, - 0xe3,0x55,0xf6,0xc5,0x05,0x44,0xe2,0x3f, - 0xb1,0x43,0x3d,0xdf,0x73,0xbe,0x84,0xd8, - 0x79,0xde,0x7c,0x00,0x46,0xdc,0x49,0x96, - 0xd9,0xe7,0x73,0xf4,0xbc,0x9e,0xfe,0x57, - 0x38,0x82,0x9a,0xdb,0x26,0xc8,0x1b,0x37, - 0xc9,0x3a,0x1b,0x27,0x0b,0x20,0x32,0x9d, - 0x65,0x86,0x75,0xfc,0x6e,0xa5,0x34,0xe0, - 0x81,0x0a,0x44,0x32,0x82,0x6b,0xf5,0x8c, - 0x94,0x1e,0xfb,0x65,0xd5,0x7a,0x33,0x8b, - 0xbd,0x2e,0x26,0x64,0x0f,0x89,0xff,0xbc, - 0x1a,0x85,0x8e,0xfc,0xb8,0x55,0x0e,0xe3, - 0xa5,0xe1,0x99,0x8b,0xd1,0x77,0xe9,0x3a, - 0x73,0x63,0xc3,0x44,0xfe,0x6b,0x19,0x9e, - 0xe5,0xd0,0x2e,0x82,0xd5,0x22,0xc4,0xfe, - 0xba,0x15,0x45,0x2f,0x80,0x28,0x8a,0x82, - 0x1a,0x57,0x91,0x16,0xec,0x6d,0xad,0x2b, - 0x3b,0x31,0x0d,0xa9,0x03,0x40,0x1a,0xa6, - 0x21,0x00,0xab,0x5d,0x1a,0x36,0x55,0x3e, - 0x06,0x20,0x3b,0x33,0x89,0x0c,0xc9,0xb8, - 0x32,0xf7,0x9e,0xf8,0x05,0x60,0xcc,0xb9, - 0xa3,0x9c,0xe7,0x67,0x96,0x7e,0xd6,0x28, - 0xc6,0xad,0x57,0x3c,0xb1,0x16,0xdb,0xef, - 0xef,0xd7,0x54,0x99,0xda,0x96,0xbd,0x68, - 0xa8,0xa9,0x7b,0x92,0x8a,0x8b,0xbc,0x10, - 0x3b,0x66,0x21,0xfc,0xde,0x2b,0xec,0xa1, - 0x23,0x1d,0x20,0x6b,0xe6,0xcd,0x9e,0xc7, - 0xaf,0xf6,0xf6,0xc9,0x4f,0xcd,0x72,0x04, - 0xed,0x34,0x55,0xc6,0x8c,0x83,0xf4,0xa4, - 0x1d,0xa4,0xaf,0x2b,0x74,0xef,0x5c,0x53, - 0xf1,0xd8,0xac,0x70,0xbd,0xcb,0x7e,0xd1, - 0x85,0xce,0x81,0xbd,0x84,0x35,0x9d,0x44, - 0x25,0x4d,0x95,0x62,0x9e,0x98,0x55,0xa9, - 0x4a,0x7c,0x19,0x58,0xd1,0xf8,0xad,0xa5, - 0xd0,0x53,0x2e,0xd8,0xa5,0xaa,0x3f,0xb2, - 0xd1,0x7b,0xa7,0x0e,0xb6,0x24,0x8e,0x59, - 0x4e,0x1a,0x22,0x97,0xac,0xbb,0xb3,0x9d, - 0x50,0x2f,0x1a,0x8c,0x6e,0xb6,0xf1,0xce, - 0x22,0xb3,0xde,0x1a,0x1f,0x40,0xcc,0x24, - 0x55,0x41,0x19,0xa8,0x31,0xa9,0xaa,0xd6, - 0x07,0x9c,0xad,0x88,0x42,0x5d,0xe6,0xbd, - 0xe1,0xa9,0x18,0x7e,0xbb,0x60,0x92,0xcf, - 0x67,0xbf,0x2b,0x13,0xfd,0x65,0xf2,0x70, - 0x88,0xd7,0x8b,0x7e,0x88,0x3c,0x87,0x59, - 0xd2,0xc4,0xf5,0xc6,0x5a,0xdb,0x75,0x53, - 0x87,0x8a,0xd5,0x75,0xf9,0xfa,0xd8,0x78, - 0xe8,0x0a,0x0c,0x9b,0xa6,0x3b,0xcb,0xcc, - 0x27,0x32,0xe6,0x94,0x85,0xbb,0xc9,0xc9, - 0x0b,0xfb,0xd6,0x24,0x81,0xd9,0x08,0x9b, - 0xec,0xcf,0x80,0xcf,0xe2,0xdf,0x16,0xa2, - 0xcf,0x65,0xbd,0x92,0xdd,0x59,0x7b,0x07, - 0x07,0xe0,0x91,0x7a,0xf4,0x8b,0xbb,0x75, - 0xfe,0xd4,0x13,0xd2,0x38,0xf5,0x55,0x5a, - 0x7a,0x56,0x9d,0x80,0xc3,0x41,0x4a,0x8d, - 0x08,0x59,0xdc,0x65,0xa4,0x61,0x28,0xba, - 0xb2,0x7a,0xf8,0x7a,0x71,0x31,0x4f,0x31, - 0x8c,0x78,0x2b,0x23,0xeb,0xfe,0x80,0x8b, - 0x82,0xb0,0xce,0x26,0x40,0x1d,0x2e,0x22, - 0xf0,0x4d,0x83,0xd1,0x25,0x5d,0xc5,0x1a, - 0xdd,0xd3,0xb7,0x5a,0x2b,0x1a,0xe0,0x78, - 0x45,0x04,0xdf,0x54,0x3a,0xf8,0x96,0x9b, - 0xe3,0xea,0x70,0x82,0xff,0x7f,0xc9,0x88, - 0x8c,0x14,0x4d,0xa2,0xaf,0x58,0x42,0x9e, - 0xc9,0x60,0x31,0xdb,0xca,0xd3,0xda,0xd9, - 0xaf,0x0d,0xcb,0xaa,0xaf,0x26,0x8c,0xb8, - 0xfc,0xff,0xea,0xd9,0x4f,0x3c,0x7c,0xa4, - 0x95,0xe0,0x56,0xa9,0xb4,0x7a,0xcd,0xb7, - 0x51,0xfb,0x73,0xe6,0x66,0xc6,0xc6,0x55, - 0xad,0xe8,0x29,0x72,0x97,0xd0,0x7a,0xd1, - 0xba,0x5e,0x43,0xf1,0xbc,0xa3,0x23,0x01, - 0x65,0x13,0x39,0xe2,0x29,0x04,0xcc,0x8c, - 0x42,0xf5,0x8c,0x30,0xc0,0x4a,0xaf,0xdb, - 0x03,0x8d,0xda,0x08,0x47,0xdd,0x98,0x8d, - 0xcd,0xa6,0xf3,0xbf,0xd1,0x5c,0x4b,0x4c, - 0x45,0x25,0x00,0x4a,0xa0,0x6e,0xef,0xf8, - 0xca,0x61,0x78,0x3a,0xac,0xec,0x57,0xfb, - 0x3d,0x1f,0x92,0xb0,0xfe,0x2f,0xd1,0xa8, - 0x5f,0x67,0x24,0x51,0x7b,0x65,0xe6,0x14, - 0xad,0x68,0x08,0xd6,0xf6,0xee,0x34,0xdf, - 0xf7,0x31,0x0f,0xdc,0x82,0xae,0xbf,0xd9, - 0x04,0xb0,0x1e,0x1d,0xc5,0x4b,0x29,0x27, - 0x09,0x4b,0x2d,0xb6,0x8d,0x6f,0x90,0x3b, - 0x68,0x40,0x1a,0xde,0xbf,0x5a,0x7e,0x08, - 0xd7,0x8f,0xf4,0xef,0x5d,0x63,0x65,0x3a, - 0x65,0x04,0x0c,0xf9,0xbf,0xd4,0xac,0xa7, - 0x98,0x4a,0x74,0xd3,0x71,0x45,0x98,0x67, - 0x80,0xfc,0x0b,0x16,0xac,0x45,0x16,0x49, - 0xde,0x61,0x88,0xa7,0xdb,0xdf,0x19,0x1f, - 0x64,0xb5,0xfc,0x5e,0x2a,0xb4,0x7b,0x57, - 0xf7,0xf7,0x27,0x6c,0xd4,0x19,0xc1,0x7a, - 0x3c,0xa8,0xe1,0xb9,0x39,0xae,0x49,0xe4, - 0x88,0xac,0xba,0x6b,0x96,0x56,0x10,0xb5, - 0x48,0x01,0x09,0xc8,0xb1,0x7b,0x80,0xe1, - 0xb7,0xb7,0x50,0xdf,0xc7,0x59,0x8d,0x5d, - 0x50,0x11,0xfd,0x2d,0xcc,0x56,0x00,0xa3, - 0x2e,0xf5,0xb5,0x2a,0x1e,0xcc,0x82,0x0e, - 0x30,0x8a,0xa3,0x42,0x72,0x1a,0xac,0x09, - 0x43,0xbf,0x66,0x86,0xb6,0x4b,0x25,0x79, - 0x37,0x65,0x04,0xcc,0xc4,0x93,0xd9,0x7e, - 0x6a,0xed,0x3f,0xb0,0xf9,0xcd,0x71,0xa4, - 0x3d,0xd4,0x97,0xf0,0x1f,0x17,0xc0,0xe2, - 0xcb,0x37,0x97,0xaa,0x2a,0x2f,0x25,0x66, - 0x56,0x16,0x8e,0x6c,0x49,0x6a,0xfc,0x5f, - 0xb9,0x32,0x46,0xf6,0xb1,0x11,0x63,0x98, - 0xa3,0x46,0xf1,0xa6,0x41,0xf3,0xb0,0x41, - 0xe9,0x89,0xf7,0x91,0x4f,0x90,0xcc,0x2c, - 0x7f,0xff,0x35,0x78,0x76,0xe5,0x06,0xb5, - 0x0d,0x33,0x4b,0xa7,0x7c,0x22,0x5b,0xc3, - 0x07,0xba,0x53,0x71,0x52,0xf3,0xf1,0x61, - 0x0e,0x4e,0xaf,0xe5,0x95,0xf6,0xd9,0xd9, - 0x0d,0x11,0xfa,0xa9,0x33,0xa1,0x5e,0xf1, - 0x36,0x95,0x46,0x86,0x8a,0x7f,0x3a,0x45, - 0xa9,0x67,0x68,0xd4,0x0f,0xd9,0xd0,0x34, - 0x12,0xc0,0x91,0xc6,0x31,0x5c,0xf4,0xfd, - 0xe7,0xcb,0x68,0x60,0x69,0x37,0x38,0x0d, - 0xb2,0xea,0xaa,0x70,0x7b,0x4c,0x41,0x85, - 0xc3,0x2e,0xdd,0xcd,0xd3,0x06,0x70,0x5e, - 0x4d,0xc1,0xff,0xc8,0x72,0xee,0xee,0x47, - 0x5a,0x64,0xdf,0xac,0x86,0xab,0xa4,0x1c, - 0x06,0x18,0x98,0x3f,0x87,0x41,0xc5,0xef, - 0x68,0xd3,0xa1,0x01,0xe8,0xa3,0xb8,0xca, - 0xc6,0x0c,0x90,0x5c,0x15,0xfc,0x91,0x08, - 0x40,0xb9,0x4c,0x00,0xa0,0xb9,0xd0 + static const byte msg4[] = { + 0x08,0xb8,0xb2,0xb7,0x33,0x42,0x42,0x43, + 0x76,0x0f,0xe4,0x26,0xa4,0xb5,0x49,0x08, + 0x63,0x21,0x10,0xa6,0x6c,0x2f,0x65,0x91, + 0xea,0xbd,0x33,0x45,0xe3,0xe4,0xeb,0x98, + 0xfa,0x6e,0x26,0x4b,0xf0,0x9e,0xfe,0x12, + 0xee,0x50,0xf8,0xf5,0x4e,0x9f,0x77,0xb1, + 0xe3,0x55,0xf6,0xc5,0x05,0x44,0xe2,0x3f, + 0xb1,0x43,0x3d,0xdf,0x73,0xbe,0x84,0xd8, + 0x79,0xde,0x7c,0x00,0x46,0xdc,0x49,0x96, + 0xd9,0xe7,0x73,0xf4,0xbc,0x9e,0xfe,0x57, + 0x38,0x82,0x9a,0xdb,0x26,0xc8,0x1b,0x37, + 0xc9,0x3a,0x1b,0x27,0x0b,0x20,0x32,0x9d, + 0x65,0x86,0x75,0xfc,0x6e,0xa5,0x34,0xe0, + 0x81,0x0a,0x44,0x32,0x82,0x6b,0xf5,0x8c, + 0x94,0x1e,0xfb,0x65,0xd5,0x7a,0x33,0x8b, + 0xbd,0x2e,0x26,0x64,0x0f,0x89,0xff,0xbc, + 0x1a,0x85,0x8e,0xfc,0xb8,0x55,0x0e,0xe3, + 0xa5,0xe1,0x99,0x8b,0xd1,0x77,0xe9,0x3a, + 0x73,0x63,0xc3,0x44,0xfe,0x6b,0x19,0x9e, + 0xe5,0xd0,0x2e,0x82,0xd5,0x22,0xc4,0xfe, + 0xba,0x15,0x45,0x2f,0x80,0x28,0x8a,0x82, + 0x1a,0x57,0x91,0x16,0xec,0x6d,0xad,0x2b, + 0x3b,0x31,0x0d,0xa9,0x03,0x40,0x1a,0xa6, + 0x21,0x00,0xab,0x5d,0x1a,0x36,0x55,0x3e, + 0x06,0x20,0x3b,0x33,0x89,0x0c,0xc9,0xb8, + 0x32,0xf7,0x9e,0xf8,0x05,0x60,0xcc,0xb9, + 0xa3,0x9c,0xe7,0x67,0x96,0x7e,0xd6,0x28, + 0xc6,0xad,0x57,0x3c,0xb1,0x16,0xdb,0xef, + 0xef,0xd7,0x54,0x99,0xda,0x96,0xbd,0x68, + 0xa8,0xa9,0x7b,0x92,0x8a,0x8b,0xbc,0x10, + 0x3b,0x66,0x21,0xfc,0xde,0x2b,0xec,0xa1, + 0x23,0x1d,0x20,0x6b,0xe6,0xcd,0x9e,0xc7, + 0xaf,0xf6,0xf6,0xc9,0x4f,0xcd,0x72,0x04, + 0xed,0x34,0x55,0xc6,0x8c,0x83,0xf4,0xa4, + 0x1d,0xa4,0xaf,0x2b,0x74,0xef,0x5c,0x53, + 0xf1,0xd8,0xac,0x70,0xbd,0xcb,0x7e,0xd1, + 0x85,0xce,0x81,0xbd,0x84,0x35,0x9d,0x44, + 0x25,0x4d,0x95,0x62,0x9e,0x98,0x55,0xa9, + 0x4a,0x7c,0x19,0x58,0xd1,0xf8,0xad,0xa5, + 0xd0,0x53,0x2e,0xd8,0xa5,0xaa,0x3f,0xb2, + 0xd1,0x7b,0xa7,0x0e,0xb6,0x24,0x8e,0x59, + 0x4e,0x1a,0x22,0x97,0xac,0xbb,0xb3,0x9d, + 0x50,0x2f,0x1a,0x8c,0x6e,0xb6,0xf1,0xce, + 0x22,0xb3,0xde,0x1a,0x1f,0x40,0xcc,0x24, + 0x55,0x41,0x19,0xa8,0x31,0xa9,0xaa,0xd6, + 0x07,0x9c,0xad,0x88,0x42,0x5d,0xe6,0xbd, + 0xe1,0xa9,0x18,0x7e,0xbb,0x60,0x92,0xcf, + 0x67,0xbf,0x2b,0x13,0xfd,0x65,0xf2,0x70, + 0x88,0xd7,0x8b,0x7e,0x88,0x3c,0x87,0x59, + 0xd2,0xc4,0xf5,0xc6,0x5a,0xdb,0x75,0x53, + 0x87,0x8a,0xd5,0x75,0xf9,0xfa,0xd8,0x78, + 0xe8,0x0a,0x0c,0x9b,0xa6,0x3b,0xcb,0xcc, + 0x27,0x32,0xe6,0x94,0x85,0xbb,0xc9,0xc9, + 0x0b,0xfb,0xd6,0x24,0x81,0xd9,0x08,0x9b, + 0xec,0xcf,0x80,0xcf,0xe2,0xdf,0x16,0xa2, + 0xcf,0x65,0xbd,0x92,0xdd,0x59,0x7b,0x07, + 0x07,0xe0,0x91,0x7a,0xf4,0x8b,0xbb,0x75, + 0xfe,0xd4,0x13,0xd2,0x38,0xf5,0x55,0x5a, + 0x7a,0x56,0x9d,0x80,0xc3,0x41,0x4a,0x8d, + 0x08,0x59,0xdc,0x65,0xa4,0x61,0x28,0xba, + 0xb2,0x7a,0xf8,0x7a,0x71,0x31,0x4f,0x31, + 0x8c,0x78,0x2b,0x23,0xeb,0xfe,0x80,0x8b, + 0x82,0xb0,0xce,0x26,0x40,0x1d,0x2e,0x22, + 0xf0,0x4d,0x83,0xd1,0x25,0x5d,0xc5,0x1a, + 0xdd,0xd3,0xb7,0x5a,0x2b,0x1a,0xe0,0x78, + 0x45,0x04,0xdf,0x54,0x3a,0xf8,0x96,0x9b, + 0xe3,0xea,0x70,0x82,0xff,0x7f,0xc9,0x88, + 0x8c,0x14,0x4d,0xa2,0xaf,0x58,0x42,0x9e, + 0xc9,0x60,0x31,0xdb,0xca,0xd3,0xda,0xd9, + 0xaf,0x0d,0xcb,0xaa,0xaf,0x26,0x8c,0xb8, + 0xfc,0xff,0xea,0xd9,0x4f,0x3c,0x7c,0xa4, + 0x95,0xe0,0x56,0xa9,0xb4,0x7a,0xcd,0xb7, + 0x51,0xfb,0x73,0xe6,0x66,0xc6,0xc6,0x55, + 0xad,0xe8,0x29,0x72,0x97,0xd0,0x7a,0xd1, + 0xba,0x5e,0x43,0xf1,0xbc,0xa3,0x23,0x01, + 0x65,0x13,0x39,0xe2,0x29,0x04,0xcc,0x8c, + 0x42,0xf5,0x8c,0x30,0xc0,0x4a,0xaf,0xdb, + 0x03,0x8d,0xda,0x08,0x47,0xdd,0x98,0x8d, + 0xcd,0xa6,0xf3,0xbf,0xd1,0x5c,0x4b,0x4c, + 0x45,0x25,0x00,0x4a,0xa0,0x6e,0xef,0xf8, + 0xca,0x61,0x78,0x3a,0xac,0xec,0x57,0xfb, + 0x3d,0x1f,0x92,0xb0,0xfe,0x2f,0xd1,0xa8, + 0x5f,0x67,0x24,0x51,0x7b,0x65,0xe6,0x14, + 0xad,0x68,0x08,0xd6,0xf6,0xee,0x34,0xdf, + 0xf7,0x31,0x0f,0xdc,0x82,0xae,0xbf,0xd9, + 0x04,0xb0,0x1e,0x1d,0xc5,0x4b,0x29,0x27, + 0x09,0x4b,0x2d,0xb6,0x8d,0x6f,0x90,0x3b, + 0x68,0x40,0x1a,0xde,0xbf,0x5a,0x7e,0x08, + 0xd7,0x8f,0xf4,0xef,0x5d,0x63,0x65,0x3a, + 0x65,0x04,0x0c,0xf9,0xbf,0xd4,0xac,0xa7, + 0x98,0x4a,0x74,0xd3,0x71,0x45,0x98,0x67, + 0x80,0xfc,0x0b,0x16,0xac,0x45,0x16,0x49, + 0xde,0x61,0x88,0xa7,0xdb,0xdf,0x19,0x1f, + 0x64,0xb5,0xfc,0x5e,0x2a,0xb4,0x7b,0x57, + 0xf7,0xf7,0x27,0x6c,0xd4,0x19,0xc1,0x7a, + 0x3c,0xa8,0xe1,0xb9,0x39,0xae,0x49,0xe4, + 0x88,0xac,0xba,0x6b,0x96,0x56,0x10,0xb5, + 0x48,0x01,0x09,0xc8,0xb1,0x7b,0x80,0xe1, + 0xb7,0xb7,0x50,0xdf,0xc7,0x59,0x8d,0x5d, + 0x50,0x11,0xfd,0x2d,0xcc,0x56,0x00,0xa3, + 0x2e,0xf5,0xb5,0x2a,0x1e,0xcc,0x82,0x0e, + 0x30,0x8a,0xa3,0x42,0x72,0x1a,0xac,0x09, + 0x43,0xbf,0x66,0x86,0xb6,0x4b,0x25,0x79, + 0x37,0x65,0x04,0xcc,0xc4,0x93,0xd9,0x7e, + 0x6a,0xed,0x3f,0xb0,0xf9,0xcd,0x71,0xa4, + 0x3d,0xd4,0x97,0xf0,0x1f,0x17,0xc0,0xe2, + 0xcb,0x37,0x97,0xaa,0x2a,0x2f,0x25,0x66, + 0x56,0x16,0x8e,0x6c,0x49,0x6a,0xfc,0x5f, + 0xb9,0x32,0x46,0xf6,0xb1,0x11,0x63,0x98, + 0xa3,0x46,0xf1,0xa6,0x41,0xf3,0xb0,0x41, + 0xe9,0x89,0xf7,0x91,0x4f,0x90,0xcc,0x2c, + 0x7f,0xff,0x35,0x78,0x76,0xe5,0x06,0xb5, + 0x0d,0x33,0x4b,0xa7,0x7c,0x22,0x5b,0xc3, + 0x07,0xba,0x53,0x71,0x52,0xf3,0xf1,0x61, + 0x0e,0x4e,0xaf,0xe5,0x95,0xf6,0xd9,0xd9, + 0x0d,0x11,0xfa,0xa9,0x33,0xa1,0x5e,0xf1, + 0x36,0x95,0x46,0x86,0x8a,0x7f,0x3a,0x45, + 0xa9,0x67,0x68,0xd4,0x0f,0xd9,0xd0,0x34, + 0x12,0xc0,0x91,0xc6,0x31,0x5c,0xf4,0xfd, + 0xe7,0xcb,0x68,0x60,0x69,0x37,0x38,0x0d, + 0xb2,0xea,0xaa,0x70,0x7b,0x4c,0x41,0x85, + 0xc3,0x2e,0xdd,0xcd,0xd3,0x06,0x70,0x5e, + 0x4d,0xc1,0xff,0xc8,0x72,0xee,0xee,0x47, + 0x5a,0x64,0xdf,0xac,0x86,0xab,0xa4,0x1c, + 0x06,0x18,0x98,0x3f,0x87,0x41,0xc5,0xef, + 0x68,0xd3,0xa1,0x01,0xe8,0xa3,0xb8,0xca, + 0xc6,0x0c,0x90,0x5c,0x15,0xfc,0x91,0x08, + 0x40,0xb9,0x4c,0x00,0xa0,0xb9,0xd0 }; - const byte* msgs[] = {msg1, msg2, msg3, msg1, msg1, msg4}; - const word16 msgSz[] = {sizeof(msg1), sizeof(msg2), sizeof(msg3), - sizeof(msg1), 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) + }; +#ifndef NO_ASN + static byte privateEd25519[] = { + 0x30,0x2e,0x02,0x01,0x00,0x30,0x05,0x06, + 0x03,0x2b,0x65,0x70,0x04,0x22,0x04,0x20, + 0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60, + 0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4, + 0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19, + 0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60 + }; + static byte publicEd25519[] = { + 0x30,0x2a,0x30,0x05,0x06,0x03,0x2b,0x65, + 0x70,0x03,0x21,0x00,0xd7,0x5a,0x98,0x01, + 0x82,0xb1,0x0a,0xb7,0xd5,0x4b,0xfe,0xd3, + 0xc9,0x64,0x07,0x3a,0x0e,0xe1,0x72,0xf3, + 0xda,0xa6,0x23,0x25,0xaf,0x02,0x1a,0x68, + 0xf7,0x07,0x51,0x1a + }; + static byte privPubEd25519[] = { + 0x30,0x52,0x02,0x01,0x00,0x30,0x05,0x06, + 0x03,0x2b,0x65,0x70,0x04,0x22,0x04,0x20, + 0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60, + 0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4, + 0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19, + 0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60, + 0xa1,0x22,0x04,0x20,0xd7,0x5a,0x98,0x01, + 0x82,0xb1,0x0a,0xb7,0xd5,0x4b,0xfe,0xd3, + 0xc9,0x64,0x07,0x3a,0x0e,0xe1,0x72,0xf3, + 0xda,0xa6,0x23,0x25,0xaf,0x02,0x1a,0x68, + 0xf7,0x07,0x51,0x1a + }; + + word32 idx; + ed25519_key key3; +#endif /* NO_ASN */ +#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 -10600; + wc_ed25519_init(&key); wc_ed25519_init(&key2); +#ifndef NO_ASN + wc_ed25519_init(&key3); +#endif wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key); wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key2); @@ -5726,62 +21659,122 @@ int ed25519_test(void) keySz = wc_ed25519_size(&key); sigSz = wc_ed25519_sig_size(&key); +#if defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_KEY_EXPORT) &&\ + defined(HAVE_ED25519_KEY_IMPORT) for (i = 0; i < 6; i++) { outlen = sizeof(out); XMEMSET(out, 0, sizeof(out)); if (wc_ed25519_import_private_key(sKeys[i], ED25519_KEY_SIZE, pKeys[i], pKeySz[i], &key) != 0) - return -1021 - i; + return -10601 - i; - if (wc_ed25519_sign_msg(msgs[i], msgSz[i], out, &outlen, &key) - != 0) - return -1027 - i; + if (wc_ed25519_sign_msg(msgs[i], msgSz[i], out, &outlen, &key) != 0) + return -10611 - i; if (XMEMCMP(out, sigs[i], 64)) - return -1033 - i; + return -10621 - 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 -10631 - 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 -10641 - 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 -10651 - i; if (wc_ed25519_import_public(exportPKey, exportPSz, &key2) != 0) - return -1057 - i; + return -10661 - i; if (wc_ed25519_export_private_only(&key, exportSKey, &exportSSz) != 0) - return -1063 - i; + return -10671 - i; if (wc_ed25519_import_private_key(exportSKey, exportSSz, exportPKey, exportPSz, &key2) != 0) - return -1069 - i; + return -10681 - 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 -10691 - 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 -10701 - i; if (XMEMCMP(out, sigs[i], 64)) - return -1087 - i; + return -10711 - i; +#endif /* HAVE_ED25519_VERIFY */ } + ret = ed25519ctx_test(); + if (ret != 0) + return ret; + + ret = ed25519ph_test(); + if (ret != 0) + return ret; + +#ifndef NO_ASN + /* Try ASN.1 encoded private-only key and public key. */ + idx = 0; + if (wc_Ed25519PrivateKeyDecode(privateEd25519, &idx, &key3, + sizeof(privateEd25519)) != 0) + return -10721 - i; + + if (wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, &key3) + != BAD_FUNC_ARG) + return -10731 - i; + + idx = 0; + if (wc_Ed25519PublicKeyDecode(publicEd25519, &idx, &key3, + sizeof(publicEd25519)) != 0) + return -10741 - i; + + if (wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, &key3) != 0) + return -10751 - i; + + if (XMEMCMP(out, sigs[0], 64)) + return -10761 - i; + +#if defined(HAVE_ED25519_VERIFY) + /* test verify on good msg */ + if (wc_ed25519_verify_msg(out, outlen, msgs[0], msgSz[0], &verify, &key3) + != 0 || verify != 1) + return -10771 - i; +#endif /* HAVE_ED25519_VERIFY */ + + wc_ed25519_free(&key3); + wc_ed25519_init(&key3); + + idx = 0; + if (wc_Ed25519PrivateKeyDecode(privPubEd25519, &idx, &key3, + sizeof(privPubEd25519)) != 0) + return -10781 - i; + + if (wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, &key3) != 0) + return -10791 - i; + + if (XMEMCMP(out, sigs[0], 64)) + return -10801 - i; + + wc_ed25519_free(&key3); +#endif /* NO_ASN */ +#endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */ + /* clean up keys when done */ wc_ed25519_free(&key); wc_ed25519_free(&key2); @@ -5790,14 +21783,1624 @@ int ed25519_test(void) wc_FreeRng(&rng); #endif - /* hush warrnings of unused keySz and sigSz */ + /* hush warnings of unused keySz and sigSz */ (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 */ +#ifdef HAVE_CURVE448 +#if defined(HAVE_CURVE448_SHARED_SECRET) && \ + defined(HAVE_CURVE448_KEY_IMPORT) +/* Test the wc_curve448_check_public API. + * + * returns 0 on success and -ve on failure. + */ +static int curve448_check_public_test(void) +{ + /* Little-endian values that will fail */ + byte fail_le[][CURVE448_KEY_SIZE] = { + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }, + { + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }, + }; + /* Big-endian values that will fail */ + byte fail_be[][CURVE448_KEY_SIZE] = { + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }, + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,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 + }, + }; + /* Good or valid public value */ + byte good[CURVE448_KEY_SIZE] = { + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 + }; + int i; + + /* Parameter checks */ + /* NULL pointer */ + if (wc_curve448_check_public(NULL, 0, EC448_LITTLE_ENDIAN) != + BAD_FUNC_ARG) { + return -10900; + } + if (wc_curve448_check_public(NULL, 0, EC448_BIG_ENDIAN) != BAD_FUNC_ARG) { + return -10901; + } + /* Length of 0 treated differently to other invalid lengths for TLS */ + if (wc_curve448_check_public(good, 0, EC448_LITTLE_ENDIAN) != BUFFER_E) + return -10902; + if (wc_curve448_check_public(good, 0, EC448_BIG_ENDIAN) != BUFFER_E) + return -10903; + + /* Length not CURVE448_KEY_SIZE */ + for (i = 1; i < CURVE448_KEY_SIZE + 2; i++) { + if (i == CURVE448_KEY_SIZE) + continue; + if (wc_curve448_check_public(good, i, EC448_LITTLE_ENDIAN) != + ECC_BAD_ARG_E) { + return -10904 - i; + } + if (wc_curve448_check_public(good, i, EC448_BIG_ENDIAN) != + ECC_BAD_ARG_E) { + return -10914 - i; + } + } + + /* Little-endian fail cases */ + for (i = 0; i < (int)(sizeof(fail_le) / sizeof(*fail_le)); i++) { + if (wc_curve448_check_public(fail_le[i], CURVE448_KEY_SIZE, + EC448_LITTLE_ENDIAN) == 0) { + return -10924 - i; + } + } + /* Big-endian fail cases */ + for (i = 0; i < (int)(sizeof(fail_be) / sizeof(*fail_be)); i++) { + if (wc_curve448_check_public(fail_be[i], CURVE448_KEY_SIZE, + EC448_BIG_ENDIAN) == 0) { + return -10934 - i; + } + } + + /* Check a valid public value works! */ + if (wc_curve448_check_public(good, CURVE448_KEY_SIZE, + EC448_LITTLE_ENDIAN) != 0) { + return -10944; + } + if (wc_curve448_check_public(good, CURVE448_KEY_SIZE, + EC448_BIG_ENDIAN) != 0) { + return -10945; + } + + return 0; +} + +#endif /* HAVE_CURVE448_SHARED_SECRET && HAVE_CURVE448_KEY_IMPORT */ + +int curve448_test(void) +{ + WC_RNG rng; + int ret; +#ifdef HAVE_CURVE448_SHARED_SECRET + byte sharedA[CURVE448_KEY_SIZE]; + byte sharedB[CURVE448_KEY_SIZE]; + word32 y; +#endif +#ifdef HAVE_CURVE448_KEY_EXPORT + byte exportBuf[CURVE448_KEY_SIZE]; +#endif + word32 x; + curve448_key userA, userB, pubKey; + + (void)x; + +#if defined(HAVE_CURVE448_SHARED_SECRET) && \ + defined(HAVE_CURVE448_KEY_IMPORT) + /* test vectors from + https://www.rfc-editor.org/rfc/rfc7748.html + */ + + /* secret key for party a */ + byte sa[] = { + 0x6b, 0x72, 0x98, 0xa5, 0xc0, 0xd8, 0xc2, 0x9a, + 0x1d, 0xab, 0x27, 0xf1, 0xa6, 0x82, 0x63, 0x00, + 0x91, 0x73, 0x89, 0x44, 0x97, 0x41, 0xa9, 0x74, + 0xf5, 0xba, 0xc9, 0xd9, 0x8d, 0xc2, 0x98, 0xd4, + 0x65, 0x55, 0xbc, 0xe8, 0xba, 0xe8, 0x9e, 0xee, + 0xd4, 0x00, 0x58, 0x4b, 0xb0, 0x46, 0xcf, 0x75, + 0x57, 0x9f, 0x51, 0xd1, 0x25, 0x49, 0x8f, 0x9a, + }; + + /* public key for party a */ + byte pa[] = { + 0xa0, 0x1f, 0xc4, 0x32, 0xe5, 0x80, 0x7f, 0x17, + 0x53, 0x0d, 0x12, 0x88, 0xda, 0x12, 0x5b, 0x0c, + 0xd4, 0x53, 0xd9, 0x41, 0x72, 0x64, 0x36, 0xc8, + 0xbb, 0xd9, 0xc5, 0x22, 0x2c, 0x3d, 0xa7, 0xfa, + 0x63, 0x9c, 0xe0, 0x3d, 0xb8, 0xd2, 0x3b, 0x27, + 0x4a, 0x07, 0x21, 0xa1, 0xae, 0xd5, 0x22, 0x7d, + 0xe6, 0xe3, 0xb7, 0x31, 0xcc, 0xf7, 0x08, 0x9b, + }; + + /* secret key for party b */ + byte sb[] = { + 0x2d, 0x99, 0x73, 0x51, 0xb6, 0x10, 0x6f, 0x36, + 0xb0, 0xd1, 0x09, 0x1b, 0x92, 0x9c, 0x4c, 0x37, + 0x21, 0x3e, 0x0d, 0x2b, 0x97, 0xe8, 0x5e, 0xbb, + 0x20, 0xc1, 0x27, 0x69, 0x1d, 0x0d, 0xad, 0x8f, + 0x1d, 0x81, 0x75, 0xb0, 0x72, 0x37, 0x45, 0xe6, + 0x39, 0xa3, 0xcb, 0x70, 0x44, 0x29, 0x0b, 0x99, + 0xe0, 0xe2, 0xa0, 0xc2, 0x7a, 0x6a, 0x30, 0x1c, + }; + + /* public key for party b */ + byte pb[] = { + 0x09, 0x36, 0xf3, 0x7b, 0xc6, 0xc1, 0xbd, 0x07, + 0xae, 0x3d, 0xec, 0x7a, 0xb5, 0xdc, 0x06, 0xa7, + 0x3c, 0xa1, 0x32, 0x42, 0xfb, 0x34, 0x3e, 0xfc, + 0x72, 0xb9, 0xd8, 0x27, 0x30, 0xb4, 0x45, 0xf3, + 0xd4, 0xb0, 0xbd, 0x07, 0x71, 0x62, 0xa4, 0x6d, + 0xcf, 0xec, 0x6f, 0x9b, 0x59, 0x0b, 0xfc, 0xbc, + 0xf5, 0x20, 0xcd, 0xb0, 0x29, 0xa8, 0xb7, 0x3e, + }; + + /* expected shared key */ + byte ss[] = { + 0x9d, 0x87, 0x4a, 0x51, 0x37, 0x50, 0x9a, 0x44, + 0x9a, 0xd5, 0x85, 0x30, 0x40, 0x24, 0x1c, 0x52, + 0x36, 0x39, 0x54, 0x35, 0xc3, 0x64, 0x24, 0xfd, + 0x56, 0x0b, 0x0c, 0xb6, 0x2b, 0x28, 0x1d, 0x28, + 0x52, 0x75, 0xa7, 0x40, 0xce, 0x32, 0xa2, 0x2d, + 0xd1, 0x74, 0x0f, 0x4a, 0xa9, 0x16, 0x1c, 0xec, + 0x95, 0xcc, 0xc6, 0x1a, 0x18, 0xf4, 0xff, 0x07, + }; +#endif /* HAVE_CURVE448_SHARED_SECRET */ + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -11000; + + wc_curve448_init(&userA); + wc_curve448_init(&userB); + wc_curve448_init(&pubKey); + + /* make curve448 keys */ + if (wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &userA) != 0) + return -11001; + + if (wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &userB) != 0) + return -11002; + +#ifdef HAVE_CURVE448_SHARED_SECRET + /* find shared secret key */ + x = sizeof(sharedA); + if (wc_curve448_shared_secret(&userA, &userB, sharedA, &x) != 0) + return -11003; + + y = sizeof(sharedB); + if (wc_curve448_shared_secret(&userB, &userA, sharedB, &y) != 0) + return -11004; + + /* compare shared secret keys to test they are the same */ + if (y != x) + return -11005; + + if (XMEMCMP(sharedA, sharedB, x)) + return -11006; +#endif + +#ifdef HAVE_CURVE448_KEY_EXPORT + /* export a public key and import it for another user */ + x = sizeof(exportBuf); + if (wc_curve448_export_public(&userA, exportBuf, &x) != 0) + return -11007; + +#ifdef HAVE_CURVE448_KEY_IMPORT + if (wc_curve448_import_public(exportBuf, x, &pubKey) != 0) + return -11008; +#endif +#endif + +#if defined(HAVE_CURVE448_SHARED_SECRET) && \ + defined(HAVE_CURVE448_KEY_IMPORT) + /* test shared key after importing a public key */ + XMEMSET(sharedB, 0, sizeof(sharedB)); + y = sizeof(sharedB); + if (wc_curve448_shared_secret(&userB, &pubKey, sharedB, &y) != 0) + return -11009; + + if (XMEMCMP(sharedA, sharedB, y)) + return -11010; + + /* import RFC test vectors and compare shared key */ + if (wc_curve448_import_private_raw(sa, sizeof(sa), pa, sizeof(pa), &userA) + != 0) + return -11011; + + if (wc_curve448_import_private_raw(sb, sizeof(sb), pb, sizeof(pb), &userB) + != 0) + return -11012; + + /* test against known test vector */ + XMEMSET(sharedB, 0, sizeof(sharedB)); + y = sizeof(sharedB); + if (wc_curve448_shared_secret(&userA, &userB, sharedB, &y) != 0) + return -11013; + + if (XMEMCMP(ss, sharedB, y)) + return -11014; + + /* test swapping roles of keys and generating same shared key */ + XMEMSET(sharedB, 0, sizeof(sharedB)); + y = sizeof(sharedB); + if (wc_curve448_shared_secret(&userB, &userA, sharedB, &y) != 0) + return -11015; + + if (XMEMCMP(ss, sharedB, y)) + return -11016; + + /* test with 1 generated key and 1 from known test vector */ + if (wc_curve448_import_private_raw(sa, sizeof(sa), pa, sizeof(pa), &userA) + != 0) + return -11017; + + if (wc_curve448_make_key(&rng, 56, &userB) != 0) + return -11018; + + x = sizeof(sharedA); + if (wc_curve448_shared_secret(&userA, &userB, sharedA, &x) != 0) + return -11019; + + y = sizeof(sharedB); + if (wc_curve448_shared_secret(&userB, &userA, sharedB, &y) != 0) + return -11020; + + /* compare shared secret keys to test they are the same */ + if (y != x) + return -11021; + + if (XMEMCMP(sharedA, sharedB, x)) + return -11022; + + ret = curve448_check_public_test(); + if (ret != 0) + return ret; +#endif /* HAVE_CURVE448_SHARED_SECRET && HAVE_CURVE448_KEY_IMPORT */ + + /* clean up keys when done */ + wc_curve448_free(&pubKey); + wc_curve448_free(&userB); + wc_curve448_free(&userA); + + wc_FreeRng(&rng); + + return 0; +} +#endif /* HAVE_CURVE448 */ + +#ifdef HAVE_ED448 +#ifdef WOLFSSL_TEST_CERT +static int ed448_test_cert(void) +{ + DecodedCert cert[2]; + DecodedCert* serverCert = NULL; + DecodedCert* caCert = NULL; +#ifdef HAVE_ED448_VERIFY + ed448_key key; + ed448_key* pubKey = NULL; + int verify; +#endif /* HAVE_ED448_VERIFY */ + int ret; + byte* tmp; + size_t bytes; + XFILE file; + + tmp = XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ERROR_OUT(-11023, done); + } + +#ifdef USE_CERT_BUFFERS_256 + XMEMCPY(tmp, ca_ed448_cert, sizeof_ca_ed448_cert); + bytes = sizeof_ca_ed448_cert; +#elif !defined(NO_FILESYSTEM) + file = XFOPEN(caEd448Cert, "rb"); + if (file == NULL) { + ERROR_OUT(-11024, done); + } + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); +#else + /* No certificate to use. */ + ERROR_OUT(-11025, 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(-11026, done); + } + +#ifdef USE_CERT_BUFFERS_256 + XMEMCPY(tmp, server_ed448_cert, sizeof_server_ed448_cert); + bytes = sizeof_server_ed448_cert; +#elif !defined(NO_FILESYSTEM) + file = XFOPEN(serverEd448Cert, "rb"); + if (file == NULL) { + ERROR_OUT(-11027, done); + } + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); +#else + /* No certificate to use. */ + ERROR_OUT(-11028, 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(-11029, done); + } + +#ifdef HAVE_ED448_VERIFY + ret = wc_ed448_init(&key); + if (ret < 0) { + ERROR_OUT(-11030, done); + } + pubKey = &key; + ret = wc_ed448_import_public(caCert->publicKey, caCert->pubKeySize, pubKey); + if (ret < 0) { + ERROR_OUT(-11031, done); + } + + if (wc_ed448_verify_msg(serverCert->signature, serverCert->sigLength, + serverCert->source + serverCert->certBegin, + serverCert->sigIndex - serverCert->certBegin, + &verify, pubKey) < 0 || verify != 1) { + ERROR_OUT(-11032, done); + } +#endif /* HAVE_ED448_VERIFY */ + +done: + if (tmp != NULL) + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef HAVE_ED448_VERIFY + wc_ed448_free(pubKey); +#endif /* HAVE_ED448_VERIFY */ + if (caCert != NULL) + FreeDecodedCert(caCert); + if (serverCert != NULL) + FreeDecodedCert(serverCert); + + return ret; +} + +static int ed448_test_make_cert(void) +{ + WC_RNG rng; + Cert cert; + DecodedCert decode; + ed448_key key; + ed448_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 -11033; + + wc_ed448_init(&key); + privKey = &key; + wc_ed448_make_key(&rng, ED448_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(-11034, done); + } + ret = wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ED448_TYPE, privKey); + if (ret < 0) { + ERROR_OUT(-11035, done); + } + ret = wc_SetAuthKeyIdFromPublicKey_ex(&cert, ED448_TYPE, privKey); + if (ret < 0) { + ERROR_OUT(-11036, done); + } +#endif + tmp = XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ERROR_OUT(-11037, done); + } + + cert.sigType = CTC_ED448; + ret = wc_MakeCert_ex(&cert, tmp, FOURK_BUF, ED448_TYPE, privKey, &rng); + if (ret < 0) { + ERROR_OUT(-11038, done); + } + ret = wc_SignCert_ex(cert.bodySz, cert.sigType, tmp, FOURK_BUF, ED448_TYPE, + privKey, &rng); + if (ret < 0) { + ERROR_OUT(-11039, done); + } + + InitDecodedCert(&decode, tmp, ret, HEAP_HINT); + ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); + FreeDecodedCert(&decode); + if (ret != 0) { + ERROR_OUT(-11040, done); + } + +done: + if (tmp != NULL) + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_ed448_free(privKey); + wc_FreeRng(&rng); + return ret; +} +#endif /* WOLFSSL_TEST_CERT */ + +#if defined(HAVE_ED448_SIGN) && defined(HAVE_ED448_KEY_EXPORT) && \ + defined(HAVE_ED448_KEY_IMPORT) +static int ed448_ctx_test(void) +{ + byte out[ED448_SIG_SIZE]; + word32 outlen; +#ifdef HAVE_ED448_VERIFY + int verify; +#endif /* HAVE_ED448_VERIFY */ + ed448_key key; + + static const byte sKeyCtx[] = { + 0xc4, 0xea, 0xb0, 0x5d, 0x35, 0x70, 0x07, 0xc6, + 0x32, 0xf3, 0xdb, 0xb4, 0x84, 0x89, 0x92, 0x4d, + 0x55, 0x2b, 0x08, 0xfe, 0x0c, 0x35, 0x3a, 0x0d, + 0x4a, 0x1f, 0x00, 0xac, 0xda, 0x2c, 0x46, 0x3a, + 0xfb, 0xea, 0x67, 0xc5, 0xe8, 0xd2, 0x87, 0x7c, + 0x5e, 0x3b, 0xc3, 0x97, 0xa6, 0x59, 0x94, 0x9e, + 0xf8, 0x02, 0x1e, 0x95, 0x4e, 0x0a, 0x12, 0x27, + 0x4e + }; + + static const byte pKeyCtx[] = { + 0x43, 0xba, 0x28, 0xf4, 0x30, 0xcd, 0xff, 0x45, + 0x6a, 0xe5, 0x31, 0x54, 0x5f, 0x7e, 0xcd, 0x0a, + 0xc8, 0x34, 0xa5, 0x5d, 0x93, 0x58, 0xc0, 0x37, + 0x2b, 0xfa, 0x0c, 0x6c, 0x67, 0x98, 0xc0, 0x86, + 0x6a, 0xea, 0x01, 0xeb, 0x00, 0x74, 0x28, 0x02, + 0xb8, 0x43, 0x8e, 0xa4, 0xcb, 0x82, 0x16, 0x9c, + 0x23, 0x51, 0x60, 0x62, 0x7b, 0x4c, 0x3a, 0x94, + 0x80 + }; + + static const byte sigCtx[] = { + 0xd4, 0xf8, 0xf6, 0x13, 0x17, 0x70, 0xdd, 0x46, + 0xf4, 0x08, 0x67, 0xd6, 0xfd, 0x5d, 0x50, 0x55, + 0xde, 0x43, 0x54, 0x1f, 0x8c, 0x5e, 0x35, 0xab, + 0xbc, 0xd0, 0x01, 0xb3, 0x2a, 0x89, 0xf7, 0xd2, + 0x15, 0x1f, 0x76, 0x47, 0xf1, 0x1d, 0x8c, 0xa2, + 0xae, 0x27, 0x9f, 0xb8, 0x42, 0xd6, 0x07, 0x21, + 0x7f, 0xce, 0x6e, 0x04, 0x2f, 0x68, 0x15, 0xea, + 0x00, 0x0c, 0x85, 0x74, 0x1d, 0xe5, 0xc8, 0xda, + 0x11, 0x44, 0xa6, 0xa1, 0xab, 0xa7, 0xf9, 0x6d, + 0xe4, 0x25, 0x05, 0xd7, 0xa7, 0x29, 0x85, 0x24, + 0xfd, 0xa5, 0x38, 0xfc, 0xcb, 0xbb, 0x75, 0x4f, + 0x57, 0x8c, 0x1c, 0xad, 0x10, 0xd5, 0x4d, 0x0d, + 0x54, 0x28, 0x40, 0x7e, 0x85, 0xdc, 0xbc, 0x98, + 0xa4, 0x91, 0x55, 0xc1, 0x37, 0x64, 0xe6, 0x6c, + 0x3c, 0x00 + }; + + static const byte msgCtx[] = { + 0x03 + }; + + static const byte contextCtx[] = { + 0x66,0x6f,0x6f + }; + + outlen = sizeof(out); + XMEMSET(out, 0, sizeof(out)); + + if (wc_ed448_import_private_key(sKeyCtx, ED448_KEY_SIZE, pKeyCtx, + sizeof(pKeyCtx), &key) != 0) + return -11100; + + if (wc_ed448_sign_msg(msgCtx, sizeof(msgCtx), out, &outlen, &key, + contextCtx, sizeof(contextCtx)) != 0) + return -11101; + + if (XMEMCMP(out, sigCtx, sizeof(sigCtx))) + return -11102; + +#if defined(HAVE_ED448_VERIFY) + /* test verify on good msg */ + if (wc_ed448_verify_msg(out, outlen, msgCtx, sizeof(msgCtx), &verify, &key, + contextCtx, sizeof(contextCtx)) != 0 || verify != 1) + return -11103; +#endif + + wc_ed448_free(&key); + + return 0; +} + +static int ed448ph_test(void) +{ + byte out[ED448_SIG_SIZE]; + word32 outlen; +#ifdef HAVE_ED448_VERIFY + int verify; +#endif /* HAVE_ED448_VERIFY */ + ed448_key key; + + static const byte sKeyPh[] = { + 0x83, 0x3f, 0xe6, 0x24, 0x09, 0x23, 0x7b, 0x9d, + 0x62, 0xec, 0x77, 0x58, 0x75, 0x20, 0x91, 0x1e, + 0x9a, 0x75, 0x9c, 0xec, 0x1d, 0x19, 0x75, 0x5b, + 0x7d, 0xa9, 0x01, 0xb9, 0x6d, 0xca, 0x3d, 0x42, + 0xef, 0x78, 0x22, 0xe0, 0xd5, 0x10, 0x41, 0x27, + 0xdc, 0x05, 0xd6, 0xdb, 0xef, 0xde, 0x69, 0xe3, + 0xab, 0x2c, 0xec, 0x7c, 0x86, 0x7c, 0x6e, 0x2c, + 0x49 + }; + + static const byte pKeyPh[] = { + 0x25, 0x9b, 0x71, 0xc1, 0x9f, 0x83, 0xef, 0x77, + 0xa7, 0xab, 0xd2, 0x65, 0x24, 0xcb, 0xdb, 0x31, + 0x61, 0xb5, 0x90, 0xa4, 0x8f, 0x7d, 0x17, 0xde, + 0x3e, 0xe0, 0xba, 0x9c, 0x52, 0xbe, 0xb7, 0x43, + 0xc0, 0x94, 0x28, 0xa1, 0x31, 0xd6, 0xb1, 0xb5, + 0x73, 0x03, 0xd9, 0x0d, 0x81, 0x32, 0xc2, 0x76, + 0xd5, 0xed, 0x3d, 0x5d, 0x01, 0xc0, 0xf5, 0x38, + 0x80 + }; + + static const byte sigPh1[] = { + 0x82, 0x2f, 0x69, 0x01, 0xf7, 0x48, 0x0f, 0x3d, + 0x5f, 0x56, 0x2c, 0x59, 0x29, 0x94, 0xd9, 0x69, + 0x36, 0x02, 0x87, 0x56, 0x14, 0x48, 0x32, 0x56, + 0x50, 0x56, 0x00, 0xbb, 0xc2, 0x81, 0xae, 0x38, + 0x1f, 0x54, 0xd6, 0xbc, 0xe2, 0xea, 0x91, 0x15, + 0x74, 0x93, 0x2f, 0x52, 0xa4, 0xe6, 0xca, 0xdd, + 0x78, 0x76, 0x93, 0x75, 0xec, 0x3f, 0xfd, 0x1b, + 0x80, 0x1a, 0x0d, 0x9b, 0x3f, 0x40, 0x30, 0xcd, + 0x43, 0x39, 0x64, 0xb6, 0x45, 0x7e, 0xa3, 0x94, + 0x76, 0x51, 0x12, 0x14, 0xf9, 0x74, 0x69, 0xb5, + 0x7d, 0xd3, 0x2d, 0xbc, 0x56, 0x0a, 0x9a, 0x94, + 0xd0, 0x0b, 0xff, 0x07, 0x62, 0x04, 0x64, 0xa3, + 0xad, 0x20, 0x3d, 0xf7, 0xdc, 0x7c, 0xe3, 0x60, + 0xc3, 0xcd, 0x36, 0x96, 0xd9, 0xd9, 0xfa, 0xb9, + 0x0f, 0x00 + }; + + static const byte sigPh2[] = { + 0xc3, 0x22, 0x99, 0xd4, 0x6e, 0xc8, 0xff, 0x02, + 0xb5, 0x45, 0x40, 0x98, 0x28, 0x14, 0xdc, 0xe9, + 0xa0, 0x58, 0x12, 0xf8, 0x19, 0x62, 0xb6, 0x49, + 0xd5, 0x28, 0x09, 0x59, 0x16, 0xa2, 0xaa, 0x48, + 0x10, 0x65, 0xb1, 0x58, 0x04, 0x23, 0xef, 0x92, + 0x7e, 0xcf, 0x0a, 0xf5, 0x88, 0x8f, 0x90, 0xda, + 0x0f, 0x6a, 0x9a, 0x85, 0xad, 0x5d, 0xc3, 0xf2, + 0x80, 0xd9, 0x12, 0x24, 0xba, 0x99, 0x11, 0xa3, + 0x65, 0x3d, 0x00, 0xe4, 0x84, 0xe2, 0xce, 0x23, + 0x25, 0x21, 0x48, 0x1c, 0x86, 0x58, 0xdf, 0x30, + 0x4b, 0xb7, 0x74, 0x5a, 0x73, 0x51, 0x4c, 0xdb, + 0x9b, 0xf3, 0xe1, 0x57, 0x84, 0xab, 0x71, 0x28, + 0x4f, 0x8d, 0x07, 0x04, 0xa6, 0x08, 0xc5, 0x4a, + 0x6b, 0x62, 0xd9, 0x7b, 0xeb, 0x51, 0x1d, 0x13, + 0x21, 0x00 + }; + + static const byte msgPh[] = { + 0x61,0x62,0x63 + }; + + /* SHA-512 hash of msgPh */ + static const byte hashPh[] = { + 0x48, 0x33, 0x66, 0x60, 0x13, 0x60, 0xa8, 0x77, + 0x1c, 0x68, 0x63, 0x08, 0x0c, 0xc4, 0x11, 0x4d, + 0x8d, 0xb4, 0x45, 0x30, 0xf8, 0xf1, 0xe1, 0xee, + 0x4f, 0x94, 0xea, 0x37, 0xe7, 0x8b, 0x57, 0x39, + 0xd5, 0xa1, 0x5b, 0xef, 0x18, 0x6a, 0x53, 0x86, + 0xc7, 0x57, 0x44, 0xc0, 0x52, 0x7e, 0x1f, 0xaa, + 0x9f, 0x87, 0x26, 0xe4, 0x62, 0xa1, 0x2a, 0x4f, + 0xeb, 0x06, 0xbd, 0x88, 0x01, 0xe7, 0x51, 0xe4 + }; + + static const byte contextPh2[] = { + 0x66,0x6f,0x6f + }; + + outlen = sizeof(out); + XMEMSET(out, 0, sizeof(out)); + + if (wc_ed448_import_private_key(sKeyPh, ED448_KEY_SIZE, pKeyPh, + sizeof(pKeyPh), &key) != 0) { + return -11200; + } + + if (wc_ed448ph_sign_msg(msgPh, sizeof(msgPh), out, &outlen, &key, NULL, + 0) != 0) { + return -11201; + } + + if (XMEMCMP(out, sigPh1, sizeof(sigPh1))) + return -11202; + +#if defined(HAVE_ED448_VERIFY) + /* test verify on good msg */ + if (wc_ed448ph_verify_msg(out, outlen, msgPh, sizeof(msgPh), &verify, &key, + NULL, 0) != 0 || verify != 1) { + return -11203; + } +#endif + + if (wc_ed448ph_sign_msg(msgPh, sizeof(msgPh), out, &outlen, &key, + contextPh2, sizeof(contextPh2)) != 0) { + return -11204; + } + + if (XMEMCMP(out, sigPh2, sizeof(sigPh2))) + return -11205; + +#if defined(HAVE_ED448_VERIFY) + /* test verify on good msg */ + if (wc_ed448ph_verify_msg(out, outlen, msgPh, sizeof(msgPh), &verify, &key, + contextPh2, sizeof(contextPh2)) != 0 || + verify != 1) { + return -11206; + } +#endif + + if (wc_ed448ph_sign_hash(hashPh, sizeof(hashPh), out, &outlen, &key, NULL, + 0) != 0) { + return -11207; + } + + if (XMEMCMP(out, sigPh1, sizeof(sigPh1))) + return -11208; + +#if defined(HAVE_ED448_VERIFY) + if (wc_ed448ph_verify_hash(out, outlen, hashPh, sizeof(hashPh), &verify, + &key, NULL, 0) != 0 || verify != 1) { + return -11209; + } +#endif + + if (wc_ed448ph_sign_hash(hashPh, sizeof(hashPh), out, &outlen, &key, + contextPh2, sizeof(contextPh2)) != 0) { + return -11210; + } + + if (XMEMCMP(out, sigPh2, sizeof(sigPh2))) + return -11211; + +#if defined(HAVE_ED448_VERIFY) + if (wc_ed448ph_verify_hash(out, outlen, hashPh, sizeof(hashPh), &verify, + &key, contextPh2, sizeof(contextPh2)) != 0 || + verify != 1) { + return -11212; + } +#endif + + wc_ed448_free(&key); + + return 0; +} +#endif /* HAVE_ED448_SIGN && HAVE_ED448_KEY_EXPORT && HAVE_ED448_KEY_IMPORT */ + +int ed448_test(void) +{ + int ret; + WC_RNG rng; +#if defined(HAVE_ED448_SIGN) && defined(HAVE_ED448_KEY_EXPORT) &&\ + defined(HAVE_ED448_KEY_IMPORT) + byte out[ED448_SIG_SIZE]; + byte exportPKey[ED448_KEY_SIZE]; + byte exportSKey[ED448_KEY_SIZE]; + word32 exportPSz; + word32 exportSSz; + int i; + word32 outlen; +#ifdef HAVE_ED448_VERIFY + int verify; +#endif /* HAVE_ED448_VERIFY */ +#endif /* HAVE_ED448_SIGN && HAVE_ED448_KEY_EXPORT && HAVE_ED448_KEY_IMPORT */ + word32 keySz, sigSz; + ed448_key key; + ed448_key key2; + +#if defined(HAVE_ED448_SIGN) && defined(HAVE_ED448_KEY_EXPORT) && \ + defined(HAVE_ED448_KEY_IMPORT) + /* test vectors from + https://tools.ietf.org/html/rfc8032 + */ + + static const byte sKey1[] = { + 0x6c, 0x82, 0xa5, 0x62, 0xcb, 0x80, 0x8d, 0x10, + 0xd6, 0x32, 0xbe, 0x89, 0xc8, 0x51, 0x3e, 0xbf, + 0x6c, 0x92, 0x9f, 0x34, 0xdd, 0xfa, 0x8c, 0x9f, + 0x63, 0xc9, 0x96, 0x0e, 0xf6, 0xe3, 0x48, 0xa3, + 0x52, 0x8c, 0x8a, 0x3f, 0xcc, 0x2f, 0x04, 0x4e, + 0x39, 0xa3, 0xfc, 0x5b, 0x94, 0x49, 0x2f, 0x8f, + 0x03, 0x2e, 0x75, 0x49, 0xa2, 0x00, 0x98, 0xf9, + 0x5b + }; + + static const byte sKey2[] = { + 0xc4, 0xea, 0xb0, 0x5d, 0x35, 0x70, 0x07, 0xc6, + 0x32, 0xf3, 0xdb, 0xb4, 0x84, 0x89, 0x92, 0x4d, + 0x55, 0x2b, 0x08, 0xfe, 0x0c, 0x35, 0x3a, 0x0d, + 0x4a, 0x1f, 0x00, 0xac, 0xda, 0x2c, 0x46, 0x3a, + 0xfb, 0xea, 0x67, 0xc5, 0xe8, 0xd2, 0x87, 0x7c, + 0x5e, 0x3b, 0xc3, 0x97, 0xa6, 0x59, 0x94, 0x9e, + 0xf8, 0x02, 0x1e, 0x95, 0x4e, 0x0a, 0x12, 0x27, + 0x4e + }; + + static const byte sKey3[] = { + 0x25, 0x8c, 0xdd, 0x4a, 0xda, 0x32, 0xed, 0x9c, + 0x9f, 0xf5, 0x4e, 0x63, 0x75, 0x6a, 0xe5, 0x82, + 0xfb, 0x8f, 0xab, 0x2a, 0xc7, 0x21, 0xf2, 0xc8, + 0xe6, 0x76, 0xa7, 0x27, 0x68, 0x51, 0x3d, 0x93, + 0x9f, 0x63, 0xdd, 0xdb, 0x55, 0x60, 0x91, 0x33, + 0xf2, 0x9a, 0xdf, 0x86, 0xec, 0x99, 0x29, 0xdc, + 0xcb, 0x52, 0xc1, 0xc5, 0xfd, 0x2f, 0xf7, 0xe2, + 0x1b + }; + + /* uncompressed test */ + static const byte sKey4[] = { + 0x6c, 0x82, 0xa5, 0x62, 0xcb, 0x80, 0x8d, 0x10, + 0xd6, 0x32, 0xbe, 0x89, 0xc8, 0x51, 0x3e, 0xbf, + 0x6c, 0x92, 0x9f, 0x34, 0xdd, 0xfa, 0x8c, 0x9f, + 0x63, 0xc9, 0x96, 0x0e, 0xf6, 0xe3, 0x48, 0xa3, + 0x52, 0x8c, 0x8a, 0x3f, 0xcc, 0x2f, 0x04, 0x4e, + 0x39, 0xa3, 0xfc, 0x5b, 0x94, 0x49, 0x2f, 0x8f, + 0x03, 0x2e, 0x75, 0x49, 0xa2, 0x00, 0x98, 0xf9, + 0x5b + }; + + /* compressed prefix test */ + static const byte sKey5[] = { + 0x6c, 0x82, 0xa5, 0x62, 0xcb, 0x80, 0x8d, 0x10, + 0xd6, 0x32, 0xbe, 0x89, 0xc8, 0x51, 0x3e, 0xbf, + 0x6c, 0x92, 0x9f, 0x34, 0xdd, 0xfa, 0x8c, 0x9f, + 0x63, 0xc9, 0x96, 0x0e, 0xf6, 0xe3, 0x48, 0xa3, + 0x52, 0x8c, 0x8a, 0x3f, 0xcc, 0x2f, 0x04, 0x4e, + 0x39, 0xa3, 0xfc, 0x5b, 0x94, 0x49, 0x2f, 0x8f, + 0x03, 0x2e, 0x75, 0x49, 0xa2, 0x00, 0x98, 0xf9, + 0x5b + }; + + static const byte sKey6[] = { + 0x87, 0x2d, 0x09, 0x37, 0x80, 0xf5, 0xd3, 0x73, + 0x0d, 0xf7, 0xc2, 0x12, 0x66, 0x4b, 0x37, 0xb8, + 0xa0, 0xf2, 0x4f, 0x56, 0x81, 0x0d, 0xaa, 0x83, + 0x82, 0xcd, 0x4f, 0xa3, 0xf7, 0x76, 0x34, 0xec, + 0x44, 0xdc, 0x54, 0xf1, 0xc2, 0xed, 0x9b, 0xea, + 0x86, 0xfa, 0xfb, 0x76, 0x32, 0xd8, 0xbe, 0x19, + 0x9e, 0xa1, 0x65, 0xf5, 0xad, 0x55, 0xdd, 0x9c, + 0xe8 + }; + + static const byte* sKeys[] = {sKey1, sKey2, sKey3, sKey4, sKey5, sKey6}; + + static const byte pKey1[] = { + 0x5f, 0xd7, 0x44, 0x9b, 0x59, 0xb4, 0x61, 0xfd, + 0x2c, 0xe7, 0x87, 0xec, 0x61, 0x6a, 0xd4, 0x6a, + 0x1d, 0xa1, 0x34, 0x24, 0x85, 0xa7, 0x0e, 0x1f, + 0x8a, 0x0e, 0xa7, 0x5d, 0x80, 0xe9, 0x67, 0x78, + 0xed, 0xf1, 0x24, 0x76, 0x9b, 0x46, 0xc7, 0x06, + 0x1b, 0xd6, 0x78, 0x3d, 0xf1, 0xe5, 0x0f, 0x6c, + 0xd1, 0xfa, 0x1a, 0xbe, 0xaf, 0xe8, 0x25, 0x61, + 0x80 + }; + + static const byte pKey2[] = { + 0x43, 0xba, 0x28, 0xf4, 0x30, 0xcd, 0xff, 0x45, + 0x6a, 0xe5, 0x31, 0x54, 0x5f, 0x7e, 0xcd, 0x0a, + 0xc8, 0x34, 0xa5, 0x5d, 0x93, 0x58, 0xc0, 0x37, + 0x2b, 0xfa, 0x0c, 0x6c, 0x67, 0x98, 0xc0, 0x86, + 0x6a, 0xea, 0x01, 0xeb, 0x00, 0x74, 0x28, 0x02, + 0xb8, 0x43, 0x8e, 0xa4, 0xcb, 0x82, 0x16, 0x9c, + 0x23, 0x51, 0x60, 0x62, 0x7b, 0x4c, 0x3a, 0x94, + 0x80 + }; + + static const byte pKey3[] = { + 0x3b, 0xa1, 0x6d, 0xa0, 0xc6, 0xf2, 0xcc, 0x1f, + 0x30, 0x18, 0x77, 0x40, 0x75, 0x6f, 0x5e, 0x79, + 0x8d, 0x6b, 0xc5, 0xfc, 0x01, 0x5d, 0x7c, 0x63, + 0xcc, 0x95, 0x10, 0xee, 0x3f, 0xd4, 0x4a, 0xdc, + 0x24, 0xd8, 0xe9, 0x68, 0xb6, 0xe4, 0x6e, 0x6f, + 0x94, 0xd1, 0x9b, 0x94, 0x53, 0x61, 0x72, 0x6b, + 0xd7, 0x5e, 0x14, 0x9e, 0xf0, 0x98, 0x17, 0xf5, + 0x80 + }; + + /* uncompressed test */ + static const byte pKey4[] = { + 0x5f, 0xd7, 0x44, 0x9b, 0x59, 0xb4, 0x61, 0xfd, + 0x2c, 0xe7, 0x87, 0xec, 0x61, 0x6a, 0xd4, 0x6a, + 0x1d, 0xa1, 0x34, 0x24, 0x85, 0xa7, 0x0e, 0x1f, + 0x8a, 0x0e, 0xa7, 0x5d, 0x80, 0xe9, 0x67, 0x78, + 0xed, 0xf1, 0x24, 0x76, 0x9b, 0x46, 0xc7, 0x06, + 0x1b, 0xd6, 0x78, 0x3d, 0xf1, 0xe5, 0x0f, 0x6c, + 0xd1, 0xfa, 0x1a, 0xbe, 0xaf, 0xe8, 0x25, 0x61, + 0x80 + }; + + /* compressed prefix */ + static const byte pKey5[] = { + 0x5f, 0xd7, 0x44, 0x9b, 0x59, 0xb4, 0x61, 0xfd, + 0x2c, 0xe7, 0x87, 0xec, 0x61, 0x6a, 0xd4, 0x6a, + 0x1d, 0xa1, 0x34, 0x24, 0x85, 0xa7, 0x0e, 0x1f, + 0x8a, 0x0e, 0xa7, 0x5d, 0x80, 0xe9, 0x67, 0x78, + 0xed, 0xf1, 0x24, 0x76, 0x9b, 0x46, 0xc7, 0x06, + 0x1b, 0xd6, 0x78, 0x3d, 0xf1, 0xe5, 0x0f, 0x6c, + 0xd1, 0xfa, 0x1a, 0xbe, 0xaf, 0xe8, 0x25, 0x61, + 0x80 + }; + + static const byte pKey6[] = { + 0xa8, 0x1b, 0x2e, 0x8a, 0x70, 0xa5, 0xac, 0x94, + 0xff, 0xdb, 0xcc, 0x9b, 0xad, 0xfc, 0x3f, 0xeb, + 0x08, 0x01, 0xf2, 0x58, 0x57, 0x8b, 0xb1, 0x14, + 0xad, 0x44, 0xec, 0xe1, 0xec, 0x0e, 0x79, 0x9d, + 0xa0, 0x8e, 0xff, 0xb8, 0x1c, 0x5d, 0x68, 0x5c, + 0x0c, 0x56, 0xf6, 0x4e, 0xec, 0xae, 0xf8, 0xcd, + 0xf1, 0x1c, 0xc3, 0x87, 0x37, 0x83, 0x8c, 0xf4, + 0x00 + }; + + static const byte* pKeys[] = {pKey1, pKey2, pKey3, pKey4, pKey5, pKey6}; + static const byte pKeySz[] = {sizeof(pKey1), sizeof(pKey2), sizeof(pKey3), + sizeof(pKey4), sizeof(pKey5), sizeof(pKey6)}; + + static const byte sig1[] = { + 0x53, 0x3a, 0x37, 0xf6, 0xbb, 0xe4, 0x57, 0x25, + 0x1f, 0x02, 0x3c, 0x0d, 0x88, 0xf9, 0x76, 0xae, + 0x2d, 0xfb, 0x50, 0x4a, 0x84, 0x3e, 0x34, 0xd2, + 0x07, 0x4f, 0xd8, 0x23, 0xd4, 0x1a, 0x59, 0x1f, + 0x2b, 0x23, 0x3f, 0x03, 0x4f, 0x62, 0x82, 0x81, + 0xf2, 0xfd, 0x7a, 0x22, 0xdd, 0xd4, 0x7d, 0x78, + 0x28, 0xc5, 0x9b, 0xd0, 0xa2, 0x1b, 0xfd, 0x39, + 0x80, 0xff, 0x0d, 0x20, 0x28, 0xd4, 0xb1, 0x8a, + 0x9d, 0xf6, 0x3e, 0x00, 0x6c, 0x5d, 0x1c, 0x2d, + 0x34, 0x5b, 0x92, 0x5d, 0x8d, 0xc0, 0x0b, 0x41, + 0x04, 0x85, 0x2d, 0xb9, 0x9a, 0xc5, 0xc7, 0xcd, + 0xda, 0x85, 0x30, 0xa1, 0x13, 0xa0, 0xf4, 0xdb, + 0xb6, 0x11, 0x49, 0xf0, 0x5a, 0x73, 0x63, 0x26, + 0x8c, 0x71, 0xd9, 0x58, 0x08, 0xff, 0x2e, 0x65, + 0x26, 0x00 + }; + + static const byte sig2[] = { + 0x26, 0xb8, 0xf9, 0x17, 0x27, 0xbd, 0x62, 0x89, + 0x7a, 0xf1, 0x5e, 0x41, 0xeb, 0x43, 0xc3, 0x77, + 0xef, 0xb9, 0xc6, 0x10, 0xd4, 0x8f, 0x23, 0x35, + 0xcb, 0x0b, 0xd0, 0x08, 0x78, 0x10, 0xf4, 0x35, + 0x25, 0x41, 0xb1, 0x43, 0xc4, 0xb9, 0x81, 0xb7, + 0xe1, 0x8f, 0x62, 0xde, 0x8c, 0xcd, 0xf6, 0x33, + 0xfc, 0x1b, 0xf0, 0x37, 0xab, 0x7c, 0xd7, 0x79, + 0x80, 0x5e, 0x0d, 0xbc, 0xc0, 0xaa, 0xe1, 0xcb, + 0xce, 0xe1, 0xaf, 0xb2, 0xe0, 0x27, 0xdf, 0x36, + 0xbc, 0x04, 0xdc, 0xec, 0xbf, 0x15, 0x43, 0x36, + 0xc1, 0x9f, 0x0a, 0xf7, 0xe0, 0xa6, 0x47, 0x29, + 0x05, 0xe7, 0x99, 0xf1, 0x95, 0x3d, 0x2a, 0x0f, + 0xf3, 0x34, 0x8a, 0xb2, 0x1a, 0xa4, 0xad, 0xaf, + 0xd1, 0xd2, 0x34, 0x44, 0x1c, 0xf8, 0x07, 0xc0, + 0x3a, 0x00 + }; + + static const byte sig3[] = { + 0x7e, 0xee, 0xab, 0x7c, 0x4e, 0x50, 0xfb, 0x79, + 0x9b, 0x41, 0x8e, 0xe5, 0xe3, 0x19, 0x7f, 0xf6, + 0xbf, 0x15, 0xd4, 0x3a, 0x14, 0xc3, 0x43, 0x89, + 0xb5, 0x9d, 0xd1, 0xa7, 0xb1, 0xb8, 0x5b, 0x4a, + 0xe9, 0x04, 0x38, 0xac, 0xa6, 0x34, 0xbe, 0xa4, + 0x5e, 0x3a, 0x26, 0x95, 0xf1, 0x27, 0x0f, 0x07, + 0xfd, 0xcd, 0xf7, 0xc6, 0x2b, 0x8e, 0xfe, 0xaf, + 0x00, 0xb4, 0x5c, 0x2c, 0x96, 0xba, 0x45, 0x7e, + 0xb1, 0xa8, 0xbf, 0x07, 0x5a, 0x3d, 0xb2, 0x8e, + 0x5c, 0x24, 0xf6, 0xb9, 0x23, 0xed, 0x4a, 0xd7, + 0x47, 0xc3, 0xc9, 0xe0, 0x3c, 0x70, 0x79, 0xef, + 0xb8, 0x7c, 0xb1, 0x10, 0xd3, 0xa9, 0x98, 0x61, + 0xe7, 0x20, 0x03, 0xcb, 0xae, 0x6d, 0x6b, 0x8b, + 0x82, 0x7e, 0x4e, 0x6c, 0x14, 0x30, 0x64, 0xff, + 0x3c, 0x00 + }; + + /* uncompressed test */ + static const byte sig4[] = { + 0x53, 0x3a, 0x37, 0xf6, 0xbb, 0xe4, 0x57, 0x25, + 0x1f, 0x02, 0x3c, 0x0d, 0x88, 0xf9, 0x76, 0xae, + 0x2d, 0xfb, 0x50, 0x4a, 0x84, 0x3e, 0x34, 0xd2, + 0x07, 0x4f, 0xd8, 0x23, 0xd4, 0x1a, 0x59, 0x1f, + 0x2b, 0x23, 0x3f, 0x03, 0x4f, 0x62, 0x82, 0x81, + 0xf2, 0xfd, 0x7a, 0x22, 0xdd, 0xd4, 0x7d, 0x78, + 0x28, 0xc5, 0x9b, 0xd0, 0xa2, 0x1b, 0xfd, 0x39, + 0x80, 0xff, 0x0d, 0x20, 0x28, 0xd4, 0xb1, 0x8a, + 0x9d, 0xf6, 0x3e, 0x00, 0x6c, 0x5d, 0x1c, 0x2d, + 0x34, 0x5b, 0x92, 0x5d, 0x8d, 0xc0, 0x0b, 0x41, + 0x04, 0x85, 0x2d, 0xb9, 0x9a, 0xc5, 0xc7, 0xcd, + 0xda, 0x85, 0x30, 0xa1, 0x13, 0xa0, 0xf4, 0xdb, + 0xb6, 0x11, 0x49, 0xf0, 0x5a, 0x73, 0x63, 0x26, + 0x8c, 0x71, 0xd9, 0x58, 0x08, 0xff, 0x2e, 0x65, + 0x26, 0x00 + }; + + /* compressed prefix */ + static const byte sig5[] = { + 0x53, 0x3a, 0x37, 0xf6, 0xbb, 0xe4, 0x57, 0x25, + 0x1f, 0x02, 0x3c, 0x0d, 0x88, 0xf9, 0x76, 0xae, + 0x2d, 0xfb, 0x50, 0x4a, 0x84, 0x3e, 0x34, 0xd2, + 0x07, 0x4f, 0xd8, 0x23, 0xd4, 0x1a, 0x59, 0x1f, + 0x2b, 0x23, 0x3f, 0x03, 0x4f, 0x62, 0x82, 0x81, + 0xf2, 0xfd, 0x7a, 0x22, 0xdd, 0xd4, 0x7d, 0x78, + 0x28, 0xc5, 0x9b, 0xd0, 0xa2, 0x1b, 0xfd, 0x39, + 0x80, 0xff, 0x0d, 0x20, 0x28, 0xd4, 0xb1, 0x8a, + 0x9d, 0xf6, 0x3e, 0x00, 0x6c, 0x5d, 0x1c, 0x2d, + 0x34, 0x5b, 0x92, 0x5d, 0x8d, 0xc0, 0x0b, 0x41, + 0x04, 0x85, 0x2d, 0xb9, 0x9a, 0xc5, 0xc7, 0xcd, + 0xda, 0x85, 0x30, 0xa1, 0x13, 0xa0, 0xf4, 0xdb, + 0xb6, 0x11, 0x49, 0xf0, 0x5a, 0x73, 0x63, 0x26, + 0x8c, 0x71, 0xd9, 0x58, 0x08, 0xff, 0x2e, 0x65, + 0x26, 0x00 + }; + + static const byte sig6[] = { + 0xe3, 0x01, 0x34, 0x5a, 0x41, 0xa3, 0x9a, 0x4d, + 0x72, 0xff, 0xf8, 0xdf, 0x69, 0xc9, 0x80, 0x75, + 0xa0, 0xcc, 0x08, 0x2b, 0x80, 0x2f, 0xc9, 0xb2, + 0xb6, 0xbc, 0x50, 0x3f, 0x92, 0x6b, 0x65, 0xbd, + 0xdf, 0x7f, 0x4c, 0x8f, 0x1c, 0xb4, 0x9f, 0x63, + 0x96, 0xaf, 0xc8, 0xa7, 0x0a, 0xbe, 0x6d, 0x8a, + 0xef, 0x0d, 0xb4, 0x78, 0xd4, 0xc6, 0xb2, 0x97, + 0x00, 0x76, 0xc6, 0xa0, 0x48, 0x4f, 0xe7, 0x6d, + 0x76, 0xb3, 0xa9, 0x76, 0x25, 0xd7, 0x9f, 0x1c, + 0xe2, 0x40, 0xe7, 0xc5, 0x76, 0x75, 0x0d, 0x29, + 0x55, 0x28, 0x28, 0x6f, 0x71, 0x9b, 0x41, 0x3d, + 0xe9, 0xad, 0xa3, 0xe8, 0xeb, 0x78, 0xed, 0x57, + 0x36, 0x03, 0xce, 0x30, 0xd8, 0xbb, 0x76, 0x17, + 0x85, 0xdc, 0x30, 0xdb, 0xc3, 0x20, 0x86, 0x9e, + 0x1a, 0x00 + }; + + static const byte* sigs[] = {sig1, sig2, sig3, sig4, sig5, sig6}; + + static const byte msg1[] = { }; + static const byte msg2[] = { 0x03 }; + static const byte msg3[] = { 0x64, 0xa6, 0x5f, 0x3c, 0xde, 0xdc, 0xdd, + 0x66, 0x81, 0x1e, 0x29, 0x15 }; + + /* test of a 1023 byte long message */ + static const byte msg4[] = { + 0x6d, 0xdf, 0x80, 0x2e, 0x1a, 0xae, 0x49, 0x86, + 0x93, 0x5f, 0x7f, 0x98, 0x1b, 0xa3, 0xf0, 0x35, + 0x1d, 0x62, 0x73, 0xc0, 0xa0, 0xc2, 0x2c, 0x9c, + 0x0e, 0x83, 0x39, 0x16, 0x8e, 0x67, 0x54, 0x12, + 0xa3, 0xde, 0xbf, 0xaf, 0x43, 0x5e, 0xd6, 0x51, + 0x55, 0x80, 0x07, 0xdb, 0x43, 0x84, 0xb6, 0x50, + 0xfc, 0xc0, 0x7e, 0x3b, 0x58, 0x6a, 0x27, 0xa4, + 0xf7, 0xa0, 0x0a, 0xc8, 0xa6, 0xfe, 0xc2, 0xcd, + 0x86, 0xae, 0x4b, 0xf1, 0x57, 0x0c, 0x41, 0xe6, + 0xa4, 0x0c, 0x93, 0x1d, 0xb2, 0x7b, 0x2f, 0xaa, + 0x15, 0xa8, 0xce, 0xdd, 0x52, 0xcf, 0xf7, 0x36, + 0x2c, 0x4e, 0x6e, 0x23, 0xda, 0xec, 0x0f, 0xbc, + 0x3a, 0x79, 0xb6, 0x80, 0x6e, 0x31, 0x6e, 0xfc, + 0xc7, 0xb6, 0x81, 0x19, 0xbf, 0x46, 0xbc, 0x76, + 0xa2, 0x60, 0x67, 0xa5, 0x3f, 0x29, 0x6d, 0xaf, + 0xdb, 0xdc, 0x11, 0xc7, 0x7f, 0x77, 0x77, 0xe9, + 0x72, 0x66, 0x0c, 0xf4, 0xb6, 0xa9, 0xb3, 0x69, + 0xa6, 0x66, 0x5f, 0x02, 0xe0, 0xcc, 0x9b, 0x6e, + 0xdf, 0xad, 0x13, 0x6b, 0x4f, 0xab, 0xe7, 0x23, + 0xd2, 0x81, 0x3d, 0xb3, 0x13, 0x6c, 0xfd, 0xe9, + 0xb6, 0xd0, 0x44, 0x32, 0x2f, 0xee, 0x29, 0x47, + 0x95, 0x2e, 0x03, 0x1b, 0x73, 0xab, 0x5c, 0x60, + 0x33, 0x49, 0xb3, 0x07, 0xbd, 0xc2, 0x7b, 0xc6, + 0xcb, 0x8b, 0x8b, 0xbd, 0x7b, 0xd3, 0x23, 0x21, + 0x9b, 0x80, 0x33, 0xa5, 0x81, 0xb5, 0x9e, 0xad, + 0xeb, 0xb0, 0x9b, 0x3c, 0x4f, 0x3d, 0x22, 0x77, + 0xd4, 0xf0, 0x34, 0x36, 0x24, 0xac, 0xc8, 0x17, + 0x80, 0x47, 0x28, 0xb2, 0x5a, 0xb7, 0x97, 0x17, + 0x2b, 0x4c, 0x5c, 0x21, 0xa2, 0x2f, 0x9c, 0x78, + 0x39, 0xd6, 0x43, 0x00, 0x23, 0x2e, 0xb6, 0x6e, + 0x53, 0xf3, 0x1c, 0x72, 0x3f, 0xa3, 0x7f, 0xe3, + 0x87, 0xc7, 0xd3, 0xe5, 0x0b, 0xdf, 0x98, 0x13, + 0xa3, 0x0e, 0x5b, 0xb1, 0x2c, 0xf4, 0xcd, 0x93, + 0x0c, 0x40, 0xcf, 0xb4, 0xe1, 0xfc, 0x62, 0x25, + 0x92, 0xa4, 0x95, 0x88, 0x79, 0x44, 0x94, 0xd5, + 0x6d, 0x24, 0xea, 0x4b, 0x40, 0xc8, 0x9f, 0xc0, + 0x59, 0x6c, 0xc9, 0xeb, 0xb9, 0x61, 0xc8, 0xcb, + 0x10, 0xad, 0xde, 0x97, 0x6a, 0x5d, 0x60, 0x2b, + 0x1c, 0x3f, 0x85, 0xb9, 0xb9, 0xa0, 0x01, 0xed, + 0x3c, 0x6a, 0x4d, 0x3b, 0x14, 0x37, 0xf5, 0x20, + 0x96, 0xcd, 0x19, 0x56, 0xd0, 0x42, 0xa5, 0x97, + 0xd5, 0x61, 0xa5, 0x96, 0xec, 0xd3, 0xd1, 0x73, + 0x5a, 0x8d, 0x57, 0x0e, 0xa0, 0xec, 0x27, 0x22, + 0x5a, 0x2c, 0x4a, 0xaf, 0xf2, 0x63, 0x06, 0xd1, + 0x52, 0x6c, 0x1a, 0xf3, 0xca, 0x6d, 0x9c, 0xf5, + 0xa2, 0xc9, 0x8f, 0x47, 0xe1, 0xc4, 0x6d, 0xb9, + 0xa3, 0x32, 0x34, 0xcf, 0xd4, 0xd8, 0x1f, 0x2c, + 0x98, 0x53, 0x8a, 0x09, 0xeb, 0xe7, 0x69, 0x98, + 0xd0, 0xd8, 0xfd, 0x25, 0x99, 0x7c, 0x7d, 0x25, + 0x5c, 0x6d, 0x66, 0xec, 0xe6, 0xfa, 0x56, 0xf1, + 0x11, 0x44, 0x95, 0x0f, 0x02, 0x77, 0x95, 0xe6, + 0x53, 0x00, 0x8f, 0x4b, 0xd7, 0xca, 0x2d, 0xee, + 0x85, 0xd8, 0xe9, 0x0f, 0x3d, 0xc3, 0x15, 0x13, + 0x0c, 0xe2, 0xa0, 0x03, 0x75, 0xa3, 0x18, 0xc7, + 0xc3, 0xd9, 0x7b, 0xe2, 0xc8, 0xce, 0x5b, 0x6d, + 0xb4, 0x1a, 0x62, 0x54, 0xff, 0x26, 0x4f, 0xa6, + 0x15, 0x5b, 0xae, 0xe3, 0xb0, 0x77, 0x3c, 0x0f, + 0x49, 0x7c, 0x57, 0x3f, 0x19, 0xbb, 0x4f, 0x42, + 0x40, 0x28, 0x1f, 0x0b, 0x1f, 0x4f, 0x7b, 0xe8, + 0x57, 0xa4, 0xe5, 0x9d, 0x41, 0x6c, 0x06, 0xb4, + 0xc5, 0x0f, 0xa0, 0x9e, 0x18, 0x10, 0xdd, 0xc6, + 0xb1, 0x46, 0x7b, 0xae, 0xac, 0x5a, 0x36, 0x68, + 0xd1, 0x1b, 0x6e, 0xca, 0xa9, 0x01, 0x44, 0x00, + 0x16, 0xf3, 0x89, 0xf8, 0x0a, 0xcc, 0x4d, 0xb9, + 0x77, 0x02, 0x5e, 0x7f, 0x59, 0x24, 0x38, 0x8c, + 0x7e, 0x34, 0x0a, 0x73, 0x2e, 0x55, 0x44, 0x40, + 0xe7, 0x65, 0x70, 0xf8, 0xdd, 0x71, 0xb7, 0xd6, + 0x40, 0xb3, 0x45, 0x0d, 0x1f, 0xd5, 0xf0, 0x41, + 0x0a, 0x18, 0xf9, 0xa3, 0x49, 0x4f, 0x70, 0x7c, + 0x71, 0x7b, 0x79, 0xb4, 0xbf, 0x75, 0xc9, 0x84, + 0x00, 0xb0, 0x96, 0xb2, 0x16, 0x53, 0xb5, 0xd2, + 0x17, 0xcf, 0x35, 0x65, 0xc9, 0x59, 0x74, 0x56, + 0xf7, 0x07, 0x03, 0x49, 0x7a, 0x07, 0x87, 0x63, + 0x82, 0x9b, 0xc0, 0x1b, 0xb1, 0xcb, 0xc8, 0xfa, + 0x04, 0xea, 0xdc, 0x9a, 0x6e, 0x3f, 0x66, 0x99, + 0x58, 0x7a, 0x9e, 0x75, 0xc9, 0x4e, 0x5b, 0xab, + 0x00, 0x36, 0xe0, 0xb2, 0xe7, 0x11, 0x39, 0x2c, + 0xff, 0x00, 0x47, 0xd0, 0xd6, 0xb0, 0x5b, 0xd2, + 0xa5, 0x88, 0xbc, 0x10, 0x97, 0x18, 0x95, 0x42, + 0x59, 0xf1, 0xd8, 0x66, 0x78, 0xa5, 0x79, 0xa3, + 0x12, 0x0f, 0x19, 0xcf, 0xb2, 0x96, 0x3f, 0x17, + 0x7a, 0xeb, 0x70, 0xf2, 0xd4, 0x84, 0x48, 0x26, + 0x26, 0x2e, 0x51, 0xb8, 0x02, 0x71, 0x27, 0x20, + 0x68, 0xef, 0x5b, 0x38, 0x56, 0xfa, 0x85, 0x35, + 0xaa, 0x2a, 0x88, 0xb2, 0xd4, 0x1f, 0x2a, 0x0e, + 0x2f, 0xda, 0x76, 0x24, 0xc2, 0x85, 0x02, 0x72, + 0xac, 0x4a, 0x2f, 0x56, 0x1f, 0x8f, 0x2f, 0x7a, + 0x31, 0x8b, 0xfd, 0x5c, 0xaf, 0x96, 0x96, 0x14, + 0x9e, 0x4a, 0xc8, 0x24, 0xad, 0x34, 0x60, 0x53, + 0x8f, 0xdc, 0x25, 0x42, 0x1b, 0xee, 0xc2, 0xcc, + 0x68, 0x18, 0x16, 0x2d, 0x06, 0xbb, 0xed, 0x0c, + 0x40, 0xa3, 0x87, 0x19, 0x23, 0x49, 0xdb, 0x67, + 0xa1, 0x18, 0xba, 0xda, 0x6c, 0xd5, 0xab, 0x01, + 0x40, 0xee, 0x27, 0x32, 0x04, 0xf6, 0x28, 0xaa, + 0xd1, 0xc1, 0x35, 0xf7, 0x70, 0x27, 0x9a, 0x65, + 0x1e, 0x24, 0xd8, 0xc1, 0x4d, 0x75, 0xa6, 0x05, + 0x9d, 0x76, 0xb9, 0x6a, 0x6f, 0xd8, 0x57, 0xde, + 0xf5, 0xe0, 0xb3, 0x54, 0xb2, 0x7a, 0xb9, 0x37, + 0xa5, 0x81, 0x5d, 0x16, 0xb5, 0xfa, 0xe4, 0x07, + 0xff, 0x18, 0x22, 0x2c, 0x6d, 0x1e, 0xd2, 0x63, + 0xbe, 0x68, 0xc9, 0x5f, 0x32, 0xd9, 0x08, 0xbd, + 0x89, 0x5c, 0xd7, 0x62, 0x07, 0xae, 0x72, 0x64, + 0x87, 0x56, 0x7f, 0x9a, 0x67, 0xda, 0xd7, 0x9a, + 0xbe, 0xc3, 0x16, 0xf6, 0x83, 0xb1, 0x7f, 0x2d, + 0x02, 0xbf, 0x07, 0xe0, 0xac, 0x8b, 0x5b, 0xc6, + 0x16, 0x2c, 0xf9, 0x46, 0x97, 0xb3, 0xc2, 0x7c, + 0xd1, 0xfe, 0xa4, 0x9b, 0x27, 0xf2, 0x3b, 0xa2, + 0x90, 0x18, 0x71, 0x96, 0x25, 0x06, 0x52, 0x0c, + 0x39, 0x2d, 0xa8, 0xb6, 0xad, 0x0d, 0x99, 0xf7, + 0x01, 0x3f, 0xbc, 0x06, 0xc2, 0xc1, 0x7a, 0x56, + 0x95, 0x00, 0xc8, 0xa7, 0x69, 0x64, 0x81, 0xc1, + 0xcd, 0x33, 0xe9, 0xb1, 0x4e, 0x40, 0xb8, 0x2e, + 0x79, 0xa5, 0xf5, 0xdb, 0x82, 0x57, 0x1b, 0xa9, + 0x7b, 0xae, 0x3a, 0xd3, 0xe0, 0x47, 0x95, 0x15, + 0xbb, 0x0e, 0x2b, 0x0f, 0x3b, 0xfc, 0xd1, 0xfd, + 0x33, 0x03, 0x4e, 0xfc, 0x62, 0x45, 0xed, 0xdd, + 0x7e, 0xe2, 0x08, 0x6d, 0xda, 0xe2, 0x60, 0x0d, + 0x8c, 0xa7, 0x3e, 0x21, 0x4e, 0x8c, 0x2b, 0x0b, + 0xdb, 0x2b, 0x04, 0x7c, 0x6a, 0x46, 0x4a, 0x56, + 0x2e, 0xd7, 0x7b, 0x73, 0xd2, 0xd8, 0x41, 0xc4, + 0xb3, 0x49, 0x73, 0x55, 0x12, 0x57, 0x71, 0x3b, + 0x75, 0x36, 0x32, 0xef, 0xba, 0x34, 0x81, 0x69, + 0xab, 0xc9, 0x0a, 0x68, 0xf4, 0x26, 0x11, 0xa4, + 0x01, 0x26, 0xd7, 0xcb, 0x21, 0xb5, 0x86, 0x95, + 0x56, 0x81, 0x86, 0xf7, 0xe5, 0x69, 0xd2, 0xff, + 0x0f, 0x9e, 0x74, 0x5d, 0x04, 0x87, 0xdd, 0x2e, + 0xb9, 0x97, 0xca, 0xfc, 0x5a, 0xbf, 0x9d, 0xd1, + 0x02, 0xe6, 0x2f, 0xf6, 0x6c, 0xba, 0x87 + }; + + 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) + }; +#ifndef NO_ASN + static byte privateEd448[] = { + 0x30, 0x47, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, + 0x03, 0x2b, 0x65, 0x71, 0x04, 0x3b, 0x04, 0x39, + 0x6c, 0x82, 0xa5, 0x62, 0xcb, 0x80, 0x8d, 0x10, + 0xd6, 0x32, 0xbe, 0x89, 0xc8, 0x51, 0x3e, 0xbf, + 0x6c, 0x92, 0x9f, 0x34, 0xdd, 0xfa, 0x8c, 0x9f, + 0x63, 0xc9, 0x96, 0x0e, 0xf6, 0xe3, 0x48, 0xa3, + 0x52, 0x8c, 0x8a, 0x3f, 0xcc, 0x2f, 0x04, 0x4e, + 0x39, 0xa3, 0xfc, 0x5b, 0x94, 0x49, 0x2f, 0x8f, + 0x03, 0x2e, 0x75, 0x49, 0xa2, 0x00, 0x98, 0xf9, + 0x5b + }; + static byte publicEd448[] = { + 0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, + 0x71, 0x03, 0x3a, 0x00, 0x5f, 0xd7, 0x44, 0x9b, + 0x59, 0xb4, 0x61, 0xfd, 0x2c, 0xe7, 0x87, 0xec, + 0x61, 0x6a, 0xd4, 0x6a, 0x1d, 0xa1, 0x34, 0x24, + 0x85, 0xa7, 0x0e, 0x1f, 0x8a, 0x0e, 0xa7, 0x5d, + 0x80, 0xe9, 0x67, 0x78, 0xed, 0xf1, 0x24, 0x76, + 0x9b, 0x46, 0xc7, 0x06, 0x1b, 0xd6, 0x78, 0x3d, + 0xf1, 0xe5, 0x0f, 0x6c, 0xd1, 0xfa, 0x1a, 0xbe, + 0xaf, 0xe8, 0x25, 0x61, 0x80 + }; + static byte privPubEd448[] = { + 0x30, 0x81, 0x84, 0x02, 0x01, 0x00, 0x30, 0x05, + 0x06, 0x03, 0x2b, 0x65, 0x71, 0x04, 0x3b, 0x04, + 0x39, 0x6c, 0x82, 0xa5, 0x62, 0xcb, 0x80, 0x8d, + 0x10, 0xd6, 0x32, 0xbe, 0x89, 0xc8, 0x51, 0x3e, + 0xbf, 0x6c, 0x92, 0x9f, 0x34, 0xdd, 0xfa, 0x8c, + 0x9f, 0x63, 0xc9, 0x96, 0x0e, 0xf6, 0xe3, 0x48, + 0xa3, 0x52, 0x8c, 0x8a, 0x3f, 0xcc, 0x2f, 0x04, + 0x4e, 0x39, 0xa3, 0xfc, 0x5b, 0x94, 0x49, 0x2f, + 0x8f, 0x03, 0x2e, 0x75, 0x49, 0xa2, 0x00, 0x98, + 0xf9, 0x5b, 0xa1, 0x3b, 0x04, 0x39, 0x5f, 0xd7, + 0x44, 0x9b, 0x59, 0xb4, 0x61, 0xfd, 0x2c, 0xe7, + 0x87, 0xec, 0x61, 0x6a, 0xd4, 0x6a, 0x1d, 0xa1, + 0x34, 0x24, 0x85, 0xa7, 0x0e, 0x1f, 0x8a, 0x0e, + 0xa7, 0x5d, 0x80, 0xe9, 0x67, 0x78, 0xed, 0xf1, + 0x24, 0x76, 0x9b, 0x46, 0xc7, 0x06, 0x1b, 0xd6, + 0x78, 0x3d, 0xf1, 0xe5, 0x0f, 0x6c, 0xd1, 0xfa, + 0x1a, 0xbe, 0xaf, 0xe8, 0x25, 0x61, 0x80 + }; + + word32 idx; + ed448_key key3; +#endif /* NO_ASN */ +#endif /* HAVE_ED448_SIGN && HAVE_ED448_KEY_EXPORT && HAVE_ED448_KEY_IMPORT */ + + /* create ed448 keys */ +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -11300; + + wc_ed448_init(&key); + wc_ed448_init(&key2); +#ifndef NO_ASN + wc_ed448_init(&key3); +#endif + wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key); + wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key2); + + /* helper functions for signature and key size */ + keySz = wc_ed448_size(&key); + sigSz = wc_ed448_sig_size(&key); + +#if defined(HAVE_ED448_SIGN) && defined(HAVE_ED448_KEY_EXPORT) &&\ + defined(HAVE_ED448_KEY_IMPORT) + for (i = 0; i < 6; i++) { + outlen = sizeof(out); + XMEMSET(out, 0, sizeof(out)); + + if (wc_ed448_import_private_key(sKeys[i], ED448_KEY_SIZE, pKeys[i], + pKeySz[i], &key) != 0) + return -11301 - i; + + if (wc_ed448_sign_msg(msgs[i], msgSz[i], out, &outlen, &key, NULL, + 0) != 0) { + return -11311 - i; + } + + if (XMEMCMP(out, sigs[i], 114)) + return -11321 - i; + +#if defined(HAVE_ED448_VERIFY) + /* test verify on good msg */ + if (wc_ed448_verify_msg(out, outlen, msgs[i], msgSz[i], &verify, &key, + NULL, 0) != 0 || verify != 1) { + return -11331 - i; + } + + /* test verify on bad msg */ + out[outlen-2] = out[outlen-2] + 1; + if (wc_ed448_verify_msg(out, outlen, msgs[i], msgSz[i], &verify, &key, + NULL, 0) == 0 || verify == 1) { + return -11341 - i; + } +#endif /* HAVE_ED448_VERIFY */ + + /* test api for import/exporting keys */ + exportPSz = sizeof(exportPKey); + exportSSz = sizeof(exportSKey); + if (wc_ed448_export_public(&key, exportPKey, &exportPSz) != 0) + return -11351 - i; + + if (wc_ed448_import_public(exportPKey, exportPSz, &key2) != 0) + return -11361 - i; + + if (wc_ed448_export_private_only(&key, exportSKey, &exportSSz) != 0) + return -11371 - i; + + if (wc_ed448_import_private_key(exportSKey, exportSSz, + exportPKey, exportPSz, &key2) != 0) + return -11381 - i; + + /* clear "out" buffer and test sign with imported keys */ + outlen = sizeof(out); + XMEMSET(out, 0, sizeof(out)); + if (wc_ed448_sign_msg(msgs[i], msgSz[i], out, &outlen, &key2, NULL, + 0) != 0) { + return -11391 - i; + } + +#if defined(HAVE_ED448_VERIFY) + if (wc_ed448_verify_msg(out, outlen, msgs[i], msgSz[i], &verify, &key2, + NULL, 0) != 0 || verify != 1) + return -11401 - i; + + if (XMEMCMP(out, sigs[i], sizeof(sigs[i]))) + return -11411 - i; +#endif /* HAVE_ED448_VERIFY */ + } + + ret = ed448_ctx_test(); + if (ret != 0) + return ret; + + ret = ed448ph_test(); + if (ret != 0) + return ret; + +#ifndef NO_ASN + /* Try ASN.1 encoded private-only key and public key. */ + idx = 0; + if (wc_Ed448PrivateKeyDecode(privateEd448, &idx, &key3, + sizeof(privateEd448)) != 0) + return -11421 - i; + + if (wc_ed448_sign_msg(msgs[0], msgSz[0], out, &outlen, &key3, NULL, 0) + != BAD_FUNC_ARG) + return -11431 - i; + + idx = 0; + if (wc_Ed448PublicKeyDecode(publicEd448, &idx, &key3, + sizeof(publicEd448)) != 0) + return -11441 - i; + + if (wc_ed448_sign_msg(msgs[0], msgSz[0], out, &outlen, &key3, NULL, 0) != 0) + return -11451 - i; + + if (XMEMCMP(out, sigs[0], sizeof(sigs[0]))) + return -11461 - i; + +#if defined(HAVE_ED448_VERIFY) + /* test verify on good msg */ + if (wc_ed448_verify_msg(out, outlen, msgs[0], msgSz[0], &verify, &key3, + NULL, 0) != 0 || verify != 1) + return -11471 - i; +#endif /* HAVE_ED448_VERIFY */ + + wc_ed448_free(&key3); + wc_ed448_init(&key3); + + idx = 0; + if (wc_Ed448PrivateKeyDecode(privPubEd448, &idx, &key3, + sizeof(privPubEd448)) != 0) + return -11481 - i; + + if (wc_ed448_sign_msg(msgs[0], msgSz[0], out, &outlen, &key3, NULL, 0) != 0) + return -11491 - i; + + if (XMEMCMP(out, sigs[0], sizeof(sigs[0]))) + return -11501 - i; + + wc_ed448_free(&key3); +#endif /* NO_ASN */ +#endif /* HAVE_ED448_SIGN && HAVE_ED448_KEY_EXPORT && HAVE_ED448_KEY_IMPORT */ + + /* clean up keys when done */ + wc_ed448_free(&key); + wc_ed448_free(&key2); + +#if defined(HAVE_HASHDRBG) || defined(NO_RC4) + wc_FreeRng(&rng); +#endif + + /* hush warnings of unused keySz and sigSz */ + (void)keySz; + (void)sigSz; + +#ifdef WOLFSSL_TEST_CERT + ret = ed448_test_cert(); + if (ret < 0) + return ret; +#ifdef WOLFSSL_CERT_GEN + ret = ed448_test_make_cert(); + if (ret < 0) + return ret; +#endif /* WOLFSSL_CERT_GEN */ +#endif /* WOLFSSL_TEST_CERT */ + + return 0; +} +#endif /* HAVE_ED448 */ + +#if defined(WOLFSSL_CMAC) && !defined(NO_AES) + +typedef struct CMAC_Test_Case { + int type; + int partial; + const byte* m; + word32 mSz; + const byte* k; + word32 kSz; + const byte* t; + word32 tSz; +} CMAC_Test_Case; + +int cmac_test(void) +{ +#ifdef WOLFSSL_AES_128 + const byte k128[] = + { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c + }; + #define KLEN_128 (sizeof(k128)) +#endif +#ifdef WOLFSSL_AES_192 + const byte k192[] = + { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b + }; + #define KLEN_192 (sizeof(k192)) +#endif +#ifdef WOLFSSL_AES_256 + const byte k256[] = + { + 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 + }; + #define KLEN_256 (sizeof(k256)) +#endif + + const byte m[] = + { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + #define MLEN_0 (0) + #define MLEN_128 (128/8) + #define MLEN_320 (320/8) + #define MLEN_319 (MLEN_320 - 1) + #define MLEN_512 (512/8) + +#ifdef WOLFSSL_AES_128 + const byte t128_0[] = + { + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 + }; + const byte t128_128[] = + { + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c + }; + const byte t128_319[] = + { + 0x2c, 0x17, 0x84, 0x4c, 0x93, 0x1c, 0x07, 0x95, + 0x15, 0x92, 0x73, 0x0a, 0x34, 0xd0, 0xd9, 0xd2 + }; + const byte t128_320[] = + { + 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, + 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 + }; + const byte t128_512[] = + { + 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe + }; +#endif +#ifdef WOLFSSL_AES_192 + const byte t192_0[] = + { + 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, + 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 + }; + const byte t192_128[] = + { + 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, + 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 + }; + const byte t192_320[] = + { + 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad, + 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e + }; + const byte t192_512[] = + { + 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, + 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 + }; +#endif +#ifdef WOLFSSL_AES_256 + const byte t256_0[] = + { + 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, + 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 + }; + const byte t256_128[] = + { + 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, + 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c + }; + const byte t256_320[] = + { + 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2, + 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6 + }; + const byte t256_512[] = + { + 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, + 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 + }; +#endif + const CMAC_Test_Case testCases[] = + { +#ifdef WOLFSSL_AES_128 + {WC_CMAC_AES, 0, m, MLEN_0, k128, KLEN_128, t128_0, AES_BLOCK_SIZE}, + {WC_CMAC_AES, 0, m, MLEN_128, k128, KLEN_128, t128_128, AES_BLOCK_SIZE}, + {WC_CMAC_AES, 0, m, MLEN_320, k128, KLEN_128, t128_320, AES_BLOCK_SIZE}, + {WC_CMAC_AES, 0, m, MLEN_512, k128, KLEN_128, t128_512, AES_BLOCK_SIZE}, + {WC_CMAC_AES, 5, m, MLEN_512, k128, KLEN_128, t128_512, AES_BLOCK_SIZE}, +#endif +#ifdef WOLFSSL_AES_192 + {WC_CMAC_AES, 0, m, MLEN_0, k192, KLEN_192, t192_0, AES_BLOCK_SIZE}, + {WC_CMAC_AES, 0, m, MLEN_128, k192, KLEN_192, t192_128, AES_BLOCK_SIZE}, + {WC_CMAC_AES, 0, m, MLEN_320, k192, KLEN_192, t192_320, AES_BLOCK_SIZE}, + {WC_CMAC_AES, 0, m, MLEN_512, k192, KLEN_192, t192_512, AES_BLOCK_SIZE}, +#endif +#ifdef WOLFSSL_AES_256 + {WC_CMAC_AES, 0, m, MLEN_0, k256, KLEN_256, t256_0, AES_BLOCK_SIZE}, + {WC_CMAC_AES, 0, m, MLEN_128, k256, KLEN_256, t256_128, AES_BLOCK_SIZE}, + {WC_CMAC_AES, 0, m, MLEN_320, k256, KLEN_256, t256_320, AES_BLOCK_SIZE}, + {WC_CMAC_AES, 0, m, MLEN_512, k256, KLEN_256, t256_512, AES_BLOCK_SIZE}, +#endif +#ifdef WOLFSSL_AES_128 + {WC_CMAC_AES, 0, m, MLEN_319, k128, KLEN_128, t128_319, AES_BLOCK_SIZE} +#endif + }; + + Cmac cmac; + byte tag[AES_BLOCK_SIZE]; + const CMAC_Test_Case* tc; + word32 i, tagSz; + + for (i = 0, tc = testCases; + i < sizeof(testCases)/sizeof(CMAC_Test_Case); + i++, tc++) { + + XMEMSET(tag, 0, sizeof(tag)); + tagSz = AES_BLOCK_SIZE; + if (wc_InitCmac(&cmac, tc->k, tc->kSz, tc->type, NULL) != 0) + return -11600; + if (tc->partial) { + if (wc_CmacUpdate(&cmac, tc->m, + tc->mSz/2 - tc->partial) != 0) + return -11601; + if (wc_CmacUpdate(&cmac, tc->m + tc->mSz/2 - tc->partial, + tc->mSz/2 + tc->partial) != 0) + return -11602; + } + else { + if (wc_CmacUpdate(&cmac, tc->m, tc->mSz) != 0) + return -11603; + } + if (wc_CmacFinal(&cmac, tag, &tagSz) != 0) + return -11604; + if (XMEMCMP(tag, tc->t, AES_BLOCK_SIZE) != 0) + return -11605; + + XMEMSET(tag, 0, sizeof(tag)); + tagSz = sizeof(tag); + if (wc_AesCmacGenerate(tag, &tagSz, tc->m, tc->mSz, + tc->k, tc->kSz) != 0) + return -11606; + if (XMEMCMP(tag, tc->t, AES_BLOCK_SIZE) != 0) + return -11607; + if (wc_AesCmacVerify(tc->t, tc->tSz, tc->m, tc->mSz, + tc->k, tc->kSz) != 0) + return -11608; + } + + return 0; +} + +#endif /* NO_AES && WOLFSSL_CMAC */ #ifdef HAVE_LIBZ @@ -5878,37 +23481,228 @@ const byte sample_text[] = "swag consectetur et. Irure skateboard banjo, nulla deserunt messenger\n" "bag dolor terry richardson sapiente.\n"; +const byte sample_text_gz[] = { + 0x1F, 0x8B, 0x08, 0x08, 0xC5, 0x49, 0xB5, 0x5B, 0x00, 0x03, 0x63, 0x69, 0x70, + 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x2E, 0x74, 0x78, 0x74, 0x00, 0x8D, + 0x58, 0xCB, 0x92, 0xE4, 0xB6, 0x11, 0xBC, 0xE3, 0x2B, 0xEA, 0xA6, 0x83, 0xD9, + 0x1D, 0x72, 0xF8, 0x22, 0x1F, 0xB5, 0x96, 0xA5, 0xDD, 0x90, 0xBC, 0xAB, 0xD0, + 0x28, 0x36, 0x42, 0x47, 0x90, 0x2C, 0x36, 0xA1, 0x06, 0x09, 0x0A, 0x8F, 0xEE, + 0xE1, 0xDF, 0x3B, 0x0B, 0xE0, 0x73, 0x2C, 0x4B, 0xBA, 0xCD, 0xCE, 0x80, 0x78, + 0x64, 0x65, 0x65, 0x66, 0xED, 0x3B, 0xE3, 0x5A, 0xC3, 0x81, 0x2D, 0x35, 0x69, + 0x32, 0xAD, 0x8E, 0x3A, 0xD2, 0xA0, 0x7D, 0xA7, 0x2B, 0x6A, 0xAC, 0x69, 0x7A, + 0x26, 0x9D, 0x22, 0xD3, 0x94, 0x22, 0x69, 0xAA, 0x8D, 0x6F, 0xC9, 0x8D, 0x64, + 0x22, 0x99, 0xB1, 0x31, 0xAD, 0x69, 0xD3, 0x18, 0x89, 0xAD, 0x89, 0x6A, 0x72, + 0x56, 0x7B, 0x67, 0xDA, 0x2B, 0xBD, 0xC8, 0xEF, 0xB0, 0x4D, 0x74, 0x8E, 0x5B, + 0xAA, 0x39, 0x4C, 0xEE, 0xCE, 0xE4, 0x79, 0xF2, 0xDC, 0xF3, 0xD8, 0xB2, 0x37, + 0x11, 0x8B, 0x8C, 0x2C, 0x7A, 0x32, 0x93, 0xF3, 0x37, 0x3D, 0x9A, 0x86, 0x4C, + 0xAB, 0xF2, 0xB9, 0x57, 0xFA, 0x97, 0x1B, 0x06, 0xD7, 0x3A, 0x7A, 0xF0, 0x68, + 0xF4, 0x40, 0xBA, 0x25, 0x0E, 0x81, 0xE9, 0xA6, 0x43, 0xF4, 0x6E, 0x4A, 0xF5, + 0x95, 0xFE, 0x41, 0x4F, 0x67, 0x3B, 0x1A, 0x1C, 0xEE, 0x12, 0xB4, 0x8F, 0xCE, + 0x1B, 0x6D, 0xB1, 0xDE, 0xBB, 0x4A, 0x4D, 0x56, 0x9B, 0x96, 0x5A, 0xB6, 0xDC, + 0xC4, 0x14, 0x70, 0xE5, 0xF5, 0x7D, 0xE1, 0xB7, 0x84, 0x3F, 0xFC, 0xED, 0xEF, + 0xF4, 0x30, 0x0D, 0x5F, 0xE9, 0x47, 0x17, 0xE2, 0xC5, 0x78, 0x27, 0x67, 0xDF, + 0xB9, 0xEB, 0xCC, 0xCC, 0x3D, 0x59, 0xBE, 0xDD, 0xCC, 0x78, 0x0B, 0x0A, 0x1F, + 0x74, 0xF8, 0x8C, 0x1A, 0xAF, 0x67, 0xEA, 0xF4, 0x44, 0xBD, 0x93, 0x7D, 0x2A, + 0xEA, 0x9C, 0xD7, 0x37, 0x80, 0x32, 0x9A, 0x01, 0x37, 0xD5, 0xDE, 0xCA, 0xA2, + 0x0D, 0xB9, 0xD0, 0x3B, 0xCF, 0xAD, 0x89, 0x4D, 0x5F, 0xD1, 0xE7, 0xF7, 0x2F, + 0x2A, 0x0C, 0xDA, 0x5A, 0xAA, 0x35, 0x7E, 0x41, 0xC3, 0xB2, 0x37, 0xDD, 0xDD, + 0xCD, 0x50, 0xEB, 0x2C, 0x96, 0x62, 0x3B, 0xD7, 0x52, 0xF4, 0xA9, 0xB9, 0x6F, + 0x48, 0xED, 0xEF, 0x54, 0xEA, 0x67, 0xF6, 0x7E, 0x26, 0x8F, 0x3A, 0x68, 0xDF, + 0x06, 0xBC, 0x56, 0xB7, 0x66, 0x32, 0xC1, 0x34, 0xD8, 0x88, 0x34, 0x1E, 0x88, + 0xED, 0x67, 0x8A, 0xF3, 0xC4, 0x4F, 0xC0, 0xCA, 0x9E, 0x62, 0x1A, 0x6A, 0xEB, + 0xAB, 0x02, 0xED, 0xB3, 0xD7, 0x91, 0x81, 0x8A, 0xEA, 0x5C, 0xF2, 0x64, 0xDD, + 0xDD, 0xD1, 0xEC, 0x12, 0x4D, 0xDE, 0xD5, 0xBA, 0xC6, 0x77, 0xBD, 0x06, 0xC4, + 0x5F, 0x44, 0xEA, 0x59, 0x4B, 0x5D, 0x3B, 0x8A, 0x3D, 0x0F, 0xD4, 0x9B, 0x1B, + 0x80, 0x30, 0x1D, 0x30, 0xFA, 0x8F, 0x00, 0x3F, 0xDE, 0xB0, 0x6F, 0xAD, 0x6F, + 0x6A, 0xDD, 0x6E, 0x2F, 0x6E, 0xCB, 0x3C, 0xD1, 0x83, 0x06, 0x7B, 0x0F, 0xFD, + 0xFD, 0x4A, 0xEF, 0xBC, 0x73, 0x77, 0x3B, 0x8F, 0x34, 0xA1, 0xBA, 0xEC, 0x39, + 0x80, 0x33, 0x21, 0xA4, 0x01, 0x55, 0xD7, 0xD4, 0xF4, 0xC6, 0xDA, 0x27, 0x4E, + 0x54, 0x1C, 0x2B, 0xEC, 0x37, 0xDE, 0xC3, 0x4C, 0xC9, 0x5A, 0x3D, 0x34, 0x0E, + 0xD8, 0x1C, 0x0E, 0xA2, 0x34, 0xE8, 0xC1, 0xD0, 0xA4, 0x51, 0xD5, 0x88, 0x8B, + 0xB7, 0xC6, 0xA3, 0x96, 0x40, 0x49, 0xB7, 0xBC, 0xE0, 0x7F, 0x55, 0x3F, 0xEF, + 0x6F, 0x6E, 0x92, 0x9D, 0x34, 0xFE, 0x3C, 0x5F, 0x04, 0xA5, 0x6A, 0xFF, 0x30, + 0x08, 0xC9, 0xEA, 0xF5, 0x52, 0x2B, 0xFE, 0x57, 0xFA, 0x8E, 0xC7, 0xE8, 0x4D, + 0x37, 0xAB, 0x03, 0xFA, 0x23, 0xBF, 0x46, 0x94, 0xFF, 0xC1, 0x16, 0xE0, 0xB9, + 0x14, 0x2C, 0x9E, 0x27, 0xEC, 0x98, 0x69, 0x14, 0x92, 0xF1, 0x60, 0x5C, 0x34, + 0x4D, 0xA0, 0x1F, 0xDF, 0xFD, 0x44, 0x1C, 0x7B, 0xD3, 0x80, 0x70, 0x42, 0x02, + 0x30, 0x84, 0x5B, 0xE5, 0x59, 0xB7, 0xF3, 0x80, 0xFB, 0x01, 0x33, 0xA9, 0x00, + 0x37, 0x52, 0xDC, 0xDA, 0xA7, 0x11, 0x85, 0xB7, 0x6E, 0x70, 0xE4, 0xDA, 0x96, + 0xBA, 0x84, 0x5B, 0x81, 0x43, 0x93, 0xF3, 0xD1, 0xEA, 0xB1, 0xDD, 0xB8, 0x1F, + 0xA5, 0xCC, 0xEA, 0x50, 0x66, 0x69, 0xA9, 0x8D, 0x8C, 0xA7, 0xA2, 0xF3, 0x38, + 0x26, 0x43, 0x5E, 0x3F, 0x01, 0xBE, 0x1C, 0x0F, 0x20, 0x7F, 0x75, 0xA8, 0x20, + 0x80, 0xC4, 0xC3, 0x5C, 0x8B, 0x0D, 0xD4, 0x60, 0x5E, 0xA3, 0x9E, 0xD0, 0xB4, + 0x4B, 0x4F, 0xE6, 0x13, 0x85, 0x60, 0x42, 0x96, 0xED, 0xAA, 0xDB, 0xE9, 0x99, + 0xE3, 0x07, 0x0E, 0x61, 0xB3, 0x07, 0xE3, 0xB1, 0xFA, 0xC0, 0x9B, 0xAD, 0xF6, + 0xE0, 0x26, 0x33, 0xEA, 0xEA, 0x23, 0xCD, 0x1E, 0x9D, 0xE1, 0x87, 0x4B, 0x74, + 0x97, 0x08, 0x3E, 0xA1, 0x28, 0xEA, 0xB3, 0x19, 0x67, 0x8B, 0x76, 0x9A, 0xA3, + 0xF6, 0xB9, 0xCF, 0x80, 0x65, 0x97, 0xAE, 0xF4, 0x83, 0x6B, 0xF4, 0x43, 0x20, + 0xF9, 0x0B, 0xFC, 0x9B, 0xD2, 0x4D, 0x4D, 0xA6, 0xB9, 0xA3, 0x02, 0x55, 0x79, + 0x18, 0x36, 0x19, 0x5F, 0xC9, 0xEA, 0x5A, 0x76, 0x40, 0xB9, 0xBA, 0x0E, 0x9A, + 0x44, 0xDF, 0x7C, 0xF8, 0x65, 0x61, 0x5E, 0x81, 0xAB, 0x71, 0xA1, 0x9E, 0x29, + 0x3C, 0x59, 0xCB, 0x23, 0xA4, 0xF6, 0x60, 0x1A, 0x0D, 0x5B, 0x39, 0xAE, 0xF4, + 0x6F, 0x59, 0x16, 0x9E, 0x60, 0xD8, 0x56, 0xCF, 0xEA, 0x2C, 0x4C, 0x79, 0xD3, + 0x5D, 0x51, 0x46, 0xA0, 0x4E, 0xE9, 0xD6, 0xAB, 0x91, 0x43, 0x63, 0x44, 0xD7, + 0x70, 0xB9, 0x23, 0x98, 0x4F, 0x3D, 0x03, 0x02, 0xF6, 0x81, 0x56, 0xC1, 0x58, + 0x85, 0x07, 0xA7, 0x2D, 0x2C, 0x29, 0xCA, 0x01, 0x45, 0x31, 0x51, 0x8F, 0xD4, + 0x19, 0xA1, 0x79, 0x88, 0x5A, 0xA4, 0xF5, 0xAE, 0x2D, 0x4B, 0x63, 0x4C, 0x58, + 0xFE, 0xBF, 0xAD, 0xEE, 0xA3, 0x09, 0xF8, 0xE2, 0x89, 0xBE, 0x81, 0x0E, 0x86, + 0x3A, 0xF9, 0x5B, 0xA5, 0xD8, 0xA4, 0x00, 0x75, 0x04, 0xF2, 0x23, 0xB8, 0x39, + 0x69, 0x50, 0xB7, 0xD0, 0x34, 0x63, 0x54, 0xD8, 0x61, 0xDD, 0xA5, 0x33, 0x47, + 0x85, 0x96, 0x22, 0xD0, 0x2F, 0x9F, 0x7E, 0xF8, 0x74, 0x24, 0xEA, 0x57, 0x97, + 0x5A, 0xE0, 0x00, 0xCF, 0xC1, 0x67, 0xE1, 0x41, 0xBD, 0x94, 0xA1, 0x03, 0xD3, + 0xB4, 0x08, 0x64, 0xF2, 0x17, 0x27, 0x35, 0x37, 0x53, 0xEF, 0x46, 0xCE, 0xD8, + 0xD4, 0x09, 0x52, 0xC6, 0x1E, 0xF7, 0x28, 0xDF, 0x08, 0x0F, 0xD0, 0x6F, 0x71, + 0xA6, 0xDF, 0xE4, 0x60, 0x8E, 0xC0, 0x1E, 0x78, 0x86, 0x50, 0xB0, 0x9B, 0x84, + 0x7E, 0xE8, 0x36, 0xFA, 0x95, 0xF1, 0x12, 0x51, 0xC7, 0x18, 0x96, 0xA2, 0x29, + 0xBB, 0x70, 0x02, 0xB4, 0xF9, 0xA8, 0x3D, 0x08, 0x66, 0xA9, 0xB3, 0xFC, 0x0A, + 0x94, 0x80, 0xFD, 0x78, 0xDC, 0xAB, 0x82, 0x5A, 0xD2, 0xCD, 0xC2, 0x87, 0xC6, + 0x4B, 0x07, 0xFA, 0xD1, 0xC3, 0xD9, 0x34, 0x41, 0x85, 0xF8, 0xD0, 0xB6, 0x0A, + 0x9D, 0x00, 0x91, 0x35, 0x05, 0x88, 0xC3, 0xE3, 0x9B, 0x22, 0xD2, 0xB8, 0xFD, + 0x95, 0x3E, 0x6D, 0x5D, 0x48, 0xA3, 0x68, 0xCF, 0x02, 0x42, 0x79, 0x79, 0x8A, + 0xAA, 0x01, 0xD6, 0x09, 0x14, 0x2C, 0xF4, 0x83, 0xA3, 0x80, 0x31, 0x55, 0x46, + 0x6E, 0xC5, 0xE5, 0x2F, 0x30, 0x58, 0x81, 0xA2, 0x90, 0xBE, 0x2E, 0xA1, 0xC3, + 0x0F, 0xA6, 0xF5, 0x51, 0x00, 0x39, 0xB6, 0xF2, 0x2A, 0xA3, 0x15, 0x7D, 0x8D, + 0xF5, 0x66, 0x5C, 0xD9, 0xFC, 0xCF, 0x2F, 0xBF, 0x08, 0x27, 0xE7, 0xD0, 0x03, + 0xB8, 0xD9, 0x00, 0x13, 0x3D, 0x01, 0x6B, 0xB6, 0xA8, 0xCD, 0x5B, 0x3B, 0x3E, + 0x93, 0xBF, 0xE6, 0x2E, 0xB7, 0x4A, 0xCF, 0xB3, 0x0A, 0xCE, 0x62, 0x11, 0xD6, + 0x1F, 0x68, 0x9B, 0x1D, 0x68, 0xD1, 0x8C, 0x97, 0xBD, 0xA1, 0x07, 0x67, 0x73, + 0x87, 0xE0, 0x36, 0xDA, 0x8C, 0xD2, 0xD2, 0xBB, 0x84, 0x28, 0xA9, 0xFE, 0x52, + 0x74, 0xD6, 0xB9, 0x0F, 0x0A, 0x6A, 0x2D, 0x28, 0x35, 0x34, 0x3A, 0xD3, 0xE2, + 0xCD, 0x35, 0x06, 0x7D, 0x1B, 0x35, 0x85, 0x86, 0xD1, 0x3E, 0xF2, 0x6F, 0xA1, + 0xC4, 0x55, 0xBD, 0x00, 0xD8, 0xC3, 0x5D, 0xC2, 0x1D, 0x6B, 0x6B, 0x27, 0x5B, + 0x95, 0xF3, 0xAB, 0xB5, 0xD3, 0x37, 0xF2, 0x2C, 0x9C, 0xC7, 0x5D, 0xBD, 0xF1, + 0x68, 0x1C, 0xAD, 0xF8, 0xB5, 0xE1, 0x29, 0x72, 0x7A, 0x73, 0x62, 0x55, 0x24, + 0xB9, 0x85, 0xDF, 0x7B, 0x29, 0x7D, 0xDE, 0x08, 0xF5, 0xE4, 0x44, 0xDA, 0x1A, + 0x30, 0x74, 0xDA, 0xB4, 0x9B, 0x23, 0x9A, 0x3A, 0xC1, 0x53, 0xB2, 0xA2, 0xA3, + 0x7B, 0x1F, 0xD9, 0x56, 0xD4, 0x4F, 0x9B, 0xB2, 0x1E, 0xEE, 0xB8, 0x6A, 0x4E, + 0xB5, 0xF4, 0x5A, 0xC9, 0x18, 0x27, 0x9C, 0xDE, 0x14, 0x44, 0xED, 0xC4, 0x3C, + 0x71, 0x9F, 0x5F, 0xD9, 0x37, 0xA0, 0x78, 0x34, 0x6E, 0xBC, 0xD2, 0x7B, 0x1D, + 0xFA, 0x08, 0x39, 0x5A, 0x04, 0x73, 0x15, 0xD9, 0x0A, 0x48, 0xC1, 0x2D, 0x15, + 0x4E, 0x84, 0x30, 0x45, 0x69, 0xB3, 0xE5, 0xF6, 0xAD, 0x09, 0x1E, 0xCC, 0x5F, + 0x1F, 0x06, 0xD5, 0x58, 0xAD, 0x78, 0xD7, 0x9F, 0xE5, 0xED, 0x3B, 0x09, 0xD5, + 0xA6, 0x52, 0x6F, 0x92, 0xD3, 0x3C, 0xC6, 0x1E, 0xF2, 0x93, 0x7C, 0xD3, 0x5F, + 0x70, 0x85, 0x5D, 0xF8, 0xAA, 0x9D, 0xB7, 0x7B, 0x24, 0x5A, 0xE9, 0x0A, 0x35, + 0x2F, 0xF5, 0xD9, 0x82, 0x02, 0x8A, 0x90, 0x13, 0x5B, 0xB5, 0x67, 0x9C, 0xDD, + 0xA0, 0x4E, 0x82, 0x27, 0xDA, 0x7E, 0xE8, 0x8E, 0xCD, 0xE1, 0x56, 0x71, 0x2C, + 0xE6, 0x4E, 0x1F, 0x91, 0xCD, 0x7C, 0x6A, 0xB7, 0x78, 0xD0, 0x26, 0xF3, 0x56, + 0xA9, 0xD5, 0xA1, 0xC3, 0x3B, 0x98, 0xE9, 0x28, 0x09, 0xEF, 0x50, 0x90, 0xCD, + 0xC4, 0x8E, 0x75, 0xCC, 0xAC, 0x2D, 0xC9, 0x03, 0x6D, 0xAC, 0xFE, 0xC4, 0x88, + 0x36, 0xD1, 0x3F, 0xBB, 0x1C, 0x7D, 0xB3, 0x14, 0x61, 0x2C, 0xB7, 0x54, 0x4B, + 0xDB, 0x64, 0xB6, 0x57, 0x14, 0x16, 0x8E, 0x1E, 0x6C, 0x64, 0xBB, 0x8B, 0x48, + 0x5D, 0x96, 0x9D, 0xDC, 0x80, 0xA7, 0xF7, 0x54, 0xC7, 0x46, 0x38, 0x3E, 0x44, + 0xDE, 0x7E, 0x92, 0x8D, 0x07, 0xF6, 0x07, 0x37, 0x4E, 0x16, 0x10, 0xB4, 0x7D, + 0x88, 0x66, 0x7F, 0xBB, 0xFF, 0xEA, 0x00, 0xF3, 0xFF, 0x97, 0x2C, 0xB5, 0xBE, + 0x35, 0x4B, 0x5C, 0x36, 0xEC, 0x4C, 0xBD, 0x2B, 0x7D, 0xBF, 0x46, 0xE2, 0x9C, + 0x0E, 0x8A, 0xA3, 0xEC, 0xB1, 0x0E, 0x9A, 0xDA, 0x9A, 0x9B, 0x28, 0x92, 0x10, + 0x53, 0x57, 0xEA, 0xEC, 0xA2, 0x32, 0x32, 0x20, 0x1D, 0x97, 0x5C, 0xB6, 0x84, + 0xA9, 0x93, 0x8D, 0x95, 0x11, 0xA3, 0x24, 0xA3, 0x2D, 0xC6, 0x4A, 0xEF, 0xAA, + 0x1D, 0x85, 0x2B, 0x7D, 0x28, 0xBE, 0x53, 0xCE, 0x10, 0x1F, 0xAE, 0x0E, 0x41, + 0x6C, 0x4B, 0x79, 0x12, 0xFB, 0xF7, 0x54, 0xA3, 0x96, 0x54, 0x83, 0x20, 0x96, + 0x8F, 0x28, 0xA9, 0x3F, 0x8B, 0x3D, 0xBA, 0x77, 0xDC, 0x24, 0xE1, 0xD4, 0x49, + 0x40, 0xD8, 0x78, 0x31, 0x85, 0x43, 0xF6, 0xFE, 0x5C, 0xA6, 0x8F, 0x90, 0x09, + 0xB0, 0xE7, 0xC4, 0x95, 0xB2, 0x55, 0x49, 0x97, 0x8F, 0x1C, 0x78, 0x30, 0x20, + 0xA0, 0xB4, 0xEF, 0x73, 0x56, 0x59, 0x82, 0xFD, 0xCE, 0xBA, 0x6A, 0x8F, 0x2C, + 0x8B, 0x15, 0xFD, 0xA1, 0x85, 0xA8, 0x5C, 0x0F, 0x11, 0xA5, 0x9D, 0xC2, 0x46, + 0xC6, 0x9C, 0xC9, 0x40, 0x0B, 0x58, 0x6A, 0x1C, 0x7A, 0x23, 0xF9, 0xE0, 0x95, + 0x05, 0x13, 0x58, 0x72, 0xE8, 0x9F, 0x30, 0xAC, 0xCD, 0x26, 0xD4, 0x66, 0x13, + 0xDF, 0x1E, 0x7B, 0x4F, 0x9C, 0xBE, 0x38, 0x79, 0x75, 0x92, 0xA4, 0xDA, 0x26, + 0x44, 0x55, 0x17, 0xA3, 0xE5, 0x62, 0xDA, 0xEB, 0x86, 0xEA, 0x68, 0xC7, 0xAB, + 0xFD, 0x2D, 0x43, 0x59, 0x51, 0xC0, 0x75, 0x64, 0x91, 0x01, 0x29, 0x33, 0x28, + 0xF3, 0x04, 0x83, 0x80, 0x75, 0x37, 0x75, 0x0C, 0x03, 0x7B, 0x0A, 0xAB, 0x8E, + 0x60, 0x62, 0x8B, 0x4C, 0xAF, 0x2D, 0xA3, 0x2F, 0xFE, 0xAB, 0x45, 0xCF, 0xDA, + 0xAB, 0xFA, 0xFA, 0x30, 0x3D, 0xE8, 0xA1, 0x96, 0xA5, 0x7B, 0xE2, 0x2A, 0xD0, + 0xAF, 0x59, 0xF7, 0xD0, 0x32, 0x57, 0x19, 0xBD, 0xCA, 0x9F, 0xD5, 0x1A, 0xC7, + 0xAA, 0x65, 0x4A, 0x38, 0xB2, 0x70, 0x33, 0xB7, 0x75, 0xD2, 0xCD, 0xD1, 0xF0, + 0xA8, 0x87, 0x59, 0x20, 0xA5, 0x57, 0x55, 0xB1, 0xB2, 0xC9, 0x4D, 0x97, 0x34, + 0x41, 0xF3, 0xF0, 0x30, 0xA1, 0x2C, 0x1C, 0x49, 0x3E, 0x89, 0x7D, 0x12, 0xE2, + 0xC3, 0x04, 0xC3, 0x92, 0xC0, 0xF6, 0x39, 0x10, 0x80, 0x81, 0x8F, 0x08, 0xB4, + 0xF8, 0xB9, 0x13, 0x4E, 0x2C, 0xAE, 0xB3, 0x71, 0x82, 0x63, 0x98, 0xAB, 0x5C, + 0x1C, 0x10, 0xEA, 0x66, 0xF9, 0x02, 0x3A, 0x82, 0x61, 0xD0, 0xD4, 0xAE, 0x43, + 0xD4, 0x01, 0x3E, 0x9D, 0x04, 0x14, 0xF6, 0x60, 0xD8, 0xA7, 0xD6, 0xB8, 0x53, + 0xC8, 0xDA, 0x80, 0x93, 0xA0, 0x02, 0xDD, 0xCC, 0xE2, 0xF2, 0xBB, 0xFB, 0xE0, + 0x27, 0xD7, 0x34, 0x9A, 0x71, 0x49, 0xB5, 0x4F, 0x42, 0x1F, 0xB2, 0x9D, 0x6D, + 0xAA, 0x9D, 0xD3, 0x50, 0xB5, 0x8F, 0x6A, 0x4B, 0xDF, 0x1F, 0xD5, 0x27, 0x8F, + 0x3B, 0x27, 0xCF, 0x2F, 0x8C, 0xF8, 0x9D, 0x4C, 0x52, 0xBC, 0x32, 0x0F, 0x73, + 0xD5, 0x51, 0x8E, 0x36, 0x7E, 0xAD, 0x09, 0xF0, 0x94, 0x83, 0x5F, 0x36, 0xFD, + 0x7C, 0x03, 0xED, 0xF1, 0x5E, 0x4B, 0xF7, 0xAA, 0x55, 0x5C, 0x4A, 0x14, 0x59, + 0x85, 0x38, 0x2D, 0x8C, 0xDF, 0xEC, 0x65, 0x1B, 0xB8, 0x76, 0x57, 0x96, 0x3C, + 0x86, 0xED, 0xF2, 0x7F, 0x2D, 0x28, 0x48, 0xDA, 0x49, 0x7F, 0xF7, 0x54, 0x2B, + 0xD5, 0x39, 0xD5, 0x57, 0x0A, 0x75, 0x7A, 0x3E, 0x5E, 0x5D, 0xBA, 0x4A, 0x15, + 0xFA, 0xB8, 0x31, 0x80, 0x71, 0x2C, 0xCA, 0xC4, 0x51, 0x10, 0x16, 0x5D, 0x39, + 0xEC, 0x9D, 0x07, 0xB6, 0x6A, 0x89, 0x9F, 0x9B, 0x5B, 0x6F, 0x03, 0xB0, 0x92, + 0x01, 0x38, 0x6B, 0x48, 0x99, 0x0A, 0x8F, 0x13, 0xC1, 0xA6, 0x01, 0xEA, 0xBF, + 0x6F, 0x86, 0x43, 0x51, 0xB6, 0x11, 0x00, 0x00 +}; int compress_test(void) { int ret = 0; word32 dSz = sizeof(sample_text); word32 cSz = (dSz + (word32)(dSz * 0.001) + 12); - byte *c = NULL; - byte *d = NULL; + byte *c; + byte *d; - c = calloc(cSz, sizeof(byte)); - d = calloc(dSz, sizeof(byte)); - - if (c == NULL || d == NULL) - ret = -300; - - if (ret == 0 && (ret = wc_Compress(c, cSz, sample_text, dSz, 0)) < 0) - ret = -301; - - if (ret > 0) { - cSz = (word32)ret; - ret = 0; + 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(-11700, exit); } - if (ret == 0 && wc_DeCompress(d, dSz, c, cSz) != (int)dSz) - ret = -302; + /* follow calloc and initialize to 0 */ + XMEMSET(c, 0, cSz); + XMEMSET(d, 0, dSz); - if (ret == 0 && memcmp(d, sample_text, dSz)) - ret = -303; + if ((ret = wc_Compress(c, cSz, sample_text, dSz, 0)) < 0) { + ERROR_OUT(-11701, exit); + } + cSz = (word32)ret; - if (c) free(c); - if (d) free(d); + if ((ret = wc_DeCompress(d, dSz, c, cSz)) != (int)dSz) { + ERROR_OUT(-11702, exit); + } + + if (XMEMCMP(d, sample_text, dSz) != 0) { + ERROR_OUT(-11703, exit); + } + + /* GZIP tests */ + cSz = (dSz + (word32)(dSz * 0.001) + 12); /* reset cSz */ + XMEMSET(c, 0, cSz); + XMEMSET(d, 0, dSz); + + ret = wc_Compress_ex(c, cSz, sample_text, dSz, 0, LIBZ_WINBITS_GZIP); + if (ret < 0) { + ERROR_OUT(-11704, exit); + } + cSz = (word32)ret; + + ret = wc_DeCompress_ex(d, dSz, c, cSz, LIBZ_WINBITS_GZIP); + if (ret < 0) { + ERROR_OUT(-11705, exit); + } + + if (XMEMCMP(d, sample_text, dSz) != 0) { + ERROR_OUT(-11706, exit); + } + + /* Try with gzip generated output */ + XMEMSET(d, 0, dSz); + ret = wc_DeCompress_ex(d, dSz, sample_text_gz, sizeof(sample_text_gz), + LIBZ_WINBITS_GZIP); + if (ret < 0) { + ERROR_OUT(-11707, exit); + } + dSz = (word32)ret; + + if (XMEMCMP(d, sample_text, dSz) != 0) { + ERROR_OUT(-11708, exit); + } + + ret = 0; /* success */ + +exit: + if (c) XFREE(c, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (d) XFREE(d, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return ret; } @@ -5917,323 +23711,4857 @@ int compress_test(void) #ifdef HAVE_PKCS7 -int pkcs7enveloped_test(void) +/* External Debugging/Testing Note: + * + * PKCS#7 test functions can output generated PKCS#7/CMS bundles for + * additional testing. To dump bundles to files DER encoded files, please + * define: + * + * #define PKCS7_OUTPUT_TEST_BUNDLES + */ + + +/* Loads certs and keys for use with PKCS7 tests, from either files + * or buffers. + * + * rsaClientCertBuf - output buffer for RSA client cert + * rsaClientCertBufSz - IN/OUT size of output buffer, size of RSA client cert + * rsaClientPrivKeyBuf - output buffer for RSA client private key + * rsaClientPrivKeyBufSz - IN/OUT size of output buffer, size of RSA client key + * + * rsaServerCertBuf - output buffer for RSA server cert + * rsaServerCertBufSz - IN/OUT size of output buffer, size of RSA server cert + * rsaServerPrivKeyBuf - output buffer for RSA server private key + * rsaServerPrivKeyBufSz - IN/OUT size of output buffer, size of RSA server key + * + * rsaCaCertBuf - output buffer for RSA CA cert + * rsaCaCertBufSz - IN/OUT size of output buffer, size of RSA ca cert + * rsaCaPrivKeyBuf - output buffer for RSA CA private key + * rsaCaPrivKeyBufSz - IN/OUT size of output buffer, size of RSA CA key + * + * eccClientCertBuf - output buffer for ECC cert + * eccClientCertBufSz - IN/OUT size of output buffer, size of ECC cert + * eccClientPrivKeyBuf - output buffer for ECC private key + * eccClientPrivKeyBufSz - 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* rsaClientCertBuf, word32* rsaClientCertBufSz, + byte* rsaClientPrivKeyBuf, word32* rsaClientPrivKeyBufSz, + byte* rsaServerCertBuf, word32* rsaServerCertBufSz, + byte* rsaServerPrivKeyBuf, word32* rsaServerPrivKeyBufSz, + byte* rsaCaCertBuf, word32* rsaCaCertBufSz, + byte* rsaCaPrivKeyBuf, word32* rsaCaPrivKeyBufSz, + byte* eccClientCertBuf, word32* eccClientCertBufSz, + byte* eccClientPrivKeyBuf, word32* eccClientPrivKeyBufSz) { - int ret = 0; +#ifndef NO_FILESYSTEM + XFILE certFile; + XFILE keyFile; - int cipher = DES3b; + (void)certFile; + (void)keyFile; +#endif + +#ifndef NO_RSA + if (rsaClientCertBuf == NULL || rsaClientCertBufSz == NULL || + rsaClientPrivKeyBuf == NULL || rsaClientPrivKeyBufSz == NULL) + return BAD_FUNC_ARG; +#endif + +#ifdef HAVE_ECC + if (eccClientCertBuf == NULL || eccClientCertBufSz == NULL || + eccClientPrivKeyBuf == NULL || eccClientPrivKeyBufSz == NULL) + return BAD_FUNC_ARG; +#endif + +/* RSA */ +#ifndef NO_RSA + +#ifdef USE_CERT_BUFFERS_1024 + if (*rsaClientCertBufSz < (word32)sizeof_client_cert_der_1024) + return -11709; + + XMEMCPY(rsaClientCertBuf, client_cert_der_1024, + sizeof_client_cert_der_1024); + *rsaClientCertBufSz = sizeof_client_cert_der_1024; + + if (rsaServerCertBuf != NULL) { + if (*rsaServerCertBufSz < (word32)sizeof_server_cert_der_1024) + return -11710; + + XMEMCPY(rsaServerCertBuf, server_cert_der_1024, + sizeof_server_cert_der_1024); + *rsaServerCertBufSz = sizeof_server_cert_der_1024; + } + + if (rsaCaCertBuf != NULL) { + if (*rsaCaCertBufSz < (word32)sizeof_ca_cert_der_1024) + return -11711; + + XMEMCPY(rsaCaCertBuf, ca_cert_der_1024, sizeof_ca_cert_der_1024); + *rsaCaCertBufSz = sizeof_ca_cert_der_1024; + } +#elif defined(USE_CERT_BUFFERS_2048) + if (*rsaClientCertBufSz < (word32)sizeof_client_cert_der_2048) + return -11712; + + XMEMCPY(rsaClientCertBuf, client_cert_der_2048, + sizeof_client_cert_der_2048); + *rsaClientCertBufSz = sizeof_client_cert_der_2048; + + if (rsaServerCertBuf != NULL) { + if (*rsaServerCertBufSz < (word32)sizeof_server_cert_der_2048) + return -11713; + + XMEMCPY(rsaServerCertBuf, server_cert_der_2048, + sizeof_server_cert_der_2048); + *rsaServerCertBufSz = sizeof_server_cert_der_2048; + } + + if (rsaCaCertBuf != NULL) { + if (*rsaCaCertBufSz < (word32)sizeof_ca_cert_der_2048) + return -11714; + + XMEMCPY(rsaCaCertBuf, ca_cert_der_2048, sizeof_ca_cert_der_2048); + *rsaCaCertBufSz = sizeof_ca_cert_der_2048; + } +#else + certFile = XFOPEN(clientCert, "rb"); + if (!certFile) + return -11715; + + *rsaClientCertBufSz = (word32)XFREAD(rsaClientCertBuf, 1, + *rsaClientCertBufSz, certFile); + XFCLOSE(certFile); + + if (rsaServerCertBuf != NULL) { + certFile = XFOPEN(rsaServerCertDerFile, "rb"); + if (!certFile) + return -11716; + + *rsaServerCertBufSz = (word32)XFREAD(rsaServerCertBuf, 1, + *rsaServerCertBufSz, certFile); + XFCLOSE(certFile); + } + + if (rsaCaCertBuf != NULL) { + certFile = XFOPEN(rsaCaCertDerFile, "rb"); + if (!certFile) + return -11717; + + *rsaCaCertBufSz = (word32)XFREAD(rsaCaCertBuf, 1, *rsaCaCertBufSz, + certFile); + XFCLOSE(certFile); + } +#endif + +#ifdef USE_CERT_BUFFERS_1024 + if (*rsaClientPrivKeyBufSz < (word32)sizeof_client_key_der_1024) + return -11718; + + XMEMCPY(rsaClientPrivKeyBuf, client_key_der_1024, + sizeof_client_key_der_1024); + *rsaClientPrivKeyBufSz = sizeof_client_key_der_1024; + + if (rsaServerPrivKeyBuf != NULL) { + if (*rsaServerPrivKeyBufSz < (word32)sizeof_server_key_der_1024) + return -11719; + + XMEMCPY(rsaServerPrivKeyBuf, server_key_der_1024, + sizeof_server_key_der_1024); + *rsaServerPrivKeyBufSz = sizeof_server_key_der_1024; + } + + if (rsaCaPrivKeyBuf != NULL) { + if (*rsaCaPrivKeyBufSz < (word32)sizeof_ca_key_der_1024) + return -11720; + + XMEMCPY(rsaCaPrivKeyBuf, ca_key_der_1024, sizeof_ca_key_der_1024); + *rsaCaPrivKeyBufSz = sizeof_ca_key_der_1024; + } +#elif defined(USE_CERT_BUFFERS_2048) + if (*rsaClientPrivKeyBufSz < (word32)sizeof_client_key_der_2048) + return -11721; + + XMEMCPY(rsaClientPrivKeyBuf, client_key_der_2048, + sizeof_client_key_der_2048); + *rsaClientPrivKeyBufSz = sizeof_client_key_der_2048; + + if (rsaServerPrivKeyBuf != NULL) { + if (*rsaServerPrivKeyBufSz < (word32)sizeof_server_key_der_2048) + return -11722; + + XMEMCPY(rsaServerPrivKeyBuf, server_key_der_2048, + sizeof_server_key_der_2048); + *rsaServerPrivKeyBufSz = sizeof_server_key_der_2048; + } + + if (rsaCaPrivKeyBuf != NULL) { + if (*rsaCaPrivKeyBufSz < (word32)sizeof_ca_key_der_2048) + return -11723; + + XMEMCPY(rsaCaPrivKeyBuf, ca_key_der_2048, sizeof_ca_key_der_2048); + *rsaCaPrivKeyBufSz = sizeof_ca_key_der_2048; + } +#else + keyFile = XFOPEN(clientKey, "rb"); + if (!keyFile) + return -11724; + + *rsaClientPrivKeyBufSz = (word32)XFREAD(rsaClientPrivKeyBuf, 1, + *rsaClientPrivKeyBufSz, keyFile); + XFCLOSE(keyFile); + + if (rsaServerPrivKeyBuf != NULL) { + keyFile = XFOPEN(rsaServerKeyDerFile, "rb"); + if (!keyFile) + return -11725; + + *rsaServerPrivKeyBufSz = (word32)XFREAD(rsaServerPrivKeyBuf, 1, + *rsaServerPrivKeyBufSz, keyFile); + XFCLOSE(keyFile); + } + + if (rsaCaPrivKeyBuf != NULL) { + keyFile = XFOPEN(rsaCaKeyFile, "rb"); + if (!keyFile) + return -11726; + + *rsaCaPrivKeyBufSz = (word32)XFREAD(rsaCaPrivKeyBuf, 1, + *rsaCaPrivKeyBufSz, keyFile); + XFCLOSE(keyFile); + } +#endif /* USE_CERT_BUFFERS */ + +#endif /* NO_RSA */ + +/* ECC */ +#ifdef HAVE_ECC + +#ifdef USE_CERT_BUFFERS_256 + if (*eccClientCertBufSz < (word32)sizeof_cliecc_cert_der_256) + return -11727; + + XMEMCPY(eccClientCertBuf, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); + *eccClientCertBufSz = sizeof_cliecc_cert_der_256; +#else + certFile = XFOPEN(eccClientCert, "rb"); + if (!certFile) + return -11728; + + *eccClientCertBufSz = (word32)XFREAD(eccClientCertBuf, 1, + *eccClientCertBufSz, certFile); + XFCLOSE(certFile); +#endif /* USE_CERT_BUFFERS_256 */ + +#ifdef USE_CERT_BUFFERS_256 + if (*eccClientPrivKeyBufSz < (word32)sizeof_ecc_clikey_der_256) + return -11729; + + XMEMCPY(eccClientPrivKeyBuf, ecc_clikey_der_256, sizeof_ecc_clikey_der_256); + *eccClientPrivKeyBufSz = sizeof_ecc_clikey_der_256; +#else + keyFile = XFOPEN(eccClientKey, "rb"); + if (!keyFile) + return -11730; + + *eccClientPrivKeyBufSz = (word32)XFREAD(eccClientPrivKeyBuf, 1, + *eccClientPrivKeyBufSz, keyFile); + XFCLOSE(keyFile); +#endif /* USE_CERT_BUFFERS_256 */ +#endif /* HAVE_ECC */ + +#ifdef NO_RSA + (void)rsaClientCertBuf; + (void)rsaClientCertBufSz; + (void)rsaClientPrivKeyBuf; + (void)rsaClientPrivKeyBufSz; + (void)rsaServerCertBuf; + (void)rsaServerCertBufSz; + (void)rsaServerPrivKeyBuf; + (void)rsaServerPrivKeyBufSz; + (void)rsaCaCertBuf; + (void)rsaCaCertBufSz; + (void)rsaCaPrivKeyBuf; + (void)rsaCaPrivKeyBufSz; +#endif +#ifndef HAVE_ECC + (void)eccClientCertBuf; + (void)eccClientCertBufSz; + (void)eccClientPrivKeyBuf; + (void)eccClientPrivKeyBufSz; +#endif +#ifndef NO_FILESYSTEM + (void)certFile; + (void)keyFile; +#endif + return 0; +} + + +typedef struct { + const byte* content; + word32 contentSz; + int contentOID; + int encryptOID; + int keyWrapOID; + int keyAgreeOID; + byte* cert; + size_t certSz; + byte* privateKey; + word32 privateKeySz; + byte* optionalUkm; + word32 optionalUkmSz; + int ktriOptions; /* KTRI options flags */ + int kariOptions; /* KARI options flags */ + + /* KEKRI specific */ + byte* secretKey; /* key, only for kekri RecipientInfo types */ + word32 secretKeySz; /* size of secretKey, bytes */ + byte* secretKeyId; /* key identifier */ + word32 secretKeyIdSz; /* size of key identifier, bytes */ + void* timePtr; /* time_t pointer */ + byte* otherAttrOID; /* OPTIONAL, other attribute OID */ + word32 otherAttrOIDSz; /* size of otherAttrOID, bytes */ + byte* otherAttr; /* OPTIONAL, other attribute, ASN.1 encoded */ + word32 otherAttrSz; /* size of otherAttr, bytes */ + int kekriOptions; /* KEKRI options flags */ + + /* PWRI specific */ + char* password; + word32 passwordSz; + byte* salt; + word32 saltSz; + int kdfOID; + int hashOID; + int kdfIterations; + int pwriOptions; /* PWRI options flags */ + + /* ORI specific */ + int isOri; + int oriOptions; /* ORI options flags */ + + const char* outFileName; +} pkcs7EnvelopedVector; + + +static const byte asnDataOid[] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 +}; + +/* ORI encrypt callback, responsible for encrypting content-encryption key (CEK) + * and giving wolfCrypt the value for oriOID and oriValue to place in + * OtherRecipientInfo. + * + * Returns 0 on success, negative upon error. */ +static int myOriEncryptCb(PKCS7* pkcs7, byte* cek, word32 cekSz, byte* oriType, + word32* oriTypeSz, byte* oriValue, word32* oriValueSz, + void* ctx) +{ + int i; + + /* make sure buffers are large enough */ + if ((*oriValueSz < (2 + cekSz)) || (*oriTypeSz < sizeof(oriType))) + return -11731; + + /* our simple encryption algorithm will be take the bitwise complement */ + oriValue[0] = 0x04; /*ASN OCTET STRING */ + oriValue[1] = (byte)cekSz; /* length */ + for (i = 0; i < (int)cekSz; i++) { + oriValue[2 + i] = ~cek[i]; + } + *oriValueSz = 2 + cekSz; + + /* set oriType to ASN.1 encoded data OID */ + XMEMCPY(oriType, asnDataOid, sizeof(asnDataOid)); + *oriTypeSz = sizeof(asnDataOid); + + (void)pkcs7; + (void)ctx; + + return 0; +} + + +/* ORI decrypt callback, responsible for providing a decrypted content + * encryption key (CEK) placed into decryptedKey and size placed into + * decryptedKeySz. oriOID and oriValue are given to the callback to help + * in decrypting the encrypted CEK. + * + * Returns 0 on success, negative upon error. */ +static int myOriDecryptCb(PKCS7* pkcs7, byte* oriType, word32 oriTypeSz, + byte* oriValue, word32 oriValueSz, byte* decryptedKey, + word32* decryptedKeySz, void* ctx) +{ + int i; + + /* make sure oriType matches what we expect */ + if (oriTypeSz != sizeof(asnDataOid)) + return -11732; + + if (XMEMCMP(oriType, asnDataOid, sizeof(asnDataOid)) != 0) + return -11733; + + /* make sure decrypted buffer is large enough */ + if (*decryptedKeySz < oriValueSz) + return -11734; + + /* decrypt encrypted CEK using simple bitwise complement, + only for example */ + for (i = 0; i < (int)oriValueSz - 2; i++) { + decryptedKey[i] = ~oriValue[2 + i]; + } + + *decryptedKeySz = oriValueSz - 2; + + (void)pkcs7; + (void)ctx; + + return 0; +} + + +#ifndef NO_AES +/* returns 0 on success */ +static int myDecryptionFunc(PKCS7* pkcs7, int encryptOID, byte* iv, int ivSz, + byte* aad, word32 aadSz, byte* authTag, word32 authTagSz, + byte* in, int inSz, byte* out, void* usrCtx) +{ + int keyId = -1, ret, keySz; + word32 keyIdSz = 8; + const byte* key; + byte keyIdRaw[8]; + Aes aes; + + /* looking for KEY ID + * fwDecryptKeyID OID "1.2.840.113549.1.9.16.2.37 + */ + const unsigned char OID[] = { + /* 0x06, 0x0B do not pass in tag and length */ + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x02, 0x25 + }; + + const byte defKey[] = { + 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 + }; + + const byte altKey[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 + }; + + /* test user context passed in */ + if (usrCtx == NULL || *(int*)usrCtx != 1) { + return -11735; + } + + /* if needing to find keyIdSz can call with NULL */ + ret = wc_PKCS7_GetAttributeValue(pkcs7, OID, sizeof(OID), NULL, + &keyIdSz); + if (ret != LENGTH_ONLY_E) { + printf("Unexpected error %d when getting keyIdSz\n", ret); + printf("Possibly no KEY ID attribute set\n"); + return -11736; + } + else { + XMEMSET(keyIdRaw, 0, sizeof(keyIdRaw)); + ret = wc_PKCS7_GetAttributeValue(pkcs7, OID, sizeof(OID), keyIdRaw, + &keyIdSz); + if (ret < 0) { + return ret; + } + + if (keyIdSz < 3) { + printf("keyIdSz is smaller than expected\n"); + return -11737; + } + if (keyIdSz > 2 + sizeof(int)) { + printf("example case was only expecting a keyId of int size\n"); + return -11738; + } + + /* keyIdRaw[0] OCTET TAG */ + /* keyIdRaw[1] Length */ +#ifdef BIG_ENDIAN_ORDER + if (keyIdRaw[1] == 0x01) { + keyId = 1; + } +#else + keyId = *(int*)(keyIdRaw + 2); +#endif + } + + + /* Use keyID here if found to select key and decrypt in HSM or in this + * example just select key and do software decryption */ + if (keyId == 1) { + key = altKey; + keySz = sizeof(altKey); + } + else { + key = defKey; + keySz = sizeof(defKey); + } + + switch (encryptOID) { + case AES256CBCb: + if ((keySz != 32 ) || (ivSz != AES_BLOCK_SIZE)) + return BAD_FUNC_ARG; + break; + + case AES128CBCb: + if ((keySz != 16 ) || (ivSz != AES_BLOCK_SIZE)) + return BAD_FUNC_ARG; + break; + + default: + printf("Unsupported content cipher type for example"); + return ALGO_ID_E; + }; + + ret = wc_AesInit(&aes, HEAP_HINT, 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); + } + + (void)aad; + (void)aadSz; + (void)authTag; + (void)authTagSz; + return ret; +} +#endif /* NO_AES */ + + +static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, + byte* rsaPrivKey, word32 rsaPrivKeySz, + byte* eccCert, word32 eccCertSz, + byte* eccPrivKey, word32 eccPrivKeySz) +{ + int ret, testSz, i; int envelopedSz, decodedSz; - PKCS7 pkcs7; - byte* cert; - byte* privKey; - byte enveloped[2048]; - byte decoded[2048]; - size_t certSz; - size_t privKeySz; - FILE* certFile; - FILE* keyFile; - FILE* pkcs7File; - const char* pkcs7OutFile = "pkcs7envelopedData.der"; + byte enveloped[2048]; + byte decoded[2048]; + PKCS7* pkcs7; +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + XFILE pkcs7File; +#endif const byte data[] = { /* Hello World */ 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, 0x72,0x6c,0x64 }; - /* read client cert and key in DER format */ - cert = (byte*)malloc(FOURK_BUF); - if (cert == NULL) - return -201; +#if !defined(NO_AES) && defined(WOLFSSL_AES_256) && defined(HAVE_ECC) && \ + defined(WOLFSSL_SHA512) + byte optionalUkm[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + }; +#endif /* NO_AES */ - privKey = (byte*)malloc(FOURK_BUF); - if (privKey == NULL) { - free(cert); - return -202; +#if !defined(NO_AES) && !defined(NO_SHA) && defined(WOLFSSL_AES_128) + /* encryption key for kekri recipient types */ + byte secretKey[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + }; + + /* encryption key identifier */ + byte secretKeyId[] = { + 0x02,0x02,0x03,0x04 + }; +#endif + +#if !defined(NO_PWDBASED) && !defined(NO_AES) && \ + !defined(NO_SHA) && defined(WOLFSSL_AES_128) + + char password[] = "password"; + + byte salt[] = { + 0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12 + }; +#endif + + const pkcs7EnvelopedVector testVectors[] = + { + /* 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, 0, 0, NULL, 0, NULL, 0, NULL, NULL, + 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, + "pkcs7envelopedDataDES3.der"}, + #endif + + #ifndef NO_AES + #ifdef WOLFSSL_AES_128 + {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, + 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES128CBC.der"}, + #endif + #ifdef WOLFSSL_AES_192 + {data, (word32)sizeof(data), DATA, AES192CBCb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, + 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES192CBC.der"}, + #endif + #ifdef WOLFSSL_AES_256 + {data, (word32)sizeof(data), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, + 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES256CBC.der"}, + + /* explicitly using SKID for SubjectKeyIdentifier */ + {data, (word32)sizeof(data), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, CMS_SKID, 0, NULL, 0, NULL, 0, NULL, + NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES256CBC_SKID.der"}, + + /* explicitly using IssuerAndSerialNumber for SubjectKeyIdentifier */ + {data, (word32)sizeof(data), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, CMS_ISSUER_AND_SERIAL_NUMBER, 0, + NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, + 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_IANDS.der"}, + #endif + #endif /* NO_AES */ +#endif + + /* key agreement key encryption technique*/ +#ifdef HAVE_ECC + #ifndef NO_AES + #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) + {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, + dhSinglePass_stdDH_sha1kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, + 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der"}, + #endif + + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_256) + {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, + 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der"}, + #endif /* NO_SHA256 && WOLFSSL_AES_256 */ + + #if defined(WOLFSSL_SHA512) && defined(WOLFSSL_AES_256) + {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, + dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, + 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der"}, + + /* with optional user keying material (ukm) */ + {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, + dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, optionalUkm, sizeof(optionalUkm), 0, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der"}, + #endif /* WOLFSSL_SHA512 && WOLFSSL_AES_256 */ + #endif /* NO_AES */ +#endif + + /* kekri (KEKRecipientInfo) recipient types */ +#ifndef NO_AES + #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) + {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, 0, + NULL, 0, NULL, 0, NULL, 0, 0, 0, secretKey, sizeof(secretKey), + secretKeyId, sizeof(secretKeyId), NULL, NULL, 0, NULL, 0, + 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES128CBC_KEKRI.der"}, + #endif +#endif + + /* pwri (PasswordRecipientInfo) recipient types */ +#if !defined(NO_PWDBASED) && !defined(NO_AES) + #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) + {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, + NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, password, + (word32)XSTRLEN(password), salt, sizeof(salt), PBKDF2_OID, WC_SHA, 5, + 0, 0, 0, "pkcs7envelopedDataAES128CBC_PWRI.der"}, + #endif +#endif + +#if !defined(NO_AES) && !defined(NO_AES_128) + /* ori (OtherRecipientInfo) recipient types */ + {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, NULL, 0, NULL, 0, + NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, + NULL, 0, 0, 0, 0, 0, 1, 0, "pkcs7envelopedDataAES128CBC_ORI.der"}, +#endif + }; + + testSz = sizeof(testVectors) / sizeof(pkcs7EnvelopedVector); + + for (i = 0; i < testSz; i++) { + pkcs7 = wc_PKCS7_New(HEAP_HINT, + #ifdef WOLFSSL_ASYNC_CRYPT + INVALID_DEVID /* async PKCS7 is not supported */ + #else + devId + #endif + ); + if (pkcs7 == NULL) + return -11739; + + if (testVectors[i].secretKey != NULL) { + /* KEKRI recipient type */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -11740; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + + ret = wc_PKCS7_AddRecipient_KEKRI(pkcs7, testVectors[i].keyWrapOID, + testVectors[i].secretKey, testVectors[i].secretKeySz, + testVectors[i].secretKeyId, testVectors[i].secretKeyIdSz, + testVectors[i].timePtr, testVectors[i].otherAttrOID, + testVectors[i].otherAttrOIDSz, testVectors[i].otherAttr, + testVectors[i].otherAttrSz, testVectors[i].kekriOptions); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -11741; + } + + /* set key, for decryption */ + ret = wc_PKCS7_SetKey(pkcs7, testVectors[i].secretKey, + testVectors[i].secretKeySz); + + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -11742; + } + + } else if (testVectors[i].password != NULL) { + #ifndef NO_PWDBASED + /* PWRI recipient type */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -11743; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + + ret = wc_PKCS7_AddRecipient_PWRI(pkcs7, + (byte*)testVectors[i].password, + testVectors[i].passwordSz, testVectors[i].salt, + testVectors[i].saltSz, testVectors[i].kdfOID, + testVectors[i].hashOID, testVectors[i].kdfIterations, + testVectors[i].encryptOID, testVectors[i].pwriOptions); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -11744; + } + + /* set password, for decryption */ + ret = wc_PKCS7_SetPassword(pkcs7, (byte*)testVectors[i].password, + testVectors[i].passwordSz); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -11745; + } + #endif /* NO_PWDBASED */ + + } else if (testVectors[i].isOri == 1) { + /* ORI recipient type */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -11746; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + + ret = wc_PKCS7_AddRecipient_ORI(pkcs7, myOriEncryptCb, + testVectors[i].oriOptions); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -11747; + } + + /* set decrypt callback for decryption */ + ret = wc_PKCS7_SetOriDecryptCb(pkcs7, myOriDecryptCb); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -11748; + } + + } else { + /* KTRI or KARI recipient types */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -11749; + } + + ret = wc_PKCS7_InitWithCert(pkcs7, testVectors[i].cert, + (word32)testVectors[i].certSz); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -11750; + } + + pkcs7->keyWrapOID = testVectors[i].keyWrapOID; + pkcs7->keyAgreeOID = testVectors[i].keyAgreeOID; + pkcs7->privateKey = testVectors[i].privateKey; + pkcs7->privateKeySz = testVectors[i].privateKeySz; + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + + /* set SubjectIdentifier type for KTRI types */ + if (testVectors[i].ktriOptions & CMS_SKID) { + + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -11751; + } + } else if (testVectors[i].ktriOptions & + CMS_ISSUER_AND_SERIAL_NUMBER) { + + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, + CMS_ISSUER_AND_SERIAL_NUMBER); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -11752; + } + } + } + + /* encode envelopedData */ + envelopedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, enveloped, + sizeof(enveloped)); + if (envelopedSz <= 0) { + wc_PKCS7_Free(pkcs7); + return -11753; + } + + /* decode envelopedData */ + decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, enveloped, envelopedSz, + decoded, sizeof(decoded)); + if (decodedSz <= 0) { + wc_PKCS7_Free(pkcs7); + return -11754; + } + + /* test decode result */ + if (XMEMCMP(decoded, data, sizeof(data)) != 0){ + wc_PKCS7_Free(pkcs7); + return -11755; + } + +#ifndef NO_PKCS7_STREAM + { /* test reading byte by byte */ + int z; + for (z = 0; z < envelopedSz; z++) { + decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, enveloped + z, 1, + decoded, sizeof(decoded)); + if (decodedSz <= 0 && decodedSz != WC_PKCS7_WANT_READ_E) { + printf("unexpected error %d\n", decodedSz); + return -11756; + } + } + /* test decode result */ + if (XMEMCMP(decoded, data, sizeof(data)) != 0) { + printf("stream read compare failed\n"); + wc_PKCS7_Free(pkcs7); + return -11757; + } + } +#endif +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* output pkcs7 envelopedData for external testing */ + pkcs7File = XFOPEN(testVectors[i].outFileName, "wb"); + if (!pkcs7File) { + wc_PKCS7_Free(pkcs7); + return -11758; + } + + ret = (int)XFWRITE(enveloped, 1, envelopedSz, pkcs7File); + XFCLOSE(pkcs7File); + if (ret != envelopedSz) { + wc_PKCS7_Free(pkcs7); + return -11759; + } +#endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + + wc_PKCS7_Free(pkcs7); + pkcs7 = NULL; } - certFile = fopen(clientCert, "rb"); - if (!certFile) { - free(cert); - free(privKey); - err_sys("can't open ./certs/client-cert.der, " - "Please run from wolfSSL home dir", -42); - return -42; + (void)eccCert; + (void)eccCertSz; + (void)eccPrivKey; + (void)eccPrivKeySz; + (void)rsaCert; + (void)rsaCertSz; + (void)rsaPrivKey; + (void)rsaPrivKeySz; + + return 0; +} + + +int pkcs7enveloped_test(void) +{ + int ret = 0; + + byte* rsaCert = NULL; + byte* rsaPrivKey = NULL; + word32 rsaCertSz = 0; + word32 rsaPrivKeySz = 0; + + byte* eccCert = NULL; + byte* eccPrivKey = NULL; + 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 -11800; + + rsaPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (rsaPrivKey == NULL) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -11801; } - certSz = fread(cert, 1, FOURK_BUF, certFile); - fclose(certFile); + rsaCertSz = FOURK_BUF; + rsaPrivKeySz = FOURK_BUF; +#endif /* NO_RSA */ - keyFile = fopen(clientKey, "rb"); - if (!keyFile) { - free(cert); - free(privKey); - err_sys("can't open ./certs/client-key.der, " - "Please run from wolfSSL home dir", -43); - return -43; +#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); + #endif + return -11802; } - privKeySz = fread(privKey, 1, FOURK_BUF, keyFile); - fclose(keyFile); - - wc_PKCS7_InitWithCert(&pkcs7, cert, (word32)certSz); - pkcs7.content = (byte*)data; - pkcs7.contentSz = (word32)sizeof(data); - pkcs7.contentOID = DATA; - pkcs7.encryptOID = cipher; - pkcs7.privateKey = privKey; - pkcs7.privateKeySz = (word32)privKeySz; - - /* encode envelopedData */ - envelopedSz = wc_PKCS7_EncodeEnvelopedData(&pkcs7, enveloped, - sizeof(enveloped)); - if (envelopedSz <= 0) { - free(cert); - free(privKey); - return -203; + 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 -11803; } - /* decode envelopedData */ - decodedSz = wc_PKCS7_DecodeEnvelopedData(&pkcs7, enveloped, envelopedSz, - decoded, sizeof(decoded)); - if (decodedSz <= 0) { - free(cert); - free(privKey); - return -204; + eccCertSz = FOURK_BUF; + eccPrivKeySz = FOURK_BUF; +#endif /* HAVE_ECC */ + + ret = pkcs7_load_certs_keys(rsaCert, &rsaCertSz, rsaPrivKey, + &rsaPrivKeySz, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 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 -11804; } - /* test decode result */ - if (memcmp(decoded, data, sizeof(data)) != 0) { - free(cert); - free(privKey); - return -205; + ret = pkcs7enveloped_run_vectors(rsaCert, (word32)rsaCertSz, + rsaPrivKey, (word32)rsaPrivKeySz, + eccCert, (word32)eccCertSz, + eccPrivKey, (word32)eccPrivKeySz); + +#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; +} + + +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + +typedef struct { + const byte* content; + word32 contentSz; + int contentOID; + int encryptOID; + int keyWrapOID; + int keyAgreeOID; + byte* cert; + size_t certSz; + byte* privateKey; + word32 privateKeySz; + PKCS7Attrib* authAttribs; + word32 authAttribsSz; + PKCS7Attrib* unauthAttribs; + word32 unauthAttribsSz; + + /* KARI / KTRI specific */ + byte* optionalUkm; + word32 optionalUkmSz; + int ktriOptions; /* KTRI options flags */ + int kariOptions; /* KARI options flags */ + + /* KEKRI specific */ + byte* secretKey; /* key, only for kekri RecipientInfo types */ + word32 secretKeySz; /* size of secretKey, bytes */ + byte* secretKeyId; /* key identifier */ + word32 secretKeyIdSz; /* size of key identifier, bytes */ + void* timePtr; /* time_t pointer */ + byte* otherAttrOID; /* OPTIONAL, other attribute OID */ + word32 otherAttrOIDSz; /* size of otherAttrOID, bytes */ + byte* otherAttr; /* OPTIONAL, other attribute, ASN.1 encoded */ + word32 otherAttrSz; /* size of otherAttr, bytes */ + int kekriOptions; /* KEKRI options flags */ + + /* PWRI specific */ + char* password; /* password */ + word32 passwordSz; /* password size, bytes */ + byte* salt; /* KDF salt */ + word32 saltSz; /* KDF salt size, bytes */ + int kdfOID; /* KDF OID */ + int hashOID; /* KDF hash algorithm OID */ + int kdfIterations; /* KDF iterations */ + int kekEncryptOID; /* KEK encryption algorithm OID */ + int pwriOptions; /* PWRI options flags */ + + /* ORI specific */ + int isOri; + int oriOptions; /* ORI options flags */ + + const char* outFileName; +} pkcs7AuthEnvelopedVector; + + +static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, + byte* rsaPrivKey, word32 rsaPrivKeySz, + byte* eccCert, word32 eccCertSz, + byte* eccPrivKey, word32 eccPrivKeySz) +{ + int ret, testSz, i; + int envelopedSz, decodedSz; + + byte enveloped[2048]; + byte decoded[2048]; + WC_RNG rng; + PKCS7* pkcs7; +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + XFILE pkcs7File; +#endif + + const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 + }; + byte senderNonce[PKCS7_NONCE_SZ + 2]; + +#ifdef HAVE_ECC + byte senderNonceOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x05 }; + + PKCS7Attrib attribs[] = + { + { senderNonceOid, sizeof(senderNonceOid), senderNonce, + sizeof(senderNonce) } + }; +#endif + +#if !defined(NO_AES) && defined(WOLFSSL_AES_256) && defined(HAVE_ECC) && \ + defined(WOLFSSL_SHA512) + byte optionalUkm[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + }; +#endif /* NO_AES */ + +#if !defined(NO_AES) && !defined(NO_SHA) && defined(WOLFSSL_AES_128) + /* encryption key for kekri recipient types */ + byte secretKey[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + }; + + /* encryption key identifier */ + byte secretKeyId[] = { + 0x02,0x02,0x03,0x04 + }; +#endif + +#if !defined(NO_PWDBASED) && !defined(NO_AES) && defined(HAVE_AESGCM) && \ + !defined(NO_SHA) && defined(WOLFSSL_AES_128) + + char password[] = "password"; + + byte salt[] = { + 0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12 + }; +#endif + + const pkcs7AuthEnvelopedVector testVectors[] = + { + /* key transport key encryption technique */ +#ifndef NO_RSA + #if !defined(NO_AES) && defined(HAVE_AESGCM) + #ifdef WOLFSSL_AES_128 + {data, (word32)sizeof(data), DATA, AES128GCMb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, + 0, 0, "pkcs7authEnvelopedDataAES128GCM.der"}, + #endif + #ifdef WOLFSSL_AES_192 + {data, (word32)sizeof(data), DATA, AES192GCMb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, + 0, 0, "pkcs7authEnvelopedDataAES192GCM.der"}, + #endif + #ifdef WOLFSSL_AES_256 + {data, (word32)sizeof(data), DATA, AES256GCMb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, + 0, 0, "pkcs7authEnvelopedDataAES256GCM.der"}, + + /* test with contentType set to FirmwarePkgData */ + {data, (word32)sizeof(data), FIRMWARE_PKG_DATA, AES256GCMb, 0, 0, + rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, + 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, + 0, 0, 0, 0, 0, 0, 0, 0, + "pkcs7authEnvelopedDataAES256GCM_firmwarePkgData.der"}, + + /* explicitly using SKID for SubjectKeyIdentifier */ + {data, (word32)sizeof(data), DATA, AES256GCMb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, CMS_SKID, 0, + NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, + 0, 0, 0, 0, 0, "pkcs7authEnvelopedDataAES256GCM_SKID.der"}, + + /* explicitly using IssuerAndSerialNumber for SubjectKeyIdentifier */ + {data, (word32)sizeof(data), DATA, AES256GCMb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, + CMS_ISSUER_AND_SERIAL_NUMBER, 0, NULL, 0, NULL, 0, NULL, NULL, 0, + NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, + "pkcs7authEnvelopedDataAES256GCM_IANDS.der"}, + #endif + #endif /* NO_AES */ +#endif + + /* key agreement key encryption technique*/ +#ifdef HAVE_ECC + #if !defined(NO_AES) && defined(HAVE_AESGCM) + #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) + {data, (word32)sizeof(data), DATA, AES128GCMb, AES128_WRAP, + dhSinglePass_stdDH_sha1kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, NULL, 0, + NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, + "pkcs7authEnvelopedDataAES128GCM_ECDH_SHA1KDF.der"}, + #endif + + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_256) + {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, NULL, 0, + NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, + "pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der"}, + + /* with authenticated attributes */ + {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, attribs, (sizeof(attribs) / sizeof(PKCS7Attrib)), + NULL, 0, NULL, 0, 0, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, + 0, 0, 0, + "pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_authAttribs.der"}, + + /* with unauthenticated attributes */ + {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, attribs, + (sizeof(attribs) / sizeof(PKCS7Attrib)), NULL, 0, 0, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, + 0, 0, 0, + "pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_unauthAttribs.der"}, + + /* with authenticated AND unauthenticated attributes */ + {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, attribs, (sizeof(attribs) / sizeof(PKCS7Attrib)), + attribs, (sizeof(attribs) / sizeof(PKCS7Attrib)), NULL, 0, 0, 0, + NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, + 0, 0, 0, 0, 0, 0, + "pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_bothAttribs.der"}, + + /* with authenticated AND unauthenticated attributes AND + * contentType of FirmwarePkgData */ + {data, (word32)sizeof(data), FIRMWARE_PKG_DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, attribs, (sizeof(attribs) / sizeof(PKCS7Attrib)), + attribs, (sizeof(attribs) / sizeof(PKCS7Attrib)), NULL, 0, 0, 0, + NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, + 0, 0, 0, 0, 0, 0, + "pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_fw_bothAttribs.der"}, + #endif /* NO_SHA256 && WOLFSSL_AES_256 */ + + #if defined(WOLFSSL_SHA512) && defined(WOLFSSL_AES_256) + {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, + NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, + "pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der"}, + + /* with optional user keying material (ukm) */ + {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, NULL, 0, optionalUkm, sizeof(optionalUkm), 0, + 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, + 0, 0, 0, 0, 0, 0, + "pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der"}, + #endif /* WOLFSSL_SHA512 && WOLFSSL_AES_256 */ + #endif /* NO_AES */ +#endif + + /* kekri (KEKRecipientInfo) recipient types */ +#if !defined(NO_AES) && defined(HAVE_AESGCM) + #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) + {data, (word32)sizeof(data), DATA, AES128GCMb, AES128_WRAP, 0, + NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, + secretKey, sizeof(secretKey), secretKeyId, sizeof(secretKeyId), + NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, + "pkcs7authEnvelopedDataAES128GCM_KEKRI.der"}, + #endif +#endif + + /* pwri (PasswordRecipientInfo) recipient types */ +#if !defined(NO_PWDBASED) && !defined(NO_AES) && defined(HAVE_AESGCM) + #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) + {data, (word32)sizeof(data), DATA, AES128GCMb, 0, 0, + NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, password, + (word32)XSTRLEN(password), salt, sizeof(salt), PBKDF2_OID, WC_SHA, 5, + AES128CBCb, 0, 0, 0, "pkcs7authEnvelopedDataAES128GCM_PWRI.der"}, + #endif +#endif + +#if !defined(NO_AES) && defined(HAVE_AESGCM) + #ifdef WOLFSSL_AES_128 + /* ori (OtherRecipientInfo) recipient types */ + {data, (word32)sizeof(data), DATA, AES128GCMb, 0, 0, NULL, 0, NULL, 0, + NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, + NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 1, 0, + "pkcs7authEnvelopedDataAES128GCM_ORI.der"}, + #endif +#endif + }; + + testSz = sizeof(testVectors) / sizeof(pkcs7AuthEnvelopedVector); + + + /* generate senderNonce */ + { +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) { + return -11805; + } + + senderNonce[0] = 0x04; + senderNonce[1] = PKCS7_NONCE_SZ; + + ret = wc_RNG_GenerateBlock(&rng, &senderNonce[2], PKCS7_NONCE_SZ); + if (ret != 0) { + wc_FreeRng(&rng); + return -11806; + } + + wc_FreeRng(&rng); } - /* output pkcs7 envelopedData for external testing */ - pkcs7File = fopen(pkcs7OutFile, "wb"); - if (!pkcs7File) { - free(cert); - free(privKey); - return -206; + for (i = 0; i < testSz; i++) { + pkcs7 = wc_PKCS7_New(HEAP_HINT, + #ifdef WOLFSSL_ASYNC_CRYPT + INVALID_DEVID /* async PKCS7 is not supported */ + #else + devId + #endif + ); + if (pkcs7 == NULL) + return -11807; + + if (testVectors[i].secretKey != NULL) { + /* KEKRI recipient type */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -11808; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + pkcs7->authAttribs = testVectors[i].authAttribs; + pkcs7->authAttribsSz = testVectors[i].authAttribsSz; + pkcs7->unauthAttribs = testVectors[i].unauthAttribs; + pkcs7->unauthAttribsSz = testVectors[i].unauthAttribsSz; + + ret = wc_PKCS7_AddRecipient_KEKRI(pkcs7, testVectors[i].keyWrapOID, + testVectors[i].secretKey, testVectors[i].secretKeySz, + testVectors[i].secretKeyId, testVectors[i].secretKeyIdSz, + testVectors[i].timePtr, testVectors[i].otherAttrOID, + testVectors[i].otherAttrOIDSz, testVectors[i].otherAttr, + testVectors[i].otherAttrSz, testVectors[i].kekriOptions); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -11809; + } + + /* set key, for decryption */ + ret = wc_PKCS7_SetKey(pkcs7, testVectors[i].secretKey, + testVectors[i].secretKeySz); + + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -11810; + } + + } else if (testVectors[i].password != NULL) { + #ifndef NO_PWDBASED + /* PWRI recipient type */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -11811; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + pkcs7->authAttribs = testVectors[i].authAttribs; + pkcs7->authAttribsSz = testVectors[i].authAttribsSz; + pkcs7->unauthAttribs = testVectors[i].unauthAttribs; + pkcs7->unauthAttribsSz = testVectors[i].unauthAttribsSz; + + ret = wc_PKCS7_AddRecipient_PWRI(pkcs7, + (byte*)testVectors[i].password, + testVectors[i].passwordSz, testVectors[i].salt, + testVectors[i].saltSz, testVectors[i].kdfOID, + testVectors[i].hashOID, testVectors[i].kdfIterations, + testVectors[i].kekEncryptOID, testVectors[i].pwriOptions); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -11812; + } + + /* set password, for decryption */ + ret = wc_PKCS7_SetPassword(pkcs7, (byte*)testVectors[i].password, + testVectors[i].passwordSz); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -11813; + } + + #endif /* NO_PWDBASED */ + } else if (testVectors[i].isOri == 1) { + /* ORI recipient type */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -11814; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->authAttribs = testVectors[i].authAttribs; + pkcs7->authAttribsSz = testVectors[i].authAttribsSz; + pkcs7->unauthAttribs = testVectors[i].unauthAttribs; + pkcs7->unauthAttribsSz = testVectors[i].unauthAttribsSz; + + ret = wc_PKCS7_AddRecipient_ORI(pkcs7, myOriEncryptCb, + testVectors[i].oriOptions); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -11815; + } + + /* set decrypt callback for decryption */ + ret = wc_PKCS7_SetOriDecryptCb(pkcs7, myOriDecryptCb); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -11816; + } + + } else { + /* KTRI or KARI recipient types */ + + ret = wc_PKCS7_InitWithCert(pkcs7, testVectors[i].cert, + (word32)testVectors[i].certSz); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -11817; + } + + pkcs7->keyWrapOID = testVectors[i].keyWrapOID; + pkcs7->keyAgreeOID = testVectors[i].keyAgreeOID; + pkcs7->privateKey = testVectors[i].privateKey; + pkcs7->privateKeySz = testVectors[i].privateKeySz; + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + pkcs7->authAttribs = testVectors[i].authAttribs; + pkcs7->authAttribsSz = testVectors[i].authAttribsSz; + pkcs7->unauthAttribs = testVectors[i].unauthAttribs; + pkcs7->unauthAttribsSz = testVectors[i].unauthAttribsSz; + + /* set SubjectIdentifier type for KTRI types */ + if (testVectors[i].ktriOptions & CMS_SKID) { + + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -11818; + } + } else if (testVectors[i].ktriOptions & + CMS_ISSUER_AND_SERIAL_NUMBER) { + + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, + CMS_ISSUER_AND_SERIAL_NUMBER); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -11819; + } + } + } + + /* encode envelopedData */ + envelopedSz = wc_PKCS7_EncodeAuthEnvelopedData(pkcs7, enveloped, + sizeof(enveloped)); + if (envelopedSz <= 0) { + wc_PKCS7_Free(pkcs7); + return -11820; + } +#ifndef NO_PKCS7_STREAM + { /* test reading byte by byte */ + int z; + for (z = 0; z < envelopedSz; z++) { + decodedSz = wc_PKCS7_DecodeAuthEnvelopedData(pkcs7, + enveloped + z, 1, decoded, sizeof(decoded)); + if (decodedSz <= 0 && decodedSz != WC_PKCS7_WANT_READ_E) { + printf("unexpected error %d\n", decodedSz); + return -11821; + } + } + /* test decode result */ + if (XMEMCMP(decoded, data, sizeof(data)) != 0) { + printf("stream read compare failed\n"); + wc_PKCS7_Free(pkcs7); + return -11822; + } + } +#endif + /* decode envelopedData */ + decodedSz = wc_PKCS7_DecodeAuthEnvelopedData(pkcs7, enveloped, + envelopedSz, decoded, + sizeof(decoded)); + if (decodedSz <= 0) { + wc_PKCS7_Free(pkcs7); + return -11823; + } + + /* test decode result */ + if (XMEMCMP(decoded, data, sizeof(data)) != 0){ + wc_PKCS7_Free(pkcs7); + return -11824; + } + +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* output pkcs7 envelopedData for external testing */ + pkcs7File = XFOPEN(testVectors[i].outFileName, "wb"); + if (!pkcs7File) { + wc_PKCS7_Free(pkcs7); + return -11825; + } + + ret = (int)XFWRITE(enveloped, 1, envelopedSz, pkcs7File); + XFCLOSE(pkcs7File); + if (ret != envelopedSz) { + wc_PKCS7_Free(pkcs7); + return -11826; + } +#endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + + wc_PKCS7_Free(pkcs7); + pkcs7 = NULL; } - ret = (int)fwrite(enveloped, envelopedSz, 1, pkcs7File); - fclose(pkcs7File); +#if !defined(HAVE_ECC) || defined(NO_AES) + (void)eccCert; + (void)eccCertSz; + (void)eccPrivKey; + (void)eccPrivKeySz; + (void)secretKey; + (void)secretKeyId; +#endif +#ifdef NO_RSA + (void)rsaCert; + (void)rsaCertSz; + (void)rsaPrivKey; + (void)rsaPrivKeySz; +#endif + return 0; +} - free(cert); - free(privKey); - wc_PKCS7_Free(&pkcs7); + +int pkcs7authenveloped_test(void) +{ + int ret = 0; + + byte* rsaCert = NULL; + byte* rsaPrivKey = NULL; + word32 rsaCertSz = 0; + word32 rsaPrivKeySz = 0; + + byte* eccCert = NULL; + byte* eccPrivKey = NULL; + 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 -11900; + + rsaPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (rsaPrivKey == NULL) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -11901; + } + + 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); + #endif + return -11902; + } + + 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 -11903; + } + + eccCertSz = FOURK_BUF; + eccPrivKeySz = FOURK_BUF; +#endif /* HAVE_ECC */ + + ret = pkcs7_load_certs_keys(rsaCert, &rsaCertSz, rsaPrivKey, + &rsaPrivKeySz, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 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 -11904; + } + + ret = pkcs7authenveloped_run_vectors(rsaCert, (word32)rsaCertSz, + rsaPrivKey, (word32)rsaPrivKeySz, + eccCert, (word32)eccCertSz, + eccPrivKey, (word32)eccPrivKeySz); + +#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; +} + +#endif /* HAVE_AESGCM || HAVE_AESCCM */ +#ifndef NO_AES +static const byte p7DefKey[] = { + 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 +}; + +static const byte p7AltKey[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 +}; + +static int myCEKwrapFunc(PKCS7* pkcs7, byte* cek, word32 cekSz, byte* keyId, + word32 keyIdSz, byte* orginKey, word32 orginKeySz, + byte* out, word32 outSz, int keyWrapAlgo, int type, int direction) +{ + int ret; + + if (cek == NULL || out == NULL) + return BAD_FUNC_ARG; + + /* test case sanity checks */ + if (keyIdSz != 1) { + return -11905; + } + + if (keyId[0] != 0x00) { + return -11906; + } + + if (type != (int)PKCS7_KEKRI) { + return -11907; + } + + switch (keyWrapAlgo) { + case AES256_WRAP: + ret = wc_AesKeyUnWrap(p7DefKey, sizeof(p7DefKey), cek, cekSz, + out, outSz, NULL); + if (ret <= 0) + return ret; + break; + + default: + WOLFSSL_MSG("Unsupported key wrap algorithm in example"); + return BAD_KEYWRAP_ALG_E; + }; + + (void)pkcs7; + (void)direction; + (void)orginKey; /* used with KAKRI */ + (void)orginKeySz; + return ret; +} + + +/* returns key size on success */ +static int getFirmwareKey(PKCS7* pkcs7, byte* key, word32 keySz) +{ + int ret; + word32 atrSz; + byte atr[256]; + + /* Additionally can look for fwWrappedFirmwareKey + * 1.2.840.113529.1.9.16.1.16 */ + const unsigned char fwWrappedFirmwareKey[] = { + /* 0x06, 0x0B */ + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x02, 0x27 + }; + + /* find keyID in fwWrappedFirmwareKey */ + ret = wc_PKCS7_GetAttributeValue(pkcs7, fwWrappedFirmwareKey, + sizeof(fwWrappedFirmwareKey), NULL, &atrSz); + if (ret == LENGTH_ONLY_E) { + XMEMSET(atr, 0, sizeof(atr)); + ret = wc_PKCS7_GetAttributeValue(pkcs7, fwWrappedFirmwareKey, + sizeof(fwWrappedFirmwareKey), atr, &atrSz); + + /* keyIdRaw[0] OCTET TAG */ + /* keyIdRaw[1] Length */ + + if (ret > 0) { + PKCS7* envPkcs7; + + envPkcs7 = wc_PKCS7_New(NULL, 0); + if (envPkcs7 == NULL) { + return MEMORY_E; + } + + wc_PKCS7_Init(envPkcs7, NULL, 0); + ret = wc_PKCS7_SetWrapCEKCb(envPkcs7, myCEKwrapFunc); + if (ret == 0) { + /* expecting FIRMWARE_PKG_DATA content */ + envPkcs7->contentOID = FIRMWARE_PKG_DATA; + ret = wc_PKCS7_DecodeEnvelopedData(envPkcs7, atr, atrSz, + key, keySz); + } + wc_PKCS7_Free(envPkcs7); + } + } + + return ret; +} + +/* create a KEKRI enveloped data + * return size on success */ +static int envelopedData_encrypt(byte* in, word32 inSz, byte* out, + word32 outSz) +{ + int ret; + PKCS7* pkcs7; + const byte keyId[] = { 0x00 }; + + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -11908; + + pkcs7->content = in; + pkcs7->contentSz = inSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + pkcs7->encryptOID = AES256CBCb; + pkcs7->ukm = NULL; + pkcs7->ukmSz = 0; + + /* add recipient (KEKRI type) */ + ret = wc_PKCS7_AddRecipient_KEKRI(pkcs7, AES256_WRAP, (byte*)p7DefKey, + sizeof(p7DefKey), (byte*)keyId, + sizeof(keyId), NULL, NULL, 0, NULL, 0, 0); + if (ret < 0) { + printf("wc_PKCS7_AddRecipient_KEKRI() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -11909; + } + + /* encode envelopedData, returns size */ + ret = wc_PKCS7_EncodeEnvelopedData(pkcs7, out, outSz); + if (ret <= 0) { + printf("wc_PKCS7_EncodeEnvelopedData() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -11910; + + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + + +/* + * keyHint is the KeyID to be set in the fwDecryptKeyID attribute + * returns size of buffer output on success + */ +static int generateBundle(byte* out, word32 *outSz, const byte* encryptKey, + word32 encryptKeySz, byte keyHint, byte* cert, word32 certSz, + byte* key, word32 keySz) +{ + int ret, attribNum = 1; + PKCS7* pkcs7; + + /* KEY ID + * fwDecryptKeyID OID 1.2.840.113549.1.9.16.2.37 + */ + const unsigned char fwDecryptKeyID[] = { + 0x06, 0x0B, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x02, 0x25 + }; + + /* fwWrappedFirmwareKey 1.2.840.113529.1.9.16.1.16 */ + const unsigned char fwWrappedFirmwareKey[] = { + 0x06, 0x0B, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x02, 0x27 + }; + + byte keyID[] = { 0x04, 0x01, 0x00 }; + byte env[256]; + char data[] = "Test of wolfSSL PKCS7 decrypt callback"; + + PKCS7Attrib attribs[] = + { + { fwDecryptKeyID, sizeof(fwDecryptKeyID), keyID, sizeof(keyID) }, + { fwWrappedFirmwareKey, sizeof(fwWrappedFirmwareKey), env, 0 } + }; + + keyID[2] = keyHint; + + /* If using keyHint 0 then create a bundle with fwWrappedFirmwareKey */ + if (keyHint == 0) { + ret = envelopedData_encrypt((byte*)p7DefKey, sizeof(p7DefKey), env, + sizeof(env)); + if (ret <= 0) { + return ret; + } + attribs[1].valueSz = ret; + attribNum++; + } + + /* init PKCS7 */ + pkcs7 = wc_PKCS7_New(NULL, INVALID_DEVID); + if (pkcs7 == NULL) + return -11911; + + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) { + printf("ERROR: wc_PKCS7_InitWithCert() failed, ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -11912; + } + + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -11913; + } + + /* encode Signed Encrypted FirmwarePkgData */ + if (encryptKeySz == 16) { + ret = wc_PKCS7_EncodeSignedEncryptedFPD(pkcs7, (byte*)encryptKey, + encryptKeySz, key, keySz, AES128CBCb, RSAk, SHA256h, + (byte*)data, sizeof(data), NULL, 0, + attribs, attribNum, out, *outSz); + } + else { + ret = wc_PKCS7_EncodeSignedEncryptedFPD(pkcs7, (byte*)encryptKey, + encryptKeySz, key, keySz, AES256CBCb, RSAk, SHA256h, + (byte*)data, sizeof(data), NULL, 0, + attribs, attribNum, out, *outSz); + } + if (ret <= 0) { + printf("ERROR: wc_PKCS7_EncodeSignedEncryptedFPD() failed, " + "ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -11914; + + } else { + *outSz = ret; + } + + wc_PKCS7_Free(pkcs7); + + return ret; +} + + +/* test verification and decryption of PKCS7 bundle + * return 0 on success + */ +static int verifyBundle(byte* derBuf, word32 derSz, int keyHint) +{ + int ret = 0; + int usrCtx = 1; /* test value to pass as user context to callback */ + PKCS7* pkcs7; + byte* sid; + word32 sidSz; + byte key[256]; + word32 keySz = sizeof(key); + + byte decoded[FOURK_BUF/2]; + int decodedSz = FOURK_BUF/2; + + const byte expectedSid[] = { + 0x33, 0xD8, 0x45, 0x66, 0xD7, 0x68, 0x87, 0x18, + 0x7E, 0x54, 0x0D, 0x70, 0x27, 0x91, 0xC7, 0x26, + 0xD7, 0x85, 0x65, 0xC0 + }; + + pkcs7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); + if (pkcs7 == NULL) { + return MEMORY_E; + } + + /* Test verify */ + ret = wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return ret; + } + ret = wc_PKCS7_InitWithCert(pkcs7, NULL, 0); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return ret; + } + ret = wc_PKCS7_VerifySignedData(pkcs7, derBuf, derSz); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return ret; + } + + /* Get size of SID and print it out */ + ret = wc_PKCS7_GetSignerSID(pkcs7, NULL, &sidSz); + if (ret != LENGTH_ONLY_E) { + wc_PKCS7_Free(pkcs7); + return ret; + } + + sid = (byte*)XMALLOC(sidSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (sid == NULL) { + wc_PKCS7_Free(pkcs7); + return ret; + } + + ret = wc_PKCS7_GetSignerSID(pkcs7, sid, &sidSz); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + XFREE(sid, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + ret = XMEMCMP(sid, expectedSid, sidSz); + XFREE(sid, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return ret; + } + + /* get expected fwWrappedFirmwareKey */ + if (keyHint == 0) { + ret = getFirmwareKey(pkcs7, key, keySz); + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return ret; + } + pkcs7->encryptionKey = key; + pkcs7->encryptionKeySz = ret; + } + else { + decodedSz = sizeof(decoded); + ret = wc_PKCS7_SetDecodeEncryptedCb(pkcs7, myDecryptionFunc); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return ret; + } + + ret = wc_PKCS7_SetDecodeEncryptedCtx(pkcs7, (void*)&usrCtx); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return ret; + } + } + + decodedSz = wc_PKCS7_DecodeEncryptedData(pkcs7, pkcs7->content, + pkcs7->contentSz, decoded, decodedSz); + if (decodedSz < 0) { + ret = decodedSz; + wc_PKCS7_Free(pkcs7); + return ret; + } + + wc_PKCS7_Free(pkcs7); + return 0; +} + + +int pkcs7callback_test(byte* cert, word32 certSz, byte* key, word32 keySz) +{ + + int ret = 0; + byte derBuf[FOURK_BUF/2]; + word32 derSz = FOURK_BUF/2; + + /* Doing default generation and verify */ + ret = generateBundle(derBuf, &derSz, p7DefKey, sizeof(p7DefKey), 0, cert, + certSz, key, keySz); + if (ret <= 0) { + return -11915; + } + + ret = verifyBundle(derBuf, derSz, 0); + if (ret != 0) { + return -11916; + } + + /* test choosing other key with keyID */ + derSz = FOURK_BUF/2; + ret = generateBundle(derBuf, &derSz, p7AltKey, sizeof(p7AltKey), 1, + cert, certSz, key, keySz); + if (ret <= 0) { + return -11917; + } + + ret = verifyBundle(derBuf, derSz, 1); + if (ret != 0) { + return -11918; + } + + /* test fail case with wrong keyID */ + derSz = FOURK_BUF/2; + ret = generateBundle(derBuf, &derSz, p7DefKey, sizeof(p7DefKey), 1, + cert, certSz, key, keySz); + if (ret <= 0) { + return -11919; + } + + ret = verifyBundle(derBuf, derSz, 1); + if (ret == 0) { + return -11920; + } + + return 0; +} +#endif /* NO_AES */ + +#ifndef NO_PKCS7_ENCRYPTED_DATA + +typedef struct { + const byte* content; + word32 contentSz; + int contentOID; + int encryptOID; + byte* encryptionKey; + word32 encryptionKeySz; + PKCS7Attrib* attribs; + word32 attribsSz; + const char* outFileName; +} pkcs7EncryptedVector; + + +int pkcs7encrypted_test(void) +{ + int ret = 0; + int i, testSz; + int encryptedSz, decodedSz, attribIdx; + PKCS7* pkcs7; + byte encrypted[2048]; + byte decoded[2048]; +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + XFILE pkcs7File; +#endif + + PKCS7Attrib* expectedAttrib; + PKCS7DecodedAttrib* decodedAttrib; + + const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 + }; + +#ifndef NO_DES3 + byte desKey[] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef + }; + byte des3Key[] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 + }; +#endif + +#ifndef NO_AES +#ifdef WOLFSSL_AES_128 + byte aes128Key[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 + }; +#endif +#ifdef WOLFSSL_AES_192 + byte aes192Key[] = { + 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 +#ifdef WOLFSSL_AES_256 + byte aes256Key[] = { + 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 + +#ifdef WOLFSSL_AES_256 + /* Attribute example from RFC 4134, Section 7.2 + * OID = 1.2.5555 + * OCTET STRING = 'This is a test General ASN Attribute, number 1.' */ + static byte genAttrOid[] = { 0x06, 0x03, 0x2a, 0xab, 0x33 }; + static byte genAttr[] = { 0x04, 47, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x41, + 0x53, 0x4e, 0x20, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x2c, 0x20, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x20, 0x31, 0x2e }; + + static byte genAttrOid2[] = { 0x06, 0x03, 0x2a, 0xab, 0x34 }; + static byte genAttr2[] = { 0x04, 47, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x41, + 0x53, 0x4e, 0x20, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x2c, 0x20, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x20, 0x32, 0x2e }; + + PKCS7Attrib attribs[] = + { + { genAttrOid, sizeof(genAttrOid), genAttr, sizeof(genAttr) } + }; + + PKCS7Attrib multiAttribs[] = + { + { genAttrOid, sizeof(genAttrOid), genAttr, sizeof(genAttr) }, + { genAttrOid2, sizeof(genAttrOid2), genAttr2, sizeof(genAttr2) } + }; +#endif +#endif /* NO_AES */ + + const pkcs7EncryptedVector testVectors[] = + { +#ifndef NO_DES3 + {data, (word32)sizeof(data), DATA, DES3b, des3Key, sizeof(des3Key), + NULL, 0, "pkcs7encryptedDataDES3.der"}, + + {data, (word32)sizeof(data), DATA, DESb, desKey, sizeof(desKey), + NULL, 0, "pkcs7encryptedDataDES.der"}, +#endif /* NO_DES3 */ + +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + {data, (word32)sizeof(data), DATA, AES128CBCb, aes128Key, + sizeof(aes128Key), NULL, 0, "pkcs7encryptedDataAES128CBC.der"}, + #endif + #ifdef WOLFSSL_AES_192 + {data, (word32)sizeof(data), DATA, AES192CBCb, aes192Key, + sizeof(aes192Key), NULL, 0, "pkcs7encryptedDataAES192CBC.der"}, + #endif + #ifdef WOLFSSL_AES_256 + {data, (word32)sizeof(data), DATA, AES256CBCb, aes256Key, + sizeof(aes256Key), NULL, 0, "pkcs7encryptedDataAES256CBC.der"}, + + /* test with optional unprotected attributes */ + {data, (word32)sizeof(data), DATA, AES256CBCb, aes256Key, + sizeof(aes256Key), attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7encryptedDataAES256CBC_attribs.der"}, + + /* test with multiple optional unprotected attributes */ + {data, (word32)sizeof(data), DATA, AES256CBCb, aes256Key, + sizeof(aes256Key), multiAttribs, + (sizeof(multiAttribs)/sizeof(PKCS7Attrib)), + "pkcs7encryptedDataAES256CBC_multi_attribs.der"}, + + /* test with contentType set to FirmwarePkgData */ + {data, (word32)sizeof(data), FIRMWARE_PKG_DATA, AES256CBCb, aes256Key, + sizeof(aes256Key), NULL, 0, + "pkcs7encryptedDataAES256CBC_firmwarePkgData.der"}, + #endif +#endif /* NO_AES */ + }; + + testSz = sizeof(testVectors) / sizeof(pkcs7EncryptedVector); + + for (i = 0; i < testSz; i++) { + pkcs7 = wc_PKCS7_New(HEAP_HINT, devId); + if (pkcs7 == NULL) + return -12000; + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->encryptionKey = testVectors[i].encryptionKey; + pkcs7->encryptionKeySz = testVectors[i].encryptionKeySz; + pkcs7->unprotectedAttribs = testVectors[i].attribs; + pkcs7->unprotectedAttribsSz = testVectors[i].attribsSz; + + /* encode encryptedData */ + encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, + sizeof(encrypted)); + if (encryptedSz <= 0) { + wc_PKCS7_Free(pkcs7); + return -12001; + } + + /* decode encryptedData */ +#ifndef NO_PKCS7_STREAM + { /* test reading byte by byte */ + int z; + for (z = 0; z < encryptedSz; z++) { + decodedSz = wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted + z, 1, + decoded, sizeof(decoded)); + if (decodedSz <= 0 && decodedSz != WC_PKCS7_WANT_READ_E) { + printf("unexpected error %d\n", decodedSz); + return -12002; + } + } + /* test decode result */ + if (XMEMCMP(decoded, data, sizeof(data)) != 0) { + printf("stream read failed\n"); + wc_PKCS7_Free(pkcs7); + return -12003; + } + } +#endif + decodedSz = wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz, + decoded, sizeof(decoded)); + if (decodedSz <= 0){ + wc_PKCS7_Free(pkcs7); + return -12004; + } + + /* test decode result */ + if (XMEMCMP(decoded, data, sizeof(data)) != 0) { + wc_PKCS7_Free(pkcs7); + return -12005; + } + + /* verify decoded unprotected attributes */ + if (pkcs7->decodedAttrib != NULL) { + decodedAttrib = pkcs7->decodedAttrib; + attribIdx = 1; + + while (decodedAttrib != NULL) { + + /* expected attribute, stored list is reversed */ + expectedAttrib = &(pkcs7->unprotectedAttribs + [pkcs7->unprotectedAttribsSz - attribIdx]); + + /* verify oid */ + if (XMEMCMP(decodedAttrib->oid, expectedAttrib->oid, + decodedAttrib->oidSz) != 0) { + wc_PKCS7_Free(pkcs7); + return -12006; + } + + /* verify value */ + if (XMEMCMP(decodedAttrib->value, expectedAttrib->value, + decodedAttrib->valueSz) != 0) { + wc_PKCS7_Free(pkcs7); + return -12007; + } + + decodedAttrib = decodedAttrib->next; + attribIdx++; + } + } + +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* output pkcs7 envelopedData for external testing */ + pkcs7File = XFOPEN(testVectors[i].outFileName, "wb"); + if (!pkcs7File) { + wc_PKCS7_Free(pkcs7); + return -12008; + } + + ret = (int)XFWRITE(encrypted, encryptedSz, 1, pkcs7File); + XFCLOSE(pkcs7File); + + if (ret > 0) + ret = 0; +#endif + + wc_PKCS7_Free(pkcs7); + } + + return ret; +} + +#endif /* NO_PKCS7_ENCRYPTED_DATA */ + + +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + +typedef struct { + const byte* content; + word32 contentSz; + int contentOID; + const char* outFileName; +} pkcs7CompressedVector; + + +int pkcs7compressed_test(void) +{ + int ret = 0; + int i, testSz; + int compressedSz, decodedSz; + PKCS7* pkcs7; + byte compressed[2048]; + byte decoded[2048]; +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + XFILE pkcs7File; +#endif + + const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 + }; + + const pkcs7CompressedVector testVectors[] = + { + {data, (word32)sizeof(data), DATA, + "pkcs7compressedData_data_zlib.der"}, + {data, (word32)sizeof(data), FIRMWARE_PKG_DATA, + "pkcs7compressedData_firmwarePkgData_zlib.der"}, + }; + + testSz = sizeof(testVectors) / sizeof(pkcs7CompressedVector); + + for (i = 0; i < testSz; i++) { + pkcs7 = wc_PKCS7_New(HEAP_HINT, devId); + if (pkcs7 == NULL) + return -12100; + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + + /* encode compressedData */ + compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, compressed, + sizeof(compressed)); + if (compressedSz <= 0) { + wc_PKCS7_Free(pkcs7); + return -12101; + } + + /* decode compressedData */ + decodedSz = wc_PKCS7_DecodeCompressedData(pkcs7, compressed, + compressedSz, decoded, + sizeof(decoded)); + if (decodedSz <= 0){ + wc_PKCS7_Free(pkcs7); + return -12102; + } + + /* test decode result */ + if (XMEMCMP(decoded, testVectors[i].content, + testVectors[i].contentSz) != 0) { + wc_PKCS7_Free(pkcs7); + return -12103; + } + + /* make sure content type is the same */ + if (testVectors[i].contentOID != pkcs7->contentOID) + return -12104; + +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* output pkcs7 compressedData for external testing */ + pkcs7File = XFOPEN(testVectors[i].outFileName, "wb"); + if (!pkcs7File) { + wc_PKCS7_Free(pkcs7); + return -12105; + } + + ret = (int)XFWRITE(compressed, compressedSz, 1, pkcs7File); + XFCLOSE(pkcs7File); + + if (ret > 0) + ret = 0; +#endif + + wc_PKCS7_Free(pkcs7); + } + + return ret; +} /* pkcs7compressed_test() */ + +#endif /* HAVE_LIBZ */ + + +typedef struct { + const byte* content; + word32 contentSz; + int hashOID; + int signOID; + byte* privateKey; + word32 privateKeySz; + byte* cert; + size_t certSz; + byte* caCert; + size_t caCertSz; + PKCS7Attrib* signedAttribs; + word32 signedAttribsSz; + const char* outFileName; + int contentOID; + byte* contentType; + word32 contentTypeSz; + int sidType; + int encryptOID; /* for single-shot encrypt alg OID */ + int encCompFlag; /* for single-shot. 1 = enc, 2 = comp, 3 = both*/ + byte* encryptKey; /* for single-shot, encryptedData */ + word32 encryptKeySz; /* for single-shot, encryptedData */ + PKCS7Attrib* unprotectedAttribs; /* for single-shot, encryptedData */ + word32 unprotectedAttribsSz; /* for single-shot, encryptedData */ + word16 detachedSignature; /* generate detached signature (0:1) */ +} pkcs7SignedVector; + + +static int pkcs7signed_run_vectors( + byte* rsaClientCertBuf, word32 rsaClientCertBufSz, + byte* rsaClientPrivKeyBuf, word32 rsaClientPrivKeyBufSz, + byte* rsaServerCertBuf, word32 rsaServerCertBufSz, + byte* rsaServerPrivKeyBuf, word32 rsaServerPrivKeyBufSz, + byte* rsaCaCertBuf, word32 rsaCaCertBufSz, + byte* rsaCaPrivKeyBuf, word32 rsaCaPrivKeyBufSz, + byte* eccClientCertBuf, word32 eccClientCertBufSz, + byte* eccClientPrivKeyBuf, word32 eccClientPrivKeyBufSz) +{ + int ret, testSz, i; + int encodedSz; + byte* out; + word32 outSz; + WC_RNG rng; + PKCS7* pkcs7; +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + XFILE 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, + 0x09, 0x07 }; + static byte messageTypeOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x02 }; + static byte senderNonceOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x05 }; +#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]; + + PKCS7Attrib attribs[] = + { + { transIdOid, sizeof(transIdOid), transId, + sizeof(transId) - 1 }, /* take off the null */ + { messageTypeOid, sizeof(messageTypeOid), messageType, + sizeof(messageType) }, + { senderNonceOid, sizeof(senderNonceOid), senderNonce, + sizeof(senderNonce) } + }; + + /* for testing custom contentType, FirmwarePkgData */ + byte customContentType[] = { 0x06, 0x0B, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x01, 0x10 }; + + const pkcs7SignedVector testVectors[] = + { +#ifndef NO_RSA + #ifndef NO_SHA + /* RSA with SHA */ + {data, (word32)sizeof(data), SHAh, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA.der", 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, + 0, 0}, + + /* RSA with SHA, no signed attributes */ + {data, (word32)sizeof(data), SHAh, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, + NULL, 0, NULL, 0, + "pkcs7signedData_RSA_SHA_noattr.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0, 0}, + #endif + #ifdef WOLFSSL_SHA224 + /* RSA with SHA224 */ + {data, (word32)sizeof(data), SHA224h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA224.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0, 0}, + #endif + #ifndef NO_SHA256 + /* RSA with SHA256 */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA256.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0, 0}, + + /* RSA with SHA256, detached signature */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA256_detachedSig.der", 0, NULL, 0, 0, 0, 0, + NULL, 0, NULL, 0, 1}, + + /* RSA with SHA256 and SubjectKeyIdentifier in SignerIdentifier */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA256_SKID.der", 0, NULL, 0, CMS_SKID, 0, 0, + NULL, 0, NULL, 0, 0}, + + /* RSA with SHA256 and custom contentType */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA256_custom_contentType.der", 0, + customContentType, sizeof(customContentType), 0, 0, 0, NULL, 0, + NULL, 0, 0}, + + /* RSA with SHA256 and FirmwarePkgData contentType */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA256_firmwarePkgData.der", + FIRMWARE_PKG_DATA, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0, 0}, + + /* RSA with SHA256 using server cert and ca cert */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaServerPrivKeyBuf, + rsaServerPrivKeyBufSz, rsaServerCertBuf, rsaServerCertBufSz, + rsaCaCertBuf, rsaCaCertBufSz, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA256_with_ca_cert.der", 0, NULL, 0, 0, 0, 0, + NULL, 0, NULL, 0, 0}, + #endif + #if defined(WOLFSSL_SHA384) + /* RSA with SHA384 */ + {data, (word32)sizeof(data), SHA384h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA384.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0, 0}, + #endif + #if defined(WOLFSSL_SHA512) + /* RSA with SHA512 */ + {data, (word32)sizeof(data), SHA512h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA512.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0, 0}, + #endif +#endif /* NO_RSA */ + +#ifdef HAVE_ECC + #ifndef NO_SHA + /* ECDSA with SHA */ + {data, (word32)sizeof(data), SHAh, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0, 0}, + + /* ECDSA with SHA, no signed attributes */ + {data, (word32)sizeof(data), SHAh, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, + NULL, 0, NULL, 0, + "pkcs7signedData_ECDSA_SHA_noattr.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0, 0}, + #endif + #ifdef WOLFSSL_SHA224 + /* ECDSA with SHA224 */ + {data, (word32)sizeof(data), SHA224h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA224.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0, 0}, + #endif + #ifndef NO_SHA256 + /* ECDSA with SHA256 */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA256.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0, 0}, + + /* ECDSA with SHA256 and SubjectKeyIdentifier in SigherIdentifier */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA256_SKID.der", 0, NULL, 0, CMS_SKID, 0, 0, + NULL, 0, NULL, 0, 0}, + + /* ECDSA with SHA256 and custom contentType */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA256_custom_contentType.der", 0, + customContentType, sizeof(customContentType), 0, 0, 0, NULL, 0, + NULL, 0, 0}, + + /* ECDSA with SHA256 and FirmwarePkgData contentType */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA256_firmwarePkgData.der", + FIRMWARE_PKG_DATA, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0, 0}, + #endif + #ifdef WOLFSSL_SHA384 + /* ECDSA with SHA384 */ + {data, (word32)sizeof(data), SHA384h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA384.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0, 0}, + #endif + #ifdef WOLFSSL_SHA512 + /* ECDSA with SHA512 */ + {data, (word32)sizeof(data), SHA512h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA512.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0, 0}, + #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 -12106; + + XMEMSET(out, 0, outSz); + + ret = wc_PKCS7_PadData((byte*)data, sizeof(data), out, outSz, 16); + if (ret < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -12107; + } + +#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 -12108; + } + + for (i = 0; i < testSz; i++) { + pkcs7 = wc_PKCS7_New(HEAP_HINT, devId); + if (pkcs7 == NULL) + return -12109; + + ret = wc_PKCS7_InitWithCert(pkcs7, testVectors[i].cert, + (word32)testVectors[i].certSz); + + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12110; + } + + /* load CA certificate, if present */ + if (testVectors[i].caCert != NULL) { + ret = wc_PKCS7_AddCertificate(pkcs7, testVectors[i].caCert, + (word32)testVectors[i].caCertSz); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12111; + } + } + + pkcs7->rng = &rng; + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->hashOID = testVectors[i].hashOID; + pkcs7->encryptOID = testVectors[i].signOID; + pkcs7->privateKey = testVectors[i].privateKey; + pkcs7->privateKeySz = testVectors[i].privateKeySz; + pkcs7->signedAttribs = testVectors[i].signedAttribs; + pkcs7->signedAttribsSz = testVectors[i].signedAttribsSz; + + /* optional custom contentType, default is DATA, + overrides contentOID if set */ + if (testVectors[i].contentType != NULL) { + ret = wc_PKCS7_SetContentType(pkcs7, testVectors[i].contentType, + testVectors[i].contentTypeSz); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12112; + } + } + + /* set SignerIdentifier to use SubjectKeyIdentifier if desired, + default is IssuerAndSerialNumber */ + if (testVectors[i].sidType == CMS_SKID) { + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12113; + } + } + + /* 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 -12114; + } + } + + /* 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; + + transId[0] = 0x13; + transId[1] = sizeof(digest) * 2; + + #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 -12115; + } + 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 -12116; + } + 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]); + } + } + + /* enable detached signature generation, if set */ + if (testVectors[i].detachedSignature == 1) { + ret = wc_PKCS7_SetDetached(pkcs7, 1); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12117; + } + } + + encodedSz = wc_PKCS7_EncodeSignedData(pkcs7, out, outSz); + if (encodedSz < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12118; + } + + #ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* write PKCS#7 to output file for more testing */ + file = XFOPEN(testVectors[i].outFileName, "wb"); + if (!file) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12119; + } + ret = (int)XFWRITE(out, 1, encodedSz, file); + XFCLOSE(file); + if (ret != (int)encodedSz) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12120; + } + #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + + wc_PKCS7_Free(pkcs7); + + pkcs7 = wc_PKCS7_New(HEAP_HINT, devId); + if (pkcs7 == NULL) + return -12121; + wc_PKCS7_InitWithCert(pkcs7, NULL, 0); + + if (testVectors[i].detachedSignature == 1) { + /* set content for verifying detached signatures */ + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + } + + ret = wc_PKCS7_VerifySignedData(pkcs7, out, outSz); + if (ret < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12122; + } + + /* verify contentType extracted successfully for custom content types */ + if (testVectors[i].contentTypeSz > 0) { + if (pkcs7->contentTypeSz != testVectors[i].contentTypeSz) { + return -12123; + } else if (XMEMCMP(pkcs7->contentType, testVectors[i].contentType, + pkcs7->contentTypeSz) != 0) { + return -12124; + } + } + + if (pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12125; + } + + { + /* check getting signed attributes */ + #ifndef NO_SHA + byte buf[(WC_SHA_DIGEST_SIZE + 1) * 2 + 1]; + #else + byte buf[(WC_SHA256_DIGEST_SIZE + 1) * 2 + 1]; + #endif + byte* oidPt = transIdOid + 2; /* skip object id tag and size */ + int oidSz = (int)sizeof(transIdOid) - 2; + int bufSz = 0; + + if (testVectors[i].signedAttribs != NULL && + wc_PKCS7_GetAttributeValue(pkcs7, oidPt, oidSz, + NULL, (word32*)&bufSz) != LENGTH_ONLY_E) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12126; + } + + if (bufSz > (int)sizeof(buf)) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12127; + } + + bufSz = wc_PKCS7_GetAttributeValue(pkcs7, oidPt, oidSz, + buf, (word32*)&bufSz); + if ((testVectors[i].signedAttribs != NULL && bufSz < 0) || + (testVectors[i].signedAttribs == NULL && bufSz > 0)) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12128; + } + } + + #ifdef PKCS7_OUTPUT_TEST_BUNDLES + file = XFOPEN("./pkcs7cert.der", "wb"); + if (!file) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12129; + } + ret = (int)XFWRITE(pkcs7->singleCert, 1, pkcs7->singleCertSz, file); + XFCLOSE(file); + #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + + wc_PKCS7_Free(pkcs7); + } + + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeRng(&rng); if (ret > 0) return 0; + (void)rsaClientCertBuf; + (void)rsaClientCertBufSz; + (void)rsaClientPrivKeyBuf; + (void)rsaClientPrivKeyBufSz; + (void)rsaServerCertBuf; + (void)rsaServerCertBufSz; + (void)rsaServerPrivKeyBuf; + (void)rsaServerPrivKeyBufSz; + (void)rsaCaCertBuf; + (void)rsaCaCertBufSz; + (void)rsaCaPrivKeyBuf; + (void)rsaCaPrivKeyBufSz; + (void)eccClientCertBuf; + (void)eccClientCertBufSz; + (void)eccClientPrivKeyBuf; + (void)eccClientPrivKeyBufSz; + return ret; } + +static int pkcs7signed_run_SingleShotVectors( + byte* rsaClientCertBuf, word32 rsaClientCertBufSz, + byte* rsaClientPrivKeyBuf, word32 rsaClientPrivKeyBufSz, + byte* rsaServerCertBuf, word32 rsaServerCertBufSz, + byte* rsaServerPrivKeyBuf, word32 rsaServerPrivKeyBufSz, + byte* rsaCaCertBuf, word32 rsaCaCertBufSz, + byte* rsaCaPrivKeyBuf, word32 rsaCaPrivKeyBufSz, + byte* eccClientCertBuf, word32 eccClientCertBufSz, + byte* eccClientPrivKeyBuf, word32 eccClientPrivKeyBufSz) +{ + int ret, testSz, i; + int encodedSz; + byte* out; + word32 outSz; + WC_RNG rng; + PKCS7* pkcs7; +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + XFILE file; +#endif + + const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 + }; + +#if defined(WOLFSSL_AES_256) && !defined(NO_PKCS7_ENCRYPTED_DATA) + byte aes256Key[] = { + 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 + + static byte messageTypeOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x02 }; + static byte messageType[] = { 0x13, 2, '1', '9' }; + + PKCS7Attrib attribs[] = + { + { messageTypeOid, sizeof(messageTypeOid), messageType, + sizeof(messageType) }, + }; + + const pkcs7SignedVector testVectors[] = + { +#ifndef NO_RSA + #ifndef NO_SHA256 + /* Signed FirmwarePkgData, RSA, SHA256, no attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedFirmwarePkgData_RSA_SHA256_noattr.der", 0, NULL, 0, 0, + 0, 0, NULL, 0, NULL, 0, 0}, + + /* Signed FirmwarePkgData, RSA, SHA256, attrs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedFirmwarePkgData_RSA_SHA256.der", 0, NULL, 0, 0, 0, 0, + NULL, 0, NULL, 0, 0}, + + /* Signed FirmwarePkgData, RSA, SHA256, SubjectKeyIdentifier, attrs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedFirmwarePkgData_RSA_SHA256_SKID.der", 0, NULL, + 0, CMS_SKID, 0, 0, NULL, 0, NULL, 0, 0}, + + /* Signed FirmwraePkgData, RSA, SHA256, server cert and ca cert, attr */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaServerPrivKeyBuf, + rsaServerPrivKeyBufSz, rsaServerCertBuf, rsaServerCertBufSz, + rsaCaCertBuf, rsaCaCertBufSz, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedFirmwarePkgData_RSA_SHA256_with_ca_cert.der", 0, NULL, + 0, 0, 0, 0, NULL, 0, NULL, 0, 0}, + + #if defined(WOLFSSL_AES_256) && !defined(NO_PKCS7_ENCRYPTED_DATA) + /* Signed Encrypted FirmwarePkgData, RSA, SHA256, no attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256_noattr.der", 0, + NULL, 0, 0, AES256CBCb, 1, aes256Key, sizeof(aes256Key), NULL, 0, 0}, + + /* Signed Encrypted FirmwarePkgData, RSA, SHA256, attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256.der", 0, + NULL, 0, 0, AES256CBCb, 1, aes256Key, sizeof(aes256Key), + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), 0}, + #endif /* WOLFSSL_AES_256 && !NO_PKCS7_ENCRYPTED_DATA */ + + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + /* Signed Compressed FirmwarePkgData, RSA, SHA256, no attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedCompressedFirmwarePkgData_RSA_SHA256_noattr.der", 0, + NULL, 0, 0, 0, 2, NULL, 0, NULL, 0, 0}, + + /* Signed Compressed FirmwarePkgData, RSA, SHA256, attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedCompressedFirmwarePkgData_RSA_SHA256.der", 0, + NULL, 0, 0, 0, 2, NULL, 0, NULL, 0, 0}, + + #ifndef NO_PKCS7_ENCRYPTED_DATA + /* Signed Encrypted Compressed FirmwarePkgData, RSA, SHA256, + no attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256_noattr.der", + 0, NULL, 0, 0, AES256CBCb, 3, aes256Key, sizeof(aes256Key), NULL, + 0, 0}, + + /* Signed Encrypted Compressed FirmwarePkgData, RSA, SHA256, + attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256.der", + 0, NULL, 0, 0, AES256CBCb, 3, aes256Key, sizeof(aes256Key), + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), 0}, + #endif /* !NO_PKCS7_ENCRYPTED_DATA */ + + #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + + #endif /* NO_SHA256 */ +#endif /* NO_RSA */ + +#ifdef HAVE_ECC + #ifndef NO_SHA256 + /* Signed FirmwarePkgData, ECDSA, SHA256, no attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedFirmwarePkgData_ECDSA_SHA256_noattr.der", 0, NULL, + 0, 0, 0, 0, NULL, 0, NULL, 0, 0}, + + /* Signed FirmwarePkgData, ECDSA, SHA256, attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedFirmwarePkgData_ECDSA_SHA256.der", 0, NULL, + 0, 0, 0, 0, NULL, 0, NULL, 0, 0}, + + /* Signed FirmwarePkgData, ECDSA, SHA256, SubjectKeyIdentifier, attr */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedFirmwarePkgData_ECDSA_SHA256_SKID.der", 0, NULL, + 0, CMS_SKID, 0, 0, NULL, 0, NULL, 0, 0}, + + #if defined(WOLFSSL_AES_256) && !defined(NO_PKCS7_ENCRYPTED_DATA) + /* Signed Encrypted FirmwarePkgData, ECDSA, SHA256, no attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256_noattr.der", 0, NULL, + 0, 0, AES256CBCb, 1, aes256Key, sizeof(aes256Key), NULL, 0, 0}, + + /* Signed Encrypted FirmwarePkgData, ECDSA, SHA256, attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256.der", 0, NULL, + 0, 0, AES256CBCb, 1, aes256Key, sizeof(aes256Key), + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), 0}, + #endif /* WOLFSSL_AES_256 && !NO_PKCS7_ENCRYPTED_DATA */ + + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + /* Signed Compressed FirmwarePkgData, ECDSA, SHA256, no attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der", 0, NULL, + 0, 0, 0, 2, NULL, 0, NULL, 0, 0}, + + /* Signed Compressed FirmwarePkgData, ECDSA, SHA256, attrib */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256.der", 0, NULL, + 0, 0, 0, 2, NULL, 0, NULL, 0, 0}, + + #ifndef NO_PKCS7_ENCRYPTED_DATA + /* Signed Encrypted Compressed FirmwarePkgData, ECDSA, SHA256, + no attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der", + 0, NULL, 0, 0, AES256CBCb, 3, aes256Key, sizeof(aes256Key), NULL, + 0, 0}, + + /* Signed Encrypted Compressed FirmwarePkgData, ECDSA, SHA256, + attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256.der", + 0, NULL, 0, 0, AES256CBCb, 3, aes256Key, sizeof(aes256Key), + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), 0}, + #endif /* !NO_PKCS7_ENCRYPTED_DATA */ + + #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + + #endif /* NO_SHA256 */ +#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 -12130; + + XMEMSET(out, 0, outSz); + + ret = wc_PKCS7_PadData((byte*)data, sizeof(data), out, outSz, 16); + if (ret < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -12131; + } + +#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 -12132; + } + + for (i = 0; i < testSz; i++) { + pkcs7 = wc_PKCS7_New(HEAP_HINT, devId); + if (pkcs7 == NULL) + return -12133; + + ret = wc_PKCS7_InitWithCert(pkcs7, testVectors[i].cert, + (word32)testVectors[i].certSz); + + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12134; + } + + /* load CA certificate, if present */ + if (testVectors[i].caCert != NULL) { + ret = wc_PKCS7_AddCertificate(pkcs7, testVectors[i].caCert, + (word32)testVectors[i].caCertSz); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12135; + } + } + + /* set SignerIdentifier to use SubjectKeyIdentifier if desired, + default is IssuerAndSerialNumber */ + if (testVectors[i].sidType == CMS_SKID) { + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12136; + } + } + + if (testVectors[i].encCompFlag == 0) { + + /* encode Signed FirmwarePkgData */ + encodedSz = wc_PKCS7_EncodeSignedFPD(pkcs7, + testVectors[i].privateKey, testVectors[i].privateKeySz, + testVectors[i].signOID, testVectors[i].hashOID, + (byte*)testVectors[i].content, testVectors[i].contentSz, + testVectors[i].signedAttribs, + testVectors[i].signedAttribsSz, out, outSz); + + if (encodedSz < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12137; + } + + #ifndef NO_PKCS7_ENCRYPTED_DATA + + } else if (testVectors[i].encCompFlag == 1) { + + /* encode Signed Encrypted FirmwarePkgData */ + encodedSz = wc_PKCS7_EncodeSignedEncryptedFPD(pkcs7, + testVectors[i].encryptKey, testVectors[i].encryptKeySz, + testVectors[i].privateKey, testVectors[i].privateKeySz, + testVectors[i].encryptOID, testVectors[i].signOID, + testVectors[i].hashOID, (byte*)testVectors[i].content, + testVectors[i].contentSz, testVectors[i].unprotectedAttribs, + testVectors[i].unprotectedAttribsSz, + testVectors[i].signedAttribs, + testVectors[i].signedAttribsSz, out, outSz); + + if (encodedSz <= 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12138; + } + #endif + + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + } else if (testVectors[i].encCompFlag == 2) { + + /* encode Signed Compressed FirmwarePkgData */ + encodedSz = wc_PKCS7_EncodeSignedCompressedFPD(pkcs7, + testVectors[i].privateKey, testVectors[i].privateKeySz, + testVectors[i].signOID, testVectors[i].hashOID, + (byte*)testVectors[i].content, testVectors[i].contentSz, + testVectors[i].signedAttribs, + testVectors[i].signedAttribsSz, out, outSz); + + if (encodedSz <= 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12139; + } + + #ifndef NO_PKCS7_ENCRYPTED_DATA + } else if (testVectors[i].encCompFlag == 3) { + + /* encode Signed Encrypted Compressed FirmwarePkgData */ + encodedSz = wc_PKCS7_EncodeSignedEncryptedCompressedFPD(pkcs7, + testVectors[i].encryptKey, testVectors[i].encryptKeySz, + testVectors[i].privateKey, testVectors[i].privateKeySz, + testVectors[i].encryptOID, testVectors[i].signOID, + testVectors[i].hashOID, (byte*)testVectors[i].content, + testVectors[i].contentSz, testVectors[i].unprotectedAttribs, + testVectors[i].unprotectedAttribsSz, + testVectors[i].signedAttribs, + testVectors[i].signedAttribsSz, out, outSz); + + if (encodedSz <= 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12140; + } + + #endif /* NO_PKCS7_ENCRYPTED_DATA */ + #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + + } else { + /* unsupported SignedData single-shot combination */ + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12141; + } + + #ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* write PKCS#7 to output file for more testing */ + file = XFOPEN(testVectors[i].outFileName, "wb"); + if (!file) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12142; + } + ret = (int)XFWRITE(out, 1, encodedSz, file); + XFCLOSE(file); + if (ret != (int)encodedSz) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12143; + } + #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + + wc_PKCS7_Free(pkcs7); + + pkcs7 = wc_PKCS7_New(HEAP_HINT, devId); + if (pkcs7 == NULL) + return -12144; + 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 -12145; + } +#ifndef NO_PKCS7_STREAM + { + word32 z; + for (z = 0; z < outSz && ret != 0; z++) { + ret = wc_PKCS7_VerifySignedData(pkcs7, out + z, 1); + if (ret < 0 && ret != WC_PKCS7_WANT_READ_E) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + printf("unexpected error %d\n", ret); + return -12146; + } + } + } +#endif + + if (pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12147; + } + + if (testVectors[i].encCompFlag == 0) { + /* verify decoded content matches expected */ + if ((pkcs7->contentSz != testVectors[i].contentSz) || + XMEMCMP(pkcs7->content, testVectors[i].content, + pkcs7->contentSz)) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12148; + } + + } + #ifndef NO_PKCS7_ENCRYPTED_DATA + else if (testVectors[i].encCompFlag == 1) { + + /* decrypt inner encryptedData */ + pkcs7->encryptionKey = testVectors[i].encryptKey; + pkcs7->encryptionKeySz = testVectors[i].encryptKeySz; + + ret = wc_PKCS7_DecodeEncryptedData(pkcs7, pkcs7->content, + pkcs7->contentSz, out, outSz); + if (ret < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12149; + } + + /* compare decrypted to expected */ + if (((word32)ret != testVectors[i].contentSz) || + XMEMCMP(out, testVectors[i].content, ret)) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12150; + } + } + #endif + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + else if (testVectors[i].encCompFlag == 2) { + + /* decompress inner compressedData */ + ret = wc_PKCS7_DecodeCompressedData(pkcs7, pkcs7->content, + pkcs7->contentSz, out, outSz); + if (ret < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12151; + } + + /* compare decompressed to expected */ + if (((word32)ret != testVectors[i].contentSz) || + XMEMCMP(out, testVectors[i].content, ret)) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12152; + } + } + #ifndef NO_PKCS7_ENCRYPTED_DATA + else if (testVectors[i].encCompFlag == 3) { + + byte* encryptedTmp; + int encryptedTmpSz; + + encryptedTmpSz = FOURK_BUF; + encryptedTmp = (byte*)XMALLOC(encryptedTmpSz, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedTmp == NULL) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12153; + } + + XMEMSET(encryptedTmp, 0, encryptedTmpSz); + + /* decrypt inner encryptedData */ + pkcs7->encryptionKey = testVectors[i].encryptKey; + pkcs7->encryptionKeySz = testVectors[i].encryptKeySz; + + encryptedTmpSz = wc_PKCS7_DecodeEncryptedData(pkcs7, pkcs7->content, + pkcs7->contentSz, encryptedTmp, + encryptedTmpSz); + + if (encryptedTmpSz < 0) { + XFREE(encryptedTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12154; + } + + /* decompress inner compressedData */ + ret = wc_PKCS7_DecodeCompressedData(pkcs7, encryptedTmp, + encryptedTmpSz, out, outSz); + if (ret < 0) { + XFREE(encryptedTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12155; + } + + XFREE(encryptedTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + /* compare decompressed to expected */ + if (((word32)ret != testVectors[i].contentSz) || + XMEMCMP(out, testVectors[i].content, ret)) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -12156; + } + } + #endif /* NO_PKCS7_ENCRYPTED_DATA */ + #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + + wc_PKCS7_Free(pkcs7); + } + + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeRng(&rng); + + if (ret > 0) + return 0; + + (void)eccClientCertBuf; + (void)eccClientCertBufSz; + (void)eccClientPrivKeyBuf; + (void)eccClientPrivKeyBufSz; + + (void)rsaClientCertBuf; + (void)rsaClientCertBufSz; + (void)rsaClientPrivKeyBuf; + (void)rsaClientPrivKeyBufSz; + (void)rsaServerCertBuf; + (void)rsaServerCertBufSz; + (void)rsaServerPrivKeyBuf; + (void)rsaServerPrivKeyBufSz; + (void)rsaCaCertBuf; + (void)rsaCaCertBufSz; + (void)rsaCaPrivKeyBuf; + (void)rsaCaPrivKeyBufSz; + + return ret; +} + + int pkcs7signed_test(void) { int ret = 0; - FILE* file; - byte* certDer; - byte* keyDer; - byte* out; - char data[] = "Hello World"; - word32 dataSz, outSz, certDerSz, keyDerSz; - PKCS7 msg; - RNG rng; + byte* rsaClientCertBuf = NULL; + byte* rsaServerCertBuf = NULL; + byte* rsaCaCertBuf = NULL; + byte* eccClientCertBuf = NULL; + byte* rsaClientPrivKeyBuf = NULL; + byte* rsaServerPrivKeyBuf = NULL; + byte* rsaCaPrivKeyBuf = NULL; + byte* eccClientPrivKeyBuf = NULL; - byte transIdOid[] = - { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, - 0x09, 0x07 }; - byte messageTypeOid[] = - { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, - 0x09, 0x02 }; - byte senderNonceOid[] = - { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, - 0x09, 0x05 }; - byte transId[(SHA_DIGEST_SIZE + 1) * 2 + 1]; - byte messageType[] = { 0x13, 2, '1', '9' }; - byte senderNonce[PKCS7_NONCE_SZ + 2]; + word32 rsaClientCertBufSz = 0; + word32 rsaServerCertBufSz = 0; + word32 rsaCaCertBufSz = 0; + word32 eccClientCertBufSz = 0; + word32 rsaClientPrivKeyBufSz = 0; + word32 rsaServerPrivKeyBufSz = 0; + word32 rsaCaPrivKeyBufSz = 0; + word32 eccClientPrivKeyBufSz = 0; - PKCS7Attrib attribs[] = - { - { transIdOid, sizeof(transIdOid), - transId, sizeof(transId) - 1 }, /* take off the null */ - { messageTypeOid, sizeof(messageTypeOid), - messageType, sizeof(messageType) }, - { senderNonceOid, sizeof(senderNonceOid), - senderNonce, sizeof(senderNonce) } - }; +#ifndef NO_RSA + /* read client RSA cert and key in DER format */ + rsaClientCertBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (rsaClientCertBuf == NULL) + ret = -12200; - dataSz = (word32) strlen(data); - outSz = FOURK_BUF; - - certDer = (byte*)malloc(FOURK_BUF); - if (certDer == NULL) - return -207; - keyDer = (byte*)malloc(FOURK_BUF); - if (keyDer == NULL) { - free(certDer); - return -208; - } - out = (byte*)malloc(FOURK_BUF); - if (out == NULL) { - free(certDer); - free(keyDer); - return -209; + rsaClientPrivKeyBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (ret == 0 && rsaClientPrivKeyBuf == NULL) { + ret = -12201; } - /* read in DER cert of recipient, into cert of size certSz */ - file = fopen(clientCert, "rb"); - if (!file) { - free(certDer); - free(keyDer); - free(out); - 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); + rsaClientCertBufSz = FOURK_BUF; + rsaClientPrivKeyBufSz = FOURK_BUF; - file = fopen(clientKey, "rb"); - if (!file) { - free(certDer); - free(keyDer); - free(out); - 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); + /* read server RSA cert and key in DER format */ + rsaServerCertBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (ret == 0 && rsaServerCertBuf == NULL) + ret = -12202; - ret = wc_InitRng(&rng); - if (ret != 0) { - free(certDer); - free(keyDer); - free(out); - return -210; + rsaServerPrivKeyBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (ret == 0 && rsaServerPrivKeyBuf == NULL) { + ret = -12203; } - senderNonce[0] = 0x04; - senderNonce[1] = PKCS7_NONCE_SZ; + rsaServerCertBufSz = FOURK_BUF; + rsaServerPrivKeyBufSz = FOURK_BUF; - ret = wc_RNG_GenerateBlock(&rng, &senderNonce[2], PKCS7_NONCE_SZ); - if (ret != 0) { - free(certDer); - free(keyDer); - free(out); - return -211; + /* read CA RSA cert and key in DER format, for use with server cert */ + rsaCaCertBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (ret == 0 && rsaCaCertBuf == NULL) + ret = -12204; + + rsaCaPrivKeyBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (ret == 0 && rsaCaPrivKeyBuf == NULL) { + ret = -12205; } - 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; - { - Sha sha; - byte digest[SHA_DIGEST_SIZE]; - int i,j; + rsaCaCertBufSz = FOURK_BUF; + rsaCaPrivKeyBufSz = FOURK_BUF; +#endif /* NO_RSA */ - transId[0] = 0x13; - transId[1] = SHA_DIGEST_SIZE * 2; - - ret = wc_InitSha(&sha); - if (ret != 0) { - free(certDer); - free(keyDer); - free(out); - return -4003; - } - 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]); - } +#ifdef HAVE_ECC + /* read client ECC cert and key in DER format */ + eccClientCertBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (ret == 0 && eccClientCertBuf == NULL) { + ret = -12206; } - ret = wc_PKCS7_EncodeSignedData(&msg, out, outSz); + + eccClientPrivKeyBuf =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (ret == 0 && eccClientPrivKeyBuf == NULL) { + ret = -12207; + } + + eccClientCertBufSz = FOURK_BUF; + eccClientPrivKeyBufSz = FOURK_BUF; +#endif /* HAVE_ECC */ + + if (ret >= 0) + ret = pkcs7_load_certs_keys(rsaClientCertBuf, &rsaClientCertBufSz, + rsaClientPrivKeyBuf, &rsaClientPrivKeyBufSz, + rsaServerCertBuf, &rsaServerCertBufSz, + rsaServerPrivKeyBuf, &rsaServerPrivKeyBufSz, + rsaCaCertBuf, &rsaCaCertBufSz, + rsaCaPrivKeyBuf, &rsaCaPrivKeyBufSz, + eccClientCertBuf, &eccClientCertBufSz, + eccClientPrivKeyBuf, &eccClientPrivKeyBufSz); if (ret < 0) { - free(certDer); - free(keyDer); - free(out); - wc_PKCS7_Free(&msg); - return -212; - } - else - outSz = ret; - - /* write PKCS#7 to output file for more testing */ - file = fopen("./pkcs7signedData.der", "wb"); - if (!file) { - free(certDer); - free(keyDer); - free(out); - wc_PKCS7_Free(&msg); - return -213; - } - ret = (int)fwrite(out, 1, outSz, file); - fclose(file); - if (ret != (int)outSz) { - free(certDer); - free(keyDer); - free(out); - wc_PKCS7_Free(&msg); - return -218; + ret = -12208; } - wc_PKCS7_Free(&msg); - wc_PKCS7_InitWithCert(&msg, NULL, 0); + if (ret >= 0) + ret = pkcs7signed_run_vectors(rsaClientCertBuf, (word32)rsaClientCertBufSz, + rsaClientPrivKeyBuf, (word32)rsaClientPrivKeyBufSz, + rsaServerCertBuf, (word32)rsaServerCertBufSz, + rsaServerPrivKeyBuf, (word32)rsaServerPrivKeyBufSz, + rsaCaCertBuf, (word32)rsaCaCertBufSz, + rsaCaPrivKeyBuf, (word32)rsaCaPrivKeyBufSz, + eccClientCertBuf, (word32)eccClientCertBufSz, + eccClientPrivKeyBuf, (word32)eccClientPrivKeyBufSz); - ret = wc_PKCS7_VerifySignedData(&msg, out, outSz); - if (ret < 0) { - free(certDer); - free(keyDer); - free(out); - wc_PKCS7_Free(&msg); - return -214; - } + if (ret >= 0) + ret = pkcs7signed_run_SingleShotVectors( + rsaClientCertBuf, (word32)rsaClientCertBufSz, + rsaClientPrivKeyBuf, (word32)rsaClientPrivKeyBufSz, + rsaServerCertBuf, (word32)rsaServerCertBufSz, + rsaServerPrivKeyBuf, (word32)rsaServerPrivKeyBufSz, + rsaCaCertBuf, (word32)rsaCaCertBufSz, + rsaCaPrivKeyBuf, (word32)rsaCaPrivKeyBufSz, + eccClientCertBuf, (word32)eccClientCertBufSz, + eccClientPrivKeyBuf, (word32)eccClientPrivKeyBufSz); - if (msg.singleCert == NULL || msg.singleCertSz == 0) { - free(certDer); - free(keyDer); - free(out); - wc_PKCS7_Free(&msg); - return -215; - } +#ifndef NO_AES + if (ret >= 0) + ret = pkcs7callback_test( + rsaClientCertBuf, (word32)rsaClientCertBufSz, + rsaClientPrivKeyBuf, (word32)rsaClientPrivKeyBufSz); +#endif - file = fopen("./pkcs7cert.der", "wb"); - if (!file) { - free(certDer); - free(keyDer); - free(out); - wc_PKCS7_Free(&msg); - return -216; - } - ret = (int)fwrite(msg.singleCert, 1, msg.singleCertSz, file); - fclose(file); - - free(certDer); - free(keyDer); - free(out); - wc_PKCS7_Free(&msg); - - wc_FreeRng(&rng); - - if (ret > 0) - return 0; + XFREE(rsaClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaServerCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaServerPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaCaCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaCaPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccClientPrivKeyBuf, 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 -12300; + + 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 -12301; + + 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 -12302; + ret = randNum(&a, j, &rng, NULL); + if (ret != 0) + return -12303; + ret = randNum(&b, j, &rng, NULL); + if (ret != 0) + return -12304; + ret = wc_RNG_GenerateBlock(&rng, (byte*)&d, sizeof(d)); + if (ret != 0) + return -12305; + d &= MP_MASK; + + /* Ensure sqrmod produce same result as mulmod. */ + ret = mp_sqrmod(&a, &p, &r1); + if (ret != 0) + return -12306; + ret = mp_mulmod(&a, &a, &p, &r2); + if (ret != 0) + return -12307; + if (mp_cmp(&r1, &r2) != 0) + return -12308; + + /* Ensure add with mod produce same result as sub with mod. */ + ret = mp_addmod(&a, &b, &p, &r1); + if (ret != 0) + return -12309; + b.sign ^= 1; + ret = mp_submod(&a, &b, &p, &r2); + if (ret != 0) + return -12310; + if (mp_cmp(&r1, &r2) != 0) + return -12311; + + /* Ensure add digit produce same result as sub digit. */ + ret = mp_add_d(&a, d, &r1); + if (ret != 0) + return -12312; + ret = mp_sub_d(&r1, d, &r2); + if (ret != 0) + return -12313; + if (mp_cmp(&a, &r2) != 0) + return -12314; + + /* 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 -12315; + 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 -12316; + if (!mp_iszero(&p)) + return -12317; + mp_rshb(&r1, k); + if (mp_cmp(&a, &r1) != 0) + return -12318; + } + } + } + + /* Check that setting a 32-bit digit works. */ + d &= 0xffffffff; + mp_set_int(&a, d); + if (a.used != 1 || a.dp[0] != d) + return -12319; + + /* 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 -12320; + } +#endif + +done: + mp_clear(&p); + mp_clear(&r2); + mp_clear(&r1); + mp_clear(&b); + mp_clear(&a); + wc_FreeRng(&rng); + return ret; +} +#endif + + +#if defined(WOLFSSL_PUBLIC_MP) && defined(WOLFSSL_KEY_GEN) + +typedef struct pairs_t { + const unsigned char* coeff; + int coeffSz; + int exp; +} pairs_t; + + +/* +n =p1p2p3, where pi = ki(p1−1)+1 with (k2,k3) = (173,293) +p1 = 2^192 * 0x000000000000e24fd4f6d6363200bf2323ec46285cac1d3a + + 2^0 * 0x0b2488b0c29d96c5e67f8bec15b54b189ae5636efe89b45b +*/ + +static const unsigned char c192a[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x4f, + 0xd4, 0xf6, 0xd6, 0x36, 0x32, 0x00, 0xbf, 0x23, + 0x23, 0xec, 0x46, 0x28, 0x5c, 0xac, 0x1d, 0x3a +}; +static const unsigned char c0a[] = +{ + 0x0b, 0x24, 0x88, 0xb0, 0xc2, 0x9d, 0x96, 0xc5, + 0xe6, 0x7f, 0x8b, 0xec, 0x15, 0xb5, 0x4b, 0x18, + 0x9a, 0xe5, 0x63, 0x6e, 0xfe, 0x89, 0xb4, 0x5b +}; + +static const pairs_t ecPairsA[] = +{ + {c192a, sizeof(c192a), 192}, + {c0a, sizeof(c0a), 0} +}; + +static const int kA[] = {173, 293}; + +static const unsigned char controlPrime[] = { + 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 +}; + +static const unsigned char testOne[] = { 1 }; + + +static int GenerateNextP(mp_int* p1, mp_int* p2, int k) +{ + int ret; + mp_int ki; + + ret = mp_init(&ki); + if (ret == 0) + ret = mp_set(&ki, k); + if (ret == 0) + ret = mp_sub_d(p1, 1, p2); + if (ret == 0) + ret = mp_mul(p2, &ki, p2); + if (ret == 0) + ret = mp_add_d(p2, 1, p2); + mp_clear(&ki); + + return ret; +} + + +static int GenerateP(mp_int* p1, mp_int* p2, mp_int* p3, + const pairs_t* ecPairs, int ecPairsSz, + const int* k) +{ + mp_int x,y; + int ret, i; + + ret = mp_init(&x); + if (ret == 0) { + ret = mp_init(&y); + if (ret != 0) { + mp_clear(&x); + return MP_MEM; + } + } + for (i = 0; ret == 0 && i < ecPairsSz; i++) { + ret = mp_read_unsigned_bin(&x, ecPairs[i].coeff, ecPairs[i].coeffSz); + /* p1 = 2^exp */ + if (ret == 0) + ret = mp_2expt(&y, ecPairs[i].exp); + /* p1 = p1 * m */ + if (ret == 0) + ret = mp_mul(&x, &y, &x); + /* p1 += */ + if (ret == 0) + ret = mp_add(p1, &x, p1); + mp_zero(&x); + mp_zero(&y); + } + mp_clear(&x); + mp_clear(&y); + + if (ret == 0) + ret = GenerateNextP(p1, p2, k[0]); + if (ret == 0) + ret = GenerateNextP(p1, p3, k[1]); + + return ret; +} + +int prime_test(void) +{ + mp_int n, p1, p2, p3; + int ret, isPrime = 0; + WC_RNG rng; + + ret = wc_InitRng(&rng); + if (ret == 0) + ret = mp_init_multi(&n, &p1, &p2, &p3, NULL, NULL); + if (ret == 0) + ret = GenerateP(&p1, &p2, &p3, + ecPairsA, sizeof(ecPairsA) / sizeof(ecPairsA[0]), kA); + if (ret == 0) + ret = mp_mul(&p1, &p2, &n); + if (ret == 0) + ret = mp_mul(&n, &p3, &n); + if (ret != 0) + return -12400; + + /* Check the old prime test using the number that false positives. + * This test result should indicate as not prime. */ + ret = mp_prime_is_prime(&n, 40, &isPrime); + if (ret != 0) + return -12401; + if (isPrime) + return -12402; + + /* This test result should fail. It should indicate the value as prime. */ + ret = mp_prime_is_prime(&n, 8, &isPrime); + if (ret != 0) + return -12403; + if (!isPrime) + return -12404; + + /* This test result should indicate the value as not prime. */ + ret = mp_prime_is_prime_ex(&n, 8, &isPrime, &rng); + if (ret != 0) + return -12405; + if (isPrime) + return -12406; + + ret = mp_read_unsigned_bin(&n, controlPrime, sizeof(controlPrime)); + if (ret != 0) + return -12407; + + /* This test result should indicate the value as prime. */ + ret = mp_prime_is_prime_ex(&n, 8, &isPrime, &rng); + if (ret != 0) + return -12408; + if (!isPrime) + return -12409; + + /* This test result should indicate the value as prime. */ + isPrime = -1; + ret = mp_prime_is_prime(&n, 8, &isPrime); + if (ret != 0) + return -12410; + if (!isPrime) + return -12411; + + ret = mp_read_unsigned_bin(&n, testOne, sizeof(testOne)); + if (ret != 0) + return -12412; + + /* This test result should indicate the value as not prime. */ + ret = mp_prime_is_prime_ex(&n, 8, &isPrime, &rng); + if (ret != 0) + return -12413; + if (isPrime) + return -12414; + + ret = mp_prime_is_prime(&n, 8, &isPrime); + if (ret != 0) + return -12415; + if (isPrime) + return -12416; + + mp_clear(&p3); + mp_clear(&p2); + mp_clear(&p1); + mp_clear(&n); + wc_FreeRng(&rng); + + return 0; +} + +#endif /* WOLFSSL_PUBLIC_MP */ + + +#if defined(ASN_BER_TO_DER) && \ + (defined(WOLFSSL_TEST_CERT) || defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL)) +/* wc_BerToDer is only public facing in the case of test cert or opensslextra */ +typedef struct berDerTestData { + const byte *in; + word32 inSz; + const byte *out; + word32 outSz; +} berDerTestData; + +int berder_test(void) +{ + int ret; + int i; + word32 len = 0, l; + byte out[32]; + static const byte good1_in[] = { 0x30, 0x80, 0x00, 0x00 }; + static const byte good1_out[] = { 0x30, 0x00 }; + static const byte good2_in[] = { 0x30, 0x80, 0x02, 0x01, 0x01, 0x00, 0x00 }; + static const byte good2_out[] = { 0x30, 0x03, 0x02, 0x01, 0x01 }; + static const byte good3_in[] = { + 0x24, 0x80, 0x04, 0x01, 0x01, 0x00, 0x00 + }; + static const byte good3_out[] = { 0x04, 0x1, 0x01 }; + static const byte good4_in[] = { + 0x30, 0x80, + 0x02, 0x01, 0x01, + 0x30, 0x80, + 0x24, 0x80, + 0x04, 0x01, 0x01, + 0x04, 0x02, 0x02, 0x03, + 0x00, 0x00, + 0x06, 0x01, 0x01, + 0x00, 0x00, + 0x31, 0x80, + 0x06, 0x01, 0x01, + 0x00, 0x00, + 0x00, 0x00, + }; + static const byte good4_out[] = { + 0x30, 0x12, + 0x02, 0x01, 0x01, + 0x30, 0x08, + 0x04, 0x03, 0x01, 0x02, 0x03, + 0x06, 0x01, 0x01, + 0x31, 0x03, + 0x06, 0x01, 0x01 + }; + static const byte good5_in[] = { 0x30, 0x03, 0x02, 0x01, 0x01 }; + + berDerTestData testData[] = { + { good1_in, sizeof(good1_in), good1_out, sizeof(good1_out) }, + { good2_in, sizeof(good2_in), good2_out, sizeof(good2_out) }, + { good3_in, sizeof(good3_in), good3_out, sizeof(good3_out) }, + { good4_in, sizeof(good4_in), good4_out, sizeof(good4_out) }, + { good5_in, sizeof(good5_in), good5_in , sizeof(good5_in ) }, + }; + + for (i = 0; i < (int)(sizeof(testData) / sizeof(*testData)); i++) { + ret = wc_BerToDer(testData[i].in, testData[i].inSz, NULL, &len); + if (ret != LENGTH_ONLY_E) + return -12500 - i; + if (len != testData[i].outSz) + return -12510 - i; + len = testData[i].outSz; + ret = wc_BerToDer(testData[i].in, testData[i].inSz, out, &len); + if (ret != 0) + return -12520 - i; + if (XMEMCMP(out, testData[i].out, len) != 0) + return -12530 - i; + + for (l = 1; l < testData[i].inSz; l++) { + ret = wc_BerToDer(testData[i].in, l, NULL, &len); + if (ret != ASN_PARSE_E) + return -12540; + len = testData[i].outSz; + ret = wc_BerToDer(testData[i].in, l, out, &len); + if (ret != ASN_PARSE_E) + return -12541; + } + + for (l = 0; l < testData[i].outSz-1; l++) { + ret = wc_BerToDer(testData[i].in, testData[i].inSz, out, &l); + if (ret != BUFFER_E) + return -12542; + } + } + + ret = wc_BerToDer(NULL, 4, NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -12543; + ret = wc_BerToDer(out, 4, NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -12544; + ret = wc_BerToDer(NULL, 4, NULL, &len); + if (ret != BAD_FUNC_ARG) + return -12545; + ret = wc_BerToDer(NULL, 4, out, NULL); + if (ret != BAD_FUNC_ARG) + return -12546; + ret = wc_BerToDer(out, 4, out, NULL); + if (ret != BAD_FUNC_ARG) + return -12547; + ret = wc_BerToDer(NULL, 4, out, &len); + if (ret != BAD_FUNC_ARG) + return -12548; + + for (l = 1; l < sizeof(good4_out); l++) { + len = l; + ret = wc_BerToDer(good4_in, sizeof(good4_in), out, &len); + if (ret != BUFFER_E) + return -12549; + } + + return 0; +} +#endif + +#ifdef DEBUG_WOLFSSL +static THREAD_LS_T int log_cnt = 0; +static void my_Logging_cb(const int logLevel, const char *const logMessage) +{ + (void)logLevel; + (void)logMessage; + log_cnt++; +} +#endif /* DEBUG_WOLFSSL */ + +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]; + int i; + + for (i = 0; i < (int)sizeof(b); i++) + b[i] = i; + + if (wolfSSL_Debugging_ON() != 0) + return -12600; + + if (wolfSSL_SetLoggingCb(my_Logging_cb) != 0) + return -12601; + + WOLFSSL_MSG(msg); + WOLFSSL_BUFFER(a, sizeof(a)); + WOLFSSL_BUFFER(b, sizeof(b)); + WOLFSSL_BUFFER(NULL, 0); + WOLFSSL_ERROR(MEMORY_E); + WOLFSSL_ERROR_MSG(msg); + + /* turn off logs */ + wolfSSL_Debugging_OFF(); + + /* capture log count */ + i = log_cnt; + + /* validate no logs are output when disabled */ + WOLFSSL_MSG(msg); + WOLFSSL_BUFFER(a, sizeof(a)); + WOLFSSL_BUFFER(b, sizeof(b)); + WOLFSSL_BUFFER(NULL, 0); + WOLFSSL_ERROR(MEMORY_E); + WOLFSSL_ERROR_MSG(msg); + + /* check the logs were disabled */ + if (i != log_cnt) + return -12602; + + /* restore callback and leave logging enabled */ + wolfSSL_SetLoggingCb(NULL); + wolfSSL_Debugging_ON(); + + /* suppress unused args */ + (void)a; + (void)b; + +#else + if (wolfSSL_Debugging_ON() != NOT_COMPILED_IN) + return -12603; + wolfSSL_Debugging_OFF(); + if (wolfSSL_SetLoggingCb(NULL) != NOT_COMPILED_IN) + return -12604; +#endif /* DEBUG_WOLFSSL */ + return 0; +} + + +int mutex_test(void) +{ +#ifdef WOLFSSL_PTHREADS + wolfSSL_Mutex m; +#endif +#ifndef WOLFSSL_NO_MALLOC + wolfSSL_Mutex *mm = wc_InitAndAllocMutex(); + if (mm == NULL) + return -12700; + wc_FreeMutex(mm); + XFREE(mm, NULL, DYNAMIC_TYPE_MUTEX); +#endif + +#ifdef WOLFSSL_PTHREADS + if (wc_InitMutex(&m) != 0) + return -12701; + if (wc_LockMutex(&m) != 0) + return -12702; + if (wc_FreeMutex(&m) != BAD_MUTEX_E) + return -12703; + if (wc_UnLockMutex(&m) != 0) + return -12704; + if (wc_FreeMutex(&m) != 0) + return -12705; +#ifndef WOLFSSL_NO_MUTEXLOCK_AFTER_FREE + if (wc_LockMutex(&m) != BAD_MUTEX_E) + return -12706; + if (wc_UnLockMutex(&m) != BAD_MUTEX_E) + return -12707; +#endif +#endif + + return 0; +} + +#if defined(USE_WOLFSSL_MEMORY) && !defined(FREERTOS) + +#ifndef WOLFSSL_NO_MALLOC +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++; + #ifndef WOLFSSL_NO_MALLOC + return malloc(size); + #else + WOLFSSL_MSG("No malloc available"); + (void)size; + return NULL; + #endif +} +static void my_Free_cb(void *ptr) +{ + free_cnt++; + #ifndef WOLFSSL_NO_MALLOC + free(ptr); + #else + WOLFSSL_MSG("No free available"); + (void)ptr; + #endif +} +static void *my_Realloc_cb(void *ptr, size_t size) +{ + realloc_cnt++; + #ifndef WOLFSSL_NO_MALLOC + return realloc(ptr, size); + #else + WOLFSSL_MSG("No realloc available"); + (void)ptr; + (void)size; + return NULL; + #endif +} +#endif /* !WOLFSSL_NO_MALLOC */ + +int memcb_test(void) +{ + int ret = 0; +#ifndef WOLFSSL_NO_MALLOC + byte* b = NULL; +#endif + wolfSSL_Malloc_cb mc; + wolfSSL_Free_cb fc; + wolfSSL_Realloc_cb rc; + + /* Save existing memory callbacks */ + if (wolfSSL_GetAllocators(&mc, &fc, &rc) != 0) + return -12800; + +#ifndef WOLFSSL_NO_MALLOC + /* test realloc */ + b = (byte*)XREALLOC(b, 1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) { + ERROR_OUT(-12801, exit_memcb); + } + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); + b = NULL; + + /* Use API. */ + if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)(void*)&my_Malloc_cb, + (wolfSSL_Free_cb)(void*)&my_Free_cb, + (wolfSSL_Realloc_cb)(void*)&my_Realloc_cb) != 0) { + ERROR_OUT(-12802, 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 = -12803; +#endif /* !WOLFSSL_NO_MALLOC */ + +#ifndef WOLFSSL_NO_MALLOC +exit_memcb: +#endif + + /* restore memory callbacks */ + wolfSSL_SetAllocators(mc, fc, rc); + + return ret; +} +#endif /* USE_WOLFSSL_MEMORY && !WOLFSSL_NO_MALLOC */ + + +#ifdef WOLFSSL_IMX6_CAAM_BLOB +int blob_test(void) +{ + int ret = 0; + byte out[112]; + byte blob[112]; + word32 outSz; + + const byte iv[] = + { + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff + }; + + const byte text[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; + + + XMEMSET(blob, 0, sizeof(blob)); + outSz = sizeof(blob); + ret = wc_caamCreateBlob((byte*)iv, sizeof(iv), blob, &outSz); + if (ret != 0) { + ERROR_OUT(-12900, exit_blob); + } + + blob[outSz - 2] += 1; + ret = wc_caamOpenBlob(blob, outSz, out, &outSz); + if (ret == 0) { /* should fail with altered blob */ + ERROR_OUT(-12901, exit_blob); + } + + XMEMSET(blob, 0, sizeof(blob)); + outSz = sizeof(blob); + ret = wc_caamCreateBlob((byte*)iv, sizeof(iv), blob, &outSz); + if (ret != 0) { + ERROR_OUT(-12902, exit_blob); + } + + ret = wc_caamOpenBlob(blob, outSz, out, &outSz); + if (ret != 0) { + ERROR_OUT(-12903, exit_blob); + } + + if (XMEMCMP(out, iv, sizeof(iv))) { + ERROR_OUT(-12904, exit_blob); + } + + XMEMSET(blob, 0, sizeof(blob)); + outSz = sizeof(blob); + ret = wc_caamCreateBlob((byte*)text, sizeof(text), blob, &outSz); + if (ret != 0) { + ERROR_OUT(-12905, exit_blob); + } + + ret = wc_caamOpenBlob(blob, outSz, out, &outSz); + if (ret != 0) { + ERROR_OUT(-12906, exit_blob); + } + + if (XMEMCMP(out, text, sizeof(text))) { + ERROR_OUT(-12907, exit_blob); + } + + exit_blob: + + return ret; +} +#endif /* WOLFSSL_IMX6_CAAM_BLOB */ + +#ifdef WOLF_CRYPTO_CB + +/* Example custom context for crypto callback */ +typedef struct { + int exampleVar; /* example, not used */ +} myCryptoDevCtx; + + +/* Example crypto dev callback function that calls software version */ +static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) +{ + int ret = NOT_COMPILED_IN; /* return this to bypass HW and use SW */ + myCryptoDevCtx* myCtx = (myCryptoDevCtx*)ctx; + + if (info == NULL) + return BAD_FUNC_ARG; + +#ifdef DEBUG_WOLFSSL + printf("CryptoDevCb: Algo Type %d\n", info->algo_type); +#endif + + if (info->algo_type == WC_ALGO_TYPE_RNG) { + #ifndef WC_NO_RNG + /* set devId to invalid, so software is used */ + info->rng.rng->devId = INVALID_DEVID; + + ret = wc_RNG_GenerateBlock(info->rng.rng, + info->rng.out, info->rng.sz); + + /* reset devId */ + info->rng.rng->devId = devIdArg; + #endif + } + else if (info->algo_type == WC_ALGO_TYPE_SEED) { + #ifndef WC_NO_RNG + static byte seed[sizeof(word32)] = { 0x00, 0x00, 0x00, 0x01 }; + word32* seedWord32 = (word32*)seed; + word32 len; + + /* wc_GenerateSeed is a local symbol so we need to fake the entropy. */ + while (info->seed.sz > 0) { + len = (word32)sizeof(seed); + if (info->seed.sz < len) + len = info->seed.sz; + XMEMCPY(info->seed.seed, seed, sizeof(seed)); + info->seed.seed += len; + info->seed.sz -= len; + (*seedWord32)++; + } + + ret = 0; + #endif + } + else if (info->algo_type == WC_ALGO_TYPE_PK) { + #ifdef DEBUG_WOLFSSL + printf("CryptoDevCb: Pk Type %d\n", info->pk.type); + #endif + + #ifndef NO_RSA + if (info->pk.type == WC_PK_TYPE_RSA) { + /* set devId to invalid, so software is used */ + info->pk.rsa.key->devId = INVALID_DEVID; + + switch (info->pk.rsa.type) { + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + /* perform software based RSA public op */ + ret = wc_RsaFunction( + info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, info->pk.rsa.outLen, + info->pk.rsa.type, info->pk.rsa.key, info->pk.rsa.rng); + break; + case RSA_PRIVATE_ENCRYPT: + case RSA_PRIVATE_DECRYPT: + /* perform software based RSA private op */ + ret = wc_RsaFunction( + info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, info->pk.rsa.outLen, + info->pk.rsa.type, info->pk.rsa.key, info->pk.rsa.rng); + break; + } + + /* reset devId */ + info->pk.rsa.key->devId = devIdArg; + } + #ifdef WOLFSSL_KEY_GEN + else if (info->pk.type == WC_PK_TYPE_RSA_KEYGEN) { + info->pk.rsakg.key->devId = INVALID_DEVID; + + ret = wc_MakeRsaKey(info->pk.rsakg.key, info->pk.rsakg.size, + info->pk.rsakg.e, info->pk.rsakg.rng); + + /* reset devId */ + info->pk.rsakg.key->devId = devIdArg; + } + #endif + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (info->pk.type == WC_PK_TYPE_EC_KEYGEN) { + /* set devId to invalid, so software is used */ + info->pk.eckg.key->devId = INVALID_DEVID; + + ret = wc_ecc_make_key_ex(info->pk.eckg.rng, info->pk.eckg.size, + info->pk.eckg.key, info->pk.eckg.curveId); + + /* reset devId */ + info->pk.eckg.key->devId = devIdArg; + } + else if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) { + /* set devId to invalid, so software is used */ + info->pk.eccsign.key->devId = INVALID_DEVID; + + ret = wc_ecc_sign_hash( + info->pk.eccsign.in, info->pk.eccsign.inlen, + info->pk.eccsign.out, info->pk.eccsign.outlen, + info->pk.eccsign.rng, info->pk.eccsign.key); + + /* reset devId */ + info->pk.eccsign.key->devId = devIdArg; + } + else if (info->pk.type == WC_PK_TYPE_ECDSA_VERIFY) { + /* set devId to invalid, so software is used */ + info->pk.eccverify.key->devId = INVALID_DEVID; + + ret = wc_ecc_verify_hash( + info->pk.eccverify.sig, info->pk.eccverify.siglen, + info->pk.eccverify.hash, info->pk.eccverify.hashlen, + info->pk.eccverify.res, info->pk.eccverify.key); + + /* reset devId */ + info->pk.eccverify.key->devId = devIdArg; + } + else if (info->pk.type == WC_PK_TYPE_ECDH) { + /* set devId to invalid, so software is used */ + info->pk.ecdh.private_key->devId = INVALID_DEVID; + + ret = wc_ecc_shared_secret( + info->pk.ecdh.private_key, info->pk.ecdh.public_key, + info->pk.ecdh.out, info->pk.ecdh.outlen); + + /* reset devId */ + info->pk.ecdh.private_key->devId = devIdArg; + } + #endif /* HAVE_ECC */ + } + else if (info->algo_type == WC_ALGO_TYPE_CIPHER) { +#if !defined(NO_AES) || !defined(NO_DES3) + #ifdef HAVE_AESGCM + if (info->cipher.type == WC_CIPHER_AES_GCM) { + if (info->cipher.enc) { + /* set devId to invalid, so software is used */ + info->cipher.aesgcm_enc.aes->devId = INVALID_DEVID; + + ret = wc_AesGcmEncrypt( + info->cipher.aesgcm_enc.aes, + info->cipher.aesgcm_enc.out, + info->cipher.aesgcm_enc.in, + info->cipher.aesgcm_enc.sz, + info->cipher.aesgcm_enc.iv, + info->cipher.aesgcm_enc.ivSz, + info->cipher.aesgcm_enc.authTag, + info->cipher.aesgcm_enc.authTagSz, + info->cipher.aesgcm_enc.authIn, + info->cipher.aesgcm_enc.authInSz); + + /* reset devId */ + info->cipher.aesgcm_enc.aes->devId = devIdArg; + } + else { + /* set devId to invalid, so software is used */ + info->cipher.aesgcm_dec.aes->devId = INVALID_DEVID; + + ret = wc_AesGcmDecrypt( + info->cipher.aesgcm_dec.aes, + info->cipher.aesgcm_dec.out, + info->cipher.aesgcm_dec.in, + info->cipher.aesgcm_dec.sz, + info->cipher.aesgcm_dec.iv, + info->cipher.aesgcm_dec.ivSz, + info->cipher.aesgcm_dec.authTag, + info->cipher.aesgcm_dec.authTagSz, + info->cipher.aesgcm_dec.authIn, + info->cipher.aesgcm_dec.authInSz); + + /* reset devId */ + info->cipher.aesgcm_dec.aes->devId = devIdArg; + } + } + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AES_CBC + if (info->cipher.type == WC_CIPHER_AES_CBC) { + if (info->cipher.enc) { + /* set devId to invalid, so software is used */ + info->cipher.aescbc.aes->devId = INVALID_DEVID; + + ret = wc_AesCbcEncrypt( + info->cipher.aescbc.aes, + info->cipher.aescbc.out, + info->cipher.aescbc.in, + info->cipher.aescbc.sz); + + /* reset devId */ + info->cipher.aescbc.aes->devId = devIdArg; + } + else { + /* set devId to invalid, so software is used */ + info->cipher.aescbc.aes->devId = INVALID_DEVID; + + ret = wc_AesCbcDecrypt( + info->cipher.aescbc.aes, + info->cipher.aescbc.out, + info->cipher.aescbc.in, + info->cipher.aescbc.sz); + + /* reset devId */ + info->cipher.aescbc.aes->devId = devIdArg; + } + } + #endif /* HAVE_AES_CBC */ + #ifndef NO_DES3 + if (info->cipher.type == WC_CIPHER_DES3) { + if (info->cipher.enc) { + /* set devId to invalid, so software is used */ + info->cipher.des3.des->devId = INVALID_DEVID; + + ret = wc_Des3_CbcEncrypt( + info->cipher.des3.des, + info->cipher.des3.out, + info->cipher.des3.in, + info->cipher.des3.sz); + + /* reset devId */ + info->cipher.des3.des->devId = devIdArg; + } + else { + /* set devId to invalid, so software is used */ + info->cipher.des3.des->devId = INVALID_DEVID; + + ret = wc_Des3_CbcDecrypt( + info->cipher.des3.des, + info->cipher.des3.out, + info->cipher.des3.in, + info->cipher.des3.sz); + + /* reset devId */ + info->cipher.des3.des->devId = devIdArg; + } + } + #endif /* !NO_DES3 */ +#endif /* !NO_AES || !NO_DES3 */ + } +#if !defined(NO_SHA) || !defined(NO_SHA256) + else if (info->algo_type == WC_ALGO_TYPE_HASH) { + #if !defined(NO_SHA) + if (info->hash.type == WC_HASH_TYPE_SHA) { + if (info->hash.sha1 == NULL) + return NOT_COMPILED_IN; + + /* set devId to invalid, so software is used */ + info->hash.sha1->devId = INVALID_DEVID; + + if (info->hash.in != NULL) { + ret = wc_ShaUpdate( + info->hash.sha1, + info->hash.in, + info->hash.inSz); + } + if (info->hash.digest != NULL) { + ret = wc_ShaFinal( + info->hash.sha1, + info->hash.digest); + } + + /* reset devId */ + info->hash.sha1->devId = devIdArg; + } + else + #endif + #if !defined(NO_SHA256) + if (info->hash.type == WC_HASH_TYPE_SHA256) { + if (info->hash.sha256 == NULL) + return NOT_COMPILED_IN; + + /* set devId to invalid, so software is used */ + info->hash.sha256->devId = INVALID_DEVID; + + if (info->hash.in != NULL) { + ret = wc_Sha256Update( + info->hash.sha256, + info->hash.in, + info->hash.inSz); + } + if (info->hash.digest != NULL) { + ret = wc_Sha256Final( + info->hash.sha256, + info->hash.digest); + } + + /* reset devId */ + info->hash.sha256->devId = devIdArg; + } + else + #endif + { + } + } +#endif /* !NO_SHA || !NO_SHA256 */ +#ifndef NO_HMAC + else if (info->algo_type == WC_ALGO_TYPE_HMAC) { + if (info->hmac.hmac == NULL) + return NOT_COMPILED_IN; + + /* set devId to invalid, so software is used */ + info->hmac.hmac->devId = INVALID_DEVID; + + if (info->hash.in != NULL) { + ret = wc_HmacUpdate( + info->hmac.hmac, + info->hmac.in, + info->hmac.inSz); + } + else if (info->hash.digest != NULL) { + ret = wc_HmacFinal( + info->hmac.hmac, + info->hmac.digest); + } + + /* reset devId */ + info->hmac.hmac->devId = devIdArg; + } +#endif + + (void)devIdArg; + (void)myCtx; + + return ret; +} + +int cryptocb_test(void) +{ + int ret = 0; + myCryptoDevCtx myCtx; + + /* example data for callback */ + myCtx.exampleVar = 1; + + /* set devId to something other than INVALID_DEVID */ + devId = 1; + ret = wc_CryptoCb_RegisterDevice(devId, myCryptoDevCb, &myCtx); + +#ifndef WC_NO_RNG + if (ret == 0) + ret = random_test(); +#endif /* WC_NO_RNG */ +#ifndef NO_RSA + if (ret == 0) + ret = rsa_test(); +#endif +#ifdef HAVE_ECC + if (ret == 0) + ret = ecc_test(); +#endif +#ifndef NO_AES + #ifdef HAVE_AESGCM + if (ret == 0) + ret = aesgcm_test(); + #endif + #ifdef HAVE_AES_CBC + if (ret == 0) + ret = aes_test(); + #endif +#endif /* !NO_AES */ +#ifndef NO_DES3 + if (ret == 0) + ret = des3_test(); +#endif /* !NO_DES3 */ +#if !defined(NO_SHA) || !defined(NO_SHA256) + #ifndef NO_SHA + if (ret == 0) + ret = sha_test(); + #endif + #ifndef NO_SHA256 + if (ret == 0) + ret = sha256_test(); + #endif +#endif +#ifndef NO_HMAC + #ifndef NO_SHA + if (ret == 0) + ret = hmac_sha_test(); + #endif + #ifndef NO_SHA256 + if (ret == 0) + ret = hmac_sha256_test(); + #endif +#endif +#ifndef NO_PWDBASED + #if defined(HAVE_PBKDF2) && !defined(NO_SHA256) + if (ret == 0) + ret = pbkdf2_test(); + #endif +#endif + + /* reset devId */ + devId = INVALID_DEVID; + + return ret; +} +#endif /* WOLF_CRYPTO_CB */ + +#ifdef WOLFSSL_CERT_PIV +int certpiv_test(void) +{ + int ret; + wc_CertPIV piv; + + /* Template for Identiv PIV cert, nonce and signature */ + const byte pivCertIdentiv[] = { + 0x0A, 0x0D, + 0x53, 0x04, /* NIST PIV Cert */ + 0x70, 0x02, /* Certificate */ + 0x30, 0x00, + 0x71, 0x01, 0x00, /* Cert Info */ + 0xFE, 0x00, /* Error Detection */ + 0x0B, 0x01, 0x00, /* Nonce */ + 0x0C, 0x01, 0x00, /* Signed Nonce */ + }; + + const byte pivCert[] = { + 0x53, 0x04, /* NIST PIV Cert */ + 0x70, 0x02, /* Certificate */ + 0x30, 0x00, + 0x71, 0x01, 0x00, /* Cert Info */ + 0xFE, 0x00, /* Error Detection */ + }; + + /* Test with identiv 0x0A, 0x0B and 0x0C markers */ + ret = wc_ParseCertPIV(&piv, pivCertIdentiv, sizeof(pivCertIdentiv)); + if (ret == 0) { + /* Test with NIST PIV format */ + ret = wc_ParseCertPIV(&piv, pivCert, sizeof(pivCert)); + } + + return ret; +} +#endif /* WOLFSSL_CERT_PIV */ + + +#undef ERROR_OUT + +#else + #ifndef NO_MAIN_DRIVER + int main() { return 0; } + #endif #endif /* NO_CRYPT_TEST */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.h b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.h index dbe6e25e0..7a6fc7c84 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.h @@ -1,8 +1,8 @@ -/* ctaocrypt/test/test.h +/* wolfcrypt/test/test.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,18 +16,28 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#pragma once + +#ifndef WOLFCRYPT_TEST_H +#define WOLFCRYPT_TEST_H + #ifdef __cplusplus 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" */ #endif + +#endif /* WOLFCRYPT_TEST_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.sln b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.sln index 97b2e8dfd..55b9872f0 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.sln +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.sln @@ -2,17 +2,56 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C++ Express 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{D04BDF66-664A-4D59-BEAC-8AB2D5809C21}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfssl", "..\..\wolfssl.vcxproj", "{73973223-5EE8-41CA-8E88-1D60E89A237B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + DLL Debug|Win32 = DLL Debug|Win32 + DLL Debug|x64 = DLL Debug|x64 + DLL Release|Win32 = DLL Release|Win32 + DLL Release|x64 = DLL Release|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Debug|Win32.ActiveCfg = Debug|Win32 {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Debug|Win32.Build.0 = Debug|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Debug|x64.ActiveCfg = Debug|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Debug|x64.Build.0 = Debug|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Debug|Win32.ActiveCfg = Debug|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Debug|Win32.Build.0 = Debug|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Debug|x64.ActiveCfg = Debug|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Debug|x64.Build.0 = Debug|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Release|Win32.ActiveCfg = Release|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Release|Win32.Build.0 = Release|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Release|x64.ActiveCfg = Release|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Release|x64.Build.0 = Release|x64 {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Release|Win32.ActiveCfg = Release|Win32 {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Release|Win32.Build.0 = Release|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Release|x64.ActiveCfg = Release|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Release|x64.Build.0 = Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.ActiveCfg = Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.Build.0 = Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|x64.ActiveCfg = Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|x64.Build.0 = Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|x64.Build.0 = DLL Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.ActiveCfg = Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.Build.0 = Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|x64.ActiveCfg = Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.vcproj b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.vcproj index 38c5c6bed..9758d8b77 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.vcproj +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/test/test.vcproj @@ -38,8 +38,8 @@ + +#ifndef NO_RSA + +#include +#include + +/* intels crypto */ +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* needed for WOLFSSL_RSA type but use macro guard against redefine */ +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_TYPES_DEFINED) \ + && !defined(WOLFSSL_RSA_TYPE_DEFINED) + struct WOLFSSL_RSA; + typedef struct WOLFSSL_RSA WOLFSSL_RSA; + #define WOLFSSL_RSA_TYPE_DEFINED +#endif + + +enum { + RSA_PUBLIC = 0, + RSA_PRIVATE = 1, +}; + +/* RSA */ +struct RsaKey { + IppsBigNumState* n; + IppsBigNumState* e; + IppsBigNumState* dipp; + IppsBigNumState* pipp; + IppsBigNumState* qipp; + IppsBigNumState* dPipp; + IppsBigNumState* dQipp; + IppsBigNumState* uipp; + int nSz, eSz, dSz; + IppsRSAPublicKeyState* pPub; + IppsRSAPrivateKeyState* pPrv; + word32 prvSz; /* size of private key */ + word32 sz; /* size of signature */ + int type; /* public or private */ + void* heap; /* for user memory overrides */ +}; + +#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); +WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); + +WOLFSSL_API int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng); +WOLFSSL_API int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, + RsaKey* key); +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_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_RsaEncryptSize(RsaKey* key); + +WOLFSSL_API int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, + RsaKey*, word32); +WOLFSSL_API int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, + word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz); +WOLFSSL_API int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, + RsaKey*, word32); +WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, + const byte* e, word32 eSz, RsaKey* key); +WOLFSSL_API int wc_RsaKeyToDer(RsaKey*, byte* output, word32 inLen); +WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen); +#ifdef WOLFSSL_KEY_GEN + WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); +#endif +WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, + word32*); +WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng); + + +#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) + /* abstracted BN operations with RSA key */ + WOLFSSL_API int wc_Rsa_leading_bit(void* BN); + WOLFSSL_API int wc_Rsa_unsigned_bin_size(void* BN); + + /* return MP_OKAY on success */ + WOLFSSL_API int wc_Rsa_to_unsigned_bin(void* BN, byte* in, int inLen); +#endif + +#ifdef OPENSSL_EXTRA /* abstracted functions to deal with rsa key */ + WOLFSSL_API int SetRsaExternal(WOLFSSL_RSA* rsa); + WOLFSSL_API int SetRsaInternal(WOLFSSL_RSA* rsa); +#endif +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_RSA */ +#endif /* USER_WOLF_CRYPT_RSA_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/lib/.gitkeep b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/lib/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/src/rsa.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/src/rsa.c new file mode 100644 index 000000000..a9f5afd8b --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/user-crypto/src/rsa.c @@ -0,0 +1,2790 @@ +/* rsa.c + * + * Copyright (C) 2006-2020 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 /* configure options when using autoconf */ + #include +#endif + +#include +#include + +#ifndef NO_RSA + +#define USER_CRYPTO_ERROR -101 + +#ifdef OPENSSL_EXTRA + #include /* include for openssl compatibility */ + #include +#endif +#include "user_rsa.h" + +#ifdef DEBUG_WOLFSSL /* debug done without variadric to allow older compilers */ + #include + #define USER_DEBUG(x) printf x +#else + #define USER_DEBUG(x) +#endif + +#define ASN_INTEGER 0x02 +#define ASN_BIT_STRING 0x03 +#define ASN_TAG_NULL 0x05 +#define ASN_OBJECT_ID 0x06 + + +/* Make sure compiler doesn't skip -- used from wolfSSL */ +static inline void ForceZero(const void* mem, word32 len) +{ + volatile byte* z = (volatile byte*)mem; + + while (len--) *z++ = 0; +} + +enum { + RSA_PUBLIC_ENCRYPT = 0, + RSA_PUBLIC_DECRYPT = 1, + RSA_PRIVATE_ENCRYPT = 2, + RSA_PRIVATE_DECRYPT = 3, + + RSA_BLOCK_TYPE_1 = 1, + RSA_BLOCK_TYPE_2 = 2, + + RSA_MIN_SIZE = 512, + RSA_MAX_SIZE = 4096, /* max allowed in IPP library */ + + RSA_MIN_PAD_SZ = 11 /* separator + 0 + pad value + 8 pads */ +}; + + +int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) +{ + + USER_DEBUG(("Entering wc_InitRsaKey\n")); + + if (key == NULL) + return USER_CRYPTO_ERROR; + + /* set full struct as 0 */ + ForceZero(key, sizeof(RsaKey)); + + USER_DEBUG(("\tExit wc_InitRsaKey\n")); + + (void)devId; + (void)heap; + return 0; +} + +int wc_InitRsaKey(RsaKey* key, void* heap) +{ + return wc_InitRsaKey_ex(key, heap, INVALID_DEVID); +} + + +/* three functions needed for cert and key gen */ +#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) +/* return 1 if there is a leading bit*/ +int wc_Rsa_leading_bit(void* bn) +{ + int ret = 0; + int dataSz; + Ipp32u* data; + Ipp32u q; + int qSz = sizeof(Ipp32u); + + if (ippsExtGet_BN(NULL, &dataSz, NULL, bn) != ippStsNoErr) { + USER_DEBUG(("ippsExtGet_BN Rsa leading bit error\n")); + return USER_CRYPTO_ERROR; + } + + /* convert from size in binary to Ipp32u */ + dataSz = dataSz / 32 + ((dataSz % 32)? 1 : 0); + data = (Ipp32u*)XMALLOC(dataSz * sizeof(Ipp32u), NULL, + DYNAMIC_TYPE_USER_CRYPTO); + if (data == NULL) { + USER_DEBUG(("Rsa leading bit memory error\n")); + return 0; + } + + /* extract value from BN */ + if (ippsExtGet_BN(NULL, NULL, data, bn) != ippStsNoErr) { + USER_DEBUG(("Rsa leading bit error\n")); + XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return 0; + } + + /* use method like what's used in wolfssl tfm.c */ + q = data[dataSz - 1]; + + ret = 0; + while (qSz > 0) { + if (q != 0) + ret = (q & 0x80) != 0; + q >>= 8; + qSz--; + } + + XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + return ret; +} + + +/* get the size in bytes of BN */ +int wc_Rsa_unsigned_bin_size(void* bn) +{ + int ret = 0; + if (ippsExtGet_BN(NULL, &ret, NULL, bn) != ippStsNoErr) { + USER_DEBUG(("Rsa unsigned bin size error\n")); + return USER_CRYPTO_ERROR; + } + return (ret / 8) + ((ret % 8)? 1: 0); /* size in bytes */ +} + +#ifndef MP_OKAY +#define MP_OKAY 0 +#endif + +/* extract the bn value to a unsigned byte array and return MP_OKAY on success */ +int wc_Rsa_to_unsigned_bin(void* bn, byte* in, int inLen) +{ + if (ippsGetOctString_BN((Ipp8u*)in, inLen, bn) != ippStsNoErr) { + USER_DEBUG(("Rsa to unsigned bin error\n")); + return USER_CRYPTO_ERROR; + } + return MP_OKAY; +} +#endif /* WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN || OPENSSL_EXTRA */ + + +#ifdef OPENSSL_EXTRA /* functions needed for openssl compatibility layer */ +static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, IppsBigNumState* in) +{ + IppStatus ret; + byte* data; + int sz; + + USER_DEBUG(("Entering SetIndividualExternal\n")); + + if (bn == NULL || in == NULL) { + USER_DEBUG(("inputs NULL error\n")); + return USER_CRYPTO_ERROR; + } + + if (*bn == NULL) { + *bn = wolfSSL_BN_new(); + if (*bn == NULL) { + USER_DEBUG(("SetIndividualExternal alloc failed\n")); + return USER_CRYPTO_ERROR; + } + } + + /* get size of array needed and extract oct array of data */ + ret = ippsGetSize_BN(in, &sz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + data = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (data == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsGetOctString_BN(data, sz, in); + if (ret != ippStsNoErr) { + XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return USER_CRYPTO_ERROR; + } + + /* store the data into a wolfSSL Big Number */ + *bn = wolfSSL_BN_bin2bn(data, sz, *bn); + + XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + return 0; +} + + +static int SetIndividualInternal(WOLFSSL_BIGNUM* bn, IppsBigNumState** mpi) +{ + int length, ctxSz, sz; + IppStatus ret; + Ipp8u* data; + + USER_DEBUG(("Entering SetIndividualInternal\n")); + + if (bn == NULL || bn->internal == NULL) { + USER_DEBUG(("bn NULL error\n")); + return USER_CRYPTO_ERROR; + } + + length = wolfSSL_BN_num_bytes(bn); + + /* if not IPP BN then create one */ + if (*mpi == NULL) { + ret = ippsBigNumGetSize(length, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *mpi = (IppsBigNumState*)XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (*mpi == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(length, *mpi); + if (ret != ippStsNoErr) { + XFREE(*mpi, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return USER_CRYPTO_ERROR; + } + + } + + /* get the size of array needed and check IPP BigNum */ + if (ippsGetSize_BN(*mpi, &sz) != ippStsNoErr) + return USER_CRYPTO_ERROR; + + if (sz < length) { + USER_DEBUG(("big num size is too small\n")); + return USER_CRYPTO_ERROR; + } + + data = (Ipp8u*)XMALLOC(length, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (data == NULL) + return USER_CRYPTO_ERROR; + + /* extract the wolfSSL BigNum and store it into IPP BigNum */ + if (wolfSSL_BN_bn2bin(bn, data) < 0) { + XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO); + USER_DEBUG(("error in getting bin from wolfssl bn\n")); + return USER_CRYPTO_ERROR; + } + + ret = ippsSetOctString_BN(data, length, *mpi); + if (ret != ippStsNoErr) { + XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return USER_CRYPTO_ERROR; + } + + XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + return 0; +} + + +/* WolfSSL -> OpenSSL */ +int SetRsaExternal(WOLFSSL_RSA* rsa) +{ + RsaKey* key; + USER_DEBUG(("Entering SetRsaExternal\n")); + + if (rsa == NULL || rsa->internal == NULL) { + USER_DEBUG(("rsa key NULL error\n")); + return USER_CRYPTO_ERROR; + } + + key = (RsaKey*)rsa->internal; + + if (SetIndividualExternal(&rsa->n, key->n) != 0) { + USER_DEBUG(("rsa n key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->e, key->e) != 0) { + USER_DEBUG(("rsa e key error\n")); + return USER_CRYPTO_ERROR; + } + + if (key->type == RSA_PRIVATE) { + if (SetIndividualExternal(&rsa->d, key->dipp) != 0) { + USER_DEBUG(("rsa d key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->p, key->pipp) != 0) { + USER_DEBUG(("rsa p key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->q, key->qipp) != 0) { + USER_DEBUG(("rsa q key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->dmp1, key->dPipp) != 0) { + USER_DEBUG(("rsa dP key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->dmq1, key->dQipp) != 0) { + USER_DEBUG(("rsa dQ key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->iqmp, key->uipp) != 0) { + USER_DEBUG(("rsa u key error\n")); + return USER_CRYPTO_ERROR; + } + } + + rsa->exSet = 1; + + /* SSL_SUCCESS */ + return 1; +} + + +/* Openssl -> WolfSSL */ +int SetRsaInternal(WOLFSSL_RSA* rsa) +{ + int ctxSz, pSz, qSz; + IppStatus ret; + RsaKey* key; + USER_DEBUG(("Entering SetRsaInternal\n")); + + if (rsa == NULL || rsa->internal == NULL) { + USER_DEBUG(("rsa key NULL error\n")); + return USER_CRYPTO_ERROR; + } + + key = (RsaKey*)rsa->internal; + + if (SetIndividualInternal(rsa->n, &key->n) != 0) { + USER_DEBUG(("rsa n key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualInternal(rsa->e, &key->e) != 0) { + USER_DEBUG(("rsa e key error\n")); + return USER_CRYPTO_ERROR; + } + + /* public key */ + key->type = RSA_PUBLIC; + + if (rsa->d != NULL) { + if (SetIndividualInternal(rsa->d, &key->dipp) != 0) { + USER_DEBUG(("rsa d key error\n")); + return USER_CRYPTO_ERROR; + } + + /* private key */ + key->type = RSA_PRIVATE; + } + + if (rsa->p != NULL && + SetIndividualInternal(rsa->p, &key->pipp) != 0) { + USER_DEBUG(("rsa p key error\n")); + return USER_CRYPTO_ERROR; + } + + if (rsa->q != NULL && + SetIndividualInternal(rsa->q, &key->qipp) != 0) { + USER_DEBUG(("rsa q key error\n")); + return USER_CRYPTO_ERROR; + } + + if (rsa->dmp1 != NULL && + SetIndividualInternal(rsa->dmp1, &key->dPipp) != 0) { + USER_DEBUG(("rsa dP key error\n")); + return USER_CRYPTO_ERROR; + } + + if (rsa->dmq1 != NULL && + SetIndividualInternal(rsa->dmq1, &key->dQipp) != 0) { + USER_DEBUG(("rsa dQ key error\n")); + return USER_CRYPTO_ERROR; + } + + if (rsa->iqmp != NULL && + SetIndividualInternal(rsa->iqmp, &key->uipp) != 0) { + USER_DEBUG(("rsa u key error\n")); + return USER_CRYPTO_ERROR; + } + + rsa->inSet = 1; + + /* get sizes of IPP BN key states created from input */ + ret = ippsGetSize_BN(key->n, &key->nSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->e, &key->eSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->sz = key->nSz; /* set modulus size */ + + /* convert to size in bits */ + key->nSz = key->nSz * 8; + key->eSz = key->eSz * 8; + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->pPub = (IppsRSAPublicKeyState*)XMALLOC(ctxSz, NULL, + DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + 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 = ippsRSA_SetPublicKey(key->n, key->e, key->pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + if (key->pipp != NULL && key->qipp != NULL && key->dipp != NULL && + key->dPipp != NULL && key->dQipp != NULL && key->uipp != NULL) { + /* get bn sizes needed for private key set up */ + ret = ippsGetSize_BN(key->pipp, &pSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->qipp, &qSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* store sizes needed for creating tmp private keys */ + ret = ippsGetSize_BN(key->dipp, &key->dSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* convert to size in bits */ + key->dSz = key->dSz * 8; + pSz = pSz * 8; + qSz = qSz * 8; + + /* set up private key state */ + ret = ippsRSA_GetSizePrivateKeyType2(pSz, qSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->prvSz = ctxSz; + key->pPrv = (IppsRSAPrivateKeyState*)XMALLOC(ctxSz, 0, + DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPrv == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPrivateKeyType2(pSz, qSz, key->pPrv, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPrivateKeyType2(key->pipp, key->qipp, key->dPipp, + key->dQipp, key->uipp, key->pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + } + + /* SSL_SUCCESS */ + return 1; +} +#endif /* OPENSSLEXTRA */ + + +/* Padding scheme function used in wolfSSL for signing needed for matching + existing API signing scheme + input : the msg to be signed + inputLen : length of input msg + pkcsBlock : the outputted padded msg + pkcsBlockLen : length of outputted padded msg buffer + padValue : the padded value after first 00 , is either 01 or 02 + rng : random number generator structure + */ +static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, byte padValue, WC_RNG* rng) +{ + if (inputLen == 0 || pkcsBlockLen == 0) { + return USER_CRYPTO_ERROR; + } + + pkcsBlock[0] = 0x0; /* set first byte to zero and advance */ + pkcsBlock++; pkcsBlockLen--; + pkcsBlock[0] = padValue; /* insert padValue */ + + if (padValue == RSA_BLOCK_TYPE_1) { + if (pkcsBlockLen < inputLen + 2) { + return USER_CRYPTO_ERROR; + } + + /* pad with 0xff bytes */ + XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2); + } + else { + /* pad with non-zero random bytes */ + word32 padLen, i; + int ret; + + if (pkcsBlockLen < inputLen + 1) { + return USER_CRYPTO_ERROR; + } + + padLen = pkcsBlockLen - inputLen - 1; + ret = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen); + + if (ret != 0) + return ret; + + /* remove zeros */ + for (i = 1; i < padLen; i++) + if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01; + } + + pkcsBlock[pkcsBlockLen-inputLen-1] = 0; /* separator */ + XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen); + + return 0; +} + + +/* UnPad plaintext, set start to *output, return length of plaintext, + * < 0 on error */ +static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, + byte **output, byte padValue) +{ + word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0, + invalid = 0, + i = 1, + outputLen; + + if (pkcsBlockLen == 0) { + return USER_CRYPTO_ERROR; + } + + if (pkcsBlock[0] != 0x0) /* skip past zero */ + invalid = 1; + pkcsBlock++; pkcsBlockLen--; + + /* Require block type padValue */ + invalid = (pkcsBlock[0] != padValue) || invalid; + + /* verify the padding until we find the separator */ + if (padValue == RSA_BLOCK_TYPE_1) { + while (i maxOutputLen) || invalid; + + if (invalid) { + USER_DEBUG(("RsaUnPad error, bad formatting\n")); + return USER_CRYPTO_ERROR; + } + + *output = (byte *)(pkcsBlock + i); + return outputLen; +} + + +/* Set up memory and structure for a Big Number + * returns ippStsNoErr on success + */ +static IppStatus init_bn(IppsBigNumState** in, int sz) +{ + int ctxSz; + IppStatus ret; + + ret = ippsBigNumGetSize(sz, &ctxSz); + if (ret != ippStsNoErr) { + return ret; + } + + *in = (IppsBigNumState*)XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (*in == NULL) { + return ippStsNoMemErr; + } + + ret = ippsBigNumInit(sz, *in); + if (ret != ippStsNoErr) { + XFREE(*in, NULL, DYNAMIC_TYPE_USER_CRYPTO); + *in = NULL; + return ret; + } + + return ippStsNoErr; +} + + +/* Set up memory and structure for a Montgomery struct + * returns ippStsNoErr on success + */ +static IppStatus init_mont(IppsMontState** mont, int* ctxSz, + IppsBigNumState* modul) +{ + int mSz; + Ipp32u* m; + IppStatus ret; + + ret = ippsExtGet_BN(NULL, ctxSz, NULL, modul); + if (ret != ippStsNoErr) { + return ret; + } + + /* convert bits to Ipp32u array size and round up + 32 is number of bits in type */ + mSz = (*ctxSz/32)+((*ctxSz % 32)? 1: 0); + m = (Ipp32u*)XMALLOC(mSz * sizeof(Ipp32u), 0, DYNAMIC_TYPE_USER_CRYPTO); + if (m == NULL) { + XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return ippStsNoMemErr; + } + + ret = ippsExtGet_BN(NULL, NULL, m, modul); + if (ret != ippStsNoErr) { + XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return ret; + } + + ret = ippsMontGetSize(IppsSlidingWindows, mSz, ctxSz); + if (ret != ippStsNoErr) { + XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return ret; + } + + /* 2. Allocate working buffer using malloc */ + *mont = (IppsMontState*)XMALLOC(*ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (*mont == NULL) { + XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return ippStsNoMemErr; + } + ret = ippsMontInit(IppsSlidingWindows, mSz, *mont); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsMontInit error of %s\n", ippGetStatusString(ret))); + XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(*mont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + *mont = NULL; + return ret; + } + + /* 3. Call the function MontSet to set big number module */ + ret = ippsMontSet(m, mSz, *mont); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsMontSet error of %s\n", ippGetStatusString(ret))); + XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(*mont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + *mont = NULL; + return ret; + } + + XFREE(m, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + return ippStsNoErr; +} + + + +int wc_FreeRsaKey(RsaKey* key) +{ + if (key == NULL) + return 0; + + USER_DEBUG(("Entering wc_FreeRsaKey\n")); + + if (key->pPub != NULL) { + XFREE(key->pPub, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->pPub = NULL; + } + + if (key->pPrv != NULL) { + /* write over sensitive information */ + ForceZero(key->pPrv, key->prvSz); + XFREE(key->pPrv, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->pPrv = NULL; + } + + if (key->n != NULL) { + XFREE(key->n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->n = NULL; + } + + if (key->e != NULL) { + XFREE(key->e, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->e = NULL; + } + + if (key->dipp != NULL) { + XFREE(key->dipp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->dipp = NULL; + } + + if (key->pipp != NULL) { + XFREE(key->pipp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->pipp = NULL; + } + + if (key->qipp != NULL) { + XFREE(key->qipp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->qipp = NULL; + } + + if (key->dPipp != NULL) { + XFREE(key->dPipp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->dPipp = NULL; + } + + if (key->dQipp != NULL) { + XFREE(key->dQipp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->dQipp = NULL; + } + + if (key->uipp != NULL) { + XFREE(key->uipp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->uipp = NULL; + } + + USER_DEBUG(("\tExit wc_FreeRsaKey\n")); + (void)key; + + return 0; +} + + +/* Some parsing functions from wolfSSL code needed to match wolfSSL API used */ +static int GetLength(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int length = 0; + word32 idx = *inOutIdx; + byte b; + + *len = 0; /* default length */ + + if ((idx + 1) > maxIdx) { /* for first read */ + USER_DEBUG(("GetLength bad index on input\n")); + return USER_CRYPTO_ERROR; + } + + b = input[idx++]; + if (b >= 0x80) { + word32 bytes = b & 0x7F; + + if ((idx + bytes) > maxIdx) { /* for reading bytes */ + USER_DEBUG(("GetLength bad long length\n")); + return USER_CRYPTO_ERROR; + } + + while (bytes--) { + b = input[idx++]; + length = (length << 8) | b; + } + } + else + length = b; + + if ((idx + length) > maxIdx) { /* for user of length */ + USER_DEBUG(("GetLength value exceeds buffer length\n")); + return USER_CRYPTO_ERROR; + } + + *inOutIdx = idx; + if (length > 0) + *len = length; + + return length; +} + +static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len, + word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + int length; + + if ((idx + 1) > maxIdx) + return USER_CRYPTO_ERROR; + + b = input[idx++]; + if (b != tag) + return USER_CRYPTO_ERROR; + + if (GetLength(input, &idx, &length, maxIdx) < 0) + return USER_CRYPTO_ERROR; + + *len = length; + *inOutIdx = idx; + return length; +} + +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 USER_CRYPTO_ERROR; + } + } + + return 0; +} + +static int GetInt(IppsBigNumState** mpi, const byte* input, word32* inOutIdx, + word32 maxIdx) +{ + IppStatus ret; + word32 idx = *inOutIdx; + int length; + int ctxSz; + + if (GetASNInt(input, &idx, &length, maxIdx) < 0) { + return USER_CRYPTO_ERROR; + } + + ret = ippsBigNumGetSize(length, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *mpi = (IppsBigNumState*)XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (*mpi == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(length, *mpi); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)input + idx, length, *mpi); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *inOutIdx = idx + length; + return 0; +} + + +static int GetSequence(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int length = -1; + word32 idx = *inOutIdx; + + if ((idx + 1) > maxIdx) + return USER_CRYPTO_ERROR; + + if (input[idx++] != (0x10 | 0x20) || + GetLength(input, &idx, &length, maxIdx) < 0) + return USER_CRYPTO_ERROR; + + *len = length; + *inOutIdx = idx; + + return length; +} + + +static int GetMyVersion(const byte* input, word32* inOutIdx, + int* version, word32 maxIdx) +{ + word32 idx = *inOutIdx; + + if ((idx + 3) > maxIdx) + return USER_CRYPTO_ERROR; + + if (input[idx++] != 0x02) + return USER_CRYPTO_ERROR; + + if (input[idx++] != 0x01) + return USER_CRYPTO_ERROR; + + *version = input[idx++]; + *inOutIdx = idx; + + return *version; +} + + +int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, + word32 inSz) +{ + int version, length; + 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 */ + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + + if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) + return USER_CRYPTO_ERROR; + + key->type = RSA_PRIVATE; + + if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || + GetInt(&key->e, input, inOutIdx, inSz) < 0 || + GetInt(&key->dipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->pipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->qipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->dPipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->dQipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->uipp, input, inOutIdx, inSz) < 0 ) + return USER_CRYPTO_ERROR; + + /* get sizes of IPP BN key states created from input */ + ret = ippsGetSize_BN(key->n, &key->nSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->e, &key->eSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->sz = key->nSz; /* set modulus size */ + + /* convert to size in bits */ + key->nSz = key->nSz * 8; + key->eSz = key->eSz * 8; + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->pPub = (IppsRSAPublicKeyState*)XMALLOC(ctxSz, NULL, + DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + 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 = ippsRSA_SetPublicKey(key->n, key->e, key->pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* get bn sizes needed for private key set up */ + ret = ippsGetSize_BN(key->pipp, &pSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->qipp, &qSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* store sizes needed for creating tmp private keys */ + ret = ippsGetSize_BN(key->dipp, &key->dSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* convert to size in bits */ + key->dSz = key->dSz * 8; + pSz = pSz * 8; + qSz = qSz * 8; + + /* set up private key state */ + ret = ippsRSA_GetSizePrivateKeyType2(pSz, qSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->prvSz = ctxSz; + key->pPrv = (IppsRSAPrivateKeyState*)XMALLOC(ctxSz, 0, + DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPrv == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPrivateKeyType2(pSz, qSz, key->pPrv, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPrivateKeyType2(key->pipp, key->qipp, key->dPipp, + key->dQipp, key->uipp, key->pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + USER_DEBUG(("\tExit wc_RsaPrivateKeyDecode\n")); + + return 0; +} + + +int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, + word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz) +{ + IppStatus ret = 0; + int length; +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + byte b; +#endif + + if (input == NULL || inOutIdx == NULL) { + return USER_CRYPTO_ERROR; + } + + USER_DEBUG(("Entering wc_RsaPublicKeyDecode_ex\n")); + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + if ((*inOutIdx + 1) > inSz) + return USER_CRYPTO_ERROR; + + 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 USER_CRYPTO_ERROR; + + b = input[(*inOutIdx)++]; + if (b != ASN_OBJECT_ID) + return USER_CRYPTO_ERROR; + + if (GetLength(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + + *inOutIdx += length; /* skip past */ + + /* 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 USER_CRYPTO_ERROR; + } + else { + /* go back, didn't have it */ + (*inOutIdx)--; + } + + /* should have bit tag length and seq next */ + b = input[(*inOutIdx)++]; + if (b != ASN_BIT_STRING) + return USER_CRYPTO_ERROR; + + if (GetLength(input, inOutIdx, &length, inSz) <= 0) + return USER_CRYPTO_ERROR; + + /* could have 0 */ + b = input[(*inOutIdx)++]; + if (b != 0) + (*inOutIdx)--; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + } +#endif /* OPENSSL_EXTRA || RSA_DECODE_EXTRA */ + + /* Get modulus */ + ret = GetASNInt(input, inOutIdx, &length, inSz); + if (ret < 0) { + return USER_CRYPTO_ERROR; + } + if (nSz) + *nSz = length; + if (n) + *n = &input[*inOutIdx]; + *inOutIdx += length; + + /* Get exponent */ + ret = GetASNInt(input, inOutIdx, &length, inSz); + if (ret < 0) { + return USER_CRYPTO_ERROR; + } + if (eSz) + *eSz = length; + if (e) + *e = &input[*inOutIdx]; + *inOutIdx += length; + + USER_DEBUG(("\tExit wc_RsaPublicKeyDecode_ex\n")); + + return ret; +} + +/* read in a public RSA key */ +int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, + word32 inSz) +{ + IppStatus ret; + const byte *n = NULL, *e = NULL; + word32 nSz = 0, eSz = 0; + + if (key == NULL) + return USER_CRYPTO_ERROR; + + USER_DEBUG(("Entering wc_RsaPublicKeyDecode\n")); + + ret = wc_RsaPublicKeyDecode_ex(input, inOutIdx, inSz, &n, &nSz, &e, &eSz); + if (ret == 0) { + ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, key); + } + + USER_DEBUG(("\tExit RsaPublicKeyDecode\n")); + + return ret; +} + +/* import RSA public key elements (n, e) into RsaKey structure (key) */ +int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, + word32 eSz, RsaKey* key) +{ + IppStatus ret; + int ctxSz; + + USER_DEBUG(("Entering wc_RsaPublicKeyDecodeRaw\n")); + + if (n == NULL || e == NULL || key == NULL) + return USER_CRYPTO_ERROR; + + /* set up IPP key states -- read in n */ + ret = init_bn(&key->n, nSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)n, nSz, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* read in e */ + ret = init_bn(&key->e, eSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)e, eSz, key->e); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* store size and convert to binary */ + key->sz = nSz; + nSz = nSz * 8; + eSz = eSz * 8; + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(nSz, eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->pPub = (IppsRSAPublicKeyState*)XMALLOC(ctxSz, NULL, + DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPublicKey(nSz, eSz, key->pPub, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + 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; + } + + key->nSz = nSz; + key->eSz = eSz; + key->type = RSA_PUBLIC; + + return 0; +} + + +/* encrypt using PKCS v15 */ +int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, WC_RNG* rng) +{ + IppStatus ret; + Ipp8u* scratchBuffer; + int scratchSz; + + if (key == NULL || in == NULL || out == NULL) + return USER_CRYPTO_ERROR; + + if (key->pPub == NULL || outLen < key->sz) + return USER_CRYPTO_ERROR; + + /* set size of scratch buffer */ + ret = ippsRSA_GetBufferSizePublicKey(&scratchSz, key->pPub); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + scratchBuffer = (Ipp8u*)XMALLOC(scratchSz*(sizeof(Ipp8u)), 0, + DYNAMIC_TYPE_USER_CRYPTO); + if (scratchBuffer == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSAEncrypt_PKCSv15((Ipp8u*)in, inLen, NULL, (Ipp8u*)out, + key->pPub, scratchBuffer); + if (ret != ippStsNoErr) { + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO); + USER_DEBUG(("encrypt error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + (void)rng; + return key->sz; +} + + +/* decrypt using PLCS v15 */ +int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key) +{ + IppStatus ret; + Ipp8u* scratchBuffer; + int scratchSz; + int outSz; + + if (in == NULL || out == NULL || key == NULL) + return USER_CRYPTO_ERROR; + + if (key->pPrv == NULL || inLen != key->sz) + return USER_CRYPTO_ERROR; + + outSz = outLen; + + /* set size of scratch buffer */ + ret = ippsRSA_GetBufferSizePrivateKey(&scratchSz, key->pPrv); + if (ret != ippStsNoErr) { + return USER_CRYPTO_ERROR; + } + + scratchBuffer = (Ipp8u*)XMALLOC(scratchSz*(sizeof(Ipp8u)), 0, + DYNAMIC_TYPE_USER_CRYPTO); + if (scratchBuffer == NULL) { + return USER_CRYPTO_ERROR; + } + + /* perform decryption using IPP */ + ret = ippsRSADecrypt_PKCSv15((Ipp8u*)in, (Ipp8u*)out, &outSz, key->pPrv, + scratchBuffer); + if (ret != ippStsNoErr) { + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO); + USER_DEBUG(("decrypt error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + return outSz; +} + + +/* out is a pointer that is set to the location in byte array "in" where input + data has been decrypted */ +int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key) +{ + int outSz; + byte* tmp; + + USER_DEBUG(("Entering wc_RsaPrivateDecryptInline\n")); + + /* allocate a buffer for max decrypted text */ + tmp = (byte*)XMALLOC(key->sz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (tmp == NULL) + return USER_CRYPTO_ERROR; + + outSz = wc_RsaPrivateDecrypt(in, inLen, tmp, key->sz, key); + if (outSz >= 0) { + XMEMCPY(in, tmp, outSz); + *out = in; + } + else { + XFREE(tmp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return USER_CRYPTO_ERROR; + } + + XFREE(tmp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + USER_DEBUG(("\tExit wc_RsaPrivateDecryptInline\n")); + + return outSz; +} + + +/* Used to clean up memory when exiting, clean up memory used */ +static int FreeHelper(IppsBigNumState* pTxt, IppsBigNumState* cTxt, + Ipp8u* scratchBuffer, void* pPub) +{ + if (pTxt != NULL) + XFREE(pTxt, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (cTxt != NULL) + XFREE(cTxt, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (scratchBuffer != NULL) + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (pPub != NULL) + XFREE(pPub, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + return 0; +} + + +/* for Rsa Verify + in : byte array to be verified + inLen : length of input array + out : pointer to location of in byte array that has been verified + */ +int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) +{ + + int ctxSz; + int scratchSz; + Ipp8u* scratchBuffer = NULL; + IppStatus ret; + IppsRSAPrivateKeyState* pPub = NULL; + IppsBigNumState* pTxt = NULL; + IppsBigNumState* cTxt = NULL; + + USER_DEBUG(("Entering wc_RsaSSL_VerifyInline\n")); + + if (key == NULL || key->n == NULL || key->e == NULL) { + USER_DEBUG(("n or e element was null\n")); + return USER_CRYPTO_ERROR; + } + + if (in == NULL || inLen == 0 || out == NULL) + return USER_CRYPTO_ERROR; + + /* set up a private key state using public key values */ + ret = ippsRSA_GetSizePrivateKeyType1(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + pPub = (IppsRSAPrivateKeyState*)XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPrivateKeyType1(key->nSz, key->eSz, pPub, ctxSz); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPrivateKeyType1(key->n, key->e, pPub); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* set size of scratch buffer */ + ret = ippsRSA_GetBufferSizePrivateKey(&scratchSz, pPub); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + scratchBuffer = (Ipp8u*)XMALLOC(scratchSz*(sizeof(Ipp8u)), 0, + DYNAMIC_TYPE_USER_CRYPTO); + if (scratchBuffer == NULL) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + /* load plain and cipher into big num states */ + ret = init_bn(&pTxt, key->sz); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + ret = ippsSetOctString_BN((Ipp8u*)in, key->sz, pTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + /* set up cipher to hold signature */ + ret = init_bn(&cTxt, key->sz); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + ret = ippsSetOctString_BN((Ipp8u*)in, key->sz, cTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + /* decrypt using public key information */ + ret = ippsRSA_Decrypt(cTxt, pTxt, pPub, scratchBuffer); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + USER_DEBUG(("decrypt error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* extract big num struct to octet string */ + ret = ippsGetOctString_BN((Ipp8u*)in, key->sz, pTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + USER_DEBUG(("BN get string error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + + /* unpad the decrypted information and return size of array */ + return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1); +} + + +/* sets up and call VerifyInline to verify a signature */ +int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key) +{ + int plainLen; + byte* tmp; + byte* pad = 0; + + if (out == NULL || in == NULL || key == NULL) + return USER_CRYPTO_ERROR; + + tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_USER_CRYPTO); + if (tmp == NULL) { + return USER_CRYPTO_ERROR; + } + + XMEMCPY(tmp, in, inLen); + + /* verify signature and test if output buffer is large enough */ + plainLen = wc_RsaSSL_VerifyInline(tmp, inLen, &pad, key); + if (plainLen < 0) { + XFREE(tmp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return plainLen; + } + + if (plainLen > (int)outLen) + plainLen = USER_CRYPTO_ERROR; + else + XMEMCPY(out, pad, plainLen); + + ForceZero(tmp, inLen); + XFREE(tmp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + return plainLen; +} + + +/* Check if a > b , if so c = a mod b + return ippStsNoErr on success */ +static IppStatus reduce(IppsBigNumState* a, IppsBigNumState* b, + IppsBigNumState* c) +{ + IppStatus ret; + + if ((ret = ippsMod_BN(a, b, c)) != ippStsNoErr) + return ret; + + return ippStsNoErr; +} + + +static IppStatus exptmod(IppsBigNumState* a, IppsBigNumState* b, + IppsMontState* mont, IppsBigNumState* out, IppsBigNumState* one) +{ + IppStatus ret; + + ret = ippsMontForm(a, mont, a); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsMontForm error of %s\n", ippGetStatusString(ret))); + return ret; + } + + /* a = a^b mod mont */ + ret = ippsMontExp(a, b, mont, out); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsMontExp error of %s\n", ippGetStatusString(ret))); + return ret; + } + + /* convert back from montgomery */ + ret = ippsMontMul(out, one, mont, out); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsMontMul error of %s\n", ippGetStatusString(ret))); + return ret; + } + + return ippStsNoErr; +} + + +static void Free_BN(IppsBigNumState* bn) +{ + int sz, ctxSz; + IppStatus ret; + + if (bn != NULL) { + ret = ippStsNoErr; + ret |= ippsGetSize_BN(bn, &sz); + ret |= ippsBigNumGetSize(sz, &ctxSz); + if (ret == ippStsNoErr) { + ForceZero(bn, ctxSz); + } + else { + USER_DEBUG(("Issue with clearing a struct in RsaSSL_Sign free\n")); + } + XFREE(bn, NULL, DYNAMIC_TYPE_USER_CRYPTO); + } +} + + +/* free up memory used during CRT sign operation */ +static void FreeSignHelper(IppsBigNumState* one, IppsBigNumState* tmp, + IppsBigNumState* tmpP, IppsBigNumState* tmpQ, IppsBigNumState* tmpa, + IppsBigNumState* tmpb) +{ + Free_BN(one); + Free_BN(tmp); + Free_BN(tmpP); + Free_BN(tmpQ); + Free_BN(tmpa); + Free_BN(tmpb); +} + + +/* for Rsa Sign */ +int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, WC_RNG* rng) +{ + int sz, pSz, qSz; + IppStatus ret; + word32 outSz = outLen; + + IppsMontState* pMont = NULL; + IppsMontState* qMont = NULL; + + IppsBigNumState* one = NULL; + IppsBigNumState* tmp = NULL; + IppsBigNumState* tmpP = NULL; + IppsBigNumState* tmpQ = NULL; + IppsBigNumState* tmpa = NULL; + IppsBigNumState* tmpb = NULL; + + IppsBigNumSGN sa, sb; + + Ipp8u o[1]; + o[0] = 1; + + USER_DEBUG(("Entering wc_RsaSSL_Sign\n")); + + 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) { + USER_DEBUG(("Bad key argument to wc_RsaSSL_Sign\n")); + return USER_CRYPTO_ERROR; + } + + if (sz > (int)outLen) { + USER_DEBUG(("Bad argument outLen to wc_RsaSSL_Sign\n")); + return USER_CRYPTO_ERROR; + } + + if (sz < RSA_MIN_PAD_SZ) { + USER_DEBUG(("Key size is too small\n")); + return USER_CRYPTO_ERROR; + } + + if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) { + USER_DEBUG(("Bad argument inLen to wc_RsaSSL_Sign\n")); + return USER_CRYPTO_ERROR; + } + + /* Set up needed pkcs v15 padding */ + if (wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng) != 0) { + USER_DEBUG(("RSA Padding error\n")); + return USER_CRYPTO_ERROR; + } + + /* tmp = input to sign */ + ret = init_bn(&tmp, sz); + if (ret != ippStsNoErr) { + USER_DEBUG(("init_BN error of %s\n", ippGetStatusString(ret))); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + ret = ippsSetOctString_BN(out, sz, tmp); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsSetOctString_BN error of %s\n", + ippGetStatusString(ret))); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /* tmpP = tmp mod p */ + ret = init_bn(&tmpP, sz); + if (ret != ippStsNoErr) { + USER_DEBUG(("init_BN error of %s\n", ippGetStatusString(ret))); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /* tmpQ = tmp mod q */ + ret = init_bn(&tmpQ, sz); + if (ret != ippStsNoErr) { + USER_DEBUG(("init_BN error of %s\n", ippGetStatusString(ret))); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /* tmpa */ + ret = init_bn(&tmpa, sz); + if (ret != ippStsNoErr) { + USER_DEBUG(("init_BN error of %s\n", ippGetStatusString(ret))); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /* tmpb */ + ret = init_bn(&tmpb, sz); + if (ret != ippStsNoErr) { + USER_DEBUG(("init_BN error of %s\n", ippGetStatusString(ret))); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /* one : used for conversion from Montgomery to classical */ + ret = init_bn(&one, sz); + if (ret != ippStsNoErr) { + USER_DEBUG(("init_BN error of %s\n", ippGetStatusString(ret))); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + ret = ippsSetOctString_BN(o, 1, one); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsSetOctString_BN error of %s\n", + ippGetStatusString(ret))); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /** + Set up Montgomery state + */ + ret = init_mont(&pMont, &pSz, key->pipp); + if (ret != ippStsNoErr) { + USER_DEBUG(("init_mont error of %s\n", ippGetStatusString(ret))); + if (pMont != NULL) { + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + } + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + ret = init_mont(&qMont, &qSz, key->qipp); + if (ret != ippStsNoErr) { + USER_DEBUG(("init_mont error of %s\n", ippGetStatusString(ret))); + if (qMont != NULL) { + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + } + ForceZero(pMont, pSz); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /** + Check and reduce input + This is needed for calls to MontExp since required value of a < modulus + */ + ret = reduce(tmp, key->pipp, tmpP); + if (ret != ippStsNoErr) + { + USER_DEBUG(("reduce error of %s\n", ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + ret = reduce(tmp, key->qipp, tmpQ); + if (ret != ippStsNoErr) + { + USER_DEBUG(("reduce error of %s\n", ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /* tmpa = (tmp mod p)^dP mod p */ + ret = exptmod(tmpP, key->dPipp, pMont, tmpa, one); + if (ret != ippStsNoErr) { + USER_DEBUG(("exptmod error of %s\n", ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /* tmpb = (tmp mod q)^dQ mod q */ + ret = exptmod(tmpQ, key->dQipp, qMont, tmpb, one); + if (ret != ippStsNoErr) { + USER_DEBUG(("exptmod error of %s\n", ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /* tmp = (tmpa - tmpb) * qInv (mod p) */ + ret = ippsSub_BN(tmpa, tmpb, tmp); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsSub_BN error of %s\n", ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + ret = ippsMul_BN(tmp, key->uipp, tmp); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsMul_BN error of %s\n", ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /* mod performed the same was as wolfSSL fp_mod -- tmpa is just scratch */ + ret = ippsDiv_BN(tmp, key->pipp, tmpa, tmp); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsDiv_BN error of %s\n", ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /* Check sign of values and perform conditional add */ + ret = ippsExtGet_BN(&sa, NULL, NULL, tmp); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsExtGet_BN error of %s\n", ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + ret = ippsExtGet_BN(&sb, NULL, NULL, key->pipp); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsExtGet_BN error of %s\n", ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + if (sa != sb) { + ret = ippsAdd_BN(tmp, key->pipp, tmp); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsAdd_BN error of %s\n", ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + } + + /* tmp = tmpb + q * tmp */ + ret = ippsMul_BN(tmp, key->qipp, tmp); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsSub_BN error of %s\n", ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + + ret = ippsAdd_BN(tmp, tmpb, tmp); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsSub_BN error of %s\n", ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + /* Extract the output */ + ret = ippsGetOctString_BN(out, sz, tmp); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetOctString_BN error of %s\n", + ippGetStatusString(ret))); + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + return USER_CRYPTO_ERROR; + } + + outSz = sz; + + /* clear memory and free */ + ForceZero(pMont, pSz); + ForceZero(qMont, qSz); + XFREE(qMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pMont, NULL, DYNAMIC_TYPE_USER_CRYPTO); + FreeSignHelper(one, tmp, tmpP, tmpQ, tmpa, tmpb); + + return outSz; +} + + +int wc_RsaEncryptSize(RsaKey* key) +{ + if (key == NULL) + return 0; + + return key->sz; +} + + +/* flatten RsaKey structure into individual elements (e, n) */ +int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, + word32* nSz) +{ + int sz, bytSz; + IppStatus ret; + + USER_DEBUG(("Entering wc_RsaFlattenPublicKey\n")); + + if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) + return USER_CRYPTO_ERROR; + + 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)? 1 : 0); + + if (*eSz < (word32)sz) + return USER_CRYPTO_ERROR; + + ret = ippsGetOctString_BN(e, sz, key->e); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *eSz = (word32)sz; + + /* flatten n */ + ret = ippsExtGet_BN(NULL, &sz, NULL, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* sz is in bits change to bytes */ + sz = (sz / bytSz) + ((sz % bytSz)? 1: 0); + + if (*nSz < (word32)sz) + return USER_CRYPTO_ERROR; + + ret = ippsGetOctString_BN(n, sz, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *nSz = (word32)sz; + + return 0; +} + + +IppStatus wolfSSL_rng(Ipp32u* pData, int nBits, void* pEbsParams); +IppStatus wolfSSL_rng(Ipp32u* pData, int nBits, void* pEbsParams) +{ + int nBytes; + + if (pData == NULL) { + USER_DEBUG(("error with wolfSSL_rng argument\n")); + return ippStsErr; + } + + nBytes = (nBits/8) + ((nBits % 8)? 1: 0); + if (wc_RNG_GenerateBlock((WC_RNG*)pEbsParams, (byte*)pData, nBytes) != 0) { + USER_DEBUG(("error in generating random wolfSSL block\n")); + return ippStsErr; + } + + return ippStsNoErr; +} + + +#ifdef WOLFSSL_KEY_GEN +/* Make an RSA key for size bits, with e specified, 65537 is a good e */ +int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) +{ + IppStatus ret; + int scratchSz; + int i; /* for trys on calling make key */ + int ctxSz; + + IppsBigNumState* pSrcPublicExp = NULL; + Ipp8u* scratchBuffer = NULL; + Ipp8u eAry[8]; + int trys = 8; /* Miller-Rabin test parameter */ + IppsPrimeState* pPrime = NULL; + + int qBitSz; /* size of q factor */ + int bytSz; /* size of key in bytes */ + int leng; + + USER_DEBUG(("Entering wc_MakeRsaKey\n")); + + /* get byte size and individual private key size -- round up */ + qBitSz = (size / 2) + ((size % 2)? 1: 0); + bytSz = (size / 8) + ((size % 8)? 1: 0); + + 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; + + if (size > RSA_MAX_SIZE || size < RSA_MIN_SIZE) + return USER_CRYPTO_ERROR; + + key->type = RSA_PRIVATE; + key->sz = bytSz; + + /* initialize prime number */ + ret = ippsPrimeGetSize(size, &ctxSz); /* size in bits */ + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsPrimeGetSize error of %s\n", ippGetStatusString(ret))); + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + pPrime = (IppsPrimeState*)XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + 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))); + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* define RSA privete key type 2 */ + /* length in bits of p and q factors */ + ret = ippsRSA_GetSizePrivateKeyType2(qBitSz, qBitSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKeyType2 error of %s\n", + ippGetStatusString(ret))); + 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) { + 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))); + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* allocate scratch buffer */ + ret = ippsRSA_GetBufferSizePrivateKey(&scratchSz, key->pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetBufferSizePrivateKey error of %s\n", + ippGetStatusString(ret))); + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + scratchBuffer = (Ipp8u*)XMALLOC(scratchSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (scratchBuffer == NULL) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* set up initial value of pScrPublicExp */ + leng = (int)sizeof(long); /* # of Ipp32u in long */ + + /* place the value of e into the array eAry then load into BN */ + for (i = 0; i < leng; i++) { + eAry[i] = (e >> (8 * (leng - 1 - i))) & 0XFF; + } + ret = init_bn(&pSrcPublicExp, leng); + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + ret = ippsSetOctString_BN(eAry, leng, pSrcPublicExp); + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* initializing key->n */ + ret = init_bn(&key->n, bytSz); + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* initializing public exponent key->e */ + ret = init_bn(&key->e, leng); + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* private exponent key->dipp */ + ret = init_bn(&key->dipp, bytSz); + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* 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); + if (ret == ippStsNoErr) { + break; + } + + /* catch all errors other than entropy error */ + if (ret != ippStsInsufficientEntropy) { + USER_DEBUG(("ippsRSA_GeneratKeys error of %s\n", + ippGetStatusString(ret))); + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + } + + /* 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))); + 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))); + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s nSz = %d eSz = %d\n", + ippGetStatusString(ret), key->nSz, key->eSz)); + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + key->pPub = (IppsRSAPublicKeyState*)XMALLOC(ctxSz, NULL, + DYNAMIC_TYPE_USER_CRYPTO); + 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))); + 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))); + 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) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* set up q BN for key */ + ret = init_bn(&key->qipp, leng); + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* set up dP BN for key */ + ret = init_bn(&key->dPipp, leng); + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* set up dQ BN for key */ + ret = init_bn(&key->dQipp, leng); + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* set up u BN for key */ + ret = init_bn(&key->uipp, leng); + if (ret != ippStsNoErr) { + ret = USER_CRYPTO_ERROR; + goto makeKeyEnd; + } + + /* get values from created key */ + ret = ippsRSA_GetPrivateKeyType2(key->pipp, key->qipp, key->dPipp, + key->dQipp, key->uipp, key->pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetPrivateKeyType2 error %s\n", + ippGetStatusString(ret))); + 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); + + if (ret != 0) { /* with fail case free RSA components created */ + wc_FreeRsaKey(key); + } + + return ret; +} + +#endif + +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) + +/********** duplicate code needed -- future refactor */ +#define MAX_VERSION_SZ 5 +#define MAX_SEQ_SZ 5 +#define ASN_CONTEXT_SPECIFIC 0x80 +#define ASN_CONSTRUCTED 0x20 +#define ASN_LONG_LENGTH 0x80 +#define ASN_SEQUENCE 0x10 +#define RSA_INTS 8 +#define FALSE 0 +#define TRUE 1 + +#define MAX_LENGTH_SZ 4 +#define RSAk 645 +#define keyType 2 +#define MAX_RSA_INT_SZ 517 +#define MAX_RSA_E_SZ 16 +#define MAX_ALGO_SZ 20 + +static word32 BytePrecision(word32 value) +{ + word32 i; + for (i = sizeof(value); i; --i) + if (value >> ((i - 1) * WOLFSSL_BIT_SIZE)) + break; + + return i; +} + + +static int SetMyVersion(word32 version, byte* output, int header) +{ + int i = 0; + + if (output == NULL) + return USER_CRYPTO_ERROR; + + if (header) { + output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED; + output[i++] = ASN_BIT_STRING; + } + output[i++] = ASN_INTEGER; + output[i++] = 0x01; + output[i++] = (byte)version; + + return i; +} + + +static word32 SetLength(word32 length, byte* output) +{ + word32 i = 0, j; + + if (length < 0x80) + output[i++] = (byte)length; + else { + output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH); + + for (j = BytePrecision(length); j; --j) { + output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE)); + i++; + } + } + + return i; +} + + +static word32 SetSequence(word32 len, byte* output) +{ + output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED; + return SetLength(len, output + 1) + 1; +} + + +static word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) +{ + /* adding TAG_NULL and 0 to end */ + + /* RSA keyType */ + #ifndef NO_RSA + static const byte RSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00}; + #endif /* NO_RSA */ + + int algoSz = 0; + int tagSz = 2; /* tag null and terminator */ + word32 idSz, seqSz; + const byte* algoName = 0; + byte ID_Length[MAX_LENGTH_SZ]; + byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ + + if (type == keyType) { /* keyType */ + switch (algoOID) { + #ifndef NO_RSA + case RSAk: + algoSz = sizeof(RSA_AlgoID); + algoName = RSA_AlgoID; + break; + #endif /* NO_RSA */ + default: + /* unknown key algo */ + return 0; + } + } + else { + /* unknown algo type */ + return 0; + } + + idSz = SetLength(algoSz - tagSz, ID_Length); /* don't include tags */ + seqSz = SetSequence(idSz + algoSz + 1 + curveSz, seqArray); + /* +1 for object id, curveID of curveSz follows for ecc */ + seqArray[seqSz++] = ASN_OBJECT_ID; + + XMEMCPY(output, seqArray, seqSz); + XMEMCPY(output + seqSz, ID_Length, idSz); + XMEMCPY(output + seqSz + idSz, algoName, algoSz); + + return seqSz + idSz + algoSz; + +} + + +/* Write a public RSA key to output */ +static int SetRsaPublicKey(byte* output, RsaKey* key, + int outLen, int with_header) +{ +#ifdef WOLFSSL_SMALL_STACK + byte* n = NULL; + byte* e = NULL; +#else + byte n[MAX_RSA_INT_SZ]; + byte e[MAX_RSA_E_SZ]; +#endif + byte seq[MAX_SEQ_SZ]; + byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */ + int nSz; + int eSz; + int seqSz; + int lenSz; + int idx; + int rawLen; + int leadingBit; + int err; + + if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) + return USER_CRYPTO_ERROR; + + /* n */ +#ifdef WOLFSSL_SMALL_STACK + n = (byte*)XMALLOC(MAX_RSA_INT_SZ, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (n == NULL) + return USER_CRYPTO_ERROR; +#endif + + leadingBit = wc_Rsa_leading_bit(key->n); + rawLen = wc_Rsa_unsigned_bin_size(key->n); + if ((int)rawLen < 0) { + return USER_CRYPTO_ERROR; + } + + rawLen = rawLen + leadingBit; + n[0] = ASN_INTEGER; + nSz = SetLength(rawLen, n + 1) + 1; /* int tag */ + + if ( (nSz + rawLen) < MAX_RSA_INT_SZ) { + if (leadingBit) + n[nSz] = 0; + err = ippsGetOctString_BN((Ipp8u*)n + nSz, rawLen - leadingBit, key->n); + if (err == ippStsNoErr) + nSz += rawLen; + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + return USER_CRYPTO_ERROR; + } + } + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + return USER_CRYPTO_ERROR; + } + + /* e */ +#ifdef WOLFSSL_SMALL_STACK + e = (byte*)XMALLOC(MAX_RSA_E_SZ, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (e == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + return USER_CRYPTO_ERROR; + } +#endif + + leadingBit = wc_Rsa_leading_bit(key->e); + rawLen = wc_Rsa_unsigned_bin_size(key->e); + if ((int)rawLen < 0) { + return USER_CRYPTO_ERROR; + } + + rawLen = rawLen + leadingBit; + e[0] = ASN_INTEGER; + eSz = SetLength(rawLen, e + 1) + 1; /* int tag */ + + if ( (eSz + rawLen) < MAX_RSA_E_SZ) { + if (leadingBit) + e[eSz] = 0; + err = ippsGetOctString_BN((Ipp8u*)e + eSz, rawLen - leadingBit, key->e); + if (err == ippStsNoErr) + eSz += rawLen; + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + return USER_CRYPTO_ERROR; + } + } + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + return USER_CRYPTO_ERROR; + } + + seqSz = SetSequence(nSz + eSz, seq); + + /* check output size */ + if ( (seqSz + nSz + eSz) > outLen) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + return USER_CRYPTO_ERROR; + } + + /* headers */ + if (with_header) { + int algoSz; +#ifdef WOLFSSL_SMALL_STACK + byte* algo; + + algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (algo == NULL) { + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return USER_CRYPTO_ERROR; + } +#else + byte algo[MAX_ALGO_SZ]; +#endif + algoSz = SetAlgoID(RSAk, algo, keyType, 0); + lenSz = SetLength(seqSz + nSz + eSz + 1, len); + len[lenSz++] = 0; /* trailing 0 */ + + /* write, 1 is for ASN_BIT_STRING */ + idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output); + + /* check output size */ + if ( (idx + algoSz + 1 + lenSz + seqSz + nSz + eSz) > outLen) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(algo, NULL, DYNAMIC_TYPE_USER_CRYPTO); + #endif + + return USER_CRYPTO_ERROR; + } + + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* bit string */ + output[idx++] = ASN_BIT_STRING; + /* length */ + XMEMCPY(output + idx, len, lenSz); + idx += lenSz; +#ifdef WOLFSSL_SMALL_STACK + XFREE(algo, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + } + else + idx = 0; + + /* seq */ + XMEMCPY(output + idx, seq, seqSz); + idx += seqSz; + /* n */ + XMEMCPY(output + idx, n, nSz); + idx += nSz; + /* e */ + XMEMCPY(output + idx, e, eSz); + idx += eSz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + + return idx; +} + + +static IppsBigNumState* GetRsaInt(RsaKey* key, int idx) +{ + if (idx == 0) + return key->n; + if (idx == 1) + return key->e; + if (idx == 2) + return key->dipp; + if (idx == 3) + return key->pipp; + if (idx == 4) + return key->qipp; + if (idx == 5) + return key->dPipp; + if (idx == 6) + return key->dQipp; + if (idx == 7) + return key->uipp; + + return NULL; +} + + +/* Release Tmp RSA resources */ +static WC_INLINE void FreeTmpRsas(byte** tmps, void* heap) +{ + int i; + + (void)heap; + + for (i = 0; i < RSA_INTS; i++) + XFREE(tmps[i], heap, DYNAMIC_TYPE_USER_CRYPTO); +} + + +/* Convert RsaKey key to DER format, write to output (inLen), return bytes + written */ +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; + + byte seq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + byte* tmps[RSA_INTS]; + + USER_DEBUG(("Entering RsaKeyToDer\n")); + + if (!key) + return USER_CRYPTO_ERROR; + + if (key->type != RSA_PRIVATE) + return USER_CRYPTO_ERROR; + + for (i = 0; i < RSA_INTS; i++) + tmps[i] = NULL; + + /* write all big ints from key to DER tmps */ + for (i = 0; i < RSA_INTS; i++) { + Ipp32u isZero; + IppsBigNumState* keyInt = GetRsaInt(key, i); + + ippsCmpZero_BN(keyInt, &isZero); /* makes isZero 0 if true */ + rawLen = wc_Rsa_unsigned_bin_size(keyInt); + if ((int)rawLen < 0) { + return USER_CRYPTO_ERROR; + } + + /* leading zero */ + if (!isZero || wc_Rsa_leading_bit(keyInt)) + lbit = 1; + else + lbit = 0; + + rawLen += lbit; + + tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, + DYNAMIC_TYPE_USER_CRYPTO); + if (tmps[i] == NULL) { + ret = USER_CRYPTO_ERROR; + 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; + + /* extract data*/ + err = ippsGetOctString_BN((Ipp8u*)(tmps[i] + sizes[i]), + rawLen - lbit, keyInt); + if (err == ippStsOk) { + sizes[i] += (rawLen-lbit); /* lbit included in rawLen */ + intTotalLen += sizes[i]; + ret = 0; + } + else { + ret = USER_CRYPTO_ERROR; + USER_DEBUG(("ippsGetOctString_BN error %s\n", + ippGetStatusString(err))); + break; + } + } + else { + ret = USER_CRYPTO_ERROR; + break; + } + } + + if (ret != 0) { + FreeTmpRsas(tmps, key->heap); + return ret; + } + + /* make headers */ + verSz = SetMyVersion(0, ver, FALSE); + seqSz = SetSequence(verSz + intTotalLen, seq); + + outLen = seqSz + verSz + intTotalLen; + if (output) { + if (outLen > (int)inLen) { + return USER_CRYPTO_ERROR; + } + + /* write to output */ + XMEMCPY(output, seq, seqSz); + j = seqSz; + XMEMCPY(output + j, ver, verSz); + j += verSz; + + for (i = 0; i < RSA_INTS; i++) { + XMEMCPY(output + j, tmps[i], sizes[i]); + j += sizes[i]; + } + } + FreeTmpRsas(tmps, key->heap); + + return outLen; +} + + +/* Convert Rsa Public key to DER format, write to output (inLen), return bytes + written +*/ +int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen) +{ + return SetRsaPublicKey(output, key, inLen, 1); +} + + +#endif /* WOLFSSL_KEY_GEN || OPENSSL_EXTRA */ + +#ifdef WC_RSA_BLINDING + +int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng) +{ + if (key == NULL) + return USER_CRYPTO_ERROR; + + (void)rng; + + return 0; +} + +#endif /* WC_RSA_BLINDING */ + +#endif /* NO_RSA */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl-ntru.sln b/FreeRTOS-Plus/Source/WolfSSL/wolfssl-ntru.sln new file mode 100644 index 000000000..c43e1cf19 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl-ntru.sln @@ -0,0 +1,65 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfssl", "wolfssl-ntru.vcproj", "{73973223-5EE8-41CA-8E88-1D60E89A237B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsuite", "testsuite\testsuite-ntru.vcproj", "{611E8971-46E0-4D0A-B5A1-632C3B00CB80}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "echoserver", "examples\echoserver\echoserver-ntru.vcproj", "{07D97C48-E08F-4E34-9F67-3064039FF2CB}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "echoclient", "examples\echoclient\echoclient-ntru.vcproj", "{8362A816-C5DC-4E22-B5C5-9E6806387073}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client", "examples\client\client-ntru.vcproj", "{3ADE9549-582D-4D8E-9826-B172197A7959}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server", "examples\server\server-ntru.vcproj", "{E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.ActiveCfg = Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.Build.0 = Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.ActiveCfg = Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.Build.0 = Release|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|Win32.ActiveCfg = Debug|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|Win32.Build.0 = Debug|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|Win32.ActiveCfg = Release|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|Win32.Build.0 = Release|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Debug|Win32.ActiveCfg = Debug|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Debug|Win32.Build.0 = Debug|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Release|Win32.ActiveCfg = Release|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Release|Win32.Build.0 = Release|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Debug|Win32.ActiveCfg = Debug|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Debug|Win32.Build.0 = Debug|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Release|Win32.ActiveCfg = Release|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Release|Win32.Build.0 = Release|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Debug|Win32.ActiveCfg = Debug|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Debug|Win32.Build.0 = Debug|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Release|Win32.ActiveCfg = Release|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Release|Win32.Build.0 = Release|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Debug|Win32.ActiveCfg = Debug|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Debug|Win32.Build.0 = Debug|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Release|Win32.ActiveCfg = Release|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl-ntru.vcproj b/FreeRTOS-Plus/Source/WolfSSL/wolfssl-ntru.vcproj new file mode 100644 index 000000000..18964c739 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl-ntru.vcproj @@ -0,0 +1,349 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl.rc b/FreeRTOS-Plus/Source/WolfSSL/wolfssl.rc new file mode 100644 index 0000000000000000000000000000000000000000..1f5bcd15c2791e0768b6dea0f84decb9f93e11cf GIT binary patch literal 4918 zcmdUzOK%!U5Xb8rX}`k+UlL_w{GY-Eo%vxy~)fz5$+fF-uDdmFQ>*ejmMhSs;3 zF#|ql?g5)Ii*CW{k#)pQ+(tG9=g@w!XPk26<^!NHZ^vNw9Byfi{?I;H$zhA~z~K!X zop`^q8*5t2+IDW2*08SKS{3Ly>uamqA3&P?UfCItI_q%0WZ1taNEhbFYS?Af#sjQ0 zv5)9K$2zh@3$5Stdx_Q+^priSz~3-dJ@U^!_{-VX)8*~Ie-;Z8`RG_+D@D=(y?2X^ zVEMpzzvduagm+`|Z;YoBVj!{?_&jD8^03LuXJuk93!)&&v=A>dT@Ma7etlM zsV4c;Cc7$}+$Fl|JmUL>C)!Bag2yc}+=c2I`j_t1I?!vNZRVPb(*W^!HF#f=tH0T= z@NR;42E@~>Vsv@yv)V_1blDsM%8w43{LZQ8|GQdHoaG@VG;17VvtrE1y+1?unyVDT zj+Rex<-N1=viiz@-eRIsUD@S~qKaR#^?FmXJL=XQ5$$V#D&;1LPIi=N+j9(Lf`v|m*vD~%-7KFqrNb;BoUJi#9U9yIBYeO+*>g<~U7j*>2C3#(4!HMjYyw@nZ;c;)^-yj0pRG`*RQ3UQ6u6ERr?ur`HB=;jY|7|CD zuRZ*^uvJTyYHK7NXkb+VF;#oR(xy)ObHifrg?%+rDII=+rxz!6zx$R>6MBLr8>jT%_q1rM*g8^DKp^2O( zj~h-e<{xZu4%cii>+>O;(^__7tLOER<^jr{yOq=-2T62yKVa#5#wXyq$s=}=yVZyA znVoq}3GI2#C&6L`h#+lH0rcF_qAoX}FiR*A3I-ZLADVCH)eS`$L*Wai=thj#d4ccgIqfKLZhH8Se2^pbX zQLcHd4)ND`OYLqrX#(AX$e3@mn$MtZG|2Pa-P>sw6yj+elCOImY&82}v0dtDzS_0m zrVLQrDEhNiNVl4=vdWrc=jZbBhVk;I(xxljK%2Xo|K>X*+hOe2TH0ra?**Rvid^sN v_DiFzG}27_F#p^C6HbV$r~gj~w#-VgUu#LYIo@OHkM6$pe-GCEE>7P8>El_@ literal 0 HcmV?d00001 diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl.sln b/FreeRTOS-Plus/Source/WolfSSL/wolfssl.sln new file mode 100644 index 000000000..15fa6f791 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl.sln @@ -0,0 +1,74 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfssl", "wolfssl.vcproj", "{73973223-5EE8-41CA-8E88-1D60E89A237B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsuite", "testsuite\testsuite.vcproj", "{611E8971-46E0-4D0A-B5A1-632C3B00CB80}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sslSniffer", "sslSniffer\sslSniffer.vcproj", "{34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "echoserver", "examples\echoserver\echoserver.vcproj", "{07D97C48-E08F-4E34-9F67-3064039FF2CB}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "echoclient", "examples\echoclient\echoclient.vcproj", "{8362A816-C5DC-4E22-B5C5-9E6806387073}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client", "examples\client\client.vcproj", "{3ADE9549-582D-4D8E-9826-B172197A7959}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server", "examples\server\server.vcproj", "{E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}" + ProjectSection(ProjectDependencies) = postProject + {73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.ActiveCfg = Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.Build.0 = Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.ActiveCfg = Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.Build.0 = Release|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|Win32.ActiveCfg = Debug|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|Win32.Build.0 = Debug|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|Win32.ActiveCfg = Release|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|Win32.Build.0 = Release|Win32 + {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.Debug|Win32.ActiveCfg = Debug|Win32 + {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.Debug|Win32.Build.0 = Debug|Win32 + {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.Release|Win32.ActiveCfg = Release|Win32 + {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.Release|Win32.Build.0 = Release|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Debug|Win32.ActiveCfg = Debug|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Debug|Win32.Build.0 = Debug|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Release|Win32.ActiveCfg = Release|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Release|Win32.Build.0 = Release|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Debug|Win32.ActiveCfg = Debug|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Debug|Win32.Build.0 = Debug|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Release|Win32.ActiveCfg = Release|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Release|Win32.Build.0 = Release|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Debug|Win32.ActiveCfg = Debug|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Debug|Win32.Build.0 = Debug|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Release|Win32.ActiveCfg = Release|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Release|Win32.Build.0 = Release|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Debug|Win32.ActiveCfg = Debug|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Debug|Win32.Build.0 = Debug|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Release|Win32.ActiveCfg = Release|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl.vcproj b/FreeRTOS-Plus/Source/WolfSSL/wolfssl.vcproj new file mode 100644 index 000000000..5505e4912 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl.vcproj @@ -0,0 +1,406 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl.vcxproj b/FreeRTOS-Plus/Source/WolfSSL/wolfssl.vcxproj new file mode 100644 index 000000000..834c307e0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl.vcxproj @@ -0,0 +1,372 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + DLL Debug + Win32 + + + DLL Debug + x64 + + + DLL Release + Win32 + + + DLL Release + x64 + + + Release + Win32 + + + Release + x64 + + + + {73973223-5EE8-41CA-8E88-1D60E89A237B} + wolfssl + Win32Proj + + + + StaticLibrary + v110 + Unicode + true + + + DynamicLibrary + v110 + Unicode + true + + + StaticLibrary + v110 + Unicode + true + + + DynamicLibrary + v110 + Unicode + true + + + StaticLibrary + v110 + Unicode + + + DynamicLibrary + v110 + Unicode + + + StaticLibrary + v110 + Unicode + + + DynamicLibrary + v110 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\obj\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\obj\ + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\obj\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\obj\ + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\obj\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\obj\ + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\obj\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\obj\ + + + + Disabled + ./;./IDE/WIN;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level4 + EditAndContinue + 4206;4214;4706;%(DisableSpecificWarnings) + + + + + Disabled + ./;./IDE/WIN;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;BUILDING_WOLFSSL;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + EditAndContinue + 4206;4214;4706;%(DisableSpecificWarnings) + + + ws2_32.lib;%(AdditionalDependencies) + false + true + false + + + + + Disabled + ./;./IDE/WIN;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + ProgramDatabase + 4206;4214;4706;%(DisableSpecificWarnings) + + + + + Disabled + ./;./IDE/WIN;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;BUILDING_WOLFSSL;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + ProgramDatabase + 4206;4214;4706;%(DisableSpecificWarnings) + + + ws2_32.lib;%(AdditionalDependencies) + false + true + + + + + MaxSpeed + true + ./;./IDE/WIN;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + + + MaxSpeed + true + ./;./IDE/WIN;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;BUILDING_WOLFSSL;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + + + ws2_32.lib;%(AdditionalDependencies) + true + + + + + MaxSpeed + true + ./;./IDE/WIN;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + + + + + MaxSpeed + true + ./;./IDE/WIN;%(AdditionalIncludeDirectories) + WOLFSSL_LIB;BUILDING_WOLFSSL;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + + + ws2_32.lib;%(AdditionalDependencies) + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + false + false + ml64.exe /c /Zi /Fo"$(OutDir)%(Filename).obj" %(Identity) + ml64.exe /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(OutDir)%(Filename).obj + $(IntDir)%(Filename).obj + + + + + + true + true + true + true + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/callbacks.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/callbacks.h index 8794e9e4a..eed27293c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/callbacks.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/callbacks.h @@ -1,8 +1,8 @@ /* callbacks.h * - * Copyright (C) 2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,46 +16,59 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLFSSL_CALLBACKS_H #define WOLFSSL_CALLBACKS_H -#include +#include #ifdef __cplusplus extern "C" { #endif -enum { /* CALLBACK CONTSTANTS */ +enum { /* CALLBACK CONSTANTS */ 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 */ }; +struct WOLFSSL; 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; -typedef struct timeval Timeval; - +#if defined(HAVE_SYS_TIME_H) && !defined(NO_TIMEVAL) + typedef struct timeval WOLFSSL_TIMEVAL; +#else /* HAVE_SYS_TIME_H */ + /* Define the timeval explicitly. */ + typedef struct { + long tv_sec; /* Seconds. */ + long tv_usec; /* Microseconds. */ + } WOLFSSL_TIMEVAL; +#endif /* HAVE_SYS_TIME_H */ +#if !defined(NO_OLD_TIMEVAL_NAME) + #define Timeval WOLFSSL_TIMEVAL +#endif typedef struct packetInfo_st { char packetName[MAX_PACKETNAME_SZ + 1]; /* SSL packet name */ - Timeval timestamp; /* when it occured */ - unsigned char value[MAX_VALUE_SZ]; /* if fits, it's here */ + WOLFSSL_TIMEVAL timestamp; /* when it occurred */ + 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; @@ -66,7 +79,7 @@ typedef struct timeoutInfo_st { int flags; /* for future use */ int numberPackets; /* actual # of packets */ PacketInfo packets[MAX_PACKETS_HANDSHAKE]; /* list of all packets */ - Timeval timeoutValue; /* timer that caused it */ + WOLFSSL_TIMEVAL timeoutValue; /* timer that caused it */ } TimeoutInfo; diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/certs_test.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/certs_test.h index 3ce491551..6562e9f6e 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/certs_test.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/certs_test.h @@ -8,565 +8,964 @@ /* ./certs/1024/client-key.der, 1024-bit */ static const unsigned char client_key_der_1024[] = { - 0x30, 0x82, 0x02, 0x5C, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, - 0x00, 0xBC, 0x73, 0x0E, 0xA8, 0x49, 0xF3, 0x74, 0xA2, 0xA9, - 0xEF, 0x18, 0xA5, 0xDA, 0x55, 0x99, 0x21, 0xF9, 0xC8, 0xEC, - 0xB3, 0x6D, 0x48, 0xE5, 0x35, 0x35, 0x75, 0x77, 0x37, 0xEC, - 0xD1, 0x61, 0x90, 0x5F, 0x3E, 0xD9, 0xE4, 0xD5, 0xDF, 0x94, - 0xCA, 0xC1, 0xA9, 0xD7, 0x19, 0xDA, 0x86, 0xC9, 0xE8, 0x4D, - 0xC4, 0x61, 0x36, 0x82, 0xFE, 0xAB, 0xAD, 0x7E, 0x77, 0x25, - 0xBB, 0x8D, 0x11, 0xA5, 0xBC, 0x62, 0x3A, 0xA8, 0x38, 0xCC, - 0x39, 0xA2, 0x04, 0x66, 0xB4, 0xF7, 0xF7, 0xF3, 0xAA, 0xDA, - 0x4D, 0x02, 0x0E, 0xBB, 0x5E, 0x8D, 0x69, 0x48, 0xDC, 0x77, - 0xC9, 0x28, 0x0E, 0x22, 0xE9, 0x6B, 0xA4, 0x26, 0xBA, 0x4C, - 0xE8, 0xC1, 0xFD, 0x4A, 0x6F, 0x2B, 0x1F, 0xEF, 0x8A, 0xAE, - 0xF6, 0x90, 0x62, 0xE5, 0x64, 0x1E, 0xEB, 0x2B, 0x3C, 0x67, - 0xC8, 0xDC, 0x27, 0x00, 0xF6, 0x91, 0x68, 0x65, 0xA9, 0x02, - 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x13, 0x97, 0xEA, - 0xE8, 0x38, 0x78, 0x25, 0xA2, 0x5C, 0x04, 0xCE, 0x0D, 0x40, - 0x7C, 0x31, 0xE5, 0xC4, 0x70, 0xCD, 0x9B, 0x82, 0x3B, 0x58, - 0x09, 0x86, 0x3B, 0x66, 0x5F, 0xDC, 0x31, 0x90, 0xF1, 0x4F, - 0xD5, 0xDB, 0x15, 0xDD, 0xDE, 0xD7, 0x3B, 0x95, 0x93, 0x31, - 0x18, 0x31, 0x0E, 0x5E, 0xA3, 0xD6, 0xA2, 0x1A, 0x71, 0x6E, - 0x81, 0x48, 0x1C, 0x4B, 0xCF, 0xDB, 0x8E, 0x7A, 0x86, 0x61, - 0x32, 0xDC, 0xFB, 0x55, 0xC1, 0x16, 0x6D, 0x27, 0x92, 0x24, - 0x45, 0x8B, 0xF1, 0xB8, 0x48, 0xB1, 0x4B, 0x1D, 0xAC, 0xDE, - 0xDA, 0xDD, 0x8E, 0x2F, 0xC2, 0x91, 0xFB, 0xA5, 0xA9, 0x6E, - 0xF8, 0x3A, 0x6A, 0xF1, 0xFD, 0x50, 0x18, 0xEF, 0x9F, 0xE7, - 0xC3, 0xCA, 0x78, 0xEA, 0x56, 0xD3, 0xD3, 0x72, 0x5B, 0x96, - 0xDD, 0x4E, 0x06, 0x4E, 0x3A, 0xC3, 0xD9, 0xBE, 0x72, 0xB6, - 0x65, 0x07, 0x07, 0x4C, 0x01, 0x02, 0x41, 0x00, 0xFA, 0x47, - 0xD4, 0x7A, 0x7C, 0x92, 0x3C, 0x55, 0xEF, 0x81, 0xF0, 0x41, - 0x30, 0x2D, 0xA3, 0xCF, 0x8F, 0x1C, 0xE6, 0x87, 0x27, 0x05, - 0x70, 0x0D, 0xDF, 0x98, 0x35, 0xD6, 0xF1, 0x8B, 0x38, 0x2F, - 0x24, 0xB5, 0xD0, 0x84, 0xB6, 0x79, 0x4F, 0x71, 0x29, 0x94, - 0x5A, 0xF0, 0x64, 0x6A, 0xAC, 0xE7, 0x72, 0xC6, 0xED, 0x4D, - 0x59, 0x98, 0x3E, 0x67, 0x3A, 0xF3, 0x74, 0x2C, 0xF9, 0x61, - 0x17, 0x69, 0x02, 0x41, 0x00, 0xC0, 0xC1, 0x82, 0x0D, 0x0C, - 0xEB, 0xC6, 0x2F, 0xDC, 0x92, 0xF9, 0x9D, 0x82, 0x1A, 0x31, - 0xE9, 0xE9, 0xF7, 0x4B, 0xF2, 0x82, 0x87, 0x1C, 0xEE, 0x16, - 0x6A, 0xD1, 0x1D, 0x18, 0x82, 0x70, 0xF3, 0xC0, 0xB6, 0x2F, - 0xF6, 0xF3, 0xF7, 0x1D, 0xF1, 0x86, 0x23, 0xC8, 0x4E, 0xEB, - 0x8F, 0x56, 0x8E, 0x8F, 0xF5, 0xBF, 0xF1, 0xF7, 0x2B, 0xB5, - 0xCC, 0x3D, 0xC6, 0x57, 0x39, 0x0C, 0x1B, 0x54, 0x41, 0x02, - 0x41, 0x00, 0x9D, 0x7E, 0x05, 0xDE, 0xED, 0xF4, 0xB7, 0xB2, - 0xFB, 0xFC, 0x30, 0x4B, 0x55, 0x1D, 0xE3, 0x2F, 0x01, 0x47, - 0x96, 0x69, 0x05, 0xCD, 0x0E, 0x2E, 0x2C, 0xBD, 0x83, 0x63, - 0xB6, 0xAB, 0x7C, 0xB7, 0x6D, 0xCA, 0x5B, 0x64, 0xA7, 0xCE, - 0xBE, 0x86, 0xDF, 0x3B, 0x53, 0xDE, 0x61, 0xD2, 0x1E, 0xEB, - 0xA5, 0xF6, 0x37, 0xED, 0xAC, 0xAB, 0x78, 0xD9, 0x4C, 0xE7, - 0x55, 0xFB, 0xD7, 0x11, 0x99, 0xC1, 0x02, 0x40, 0x18, 0x98, - 0x18, 0x29, 0xE6, 0x1E, 0x27, 0x39, 0x70, 0x21, 0x68, 0xAC, - 0x0A, 0x2F, 0xA1, 0x72, 0xC1, 0x21, 0x86, 0x95, 0x38, 0xC6, - 0x58, 0x90, 0xA0, 0x57, 0x9C, 0xBA, 0xE3, 0xA7, 0xB1, 0x15, - 0xC8, 0xDE, 0xF6, 0x1B, 0xC2, 0x61, 0x23, 0x76, 0xEF, 0xB0, - 0x9D, 0x1C, 0x44, 0xBE, 0x13, 0x43, 0x39, 0x67, 0x17, 0xC8, - 0x9D, 0xCA, 0xFB, 0xF5, 0x45, 0x64, 0x8B, 0x38, 0x82, 0x2C, - 0xF2, 0x81, 0x02, 0x40, 0x39, 0x89, 0xE5, 0x9C, 0x19, 0x55, - 0x30, 0xBA, 0xB7, 0x48, 0x8C, 0x48, 0x14, 0x0E, 0xF4, 0x9F, - 0x7E, 0x77, 0x97, 0x43, 0xE1, 0xB4, 0x19, 0x35, 0x31, 0x23, - 0x75, 0x9C, 0x3B, 0x44, 0xAD, 0x69, 0x12, 0x56, 0xEE, 0x00, - 0x61, 0x64, 0x16, 0x66, 0xD3, 0x7C, 0x74, 0x2B, 0x15, 0xB4, - 0xA2, 0xFE, 0xBF, 0x08, 0x6B, 0x1A, 0x5D, 0x3F, 0x90, 0x12, - 0xB1, 0x05, 0x86, 0x31, 0x29, 0xDB, 0xD9, 0xE2 + 0x30, 0x82, 0x02, 0x5C, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xBC, 0x73, 0x0E, 0xA8, 0x49, 0xF3, 0x74, 0xA2, 0xA9, + 0xEF, 0x18, 0xA5, 0xDA, 0x55, 0x99, 0x21, 0xF9, 0xC8, 0xEC, + 0xB3, 0x6D, 0x48, 0xE5, 0x35, 0x35, 0x75, 0x77, 0x37, 0xEC, + 0xD1, 0x61, 0x90, 0x5F, 0x3E, 0xD9, 0xE4, 0xD5, 0xDF, 0x94, + 0xCA, 0xC1, 0xA9, 0xD7, 0x19, 0xDA, 0x86, 0xC9, 0xE8, 0x4D, + 0xC4, 0x61, 0x36, 0x82, 0xFE, 0xAB, 0xAD, 0x7E, 0x77, 0x25, + 0xBB, 0x8D, 0x11, 0xA5, 0xBC, 0x62, 0x3A, 0xA8, 0x38, 0xCC, + 0x39, 0xA2, 0x04, 0x66, 0xB4, 0xF7, 0xF7, 0xF3, 0xAA, 0xDA, + 0x4D, 0x02, 0x0E, 0xBB, 0x5E, 0x8D, 0x69, 0x48, 0xDC, 0x77, + 0xC9, 0x28, 0x0E, 0x22, 0xE9, 0x6B, 0xA4, 0x26, 0xBA, 0x4C, + 0xE8, 0xC1, 0xFD, 0x4A, 0x6F, 0x2B, 0x1F, 0xEF, 0x8A, 0xAE, + 0xF6, 0x90, 0x62, 0xE5, 0x64, 0x1E, 0xEB, 0x2B, 0x3C, 0x67, + 0xC8, 0xDC, 0x27, 0x00, 0xF6, 0x91, 0x68, 0x65, 0xA9, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x13, 0x97, 0xEA, + 0xE8, 0x38, 0x78, 0x25, 0xA2, 0x5C, 0x04, 0xCE, 0x0D, 0x40, + 0x7C, 0x31, 0xE5, 0xC4, 0x70, 0xCD, 0x9B, 0x82, 0x3B, 0x58, + 0x09, 0x86, 0x3B, 0x66, 0x5F, 0xDC, 0x31, 0x90, 0xF1, 0x4F, + 0xD5, 0xDB, 0x15, 0xDD, 0xDE, 0xD7, 0x3B, 0x95, 0x93, 0x31, + 0x18, 0x31, 0x0E, 0x5E, 0xA3, 0xD6, 0xA2, 0x1A, 0x71, 0x6E, + 0x81, 0x48, 0x1C, 0x4B, 0xCF, 0xDB, 0x8E, 0x7A, 0x86, 0x61, + 0x32, 0xDC, 0xFB, 0x55, 0xC1, 0x16, 0x6D, 0x27, 0x92, 0x24, + 0x45, 0x8B, 0xF1, 0xB8, 0x48, 0xB1, 0x4B, 0x1D, 0xAC, 0xDE, + 0xDA, 0xDD, 0x8E, 0x2F, 0xC2, 0x91, 0xFB, 0xA5, 0xA9, 0x6E, + 0xF8, 0x3A, 0x6A, 0xF1, 0xFD, 0x50, 0x18, 0xEF, 0x9F, 0xE7, + 0xC3, 0xCA, 0x78, 0xEA, 0x56, 0xD3, 0xD3, 0x72, 0x5B, 0x96, + 0xDD, 0x4E, 0x06, 0x4E, 0x3A, 0xC3, 0xD9, 0xBE, 0x72, 0xB6, + 0x65, 0x07, 0x07, 0x4C, 0x01, 0x02, 0x41, 0x00, 0xFA, 0x47, + 0xD4, 0x7A, 0x7C, 0x92, 0x3C, 0x55, 0xEF, 0x81, 0xF0, 0x41, + 0x30, 0x2D, 0xA3, 0xCF, 0x8F, 0x1C, 0xE6, 0x87, 0x27, 0x05, + 0x70, 0x0D, 0xDF, 0x98, 0x35, 0xD6, 0xF1, 0x8B, 0x38, 0x2F, + 0x24, 0xB5, 0xD0, 0x84, 0xB6, 0x79, 0x4F, 0x71, 0x29, 0x94, + 0x5A, 0xF0, 0x64, 0x6A, 0xAC, 0xE7, 0x72, 0xC6, 0xED, 0x4D, + 0x59, 0x98, 0x3E, 0x67, 0x3A, 0xF3, 0x74, 0x2C, 0xF9, 0x61, + 0x17, 0x69, 0x02, 0x41, 0x00, 0xC0, 0xC1, 0x82, 0x0D, 0x0C, + 0xEB, 0xC6, 0x2F, 0xDC, 0x92, 0xF9, 0x9D, 0x82, 0x1A, 0x31, + 0xE9, 0xE9, 0xF7, 0x4B, 0xF2, 0x82, 0x87, 0x1C, 0xEE, 0x16, + 0x6A, 0xD1, 0x1D, 0x18, 0x82, 0x70, 0xF3, 0xC0, 0xB6, 0x2F, + 0xF6, 0xF3, 0xF7, 0x1D, 0xF1, 0x86, 0x23, 0xC8, 0x4E, 0xEB, + 0x8F, 0x56, 0x8E, 0x8F, 0xF5, 0xBF, 0xF1, 0xF7, 0x2B, 0xB5, + 0xCC, 0x3D, 0xC6, 0x57, 0x39, 0x0C, 0x1B, 0x54, 0x41, 0x02, + 0x41, 0x00, 0x9D, 0x7E, 0x05, 0xDE, 0xED, 0xF4, 0xB7, 0xB2, + 0xFB, 0xFC, 0x30, 0x4B, 0x55, 0x1D, 0xE3, 0x2F, 0x01, 0x47, + 0x96, 0x69, 0x05, 0xCD, 0x0E, 0x2E, 0x2C, 0xBD, 0x83, 0x63, + 0xB6, 0xAB, 0x7C, 0xB7, 0x6D, 0xCA, 0x5B, 0x64, 0xA7, 0xCE, + 0xBE, 0x86, 0xDF, 0x3B, 0x53, 0xDE, 0x61, 0xD2, 0x1E, 0xEB, + 0xA5, 0xF6, 0x37, 0xED, 0xAC, 0xAB, 0x78, 0xD9, 0x4C, 0xE7, + 0x55, 0xFB, 0xD7, 0x11, 0x99, 0xC1, 0x02, 0x40, 0x18, 0x98, + 0x18, 0x29, 0xE6, 0x1E, 0x27, 0x39, 0x70, 0x21, 0x68, 0xAC, + 0x0A, 0x2F, 0xA1, 0x72, 0xC1, 0x21, 0x86, 0x95, 0x38, 0xC6, + 0x58, 0x90, 0xA0, 0x57, 0x9C, 0xBA, 0xE3, 0xA7, 0xB1, 0x15, + 0xC8, 0xDE, 0xF6, 0x1B, 0xC2, 0x61, 0x23, 0x76, 0xEF, 0xB0, + 0x9D, 0x1C, 0x44, 0xBE, 0x13, 0x43, 0x39, 0x67, 0x17, 0xC8, + 0x9D, 0xCA, 0xFB, 0xF5, 0x45, 0x64, 0x8B, 0x38, 0x82, 0x2C, + 0xF2, 0x81, 0x02, 0x40, 0x39, 0x89, 0xE5, 0x9C, 0x19, 0x55, + 0x30, 0xBA, 0xB7, 0x48, 0x8C, 0x48, 0x14, 0x0E, 0xF4, 0x9F, + 0x7E, 0x77, 0x97, 0x43, 0xE1, 0xB4, 0x19, 0x35, 0x31, 0x23, + 0x75, 0x9C, 0x3B, 0x44, 0xAD, 0x69, 0x12, 0x56, 0xEE, 0x00, + 0x61, 0x64, 0x16, 0x66, 0xD3, 0x7C, 0x74, 0x2B, 0x15, 0xB4, + 0xA2, 0xFE, 0xBF, 0x08, 0x6B, 0x1A, 0x5D, 0x3F, 0x90, 0x12, + 0xB1, 0x05, 0x86, 0x31, 0x29, 0xDB, 0xD9, 0xE2 }; static const int sizeof_client_key_der_1024 = sizeof(client_key_der_1024); +/* ./certs/1024/client-keyPub.der, 1024-bit */ +static const unsigned char client_keypub_der_1024[] = +{ + 0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, + 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, + 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xBC, + 0x73, 0x0E, 0xA8, 0x49, 0xF3, 0x74, 0xA2, 0xA9, 0xEF, 0x18, + 0xA5, 0xDA, 0x55, 0x99, 0x21, 0xF9, 0xC8, 0xEC, 0xB3, 0x6D, + 0x48, 0xE5, 0x35, 0x35, 0x75, 0x77, 0x37, 0xEC, 0xD1, 0x61, + 0x90, 0x5F, 0x3E, 0xD9, 0xE4, 0xD5, 0xDF, 0x94, 0xCA, 0xC1, + 0xA9, 0xD7, 0x19, 0xDA, 0x86, 0xC9, 0xE8, 0x4D, 0xC4, 0x61, + 0x36, 0x82, 0xFE, 0xAB, 0xAD, 0x7E, 0x77, 0x25, 0xBB, 0x8D, + 0x11, 0xA5, 0xBC, 0x62, 0x3A, 0xA8, 0x38, 0xCC, 0x39, 0xA2, + 0x04, 0x66, 0xB4, 0xF7, 0xF7, 0xF3, 0xAA, 0xDA, 0x4D, 0x02, + 0x0E, 0xBB, 0x5E, 0x8D, 0x69, 0x48, 0xDC, 0x77, 0xC9, 0x28, + 0x0E, 0x22, 0xE9, 0x6B, 0xA4, 0x26, 0xBA, 0x4C, 0xE8, 0xC1, + 0xFD, 0x4A, 0x6F, 0x2B, 0x1F, 0xEF, 0x8A, 0xAE, 0xF6, 0x90, + 0x62, 0xE5, 0x64, 0x1E, 0xEB, 0x2B, 0x3C, 0x67, 0xC8, 0xDC, + 0x27, 0x00, 0xF6, 0x91, 0x68, 0x65, 0xA9, 0x02, 0x03, 0x01, + 0x00, 0x01 +}; +static const int sizeof_client_keypub_der_1024 = sizeof(client_keypub_der_1024); + /* ./certs/1024/client-cert.der, 1024-bit */ static const unsigned char client_cert_der_1024[] = { - 0x30, 0x82, 0x03, 0xC5, 0x30, 0x82, 0x03, 0x2E, 0xA0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xE3, 0xD7, 0xA0, 0xFA, - 0x76, 0xDF, 0x2A, 0xFA, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, - 0x81, 0x9E, 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, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, - 0x31, 0x30, 0x32, 0x34, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, - 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, - 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x31, 0x30, 0x32, - 0x34, 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, 0x35, 0x30, 0x35, 0x30, 0x37, - 0x31, 0x38, 0x32, 0x31, 0x30, 0x31, 0x5A, 0x17, 0x0D, 0x31, - 0x38, 0x30, 0x31, 0x33, 0x31, 0x31, 0x38, 0x32, 0x31, 0x30, - 0x31, 0x5A, 0x30, 0x81, 0x9E, 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, 0x15, 0x30, 0x13, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, - 0x53, 0x4C, 0x5F, 0x31, 0x30, 0x32, 0x34, 0x31, 0x19, 0x30, - 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, - 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, - 0x31, 0x30, 0x32, 0x34, 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, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, - 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, - 0x81, 0x00, 0xBC, 0x73, 0x0E, 0xA8, 0x49, 0xF3, 0x74, 0xA2, - 0xA9, 0xEF, 0x18, 0xA5, 0xDA, 0x55, 0x99, 0x21, 0xF9, 0xC8, - 0xEC, 0xB3, 0x6D, 0x48, 0xE5, 0x35, 0x35, 0x75, 0x77, 0x37, - 0xEC, 0xD1, 0x61, 0x90, 0x5F, 0x3E, 0xD9, 0xE4, 0xD5, 0xDF, - 0x94, 0xCA, 0xC1, 0xA9, 0xD7, 0x19, 0xDA, 0x86, 0xC9, 0xE8, - 0x4D, 0xC4, 0x61, 0x36, 0x82, 0xFE, 0xAB, 0xAD, 0x7E, 0x77, - 0x25, 0xBB, 0x8D, 0x11, 0xA5, 0xBC, 0x62, 0x3A, 0xA8, 0x38, - 0xCC, 0x39, 0xA2, 0x04, 0x66, 0xB4, 0xF7, 0xF7, 0xF3, 0xAA, - 0xDA, 0x4D, 0x02, 0x0E, 0xBB, 0x5E, 0x8D, 0x69, 0x48, 0xDC, - 0x77, 0xC9, 0x28, 0x0E, 0x22, 0xE9, 0x6B, 0xA4, 0x26, 0xBA, - 0x4C, 0xE8, 0xC1, 0xFD, 0x4A, 0x6F, 0x2B, 0x1F, 0xEF, 0x8A, - 0xAE, 0xF6, 0x90, 0x62, 0xE5, 0x64, 0x1E, 0xEB, 0x2B, 0x3C, - 0x67, 0xC8, 0xDC, 0x27, 0x00, 0xF6, 0x91, 0x68, 0x65, 0xA9, - 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x07, 0x30, - 0x82, 0x01, 0x03, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, - 0x04, 0x16, 0x04, 0x14, 0x81, 0x69, 0x0F, 0xF8, 0xDF, 0xDD, - 0xCF, 0x34, 0x29, 0xD5, 0x67, 0x75, 0x71, 0x85, 0xC7, 0x75, - 0x10, 0x69, 0x59, 0xEC, 0x30, 0x81, 0xD3, 0x06, 0x03, 0x55, - 0x1D, 0x23, 0x04, 0x81, 0xCB, 0x30, 0x81, 0xC8, 0x80, 0x14, - 0x81, 0x69, 0x0F, 0xF8, 0xDF, 0xDD, 0xCF, 0x34, 0x29, 0xD5, - 0x67, 0x75, 0x71, 0x85, 0xC7, 0x75, 0x10, 0x69, 0x59, 0xEC, - 0xA1, 0x81, 0xA4, 0xA4, 0x81, 0xA1, 0x30, 0x81, 0x9E, 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, 0x15, - 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, - 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, 0x31, 0x30, 0x32, - 0x34, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, - 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, - 0x69, 0x6E, 0x67, 0x2D, 0x31, 0x30, 0x32, 0x34, 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, - 0xE3, 0xD7, 0xA0, 0xFA, 0x76, 0xDF, 0x2A, 0xFA, 0x30, 0x0C, - 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, - 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, - 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x81, 0x81, - 0x00, 0x1D, 0xB7, 0xD5, 0x7C, 0xE1, 0xB1, 0xD8, 0xC0, 0x67, - 0x5D, 0xB5, 0xD3, 0x88, 0xE7, 0x50, 0x29, 0x71, 0x63, 0x8F, - 0xCC, 0x26, 0x1F, 0x33, 0x09, 0x55, 0x43, 0x9B, 0xAB, 0xC6, - 0x1B, 0xBC, 0xC7, 0x01, 0x95, 0x1A, 0xFA, 0x65, 0xE0, 0xFD, - 0x9C, 0xEB, 0x6F, 0x0A, 0x0F, 0x14, 0xEC, 0xB5, 0x2F, 0xDC, - 0x1C, 0x30, 0xDD, 0x52, 0x97, 0xD4, 0x1C, 0x09, 0x00, 0x33, - 0x38, 0x5F, 0xCB, 0xA8, 0x16, 0x8F, 0x11, 0xB7, 0xB8, 0xD0, - 0x66, 0xE1, 0x54, 0x28, 0xF3, 0x3F, 0xBF, 0x6A, 0x6F, 0x76, - 0x48, 0x2A, 0x5E, 0x56, 0xA7, 0xCE, 0x1C, 0xF0, 0x04, 0xDD, - 0x17, 0xBD, 0x06, 0x78, 0x21, 0x6D, 0xD6, 0xB1, 0x9B, 0x75, - 0x31, 0x92, 0xC1, 0xFE, 0xD4, 0x8D, 0xD4, 0x67, 0x2F, 0x03, - 0x1B, 0x27, 0x8D, 0xAB, 0xFF, 0x30, 0x3B, 0xC3, 0x7F, 0x23, - 0xE4, 0xAB, 0x5B, 0x91, 0xE1, 0x1B, 0x66, 0xE6, 0xED + 0x30, 0x82, 0x03, 0xC5, 0x30, 0x82, 0x03, 0x2E, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xBB, 0xD3, 0x10, 0x03, + 0xE6, 0x9D, 0x28, 0x03, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x9E, 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, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, + 0x31, 0x30, 0x32, 0x34, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, + 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x31, 0x30, 0x32, + 0x34, 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, 0x38, 0x30, 0x34, 0x31, 0x33, + 0x31, 0x35, 0x32, 0x33, 0x30, 0x39, 0x5A, 0x17, 0x0D, 0x32, + 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x30, + 0x39, 0x5A, 0x30, 0x81, 0x9E, 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, 0x15, 0x30, 0x13, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, + 0x53, 0x4C, 0x5F, 0x31, 0x30, 0x32, 0x34, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, + 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, + 0x31, 0x30, 0x32, 0x34, 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, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, + 0x81, 0x00, 0xBC, 0x73, 0x0E, 0xA8, 0x49, 0xF3, 0x74, 0xA2, + 0xA9, 0xEF, 0x18, 0xA5, 0xDA, 0x55, 0x99, 0x21, 0xF9, 0xC8, + 0xEC, 0xB3, 0x6D, 0x48, 0xE5, 0x35, 0x35, 0x75, 0x77, 0x37, + 0xEC, 0xD1, 0x61, 0x90, 0x5F, 0x3E, 0xD9, 0xE4, 0xD5, 0xDF, + 0x94, 0xCA, 0xC1, 0xA9, 0xD7, 0x19, 0xDA, 0x86, 0xC9, 0xE8, + 0x4D, 0xC4, 0x61, 0x36, 0x82, 0xFE, 0xAB, 0xAD, 0x7E, 0x77, + 0x25, 0xBB, 0x8D, 0x11, 0xA5, 0xBC, 0x62, 0x3A, 0xA8, 0x38, + 0xCC, 0x39, 0xA2, 0x04, 0x66, 0xB4, 0xF7, 0xF7, 0xF3, 0xAA, + 0xDA, 0x4D, 0x02, 0x0E, 0xBB, 0x5E, 0x8D, 0x69, 0x48, 0xDC, + 0x77, 0xC9, 0x28, 0x0E, 0x22, 0xE9, 0x6B, 0xA4, 0x26, 0xBA, + 0x4C, 0xE8, 0xC1, 0xFD, 0x4A, 0x6F, 0x2B, 0x1F, 0xEF, 0x8A, + 0xAE, 0xF6, 0x90, 0x62, 0xE5, 0x64, 0x1E, 0xEB, 0x2B, 0x3C, + 0x67, 0xC8, 0xDC, 0x27, 0x00, 0xF6, 0x91, 0x68, 0x65, 0xA9, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x07, 0x30, + 0x82, 0x01, 0x03, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, + 0x04, 0x16, 0x04, 0x14, 0x81, 0x69, 0x0F, 0xF8, 0xDF, 0xDD, + 0xCF, 0x34, 0x29, 0xD5, 0x67, 0x75, 0x71, 0x85, 0xC7, 0x75, + 0x10, 0x69, 0x59, 0xEC, 0x30, 0x81, 0xD3, 0x06, 0x03, 0x55, + 0x1D, 0x23, 0x04, 0x81, 0xCB, 0x30, 0x81, 0xC8, 0x80, 0x14, + 0x81, 0x69, 0x0F, 0xF8, 0xDF, 0xDD, 0xCF, 0x34, 0x29, 0xD5, + 0x67, 0x75, 0x71, 0x85, 0xC7, 0x75, 0x10, 0x69, 0x59, 0xEC, + 0xA1, 0x81, 0xA4, 0xA4, 0x81, 0xA1, 0x30, 0x81, 0x9E, 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, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, + 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, 0x31, 0x30, 0x32, + 0x34, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, + 0x69, 0x6E, 0x67, 0x2D, 0x31, 0x30, 0x32, 0x34, 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, + 0xBB, 0xD3, 0x10, 0x03, 0xE6, 0x9D, 0x28, 0x03, 0x30, 0x0C, + 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x81, 0x81, + 0x00, 0x84, 0x99, 0xD9, 0xE5, 0x37, 0xC4, 0x44, 0x7D, 0xCE, + 0x29, 0xB8, 0xB6, 0x80, 0x0E, 0xEA, 0xA3, 0xE2, 0xFA, 0xA2, + 0x2F, 0x5C, 0xD2, 0x4A, 0x85, 0x67, 0xB9, 0x8B, 0xFA, 0x9F, + 0x7D, 0xDA, 0x6D, 0x85, 0x2A, 0xC2, 0x20, 0xF3, 0x18, 0xC8, + 0xD4, 0x6B, 0x26, 0xB2, 0x7A, 0x68, 0xE7, 0x82, 0x52, 0x87, + 0xE7, 0x0C, 0x5B, 0x08, 0x47, 0x7A, 0x55, 0xA5, 0x0D, 0xFA, + 0x72, 0xCE, 0x6B, 0xA1, 0xB2, 0xAE, 0x5A, 0xA1, 0x63, 0xFF, + 0x68, 0xDB, 0xE5, 0x49, 0xEF, 0xF1, 0x0E, 0x98, 0x96, 0x09, + 0xB5, 0x04, 0x5F, 0xD4, 0x0A, 0x9B, 0x8A, 0xAF, 0xD2, 0x31, + 0x1F, 0x95, 0xE5, 0x0F, 0xA8, 0xCD, 0xBB, 0xA1, 0x2D, 0x64, + 0xB0, 0xB7, 0xEE, 0x47, 0xA7, 0x58, 0xD9, 0xC7, 0xDB, 0xB0, + 0x92, 0xBB, 0xAA, 0xCF, 0xB8, 0x8A, 0x04, 0x5B, 0x0F, 0x9F, + 0x3E, 0xE0, 0xD2, 0x42, 0x52, 0xBD, 0x5D, 0xA7, 0x48 }; static const int sizeof_client_cert_der_1024 = sizeof(client_cert_der_1024); /* ./certs/1024/dh1024.der, 1024-bit */ static const unsigned char dh_key_der_1024[] = { - 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0xA4, 0xD2, 0xB8, - 0x6E, 0x78, 0xF5, 0xD9, 0xED, 0x2D, 0x7C, 0xDD, 0xB6, 0x16, - 0x86, 0x5A, 0x4B, 0x05, 0x76, 0x90, 0xDD, 0x66, 0x61, 0xB9, - 0x6D, 0x52, 0xA7, 0x1C, 0xAF, 0x62, 0xC6, 0x69, 0x47, 0x7B, - 0x39, 0xF2, 0xFB, 0x94, 0xEC, 0xBC, 0x79, 0xFF, 0x24, 0x5E, - 0xEF, 0x79, 0xBB, 0x59, 0xB2, 0xFC, 0xCA, 0x07, 0xD6, 0xF4, - 0xE9, 0x34, 0xF7, 0xE8, 0x38, 0xE7, 0xD7, 0x33, 0x44, 0x1D, - 0xA3, 0x64, 0x76, 0x1A, 0x84, 0x97, 0x54, 0x74, 0x40, 0x84, - 0x1F, 0x15, 0xFE, 0x7C, 0x25, 0x2A, 0x2B, 0x25, 0xFD, 0x9E, - 0xC1, 0x89, 0x33, 0x8C, 0x39, 0x25, 0x2B, 0x40, 0xE6, 0xCD, - 0xF8, 0xA8, 0xA1, 0x8A, 0x53, 0xC6, 0x47, 0xB2, 0xA0, 0xD7, - 0x8F, 0xEB, 0x2E, 0x60, 0x0A, 0x0D, 0x4B, 0xF8, 0xB4, 0x94, - 0x8C, 0x63, 0x0A, 0xAD, 0xC7, 0x10, 0xEA, 0xC7, 0xA1, 0xB9, - 0x9D, 0xF2, 0xA8, 0x37, 0x73, 0x02, 0x01, 0x02 + 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0xA4, 0xD2, 0xB8, + 0x6E, 0x78, 0xF5, 0xD9, 0xED, 0x2D, 0x7C, 0xDD, 0xB6, 0x16, + 0x86, 0x5A, 0x4B, 0x05, 0x76, 0x90, 0xDD, 0x66, 0x61, 0xB9, + 0x6D, 0x52, 0xA7, 0x1C, 0xAF, 0x62, 0xC6, 0x69, 0x47, 0x7B, + 0x39, 0xF2, 0xFB, 0x94, 0xEC, 0xBC, 0x79, 0xFF, 0x24, 0x5E, + 0xEF, 0x79, 0xBB, 0x59, 0xB2, 0xFC, 0xCA, 0x07, 0xD6, 0xF4, + 0xE9, 0x34, 0xF7, 0xE8, 0x38, 0xE7, 0xD7, 0x33, 0x44, 0x1D, + 0xA3, 0x64, 0x76, 0x1A, 0x84, 0x97, 0x54, 0x74, 0x40, 0x84, + 0x1F, 0x15, 0xFE, 0x7C, 0x25, 0x2A, 0x2B, 0x25, 0xFD, 0x9E, + 0xC1, 0x89, 0x33, 0x8C, 0x39, 0x25, 0x2B, 0x40, 0xE6, 0xCD, + 0xF8, 0xA8, 0xA1, 0x8A, 0x53, 0xC6, 0x47, 0xB2, 0xA0, 0xD7, + 0x8F, 0xEB, 0x2E, 0x60, 0x0A, 0x0D, 0x4B, 0xF8, 0xB4, 0x94, + 0x8C, 0x63, 0x0A, 0xAD, 0xC7, 0x10, 0xEA, 0xC7, 0xA1, 0xB9, + 0x9D, 0xF2, 0xA8, 0x37, 0x73, 0x02, 0x01, 0x02 }; static const int sizeof_dh_key_der_1024 = sizeof(dh_key_der_1024); /* ./certs/1024/dsa1024.der, 1024-bit */ static const unsigned char dsa_key_der_1024[] = { - 0x30, 0x82, 0x01, 0xBC, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, - 0x00, 0xF7, 0x4B, 0xF9, 0xBB, 0x15, 0x98, 0xEB, 0xDD, 0xDE, - 0x1E, 0x4E, 0x71, 0x88, 0x85, 0xF2, 0xB7, 0xBA, 0xE2, 0x4A, - 0xDA, 0x76, 0x40, 0xCD, 0x69, 0x48, 0x9E, 0x83, 0x7C, 0x11, - 0xF7, 0x65, 0x31, 0x78, 0xF5, 0x25, 0x2D, 0xF7, 0xB7, 0xF8, - 0x52, 0x3F, 0xBE, 0xD8, 0xB6, 0xC5, 0xFE, 0x18, 0x15, 0x5B, - 0xB9, 0xD5, 0x92, 0x86, 0xBC, 0xB2, 0x17, 0x7C, 0xD8, 0xB0, - 0xBE, 0xA0, 0x7C, 0xF2, 0xD5, 0x73, 0x7A, 0x58, 0x8F, 0x8D, - 0xE5, 0x4A, 0x00, 0x99, 0x83, 0x4A, 0xC0, 0x9E, 0x16, 0x09, - 0xA1, 0x10, 0x34, 0xD5, 0x19, 0xBB, 0x63, 0xE3, 0xDD, 0x83, - 0x74, 0x7F, 0x10, 0xCA, 0x73, 0x75, 0xEE, 0x31, 0x4A, 0xDD, - 0x9F, 0xE0, 0x02, 0x6A, 0x9D, 0xEE, 0xB2, 0x4B, 0xA7, 0x6B, - 0x2A, 0x6C, 0xC7, 0x86, 0x77, 0xE8, 0x04, 0x15, 0xDC, 0x92, - 0xB4, 0x7A, 0x29, 0x1F, 0x4E, 0x83, 0x63, 0x85, 0x55, 0x02, - 0x15, 0x00, 0xD2, 0x05, 0xE4, 0x73, 0xFB, 0xC1, 0x99, 0xC5, - 0xDC, 0x68, 0xA4, 0x8D, 0x92, 0x27, 0x3D, 0xE2, 0x52, 0x5F, - 0x89, 0x8B, 0x02, 0x81, 0x81, 0x00, 0xAA, 0x21, 0x02, 0x09, - 0x43, 0x6E, 0xFB, 0xA2, 0x54, 0x14, 0x85, 0x0A, 0xF4, 0x28, - 0x7C, 0xCB, 0xCC, 0xDB, 0xF5, 0x1E, 0xA2, 0x18, 0xA9, 0x21, - 0xDE, 0x88, 0x88, 0x33, 0x8C, 0x2E, 0xEB, 0x8D, 0xA3, 0xF0, - 0x1D, 0xC8, 0x8F, 0xF6, 0x7E, 0xF8, 0xCF, 0x12, 0xF5, 0xB4, - 0xA1, 0x11, 0x6F, 0x0C, 0xD4, 0xF0, 0x06, 0xAD, 0xC4, 0xFC, - 0x14, 0x45, 0xC7, 0x94, 0x15, 0xBC, 0x19, 0x4B, 0xAE, 0xEF, - 0x93, 0x6A, 0x4F, 0xCC, 0x14, 0xD8, 0x47, 0x8B, 0x39, 0x66, - 0x87, 0x02, 0xD4, 0x28, 0x0A, 0xB8, 0xEE, 0x09, 0x37, 0xF4, - 0x00, 0xA0, 0x04, 0xA7, 0x79, 0xA7, 0xD2, 0x3C, 0xF7, 0x34, - 0x43, 0x56, 0x8E, 0xD0, 0x7C, 0xC2, 0xD8, 0x4D, 0x0F, 0x89, - 0xED, 0x14, 0xC1, 0x2C, 0x9C, 0x4C, 0x19, 0x9B, 0x9E, 0xDC, - 0x53, 0x09, 0x9F, 0xDF, 0x2D, 0xF0, 0x0C, 0x27, 0x54, 0x3A, - 0x77, 0x14, 0x2D, 0xDE, 0x02, 0x81, 0x81, 0x00, 0xE8, 0x1F, - 0x7C, 0xB7, 0xC0, 0x54, 0x51, 0xA7, 0x28, 0x2D, 0x58, 0x7C, - 0xDE, 0xD4, 0x5C, 0xDD, 0xD5, 0x76, 0x84, 0x3C, 0x36, 0x20, - 0xC0, 0xC3, 0x25, 0xD7, 0x3A, 0x38, 0xE1, 0x54, 0xC8, 0xFD, - 0x40, 0x68, 0x1A, 0x21, 0x54, 0x26, 0x39, 0x14, 0xBF, 0xF6, - 0xA3, 0x9C, 0x5E, 0xD9, 0x2B, 0xF7, 0xC9, 0x25, 0xBA, 0x00, - 0x09, 0xCB, 0x7F, 0x0C, 0x4A, 0x24, 0xFD, 0x15, 0x16, 0x15, - 0x48, 0xCD, 0x0B, 0x52, 0x44, 0x40, 0x7B, 0x90, 0x63, 0x2B, - 0x90, 0x22, 0xC5, 0x18, 0x05, 0x80, 0x53, 0xAF, 0x83, 0x1F, - 0x54, 0xE2, 0xB0, 0xA2, 0x0B, 0x5A, 0x92, 0x24, 0xE1, 0x62, - 0x28, 0x3F, 0xB7, 0xCA, 0xB9, 0x89, 0xD6, 0xA0, 0xB7, 0xAD, - 0xAE, 0x05, 0xE1, 0xC1, 0x59, 0x40, 0xED, 0x4A, 0x1B, 0x68, - 0xA7, 0x7B, 0xFB, 0xC3, 0x20, 0x81, 0xEF, 0x4B, 0xF3, 0x69, - 0x91, 0xB0, 0xCE, 0x3A, 0xB0, 0x38, 0x02, 0x14, 0x25, 0x38, - 0x3B, 0xA1, 0x19, 0x75, 0xDF, 0x9B, 0xF5, 0x72, 0x53, 0x4F, - 0x39, 0xE1, 0x1C, 0xEC, 0x13, 0x84, 0x82, 0x18 + 0x30, 0x82, 0x01, 0xBC, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xF7, 0x4B, 0xF9, 0xBB, 0x15, 0x98, 0xEB, 0xDD, 0xDE, + 0x1E, 0x4E, 0x71, 0x88, 0x85, 0xF2, 0xB7, 0xBA, 0xE2, 0x4A, + 0xDA, 0x76, 0x40, 0xCD, 0x69, 0x48, 0x9E, 0x83, 0x7C, 0x11, + 0xF7, 0x65, 0x31, 0x78, 0xF5, 0x25, 0x2D, 0xF7, 0xB7, 0xF8, + 0x52, 0x3F, 0xBE, 0xD8, 0xB6, 0xC5, 0xFE, 0x18, 0x15, 0x5B, + 0xB9, 0xD5, 0x92, 0x86, 0xBC, 0xB2, 0x17, 0x7C, 0xD8, 0xB0, + 0xBE, 0xA0, 0x7C, 0xF2, 0xD5, 0x73, 0x7A, 0x58, 0x8F, 0x8D, + 0xE5, 0x4A, 0x00, 0x99, 0x83, 0x4A, 0xC0, 0x9E, 0x16, 0x09, + 0xA1, 0x10, 0x34, 0xD5, 0x19, 0xBB, 0x63, 0xE3, 0xDD, 0x83, + 0x74, 0x7F, 0x10, 0xCA, 0x73, 0x75, 0xEE, 0x31, 0x4A, 0xDD, + 0x9F, 0xE0, 0x02, 0x6A, 0x9D, 0xEE, 0xB2, 0x4B, 0xA7, 0x6B, + 0x2A, 0x6C, 0xC7, 0x86, 0x77, 0xE8, 0x04, 0x15, 0xDC, 0x92, + 0xB4, 0x7A, 0x29, 0x1F, 0x4E, 0x83, 0x63, 0x85, 0x55, 0x02, + 0x15, 0x00, 0xD2, 0x05, 0xE4, 0x73, 0xFB, 0xC1, 0x99, 0xC5, + 0xDC, 0x68, 0xA4, 0x8D, 0x92, 0x27, 0x3D, 0xE2, 0x52, 0x5F, + 0x89, 0x8B, 0x02, 0x81, 0x81, 0x00, 0xAA, 0x21, 0x02, 0x09, + 0x43, 0x6E, 0xFB, 0xA2, 0x54, 0x14, 0x85, 0x0A, 0xF4, 0x28, + 0x7C, 0xCB, 0xCC, 0xDB, 0xF5, 0x1E, 0xA2, 0x18, 0xA9, 0x21, + 0xDE, 0x88, 0x88, 0x33, 0x8C, 0x2E, 0xEB, 0x8D, 0xA3, 0xF0, + 0x1D, 0xC8, 0x8F, 0xF6, 0x7E, 0xF8, 0xCF, 0x12, 0xF5, 0xB4, + 0xA1, 0x11, 0x6F, 0x0C, 0xD4, 0xF0, 0x06, 0xAD, 0xC4, 0xFC, + 0x14, 0x45, 0xC7, 0x94, 0x15, 0xBC, 0x19, 0x4B, 0xAE, 0xEF, + 0x93, 0x6A, 0x4F, 0xCC, 0x14, 0xD8, 0x47, 0x8B, 0x39, 0x66, + 0x87, 0x02, 0xD4, 0x28, 0x0A, 0xB8, 0xEE, 0x09, 0x37, 0xF4, + 0x00, 0xA0, 0x04, 0xA7, 0x79, 0xA7, 0xD2, 0x3C, 0xF7, 0x34, + 0x43, 0x56, 0x8E, 0xD0, 0x7C, 0xC2, 0xD8, 0x4D, 0x0F, 0x89, + 0xED, 0x14, 0xC1, 0x2C, 0x9C, 0x4C, 0x19, 0x9B, 0x9E, 0xDC, + 0x53, 0x09, 0x9F, 0xDF, 0x2D, 0xF0, 0x0C, 0x27, 0x54, 0x3A, + 0x77, 0x14, 0x2D, 0xDE, 0x02, 0x81, 0x81, 0x00, 0xE8, 0x1F, + 0x7C, 0xB7, 0xC0, 0x54, 0x51, 0xA7, 0x28, 0x2D, 0x58, 0x7C, + 0xDE, 0xD4, 0x5C, 0xDD, 0xD5, 0x76, 0x84, 0x3C, 0x36, 0x20, + 0xC0, 0xC3, 0x25, 0xD7, 0x3A, 0x38, 0xE1, 0x54, 0xC8, 0xFD, + 0x40, 0x68, 0x1A, 0x21, 0x54, 0x26, 0x39, 0x14, 0xBF, 0xF6, + 0xA3, 0x9C, 0x5E, 0xD9, 0x2B, 0xF7, 0xC9, 0x25, 0xBA, 0x00, + 0x09, 0xCB, 0x7F, 0x0C, 0x4A, 0x24, 0xFD, 0x15, 0x16, 0x15, + 0x48, 0xCD, 0x0B, 0x52, 0x44, 0x40, 0x7B, 0x90, 0x63, 0x2B, + 0x90, 0x22, 0xC5, 0x18, 0x05, 0x80, 0x53, 0xAF, 0x83, 0x1F, + 0x54, 0xE2, 0xB0, 0xA2, 0x0B, 0x5A, 0x92, 0x24, 0xE1, 0x62, + 0x28, 0x3F, 0xB7, 0xCA, 0xB9, 0x89, 0xD6, 0xA0, 0xB7, 0xAD, + 0xAE, 0x05, 0xE1, 0xC1, 0x59, 0x40, 0xED, 0x4A, 0x1B, 0x68, + 0xA7, 0x7B, 0xFB, 0xC3, 0x20, 0x81, 0xEF, 0x4B, 0xF3, 0x69, + 0x91, 0xB0, 0xCE, 0x3A, 0xB0, 0x38, 0x02, 0x14, 0x25, 0x38, + 0x3B, 0xA1, 0x19, 0x75, 0xDF, 0x9B, 0xF5, 0x72, 0x53, 0x4F, + 0x39, 0xE1, 0x1C, 0xEC, 0x13, 0x84, 0x82, 0x18 }; static const int sizeof_dsa_key_der_1024 = sizeof(dsa_key_der_1024); /* ./certs/1024/rsa1024.der, 1024-bit */ static const unsigned char rsa_key_der_1024[] = { - 0x30, 0x82, 0x02, 0x5D, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, - 0x00, 0xBE, 0x70, 0x70, 0xB8, 0x04, 0x18, 0xE5, 0x28, 0xFE, - 0x66, 0xD8, 0x90, 0x88, 0xE0, 0xF1, 0xB7, 0xC3, 0xD0, 0xD2, - 0x3E, 0xE6, 0x4B, 0x94, 0x74, 0xB0, 0xFF, 0xB0, 0xF7, 0x63, - 0xA5, 0xAB, 0x7E, 0xAF, 0xB6, 0x2B, 0xB7, 0x38, 0x16, 0x1A, - 0x50, 0xBF, 0xF1, 0xCA, 0x87, 0x3A, 0xD5, 0xB0, 0xDA, 0xF8, - 0x43, 0x7A, 0x15, 0xB9, 0x7E, 0xEA, 0x2A, 0x80, 0xD2, 0x51, - 0xB0, 0x35, 0xAF, 0x07, 0xF3, 0xF2, 0x5D, 0x24, 0x3A, 0x4B, - 0x87, 0x56, 0x48, 0x1B, 0x3C, 0x24, 0x9A, 0xDA, 0x70, 0x80, - 0xBD, 0x3C, 0x8B, 0x03, 0x4A, 0x0C, 0x83, 0x71, 0xDE, 0xE3, - 0x03, 0x70, 0xA2, 0xB7, 0x60, 0x09, 0x1B, 0x5E, 0xC7, 0x3D, - 0xA0, 0x64, 0x60, 0xE3, 0xA9, 0x06, 0x8D, 0xD3, 0xFF, 0x42, - 0xBB, 0x0A, 0x94, 0x27, 0x2D, 0x57, 0x42, 0x0D, 0xB0, 0x2D, - 0xE0, 0xBA, 0x18, 0x25, 0x60, 0x92, 0x11, 0x92, 0xF3, 0x02, - 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x0E, 0xEE, 0x1D, - 0xC8, 0x2F, 0x7A, 0x0C, 0x2D, 0x44, 0x94, 0xA7, 0x91, 0xDD, - 0x49, 0x55, 0x6A, 0x04, 0xCE, 0x10, 0x4D, 0xA2, 0x1C, 0x76, - 0xCD, 0x17, 0x3B, 0x54, 0x92, 0x70, 0x9B, 0x82, 0x70, 0x72, - 0x32, 0x24, 0x07, 0x3F, 0x3C, 0x6C, 0x5F, 0xBC, 0x4C, 0xA6, - 0x86, 0x27, 0x94, 0xAD, 0x42, 0xDD, 0x87, 0xDC, 0xC0, 0x6B, - 0x44, 0x89, 0xF3, 0x3F, 0x1A, 0x3E, 0x11, 0x44, 0x84, 0x2E, - 0x69, 0x4C, 0xBB, 0x4A, 0x71, 0x1A, 0xBB, 0x9A, 0x52, 0x3C, - 0x6B, 0xDE, 0xBC, 0xB2, 0x7C, 0x51, 0xEF, 0x4F, 0x8F, 0x3A, - 0xDC, 0x50, 0x04, 0x4E, 0xB6, 0x31, 0x66, 0xA8, 0x8E, 0x06, - 0x3B, 0x51, 0xA9, 0xC1, 0x8A, 0xCB, 0xC4, 0x81, 0xCA, 0x2D, - 0x69, 0xEC, 0x88, 0xFC, 0x33, 0x88, 0xD1, 0xD4, 0x29, 0x47, - 0x87, 0x37, 0xF9, 0x6A, 0x22, 0x69, 0xB9, 0xC9, 0xFE, 0xEB, - 0x8C, 0xC5, 0x21, 0x41, 0x71, 0x02, 0x41, 0x00, 0xFD, 0x17, - 0x98, 0x42, 0x54, 0x1C, 0x23, 0xF8, 0xD7, 0x5D, 0xEF, 0x49, - 0x4F, 0xAF, 0xD9, 0x35, 0x6F, 0x08, 0xC6, 0xC7, 0x40, 0x5C, - 0x7E, 0x58, 0x86, 0xC2, 0xB2, 0x16, 0x39, 0x24, 0xC5, 0x06, - 0xB0, 0x3D, 0xAF, 0x02, 0xD2, 0x87, 0x77, 0xD2, 0x76, 0xBA, - 0xE3, 0x59, 0x60, 0x42, 0xF1, 0x16, 0xEF, 0x33, 0x0B, 0xF2, - 0x0B, 0xBA, 0x99, 0xCC, 0xB6, 0x4C, 0x46, 0x3F, 0x33, 0xE4, - 0xD4, 0x67, 0x02, 0x41, 0x00, 0xC0, 0xA0, 0x91, 0x6D, 0xFE, - 0x28, 0xE0, 0x81, 0x5A, 0x15, 0xA7, 0xC9, 0xA8, 0x98, 0xC6, - 0x0A, 0xAB, 0x00, 0xC5, 0x40, 0xC9, 0x21, 0xBB, 0xB2, 0x33, - 0x5A, 0xA7, 0xCB, 0x6E, 0xB8, 0x08, 0x56, 0x4A, 0x76, 0x28, - 0xE8, 0x6D, 0xBD, 0xF5, 0x26, 0x7B, 0xBF, 0xC5, 0x46, 0x45, - 0x0D, 0xEC, 0x7D, 0xEE, 0x82, 0xD6, 0xCA, 0x5F, 0x3D, 0x6E, - 0xCC, 0x94, 0x73, 0xCD, 0xCE, 0x86, 0x6E, 0x95, 0x95, 0x02, - 0x40, 0x38, 0xFD, 0x28, 0x1E, 0xBF, 0x5B, 0xBA, 0xC9, 0xDC, - 0x8C, 0xDD, 0x45, 0xAF, 0xB8, 0xD3, 0xFB, 0x11, 0x2E, 0x73, - 0xBC, 0x08, 0x05, 0x0B, 0xBA, 0x19, 0x56, 0x1B, 0xCD, 0x9F, - 0x3E, 0x65, 0x53, 0x15, 0x3A, 0x3E, 0x7F, 0x2F, 0x32, 0xAB, - 0xCB, 0x6B, 0x4A, 0xB7, 0xC8, 0xB7, 0x41, 0x3B, 0x92, 0x43, - 0x78, 0x46, 0x17, 0x51, 0x86, 0xC9, 0xFC, 0xEB, 0x8B, 0x8F, - 0x41, 0xCA, 0x08, 0x9B, 0xBF, 0x02, 0x41, 0x00, 0xAD, 0x9B, - 0x89, 0xB6, 0xF2, 0x8C, 0x70, 0xDA, 0xE4, 0x10, 0x04, 0x6B, - 0x11, 0x92, 0xAF, 0x5A, 0xCA, 0x08, 0x25, 0xBF, 0x60, 0x07, - 0x11, 0x1D, 0x68, 0x7F, 0x5A, 0x1F, 0x55, 0x28, 0x74, 0x0B, - 0x21, 0x8D, 0x21, 0x0D, 0x6A, 0x6A, 0xFB, 0xD9, 0xB5, 0x4A, - 0x7F, 0x47, 0xF7, 0xD0, 0xB6, 0xC6, 0x41, 0x02, 0x97, 0x07, - 0x49, 0x93, 0x1A, 0x9B, 0x33, 0x68, 0xB3, 0xA2, 0x61, 0x32, - 0xA5, 0x89, 0x02, 0x41, 0x00, 0x8F, 0xEF, 0xAD, 0xB5, 0xB0, - 0xB0, 0x7E, 0x86, 0x03, 0x43, 0x93, 0x6E, 0xDD, 0x3C, 0x2D, - 0x9B, 0x6A, 0x55, 0xFF, 0x6F, 0x3E, 0x70, 0x2A, 0xD4, 0xBF, - 0x1F, 0x8C, 0x93, 0x60, 0x9E, 0x6D, 0x2F, 0x18, 0x6C, 0x11, - 0x36, 0x98, 0x3F, 0x10, 0x78, 0xE8, 0x3E, 0x8F, 0xFE, 0x55, - 0xB9, 0x9E, 0xD5, 0x5B, 0x2E, 0x87, 0x1C, 0x58, 0xD0, 0x37, - 0x89, 0x96, 0xEC, 0x48, 0x54, 0xF5, 0x9F, 0x0F, 0xB3 + 0x30, 0x82, 0x02, 0x5D, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xBE, 0x70, 0x70, 0xB8, 0x04, 0x18, 0xE5, 0x28, 0xFE, + 0x66, 0xD8, 0x90, 0x88, 0xE0, 0xF1, 0xB7, 0xC3, 0xD0, 0xD2, + 0x3E, 0xE6, 0x4B, 0x94, 0x74, 0xB0, 0xFF, 0xB0, 0xF7, 0x63, + 0xA5, 0xAB, 0x7E, 0xAF, 0xB6, 0x2B, 0xB7, 0x38, 0x16, 0x1A, + 0x50, 0xBF, 0xF1, 0xCA, 0x87, 0x3A, 0xD5, 0xB0, 0xDA, 0xF8, + 0x43, 0x7A, 0x15, 0xB9, 0x7E, 0xEA, 0x2A, 0x80, 0xD2, 0x51, + 0xB0, 0x35, 0xAF, 0x07, 0xF3, 0xF2, 0x5D, 0x24, 0x3A, 0x4B, + 0x87, 0x56, 0x48, 0x1B, 0x3C, 0x24, 0x9A, 0xDA, 0x70, 0x80, + 0xBD, 0x3C, 0x8B, 0x03, 0x4A, 0x0C, 0x83, 0x71, 0xDE, 0xE3, + 0x03, 0x70, 0xA2, 0xB7, 0x60, 0x09, 0x1B, 0x5E, 0xC7, 0x3D, + 0xA0, 0x64, 0x60, 0xE3, 0xA9, 0x06, 0x8D, 0xD3, 0xFF, 0x42, + 0xBB, 0x0A, 0x94, 0x27, 0x2D, 0x57, 0x42, 0x0D, 0xB0, 0x2D, + 0xE0, 0xBA, 0x18, 0x25, 0x60, 0x92, 0x11, 0x92, 0xF3, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x0E, 0xEE, 0x1D, + 0xC8, 0x2F, 0x7A, 0x0C, 0x2D, 0x44, 0x94, 0xA7, 0x91, 0xDD, + 0x49, 0x55, 0x6A, 0x04, 0xCE, 0x10, 0x4D, 0xA2, 0x1C, 0x76, + 0xCD, 0x17, 0x3B, 0x54, 0x92, 0x70, 0x9B, 0x82, 0x70, 0x72, + 0x32, 0x24, 0x07, 0x3F, 0x3C, 0x6C, 0x5F, 0xBC, 0x4C, 0xA6, + 0x86, 0x27, 0x94, 0xAD, 0x42, 0xDD, 0x87, 0xDC, 0xC0, 0x6B, + 0x44, 0x89, 0xF3, 0x3F, 0x1A, 0x3E, 0x11, 0x44, 0x84, 0x2E, + 0x69, 0x4C, 0xBB, 0x4A, 0x71, 0x1A, 0xBB, 0x9A, 0x52, 0x3C, + 0x6B, 0xDE, 0xBC, 0xB2, 0x7C, 0x51, 0xEF, 0x4F, 0x8F, 0x3A, + 0xDC, 0x50, 0x04, 0x4E, 0xB6, 0x31, 0x66, 0xA8, 0x8E, 0x06, + 0x3B, 0x51, 0xA9, 0xC1, 0x8A, 0xCB, 0xC4, 0x81, 0xCA, 0x2D, + 0x69, 0xEC, 0x88, 0xFC, 0x33, 0x88, 0xD1, 0xD4, 0x29, 0x47, + 0x87, 0x37, 0xF9, 0x6A, 0x22, 0x69, 0xB9, 0xC9, 0xFE, 0xEB, + 0x8C, 0xC5, 0x21, 0x41, 0x71, 0x02, 0x41, 0x00, 0xFD, 0x17, + 0x98, 0x42, 0x54, 0x1C, 0x23, 0xF8, 0xD7, 0x5D, 0xEF, 0x49, + 0x4F, 0xAF, 0xD9, 0x35, 0x6F, 0x08, 0xC6, 0xC7, 0x40, 0x5C, + 0x7E, 0x58, 0x86, 0xC2, 0xB2, 0x16, 0x39, 0x24, 0xC5, 0x06, + 0xB0, 0x3D, 0xAF, 0x02, 0xD2, 0x87, 0x77, 0xD2, 0x76, 0xBA, + 0xE3, 0x59, 0x60, 0x42, 0xF1, 0x16, 0xEF, 0x33, 0x0B, 0xF2, + 0x0B, 0xBA, 0x99, 0xCC, 0xB6, 0x4C, 0x46, 0x3F, 0x33, 0xE4, + 0xD4, 0x67, 0x02, 0x41, 0x00, 0xC0, 0xA0, 0x91, 0x6D, 0xFE, + 0x28, 0xE0, 0x81, 0x5A, 0x15, 0xA7, 0xC9, 0xA8, 0x98, 0xC6, + 0x0A, 0xAB, 0x00, 0xC5, 0x40, 0xC9, 0x21, 0xBB, 0xB2, 0x33, + 0x5A, 0xA7, 0xCB, 0x6E, 0xB8, 0x08, 0x56, 0x4A, 0x76, 0x28, + 0xE8, 0x6D, 0xBD, 0xF5, 0x26, 0x7B, 0xBF, 0xC5, 0x46, 0x45, + 0x0D, 0xEC, 0x7D, 0xEE, 0x82, 0xD6, 0xCA, 0x5F, 0x3D, 0x6E, + 0xCC, 0x94, 0x73, 0xCD, 0xCE, 0x86, 0x6E, 0x95, 0x95, 0x02, + 0x40, 0x38, 0xFD, 0x28, 0x1E, 0xBF, 0x5B, 0xBA, 0xC9, 0xDC, + 0x8C, 0xDD, 0x45, 0xAF, 0xB8, 0xD3, 0xFB, 0x11, 0x2E, 0x73, + 0xBC, 0x08, 0x05, 0x0B, 0xBA, 0x19, 0x56, 0x1B, 0xCD, 0x9F, + 0x3E, 0x65, 0x53, 0x15, 0x3A, 0x3E, 0x7F, 0x2F, 0x32, 0xAB, + 0xCB, 0x6B, 0x4A, 0xB7, 0xC8, 0xB7, 0x41, 0x3B, 0x92, 0x43, + 0x78, 0x46, 0x17, 0x51, 0x86, 0xC9, 0xFC, 0xEB, 0x8B, 0x8F, + 0x41, 0xCA, 0x08, 0x9B, 0xBF, 0x02, 0x41, 0x00, 0xAD, 0x9B, + 0x89, 0xB6, 0xF2, 0x8C, 0x70, 0xDA, 0xE4, 0x10, 0x04, 0x6B, + 0x11, 0x92, 0xAF, 0x5A, 0xCA, 0x08, 0x25, 0xBF, 0x60, 0x07, + 0x11, 0x1D, 0x68, 0x7F, 0x5A, 0x1F, 0x55, 0x28, 0x74, 0x0B, + 0x21, 0x8D, 0x21, 0x0D, 0x6A, 0x6A, 0xFB, 0xD9, 0xB5, 0x4A, + 0x7F, 0x47, 0xF7, 0xD0, 0xB6, 0xC6, 0x41, 0x02, 0x97, 0x07, + 0x49, 0x93, 0x1A, 0x9B, 0x33, 0x68, 0xB3, 0xA2, 0x61, 0x32, + 0xA5, 0x89, 0x02, 0x41, 0x00, 0x8F, 0xEF, 0xAD, 0xB5, 0xB0, + 0xB0, 0x7E, 0x86, 0x03, 0x43, 0x93, 0x6E, 0xDD, 0x3C, 0x2D, + 0x9B, 0x6A, 0x55, 0xFF, 0x6F, 0x3E, 0x70, 0x2A, 0xD4, 0xBF, + 0x1F, 0x8C, 0x93, 0x60, 0x9E, 0x6D, 0x2F, 0x18, 0x6C, 0x11, + 0x36, 0x98, 0x3F, 0x10, 0x78, 0xE8, 0x3E, 0x8F, 0xFE, 0x55, + 0xB9, 0x9E, 0xD5, 0x5B, 0x2E, 0x87, 0x1C, 0x58, 0xD0, 0x37, + 0x89, 0x96, 0xEC, 0x48, 0x54, 0xF5, 0x9F, 0x0F, 0xB3 }; static const int sizeof_rsa_key_der_1024 = sizeof(rsa_key_der_1024); -#elif defined(USE_CERT_BUFFERS_2048) +/* ./certs/1024/ca-key.der, 1024-bit */ +static const unsigned char ca_key_der_1024[] = +{ + 0x30, 0x82, 0x02, 0x5E, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xCD, 0xAC, 0xDD, 0x47, 0xEC, 0xBE, 0xB7, 0x24, 0xC3, + 0x63, 0x1B, 0x54, 0x98, 0x79, 0xE1, 0xC7, 0x31, 0x16, 0x59, + 0xD6, 0x9D, 0x77, 0x9D, 0x8D, 0xE2, 0x8B, 0xED, 0x04, 0x17, + 0xB2, 0xC6, 0xEB, 0xE4, 0x9B, 0x91, 0xBE, 0x31, 0x50, 0x62, + 0x97, 0x58, 0xB5, 0x7F, 0x29, 0xDE, 0xB3, 0x71, 0x24, 0x0B, + 0xBF, 0x97, 0x09, 0x7F, 0x26, 0xDC, 0x2D, 0xEC, 0xA8, 0x2E, + 0xB2, 0x64, 0x2B, 0x7A, 0x2B, 0x35, 0x19, 0x2D, 0xA2, 0x80, + 0xCB, 0x99, 0xFD, 0x94, 0x71, 0x1B, 0x23, 0x8D, 0x54, 0xDB, + 0x2E, 0x62, 0x8D, 0x81, 0x08, 0x2D, 0xF4, 0x24, 0x72, 0x27, + 0x6C, 0xF9, 0xC9, 0x8E, 0xDB, 0x4C, 0x75, 0xBA, 0x9B, 0x01, + 0xF8, 0x3F, 0x18, 0xF4, 0xE6, 0x7F, 0xFB, 0x57, 0x94, 0x92, + 0xCC, 0x88, 0xC4, 0xB4, 0x00, 0xC2, 0xAA, 0xD4, 0xE5, 0x88, + 0x18, 0xB3, 0x11, 0x2F, 0x73, 0xC0, 0xD6, 0x29, 0x09, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x52, 0x35, 0x3D, + 0x01, 0x29, 0xA4, 0x95, 0x29, 0x71, 0x9B, 0x64, 0x6A, 0x2C, + 0xC3, 0xD2, 0xB5, 0xBE, 0x6E, 0x13, 0x9C, 0x8F, 0xB6, 0x26, + 0xD8, 0x76, 0x6B, 0xBD, 0x61, 0xBC, 0x63, 0x2D, 0xD5, 0x4D, + 0xBB, 0xCC, 0xC6, 0x3B, 0x89, 0xC8, 0xCE, 0x7B, 0x9B, 0x97, + 0xE7, 0x51, 0x67, 0x61, 0xDA, 0xA9, 0x83, 0x7B, 0xC8, 0x44, + 0xF5, 0x70, 0x5E, 0x3E, 0xD0, 0x7E, 0x51, 0xB9, 0x6E, 0x13, + 0x57, 0x08, 0x5C, 0xE1, 0x67, 0x4F, 0x61, 0x5E, 0xA5, 0x09, + 0xEC, 0x11, 0xDD, 0xE4, 0xB8, 0xB4, 0xF4, 0xE0, 0x63, 0x34, + 0x4C, 0xDA, 0x32, 0x20, 0x1F, 0x85, 0x41, 0x5D, 0xBC, 0xDB, + 0x24, 0xC5, 0xAF, 0xBE, 0x02, 0x5F, 0x22, 0xF1, 0x7C, 0xCC, + 0x05, 0x56, 0xA6, 0xA6, 0x37, 0x9A, 0xEB, 0xFF, 0x52, 0x2D, + 0xBF, 0x30, 0x4B, 0x9A, 0x1D, 0xEE, 0xAB, 0x9C, 0x2C, 0xE2, + 0xC1, 0xB8, 0x9D, 0xC9, 0x31, 0x02, 0x41, 0x00, 0xE9, 0x89, + 0x16, 0xCD, 0xAC, 0x2E, 0xF2, 0x4D, 0x66, 0x17, 0xBD, 0x78, + 0x12, 0x12, 0x8D, 0x8E, 0x84, 0x24, 0xDE, 0x2D, 0x50, 0x41, + 0x85, 0x8C, 0x34, 0x09, 0xFA, 0xFB, 0x6D, 0x87, 0x51, 0x4C, + 0x13, 0x28, 0xF0, 0x60, 0x11, 0x86, 0x3D, 0xC2, 0xA4, 0xCF, + 0x5E, 0xC5, 0x6F, 0x5B, 0x11, 0x32, 0x0A, 0xB5, 0x28, 0xD0, + 0x82, 0x47, 0x44, 0x26, 0x92, 0xE2, 0x78, 0x59, 0xB4, 0x08, + 0xB3, 0xFD, 0x02, 0x41, 0x00, 0xE1, 0x75, 0xB4, 0x6A, 0xB5, + 0x8C, 0x11, 0xFB, 0xCC, 0x42, 0x02, 0xC5, 0xDA, 0x48, 0xCE, + 0x29, 0x43, 0x14, 0x01, 0x9A, 0x2C, 0xB3, 0xA4, 0xCB, 0x73, + 0xEB, 0xA1, 0x35, 0x57, 0xAD, 0xB5, 0x16, 0x17, 0x80, 0x03, + 0x5F, 0x32, 0x37, 0xBE, 0xA2, 0x6F, 0xF9, 0x31, 0x84, 0xBF, + 0x00, 0x6E, 0x8D, 0x03, 0x0E, 0x30, 0x1C, 0xD0, 0x2F, 0x37, + 0xF0, 0x7E, 0xC2, 0x64, 0xBF, 0xEE, 0x4B, 0xE8, 0xFD, 0x02, + 0x41, 0x00, 0xE1, 0x99, 0x8B, 0x2B, 0xD8, 0x9F, 0xE9, 0x76, + 0x97, 0x9F, 0x6B, 0x6B, 0x28, 0x9A, 0x3F, 0xA1, 0x63, 0x4A, + 0x72, 0x4E, 0xF7, 0xEE, 0xB3, 0xE2, 0x43, 0x0B, 0x39, 0x27, + 0xD6, 0x21, 0x18, 0x8A, 0x13, 0x20, 0x43, 0x45, 0xAA, 0xE8, + 0x31, 0x95, 0x6C, 0xBC, 0xDE, 0xE2, 0x7F, 0xB6, 0x4B, 0xA0, + 0x39, 0xF3, 0xD3, 0x9F, 0xC9, 0x9A, 0xAA, 0xDD, 0x50, 0x9B, + 0xF2, 0x83, 0x45, 0x85, 0xFA, 0xC9, 0x02, 0x41, 0x00, 0xAF, + 0xB0, 0xC7, 0x7C, 0xF8, 0x28, 0x44, 0xC3, 0x50, 0xF2, 0x87, + 0xB2, 0xA2, 0x5D, 0x65, 0xBA, 0x25, 0xB9, 0x6B, 0x5E, 0x37, + 0x43, 0x6E, 0x41, 0xD4, 0xFD, 0x63, 0x4C, 0x6C, 0x1C, 0xC3, + 0x26, 0x89, 0xFD, 0x89, 0xA3, 0x1F, 0x40, 0xED, 0x5F, 0x2B, + 0x9E, 0xA6, 0x85, 0xE9, 0x49, 0x6E, 0xDC, 0x97, 0xEA, 0xF0, + 0x77, 0x23, 0x8C, 0x08, 0x2D, 0x72, 0xBA, 0x0D, 0x44, 0xBB, + 0x6F, 0x90, 0x09, 0x02, 0x41, 0x00, 0x91, 0xE4, 0x2E, 0xCA, + 0x8C, 0x0A, 0x69, 0x2F, 0x62, 0xE2, 0x62, 0x3B, 0xA5, 0x8D, + 0x5A, 0x2C, 0x56, 0x3E, 0x7F, 0x67, 0x42, 0x92, 0x12, 0x92, + 0x5F, 0xF3, 0x97, 0xDD, 0xE1, 0xA9, 0x7F, 0xAD, 0x2E, 0x2D, + 0xF4, 0x4A, 0x57, 0xB3, 0x7A, 0x10, 0xBD, 0xD7, 0xE4, 0xEC, + 0x6A, 0x08, 0x21, 0xE9, 0xF2, 0x46, 0x49, 0xD2, 0x69, 0x47, + 0x8A, 0x20, 0x4B, 0xF2, 0xB1, 0x52, 0x83, 0xAB, 0x6F, 0x10 + +}; +static const int sizeof_ca_key_der_1024 = sizeof(ca_key_der_1024); + +/* ./certs/1024/ca-cert.der, 1024-bit */ +static const unsigned char ca_cert_der_1024[] = +{ + 0x30, 0x82, 0x03, 0xB5, 0x30, 0x82, 0x03, 0x1E, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xDA, 0xFB, 0x6A, 0x0D, + 0xFE, 0xCF, 0x9B, 0x47, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x99, 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, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x0F, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, + 0x67, 0x5F, 0x31, 0x30, 0x32, 0x34, 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, + 0x38, 0x30, 0x34, 0x31, 0x33, 0x31, 0x35, 0x32, 0x33, 0x31, + 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, + 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x30, 0x81, 0x99, + 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, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, + 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, + 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, + 0x31, 0x30, 0x32, 0x34, 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, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, + 0x81, 0x00, 0xCD, 0xAC, 0xDD, 0x47, 0xEC, 0xBE, 0xB7, 0x24, + 0xC3, 0x63, 0x1B, 0x54, 0x98, 0x79, 0xE1, 0xC7, 0x31, 0x16, + 0x59, 0xD6, 0x9D, 0x77, 0x9D, 0x8D, 0xE2, 0x8B, 0xED, 0x04, + 0x17, 0xB2, 0xC6, 0xEB, 0xE4, 0x9B, 0x91, 0xBE, 0x31, 0x50, + 0x62, 0x97, 0x58, 0xB5, 0x7F, 0x29, 0xDE, 0xB3, 0x71, 0x24, + 0x0B, 0xBF, 0x97, 0x09, 0x7F, 0x26, 0xDC, 0x2D, 0xEC, 0xA8, + 0x2E, 0xB2, 0x64, 0x2B, 0x7A, 0x2B, 0x35, 0x19, 0x2D, 0xA2, + 0x80, 0xCB, 0x99, 0xFD, 0x94, 0x71, 0x1B, 0x23, 0x8D, 0x54, + 0xDB, 0x2E, 0x62, 0x8D, 0x81, 0x08, 0x2D, 0xF4, 0x24, 0x72, + 0x27, 0x6C, 0xF9, 0xC9, 0x8E, 0xDB, 0x4C, 0x75, 0xBA, 0x9B, + 0x01, 0xF8, 0x3F, 0x18, 0xF4, 0xE6, 0x7F, 0xFB, 0x57, 0x94, + 0x92, 0xCC, 0x88, 0xC4, 0xB4, 0x00, 0xC2, 0xAA, 0xD4, 0xE5, + 0x88, 0x18, 0xB3, 0x11, 0x2F, 0x73, 0xC0, 0xD6, 0x29, 0x09, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x01, 0x30, + 0x81, 0xFE, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, + 0x16, 0x04, 0x14, 0xD3, 0x22, 0x8F, 0x28, 0x2C, 0xE0, 0x05, + 0xEE, 0xD3, 0xED, 0xC3, 0x71, 0x3D, 0xC9, 0xB2, 0x36, 0x3A, + 0x1D, 0xBF, 0xA8, 0x30, 0x81, 0xCE, 0x06, 0x03, 0x55, 0x1D, + 0x23, 0x04, 0x81, 0xC6, 0x30, 0x81, 0xC3, 0x80, 0x14, 0xD3, + 0x22, 0x8F, 0x28, 0x2C, 0xE0, 0x05, 0xEE, 0xD3, 0xED, 0xC3, + 0x71, 0x3D, 0xC9, 0xB2, 0x36, 0x3A, 0x1D, 0xBF, 0xA8, 0xA1, + 0x81, 0x9F, 0xA4, 0x81, 0x9C, 0x30, 0x81, 0x99, 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, 0x11, 0x30, + 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, + 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, 0x6F, 0x6E, + 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, 0x31, 0x30, + 0x32, 0x34, 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, 0xDA, 0xFB, 0x6A, 0x0D, 0xFE, 0xCF, + 0x9B, 0x47, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x03, 0x81, 0x81, 0x00, 0x1D, 0x48, 0xF6, 0x40, 0x41, + 0x04, 0x06, 0xF2, 0xE4, 0x72, 0x2F, 0xEA, 0xFF, 0xC1, 0x67, + 0x6B, 0x15, 0xBB, 0x0A, 0x28, 0x23, 0x28, 0x07, 0xC6, 0xD7, + 0x13, 0x2C, 0xBE, 0x00, 0x00, 0xAC, 0x1D, 0xF7, 0xF4, 0x92, + 0xD3, 0x2B, 0xAF, 0x23, 0xEB, 0x9F, 0x1A, 0xE2, 0x11, 0x3C, + 0x2D, 0x97, 0xF2, 0x0F, 0xAC, 0xAE, 0x97, 0x86, 0x0A, 0xFB, + 0xA8, 0x4F, 0x74, 0x1B, 0xDE, 0x19, 0x51, 0xDB, 0xCD, 0xE2, + 0x11, 0x38, 0xC1, 0xA4, 0x9D, 0x56, 0xAB, 0x47, 0x5C, 0xDE, + 0xBA, 0xEB, 0x27, 0xDF, 0x6D, 0xC8, 0x7E, 0x3A, 0xBD, 0x2E, + 0x9B, 0x2A, 0xAD, 0x22, 0x3B, 0x95, 0xA9, 0xF2, 0x28, 0x03, + 0xBC, 0xE5, 0xEC, 0xCC, 0xF2, 0x08, 0xD4, 0xC8, 0x2F, 0xDB, + 0xEA, 0xFB, 0x2E, 0x52, 0x16, 0x8C, 0x42, 0x02, 0xA4, 0x59, + 0x6D, 0x4C, 0x33, 0xB4, 0x9A, 0xD2, 0x73, 0x4A, 0x1E, 0x9F, + 0xD9, 0xC8, 0x83 +}; +static const int sizeof_ca_cert_der_1024 = sizeof(ca_cert_der_1024); + +/* ./certs/1024/server-key.der, 1024-bit */ +static const unsigned char server_key_der_1024[] = +{ + 0x30, 0x82, 0x02, 0x5D, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xAA, 0x3E, 0xA5, 0x9C, 0xD3, 0x17, 0x49, 0x65, 0x43, + 0xDE, 0xD0, 0xF3, 0x4B, 0x1C, 0xDB, 0x49, 0x0C, 0xFC, 0x7A, + 0x65, 0x05, 0x6D, 0xDE, 0x6A, 0xC4, 0xE4, 0x73, 0x2C, 0x8A, + 0x96, 0x82, 0x8F, 0x23, 0xA5, 0x06, 0x71, 0x1C, 0x06, 0x3E, + 0x2F, 0x92, 0x8D, 0x0B, 0x29, 0x34, 0x45, 0x59, 0xE9, 0xA9, + 0xBC, 0x61, 0xD7, 0x24, 0x37, 0x5D, 0xB5, 0xC4, 0x37, 0x8D, + 0xBA, 0x67, 0xB2, 0xEF, 0x03, 0x27, 0xFA, 0xC1, 0xB4, 0xCD, + 0x6B, 0x00, 0x66, 0xB4, 0xD6, 0x73, 0x70, 0x1F, 0x08, 0x3A, + 0xCC, 0x77, 0xAD, 0xE9, 0xF9, 0x34, 0xD4, 0xF3, 0xA0, 0x2D, + 0xA9, 0xE7, 0x58, 0xA9, 0xC0, 0x61, 0x84, 0xB6, 0xEC, 0x3D, + 0x0A, 0xAD, 0xFD, 0x5C, 0x86, 0x73, 0xAA, 0x6B, 0x47, 0xD8, + 0x8B, 0x2E, 0x58, 0x4B, 0x69, 0x12, 0x82, 0x26, 0x55, 0xE6, + 0x14, 0xBF, 0x55, 0x70, 0x88, 0xFE, 0xF9, 0x75, 0xE1, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x0A, 0x4C, 0xC1, + 0xFE, 0x4B, 0xF3, 0x23, 0xB8, 0xA1, 0xB3, 0x90, 0x56, 0xB7, + 0xDB, 0xA6, 0x14, 0xB4, 0x59, 0x6E, 0x1A, 0x40, 0x8A, 0xD6, + 0x23, 0x05, 0x88, 0x80, 0xC3, 0x58, 0x1B, 0x25, 0x08, 0xFD, + 0xF2, 0x15, 0x02, 0xB0, 0xDC, 0x5B, 0xD4, 0xCA, 0xFC, 0x07, + 0x89, 0xD5, 0xA4, 0xC0, 0x7C, 0xD7, 0x8D, 0x13, 0x2A, 0x4E, + 0x01, 0x9F, 0x84, 0xC8, 0xBB, 0x47, 0xB2, 0xD8, 0x65, 0x45, + 0xFA, 0x84, 0x9F, 0x88, 0xD0, 0xF4, 0xF5, 0x22, 0x35, 0x77, + 0x11, 0x67, 0x1C, 0xDE, 0x5F, 0x85, 0x6D, 0x55, 0xD8, 0xA7, + 0x07, 0x15, 0x8C, 0xE1, 0xB0, 0xA7, 0x79, 0xB4, 0x47, 0x9D, + 0x70, 0xB3, 0xD2, 0xF1, 0x1F, 0x41, 0x4C, 0x65, 0x72, 0x26, + 0xEB, 0x66, 0xC8, 0x95, 0xF6, 0x6D, 0x87, 0x35, 0x53, 0xFE, + 0xB1, 0x52, 0x4D, 0x76, 0x5B, 0x61, 0x53, 0x89, 0xB1, 0x20, + 0x1A, 0x8B, 0xE4, 0x7D, 0xF1, 0x02, 0x41, 0x00, 0xD9, 0x6E, + 0xE1, 0xD9, 0x06, 0x56, 0xA1, 0xF6, 0xDF, 0x54, 0x45, 0xC5, + 0xEC, 0x6A, 0xC8, 0x2A, 0x38, 0x4E, 0x6B, 0xC6, 0xE8, 0xEA, + 0xFB, 0x6F, 0x65, 0x2D, 0xBA, 0xDE, 0x27, 0x63, 0x37, 0x21, + 0x2E, 0xA4, 0x55, 0xAB, 0xE7, 0xDB, 0xCE, 0x71, 0xE1, 0x08, + 0xFC, 0xF2, 0xCA, 0x52, 0x33, 0x55, 0xE8, 0x39, 0xB3, 0xDA, + 0xC5, 0xB0, 0x69, 0x84, 0x6E, 0xE3, 0xCF, 0x47, 0x80, 0xA6, + 0xB6, 0x85, 0x02, 0x41, 0x00, 0xC8, 0x71, 0x0D, 0x37, 0x47, + 0xE1, 0x7B, 0x21, 0x2D, 0x11, 0x2D, 0x95, 0x2E, 0xC7, 0xD0, + 0xB6, 0xD3, 0x7C, 0x5C, 0x93, 0x3C, 0x5B, 0x22, 0xE5, 0xE0, + 0x8B, 0x6D, 0x47, 0xF9, 0x14, 0x0F, 0x9E, 0x08, 0x1B, 0x53, + 0xAB, 0x0A, 0xA9, 0xE4, 0x7F, 0x40, 0xD3, 0xDF, 0x62, 0x74, + 0x10, 0xA2, 0xFE, 0x83, 0x1F, 0xCF, 0x55, 0x66, 0xEB, 0x5D, + 0xC5, 0x83, 0xBA, 0xEC, 0x9F, 0xD2, 0xB5, 0x06, 0xAD, 0x02, + 0x41, 0x00, 0xB7, 0x68, 0x19, 0xA7, 0xC7, 0xF9, 0xF1, 0x9A, + 0xDD, 0x5D, 0x27, 0x91, 0xC1, 0x4F, 0x7D, 0x52, 0x67, 0xB6, + 0x76, 0xA1, 0x0D, 0x3D, 0x91, 0x23, 0xB0, 0xB3, 0xF7, 0x49, + 0x86, 0xED, 0xE0, 0xC5, 0xE3, 0xA3, 0x09, 0x04, 0xFD, 0x89, + 0xE2, 0xC5, 0x1A, 0x6E, 0x4B, 0x77, 0xBD, 0x03, 0xC3, 0x7B, + 0xB6, 0x6C, 0x5D, 0xF2, 0xAF, 0x08, 0x94, 0xA8, 0xFA, 0x24, + 0xBD, 0x66, 0x71, 0xF5, 0xAE, 0x45, 0x02, 0x40, 0x15, 0x52, + 0xD1, 0x91, 0x1B, 0xF8, 0x84, 0xDC, 0xD6, 0xAA, 0x89, 0x2A, + 0xE1, 0xBB, 0x28, 0x1D, 0x0B, 0x0A, 0xA3, 0xDE, 0x96, 0x01, + 0x2C, 0x09, 0x40, 0x86, 0x14, 0xAE, 0x1F, 0x75, 0x5E, 0xE3, + 0xF5, 0x00, 0xD3, 0x39, 0xD2, 0xFC, 0x97, 0xEE, 0x61, 0xBB, + 0x28, 0x7C, 0x94, 0xD4, 0x60, 0x42, 0xAB, 0x38, 0x6B, 0x1A, + 0x2E, 0xC4, 0xC3, 0x49, 0x0B, 0xE6, 0x8A, 0xDD, 0xC5, 0xD0, + 0xB4, 0x51, 0x02, 0x41, 0x00, 0xA9, 0x8B, 0xA7, 0xA9, 0xEE, + 0xAE, 0xBB, 0x17, 0xCB, 0x72, 0xF2, 0x50, 0x22, 0x9D, 0xB3, + 0xDF, 0xE0, 0x40, 0x37, 0x08, 0xD5, 0x7F, 0x19, 0x58, 0x80, + 0x70, 0x79, 0x69, 0x99, 0xDF, 0x62, 0x0D, 0x21, 0xAB, 0xDD, + 0xB2, 0xCE, 0x68, 0xB3, 0x9F, 0x87, 0xAF, 0x55, 0xF4, 0xAA, + 0xE1, 0x00, 0x72, 0xBE, 0x6E, 0xC3, 0x94, 0x49, 0xDC, 0xBB, + 0x8E, 0x1A, 0x78, 0xE5, 0x49, 0x1F, 0x55, 0x41, 0xA1 +}; +static const int sizeof_server_key_der_1024 = sizeof(server_key_der_1024); + +/* ./certs/1024/server-cert.der, 1024-bit */ +static const unsigned char server_cert_der_1024[] = +{ + 0x30, 0x82, 0x03, 0xA9, 0x30, 0x82, 0x03, 0x12, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x30, 0x81, 0x99, 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, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, + 0x74, 0x68, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x0F, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, + 0x69, 0x6E, 0x67, 0x5F, 0x31, 0x30, 0x32, 0x34, 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, 0x38, 0x30, 0x34, 0x31, 0x33, 0x31, 0x35, 0x32, + 0x33, 0x31, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x31, + 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x30, + 0x81, 0x95, 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, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0C, + 0x53, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x31, 0x30, + 0x32, 0x34, 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, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, + 0xAA, 0x3E, 0xA5, 0x9C, 0xD3, 0x17, 0x49, 0x65, 0x43, 0xDE, + 0xD0, 0xF3, 0x4B, 0x1C, 0xDB, 0x49, 0x0C, 0xFC, 0x7A, 0x65, + 0x05, 0x6D, 0xDE, 0x6A, 0xC4, 0xE4, 0x73, 0x2C, 0x8A, 0x96, + 0x82, 0x8F, 0x23, 0xA5, 0x06, 0x71, 0x1C, 0x06, 0x3E, 0x2F, + 0x92, 0x8D, 0x0B, 0x29, 0x34, 0x45, 0x59, 0xE9, 0xA9, 0xBC, + 0x61, 0xD7, 0x24, 0x37, 0x5D, 0xB5, 0xC4, 0x37, 0x8D, 0xBA, + 0x67, 0xB2, 0xEF, 0x03, 0x27, 0xFA, 0xC1, 0xB4, 0xCD, 0x6B, + 0x00, 0x66, 0xB4, 0xD6, 0x73, 0x70, 0x1F, 0x08, 0x3A, 0xCC, + 0x77, 0xAD, 0xE9, 0xF9, 0x34, 0xD4, 0xF3, 0xA0, 0x2D, 0xA9, + 0xE7, 0x58, 0xA9, 0xC0, 0x61, 0x84, 0xB6, 0xEC, 0x3D, 0x0A, + 0xAD, 0xFD, 0x5C, 0x86, 0x73, 0xAA, 0x6B, 0x47, 0xD8, 0x8B, + 0x2E, 0x58, 0x4B, 0x69, 0x12, 0x82, 0x26, 0x55, 0xE6, 0x14, + 0xBF, 0x55, 0x70, 0x88, 0xFE, 0xF9, 0x75, 0xE1, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x01, 0x30, 0x81, 0xFE, + 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0xD9, 0x3C, 0x35, 0xEA, 0x74, 0x0E, 0x23, 0xBE, 0x9C, + 0xFC, 0xFA, 0x29, 0x90, 0x09, 0xC1, 0xE7, 0x84, 0x16, 0x9F, + 0x7C, 0x30, 0x81, 0xCE, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, + 0x81, 0xC6, 0x30, 0x81, 0xC3, 0x80, 0x14, 0xD3, 0x22, 0x8F, + 0x28, 0x2C, 0xE0, 0x05, 0xEE, 0xD3, 0xED, 0xC3, 0x71, 0x3D, + 0xC9, 0xB2, 0x36, 0x3A, 0x1D, 0xBF, 0xA8, 0xA1, 0x81, 0x9F, + 0xA4, 0x81, 0x9C, 0x30, 0x81, 0x99, 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, 0x11, 0x30, 0x0F, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, + 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, 0x6F, 0x6E, 0x73, 0x75, + 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, 0x31, 0x30, 0x32, 0x34, + 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, 0xDA, 0xFB, 0x6A, 0x0D, 0xFE, 0xCF, 0x9B, 0x47, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, + 0x81, 0x81, 0x00, 0x0B, 0xC3, 0xAF, 0x43, 0x85, 0x64, 0x61, + 0xE7, 0xAB, 0x5A, 0x2A, 0x1B, 0xB2, 0x29, 0xD5, 0x66, 0x68, + 0x44, 0x1A, 0x6D, 0x66, 0xFC, 0x3D, 0xB1, 0x88, 0xEC, 0xA5, + 0x41, 0x18, 0x67, 0x62, 0x34, 0xA4, 0x5E, 0xC9, 0x69, 0xCD, + 0x40, 0xC8, 0x56, 0x7E, 0xBF, 0xEB, 0xBC, 0x61, 0x1F, 0x33, + 0x34, 0x58, 0xBE, 0x57, 0xFD, 0xE6, 0x98, 0xDD, 0x51, 0x27, + 0x7C, 0xB7, 0x2C, 0xBC, 0xC9, 0x39, 0xE5, 0xE5, 0x95, 0x82, + 0xE1, 0x3F, 0xD9, 0xB9, 0x97, 0x30, 0x4E, 0x33, 0x2C, 0xEF, + 0xF8, 0xDB, 0xB4, 0xEE, 0x35, 0x75, 0x9E, 0x7A, 0x3F, 0x22, + 0x8F, 0xA5, 0x71, 0xD4, 0x01, 0x64, 0x6C, 0xF2, 0x85, 0xF7, + 0x72, 0x99, 0x2C, 0x80, 0x0F, 0xA4, 0x31, 0x1D, 0xD4, 0x0B, + 0x1E, 0xA5, 0x0F, 0xE7, 0x53, 0x0A, 0xDE, 0x15, 0x0D, 0xB2, + 0xD0, 0x6B, 0xF4, 0xD6, 0x2F, 0xE2, 0x0B, 0xA3, 0x8A, 0x5A, + 0x6E +}; +static const int sizeof_server_cert_der_1024 = sizeof(server_cert_der_1024); + +#endif /* USE_CERT_BUFFERS_1024 */ + +#ifdef USE_CERT_BUFFERS_2048 /* ./certs/client-key.der, 2048-bit */ static const unsigned char client_key_der_2048[] = { - 0x30, 0x82, 0x04, 0xA4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, - 0x01, 0x00, 0xC3, 0x03, 0xD1, 0x2B, 0xFE, 0x39, 0xA4, 0x32, - 0x45, 0x3B, 0x53, 0xC8, 0x84, 0x2B, 0x2A, 0x7C, 0x74, 0x9A, - 0xBD, 0xAA, 0x2A, 0x52, 0x07, 0x47, 0xD6, 0xA6, 0x36, 0xB2, - 0x07, 0x32, 0x8E, 0xD0, 0xBA, 0x69, 0x7B, 0xC6, 0xC3, 0x44, - 0x9E, 0xD4, 0x81, 0x48, 0xFD, 0x2D, 0x68, 0xA2, 0x8B, 0x67, - 0xBB, 0xA1, 0x75, 0xC8, 0x36, 0x2C, 0x4A, 0xD2, 0x1B, 0xF7, - 0x8B, 0xBA, 0xCF, 0x0D, 0xF9, 0xEF, 0xEC, 0xF1, 0x81, 0x1E, - 0x7B, 0x9B, 0x03, 0x47, 0x9A, 0xBF, 0x65, 0xCC, 0x7F, 0x65, - 0x24, 0x69, 0xA6, 0xE8, 0x14, 0x89, 0x5B, 0xE4, 0x34, 0xF7, - 0xC5, 0xB0, 0x14, 0x93, 0xF5, 0x67, 0x7B, 0x3A, 0x7A, 0x78, - 0xE1, 0x01, 0x56, 0x56, 0x91, 0xA6, 0x13, 0x42, 0x8D, 0xD2, - 0x3C, 0x40, 0x9C, 0x4C, 0xEF, 0xD1, 0x86, 0xDF, 0x37, 0x51, - 0x1B, 0x0C, 0xA1, 0x3B, 0xF5, 0xF1, 0xA3, 0x4A, 0x35, 0xE4, - 0xE1, 0xCE, 0x96, 0xDF, 0x1B, 0x7E, 0xBF, 0x4E, 0x97, 0xD0, - 0x10, 0xE8, 0xA8, 0x08, 0x30, 0x81, 0xAF, 0x20, 0x0B, 0x43, - 0x14, 0xC5, 0x74, 0x67, 0xB4, 0x32, 0x82, 0x6F, 0x8D, 0x86, - 0xC2, 0x88, 0x40, 0x99, 0x36, 0x83, 0xBA, 0x1E, 0x40, 0x72, - 0x22, 0x17, 0xD7, 0x52, 0x65, 0x24, 0x73, 0xB0, 0xCE, 0xEF, - 0x19, 0xCD, 0xAE, 0xFF, 0x78, 0x6C, 0x7B, 0xC0, 0x12, 0x03, - 0xD4, 0x4E, 0x72, 0x0D, 0x50, 0x6D, 0x3B, 0xA3, 0x3B, 0xA3, - 0x99, 0x5E, 0x9D, 0xC8, 0xD9, 0x0C, 0x85, 0xB3, 0xD9, 0x8A, - 0xD9, 0x54, 0x26, 0xDB, 0x6D, 0xFA, 0xAC, 0xBB, 0xFF, 0x25, - 0x4C, 0xC4, 0xD1, 0x79, 0xF4, 0x71, 0xD3, 0x86, 0x40, 0x18, - 0x13, 0xB0, 0x63, 0xB5, 0x72, 0x4E, 0x30, 0xC4, 0x97, 0x84, - 0x86, 0x2D, 0x56, 0x2F, 0xD7, 0x15, 0xF7, 0x7F, 0xC0, 0xAE, - 0xF5, 0xFC, 0x5B, 0xE5, 0xFB, 0xA1, 0xBA, 0xD3, 0x02, 0x03, - 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x01, 0x00, 0xA2, 0xE6, - 0xD8, 0x5F, 0x10, 0x71, 0x64, 0x08, 0x9E, 0x2E, 0x6D, 0xD1, - 0x6D, 0x1E, 0x85, 0xD2, 0x0A, 0xB1, 0x8C, 0x47, 0xCE, 0x2C, - 0x51, 0x6A, 0xA0, 0x12, 0x9E, 0x53, 0xDE, 0x91, 0x4C, 0x1D, - 0x6D, 0xEA, 0x59, 0x7B, 0xF2, 0x77, 0xAA, 0xD9, 0xC6, 0xD9, - 0x8A, 0xAB, 0xD8, 0xE1, 0x16, 0xE4, 0x63, 0x26, 0xFF, 0xB5, - 0x6C, 0x13, 0x59, 0xB8, 0xE3, 0xA5, 0xC8, 0x72, 0x17, 0x2E, - 0x0C, 0x9F, 0x6F, 0xE5, 0x59, 0x3F, 0x76, 0x6F, 0x49, 0xB1, - 0x11, 0xC2, 0x5A, 0x2E, 0x16, 0x29, 0x0D, 0xDE, 0xB7, 0x8E, - 0xDC, 0x40, 0xD5, 0xA2, 0xEE, 0xE0, 0x1E, 0xA1, 0xF4, 0xBE, - 0x97, 0xDB, 0x86, 0x63, 0x96, 0x14, 0xCD, 0x98, 0x09, 0x60, - 0x2D, 0x30, 0x76, 0x9C, 0x3C, 0xCD, 0xE6, 0x88, 0xEE, 0x47, - 0x92, 0x79, 0x0B, 0x5A, 0x00, 0xE2, 0x5E, 0x5F, 0x11, 0x7C, - 0x7D, 0xF9, 0x08, 0xB7, 0x20, 0x06, 0x89, 0x2A, 0x5D, 0xFD, - 0x00, 0xAB, 0x22, 0xE1, 0xF0, 0xB3, 0xBC, 0x24, 0xA9, 0x5E, - 0x26, 0x0E, 0x1F, 0x00, 0x2D, 0xFE, 0x21, 0x9A, 0x53, 0x5B, - 0x6D, 0xD3, 0x2B, 0xAB, 0x94, 0x82, 0x68, 0x43, 0x36, 0xD8, - 0xF6, 0x2F, 0xC6, 0x22, 0xFC, 0xB5, 0x41, 0x5D, 0x0D, 0x33, - 0x60, 0xEA, 0xA4, 0x7D, 0x7E, 0xE8, 0x4B, 0x55, 0x91, 0x56, - 0xD3, 0x5C, 0x57, 0x8F, 0x1F, 0x94, 0x17, 0x2F, 0xAA, 0xDE, - 0xE9, 0x9E, 0xA8, 0xF4, 0xCF, 0x8A, 0x4C, 0x8E, 0xA0, 0xE4, - 0x56, 0x73, 0xB2, 0xCF, 0x4F, 0x86, 0xC5, 0x69, 0x3C, 0xF3, - 0x24, 0x20, 0x8B, 0x5C, 0x96, 0x0C, 0xFA, 0x6B, 0x12, 0x3B, - 0x9A, 0x67, 0xC1, 0xDF, 0xC6, 0x96, 0xB2, 0xA5, 0xD5, 0x92, - 0x0D, 0x9B, 0x09, 0x42, 0x68, 0x24, 0x10, 0x45, 0xD4, 0x50, - 0xE4, 0x17, 0x39, 0x48, 0xD0, 0x35, 0x8B, 0x94, 0x6D, 0x11, - 0xDE, 0x8F, 0xCA, 0x59, 0x02, 0x81, 0x81, 0x00, 0xEA, 0x24, - 0xA7, 0xF9, 0x69, 0x33, 0xE9, 0x71, 0xDC, 0x52, 0x7D, 0x88, - 0x21, 0x28, 0x2F, 0x49, 0xDE, 0xBA, 0x72, 0x16, 0xE9, 0xCC, - 0x47, 0x7A, 0x88, 0x0D, 0x94, 0x57, 0x84, 0x58, 0x16, 0x3A, - 0x81, 0xB0, 0x3F, 0xA2, 0xCF, 0xA6, 0x6C, 0x1E, 0xB0, 0x06, - 0x29, 0x00, 0x8F, 0xE7, 0x77, 0x76, 0xAC, 0xDB, 0xCA, 0xC7, - 0xD9, 0x5E, 0x9B, 0x3F, 0x26, 0x90, 0x52, 0xAE, 0xFC, 0x38, - 0x90, 0x00, 0x14, 0xBB, 0xB4, 0x0F, 0x58, 0x94, 0xE7, 0x2F, - 0x6A, 0x7E, 0x1C, 0x4F, 0x41, 0x21, 0xD4, 0x31, 0x59, 0x1F, - 0x4E, 0x8A, 0x1A, 0x8D, 0xA7, 0x57, 0x6C, 0x22, 0xD8, 0xE5, - 0xF4, 0x7E, 0x32, 0xA6, 0x10, 0xCB, 0x64, 0xA5, 0x55, 0x03, - 0x87, 0xA6, 0x27, 0x05, 0x8C, 0xC3, 0xD7, 0xB6, 0x27, 0xB2, - 0x4D, 0xBA, 0x30, 0xDA, 0x47, 0x8F, 0x54, 0xD3, 0x3D, 0x8B, - 0x84, 0x8D, 0x94, 0x98, 0x58, 0xA5, 0x02, 0x81, 0x81, 0x00, - 0xD5, 0x38, 0x1B, 0xC3, 0x8F, 0xC5, 0x93, 0x0C, 0x47, 0x0B, - 0x6F, 0x35, 0x92, 0xC5, 0xB0, 0x8D, 0x46, 0xC8, 0x92, 0x18, - 0x8F, 0xF5, 0x80, 0x0A, 0xF7, 0xEF, 0xA1, 0xFE, 0x80, 0xB9, - 0xB5, 0x2A, 0xBA, 0xCA, 0x18, 0xB0, 0x5D, 0xA5, 0x07, 0xD0, - 0x93, 0x8D, 0xD8, 0x9C, 0x04, 0x1C, 0xD4, 0x62, 0x8E, 0xA6, - 0x26, 0x81, 0x01, 0xFF, 0xCE, 0x8A, 0x2A, 0x63, 0x34, 0x35, - 0x40, 0xAA, 0x6D, 0x80, 0xDE, 0x89, 0x23, 0x6A, 0x57, 0x4D, - 0x9E, 0x6E, 0xAD, 0x93, 0x4E, 0x56, 0x90, 0x0B, 0x6D, 0x9D, - 0x73, 0x8B, 0x0C, 0xAE, 0x27, 0x3D, 0xDE, 0x4E, 0xF0, 0xAA, - 0xC5, 0x6C, 0x78, 0x67, 0x6C, 0x94, 0x52, 0x9C, 0x37, 0x67, - 0x6C, 0x2D, 0xEF, 0xBB, 0xAF, 0xDF, 0xA6, 0x90, 0x3C, 0xC4, - 0x47, 0xCF, 0x8D, 0x96, 0x9E, 0x98, 0xA9, 0xB4, 0x9F, 0xC5, - 0xA6, 0x50, 0xDC, 0xB3, 0xF0, 0xFB, 0x74, 0x17, 0x02, 0x81, - 0x80, 0x5E, 0x83, 0x09, 0x62, 0xBD, 0xBA, 0x7C, 0xA2, 0xBF, - 0x42, 0x74, 0xF5, 0x7C, 0x1C, 0xD2, 0x69, 0xC9, 0x04, 0x0D, - 0x85, 0x7E, 0x3E, 0x3D, 0x24, 0x12, 0xC3, 0x18, 0x7B, 0xF3, - 0x29, 0xF3, 0x5F, 0x0E, 0x76, 0x6C, 0x59, 0x75, 0xE4, 0x41, - 0x84, 0x69, 0x9D, 0x32, 0xF3, 0xCD, 0x22, 0xAB, 0xB0, 0x35, - 0xBA, 0x4A, 0xB2, 0x3C, 0xE5, 0xD9, 0x58, 0xB6, 0x62, 0x4F, - 0x5D, 0xDE, 0xE5, 0x9E, 0x0A, 0xCA, 0x53, 0xB2, 0x2C, 0xF7, - 0x9E, 0xB3, 0x6B, 0x0A, 0x5B, 0x79, 0x65, 0xEC, 0x6E, 0x91, - 0x4E, 0x92, 0x20, 0xF6, 0xFC, 0xFC, 0x16, 0xED, 0xD3, 0x76, - 0x0C, 0xE2, 0xEC, 0x7F, 0xB2, 0x69, 0x13, 0x6B, 0x78, 0x0E, - 0x5A, 0x46, 0x64, 0xB4, 0x5E, 0xB7, 0x25, 0xA0, 0x5A, 0x75, - 0x3A, 0x4B, 0xEF, 0xC7, 0x3C, 0x3E, 0xF7, 0xFD, 0x26, 0xB8, - 0x20, 0xC4, 0x99, 0x0A, 0x9A, 0x73, 0xBE, 0xC3, 0x19, 0x02, - 0x81, 0x81, 0x00, 0xBA, 0x44, 0x93, 0x14, 0xAC, 0x34, 0x19, - 0x3B, 0x5F, 0x91, 0x60, 0xAC, 0xF7, 0xB4, 0xD6, 0x81, 0x05, - 0x36, 0x51, 0x53, 0x3D, 0xE8, 0x65, 0xDC, 0xAF, 0x2E, 0xDC, - 0x61, 0x3E, 0xC9, 0x7D, 0xB8, 0x7F, 0x87, 0xF0, 0x3B, 0x9B, - 0x03, 0x82, 0x29, 0x37, 0xCE, 0x72, 0x4E, 0x11, 0xD5, 0xB1, - 0xC1, 0x0C, 0x07, 0xA0, 0x99, 0x91, 0x4A, 0x8D, 0x7F, 0xEC, - 0x79, 0xCF, 0xF1, 0x39, 0xB5, 0xE9, 0x85, 0xEC, 0x62, 0xF7, - 0xDA, 0x7D, 0xBC, 0x64, 0x4D, 0x22, 0x3C, 0x0E, 0xF2, 0xD6, - 0x51, 0xF5, 0x87, 0xD8, 0x99, 0xC0, 0x11, 0x20, 0x5D, 0x0F, - 0x29, 0xFD, 0x5B, 0xE2, 0xAE, 0xD9, 0x1C, 0xD9, 0x21, 0x56, - 0x6D, 0xFC, 0x84, 0xD0, 0x5F, 0xED, 0x10, 0x15, 0x1C, 0x18, - 0x21, 0xE7, 0xC4, 0x3D, 0x4B, 0xD7, 0xD0, 0x9E, 0x6A, 0x95, - 0xCF, 0x22, 0xC9, 0x03, 0x7B, 0x9E, 0xE3, 0x60, 0x01, 0xFC, - 0x2F, 0x02, 0x81, 0x80, 0x11, 0xD0, 0x4B, 0xCF, 0x1B, 0x67, - 0xB9, 0x9F, 0x10, 0x75, 0x47, 0x86, 0x65, 0xAE, 0x31, 0xC2, - 0xC6, 0x30, 0xAC, 0x59, 0x06, 0x50, 0xD9, 0x0F, 0xB5, 0x70, - 0x06, 0xF7, 0xF0, 0xD3, 0xC8, 0x62, 0x7C, 0xA8, 0xDA, 0x6E, - 0xF6, 0x21, 0x3F, 0xD3, 0x7F, 0x5F, 0xEA, 0x8A, 0xAB, 0x3F, - 0xD9, 0x2A, 0x5E, 0xF3, 0x51, 0xD2, 0xC2, 0x30, 0x37, 0xE3, - 0x2D, 0xA3, 0x75, 0x0D, 0x1E, 0x4D, 0x21, 0x34, 0xD5, 0x57, - 0x70, 0x5C, 0x89, 0xBF, 0x72, 0xEC, 0x4A, 0x6E, 0x68, 0xD5, - 0xCD, 0x18, 0x74, 0x33, 0x4E, 0x8C, 0x3A, 0x45, 0x8F, 0xE6, - 0x96, 0x40, 0xEB, 0x63, 0xF9, 0x19, 0x86, 0x3A, 0x51, 0xDD, - 0x89, 0x4B, 0xB0, 0xF3, 0xF9, 0x9F, 0x5D, 0x28, 0x95, 0x38, - 0xBE, 0x35, 0xAB, 0xCA, 0x5C, 0xE7, 0x93, 0x53, 0x34, 0xA1, - 0x45, 0x5D, 0x13, 0x39, 0x65, 0x42, 0x46, 0xA1, 0x9F, 0xCD, - 0xF5, 0xBF + 0x30, 0x82, 0x04, 0xA4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xC3, 0x03, 0xD1, 0x2B, 0xFE, 0x39, 0xA4, 0x32, + 0x45, 0x3B, 0x53, 0xC8, 0x84, 0x2B, 0x2A, 0x7C, 0x74, 0x9A, + 0xBD, 0xAA, 0x2A, 0x52, 0x07, 0x47, 0xD6, 0xA6, 0x36, 0xB2, + 0x07, 0x32, 0x8E, 0xD0, 0xBA, 0x69, 0x7B, 0xC6, 0xC3, 0x44, + 0x9E, 0xD4, 0x81, 0x48, 0xFD, 0x2D, 0x68, 0xA2, 0x8B, 0x67, + 0xBB, 0xA1, 0x75, 0xC8, 0x36, 0x2C, 0x4A, 0xD2, 0x1B, 0xF7, + 0x8B, 0xBA, 0xCF, 0x0D, 0xF9, 0xEF, 0xEC, 0xF1, 0x81, 0x1E, + 0x7B, 0x9B, 0x03, 0x47, 0x9A, 0xBF, 0x65, 0xCC, 0x7F, 0x65, + 0x24, 0x69, 0xA6, 0xE8, 0x14, 0x89, 0x5B, 0xE4, 0x34, 0xF7, + 0xC5, 0xB0, 0x14, 0x93, 0xF5, 0x67, 0x7B, 0x3A, 0x7A, 0x78, + 0xE1, 0x01, 0x56, 0x56, 0x91, 0xA6, 0x13, 0x42, 0x8D, 0xD2, + 0x3C, 0x40, 0x9C, 0x4C, 0xEF, 0xD1, 0x86, 0xDF, 0x37, 0x51, + 0x1B, 0x0C, 0xA1, 0x3B, 0xF5, 0xF1, 0xA3, 0x4A, 0x35, 0xE4, + 0xE1, 0xCE, 0x96, 0xDF, 0x1B, 0x7E, 0xBF, 0x4E, 0x97, 0xD0, + 0x10, 0xE8, 0xA8, 0x08, 0x30, 0x81, 0xAF, 0x20, 0x0B, 0x43, + 0x14, 0xC5, 0x74, 0x67, 0xB4, 0x32, 0x82, 0x6F, 0x8D, 0x86, + 0xC2, 0x88, 0x40, 0x99, 0x36, 0x83, 0xBA, 0x1E, 0x40, 0x72, + 0x22, 0x17, 0xD7, 0x52, 0x65, 0x24, 0x73, 0xB0, 0xCE, 0xEF, + 0x19, 0xCD, 0xAE, 0xFF, 0x78, 0x6C, 0x7B, 0xC0, 0x12, 0x03, + 0xD4, 0x4E, 0x72, 0x0D, 0x50, 0x6D, 0x3B, 0xA3, 0x3B, 0xA3, + 0x99, 0x5E, 0x9D, 0xC8, 0xD9, 0x0C, 0x85, 0xB3, 0xD9, 0x8A, + 0xD9, 0x54, 0x26, 0xDB, 0x6D, 0xFA, 0xAC, 0xBB, 0xFF, 0x25, + 0x4C, 0xC4, 0xD1, 0x79, 0xF4, 0x71, 0xD3, 0x86, 0x40, 0x18, + 0x13, 0xB0, 0x63, 0xB5, 0x72, 0x4E, 0x30, 0xC4, 0x97, 0x84, + 0x86, 0x2D, 0x56, 0x2F, 0xD7, 0x15, 0xF7, 0x7F, 0xC0, 0xAE, + 0xF5, 0xFC, 0x5B, 0xE5, 0xFB, 0xA1, 0xBA, 0xD3, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x01, 0x00, 0xA2, 0xE6, + 0xD8, 0x5F, 0x10, 0x71, 0x64, 0x08, 0x9E, 0x2E, 0x6D, 0xD1, + 0x6D, 0x1E, 0x85, 0xD2, 0x0A, 0xB1, 0x8C, 0x47, 0xCE, 0x2C, + 0x51, 0x6A, 0xA0, 0x12, 0x9E, 0x53, 0xDE, 0x91, 0x4C, 0x1D, + 0x6D, 0xEA, 0x59, 0x7B, 0xF2, 0x77, 0xAA, 0xD9, 0xC6, 0xD9, + 0x8A, 0xAB, 0xD8, 0xE1, 0x16, 0xE4, 0x63, 0x26, 0xFF, 0xB5, + 0x6C, 0x13, 0x59, 0xB8, 0xE3, 0xA5, 0xC8, 0x72, 0x17, 0x2E, + 0x0C, 0x9F, 0x6F, 0xE5, 0x59, 0x3F, 0x76, 0x6F, 0x49, 0xB1, + 0x11, 0xC2, 0x5A, 0x2E, 0x16, 0x29, 0x0D, 0xDE, 0xB7, 0x8E, + 0xDC, 0x40, 0xD5, 0xA2, 0xEE, 0xE0, 0x1E, 0xA1, 0xF4, 0xBE, + 0x97, 0xDB, 0x86, 0x63, 0x96, 0x14, 0xCD, 0x98, 0x09, 0x60, + 0x2D, 0x30, 0x76, 0x9C, 0x3C, 0xCD, 0xE6, 0x88, 0xEE, 0x47, + 0x92, 0x79, 0x0B, 0x5A, 0x00, 0xE2, 0x5E, 0x5F, 0x11, 0x7C, + 0x7D, 0xF9, 0x08, 0xB7, 0x20, 0x06, 0x89, 0x2A, 0x5D, 0xFD, + 0x00, 0xAB, 0x22, 0xE1, 0xF0, 0xB3, 0xBC, 0x24, 0xA9, 0x5E, + 0x26, 0x0E, 0x1F, 0x00, 0x2D, 0xFE, 0x21, 0x9A, 0x53, 0x5B, + 0x6D, 0xD3, 0x2B, 0xAB, 0x94, 0x82, 0x68, 0x43, 0x36, 0xD8, + 0xF6, 0x2F, 0xC6, 0x22, 0xFC, 0xB5, 0x41, 0x5D, 0x0D, 0x33, + 0x60, 0xEA, 0xA4, 0x7D, 0x7E, 0xE8, 0x4B, 0x55, 0x91, 0x56, + 0xD3, 0x5C, 0x57, 0x8F, 0x1F, 0x94, 0x17, 0x2F, 0xAA, 0xDE, + 0xE9, 0x9E, 0xA8, 0xF4, 0xCF, 0x8A, 0x4C, 0x8E, 0xA0, 0xE4, + 0x56, 0x73, 0xB2, 0xCF, 0x4F, 0x86, 0xC5, 0x69, 0x3C, 0xF3, + 0x24, 0x20, 0x8B, 0x5C, 0x96, 0x0C, 0xFA, 0x6B, 0x12, 0x3B, + 0x9A, 0x67, 0xC1, 0xDF, 0xC6, 0x96, 0xB2, 0xA5, 0xD5, 0x92, + 0x0D, 0x9B, 0x09, 0x42, 0x68, 0x24, 0x10, 0x45, 0xD4, 0x50, + 0xE4, 0x17, 0x39, 0x48, 0xD0, 0x35, 0x8B, 0x94, 0x6D, 0x11, + 0xDE, 0x8F, 0xCA, 0x59, 0x02, 0x81, 0x81, 0x00, 0xEA, 0x24, + 0xA7, 0xF9, 0x69, 0x33, 0xE9, 0x71, 0xDC, 0x52, 0x7D, 0x88, + 0x21, 0x28, 0x2F, 0x49, 0xDE, 0xBA, 0x72, 0x16, 0xE9, 0xCC, + 0x47, 0x7A, 0x88, 0x0D, 0x94, 0x57, 0x84, 0x58, 0x16, 0x3A, + 0x81, 0xB0, 0x3F, 0xA2, 0xCF, 0xA6, 0x6C, 0x1E, 0xB0, 0x06, + 0x29, 0x00, 0x8F, 0xE7, 0x77, 0x76, 0xAC, 0xDB, 0xCA, 0xC7, + 0xD9, 0x5E, 0x9B, 0x3F, 0x26, 0x90, 0x52, 0xAE, 0xFC, 0x38, + 0x90, 0x00, 0x14, 0xBB, 0xB4, 0x0F, 0x58, 0x94, 0xE7, 0x2F, + 0x6A, 0x7E, 0x1C, 0x4F, 0x41, 0x21, 0xD4, 0x31, 0x59, 0x1F, + 0x4E, 0x8A, 0x1A, 0x8D, 0xA7, 0x57, 0x6C, 0x22, 0xD8, 0xE5, + 0xF4, 0x7E, 0x32, 0xA6, 0x10, 0xCB, 0x64, 0xA5, 0x55, 0x03, + 0x87, 0xA6, 0x27, 0x05, 0x8C, 0xC3, 0xD7, 0xB6, 0x27, 0xB2, + 0x4D, 0xBA, 0x30, 0xDA, 0x47, 0x8F, 0x54, 0xD3, 0x3D, 0x8B, + 0x84, 0x8D, 0x94, 0x98, 0x58, 0xA5, 0x02, 0x81, 0x81, 0x00, + 0xD5, 0x38, 0x1B, 0xC3, 0x8F, 0xC5, 0x93, 0x0C, 0x47, 0x0B, + 0x6F, 0x35, 0x92, 0xC5, 0xB0, 0x8D, 0x46, 0xC8, 0x92, 0x18, + 0x8F, 0xF5, 0x80, 0x0A, 0xF7, 0xEF, 0xA1, 0xFE, 0x80, 0xB9, + 0xB5, 0x2A, 0xBA, 0xCA, 0x18, 0xB0, 0x5D, 0xA5, 0x07, 0xD0, + 0x93, 0x8D, 0xD8, 0x9C, 0x04, 0x1C, 0xD4, 0x62, 0x8E, 0xA6, + 0x26, 0x81, 0x01, 0xFF, 0xCE, 0x8A, 0x2A, 0x63, 0x34, 0x35, + 0x40, 0xAA, 0x6D, 0x80, 0xDE, 0x89, 0x23, 0x6A, 0x57, 0x4D, + 0x9E, 0x6E, 0xAD, 0x93, 0x4E, 0x56, 0x90, 0x0B, 0x6D, 0x9D, + 0x73, 0x8B, 0x0C, 0xAE, 0x27, 0x3D, 0xDE, 0x4E, 0xF0, 0xAA, + 0xC5, 0x6C, 0x78, 0x67, 0x6C, 0x94, 0x52, 0x9C, 0x37, 0x67, + 0x6C, 0x2D, 0xEF, 0xBB, 0xAF, 0xDF, 0xA6, 0x90, 0x3C, 0xC4, + 0x47, 0xCF, 0x8D, 0x96, 0x9E, 0x98, 0xA9, 0xB4, 0x9F, 0xC5, + 0xA6, 0x50, 0xDC, 0xB3, 0xF0, 0xFB, 0x74, 0x17, 0x02, 0x81, + 0x80, 0x5E, 0x83, 0x09, 0x62, 0xBD, 0xBA, 0x7C, 0xA2, 0xBF, + 0x42, 0x74, 0xF5, 0x7C, 0x1C, 0xD2, 0x69, 0xC9, 0x04, 0x0D, + 0x85, 0x7E, 0x3E, 0x3D, 0x24, 0x12, 0xC3, 0x18, 0x7B, 0xF3, + 0x29, 0xF3, 0x5F, 0x0E, 0x76, 0x6C, 0x59, 0x75, 0xE4, 0x41, + 0x84, 0x69, 0x9D, 0x32, 0xF3, 0xCD, 0x22, 0xAB, 0xB0, 0x35, + 0xBA, 0x4A, 0xB2, 0x3C, 0xE5, 0xD9, 0x58, 0xB6, 0x62, 0x4F, + 0x5D, 0xDE, 0xE5, 0x9E, 0x0A, 0xCA, 0x53, 0xB2, 0x2C, 0xF7, + 0x9E, 0xB3, 0x6B, 0x0A, 0x5B, 0x79, 0x65, 0xEC, 0x6E, 0x91, + 0x4E, 0x92, 0x20, 0xF6, 0xFC, 0xFC, 0x16, 0xED, 0xD3, 0x76, + 0x0C, 0xE2, 0xEC, 0x7F, 0xB2, 0x69, 0x13, 0x6B, 0x78, 0x0E, + 0x5A, 0x46, 0x64, 0xB4, 0x5E, 0xB7, 0x25, 0xA0, 0x5A, 0x75, + 0x3A, 0x4B, 0xEF, 0xC7, 0x3C, 0x3E, 0xF7, 0xFD, 0x26, 0xB8, + 0x20, 0xC4, 0x99, 0x0A, 0x9A, 0x73, 0xBE, 0xC3, 0x19, 0x02, + 0x81, 0x81, 0x00, 0xBA, 0x44, 0x93, 0x14, 0xAC, 0x34, 0x19, + 0x3B, 0x5F, 0x91, 0x60, 0xAC, 0xF7, 0xB4, 0xD6, 0x81, 0x05, + 0x36, 0x51, 0x53, 0x3D, 0xE8, 0x65, 0xDC, 0xAF, 0x2E, 0xDC, + 0x61, 0x3E, 0xC9, 0x7D, 0xB8, 0x7F, 0x87, 0xF0, 0x3B, 0x9B, + 0x03, 0x82, 0x29, 0x37, 0xCE, 0x72, 0x4E, 0x11, 0xD5, 0xB1, + 0xC1, 0x0C, 0x07, 0xA0, 0x99, 0x91, 0x4A, 0x8D, 0x7F, 0xEC, + 0x79, 0xCF, 0xF1, 0x39, 0xB5, 0xE9, 0x85, 0xEC, 0x62, 0xF7, + 0xDA, 0x7D, 0xBC, 0x64, 0x4D, 0x22, 0x3C, 0x0E, 0xF2, 0xD6, + 0x51, 0xF5, 0x87, 0xD8, 0x99, 0xC0, 0x11, 0x20, 0x5D, 0x0F, + 0x29, 0xFD, 0x5B, 0xE2, 0xAE, 0xD9, 0x1C, 0xD9, 0x21, 0x56, + 0x6D, 0xFC, 0x84, 0xD0, 0x5F, 0xED, 0x10, 0x15, 0x1C, 0x18, + 0x21, 0xE7, 0xC4, 0x3D, 0x4B, 0xD7, 0xD0, 0x9E, 0x6A, 0x95, + 0xCF, 0x22, 0xC9, 0x03, 0x7B, 0x9E, 0xE3, 0x60, 0x01, 0xFC, + 0x2F, 0x02, 0x81, 0x80, 0x11, 0xD0, 0x4B, 0xCF, 0x1B, 0x67, + 0xB9, 0x9F, 0x10, 0x75, 0x47, 0x86, 0x65, 0xAE, 0x31, 0xC2, + 0xC6, 0x30, 0xAC, 0x59, 0x06, 0x50, 0xD9, 0x0F, 0xB5, 0x70, + 0x06, 0xF7, 0xF0, 0xD3, 0xC8, 0x62, 0x7C, 0xA8, 0xDA, 0x6E, + 0xF6, 0x21, 0x3F, 0xD3, 0x7F, 0x5F, 0xEA, 0x8A, 0xAB, 0x3F, + 0xD9, 0x2A, 0x5E, 0xF3, 0x51, 0xD2, 0xC2, 0x30, 0x37, 0xE3, + 0x2D, 0xA3, 0x75, 0x0D, 0x1E, 0x4D, 0x21, 0x34, 0xD5, 0x57, + 0x70, 0x5C, 0x89, 0xBF, 0x72, 0xEC, 0x4A, 0x6E, 0x68, 0xD5, + 0xCD, 0x18, 0x74, 0x33, 0x4E, 0x8C, 0x3A, 0x45, 0x8F, 0xE6, + 0x96, 0x40, 0xEB, 0x63, 0xF9, 0x19, 0x86, 0x3A, 0x51, 0xDD, + 0x89, 0x4B, 0xB0, 0xF3, 0xF9, 0x9F, 0x5D, 0x28, 0x95, 0x38, + 0xBE, 0x35, 0xAB, 0xCA, 0x5C, 0xE7, 0x93, 0x53, 0x34, 0xA1, + 0x45, 0x5D, 0x13, 0x39, 0x65, 0x42, 0x46, 0xA1, 0x9F, 0xCD, + 0xF5, 0xBF }; static const int sizeof_client_key_der_2048 = sizeof(client_key_der_2048); +/* ./certs/client-keyPub.der, 2048-bit */ +static const unsigned char client_keypub_der_2048[] = +{ + 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, + 0x01, 0x01, 0x00, 0xC3, 0x03, 0xD1, 0x2B, 0xFE, 0x39, 0xA4, + 0x32, 0x45, 0x3B, 0x53, 0xC8, 0x84, 0x2B, 0x2A, 0x7C, 0x74, + 0x9A, 0xBD, 0xAA, 0x2A, 0x52, 0x07, 0x47, 0xD6, 0xA6, 0x36, + 0xB2, 0x07, 0x32, 0x8E, 0xD0, 0xBA, 0x69, 0x7B, 0xC6, 0xC3, + 0x44, 0x9E, 0xD4, 0x81, 0x48, 0xFD, 0x2D, 0x68, 0xA2, 0x8B, + 0x67, 0xBB, 0xA1, 0x75, 0xC8, 0x36, 0x2C, 0x4A, 0xD2, 0x1B, + 0xF7, 0x8B, 0xBA, 0xCF, 0x0D, 0xF9, 0xEF, 0xEC, 0xF1, 0x81, + 0x1E, 0x7B, 0x9B, 0x03, 0x47, 0x9A, 0xBF, 0x65, 0xCC, 0x7F, + 0x65, 0x24, 0x69, 0xA6, 0xE8, 0x14, 0x89, 0x5B, 0xE4, 0x34, + 0xF7, 0xC5, 0xB0, 0x14, 0x93, 0xF5, 0x67, 0x7B, 0x3A, 0x7A, + 0x78, 0xE1, 0x01, 0x56, 0x56, 0x91, 0xA6, 0x13, 0x42, 0x8D, + 0xD2, 0x3C, 0x40, 0x9C, 0x4C, 0xEF, 0xD1, 0x86, 0xDF, 0x37, + 0x51, 0x1B, 0x0C, 0xA1, 0x3B, 0xF5, 0xF1, 0xA3, 0x4A, 0x35, + 0xE4, 0xE1, 0xCE, 0x96, 0xDF, 0x1B, 0x7E, 0xBF, 0x4E, 0x97, + 0xD0, 0x10, 0xE8, 0xA8, 0x08, 0x30, 0x81, 0xAF, 0x20, 0x0B, + 0x43, 0x14, 0xC5, 0x74, 0x67, 0xB4, 0x32, 0x82, 0x6F, 0x8D, + 0x86, 0xC2, 0x88, 0x40, 0x99, 0x36, 0x83, 0xBA, 0x1E, 0x40, + 0x72, 0x22, 0x17, 0xD7, 0x52, 0x65, 0x24, 0x73, 0xB0, 0xCE, + 0xEF, 0x19, 0xCD, 0xAE, 0xFF, 0x78, 0x6C, 0x7B, 0xC0, 0x12, + 0x03, 0xD4, 0x4E, 0x72, 0x0D, 0x50, 0x6D, 0x3B, 0xA3, 0x3B, + 0xA3, 0x99, 0x5E, 0x9D, 0xC8, 0xD9, 0x0C, 0x85, 0xB3, 0xD9, + 0x8A, 0xD9, 0x54, 0x26, 0xDB, 0x6D, 0xFA, 0xAC, 0xBB, 0xFF, + 0x25, 0x4C, 0xC4, 0xD1, 0x79, 0xF4, 0x71, 0xD3, 0x86, 0x40, + 0x18, 0x13, 0xB0, 0x63, 0xB5, 0x72, 0x4E, 0x30, 0xC4, 0x97, + 0x84, 0x86, 0x2D, 0x56, 0x2F, 0xD7, 0x15, 0xF7, 0x7F, 0xC0, + 0xAE, 0xF5, 0xFC, 0x5B, 0xE5, 0xFB, 0xA1, 0xBA, 0xD3, 0x02, + 0x03, 0x01, 0x00, 0x01 +}; +static const int sizeof_client_keypub_der_2048 = sizeof(client_keypub_der_2048); + /* ./certs/client-cert.der, 2048-bit */ static const unsigned char client_cert_der_2048[] = { - 0x30, 0x82, 0x04, 0xCA, 0x30, 0x82, 0x03, 0xB2, 0xA0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xAA, 0x27, 0xB3, 0xC5, - 0xA9, 0x72, 0x6E, 0x0D, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, - 0x81, 0x9E, 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, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, - 0x32, 0x30, 0x34, 0x38, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, - 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, - 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x32, 0x30, 0x34, - 0x38, 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, 0x35, 0x30, 0x35, 0x30, 0x37, - 0x31, 0x38, 0x32, 0x31, 0x30, 0x31, 0x5A, 0x17, 0x0D, 0x31, - 0x38, 0x30, 0x31, 0x33, 0x31, 0x31, 0x38, 0x32, 0x31, 0x30, - 0x31, 0x5A, 0x30, 0x81, 0x9E, 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, 0x15, 0x30, 0x13, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, - 0x53, 0x4C, 0x5F, 0x32, 0x30, 0x34, 0x38, 0x31, 0x19, 0x30, - 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, - 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, - 0x32, 0x30, 0x34, 0x38, 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, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, - 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, - 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xC3, 0x03, 0xD1, 0x2B, - 0xFE, 0x39, 0xA4, 0x32, 0x45, 0x3B, 0x53, 0xC8, 0x84, 0x2B, - 0x2A, 0x7C, 0x74, 0x9A, 0xBD, 0xAA, 0x2A, 0x52, 0x07, 0x47, - 0xD6, 0xA6, 0x36, 0xB2, 0x07, 0x32, 0x8E, 0xD0, 0xBA, 0x69, - 0x7B, 0xC6, 0xC3, 0x44, 0x9E, 0xD4, 0x81, 0x48, 0xFD, 0x2D, - 0x68, 0xA2, 0x8B, 0x67, 0xBB, 0xA1, 0x75, 0xC8, 0x36, 0x2C, - 0x4A, 0xD2, 0x1B, 0xF7, 0x8B, 0xBA, 0xCF, 0x0D, 0xF9, 0xEF, - 0xEC, 0xF1, 0x81, 0x1E, 0x7B, 0x9B, 0x03, 0x47, 0x9A, 0xBF, - 0x65, 0xCC, 0x7F, 0x65, 0x24, 0x69, 0xA6, 0xE8, 0x14, 0x89, - 0x5B, 0xE4, 0x34, 0xF7, 0xC5, 0xB0, 0x14, 0x93, 0xF5, 0x67, - 0x7B, 0x3A, 0x7A, 0x78, 0xE1, 0x01, 0x56, 0x56, 0x91, 0xA6, - 0x13, 0x42, 0x8D, 0xD2, 0x3C, 0x40, 0x9C, 0x4C, 0xEF, 0xD1, - 0x86, 0xDF, 0x37, 0x51, 0x1B, 0x0C, 0xA1, 0x3B, 0xF5, 0xF1, - 0xA3, 0x4A, 0x35, 0xE4, 0xE1, 0xCE, 0x96, 0xDF, 0x1B, 0x7E, - 0xBF, 0x4E, 0x97, 0xD0, 0x10, 0xE8, 0xA8, 0x08, 0x30, 0x81, - 0xAF, 0x20, 0x0B, 0x43, 0x14, 0xC5, 0x74, 0x67, 0xB4, 0x32, - 0x82, 0x6F, 0x8D, 0x86, 0xC2, 0x88, 0x40, 0x99, 0x36, 0x83, - 0xBA, 0x1E, 0x40, 0x72, 0x22, 0x17, 0xD7, 0x52, 0x65, 0x24, - 0x73, 0xB0, 0xCE, 0xEF, 0x19, 0xCD, 0xAE, 0xFF, 0x78, 0x6C, - 0x7B, 0xC0, 0x12, 0x03, 0xD4, 0x4E, 0x72, 0x0D, 0x50, 0x6D, - 0x3B, 0xA3, 0x3B, 0xA3, 0x99, 0x5E, 0x9D, 0xC8, 0xD9, 0x0C, - 0x85, 0xB3, 0xD9, 0x8A, 0xD9, 0x54, 0x26, 0xDB, 0x6D, 0xFA, - 0xAC, 0xBB, 0xFF, 0x25, 0x4C, 0xC4, 0xD1, 0x79, 0xF4, 0x71, - 0xD3, 0x86, 0x40, 0x18, 0x13, 0xB0, 0x63, 0xB5, 0x72, 0x4E, - 0x30, 0xC4, 0x97, 0x84, 0x86, 0x2D, 0x56, 0x2F, 0xD7, 0x15, - 0xF7, 0x7F, 0xC0, 0xAE, 0xF5, 0xFC, 0x5B, 0xE5, 0xFB, 0xA1, - 0xBA, 0xD3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, - 0x07, 0x30, 0x82, 0x01, 0x03, 0x30, 0x1D, 0x06, 0x03, 0x55, - 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x33, 0xD8, 0x45, 0x66, - 0xD7, 0x68, 0x87, 0x18, 0x7E, 0x54, 0x0D, 0x70, 0x27, 0x91, - 0xC7, 0x26, 0xD7, 0x85, 0x65, 0xC0, 0x30, 0x81, 0xD3, 0x06, - 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0xCB, 0x30, 0x81, 0xC8, - 0x80, 0x14, 0x33, 0xD8, 0x45, 0x66, 0xD7, 0x68, 0x87, 0x18, - 0x7E, 0x54, 0x0D, 0x70, 0x27, 0x91, 0xC7, 0x26, 0xD7, 0x85, - 0x65, 0xC0, 0xA1, 0x81, 0xA4, 0xA4, 0x81, 0xA1, 0x30, 0x81, - 0x9E, 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, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, - 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, 0x32, - 0x30, 0x34, 0x38, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, - 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, - 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x32, 0x30, 0x34, 0x38, - 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, 0xAA, 0x27, 0xB3, 0xC5, 0xA9, 0x72, 0x6E, 0x0D, - 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, - 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x01, 0x00, 0x51, 0x96, 0xA7, 0x1C, 0x26, 0x5D, - 0x1C, 0x90, 0xC6, 0x32, 0x9F, 0x96, 0x15, 0xF2, 0x1D, 0xE7, - 0x93, 0x9C, 0xAC, 0x75, 0x56, 0x95, 0xFD, 0x20, 0x70, 0xAB, - 0x45, 0x6A, 0x09, 0xB0, 0xF3, 0xF2, 0x03, 0xA8, 0xDB, 0xDC, - 0x2F, 0xBC, 0x1F, 0x87, 0x7A, 0xA3, 0xD4, 0x8F, 0xD5, 0x49, - 0x97, 0x7E, 0x3C, 0x54, 0xAC, 0xB1, 0xE3, 0xF0, 0x39, 0x0D, - 0xFE, 0x09, 0x9A, 0x23, 0xF6, 0x32, 0xA6, 0x41, 0x59, 0xBD, - 0x60, 0xE8, 0xBD, 0xDE, 0x00, 0x36, 0x6F, 0x3E, 0xE9, 0x41, - 0x6F, 0xA9, 0x63, 0xC7, 0xAA, 0xD5, 0x7B, 0xF3, 0xE4, 0x39, - 0x48, 0x9E, 0xF6, 0x60, 0xC6, 0xC6, 0x86, 0xD5, 0x72, 0x86, - 0x23, 0xCD, 0xF5, 0x6A, 0x63, 0x53, 0xA4, 0xF8, 0xFC, 0x51, - 0x6A, 0xCD, 0x60, 0x74, 0x8E, 0xA3, 0x86, 0x61, 0x01, 0x34, - 0x78, 0xF7, 0x29, 0x97, 0xB3, 0xA7, 0x34, 0xB6, 0x0A, 0xDE, - 0xB5, 0x71, 0x7A, 0x09, 0xA6, 0x3E, 0xD6, 0x82, 0x58, 0x89, - 0x67, 0x9C, 0xC5, 0x68, 0x62, 0xBA, 0x06, 0xD6, 0x39, 0xBB, - 0xCB, 0x3A, 0xC0, 0xE0, 0x63, 0x1F, 0xC7, 0x0C, 0x9C, 0x12, - 0x86, 0xEC, 0xF7, 0x39, 0x6A, 0x61, 0x93, 0xD0, 0x33, 0x14, - 0xC6, 0x55, 0x3B, 0xB6, 0xCF, 0x80, 0x5B, 0x8C, 0x43, 0xEF, - 0x43, 0x44, 0x0B, 0x3C, 0x93, 0x39, 0xA3, 0x4E, 0x15, 0xD1, - 0x0B, 0x5F, 0x84, 0x98, 0x1D, 0xCD, 0x9F, 0xA9, 0x47, 0xEB, - 0x3B, 0x56, 0x30, 0xB6, 0x76, 0x92, 0xC1, 0x48, 0x5F, 0xBC, - 0x95, 0xB0, 0x50, 0x1A, 0x55, 0xC8, 0x4E, 0x62, 0x47, 0x87, - 0x54, 0x64, 0x0C, 0x9B, 0x91, 0xFA, 0x43, 0xB3, 0x29, 0x48, - 0xBE, 0xE6, 0x12, 0xEB, 0xE3, 0x44, 0xC6, 0x52, 0xE4, 0x40, - 0xC6, 0x83, 0x95, 0x1B, 0xA7, 0x65, 0x27, 0x69, 0x73, 0x2F, - 0xC8, 0xA0, 0x4D, 0x7F, 0xBE, 0xEA, 0x9B, 0x67, 0xB2, 0x7B + 0x30, 0x82, 0x04, 0xCA, 0x30, 0x82, 0x03, 0xB2, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xAA, 0xC4, 0xBF, 0x4C, + 0x50, 0xBD, 0x55, 0x77, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x9E, 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, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, + 0x32, 0x30, 0x34, 0x38, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, + 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x32, 0x30, 0x34, + 0x38, 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, 0x38, 0x30, 0x34, 0x31, 0x33, + 0x31, 0x35, 0x32, 0x33, 0x30, 0x39, 0x5A, 0x17, 0x0D, 0x32, + 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x30, + 0x39, 0x5A, 0x30, 0x81, 0x9E, 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, 0x15, 0x30, 0x13, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, + 0x53, 0x4C, 0x5F, 0x32, 0x30, 0x34, 0x38, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, + 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, + 0x32, 0x30, 0x34, 0x38, 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, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, + 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xC3, 0x03, 0xD1, 0x2B, + 0xFE, 0x39, 0xA4, 0x32, 0x45, 0x3B, 0x53, 0xC8, 0x84, 0x2B, + 0x2A, 0x7C, 0x74, 0x9A, 0xBD, 0xAA, 0x2A, 0x52, 0x07, 0x47, + 0xD6, 0xA6, 0x36, 0xB2, 0x07, 0x32, 0x8E, 0xD0, 0xBA, 0x69, + 0x7B, 0xC6, 0xC3, 0x44, 0x9E, 0xD4, 0x81, 0x48, 0xFD, 0x2D, + 0x68, 0xA2, 0x8B, 0x67, 0xBB, 0xA1, 0x75, 0xC8, 0x36, 0x2C, + 0x4A, 0xD2, 0x1B, 0xF7, 0x8B, 0xBA, 0xCF, 0x0D, 0xF9, 0xEF, + 0xEC, 0xF1, 0x81, 0x1E, 0x7B, 0x9B, 0x03, 0x47, 0x9A, 0xBF, + 0x65, 0xCC, 0x7F, 0x65, 0x24, 0x69, 0xA6, 0xE8, 0x14, 0x89, + 0x5B, 0xE4, 0x34, 0xF7, 0xC5, 0xB0, 0x14, 0x93, 0xF5, 0x67, + 0x7B, 0x3A, 0x7A, 0x78, 0xE1, 0x01, 0x56, 0x56, 0x91, 0xA6, + 0x13, 0x42, 0x8D, 0xD2, 0x3C, 0x40, 0x9C, 0x4C, 0xEF, 0xD1, + 0x86, 0xDF, 0x37, 0x51, 0x1B, 0x0C, 0xA1, 0x3B, 0xF5, 0xF1, + 0xA3, 0x4A, 0x35, 0xE4, 0xE1, 0xCE, 0x96, 0xDF, 0x1B, 0x7E, + 0xBF, 0x4E, 0x97, 0xD0, 0x10, 0xE8, 0xA8, 0x08, 0x30, 0x81, + 0xAF, 0x20, 0x0B, 0x43, 0x14, 0xC5, 0x74, 0x67, 0xB4, 0x32, + 0x82, 0x6F, 0x8D, 0x86, 0xC2, 0x88, 0x40, 0x99, 0x36, 0x83, + 0xBA, 0x1E, 0x40, 0x72, 0x22, 0x17, 0xD7, 0x52, 0x65, 0x24, + 0x73, 0xB0, 0xCE, 0xEF, 0x19, 0xCD, 0xAE, 0xFF, 0x78, 0x6C, + 0x7B, 0xC0, 0x12, 0x03, 0xD4, 0x4E, 0x72, 0x0D, 0x50, 0x6D, + 0x3B, 0xA3, 0x3B, 0xA3, 0x99, 0x5E, 0x9D, 0xC8, 0xD9, 0x0C, + 0x85, 0xB3, 0xD9, 0x8A, 0xD9, 0x54, 0x26, 0xDB, 0x6D, 0xFA, + 0xAC, 0xBB, 0xFF, 0x25, 0x4C, 0xC4, 0xD1, 0x79, 0xF4, 0x71, + 0xD3, 0x86, 0x40, 0x18, 0x13, 0xB0, 0x63, 0xB5, 0x72, 0x4E, + 0x30, 0xC4, 0x97, 0x84, 0x86, 0x2D, 0x56, 0x2F, 0xD7, 0x15, + 0xF7, 0x7F, 0xC0, 0xAE, 0xF5, 0xFC, 0x5B, 0xE5, 0xFB, 0xA1, + 0xBA, 0xD3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, + 0x07, 0x30, 0x82, 0x01, 0x03, 0x30, 0x1D, 0x06, 0x03, 0x55, + 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x33, 0xD8, 0x45, 0x66, + 0xD7, 0x68, 0x87, 0x18, 0x7E, 0x54, 0x0D, 0x70, 0x27, 0x91, + 0xC7, 0x26, 0xD7, 0x85, 0x65, 0xC0, 0x30, 0x81, 0xD3, 0x06, + 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0xCB, 0x30, 0x81, 0xC8, + 0x80, 0x14, 0x33, 0xD8, 0x45, 0x66, 0xD7, 0x68, 0x87, 0x18, + 0x7E, 0x54, 0x0D, 0x70, 0x27, 0x91, 0xC7, 0x26, 0xD7, 0x85, + 0x65, 0xC0, 0xA1, 0x81, 0xA4, 0xA4, 0x81, 0xA1, 0x30, 0x81, + 0x9E, 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, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, 0x32, + 0x30, 0x34, 0x38, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, + 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x32, 0x30, 0x34, 0x38, + 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, 0xAA, 0xC4, 0xBF, 0x4C, 0x50, 0xBD, 0x55, 0x77, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x01, 0x00, 0x80, 0x52, 0x54, 0x61, 0x2A, 0x77, + 0x80, 0x53, 0x44, 0xA9, 0x80, 0x6D, 0x45, 0xFF, 0x0D, 0x25, + 0x7D, 0x1A, 0x8F, 0x23, 0x93, 0x53, 0x74, 0x35, 0x12, 0x6F, + 0xF0, 0x2E, 0x20, 0xEA, 0xED, 0x80, 0x63, 0x69, 0x88, 0xE6, + 0x0C, 0xA1, 0x49, 0x30, 0xE0, 0x82, 0xDB, 0x68, 0x0F, 0x7E, + 0x84, 0xAC, 0xFF, 0xFF, 0x7B, 0x42, 0xFA, 0x7E, 0x2F, 0xB2, + 0x52, 0x9F, 0xD2, 0x79, 0x5E, 0x35, 0x12, 0x27, 0x36, 0xBC, + 0xDF, 0x96, 0x58, 0x44, 0x96, 0x55, 0xC8, 0x4A, 0x94, 0x02, + 0x5F, 0x4A, 0x9D, 0xDC, 0xD3, 0x3A, 0xF7, 0x6D, 0xAC, 0x8B, + 0x79, 0x6E, 0xFC, 0xBE, 0x8F, 0x23, 0x58, 0x6A, 0x8A, 0xF5, + 0x38, 0x0A, 0x42, 0xF6, 0x98, 0x74, 0x88, 0x53, 0x2E, 0x02, + 0xAF, 0xE1, 0x0E, 0xBE, 0x6F, 0xCC, 0x74, 0x33, 0x7C, 0xEC, + 0xB4, 0xCB, 0xA7, 0x49, 0x6D, 0x82, 0x42, 0x4F, 0xEB, 0x73, + 0x29, 0xC3, 0x32, 0x00, 0x2B, 0x15, 0xF8, 0x88, 0x7A, 0x8F, + 0x6D, 0x20, 0x1B, 0xAE, 0x65, 0x5F, 0xC5, 0xD0, 0x8A, 0xD1, + 0xE2, 0x64, 0x6D, 0xA3, 0xA8, 0xFE, 0x64, 0xE1, 0xA9, 0x5B, + 0xE6, 0xD0, 0x23, 0xD6, 0x02, 0x72, 0x5A, 0xEC, 0x03, 0x8E, + 0x87, 0x67, 0x19, 0x8D, 0xE4, 0xA8, 0x99, 0x15, 0xC1, 0x3D, + 0x91, 0x48, 0x99, 0x8D, 0xFE, 0xAE, 0x1C, 0xBF, 0xF6, 0x28, + 0x1B, 0x45, 0xBE, 0xAD, 0xEF, 0x72, 0x83, 0x9A, 0xF6, 0xC7, + 0x3B, 0x51, 0xA3, 0x6E, 0x7A, 0x73, 0xBD, 0x83, 0xAA, 0x97, + 0xFD, 0x63, 0xB4, 0xF4, 0x6B, 0x1C, 0x14, 0x81, 0x9A, 0xEF, + 0x14, 0x24, 0xD3, 0xE1, 0x8B, 0xF4, 0x04, 0x04, 0x84, 0x54, + 0x0F, 0x61, 0xA2, 0xA8, 0xF2, 0x50, 0x37, 0x0C, 0x17, 0x0C, + 0xBC, 0xE0, 0xC2, 0x84, 0x85, 0xF4, 0x0B, 0xAE, 0x00, 0xCA, + 0x9F, 0x27, 0xE2, 0x44, 0x4F, 0x15, 0x0B, 0x8B, 0x1D, 0xB4 }; static const int sizeof_client_cert_der_2048 = sizeof(client_cert_der_2048); @@ -574,630 +973,2919 @@ static const int sizeof_client_cert_der_2048 = sizeof(client_cert_der_2048); /* ./certs/dh2048.der, 2048-bit */ static const unsigned char dh_key_der_2048[] = { - 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB0, - 0xA1, 0x08, 0x06, 0x9C, 0x08, 0x13, 0xBA, 0x59, 0x06, 0x3C, - 0xBC, 0x30, 0xD5, 0xF5, 0x00, 0xC1, 0x4F, 0x44, 0xA7, 0xD6, - 0xEF, 0x4A, 0xC6, 0x25, 0x27, 0x1C, 0xE8, 0xD2, 0x96, 0x53, - 0x0A, 0x5C, 0x91, 0xDD, 0xA2, 0xC2, 0x94, 0x84, 0xBF, 0x7D, - 0xB2, 0x44, 0x9F, 0x9B, 0xD2, 0xC1, 0x8A, 0xC5, 0xBE, 0x72, - 0x5C, 0xA7, 0xE7, 0x91, 0xE6, 0xD4, 0x9F, 0x73, 0x07, 0x85, - 0x5B, 0x66, 0x48, 0xC7, 0x70, 0xFA, 0xB4, 0xEE, 0x02, 0xC9, - 0x3D, 0x9A, 0x4A, 0xDA, 0x3D, 0xC1, 0x46, 0x3E, 0x19, 0x69, - 0xD1, 0x17, 0x46, 0x07, 0xA3, 0x4D, 0x9F, 0x2B, 0x96, 0x17, - 0x39, 0x6D, 0x30, 0x8D, 0x2A, 0xF3, 0x94, 0xD3, 0x75, 0xCF, - 0xA0, 0x75, 0xE6, 0xF2, 0x92, 0x1F, 0x1A, 0x70, 0x05, 0xAA, - 0x04, 0x83, 0x57, 0x30, 0xFB, 0xDA, 0x76, 0x93, 0x38, 0x50, - 0xE8, 0x27, 0xFD, 0x63, 0xEE, 0x3C, 0xE5, 0xB7, 0xC8, 0x09, - 0xAE, 0x6F, 0x50, 0x35, 0x8E, 0x84, 0xCE, 0x4A, 0x00, 0xE9, - 0x12, 0x7E, 0x5A, 0x31, 0xD7, 0x33, 0xFC, 0x21, 0x13, 0x76, - 0xCC, 0x16, 0x30, 0xDB, 0x0C, 0xFC, 0xC5, 0x62, 0xA7, 0x35, - 0xB8, 0xEF, 0xB7, 0xB0, 0xAC, 0xC0, 0x36, 0xF6, 0xD9, 0xC9, - 0x46, 0x48, 0xF9, 0x40, 0x90, 0x00, 0x2B, 0x1B, 0xAA, 0x6C, - 0xE3, 0x1A, 0xC3, 0x0B, 0x03, 0x9E, 0x1B, 0xC2, 0x46, 0xE4, - 0x48, 0x4E, 0x22, 0x73, 0x6F, 0xC3, 0x5F, 0xD4, 0x9A, 0xD6, - 0x30, 0x07, 0x48, 0xD6, 0x8C, 0x90, 0xAB, 0xD4, 0xF6, 0xF1, - 0xE3, 0x48, 0xD3, 0x58, 0x4B, 0xA6, 0xB9, 0xCD, 0x29, 0xBF, - 0x68, 0x1F, 0x08, 0x4B, 0x63, 0x86, 0x2F, 0x5C, 0x6B, 0xD6, - 0xB6, 0x06, 0x65, 0xF7, 0xA6, 0xDC, 0x00, 0x67, 0x6B, 0xBB, - 0xC3, 0xA9, 0x41, 0x83, 0xFB, 0xC7, 0xFA, 0xC8, 0xE2, 0x1E, - 0x7E, 0xAF, 0x00, 0x3F, 0x93, 0x02, 0x01, 0x02 + 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB0, + 0xA1, 0x08, 0x06, 0x9C, 0x08, 0x13, 0xBA, 0x59, 0x06, 0x3C, + 0xBC, 0x30, 0xD5, 0xF5, 0x00, 0xC1, 0x4F, 0x44, 0xA7, 0xD6, + 0xEF, 0x4A, 0xC6, 0x25, 0x27, 0x1C, 0xE8, 0xD2, 0x96, 0x53, + 0x0A, 0x5C, 0x91, 0xDD, 0xA2, 0xC2, 0x94, 0x84, 0xBF, 0x7D, + 0xB2, 0x44, 0x9F, 0x9B, 0xD2, 0xC1, 0x8A, 0xC5, 0xBE, 0x72, + 0x5C, 0xA7, 0xE7, 0x91, 0xE6, 0xD4, 0x9F, 0x73, 0x07, 0x85, + 0x5B, 0x66, 0x48, 0xC7, 0x70, 0xFA, 0xB4, 0xEE, 0x02, 0xC9, + 0x3D, 0x9A, 0x4A, 0xDA, 0x3D, 0xC1, 0x46, 0x3E, 0x19, 0x69, + 0xD1, 0x17, 0x46, 0x07, 0xA3, 0x4D, 0x9F, 0x2B, 0x96, 0x17, + 0x39, 0x6D, 0x30, 0x8D, 0x2A, 0xF3, 0x94, 0xD3, 0x75, 0xCF, + 0xA0, 0x75, 0xE6, 0xF2, 0x92, 0x1F, 0x1A, 0x70, 0x05, 0xAA, + 0x04, 0x83, 0x57, 0x30, 0xFB, 0xDA, 0x76, 0x93, 0x38, 0x50, + 0xE8, 0x27, 0xFD, 0x63, 0xEE, 0x3C, 0xE5, 0xB7, 0xC8, 0x09, + 0xAE, 0x6F, 0x50, 0x35, 0x8E, 0x84, 0xCE, 0x4A, 0x00, 0xE9, + 0x12, 0x7E, 0x5A, 0x31, 0xD7, 0x33, 0xFC, 0x21, 0x13, 0x76, + 0xCC, 0x16, 0x30, 0xDB, 0x0C, 0xFC, 0xC5, 0x62, 0xA7, 0x35, + 0xB8, 0xEF, 0xB7, 0xB0, 0xAC, 0xC0, 0x36, 0xF6, 0xD9, 0xC9, + 0x46, 0x48, 0xF9, 0x40, 0x90, 0x00, 0x2B, 0x1B, 0xAA, 0x6C, + 0xE3, 0x1A, 0xC3, 0x0B, 0x03, 0x9E, 0x1B, 0xC2, 0x46, 0xE4, + 0x48, 0x4E, 0x22, 0x73, 0x6F, 0xC3, 0x5F, 0xD4, 0x9A, 0xD6, + 0x30, 0x07, 0x48, 0xD6, 0x8C, 0x90, 0xAB, 0xD4, 0xF6, 0xF1, + 0xE3, 0x48, 0xD3, 0x58, 0x4B, 0xA6, 0xB9, 0xCD, 0x29, 0xBF, + 0x68, 0x1F, 0x08, 0x4B, 0x63, 0x86, 0x2F, 0x5C, 0x6B, 0xD6, + 0xB6, 0x06, 0x65, 0xF7, 0xA6, 0xDC, 0x00, 0x67, 0x6B, 0xBB, + 0xC3, 0xA9, 0x41, 0x83, 0xFB, 0xC7, 0xFA, 0xC8, 0xE2, 0x1E, + 0x7E, 0xAF, 0x00, 0x3F, 0x93, 0x02, 0x01, 0x02 }; static const int sizeof_dh_key_der_2048 = sizeof(dh_key_der_2048); /* ./certs/dsa2048.der, 2048-bit */ static const unsigned char dsa_key_der_2048[] = { - 0x30, 0x82, 0x03, 0x3F, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, - 0x01, 0x00, 0xCC, 0x8E, 0xC9, 0xA0, 0xD5, 0x9A, 0x27, 0x1C, - 0xDA, 0x52, 0xDF, 0xC7, 0xC0, 0xE6, 0x06, 0xA4, 0x3E, 0x8A, - 0x66, 0x49, 0xD0, 0x59, 0x33, 0x51, 0x69, 0xC4, 0x9C, 0x5E, - 0x64, 0x85, 0xC7, 0xF1, 0xAB, 0xD5, 0xD9, 0x62, 0xAC, 0xFD, - 0xA1, 0xE0, 0x1B, 0x57, 0xFF, 0x96, 0xEF, 0x0C, 0x9F, 0xC8, - 0x44, 0x87, 0xEB, 0x5C, 0x91, 0xD0, 0x46, 0x42, 0x09, 0x50, - 0x6A, 0x23, 0xCB, 0x89, 0x6F, 0x55, 0xE9, 0x6A, 0x11, 0xA9, - 0xA8, 0x32, 0xAB, 0x33, 0x0D, 0x51, 0xB5, 0x79, 0x51, 0xB4, - 0xAB, 0xA2, 0x25, 0x11, 0x8D, 0xE5, 0x24, 0xBE, 0xD8, 0xF1, - 0x9D, 0x4E, 0x12, 0x6F, 0xAC, 0x44, 0x54, 0x80, 0xA9, 0xB4, - 0x81, 0x68, 0x4E, 0x44, 0x0E, 0xB8, 0x39, 0xF3, 0xBE, 0x83, - 0x08, 0x74, 0xA2, 0xC6, 0x7A, 0xD7, 0x6A, 0x7D, 0x0A, 0x88, - 0x57, 0x83, 0x48, 0xDC, 0xCF, 0x5E, 0x6F, 0xEE, 0x68, 0x0C, - 0xF7, 0xFF, 0x03, 0x04, 0x90, 0xAA, 0xF7, 0x07, 0x98, 0xF8, - 0x67, 0x5A, 0x83, 0x23, 0x66, 0x47, 0x60, 0xC3, 0x43, 0x6E, - 0x03, 0x91, 0xAC, 0x28, 0x66, 0xCB, 0xF0, 0xD3, 0x05, 0xC8, - 0x09, 0x97, 0xB5, 0xAE, 0x01, 0x5E, 0x80, 0x3B, 0x9D, 0x4F, - 0xDE, 0x3E, 0x94, 0xFE, 0xCB, 0x82, 0xB0, 0xB1, 0xFC, 0x91, - 0x8B, 0x1D, 0x8A, 0xEE, 0xC6, 0x06, 0x1F, 0x37, 0x91, 0x48, - 0xD2, 0xF8, 0x6C, 0x5D, 0x60, 0x13, 0x83, 0xA7, 0x81, 0xAC, - 0xCA, 0x8D, 0xD0, 0x6A, 0x04, 0x0A, 0xEA, 0x3E, 0x22, 0x4E, - 0x13, 0xF1, 0x0D, 0xBB, 0x60, 0x6B, 0xCD, 0xBC, 0x5C, 0x87, - 0xA3, 0x67, 0x2B, 0x42, 0xA1, 0x9F, 0xCD, 0x39, 0x58, 0xBE, - 0x55, 0xB1, 0x93, 0x84, 0xCE, 0xB2, 0x10, 0x4E, 0xE4, 0xC3, - 0x9F, 0xB2, 0x53, 0x61, 0x01, 0x29, 0xAA, 0x96, 0xCB, 0x20, - 0x60, 0x42, 0x1D, 0xBA, 0x75, 0x4B, 0x63, 0xC1, 0x02, 0x15, - 0x00, 0xE7, 0xA5, 0x39, 0xD4, 0x6A, 0x37, 0x5E, 0x95, 0x06, - 0x39, 0x07, 0x77, 0x0A, 0xEB, 0xA0, 0x03, 0xEB, 0x78, 0x82, - 0x9B, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9A, 0xD4, 0x4C, 0x71, - 0x2F, 0xEC, 0xFA, 0x32, 0xB2, 0x80, 0x7E, 0x61, 0x4A, 0x6B, - 0x5F, 0x18, 0x76, 0x43, 0xC3, 0x69, 0xBA, 0x41, 0xC7, 0xA7, - 0x1D, 0x79, 0x01, 0xEC, 0xAF, 0x34, 0x87, 0x67, 0x4F, 0x29, - 0x80, 0xA8, 0x3B, 0x87, 0xF6, 0xE8, 0xA1, 0xE8, 0xCD, 0x1B, - 0x1C, 0x86, 0x38, 0xF6, 0xD1, 0x0C, 0x46, 0x2E, 0xC8, 0xE0, - 0xC9, 0x30, 0x26, 0xD5, 0x2C, 0x7F, 0xC1, 0x08, 0xBF, 0xCC, - 0x5A, 0x82, 0x8E, 0xD4, 0xD4, 0x49, 0xAA, 0xA2, 0xFA, 0xE6, - 0xC1, 0x9D, 0xF0, 0xD9, 0x96, 0xB0, 0xFF, 0x0C, 0x5B, 0x33, - 0x8E, 0x06, 0xDD, 0x9D, 0x28, 0xA9, 0xE9, 0x80, 0x41, 0x3B, - 0xD8, 0x7A, 0x94, 0x21, 0x8F, 0x56, 0xF1, 0xA2, 0xB4, 0x2B, - 0x89, 0x1C, 0x74, 0xFF, 0x7E, 0x91, 0xDC, 0x1F, 0x91, 0x13, - 0x98, 0xAF, 0xC7, 0x06, 0xD2, 0x4C, 0x90, 0xA2, 0xBD, 0xDA, - 0x16, 0xBA, 0x65, 0xB0, 0x2D, 0x68, 0x87, 0x3C, 0x6E, 0x25, - 0x8D, 0x90, 0xC7, 0xBC, 0x0D, 0xA9, 0x43, 0x03, 0xC9, 0xBE, - 0xCF, 0x85, 0x6F, 0xDB, 0x07, 0x7B, 0x8C, 0xF8, 0xB1, 0xC2, - 0x49, 0x10, 0x69, 0x63, 0x56, 0x37, 0xC5, 0x30, 0xD2, 0xFB, - 0x71, 0x9A, 0xE8, 0x82, 0x07, 0x2E, 0x3E, 0x95, 0x50, 0xF3, - 0x73, 0xCF, 0x34, 0x5B, 0xD5, 0xAB, 0x02, 0x15, 0xF2, 0xCC, - 0xD7, 0x52, 0xC5, 0x28, 0xD8, 0x41, 0x19, 0x55, 0x6F, 0xB8, - 0x5F, 0xF1, 0x99, 0xB3, 0xC7, 0xD9, 0xB3, 0x71, 0xF4, 0x2D, - 0xDF, 0x22, 0x59, 0x35, 0x86, 0xDB, 0x39, 0xCA, 0x1B, 0x4D, - 0x35, 0x90, 0x19, 0x6B, 0x31, 0xE3, 0xC8, 0xC6, 0x09, 0xBF, - 0x7C, 0xED, 0x01, 0xB4, 0xB2, 0xF5, 0x6E, 0xDA, 0x63, 0x41, - 0x3C, 0xE6, 0x3A, 0x72, 0x2D, 0x65, 0x48, 0xF6, 0x07, 0xCD, - 0x92, 0x84, 0x8B, 0x1D, 0xA7, 0x31, 0x6B, 0xD6, 0xF0, 0xFB, - 0xD9, 0xF4, 0x02, 0x82, 0x01, 0x00, 0x66, 0x4B, 0xBB, 0xB7, - 0xC9, 0x48, 0x95, 0x0D, 0x5A, 0xA6, 0x2D, 0xA1, 0x7F, 0xDF, - 0x1F, 0x67, 0x6D, 0xED, 0x52, 0x4B, 0x16, 0x6C, 0x17, 0xC6, - 0xAE, 0xF8, 0x6A, 0xC4, 0x57, 0xED, 0x2F, 0xB3, 0xF0, 0x2A, - 0x55, 0xAB, 0xBA, 0xCA, 0xEA, 0x17, 0xE8, 0x35, 0x7C, 0xE5, - 0x31, 0x0D, 0x4A, 0x95, 0xFC, 0x43, 0x6F, 0x97, 0x3C, 0x5C, - 0x67, 0xAC, 0xBE, 0x67, 0x7F, 0xE9, 0x4E, 0xAA, 0x48, 0xB3, - 0x92, 0xA1, 0x76, 0x75, 0xEA, 0x04, 0x34, 0x7F, 0x87, 0x33, - 0x2D, 0x24, 0xB6, 0x29, 0x97, 0xE3, 0x04, 0x77, 0x93, 0x89, - 0x13, 0xDB, 0x1B, 0x93, 0xB8, 0x2C, 0x90, 0x1A, 0x09, 0x3B, - 0x26, 0xD9, 0x59, 0xF3, 0x2A, 0x09, 0x58, 0xDC, 0xAC, 0x25, - 0xB4, 0xA9, 0x45, 0x3B, 0xA2, 0x3A, 0x6C, 0x61, 0x84, 0xBF, - 0x68, 0xD4, 0xEA, 0x9B, 0xC5, 0x29, 0x48, 0x60, 0x15, 0x10, - 0x35, 0x2C, 0x44, 0x1D, 0xB5, 0x9A, 0xEE, 0xAC, 0xC1, 0x68, - 0xE8, 0x47, 0xB7, 0x41, 0x34, 0x39, 0x9A, 0xF8, 0xA5, 0x20, - 0xE9, 0x24, 0xC4, 0x2C, 0x58, 0x3F, 0x4C, 0x41, 0x30, 0x3A, - 0x14, 0x6E, 0x8D, 0xEA, 0xAD, 0xBA, 0x9B, 0x43, 0xD3, 0x98, - 0x2F, 0x83, 0xD8, 0x14, 0x67, 0xE8, 0xF8, 0xD5, 0x4F, 0xAC, - 0xE0, 0x3B, 0xBF, 0xA7, 0x54, 0x16, 0x5E, 0x49, 0x64, 0x26, - 0x54, 0xA4, 0x6B, 0x69, 0x7C, 0xBA, 0x8A, 0x83, 0xD9, 0x2E, - 0x65, 0x0A, 0xA2, 0x27, 0xEF, 0x99, 0x99, 0x08, 0xD7, 0xB5, - 0x9F, 0xA0, 0x01, 0xEF, 0x7E, 0x17, 0xBF, 0x83, 0x6B, 0x2E, - 0xDD, 0xC0, 0x39, 0x38, 0x23, 0x68, 0xB4, 0x76, 0x6B, 0xE5, - 0xCA, 0xF7, 0x7C, 0xEE, 0xC0, 0x52, 0xE2, 0xDD, 0xAD, 0x59, - 0x3A, 0x42, 0x06, 0x45, 0xB0, 0xC7, 0xC1, 0x77, 0x05, 0xB2, - 0x0C, 0x32, 0x40, 0x46, 0xAA, 0xDA, 0x79, 0x77, 0x04, 0x71, - 0xDF, 0x7A, 0x02, 0x15, 0x00, 0x98, 0xEE, 0xB9, 0x51, 0x37, - 0x3E, 0x75, 0x13, 0x13, 0x06, 0x8F, 0x94, 0xD3, 0xE6, 0xE9, - 0x00, 0xCB, 0x62, 0x6D, 0x9A + 0x30, 0x82, 0x03, 0x3F, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xCC, 0x8E, 0xC9, 0xA0, 0xD5, 0x9A, 0x27, 0x1C, + 0xDA, 0x52, 0xDF, 0xC7, 0xC0, 0xE6, 0x06, 0xA4, 0x3E, 0x8A, + 0x66, 0x49, 0xD0, 0x59, 0x33, 0x51, 0x69, 0xC4, 0x9C, 0x5E, + 0x64, 0x85, 0xC7, 0xF1, 0xAB, 0xD5, 0xD9, 0x62, 0xAC, 0xFD, + 0xA1, 0xE0, 0x1B, 0x57, 0xFF, 0x96, 0xEF, 0x0C, 0x9F, 0xC8, + 0x44, 0x87, 0xEB, 0x5C, 0x91, 0xD0, 0x46, 0x42, 0x09, 0x50, + 0x6A, 0x23, 0xCB, 0x89, 0x6F, 0x55, 0xE9, 0x6A, 0x11, 0xA9, + 0xA8, 0x32, 0xAB, 0x33, 0x0D, 0x51, 0xB5, 0x79, 0x51, 0xB4, + 0xAB, 0xA2, 0x25, 0x11, 0x8D, 0xE5, 0x24, 0xBE, 0xD8, 0xF1, + 0x9D, 0x4E, 0x12, 0x6F, 0xAC, 0x44, 0x54, 0x80, 0xA9, 0xB4, + 0x81, 0x68, 0x4E, 0x44, 0x0E, 0xB8, 0x39, 0xF3, 0xBE, 0x83, + 0x08, 0x74, 0xA2, 0xC6, 0x7A, 0xD7, 0x6A, 0x7D, 0x0A, 0x88, + 0x57, 0x83, 0x48, 0xDC, 0xCF, 0x5E, 0x6F, 0xEE, 0x68, 0x0C, + 0xF7, 0xFF, 0x03, 0x04, 0x90, 0xAA, 0xF7, 0x07, 0x98, 0xF8, + 0x67, 0x5A, 0x83, 0x23, 0x66, 0x47, 0x60, 0xC3, 0x43, 0x6E, + 0x03, 0x91, 0xAC, 0x28, 0x66, 0xCB, 0xF0, 0xD3, 0x05, 0xC8, + 0x09, 0x97, 0xB5, 0xAE, 0x01, 0x5E, 0x80, 0x3B, 0x9D, 0x4F, + 0xDE, 0x3E, 0x94, 0xFE, 0xCB, 0x82, 0xB0, 0xB1, 0xFC, 0x91, + 0x8B, 0x1D, 0x8A, 0xEE, 0xC6, 0x06, 0x1F, 0x37, 0x91, 0x48, + 0xD2, 0xF8, 0x6C, 0x5D, 0x60, 0x13, 0x83, 0xA7, 0x81, 0xAC, + 0xCA, 0x8D, 0xD0, 0x6A, 0x04, 0x0A, 0xEA, 0x3E, 0x22, 0x4E, + 0x13, 0xF1, 0x0D, 0xBB, 0x60, 0x6B, 0xCD, 0xBC, 0x5C, 0x87, + 0xA3, 0x67, 0x2B, 0x42, 0xA1, 0x9F, 0xCD, 0x39, 0x58, 0xBE, + 0x55, 0xB1, 0x93, 0x84, 0xCE, 0xB2, 0x10, 0x4E, 0xE4, 0xC3, + 0x9F, 0xB2, 0x53, 0x61, 0x01, 0x29, 0xAA, 0x96, 0xCB, 0x20, + 0x60, 0x42, 0x1D, 0xBA, 0x75, 0x4B, 0x63, 0xC1, 0x02, 0x15, + 0x00, 0xE7, 0xA5, 0x39, 0xD4, 0x6A, 0x37, 0x5E, 0x95, 0x06, + 0x39, 0x07, 0x77, 0x0A, 0xEB, 0xA0, 0x03, 0xEB, 0x78, 0x82, + 0x9B, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9A, 0xD4, 0x4C, 0x71, + 0x2F, 0xEC, 0xFA, 0x32, 0xB2, 0x80, 0x7E, 0x61, 0x4A, 0x6B, + 0x5F, 0x18, 0x76, 0x43, 0xC3, 0x69, 0xBA, 0x41, 0xC7, 0xA7, + 0x1D, 0x79, 0x01, 0xEC, 0xAF, 0x34, 0x87, 0x67, 0x4F, 0x29, + 0x80, 0xA8, 0x3B, 0x87, 0xF6, 0xE8, 0xA1, 0xE8, 0xCD, 0x1B, + 0x1C, 0x86, 0x38, 0xF6, 0xD1, 0x0C, 0x46, 0x2E, 0xC8, 0xE0, + 0xC9, 0x30, 0x26, 0xD5, 0x2C, 0x7F, 0xC1, 0x08, 0xBF, 0xCC, + 0x5A, 0x82, 0x8E, 0xD4, 0xD4, 0x49, 0xAA, 0xA2, 0xFA, 0xE6, + 0xC1, 0x9D, 0xF0, 0xD9, 0x96, 0xB0, 0xFF, 0x0C, 0x5B, 0x33, + 0x8E, 0x06, 0xDD, 0x9D, 0x28, 0xA9, 0xE9, 0x80, 0x41, 0x3B, + 0xD8, 0x7A, 0x94, 0x21, 0x8F, 0x56, 0xF1, 0xA2, 0xB4, 0x2B, + 0x89, 0x1C, 0x74, 0xFF, 0x7E, 0x91, 0xDC, 0x1F, 0x91, 0x13, + 0x98, 0xAF, 0xC7, 0x06, 0xD2, 0x4C, 0x90, 0xA2, 0xBD, 0xDA, + 0x16, 0xBA, 0x65, 0xB0, 0x2D, 0x68, 0x87, 0x3C, 0x6E, 0x25, + 0x8D, 0x90, 0xC7, 0xBC, 0x0D, 0xA9, 0x43, 0x03, 0xC9, 0xBE, + 0xCF, 0x85, 0x6F, 0xDB, 0x07, 0x7B, 0x8C, 0xF8, 0xB1, 0xC2, + 0x49, 0x10, 0x69, 0x63, 0x56, 0x37, 0xC5, 0x30, 0xD2, 0xFB, + 0x71, 0x9A, 0xE8, 0x82, 0x07, 0x2E, 0x3E, 0x95, 0x50, 0xF3, + 0x73, 0xCF, 0x34, 0x5B, 0xD5, 0xAB, 0x02, 0x15, 0xF2, 0xCC, + 0xD7, 0x52, 0xC5, 0x28, 0xD8, 0x41, 0x19, 0x55, 0x6F, 0xB8, + 0x5F, 0xF1, 0x99, 0xB3, 0xC7, 0xD9, 0xB3, 0x71, 0xF4, 0x2D, + 0xDF, 0x22, 0x59, 0x35, 0x86, 0xDB, 0x39, 0xCA, 0x1B, 0x4D, + 0x35, 0x90, 0x19, 0x6B, 0x31, 0xE3, 0xC8, 0xC6, 0x09, 0xBF, + 0x7C, 0xED, 0x01, 0xB4, 0xB2, 0xF5, 0x6E, 0xDA, 0x63, 0x41, + 0x3C, 0xE6, 0x3A, 0x72, 0x2D, 0x65, 0x48, 0xF6, 0x07, 0xCD, + 0x92, 0x84, 0x8B, 0x1D, 0xA7, 0x31, 0x6B, 0xD6, 0xF0, 0xFB, + 0xD9, 0xF4, 0x02, 0x82, 0x01, 0x00, 0x66, 0x4B, 0xBB, 0xB7, + 0xC9, 0x48, 0x95, 0x0D, 0x5A, 0xA6, 0x2D, 0xA1, 0x7F, 0xDF, + 0x1F, 0x67, 0x6D, 0xED, 0x52, 0x4B, 0x16, 0x6C, 0x17, 0xC6, + 0xAE, 0xF8, 0x6A, 0xC4, 0x57, 0xED, 0x2F, 0xB3, 0xF0, 0x2A, + 0x55, 0xAB, 0xBA, 0xCA, 0xEA, 0x17, 0xE8, 0x35, 0x7C, 0xE5, + 0x31, 0x0D, 0x4A, 0x95, 0xFC, 0x43, 0x6F, 0x97, 0x3C, 0x5C, + 0x67, 0xAC, 0xBE, 0x67, 0x7F, 0xE9, 0x4E, 0xAA, 0x48, 0xB3, + 0x92, 0xA1, 0x76, 0x75, 0xEA, 0x04, 0x34, 0x7F, 0x87, 0x33, + 0x2D, 0x24, 0xB6, 0x29, 0x97, 0xE3, 0x04, 0x77, 0x93, 0x89, + 0x13, 0xDB, 0x1B, 0x93, 0xB8, 0x2C, 0x90, 0x1A, 0x09, 0x3B, + 0x26, 0xD9, 0x59, 0xF3, 0x2A, 0x09, 0x58, 0xDC, 0xAC, 0x25, + 0xB4, 0xA9, 0x45, 0x3B, 0xA2, 0x3A, 0x6C, 0x61, 0x84, 0xBF, + 0x68, 0xD4, 0xEA, 0x9B, 0xC5, 0x29, 0x48, 0x60, 0x15, 0x10, + 0x35, 0x2C, 0x44, 0x1D, 0xB5, 0x9A, 0xEE, 0xAC, 0xC1, 0x68, + 0xE8, 0x47, 0xB7, 0x41, 0x34, 0x39, 0x9A, 0xF8, 0xA5, 0x20, + 0xE9, 0x24, 0xC4, 0x2C, 0x58, 0x3F, 0x4C, 0x41, 0x30, 0x3A, + 0x14, 0x6E, 0x8D, 0xEA, 0xAD, 0xBA, 0x9B, 0x43, 0xD3, 0x98, + 0x2F, 0x83, 0xD8, 0x14, 0x67, 0xE8, 0xF8, 0xD5, 0x4F, 0xAC, + 0xE0, 0x3B, 0xBF, 0xA7, 0x54, 0x16, 0x5E, 0x49, 0x64, 0x26, + 0x54, 0xA4, 0x6B, 0x69, 0x7C, 0xBA, 0x8A, 0x83, 0xD9, 0x2E, + 0x65, 0x0A, 0xA2, 0x27, 0xEF, 0x99, 0x99, 0x08, 0xD7, 0xB5, + 0x9F, 0xA0, 0x01, 0xEF, 0x7E, 0x17, 0xBF, 0x83, 0x6B, 0x2E, + 0xDD, 0xC0, 0x39, 0x38, 0x23, 0x68, 0xB4, 0x76, 0x6B, 0xE5, + 0xCA, 0xF7, 0x7C, 0xEE, 0xC0, 0x52, 0xE2, 0xDD, 0xAD, 0x59, + 0x3A, 0x42, 0x06, 0x45, 0xB0, 0xC7, 0xC1, 0x77, 0x05, 0xB2, + 0x0C, 0x32, 0x40, 0x46, 0xAA, 0xDA, 0x79, 0x77, 0x04, 0x71, + 0xDF, 0x7A, 0x02, 0x15, 0x00, 0x98, 0xEE, 0xB9, 0x51, 0x37, + 0x3E, 0x75, 0x13, 0x13, 0x06, 0x8F, 0x94, 0xD3, 0xE6, 0xE9, + 0x00, 0xCB, 0x62, 0x6D, 0x9A }; static const int sizeof_dsa_key_der_2048 = sizeof(dsa_key_der_2048); /* ./certs/rsa2048.der, 2048-bit */ static const unsigned char rsa_key_der_2048[] = { - 0x30, 0x82, 0x04, 0xA3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, - 0x01, 0x00, 0xE9, 0x8A, 0x5D, 0x15, 0xA4, 0xD4, 0x34, 0xB9, - 0x59, 0xA2, 0xDA, 0xAF, 0x74, 0xC8, 0xC9, 0x03, 0x26, 0x38, - 0xFA, 0x48, 0xFC, 0x4D, 0x30, 0x6E, 0xEA, 0x76, 0x89, 0xCE, - 0x4F, 0xF6, 0x87, 0xDE, 0x32, 0x3A, 0x46, 0x6E, 0x38, 0x12, - 0x58, 0x37, 0x22, 0x0D, 0x80, 0xAC, 0x2D, 0xAF, 0x2F, 0x12, - 0x3E, 0x62, 0x73, 0x60, 0x66, 0x68, 0x90, 0xB2, 0x6F, 0x47, - 0x17, 0x04, 0x2B, 0xCA, 0xB7, 0x26, 0xB7, 0x10, 0xC2, 0x13, - 0xF9, 0x7A, 0x62, 0x0A, 0x93, 0x32, 0x90, 0x42, 0x0D, 0x16, - 0x2E, 0xFA, 0xD7, 0x29, 0xD7, 0x9F, 0x54, 0xE4, 0xFC, 0x65, - 0x74, 0xF8, 0xF6, 0x43, 0x6B, 0x4E, 0x9E, 0x34, 0x7F, 0xCB, - 0x6B, 0x1C, 0x1A, 0xDE, 0x82, 0x81, 0xBF, 0x08, 0x5D, 0x3F, - 0xC0, 0xB6, 0xB1, 0xA8, 0xA5, 0x9C, 0x81, 0x70, 0xA7, 0x4E, - 0x32, 0x87, 0x15, 0x1C, 0x78, 0x0E, 0xF0, 0x18, 0xFE, 0xEB, - 0x4B, 0x37, 0x2B, 0xE9, 0xE1, 0xF7, 0xFA, 0x51, 0xC6, 0x58, - 0xB9, 0xD8, 0x06, 0x03, 0xED, 0xC0, 0x03, 0x18, 0x55, 0x8B, - 0x98, 0xFE, 0xB1, 0xF6, 0xD0, 0x3D, 0xFA, 0x63, 0xC0, 0x38, - 0x19, 0xC7, 0x00, 0xEF, 0x4D, 0x99, 0x60, 0xB4, 0xBA, 0xCE, - 0xE3, 0xCE, 0xD9, 0x6B, 0x2D, 0x76, 0x94, 0xFF, 0xFB, 0x77, - 0x18, 0x4A, 0xFE, 0x65, 0xF0, 0x0A, 0x91, 0x5C, 0x3B, 0x22, - 0x94, 0x85, 0xD0, 0x20, 0x18, 0x59, 0x2E, 0xA5, 0x33, 0x03, - 0xAC, 0x1B, 0x5F, 0x78, 0x32, 0x11, 0x25, 0xEE, 0x7F, 0x96, - 0x21, 0xA9, 0xD6, 0x76, 0x97, 0x8D, 0x66, 0x7E, 0xB2, 0x91, - 0xD0, 0x36, 0x2E, 0xA3, 0x1D, 0xBF, 0xF1, 0x85, 0xED, 0xC0, - 0x3E, 0x60, 0xB8, 0x5A, 0x9F, 0xAB, 0x80, 0xE0, 0xEA, 0x5D, - 0x5F, 0x75, 0x56, 0xC7, 0x4D, 0x51, 0x8E, 0xD4, 0x1F, 0x34, - 0xA6, 0x36, 0xF1, 0x30, 0x1F, 0x51, 0x99, 0x2F, 0x02, 0x03, - 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x52, 0x11, 0x33, - 0x40, 0xC5, 0xD9, 0x64, 0x65, 0xB5, 0xE0, 0x0A, 0xA5, 0x19, - 0x8E, 0xED, 0x44, 0x54, 0x0C, 0x35, 0xB7, 0xAC, 0x21, 0x9B, - 0xE1, 0x7E, 0x37, 0x05, 0x9A, 0x20, 0x73, 0x6B, 0xAF, 0x63, - 0x4B, 0x23, 0x30, 0xDC, 0x37, 0x66, 0x14, 0x89, 0xBC, 0xE0, - 0xF8, 0xA0, 0x5D, 0x2D, 0x57, 0x65, 0xE0, 0xC6, 0xD6, 0x9B, - 0x66, 0x27, 0x62, 0xEC, 0xC3, 0xB8, 0x8C, 0xD8, 0xAE, 0xB5, - 0xC9, 0xBF, 0x0E, 0xFE, 0x84, 0x72, 0x68, 0xD5, 0x47, 0x0E, - 0x0E, 0xF8, 0xAE, 0x9D, 0x56, 0xAC, 0x4F, 0xAD, 0x88, 0xA0, - 0xA2, 0xF6, 0xFC, 0x38, 0xCD, 0x96, 0x5B, 0x5E, 0x7E, 0xB6, - 0x98, 0xBB, 0xF3, 0x8A, 0xEC, 0xFA, 0xC8, 0xB7, 0x90, 0x75, - 0xA0, 0x0E, 0x77, 0x6B, 0xFD, 0x59, 0x45, 0x5A, 0x0C, 0xFF, - 0x95, 0x8D, 0xCE, 0xFE, 0x9B, 0xF6, 0x19, 0x8E, 0x0B, 0xA1, - 0x0C, 0xEE, 0xC6, 0x79, 0xDD, 0x9D, 0x61, 0x85, 0x5C, 0x19, - 0x6C, 0x47, 0xCC, 0x08, 0xFF, 0xA5, 0x62, 0xDB, 0xE4, 0x2D, - 0x2D, 0xDD, 0x14, 0x67, 0xD6, 0x4A, 0x64, 0x2A, 0x66, 0x49, - 0x54, 0x9C, 0xE3, 0x85, 0x18, 0xE7, 0x31, 0x42, 0xE2, 0xD0, - 0x2C, 0x20, 0xA0, 0x74, 0x0F, 0x1F, 0x20, 0x89, 0xBA, 0xAB, - 0x80, 0xD8, 0x38, 0xD9, 0x46, 0x69, 0xBB, 0xEF, 0xCC, 0x8B, - 0xA1, 0x73, 0xA7, 0xF2, 0xE4, 0x38, 0x5D, 0xD6, 0x75, 0x9F, - 0x88, 0x0E, 0x56, 0xCD, 0xD8, 0x84, 0x59, 0x29, 0x73, 0xF5, - 0xA1, 0x79, 0xDA, 0x7A, 0x1F, 0xBF, 0x73, 0x83, 0xC0, 0x6D, - 0x9F, 0x8B, 0x34, 0x15, 0xC0, 0x6D, 0x69, 0x6A, 0x20, 0xE6, - 0x51, 0xCF, 0x45, 0x6E, 0xCC, 0x05, 0xC4, 0x3A, 0xC0, 0x9E, - 0xAA, 0xC1, 0x06, 0x2F, 0xAB, 0x99, 0x30, 0xE1, 0x6E, 0x9D, - 0x45, 0x7A, 0xFF, 0xA9, 0xCE, 0x70, 0xB8, 0x16, 0x1A, 0x0E, - 0x20, 0xFA, 0xC1, 0x02, 0x81, 0x81, 0x00, 0xFF, 0x30, 0x11, - 0xC2, 0x3C, 0x6B, 0xB4, 0xD6, 0x9E, 0x6B, 0xC1, 0x93, 0xD1, - 0x48, 0xCE, 0x80, 0x2D, 0xBE, 0xAF, 0xF7, 0xBA, 0xB2, 0xD7, - 0xC3, 0xC4, 0x53, 0x6E, 0x15, 0x02, 0xAA, 0x61, 0xB9, 0xEA, - 0x05, 0x9B, 0x79, 0x67, 0x0B, 0xCE, 0xD9, 0xFB, 0x98, 0x8C, - 0x1D, 0x6B, 0xF4, 0x5A, 0xA7, 0xA0, 0x5E, 0x54, 0x18, 0xE9, - 0x31, 0x44, 0x7C, 0xC7, 0x52, 0xD8, 0x6D, 0xA0, 0x3E, 0xD6, - 0x14, 0x2D, 0x7B, 0x15, 0x9D, 0x1E, 0x39, 0x87, 0x96, 0xDD, - 0xA8, 0x33, 0x55, 0x2A, 0x8E, 0x32, 0xC0, 0xC4, 0xE5, 0xB8, - 0xCB, 0xCD, 0x32, 0x8D, 0xAD, 0x7B, 0xE5, 0xC6, 0x7E, 0x4D, - 0x6F, 0xF3, 0xA4, 0xC5, 0xA6, 0x40, 0xBE, 0x90, 0x3A, 0x33, - 0x6A, 0x24, 0xB2, 0x80, 0x81, 0x12, 0xAC, 0xE3, 0x7B, 0x26, - 0x63, 0xCF, 0x88, 0xB9, 0xFF, 0x74, 0x23, 0x37, 0x52, 0xF0, - 0xC4, 0x27, 0x5D, 0x45, 0x1F, 0x02, 0x81, 0x81, 0x00, 0xEA, - 0x48, 0xA7, 0xDD, 0x73, 0x41, 0x56, 0x21, 0x15, 0xF7, 0x42, - 0x45, 0x4D, 0xA9, 0xE1, 0x66, 0x5B, 0xBD, 0x25, 0x7D, 0xF7, - 0xA8, 0x65, 0x13, 0xAE, 0x2D, 0x38, 0x11, 0xCD, 0x93, 0xFC, - 0x30, 0xA3, 0x2C, 0x44, 0xBB, 0xCF, 0xD0, 0x21, 0x8F, 0xFB, - 0xC1, 0xF9, 0xAD, 0x1D, 0xEE, 0x96, 0xCF, 0x97, 0x49, 0x60, - 0x53, 0x80, 0xA5, 0xA2, 0xF8, 0xEE, 0xB9, 0xD5, 0x77, 0x44, - 0xDD, 0xFD, 0x19, 0x2A, 0xF1, 0x81, 0xF4, 0xD9, 0x3C, 0xEC, - 0x73, 0xD0, 0x2A, 0xD8, 0x3C, 0x27, 0x87, 0x79, 0x12, 0x86, - 0xE7, 0x57, 0x0C, 0x59, 0xD1, 0x44, 0x55, 0xAE, 0xC3, 0x4D, - 0x42, 0xAD, 0xA9, 0xB3, 0x28, 0x61, 0xB4, 0x9C, 0xA6, 0x63, - 0xD3, 0x96, 0xB1, 0x75, 0x9F, 0x2A, 0x78, 0x99, 0xE3, 0x1E, - 0x71, 0x47, 0x39, 0xF4, 0x52, 0xE3, 0x66, 0xF1, 0xEB, 0x7F, - 0xEF, 0xC6, 0x81, 0x93, 0x4C, 0x99, 0xF1, 0x02, 0x81, 0x81, - 0x00, 0xC5, 0xB6, 0x20, 0x8C, 0x34, 0xF3, 0xDD, 0xF0, 0x4A, - 0x5D, 0x82, 0x65, 0x5C, 0x48, 0xE4, 0x75, 0x3A, 0xFB, 0xFA, - 0xAA, 0x1C, 0xE4, 0x63, 0x77, 0x31, 0xAC, 0xD2, 0x25, 0x45, - 0x23, 0x6D, 0x03, 0xF5, 0xE4, 0xD2, 0x48, 0x85, 0x26, 0x08, - 0xE5, 0xAA, 0xA0, 0xCE, 0x2E, 0x1D, 0x6D, 0xFC, 0xAE, 0xD2, - 0xF9, 0x42, 0x7E, 0xEA, 0x6D, 0x59, 0x7A, 0xB3, 0x93, 0xE4, - 0x4B, 0x4B, 0x54, 0x63, 0xD8, 0xCE, 0x44, 0x06, 0xC2, 0xEC, - 0x9F, 0xF6, 0x05, 0x55, 0x46, 0xF4, 0x3E, 0x8F, 0xF2, 0x0C, - 0x30, 0x7E, 0x5C, 0xDD, 0x88, 0x49, 0x3B, 0x59, 0xB9, 0x87, - 0xBC, 0xC6, 0xC5, 0x24, 0x8A, 0x10, 0x63, 0x21, 0x1F, 0x66, - 0x1A, 0x3E, 0xF4, 0x58, 0xD1, 0x6C, 0x0D, 0x40, 0xB2, 0xC0, - 0x1D, 0x63, 0x42, 0x0E, 0xC4, 0x56, 0x0E, 0xC0, 0xCC, 0xC2, - 0xD6, 0x66, 0x0E, 0xC4, 0xAB, 0xB5, 0x33, 0xF6, 0x51, 0x02, - 0x81, 0x80, 0x19, 0x7E, 0xE6, 0xA5, 0xB6, 0xD1, 0x39, 0x6A, - 0x48, 0x55, 0xAC, 0x24, 0x96, 0x9B, 0x12, 0x28, 0x6D, 0x7B, - 0x5C, 0x05, 0x25, 0x5A, 0x72, 0x05, 0x7E, 0x42, 0xF5, 0x83, - 0x1A, 0x78, 0x2C, 0x4D, 0xAE, 0xB4, 0x36, 0x96, 0xA9, 0xBA, - 0xE0, 0xAC, 0x26, 0x9D, 0xA9, 0x6A, 0x29, 0x83, 0xB9, 0x6D, - 0xC5, 0xEC, 0xFA, 0x4A, 0x9C, 0x09, 0x6A, 0x7E, 0xE4, 0x9B, - 0xDC, 0x9B, 0x2A, 0x27, 0x6E, 0x4F, 0xBA, 0xD8, 0xA5, 0x67, - 0xDB, 0xEC, 0x41, 0x5F, 0x29, 0x1C, 0x40, 0x83, 0xEB, 0x59, - 0x56, 0xD7, 0xA9, 0x4E, 0xAB, 0xAE, 0x70, 0x67, 0xD1, 0xA3, - 0xF1, 0x6C, 0xD7, 0x8F, 0x96, 0x0E, 0x8D, 0xAC, 0xAB, 0x55, - 0x58, 0x66, 0xD3, 0x1E, 0x47, 0x9B, 0xF0, 0x4C, 0xED, 0xF6, - 0x49, 0xE8, 0xE9, 0x7B, 0x32, 0x61, 0x20, 0x31, 0x95, 0x05, - 0xB2, 0xF6, 0x09, 0xEA, 0x32, 0x14, 0x0F, 0xCF, 0x9A, 0x41, - 0x02, 0x81, 0x80, 0x77, 0x3F, 0xB6, 0x14, 0x8D, 0xC5, 0x13, - 0x08, 0x7E, 0xC9, 0xC4, 0xEA, 0xD4, 0xBA, 0x0D, 0xA4, 0x9E, - 0xB3, 0x6E, 0xDE, 0x1A, 0x7A, 0xF8, 0x89, 0x88, 0xEF, 0x36, - 0x3C, 0x11, 0xBC, 0x83, 0xE8, 0x30, 0x6C, 0x81, 0x7C, 0x47, - 0xF3, 0x4D, 0xCA, 0xEA, 0x56, 0x01, 0x62, 0x55, 0x2E, 0x4B, - 0x89, 0xA9, 0xBD, 0x6F, 0x01, 0xF6, 0x74, 0x02, 0xAA, 0xE3, - 0x84, 0x66, 0x06, 0x95, 0x34, 0xA1, 0xE2, 0xCA, 0x65, 0xFE, - 0xA3, 0x2D, 0x43, 0x97, 0x95, 0x6C, 0x6F, 0xD5, 0xB4, 0x38, - 0xF6, 0xF9, 0x95, 0x30, 0xFA, 0xF8, 0x9C, 0x25, 0x2B, 0xB6, - 0x14, 0x51, 0xCC, 0x2E, 0xB3, 0x5B, 0xD6, 0xDC, 0x1A, 0xEC, - 0x2D, 0x09, 0x5B, 0x3F, 0x3A, 0xD0, 0xB8, 0x4E, 0x27, 0x1F, - 0xDC, 0x2A, 0xEE, 0xAC, 0xA9, 0x59, 0x5D, 0x07, 0x63, 0x11, - 0x83, 0x0B, 0xD4, 0x74, 0x80, 0xB6, 0x7D, 0x62, 0x45, 0xBF, - 0x56 + 0x30, 0x82, 0x04, 0xA3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xE9, 0x8A, 0x5D, 0x15, 0xA4, 0xD4, 0x34, 0xB9, + 0x59, 0xA2, 0xDA, 0xAF, 0x74, 0xC8, 0xC9, 0x03, 0x26, 0x38, + 0xFA, 0x48, 0xFC, 0x4D, 0x30, 0x6E, 0xEA, 0x76, 0x89, 0xCE, + 0x4F, 0xF6, 0x87, 0xDE, 0x32, 0x3A, 0x46, 0x6E, 0x38, 0x12, + 0x58, 0x37, 0x22, 0x0D, 0x80, 0xAC, 0x2D, 0xAF, 0x2F, 0x12, + 0x3E, 0x62, 0x73, 0x60, 0x66, 0x68, 0x90, 0xB2, 0x6F, 0x47, + 0x17, 0x04, 0x2B, 0xCA, 0xB7, 0x26, 0xB7, 0x10, 0xC2, 0x13, + 0xF9, 0x7A, 0x62, 0x0A, 0x93, 0x32, 0x90, 0x42, 0x0D, 0x16, + 0x2E, 0xFA, 0xD7, 0x29, 0xD7, 0x9F, 0x54, 0xE4, 0xFC, 0x65, + 0x74, 0xF8, 0xF6, 0x43, 0x6B, 0x4E, 0x9E, 0x34, 0x7F, 0xCB, + 0x6B, 0x1C, 0x1A, 0xDE, 0x82, 0x81, 0xBF, 0x08, 0x5D, 0x3F, + 0xC0, 0xB6, 0xB1, 0xA8, 0xA5, 0x9C, 0x81, 0x70, 0xA7, 0x4E, + 0x32, 0x87, 0x15, 0x1C, 0x78, 0x0E, 0xF0, 0x18, 0xFE, 0xEB, + 0x4B, 0x37, 0x2B, 0xE9, 0xE1, 0xF7, 0xFA, 0x51, 0xC6, 0x58, + 0xB9, 0xD8, 0x06, 0x03, 0xED, 0xC0, 0x03, 0x18, 0x55, 0x8B, + 0x98, 0xFE, 0xB1, 0xF6, 0xD0, 0x3D, 0xFA, 0x63, 0xC0, 0x38, + 0x19, 0xC7, 0x00, 0xEF, 0x4D, 0x99, 0x60, 0xB4, 0xBA, 0xCE, + 0xE3, 0xCE, 0xD9, 0x6B, 0x2D, 0x76, 0x94, 0xFF, 0xFB, 0x77, + 0x18, 0x4A, 0xFE, 0x65, 0xF0, 0x0A, 0x91, 0x5C, 0x3B, 0x22, + 0x94, 0x85, 0xD0, 0x20, 0x18, 0x59, 0x2E, 0xA5, 0x33, 0x03, + 0xAC, 0x1B, 0x5F, 0x78, 0x32, 0x11, 0x25, 0xEE, 0x7F, 0x96, + 0x21, 0xA9, 0xD6, 0x76, 0x97, 0x8D, 0x66, 0x7E, 0xB2, 0x91, + 0xD0, 0x36, 0x2E, 0xA3, 0x1D, 0xBF, 0xF1, 0x85, 0xED, 0xC0, + 0x3E, 0x60, 0xB8, 0x5A, 0x9F, 0xAB, 0x80, 0xE0, 0xEA, 0x5D, + 0x5F, 0x75, 0x56, 0xC7, 0x4D, 0x51, 0x8E, 0xD4, 0x1F, 0x34, + 0xA6, 0x36, 0xF1, 0x30, 0x1F, 0x51, 0x99, 0x2F, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x52, 0x11, 0x33, + 0x40, 0xC5, 0xD9, 0x64, 0x65, 0xB5, 0xE0, 0x0A, 0xA5, 0x19, + 0x8E, 0xED, 0x44, 0x54, 0x0C, 0x35, 0xB7, 0xAC, 0x21, 0x9B, + 0xE1, 0x7E, 0x37, 0x05, 0x9A, 0x20, 0x73, 0x6B, 0xAF, 0x63, + 0x4B, 0x23, 0x30, 0xDC, 0x37, 0x66, 0x14, 0x89, 0xBC, 0xE0, + 0xF8, 0xA0, 0x5D, 0x2D, 0x57, 0x65, 0xE0, 0xC6, 0xD6, 0x9B, + 0x66, 0x27, 0x62, 0xEC, 0xC3, 0xB8, 0x8C, 0xD8, 0xAE, 0xB5, + 0xC9, 0xBF, 0x0E, 0xFE, 0x84, 0x72, 0x68, 0xD5, 0x47, 0x0E, + 0x0E, 0xF8, 0xAE, 0x9D, 0x56, 0xAC, 0x4F, 0xAD, 0x88, 0xA0, + 0xA2, 0xF6, 0xFC, 0x38, 0xCD, 0x96, 0x5B, 0x5E, 0x7E, 0xB6, + 0x98, 0xBB, 0xF3, 0x8A, 0xEC, 0xFA, 0xC8, 0xB7, 0x90, 0x75, + 0xA0, 0x0E, 0x77, 0x6B, 0xFD, 0x59, 0x45, 0x5A, 0x0C, 0xFF, + 0x95, 0x8D, 0xCE, 0xFE, 0x9B, 0xF6, 0x19, 0x8E, 0x0B, 0xA1, + 0x0C, 0xEE, 0xC6, 0x79, 0xDD, 0x9D, 0x61, 0x85, 0x5C, 0x19, + 0x6C, 0x47, 0xCC, 0x08, 0xFF, 0xA5, 0x62, 0xDB, 0xE4, 0x2D, + 0x2D, 0xDD, 0x14, 0x67, 0xD6, 0x4A, 0x64, 0x2A, 0x66, 0x49, + 0x54, 0x9C, 0xE3, 0x85, 0x18, 0xE7, 0x31, 0x42, 0xE2, 0xD0, + 0x2C, 0x20, 0xA0, 0x74, 0x0F, 0x1F, 0x20, 0x89, 0xBA, 0xAB, + 0x80, 0xD8, 0x38, 0xD9, 0x46, 0x69, 0xBB, 0xEF, 0xCC, 0x8B, + 0xA1, 0x73, 0xA7, 0xF2, 0xE4, 0x38, 0x5D, 0xD6, 0x75, 0x9F, + 0x88, 0x0E, 0x56, 0xCD, 0xD8, 0x84, 0x59, 0x29, 0x73, 0xF5, + 0xA1, 0x79, 0xDA, 0x7A, 0x1F, 0xBF, 0x73, 0x83, 0xC0, 0x6D, + 0x9F, 0x8B, 0x34, 0x15, 0xC0, 0x6D, 0x69, 0x6A, 0x20, 0xE6, + 0x51, 0xCF, 0x45, 0x6E, 0xCC, 0x05, 0xC4, 0x3A, 0xC0, 0x9E, + 0xAA, 0xC1, 0x06, 0x2F, 0xAB, 0x99, 0x30, 0xE1, 0x6E, 0x9D, + 0x45, 0x7A, 0xFF, 0xA9, 0xCE, 0x70, 0xB8, 0x16, 0x1A, 0x0E, + 0x20, 0xFA, 0xC1, 0x02, 0x81, 0x81, 0x00, 0xFF, 0x30, 0x11, + 0xC2, 0x3C, 0x6B, 0xB4, 0xD6, 0x9E, 0x6B, 0xC1, 0x93, 0xD1, + 0x48, 0xCE, 0x80, 0x2D, 0xBE, 0xAF, 0xF7, 0xBA, 0xB2, 0xD7, + 0xC3, 0xC4, 0x53, 0x6E, 0x15, 0x02, 0xAA, 0x61, 0xB9, 0xEA, + 0x05, 0x9B, 0x79, 0x67, 0x0B, 0xCE, 0xD9, 0xFB, 0x98, 0x8C, + 0x1D, 0x6B, 0xF4, 0x5A, 0xA7, 0xA0, 0x5E, 0x54, 0x18, 0xE9, + 0x31, 0x44, 0x7C, 0xC7, 0x52, 0xD8, 0x6D, 0xA0, 0x3E, 0xD6, + 0x14, 0x2D, 0x7B, 0x15, 0x9D, 0x1E, 0x39, 0x87, 0x96, 0xDD, + 0xA8, 0x33, 0x55, 0x2A, 0x8E, 0x32, 0xC0, 0xC4, 0xE5, 0xB8, + 0xCB, 0xCD, 0x32, 0x8D, 0xAD, 0x7B, 0xE5, 0xC6, 0x7E, 0x4D, + 0x6F, 0xF3, 0xA4, 0xC5, 0xA6, 0x40, 0xBE, 0x90, 0x3A, 0x33, + 0x6A, 0x24, 0xB2, 0x80, 0x81, 0x12, 0xAC, 0xE3, 0x7B, 0x26, + 0x63, 0xCF, 0x88, 0xB9, 0xFF, 0x74, 0x23, 0x37, 0x52, 0xF0, + 0xC4, 0x27, 0x5D, 0x45, 0x1F, 0x02, 0x81, 0x81, 0x00, 0xEA, + 0x48, 0xA7, 0xDD, 0x73, 0x41, 0x56, 0x21, 0x15, 0xF7, 0x42, + 0x45, 0x4D, 0xA9, 0xE1, 0x66, 0x5B, 0xBD, 0x25, 0x7D, 0xF7, + 0xA8, 0x65, 0x13, 0xAE, 0x2D, 0x38, 0x11, 0xCD, 0x93, 0xFC, + 0x30, 0xA3, 0x2C, 0x44, 0xBB, 0xCF, 0xD0, 0x21, 0x8F, 0xFB, + 0xC1, 0xF9, 0xAD, 0x1D, 0xEE, 0x96, 0xCF, 0x97, 0x49, 0x60, + 0x53, 0x80, 0xA5, 0xA2, 0xF8, 0xEE, 0xB9, 0xD5, 0x77, 0x44, + 0xDD, 0xFD, 0x19, 0x2A, 0xF1, 0x81, 0xF4, 0xD9, 0x3C, 0xEC, + 0x73, 0xD0, 0x2A, 0xD8, 0x3C, 0x27, 0x87, 0x79, 0x12, 0x86, + 0xE7, 0x57, 0x0C, 0x59, 0xD1, 0x44, 0x55, 0xAE, 0xC3, 0x4D, + 0x42, 0xAD, 0xA9, 0xB3, 0x28, 0x61, 0xB4, 0x9C, 0xA6, 0x63, + 0xD3, 0x96, 0xB1, 0x75, 0x9F, 0x2A, 0x78, 0x99, 0xE3, 0x1E, + 0x71, 0x47, 0x39, 0xF4, 0x52, 0xE3, 0x66, 0xF1, 0xEB, 0x7F, + 0xEF, 0xC6, 0x81, 0x93, 0x4C, 0x99, 0xF1, 0x02, 0x81, 0x81, + 0x00, 0xC5, 0xB6, 0x20, 0x8C, 0x34, 0xF3, 0xDD, 0xF0, 0x4A, + 0x5D, 0x82, 0x65, 0x5C, 0x48, 0xE4, 0x75, 0x3A, 0xFB, 0xFA, + 0xAA, 0x1C, 0xE4, 0x63, 0x77, 0x31, 0xAC, 0xD2, 0x25, 0x45, + 0x23, 0x6D, 0x03, 0xF5, 0xE4, 0xD2, 0x48, 0x85, 0x26, 0x08, + 0xE5, 0xAA, 0xA0, 0xCE, 0x2E, 0x1D, 0x6D, 0xFC, 0xAE, 0xD2, + 0xF9, 0x42, 0x7E, 0xEA, 0x6D, 0x59, 0x7A, 0xB3, 0x93, 0xE4, + 0x4B, 0x4B, 0x54, 0x63, 0xD8, 0xCE, 0x44, 0x06, 0xC2, 0xEC, + 0x9F, 0xF6, 0x05, 0x55, 0x46, 0xF4, 0x3E, 0x8F, 0xF2, 0x0C, + 0x30, 0x7E, 0x5C, 0xDD, 0x88, 0x49, 0x3B, 0x59, 0xB9, 0x87, + 0xBC, 0xC6, 0xC5, 0x24, 0x8A, 0x10, 0x63, 0x21, 0x1F, 0x66, + 0x1A, 0x3E, 0xF4, 0x58, 0xD1, 0x6C, 0x0D, 0x40, 0xB2, 0xC0, + 0x1D, 0x63, 0x42, 0x0E, 0xC4, 0x56, 0x0E, 0xC0, 0xCC, 0xC2, + 0xD6, 0x66, 0x0E, 0xC4, 0xAB, 0xB5, 0x33, 0xF6, 0x51, 0x02, + 0x81, 0x80, 0x19, 0x7E, 0xE6, 0xA5, 0xB6, 0xD1, 0x39, 0x6A, + 0x48, 0x55, 0xAC, 0x24, 0x96, 0x9B, 0x12, 0x28, 0x6D, 0x7B, + 0x5C, 0x05, 0x25, 0x5A, 0x72, 0x05, 0x7E, 0x42, 0xF5, 0x83, + 0x1A, 0x78, 0x2C, 0x4D, 0xAE, 0xB4, 0x36, 0x96, 0xA9, 0xBA, + 0xE0, 0xAC, 0x26, 0x9D, 0xA9, 0x6A, 0x29, 0x83, 0xB9, 0x6D, + 0xC5, 0xEC, 0xFA, 0x4A, 0x9C, 0x09, 0x6A, 0x7E, 0xE4, 0x9B, + 0xDC, 0x9B, 0x2A, 0x27, 0x6E, 0x4F, 0xBA, 0xD8, 0xA5, 0x67, + 0xDB, 0xEC, 0x41, 0x5F, 0x29, 0x1C, 0x40, 0x83, 0xEB, 0x59, + 0x56, 0xD7, 0xA9, 0x4E, 0xAB, 0xAE, 0x70, 0x67, 0xD1, 0xA3, + 0xF1, 0x6C, 0xD7, 0x8F, 0x96, 0x0E, 0x8D, 0xAC, 0xAB, 0x55, + 0x58, 0x66, 0xD3, 0x1E, 0x47, 0x9B, 0xF0, 0x4C, 0xED, 0xF6, + 0x49, 0xE8, 0xE9, 0x7B, 0x32, 0x61, 0x20, 0x31, 0x95, 0x05, + 0xB2, 0xF6, 0x09, 0xEA, 0x32, 0x14, 0x0F, 0xCF, 0x9A, 0x41, + 0x02, 0x81, 0x80, 0x77, 0x3F, 0xB6, 0x14, 0x8D, 0xC5, 0x13, + 0x08, 0x7E, 0xC9, 0xC4, 0xEA, 0xD4, 0xBA, 0x0D, 0xA4, 0x9E, + 0xB3, 0x6E, 0xDE, 0x1A, 0x7A, 0xF8, 0x89, 0x88, 0xEF, 0x36, + 0x3C, 0x11, 0xBC, 0x83, 0xE8, 0x30, 0x6C, 0x81, 0x7C, 0x47, + 0xF3, 0x4D, 0xCA, 0xEA, 0x56, 0x01, 0x62, 0x55, 0x2E, 0x4B, + 0x89, 0xA9, 0xBD, 0x6F, 0x01, 0xF6, 0x74, 0x02, 0xAA, 0xE3, + 0x84, 0x66, 0x06, 0x95, 0x34, 0xA1, 0xE2, 0xCA, 0x65, 0xFE, + 0xA3, 0x2D, 0x43, 0x97, 0x95, 0x6C, 0x6F, 0xD5, 0xB4, 0x38, + 0xF6, 0xF9, 0x95, 0x30, 0xFA, 0xF8, 0x9C, 0x25, 0x2B, 0xB6, + 0x14, 0x51, 0xCC, 0x2E, 0xB3, 0x5B, 0xD6, 0xDC, 0x1A, 0xEC, + 0x2D, 0x09, 0x5B, 0x3F, 0x3A, 0xD0, 0xB8, 0x4E, 0x27, 0x1F, + 0xDC, 0x2A, 0xEE, 0xAC, 0xA9, 0x59, 0x5D, 0x07, 0x63, 0x11, + 0x83, 0x0B, 0xD4, 0x74, 0x80, 0xB6, 0x7D, 0x62, 0x45, 0xBF, + 0x56 }; 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[] = { - 0x30, 0x82, 0x04, 0xAA, 0x30, 0x82, 0x03, 0x92, 0xA0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xD9, 0x80, 0x3A, 0xC3, - 0xD2, 0xF4, 0xDA, 0x37, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, - 0x81, 0x94, 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, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, - 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, - 0x67, 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, 0x35, 0x30, 0x35, 0x30, 0x37, - 0x31, 0x38, 0x32, 0x31, 0x30, 0x31, 0x5A, 0x17, 0x0D, 0x31, - 0x38, 0x30, 0x31, 0x33, 0x31, 0x31, 0x38, 0x32, 0x31, 0x30, - 0x31, 0x5A, 0x30, 0x81, 0x94, 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, 0x11, 0x30, 0x0F, 0x06, 0x03, - 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, - 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, - 0x74, 0x69, 0x6E, 0x67, 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, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, - 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, - 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 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, 0xA3, 0x81, 0xFC, - 0x30, 0x81, 0xF9, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, - 0x04, 0x16, 0x04, 0x14, 0x27, 0x8E, 0x67, 0x11, 0x74, 0xC3, - 0x26, 0x1D, 0x3F, 0xED, 0x33, 0x63, 0xB3, 0xA4, 0xD8, 0x1D, - 0x30, 0xE5, 0xE8, 0xD5, 0x30, 0x81, 0xC9, 0x06, 0x03, 0x55, - 0x1D, 0x23, 0x04, 0x81, 0xC1, 0x30, 0x81, 0xBE, 0x80, 0x14, - 0x27, 0x8E, 0x67, 0x11, 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, - 0x33, 0x63, 0xB3, 0xA4, 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, - 0xA1, 0x81, 0x9A, 0xA4, 0x81, 0x97, 0x30, 0x81, 0x94, 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, 0x11, - 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, - 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, - 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, - 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 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, - 0xD9, 0x80, 0x3A, 0xC3, 0xD2, 0xF4, 0xDA, 0x37, 0x30, 0x0C, - 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, - 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, - 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x01, 0x00, 0x7A, 0xAF, 0x44, 0x3B, 0xAA, 0x6F, 0x53, 0x42, - 0xB2, 0x33, 0xAA, 0x43, 0x5F, 0x56, 0x30, 0xD3, 0xB9, 0x96, - 0x0B, 0x9A, 0x55, 0x5A, 0x39, 0x2A, 0x0B, 0x4E, 0xE4, 0x2E, - 0xF1, 0x95, 0x66, 0xC9, 0x86, 0x36, 0x82, 0x8D, 0x63, 0x7C, - 0x4D, 0xA2, 0xEE, 0x48, 0xBA, 0x03, 0xC7, 0x90, 0xD7, 0xA7, - 0xC6, 0x74, 0x60, 0x48, 0x5F, 0x31, 0xA2, 0xF9, 0x5E, 0x3E, - 0xC3, 0x82, 0xE1, 0xE5, 0x2F, 0x41, 0x81, 0x83, 0x29, 0x25, - 0x79, 0xD1, 0x53, 0x00, 0x69, 0x3C, 0xED, 0x0A, 0x30, 0x3B, - 0x41, 0x1D, 0x92, 0xA1, 0x2C, 0xA8, 0x9D, 0x2C, 0xE3, 0x23, - 0x87, 0x79, 0xE0, 0x55, 0x6E, 0x91, 0xA8, 0x50, 0xDA, 0x46, - 0x2F, 0xC2, 0x20, 0x50, 0x3E, 0x2B, 0x47, 0x97, 0x14, 0xB0, - 0x7D, 0x04, 0xBA, 0x45, 0x51, 0xD0, 0x6E, 0xE1, 0x5A, 0xA2, - 0x4B, 0x84, 0x9C, 0x4D, 0xCD, 0x85, 0x04, 0xF9, 0x28, 0x31, - 0x82, 0x93, 0xBC, 0xC7, 0x59, 0x49, 0x91, 0x03, 0xE8, 0xDF, - 0x6A, 0xE4, 0x56, 0xAD, 0x6A, 0xCB, 0x1F, 0x0D, 0x37, 0xE4, - 0x5E, 0xBD, 0xE7, 0x9F, 0xD5, 0xEC, 0x9D, 0x3C, 0x18, 0x25, - 0x9B, 0xF1, 0x2F, 0x50, 0x7D, 0xEB, 0x31, 0xCB, 0xF1, 0x63, - 0x22, 0x9D, 0x57, 0xFC, 0xF3, 0x84, 0x20, 0x1A, 0xC6, 0x07, - 0x87, 0x92, 0x26, 0x9E, 0x15, 0x18, 0x59, 0x33, 0x06, 0xDC, - 0xFB, 0xB0, 0xB6, 0x76, 0x5D, 0xF1, 0xC1, 0x2F, 0xC8, 0x2F, - 0x62, 0x9C, 0xC0, 0xD6, 0xDE, 0xEB, 0x65, 0x77, 0xF3, 0x5C, - 0xA6, 0xC3, 0x88, 0x27, 0x96, 0x75, 0xB4, 0xF4, 0x54, 0xCD, - 0xFF, 0x2D, 0x21, 0x2E, 0x96, 0xF0, 0x07, 0x73, 0x4B, 0xE9, - 0x93, 0x92, 0x90, 0xDE, 0x62, 0xD9, 0xA3, 0x3B, 0xAC, 0x6E, - 0x24, 0x5F, 0x27, 0x4A, 0xB3, 0x94, 0x70, 0xFF, 0x30, 0x17, - 0xE7, 0x7E, 0x32, 0x8F, 0x65, 0xB7, 0x75, 0x58 + 0x30, 0x82, 0x04, 0xAA, 0x30, 0x82, 0x03, 0x92, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x86, 0xFF, 0xF5, 0x8E, + 0x10, 0xDE, 0xB8, 0xFB, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x94, 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, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, + 0x67, 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, 0x38, 0x30, 0x34, 0x31, 0x33, + 0x31, 0x35, 0x32, 0x33, 0x30, 0x39, 0x5A, 0x17, 0x0D, 0x32, + 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x30, + 0x39, 0x5A, 0x30, 0x81, 0x94, 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, 0x11, 0x30, 0x0F, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, + 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, + 0x74, 0x69, 0x6E, 0x67, 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, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, + 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 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, 0xA3, 0x81, 0xFC, + 0x30, 0x81, 0xF9, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, + 0x04, 0x16, 0x04, 0x14, 0x27, 0x8E, 0x67, 0x11, 0x74, 0xC3, + 0x26, 0x1D, 0x3F, 0xED, 0x33, 0x63, 0xB3, 0xA4, 0xD8, 0x1D, + 0x30, 0xE5, 0xE8, 0xD5, 0x30, 0x81, 0xC9, 0x06, 0x03, 0x55, + 0x1D, 0x23, 0x04, 0x81, 0xC1, 0x30, 0x81, 0xBE, 0x80, 0x14, + 0x27, 0x8E, 0x67, 0x11, 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, + 0x33, 0x63, 0xB3, 0xA4, 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, + 0xA1, 0x81, 0x9A, 0xA4, 0x81, 0x97, 0x30, 0x81, 0x94, 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, 0x11, + 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, + 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, + 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 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, + 0x86, 0xFF, 0xF5, 0x8E, 0x10, 0xDE, 0xB8, 0xFB, 0x30, 0x0C, + 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, + 0x01, 0x00, 0x9E, 0x28, 0x88, 0x72, 0x00, 0xCA, 0xE6, 0xE7, + 0x97, 0xCA, 0xC1, 0xF1, 0x1F, 0x9E, 0x12, 0xB2, 0xB8, 0xC7, + 0x51, 0xEA, 0x28, 0xE1, 0x36, 0xB5, 0x2D, 0xE6, 0x2F, 0x08, + 0x23, 0xCB, 0xA9, 0x4A, 0x87, 0x25, 0xC6, 0x5D, 0x89, 0x45, + 0xEA, 0xF5, 0x00, 0x98, 0xAC, 0x76, 0xFB, 0x1B, 0xAF, 0xF0, + 0xCE, 0x64, 0x9E, 0xDA, 0x08, 0xBF, 0xB6, 0xEB, 0xB4, 0xB5, + 0x0C, 0xA0, 0xE7, 0xF6, 0x47, 0x59, 0x1C, 0x61, 0xCF, 0x2E, + 0x0E, 0x58, 0xA4, 0x82, 0xAC, 0x0F, 0x3F, 0xEC, 0xC4, 0xAE, + 0x80, 0xF7, 0xB0, 0x8A, 0x1E, 0x85, 0x41, 0xE8, 0xFF, 0xFE, + 0xFE, 0x4F, 0x1A, 0x24, 0xD5, 0x49, 0xFA, 0xFB, 0xFE, 0x5E, + 0xE5, 0xD3, 0x91, 0x0E, 0x4F, 0x4E, 0x0C, 0x21, 0x51, 0x71, + 0x83, 0x04, 0x6B, 0x62, 0x7B, 0x4F, 0x59, 0x76, 0x48, 0x81, + 0x1E, 0xB4, 0xF7, 0x04, 0x47, 0x8A, 0x91, 0x57, 0xA3, 0x11, + 0xA9, 0xF2, 0x20, 0xB4, 0x78, 0x33, 0x62, 0x3D, 0xB0, 0x5E, + 0x0D, 0xF9, 0x86, 0x38, 0x82, 0xDA, 0xA1, 0x98, 0x8D, 0x19, + 0x06, 0x87, 0x21, 0x39, 0xB7, 0x02, 0xF7, 0xDA, 0x7D, 0x58, + 0xBA, 0x52, 0x15, 0xD8, 0x3B, 0xC9, 0x7B, 0x58, 0x34, 0xA0, + 0xC7, 0xE2, 0x7C, 0xA9, 0x83, 0x13, 0xE1, 0xB6, 0xEC, 0x01, + 0xBF, 0x52, 0x33, 0x0B, 0xC4, 0xFE, 0x43, 0xD3, 0xC6, 0xA4, + 0x8E, 0x2F, 0x87, 0x7F, 0x7A, 0x44, 0xEA, 0xCA, 0x53, 0x6C, + 0x85, 0xED, 0x65, 0x76, 0x73, 0x31, 0x03, 0x4E, 0xEA, 0xBD, + 0x35, 0x54, 0x13, 0xF3, 0x64, 0x87, 0x6B, 0xDF, 0x34, 0xDD, + 0x34, 0xA1, 0x88, 0x3B, 0xDB, 0x4D, 0xAF, 0x1B, 0x64, 0x90, + 0x92, 0x71, 0x30, 0x8E, 0xC8, 0xCC, 0xE5, 0x60, 0x24, 0xAF, + 0x31, 0x16, 0x39, 0x33, 0x91, 0x50, 0xF9, 0xAB, 0x68, 0x42, + 0x74, 0x7A, 0x35, 0xD9, 0xDD, 0xC8, 0xC4, 0x52 }; static const int sizeof_ca_cert_der_2048 = sizeof(ca_cert_der_2048); +/* ./certs/ca-cert-chain.der, 2048-bit */ +static const unsigned char ca_cert_chain_der[] = +{ + 0x30, 0x82, 0x03, 0xB5, 0x30, 0x82, 0x03, 0x1E, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xDA, 0xFB, 0x6A, 0x0D, + 0xFE, 0xCF, 0x9B, 0x47, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x99, 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, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x0F, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, + 0x67, 0x5F, 0x31, 0x30, 0x32, 0x34, 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, + 0x38, 0x30, 0x34, 0x31, 0x33, 0x31, 0x35, 0x32, 0x33, 0x31, + 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, + 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x30, 0x81, 0x99, + 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, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, + 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, + 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, + 0x31, 0x30, 0x32, 0x34, 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, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, + 0x81, 0x00, 0xCD, 0xAC, 0xDD, 0x47, 0xEC, 0xBE, 0xB7, 0x24, + 0xC3, 0x63, 0x1B, 0x54, 0x98, 0x79, 0xE1, 0xC7, 0x31, 0x16, + 0x59, 0xD6, 0x9D, 0x77, 0x9D, 0x8D, 0xE2, 0x8B, 0xED, 0x04, + 0x17, 0xB2, 0xC6, 0xEB, 0xE4, 0x9B, 0x91, 0xBE, 0x31, 0x50, + 0x62, 0x97, 0x58, 0xB5, 0x7F, 0x29, 0xDE, 0xB3, 0x71, 0x24, + 0x0B, 0xBF, 0x97, 0x09, 0x7F, 0x26, 0xDC, 0x2D, 0xEC, 0xA8, + 0x2E, 0xB2, 0x64, 0x2B, 0x7A, 0x2B, 0x35, 0x19, 0x2D, 0xA2, + 0x80, 0xCB, 0x99, 0xFD, 0x94, 0x71, 0x1B, 0x23, 0x8D, 0x54, + 0xDB, 0x2E, 0x62, 0x8D, 0x81, 0x08, 0x2D, 0xF4, 0x24, 0x72, + 0x27, 0x6C, 0xF9, 0xC9, 0x8E, 0xDB, 0x4C, 0x75, 0xBA, 0x9B, + 0x01, 0xF8, 0x3F, 0x18, 0xF4, 0xE6, 0x7F, 0xFB, 0x57, 0x94, + 0x92, 0xCC, 0x88, 0xC4, 0xB4, 0x00, 0xC2, 0xAA, 0xD4, 0xE5, + 0x88, 0x18, 0xB3, 0x11, 0x2F, 0x73, 0xC0, 0xD6, 0x29, 0x09, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x01, 0x30, + 0x81, 0xFE, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, + 0x16, 0x04, 0x14, 0xD3, 0x22, 0x8F, 0x28, 0x2C, 0xE0, 0x05, + 0xEE, 0xD3, 0xED, 0xC3, 0x71, 0x3D, 0xC9, 0xB2, 0x36, 0x3A, + 0x1D, 0xBF, 0xA8, 0x30, 0x81, 0xCE, 0x06, 0x03, 0x55, 0x1D, + 0x23, 0x04, 0x81, 0xC6, 0x30, 0x81, 0xC3, 0x80, 0x14, 0xD3, + 0x22, 0x8F, 0x28, 0x2C, 0xE0, 0x05, 0xEE, 0xD3, 0xED, 0xC3, + 0x71, 0x3D, 0xC9, 0xB2, 0x36, 0x3A, 0x1D, 0xBF, 0xA8, 0xA1, + 0x81, 0x9F, 0xA4, 0x81, 0x9C, 0x30, 0x81, 0x99, 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, 0x11, 0x30, + 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, + 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, 0x6F, 0x6E, + 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, 0x31, 0x30, + 0x32, 0x34, 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, 0xDA, 0xFB, 0x6A, 0x0D, 0xFE, 0xCF, + 0x9B, 0x47, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x03, 0x81, 0x81, 0x00, 0x1D, 0x48, 0xF6, 0x40, 0x41, + 0x04, 0x06, 0xF2, 0xE4, 0x72, 0x2F, 0xEA, 0xFF, 0xC1, 0x67, + 0x6B, 0x15, 0xBB, 0x0A, 0x28, 0x23, 0x28, 0x07, 0xC6, 0xD7, + 0x13, 0x2C, 0xBE, 0x00, 0x00, 0xAC, 0x1D, 0xF7, 0xF4, 0x92, + 0xD3, 0x2B, 0xAF, 0x23, 0xEB, 0x9F, 0x1A, 0xE2, 0x11, 0x3C, + 0x2D, 0x97, 0xF2, 0x0F, 0xAC, 0xAE, 0x97, 0x86, 0x0A, 0xFB, + 0xA8, 0x4F, 0x74, 0x1B, 0xDE, 0x19, 0x51, 0xDB, 0xCD, 0xE2, + 0x11, 0x38, 0xC1, 0xA4, 0x9D, 0x56, 0xAB, 0x47, 0x5C, 0xDE, + 0xBA, 0xEB, 0x27, 0xDF, 0x6D, 0xC8, 0x7E, 0x3A, 0xBD, 0x2E, + 0x9B, 0x2A, 0xAD, 0x22, 0x3B, 0x95, 0xA9, 0xF2, 0x28, 0x03, + 0xBC, 0xE5, 0xEC, 0xCC, 0xF2, 0x08, 0xD4, 0xC8, 0x2F, 0xDB, + 0xEA, 0xFB, 0x2E, 0x52, 0x16, 0x8C, 0x42, 0x02, 0xA4, 0x59, + 0x6D, 0x4C, 0x33, 0xB4, 0x9A, 0xD2, 0x73, 0x4A, 0x1E, 0x9F, + 0xD9, 0xC8, 0x83, 0x30, 0x82, 0x04, 0xAA, 0x30, 0x82, 0x03, + 0x92, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x86, + 0xFF, 0xF5, 0x8E, 0x10, 0xDE, 0xB8, 0xFB, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + 0x05, 0x00, 0x30, 0x81, 0x94, 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, 0x11, 0x30, 0x0F, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, + 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, + 0x74, 0x69, 0x6E, 0x67, 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, 0x38, 0x30, + 0x34, 0x31, 0x33, 0x31, 0x35, 0x32, 0x33, 0x30, 0x39, 0x5A, + 0x17, 0x0D, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, + 0x32, 0x33, 0x30, 0x39, 0x5A, 0x30, 0x81, 0x94, 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, 0x11, 0x30, + 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, + 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, + 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 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, 0x82, 0x01, 0x22, + 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, + 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 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, + 0xA3, 0x81, 0xFC, 0x30, 0x81, 0xF9, 0x30, 0x1D, 0x06, 0x03, + 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x27, 0x8E, 0x67, + 0x11, 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, 0x33, 0x63, 0xB3, + 0xA4, 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, 0x30, 0x81, 0xC9, + 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0xC1, 0x30, 0x81, + 0xBE, 0x80, 0x14, 0x27, 0x8E, 0x67, 0x11, 0x74, 0xC3, 0x26, + 0x1D, 0x3F, 0xED, 0x33, 0x63, 0xB3, 0xA4, 0xD8, 0x1D, 0x30, + 0xE5, 0xE8, 0xD5, 0xA1, 0x81, 0x9A, 0xA4, 0x81, 0x97, 0x30, + 0x81, 0x94, 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, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, + 0x67, 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, 0x86, 0xFF, 0xF5, 0x8E, 0x10, 0xDE, 0xB8, + 0xFB, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, + 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x01, 0x00, 0x9E, 0x28, 0x88, 0x72, 0x00, + 0xCA, 0xE6, 0xE7, 0x97, 0xCA, 0xC1, 0xF1, 0x1F, 0x9E, 0x12, + 0xB2, 0xB8, 0xC7, 0x51, 0xEA, 0x28, 0xE1, 0x36, 0xB5, 0x2D, + 0xE6, 0x2F, 0x08, 0x23, 0xCB, 0xA9, 0x4A, 0x87, 0x25, 0xC6, + 0x5D, 0x89, 0x45, 0xEA, 0xF5, 0x00, 0x98, 0xAC, 0x76, 0xFB, + 0x1B, 0xAF, 0xF0, 0xCE, 0x64, 0x9E, 0xDA, 0x08, 0xBF, 0xB6, + 0xEB, 0xB4, 0xB5, 0x0C, 0xA0, 0xE7, 0xF6, 0x47, 0x59, 0x1C, + 0x61, 0xCF, 0x2E, 0x0E, 0x58, 0xA4, 0x82, 0xAC, 0x0F, 0x3F, + 0xEC, 0xC4, 0xAE, 0x80, 0xF7, 0xB0, 0x8A, 0x1E, 0x85, 0x41, + 0xE8, 0xFF, 0xFE, 0xFE, 0x4F, 0x1A, 0x24, 0xD5, 0x49, 0xFA, + 0xFB, 0xFE, 0x5E, 0xE5, 0xD3, 0x91, 0x0E, 0x4F, 0x4E, 0x0C, + 0x21, 0x51, 0x71, 0x83, 0x04, 0x6B, 0x62, 0x7B, 0x4F, 0x59, + 0x76, 0x48, 0x81, 0x1E, 0xB4, 0xF7, 0x04, 0x47, 0x8A, 0x91, + 0x57, 0xA3, 0x11, 0xA9, 0xF2, 0x20, 0xB4, 0x78, 0x33, 0x62, + 0x3D, 0xB0, 0x5E, 0x0D, 0xF9, 0x86, 0x38, 0x82, 0xDA, 0xA1, + 0x98, 0x8D, 0x19, 0x06, 0x87, 0x21, 0x39, 0xB7, 0x02, 0xF7, + 0xDA, 0x7D, 0x58, 0xBA, 0x52, 0x15, 0xD8, 0x3B, 0xC9, 0x7B, + 0x58, 0x34, 0xA0, 0xC7, 0xE2, 0x7C, 0xA9, 0x83, 0x13, 0xE1, + 0xB6, 0xEC, 0x01, 0xBF, 0x52, 0x33, 0x0B, 0xC4, 0xFE, 0x43, + 0xD3, 0xC6, 0xA4, 0x8E, 0x2F, 0x87, 0x7F, 0x7A, 0x44, 0xEA, + 0xCA, 0x53, 0x6C, 0x85, 0xED, 0x65, 0x76, 0x73, 0x31, 0x03, + 0x4E, 0xEA, 0xBD, 0x35, 0x54, 0x13, 0xF3, 0x64, 0x87, 0x6B, + 0xDF, 0x34, 0xDD, 0x34, 0xA1, 0x88, 0x3B, 0xDB, 0x4D, 0xAF, + 0x1B, 0x64, 0x90, 0x92, 0x71, 0x30, 0x8E, 0xC8, 0xCC, 0xE5, + 0x60, 0x24, 0xAF, 0x31, 0x16, 0x39, 0x33, 0x91, 0x50, 0xF9, + 0xAB, 0x68, 0x42, 0x74, 0x7A, 0x35, 0xD9, 0xDD, 0xC8, 0xC4, + 0x52 +}; +static const int sizeof_ca_cert_chain_der = sizeof(ca_cert_chain_der); + /* ./certs/server-key.der, 2048-bit */ static const unsigned char server_key_der_2048[] = { - 0x30, 0x82, 0x04, 0xA5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, - 0x01, 0x00, 0xC0, 0x95, 0x08, 0xE1, 0x57, 0x41, 0xF2, 0x71, - 0x6D, 0xB7, 0xD2, 0x45, 0x41, 0x27, 0x01, 0x65, 0xC6, 0x45, - 0xAE, 0xF2, 0xBC, 0x24, 0x30, 0xB8, 0x95, 0xCE, 0x2F, 0x4E, - 0xD6, 0xF6, 0x1C, 0x88, 0xBC, 0x7C, 0x9F, 0xFB, 0xA8, 0x67, - 0x7F, 0xFE, 0x5C, 0x9C, 0x51, 0x75, 0xF7, 0x8A, 0xCA, 0x07, - 0xE7, 0x35, 0x2F, 0x8F, 0xE1, 0xBD, 0x7B, 0xC0, 0x2F, 0x7C, - 0xAB, 0x64, 0xA8, 0x17, 0xFC, 0xCA, 0x5D, 0x7B, 0xBA, 0xE0, - 0x21, 0xE5, 0x72, 0x2E, 0x6F, 0x2E, 0x86, 0xD8, 0x95, 0x73, - 0xDA, 0xAC, 0x1B, 0x53, 0xB9, 0x5F, 0x3F, 0xD7, 0x19, 0x0D, - 0x25, 0x4F, 0xE1, 0x63, 0x63, 0x51, 0x8B, 0x0B, 0x64, 0x3F, - 0xAD, 0x43, 0xB8, 0xA5, 0x1C, 0x5C, 0x34, 0xB3, 0xAE, 0x00, - 0xA0, 0x63, 0xC5, 0xF6, 0x7F, 0x0B, 0x59, 0x68, 0x78, 0x73, - 0xA6, 0x8C, 0x18, 0xA9, 0x02, 0x6D, 0xAF, 0xC3, 0x19, 0x01, - 0x2E, 0xB8, 0x10, 0xE3, 0xC6, 0xCC, 0x40, 0xB4, 0x69, 0xA3, - 0x46, 0x33, 0x69, 0x87, 0x6E, 0xC4, 0xBB, 0x17, 0xA6, 0xF3, - 0xE8, 0xDD, 0xAD, 0x73, 0xBC, 0x7B, 0x2F, 0x21, 0xB5, 0xFD, - 0x66, 0x51, 0x0C, 0xBD, 0x54, 0xB3, 0xE1, 0x6D, 0x5F, 0x1C, - 0xBC, 0x23, 0x73, 0xD1, 0x09, 0x03, 0x89, 0x14, 0xD2, 0x10, - 0xB9, 0x64, 0xC3, 0x2A, 0xD0, 0xA1, 0x96, 0x4A, 0xBC, 0xE1, - 0xD4, 0x1A, 0x5B, 0xC7, 0xA0, 0xC0, 0xC1, 0x63, 0x78, 0x0F, - 0x44, 0x37, 0x30, 0x32, 0x96, 0x80, 0x32, 0x23, 0x95, 0xA1, - 0x77, 0xBA, 0x13, 0xD2, 0x97, 0x73, 0xE2, 0x5D, 0x25, 0xC9, - 0x6A, 0x0D, 0xC3, 0x39, 0x60, 0xA4, 0xB4, 0xB0, 0x69, 0x42, - 0x42, 0x09, 0xE9, 0xD8, 0x08, 0xBC, 0x33, 0x20, 0xB3, 0x58, - 0x22, 0xA7, 0xAA, 0xEB, 0xC4, 0xE1, 0xE6, 0x61, 0x83, 0xC5, - 0xD2, 0x96, 0xDF, 0xD9, 0xD0, 0x4F, 0xAD, 0xD7, 0x02, 0x03, - 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9A, 0xD0, - 0x34, 0x0F, 0x52, 0x62, 0x05, 0x50, 0x01, 0xEF, 0x9F, 0xED, - 0x64, 0x6E, 0xC2, 0xC4, 0xDA, 0x1A, 0xF2, 0x84, 0xD7, 0x92, - 0x10, 0x48, 0x92, 0xC4, 0xE9, 0x6A, 0xEB, 0x8B, 0x75, 0x6C, - 0xC6, 0x79, 0x38, 0xF2, 0xC9, 0x72, 0x4A, 0x86, 0x64, 0x54, - 0x95, 0x77, 0xCB, 0xC3, 0x9A, 0x9D, 0xB7, 0xD4, 0x1D, 0xA4, - 0x00, 0xC8, 0x9E, 0x4E, 0xE4, 0xDD, 0xC7, 0xBA, 0x67, 0x16, - 0xC1, 0x74, 0xBC, 0xA9, 0xD6, 0x94, 0x8F, 0x2B, 0x30, 0x1A, - 0xFB, 0xED, 0xDF, 0x21, 0x05, 0x23, 0xD9, 0x4A, 0x39, 0xBD, - 0x98, 0x6B, 0x65, 0x9A, 0xB8, 0xDC, 0xC4, 0x7D, 0xEE, 0xA6, - 0x43, 0x15, 0x2E, 0x3D, 0xBE, 0x1D, 0x22, 0x60, 0x2A, 0x73, - 0x30, 0xD5, 0x3E, 0xD8, 0xA2, 0xAC, 0x86, 0x43, 0x2E, 0xC4, - 0xF5, 0x64, 0x5E, 0x3F, 0x89, 0x75, 0x0F, 0x11, 0xD8, 0x51, - 0x25, 0x4E, 0x9F, 0xD8, 0xAA, 0xA3, 0xCE, 0x60, 0xB3, 0xE2, - 0x8A, 0xD9, 0x7E, 0x1B, 0xF0, 0x64, 0xCA, 0x9A, 0x5B, 0x05, - 0x0B, 0x5B, 0xAA, 0xCB, 0xE5, 0xE3, 0x3F, 0x6E, 0x32, 0x22, - 0x05, 0xF3, 0xD0, 0xFA, 0xEF, 0x74, 0x52, 0x81, 0xE2, 0x5F, - 0x74, 0xD3, 0xBD, 0xFF, 0x31, 0x83, 0x45, 0x75, 0xFA, 0x63, - 0x7A, 0x97, 0x2E, 0xD6, 0xB6, 0x19, 0xC6, 0x92, 0x26, 0xE4, - 0x28, 0x06, 0x50, 0x50, 0x0E, 0x78, 0x2E, 0xA9, 0x78, 0x0D, - 0x14, 0x97, 0xB4, 0x12, 0xD8, 0x31, 0x40, 0xAB, 0xA1, 0x01, - 0x41, 0xC2, 0x30, 0xF8, 0x07, 0x5F, 0x16, 0xE4, 0x61, 0x77, - 0xD2, 0x60, 0xF2, 0x9F, 0x8D, 0xE8, 0xF4, 0xBA, 0xEB, 0x63, - 0xDE, 0x2A, 0x97, 0x81, 0xEF, 0x4C, 0x6C, 0xE6, 0x55, 0x34, - 0x51, 0x2B, 0x28, 0x34, 0xF4, 0x53, 0x1C, 0xC4, 0x58, 0x0A, - 0x3F, 0xBB, 0xAF, 0xB5, 0xF7, 0x4A, 0x85, 0x43, 0x2D, 0x3C, - 0xF1, 0x58, 0x58, 0x81, 0x02, 0x81, 0x81, 0x00, 0xF2, 0x2C, - 0x54, 0x76, 0x39, 0x23, 0x63, 0xC9, 0x10, 0x32, 0xB7, 0x93, - 0xAD, 0xAF, 0xBE, 0x19, 0x75, 0x96, 0x81, 0x64, 0xE6, 0xB5, - 0xB8, 0x89, 0x42, 0x41, 0xD1, 0x6D, 0xD0, 0x1C, 0x1B, 0xF8, - 0x1B, 0xAC, 0x69, 0xCB, 0x36, 0x3C, 0x64, 0x7D, 0xDC, 0xF4, - 0x19, 0xB8, 0xC3, 0x60, 0xB1, 0x57, 0x48, 0x5F, 0x52, 0x4F, - 0x59, 0x3A, 0x55, 0x7F, 0x32, 0xC0, 0x19, 0x43, 0x50, 0x3F, - 0xAE, 0xCE, 0x6F, 0x17, 0xF3, 0x0E, 0x9F, 0x40, 0xCA, 0x4E, - 0xAD, 0x15, 0x3B, 0xC9, 0x79, 0xE9, 0xC0, 0x59, 0x38, 0x73, - 0x70, 0x9C, 0x0A, 0x7C, 0xC9, 0x3A, 0x48, 0x32, 0xA7, 0xD8, - 0x49, 0x75, 0x0A, 0x85, 0xC2, 0xC2, 0xFD, 0x15, 0x73, 0xDA, - 0x99, 0x09, 0x2A, 0x69, 0x9A, 0x9F, 0x0A, 0x71, 0xBF, 0xB0, - 0x04, 0xA6, 0x8C, 0x7A, 0x5A, 0x6F, 0x48, 0x5A, 0x54, 0x3B, - 0xC6, 0xB1, 0x53, 0x17, 0xDF, 0xE7, 0x02, 0x81, 0x81, 0x00, - 0xCB, 0x93, 0xDE, 0x77, 0x15, 0x5D, 0xB7, 0x5C, 0x5C, 0x7C, - 0xD8, 0x90, 0xA9, 0x98, 0x2D, 0xD6, 0x69, 0x0E, 0x63, 0xB3, - 0xA3, 0xDC, 0xA6, 0xCC, 0x8B, 0x6A, 0xA4, 0xA2, 0x12, 0x8C, - 0x8E, 0x7B, 0x48, 0x2C, 0xB2, 0x4B, 0x37, 0xDC, 0x06, 0x18, - 0x7D, 0xEA, 0xFE, 0x76, 0xA1, 0xD4, 0xA1, 0xE9, 0x3F, 0x0D, - 0xCD, 0x1B, 0x5F, 0xAF, 0x5F, 0x9E, 0x96, 0x5B, 0x5B, 0x0F, - 0xA1, 0x7C, 0xAF, 0xB3, 0x9B, 0x90, 0xDB, 0x57, 0x73, 0x3A, - 0xED, 0xB0, 0x23, 0x44, 0xAE, 0x41, 0x4F, 0x1F, 0x07, 0x42, - 0x13, 0x23, 0x4C, 0xCB, 0xFA, 0xF4, 0x14, 0xA4, 0xD5, 0xF7, - 0x9E, 0x36, 0x7C, 0x5B, 0x9F, 0xA8, 0x3C, 0xC1, 0x85, 0x5F, - 0x74, 0xD2, 0x39, 0x2D, 0xFF, 0xD0, 0x84, 0xDF, 0xFB, 0xB3, - 0x20, 0x7A, 0x2E, 0x9B, 0x17, 0xAE, 0xE6, 0xBA, 0x0B, 0xAE, - 0x5F, 0x53, 0xA4, 0x52, 0xED, 0x1B, 0xC4, 0x91, 0x02, 0x81, - 0x81, 0x00, 0xEC, 0x98, 0xDA, 0xBB, 0xD5, 0xFE, 0xF9, 0x52, - 0x4A, 0x7D, 0x02, 0x55, 0x49, 0x6F, 0x55, 0x6E, 0x52, 0x2F, - 0x84, 0xA3, 0x2B, 0xB3, 0x86, 0x62, 0xB3, 0x54, 0xD2, 0x63, - 0x52, 0xDA, 0xE3, 0x88, 0x76, 0xA0, 0xEF, 0x8B, 0x15, 0xA5, - 0xD3, 0x18, 0x14, 0x72, 0x77, 0x5E, 0xC7, 0xA3, 0x04, 0x1F, - 0x9E, 0x19, 0x62, 0xB5, 0x1B, 0x1B, 0x9E, 0xC3, 0xF2, 0xB5, - 0x32, 0xF9, 0x4C, 0xC1, 0xAA, 0xEB, 0x0C, 0x26, 0x7D, 0xD4, - 0x5F, 0x4A, 0x51, 0x5C, 0xA4, 0x45, 0x06, 0x70, 0x44, 0xA7, - 0x56, 0xC0, 0xD4, 0x22, 0x14, 0x76, 0x9E, 0xD8, 0x63, 0x50, - 0x89, 0x90, 0xD3, 0xE2, 0xBF, 0x81, 0x95, 0x92, 0x31, 0x41, - 0x87, 0x39, 0x1A, 0x43, 0x0B, 0x18, 0xA5, 0x53, 0x1F, 0x39, - 0x1A, 0x5F, 0x1F, 0x43, 0xBC, 0x87, 0x6A, 0xDF, 0x6E, 0xD3, - 0x22, 0x00, 0xFE, 0x22, 0x98, 0x70, 0x4E, 0x1A, 0x19, 0x29, - 0x02, 0x81, 0x81, 0x00, 0x8A, 0x41, 0x56, 0x28, 0x51, 0x9E, - 0x5F, 0xD4, 0x9E, 0x0B, 0x3B, 0x98, 0xA3, 0x54, 0xF2, 0x6C, - 0x56, 0xD4, 0xAA, 0xE9, 0x69, 0x33, 0x85, 0x24, 0x0C, 0xDA, - 0xD4, 0x0C, 0x2D, 0xC4, 0xBF, 0x4F, 0x02, 0x69, 0x38, 0x7C, - 0xD4, 0xE6, 0xDC, 0x4C, 0xED, 0xD7, 0x16, 0x11, 0xC3, 0x3E, - 0x00, 0xE7, 0xC3, 0x26, 0xC0, 0x51, 0x02, 0xDE, 0xBB, 0x75, - 0x9C, 0x6F, 0x56, 0x9C, 0x7A, 0xF3, 0x8E, 0xEF, 0xCF, 0x8A, - 0xC5, 0x2B, 0xD2, 0xDA, 0x06, 0x6A, 0x44, 0xC9, 0x73, 0xFE, - 0x6E, 0x99, 0x87, 0xF8, 0x5B, 0xBE, 0xF1, 0x7C, 0xE6, 0x65, - 0xB5, 0x4F, 0x6C, 0xF0, 0xC9, 0xC5, 0xFF, 0x16, 0xCA, 0x8B, - 0x1B, 0x17, 0xE2, 0x58, 0x3D, 0xA2, 0x37, 0xAB, 0x01, 0xBC, - 0xBF, 0x40, 0xCE, 0x53, 0x8C, 0x8E, 0xED, 0xEF, 0xEE, 0x59, - 0x9D, 0xE0, 0x63, 0xE6, 0x7C, 0x5E, 0xF5, 0x8E, 0x4B, 0xF1, - 0x3B, 0xC1, 0x02, 0x81, 0x80, 0x4D, 0x45, 0xF9, 0x40, 0x8C, - 0xC5, 0x5B, 0xF4, 0x2A, 0x1A, 0x8A, 0xB4, 0xF2, 0x1C, 0xAC, - 0x6B, 0xE9, 0x0C, 0x56, 0x36, 0xB7, 0x4E, 0x72, 0x96, 0xD5, - 0xE5, 0x8A, 0xD2, 0xE2, 0xFF, 0xF1, 0xF1, 0x18, 0x13, 0x3D, - 0x86, 0x09, 0xB8, 0xD8, 0x76, 0xA7, 0xC9, 0x1C, 0x71, 0x52, - 0x94, 0x30, 0x43, 0xE0, 0xF1, 0x78, 0x74, 0xFD, 0x61, 0x1B, - 0x4C, 0x09, 0xCC, 0xE6, 0x68, 0x2A, 0x71, 0xAD, 0x1C, 0xDF, - 0x43, 0xBC, 0x56, 0xDB, 0xA5, 0xA4, 0xBE, 0x35, 0x70, 0xA4, - 0x5E, 0xCF, 0x4F, 0xFC, 0x00, 0x55, 0x99, 0x3A, 0x3D, 0x23, - 0xCF, 0x67, 0x5A, 0xF5, 0x22, 0xF8, 0xB5, 0x29, 0xD0, 0x44, - 0x11, 0xEB, 0x35, 0x2E, 0x46, 0xBE, 0xFD, 0x8E, 0x18, 0xB2, - 0x5F, 0xA8, 0xBF, 0x19, 0x32, 0xA1, 0xF5, 0xDC, 0x03, 0xE6, - 0x7C, 0x9A, 0x1F, 0x0C, 0x7C, 0xA9, 0xB0, 0x0E, 0x21, 0x37, - 0x3B, 0xF1, 0xB0 + 0x30, 0x82, 0x04, 0xA5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xC0, 0x95, 0x08, 0xE1, 0x57, 0x41, 0xF2, 0x71, + 0x6D, 0xB7, 0xD2, 0x45, 0x41, 0x27, 0x01, 0x65, 0xC6, 0x45, + 0xAE, 0xF2, 0xBC, 0x24, 0x30, 0xB8, 0x95, 0xCE, 0x2F, 0x4E, + 0xD6, 0xF6, 0x1C, 0x88, 0xBC, 0x7C, 0x9F, 0xFB, 0xA8, 0x67, + 0x7F, 0xFE, 0x5C, 0x9C, 0x51, 0x75, 0xF7, 0x8A, 0xCA, 0x07, + 0xE7, 0x35, 0x2F, 0x8F, 0xE1, 0xBD, 0x7B, 0xC0, 0x2F, 0x7C, + 0xAB, 0x64, 0xA8, 0x17, 0xFC, 0xCA, 0x5D, 0x7B, 0xBA, 0xE0, + 0x21, 0xE5, 0x72, 0x2E, 0x6F, 0x2E, 0x86, 0xD8, 0x95, 0x73, + 0xDA, 0xAC, 0x1B, 0x53, 0xB9, 0x5F, 0x3F, 0xD7, 0x19, 0x0D, + 0x25, 0x4F, 0xE1, 0x63, 0x63, 0x51, 0x8B, 0x0B, 0x64, 0x3F, + 0xAD, 0x43, 0xB8, 0xA5, 0x1C, 0x5C, 0x34, 0xB3, 0xAE, 0x00, + 0xA0, 0x63, 0xC5, 0xF6, 0x7F, 0x0B, 0x59, 0x68, 0x78, 0x73, + 0xA6, 0x8C, 0x18, 0xA9, 0x02, 0x6D, 0xAF, 0xC3, 0x19, 0x01, + 0x2E, 0xB8, 0x10, 0xE3, 0xC6, 0xCC, 0x40, 0xB4, 0x69, 0xA3, + 0x46, 0x33, 0x69, 0x87, 0x6E, 0xC4, 0xBB, 0x17, 0xA6, 0xF3, + 0xE8, 0xDD, 0xAD, 0x73, 0xBC, 0x7B, 0x2F, 0x21, 0xB5, 0xFD, + 0x66, 0x51, 0x0C, 0xBD, 0x54, 0xB3, 0xE1, 0x6D, 0x5F, 0x1C, + 0xBC, 0x23, 0x73, 0xD1, 0x09, 0x03, 0x89, 0x14, 0xD2, 0x10, + 0xB9, 0x64, 0xC3, 0x2A, 0xD0, 0xA1, 0x96, 0x4A, 0xBC, 0xE1, + 0xD4, 0x1A, 0x5B, 0xC7, 0xA0, 0xC0, 0xC1, 0x63, 0x78, 0x0F, + 0x44, 0x37, 0x30, 0x32, 0x96, 0x80, 0x32, 0x23, 0x95, 0xA1, + 0x77, 0xBA, 0x13, 0xD2, 0x97, 0x73, 0xE2, 0x5D, 0x25, 0xC9, + 0x6A, 0x0D, 0xC3, 0x39, 0x60, 0xA4, 0xB4, 0xB0, 0x69, 0x42, + 0x42, 0x09, 0xE9, 0xD8, 0x08, 0xBC, 0x33, 0x20, 0xB3, 0x58, + 0x22, 0xA7, 0xAA, 0xEB, 0xC4, 0xE1, 0xE6, 0x61, 0x83, 0xC5, + 0xD2, 0x96, 0xDF, 0xD9, 0xD0, 0x4F, 0xAD, 0xD7, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9A, 0xD0, + 0x34, 0x0F, 0x52, 0x62, 0x05, 0x50, 0x01, 0xEF, 0x9F, 0xED, + 0x64, 0x6E, 0xC2, 0xC4, 0xDA, 0x1A, 0xF2, 0x84, 0xD7, 0x92, + 0x10, 0x48, 0x92, 0xC4, 0xE9, 0x6A, 0xEB, 0x8B, 0x75, 0x6C, + 0xC6, 0x79, 0x38, 0xF2, 0xC9, 0x72, 0x4A, 0x86, 0x64, 0x54, + 0x95, 0x77, 0xCB, 0xC3, 0x9A, 0x9D, 0xB7, 0xD4, 0x1D, 0xA4, + 0x00, 0xC8, 0x9E, 0x4E, 0xE4, 0xDD, 0xC7, 0xBA, 0x67, 0x16, + 0xC1, 0x74, 0xBC, 0xA9, 0xD6, 0x94, 0x8F, 0x2B, 0x30, 0x1A, + 0xFB, 0xED, 0xDF, 0x21, 0x05, 0x23, 0xD9, 0x4A, 0x39, 0xBD, + 0x98, 0x6B, 0x65, 0x9A, 0xB8, 0xDC, 0xC4, 0x7D, 0xEE, 0xA6, + 0x43, 0x15, 0x2E, 0x3D, 0xBE, 0x1D, 0x22, 0x60, 0x2A, 0x73, + 0x30, 0xD5, 0x3E, 0xD8, 0xA2, 0xAC, 0x86, 0x43, 0x2E, 0xC4, + 0xF5, 0x64, 0x5E, 0x3F, 0x89, 0x75, 0x0F, 0x11, 0xD8, 0x51, + 0x25, 0x4E, 0x9F, 0xD8, 0xAA, 0xA3, 0xCE, 0x60, 0xB3, 0xE2, + 0x8A, 0xD9, 0x7E, 0x1B, 0xF0, 0x64, 0xCA, 0x9A, 0x5B, 0x05, + 0x0B, 0x5B, 0xAA, 0xCB, 0xE5, 0xE3, 0x3F, 0x6E, 0x32, 0x22, + 0x05, 0xF3, 0xD0, 0xFA, 0xEF, 0x74, 0x52, 0x81, 0xE2, 0x5F, + 0x74, 0xD3, 0xBD, 0xFF, 0x31, 0x83, 0x45, 0x75, 0xFA, 0x63, + 0x7A, 0x97, 0x2E, 0xD6, 0xB6, 0x19, 0xC6, 0x92, 0x26, 0xE4, + 0x28, 0x06, 0x50, 0x50, 0x0E, 0x78, 0x2E, 0xA9, 0x78, 0x0D, + 0x14, 0x97, 0xB4, 0x12, 0xD8, 0x31, 0x40, 0xAB, 0xA1, 0x01, + 0x41, 0xC2, 0x30, 0xF8, 0x07, 0x5F, 0x16, 0xE4, 0x61, 0x77, + 0xD2, 0x60, 0xF2, 0x9F, 0x8D, 0xE8, 0xF4, 0xBA, 0xEB, 0x63, + 0xDE, 0x2A, 0x97, 0x81, 0xEF, 0x4C, 0x6C, 0xE6, 0x55, 0x34, + 0x51, 0x2B, 0x28, 0x34, 0xF4, 0x53, 0x1C, 0xC4, 0x58, 0x0A, + 0x3F, 0xBB, 0xAF, 0xB5, 0xF7, 0x4A, 0x85, 0x43, 0x2D, 0x3C, + 0xF1, 0x58, 0x58, 0x81, 0x02, 0x81, 0x81, 0x00, 0xF2, 0x2C, + 0x54, 0x76, 0x39, 0x23, 0x63, 0xC9, 0x10, 0x32, 0xB7, 0x93, + 0xAD, 0xAF, 0xBE, 0x19, 0x75, 0x96, 0x81, 0x64, 0xE6, 0xB5, + 0xB8, 0x89, 0x42, 0x41, 0xD1, 0x6D, 0xD0, 0x1C, 0x1B, 0xF8, + 0x1B, 0xAC, 0x69, 0xCB, 0x36, 0x3C, 0x64, 0x7D, 0xDC, 0xF4, + 0x19, 0xB8, 0xC3, 0x60, 0xB1, 0x57, 0x48, 0x5F, 0x52, 0x4F, + 0x59, 0x3A, 0x55, 0x7F, 0x32, 0xC0, 0x19, 0x43, 0x50, 0x3F, + 0xAE, 0xCE, 0x6F, 0x17, 0xF3, 0x0E, 0x9F, 0x40, 0xCA, 0x4E, + 0xAD, 0x15, 0x3B, 0xC9, 0x79, 0xE9, 0xC0, 0x59, 0x38, 0x73, + 0x70, 0x9C, 0x0A, 0x7C, 0xC9, 0x3A, 0x48, 0x32, 0xA7, 0xD8, + 0x49, 0x75, 0x0A, 0x85, 0xC2, 0xC2, 0xFD, 0x15, 0x73, 0xDA, + 0x99, 0x09, 0x2A, 0x69, 0x9A, 0x9F, 0x0A, 0x71, 0xBF, 0xB0, + 0x04, 0xA6, 0x8C, 0x7A, 0x5A, 0x6F, 0x48, 0x5A, 0x54, 0x3B, + 0xC6, 0xB1, 0x53, 0x17, 0xDF, 0xE7, 0x02, 0x81, 0x81, 0x00, + 0xCB, 0x93, 0xDE, 0x77, 0x15, 0x5D, 0xB7, 0x5C, 0x5C, 0x7C, + 0xD8, 0x90, 0xA9, 0x98, 0x2D, 0xD6, 0x69, 0x0E, 0x63, 0xB3, + 0xA3, 0xDC, 0xA6, 0xCC, 0x8B, 0x6A, 0xA4, 0xA2, 0x12, 0x8C, + 0x8E, 0x7B, 0x48, 0x2C, 0xB2, 0x4B, 0x37, 0xDC, 0x06, 0x18, + 0x7D, 0xEA, 0xFE, 0x76, 0xA1, 0xD4, 0xA1, 0xE9, 0x3F, 0x0D, + 0xCD, 0x1B, 0x5F, 0xAF, 0x5F, 0x9E, 0x96, 0x5B, 0x5B, 0x0F, + 0xA1, 0x7C, 0xAF, 0xB3, 0x9B, 0x90, 0xDB, 0x57, 0x73, 0x3A, + 0xED, 0xB0, 0x23, 0x44, 0xAE, 0x41, 0x4F, 0x1F, 0x07, 0x42, + 0x13, 0x23, 0x4C, 0xCB, 0xFA, 0xF4, 0x14, 0xA4, 0xD5, 0xF7, + 0x9E, 0x36, 0x7C, 0x5B, 0x9F, 0xA8, 0x3C, 0xC1, 0x85, 0x5F, + 0x74, 0xD2, 0x39, 0x2D, 0xFF, 0xD0, 0x84, 0xDF, 0xFB, 0xB3, + 0x20, 0x7A, 0x2E, 0x9B, 0x17, 0xAE, 0xE6, 0xBA, 0x0B, 0xAE, + 0x5F, 0x53, 0xA4, 0x52, 0xED, 0x1B, 0xC4, 0x91, 0x02, 0x81, + 0x81, 0x00, 0xEC, 0x98, 0xDA, 0xBB, 0xD5, 0xFE, 0xF9, 0x52, + 0x4A, 0x7D, 0x02, 0x55, 0x49, 0x6F, 0x55, 0x6E, 0x52, 0x2F, + 0x84, 0xA3, 0x2B, 0xB3, 0x86, 0x62, 0xB3, 0x54, 0xD2, 0x63, + 0x52, 0xDA, 0xE3, 0x88, 0x76, 0xA0, 0xEF, 0x8B, 0x15, 0xA5, + 0xD3, 0x18, 0x14, 0x72, 0x77, 0x5E, 0xC7, 0xA3, 0x04, 0x1F, + 0x9E, 0x19, 0x62, 0xB5, 0x1B, 0x1B, 0x9E, 0xC3, 0xF2, 0xB5, + 0x32, 0xF9, 0x4C, 0xC1, 0xAA, 0xEB, 0x0C, 0x26, 0x7D, 0xD4, + 0x5F, 0x4A, 0x51, 0x5C, 0xA4, 0x45, 0x06, 0x70, 0x44, 0xA7, + 0x56, 0xC0, 0xD4, 0x22, 0x14, 0x76, 0x9E, 0xD8, 0x63, 0x50, + 0x89, 0x90, 0xD3, 0xE2, 0xBF, 0x81, 0x95, 0x92, 0x31, 0x41, + 0x87, 0x39, 0x1A, 0x43, 0x0B, 0x18, 0xA5, 0x53, 0x1F, 0x39, + 0x1A, 0x5F, 0x1F, 0x43, 0xBC, 0x87, 0x6A, 0xDF, 0x6E, 0xD3, + 0x22, 0x00, 0xFE, 0x22, 0x98, 0x70, 0x4E, 0x1A, 0x19, 0x29, + 0x02, 0x81, 0x81, 0x00, 0x8A, 0x41, 0x56, 0x28, 0x51, 0x9E, + 0x5F, 0xD4, 0x9E, 0x0B, 0x3B, 0x98, 0xA3, 0x54, 0xF2, 0x6C, + 0x56, 0xD4, 0xAA, 0xE9, 0x69, 0x33, 0x85, 0x24, 0x0C, 0xDA, + 0xD4, 0x0C, 0x2D, 0xC4, 0xBF, 0x4F, 0x02, 0x69, 0x38, 0x7C, + 0xD4, 0xE6, 0xDC, 0x4C, 0xED, 0xD7, 0x16, 0x11, 0xC3, 0x3E, + 0x00, 0xE7, 0xC3, 0x26, 0xC0, 0x51, 0x02, 0xDE, 0xBB, 0x75, + 0x9C, 0x6F, 0x56, 0x9C, 0x7A, 0xF3, 0x8E, 0xEF, 0xCF, 0x8A, + 0xC5, 0x2B, 0xD2, 0xDA, 0x06, 0x6A, 0x44, 0xC9, 0x73, 0xFE, + 0x6E, 0x99, 0x87, 0xF8, 0x5B, 0xBE, 0xF1, 0x7C, 0xE6, 0x65, + 0xB5, 0x4F, 0x6C, 0xF0, 0xC9, 0xC5, 0xFF, 0x16, 0xCA, 0x8B, + 0x1B, 0x17, 0xE2, 0x58, 0x3D, 0xA2, 0x37, 0xAB, 0x01, 0xBC, + 0xBF, 0x40, 0xCE, 0x53, 0x8C, 0x8E, 0xED, 0xEF, 0xEE, 0x59, + 0x9D, 0xE0, 0x63, 0xE6, 0x7C, 0x5E, 0xF5, 0x8E, 0x4B, 0xF1, + 0x3B, 0xC1, 0x02, 0x81, 0x80, 0x4D, 0x45, 0xF9, 0x40, 0x8C, + 0xC5, 0x5B, 0xF4, 0x2A, 0x1A, 0x8A, 0xB4, 0xF2, 0x1C, 0xAC, + 0x6B, 0xE9, 0x0C, 0x56, 0x36, 0xB7, 0x4E, 0x72, 0x96, 0xD5, + 0xE5, 0x8A, 0xD2, 0xE2, 0xFF, 0xF1, 0xF1, 0x18, 0x13, 0x3D, + 0x86, 0x09, 0xB8, 0xD8, 0x76, 0xA7, 0xC9, 0x1C, 0x71, 0x52, + 0x94, 0x30, 0x43, 0xE0, 0xF1, 0x78, 0x74, 0xFD, 0x61, 0x1B, + 0x4C, 0x09, 0xCC, 0xE6, 0x68, 0x2A, 0x71, 0xAD, 0x1C, 0xDF, + 0x43, 0xBC, 0x56, 0xDB, 0xA5, 0xA4, 0xBE, 0x35, 0x70, 0xA4, + 0x5E, 0xCF, 0x4F, 0xFC, 0x00, 0x55, 0x99, 0x3A, 0x3D, 0x23, + 0xCF, 0x67, 0x5A, 0xF5, 0x22, 0xF8, 0xB5, 0x29, 0xD0, 0x44, + 0x11, 0xEB, 0x35, 0x2E, 0x46, 0xBE, 0xFD, 0x8E, 0x18, 0xB2, + 0x5F, 0xA8, 0xBF, 0x19, 0x32, 0xA1, 0xF5, 0xDC, 0x03, 0xE6, + 0x7C, 0x9A, 0x1F, 0x0C, 0x7C, 0xA9, 0xB0, 0x0E, 0x21, 0x37, + 0x3B, 0xF1, 0xB0 }; static const int sizeof_server_key_der_2048 = sizeof(server_key_der_2048); /* ./certs/server-cert.der, 2048-bit */ static const unsigned char server_cert_der_2048[] = { - 0x30, 0x82, 0x04, 0x9E, 0x30, 0x82, 0x03, 0x86, 0xA0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, - 0x00, 0x30, 0x81, 0x94, 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, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, - 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, - 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, - 0x69, 0x6E, 0x67, 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, 0x35, 0x30, 0x35, - 0x30, 0x37, 0x31, 0x38, 0x32, 0x31, 0x30, 0x31, 0x5A, 0x17, - 0x0D, 0x31, 0x38, 0x30, 0x31, 0x33, 0x31, 0x31, 0x38, 0x32, - 0x31, 0x30, 0x31, 0x5A, 0x30, 0x81, 0x90, 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, 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, 0x53, 0x75, 0x70, 0x70, 0x6F, - 0x72, 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, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, - 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, - 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, - 0x82, 0x01, 0x01, 0x00, 0xC0, 0x95, 0x08, 0xE1, 0x57, 0x41, - 0xF2, 0x71, 0x6D, 0xB7, 0xD2, 0x45, 0x41, 0x27, 0x01, 0x65, - 0xC6, 0x45, 0xAE, 0xF2, 0xBC, 0x24, 0x30, 0xB8, 0x95, 0xCE, - 0x2F, 0x4E, 0xD6, 0xF6, 0x1C, 0x88, 0xBC, 0x7C, 0x9F, 0xFB, - 0xA8, 0x67, 0x7F, 0xFE, 0x5C, 0x9C, 0x51, 0x75, 0xF7, 0x8A, - 0xCA, 0x07, 0xE7, 0x35, 0x2F, 0x8F, 0xE1, 0xBD, 0x7B, 0xC0, - 0x2F, 0x7C, 0xAB, 0x64, 0xA8, 0x17, 0xFC, 0xCA, 0x5D, 0x7B, - 0xBA, 0xE0, 0x21, 0xE5, 0x72, 0x2E, 0x6F, 0x2E, 0x86, 0xD8, - 0x95, 0x73, 0xDA, 0xAC, 0x1B, 0x53, 0xB9, 0x5F, 0x3F, 0xD7, - 0x19, 0x0D, 0x25, 0x4F, 0xE1, 0x63, 0x63, 0x51, 0x8B, 0x0B, - 0x64, 0x3F, 0xAD, 0x43, 0xB8, 0xA5, 0x1C, 0x5C, 0x34, 0xB3, - 0xAE, 0x00, 0xA0, 0x63, 0xC5, 0xF6, 0x7F, 0x0B, 0x59, 0x68, - 0x78, 0x73, 0xA6, 0x8C, 0x18, 0xA9, 0x02, 0x6D, 0xAF, 0xC3, - 0x19, 0x01, 0x2E, 0xB8, 0x10, 0xE3, 0xC6, 0xCC, 0x40, 0xB4, - 0x69, 0xA3, 0x46, 0x33, 0x69, 0x87, 0x6E, 0xC4, 0xBB, 0x17, - 0xA6, 0xF3, 0xE8, 0xDD, 0xAD, 0x73, 0xBC, 0x7B, 0x2F, 0x21, - 0xB5, 0xFD, 0x66, 0x51, 0x0C, 0xBD, 0x54, 0xB3, 0xE1, 0x6D, - 0x5F, 0x1C, 0xBC, 0x23, 0x73, 0xD1, 0x09, 0x03, 0x89, 0x14, - 0xD2, 0x10, 0xB9, 0x64, 0xC3, 0x2A, 0xD0, 0xA1, 0x96, 0x4A, - 0xBC, 0xE1, 0xD4, 0x1A, 0x5B, 0xC7, 0xA0, 0xC0, 0xC1, 0x63, - 0x78, 0x0F, 0x44, 0x37, 0x30, 0x32, 0x96, 0x80, 0x32, 0x23, - 0x95, 0xA1, 0x77, 0xBA, 0x13, 0xD2, 0x97, 0x73, 0xE2, 0x5D, - 0x25, 0xC9, 0x6A, 0x0D, 0xC3, 0x39, 0x60, 0xA4, 0xB4, 0xB0, - 0x69, 0x42, 0x42, 0x09, 0xE9, 0xD8, 0x08, 0xBC, 0x33, 0x20, - 0xB3, 0x58, 0x22, 0xA7, 0xAA, 0xEB, 0xC4, 0xE1, 0xE6, 0x61, - 0x83, 0xC5, 0xD2, 0x96, 0xDF, 0xD9, 0xD0, 0x4F, 0xAD, 0xD7, - 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x81, 0xFC, 0x30, 0x81, - 0xF9, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, - 0x04, 0x14, 0xB3, 0x11, 0x32, 0xC9, 0x92, 0x98, 0x84, 0xE2, - 0xC9, 0xF8, 0xD0, 0x3B, 0x6E, 0x03, 0x42, 0xCA, 0x1F, 0x0E, - 0x8E, 0x3C, 0x30, 0x81, 0xC9, 0x06, 0x03, 0x55, 0x1D, 0x23, - 0x04, 0x81, 0xC1, 0x30, 0x81, 0xBE, 0x80, 0x14, 0x27, 0x8E, - 0x67, 0x11, 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, 0x33, 0x63, - 0xB3, 0xA4, 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, 0xA1, 0x81, - 0x9A, 0xA4, 0x81, 0x97, 0x30, 0x81, 0x94, 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, 0x11, 0x30, 0x0F, - 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, - 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, - 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 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, 0xD9, 0x80, - 0x3A, 0xC3, 0xD2, 0xF4, 0xDA, 0x37, 0x30, 0x0C, 0x06, 0x03, - 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, - 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, - 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, - 0x67, 0xC0, 0x2C, 0xA9, 0x43, 0x47, 0xE7, 0x11, 0x14, 0x77, - 0xAE, 0xCC, 0xD8, 0xE0, 0x6B, 0x23, 0x82, 0x91, 0x63, 0xE8, - 0xA8, 0x0D, 0x21, 0xC5, 0xC8, 0x47, 0x97, 0x2F, 0xD5, 0xF3, - 0x86, 0xFB, 0x6C, 0xCE, 0x25, 0xF9, 0x7C, 0x78, 0xC8, 0x3A, - 0x22, 0x68, 0xF2, 0x16, 0x1E, 0xD2, 0xD2, 0x3F, 0x24, 0x04, - 0x87, 0xF2, 0xB7, 0xC1, 0x62, 0x63, 0xBA, 0xC5, 0xFA, 0xAE, - 0xD2, 0x20, 0x81, 0x1A, 0xD2, 0x0C, 0xAE, 0x26, 0x6B, 0x1B, - 0x2B, 0x10, 0xD3, 0xE1, 0x9A, 0x4E, 0x64, 0x6C, 0x97, 0xDB, - 0x36, 0xA8, 0x8F, 0xF8, 0x05, 0x63, 0xBF, 0xBA, 0x0D, 0x88, - 0x0B, 0x87, 0x46, 0xC9, 0xE4, 0x64, 0xE3, 0xD7, 0xBD, 0xB8, - 0x2D, 0xD5, 0xC1, 0xC3, 0xC4, 0xDB, 0x55, 0x68, 0xDC, 0xA3, - 0x7A, 0x40, 0xB9, 0xA9, 0xF6, 0x04, 0x4A, 0x22, 0xCF, 0x98, - 0x76, 0x1C, 0xE4, 0xA3, 0xFF, 0x79, 0x19, 0x96, 0x57, 0x63, - 0x07, 0x6F, 0xF6, 0x32, 0x77, 0x16, 0x50, 0x9B, 0xE3, 0x34, - 0x18, 0xD4, 0xEB, 0xBE, 0xFD, 0xB6, 0x6F, 0xE3, 0xC7, 0xF6, - 0x85, 0xBF, 0xAC, 0x32, 0xAD, 0x98, 0x57, 0xBE, 0x13, 0x92, - 0x44, 0x10, 0xA5, 0xF3, 0xAE, 0xE2, 0x66, 0xDA, 0x44, 0xA9, - 0x94, 0x71, 0x3F, 0xD0, 0x2F, 0x20, 0x59, 0x87, 0xE4, 0x5A, - 0x40, 0xEE, 0xD2, 0xE4, 0x0C, 0xCE, 0x25, 0x94, 0xDC, 0x0F, - 0xFE, 0x38, 0xE0, 0x41, 0x52, 0x34, 0x5C, 0xBB, 0xC3, 0xDB, - 0xC1, 0x5F, 0x76, 0xC3, 0x5D, 0x0E, 0x32, 0x69, 0x2B, 0x9D, - 0x01, 0xED, 0x50, 0x1B, 0x4F, 0x77, 0xA9, 0xA9, 0xD8, 0x71, - 0x30, 0xCB, 0x2E, 0x2C, 0x70, 0x00, 0xAB, 0x78, 0x4B, 0xD7, - 0x15, 0xD9, 0x17, 0xF8, 0x64, 0xB2, 0xF7, 0x3A, 0xDA, 0xE1, - 0x0B, 0x8B, 0x0A, 0xE1, 0x4E, 0xB1, 0x03, 0x46, 0x14, 0xCA, - 0x94, 0xE3, 0x44, 0x77, 0xD7, 0x59 + 0x30, 0x82, 0x04, 0x9E, 0x30, 0x82, 0x03, 0x86, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x30, 0x81, 0x94, 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, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, + 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, + 0x69, 0x6E, 0x67, 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, 0x38, 0x30, 0x34, + 0x31, 0x33, 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x17, + 0x0D, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, + 0x33, 0x31, 0x30, 0x5A, 0x30, 0x81, 0x90, 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, 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, 0x53, 0x75, 0x70, 0x70, 0x6F, + 0x72, 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, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, + 0x82, 0x01, 0x01, 0x00, 0xC0, 0x95, 0x08, 0xE1, 0x57, 0x41, + 0xF2, 0x71, 0x6D, 0xB7, 0xD2, 0x45, 0x41, 0x27, 0x01, 0x65, + 0xC6, 0x45, 0xAE, 0xF2, 0xBC, 0x24, 0x30, 0xB8, 0x95, 0xCE, + 0x2F, 0x4E, 0xD6, 0xF6, 0x1C, 0x88, 0xBC, 0x7C, 0x9F, 0xFB, + 0xA8, 0x67, 0x7F, 0xFE, 0x5C, 0x9C, 0x51, 0x75, 0xF7, 0x8A, + 0xCA, 0x07, 0xE7, 0x35, 0x2F, 0x8F, 0xE1, 0xBD, 0x7B, 0xC0, + 0x2F, 0x7C, 0xAB, 0x64, 0xA8, 0x17, 0xFC, 0xCA, 0x5D, 0x7B, + 0xBA, 0xE0, 0x21, 0xE5, 0x72, 0x2E, 0x6F, 0x2E, 0x86, 0xD8, + 0x95, 0x73, 0xDA, 0xAC, 0x1B, 0x53, 0xB9, 0x5F, 0x3F, 0xD7, + 0x19, 0x0D, 0x25, 0x4F, 0xE1, 0x63, 0x63, 0x51, 0x8B, 0x0B, + 0x64, 0x3F, 0xAD, 0x43, 0xB8, 0xA5, 0x1C, 0x5C, 0x34, 0xB3, + 0xAE, 0x00, 0xA0, 0x63, 0xC5, 0xF6, 0x7F, 0x0B, 0x59, 0x68, + 0x78, 0x73, 0xA6, 0x8C, 0x18, 0xA9, 0x02, 0x6D, 0xAF, 0xC3, + 0x19, 0x01, 0x2E, 0xB8, 0x10, 0xE3, 0xC6, 0xCC, 0x40, 0xB4, + 0x69, 0xA3, 0x46, 0x33, 0x69, 0x87, 0x6E, 0xC4, 0xBB, 0x17, + 0xA6, 0xF3, 0xE8, 0xDD, 0xAD, 0x73, 0xBC, 0x7B, 0x2F, 0x21, + 0xB5, 0xFD, 0x66, 0x51, 0x0C, 0xBD, 0x54, 0xB3, 0xE1, 0x6D, + 0x5F, 0x1C, 0xBC, 0x23, 0x73, 0xD1, 0x09, 0x03, 0x89, 0x14, + 0xD2, 0x10, 0xB9, 0x64, 0xC3, 0x2A, 0xD0, 0xA1, 0x96, 0x4A, + 0xBC, 0xE1, 0xD4, 0x1A, 0x5B, 0xC7, 0xA0, 0xC0, 0xC1, 0x63, + 0x78, 0x0F, 0x44, 0x37, 0x30, 0x32, 0x96, 0x80, 0x32, 0x23, + 0x95, 0xA1, 0x77, 0xBA, 0x13, 0xD2, 0x97, 0x73, 0xE2, 0x5D, + 0x25, 0xC9, 0x6A, 0x0D, 0xC3, 0x39, 0x60, 0xA4, 0xB4, 0xB0, + 0x69, 0x42, 0x42, 0x09, 0xE9, 0xD8, 0x08, 0xBC, 0x33, 0x20, + 0xB3, 0x58, 0x22, 0xA7, 0xAA, 0xEB, 0xC4, 0xE1, 0xE6, 0x61, + 0x83, 0xC5, 0xD2, 0x96, 0xDF, 0xD9, 0xD0, 0x4F, 0xAD, 0xD7, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x81, 0xFC, 0x30, 0x81, + 0xF9, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, + 0x04, 0x14, 0xB3, 0x11, 0x32, 0xC9, 0x92, 0x98, 0x84, 0xE2, + 0xC9, 0xF8, 0xD0, 0x3B, 0x6E, 0x03, 0x42, 0xCA, 0x1F, 0x0E, + 0x8E, 0x3C, 0x30, 0x81, 0xC9, 0x06, 0x03, 0x55, 0x1D, 0x23, + 0x04, 0x81, 0xC1, 0x30, 0x81, 0xBE, 0x80, 0x14, 0x27, 0x8E, + 0x67, 0x11, 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, 0x33, 0x63, + 0xB3, 0xA4, 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, 0xA1, 0x81, + 0x9A, 0xA4, 0x81, 0x97, 0x30, 0x81, 0x94, 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, 0x11, 0x30, 0x0F, + 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, + 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, + 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 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, 0x86, 0xFF, + 0xF5, 0x8E, 0x10, 0xDE, 0xB8, 0xFB, 0x30, 0x0C, 0x06, 0x03, + 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, + 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, + 0xB4, 0x54, 0x60, 0xAD, 0xA0, 0x03, 0x32, 0xDE, 0x02, 0x7F, + 0x21, 0x4A, 0x81, 0xC6, 0xED, 0xCD, 0xCD, 0xD8, 0x12, 0x8A, + 0xC0, 0xBA, 0x82, 0x5B, 0x75, 0xAD, 0x54, 0xE3, 0x7C, 0x80, + 0x6A, 0xAC, 0x2E, 0x6C, 0x20, 0x4E, 0xBE, 0x4D, 0x82, 0xA7, + 0x47, 0x13, 0x5C, 0xF4, 0xC6, 0x6A, 0x2B, 0x10, 0x99, 0x58, + 0xDE, 0xAB, 0x6B, 0x7C, 0x22, 0x05, 0xC1, 0x83, 0x9D, 0xCB, + 0xFF, 0x3C, 0xE4, 0x2D, 0x57, 0x6A, 0xA6, 0x96, 0xDF, 0xD3, + 0xC1, 0x68, 0xE3, 0xD2, 0xC6, 0x83, 0x4B, 0x97, 0xE2, 0xC6, + 0x32, 0x0E, 0xBE, 0xC4, 0x03, 0xB9, 0x07, 0x8A, 0x5B, 0xB8, + 0x84, 0xBA, 0xC5, 0x39, 0x3F, 0x1C, 0x58, 0xA7, 0x55, 0xD7, + 0xF0, 0x9B, 0xE8, 0xD2, 0x45, 0xB9, 0xE3, 0x83, 0x2E, 0xEE, + 0xB6, 0x71, 0x56, 0xB9, 0x3A, 0xEE, 0x3F, 0x27, 0xD8, 0x77, + 0xE8, 0xFB, 0x44, 0x48, 0x65, 0x27, 0x47, 0x4C, 0xFB, 0xFE, + 0x72, 0xC3, 0xAC, 0x05, 0x7B, 0x1D, 0xCB, 0xEB, 0x5E, 0x65, + 0x9A, 0xAB, 0x02, 0xE4, 0x88, 0x5B, 0x3B, 0x8B, 0x0B, 0xC7, + 0xCC, 0xA9, 0xA6, 0x8B, 0xE1, 0x87, 0xB0, 0x19, 0x1A, 0x0C, + 0x28, 0x58, 0x6F, 0x99, 0x52, 0x7E, 0xED, 0xB0, 0x3A, 0x68, + 0x3B, 0x8C, 0x0A, 0x08, 0x74, 0x72, 0xAB, 0xB9, 0x09, 0xC5, + 0xED, 0x04, 0x7E, 0x6F, 0x0B, 0x1C, 0x09, 0x21, 0xD0, 0xCD, + 0x7F, 0xF9, 0xC4, 0x5E, 0x27, 0x20, 0xE4, 0x85, 0x73, 0x52, + 0x05, 0xD2, 0xBA, 0xF8, 0xD5, 0x8F, 0x41, 0xCC, 0x23, 0x2E, + 0x12, 0x6D, 0xBC, 0x31, 0x98, 0xE7, 0x63, 0xA3, 0x8E, 0x26, + 0xCD, 0xE8, 0x2B, 0x88, 0xEE, 0xE2, 0xFE, 0x3A, 0x74, 0x52, + 0x34, 0x0E, 0xFD, 0x12, 0xE5, 0x5E, 0x69, 0x50, 0x20, 0x31, + 0x34, 0xE4, 0x31, 0xF1, 0xE7, 0xE4, 0x5B, 0x03, 0x13, 0xDA, + 0xAC, 0x41, 0x6C, 0xE7, 0xCF, 0x2B }; static const int sizeof_server_cert_der_2048 = sizeof(server_cert_der_2048); -#endif /* USE_CERT_BUFFERS_1024 */ +#endif /* USE_CERT_BUFFERS_2048 */ + +#ifdef USE_CERT_BUFFERS_3072 + +/* ./certs/dh3072.der, 3072-bit */ +static const unsigned char dh_key_der_3072[] = +{ + 0x30, 0x82, 0x01, 0x88, 0x02, 0x82, 0x01, 0x81, 0x00, 0x89, + 0x1B, 0x75, 0x3F, 0x84, 0xB6, 0x11, 0xED, 0x21, 0xF1, 0x08, + 0x0F, 0xB8, 0x06, 0xC9, 0xA3, 0xC9, 0x41, 0xDB, 0x5A, 0xC8, + 0xF8, 0x82, 0x73, 0x0F, 0xEB, 0x89, 0x1E, 0x54, 0x18, 0xBE, + 0xE6, 0x48, 0x41, 0x9E, 0xFA, 0xC2, 0x0C, 0x50, 0x67, 0xC3, + 0x5D, 0xB5, 0xF5, 0x0F, 0x23, 0x6A, 0x43, 0x33, 0x91, 0xD9, + 0x40, 0xF3, 0x66, 0xC6, 0x99, 0xFF, 0x97, 0xB6, 0x7B, 0xAF, + 0x27, 0x72, 0x3B, 0x9F, 0x7E, 0x58, 0x18, 0x14, 0x9F, 0x91, + 0x6E, 0x2B, 0x11, 0xC1, 0x57, 0x49, 0x27, 0x36, 0x78, 0xE1, + 0x09, 0x68, 0x9C, 0x05, 0x5A, 0xAC, 0xE6, 0x00, 0x38, 0xBE, + 0x95, 0x74, 0x81, 0x53, 0x28, 0xF0, 0xAD, 0xDF, 0xB5, 0x87, + 0x1C, 0x72, 0x17, 0x4E, 0xEC, 0x00, 0x91, 0x22, 0xAA, 0xE4, + 0x88, 0xD7, 0xF5, 0x3D, 0x1F, 0x03, 0x13, 0x2D, 0x1C, 0xFB, + 0xDE, 0x59, 0x68, 0xAD, 0xE0, 0x17, 0xA1, 0xEE, 0x8D, 0xCC, + 0xBF, 0xFE, 0xCF, 0x24, 0x42, 0xED, 0x26, 0xDD, 0x29, 0xD0, + 0x4E, 0x62, 0x3C, 0x85, 0x36, 0x1B, 0x5F, 0x6A, 0x47, 0x88, + 0x21, 0xE5, 0x1B, 0x85, 0x0A, 0x2C, 0xE9, 0x2F, 0xE0, 0x20, + 0xFC, 0x1D, 0xCD, 0x55, 0x66, 0xF5, 0xAC, 0x32, 0x00, 0x8E, + 0xA3, 0xE9, 0xED, 0xFB, 0x35, 0xA7, 0xE6, 0x76, 0x53, 0x42, + 0xC6, 0x77, 0x77, 0xAB, 0x90, 0x99, 0x7C, 0xC2, 0xEC, 0xC9, + 0x18, 0x4A, 0x3C, 0xF4, 0x11, 0x75, 0x27, 0x83, 0xBD, 0x9E, + 0xC2, 0x8F, 0x23, 0xAB, 0x52, 0x46, 0xE2, 0x52, 0x5D, 0x9A, + 0x04, 0xC3, 0x15, 0x1F, 0x69, 0x9C, 0x72, 0x69, 0x59, 0x52, + 0xD4, 0x69, 0x3D, 0x19, 0x77, 0x36, 0x25, 0xAF, 0x07, 0x71, + 0x82, 0xDE, 0xB7, 0x24, 0x60, 0x82, 0x6A, 0x72, 0xBB, 0xED, + 0xB6, 0x76, 0xAE, 0x7E, 0xBC, 0x7D, 0x2F, 0x73, 0x4B, 0x04, + 0x16, 0xD5, 0xA4, 0xF3, 0x03, 0x26, 0xFB, 0xF3, 0xCD, 0x7B, + 0x77, 0x7E, 0x7C, 0x8D, 0x65, 0xAE, 0xA5, 0xDC, 0x6C, 0xE3, + 0x70, 0xD2, 0x29, 0x6B, 0xF2, 0xEB, 0x76, 0xC9, 0xE5, 0x46, + 0x18, 0x12, 0x57, 0xB0, 0x55, 0xA5, 0x7C, 0xCD, 0x41, 0x93, + 0x26, 0x99, 0xF7, 0xA5, 0xC5, 0x34, 0xBE, 0x59, 0x79, 0xDE, + 0x0A, 0x57, 0x5F, 0x21, 0xF8, 0x98, 0x52, 0xF0, 0x2F, 0x7B, + 0x57, 0xB6, 0x9D, 0xFC, 0x40, 0xA6, 0x55, 0xFB, 0xAF, 0xD9, + 0x16, 0x9B, 0x20, 0x4F, 0xA8, 0xA3, 0x0B, 0x04, 0x48, 0xE3, + 0x77, 0x22, 0xC4, 0xCC, 0x57, 0x14, 0x33, 0xA2, 0xF0, 0x9A, + 0xE3, 0x12, 0xBD, 0xFF, 0x72, 0x8B, 0xEE, 0x52, 0xF3, 0xC9, + 0x59, 0xC2, 0xA2, 0x6B, 0xA5, 0x75, 0x48, 0x51, 0x82, 0x0E, + 0x7A, 0xFF, 0xFE, 0x41, 0xCD, 0x7C, 0x63, 0xD2, 0x53, 0xA8, + 0x11, 0x03, 0xB9, 0x03, 0x07, 0xFE, 0x66, 0x38, 0x5F, 0xA2, + 0x3E, 0x9C, 0x1B, 0x02, 0x01, 0x02 +}; +static const int sizeof_dh_key_der_3072 = sizeof(dh_key_der_3072); + +/* ./certs/dsa3072.der, 3072-bit */ +static const unsigned char dsa_key_der_3072[] = +{ + 0x30, 0x82, 0x04, 0xD7, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x81, 0x00, 0xB5, 0xD0, 0x2F, 0x55, 0xC1, 0x27, 0x4C, 0x5B, + 0x28, 0x81, 0x4E, 0xA4, 0x32, 0x0D, 0x73, 0x54, 0x68, 0x4F, + 0x0A, 0x36, 0x68, 0x4A, 0x51, 0xBE, 0xDE, 0x49, 0xD4, 0x9D, + 0xCE, 0xC6, 0xF7, 0x01, 0x70, 0xD2, 0x88, 0x90, 0x1D, 0x60, + 0x30, 0x9B, 0x0A, 0x9C, 0x23, 0xDA, 0xE0, 0x74, 0x46, 0x5B, + 0xC7, 0x41, 0x40, 0x5C, 0xD9, 0x7A, 0xBE, 0x78, 0xCA, 0x49, + 0xF5, 0x2D, 0x7B, 0xD7, 0xBF, 0x67, 0x0D, 0x84, 0x28, 0xBB, + 0x9D, 0xC2, 0xAB, 0x23, 0x06, 0x28, 0x0C, 0x98, 0x46, 0x43, + 0xCE, 0x6F, 0x9E, 0xD0, 0xE9, 0x0E, 0xF3, 0x7E, 0x30, 0x5D, + 0xD3, 0x45, 0x44, 0x7B, 0x0C, 0x7A, 0x73, 0xA6, 0x95, 0x65, + 0xAA, 0x8B, 0xD8, 0x75, 0x6A, 0x11, 0xB3, 0x10, 0x7C, 0x57, + 0xAF, 0xCE, 0xBE, 0x5B, 0xF7, 0xC8, 0xFE, 0x42, 0xA3, 0x77, + 0xB7, 0x0B, 0x3D, 0x66, 0xB5, 0x08, 0x74, 0x22, 0x74, 0x26, + 0xE6, 0xDB, 0x8E, 0xEF, 0xA3, 0x99, 0xAE, 0x0B, 0x42, 0x8C, + 0x5F, 0x7E, 0x48, 0xE9, 0x19, 0x90, 0xA8, 0x35, 0xA9, 0xFC, + 0x48, 0x0D, 0xC8, 0xB8, 0xE4, 0x1A, 0x0C, 0x26, 0xC7, 0x1A, + 0x20, 0x02, 0xEB, 0x72, 0x2E, 0x94, 0xD6, 0x19, 0x34, 0x39, + 0x55, 0x4E, 0xFC, 0x53, 0x48, 0xD8, 0x10, 0x89, 0xA1, 0x6E, + 0x22, 0x39, 0x71, 0x15, 0xA6, 0x13, 0xBC, 0x77, 0x49, 0x53, + 0xCB, 0x16, 0x4B, 0x56, 0x3D, 0x08, 0xA2, 0x71, 0x0E, 0x06, + 0x0C, 0x3A, 0xDE, 0x82, 0xC0, 0xDF, 0xE7, 0x96, 0x57, 0xD7, + 0x3F, 0x6B, 0xF0, 0xAE, 0xD1, 0x38, 0xB8, 0x5B, 0x83, 0x77, + 0x8B, 0xEB, 0x2B, 0xDA, 0x38, 0xC8, 0x4C, 0xA9, 0x48, 0x52, + 0xD8, 0x41, 0x03, 0xD3, 0x11, 0x1C, 0x66, 0x9E, 0xDE, 0xC9, + 0x78, 0x5A, 0xE1, 0x7B, 0xEA, 0x6F, 0xD6, 0xCA, 0x6A, 0x2F, + 0x01, 0xB2, 0x83, 0x37, 0x25, 0xD9, 0x9C, 0xD4, 0xB0, 0x21, + 0xD9, 0x8F, 0xA6, 0xF8, 0xD6, 0x21, 0x82, 0xBB, 0x08, 0x64, + 0x28, 0x0E, 0x0C, 0x26, 0xE6, 0xA5, 0x69, 0xE0, 0x23, 0xE9, + 0xB3, 0xC4, 0xF9, 0xDE, 0xC6, 0xD6, 0x32, 0x00, 0x66, 0x9B, + 0x8A, 0x0B, 0x6F, 0xDE, 0xB8, 0xDD, 0x68, 0x7F, 0x9D, 0x68, + 0x59, 0x6B, 0x55, 0xD9, 0x53, 0x01, 0x7B, 0x1A, 0x1C, 0x8D, + 0xBF, 0xAF, 0xC0, 0xB1, 0x14, 0x9E, 0xC1, 0x8D, 0x3E, 0x1E, + 0xFB, 0x40, 0xF9, 0x6D, 0x48, 0x43, 0xCD, 0x6C, 0xE8, 0xBC, + 0x3C, 0x7C, 0x35, 0x3C, 0x65, 0x6D, 0xA0, 0x25, 0x87, 0xBF, + 0xEC, 0x9B, 0x12, 0x74, 0x48, 0xC8, 0xE4, 0xBF, 0x53, 0x53, + 0x47, 0x78, 0xD9, 0x9B, 0x1A, 0xA5, 0x07, 0x46, 0x15, 0x16, + 0xD2, 0x33, 0x93, 0xCC, 0x41, 0x9B, 0xB7, 0x22, 0xDF, 0x07, + 0xDD, 0x72, 0xC6, 0x1A, 0x9B, 0x92, 0xE7, 0x32, 0x04, 0xAB, + 0x94, 0x80, 0xBD, 0x58, 0xF2, 0x35, 0x02, 0x21, 0x00, 0x9A, + 0xDD, 0x98, 0x1A, 0x6F, 0xEA, 0xB5, 0x8B, 0xC9, 0x68, 0x18, + 0x81, 0xE4, 0x4C, 0xFD, 0x8E, 0x45, 0xCF, 0x5F, 0x0E, 0x62, + 0x1E, 0x7D, 0x2D, 0x4A, 0x4C, 0x5D, 0x7F, 0xF8, 0xD8, 0x52, + 0xD7, 0x02, 0x82, 0x01, 0x81, 0x00, 0x84, 0xDF, 0xAB, 0x91, + 0x61, 0xE4, 0x2B, 0x07, 0x0A, 0x1C, 0xC7, 0x9C, 0xD7, 0xAC, + 0x8D, 0xA5, 0xAA, 0x41, 0x65, 0x9E, 0x4A, 0xED, 0x21, 0x45, + 0x96, 0xF7, 0xF7, 0xCB, 0x7A, 0x88, 0x19, 0x0F, 0x36, 0x80, + 0x25, 0x2F, 0x23, 0x0D, 0xFF, 0x6C, 0x0D, 0x02, 0xBB, 0x6A, + 0x79, 0x6A, 0xCB, 0x05, 0x00, 0x9B, 0x77, 0xED, 0x6B, 0xF3, + 0xC2, 0xEA, 0x1A, 0xDF, 0xB8, 0x15, 0xA8, 0x92, 0x19, 0x5A, + 0x51, 0x3B, 0x76, 0x06, 0x98, 0x47, 0xC7, 0x6F, 0x76, 0x99, + 0xAD, 0x50, 0xC5, 0x98, 0xE7, 0xFF, 0x88, 0xBC, 0x49, 0x77, + 0xEF, 0x96, 0x75, 0xE2, 0x36, 0x66, 0x1F, 0x0C, 0xFA, 0x57, + 0x1E, 0x11, 0xFF, 0x8F, 0x3C, 0xD0, 0xEA, 0x97, 0x25, 0x3F, + 0xFA, 0xD1, 0x4F, 0xBA, 0xDF, 0xE3, 0x35, 0xFB, 0x6E, 0x5C, + 0x65, 0xF9, 0xA2, 0x26, 0x43, 0xF2, 0xF4, 0xE0, 0x05, 0x3D, + 0xC6, 0x5B, 0xC4, 0x21, 0xE7, 0xB1, 0x02, 0xEB, 0xF2, 0xA9, + 0x06, 0x5E, 0xB7, 0x1B, 0xC1, 0xD8, 0x86, 0x34, 0xED, 0x84, + 0x89, 0xCE, 0xCE, 0xC2, 0x63, 0x78, 0x67, 0xF8, 0xC3, 0xAA, + 0x7C, 0x1C, 0x59, 0x32, 0xE4, 0x77, 0xA2, 0x36, 0x31, 0xFE, + 0x4B, 0x9C, 0x98, 0xCE, 0x01, 0x55, 0x61, 0xCE, 0x23, 0xAE, + 0x0F, 0x7E, 0x24, 0x8B, 0x54, 0x8A, 0xE4, 0xCB, 0x8E, 0xDC, + 0x7A, 0x94, 0x4C, 0xF9, 0x3C, 0xF8, 0x67, 0x68, 0x9D, 0x7A, + 0x82, 0xA1, 0xA0, 0x01, 0xC7, 0x1B, 0x8D, 0xA0, 0xC0, 0x53, + 0x1E, 0x93, 0xC7, 0x86, 0x12, 0xD3, 0x16, 0xDC, 0x28, 0xA0, + 0xD1, 0x0D, 0x1E, 0x42, 0x9A, 0xCB, 0x55, 0x8C, 0x22, 0x7F, + 0x41, 0xC3, 0xC9, 0x14, 0xF2, 0xB0, 0x73, 0xA1, 0x4D, 0x72, + 0xFD, 0x88, 0xB6, 0xDE, 0xE5, 0xF0, 0x3C, 0x3A, 0x7E, 0x68, + 0x3E, 0x82, 0x58, 0x60, 0xCD, 0xB4, 0x08, 0x64, 0x18, 0xB2, + 0x24, 0x97, 0x13, 0xA6, 0x07, 0x75, 0xBE, 0xE0, 0x14, 0x92, + 0x9A, 0x98, 0x6C, 0x08, 0x94, 0xD1, 0x0D, 0x48, 0x44, 0xC3, + 0xE3, 0xD5, 0xC0, 0x93, 0x49, 0x79, 0x2F, 0x67, 0x15, 0x76, + 0xD8, 0x90, 0x11, 0xDB, 0xEC, 0xA7, 0xE2, 0xDB, 0xD4, 0x4F, + 0x49, 0x5E, 0xEF, 0xC5, 0xB9, 0x77, 0x69, 0xDA, 0x02, 0xB7, + 0x23, 0xBC, 0xEA, 0xDC, 0x84, 0xD4, 0xA5, 0x5C, 0xA2, 0x6C, + 0xAD, 0x4A, 0x9F, 0xF0, 0x65, 0x48, 0xE9, 0xBF, 0xDF, 0xA5, + 0xB3, 0x99, 0xD6, 0x76, 0x08, 0x87, 0x2C, 0xF2, 0x29, 0x79, + 0xB2, 0x20, 0x7C, 0x6F, 0xC1, 0xC5, 0x3C, 0xB0, 0x50, 0x3F, + 0x72, 0xA5, 0x57, 0xE3, 0xB0, 0x62, 0x18, 0x80, 0x71, 0xB9, + 0x3F, 0x4D, 0x4E, 0x7C, 0xF6, 0x29, 0xDB, 0xB8, 0xAD, 0xF6, + 0x41, 0x69, 0x06, 0x90, 0x45, 0x7B, 0x95, 0x03, 0xE1, 0x9E, + 0xA5, 0xA1, 0x5A, 0xE3, 0x08, 0x26, 0x73, 0xFC, 0x2B, 0x20, + 0x02, 0x82, 0x01, 0x81, 0x00, 0xA5, 0x52, 0x8F, 0x53, 0xF0, + 0xB9, 0x4F, 0x06, 0xB9, 0xC8, 0xB4, 0x50, 0xA4, 0x39, 0xBA, + 0x12, 0x92, 0x75, 0x27, 0x43, 0xA8, 0x30, 0xA9, 0xF2, 0x2A, + 0xC6, 0x93, 0x26, 0x3C, 0x8C, 0x9F, 0xA2, 0x6F, 0x53, 0xD9, + 0x14, 0xAB, 0x3F, 0x00, 0xC6, 0x11, 0x13, 0x90, 0x6A, 0x42, + 0xF2, 0x9D, 0xA3, 0x8F, 0x31, 0x32, 0x46, 0x73, 0xA3, 0x93, + 0x57, 0x5D, 0x76, 0x45, 0x49, 0x6C, 0xBD, 0xEA, 0xAF, 0xAA, + 0xB3, 0x55, 0x25, 0x11, 0x8E, 0xA5, 0x2A, 0xB1, 0xBA, 0xA5, + 0x06, 0x4A, 0x66, 0xAA, 0x78, 0x9E, 0xF6, 0x5C, 0x1E, 0xB1, + 0x4A, 0xCA, 0x5C, 0x3F, 0x1D, 0x33, 0x75, 0x91, 0xF2, 0xF9, + 0x53, 0x14, 0x2F, 0xDC, 0xF0, 0x4C, 0xA4, 0xF4, 0x50, 0x04, + 0x1F, 0xFF, 0xC9, 0x0C, 0xC6, 0x8A, 0x04, 0x8B, 0x80, 0x87, + 0xA7, 0x70, 0x49, 0xD7, 0xE4, 0xE7, 0x83, 0xF1, 0x86, 0x1A, + 0xB0, 0x85, 0x3C, 0x59, 0x04, 0x96, 0xD1, 0x85, 0x47, 0xA1, + 0x57, 0x7D, 0xC6, 0x8E, 0x60, 0x7D, 0xC6, 0xE8, 0x18, 0xB3, + 0x1F, 0xB8, 0x99, 0xF0, 0xC4, 0xE5, 0x1E, 0xBC, 0x34, 0x07, + 0x8E, 0x40, 0x57, 0xA5, 0x8D, 0x3A, 0xA3, 0x88, 0x96, 0xF1, + 0xB3, 0x61, 0xF1, 0x1C, 0x96, 0x8A, 0xA4, 0x9E, 0xCD, 0x21, + 0xA2, 0x94, 0xAE, 0x5E, 0x1F, 0xCD, 0x5B, 0x5B, 0xE3, 0x88, + 0x1E, 0x17, 0x4A, 0x46, 0xAB, 0x9C, 0xE0, 0x59, 0x03, 0x4A, + 0xB8, 0xC8, 0x83, 0xE7, 0xFF, 0x39, 0x27, 0x68, 0x80, 0xA0, + 0x8E, 0xB3, 0xA2, 0x00, 0xC6, 0x2D, 0x2C, 0x76, 0xBA, 0x90, + 0x7C, 0x03, 0x1B, 0x19, 0xC8, 0x33, 0xB2, 0x12, 0x3A, 0xC8, + 0x8D, 0x32, 0xFE, 0xC0, 0xF9, 0xA5, 0x6A, 0x63, 0xE2, 0xA4, + 0x12, 0x43, 0x19, 0xF5, 0x14, 0xF2, 0x27, 0xF8, 0x0B, 0xBD, + 0x1A, 0x22, 0x64, 0x2D, 0xC9, 0x05, 0xFA, 0xD8, 0xDD, 0x11, + 0x1A, 0xD3, 0xF2, 0xBC, 0x99, 0x3A, 0xCD, 0x21, 0xCF, 0x10, + 0x14, 0x36, 0xDF, 0xED, 0x66, 0x02, 0x03, 0x4A, 0x42, 0x70, + 0x71, 0x22, 0xAD, 0xE7, 0x53, 0x91, 0xF4, 0x40, 0x8F, 0x72, + 0x7E, 0x54, 0xA0, 0x5D, 0x58, 0x93, 0xD6, 0xF6, 0xBC, 0x87, + 0x1A, 0x68, 0x0F, 0xAB, 0x94, 0x20, 0x70, 0xC2, 0x11, 0xA1, + 0x14, 0xBC, 0x06, 0xA8, 0x44, 0xB9, 0x1F, 0x04, 0x49, 0x7E, + 0xB3, 0x9A, 0x53, 0x46, 0x05, 0x75, 0x5D, 0x29, 0x77, 0x28, + 0xA9, 0xB1, 0xDC, 0xF1, 0x0D, 0x8A, 0x1C, 0x5E, 0xCD, 0xD7, + 0x4C, 0x16, 0x6F, 0x88, 0xBF, 0xB3, 0x34, 0xE2, 0xAD, 0x9A, + 0xC4, 0x89, 0xE2, 0x2E, 0x5C, 0x20, 0xE1, 0x5F, 0x39, 0xBF, + 0xB7, 0x45, 0xD3, 0x0F, 0x98, 0xB0, 0xD8, 0xC9, 0x18, 0x91, + 0x17, 0x25, 0xBC, 0x53, 0x62, 0xFF, 0x27, 0x85, 0xBD, 0xE2, + 0xE3, 0x9C, 0xA8, 0x06, 0x7A, 0x54, 0xEA, 0xFD, 0xEA, 0x02, + 0x20, 0x4C, 0xAC, 0x69, 0x62, 0x08, 0xE5, 0xCD, 0x14, 0xC8, + 0x2D, 0x4E, 0xDF, 0x1F, 0x60, 0x1D, 0x93, 0x44, 0x86, 0x5D, + 0x73, 0x99, 0x40, 0x1B, 0xDC, 0xA9, 0xBA, 0xC4, 0x1B, 0x12, + 0x6C, 0xFF, 0x53 +}; +static const int sizeof_dsa_key_der_3072 = sizeof(dsa_key_der_3072); + +/* ./certs/rsa3072.der, 3072-bit */ +static const unsigned char rsa_key_der_3072[] = +{ + 0x30, 0x82, 0x06, 0xE4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x81, 0x00, 0xBC, 0x6D, 0x68, 0xFF, 0xC0, 0x07, 0x0E, 0x0C, + 0x4A, 0xE6, 0x76, 0x1F, 0x7A, 0x25, 0x3A, 0x75, 0xA7, 0xE2, + 0xF1, 0x17, 0x00, 0xF8, 0x85, 0xE6, 0x8F, 0x59, 0x14, 0xA7, + 0xDE, 0x8C, 0x74, 0x4B, 0xEB, 0x85, 0xEC, 0x49, 0x9B, 0xFF, + 0x4B, 0x43, 0x0A, 0x08, 0xA1, 0xEC, 0x64, 0x58, 0x47, 0x28, + 0xD5, 0xCE, 0x48, 0xE9, 0xCF, 0x34, 0xDF, 0x15, 0x20, 0x37, + 0x99, 0x0E, 0x3C, 0x81, 0xBE, 0x2E, 0xE4, 0x6C, 0xBB, 0xDE, + 0xD1, 0x93, 0xC5, 0xEC, 0x6C, 0xCC, 0x40, 0x0B, 0x46, 0xA1, + 0xE6, 0xCA, 0xA0, 0xD5, 0x3B, 0x44, 0x48, 0x79, 0x67, 0x52, + 0x6F, 0xDA, 0xED, 0x73, 0x8B, 0x7C, 0x33, 0xDA, 0x17, 0x96, + 0xE8, 0xA2, 0x91, 0x3C, 0x57, 0xDD, 0xC9, 0x2E, 0x01, 0x74, + 0x87, 0x33, 0xA0, 0x12, 0x7C, 0xBB, 0xF9, 0x53, 0xF4, 0xC4, + 0x31, 0x48, 0x53, 0xCB, 0xBB, 0x3C, 0x42, 0x43, 0x0C, 0x7A, + 0x7B, 0xB8, 0x2A, 0xFC, 0xDC, 0x70, 0xD5, 0x64, 0x16, 0x74, + 0xA8, 0x80, 0xDE, 0x16, 0xE0, 0xB2, 0x6C, 0x04, 0x47, 0x6C, + 0x25, 0xA6, 0x7F, 0xB4, 0x73, 0x49, 0xBC, 0xF3, 0xAE, 0xE3, + 0x93, 0x36, 0x87, 0x2B, 0xB7, 0x8F, 0xB5, 0x88, 0x88, 0x22, + 0x47, 0xDF, 0xBF, 0x4D, 0x3C, 0x2A, 0xBD, 0x3F, 0x2F, 0x11, + 0x29, 0xCC, 0x1C, 0x33, 0x40, 0x4E, 0x23, 0xF6, 0x25, 0xF0, + 0xAF, 0x02, 0x16, 0x48, 0xED, 0x1C, 0xD8, 0xC9, 0x92, 0x2F, + 0x5B, 0xAF, 0xBA, 0xDB, 0x60, 0x1E, 0x0E, 0xE1, 0x65, 0x91, + 0x96, 0xF8, 0x7D, 0x73, 0x4C, 0x72, 0x23, 0x33, 0xD5, 0x32, + 0x2B, 0x0F, 0x4F, 0xBC, 0x81, 0x45, 0x9E, 0x31, 0x76, 0xEF, + 0xE1, 0x76, 0x2D, 0x3F, 0x8F, 0xC4, 0x19, 0x8F, 0x27, 0x2A, + 0x8F, 0x6E, 0x76, 0xCC, 0xE0, 0x5D, 0xB0, 0x86, 0x66, 0xFE, + 0x72, 0xD9, 0x06, 0x40, 0xB6, 0xCE, 0x85, 0xC6, 0x2D, 0x34, + 0x33, 0xAA, 0x8E, 0xE5, 0x54, 0x8E, 0xB8, 0xBA, 0xEE, 0x92, + 0x07, 0x5D, 0xB5, 0xF1, 0x67, 0xBF, 0xCA, 0xE4, 0xCA, 0xCB, + 0xD9, 0x01, 0x73, 0x22, 0x01, 0x32, 0x39, 0xF4, 0x0A, 0xEC, + 0x5F, 0x4A, 0x00, 0x10, 0x3F, 0x01, 0x3D, 0x15, 0xBB, 0x55, + 0x91, 0x80, 0xBE, 0xD8, 0xD3, 0x59, 0xCC, 0xB0, 0x7C, 0x56, + 0xF7, 0xFF, 0xE0, 0x28, 0x40, 0x02, 0xB3, 0x98, 0x8A, 0x54, + 0x52, 0x60, 0xA5, 0x0B, 0x95, 0x53, 0x86, 0x6B, 0xA4, 0x35, + 0xCA, 0x04, 0xC7, 0xFB, 0x0A, 0xC8, 0x9D, 0x5A, 0x11, 0x40, + 0xF7, 0x60, 0x07, 0xB1, 0xB3, 0x42, 0xB6, 0x80, 0x8F, 0xE4, + 0x25, 0xC9, 0xE8, 0xBC, 0x8E, 0x21, 0x0D, 0x47, 0xCF, 0xB8, + 0x37, 0x09, 0xAF, 0xBF, 0x2C, 0x34, 0x09, 0x22, 0xC2, 0x6E, + 0x0D, 0x06, 0x30, 0x80, 0x1E, 0xA5, 0x8A, 0x46, 0x2D, 0xDC, + 0x57, 0xD4, 0x57, 0x82, 0x6A, 0x11, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x02, 0x82, 0x01, 0x81, 0x00, 0xAD, 0x99, 0xAF, 0xCF, + 0x51, 0x40, 0x2E, 0xB5, 0x2C, 0x9C, 0xBF, 0xDF, 0xA8, 0x4D, + 0x7C, 0x5A, 0xC1, 0xDE, 0xD8, 0x78, 0x75, 0x30, 0x83, 0x4D, + 0x34, 0x6C, 0xC2, 0x17, 0x17, 0x77, 0x17, 0xFE, 0x8A, 0x73, + 0xCC, 0x8A, 0xD4, 0xEA, 0x94, 0x90, 0xA3, 0x41, 0xE8, 0xCD, + 0x3E, 0x76, 0x06, 0xB9, 0x9C, 0xA2, 0x7D, 0x92, 0xCC, 0x90, + 0xCD, 0xA7, 0x4D, 0x13, 0x6C, 0x34, 0x2D, 0x92, 0xEB, 0x81, + 0x90, 0x7A, 0x8D, 0x6C, 0x70, 0x72, 0x51, 0x3B, 0xCD, 0xD1, + 0x30, 0x80, 0x33, 0x07, 0x1E, 0xF7, 0x38, 0xCE, 0xBB, 0xD7, + 0xE1, 0x5D, 0xD8, 0xCF, 0x9E, 0xB6, 0x79, 0x66, 0xA6, 0xF0, + 0x3B, 0x65, 0x87, 0xAE, 0x45, 0x8E, 0xE1, 0x78, 0x53, 0x0B, + 0xC7, 0x3A, 0x57, 0xA4, 0xE0, 0x9B, 0xB3, 0xB2, 0xD4, 0xB0, + 0xEA, 0xB9, 0x6B, 0x1D, 0x06, 0xBA, 0xB8, 0x59, 0x4F, 0x9B, + 0xE9, 0x00, 0x95, 0x12, 0x93, 0xC1, 0xCD, 0xF9, 0x41, 0xAF, + 0xC3, 0x2A, 0x7F, 0x75, 0xE3, 0x79, 0x37, 0x24, 0xA4, 0xC8, + 0x3D, 0xB4, 0x83, 0x89, 0x23, 0xF7, 0x0E, 0x59, 0x56, 0x8E, + 0x6D, 0x43, 0xA5, 0xB1, 0x8E, 0x04, 0x02, 0xED, 0x48, 0x25, + 0x62, 0xFE, 0xF3, 0x4D, 0x82, 0x22, 0xA6, 0xC1, 0xA5, 0xD9, + 0x4A, 0x9A, 0x57, 0xE6, 0xDC, 0x37, 0x6D, 0x13, 0xDA, 0xFF, + 0x23, 0x2A, 0xB9, 0x31, 0xD2, 0x4B, 0x7D, 0xF3, 0x02, 0x90, + 0xF6, 0x28, 0x3D, 0x98, 0x3C, 0xF6, 0x43, 0x45, 0xAE, 0xAB, + 0x91, 0x15, 0xC7, 0xC4, 0x90, 0x9C, 0x3E, 0xDA, 0xD4, 0x20, + 0x12, 0xB2, 0xE1, 0x2B, 0x56, 0xE2, 0x38, 0x32, 0x9C, 0xE6, + 0xA9, 0x1D, 0xFE, 0xA5, 0xEE, 0xD7, 0x52, 0xB4, 0xE3, 0xE4, + 0x65, 0xEA, 0x41, 0x9D, 0xD4, 0x91, 0x83, 0x5D, 0xFF, 0x52, + 0xA7, 0xC3, 0x42, 0x9F, 0x14, 0x70, 0x9F, 0x98, 0x14, 0xB2, + 0x33, 0xEE, 0x4C, 0x5A, 0xC9, 0x5F, 0x16, 0xF6, 0x06, 0xE9, + 0xF3, 0x39, 0xD2, 0xC5, 0x31, 0x53, 0x2A, 0x39, 0xED, 0x3A, + 0x4D, 0x2A, 0xC1, 0x4C, 0x87, 0x82, 0xC6, 0xCA, 0xCF, 0xF5, + 0x9A, 0x71, 0x27, 0xAE, 0xFB, 0xFE, 0xD0, 0x66, 0xDB, 0xAA, + 0x03, 0x16, 0x4B, 0xEF, 0xB4, 0x28, 0xAB, 0xCF, 0xBE, 0x9B, + 0x58, 0xCF, 0xA4, 0x58, 0x82, 0xD2, 0x37, 0x8C, 0xEA, 0x3D, + 0x75, 0x4D, 0x0B, 0x46, 0x7A, 0x04, 0xDE, 0xF1, 0x6E, 0xBB, + 0x03, 0xBF, 0xF7, 0x8E, 0xE6, 0xF4, 0x9A, 0xE1, 0xCA, 0x26, + 0x2C, 0x41, 0x08, 0xAD, 0x21, 0xA7, 0xC2, 0x40, 0xF5, 0x9C, + 0xDD, 0xAB, 0xC5, 0x5A, 0x4C, 0xF4, 0xE6, 0x9A, 0x50, 0xFD, + 0xAA, 0x47, 0xD6, 0xA6, 0x07, 0x25, 0xB2, 0x4B, 0x9C, 0x1D, + 0x90, 0xA2, 0x4A, 0x98, 0xE0, 0x05, 0x8A, 0x5C, 0xD1, 0x2C, + 0xC0, 0x28, 0xD1, 0x84, 0x3C, 0x72, 0xFF, 0x83, 0xEA, 0xB1, + 0x02, 0x81, 0xC1, 0x00, 0xF8, 0xA0, 0x5F, 0x25, 0x2E, 0x23, + 0x73, 0x30, 0xB6, 0x97, 0xAF, 0x08, 0xE7, 0xD2, 0xD8, 0xC3, + 0x95, 0xEA, 0x9D, 0x8E, 0x9F, 0xF1, 0x36, 0x81, 0xD7, 0x7A, + 0x21, 0x2B, 0x90, 0x38, 0x9C, 0xA6, 0x08, 0x40, 0xEA, 0xD2, + 0x6E, 0x29, 0xB5, 0x0B, 0x3E, 0x91, 0xB2, 0x04, 0x92, 0xCF, + 0x94, 0xFF, 0xA6, 0xA7, 0x1A, 0x5F, 0x93, 0x0C, 0x86, 0xE6, + 0x4B, 0x61, 0xD4, 0x5E, 0xD7, 0xE3, 0x66, 0x0B, 0x83, 0xDB, + 0x16, 0x49, 0x27, 0xD5, 0xA3, 0xB3, 0xF5, 0x5D, 0x8F, 0xC9, + 0x48, 0x10, 0xD7, 0x77, 0x1E, 0x7B, 0x01, 0xC4, 0xFD, 0x14, + 0x0C, 0xAB, 0x40, 0xF7, 0x9B, 0x07, 0xDE, 0x55, 0xEF, 0x36, + 0x4C, 0x22, 0x37, 0x37, 0x09, 0x9D, 0x2A, 0x73, 0xA6, 0xA5, + 0xF4, 0xAF, 0x39, 0x2B, 0x87, 0xB4, 0xB2, 0x28, 0x9E, 0x08, + 0xA6, 0xCA, 0xB4, 0x39, 0x5A, 0x3A, 0xFB, 0x41, 0x93, 0xEC, + 0x44, 0xBB, 0xD2, 0x7C, 0x3B, 0x27, 0x3E, 0x26, 0xFD, 0x7B, + 0x20, 0xFC, 0x44, 0x67, 0xC0, 0x84, 0xD1, 0xA0, 0xCC, 0xBB, + 0x26, 0xC7, 0x32, 0x0E, 0x01, 0x9B, 0x2B, 0x1F, 0x58, 0x85, + 0x5A, 0x6C, 0xD0, 0xC1, 0xAC, 0x14, 0x5E, 0x06, 0x07, 0xCA, + 0x69, 0x52, 0xF5, 0xA6, 0x16, 0x75, 0x42, 0x8A, 0xE1, 0xBA, + 0x8B, 0x46, 0x38, 0x17, 0x7B, 0xF1, 0x7D, 0x79, 0x1F, 0x7E, + 0x4C, 0x6A, 0x75, 0xDC, 0xA8, 0x3B, 0x02, 0x81, 0xC1, 0x00, + 0xC2, 0x03, 0xFE, 0x57, 0xDF, 0x26, 0xD8, 0x79, 0xDC, 0x2C, + 0x47, 0x9B, 0x92, 0x9B, 0x53, 0x40, 0x82, 0xEC, 0xBD, 0x0B, + 0xC0, 0x96, 0x89, 0x21, 0xC5, 0x26, 0x7E, 0x7A, 0x59, 0xA7, + 0x85, 0x11, 0xCC, 0x39, 0x33, 0xA7, 0xE6, 0x42, 0x9C, 0x12, + 0x81, 0xA0, 0x87, 0xBC, 0x57, 0x07, 0xC4, 0x51, 0x93, 0x59, + 0xC6, 0xAB, 0x11, 0xCC, 0xCB, 0xC8, 0xC1, 0x40, 0xDF, 0xCB, + 0xE8, 0x45, 0x31, 0x20, 0x91, 0x88, 0x5F, 0x76, 0x76, 0xEE, + 0x30, 0x37, 0xFA, 0xA7, 0x22, 0x72, 0x82, 0x50, 0x31, 0xE9, + 0xA0, 0x44, 0xCA, 0xDD, 0xD6, 0xAC, 0xEC, 0x82, 0xE8, 0x62, + 0xD8, 0x43, 0xFD, 0x77, 0x0F, 0x1C, 0x23, 0x12, 0x91, 0x1C, + 0xFE, 0x93, 0x2C, 0x87, 0x52, 0xBF, 0x96, 0x79, 0x5E, 0x3A, + 0x5A, 0x33, 0x28, 0x27, 0x3F, 0x20, 0x2C, 0xB3, 0x26, 0xE2, + 0x0D, 0x44, 0xA9, 0x2F, 0x39, 0x7B, 0x7B, 0xAD, 0xA3, 0x21, + 0xD2, 0x7F, 0x3C, 0x89, 0x63, 0xDD, 0x13, 0xB1, 0x2E, 0xD6, + 0x34, 0xFB, 0x2A, 0x83, 0x29, 0xE7, 0x8A, 0x88, 0xD7, 0xA3, + 0x38, 0x3C, 0x43, 0x62, 0x8F, 0x69, 0xFA, 0x4B, 0x15, 0xB5, + 0xF6, 0x59, 0x90, 0x62, 0x7D, 0xCF, 0x1D, 0xDD, 0x49, 0x43, + 0x33, 0x96, 0xA9, 0xF7, 0x76, 0x9F, 0xE4, 0x0D, 0x6E, 0x1C, + 0xEA, 0x18, 0x5B, 0xBD, 0x5C, 0x98, 0x90, 0x09, 0xCA, 0x59, + 0x9E, 0x23, 0x02, 0x81, 0xC0, 0x66, 0xFF, 0x99, 0x2A, 0xFF, + 0xF8, 0x33, 0xAA, 0x44, 0x9A, 0x86, 0x2A, 0xBC, 0x4F, 0x3E, + 0xF9, 0x97, 0xCB, 0xC0, 0x45, 0xEB, 0xC0, 0xB4, 0x02, 0x0A, + 0x50, 0x50, 0x19, 0x89, 0xFF, 0xC9, 0xF5, 0x86, 0x89, 0xCE, + 0x3E, 0x2A, 0xE1, 0x20, 0x5D, 0x6E, 0x28, 0x51, 0x85, 0x4F, + 0x84, 0xAB, 0x87, 0x55, 0x74, 0xF8, 0x9A, 0x0B, 0x83, 0x2F, + 0x07, 0x8C, 0xC7, 0x14, 0x81, 0xCE, 0x12, 0x28, 0x9E, 0x30, + 0x9B, 0xBC, 0x99, 0xC5, 0xE4, 0xDD, 0x92, 0x99, 0xDD, 0x8E, + 0xC9, 0xA6, 0x0F, 0x44, 0x13, 0xD7, 0x0E, 0xC2, 0x66, 0xE7, + 0x29, 0x3D, 0x2E, 0x5D, 0x15, 0xB6, 0xA6, 0x05, 0xD7, 0xB7, + 0xE7, 0xD8, 0x96, 0x7C, 0x25, 0x52, 0xD8, 0x47, 0x53, 0xED, + 0xFF, 0xE6, 0x64, 0x08, 0xDD, 0x1D, 0xB5, 0x1F, 0xF1, 0x6F, + 0xB6, 0xC9, 0xD2, 0x43, 0xE3, 0x56, 0x9C, 0x04, 0xA6, 0xE0, + 0x2F, 0x0B, 0x32, 0x7C, 0x3A, 0x77, 0x0F, 0x04, 0xD2, 0x86, + 0x44, 0x52, 0x1F, 0xEF, 0xFE, 0xC3, 0x64, 0xC2, 0xAB, 0x48, + 0xE5, 0x67, 0x65, 0x32, 0x39, 0x57, 0x34, 0xFF, 0x22, 0x57, + 0x3B, 0xB7, 0x80, 0x48, 0xE3, 0x52, 0xF4, 0x85, 0x17, 0x1E, + 0x77, 0x1E, 0x36, 0xFE, 0x09, 0x36, 0x58, 0x91, 0x9E, 0x93, + 0x71, 0x02, 0x6D, 0xAE, 0xA3, 0x1B, 0xF7, 0xA9, 0x31, 0x5A, + 0x78, 0xAA, 0x13, 0x98, 0x8C, 0x37, 0x2D, 0x02, 0x81, 0xC1, + 0x00, 0xBE, 0x01, 0xD9, 0x3A, 0xC7, 0x81, 0xAC, 0xAA, 0x13, + 0x75, 0x8E, 0x1F, 0x8F, 0x41, 0xED, 0x13, 0x95, 0xE5, 0x31, + 0xF3, 0x6B, 0x86, 0x42, 0x00, 0xBF, 0xAA, 0xC6, 0x5D, 0x1E, + 0xA6, 0x90, 0x0C, 0xF1, 0x1B, 0xE8, 0x39, 0xFB, 0xA8, 0xAA, + 0x5E, 0xF9, 0x72, 0x74, 0xDC, 0x7F, 0xC3, 0x4C, 0x81, 0xB3, + 0xB4, 0x4D, 0x7B, 0xC6, 0x2F, 0xF2, 0x37, 0xC7, 0x03, 0xB8, + 0xE9, 0x62, 0xAD, 0x38, 0xC2, 0xB3, 0xA4, 0x82, 0x11, 0x6B, + 0xC2, 0x33, 0x98, 0xEF, 0x32, 0x75, 0xEA, 0xFD, 0x32, 0x7A, + 0xDF, 0x59, 0xA5, 0x65, 0xA4, 0x42, 0x95, 0x11, 0xFF, 0xD6, + 0x84, 0xCF, 0x56, 0x2E, 0xCA, 0x46, 0x13, 0x01, 0x4A, 0x32, + 0xB1, 0xD9, 0xA3, 0xDB, 0x0D, 0x20, 0x7E, 0x1F, 0x68, 0xF7, + 0x5E, 0x60, 0x6E, 0x0F, 0x59, 0xF8, 0x59, 0x93, 0x4D, 0x54, + 0xBC, 0x37, 0xD0, 0x51, 0x7C, 0xBD, 0x67, 0xF0, 0xA5, 0x09, + 0xC9, 0x9A, 0xF4, 0x1F, 0x1E, 0x52, 0x9D, 0xF5, 0xA6, 0x25, + 0xBF, 0x85, 0x1D, 0xA1, 0xF1, 0xD8, 0xBD, 0x39, 0x10, 0x71, + 0x57, 0x19, 0x40, 0xF3, 0xA1, 0x77, 0xE0, 0x8B, 0x4E, 0xB3, + 0x91, 0x84, 0x15, 0x0C, 0xF1, 0x58, 0x52, 0xD9, 0xE5, 0x98, + 0xD5, 0x66, 0x95, 0x9C, 0x19, 0x8D, 0xA4, 0x63, 0x5C, 0xBF, + 0xC5, 0x33, 0x81, 0xED, 0x7E, 0x93, 0x4B, 0x9A, 0x6C, 0xEC, + 0x2E, 0x3E, 0x4F, 0x02, 0x81, 0xC0, 0x34, 0xF8, 0xDF, 0x74, + 0xC6, 0xC1, 0xD9, 0x03, 0x9B, 0x3B, 0x53, 0x19, 0xEB, 0x43, + 0xC4, 0xAA, 0x1E, 0x73, 0xE3, 0x13, 0x25, 0x32, 0x04, 0x22, + 0x79, 0x4A, 0x07, 0xF0, 0x06, 0x38, 0xBD, 0x57, 0xE6, 0x01, + 0x33, 0x8C, 0xF1, 0x02, 0xCC, 0x34, 0x2C, 0x60, 0x32, 0xA4, + 0x22, 0x1D, 0x0E, 0x39, 0x6B, 0xAB, 0xF7, 0xCE, 0xDB, 0xA7, + 0xC3, 0xD8, 0xA2, 0x3B, 0x70, 0x31, 0x91, 0x68, 0xB9, 0xBF, + 0xE0, 0xA1, 0x39, 0x80, 0xFE, 0x47, 0x99, 0x56, 0x6D, 0x76, + 0x90, 0x17, 0xF5, 0x67, 0x41, 0x44, 0x27, 0x10, 0x07, 0x98, + 0x4D, 0x4C, 0x53, 0xD4, 0x15, 0xDC, 0x0A, 0x2F, 0xE0, 0x83, + 0x28, 0x22, 0x8D, 0x61, 0x3B, 0xE4, 0x8E, 0xE5, 0xE7, 0x24, + 0x98, 0x19, 0xA8, 0xA3, 0xED, 0x70, 0x59, 0x06, 0x86, 0x76, + 0xC2, 0x4B, 0xCB, 0x17, 0xC5, 0x77, 0x12, 0x07, 0xB8, 0xAB, + 0x1A, 0x91, 0xFC, 0x72, 0x8E, 0xB7, 0xB1, 0xE6, 0x74, 0xDD, + 0x3D, 0x92, 0xA7, 0xDE, 0x6C, 0x6E, 0xCB, 0x50, 0x44, 0x2F, + 0xAC, 0x99, 0xF7, 0x36, 0x4D, 0x62, 0xC7, 0xAC, 0xCE, 0x7D, + 0x26, 0xC9, 0xD2, 0x4E, 0x49, 0xD7, 0x8E, 0x66, 0x6C, 0xC1, + 0x53, 0xDF, 0x31, 0xAB, 0x25, 0x35, 0xCA, 0xD6, 0xC4, 0xA3, + 0xA6, 0x9F, 0x7E, 0x3D, 0x2D, 0x1A, 0x44, 0x31, 0x3D, 0x81, + 0x91, 0xB8, 0x36, 0x08, 0x27, 0x42, 0x9E, 0x08 +}; +static const int sizeof_rsa_key_der_3072 = sizeof(rsa_key_der_3072); + +/* ./certs/3072/client-key.der, 3072-bit */ +static const unsigned char client_key_der_3072[] = +{ + 0x30, 0x82, 0x06, 0xE4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x81, 0x00, 0xAC, 0x39, 0x50, 0x68, 0x8F, 0x78, 0xF8, 0x10, + 0x9B, 0x68, 0x96, 0xD3, 0xE1, 0x9C, 0x56, 0x68, 0x5A, 0x41, + 0x62, 0xE3, 0xB3, 0x41, 0xB0, 0x55, 0x80, 0x17, 0xB0, 0x88, + 0x16, 0x9B, 0xE0, 0x97, 0x74, 0x5F, 0x42, 0x79, 0x73, 0x42, + 0xDF, 0x93, 0xF3, 0xAA, 0x9D, 0xEE, 0x2D, 0x6F, 0xAA, 0xBC, + 0x27, 0x90, 0x84, 0xC0, 0x5D, 0xC7, 0xEC, 0x49, 0xEA, 0x5C, + 0x66, 0x1D, 0x70, 0x9C, 0x53, 0x5C, 0xBA, 0xA1, 0xB3, 0x58, + 0xC9, 0x3E, 0x8E, 0x9B, 0x72, 0x3D, 0x6E, 0x02, 0x02, 0x00, + 0x9C, 0x65, 0x56, 0x82, 0xA3, 0x22, 0xB4, 0x08, 0x5F, 0x2A, + 0xEF, 0xDF, 0x9A, 0xD0, 0xE7, 0x31, 0x59, 0x26, 0x5B, 0x0B, + 0x1C, 0x63, 0x61, 0xFF, 0xD5, 0x69, 0x32, 0x19, 0x06, 0x7E, + 0x0F, 0x40, 0x3C, 0x7A, 0x1E, 0xC8, 0xFC, 0x58, 0x6C, 0x64, + 0xAE, 0x10, 0x3D, 0xA8, 0x23, 0xFF, 0x8E, 0x1A, 0xCA, 0x6A, + 0x82, 0xE2, 0xF9, 0x01, 0x64, 0x2C, 0x97, 0xA0, 0x1A, 0x89, + 0xA0, 0x74, 0xD3, 0xB6, 0x05, 0x11, 0xF2, 0x62, 0x06, 0x48, + 0x2A, 0xF7, 0x66, 0xCE, 0xC1, 0x85, 0xE1, 0xD2, 0x27, 0xEA, + 0xCA, 0x12, 0xA5, 0x91, 0x97, 0x3E, 0xFC, 0x94, 0x06, 0x59, + 0x51, 0xC0, 0xE7, 0x13, 0xB6, 0x87, 0x7B, 0x5F, 0xD2, 0xC0, + 0x56, 0x2F, 0x5E, 0x1D, 0x02, 0xC3, 0x11, 0x2C, 0xDF, 0xF7, + 0x01, 0xDA, 0xBD, 0x85, 0x54, 0x35, 0x32, 0x5F, 0xC5, 0xC8, + 0xF9, 0x7A, 0x9F, 0x89, 0xF7, 0x03, 0x0E, 0x7E, 0x79, 0x5D, + 0x04, 0x82, 0x35, 0x10, 0xFE, 0x6D, 0x9B, 0xBF, 0xB8, 0xEE, + 0xE2, 0x62, 0x87, 0x26, 0x5E, 0x2F, 0x50, 0x2F, 0x78, 0x0C, + 0xE8, 0x73, 0x4F, 0x88, 0x6A, 0xD6, 0x26, 0xA4, 0xC9, 0xFC, + 0xFA, 0x1E, 0x8A, 0xB0, 0xF4, 0x32, 0xCF, 0x57, 0xCD, 0xA1, + 0x58, 0x8A, 0x49, 0x0F, 0xBB, 0xA9, 0x1D, 0x86, 0xAB, 0xB9, + 0x8F, 0x8D, 0x57, 0x19, 0xB2, 0x5A, 0x7E, 0xA4, 0xEA, 0xCC, + 0xB7, 0x96, 0x7A, 0x3B, 0x38, 0xCD, 0xDE, 0xE0, 0x61, 0xFC, + 0xC9, 0x06, 0x8F, 0x93, 0x5A, 0xCE, 0xAD, 0x2A, 0xE3, 0x2D, + 0x3E, 0x39, 0x5D, 0x41, 0x83, 0x01, 0x1F, 0x0F, 0xE1, 0x7F, + 0x76, 0xC7, 0x28, 0xDA, 0x56, 0xEF, 0xBF, 0xDC, 0x26, 0x35, + 0x40, 0xBE, 0xAD, 0xC7, 0x38, 0xAD, 0xA4, 0x06, 0xAC, 0xCA, + 0xE8, 0x51, 0xEB, 0xC0, 0xF8, 0x68, 0x02, 0x2C, 0x9B, 0xA1, + 0x14, 0xBC, 0xF8, 0x61, 0x86, 0xD7, 0x56, 0xD7, 0x73, 0xF4, + 0xAB, 0xBB, 0x6A, 0x21, 0xD3, 0x88, 0x22, 0xB4, 0xE7, 0x6F, + 0x7F, 0x91, 0xE5, 0x0E, 0xC6, 0x08, 0x49, 0xDE, 0xEA, 0x13, + 0x58, 0x72, 0xA0, 0xAA, 0x3A, 0xF9, 0x36, 0x03, 0x45, 0x57, + 0x5E, 0x87, 0xD2, 0x73, 0x65, 0xC4, 0x8C, 0xA3, 0xEE, 0xC9, + 0xD6, 0x73, 0x7C, 0x96, 0x41, 0x93, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x02, 0x82, 0x01, 0x80, 0x40, 0x19, 0x74, 0xDB, 0xF5, + 0xCA, 0x48, 0x49, 0xA6, 0x0D, 0xDF, 0x55, 0x2C, 0xFB, 0x4B, + 0x0D, 0xBB, 0xC9, 0xEA, 0x4C, 0x65, 0x43, 0x65, 0xA5, 0xEC, + 0xEE, 0xE4, 0x3D, 0x42, 0x6C, 0xF1, 0xC2, 0x6D, 0x05, 0xA7, + 0x70, 0x1C, 0x7E, 0x1F, 0x48, 0xA9, 0xC0, 0x2E, 0xD7, 0x9F, + 0x01, 0x98, 0xC2, 0x3E, 0xD7, 0x83, 0x11, 0x35, 0xD6, 0x5B, + 0x13, 0x87, 0xAE, 0xAC, 0x32, 0xF8, 0xDE, 0xB6, 0x08, 0x25, + 0x4E, 0x59, 0xBA, 0x09, 0xEC, 0xC6, 0x97, 0x04, 0x85, 0xE8, + 0x93, 0xC6, 0xBB, 0x03, 0x7A, 0x94, 0x20, 0x3B, 0x27, 0x87, + 0x6A, 0x36, 0x41, 0x7C, 0xD5, 0xF4, 0x81, 0x1C, 0x0B, 0x39, + 0xEB, 0x14, 0xA7, 0xA6, 0x01, 0x37, 0x50, 0x48, 0xD5, 0xC6, + 0x57, 0x9A, 0x1B, 0x01, 0x02, 0x1F, 0x80, 0x34, 0x45, 0x09, + 0xE6, 0xBF, 0x31, 0x19, 0xB7, 0xE1, 0xBA, 0xDA, 0xEB, 0x1A, + 0xB0, 0xCD, 0xF5, 0xA6, 0x91, 0x63, 0xAC, 0x28, 0xE4, 0x8F, + 0xEA, 0x7E, 0xF6, 0x0A, 0x4A, 0x71, 0x21, 0xA5, 0xF1, 0x70, + 0x0D, 0x1B, 0xD9, 0x70, 0x64, 0x74, 0x57, 0x2F, 0x9F, 0xEC, + 0xD4, 0x93, 0x16, 0xC7, 0xEE, 0xF8, 0xC0, 0x9F, 0x52, 0x4A, + 0x1F, 0xAD, 0xDD, 0x40, 0x98, 0x53, 0x68, 0xFA, 0xDE, 0xA2, + 0x04, 0xA0, 0x24, 0x05, 0xEF, 0xCB, 0x4F, 0x70, 0xDF, 0xB9, + 0x5C, 0xC2, 0x5E, 0xE4, 0xC9, 0xCD, 0x0F, 0x5E, 0x4B, 0x77, + 0xBB, 0x84, 0x69, 0x54, 0x98, 0x41, 0xB7, 0x9C, 0x0E, 0x38, + 0xD8, 0xF7, 0xF3, 0x9F, 0xEF, 0xE5, 0x9B, 0xB6, 0x4B, 0xD6, + 0x7A, 0x65, 0xF5, 0x69, 0xFA, 0xC2, 0x13, 0x70, 0x6C, 0x28, + 0xA4, 0x29, 0xAC, 0xD9, 0xBF, 0xEC, 0x6A, 0x2E, 0xED, 0xE4, + 0xBA, 0xDF, 0xD0, 0xF1, 0xF3, 0x3C, 0x6C, 0x84, 0xDF, 0xB7, + 0x5A, 0x94, 0xCF, 0xD9, 0x2D, 0xEA, 0xEA, 0xB4, 0xD0, 0x91, + 0x2E, 0x77, 0x15, 0x18, 0x0D, 0x6B, 0xBA, 0x2A, 0x0C, 0xF1, + 0x92, 0x9D, 0xD6, 0x04, 0x05, 0xB6, 0x38, 0xC2, 0xE0, 0xA7, + 0x2D, 0x64, 0xF8, 0xDF, 0x0C, 0x3A, 0x93, 0x83, 0xE1, 0x88, + 0x83, 0x5F, 0x67, 0x90, 0x9F, 0x2B, 0xE0, 0x60, 0x8E, 0xCA, + 0x30, 0x13, 0xCA, 0x9F, 0xCF, 0x7B, 0x6D, 0xD8, 0xCD, 0xEE, + 0xF9, 0x96, 0xDD, 0x5E, 0xF4, 0x47, 0xC9, 0x4C, 0xE6, 0x8F, + 0x7F, 0x33, 0x2A, 0x38, 0x30, 0xAF, 0xD5, 0x4A, 0x79, 0x47, + 0x06, 0xCC, 0x96, 0x44, 0x29, 0x8C, 0x60, 0x2B, 0x08, 0xC7, + 0xD0, 0xD3, 0xC3, 0xC5, 0x2C, 0x63, 0x6C, 0x87, 0xD2, 0xAE, + 0x2A, 0xA4, 0x86, 0xE7, 0x76, 0x74, 0x90, 0xD1, 0x04, 0x37, + 0x64, 0x1A, 0xED, 0x08, 0xD9, 0x98, 0x07, 0x1A, 0x98, 0x0B, + 0x89, 0x99, 0xA4, 0xB0, 0x8C, 0x1A, 0x10, 0xEB, 0xEC, 0xF4, + 0xEE, 0x3C, 0xC4, 0x00, 0xCC, 0x30, 0x9C, 0x43, 0x01, 0x02, + 0x81, 0xC1, 0x00, 0xD9, 0x43, 0xF6, 0x2C, 0x78, 0x26, 0xD2, + 0xE7, 0x15, 0xA7, 0x0A, 0x88, 0x5E, 0xDB, 0x2D, 0xAF, 0xC6, + 0xA9, 0x6F, 0x73, 0x88, 0x3B, 0x6A, 0x08, 0x1F, 0xF5, 0x80, + 0xB5, 0x2E, 0x29, 0x8B, 0x72, 0xF8, 0x35, 0xC8, 0x23, 0x18, + 0x1C, 0x0D, 0x0E, 0x38, 0x82, 0xBB, 0x5B, 0x2F, 0xB4, 0x5C, + 0x4E, 0x24, 0x05, 0xA7, 0x4C, 0x79, 0x48, 0x89, 0x8D, 0x1C, + 0x1D, 0x0A, 0x2C, 0xFE, 0xD9, 0x99, 0xDF, 0x25, 0x8A, 0x2D, + 0xF8, 0xEB, 0x2F, 0xDA, 0x1B, 0x63, 0xE1, 0xCD, 0x09, 0x97, + 0x64, 0x14, 0xAB, 0xEA, 0x0B, 0xD8, 0xE2, 0xA8, 0x2A, 0x63, + 0x35, 0x90, 0xEE, 0x7F, 0xEA, 0xCE, 0xA5, 0xEF, 0x7F, 0xAB, + 0x87, 0x47, 0x9B, 0x45, 0x35, 0x9A, 0xDA, 0x8C, 0xF4, 0xD3, + 0x8A, 0x0B, 0x9B, 0xE6, 0xEA, 0x92, 0xBB, 0x05, 0xE1, 0xAC, + 0x3E, 0x35, 0xDB, 0xED, 0x65, 0x1D, 0xB6, 0x92, 0xEB, 0x29, + 0x79, 0xF8, 0x3F, 0xC2, 0x58, 0x40, 0x32, 0x66, 0x87, 0x56, + 0x50, 0xFF, 0xBF, 0x3E, 0xBD, 0xE9, 0x94, 0xBF, 0x31, 0xBE, + 0x87, 0x2D, 0xEF, 0x64, 0x1E, 0x0E, 0x67, 0x3A, 0x9C, 0x94, + 0xDA, 0x5B, 0x0C, 0x8C, 0x3D, 0xEE, 0x9D, 0xCD, 0x92, 0xDE, + 0x40, 0x02, 0x65, 0x36, 0xC9, 0x1B, 0xF5, 0x7E, 0x4E, 0x07, + 0xB4, 0x7F, 0x14, 0x0E, 0x03, 0x2E, 0x86, 0xF0, 0x45, 0x5F, + 0xDC, 0xA2, 0xE8, 0xC7, 0x83, 0x02, 0x81, 0xC1, 0x00, 0xCA, + 0xED, 0xA5, 0x3F, 0x59, 0xAC, 0x4C, 0xAD, 0xAB, 0x23, 0x02, + 0x95, 0x80, 0xA0, 0xAF, 0x35, 0x17, 0xDB, 0xE7, 0x7F, 0x72, + 0x41, 0x2C, 0x5C, 0xB4, 0x43, 0x85, 0x46, 0x73, 0x9F, 0x58, + 0xE9, 0x40, 0x8B, 0xEC, 0xB0, 0xEF, 0x86, 0x4C, 0x31, 0xDE, + 0xC8, 0x6C, 0x74, 0x75, 0xA2, 0xDB, 0x65, 0xF4, 0x50, 0xC6, + 0x99, 0xA2, 0x70, 0xDE, 0xB6, 0x22, 0xC2, 0x01, 0x15, 0x49, + 0x13, 0xA0, 0xE2, 0x20, 0x78, 0x44, 0xEC, 0x1F, 0x42, 0xB3, + 0x25, 0x09, 0xCE, 0x75, 0x13, 0x75, 0x36, 0x11, 0x47, 0x2C, + 0x3C, 0x15, 0x1F, 0xF0, 0x54, 0xD5, 0x18, 0xAE, 0x61, 0x07, + 0xAC, 0x3D, 0x83, 0x46, 0x03, 0x8C, 0xBF, 0x63, 0x26, 0xA8, + 0x19, 0x7C, 0xFF, 0xDE, 0x20, 0x78, 0xD0, 0xDA, 0x70, 0x2E, + 0xBD, 0xFA, 0x96, 0xDD, 0x15, 0x78, 0x9B, 0xEF, 0xED, 0x17, + 0x90, 0x6F, 0x14, 0x35, 0x50, 0x8E, 0x1D, 0x78, 0xB0, 0x8A, + 0xA0, 0x53, 0x10, 0x15, 0x64, 0xCC, 0x47, 0x05, 0xB6, 0xC6, + 0x48, 0xC0, 0x5D, 0xB4, 0x4B, 0x1A, 0x5F, 0xB8, 0x9E, 0x75, + 0xCD, 0xC3, 0x64, 0x66, 0x88, 0x10, 0x9C, 0x8B, 0x87, 0x14, + 0x34, 0xE6, 0x60, 0x3C, 0xA5, 0xB7, 0x81, 0x1D, 0x0B, 0x79, + 0x93, 0x5D, 0x4A, 0x42, 0x7A, 0x7F, 0x33, 0xF0, 0x3E, 0x9E, + 0x63, 0xBD, 0xB6, 0x5F, 0xF9, 0x47, 0xA7, 0x0A, 0x49, 0x70, + 0xB1, 0x02, 0x81, 0xC0, 0x6F, 0xC6, 0xF4, 0x3E, 0xDA, 0xAD, + 0xF6, 0xB1, 0x66, 0xC5, 0x62, 0xB8, 0xD8, 0x3C, 0x61, 0x1B, + 0xDE, 0xD4, 0x4A, 0xFF, 0xA0, 0x66, 0x18, 0xDE, 0x07, 0x3B, + 0x32, 0x35, 0x84, 0x83, 0x61, 0x38, 0x0C, 0x14, 0xF7, 0x5B, + 0x7E, 0xCA, 0xE7, 0xB8, 0x9A, 0x40, 0x40, 0x0D, 0xE0, 0xD4, + 0x24, 0xED, 0x1A, 0xC1, 0x41, 0xDA, 0x29, 0x47, 0xB5, 0x64, + 0xC0, 0xC2, 0xFB, 0xFA, 0x3C, 0x3F, 0x4D, 0x57, 0xAD, 0xA3, + 0x92, 0x95, 0x4E, 0xC2, 0x76, 0xAE, 0xC2, 0xCB, 0x67, 0xC6, + 0x78, 0x79, 0xC7, 0xDC, 0xCE, 0x73, 0xBB, 0xE8, 0x98, 0x65, + 0xFE, 0x56, 0x8F, 0xB2, 0xF4, 0x62, 0xA4, 0x60, 0x60, 0x80, + 0x49, 0x8A, 0x36, 0xBF, 0xDE, 0x72, 0x7E, 0xB1, 0xD3, 0xF5, + 0x1D, 0x64, 0x17, 0x26, 0xE5, 0x3D, 0x67, 0xB2, 0x0A, 0x8B, + 0x99, 0x27, 0x04, 0x64, 0x9A, 0x94, 0xFC, 0x1D, 0x73, 0x26, + 0xC3, 0x56, 0xF9, 0xEE, 0x2B, 0x99, 0x65, 0xA5, 0xC8, 0x73, + 0xF6, 0x67, 0x83, 0xBC, 0x2B, 0x96, 0x5F, 0x36, 0xE4, 0xCA, + 0xBD, 0xE0, 0x24, 0x34, 0xD6, 0x48, 0x54, 0x56, 0xAD, 0xA3, + 0xE3, 0x3D, 0x17, 0xBC, 0xB3, 0xE6, 0x24, 0xFE, 0x50, 0xC6, + 0x2F, 0xCB, 0xB4, 0xAF, 0xC7, 0xE8, 0xDD, 0x96, 0x86, 0x9D, + 0xB4, 0x7F, 0x1B, 0x26, 0x01, 0x33, 0x87, 0xDB, 0x6A, 0x7F, + 0xF6, 0x9A, 0xB7, 0xC1, 0x94, 0xEB, 0x02, 0x81, 0xC1, 0x00, + 0xB0, 0x6D, 0x20, 0x68, 0x0D, 0x7C, 0x81, 0x45, 0xD4, 0x2E, + 0x22, 0x06, 0xFC, 0xC7, 0xB6, 0xCC, 0x40, 0x2C, 0x0D, 0xFE, + 0x7D, 0xC5, 0x2F, 0xDE, 0x81, 0x52, 0xDA, 0xC2, 0x3F, 0xAF, + 0xE0, 0x4B, 0x1A, 0xB5, 0x0C, 0x59, 0x60, 0x45, 0xB0, 0x65, + 0x03, 0x3D, 0xD9, 0x1C, 0xFF, 0x51, 0x51, 0xD2, 0x38, 0x31, + 0x2A, 0x19, 0x54, 0x63, 0x31, 0x1D, 0xC4, 0xE6, 0x4A, 0xAE, + 0xC8, 0xD3, 0xE9, 0xE1, 0xEF, 0x3C, 0xE1, 0x1F, 0x30, 0xA6, + 0x7A, 0xBD, 0xCE, 0xE2, 0xD2, 0x62, 0xD2, 0x5A, 0xE9, 0x76, + 0xA9, 0x7C, 0xAB, 0x19, 0x13, 0x87, 0x8D, 0xA5, 0x61, 0xA6, + 0x36, 0x57, 0x87, 0x3B, 0x64, 0x59, 0x9D, 0xBA, 0x9F, 0x67, + 0x72, 0x6A, 0x86, 0x84, 0xA6, 0x08, 0x31, 0x41, 0xD3, 0x48, + 0x09, 0x3B, 0x5E, 0x6C, 0x5F, 0x56, 0x55, 0x7F, 0xAD, 0x7E, + 0xC2, 0x27, 0xEE, 0x8A, 0xF1, 0x37, 0x51, 0xF7, 0x49, 0x80, + 0xA3, 0x65, 0x74, 0x11, 0xDD, 0xA7, 0xBE, 0xFA, 0x58, 0x7B, + 0x69, 0xB4, 0xC2, 0x9A, 0x35, 0x2F, 0xBE, 0x84, 0x4E, 0x2C, + 0x66, 0x5B, 0x38, 0x6F, 0x47, 0xBD, 0x30, 0x44, 0x0A, 0x02, + 0xAC, 0x8C, 0xB9, 0x66, 0x1E, 0x14, 0x2D, 0x90, 0x71, 0x42, + 0x12, 0xB7, 0x0E, 0x3A, 0x8B, 0xC5, 0x98, 0x65, 0xFD, 0x8F, + 0x53, 0x81, 0x7F, 0xE4, 0xD9, 0x58, 0x0E, 0xF5, 0xA9, 0x39, + 0xE4, 0x61, 0x02, 0x81, 0xC1, 0x00, 0xB3, 0x94, 0x8F, 0x2B, + 0xFD, 0x84, 0x2E, 0x83, 0x42, 0x86, 0x56, 0x7E, 0xB5, 0xF8, + 0x3C, 0xC5, 0x0C, 0xCB, 0xBD, 0x32, 0x0C, 0xD7, 0xAA, 0xA7, + 0xB0, 0xE9, 0xA4, 0x6A, 0xD1, 0x01, 0xDB, 0x87, 0x2A, 0xF7, + 0xDF, 0xEC, 0xC2, 0x03, 0x5D, 0x55, 0xA8, 0x66, 0x73, 0x79, + 0xA9, 0xAB, 0xBD, 0xAF, 0x69, 0x37, 0xFE, 0x41, 0xB5, 0x53, + 0xB3, 0xB2, 0xC0, 0xB1, 0x80, 0x34, 0xE6, 0xE1, 0x7B, 0xAE, + 0x67, 0xC7, 0xF3, 0x57, 0xFE, 0x12, 0xBC, 0x78, 0xAA, 0x75, + 0x0D, 0xAC, 0x79, 0x90, 0x14, 0x49, 0xFE, 0x6B, 0x51, 0xE3, + 0xE4, 0x46, 0xB2, 0x10, 0x4D, 0x05, 0x6A, 0x12, 0x80, 0x2A, + 0x8F, 0x39, 0x42, 0x0E, 0x3B, 0x24, 0x2B, 0x50, 0x5D, 0xF3, + 0xA7, 0x7F, 0x2F, 0x82, 0x89, 0x87, 0x9F, 0xF8, 0x7B, 0x1E, + 0x05, 0x6E, 0x75, 0x83, 0x04, 0x35, 0x66, 0x4A, 0x06, 0x57, + 0x39, 0xAB, 0x21, 0x0B, 0x94, 0x41, 0x6A, 0x2A, 0xC7, 0xDE, + 0x98, 0x45, 0x8F, 0x96, 0x1C, 0xF2, 0xD8, 0xFB, 0x9C, 0x10, + 0x8E, 0x41, 0x7A, 0xDD, 0xDD, 0x1D, 0xEF, 0xA5, 0x67, 0xEC, + 0xFE, 0xA3, 0x2D, 0xA9, 0xFD, 0xF3, 0xEE, 0x35, 0xF4, 0xA7, + 0xBC, 0xF9, 0x71, 0xCC, 0xB9, 0xC0, 0x5F, 0x58, 0x5B, 0xBD, + 0x1A, 0x9E, 0xC7, 0x08, 0x67, 0x7C, 0xC7, 0x51, 0x5B, 0xBE, + 0xE3, 0xF8, 0xBE, 0x1E, 0xC7, 0xD2, 0x28, 0x97 +}; +static const int sizeof_client_key_der_3072 = sizeof(client_key_der_3072); + +/* ./certs/3072/client-keyPub.der, 3072-bit */ +static const unsigned char client_keypub_der_3072[] = +{ + 0x30, 0x82, 0x01, 0xA2, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x8F, 0x00, 0x30, 0x82, 0x01, 0x8A, 0x02, 0x82, + 0x01, 0x81, 0x00, 0xAC, 0x39, 0x50, 0x68, 0x8F, 0x78, 0xF8, + 0x10, 0x9B, 0x68, 0x96, 0xD3, 0xE1, 0x9C, 0x56, 0x68, 0x5A, + 0x41, 0x62, 0xE3, 0xB3, 0x41, 0xB0, 0x55, 0x80, 0x17, 0xB0, + 0x88, 0x16, 0x9B, 0xE0, 0x97, 0x74, 0x5F, 0x42, 0x79, 0x73, + 0x42, 0xDF, 0x93, 0xF3, 0xAA, 0x9D, 0xEE, 0x2D, 0x6F, 0xAA, + 0xBC, 0x27, 0x90, 0x84, 0xC0, 0x5D, 0xC7, 0xEC, 0x49, 0xEA, + 0x5C, 0x66, 0x1D, 0x70, 0x9C, 0x53, 0x5C, 0xBA, 0xA1, 0xB3, + 0x58, 0xC9, 0x3E, 0x8E, 0x9B, 0x72, 0x3D, 0x6E, 0x02, 0x02, + 0x00, 0x9C, 0x65, 0x56, 0x82, 0xA3, 0x22, 0xB4, 0x08, 0x5F, + 0x2A, 0xEF, 0xDF, 0x9A, 0xD0, 0xE7, 0x31, 0x59, 0x26, 0x5B, + 0x0B, 0x1C, 0x63, 0x61, 0xFF, 0xD5, 0x69, 0x32, 0x19, 0x06, + 0x7E, 0x0F, 0x40, 0x3C, 0x7A, 0x1E, 0xC8, 0xFC, 0x58, 0x6C, + 0x64, 0xAE, 0x10, 0x3D, 0xA8, 0x23, 0xFF, 0x8E, 0x1A, 0xCA, + 0x6A, 0x82, 0xE2, 0xF9, 0x01, 0x64, 0x2C, 0x97, 0xA0, 0x1A, + 0x89, 0xA0, 0x74, 0xD3, 0xB6, 0x05, 0x11, 0xF2, 0x62, 0x06, + 0x48, 0x2A, 0xF7, 0x66, 0xCE, 0xC1, 0x85, 0xE1, 0xD2, 0x27, + 0xEA, 0xCA, 0x12, 0xA5, 0x91, 0x97, 0x3E, 0xFC, 0x94, 0x06, + 0x59, 0x51, 0xC0, 0xE7, 0x13, 0xB6, 0x87, 0x7B, 0x5F, 0xD2, + 0xC0, 0x56, 0x2F, 0x5E, 0x1D, 0x02, 0xC3, 0x11, 0x2C, 0xDF, + 0xF7, 0x01, 0xDA, 0xBD, 0x85, 0x54, 0x35, 0x32, 0x5F, 0xC5, + 0xC8, 0xF9, 0x7A, 0x9F, 0x89, 0xF7, 0x03, 0x0E, 0x7E, 0x79, + 0x5D, 0x04, 0x82, 0x35, 0x10, 0xFE, 0x6D, 0x9B, 0xBF, 0xB8, + 0xEE, 0xE2, 0x62, 0x87, 0x26, 0x5E, 0x2F, 0x50, 0x2F, 0x78, + 0x0C, 0xE8, 0x73, 0x4F, 0x88, 0x6A, 0xD6, 0x26, 0xA4, 0xC9, + 0xFC, 0xFA, 0x1E, 0x8A, 0xB0, 0xF4, 0x32, 0xCF, 0x57, 0xCD, + 0xA1, 0x58, 0x8A, 0x49, 0x0F, 0xBB, 0xA9, 0x1D, 0x86, 0xAB, + 0xB9, 0x8F, 0x8D, 0x57, 0x19, 0xB2, 0x5A, 0x7E, 0xA4, 0xEA, + 0xCC, 0xB7, 0x96, 0x7A, 0x3B, 0x38, 0xCD, 0xDE, 0xE0, 0x61, + 0xFC, 0xC9, 0x06, 0x8F, 0x93, 0x5A, 0xCE, 0xAD, 0x2A, 0xE3, + 0x2D, 0x3E, 0x39, 0x5D, 0x41, 0x83, 0x01, 0x1F, 0x0F, 0xE1, + 0x7F, 0x76, 0xC7, 0x28, 0xDA, 0x56, 0xEF, 0xBF, 0xDC, 0x26, + 0x35, 0x40, 0xBE, 0xAD, 0xC7, 0x38, 0xAD, 0xA4, 0x06, 0xAC, + 0xCA, 0xE8, 0x51, 0xEB, 0xC0, 0xF8, 0x68, 0x02, 0x2C, 0x9B, + 0xA1, 0x14, 0xBC, 0xF8, 0x61, 0x86, 0xD7, 0x56, 0xD7, 0x73, + 0xF4, 0xAB, 0xBB, 0x6A, 0x21, 0xD3, 0x88, 0x22, 0xB4, 0xE7, + 0x6F, 0x7F, 0x91, 0xE5, 0x0E, 0xC6, 0x08, 0x49, 0xDE, 0xEA, + 0x13, 0x58, 0x72, 0xA0, 0xAA, 0x3A, 0xF9, 0x36, 0x03, 0x45, + 0x57, 0x5E, 0x87, 0xD2, 0x73, 0x65, 0xC4, 0x8C, 0xA3, 0xEE, + 0xC9, 0xD6, 0x73, 0x7C, 0x96, 0x41, 0x93, 0x02, 0x03, 0x01, + 0x00, 0x01 +}; +static const int sizeof_client_keypub_der_3072 = sizeof(client_keypub_der_3072); + +/* ./certs/3072/client-cert.der, 3072-bit */ +static const unsigned char client_cert_der_3072[] = +{ + 0x30, 0x82, 0x05, 0xF8, 0x30, 0x82, 0x04, 0x60, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x14, 0x2F, 0x06, 0x07, 0xA8, 0xB6, + 0xF4, 0xEE, 0x10, 0x91, 0x43, 0xDE, 0xE1, 0x46, 0x99, 0xC4, + 0x90, 0x79, 0xE6, 0xF1, 0xD1, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + 0x30, 0x81, 0x9E, 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, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, + 0x5F, 0x33, 0x30, 0x37, 0x32, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, + 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x33, 0x30, + 0x37, 0x32, 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, 0x32, 0x30, 0x30, 0x31, 0x32, + 0x32, 0x30, 0x35, 0x35, 0x31, 0x34, 0x38, 0x5A, 0x17, 0x0D, + 0x32, 0x32, 0x31, 0x30, 0x31, 0x38, 0x30, 0x35, 0x35, 0x31, + 0x34, 0x38, 0x5A, 0x30, 0x81, 0x9E, 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, 0x15, 0x30, 0x13, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, + 0x53, 0x53, 0x4C, 0x5F, 0x33, 0x30, 0x37, 0x32, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, + 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, + 0x2D, 0x33, 0x30, 0x37, 0x32, 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, 0x82, 0x01, 0xA2, 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x8F, 0x00, 0x30, 0x82, + 0x01, 0x8A, 0x02, 0x82, 0x01, 0x81, 0x00, 0xAC, 0x39, 0x50, + 0x68, 0x8F, 0x78, 0xF8, 0x10, 0x9B, 0x68, 0x96, 0xD3, 0xE1, + 0x9C, 0x56, 0x68, 0x5A, 0x41, 0x62, 0xE3, 0xB3, 0x41, 0xB0, + 0x55, 0x80, 0x17, 0xB0, 0x88, 0x16, 0x9B, 0xE0, 0x97, 0x74, + 0x5F, 0x42, 0x79, 0x73, 0x42, 0xDF, 0x93, 0xF3, 0xAA, 0x9D, + 0xEE, 0x2D, 0x6F, 0xAA, 0xBC, 0x27, 0x90, 0x84, 0xC0, 0x5D, + 0xC7, 0xEC, 0x49, 0xEA, 0x5C, 0x66, 0x1D, 0x70, 0x9C, 0x53, + 0x5C, 0xBA, 0xA1, 0xB3, 0x58, 0xC9, 0x3E, 0x8E, 0x9B, 0x72, + 0x3D, 0x6E, 0x02, 0x02, 0x00, 0x9C, 0x65, 0x56, 0x82, 0xA3, + 0x22, 0xB4, 0x08, 0x5F, 0x2A, 0xEF, 0xDF, 0x9A, 0xD0, 0xE7, + 0x31, 0x59, 0x26, 0x5B, 0x0B, 0x1C, 0x63, 0x61, 0xFF, 0xD5, + 0x69, 0x32, 0x19, 0x06, 0x7E, 0x0F, 0x40, 0x3C, 0x7A, 0x1E, + 0xC8, 0xFC, 0x58, 0x6C, 0x64, 0xAE, 0x10, 0x3D, 0xA8, 0x23, + 0xFF, 0x8E, 0x1A, 0xCA, 0x6A, 0x82, 0xE2, 0xF9, 0x01, 0x64, + 0x2C, 0x97, 0xA0, 0x1A, 0x89, 0xA0, 0x74, 0xD3, 0xB6, 0x05, + 0x11, 0xF2, 0x62, 0x06, 0x48, 0x2A, 0xF7, 0x66, 0xCE, 0xC1, + 0x85, 0xE1, 0xD2, 0x27, 0xEA, 0xCA, 0x12, 0xA5, 0x91, 0x97, + 0x3E, 0xFC, 0x94, 0x06, 0x59, 0x51, 0xC0, 0xE7, 0x13, 0xB6, + 0x87, 0x7B, 0x5F, 0xD2, 0xC0, 0x56, 0x2F, 0x5E, 0x1D, 0x02, + 0xC3, 0x11, 0x2C, 0xDF, 0xF7, 0x01, 0xDA, 0xBD, 0x85, 0x54, + 0x35, 0x32, 0x5F, 0xC5, 0xC8, 0xF9, 0x7A, 0x9F, 0x89, 0xF7, + 0x03, 0x0E, 0x7E, 0x79, 0x5D, 0x04, 0x82, 0x35, 0x10, 0xFE, + 0x6D, 0x9B, 0xBF, 0xB8, 0xEE, 0xE2, 0x62, 0x87, 0x26, 0x5E, + 0x2F, 0x50, 0x2F, 0x78, 0x0C, 0xE8, 0x73, 0x4F, 0x88, 0x6A, + 0xD6, 0x26, 0xA4, 0xC9, 0xFC, 0xFA, 0x1E, 0x8A, 0xB0, 0xF4, + 0x32, 0xCF, 0x57, 0xCD, 0xA1, 0x58, 0x8A, 0x49, 0x0F, 0xBB, + 0xA9, 0x1D, 0x86, 0xAB, 0xB9, 0x8F, 0x8D, 0x57, 0x19, 0xB2, + 0x5A, 0x7E, 0xA4, 0xEA, 0xCC, 0xB7, 0x96, 0x7A, 0x3B, 0x38, + 0xCD, 0xDE, 0xE0, 0x61, 0xFC, 0xC9, 0x06, 0x8F, 0x93, 0x5A, + 0xCE, 0xAD, 0x2A, 0xE3, 0x2D, 0x3E, 0x39, 0x5D, 0x41, 0x83, + 0x01, 0x1F, 0x0F, 0xE1, 0x7F, 0x76, 0xC7, 0x28, 0xDA, 0x56, + 0xEF, 0xBF, 0xDC, 0x26, 0x35, 0x40, 0xBE, 0xAD, 0xC7, 0x38, + 0xAD, 0xA4, 0x06, 0xAC, 0xCA, 0xE8, 0x51, 0xEB, 0xC0, 0xF8, + 0x68, 0x02, 0x2C, 0x9B, 0xA1, 0x14, 0xBC, 0xF8, 0x61, 0x86, + 0xD7, 0x56, 0xD7, 0x73, 0xF4, 0xAB, 0xBB, 0x6A, 0x21, 0xD3, + 0x88, 0x22, 0xB4, 0xE7, 0x6F, 0x7F, 0x91, 0xE5, 0x0E, 0xC6, + 0x08, 0x49, 0xDE, 0xEA, 0x13, 0x58, 0x72, 0xA0, 0xAA, 0x3A, + 0xF9, 0x36, 0x03, 0x45, 0x57, 0x5E, 0x87, 0xD2, 0x73, 0x65, + 0xC4, 0x8C, 0xA3, 0xEE, 0xC9, 0xD6, 0x73, 0x7C, 0x96, 0x41, + 0x93, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x2A, + 0x30, 0x82, 0x01, 0x26, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, + 0x0E, 0x04, 0x16, 0x04, 0x14, 0x3D, 0xD1, 0x84, 0xC2, 0xAF, + 0xB0, 0x20, 0x49, 0xBC, 0x74, 0x87, 0x41, 0x38, 0xAB, 0xBA, + 0xD2, 0xD4, 0x0C, 0xA3, 0xA8, 0x30, 0x81, 0xDE, 0x06, 0x03, + 0x55, 0x1D, 0x23, 0x04, 0x81, 0xD6, 0x30, 0x81, 0xD3, 0x80, + 0x14, 0x3D, 0xD1, 0x84, 0xC2, 0xAF, 0xB0, 0x20, 0x49, 0xBC, + 0x74, 0x87, 0x41, 0x38, 0xAB, 0xBA, 0xD2, 0xD4, 0x0C, 0xA3, + 0xA8, 0xA1, 0x81, 0xA4, 0xA4, 0x81, 0xA1, 0x30, 0x81, 0x9E, + 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, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, + 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, 0x33, 0x30, + 0x37, 0x32, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, + 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x33, 0x30, 0x37, 0x32, 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, 0x14, + 0x2F, 0x06, 0x07, 0xA8, 0xB6, 0xF4, 0xEE, 0x10, 0x91, 0x43, + 0xDE, 0xE1, 0x46, 0x99, 0xC4, 0x90, 0x79, 0xE6, 0xF1, 0xD1, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xFF, 0x30, 0x16, 0x06, 0x03, 0x55, 0x1D, + 0x11, 0x04, 0x0F, 0x30, 0x0D, 0x82, 0x0B, 0x65, 0x78, 0x61, + 0x6D, 0x70, 0x6C, 0x65, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, + 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x81, 0x00, 0x04, 0xF5, + 0xE0, 0xE5, 0x75, 0x6B, 0xCF, 0xEE, 0x19, 0xEF, 0x3C, 0xB5, + 0xB6, 0x78, 0xCE, 0xB2, 0xC3, 0xF2, 0x3E, 0x0D, 0x3F, 0xB7, + 0x6D, 0x59, 0x7D, 0xB6, 0x7E, 0x6A, 0x91, 0x0F, 0x85, 0xAC, + 0xCA, 0x56, 0x30, 0x3C, 0x3F, 0x5D, 0x30, 0x10, 0x7C, 0x5E, + 0x7F, 0x98, 0xB2, 0x9D, 0x95, 0x04, 0xE1, 0xEE, 0xC0, 0x9E, + 0x1B, 0x01, 0x39, 0xCB, 0x02, 0x05, 0xB9, 0x9B, 0x02, 0x88, + 0xEB, 0xD0, 0xAD, 0x06, 0xD5, 0x39, 0x2D, 0x24, 0xE6, 0xDC, + 0x4E, 0xCE, 0x8C, 0x36, 0x7D, 0xB6, 0x8E, 0x1D, 0xE8, 0xB7, + 0xEF, 0xFF, 0xB4, 0x17, 0xC1, 0xA5, 0xD8, 0xFA, 0x34, 0xDD, + 0x99, 0x3D, 0x30, 0x4B, 0x45, 0xA2, 0x14, 0x6A, 0x88, 0x93, + 0xCA, 0x25, 0xE2, 0x5C, 0xD5, 0xBA, 0xE8, 0x9D, 0xEF, 0xD7, + 0x68, 0x76, 0x05, 0x92, 0x48, 0x19, 0x92, 0x11, 0x79, 0xC2, + 0xFE, 0x11, 0x49, 0x4D, 0xD6, 0xD1, 0x8F, 0x32, 0x1C, 0x5F, + 0x3B, 0x41, 0x2C, 0x08, 0xB2, 0x72, 0x65, 0x1C, 0xE5, 0x86, + 0x02, 0x94, 0xB3, 0x9D, 0x30, 0xDA, 0x59, 0x42, 0xA1, 0xB0, + 0x1E, 0x00, 0x92, 0x93, 0x6E, 0x0D, 0x27, 0xCF, 0xDF, 0xD8, + 0xCF, 0x2B, 0xCD, 0xCB, 0x8C, 0xFF, 0xB5, 0x6F, 0x83, 0x92, + 0x27, 0x00, 0x58, 0x59, 0xA2, 0x0B, 0x91, 0xB0, 0x39, 0xCA, + 0xA8, 0x78, 0xFD, 0x83, 0x56, 0x4F, 0xA1, 0x6E, 0xC3, 0xE0, + 0x2B, 0xAE, 0xEF, 0x3C, 0x09, 0x04, 0xF0, 0x9B, 0x5B, 0x00, + 0xD3, 0xED, 0xB6, 0x06, 0xF6, 0x9C, 0xDA, 0xAF, 0x61, 0x68, + 0x8F, 0xE3, 0x2A, 0xC3, 0x85, 0x20, 0x66, 0x2C, 0xAC, 0xDD, + 0x65, 0x37, 0x36, 0xC2, 0x2F, 0xBA, 0xB8, 0x90, 0x66, 0x6E, + 0x9E, 0x58, 0xA2, 0x4B, 0xD6, 0xA7, 0x30, 0xC8, 0xC9, 0x6C, + 0xBD, 0x13, 0x40, 0xA0, 0xCA, 0x59, 0x7C, 0xC5, 0x86, 0x9C, + 0x55, 0xC5, 0x68, 0xC7, 0x0C, 0x7F, 0x94, 0x73, 0xA5, 0x4B, + 0xEB, 0xF1, 0x27, 0x96, 0xB5, 0xF9, 0x69, 0x6B, 0x2B, 0xB6, + 0x62, 0xD7, 0x3A, 0x0D, 0x40, 0x65, 0xF0, 0x0D, 0xDE, 0x91, + 0x77, 0xD4, 0xF6, 0xBB, 0x13, 0x7B, 0x4A, 0x55, 0x8F, 0x7E, + 0x49, 0x65, 0x89, 0x37, 0x46, 0x05, 0x2F, 0x90, 0x14, 0x73, + 0x0D, 0x2D, 0x1E, 0xA4, 0xD4, 0xBB, 0x4E, 0x6D, 0x29, 0xDA, + 0x79, 0x6E, 0x73, 0x08, 0xDE, 0x5F, 0x27, 0xDC, 0x23, 0x14, + 0xDB, 0x7B, 0xE7, 0x02, 0x13, 0x2E, 0xC7, 0x94, 0x19, 0xF3, + 0x7D, 0x2E, 0xC4, 0x8A, 0x69, 0xBA, 0xF5, 0xBA, 0x62, 0xC2, + 0x88, 0xB5, 0xCB, 0xC7, 0x92, 0xA2, 0x8A, 0xE3, 0x69, 0x10, + 0x6E, 0xC5, 0xB8, 0xB2, 0x10, 0x7E, 0xB6, 0x0C, 0x71, 0x2A, + 0xC3, 0xE9, 0x71, 0x0C, 0xA2, 0x8B, 0x9A, 0x1D, 0x2C, 0x4E, + 0x21, 0x68, 0x53, 0x51, 0x6D, 0x0C, 0xD2, 0xB4, 0x4B, 0x50, + 0x4B, 0x0A +}; +static const int sizeof_client_cert_der_3072 = sizeof(client_cert_der_3072); + +#endif /* USE_CERT_BUFFERS_3072 */ + +#ifdef USE_CERT_BUFFERS_4096 + +/* ./certs/4096/client-key.der, 4096-bit */ +static const unsigned char client_key_der_4096[] = +{ + 0x30, 0x82, 0x09, 0x28, 0x02, 0x01, 0x00, 0x02, 0x82, 0x02, + 0x01, 0x00, 0xF5, 0xD0, 0x31, 0xE4, 0x71, 0x59, 0x58, 0xB3, + 0x07, 0x50, 0xDD, 0x16, 0x79, 0xFC, 0xC6, 0x95, 0x50, 0xFC, + 0x46, 0x0E, 0x57, 0x12, 0x86, 0x71, 0x8D, 0xE3, 0x9B, 0x4A, + 0x33, 0xEA, 0x4F, 0xD9, 0x17, 0x13, 0x6D, 0x48, 0x69, 0xDF, + 0x59, 0x11, 0x08, 0x02, 0x9D, 0xAF, 0x2B, 0xC7, 0x30, 0xBE, + 0x0C, 0xDC, 0x87, 0xD4, 0x5A, 0x12, 0x09, 0x23, 0x5D, 0xE1, + 0x76, 0x5A, 0x62, 0x37, 0x46, 0x74, 0xEF, 0x03, 0x05, 0xBB, + 0x1E, 0x6D, 0x29, 0x75, 0x6C, 0x2E, 0x9D, 0x87, 0x0D, 0x8F, + 0x87, 0xCB, 0x14, 0x95, 0x9B, 0xBE, 0x17, 0x6B, 0x51, 0xD1, + 0x4C, 0xDA, 0xD7, 0x91, 0x66, 0xC5, 0x36, 0xEB, 0xE0, 0x07, + 0x1A, 0x76, 0x4D, 0xB0, 0xFB, 0xC1, 0xF5, 0x5E, 0x05, 0xDB, + 0xBA, 0xCB, 0x25, 0xD9, 0x99, 0x13, 0x1C, 0xC0, 0x35, 0xDC, + 0x40, 0xE9, 0x36, 0xCD, 0xC4, 0xD5, 0x7A, 0x41, 0x70, 0x0F, + 0x36, 0xEB, 0xA5, 0x4E, 0x17, 0x05, 0xD5, 0x75, 0x1B, 0x64, + 0x62, 0x7A, 0x3F, 0x0D, 0x28, 0x48, 0x6A, 0xE3, 0xAC, 0x9C, + 0xA8, 0x8F, 0xE9, 0xED, 0xF7, 0xCD, 0x24, 0xA0, 0xB1, 0xA0, + 0x03, 0xAC, 0xE3, 0x03, 0xF5, 0x3F, 0xD1, 0x96, 0xFF, 0x2A, + 0x7E, 0x08, 0xB1, 0xD3, 0xE0, 0x18, 0x14, 0xEC, 0x65, 0x37, + 0x50, 0x43, 0xC2, 0x6A, 0x8C, 0xF4, 0x5B, 0xFE, 0xC4, 0xCB, + 0x8D, 0x3F, 0x81, 0x02, 0xF7, 0xC2, 0xDD, 0xE4, 0xC1, 0x8E, + 0x80, 0x0C, 0x04, 0x25, 0x2D, 0x80, 0x5A, 0x2E, 0x0F, 0x22, + 0x35, 0x4A, 0xF4, 0x85, 0xED, 0x51, 0xD8, 0xAB, 0x6D, 0x8F, + 0xA2, 0x3B, 0x24, 0x00, 0x6E, 0x81, 0xE2, 0x1E, 0x76, 0xD6, + 0xAC, 0x31, 0x12, 0xDB, 0xF3, 0x8E, 0x07, 0xA1, 0xDE, 0x89, + 0x4A, 0x39, 0x60, 0x77, 0xC5, 0xAA, 0xF1, 0x51, 0xE6, 0x06, + 0xF1, 0x95, 0x56, 0x2A, 0xE1, 0x8E, 0x92, 0x30, 0x9F, 0xFE, + 0x58, 0x44, 0xAC, 0x46, 0xF2, 0xFD, 0x9A, 0xFC, 0xA8, 0x1D, + 0xA1, 0xD3, 0x55, 0x37, 0x4A, 0x8B, 0xFC, 0x9C, 0x33, 0xF8, + 0xA7, 0x61, 0x48, 0x41, 0x7C, 0x9C, 0x77, 0x3F, 0xF5, 0x80, + 0x23, 0x7D, 0x43, 0xB4, 0xD5, 0x88, 0x0A, 0xC9, 0x75, 0xD7, + 0x44, 0x19, 0x4D, 0x77, 0x6C, 0x0B, 0x0A, 0x49, 0xAA, 0x1C, + 0x2F, 0xD6, 0x5A, 0x44, 0xA6, 0x47, 0x4D, 0xE5, 0x36, 0x96, + 0x40, 0x99, 0x2C, 0x56, 0x26, 0xB1, 0xF2, 0x92, 0x31, 0x59, + 0xD7, 0x2C, 0xD4, 0xB4, 0x21, 0xD6, 0x65, 0x13, 0x0B, 0x3E, + 0xFB, 0xFF, 0x04, 0xEB, 0xB9, 0x85, 0xB9, 0xD8, 0xD8, 0x28, + 0x4F, 0x5C, 0x17, 0x96, 0xA3, 0x51, 0xBE, 0xFE, 0x7D, 0x0B, + 0x1B, 0x48, 0x40, 0x25, 0x76, 0x94, 0xDC, 0x41, 0xFB, 0xBF, + 0x73, 0x76, 0xDA, 0xEB, 0xB3, 0x62, 0xE7, 0xC1, 0xC8, 0x54, + 0x6A, 0x93, 0xE1, 0x8D, 0x31, 0xE8, 0x3E, 0x3E, 0xDF, 0xBC, + 0x87, 0x02, 0x30, 0x22, 0x57, 0xC4, 0xE0, 0x18, 0x7A, 0xD3, + 0xAE, 0xE4, 0x02, 0x9B, 0xAA, 0xBD, 0x4E, 0x49, 0x47, 0x72, + 0xE9, 0x8D, 0x13, 0x2D, 0x54, 0x9B, 0x00, 0xA7, 0x91, 0x61, + 0x71, 0xC9, 0xCC, 0x48, 0x4F, 0xEE, 0xDF, 0x5E, 0x1B, 0x1A, + 0xDF, 0x67, 0xD3, 0x20, 0xE6, 0x44, 0x45, 0x98, 0x7E, 0xE7, + 0x0E, 0x63, 0x16, 0x83, 0xC9, 0x26, 0x5D, 0x90, 0xC1, 0xE5, + 0x2A, 0x5C, 0x45, 0x54, 0x13, 0xB2, 0x81, 0x18, 0x06, 0x20, + 0x2E, 0x2E, 0x66, 0x5A, 0xB5, 0x7B, 0x6E, 0xD6, 0x0C, 0x4E, + 0x89, 0x01, 0x56, 0x70, 0xBB, 0xAE, 0xDE, 0xE9, 0x99, 0x5E, + 0xD1, 0xB9, 0x3A, 0xB7, 0x6C, 0x17, 0xB6, 0x03, 0xA9, 0x08, + 0xDD, 0x9C, 0xF4, 0x14, 0xC9, 0xC9, 0x59, 0x39, 0x72, 0xD4, + 0x7E, 0x02, 0x37, 0x31, 0xCD, 0x0E, 0xA7, 0x3D, 0xF8, 0xF2, + 0xCF, 0x6B, 0x15, 0xAB, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, + 0x82, 0x02, 0x01, 0x00, 0xC5, 0x76, 0x57, 0x7D, 0xF1, 0x68, + 0x1A, 0x8E, 0xC6, 0x63, 0xB9, 0x16, 0xA3, 0x2B, 0xE1, 0xC2, + 0x74, 0xEA, 0x12, 0xC4, 0xD6, 0x41, 0x75, 0x6A, 0xA6, 0xD6, + 0x9E, 0x1A, 0x7F, 0x95, 0xCC, 0x4A, 0xD1, 0xF4, 0xB3, 0x27, + 0x26, 0x95, 0x5A, 0x91, 0x09, 0xE4, 0x40, 0x13, 0x45, 0x91, + 0x9F, 0xA0, 0x2B, 0xE8, 0xC3, 0xDC, 0x5B, 0xF6, 0x7D, 0x0C, + 0xC2, 0x0F, 0xA9, 0xE9, 0x75, 0x58, 0x7D, 0xEA, 0xD5, 0x4D, + 0x92, 0x3E, 0xFC, 0x74, 0x28, 0x87, 0xC1, 0x3D, 0xB9, 0x21, + 0x92, 0x4D, 0x28, 0x82, 0x84, 0xA8, 0xA2, 0x11, 0x93, 0xF2, + 0x8C, 0x29, 0x1C, 0x19, 0xF8, 0x6D, 0x3F, 0x27, 0x51, 0xB5, + 0x2D, 0xA3, 0xC7, 0x28, 0x1D, 0xC4, 0xFC, 0x98, 0x94, 0xA8, + 0xD0, 0xFF, 0xF0, 0x0F, 0xDC, 0xF9, 0xED, 0xB3, 0xA2, 0xB6, + 0xED, 0x0D, 0x5F, 0xBF, 0x78, 0x5C, 0xD7, 0xAF, 0xBD, 0xA3, + 0xEF, 0x86, 0xE9, 0x51, 0x66, 0xDB, 0x52, 0x37, 0x47, 0x7F, + 0xE9, 0x5F, 0x3C, 0x94, 0x83, 0x2D, 0xE8, 0x9C, 0x33, 0xF1, + 0x6C, 0xE9, 0xF3, 0xA6, 0x97, 0xFE, 0xA7, 0xBF, 0x4D, 0x9B, + 0x20, 0xD5, 0x2F, 0xDE, 0xA4, 0x06, 0xBB, 0xEE, 0x66, 0x49, + 0x6B, 0xF5, 0x10, 0x85, 0x9F, 0x84, 0x5A, 0x52, 0x3E, 0x0C, + 0xA0, 0x4A, 0x4C, 0xDA, 0x01, 0xC5, 0x62, 0x31, 0xB1, 0xEC, + 0xF8, 0xDD, 0xA3, 0x3B, 0xCE, 0x41, 0x3A, 0x12, 0x79, 0xF9, + 0x97, 0x5B, 0x07, 0x95, 0x9F, 0x86, 0xD6, 0x04, 0x73, 0x6C, + 0xE8, 0x8F, 0x4C, 0x4C, 0x48, 0x1D, 0x85, 0xC4, 0xE7, 0xCE, + 0xDE, 0x16, 0x31, 0xF6, 0x5C, 0x37, 0x54, 0x8E, 0x55, 0xBC, + 0xAF, 0x2E, 0x47, 0xE8, 0xAC, 0x03, 0xB0, 0xA4, 0xF9, 0x90, + 0x98, 0x99, 0xA4, 0xDC, 0x6E, 0x98, 0x08, 0x5C, 0x07, 0xBB, + 0x08, 0x93, 0xAF, 0x61, 0x8D, 0x74, 0xA8, 0xF8, 0xC4, 0x89, + 0x64, 0x10, 0xE1, 0xE6, 0xC0, 0xCD, 0x1D, 0x39, 0x20, 0xD6, + 0x5A, 0x89, 0x83, 0xFC, 0x37, 0xE2, 0x12, 0x66, 0xA8, 0x12, + 0xCC, 0x72, 0xBB, 0x1E, 0xFB, 0x6A, 0xE3, 0x7C, 0x71, 0x7E, + 0xB9, 0x2E, 0x8E, 0x84, 0x66, 0xE1, 0xB9, 0xD0, 0x25, 0x9A, + 0x6F, 0x9D, 0x19, 0xE6, 0x7E, 0xE8, 0xD8, 0xF0, 0xC5, 0x23, + 0x16, 0x9A, 0x68, 0x2C, 0x1D, 0x55, 0xAE, 0x8E, 0x90, 0xEE, + 0x8E, 0xEC, 0x5E, 0x46, 0x9D, 0x60, 0x52, 0x32, 0x17, 0x28, + 0x59, 0xC4, 0x49, 0x2A, 0x20, 0x3E, 0x95, 0xC5, 0xDF, 0xF6, + 0x3D, 0xF7, 0xC5, 0xCF, 0xB1, 0xC2, 0xC9, 0x76, 0xF8, 0x3D, + 0xBE, 0xF4, 0x63, 0xFC, 0x2A, 0x00, 0x6F, 0x99, 0xA6, 0xB6, + 0xAD, 0x35, 0xEE, 0xDE, 0xC5, 0xE0, 0x97, 0xC6, 0x73, 0xEE, + 0x33, 0xA0, 0xA8, 0xFC, 0x4C, 0x8F, 0xF2, 0x8C, 0x61, 0xFB, + 0x03, 0x19, 0xA1, 0xE8, 0x17, 0x4E, 0xE3, 0x21, 0x58, 0xCE, + 0xFE, 0xF2, 0x5F, 0xBB, 0xDD, 0x4F, 0xF7, 0x18, 0xCB, 0x35, + 0x57, 0xDD, 0xE5, 0x50, 0x2A, 0x7B, 0x1A, 0xE9, 0x12, 0xF2, + 0x7A, 0x11, 0xB1, 0x43, 0xB9, 0x70, 0x07, 0x0C, 0x8F, 0x69, + 0xB9, 0xE5, 0xA5, 0xC9, 0xE2, 0x1B, 0x96, 0x74, 0x11, 0xF5, + 0x95, 0xB9, 0x58, 0xC0, 0xBD, 0x37, 0xFB, 0x28, 0x2A, 0xBD, + 0x84, 0xB1, 0x2B, 0x67, 0x42, 0x82, 0xC3, 0x95, 0x55, 0x45, + 0xD5, 0xEA, 0xC3, 0x8A, 0x42, 0x3A, 0x43, 0x17, 0x5E, 0xCD, + 0xD2, 0xEA, 0xFC, 0xDF, 0x67, 0xEC, 0xE1, 0x6C, 0xA8, 0x03, + 0x19, 0xB2, 0x1D, 0x4A, 0x5F, 0x4F, 0xE7, 0xD3, 0xE0, 0x86, + 0xC5, 0x1A, 0x10, 0xC3, 0x08, 0xD2, 0xED, 0x85, 0x93, 0x08, + 0x51, 0x05, 0xA6, 0x37, 0x15, 0x32, 0xBD, 0x6C, 0x73, 0x63, + 0x01, 0x5D, 0x5B, 0x4F, 0x6A, 0xDC, 0x6D, 0x1D, 0x55, 0x91, + 0x21, 0xE4, 0x8E, 0xB7, 0xF0, 0x81, 0x02, 0x82, 0x01, 0x01, + 0x00, 0xFD, 0x27, 0xC8, 0xFE, 0x76, 0x5C, 0x89, 0x32, 0xCB, + 0x8A, 0x22, 0x87, 0x61, 0x48, 0x91, 0x4A, 0x05, 0xAD, 0xA4, + 0x5C, 0x8A, 0xCA, 0x5C, 0x02, 0x88, 0x7E, 0x51, 0xC5, 0x66, + 0x90, 0x2C, 0xA3, 0xED, 0xA7, 0x43, 0x19, 0x0B, 0xA2, 0x42, + 0xB4, 0xE0, 0xE0, 0x45, 0xBF, 0xFE, 0xA0, 0xF2, 0x75, 0x0B, + 0x8E, 0x7D, 0x9D, 0x73, 0x67, 0xD3, 0x10, 0x09, 0xC5, 0xD9, + 0x8C, 0xAD, 0x3A, 0x64, 0x72, 0xAD, 0x96, 0x35, 0x91, 0x0F, + 0x4B, 0xC9, 0xBD, 0x4F, 0x65, 0x47, 0xA6, 0x2D, 0xEB, 0x3F, + 0xE2, 0x99, 0x72, 0x66, 0x12, 0xED, 0xEB, 0xD2, 0x7C, 0xFF, + 0x3A, 0x20, 0x37, 0x2A, 0xD3, 0x65, 0x51, 0x9B, 0xC3, 0xAA, + 0x18, 0xB1, 0x1F, 0x6E, 0x9D, 0x40, 0x47, 0xA4, 0x1F, 0x82, + 0x9B, 0xDB, 0x50, 0x6B, 0x86, 0x2F, 0xFB, 0x3F, 0x31, 0xB9, + 0x81, 0x11, 0x04, 0x14, 0x63, 0x86, 0x4F, 0x40, 0x2A, 0xF5, + 0xF9, 0x7C, 0xA1, 0x78, 0x19, 0x13, 0xD0, 0x51, 0x51, 0x0F, + 0x79, 0x88, 0x8D, 0x14, 0xA3, 0xDE, 0xB6, 0x33, 0x29, 0x42, + 0xB9, 0xE8, 0x59, 0x76, 0xF7, 0x43, 0x1A, 0xB6, 0xA6, 0xDF, + 0x0A, 0xC1, 0x42, 0xC7, 0x3F, 0x1C, 0x7E, 0x5C, 0x2C, 0x91, + 0x4B, 0x1E, 0xF8, 0x46, 0x91, 0x1F, 0xEE, 0x56, 0xB3, 0x0E, + 0xC8, 0xD0, 0x31, 0xD3, 0x3D, 0xED, 0x3D, 0xD9, 0xC5, 0x30, + 0x0C, 0x58, 0xD8, 0xB7, 0xB5, 0xEC, 0x14, 0xAC, 0x41, 0x64, + 0x6D, 0xE4, 0xC6, 0x59, 0xFD, 0x14, 0x05, 0x60, 0x65, 0xD8, + 0xC4, 0x84, 0x44, 0x7E, 0x1B, 0xB4, 0xA4, 0x16, 0x75, 0xC1, + 0x27, 0x96, 0xB2, 0x19, 0xD6, 0x39, 0x54, 0xC0, 0x93, 0xF3, + 0xD7, 0x1F, 0xCD, 0x1B, 0xDF, 0xF8, 0x12, 0x88, 0x14, 0x9F, + 0x98, 0x05, 0x47, 0x46, 0x71, 0x81, 0x6C, 0xDF, 0x91, 0xEF, + 0x53, 0xE3, 0xC5, 0xB1, 0x89, 0x2F, 0xE1, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xF8, 0x93, 0x4A, 0x28, 0x77, 0x94, 0xEF, 0xE9, + 0xC4, 0x0A, 0xC3, 0xE8, 0x52, 0x59, 0xB6, 0x1D, 0x8D, 0xCE, + 0x14, 0xE7, 0x43, 0xC6, 0xED, 0x09, 0x27, 0x5D, 0xF3, 0x8E, + 0x08, 0x6A, 0x19, 0x6B, 0x2C, 0x97, 0x9B, 0x88, 0x53, 0x2B, + 0xDA, 0xFE, 0x4B, 0x94, 0x66, 0x84, 0xD5, 0xA9, 0xCE, 0xA5, + 0x43, 0x70, 0xFB, 0x01, 0x5A, 0x6F, 0xCD, 0xF7, 0xD1, 0x9D, + 0x51, 0xEE, 0xA0, 0xDC, 0x46, 0xF5, 0x7D, 0xA7, 0xEE, 0xA0, + 0x86, 0xB7, 0x83, 0xFF, 0x21, 0x8B, 0x76, 0x05, 0x7D, 0xDE, + 0xC4, 0x26, 0x36, 0xBC, 0xB4, 0x8A, 0x48, 0xC3, 0x06, 0x90, + 0x97, 0xE5, 0xA6, 0x38, 0xC3, 0xE6, 0x7C, 0xD0, 0xF8, 0x23, + 0xD2, 0x33, 0x1F, 0x81, 0xC3, 0xE3, 0x7D, 0x85, 0x5A, 0x38, + 0x10, 0x03, 0xE6, 0x88, 0xDB, 0xC8, 0x4C, 0xD0, 0xF7, 0xB2, + 0x4D, 0x27, 0x33, 0x85, 0xCD, 0x3A, 0x74, 0x83, 0x6B, 0x82, + 0x58, 0xD9, 0xDF, 0xEE, 0xF5, 0xD3, 0xE9, 0xFE, 0x1C, 0xEF, + 0x06, 0x12, 0x16, 0xD1, 0x4C, 0xAE, 0x54, 0x4B, 0x0D, 0x1A, + 0xBD, 0xE2, 0xCF, 0x56, 0xB3, 0x74, 0xBE, 0x44, 0x4F, 0xA4, + 0x73, 0x0A, 0x98, 0x8D, 0x61, 0x84, 0x38, 0x46, 0xDC, 0x95, + 0xCF, 0x3F, 0x6B, 0xE7, 0x65, 0x87, 0x02, 0xBF, 0x4B, 0x57, + 0xE2, 0x3D, 0xC4, 0x2B, 0x1C, 0x82, 0x1D, 0xCC, 0x13, 0x7F, + 0xC0, 0x06, 0x12, 0x8C, 0x6F, 0x97, 0x50, 0x7B, 0x8C, 0x81, + 0xC3, 0x23, 0x15, 0xEB, 0x70, 0x07, 0x8E, 0xA1, 0x07, 0x1E, + 0x59, 0xFA, 0x10, 0xCA, 0x7E, 0x0F, 0xE2, 0xBB, 0xEE, 0x86, + 0x26, 0x1E, 0x55, 0xB9, 0x98, 0x66, 0x85, 0xEC, 0x27, 0xC5, + 0xD9, 0x63, 0x8D, 0x51, 0x77, 0xAA, 0xA0, 0x36, 0x55, 0x33, + 0x10, 0x21, 0x5E, 0xEC, 0x47, 0x67, 0x71, 0xD1, 0xAF, 0xFC, + 0x3E, 0x50, 0xF5, 0xBE, 0xD6, 0x92, 0xE7, 0x0B, 0x02, 0x82, + 0x01, 0x00, 0x21, 0x7C, 0x8A, 0xC4, 0xC6, 0x29, 0x55, 0x68, + 0xA7, 0xAD, 0xDD, 0x05, 0x65, 0x63, 0xF0, 0xFC, 0x06, 0xA6, + 0x42, 0x70, 0x8F, 0x57, 0x57, 0x36, 0x6A, 0x91, 0xB3, 0x05, + 0x56, 0x9C, 0xC9, 0x9A, 0xE1, 0x8B, 0xD7, 0x7F, 0x4F, 0x9F, + 0xA6, 0x0D, 0x41, 0x15, 0xC9, 0x84, 0x2D, 0x0D, 0x63, 0x25, + 0x02, 0x63, 0x55, 0xD0, 0x66, 0xFC, 0x9B, 0xD9, 0xAA, 0x41, + 0x46, 0x96, 0xAA, 0x2F, 0x68, 0x2C, 0x17, 0x34, 0x20, 0x5F, + 0xD0, 0xD3, 0x28, 0x9B, 0x67, 0x0E, 0x31, 0x9D, 0x14, 0xC3, + 0xE2, 0x8E, 0x79, 0xD7, 0xBD, 0x12, 0xD1, 0xEF, 0xF8, 0xC6, + 0xDA, 0x07, 0xF9, 0x4C, 0xF2, 0xD8, 0x45, 0xB5, 0xB6, 0xD1, + 0xFA, 0x05, 0x0C, 0x20, 0xE9, 0x43, 0xD9, 0xC5, 0xE0, 0x3A, + 0xDE, 0xCE, 0xF9, 0x02, 0xB9, 0x46, 0x65, 0xC0, 0x69, 0x4A, + 0x8D, 0x8C, 0x3A, 0x10, 0xFD, 0x15, 0x71, 0x25, 0xB8, 0x8A, + 0x36, 0x41, 0x4B, 0x30, 0x1C, 0xAF, 0xCC, 0x84, 0x28, 0xCD, + 0x7D, 0x2B, 0x89, 0x59, 0x88, 0x1A, 0x69, 0x12, 0x56, 0xD0, + 0x25, 0x68, 0x6C, 0x08, 0xB1, 0x88, 0xE1, 0x92, 0x7E, 0x08, + 0xB2, 0xC6, 0x3C, 0x6C, 0x35, 0xE8, 0xEE, 0x3E, 0xF4, 0xB8, + 0x5C, 0x7B, 0xC0, 0x5B, 0xFD, 0x11, 0xA3, 0x54, 0xA6, 0x99, + 0x46, 0xE2, 0x5F, 0x4F, 0xC7, 0xEE, 0x90, 0x1C, 0x37, 0x5B, + 0x33, 0x10, 0xDF, 0x0B, 0xC3, 0xB9, 0x47, 0xC2, 0x30, 0x4A, + 0xF2, 0x1A, 0xEB, 0x41, 0x25, 0x94, 0x29, 0x7A, 0xD0, 0x96, + 0x88, 0x46, 0xEE, 0x6C, 0x14, 0xF6, 0x5B, 0x3D, 0xBD, 0x4E, + 0xD4, 0x3F, 0x05, 0x5B, 0x07, 0xB9, 0xE3, 0x99, 0x87, 0x63, + 0xCA, 0xC4, 0x71, 0x0B, 0x73, 0x9D, 0x7B, 0xB6, 0x0F, 0xD4, + 0x12, 0x8C, 0x4C, 0x5E, 0x72, 0x3D, 0xFF, 0x6D, 0xC4, 0x61, + 0x0C, 0x74, 0x5F, 0x53, 0xBE, 0x39, 0x34, 0x61, 0x02, 0x82, + 0x01, 0x00, 0x5F, 0xF2, 0xF2, 0xB0, 0x16, 0x20, 0x8E, 0x4E, + 0xCC, 0x96, 0x5F, 0x32, 0x80, 0xFF, 0x11, 0xF5, 0xEC, 0x73, + 0xBC, 0xCB, 0xDB, 0xF4, 0xA0, 0x30, 0x65, 0x5A, 0xB5, 0x95, + 0x80, 0x97, 0xFB, 0xC1, 0xCB, 0xCF, 0xA5, 0x80, 0x84, 0xA2, + 0x2C, 0x00, 0xF6, 0x89, 0x8C, 0xDC, 0xFF, 0x60, 0x71, 0x5C, + 0x87, 0x60, 0xC7, 0xF2, 0xA8, 0xC6, 0xF9, 0x59, 0x0C, 0x37, + 0x4E, 0x95, 0xEE, 0xCF, 0xB8, 0x30, 0x30, 0x55, 0xAF, 0x1D, + 0x95, 0x82, 0xA6, 0xD7, 0xC7, 0x49, 0xFE, 0xBF, 0x75, 0xEB, + 0x94, 0x09, 0x30, 0x1D, 0xBD, 0x0E, 0x97, 0xB1, 0x78, 0x0A, + 0x3E, 0x27, 0xAD, 0xF6, 0xC1, 0x5F, 0x69, 0x94, 0x7C, 0x03, + 0xCF, 0xB2, 0x5E, 0x1A, 0x07, 0xD3, 0xFA, 0xF2, 0x8B, 0x75, + 0x92, 0x70, 0xFE, 0xFE, 0x9A, 0xDF, 0x81, 0x0F, 0x34, 0x5D, + 0x45, 0xBC, 0xB8, 0xFD, 0x8F, 0xCF, 0x5D, 0x84, 0x10, 0xEE, + 0x9A, 0x7F, 0x57, 0x19, 0xF5, 0x17, 0xDC, 0x7D, 0x73, 0x0B, + 0xAC, 0x6B, 0x35, 0x15, 0x8B, 0x24, 0xCB, 0x72, 0xC0, 0xD7, + 0x2E, 0xAE, 0xAA, 0xDB, 0xCB, 0x9F, 0x67, 0x86, 0x14, 0xBB, + 0xE4, 0x90, 0x15, 0x7C, 0x95, 0x44, 0xA5, 0x38, 0x6D, 0x13, + 0x02, 0x91, 0x77, 0x84, 0x35, 0x43, 0x5D, 0x03, 0x1C, 0x01, + 0x0B, 0x5A, 0x4E, 0x2B, 0x59, 0xF0, 0xBB, 0xB1, 0xB7, 0x61, + 0x1B, 0x6C, 0xFC, 0xA1, 0xEA, 0xBD, 0x1C, 0x9A, 0xE4, 0x0C, + 0x7E, 0x97, 0x3F, 0x71, 0xC6, 0xA7, 0x94, 0x1D, 0x82, 0x12, + 0xEC, 0x26, 0x43, 0x6E, 0xF6, 0x24, 0x09, 0xA0, 0x03, 0x1D, + 0x12, 0xFF, 0xA8, 0x95, 0x60, 0x47, 0x4A, 0xB0, 0x72, 0x55, + 0xC3, 0x68, 0xD2, 0xF6, 0xBC, 0x5B, 0x47, 0x46, 0x51, 0xB2, + 0xC9, 0x2A, 0x28, 0x6A, 0xC9, 0xD1, 0x1B, 0x35, 0x16, 0x5A, + 0x26, 0x6F, 0xB7, 0xBB, 0xF7, 0x35, 0x73, 0x2B, 0x02, 0x82, + 0x01, 0x00, 0x56, 0xBA, 0xD8, 0x02, 0xD7, 0x4B, 0x30, 0x5E, + 0x1B, 0x1E, 0x2F, 0xF3, 0x0D, 0xBC, 0xF1, 0x05, 0x6A, 0x68, + 0x4A, 0xE1, 0xEA, 0xB3, 0xDE, 0x61, 0x8C, 0x89, 0x44, 0xBA, + 0x63, 0x5E, 0xDF, 0x05, 0x24, 0x32, 0x71, 0x65, 0x1A, 0x36, + 0x2F, 0xBC, 0x07, 0x75, 0xA3, 0xCE, 0x9E, 0x52, 0x92, 0x95, + 0x4D, 0x3F, 0xC9, 0x06, 0xBC, 0xA1, 0x14, 0x33, 0x37, 0x95, + 0xAB, 0x9A, 0xEB, 0x04, 0xF6, 0x15, 0xC3, 0x9B, 0x10, 0x56, + 0x53, 0xA2, 0x28, 0xF2, 0x68, 0xDA, 0x7D, 0x97, 0x52, 0x63, + 0xAC, 0x9B, 0x56, 0xA9, 0xAB, 0x2E, 0x1E, 0x9E, 0x01, 0x70, + 0xFF, 0x2B, 0x6D, 0x0C, 0x4B, 0xA6, 0xC3, 0x3A, 0xB3, 0xD1, + 0xA7, 0x4B, 0x5E, 0x49, 0x2E, 0x95, 0xD6, 0x6A, 0xAE, 0x58, + 0x13, 0x66, 0x8F, 0x2F, 0x93, 0xE4, 0x6E, 0x8B, 0xFA, 0x94, + 0x30, 0x3E, 0xEC, 0x96, 0xAB, 0x46, 0x20, 0x3E, 0xC5, 0x30, + 0xB4, 0xEB, 0x41, 0x00, 0x39, 0x60, 0x1D, 0xE1, 0x20, 0xCE, + 0x31, 0x70, 0x17, 0x39, 0xCB, 0x76, 0x56, 0x6C, 0x55, 0x7B, + 0x90, 0x20, 0xBC, 0x39, 0xB2, 0x5B, 0xD1, 0x28, 0x6F, 0x0C, + 0x4F, 0x45, 0x6B, 0x82, 0xC4, 0x57, 0x23, 0x0C, 0x3F, 0x3F, + 0x2D, 0x83, 0xB3, 0x3D, 0x8E, 0xF9, 0x1A, 0xDA, 0x77, 0x54, + 0x2E, 0xFE, 0x16, 0x2E, 0xBA, 0x99, 0xDD, 0xCA, 0xB3, 0xD1, + 0xD8, 0xBB, 0x87, 0xE1, 0xD0, 0xA9, 0xD4, 0xE6, 0x8F, 0xE8, + 0x00, 0x3E, 0x49, 0x8A, 0xDD, 0xA6, 0x32, 0x91, 0x00, 0x31, + 0x31, 0x21, 0x98, 0x18, 0x94, 0xC9, 0x2D, 0x27, 0x05, 0xB7, + 0x9B, 0x09, 0x2E, 0xBB, 0x5D, 0xBF, 0x67, 0xE8, 0x0E, 0xD1, + 0x44, 0x75, 0x80, 0x1D, 0x0A, 0x21, 0x8F, 0x95, 0x76, 0xB0, + 0xFC, 0x19, 0x3C, 0xFF, 0x92, 0xEA, 0x01, 0x45, 0x89, 0xD1, + 0x4E, 0xFE, 0x4D, 0x2B, 0x4B, 0x18, 0xE6, 0xCE +}; +static const int sizeof_client_key_der_4096 = sizeof(client_key_der_4096); + +/* ./certs/4096/client-keyPub.der, 4096-bit */ +static const unsigned char client_keypub_der_4096[] = +{ + 0x30, 0x82, 0x02, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x82, 0x02, 0x0F, 0x00, 0x30, 0x82, 0x02, 0x0A, 0x02, 0x82, + 0x02, 0x01, 0x00, 0xF5, 0xD0, 0x31, 0xE4, 0x71, 0x59, 0x58, + 0xB3, 0x07, 0x50, 0xDD, 0x16, 0x79, 0xFC, 0xC6, 0x95, 0x50, + 0xFC, 0x46, 0x0E, 0x57, 0x12, 0x86, 0x71, 0x8D, 0xE3, 0x9B, + 0x4A, 0x33, 0xEA, 0x4F, 0xD9, 0x17, 0x13, 0x6D, 0x48, 0x69, + 0xDF, 0x59, 0x11, 0x08, 0x02, 0x9D, 0xAF, 0x2B, 0xC7, 0x30, + 0xBE, 0x0C, 0xDC, 0x87, 0xD4, 0x5A, 0x12, 0x09, 0x23, 0x5D, + 0xE1, 0x76, 0x5A, 0x62, 0x37, 0x46, 0x74, 0xEF, 0x03, 0x05, + 0xBB, 0x1E, 0x6D, 0x29, 0x75, 0x6C, 0x2E, 0x9D, 0x87, 0x0D, + 0x8F, 0x87, 0xCB, 0x14, 0x95, 0x9B, 0xBE, 0x17, 0x6B, 0x51, + 0xD1, 0x4C, 0xDA, 0xD7, 0x91, 0x66, 0xC5, 0x36, 0xEB, 0xE0, + 0x07, 0x1A, 0x76, 0x4D, 0xB0, 0xFB, 0xC1, 0xF5, 0x5E, 0x05, + 0xDB, 0xBA, 0xCB, 0x25, 0xD9, 0x99, 0x13, 0x1C, 0xC0, 0x35, + 0xDC, 0x40, 0xE9, 0x36, 0xCD, 0xC4, 0xD5, 0x7A, 0x41, 0x70, + 0x0F, 0x36, 0xEB, 0xA5, 0x4E, 0x17, 0x05, 0xD5, 0x75, 0x1B, + 0x64, 0x62, 0x7A, 0x3F, 0x0D, 0x28, 0x48, 0x6A, 0xE3, 0xAC, + 0x9C, 0xA8, 0x8F, 0xE9, 0xED, 0xF7, 0xCD, 0x24, 0xA0, 0xB1, + 0xA0, 0x03, 0xAC, 0xE3, 0x03, 0xF5, 0x3F, 0xD1, 0x96, 0xFF, + 0x2A, 0x7E, 0x08, 0xB1, 0xD3, 0xE0, 0x18, 0x14, 0xEC, 0x65, + 0x37, 0x50, 0x43, 0xC2, 0x6A, 0x8C, 0xF4, 0x5B, 0xFE, 0xC4, + 0xCB, 0x8D, 0x3F, 0x81, 0x02, 0xF7, 0xC2, 0xDD, 0xE4, 0xC1, + 0x8E, 0x80, 0x0C, 0x04, 0x25, 0x2D, 0x80, 0x5A, 0x2E, 0x0F, + 0x22, 0x35, 0x4A, 0xF4, 0x85, 0xED, 0x51, 0xD8, 0xAB, 0x6D, + 0x8F, 0xA2, 0x3B, 0x24, 0x00, 0x6E, 0x81, 0xE2, 0x1E, 0x76, + 0xD6, 0xAC, 0x31, 0x12, 0xDB, 0xF3, 0x8E, 0x07, 0xA1, 0xDE, + 0x89, 0x4A, 0x39, 0x60, 0x77, 0xC5, 0xAA, 0xF1, 0x51, 0xE6, + 0x06, 0xF1, 0x95, 0x56, 0x2A, 0xE1, 0x8E, 0x92, 0x30, 0x9F, + 0xFE, 0x58, 0x44, 0xAC, 0x46, 0xF2, 0xFD, 0x9A, 0xFC, 0xA8, + 0x1D, 0xA1, 0xD3, 0x55, 0x37, 0x4A, 0x8B, 0xFC, 0x9C, 0x33, + 0xF8, 0xA7, 0x61, 0x48, 0x41, 0x7C, 0x9C, 0x77, 0x3F, 0xF5, + 0x80, 0x23, 0x7D, 0x43, 0xB4, 0xD5, 0x88, 0x0A, 0xC9, 0x75, + 0xD7, 0x44, 0x19, 0x4D, 0x77, 0x6C, 0x0B, 0x0A, 0x49, 0xAA, + 0x1C, 0x2F, 0xD6, 0x5A, 0x44, 0xA6, 0x47, 0x4D, 0xE5, 0x36, + 0x96, 0x40, 0x99, 0x2C, 0x56, 0x26, 0xB1, 0xF2, 0x92, 0x31, + 0x59, 0xD7, 0x2C, 0xD4, 0xB4, 0x21, 0xD6, 0x65, 0x13, 0x0B, + 0x3E, 0xFB, 0xFF, 0x04, 0xEB, 0xB9, 0x85, 0xB9, 0xD8, 0xD8, + 0x28, 0x4F, 0x5C, 0x17, 0x96, 0xA3, 0x51, 0xBE, 0xFE, 0x7D, + 0x0B, 0x1B, 0x48, 0x40, 0x25, 0x76, 0x94, 0xDC, 0x41, 0xFB, + 0xBF, 0x73, 0x76, 0xDA, 0xEB, 0xB3, 0x62, 0xE7, 0xC1, 0xC8, + 0x54, 0x6A, 0x93, 0xE1, 0x8D, 0x31, 0xE8, 0x3E, 0x3E, 0xDF, + 0xBC, 0x87, 0x02, 0x30, 0x22, 0x57, 0xC4, 0xE0, 0x18, 0x7A, + 0xD3, 0xAE, 0xE4, 0x02, 0x9B, 0xAA, 0xBD, 0x4E, 0x49, 0x47, + 0x72, 0xE9, 0x8D, 0x13, 0x2D, 0x54, 0x9B, 0x00, 0xA7, 0x91, + 0x61, 0x71, 0xC9, 0xCC, 0x48, 0x4F, 0xEE, 0xDF, 0x5E, 0x1B, + 0x1A, 0xDF, 0x67, 0xD3, 0x20, 0xE6, 0x44, 0x45, 0x98, 0x7E, + 0xE7, 0x0E, 0x63, 0x16, 0x83, 0xC9, 0x26, 0x5D, 0x90, 0xC1, + 0xE5, 0x2A, 0x5C, 0x45, 0x54, 0x13, 0xB2, 0x81, 0x18, 0x06, + 0x20, 0x2E, 0x2E, 0x66, 0x5A, 0xB5, 0x7B, 0x6E, 0xD6, 0x0C, + 0x4E, 0x89, 0x01, 0x56, 0x70, 0xBB, 0xAE, 0xDE, 0xE9, 0x99, + 0x5E, 0xD1, 0xB9, 0x3A, 0xB7, 0x6C, 0x17, 0xB6, 0x03, 0xA9, + 0x08, 0xDD, 0x9C, 0xF4, 0x14, 0xC9, 0xC9, 0x59, 0x39, 0x72, + 0xD4, 0x7E, 0x02, 0x37, 0x31, 0xCD, 0x0E, 0xA7, 0x3D, 0xF8, + 0xF2, 0xCF, 0x6B, 0x15, 0xAB, 0x02, 0x03, 0x01, 0x00, 0x01 + +}; +static const int sizeof_client_keypub_der_4096 = sizeof(client_keypub_der_4096); + +/* ./certs/4096/client-cert.der, 4096-bit */ +static const unsigned char client_cert_der_4096[] = +{ + 0x30, 0x82, 0x06, 0xE0, 0x30, 0x82, 0x04, 0xC8, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x14, 0x2F, 0x0F, 0xAB, 0x23, 0xBC, + 0xA3, 0x14, 0x07, 0x91, 0x06, 0x55, 0x35, 0x01, 0x63, 0x7F, + 0x42, 0xBD, 0xFB, 0xF2, 0x43, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + 0x30, 0x81, 0x9E, 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, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, + 0x5F, 0x34, 0x30, 0x39, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, + 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x34, 0x30, + 0x39, 0x36, 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, 0x39, 0x30, 0x37, 0x30, + 0x39, 0x30, 0x33, 0x30, 0x36, 0x30, 0x32, 0x5A, 0x17, 0x0D, + 0x32, 0x32, 0x30, 0x34, 0x30, 0x34, 0x30, 0x33, 0x30, 0x36, + 0x30, 0x32, 0x5A, 0x30, 0x81, 0x9E, 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, 0x15, 0x30, 0x13, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, + 0x53, 0x53, 0x4C, 0x5F, 0x34, 0x30, 0x39, 0x36, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, + 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, + 0x2D, 0x34, 0x30, 0x39, 0x36, 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, 0x82, 0x02, 0x22, 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0F, 0x00, 0x30, 0x82, + 0x02, 0x0A, 0x02, 0x82, 0x02, 0x01, 0x00, 0xF5, 0xD0, 0x31, + 0xE4, 0x71, 0x59, 0x58, 0xB3, 0x07, 0x50, 0xDD, 0x16, 0x79, + 0xFC, 0xC6, 0x95, 0x50, 0xFC, 0x46, 0x0E, 0x57, 0x12, 0x86, + 0x71, 0x8D, 0xE3, 0x9B, 0x4A, 0x33, 0xEA, 0x4F, 0xD9, 0x17, + 0x13, 0x6D, 0x48, 0x69, 0xDF, 0x59, 0x11, 0x08, 0x02, 0x9D, + 0xAF, 0x2B, 0xC7, 0x30, 0xBE, 0x0C, 0xDC, 0x87, 0xD4, 0x5A, + 0x12, 0x09, 0x23, 0x5D, 0xE1, 0x76, 0x5A, 0x62, 0x37, 0x46, + 0x74, 0xEF, 0x03, 0x05, 0xBB, 0x1E, 0x6D, 0x29, 0x75, 0x6C, + 0x2E, 0x9D, 0x87, 0x0D, 0x8F, 0x87, 0xCB, 0x14, 0x95, 0x9B, + 0xBE, 0x17, 0x6B, 0x51, 0xD1, 0x4C, 0xDA, 0xD7, 0x91, 0x66, + 0xC5, 0x36, 0xEB, 0xE0, 0x07, 0x1A, 0x76, 0x4D, 0xB0, 0xFB, + 0xC1, 0xF5, 0x5E, 0x05, 0xDB, 0xBA, 0xCB, 0x25, 0xD9, 0x99, + 0x13, 0x1C, 0xC0, 0x35, 0xDC, 0x40, 0xE9, 0x36, 0xCD, 0xC4, + 0xD5, 0x7A, 0x41, 0x70, 0x0F, 0x36, 0xEB, 0xA5, 0x4E, 0x17, + 0x05, 0xD5, 0x75, 0x1B, 0x64, 0x62, 0x7A, 0x3F, 0x0D, 0x28, + 0x48, 0x6A, 0xE3, 0xAC, 0x9C, 0xA8, 0x8F, 0xE9, 0xED, 0xF7, + 0xCD, 0x24, 0xA0, 0xB1, 0xA0, 0x03, 0xAC, 0xE3, 0x03, 0xF5, + 0x3F, 0xD1, 0x96, 0xFF, 0x2A, 0x7E, 0x08, 0xB1, 0xD3, 0xE0, + 0x18, 0x14, 0xEC, 0x65, 0x37, 0x50, 0x43, 0xC2, 0x6A, 0x8C, + 0xF4, 0x5B, 0xFE, 0xC4, 0xCB, 0x8D, 0x3F, 0x81, 0x02, 0xF7, + 0xC2, 0xDD, 0xE4, 0xC1, 0x8E, 0x80, 0x0C, 0x04, 0x25, 0x2D, + 0x80, 0x5A, 0x2E, 0x0F, 0x22, 0x35, 0x4A, 0xF4, 0x85, 0xED, + 0x51, 0xD8, 0xAB, 0x6D, 0x8F, 0xA2, 0x3B, 0x24, 0x00, 0x6E, + 0x81, 0xE2, 0x1E, 0x76, 0xD6, 0xAC, 0x31, 0x12, 0xDB, 0xF3, + 0x8E, 0x07, 0xA1, 0xDE, 0x89, 0x4A, 0x39, 0x60, 0x77, 0xC5, + 0xAA, 0xF1, 0x51, 0xE6, 0x06, 0xF1, 0x95, 0x56, 0x2A, 0xE1, + 0x8E, 0x92, 0x30, 0x9F, 0xFE, 0x58, 0x44, 0xAC, 0x46, 0xF2, + 0xFD, 0x9A, 0xFC, 0xA8, 0x1D, 0xA1, 0xD3, 0x55, 0x37, 0x4A, + 0x8B, 0xFC, 0x9C, 0x33, 0xF8, 0xA7, 0x61, 0x48, 0x41, 0x7C, + 0x9C, 0x77, 0x3F, 0xF5, 0x80, 0x23, 0x7D, 0x43, 0xB4, 0xD5, + 0x88, 0x0A, 0xC9, 0x75, 0xD7, 0x44, 0x19, 0x4D, 0x77, 0x6C, + 0x0B, 0x0A, 0x49, 0xAA, 0x1C, 0x2F, 0xD6, 0x5A, 0x44, 0xA6, + 0x47, 0x4D, 0xE5, 0x36, 0x96, 0x40, 0x99, 0x2C, 0x56, 0x26, + 0xB1, 0xF2, 0x92, 0x31, 0x59, 0xD7, 0x2C, 0xD4, 0xB4, 0x21, + 0xD6, 0x65, 0x13, 0x0B, 0x3E, 0xFB, 0xFF, 0x04, 0xEB, 0xB9, + 0x85, 0xB9, 0xD8, 0xD8, 0x28, 0x4F, 0x5C, 0x17, 0x96, 0xA3, + 0x51, 0xBE, 0xFE, 0x7D, 0x0B, 0x1B, 0x48, 0x40, 0x25, 0x76, + 0x94, 0xDC, 0x41, 0xFB, 0xBF, 0x73, 0x76, 0xDA, 0xEB, 0xB3, + 0x62, 0xE7, 0xC1, 0xC8, 0x54, 0x6A, 0x93, 0xE1, 0x8D, 0x31, + 0xE8, 0x3E, 0x3E, 0xDF, 0xBC, 0x87, 0x02, 0x30, 0x22, 0x57, + 0xC4, 0xE0, 0x18, 0x7A, 0xD3, 0xAE, 0xE4, 0x02, 0x9B, 0xAA, + 0xBD, 0x4E, 0x49, 0x47, 0x72, 0xE9, 0x8D, 0x13, 0x2D, 0x54, + 0x9B, 0x00, 0xA7, 0x91, 0x61, 0x71, 0xC9, 0xCC, 0x48, 0x4F, + 0xEE, 0xDF, 0x5E, 0x1B, 0x1A, 0xDF, 0x67, 0xD3, 0x20, 0xE6, + 0x44, 0x45, 0x98, 0x7E, 0xE7, 0x0E, 0x63, 0x16, 0x83, 0xC9, + 0x26, 0x5D, 0x90, 0xC1, 0xE5, 0x2A, 0x5C, 0x45, 0x54, 0x13, + 0xB2, 0x81, 0x18, 0x06, 0x20, 0x2E, 0x2E, 0x66, 0x5A, 0xB5, + 0x7B, 0x6E, 0xD6, 0x0C, 0x4E, 0x89, 0x01, 0x56, 0x70, 0xBB, + 0xAE, 0xDE, 0xE9, 0x99, 0x5E, 0xD1, 0xB9, 0x3A, 0xB7, 0x6C, + 0x17, 0xB6, 0x03, 0xA9, 0x08, 0xDD, 0x9C, 0xF4, 0x14, 0xC9, + 0xC9, 0x59, 0x39, 0x72, 0xD4, 0x7E, 0x02, 0x37, 0x31, 0xCD, + 0x0E, 0xA7, 0x3D, 0xF8, 0xF2, 0xCF, 0x6B, 0x15, 0xAB, 0x02, + 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x12, 0x30, 0x82, + 0x01, 0x0E, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, + 0x16, 0x04, 0x14, 0xFA, 0x54, 0x89, 0x67, 0xE5, 0x5F, 0xB7, + 0x31, 0x40, 0xEA, 0xFD, 0xE7, 0xF6, 0xA3, 0xC6, 0x5A, 0x56, + 0x16, 0xA5, 0x6E, 0x30, 0x81, 0xDE, 0x06, 0x03, 0x55, 0x1D, + 0x23, 0x04, 0x81, 0xD6, 0x30, 0x81, 0xD3, 0x80, 0x14, 0xFA, + 0x54, 0x89, 0x67, 0xE5, 0x5F, 0xB7, 0x31, 0x40, 0xEA, 0xFD, + 0xE7, 0xF6, 0xA3, 0xC6, 0x5A, 0x56, 0x16, 0xA5, 0x6E, 0xA1, + 0x81, 0xA4, 0xA4, 0x81, 0xA1, 0x30, 0x81, 0x9E, 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, 0x15, 0x30, + 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, 0x6F, + 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, 0x34, 0x30, 0x39, 0x36, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x69, + 0x6E, 0x67, 0x2D, 0x34, 0x30, 0x39, 0x36, 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, 0x14, 0x2F, 0x0F, + 0xAB, 0x23, 0xBC, 0xA3, 0x14, 0x07, 0x91, 0x06, 0x55, 0x35, + 0x01, 0x63, 0x7F, 0x42, 0xBD, 0xFB, 0xF2, 0x43, 0x30, 0x0C, + 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, + 0x01, 0x00, 0x57, 0x0D, 0x97, 0x98, 0x78, 0xBF, 0x2A, 0x31, + 0x9A, 0x39, 0x41, 0x38, 0x33, 0x46, 0xD5, 0x50, 0x47, 0xE8, + 0x19, 0x62, 0xA8, 0x36, 0x1E, 0xB7, 0xFD, 0xD1, 0xBC, 0x50, + 0x5C, 0x3A, 0xEB, 0x96, 0x1A, 0x9B, 0x43, 0xB0, 0x67, 0x5D, + 0xF4, 0x51, 0x77, 0x87, 0x33, 0x0B, 0x90, 0x6F, 0xE8, 0xD3, + 0x82, 0x4D, 0x1A, 0xAA, 0x93, 0x5F, 0x7D, 0x78, 0xB1, 0xE0, + 0x7B, 0xEE, 0x88, 0x01, 0xE7, 0xB3, 0xFA, 0x7E, 0x0B, 0x76, + 0x9C, 0x9E, 0x81, 0x36, 0xE4, 0xA3, 0xC1, 0x41, 0x62, 0xA4, + 0x0A, 0x7E, 0x24, 0xD0, 0xAB, 0x9F, 0xBA, 0xD8, 0x1E, 0x38, + 0xAD, 0xF1, 0x12, 0x52, 0x0D, 0xF2, 0x96, 0x8A, 0x0B, 0x25, + 0xA2, 0x49, 0x3F, 0x88, 0x5B, 0xEA, 0x23, 0x87, 0x26, 0x22, + 0x7A, 0xB9, 0x60, 0x6B, 0xD6, 0x7A, 0x88, 0x37, 0xAC, 0x64, + 0x9B, 0x18, 0x51, 0x07, 0xEA, 0xDF, 0x00, 0x96, 0x70, 0x95, + 0x88, 0x9D, 0x8F, 0xAF, 0xBE, 0x3C, 0x4E, 0xC7, 0x5E, 0x55, + 0x15, 0x3D, 0x1F, 0xE4, 0x2D, 0xDC, 0xC9, 0xA3, 0xAE, 0xAF, + 0xFA, 0x44, 0xA8, 0xE2, 0xF4, 0xDF, 0x8E, 0xCD, 0xF9, 0x10, + 0x7F, 0x8B, 0x86, 0xCC, 0x6D, 0x45, 0x91, 0x91, 0x4F, 0xE3, + 0xD0, 0xA7, 0xD2, 0xD9, 0x8E, 0x09, 0xC6, 0xF8, 0xEB, 0xE7, + 0xBD, 0x17, 0x19, 0xD6, 0xE7, 0x1A, 0xB8, 0xCA, 0x4D, 0xEC, + 0x34, 0x07, 0x7D, 0x2D, 0xE8, 0x23, 0x9D, 0x82, 0xE9, 0xF7, + 0x47, 0x03, 0xAB, 0x5F, 0x7C, 0xF5, 0x41, 0x6F, 0x70, 0x11, + 0xCB, 0x24, 0xD8, 0x23, 0xC2, 0x65, 0x31, 0xB7, 0x0B, 0x8F, + 0x0A, 0x26, 0x5B, 0x0F, 0xF6, 0x9B, 0x11, 0x7F, 0x9A, 0x8D, + 0x94, 0x6D, 0x5A, 0x9C, 0x5E, 0x73, 0x35, 0x15, 0x7B, 0xE3, + 0x09, 0xE8, 0x08, 0xD0, 0x3F, 0xB4, 0xE5, 0x29, 0x2C, 0xF6, + 0x3E, 0x71, 0x6E, 0xF4, 0x1B, 0x20, 0x55, 0x34, 0x40, 0x2F, + 0xB0, 0x9B, 0xDD, 0xF1, 0xDC, 0xBF, 0x17, 0x1D, 0xA7, 0x2D, + 0x85, 0x01, 0xD6, 0xD2, 0xB2, 0x56, 0x56, 0x98, 0x33, 0x85, + 0xED, 0xF6, 0xA3, 0xF6, 0x3E, 0x7B, 0xF4, 0x03, 0xA4, 0x58, + 0x8E, 0xC5, 0x5B, 0xAB, 0x66, 0xE8, 0x0F, 0x34, 0x17, 0x2D, + 0x33, 0x36, 0x71, 0x0C, 0xB8, 0xD9, 0x78, 0xE7, 0x06, 0xFC, + 0xDA, 0x4F, 0xA1, 0xFA, 0xDB, 0x74, 0xCE, 0xEA, 0x85, 0x27, + 0xF9, 0x75, 0xA9, 0xAD, 0x50, 0x86, 0x6E, 0xEA, 0x01, 0x01, + 0x19, 0x0D, 0x28, 0x4A, 0xED, 0x06, 0xBE, 0x65, 0x70, 0xB2, + 0x06, 0x46, 0x2E, 0x16, 0x57, 0xDF, 0x55, 0xC7, 0x8E, 0xCD, + 0x5B, 0xAD, 0x66, 0x28, 0xB8, 0x74, 0x87, 0xBF, 0xC4, 0xC7, + 0x08, 0x3F, 0x37, 0xA3, 0x23, 0x84, 0x9F, 0x4E, 0xE8, 0x48, + 0x6C, 0x8D, 0x54, 0x9F, 0xFB, 0xE0, 0xFB, 0x53, 0xA3, 0x41, + 0xE1, 0x68, 0x8A, 0x94, 0xC9, 0xF5, 0xEE, 0x3E, 0x15, 0x46, + 0xD2, 0x62, 0x33, 0x86, 0x86, 0x06, 0x34, 0xB4, 0xE4, 0x2F, + 0xDA, 0x28, 0x2E, 0x2F, 0xC0, 0xBD, 0x75, 0xE8, 0x2C, 0x3F, + 0xE2, 0xA5, 0x43, 0x7D, 0x02, 0xEB, 0x25, 0xB9, 0xEF, 0x87, + 0x8A, 0xD7, 0x57, 0x61, 0x16, 0xE8, 0x9E, 0x83, 0x65, 0xF9, + 0x10, 0xF4, 0x5E, 0x5F, 0x1C, 0x7A, 0x25, 0xD6, 0x47, 0xBD, + 0x29, 0xC5, 0x4F, 0x8B, 0xB9, 0x6A, 0x48, 0x7A, 0x9B, 0x1E, + 0x6D, 0x77, 0x8E, 0x72, 0x6C, 0x0C, 0x07, 0xFE, 0x4C, 0xC5, + 0xCF, 0x55, 0x0E, 0xCB, 0x4B, 0xAD, 0x16, 0xE1, 0xE2, 0x54, + 0xB8, 0x9D, 0x34, 0x03, 0xD1, 0x8D, 0xB7, 0x37, 0x9B, 0xE3, + 0x5A, 0x32, 0x60, 0x03, 0x7F, 0x61, 0x0F, 0x50, 0x0B, 0x72, + 0x54, 0x8B, 0x0D, 0xC7, 0x97, 0x7E, 0xBB, 0x9B, 0xB2, 0xF7, + 0x73, 0x47, 0x71, 0x7B, 0x78, 0x65, 0x36, 0xDF, 0x57, 0x72, + 0x9E, 0x42, 0x9C, 0x8A +}; +static const int sizeof_client_cert_der_4096 = sizeof(client_cert_der_4096); + +/* ./certs/dh4096.der, 4096-bit */ +static const unsigned char dh_key_der_4096[] = +{ + 0x30, 0x82, 0x02, 0x08, 0x02, 0x82, 0x02, 0x01, 0x00, 0xE9, + 0x0E, 0x3E, 0x79, 0x4F, 0xC9, 0xB2, 0xA0, 0xB1, 0xDB, 0x2F, + 0x1E, 0x24, 0x21, 0x90, 0x5C, 0x50, 0xA4, 0x34, 0xDB, 0x99, + 0x90, 0xAC, 0xF7, 0xBF, 0x2F, 0x01, 0x4B, 0xAC, 0x87, 0x70, + 0xBA, 0xEC, 0xD1, 0x64, 0xDE, 0x04, 0xCA, 0xFC, 0xF9, 0x51, + 0x69, 0x1E, 0xB7, 0x99, 0xE2, 0xB4, 0x0D, 0xDB, 0x5D, 0x78, + 0x38, 0x38, 0x41, 0x05, 0xE8, 0x67, 0x48, 0x65, 0x54, 0x71, + 0xCC, 0xC9, 0xAA, 0x95, 0x1E, 0xD4, 0xBF, 0xBC, 0xCA, 0x5D, + 0xC2, 0x9C, 0x9E, 0x7E, 0x5E, 0x94, 0x5B, 0x2F, 0x60, 0x72, + 0xED, 0xEB, 0x54, 0x0C, 0x48, 0x2B, 0x21, 0x74, 0x4D, 0x37, + 0x04, 0x5A, 0x2F, 0x8B, 0x24, 0x4A, 0xDB, 0xEE, 0xFA, 0xA9, + 0x94, 0x13, 0x8F, 0x52, 0x4A, 0x1B, 0xAE, 0xE6, 0xC8, 0x7F, + 0x99, 0x09, 0x23, 0x84, 0x89, 0xE9, 0xA6, 0x53, 0x82, 0xB6, + 0x03, 0x6D, 0x38, 0x5D, 0x2E, 0xEB, 0x0B, 0xF0, 0xE6, 0xAA, + 0xB1, 0x8B, 0x51, 0xFC, 0xD6, 0x13, 0xFB, 0x20, 0xCB, 0xDF, + 0x79, 0x97, 0xDB, 0x55, 0x74, 0xC2, 0x21, 0xE8, 0xDB, 0x8C, + 0x6A, 0x95, 0x2D, 0x51, 0x91, 0xA7, 0xA1, 0x3C, 0x9B, 0xEF, + 0xF5, 0x43, 0xAC, 0xA6, 0x69, 0xCE, 0x66, 0x5C, 0xD5, 0xB1, + 0xF8, 0xBA, 0xD4, 0x86, 0x25, 0x29, 0x2E, 0x0E, 0x23, 0x05, + 0xDA, 0x7C, 0x7C, 0xC2, 0x7B, 0xC8, 0xB5, 0x79, 0x84, 0x6D, + 0x68, 0x2D, 0x82, 0x4A, 0x35, 0x9F, 0xDC, 0x0E, 0x63, 0x2B, + 0x58, 0x5F, 0x34, 0x7E, 0xA8, 0x73, 0xCE, 0x44, 0x53, 0x11, + 0xE3, 0xDB, 0x46, 0xFA, 0x3A, 0xC3, 0xDA, 0x63, 0xA5, 0x65, + 0x56, 0x99, 0xA5, 0x91, 0x27, 0xD6, 0xE7, 0xDF, 0x2D, 0xEF, + 0xA0, 0x81, 0xB6, 0x07, 0x3A, 0xC6, 0xC1, 0x2B, 0xA1, 0x3A, + 0x74, 0xB4, 0xE9, 0xE1, 0x2F, 0x6B, 0x2B, 0xE4, 0xF0, 0x98, + 0xBE, 0x6F, 0xCB, 0xBB, 0xAE, 0x8D, 0xD2, 0x7E, 0x1B, 0x6F, + 0xBA, 0xF2, 0xB2, 0xB8, 0xB1, 0x5D, 0x9E, 0x79, 0x19, 0xF7, + 0x94, 0xB2, 0xC1, 0x17, 0x5E, 0x9B, 0xB3, 0x05, 0x67, 0x6D, + 0x5C, 0x62, 0x64, 0xA8, 0x2B, 0xB0, 0x36, 0x3D, 0xF9, 0x4C, + 0x65, 0x53, 0xEE, 0x2E, 0x55, 0x69, 0xCC, 0x1C, 0xF5, 0x96, + 0xDC, 0xBE, 0x60, 0x5E, 0x37, 0xEE, 0xD4, 0x63, 0x96, 0x51, + 0x97, 0x96, 0x14, 0x3C, 0x61, 0xBF, 0x53, 0xAA, 0x24, 0xB5, + 0x24, 0x5B, 0x26, 0x67, 0xAD, 0x02, 0x67, 0xB8, 0xD3, 0x05, + 0x6E, 0xA4, 0x8F, 0x46, 0x91, 0x9D, 0x84, 0xA6, 0x2C, 0x44, + 0x9F, 0x2D, 0x18, 0x2F, 0x73, 0xA5, 0xE5, 0xC4, 0xD9, 0x4F, + 0xD9, 0x9F, 0xF5, 0xC0, 0xC5, 0x48, 0xE8, 0x23, 0x32, 0xC4, + 0x4A, 0xCE, 0xFF, 0x3B, 0x16, 0x87, 0x85, 0xA5, 0x1F, 0x22, + 0xA8, 0x0B, 0x91, 0x97, 0x24, 0x95, 0x07, 0xC8, 0x73, 0xD2, + 0xB0, 0x01, 0xF8, 0x20, 0xA9, 0xAB, 0x6B, 0x71, 0x79, 0x24, + 0xF3, 0x79, 0xB5, 0x9B, 0x00, 0xF5, 0xF9, 0xAE, 0x23, 0xAC, + 0xEA, 0xE1, 0x48, 0x88, 0x28, 0x53, 0xE0, 0xC8, 0x76, 0x29, + 0xAE, 0x3E, 0x25, 0x9F, 0x1C, 0xC5, 0x8A, 0x86, 0x33, 0x02, + 0x21, 0xAB, 0xA5, 0x10, 0xF0, 0x07, 0x1B, 0x56, 0x8F, 0xCD, + 0xFC, 0x87, 0x9E, 0x2E, 0xD0, 0x44, 0x98, 0x44, 0x99, 0xB3, + 0xC2, 0x14, 0xCE, 0xD8, 0x93, 0xEA, 0xD1, 0x82, 0x3C, 0x1B, + 0x49, 0xE8, 0x6F, 0x04, 0xB2, 0xF5, 0xAF, 0x9B, 0x37, 0x7D, + 0xE5, 0xE0, 0x56, 0xE9, 0xEE, 0x00, 0x58, 0x25, 0x16, 0x23, + 0xC3, 0x8E, 0xF0, 0xB9, 0xE2, 0x98, 0x5D, 0xF2, 0x4F, 0x5C, + 0xC3, 0x27, 0x2A, 0x67, 0x7D, 0x43, 0xF6, 0x36, 0x76, 0xD4, + 0x2C, 0x7E, 0x16, 0x80, 0xCB, 0xF1, 0x07, 0xDC, 0xB9, 0xF5, + 0xF3, 0x56, 0xBD, 0xF0, 0xFC, 0x00, 0x78, 0x00, 0x56, 0xB4, + 0x3B, 0x02, 0x01, 0x02 +}; +static const int sizeof_dh_key_der_4096 = sizeof(dh_key_der_4096); + +#endif /* USE_CERT_BUFFERS_4096 */ + +#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + +/* ./certs/ecc-client-key.der, ECC */ +static const unsigned char ecc_clikey_der_256[] = +{ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xF8, 0xCF, 0x92, + 0x6B, 0xBD, 0x1E, 0x28, 0xF1, 0xA8, 0xAB, 0xA1, 0x23, 0x4F, + 0x32, 0x74, 0x18, 0x88, 0x50, 0xAD, 0x7E, 0xC7, 0xEC, 0x92, + 0xF8, 0x8F, 0x97, 0x4D, 0xAF, 0x56, 0x89, 0x65, 0xC7, 0xA0, + 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, + 0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x55, 0xBF, 0xF4, + 0x0F, 0x44, 0x50, 0x9A, 0x3D, 0xCE, 0x9B, 0xB7, 0xF0, 0xC5, + 0x4D, 0xF5, 0x70, 0x7B, 0xD4, 0xEC, 0x24, 0x8E, 0x19, 0x80, + 0xEC, 0x5A, 0x4C, 0xA2, 0x24, 0x03, 0x62, 0x2C, 0x9B, 0xDA, + 0xEF, 0xA2, 0x35, 0x12, 0x43, 0x84, 0x76, 0x16, 0xC6, 0x56, + 0x95, 0x06, 0xCC, 0x01, 0xA9, 0xBD, 0xF6, 0x75, 0x1A, 0x42, + 0xF7, 0xBD, 0xA9, 0xB2, 0x36, 0x22, 0x5F, 0xC7, 0x5D, 0x7F, + 0xB4 +}; +static const int sizeof_ecc_clikey_der_256 = sizeof(ecc_clikey_der_256); + +/* ./certs/ecc-client-keyPub.der, ECC */ +static const unsigned char ecc_clikeypub_der_256[] = +{ + 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, 0x55, 0xBF, 0xF4, + 0x0F, 0x44, 0x50, 0x9A, 0x3D, 0xCE, 0x9B, 0xB7, 0xF0, 0xC5, + 0x4D, 0xF5, 0x70, 0x7B, 0xD4, 0xEC, 0x24, 0x8E, 0x19, 0x80, + 0xEC, 0x5A, 0x4C, 0xA2, 0x24, 0x03, 0x62, 0x2C, 0x9B, 0xDA, + 0xEF, 0xA2, 0x35, 0x12, 0x43, 0x84, 0x76, 0x16, 0xC6, 0x56, + 0x95, 0x06, 0xCC, 0x01, 0xA9, 0xBD, 0xF6, 0x75, 0x1A, 0x42, + 0xF7, 0xBD, 0xA9, 0xB2, 0x36, 0x22, 0x5F, 0xC7, 0x5D, 0x7F, + 0xB4 +}; +static const int sizeof_ecc_clikeypub_der_256 = sizeof(ecc_clikeypub_der_256); + +/* ./certs/client-ecc-cert.der, ECC */ +static const unsigned char cliecc_cert_der_256[] = +{ + 0x30, 0x82, 0x03, 0x08, 0x30, 0x82, 0x02, 0xAF, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x93, 0xBF, 0x6A, 0xDE, + 0x9B, 0x41, 0x9D, 0xAD, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81, 0x8D, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x06, 0x4F, 0x72, 0x65, 0x67, 0x6F, 0x6E, 0x31, + 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x05, + 0x53, 0x61, 0x6C, 0x65, 0x6D, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0A, 0x43, 0x6C, 0x69, 0x65, + 0x6E, 0x74, 0x20, 0x45, 0x43, 0x43, 0x31, 0x0D, 0x30, 0x0B, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x04, 0x46, 0x61, 0x73, + 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, 0x38, 0x30, 0x34, 0x31, 0x33, + 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x17, 0x0D, 0x32, + 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x31, + 0x30, 0x5A, 0x30, 0x81, 0x8D, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0F, + 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x06, 0x4F, + 0x72, 0x65, 0x67, 0x6F, 0x6E, 0x31, 0x0E, 0x30, 0x0C, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x05, 0x53, 0x61, 0x6C, 0x65, + 0x6D, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0A, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x45, + 0x43, 0x43, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x04, 0x46, 0x61, 0x73, 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, 0x55, 0xBF, 0xF4, 0x0F, 0x44, 0x50, 0x9A, + 0x3D, 0xCE, 0x9B, 0xB7, 0xF0, 0xC5, 0x4D, 0xF5, 0x70, 0x7B, + 0xD4, 0xEC, 0x24, 0x8E, 0x19, 0x80, 0xEC, 0x5A, 0x4C, 0xA2, + 0x24, 0x03, 0x62, 0x2C, 0x9B, 0xDA, 0xEF, 0xA2, 0x35, 0x12, + 0x43, 0x84, 0x76, 0x16, 0xC6, 0x56, 0x95, 0x06, 0xCC, 0x01, + 0xA9, 0xBD, 0xF6, 0x75, 0x1A, 0x42, 0xF7, 0xBD, 0xA9, 0xB2, + 0x36, 0x22, 0x5F, 0xC7, 0x5D, 0x7F, 0xB4, 0xA3, 0x81, 0xF5, + 0x30, 0x81, 0xF2, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, + 0x04, 0x16, 0x04, 0x14, 0xEB, 0xD4, 0x4B, 0x59, 0x6B, 0x95, + 0x61, 0x3F, 0x51, 0x57, 0xB6, 0x04, 0x4D, 0x89, 0x41, 0x88, + 0x44, 0x5C, 0xAB, 0xF2, 0x30, 0x81, 0xC2, 0x06, 0x03, 0x55, + 0x1D, 0x23, 0x04, 0x81, 0xBA, 0x30, 0x81, 0xB7, 0x80, 0x14, + 0xEB, 0xD4, 0x4B, 0x59, 0x6B, 0x95, 0x61, 0x3F, 0x51, 0x57, + 0xB6, 0x04, 0x4D, 0x89, 0x41, 0x88, 0x44, 0x5C, 0xAB, 0xF2, + 0xA1, 0x81, 0x93, 0xA4, 0x81, 0x90, 0x30, 0x81, 0x8D, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x06, 0x4F, 0x72, 0x65, 0x67, 0x6F, 0x6E, 0x31, + 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x05, + 0x53, 0x61, 0x6C, 0x65, 0x6D, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0A, 0x43, 0x6C, 0x69, 0x65, + 0x6E, 0x74, 0x20, 0x45, 0x43, 0x43, 0x31, 0x0D, 0x30, 0x0B, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x04, 0x46, 0x61, 0x73, + 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, 0x93, 0xBF, 0x6A, 0xDE, 0x9B, 0x41, 0x9D, + 0xAD, 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, 0x47, 0x00, + 0x30, 0x44, 0x02, 0x20, 0x61, 0xBC, 0x9D, 0x4D, 0x88, 0x64, + 0x86, 0xB8, 0x71, 0xAA, 0x35, 0x59, 0x68, 0xB8, 0xEE, 0x2C, + 0xF3, 0x23, 0xB5, 0x1A, 0xB9, 0xBA, 0x41, 0x50, 0xA8, 0xC6, + 0xC3, 0x58, 0xEB, 0x58, 0xBD, 0x60, 0x02, 0x20, 0x61, 0xAA, + 0xEB, 0xB5, 0x73, 0x0D, 0x01, 0xDB, 0x69, 0x8F, 0x52, 0xF5, + 0x72, 0x6D, 0x37, 0x42, 0xB5, 0xFD, 0x94, 0xB6, 0x6E, 0xB1, + 0xC4, 0x25, 0x2E, 0x96, 0x96, 0xF3, 0x39, 0xB2, 0x5D, 0xEA + +}; +static const int sizeof_cliecc_cert_der_256 = sizeof(cliecc_cert_der_256); + +/* ./certs/ecc-key.der, ECC */ +static const unsigned char ecc_key_der_256[] = +{ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x45, 0xB6, 0x69, + 0x02, 0x73, 0x9C, 0x6C, 0x85, 0xA1, 0x38, 0x5B, 0x72, 0xE8, + 0xE8, 0xC7, 0xAC, 0xC4, 0x03, 0x8D, 0x53, 0x35, 0x04, 0xFA, + 0x6C, 0x28, 0xDC, 0x34, 0x8D, 0xE1, 0xA8, 0x09, 0x8C, 0xA0, + 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, + 0x07, 0xA1, 0x44, 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 +}; +static const int sizeof_ecc_key_der_256 = sizeof(ecc_key_der_256); + +/* ./certs/ecc-keyPub.der, ECC */ +static const unsigned char ecc_key_pub_der_256[] = +{ + 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 +}; +static const int sizeof_ecc_key_pub_der_256 = sizeof(ecc_key_pub_der_256); + +/* ./certs/server-ecc-comp.der, ECC */ +static const unsigned char serv_ecc_comp_der_256[] = +{ + 0x30, 0x82, 0x03, 0x23, 0x30, 0x82, 0x02, 0xCA, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x80, 0x78, 0xC9, 0xB7, + 0x06, 0x5A, 0xC5, 0x83, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81, 0xA0, 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, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, 0x45, + 0x6C, 0x6C, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x2D, 0x20, + 0x63, 0x6F, 0x6D, 0x70, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x45, 0x43, 0x43, 0x2D, 0x63, 0x6F, 0x6D, 0x70, + 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, 0x38, 0x30, 0x34, 0x31, 0x33, 0x31, + 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x31, + 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, + 0x5A, 0x30, 0x81, 0xA0, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x0F, 0x45, 0x6C, 0x6C, 0x69, 0x70, 0x74, + 0x69, 0x63, 0x20, 0x2D, 0x20, 0x63, 0x6F, 0x6D, 0x70, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0F, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x45, 0x43, 0x43, + 0x2D, 0x63, 0x6F, 0x6D, 0x70, 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, 0x39, 0x30, 0x13, 0x06, 0x07, + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, + 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x22, 0x00, + 0x02, 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, 0xA3, 0x82, 0x01, 0x09, 0x30, 0x82, 0x01, + 0x05, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, + 0x04, 0x14, 0x8C, 0x38, 0x3A, 0x6B, 0xB8, 0x24, 0xB7, 0xDF, + 0x6E, 0xF4, 0x59, 0xAC, 0x56, 0x4E, 0xAA, 0xE2, 0x58, 0xA6, + 0x5A, 0x18, 0x30, 0x81, 0xD5, 0x06, 0x03, 0x55, 0x1D, 0x23, + 0x04, 0x81, 0xCD, 0x30, 0x81, 0xCA, 0x80, 0x14, 0x8C, 0x38, + 0x3A, 0x6B, 0xB8, 0x24, 0xB7, 0xDF, 0x6E, 0xF4, 0x59, 0xAC, + 0x56, 0x4E, 0xAA, 0xE2, 0x58, 0xA6, 0x5A, 0x18, 0xA1, 0x81, + 0xA6, 0xA4, 0x81, 0xA3, 0x30, 0x81, 0xA0, 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, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, 0x45, 0x6C, 0x6C, + 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x2D, 0x20, 0x63, 0x6F, + 0x6D, 0x70, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x0F, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, + 0x45, 0x43, 0x43, 0x2D, 0x63, 0x6F, 0x6D, 0x70, 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, + 0x80, 0x78, 0xC9, 0xB7, 0x06, 0x5A, 0xC5, 0x83, 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, 0x47, 0x00, 0x30, 0x44, 0x02, + 0x20, 0x31, 0x44, 0xD0, 0x4E, 0xD7, 0xC4, 0xB4, 0x96, 0xA3, + 0xE6, 0x25, 0xFD, 0xFA, 0xD6, 0x28, 0xA8, 0x67, 0x51, 0x72, + 0x90, 0x95, 0x31, 0xF9, 0xCD, 0x10, 0xBF, 0x11, 0xE4, 0xEC, + 0xB7, 0x42, 0x5B, 0x02, 0x20, 0x45, 0xDB, 0x45, 0x0A, 0x24, + 0x58, 0x8E, 0x2E, 0xE6, 0xEA, 0x0C, 0x6C, 0xBC, 0x72, 0x4F, + 0x0A, 0x1B, 0xF3, 0x2D, 0x97, 0xE9, 0xC2, 0x19, 0xF9, 0x97, + 0x3A, 0x60, 0xDD, 0x08, 0xD3, 0x52, 0x3E +}; +static const int sizeof_serv_ecc_comp_der_256 = sizeof(serv_ecc_comp_der_256); + +/* ./certs/server-ecc-rsa.der, ECC */ +static const unsigned char serv_ecc_rsa_der_256[] = +{ + 0x30, 0x82, 0x03, 0xE0, 0x30, 0x82, 0x02, 0xC8, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x30, 0x81, 0x94, 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, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, + 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, + 0x69, 0x6E, 0x67, 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, 0x38, 0x30, 0x34, + 0x31, 0x33, 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x17, + 0x0D, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, + 0x33, 0x31, 0x30, 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, 0x1A, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x11, 0x45, 0x6C, 0x6C, + 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x2D, 0x20, 0x52, 0x53, + 0x41, 0x73, 0x69, 0x67, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x45, 0x43, 0x43, 0x2D, 0x52, + 0x53, 0x41, 0x73, 0x69, 0x67, 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, 0xFC, 0x30, 0x81, + 0xF9, 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, 0xC9, 0x06, 0x03, 0x55, 0x1D, 0x23, + 0x04, 0x81, 0xC1, 0x30, 0x81, 0xBE, 0x80, 0x14, 0x27, 0x8E, + 0x67, 0x11, 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, 0x33, 0x63, + 0xB3, 0xA4, 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, 0xA1, 0x81, + 0x9A, 0xA4, 0x81, 0x97, 0x30, 0x81, 0x94, 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, 0x11, 0x30, 0x0F, + 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, + 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, + 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 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, 0x86, 0xFF, + 0xF5, 0x8E, 0x10, 0xDE, 0xB8, 0xFB, 0x30, 0x0C, 0x06, 0x03, + 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, + 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, + 0x0C, 0xBB, 0x67, 0xBD, 0xFC, 0xCD, 0x53, 0x6C, 0xFB, 0x4E, + 0x58, 0xC8, 0xEA, 0x52, 0x92, 0xEB, 0xE4, 0xC8, 0xBC, 0x57, + 0x0F, 0x08, 0x20, 0xC8, 0x83, 0xB0, 0xD5, 0xEA, 0x57, 0x27, + 0xBD, 0x68, 0x91, 0xFB, 0x99, 0x84, 0x8D, 0x15, 0x9E, 0x4F, + 0x8F, 0xC4, 0xCB, 0x34, 0x61, 0xC0, 0x59, 0x12, 0x9B, 0xC8, + 0x82, 0x17, 0x38, 0x4F, 0x9E, 0x53, 0x08, 0xA3, 0x69, 0x2E, + 0x2F, 0xC0, 0xB4, 0x2F, 0xA2, 0x4E, 0x10, 0x64, 0xB0, 0x07, + 0xA1, 0x51, 0x08, 0x1D, 0x91, 0x53, 0xA2, 0x79, 0x55, 0x20, + 0x41, 0x65, 0x35, 0x3E, 0x0B, 0x38, 0x01, 0x57, 0x02, 0x8C, + 0x25, 0xE7, 0xAB, 0x4F, 0x8B, 0x59, 0xF0, 0xED, 0x8E, 0x4A, + 0x15, 0x0B, 0x32, 0xFB, 0x7A, 0x8B, 0x02, 0xEA, 0x9D, 0xE1, + 0xAB, 0xC4, 0x07, 0xCC, 0xDA, 0x0F, 0xA3, 0x16, 0xDB, 0x8E, + 0x5B, 0xBC, 0x96, 0xAB, 0x10, 0xB8, 0xDE, 0x09, 0x8B, 0xF7, + 0xCB, 0xA7, 0x78, 0x66, 0x17, 0xE3, 0x25, 0x6E, 0x57, 0x9D, + 0x13, 0x61, 0x7B, 0x55, 0x1A, 0xDF, 0x8F, 0x39, 0x15, 0x4E, + 0x42, 0x22, 0x00, 0x85, 0xC4, 0x51, 0x0B, 0x6B, 0xA6, 0x67, + 0xC0, 0xFB, 0xEA, 0x22, 0x77, 0x7D, 0x48, 0x76, 0xAB, 0x39, + 0x20, 0x09, 0xD5, 0x52, 0x89, 0x3E, 0x6B, 0x30, 0x7B, 0x50, + 0x18, 0xE8, 0x62, 0x05, 0xBE, 0xBB, 0x7F, 0x16, 0x77, 0x9C, + 0xBB, 0x5A, 0x22, 0x96, 0x99, 0xB0, 0x96, 0x83, 0xB7, 0x43, + 0x31, 0x97, 0xCF, 0xFD, 0x85, 0x52, 0xD8, 0x52, 0xC8, 0x67, + 0x5C, 0xF8, 0x22, 0x72, 0x35, 0x93, 0x92, 0x6C, 0xEC, 0x3C, + 0x6A, 0xC6, 0x81, 0x20, 0xA5, 0xCD, 0x50, 0xF9, 0x21, 0x7A, + 0xA6, 0x7A, 0x1E, 0xE7, 0x59, 0x22, 0x5D, 0x8A, 0x93, 0x51, + 0x8E, 0xFB, 0x29, 0x56, 0xFB, 0xBE, 0x9B, 0x87, 0x48, 0x5F, + 0xA5, 0x72, 0xE7, 0x4E, 0xFE, 0x5E +}; +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, 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, 0x8B, 0x30, 0x82, 0x02, 0x30, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xFD, 0x0E, 0x29, 0x21, + 0x66, 0xCB, 0x48, 0xA3, 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, 0x38, 0x30, 0x34, 0x31, 0x33, + 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x17, 0x0D, 0x32, + 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x31, + 0x30, 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, 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, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xF0, 0x7B, + 0xCC, 0x24, 0x73, 0x19, 0x3F, 0x61, 0x68, 0xED, 0xC8, 0x0A, + 0x54, 0x4A, 0xB8, 0xAC, 0x79, 0xEF, 0x10, 0x32, 0x91, 0x52, + 0x2C, 0x3E, 0xBF, 0x50, 0xAA, 0x5F, 0x18, 0xC1, 0x97, 0xF5, + 0x02, 0x21, 0x00, 0xD9, 0x4B, 0x63, 0x67, 0x6F, 0x9B, 0x29, + 0xA9, 0xD7, 0x6B, 0x63, 0x9B, 0x98, 0x9F, 0x32, 0x82, 0x36, + 0xDA, 0xF0, 0xA9, 0xF7, 0x51, 0xB4, 0x97, 0xAA, 0xFA, 0xFA, + 0xDD, 0xEF, 0xEF, 0x4A, 0xAE +}; +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, 0xFC, 0x39, 0x04, 0xA4, + 0x0E, 0xA5, 0x6C, 0x87, 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, 0x38, 0x30, 0x34, 0x31, 0x33, + 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x17, 0x0D, 0x32, + 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x31, + 0x30, 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, 0x0D, 0x0A, 0x62, 0xFB, + 0xE6, 0x3A, 0xFE, 0x71, 0xD8, 0x2B, 0x44, 0xE5, 0x97, 0x34, + 0x04, 0xA9, 0x8C, 0x0A, 0x99, 0x88, 0xA0, 0xBD, 0x1F, 0xB0, + 0xDF, 0x94, 0x59, 0x27, 0xBB, 0x2B, 0xC6, 0x2A, 0xBE, 0xA4, + 0x69, 0x1B, 0xCF, 0x97, 0x78, 0x2A, 0x28, 0x96, 0xEE, 0xBA, + 0xD4, 0x87, 0x45, 0xFD, 0x02, 0x31, 0x00, 0xC0, 0x73, 0x19, + 0x66, 0x76, 0x5E, 0x9F, 0xA3, 0x65, 0x85, 0x41, 0xEF, 0xB7, + 0x7B, 0x3D, 0x63, 0x6D, 0x98, 0x71, 0x99, 0x6F, 0x9C, 0xDB, + 0xA8, 0x5E, 0x53, 0x6E, 0xA0, 0x68, 0x11, 0x65, 0xBC, 0x78, + 0x74, 0x28, 0x69, 0xC7, 0x64, 0x9D, 0x88, 0xF2, 0xD8, 0xC2, + 0x3D, 0x29, 0x03, 0x83, 0x23 +}; +static const int sizeof_ca_ecc_cert_der_384 = sizeof(ca_ecc_cert_der_384); + +#endif /* HAVE_ECC && USE_CERT_BUFFERS_256 */ /* dh1024 p */ static const unsigned char dh_p[] = @@ -1221,6 +3909,240 @@ 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, 0x52, 0x30, 0x82, 0x02, 0x04, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x10, 0x00, 0xCD, 0xF2, 0x2F, 0xBE, + 0xDC, 0x07, 0xFA, 0xBB, 0x65, 0x03, 0xE2, 0xFF, 0xEA, 0x6A, + 0x99, 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, 0x38, 0x30, 0x34, 0x31, 0x32, + 0x31, 0x36, 0x32, 0x32, 0x31, 0x37, 0x5A, 0x18, 0x0F, 0x32, + 0x30, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, + 0x32, 0x31, 0x37, 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, 0x61, 0x5D, + 0xEC, 0xB7, 0x45, 0x93, 0xC9, 0x84, 0x7B, 0x68, 0x21, 0x4A, + 0x4D, 0xF4, 0x04, 0x8B, 0xBD, 0xCD, 0x6C, 0x5D, 0x3D, 0xB7, + 0x62, 0x2C, 0x2D, 0x25, 0xC3, 0x22, 0x49, 0xC8, 0x86, 0xF2, + 0xA3, 0x52, 0x30, 0x50, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, + 0x0E, 0x04, 0x16, 0x04, 0x14, 0x33, 0xC8, 0x28, 0x63, 0x8C, + 0xF4, 0x57, 0xEE, 0x1E, 0xB0, 0xC7, 0x12, 0x12, 0x76, 0x8A, + 0x80, 0x30, 0x3A, 0xCB, 0x10, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x92, 0x3F, + 0x96, 0x72, 0x02, 0xFA, 0x61, 0x1C, 0x21, 0x6D, 0x88, 0xDD, + 0xEB, 0xDD, 0x3C, 0x9B, 0x17, 0xC4, 0x9F, 0xB7, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, + 0x03, 0x02, 0x06, 0xC0, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, + 0x70, 0x03, 0x41, 0x00, 0x15, 0x88, 0x86, 0xFC, 0x66, 0xD1, + 0xE0, 0xF6, 0xCF, 0xC9, 0x09, 0x46, 0xD0, 0x50, 0xE2, 0x01, + 0x5D, 0xF7, 0xCF, 0x57, 0xB8, 0xBA, 0x90, 0x84, 0xCB, 0xF1, + 0x24, 0x4B, 0xEF, 0xA5, 0x95, 0x7D, 0x69, 0x92, 0x88, 0xA8, + 0x89, 0x63, 0xCC, 0x90, 0x40, 0xC2, 0x41, 0x3A, 0x40, 0x76, + 0xB1, 0x2D, 0xA8, 0xA8, 0x97, 0xC9, 0x73, 0xC7, 0x82, 0x30, + 0x24, 0x61, 0xB0, 0xAA, 0xCA, 0xAA, 0x68, 0x00 +}; +static const int sizeof_server_ed25519_cert = sizeof(server_ed25519_cert); + +/* ./certs/ed25519/server-ed25519-key.der, ED25519 */ +static const unsigned char server_ed25519_key[] = +{ + 0x30, 0x52, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2B, + 0x65, 0x70, 0x04, 0x22, 0x04, 0x20, 0x02, 0x2F, 0xC5, 0xFF, + 0xBA, 0x8E, 0xD0, 0xD2, 0xBF, 0x03, 0x8E, 0x76, 0x8F, 0xC8, + 0x86, 0x80, 0x71, 0x87, 0x97, 0x31, 0xE2, 0x40, 0xAC, 0xDF, + 0xBB, 0x90, 0x15, 0x52, 0x6E, 0x24, 0xA1, 0x39, 0xA1, 0x22, + 0x04, 0x20, 0x61, 0x5D, 0xEC, 0xB7, 0x45, 0x93, 0xC9, 0x84, + 0x7B, 0x68, 0x21, 0x4A, 0x4D, 0xF4, 0x04, 0x8B, 0xBD, 0xCD, + 0x6C, 0x5D, 0x3D, 0xB7, 0x62, 0x2C, 0x2D, 0x25, 0xC3, 0x22, + 0x49, 0xC8, 0x86, 0xF2 +}; +static const int sizeof_server_ed25519_key = sizeof(server_ed25519_key); + +/* ./certs/ed25519/ca-ed25519.der, ED25519 */ +static const unsigned char ca_ed25519_cert[] = +{ + 0x30, 0x82, 0x02, 0x60, 0x30, 0x82, 0x02, 0x12, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x10, 0x00, 0x80, 0xBA, 0x68, 0x77, + 0xEF, 0xA5, 0xE5, 0x42, 0x7D, 0xC6, 0x73, 0x2C, 0x54, 0x85, + 0xB8, 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, 0x38, 0x30, 0x34, + 0x31, 0x32, 0x31, 0x36, 0x32, 0x32, 0x31, 0x37, 0x5A, 0x18, + 0x0F, 0x32, 0x30, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, + 0x35, 0x32, 0x32, 0x31, 0x37, 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, 0x65, 0xAA, + 0x7F, 0x05, 0xA4, 0x04, 0x34, 0xA0, 0xEA, 0xAD, 0x1F, 0xA9, + 0x86, 0xF0, 0xD8, 0x7F, 0x72, 0xDF, 0xA9, 0x0E, 0x13, 0xA0, + 0x38, 0x66, 0x26, 0x5E, 0xEB, 0x48, 0x30, 0x80, 0x48, 0x49, + 0xA3, 0x60, 0x30, 0x5E, 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, + 0x3F, 0x96, 0x72, 0x02, 0xFA, 0x61, 0x1C, 0x21, 0x6D, 0x88, + 0xDD, 0xEB, 0xDD, 0x3C, 0x9B, 0x17, 0xC4, 0x9F, 0xB7, 0x30, + 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, + 0x80, 0x14, 0xFE, 0x01, 0x46, 0x7F, 0x6F, 0x2B, 0x3E, 0x1C, + 0xB0, 0x6F, 0xE1, 0xCC, 0x4D, 0x02, 0x25, 0xF7, 0x4D, 0x0A, + 0x95, 0xB8, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, + 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0xC6, 0x30, 0x05, + 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x41, 0x00, 0x4C, 0x40, + 0xD0, 0x7F, 0xBC, 0xFB, 0xF4, 0xA2, 0x1A, 0x58, 0xF6, 0x72, + 0xE3, 0xE8, 0xDA, 0x18, 0x0D, 0x94, 0xDC, 0x0E, 0xFD, 0xC1, + 0xE7, 0x02, 0xA5, 0x7A, 0xEE, 0xCB, 0xC2, 0x7E, 0xFA, 0xA1, + 0xFC, 0x15, 0x9A, 0xFE, 0x1E, 0xE0, 0x37, 0xDF, 0x7F, 0xAB, + 0x76, 0x50, 0x06, 0xD4, 0x3D, 0x1A, 0x65, 0x73, 0x3F, 0x92, + 0xD4, 0x44, 0x62, 0xA7, 0x4C, 0xB3, 0x2A, 0x01, 0x87, 0xE3, + 0x06, 0x06 +}; +static const int sizeof_ca_ed25519_cert = sizeof(ca_ed25519_cert); + +/* ./certs/ed25519/client-ed25519.der, ED25519 */ +static const unsigned char client_ed25519_cert[] = +{ + 0x30, 0x82, 0x02, 0x58, 0x30, 0x82, 0x02, 0x0A, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x10, 0x00, 0x8F, 0x2F, 0x35, 0xB2, + 0x53, 0xBD, 0x4F, 0x92, 0xD1, 0xFF, 0x1D, 0x4B, 0x40, 0xA5, + 0x49, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x30, 0x81, + 0xA1, 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, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, + 0x06, 0x63, 0x6C, 0x69, 0x65, 0x6E, 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, 0x38, + 0x30, 0x34, 0x31, 0x32, 0x31, 0x36, 0x32, 0x32, 0x31, 0x37, + 0x5A, 0x18, 0x0F, 0x32, 0x30, 0x32, 0x31, 0x30, 0x31, 0x30, + 0x37, 0x31, 0x35, 0x32, 0x32, 0x31, 0x37, 0x5A, 0x30, 0x81, + 0xA1, 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, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, + 0x06, 0x63, 0x6C, 0x69, 0x65, 0x6E, 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, 0x2A, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, + 0x70, 0x03, 0x21, 0x00, 0xA2, 0xF1, 0x26, 0x40, 0x9B, 0xA2, + 0x59, 0xDA, 0xDB, 0xE6, 0x15, 0x7F, 0x9A, 0x11, 0xB5, 0x48, + 0x5F, 0x55, 0xBA, 0x5E, 0xED, 0x46, 0xF7, 0x98, 0x67, 0xBE, + 0x0C, 0x93, 0xE3, 0xA4, 0x8E, 0x18, 0xA3, 0x52, 0x30, 0x50, + 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0xFE, 0x01, 0x46, 0x7F, 0x6F, 0x2B, 0x3E, 0x1C, 0xB0, + 0x6F, 0xE1, 0xCC, 0x4D, 0x02, 0x25, 0xF7, 0x4D, 0x0A, 0x95, + 0xB8, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0xFE, 0x01, 0x46, 0x7F, 0x6F, 0x2B, + 0x3E, 0x1C, 0xB0, 0x6F, 0xE1, 0xCC, 0x4D, 0x02, 0x25, 0xF7, + 0x4D, 0x0A, 0x95, 0xB8, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, + 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x06, 0xC0, + 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x41, 0x00, + 0x29, 0xF6, 0x69, 0xE2, 0xB9, 0x73, 0x12, 0xD1, 0x64, 0xEB, + 0x8F, 0xE9, 0x6B, 0x61, 0xDB, 0x5F, 0xE9, 0xA7, 0x62, 0x6C, + 0x10, 0x89, 0x41, 0x80, 0xE3, 0xE8, 0xFD, 0x1F, 0xD0, 0x13, + 0xAE, 0x95, 0x00, 0xAF, 0xF7, 0x77, 0xE1, 0x22, 0x32, 0xAD, + 0x46, 0x4F, 0xDC, 0x7E, 0xFE, 0xAE, 0xBC, 0x8A, 0x1F, 0x96, + 0x0A, 0xDA, 0x9F, 0xC9, 0x93, 0x52, 0x27, 0x18, 0xB0, 0x8B, + 0xDA, 0xBE, 0x81, 0x09 +}; +static const int sizeof_client_ed25519_cert = sizeof(client_ed25519_cert); + +/* ./certs/ed25519/client-ed25519-key.der, ED25519 */ +static const unsigned char client_ed25519_key[] = +{ + 0x30, 0x52, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2B, + 0x65, 0x70, 0x04, 0x22, 0x04, 0x20, 0x27, 0xA3, 0x34, 0x2A, + 0x35, 0xD4, 0xBB, 0xB8, 0xE1, 0xDC, 0xD8, 0xEC, 0x0F, 0xC1, + 0xA0, 0xD1, 0xA2, 0x5C, 0xF9, 0x06, 0xF0, 0x44, 0x5D, 0x3B, + 0x97, 0x4D, 0xBD, 0xDF, 0x4A, 0x3B, 0xA3, 0x4E, 0xA1, 0x22, + 0x04, 0x20, 0xA2, 0xF1, 0x26, 0x40, 0x9B, 0xA2, 0x59, 0xDA, + 0xDB, 0xE6, 0x15, 0x7F, 0x9A, 0x11, 0xB5, 0x48, 0x5F, 0x55, + 0xBA, 0x5E, 0xED, 0x46, 0xF7, 0x98, 0x67, 0xBE, 0x0C, 0x93, + 0xE3, 0xA4, 0x8E, 0x18 +}; +static const int sizeof_client_ed25519_key = sizeof(client_ed25519_key); + +#endif /* HAVE_ED25519 */ #endif /* WOLFSSL_CERTS_TEST_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/crl.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/crl.h index 05c039aa3..363d77cb9 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/crl.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/crl.h @@ -1,8 +1,8 @@ /* crl.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLFSSL_CRL_H #define WOLFSSL_CRL_H @@ -33,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/FreeRTOS-Plus/Source/WolfSSL/wolfssl/error-ssl.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/error-ssl.h index f151c3fb5..9b44326e7 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/error-ssl.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/error-ssl.h @@ -1,8 +1,8 @@ /* error-ssl.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLFSSL_ERROR_H #define WOLFSSL_ERROR_H @@ -30,124 +31,160 @@ #endif enum wolfSSL_ErrorCodes { - INPUT_CASE_ERROR = -301, /* process input state error */ - PREFIX_ERROR = -302, /* bad index to key rounds */ - MEMORY_ERROR = -303, /* out of memory */ - VERIFY_FINISHED_ERROR = -304, /* verify problem on finished */ - VERIFY_MAC_ERROR = -305, /* verify mac problem */ - PARSE_ERROR = -306, /* parse error on header */ - UNKNOWN_HANDSHAKE_TYPE = -307, /* weird handshake type */ - SOCKET_ERROR_E = -308, /* error state on socket */ - SOCKET_NODATA = -309, /* expected data, not there */ - INCOMPLETE_DATA = -310, /* don't have enough data to + INPUT_CASE_ERROR = -301, /* process input state error */ + PREFIX_ERROR = -302, /* bad index to key rounds */ + MEMORY_ERROR = -303, /* out of memory */ + VERIFY_FINISHED_ERROR = -304, /* verify problem on finished */ + VERIFY_MAC_ERROR = -305, /* verify mac problem */ + PARSE_ERROR = -306, /* parse error on header */ + UNKNOWN_HANDSHAKE_TYPE = -307, /* weird handshake type */ + SOCKET_ERROR_E = -308, /* error state on socket */ + SOCKET_NODATA = -309, /* expected data, not there */ + INCOMPLETE_DATA = -310, /* don't have enough data to complete task */ - UNKNOWN_RECORD_TYPE = -311, /* unknown type in record hdr */ - DECRYPT_ERROR = -312, /* error during decryption */ - FATAL_ERROR = -313, /* recvd alert fatal error */ - ENCRYPT_ERROR = -314, /* error during encryption */ - FREAD_ERROR = -315, /* fread problem */ - NO_PEER_KEY = -316, /* need peer's key */ - NO_PRIVATE_KEY = -317, /* need the private key */ - RSA_PRIVATE_ERROR = -318, /* error during rsa priv op */ - NO_DH_PARAMS = -319, /* server missing DH params */ - BUILD_MSG_ERROR = -320, /* build message failure */ + UNKNOWN_RECORD_TYPE = -311, /* unknown type in record hdr */ + DECRYPT_ERROR = -312, /* error during decryption */ + FATAL_ERROR = -313, /* recvd alert fatal error */ + ENCRYPT_ERROR = -314, /* error during encryption */ + FREAD_ERROR = -315, /* fread problem */ + NO_PEER_KEY = -316, /* need peer's key */ + NO_PRIVATE_KEY = -317, /* need the private key */ + RSA_PRIVATE_ERROR = -318, /* error during rsa priv op */ + NO_DH_PARAMS = -319, /* server missing DH params */ + BUILD_MSG_ERROR = -320, /* build message failure */ - BAD_HELLO = -321, /* client hello malformed */ - 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 */ - VERIFY_CERT_ERROR = -329, /* verify cert error */ - VERIFY_SIGN_ERROR = -330, /* verify sign error */ - CLIENT_ID_ERROR = -331, /* psk client identity error */ - SERVER_HINT_ERROR = -332, /* psk server hint error */ - PSK_KEY_ERROR = -333, /* psk key error */ - ZLIB_INIT_ERROR = -334, /* zlib init error */ - ZLIB_COMPRESS_ERROR = -335, /* zlib compression error */ - ZLIB_DECOMPRESS_ERROR = -336, /* zlib decompression error */ + BAD_HELLO = -321, /* client hello malformed */ + DOMAIN_NAME_MISMATCH = -322, /* peer subject name mismatch */ + WANT_READ = -323, /* want read, call again */ + NOT_READY_ERROR = -324, /* handshake layer not ready */ + IPADDR_MISMATCH = -325, /* peer ip address mismatch */ + VERSION_ERROR = -326, /* record layer version error */ + WANT_WRITE = -327, /* want write, call again */ + BUFFER_ERROR = -328, /* malformed buffer input */ + VERIFY_CERT_ERROR = -329, /* verify cert error */ + VERIFY_SIGN_ERROR = -330, /* verify sign error */ + CLIENT_ID_ERROR = -331, /* psk client identity error */ + SERVER_HINT_ERROR = -332, /* psk server hint error */ + PSK_KEY_ERROR = -333, /* psk key error */ - GETTIME_ERROR = -337, /* gettimeofday failed ??? */ - GETITIMER_ERROR = -338, /* getitimer failed ??? */ - SIGACT_ERROR = -339, /* sigaction failed ??? */ - SETITIMER_ERROR = -340, /* setitimer failed ??? */ - LENGTH_ERROR = -341, /* record layer length error */ - PEER_KEY_ERROR = -342, /* can't decode peer key */ - ZERO_RETURN = -343, /* peer sent close notify */ - SIDE_ERROR = -344, /* wrong client/server type */ - NO_PEER_CERT = -345, /* peer didn't send key */ - NTRU_KEY_ERROR = -346, /* NTRU key error */ - NTRU_DRBG_ERROR = -347, /* NTRU drbg error */ - NTRU_ENCRYPT_ERROR = -348, /* NTRU encrypt error */ - NTRU_DECRYPT_ERROR = -349, /* NTRU decrypt error */ - ECC_CURVETYPE_ERROR = -350, /* Bad ECC Curve Type */ - ECC_CURVE_ERROR = -351, /* Bad ECC Curve */ - ECC_PEERKEY_ERROR = -352, /* Bad Peer ECC Key */ - ECC_MAKEKEY_ERROR = -353, /* Bad Make ECC Key */ - 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 */ - CRL_MISSING = -362, /* CRL Not loaded */ - MONITOR_RUNNING_E = -363, /* CRL Monitor already running */ - THREAD_CREATE_E = -364, /* Thread Create Error */ - OCSP_NEED_URL = -365, /* OCSP need an URL for lookup */ - OCSP_CERT_UNKNOWN = -366, /* OCSP responder doesn't know */ - OCSP_LOOKUP_FAIL = -367, /* OCSP lookup not successful */ - MAX_CHAIN_ERROR = -368, /* max chain depth exceeded */ - COOKIE_ERROR = -369, /* dtls cookie error */ - SEQUENCE_ERROR = -370, /* dtls sequence error */ - SUITES_ERROR = -371, /* suites pointer error */ - SSL_NO_PEM_HEADER = -372, /* no PEM header found */ - OUT_OF_ORDER_E = -373, /* out of order message */ - BAD_KEA_TYPE_E = -374, /* bad KEA type found */ - SANITY_CIPHER_E = -375, /* sanity check on cipher error */ - RECV_OVERFLOW_E = -376, /* RXCB returned more than rqed */ - GEN_COOKIE_E = -377, /* Generate Cookie Error */ - NO_PEER_VERIFY = -378, /* Need peer cert verify Error */ - FWRITE_ERROR = -379, /* fwrite problem */ - CACHE_MATCH_ERROR = -380, /* chache hdr match error */ - UNKNOWN_SNI_HOST_NAME_E = -381, /* Unrecognized host name Error */ - UNKNOWN_MAX_FRAG_LEN_E = -382, /* Unrecognized max frag len Error */ - KEYUSE_SIGNATURE_E = -383, /* KeyUse digSignature error */ - KEYUSE_ENCIPHER_E = -385, /* KeyUse keyEncipher error */ - EXTKEYUSE_AUTH_E = -386, /* ExtKeyUse server|client_auth */ - SEND_OOB_READ_E = -387, /* Send Cb out of bounds read */ - SECURE_RENEGOTIATION_E = -388, /* Invalid Renegotiation Info */ - SESSION_TICKET_LEN_E = -389, /* Session Ticket too large */ - SESSION_TICKET_EXPECT_E = -390, /* Session Ticket missing */ - SCR_DIFFERENT_CERT_E = -391, /* SCR Different cert error */ - SESSION_SECRET_CB_E = -392, /* Session secret Cb fcn failure */ - NO_CHANGE_CIPHER_E = -393, /* Finished before change cipher */ - SANITY_MSG_E = -394, /* Sanity check on msg order error */ - DUPLICATE_MSG_E = -395, /* Duplicate message error */ - SNI_UNSUPPORTED = -396, /* SSL 3.0 does not support SNI */ - SOCKET_PEER_CLOSED_E = -397, /* Underlying transport closed */ + GETTIME_ERROR = -337, /* gettimeofday failed ??? */ + GETITIMER_ERROR = -338, /* getitimer failed ??? */ + SIGACT_ERROR = -339, /* sigaction failed ??? */ + SETITIMER_ERROR = -340, /* setitimer failed ??? */ + LENGTH_ERROR = -341, /* record layer length error */ + PEER_KEY_ERROR = -342, /* can't decode peer key */ + ZERO_RETURN = -343, /* peer sent close notify */ + SIDE_ERROR = -344, /* wrong client/server type */ + NO_PEER_CERT = -345, /* peer didn't send key */ + NTRU_KEY_ERROR = -346, /* NTRU key error */ + NTRU_DRBG_ERROR = -347, /* NTRU drbg error */ + NTRU_ENCRYPT_ERROR = -348, /* NTRU encrypt error */ + NTRU_DECRYPT_ERROR = -349, /* NTRU decrypt error */ + ECC_CURVETYPE_ERROR = -350, /* Bad ECC Curve Type */ + ECC_CURVE_ERROR = -351, /* Bad ECC Curve */ + ECC_PEERKEY_ERROR = -352, /* Bad Peer ECC Key */ + ECC_MAKEKEY_ERROR = -353, /* Bad Make ECC Key */ + 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_TICKET_KEY_CB_SZ = -398, /* Bad session ticket key cb size */ - BAD_TICKET_MSG_SZ = -399, /* Bad session ticket msg size */ - BAD_TICKET_ENCRYPT = -400, /* Bad user ticket encrypt */ + BAD_CERT_MANAGER_ERROR = -359, /* Bad Cert Manager */ + OCSP_CERT_REVOKED = -360, /* OCSP Certificate revoked */ + CRL_CERT_REVOKED = -361, /* CRL Certificate revoked */ + CRL_MISSING = -362, /* CRL Not loaded */ + MONITOR_SETUP_E = -363, /* CRL Monitor setup error */ + THREAD_CREATE_E = -364, /* Thread Create Error */ + OCSP_NEED_URL = -365, /* OCSP need an URL for lookup */ + OCSP_CERT_UNKNOWN = -366, /* OCSP responder doesn't know */ + OCSP_LOOKUP_FAIL = -367, /* OCSP lookup not successful */ + MAX_CHAIN_ERROR = -368, /* max chain depth exceeded */ + COOKIE_ERROR = -369, /* dtls cookie error */ + SEQUENCE_ERROR = -370, /* dtls sequence error */ + SUITES_ERROR = -371, /* suites pointer error */ - DH_KEY_SIZE_E = -401, /* DH Key too small */ + OUT_OF_ORDER_E = -373, /* out of order message */ + BAD_KEA_TYPE_E = -374, /* bad KEA type found */ + SANITY_CIPHER_E = -375, /* sanity check on cipher error */ + RECV_OVERFLOW_E = -376, /* RXCB returned more than read */ + GEN_COOKIE_E = -377, /* Generate Cookie Error */ + NO_PEER_VERIFY = -378, /* Need peer cert verify Error */ + FWRITE_ERROR = -379, /* fwrite problem */ + CACHE_MATCH_ERROR = -380, /* Cache hdr match error */ + UNKNOWN_SNI_HOST_NAME_E = -381, /* Unrecognized host name Error */ + UNKNOWN_MAX_FRAG_LEN_E = -382, /* Unrecognized max frag len Error */ + KEYUSE_SIGNATURE_E = -383, /* KeyUse digSignature error */ + KEYUSE_ENCIPHER_E = -385, /* KeyUse keyEncipher error */ + EXTKEYUSE_AUTH_E = -386, /* ExtKeyUse server|client_auth */ + SEND_OOB_READ_E = -387, /* Send Cb out of bounds read */ + SECURE_RENEGOTIATION_E = -388, /* Invalid Renegotiation Info */ + SESSION_TICKET_LEN_E = -389, /* Session Ticket too large */ + SESSION_TICKET_EXPECT_E = -390, /* Session Ticket missing */ + SCR_DIFFERENT_CERT_E = -391, /* SCR Different cert error */ + SESSION_SECRET_CB_E = -392, /* Session secret Cb fcn failure */ + NO_CHANGE_CIPHER_E = -393, /* Finished before change cipher */ + SANITY_MSG_E = -394, /* Sanity check on msg order error */ + DUPLICATE_MSG_E = -395, /* Duplicate message error */ + SNI_UNSUPPORTED = -396, /* SSL 3.0 does not support SNI */ + SOCKET_PEER_CLOSED_E = -397, /* Underlying transport closed */ + BAD_TICKET_KEY_CB_SZ = -398, /* Bad session ticket key cb size */ + BAD_TICKET_MSG_SZ = -399, /* Bad session ticket msg size */ + BAD_TICKET_ENCRYPT = -400, /* Bad user ticket encrypt */ + DH_KEY_SIZE_E = -401, /* DH Key too small */ + SNI_ABSENT_ERROR = -402, /* No SNI request. */ + RSA_SIGN_FAULT = -403, /* RSA Sign fault */ + HANDSHAKE_SIZE_ERROR = -404, /* Handshake message too large */ + 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 */ + DTLS_EXPORT_VER_E = -411, /* export version error */ + INPUT_SIZE_E = -412, /* input size too big error */ + CTX_INIT_MUTEX_E = -413, /* initialize ctx mutex error */ + 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 */ + PRF_MISSING = -430, /* PRF not compiled in */ + DTLS_RETX_OVER_TX = -431, /* Retransmit DTLS flight over */ + DH_PARAMS_NOT_FFDHE_E = -432, /* DH params from server not FFDHE */ + TCA_INVALID_ID_TYPE = -433, /* TLSX TCA ID type invalid */ + TCA_ABSENT_ERROR = -434, /* TLSX TCA ID no response */ + TSIP_MAC_DIGSZ_E = -435, /* Invalid MAC size for TSIP */ + CLIENT_CERT_CB_ERROR = -436, /* Client cert callback error */ + SSL_SHUTDOWN_ALREADY_DONE_E = -437, /* Shutdown called redundantly */ + TLS13_SECRET_CB_E = -438, /* TLS1.3 secret Cb fcn failure */ - /* add strings to SetErrorString !!!!! */ + /* 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 */ + 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 SetErrorString !!!!! */ + /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ /* no error stings go down here, add above negotiation errors !!!! */ }; -#ifdef WOLFSSL_CALLBACKS +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) enum { MIN_PARAM_ERR = UNSUPPORTED_SUITE, MAX_PARAM_ERR = MIN_PARAM_ERR - 10 @@ -165,5 +202,3 @@ void SetErrorString(int err, char* buff); #endif /* wolfSSL_ERROR_H */ - - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/include.am b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/include.am index a02488fc8..201a96fbe 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/include.am @@ -16,10 +16,17 @@ nobase_include_HEADERS+= \ wolfssl/certs_test.h \ wolfssl/test.h \ wolfssl/version.h \ - wolfssl/options.h \ wolfssl/ocsp.h \ - wolfssl/crl.h + wolfssl/crl.h \ + wolfssl/wolfio.h noinst_HEADERS+= \ wolfssl/internal.h +# For distro build don't install options.h. +# It depends on the architecture and conflicts with Multi-Arch. +if BUILD_DISTRO +noinst_HEADERS+= wolfssl/options.h +else +nobase_include_HEADERS+= wolfssl/options.h +endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/internal.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/internal.h index 99d3e9a95..ab04b3ded 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/internal.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/internal.h @@ -1,8 +1,8 @@ /* internal.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as wolfSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLFSSL_INT_H #define WOLFSSL_INT_H @@ -44,6 +45,7 @@ #endif #ifndef NO_ASN #include + #include #endif #ifndef NO_MD5 #include @@ -67,31 +69,56 @@ #ifndef NO_RC4 #include #endif -#ifdef HAVE_ECC - #include -#endif #ifndef NO_SHA256 #include #endif #ifdef HAVE_OCSP #include #endif +#ifdef WOLFSSL_SHA384 + #include +#endif #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 +#ifdef HAVE_ED25519 + #include +#endif +#ifdef HAVE_CURVE25519 + #include +#endif +#ifdef HAVE_ED448 + #include +#endif +#ifdef HAVE_CURVE448 + #include +#endif +#include #include -#ifdef WOLFSSL_CALLBACKS +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) #include +#endif +#ifdef WOLFSSL_CALLBACKS #include #endif @@ -109,59 +136,96 @@ #ifndef SINGLE_THREADED #include "tx_api.h" #endif + +#elif defined(WOLFSSL_DEOS) + /* do nothing, just don't pick Unix */ #elif defined(MICRIUM) /* do nothing, just don't pick Unix */ -#elif defined(FREERTOS) || defined(WOLFSSL_SAFERTOS) +#elif defined(FREERTOS) || defined(FREERTOS_TCP) || defined(WOLFSSL_SAFERTOS) /* do nothing */ #elif defined(EBSNET) /* do nothing */ -#elif defined(FREESCALE_MQX) +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) /* do nothing */ +#elif defined(FREESCALE_FREE_RTOS) + #include "fsl_os_abstraction.h" +#elif defined(WOLFSSL_uITRON4) + /* do nothing */ +#elif defined(WOLFSSL_uTKERNEL2) + /* do nothing */ +#elif defined(WOLFSSL_CMSIS_RTOS) + #include "cmsis_os.h" +#elif defined(WOLFSSL_CMSIS_RTOSv2) + #include "cmsis_os2.h" #elif defined(WOLFSSL_MDK_ARM) #if defined(WOLFSSL_MDK5) - #include "cmsis_os.h" + #include "cmsis_os.h" #else #include #endif #elif defined(MBED) #elif defined(WOLFSSL_TIRTOS) /* do nothing */ +#elif defined(INTIME_RTOS) + #include +#elif defined(WOLFSSL_NUCLEUS_1_2) + /* do nothing */ +#elif defined(WOLFSSL_APACHE_MYNEWT) + #if !defined(WOLFSSL_LWIP) + void mynewt_ctx_clear(void *ctx); + void* mynewt_ctx_new(); + #endif +#elif defined(WOLFSSL_ZEPHYR) + #ifndef SINGLE_THREADED + #include + #endif +#elif defined(WOLFSSL_TELIT_M2MB) + /* do nothing */ #else #ifndef SINGLE_THREADED #define WOLFSSL_PTHREADS #include #endif - #if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS) + #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) #include /* for close of BIO */ #endif #endif +#ifndef CHAR_BIT + /* Needed for DTLS without big math */ + #include +#endif + #ifdef HAVE_LIBZ #include "zlib.h" #endif +#ifdef WOLFSSL_ASYNC_CRYPT + #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_AES - #if !defined (ALIGN16) - #define ALIGN16 - #endif -#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 @@ -169,16 +233,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 @@ -203,68 +257,114 @@ typedef byte word24[3]; #error "You are trying to build max strength with requirements disabled." #endif +/* Have QSH : Quantum-safe Handshake */ +#if defined(HAVE_QSH) + #define BUILD_TLS_QSH +#endif + +#ifndef WOLFSSL_NO_TLS12 + #ifndef WOLFSSL_MAX_STRENGTH +#ifdef WOLFSSL_AEAD_ONLY + /* AES CBC ciphers are not allowed in AEAD only mode */ + #undef HAVE_AES_CBC +#endif + +#ifndef WOLFSSL_AEAD_ONLY #if !defined(NO_RSA) && !defined(NO_RC4) - #if !defined(NO_SHA) - #define BUILD_SSL_RSA_WITH_RC4_128_SHA + #if defined(WOLFSSL_STATIC_RSA) + #if !defined(NO_SHA) + #define BUILD_SSL_RSA_WITH_RC4_128_SHA + #endif + #if !defined(NO_MD5) + #define BUILD_SSL_RSA_WITH_RC4_128_MD5 + #endif #endif - #if !defined(NO_MD5) - #define BUILD_SSL_RSA_WITH_RC4_128_MD5 - #endif - #if !defined(NO_TLS) && defined(HAVE_NTRU) && !defined(NO_SHA) + #if !defined(NO_TLS) && defined(HAVE_NTRU) && !defined(NO_SHA) \ + && defined(WOLFSSL_STATIC_RSA) #define BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA #endif #endif #if !defined(NO_RSA) && !defined(NO_DES3) #if !defined(NO_SHA) - #define BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA - #if !defined(NO_TLS) && defined(HAVE_NTRU) + #if defined(WOLFSSL_STATIC_RSA) + #define BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA + #endif + #if !defined(NO_TLS) && defined(HAVE_NTRU) \ + && defined(WOLFSSL_STATIC_RSA) #define BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA #endif #endif #endif + #if !defined(NO_RSA) && defined(HAVE_IDEA) + #if !defined(NO_SHA) && defined(WOLFSSL_STATIC_RSA) + #define BUILD_SSL_RSA_WITH_IDEA_CBC_SHA + #endif + #endif +#endif /* !WOLFSSL_AEAD_ONLY */ + #if !defined(NO_RSA) && !defined(NO_AES) && !defined(NO_TLS) - #if !defined(NO_SHA) - #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA - #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA - #if defined(HAVE_NTRU) + #if !defined(NO_SHA) && defined(HAVE_AES_CBC) + #if defined(WOLFSSL_STATIC_RSA) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA + #endif + #endif + #if defined(HAVE_NTRU) && defined(WOLFSSL_STATIC_RSA) + #ifdef WOLFSSL_AES_128 #define BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 #define BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + #endif #endif #endif - #if !defined (NO_SHA256) - #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 - #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 - #endif - #if defined (HAVE_AESGCM) - #define BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 - #if defined (WOLFSSL_SHA384) - #define BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + #if defined(WOLFSSL_STATIC_RSA) + #if !defined (NO_SHA256) && defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 + #endif + #endif + #if defined (HAVE_AESGCM) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + #endif + #if defined (WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) + #define BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + #endif + #endif + #if defined (HAVE_AESCCM) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_RSA_WITH_AES_128_CCM_8 + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_RSA_WITH_AES_256_CCM_8 + #endif #endif - #endif - #if defined (HAVE_AESCCM) - #define BUILD_TLS_RSA_WITH_AES_128_CCM_8 - #define BUILD_TLS_RSA_WITH_AES_256_CCM_8 - #endif - #if defined(HAVE_BLAKE2) - #define BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256 - #define BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256 #endif #endif - #if defined(HAVE_CAMELLIA) && !defined(NO_TLS) + #if defined(HAVE_CAMELLIA) && !defined(NO_TLS) && !defined(NO_CAMELLIA_CBC) #ifndef NO_RSA - #if !defined(NO_SHA) - #define BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - #define BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - #endif + #if defined(WOLFSSL_STATIC_RSA) + #if !defined(NO_SHA) + #define BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + #define BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + #endif #ifndef NO_SHA256 #define BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 #define BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 #endif + #endif #if !defined(NO_DH) #if !defined(NO_SHA) #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA @@ -278,41 +378,62 @@ typedef byte word24[3]; #endif #endif +#if defined(WOLFSSL_STATIC_PSK) #if !defined(NO_PSK) && !defined(NO_AES) && !defined(NO_TLS) #if !defined(NO_SHA) - #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA - #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA + #endif #endif #ifndef NO_SHA256 - #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 - #ifdef HAVE_AESGCM - #define BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 - #endif + #ifdef WOLFSSL_AES_128 + #ifdef HAVE_AES_CBC + #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 + #endif + #ifdef HAVE_AESGCM + #define BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 + #endif + #endif /* WOLFSSL_AES_128 */ #ifdef HAVE_AESCCM - #define BUILD_TLS_PSK_WITH_AES_128_CCM_8 - #define BUILD_TLS_PSK_WITH_AES_256_CCM_8 - #define BUILD_TLS_PSK_WITH_AES_128_CCM - #define BUILD_TLS_PSK_WITH_AES_256_CCM + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_PSK_WITH_AES_128_CCM_8 + #define BUILD_TLS_PSK_WITH_AES_128_CCM + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_PSK_WITH_AES_256_CCM_8 + #define BUILD_TLS_PSK_WITH_AES_256_CCM + #endif #endif #endif - #ifdef WOLFSSL_SHA384 - #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 + #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) + #ifdef HAVE_AES_CBC + #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 + #endif #ifdef HAVE_AESGCM #define BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384 #endif #endif #endif +#endif #if !defined(NO_TLS) && defined(HAVE_NULL_CIPHER) #if !defined(NO_RSA) - #if !defined(NO_SHA) - #define BUILD_TLS_RSA_WITH_NULL_SHA - #endif - #ifndef NO_SHA256 - #define BUILD_TLS_RSA_WITH_NULL_SHA256 + #if defined(WOLFSSL_STATIC_RSA) + #ifndef NO_MD5 + #define BUILD_TLS_RSA_WITH_NULL_MD5 + #endif + #if !defined(NO_SHA) + #define BUILD_TLS_RSA_WITH_NULL_SHA + #endif + #ifndef NO_SHA256 + #define BUILD_TLS_RSA_WITH_NULL_SHA256 + #endif #endif #endif - #if !defined(NO_PSK) + #if !defined(NO_PSK) && defined(WOLFSSL_STATIC_PSK) #if !defined(NO_SHA) #define BUILD_TLS_PSK_WITH_NULL_SHA #endif @@ -325,14 +446,14 @@ typedef byte word24[3]; #endif #endif +#if defined(WOLFSSL_STATIC_RSA) #if !defined(NO_HC128) && !defined(NO_RSA) && !defined(NO_TLS) - #define BUILD_TLS_RSA_WITH_HC_128_MD5 + #ifndef NO_MD5 + #define BUILD_TLS_RSA_WITH_HC_128_MD5 + #endif #if !defined(NO_SHA) #define BUILD_TLS_RSA_WITH_HC_128_SHA #endif - #if defined(HAVE_BLAKE2) - #define BUILD_TLS_RSA_WITH_HC_128_B2B256 - #endif #endif #if !defined(NO_RABBIT) && !defined(NO_TLS) && !defined(NO_RSA) @@ -340,111 +461,253 @@ typedef byte word24[3]; #define BUILD_TLS_RSA_WITH_RABBIT_SHA #endif #endif +#endif #if !defined(NO_DH) && !defined(NO_AES) && !defined(NO_TLS) && \ !defined(NO_RSA) #if !defined(NO_SHA) - #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA - #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + #if defined(WOLFSSL_AES_128) && defined(HAVE_AES_CBC) + #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + #endif + #if defined(WOLFSSL_AES_256) && defined(HAVE_AES_CBC) + #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + #endif + #if !defined(NO_DES3) + #define BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + #endif #endif - #if !defined(NO_SHA256) - #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + #if !defined(NO_SHA256) && defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + #endif #endif #endif #if defined(HAVE_ANON) && !defined(NO_TLS) && !defined(NO_DH) && \ - !defined(NO_AES) && !defined(NO_SHA) - #define BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA + !defined(NO_AES) && !defined(NO_SHA) && defined(WOLFSSL_AES_128) + #ifdef HAVE_AES_CBC + #define BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA + #endif + + #if defined(WOLFSSL_SHA384) && defined(HAVE_AESGCM) + #define BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384 + #endif #endif #if !defined(NO_DH) && !defined(NO_PSK) && !defined(NO_TLS) #ifndef NO_SHA256 - #define BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + #if !defined(NO_AES) && defined(WOLFSSL_AES_128) && \ + defined(HAVE_AES_CBC) + #define BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + #endif #ifdef HAVE_NULL_CIPHER #define BUILD_TLS_DHE_PSK_WITH_NULL_SHA256 #endif #endif #ifdef WOLFSSL_SHA384 - #define BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + #if !defined(NO_AES) && defined(WOLFSSL_AES_256) && \ + defined(HAVE_AES_CBC) + #define BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + #endif #ifdef HAVE_NULL_CIPHER #define BUILD_TLS_DHE_PSK_WITH_NULL_SHA384 #endif #endif #endif - #if defined(HAVE_ECC) && !defined(NO_TLS) + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && !defined(NO_TLS) #if !defined(NO_AES) - #if !defined(NO_SHA) + #if !defined(NO_SHA) && defined(HAVE_AES_CBC) #if !defined(NO_RSA) - #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + #endif + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + #endif + #endif #endif - #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + #if defined(HAVE_ECC) || \ + (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + #endif + #endif - #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + #endif + #endif #endif /* NO_SHA */ - #ifndef NO_SHA256 + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) && \ + defined(HAVE_AES_CBC) #if !defined(NO_RSA) #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + #endif + #endif + #if defined(HAVE_ECC) || \ + (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + #endif + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 #endif - #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 #endif - #ifdef WOLFSSL_SHA384 + #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) && \ + defined(HAVE_AES_CBC) #if !defined(NO_RSA) #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + #endif + #endif + #if defined(HAVE_ECC) || \ + (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + #endif + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 #endif - #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 #endif #if defined (HAVE_AESGCM) #if !defined(NO_RSA) - #define BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + #endif + #endif #if defined(WOLFSSL_SHA384) - #define BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + #endif + #endif #endif #endif - #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + #if defined(WOLFSSL_STATIC_DH) && defined(WOLFSSL_AES_128) && \ + defined(HAVE_ECC) + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + #endif #if defined(WOLFSSL_SHA384) - #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + #if defined(WOLFSSL_STATIC_DH) && \ + defined(WOLFSSL_AES_256) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + #endif #endif #endif #endif /* NO_AES */ #if !defined(NO_RC4) #if !defined(NO_SHA) #if !defined(NO_RSA) - #define BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA - #define BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + #ifndef WOLFSSL_AEAD_ONLY + #define BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA + #endif + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + #endif #endif - #define BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - #define BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + #if defined(HAVE_ECC) || \ + (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) + #ifndef WOLFSSL_AEAD_ONLY + #define BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + #endif + #endif + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + #endif #endif #endif #if !defined(NO_DES3) #ifndef NO_SHA #if !defined(NO_RSA) #define BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - #define BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + #endif #endif - #define BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - #define BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + #if defined(HAVE_ECC) || \ + (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + #endif + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + #endif #endif /* NO_SHA */ #endif + #if defined(HAVE_NULL_CIPHER) + #if !defined(NO_SHA) + #if defined(HAVE_ECC) || \ + (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA + #endif + #endif + #if !defined(NO_PSK) && !defined(NO_SHA256) + #define BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256 + #endif + #endif + #if !defined(NO_PSK) && !defined(NO_SHA256) && !defined(NO_AES) && \ + defined(WOLFSSL_AES_128) && defined(HAVE_AES_CBC) + #define BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + #endif + #endif + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256) + #if !defined(NO_OLD_POLY1305) + #if defined(HAVE_ECC) || \ + (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + #endif + #if !defined(NO_RSA) && defined(HAVE_ECC) + #define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + #endif + #if !defined(NO_DH) && !defined(NO_RSA) + #define BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + #endif + #endif /* NO_OLD_POLY1305 */ + #if !defined(NO_PSK) + #define BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_ED448) + #define BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + #endif + #ifndef NO_DH + #define BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + #endif + #endif /* !NO_PSK */ #endif #endif /* !WOLFSSL_MAX_STRENGTH */ @@ -452,54 +715,81 @@ typedef byte word24[3]; #if !defined(NO_DH) && !defined(NO_AES) && !defined(NO_TLS) && \ !defined(NO_RSA) && defined(HAVE_AESGCM) - #ifndef NO_SHA256 + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) #define BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 #endif - #ifdef WOLFSSL_SHA384 + #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) #define BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 #endif #endif #if !defined(NO_DH) && !defined(NO_PSK) && !defined(NO_TLS) #ifndef NO_SHA256 - #ifdef HAVE_AESGCM + #if defined(HAVE_AESGCM) && defined(WOLFSSL_AES_128) #define BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 #endif #ifdef HAVE_AESCCM - #define BUILD_TLS_DHE_PSK_WITH_AES_128_CCM - #define BUILD_TLS_DHE_PSK_WITH_AES_256_CCM + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_DHE_PSK_WITH_AES_128_CCM + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_DHE_PSK_WITH_AES_256_CCM + #endif #endif #endif - #if defined(WOLFSSL_SHA384) && defined(HAVE_AESGCM) + #if defined(WOLFSSL_SHA384) && defined(HAVE_AESGCM) && \ + defined(WOLFSSL_AES_256) #define BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 #endif #endif -#if defined(HAVE_ECC) && !defined(NO_TLS) && !defined(NO_AES) +#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)) \ + && !defined(NO_TLS) && !defined(NO_AES) #ifdef HAVE_AESGCM - #ifndef NO_SHA256 - #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) + #if defined(HAVE_ECC) || \ + (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + #endif #ifndef NO_RSA #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 #endif #endif - #ifdef WOLFSSL_SHA384 - #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) + #if defined(HAVE_ECC) || \ + (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + #endif #ifndef NO_RSA #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 #endif #endif #endif #if defined(HAVE_AESCCM) && !defined(NO_SHA256) - #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 - #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 + #if defined(HAVE_ECC) || \ + (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 + #endif + #endif #endif #endif #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256) - #ifdef HAVE_ECC - #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) + #if defined(HAVE_ECC) || \ + (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \ + (defined(HAVE_CURVE448) && defined(HAVE_ED448)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + #endif #ifndef NO_RSA #define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 #endif @@ -509,6 +799,45 @@ typedef byte word24[3]; #endif #endif +#endif + +#if defined(WOLFSSL_TLS13) + #ifdef HAVE_AESGCM + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) + #define BUILD_TLS_AES_128_GCM_SHA256 + #endif + #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) + #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 + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) + #define BUILD_TLS_AES_128_CCM_SHA256 + #define BUILD_TLS_AES_128_CCM_8_SHA256 + #endif + #endif + #ifdef HAVE_NULL_CIPHER + #ifndef NO_SHA256 + #define BUILD_TLS_SHA256_SHA256 + #endif + #ifdef WOLFSSL_SHA384 + #define BUILD_TLS_SHA384_SHA384 + #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) @@ -521,7 +850,8 @@ typedef byte word24[3]; #if defined(BUILD_TLS_RSA_WITH_AES_128_CBC_SHA) || \ defined(BUILD_TLS_RSA_WITH_AES_256_CBC_SHA) || \ - defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) || \ + defined(BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256) #undef BUILD_AES #define BUILD_AES #endif @@ -529,13 +859,39 @@ typedef byte word24[3]; #if defined(BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256) || \ defined(BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) || \ defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) || \ - defined(BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256) + defined(BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256) || \ + defined(BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) || \ + defined(BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384) || \ + defined(BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) || \ + defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) || \ + defined(BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384) || \ + defined(BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384) || \ + defined(BUILD_TLS_AES_128_GCM_SHA256) || \ + defined(BUILD_TLS_AES_256_GCM_SHA384) #define BUILD_AESGCM +#else + /* No AES-GCM cipher suites available with build */ + #define NO_AESGCM_AEAD +#endif + +#if defined(BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \ + defined(BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \ + defined(BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \ + defined(BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(BUILD_TLS_CHACHA20_POLY1305_SHA256) + /* Have an available ChaCha Poly cipher suite */ +#else + /* No ChaCha Poly cipher suites available with build */ + #define NO_CHAPOL_AEAD #endif #if defined(BUILD_TLS_RSA_WITH_HC_128_SHA) || \ - defined(BUILD_TLS_RSA_WITH_HC_128_MD5) || \ - defined(BUILD_TLS_RSA_WITH_HC_128_B2B256) + defined(BUILD_TLS_RSA_WITH_HC_128_MD5) #define BUILD_HC128 #endif @@ -550,8 +906,9 @@ typedef byte word24[3]; #define BUILD_DES3 #endif -#ifdef NO_AES +#if defined(NO_AES) || defined(NO_AES_DECRYPT) #define AES_BLOCK_SIZE 16 + #undef BUILD_AES #else #undef BUILD_AES #define BUILD_AES @@ -567,8 +924,11 @@ typedef byte word24[3]; #endif #if defined(WOLFSSL_MAX_STRENGTH) || \ - defined(HAVE_AESGCM) || defined(HAVE_AESCCM) || \ - (defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) + (defined(HAVE_AESGCM) && !defined(NO_AESGCM_AEAD)) || \ + defined(HAVE_AESCCM) || \ + (defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \ + !defined(NO_CHAPOL_AEAD)) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER)) #define HAVE_AEAD #endif @@ -579,14 +939,19 @@ typedef byte word24[3]; #define HAVE_PFS #endif +#if defined(BUILD_SSL_RSA_WITH_IDEA_CBC_SHA) + #define BUILD_IDEA +#endif /* actual cipher values, 2nd byte */ enum { + TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x16, TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x39, TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x33, TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x34, TLS_RSA_WITH_AES_256_CBC_SHA = 0x35, TLS_RSA_WITH_AES_128_CBC_SHA = 0x2F, + TLS_RSA_WITH_NULL_MD5 = 0x01, TLS_RSA_WITH_NULL_SHA = 0x02, TLS_PSK_WITH_AES_256_CBC_SHA = 0x8d, TLS_PSK_WITH_AES_128_CBC_SHA256 = 0xae, @@ -598,6 +963,7 @@ enum { SSL_RSA_WITH_RC4_128_SHA = 0x05, SSL_RSA_WITH_RC4_128_MD5 = 0x04, SSL_RSA_WITH_3DES_EDE_CBC_SHA = 0x0A, + SSL_RSA_WITH_IDEA_CBC_SHA = 0x07, /* ECC suites, first byte is 0xC0 (ECC_BYTE) */ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0x14, @@ -612,6 +978,9 @@ enum { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0x23, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0x28, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0x24, + TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0x06, + TLS_ECDHE_PSK_WITH_NULL_SHA256 = 0x3a, + TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = 0x37, /* static ECDH, first byte is 0xC0 (ECC_BYTE) */ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0x0F, @@ -631,11 +1000,7 @@ enum { TLS_RSA_WITH_HC_128_MD5 = 0xFB, TLS_RSA_WITH_HC_128_SHA = 0xFC, TLS_RSA_WITH_RABBIT_SHA = 0xFD, - - /* wolfSSL extension - Blake2b 256 */ - TLS_RSA_WITH_AES_128_CBC_B2B256 = 0xF8, - TLS_RSA_WITH_AES_256_CBC_B2B256 = 0xF9, - TLS_RSA_WITH_HC_128_B2B256 = 0xFA, /* eSTREAM too */ + WDM_WITH_NULL_SHA256 = 0xFE, /* wolfSSL DTLS Multicast */ /* wolfSSL extension - NTRU */ TLS_NTRU_RSA_WITH_RC4_128_SHA = 0xe5, @@ -643,6 +1008,10 @@ enum { TLS_NTRU_RSA_WITH_AES_128_CBC_SHA = 0xe7, /* clashes w/official SHA-256 */ TLS_NTRU_RSA_WITH_AES_256_CBC_SHA = 0xe8, + /* wolfSSL extension - NTRU , Quantum-safe Handshake + first byte is 0xD0 (QSH_BYTE) */ + TLS_QSH = 0x01, + /* SHA256 */ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x6b, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x67, @@ -661,6 +1030,7 @@ enum { TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x9d, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x9e, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x9f, + TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0xa7, TLS_PSK_WITH_AES_128_GCM_SHA256 = 0xa8, TLS_PSK_WITH_AES_256_GCM_SHA384 = 0xa9, TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0xaa, @@ -682,6 +1052,7 @@ enum { * with non-ECC AES-GCM */ TLS_RSA_WITH_AES_128_CCM_8 = 0xa0, TLS_RSA_WITH_AES_256_CCM_8 = 0xa1, + TLS_ECDHE_ECDSA_WITH_AES_128_CCM = 0xac, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xae, TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = 0xaf, TLS_PSK_WITH_AES_128_CCM = 0xa4, @@ -701,10 +1072,32 @@ enum { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xbe, TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0xc4, - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0x13, - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0x14, - TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0x15, + /* chacha20-poly1305 suites first byte is 0xCC (CHACHA_BYTE) */ + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xa8, + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xa9, + TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xaa, + TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xac, + TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xab, + TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xad, + /* chacha20-poly1305 earlier version of nonce and padding (CHACHA_BYTE) */ + TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x13, + 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, + + /* TLS v1.3 Integity only cipher suites - 0xC0 (ECC) first byte */ + TLS_SHA256_SHA256 = 0xB4, + TLS_SHA384_SHA384 = 0xB5, + + /* Fallback SCSV (Signaling Cipher Suite Value) */ + TLS_FALLBACK_SCSV = 0x56, /* Renegotiation Indication Extension Special Suite */ TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0xff }; @@ -716,190 +1109,29 @@ enum { #endif -enum Misc { - ECC_BYTE = 0xC0, /* ECC first cipher suite byte */ - CHACHA_BYTE = 0xCC, /* ChaCha first cipher suite */ +#ifndef WOLFSSL_DTLS_WINDOW_WORDS + #define WOLFSSL_DTLS_WINDOW_WORDS 2 +#endif /* WOLFSSL_DTLS_WINDOW_WORDS */ +#define DTLS_WORD_BITS (sizeof(word32) * CHAR_BIT) +#define DTLS_SEQ_BITS (WOLFSSL_DTLS_WINDOW_WORDS * DTLS_WORD_BITS) +#define DTLS_SEQ_SZ (sizeof(word32) * WOLFSSL_DTLS_WINDOW_WORDS) - SEND_CERT = 1, - SEND_BLANK_CERT = 2, +#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 */ - DTLS_MAJOR = 0xfe, /* DTLS major version number */ - DTLS_MINOR = 0xff, /* DTLS minor version number */ - DTLSv1_2_MINOR = 0xfd, /* DTLS minor version number */ - SSLv3_MAJOR = 3, /* SSLv3 and TLSv1+ major version number */ - SSLv3_MINOR = 0, /* TLSv1 minor version number */ - 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 */ - 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 */ - SECRET_LEN = 48, /* pre RSA and all master */ - ENCRYPT_LEN = 512, /* allow 4096 bit static buffer */ - SIZEOF_SENDER = 4, /* clnt or srvr */ - FINISHED_SZ = 36, /* MD5_DIGEST_SIZE + 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_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 */ - - PAD_MD5 = 48, /* pad length for finished */ - PAD_SHA = 40, /* pad length for finished */ - MAX_PAD_SIZE = 256, /* maximum length of padding */ - COMPRESS_DUMMY_SIZE = 64, /* compression dummy round size */ - COMPRESS_CONSTANT = 13, /* compression calc constant */ - COMPRESS_UPPER = 55, /* compression calc numerator */ - COMPRESS_LOWER = 64, /* compression calc denominator */ - - PEM_LINE_LEN = 80, /* PEM line max + fudge */ - LENGTH_SZ = 2, /* length field for HMAC, data only */ - VERSION_SZ = 2, /* length of proctocol version */ - SEQ_SZ = 8, /* 64 bit sequence number */ - BYTE3_LEN = 3, /* up to 24 bit byte lengths */ - ALERT_SIZE = 2, /* level + description */ - VERIFY_HEADER = 2, /* always use 2 bytes */ - EXT_ID_SZ = 2, /* always use 2 bytes */ - MAX_DH_SIZE = 513, /* 4096 bit plus possible leading 0 */ - SESSION_HINT_SZ = 4, /* session timeout hint */ - - MAX_SUITE_SZ = 200, /* 100 suites for now! */ - RAN_LEN = 32, /* random length */ - SEED_LEN = RAN_LEN * 2, /* tls prf seed length */ - ID_LEN = 32, /* session id length */ - MAX_COOKIE_LEN = 32, /* max dtls cookie size */ - COOKIE_SZ = 20, /* use a 20 byte cookie */ - SUITE_LEN = 2, /* cipher suite sz length */ - ENUM_LEN = 1, /* always a byte */ - OPAQUE8_LEN = 1, /* 1 byte */ - OPAQUE16_LEN = 2, /* 2 bytes */ - OPAQUE24_LEN = 3, /* 3 bytes */ - OPAQUE32_LEN = 4, /* 4 bytes */ - COMP_LEN = 1, /* compression length */ - CURVE_LEN = 2, /* ecc named curve length */ - SERVER_ID_LEN = 20, /* server session id length */ - - HANDSHAKE_HEADER_SZ = 4, /* type + length(3) */ - RECORD_HEADER_SZ = 5, /* type + version + len(2) */ - CERT_HEADER_SZ = 3, /* always 3 bytes */ - REQ_HEADER_SZ = 2, /* cert request header sz */ - HINT_LEN_SZ = 2, /* length of hint size field */ - TRUNCATED_HMAC_SZ = 10, /* length of hmac w/ truncated hmac extension */ - HELLO_EXT_TYPE_SZ = 2, /* length of a hello extension type */ - HELLO_EXT_SZ = 8, /* total length of the lazy hello extensions */ - HELLO_EXT_LEN = 6, /* length of the lazy hello extensions */ - HELLO_EXT_SIGALGO_SZ = 2, /* length of signature algo extension */ - 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) */ - DTLS_HANDSHAKE_EXTRA = 8, /* diff from normal */ - DTLS_RECORD_EXTRA = 8, /* diff from normal */ - DTLS_HANDSHAKE_SEQ_SZ = 2, /* handshake header sequence number */ - DTLS_HANDSHAKE_FRAG_SZ = 3, /* fragment offset and length are 24 bit */ - DTLS_POOL_SZ = 5, /* buffers to hold in the retry pool */ - - FINISHED_LABEL_SZ = 15, /* TLS finished label size */ - TLS_FINISHED_SZ = 12, /* TLS has a shorter size */ - MASTER_LABEL_SZ = 13, /* TLS master secret label sz */ - KEY_LABEL_SZ = 13, /* TLS key block expansion sz */ - MAX_PRF_HALF = 256, /* Maximum half secret len */ - MAX_PRF_LABSEED = 128, /* Maximum label + seed len */ - MAX_PRF_DIG = 224, /* Maximum digest len */ - MAX_REQUEST_SZ = 256, /* Maximum cert req len (no auth yet */ - SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */ - - RC4_KEY_SIZE = 16, /* always 128bit */ - DES_KEY_SIZE = 8, /* des */ - DES3_KEY_SIZE = 24, /* 3 des ede */ - DES_IV_SIZE = DES_BLOCK_SIZE, - AES_256_KEY_SIZE = 32, /* for 256 bit */ - AES_192_KEY_SIZE = 24, /* for 192 bit */ - AES_IV_SIZE = 16, /* always block size */ - AES_128_KEY_SIZE = 16, /* for 128 bit */ - - AEAD_SEQ_OFFSET = 4, /* Auth Data: Sequence number */ - AEAD_TYPE_OFFSET = 8, /* Auth Data: Type */ - AEAD_VMAJ_OFFSET = 9, /* Auth Data: Major Version */ - 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_IMP_IV_SZ = 4, /* Size of the implicit IV */ - AEAD_EXP_IV_SZ = 8, /* Size of the explicit IV */ - AEAD_NONCE_SZ = AEAD_EXP_IV_SZ + AEAD_IMP_IV_SZ, - - 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 */ - - CAMELLIA_128_KEY_SIZE = 16, /* for 128 bit */ - CAMELLIA_192_KEY_SIZE = 24, /* for 192 bit */ - CAMELLIA_256_KEY_SIZE = 32, /* for 256 bit */ - CAMELLIA_IV_SIZE = 16, /* always block size */ - - CHACHA20_256_KEY_SIZE = 32, /* for 256 bit */ - CHACHA20_128_KEY_SIZE = 16, /* for 128 bit */ - CHACHA20_IV_SIZE = 8, /* 64 bits for iv */ - - POLY1305_AUTH_SZ = 16, /* 128 bits */ - - HC_128_KEY_SIZE = 16, /* 128 bits */ - HC_128_IV_SIZE = 16, /* also 128 bits */ - - RABBIT_KEY_SIZE = 16, /* 128 bits */ - RABBIT_IV_SIZE = 8, /* 64 bits for iv */ - - EVP_SALT_SIZE = 8, /* evp salt size 64 bits */ - - ECDHE_SIZE = 32, /* ECHDE server size defaults to 256 bit */ - MAX_EXPORT_ECC_SZ = 256, /* Export ANS X9.62 max future size */ - - MAX_HELLO_SZ = 128, /* max client or server hello */ - 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 */ - - DTLS_TIMEOUT_INIT = 1, /* default timeout init for DTLS receive */ - DTLS_TIMEOUT_MAX = 64, /* default max timeout for DTLS receive */ - DTLS_TIMEOUT_MULTIPLIER = 2, /* default timeout multiplier for DTLS recv */ - - MAX_PSK_ID_LEN = 128, /* max psk identity/hint supported */ - MAX_PSK_KEY_LEN = 64, /* max psk key supported */ - - MAX_WOLFSSL_FILE_SIZE = 1024 * 1024 * 4, /* 4 mb file size alloc limit */ - -#ifdef FORTRESS - MAX_EX_DATA = 3, /* allow for three 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 */ - - MAX_NTRU_PUB_KEY_SZ = 1027, /* NTRU max for now */ - MAX_NTRU_ENCRYPT_SZ = 1027, /* NTRU max for now */ - MAX_NTRU_BITS = 256, /* max symmetric bit strength */ - NO_SNIFF = 0, /* not sniffing */ - SNIFF = 1, /* currently sniffing */ - - HASH_SIG_SIZE = 2, /* default SHA1 RSA */ - - NO_CAVIUM_DEVICE = -2, /* invalid cavium device id */ - - NO_COPY = 0, /* should we copy static buffer for write */ - COPY = 1 /* should we copy static buffer for write */ -}; +#ifndef WOLFSSL_MAX_MTU + #define WOLFSSL_MAX_MTU 1500 +#endif /* WOLFSSL_MAX_MTU */ +/* set minimum DH key size allowed */ #ifndef WOLFSSL_MIN_DHKEY_BITS #ifdef WOLFSSL_MAX_STRENGTH #define WOLFSSL_MIN_DHKEY_BITS 2048 @@ -914,7 +1146,387 @@ enum Misc { #error DH minimum bit size must not be greater than 16000 #endif #define MIN_DHKEY_SZ (WOLFSSL_MIN_DHKEY_BITS / 8) +/* set maximum DH key size allowed */ +#ifndef WOLFSSL_MAX_DHKEY_BITS + #if (defined(USE_FAST_MATH) && defined(FP_MAX_BITS) && FP_MAX_BITS >= 16384) + #define WOLFSSL_MAX_DHKEY_BITS 8192 + #else + #define WOLFSSL_MAX_DHKEY_BITS 4096 + #endif +#endif +#if (WOLFSSL_MAX_DHKEY_BITS % 8) + #error DH maximum bit size must be multiple of 8 +#endif +#if (WOLFSSL_MAX_DHKEY_BITS > 16000) + #error DH maximum bit size must not be greater than 16000 +#endif +#define MAX_DHKEY_SZ (WOLFSSL_MAX_DHKEY_BITS / 8) +#ifndef MAX_PSK_ID_LEN + /* max psk identity/hint supported */ + #if defined(WOLFSSL_TLS13) + #define MAX_PSK_ID_LEN 256 + #else + #define MAX_PSK_ID_LEN 128 + #endif +#endif + +#ifndef MAX_EARLY_DATA_SZ + /* maximum early data size */ + #define MAX_EARLY_DATA_SZ 4096 +#endif + +enum Misc { + CIPHER_BYTE = 0x00, /* Default ciphers */ + 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, + + DTLS_MAJOR = 0xfe, /* DTLS major version number */ + DTLS_MINOR = 0xff, /* DTLS minor version number */ + DTLSv1_2_MINOR = 0xfd, /* DTLS minor version number */ + SSLv3_MAJOR = 3, /* SSLv3 and TLSv1+ major version number */ + SSLv3_MINOR = 0, /* TLSv1 minor version number */ + 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 +#ifdef WOLFSSL_TLS13_DRAFT_18 + TLS_DRAFT_MINOR = 0x12, /* Minor version number of TLS draft */ +#elif defined(WOLFSSL_TLS13_DRAFT_22) + TLS_DRAFT_MINOR = 0x16, /* Minor version number of TLS draft */ +#elif defined(WOLFSSL_TLS13_DRAFT_23) + TLS_DRAFT_MINOR = 0x17, /* Minor version number of TLS draft */ +#elif defined(WOLFSSL_TLS13_DRAFT_26) + TLS_DRAFT_MINOR = 0x1a, /* Minor version number of TLS draft */ +#else + TLS_DRAFT_MINOR = 0x1c, /* Minor version number of TLS draft */ +#endif +#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 = WOLFSSL_MAX_MASTER_KEY_LENGTH, + /* pre RSA and all master */ +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + (defined(USE_FAST_MATH) && defined(FP_MAX_BITS) && FP_MAX_BITS > 8192) +#ifndef NO_PSK + ENCRYPT_LEN = 1024 + MAX_PSK_ID_LEN + 2, /* 8192 bit static buffer */ +#else + ENCRYPT_LEN = 1024, /* allow 8192 bit static buffer */ +#endif +#else +#ifndef NO_PSK + ENCRYPT_LEN = 512 + MAX_PSK_ID_LEN + 2, /* 4096 bit static buffer */ +#else + ENCRYPT_LEN = 512, /* allow 4096 bit static buffer */ +#endif +#endif + SIZEOF_SENDER = 4, /* clnt or srvr */ + FINISHED_SZ = 36, /* WC_MD5_DIGEST_SIZE + WC_SHA_DIGEST_SIZE */ + MAX_RECORD_SIZE = 16384, /* 2^14, max size by standard */ + MAX_PLAINTEXT_SZ = (1 << 14), /* Max plaintext sz */ + MAX_TLS_CIPHER_SZ = (1 << 14) + 2048, /* Max TLS encrypted data sz */ +#ifdef WOLFSSL_TLS13 + MAX_TLS13_PLAIN_SZ = (1 << 14) + 1, /* Max unencrypted data sz */ + MAX_TLS13_ENC_SZ = (1 << 14) + 256, /* Max encrypted data sz */ +#endif + MAX_MSG_EXTRA = 38 + WC_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 = WOLFSSL_MAX_MTU, /* max expected MTU */ + MAX_UDP_SIZE = 8192 - 100, /* was MAX_MTU - 100 */ + MAX_DH_SZ = (MAX_DHKEY_SZ * 3) + 12, /* DH_P, DH_G and DH_Pub */ + /* 4096 p, pub, g + 2 byte size for each */ + MAX_STR_VERSION = 8, /* string rep of protocol version */ + + PAD_MD5 = 48, /* pad length for finished */ + PAD_SHA = 40, /* pad length for finished */ + MAX_PAD_SIZE = 256, /* maximum length of padding */ + + LENGTH_SZ = 2, /* length field for HMAC, data only */ + VERSION_SZ = 2, /* length of proctocol version */ + 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 = MAX_DHKEY_SZ+1, + /* Max size plus possible leading 0 */ + NAMED_DH_MASK = 0x100, /* Named group mask for DH parameters */ + MIN_FFHDE_GROUP = 0x100, /* Named group minimum for FFDHE parameters */ + MAX_FFHDE_GROUP = 0x1FF, /* Named group maximum for FFDHE 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 = 8, /* maximum ticket nonce size */ + MAX_LIFETIME = 604800, /* maximum ticket lifetime */ + + RAN_LEN = 32, /* random length */ + SEED_LEN = RAN_LEN * 2, /* tls prf seed length */ + ID_LEN = 32, /* session id length */ + COOKIE_SECRET_SZ = 14, /* dtls cookie secret size */ + MAX_COOKIE_LEN = 32, /* max dtls cookie size */ + COOKIE_SZ = 20, /* use a 20 byte cookie */ + SUITE_LEN = 2, /* cipher suite sz length */ + ENUM_LEN = 1, /* always a byte */ + OPAQUE8_LEN = 1, /* 1 byte */ + OPAQUE16_LEN = 2, /* 2 bytes */ + OPAQUE24_LEN = 3, /* 3 bytes */ + OPAQUE32_LEN = 4, /* 4 bytes */ + 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) */ + RECORD_HEADER_SZ = 5, /* type + version + len(2) */ + CERT_HEADER_SZ = 3, /* always 3 bytes */ + REQ_HEADER_SZ = 2, /* cert request header sz */ + HINT_LEN_SZ = 2, /* length of hint size field */ + TRUNCATED_HMAC_SZ = 10, /* length of hmac w/ truncated hmac extension */ + HELLO_EXT_SZ = 4, /* base length of a hello extension */ + 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 */ + + DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */ + DTLS_RECORD_HEADER_SZ = 13, /* normal + epoch(2) + seq_num(6) */ + DTLS_HANDSHAKE_EXTRA = 8, /* diff from normal */ + DTLS_RECORD_EXTRA = 8, /* diff from normal */ + DTLS_HANDSHAKE_SEQ_SZ = 2, /* handshake header sequence number */ + 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_STATE_PRO = 166,/* wolfSSL protocol for serialized state */ + DTLS_EXPORT_VERSION = 4, /* wolfSSL version for serialized session */ + DTLS_EXPORT_OPT_SZ = 60, /* amount of bytes used from Options */ + DTLS_EXPORT_VERSION_3 = 3, /* wolfSSL version before TLS 1.3 addition */ + DTLS_EXPORT_OPT_SZ_3 = 59, /* 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 = 85 + (DTLS_SEQ_SZ * 2), + /* min amount of bytes used from Keys */ + DTLS_EXPORT_SPC_SZ = 16, /* amount of bytes used from CipherSpecs */ + DTLS_EXPORT_LEN = 2, /* 2 bytes for length and protocol */ + DTLS_EXPORT_IP = 46, /* max ip size IPv4 mapped IPv6 */ + MAX_EXPORT_BUFFER = 514, /* max size of buffer for exporting */ + MAX_EXPORT_STATE_BUFFER = (DTLS_EXPORT_MIN_KEY_SZ) + (3 * DTLS_EXPORT_LEN), + /* max size of buffer for exporting state */ + FINISHED_LABEL_SZ = 15, /* TLS finished label size */ + TLS_FINISHED_SZ = 12, /* TLS has a shorter size */ + EXT_MASTER_LABEL_SZ = 22, /* TLS extended master secret label sz */ + MASTER_LABEL_SZ = 13, /* TLS master secret label sz */ + KEY_LABEL_SZ = 13, /* TLS key block expansion sz */ + 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 + WC_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 */ + TLS_MAX_PAD_SZ = 255, /* Max padding in TLS */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + MAX_SYM_KEY_SIZE = AES_256_KEY_SIZE, +#else + MAX_SYM_KEY_SIZE = WC_MAX_SYM_KEY_SIZE, +#endif + +#ifdef HAVE_SELFTEST + #ifndef WOLFSSL_AES_KEY_SIZE_ENUM + #define WOLFSSL_AES_KEY_SIZE_ENUM + AES_IV_SIZE = 16, + AES_128_KEY_SIZE = 16, + AES_192_KEY_SIZE = 24, + AES_256_KEY_SIZE = 32, + #endif +#endif + + MAX_IV_SZ = AES_BLOCK_SIZE, + + AEAD_SEQ_OFFSET = 4, /* Auth Data: Sequence number */ + AEAD_TYPE_OFFSET = 8, /* Auth Data: Type */ + AEAD_VMAJ_OFFSET = 9, /* Auth Data: Major Version */ + 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, + + CHACHA20_IMP_IV_SZ = 12, /* Size of ChaCha20 AEAD implicit IV */ + CHACHA20_NONCE_SZ = 12, /* Size of ChacCha20 nonce */ + CHACHA20_OLD_OFFSET = 4, /* Offset for seq # in old poly1305 */ + + /* For any new implicit/explicit IV size adjust AEAD_MAX_***_SZ */ + + 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 */ + CAMELLIA_256_KEY_SIZE = 32, /* for 256 bit */ + CAMELLIA_IV_SIZE = 16, /* always block size */ + + CHACHA20_256_KEY_SIZE = 32, /* for 256 bit */ + CHACHA20_128_KEY_SIZE = 16, /* for 128 bit */ + CHACHA20_IV_SIZE = 12, /* 96 bits for iv */ + + POLY1305_AUTH_SZ = 16, /* 128 bits */ + + HMAC_NONCE_SZ = 12, /* Size of HMAC nonce */ + + HC_128_KEY_SIZE = 16, /* 128 bits */ + HC_128_IV_SIZE = 16, /* also 128 bits */ + + RABBIT_KEY_SIZE = 16, /* 128 bits */ + RABBIT_IV_SIZE = 8, /* 64 bits for iv */ + + EVP_SALT_SIZE = 8, /* evp salt size 64 bits */ + +#ifndef ECDHE_SIZE /* allow this to be overridden at compile-time */ + ECDHE_SIZE = 32, /* ECHDE server size defaults to 256 bit */ +#endif + 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 significant 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 */ + +#ifndef NO_RSA + MAX_CERT_VERIFY_SZ = 4096 / 8, /* max RSA - default 4096-bits */ +#elif defined(HAVE_ECC) + MAX_CERT_VERIFY_SZ = ECC_MAX_SIG_SIZE, /* max ECC */ +#elif defined(HAVE_ED448) + MAX_CERT_VERIFY_SZ = ED448_SIG_SIZE, /* max Ed448 */ +#elif defined(HAVE_ED25519) + MAX_CERT_VERIFY_SZ = ED25519_SIG_SIZE, /* max Ed25519 */ +#else + MAX_CERT_VERIFY_SZ = 1024, /* max default */ +#endif + CLIENT_HELLO_FIRST = 35, /* Protocol + RAN_LEN + sizeof(id_len) */ + MAX_SUITE_NAME = 48, /* maximum length of cipher suite string */ + + DTLS_TIMEOUT_INIT = 1, /* default timeout init for DTLS receive */ + DTLS_TIMEOUT_MAX = 64, /* default max timeout for DTLS receive */ + DTLS_TIMEOUT_MULTIPLIER = 2, /* default timeout multiplier for DTLS recv */ + + 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 */ + +#ifndef MAX_WOLFSSL_FILE_SIZE + MAX_WOLFSSL_FILE_SIZE = 1024ul * 1024ul * 4, /* 4 mb file size alloc limit */ +#endif + + MAX_X509_SIZE = 2048, /* max static x509 buffer size */ + CERT_MIN_SIZE = 256, /* min PEM cert size with header/footer */ + + MAX_NTRU_PUB_KEY_SZ = 1027, /* NTRU max for now */ + MAX_NTRU_ENCRYPT_SZ = 1027, /* NTRU max for now */ + MAX_NTRU_BITS = 256, /* max symmetric bit strength */ + NO_SNIFF = 0, /* not sniffing */ + SNIFF = 1, /* currently sniffing */ + + HASH_SIG_SIZE = 2, /* default SHA1 RSA */ + + 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. */ + WRITE_PROTO = 1, /* writing a protocol message */ + READ_PROTO = 0 /* reading a protocol message */ +}; + +/* minimum Downgrade Minor version */ +#ifndef WOLFSSL_MIN_DOWNGRADE + #ifndef NO_OLD_TLS + #define WOLFSSL_MIN_DOWNGRADE TLSv1_MINOR + #else + #define WOLFSSL_MIN_DOWNGRADE TLSv1_2_MINOR + #endif +#endif + +/* Set max implicit IV size for AEAD cipher suites */ +#define AEAD_MAX_IMP_SZ 12 + +/* Set max explicit IV size for AEAD cipher suites */ +#define AEAD_MAX_EXP_SZ 8 + + +#ifndef WOLFSSL_MAX_SUITE_SZ + #define WOLFSSL_MAX_SUITE_SZ 300 + /* 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 + #define WOLFSSL_MIN_ECC_BITS 256 + #else + #define WOLFSSL_MIN_ECC_BITS 224 + #endif +#endif /* WOLFSSL_MIN_ECC_BITS */ +#if (WOLFSSL_MIN_ECC_BITS % 8) + /* Some ECC keys are not divisible by 8 such as prime239v1 or sect131r1. + In these cases round down to the nearest value divisible by 8. The + restriction of being divisible by 8 is in place to match wc_ecc_size + function from wolfSSL. + */ + #error ECC minimum bit size must be a multiple of 8 +#endif +#define MIN_ECCKEY_SZ (WOLFSSL_MIN_ECC_BITS / 8) + +/* set minimum RSA key size allowed */ +#ifndef WOLFSSL_MIN_RSA_BITS + #ifdef WOLFSSL_MAX_STRENGTH + #define WOLFSSL_MIN_RSA_BITS 2048 + #else + #define WOLFSSL_MIN_RSA_BITS 1024 + #endif +#endif /* WOLFSSL_MIN_RSA_BITS */ +#if (WOLFSSL_MIN_RSA_BITS % 8) + /* This is to account for the example case of a min size of 2050 bits but + still allows 2049 bit key. So we need the measurement to be in bytes. */ + #error RSA minimum bit size must be a multiple of 8 +#endif +#define MIN_RSAKEY_SZ (WOLFSSL_MIN_RSA_BITS / 8) #ifdef SESSION_INDEX /* Shift values for making a session index */ @@ -928,6 +1540,19 @@ enum Misc { #define MAX_CHAIN_DEPTH 9 #endif +/* max size of a certificate message payload */ +/* assumes MAX_CHAIN_DEPTH number of certificates at 2kb per certificate */ +#ifndef MAX_CERTIFICATE_SZ + #define MAX_CERTIFICATE_SZ \ + CERT_HEADER_SZ + \ + (MAX_X509_SIZE + CERT_HEADER_SZ) * MAX_CHAIN_DEPTH +#endif + +/* max size of a handshake message, currently set to the certificate */ +#ifndef MAX_HANDSHAKE_SZ + #define MAX_HANDSHAKE_SZ MAX_CERTIFICATE_SZ +#endif + #ifndef SESSION_TICKET_LEN #define SESSION_TICKET_LEN 256 #endif @@ -950,26 +1575,24 @@ enum states { NULL_STATE = 0, SERVER_HELLOVERIFYREQUEST_COMPLETE, + SERVER_HELLO_RETRY_REQUEST_COMPLETE, SERVER_HELLO_COMPLETE, + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE, SERVER_CERT_COMPLETE, SERVER_KEYEXCHANGE_COMPLETE, SERVER_HELLODONE_COMPLETE, + SERVER_CHANGECIPHERSPEC_COMPLETE, SERVER_FINISHED_COMPLETE, + CLIENT_HELLO_RETRY, CLIENT_HELLO_COMPLETE, CLIENT_KEYEXCHANGE_COMPLETE, + CLIENT_CHANGECIPHERSPEC_COMPLETE, CLIENT_FINISHED_COMPLETE, HANDSHAKE_DONE }; - -#if defined(__GNUC__) - #define WOLFSSL_PACK __attribute__ ((packed)) -#else - #define WOLFSSL_PACK -#endif - /* SSL Version */ typedef struct ProtocolVersion { byte major; @@ -981,41 +1604,26 @@ 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); WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void); + + #ifdef WOLFSSL_SESSION_EXPORT + WOLFSSL_LOCAL int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, + word32 sz); + WOLFSSL_LOCAL int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, + word32 sz); + WOLFSSL_LOCAL int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, + byte* buf, word32 sz); + WOLFSSL_LOCAL int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, + byte* buf, word32 sz); + WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl); + #endif #endif -enum BIO_TYPE { - BIO_BUFFER = 1, - BIO_SOCKET = 2, - BIO_SSL = 3, - BIO_MEMORY = 4 -}; - - -/* wolfSSL BIO_METHOD type */ -struct WOLFSSL_BIO_METHOD { - byte type; /* method type */ -}; - - -/* wolfSSL BIO type */ -struct WOLFSSL_BIO { - byte type; /* method type */ - byte close; /* close flag */ - byte eof; /* eof flag */ - WOLFSSL* ssl; /* possible associated ssl */ - byte* mem; /* memory buffer */ - int memLen; /* memory buffer length */ - int fd; /* possible file descriptor */ - WOLFSSL_BIO* prev; /* previous in chain */ - WOLFSSL_BIO* next; /* next in chain */ -}; - - /* wolfSSL method type */ struct WOLFSSL_METHOD { ProtocolVersion version; @@ -1023,21 +1631,79 @@ struct WOLFSSL_METHOD { byte downgrade; /* whether to downgrade version, default no */ }; +/* wolfSSL buffer type - internal uses "buffer" type */ +typedef WOLFSSL_BUFFER_INFO buffer; -/* defautls to client */ +typedef struct Suites Suites; + + +/* defaults to client */ WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD*, ProtocolVersion); +WOLFSSL_LOCAL int InitSSL_Suites(WOLFSSL* ssl); +WOLFSSL_LOCAL int InitSSL_Side(WOLFSSL* ssl, word16 side); + /* for sniffer */ 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 */ -typedef struct buffer { - byte* buffer; - word32 length; -} buffer; +/* TLS v1.3 needs these */ +WOLFSSL_LOCAL int HandleTlsResumption(WOLFSSL* ssl, int bogusID, + Suites* clSuites); +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int FindSuite(Suites* suites, byte first, byte second); +#endif +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 CompleteServerHello(WOLFSSL *ssl); +WOLFSSL_LOCAL int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv); +WOLFSSL_LOCAL int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, + word32 hashSigAlgoSz); +WOLFSSL_LOCAL int DecodePrivateKey(WOLFSSL *ssl, word16* length); +#ifdef HAVE_PK_CALLBACKS +WOLFSSL_LOCAL int GetPrivateKeySigSize(WOLFSSL* ssl); +#ifndef NO_ASN + WOLFSSL_LOCAL int InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx); +#endif +#endif +WOLFSSL_LOCAL void FreeKeyExchange(WOLFSSL* ssl); +WOLFSSL_LOCAL void FreeSuites(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); +#ifdef OPENSSL_EXTRA +WOLFSSL_LOCAL int CheckIPAddr(DecodedCert* dCert, char* ipasc); +#endif +#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(OPENSSL_ALL) || 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, const byte* aad, word16 aadSz); +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, + byte* extMsgType); +#endif +int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t, + int pLen, int content); enum { @@ -1055,7 +1721,7 @@ enum { /* only the sniffer needs space in the buffer for extra MTU record(s) */ #ifdef WOLFSSL_SNIFFER - #define MTU_EXTRA MAX_MTU * 3 + #define MTU_EXTRA MAX_MTU * 3 #else #define MTU_EXTRA 0 #endif @@ -1073,9 +1739,9 @@ enum { #define RECORD_SIZE MAX_RECORD_SIZE #else #ifdef WOLFSSL_DTLS - #define RECORD_SIZE MAX_MTU + #define RECORD_SIZE MAX_MTU #else - #define RECORD_SIZE 128 + #define RECORD_SIZE 128 #endif #endif @@ -1083,7 +1749,7 @@ enum { /* user option to turn off 16K output option */ /* if using small static buffers (default) and SSL_write tries to write data larger than the record we have, dynamically get it, unless user says only - write in static buffer chuncks */ + write in static buffer chunks */ #ifndef STATIC_CHUNKS_ONLY #define OUTPUT_RECORD_SIZE MAX_RECORD_SIZE #else @@ -1117,75 +1783,88 @@ typedef struct { } bufferStatic; /* Cipher Suites holder */ -typedef struct Suites { +struct Suites { word16 suiteSz; /* suite length in bytes */ word16 hashSigAlgoSz; /* SigAlgo extension length in bytes */ - byte suites[MAX_SUITE_SZ]; - byte hashSigAlgo[HELLO_EXT_SIGALGO_MAX]; /* sig/algo to offer */ + byte suites[WOLFSSL_MAX_SUITE_SZ]; + 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, int); -WOLFSSL_LOCAL -int SetCipherList(Suites*, const char* list); - -#ifndef PSK_TYPES_DEFINED - typedef unsigned int (*psk_client_callback)(WOLFSSL*, const char*, char*, - unsigned int, unsigned char*, unsigned int); - typedef unsigned int (*psk_server_callback)(WOLFSSL*, const char*, - unsigned char*, unsigned int); -#endif /* PSK_TYPES_DEFINED */ - - -#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 { - WOLFSSL* ssl; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + WOLF_STACK_OF(WOLFSSL_CIPHER)* stack; /* stack of available cipher suites */ +#endif }; -typedef struct OCSP_Entry OCSP_Entry; +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); -#ifdef NO_SHA - #define OCSP_DIGEST_SIZE SHA256_DIGEST_SIZE -#else - #define OCSP_DIGEST_SIZE SHA_DIGEST_SIZE +#ifndef PSK_TYPES_DEFINED + typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*, + unsigned int, unsigned char*, unsigned int); + typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*, + unsigned char*, unsigned int); +#ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_client_tls13_callback)(WOLFSSL*, const char*, + char*, unsigned int, unsigned char*, unsigned int, + const char**); + typedef unsigned int (*wc_psk_server_tls13_callback)(WOLFSSL*, const char*, + unsigned char*, unsigned int, const char**); #endif +#endif /* PSK_TYPES_DEFINED */ +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) && \ + !defined(WOLFSSL_DTLS_EXPORT_TYPES) + typedef int (*wc_dtls_export)(WOLFSSL* ssl, + unsigned char* exportBuffer, unsigned int sz, void* userCtx); +#define WOLFSSL_DTLS_EXPORT_TYPES +#endif /* WOLFSSL_DTLS_EXPORT_TYPES */ -#ifdef NO_ASN + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +#define MAX_DESCRIPTION_SZ 255 +#endif +/* wolfSSL Cipher type just points back to SSL */ +struct WOLFSSL_CIPHER { + byte cipherSuite0; + byte cipherSuite; + WOLFSSL* ssl; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + char description[MAX_DESCRIPTION_SZ]; + unsigned long offset; + unsigned int in_stack; /* TRUE if added to stack in wolfSSL_get_ciphers_compat */ + int bits; +#endif +}; + + +#ifdef NO_ASN /* no_asn won't have */ typedef struct CertStatus CertStatus; #endif -struct OCSP_Entry { - OCSP_Entry* next; /* next entry */ - byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */ - byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */ - CertStatus* status; /* OCSP response list */ - int totalStatus; /* number on list */ -}; - - #ifndef HAVE_OCSP typedef struct WOLFSSL_OCSP WOLFSSL_OCSP; #endif /* wolfSSL OCSP controller */ +#ifdef HAVE_OCSP struct WOLFSSL_OCSP { WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */ - OCSP_Entry* ocspList; /* OCSP response list */ + OcspEntry* ocspList; /* OCSP response list */ wolfSSL_Mutex ocspLock; /* OCSP list lock */ + int error; +#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + int(*statusCb)(WOLFSSL*, void*); +#endif }; +#endif #ifndef MAX_DATE_SIZE #define MAX_DATE_SIZE 32 @@ -1194,20 +1873,20 @@ 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 +#ifdef NO_ASN typedef struct RevokedCert RevokedCert; #endif /* Complete CRL */ struct CRL_Entry { CRL_Entry* next; /* next entry */ - byte issuerHash[CRL_DIGEST_SIZE]; /* issuer hash */ - /* byte crlHash[CRL_DIGEST_SIZE]; raw crl data hash */ + byte issuerHash[CRL_DIGEST_SIZE]; /* issuer hash */ + /* byte crlHash[CRL_DIGEST_SIZE]; raw crl data hash */ /* restore the hash here if needed for optimized comparisons */ byte lastDate[MAX_DATE_SIZE]; /* last date updated */ byte nextDate[MAX_DATE_SIZE]; /* next update date */ @@ -1215,6 +1894,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(NO_ASN) + byte extAuthKeyIdSet; + byte extAuthKeyId[KEYID_SIZE]; +#endif }; @@ -1227,51 +1916,82 @@ struct CRL_Monitor { }; -#ifndef HAVE_CRL - typedef struct WOLFSSL_CRL WOLFSSL_CRL; +#if defined(HAVE_CRL) && defined(NO_FILESYSTEM) + #undef HAVE_CRL_MONITOR #endif /* wolfSSL CRL controller */ struct WOLFSSL_CRL { WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */ - CRL_Entry* crlList; /* our CRL list */ - wolfSSL_Mutex crlLock; /* CRL list lock */ - CRL_Monitor monitors[2]; /* PEM and DER possible */ -#ifdef HAVE_CRL_MONITOR - pthread_t tid; /* monitoring thread */ - int mfd; /* monitor fd, -1 if no init yet */ + 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 + pthread_cond_t cond; /* condition to signal setup */ + pthread_t tid; /* monitoring thread */ + int mfd; /* monitor fd, -1 if no init yet */ + int setup; /* thread is setup predicate */ +#endif + void* heap; /* heap hint for dynamic memory */ }; -#ifdef NO_ASN +#ifdef NO_ASN typedef struct Signer Signer; +#ifdef WOLFSSL_TRUST_PEER_CERT + typedef struct TrustedPeerCert TrustedPeerCert; +#endif #endif #ifndef CA_TABLE_SIZE #define CA_TABLE_SIZE 11 #endif +#ifdef WOLFSSL_TRUST_PEER_CERT + #define TP_TABLE_SIZE 11 +#endif /* wolfSSL Certificate Manager */ struct WOLFSSL_CERT_MANAGER { Signer* caTable[CA_TABLE_SIZE]; /* the CA signer table */ - void* heap; /* heap helper */ - WOLFSSL_CRL* crl; /* CRL checker */ - WOLFSSL_OCSP* ocsp; /* OCSP checker */ - char* ocspOverrideURL; /* use this responder */ - void* ocspIOCtx; /* I/O callback CTX */ - CallbackCACache caCacheCallback; /* CA cache addition callback */ - CbMissingCRL cbMissingCRL; /* notify through cb of missing crl */ - CbOCSPIO ocspIOCb; /* I/O callback for OCSP lookup */ - CbOCSPRespFree ocspRespFreeCb; /* Frees OCSP Response from IO Cb */ - wolfSSL_Mutex caLock; /* CA list lock */ - byte crlEnabled; /* is CRL on ? */ - byte crlCheckAll; /* always leaf, but all ? */ - byte ocspEnabled; /* is OCSP on ? */ - byte ocspCheckAll; /* always leaf, but all ? */ - byte ocspSendNonce; /* send the OCSP nonce ? */ - byte ocspUseOverrideURL; /* ignore cert's responder, override */ + void* heap; /* heap helper */ +#ifdef WOLFSSL_TRUST_PEER_CERT + TrustedPeerCert* tpTable[TP_TABLE_SIZE]; /* table of trusted peer certs */ + wolfSSL_Mutex tpLock; /* trusted peer list lock */ +#endif + WOLFSSL_CRL* crl; /* CRL checker */ + WOLFSSL_OCSP* ocsp; /* OCSP checker */ +#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) + WOLFSSL_OCSP* ocsp_stapling; /* OCSP checker for OCSP stapling */ +#endif + char* ocspOverrideURL; /* use this responder */ + void* ocspIOCtx; /* I/O callback CTX */ +#ifndef NO_WOLFSSL_CM_VERIFY + VerifyCallback verifyCallback; /* Verify callback */ +#endif + CallbackCACache caCacheCallback; /* CA cache addition callback */ + CbMissingCRL cbMissingCRL; /* notify through cb of missing crl */ + CbOCSPIO ocspIOCb; /* I/O callback for OCSP lookup */ + CbOCSPRespFree ocspRespFreeCb; /* Frees OCSP Response from IO Cb */ + wolfSSL_Mutex caLock; /* CA list lock */ + byte crlEnabled; /* is CRL on ? */ + byte crlCheckAll; /* always leaf, but all ? */ + byte ocspEnabled; /* is OCSP on ? */ + byte ocspCheckAll; /* always leaf, but all ? */ + byte ocspSendNonce; /* send the OCSP nonce ? */ + byte ocspUseOverrideURL; /* ignore cert's responder, override */ + byte ocspStaplingEnabled; /* is OCSP Stapling on ? */ + +#ifndef NO_RSA + short minRsaKeySz; /* minimum allowed RSA key size */ +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + short minEccKeySz; /* minimum allowed ECC key size */ +#endif }; WOLFSSL_LOCAL int CM_SaveCertCache(WOLFSSL_CERT_MANAGER*, const char*); @@ -1279,6 +1999,42 @@ WOLFSSL_LOCAL int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER*, const char*); WOLFSSL_LOCAL int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER*, void*, int, int*); WOLFSSL_LOCAL int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER*, const void*, int); WOLFSSL_LOCAL int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER*); +WOLFSSL_LOCAL int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const byte* buff, + long sz, int format, int err_val); + + +#ifndef NO_CERTS +#if !defined NOCERTS &&\ + (!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)) +typedef struct ProcPeerCertArgs { + buffer* certs; +#ifdef WOLFSSL_TLS13 + buffer* exts; /* extensions */ +#endif + DecodedCert* dCert; + word32 idx; + word32 begin; + int totalCerts; /* number of certs in certs buffer */ + int count; + int certIdx; + int lastErr; +#ifdef WOLFSSL_TLS13 + byte ctxSz; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + char untrustedDepth; +#endif + word16 fatal:1; + word16 verifyErr:1; + word16 dCertInit:1; +#ifdef WOLFSSL_TRUST_PEER_CERT + word16 haveTrustPeer:1; /* was cert verified by loaded trusted peer cert */ +#endif +} ProcPeerCertArgs; +WOLFSSL_LOCAL int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, + int ret, ProcPeerCertArgs* args); +#endif /* !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH) */ +#endif /* !defined NO_CERTS */ /* wolfSSL Sock Addr */ struct WOLFSSL_SOCKADDR { @@ -1288,58 +2044,71 @@ struct WOLFSSL_SOCKADDR { typedef struct WOLFSSL_DTLS_CTX { WOLFSSL_SOCKADDR peer; - int fd; + int rfd; + int wfd; } WOLFSSL_DTLS_CTX; -#ifdef WOLFSSL_DTLS +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; - #ifdef WORD64_AVAILABLE - typedef word64 DtlsSeq; - #else - typedef word32 DtlsSeq; - #endif - #define DTLS_SEQ_BITS (sizeof(DtlsSeq) * CHAR_BIT) + word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS]; + /* Sliding window for old epoch */ + word32 prevSeq_lo; + word16 prevSeq_hi; /* Next sequence in allowed old epoch */ - typedef struct DtlsState { - DtlsSeq window; /* Sliding window for current epoch */ - word16 nextEpoch; /* Expected epoch in next record */ - word32 nextSeq; /* Expected sequence in next record */ - - word16 curEpoch; /* Received epoch in current record */ - word32 curSeq; /* Received sequence in current record */ - - DtlsSeq prevWindow; /* Sliding window for old epoch */ - word32 prevSeq; /* Next sequence in allowed old epoch */ - } DtlsState; - -#endif /* WOLFSSL_DTLS */ +#ifdef WOLFSSL_MULTICAST + word16 peerId; + word32 highwaterMark; +#endif +} WOLFSSL_DTLS_PEERSEQ; -/* keys and secrets */ +#define MAX_WRITE_IV_SZ 16 /* max size of client/server write_IV */ + +/* keys and secrets + * keep as a constant size (no additional ifdefs) for session export */ typedef struct Keys { - byte client_write_MAC_secret[MAX_DIGEST_SIZE]; /* max sizes */ - byte server_write_MAC_secret[MAX_DIGEST_SIZE]; - byte client_write_key[AES_256_KEY_SIZE]; /* max sizes */ - byte server_write_key[AES_256_KEY_SIZE]; - byte client_write_IV[AES_IV_SIZE]; /* max sizes */ - byte server_write_IV[AES_IV_SIZE]; -#ifdef HAVE_AEAD - byte aead_exp_IV[AEAD_EXP_IV_SZ]; - byte aead_enc_imp_IV[AEAD_IMP_IV_SZ]; - byte aead_dec_imp_IV[AEAD_IMP_IV_SZ]; +#if !defined(WOLFSSL_AEAD_ONLY) || defined(WOLFSSL_TLS13) + byte client_write_MAC_secret[WC_MAX_DIGEST_SIZE]; /* max sizes */ + byte server_write_MAC_secret[WC_MAX_DIGEST_SIZE]; +#endif + byte client_write_key[MAX_SYM_KEY_SIZE]; /* max sizes */ + byte server_write_key[MAX_SYM_KEY_SIZE]; + byte client_write_IV[MAX_WRITE_IV_SZ]; /* max sizes */ + byte server_write_IV[MAX_WRITE_IV_SZ]; +#if defined(HAVE_AEAD) || defined(WOLFSSL_SESSION_EXPORT) + byte aead_exp_IV[AEAD_MAX_EXP_SZ]; + byte aead_enc_imp_IV[AEAD_MAX_IMP_SZ]; + byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ]; #endif - word32 peer_sequence_number; - word32 sequence_number; + word32 peer_sequence_number_hi; + word32 peer_sequence_number_lo; + word32 sequence_number_hi; + word32 sequence_number_lo; #ifdef WOLFSSL_DTLS - DtlsState dtls_state; /* Peer's state */ + word16 curEpoch; /* Received epoch in current record */ + word16 curSeq_hi; /* Received sequence in current record */ + word32 curSeq_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; - word16 dtls_epoch; /* Current tx epoch */ - word32 dtls_sequence_number; /* Current tx sequence */ + word16 dtls_epoch; /* Current epoch */ + word16 dtls_sequence_number_hi; /* Current epoch */ + word32 dtls_sequence_number_lo; + word16 dtls_prev_sequence_number_hi; /* Previous epoch */ + word32 dtls_prev_sequence_number_lo; word16 dtls_handshake_number; /* Current tx handshake seq */ #endif @@ -1347,115 +2116,275 @@ 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 +#ifdef WOLFSSL_RENESAS_TSIP_TLS + byte tsip_client_write_MAC_secret[TSIP_TLS_HMAC_KEY_INDEX_WORDSIZE]; + byte tsip_server_write_MAC_secret[TSIP_TLS_HMAC_KEY_INDEX_WORDSIZE]; +#endif } Keys; -/* RFC 6066 TLS Extensions */ +/** TLS Extensions - RFC 6066 */ #ifdef HAVE_TLS_EXTENSIONS typedef enum { - SERVER_NAME_INDICATION = 0x0000, - MAX_FRAGMENT_LENGTH = 0x0001, - TRUNCATED_HMAC = 0x0004, - ELLIPTIC_CURVES = 0x000a, - SESSION_TICKET = 0x0023, - SECURE_RENEGOTIATION = 0xff01 + TLSX_SERVER_NAME = 0x0000, /* a.k.a. SNI */ + TLSX_MAX_FRAGMENT_LENGTH = 0x0001, + TLSX_TRUSTED_CA_KEYS = 0x0003, + 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, +#if !defined(WOLFSSL_NO_SIGALG) + TLSX_SIGNATURE_ALGORITHMS = 0x000d, +#endif + TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ + TLSX_STATUS_REQUEST_V2 = 0x0011, /* a.k.a. OCSP stapling v2 */ +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + TLSX_ENCRYPT_THEN_MAC = 0x0016, /* RFC 7366 */ +#endif + TLSX_QUANTUM_SAFE_HYBRID = 0x0018, /* a.k.a. QSH */ + TLSX_SESSION_TICKET = 0x0023, +#ifdef WOLFSSL_TLS13 + #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 + #if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22) + TLSX_KEY_SHARE = 0x0028, + #else + TLSX_SIGNATURE_ALGORITHMS_CERT = 0x0032, + TLSX_KEY_SHARE = 0x0033, + #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; -WOLFSSL_LOCAL TLSX* TLSX_Find(TLSX* list, TLSX_Type type); -WOLFSSL_LOCAL void TLSX_FreeAll(TLSX* list); -WOLFSSL_LOCAL int TLSX_SupportExtensions(WOLFSSL* ssl); +WOLFSSL_LOCAL TLSX* TLSX_Find(TLSX* list, TLSX_Type type); +WOLFSSL_LOCAL void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap); +WOLFSSL_LOCAL void TLSX_FreeAll(TLSX* list, void* heap); +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); +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT) +WOLFSSL_LOCAL int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, + word16* pLength); +WOLFSSL_LOCAL int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, + byte msgType, word16* pOffset); #endif -#ifndef NO_WOLFSSL_SERVER -WOLFSSL_LOCAL word16 TLSX_GetResponseSize(WOLFSSL* ssl); -WOLFSSL_LOCAL word16 TLSX_WriteResponse(WOLFSSL* ssl, byte* output); +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER) +/* TLS 1.3 Certificate messages have extensions. */ +WOLFSSL_LOCAL int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, + word16* pLength); +WOLFSSL_LOCAL int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, + word16* pOffset); #endif -WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte isRequest, Suites *suites); - -#elif defined(HAVE_SNI) \ - || defined(HAVE_MAX_FRAGMENT) \ - || defined(HAVE_TRUNCATED_HMAC) \ - || defined(HAVE_SUPPORTED_CURVES) \ - || defined(HAVE_SECURE_RENEGOTIATION) \ - || defined(HAVE_SESSION_TICKET) +WOLFSSL_LOCAL int TLSX_ParseVersion(WOLFSSL* ssl, byte* input, word16 length, + byte msgType, int* found); +WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType, Suites *suites); + +#elif defined(HAVE_SNI) \ + || defined(HAVE_MAX_FRAGMENT) \ + || defined(HAVE_TRUSTED_CA) \ + || defined(HAVE_TRUNCATED_HMAC) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \ + || defined(HAVE_SUPPORTED_CURVES) \ + || defined(HAVE_ALPN) \ + || defined(HAVE_QSH) \ + || defined(HAVE_SESSION_TICKET) \ + || defined(HAVE_SECURE_RENEGOTIATION) \ + || defined(HAVE_SERVER_RENEGOTIATION_INFO) #error Using TLS extensions requires HAVE_TLS_EXTENSIONS to be defined. #endif /* HAVE_TLS_EXTENSIONS */ -/* Server Name Indication */ +/** Server Name Indication - RFC 6066 (session 3) */ #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; /* Behaviour options */ - byte status; /* Matching result */ + byte options; /* Behavior options */ #endif } SNI; WOLFSSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, - word16 size); + 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 #endif /* HAVE_SNI */ -/* Maximum Fragment Length */ +/* Trusted CA Key Indication - RFC 6066 (section 6) */ +#ifdef HAVE_TRUSTED_CA + +typedef struct TCA { + byte type; /* TCA Type */ + byte* id; /* TCA identifier */ + word16 idSz; /* TCA identifier size */ + struct TCA* next; /* List Behavior */ +} TCA; + +WOLFSSL_LOCAL int TLSX_UseTrustedCA(TLSX** extensions, byte type, + const byte* id, word16 idSz, void* heap); + +#endif /* HAVE_TRUSTED_CA */ + +/* Application-Layer Protocol Negotiation - RFC 7301 */ +#ifdef HAVE_ALPN +typedef struct ALPN { + char* protocol_name; /* ALPN protocol name */ + struct ALPN* next; /* List Behavior */ + byte options; /* Behavior options */ + byte negotiated; /* ALPN protocol negotiated or not */ +} ALPN; + +WOLFSSL_LOCAL int TLSX_ALPN_GetRequest(TLSX* extensions, + void** data, word16 *dataSz); + +WOLFSSL_LOCAL int TLSX_UseALPN(TLSX** extensions, const void* data, + word16 size, byte options, void* heap); + +WOLFSSL_LOCAL int TLSX_ALPN_SetOptions(TLSX** extensions, const byte option); + +#endif /* HAVE_ALPN */ + +/** Maximum Fragment Length Negotiation - RFC 6066 (session 4) */ #ifdef HAVE_MAX_FRAGMENT -WOLFSSL_LOCAL int TLSX_UseMaxFragment(TLSX** extensions, byte mfl); +WOLFSSL_LOCAL int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap); #endif /* HAVE_MAX_FRAGMENT */ +/** Truncated HMAC - RFC 6066 (session 7) */ #ifdef HAVE_TRUNCATED_HMAC -WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions); +WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap); #endif /* HAVE_TRUNCATED_HMAC */ +/** Certificate Status Request - RFC 6066 (session 8) */ +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + +typedef struct { + byte status_type; + byte options; + WOLFSSL* ssl; + union { + OcspRequest ocsp; + } request; +#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + buffer response; +#endif +} CertificateStatusRequest; + +WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, + byte status_type, byte options, WOLFSSL* ssl, 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); + +#endif + +/** Certificate Status Request v2 - RFC 6961 */ +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + +typedef struct CSRIv2 { + byte status_type; + byte options; + word16 requests; + union { + OcspRequest ocsp[1 + MAX_CHAIN_DEPTH]; + } request; + struct CSRIv2* next; +} CertificateStatusRequestItemV2; + +WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, + 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); + +#endif + +/** 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; -WOLFSSL_LOCAL int TLSX_UseSupportedCurve(TLSX** extensions, word16 name); +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); +WOLFSSL_LOCAL int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl); #endif +WOLFSSL_LOCAL int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl, + int checkSupported); #endif /* HAVE_SUPPORTED_CURVES */ -#ifdef HAVE_SECURE_RENEGOTIATION +/** Renegotiation Indication - RFC 5746 */ +#if defined(HAVE_SECURE_RENEGOTIATION) \ + || defined(HAVE_SERVER_RENEGOTIATION_INFO) enum key_cache_state { SCR_CACHE_NULL = 0, /* empty / begin state */ @@ -1465,132 +2394,492 @@ enum key_cache_state { SCR_CACHE_COMPLETE /* complete restore to real keys */ }; - -/* Additional Conection State according to rfc5746 section 3.1 */ +/* Additional Connection State according to rfc5746 section 3.1 */ typedef struct SecureRenegotiation { byte enabled; /* secure_renegotiation flag in rfc */ + byte verifySet; byte startScr; /* server requested client to start scr */ 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_set; /* if peer cert hash is set */ + byte subject_hash[KEYID_SIZE]; /* peer cert hash */ Keys tmp_keys; /* can't overwrite real keys yet */ } SecureRenegotiation; -WOLFSSL_LOCAL int TLSX_UseSecureRenegotiation(TLSX** extensions); +WOLFSSL_LOCAL int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap); + +#ifdef HAVE_SERVER_RENEGOTIATION_INFO +WOLFSSL_LOCAL int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap); +#endif #endif /* HAVE_SECURE_RENEGOTIATION */ +/** Session Ticket - RFC 5077 (session 3.2) */ #ifdef HAVE_SESSION_TICKET typedef struct SessionTicket { word32 lifetime; +#ifdef WOLFSSL_TLS13 + word64 seen; + word32 ageAdd; +#endif byte* data; word16 size; } SessionTicket; -WOLFSSL_LOCAL int TLSX_UseSessionTicket(TLSX** extensions, - SessionTicket* ticket); +WOLFSSL_LOCAL int TLSX_UseSessionTicket(TLSX** extensions, + SessionTicket* ticket, void* heap); WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime, - byte* data, word16 size); -WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket); + byte* data, word16 size, void* heap); +WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap); + #endif /* HAVE_SESSION_TICKET */ +/** Quantum-Safe-Hybrid - draft-whyte-qsh-tls12-00 */ +#ifdef HAVE_QSH + +typedef struct QSHScheme { + struct QSHScheme* next; /* List Behavior */ + byte* PK; + word16 name; /* QSHScheme Names */ + word16 PKLen; +} QSHScheme; + +typedef struct QSHkey { + struct QSHKey* next; + word16 name; + buffer pub; + buffer pri; +} QSHKey; + +typedef struct QSHSecret { + QSHScheme* list; + buffer* SerSi; + buffer* CliSi; +} QSHSecret; + +/* used in key exchange during handshake */ +WOLFSSL_LOCAL int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input, + word16 length, byte isServer); +WOLFSSL_LOCAL word16 TLSX_QSHPK_Write(QSHScheme* list, byte* output); +WOLFSSL_LOCAL word16 TLSX_QSH_GetSize(QSHScheme* list, byte isRequest); + +/* used by api for setting a specific QSH scheme */ +WOLFSSL_LOCAL int TLSX_UseQSHScheme(TLSX** extensions, word16 name, + byte* pKey, word16 pKeySz, void* heap); + +/* used when parsing in QSHCipher structs */ +WOLFSSL_LOCAL int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, + byte* out, word16* szOut); +#ifndef NO_WOLFSSL_SERVER +WOLFSSL_LOCAL int TLSX_ValidateQSHScheme(TLSX** extensions, word16 name); +#endif + +#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 */ + byte* pubKey; /* Public key */ + word32 pubKeyLen; /* Public 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); +WOLFSSL_LOCAL int TLSX_KeyShare_DeriveSecret(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[WC_MAX_DIGEST_SIZE]; /* HMAC of handshake */ + byte hmac; /* HMAC algorithm */ + byte resumption:1; /* Resumption PSK */ + byte chosen:1; /* Server's choice */ + struct PreSharedKey* next; /* List pointer */ +} PreSharedKey; + +WOLFSSL_LOCAL int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, + byte* output, byte msgType, + word16* pSz); +WOLFSSL_LOCAL int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, + byte msgType, word16* pSz); +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 */ + + +#ifdef OPENSSL_EXTRA +enum SetCBIO { + WOLFSSL_CBIO_NONE = 0, + WOLFSSL_CBIO_RECV = 0x1, + WOLFSSL_CBIO_SEND = 0x2, +}; +#endif + /* wolfSSL context type */ struct WOLFSSL_CTX { WOLFSSL_METHOD* method; - wolfSSL_Mutex countMutex; /* reference count mutex */ +#ifdef SINGLE_THREADED + WC_RNG* rng; /* to be shared with WOLFSSL w/o locking */ +#endif + wolfSSL_Mutex countMutex; /* reference count mutex */ int refCount; /* reference count */ + int err; /* error code in case of mutex not created */ #ifndef NO_DH buffer serverDH_P; buffer serverDH_G; #endif #ifndef NO_CERTS - buffer certificate; - buffer certChain; + DerBuffer* certificate; + DerBuffer* certChain; /* chain after self, in DER, with leading size for each cert */ - buffer privateKey; + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names; + #endif + #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ + defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) + WOLF_STACK_OF(WOLFSSL_X509)* x509Chain; + client_cert_cb CBClientCert; /* client certificate callback */ + #endif +#ifdef WOLFSSL_TLS13 + int certChainCnt; +#endif + DerBuffer* privateKey; + byte privateKeyType:7; + byte privateKeyId:1; + int privateKeySz; + int privateKeyDevId; 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 */ - byte verifyPeer; - byte verifyNone; - byte failNoCert; - byte sessionCacheOff; - byte sessionCacheFlushOff; - byte sendVerify; /* for client side */ - byte haveRSA; /* RSA available */ - byte haveDH; /* server DH parms set by user */ - byte haveNTRU; /* server private NTRU key loaded */ - byte haveECDSAsig; /* server cert signed w/ ECDSA */ - byte haveStaticECC; /* static server ECC private key */ - byte partialWrite; /* only one msg per write call */ - byte quietShutdown; /* don't send close notify */ - byte groupMessages; /* group handshake messages before sending */ + byte verifyDepth; + byte verifyPeer:1; + byte verifyNone:1; + byte failNoCert:1; + byte failNoCertxPSK:1; /* fail if no cert with the exception of PSK*/ + byte sessionCacheOff:1; + byte sessionCacheFlushOff:1; +#ifdef HAVE_EXT_CACHE + byte internalCacheOff:1; +#endif + byte sendVerify:2; /* for client side (can not be single bit) */ + byte haveRSA:1; /* RSA available */ + byte haveECC:1; /* ECC available */ + byte haveDH:1; /* server DH parms set by user */ + byte haveNTRU:1; /* server private NTRU key loaded */ + byte haveECDSAsig:1; /* server cert signed w/ ECDSA */ + byte haveStaticECC:1; /* static server ECC private key */ + byte partialWrite:1; /* only one msg per write call */ + byte quietShutdown:1; /* don't send close notify */ + byte groupMessages:1; /* group handshake messages before sending */ byte minDowngrade; /* minimum downgrade version */ + byte haveEMS:1; /* 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 + byte mutualAuth:1; /* Mutual authentication required */ +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + byte postHandshakeAuth:1; /* Post-handshake auth supported. */ +#endif +#ifndef NO_DH + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + byte dhKeyTested:1; /* Set when key has been tested. */ + #endif +#endif +#ifdef HAVE_SECURE_RENEGOTIATION + byte useSecureReneg:1; /* when set will set WOLFSSL objects generated to enable */ +#endif +#ifdef HAVE_ENCRYPT_THEN_MAC + byte disallowEncThenMac:1; /* Don't do Encrypt-Then-MAC */ +#endif +#ifdef WOLFSSL_STATIC_MEMORY + byte onHeap:1; /* whether the ctx/method is put on heap hint */ +#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 */ +#endif +#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \ + defined(WOLFSSL_DTLS) + word16 dtlsMtuSz; /* DTLS MTU size */ +#endif #ifndef NO_DH word16 minDhKeySz; /* minimum DH key size */ + word16 maxDhKeySz; /* maximum DH key size */ +#endif +#ifndef NO_RSA + short minRsaKeySz; /* minimum RSA key size */ +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + short minEccKeySz; /* minimum ECC key size */ +#endif +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + unsigned long mask; /* store SSL_OP_ flags */ +#endif +#ifdef OPENSSL_EXTRA + byte sessionCtx[ID_LEN]; /* app session context ID */ + word32 disabledCurves; /* curves disabled by user */ + const unsigned char *alpn_cli_protos;/* ALPN client protocol list */ + unsigned int alpn_cli_protos_len; + byte sessionCtxSz; + byte cbioFlag; /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */ + CallbackInfoState* CBIS; /* used to get info about SSL state */ #endif CallbackIORecv CBIORecv; CallbackIOSend CBIOSend; #ifdef WOLFSSL_DTLS CallbackGenCookie CBIOCookie; /* gen cookie callback */ +#ifdef WOLFSSL_SESSION_EXPORT + wc_dtls_export dtls_export; /* export function for DTLS session */ + CallbackGetPeer CBGetPeer; + CallbackSetPeer CBSetPeer; #endif +#endif /* WOLFSSL_DTLS */ VerifyCallback verifyCallback; /* cert verification callback */ +#ifdef OPENSSL_ALL + CertVerifyCallback verifyCertCb; + void* verifyCertCbArg; +#endif /* OPENSSL_ALL */ word32 timeout; /* session timeout */ +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_ED448) + word32 ecdhCurveOID; /* curve Ecc_Sum */ +#endif #ifdef HAVE_ECC word16 eccTempKeySz; /* in octets 20 - 66 */ +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) word32 pkCurveOID; /* curve Ecc_Sum */ #endif -#ifndef NO_PSK +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) byte havePSK; /* psk key set by user */ - psk_client_callback client_psk_cb; /* client callback */ - psk_server_callback server_psk_cb; /* server callback */ - char server_hint[MAX_PSK_ID_LEN]; -#endif /* NO_PSK */ + wc_psk_client_callback client_psk_cb; /* client callback */ + wc_psk_server_callback server_psk_cb; /* server callback */ +#ifdef WOLFSSL_TLS13 + wc_psk_client_tls13_callback client_psk_tls13_cb; /* client callback */ + wc_psk_server_tls13_callback server_psk_tls13_cb; /* server callback */ +#endif + char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ +#ifdef WOLFSSL_TLS13 + word16 group[WOLFSSL_MAX_GROUP_COUNT]; + byte numGroups; +#endif +#ifdef WOLFSSL_EARLY_DATA + word32 maxEarlyDataSz; +#endif #ifdef HAVE_ANON byte haveAnon; /* User wants to allow Anon suites */ #endif /* HAVE_ANON */ +#ifdef WOLFSSL_ENCRYPTED_KEYS + pem_password_cb* passwd_cb; + void* passwd_userdata; +#endif #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - pem_password_cb passwd_cb; - void* userdata; -#endif /* OPENSSL_EXTRA */ + WOLFSSL_X509_STORE x509_store; /* points to ctx->cm */ + WOLFSSL_X509_STORE* x509_store_pt; /* take ownership of external store */ + byte readAhead; + void* userPRFArg; /* passed to prf callback */ +#endif +#ifdef HAVE_EX_DATA + WOLFSSL_CRYPTO_EX_DATA ex_data; +#endif +#if defined(HAVE_ALPN) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) + CallbackALPNSelect alpnSelect; + void* alpnSelectArg; +#endif +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH) )) + 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 trigger level */ + word32 mcastMaxSeq; /* max level */ +#endif #ifdef HAVE_OCSP WOLFSSL_OCSP ocsp; #endif -#ifdef HAVE_CAVIUM - int devId; /* cavium device id to use */ -#endif + int devId; /* async device id to use */ #ifdef HAVE_TLS_EXTENSIONS TLSX* extensions; /* RFC 6066 TLS Extensions data */ - #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SEVER) + #ifndef NO_WOLFSSL_SERVER + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + OcspRequest* certOcspRequest; + #endif + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + OcspRequest* chainOcspRequest[MAX_CHAIN_DEPTH]; + #endif + #endif + #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) SessionTicketEncCb ticketEncCb; /* enc/dec session ticket Cb */ void* ticketEncCtx; /* session encrypt context */ int ticketHint; /* ticket hint in seconds */ #endif + #ifdef HAVE_SUPPORTED_CURVES + byte userCurves; /* indicates user called wolfSSL_CTX_UseSupportedCurve */ + #endif #endif #ifdef ATOMIC_USER CallbackMacEncrypt MacEncryptCb; /* Atomic User Mac/Encrypt Cb */ CallbackDecryptVerify DecryptVerifyCb; /* Atomic User Decrypt/Verify Cb */ + #ifdef HAVE_ENCRYPT_THEN_MAC + CallbackEncryptMac EncryptMacCb; /* Atomic User Mac/Enc Cb */ + CallbackVerifyDecrypt VerifyDecryptCb; /* Atomic User Dec/Verify Cb */ + #endif #endif #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC + CallbackEccKeyGen EccKeyGenCb; /* User EccKeyGen Callback Handler */ 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 X25519 KeyGen Callback Handler */ + CallbackX25519KeyGen X25519KeyGenCb; + /* User X25519 SharedSecret Callback handler */ + CallbackX25519SharedSecret X25519SharedSecretCb; + #endif + #ifdef HAVE_ED448 + /* User Ed448Sign Callback handler */ + CallbackEd448Sign Ed448SignCb; + /* User Ed448Verify Callback handler */ + CallbackEd448Verify Ed448VerifyCb; + #endif + #ifdef HAVE_CURVE448 + /* User X448 KeyGen Callback Handler */ + CallbackX448KeyGen X448KeyGenCb; + /* User X448 SharedSecret Callback handler */ + CallbackX448SharedSecret X448SharedSecretCb; + #endif #endif /* HAVE_ECC */ - #ifndef NO_RSA - CallbackRsaSign RsaSignCb; /* User RsaSign Callback handler */ - CallbackRsaVerify RsaVerifyCb; /* User RsaVerify Callback handler */ + #ifndef NO_DH + CallbackDhAgree DhAgreeCb; /* User DH Agree Callback handler */ + #endif + #ifndef NO_RSA + CallbackRsaSign RsaSignCb; /* User RsaSign Callback handler (priv key) */ + CallbackRsaVerify RsaVerifyCb; /* User RsaVerify Callback handler (pub key) */ + CallbackRsaVerify RsaSignCheckCb; /* User VerifyRsaSign Callback handler (priv key) */ + #ifdef WC_RSA_PSS + CallbackRsaPssSign RsaPssSignCb; /* User RsaSign (priv key) */ + CallbackRsaPssVerify RsaPssVerifyCb; /* User RsaVerify (pub key) */ + CallbackRsaPssVerify RsaPssSignCheckCb; /* User VerifyRsaSign (priv key) */ + #endif CallbackRsaEnc RsaEncCb; /* User Rsa Public Encrypt handler */ CallbackRsaDec RsaDecCb; /* User Rsa Private Decrypt handler */ #endif /* NO_RSA */ #endif /* HAVE_PK_CALLBACKS */ +#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 }; - WOLFSSL_LOCAL -int InitSSL_Ctx(WOLFSSL_CTX*, WOLFSSL_METHOD*); +int InitSSL_Ctx(WOLFSSL_CTX*, WOLFSSL_METHOD*, void* heap); WOLFSSL_LOCAL void FreeSSL_Ctx(WOLFSSL_CTX*); WOLFSSL_LOCAL @@ -1601,14 +2890,22 @@ 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* ctx, buffer der, int type, int verify); + int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify); WOLFSSL_LOCAL int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash); +#ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_LOCAL + int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify); + WOLFSSL_LOCAL + int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash); +#endif #endif -/* All cipher suite related info */ +/* All cipher suite related info + * Keep as a constant size (no ifdefs) for session export */ typedef struct CipherSpecs { word16 key_size; word16 iv_size; @@ -1628,28 +2925,15 @@ typedef struct CipherSpecs { void InitCipherSpecs(CipherSpecs* cs); -/* Supported Message Authentication Codes from page 43 */ -enum MACAlgorithm { - no_mac, - md5_mac, - sha_mac, - sha224_mac, - sha256_mac, /* needs to match external KDF_MacAlgorithm */ - sha384_mac, - sha512_mac, - rmd_mac, - blake2b_mac -}; - - /* Supported Key Exchange Protocols */ -enum KeyExchangeAlgorithm { +enum KeyExchangeAlgorithm { no_kea, - rsa_kea, - diffie_hellman_kea, + rsa_kea, + diffie_hellman_kea, fortezza_kea, psk_kea, dhe_psk_kea, + ecdhe_psk_kea, ntru_kea, ecc_diffie_hellman_kea, ecc_static_diffie_hellman_kea /* for verify suite only */ @@ -1658,10 +2942,26 @@ 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, + rsa_pss_pss_algo = 10, + ed448_sa_algo = 11 +}; + +#define PSS_RSAE_TO_PSS_PSS(macAlgo) \ + (macAlgo + (pss_sha256 - sha256_mac)) + +#define PSS_PSS_HASH_TO_MAC(macAlgo) \ + (macAlgo - (pss_sha256 - sha256_mac)) + +enum SigAlgRsaPss { + pss_sha256 = 0x09, + pss_sha384 = 0x0a, + pss_sha512 = 0x0b, }; @@ -1672,8 +2972,8 @@ enum EccCurves { /* Valid client certificate request types from page 27 */ -enum ClientCertificateType { - rsa_sign = 1, +enum ClientCertificateType { + rsa_sign = 1, dss_sign = 2, rsa_fixed_dh = 3, dss_fixed_dh = 4, @@ -1686,11 +2986,17 @@ enum ClientCertificateType { }; +#ifndef WOLFSSL_AEAD_ONLY enum CipherType { stream, block, aead }; +#else +enum CipherType { aead }; +#endif - - +#if defined(BUILD_AES) || defined(BUILD_AESGCM) || (defined(HAVE_CHACHA) && \ + defined(HAVE_POLY1305)) || defined(WOLFSSL_TLS13) + #define CIPHER_NONCE +#endif /* cipher for now */ @@ -1703,6 +3009,13 @@ typedef struct Ciphers { #endif #if defined(BUILD_AES) || defined(BUILD_AESGCM) Aes* aes; + #if (defined(BUILD_AESGCM) || defined(HAVE_AESCCM)) && \ + !defined(WOLFSSL_NO_TLS12) + byte* additional; + #endif +#endif +#ifdef CIPHER_NONCE + byte* nonce; #endif #ifdef HAVE_CAMELLIA Camellia* cam; @@ -1716,6 +3029,13 @@ typedef struct Ciphers { #ifdef BUILD_RABBIT Rabbit* rabbit; #endif +#ifdef HAVE_IDEA + Idea* idea; +#endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER) + Hmac* hmac; +#endif + byte state; byte setup; /* have we set it up flag for detection */ } Ciphers; @@ -1738,21 +3058,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 { @@ -1770,34 +3107,74 @@ 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 */ + 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 */ +#ifdef OPENSSL_EXTRA + WOLFSSL_X509* peer; /* peer cert */ +#endif + 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 */ +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + 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 OPENSSL_EXTRA + byte sessionCtxSz; /* sessionCtx length */ + byte sessionCtx[ID_LEN]; /* app specific context id */ +#endif +#ifdef WOLFSSL_TLS13 + word16 namedGroup; +#endif +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + #ifdef WOLFSSL_TLS13 + 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 #endif #ifdef HAVE_SESSION_TICKET - word16 ticketLen; - byte ticket[SESSION_TICKET_LEN]; + byte* ticket; + word16 ticketLen; + byte staticTicket[SESSION_TICKET_LEN]; + byte isDynamic; +#endif +#ifdef HAVE_EXT_CACHE + byte isAlloced; +#endif +#ifdef HAVE_EX_DATA + WOLFSSL_CRYPTO_EX_DATA ex_data; #endif }; WOLFSSL_LOCAL -WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*); +WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*, byte); WOLFSSL_LOCAL int SetSession(WOLFSSL*, WOLFSSL_SESSION*); -typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int); +typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int, int); #ifndef NO_CLIENT_CACHE WOLFSSL_SESSION* GetSessionClient(WOLFSSL*, const byte*, int); @@ -1822,11 +3199,15 @@ enum ConnectState { /* server accept state for nonblocking restart */ enum AcceptState { ACCEPT_BEGIN = 0, + ACCEPT_BEGIN_RENEG, ACCEPT_CLIENT_HELLO_DONE, - HELLO_VERIFY_SENT, + 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, SERVER_HELLO_DONE, @@ -1837,12 +3218,34 @@ enum AcceptState { ACCEPT_THIRD_REPLY_DONE }; +/* TLS 1.3 server accept state for nonblocking restart */ +enum AcceptStateTls13 { + TLS13_ACCEPT_BEGIN = 0, + TLS13_ACCEPT_BEGIN_RENEG, + TLS13_ACCEPT_CLIENT_HELLO_DONE, + TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE, + TLS13_ACCEPT_FIRST_REPLY_DONE, + TLS13_ACCEPT_SECOND_REPLY_DONE, + TLS13_SERVER_HELLO_SENT, + TLS13_ACCEPT_THIRD_REPLY_DONE, + TLS13_SERVER_EXTENSIONS_SENT, + TLS13_CERT_REQ_SENT, + TLS13_CERT_SENT, + TLS13_CERT_VERIFY_SENT, + TLS13_ACCEPT_FINISHED_SENT, + TLS13_PRE_TICKET_SENT, + TLS13_ACCEPT_FINISHED_DONE, + TLS13_TICKET_SENT +}; +/* buffers for struct WOLFSSL */ typedef struct Buffers { bufferStatic inputBuffer; bufferStatic outputBuffer; - buffer domainName; /* for client check */ + buffer domainName; /* for client check */ buffer clearOutputBuffer; + buffer sig; /* signature data */ + buffer digest; /* digest data */ int prevSent; /* previous plain text bytes sent when got WANT_WRITE */ int plainSz; /* plain text bytes in buffer to send @@ -1856,69 +3259,135 @@ 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 - buffer certificate; /* WOLFSSL_CTX owns, unless we own */ - buffer key; /* WOLFSSL_CTX owns, unless we own */ - buffer certChain; /* WOLFSSL_CTX owns, unless we own */ + DerBuffer* certificate; /* WOLFSSL_CTX owns, unless we own */ + DerBuffer* key; /* WOLFSSL_CTX owns, unless we own */ + byte keyType:7; /* Type of key: RSA, ECC, Ed25519 */ + byte keyId:1; /* Key data is an id not data */ + int keySz; /* Size of RSA key */ + int keyDevId; /* Device Id for 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; + DerBuffer* certExts; +#endif +#endif +#ifdef WOLFSSL_SEND_HRR_COOKIE + buffer tls13CookieSecret; /* HRR cookie secret */ #endif #ifdef WOLFSSL_DTLS - WOLFSSL_DTLS_CTX dtlsCtx; /* DTLS connection context */ + WOLFSSL_DTLS_CTX dtlsCtx; /* DTLS connection context */ + #ifndef NO_WOLFSSL_SERVER + buffer dtlsCookieSecret; /* DTLS cookie secret */ + #endif /* NO_WOLFSSL_SERVER */ #endif #ifdef HAVE_PK_CALLBACKS #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 */ + #ifdef HAVE_ED448 + buffer peerEd448Key; /* for Ed448 Verify Callbacks */ + #endif /* HAVE_ED448 */ #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, + BUILD_MSG_ENCRYPTED_VERIFY_MAC, +}; + +/* sub-states for cipher operations */ +enum cipherState { + CIPHER_STATE_BEGIN = 0, + CIPHER_STATE_DO, + CIPHER_STATE_END, +}; + typedef struct Options { #ifndef NO_PSK - psk_client_callback client_psk_cb; - psk_server_callback server_psk_cb; - word16 havePSK:1; /* psk key set by user */ + wc_psk_client_callback client_psk_cb; + wc_psk_server_callback server_psk_cb; +#ifdef WOLFSSL_TLS13 + wc_psk_client_tls13_callback client_psk_tls13_cb; /* client callback */ + wc_psk_server_tls13_callback server_psk_tls13_cb; /* server callback */ +#endif #endif /* NO_PSK */ +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + 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; - word16 side:1; /* client or server end */ +#ifdef HAVE_EXT_CACHE + word16 internalCacheOff:1; +#endif + word16 side:2; /* client, server or neither end */ word16 verifyPeer:1; word16 verifyNone:1; word16 failNoCert:1; + word16 failNoCertxPSK:1; /* fail for no cert except with PSK */ word16 downgrade:1; /* allow downgrade of versions */ word16 resuming:1; 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 */ - word16 closeNotify:1; /* we've recieved a close notify */ + word16 closeNotify:1; /* we've received a close notify */ word16 sentNotify:1; /* we've sent a close notify */ word16 usingCompression:1; /* are we using compression */ word16 haveRSA:1; /* RSA available */ + word16 haveECC:1; /* ECC available */ word16 haveDH:1; /* server DH parms set by user */ word16 haveNTRU:1; /* server NTRU private key loaded */ + word16 haveQSH:1; /* have QSH ability */ word16 haveECDSAsig:1; /* server ECDSA signed cert */ word16 haveStaticECC:1; /* static server ECC private key */ word16 havePeerCert:1; /* do we have peer's cert */ 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 */ word16 certOnly:1; /* stop once we get cert */ word16 groupMessages:1; /* group handshake messages */ - word16 usingNonblock:1; /* are we using nonblocking socket */ 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 @@ -1928,6 +3397,58 @@ typedef struct Options { #ifdef HAVE_SESSION_TICKET 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 dtlsUseNonblock:1; /* are we using nonblocking socket */ + word16 dtlsHsRetain:1; /* DTLS retaining HS data */ + word16 haveMcast:1; /* using multicast ? */ +#ifdef WOLFSSL_SCTP + word16 dtlsSctp:1; /* DTLS-over-SCTP mode */ +#endif +#endif +#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 */ + word16 mutualAuth:1; /* Mutual authentication is rquired */ +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + word16 postHandshakeAuth:1;/* Client send post_handshake_auth + * extension */ +#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 +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + word16 sentChangeCipher:1; /* Change Cipher Spec sent */ +#endif +#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ + ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ + (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) + word16 cacheMessages:1; /* Cache messages for sign/verify */ +#endif +#ifndef NO_DH + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \ + !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + word16 dhDoKeyTest:1; /* Need to do the DH Key prime test */ + word16 dhKeyTested:1; /* Set when key has been tested. */ + #endif +#endif +#ifdef SINGLE_THREADED + word16 ownSuites:1; /* if suites are malloced in ssl object */ +#endif +#ifdef HAVE_ENCRYPT_THEN_MAC + word16 disallowEncThenMac:1; /* Don't do Encrypt-Then-MAC */ + word16 encThenMac:1; /* Doing Encrypt-Then-MAC */ + word16 startedETMRead:1; /* Doing Encrypt-Then-MAC read */ + word16 startedETMWrite:1; /* Doing Encrypt-Then-MAC write */ #endif /* need full byte values for this section */ @@ -1941,31 +3462,64 @@ typedef struct Options { byte minDowngrade; /* minimum downgrade version */ byte connectState; /* nonblocking resume */ byte acceptState; /* nonblocking resume */ + 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 maxDhKeySz; /* minimum DH key size */ word16 dhKeySz; /* actual DH key size */ #endif - +#ifndef NO_RSA + short minRsaKeySz; /* minimum RSA key size */ +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + short minEccKeySz; /* minimum ECC key size */ +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + byte verifyDepth; /* maximum verification depth */ +#endif +#ifdef WOLFSSL_EARLY_DATA + word16 pskIdIndex; + word32 maxEarlyDataSz; +#endif +#ifdef WOLFSSL_TLS13 + byte oldMinor; /* client preferred version < TLS 1.3 */ +#endif } Options; typedef struct Arrays { + byte* pendingMsg; /* defrag buffer */ + byte* preMasterSecret; word32 preMasterSz; /* differs for DH, actual size */ -#ifndef NO_PSK - word32 psk_keySz; /* acutal size */ - char client_identity[MAX_PSK_ID_LEN]; - char server_hint[MAX_PSK_ID_LEN]; + word32 pendingMsgSz; /* defrag buffer size */ + word32 pendingMsgOffset; /* current offset into defrag buffer */ +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + word32 psk_keySz; /* actual size */ + 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 secret[SECRET_LEN]; +#endif byte masterSecret[SECRET_LEN]; +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + byte tsip_masterSecret[TSIP_TLS_MASTERSECRET_SIZE]; +#endif #ifdef WOLFSSL_DTLS byte cookie[MAX_COOKIE_LEN]; byte cookieSz; #endif + byte pendingMsgType; /* defrag buffer message type */ } Arrays; #ifndef ASN_NAME_MAX @@ -1976,78 +3530,171 @@ typedef struct Arrays { #define MAX_DATE_SZ 32 #endif +#define STACK_TYPE_X509 0 +#define STACK_TYPE_GEN_NAME 1 +#define STACK_TYPE_BIO 2 +#define STACK_TYPE_OBJ 3 +#define STACK_TYPE_STRING 4 +#define STACK_TYPE_CIPHER 5 +#define STACK_TYPE_ACCESS_DESCRIPTION 6 +#define STACK_TYPE_X509_EXT 7 +#define STACK_TYPE_NULL 8 +#define STACK_TYPE_X509_NAME 9 +#define STACK_TYPE_CONF_VALUE 10 +#define STACK_TYPE_X509_INFO 11 + +struct WOLFSSL_STACK { + unsigned long num; /* number of nodes in stack + * (safety measure for freeing and shortcut for count) */ + #if defined(OPENSSL_ALL) + wolf_sk_compare_cb comp; + #endif + + union { + WOLFSSL_X509* x509; + WOLFSSL_X509_NAME* name; + WOLFSSL_X509_INFO* info; + WOLFSSL_BIO* bio; + WOLFSSL_ASN1_OBJECT* obj; + WOLFSSL_CIPHER cipher; + WOLFSSL_ACCESS_DESCRIPTION* access; + WOLFSSL_X509_EXTENSION* ext; + WOLFSSL_CONF_VALUE* conf; + void* generic; + char* string; + WOLFSSL_GENERAL_NAME* gn; + } data; + void* heap; /* memory heap hint */ + WOLFSSL_STACK* next; + byte type; /* Identifies type of stack. */ +}; + struct WOLFSSL_X509_NAME { char *name; - char staticName[ASN_NAME_MAX]; int dynamicName; int sz; -#ifdef OPENSSL_EXTRA + char staticName[ASN_NAME_MAX]; +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + !defined(NO_ASN) DecodedName fullName; + WOLFSSL_X509_NAME_ENTRY cnEntry; + WOLFSSL_X509_NAME_ENTRY extra[MAX_NAME_ENTRIES]; /* extra entries added */ + WOLFSSL_X509* x509; /* x509 that struct belongs to */ #endif /* OPENSSL_EXTRA */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + byte raw[ASN_NAME_MAX]; + int rawLen; +#endif }; #ifndef EXTERNAL_SERIAL_SIZE #define EXTERNAL_SERIAL_SIZE 32 #endif -#ifdef NO_ASN +#ifdef NO_ASN typedef struct DNS_entry DNS_entry; #endif struct WOLFSSL_X509 { int version; - WOLFSSL_X509_NAME issuer; - WOLFSSL_X509_NAME subject; int serialSz; - byte serial[EXTERNAL_SERIAL_SIZE]; - char subjectCN[ASN_NAME_MAX]; /* common name short cut */ #ifdef WOLFSSL_SEP int deviceTypeSz; - byte deviceType[EXTERNAL_SERIAL_SIZE]; int hwTypeSz; + byte deviceType[EXTERNAL_SERIAL_SIZE]; byte hwType[EXTERNAL_SERIAL_SIZE]; int hwSerialNumSz; byte hwSerialNum[EXTERNAL_SERIAL_SIZE]; - #ifdef OPENSSL_EXTRA - byte certPolicySet; - byte certPolicyCrit; - #endif /* OPENSSL_EXTRA */ -#endif - int notBeforeSz; - byte notBefore[MAX_DATE_SZ]; - int notAfterSz; - byte notAfter[MAX_DATE_SZ]; - int sigOID; - buffer sig; - int pubKeyOID; - buffer pubKey; - #ifdef HAVE_ECC - word32 pkCurveOID; - #endif /* HAVE_ECC */ - buffer derCert; /* may need */ - DNS_entry* altNames; /* alt names list */ - DNS_entry* altNamesNext; /* hint for retrieval */ - byte dynamicMemory; /* dynamic memory flag */ - byte isCa; +#endif /* WOLFSSL_SEP */ +#if (defined(WOLFSSL_SEP) || defined(WOLFSSL_QT) || defined (OPENSSL_ALL)) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + byte certPolicySet; + byte certPolicyCrit; +#endif /* (WOLFSSL_SEP || WOLFSSL_QT) && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */ +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + WOLFSSL_STACK* ext_sk; /* Store X509_EXTENSIONS from wolfSSL_X509_get_ext */ + WOLFSSL_STACK* ext_d2i;/* Store d2i extensions from wolfSSL_X509_get_ext_d2i */ +#endif /* WOLFSSL_QT || OPENSSL_ALL */ #ifdef OPENSSL_EXTRA + WOLFSSL_ASN1_INTEGER* serialNumber; /* Stores SN from wolfSSL_X509_get_serialNumber */ +#endif + WOLFSSL_ASN1_TIME notBefore; + WOLFSSL_ASN1_TIME notAfter; + buffer sig; + int sigOID; + DNS_entry* altNames; /* alt names list */ + buffer pubKey; + int pubKeyOID; + DNS_entry* altNamesNext; /* hint for retrieval */ +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + word32 pkCurveOID; +#endif /* HAVE_ECC */ +#ifndef NO_CERTS + DerBuffer* derCert; /* may need */ +#endif + void* heap; /* heap hint */ + byte dynamicMemory; /* dynamic memory flag */ + byte isCa:1; +#ifdef WOLFSSL_CERT_EXT + char certPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ]; + int certPoliciesNb; +#endif /* WOLFSSL_CERT_EXT */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + wolfSSL_Mutex refMutex; /* ref count mutex */ + int refCount; /* reference count */ +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +#ifdef HAVE_EX_DATA + WOLFSSL_CRYPTO_EX_DATA ex_data; +#endif + byte* authKeyId; + byte* subjKeyId; + byte* extKeyUsageSrc; + const byte* CRLInfo; + byte* authInfo; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + byte* authInfoCaIssuer; + int authInfoCaIssuerSz; +#endif word32 pathLength; word16 keyUsage; - byte basicConstSet; - byte basicConstCrit; - byte basicConstPlSet; - byte subjAltNameSet; - byte subjAltNameCrit; - byte authKeyIdSet; - byte authKeyIdCrit; - byte* authKeyId; + int CRLInfoSz; + int authInfoSz; word32 authKeyIdSz; - byte subjKeyIdSet; - byte subjKeyIdCrit; - byte* subjKeyId; word32 subjKeyIdSz; - byte keyUsageSet; - byte keyUsageCrit; -#endif /* OPENSSL_EXTRA */ + word32 extKeyUsageSz; + word32 extKeyUsageCount; + + byte CRLdistSet:1; + byte CRLdistCrit:1; + byte authInfoSet:1; + byte authInfoCrit:1; + byte keyUsageSet:1; + byte keyUsageCrit:1; + byte extKeyUsageCrit:1; + byte subjKeyIdSet:1; + + byte subjKeyIdCrit:1; + byte basicConstSet:1; + byte basicConstCrit:1; + byte basicConstPlSet:1; + byte subjAltNameSet:1; + byte subjAltNameCrit:1; + byte authKeyIdSet:1; + byte authKeyIdCrit:1; +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + byte serial[EXTERNAL_SERIAL_SIZE]; + char subjectCN[ASN_NAME_MAX]; /* common name short cut */ +#ifdef WOLFSSL_CERT_REQ + char challengePw[CTC_NAME_SIZE]; /* for REQ certs */ +#endif + WOLFSSL_X509_NAME issuer; + WOLFSSL_X509_NAME subject; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS) + WOLFSSL_X509_ALGOR algor; + WOLFSSL_X509_PUBKEY key; +#endif + byte issuerSet:1; }; @@ -2065,25 +3712,27 @@ typedef struct DtlsRecordLayerHeader { byte type; byte pvMajor; byte pvMinor; - byte epoch[2]; /* increment on cipher state change */ - byte sequence_number[6]; /* per record */ + byte sequence_number[8]; /* per record */ byte length[2]; } DtlsRecordLayerHeader; -typedef struct DtlsPool { - buffer buf[DTLS_POOL_SZ]; - int used; -} DtlsPool; +typedef struct DtlsFrag { + word32 begin; + word32 end; + struct DtlsFrag* next; +} DtlsFrag; + typedef struct DtlsMsg { struct DtlsMsg* next; - word32 seq; /* Handshake sequence number */ - word32 sz; /* Length of whole mesage */ - word32 fragSz; /* Length of fragments received */ - byte type; byte* buf; byte* msg; + DtlsFrag* fragList; + word32 fragSz; /* Length of fragments received */ + word32 seq; /* Handshake sequence number */ + word32 sz; /* Length of whole message */ + byte type; } DtlsMsg; @@ -2099,21 +3748,25 @@ typedef struct DtlsMsg { #endif - -/* Handshake messages recevied from peer (plus change cipher */ +/* Handshake messages received from peer (plus change cipher */ typedef struct MsgsReceived { word16 got_hello_request:1; - word16 got_client_hello:1; - word16 got_server_hello:1; + word16 got_client_hello:2; + word16 got_server_hello:2; 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; word16 got_certificate_request:1; word16 got_server_hello_done:1; 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; @@ -2122,48 +3775,127 @@ 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 +#if (defined(HAVE_ED25519) || defined(HAVE_ED448)) && \ + !defined(WOLFSSL_NO_CLIENT_AUTH) + byte* messages; /* handshake messages */ + int length; /* length of handshake messages' data */ + int prevLen; /* length of messages but last */ #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 + +#ifdef WOLFSSL_EARLY_DATA +typedef enum EarlyDataState { + no_early_data, + early_data_ext, + expecting_early_data, + process_early_data, + done_early_data +} EarlyDataState; +#endif + /* wolfSSL ssl type */ struct WOLFSSL { WOLFSSL_CTX* ctx; Suites* suites; /* only need during handshake */ Arrays* arrays; +#ifdef WOLFSSL_TLS13 + byte clientSecret[SECRET_LEN]; + byte serverSecret[SECRET_LEN]; +#endif HS_Hashes* hsHashes; void* IOCB_ReadCtx; void* IOCB_WriteCtx; - RNG* rng; + WC_RNG* rng; 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 OPENSSL_EXTRA + byte cbioFlag; /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */ +#endif + CallbackIORecv CBIORecv; + CallbackIOSend CBIOSend; +#ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_HEAP_HINT heap_hint; +#endif #ifndef NO_HANDSHAKE_DONE_CB HandShakeDoneCb hsDoneCb; /* notify user handshake done */ void* hsDoneCtx; /* user handshake cb context */ #endif +#ifdef WOLFSSL_ASYNC_CRYPT + struct WOLFSSL_ASYNC async; +#elif defined(WOLFSSL_NONBLOCK_OCSP) + void* nonblockarg; /* dynamic arg for handling non-block resume */ +#endif + void* hsKey; /* Handshake key (RsaKey or ecc_key) allocated from heap */ + word32 hsType; /* Type of Handshake key (hsKey) */ WOLFSSL_CIPHER cipher; +#ifndef WOLFSSL_AEAD_ONLY hmacfp hmac; +#endif 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 */ @@ -2171,7 +3903,9 @@ struct WOLFSSL { int rflags; /* user read flags */ int wflags; /* user write flags */ word32 timeout; /* session timeout */ + word32 fragOffset; /* fragment offset */ word16 curSize; + byte verifyDepth; RecordLayerHeader curRL; MsgsReceived msgsReceived; /* peer messages received */ ProtocolVersion version; /* negotiated version */ @@ -2180,27 +3914,96 @@ struct WOLFSSL { Keys keys; Options options; #ifdef OPENSSL_EXTRA + CallbackInfoState* CBIS; /* used to get info about SSL state */ + int cbmode; /* read or write on info callback */ + int cbtype; /* event type in info callback */ WOLFSSL_BIO* biord; /* socket bio read to free/close */ WOLFSSL_BIO* biowr; /* socket bio write to free/close */ + byte sessionCtx[ID_LEN]; /* app session context ID */ + WOLFSSL_X509_VERIFY_PARAM* param; /* verification parameters*/ #endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + unsigned long peerVerifyRet; +#endif +#ifdef OPENSSL_EXTRA + byte readAhead; + byte sessionCtxSz; /* size of sessionCtx stored */ +#ifdef HAVE_PK_CALLBACKS + void* loggingCtx; /* logging callback argument */ +#endif +#endif /* OPENSSL_EXTRA */ #ifndef NO_RSA RsaKey* peerRsaKey; +#ifdef WOLFSSL_RENESAS_TSIP_TLS + byte *peerTsipEncRsaKeyIndex; +#endif byte peerRsaKeyPresent; #endif +#ifdef HAVE_QSH + QSHKey* QSH_Key; + QSHKey* peerQSHKey; + QSHSecret* QSH_secret; + byte isQSH; /* is the handshake a QSH? */ + byte sendQSHKeys; /* flag for if the client should sen + public keys */ + byte peerQSHKeyPresent; + byte minRequest; + byte maxRequest; + byte user_set_QSHSchemes; +#endif +#if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE) + word16 namedGroup; +#endif +#ifdef WOLFSSL_TLS13 + word16 group[WOLFSSL_MAX_GROUP_COUNT]; + byte numGroups; +#endif + word16 pssAlgo; +#ifdef WOLFSSL_TLS13 + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + word16 certHashSigAlgoSz; /* SigAlgoCert ext length in bytes */ + byte certHashSigAlgo[WOLFSSL_MAX_SIGALGO]; /* cert sig/algo to + * offer */ + #endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */ +#endif #ifdef HAVE_NTRU word16 peerNtruKeyLen; byte peerNtruKey[MAX_NTRU_PUB_KEY_SZ]; byte peerNtruKeyPresent; #endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + int eccVerifyRes; +#endif +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) + 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 +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_CURVE448) + word32 pkCurveOID; /* curve Ecc_Sum */ +#endif +#ifdef HAVE_ED25519 + ed25519_key* peerEd25519Key; + byte peerEd25519KeyPresent; +#endif +#ifdef HAVE_CURVE25519 + curve25519_key* peerX25519Key; + byte peerX25519KeyPresent; +#endif +#ifdef HAVE_ED448 + ed448_key* peerEd448Key; + byte peerEd448KeyPresent; +#endif +#ifdef HAVE_CURVE448 + curve448_key* peerX448Key; + byte peerX448KeyPresent; #endif #ifdef HAVE_LIBZ z_stream c_stream; /* compression stream */ @@ -2208,17 +4011,39 @@ struct WOLFSSL { byte didStreamInit; /* for stream init and end */ #endif #ifdef WOLFSSL_DTLS - int dtls_timeout_init; /* starting timeout vaule */ + int dtls_timeout_init; /* starting timeout value */ int dtls_timeout_max; /* maximum timeout value */ int dtls_timeout; /* current timeout value, changes */ - DtlsPool* dtls_pool; - DtlsMsg* dtls_msg_list; + word32 dtls_tx_msg_list_sz; + word32 dtls_rx_msg_list_sz; + DtlsMsg* dtls_tx_msg_list; + DtlsMsg* dtls_tx_msg; + DtlsMsg* dtls_rx_msg_list; void* IOCB_CookieCtx; /* gen cookie ctx */ word32 dtls_expected_rx; +#ifdef WOLFSSL_SESSION_EXPORT + wc_dtls_export dtls_export; /* export function for session */ #endif +#if defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU) + word16 dtlsMtuSz; +#endif /* WOLFSSL_SCTP || WOLFSSL_DTLS_MTU */ +#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 */ + HandShakeInfo handShakeInfo; /* info saved during handshake */ +#endif +#ifdef OPENSSL_EXTRA + SSL_Msg_Cb protoMsgCb; /* inspect protocol message callback */ + void* protoMsgCtx; /* user set context with msg callback */ +#endif +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) byte hsInfoOn; /* track handshake info */ byte toInfoOn; /* track timeout info */ #endif @@ -2226,15 +4051,22 @@ 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 -#ifdef FORTRESS - void* ex_data[MAX_EX_DATA]; /* external data, for Fortress */ +#ifdef KEEP_OUR_CERT + WOLFSSL_X509* ourCert; /* keep alive a X509 struct of cert. + points to ctx if not owned (owned + flag found in buffers.weOwnCert) */ #endif -#ifdef HAVE_CAVIUM - int devId; /* cavium device id to use */ + byte keepCert; /* keep certificate after handshake */ +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + WOLFSSL_CRYPTO_EX_DATA ex_data; /* external data, for Fortress */ #endif + int devId; /* async device id to use */ #ifdef HAVE_ONE_TIME_AUTH OneTimeAuth auth; #endif @@ -2246,33 +4078,93 @@ struct WOLFSSL { #ifdef HAVE_TRUNCATED_HMAC byte truncated_hmac; #endif - #ifdef HAVE_SECURE_RENEGOTIATION + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + byte status_request; + #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + byte status_request_v2; + #endif + #if defined(HAVE_SECURE_RENEGOTIATION) \ + || defined(HAVE_SERVER_RENEGOTIATION_INFO) + int secure_rene_count; /* how many times */ SecureRenegotiation* secure_renegotiation; /* valid pointer indicates */ #endif /* user turned on */ + #ifdef HAVE_ALPN + char* alpn_client_list; /* keep the client's list */ + #if defined(OPENSSL_ALL) || 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; void* session_ticket_ctx; byte expect_session_ticket; #endif #endif /* HAVE_TLS_EXTENSIONS */ +#ifdef HAVE_OCSP + void* ocspIOCtx; + #ifdef OPENSSL_EXTRA + byte* ocspResp; + int ocspRespSz; + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + char* url; + #endif + #endif +#endif #ifdef HAVE_NETX NetX_Ctx nxCtx; /* NetX IO Context */ #endif +#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + void* mnCtx; /* mynewt mn_socket IO Context */ +#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */ +#ifdef WOLFSSL_GNRC + struct gnrc_wolfssl_ctx *gnrcCtx; /* Riot-OS GNRC UDP/IP context */ +#endif #ifdef SESSION_INDEX int sessionIndex; /* Session's location in the cache. */ #endif #ifdef ATOMIC_USER void* MacEncryptCtx; /* Atomic User Mac/Encrypt Callback Context */ void* DecryptVerifyCtx; /* Atomic User Decrypt/Verify Callback Context */ + #ifdef HAVE_ENCRYPT_THEN_MAC + void* EncryptMacCtx; /* Atomic User Encrypt/Mac Callback Ctx */ + void* VerifyDecryptCtx; /* Atomic User Verify/Decrypt Callback Ctx */ + #endif #endif #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC - void* EccSignCtx; /* Ecc Sign Callback Context */ - void* EccVerifyCtx; /* Ecc Verify Callback Context */ + void* EccKeyGenCtx; /* EccKeyGen Callback Context */ + 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* X25519KeyGenCtx; /* X25519 KeyGen Callback Context */ + void* X25519SharedSecretCtx; /* X25519 Pms Callback Context */ + #endif + #ifdef HAVE_ED448 + void* Ed448SignCtx; /* ED448 Sign Callback Context */ + void* Ed448VerifyCtx; /* ED448 Verify Callback Context */ + #endif + #ifdef HAVE_CURVE448 + void* X448KeyGenCtx; /* X448 KeyGen Callback Context */ + void* X448SharedSecretCtx; /* X448 Pms Callback Context */ + #endif #endif /* HAVE_ECC */ + #ifndef NO_DH + void* DhAgreeCtx; /* DH Pms Callback Context */ + #endif /* !NO_DH */ #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 */ @@ -2280,61 +4172,69 @@ struct WOLFSSL { #ifdef HAVE_SECRET_CALLBACK SessionSecretCb sessionSecretCb; void* sessionSecretCtx; + #ifdef WOLFSSL_TLS13 + Tls13SecretCb tls13SecretCb; + void* tls13SecretCtx; + #endif #endif /* HAVE_SECRET_CALLBACK */ +#ifdef WOLFSSL_JNI + void* jObjectRef; /* reference to WolfSSLSession in JNI wrapper */ +#endif /* WOLFSSL_JNI */ +#ifdef WOLFSSL_EARLY_DATA + EarlyDataState earlyData; + word32 earlyDataSz; +#endif +#ifdef OPENSSL_ALL + long verifyCallbackResult; +#endif +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + WOLFSSL_STACK* supportedCiphers; /* Used in wolfSSL_get_ciphers_compat */ + WOLFSSL_STACK* peerCertChain; /* Used in wolfSSL_get_peer_cert_chain */ +#endif }; -WOLFSSL_LOCAL -int InitSSL(WOLFSSL*, WOLFSSL_CTX*); -WOLFSSL_LOCAL -void FreeSSL(WOLFSSL*); -WOLFSSL_API void SSL_ResourceFree(WOLFSSL*); /* Micrium uses */ - - -enum { - IV_SZ = 32, /* max iv sz */ - NAME_SZ = 80 /* max one line */ -}; - - -typedef struct EncryptedInfo { - char name[NAME_SZ]; /* encryption name */ - byte iv[IV_SZ]; /* encrypted IV */ - word32 ivSz; /* encrypted IV size */ - long consumed; /* tracks PEM bytes consumed */ - byte set; /* if encryption set */ - WOLFSSL_CTX* ctx; /* CTX owner */ -} EncryptedInfo; +WOLFSSL_LOCAL int SSL_CTX_RefCount(WOLFSSL_CTX* ctx, int incr); +WOLFSSL_LOCAL int SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*, int); +WOLFSSL_LOCAL int InitSSL(WOLFSSL*, WOLFSSL_CTX*, int); +WOLFSSL_LOCAL void FreeSSL(WOLFSSL*, void* heap); +WOLFSSL_API void SSL_ResourceFree(WOLFSSL*); /* Micrium uses */ #ifndef NO_CERTS - WOLFSSL_LOCAL int PemToDer(const unsigned char* buff, long sz, int type, - buffer* der, void* heap, EncryptedInfo* info, - int* eccKey); + WOLFSSL_LOCAL int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, + long sz, int format, int type, WOLFSSL* ssl, + long* used, int userChain, int verify); WOLFSSL_LOCAL int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, WOLFSSL* ssl, int userChain, - WOLFSSL_CRL* crl); + WOLFSSL_CRL* crl, int verify); + + #ifdef OPENSSL_EXTRA + WOLFSSL_LOCAL int CheckHostName(DecodedCert* dCert, char *domainName, + size_t domainNameLen); + #endif #endif -#ifdef WOLFSSL_CALLBACKS +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) WOLFSSL_LOCAL - void InitHandShakeInfo(HandShakeInfo*); - WOLFSSL_LOCAL - void FinishHandShakeInfo(HandShakeInfo*, const WOLFSSL*); - WOLFSSL_LOCAL - void AddPacketName(const char*, HandShakeInfo*); + void InitHandShakeInfo(HandShakeInfo*, WOLFSSL*); + WOLFSSL_LOCAL + void FinishHandShakeInfo(HandShakeInfo*); + WOLFSSL_LOCAL + void AddPacketName(WOLFSSL* ssl, const char* name); WOLFSSL_LOCAL void InitTimeoutInfo(TimeoutInfo*); - WOLFSSL_LOCAL + WOLFSSL_LOCAL void FreeTimeoutInfo(TimeoutInfo*, void*); - WOLFSSL_LOCAL - void AddPacketInfo(const char*, TimeoutInfo*, const byte*, int, void*); - WOLFSSL_LOCAL + WOLFSSL_LOCAL + void AddPacketInfo(WOLFSSL* ssl, const char* name, int type, + const byte* data, int sz, int write, void* heap); + WOLFSSL_LOCAL void AddLateName(const char*, TimeoutInfo*); - WOLFSSL_LOCAL + WOLFSSL_LOCAL void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info); #endif @@ -2342,10 +4242,10 @@ typedef struct EncryptedInfo { /* Record Layer Header identifier from page 12 */ enum ContentType { no_type = 0, - change_cipher_spec = 20, - alert = 21, - handshake = 22, - application_data = 23 + change_cipher_spec = 20, + alert = 21, + handshake = 22, + application_data = 23 }; @@ -2360,30 +4260,41 @@ typedef struct HandShakeHeader { typedef struct DtlsHandShakeHeader { byte type; word24 length; - byte message_seq[2]; /* start at 0, restransmit gets same # */ + byte message_seq[2]; /* start at 0, retransmit gets same # */ word24 fragment_offset; /* bytes in previous fragments */ word24 fragment_length; /* length of this fragment */ } DtlsHandShakeHeader; enum HandShakeType { - no_shake = -1, - 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 */ + 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 }; @@ -2393,14 +4304,41 @@ static const byte server[SIZEOF_SENDER] = { 0x53, 0x52, 0x56, 0x52 }; static const byte tls_client[FINISHED_LABEL_SZ + 1] = "client finished"; static const byte tls_server[FINISHED_LABEL_SZ + 1] = "server finished"; +#ifdef OPENSSL_EXTRA +typedef struct { + int name_len; + const char *name; + int nid; +} WOLF_EC_NIST_NAME; +extern const WOLF_EC_NIST_NAME kNistCurves[]; +/* This is the longest and shortest curve name in the kNistCurves list */ +#define kNistCurves_MIN_NAME_LEN 5 +#define kNistCurves_MAX_NAME_LEN 7 +#endif /* internal functions */ 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 +#ifdef WOLFSSL_TLS13_DRAFT_18 +WOLFSSL_LOCAL int SendTls13HelloRetryRequest(WOLFSSL*); +#else +WOLFSSL_LOCAL int SendTls13ServerHello(WOLFSSL*, byte); +#endif +#endif WOLFSSL_LOCAL int SendCertificate(WOLFSSL*); WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*); +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) +WOLFSSL_LOCAL int CreateOcspResponse(WOLFSSL*, OcspRequest**, buffer*); +#endif +#if defined(HAVE_SECURE_RENEGOTIATION) && \ + defined(HAVE_SERVER_RENEGOTIATION_INFO) +WOLFSSL_LOCAL int SendHelloRequest(WOLFSSL*); +#endif +WOLFSSL_LOCAL int SendCertificateStatus(WOLFSSL*); WOLFSSL_LOCAL int SendServerKeyExchange(WOLFSSL*); WOLFSSL_LOCAL int SendBuffered(WOLFSSL*); WOLFSSL_LOCAL int ReceiveData(WOLFSSL*, byte*, int, int); @@ -2411,24 +4349,100 @@ WOLFSSL_LOCAL int ProcessReply(WOLFSSL*); WOLFSSL_LOCAL int SetCipherSpecs(WOLFSSL*); 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 AddSession(WOLFSSL*); +WOLFSSL_LOCAL int DeriveKeys(WOLFSSL* ssl); +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); +WOLFSSL_LOCAL int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment); + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) +WOLFSSL_LOCAL int SetECKeyInternal(WOLFSSL_EC_KEY* eckey); +WOLFSSL_LOCAL int SetECKeyExternal(WOLFSSL_EC_KEY* eckey); +#endif + +WOLFSSL_LOCAL WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG, + int *initTmpRng); + #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, DerBuffer* keyBufInfo); + WOLFSSL_LOCAL int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key, + DerBuffer* keyBufInfo); + WOLFSSL_LOCAL int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, + byte** out, int sigAlgo, int hashAlgo, RsaKey* key, + buffer* keyBufInfo); + WOLFSSL_LOCAL int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, + word32* outSz, RsaKey* key, DerBuffer* keyBufInfo); + WOLFSSL_LOCAL int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, RsaKey* key, buffer* keyBufInfo); + #endif /* !NO_RSA */ + + #ifdef HAVE_ECC + WOLFSSL_LOCAL int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, ecc_key* key, DerBuffer* keyBufInfo); + WOLFSSL_LOCAL int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, + const byte* out, word32 outSz, ecc_key* key, buffer* keyBufInfo); + WOLFSSL_LOCAL int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, + ecc_key* pub_key, byte* pubKeyDer, word32* pubKeySz, byte* out, + word32* outlen, int side); + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + WOLFSSL_LOCAL int Ed25519CheckPubKey(WOLFSSL* ssl); + WOLFSSL_LOCAL int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, ed25519_key* key, DerBuffer* keyBufInfo); + WOLFSSL_LOCAL int Ed25519Verify(WOLFSSL* ssl, const byte* in, + word32 inSz, const byte* msg, word32 msgSz, ed25519_key* key, + buffer* keyBufInfo); + #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED448 + WOLFSSL_LOCAL int Ed448CheckPubKey(WOLFSSL* ssl); + WOLFSSL_LOCAL int Ed448Sign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, ed448_key* key, DerBuffer* keyBufInfo); + WOLFSSL_LOCAL int Ed448Verify(WOLFSSL* ssl, const byte* in, + word32 inSz, const byte* msg, word32 msgSz, ed448_key* key, + buffer* keyBufInfo); + #endif /* HAVE_ED448 */ + + + #ifdef WOLFSSL_TRUST_PEER_CERT + + /* options for searching hash table for a matching trusted peer cert */ + #define WC_MATCH_SKID 0 + #define WC_MATCH_NAME 1 + + WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, + int type); + WOLFSSL_LOCAL int MatchTrustedPeer(TrustedPeerCert* tp, + DecodedCert* cert); + #endif + WOLFSSL_LOCAL Signer* GetCA(void* cm, byte* hash); #ifndef NO_SKID WOLFSSL_LOCAL Signer* GetCAByName(void* cm, byte* hash); #endif -#endif +#endif /* !NO_CERTS */ +WOLFSSL_LOCAL int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, + word32* hashLen); WOLFSSL_LOCAL int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender); WOLFSSL_LOCAL void FreeArrays(WOLFSSL* ssl, int keep); @@ -2437,12 +4451,17 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); #ifndef NO_TLS WOLFSSL_LOCAL int MakeTlsMasterSecret(WOLFSSL*); +#ifndef WOLFSSL_AEAD_ONLY WOLFSSL_LOCAL int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, - word32 sz, int content, int verify); + word32 sz, int padSz, int content, int verify); +#endif #endif #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 */ @@ -2450,51 +4469,87 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); #ifndef NO_WOLFSSL_SERVER WOLFSSL_LOCAL int SendServerHello(WOLFSSL*); WOLFSSL_LOCAL int SendServerHelloDone(WOLFSSL*); - #ifdef WOLFSSL_DTLS - WOLFSSL_LOCAL int SendHelloVerifyRequest(WOLFSSL*); - #endif #endif /* NO_WOLFSSL_SERVER */ #ifdef WOLFSSL_DTLS - WOLFSSL_LOCAL int DtlsPoolInit(WOLFSSL*); - WOLFSSL_LOCAL int DtlsPoolSave(WOLFSSL*, const byte*, int); - WOLFSSL_LOCAL int DtlsPoolTimeout(WOLFSSL*); - WOLFSSL_LOCAL int DtlsPoolSend(WOLFSSL*); - WOLFSSL_LOCAL void DtlsPoolReset(WOLFSSL*); - WOLFSSL_LOCAL DtlsMsg* DtlsMsgNew(word32, void*); WOLFSSL_LOCAL void DtlsMsgDelete(DtlsMsg*, void*); WOLFSSL_LOCAL void DtlsMsgListDelete(DtlsMsg*, void*); - WOLFSSL_LOCAL void DtlsMsgSet(DtlsMsg*, word32, const byte*, byte, - word32, word32); + WOLFSSL_LOCAL int DtlsMsgSet(DtlsMsg*, word32, const byte*, byte, + word32, word32, void*); WOLFSSL_LOCAL DtlsMsg* DtlsMsgFind(DtlsMsg*, word32); - WOLFSSL_LOCAL DtlsMsg* DtlsMsgStore(DtlsMsg*, word32, const byte*, word32, + WOLFSSL_LOCAL void DtlsMsgStore(WOLFSSL*, word32, const byte*, word32, byte, word32, word32, void*); WOLFSSL_LOCAL DtlsMsg* DtlsMsgInsert(DtlsMsg*, DtlsMsg*); + + WOLFSSL_LOCAL int DtlsMsgPoolSave(WOLFSSL*, const byte*, word32); + WOLFSSL_LOCAL int DtlsMsgPoolTimeout(WOLFSSL*); + WOLFSSL_LOCAL int VerifyForDtlsMsgPoolSend(WOLFSSL*, byte, word32); + WOLFSSL_LOCAL void DtlsMsgPoolReset(WOLFSSL*); + WOLFSSL_LOCAL int DtlsMsgPoolSend(WOLFSSL*, int); #endif /* WOLFSSL_DTLS */ #ifndef NO_TLS - + #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); -WOLFSSL_LOCAL void InitX509Name(WOLFSSL_X509_NAME*, int); -WOLFSSL_LOCAL void FreeX509Name(WOLFSSL_X509_NAME* name); -WOLFSSL_LOCAL void InitX509(WOLFSSL_X509*, int); -WOLFSSL_LOCAL void FreeX509(WOLFSSL_X509*); #ifndef NO_CERTS + WOLFSSL_LOCAL void InitX509Name(WOLFSSL_X509_NAME*, int); + WOLFSSL_LOCAL void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap); + WOLFSSL_LOCAL void InitX509(WOLFSSL_X509*, int, void* heap); + WOLFSSL_LOCAL void FreeX509(WOLFSSL_X509*); WOLFSSL_LOCAL int CopyDecodedToX509(WOLFSSL_X509*, DecodedCert*); #endif -/* used by ssl.c and wolfssl_int.c */ -WOLFSSL_LOCAL void c32to24(word32 in, word24 out); +#ifndef MAX_CIPHER_NAME +#define MAX_CIPHER_NAME 50 +#endif -WOLFSSL_LOCAL const char* const* GetCipherNames(void); +#ifdef WOLFSSL_NAMES_STATIC +typedef char cipher_name[MAX_CIPHER_NAME]; +#else +typedef const char* cipher_name; +#endif + +typedef struct CipherSuiteInfo { + cipher_name name; +#ifndef NO_ERROR_STRINGS + cipher_name name_iana; +#endif + byte cipherSuite0; + byte cipherSuite; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + byte minor; + byte major; +#endif +} CipherSuiteInfo; + +WOLFSSL_LOCAL const CipherSuiteInfo* GetCipherNames(void); WOLFSSL_LOCAL int GetCipherNamesSize(void); - +WOLFSSL_LOCAL const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite); +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +/* used in wolfSSL_sk_CIPHER_description */ +#define MAX_SEGMENTS 5 +#define MAX_SEGMENT_SZ 20 +WOLFSSL_LOCAL int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER*); +WOLFSSL_LOCAL const char* GetCipherProtocol(const byte minor); +WOLFSSL_LOCAL const char* GetCipherKeaStr(char n[][MAX_SEGMENT_SZ]); +WOLFSSL_LOCAL const char* GetCipherAuthStr(char n[][MAX_SEGMENT_SZ]); +WOLFSSL_LOCAL const char* GetCipherEncStr(char n[][MAX_SEGMENT_SZ]); +WOLFSSL_LOCAL const char* GetCipherMacStr(char n[][MAX_SEGMENT_SZ]); +WOLFSSL_LOCAL int SetCipherBits(const char* enc); +#endif +WOLFSSL_LOCAL const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite); +WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl); +WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl); +WOLFSSL_LOCAL int GetCipherSuiteFromName(const char* name, byte* cipherSuite0, + byte* cipherSuite); enum encrypt_side { ENCRYPT_SIDE_ONLY = 1, @@ -2504,10 +4559,55 @@ enum encrypt_side { WOLFSSL_LOCAL int SetKeysSide(WOLFSSL*, enum encrypt_side); +/* Set*Internal and Set*External functions */ +WOLFSSL_LOCAL int SetDsaInternal(WOLFSSL_DSA* dsa); +WOLFSSL_LOCAL int SetDsaExternal(WOLFSSL_DSA* dsa); +#ifndef HAVE_USER_RSA +WOLFSSL_LOCAL int SetRsaExternal(WOLFSSL_RSA* rsa); +WOLFSSL_LOCAL int SetRsaInternal(WOLFSSL_RSA* rsa); +#endif +WOLFSSL_LOCAL int SetDhInternal(WOLFSSL_DH* dh); +WOLFSSL_LOCAL int SetDhExternal(WOLFSSL_DH *dh); + +#ifndef NO_DH + WOLFSSL_LOCAL int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, + 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 /* !NO_DH */ + +#ifdef HAVE_ECC + WOLFSSL_LOCAL int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer); + WOLFSSL_LOCAL word16 GetCurveByOID(int oidSum); +#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 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" */ #endif #endif /* wolfSSL_INT_H */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/ocsp.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/ocsp.h index 77a4157ee..5159d4c43 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/ocsp.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/ocsp.h @@ -1,8 +1,8 @@ /* ocsp.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* wolfSSL OCSP API */ #ifndef WOLFSSL_OCSP_H @@ -36,10 +37,90 @@ typedef struct WOLFSSL_OCSP WOLFSSL_OCSP; +#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(WOLFSSL_NGINX) ||\ + defined(WOLFSSL_HAPROXY) +typedef struct OcspResponse WOLFSSL_OCSP_BASICRESP; + +typedef struct OcspRequest WOLFSSL_OCSP_CERTID; + +typedef struct OcspRequest WOLFSSL_OCSP_ONEREQ; + +typedef struct OcspRequest WOLFSSL_OCSP_REQUEST; +#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_LOCAL int CheckCertOCSP(WOLFSSL_OCSP*, DecodedCert*, + 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); +WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz, + WOLFSSL_BUFFER_INFO *responseBuffer, CertStatus *status, + OcspEntry *entry, OcspRequest *ocspRequest); + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_APACHE_HTTPD) + + 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); +WOLFSSL_API WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_CERTID_dup(WOLFSSL_OCSP_CERTID*); +WOLFSSL_API int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out, + WOLFSSL_OCSP_REQUEST *req); + +#endif +#ifdef OPENSSL_EXTRA +WOLFSSL_API int wolfSSL_OCSP_REQUEST_add_ext(OcspRequest* req, + WOLFSSL_X509_EXTENSION* ext, int idx); +WOLFSSL_API OcspResponse* wolfSSL_OCSP_response_create(int status, + WOLFSSL_OCSP_BASICRESP* bs); +WOLFSSL_API const char* wolfSSL_OCSP_crl_reason_str(long s); + +WOLFSSL_API int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING**, + WOLFSSL_ASN1_OBJECT**, WOLFSSL_ASN1_STRING**, + WOLFSSL_ASN1_INTEGER**, WOLFSSL_OCSP_CERTID*); + +WOLFSSL_API int wolfSSL_OCSP_request_add1_nonce(OcspRequest* req, + unsigned char* val, int sz); +WOLFSSL_API int wolfSSL_OCSP_check_nonce(OcspRequest* req, + WOLFSSL_OCSP_BASICRESP* bs); +#endif + #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/aes.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/aes.h new file mode 100644 index 000000000..de9f5b897 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/aes.h @@ -0,0 +1,111 @@ +/* aes.h + * + * Copyright (C) 2006-2020 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 + */ + + + +/* aes.h defines mini des openssl compatibility layer + * + */ + + +#ifndef WOLFSSL_AES_H_ +#define WOLFSSL_AES_H_ + +#include + +#ifndef NO_AES +#include /* for size_t */ + +#ifdef __cplusplus + extern "C" { +#endif + +/* This structure wrapper is done because there is no aes_new function with + * OpenSSL compatibility layer. This makes code working with an AES structure + * to need the size of the structure. */ +typedef struct WOLFSSL_AES_KEY { + /* aligned and big enough for Aes from wolfssl/wolfcrypt/aes.h */ + ALIGN16 void* holder[(376 + WC_ASYNC_DEV_SIZE)/ sizeof(void*)]; + #ifdef GCM_TABLE + /* key-based fast multiplication table. */ + ALIGN16 void* M0[4096 / sizeof(void*)]; + #endif /* GCM_TABLE */ + #if defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC)) + /* large enough for additional devcrypto information */ + void* devKey[288 / sizeof(void*)]; + #endif + #ifdef WOLFSSL_AFALG + void* afalg_holder[288 / sizeof(void*)]; + #endif + #ifdef HAVE_PKCS11 + void* pkcs11_holder[(AES_MAX_ID_LEN + sizeof(int)) / sizeof(void*)]; + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + void* async_holder[128 / sizeof(void*)]; + #endif +} WOLFSSL_AES_KEY; +typedef WOLFSSL_AES_KEY AES_KEY; + +WOLFSSL_API int wolfSSL_AES_set_encrypt_key + (const unsigned char *, const int bits, AES_KEY *); +WOLFSSL_API int wolfSSL_AES_set_decrypt_key + (const unsigned char *, const int bits, AES_KEY *); +WOLFSSL_API void wolfSSL_AES_cbc_encrypt + (const unsigned char *in, unsigned char* out, size_t len, + AES_KEY *key, unsigned char* iv, const int enc); +WOLFSSL_API void wolfSSL_AES_ecb_encrypt + (const unsigned char *in, unsigned char* out, + AES_KEY *key, const int enc); +WOLFSSL_API void wolfSSL_AES_cfb128_encrypt + (const unsigned char *in, unsigned char* out, size_t len, + AES_KEY *key, unsigned char* iv, int* num, const int enc); + +#define AES_cbc_encrypt wolfSSL_AES_cbc_encrypt +#define AES_ecb_encrypt wolfSSL_AES_ecb_encrypt +#define AES_cfb128_encrypt wolfSSL_AES_cfb128_encrypt +#define AES_set_encrypt_key wolfSSL_AES_set_encrypt_key +#define AES_set_decrypt_key wolfSSL_AES_set_decrypt_key + +#ifdef WOLFSSL_AES_DIRECT +WOLFSSL_API void wolfSSL_AES_encrypt + (const unsigned char* input, unsigned char* output, AES_KEY *); +WOLFSSL_API void wolfSSL_AES_decrypt + (const unsigned char* input, unsigned char* output, AES_KEY *); + +#define AES_encrypt wolfSSL_AES_encrypt +#define AES_decrypt wolfSSL_AES_decrypt +#endif /* HAVE_AES_DIRECT */ + +#ifndef AES_ENCRYPT +#define AES_ENCRYPT AES_ENCRYPTION +#endif +#ifndef AES_DECRYPT +#define AES_DECRYPT AES_DECRYPTION +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_AES */ + +#endif /* WOLFSSL_AES_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/asn1.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/asn1.h index 3f34d7d2c..0566ceb2b 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/asn1.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/asn1.h @@ -1,2 +1,152 @@ +/* asn1.h + * + * Copyright (C) 2006-2020 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 + */ + /* asn1.h for openssl */ +#ifndef WOLFSSL_ASN1_H_ +#define WOLFSSL_ASN1_H_ + +#include + +#define ASN1_STRING_new wolfSSL_ASN1_STRING_new +#define ASN1_STRING_type_new wolfSSL_ASN1_STRING_type_new +#define ASN1_STRING_type wolfSSL_ASN1_STRING_type +#define ASN1_STRING_set wolfSSL_ASN1_STRING_set +#define ASN1_STRING_free wolfSSL_ASN1_STRING_free + +#define V_ASN1_INTEGER 0x02 +#define V_ASN1_OCTET_STRING 0x04 /* tag for ASN1_OCTET_STRING */ +#define V_ASN1_NEG 0x100 +#define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG) +#define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG) + +/* Type for ASN1_print_ex */ +# define ASN1_STRFLGS_ESC_2253 1 +# define ASN1_STRFLGS_ESC_CTRL 2 +# define ASN1_STRFLGS_ESC_MSB 4 +# define ASN1_STRFLGS_ESC_QUOTE 8 +# define ASN1_STRFLGS_UTF8_CONVERT 0x10 +# define ASN1_STRFLGS_IGNORE_TYPE 0x20 +# define ASN1_STRFLGS_SHOW_TYPE 0x40 +# define ASN1_STRFLGS_DUMP_ALL 0x80 +# define ASN1_STRFLGS_DUMP_UNKNOWN 0x100 +# define ASN1_STRFLGS_DUMP_DER 0x200 +# define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \ + ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + ASN1_STRFLGS_UTF8_CONVERT | \ + ASN1_STRFLGS_DUMP_UNKNOWN | \ + ASN1_STRFLGS_DUMP_DER) + +#define MBSTRING_UTF8 0x1000 +#define MBSTRING_ASC 0x1001 +#define MBSTRING_BMP 0x1002 +#define MBSTRING_UNIV 0x1004 + +#define ASN1_UTCTIME_print wolfSSL_ASN1_UTCTIME_print +#define ASN1_TIME_check wolfSSL_ASN1_TIME_check +#define ASN1_TIME_diff wolfSSL_ASN1_TIME_diff +#define ASN1_TIME_set wolfSSL_ASN1_TIME_set + +#define V_ASN1_OBJECT 6 +#define V_ASN1_UTCTIME 23 +#define V_ASN1_GENERALIZEDTIME 24 + +#define ASN1_STRING_FLAG_BITS_LEFT 0x008 +#define ASN1_STRING_FLAG_NDEF 0x010 +#define ASN1_STRING_FLAG_CONT 0x020 +#define ASN1_STRING_FLAG_MSTRING 0x040 +#define ASN1_STRING_FLAG_EMBED 0x080 + + +WOLFSSL_API WOLFSSL_ASN1_INTEGER *wolfSSL_BN_to_ASN1_INTEGER( + const WOLFSSL_BIGNUM*, WOLFSSL_ASN1_INTEGER*); + +WOLFSSL_API void wolfSSL_ASN1_TYPE_set(WOLFSSL_ASN1_TYPE *a, int type, void *value); + +#ifdef OPENSSL_ALL +/* IMPLEMENT_ASN1_FUNCTIONS is strictly for external use only. Internally + * we don't use this. Some projects use OpenSSL to implement ASN1 types and + * this section is only to provide those projects with ASN1 functionality. */ +typedef struct { + size_t offset; /* Offset of this field in structure */ + byte type; /* The type of the member as defined in + * WOLFSSL_ASN1_TYPES */ +} WOLFSSL_ASN1_TEMPLATE; + +typedef struct { + byte type; /* One of the ASN_Tags types */ + const WOLFSSL_ASN1_TEMPLATE *members; /* If SEQUENCE or CHOICE this + * contains the contents */ + size_t mcount; /* Number of members if SEQUENCE + * or CHOICE */ + size_t size; /* Structure size */ +} WOLFSSL_ASN1_ITEM; + +typedef enum { + WOLFSSL_X509_ALGOR_ASN1 = 0, + WOLFSSL_ASN1_BIT_STRING_ASN1, +} WOLFSSL_ASN1_TYPES; + +#define ASN1_SEQUENCE(type) \ + static const type __##type##_dummy_struct;\ + static const WOLFSSL_ASN1_TEMPLATE type##_member_data[] + +#define ASN1_SIMPLE(type, member, member_type) \ + { (char*)&__##type##_dummy_struct.member - (char*)&__##type##_dummy_struct, \ + WOLFSSL_##member_type##_ASN1 } + +#define ASN1_SEQUENCE_END(type) \ + ; \ + const WOLFSSL_ASN1_ITEM type##_template_data = { \ + ASN_SEQUENCE, \ + type##_member_data, \ + sizeof(type##_member_data) / sizeof(WOLFSSL_ASN1_TEMPLATE), \ + sizeof(type) \ + }; + +WOLFSSL_API void *wolfSSL_ASN1_item_new(const WOLFSSL_ASN1_ITEM *template); +WOLFSSL_API void wolfSSL_ASN1_item_free(void *val, const WOLFSSL_ASN1_ITEM *template); +WOLFSSL_API int wolfSSL_ASN1_item_i2d(const void *src, byte **dest, + const WOLFSSL_ASN1_ITEM *template); + +/* Need function declaration otherwise compiler complains */ +#define IMPLEMENT_ASN1_FUNCTIONS(type) \ + type *type##_new(void); \ + type *type##_new(void){ \ + return (type*)wolfSSL_ASN1_item_new(&type##_template_data); \ + } \ + void type##_free(type *t); \ + void type##_free(type *t){ \ + wolfSSL_ASN1_item_free(t, &type##_template_data); \ + } \ + int i2d_##type(type *src, byte **dest); \ + int i2d_##type(type *src, byte **dest) \ + { \ + return wolfSSL_ASN1_item_i2d(src, dest, &type##_template_data);\ + } + +#endif /* OPENSSL_ALL */ + +#define BN_to_ASN1_INTEGER wolfSSL_BN_to_ASN1_INTEGER +#define ASN1_TYPE_set wolfSSL_ASN1_TYPE_set + +#endif /* WOLFSSL_ASN1_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/asn1t.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/asn1t.h new file mode 100644 index 000000000..0ee58a2d5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/asn1t.h @@ -0,0 +1,30 @@ +/* asn1t.h + * + * Copyright (C) 2006-2020 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 + */ + +/* asn1t.h for openssl */ + +#ifndef WOLFSSL_ASN1T_H_ +#define WOLFSSL_ASN1T_H_ + +#include +#include + +#endif /* WOLFSSL_ASN1T_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/bio.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/bio.h index 5f1d4211d..1eb55b149 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/bio.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/bio.h @@ -1,3 +1,24 @@ +/* bio.h + * + * Copyright (C) 2006-2020 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 + */ + /* bio.h for openssl */ @@ -12,10 +33,130 @@ #endif +#define BIO_FLAG_BASE64_NO_NL WOLFSSL_BIO_FLAG_BASE64_NO_NL +#define BIO_FLAG_READ WOLFSSL_BIO_FLAG_READ +#define BIO_FLAG_WRITE WOLFSSL_BIO_FLAG_WRITE +#define BIO_FLAG_IO_SPECIAL WOLFSSL_BIO_FLAG_IO_SPECIAL +#define BIO_FLAG_RETRY WOLFSSL_BIO_FLAG_RETRY + +#define BIO_new_fp wolfSSL_BIO_new_fp +#define BIO_new_file wolfSSL_BIO_new_file +#define BIO_new_fp wolfSSL_BIO_new_fp +#define BIO_ctrl wolfSSL_BIO_ctrl +#define BIO_ctrl_pending wolfSSL_BIO_ctrl_pending +#define BIO_wpending wolfSSL_BIO_wpending +#define BIO_get_mem_ptr wolfSSL_BIO_get_mem_ptr +#define BIO_int_ctrl wolfSSL_BIO_int_ctrl +#define BIO_reset wolfSSL_BIO_reset +#define BIO_s_file wolfSSL_BIO_s_file +#define BIO_s_bio wolfSSL_BIO_s_bio +#define BIO_s_socket wolfSSL_BIO_s_socket +#define BIO_set_fd wolfSSL_BIO_set_fd +#define BIO_set_close wolfSSL_BIO_set_close +#define BIO_ctrl_reset_read_request wolfSSL_BIO_ctrl_reset_read_request +#define BIO_set_write_buf_size wolfSSL_BIO_set_write_buf_size +#define BIO_make_bio_pair wolfSSL_BIO_make_bio_pair + +#define BIO_set_fp wolfSSL_BIO_set_fp +#define BIO_get_fp wolfSSL_BIO_get_fp +#define BIO_seek wolfSSL_BIO_seek +#define BIO_write_filename wolfSSL_BIO_write_filename +#define BIO_set_mem_eof_return wolfSSL_BIO_set_mem_eof_return + +#define BIO_find_type wolfSSL_BIO_find_type +#define BIO_next wolfSSL_BIO_next +#define BIO_gets wolfSSL_BIO_gets +#define BIO_puts wolfSSL_BIO_puts + +#define BIO_should_retry wolfSSL_BIO_should_retry + +#define BIO_TYPE_FILE WOLFSSL_BIO_FILE +#define BIO_TYPE_BIO WOLFSSL_BIO_BIO +#define BIO_TYPE_MEM WOLFSSL_BIO_MEMORY +#define BIO_TYPE_BASE64 WOLFSSL_BIO_BASE64 + +#define BIO_vprintf wolfSSL_BIO_vprintf +#define BIO_printf wolfSSL_BIO_printf +#define BIO_dump wolfSSL_BIO_dump + +/* BIO info callback */ +#define BIO_CB_FREE WOLFSSL_BIO_CB_FREE +#define BIO_CB_READ WOLFSSL_BIO_CB_READ +#define BIO_CB_WRITE WOLFSSL_BIO_CB_WRITE +#define BIO_CB_PUTS WOLFSSL_BIO_CB_PUTS +#define BIO_CB_GETS WOLFSSL_BIO_CB_GETS +#define BIO_CB_CTRL WOLFSSL_BIO_CB_CTRL +#define BIO_CB_RETURN WOLFSSL_BIO_CB_RETURN + +#define BIO_set_callback wolfSSL_BIO_set_callback +#define BIO_get_callback wolfSSL_BIO_get_callback +#define BIO_set_callback_arg wolfSSL_BIO_set_callback_arg +#define BIO_get_callback_arg wolfSSL_BIO_get_callback_arg + +/* BIO for 1.1.0 or later */ +#define BIO_set_init wolfSSL_BIO_set_init +#define BIO_get_data wolfSSL_BIO_get_data +#define BIO_set_data wolfSSL_BIO_set_data +#define BIO_get_shutdown wolfSSL_BIO_get_shutdown +#define BIO_set_shutdown wolfSSL_BIO_set_shutdown + +#define BIO_clear_flags wolfSSL_BIO_clear_flags +#define BIO_set_ex_data wolfSSL_BIO_set_ex_data +#define BIO_get_ex_data wolfSSL_BIO_get_ex_data + +/* helper to set specific retry/read flags */ +#define BIO_set_retry_read(bio)\ + wolfSSL_BIO_set_flags((bio), WOLFSSL_BIO_FLAG_RETRY | WOLFSSL_BIO_FLAG_READ) +#define BIO_set_retry_write(bio)\ + wolfSSL_BIO_set_flags((bio), WOLFSSL_BIO_FLAG_RETRY | WOLFSSL_BIO_FLAG_WRITE) + +#define BIO_clear_retry_flags wolfSSL_BIO_clear_retry_flags + +#define BIO_meth_new wolfSSL_BIO_meth_new +#define BIO_meth_set_write wolfSSL_BIO_meth_set_write +#define BIO_meth_free wolfSSL_BIO_meth_free +#define BIO_meth_set_write wolfSSL_BIO_meth_set_write +#define BIO_meth_set_read wolfSSL_BIO_meth_set_read +#define BIO_meth_set_puts wolfSSL_BIO_meth_set_puts +#define BIO_meth_set_gets wolfSSL_BIO_meth_set_gets +#define BIO_meth_set_ctrl wolfSSL_BIO_meth_set_ctrl +#define BIO_meth_set_create wolfSSL_BIO_meth_set_create +#define BIO_meth_set_destroy wolfSSL_BIO_meth_set_destroy + + +/* BIO CTRL */ +#define BIO_CTRL_RESET 1 +#define BIO_CTRL_EOF 2 +#define BIO_CTRL_INFO 3 +#define BIO_CTRL_PUSH 6 +#define BIO_CTRL_POP 7 +#define BIO_CTRL_GET_CLOSE 8 +#define BIO_CTRL_SET_CLOSE 9 +#define BIO_CTRL_PENDING 10 +#define BIO_CTRL_FLUSH 11 +#define BIO_CTRL_DUP 12 +#define BIO_CTRL_WPENDING 13 + +#define BIO_C_SET_FILE_PTR 106 +#define BIO_C_GET_FILE_PTR 107 +#define BIO_C_SET_FILENAME 108 +#define BIO_C_SET_BUF_MEM 114 +#define BIO_C_GET_BUF_MEM_PTR 115 +#define BIO_C_FILE_SEEK 128 +#define BIO_C_SET_BUF_MEM_EOF_RETURN 130 +#define BIO_C_SET_WRITE_BUF_SIZE 136 +#define BIO_C_MAKE_BIO_PAIR 138 + +#define BIO_CTRL_DGRAM_QUERY_MTU 40 + +#define BIO_NOCLOSE 0x00 +#define BIO_CLOSE 0x01 + +#define BIO_FP_WRITE 0x04 #ifdef __cplusplus - } /* extern "C" */ + } /* extern "C" */ #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/bn.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/bn.h index 4d81eb1b3..312954d7c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/bn.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/bn.h @@ -1,38 +1,80 @@ +/* bn.h + * + * Copyright (C) 2006-2020 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 + */ + /* bn.h for openssl */ +/*! + \file wolfssl/openssl/bn.h + \brief bn.h for openssl +*/ + #ifndef WOLFSSL_BN_H_ #define WOLFSSL_BN_H_ #include +#include #ifdef __cplusplus extern "C" { #endif typedef struct WOLFSSL_BIGNUM { - int neg; /* openssh deference */ - void* internal; /* our big num */ + int neg; /* openssh deference */ + void *internal; /* our big num */ +#ifdef WOLFSSL_SP_MATH + sp_int fp; +#elif defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) + fp_int fp; +#endif } WOLFSSL_BIGNUM; -typedef struct WOLFSSL_BN_CTX WOLFSSL_BN_CTX; +#define BN_ULONG WOLFSSL_BN_ULONG +#define WOLFSSL_BN_ULONG mp_digit +typedef struct WOLFSSL_BN_CTX WOLFSSL_BN_CTX; +typedef struct WOLFSSL_BN_GENCB WOLFSSL_BN_GENCB; WOLFSSL_API WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void); WOLFSSL_API void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX*); WOLFSSL_API void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX*); WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_BN_new(void); +#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) +WOLFSSL_API void wolfSSL_BN_init(WOLFSSL_BIGNUM *); +#endif WOLFSSL_API void wolfSSL_BN_free(WOLFSSL_BIGNUM*); WOLFSSL_API void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM*); +WOLFSSL_API void wolfSSL_BN_clear(WOLFSSL_BIGNUM*); WOLFSSL_API int wolfSSL_BN_sub(WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*, - const WOLFSSL_BIGNUM*); + const WOLFSSL_BIGNUM*); WOLFSSL_API int wolfSSL_BN_mod(WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*, - const WOLFSSL_BIGNUM*, const WOLFSSL_BN_CTX*); - + const WOLFSSL_BIGNUM*, const WOLFSSL_BN_CTX*); +WOLFSSL_API int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx); +WOLFSSL_API int wolfSSL_BN_mod_mul(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx); WOLFSSL_API const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void); @@ -42,38 +84,69 @@ WOLFSSL_API int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM*); WOLFSSL_API int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM*); WOLFSSL_API int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM*); WOLFSSL_API int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM*); +WOLFSSL_API int wolfSSL_BN_is_negative(const WOLFSSL_BIGNUM*); +WOLFSSL_API int wolfSSL_BN_is_word(const WOLFSSL_BIGNUM*, WOLFSSL_BN_ULONG); WOLFSSL_API int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*); WOLFSSL_API int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM*, unsigned char*); WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char*, int len, - WOLFSSL_BIGNUM* ret); + WOLFSSL_BIGNUM* ret); WOLFSSL_API int wolfSSL_mask_bits(WOLFSSL_BIGNUM*, int n); +WOLFSSL_API int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM*, int bits, int top, + int bottom); WOLFSSL_API int wolfSSL_BN_rand(WOLFSSL_BIGNUM*, int bits, int top, int bottom); WOLFSSL_API int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM*, int n); WOLFSSL_API int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM**, const char* str); WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM*); -WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*); - -WOLFSSL_API int wolfSSL_BN_set_word(WOLFSSL_BIGNUM*, unsigned long w); +WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM*, + const WOLFSSL_BIGNUM*); WOLFSSL_API int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM**, const char* str); WOLFSSL_API char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM*); +WOLFSSL_API int wolfSSL_BN_lshift(WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*, int); +WOLFSSL_API int wolfSSL_BN_add_word(WOLFSSL_BIGNUM*, WOLFSSL_BN_ULONG); +WOLFSSL_API int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM*, int); +WOLFSSL_API int wolfSSL_BN_clear_bit(WOLFSSL_BIGNUM*, int); +WOLFSSL_API int wolfSSL_BN_set_word(WOLFSSL_BIGNUM*, WOLFSSL_BN_ULONG); +WOLFSSL_API unsigned long wolfSSL_BN_get_word(const WOLFSSL_BIGNUM*); + +WOLFSSL_API int wolfSSL_BN_add(WOLFSSL_BIGNUM*, WOLFSSL_BIGNUM*, + WOLFSSL_BIGNUM*); +WOLFSSL_API int wolfSSL_BN_mod_add(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *b, const WOLFSSL_BIGNUM *m, + WOLFSSL_BN_CTX *ctx); +WOLFSSL_API char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM*); +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); +#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) + WOLFSSL_API int wolfSSL_BN_print_fp(XFILE, 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; #define BN_CTX_new wolfSSL_BN_CTX_new #define BN_CTX_init wolfSSL_BN_CTX_init #define BN_CTX_free wolfSSL_BN_CTX_free #define BN_new wolfSSL_BN_new +#define BN_init wolfSSL_BN_init #define BN_free wolfSSL_BN_free #define BN_clear_free wolfSSL_BN_clear_free +#define BN_clear wolfSSL_BN_clear #define BN_num_bytes wolfSSL_BN_num_bytes #define BN_num_bits wolfSSL_BN_num_bits @@ -81,6 +154,8 @@ typedef WOLFSSL_BN_CTX BN_CTX; #define BN_is_zero wolfSSL_BN_is_zero #define BN_is_one wolfSSL_BN_is_one #define BN_is_odd wolfSSL_BN_is_odd +#define BN_is_negative wolfSSL_BN_is_negative +#define BN_is_word wolfSSL_BN_is_word #define BN_cmp wolfSSL_BN_cmp @@ -88,28 +163,64 @@ typedef WOLFSSL_BN_CTX BN_CTX; #define BN_bin2bn wolfSSL_BN_bin2bn #define BN_mod wolfSSL_BN_mod +#define BN_mod_exp wolfSSL_BN_mod_exp +#define BN_mod_mul wolfSSL_BN_mod_mul #define BN_sub wolfSSL_BN_sub #define BN_value_one wolfSSL_BN_value_one #define BN_mask_bits wolfSSL_mask_bits -#define BN_rand wolfSSL_BN_rand -#define BN_is_bit_set wolfSSL_BN_is_bit_set -#define BN_hex2bn wolfSSL_BN_hex2bn +#define BN_pseudo_rand wolfSSL_BN_pseudo_rand +#define BN_rand wolfSSL_BN_rand +#define BN_is_bit_set wolfSSL_BN_is_bit_set +#define BN_hex2bn wolfSSL_BN_hex2bn #define BN_dup wolfSSL_BN_dup #define BN_copy wolfSSL_BN_copy +#define BN_get_word wolfSSL_BN_get_word #define BN_set_word wolfSSL_BN_set_word #define BN_dec2bn wolfSSL_BN_dec2bn #define BN_bn2dec wolfSSL_BN_bn2dec +#define BN_bn2hex wolfSSL_BN_bn2hex + +#define BN_lshift wolfSSL_BN_lshift +#define BN_add_word wolfSSL_BN_add_word +#define BN_add wolfSSL_BN_add +#define BN_mod_add wolfSSL_BN_mod_add +#define BN_set_word wolfSSL_BN_set_word +#define BN_set_bit wolfSSL_BN_set_bit +#define BN_clear_bit wolfSSL_BN_clear_bit + + +#define BN_is_prime_ex wolfSSL_BN_is_prime_ex +#define BN_print_fp wolfSSL_BN_print_fp +#define BN_rshift wolfSSL_BN_rshift +#define BN_mod_word wolfSSL_BN_mod_word + +#define BN_CTX_get wolfSSL_BN_CTX_get +#define BN_CTX_start wolfSSL_BN_CTX_start + +#define BN_mod_inverse wolfSSL_BN_mod_inverse + +#define BN_set_flags(x1, x2) + +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +#define BN_get_rfc2409_prime_768 wolfSSL_DH_768_prime +#define BN_get_rfc2409_prime_1024 wolfSSL_DH_1024_prime +#define BN_get_rfc3526_prime_1536 wolfSSL_DH_1536_prime +#define BN_get_rfc3526_prime_2048 wolfSSL_DH_2048_prime +#define BN_get_rfc3526_prime_3072 wolfSSL_DH_3072_prime +#define BN_get_rfc3526_prime_4096 wolfSSL_DH_4096_prime +#define BN_get_rfc3526_prime_6144 wolfSSL_DH_6144_prime +#define BN_get_rfc3526_prime_8192 wolfSSL_DH_8192_prime +#endif #ifdef __cplusplus - } /* extern "C" */ + } /* extern "C" */ #endif #endif /* WOLFSSL__H_ */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/buffer.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/buffer.h new file mode 100644 index 000000000..8e0a73000 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/buffer.h @@ -0,0 +1,47 @@ +/* buffer.h + * + * Copyright (C) 2006-2020 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_BUFFER_H_ +#define WOLFSSL_BUFFER_H_ + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + +WOLFSSL_API WOLFSSL_BUF_MEM* wolfSSL_BUF_MEM_new(void); +WOLFSSL_API int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len); +WOLFSSL_API void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf); + + +#define BUF_MEM_new wolfSSL_BUF_MEM_new +#define BUF_MEM_grow wolfSSL_BUF_MEM_grow +#define BUF_MEM_free wolfSSL_BUF_MEM_free + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_BUFFER_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/conf.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/conf.h index 1e328cf47..373239ff6 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/conf.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/conf.h @@ -1,2 +1,48 @@ -/* conf.h for openssl */ +/* conf.h + * + * Copyright (C) 2006-2020 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 + */ +/* conf.h for openSSL */ + +#ifndef WOLFSSL_conf_H_ +#define WOLFSSL_conf_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +struct WOLFSSL_CONF_VALUE { + char *section; + char *name; + char *value; +}; + +struct WOLFSSL_INIT_SETTINGS { + char* appname; +}; + +typedef struct WOLFSSL_CONF_VALUE CONF_VALUE; +typedef struct WOLFSSL_INIT_SETTINGS OPENSSL_INIT_SETTINGS; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* WOLFSSL_conf_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/crypto.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/crypto.h index 8f7c6f40e..fe2bb7d94 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/crypto.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/crypto.h @@ -1,8 +1,30 @@ +/* crypto.h + * + * Copyright (C) 2006-2020 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 + */ + /* crypto.h for openSSL */ #ifndef WOLFSSL_CRYPTO_H_ #define WOLFSSL_CRYPTO_H_ +#include #include @@ -13,14 +35,57 @@ WOLFSSL_API const char* wolfSSLeay_version(int type); WOLFSSL_API unsigned long wolfSSLeay(void); +WOLFSSL_API unsigned long wolfSSL_OpenSSL_version_num(void); + +#ifdef OPENSSL_EXTRA +WOLFSSL_API void wolfSSL_OPENSSL_free(void*); +WOLFSSL_API void *wolfSSL_OPENSSL_malloc(size_t a); +#endif + +#define CRYPTO_THREADID void #define SSLeay_version wolfSSLeay_version #define SSLeay wolfSSLeay +#define OpenSSL_version_num wolfSSL_OpenSSL_version_num - -#define SSLEAY_VERSION 0x0090600fL +#ifdef WOLFSSL_QT + #define SSLEAY_VERSION 0x10001000L +#else + #define SSLEAY_VERSION 0x0090600fL +#endif #define SSLEAY_VERSION_NUMBER SSLEAY_VERSION +#define CRYPTO_lock wc_LockMutex_ex +/* this function was used to set the default malloc, free, and realloc */ +#define CRYPTO_malloc_init() 0 /* CRYPTO_malloc_init is not needed */ + +#define OPENSSL_free wolfSSL_OPENSSL_free +#define OPENSSL_malloc wolfSSL_OPENSSL_malloc + +#ifdef WOLFSSL_QT + #define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L + #define OPENSSL_INIT_ADD_ALL_DIGESTS 0x00000008L + #define OPENSSL_INIT_LOAD_CONFIG 0x00000040L +#endif + +#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) +#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 +typedef struct CRYPTO_EX_DATA CRYPTO_EX_DATA; +typedef void (CRYPTO_free_func)(void*parent, void*ptr, CRYPTO_EX_DATA *ad, int idx, + long argl, void* argp); +#define CRYPTO_THREADID_set_callback wolfSSL_THREADID_set_callback +#define CRYPTO_THREADID_set_numeric wolfSSL_THREADID_set_numeric + +#define CRYPTO_r_lock wc_LockMutex_ex +#define CRYPTO_unlock wc_LockMutex_ex + +#define CRYPTO_THREAD_lock wc_LockMutex +#define CRYPTO_THREAD_r_lock wc_LockMutex +#define CRYPTO_THREAD_unlock wc_UnLockMutex + +#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ #endif /* header */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/des.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/des.h index f5b4f2a84..14d12ec3c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/des.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/des.h @@ -1,8 +1,8 @@ /* des.h * - * Copyright (C) 2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as wolfSSL) + * 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 @@ -16,11 +16,12 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* des.h defines mini des openssl compatibility layer + +/* des.h defines mini des openssl compatibility layer * */ @@ -44,6 +45,7 @@ typedef unsigned char WOLFSSL_DES_cblock[8]; typedef /* const */ WOLFSSL_DES_cblock WOLFSSL_const_DES_cblock; typedef WOLFSSL_DES_cblock WOLFSSL_DES_key_schedule; +typedef unsigned int WOLFSSL_DES_LONG; enum { @@ -52,6 +54,14 @@ enum { }; +WOLFSSL_API int wolfSSL_DES_is_weak_key(WOLFSSL_const_DES_cblock* key); +WOLFSSL_API WOLFSSL_DES_LONG wolfSSL_DES_cbc_cksum(const unsigned char* in, + WOLFSSL_DES_cblock* out, long length, WOLFSSL_DES_key_schedule* sc, + WOLFSSL_const_DES_cblock* iv); +WOLFSSL_API int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes, + WOLFSSL_DES_key_schedule* key); +WOLFSSL_API int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, + WOLFSSL_DES_key_schedule* key); WOLFSSL_API void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock*, WOLFSSL_DES_key_schedule*); WOLFSSL_API int wolfSSL_DES_key_sched(WOLFSSL_const_DES_cblock* key, @@ -60,6 +70,12 @@ WOLFSSL_API void wolfSSL_DES_cbc_encrypt(const unsigned char* input, unsigned char* output, long length, WOLFSSL_DES_key_schedule* schedule, WOLFSSL_DES_cblock* ivec, int enc); +WOLFSSL_API void wolfSSL_DES_ede3_cbc_encrypt(const unsigned char* input, + unsigned char* output, long sz, + WOLFSSL_DES_key_schedule* ks1, + WOLFSSL_DES_key_schedule* ks2, + WOLFSSL_DES_key_schedule* ks3, + WOLFSSL_DES_cblock* ivec, int enc); WOLFSSL_API void wolfSSL_DES_ncbc_encrypt(const unsigned char* input, unsigned char* output, long length, WOLFSSL_DES_key_schedule* schedule, @@ -68,34 +84,27 @@ WOLFSSL_API void wolfSSL_DES_ncbc_encrypt(const unsigned char* input, WOLFSSL_API void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock*); WOLFSSL_API void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock*, WOLFSSL_DES_cblock*, WOLFSSL_DES_key_schedule*, int); +WOLFSSL_API int wolfSSL_DES_check_key_parity(WOLFSSL_DES_cblock*); typedef WOLFSSL_DES_cblock DES_cblock; typedef WOLFSSL_const_DES_cblock const_DES_cblock; typedef WOLFSSL_DES_key_schedule DES_key_schedule; +typedef WOLFSSL_DES_LONG DES_LONG; +#define DES_check_key(x) /* Define WOLFSSL_CHECK_DESKEY to check key */ +#define DES_is_weak_key wolfSSL_DES_is_weak_key +#define DES_set_key wolfSSL_DES_set_key +#define DES_set_key_checked wolfSSL_DES_set_key_checked #define DES_set_key_unchecked wolfSSL_DES_set_key_unchecked -#define DES_key_sched wolfSSL_DES_key_sched -#define DES_cbc_encrypt wolfSSL_DES_cbc_encrypt -#define DES_ncbc_encrypt wolfSSL_DES_ncbc_encrypt -#define DES_set_odd_parity wolfSSL_DES_set_odd_parity -#define DES_ecb_encrypt wolfSSL_DES_ecb_encrypt -#define DES_ede3_cbc_encrypt(input, output, sz, ks1, ks2, ks3, ivec, enc) \ -do { \ - Des3 des; \ - byte key[24];/* EDE uses 24 size key */ \ - memcpy(key, (ks1), DES_BLOCK_SIZE); \ - memcpy(&key[DES_BLOCK_SIZE], (ks2), DES_BLOCK_SIZE); \ - memcpy(&key[DES_BLOCK_SIZE * 2], (ks3), DES_BLOCK_SIZE); \ - if (enc) { \ - wc_Des3_SetKey(&des, key, (const byte*)(ivec), DES_ENCRYPTION); \ - wc_Des3_CbcEncrypt(&des, (output), (input), (sz)); \ - } \ - else { \ - wc_Des3_SetKey(&des, key, (const byte*)(ivec), DES_ENCRYPTION); \ - wc_Des3_CbcDecrypt(&des, (output), (input), (sz)); \ - } \ -} while(0) +#define DES_key_sched wolfSSL_DES_key_sched +#define DES_cbc_encrypt wolfSSL_DES_cbc_encrypt +#define DES_ncbc_encrypt wolfSSL_DES_ncbc_encrypt +#define DES_set_odd_parity wolfSSL_DES_set_odd_parity +#define DES_ecb_encrypt wolfSSL_DES_ecb_encrypt +#define DES_ede3_cbc_encrypt wolfSSL_DES_ede3_cbc_encrypt +#define DES_cbc_cksum wolfSSL_DES_cbc_cksum +#define DES_check_key_parity wolfSSL_DES_check_key_parity #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/dh.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/dh.h index 071abf70f..ff021ed8b 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/dh.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/dh.h @@ -1,52 +1,115 @@ +/* dh.h + * + * Copyright (C) 2006-2020 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 + */ + /* dh.h for openSSL */ #ifndef WOLFSSL_DH_H_ #define WOLFSSL_DH_H_ - -#include #include - #ifdef __cplusplus extern "C" { #endif +#ifndef WOLFSSL_DH_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_DH WOLFSSL_DH; +#define WOLFSSL_DH_TYPE_DEFINED +#endif +typedef WOLFSSL_DH DH; - -typedef struct WOLFSSL_DH { - WOLFSSL_BIGNUM* p; - WOLFSSL_BIGNUM* g; +struct WOLFSSL_DH { + WOLFSSL_BIGNUM* p; + WOLFSSL_BIGNUM* g; + WOLFSSL_BIGNUM* q; WOLFSSL_BIGNUM* pub_key; /* openssh deference g^x */ WOLFSSL_BIGNUM* priv_key; /* openssh deference x */ void* internal; /* our DH */ char inSet; /* internal set from external ? */ char exSet; /* external set from internal ? */ -} WOLFSSL_DH; - + /*added for lighttpd openssl compatibility, go back and add a getter in + * lighttpd src code. + */ + int length; +}; +WOLFSSL_API WOLFSSL_DH *wolfSSL_d2i_DHparams(WOLFSSL_DH **dh, + const unsigned char **pp, long length); +WOLFSSL_API int wolfSSL_i2d_DHparams(const WOLFSSL_DH *dh, unsigned char **out); WOLFSSL_API WOLFSSL_DH* wolfSSL_DH_new(void); -WOLFSSL_API void wolfSSL_DH_free(WOLFSSL_DH*); +WOLFSSL_API void wolfSSL_DH_free(WOLFSSL_DH*); +WOLFSSL_API int wolfSSL_DH_check(const WOLFSSL_DH *dh, int *codes); WOLFSSL_API int wolfSSL_DH_size(WOLFSSL_DH*); WOLFSSL_API int wolfSSL_DH_generate_key(WOLFSSL_DH*); WOLFSSL_API int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* pub, WOLFSSL_DH*); +WOLFSSL_API int wolfSSL_DH_LoadDer(WOLFSSL_DH*, const unsigned char*, int sz); +WOLFSSL_API int wolfSSL_DH_set0_pqg(WOLFSSL_DH*, WOLFSSL_BIGNUM*, + WOLFSSL_BIGNUM*, WOLFSSL_BIGNUM*); -typedef WOLFSSL_DH DH; - -#define DH_new wolfSSL_DH_new +#define DH_new wolfSSL_DH_new #define DH_free wolfSSL_DH_free +#define d2i_DHparams wolfSSL_d2i_DHparams +#define i2d_DHparams wolfSSL_i2d_DHparams +#define DH_check wolfSSL_DH_check + #define DH_size wolfSSL_DH_size #define DH_generate_key wolfSSL_DH_generate_key #define DH_compute_key wolfSSL_DH_compute_key +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +#define DH_set0_pqg wolfSSL_DH_set0_pqg +#endif +#define DH_bits(x) (BN_num_bits(x->p)) +#define DH_GENERATOR_2 2 +#define DH_CHECK_P_NOT_PRIME 0x01 +#define DH_CHECK_P_NOT_SAFE_PRIME 0x02 +#define DH_NOT_SUITABLE_GENERATOR 0x08 + +/* Temporary values for wolfSSL_DH_Check*/ +#define DH_CHECK_INVALID_Q_VALUE 0x10 +#define DH_CHECK_Q_NOT_PRIME 0x11 +/* end temp */ + +/* for pre 1.1.0 */ +#define get_rfc2409_prime_768 wolfSSL_DH_768_prime +#define get_rfc2409_prime_1024 wolfSSL_DH_1024_prime +#define get_rfc3526_prime_1536 wolfSSL_DH_1536_prime +#define get_rfc3526_prime_2048 wolfSSL_DH_2048_prime +#define get_rfc3526_prime_3072 wolfSSL_DH_3072_prime +#define get_rfc3526_prime_4096 wolfSSL_DH_4096_prime +#define get_rfc3526_prime_6144 wolfSSL_DH_6144_prime +#define get_rfc3526_prime_8192 wolfSSL_DH_8192_prime #ifdef __cplusplus - } /* extern "C" */ + } /* extern "C" */ #endif -#endif /* header */ +#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) +#define DH_generate_parameters wolfSSL_DH_generate_parameters +#define DH_generate_parameters_ex wolfSSL_DH_generate_parameters_ex +#endif /* OPENSSL_ALL || HAVE_STUNNEL */ + +#endif /* WOLFSSL_DH_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/dsa.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/dsa.h index 725567018..9267cf479 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/dsa.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/dsa.h @@ -1,26 +1,54 @@ +/* dsa.h + * + * Copyright (C) 2006-2020 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 + */ + /* dsa.h for openSSL */ #ifndef WOLFSSL_DSA_H_ #define WOLFSSL_DSA_H_ - -#include #include - #ifdef __cplusplus extern "C" { #endif +typedef struct WOLFSSL_DSA_SIG { + WOLFSSL_BIGNUM *r; + WOLFSSL_BIGNUM *s; +} WOLFSSL_DSA_SIG; +#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; - WOLFSSL_BIGNUM* g; - WOLFSSL_BIGNUM* pub_key; /* our y */ - WOLFSSL_BIGNUM* priv_key; /* our x */ + WOLFSSL_BIGNUM* p; + WOLFSSL_BIGNUM* q; + WOLFSSL_BIGNUM* g; + WOLFSSL_BIGNUM* pub_key; /* our y */ + WOLFSSL_BIGNUM* priv_key; /* our x */ void* internal; /* our Dsa Key */ char inSet; /* internal set from external ? */ char exSet; /* external set from internal ? */ @@ -28,23 +56,55 @@ struct WOLFSSL_DSA { WOLFSSL_API WOLFSSL_DSA* wolfSSL_DSA_new(void); -WOLFSSL_API void wolfSSL_DSA_free(WOLFSSL_DSA*); +WOLFSSL_API void wolfSSL_DSA_free(WOLFSSL_DSA*); WOLFSSL_API int wolfSSL_DSA_generate_key(WOLFSSL_DSA*); + +typedef void (*WOLFSSL_BN_CB)(int i, int j, void* exArg); +WOLFSSL_API WOLFSSL_DSA* wolfSSL_DSA_generate_parameters(int bits, + unsigned char* seed, int seedLen, int* counterRet, + unsigned long* hRet, WOLFSSL_BN_CB cb, void* CBArg); WOLFSSL_API int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA*, int bits, unsigned char* seed, int seedLen, int* counterRet, unsigned long* hRet, void* cb); WOLFSSL_API int wolfSSL_DSA_LoadDer(WOLFSSL_DSA*, const unsigned char*, int sz); -WOLFSSL_API int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, - WOLFSSL_DSA* dsa); + +WOLFSSL_API int wolfSSL_DSA_LoadDer_ex(WOLFSSL_DSA*, const unsigned char*, + int sz, int opt); + +WOLFSSL_API int wolfSSL_DSA_do_sign(const unsigned char* d, + unsigned char* sigRet, WOLFSSL_DSA* dsa); + +WOLFSSL_API int wolfSSL_DSA_do_verify(const unsigned char* d, + unsigned char* sig, + WOLFSSL_DSA* dsa, int *dsacheck); + +WOLFSSL_API WOLFSSL_DSA_SIG* wolfSSL_DSA_SIG_new(void); +WOLFSSL_API void wolfSSL_DSA_SIG_free(WOLFSSL_DSA_SIG *sig); +WOLFSSL_API WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest, + int outLen, WOLFSSL_DSA* dsa); +WOLFSSL_API int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len, + WOLFSSL_DSA_SIG* sig, WOLFSSL_DSA* dsa); + +#define WOLFSSL_DSA_LOAD_PRIVATE 1 +#define WOLFSSL_DSA_LOAD_PUBLIC 2 #define DSA_new wolfSSL_DSA_new #define DSA_free wolfSSL_DSA_free +#define DSA_LoadDer wolfSSL_DSA_LoadDer #define DSA_generate_key wolfSSL_DSA_generate_key +#define DSA_generate_parameters wolfSSL_DSA_generate_parameters #define DSA_generate_parameters_ex wolfSSL_DSA_generate_parameters_ex +#define DSA_SIG_new wolfSSL_DSA_SIG_new +#define DSA_SIG_free wolfSSL_DSA_SIG_free +#define DSA_do_sign wolfSSL_DSA_do_sign_ex +#define DSA_do_verify wolfSSL_DSA_do_verify_ex + + +#define DSA_SIG WOLFSSL_DSA_SIG #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ec.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ec.h index 5ffdaf6e5..1f11593fe 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ec.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ec.h @@ -1,2 +1,323 @@ +/* ec.h + * + * Copyright (C) 2006-2020 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 + */ + /* ec.h for openssl */ +#ifndef WOLFSSL_EC_H_ +#define WOLFSSL_EC_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Map OpenSSL NID value */ +enum { + POINT_CONVERSION_COMPRESSED = 2, + POINT_CONVERSION_UNCOMPRESSED = 4, + +#ifdef HAVE_ECC + /* Use OpenSSL NIDs. NIDs can be mapped to ecc_curve_id enum values by + calling NIDToEccEnum() in ssl.c */ + NID_X9_62_prime192v1 = 409, + NID_X9_62_prime192v2 = 410, + NID_X9_62_prime192v3 = 411, + NID_X9_62_prime239v1 = 412, + NID_X9_62_prime239v2 = 413, + NID_X9_62_prime239v3 = 414, + NID_X9_62_prime256v1 = 415, + NID_secp112r1 = 704, + NID_secp112r2 = 705, + NID_secp128r1 = 706, + NID_secp128r2 = 707, + NID_secp160r1 = 709, + NID_secp160r2 = 710, + NID_secp224r1 = 713, + NID_secp384r1 = 715, + NID_secp521r1 = 716, + NID_secp160k1 = 708, + NID_secp192k1 = 711, + NID_secp224k1 = 712, + NID_secp256k1 = 714, + NID_brainpoolP160r1 = 921, + NID_brainpoolP192r1 = 923, + NID_brainpoolP224r1 = 925, + NID_brainpoolP256r1 = 927, + NID_brainpoolP320r1 = 929, + NID_brainpoolP384r1 = 931, + NID_brainpoolP512r1 = 933, +#endif + + 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; +typedef struct WOLFSSL_EC_BUILTIN_CURVE WOLFSSL_EC_BUILTIN_CURVE; +/* WOLFSSL_EC_METHOD is just an alias of WOLFSSL_EC_GROUP for now */ +typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_METHOD; +#define WOLFSSL_EC_TYPE_DEFINED +#endif + +typedef WOLFSSL_EC_KEY EC_KEY; +typedef WOLFSSL_EC_GROUP EC_GROUP; +typedef WOLFSSL_EC_GROUP EC_METHOD; +typedef WOLFSSL_EC_POINT EC_POINT; +typedef WOLFSSL_EC_BUILTIN_CURVE EC_builtin_curve; + +struct WOLFSSL_EC_POINT { + WOLFSSL_BIGNUM *X; + WOLFSSL_BIGNUM *Y; + WOLFSSL_BIGNUM *Z; + + void* internal; /* our ECC point */ + char inSet; /* internal set from external ? */ + char exSet; /* external set from internal ? */ +}; + +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 { + WOLFSSL_EC_GROUP *group; + WOLFSSL_EC_POINT *pub_key; + WOLFSSL_BIGNUM *priv_key; + + void* internal; /* our ECC Key */ + char inSet; /* internal set from external ? */ + char exSet; /* external set from internal ? */ + char form; /* Either POINT_CONVERSION_UNCOMPRESSED or + * POINT_CONVERSION_COMPRESSED */ +}; + +struct WOLFSSL_EC_BUILTIN_CURVE { + int nid; + const char *comment; +}; + +#define WOLFSSL_EC_KEY_LOAD_PRIVATE 1 +#define WOLFSSL_EC_KEY_LOAD_PUBLIC 2 + +WOLFSSL_API +size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *r,size_t nitems); + +WOLFSSL_API +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src); + +WOLFSSL_API +int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *curve, + const WOLFSSL_EC_POINT *p, + unsigned char *out, unsigned int *len); +WOLFSSL_API +int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len, + const WOLFSSL_EC_GROUP *curve, WOLFSSL_EC_POINT *p); +WOLFSSL_API +size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *p, + char form, + byte *buf, size_t len, WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group, + WOLFSSL_EC_POINT *p, const unsigned char *buf, + size_t len, WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *in, unsigned char **out); +WOLFSSL_API +void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *eckey, char form); +WOLFSSL_API +WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *p, + char form, + WOLFSSL_BIGNUM *in, WOLFSSL_BN_CTX *ctx); + +WOLFSSL_API +int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, + const unsigned char* der, int derSz); +WOLFSSL_API +int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, + const unsigned char* der, int derSz, int opt); +WOLFSSL_API +void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key); +WOLFSSL_API +WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key); +WOLFSSL_API +const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key); +WOLFSSL_API +int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, + const WOLFSSL_BIGNUM *priv_key); +WOLFSSL_API +WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key); +WOLFSSL_API +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid); +WOLFSSL_API const char* wolfSSL_EC_curve_nid2nist(int nid); +WOLFSSL_API +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void); +WOLFSSL_API +int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group); +WOLFSSL_API +int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key); +WOLFSSL_API +void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag); +WOLFSSL_API +int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, + const WOLFSSL_EC_POINT *pub); +WOLFSSL_API int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key); +WOLFSSL_API int wolfSSL_ECDSA_sign(int type, const unsigned char *digest, + int digestSz, unsigned char *sig, + unsigned int *sigSz, WOLFSSL_EC_KEY *key); +WOLFSSL_API +void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag); +WOLFSSL_API +WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid); +WOLFSSL_API +int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b, + WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group); +WOLFSSL_API +int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group); +WOLFSSL_API +int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group, + WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group); +WOLFSSL_API +void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group); +WOLFSSL_API +const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of( + const WOLFSSL_EC_GROUP *group); +WOLFSSL_API +int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth); +WOLFSSL_API +WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group); +WOLFSSL_API +int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *p, + WOLFSSL_BIGNUM *x, + WOLFSSL_BIGNUM *y, + WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +int wolfSSL_EC_POINT_set_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, + WOLFSSL_EC_POINT *point, + const WOLFSSL_BIGNUM *x, + const WOLFSSL_BIGNUM *y, + WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, + const WOLFSSL_BIGNUM *n, + const WOLFSSL_EC_POINT *q, const WOLFSSL_BIGNUM *m, + WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *point); +WOLFSSL_API +int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, + WOLFSSL_BN_CTX *ctx); +WOLFSSL_API int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, + const WOLFSSL_EC_POINT *src); +WOLFSSL_API +void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *point); +WOLFSSL_API +int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *a); + +#ifndef HAVE_SELFTEST +WOLFSSL_API +char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, + const WOLFSSL_EC_POINT* point, int form, + WOLFSSL_BN_CTX* ctx); +#endif + +#ifndef HAVE_ECC +#define OPENSSL_NO_EC +#endif + +#define EC_KEY_new wolfSSL_EC_KEY_new +#define EC_KEY_free wolfSSL_EC_KEY_free +#define EC_KEY_dup wolfSSL_EC_KEY_dup +#define EC_KEY_get0_public_key wolfSSL_EC_KEY_get0_public_key +#define EC_KEY_get0_group wolfSSL_EC_KEY_get0_group +#define EC_KEY_set_private_key wolfSSL_EC_KEY_set_private_key +#define EC_KEY_get0_private_key wolfSSL_EC_KEY_get0_private_key +#define EC_KEY_new_by_curve_name wolfSSL_EC_KEY_new_by_curve_name +#define EC_KEY_set_group wolfSSL_EC_KEY_set_group +#define EC_KEY_generate_key wolfSSL_EC_KEY_generate_key +#define EC_KEY_set_asn1_flag wolfSSL_EC_KEY_set_asn1_flag +#define EC_KEY_set_public_key wolfSSL_EC_KEY_set_public_key + +#define ECDSA_size wolfSSL_ECDSA_size +#define ECDSA_sign wolfSSL_ECDSA_sign + +#define EC_GROUP_free wolfSSL_EC_GROUP_free +#define EC_GROUP_set_asn1_flag wolfSSL_EC_GROUP_set_asn1_flag +#define EC_GROUP_new_by_curve_name wolfSSL_EC_GROUP_new_by_curve_name +#define EC_GROUP_cmp wolfSSL_EC_GROUP_cmp +#define EC_GROUP_get_curve_name wolfSSL_EC_GROUP_get_curve_name +#define EC_GROUP_get_degree wolfSSL_EC_GROUP_get_degree +#define EC_GROUP_get_order wolfSSL_EC_GROUP_get_order +#define EC_GROUP_order_bits wolfSSL_EC_GROUP_order_bits +#define EC_GROUP_method_of wolfSSL_EC_GROUP_method_of + +#define EC_METHOD_get_field_type wolfSSL_EC_METHOD_get_field_type + +#define EC_POINT_new wolfSSL_EC_POINT_new +#define EC_POINT_free wolfSSL_EC_POINT_free +#define EC_POINT_get_affine_coordinates_GFp \ + wolfSSL_EC_POINT_get_affine_coordinates_GFp +#define EC_POINT_set_affine_coordinates_GFp \ + wolfSSL_EC_POINT_set_affine_coordinates_GFp +#define EC_POINT_mul wolfSSL_EC_POINT_mul +#define EC_POINT_clear_free wolfSSL_EC_POINT_clear_free +#define EC_POINT_cmp wolfSSL_EC_POINT_cmp +#define EC_POINT_copy wolfSSL_EC_POINT_copy +#define EC_POINT_is_at_infinity wolfSSL_EC_POINT_is_at_infinity + +#define EC_get_builtin_curves wolfSSL_EC_get_builtin_curves + +#define ECPoint_i2d wolfSSL_ECPoint_i2d +#define ECPoint_d2i wolfSSL_ECPoint_d2i +#define EC_POINT_point2oct wolfSSL_EC_POINT_point2oct +#define EC_POINT_oct2point wolfSSL_EC_POINT_oct2point +#define EC_POINT_point2bn wolfSSL_EC_POINT_point2bn +#define i2o_ECPublicKey wolfSSL_i2o_ECPublicKey +#define EC_KEY_set_conv_form wolfSSL_EC_KEY_set_conv_form + +#ifndef HAVE_SELFTEST + #define EC_POINT_point2hex wolfSSL_EC_POINT_point2hex +#endif + +#define EC_POINT_dump wolfSSL_EC_POINT_dump +#define EC_get_builtin_curves wolfSSL_EC_get_builtin_curves + +#define EC_curve_nid2nist wolfSSL_EC_curve_nid2nist + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* header */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ec25519.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ec25519.h new file mode 100644 index 000000000..180eb8e83 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ec25519.h @@ -0,0 +1,44 @@ +/* ec25519.h + * + * Copyright (C) 2006-2020 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 + */ + +/* ec25519.h */ + +#ifndef WOLFSSL_EC25519_H_ +#define WOLFSSL_EC25519_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +WOLFSSL_API +int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz); + +WOLFSSL_API +int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz, + const unsigned char *priv, unsigned int privSz, + const unsigned char *pub, unsigned int pubSz); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* header */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ec448.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ec448.h new file mode 100644 index 000000000..fb3b9005d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ec448.h @@ -0,0 +1,44 @@ +/* ec448.h + * + * Copyright (C) 2006-2020 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 + */ + +/* ec448.h */ + +#ifndef WOLFSSL_EC448_H_ +#define WOLFSSL_EC448_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +WOLFSSL_API +int wolfSSL_EC448_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz); + +WOLFSSL_API +int wolfSSL_EC448_shared_key(unsigned char *shared, unsigned int *sharedSz, + const unsigned char *priv, unsigned int privSz, + const unsigned char *pub, unsigned int pubSz); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* header */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ecdh.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ecdh.h new file mode 100644 index 000000000..7d7aa09ec --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ecdh.h @@ -0,0 +1,49 @@ +/* ecdh.h + * + * Copyright (C) 2006-2020 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 + */ + +/* ecdh.h for openssl */ + +#ifndef WOLFSSL_ECDH_H_ +#define WOLFSSL_ECDH_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +WOLFSSL_API int wolfSSL_ECDH_compute_key(void *out, size_t outlen, + const WOLFSSL_EC_POINT *pub_key, + WOLFSSL_EC_KEY *ecdh, + void *(*KDF) (const void *in, + size_t inlen, + void *out, + size_t *outlen)); + +#define ECDH_compute_key wolfSSL_ECDH_compute_key + +#ifdef __cplusplus +} /* extern C */ +#endif + +#endif /* header */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ecdsa.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ecdsa.h index f3cf0de35..77c1a18b0 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ecdsa.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ecdsa.h @@ -1,2 +1,75 @@ +/* ecdsa.h + * + * Copyright (C) 2006-2020 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 + */ + /* ecdsa.h for openssl */ +#ifndef WOLFSSL_ECDSA_H_ +#define WOLFSSL_ECDSA_H_ + +#include +#include + + +#ifdef __cplusplus +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; +}; + +WOLFSSL_API void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig); +WOLFSSL_API WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void); +WOLFSSL_API WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *dgst, + int dgst_len, + WOLFSSL_EC_KEY *eckey); +WOLFSSL_API int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, + int dgst_len, + const WOLFSSL_ECDSA_SIG *sig, + WOLFSSL_EC_KEY *eckey); + +WOLFSSL_API WOLFSSL_ECDSA_SIG *wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG **sig, + const unsigned char **pp, + long len); +WOLFSSL_API int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, + unsigned char **pp); + +#define ECDSA_SIG_free wolfSSL_ECDSA_SIG_free +#define ECDSA_SIG_new wolfSSL_ECDSA_SIG_new +#define ECDSA_do_sign wolfSSL_ECDSA_do_sign +#define ECDSA_do_verify wolfSSL_ECDSA_do_verify +#define d2i_ECDSA_SIG wolfSSL_d2i_ECDSA_SIG +#define i2d_ECDSA_SIG wolfSSL_i2d_ECDSA_SIG + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* header */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ed25519.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ed25519.h new file mode 100644 index 000000000..579c653f6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ed25519.h @@ -0,0 +1,47 @@ +/* ed25519.h + * + * Copyright (C) 2006-2020 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 + */ + +/* ed25519.h */ + +#ifndef WOLFSSL_ED25519_H_ +#define WOLFSSL_ED25519_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +WOLFSSL_API +int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz); +WOLFSSL_API +int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz, + const unsigned char *priv, unsigned int privSz, + unsigned char *sig, unsigned int *sigSz); +WOLFSSL_API +int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz, + const unsigned char *pub, unsigned int pubSz, + const unsigned char *sig, unsigned int sigSz); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* header */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ed448.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ed448.h new file mode 100644 index 000000000..b9411e92c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ed448.h @@ -0,0 +1,47 @@ +/* ed448.h + * + * Copyright (C) 2006-2020 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 + */ + +/* ed448.h */ + +#ifndef WOLFSSL_ED448_H_ +#define WOLFSSL_ED448_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +WOLFSSL_API +int wolfSSL_ED448_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz); +WOLFSSL_API +int wolfSSL_ED448_sign(const unsigned char *msg, unsigned int msgSz, + const unsigned char *priv, unsigned int privSz, + unsigned char *sig, unsigned int *sigSz); +WOLFSSL_API +int wolfSSL_ED448_verify(const unsigned char *msg, unsigned int msgSz, + const unsigned char *pub, unsigned int pubSz, + const unsigned char *sig, unsigned int sigSz); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* header */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/engine.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/engine.h index 39952fcae..e4a1ff193 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/engine.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/engine.h @@ -1,5 +1,8 @@ /* engine.h for libcurl */ +#include + #undef HAVE_OPENSSL_ENGINE_H +#define ENGINE_load_builtin_engines() /*ENGINE_load_builtin_engines not needed*/ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/err.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/err.h index 7e7f1eb78..cb1acc094 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/err.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/err.h @@ -1,2 +1,55 @@ -/* err.h for openssl */ +/* err.h + * + * Copyright (C) 2006-2020 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_OPENSSL_ERR_ +#define WOLFSSL_OPENSSL_ERR_ + +#include + +/* err.h for openssl */ +#define ERR_load_crypto_strings wolfSSL_ERR_load_crypto_strings +#define ERR_load_CRYPTO_strings wolfSSL_ERR_load_crypto_strings +#define ERR_peek_last_error wolfSSL_ERR_peek_last_error + +/* fatal error */ +#define ERR_R_MALLOC_FAILURE MEMORY_E +#define ERR_R_PASSED_NULL_PARAMETER BAD_FUNC_ARG +#define ERR_R_DISABLED NOT_COMPILED_IN +#define ERR_R_PASSED_INVALID_ARGUMENT BAD_FUNC_ARG +#define RSA_R_UNKNOWN_PADDING_TYPE RSA_PAD_E +#define EC_R_BUFFER_TOO_SMALL BUFFER_E + +/* SSL function codes */ +#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT 1 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 2 +#define SSL_F_SSL_USE_PRIVATEKEY 3 +#define EC_F_EC_GFP_SIMPLE_POINT2OCT 4 + +/* reasons */ +#define ERR_R_SYS_LIB 1 +#define PKCS12_R_MAC_VERIFY_FAILURE 2 + +#define RSAerr(f,r) ERR_put_error(0,(f),(r),__FILE__,__LINE__) +#define SSLerr(f,r) ERR_put_error(0,(f),(r),__FILE__,__LINE__) +#define ECerr(f,r) ERR_put_error(0,(f),(r),__FILE__,__LINE__) + +#endif /* WOLFSSL_OPENSSL_ERR_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/evp.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/evp.h index ded0b2f62..3f9026ac3 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/evp.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/evp.h @@ -1,8 +1,8 @@ /* evp.h * - * Copyright (C) 2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,12 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* evp.h defines mini evp openssl compatibility layer - * + +/*! + \file wolfssl/openssl/evp.h + \brief evp.h defines mini evp openssl compatibility layer */ @@ -34,52 +36,123 @@ #include "prefix_evp.h" #endif +#ifndef NO_MD4 + #include +#endif #ifndef NO_MD5 #include #endif #include +#include #include #include #include +#include +#include #include #include #include - +#include +#ifdef HAVE_IDEA + #include +#endif +#include #ifdef __cplusplus extern "C" { #endif -typedef char WOLFSSL_EVP_MD; -typedef char WOLFSSL_EVP_CIPHER; +typedef char WOLFSSL_EVP_CIPHER; +#ifndef WOLFSSL_EVP_TYPE_DEFINED /* guard on redeclaration */ +typedef char WOLFSSL_EVP_MD; +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_EVP_PKEY; +typedef struct WOLFSSL_EVP_MD_CTX WOLFSSL_EVP_MD_CTX; +#define WOLFSSL_EVP_TYPE_DEFINED +#endif + +typedef WOLFSSL_EVP_PKEY EVP_PKEY; +typedef WOLFSSL_EVP_PKEY PKCS8_PRIV_KEY_INFO; + +#ifndef NO_MD4 + WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_md4(void); +#endif #ifndef NO_MD5 WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void); #endif +WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_mdc2(void); WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void); +WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha224(void); WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void); WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void); WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void); WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void); +WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_224(void); +WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_256(void); +WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_384(void); +WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_512(void); + +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void); +#if !defined(NO_AES) && defined(HAVE_AES_CBC) WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void); +#endif +#ifndef NO_AES +#ifdef WOLFSSL_AES_CFB +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb1(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb1(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb1(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb8(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb8(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb8(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb128(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cfb128(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cfb128(void); +#endif +#ifdef WOLFSSL_AES_OFB +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ofb(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ofb(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ofb(void); +#endif +#ifdef WOLFSSL_AES_XTS +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_xts(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_xts(void); +#endif +#endif /* NO_AES */ +#if !defined(NO_AES) && defined(HAVE_AESGCM) +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_gcm(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_gcm(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_gcm(void); +#endif WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ecb(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_ecb(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_idea_cbc(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc2_cbc(void); typedef union { + #ifndef NO_MD4 + WOLFSSL_MD4_CTX md4; + #endif #ifndef NO_MD5 WOLFSSL_MD5_CTX md5; #endif WOLFSSL_SHA_CTX sha; + #ifdef WOLFSSL_SHA224 + WOLFSSL_SHA224_CTX sha224; + #endif WOLFSSL_SHA256_CTX sha256; #ifdef WOLFSSL_SHA384 WOLFSSL_SHA384_CTX sha384; @@ -90,24 +163,51 @@ typedef union { #ifdef WOLFSSL_RIPEMD WOLFSSL_RIPEMD_CTX ripemd; #endif + #ifndef WOLFSSL_NOSHA3_224 + WOLFSSL_SHA3_224_CTX sha3_224; + #endif + #ifndef WOLFSSL_NOSHA3_256 + WOLFSSL_SHA3_256_CTX sha3_256; + #endif + WOLFSSL_SHA3_384_CTX sha3_384; + #ifndef WOLFSSL_NOSHA3_512 + WOLFSSL_SHA3_512_CTX sha3_512; + #endif } WOLFSSL_Hasher; +typedef struct WOLFSSL_EVP_PKEY_CTX WOLFSSL_EVP_PKEY_CTX; +typedef struct WOLFSSL_EVP_CIPHER_CTX WOLFSSL_EVP_CIPHER_CTX; -typedef struct WOLFSSL_EVP_MD_CTX { - unsigned char macType; - WOLFSSL_Hasher hash; -} WOLFSSL_EVP_MD_CTX; +struct WOLFSSL_EVP_MD_CTX { + union { + WOLFSSL_Hasher digest; + #ifndef NO_HMAC + Hmac hmac; + #endif + } hash; + int macType; + WOLFSSL_EVP_PKEY_CTX *pctx; +}; typedef union { #ifndef NO_AES Aes aes; +#ifdef WOLFSSL_AES_XTS + XtsAes xts; +#endif #endif #ifndef NO_DES3 Des des; Des3 des3; #endif Arc4 arc4; +#ifdef HAVE_IDEA + Idea idea; +#endif +#ifdef WOLFSSL_QT + int (*ctrl) (WOLFSSL_EVP_CIPHER_CTX *, int type, int arg, void *ptr); +#endif } WOLFSSL_Cipher; @@ -118,70 +218,364 @@ enum { AES_128_CTR_TYPE = 4, AES_192_CTR_TYPE = 5, AES_256_CTR_TYPE = 6, - DES_CBC_TYPE = 7, - DES_EDE3_CBC_TYPE = 8, - ARC4_TYPE = 9, - NULL_CIPHER_TYPE = 10, - EVP_PKEY_RSA = 11, - EVP_PKEY_DSA = 12, + AES_128_ECB_TYPE = 7, + AES_192_ECB_TYPE = 8, + AES_256_ECB_TYPE = 9, + DES_CBC_TYPE = 10, + DES_ECB_TYPE = 11, + DES_EDE3_CBC_TYPE = 12, + DES_EDE3_ECB_TYPE = 13, + ARC4_TYPE = 14, + NULL_CIPHER_TYPE = 15, + EVP_PKEY_RSA = 16, + EVP_PKEY_DSA = 17, + EVP_PKEY_EC = 18, +#ifdef HAVE_IDEA + IDEA_CBC_TYPE = 19, +#endif + AES_128_GCM_TYPE = 21, + AES_192_GCM_TYPE = 22, + AES_256_GCM_TYPE = 23, NID_sha1 = 64, - NID_md5 = 4 + NID_sha224 = 65, + NID_md2 = 77, + NID_md4 = 257, + NID_md5 = 4, + NID_hmac = 855, + NID_dhKeyAgreement= 28, + EVP_PKEY_DH = NID_dhKeyAgreement, + EVP_PKEY_HMAC = NID_hmac, + AES_128_CFB1_TYPE = 24, + AES_192_CFB1_TYPE = 25, + AES_256_CFB1_TYPE = 26, + AES_128_CFB8_TYPE = 27, + AES_192_CFB8_TYPE = 28, + AES_256_CFB8_TYPE = 29, + AES_128_CFB128_TYPE = 30, + AES_192_CFB128_TYPE = 31, + AES_256_CFB128_TYPE = 32, + AES_128_OFB_TYPE = 33, + AES_192_OFB_TYPE = 34, + AES_256_OFB_TYPE = 35, + AES_128_XTS_TYPE = 36, + AES_256_XTS_TYPE = 37 }; +enum { + NID_md5WithRSA = 104, + NID_md5WithRSAEncryption = 8, + NID_dsaWithSHA1 = 113, + NID_dsaWithSHA1_2 = 70, + NID_sha1WithRSA = 115, + NID_sha1WithRSAEncryption = 65, + NID_sha224WithRSAEncryption = 671, + NID_sha256WithRSAEncryption = 668, + NID_sha384WithRSAEncryption = 669, + NID_sha512WithRSAEncryption = 670, + NID_ecdsa_with_SHA1 = 416, + NID_ecdsa_with_SHA224 = 793, + NID_ecdsa_with_SHA256 = 794, + NID_ecdsa_with_SHA384 = 795, + NID_ecdsa_with_SHA512 = 796, + NID_dsa_with_SHA224 = 802, + NID_dsa_with_SHA256 = 803, + NID_sha3_224 = 1096, + NID_sha3_256 = 1097, + NID_sha3_384 = 1098, + NID_sha3_512 = 1099, +}; -typedef struct WOLFSSL_EVP_CIPHER_CTX { +enum { + NID_aes_128_cbc = 419, + NID_aes_192_cbc = 423, + NID_aes_256_cbc = 427, + NID_aes_128_gcm = 895, + NID_aes_192_gcm = 898, + NID_aes_256_gcm = 901, + 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, + NID_aes_128_cfb1= 650, + NID_aes_192_cfb1= 651, + NID_aes_256_cfb1= 652, + NID_aes_128_cfb8= 653, + NID_aes_192_cfb8= 654, + NID_aes_256_cfb8= 655, + NID_aes_128_cfb128 = 421, + NID_aes_192_cfb128 = 425, + NID_aes_256_cfb128 = 429, + NID_aes_128_ofb = 420, + NID_aes_192_ofb = 424, + NID_aes_256_ofb = 428, + NID_aes_128_xts = 913, + NID_aes_256_xts = 914 +}; + +#define NID_X9_62_id_ecPublicKey EVP_PKEY_EC +#define NID_dhKeyAgreement EVP_PKEY_DH +#define NID_rsaEncryption EVP_PKEY_RSA +#define NID_dsa EVP_PKEY_DSA + +#define WOLFSSL_EVP_BUF_SIZE 16 +struct WOLFSSL_EVP_CIPHER_CTX { int keyLen; /* user may set for variable */ + int block_size; + unsigned long flags; unsigned char enc; /* if encrypt side, then true */ unsigned char cipherType; #ifndef NO_AES - unsigned char iv[AES_BLOCK_SIZE]; /* working iv pointer into cipher */ + /* working iv pointer into cipher */ + ALIGN16 unsigned char iv[AES_BLOCK_SIZE]; #elif !defined(NO_DES3) - unsigned char iv[DES_BLOCK_SIZE]; /* working iv pointer into cipher */ + /* working iv pointer into cipher */ + ALIGN16 unsigned char iv[DES_BLOCK_SIZE]; +#elif defined(HAVE_IDEA) + /* working iv pointer into cipher */ + ALIGN16 unsigned char iv[IDEA_BLOCK_SIZE]; #endif WOLFSSL_Cipher cipher; -} WOLFSSL_EVP_CIPHER_CTX; + ALIGN16 byte buf[WOLFSSL_EVP_BUF_SIZE]; + int bufUsed; + ALIGN16 byte lastBlock[WOLFSSL_EVP_BUF_SIZE]; + int lastUsed; +#if !defined(NO_AES) || !defined(NO_DES3) || defined(HAVE_IDEA) || \ + defined(HAVE_AESGCM) || defined (WOLFSSL_AES_XTS) +#define HAVE_WOLFSSL_EVP_CIPHER_CTX_IV + int ivSz; + ALIGN16 unsigned char authTag[AES_BLOCK_SIZE]; + int authTagSz; +#endif +}; +struct WOLFSSL_EVP_PKEY_CTX { + WOLFSSL_EVP_PKEY *pkey; + WOLFSSL_EVP_PKEY *peerKey; + int op; /* operation */ + int padding; + int nbits; +}; +typedef int WOLFSSL_ENGINE ; +typedef WOLFSSL_ENGINE ENGINE; +typedef WOLFSSL_EVP_PKEY_CTX EVP_PKEY_CTX; + +#define EVP_PKEY_OP_SIGN (1 << 3) +#define EVP_PKEY_OP_ENCRYPT (1 << 6) +#define EVP_PKEY_OP_DECRYPT (1 << 7) +#define EVP_PKEY_OP_DERIVE (1 << 8) + +WOLFSSL_API void wolfSSL_EVP_init(void); WOLFSSL_API int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* md); +WOLFSSL_API int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md); +WOLFSSL_API int wolfSSL_EVP_MD_block_size(const WOLFSSL_EVP_MD *md); + +WOLFSSL_API WOLFSSL_EVP_MD_CTX *wolfSSL_EVP_MD_CTX_new (void); +WOLFSSL_API void wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX* ctx); WOLFSSL_API void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx); +WOLFSSL_API int wolfSSL_EVP_MD_CTX_copy(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in); +WOLFSSL_API int wolfSSL_EVP_MD_CTX_copy_ex(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in); +WOLFSSL_API int wolfSSL_EVP_MD_CTX_type(const WOLFSSL_EVP_MD_CTX *ctx); +WOLFSSL_API int wolfSSL_EVP_MD_CTX_size(const WOLFSSL_EVP_MD_CTX *ctx); +WOLFSSL_API int wolfSSL_EVP_MD_CTX_block_size(const WOLFSSL_EVP_MD_CTX *ctx); +WOLFSSL_API const WOLFSSL_EVP_MD *wolfSSL_EVP_MD_CTX_md(const WOLFSSL_EVP_MD_CTX *ctx); +WOLFSSL_API const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name); +WOLFSSL_API const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name); +WOLFSSL_API int wolfSSL_EVP_CIPHER_nid(const WOLFSSL_EVP_CIPHER *cipher); WOLFSSL_API int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx, const WOLFSSL_EVP_MD* type); +WOLFSSL_API int wolfSSL_EVP_DigestInit_ex(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* type, + WOLFSSL_ENGINE *impl); WOLFSSL_API int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data, - unsigned long sz); + size_t sz); WOLFSSL_API int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s); WOLFSSL_API int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s); -#ifndef NO_MD5 + +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); + +WOLFSSL_API int wolfSSL_EVP_DigestVerifyInit(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_DigestVerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, + const void *d, size_t cnt); +WOLFSSL_API int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, + const unsigned char *sig, + size_t siglen); +WOLFSSL_API int wolfSSL_EVP_Digest(const unsigned char* in, int inSz, unsigned char* out, + unsigned int* outSz, const WOLFSSL_EVP_MD* evp, + WOLFSSL_ENGINE* eng); + + WOLFSSL_API int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER*, const WOLFSSL_EVP_MD*, const unsigned char*, const unsigned char*, int, int, unsigned char*, unsigned char*); -#endif 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_ctrl(WOLFSSL_EVP_CIPHER_CTX *ctx, \ + int type, int arg, void *ptr); 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_Cipher_key_length(const WOLFSSL_EVP_CIPHER* c); WOLFSSL_API int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx, const WOLFSSL_EVP_CIPHER* type, - unsigned char* key, unsigned char* iv, + const unsigned char* key, + const unsigned char* iv, int enc); +WOLFSSL_API int wolfSSL_EVP_CipherInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + const unsigned char* key, + const unsigned char* iv, + int enc); +WOLFSSL_API int wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + 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, + const unsigned char* key, + const unsigned char* iv); +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_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); +WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, + const unsigned char *in, int inl); +WOLFSSL_API int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl); +WOLFSSL_API int wolfSSL_EVP_CipherFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, int enc); +WOLFSSL_API int wolfSSL_EVP_EncryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl); +WOLFSSL_API int wolfSSL_EVP_EncryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl); +WOLFSSL_API int wolfSSL_EVP_DecryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl); +WOLFSSL_API int wolfSSL_EVP_DecryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl); +WOLFSSL_API int wolfSSL_EVP_DecryptFinal_legacy(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl); + +WOLFSSL_API WOLFSSL_EVP_CIPHER_CTX *wolfSSL_EVP_CIPHER_CTX_new(void); +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_free(WOLFSSL_EVP_CIPHER_CTX *ctx); +WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_reset(WOLFSSL_EVP_CIPHER_CTX *ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx, int keylen); +WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_set_iv_length(WOLFSSL_EVP_CIPHER_CTX* ctx, + int ivLen); +WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_set_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* iv, + int ivLen); 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 const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_CIPHER_CTX_cipher(const WOLFSSL_EVP_CIPHER_CTX *ctx); +WOLFSSL_API int wolfSSL_EVP_PKEY_assign_RSA(WOLFSSL_EVP_PKEY* pkey, + WOLFSSL_RSA* key); +WOLFSSL_API int wolfSSL_EVP_PKEY_assign_EC_KEY(WOLFSSL_EVP_PKEY* pkey, + WOLFSSL_EC_KEY* key); +WOLFSSL_API int wolfSSL_EVP_PKEY_assign_DSA(EVP_PKEY* pkey, WOLFSSL_DSA* key); +WOLFSSL_API int wolfSSL_EVP_PKEY_assign_DH(EVP_PKEY* pkey, WOLFSSL_DH* key); +WOLFSSL_API WOLFSSL_RSA* wolfSSL_EVP_PKEY_get0_RSA(struct WOLFSSL_EVP_PKEY *pkey); 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_get0_EC_KEY(WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API WOLFSSL_EC_KEY *wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY *key); +WOLFSSL_API WOLFSSL_DH* wolfSSL_EVP_PKEY_get0_DH(WOLFSSL_EVP_PKEY* key); +WOLFSSL_API WOLFSSL_DH* wolfSSL_EVP_PKEY_get1_DH(WOLFSSL_EVP_PKEY* key); +WOLFSSL_API int wolfSSL_EVP_PKEY_set1_RSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_RSA *key); +WOLFSSL_API int wolfSSL_EVP_PKEY_set1_DSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DSA *key); +WOLFSSL_API int wolfSSL_EVP_PKEY_set1_DH(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DH *key); +WOLFSSL_API int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_KEY *key); +WOLFSSL_API int wolfSSL_EVP_PKEY_assign(WOLFSSL_EVP_PKEY *pkey, int type, void *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); +WOLFSSL_API int wolfSSL_EVP_PKEY_sign_init(WOLFSSL_EVP_PKEY_CTX *ctx); +WOLFSSL_API int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen); +WOLFSSL_API int wolfSSL_EVP_PKEY_keygen_init(WOLFSSL_EVP_PKEY_CTX *ctx); +WOLFSSL_API int wolfSSL_EVP_PKEY_keygen(WOLFSSL_EVP_PKEY_CTX *ctx, + WOLFSSL_EVP_PKEY **ppkey); +WOLFSSL_API int wolfSSL_EVP_PKEY_bits(const WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx); +WOLFSSL_API WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_ENGINE *e); +WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_rsa_padding(WOLFSSL_EVP_PKEY_CTX *ctx, int padding); +WOLFSSL_API WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new_id(int id, WOLFSSL_ENGINE *e); +WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_rsa_keygen_bits(WOLFSSL_EVP_PKEY_CTX *ctx, int bits); + +WOLFSSL_API int wolfSSL_EVP_PKEY_derive_init(WOLFSSL_EVP_PKEY_CTX *ctx); +WOLFSSL_API int wolfSSL_EVP_PKEY_derive_set_peer(WOLFSSL_EVP_PKEY_CTX *ctx, WOLFSSL_EVP_PKEY *peer); +WOLFSSL_API int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); + +WOLFSSL_API int wolfSSL_EVP_PKEY_decrypt(WOLFSSL_EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); +WOLFSSL_API int wolfSSL_EVP_PKEY_decrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx); +WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt(WOLFSSL_EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); +WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx); +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_EVP_PKEY_new(void); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap); +WOLFSSL_API void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY*); +WOLFSSL_API int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_PKEY_missing_parameters(WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_PKEY_cmp(const WOLFSSL_EVP_PKEY *a, const WOLFSSL_EVP_PKEY *b); +WOLFSSL_API int wolfSSL_EVP_PKEY_type(int type); +WOLFSSL_API int wolfSSL_EVP_PKEY_id(const EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_SignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sigret, + unsigned int *siglen, WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_SignInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type); +WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* type, + WOLFSSL_ENGINE *impl); +WOLFSSL_API int wolfSSL_EVP_SignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len); +WOLFSSL_API int wolfSSL_EVP_VerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, + unsigned char* sig, unsigned int sig_len, WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int wolfSSL_EVP_VerifyInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type); +WOLFSSL_API int wolfSSL_EVP_VerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, 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); @@ -195,6 +589,60 @@ WOLFSSL_API void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, WOLFSSL_API int wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx); +WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_block_size(const WOLFSSL_EVP_CIPHER_CTX *ctx); +WOLFSSL_API int wolfSSL_EVP_CIPHER_block_size(const WOLFSSL_EVP_CIPHER *cipher); +WOLFSSL_API unsigned long WOLFSSL_EVP_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher); +WOLFSSL_API unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher); +WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_flags(const WOLFSSL_EVP_CIPHER *cipher); +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags); +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_clear_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags); +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 void wolfSSL_EVP_cleanup(void); +WOLFSSL_API int wolfSSL_add_all_algorithms(void); +WOLFSSL_API int wolfSSL_OpenSSL_add_all_algorithms_conf(void); +WOLFSSL_API int wolfSSL_OpenSSL_add_all_algorithms_noconf(void); +WOLFSSL_API int wolfSSL_EVP_read_pw_string(char*, int, const char*, int); + +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); + +WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen, + const unsigned char *salt, + int saltlen, int iter, + const WOLFSSL_EVP_MD *digest, + int keylen, unsigned char *out); + +WOLFSSL_LOCAL int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp, + int* pHash, int* pHashSz); + +#define EVP_CIPH_STREAM_CIPHER WOLFSSL_EVP_CIPH_STREAM_CIPHER +#define EVP_CIPH_ECB_MODE WOLFSSL_EVP_CIPH_ECB_MODE +#define EVP_CIPH_CBC_MODE WOLFSSL_EVP_CIPH_CBC_MODE +#define EVP_CIPH_CFB_MODE WOLFSSL_EVP_CIPH_CFB_MODE +#define EVP_CIPH_OFB_MODE WOLFSSL_EVP_CIPH_OFB_MODE +#define EVP_CIPH_CTR_MODE WOLFSSL_EVP_CIPH_CTR_MODE +#define EVP_CIPH_GCM_MODE WOLFSSL_EVP_CIPH_GCM_MODE +#define EVP_CIPH_CCM_MODE WOLFSSL_EVP_CIPH_CCM_MODE +#define EVP_CIPH_XTS_MODE WOLFSSL_EVP_CIPH_XTS_MODE + +#define WOLFSSL_EVP_CIPH_MODE 0x0007 +#define WOLFSSL_EVP_CIPH_STREAM_CIPHER 0x0 +#define WOLFSSL_EVP_CIPH_ECB_MODE 0x1 +#define WOLFSSL_EVP_CIPH_CBC_MODE 0x2 +#define WOLFSSL_EVP_CIPH_CFB_MODE 0x3 +#define WOLFSSL_EVP_CIPH_OFB_MODE 0x4 +#define WOLFSSL_EVP_CIPH_CTR_MODE 0x5 +#define WOLFSSL_EVP_CIPH_GCM_MODE 0x6 +#define WOLFSSL_EVP_CIPH_CCM_MODE 0x7 +#define WOLFSSL_EVP_CIPH_XTS_MODE 0x10 +#define WOLFSSL_EVP_CIPH_NO_PADDING 0x100 +#define EVP_CIPH_VARIABLE_LENGTH 0x200 +#define WOLFSSL_EVP_CIPH_TYPE_INIT 0xff /* end OpenSSH compat */ @@ -203,55 +651,280 @@ typedef WOLFSSL_EVP_CIPHER EVP_CIPHER; typedef WOLFSSL_EVP_MD_CTX EVP_MD_CTX; typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; +#ifndef NO_MD4 + #define EVP_md4 wolfSSL_EVP_md4 +#endif #ifndef NO_MD5 #define EVP_md5 wolfSSL_EVP_md5 #endif #define EVP_sha1 wolfSSL_EVP_sha1 +#define EVP_mdc2 wolfSSL_EVP_mdc2 +#define EVP_dds1 wolfSSL_EVP_sha1 +#define EVP_sha224 wolfSSL_EVP_sha224 #define EVP_sha256 wolfSSL_EVP_sha256 #define EVP_sha384 wolfSSL_EVP_sha384 #define EVP_sha512 wolfSSL_EVP_sha512 #define EVP_ripemd160 wolfSSL_EVP_ripemd160 -#define EVP_aes_128_cbc wolfSSL_EVP_aes_128_cbc -#define EVP_aes_192_cbc wolfSSL_EVP_aes_192_cbc -#define EVP_aes_256_cbc wolfSSL_EVP_aes_256_cbc -#define EVP_aes_128_ctr wolfSSL_EVP_aes_128_ctr -#define EVP_aes_192_ctr wolfSSL_EVP_aes_192_ctr -#define EVP_aes_256_ctr wolfSSL_EVP_aes_256_ctr -#define EVP_des_cbc wolfSSL_EVP_des_cbc -#define EVP_des_ede3_cbc wolfSSL_EVP_des_ede3_cbc -#define EVP_rc4 wolfSSL_EVP_rc4 -#define EVP_enc_null wolfSSL_EVP_enc_null +#define EVP_sha3_224 wolfSSL_EVP_sha3_224 +#define EVP_sha3_256 wolfSSL_EVP_sha3_256 +#define EVP_sha3_384 wolfSSL_EVP_sha3_384 +#define EVP_sha3_512 wolfSSL_EVP_sha3_512 -#define EVP_MD_size wolfSSL_EVP_MD_size -#define EVP_MD_CTX_init wolfSSL_EVP_MD_CTX_init -#define EVP_MD_CTX_cleanup wolfSSL_EVP_MD_CTX_cleanup -#define EVP_DigestInit wolfSSL_EVP_DigestInit -#define EVP_DigestUpdate wolfSSL_EVP_DigestUpdate -#define EVP_DigestFinal wolfSSL_EVP_DigestFinal -#define EVP_DigestFinal_ex wolfSSL_EVP_DigestFinal_ex -#define EVP_BytesToKey wolfSSL_EVP_BytesToKey +#define EVP_aes_128_cbc wolfSSL_EVP_aes_128_cbc +#define EVP_aes_192_cbc wolfSSL_EVP_aes_192_cbc +#define EVP_aes_256_cbc wolfSSL_EVP_aes_256_cbc +#define EVP_aes_128_cfb1 wolfSSL_EVP_aes_128_cfb1 +#define EVP_aes_192_cfb1 wolfSSL_EVP_aes_192_cfb1 +#define EVP_aes_256_cfb1 wolfSSL_EVP_aes_256_cfb1 +#define EVP_aes_128_cfb8 wolfSSL_EVP_aes_128_cfb8 +#define EVP_aes_192_cfb8 wolfSSL_EVP_aes_192_cfb8 +#define EVP_aes_256_cfb8 wolfSSL_EVP_aes_256_cfb8 +#define EVP_aes_128_cfb128 wolfSSL_EVP_aes_128_cfb128 +#define EVP_aes_192_cfb128 wolfSSL_EVP_aes_192_cfb128 +#define EVP_aes_256_cfb128 wolfSSL_EVP_aes_256_cfb128 +#define EVP_aes_128_ofb wolfSSL_EVP_aes_128_ofb +#define EVP_aes_192_ofb wolfSSL_EVP_aes_192_ofb +#define EVP_aes_256_ofb wolfSSL_EVP_aes_256_ofb +#define EVP_aes_128_xts wolfSSL_EVP_aes_128_xts +#define EVP_aes_256_xts wolfSSL_EVP_aes_256_xts +#define EVP_aes_128_gcm wolfSSL_EVP_aes_128_gcm +#define EVP_aes_192_gcm wolfSSL_EVP_aes_192_gcm +#define EVP_aes_256_gcm wolfSSL_EVP_aes_256_gcm +#define EVP_aes_128_ecb wolfSSL_EVP_aes_128_ecb +#define EVP_aes_192_ecb wolfSSL_EVP_aes_192_ecb +#define EVP_aes_256_ecb wolfSSL_EVP_aes_256_ecb +#define EVP_aes_128_ctr wolfSSL_EVP_aes_128_ctr +#define EVP_aes_192_ctr wolfSSL_EVP_aes_192_ctr +#define EVP_aes_256_ctr wolfSSL_EVP_aes_256_ctr +#define EVP_des_cbc wolfSSL_EVP_des_cbc +#define EVP_des_ecb wolfSSL_EVP_des_ecb +#define EVP_des_ede3_cbc wolfSSL_EVP_des_ede3_cbc +#define EVP_des_ede3_ecb wolfSSL_EVP_des_ede3_ecb +#define EVP_rc4 wolfSSL_EVP_rc4 +#define EVP_idea_cbc wolfSSL_EVP_idea_cbc +#define EVP_enc_null wolfSSL_EVP_enc_null + +#define EVP_MD_size wolfSSL_EVP_MD_size +#define EVP_MD_CTX_new wolfSSL_EVP_MD_CTX_new +#define EVP_MD_CTX_create wolfSSL_EVP_MD_CTX_new +#define EVP_MD_CTX_free wolfSSL_EVP_MD_CTX_free +#define EVP_MD_CTX_destroy wolfSSL_EVP_MD_CTX_free +#define EVP_MD_CTX_init wolfSSL_EVP_MD_CTX_init +#define EVP_MD_CTX_cleanup wolfSSL_EVP_MD_CTX_cleanup +#define EVP_MD_CTX_reset wolfSSL_EVP_MD_CTX_cleanup +#define EVP_MD_CTX_md wolfSSL_EVP_MD_CTX_md +#define EVP_MD_CTX_type wolfSSL_EVP_MD_CTX_type +#define EVP_MD_CTX_size wolfSSL_EVP_MD_CTX_size +#define EVP_MD_CTX_block_size wolfSSL_EVP_MD_CTX_block_size +#define EVP_MD_type wolfSSL_EVP_MD_type + +#define EVP_Digest wolfSSL_EVP_Digest +#define EVP_DigestInit wolfSSL_EVP_DigestInit +#define EVP_DigestInit_ex wolfSSL_EVP_DigestInit_ex +#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_DigestVerifyInit wolfSSL_EVP_DigestVerifyInit +#define EVP_DigestVerifyUpdate wolfSSL_EVP_DigestVerifyUpdate +#define EVP_DigestVerifyFinal wolfSSL_EVP_DigestVerifyFinal +#define EVP_BytesToKey wolfSSL_EVP_BytesToKey + +#define EVP_get_cipherbyname wolfSSL_EVP_get_cipherbyname +#define EVP_get_digestbyname wolfSSL_EVP_get_digestbyname #define EVP_CIPHER_CTX_init wolfSSL_EVP_CIPHER_CTX_init #define EVP_CIPHER_CTX_cleanup wolfSSL_EVP_CIPHER_CTX_cleanup #define EVP_CIPHER_CTX_iv_length wolfSSL_EVP_CIPHER_CTX_iv_length #define EVP_CIPHER_CTX_key_length wolfSSL_EVP_CIPHER_CTX_key_length #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_CTX_cipher wolfSSL_EVP_CIPHER_CTX_cipher + +#define EVP_CIPHER_iv_length wolfSSL_EVP_CIPHER_iv_length +#define EVP_CIPHER_key_length wolfSSL_EVP_Cipher_key_length + #define EVP_CipherInit wolfSSL_EVP_CipherInit +#define EVP_CipherInit_ex wolfSSL_EVP_CipherInit_ex +#define EVP_EncryptInit wolfSSL_EVP_EncryptInit +#define EVP_EncryptInit_ex wolfSSL_EVP_EncryptInit_ex +#define EVP_DecryptInit wolfSSL_EVP_DecryptInit +#define EVP_DecryptInit_ex wolfSSL_EVP_DecryptInit_ex + #define EVP_Cipher wolfSSL_EVP_Cipher +#define EVP_CipherUpdate wolfSSL_EVP_CipherUpdate +#define EVP_EncryptUpdate wolfSSL_EVP_CipherUpdate +#define EVP_DecryptUpdate wolfSSL_EVP_CipherUpdate +#define EVP_CipherFinal wolfSSL_EVP_CipherFinal +#define EVP_CipherFinal_ex wolfSSL_EVP_CipherFinal +#define EVP_EncryptFinal wolfSSL_EVP_CipherFinal +#define EVP_EncryptFinal_ex wolfSSL_EVP_CipherFinal +#define EVP_DecryptFinal wolfSSL_EVP_CipherFinal +#define EVP_DecryptFinal_ex wolfSSL_EVP_CipherFinal +#define EVP_CIPHER_CTX_free wolfSSL_EVP_CIPHER_CTX_free +#define EVP_CIPHER_CTX_reset wolfSSL_EVP_CIPHER_CTX_reset +#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 -#define EVP_PKEY_get1_RSA wolfSSL_EVP_PKEY_get1_RSA -#define EVP_PKEY_get1_DSA wolfSSL_EVP_PKEY_get1_DSA +#define EVP_PKEY_assign wolfSSL_EVP_PKEY_assign +#define EVP_PKEY_assign_RSA wolfSSL_EVP_PKEY_assign_RSA +#define EVP_PKEY_assign_DSA wolfSSL_EVP_PKEY_assign_DSA +#define EVP_PKEY_assign_DH wolfSSL_EVP_PKEY_assign_DH +#define EVP_PKEY_assign_EC_KEY wolfSSL_EVP_PKEY_assign_EC_KEY +#define EVP_PKEY_get1_DSA wolfSSL_EVP_PKEY_get1_DSA +#define EVP_PKEY_set1_DSA wolfSSL_EVP_PKEY_set1_DSA +#define EVP_PKEY_get0_RSA wolfSSL_EVP_PKEY_get0_RSA +#define EVP_PKEY_get1_RSA wolfSSL_EVP_PKEY_get1_RSA +#define EVP_PKEY_set1_RSA wolfSSL_EVP_PKEY_set1_RSA +#define EVP_PKEY_set1_EC_KEY wolfSSL_EVP_PKEY_set1_EC_KEY +#define EVP_PKEY_get1_EC_KEY wolfSSL_EVP_PKEY_get1_EC_KEY +#define EVP_PKEY_set1_DH wolfSSL_EVP_PKEY_set1_DH +#define EVP_PKEY_get0_DH wolfSSL_EVP_PKEY_get0_DH +#define EVP_PKEY_get1_DH wolfSSL_EVP_PKEY_get1_DH +#define EVP_PKEY_get0_EC_KEY wolfSSL_EVP_PKEY_get0_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_MD_CTX_copy wolfSSL_EVP_MD_CTX_copy +#define EVP_MD_CTX_copy_ex wolfSSL_EVP_MD_CTX_copy_ex +#define EVP_PKEY_sign_init wolfSSL_EVP_PKEY_sign_init +#define EVP_PKEY_sign wolfSSL_EVP_PKEY_sign +#define EVP_PKEY_keygen wolfSSL_EVP_PKEY_keygen +#define EVP_PKEY_keygen_init wolfSSL_EVP_PKEY_keygen_init +#define EVP_PKEY_bits wolfSSL_EVP_PKEY_bits +#define EVP_PKEY_CTX_free wolfSSL_EVP_PKEY_CTX_free +#define EVP_PKEY_CTX_new wolfSSL_EVP_PKEY_CTX_new +#define EVP_PKEY_CTX_set_rsa_padding wolfSSL_EVP_PKEY_CTX_set_rsa_padding +#define EVP_PKEY_CTX_new_id wolfSSL_EVP_PKEY_CTX_new_id +#define EVP_PKEY_CTX_set_rsa_keygen_bits wolfSSL_EVP_PKEY_CTX_set_rsa_keygen_bits +#define EVP_PKEY_derive_init wolfSSL_EVP_PKEY_derive_init +#define EVP_PKEY_derive_set_peer wolfSSL_EVP_PKEY_derive_set_peer +#define EVP_PKEY_derive wolfSSL_EVP_PKEY_derive +#define EVP_PKEY_decrypt wolfSSL_EVP_PKEY_decrypt +#define EVP_PKEY_decrypt_init wolfSSL_EVP_PKEY_decrypt_init +#define EVP_PKEY_encrypt wolfSSL_EVP_PKEY_encrypt +#define EVP_PKEY_encrypt_init wolfSSL_EVP_PKEY_encrypt_init +#define EVP_PKEY_new wolfSSL_EVP_PKEY_new +#define EVP_PKEY_free wolfSSL_EVP_PKEY_free +#define EVP_PKEY_up_ref wolfSSL_EVP_PKEY_up_ref +#define EVP_PKEY_size wolfSSL_EVP_PKEY_size +#define EVP_PKEY_missing_parameters wolfSSL_EVP_PKEY_missing_parameters +#define EVP_PKEY_cmp wolfSSL_EVP_PKEY_cmp +#define EVP_PKEY_type wolfSSL_EVP_PKEY_type +#define EVP_PKEY_base_id wolfSSL_EVP_PKEY_base_id +#define EVP_PKEY_id wolfSSL_EVP_PKEY_id +#define EVP_SignFinal wolfSSL_EVP_SignFinal +#define EVP_SignInit wolfSSL_EVP_SignInit +#define EVP_SignInit_ex wolfSSL_EVP_SignInit_ex +#define EVP_SignUpdate wolfSSL_EVP_SignUpdate +#define EVP_VerifyFinal wolfSSL_EVP_VerifyFinal +#define EVP_VerifyInit wolfSSL_EVP_VerifyInit +#define EVP_VerifyUpdate wolfSSL_EVP_VerifyUpdate + +#define EVP_CIPHER_CTX_ctrl wolfSSL_EVP_CIPHER_CTX_ctrl +#define EVP_CIPHER_CTX_block_size wolfSSL_EVP_CIPHER_CTX_block_size +#define EVP_CIPHER_block_size wolfSSL_EVP_CIPHER_block_size +#define EVP_CIPHER_flags wolfSSL_EVP_CIPHER_flags +#define EVP_CIPHER_CTX_set_flags wolfSSL_EVP_CIPHER_CTX_set_flags +#define EVP_CIPHER_CTX_clear_flags wolfSSL_EVP_CIPHER_CTX_clear_flags +#define EVP_CIPHER_CTX_set_padding wolfSSL_EVP_CIPHER_CTX_set_padding +#define EVP_CIPHER_CTX_flags wolfSSL_EVP_CIPHER_CTX_flags +#define EVP_CIPHER_CTX_set_iv wolfSSL_EVP_CIPHER_CTX_set_iv +#define EVP_add_digest wolfSSL_EVP_add_digest +#define EVP_add_cipher wolfSSL_EVP_add_cipher +#define EVP_cleanup wolfSSL_EVP_cleanup +#define EVP_read_pw_string wolfSSL_EVP_read_pw_string +#define EVP_rc2_cbc wolfSSL_EVP_rc2_cbc + +#define OpenSSL_add_all_digests() wolfSSL_EVP_init() +#define OpenSSL_add_all_ciphers() wolfSSL_EVP_init() +#define OpenSSL_add_all_algorithms wolfSSL_add_all_algorithms +#define OpenSSL_add_all_algorithms_noconf wolfSSL_OpenSSL_add_all_algorithms_noconf +#define OpenSSL_add_all_algorithms_conf wolfSSL_OpenSSL_add_all_algorithms_conf + +#define wolfSSL_OPENSSL_add_all_algorithms_noconf wolfSSL_OpenSSL_add_all_algorithms_noconf +#define wolfSSL_OPENSSL_add_all_algorithms_conf wolfSSL_OpenSSL_add_all_algorithms_conf + +/* provides older OpenSSL API compatibility */ +#define OPENSSL_add_all_algorithms OpenSSL_add_all_algorithms +#define OPENSSL_add_all_algorithms_noconf OpenSSL_add_all_algorithms_noconf +#define OPENSSL_add_all_algorithms_conf OpenSSL_add_all_algorithms_conf + +#define NO_PADDING_BLOCK_SIZE 1 + +#define PKCS5_PBKDF2_HMAC_SHA1 wolfSSL_PKCS5_PBKDF2_HMAC_SHA1 +#define PKCS5_PBKDF2_HMAC wolfSSL_PKCS5_PBKDF2_HMAC + +/* OpenSSL compat. ctrl values */ +#define EVP_CTRL_INIT 0x0 +#define EVP_CTRL_SET_KEY_LENGTH 0x1 +#define EVP_CTRL_SET_RC2_KEY_BITS 0x3 /* needed for qt compilation */ + +#define EVP_CTRL_AEAD_SET_IVLEN 0x9 +#define EVP_CTRL_AEAD_GET_TAG 0x10 +#define EVP_CTRL_AEAD_SET_TAG 0x11 +#define EVP_CTRL_AEAD_SET_IV_FIXED 0x12 +#define EVP_CTRL_GCM_IV_GEN 0x13 +#define EVP_CTRL_GCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN +#define EVP_CTRL_GCM_GET_TAG EVP_CTRL_AEAD_GET_TAG +#define EVP_CTRL_GCM_SET_TAG EVP_CTRL_AEAD_SET_TAG +#define EVP_CTRL_GCM_SET_IV_FIXED EVP_CTRL_AEAD_SET_IV_FIXED + +#define EVP_PKEY_print_private(arg1, arg2, arg3, arg4) #ifndef EVP_MAX_MD_SIZE #define EVP_MAX_MD_SIZE 64 /* sha512 */ #endif +#ifndef EVP_MAX_KEY_LENGTH +#define EVP_MAX_KEY_LENGTH 64 +#endif + +#ifndef EVP_MAX_IV_LENGTH +#define EVP_MAX_IV_LENGTH 16 +#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 + +#ifndef EVP_MAX_IV_LENGTH + #define EVP_MAX_IV_LENGTH 16 +#endif + + +#define EVP_R_BAD_DECRYPT (-MIN_CODE_E + 100 + 1) +#define EVP_R_BN_DECODE_ERROR (-MIN_CODE_E + 100 + 2) +#define EVP_R_DECODE_ERROR (-MIN_CODE_E + 100 + 3) +#define EVP_R_PRIVATE_KEY_DECODE_ERROR (-MIN_CODE_E + 100 + 4) + +#define EVP_PKEY_NONE NID_undef +#define EVP_PKEY_RSA 6 +#define EVP_PKEY_RSA2 19 +#define EVP_PKEY_DH 28 +#define EVP_CIPHER_mode WOLFSSL_CIPHER_mode +/* WOLFSSL_EVP_CIPHER is just the string name of the cipher */ +#define EVP_CIPHER_name(x) x +#define EVP_MD_CTX_reset wolfSSL_EVP_MD_CTX_cleanup +/* WOLFSSL_EVP_MD is just the string name of the digest */ +#define EVP_MD_name(x) x +#define EVP_CIPHER_nid wolfSSL_EVP_CIPHER_nid + + +WOLFSSL_API void printPKEY(WOLFSSL_EVP_PKEY *k); + #ifdef __cplusplus } /* extern "C" */ #endif +#include #endif /* WOLFSSL_EVP_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/hmac.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/hmac.h index 0dca8cb2b..6ebd6dca6 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/hmac.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/hmac.h @@ -1,8 +1,8 @@ /* hmac.h * - * Copyright (C) 2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,11 +16,12 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* hmac.h defines mini hamc openssl compatibility layer + +/* hmac.h defines mini hamc openssl compatibility layer * */ @@ -35,6 +36,7 @@ #endif #include +#include #include #ifdef __cplusplus @@ -51,26 +53,43 @@ WOLFSSL_API unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, typedef struct WOLFSSL_HMAC_CTX { Hmac hmac; int type; + word32 save_ipad[WC_HMAC_BLOCK_SIZE / sizeof(word32)]; /* same block size all*/ + word32 save_opad[WC_HMAC_BLOCK_SIZE / sizeof(word32)]; } WOLFSSL_HMAC_CTX; -WOLFSSL_API void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, +WOLFSSL_API WOLFSSL_HMAC_CTX* wolfSSL_HMAC_CTX_new(void); +WOLFSSL_API int wolfSSL_HMAC_CTX_Init(WOLFSSL_HMAC_CTX* ctx); +WOLFSSL_API int wolfSSL_HMAC_CTX_copy(WOLFSSL_HMAC_CTX* des, + WOLFSSL_HMAC_CTX* src); +WOLFSSL_LOCAL int wolfSSL_HmacCopy(Hmac* des, Hmac* src); +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 keylen, const EVP_MD* type, WOLFSSL_ENGINE* e); +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 void wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx); - +WOLFSSL_API int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx); +WOLFSSL_API void wolfSSL_HMAC_CTX_free(WOLFSSL_HMAC_CTX* ctx); +WOLFSSL_API size_t wolfSSL_HMAC_size(const WOLFSSL_HMAC_CTX *ctx); 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_new wolfSSL_HMAC_CTX_new +#define HMAC_CTX_init wolfSSL_HMAC_CTX_Init +#define HMAC_CTX_copy wolfSSL_HMAC_CTX_copy +#define HMAC_CTX_free wolfSSL_HMAC_CTX_free +#define HMAC_CTX_reset wolfSSL_HMAC_cleanup +#define HMAC_Init_ex wolfSSL_HMAC_Init_ex +#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_size wolfSSL_HMAC_size #ifdef __cplusplus diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/include.am b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/include.am index 05b509bcc..c4ab3948f 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/include.am @@ -3,15 +3,23 @@ nobase_include_HEADERS+= \ wolfssl/openssl/asn1.h \ + wolfssl/openssl/asn1t.h \ + wolfssl/openssl/aes.h\ wolfssl/openssl/bio.h \ wolfssl/openssl/bn.h \ + wolfssl/openssl/buffer.h \ wolfssl/openssl/conf.h \ wolfssl/openssl/crypto.h \ wolfssl/openssl/des.h \ wolfssl/openssl/dh.h \ wolfssl/openssl/dsa.h \ wolfssl/openssl/ecdsa.h \ + wolfssl/openssl/ecdh.h \ wolfssl/openssl/ec.h \ + wolfssl/openssl/ec25519.h \ + wolfssl/openssl/ed25519.h \ + wolfssl/openssl/ec448.h \ + wolfssl/openssl/ed448.h \ wolfssl/openssl/engine.h \ wolfssl/openssl/err.h \ wolfssl/openssl/evp.h \ @@ -20,17 +28,25 @@ nobase_include_HEADERS+= \ wolfssl/openssl/md4.h \ wolfssl/openssl/md5.h \ wolfssl/openssl/ripemd.h \ + wolfssl/openssl/obj_mac.h \ + wolfssl/openssl/objects.h \ wolfssl/openssl/ocsp.h \ wolfssl/openssl/opensslconf.h \ wolfssl/openssl/opensslv.h \ wolfssl/openssl/ossl_typ.h \ wolfssl/openssl/pem.h \ wolfssl/openssl/pkcs12.h \ + wolfssl/openssl/pkcs7.h \ wolfssl/openssl/rand.h \ wolfssl/openssl/rsa.h \ wolfssl/openssl/sha.h \ + wolfssl/openssl/sha3.h \ + wolfssl/openssl/ssl23.h \ wolfssl/openssl/ssl.h \ wolfssl/openssl/stack.h \ + wolfssl/openssl/tls1.h \ wolfssl/openssl/ui.h \ wolfssl/openssl/x509.h \ - wolfssl/openssl/x509v3.h + wolfssl/openssl/x509_vfy.h \ + wolfssl/openssl/x509v3.h \ + wolfssl/openssl/rc4.h diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/md4.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/md4.h index 2e99f977f..aafe9cc17 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/md4.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/md4.h @@ -1 +1,62 @@ -/* md4.h for libcurl */ +/* md4.h + * + * Copyright (C) 2006-2020 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_MD4_H_ +#define WOLFSSL_MD4_H_ + +#include + +#ifndef NO_MD4 + +#ifdef WOLFSSL_PREFIX +#include "prefix_md4.h" +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +typedef struct WOLFSSL_MD4_CTX { + int buffer[32]; /* big enough to hold, check size in Init */ +} WOLFSSL_MD4_CTX; + + +WOLFSSL_API void wolfSSL_MD4_Init(WOLFSSL_MD4_CTX*); +WOLFSSL_API void wolfSSL_MD4_Update(WOLFSSL_MD4_CTX*, const void*, unsigned long); +WOLFSSL_API void wolfSSL_MD4_Final(unsigned char*, WOLFSSL_MD4_CTX*); + + +typedef WOLFSSL_MD4_CTX MD4_CTX; + +#define MD4_Init wolfSSL_MD4_Init +#define MD4_Update wolfSSL_MD4_Update +#define MD4_Final wolfSSL_MD4_Final + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_MD4 */ + +#endif /* WOLFSSL_MD4_H_ */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/md5.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/md5.h index bdcda5b98..49ac1e32f 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/md5.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/md5.h @@ -1,3 +1,24 @@ +/* md5.h + * + * Copyright (C) 2006-2020 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 + */ + /* md5.h for openssl */ @@ -8,6 +29,8 @@ #ifndef NO_MD5 +#include + #ifdef WOLFSSL_PREFIX #include "prefix_md5.h" #endif @@ -18,12 +41,17 @@ typedef struct WOLFSSL_MD5_CTX { - int holder[24]; /* big enough to hold wolfcrypt md5, but check on init */ + /* big enough to hold wolfcrypt md5, but check on init */ +#ifdef STM32_HASH + void* holder[(112 + WC_ASYNC_DEV_SIZE + sizeof(STM32_HASH_Context)) / sizeof(void*)]; +#else + void* holder[(112 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; +#endif } 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; @@ -32,11 +60,22 @@ typedef WOLFSSL_MD5_CTX MD5_CTX; #define MD5_Update wolfSSL_MD5_Update #define MD5_Final wolfSSL_MD5_Final +#ifdef OPENSSL_EXTRA_BSD + #define MD5Init wolfSSL_MD5_Init + #define MD5Update wolfSSL_MD5_Update + #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" */ + } /* extern "C" */ #endif #endif /* NO_MD5 */ #endif /* WOLFSSL_MD5_H_ */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/obj_mac.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/obj_mac.h new file mode 100644 index 000000000..6d0f90047 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/obj_mac.h @@ -0,0 +1,50 @@ +/* obj_mac.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 + */ + +/* obj_mac.h for openSSL */ + +#ifndef WOLFSSL_OBJ_MAC_H_ +#define WOLFSSL_OBJ_MAC_H_ +#ifdef __cplusplus + extern "C" { +#endif + +#define NID_sect163k1 721 +#define NID_sect163r1 722 +#define NID_sect163r2 723 +#define NID_sect193r1 724 +#define NID_sect193r2 725 +#define NID_sect233k1 726 +#define NID_sect233r1 727 +#define NID_sect239k1 728 +#define NID_sect283k1 729 +#define NID_sect283r1 730 +#define NID_sect409k1 731 +#define NID_sect409r1 732 +#define NID_sect571k1 733 +#define NID_sect571r1 734 + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_OBJ_MAC_H_ */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/objects.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/objects.h new file mode 100644 index 000000000..cd44b6628 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/objects.h @@ -0,0 +1,63 @@ +/* objects.h + * + * Copyright (C) 2006-2020 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_OBJECTS_H_ +#define WOLFSSL_OBJECTS_H_ + +#include +//#include +#ifndef OPENSSL_EXTRA_SSL_GUARD +#define OPENSSL_EXTRA_SSL_GUARD +#include +#endif /* OPENSSL_EXTRA_SSL_GUARD */ + +#ifdef __cplusplus + extern "C" { +#endif + +#define OBJ_nid2sn wolfSSL_OBJ_nid2sn +#define OBJ_obj2nid wolfSSL_OBJ_obj2nid +#define OBJ_sn2nid wolfSSL_OBJ_sn2nid +#define OBJ_nid2ln wolfSSL_OBJ_nid2ln +#define OBJ_ln2nid wolfSSL_OBJ_ln2nid +#define OBJ_txt2nid wolfSSL_OBJ_txt2nid +#define OBJ_txt2obj wolfSSL_OBJ_txt2obj +#define OBJ_nid2obj wolfSSL_OBJ_nid2obj +#define OBJ_obj2txt wolfSSL_OBJ_obj2txt +#define OBJ_cleanup wolfSSL_OBJ_cleanup +#define OBJ_cmp wolfSSL_OBJ_cmp +#define OBJ_create wolfSSL_OBJ_create +#define ASN1_OBJECT_free wolfSSL_ASN1_OBJECT_free + +/* not required for wolfSSL */ +#define OPENSSL_load_builtin_modules() + + +#define NID_ad_OCSP 178 +#define NID_ad_ca_issuers 179 + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_OBJECTS_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ocsp.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ocsp.h index 7463eec96..d880f23ca 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ocsp.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ocsp.h @@ -1 +1,82 @@ +/* ocsp.h + * + * Copyright (C) 2006-2020 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 + */ + /* 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_REVOKED_STATUS_NOSTATUS -1 + + +#define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 +#define OCSP_RESPONSE_STATUS_TRYLATER 3 + +#define V_OCSP_CERTSTATUS_GOOD 0 +#define V_OCSP_CERTSTATUS_REVOKED 1 +#define V_OCSP_CERTSTATUS_UNKNOWN 2 + +#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_response_create wolfSSL_OCSP_response_create + +#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 +#define OCSP_request_add1_nonce wolfSSL_OCSP_request_add1_nonce +#define OCSP_check_nonce wolfSSL_OCSP_check_nonce +#define OCSP_id_get0_info wolfSSL_OCSP_id_get0_info +#define OCSP_crl_reason_str wolfSSL_OCSP_crl_reason_str +#define OCSP_REQUEST_add_ext wolfSSL_OCSP_REQUEST_add_ext + +#define OCSP_CERTID_dup wolfSSL_OCSP_CERTID_dup + +#define i2d_OCSP_REQUEST_bio wolfSSL_i2d_OCSP_REQUEST_bio + +#endif /* HAVE_OCSP */ + +#endif /* WOLFSSL_OCSP_H_ */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/opensslv.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/opensslv.h index e13e992b8..1ec8db137 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/opensslv.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/opensslv.h @@ -1,3 +1,24 @@ +/* opensslv.h + * + * Copyright (C) 2006-2020 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 + */ + /* opensslv.h compatibility */ #ifndef WOLFSSL_OPENSSLV_H_ @@ -5,8 +26,20 @@ /* api version compatibility */ -#define OPENSSL_VERSION_NUMBER 0x0090410fL +#if defined(WOLFSSL_APACHE_HTTPD) + /* For Apache httpd, Use 1.1.0 compatibility */ + #define OPENSSL_VERSION_NUMBER 0x10100000L +#elif defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_OPENSSH) || defined(WOLFSSL_QT) + /* version number can be increased for Lighty after compatibility for ECDH + is added */ + #define OPENSSL_VERSION_NUMBER 0x1000100fL +#else + #define OPENSSL_VERSION_NUMBER 0x0090810fL +#endif +#define OPENSSL_VERSION_TEXT LIBWOLFSSL_VERSION_STRING +#define OPENSSL_VERSION 0 #endif /* header */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ossl_typ.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ossl_typ.h index 65b00c728..5e90ffe0c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ossl_typ.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ossl_typ.h @@ -1,2 +1,32 @@ -/* ossl_typ.h for openssl */ +/* ossl_typ.h + * + * Copyright (C) 2006-2020 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 + */ +/*! + \file wolfssl/openssl/ossl_typ.h +*/ + + +#ifndef WOLFSSL_OSSL_TYP_H_ +#define WOLFSSL_OSSL_TYP_H_ + +#include + +#endif /* !WOLFSSL_OSSL_TYP_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/pem.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/pem.h index 926e43f48..5d6029173 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/pem.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/pem.h @@ -1,5 +1,30 @@ +/* pem.h + * + * Copyright (C) 2006-2020 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 + */ + /* pem.h for openssl */ +/*! + \file wolfssl/openssl/pem.h +*/ + #ifndef WOLFSSL_PEM_H_ #define WOLFSSL_PEM_H_ @@ -8,34 +33,224 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { #endif +/* RSA */ +WOLFSSL_API +int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg); +WOLFSSL_API +WOLFSSL_RSA* wolfSSL_PEM_read_bio_RSAPrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_RSA**, + pem_password_cb* cb, + void* arg); -WOLFSSL_API int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, RSA* rsa, - const EVP_CIPHER* cipher, - unsigned char* passwd, int len, - pem_password_cb cb, void* arg); +WOLFSSL_API +int wolfSSL_PEM_write_bio_RSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa); -WOLFSSL_API int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, DSA* rsa, - const EVP_CIPHER* cipher, - unsigned char* passwd, int len, - pem_password_cb cb, void* arg); +WOLFSSL_API +WOLFSSL_RSA *wolfSSL_PEM_read_bio_RSA_PUBKEY(WOLFSSL_BIO* bio, + WOLFSSL_RSA** rsa, + pem_password_cb* cb, void *u); -WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, - WOLFSSL_EVP_PKEY**, pem_password_cb cb, void* arg); +WOLFSSL_API +WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio, + WOLFSSL_EC_GROUP** group, + pem_password_cb* cb, + void* pass); +WOLFSSL_API +int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + unsigned char **pem, int *plen); +#if !defined(NO_FILESYSTEM) +WOLFSSL_API +int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u); +WOLFSSL_API +WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(XFILE fp, WOLFSSL_RSA **x, + pem_password_cb *cb, void *u); +WOLFSSL_API +int wolfSSL_PEM_write_RSAPublicKey(XFILE fp, WOLFSSL_RSA *x); -#define PEM_write_bio_RSAPrivateKey wolfSSL_PEM_write_bio_RSAPrivateKey -#define PEM_write_bio_DSAPrivateKey wolfSSL_PEM_write_bio_DSAPrivateKey -#define PEM_read_bio_PrivateKey wolfSSL_PEM_read_bio_PrivateKey +WOLFSSL_API +int wolfSSL_PEM_write_RSA_PUBKEY(XFILE fp, WOLFSSL_RSA *x); +#endif /* NO_FILESYSTEM */ +/* DSA */ +WOLFSSL_API +int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_DSA* dsa, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg); + +WOLFSSL_API +WOLFSSL_DSA* wolfSSL_PEM_read_bio_DSAPrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_DSA** dsa, + pem_password_cb* cb,void *pass); + +WOLFSSL_API +WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSA_PUBKEY(WOLFSSL_BIO* bio,WOLFSSL_DSA** dsa, + pem_password_cb* cb, void *pass); + +WOLFSSL_API +int wolfSSL_PEM_write_bio_DSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa); + +WOLFSSL_API +int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + unsigned char **pem, int *plen); +#if !defined(NO_FILESYSTEM) +WOLFSSL_API +int wolfSSL_PEM_write_DSAPrivateKey(XFILE fp, WOLFSSL_DSA *dsa, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u); +WOLFSSL_API +int wolfSSL_PEM_write_DSA_PUBKEY(XFILE fp, WOLFSSL_DSA *x); +#endif /* NO_FILESYSTEM */ + +/* ECC */ +WOLFSSL_API +int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg); +WOLFSSL_API +WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_ECPrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EC_KEY** ec, + pem_password_cb* cb, + void *pass); +WOLFSSL_API +int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec); + +WOLFSSL_API +int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* key, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + unsigned char **pem, int *plen); +#if !defined(NO_FILESYSTEM) +WOLFSSL_API +int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *key, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u); +WOLFSSL_API +int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY *key); + +WOLFSSL_API +WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio, + WOLFSSL_EC_KEY** ec, + pem_password_cb* cb, void *pass); +#endif /* NO_FILESYSTEM */ + +/* EVP_KEY */ +WOLFSSL_API +WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY**, + pem_password_cb* cb, + void* arg); +WOLFSSL_API +WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_bio_PUBKEY(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY **key, + pem_password_cb *cb, void *pass); +WOLFSSL_API +int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, + const WOLFSSL_EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg); +WOLFSSL_API +int wolfSSL_PEM_write_bio_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key); + + +WOLFSSL_API +int wolfSSL_PEM_read_bio(WOLFSSL_BIO* bio, char **name, char **header, + unsigned char **data, long *len); +WOLFSSL_API +int wolfSSL_PEM_write_bio(WOLFSSL_BIO *bio, const char *name, + const char *header, const unsigned char *data, + long len); +#if !defined(NO_FILESYSTEM) +WOLFSSL_API +int wolfSSL_PEM_read(XFILE fp, char **name, char **header, unsigned char **data, + long *len); +WOLFSSL_API +int wolfSSL_PEM_write(XFILE fp, const char *name, const char *header, + const unsigned char *data, long len); +#endif + +#if !defined(NO_FILESYSTEM) +WOLFSSL_API +WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(XFILE fp, EVP_PKEY **x, + pem_password_cb *cb, void *u); +WOLFSSL_API +WOLFSSL_X509 *wolfSSL_PEM_read_X509(XFILE fp, WOLFSSL_X509 **x, + pem_password_cb *cb, void *u); +WOLFSSL_API +WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(XFILE fp, WOLFSSL_EVP_PKEY **x, + pem_password_cb *cb, void *u); + +WOLFSSL_API +int wolfSSL_PEM_write_X509(XFILE fp, WOLFSSL_X509 *x); +WOLFSSL_API +int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh); +#endif /* NO_FILESYSTEM */ + +#define PEM_read wolfSSL_PEM_read +#define PEM_read_bio wolfSSL_PEM_read_bio +#define PEM_write wolfSSL_PEM_write +#define PEM_write_bio wolfSSL_PEM_write_bio + +#define PEM_read_X509 wolfSSL_PEM_read_X509 +#define PEM_read_PrivateKey wolfSSL_PEM_read_PrivateKey +#define PEM_write_X509 wolfSSL_PEM_write_X509 +#define PEM_write_bio_PrivateKey wolfSSL_PEM_write_bio_PrivateKey +#define PEM_write_bio_PKCS8PrivateKey wolfSSL_PEM_write_bio_PKCS8PrivateKey + +/* DH */ +#define PEM_write_DHparams wolfSSL_PEM_write_DHparams +/* RSA */ +#define PEM_write_bio_RSAPrivateKey wolfSSL_PEM_write_bio_RSAPrivateKey +#define PEM_read_bio_RSAPrivateKey wolfSSL_PEM_read_bio_RSAPrivateKey +#define PEM_write_bio_RSA_PUBKEY wolfSSL_PEM_write_bio_RSA_PUBKEY +#define PEM_read_bio_RSA_PUBKEY wolfSSL_PEM_read_bio_RSA_PUBKEY +#define PEM_read_bio_ECPKParameters wolfSSL_PEM_read_bio_ECPKParameters +#define PEM_write_RSAPrivateKey wolfSSL_PEM_write_RSAPrivateKey +#define PEM_write_RSA_PUBKEY wolfSSL_PEM_write_RSA_PUBKEY +#define PEM_write_RSAPublicKey wolfSSL_PEM_write_RSAPublicKey +#define PEM_read_RSAPublicKey wolfSSL_PEM_read_RSAPublicKey +/* DSA */ +#define PEM_write_bio_DSAPrivateKey wolfSSL_PEM_write_bio_DSAPrivateKey +#define PEM_write_DSAPrivateKey wolfSSL_PEM_write_DSAPrivateKey +#define PEM_write_bio_DSA_PUBKEY wolfSSL_PEM_write_bio_DSA_PUBKEY +#define PEM_write_DSA_PUBKEY wolfSSL_PEM_write_DSA_PUBKEY +#define PEM_read_bio_DSAPrivateKey wolfSSL_PEM_read_bio_DSAPrivateKey +#define PEM_read_bio_DSA_PUBKEY wolfSSL_PEM_read_bio_DSA_PUBKEY +/* ECC */ +#define PEM_write_bio_ECPrivateKey wolfSSL_PEM_write_bio_ECPrivateKey +#define PEM_write_bio_EC_PUBKEY wolfSSL_PEM_write_bio_EC_PUBKEY +#define PEM_write_EC_PUBKEY wolfSSL_PEM_write_EC_PUBKEY +#define PEM_write_ECPrivateKey wolfSSL_PEM_write_ECPrivateKey +#define PEM_read_bio_ECPrivateKey wolfSSL_PEM_read_bio_ECPrivateKey +#define PEM_read_bio_EC_PUBKEY wolfSSL_PEM_read_bio_EC_PUBKEY +/* EVP_KEY */ +#define PEM_read_bio_PrivateKey wolfSSL_PEM_read_bio_PrivateKey +#define PEM_read_PUBKEY wolfSSL_PEM_read_PUBKEY +#define PEM_read_bio_PUBKEY wolfSSL_PEM_read_bio_PUBKEY +#define PEM_write_bio_PUBKEY wolfSSL_PEM_write_bio_PUBKEY #ifdef __cplusplus } /* extern "C" */ #endif - #endif /* WOLFSSL_PEM_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/pkcs12.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/pkcs12.h index 544b6f092..bcd994c57 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/pkcs12.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/pkcs12.h @@ -1,2 +1,49 @@ +/* pkcs12.h + * + * Copyright (C) 2006-2020 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 + */ + /* pkcs12.h for openssl */ + +#include +#include + +#ifndef WOLFSSL_PKCS12_COMPAT_H_ +#define WOLFSSL_PKCS12_COMPAT_H_ + +#define NID_pbe_WithSHA1AndDES_CBC 2 +#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 3 +#define NID_pbe_WithSHA1And128BitRC4 1 + +#define PKCS12_DEFAULT_ITER WC_PKCS12_ITT_DEFAULT + +/* wolfCrypt level does not make use of ssl.h */ +#define PKCS12 WC_PKCS12 +#define PKCS12_new wc_PKCS12_new +#define PKCS12_free wc_PKCS12_free + +/* wolfSSL level using structs from ssl.h and calls down to wolfCrypt */ +#define d2i_PKCS12_bio wolfSSL_d2i_PKCS12_bio +#define PKCS12_parse wolfSSL_PKCS12_parse +#define PKCS12_create wolfSSL_PKCS12_create +#define PKCS12_PBE_add wolfSSL_PKCS12_PBE_add + +#endif /* WOLFSSL_PKCS12_COMPAT_H_ */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/pkcs7.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/pkcs7.h new file mode 100644 index 000000000..94ddf2494 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/pkcs7.h @@ -0,0 +1,79 @@ +/* pkcs7.h + * + * Copyright (C) 2006-2020 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 + */ + +/* pkcs7.h for openSSL */ + + +#ifndef WOLFSSL_PKCS7_H_ +#define WOLFSSL_PKCS7_H_ + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(OPENSSL_ALL) && defined(HAVE_PKCS7) + +#define PKCS7_NOINTERN 0x0010 +#define PKCS7_NOVERIFY 0x0020 + + +typedef struct WOLFSSL_PKCS7 +{ + PKCS7 pkcs7; + unsigned char* data; + int len; +} WOLFSSL_PKCS7; + + +WOLFSSL_API PKCS7* wolfSSL_PKCS7_new(void); +WOLFSSL_API PKCS7_SIGNED* wolfSSL_PKCS7_SIGNED_new(void); +WOLFSSL_API void wolfSSL_PKCS7_free(PKCS7* p7); +WOLFSSL_API void wolfSSL_PKCS7_SIGNED_free(PKCS7_SIGNED* p7); +WOLFSSL_API PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, + int len); +WOLFSSL_API PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7); +WOLFSSL_API int wolfSSL_PKCS7_verify(PKCS7* p7, WOLFSSL_STACK* certs, + WOLFSSL_X509_STORE* store, WOLFSSL_BIO* in, WOLFSSL_BIO* out, int flags); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* p7, + WOLFSSL_STACK* certs, int flags); +WOLFSSL_API int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7); + +#define PKCS7_new wolfSSL_PKCS7_new +#define PKCS7_SIGNED_new wolfSSL_PKCS7_SIGNED_new +#define PKCS7_free wolfSSL_PKCS7_free +#define PKCS7_SIGNED_free wolfSSL_PKCS7_SIGNED_free +#define d2i_PKCS7 wolfSSL_d2i_PKCS7 +#define d2i_PKCS7_bio wolfSSL_d2i_PKCS7_bio +#define PKCS7_verify wolfSSL_PKCS7_verify +#define PKCS7_get0_signers wolfSSL_PKCS7_get0_signers +#define PEM_write_bio_PKCS7 wolfSSL_PEM_write_bio_PKCS7 + +#endif /* OPENSSL_ALL && HAVE_PKCS7 */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_PKCS7_H_ */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/rand.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/rand.h index c1fa62e1c..4b826f8f2 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/rand.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/rand.h @@ -1,4 +1,27 @@ +/* rand.h + * + * Copyright (C) 2006-2020 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 + */ + /* rand.h for openSSL */ #include +#include +#define RAND_set_rand_method wolfSSL_RAND_set_rand_method diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/rc4.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/rc4.h new file mode 100644 index 000000000..fc11e5a12 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/rc4.h @@ -0,0 +1,59 @@ +/* rc4.h + * + * Copyright (C) 2006-2020 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 + */ + + + +/* rc4.h defines mini des openssl compatibility layer + * + */ + +#ifndef WOLFSSL_RC4_COMPAT_H_ +#define WOLFSSL_RC4_COMPAT_H_ + +#include +#include /* included for size_t */ + +#ifdef __cplusplus + extern "C" { +#endif + +/* applications including wolfssl/openssl/rc4.h are expecting to have access to + * the size of RC4_KEY structures. */ +typedef struct WOLFSSL_RC4_KEY { + /* big enough for Arc4 from wolfssl/wolfcrypt/arc4.h */ + void* holder[(272 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; +} WOLFSSL_RC4_KEY; +typedef WOLFSSL_RC4_KEY RC4_KEY; + +WOLFSSL_API void wolfSSL_RC4_set_key(WOLFSSL_RC4_KEY* key, int len, + const unsigned char* data); +WOLFSSL_API void wolfSSL_RC4(WOLFSSL_RC4_KEY* key, size_t len, + const unsigned char* in, unsigned char* out); + +#define RC4 wolfSSL_RC4 +#define RC4_set_key wolfSSL_RC4_set_key + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_RC4_COMPAT_H_ */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ripemd.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ripemd.h index ef1578e91..3f1d26848 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ripemd.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ripemd.h @@ -1,3 +1,24 @@ +/* ripemd.h + * + * Copyright (C) 2006-2020 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 + */ + /* ripemd.h for openssl */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/rsa.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/rsa.h index 2db993b65..5445db196 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/rsa.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/rsa.h @@ -1,36 +1,100 @@ +/* rsa.h + * + * Copyright (C) 2006-2020 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 + */ + /* rsa.h for openSSL */ #ifndef WOLFSSL_RSA_H_ #define WOLFSSL_RSA_H_ -#include #include - +#include +#include #ifdef __cplusplus extern "C" { #endif +/* Padding types */ +#define RSA_PKCS1_PADDING 0 +#define RSA_PKCS1_OAEP_PADDING 1 +#define RSA_PKCS1_PSS_PADDING 2 +#define RSA_NO_PADDING 3 -enum { - RSA_PKCS1_PADDING = 1 - }; +/* Emulate OpenSSL flags */ +#define RSA_METHOD_FLAG_NO_CHECK (1 << 1) +#define RSA_FLAG_CACHE_PUBLIC (1 << 2) +#define RSA_FLAG_CACHE_PRIVATE (1 << 3) +#define RSA_FLAG_BLINDING (1 << 4) +#define RSA_FLAG_THREAD_SAFE (1 << 5) +#define RSA_FLAG_EXT_PKEY (1 << 6) +#define RSA_FLAG_NO_BLINDING (1 << 7) +#define RSA_FLAG_NO_CONSTTIME (1 << 8) -struct WOLFSSL_RSA { - WOLFSSL_BIGNUM* n; - WOLFSSL_BIGNUM* e; - WOLFSSL_BIGNUM* d; - WOLFSSL_BIGNUM* p; - WOLFSSL_BIGNUM* q; - WOLFSSL_BIGNUM* dmp1; /* dP */ - WOLFSSL_BIGNUM* dmq1; /* dQ */ - WOLFSSL_BIGNUM* iqmp; /* u */ +/* Salt length same as digest length */ +#define RSA_PSS_SALTLEN_DIGEST -1 +/* Old max salt length */ +#define RSA_PSS_SALTLEN_MAX_SIGN -2 +/* Max salt length */ +#define RSA_PSS_SALTLEN_MAX -3 + +typedef struct WOLFSSL_RSA_METHOD { + int flags; + char *name; +} WOLFSSL_RSA_METHOD; + +#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ +#define WOLFSSL_RSA_TYPE_DEFINED +typedef struct WOLFSSL_RSA { +#ifdef WC_RSA_BLINDING + WC_RNG* rng; /* for PrivateDecrypt blinding */ +#endif + WOLFSSL_BIGNUM* n; + WOLFSSL_BIGNUM* e; + WOLFSSL_BIGNUM* d; + WOLFSSL_BIGNUM* p; + WOLFSSL_BIGNUM* q; + WOLFSSL_BIGNUM* dmp1; /* dP */ + WOLFSSL_BIGNUM* dmq1; /* dQ */ + WOLFSSL_BIGNUM* iqmp; /* u */ + void* heap; void* internal; /* our RSA */ char inSet; /* internal set from external ? */ char exSet; /* external set from internal ? */ -}; + char ownRng; /* flag for if the rng should be free'd */ +#if defined(OPENSSL_EXTRA) + WOLFSSL_RSA_METHOD* meth; +#endif +#if defined(HAVE_EX_DATA) + WOLFSSL_CRYPTO_EX_DATA ex_data; /* external data */ +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + wolfSSL_Mutex refMutex; /* ref count mutex */ + int refCount; /* reference count */ +#endif +} WOLFSSL_RSA; +#endif +typedef WOLFSSL_RSA RSA; +typedef WOLFSSL_RSA_METHOD RSA_METHOD; WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSA_new(void); WOLFSSL_API void wolfSSL_RSA_free(WOLFSSL_RSA*); @@ -39,20 +103,52 @@ 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, +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, unsigned char* fr, +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_private_encrypt(int len, unsigned char* in, + unsigned char* out, WOLFSSL_RSA* 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_sign_ex(int type, const unsigned char* m, + unsigned int mLen, unsigned char* sigRet, + unsigned int* sigLen, WOLFSSL_RSA*, int); +WOLFSSL_API int wolfSSL_RSA_verify(int type, const unsigned char* m, + unsigned int mLen, const unsigned char* sig, + unsigned int sigLen, WOLFSSL_RSA*); +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); +WOLFSSL_API int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA*, const unsigned char*, int sz, int opt); +WOLFSSL_API WOLFSSL_RSA_METHOD *wolfSSL_RSA_meth_new(const char *name, int flags); +WOLFSSL_API void wolfSSL_RSA_meth_free(WOLFSSL_RSA_METHOD *meth); +WOLFSSL_API int wolfSSL_RSA_meth_set(WOLFSSL_RSA_METHOD *rsa, void* p); +WOLFSSL_API int wolfSSL_RSA_set_method(WOLFSSL_RSA *rsa, WOLFSSL_RSA_METHOD *meth); +WOLFSSL_API const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_method(const WOLFSSL_RSA *rsa); +WOLFSSL_API const WOLFSSL_RSA_METHOD* wolfSSL_RSA_get_default_method(void); + +WOLFSSL_API void wolfSSL_RSA_get0_key(const WOLFSSL_RSA *r, const WOLFSSL_BIGNUM **n, + const WOLFSSL_BIGNUM **e, const WOLFSSL_BIGNUM **d); +WOLFSSL_API int wolfSSL_RSA_set0_key(WOLFSSL_RSA *r, WOLFSSL_BIGNUM *n, WOLFSSL_BIGNUM *e, + WOLFSSL_BIGNUM *d); +WOLFSSL_API int wolfSSL_RSA_flags(const WOLFSSL_RSA *r); +WOLFSSL_API void wolfSSL_RSA_set_flags(WOLFSSL_RSA *r, int flags); + +WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSAPublicKey_dup(WOLFSSL_RSA *rsa); + +WOLFSSL_API void* wolfSSL_RSA_get_ex_data(const WOLFSSL_RSA *rsa, int idx); +WOLFSSL_API int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data); + + +#define WOLFSSL_RSA_LOAD_PRIVATE 1 +#define WOLFSSL_RSA_LOAD_PUBLIC 2 +#define WOLFSSL_RSA_F4 0x10001L #define RSA_new wolfSSL_RSA_new #define RSA_free wolfSSL_RSA_free @@ -62,14 +158,40 @@ WOLFSSL_API int wolfSSL_RSA_LoadDer(WOLFSSL_RSA*, const unsigned char*, int sz); #define RSA_blinding_on wolfSSL_RSA_blinding_on #define RSA_public_encrypt wolfSSL_RSA_public_encrypt #define RSA_private_decrypt wolfSSL_RSA_private_decrypt +#define RSA_private_encrypt wolfSSL_RSA_private_encrypt #define RSA_size wolfSSL_RSA_size #define RSA_sign wolfSSL_RSA_sign +#define RSA_verify wolfSSL_RSA_verify #define RSA_public_decrypt wolfSSL_RSA_public_decrypt +#define RSA_meth_new wolfSSL_RSA_meth_new +#define RSA_meth_free wolfSSL_RSA_meth_free +#define RSA_meth_set_pub_enc wolfSSL_RSA_meth_set +#define RSA_meth_set_pub_dec wolfSSL_RSA_meth_set +#define RSA_meth_set_priv_enc wolfSSL_RSA_meth_set +#define RSA_meth_set_priv_dec wolfSSL_RSA_meth_set +#define RSA_meth_set_init wolfSSL_RSA_meth_set +#define RSA_meth_set_finish wolfSSL_RSA_meth_set +#define RSA_meth_set0_app_data wolfSSL_RSA_meth_set +#define RSA_get_default_method wolfSSL_RSA_get_default_method +#define RSA_get_method wolfSSL_RSA_get_method +#define RSA_set_method wolfSSL_RSA_set_method +#define RSA_get0_key wolfSSL_RSA_get0_key +#define RSA_set0_key wolfSSL_RSA_set0_key +#define RSA_flags wolfSSL_RSA_flags +#define RSA_set_flags wolfSSL_RSA_set_flags + +#define RSAPublicKey_dup wolfSSL_RSAPublicKey_dup +#define RSA_get_ex_data wolfSSL_RSA_get_ex_data +#define RSA_set_ex_data wolfSSL_RSA_set_ex_data + +#define RSA_get0_key wolfSSL_RSA_get0_key + +#define RSA_F4 WOLFSSL_RSA_F4 #ifdef __cplusplus - } /* extern "C" */ + } /* extern "C" */ #endif #endif /* header */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/sha.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/sha.h index 7f8b0ebd6..e3a814717 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/sha.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/sha.h @@ -1,3 +1,24 @@ +/* sha.h + * + * Copyright (C) 2006-2020 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 + */ + /* sha.h for openssl */ @@ -5,6 +26,7 @@ #define WOLFSSL_SHA_H_ #include +#include #ifdef WOLFSSL_PREFIX #include "prefix_sha.h" @@ -16,17 +38,25 @@ 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 */ +#if defined(STM32_HASH) + void* holder[(112 + WC_ASYNC_DEV_SIZE + sizeof(STM32_HASH_Context)) / sizeof(void*)]; +#else + void* holder[(112 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; +#endif + #ifdef WOLF_CRYPTO_CB + void* cryptocb_holder[(sizeof(int) + sizeof(void*) + 4) / sizeof(void*)]; + #endif } 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 @@ -44,17 +74,50 @@ typedef WOLFSSL_SHA_CTX SHA_CTX; #define SHA1_Final wolfSSL_SHA1_Final -typedef struct WOLFSSL_SHA256_CTX { - int holder[28]; /* big enough to hold wolfcrypt sha, but check on init */ -} WOLFSSL_SHA256_CTX; +#ifdef WOLFSSL_SHA224 -WOLFSSL_API void wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX*); -WOLFSSL_API void wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX*, const void*, +/* Using ALIGN16 because when AES-NI is enabled digest and buffer in Sha256 + * struct are 16 byte aligned. Any dereference to those elements after casting + * to Sha224, is expected to also be 16 byte aligned addresses. */ +typedef struct WOLFSSL_SHA224_CTX { + /* big enough to hold wolfcrypt Sha224, but check on init */ + ALIGN16 void* holder[(272 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; +} WOLFSSL_SHA224_CTX; + +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_SHA256_Final(unsigned char*, WOLFSSL_SHA256_CTX*); +WOLFSSL_API int wolfSSL_SHA224_Final(unsigned char*, WOLFSSL_SHA224_CTX*); enum { - SHA256_DIGEST_LENGTH = 32 + SHA224_DIGEST_LENGTH = 28 +}; + + +typedef WOLFSSL_SHA224_CTX SHA224_CTX; + +#define SHA224_Init wolfSSL_SHA224_Init +#define SHA224_Update wolfSSL_SHA224_Update +#define SHA224_Final wolfSSL_SHA224_Final + +#endif /* WOLFSSL_SHA224 */ + + +/* Using ALIGN16 because when AES-NI is enabled digest and buffer in Sha256 + * struct are 16 byte aligned. Any dereference to those elements after casting + * to Sha256, is expected to also be 16 byte aligned addresses. */ +typedef struct WOLFSSL_SHA256_CTX { + /* big enough to hold wolfcrypt Sha256, but check on init */ + ALIGN16 void* holder[(272 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; +} WOLFSSL_SHA256_CTX; + +WOLFSSL_API int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX*); +WOLFSSL_API int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX*, const void*, + unsigned long); +WOLFSSL_API int wolfSSL_SHA256_Final(unsigned char*, WOLFSSL_SHA256_CTX*); + +enum { + SHA256_DIGEST_LENGTH = 32 }; @@ -63,21 +126,27 @@ typedef WOLFSSL_SHA256_CTX SHA256_CTX; #define SHA256_Init wolfSSL_SHA256_Init #define SHA256_Update wolfSSL_SHA256_Update #define SHA256_Final wolfSSL_SHA256_Final +#if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + /* SHA256 is only available in non-fips mode because of SHA256 enum in FIPS + * build. */ + #define SHA256 wolfSSL_SHA256 +#endif #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 */ + void* holder[(256 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; } 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 + SHA384_DIGEST_LENGTH = 48 }; @@ -86,22 +155,27 @@ typedef WOLFSSL_SHA384_CTX SHA384_CTX; #define SHA384_Init wolfSSL_SHA384_Init #define SHA384_Update wolfSSL_SHA384_Update #define SHA384_Final wolfSSL_SHA384_Final - +#if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + /* SHA384 is only available in non-fips mode because of SHA384 enum in FIPS + * build. */ + #define SHA384 wolfSSL_SHA384 +#endif #endif /* WOLFSSL_SHA384 */ #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 */ + void* holder[(288 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; } 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 + SHA512_DIGEST_LENGTH = 64 }; @@ -110,14 +184,18 @@ typedef WOLFSSL_SHA512_CTX SHA512_CTX; #define SHA512_Init wolfSSL_SHA512_Init #define SHA512_Update wolfSSL_SHA512_Update #define SHA512_Final wolfSSL_SHA512_Final - +#if defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + /* SHA512 is only available in non-fips mode because of SHA512 enum in FIPS + * build. */ + #define SHA512 wolfSSL_SHA512 +#endif #endif /* WOLFSSL_SHA512 */ #ifdef __cplusplus - } /* extern "C" */ + } /* extern "C" */ #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/sha3.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/sha3.h new file mode 100644 index 000000000..2039104d2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/sha3.h @@ -0,0 +1,150 @@ +/* sha3.h + * + * Copyright (C) 2006-2020 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 + */ + +/* sha3.h for openssl */ + + +#ifndef WOLFSSL_SHA3_H_ +#define WOLFSSL_SHA3_H_ + +#include +#include + +#ifdef WOLFSSL_PREFIX +#include "prefix_sha.h" +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +/* Using ALIGN16 because when AES-NI is enabled digest and buffer in Sha3 + * struct are 16 byte aligned. Any dereference to those elements after casting + * to Sha3 is expected to also be 16 byte aligned addresses. */ +struct WOLFSSL_SHA3_CTX { + /* big enough to hold wolfcrypt Sha3, but check on init */ + ALIGN16 void* holder[(424 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; +}; + +#ifndef WOLFSSL_NOSHA3_224 +typedef struct WOLFSSL_SHA3_CTX WOLFSSL_SHA3_224_CTX; + +WOLFSSL_API int wolfSSL_SHA3_224_Init(WOLFSSL_SHA3_224_CTX*); +WOLFSSL_API int wolfSSL_SHA3_224_Update(WOLFSSL_SHA3_224_CTX*, const void*, + unsigned long); +WOLFSSL_API int wolfSSL_SHA3_224_Final(unsigned char*, WOLFSSL_SHA3_224_CTX*); + +enum { + SHA3_224_DIGEST_LENGTH = 28 +}; + +typedef WOLFSSL_SHA3_224_CTX SHA3_224_CTX; + +#define SHA3_224_Init wolfSSL_SHA3_224_Init +#define SHA3_224_Update wolfSSL_SHA3_224_Update +#define SHA3_224_Final wolfSSL_SHA3_224_Final +#if defined(NO_OLD_WC_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + #define SHA3_224 wolfSSL_SHA3_224 +#endif +#endif /* WOLFSSL_NOSHA3_224 */ + + +#ifndef WOLFSSL_NOSHA3_256 +typedef struct WOLFSSL_SHA3_CTX WOLFSSL_SHA3_256_CTX; + + +WOLFSSL_API int wolfSSL_SHA3_256_Init(WOLFSSL_SHA3_256_CTX*); +WOLFSSL_API int wolfSSL_SHA3_256_Update(WOLFSSL_SHA3_256_CTX*, const void*, + unsigned long); +WOLFSSL_API int wolfSSL_SHA3_256_Final(unsigned char*, WOLFSSL_SHA3_256_CTX*); + +enum { + SHA3_256_DIGEST_LENGTH = 32 +}; + + +typedef WOLFSSL_SHA3_256_CTX SHA3_256_CTX; + +#define SHA3_256_Init wolfSSL_SHA3_256_Init +#define SHA3_256_Update wolfSSL_SHA3_256_Update +#define SHA3_256_Final wolfSSL_SHA3_256_Final +#if defined(NO_OLD_WC_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + #define SHA3_256 wolfSSL_SHA3_256 +#endif +#endif /* WOLFSSL_NOSHA3_256 */ + + +typedef struct WOLFSSL_SHA3_CTX WOLFSSL_SHA3_384_CTX; + +WOLFSSL_API int wolfSSL_SHA3_384_Init(WOLFSSL_SHA3_384_CTX*); +WOLFSSL_API int wolfSSL_SHA3_384_Update(WOLFSSL_SHA3_384_CTX*, const void*, + unsigned long); +WOLFSSL_API int wolfSSL_SHA3_384_Final(unsigned char*, WOLFSSL_SHA3_384_CTX*); + +enum { + SHA3_384_DIGEST_LENGTH = 48 +}; + +typedef WOLFSSL_SHA3_384_CTX SHA3_384_CTX; + +#define SHA3_384_Init wolfSSL_SHA3_384_Init +#define SHA3_384_Update wolfSSL_SHA3_384_Update +#define SHA3_384_Final wolfSSL_SHA3_384_Final +#if defined(NO_OLD_WC_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + #define SHA3_384 wolfSSL_SHA3_384 +#endif + + +#ifndef WOLFSSL_NOSHA3_512 + +typedef struct WOLFSSL_SHA3_CTX WOLFSSL_SHA3_512_CTX; + +WOLFSSL_API int wolfSSL_SHA3_512_Init(WOLFSSL_SHA3_512_CTX*); +WOLFSSL_API int wolfSSL_SHA3_512_Update(WOLFSSL_SHA3_512_CTX*, const void*, + unsigned long); +WOLFSSL_API int wolfSSL_SHA3_512_Final(unsigned char*, WOLFSSL_SHA3_512_CTX*); + +enum { + SHA3_512_DIGEST_LENGTH = 64 +}; + + +typedef WOLFSSL_SHA3_512_CTX SHA3_512_CTX; + +#define SHA3_512_Init wolfSSL_SHA3_512_Init +#define SHA3_512_Update wolfSSL_SHA3_512_Update +#define SHA3_512_Final wolfSSL_SHA3_512_Final +#if defined(NO_OLD_WC_NAMES) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + #define SHA3_512 wolfSSL_SHA3_512 +#endif +#endif /* WOLFSSL_NOSHA3_512 */ + + + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLFSSL_SHA3_H_ */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ssl.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ssl.h index 34d7948c3..e238cfcab 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ssl.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ssl.h @@ -1,8 +1,8 @@ /* ssl.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -15,12 +15,13 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * a with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* ssl.h defines wolfssl_openssl compatibility layer + +/* ssl.h defines wolfssl_openssl compatibility layer * */ @@ -29,7 +30,28 @@ #define WOLFSSL_OPENSSL_H_ /* wolfssl_openssl compatibility layer */ +#ifndef OPENSSL_EXTRA_SSL_GUARD +#define OPENSSL_EXTRA_SSL_GUARD #include +#endif /* OPENSSL_EXTRA_SSL_GUARD */ + +#include +#include +#include +#ifdef OPENSSL_EXTRA +#include +#endif + +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +#include +#include +#endif + +/* need MIN_CODE_E to determine wolfSSL error range */ +#include + +/* all NID_* values are in asn.h */ +#include #ifdef __cplusplus extern "C" { @@ -40,6 +62,11 @@ #undef X509_NAME #endif +#ifdef WOLFSSL_UTASKER + /* tcpip.h clashes */ + #undef ASN1_INTEGER +#endif + typedef WOLFSSL SSL; typedef WOLFSSL_SESSION SSL_SESSION; @@ -47,17 +74,17 @@ typedef WOLFSSL_METHOD SSL_METHOD; typedef WOLFSSL_CTX SSL_CTX; typedef WOLFSSL_X509 X509; +typedef WOLFSSL_X509 X509_REQ; typedef WOLFSSL_X509_NAME X509_NAME; +typedef WOLFSSL_X509_INFO X509_INFO; typedef WOLFSSL_X509_CHAIN X509_CHAIN; +typedef WOLFSSL_STACK EXTENDED_KEY_USAGE; + /* redeclare guard */ #define WOLFSSL_TYPES_DEFINED - -typedef WOLFSSL_EVP_PKEY EVP_PKEY; -typedef WOLFSSL_RSA RSA; -typedef WOLFSSL_DSA DSA; typedef WOLFSSL_BIO BIO; typedef WOLFSSL_BIO_METHOD BIO_METHOD; typedef WOLFSSL_CIPHER SSL_CIPHER; @@ -65,342 +92,1154 @@ 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_X509_PUBKEY X509_PUBKEY; +typedef WOLFSSL_X509_ALGOR X509_ALGOR; 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_ASN1_TYPE ASN1_TYPE; +typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; typedef WOLFSSL_dynlock_value CRYPTO_dynlock_value; +typedef WOLFSSL_BUF_MEM BUF_MEM; +typedef WOLFSSL_GENERAL_NAMES GENERAL_NAMES; +typedef WOLFSSL_GENERAL_NAME GENERAL_NAME; -#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_COMP SSL_COMP; 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; +typedef WOLFSSL_X509_VERIFY_PARAM X509_VERIFY_PARAM; -#define SSL_get_cipher_list(ctx,i) wolfSSL_get_cipher_list((i)) -#define SSL_get_cipher_name(ctx) wolfSSL_get_cipher((ctx)) +#define EVP_CIPHER_INFO EncryptedInfo + +#define STACK_OF(x) WOLFSSL_STACK +#define OPENSSL_STACK WOLFSSL_STACK +#define _STACK OPENSSL_STACK + +#define CONF_get1_default_config_file wolfSSL_CONF_get1_default_config_file +typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; + +#ifdef WOLFSSL_QT + #if defined(NO_WOLFSSL_MEMORY) + #define CRYPTO_free(xp) XFREE(xp, NULL, NULL); + #else + #define CRYPTO_free(xp) { if((xp)) wolfSSL_Free((xp));} + #endif +#else + #define CRYPTO_free XFREE +#endif + +#define CRYPTO_malloc XMALLOC +#define CRYPTO_EX_new WOLFSSL_CRYPTO_EX_new +#define CRYPTO_EX_dup WOLFSSL_CRYPTO_EX_dup +#define CRYPTO_EX_free WOLFSSL_CRYPTO_EX_free +#define CRYPTO_EX_DATA WOLFSSL_CRYPTO_EX_DATA + +/* depreciated */ +#define CRYPTO_thread_id wolfSSL_thread_id +#define CRYPTO_set_id_callback wolfSSL_set_id_callback + +#define CRYPTO_LOCK 0x01 +#define CRYPTO_UNLOCK 0x02 +#define CRYPTO_READ 0x04 +#define CRYPTO_WRITE 0x08 + +#define CRYPTO_set_locking_callback wolfSSL_set_locking_callback +#define CRYPTO_set_dynlock_create_callback wolfSSL_set_dynlock_create_callback +#define CRYPTO_set_dynlock_lock_callback wolfSSL_set_dynlock_lock_callback +#define CRYPTO_set_dynlock_destroy_callback wolfSSL_set_dynlock_destroy_callback +#define CRYPTO_num_locks wolfSSL_num_locks +#define CRYPTO_dynlock_value WOLFSSL_dynlock_value + +#define CRYPTO_cleanup_all_ex_data wolfSSL_cleanup_all_ex_data +#define set_ex_data wolfSSL_CRYPTO_set_ex_data +#define get_ex_data wolfSSL_CRYPTO_get_ex_data + +/* this function was used to set the default malloc, free, and realloc */ +#define CRYPTO_malloc_init() 0 /* CRYPTO_malloc_init is not needed */ +#define OPENSSL_malloc_init() 0 /* OPENSSL_malloc_init is not needed */ + +#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_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) - -/* @TODO */ -#define ERR_print_errors_fp(file) + wolfSSL_get_shared_ciphers((ctx),(buf),(len)) /* at the moment only returns ok */ -#define SSL_get_verify_result(ctx) X509_V_OK -#define SSL_get_verify_mode wolfSSL_SSL_get_mode -#define SSL_get_verify_depth wolfSSL_get_verify_depth -#define SSL_CTX_get_verify_mode wolfSSL_CTX_get_mode -#define SSL_CTX_get_verify_depth wolfSSL_CTX_get_verify_depth -#define SSL_get_certificate(ctx) 0 /* used to pass to get_privatekey */ +#define SSL_get_verify_result wolfSSL_get_verify_result +#define SSL_get_verify_mode wolfSSL_SSL_get_mode +#define SSL_get_verify_depth wolfSSL_get_verify_depth +#define SSL_CTX_get_verify_mode wolfSSL_CTX_get_verify_mode +#define SSL_CTX_get_verify_depth wolfSSL_CTX_get_verify_depth +#define SSL_get_certificate wolfSSL_get_certificate +#define SSL_use_certificate wolfSSL_use_certificate +#define SSL_use_certificate_ASN1 wolfSSL_use_certificate_ASN1 +#define d2i_PKCS8_PRIV_KEY_INFO_bio wolfSSL_d2i_PKCS8_PKEY_bio +#define d2i_PKCS8PrivateKey_bio wolfSSL_d2i_PKCS8PrivateKey_bio +#define PKCS8_PRIV_KEY_INFO_free wolfSSL_EVP_PKEY_free +#define d2i_PKCS12_fp wolfSSL_d2i_PKCS12_fp -#define SSLv3_server_method wolfSSLv3_server_method -#define SSLv3_client_method wolfSSLv3_client_method -#define TLSv1_server_method wolfTLSv1_server_method -#define TLSv1_client_method wolfTLSv1_client_method -#define TLSv1_1_server_method wolfTLSv1_1_server_method -#define TLSv1_1_client_method wolfTLSv1_1_client_method -#define TLSv1_2_server_method wolfTLSv1_2_server_method -#define TLSv1_2_client_method wolfTLSv1_2_client_method +#define d2i_PUBKEY wolfSSL_d2i_PUBKEY +#define d2i_PUBKEY_bio wolfSSL_d2i_PUBKEY_bio +#define d2i_PrivateKey wolfSSL_d2i_PrivateKey +#define d2i_AutoPrivateKey wolfSSL_d2i_AutoPrivateKey +#define i2d_PrivateKey wolfSSL_i2d_PrivateKey +#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 SSL_CTX_use_PrivateKey_ASN1 wolfSSL_CTX_use_PrivateKey_ASN1 + +#define SSLv23_method wolfSSLv23_method +#define SSLv23_client_method wolfSSLv23_client_method +#define SSLv2_client_method wolfSSLv2_client_method +#define SSLv2_server_method wolfSSLv2_server_method +#define SSLv3_server_method wolfSSLv3_server_method +#define SSLv3_client_method wolfSSLv3_client_method +#define TLS_client_method wolfTLS_client_method +#define TLS_server_method wolfTLS_server_method +#define TLSv1_method wolfTLSv1_method +#define TLSv1_server_method wolfTLSv1_server_method +#define TLSv1_client_method wolfTLSv1_client_method +#define TLSv1_1_method wolfTLSv1_1_method +#define TLSv1_1_server_method wolfTLSv1_1_server_method +#define TLSv1_1_client_method wolfTLSv1_1_client_method +#define TLSv1_2_method wolfTLSv1_2_method +#define TLSv1_2_server_method wolfTLSv1_2_server_method +#define TLSv1_2_client_method wolfTLSv1_2_client_method +#define TLSv1_3_method wolfTLSv1_3_method +#define TLSv1_3_server_method wolfTLSv1_3_server_method +#define TLSv1_3_client_method wolfTLSv1_3_client_method +#define TLS_method wolfSSLv23_method + +#define X509_FILETYPE_ASN1 SSL_FILETYPE_ASN1 + +#define X509_F_X509_CHECK_PRIVATE_KEY 128 #ifdef WOLFSSL_DTLS - #define DTLSv1_client_method wolfDTLSv1_client_method - #define DTLSv1_server_method wolfDTLSv1_server_method - #define DTLSv1_2_client_method wolfDTLSv1_2_client_method - #define DTLSv1_2_server_method wolfDTLSv1_2_server_method + #define DTLSv1_client_method wolfDTLSv1_client_method + #define DTLSv1_server_method wolfDTLSv1_server_method + #define DTLSv1_2_client_method wolfDTLSv1_2_client_method + #define DTLSv1_2_server_method wolfDTLSv1_2_server_method + #define DTLS_method wolfDTLS_method #endif #ifndef NO_FILESYSTEM - #define SSL_CTX_use_certificate_file wolfSSL_CTX_use_certificate_file - #define SSL_CTX_use_PrivateKey_file wolfSSL_CTX_use_PrivateKey_file - #define SSL_CTX_load_verify_locations wolfSSL_CTX_load_verify_locations + #define SSL_CTX_use_certificate_file wolfSSL_CTX_use_certificate_file + #define SSL_CTX_use_PrivateKey_file wolfSSL_CTX_use_PrivateKey_file +#ifdef WOLFSSL_APACHE_HTTPD + #define SSL_CTX_load_verify_locations(ctx,file,path) \ + wolfSSL_CTX_load_verify_locations_ex(ctx,file,path,\ + WOLFSSL_LOAD_FLAG_IGNORE_ERR) +#else + #define SSL_CTX_load_verify_locations wolfSSL_CTX_load_verify_locations +#endif #define SSL_CTX_use_certificate_chain_file wolfSSL_CTX_use_certificate_chain_file - #define SSL_CTX_use_RSAPrivateKey_file wolfSSL_CTX_use_RSAPrivateKey_file - - #define SSL_use_certificate_file wolfSSL_use_certificate_file - #define SSL_use_PrivateKey_file wolfSSL_use_PrivateKey_file - #define SSL_use_certificate_chain_file wolfSSL_use_certificate_chain_file - #define SSL_use_RSAPrivateKey_file wolfSSL_use_RSAPrivateKey_file + #define SSL_CTX_use_RSAPrivateKey_file wolfSSL_CTX_use_RSAPrivateKey_file + + #define SSL_use_certificate_file wolfSSL_use_certificate_file + #define SSL_use_PrivateKey_file wolfSSL_use_PrivateKey_file + #define SSL_use_certificate_chain_file wolfSSL_use_certificate_chain_file + #define SSL_use_RSAPrivateKey_file wolfSSL_use_RSAPrivateKey_file #endif -#define SSL_CTX_new wolfSSL_CTX_new -#define SSL_new wolfSSL_new -#define SSL_set_fd wolfSSL_set_fd -#define SSL_get_fd wolfSSL_get_fd -#define SSL_connect wolfSSL_connect -#define SSL_clear wolfSSL_clear +#define SSL_CTX_new(method) wolfSSL_CTX_new((WOLFSSL_METHOD*)(method)) +#ifdef OPENSSL_EXTRA +#define SSL_CTX_up_ref wolfSSL_CTX_up_ref +#endif +#define SSL_new wolfSSL_new +#define SSL_set_fd wolfSSL_set_fd +#define SSL_get_fd wolfSSL_get_fd +#define SSL_connect wolfSSL_connect +#define SSL_clear wolfSSL_clear +#define SSL_state wolfSSL_state -#define SSL_write wolfSSL_write -#define SSL_read wolfSSL_read -#define SSL_peek wolfSSL_peek -#define SSL_accept wolfSSL_accept -#define SSL_CTX_free wolfSSL_CTX_free -#define SSL_free wolfSSL_free -#define SSL_shutdown wolfSSL_shutdown +#define SSL_write wolfSSL_write +#define SSL_read wolfSSL_read +#define SSL_peek wolfSSL_peek +#define SSL_accept wolfSSL_accept +#define SSL_CTX_free wolfSSL_CTX_free +#define SSL_free wolfSSL_free +#define SSL_shutdown wolfSSL_shutdown +#define SSL_set_timeout wolfSSL_set_timeout -#define SSL_CTX_set_quiet_shutdown wolfSSL_CTX_set_quiet_shutdown -#define SSL_set_quiet_shutdown wolfSSL_set_quiet_shutdown -#define SSL_get_error wolfSSL_get_error -#define SSL_set_session wolfSSL_set_session -#define SSL_get_session wolfSSL_get_session -#define SSL_flush_sessions wolfSSL_flush_sessions -/* assume unlimited temporarly */ +#define SSL_CTX_set_quiet_shutdown wolfSSL_CTX_set_quiet_shutdown +#define SSL_set_quiet_shutdown wolfSSL_set_quiet_shutdown +#define SSL_get_error wolfSSL_get_error +#define SSL_set_session wolfSSL_set_session +#define SSL_get_session(x) wolfSSL_get_session((WOLFSSL*) (x)) +#define SSL_SESSION_get0_peer wolfSSL_SESSION_get0_peer +#define SSL_flush_sessions wolfSSL_flush_sessions +/* assume unlimited temporarily */ #define SSL_CTX_get_session_cache_mode(ctx) 0 -#define SSL_CTX_set_verify wolfSSL_CTX_set_verify -#define SSL_set_verify wolfSSL_set_verify -#define SSL_pending wolfSSL_pending -#define SSL_load_error_strings wolfSSL_load_error_strings -#define SSL_library_init wolfSSL_library_init -#define SSL_CTX_set_session_cache_mode wolfSSL_CTX_set_session_cache_mode -#define SSL_CTX_set_cipher_list wolfSSL_CTX_set_cipher_list -#define SSL_set_cipher_list wolfSSL_set_cipher_list +#define SSL_CTX_set_verify wolfSSL_CTX_set_verify +#define SSL_CTX_set_cert_verify_callback wolfSSL_CTX_set_cert_verify_callback +#define SSL_set_verify wolfSSL_set_verify +#define SSL_set_verify_result wolfSSL_set_verify_result +#define SSL_pending wolfSSL_pending +#define SSL_load_error_strings wolfSSL_load_error_strings +#define SSL_library_init wolfSSL_library_init +#define OpenSSL_add_ssl_algorithms wolfSSL_library_init +#define SSL_CTX_set_session_cache_mode wolfSSL_CTX_set_session_cache_mode +#define SSL_CTX_set_cipher_list wolfSSL_CTX_set_cipher_list +#define SSL_CTX_set_ciphersuites wolfSSL_CTX_set_cipher_list +#define SSL_set_cipher_list wolfSSL_set_cipher_list +/* wolfSSL does not support security levels */ +#define SSL_CTX_set_security_level(...) +/* wolfSSL does not support exporting keying material */ +#define SSL_export_keying_material(...) 0 -#define ERR_error_string wolfSSL_ERR_error_string -#define ERR_error_string_n wolfSSL_ERR_error_string_n -#define ERR_reason_error_string wolfSSL_ERR_reason_error_string +#define SSL_CTX_set1_groups_list wolfSSL_CTX_set1_groups_list +#define SSL_set1_groups_list wolfSSL_set1_groups_list -#define SSL_set_ex_data wolfSSL_set_ex_data -#define SSL_get_shutdown wolfSSL_get_shutdown -#define SSL_set_rfd wolfSSL_set_rfd -#define SSL_set_wfd wolfSSL_set_wfd -#define SSL_set_shutdown wolfSSL_set_shutdown -#define SSL_set_session_id_context wolfSSL_set_session_id_context -#define SSL_set_connect_state wolfSSL_set_connect_state -#define SSL_set_accept_state wolfSSL_set_accept_state -#define SSL_session_reused wolfSSL_session_reused -#define SSL_SESSION_free wolfSSL_SESSION_free -#define SSL_is_init_finished wolfSSL_is_init_finished +#define SSL_set_ex_data wolfSSL_set_ex_data +#define SSL_get_shutdown wolfSSL_get_shutdown +#define SSL_set_rfd wolfSSL_set_rfd +#define SSL_set_wfd wolfSSL_set_wfd +#define SSL_set_shutdown wolfSSL_set_shutdown +#define SSL_set_session_id_context wolfSSL_set_session_id_context +#define SSL_set_connect_state wolfSSL_set_connect_state +#define SSL_set_accept_state wolfSSL_set_accept_state +#define SSL_session_reused wolfSSL_session_reused +#define SSL_SESSION_dup wolfSSL_SESSION_dup +#define SSL_SESSION_free wolfSSL_SESSION_free +#define SSL_is_init_finished wolfSSL_is_init_finished -#define SSL_get_version wolfSSL_get_version -#define SSL_get_current_cipher wolfSSL_get_current_cipher -#define SSL_get_cipher wolfSSL_get_cipher -#define SSL_CIPHER_description wolfSSL_CIPHER_description -#define SSL_CIPHER_get_name wolfSSL_CIPHER_get_name -#define SSL_get1_session wolfSSL_get1_session +#define SSL_get_version wolfSSL_get_version +#define SSL_get_current_cipher wolfSSL_get_current_cipher -#define SSL_get_keyblock_size wolfSSL_get_keyblock_size -#define SSL_get_keys wolfSSL_get_keys +/* use wolfSSL_get_cipher_name for its return format */ +#define SSL_get_cipher wolfSSL_get_cipher_name +#define SSL_CIPHER_description wolfSSL_CIPHER_description +#define SSL_CIPHER_get_name wolfSSL_CIPHER_get_name +#define SSL_CIPHER_get_version wolfSSL_CIPHER_get_version +#define SSL_CIPHER_get_id wolfSSL_CIPHER_get_id +#define SSL_CIPHER_get_rfc_name wolfSSL_CIPHER_get_name +#define SSL_CIPHER_standard_name wolfSSL_CIPHER_get_name +#define SSL_get_cipher_by_value wolfSSL_get_cipher_by_value -#define X509_free wolfSSL_X509_free -#define OPENSSL_free wolfSSL_OPENSSL_free +#define SSL_get1_session wolfSSL_get1_session -#define OCSP_parse_url wolfSSL_OCSP_parse_url -#define SSLv23_client_method wolfSSLv23_client_method -#define SSLv2_client_method wolfSSLv2_client_method -#define SSLv2_server_method wolfSSLv2_server_method +#define SSL_get_keyblock_size wolfSSL_get_keyblock_size +#define SSL_get_keys wolfSSL_get_keys +#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 MD4_Init wolfSSL_MD4_Init -#define MD4_Update wolfSSL_MD4_Update -#define MD4_Final wolfSSL_MD4_Final +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + #define SSL_MODE_RELEASE_BUFFERS 0x00000010U + #define ASN1_BOOLEAN WOLFSSL_ASN1_BOOLEAN + #define X509_get_ext wolfSSL_X509_get_ext + #define X509_cmp wolfSSL_X509_cmp + #define X509_EXTENSION_get_object wolfSSL_X509_EXTENSION_get_object + #define X509_EXTENSION_get_critical wolfSSL_X509_EXTENSION_get_critical + #define X509_EXTENSION_get_data wolfSSL_X509_EXTENSION_get_data + #define X509_EXTENSION_new wolfSSL_X509_EXTENSION_new + #define X509_EXTENSION_free wolfSSL_X509_EXTENSION_free + #define X509_gmtime_adj wolfSSL_X509_gmtime_adj +#endif -#define BIO_new wolfSSL_BIO_new -#define BIO_free wolfSSL_BIO_free -#define BIO_free_all wolfSSL_BIO_free_all -#define BIO_read wolfSSL_BIO_read -#define BIO_write wolfSSL_BIO_write -#define BIO_push wolfSSL_BIO_push -#define BIO_pop wolfSSL_BIO_pop -#define BIO_flush wolfSSL_BIO_flush -#define BIO_pending wolfSSL_BIO_pending +#define DSA_dup_DH wolfSSL_DSA_dup_DH +/* wolfSSL does not support DSA as the cert public key */ +#define EVP_PKEY_get0_DSA(...) NULL +#define DSA_bits(...) 0 -#define BIO_get_mem_data wolfSSL_BIO_get_mem_data -#define BIO_new_mem_buf wolfSSL_BIO_new_mem_buf +#define i2d_X509_bio wolfSSL_i2d_X509_bio +#define d2i_X509_bio wolfSSL_d2i_X509_bio +#define d2i_X509_fp wolfSSL_d2i_X509_fp +#define i2d_X509 wolfSSL_i2d_X509 +#define d2i_X509 wolfSSL_d2i_X509 +#define PEM_read_bio_X509 wolfSSL_PEM_read_bio_X509 +#define PEM_read_bio_X509_CRL wolfSSL_PEM_read_bio_X509_CRL +#define PEM_read_bio_X509_AUX wolfSSL_PEM_read_bio_X509_AUX +#define PEM_read_X509 wolfSSL_PEM_read_X509 +#define PEM_X509_INFO_read_bio wolfSSL_PEM_X509_INFO_read_bio +#define PEM_write_bio_X509 wolfSSL_PEM_write_bio_X509 +#define PEM_write_bio_X509_AUX wolfSSL_PEM_write_bio_X509_AUX +#define PEM_X509_INFO_read_bio wolfSSL_PEM_X509_INFO_read_bio +#define i2d_PrivateKey wolfSSL_i2d_PrivateKey -#define BIO_f_buffer wolfSSL_BIO_f_buffer -#define BIO_set_write_buffer_size wolfSSL_BIO_set_write_buffer_size -#define BIO_f_ssl wolfSSL_BIO_f_ssl -#define BIO_new_socket wolfSSL_BIO_new_socket -#define SSL_set_bio wolfSSL_set_bio -#define BIO_eof wolfSSL_BIO_eof -#define BIO_set_ss wolfSSL_BIO_set_ss +#define i2d_X509_REQ wolfSSL_i2d_X509_REQ +#define X509_REQ_new wolfSSL_X509_REQ_new +#define X509_REQ_free wolfSSL_X509_REQ_free +#define X509_REQ_sign wolfSSL_X509_REQ_sign +#define X509_REQ_add_extensions wolfSSL_X509_REQ_add_extensions +#define X509_REQ_set_subject_name wolfSSL_X509_REQ_set_subject_name +#define X509_REQ_set_pubkey wolfSSL_X509_REQ_set_pubkey +#define PEM_write_bio_X509_REQ wolfSSL_PEM_write_bio_X509_REQ -#define BIO_s_mem wolfSSL_BIO_s_mem -#define BIO_f_base64 wolfSSL_BIO_f_base64 -#define BIO_set_flags wolfSSL_BIO_set_flags +#define X509_new wolfSSL_X509_new +#define X509_up_ref wolfSSL_X509_up_ref +#define X509_free wolfSSL_X509_free +#define X509_load_certificate_file wolfSSL_X509_load_certificate_file +#define X509_digest wolfSSL_X509_digest +#define X509_get_ext_count wolfSSL_X509_get_ext_count +#define X509_get_ext_d2i wolfSSL_X509_get_ext_d2i +#define X509_get_ext wolfSSL_X509_get_ext +#define X509_get_ext_by_NID wolfSSL_X509_get_ext_by_NID +#define X509_get_issuer_name wolfSSL_X509_get_issuer_name +#define X509_get_subject_name wolfSSL_X509_get_subject_name +#define X509_get_pubkey wolfSSL_X509_get_pubkey +#define X509_get0_pubkey wolfSSL_X509_get_pubkey +#define X509_get_notBefore wolfSSL_X509_get_notBefore +#define X509_get_notAfter wolfSSL_X509_get_notAfter +#define X509_get_serialNumber wolfSSL_X509_get_serialNumber +#define X509_get0_pubkey_bitstr wolfSSL_X509_get0_pubkey_bitstr +#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_get1_ocsp wolfSSL_X509_get1_ocsp +#ifndef WOLFSSL_HAPROXY +#define X509_get_version wolfSSL_X509_get_version +#endif +#define X509_get_signature_nid wolfSSL_X509_get_signature_nid +#define X509_set_subject_name wolfSSL_X509_set_subject_name +#define X509_set_issuer_name wolfSSL_X509_set_issuer_name +#define X509_set_pubkey wolfSSL_X509_set_pubkey +#define X509_set_notAfter wolfSSL_X509_set_notAfter +#define X509_set_notBefore wolfSSL_X509_set_notBefore +#define X509_set_serialNumber wolfSSL_X509_set_serialNumber +#define X509_set_version wolfSSL_X509_set_version +#define X509_sign wolfSSL_X509_sign +#define X509_print wolfSSL_X509_print +#define X509_print_ex wolfSSL_X509_print_ex +#define X509_verify_cert_error_string wolfSSL_X509_verify_cert_error_string +#define X509_verify_cert wolfSSL_X509_verify_cert +#define X509_check_private_key wolfSSL_X509_check_private_key +#define X509_check_ca wolfSSL_X509_check_ca +#define X509_check_host wolfSSL_X509_check_host +#define X509_email_free wolfSSL_X509_email_free +#define X509_check_issued wolfSSL_X509_check_issued +#define X509_dup wolfSSL_X509_dup -#define OpenSSL_add_all_algorithms wolfSSL_add_all_algorithms -#define SSLeay_add_ssl_algorithms wolfSSL_add_all_algorithms -#define SSLeay_add_all_algorithms wolfSSL_add_all_algorithms +#define X509_EXTENSION_get_object wolfSSL_X509_EXTENSION_get_object +#define X509_EXTENSION_get_data wolfSSL_X509_EXTENSION_get_data -#define RAND_screen wolfSSL_RAND_screen -#define RAND_file_name wolfSSL_RAND_file_name -#define RAND_write_file wolfSSL_RAND_write_file -#define RAND_load_file wolfSSL_RAND_load_file -#define RAND_egd wolfSSL_RAND_egd -#define RAND_seed wolfSSL_RAND_seed -#define RAND_add wolfSSL_RAND_add +#define sk_X509_new wolfSSL_sk_X509_new +#define sk_X509_new_null wolfSSL_sk_X509_new +#define sk_X509_num wolfSSL_sk_X509_num +#define sk_X509_value wolfSSL_sk_X509_value +#define sk_X509_shift wolfSSL_sk_X509_shift +#define sk_X509_push wolfSSL_sk_X509_push +#define sk_X509_pop wolfSSL_sk_X509_pop +#define sk_X509_pop_free wolfSSL_sk_X509_pop_free +#define sk_X509_dup wolfSSL_sk_X509_dup +#define sk_X509_free wolfSSL_sk_X509_free + +#define sk_X509_EXTENSION_num wolfSSL_sk_X509_EXTENSION_num +#define sk_X509_EXTENSION_value wolfSSL_sk_X509_EXTENSION_value +#define sk_X509_EXTENSION_new_null wolfSSL_sk_X509_EXTENSION_new_null +#define sk_X509_EXTENSION_pop_free wolfSSL_sk_X509_EXTENSION_pop_free +#define sk_X509_EXTENSION_push wolfSSL_sk_X509_EXTENSION_push +#define X509_EXTENSION_free wolfSSL_X509_EXTENSION_free + +#define X509_INFO_new wolfSSL_X509_INFO_new +#define X509_INFO_free wolfSSL_X509_INFO_free + +#define sk_X509_INFO_new_null wolfSSL_sk_X509_INFO_new_null +#define sk_X509_INFO_num wolfSSL_sk_X509_INFO_num +#define sk_X509_INFO_value wolfSSL_sk_X509_INFO_value +#define sk_X509_INFO_push wolfSSL_sk_X509_INFO_push +#define sk_X509_INFO_pop wolfSSL_sk_X509_INFO_pop +#define sk_X509_INFO_pop_free wolfSSL_sk_X509_INFO_pop_free +#define sk_X509_INFO_free wolfSSL_sk_X509_INFO_free + +#define i2d_X509_NAME wolfSSL_i2d_X509_NAME +#define X509_NAME_new wolfSSL_X509_NAME_new +#define X509_NAME_free wolfSSL_X509_NAME_free +#define X509_NAME_dup wolfSSL_X509_NAME_dup +#define X509_NAME_get_text_by_NID wolfSSL_X509_NAME_get_text_by_NID +#define X509_NAME_get_index_by_OBJ wolfSSL_X509_NAME_get_index_by_OBJ +#define X509_NAME_cmp wolfSSL_X509_NAME_cmp +#define X509_NAME_ENTRY_new wolfSSL_X509_NAME_ENTRY_new +#define X509_NAME_ENTRY_free wolfSSL_X509_NAME_ENTRY_free +#define X509_NAME_ENTRY_create_by_NID wolfSSL_X509_NAME_ENTRY_create_by_NID +#define X509_NAME_ENTRY_create_by_txt wolfSSL_X509_NAME_ENTRY_create_by_txt +#define X509_NAME_add_entry wolfSSL_X509_NAME_add_entry +#define X509_NAME_add_entry_by_txt wolfSSL_X509_NAME_add_entry_by_txt +#define X509_NAME_add_entry_by_NID wolfSSL_X509_NAME_add_entry_by_NID +#define X509_NAME_oneline wolfSSL_X509_NAME_oneline +#define X509_NAME_get_index_by_NID wolfSSL_X509_NAME_get_index_by_NID +#define X509_NAME_print_ex wolfSSL_X509_NAME_print_ex +#define X509_NAME_digest wolfSSL_X509_NAME_digest +#define X509_cmp_current_time wolfSSL_X509_cmp_current_time +#define X509_cmp_time wolfSSL_X509_cmp_time +#define X509_time_adj wolfSSL_X509_time_adj +#define X509_time_adj_ex wolfSSL_X509_time_adj_ex + +#define sk_ACCESS_DESCRIPTION_num wolfSSL_sk_ACCESS_DESCRIPTION_num +#define sk_ACCESS_DESCRIPTION_value wolfSSL_sk_ACCESS_DESCRIPTION_value + +#define sk_X509_NAME_new wolfSSL_sk_X509_NAME_new +#define sk_X509_NAME_push wolfSSL_sk_X509_NAME_push +#define sk_X509_NAME_find wolfSSL_sk_X509_NAME_find +#define sk_X509_NAME_set_cmp_func wolfSSL_sk_X509_NAME_set_cmp_func +#define sk_X509_NAME_num wolfSSL_sk_X509_NAME_num +#define sk_X509_NAME_value wolfSSL_sk_X509_NAME_value +#define sk_X509_NAME_pop wolfSSL_sk_X509_NAME_pop +#define sk_X509_NAME_pop_free wolfSSL_sk_X509_NAME_pop_free +#define sk_X509_NAME_free wolfSSL_sk_X509_NAME_free + +typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; + +#define X509_NAME_entry_count wolfSSL_X509_NAME_entry_count +#define X509_NAME_ENTRY_get_object wolfSSL_X509_NAME_ENTRY_get_object +#define X509_NAME_get_entry wolfSSL_X509_NAME_get_entry +#define X509_NAME_ENTRY_get_data wolfSSL_X509_NAME_ENTRY_get_data +#define X509_NAME_ENTRY_get_object wolfSSL_X509_NAME_ENTRY_get_object + +#define X509_V_FLAG_CRL_CHECK WOLFSSL_CRL_CHECK +#define X509_V_FLAG_CRL_CHECK_ALL WOLFSSL_CRL_CHECKALL + +#define X509_V_FLAG_USE_CHECK_TIME WOLFSSL_USE_CHECK_TIME +#define X509_V_FLAG_NO_CHECK_TIME WOLFSSL_NO_CHECK_TIME +#define X509_CHECK_FLAG_NO_WILDCARDS WOLFSSL_NO_WILDCARDS + +#define X509_STORE_CTX_get_current_cert wolfSSL_X509_STORE_CTX_get_current_cert +#define X509_STORE_CTX_set_verify_cb wolfSSL_X509_STORE_CTX_set_verify_cb +#define X509_STORE_CTX_new wolfSSL_X509_STORE_CTX_new +#define X509_STORE_CTX_free wolfSSL_X509_STORE_CTX_free +#define X509_STORE_CTX_get_chain wolfSSL_X509_STORE_CTX_get_chain +#define X509_STORE_CTX_get1_chain wolfSSL_X509_STORE_CTX_get1_chain +#define X509_STORE_CTX_get_error wolfSSL_X509_STORE_CTX_get_error +#define X509_STORE_CTX_get_error_depth wolfSSL_X509_STORE_CTX_get_error_depth +#define X509_STORE_CTX_init wolfSSL_X509_STORE_CTX_init +#define X509_STORE_CTX_cleanup wolfSSL_X509_STORE_CTX_cleanup +#define X509_STORE_CTX_set_error wolfSSL_X509_STORE_CTX_set_error +#define X509_STORE_CTX_set_error_depth wolfSSL_X509_STORE_CTX_set_error_depth +#define X509_STORE_CTX_get_ex_data wolfSSL_X509_STORE_CTX_get_ex_data +#define X509_STORE_CTX_set_ex_data wolfSSL_X509_STORE_CTX_set_ex_data +#define X509_STORE_CTX_set_depth wolfSSL_X509_STORE_CTX_set_depth +#define X509_STORE_CTX_verify_cb WOLFSSL_X509_STORE_CTX_verify_cb +#define X509_STORE_CTX_get0_current_issuer \ + wolfSSL_X509_STORE_CTX_get0_current_issuer +#define X509_STORE_CTX_get0_store wolfSSL_X509_STORE_CTX_get0_store +#define X509_STORE_CTX_get0_cert wolfSSL_X509_STORE_CTX_get0_cert + +#define X509_STORE_set_verify_cb(s, c) \ +wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_CTX_verify_cb)(c)) +#define X509_STORE_set_verify_cb_func(s, c) \ +wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_CTX_verify_cb)(c)) + + +#define X509_STORE_new wolfSSL_X509_STORE_new +#define X509_STORE_free wolfSSL_X509_STORE_free +#define X509_STORE_add_lookup wolfSSL_X509_STORE_add_lookup +#define X509_STORE_add_cert wolfSSL_X509_STORE_add_cert +#define X509_STORE_add_crl wolfSSL_X509_STORE_add_crl +#define X509_STORE_set_flags wolfSSL_X509_STORE_set_flags +#define X509_STORE_get1_certs wolfSSL_X509_STORE_get1_certs +#define X509_STORE_get_by_subject wolfSSL_X509_STORE_get_by_subject +#define X509_STORE_CTX_get1_issuer wolfSSL_X509_STORE_CTX_get1_issuer +#define X509_STORE_CTX_set_time wolfSSL_X509_STORE_CTX_set_time +#define X509_VERIFY_PARAM_set_hostflags wolfSSL_X509_VERIFY_PARAM_set_hostflags +#define X509_VERIFY_PARAM_set1_host wolfSSL_X509_VERIFY_PARAM_set1_host +#define X509_VERIFY_PARAM_set1_ip_asc wolfSSL_X509_VERIFY_PARAM_set1_ip_asc +#define X509_STORE_load_locations wolfSSL_X509_STORE_load_locations + +#define X509_LOOKUP_add_dir wolfSSL_X509_LOOKUP_add_dir +#define X509_LOOKUP_load_file wolfSSL_X509_LOOKUP_load_file +#define X509_LOOKUP_hash_dir wolfSSL_X509_LOOKUP_hash_dir +#define X509_LOOKUP_file wolfSSL_X509_LOOKUP_file + +#define d2i_X509_CRL wolfSSL_d2i_X509_CRL +#define d2i_X509_CRL_fp wolfSSL_d2i_X509_CRL_fp +#define PEM_read_X509_CRL wolfSSL_PEM_read_X509_CRL + +#define X509_CRL_free wolfSSL_X509_CRL_free +#define X509_CRL_get_lastUpdate wolfSSL_X509_CRL_get_lastUpdate +#define X509_CRL_get_nextUpdate wolfSSL_X509_CRL_get_nextUpdate +#define X509_CRL_verify wolfSSL_X509_CRL_verify +#define X509_CRL_get_REVOKED wolfSSL_X509_CRL_get_REVOKED + +#define X509_get_X509_PUBKEY wolfSSL_X509_get_X509_PUBKEY +#define X509_get0_tbs_sigalg wolfSSL_X509_get0_tbs_sigalg +#define X509_PUBKEY_get0_param wolfSSL_X509_PUBKEY_get0_param +#define X509_PUBKEY_get wolfSSL_X509_PUBKEY_get +#define X509_PUBKEY_set wolfSSL_X509_PUBKEY_set +#define X509_ALGOR_get0 wolfSSL_X509_ALGOR_get0 +#define X509_ALGOR_set0 wolfSSL_X509_ALGOR_set0 + +#define X509_ALGOR_new wolfSSL_X509_ALGOR_new +#define X509_ALGOR_free wolfSSL_X509_ALGOR_free +#define X509_PUBKEY_new wolfSSL_X509_PUBKEY_new +#define X509_PUBKEY_free wolfSSL_X509_PUBKEY_free + +#define sk_X509_REVOKED_num wolfSSL_sk_X509_REVOKED_num +#define sk_X509_REVOKED_value wolfSSL_sk_X509_REVOKED_value + +#define X509_OBJECT_free_contents wolfSSL_X509_OBJECT_free_contents +#define X509_subject_name_hash wolfSSL_X509_subject_name_hash + +#define X509_check_purpose(...) 0 + +#define OCSP_parse_url wolfSSL_OCSP_parse_url + +#define MD4_Init wolfSSL_MD4_Init +#define MD4_Update wolfSSL_MD4_Update +#define MD4_Final wolfSSL_MD4_Final + +#define BIO_new wolfSSL_BIO_new +#define BIO_free wolfSSL_BIO_free +#define BIO_vfree wolfSSL_BIO_vfree +#define BIO_free_all wolfSSL_BIO_free_all +#define BIO_nread0 wolfSSL_BIO_nread0 +#define BIO_nread wolfSSL_BIO_nread +#define BIO_read wolfSSL_BIO_read +#define BIO_nwrite0 wolfSSL_BIO_nwrite0 +#define BIO_nwrite wolfSSL_BIO_nwrite +#define BIO_write wolfSSL_BIO_write +#define BIO_push wolfSSL_BIO_push +#define BIO_pop wolfSSL_BIO_pop +#define BIO_flush wolfSSL_BIO_flush +#define BIO_pending wolfSSL_BIO_pending + +#define BIO_get_mem_data wolfSSL_BIO_get_mem_data +#define BIO_new_mem_buf wolfSSL_BIO_new_mem_buf + +#define BIO_f_buffer wolfSSL_BIO_f_buffer +#define BIO_set_write_buffer_size wolfSSL_BIO_set_write_buffer_size +#define BIO_f_ssl wolfSSL_BIO_f_ssl +#define BIO_new_socket wolfSSL_BIO_new_socket +#define SSL_set_bio wolfSSL_set_bio +#define BIO_set_ssl wolfSSL_BIO_set_ssl +#define BIO_eof wolfSSL_BIO_eof +#define BIO_set_ss wolfSSL_BIO_set_ss + +#define BIO_f_md wolfSSL_BIO_f_md +#define BIO_get_md_ctx wolfSSL_BIO_get_md_ctx +#define BIO_s_mem wolfSSL_BIO_s_mem +#define BIO_f_base64 wolfSSL_BIO_f_base64 +#define BIO_set_flags wolfSSL_BIO_set_flags +#define BIO_set_nbio wolfSSL_BIO_set_nbio + +#define SSLeay_add_ssl_algorithms wolfSSL_add_all_algorithms +#define SSLeay_add_all_algorithms wolfSSL_add_all_algorithms + +#define RAND_screen wolfSSL_RAND_screen +#define RAND_file_name wolfSSL_RAND_file_name +#define RAND_write_file wolfSSL_RAND_write_file +#define RAND_load_file wolfSSL_RAND_load_file +#define RAND_egd wolfSSL_RAND_egd +#define RAND_seed wolfSSL_RAND_seed +#define RAND_cleanup wolfSSL_RAND_Cleanup +#define RAND_add wolfSSL_RAND_add +#define RAND_poll wolfSSL_RAND_poll +#define RAND_status wolfSSL_RAND_status +#define RAND_bytes wolfSSL_RAND_bytes +#define RAND_pseudo_bytes wolfSSL_RAND_pseudo_bytes #define COMP_zlib wolfSSL_COMP_zlib #define COMP_rle wolfSSL_COMP_rle #define SSL_COMP_add_compression_method wolfSSL_COMP_add_compression_method -#define SSL_get_ex_new_index wolfSSL_get_ex_new_index +#define SSL_get_ex_new_index wolfSSL_get_ex_new_index +#define RSA_get_ex_new_index wolfSSL_get_ex_new_index -#define CRYPTO_set_id_callback wolfSSL_set_id_callback -#define CRYPTO_set_locking_callback wolfSSL_set_locking_callback -#define CRYPTO_set_dynlock_create_callback wolfSSL_set_dynlock_create_callback -#define CRYPTO_set_dynlock_lock_callback wolfSSL_set_dynlock_lock_callback -#define CRYPTO_set_dynlock_destroy_callback wolfSSL_set_dynlock_destroy_callback -#define CRYPTO_num_locks wolfSSL_num_locks +#define ASN1_BIT_STRING_new wolfSSL_ASN1_BIT_STRING_new +#define ASN1_BIT_STRING_free wolfSSL_ASN1_BIT_STRING_free +#define ASN1_BIT_STRING_get_bit wolfSSL_ASN1_BIT_STRING_get_bit +#define ASN1_BIT_STRING_set_bit wolfSSL_ASN1_BIT_STRING_set_bit -#define X509_STORE_CTX_get_current_cert wolfSSL_X509_STORE_CTX_get_current_cert -#define X509_STORE_CTX_get_error wolfSSL_X509_STORE_CTX_get_error -#define X509_STORE_CTX_get_error_depth wolfSSL_X509_STORE_CTX_get_error_depth +#define sk_ASN1_OBJECT_free wolfSSL_sk_ASN1_OBJECT_free -#define X509_NAME_oneline wolfSSL_X509_NAME_oneline -#define X509_get_issuer_name wolfSSL_X509_get_issuer_name -#define X509_get_subject_name wolfSSL_X509_get_subject_name -#define X509_verify_cert_error_string wolfSSL_X509_verify_cert_error_string +#define ASN1_TIME_free wolfSSL_ASN1_TIME_free +#define ASN1_TIME_adj wolfSSL_ASN1_TIME_adj +#define ASN1_TIME_print wolfSSL_ASN1_TIME_print +#define ASN1_TIME_to_generalizedtime wolfSSL_ASN1_TIME_to_generalizedtime +#define ASN1_GENERALIZEDTIME_print wolfSSL_ASN1_GENERALIZEDTIME_print +#define ASN1_GENERALIZEDTIME_free wolfSSL_ASN1_GENERALIZEDTIME_free -#define X509_LOOKUP_add_dir wolfSSL_X509_LOOKUP_add_dir -#define X509_LOOKUP_load_file wolfSSL_X509_LOOKUP_load_file -#define X509_LOOKUP_hash_dir wolfSSL_X509_LOOKUP_hash_dir -#define X509_LOOKUP_file wolfSSL_X509_LOOKUP_file +#define ASN1_tag2str wolfSSL_ASN1_tag2str -#define X509_STORE_add_lookup wolfSSL_X509_STORE_add_lookup -#define X509_STORE_new wolfSSL_X509_STORE_new -#define X509_STORE_get_by_subject wolfSSL_X509_STORE_get_by_subject -#define X509_STORE_CTX_init wolfSSL_X509_STORE_CTX_init -#define X509_STORE_CTX_cleanup wolfSSL_X509_STORE_CTX_cleanup +#define i2a_ASN1_INTEGER wolfSSL_i2a_ASN1_INTEGER +#define i2c_ASN1_INTEGER wolfSSL_i2c_ASN1_INTEGER +#define ASN1_INTEGER_new wolfSSL_ASN1_INTEGER_new +#define ASN1_INTEGER_free wolfSSL_ASN1_INTEGER_free +#define ASN1_INTEGER_cmp wolfSSL_ASN1_INTEGER_cmp +#define ASN1_INTEGER_get wolfSSL_ASN1_INTEGER_get +#define ASN1_INTEGER_set wolfSSL_ASN1_INTEGER_set +#define ASN1_INTEGER_to_BN wolfSSL_ASN1_INTEGER_to_BN -#define X509_CRL_get_lastUpdate wolfSSL_X509_CRL_get_lastUpdate -#define X509_CRL_get_nextUpdate wolfSSL_X509_CRL_get_nextUpdate +#define i2a_ASN1_OBJECT wolfSSL_i2a_ASN1_OBJECT -#define X509_get_pubkey wolfSSL_X509_get_pubkey -#define X509_CRL_verify wolfSSL_X509_CRL_verify -#define X509_STORE_CTX_set_error wolfSSL_X509_STORE_CTX_set_error -#define X509_OBJECT_free_contents wolfSSL_X509_OBJECT_free_contents -#define EVP_PKEY_free wolfSSL_EVP_PKEY_free -#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 -#define sk_X509_REVOKED_value wolfSSL_sk_X509_REVOKED_value -#define X509_get_notBefore(cert) (ASN1_TIME*)wolfSSL_X509_notBefore((cert)) -#define X509_get_notAfter(cert) (ASN1_TIME*)wolfSSL_X509_notAfter((cert)) +#define ASN1_STRING_data wolfSSL_ASN1_STRING_data +#define ASN1_STRING_get0_data wolfSSL_ASN1_STRING_data +#define ASN1_STRING_length wolfSSL_ASN1_STRING_length +#define ASN1_STRING_to_UTF8 wolfSSL_ASN1_STRING_to_UTF8 +#define ASN1_STRING_print_ex wolfSSL_ASN1_STRING_print_ex +#define ASN1_STRING_print(x, y) wolfSSL_ASN1_STRING_print ((WOLFSSL_BIO*)(x), (WOLFSSL_ASN1_STRING*)(y)) +#define d2i_DISPLAYTEXT wolfSSL_d2i_DISPLAYTEXT +#define ASN1_UTCTIME_pr wolfSSL_ASN1_UTCTIME_pr -#define X509_get_serialNumber wolfSSL_X509_get_serialNumber +#define ASN1_IA5STRING WOLFSSL_ASN1_STRING -#define ASN1_TIME_pr wolfSSL_ASN1_TIME_pr +#define ASN1_OCTET_STRING WOLFSSL_ASN1_STRING +#define ASN1_BOOLEAN WOLFSSL_ASN1_BOOLEAN -#define ASN1_INTEGER_cmp wolfSSL_ASN1_INTEGER_cmp -#define ASN1_INTEGER_get wolfSSL_ASN1_INTEGER_get +#define SSL_load_client_CA_file wolfSSL_load_client_CA_file -#define SSL_load_client_CA_file wolfSSL_load_client_CA_file - -#define SSL_CTX_set_client_CA_list wolfSSL_CTX_set_client_CA_list -#define X509_STORE_CTX_get_ex_data wolfSSL_X509_STORE_CTX_get_ex_data +#define SSL_CTX_get_client_CA_list wolfSSL_CTX_get_client_CA_list +#define SSL_CTX_set_client_CA_list wolfSSL_CTX_set_client_CA_list +#define SSL_CTX_set_client_cert_cb wolfSSL_CTX_set_client_cert_cb +#define SSL_CTX_set_cert_store wolfSSL_CTX_set_cert_store +#define SSL_CTX_get_cert_store(x) wolfSSL_CTX_get_cert_store ((WOLFSSL_CTX*) (x)) +#define SSL_get_client_CA_list wolfSSL_get_client_CA_list #define SSL_get_ex_data_X509_STORE_CTX_idx wolfSSL_get_ex_data_X509_STORE_CTX_idx -#define SSL_get_ex_data wolfSSL_get_ex_data +#define SSL_get_ex_data wolfSSL_get_ex_data #define SSL_CTX_set_default_passwd_cb_userdata wolfSSL_CTX_set_default_passwd_cb_userdata -#define SSL_CTX_set_default_passwd_cb wolfSSL_CTX_set_default_passwd_cb +#define SSL_CTX_set_default_passwd_cb wolfSSL_CTX_set_default_passwd_cb -#define SSL_CTX_set_timeout wolfSSL_CTX_set_timeout -#define SSL_CTX_set_info_callback wolfSSL_CTX_set_info_callback +#define SSL_CTX_set_timeout(ctx, to) \ + wolfSSL_CTX_set_timeout(ctx, (unsigned int) to) +#define SSL_CTX_set_info_callback wolfSSL_CTX_set_info_callback +#define SSL_CTX_set_alpn_protos wolfSSL_CTX_set_alpn_protos -#define ERR_peek_error wolfSSL_ERR_peek_error -#define ERR_GET_REASON wolfSSL_ERR_GET_REASON +#define SSL_alert_type_string wolfSSL_alert_type_string +#define SSL_alert_desc_string wolfSSL_alert_desc_string +#define SSL_state_string wolfSSL_state_string -#define SSL_alert_type_string wolfSSL_alert_type_string -#define SSL_alert_desc_string wolfSSL_alert_desc_string -#define SSL_state_string wolfSSL_state_string +#define RSA_free wolfSSL_RSA_free +#define RSA_generate_key wolfSSL_RSA_generate_key +#define SSL_CTX_set_tmp_rsa_callback wolfSSL_CTX_set_tmp_rsa_callback +#define RSA_print wolfSSL_RSA_print +#define RSA_bits wolfSSL_RSA_size +#define RSA_up_ref wolfSSL_RSA_up_ref +#define RSA_padding_add_PKCS1_PSS wolfSSL_RSA_padding_add_PKCS1_PSS +#define RSA_verify_PKCS1_PSS wolfSSL_RSA_verify_PKCS1_PSS -#define RSA_free wolfSSL_RSA_free -#define RSA_generate_key wolfSSL_RSA_generate_key -#define SSL_CTX_set_tmp_rsa_callback wolfSSL_CTX_set_tmp_rsa_callback +#define PEM_def_callback wolfSSL_PEM_def_callback -#define PEM_def_callback wolfSSL_PEM_def_callback - -#define SSL_CTX_sess_accept wolfSSL_CTX_sess_accept -#define SSL_CTX_sess_connect wolfSSL_CTX_sess_connect -#define SSL_CTX_sess_accept_good wolfSSL_CTX_sess_accept_good -#define SSL_CTX_sess_connect_good wolfSSL_CTX_sess_connect_good +#define SSL_CTX_sess_accept wolfSSL_CTX_sess_accept +#define SSL_CTX_sess_connect wolfSSL_CTX_sess_connect +#define SSL_CTX_sess_accept_good wolfSSL_CTX_sess_accept_good +#define SSL_CTX_sess_connect_good wolfSSL_CTX_sess_connect_good #define SSL_CTX_sess_accept_renegotiate wolfSSL_CTX_sess_accept_renegotiate #define SSL_CTX_sess_connect_renegotiate wolfSSL_CTX_sess_connect_renegotiate -#define SSL_CTX_sess_hits wolfSSL_CTX_sess_hits -#define SSL_CTX_sess_cb_hits wolfSSL_CTX_sess_cb_hits -#define SSL_CTX_sess_cache_full wolfSSL_CTX_sess_cache_full -#define SSL_CTX_sess_misses wolfSSL_CTX_sess_misses -#define SSL_CTX_sess_timeouts wolfSSL_CTX_sess_timeouts -#define SSL_CTX_sess_number wolfSSL_CTX_sess_number -#define SSL_CTX_sess_get_cache_size wolfSSL_CTX_sess_get_cache_size +#define SSL_CTX_sess_hits wolfSSL_CTX_sess_hits +#define SSL_CTX_sess_cb_hits wolfSSL_CTX_sess_cb_hits +#define SSL_CTX_sess_cache_full wolfSSL_CTX_sess_cache_full +#define SSL_CTX_sess_misses wolfSSL_CTX_sess_misses +#define SSL_CTX_sess_timeouts wolfSSL_CTX_sess_timeouts +#define SSL_CTX_sess_number wolfSSL_CTX_sess_number +#define SSL_CTX_sess_get_cache_size wolfSSL_CTX_sess_get_cache_size #define SSL_DEFAULT_CIPHER_LIST WOLFSSL_DEFAULT_CIPHER_LIST -#define RSA_F4 WOLFSSL_RSA_F4 #define SSL_CTX_set_psk_client_callback wolfSSL_CTX_set_psk_client_callback -#define SSL_set_psk_client_callback wolfSSL_set_psk_client_callback +#define SSL_set_psk_client_callback wolfSSL_set_psk_client_callback -#define SSL_get_psk_identity_hint wolfSSL_get_psk_identity_hint -#define SSL_get_psk_identity wolfSSL_get_psk_identity +#define SSL_get_psk_identity_hint wolfSSL_get_psk_identity_hint +#define SSL_get_psk_identity wolfSSL_get_psk_identity -#define SSL_CTX_use_psk_identity_hint wolfSSL_CTX_use_psk_identity_hint -#define SSL_use_psk_identity_hint wolfSSL_use_psk_identity_hint +#define SSL_CTX_use_psk_identity_hint wolfSSL_CTX_use_psk_identity_hint +#define SSL_use_psk_identity_hint wolfSSL_use_psk_identity_hint #define SSL_CTX_set_psk_server_callback wolfSSL_CTX_set_psk_server_callback -#define SSL_set_psk_server_callback wolfSSL_set_psk_server_callback +#define SSL_set_psk_server_callback wolfSSL_set_psk_server_callback -#define ERR_get_error_line_data wolfSSL_ERR_get_error_line_data +/* system file ints for ERR_put_error */ +#define SYS_F_ACCEPT WOLFSSL_SYS_ACCEPT +#define SYS_F_BIND WOLFSSL_SYS_BIND +#define SYS_F_CONNECT WOLFSSL_SYS_CONNECT +#define SYS_F_FOPEN WOLFSSL_SYS_FOPEN +#define SYS_F_FREAD WOLFSSL_SYS_FREAD +#define SYS_F_GETADDRINFO WOLFSSL_SYS_GETADDRINFO +#define SYS_F_GETSOCKOPT WOLFSSL_SYS_GETSOCKOPT +#define SYS_F_GETSOCKNAME WOLFSSL_SYS_GETSOCKNAME +#define SYS_F_OPENDIR WOLFSSL_SYS_OPENDIR +#define SYS_F_SETSOCKOPT WOLFSSL_SYS_SETSOCKOPT +#define SYS_F_SOCKET WOLFSSL_SYS_SOCKET +#define SYS_F_GETHOSTBYNAME WOLFSSL_SYS_GETHOSTBYNAME +#define SYS_F_GETNAMEINFO WOLFSSL_SYS_GETNAMEINFO +#define SYS_F_GETSERVBYNAME WOLFSSL_SYS_GETSERVBYNAME +#define SYS_F_IOCTLSOCKET WOLFSSL_SYS_IOCTLSOCKET +#define SYS_F_LISTEN WOLFSSL_SYS_LISTEN -#define ERR_get_error wolfSSL_ERR_get_error -#define ERR_clear_error wolfSSL_ERR_clear_error +#define ERR_GET_LIB wolfSSL_ERR_GET_LIB +#define ERR_GET_REASON wolfSSL_ERR_GET_REASON -#define RAND_status wolfSSL_RAND_status -#define RAND_bytes wolfSSL_RAND_bytes -#define SSLv23_server_method wolfSSLv23_server_method -#define SSL_CTX_set_options wolfSSL_CTX_set_options -#define SSL_CTX_check_private_key wolfSSL_CTX_check_private_key +#define ERR_put_error wolfSSL_ERR_put_error +#define ERR_peek_error wolfSSL_ERR_peek_error +#define ERR_peek_errors_fp wolfSSL_ERR_peek_errors_fp +#define ERR_peek_error_line_data wolfSSL_ERR_peek_error_line_data +#define ERR_peek_last_error wolfSSL_ERR_peek_last_error +#define ERR_peek_last_error_line wolfSSL_ERR_peek_last_error_line +#define ERR_get_error_line wolfSSL_ERR_get_error_line +#define ERR_get_error_line_data wolfSSL_ERR_get_error_line_data +#define ERR_get_error wolfSSL_ERR_get_error +#define ERR_print_errors_fp(file) wolfSSL_ERR_dump_errors_fp((file)) +#define ERR_print_errors_cb wolfSSL_ERR_print_errors_cb +#define ERR_print_errors wolfSSL_ERR_print_errors +#define ERR_clear_error wolfSSL_ERR_clear_error +#define ERR_free_strings wolfSSL_ERR_free_strings +#define ERR_remove_state wolfSSL_ERR_remove_state +#define ERR_remove_thread_state wolfSSL_ERR_remove_thread_state +#define ERR_error_string wolfSSL_ERR_error_string +#define ERR_error_string_n wolfSSL_ERR_error_string_n +#define ERR_reason_error_string wolfSSL_ERR_reason_error_string +#define ERR_load_BIO_strings wolfSSL_ERR_load_BIO_strings -#define ERR_free_strings wolfSSL_ERR_free_strings -#define ERR_remove_state wolfSSL_ERR_remove_state -#define EVP_cleanup wolfSSL_EVP_cleanup +#ifndef WOLFCRYPT_ONLY +#define PEMerr(func, reason) wolfSSL_ERR_put_error(ERR_LIB_PEM, \ + (func), (reason), __FILE__, __LINE__) +#else +#define PEMerr(func, reason) WOLFSSL_ERROR_LINE((reason), \ + NULL, __LINE__, __FILE__, NULL) +#endif -#define CRYPTO_cleanup_all_ex_data wolfSSL_cleanup_all_ex_data -#define SSL_CTX_set_mode wolfSSL_CTX_set_mode -#define SSL_CTX_get_mode wolfSSL_CTX_get_mode -#define SSL_CTX_set_default_read_ahead wolfSSL_CTX_set_default_read_ahead +#define SSLv23_server_method wolfSSLv23_server_method +#define SSL_CTX_set_options wolfSSL_CTX_set_options +#define SSL_CTX_get_options wolfSSL_CTX_get_options +#define SSL_CTX_clear_options wolfSSL_CTX_clear_options -#define SSL_CTX_sess_set_cache_size wolfSSL_CTX_sess_set_cache_size +#define SSL_CTX_check_private_key wolfSSL_CTX_check_private_key +#define SSL_check_private_key wolfSSL_check_private_key + +#define SSL_CTX_set_mode wolfSSL_CTX_set_mode +#define SSL_CTX_get_mode wolfSSL_CTX_get_mode +#define SSL_CTX_set_default_read_ahead wolfSSL_CTX_set_default_read_ahead + +#define SSL_CTX_sess_set_cache_size wolfSSL_CTX_sess_set_cache_size #define SSL_CTX_set_default_verify_paths wolfSSL_CTX_set_default_verify_paths -#define SSL_CTX_set_session_id_context wolfSSL_CTX_set_session_id_context -#define SSL_get_peer_certificate wolfSSL_get_peer_certificate +#define SSL_CTX_set_session_id_context wolfSSL_CTX_set_session_id_context +#define SSL_get_peer_certificate wolfSSL_get_peer_certificate +#define SSL_get_peer_cert_chain wolfSSL_get_peer_cert_chain -#define SSL_want_read wolfSSL_want_read -#define SSL_want_write wolfSSL_want_write +#define SSL_want wolfSSL_want +#define SSL_want_read wolfSSL_want_read +#define SSL_want_write wolfSSL_want_write -#define BIO_prf wolfSSL_BIO_prf -#define ASN1_UTCTIME_pr wolfSSL_ASN1_UTCTIME_pr +#define BIO_prf wolfSSL_BIO_prf -#define sk_num wolfSSL_sk_num -#define sk_value wolfSSL_sk_value +#define sk_num wolfSSL_sk_num +#define sk_ASN1_OBJECT_num wolfSSL_sk_num +#define sk_value wolfSSL_sk_value +#define sk_ASN1_OBJECT_value wolfSSL_sk_value -#define SSL_CTX_get_ex_data wolfSSL_CTX_get_ex_data -#define SSL_CTX_set_ex_data wolfSSL_CTX_set_ex_data -#define SSL_CTX_sess_set_get_cb wolfSSL_CTX_sess_set_get_cb -#define SSL_CTX_sess_set_new_cb wolfSSL_CTX_sess_set_new_cb -#define SSL_CTX_sess_set_remove_cb wolfSSL_CTX_sess_set_remove_cb +#define d2i_PKCS12_bio wolfSSL_d2i_PKCS12_bio +#define d2i_PKCS12_fp wolfSSL_d2i_PKCS12_fp +#define i2d_PKCS12_bio wolfSSL_i2d_PKCS12_bio -#define i2d_SSL_SESSION wolfSSL_i2d_SSL_SESSION -#define d2i_SSL_SESSION wolfSSL_d2i_SSL_SESSION -#define SSL_SESSION_set_timeout wolfSSL_SSL_SESSION_set_timeout -#define SSL_SESSION_get_timeout wolfSSL_SESSION_get_timeout -#define SSL_SESSION_get_time wolfSSL_SESSION_get_time -#define SSL_CTX_get_ex_new_index wolfSSL_CTX_get_ex_new_index +#define d2i_RSAPublicKey wolfSSL_d2i_RSAPublicKey +#define d2i_RSAPrivateKey wolfSSL_d2i_RSAPrivateKey +#define i2d_RSAPrivateKey wolfSSL_i2d_RSAPrivateKey +#define i2d_RSAPublicKey wolfSSL_i2d_RSAPublicKey + +#define SSL_CTX_get_ex_data wolfSSL_CTX_get_ex_data +#define SSL_CTX_set_ex_data wolfSSL_CTX_set_ex_data +#define SSL_CTX_sess_set_get_cb wolfSSL_CTX_sess_set_get_cb +#define SSL_CTX_sess_set_new_cb wolfSSL_CTX_sess_set_new_cb +#define SSL_CTX_sess_set_remove_cb wolfSSL_CTX_sess_set_remove_cb + +#define i2d_SSL_SESSION wolfSSL_i2d_SSL_SESSION +#define d2i_SSL_SESSION wolfSSL_d2i_SSL_SESSION +#define SSL_SESSION_set_timeout wolfSSL_SSL_SESSION_set_timeout +#define SSL_SESSION_get_timeout wolfSSL_SESSION_get_timeout +#define SSL_SESSION_get_time wolfSSL_SESSION_get_time + +#define SSL_CTX_get_ex_new_index wolfSSL_CTX_get_ex_new_index +#define PEM_read wolfSSL_PEM_read +#define PEM_write wolfSSL_PEM_write +#define PEM_get_EVP_CIPHER_INFO wolfSSL_PEM_get_EVP_CIPHER_INFO +#define PEM_do_header wolfSSL_PEM_do_header + +/*#if OPENSSL_API_COMPAT < 0x10100000L*/ +#define CONF_modules_free() +#define ENGINE_cleanup() +#define HMAC_CTX_cleanup wolfSSL_HMAC_cleanup +#define SSL_CTX_need_tmp_RSA(ctx) 0 +#define SSL_CTX_set_tmp_rsa(ctx,rsa) 1 +#define SSL_need_tmp_RSA(ssl) 0 +#define SSL_set_tmp_rsa(ssl,rsa) 1 +/*#endif*/ + +#define CONF_modules_unload(a) +#define CONF_get1_default_config_file wolfSSL_CONF_get1_default_config_file + +#define SSL_get_hit wolfSSL_session_reused /* yassl had set the default to be 500 */ -#define SSL_get_default_timeout(ctx) 500 +#define SSL_get_default_timeout(ctx) 500 +#define DTLSv1_get_timeout(ssl, timeleft) wolfSSL_DTLSv1_get_timeout((ssl), (WOLFSSL_TIMEVAL*)(timeleft)) +#define DTLSv1_handle_timeout wolfSSL_DTLSv1_handle_timeout +#define DTLSv1_set_initial_timeout_duration wolfSSL_DTLSv1_set_initial_timeout_duration + +#ifndef NO_WOLFSSL_STUB +#define SSL_CTX_set_current_time_cb(ssl, cb) ({ (void)ssl; (void)cb; }) +#endif + +#define SSL_CTX_use_certificate wolfSSL_CTX_use_certificate +#define SSL_CTX_add1_chain_cert wolfSSL_CTX_add1_chain_cert +#define SSL_CTX_use_PrivateKey wolfSSL_CTX_use_PrivateKey +#define BIO_read_filename wolfSSL_BIO_read_filename +#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 SHA1 wolfSSL_SHA1 + +#define SSL_dup_CA_list wolfSSL_dup_CA_list + +#define sk_X509_NAME_find wolfSSL_sk_X509_NAME_find + +enum { + GEN_DNS = 0x02, /* ASN_DNS_TYPE */ + GEN_EMAIL = 0x01, /* ASN_RFC822_TYPE */ + GEN_URI = 0x06, /* ASN_URI_TYPE */ + GEN_IPADD = 0x07, + GEN_RID = 0x08, /* Registered ID, not supported */ +}; + +#define PEM_read_bio_DHparams wolfSSL_PEM_read_bio_DHparams +#define PEM_read_bio_DSAparams wolfSSL_PEM_read_bio_DSAparams + +#if defined(OPENSSL_ALL) || defined(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 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 /* OPENSSL_ALL || WOLFSSL_HAPROXY */ +#define sk_SSL_CIPHER_dup wolfSSL_sk_SSL_CIPHER_dup +#define sk_SSL_CIPHER_free wolfSSL_sk_SSL_CIPHER_free +#define sk_SSL_CIPHER_find wolfSSL_sk_SSL_CIPHER_find + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \ + || defined(WOLFSSL_NGINX) +#include + +#define SSL_CTRL_CHAIN 88 +#define GEN_IPADD 7 +#define ERR_LIB_SSL 20 +#define SSL_R_SHORT_READ 10 +#define ERR_R_PEM_LIB 9 +#define V_ASN1_IA5STRING 22 +#define V_ASN1_UTF8STRING 12 +#define SSL_CTRL_MODE 33 + +#define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83 + +#define SSL_CTX_clear_chain_certs(ctx) SSL_CTX_set0_chain(ctx,NULL) +#define d2i_RSAPrivateKey_bio wolfSSL_d2i_RSAPrivateKey_bio +#define SSL_CTX_use_RSAPrivateKey wolfSSL_CTX_use_RSAPrivateKey +#define d2i_PrivateKey_bio wolfSSL_d2i_PrivateKey_bio +#define BIO_new_bio_pair wolfSSL_BIO_new_bio_pair +#define SSL_get_verify_callback wolfSSL_get_verify_callback + +#define SSL_set_mode(ssl,op) wolfSSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL) + +#define SSL_CTX_use_certificate_ASN1 wolfSSL_CTX_use_certificate_ASN1 +#define SSL_CTX_set0_chain(ctx,sk) \ + wolfSSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk)) +#define SSL_CTX_get_app_data(ctx) wolfSSL_CTX_get_ex_data(ctx,0) +#define SSL_CTX_set_app_data(ctx,arg) wolfSSL_CTX_set_ex_data(ctx,0, \ + (char *)(arg)) +#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY */ + +#define SSL_CTX_set_tmp_dh wolfSSL_CTX_set_tmp_dh + +#define TLSEXT_STATUSTYPE_ocsp 1 + +#define SSL_set_options wolfSSL_set_options +#define SSL_get_options wolfSSL_get_options +#define SSL_clear_options wolfSSL_clear_options +#define SSL_set_tmp_dh wolfSSL_set_tmp_dh +#define SSL_clear_num_renegotiations wolfSSL_clear_num_renegotiations +#define SSL_total_renegotiations wolfSSL_total_renegotiations +#define SSL_num_renegotiations wolfSSL_num_renegotiations +#define SSL_renegotiate wolfSSL_Rehandshake +#define SSL_get_secure_renegotiation_support wolfSSL_SSL_get_secure_renegotiation_support +#define SSL_set_tlsext_debug_arg wolfSSL_set_tlsext_debug_arg +#define SSL_set_tlsext_status_type wolfSSL_set_tlsext_status_type +#define SSL_set_tlsext_status_exts wolfSSL_set_tlsext_status_exts +#define SSL_get_tlsext_status_ids wolfSSL_get_tlsext_status_ids +#define SSL_set_tlsext_status_ids wolfSSL_set_tlsext_status_ids +#define SSL_get_tlsext_status_ocsp_res wolfSSL_get_tlsext_status_ocsp_resp +#define SSL_set_tlsext_status_ocsp_res wolfSSL_set_tlsext_status_ocsp_resp +#define SSL_set_tlsext_status_ocsp_resp wolfSSL_set_tlsext_status_ocsp_resp +#define SSL_get_tlsext_status_ocsp_resp wolfSSL_get_tlsext_status_ocsp_resp + +#define SSL_CTX_add_extra_chain_cert wolfSSL_CTX_add_extra_chain_cert +#define SSL_CTX_get_read_ahead wolfSSL_CTX_get_read_ahead +#define SSL_CTX_set_read_ahead wolfSSL_CTX_set_read_ahead +#define SSL_CTX_set_tlsext_status_arg wolfSSL_CTX_set_tlsext_status_arg +#define SSL_CTX_set_tlsext_opaque_prf_input_callback_arg \ + wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg +#define SSL_get_server_random wolfSSL_get_server_random +#define SSL_get_server_tmp_key wolfSSL_get_server_tmp_key + +#define SSL_CTX_set_min_proto_version wolfSSL_CTX_set_min_proto_version +#define SSL_CTX_set_max_proto_version wolfSSL_CTX_set_max_proto_version + +#define SSL_get_tlsext_status_exts wolfSSL_get_tlsext_status_exts + +#define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 11 +#define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12 +#define SSL_CTRL_SET_TMP_DH 3 +#define SSL_CTRL_SET_TMP_ECDH 4 +#define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71 + +#define SSL_CTRL_EXTRA_CHAIN_CERT 14 +#define SSL_CTRL_OPTIONS 32 + +#define SSL_CTRL_SET_SESS_CACHE_SIZE 42 +#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_GET_SESSION_REUSED 0 + +#define SSL_ctrl wolfSSL_ctrl +#define SSL_CTX_ctrl wolfSSL_CTX_ctrl +#define SSL_CTX_callback_ctrl wolfSSL_CTX_callback_ctrl + +#define SSL3_RANDOM_SIZE 32 /* same as RAN_LEN in internal.h */ + +#define SSL2_VERSION 0x0002 +#define SSL3_VERSION 0x0300 +#define TLS1_VERSION 0x0301 +#define TLS1_1_VERSION 0x0302 +#define TLS1_2_VERSION 0x0303 +#define TLS1_3_VERSION 0x0304 +#define DTLS1_VERSION 0xFEFF +#define DTLS1_2_VERSION 0xFEFD + +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(OPENSSL_EXTRA) \ + || defined(OPENSSL_ALL) +#include + +#define SSL23_ST_SR_CLNT_HELLO_A (0x210|0x2000) +#define SSL3_ST_SR_CLNT_HELLO_A (0x110|0x2000) + +#define SSL3_AD_BAD_CERTIFICATE bad_certificate +#define SSL_AD_BAD_CERTIFICATE SSL3_AD_BAD_CERTIFICATE + +#define ASN1_STRFLGS_ESC_MSB 4 + +#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 +#define sk_GENERAL_NAME_num wolfSSL_sk_GENERAL_NAME_num +#define SSL_CTX_get_options wolfSSL_CTX_get_options + +#define SSL_CTX_flush_sessions wolfSSL_flush_sessions +#define SSL_CTX_add_session wolfSSL_CTX_add_session +#define SSL_version(x) wolfSSL_version ((WOLFSSL*) (x)) +#define SSL_get_state wolfSSL_get_state +#define SSL_state_string_long wolfSSL_state_string_long + +#define GENERAL_NAME_new wolfSSL_GENERAL_NAME_new +#define GENERAL_NAME_free wolfSSL_GENERAL_NAME_free +#define sk_GENERAL_NAME_push wolfSSL_sk_GENERAL_NAME_push +#define sk_GENERAL_NAME_value wolfSSL_sk_GENERAL_NAME_value +#define SSL_SESSION_get_ex_data wolfSSL_SESSION_get_ex_data +#define SSL_SESSION_set_ex_data wolfSSL_SESSION_set_ex_data +#define SSL_SESSION_get_ex_new_index wolfSSL_SESSION_get_ex_new_index +#define SSL_SESSION_get_id wolfSSL_SESSION_get_id +#define SSL_SESSION_print wolfSSL_SESSION_print +#define sk_GENERAL_NAME_pop_free wolfSSL_sk_GENERAL_NAME_pop_free +#define sk_GENERAL_NAME_free wolfSSL_sk_GENERAL_NAME_free +#define sk_ASN1_OBJECT_pop_free wolfSSL_sk_ASN1_OBJECT_pop_free +#define GENERAL_NAME_free wolfSSL_GENERAL_NAME_free +#define GENERAL_NAMES_free wolfSSL_GENERAL_NAMES_free + +#define AUTHORITY_INFO_ACCESS_free wolfSSL_AUTHORITY_INFO_ACCESS_free +#define sk_ACCESS_DESCRIPTION_pop_free wolfSSL_sk_ACCESS_DESCRIPTION_pop_free +#define sk_ACCESS_DESCRIPTION_free wolfSSL_sk_ACCESS_DESCRIPTION_free +#define ACCESS_DESCRIPTION_free wolfSSL_ACCESS_DESCRIPTION_free + +#define SSL3_AL_FATAL 2 +#define SSL_TLSEXT_ERR_OK 0 +#define SSL_TLSEXT_ERR_ALERT_FATAL alert_fatal +#define SSL_TLSEXT_ERR_NOACK alert_warning +#define TLSEXT_NAMETYPE_host_name WOLFSSL_SNI_HOST_NAME + +#define SSL_set_tlsext_host_name wolfSSL_set_tlsext_host_name +#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_tlsext_servername_callback +#define SSL_CTX_set_tlsext_servername_arg wolfSSL_CTX_set_servername_arg + +#define PSK_MAX_PSK_LEN 256 +#define PSK_MAX_IDENTITY_LEN 128 +#define SSL_CTX_clear_options wolfSSL_CTX_clear_options + + +#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 + +#define SSL_CTX_set_msg_callback wolfSSL_CTX_set_msg_callback +#define SSL_set_msg_callback wolfSSL_set_msg_callback +#define SSL_CTX_set_msg_callback_arg wolfSSL_CTX_set_msg_callback_arg +#define SSL_set_msg_callback_arg wolfSSL_set_msg_callback_arg + +#define SSL_CTX_clear_extra_chain_certs wolfSSL_CTX_clear_extra_chain_certs + + +/* 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_FUNC(l) (int)((((unsigned long)l) >> 12L) & 0xfffL) + +#define PEM_F_PEM_DEF_CALLBACK 100 + +/* Avoid wolfSSL error code range */ +#define PEM_R_NO_START_LINE (-MIN_CODE_E + 1) +#define PEM_R_PROBLEMS_GETTING_PASSWORD (-MIN_CODE_E + 2) +#define PEM_R_BAD_PASSWORD_READ (-MIN_CODE_E + 3) +#define PEM_R_BAD_DECRYPT (-MIN_CODE_E + 4) + +#define ERR_LIB_PEM 9 +#define ERR_LIB_X509 10 +#define ERR_LIB_EVP 11 +#define ERR_LIB_ASN1 12 + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_ALL) || \ + defined(HAVE_LIGHTY) + +#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 +#define SSL_R_HTTPS_PROXY_REQUEST PARSE_ERROR +#define SSL_R_HTTP_REQUEST PARSE_ERROR +#define SSL_R_UNSUPPORTED_PROTOCOL VERSION_ERROR + + +#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 OPENSSL_memdup wolfSSL_OPENSSL_memdup +#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_in_connect_init wolfSSL_SSL_in_connect_init +#define SSL_get0_session wolfSSL_SSL_get0_session +#define SSL_CTX_set_tlsext_ticket_key_cb wolfSSL_CTX_set_tlsext_ticket_key_cb +#define SSL_CTX_set_tlsext_status_cb wolfSSL_CTX_set_tlsext_status_cb +#define SSL_CTX_get_extra_chain_certs wolfSSL_CTX_get_extra_chain_certs +#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_set_alpn_protos wolfSSL_set_alpn_protos +#define SSL_get0_next_proto_negotiated wolfSSL_get0_next_proto_negotiated +#define SSL_is_server wolfSSL_is_server + +#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || WOLFSSL_MYSQL_COMPATIBLE || + OPENSSL_ALL || HAVE_LIGHTY */ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) +#define SSL_CTX_set1_curves_list wolfSSL_CTX_set1_curves_list +#define SSL_set1_curves_list wolfSSL_set1_curves_list +#endif + +#ifdef OPENSSL_EXTRA +#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 +#define SSL_get_SSL_CTX wolfSSL_get_SSL_CTX +#define SSL_get0_param wolfSSL_get0_param + +#define ERR_NUM_ERRORS 16 +#define SN_pkcs9_emailAddress "Email" +#define LN_pkcs9_emailAddress "emailAddress" +#define NID_pkcs9_emailAddress 48 +#define OBJ_pkcs9_emailAddress 1L,2L,840L,113539L,1L,9L,1L + +#define SSL_get_rbio wolfSSL_SSL_get_rbio +#define SSL_get_wbio wolfSSL_SSL_get_wbio +#define SSL_do_handshake wolfSSL_SSL_do_handshake +#endif /* OPENSSL_EXTRA */ + +/* cipher suites for compatibility */ +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013) +#define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014) +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f) +#define TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8) +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009) +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a) +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b) +#define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9) + +#define X509_STORE_get0_objects wolfSSL_X509_STORE_get0_objects +#define sk_X509_OBJECT_num wolfSSL_sk_X509_OBJECT_num +#define sk_X509_OBJECT_value wolfSSL_sk_X509_OBJECT_value +#define sk_X509_OBJECT_delete wolfSSL_sk_X509_OBJECT_delete +#define X509_OBJECT_free wolfSSL_X509_OBJECT_free +#define X509_OBJECT_get_type(x) 0 + +#define OpenSSL_version(x) wolfSSL_lib_version() #ifdef __cplusplus } /* extern "C" */ #endif - #endif /* wolfSSL_openssl_h__ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ssl23.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ssl23.h new file mode 100644 index 000000000..fc3ddfb5f --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/ssl23.h @@ -0,0 +1 @@ +/* ssl23.h for openssl */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/stack.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/stack.h index 374c1fcda..13e2c5d45 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/stack.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/stack.h @@ -1,2 +1,59 @@ -/* stack.h for openssl */ +/* stack.h + * + * Copyright (C) 2006-2020 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 + */ +/* stack.h for openSSL */ + +#ifndef WOLFSSL_STACK_H_ +#define WOLFSSL_STACK_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +typedef void (*wolfSSL_sk_freefunc)(void *); + +WOLFSSL_API void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk, wolfSSL_sk_freefunc); +WOLFSSL_API void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK *); +WOLFSSL_API int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK *sk, void *data); +WOLFSSL_API void wolfSSL_sk_pop_free(WOLFSSL_STACK *st, void (*func) (void *)); +WOLFSSL_API void wolfSSL_sk_CONF_VALUE_free(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk); +WOLFSSL_API WOLFSSL_STACK *wolfSSL_sk_new_null(void); + +WOLFSSL_API int wolfSSL_sk_CIPHER_push(WOLFSSL_STACK *st,WOLFSSL_CIPHER *cipher); +WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_CIPHER_pop(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_new_cipher(void); + +#define OPENSSL_sk_free wolfSSL_sk_free +#define OPENSSL_sk_pop_free wolfSSL_sk_pop_free +#define OPENSSL_sk_new_null wolfSSL_sk_new_null +#define OPENSSL_sk_push wolfSSL_sk_push + +/* provides older OpenSSL API compatibility */ +#define sk_free OPENSSL_sk_free +#define sk_pop_free OPENSSL_sk_pop_free +#define sk_new_null OPENSSL_sk_new_null +#define sk_push OPENSSL_sk_push + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/tls1.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/tls1.h new file mode 100644 index 000000000..b73a8b0a2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/tls1.h @@ -0,0 +1,46 @@ +/* tls1.h + * + * Copyright (C) 2006-2020 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_OPENSSL_TLS1_H_ +#define WOLFSSL_OPENSSL_TLS1_H_ + +#ifndef TLS1_VERSION +#define TLS1_VERSION 0x0301 +#endif + +#ifndef TLS1_1_VERSION +#define TLS1_1_VERSION 0x0302 +#endif + +#ifndef TLS1_2_VERSION +#define TLS1_2_VERSION 0x0303 +#endif + +#ifndef TLS1_3_VERSION +#define TLS1_3_VERSION 0x0304 +#endif + +#ifndef TLS_MAX_VERSION +#define TLS_MAX_VERSION TLS1_3_VERSION +#endif + +#endif /* WOLFSSL_OPENSSL_TLS1_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/x509.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/x509.h index 9d1300284..77a8bca54 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/x509.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/x509.h @@ -1,3 +1,26 @@ /* x509.h for openssl */ #include +#include +#include +#include +#include + +/* wolfSSL_X509_print_ex flags */ +#define X509_FLAG_COMPAT (0UL) +#define X509_FLAG_NO_HEADER (1UL << 0) +#define X509_FLAG_NO_VERSION (1UL << 1) +#define X509_FLAG_NO_SERIAL (1UL << 2) +#define X509_FLAG_NO_SIGNAME (1UL << 3) +#define X509_FLAG_NO_ISSUER (1UL << 4) +#define X509_FLAG_NO_VALIDITY (1UL << 5) +#define X509_FLAG_NO_SUBJECT (1UL << 6) +#define X509_FLAG_NO_PUBKEY (1UL << 7) +#define X509_FLAG_NO_EXTENSIONS (1UL << 8) +#define X509_FLAG_NO_SIGDUMP (1UL << 9) +#define X509_FLAG_NO_AUX (1UL << 10) +#define X509_FLAG_NO_ATTRIBUTES (1UL << 11) +#define X509_FLAG_NO_IDS (1UL << 12) + +#define XN_FLAG_FN_SN 0 +#define XN_FLAG_SEP_CPLUS_SPC 2 diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/x509_vfy.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/x509_vfy.h new file mode 100644 index 000000000..86c995b43 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/x509_vfy.h @@ -0,0 +1,45 @@ +/* x509_vfy.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 + */ + +/* x509_vfy.h for openSSL */ + +#ifndef WOLFSSL_x509_vfy_H_ +#define WOLFSSL_x509_vfy_H_ + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + WOLFSSL_API int wolfSSL_X509_STORE_CTX_set_purpose(WOLFSSL_X509_STORE_CTX *ctx, int purpose); +#endif + +#ifdef WOLFSSL_QT + #define X509_STORE_CTX_set_purpose wolfSSL_X509_STORE_CTX_set_purpose +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* WOLFSSL_x509_vfy_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/x509v3.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/x509v3.h index 77828a33b..782578bdd 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/x509v3.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/openssl/x509v3.h @@ -1,2 +1,116 @@ -/* x509v3.h for openssl */ +/* x509v3.h + * + * Copyright (C) 2006-2020 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 + */ +/* x509v3.h for openSSL */ + +#ifndef WOLFSSL_x509v3_H +#define WOLFSSL_x509v3_H + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#define X509_PURPOSE_SSL_CLIENT 0 +#define X509_PURPOSE_SSL_SERVER 1 + +#define NS_SSL_CLIENT 0 +#define NS_SSL_SERVER 1 + +/* Forward reference */ + +typedef void *(*X509V3_EXT_D2I)(void *, const unsigned char **, long); +typedef STACK_OF(CONF_VALUE) *(*X509V3_EXT_I2V) ( + struct WOLFSSL_v3_ext_method *method, + void *ext, STACK_OF(CONF_VALUE) *extlist); +typedef char *(*X509V3_EXT_I2S)(struct WOLFSSL_v3_ext_method *method, void *ext); +typedef int (*X509V3_EXT_I2R) (struct WOLFSSL_v3_ext_method *method, + void *ext, BIO *out, int indent); +typedef struct WOLFSSL_v3_ext_method X509V3_EXT_METHOD; + +struct WOLFSSL_v3_ext_method { + int ext_nid; + int ext_flags; + void *usr_data; + X509V3_EXT_D2I d2i; + X509V3_EXT_I2V i2v; + X509V3_EXT_I2S i2s; + X509V3_EXT_I2R i2r; +}; + +struct WOLFSSL_X509_EXTENSION { + WOLFSSL_ASN1_OBJECT *obj; + WOLFSSL_ASN1_BOOLEAN crit; + WOLFSSL_ASN1_STRING value; + WOLFSSL_v3_ext_method ext_method; + WOLFSSL_STACK* ext_sk; /* For extension specific data */ +}; + +#define WOLFSSL_ASN1_BOOLEAN int +#define GEN_OTHERNAME 0 +#define GEN_EMAIL 1 +#define GEN_DNS 2 +#define GEN_X400 3 +#define GEN_DIRNAME 4 +#define GEN_EDIPARTY 5 +#define GEN_URI 6 +#define GEN_IPADD 7 +#define GEN_RID 8 + +#define GENERAL_NAME WOLFSSL_GENERAL_NAME + +#define X509V3_CTX WOLFSSL_X509V3_CTX + +typedef struct WOLFSSL_AUTHORITY_KEYID AUTHORITY_KEYID; +typedef struct WOLFSSL_BASIC_CONSTRAINTS BASIC_CONSTRAINTS; +typedef struct WOLFSSL_ACCESS_DESCRIPTION ACCESS_DESCRIPTION; +typedef WOLF_STACK_OF(WOLFSSL_ACCESS_DESCRIPTION) WOLFSSL_AUTHORITY_INFO_ACCESS; + +WOLFSSL_API void wolfSSL_BASIC_CONSTRAINTS_free(WOLFSSL_BASIC_CONSTRAINTS *bc); +WOLFSSL_API void wolfSSL_AUTHORITY_KEYID_free(WOLFSSL_AUTHORITY_KEYID *id); +WOLFSSL_API const WOLFSSL_v3_ext_method* wolfSSL_X509V3_EXT_get( + WOLFSSL_X509_EXTENSION* ex); +WOLFSSL_API void* wolfSSL_X509V3_EXT_d2i(WOLFSSL_X509_EXTENSION* ex); +WOLFSSL_API char* wolfSSL_i2s_ASN1_STRING(WOLFSSL_v3_ext_method *method, + const WOLFSSL_ASN1_STRING *s); +WOLFSSL_API int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, + WOLFSSL_X509_EXTENSION *ext, unsigned long flag, int indent); + +#define BASIC_CONSTRAINTS_free wolfSSL_BASIC_CONSTRAINTS_free +#define AUTHORITY_KEYID_free wolfSSL_AUTHORITY_KEYID_free +#define SSL_CTX_get_cert_store(x) wolfSSL_CTX_get_cert_store ((WOLFSSL_CTX*) (x)) +#define ASN1_INTEGER WOLFSSL_ASN1_INTEGER +#define ASN1_OCTET_STRING WOLFSSL_ASN1_STRING +#define X509V3_EXT_get wolfSSL_X509V3_EXT_get +#define X509V3_EXT_d2i wolfSSL_X509V3_EXT_d2i +#define i2s_ASN1_OCTET_STRING wolfSSL_i2s_ASN1_STRING +#define X509V3_EXT_print wolfSSL_X509V3_EXT_print +#define X509V3_EXT_conf_nid wolfSSL_X509V3_EXT_conf_nid +#define X509V3_set_ctx wolfSSL_X509V3_set_ctx +#define X509V3_set_ctx_nodb wolfSSL_X509V3_set_ctx_nodb + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/options.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/options.h index d1e362c20..0a5f45c23 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/options.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/options.h @@ -1,8 +1,8 @@ /* options.h.in * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,12 +16,15 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* default blank options for autoconf */ -#pragma once +#ifndef WOLFSSL_OPTIONS_H +#define WOLFSSL_OPTIONS_H + #ifdef __cplusplus extern "C" { @@ -32,3 +35,6 @@ extern "C" { } #endif + +#endif /* WOLFSSL_OPTIONS_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/options.h.in b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/options.h.in index d1e362c20..0a5f45c23 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/options.h.in +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/options.h.in @@ -1,8 +1,8 @@ /* options.h.in * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,12 +16,15 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* default blank options for autoconf */ -#pragma once +#ifndef WOLFSSL_OPTIONS_H +#define WOLFSSL_OPTIONS_H + #ifdef __cplusplus extern "C" { @@ -32,3 +35,6 @@ extern "C" { } #endif + +#endif /* WOLFSSL_OPTIONS_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/sniffer.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/sniffer.h index a14f883ff..519518f3c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/sniffer.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/sniffer.h @@ -1,8 +1,8 @@ /* sniffer.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLFSSL_SNIFFER_H #define WOLFSSL_SNIFFER_H @@ -40,10 +41,10 @@ extern "C" { #endif -/* @param typeK: (formerly keyType) was shadowing a global declaration in +/* @param typeK: (formerly keyType) was shadowing a global declaration in * wolfssl/wolfcrypt/asn.h line 175 */ -WOLFSSL_API +WOLFSSL_API SSL_SNIFFER_API int ssl_SetPrivateKey(const char* address, int port, const char* keyFile, int typeK, const char* password, char* error); @@ -54,19 +55,37 @@ SSL_SNIFFER_API int ssl_SetNamedPrivateKey(const char* name, const char* keyFile, int typeK, const char* password, char* error); -WOLFSSL_API +WOLFSSL_API SSL_SNIFFER_API int ssl_DecodePacket(const unsigned char* packet, int length, - unsigned char* data, char* error); + unsigned char** data, char* error); -WOLFSSL_API +WOLFSSL_API +SSL_SNIFFER_API int ssl_FreeDecodeBuffer(unsigned char** data, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_FreeZeroDecodeBuffer(unsigned char** data, int sz, + char* error); + +WOLFSSL_API SSL_SNIFFER_API int ssl_Trace(const char* traceFile, char* error); - - + +WOLFSSL_API +SSL_SNIFFER_API int ssl_EnableRecovery(int onOff, int maxMemory, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_GetSessionStats(unsigned int* active, + unsigned int* total, + unsigned int* peak, + unsigned int* maxSessions, + unsigned int* missedData, + unsigned int* reassemblyMemory, + char* error); + WOLFSSL_API void ssl_InitSniffer(void); - + WOLFSSL_API void ssl_FreeSniffer(void); - + /* ssl_SetPrivateKey typeKs */ enum { FILETYPE_PEM = 1, @@ -74,6 +93,126 @@ enum { }; +/* + * New Sniffer API that provides read-only access to the TLS and cipher + * information associated with the SSL session. + */ + +typedef struct SSLInfo +{ + unsigned char isValid; + /* indicates if the info in this struct is valid: 0 = no, 1 = yes */ + unsigned char protocolVersionMajor; /* SSL Version: major */ + unsigned char protocolVersionMinor; /* SSL Version: minor */ + unsigned char serverCipherSuite0; /* first byte, normally 0 */ + unsigned char serverCipherSuite; /* second byte, actual suite */ + unsigned char serverCipherSuiteName[256]; + /* cipher name, e.g., "TLS_RSA_..." */ + unsigned char serverNameIndication[128]; + unsigned int keySize; +} SSLInfo; + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_DecodePacketWithSessionInfo( + const unsigned char* packet, int length, + unsigned char** data, SSLInfo* sslInfo, char* error); + +typedef void (*SSLConnCb)(const void* session, SSLInfo* info, void* ctx); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetConnectionCb(SSLConnCb cb); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetConnectionCtx(void* ctx); + + +typedef struct SSLStats +{ + unsigned long int sslStandardConns; + unsigned long int sslClientAuthConns; + unsigned long int sslResumedConns; + unsigned long int sslEphemeralMisses; + unsigned long int sslResumeMisses; + unsigned long int sslCiphersUnsupported; + unsigned long int sslKeysUnmatched; + unsigned long int sslKeyFails; + unsigned long int sslDecodeFails; + unsigned long int sslAlerts; + unsigned long int sslDecryptedBytes; + unsigned long int sslEncryptedBytes; + unsigned long int sslEncryptedPackets; + unsigned long int sslDecryptedPackets; + unsigned long int sslKeyMatches; + unsigned long int sslEncryptedConns; + + unsigned long int sslResumptionValid; + unsigned long int sslResumptionInserts; +} SSLStats; + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_ResetStatistics(void); + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_ReadStatistics(SSLStats* stats); + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_ReadResetStatistics(SSLStats* stats); + + +typedef int (*SSLWatchCb)(void* vSniffer, + const unsigned char* certHash, + unsigned int certHashSz, + const unsigned char* certChain, + unsigned int certChainSz, + void* ctx, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetWatchKeyCallback(SSLWatchCb cb, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetWatchKeyCallback_ex(SSLWatchCb cb, int devId, + char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetWatchKeyCtx(void* ctx, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetWatchKey_buffer(void* vSniffer, + const unsigned char* key, unsigned int keySz, + int keyType, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetWatchKey_file(void* vSniffer, + const char* keyFile, int keyType, + const char* password, char* error); + + +typedef int (*SSLStoreDataCb)(const unsigned char* decryptBuf, + unsigned int decryptBufSz, unsigned int decryptBufOffset, void* ctx); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetStoreDataCallback(SSLStoreDataCb cb); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_DecodePacketWithSessionInfoStoreData( + const unsigned char* packet, int length, void* ctx, + SSLInfo* sslInfo, char* error); + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_DecodePacketWithChain(void* vChain, + unsigned int chainSz, unsigned char** data, char* error); + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_DecodePacketWithChainSessionInfoStoreData( + void* vChain, unsigned int chainSz, void* ctx, SSLInfo* sslInfo, + char* error); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/sniffer_error.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/sniffer_error.h index ad89a50d9..d4e836927 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/sniffer_error.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/sniffer_error.h @@ -1,8 +1,8 @@ /* sniffer_error.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLFSSL_SNIFFER_ERROR_H #define WOLFSSL_SNIFFER_ERROR_H @@ -101,12 +102,34 @@ #define BAD_COMPRESSION_STR 67 #define BAD_DERIVE_STR 68 #define ACK_MISSED_STR 69 -#define BAD_DECRYPT 70 +#define BAD_DECRYPT 70 #define DECRYPT_KEYS_NOT_SETUP 71 #define CLIENT_HELLO_LATE_KEY_STR 72 #define GOT_CERT_STATUS_STR 73 #define RSA_KEY_MISSING_STR 74 +#define NO_SECURE_RENEGOTIATION 75 + +#define BAD_SESSION_STATS 76 +#define REASSEMBLY_MAX_STR 77 +#define DROPPING_LOST_FRAG_STR 78 +#define DROPPING_PARTIAL_RECORD 79 +#define CLEAR_ACK_FAULT 80 + +#define BAD_DECRYPT_SIZE 81 +#define EXTENDED_MASTER_HASH_STR 82 +#define SPLIT_HANDSHAKE_MSG_STR 83 +#define ECC_DECODE_STR 84 +#define ECC_PUB_DECODE_STR 85 +#define WATCH_CB_MISSING_STR 86 +#define WATCH_HASH_STR 87 +#define WATCH_FAIL_STR 88 +#define BAD_CERT_MSG_STR 89 +#define STORE_DATA_CB_MISSING_STR 90 + +#define NO_DATA_DEST_STR 91 +#define STORE_DATA_FAIL_STR 92 +#define CHAIN_INPUT_STR 93 /* !!!! also add to msgTable in sniffer.c and .rc file !!!! */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/sniffer_error.rc b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/sniffer_error.rc index 8bcd6926c..72fe36e9e 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/sniffer_error.rc +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/sniffer_error.rc @@ -89,5 +89,28 @@ STRINGTABLE 72, "Late Key Load Error" 73, "Got Certificate Status msg" 74, "RSA Key Missing Error" + 75, "Secure Renegotiation Not Supported" + + 76, "Get Session Stats Failure" + 77, "Reassembly Buffer Size Exceeded" + 78, "Dropping Lost Fragment" + 79, "Dropping Partial Record" + 80, "Clear ACK Fault" + + 81, "Bad Decrypt Size" + 82, "Extended Master Secret Hash Error" + 83, "Handshake Message Split Across TLS Records" + 84, "ECC Private Decode Error" + 85, "ECC Public Decode Error" + + 86, "Watch callback not set" + 87, "Watch hash failed" + 88, "Watch callback failed" + 89, "Bad Certificate Message" + 90, "Store data callback not set" + + 91, "No data destination Error" + 92, "Store Data callback failed" + 93, "Loading chain input" } diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/ssl.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/ssl.h index 9c3ac84c9..87bac7c45 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/ssl.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/ssl.h @@ -1,8 +1,8 @@ /* ssl.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,12 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ - +/*! + \file ../wolfssl/ssl.h + \brief Header file containing key wolfSSL API +*/ /* wolfSSL API */ @@ -29,15 +32,17 @@ /* for users not using preprocessor flags*/ #include #include +#include +#include +#include -#ifndef NO_FILESYSTEM - #ifdef FREESCALE_MQX - #include - #else - #include /* ERR_printf */ - #endif +#ifdef HAVE_WOLF_EVENT + #include #endif +/* used internally by wolfSSL while OpenSSL types aren't */ +#include + #ifdef WOLFSSL_PREFIX #include "prefix_ssl.h" #endif @@ -52,71 +57,484 @@ #undef OCSP_RESPONSE #endif +#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) || defined(OPENSSL_EXTRA_X509_SMALL)) + #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; typedef struct WOLFSSL_X509_NAME WOLFSSL_X509_NAME; +typedef struct WOLFSSL_X509_NAME_ENTRY WOLFSSL_X509_NAME_ENTRY; +typedef struct WOLFSSL_X509_PUBKEY WOLFSSL_X509_PUBKEY; +typedef struct WOLFSSL_X509_ALGOR WOLFSSL_X509_ALGOR; typedef struct WOLFSSL_X509_CHAIN WOLFSSL_X509_CHAIN; +typedef struct WC_PKCS12 WOLFSSL_X509_PKCS12; +typedef struct WOLFSSL_X509_INFO WOLFSSL_X509_INFO; typedef struct WOLFSSL_CERT_MANAGER WOLFSSL_CERT_MANAGER; typedef struct WOLFSSL_SOCKADDR WOLFSSL_SOCKADDR; +typedef struct WOLFSSL_CRL WOLFSSL_CRL; +typedef struct WOLFSSL_X509_STORE_CTX WOLFSSL_X509_STORE_CTX; + +typedef int (*WOLFSSL_X509_STORE_CTX_verify_cb)(int, WOLFSSL_X509_STORE_CTX *); /* redeclare guard */ #define WOLFSSL_TYPES_DEFINED +#include + +#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_RSA WOLFSSL_RSA; +#define WOLFSSL_RSA_TYPE_DEFINED +#endif + +#ifndef WC_RNG_TYPE_DEFINED /* guard on redeclaration */ + typedef struct WC_RNG WC_RNG; + #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; +typedef struct WOLFSSL_EC_BUILTIN_CURVE WOLFSSL_EC_BUILTIN_CURVE; +/* WOLFSSL_EC_METHOD is just an alias of WOLFSSL_EC_GROUP for now */ +typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_METHOD; +#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_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; -typedef struct WOLFSSL_ASN1_TIME WOLFSSL_ASN1_TIME; -typedef struct WOLFSSL_ASN1_INTEGER WOLFSSL_ASN1_INTEGER; +typedef struct WOLFSSL_CONF_VALUE WOLFSSL_CONF_VALUE; typedef struct WOLFSSL_ASN1_OBJECT WOLFSSL_ASN1_OBJECT; -typedef struct WOLFSSL_ASN1_STRING WOLFSSL_ASN1_STRING; -typedef struct WOLFSSL_dynlock_value WOLFSSL_dynlock_value; +typedef struct WOLFSSL_ASN1_OTHERNAME WOLFSSL_ASN1_OTHERNAME; +typedef struct WOLFSSL_X509V3_CTX WOLFSSL_X509V3_CTX; +typedef struct WOLFSSL_v3_ext_method WOLFSSL_v3_ext_method; -#define WOLFSSL_ASN1_UTCTIME WOLFSSL_ASN1_TIME +typedef struct WOLFSSL_ASN1_STRING WOLFSSL_ASN1_STRING; +typedef struct WOLFSSL_dynlock_value WOLFSSL_dynlock_value; +#ifndef WOLFSSL_DH_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_DH WOLFSSL_DH; +#define WOLFSSL_DH_TYPE_DEFINED /* guard on redeclaration */ +#endif +typedef struct WOLFSSL_ASN1_BIT_STRING WOLFSSL_ASN1_BIT_STRING; +typedef struct WOLFSSL_ASN1_TYPE WOLFSSL_ASN1_TYPE; -typedef struct WOLFSSL_EVP_PKEY { +typedef struct WOLFSSL_GENERAL_NAME WOLFSSL_GENERAL_NAME; +typedef struct WOLFSSL_AUTHORITY_KEYID WOLFSSL_AUTHORITY_KEYID; +typedef struct WOLFSSL_BASIC_CONSTRAINTS WOLFSSL_BASIC_CONSTRAINTS; +typedef struct WOLFSSL_ACCESS_DESCRIPTION WOLFSSL_ACCESS_DESCRIPTION; + +#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) + +struct WOLFSSL_AUTHORITY_KEYID { + WOLFSSL_ASN1_STRING *keyid; + WOLFSSL_ASN1_OBJECT *issuer; + WOLFSSL_ASN1_INTEGER *serial; +}; + +struct WOLFSSL_BASIC_CONSTRAINTS { + int ca; + WOLFSSL_ASN1_INTEGER *pathlen; +}; + +#endif /* OPENSSL_ALL || OPENSSL_EXTRA*/ + +#define WOLFSSL_ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define WOLFSSL_ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME + +struct WOLFSSL_ASN1_STRING { + char strData[CTC_NAME_SIZE]; + int length; + int type; /* type of string i.e. CTC_UTF8 */ + char* data; + long flags; + unsigned int isDynamic:1; /* flag for if data pointer dynamic (1 is yes 0 is no) */ +}; + +#define WOLFSSL_MAX_SNAME 40 + + +#define WOLFSSL_ASN1_DYNAMIC 0x1 +#define WOLFSSL_ASN1_DYNAMIC_DATA 0x2 + +struct WOLFSSL_ASN1_OTHERNAME { + WOLFSSL_ASN1_OBJECT* type_id; + WOLFSSL_ASN1_TYPE* value; +}; + +struct WOLFSSL_GENERAL_NAME { + int type; + union { + char* ptr; + WOLFSSL_ASN1_OTHERNAME* otherName; + WOLFSSL_ASN1_STRING* rfc822Name; + WOLFSSL_ASN1_STRING* dNSName; + WOLFSSL_ASN1_TYPE* x400Address; + WOLFSSL_X509_NAME* directoryName; + WOLFSSL_ASN1_STRING* uniformResourceIdentifier; + WOLFSSL_ASN1_STRING* iPAddress; + WOLFSSL_ASN1_OBJECT* registeredID; + + WOLFSSL_ASN1_STRING* ip; + WOLFSSL_X509_NAME* dirn; + WOLFSSL_ASN1_STRING* ia5; + WOLFSSL_ASN1_OBJECT* rid; + WOLFSSL_ASN1_TYPE* other; + } d; /* dereference */ +}; + +struct WOLFSSL_ACCESS_DESCRIPTION { + WOLFSSL_ASN1_OBJECT* method; + WOLFSSL_GENERAL_NAME* location; +}; + +struct WOLFSSL_X509V3_CTX { + WOLFSSL_X509* x509; +}; + + + +struct WOLFSSL_ASN1_OBJECT { + void* heap; + const unsigned char* obj; + /* sName is short name i.e sha256 rather than oid (null terminated) */ + char sName[WOLFSSL_MAX_SNAME]; + int type; /* oid */ + int grp; /* type of OID, i.e. oidCertPolicyType */ + int nid; + unsigned int objSz; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || defined(WOLFSSL_APACHE_HTTPD) + int ca; + WOLFSSL_ASN1_INTEGER *pathlen; +#endif + unsigned char dynamic; /* if 1 then obj was dynamically created, 0 otherwise */ + +#if defined(WOLFSSL_APACHE_HTTPD) + WOLFSSL_GENERAL_NAME* gn; +#endif + + struct d { /* derefrenced */ + WOLFSSL_ASN1_STRING* dNSName; + WOLFSSL_ASN1_STRING ia5_internal; + WOLFSSL_ASN1_STRING* ia5; /* points to ia5_internal */ +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + WOLFSSL_ASN1_STRING* uniformResourceIdentifier; + WOLFSSL_ASN1_STRING iPAddress_internal; + WOLFSSL_ASN1_OTHERNAME* otherName; /* added for Apache httpd */ +#endif + WOLFSSL_ASN1_STRING* iPAddress; /* points to iPAddress_internal */ + } d; +}; + +/* wrap ASN1 types */ +struct WOLFSSL_ASN1_TYPE { + int type; + union { + char *ptr; + WOLFSSL_ASN1_STRING* asn1_string; + WOLFSSL_ASN1_OBJECT* object; + WOLFSSL_ASN1_INTEGER* integer; + WOLFSSL_ASN1_BIT_STRING* bit_string; + WOLFSSL_ASN1_STRING* octet_string; + WOLFSSL_ASN1_STRING* printablestring; + WOLFSSL_ASN1_STRING* ia5string; + WOLFSSL_ASN1_UTCTIME* utctime; + WOLFSSL_ASN1_GENERALIZEDTIME* generalizedtime; + WOLFSSL_ASN1_STRING* utf8string; + WOLFSSL_ASN1_STRING* set; + WOLFSSL_ASN1_STRING* sequence; + } value; +}; + +struct WOLFSSL_EVP_PKEY { + void* heap; int type; /* openssh dereference */ int save_type; /* openssh dereference */ int pkey_sz; + int references; /*number of times free should be called for complete free*/ + wolfSSL_Mutex refMutex; /* ref count mutex */ + union { - char* ptr; + char* ptr; /* der format of key / or raw for NTRU */ } pkey; + #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + #ifndef NO_RSA + WOLFSSL_RSA* rsa; + byte ownRsa; /* if struct owns RSA and should free it */ + #endif + #ifndef NO_DSA + WOLFSSL_DSA* dsa; + byte ownDsa; /* if struct owns DSA and should free it */ + #endif + #ifdef HAVE_ECC + WOLFSSL_EC_KEY* ecc; + byte ownEcc; /* if struct owns ECC and should free it */ + #endif + #ifndef NO_DH + WOLFSSL_DH* dh; + byte ownDh; /* if struct owns DH and should free it */ + #endif + WC_RNG rng; + #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ #ifdef HAVE_ECC int pkey_curve; #endif -} WOLFSSL_EVP_PKEY; +}; +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_PKCS8_PRIV_KEY_INFO; +#ifndef WOLFSSL_EVP_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_EVP_PKEY; +typedef struct WOLFSSL_EVP_MD_CTX WOLFSSL_EVP_MD_CTX; +typedef char WOLFSSL_EVP_MD; +#define WOLFSSL_EVP_TYPE_DEFINED +#endif -typedef struct WOLFSSL_MD4_CTX { - int buffer[32]; /* big enough to hold, check size in Init */ -} WOLFSSL_MD4_CTX; +struct WOLFSSL_X509_PKEY { + WOLFSSL_EVP_PKEY* dec_pkey; /* dereferenced by Apache */ + void* heap; +}; +typedef struct WOLFSSL_X509_PKEY WOLFSSL_X509_PKEY; +struct WOLFSSL_X509_INFO { + WOLFSSL_X509 *x509; + WOLFSSL_X509_CRL *crl; + WOLFSSL_X509_PKEY *x_pkey; /* dereferenced by Apache */ + EncryptedInfo enc_cipher; + int enc_len; + char *enc_data; + int num; +}; + +#define WOLFSSL_EVP_PKEY_DEFAULT EVP_PKEY_RSA /* default key type */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + #define wolfSSL_SSL_MODE_RELEASE_BUFFERS 0x00000010U + #define wolfSSL_SSL_CTRL_SET_TMP_ECDH 4 +#endif + +struct WOLFSSL_X509_ALGOR { + WOLFSSL_ASN1_OBJECT* algorithm; + WOLFSSL_ASN1_TYPE* parameter; +}; + +struct WOLFSSL_X509_PUBKEY { + WOLFSSL_X509_ALGOR* algor; + WOLFSSL_EVP_PKEY* pkey; + int pubKeyOID; +}; + + +enum BIO_TYPE { + WOLFSSL_BIO_BUFFER = 1, + WOLFSSL_BIO_SOCKET = 2, + WOLFSSL_BIO_SSL = 3, + WOLFSSL_BIO_MEMORY = 4, + WOLFSSL_BIO_BIO = 5, + WOLFSSL_BIO_FILE = 6, + WOLFSSL_BIO_BASE64 = 7, + WOLFSSL_BIO_MD = 8 +}; + +enum BIO_FLAGS { + WOLFSSL_BIO_FLAG_BASE64_NO_NL = 0x01, + WOLFSSL_BIO_FLAG_READ = 0x02, + WOLFSSL_BIO_FLAG_WRITE = 0x04, + WOLFSSL_BIO_FLAG_IO_SPECIAL = 0x08, + WOLFSSL_BIO_FLAG_RETRY = 0x10 +}; + +enum BIO_CB_OPS { + WOLFSSL_BIO_CB_FREE = 0x01, + WOLFSSL_BIO_CB_READ = 0x02, + WOLFSSL_BIO_CB_WRITE = 0x03, + WOLFSSL_BIO_CB_PUTS = 0x04, + WOLFSSL_BIO_CB_GETS = 0x05, + WOLFSSL_BIO_CB_CTRL = 0x06, + WOLFSSL_BIO_CB_RETURN = 0x80 +}; + +typedef struct WOLFSSL_BUF_MEM { + char* data; /* dereferenced */ + size_t length; /* current length */ + size_t max; /* maximum length */ +} WOLFSSL_BUF_MEM; + +/* custom method with user set callbacks */ +typedef int (*wolfSSL_BIO_meth_write_cb)(WOLFSSL_BIO*, const char*, int); +typedef int (*wolfSSL_BIO_meth_read_cb)(WOLFSSL_BIO *, char *, int); +typedef int (*wolfSSL_BIO_meth_puts_cb)(WOLFSSL_BIO*, const char*); +typedef int (*wolfSSL_BIO_meth_gets_cb)(WOLFSSL_BIO*, char*, int); +typedef long (*wolfSSL_BIO_meth_ctrl_get_cb)(WOLFSSL_BIO*, int, long, void*); +typedef int (*wolfSSL_BIO_meth_create_cb)(WOLFSSL_BIO*); +typedef int (*wolfSSL_BIO_meth_destroy_cb)(WOLFSSL_BIO*); + +typedef int wolfSSL_BIO_info_cb(WOLFSSL_BIO *, int, int); +typedef long (*wolfssl_BIO_meth_ctrl_info_cb)(WOLFSSL_BIO*, int, wolfSSL_BIO_info_cb*); + +/* wolfSSL BIO_METHOD type */ +#ifndef MAX_BIO_METHOD_NAME +#define MAX_BIO_METHOD_NAME 256 +#endif +struct WOLFSSL_BIO_METHOD { + byte type; /* method type */ + char name[MAX_BIO_METHOD_NAME]; + wolfSSL_BIO_meth_write_cb writeCb; + wolfSSL_BIO_meth_read_cb readCb; + wolfSSL_BIO_meth_puts_cb putsCb; + wolfSSL_BIO_meth_gets_cb getsCb; + wolfSSL_BIO_meth_ctrl_get_cb ctrlCb; + wolfSSL_BIO_meth_create_cb createCb; + wolfSSL_BIO_meth_destroy_cb freeCb; + wolfssl_BIO_meth_ctrl_info_cb ctrlInfoCb; +}; + +/* wolfSSL BIO type */ +typedef long (*wolf_bio_info_cb)(WOLFSSL_BIO *bio, int event, const char *parg, + int iarg, long larg, long return_value); + +struct WOLFSSL_BIO { + WOLFSSL_BUF_MEM* mem_buf; + WOLFSSL_BIO_METHOD* method; + WOLFSSL_BIO* prev; /* previous in chain */ + WOLFSSL_BIO* next; /* next in chain */ + WOLFSSL_BIO* pair; /* BIO paired with */ + void* heap; /* user heap hint */ + void* ptr; /* WOLFSSL, file descriptor, MD, or mem buf */ + void* usrCtx; /* user set pointer */ + char* infoArg; /* BIO callback argument */ + wolf_bio_info_cb infoCb; /* BIO callback */ + int wrSz; /* write buffer size (mem) */ + int wrIdx; /* current index for write buffer */ + int rdIdx; /* current read index */ + int readRq; /* read request */ + int num; /* socket num or length */ + int eof; /* eof flag */ + int flags; + byte type; /* method type */ + byte init:1; /* bio has been initialized */ + byte shutdown:1; /* close flag */ +#ifdef HAVE_EX_DATA + WOLFSSL_CRYPTO_EX_DATA ex_data; +#endif +}; typedef struct WOLFSSL_COMP_METHOD { int type; /* stunnel dereference */ } WOLFSSL_COMP_METHOD; +typedef struct WOLFSSL_COMP { + int id; + const char *name; + WOLFSSL_COMP_METHOD *method; +} WOLFSSL_COMP; -typedef struct WOLFSSL_X509_STORE { - int cache; /* stunnel dereference */ +struct WOLFSSL_X509_LOOKUP_METHOD { + int type; +}; + +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; + WOLFSSL_X509_VERIFY_PARAM* param; /* certificate validation parameter */ +#endif +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + WOLFSSL_X509_STORE_CTX_verify_cb verify_cb; +#endif +#ifdef HAVE_EX_DATA + WOLFSSL_CRYPTO_EX_DATA ex_data; +#endif +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) + WOLFSSL_X509_CRL *crl; +#endif +}; + +#ifdef OPENSSL_EXTRA +#define WOLFSSL_USE_CHECK_TIME 0x2 +#define WOLFSSL_NO_CHECK_TIME 0x200000 +#define WOLFSSL_NO_WILDCARDS 0x4 +#define WOLFSSL_HOST_NAME_MAX 256 +#define WOLFSSL_MAX_IPSTR 46 /* max ip size IPv4 mapped IPv6 */ +struct WOLFSSL_X509_VERIFY_PARAM { + time_t check_time; + unsigned long flags; + char hostName[WOLFSSL_HOST_NAME_MAX]; + unsigned int hostFlags; + char ipasc[WOLFSSL_MAX_IPSTR]; +}; +#endif typedef struct WOLFSSL_ALERT { int code; @@ -136,68 +554,177 @@ typedef struct WOLFSSL_X509_REVOKED { typedef struct WOLFSSL_X509_OBJECT { union { char* ptr; + WOLFSSL_X509 *x509; WOLFSSL_X509_CRL* crl; /* stunnel dereference */ } data; } WOLFSSL_X509_OBJECT; +#define WOLFSSL_ASN1_BOOLEAN int -typedef struct WOLFSSL_X509_STORE_CTX { +typedef struct WOLFSSL_BUFFER_INFO { + unsigned char* buffer; + unsigned int length; +} WOLFSSL_BUFFER_INFO; + +struct WOLFSSL_X509_STORE_CTX { WOLFSSL_X509_STORE* store; /* Store full of a CA cert chain */ - WOLFSSL_X509* current_cert; /* stunnel dereference */ + WOLFSSL_X509* current_cert; /* current X509 (OPENSSL_EXTRA) */ +#ifdef WOLFSSL_ASIO + WOLFSSL_X509* current_issuer; /* asio dereference */ +#endif + WOLFSSL_X509_CHAIN* sesChain; /* pointer to WOLFSSL_SESSION peer chain */ + 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 */ +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + WOLFSSL_CRYPTO_EX_DATA ex_data; /* external data */ +#endif +#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_EXTRA) + int depth; /* used in X509_STORE_CTX_*_depth */ +#endif void* userCtx; /* user ctx */ int error; /* current error */ - int error_depth; /* cert depth for this error */ + int error_depth; /* index of cert depth for this error */ int discardSessionCerts; /* so verify callback can flag for discard */ -} WOLFSSL_X509_STORE_CTX; + int totalCerts; /* number of peer cert buffers */ + WOLFSSL_BUFFER_INFO* certs; /* peer certs */ + WOLFSSL_X509_STORE_CTX_verify_cb verify_cb; /* verify callback */ +}; +typedef char* WOLFSSL_STRING; -/* Valid Alert types from page 16/17 */ +/* Valid Alert types from page 16/17 + * Add alert string to the function wolfSSL_alert_type_string_long in src/ssl.c + */ enum AlertDescription { - close_notify = 0, - unexpected_message = 10, - bad_record_mac = 20, - record_overflow = 22, - decompression_failure = 30, - handshake_failure = 40, - no_certificate = 41, - bad_certificate = 42, - unsupported_certificate = 43, - certificate_revoked = 44, - certificate_expired = 45, - certificate_unknown = 46, - illegal_parameter = 47, - decrypt_error = 51, + close_notify = 0, + unexpected_message = 10, + bad_record_mac = 20, + record_overflow = 22, + decompression_failure = 30, + handshake_failure = 40, + no_certificate = 41, + bad_certificate = 42, + unsupported_certificate = 43, + certificate_revoked = 44, + certificate_expired = 45, + certificate_unknown = 46, + illegal_parameter = 47, + unknown_ca = 48, + decode_error = 50, + decrypt_error = 51, #ifdef WOLFSSL_MYSQL_COMPATIBLE /* catch name conflict for enum protocol with MYSQL build */ - wc_protocol_version = 70, + wc_protocol_version = 70, #else - protocol_version = 70, + protocol_version = 70, #endif - no_renegotiation = 100, - unrecognized_name = 112 + inappropriate_fallback = 86, + no_renegotiation = 100, + missing_extension = 109, + 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 */ + unknown_psk_identity = 115, /**< RFC 4279, section 2 */ + certificate_required = 116, /**< RFC 8446, section 8.2 */ + no_application_protocol = 120 }; enum AlertLevel { alert_warning = 1, - alert_fatal = 2 + alert_fatal = 2 }; +/* Maximum master key length (SECRET_LEN) */ +#define WOLFSSL_MAX_MASTER_KEY_LENGTH 48 +/* Maximum number of groups that can be set */ +#define WOLFSSL_MAX_GROUP_COUNT 10 -WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method(void); -WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method(void); -WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method(void); -WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method(void); -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); +#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) +enum Tls13Secret { + CLIENT_EARLY_TRAFFIC_SECRET, + CLIENT_HANDSHAKE_TRAFFIC_SECRET, + SERVER_HANDSHAKE_TRAFFIC_SECRET, + CLIENT_TRAFFIC_SECRET, + SERVER_TRAFFIC_SECRET, + EARLY_EXPORTER_SECRET, + EXPORTER_SECRET +}; +#endif + + +typedef WOLFSSL_METHOD* (*wolfSSL_method_func)(void* heap); + +/* CTX Method EX Constructor Functions */ +WOLFSSL_API WOLFSSL_METHOD *wolfTLS_client_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLS_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_method_ex(void* heap); +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_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_method_ex(void* heap); + 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_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_client_method_ex(void* heap); #ifdef WOLFSSL_DTLS + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_client_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_server_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_server_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method_ex(void* heap); +#endif + +/* CTX Method Constructor Functions */ +WOLFSSL_API WOLFSSL_METHOD *wolfTLS_client_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLS_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method(void); +WOLFSSL_ABI WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void); +#ifdef WOLFSSL_TLS13 + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method(void); + WOLFSSL_ABI WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method(void); +#endif + +#ifdef WOLFSSL_DTLS + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_server_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_client_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_server_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method(void); #endif @@ -206,21 +733,89 @@ WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void); WOLFSSL_API int wolfSSL_use_old_poly(WOLFSSL*, int); #endif +#ifdef WOLFSSL_SESSION_EXPORT +#ifdef WOLFSSL_DTLS + +#ifndef WOLFSSL_DTLS_EXPORT_TYPES +typedef int (*wc_dtls_export)(WOLFSSL* ssl, + unsigned char* exportBuffer, unsigned int sz, void* userCtx); +#define WOLFSSL_DTLS_EXPORT_TYPES +#endif /* WOLFSSL_DTLS_EXPORT_TYPES */ + +WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, + unsigned int sz); +WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, + wc_dtls_export func); +WOLFSSL_API int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func); +WOLFSSL_API int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, + unsigned int* sz); +WOLFSSL_API int wolfSSL_dtls_export_state_only(WOLFSSL* ssl, unsigned char* buf, + unsigned int* sz); +#endif /* WOLFSSL_DTLS */ +#endif /* WOLFSSL_SESSION_EXPORT */ + +#ifdef WOLFSSL_STATIC_MEMORY +#ifndef WOLFSSL_MEM_GUARD +#define WOLFSSL_MEM_GUARD + typedef struct WOLFSSL_MEM_STATS WOLFSSL_MEM_STATS; + typedef struct WOLFSSL_MEM_CONN_STATS WOLFSSL_MEM_CONN_STATS; +#endif +WOLFSSL_API int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, + wolfSSL_method_func method, + unsigned char* buf, unsigned int sz, + int flag, int max); +WOLFSSL_API int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, + WOLFSSL_MEM_STATS* mem_stats); +WOLFSSL_API int wolfSSL_is_static_memory(WOLFSSL* ssl, + WOLFSSL_MEM_CONN_STATS* mem_stats); +#endif + #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) -WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int); -WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, const char*, int); -WOLFSSL_API int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX*, const char*, - const char*); -WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX *, - const char *file); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, + const char*, int); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, + const char*, int); + +#endif + +#ifndef NO_CERTS +#define WOLFSSL_LOAD_FLAG_NONE 0x00000000 +#define WOLFSSL_LOAD_FLAG_IGNORE_ERR 0x00000001 +#define WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY 0x00000002 +#define WOLFSSL_LOAD_FLAG_PEM_CA_ONLY 0x00000004 + +#ifndef WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS +#define WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS WOLFSSL_LOAD_FLAG_NONE +#endif +#endif /* !NO_CERTS */ + +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) + +WOLFSSL_API int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX*, const char*, + const char*, unsigned int); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX*, + const char*, const char*); +#ifdef WOLFSSL_TRUST_PEER_CERT +WOLFSSL_API int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX*, const char*, int); +#endif +WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file( + WOLFSSL_CTX*, const char*); +WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX *, + const char *file, int format); WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX*, const char*, int); WOLFSSL_API long wolfSSL_get_verify_depth(WOLFSSL* ssl); WOLFSSL_API long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx); -WOLFSSL_API int wolfSSL_use_certificate_file(WOLFSSL*, const char*, int); -WOLFSSL_API int wolfSSL_use_PrivateKey_file(WOLFSSL*, const char*, int); -WOLFSSL_API int wolfSSL_use_certificate_chain_file(WOLFSSL*, const char *file); +WOLFSSL_API void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_use_certificate_file(WOLFSSL*, const char*, + int); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_use_PrivateKey_file(WOLFSSL*, const char*, + int); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_use_certificate_chain_file(WOLFSSL*, + const char*); +WOLFSSL_API int wolfSSL_use_certificate_chain_file_format(WOLFSSL*, + const char *file, int format); WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file(WOLFSSL*, const char*, int); #ifdef WOLFSSL_DER_LOAD @@ -233,74 +828,166 @@ WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file(WOLFSSL*, const char*, int); /* load NTRU private key blob */ #endif -#ifndef WOLFSSL_PEMCERT_TODER_DEFINED - WOLFSSL_API int wolfSSL_PemCertToDer(const char*, unsigned char*, int); - #define WOLFSSL_PEMCERT_TODER_DEFINED -#endif - #endif /* !NO_FILESYSTEM && !NO_CERTS */ -WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*); -WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX*); -WOLFSSL_API int wolfSSL_set_fd (WOLFSSL*, int); +WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap); +WOLFSSL_ABI WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*); +#ifdef OPENSSL_EXTRA +WOLFSSL_API int wolfSSL_CTX_up_ref(WOLFSSL_CTX*); +#endif +WOLFSSL_ABI WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX*); +WOLFSSL_API WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl); +WOLFSSL_API WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_is_server(WOLFSSL*); +WOLFSSL_API WOLFSSL* wolfSSL_write_dup(WOLFSSL*); +WOLFSSL_ABI 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 int wolfSSL_get_ciphers_iana(char*, int); +WOLFSSL_API const char* wolfSSL_get_cipher_name(WOLFSSL* ssl); +WOLFSSL_API const char* wolfSSL_get_cipher_name_from_suite(const unsigned char, + const unsigned char); +WOLFSSL_API const char* wolfSSL_get_cipher_name_iana_from_suite( + const unsigned char, const unsigned char); +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 */ -WOLFSSL_API int wolfSSL_write(WOLFSSL*, const void*, int); -WOLFSSL_API int wolfSSL_read(WOLFSSL*, void*, int); +/* please see note at top of README if you get an error from connect */ +WOLFSSL_ABI WOLFSSL_API int wolfSSL_connect(WOLFSSL*); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_write(WOLFSSL*, const void*, int); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_read(WOLFSSL*, void*, int); WOLFSSL_API int wolfSSL_peek(WOLFSSL*, void*, int); WOLFSSL_API int wolfSSL_accept(WOLFSSL*); -WOLFSSL_API void wolfSSL_CTX_free(WOLFSSL_CTX*); -WOLFSSL_API void wolfSSL_free(WOLFSSL*); -WOLFSSL_API int wolfSSL_shutdown(WOLFSSL*); +WOLFSSL_API int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req); +WOLFSSL_API int wolfSSL_mutual_auth(WOLFSSL* ssl, int req); +#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_CTX_set1_groups_list(WOLFSSL_CTX *ctx, char *list); +WOLFSSL_API int wolfSSL_set1_groups_list(WOLFSSL *ssl, char *list); + +WOLFSSL_API int wolfSSL_preferred_group(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, + int count); +WOLFSSL_API int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count); + +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_ABI WOLFSSL_API void wolfSSL_CTX_free(WOLFSSL_CTX*); +WOLFSSL_ABI WOLFSSL_API void wolfSSL_free(WOLFSSL*); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_shutdown(WOLFSSL*); WOLFSSL_API int wolfSSL_send(WOLFSSL*, const void*, int sz, int flags); WOLFSSL_API int wolfSSL_recv(WOLFSSL*, void*, int sz, int flags); WOLFSSL_API void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX*, int); WOLFSSL_API void wolfSSL_set_quiet_shutdown(WOLFSSL*, int); -WOLFSSL_API int wolfSSL_get_error(WOLFSSL*, int); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_get_error(WOLFSSL*, int); WOLFSSL_API int wolfSSL_get_alert_history(WOLFSSL*, WOLFSSL_ALERT_HISTORY *); -WOLFSSL_API int wolfSSL_set_session(WOLFSSL* ssl,WOLFSSL_SESSION* session); -WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* session, long t); -WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl); -WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX *ctx, long tm); -WOLFSSL_API int wolfSSL_SetServerID(WOLFSSL* ssl, const unsigned char*, - int, int); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_set_session(WOLFSSL*, WOLFSSL_SESSION*); +WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION*, long); +WOLFSSL_ABI WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL*); +WOLFSSL_ABI WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX*, long); +WOLFSSL_API int wolfSSL_SetServerID(WOLFSSL*, const unsigned char*, int, int); + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \ + || defined(WOLFSSL_NGINX) +WOLFSSL_API int wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO**, size_t, + WOLFSSL_BIO**, size_t); + +WOLFSSL_API int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *EM, + const unsigned char *mHash, + const WOLFSSL_EVP_MD *Hash, int saltLen); +WOLFSSL_API int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash, + const WOLFSSL_EVP_MD *hashAlg, + const unsigned char *EM, int saltLen); +WOLFSSL_API WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO*, WOLFSSL_RSA**); +WOLFSSL_API int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX*, + int, const unsigned char*); +WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX*, WOLFSSL_RSA*); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO*, WOLFSSL_EVP_PKEY**); +#endif /* OPENSSL_ALL || WOLFSSL_ASIO */ #ifdef SESSION_INDEX WOLFSSL_API int wolfSSL_GetSessionIndex(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_GetSessionAtIndex(int index, WOLFSSL_SESSION* session); #endif /* SESSION_INDEX */ -#if defined(SESSION_INDEX) && defined(SESSION_CERTS) +#if defined(SESSION_CERTS) WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session); +WOLFSSL_API WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session); #endif /* SESSION_INDEX && SESSION_CERTS */ typedef int (*VerifyCallback)(int, WOLFSSL_X509_STORE_CTX*); -typedef int (*pem_password_cb)(char*, int, int, void*); +typedef void (CallbackInfoState)(const WOLFSSL*, int, int); + +#if defined(HAVE_EX_DATA) || defined(FORTRESS) +typedef int (WOLFSSL_CRYPTO_EX_new)(void* p, void* ptr, + WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg); +typedef int (WOLFSSL_CRYPTO_EX_dup)(WOLFSSL_CRYPTO_EX_DATA* out, + WOLFSSL_CRYPTO_EX_DATA* in, void* inPtr, int idx, long argV, void* arg); +typedef void (WOLFSSL_CRYPTO_EX_free)(void* p, void* ptr, + WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg); + +WOLFSSL_API int wolfSSL_get_ex_new_index(long argValue, void* arg, + WOLFSSL_CRYPTO_EX_new* a, WOLFSSL_CRYPTO_EX_dup* b, + WOLFSSL_CRYPTO_EX_free* c); +#endif WOLFSSL_API void wolfSSL_CTX_set_verify(WOLFSSL_CTX*, int, VerifyCallback verify_callback); + +#ifdef OPENSSL_ALL +typedef int (*CertVerifyCallback)(WOLFSSL_X509_STORE_CTX* store, void* arg); +WOLFSSL_API void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx, + CertVerifyCallback cb, void* arg); +#endif + WOLFSSL_API void wolfSSL_set_verify(WOLFSSL*, int, VerifyCallback verify_callback); +WOLFSSL_API void wolfSSL_set_verify_result(WOLFSSL*, long); WOLFSSL_API void wolfSSL_SetCertCbCtx(WOLFSSL*, void*); -WOLFSSL_API int wolfSSL_pending(WOLFSSL*); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_pending(WOLFSSL*); WOLFSSL_API void wolfSSL_load_error_strings(void); WOLFSSL_API int wolfSSL_library_init(void); -WOLFSSL_API long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX*, long); +WOLFSSL_ABI WOLFSSL_API long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX*, + long); #ifdef HAVE_SECRET_CALLBACK -typedef int (*SessionSecretCb)(WOLFSSL* ssl, - void* secret, int* secretSz, void* ctx); -WOLFSSL_API int wolfSSL_set_session_secret_cb(WOLFSSL*, SessionSecretCb, void*); +typedef int (*SessionSecretCb)(WOLFSSL* ssl, void* secret, int* secretSz, + void* ctx); +WOLFSSL_API int wolfSSL_set_session_secret_cb(WOLFSSL*, SessionSecretCb, + void*); +#ifdef WOLFSSL_TLS13 +typedef int (*Tls13SecretCb)(WOLFSSL* ssl, int id, const unsigned char* secret, + int secretSz, void* ctx); +WOLFSSL_API int wolfSSL_set_tls13_secret_cb(WOLFSSL*, Tls13SecretCb, void*); +#endif #endif /* HAVE_SECRET_CALLBACK */ /* session cache persistence */ @@ -322,16 +1009,55 @@ WOLFSSL_API int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX*, const char*); WOLFSSL_API int wolfSSL_set_cipher_list(WOLFSSL*, const char*); /* Nonblocking DTLS helper functions */ +WOLFSSL_API void wolfSSL_dtls_set_using_nonblock(WOLFSSL*, int); +WOLFSSL_API int wolfSSL_dtls_get_using_nonblock(WOLFSSL*); +#define wolfSSL_set_using_nonblock wolfSSL_dtls_set_using_nonblock +#define wolfSSL_get_using_nonblock wolfSSL_dtls_get_using_nonblock + /* The old names are deprecated. */ WOLFSSL_API int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_DTLSv1_get_timeout(WOLFSSL* ssl, + WOLFSSL_TIMEVAL* timeleft); +WOLFSSL_API void wolfSSL_DTLSv1_set_initial_timeout_duration(WOLFSSL* ssl, + word32 duration_ms); +WOLFSSL_API int wolfSSL_DTLSv1_handle_timeout(WOLFSSL* ssl); + WOLFSSL_API int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int); WOLFSSL_API int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int); WOLFSSL_API int wolfSSL_dtls_got_timeout(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_dtls_retransmit(WOLFSSL*); WOLFSSL_API int wolfSSL_dtls(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_dtls_set_peer(WOLFSSL*, void*, unsigned int); WOLFSSL_API int wolfSSL_dtls_get_peer(WOLFSSL*, void*, unsigned int*); -WOLFSSL_API int wolfSSL_ERR_GET_REASON(int err); +WOLFSSL_API int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX*); +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_LIB(unsigned long err); +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, unsigned long sz); @@ -339,8 +1065,84 @@ WOLFSSL_API const char* wolfSSL_ERR_reason_error_string(unsigned long); /* extras */ -#define STACK_OF(x) x +/* for now LHASH is not implemented */ +typedef int WOLFSSL_LHASH; +#ifndef WOLF_LHASH_OF + #define WOLF_LHASH_OF(x) WOLFSSL_LHASH +#endif + +#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 WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap); +WOLFSSL_API void wolfSSL_sk_free(WOLFSSL_STACK* sk); +WOLFSSL_API void wolfSSL_sk_free_node(WOLFSSL_STACK* in); +WOLFSSL_API int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx); +WOLFSSL_API int wolfSSL_sk_push(WOLFSSL_STACK *st, const void *data); + +#if defined(HAVE_OCSP) +#include "wolfssl/ocsp.h" +#include "wolfssl/wolfcrypt/asn.h" +#endif + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +WOLFSSL_API int wolfSSL_sk_ACCESS_DESCRIPTION_push( + WOLF_STACK_OF(ACCESS_DESCRIPTION)* sk, + WOLFSSL_ACCESS_DESCRIPTION* access); +#endif /* defined(OPENSSL_ALL) || defined(WOLFSSL_QT) */ + +typedef WOLF_STACK_OF(WOLFSSL_GENERAL_NAME) WOLFSSL_GENERAL_NAMES; + +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(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_X509_dup(WOLFSSL_STACK* sk); +WOLFSSL_API void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk); +WOLFSSL_API WOLFSSL_GENERAL_NAME* wolfSSL_GENERAL_NAME_new(void); +WOLFSSL_API void wolfSSL_GENERAL_NAME_free(WOLFSSL_GENERAL_NAME* gn); +WOLFSSL_API int wolfSSL_sk_GENERAL_NAME_push(WOLF_STACK_OF(WOLFSSL_GENERAL_NAME)* sk, + WOLFSSL_GENERAL_NAME* gn); +WOLFSSL_API WOLFSSL_GENERAL_NAME* wolfSSL_sk_GENERAL_NAME_value( + WOLFSSL_STACK* sk, int i); +WOLFSSL_API int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk); +WOLFSSL_API void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk, + void (*f) (WOLFSSL_GENERAL_NAME*)); +WOLFSSL_API void wolfSSL_sk_GENERAL_NAME_free(WOLFSSL_STACK* sk); +WOLFSSL_API void wolfSSL_GENERAL_NAMES_free(WOLFSSL_GENERAL_NAMES* name); +WOLFSSL_API int wolfSSL_sk_ACCESS_DESCRIPTION_num(WOLFSSL_STACK* sk); +WOLFSSL_API void wolfSSL_AUTHORITY_INFO_ACCESS_free( + WOLF_STACK_OF(WOLFSSL_ACCESS_DESCRIPTION)* sk); +WOLFSSL_API WOLFSSL_ACCESS_DESCRIPTION* wolfSSL_sk_ACCESS_DESCRIPTION_value( + WOLFSSL_STACK* sk, int idx); +WOLFSSL_API void wolfSSL_sk_ACCESS_DESCRIPTION_free(WOLFSSL_STACK* sk); +WOLFSSL_API void wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(WOLFSSL_STACK* sk, + void (*f) (WOLFSSL_ACCESS_DESCRIPTION*)); +WOLFSSL_API void wolfSSL_ACCESS_DESCRIPTION_free(WOLFSSL_ACCESS_DESCRIPTION* access); +WOLFSSL_API void wolfSSL_sk_X509_EXTENSION_pop_free( + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, + void (*f) (WOLFSSL_X509_EXTENSION*)); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* wolfSSL_sk_X509_EXTENSION_new_null(void); +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void); +WOLFSSL_API void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_new_asn1_obj(void); +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_OBJECT_pop( + WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk); +WOLFSSL_API void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk); +WOLFSSL_API void wolfSSL_sk_ASN1_OBJECT_pop_free( + WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, + void (*f)(WOLFSSL_ASN1_OBJECT*)); +WOLFSSL_API int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in); +WOLFSSL_API int wolfSSL_sk_X509_EXTENSION_num(WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk); +WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_sk_X509_EXTENSION_value( + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, int idx); WOLFSSL_API int wolfSSL_set_ex_data(WOLFSSL*, int, void*); WOLFSSL_API int wolfSSL_get_shutdown(const WOLFSSL*); WOLFSSL_API int wolfSSL_set_rfd(WOLFSSL*, int); @@ -351,20 +1153,30 @@ WOLFSSL_API int wolfSSL_set_session_id_context(WOLFSSL*, const unsigned char*, WOLFSSL_API void wolfSSL_set_connect_state(WOLFSSL*); WOLFSSL_API void wolfSSL_set_accept_state(WOLFSSL*); WOLFSSL_API int wolfSSL_session_reused(WOLFSSL*); +WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session); WOLFSSL_API void wolfSSL_SESSION_free(WOLFSSL_SESSION* session); 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_CIPHER_get_version(const WOLFSSL_CIPHER* cipher); +WOLFSSL_API word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher); +WOLFSSL_API const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value); +WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session); WOLFSSL_API const char* wolfSSL_get_cipher(WOLFSSL*); +WOLFSSL_API void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl); /* what's ref count */ -WOLFSSL_API void wolfSSL_X509_free(WOLFSSL_X509*); -WOLFSSL_API void wolfSSL_OPENSSL_free(void*); +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_new(void); +#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_ALL) +WOLFSSL_API int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa); +WOLFSSL_API int wolfSSL_X509_up_ref(WOLFSSL_X509* x509); +WOLFSSL_API int wolfSSL_EVP_PKEY_up_ref(WOLFSSL_EVP_PKEY* pkey); +#endif WOLFSSL_API int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, int* ssl); @@ -373,20 +1185,29 @@ WOLFSSL_API WOLFSSL_METHOD* wolfSSLv23_client_method(void); WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_client_method(void); WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_server_method(void); -WOLFSSL_API void wolfSSL_MD4_Init(WOLFSSL_MD4_CTX*); -WOLFSSL_API void wolfSSL_MD4_Update(WOLFSSL_MD4_CTX*, const void*, unsigned long); -WOLFSSL_API void wolfSSL_MD4_Final(unsigned char*, WOLFSSL_MD4_CTX*); - - WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD*); WOLFSSL_API int wolfSSL_BIO_free(WOLFSSL_BIO*); +WOLFSSL_API void wolfSSL_BIO_vfree(WOLFSSL_BIO*); WOLFSSL_API int wolfSSL_BIO_free_all(WOLFSSL_BIO*); +WOLFSSL_API int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz); +WOLFSSL_API int wolfSSL_BIO_puts(WOLFSSL_BIO* bio, const char* buf); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_next(WOLFSSL_BIO* bio); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_find_type(WOLFSSL_BIO* bio, int type); WOLFSSL_API int wolfSSL_BIO_read(WOLFSSL_BIO*, void*, int); WOLFSSL_API int wolfSSL_BIO_write(WOLFSSL_BIO*, const void*, int); WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO*, WOLFSSL_BIO* append); WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO*); WOLFSSL_API int wolfSSL_BIO_flush(WOLFSSL_BIO*); WOLFSSL_API int wolfSSL_BIO_pending(WOLFSSL_BIO*); +WOLFSSL_API void wolfSSL_BIO_set_callback(WOLFSSL_BIO *bio, + wolf_bio_info_cb callback_func); +WOLFSSL_API wolf_bio_info_cb wolfSSL_BIO_get_callback(WOLFSSL_BIO *bio); +WOLFSSL_API void wolfSSL_BIO_set_callback_arg(WOLFSSL_BIO *bio, char *arg); +WOLFSSL_API char* wolfSSL_BIO_get_callback_arg(const WOLFSSL_BIO *bio); + +WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_md(void); +WOLFSSL_API int wolfSSL_BIO_get_md_ctx(WOLFSSL_BIO *bio, + WOLFSSL_EVP_MD_CTX **mdcp); WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void); WOLFSSL_API long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO*, long size); @@ -397,15 +1218,62 @@ WOLFSSL_API int wolfSSL_BIO_eof(WOLFSSL_BIO*); 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 void wolfSSL_BIO_clear_flags(WOLFSSL_BIO *bio, int flags); +WOLFSSL_API int wolfSSL_BIO_set_ex_data(WOLFSSL_BIO *bio, int idx, void *data); +WOLFSSL_API void *wolfSSL_BIO_get_ex_data(WOLFSSL_BIO *bio, int idx); +WOLFSSL_API long wolfSSL_BIO_set_nbio(WOLFSSL_BIO*, long); -WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,const unsigned char** p); -WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len); +WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,void* p); +WOLFSSL_API void wolfSSL_BIO_set_init(WOLFSSL_BIO*, int); +WOLFSSL_API void wolfSSL_BIO_set_data(WOLFSSL_BIO*, void*); +WOLFSSL_API void* wolfSSL_BIO_get_data(WOLFSSL_BIO*); +WOLFSSL_API void wolfSSL_BIO_set_shutdown(WOLFSSL_BIO*, int); +WOLFSSL_API int wolfSSL_BIO_get_shutdown(WOLFSSL_BIO*); +WOLFSSL_API void wolfSSL_BIO_clear_retry_flags(WOLFSSL_BIO*); +WOLFSSL_API int wolfSSL_BIO_should_retry(WOLFSSL_BIO *bio); -WOLFSSL_API long wolfSSL_BIO_set_ssl(WOLFSSL_BIO*, WOLFSSL*, int flag); -WOLFSSL_API void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr); +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_meth_new(int, const char*); +WOLFSSL_API void wolfSSL_BIO_meth_free(WOLFSSL_BIO_METHOD*); +WOLFSSL_API int wolfSSL_BIO_meth_set_write(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_write_cb); +WOLFSSL_API int wolfSSL_BIO_meth_set_read(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_read_cb); +WOLFSSL_API int wolfSSL_BIO_meth_set_puts(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_puts_cb); +WOLFSSL_API int wolfSSL_BIO_meth_set_gets(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_gets_cb); +WOLFSSL_API int wolfSSL_BIO_meth_set_ctrl(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_ctrl_get_cb); +WOLFSSL_API int wolfSSL_BIO_meth_set_create(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_create_cb); +WOLFSSL_API int wolfSSL_BIO_meth_set_destroy(WOLFSSL_BIO_METHOD*, wolfSSL_BIO_meth_destroy_cb); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(const void* buf, int len); -WOLFSSL_API int wolfSSL_add_all_algorithms(void); +WOLFSSL_API long wolfSSL_BIO_set_ssl(WOLFSSL_BIO*, WOLFSSL*, int flag); +#ifndef NO_FILESYSTEM +WOLFSSL_API long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int flag); +#endif +WOLFSSL_API int wolfSSL_BIO_set_close(WOLFSSL_BIO *b, long flag); +WOLFSSL_API void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr); + +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_file(void); +#endif + +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_bio(void); +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void); + +WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, void *parg); +WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg); + +WOLFSSL_API int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *b, long size); +WOLFSSL_API int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2); +WOLFSSL_API int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b); +WOLFSSL_API int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf); +WOLFSSL_API int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num); +WOLFSSL_API int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num); +WOLFSSL_API int wolfSSL_BIO_reset(WOLFSSL_BIO *bio); + +WOLFSSL_API int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs); +WOLFSSL_API int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name); +WOLFSSL_API long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v); +WOLFSSL_API long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **m); +WOLFSSL_API int wolfSSL_BIO_get_len(WOLFSSL_BIO *bio); WOLFSSL_API void wolfSSL_RAND_screen(void); WOLFSSL_API const char* wolfSSL_RAND_file_name(char*, unsigned long); @@ -413,14 +1281,15 @@ WOLFSSL_API int wolfSSL_RAND_write_file(const char*); WOLFSSL_API int wolfSSL_RAND_load_file(const char*, long); WOLFSSL_API int wolfSSL_RAND_egd(const char*); WOLFSSL_API int wolfSSL_RAND_seed(const void*, int); +WOLFSSL_API void wolfSSL_RAND_Cleanup(void); WOLFSSL_API void wolfSSL_RAND_add(const void*, int, double); +WOLFSSL_API int wolfSSL_RAND_poll(void); WOLFSSL_API WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void); WOLFSSL_API WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void); WOLFSSL_API int wolfSSL_COMP_add_compression_method(int, void*); -WOLFSSL_API int wolfSSL_get_ex_new_index(long, void*, void*, void*, void*); - +WOLFSSL_API unsigned long wolfSSL_thread_id(void); WOLFSSL_API void wolfSSL_set_id_callback(unsigned long (*f)(void)); WOLFSSL_API void wolfSSL_set_locking_callback(void (*f)(int, int, const char*, int)); @@ -437,9 +1306,27 @@ WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert( WOLFSSL_API int wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX*); WOLFSSL_API int wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX*); -WOLFSSL_API char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME*, char*, int); -WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509*); -WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509*); +WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx, + WOLFSSL_X509_STORE_CTX_verify_cb verify_cb); +WOLFSSL_API void wolfSSL_X509_STORE_set_verify_cb(WOLFSSL_X509_STORE *st, + WOLFSSL_X509_STORE_CTX_verify_cb verify_cb); +WOLFSSL_API int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* n, + unsigned char** out); +#ifndef NO_RSA +WOLFSSL_API int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int offset); +#endif +WOLFSSL_API int wolfSSL_X509_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509* x509, + unsigned long nmflags, unsigned long cflag); +WOLFSSL_API int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509); +WOLFSSL_ABI WOLFSSL_API char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME*, + char*, int); +#if defined(OPENSSL_EXTRA) && defined(XSNPRINTF) +WOLFSSL_API char* wolfSSL_X509_get_name_oneline(WOLFSSL_X509_NAME*, char*, int); +#endif +WOLFSSL_ABI WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name( + WOLFSSL_X509*); +WOLFSSL_ABI WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name( + WOLFSSL_X509*); WOLFSSL_API int wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509*, int); WOLFSSL_API int wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509*, int); WOLFSSL_API int wolfSSL_X509_get_isCA(WOLFSSL_X509*); @@ -450,13 +1337,49 @@ WOLFSSL_API unsigned char* wolfSSL_X509_get_authorityKeyID( WOLFSSL_X509*, unsigned char*, int*); WOLFSSL_API unsigned char* wolfSSL_X509_get_subjectKeyID( WOLFSSL_X509*, unsigned char*, int*); + +WOLFSSL_API int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey); +WOLFSSL_API int wolfSSL_X509_set_subject_name(WOLFSSL_X509*, + WOLFSSL_X509_NAME*); +WOLFSSL_API int wolfSSL_X509_set_issuer_name(WOLFSSL_X509*, + WOLFSSL_X509_NAME*); +WOLFSSL_API int wolfSSL_X509_set_pubkey(WOLFSSL_X509*, WOLFSSL_EVP_PKEY*); +WOLFSSL_API int wolfSSL_X509_set_notAfter(WOLFSSL_X509* x509, + const WOLFSSL_ASN1_TIME* t); +WOLFSSL_API int wolfSSL_X509_set_notBefore(WOLFSSL_X509* x509, + const WOLFSSL_ASN1_TIME* t); +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notBefore(const WOLFSSL_X509* x509); +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notAfter(const WOLFSSL_X509* x509); +WOLFSSL_API int wolfSSL_X509_set_serialNumber(WOLFSSL_X509* x509, + WOLFSSL_ASN1_INTEGER* s); +WOLFSSL_API int wolfSSL_X509_set_version(WOLFSSL_X509* x509, long v); +WOLFSSL_API int wolfSSL_X509_sign(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey, + const WOLFSSL_EVP_MD* md); + + WOLFSSL_API int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME*); WOLFSSL_API int wolfSSL_X509_NAME_get_text_by_NID( WOLFSSL_X509_NAME*, int, char*, int); +WOLFSSL_API int wolfSSL_X509_NAME_get_index_by_NID( + WOLFSSL_X509_NAME*, int, int); +WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_X509_NAME_ENTRY_get_data(WOLFSSL_X509_NAME_ENTRY*); + +WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void); +WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type); +WOLFSSL_API int wolfSSL_ASN1_STRING_type(const WOLFSSL_ASN1_STRING* asn1); +WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_d2i_DISPLAYTEXT(WOLFSSL_ASN1_STRING **asn, const unsigned char **in, long len); +WOLFSSL_API void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1); +WOLFSSL_API int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, + const void* data, int dataSz); +WOLFSSL_API unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING*); +WOLFSSL_API int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING*); WOLFSSL_API int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX*); WOLFSSL_API const char* wolfSSL_X509_verify_cert_error_string(long); WOLFSSL_API int wolfSSL_X509_get_signature_type(WOLFSSL_X509*); WOLFSSL_API int wolfSSL_X509_get_signature(WOLFSSL_X509*, unsigned char*, int*); +WOLFSSL_API int wolfSSL_X509_get_pubkey_buffer(WOLFSSL_X509*, unsigned char*, + int*); +WOLFSSL_API int wolfSSL_X509_get_pubkey_type(WOLFSSL_X509* x509); WOLFSSL_API int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP*,const char*,long); WOLFSSL_API int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP*, const char*, @@ -470,64 +1393,148 @@ WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void); WOLFSSL_API void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE*); WOLFSSL_API int wolfSSL_X509_STORE_add_cert( WOLFSSL_X509_STORE*, WOLFSSL_X509*); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain( + WOLFSSL_X509_STORE_CTX* ctx); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get1_chain( + WOLFSSL_X509_STORE_CTX* ctx); +WOLFSSL_API int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, + unsigned long flag); WOLFSSL_API int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE*); WOLFSSL_API int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX*, 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*); WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL*); WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL*); +WOLFSSL_ASN1_TIME* wolfSSL_X509_gmtime_adj(WOLFSSL_ASN1_TIME *s, long adj); WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509*); WOLFSSL_API int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL*, WOLFSSL_EVP_PKEY*); -WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX*, - int); WOLFSSL_API void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT*); -WOLFSSL_API void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY*); +WOLFSSL_API WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio( + WOLFSSL_BIO* bio, WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** out); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** key, + const unsigned char** in, long inSz); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, + WOLFSSL_EVP_PKEY** out, const unsigned char **in, long inSz); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** key, + unsigned char** in, long inSz); +WOLFSSL_API int wolfSSL_i2d_PrivateKey(WOLFSSL_EVP_PKEY* key, + unsigned char** der); WOLFSSL_API int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME*); +#ifdef OPENSSL_EXTRA +WOLFSSL_API int wolfSSL_X509_cmp_time(const WOLFSSL_ASN1_TIME* asnTime, + time_t *cmpTime); +WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj_ex(WOLFSSL_ASN1_TIME *asnTime, + int offset_day, long offset_sec, time_t *in_tm); +WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj(WOLFSSL_ASN1_TIME *asnTime, + long offset_sec, time_t *in_tm); WOLFSSL_API int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED*); - +WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX*, + unsigned long flags, + time_t t); +WOLFSSL_API void wolfSSL_X509_VERIFY_PARAM_set_hostflags( + WOLFSSL_X509_VERIFY_PARAM* param, unsigned int flags); +WOLFSSL_API int wolfSSL_X509_VERIFY_PARAM_set1_host(WOLFSSL_X509_VERIFY_PARAM* pParam, + const char* name, + unsigned int nameSz); +WOLFSSL_API int wolfSSL_X509_VERIFY_PARAM_set1_ip_asc( + WOLFSSL_X509_VERIFY_PARAM *param, const char *ipasc); +#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); WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509*); +WOLFSSL_API void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER*); +WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void); +WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_dup( + const WOLFSSL_ASN1_INTEGER* src); +WOLFSSL_API int wolfSSL_ASN1_INTEGER_set(WOLFSSL_ASN1_INTEGER *a, long v); WOLFSSL_API int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO*, const WOLFSSL_ASN1_TIME*); +WOLFSSL_API char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, + char* buf, int len); WOLFSSL_API int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER*, const WOLFSSL_ASN1_INTEGER*); WOLFSSL_API long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER*); -WOLFSSL_API STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*); +#ifdef OPENSSL_EXTRA +WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, + WOLFSSL_BIGNUM *bn); +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME*, time_t, + int, long); +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_new(void); +WOLFSSL_API void wolfSSL_ASN1_TIME_free(WOLFSSL_ASN1_TIME* t); +#endif + +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *s); +/* deprecated function name */ +#define wolfSSL_SSL_CTX_get_client_CA_list wolfSSL_CTX_get_client_CA_list WOLFSSL_API void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX*, - 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); + WOLF_STACK_OF(WOLFSSL_X509_NAME)*); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list( + const WOLFSSL* ssl); + +typedef int (*client_cert_cb)(WOLFSSL *ssl, WOLFSSL_X509 **x509, + WOLFSSL_EVP_PKEY **pkey); +WOLFSSL_API void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb); + +WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data( + WOLFSSL_X509_STORE_CTX* ctx, int idx); +WOLFSSL_API int wolfSSL_X509_STORE_CTX_set_ex_data(WOLFSSL_X509_STORE_CTX* ctx, + int idx, void *data); +WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_depth(WOLFSSL_X509_STORE_CTX* ctx, + int depth); +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_current_issuer( + WOLFSSL_X509_STORE_CTX* ctx); +WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_X509_STORE_CTX_get0_store( + WOLFSSL_X509_STORE_CTX* ctx); +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_cert( + WOLFSSL_X509_STORE_CTX*); +WOLFSSL_API int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void); +WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_error( + WOLFSSL_X509_STORE_CTX* ctx, int er); +void wolfSSL_X509_STORE_CTX_set_error_depth(WOLFSSL_X509_STORE_CTX* ctx, + int depth); 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 pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx); +WOLFSSL_API void *wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx); - -WOLFSSL_API void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX*, void (*)(void)); +WOLFSSL_API void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX*, + void (*)(const WOLFSSL* ssl, int type, int val)); WOLFSSL_API unsigned long wolfSSL_ERR_peek_error(void); WOLFSSL_API int wolfSSL_GET_REASON(int); -WOLFSSL_API char* wolfSSL_alert_type_string_long(int); -WOLFSSL_API char* wolfSSL_alert_desc_string_long(int); -WOLFSSL_API char* wolfSSL_state_string_long(WOLFSSL*); +WOLFSSL_API const char* wolfSSL_alert_type_string_long(int); +WOLFSSL_API const char* wolfSSL_alert_desc_string_long(int); +WOLFSSL_API const char* wolfSSL_state_string_long(const WOLFSSL*); WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*); -WOLFSSL_API void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX*, - WOLFSSL_RSA*(*)(WOLFSSL*, int, int)); +WOLFSSL_API WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **r, + const unsigned char **pp, long len); +WOLFSSL_API WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA**, + const unsigned char**, long); +WOLFSSL_API int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *r, const unsigned char **pp); +WOLFSSL_API int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *r, unsigned char **pp); +WOLFSSL_API void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX *, + WOLFSSL_RSA *(*)(WOLFSSL *, int, int)); WOLFSSL_API int wolfSSL_PEM_def_callback(char*, int num, int w, void* key); @@ -543,12 +1550,121 @@ WOLFSSL_API long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX*); WOLFSSL_API long wolfSSL_CTX_sess_misses(WOLFSSL_CTX*); WOLFSSL_API long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX*); WOLFSSL_API long wolfSSL_CTX_sess_number(WOLFSSL_CTX*); + +WOLFSSL_API long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX*, WOLFSSL_X509*); +WOLFSSL_API long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX*, long); WOLFSSL_API long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX*); +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 long wolfSSL_set_options(WOLFSSL *s, long op); +WOLFSSL_API long wolfSSL_get_options(const WOLFSSL *s); +WOLFSSL_API long wolfSSL_clear_options(WOLFSSL *s, long op); +WOLFSSL_API long wolfSSL_clear_num_renegotiations(WOLFSSL *s); +WOLFSSL_API long wolfSSL_total_renegotiations(WOLFSSL *s); +WOLFSSL_API long wolfSSL_num_renegotiations(WOLFSSL* s); +WOLFSSL_API long wolfSSL_set_tmp_dh(WOLFSSL *s, WOLFSSL_DH *dh); +WOLFSSL_API long wolfSSL_set_tlsext_debug_arg(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type); +WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp); +WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len); + +WOLFSSL_API void wolfSSL_CONF_modules_unload(int all); +WOLFSSL_API char* wolfSSL_CONF_get1_default_config_file(void); +WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_get_verify_result(const WOLFSSL *ssl); + #define WOLFSSL_DEFAULT_CIPHER_LIST "" /* default all */ -#define WOLFSSL_RSA_F4 0x10001L + +/* These are bit-masks */ +enum { + WOLFSSL_OCSP_URL_OVERRIDE = 1, + WOLFSSL_OCSP_NO_NONCE = 2, + WOLFSSL_OCSP_CHECKALL = 4, + + WOLFSSL_CRL_CHECKALL = 1, + WOLFSSL_CRL_CHECK = 2, +}; + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(HAVE_WEBSERVER) +/* Separated 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_EPHEMERAL_RSA = 0x00000800, + WOLFSSL_OP_NO_SSLv3 = 0x00001000, + WOLFSSL_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, + WOLFSSL_OP_NO_TLSv1_1 = 0x04000000, + WOLFSSL_OP_NO_TLSv1_2 = 0x08000000, + SSL_OP_NO_COMPRESSION = 0x10000000, + WOLFSSL_OP_NO_TLSv1_3 = 0x20000000, + WOLFSSL_OP_NO_SSLv2 = 0x40000000, + SSL_OP_ALL = + (SSL_OP_MICROSOFT_SESS_ID_BUG + | SSL_OP_NETSCAPE_CHALLENGE_BUG + | SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG + | SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG + | SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER + | SSL_OP_MSIE_SSLV2_RSA_PADDING + | SSL_OP_SSLEAY_080_CLIENT_DH_BUG + | SSL_OP_TLS_D5_BUG + | SSL_OP_TLS_BLOCK_PADDING_BUG + | SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS + | SSL_OP_TLS_ROLLBACK_BUG), +}; + +/* for compatibility these must be macros */ +#define SSL_OP_NO_SSLv2 WOLFSSL_OP_NO_SSLv2 +#define SSL_OP_NO_SSLv3 WOLFSSL_OP_NO_SSLv3 +#define SSL_OP_NO_TLSv1 WOLFSSL_OP_NO_TLSv1 +#define SSL_OP_NO_TLSv1_1 WOLFSSL_OP_NO_TLSv1_1 +#define SSL_OP_NO_TLSv1_2 WOLFSSL_OP_NO_TLSv1_2 +#if !(!defined(WOLFSSL_TLS13) && defined(WOLFSSL_APACHE_HTTPD)) /* apache uses this to determine if TLS 1.3 is enabled */ +#define SSL_OP_NO_TLSv1_3 WOLFSSL_OP_NO_TLSv1_3 +#endif + +#define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | \ + SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3) + +#define SSL_NOTHING 1 +#define SSL_WRITING 2 +#define SSL_READING 3 enum { +#ifdef HAVE_OCSP + /* OCSP Flags */ OCSP_NOCERTS = 1, OCSP_NOINTERN = 2, OCSP_NOSIGS = 4, @@ -562,155 +1678,257 @@ 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, +#endif ASN1_GENERALIZEDTIME = 4, - - SSL_OP_MICROSOFT_SESS_ID_BUG = 1, - SSL_OP_NETSCAPE_CHALLENGE_BUG = 2, - SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 3, - SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 4, - SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 5, - SSL_OP_MSIE_SSLV2_RSA_PADDING = 6, - SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 7, - SSL_OP_TLS_D5_BUG = 8, - SSL_OP_TLS_BLOCK_PADDING_BUG = 9, - SSL_OP_TLS_ROLLBACK_BUG = 10, - SSL_OP_ALL = 11, - SSL_OP_EPHEMERAL_RSA = 12, - SSL_OP_NO_SSLv3 = 13, - SSL_OP_NO_TLSv1 = 14, - SSL_OP_PKCS1_CHECK_1 = 15, - SSL_OP_PKCS1_CHECK_2 = 16, - SSL_OP_NETSCAPE_CA_DN_BUG = 17, - SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 18, - SSL_OP_SINGLE_DH_USE = 19, - SSL_OP_NO_TICKET = 20, - SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 21, - SSL_OP_NO_QUERY_MTU = 22, - SSL_OP_COOKIE_EXCHANGE = 23, - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 24, - SSL_OP_SINGLE_ECDH_USE = 25, - SSL_OP_CIPHER_SERVER_PREFERENCE = 26, - SSL_MAX_SSL_SESSION_ID_LENGTH = 32, - EVP_R_BAD_DECRYPT = 2, + SSL_ST_CONNECT = 0x1000, + SSL_ST_ACCEPT = 0x2000, + SSL_ST_MASK = 0x0FFF, - SSL_CB_LOOP = 4, - SSL_ST_CONNECT = 5, - SSL_ST_ACCEPT = 6, - SSL_CB_ALERT = 7, - SSL_CB_READ = 8, - SSL_CB_HANDSHAKE_DONE = 9, + SSL_CB_LOOP = 0x01, + SSL_CB_EXIT = 0x02, + SSL_CB_READ = 0x04, + SSL_CB_WRITE = 0x08, + SSL_CB_HANDSHAKE_START = 0x10, + SSL_CB_HANDSHAKE_DONE = 0x20, + SSL_CB_ALERT = 0x4000, + SSL_CB_READ_ALERT = (SSL_CB_ALERT | SSL_CB_READ), + SSL_CB_WRITE_ALERT = (SSL_CB_ALERT | SSL_CB_WRITE), + SSL_CB_ACCEPT_LOOP = (SSL_ST_ACCEPT | SSL_CB_LOOP), + SSL_CB_ACCEPT_EXIT = (SSL_ST_ACCEPT | SSL_CB_EXIT), + SSL_CB_CONNECT_LOOP = (SSL_ST_CONNECT | SSL_CB_LOOP), + SSL_CB_CONNECT_EXIT = (SSL_ST_CONNECT | SSL_CB_EXIT), + SSL_CB_MODE_READ = 1, + SSL_CB_MODE_WRITE = 2, SSL_MODE_ENABLE_PARTIAL_WRITE = 2, + SSL_MODE_AUTO_RETRY = 3, /* wolfSSL default is to block with blocking io + * and auto retry */ + SSL_MODE_RELEASE_BUFFERS = -1, /* For libwebsockets build. No current use. */ BIO_FLAGS_BASE64_NO_NL = 1, BIO_CLOSE = 1, BIO_NOCLOSE = 0, - NID_undef = 0, - X509_FILETYPE_PEM = 8, X509_LU_X509 = 9, X509_LU_CRL = 12, - 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_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, + X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, + X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, + X509_V_ERR_CERT_SIGNATURE_FAILURE, + 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_INVALID_CA, + X509_V_ERR_PATH_LENGTH_EXCEEDED, + X509_V_ERR_INVALID_PURPOSE, + X509_V_ERR_AKID_SKID_MISMATCH, + X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH, + X509_V_ERR_KEYUSAGE_NO_CERTSIGN, + X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, + X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION, + X509_V_ERR_KEYUSAGE_NO_CRL_SIGN, + X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION, + X509_V_ERR_INVALID_NON_CA, + X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED, + X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE, + X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED, + X509_V_ERR_INVALID_EXTENSION, + X509_V_ERR_INVALID_POLICY_EXTENSION, + X509_V_ERR_NO_EXPLICIT_POLICY, + X509_V_ERR_UNNESTED_RESOURCE, + X509_V_ERR_APPLICATION_VERIFICATION, - X509_V_OK = 0, + X509_R_CERT_ALREADY_IN_HASH_TABLE, + + XN_FLAG_SPC_EQ = (1 << 23), + XN_FLAG_SEP_CPLUS_SPC = (2 << 16), + XN_FLAG_ONELINE = 0, + XN_FLAG_RFC2253 = 1, + XN_FLAG_DN_REV = (1 << 20), CRYPTO_LOCK = 1, - CRYPTO_NUM_LOCKS = 10 + CRYPTO_NUM_LOCKS = 10, + + ASN1_STRFLGS_ESC_MSB = 4 }; +#endif /* extras end */ #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) /* wolfSSL extension, provide last error from SSL_get_error since not using thread storage error queue */ -WOLFSSL_API void wolfSSL_ERR_print_errors_fp(FILE*, int err); +#include +WOLFSSL_API void wolfSSL_ERR_print_errors_fp(XFILE, int err); +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +WOLFSSL_API void wolfSSL_ERR_dump_errors_fp(XFILE fp); +WOLFSSL_API void wolfSSL_ERR_print_errors_cb(int (*cb)(const char *str, + size_t len, void *u), void *u); +#endif +#endif +WOLFSSL_API void wolfSSL_ERR_print_errors(WOLFSSL_BIO *bio); + + +#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_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_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, + 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, - 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 (*psk_client_callback)(WOLFSSL*, const char*, char*, + typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*, unsigned int, unsigned char*, unsigned int); WOLFSSL_API void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX*, - psk_client_callback); - WOLFSSL_API void wolfSSL_set_psk_client_callback(WOLFSSL*,psk_client_callback); + wc_psk_client_callback); + WOLFSSL_API void wolfSSL_set_psk_client_callback(WOLFSSL*, + wc_psk_client_callback); +#ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_client_tls13_callback)(WOLFSSL*, const char*, + char*, unsigned int, unsigned char*, unsigned int, const char**); + WOLFSSL_API void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX*, + wc_psk_client_tls13_callback); + WOLFSSL_API void wolfSSL_set_psk_client_tls13_callback(WOLFSSL*, + wc_psk_client_tls13_callback); +#endif WOLFSSL_API const char* wolfSSL_get_psk_identity_hint(const WOLFSSL*); WOLFSSL_API const char* wolfSSL_get_psk_identity(const WOLFSSL*); @@ -718,11 +1936,20 @@ enum { /* ssl Constants */ WOLFSSL_API int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX*, const char*); WOLFSSL_API int wolfSSL_use_psk_identity_hint(WOLFSSL*, const char*); - typedef unsigned int (*psk_server_callback)(WOLFSSL*, const char*, + typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*, unsigned char*, unsigned int); WOLFSSL_API void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX*, - psk_server_callback); - WOLFSSL_API void wolfSSL_set_psk_server_callback(WOLFSSL*,psk_server_callback); + wc_psk_server_callback); + WOLFSSL_API void wolfSSL_set_psk_server_callback(WOLFSSL*, + wc_psk_server_callback); +#ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_server_tls13_callback)(WOLFSSL*, const char*, + unsigned char*, unsigned int, const char**); + WOLFSSL_API void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX*, + wc_psk_server_tls13_callback); + WOLFSSL_API void wolfSSL_set_psk_server_tls13_callback(WOLFSSL*, + wc_psk_server_tls13_callback); +#endif #define PSK_TYPES_DEFINED #endif /* NO_PSK */ @@ -734,11 +1961,22 @@ enum { /* ssl Constants */ /* extra begins */ - +#ifdef OPENSSL_EXTRA enum { /* ERR Constants */ ERR_TXT_STRING = 1 }; +/* bio misc */ +enum { + WOLFSSL_BIO_ERROR = -1, + WOLFSSL_BIO_UNSET = -2, + WOLFSSL_BIO_SIZE = 17000 /* default BIO write size if not set */ +}; +#endif + +WOLFSSL_API void wolfSSL_ERR_put_error(int lib, int fun, int err, + const char* file, int line); +WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line(const char**, int*); WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line_data(const char**, int*, const char**, int *); @@ -747,17 +1985,21 @@ WOLFSSL_API void wolfSSL_ERR_clear_error(void); WOLFSSL_API int wolfSSL_RAND_status(void); +WOLFSSL_API int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num); WOLFSSL_API int wolfSSL_RAND_bytes(unsigned char* buf, int num); WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method(void); WOLFSSL_API long wolfSSL_CTX_set_options(WOLFSSL_CTX*, long); +WOLFSSL_API long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx); +WOLFSSL_API long wolfSSL_CTX_clear_options(WOLFSSL_CTX*, long); + #ifndef NO_CERTS - WOLFSSL_API int wolfSSL_CTX_check_private_key(WOLFSSL_CTX*); + WOLFSSL_API int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX*); #endif /* !NO_CERTS */ WOLFSSL_API void wolfSSL_ERR_free_strings(void); WOLFSSL_API void wolfSSL_ERR_remove_state(unsigned long); -WOLFSSL_API void wolfSSL_EVP_cleanup(void); WOLFSSL_API int wolfSSL_clear(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_state(WOLFSSL* ssl); WOLFSSL_API void wolfSSL_cleanup_all_ex_data(void); WOLFSSL_API long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode); @@ -765,21 +2007,50 @@ WOLFSSL_API long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx); WOLFSSL_API void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m); WOLFSSL_API long wolfSSL_SSL_get_mode(WOLFSSL* ssl); -WOLFSSL_API long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX*, long); WOLFSSL_API int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX*); WOLFSSL_API int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX*, const unsigned char*, unsigned int); -WOLFSSL_API WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl); +WOLFSSL_ABI WOLFSSL_API WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL*); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL*); +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl); +#endif +#ifdef OPENSSL_EXTRA +WOLFSSL_API int wolfSSL_want(WOLFSSL*); +#endif WOLFSSL_API int wolfSSL_want_read(WOLFSSL*); WOLFSSL_API int wolfSSL_want_write(WOLFSSL*); +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_EXTRA) +#include /* var_arg */ +WOLFSSL_API int wolfSSL_BIO_vprintf(WOLFSSL_BIO* bio, const char* format, + va_list args); +#endif WOLFSSL_API int wolfSSL_BIO_printf(WOLFSSL_BIO*, const char*, ...); +WOLFSSL_API int wolfSSL_BIO_dump(WOLFSSL_BIO *bio, const char*, int); WOLFSSL_API int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO*, const WOLFSSL_ASN1_UTCTIME*); -WOLFSSL_API int wolfSSL_sk_num(WOLFSSL_X509_REVOKED*); -WOLFSSL_API void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED*, int); +WOLFSSL_API int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO*, + const WOLFSSL_ASN1_GENERALIZEDTIME*); +WOLFSSL_API void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_GENERALIZEDTIME*); +WOLFSSL_API int wolfSSL_ASN1_TIME_check(const WOLFSSL_ASN1_TIME*); +WOLFSSL_API int wolfSSL_ASN1_TIME_diff(int *pday, int *psec, + const WOLFSSL_ASN1_TIME *from, const WOLFSSL_ASN1_TIME *to); +#ifdef OPENSSL_EXTRA +WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_set(WOLFSSL_ASN1_TIME *s, time_t t); +#endif + +WOLFSSL_API int wolfSSL_sk_num(WOLFSSL_STACK* sk); +WOLFSSL_API void* wolfSSL_sk_value(WOLFSSL_STACK* sk, int i); + +#if defined(HAVE_EX_DATA) || defined(FORTRESS) +WOLFSSL_API void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data, + int idx); +WOLFSSL_API int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, + void *data); +#endif /* stunnel 4.28 needs */ WOLFSSL_API void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX*, int); @@ -799,6 +2070,7 @@ WOLFSSL_API long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION*); WOLFSSL_API long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION*); WOLFSSL_API int wolfSSL_CTX_get_ex_new_index(long, void*, void*, void*, void*); + /* extra ends */ @@ -806,33 +2078,35 @@ WOLFSSL_API int wolfSSL_CTX_get_ex_new_index(long, void*, void*, void*, void*); /* call before SSL_connect, if verifying will add name check to date check and signature check */ -WOLFSSL_API int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_check_domain_name(WOLFSSL*, const char*); /* need to call once to load library (session cache) */ -WOLFSSL_API int wolfSSL_Init(void); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_Init(void); /* call when done to cleanup/free session cache mutex / resources */ -WOLFSSL_API int wolfSSL_Cleanup(void); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_Cleanup(void); /* which library version do we have */ WOLFSSL_API const char* wolfSSL_lib_version(void); /* which library version do we have in hex */ -WOLFSSL_API unsigned int wolfSSL_lib_version_hex(void); - -/* turn logging on, only if compiled in */ -WOLFSSL_API int wolfSSL_Debugging_ON(void); -/* turn logging off */ -WOLFSSL_API void wolfSSL_Debugging_OFF(void); +WOLFSSL_API word32 wolfSSL_lib_version_hex(void); /* do accept or connect depedning on side */ WOLFSSL_API int wolfSSL_negotiate(WOLFSSL* ssl); /* turn on wolfSSL data compression */ WOLFSSL_API int wolfSSL_set_compression(WOLFSSL* ssl); -WOLFSSL_API int wolfSSL_set_timeout(WOLFSSL*, unsigned int); -WOLFSSL_API int wolfSSL_CTX_set_timeout(WOLFSSL_CTX*, unsigned int); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_set_timeout(WOLFSSL*, unsigned int); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_set_timeout(WOLFSSL_CTX*, unsigned int); +WOLFSSL_API void wolfSSL_CTX_set_current_time_cb(WOLFSSL_CTX* ctx, + void (*cb)(const WOLFSSL* ssl, WOLFSSL_TIMEVAL* out_clock)); /* 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 */ @@ -842,32 +2116,48 @@ WOLFSSL_API unsigned char* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN*, int idx); /* index cert in X509 */ WOLFSSL_API WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN*, int idx); /* free X509 */ -WOLFSSL_API void wolfSSL_FreeX509(WOLFSSL_X509*); +#define wolfSSL_FreeX509(x509) wolfSSL_X509_free((x509)) +WOLFSSL_ABI WOLFSSL_API void wolfSSL_X509_free(WOLFSSL_X509*); /* get index cert in PEM */ WOLFSSL_API int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN*, int idx, - unsigned char* buffer, int inLen, int* outLen); -WOLFSSL_API const unsigned char* wolfSSL_get_sessionID(const WOLFSSL_SESSION* s); + unsigned char* buf, int inLen, int* outLen); +WOLFSSL_ABI WOLFSSL_API const unsigned char* wolfSSL_get_sessionID( + const WOLFSSL_SESSION* s); WOLFSSL_API int wolfSSL_X509_get_serial_number(WOLFSSL_X509*,unsigned char*,int*); WOLFSSL_API char* wolfSSL_X509_get_subjectCN(WOLFSSL_X509*); WOLFSSL_API const unsigned char* wolfSSL_X509_get_der(WOLFSSL_X509*, int*); -WOLFSSL_API const unsigned char* wolfSSL_X509_notBefore(WOLFSSL_X509*); -WOLFSSL_API const unsigned char* wolfSSL_X509_notAfter(WOLFSSL_X509*); +WOLFSSL_API const unsigned char* wolfSSL_X509_get_tbs(WOLFSSL_X509*, int*); +WOLFSSL_ABI WOLFSSL_API const byte* wolfSSL_X509_notBefore(WOLFSSL_X509*); +WOLFSSL_ABI WOLFSSL_API const byte* wolfSSL_X509_notAfter(WOLFSSL_X509*); WOLFSSL_API int wolfSSL_X509_version(WOLFSSL_X509*); WOLFSSL_API int wolfSSL_cmp_peer_cert_to_file(WOLFSSL*, const char*); -WOLFSSL_API char* wolfSSL_X509_get_next_altname(WOLFSSL_X509*); +WOLFSSL_ABI WOLFSSL_API char* wolfSSL_X509_get_next_altname(WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_X509_add_altname(WOLFSSL_X509*, const char*, int); +WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509, + const unsigned char** in, int len); WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const unsigned char* in, int len); +WOLFSSL_API int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out); +WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL **crl, + const unsigned char *in, int len); +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE file, WOLFSSL_X509_CRL **crl); +#endif +WOLFSSL_API void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl); + #ifndef NO_FILESYSTEM #ifndef NO_STDIO_FILESYSTEM WOLFSSL_API WOLFSSL_X509* - wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, FILE* file); + wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file); #endif -WOLFSSL_API WOLFSSL_X509* +WOLFSSL_ABI WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format); #endif +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer( + const unsigned char* buf, int sz, int format); #ifdef WOLFSSL_SEP WOLFSSL_API unsigned char* @@ -881,12 +2171,35 @@ WOLFSSL_API WOLFSSL_X509* /* connect enough to get peer cert */ WOLFSSL_API int wolfSSL_connect_cert(WOLFSSL* ssl); + + +/* PKCS12 compatibility */ +typedef struct WC_PKCS12 WC_PKCS12; +WOLFSSL_API WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, + WC_PKCS12** pkcs12); +WOLFSSL_API int wolfSSL_i2d_PKCS12_bio(WOLFSSL_BIO *bio, WC_PKCS12 *pkcs12); +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_X509_PKCS12* wolfSSL_d2i_PKCS12_fp(XFILE fp, + WOLFSSL_X509_PKCS12** pkcs12); +#endif +WOLFSSL_API int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, + WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, + WOLF_STACK_OF(WOLFSSL_X509)** ca); +WOLFSSL_API WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name, + WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert, + WOLF_STACK_OF(WOLFSSL_X509)* ca, + int keyNID, int certNID, int itt, int macItt, int keytype); +WOLFSSL_API void wolfSSL_PKCS12_PBE_add(void); + + + #ifndef NO_DH /* server Diffie-Hellman parameters */ WOLFSSL_API int wolfSSL_SetTmpDH(WOLFSSL*, const unsigned char* p, int pSz, const unsigned char* g, int gSz); WOLFSSL_API int wolfSSL_SetTmpDH_buffer(WOLFSSL*, const unsigned char* b, long sz, int format); +WOLFSSL_API int wolfSSL_SetEnableDhKeyTest(WOLFSSL*, int); #ifndef NO_FILESYSTEM WOLFSSL_API int wolfSSL_SetTmpDH_file(WOLFSSL*, const char* f, int format); #endif @@ -902,13 +2215,25 @@ WOLFSSL_API int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX*, const unsigned char* int format); #endif -WOLFSSL_API int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX*, unsigned short); -WOLFSSL_API int wolfSSL_SetMinDhKey_Sz(WOLFSSL*, unsigned short); +WOLFSSL_API int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX*, word16); +WOLFSSL_API int wolfSSL_SetMinDhKey_Sz(WOLFSSL*, word16); +WOLFSSL_API int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX*, word16); +WOLFSSL_API int wolfSSL_SetMaxDhKey_Sz(WOLFSSL*, word16); WOLFSSL_API int wolfSSL_GetDhKey_Sz(WOLFSSL*); #endif /* NO_DH */ -WOLFSSL_API int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL*, unsigned short); -WOLFSSL_API int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX*, unsigned short); +#ifndef NO_RSA +WOLFSSL_API int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX*, short); +WOLFSSL_API int wolfSSL_SetMinRsaKey_Sz(WOLFSSL*, short); +#endif /* NO_RSA */ + +#ifdef HAVE_ECC +WOLFSSL_API int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX*, short); +WOLFSSL_API int wolfSSL_SetMinEccKey_Sz(WOLFSSL*, short); +#endif /* NO_RSA */ + +WOLFSSL_API int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL*, word16); +WOLFSSL_API int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX*, word16); /* keyblock size in bytes or -1 */ /* need to call wolfSSL_KeepArrays before handshake to save keys */ @@ -927,7 +2252,11 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len, #ifdef __PPU #include #include - #elif !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM) && !defined(WOLFSSL_PICOTCP) + #elif !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM) && \ + !defined(WOLFSSL_PICOTCP) && !defined(WOLFSSL_ROWLEY_ARM) && \ + !defined(WOLFSSL_EMBOS) && !defined(WOLFSSL_FROSTED) && \ + !defined(WOLFSSL_CHIBIOS) && !defined(WOLFSSL_CONTIKI) && \ + !defined(WOLFSSL_ZEPHYR) #include #endif /* allow writev style writing */ @@ -940,31 +2269,53 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len, #ifndef NO_CERTS /* SSL_CTX versions */ WOLFSSL_API int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX*); +#ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_API int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX*); + WOLFSSL_API int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX*, + const unsigned char*, long, int); +#endif + WOLFSSL_API int wolfSSL_CTX_load_verify_buffer_ex(WOLFSSL_CTX*, + const unsigned char*, long, int, + int, word32); WOLFSSL_API int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX*, const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX*, + const unsigned char*, long, int); WOLFSSL_API int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX*, const unsigned char*, long, int); WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX*, const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX*, + const unsigned char*, long, int, long); + WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX*, + const unsigned char*, long, int); WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX*, const unsigned char*, long); /* SSL versions */ WOLFSSL_API int wolfSSL_use_certificate_buffer(WOLFSSL*, const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, + const unsigned char* der, int derSz); WOLFSSL_API int wolfSSL_use_PrivateKey_buffer(WOLFSSL*, const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_use_PrivateKey_id(WOLFSSL*, const unsigned char*, + long, int, long); + WOLFSSL_API int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL*, + const unsigned char*, long, int); WOLFSSL_API int wolfSSL_use_certificate_chain_buffer(WOLFSSL*, const unsigned char*, long); WOLFSSL_API int wolfSSL_UnloadCertsKeys(WOLFSSL*); + + #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + defined(KEEP_OUR_CERT) + WOLFSSL_API WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl); + #endif #endif 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 { @@ -981,49 +2332,8 @@ 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*); - #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 byte*, word32); /* I/O Callback default errors */ @@ -1044,18 +2354,30 @@ 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 */ }; -WOLFSSL_API int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version); -WOLFSSL_API int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version); +WOLFSSL_ABI WOLFSSL_API WC_RNG* wolfSSL_GetRNG(WOLFSSL*); + +WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX*, int); +WOLFSSL_API int wolfSSL_SetMinVersion(WOLFSSL*, int); 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 sz, unsigned char*, - int, const char*); -WOLFSSL_API int wolfSSL_CertPemToDer(const unsigned char*, int sz, unsigned char*, - int, int); + +/* moved to asn.c, old names kept for backwards compatibility */ +#define wolfSSL_KeyPemToDer wc_KeyPemToDer +#define wolfSSL_CertPemToDer wc_CertPemToDer +#define wolfSSL_PemPubKeyToDer wc_PemPubKeyToDer +#define wolfSSL_PubKeyPemToDer wc_PubKeyPemToDer +#define wolfSSL_PemCertToDer wc_PemCertToDer + typedef void (*CallbackCACache)(unsigned char* der, int sz, int type); typedef void (*CbMissingCRL)(const char* url); @@ -1063,6 +2385,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, @@ -1077,10 +2403,26 @@ typedef int (*CallbackDecryptVerify)(WOLFSSL* ssl, unsigned int decSz, int content, int verify, unsigned int* padSz, void* ctx); WOLFSSL_API void wolfSSL_CTX_SetDecryptVerifyCb(WOLFSSL_CTX*, - CallbackDecryptVerify); + CallbackDecryptVerify); WOLFSSL_API void wolfSSL_SetDecryptVerifyCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl); +typedef int (*CallbackEncryptMac)(WOLFSSL* ssl, unsigned char* macOut, + int content, int macVerify, unsigned char* encOut, + const unsigned char* encIn, unsigned int encSz, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEncryptMacCb(WOLFSSL_CTX*, CallbackEncryptMac); +WOLFSSL_API void wolfSSL_SetEncryptMacCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEncryptMacCtx(WOLFSSL* ssl); + +typedef int (*CallbackVerifyDecrypt)(WOLFSSL* ssl, + unsigned char* decOut, const unsigned char* decIn, + unsigned int decSz, int content, int verify, unsigned int* padSz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetVerifyDecryptCb(WOLFSSL_CTX*, + CallbackVerifyDecrypt); +WOLFSSL_API void wolfSSL_SetVerifyDecryptCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetVerifyDecryptCtx(WOLFSSL* ssl); + WOLFSSL_API const unsigned char* wolfSSL_GetMacSecret(WOLFSSL*, int); WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteKey(WOLFSSL*); WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteIV(WOLFSSL*); @@ -1097,12 +2439,13 @@ WOLFSSL_API int wolfSSL_GetHmacSize(WOLFSSL*); WOLFSSL_API int wolfSSL_GetHmacType(WOLFSSL*); WOLFSSL_API int wolfSSL_GetCipherType(WOLFSSL*); WOLFSSL_API int wolfSSL_SetTlsHmacInner(WOLFSSL*, unsigned char*, - unsigned int, int, int); + word32, int, int); /* Atomic User Needs */ enum { WOLFSSL_SERVER_END = 0, WOLFSSL_CLIENT_END = 1, + WOLFSSL_NEITHER_END = 3, WOLFSSL_BLOCK_TYPE = 2, WOLFSSL_STREAM_TYPE = 3, WOLFSSL_AEAD_TYPE = 4, @@ -1117,7 +2460,9 @@ enum BulkCipherAlgorithm { wolfssl_des, wolfssl_triple_des, /* leading 3 (3des) not valid identifier */ wolfssl_des40, +#ifdef HAVE_IDEA wolfssl_idea, +#endif wolfssl_aes, wolfssl_aes_gcm, wolfssl_aes_ccm, @@ -1130,19 +2475,31 @@ enum BulkCipherAlgorithm { /* for KDF TLS 1.2 mac types */ enum KDF_MacAlgorithm { - wolfssl_sha256 = 4, /* needs to match internal MACAlgorithm */ + wolfssl_sha256 = 4, /* needs to match hash.h wc_MACAlgorithm */ wolfssl_sha384, wolfssl_sha512 }; /* Public Key Callback support */ +#ifdef HAVE_PK_CALLBACKS +#ifdef HAVE_ECC + +struct ecc_key; + +typedef int (*CallbackEccKeyGen)(WOLFSSL* ssl, struct ecc_key* key, + unsigned int keySz, int ecc_curve, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX*, CallbackEccKeyGen); +WOLFSSL_API void wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl); + typedef int (*CallbackEccSign)(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, - unsigned char* out, unsigned int* outSz, + unsigned char* out, word32* outSz, const unsigned char* keyDer, unsigned int keySz, void* ctx); -WOLFSSL_API void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX*, CallbackEccSign); +WOLFSSL_ABI WOLFSSL_API void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX*, + CallbackEccSign); WOLFSSL_API void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl); @@ -1155,6 +2512,117 @@ WOLFSSL_API void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX*, CallbackEccVerify); WOLFSSL_API void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl); +typedef int (*CallbackEccSharedSecret)(WOLFSSL* ssl, struct ecc_key* otherKey, + unsigned char* pubKeyDer, word32* pubKeySz, + unsigned char* out, word32* outlen, + int side, void* ctx); /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */ +WOLFSSL_API void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX*, CallbackEccSharedSecret); +WOLFSSL_API void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl); +#endif + +#ifndef NO_DH +/* Public DH Key Callback support */ +struct DhKey; +typedef int (*CallbackDhAgree)(WOLFSSL* ssl, struct DhKey* key, + const unsigned char* priv, unsigned int privSz, + const unsigned char* otherPubKeyDer, unsigned int otherPubKeySz, + unsigned char* out, unsigned int* outlen, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX*, CallbackDhAgree); +WOLFSSL_API void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl); +#endif /* !NO_DH */ + +#ifdef HAVE_ED25519 +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); +#endif + +#ifdef HAVE_CURVE25519 +struct curve25519_key; + +typedef int (*CallbackX25519KeyGen)(WOLFSSL* ssl, struct curve25519_key* key, + unsigned int keySz, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX*, CallbackX25519KeyGen); +WOLFSSL_API void wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl); + +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); +#endif + +#ifdef HAVE_ED448 +struct ed448_key; +typedef int (*CallbackEd448Sign)(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_SetEd448SignCb(WOLFSSL_CTX*, + CallbackEd448Sign); +WOLFSSL_API void wolfSSL_SetEd448SignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEd448SignCtx(WOLFSSL* ssl); + +typedef int (*CallbackEd448Verify)(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_SetEd448VerifyCb(WOLFSSL_CTX*, + CallbackEd448Verify); +WOLFSSL_API void wolfSSL_SetEd448VerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEd448VerifyCtx(WOLFSSL* ssl); +#endif + +#ifdef HAVE_CURVE448 +struct curve448_key; + +typedef int (*CallbackX448KeyGen)(WOLFSSL* ssl, struct curve448_key* key, + unsigned int keySz, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetX448KeyGenCb(WOLFSSL_CTX*, CallbackX448KeyGen); +WOLFSSL_API void wolfSSL_SetX448KeyGenCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetX448KeyGenCtx(WOLFSSL* ssl); + +typedef int (*CallbackX448SharedSecret)(WOLFSSL* ssl, + struct curve448_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_SetX448SharedSecretCb(WOLFSSL_CTX*, + CallbackX448SharedSecret); +WOLFSSL_API void wolfSSL_SetX448SharedSecretCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetX448SharedSecretCtx(WOLFSSL* ssl); +#endif + +#ifndef NO_RSA typedef int (*CallbackRsaSign)(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, unsigned char* out, unsigned int* outSz, @@ -1170,9 +2638,35 @@ typedef int (*CallbackRsaVerify)(WOLFSSL* ssl, const unsigned char* keyDer, unsigned int keySz, void* ctx); WOLFSSL_API void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX*, CallbackRsaVerify); +WOLFSSL_API void wolfSSL_CTX_SetRsaSignCheckCb(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_CTX_SetRsaPssSignCheckCb(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, @@ -1192,17 +2686,26 @@ typedef int (*CallbackRsaDec)(WOLFSSL* ssl, WOLFSSL_API void wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX*, CallbackRsaDec); WOLFSSL_API void wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); - +#endif +#endif /* HAVE_PK_CALLBACKS */ #ifndef NO_CERTS - WOLFSSL_API void wolfSSL_CTX_SetCACb(WOLFSSL_CTX*, CallbackCACache); + 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*); WOLFSSL_API int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER*, const char* f, const char* d); + WOLFSSL_API int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER*, + const unsigned char* in, long sz, int format); WOLFSSL_API int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm); +#ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_API int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm); +#endif WOLFSSL_API int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER*, const char* f, int format); WOLFSSL_API int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, @@ -1212,10 +2715,24 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER*, int options); WOLFSSL_API int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER*); - WOLFSSL_API int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER*, const char*, - int, int); + WOLFSSL_API void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm, + VerifyCallback vc); + WOLFSSL_API int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER*, + const char*, int, int); + WOLFSSL_API int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER*, + const unsigned char*, long sz, int); WOLFSSL_API int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER*, CbMissingCRL); + WOLFSSL_API int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER *); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER*, + CbCrlIO); +#endif +#if defined(HAVE_OCSP) + WOLFSSL_API int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *, + byte *response, int responseSz, WOLFSSL_BUFFER_INFO *responseBuffer, + CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest); +#endif WOLFSSL_API int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER*, unsigned char*, int sz); WOLFSSL_API int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER*, @@ -1226,36 +2743,74 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER*, CbOCSPIO, CbOCSPRespFree, void*); + WOLFSSL_API int wolfSSL_CertManagerEnableOCSPStapling( + WOLFSSL_CERT_MANAGER* cm); + WOLFSSL_API int wolfSSL_CertManagerDisableOCSPStapling( + WOLFSSL_CERT_MANAGER* cm); +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) +WOLFSSL_API WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm); +#endif WOLFSSL_API int wolfSSL_EnableCRL(WOLFSSL* ssl, int options); WOLFSSL_API int wolfSSL_DisableCRL(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_LoadCRL(WOLFSSL*, const char*, int, int); + 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); WOLFSSL_API int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX*, const char*, int, int); + 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 */ + +#ifdef SINGLE_THREADED + WOLFSSL_API int wolfSSL_CTX_new_rng(WOLFSSL_CTX*); +#endif + /* end of handshake frees temporary arrays, if user needs for get_keys or psk hints, call KeepArrays before handshake and then FreeArrays when done if don't want to wait for object free */ 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); -/* cavium additions */ -WOLFSSL_API int wolfSSL_UseCavium(WOLFSSL*, int devId); -WOLFSSL_API int wolfSSL_CTX_UseCavium(WOLFSSL_CTX*, int devId); +WOLFSSL_API int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_UseClientSuites(WOLFSSL* ssl); + +/* async additions */ +#define wolfSSL_UseAsync wolfSSL_SetDevId +#define wolfSSL_CTX_UseAsync wolfSSL_CTX_SetDevId +WOLFSSL_ABI WOLFSSL_API int wolfSSL_SetDevId(WOLFSSL*, int devId); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_SetDevId(WOLFSSL_CTX*, int devId); + +/* helpers to get device id and heap */ +WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_GetDevId(WOLFSSL_CTX*, WOLFSSL*); +WOLFSSL_API void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl); /* TLS Extensions */ @@ -1267,41 +2822,100 @@ enum { WOLFSSL_SNI_HOST_NAME = 0 }; -WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL* ssl, unsigned char type, const void* data, - unsigned short size); -WOLFSSL_API int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, unsigned char type, - const void* data, unsigned short size); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL*, unsigned char, + const void*, unsigned short); +WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_UseSNI(WOLFSSL_CTX*, unsigned char, + const void*, unsigned short); #ifndef NO_WOLFSSL_SERVER /* SNI options */ enum { - WOLFSSL_SNI_CONTINUE_ON_MISMATCH = 0x01, /* do not abort on mismatch flag */ - WOLFSSL_SNI_ANSWER_ON_MISMATCH = 0x02 /* fake match on mismatch flag */ + /* Do not abort the handshake if the requested SNI didn't match. */ + WOLFSSL_SNI_CONTINUE_ON_MISMATCH = 0x01, + + /* Behave as if the requested SNI matched in a case of mismatch. */ + /* In this case, the status will be set to WOLFSSL_SNI_FAKE_MATCH. */ + WOLFSSL_SNI_ANSWER_ON_MISMATCH = 0x02, + + /* Abort the handshake if the client didn't send a SNI request. */ + WOLFSSL_SNI_ABORT_ON_ABSENCE = 0x04, }; 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); - -/* SNI status */ -enum { - WOLFSSL_SNI_NO_MATCH = 0, - WOLFSSL_SNI_FAKE_MATCH = 1, /* if WOLFSSL_SNI_ANSWER_ON_MISMATCH is enabled */ - WOLFSSL_SNI_REAL_MATCH = 2 -}; - -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 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 { + WOLFSSL_SNI_NO_MATCH = 0, + WOLFSSL_SNI_FAKE_MATCH = 1, /**< @see WOLFSSL_SNI_ANSWER_ON_MISMATCH */ + WOLFSSL_SNI_REAL_MATCH = 2, + WOLFSSL_SNI_FORCE_KEEP = 3 /** Used with -DWOLFSSL_ALWAYS_KEEP_SNI */ +}; + +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); + +#endif /* HAVE_SNI */ + +/* Trusted CA Key Indication - RFC 6066 (Section 6) */ +#ifdef HAVE_TRUSTED_CA + +/* TCA Identifier Type */ +enum { + WOLFSSL_TRUSTED_CA_PRE_AGREED = 0, + WOLFSSL_TRUSTED_CA_KEY_SHA1 = 1, + WOLFSSL_TRUSTED_CA_X509_NAME = 2, + WOLFSSL_TRUSTED_CA_CERT_SHA1 = 3 +}; + +WOLFSSL_API int wolfSSL_UseTrustedCA(WOLFSSL* ssl, unsigned char type, + const unsigned char* certId, unsigned int certIdSz); +#endif /* HAVE_TRUSTED_CA */ + +/* Application-Layer Protocol Negotiation */ +#ifdef HAVE_ALPN + +/* ALPN status code */ +enum { + WOLFSSL_ALPN_NO_MATCH = 0, + WOLFSSL_ALPN_MATCH = 1, + WOLFSSL_ALPN_CONTINUE_ON_MISMATCH = 2, + WOLFSSL_ALPN_FAILED_ON_MISMATCH = 4, +}; + +enum { + WOLFSSL_MAX_ALPN_PROTO_NAME_LEN = 255, + WOLFSSL_MAX_ALPN_NUMBER = 257 +}; + +#if defined(OPENSSL_ALL) || 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 -#endif + +WOLFSSL_ABI WOLFSSL_API int wolfSSL_UseALPN(WOLFSSL* ssl, + char *protocol_name_list, + unsigned int protocol_name_listSz, + unsigned char options); + +WOLFSSL_API int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name, + unsigned short *size); + +WOLFSSL_API int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, + unsigned short *listSz); +WOLFSSL_API int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list); +#endif /* HAVE_ALPN */ /* Maximum Fragment Length */ #ifdef HAVE_MAX_FRAGMENT @@ -1312,7 +2926,10 @@ enum { WOLFSSL_MFL_2_10 = 2, /* 1024 bytes */ WOLFSSL_MFL_2_11 = 3, /* 2048 bytes */ WOLFSSL_MFL_2_12 = 4, /* 4096 bytes */ - WOLFSSL_MFL_2_13 = 5 /* 8192 bytes *//* wolfSSL ONLY!!! */ + WOLFSSL_MFL_2_13 = 5, /* 8192 bytes *//* wolfSSL ONLY!!! */ + WOLFSSL_MFL_2_8 = 6, /* 256 bytes *//* wolfSSL ONLY!!! */ + WOLFSSL_MFL_MIN = WOLFSSL_MFL_2_9, + WOLFSSL_MFL_MAX = WOLFSSL_MFL_2_8, }; #ifndef NO_WOLFSSL_CLIENT @@ -1321,7 +2938,7 @@ WOLFSSL_API int wolfSSL_UseMaxFragment(WOLFSSL* ssl, unsigned char mfl); WOLFSSL_API int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, unsigned char mfl); #endif -#endif +#endif /* HAVE_MAX_FRAGMENT */ /* Truncated HMAC */ #ifdef HAVE_TRUNCATED_HMAC @@ -1333,31 +2950,128 @@ WOLFSSL_API int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx); #endif #endif -/* Elliptic Curves */ +/* Certificate Status Request */ +/* Certificate Status Type */ enum { - WOLFSSL_ECC_SECP160R1 = 0x10, - WOLFSSL_ECC_SECP192R1 = 0x13, - WOLFSSL_ECC_SECP224R1 = 0x15, - WOLFSSL_ECC_SECP256R1 = 0x17, - WOLFSSL_ECC_SECP384R1 = 0x18, - WOLFSSL_ECC_SECP521R1 = 0x19 + WOLFSSL_CSR_OCSP = 1 +}; + +/* Certificate Status Options (flags) */ +enum { + WOLFSSL_CSR_OCSP_USE_NONCE = 0x01 +}; + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, + unsigned char status_type, unsigned char options); + +WOLFSSL_API int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, + unsigned char status_type, unsigned char options); + +#endif +#endif + +/* Certificate Status Request v2 */ +/* Certificate Status Type */ +enum { + WOLFSSL_CSR2_OCSP = 1, + WOLFSSL_CSR2_OCSP_MULTI = 2 +}; + +/* Certificate Status v2 Options (flags) */ +enum { + WOLFSSL_CSR2_OCSP_USE_NONCE = 0x01 +}; + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, + unsigned char status_type, unsigned char options); + +WOLFSSL_API int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, + unsigned char status_type, unsigned char options); + +#endif +#endif + +/* Named Groups */ +enum { +#if 0 /* Not Supported */ + WOLFSSL_ECC_SECT163K1 = 1, + WOLFSSL_ECC_SECT163R1 = 2, + WOLFSSL_ECC_SECT163R2 = 3, + WOLFSSL_ECC_SECT193R1 = 4, + WOLFSSL_ECC_SECT193R2 = 5, + WOLFSSL_ECC_SECT233K1 = 6, + WOLFSSL_ECC_SECT233R1 = 7, + WOLFSSL_ECC_SECT239K1 = 8, + WOLFSSL_ECC_SECT283K1 = 9, + WOLFSSL_ECC_SECT283R1 = 10, + WOLFSSL_ECC_SECT409K1 = 11, + WOLFSSL_ECC_SECT409R1 = 12, + WOLFSSL_ECC_SECT571K1 = 13, + WOLFSSL_ECC_SECT571R1 = 14, +#endif + 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, + WOLFSSL_ECC_X25519 = 29, + WOLFSSL_ECC_X448 = 30, + + WOLFSSL_FFDHE_2048 = 256, + WOLFSSL_FFDHE_3072 = 257, + WOLFSSL_FFDHE_4096 = 258, + WOLFSSL_FFDHE_6144 = 259, + WOLFSSL_FFDHE_8192 = 260, +}; + +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 #ifndef NO_WOLFSSL_CLIENT -WOLFSSL_API int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, unsigned short name); +WOLFSSL_API int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name); WOLFSSL_API int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, - unsigned short name); + word16 name); #endif #endif +#ifdef WOLFSSL_TLS13 +WOLFSSL_API int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group); +WOLFSSL_API int wolfSSL_NoKeyShares(WOLFSSL* ssl); +#endif + + /* Secure Renegotiation */ #ifdef HAVE_SECURE_RENEGOTIATION WOLFSSL_API int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_UseSecureRenegotiation(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_StartSecureRenegotiation(WOLFSSL* ssl, int resume); WOLFSSL_API int wolfSSL_Rehandshake(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_SecureResume(WOLFSSL* ssl); +WOLFSSL_API long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl); #endif @@ -1367,14 +3081,13 @@ WOLFSSL_API int wolfSSL_Rehandshake(WOLFSSL* ssl); #ifndef NO_WOLFSSL_CLIENT 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_get_SessionTicket(WOLFSSL*, unsigned char*, word32*); +WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL*, const unsigned char*, word32); typedef int (*CallbackSessionTicket)(WOLFSSL*, const unsigned char*, int, void*); WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL*, CallbackSessionTicket, void*); #endif /* NO_WOLFSSL_CLIENT */ -#ifndef NO_WOLFSSL_SERVER #define WOLFSSL_TICKET_NAME_SZ 16 #define WOLFSSL_TICKET_IV_SZ 16 @@ -1387,6 +3100,8 @@ enum TicketEncRet { WOLFSSL_TICKET_RET_CREATE /* existing ticket ok and create new one */ }; +#ifndef NO_WOLFSSL_SERVER + typedef int (*SessionTicketEncCb)(WOLFSSL*, unsigned char key_name[WOLFSSL_TICKET_NAME_SZ], unsigned char iv[WOLFSSL_TICKET_IV_SZ], @@ -1401,11 +3116,40 @@ WOLFSSL_API int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void*); #endif /* HAVE_SESSION_TICKET */ +#ifdef HAVE_QSH +/* Quantum-safe Crypto Schemes */ +enum { + WOLFSSL_NTRU_EESS439 = 0x0101, /* max plaintext length of 65 */ + WOLFSSL_NTRU_EESS593 = 0x0102, /* max plaintext length of 86 */ + WOLFSSL_NTRU_EESS743 = 0x0103, /* max plaintext length of 106 */ + WOLFSSL_LWE_XXX = 0x0201, /* Learning With Error encryption scheme */ + WOLFSSL_HFE_XXX = 0x0301, /* Hidden Field Equation scheme */ + WOLFSSL_NULL_QSH = 0xFFFF /* QSHScheme is not used */ +}; + + +/* test if the connection is using a QSH secure connection return 1 if so */ +WOLFSSL_API int wolfSSL_isQSH(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, unsigned short name); +#ifndef NO_WOLFSSL_CLIENT + /* user control over sending client public key in hello + when flag = 1 will send keys if flag is 0 or function is not called + then will not send keys in the hello extension */ + WOLFSSL_API int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag); +#endif + +#endif /* QSH */ + +/* TLS Extended Master Secret Extension */ +WOLFSSL_API int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx); + + #define WOLFSSL_CRL_MONITOR 0x01 /* monitor this dir flag */ #define WOLFSSL_CRL_START_MON 0x02 /* start monitoring flag */ -/* notify user the hanshake is done */ +/* notify user the handshake is done */ typedef int (*HandShakeDoneCb)(WOLFSSL*, void*); WOLFSSL_API int wolfSSL_SetHsDoneCb(WOLFSSL*, HandShakeDoneCb, void*); @@ -1417,31 +3161,34 @@ WOLFSSL_API int wolfSSL_get_session_stats(unsigned int* active, unsigned int* maxSessions); /* External facing KDF */ WOLFSSL_API -int wolfSSL_MakeTlsMasterSecret(unsigned char* ms, unsigned int msLen, - const unsigned char* pms, unsigned int pmsLen, +int wolfSSL_MakeTlsMasterSecret(unsigned char* ms, word32 msLen, + const unsigned char* pms, word32 pmsLen, const unsigned char* cr, const unsigned char* sr, int tls1_2, int hash_type); WOLFSSL_API -int wolfSSL_DeriveTlsKeys(unsigned char* key_data, unsigned int keyLen, - const unsigned char* ms, unsigned int msLen, +int wolfSSL_MakeTlsExtendedMasterSecret(unsigned char* ms, word32 msLen, + const unsigned char* pms, word32 pmsLen, + const unsigned char* sHash, word32 sHashLen, + int tls1_2, int hash_type); + +WOLFSSL_API +int wolfSSL_DeriveTlsKeys(unsigned char* key_data, word32 keyLen, + const unsigned char* ms, word32 msLen, const unsigned char* sr, const unsigned char* cr, int tls1_2, int hash_type); #ifdef WOLFSSL_CALLBACKS -/* used internally by wolfSSL while OpenSSL types aren't */ -#include - typedef int (*HandShakeCallBack)(HandShakeInfo*); typedef int (*TimeoutCallBack)(TimeoutInfo*); /* wolfSSL connect extension allowing HandShakeCallBack and/or TimeoutCallBack for diagnostics */ WOLFSSL_API int wolfSSL_connect_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack, - Timeval); + WOLFSSL_TIMEVAL); WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack, - Timeval); + WOLFSSL_TIMEVAL); #endif /* WOLFSSL_CALLBACKS */ @@ -1454,6 +3201,662 @@ WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack, WOLFSSL_API void wolfSSL_cert_service(void); #endif +#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* Smaller subset of X509 compatibility functions. Avoid increasing the size of + * this subset and its memory usage */ + +#include +struct WOLFSSL_X509_NAME_ENTRY { + WOLFSSL_ASN1_OBJECT object; /* static object just for keeping grp, type */ + WOLFSSL_ASN1_STRING data; + WOLFSSL_ASN1_STRING* value; /* points to data, for lighttpd port */ + int nid; /* i.e. ASN_COMMON_NAME */ + int set; + int size; +}; + +WOLFSSL_API int wolfSSL_X509_NAME_get_index_by_OBJ(WOLFSSL_X509_NAME *name, + const WOLFSSL_ASN1_OBJECT *obj, + int idx); + +#endif /* OPENSSL_ALL || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + +enum { + WOLFSSL_SYS_ACCEPT = 0, + WOLFSSL_SYS_BIND, + WOLFSSL_SYS_CONNECT, + WOLFSSL_SYS_FOPEN, + WOLFSSL_SYS_FREAD, + WOLFSSL_SYS_GETADDRINFO, + WOLFSSL_SYS_GETSOCKOPT, + WOLFSSL_SYS_GETSOCKNAME, + WOLFSSL_SYS_GETHOSTBYNAME, + WOLFSSL_SYS_GETNAMEINFO, + WOLFSSL_SYS_GETSERVBYNAME, + WOLFSSL_SYS_IOCTLSOCKET, + WOLFSSL_SYS_LISTEN, + WOLFSSL_SYS_OPENDIR, + WOLFSSL_SYS_SETSOCKOPT, + WOLFSSL_SYS_SOCKET +}; + +/* Object functions */ +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_get_type(const WOLFSSL_ASN1_OBJECT *o); +WOLFSSL_API int wolfSSL_OBJ_sn2nid(const char *sn); + +WOLFSSL_API const char* wolfSSL_OBJ_nid2ln(int n); +WOLFSSL_API int wolfSSL_OBJ_ln2nid(const char *ln); +WOLFSSL_API int wolfSSL_OBJ_cmp(const WOLFSSL_ASN1_OBJECT* a, + const WOLFSSL_ASN1_OBJECT* b); +WOLFSSL_API int wolfSSL_OBJ_txt2nid(const char *sn); +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_txt2obj(const char* s, int no_name); + +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int n); +WOLFSSL_LOCAL WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj_ex(int n, WOLFSSL_ASN1_OBJECT *arg_obj); +WOLFSSL_API int wolfSSL_OBJ_obj2txt(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a, int no_name); + +WOLFSSL_API void wolfSSL_OBJ_cleanup(void); +WOLFSSL_API int wolfSSL_OBJ_create(const char *oid, const char *sn, const char *ln); +#ifdef HAVE_ECC +WOLFSSL_LOCAL int NIDToEccEnum(int n); +#endif +/* end of object functions */ + +WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line); +WOLFSSL_API long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt); +WOLFSSL_API long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt,void* pt); +WOLFSSL_API long wolfSSL_CTX_callback_ctrl(WOLFSSL_CTX* ctx, int cmd, void (*fp)(void)); +WOLFSSL_API long wolfSSL_CTX_clear_extra_chain_certs(WOLFSSL_CTX* ctx); + +#ifndef NO_CERTS +WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID( + WOLFSSL_X509_NAME_ENTRY** out, int nid, int type, + const unsigned char* data, int dataSz); +WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_txt( + WOLFSSL_X509_NAME_ENTRY **neIn, const char *txt, int format, + const unsigned char *data, int dataSz); +WOLFSSL_API int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name, + WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set); +WOLFSSL_API int wolfSSL_X509_NAME_add_entry_by_txt(WOLFSSL_X509_NAME *name, + const char *field, int type, const unsigned char *bytes, int len, int loc, + int set); +WOLFSSL_API int wolfSSL_X509_NAME_add_entry_by_NID(WOLFSSL_X509_NAME *name, int nid, + int type, const unsigned char *bytes, + int len, int loc, int set); +WOLFSSL_API int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x, + const WOLFSSL_X509_NAME* y); +WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void); +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509*); +WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_dup(WOLFSSL_X509_NAME*); +WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl); +WOLFSSL_API void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, + int nid, int* c, int* idx); +WOLFSSL_API int wolfSSL_X509_get_ext_count(const WOLFSSL_X509* passedCert); +WOLFSSL_API int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509 *x, int nid, int lastpos); +WOLFSSL_API int wolfSSL_X509_add_ext(WOLFSSL_X509 *x, WOLFSSL_X509_EXTENSION *ex, int loc); +WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509V3_EXT_conf_nid( + WOLF_LHASH_OF(CONF_VALUE)* conf, WOLFSSL_X509V3_CTX* ctx, int nid, + char* value); +WOLFSSL_API void wolfSSL_X509V3_set_ctx(WOLFSSL_X509V3_CTX* ctx, + WOLFSSL_X509* issuer, WOLFSSL_X509* subject, WOLFSSL_X509* req, + WOLFSSL_X509_CRL* crl, int flag); +WOLFSSL_API void wolfSSL_X509V3_set_ctx_nodb(WOLFSSL_X509V3_CTX* ctx); +WOLFSSL_API int wolfSSL_X509_digest(const WOLFSSL_X509* x509, + const WOLFSSL_EVP_MD* digest, unsigned char* buf, unsigned int* len); +WOLFSSL_API int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509); +WOLFSSL_API int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey); +WOLFSSL_API int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, + const 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); +#endif +WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx, + unsigned char* der, long derSz); + +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +WOLFSSL_API int wolfSSL_X509_cmp(const WOLFSSL_X509* a, const WOLFSSL_X509* b); +WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_get_ext(const WOLFSSL_X509* x, int loc); +WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x, int loc); +WOLFSSL_API int wolfSSL_X509_EXTENSION_get_critical(const WOLFSSL_X509_EXTENSION* ex); +WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_new(void); +WOLFSSL_API int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk, + WOLFSSL_X509_EXTENSION* ext); +WOLFSSL_API void wolfSSL_sk_X509_EXTENSION_free(WOLFSSL_STACK* sk); +WOLFSSL_API void wolfSSL_X509_EXTENSION_free(WOLFSSL_X509_EXTENSION* ext_to_free); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_new_x509_ext(void); +#endif + +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_X509_EXTENSION_get_object(WOLFSSL_X509_EXTENSION* ext); +WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_X509_EXTENSION_get_data(WOLFSSL_X509_EXTENSION* ext); +#endif /* NO_CERTS */ + +WOLFSSL_API WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *r); + +WOLFSSL_API int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses, + unsigned char* out, int outSz); +WOLFSSL_API int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses); + +WOLFSSL_API void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, + WOLFSSL_X509_STORE* str); +WOLFSSL_API int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509); +#if !defined(NO_FILESYSTEM) +WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_fp(XFILE fp, + WOLFSSL_X509** x509); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_GetCerts(WOLFSSL_X509_STORE_CTX* s); +#endif +WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, + WOLFSSL_X509** x509); +WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx); + +WOLFSSL_API size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio); +WOLFSSL_API size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b); + +WOLFSSL_API size_t wolfSSL_get_server_random(const WOLFSSL *ssl, + unsigned char *out, size_t outlen); +WOLFSSL_API int wolfSSL_get_server_tmp_key(const WOLFSSL*, WOLFSSL_EVP_PKEY**); + +WOLFSSL_API int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX*, int); +WOLFSSL_API int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX*, int); + +WOLFSSL_API size_t wolfSSL_get_client_random(const WOLFSSL* ssl, + unsigned char* out, size_t outSz); +WOLFSSL_API int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); +WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_PEM_read_bio_X509_CRL(WOLFSSL_BIO *bp, + WOLFSSL_X509_CRL **x, pem_password_cb *cb, void *u); +WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX + (WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_INFO)* wolfSSL_PEM_X509_INFO_read_bio( + WOLFSSL_BIO* bio, WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk, + pem_password_cb* cb, void* u); +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_PEM_read_X509_CRL(XFILE fp, + WOLFSSL_X509_CRL **x, pem_password_cb *cb, void *u); +#endif +WOLFSSL_API int wolfSSL_PEM_get_EVP_CIPHER_INFO(char* header, + EncryptedInfo* cipher); +WOLFSSL_API int wolfSSL_PEM_do_header(EncryptedInfo* cipher, + unsigned char* data, long* len, + pem_password_cb* callback, void* ctx); + +/*lighttp compatibility */ + +struct WOLFSSL_ASN1_BIT_STRING { + int length; + int type; + byte* data; + long flags; +}; + + +#if defined(OPENSSL_EXTRA) \ + || defined(OPENSSL_ALL) \ + || defined(HAVE_LIGHTY) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) +WOLFSSL_API void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne); +WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void); +WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME* name); +WOLFSSL_API char wolfSSL_CTX_use_certificate(WOLFSSL_CTX*, WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX*, WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name); +/* These are to be merged shortly */ +WOLFSSL_API void wolfSSL_set_verify_depth(WOLFSSL *ssl,int depth); +WOLFSSL_API void* wolfSSL_get_app_data( const WOLFSSL *ssl); +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 unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md); +WOLFSSL_API unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n, unsigned char *md); +WOLFSSL_API unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n, unsigned char *md); +WOLFSSL_API unsigned char *wolfSSL_SHA512(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 WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk ); +WOLFSSL_API int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509); + +#ifndef NO_FILESYSTEM +WOLFSSL_API long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c); +WOLFSSL_API long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_fp(XFILE fp, int c); +#endif + +#endif /* OPENSSL_EXTRA || OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#endif /* OPENSSL_EXTRA || OPENSSL_ALL */ + + +#if defined(OPENSSL_ALL) \ + || defined(HAVE_STUNNEL) \ + || defined(HAVE_LIGHTY) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) + +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_file(const char *filename, const char *mode); +WOLFSSL_API long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX*, WOLFSSL_DH*); +WOLFSSL_API WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp, + WOLFSSL_DH **x, pem_password_cb *cb, void *u); +WOLFSSL_API WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, + WOLFSSL_DSA **x, pem_password_cb *cb, void *u); +WOLFSSL_API int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp,WOLFSSL_X509 *x); +WOLFSSL_API int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp,WOLFSSL_X509 *x); +WOLFSSL_API int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x); +#endif /* HAVE_STUNNEL || HAVE_LIGHTY */ + +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && \ + defined(WOLFSSL_CERT_REQ) +WOLFSSL_API int wolfSSL_i2d_X509_REQ(WOLFSSL_X509* req, unsigned char** out); +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_REQ_new(void); +WOLFSSL_API void wolfSSL_X509_REQ_free(WOLFSSL_X509* req); +WOLFSSL_API int wolfSSL_X509_REQ_sign(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey, + const WOLFSSL_EVP_MD *md); +WOLFSSL_API int wolfSSL_X509_REQ_add_extensions(WOLFSSL_X509* req, + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* ext); +WOLFSSL_API int wolfSSL_X509_REQ_set_subject_name(WOLFSSL_X509 *req, + WOLFSSL_X509_NAME *name); +WOLFSSL_API int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, + WOLFSSL_EVP_PKEY *pkey); +#endif + + +#if defined(OPENSSL_ALL) \ + || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) \ + || defined(HAVE_LIGHTY) + +#include + +/* SNI received callback type */ +typedef int (*CallbackSniRecv)(WOLFSSL *ssl, int *ret, void* exArg); + +WOLFSSL_API int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int), + void *(*r) (void *, size_t, const char *, int), void (*f) (void *)); + +WOLFSSL_API void wolfSSL_CRYPTO_cleanup_all_ex_data(void); + +WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_768_prime(WOLFSSL_BIGNUM* bn); +WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_1024_prime(WOLFSSL_BIGNUM* bn); +WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_1536_prime(WOLFSSL_BIGNUM* bn); +WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_2048_prime(WOLFSSL_BIGNUM* bn); +WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_3072_prime(WOLFSSL_BIGNUM* bn); +WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_4096_prime(WOLFSSL_BIGNUM* bn); +WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_6144_prime(WOLFSSL_BIGNUM* bn); +WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_8192_prime(WOLFSSL_BIGNUM* bn); + +WOLFSSL_API WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator, + void (*callback) (int, int, void *), void *cb_arg); + +WOLFSSL_API int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH*, int, int, + void (*callback) (int, int, void *)); + +WOLFSSL_API void wolfSSL_ERR_load_crypto_strings(void); + +WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error(void); + +WOLFSSL_API int wolfSSL_FIPS_mode(void); + +WOLFSSL_API int wolfSSL_FIPS_mode_set(int r); + +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 WOLFSSL_STACK* wolfSSL_sk_X509_new(void); +WOLFSSL_API int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s); + +WOLFSSL_API WOLFSSL_X509_INFO *wolfSSL_X509_INFO_new(void); +WOLFSSL_API void wolfSSL_X509_INFO_free(WOLFSSL_X509_INFO* info); + +WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_X509_INFO_new_null(void); +WOLFSSL_API int wolfSSL_sk_X509_INFO_num(const WOLF_STACK_OF(WOLFSSL_X509_INFO)*); +WOLFSSL_API WOLFSSL_X509_INFO* wolfSSL_sk_X509_INFO_value( + const WOLF_STACK_OF(WOLFSSL_X509_INFO)*, int); +WOLFSSL_API int wolfSSL_sk_X509_INFO_push(WOLF_STACK_OF(WOLFSSL_X509_INFO)*, + WOLFSSL_X509_INFO*); +WOLFSSL_API WOLFSSL_X509_INFO* wolfSSL_sk_X509_INFO_pop(WOLF_STACK_OF(WOLFSSL_X509_INFO)*); +WOLFSSL_API void wolfSSL_sk_X509_INFO_pop_free(WOLF_STACK_OF(WOLFSSL_X509_INFO)*, + void (*f) (WOLFSSL_X509_INFO*)); +WOLFSSL_API void wolfSSL_sk_X509_INFO_free(WOLF_STACK_OF(WOLFSSL_X509_INFO)*); + +typedef int (*wolf_sk_compare_cb)(const void* const *a, + const void* const *b); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_sk_X509_NAME_new( + wolf_sk_compare_cb); +WOLFSSL_API int wolfSSL_sk_X509_NAME_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)*, + WOLFSSL_X509_NAME*); +WOLFSSL_API int wolfSSL_sk_X509_NAME_find(const WOLF_STACK_OF(WOLFSSL_X509_NAME)*, + WOLFSSL_X509_NAME*); +WOLFSSL_API int wolfSSL_sk_X509_NAME_set_cmp_func( + WOLF_STACK_OF(WOLFSSL_X509_NAME)*, wolf_sk_compare_cb); +WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_value(const WOLF_STACK_OF(WOLFSSL_X509_NAME)*, int); +WOLFSSL_API int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME)*); +WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)*); +WOLFSSL_API void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)*, + void (*f) (WOLFSSL_X509_NAME*)); +WOLFSSL_API void wolfSSL_sk_X509_NAME_free(WOLF_STACK_OF(WOLFSSL_X509_NAME) *); + +WOLFSSL_API int wolfSSL_sk_X509_OBJECT_num(const WOLF_STACK_OF(WOLFSSL_X509_OBJECT) *s); + +WOLFSSL_API int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO*,WOLFSSL_X509_NAME*,int, + unsigned long); + +WOLFSSL_API WOLFSSL_ASN1_BIT_STRING* wolfSSL_ASN1_BIT_STRING_new(void); +WOLFSSL_API void wolfSSL_ASN1_BIT_STRING_free(WOLFSSL_ASN1_BIT_STRING*); +WOLFSSL_API WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr( + const WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_ASN1_BIT_STRING_get_bit( + const WOLFSSL_ASN1_BIT_STRING*, int); +WOLFSSL_API int wolfSSL_ASN1_BIT_STRING_set_bit( + WOLFSSL_ASN1_BIT_STRING*, int, int); + +WOLFSSL_API int wolfSSL_CTX_add_session(WOLFSSL_CTX*, WOLFSSL_SESSION*); + +WOLFSSL_API int wolfSSL_version(WOLFSSL*); + +WOLFSSL_API int wolfSSL_get_state(const WOLFSSL*); + +WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_value(WOLF_STACK_OF(WOLFSSL_X509)*, int); + +WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_shift(WOLF_STACK_OF(WOLFSSL_X509)*); + +WOLFSSL_API void* wolfSSL_sk_X509_OBJECT_value(WOLF_STACK_OF(WOLFSSL_X509_OBJECT)*, int); + +WOLFSSL_API void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION*, int); + +WOLFSSL_API int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION*, int, void*); + +WOLFSSL_API int wolfSSL_SESSION_get_ex_new_index(long,void*,void*,void*, + CRYPTO_free_func*); + +WOLFSSL_API int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME*); + + +WOLFSSL_API const unsigned char* wolfSSL_SESSION_get_id(WOLFSSL_SESSION*, + unsigned int*); + +WOLFSSL_API int wolfSSL_SESSION_print(WOLFSSL_BIO*, const WOLFSSL_SESSION*); + +WOLFSSL_API int wolfSSL_set_tlsext_host_name(WOLFSSL *, const char *); + +WOLFSSL_API const char* wolfSSL_get_servername(WOLFSSL *, unsigned char); + +WOLFSSL_API WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL*,WOLFSSL_CTX*); + +WOLFSSL_API VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX*); + +WOLFSSL_API VerifyCallback wolfSSL_get_verify_callback(WOLFSSL*); + +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 int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX *, void*); + +WOLFSSL_API void wolfSSL_ERR_remove_thread_state(void*); + +/* support for deprecated old name */ +#define WOLFSSL_ERR_remove_thread_state wolfSSL_ERR_remove_thread_state + +#ifndef NO_FILESYSTEM +WOLFSSL_API void wolfSSL_print_all_errors_fp(XFILE fp); +#endif + +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 WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( + WOLFSSL_X509_STORE_CTX*, WOLFSSL_X509_NAME*); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* + wolfSSL_X509_STORE_get0_objects(WOLFSSL_X509_STORE *); +WOLFSSL_API WOLFSSL_X509_OBJECT* + wolfSSL_sk_X509_OBJECT_delete(WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* sk, int i); +WOLFSSL_API void wolfSSL_X509_OBJECT_free(WOLFSSL_X509_OBJECT *a); + +WOLFSSL_API void wolfSSL_sk_X509_pop_free(WOLF_STACK_OF(WOLFSSL_X509)* sk, void (*f) (WOLFSSL_X509*)); +#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_LIGHTY */ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) +WOLFSSL_API int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names); +WOLFSSL_API int wolfSSL_set1_curves_list(WOLFSSL* ssl, const char* names); +#endif /* OPENSSL_EXTRA && HAVE_ECC */ + +#if defined(OPENSSL_ALL) || \ + defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +WOLFSSL_API int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx); + +#endif + +#ifdef WOLFSSL_JNI +WOLFSSL_API int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr); +WOLFSSL_API void* wolfSSL_get_jobject(WOLFSSL* ssl); +#endif /* WOLFSSL_JNI */ + + +#ifdef WOLFSSL_ASYNC_CRYPT +WOLFSSL_API int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags); +WOLFSSL_API int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents, + WOLF_EVENT_FLAG flags, int* eventCount); +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifdef OPENSSL_EXTRA +typedef void (*SSL_Msg_Cb)(int write_p, int version, int content_type, + const void *buf, size_t len, WOLFSSL *ssl, void *arg); + +WOLFSSL_API int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb); +WOLFSSL_API int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb); +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); +WOLFSSL_API unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, + int *line, const char **data, int *flags); +WOLFSSL_API int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, + const unsigned char *protos, unsigned int protos_len); +WOLFSSL_API int wolfSSL_set_alpn_protos(WOLFSSL* ssl, + const unsigned char* protos, unsigned int protos_len); +WOLFSSL_API void *wolfSSL_OPENSSL_memdup(const void *data, + size_t siz, const char* file, int line); +WOLFSSL_API void wolfSSL_ERR_load_BIO_strings(void); +#endif + +#if defined(OPENSSL_ALL) \ + || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) +WOLFSSL_API void wolfSSL_OPENSSL_config(char *config_name); +#endif + +#if defined(OPENSSL_ALL) || 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); +#endif + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl); +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 long wolfSSL_get_timeout(WOLFSSL* ssl); +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*); +WOLFSSL_API int wolfSSL_SSL_in_connect_init(WOLFSSL*); + +#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 + +#if defined(HAVE_OCSP) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +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 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 /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || + OPENSSL_EXTRA || HAVE_LIGHTY*/ + +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(OPENSSL_ALL) || 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 WOLFSSL_X509_ALGOR* wolfSSL_X509_ALGOR_new(void); +WOLFSSL_API void wolfSSL_X509_ALGOR_free(WOLFSSL_X509_ALGOR *alg); +WOLFSSL_API const WOLFSSL_X509_ALGOR* wolfSSL_X509_get0_tbs_sigalg(const WOLFSSL_X509 *x); +WOLFSSL_API void wolfSSL_X509_ALGOR_get0(const WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const WOLFSSL_X509_ALGOR *algor); +WOLFSSL_API int wolfSSL_X509_ALGOR_set0(WOLFSSL_X509_ALGOR *algor, WOLFSSL_ASN1_OBJECT *aobj, int ptype, void *pval); +WOLFSSL_API WOLFSSL_ASN1_TYPE* wolfSSL_ASN1_TYPE_new(void); +WOLFSSL_API void wolfSSL_ASN1_TYPE_free(WOLFSSL_ASN1_TYPE* at); +WOLFSSL_API WOLFSSL_X509_PUBKEY *wolfSSL_X509_PUBKEY_new(void); +WOLFSSL_API void wolfSSL_X509_PUBKEY_free(WOLFSSL_X509_PUBKEY *x); +WOLFSSL_API WOLFSSL_X509_PUBKEY *wolfSSL_X509_get_X509_PUBKEY(const WOLFSSL_X509* x509); +WOLFSSL_API int wolfSSL_X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, WOLFSSL_X509_ALGOR **pa, WOLFSSL_X509_PUBKEY *pub); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_X509_PUBKEY_get(WOLFSSL_X509_PUBKEY* key); +WOLFSSL_API int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key); +WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a); +WOLFSSL_API int wolfSSL_i2a_ASN1_OBJECT(WOLFSSL_BIO *bp, 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 wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str, const char *file, const char *dir); +WOLFSSL_API int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *ctx, WOLFSSL_X509_CRL *x); +WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* p); +WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_find( + WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, const WOLFSSL_CIPHER* toFind); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_CIPHER)* wolfSSL_sk_SSL_CIPHER_dup( + WOLF_STACK_OF(WOLFSSL_CIPHER)* in); +WOLFSSL_API void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk); +WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st); +WOLFSSL_API int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk); +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); + +WOLFSSL_API const char *wolfSSL_ASN1_tag2str(int tag); +WOLFSSL_API int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str, unsigned long flags); +WOLFSSL_API int wolfSSL_ASN1_STRING_print(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str); +WOLFSSL_API int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME *t); +WOLFSSL_API unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME *t); +WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, + WOLFSSL_ASN1_TIME **out); +WOLFSSL_API int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp); +WOLFSSL_API int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE *store); +WOLFSSL_API long wolfSSL_X509_get_version(const WOLFSSL_X509 *x); +WOLFSSL_API int wolfSSL_X509_get_signature_nid(const WOLFSSL_X509* x); + +WOLFSSL_API int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY* pkey, const WOLFSSL_EVP_CIPHER* enc, char* passwd, + int passwdSz, pem_password_cb* cb, void* ctx); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** pkey, pem_password_cb* cb, void* u); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey( + WOLFSSL_EVP_PKEY** pkey, const unsigned char** data, long length); +WOLFSSL_API unsigned long wolfSSL_X509_subject_name_hash(const WOLFSSL_X509* x509); + + +#endif /* OPENSSL_EXTRA */ + +#ifdef HAVE_PK_CALLBACKS +WOLFSSL_API int wolfSSL_IsPrivatePkSet(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx); +#endif + +#ifdef HAVE_ENCRYPT_THEN_MAC +WOLFSSL_API int wolfSSL_CTX_AllowEncryptThenMac(WOLFSSL_CTX *, int); +WOLFSSL_API int wolfSSL_AllowEncryptThenMac(WOLFSSL *s, int); +#endif #ifdef __cplusplus } /* extern "C" */ @@ -1461,4 +3864,3 @@ WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack, #endif /* WOLFSSL_SSL_H */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/test.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/test.h index 4c95d72c8..2f133f985 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/test.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/test.h @@ -10,6 +10,11 @@ #include #include #include +#include +#if defined(SHOW_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + #include /* for domain component NID value */ +#endif #ifdef ATOMIC_USER #include @@ -18,12 +23,30 @@ #endif #ifdef HAVE_PK_CALLBACKS #include + #ifndef NO_RSA + #include + #endif #ifdef HAVE_ECC #include #endif /* HAVE_ECC */ + #ifndef NO_DH + #include + #endif /* !NO_DH */ + #ifdef HAVE_ED25519 + #include + #endif /* HAVE_ED25519 */ + #ifdef HAVE_CURVE25519 + #include + #endif /* HAVE_ECC */ + #ifdef HAVE_ED448 + #include + #endif /* HAVE_ED448 */ + #ifdef HAVE_CURVE448 + #include + #endif /* HAVE_ECC */ #endif /*HAVE_PK_CALLBACKS */ -#ifdef USE_WINDOWS_API +#ifdef USE_WINDOWS_API #include #include #ifdef TEST_IPV6 /* don't require newer SDK for IPV4 */ @@ -32,8 +55,24 @@ #endif #define SOCKET_T SOCKET #define SNPRINTF _snprintf -#elif defined(WOLFSSL_MDK_ARM) +#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) #include + #include "rl_net.h" + #define SOCKET_T int + typedef int socklen_t ; + #define inet_addr wolfSSL_inet_addr + static unsigned long wolfSSL_inet_addr(const char *cp) + { + unsigned int a[4] ; unsigned long ret ; + sscanf(cp, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) ; + ret = ((a[3]<<24) + (a[2]<<16) + (a[1]<<8) + a[0]) ; + return(ret) ; + } + #if defined(HAVE_KEIL_RTX) + #define sleep(t) os_dly_wait(t/1000+1); + #elif defined(WOLFSSL_CMSIS_RTOS) || defined(WOLFSSL_CMSIS_RTOSv2) + #define sleep(t) osDelay(t/1000+1); + #endif #elif defined(WOLFSSL_TIRTOS) #include #include @@ -42,13 +81,50 @@ #include #include struct hostent { - char *h_name; /* official name of host */ - char **h_aliases; /* alias list */ - int h_addrtype; /* host address type */ - int h_length; /* length of address */ - char **h_addr_list; /* list of addresses from name server */ + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses from name server */ }; #define SOCKET_T int +#elif defined(WOLFSSL_VXWORKS) + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #define SOCKET_T int +#elif defined(WOLFSSL_ZEPHYR) + #include + #include + #include + #define SOCKET_T int + #define SOL_SOCKET 1 + #define SO_REUSEADDR 201 + #define WOLFSSL_USE_GETADDRINFO + + static unsigned long inet_addr(const char *cp) + { + unsigned int a[4]; unsigned long ret; + int i, j; + for (i=0, j=0; i<4; i++) { + a[i] = 0; + while (cp[j] != '.' && cp[j] != '\0') { + a[i] *= 10; + a[i] += cp[j] - '0'; + j++; + } + } + ret = ((a[3]<<24) + (a[2]<<16) + (a[1]<<8) + a[0]) ; + return(ret) ; + } #else #include #include @@ -74,18 +150,52 @@ #define SNPRINTF snprintf #endif /* USE_WINDOWS_API */ -#ifdef HAVE_CAVIUM - #include "cavium_sysdep.h" - #include "cavium_common.h" - #include "cavium_ioctl.h" +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +#ifdef HAVE_CAVIUM + #include #endif - #ifdef _MSC_VER /* disable conversion warning */ /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ #pragma warning(disable:4244 4996) #endif +#ifndef WOLFSSL_CIPHER_LIST_MAX_SIZE + #define WOLFSSL_CIPHER_LIST_MAX_SIZE 4096 +#endif +/* Buffer for benchmark tests */ +#ifndef TEST_BUFFER_SIZE + #define TEST_BUFFER_SIZE 16384 +#endif + +#ifndef WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MIN + static WC_INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } +#endif /* WOLFSSL_HAVE_MIN */ + +/* Socket Handling */ +#ifndef WOLFSSL_SOCKET_INVALID +#ifdef USE_WINDOWS_API + #define WOLFSSL_SOCKET_INVALID ((SOCKET_T)INVALID_SOCKET) +#elif defined(WOLFSSL_TIRTOS) + #define WOLFSSL_SOCKET_INVALID ((SOCKET_T)-1) +#else + #define WOLFSSL_SOCKET_INVALID (SOCKET_T)(0) +#endif +#endif /* WOLFSSL_SOCKET_INVALID */ + +#ifndef WOLFSSL_SOCKET_IS_INVALID +#if defined(USE_WINDOWS_API) || defined(WOLFSSL_TIRTOS) + #define WOLFSSL_SOCKET_IS_INVALID(s) ((SOCKET_T)(s) == WOLFSSL_SOCKET_INVALID) +#else + #define WOLFSSL_SOCKET_IS_INVALID(s) ((SOCKET_T)(s) < WOLFSSL_SOCKET_INVALID) +#endif +#endif /* WOLFSSL_SOCKET_IS_INVALID */ #if defined(__MACH__) || defined(USE_WINDOWS_API) #ifndef _SOCKLEN_T @@ -96,7 +206,8 @@ /* HPUX doesn't use socklent_t for third parameter to accept, unless _XOPEN_SOURCE_EXTENDED is defined */ -#if !defined(__hpux__) && !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM) +#if !defined(__hpux__) && !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM)\ + && !defined(WOLFSSL_ROWLEY_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) typedef socklen_t* ACCEPT_THIRD_T; #else #if defined _XOPEN_SOURCE_EXTENDED @@ -107,17 +218,6 @@ #endif -#ifdef USE_WINDOWS_API - #define CloseSocket(s) closesocket(s) - #define StartTCP() { WSADATA wsd; WSAStartup(0x0002, &wsd); } -#elif defined(WOLFSSL_MDK_ARM) - #define CloseSocket(s) closesocket(s) - #define StartTCP() -#else - #define CloseSocket(s) close(s) - #define StartTCP() -#endif - #ifdef SINGLE_THREADED typedef unsigned int THREAD_RETURN; @@ -130,7 +230,7 @@ #define WOLFSSL_THREAD #define INFINITE -1 #define WAIT_OBJECT_0 0L - #elif defined(WOLFSSL_MDK_ARM) + #elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) typedef unsigned int THREAD_RETURN; typedef int THREAD_TYPE; #define WOLFSSL_THREAD @@ -138,6 +238,10 @@ typedef void THREAD_RETURN; typedef Task_Handle THREAD_TYPE; #define WOLFSSL_THREAD + #elif defined(WOLFSSL_ZEPHYR) + typedef void THREAD_RETURN; + typedef struct k_thread THREAD_TYPE; + #define WOLFSSL_THREAD #else typedef unsigned int THREAD_RETURN; typedef intptr_t THREAD_TYPE; @@ -153,47 +257,147 @@ typedef struct sockaddr_in SOCKADDR_IN_T; #define AF_INET_V AF_INET #endif - + +#ifndef WOLFSSL_NO_TLS12 #define SERVER_DEFAULT_VERSION 3 +#else +#define SERVER_DEFAULT_VERSION 4 +#endif #define SERVER_DTLS_DEFAULT_VERSION (-2) #define SERVER_INVALID_VERSION (-99) +#define SERVER_DOWNGRADE_VERSION (-98) +#ifndef WOLFSSL_NO_TLS12 #define CLIENT_DEFAULT_VERSION 3 +#else +#define CLIENT_DEFAULT_VERSION 4 +#endif #define CLIENT_DTLS_DEFAULT_VERSION (-2) #define CLIENT_INVALID_VERSION (-99) +#define CLIENT_DOWNGRADE_VERSION (-98) +#define EITHER_DOWNGRADE_VERSION (-97) #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH) #define DEFAULT_MIN_DHKEY_BITS 2048 + #define DEFAULT_MAX_DHKEY_BITS 3072 #else #define DEFAULT_MIN_DHKEY_BITS 1024 + #define DEFAULT_MAX_DHKEY_BITS 2048 +#endif +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH) + #define DEFAULT_MIN_RSAKEY_BITS 2048 +#else + #define DEFAULT_MIN_RSAKEY_BITS 1024 +#endif +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH) + #define DEFAULT_MIN_ECCKEY_BITS 256 +#else + #define DEFAULT_MIN_ECCKEY_BITS 224 #endif /* all certs relative to wolfSSL home directory now */ -#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" +#if defined(WOLFSSL_NO_CURRDIR) || defined(WOLFSSL_MDK_SHELL) +#define caCertFile "certs/ca-cert.pem" +#define eccCertFile "certs/server-ecc.pem" +#define eccKeyFile "certs/ecc-key.pem" +#define eccRsaCertFile "certs/server-ecc-rsa.pem" +#define svrCertFile "certs/server-cert.pem" +#define svrKeyFile "certs/server-key.pem" +#define cliCertFile "certs/client-cert.pem" +#define cliCertDerFile "certs/client-cert.der" +#define cliCertFileExt "certs/client-cert-ext.pem" +#define cliCertDerFileExt "certs/client-cert-ext.der" +#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" +#define edCertFile "certs/ed25519/server-ed25519-cert.pem" +#define edKeyFile "certs/ed25519/server-ed25519-priv.pem" +#define cliEdCertFile "certs/ed25519/client-ed25519.pem" +#define cliEdKeyFile "certs/ed25519/client-ed25519-priv.pem" +#define caEdCertFile "certs/ed25519/ca-ed25519.pem" +#define ed448CertFile "certs/ed448/server-ed448-cert.pem" +#define ed448KeyFile "certs/ed448/server-ed448-priv.pem" +#define cliEd448CertFile "certs/ed448/client-ed448.pem" +#define cliEd448KeyFile "certs/ed448/client-ed448-priv.pem" +#define caEd448CertFile "certs/ed448/ca-ed448.pem" +#ifdef HAVE_WNR + /* Whitewood netRandom default config file */ + #define wnrConfig "wnr-example.conf" +#endif +#else +#define caCertFile "./certs/ca-cert.pem" +#define eccCertFile "./certs/server-ecc.pem" +#define eccKeyFile "./certs/ecc-key.pem" +#define eccRsaCertFile "./certs/server-ecc-rsa.pem" +#define svrCertFile "./certs/server-cert.pem" +#define svrKeyFile "./certs/server-key.pem" +#define cliCertFile "./certs/client-cert.pem" +#define cliCertDerFile "./certs/client-cert.der" +#define cliCertFileExt "./certs/client-cert-ext.pem" +#define cliCertDerFileExt "./certs/client-cert-ext.der" +#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" +#define edCertFile "./certs/ed25519/server-ed25519-cert.pem" +#define edKeyFile "./certs/ed25519/server-ed25519-priv.pem" +#define cliEdCertFile "./certs/ed25519/client-ed25519.pem" +#define cliEdKeyFile "./certs/ed25519/client-ed25519-priv.pem" +#define caEdCertFile "./certs/ed25519/ca-ed25519.pem" +#define ed448CertFile "./certs/ed448/server-ed448-cert.pem" +#define ed448KeyFile "./certs/ed448/server-ed448-priv.pem" +#define cliEd448CertFile "./certs/ed448/client-ed448.pem" +#define cliEd448KeyFile "./certs/ed448/client-ed448-priv.pem" +#define caEd448CertFile "./certs/ed448/ca-ed448.pem" +#ifdef HAVE_WNR + /* Whitewood netRandom default config file */ + #define wnrConfig "./wnr-example.conf" +#endif +#endif typedef struct tcp_ready { word16 ready; /* predicate */ word16 port; + char* srfName; /* server ready file name */ #if defined(_POSIX_THREADS) && !defined(__MINGW32__) pthread_mutex_t mutex; pthread_cond_t cond; #endif -} tcp_ready; +} tcp_ready; -void InitTcpReady(tcp_ready*); -void FreeTcpReady(tcp_ready*); +static WC_INLINE void InitTcpReady(tcp_ready* ready) +{ + ready->ready = 0; + ready->port = 0; + ready->srfName = NULL; +#ifdef SINGLE_THREADED +#elif defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_init(&ready->mutex, 0); + pthread_cond_init(&ready->cond, 0); +#endif +} + + +static WC_INLINE void FreeTcpReady(tcp_ready* ready) +{ +#ifdef SINGLE_THREADED + (void)ready; +#elif defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_destroy(&ready->mutex); + pthread_cond_destroy(&ready->cond); +#else + (void)ready; +#endif +} typedef WOLFSSL_METHOD* (*method_provider)(void); typedef void (*ctx_callback)(WOLFSSL_CTX* ctx); @@ -204,6 +408,7 @@ typedef struct callback_functions { ctx_callback ctx_ready; ssl_callback ssl_ready; ssl_callback on_result; + WOLFSSL_CTX* ctx; } callback_functions; typedef struct func_args { @@ -214,9 +419,16 @@ typedef struct func_args { callback_functions *callbacks; } func_args; + + + void wait_tcp_ready(func_args*); +#ifdef WOLFSSL_ZEPHYR +typedef void THREAD_FUNC(void*, void*, void*); +#else typedef THREAD_RETURN WOLFSSL_THREAD THREAD_FUNC(void*); +#endif void start_thread(THREAD_FUNC, func_args*, THREAD_TYPE*); void join_thread(THREAD_TYPE); @@ -229,26 +441,70 @@ void join_thread(THREAD_TYPE); #endif static const word16 wolfSSLPort = 11111; -static INLINE void err_sys(const char* msg) + + +#ifndef MY_EX_USAGE +#define MY_EX_USAGE 2 +#endif + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + +#if defined(WOLFSSL_FORCE_MALLOC_FAIL_TEST) || defined(WOLFSSL_ZEPHYR) + #ifndef EXIT_SUCCESS + #define EXIT_SUCCESS 0 + #endif + #define XEXIT(rc) return rc + #define XEXIT_T(rc) return (THREAD_RETURN)rc +#else + #define XEXIT(rc) exit((int)(rc)) + #define XEXIT_T(rc) exit((int)(rc)) +#endif + + +static WC_INLINE +#if defined(WOLFSSL_FORCE_MALLOC_FAIL_TEST) || defined(WOLFSSL_ZEPHYR) +THREAD_RETURN +#else +WC_NORETURN void +#endif +err_sys(const char* msg) { printf("wolfSSL error: %s\n", msg); + +#if !defined(__GNUC__) + /* scan-build (which pretends to be gnuc) can get confused and think the + * msg pointer can be null even when hardcoded and then it won't exit, + * making null pointer checks above the err_sys() call useless. + * We could just always exit() but some compilers will complain about no + * possible return, with gcc we know the attribute to handle that with + * WC_NORETURN. */ if (msg) - exit(EXIT_FAILURE); +#endif + { + XEXIT_T(EXIT_FAILURE); + } } -#define MY_EX_USAGE 2 - extern int myoptind; extern char* myoptarg; -static INLINE int mygetopt(int argc, char** argv, const char* optstring) +static WC_INLINE int mygetopt(int argc, char** argv, const char* optstring) { static char* next = NULL; char c; char* cp; + /* Added sanity check becuase scan-build complains argv[myoptind] access + * results in a null pointer dereference. */ + if (argv == NULL) { + myoptarg = NULL; + return -1; + } + if (myoptind == 0) next = NULL; /* we're starting new/over */ @@ -256,8 +512,8 @@ static INLINE int mygetopt(int argc, char** argv, const char* optstring) if (myoptind == 0) myoptind++; - if (myoptind >= argc || argv[myoptind][0] != '-' || - argv[myoptind][1] == '\0') { + if (myoptind >= argc || argv[myoptind] == NULL || + argv[myoptind][0] != '-' || argv[myoptind][1] == '\0') { myoptarg = NULL; if (myoptind < argc) myoptarg = argv[myoptind]; @@ -284,7 +540,7 @@ static INLINE int mygetopt(int argc, char** argv, const char* optstring) /* The C++ strchr can return a different value */ cp = (char*)strchr(optstring, c); - if (cp == NULL || c == ':') + if (cp == NULL || c == ':') return '?'; cp++; @@ -298,7 +554,7 @@ static INLINE int mygetopt(int argc, char** argv, const char* optstring) myoptarg = argv[myoptind]; myoptind++; } - else + else return '?'; } @@ -306,46 +562,110 @@ static INLINE int mygetopt(int argc, char** argv, const char* optstring) } -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +#ifdef WOLFSSL_ENCRYPTED_KEYS -static INLINE int PasswordCallBack(char* passwd, int sz, int rw, void* userdata) +static WC_INLINE int PasswordCallBack(char* passwd, int sz, int rw, void* userdata) { (void)rw; (void)userdata; - strncpy(passwd, "yassl123", sz); - return 8; + if (userdata != NULL) { + strncpy(passwd, (char*)userdata, sz); + return (int)XSTRLEN((char*)userdata); + } + else { + strncpy(passwd, "yassl123", sz); + return 8; + } } #endif +static const char* client_showpeer_msg[][8] = { + /* English */ + { + "SSL version is", + "SSL cipher suite is", + "SSL curve name is", + "SSL DH size is", + "SSL reused session", + "Alternate cert chain used", + "peer's cert info:", + NULL + }, +#ifndef NO_MULTIBYTE_PRINT + /* Japanese */ + { + "SSL バージョンは", + "SSL 暗号スイートは", + "SSL 曲線名は", + "SSL DH サイズは", + "SSL 再利用セッション", + "代替証明チェーンを使用", + "相手方証明書情報", + NULL + }, +#endif +}; -#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) +#if defined(KEEP_PEER_CERT) || defined(KEEP_OUR_CERT) || defined(SESSION_CERTS) +static const char* client_showx509_msg[][5] = { + /* English */ + { + "issuer", + "subject", + "altname", + "serial number", + NULL + }, +#ifndef NO_MULTIBYTE_PRINT + /* Japanese */ + { + "発行者", + "サブジェクト", + "代替名", + "シリアル番号", + NULL + }, +#endif +}; -static INLINE void ShowX509(WOLFSSL_X509* x509, const char* hdr) +/* lng_index is to specify the language for displaying message. */ +/* 0:English, 1:Japanese */ +static WC_INLINE void ShowX509Ex(WOLFSSL_X509* x509, const char* hdr, + int lng_index) { char* altName; - char* issuer = wolfSSL_X509_NAME_oneline( - wolfSSL_X509_get_issuer_name(x509), 0, 0); - char* subject = wolfSSL_X509_NAME_oneline( - wolfSSL_X509_get_subject_name(x509), 0, 0); + char* issuer; + char* subject; byte serial[32]; int ret; int sz = sizeof(serial); - - printf("%s\n issuer : %s\n subject: %s\n", hdr, issuer, subject); + const char** words = client_showx509_msg[lng_index]; + + if (x509 == NULL) { + printf("%s No Cert\n", hdr); + return; + } + + issuer = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_issuer_name(x509), 0, 0); + subject = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_subject_name(x509), 0, 0); + + printf("%s\n %s : %s\n %s: %s\n", hdr, words[0], issuer, words[1], subject); while ( (altName = wolfSSL_X509_get_next_altname(x509)) != NULL) - printf(" altname = %s\n", altName); + printf(" %s = %s\n", words[2], 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]; /* testsuite has multiple threads writing to stdout, get output message ready to write once */ - strLen = sprintf(serialMsg, " serial number"); + strLen = sprintf(serialMsg, " %s", words[3]); for (i = 0; i < sz; i++) sprintf(serialMsg + strLen + (i*3), ":%02x ", serial[i]); printf("%s\n", serialMsg); @@ -353,81 +673,185 @@ static INLINE void ShowX509(WOLFSSL_X509* x509, const char* hdr) XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL); XFREE(issuer, 0, DYNAMIC_TYPE_OPENSSL); + +#if defined(SHOW_CERTS) && defined(OPENSSL_EXTRA) + { + WOLFSSL_BIO* bio; + char buf[256]; /* should be size of ASN_NAME_MAX */ + int textSz; + + /* print out domain component if certificate has it */ + textSz = wolfSSL_X509_NAME_get_text_by_NID( + wolfSSL_X509_get_subject_name(x509), NID_domainComponent, + buf, sizeof(buf)); + if (textSz > 0) { + printf("Domain Component = %s\n", buf); + } + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio != NULL) { + wolfSSL_BIO_set_fp(bio, stdout, BIO_NOCLOSE); + wolfSSL_X509_print(bio, x509); + wolfSSL_BIO_free(bio); + } + } +#endif /* SHOW_CERTS && OPENSSL_EXTRA */ +} +/* original ShowX509 to maintain compatibility */ +static WC_INLINE void ShowX509(WOLFSSL_X509* x509, const char* hdr) +{ + ShowX509Ex(x509, hdr, 0); } -#endif /* KEEP_PEER_CERT || SESSION_CERTS */ +#endif /* KEEP_PEER_CERT || KEEP_OUR_CERT || SESSION_CERTS */ - -static INLINE void showPeer(WOLFSSL* ssl) +#if defined(SHOW_CERTS) && defined(SESSION_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +static WC_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 /* SHOW_CERTS && SESSION_CERTS */ + +/* lng_index is to specify the language for displaying message. */ +/* 0:English, 1:Japanese */ +static WC_INLINE void showPeerEx(WOLFSSL* ssl, int lng_index) +{ WOLFSSL_CIPHER* cipher; + const char** words = client_showpeer_msg[lng_index]; + +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \ + !defined(NO_DH) + const char *name; +#endif +#ifndef NO_DH + int bits; +#endif #ifdef KEEP_PEER_CERT WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); if (peer) - ShowX509(peer, "peer's cert info:"); + ShowX509Ex(peer, words[6], lng_index); else printf("peer has no cert!\n"); + wolfSSL_FreeX509(peer); #endif - printf("SSL version is %s\n", wolfSSL_get_version(ssl)); +#if defined(SHOW_CERTS) && defined(KEEP_OUR_CERT) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + ShowX509(wolfSSL_get_certificate(ssl), "our cert info:"); + printf("Peer verify result = %lu\n", wolfSSL_get_verify_result(ssl)); +#endif /* SHOW_CERTS && KEEP_OUR_CERT */ + printf("%s %s\n", words[0], wolfSSL_get_version(ssl)); cipher = wolfSSL_get_current_cipher(ssl); - printf("SSL cipher suite is %s\n", wolfSSL_CIPHER_get_name(cipher)); - -#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; - - for (i = 0; i < count; i++) { - int length; - unsigned char buffer[3072]; - WOLFSSL_X509* chainX509; - - 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 HAVE_QSH + printf("%s %s%s\n", words[1], (wolfSSL_isQSH(ssl))? "QSH:": "", + wolfSSL_CIPHER_get_name(cipher)); +#else + printf("%s %s\n", words[1], wolfSSL_CIPHER_get_name(cipher)); #endif +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \ + !defined(NO_DH) + if ((name = wolfSSL_get_curve_name(ssl)) != NULL) + printf("%s %s\n", words[2], name); +#endif +#ifndef NO_DH + else if ((bits = wolfSSL_GetDhKey_Sz(ssl)) > 0) + printf("%s %d bits\n", words[3], bits); +#endif + if (wolfSSL_session_reused(ssl)) + printf("%s\n", words[4]); +#ifdef WOLFSSL_ALT_CERT_CHAINS + if (wolfSSL_is_peer_alt_cert_chain(ssl)) + printf("%s\n", words[5]); +#endif + +#if defined(SHOW_CERTS) && defined(SESSION_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + { + WOLFSSL_X509_CHAIN* chain; + + chain = wolfSSL_get_peer_chain(ssl); + ShowX509Chain(chain, wolfSSL_get_chain_count(chain), "session cert"); + + #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 /* SHOW_CERTS && SESSION_CERTS */ (void)ssl; } +/* original showPeer to maintain compatibility */ +static WC_INLINE void showPeer(WOLFSSL* ssl) +{ + showPeerEx(ssl, 0); +} - -static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, - word16 port, int udp) +static WC_INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, + word16 port, int udp, int sctp) { int useLookup = 0; (void)useLookup; (void)udp; + (void)sctp; - memset(addr, 0, sizeof(SOCKADDR_IN_T)); + if (addr == NULL) + err_sys("invalid argument to build_addr, addr is NULL"); + + XMEMSET(addr, 0, sizeof(SOCKADDR_IN_T)); #ifndef TEST_IPV6 /* peer could be in human readable form */ - if ( (peer != INADDR_ANY) && isalpha((int)peer[0])) { - #ifdef WOLFSSL_MDK_ARM + if ( ((size_t)peer != INADDR_ANY) && isalpha((int)peer[0])) { + #ifndef WOLFSSL_USE_GETADDRINFO + #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) int err; struct hostent* entry = gethostbyname(peer, &err); #elif defined(WOLFSSL_TIRTOS) struct hostent* entry = DNSGetHostByName(peer); + #elif defined(WOLFSSL_VXWORKS) + struct hostent* entry = (struct hostent*)hostGetByName((char*)peer); #else struct hostent* entry = gethostbyname(peer); #endif if (entry) { - memcpy(&addr->sin_addr.s_addr, entry->h_addr_list[0], + XMEMCPY(&addr->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length); useLookup = 1; } + #else + struct zsock_addrinfo hints, *addrInfo; + char portStr[6]; + XSNPRINTF(portStr, sizeof(portStr), "%d", port); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP; + if (getaddrinfo((char*)peer, portStr, &hints, &addrInfo) == 0) { + XMEMCPY(addr, addrInfo->ai_addr, sizeof(*addr)); + useLookup = 1; + } + #endif else err_sys("no entry for host"); } @@ -435,13 +859,13 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, #ifndef TEST_IPV6 - #if defined(WOLFSSL_MDK_ARM) + #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) addr->sin_family = PF_INET; #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) @@ -449,21 +873,34 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, } #else addr->sin6_family = AF_INET_V; - addr->sin6_port = htons(port); - if (peer == INADDR_ANY) + addr->sin6_port = XHTONS(port); + if ((size_t)peer == INADDR_ANY) { addr->sin6_addr = in6addr_any; + } else { - #ifdef HAVE_GETADDRINFO + #if defined(HAVE_GETADDRINFO) || defined(WOLF_C99) struct addrinfo hints; struct addrinfo* answer = NULL; int ret; char strPort[80]; - memset(&hints, 0, sizeof(hints)); + XMEMSET(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET_V; - hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM; - hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP; + if (udp) { + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } + #ifdef WOLFSSL_SCTP + else if (sctp) { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_SCTP; + } + #endif + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + } SNPRINTF(strPort, sizeof(strPort), "%d", port); strPort[79] = '\0'; @@ -472,7 +909,7 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, if (ret < 0 || answer == NULL) err_sys("getaddrinfo failed"); - memcpy(addr, answer->ai_addr, answer->ai_addrlen); + XMEMCPY(addr, answer->ai_addr, answer->ai_addrlen); freeaddrinfo(answer); #else printf("no ipv6 getaddrinfo, loopback only tests/examples\n"); @@ -483,25 +920,24 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, } -static INLINE void tcp_socket(SOCKET_T* sockfd, int udp) +static WC_INLINE void tcp_socket(SOCKET_T* sockfd, int udp, int sctp) { + (void)sctp; + if (udp) - *sockfd = socket(AF_INET_V, SOCK_DGRAM, 0); - else - *sockfd = socket(AF_INET_V, SOCK_STREAM, 0); - -#ifdef USE_WINDOWS_API - if (*sockfd == INVALID_SOCKET) - err_sys("socket failed\n"); -#elif defined(WOLFSSL_TIRTOS) - if (*sockfd == -1) - err_sys("socket failed\n"); -#else - if (*sockfd < 0) - err_sys("socket failed\n"); + *sockfd = socket(AF_INET_V, SOCK_DGRAM, IPPROTO_UDP); +#ifdef WOLFSSL_SCTP + else if (sctp) + *sockfd = socket(AF_INET_V, SOCK_STREAM, IPPROTO_SCTP); #endif + else + *sockfd = socket(AF_INET_V, SOCK_STREAM, IPPROTO_TCP); -#ifndef USE_WINDOWS_API + if(WOLFSSL_SOCKET_IS_INVALID(*sockfd)) { + err_sys("socket failed\n"); + } + +#ifndef USE_WINDOWS_API #ifdef SO_NOSIGPIPE { int on = 1; @@ -510,14 +946,15 @@ static INLINE void tcp_socket(SOCKET_T* sockfd, int udp) if (res < 0) err_sys("setsockopt SO_NOSIGPIPE failed\n"); } -#elif defined(WOLFSSL_MDK_ARM) || defined (WOLFSSL_TIRTOS) +#elif defined(WOLFSSL_MDK_ARM) || defined (WOLFSSL_TIRTOS) ||\ + defined(WOLFSSL_KEIL_TCP_NET) || defined(WOLFSSL_ZEPHYR) /* nothing to define */ #else /* no S_NOSIGPIPE */ signal(SIGPIPE, SIG_IGN); #endif /* S_NOSIGPIPE */ #if defined(TCP_NODELAY) - if (!udp) + if (!udp && !sctp) { int on = 1; socklen_t len = sizeof(on); @@ -529,12 +966,15 @@ static INLINE void tcp_socket(SOCKET_T* sockfd, int udp) #endif /* USE_WINDOWS_API */ } -static INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port, - int udp) +static WC_INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port, + int udp, int sctp, WOLFSSL* ssl) { SOCKADDR_IN_T addr; - build_addr(&addr, ip, port, udp); - tcp_socket(sockfd, udp); + build_addr(&addr, ip, port, udp, sctp); + if (udp) { + wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr)); + } + tcp_socket(sockfd, udp, sctp); if (!udp) { if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) @@ -543,7 +983,7 @@ static INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port, } -static INLINE void udp_connect(SOCKET_T* sockfd, void* addr, int addrSz) +static WC_INLINE void udp_connect(SOCKET_T* sockfd, void* addr, int addrSz) { if (connect(*sockfd, (const struct sockaddr*)addr, addrSz) != 0) err_sys("tcp connect failed"); @@ -554,55 +994,91 @@ enum { TEST_SELECT_FAIL, TEST_TIMEOUT, TEST_RECV_READY, + TEST_SEND_READY, TEST_ERROR_READY }; -#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_TIRTOS) -static INLINE int tcp_select(SOCKET_T socketfd, int to_sec) +#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) && \ + !defined(WOLFSSL_TIRTOS) +static WC_INLINE int tcp_select_ex(SOCKET_T socketfd, int to_sec, int rx) { - fd_set recvfds, errfds; + fd_set fds, errfds; + fd_set* recvfds = NULL; + fd_set* sendfds = NULL; SOCKET_T nfds = socketfd + 1; - struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0}; +#if !defined(__INTEGRITY) + struct timeval timeout = {(to_sec > 0) ? to_sec : 0, 0}; +#else + struct timeval timeout; +#endif int result; - FD_ZERO(&recvfds); - FD_SET(socketfd, &recvfds); + FD_ZERO(&fds); + FD_SET(socketfd, &fds); FD_ZERO(&errfds); FD_SET(socketfd, &errfds); - result = select(nfds, &recvfds, NULL, &errfds, &timeout); + if (rx) + recvfds = &fds; + else + sendfds = &fds; + +#if defined(__INTEGRITY) + timeout.tv_sec = (long long)(to_sec > 0) ? to_sec : 0, 0; +#endif + result = select(nfds, recvfds, sendfds, &errfds, &timeout); if (result == 0) return TEST_TIMEOUT; else if (result > 0) { - if (FD_ISSET(socketfd, &recvfds)) - return TEST_RECV_READY; + if (FD_ISSET(socketfd, &fds)) { + if (rx) + return TEST_RECV_READY; + else + return TEST_SEND_READY; + } else if(FD_ISSET(socketfd, &errfds)) return TEST_ERROR_READY; } return TEST_SELECT_FAIL; } -#elif defined(WOLFSSL_TIRTOS) -static INLINE int tcp_select(SOCKET_T socketfd, int to_sec) + +static WC_INLINE int tcp_select(SOCKET_T socketfd, int to_sec) +{ + return tcp_select_ex(socketfd, to_sec, 1); +} + +static WC_INLINE int tcp_select_tx(SOCKET_T socketfd, int to_sec) +{ + return tcp_select_ex(socketfd, to_sec, 0); +} + +#elif defined(WOLFSSL_TIRTOS) || defined(WOLFSSL_KEIL_TCP_NET) +static WC_INLINE int tcp_select(SOCKET_T socketfd, int to_sec) { return TEST_RECV_READY; } +static WC_INLINE int tcp_select_tx(SOCKET_T socketfd, int to_sec) +{ + return TEST_SEND_READY; +} #endif /* !WOLFSSL_MDK_ARM */ -static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, - int udp) +static WC_INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, + int udp, int sctp) { SOCKADDR_IN_T addr; /* don't use INADDR_ANY by default, firewall may block, make user switch on */ - build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), *port, udp); - tcp_socket(sockfd, udp); + build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), *port, udp, sctp); + tcp_socket(sockfd, udp, sctp); -#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM) +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\ + && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_ZEPHYR) { int res, on = 1; socklen_t len = sizeof(on); @@ -615,17 +1091,23 @@ static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) err_sys("tcp bind failed"); if (!udp) { - if (listen(*sockfd, 5) != 0) - err_sys("tcp listen failed"); + #ifdef WOLFSSL_KEIL_TCP_NET + #define SOCK_LISTEN_MAX_QUEUE 1 + #else + #define SOCK_LISTEN_MAX_QUEUE 5 + #endif + if (listen(*sockfd, SOCK_LISTEN_MAX_QUEUE) != 0) + err_sys("tcp listen failed"); } - #if (defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API)) && !defined(WOLFSSL_TIRTOS) + #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) \ + && !defined(WOLFSSL_ZEPHYR) if (*port == 0) { 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 } } @@ -633,7 +1115,8 @@ static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, } -static INLINE int udp_read_connect(SOCKET_T sockfd) +#if 0 +static WC_INLINE int udp_read_connect(SOCKET_T sockfd) { SOCKADDR_IN_T cliaddr; byte b[1500]; @@ -652,18 +1135,20 @@ static INLINE int udp_read_connect(SOCKET_T sockfd) return sockfd; } +#endif -static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, +static WC_INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, int useAnyAddr, word16 port, func_args* args) { SOCKADDR_IN_T addr; (void)args; - build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), port, 1); - tcp_socket(sockfd, 1); + build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), port, 1, 0); + tcp_socket(sockfd, 1, 0); -#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM) +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM) \ + && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_ZEPHYR) { int res, on = 1; socklen_t len = sizeof(on); @@ -681,9 +1166,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 } } @@ -704,78 +1189,94 @@ static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, tcp_ready* ready = args->signal; ready->ready = 1; ready->port = port; +#else + (void)port; #endif - *clientfd = udp_read_connect(*sockfd); + *clientfd = *sockfd; } -static INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, +static WC_INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, func_args* args, word16 port, int useAnyAddr, - int udp, int ready_file) + int udp, int sctp, int ready_file, int do_listen) { SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); + tcp_ready* ready = NULL; + + (void) ready; /* Account for case when "ready" is not used */ if (udp) { udp_accept(sockfd, clientfd, useAnyAddr, port, args); return; } - tcp_listen(sockfd, &port, useAnyAddr, udp); + if(do_listen) { + tcp_listen(sockfd, &port, useAnyAddr, udp, sctp); -#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__) - /* signal ready to tcp_accept */ - { - tcp_ready* ready = args->signal; - pthread_mutex_lock(&ready->mutex); - ready->ready = 1; - ready->port = port; - pthread_cond_signal(&ready->cond); - pthread_mutex_unlock(&ready->mutex); - } -#elif defined (WOLFSSL_TIRTOS) - /* Need mutex? */ - tcp_ready* ready = args->signal; - ready->ready = 1; - ready->port = port; -#endif - - if (ready_file) { -#ifndef NO_FILESYSTEM - #ifndef USE_WINDOWS_API - FILE* srf = fopen("/tmp/wolfssl_server_ready", "w"); - #else - FILE* srf = fopen("wolfssl_server_ready", "w"); + #if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__) + /* signal ready to tcp_accept */ + if (args) + ready = args->signal; + if (ready) { + pthread_mutex_lock(&ready->mutex); + ready->ready = 1; + ready->port = port; + pthread_cond_signal(&ready->cond); + pthread_mutex_unlock(&ready->mutex); + } + #elif defined (WOLFSSL_TIRTOS) + /* Need mutex? */ + if (args) + ready = args->signal; + if (ready) { + ready->ready = 1; + ready->port = port; + } #endif - if (srf) { - fputs("ready", srf); - fclose(srf); + if (ready_file) { + #if !defined(NO_FILESYSTEM) || defined(FORCE_BUFFER_TEST) + XFILE srf = NULL; + if (args) + ready = args->signal; + + if (ready) { + srf = XFOPEN(ready->srfName, "w"); + + if (srf) { + /* let's write port sever is listening on to ready file + external monitor can then do ephemeral ports by passing + -p 0 to server on supported platforms with -R ready_file + client can then wait for existence of ready_file and see + which port the server is listening on. */ + fprintf(srf, "%d\n", (int)port); + fclose(srf); + } + } + #endif } -#endif } *clientfd = accept(*sockfd, (struct sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); -#ifdef USE_WINDOWS_API - if (*clientfd == INVALID_SOCKET) + if(WOLFSSL_SOCKET_IS_INVALID(*clientfd)) { err_sys("tcp accept failed"); -#else - if (*clientfd == -1) - err_sys("tcp accept failed"); -#endif + } } -static INLINE void tcp_set_nonblocking(SOCKET_T* sockfd) +static WC_INLINE void tcp_set_nonblocking(SOCKET_T* sockfd) { - #ifdef USE_WINDOWS_API + #ifdef USE_WINDOWS_API unsigned long blocking = 1; int ret = ioctlsocket(*sockfd, FIONBIO, &blocking); if (ret == SOCKET_ERROR) err_sys("ioctlsocket failed"); - #elif defined(WOLFSSL_MDK_ARM) || defined (WOLFSSL_TIRTOS) - /* non blocking not suppported, for now */ + #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) \ + || defined (WOLFSSL_TIRTOS)|| defined(WOLFSSL_VXWORKS) \ + || defined(WOLFSSL_ZEPHYR) + /* non blocking not supported, for now */ #else int flags = fcntl(*sockfd, F_GETFL, 0); if (flags < 0) @@ -789,7 +1290,10 @@ static INLINE void tcp_set_nonblocking(SOCKET_T* sockfd) #ifndef NO_PSK -static INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, +/* identity is OpenSSL testing default for openssl s_client, keep same */ +static const char* kIdentityStr = "Client_identity"; + +static WC_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) { @@ -797,54 +1301,136 @@ 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); + if (wolfSSL_GetVersion(ssl) < WOLFSSL_TLSV1_3) { + /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using + unsigned binary */ + key[0] = 0x1a; + key[1] = 0x2b; + key[2] = 0x3c; + key[3] = 0x4d; - /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using - unsigned binary */ - key[0] = 26; - key[1] = 43; - key[2] = 60; - key[3] = 77; + return 4; /* length of key in octets or 0 for error */ + } + else { + int i; + int b = 0x01; - return 4; /* length of key in octets or 0 for error */ + for (i = 0; i < 32; i++, b += 0x22) { + if (b >= 0x100) + b = 0x01; + key[i] = b; + } + + return 32; /* length of key in octets or 0 for error */ + } } -static INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, +static WC_INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, unsigned char* key, unsigned int key_max_len) { (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 - unsigned binary */ - key[0] = 26; - key[1] = 43; - key[2] = 60; - key[3] = 77; + if (wolfSSL_GetVersion(ssl) < WOLFSSL_TLSV1_3) { + /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using + unsigned binary */ + key[0] = 0x1a; + key[1] = 0x2b; + key[2] = 0x3c; + key[3] = 0x4d; - return 4; /* length of key in octets or 0 for error */ + return 4; /* length of key in octets or 0 for error */ + } + else { + int i; + int b = 0x01; + + for (i = 0; i < 32; i++, b += 0x22) { + if (b >= 0x100) + b = 0x01; + key[i] = b; + } + + return 32; /* length of key in octets or 0 for error */ + } +} + + +static WC_INLINE unsigned int my_psk_client_tls13_cb(WOLFSSL* ssl, + const char* hint, char* identity, unsigned int id_max_len, + unsigned char* key, unsigned int key_max_len, const char** ciphersuite) +{ + int i; + int b = 0x01; + + (void)ssl; + (void)hint; + (void)key_max_len; + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + strncpy(identity, kIdentityStr, id_max_len); + + for (i = 0; i < 32; i++, b += 0x22) { + if (b >= 0x100) + b = 0x01; + key[i] = b; + } + + *ciphersuite = "TLS13-AES128-GCM-SHA256"; + + return 32; /* length of key in octets or 0 for error */ +} + + +static WC_INLINE unsigned int my_psk_server_tls13_cb(WOLFSSL* ssl, + const char* identity, unsigned char* key, unsigned int key_max_len, + const char** ciphersuite) +{ + int i; + int b = 0x01; + + (void)ssl; + (void)key_max_len; + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + if (strncmp(identity, kIdentityStr, strlen(kIdentityStr)) != 0) + return 0; + + for (i = 0; i < 32; i++, b += 0x22) { + if (b >= 0x100) + b = 0x01; + key[i] = b; + } + + *ciphersuite = "TLS13-AES128-GCM-SHA256"; + + return 32; /* length of key in octets or 0 for error */ } #endif /* NO_PSK */ -#ifdef USE_WINDOWS_API +#if defined(WOLFSSL_USER_CURRTIME) + extern double current_time(int reset); + +#elif defined(USE_WINDOWS_API) #define WIN32_LEAN_AND_MEAN #include - static INLINE double current_time() + static WC_INLINE double current_time(int reset) { static int init = 0; static LARGE_INTEGER freq; - + LARGE_INTEGER count; if (!init) { @@ -854,108 +1440,344 @@ static INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, QueryPerformanceCounter(&count); + (void)reset; return (double)count.QuadPart / freq.QuadPart; } #elif defined(WOLFSSL_TIRTOS) extern double current_time(); +#elif defined(WOLFSSL_ZEPHYR) + extern double current_time(); #else -#if !defined(WOLFSSL_MDK_ARM) +#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_CHIBIOS) #include - static INLINE double current_time(void) + static WC_INLINE double current_time(int reset) { struct timeval tv; gettimeofday(&tv, 0); + (void)reset; return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; } - +#else + extern double current_time(int reset); #endif #endif /* USE_WINDOWS_API */ -#if defined(NO_FILESYSTEM) && !defined(NO_CERTS) +#if defined(HAVE_OCSP) && defined(WOLFSSL_NONBLOCK_OCSP) +static WC_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 WC_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 WC_INLINE int load_file(const char* fname, byte** buf, size_t* bufLen) + { + int ret; + long int fileSz; + XFILE file; + + if (fname == NULL || buf == NULL || bufLen == NULL) + return BAD_FUNC_ARG; + + /* set defaults */ + *buf = NULL; + *bufLen = 0; + + /* open file (read-only binary) */ + file = XFOPEN(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, WOLFSSL_CERT = 2, - WOLFSSL_KEY = 3 + WOLFSSL_KEY = 3, + WOLFSSL_CERT_CHAIN = 4, }; - static INLINE void load_buffer(WOLFSSL_CTX* ctx, const char* fname, int type) + static WC_INLINE void load_buffer(WOLFSSL_CTX* ctx, const char* fname, int type) { - /* test buffer load */ - long sz = 0; - byte buff[10000]; - FILE* file = fopen(fname, "rb"); + int format = WOLFSSL_FILETYPE_PEM; + byte* buff = NULL; + size_t sz = 0; - 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 = WOLFSSL_FILETYPE_ASN1; + if (type == WOLFSSL_CA) { - if (wolfSSL_CTX_load_verify_buffer(ctx, buff, sz, SSL_FILETYPE_PEM) - != 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, - SSL_FILETYPE_PEM) != 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, - SSL_FILETYPE_PEM) != 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, + (long)sz, format) != WOLFSSL_SUCCESS) + err_sys("can't load cert chain buffer"); + } + + if (buff) + free(buff); } -#endif /* NO_FILESYSTEM */ + static WC_INLINE void load_ssl_buffer(WOLFSSL* ssl, const char* fname, int type) + { + int format = WOLFSSL_FILETYPE_PEM; + byte* buff = NULL; + size_t sz = 0; -#ifdef VERIFY_CALLBACK + if (load_file(fname, &buff, &sz) != 0) { + err_sys("can't open file for buffer load " + "Please run from wolfSSL home directory if not"); + } -static INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store) + /* determine format */ + if (strstr(fname, ".der")) + format = WOLFSSL_FILETYPE_ASN1; + + if (type == WOLFSSL_CA) { + /* verify certs (CA's) use the shared ctx->cm (WOLFSSL_CERT_MANAGER) */ + WOLFSSL_CTX* ctx = wolfSSL_get_SSL_CTX(ssl); + 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_use_certificate_buffer(ssl, buff, (long)sz, + format) != WOLFSSL_SUCCESS) + err_sys("can't load buffer cert file"); + } + else if (type == WOLFSSL_KEY) { + if (wolfSSL_use_PrivateKey_buffer(ssl, buff, (long)sz, + format) != WOLFSSL_SUCCESS) + err_sys("can't load buffer key file"); + } + else if (type == WOLFSSL_CERT_CHAIN) { + if (wolfSSL_use_certificate_chain_buffer_format(ssl, buff, + (long)sz, format) != WOLFSSL_SUCCESS) + err_sys("can't load cert chain buffer"); + } + + if (buff) + free(buff); + } + + #ifdef TEST_PK_PRIVKEY + static WC_INLINE int load_key_file(const char* fname, byte** derBuf, word32* derLen) + { + int ret; + byte* buf = NULL; + size_t bufLen; + + ret = load_file(fname, &buf, &bufLen); + if (ret != 0) + return ret; + + *derBuf = (byte*)malloc(bufLen); + if (*derBuf == NULL) { + free(buf); + return MEMORY_E; + } + + ret = wc_KeyPemToDer(buf, (word32)bufLen, *derBuf, (word32)bufLen, NULL); + if (ret < 0) { + free(buf); + free(*derBuf); + return ret; + } + *derLen = ret; + free(buf); + + return 0; + } + #endif /* TEST_PK_PRIVKEY */ + + #endif /* !NO_FILESYSTEM || (NO_FILESYSTEM && FORCE_BUFFER_TEST) */ +#endif /* !NO_CERTS */ + +static int myVerifyFail = 0; + +/* The verify callback is called for every certificate only when + * --enable-opensslextra is defined because it sets WOLFSSL_ALWAYS_VERIFY_CB and + * WOLFSSL_VERIFY_CB_ALL_CERTS. + * Normal cases of the verify callback only occur on certificate failures when the + * wolfSSL_set_verify(ssl, SSL_VERIFY_PEER, myVerifyCb); is called +*/ + +static WC_INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store) { - (void)preverify; char buffer[WOLFSSL_MAX_ERROR_SZ]; - -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) WOLFSSL_X509* peer; +#if defined(SHOW_CERTS) && !defined(NO_FILESYSTEM) + WOLFSSL_BIO* bio = NULL; + WOLFSSL_STACK* sk = NULL; + X509* x509 = NULL; + int i = 0; #endif +#endif + (void)preverify; + + /* Verify Callback Arguments: + * preverify: 1=Verify Okay, 0=Failure + * store->error: Failure error code (0 indicates no failure) + * store->current_cert: Current WOLFSSL_X509 object (only with OPENSSL_EXTRA) + * store->error_depth: Current Index + * store->domain: Subject CN as string (null term) + * store->totalCerts: Number of certs presented by peer + * store->certs[i]: A `WOLFSSL_BUFFER_INFO` with plain DER for each cert + * store->store: WOLFSSL_X509_STORE with CA cert chain + * store->store->cm: WOLFSSL_CERT_MANAGER + * store->ex_data: The WOLFSSL object pointer + * store->discardSessionCerts: When set to non-zero value session certs + will be discarded (only with SESSION_CERTS) + */ printf("In verification callback, error = %d, %s\n", store->error, wolfSSL_ERR_error_string(store->error, buffer)); -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) peer = store->current_cert; if (peer) { char* issuer = wolfSSL_X509_NAME_oneline( wolfSSL_X509_get_issuer_name(peer), 0, 0); char* subject = wolfSSL_X509_NAME_oneline( wolfSSL_X509_get_subject_name(peer), 0, 0); - printf("peer's cert info:\n issuer : %s\n subject: %s\n", issuer, + printf("\tPeer's cert info:\n issuer : %s\n subject: %s\n", issuer, subject); XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL); XFREE(issuer, 0, DYNAMIC_TYPE_OPENSSL); +#if defined(SHOW_CERTS) && !defined(NO_FILESYSTEM) +/* avoid printing duplicate certs */ + if (store->depth == 1) { + /* retrieve x509 certs and display them on stdout */ + sk = wolfSSL_X509_STORE_GetCerts(store); + + for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) { + x509 = wolfSSL_sk_X509_value(sk, i); + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio != NULL) { + wolfSSL_BIO_set_fp(bio, stdout, BIO_NOCLOSE); + wolfSSL_X509_print(bio, x509); + wolfSSL_BIO_free(bio); + } + } + wolfSSL_sk_X509_free(sk); + } +#endif } else - printf("peer has no cert!\n"); -#endif - printf("Subject's domain name is %s\n", store->domain); + printf("\tPeer has no cert!\n"); +#else + printf("\tPeer certs: %d\n", store->totalCerts); + #ifdef SHOW_CERTS + { int i; + for (i=0; itotalCerts; i++) { + WOLFSSL_BUFFER_INFO* cert = &store->certs[i]; + printf("\t\tCert %d: Ptr %p, Len %u\n", i, cert->buffer, cert->length); + } + } + #endif /* SHOW_CERTS */ +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ - printf("Allowing to continue anyway (shouldn't do this, EVER!!!)\n"); + printf("\tSubject's domain name at %d is %s\n", store->error_depth, store->domain); + + /* Testing forced fail case by return zero */ + if (myVerifyFail) { + return 0; /* test failure case */ + } + + /* If error indicate we are overriding it for testing purposes */ + if (store->error != 0) { + printf("\tAllowing failed certificate check, testing only " + "(shouldn't do this in production)\n"); + } + + /* A non-zero return code indicates failure override */ return 1; } -#endif /* VERIFY_CALLBACK */ - -static INLINE int myDateCb(int preverify, WOLFSSL_X509_STORE_CTX* store) +static WC_INLINE int myDateCb(int preverify, WOLFSSL_X509_STORE_CTX* store) { char buffer[WOLFSSL_MAX_ERROR_SZ]; (void)preverify; @@ -974,9 +1796,43 @@ static INLINE int myDateCb(int preverify, WOLFSSL_X509_STORE_CTX* store) } +#ifdef HAVE_EXT_CACHE + +static WC_INLINE WOLFSSL_SESSION* mySessGetCb(WOLFSSL* ssl, unsigned char* id, + int id_len, int* copy) +{ + (void)ssl; + (void)id; + (void)id_len; + (void)copy; + + /* using internal cache, this is for testing only */ + return NULL; +} + +static WC_INLINE int mySessNewCb(WOLFSSL* ssl, WOLFSSL_SESSION* session) +{ + (void)ssl; + (void)session; + + /* using internal cache, this is for testing only */ + return 0; +} + +static WC_INLINE void mySessRemCb(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +{ + (void)ctx; + (void)session; + + /* using internal cache, this is for testing only */ +} + +#endif /* HAVE_EXT_CACHE */ + + #ifdef HAVE_CRL -static INLINE void CRL_CallBack(const char* url) +static WC_INLINE void CRL_CallBack(const char* url) { printf("CRL callback url = %s\n", url); } @@ -984,10 +1840,10 @@ static INLINE void CRL_CallBack(const char* url) #endif #ifndef NO_DH -static INLINE void SetDH(WOLFSSL* ssl) +static WC_INLINE void SetDH(WOLFSSL* ssl) { /* dh1024 p */ - static unsigned char p[] = + static const 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, @@ -1003,7 +1859,7 @@ static INLINE void SetDH(WOLFSSL* ssl) }; /* dh1024 g */ - static unsigned char g[] = + static const unsigned char g[] = { 0x02, }; @@ -1011,10 +1867,10 @@ static INLINE void SetDH(WOLFSSL* ssl) wolfSSL_SetTmpDH(ssl, p, sizeof(p), g, sizeof(g)); } -static INLINE void SetDHCtx(WOLFSSL_CTX* ctx) +static WC_INLINE void SetDHCtx(WOLFSSL_CTX* ctx) { /* dh1024 p */ - static unsigned char p[] = + static const 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, @@ -1030,7 +1886,7 @@ static INLINE void SetDHCtx(WOLFSSL_CTX* ctx) }; /* dh1024 g */ - static unsigned char g[] = + static const unsigned char g[] = { 0x02, }; @@ -1041,7 +1897,7 @@ static INLINE void SetDHCtx(WOLFSSL_CTX* ctx) #ifndef NO_CERTS -static INLINE void CaCb(unsigned char* der, int sz, int type) +static WC_INLINE void CaCb(unsigned char* der, int sz, int type) { (void)der; printf("Got CA cache add callback, derSz = %d, type = %d\n", sz, type); @@ -1049,258 +1905,54 @@ static INLINE void CaCb(unsigned char* der, int sz, int type) #endif /* !NO_CERTS */ -#ifdef HAVE_CAVIUM -static INLINE int OpenNitroxDevice(int dma_mode,int dev_id) -{ - Csp1CoreAssignment core_assign; - Uint32 device; +/* 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) + /* Maximum depth to search for WolfSSL root */ + #define MAX_WOLF_ROOT_DEPTH 5 - 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); - - return CspInitialize(dma_mode, dev_id); -} - -#endif /* HAVE_CAVIUM */ - - -#ifdef USE_WINDOWS_API - -/* do back x number of directories */ -static INLINE void ChangeDirBack(int x) -{ - char path[MAX_PATH]; - - if (x == 1) - strncpy(path, "..\\", MAX_PATH); - else if (x == 2) - strncpy(path, "..\\..\\", MAX_PATH); - else if (x == 3) - strncpy(path, "..\\..\\..\\", MAX_PATH); - else if (x == 4) - strncpy(path, "..\\..\\..\\..\\", MAX_PATH); - else - strncpy(path, ".\\", MAX_PATH); - - SetCurrentDirectoryA(path); -} - -/* does current dir contain str */ -static INLINE int CurrentDir(const char* str) -{ - char path[MAX_PATH]; - char* baseName; - - GetCurrentDirectoryA(sizeof(path), path); - - baseName = strrchr(path, '\\'); - if (baseName) - baseName++; - else - baseName = path; - - if (strstr(baseName, str)) - return 1; - - return 0; -} - -#elif defined(WOLFSSL_MDK_ARM) - /* KEIL-RL File System does not support relative directry */ -#elif defined(WOLFSSL_TIRTOS) -#else - -#ifndef MAX_PATH - #define MAX_PATH 256 -#endif - -/* do back x number of directories */ -static INLINE void ChangeDirBack(int x) -{ - char path[MAX_PATH]; - - if (x == 1) - strncpy(path, "../", MAX_PATH); - else if (x == 2) - strncpy(path, "../../", MAX_PATH); - else if (x == 3) - strncpy(path, "../../../", MAX_PATH); - else if (x == 4) - strncpy(path, "../../../../", MAX_PATH); - else - strncpy(path, "./", MAX_PATH); - - if (chdir(path) < 0) - printf("chdir to %s failed\n", path); -} - -/* does current dir contain str */ -static INLINE int CurrentDir(const char* str) -{ - char path[MAX_PATH]; - char* baseName; - - if (getcwd(path, sizeof(path)) == NULL) { - printf("no current dir?\n"); - return 0; - } - - baseName = strrchr(path, '/'); - if (baseName) - baseName++; - else - baseName = path; - - if (strstr(baseName, str)) - return 1; - - return 0; -} - -#endif /* USE_WINDOWS_API */ - - -#ifdef USE_WOLFSSL_MEMORY - - typedef struct memoryStats { - size_t totalAllocs; /* number of allocations */ - size_t totalBytes; /* total number of bytes allocated */ - size_t peakBytes; /* concurrent max bytes */ - size_t currentBytes; /* total current bytes in use */ - } memoryStats; - - typedef struct memHint { - size_t thisSize; /* size of this memory */ - void* thisMemory; /* actual memory for user */ - } memHint; - - typedef struct memoryTrack { - union { - memHint hint; - byte alignit[16]; /* make sure we have strong alignment */ - } u; - } memoryTrack; - - #if defined(WOLFSSL_TRACK_MEMORY) - #define DO_MEM_STATS - static memoryStats ourMemStats; - #endif - - static INLINE void* TrackMalloc(size_t sz) + static WC_INLINE int ChangeToWolfRoot(void) { - memoryTrack* mt; + #if !defined(NO_FILESYSTEM) || defined(FORCE_BUFFER_TEST) + int depth, res; + XFILE file; + for(depth = 0; depth <= MAX_WOLF_ROOT_DEPTH; depth++) { + file = XFOPEN(ntruKeyFile, "rb"); + if (file != NULL) { + fclose(file); + return depth; + } + #ifdef USE_WINDOWS_API + res = SetCurrentDirectoryA("..\\"); + #else + res = chdir("../"); + #endif + if (res < 0) { + printf("chdir to ../ failed!\n"); + break; + } + } - if (sz == 0) - return NULL; - - mt = (memoryTrack*)malloc(sizeof(memoryTrack) + sz); - if (mt == NULL) - return NULL; - - mt->u.hint.thisSize = sz; - mt->u.hint.thisMemory = (byte*)mt + sizeof(memoryTrack); - -#ifdef DO_MEM_STATS - ourMemStats.totalAllocs++; - ourMemStats.totalBytes += sz; - ourMemStats.currentBytes += sz; - if (ourMemStats.currentBytes > ourMemStats.peakBytes) - ourMemStats.peakBytes = ourMemStats.currentBytes; -#endif - - return mt->u.hint.thisMemory; + err_sys("wolf root not found"); + return -1; + #else + return 0; + #endif } - - - static INLINE void TrackFree(void* ptr) - { - memoryTrack* mt; - - if (ptr == NULL) - return; - - mt = (memoryTrack*)ptr; - --mt; /* same as minus sizeof(memoryTrack), removes header */ - -#ifdef DO_MEM_STATS - ourMemStats.currentBytes -= mt->u.hint.thisSize; -#endif - - free(mt); - } - - - static INLINE void* TrackRealloc(void* ptr, size_t sz) - { - void* ret = TrackMalloc(sz); - - if (ptr) { - /* if realloc is bigger, don't overread old ptr */ - memoryTrack* mt = (memoryTrack*)ptr; - --mt; /* same as minus sizeof(memoryTrack), removes header */ - - if (mt->u.hint.thisSize < sz) - sz = mt->u.hint.thisSize; - } - - if (ret && ptr) - memcpy(ret, ptr, sz); - - if (ret) - TrackFree(ptr); - - return ret; - } - - static INLINE void InitMemoryTracker(void) - { - if (wolfSSL_SetAllocators(TrackMalloc, TrackFree, TrackRealloc) != 0) - err_sys("wolfSSL SetAllocators failed for track memory"); - - #ifdef DO_MEM_STATS - ourMemStats.totalAllocs = 0; - ourMemStats.totalBytes = 0; - ourMemStats.peakBytes = 0; - ourMemStats.currentBytes = 0; - #endif - } - - static INLINE void ShowMemoryTracker(void) - { - #ifdef DO_MEM_STATS - printf("total Allocs = %9lu\n", - (unsigned long)ourMemStats.totalAllocs); - printf("total Bytes = %9lu\n", - (unsigned long)ourMemStats.totalBytes); - printf("peak Bytes = %9lu\n", - (unsigned long)ourMemStats.peakBytes); - printf("current Bytes = %9lu\n", - (unsigned long)ourMemStats.currentBytes); - #endif - } - -#endif /* USE_WOLFSSL_MEMORY */ - +#endif /* !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS) */ #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 WC_INLINE int StackSizeCheck(func_args* args, thread_func tf) { int ret, i, used; - unsigned char* myStack; - int stackSize = 1024*128; + void* status; + unsigned char* myStack = NULL; + int stackSize = 1024*152; pthread_attr_t myAttr; pthread_t threadId; @@ -1310,10 +1962,10 @@ static INLINE void StackSizeCheck(func_args* args, thread_func tf) #endif ret = posix_memalign((void**)&myStack, sysconf(_SC_PAGESIZE), stackSize); - if (ret != 0) - err_sys("posix_memalign failed\n"); + if (ret != 0 || myStack == NULL) + err_sys("posix_memalign failed\n"); - memset(myStack, 0x01, stackSize); + XMEMSET(myStack, STACK_CHECK_VAL, stackSize); ret = pthread_attr_init(&myAttr); if (ret != 0) @@ -1329,18 +1981,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); } @@ -1360,7 +2016,7 @@ static INLINE void StackSizeCheck(func_args* args, thread_func tf) #error "can't use STACK_TRAP with STACK_SIZE, setrlimit will fail" #endif /* HAVE_STACK_SIZE */ -static INLINE void StackTrap(void) +static WC_INLINE void StackTrap(void) { struct rlimit rl; if (getrlimit(RLIMIT_STACK, &rl) != 0) @@ -1375,14 +2031,14 @@ static INLINE void StackTrap(void) #else /* STACK_TRAP */ -static INLINE void StackTrap(void) +static WC_INLINE void StackTrap(void) { } #endif /* STACK_TRAP */ -#ifdef ATOMIC_USER +#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY) /* Atomic Encrypt Context example */ typedef struct AtomicEncCtx { @@ -1398,8 +2054,8 @@ typedef struct AtomicDecCtx { } AtomicDecCtx; -static INLINE int myMacEncryptCb(WOLFSSL* ssl, unsigned char* macOut, - const unsigned char* macIn, unsigned int macInSz, int macContent, +static WC_INLINE int myMacEncryptCb(WOLFSSL* ssl, unsigned char* macOut, + const unsigned char* macIn, unsigned int macInSz, int macContent, int macVerify, unsigned char* encOut, const unsigned char* encIn, unsigned int encSz, void* ctx) { @@ -1423,6 +2079,9 @@ static INLINE int myMacEncryptCb(WOLFSSL* ssl, unsigned char* macOut, /* hmac, not needed if aead mode */ wolfSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify); + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), wolfSSL_GetMacSecret(ssl, macVerify), wolfSSL_GetHmacSize(ssl)); if (ret != 0) @@ -1466,7 +2125,7 @@ static INLINE int myMacEncryptCb(WOLFSSL* ssl, unsigned char* macOut, } -static INLINE int myDecryptVerifyCb(WOLFSSL* ssl, +static WC_INLINE int myDecryptVerifyCb(WOLFSSL* ssl, unsigned char* decOut, const unsigned char* decIn, unsigned int decSz, int macContent, int macVerify, unsigned int* padSz, void* ctx) @@ -1480,7 +2139,7 @@ static INLINE int myDecryptVerifyCb(WOLFSSL* ssl, unsigned int padByte = 0; Hmac hmac; byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; - byte verify[MAX_DIGEST_SIZE]; + byte verify[WC_MAX_DIGEST_SIZE]; const char* tlsStr = "TLS"; /* example supports (d)tls aes */ @@ -1520,6 +2179,8 @@ static INLINE int myDecryptVerifyCb(WOLFSSL* ssl, /* decrypt */ ret = wc_AesCbcDecrypt(&decCtx->aes, decOut, decIn, decSz); + if (ret != 0) + return ret; if (wolfSSL_GetCipherType(ssl) == WOLFSSL_AEAD_TYPE) { *padSz = wolfSSL_GetAeadMacSize(ssl); @@ -1538,6 +2199,9 @@ static INLINE int myDecryptVerifyCb(WOLFSSL* ssl, wolfSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify); + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), wolfSSL_GetMacSecret(ssl, macVerify), digestSz); if (ret != 0) @@ -1552,7 +2216,7 @@ static INLINE int myDecryptVerifyCb(WOLFSSL* ssl, if (ret != 0) return ret; - if (memcmp(verify, decOut + decSz - digestSz - pad - padByte, + if (XMEMCMP(verify, decOut + decSz - digestSz - pad - padByte, digestSz) != 0) { printf("myDecryptVerify verify failed\n"); return -1; @@ -1561,8 +2225,164 @@ static INLINE int myDecryptVerifyCb(WOLFSSL* ssl, return ret; } +#if defined(HAVE_ENCRYPT_THEN_MAC) -static INLINE void SetupAtomicUser(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +static WC_INLINE int myEncryptMacCb(WOLFSSL* ssl, unsigned char* macOut, + int content, int macVerify, unsigned char* encOut, + const unsigned char* encIn, unsigned int encSz, void* ctx) +{ + int ret; + Hmac hmac; + AtomicEncCtx* encCtx = (AtomicEncCtx*)ctx; + byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; + const char* tlsStr = "TLS"; + + /* example supports (d)tls aes */ + if (wolfSSL_GetBulkCipher(ssl) != wolfssl_aes) { + printf("myMacEncryptCb not using AES\n"); + return -1; + } + + if (strstr(wolfSSL_get_version(ssl), tlsStr) == NULL) { + printf("myMacEncryptCb not using (D)TLS\n"); + return -1; + } + + /* encrypt setup on first time */ + if (encCtx->keySetup == 0) { + int keyLen = wolfSSL_GetKeySize(ssl); + const byte* key; + const byte* iv; + + if (wolfSSL_GetSide(ssl) == WOLFSSL_CLIENT_END) { + key = wolfSSL_GetClientWriteKey(ssl); + iv = wolfSSL_GetClientWriteIV(ssl); + } + else { + key = wolfSSL_GetServerWriteKey(ssl); + iv = wolfSSL_GetServerWriteIV(ssl); + } + + ret = wc_AesSetKey(&encCtx->aes, key, keyLen, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("AesSetKey failed in myMacEncryptCb\n"); + return ret; + } + encCtx->keySetup = 1; + } + + /* encrypt */ + ret = wc_AesCbcEncrypt(&encCtx->aes, encOut, encIn, encSz); + if (ret != 0) + return ret; + + /* Reconstruct record header. */ + wolfSSL_SetTlsHmacInner(ssl, myInner, encSz, content, macVerify); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), + wolfSSL_GetMacSecret(ssl, macVerify), wolfSSL_GetHmacSize(ssl)); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, encOut, encSz); + if (ret != 0) + return ret; + return wc_HmacFinal(&hmac, macOut); +} + + +static WC_INLINE int myVerifyDecryptCb(WOLFSSL* ssl, + unsigned char* decOut, const unsigned char* decIn, + unsigned int decSz, int content, int macVerify, + unsigned int* padSz, void* ctx) +{ + AtomicDecCtx* decCtx = (AtomicDecCtx*)ctx; + int ret = 0; + int digestSz = wolfSSL_GetHmacSize(ssl); + Hmac hmac; + byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; + byte verify[WC_MAX_DIGEST_SIZE]; + const char* tlsStr = "TLS"; + + /* example supports (d)tls aes */ + if (wolfSSL_GetBulkCipher(ssl) != wolfssl_aes) { + printf("myMacEncryptCb not using AES\n"); + return -1; + } + + if (strstr(wolfSSL_get_version(ssl), tlsStr) == NULL) { + printf("myMacEncryptCb not using (D)TLS\n"); + return -1; + } + + /* Reconstruct record header. */ + wolfSSL_SetTlsHmacInner(ssl, myInner, decSz, content, macVerify); + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), + wolfSSL_GetMacSecret(ssl, macVerify), digestSz); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, decIn, decSz); + if (ret != 0) + return ret; + ret = wc_HmacFinal(&hmac, verify); + if (ret != 0) + return ret; + + if (XMEMCMP(verify, decOut + decSz, digestSz) != 0) { + printf("myDecryptVerify verify failed\n"); + return -1; + } + + /* decrypt */ + if (decCtx->keySetup == 0) { + int keyLen = wolfSSL_GetKeySize(ssl); + const byte* key; + const byte* iv; + + /* decrypt is from other side (peer) */ + if (wolfSSL_GetSide(ssl) == WOLFSSL_SERVER_END) { + key = wolfSSL_GetClientWriteKey(ssl); + iv = wolfSSL_GetClientWriteIV(ssl); + } + else { + key = wolfSSL_GetServerWriteKey(ssl); + iv = wolfSSL_GetServerWriteIV(ssl); + } + + ret = wc_AesSetKey(&decCtx->aes, key, keyLen, iv, AES_DECRYPTION); + if (ret != 0) { + printf("AesSetKey failed in myDecryptVerifyCb\n"); + return ret; + } + decCtx->keySetup = 1; + } + + /* decrypt */ + ret = wc_AesCbcDecrypt(&decCtx->aes, decOut, decIn, decSz); + if (ret != 0) + return ret; + + *padSz = *(decOut + decSz - 1) + 1; + + return 0; +} + +#endif + + +static WC_INLINE void SetupAtomicUser(WOLFSSL_CTX* ctx, WOLFSSL* ssl) { AtomicEncCtx* encCtx; AtomicDecCtx* decCtx; @@ -1570,228 +2390,1122 @@ static INLINE void SetupAtomicUser(WOLFSSL_CTX* ctx, WOLFSSL* ssl) encCtx = (AtomicEncCtx*)malloc(sizeof(AtomicEncCtx)); if (encCtx == NULL) err_sys("AtomicEncCtx malloc failed"); - memset(encCtx, 0, sizeof(AtomicEncCtx)); + XMEMSET(encCtx, 0, sizeof(AtomicEncCtx)); decCtx = (AtomicDecCtx*)malloc(sizeof(AtomicDecCtx)); if (decCtx == NULL) { free(encCtx); err_sys("AtomicDecCtx malloc failed"); } - memset(decCtx, 0, sizeof(AtomicDecCtx)); + XMEMSET(decCtx, 0, sizeof(AtomicDecCtx)); wolfSSL_CTX_SetMacEncryptCb(ctx, myMacEncryptCb); wolfSSL_SetMacEncryptCtx(ssl, encCtx); wolfSSL_CTX_SetDecryptVerifyCb(ctx, myDecryptVerifyCb); wolfSSL_SetDecryptVerifyCtx(ssl, decCtx); + +#if defined(HAVE_ENCRYPT_THEN_MAC) + wolfSSL_CTX_SetEncryptMacCb(ctx, myEncryptMacCb); + wolfSSL_SetEncryptMacCtx(ssl, encCtx); + + wolfSSL_CTX_SetVerifyDecryptCb(ctx, myVerifyDecryptCb); + wolfSSL_SetVerifyDecryptCtx(ssl, decCtx); +#endif } -static INLINE void FreeAtomicUser(WOLFSSL* ssl) +static WC_INLINE void FreeAtomicUser(WOLFSSL* ssl) { AtomicEncCtx* encCtx = (AtomicEncCtx*)wolfSSL_GetMacEncryptCtx(ssl); AtomicDecCtx* decCtx = (AtomicDecCtx*)wolfSSL_GetDecryptVerifyCtx(ssl); + /* Encrypt-Then-MAC callbacks use same contexts. */ + free(decCtx); free(encCtx); } #endif /* ATOMIC_USER */ +#ifdef WOLFSSL_STATIC_MEMORY +static WC_INLINE int wolfSSL_PrintStats(WOLFSSL_MEM_STATS* stats) +{ + word16 i; + + if (stats == NULL) { + return 0; + } + + /* print to stderr so is on the same pipe as WOLFSSL_DEBUG */ + fprintf(stderr, "Total mallocs = %d\n", stats->totalAlloc); + fprintf(stderr, "Total frees = %d\n", stats->totalFr); + fprintf(stderr, "Current mallocs = %d\n", stats->curAlloc); + fprintf(stderr, "Available IO = %d\n", stats->avaIO); + fprintf(stderr, "Max con. handshakes = %d\n", stats->maxHa); + fprintf(stderr, "Max con. IO = %d\n", stats->maxIO); + fprintf(stderr, "State of memory blocks: size : available \n"); + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + fprintf(stderr, " : %d\t : %d\n", stats->blockSz[i], + stats->avaBlock[i]); + } + + return 1; +} +#endif /* WOLFSSL_STATIC_MEMORY */ #ifdef HAVE_PK_CALLBACKS +typedef struct PkCbInfo { + const char* ourKey; +#ifdef TEST_PK_PRIVKEY + union { + #ifdef HAVE_ECC + ecc_key ecc; + #endif + #ifdef HAVE_CURVE25519 + curve25519_key curve; + #endif + #ifdef HAVE_CURVE448 + curve448_key curve; + #endif + } keyGen; +#endif +} PkCbInfo; + +#if defined(DEBUG_PK_CB) || defined(TEST_PK_PRIVKEY) + #define WOLFSSL_PKMSG(_f_, ...) printf(_f_, ##__VA_ARGS__) +#else + #define WOLFSSL_PKMSG(_f_, ...) +#endif + #ifdef HAVE_ECC -static INLINE int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz, - byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) +static WC_INLINE int myEccKeyGen(WOLFSSL* ssl, ecc_key* key, word32 keySz, + int ecc_curve, void* ctx) { - RNG rng; - int ret; - word32 idx = 0; - ecc_key myKey; + int ret; + WC_RNG rng; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + ecc_key* new_key; +#ifdef TEST_PK_PRIVKEY + byte qx[MAX_ECC_BYTES], qy[MAX_ECC_BYTES]; + word32 qxLen = sizeof(qx), qyLen = sizeof(qy); + + new_key = &cbInfo->keyGen.ecc; +#else + new_key = key; +#endif (void)ssl; - (void)ctx; + (void)cbInfo; + + WOLFSSL_PKMSG("PK ECC KeyGen: keySz %d, Curve ID %d\n", keySz, ecc_curve); ret = wc_InitRng(&rng); 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(new_key); + if (ret == 0) { + /* create new key */ + ret = wc_ecc_make_key_ex(&rng, keySz, new_key, ecc_curve); + + #ifdef TEST_PK_PRIVKEY + if (ret == 0) { + /* extract public portion from new key into `key` arg */ + ret = wc_ecc_export_public_raw(new_key, qx, &qxLen, qy, &qyLen); + if (ret == 0) { + /* load public portion only into key */ + ret = wc_ecc_import_unsigned(key, qx, qy, NULL, ecc_curve); + } + (void)qxLen; + (void)qyLen; + } + #endif + } + + WOLFSSL_PKMSG("PK ECC KeyGen: ret %d\n", ret); + wc_FreeRng(&rng); return ret; } +static WC_INLINE int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) +{ + int ret; + WC_RNG rng; + word32 idx = 0; + ecc_key myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; -static INLINE int myEccVerify(WOLFSSL* ssl, const byte* sig, word32 sigSz, + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK ECC Sign: inSz %d, keySz %d\n", inSz, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + ret = wc_ecc_init(&myKey); + if (ret == 0) { + ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &myKey, keySz); + if (ret == 0) { + WOLFSSL_PKMSG("PK ECC Sign: Curve ID %d\n", myKey.dp->id); + ret = wc_ecc_sign_hash(in, inSz, out, outSz, &rng, &myKey); + } + wc_ecc_free(&myKey); + } + wc_FreeRng(&rng); + +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK ECC Sign: ret %d outSz %d\n", ret, *outSz); + + return ret; +} + + +static WC_INLINE int myEccVerify(WOLFSSL* ssl, const byte* sig, word32 sigSz, const byte* hash, word32 hashSz, const byte* key, word32 keySz, int* result, void* ctx) { - int ret; - ecc_key myKey; + int ret; + word32 idx = 0; + ecc_key myKey; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; (void)ssl; - (void)ctx; + (void)cbInfo; - 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); + WOLFSSL_PKMSG("PK ECC Verify: sigSz %d, hashSz %d, keySz %d\n", sigSz, hashSz, keySz); + + ret = wc_ecc_init(&myKey); + if (ret == 0) { + ret = wc_EccPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, result, &myKey); + wc_ecc_free(&myKey); + } + + WOLFSSL_PKMSG("PK ECC Verify: ret %d, result %d\n", ret, *result); return ret; } +static WC_INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx) +{ + int ret; + ecc_key* privKey = NULL; + ecc_key* pubKey = NULL; + ecc_key tmpKey; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK ECC PMS: Side %s, Peer Curve %d\n", + side == WOLFSSL_CLIENT_END ? "client" : "server", otherKey->dp->id); + + ret = wc_ecc_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_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); + } + } + + /* for server: import public key */ + else if (side == WOLFSSL_SERVER_END) { + #ifdef TEST_PK_PRIVKEY + privKey = &cbInfo->keyGen.ecc; + #else + privKey = otherKey; + #endif + pubKey = &tmpKey; + + ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, pubKey, + otherKey->dp->id); + } + else { + ret = BAD_FUNC_ARG; + } + + /* 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 + } + +#ifdef TEST_PK_PRIVKEY + if (side == WOLFSSL_SERVER_END) { + wc_ecc_free(&cbInfo->keyGen.ecc); + } +#endif + + wc_ecc_free(&tmpKey); + + WOLFSSL_PKMSG("PK ECC PMS: ret %d, PubKeySz %d, OutLen %d\n", ret, *pubKeySz, *outlen); + + return ret; +} + +#ifdef HAVE_ED25519 +static WC_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; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK 25519 Sign: inSz %d, keySz %d\n", inSz, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + ret = wc_ed25519_init(&myKey); + if (ret == 0) { + ret = wc_Ed25519PrivateKeyDecode(keyBuf, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_ed25519_sign_msg(in, inSz, out, outSz, &myKey); + wc_ed25519_free(&myKey); + } + +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK 25519 Sign: ret %d, outSz %d\n", ret, *outSz); + + return ret; +} + + +static WC_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; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK 25519 Verify: sigSz %d, msgSz %d, keySz %d\n", sigSz, msgSz, keySz); + + 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); + } + + WOLFSSL_PKMSG("PK 25519 Verify: ret %d, result %d\n", ret, *result); + + return ret; +} +#endif /* HAVE_ED25519 */ + +#ifdef HAVE_CURVE25519 +static WC_INLINE int myX25519KeyGen(WOLFSSL* ssl, curve25519_key* key, + unsigned int keySz, void* ctx) +{ + int ret; + WC_RNG rng; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK 25519 KeyGen: keySz %d\n", keySz); + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + ret = wc_curve25519_make_key(&rng, keySz, key); + + wc_FreeRng(&rng); + + WOLFSSL_PKMSG("PK 25519 KeyGen: ret %d\n", ret); + + return ret; +} + +static WC_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; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK 25519 PMS: side %s\n", + side == WOLFSSL_CLIENT_END ? "client" : "server"); + + 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); + + WOLFSSL_PKMSG("PK 25519 PMS: ret %d, pubKeySz %d, outLen %d\n", + ret, *pubKeySz, *outlen); + + return ret; +} +#endif /* HAVE_CURVE25519 */ + +#ifdef HAVE_ED448 +static WC_INLINE int myEd448Sign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + ed448_key myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK 448 Sign: inSz %d, keySz %d\n", inSz, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + ret = wc_ed448_init(&myKey); + if (ret == 0) { + ret = wc_Ed448PrivateKeyDecode(keyBuf, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_ed448_sign_msg(in, inSz, out, outSz, &myKey); + wc_ed448_free(&myKey); + } + +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK 448 Sign: ret %d, outSz %d\n", ret, *outSz); + + return ret; +} + + +static WC_INLINE int myEd448Verify(WOLFSSL* ssl, const byte* sig, word32 sigSz, + const byte* msg, word32 msgSz, const byte* key, word32 keySz, + int* result, void* ctx) +{ + int ret; + ed448_key myKey; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK 448 Verify: sigSz %d, msgSz %d, keySz %d\n", sigSz, msgSz, + keySz); + + ret = wc_ed448_init(&myKey); + if (ret == 0) { + ret = wc_ed448_import_public(key, keySz, &myKey); + if (ret == 0) { + ret = wc_ed448_verify_msg(sig, sigSz, msg, msgSz, result, &myKey); + } + wc_ed448_free(&myKey); + } + + WOLFSSL_PKMSG("PK 448 Verify: ret %d, result %d\n", ret, *result); + + return ret; +} +#endif /* HAVE_ED448 */ + +#ifdef HAVE_CURVE448 +static WC_INLINE int myX448KeyGen(WOLFSSL* ssl, curve448_key* key, + unsigned int keySz, void* ctx) +{ + int ret; + WC_RNG rng; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK 448 KeyGen: keySz %d\n", keySz); + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + ret = wc_curve448_make_key(&rng, keySz, key); + + wc_FreeRng(&rng); + + WOLFSSL_PKMSG("PK 448 KeyGen: ret %d\n", ret); + + return ret; +} + +static WC_INLINE int myX448SharedSecret(WOLFSSL* ssl, curve448_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx) +{ + int ret; + curve448_key* privKey = NULL; + curve448_key* pubKey = NULL; + curve448_key tmpKey; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK 448 PMS: side %s\n", + side == WOLFSSL_CLIENT_END ? "client" : "server"); + + ret = wc_curve448_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_curve448_make_key(&rng, CURVE448_KEY_SIZE, privKey); + if (ret == 0) { + ret = wc_curve448_export_public_ex(privKey, pubKeyDer, + pubKeySz, EC448_LITTLE_ENDIAN); + } + wc_FreeRng(&rng); + } + } + + /* for server: import public key */ + else if (side == WOLFSSL_SERVER_END) { + privKey = otherKey; + pubKey = &tmpKey; + + ret = wc_curve448_import_public_ex(pubKeyDer, *pubKeySz, pubKey, + EC448_LITTLE_ENDIAN); + } + else { + ret = BAD_FUNC_ARG; + } + + /* generate shared secret and return it */ + if (ret == 0) { + ret = wc_curve448_shared_secret_ex(privKey, pubKey, out, outlen, + EC448_LITTLE_ENDIAN); + } + + wc_curve448_free(&tmpKey); + + WOLFSSL_PKMSG("PK 448 PMS: ret %d, pubKeySz %d, outLen %d\n", + ret, *pubKeySz, *outlen); + + return ret; +} +#endif /* HAVE_CURVE448 */ + #endif /* HAVE_ECC */ +#ifndef NO_DH +static WC_INLINE int myDhCallback(WOLFSSL* ssl, struct DhKey* key, + const unsigned char* priv, unsigned int privSz, + const unsigned char* pubKeyDer, unsigned int pubKeySz, + unsigned char* out, unsigned int* outlen, + void* ctx) +{ + int ret; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + /* return 0 on success */ + ret = wc_DhAgree(key, out, outlen, priv, privSz, pubKeyDer, pubKeySz); + + WOLFSSL_PKMSG("PK ED Agree: ret %d, privSz %d, pubKeySz %d, outlen %d\n", + ret, privSz, pubKeySz, *outlen); + + return ret; +}; + +#endif /* !NO_DH */ + #ifndef NO_RSA -static INLINE int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, +static WC_INLINE int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) { - RNG rng; + WC_RNG rng; int ret; word32 idx = 0; RsaKey myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; (void)ssl; - (void)ctx; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA Sign: inSz %d, keySz %d\n", inSz, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif ret = wc_InitRng(&rng); 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(keyBuf, &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); +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK RSA Sign: ret %d, outSz %d\n", ret, *outSz); + return ret; } -static INLINE int myRsaVerify(WOLFSSL* ssl, byte* sig, word32 sigSz, - byte** out, - const byte* key, word32 keySz, - void* ctx) +static WC_INLINE int myRsaVerify(WOLFSSL* ssl, byte* sig, word32 sigSz, + byte** out, const byte* key, word32 keySz, void* ctx) { int ret; word32 idx = 0; RsaKey myKey; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; (void)ssl; - (void)ctx; + (void)cbInfo; - wc_InitRsaKey(&myKey, NULL); + WOLFSSL_PKMSG("PK RSA Verify: sigSz %d, keySz %d\n", sigSz, keySz); - 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); + } + + WOLFSSL_PKMSG("PK RSA Verify: ret %d\n", ret); + + return ret; +} + +static WC_INLINE int myRsaSignCheck(WOLFSSL* ssl, byte* sig, word32 sigSz, + byte** out, const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + RsaKey myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA SignCheck: sigSz %d, keySz %d\n", sigSz, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_RsaSSL_VerifyInline(sig, sigSz, out, &myKey); + wc_FreeRsaKey(&myKey); + } +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK RSA SignCheck: ret %d\n", ret); + + return ret; +} + +#ifdef WC_RSA_PSS +static WC_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; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA PSS Sign: inSz %d, hash %d, mgf %d, keySz %d\n", + inSz, hash, mgf, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + 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(keyBuf, &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); + +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK RSA PSS Sign: ret %d, outSz %d\n", ret, *outSz); return ret; } -static INLINE int myRsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, +static WC_INLINE int myRsaPssVerify(WOLFSSL* ssl, byte* sig, word32 sigSz, + byte** out, int hash, int mgf, const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + RsaKey myKey; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA PSS Verify: sigSz %d, hash %d, mgf %d, keySz %d\n", + sigSz, hash, mgf, keySz); + + 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); + } + + WOLFSSL_PKMSG("PK RSA PSS Verify: ret %d\n", ret); + + return ret; +} + +static WC_INLINE int myRsaPssSignCheck(WOLFSSL* ssl, byte* sig, word32 sigSz, + byte** out, int hash, int mgf, const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + RsaKey myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA PSS SignCheck: sigSz %d, hash %d, mgf %d, keySz %d\n", + sigSz, hash, mgf, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + 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_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPSS_VerifyInline(sig, sigSz, out, hashType, mgf, + &myKey); + } + wc_FreeRsaKey(&myKey); + } + +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK RSA PSS SignCheck: ret %d\n", ret); + + return ret; +} +#endif + + +static WC_INLINE int myRsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) { - int ret; - word32 idx = 0; - RsaKey myKey; - RNG rng; + int ret; + word32 idx = 0; + RsaKey myKey; + WC_RNG rng; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; (void)ssl; - (void)ctx; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA Enc: inSz %d, keySz %d\n", inSz, keySz); ret = wc_InitRng(&rng); 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); + WOLFSSL_PKMSG("PK RSA Enc: ret %d, outSz %d\n", ret, *outSz); + return ret; } -static INLINE int myRsaDec(WOLFSSL* ssl, byte* in, word32 inSz, +static WC_INLINE int myRsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, const byte* key, word32 keySz, void* ctx) { - int ret; - word32 idx = 0; - RsaKey myKey; + int ret; + word32 idx = 0; + RsaKey myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; (void)ssl; - (void)ctx; + (void)cbInfo; - wc_InitRsaKey(&myKey, NULL); + WOLFSSL_PKMSG("PK RSA Dec: inSz %d, keySz %d\n", inSz, keySz); - ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + ret = wc_InitRsaKey(&myKey, NULL); if (ret == 0) { - ret = wc_RsaPrivateDecryptInline(in, inSz, out, &myKey); + ret = wc_RsaPrivateKeyDecode(keyBuf, &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); + +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK RSA Dec: ret %d\n", ret); return ret; } #endif /* NO_RSA */ -static INLINE void SetupPkCallbacks(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +static WC_INLINE void SetupPkCallbacks(WOLFSSL_CTX* ctx) { (void)ctx; - (void)ssl; #ifdef HAVE_ECC + wolfSSL_CTX_SetEccKeyGenCb(ctx, myEccKeyGen); wolfSSL_CTX_SetEccSignCb(ctx, myEccSign); wolfSSL_CTX_SetEccVerifyCb(ctx, myEccVerify); + wolfSSL_CTX_SetEccSharedSecretCb(ctx, myEccSharedSecret); #endif /* HAVE_ECC */ - #ifndef NO_RSA + #ifndef NO_DH + wolfSSL_CTX_SetDhAgreeCb(ctx, myDhCallback); + #endif + #ifdef HAVE_ED25519 + wolfSSL_CTX_SetEd25519SignCb(ctx, myEd25519Sign); + wolfSSL_CTX_SetEd25519VerifyCb(ctx, myEd25519Verify); + #endif + #ifdef HAVE_CURVE25519 + wolfSSL_CTX_SetX25519KeyGenCb(ctx, myX25519KeyGen); + wolfSSL_CTX_SetX25519SharedSecretCb(ctx, myX25519SharedSecret); + #endif + #ifdef HAVE_ED448 + wolfSSL_CTX_SetEd448SignCb(ctx, myEd448Sign); + wolfSSL_CTX_SetEd448VerifyCb(ctx, myEd448Verify); + #endif + #ifdef HAVE_CURVE448 + wolfSSL_CTX_SetX448KeyGenCb(ctx, myX448KeyGen); + wolfSSL_CTX_SetX448SharedSecretCb(ctx, myX448SharedSecret); + #endif + #ifndef NO_RSA wolfSSL_CTX_SetRsaSignCb(ctx, myRsaSign); wolfSSL_CTX_SetRsaVerifyCb(ctx, myRsaVerify); + wolfSSL_CTX_SetRsaSignCheckCb(ctx, myRsaSignCheck); + #ifdef WC_RSA_PSS + wolfSSL_CTX_SetRsaPssSignCb(ctx, myRsaPssSign); + wolfSSL_CTX_SetRsaPssVerifyCb(ctx, myRsaPssVerify); + wolfSSL_CTX_SetRsaPssSignCheckCb(ctx, myRsaPssSignCheck); + #endif wolfSSL_CTX_SetRsaEncCb(ctx, myRsaEnc); wolfSSL_CTX_SetRsaDecCb(ctx, myRsaDec); #endif /* NO_RSA */ } +static WC_INLINE void SetupPkCallbackContexts(WOLFSSL* ssl, void* myCtx) +{ + #ifdef HAVE_ECC + wolfSSL_SetEccKeyGenCtx(ssl, myCtx); + wolfSSL_SetEccSignCtx(ssl, myCtx); + wolfSSL_SetEccVerifyCtx(ssl, myCtx); + wolfSSL_SetEccSharedSecretCtx(ssl, myCtx); + #endif /* HAVE_ECC */ + #ifndef NO_DH + wolfSSL_SetDhAgreeCtx(ssl, myCtx); + #endif + #ifdef HAVE_ED25519 + wolfSSL_SetEd25519SignCtx(ssl, myCtx); + wolfSSL_SetEd25519VerifyCtx(ssl, myCtx); + #endif + #ifdef HAVE_CURVE25519 + wolfSSL_SetX25519KeyGenCtx(ssl, myCtx); + wolfSSL_SetX25519SharedSecretCtx(ssl, myCtx); + #endif + #ifdef HAVE_ED448 + wolfSSL_SetEd448SignCtx(ssl, myCtx); + wolfSSL_SetEd448VerifyCtx(ssl, myCtx); + #endif + #ifdef HAVE_CURVE448 + wolfSSL_SetX448KeyGenCtx(ssl, myCtx); + wolfSSL_SetX448SharedSecretCtx(ssl, myCtx); + #endif + #ifndef NO_RSA + wolfSSL_SetRsaSignCtx(ssl, myCtx); + wolfSSL_SetRsaVerifyCtx(ssl, myCtx); + #ifdef WC_RSA_PSS + wolfSSL_SetRsaPssSignCtx(ssl, myCtx); + wolfSSL_SetRsaPssVerifyCtx(ssl, myCtx); + #endif + wolfSSL_SetRsaEncCtx(ssl, myCtx); + wolfSSL_SetRsaDecCtx(ssl, myCtx); + #endif /* NO_RSA */ +} + #endif /* HAVE_PK_CALLBACKS */ - #if defined(__hpux__) || defined(__MINGW32__) || defined (WOLFSSL_TIRTOS) \ || defined(_MSC_VER) /* HP/UX doesn't have strsep, needed by test/suites.c */ -static INLINE char* strsep(char **stringp, const char *delim) +static WC_INLINE char* strsep(char **stringp, const char *delim) { char* start; char* end; @@ -1815,13 +3529,13 @@ static INLINE char* strsep(char **stringp, const char *delim) /* Create unique filename, len is length of tempfn name, assuming len does not include null terminating character, num is number of characters in tempfn name to randomize */ -static INLINE const char* mymktemp(char *tempfn, int len, int num) +static WC_INLINE const char* mymktemp(char *tempfn, int len, int num) { int x, size; static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; - RNG rng; - byte out; + WC_RNG rng; + byte out; if (tempfn == NULL || len < 1 || num < 1 || len <= num) { printf("Bad input\n"); @@ -1845,6 +3559,7 @@ static INLINE const char* mymktemp(char *tempfn, int len, int num) tempfn[len] = '\0'; wc_FreeRng(&rng); + (void)rng; /* for WC_NO_RNG case */ return tempfn; } @@ -1857,33 +3572,33 @@ static INLINE const char* mymktemp(char *tempfn, int len, int num) #include typedef struct key_ctx { - byte name[WOLFSSL_TICKET_NAME_SZ]; /* name for this context */ - byte key[16]; /* cipher key */ + byte name[WOLFSSL_TICKET_NAME_SZ]; /* name for this context */ + byte key[CHACHA20_POLY1305_AEAD_KEYSIZE]; /* cipher key */ } key_ctx; - static key_ctx myKey_ctx; - static RNG rng; + static THREAD_LS_T key_ctx myKey_ctx; + static THREAD_LS_T WC_RNG myKey_rng; - static INLINE int TicketInit(void) + static WC_INLINE int TicketInit(void) { - int ret = wc_InitRng(&rng); + int ret = wc_InitRng(&myKey_rng); if (ret != 0) return ret; - ret = wc_RNG_GenerateBlock(&rng, myKey_ctx.key, sizeof(myKey_ctx.key)); + ret = wc_RNG_GenerateBlock(&myKey_rng, myKey_ctx.key, sizeof(myKey_ctx.key)); if (ret != 0) return ret; - ret = wc_RNG_GenerateBlock(&rng, myKey_ctx.name,sizeof(myKey_ctx.name)); + ret = wc_RNG_GenerateBlock(&myKey_rng, myKey_ctx.name,sizeof(myKey_ctx.name)); if (ret != 0) return ret; return 0; } - static INLINE void TicketCleanup(void) + static WC_INLINE void TicketCleanup(void) { - wc_FreeRng(&rng); + wc_FreeRng(&myKey_rng); } - static INLINE int myTicketEncCb(WOLFSSL* ssl, + static WC_INLINE int myTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], byte iv[WOLFSSL_TICKET_IV_SZ], byte mac[WOLFSSL_TICKET_MAC_SZ], @@ -1894,7 +3609,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; @@ -1902,7 +3617,7 @@ static INLINE const char* mymktemp(char *tempfn, int len, int num) if (enc) { XMEMCPY(key_name, myKey_ctx.name, WOLFSSL_TICKET_NAME_SZ); - ret = wc_RNG_GenerateBlock(&rng, iv, WOLFSSL_TICKET_IV_SZ); + ret = wc_RNG_GenerateBlock(&myKey_rng, iv, WOLFSSL_TICKET_IV_SZ); if (ret != 0) return WOLFSSL_TICKET_RET_REJECT; /* build aad from key name, iv, and length */ @@ -1949,4 +3664,20 @@ static INLINE const char* mymktemp(char *tempfn, int len, int num) #endif /* HAVE_SESSION_TICKET && CHACHA20 && POLY1305 */ +static WC_INLINE word16 GetRandomPort(void) +{ + word16 port = 0; + + /* Generate random port for testing */ + WC_RNG rng; + if (wc_InitRng(&rng) == 0) { + if (wc_RNG_GenerateBlock(&rng, (byte*)&port, sizeof(port)) == 0) { + port |= 0xC000; /* Make sure its in the 49152 - 65535 range */ + } + wc_FreeRng(&rng); + } + (void)rng; /* for WC_NO_RNG case */ + return port; +} + #endif /* wolfSSL_TEST_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/version.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/version.h index b163a0a3d..332cadfae 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/version.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/version.h @@ -1,8 +1,8 @@ /* wolfssl_version.h.in * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,20 +16,25 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#pragma once +#ifndef WOLFSSL_VERSION_H +#define WOLFSSL_VERSION_H + #ifdef __cplusplus extern "C" { #endif -#define LIBWOLFSSL_VERSION_STRING "3.6.0" -#define LIBWOLFSSL_VERSION_HEX 0x03006000 +#define LIBWOLFSSL_VERSION_STRING "4.4.0" +#define LIBWOLFSSL_VERSION_HEX 0x04004000 #ifdef __cplusplus } #endif + +#endif /* WOLFSSL_VERSION_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/version.h.in b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/version.h.in index 966ff5a6f..0a25a3bf6 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/version.h.in +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/version.h.in @@ -1,8 +1,8 @@ /* wolfssl_version.h.in * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,11 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#pragma once +#ifndef WOLFSSL_VERSION_H +#define WOLFSSL_VERSION_H + #ifdef __cplusplus extern "C" { @@ -33,3 +35,6 @@ extern "C" { } #endif + +#endif /* WOLFSSL_VERSION_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/aes.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/aes.h index a94ad0801..858291849 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/aes.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/aes.h @@ -1,8 +1,8 @@ /* aes.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/aes.h +*/ + + #ifndef WOLF_CRYPT_AES_H #define WOLF_CRYPT_AES_H @@ -26,8 +31,14 @@ #ifndef NO_AES +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + /* included for fips @wc_fips */ -#ifdef HAVE_FIPS +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) #include #if defined(CYASSL_AES_COUNTER) && !defined(WOLFSSL_AES_COUNTER) #define WOLFSSL_AES_COUNTER @@ -37,87 +48,199 @@ #endif #endif -#ifndef HAVE_FIPS /* to avoid redefinition of macros */ -#ifdef HAVE_CAVIUM - #include - #include "cavium_common.h" +#ifndef WC_NO_RNG + #include +#endif +#ifdef STM32_CRYPTO + #include #endif #ifdef WOLFSSL_AESNI #include - -#if !defined (ALIGN16) - #if defined (__GNUC__) - #define ALIGN16 __attribute__ ( (aligned (16))) - #elif defined(_MSC_VER) - /* disable align warning, we want alignment ! */ - #pragma warning(disable: 4324) - #define ALIGN16 __declspec (align (16)) - #else - #define ALIGN16 - #endif -#endif +#include +#include #endif /* WOLFSSL_AESNI */ -#if !defined (ALIGN16) - #define ALIGN16 + +#ifdef WOLFSSL_XILINX_CRYPT +#include "xsecure_aes.h" +#endif + +#if defined(WOLFSSL_AFALG) || defined(WOLFSSL_AFALG_XILINX_AES) +/* included for struct msghdr */ +#include +#endif + +#if defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC) +#include +#endif + +#if defined(HAVE_AESGCM) && !defined(WC_NO_RNG) + #include +#endif + +#if defined(WOLFSSL_CRYPTOCELL) + #include +#endif + +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + defined(WOLFSSL_RENESAS_TSIP_TLS_AES_CRYPT) + #include #endif -#endif /* HAVE_FIPS */ #ifdef __cplusplus extern "C" { #endif -#ifndef HAVE_FIPS /* to avoid redefinition of structures */ -#define WOLFSSL_AES_CAVIUM_MAGIC 0xBEEF0002 +#ifndef WOLFSSL_AES_KEY_SIZE_ENUM +#define WOLFSSL_AES_KEY_SIZE_ENUM +/* these are required for FIPS and non-FIPS */ +enum { + AES_128_KEY_SIZE = 16, /* for 128 bit */ + AES_192_KEY_SIZE = 24, /* for 192 bit */ + AES_256_KEY_SIZE = 32, /* for 256 bit */ + + AES_IV_SIZE = 16, /* always block size */ +}; +#endif + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif enum { - AES_ENC_TYPE = 1, /* cipher unique type */ + AES_ENC_TYPE = WC_CIPHER_AES, /* cipher unique type */ AES_ENCRYPTION = 0, AES_DECRYPTION = 1, - AES_BLOCK_SIZE = 16 + + AES_BLOCK_SIZE = 16, + + KEYWRAP_BLOCK_SIZE = 8, + + GCM_NONCE_MAX_SZ = 16, /* wolfCrypt's maximum nonce size allowed. */ + GCM_NONCE_MID_SZ = 12, /* The usual default nonce size for AES-GCM. */ + GCM_NONCE_MIN_SZ = 8, /* wolfCrypt's minimum nonce size allowed. */ + CCM_NONCE_MIN_SZ = 7, + CCM_NONCE_MAX_SZ = 13, + CTR_SZ = 4, + AES_IV_FIXED_SZ = 4, +#ifdef WOLFSSL_AES_CFB + AES_CFB_MODE = 1, +#endif +#ifdef WOLFSSL_AES_OFB + AES_OFB_MODE = 2, +#endif +#ifdef WOLFSSL_AES_XTS + AES_XTS_MODE = 3, +#endif + +#ifdef HAVE_PKCS11 + AES_MAX_ID_LEN = 32, +#endif }; -typedef struct Aes { +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 */ +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + word32 invokeCtr[2]; + word32 nonceSz; +#endif #ifdef HAVE_AESGCM ALIGN16 byte H[AES_BLOCK_SIZE]; +#ifdef OPENSSL_EXTRA + word32 aadH[4]; /* additional authenticated data GHASH */ + word32 aadLen; /* additional authenticated data len */ +#endif + #ifdef GCM_TABLE /* key-based fast multiplication table. */ ALIGN16 byte M0[256][AES_BLOCK_SIZE]; #endif /* GCM_TABLE */ +#ifdef HAVE_CAVIUM_OCTEON_SYNC + word32 y0; +#endif #endif /* HAVE_AESGCM */ #ifdef WOLFSSL_AESNI byte use_aesni; #endif /* WOLFSSL_AESNI */ -#ifdef HAVE_CAVIUM - AesType type; /* aes key type */ - int devId; /* nitrox device id */ - word32 magic; /* using cavium magic */ - word64 contextHandle; /* nitrox context memory handle */ +#ifdef WOLF_CRYPTO_CB + int devId; + void* devCtx; #endif -#ifdef WOLFSSL_AES_COUNTER - word32 left; /* unsued bytes left from last call */ +#ifdef HAVE_PKCS11 + byte id[AES_MAX_ID_LEN]; + int idLen; #endif -#ifdef WOLFSSL_PIC32MZ_CRYPT - word32 key_ce[AES_BLOCK_SIZE*2/sizeof(word32)] ; - word32 iv_ce [AES_BLOCK_SIZE /sizeof(word32)] ; - int keylen ; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \ + defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) + word32 left; /* unused bytes left from last call */ #endif -#ifdef WOLFSSL_TI_CRYPT - int keylen ; +#ifdef WOLFSSL_XILINX_CRYPT + XSecure_Aes xilAes; + XCsuDma dma; + word32 key_init[8]; + word32 kup; #endif -} Aes; +#if defined(WOLFSSL_AFALG) || defined(WOLFSSL_AFALG_XILINX_AES) + int alFd; /* server socket to bind to */ + int rdFd; /* socket to read from */ + struct msghdr msg; + int dir; /* flag for encrpyt or decrypt */ +#ifdef WOLFSSL_AFALG_XILINX_AES + word32 msgBuf[CMSG_SPACE(4) + CMSG_SPACE(sizeof(struct af_alg_iv) + + GCM_NONCE_MID_SZ)]; +#endif +#endif +#if defined(WOLF_CRYPTO_CB) || (defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))) || \ + (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)) + word32 devKey[AES_MAX_KEY_SIZE/WOLFSSL_BIT_SIZE/sizeof(word32)]; /* raw key */ +#ifdef HAVE_CAVIUM_OCTEON_SYNC + int keySet; +#endif +#endif +#if defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC)) + WC_CRYPTODEV ctx; +#endif +#if defined(WOLFSSL_CRYPTOCELL) + aes_context_t ctx; +#endif +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + defined(WOLFSSL_RENESAS_TSIP_TLS_AES_CRYPT) + TSIP_AES_CTX ctx; +#endif + void* heap; /* memory hint to use */ +}; +#ifndef WC_AES_TYPE_DEFINED + typedef struct Aes Aes; + #define WC_AES_TYPE_DEFINED +#endif + +#ifdef WOLFSSL_AES_XTS +typedef struct XtsAes { + Aes aes; + Aes tweak; +} XtsAes; +#endif #ifdef HAVE_AESGCM typedef struct Gmac { @@ -126,17 +249,68 @@ typedef struct Gmac { #endif /* HAVE_AESGCM */ #endif /* HAVE_FIPS */ - 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); - WOLFSSL_API int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz); - WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz); - WOLFSSL_API int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, - const byte* key, word32 keySz, const byte* iv); + +/* 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); + +#ifdef HAVE_AES_CBC +WOLFSSL_API int wc_AesCbcEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif + +#ifdef WOLFSSL_AES_CFB +WOLFSSL_API int wc_AesCfbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesCfb1Encrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesCfb8Encrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#ifdef HAVE_AES_DECRYPT +WOLFSSL_API int wc_AesCfbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesCfb1Decrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesCfb8Decrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_CFB */ + +#ifdef WOLFSSL_AES_OFB +WOLFSSL_API int wc_AesOfbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#ifdef HAVE_AES_DECRYPT +WOLFSSL_API int wc_AesOfbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_OFB */ + +#ifdef HAVE_AES_ECB +WOLFSSL_API int wc_AesEcbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif /* AES-CTR */ #ifdef WOLFSSL_AES_COUNTER - WOLFSSL_API void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz); + WOLFSSL_API int wc_AesCtrEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); #endif /* AES-DIRECT */ #if defined(WOLFSSL_AES_DIRECT) @@ -145,39 +319,115 @@ typedef struct Gmac { WOLFSSL_API int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, 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); +#elif defined(WOLFSSL_AFALG_XILINX_AES) + WOLFSSL_LOCAL 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, - const byte* iv, word32 ivSz, - byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz); - 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); + WOLFSSL_API 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); + 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); + +#ifndef WC_NO_RNG + WOLFSSL_API int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz); + WOLFSSL_API int wc_AesGcmSetIV(Aes* aes, word32 ivSz, + const byte* ivFixed, word32 ivFixedSz, + WC_RNG* rng); + WOLFSSL_API int wc_AesGcmEncrypt_ex(Aes* aes, byte* out, + const byte* in, word32 sz, + byte* ivOut, word32 ivOutSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#endif /* WC_NO_RNG */ WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len); WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, - const byte* authIn, word32 authInSz, - byte* authTag, word32 authTagSz); + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz); +#ifndef WC_NO_RNG + WOLFSSL_API int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz, WC_RNG* rng); + WOLFSSL_API int wc_GmacVerify(const byte* key, word32 keySz, + const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + const byte* authTag, word32 authTagSz); +#endif /* WC_NO_RNG */ + 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 void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz); - WOLFSSL_API void 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); - WOLFSSL_API 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); + WOLFSSL_API int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz); + WOLFSSL_API 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); + WOLFSSL_API 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); + WOLFSSL_API int wc_AesCcmSetNonce(Aes* aes, + const byte* nonce, word32 nonceSz); + WOLFSSL_API int wc_AesCcmEncrypt_ex(Aes* aes, byte* out, + const byte* in, word32 sz, + byte* ivOut, word32 ivOutSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); #endif /* HAVE_AESCCM */ +#ifdef HAVE_AES_KEYWRAP + WOLFSSL_API int wc_AesKeyWrap(const byte* key, word32 keySz, + const byte* in, word32 inSz, + byte* out, word32 outSz, + const byte* iv); + WOLFSSL_API int wc_AesKeyUnWrap(const byte* key, word32 keySz, + const byte* in, word32 inSz, + byte* out, word32 outSz, + const byte* iv); +#endif /* HAVE_AES_KEYWRAP */ -#ifdef HAVE_CAVIUM - WOLFSSL_API int wc_AesInitCavium(Aes*, int); - WOLFSSL_API void wc_AesFreeCavium(Aes*); +#ifdef WOLFSSL_AES_XTS + +WOLFSSL_API int wc_AesXtsSetKey(XtsAes* aes, const byte* key, + word32 len, int dir, void* heap, int devId); + +WOLFSSL_API int wc_AesXtsEncryptSector(XtsAes* aes, byte* out, + const byte* in, word32 sz, word64 sector); + +WOLFSSL_API int wc_AesXtsDecryptSector(XtsAes* aes, byte* out, + const byte* in, word32 sz, word64 sector); + +WOLFSSL_API int wc_AesXtsEncrypt(XtsAes* aes, byte* out, + const byte* in, word32 sz, const byte* i, word32 iSz); + +WOLFSSL_API int wc_AesXtsDecrypt(XtsAes* aes, byte* out, + const byte* in, word32 sz, const byte* i, word32 iSz); + +WOLFSSL_API int wc_AesXtsFree(XtsAes* aes); #endif +WOLFSSL_API int wc_AesGetKeySize(Aes* aes, word32* keySize); + +WOLFSSL_API int wc_AesInit(Aes* aes, void* heap, int devId); +#ifdef HAVE_PKCS11 +WOLFSSL_API int wc_AesInit_Id(Aes* aes, unsigned char* id, int len, void* heap, + int devId); +#endif +WOLFSSL_API void wc_AesFree(Aes* aes); + #ifdef __cplusplus } /* extern "C" */ #endif @@ -185,4 +435,3 @@ typedef struct Gmac { #endif /* NO_AES */ #endif /* WOLF_CRYPT_AES_H */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/arc4.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/arc4.h index 727b62759..bcdc9076c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/arc4.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/arc4.h @@ -1,8 +1,8 @@ /* arc4.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,12 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/arc4.h +*/ #ifndef WOLF_CRYPT_ARC4_H #define WOLF_CRYPT_ARC4_H @@ -29,11 +32,14 @@ extern "C" { #endif -#define WOLFSSL_ARC4_CAVIUM_MAGIC 0xBEEF0001 +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif enum { ARC4_ENC_TYPE = 4, /* cipher unique type */ - ARC4_STATE_SIZE = 256 + ARC4_STATE_SIZE = 256, + RC4_KEY_SIZE = 16, /* always 128bit */ }; /* ARC4 encryption and decryption */ @@ -41,20 +47,17 @@ typedef struct Arc4 { byte x; byte y; byte state[ARC4_STATE_SIZE]; -#ifdef HAVE_CAVIUM - int devId; /* nitrox device id */ - word32 magic; /* using cavium magic */ - word64 contextHandle; /* nitrox context memory handle */ +#ifdef WOLFSSL_ASYNC_CRYPT + 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 HAVE_CAVIUM - WOLFSSL_API int wc_Arc4InitCavium(Arc4*, int); - WOLFSSL_API void wc_Arc4FreeCavium(Arc4*); -#endif +WOLFSSL_API int wc_Arc4Init(Arc4*, void*, int); +WOLFSSL_API void wc_Arc4Free(Arc4*); #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/asn.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/asn.h index 10d0943bb..6bdda029b 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/asn.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/asn.h @@ -1,8 +1,8 @@ /* asn.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/asn.h +*/ + #ifndef WOLF_CRYPT_ASN_H #define WOLF_CRYPT_ASN_H @@ -26,13 +30,16 @@ #ifndef NO_ASN -#include -#ifndef NO_RSA - #include + +#if !defined(NO_ASN_TIME) && defined(NO_TIME_H) + #define NO_ASN_TIME /* backwards compatibility with NO_TIME_H */ #endif +#include + /* fips declare of RsaPrivateKeyDecode @wc_fips */ -#if defined(HAVE_FIPS) && !defined(NO_RSA) +#if defined(HAVE_FIPS) && !defined(NO_RSA) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) #include #endif @@ -50,27 +57,30 @@ #endif #include #include /* public interface */ -#ifdef HAVE_ECC - #include + +#if defined(NO_SHA) && defined(NO_SHA256) + #define WC_SHA256_DIGEST_SIZE 32 #endif #ifdef __cplusplus extern "C" { #endif +#ifndef EXTERNAL_SERIAL_SIZE + #define EXTERNAL_SERIAL_SIZE 32 +#endif enum { ISSUER = 0, SUBJECT = 1, - EXTERNAL_SERIAL_SIZE = 32, - BEFORE = 0, AFTER = 1 }; /* ASN Tags */ enum ASN_Tags { + ASN_EOC = 0x00, ASN_BOOLEAN = 0x01, ASN_INTEGER = 0x02, ASN_BIT_STRING = 0x03, @@ -81,23 +91,32 @@ enum ASN_Tags { ASN_UTF8STRING = 0x0c, ASN_SEQUENCE = 0x10, ASN_SET = 0x11, + ASN_PRINTABLE_STRING = 0x13, ASN_UTC_TIME = 0x17, ASN_OTHER_TYPE = 0x00, ASN_RFC822_TYPE = 0x01, ASN_DNS_TYPE = 0x02, ASN_DIR_TYPE = 0x04, + ASN_URI_TYPE = 0x06, /* the value 6 is from GeneralName OID */ + ASN_IP_TYPE = 0x07, /* the value 7 is from GeneralName OID */ ASN_GENERALIZED_TIME = 0x18, CRL_EXTENSIONS = 0xa0, ASN_EXTENSIONS = 0xa3, - ASN_LONG_LENGTH = 0x80 + ASN_LONG_LENGTH = 0x80, + ASN_INDEF_LENGTH = 0x80, + + /* ASN_Flags - Bitmask */ + ASN_CONSTRUCTED = 0x20, + ASN_APPLICATION = 0x40, + ASN_CONTEXT_SPECIFIC = 0x80, }; -enum ASN_Flags{ - ASN_CONSTRUCTED = 0x20, - ASN_CONTEXT_SPECIFIC = 0x80 -}; +#define ASN_UTC_TIME_SIZE 14 +#define ASN_GENERALIZED_TIME_SIZE 16 +#define ASN_GENERALIZED_TIME_MAX 68 enum DN_Tags { + ASN_DN_NULL = 0x00, ASN_COMMON_NAME = 0x03, /* CN */ ASN_SUR_NAME = 0x04, /* SN */ ASN_SERIAL_NUMBER = 0x05, /* serialNumber */ @@ -105,128 +124,363 @@ enum DN_Tags { ASN_LOCALITY_NAME = 0x07, /* L */ ASN_STATE_NAME = 0x08, /* ST */ ASN_ORG_NAME = 0x0a, /* O */ - ASN_ORGUNIT_NAME = 0x0b /* OU */ + ASN_ORGUNIT_NAME = 0x0b, /* OU */ + ASN_BUS_CAT = 0x0f, /* businessCategory */ + ASN_EMAIL_NAME = 0x98, /* not oid number there is 97 in 2.5.4.0-97 */ + + /* pilot attribute types + * OID values of 0.9.2342.19200300.100.1.* */ + ASN_USER_ID = 0x01, /* UID */ + ASN_DOMAIN_COMPONENT = 0x19 /* DC */ }; -enum PBES { - PBE_MD5_DES = 0, - PBE_SHA1_DES = 1, - PBE_SHA1_DES3 = 2, - PBE_SHA1_RC4_128 = 3, - PBES2 = 13 /* algo ID */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +typedef struct WOLFSSL_ObjectInfo { + int nid; + int id; + word32 type; + const char* sName; + const char* lName; +} WOLFSSL_ObjectInfo; +extern const size_t wolfssl_object_info_sz; +extern const WOLFSSL_ObjectInfo wolfssl_object_info[]; +#endif /* defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) */ + +/* DN Tag Strings */ +#define WOLFSSL_COMMON_NAME "/CN=" +#define WOLFSSL_LN_COMMON_NAME "/commonName=" +#define WOLFSSL_SUR_NAME "/SN=" +#define WOLFSSL_SERIAL_NUMBER "/serialNumber=" +#define WOLFSSL_COUNTRY_NAME "/C=" +#define WOLFSSL_LN_COUNTRY_NAME "/countryName=" +#define WOLFSSL_LOCALITY_NAME "/L=" +#define WOLFSSL_LN_LOCALITY_NAME "/localityName=" +#define WOLFSSL_STATE_NAME "/ST=" +#define WOLFSSL_LN_STATE_NAME "/stateOrProvinceName=" +#define WOLFSSL_ORG_NAME "/O=" +#define WOLFSSL_LN_ORG_NAME "/organizationName=" +#define WOLFSSL_ORGUNIT_NAME "/OU=" +#define WOLFSSL_LN_ORGUNIT_NAME "/organizationalUnitName=" +#define WOLFSSL_DOMAIN_COMPONENT "/DC=" +#define WOLFSSL_LN_DOMAIN_COMPONENT "/domainComponent=" +#define WOLFSSL_BUS_CAT "/businessCategory=" +#define WOLFSSL_JOI_C "/jurisdictionC=" +#define WOLFSSL_JOI_ST "/jurisdictionST=" +#define WOLFSSL_EMAIL_ADDR "/emailAddress=" + +#define WOLFSSL_USER_ID "/UID=" +#define WOLFSSL_DOMAIN_COMPONENT "/DC=" + +#if defined(WOLFSSL_APACHE_HTTPD) + /* otherName strings */ + #define WOLFSSL_SN_MS_UPN "msUPN" + #define WOLFSSL_LN_MS_UPN "Microsoft User Principal Name" + #define WOLFSSL_MS_UPN_SUM 265 + #define WOLFSSL_SN_DNS_SRV "id-on-dnsSRV" + #define WOLFSSL_LN_DNS_SRV "SRVName" + /* TLS features extension strings */ + #define WOLFSSL_SN_TLS_FEATURE "tlsfeature" + #define WOLFSSL_LN_TLS_FEATURE "TLS Feature" + #define WOLFSSL_TLS_FEATURE_SUM 92 +#endif + +/* NIDs */ +enum +{ + NID_undef = 0, + NID_netscape_cert_type = NID_undef, + NID_des = 66, + NID_des3 = 67, + NID_sha256 = 672, + NID_sha384 = 673, + NID_sha512 = 674, + NID_hw_name_oid = 73, + NID_id_pkix_OCSP_basic = 74, + NID_any_policy = 75, + NID_anyExtendedKeyUsage = 76, + NID_givenName = 99, + NID_initials = 101, + NID_title = 106, + NID_description = 107, + NID_basic_constraints = 133, + NID_key_usage = 129, /* 2.5.29.15 */ + NID_ext_key_usage = 151, /* 2.5.29.37 */ + NID_subject_key_identifier = 128, + NID_authority_key_identifier = 149, + NID_private_key_usage_period = 130, /* 2.5.29.16 */ + NID_subject_alt_name = 131, + NID_issuer_alt_name = 132, + NID_info_access = 69, + NID_sinfo_access = 79, /* id-pe 11 */ + NID_name_constraints = 144, /* 2.5.29.30 */ + NID_crl_distribution_points = 145, /* 2.5.29.31 */ + NID_certificate_policies = 146, + NID_policy_mappings = 147, + NID_policy_constraints = 150, + NID_inhibit_any_policy = 168, /* 2.5.29.54 */ + NID_tlsfeature = 1020, /* id-pe 24 */ + NID_commonName = 0x03, /* matches ASN_COMMON_NAME in asn.h */ + + + NID_surname = 0x04, /* SN */ + NID_serialNumber = 0x05, /* serialNumber */ + NID_countryName = 0x06, /* C */ + NID_localityName = 0x07, /* L */ + NID_stateOrProvinceName = 0x08, /* ST */ + NID_organizationName = 0x0a, /* O */ + NID_organizationalUnitName = 0x0b, /* OU */ + NID_jurisdictionCountryName = 0xc, + NID_jurisdictionStateOrProvinceName = 0xd, + NID_businessCategory = ASN_BUS_CAT, + NID_domainComponent = ASN_DOMAIN_COMPONENT, + NID_emailAddress = 0x30, /* emailAddress */ + NID_id_on_dnsSRV = 82, /* 1.3.6.1.5.5.7.8.7 */ + NID_ms_upn = 265, /* 1.3.6.1.4.1.311.20.2.3 */ + + NID_X9_62_prime_field = 406 /* 1.2.840.10045.1.1 */ }; -enum ENCRYPTION_TYPES { - DES_TYPE = 0, - DES3_TYPE = 1, - RC4_TYPE = 2 -}; - -enum ECC_TYPES { +enum ECC_TYPES +{ ECC_PREFIX_0 = 160, ECC_PREFIX_1 = 161 }; +#ifdef WOLFSSL_CERT_PIV + enum PIV_Tags { + ASN_PIV_CERT = 0x0A, + ASN_PIV_NONCE = 0x0B, + ASN_PIV_SIGNED_NONCE = 0x0C, + + ASN_PIV_TAG_CERT = 0x70, + ASN_PIV_TAG_CERT_INFO = 0x71, + ASN_PIV_TAG_MSCUID = 0x72, + ASN_PIV_TAG_ERR_DET = 0xFE, + + /* certificate info masks */ + ASN_PIV_CERT_INFO_COMPRESSED = 0x03, + ASN_PIV_CERT_INFO_ISX509 = 0x04, + }; +#endif /* WOLFSSL_CERT_PIV */ + + +#define ASN_JOI_PREFIX_SZ 10 +#define ASN_JOI_PREFIX "\x2b\x06\x01\x04\x01\x82\x37\x3c\x02\x01" +#define ASN_JOI_C 0x3 +#define ASN_JOI_ST 0x2 + +#ifndef WC_ASN_NAME_MAX + #ifdef OPENSSL_EXTRA + #define WC_ASN_NAME_MAX 300 + #else + #define WC_ASN_NAME_MAX 256 + #endif +#endif +#define ASN_NAME_MAX WC_ASN_NAME_MAX + enum Misc_ASN { - ASN_NAME_MAX = 256, MAX_SALT_SIZE = 64, /* MAX PKCS Salt length */ MAX_IV_SIZE = 64, /* MAX PKCS Iv length */ - MAX_KEY_SIZE = 64, /* MAX PKCS Key length */ - PKCS5 = 5, /* PKCS oid tag */ - PKCS5v2 = 6, /* PKCS #5 v2.0 */ - PKCS12 = 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 */ MIN_DATE_SIZE = 13, MAX_DATE_SIZE = 32, ASN_GEN_TIME_SZ = 15, /* 7 numbers * 2 + Zulu tag */ +#ifndef NO_RSA MAX_ENCODED_SIG_SZ = 512, +#elif defined(HAVE_ECC) + MAX_ENCODED_SIG_SZ = 140, +#elif defined(HAVE_CURVE448) + MAX_ENCODED_SIG_SZ = 114, +#else + MAX_ENCODED_SIG_SZ = 64, +#endif MAX_SIG_SZ = 256, MAX_ALGO_SZ = 20, + MAX_SHORT_SZ = 6, /* asn int + byte len + 4 byte length */ MAX_SEQ_SZ = 5, /* enum(seq | con) + length(4) */ MAX_SET_SZ = 5, /* enum(set | con) + length(4) */ MAX_OCTET_STR_SZ = 5, /* enum(set | con) + length(4) */ MAX_EXP_SZ = 5, /* enum(contextspec|con|exp) + length(4) */ MAX_PRSTR_SZ = 5, /* enum(prstr) + length(4) */ MAX_VERSION_SZ = 5, /* enum + id + version(byte) + (header(2))*/ - MAX_ENCODED_DIG_SZ = 73, /* sha512 + enum(bit or octet) + legnth(4) */ + MAX_ENCODED_DIG_ASN_SZ= 9, /* enum(bit or octet) + length(4) */ + MAX_ENCODED_DIG_SZ = 64 + MAX_ENCODED_DIG_ASN_SZ, /* asn header + sha512 */ MAX_RSA_INT_SZ = 517, /* RSA raw sz 4096 for bits + tag + len(4) */ + MAX_DSA_INT_SZ = 261, /* DSA raw sz 2048 for bits + tag + len(4) */ MAX_NTRU_KEY_SZ = 610, /* NTRU 112 bit public key */ MAX_NTRU_ENC_SZ = 628, /* NTRU 112 bit DER public encoding */ MAX_LENGTH_SZ = 4, /* Max length size for DER encoding */ MAX_RSA_E_SZ = 16, /* Max RSA public e size */ MAX_CA_SZ = 32, /* Max encoded CA basic constraint length */ MAX_SN_SZ = 35, /* Max encoded serial number (INT) length */ + MAX_DER_DIGEST_SZ = MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ, + /* Maximum DER digest size */ + MAX_DER_DIGEST_ASN_SZ = MAX_ENCODED_DIG_ASN_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ, + /* Maximum DER digest ASN header size */ #ifdef WOLFSSL_CERT_GEN #ifdef WOLFSSL_CERT_REQ /* Max encoded cert req attributes length */ MAX_ATTRIB_SZ = MAX_SEQ_SZ * 3 + (11 + MAX_SEQ_SZ) * 2 + MAX_PRSTR_SZ + CTC_NAME_SIZE, /* 11 is the OID size */ #endif - #ifdef WOLFSSL_ALT_NAMES + #if defined(WOLFSSL_ALT_NAMES) || defined(WOLFSSL_CERT_EXT) MAX_EXTENSIONS_SZ = 1 + MAX_LENGTH_SZ + CTC_MAX_ALT_SIZE, #else MAX_EXTENSIONS_SZ = 1 + MAX_LENGTH_SZ + MAX_CA_SZ, #endif /* Max total extensions, id + len + others */ #endif +#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) || defined(HAVE_PKCS7) + MAX_OID_SZ = 32, /* Max DER length of OID*/ + MAX_OID_STRING_SZ = 64, /* Max string length representation of OID*/ +#endif +#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)) + + CTC_MAX_EKU_OID_SZ, /* Max encoded ExtKeyUsage + (SEQ/LEN + OBJID + OCTSTR/LEN + SEQ + + (6 * (SEQ + OID))) */ + MAX_CERTPOL_NB = CTC_MAX_CERTPOL_NB,/* Max number of Cert Policy */ + MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ, +#endif + MAX_AIA_SZ = 2, /* Max Authority Info Access extension size*/ + MAX_NAME_ENTRIES = 5, /* extra entries added to x509 name struct */ + OCSP_NONCE_EXT_SZ = 35, /* OCSP Nonce Extension size */ MAX_OCSP_EXT_SZ = 58, /* Max OCSP Extension length */ - MAX_OCSP_NONCE_SZ = 18, /* OCSP Nonce size */ + MAX_OCSP_NONCE_SZ = 16, /* OCSP Nonce size */ EIGHTK_BUF = 8192, /* Tmp buffer size */ - MAX_PUBLIC_KEY_SZ = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2 + MAX_PUBLIC_KEY_SZ = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2, /* use bigger NTRU size */ +#ifdef WOLFSSL_ENCRYPTED_KEYS + HEADER_ENCRYPTED_KEY_SIZE = 88,/* Extra header size for encrypted key */ +#else + HEADER_ENCRYPTED_KEY_SIZE = 0, +#endif + TRAILING_ZERO = 1, /* Used for size of zero pad */ + ASN_TAG_SZ = 1, /* single byte ASN.1 tag */ + MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(OPENSSL_EXTRA) || defined(HAVE_PKCS7) + MAX_TIME_STRING_SZ = 25, /* Max length of formatted time string */ +#endif + + PKCS5_SALT_SZ = 8, + + PEM_LINE_LEN = 80, /* PEM line max + fudge */ }; enum Oid_Types { - hashType = 0, - sigType = 1, - keyType = 2, - curveType = 3, - blkType = 4 + oidHashType = 0, + oidSigType = 1, + oidKeyType = 2, + oidCurveType = 3, + oidBlkType = 4, + oidOcspType = 5, + oidCertExtType = 6, + oidCertAuthInfoType = 7, + oidCertPolicyType = 8, + oidCertAltNameType = 9, + oidCertKeyUseType = 10, + oidKdfType = 11, + oidKeyWrapType = 12, + oidCmsKeyAgreeType = 13, + oidPBEType = 14, + oidHmacType = 15, + oidCompressType = 16, + oidCertNameType = 17, + oidTlsExtType = 18, + oidCrlExtType = 19, + oidIgnoreType }; enum Hash_Sum { - MD2h = 646, - MD5h = 649, - SHAh = 88, - SHA256h = 414, - SHA384h = 415, - SHA512h = 416 + MD2h = 646, + MD5h = 649, + SHAh = 88, + SHA224h = 417, + SHA256h = 414, + SHA384h = 415, + SHA512h = 416, + SHA3_224h = 420, + SHA3_256h = 421, + SHA3_384h = 422, + SHA3_512h = 423 }; +#if !defined(NO_DES3) || !defined(NO_AES) enum Block_Sum { - DESb = 69, - DES3b = 652 +#ifdef WOLFSSL_AES_128 + AES128CBCb = 414, + AES128GCMb = 418, + AES128CCMb = 419, +#endif +#ifdef WOLFSSL_AES_192 + AES192CBCb = 434, + AES192GCMb = 438, + AES192CCMb = 439, +#endif +#ifdef WOLFSSL_AES_256 + AES256CBCb = 454, + AES256GCMb = 458, + AES256CCMb = 459, +#endif +#ifndef NO_DES3 + DESb = 69, + DES3b = 652 +#endif }; +#endif /* !NO_DES3 || !NO_AES */ enum Key_Sum { - DSAk = 515, - RSAk = 645, - NTRUk = 274, - ECDSAk = 518 + DSAk = 515, + RSAk = 645, + NTRUk = 274, + ECDSAk = 518, + ED25519k = 256, + ED448k = 257, + DHk = 647, /* dhKeyAgreement OID: 1.2.840.113549.1.3.1 */ }; - -enum Ecc_Sum { - ECC_256R1 = 526, - ECC_384R1 = 210, - ECC_521R1 = 211, - ECC_160R1 = 184, - ECC_192R1 = 520, - ECC_224R1 = 209 +#if !defined(NO_AES) || defined(HAVE_PKCS7) +enum KeyWrap_Sum { +#ifdef WOLFSSL_AES_128 + AES128_WRAP = 417, +#endif +#ifdef WOLFSSL_AES_192 + AES192_WRAP = 437, +#endif +#ifdef WOLFSSL_AES_256 + AES256_WRAP = 457, +#endif +#ifdef HAVE_PKCS7 + PWRI_KEK_WRAP = 680 /*id-alg-PWRI-KEK, 1.2.840.113549.1.9.16.3.9 */ +#endif }; +#endif /* !NO_AES || PKCS7 */ + +enum Key_Agree { + dhSinglePass_stdDH_sha1kdf_scheme = 464, + dhSinglePass_stdDH_sha224kdf_scheme = 188, + dhSinglePass_stdDH_sha256kdf_scheme = 189, + dhSinglePass_stdDH_sha384kdf_scheme = 190, + dhSinglePass_stdDH_sha512kdf_scheme = 191, +}; + enum KDF_Sum { @@ -234,19 +488,37 @@ enum KDF_Sum { }; +enum HMAC_Sum { + HMAC_SHA224_OID = 652, + HMAC_SHA256_OID = 653, + HMAC_SHA384_OID = 654, + HMAC_SHA512_OID = 655, + HMAC_SHA3_224_OID = 426, + HMAC_SHA3_256_OID = 427, + HMAC_SHA3_384_OID = 428, + HMAC_SHA3_512_OID = 429 +}; + + enum Extensions_Sum { BASIC_CA_OID = 133, ALT_NAMES_OID = 131, CRL_DIST_OID = 145, - AUTH_INFO_OID = 69, - CA_ISSUER_OID = 117, + AUTH_INFO_OID = 69, /* id-pe 1 */ AUTH_KEY_OID = 149, SUBJ_KEY_OID = 128, CERT_POLICY_OID = 146, KEY_USAGE_OID = 129, /* 2.5.29.15 */ INHIBIT_ANY_OID = 168, /* 2.5.29.54 */ - EXT_KEY_USAGE_OID = 151, /* 2.5.29.37 */ - NAME_CONS_OID = 144 /* 2.5.29.30 */ + EXT_KEY_USAGE_OID = 151, /* 2.5.29.37 */ + NAME_CONS_OID = 144, /* 2.5.29.30 */ + PRIV_KEY_USAGE_PERIOD_OID = 130, /* 2.5.29.16 */ + SUBJECT_INFO_ACCESS = 79, /* id-pe 11 */ + POLICY_MAP_OID = 147, + POLICY_CONST_OID = 150, + ISSUE_ALT_NAMES_OID = 132, + TLS_FEATURE_OID = 92, /* id-pe 24 */ + NETSCAPE_CT_OID = 753 /* 2.16.840.1.113730.1.1 */ }; enum CertificatePolicy_Sum { @@ -266,36 +538,61 @@ 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 */ }; +#ifdef HAVE_LIBZ +enum CompressAlg_Sum { + ZLIBc = 679 /* 1.2.840.113549.1.9.16.3.8, id-alg-zlibCompress */ +}; +#endif enum VerifyType { - NO_VERIFY = 0, - VERIFY = 1 + NO_VERIFY = 0, + VERIFY = 1, + VERIFY_CRL = 2, + VERIFY_OCSP = 3, + VERIFY_NAME = 4, + VERIFY_SKIP_DATE = 5, }; +#ifdef WOLFSSL_CERT_EXT +enum KeyIdType { + SKID_TYPE = 0, + AKID_TYPE = 1 +}; +#endif -/* Key usage extension bits */ -#define KEYUSE_DIGITAL_SIG 0x0100 -#define KEYUSE_CONTENT_COMMIT 0x0080 -#define KEYUSE_KEY_ENCIPHER 0x0040 -#define KEYUSE_DATA_ENCIPHER 0x0020 -#define KEYUSE_KEY_AGREE 0x0010 -#define KEYUSE_KEY_CERT_SIGN 0x0008 -#define KEYUSE_CRL_SIGN 0x0004 -#define KEYUSE_ENCIPHER_ONLY 0x0002 -#define KEYUSE_DECIPHER_ONLY 0x0001 +/* Key usage extension bits (based on RFC 5280) */ +#define KEYUSE_DIGITAL_SIG 0x0080 +#define KEYUSE_CONTENT_COMMIT 0x0040 +#define KEYUSE_KEY_ENCIPHER 0x0020 +#define KEYUSE_DATA_ENCIPHER 0x0010 +#define KEYUSE_KEY_AGREE 0x0008 +#define KEYUSE_KEY_CERT_SIGN 0x0004 +#define KEYUSE_CRL_SIGN 0x0002 +#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_USER 0x80 +#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; struct DNS_entry { DNS_entry* next; /* next on DNS list */ + int type; /* i.e. ASN_DNS_TYPE */ + int len; /* actual DNS len */ char* name; /* actual DNS name */ }; @@ -309,6 +606,8 @@ struct Base_entry { byte type; /* Name base type (DNS or RFC822) */ }; +#define DOMAIN_COMPONENT_MAX 10 +#define DN_NAMES_MAX 9 struct DecodedName { char* fullName; @@ -316,34 +615,183 @@ struct DecodedName { int entryCount; int cnIdx; int cnLen; + int cnNid; int snIdx; int snLen; + int snNid; int cIdx; int cLen; + int cNid; int lIdx; int lLen; + int lNid; int stIdx; int stLen; + int stNid; int oIdx; int oLen; + int oNid; int ouIdx; int ouLen; +#ifdef WOLFSSL_CERT_EXT + int bcIdx; + int bcLen; + int jcIdx; + int jcLen; + int jsIdx; + int jsLen; +#endif + int ouNid; int emailIdx; int emailLen; + int emailNid; int uidIdx; int uidLen; + int uidNid; int serialIdx; int serialLen; + int serialNid; + int dcIdx[DOMAIN_COMPONENT_MAX]; + int dcLen[DOMAIN_COMPONENT_MAX]; + int dcNum; + int dcMode; +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + /* hold the location / order with which each of the DN tags was found + * + * example of ASN_DOMAIN_COMPONENT at index 0 if first found and so on. + */ + int loc[DOMAIN_COMPONENT_MAX + DN_NAMES_MAX]; + int locSz; +#endif }; +enum SignatureState { + SIG_STATE_BEGIN, + SIG_STATE_HASH, + SIG_STATE_KEY, + SIG_STATE_DO, + SIG_STATE_CHECK, +}; + + +#ifdef HAVE_PK_CALLBACKS +#ifdef HAVE_ECC + typedef int (*wc_CallbackEccVerify)( + const unsigned char* sig, unsigned int sigSz, + const unsigned char* hash, unsigned int hashSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx); +#endif +#ifndef NO_RSA + typedef int (*wc_CallbackRsaVerify)( + unsigned char* sig, unsigned int sigSz, + unsigned char** out, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +#endif +#endif /* HAVE_PK_CALLBACKS */ + +struct SignatureCtx { + void* heap; + byte* digest; +#ifndef NO_RSA + byte* out; + byte* plain; +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + 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 + #ifdef HAVE_ED448 + struct ed448_key* ed448; + #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 + +#ifdef HAVE_PK_CALLBACKS +#ifdef HAVE_ECC + wc_CallbackEccVerify pkCbEcc; + void* pkCtxEcc; +#endif +#ifndef NO_RSA + wc_CallbackRsaVerify pkCbRsa; + void* pkCtxRsa; +#endif +#endif /* HAVE_PK_CALLBACKS */ +#ifndef NO_RSA +#ifdef WOLFSSL_RENESAS_TSIP_TLS + byte verifyByTSIP; + word32 certBegin; + word32 pubkey_n_start; + word32 pubkey_n_len; + word32 pubkey_e_start; + word32 pubkey_e_len; +#endif +#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 */ +}; + +#ifndef WOLFSSL_MAX_PATH_LEN + /* RFC 5280 Section 6.1.2. "Initialization" - item (k) defines + * (k) max_path_length: this integer is initialized to "n", is + * decremented for each non-self-issued certificate in the path, + * and may be reduced to the value in the path length constraint + * field within the basic constraints extension of a CA + * certificate. + * + * wolfSSL has arbitrarily selected the value 127 for "n" in the above + * description. Users can modify the maximum path length by setting + * WOLFSSL_MAX_PATH_LEN to a preferred value at build time + */ + #define WOLFSSL_MAX_PATH_LEN 127 +#endif typedef struct DecodedCert DecodedCert; typedef struct DecodedName DecodedName; 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 { - byte* publicKey; + const byte* publicKey; word32 pubKeySize; int pubKeyStored; word32 certBegin; /* offset to start of cert */ @@ -361,80 +809,68 @@ struct DecodedCert { byte subjectHash[KEYID_SIZE]; /* hash of all Names */ byte issuerHash[KEYID_SIZE]; /* hash of all Names */ #ifdef HAVE_OCSP + byte subjectKeyHash[KEYID_SIZE]; /* hash of the public Key */ byte issuerKeyHash[KEYID_SIZE]; /* hash of the public Key */ #endif /* HAVE_OCSP */ - byte* signature; /* not owned, points into raw cert */ + const byte* signature; /* not owned, points into raw cert */ char* subjectCN; /* CommonName */ int subjectCNLen; /* CommonName Length */ char subjectCNEnc; /* CommonName Encoding */ - int subjectCNStored; /* have we saved a copy we own */ char issuer[ASN_NAME_MAX]; /* full name including common name */ char subject[ASN_NAME_MAX]; /* full name including common name */ int verify; /* Default to yes, but could be off */ - byte* source; /* byte buffer holder cert, NOT owner */ + const byte* source; /* byte buffer holder cert, NOT owner */ word32 srcIdx; /* current offset into buffer */ word32 maxIdx; /* max offset based on init size */ void* heap; /* for user memory overrides */ byte serial[EXTERNAL_SERIAL_SIZE]; /* raw serial number */ int serialSz; /* raw serial bytes stored */ - byte* extensions; /* not owned, points into raw cert */ + const byte* extensions; /* not owned, points into raw cert */ int extensionsSz; /* length of cert extensions */ word32 extensionsIdx; /* if want to go back and parse later */ - byte* extAuthInfo; /* Authority Information Access URI */ + const byte* extAuthInfo; /* Authority Information Access URI */ int extAuthInfoSz; /* length of the URI */ - byte* extCrlInfo; /* CRL Distribution Points */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + const byte* extAuthInfoCaIssuer; /* Authority Info Access caIssuer URI */ + int extAuthInfoCaIssuerSz; /* length of the caIssuer URI */ +#endif + const byte* extCrlInfo; /* CRL Distribution Points */ int extCrlInfoSz; /* length of the URI */ byte extSubjKeyId[KEYID_SIZE]; /* Subject Key ID */ - byte extSubjKeyIdSet; /* Set when the SKID was read from cert */ byte extAuthKeyId[KEYID_SIZE]; /* Authority Key ID */ - byte extAuthKeyIdSet; /* Set when the AKID was read from cert */ -#ifndef IGNORE_NAME_CONSTRAINTS - byte extNameConstraintSet; -#endif /* IGNORE_NAME_CONSTRAINTS */ - byte isCA; /* CA basic constraint true */ - byte weOwnAltNames; /* altNames haven't been given to copy */ - byte extKeyUsageSet; + byte pathLength; /* CA basic constraint path length */ + byte maxPathLen; /* max_path_len see RFC 5280 section + * 6.1.2 "Initialization" - (k) for + * description of max_path_len */ word16 extKeyUsage; /* Key usage bitfield */ - byte extExtKeyUsageSet; /* Extended Key Usage */ byte extExtKeyUsage; /* Extended Key usage bitfield */ -#ifdef OPENSSL_EXTRA - byte extBasicConstSet; - byte extBasicConstCrit; - byte extBasicConstPlSet; - word32 pathLength; /* CA basic constraint path length, opt */ - byte extSubjAltNameSet; - byte extSubjAltNameCrit; - byte extAuthKeyIdCrit; -#ifndef IGNORE_NAME_CONSTRAINTS - byte extNameConstraintCrit; -#endif /* IGNORE_NAME_CONSTRAINTS */ - byte extSubjKeyIdCrit; - byte extKeyUsageCrit; - byte extExtKeyUsageCrit; - byte* extExtKeyUsageSrc; + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + const byte* extExtKeyUsageSrc; word32 extExtKeyUsageSz; word32 extExtKeyUsageCount; - byte* extAuthKeyIdSrc; + const byte* extAuthKeyIdSrc; word32 extAuthKeyIdSz; - byte* extSubjKeyIdSrc; + const byte* extSubjKeyIdSrc; word32 extSubjKeyIdSz; #endif -#ifdef HAVE_ECC + +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) word32 pkCurveOID; /* Public Key's curve OID */ #endif /* HAVE_ECC */ - byte* beforeDate; + const byte* beforeDate; int beforeDateLen; - byte* afterDate; + const byte* afterDate; int afterDateLen; -#ifdef HAVE_PKCS7 - byte* issuerRaw; /* pointer to issuer inside source */ +#if defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT) + const byte* issuerRaw; /* pointer to issuer inside source */ int issuerRawLen; #endif -#ifndef IGNORE_NAME_CONSTRAINT - byte* subjectRaw; /* pointer to subject inside source */ +#if !defined(IGNORE_NAME_CONSTRAINTS) || defined(WOLFSSL_CERT_EXT) + const byte* subjectRaw; /* pointer to subject inside source */ int subjectRawLen; #endif -#if defined(WOLFSSL_CERT_GEN) +#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT) /* easy access to subject info for other sign */ char* subjectSN; int subjectSNLen; @@ -454,10 +890,24 @@ struct DecodedCert { char* subjectOU; int subjectOULen; char subjectOUEnc; + char* subjectSND; + int subjectSNDLen; + char subjectSNDEnc; +#ifdef WOLFSSL_CERT_EXT + char* subjectBC; + int subjectBCLen; + char subjectBCEnc; + char* subjectJC; + int subjectJCLen; + char subjectJCEnc; + char* subjectJS; + int subjectJSLen; + char subjectJSEnc; +#endif char* subjectEmail; int subjectEmailLen; #endif /* WOLFSSL_CERT_GEN */ -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) DecodedName issuerName; DecodedName subjectName; #endif /* OPENSSL_EXTRA */ @@ -468,18 +918,68 @@ struct DecodedCert { byte* hwType; int hwSerialNumSz; byte* hwSerialNum; - #ifdef OPENSSL_EXTRA - byte extCertPolicySet; - byte extCertPolicyCrit; - #endif /* OPENSSL_EXTRA */ #endif /* WOLFSSL_SEP */ +#ifdef WOLFSSL_CERT_EXT + char extCertPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ]; + int extCertPoliciesNb; +#endif /* defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT) */ + + Signer* ca; +#ifndef NO_CERTS + SignatureCtx sigCtx; +#endif +#ifdef WOLFSSL_RENESAS_TSIP + byte* tsip_encRsaKeyIdx; +#endif + + int badDate; + int criticalExt; + + /* Option Bits */ + byte subjectCNStored : 1; /* have we saved a copy we own */ + byte extSubjKeyIdSet : 1; /* Set when the SKID was read from cert */ + byte extAuthKeyIdSet : 1; /* Set when the AKID was read from cert */ +#ifndef IGNORE_NAME_CONSTRAINTS + byte extNameConstraintSet : 1; +#endif + byte isCA : 1; /* CA basic constraint true */ + byte pathLengthSet : 1; /* CA basic const path length set */ + byte weOwnAltNames : 1; /* altNames haven't been given to copy */ + byte extKeyUsageSet : 1; + byte extExtKeyUsageSet : 1; /* Extended Key Usage set */ + byte extCRLdistSet : 1; + byte extAuthInfoSet : 1; + byte extBasicConstSet : 1; + byte extSubjAltNameSet : 1; + byte inhibitAnyOidSet : 1; + byte selfSigned : 1; /* Indicates subject and issuer are same */ +#if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT) + byte extCertPolicySet : 1; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + byte extCRLdistCrit : 1; + byte extAuthInfoCrit : 1; + byte extBasicConstCrit : 1; + byte extSubjAltNameCrit : 1; + byte extAuthKeyIdCrit : 1; + #ifndef IGNORE_NAME_CONSTRAINTS + byte extNameConstraintCrit : 1; + #endif + byte extSubjKeyIdCrit : 1; + byte extKeyUsageCrit : 1; + byte extExtKeyUsageCrit : 1; +#endif /* OPENSSL_EXTRA */ +#if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT) + byte extCertPolicyCrit : 1; +#endif + }; #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 */ @@ -488,7 +988,11 @@ struct Signer { word32 pubKeySize; word32 keyOID; /* key type */ word16 keyUsage; - byte* publicKey; + byte maxPathLen; + byte pathLength; + byte pathLengthSet : 1; + byte selfSigned : 1; + const byte* publicKey; int nameLen; char* name; /* common name */ #ifndef IGNORE_NAME_CONSTRAINTS @@ -501,62 +1005,188 @@ struct Signer { byte subjectKeyIdHash[SIGNER_DIGEST_SIZE]; /* sha hash of names in certificate */ #endif + #ifdef HAVE_OCSP + byte subjectKeyHash[KEYID_SIZE]; + #endif +#ifdef WOLFSSL_SIGNER_DER_CERT + DerBuffer* derCert; +#endif +#ifdef WOLFSSL_RENESAS_TSIP_TLS + word32 cm_idx; +#endif Signer* next; }; -/* not for public consumption but may use for testing sometimes */ -#ifdef WOLFSSL_TEST_CERT - #define WOLFSSL_TEST_API WOLFSSL_API +#ifdef WOLFSSL_TRUST_PEER_CERT +/* used for having trusted peer certs rather then CA */ +struct TrustedPeerCert { + int nameLen; + char* name; /* common name */ + #ifndef IGNORE_NAME_CONSTRAINTS + Base_entry* permittedNames; + Base_entry* excludedNames; + #endif /* IGNORE_NAME_CONSTRAINTS */ + byte subjectNameHash[SIGNER_DIGEST_SIZE]; + /* sha hash of names in certificate */ + #ifndef NO_SKID + byte subjectKeyIdHash[SIGNER_DIGEST_SIZE]; + /* sha hash of names in certificate */ + #endif + word32 sigLen; + byte* sig; + struct TrustedPeerCert* next; +}; +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + +/* for testing or custom openssl wrappers */ +#if defined(WOLFSSL_TEST_CERT) || defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) + #define WOLFSSL_ASN_API WOLFSSL_API #else - #define WOLFSSL_TEST_API WOLFSSL_LOCAL + #define WOLFSSL_ASN_API WOLFSSL_LOCAL #endif -WOLFSSL_TEST_API void FreeAltNames(DNS_entry*, void*); +WOLFSSL_LOCAL int CalcHashId(const byte* data, word32 len, byte* hash); + +WOLFSSL_ASN_API int wc_BerToDer(const byte* ber, word32 berSz, byte* der, + word32* derSz); + +WOLFSSL_ASN_API void FreeAltNames(DNS_entry*, void*); #ifndef IGNORE_NAME_CONSTRAINTS - WOLFSSL_TEST_API void FreeNameSubtrees(Base_entry*, void*); + WOLFSSL_ASN_API void FreeNameSubtrees(Base_entry*, void*); #endif /* IGNORE_NAME_CONSTRAINTS */ -WOLFSSL_TEST_API void InitDecodedCert(DecodedCert*, byte*, word32, void*); -WOLFSSL_TEST_API void FreeDecodedCert(DecodedCert*); -WOLFSSL_TEST_API int ParseCert(DecodedCert*, int type, int verify, void* cm); +WOLFSSL_ASN_API void InitDecodedCert(DecodedCert*, const byte*, word32, void*); +WOLFSSL_ASN_API void FreeDecodedCert(DecodedCert*); +WOLFSSL_ASN_API int ParseCert(DecodedCert*, int type, int verify, void* cm); -WOLFSSL_LOCAL int ParseCertRelative(DecodedCert*, int type, int verify,void* cm); +WOLFSSL_LOCAL int DecodePolicyOID(char *o, word32 oSz, + const byte *in, word32 inSz); +WOLFSSL_LOCAL int EncodePolicyOID(byte *out, word32 *outSz, + const char *in, void* heap); +WOLFSSL_API int CheckCertSignature(const byte*,word32,void*,void* cm); +WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz, + void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID); +WOLFSSL_LOCAL int ParseCertRelative(DecodedCert*,int type,int verify,void* cm); WOLFSSL_LOCAL int DecodeToKey(DecodedCert*, int verify); +WOLFSSL_LOCAL int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate); +WOLFSSL_LOCAL const byte* OidFromId(word32 id, word32 type, word32* oidSz); WOLFSSL_LOCAL Signer* MakeSigner(void*); WOLFSSL_LOCAL void FreeSigner(Signer*, void*); WOLFSSL_LOCAL void FreeSignerTable(Signer**, int, void*); +#ifdef WOLFSSL_TRUST_PEER_CERT +WOLFSSL_LOCAL void FreeTrustedPeer(TrustedPeerCert*, void*); +WOLFSSL_LOCAL void FreeTrustedPeerTable(TrustedPeerCert**, int, void*); +#endif /* WOLFSSL_TRUST_PEER_CERT */ +WOLFSSL_ASN_API int ToTraditional(byte* buffer, word32 length); +WOLFSSL_ASN_API int ToTraditional_ex(byte* buffer, word32 length, + word32* algId); +WOLFSSL_LOCAL int ToTraditionalInline(const byte* input, word32* inOutIdx, + word32 length); +WOLFSSL_LOCAL int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, + word32 length, word32* algId); +WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*,int, + word32* algId); +WOLFSSL_ASN_API int UnTraditionalEnc(byte* key, word32 keySz, byte* out, + word32* outSz, const char* password, int passwordSz, int vPKCS, + int vAlgo, byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap); +WOLFSSL_ASN_API int TraditionalEnc(byte* key, word32 keySz, byte* out, + word32* outSz, const char* password, int passwordSz, int vPKCS, + int vAlgo, int encAlgId, byte* salt, word32 saltSz, int itt, + WC_RNG* rng, void* heap); +WOLFSSL_LOCAL int DecryptContent(byte* input, word32 sz,const char* psw,int pswSz); +WOLFSSL_LOCAL int EncryptContent(byte* input, word32 sz, byte* out, word32* outSz, + const char* password,int passwordSz, int vPKCS, int vAlgo, + byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap); +WOLFSSL_LOCAL int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, + word32* oidSz, int* algoID, void* heap); -WOLFSSL_LOCAL int ToTraditional(byte* buffer, word32 length); -WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*, int); - +typedef struct tm wolfssl_tm; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +WOLFSSL_LOCAL int GetTimeString(byte* date, int format, char* buf, int len); +#endif +#if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7) +WOLFSSL_LOCAL int GetAsnTimeString(void* currTime, byte* buf, word32 len); +#endif +WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format, + wolfssl_tm* certTime, int* idx); +WOLFSSL_LOCAL int DateGreaterThan(const struct tm* a, const struct tm* b); WOLFSSL_LOCAL int ValidateDate(const byte* date, byte format, int dateType); +WOLFSSL_LOCAL int wc_OBJ_sn2nid(const char *sn); /* ASN.1 helper functions */ +#ifdef WOLFSSL_CERT_GEN +WOLFSSL_ASN_API int SetName(byte* output, word32 outputSz, CertName* name); +#endif +WOLFSSL_LOCAL int GetShortInt(const byte* input, word32* inOutIdx, int* number, + word32 maxIdx); +WOLFSSL_LOCAL int SetShortInt(byte* input, word32* inOutIdx, word32 number, + word32 maxIdx); + +WOLFSSL_LOCAL const char* GetSigName(int oid); WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, word32 maxIdx); +WOLFSSL_LOCAL int GetLength_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check); WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, word32 maxIdx); +WOLFSSL_LOCAL int GetSequence_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check); +WOLFSSL_LOCAL int GetOctetString(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx); WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, word32 maxIdx); +WOLFSSL_LOCAL int GetSet_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check); WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, - int* version); + int* version, word32 maxIdx); WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx); +#ifdef HAVE_OID_ENCODING + WOLFSSL_LOCAL int EncodeObjectId(const word16* in, word32 inSz, + byte* out, word32* outSz); +#endif +#ifdef HAVE_OID_DECODING + WOLFSSL_LOCAL int DecodeObjectId(const byte* in, word32 inSz, + word16* out, word32* outSz); +#endif +WOLFSSL_LOCAL int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx); +WOLFSSL_LOCAL int SetObjectId(int len, byte* output); +WOLFSSL_LOCAL int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, + word32 oidType, word32 maxIdx); WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, - word32 maxIdx); + word32 oidType, word32 maxIdx); +WOLFSSL_LOCAL int GetASNTag(const byte* input, word32* idx, byte* tag, + word32 inputSz); WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output); WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output); WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output); -WOLFSSL_LOCAL word32 SetImplicit(byte tag, byte number, word32 len,byte* output); +#if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) && !defined(NO_DH) \ + || defined(WOLFSSL_OPENSSH) +WOLFSSL_LOCAL int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz); +WOLFSSL_LOCAL int wc_DhPubKeyToDer(DhKey* key, byte* out, word32* outSz); +WOLFSSL_LOCAL int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz); +#endif +WOLFSSL_LOCAL word32 SetBitString(word32 len, byte unusedBits, byte* output); +WOLFSSL_LOCAL word32 SetImplicit(byte tag,byte number,word32 len,byte* output); 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 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, + word32 outputSz, 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, int maxIdx); +WOLFSSL_LOCAL int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der); +WOLFSSL_LOCAL int StoreDHparams(byte* out, word32* outLen, mp_int* p, mp_int* g); +WOLFSSL_LOCAL int FlattenAltNames( byte*, word32, const DNS_entry*); #ifdef HAVE_ECC /* ASN sig helpers */ @@ -565,27 +1195,44 @@ WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, WOLFSSL_LOCAL int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s); #endif +#if defined HAVE_ECC && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +WOLFSSL_API int EccEnumToNID(int n); +#endif + +WOLFSSL_LOCAL void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId); +WOLFSSL_LOCAL void FreeSignatureCtx(SignatureCtx* sigCtx); + +#ifndef NO_CERTS + +WOLFSSL_LOCAL int wc_EncryptedInfoParse(EncryptedInfo* info, char** pBuffer, + size_t bufSz); + +WOLFSSL_LOCAL int PemToDer(const unsigned char* buff, long sz, int type, + DerBuffer** pDer, void* heap, EncryptedInfo* info, + int* eccKey); +WOLFSSL_LOCAL int AllocDer(DerBuffer** der, word32 length, int type, void* heap); +WOLFSSL_LOCAL void FreeDer(DerBuffer** der); + +#endif /* !NO_CERTS */ #ifdef WOLFSSL_CERT_GEN enum cert_enums { - NAME_ENTRIES = 8, +#ifdef WOLFSSL_CERT_EXT + NAME_ENTRIES = 10, +#else + NAME_ENTRIES = 9, +#endif JOINT_LEN = 2, EMAIL_JOINT_LEN = 9, + PILOT_JOINT_LEN = 10, RSA_KEY = 10, NTRU_KEY = 11, - ECC_KEY = 12 + ECC_KEY = 12, + ED25519_KEY = 13, + ED448_KEY = 14 }; -#ifndef WOLFSSL_PEMCERT_TODER_DEFINED -#ifndef NO_FILESYSTEM -/* forward from wolfSSL */ -WOLFSSL_API -int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz); -#define WOLFSSL_PEMCERT_TODER_DEFINED -#endif -#endif - #endif /* WOLFSSL_CERT_GEN */ @@ -617,6 +1264,13 @@ enum Ocsp_Sums { OCSP_NONCE_OID = 118 }; +#ifdef OPENSSL_EXTRA +enum Ocsp_Verify_Error { + OCSP_VERIFY_ERROR_NONE = 0, + OCSP_BAD_ISSUER = 1 +}; +#endif + typedef struct OcspRequest OcspRequest; typedef struct OcspResponse OcspResponse; @@ -634,6 +1288,15 @@ struct CertStatus { byte nextDate[MAX_DATE_SIZE]; byte thisDateFormat; byte nextDateFormat; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + WOLFSSL_ASN1_TIME thisDateParsed; + WOLFSSL_ASN1_TIME nextDateParsed; + byte* thisDateAsn; + byte* nextDateAsn; +#endif + + byte* rawOcspResponse; + word32 rawOcspResponseSz; }; @@ -644,7 +1307,7 @@ struct OcspResponse { word32 responseSz; /* length of the OCSP Response */ byte producedDate[MAX_DATE_SIZE]; - /* Date at which this response was signed */ + /* Date at which this response was signed */ byte producedDateFormat; /* format of the producedDate */ byte* issuerHash; byte* issuerKeyHash; @@ -663,32 +1326,55 @@ struct OcspResponse { byte* source; /* pointer to source buffer, not owned */ word32 maxIdx; /* max offset based on init size */ + +#ifdef OPENSSL_EXTRA + int verifyError; +#endif }; struct OcspRequest { - DecodedCert* cert; + byte issuerHash[KEYID_SIZE]; + byte issuerKeyHash[KEYID_SIZE]; + byte* serial; /* copy of the serial number in source cert */ + int serialSz; +#ifdef OPENSSL_EXTRA + WOLFSSL_ASN1_INTEGER* serialInt; +#endif + byte* url; /* copy of the extAuthInfo in source cert */ + int urlSz; - byte useNonce; - byte nonce[MAX_OCSP_NONCE_SZ]; - int nonceSz; - - byte* issuerHash; /* pointer to issuerHash in source cert */ - byte* issuerKeyHash; /* pointer to issuerKeyHash in source cert */ - byte* serial; /* pointer to serial number in source cert */ - int serialSz; /* length of the serial number */ - - byte* dest; /* pointer to the destination ASN.1 buffer */ - word32 destSz; /* length of the destination buffer */ + byte nonce[MAX_OCSP_NONCE_SZ]; + int nonceSz; + void* heap; + void* ssl; }; +typedef struct OcspEntry OcspEntry; + +#ifdef NO_SHA +#define OCSP_DIGEST_SIZE WC_SHA256_DIGEST_SIZE +#else +#define OCSP_DIGEST_SIZE WC_SHA_DIGEST_SIZE +#endif + +struct OcspEntry +{ + OcspEntry *next; /* next entry */ + byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */ + byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */ + CertStatus *status; /* OCSP response list */ + int totalStatus; /* number on list */ +}; WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32); -WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*); +WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*, void* heap, int); + +WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte, void*); +WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*); +WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*, byte*, word32); +WOLFSSL_LOCAL word32 EncodeOcspRequestExtensions(OcspRequest*, byte*, word32); -WOLFSSL_LOCAL void InitOcspRequest(OcspRequest*, DecodedCert*, - byte, byte*, word32); -WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*); WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest*, OcspResponse*); @@ -715,7 +1401,7 @@ struct DecodedCRL { word32 sigLength; /* length of signature */ word32 signatureOID; /* sum of algorithm object id */ byte* signature; /* pointer into raw source, not owned */ - byte issuerHash[SIGNER_DIGEST_SIZE]; /* issuer hash */ + byte issuerHash[SIGNER_DIGEST_SIZE]; /* issuer name hash */ byte crlHash[SIGNER_DIGEST_SIZE]; /* raw crl data hash */ byte lastDate[MAX_DATE_SIZE]; /* last date updated */ byte nextDate[MAX_DATE_SIZE]; /* next update date */ @@ -723,9 +1409,19 @@ struct DecodedCRL { byte nextDateFormat; /* format of next date */ RevokedCert* certs; /* revoked cert list */ int totalCerts; /* number on list */ + void* heap; +#ifndef NO_SKID + byte extAuthKeyIdSet; + byte extAuthKeyId[SIGNER_DIGEST_SIZE]; /* Authority Key ID */ +#endif }; -WOLFSSL_LOCAL void InitDecodedCRL(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*); @@ -738,5 +1434,37 @@ WOLFSSL_LOCAL void FreeDecodedCRL(DecodedCRL*); #endif #endif /* !NO_ASN */ -#endif /* WOLF_CRYPT_ASN_H */ + +#if !defined(NO_ASN) || !defined(NO_PWDBASED) + +#ifndef MAX_KEY_SIZE + #define MAX_KEY_SIZE 64 /* MAX PKCS Key length */ +#endif +#ifndef MAX_UNICODE_SZ + #define MAX_UNICODE_SZ 256 +#endif + +enum PBESTypes { + PBE_MD5_DES = 0, + PBE_SHA1_RC4_128 = 1, + PBE_SHA1_DES = 2, + PBE_SHA1_DES3 = 3, + PBE_AES256_CBC = 4, + PBE_AES128_CBC = 5, + + PBE_SHA1_RC4_128_SUM = 657, + PBE_SHA1_DES3_SUM = 659, + PBES2 = 13 /* algo ID */ +}; + +enum PKCSTypes { + PKCS5v2 = 6, /* PKCS #5 v2.0 */ + PKCS12v1 = 12, /* PKCS #12 */ + PKCS5 = 5, /* PKCS oid tag */ + PKCS8v0 = 0, /* default PKCS#8 version */ +}; + +#endif /* !NO_ASN || !NO_PWDBASED */ + +#endif /* WOLF_CRYPT_ASN_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/asn_public.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/asn_public.h index 8708708c7..393780036 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/asn_public.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/asn_public.h @@ -1,8 +1,8 @@ /* asn_public.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,34 +16,105 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/asn_public.h +*/ #ifndef WOLF_CRYPT_ASN_PUBLIC_H #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_ED448KEY_TYPE_DEFINED + typedef struct ed448_key ed448_key; + #define WC_ED448KEY_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 + +enum Ecc_Sum { + ECC_SECP112R1_OID = 182, + ECC_SECP112R2_OID = 183, + ECC_SECP128R1_OID = 204, + ECC_SECP128R2_OID = 205, + ECC_SECP160R1_OID = 184, + ECC_SECP160R2_OID = 206, + ECC_SECP160K1_OID = 185, + ECC_BRAINPOOLP160R1_OID = 98, + ECC_SECP192R1_OID = 520, + ECC_PRIME192V2_OID = 521, + ECC_PRIME192V3_OID = 522, + ECC_SECP192K1_OID = 207, + ECC_BRAINPOOLP192R1_OID = 100, + ECC_SECP224R1_OID = 209, + ECC_SECP224K1_OID = 208, + ECC_BRAINPOOLP224R1_OID = 102, + ECC_PRIME239V1_OID = 523, + ECC_PRIME239V2_OID = 524, + ECC_PRIME239V3_OID = 525, + 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_X448_OID = 362, + ECC_ED448_OID = 257, + ECC_SECP384R1_OID = 210, + ECC_BRAINPOOLP384R1_OID = 108, + ECC_BRAINPOOLP512R1_OID = 110, + ECC_SECP521R1_OID = 211, +}; + + /* Certificate file Type */ enum CertType { CERT_TYPE = 0, PRIVATEKEY_TYPE, DH_PARAM_TYPE, + DSA_PARAM_TYPE, CRL_TYPE, CA_TYPE, ECC_PRIVATEKEY_TYPE, - CERTREQ_TYPE + DSA_PRIVATEKEY_TYPE, + CERTREQ_TYPE, + DSA_TYPE, + ECC_TYPE, + RSA_TYPE, + PUBLICKEY_TYPE, + RSA_PUBLICKEY_TYPE, + ECC_PUBLICKEY_TYPE, + TRUSTED_PEER_TYPE, + EDDSA_PRIVATEKEY_TYPE, + ED25519_TYPE, + ED448_TYPE, + PKCS12_TYPE, + PKCS8_PRIVATEKEY_TYPE, + PKCS8_ENC_PRIVATEKEY_TYPE, + DETECT_CERT_TYPE, + DH_PRIVATEKEY_TYPE, }; @@ -54,12 +125,16 @@ enum Ctc_SigType { CTC_MD5wRSA = 648, CTC_SHAwRSA = 649, CTC_SHAwECDSA = 520, + CTC_SHA224wRSA = 658, + 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, + CTC_ED448 = 257 }; enum Ctc_Encoding { @@ -67,20 +142,121 @@ enum Ctc_Encoding { CTC_PRINTABLE = 0x13 /* printable */ }; - -#ifdef WOLFSSL_CERT_GEN - -#ifndef HAVE_ECC - typedef struct ecc_key ecc_key; +#ifndef WC_CTC_NAME_SIZE + #define WC_CTC_NAME_SIZE 64 +#endif +#ifndef WC_CTC_MAX_ALT_SIZE + #define WC_CTC_MAX_ALT_SIZE 16384 #endif enum Ctc_Misc { - CTC_NAME_SIZE = 64, - CTC_DATE_SIZE = 32, - CTC_MAX_ALT_SIZE = 16384, /* may be huge */ - CTC_SERIAL_SIZE = 8 + CTC_COUNTRY_SIZE = 2, + CTC_NAME_SIZE = WC_CTC_NAME_SIZE, + CTC_DATE_SIZE = 32, + CTC_MAX_ALT_SIZE = WC_CTC_MAX_ALT_SIZE, /* may be huge, default: 16384 */ + CTC_SERIAL_SIZE = 20, + CTC_GEN_SERIAL_SZ = 16, +#ifdef WOLFSSL_CERT_EXT + /* AKID could contains: hash + (Option) AuthCertIssuer,AuthCertSerialNum + * We support only hash */ + CTC_MAX_SKID_SIZE = 32, /* SHA256_DIGEST_SIZE */ + CTC_MAX_AKID_SIZE = 32, /* SHA256_DIGEST_SIZE */ + CTC_MAX_CERTPOL_SZ = 64, + CTC_MAX_CERTPOL_NB = 2 /* Max number of Certificate Policy */ +#endif /* WOLFSSL_CERT_EXT */ }; +/* DER buffer */ +typedef struct DerBuffer { + byte* buffer; + void* heap; + word32 length; + int type; /* enum CertType */ + int dynType; /* DYNAMIC_TYPE_* */ +} DerBuffer; + +typedef struct WOLFSSL_ASN1_TIME { + unsigned char data[CTC_DATE_SIZE]; /* date bytes */ + int length; + int type; +} WOLFSSL_ASN1_TIME; + +enum { + IV_SZ = 32, /* max iv sz */ + NAME_SZ = 80, /* max one line */ + + PEM_PASS_READ = 0, + PEM_PASS_WRITE = 1, +}; + + +typedef int (pem_password_cb)(char* passwd, int sz, int rw, void* userdata); + +typedef struct EncryptedInfo { + pem_password_cb* passwd_cb; + void* passwd_userdata; + + long consumed; /* tracks PEM bytes consumed */ + + int cipherType; + word32 keySz; + word32 ivSz; /* salt or encrypted IV size */ + + char name[NAME_SZ]; /* cipher name, such as "DES-CBC" */ + byte iv[IV_SZ]; /* salt or encrypted IV */ + + word16 set:1; /* if encryption set */ +} EncryptedInfo; + + +#define WOLFSSL_ASN1_INTEGER_MAX 20 +typedef struct WOLFSSL_ASN1_INTEGER { + /* size can be increased set at 20 for tag, length then to hold at least 16 + * byte type */ + unsigned char intData[WOLFSSL_ASN1_INTEGER_MAX]; + /* ASN_INTEGER | LENGTH | hex of number */ + unsigned char negative; /* negative number flag */ + + unsigned char* data; + unsigned int dataMax; /* max size of data buffer */ + unsigned int isDynamic:1; /* flag for if data pointer dynamic (1 is yes 0 is no) */ + + int length; + int type; +} WOLFSSL_ASN1_INTEGER; + + +#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT) +#ifdef WOLFSSL_EKU_OID + #ifndef CTC_MAX_EKU_NB + #define CTC_MAX_EKU_NB 1 + #endif + #ifndef CTC_MAX_EKU_OID_SZ + #define CTC_MAX_EKU_OID_SZ 30 + #endif +#else + #undef CTC_MAX_EKU_OID_SZ + #define CTC_MAX_EKU_OID_SZ 0 +#endif +#endif /* WOLFSSL_CERT_GEN || WOLFSSL_CERT_EXT */ + +#ifdef WOLFSSL_CERT_GEN + +#ifdef WOLFSSL_MULTI_ATTRIB +#ifndef CTC_MAX_ATTRIB + #define CTC_MAX_ATTRIB 4 +#endif + +/* ASN Encoded Name field */ +typedef struct NameAttrib { + int sz; /* actual string value length */ + int id; /* id of name */ + int type; /* enc of name */ + char value[CTC_NAME_SIZE]; /* name */ +} NameAttrib; +#endif /* WOLFSSL_MULTI_ATTRIB */ + + typedef struct CertName { char country[CTC_NAME_SIZE]; char countryEnc; @@ -96,7 +272,20 @@ typedef struct CertName { char unitEnc; char commonName[CTC_NAME_SIZE]; char commonNameEnc; + char serialDev[CTC_NAME_SIZE]; + char serialDevEnc; +#ifdef WOLFSSL_CERT_EXT + char busCat[CTC_NAME_SIZE]; + char busCatEnc; + char joiC[CTC_NAME_SIZE]; + char joiCEnc; + char joiSt[CTC_NAME_SIZE]; + char joiStEnc; +#endif char email[CTC_NAME_SIZE]; /* !!!! email has to be last !!!! */ +#ifdef WOLFSSL_MULTI_ATTRIB + NameAttrib name[CTC_MAX_ATTRIB]; +#endif } CertName; @@ -104,6 +293,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 */ @@ -121,18 +311,34 @@ typedef struct Cert { byte afterDate[CTC_DATE_SIZE]; /* after date copy */ int afterDateSz; /* size of copy */ #endif +#ifdef WOLFSSL_CERT_EXT + byte skid[CTC_MAX_SKID_SIZE]; /* Subject Key Identifier */ + int skidSz; /* SKID size in bytes */ + byte akid[CTC_MAX_AKID_SIZE]; /* Authority Key Identifier */ + int akidSz; /* AKID size in bytes */ + word16 keyUsage; /* Key Usage */ + byte extKeyUsage; /* Extended Key Usage */ +#ifdef WOLFSSL_EKU_OID + /* Extended Key Usage OIDs */ + byte extKeyUsageOID[CTC_MAX_EKU_NB][CTC_MAX_EKU_OID_SZ]; + byte extKeyUsageOIDSz[CTC_MAX_EKU_NB]; +#endif + char certPolicies[CTC_MAX_CERTPOL_NB][CTC_MAX_CERTPOL_SZ]; + word16 certPoliciesNb; /* Number of Cert Policy */ + byte issRaw[sizeof(CertName)]; /* raw issuer info */ + byte sbjRaw[sizeof(CertName)]; /* raw subject info */ +#endif #ifdef WOLFSSL_CERT_REQ char challengePw[CTC_NAME_SIZE]; + int challengePwPrintableString; /* encode as PrintableString */ #endif + void* decodedCert; /* internal DecodedCert allocated from heap */ + byte* der; /* Pointer to buffer of current DecodedCert cache */ + void* heap; /* heap hint */ } Cert; -#endif /* WOLFSSL_CERT_GEN */ -#ifdef WOLFSSL_CERT_GEN - - - -/* Initialize and Set Certficate defaults: +/* Initialize and Set Certificate defaults: version = 3 (0x2) serial = 0 (Will be randomly generated) sigType = SHA_WITH_RSA @@ -143,55 +349,262 @@ typedef struct Cert { isCA = 0 (false) keyType = RSA_KEY (default) */ -WOLFSSL_API void wc_InitCert(Cert*); -WOLFSSL_API int wc_MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, - ecc_key*, RNG*); +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*); #ifdef WOLFSSL_CERT_REQ - WOLFSSL_API int wc_MakeCertReq(Cert*, byte* derBuffer, word32 derSz, RsaKey*, - ecc_key*); + 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(int requestSz, int sigType, byte* derBuffer, - word32 derSz, RsaKey*, ecc_key*, RNG*); -WOLFSSL_API int wc_MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, - RNG*); -WOLFSSL_API int wc_SetIssuer(Cert*, const char*); -WOLFSSL_API int wc_SetSubject(Cert*, const char*); +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*); +WOLFSSL_API int wc_MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, + WC_RNG*); +WOLFSSL_API int wc_SetIssuer(Cert*, const char*); +WOLFSSL_API int wc_SetSubject(Cert*, const char*); #ifdef WOLFSSL_ALT_NAMES - WOLFSSL_API int wc_SetAltNames(Cert*, const char*); + WOLFSSL_API int wc_SetAltNames(Cert*, const char*); #endif -WOLFSSL_API int wc_SetIssuerBuffer(Cert*, const byte*, int); -WOLFSSL_API int wc_SetSubjectBuffer(Cert*, const byte*, int); -WOLFSSL_API int wc_SetAltNamesBuffer(Cert*, const byte*, int); -WOLFSSL_API int wc_SetDatesBuffer(Cert*, const byte*, int); + +#ifdef WOLFSSL_CERT_GEN_CACHE +WOLFSSL_API void wc_SetCert_Free(Cert* cert); +#endif + +WOLFSSL_API int wc_SetIssuerBuffer(Cert*, const byte*, int); +WOLFSSL_API int wc_SetSubjectBuffer(Cert*, const byte*, int); +WOLFSSL_API int wc_SetAltNamesBuffer(Cert*, const byte*, int); +WOLFSSL_API int wc_SetDatesBuffer(Cert*, const byte*, int); + +#ifndef NO_ASN_TIME +WOLFSSL_API int wc_GetCertDates(Cert* cert, struct tm* before, + struct tm* after); +#endif + +#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); +WOLFSSL_API int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert); +WOLFSSL_API int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz); +WOLFSSL_API int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz); + +#ifdef HAVE_NTRU +WOLFSSL_API int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey, + word16 ntruKeySz); +#endif + +/* Set the KeyUsage. + * Value is a string separated tokens with ','. Accepted tokens are : + * digitalSignature,nonRepudiation,contentCommitment,keyCertSign,cRLSign, + * dataEncipherment,keyAgreement,keyEncipherment,encipherOnly and decipherOnly. + * + * nonRepudiation and contentCommitment are for the same usage. + */ +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); + + +#ifdef WOLFSSL_EKU_OID +/* Set ExtendedKeyUsage with unique OID + * oid is expected to be in byte representation + */ +WOLFSSL_API int wc_SetExtKeyUsageOID(Cert *cert, const char *oid, word32 sz, + byte idx, void* heap); +#endif /* WOLFSSL_EKU_OID */ +#endif /* WOLFSSL_CERT_EXT */ #ifdef HAVE_NTRU - WOLFSSL_API int wc_MakeNtruCert(Cert*, byte* derBuffer, word32 derSz, - const byte* ntruKey, word16 keySz, RNG*); + WOLFSSL_API int wc_MakeNtruCert(Cert*, byte* derBuffer, word32 derSz, + const byte* ntruKey, word16 keySz, + WC_RNG*); #endif #endif /* WOLFSSL_CERT_GEN */ +WOLFSSL_API int wc_GetDateInfo(const byte* certDate, int certDateSz, + const byte** date, byte* format, int* length); +#ifndef NO_ASN_TIME +WOLFSSL_API int wc_GetDateAsCalendarTime(const byte* date, int length, + byte format, struct tm* time); +#endif -#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + + WOLFSSL_API int wc_PemGetHeaderFooter(int type, const char** header, + const char** footer); + +#endif + +WOLFSSL_API int wc_AllocDer(DerBuffer** pDer, word32 length, int type, void* heap); +WOLFSSL_API void wc_FreeDer(DerBuffer** pDer); + +#ifdef WOLFSSL_PEM_TO_DER + WOLFSSL_API int wc_PemToDer(const unsigned char* buff, long longSz, int type, + DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey); + + WOLFSSL_API int wc_KeyPemToDer(const unsigned char*, int, + unsigned char*, int, const char*); + WOLFSSL_API int wc_CertPemToDer(const unsigned char*, int, + unsigned char*, int, int); +#endif /* WOLFSSL_PEM_TO_DER */ + +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER) + #ifndef NO_FILESYSTEM + WOLFSSL_API int wc_PemPubKeyToDer(const char* fileName, + unsigned char* derBuf, int derSz); + #endif + + WOLFSSL_API int wc_PubKeyPemToDer(const unsigned char*, int, + unsigned char*, int); +#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */ + +#ifdef WOLFSSL_CERT_GEN + #ifndef NO_FILESYSTEM + WOLFSSL_API int wc_PemCertToDer(const char* fileName, + unsigned char* derBuf, int derSz); + #endif +#endif /* WOLFSSL_CERT_GEN */ + +#ifdef WOLFSSL_DER_TO_PEM WOLFSSL_API int wc_DerToPem(const byte* der, word32 derSz, byte* output, - word32 outputSz, int type); + word32 outputSz, int type); + WOLFSSL_API int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, + word32 outputSz, byte *cipherIno, int type); +#endif + +#ifndef NO_RSA + #if !defined(HAVE_USER_RSA) + WOLFSSL_API int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, + word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz); + #endif + WOLFSSL_API int wc_RsaPublicKeyDerSize(RsaKey* key, int with_header); #endif #ifdef HAVE_ECC /* private key helpers */ - WOLFSSL_API int wc_EccPrivateKeyDecode(const byte* input,word32* inOutIdx, - ecc_key*,word32); + 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); + WOLFSSL_API int wc_EccPublicKeyDerSize(ecc_key*, 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_Ed25519PublicKeyToDer(ed25519_key*, byte* output, + word32 inLen, int with_AlgCurve); + #endif +#endif + +#ifdef HAVE_ED448 + /* private key helpers */ + WOLFSSL_API int wc_Ed448PrivateKeyDecode(const byte*, word32*, + ed448_key*, word32); + WOLFSSL_API int wc_Ed448KeyToDer(ed448_key* key, byte* output, + word32 inLen); + WOLFSSL_API int wc_Ed448PrivateKeyToDer(ed448_key* key, byte* output, + word32 inLen); + + /* public key helper */ + WOLFSSL_API int wc_Ed448PublicKeyDecode(const byte*, word32*, + ed448_key*, word32); + #if (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) + WOLFSSL_API int wc_Ed448PublicKeyToDer(ed448_key*, byte* output, + word32 inLen, int with_AlgCurve); + #endif #endif /* DER encode signature */ -WOLFSSL_API word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz, - int hashOID); +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); + +#ifndef NO_ASN_TIME +/* Time */ +/* Returns seconds (Epoch/UTC) + * timePtr: is "time_t", which is typically "long" + * Example: + long lTime; + rc = wc_GetTime(&lTime, (word32)sizeof(lTime)); +*/ +WOLFSSL_API int wc_GetTime(void* timePtr, word32 timeSize); +#endif + +#ifdef WOLFSSL_ENCRYPTED_KEYS + WOLFSSL_API int wc_EncryptedInfoGet(EncryptedInfo* info, + const char* cipherInfo); +#endif + + +#ifdef WOLFSSL_CERT_PIV + +typedef struct _wc_CertPIV { + const byte* cert; + word32 certSz; + const byte* certErrDet; + word32 certErrDetSz; + const byte* nonce; /* Identiv Only */ + word32 nonceSz; /* Identiv Only */ + const byte* signedNonce; /* Identiv Only */ + word32 signedNonceSz; /* Identiv Only */ + + /* flags */ + word16 compression:2; + word16 isX509:1; + word16 isIdentiv:1; +} wc_CertPIV; + +WOLFSSL_API int wc_ParseCertPIV(wc_CertPIV* cert, const byte* buf, word32 totalSz); +#endif /* WOLFSSL_CERT_PIV */ + + #ifdef __cplusplus } /* extern "C" */ #endif #endif /* WOLF_CRYPT_ASN_PUBLIC_H */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/async.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/async.h new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/blake2-impl.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/blake2-impl.h index e1882f2a1..cb4df286c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/blake2-impl.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/blake2-impl.h @@ -12,9 +12,9 @@ */ /* blake2-impl.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -28,16 +28,17 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLFCRYPT_BLAKE2_IMPL_H #define WOLFCRYPT_BLAKE2_IMPL_H #include -static inline word32 load32( const void *src ) +static WC_INLINE word32 load32( const void *src ) { #if defined(LITTLE_ENDIAN_ORDER) return *( word32 * )( src ); @@ -51,7 +52,7 @@ static inline word32 load32( const void *src ) #endif } -static inline word64 load64( const void *src ) +static WC_INLINE word64 load64( const void *src ) { #if defined(LITTLE_ENDIAN_ORDER) return *( word64 * )( src ); @@ -69,7 +70,7 @@ static inline word64 load64( const void *src ) #endif } -static inline void store32( void *dst, word32 w ) +static WC_INLINE void store32( void *dst, word32 w ) { #if defined(LITTLE_ENDIAN_ORDER) *( word32 * )( dst ) = w; @@ -82,7 +83,7 @@ static inline void store32( void *dst, word32 w ) #endif } -static inline void store64( void *dst, word64 w ) +static WC_INLINE void store64( void *dst, word64 w ) { #if defined(LITTLE_ENDIAN_ORDER) *( word64 * )( dst ) = w; @@ -99,7 +100,7 @@ static inline void store64( void *dst, word64 w ) #endif } -static inline word64 load48( const void *src ) +static WC_INLINE word64 load48( const void *src ) { const byte *p = ( const byte * )src; word64 w = *p++; @@ -111,7 +112,7 @@ static inline word64 load48( const void *src ) return w; } -static inline void store48( void *dst, word64 w ) +static WC_INLINE void store48( void *dst, word64 w ) { byte *p = ( byte * )dst; *p++ = ( byte )w; w >>= 8; @@ -122,28 +123,28 @@ static inline void store48( void *dst, word64 w ) *p++ = ( byte )w; } -static inline word32 rotl32( const word32 w, const unsigned c ) +static WC_INLINE word32 rotl32( const word32 w, const unsigned c ) { return ( w << c ) | ( w >> ( 32 - c ) ); } -static inline word64 rotl64( const word64 w, const unsigned c ) +static WC_INLINE word64 rotl64( const word64 w, const unsigned c ) { return ( w << c ) | ( w >> ( 64 - c ) ); } -static inline word32 rotr32( const word32 w, const unsigned c ) +static WC_INLINE word32 rotr32( const word32 w, const unsigned c ) { return ( w >> c ) | ( w << ( 32 - c ) ); } -static inline word64 rotr64( const word64 w, const unsigned c ) +static WC_INLINE word64 rotr64( const word64 w, const unsigned c ) { return ( w >> c ) | ( w << ( 64 - c ) ); } /* prevents compiler optimizing out memset() */ -static inline void secure_zero_memory( void *v, word64 n ) +static WC_INLINE void secure_zero_memory( void *v, word64 n ) { volatile byte *p = ( volatile byte * )v; diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/blake2-int.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/blake2-int.h index 05fd0274a..6f5610dc7 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/blake2-int.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/blake2-int.h @@ -12,9 +12,9 @@ */ /* blake2-int.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -28,11 +28,12 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLFCRYPT_BLAKE2_INT_H #define WOLFCRYPT_BLAKE2_INT_H @@ -41,7 +42,7 @@ #if defined(_MSC_VER) #define ALIGN(x) __declspec(align(x)) -#elif defined(__GNUC__) +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__) #define ALIGN(x) __attribute__((aligned(x))) #else #define ALIGN(x) @@ -86,13 +87,13 @@ byte personal[BLAKE2S_PERSONALBYTES]; /* 32 */ } blake2s_param; - ALIGN( 64 ) typedef struct __blake2s_state + ALIGN( 32 ) typedef struct __blake2s_state { word32 h[8]; word32 t[2]; word32 f[2]; byte buf[2 * BLAKE2S_BLOCKBYTES]; - word64 buflen; + word32 buflen; byte last_node; } blake2s_state ; @@ -126,7 +127,7 @@ blake2s_state S[8][1]; blake2s_state R[1]; byte buf[8 * BLAKE2S_BLOCKBYTES]; - word64 buflen; + word32 buflen; } blake2sp_state; typedef struct __blake2bp_state @@ -142,7 +143,7 @@ int blake2s_init( blake2s_state *S, const byte outlen ); int blake2s_init_key( blake2s_state *S, const byte outlen, const void *key, const byte keylen ); int blake2s_init_param( blake2s_state *S, const blake2s_param *P ); - int blake2s_update( blake2s_state *S, const byte *in, word64 inlen ); + int blake2s_update( blake2s_state *S, const byte *in, word32 inlen ); int blake2s_final( blake2s_state *S, byte *out, byte outlen ); int blake2b_init( blake2b_state *S, const byte outlen ); @@ -153,7 +154,7 @@ int blake2sp_init( blake2sp_state *S, const byte outlen ); int blake2sp_init_key( blake2sp_state *S, const byte outlen, const void *key, const byte keylen ); - int blake2sp_update( blake2sp_state *S, const byte *in, word64 inlen ); + int blake2sp_update( blake2sp_state *S, const byte *in, word32 inlen ); int blake2sp_final( blake2sp_state *S, byte *out, byte outlen ); int blake2bp_init( blake2bp_state *S, const byte outlen ); @@ -162,13 +163,13 @@ int blake2bp_final( blake2bp_state *S, byte *out, byte outlen ); /* Simple API */ - int blake2s( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen ); + int blake2s( byte *out, const void *in, const void *key, const byte outlen, const word32 inlen, byte keylen ); int blake2b( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen ); - int blake2sp( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen ); + int blake2sp( byte *out, const void *in, const void *key, const byte outlen, const word32 inlen, byte keylen ); int blake2bp( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen ); - static inline int blake2( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen ) + static WC_INLINE int blake2( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen ) { return blake2b( out, in, key, outlen, inlen, keylen ); } diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/blake2.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/blake2.h index 51866639a..bc80d7166 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/blake2.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/blake2.h @@ -1,8 +1,8 @@ /* blake2.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -15,18 +15,20 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * a with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ - +/*! + \file wolfssl/wolfcrypt/blake2.h +*/ #ifndef WOLF_CRYPT_BLAKE2_H #define WOLF_CRYPT_BLAKE2_H #include -#ifdef HAVE_BLAKE2 +#if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) #include @@ -44,28 +46,51 @@ /* in bytes, variable digest size up to 512 bits (64 bytes) */ enum { - BLAKE2B_ID = 7, /* hash type unique */ - BLAKE2B_256 = 32 /* 256 bit type, SSL default */ +#ifdef HAVE_BLAKE2B + BLAKE2B_ID = WC_HASH_TYPE_BLAKE2B, + BLAKE2B_256 = 32, /* 256 bit type, SSL default */ +#endif +#ifdef HAVE_BLAKE2S + BLAKE2S_ID = WC_HASH_TYPE_BLAKE2S, + BLAKE2S_256 = 32 /* 256 bit type */ +#endif }; +#ifdef HAVE_BLAKE2B /* BLAKE2b digest */ typedef struct Blake2b { blake2b_state S[1]; /* our state */ word32 digestSz; /* digest size used on init */ } Blake2b; +#endif + +#ifdef HAVE_BLAKE2S +/* BLAKE2s digest */ +typedef struct Blake2s { + blake2s_state S[1]; /* our state */ + word32 digestSz; /* digest size used on init */ +} Blake2s; +#endif +#ifdef HAVE_BLAKE2B WOLFSSL_API int wc_InitBlake2b(Blake2b*, word32); WOLFSSL_API int wc_Blake2bUpdate(Blake2b*, const byte*, word32); WOLFSSL_API int wc_Blake2bFinal(Blake2b*, byte*, word32); +#endif +#ifdef HAVE_BLAKE2S +WOLFSSL_API int wc_InitBlake2s(Blake2s*, word32); +WOLFSSL_API int wc_Blake2sUpdate(Blake2s*, const byte*, word32); +WOLFSSL_API int wc_Blake2sFinal(Blake2s*, byte*, word32); +#endif #ifdef __cplusplus } #endif -#endif /* HAVE_BLAKE2 */ +#endif /* HAVE_BLAKE2 || HAVE_BLAKE2S */ #endif /* WOLF_CRYPT_BLAKE2_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/camellia.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/camellia.h index 4b7b92af3..4b86e6c13 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/camellia.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/camellia.h @@ -27,9 +27,9 @@ /* camellia.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -43,9 +43,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/camellia.h +*/ + + #ifndef WOLF_CRYPT_CAMELLIA_H #define WOLF_CRYPT_CAMELLIA_H @@ -77,13 +82,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/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/chacha.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/chacha.h index da938c973..72fc58280 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/chacha.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/chacha.h @@ -1,8 +1,8 @@ /* chacha.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/chacha.h +*/ + + #ifndef WOLF_CRYPT_CHACHA_H #define WOLF_CRYPT_CHACHA_H @@ -30,12 +35,33 @@ extern "C" { #endif +/* Size of the IV */ +#define CHACHA_IV_WORDS 3 +#define CHACHA_IV_BYTES (CHACHA_IV_WORDS * sizeof(word32)) + +/* Size of ChaCha chunks */ +#define CHACHA_CHUNK_WORDS 16 +#define CHACHA_CHUNK_BYTES (CHACHA_CHUNK_WORDS * sizeof(word32)) + +#ifdef WOLFSSL_X86_64_BUILD +#if defined(USE_INTEL_SPEEDUP) && !defined(NO_CHACHA_ASM) + #define USE_INTEL_CHACHA_SPEEDUP + #define HAVE_INTEL_AVX1 +#endif +#endif + enum { - CHACHA_ENC_TYPE = 7 /* cipher unique type */ + CHACHA_ENC_TYPE = WC_CIPHER_CHACHA, /* cipher unique type */ + CHACHA_MAX_KEY_SZ = 32, }; typedef struct ChaCha { - word32 X[16]; /* state of cipher */ + word32 X[CHACHA_CHUNK_WORDS]; /* state of cipher */ + word32 left; /* number of bytes leftover */ +#ifdef HAVE_INTEL_AVX1 + /* vpshufd reads 16 bytes but we only use bottom 4. */ + byte extra[12]; +#endif } ChaCha; /** diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/chacha20_poly1305.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/chacha20_poly1305.h index e65842bfa..7d2b1aa2a 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/chacha20_poly1305.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/chacha20_poly1305.h @@ -1,8 +1,8 @@ /* chacha20_poly1305.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,18 +16,25 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* This implementation of the ChaCha20-Poly1305 AEAD is based on "ChaCha20 * and Poly1305 for IETF protocols" (draft-irtf-cfrg-chacha20-poly1305-10): * https://tools.ietf.org/html/draft-irtf-cfrg-chacha20-poly1305-10 */ +/*! + \file wolfssl/wolfcrypt/chacha20_poly1305.h +*/ + #ifndef WOLF_CRYPT_CHACHA20_POLY1305_H #define WOLF_CRYPT_CHACHA20_POLY1305_H #include +#include +#include #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) @@ -40,18 +47,40 @@ #define CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE 16 enum { - CHACHA20_POLY_1305_ENC_TYPE = 8 /* cipher unique type */ + CHACHA20_POLY_1305_ENC_TYPE = 8, /* cipher unique type */ + + /* AEAD Cipher Direction */ + CHACHA20_POLY1305_AEAD_DECRYPT = 0, + CHACHA20_POLY1305_AEAD_ENCRYPT = 1, + + /* AEAD State */ + CHACHA20_POLY1305_STATE_INIT = 0, + CHACHA20_POLY1305_STATE_READY = 1, + CHACHA20_POLY1305_STATE_AAD = 2, + CHACHA20_POLY1305_STATE_DATA = 3, }; - /* - * The IV for this implementation is 96 bits to give the most flexibility. - * - * Some protocols may have unique per-invocation inputs that are not - * 96-bit in length. For example, IPsec may specify a 64-bit nonce. In - * such a case, it is up to the protocol document to define how to - * transform the protocol nonce into a 96-bit nonce, for example by - * concatenating a constant value. - */ +typedef struct ChaChaPoly_Aead { + ChaCha chacha; + Poly1305 poly; + + word32 aadLen; + word32 dataLen; + + byte state; + byte isEncrypt:1; +} ChaChaPoly_Aead; + + +/* + * The IV for this implementation is 96 bits to give the most flexibility. + * + * Some protocols may have unique per-invocation inputs that are not + * 96-bit in length. For example, IPsec may specify a 64-bit nonce. In + * such a case, it is up to the protocol document to define how to + * transform the protocol nonce into a 96-bit nonce, for example by + * concatenating a constant value. + */ WOLFSSL_API int wc_ChaCha20Poly1305_Encrypt( @@ -71,6 +100,27 @@ int wc_ChaCha20Poly1305_Decrypt( const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE], byte* outPlaintext); +WOLFSSL_API +int wc_ChaCha20Poly1305_CheckTag( + const byte authTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE], + const byte authTagChk[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]); + + + +/* Implementation of AEAD, which includes support for adding + data, then final calculation of authentication tag */ +WOLFSSL_API int wc_ChaCha20Poly1305_Init(ChaChaPoly_Aead* aead, + const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], + const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], + int isEncrypt); +WOLFSSL_API int wc_ChaCha20Poly1305_UpdateAad(ChaChaPoly_Aead* aead, + const byte* inAAD, word32 inAADLen); +WOLFSSL_API int wc_ChaCha20Poly1305_UpdateData(ChaChaPoly_Aead* aead, + const byte* inData, byte* outData, word32 dataLen); +WOLFSSL_API int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead, + byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]); + + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/cmac.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/cmac.h new file mode 100644 index 000000000..80f13ce97 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/cmac.h @@ -0,0 +1,97 @@ +/* cmac.h + * + * Copyright (C) 2006-2020 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_CMAC_H +#define WOLF_CRYPT_CMAC_H + +#include +#include + +#if !defined(NO_AES) && defined(WOLFSSL_CMAC) + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#ifdef __cplusplus + extern "C" { +#endif + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifndef WC_CMAC_TYPE_DEFINED + typedef struct Cmac Cmac; + #define WC_CMAC_TYPE_DEFINED +#endif +struct Cmac { + Aes aes; + byte buffer[AES_BLOCK_SIZE]; /* partially stored block */ + byte digest[AES_BLOCK_SIZE]; /* running digest */ + byte k1[AES_BLOCK_SIZE]; + byte k2[AES_BLOCK_SIZE]; + word32 bufferSz; + word32 totalSz; +}; + + + +typedef enum CmacType { + WC_CMAC_AES = 1 +} CmacType; + +#define WC_CMAC_TAG_MAX_SZ AES_BLOCK_SIZE +#define WC_CMAC_TAG_MIN_SZ (AES_BLOCK_SIZE/4) + +#endif /* HAVE_FIPS */ + +WOLFSSL_API +int wc_InitCmac(Cmac* cmac, + const byte* key, word32 keySz, + int type, void* unused); +WOLFSSL_API +int wc_CmacUpdate(Cmac* cmac, + const byte* in, word32 inSz); +WOLFSSL_API +int wc_CmacFinal(Cmac* cmac, + byte* out, word32* outSz); + +WOLFSSL_API +int wc_AesCmacGenerate(byte* out, word32* outSz, + const byte* in, word32 inSz, + const byte* key, word32 keySz); + +WOLFSSL_API +int wc_AesCmacVerify(const byte* check, word32 checkSz, + const byte* in, word32 inSz, + const byte* key, word32 keySz); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* NO_AES && WOLFSSL_CMAC */ +#endif /* WOLF_CRYPT_CMAC_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/coding.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/coding.h index 296bc3ca7..88b1caf94 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/coding.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/coding.h @@ -1,8 +1,8 @@ /* coding.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,12 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/coding.h +*/ #ifndef WOLF_CRYPT_CODING_H #define WOLF_CRYPT_CODING_H @@ -33,7 +36,8 @@ WOLFSSL_API int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen); -#if defined(OPENSSL_EXTRA) || defined(SESSION_CERTS) || defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || defined(HAVE_WEBSERVER) +#if defined(OPENSSL_EXTRA) || defined(SESSION_CERTS) || defined(WOLFSSL_KEY_GEN) \ + || defined(WOLFSSL_CERT_GEN) || defined(HAVE_WEBSERVER) || !defined(NO_DSA) #ifndef WOLFSSL_BASE64_ENCODE #define WOLFSSL_BASE64_ENCODE #endif @@ -41,6 +45,12 @@ WOLFSSL_API int Base64_Decode(const byte* in, word32 inLen, byte* out, #ifdef WOLFSSL_BASE64_ENCODE + enum Escaped { + WC_STD_ENC = 0, /* normal \n line ending encoding */ + WC_ESC_NL_ENC, /* use escape sequence encoding */ + WC_NO_NL_ENC /* no encoding at all */ + }; /* Encoding types */ + /* encode isn't */ WOLFSSL_API int Base64_Encode(const byte* in, word32 inLen, byte* out, @@ -48,11 +58,25 @@ WOLFSSL_API int Base64_Decode(const byte* in, word32 inLen, byte* out, WOLFSSL_API int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen); + WOLFSSL_API + int Base64_Encode_NoNl(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(OPENSSL_EXTRA_X509_SMALL) || \ + defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) || \ + defined(HAVE_ECC_CDH) || defined(HAVE_SELFTEST) || \ + defined(WOLFSSL_ENCRYPTED_KEYS) + #ifndef WOLFSSL_BASE16 + #define WOLFSSL_BASE16 + #endif +#endif + +#ifdef WOLFSSL_BASE16 WOLFSSL_API int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen); + WOLFSSL_API + int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen); #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/compress.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/compress.h index dc012b865..f324a8350 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/compress.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/compress.h @@ -1,8 +1,8 @@ /* compress.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/compress.h +*/ + + #ifndef WOLF_CRYPT_COMPRESS_H #define WOLF_CRYPT_COMPRESS_H @@ -33,10 +38,15 @@ #define COMPRESS_FIXED 1 +#define LIBZ_WINBITS_GZIP 16 + WOLFSSL_API int wc_Compress(byte*, word32, const byte*, word32, word32); +WOLFSSL_API int wc_Compress_ex(byte* out, word32 outSz, const byte* in, + word32 inSz, word32 flags, word32 windowBits); WOLFSSL_API int wc_DeCompress(byte*, word32, const byte*, word32); - +WOLFSSL_API int wc_DeCompress_ex(byte* out, word32 outSz, const byte* in, + word32 inSz, int windowBits); #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/cpuid.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/cpuid.h new file mode 100644 index 000000000..3c3d1c294 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/cpuid.h @@ -0,0 +1,62 @@ +/* cpuid.h + * + * Copyright (C) 2006-2020 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/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/cryptocb.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/cryptocb.h new file mode 100644 index 000000000..eb42d2675 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/cryptocb.h @@ -0,0 +1,299 @@ +/* cryptocb.h + * + * Copyright (C) 2006-2020 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 3 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, see . + */ + +#ifndef _WOLF_CRYPTO_CB_H_ +#define _WOLF_CRYPTO_CB_H_ + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* Defines the Crypto Callback interface version, for compatibility */ +/* Increment this when Crypto Callback interface changes are made */ +#define CRYPTO_CB_VER 2 + + +#ifdef WOLF_CRYPTO_CB + +#ifndef NO_RSA + #include +#endif +#ifdef HAVE_ECC + #include +#endif +#ifndef NO_AES + #include +#endif +#ifndef NO_SHA + #include +#endif +#ifndef NO_SHA256 + #include +#endif +#ifndef NO_HMAC + #include +#endif +#ifndef WC_NO_RNG + #include +#endif +#ifndef NO_DES3 + #include +#endif + + +/* Crypto Information Structure for callbacks */ +typedef struct wc_CryptoInfo { + int algo_type; /* enum wc_AlgoType */ +#if !defined(NO_RSA) || defined(HAVE_ECC) + struct { + int type; /* enum wc_PkType */ + union { + #ifndef NO_RSA + struct { + const byte* in; + word32 inLen; + byte* out; + word32* outLen; + int type; + RsaKey* key; + WC_RNG* rng; + } rsa; + #ifdef WOLFSSL_KEY_GEN + struct { + RsaKey* key; + int size; + long e; + WC_RNG* rng; + } rsakg; + #endif + #endif + #ifdef HAVE_ECC + struct { + WC_RNG* rng; + int size; + ecc_key* key; + int curveId; + } eckg; + struct { + ecc_key* private_key; + ecc_key* public_key; + byte* out; + word32* outlen; + } ecdh; + struct { + const byte* in; + word32 inlen; + byte* out; + word32* outlen; + WC_RNG* rng; + ecc_key* key; + } eccsign; + struct { + const byte* sig; + word32 siglen; + const byte* hash; + word32 hashlen; + int* res; + ecc_key* key; + } eccverify; + #endif + }; + } pk; +#endif /* !NO_RSA || HAVE_ECC */ +#if !defined(NO_AES) || !defined(NO_DES3) + struct { + int type; /* enum wc_CipherType */ + int enc; + union { + #ifdef HAVE_AESGCM + struct { + Aes* aes; + byte* out; + const byte* in; + word32 sz; + const byte* iv; + word32 ivSz; + byte* authTag; + word32 authTagSz; + const byte* authIn; + word32 authInSz; + } aesgcm_enc; + struct { + Aes* aes; + byte* out; + const byte* in; + word32 sz; + const byte* iv; + word32 ivSz; + const byte* authTag; + word32 authTagSz; + const byte* authIn; + word32 authInSz; + } aesgcm_dec; + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AES_CBC + struct { + Aes* aes; + byte* out; + const byte* in; + word32 sz; + } aescbc; + #endif /* HAVE_AES_CBC */ + #ifndef NO_DES3 + struct { + Des3* des; + byte* out; + const byte* in; + word32 sz; + } des3; + #endif + }; + } cipher; +#endif /* !NO_AES || !NO_DES3 */ +#if !defined(NO_SHA) || !defined(NO_SHA256) + struct { + int type; /* enum wc_HashType */ + const byte* in; + word32 inSz; + byte* digest; + union { + #ifndef NO_SHA + wc_Sha* sha1; + #endif + #ifndef NO_SHA256 + wc_Sha256* sha256; + #endif + }; + } hash; +#endif /* !NO_SHA || !NO_SHA256 */ +#ifndef NO_HMAC + struct { + int macType; /* enum wc_HashType */ + const byte* in; + word32 inSz; + byte* digest; + Hmac* hmac; + } hmac; +#endif +#ifndef WC_NO_RNG + struct { + WC_RNG* rng; + byte* out; + word32 sz; + } rng; + struct { + OS_Seed* os; + byte* seed; + word32 sz; + } seed; +#endif +} wc_CryptoInfo; + + +typedef int (*CryptoDevCallbackFunc)(int devId, wc_CryptoInfo* info, void* ctx); + +WOLFSSL_LOCAL void wc_CryptoCb_Init(void); + +WOLFSSL_API int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx); +WOLFSSL_API void wc_CryptoCb_UnRegisterDevice(int devId); + +/* old function names */ +#define wc_CryptoDev_RegisterDevice wc_CryptoCb_RegisterDevice +#define wc_CryptoDev_UnRegisterDevice wc_CryptoCb_UnRegisterDevice + + +#ifndef NO_RSA +WOLFSSL_LOCAL int wc_CryptoCb_Rsa(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng); + +#ifdef WOLFSSL_KEY_GEN +WOLFSSL_LOCAL int wc_CryptoCb_MakeRsaKey(RsaKey* key, int size, long e, + WC_RNG* rng); +#endif /* WOLFSSL_KEY_GEN */ +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +WOLFSSL_LOCAL int wc_CryptoCb_MakeEccKey(WC_RNG* rng, int keySize, + ecc_key* key, int curveId); + +WOLFSSL_LOCAL int wc_CryptoCb_Ecdh(ecc_key* private_key, ecc_key* public_key, + byte* out, word32* outlen); + +WOLFSSL_LOCAL int wc_CryptoCb_EccSign(const byte* in, word32 inlen, byte* out, + word32 *outlen, WC_RNG* rng, ecc_key* key); + +WOLFSSL_LOCAL int wc_CryptoCb_EccVerify(const byte* sig, word32 siglen, + const byte* hash, word32 hashlen, int* res, ecc_key* key); +#endif /* HAVE_ECC */ + +#ifndef NO_AES +#ifdef HAVE_AESGCM +WOLFSSL_LOCAL int wc_CryptoCb_AesGcmEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz, const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz); + +WOLFSSL_LOCAL int wc_CryptoCb_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); +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AES_CBC +WOLFSSL_LOCAL int wc_CryptoCb_AesCbcEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_LOCAL int wc_CryptoCb_AesCbcDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif /* HAVE_AES_CBC */ +#endif /* !NO_AES */ + +#ifndef NO_DES3 +WOLFSSL_LOCAL int wc_CryptoCb_Des3Encrypt(Des3* des3, byte* out, + const byte* in, word32 sz); +WOLFSSL_LOCAL int wc_CryptoCb_Des3Decrypt(Des3* des3, byte* out, + const byte* in, word32 sz); +#endif /* !NO_DES3 */ + +#ifndef NO_SHA +WOLFSSL_LOCAL int wc_CryptoCb_ShaHash(wc_Sha* sha, const byte* in, + word32 inSz, byte* digest); +#endif /* !NO_SHA */ + +#ifndef NO_SHA256 +WOLFSSL_LOCAL int wc_CryptoCb_Sha256Hash(wc_Sha256* sha256, const byte* in, + word32 inSz, byte* digest); +#endif /* !NO_SHA256 */ +#ifndef NO_HMAC +WOLFSSL_LOCAL int wc_CryptoCb_Hmac(Hmac* hmac, int macType, const byte* in, + word32 inSz, byte* digest); +#endif /* !NO_HMAC */ + +#ifndef WC_NO_RNG +WOLFSSL_LOCAL int wc_CryptoCb_RandomBlock(WC_RNG* rng, byte* out, word32 sz); +WOLFSSL_LOCAL int wc_CryptoCb_RandomSeed(OS_Seed* os, byte* seed, word32 sz); +#endif + +#endif /* WOLF_CRYPTO_CB */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* _WOLF_CRYPTO_CB_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/curve25519.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/curve25519.h index 11715775f..2b122e7a2 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/curve25519.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/curve25519.h @@ -1,8 +1,8 @@ /* curve25519.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/curve25519.h +*/ + + #ifndef WOLF_CRYPT_CURVE25519_H #define WOLF_CRYPT_CURVE25519_H @@ -29,26 +34,40 @@ #include #include +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + #ifdef __cplusplus extern "C" { #endif #define CURVE25519_KEYSIZE 32 +#ifdef WOLFSSL_NAMES_STATIC +typedef char curve25519_str[12]; +#else +typedef const char* curve25519_str; +#endif + /* curve25519 set type */ typedef struct { - int size; /* The size of the curve in octets */ - const char* name; /* name of this curve */ + int size; /* The size of the curve in octets */ + curve25519_str name; /* name of this curve */ } curve25519_set_type; -/* ECC point */ +/* ECC point, the internal structure is Little endian + * the mathematical functions used the endianness */ typedef struct { byte point[CURVE25519_KEYSIZE]; -}ECPoint; + #ifdef FREESCALE_LTC_ECC + byte pointY[CURVE25519_KEYSIZE]; + #endif +} 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 */ @@ -56,16 +75,30 @@ 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 { + EC25519_LITTLE_ENDIAN=0, + EC25519_BIG_ENDIAN=1 +}; + WOLFSSL_API -int wc_curve25519_make_key(RNG* rng, int keysize, curve25519_key* key); +int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key); WOLFSSL_API int wc_curve25519_shared_secret(curve25519_key* private_key, curve25519_key* public_key, byte* out, word32* outlen); +WOLFSSL_API +int wc_curve25519_shared_secret_ex(curve25519_key* private_key, + curve25519_key* public_key, + byte* out, word32* outlen, int endian); + WOLFSSL_API int wc_curve25519_init(curve25519_key* key); @@ -74,21 +107,51 @@ void wc_curve25519_free(curve25519_key* key); /* raw key helpers */ +WOLFSSL_API +int wc_curve25519_import_private(const byte* priv, word32 privSz, + curve25519_key* key); +WOLFSSL_API +int wc_curve25519_import_private_ex(const byte* priv, word32 privSz, + curve25519_key* key, int endian); + WOLFSSL_API int wc_curve25519_import_private_raw(const byte* priv, word32 privSz, const byte* pub, word32 pubSz, curve25519_key* key); WOLFSSL_API +int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + curve25519_key* key, int endian); +WOLFSSL_API int wc_curve25519_export_private_raw(curve25519_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out, + word32* outLen, int endian); WOLFSSL_API int wc_curve25519_import_public(const byte* in, word32 inLen, curve25519_key* key); +WOLFSSL_API +int wc_curve25519_import_public_ex(const byte* in, word32 inLen, + curve25519_key* key, int endian); +WOLFSSL_API +int wc_curve25519_check_public(const byte* pub, word32 pubSz, int endian); WOLFSSL_API int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_curve25519_export_public_ex(curve25519_key* key, byte* out, + word32* outLen, int endian); - +WOLFSSL_API +int wc_curve25519_export_key_raw(curve25519_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz); +WOLFSSL_API +int wc_curve25519_export_key_raw_ex(curve25519_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz, + int endian); /* size helper */ WOLFSSL_API int wc_curve25519_size(curve25519_key* key); diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/curve448.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/curve448.h new file mode 100644 index 000000000..6a9c495e2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/curve448.h @@ -0,0 +1,139 @@ +/* curve448.h + * + * Copyright (C) 2006-2020 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 + */ + +/* Implemented to: RFC 7748 */ + + +#ifndef WOLF_CRYPT_CURVE448_H +#define WOLF_CRYPT_CURVE448_H + +#include + +#ifdef HAVE_CURVE448 + +#include +#include + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#define CURVE448_KEY_SIZE 56 +#define CURVE448_PUB_KEY_SIZE 56 + + +/* A CURVE448 Key */ +typedef struct curve448_key { + byte p[CURVE448_PUB_KEY_SIZE]; /* public key */ + byte k[CURVE448_KEY_SIZE]; /* private key */ + +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif +} curve448_key; + +enum { + EC448_LITTLE_ENDIAN = 0, + EC448_BIG_ENDIAN = 1 +}; + +WOLFSSL_API +int wc_curve448_make_key(WC_RNG* rng, int keysize, curve448_key* key); + +WOLFSSL_API +int wc_curve448_shared_secret(curve448_key* private_key, + curve448_key* public_key, + byte* out, word32* outlen); + +WOLFSSL_API +int wc_curve448_shared_secret_ex(curve448_key* private_key, + curve448_key* public_key, + byte* out, word32* outlen, int endian); + +WOLFSSL_API +int wc_curve448_init(curve448_key* key); + +WOLFSSL_API +void wc_curve448_free(curve448_key* key); + + +/* raw key helpers */ +WOLFSSL_API +int wc_curve448_import_private(const byte* priv, word32 privSz, + curve448_key* key); +WOLFSSL_API +int wc_curve448_import_private_ex(const byte* priv, word32 privSz, + curve448_key* key, int endian); + +WOLFSSL_API +int wc_curve448_import_private_raw(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + curve448_key* key); +WOLFSSL_API +int wc_curve448_import_private_raw_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + curve448_key* key, int endian); +WOLFSSL_API +int wc_curve448_export_private_raw(curve448_key* key, byte* out, + word32* outLen); +WOLFSSL_API +int wc_curve448_export_private_raw_ex(curve448_key* key, byte* out, + word32* outLen, int endian); + +WOLFSSL_API +int wc_curve448_import_public(const byte* in, word32 inLen, + curve448_key* key); +WOLFSSL_API +int wc_curve448_import_public_ex(const byte* in, word32 inLen, + curve448_key* key, int endian); +WOLFSSL_API +int wc_curve448_check_public(const byte* pub, word32 pubSz, int endian); + +WOLFSSL_API +int wc_curve448_export_public(curve448_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_curve448_export_public_ex(curve448_key* key, byte* out, + word32* outLen, int endian); + +WOLFSSL_API +int wc_curve448_export_key_raw(curve448_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz); +WOLFSSL_API +int wc_curve448_export_key_raw_ex(curve448_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz, + int endian); +/* size helper */ +WOLFSSL_API +int wc_curve448_size(curve448_key* key); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_CURVE448 */ +#endif /* WOLF_CRYPT_CURVE448_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/des3.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/des3.h index c17884968..705b59e63 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/des3.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/des3.h @@ -1,8 +1,8 @@ /* des3.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/des3.h +*/ + #ifndef WOLF_CRYPT_DES3_H #define WOLF_CRYPT_DES3_H @@ -26,7 +30,13 @@ #ifndef NO_DES3 -#ifdef HAVE_FIPS +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) /* included for fips @wc_fips */ #include #endif @@ -35,14 +45,28 @@ extern "C" { #endif -#ifndef HAVE_FIPS /* to avoid redifinition of macros */ -#define WOLFSSL_3DES_CAVIUM_MAGIC 0xBEEF0003 +/* these are required for FIPS and non-FIPS */ +enum { + DES_KEY_SIZE = 8, /* des */ + DES3_KEY_SIZE = 24, /* 3 des ede */ + DES_IV_SIZE = 8, /* should be the same as DES_BLOCK_SIZE */ +}; + + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif enum { - DES_ENC_TYPE = 2, /* cipher unique type */ - DES3_ENC_TYPE = 3, /* cipher unique type */ + DES_ENC_TYPE = WC_CIPHER_DES, /* cipher unique type */ + DES3_ENC_TYPE = WC_CIPHER_DES3, /* cipher unique type */ + DES_BLOCK_SIZE = 8, - DES_KS_SIZE = 32, + DES_KS_SIZE = 32, /* internal DES key buffer size */ DES_ENCRYPTION = 0, DES_DECRYPTION = 1 @@ -54,7 +78,7 @@ enum { #define DES3_KEYLEN 24 -#ifdef STM32F2_CRYPTO +#if defined(STM32_CRYPTO) enum { DES_CBC = 0, DES_ECB = 1 @@ -71,38 +95,59 @@ typedef struct Des { /* DES3 encryption and decryption */ -typedef struct Des3 { +struct Des3 { word32 key[3][DES_KS_SIZE]; word32 reg[DES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ word32 tmp[DES_BLOCK_SIZE / sizeof(word32)]; /* same */ -#ifdef HAVE_CAVIUM - int devId; /* nitrox device id */ - word32 magic; /* using cavium magic */ - word64 contextHandle; /* nitrox context memory handle */ +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif +#if defined(WOLF_CRYPTO_CB) || \ + (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES)) + word32 devKey[DES3_KEYLEN/sizeof(word32)]; /* raw key */ +#endif +#ifdef WOLF_CRYPTO_CB + int devId; + void* devCtx; +#endif + void* heap; +}; + +#ifndef WC_DES3_TYPE_DEFINED + typedef struct Des3 Des3; + #define WC_DES3_TYPE_DEFINED #endif -} Des3; #endif /* HAVE_FIPS */ -WOLFSSL_API int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir); + +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); -WOLFSSL_API int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz); -WOLFSSL_API int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz); -WOLFSSL_API int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz); -WOLFSSL_API int wc_Des_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, - const byte* key, const byte* iv); +WOLFSSL_API int wc_Des_CbcEncrypt(Des* des, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_Des_CbcDecrypt(Des* des, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_Des_EcbEncrypt(Des* des, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_Des3_EcbEncrypt(Des3* des, byte* out, + const byte* in, word32 sz); -WOLFSSL_API int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv,int dir); +/* ECB decrypt same process as encrypt but with decrypt key */ +#define wc_Des_EcbDecrypt wc_Des_EcbEncrypt +#define wc_Des3_EcbDecrypt wc_Des3_EcbEncrypt + +WOLFSSL_API int wc_Des3_SetKey(Des3* des, const byte* key, + const byte* iv,int dir); WOLFSSL_API int wc_Des3_SetIV(Des3* des, const byte* iv); -WOLFSSL_API int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in,word32 sz); -WOLFSSL_API int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in,word32 sz); -WOLFSSL_API int wc_Des3_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, - const byte* key, const byte* iv); +WOLFSSL_API int wc_Des3_CbcEncrypt(Des3* des, byte* out, + const byte* in,word32 sz); +WOLFSSL_API int wc_Des3_CbcDecrypt(Des3* des, byte* out, + const byte* in,word32 sz); - -#ifdef HAVE_CAVIUM - WOLFSSL_API int wc_Des3_InitCavium(Des3*, int); - WOLFSSL_API void wc_Des3_FreeCavium(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/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/dh.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/dh.h index 7cee7dce3..a69232cc0 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/dh.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/dh.h @@ -1,8 +1,8 @@ /* dh.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/dh.h +*/ + #ifndef WOLF_CRYPT_DH_H #define WOLF_CRYPT_DH_H @@ -26,6 +30,11 @@ #ifndef NO_DH +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + #include #include @@ -33,17 +42,59 @@ extern "C" { #endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +typedef struct DhParams { + #ifdef HAVE_FFDHE_Q + const byte* q; + word32 q_len; + #endif /* HAVE_FFDHE_Q */ + 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 */ -} DhKey; +struct DhKey { + mp_int p, g, q; /* group parameters */ +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) + mp_int pub; + mp_int priv; +#endif + void* heap; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif +}; +#ifndef WC_DH_TYPE_DEFINED + typedef struct DhKey DhKey; + #define WC_DH_TYPE_DEFINED +#endif -WOLFSSL_API void wc_InitDhKey(DhKey* key); -WOLFSSL_API void wc_FreeDhKey(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_DhGenerateKeyPair(DhKey* key, RNG* rng, byte* priv, +WOLFSSL_API int wc_InitDhKey(DhKey* key); +WOLFSSL_API int wc_InitDhKey_ex(DhKey* key, void* heap, int devId); +WOLFSSL_API int wc_FreeDhKey(DhKey* key); + +WOLFSSL_API int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz, byte* pub, word32* pubSz); WOLFSSL_API int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, word32 privSz, const byte* otherPub, @@ -53,8 +104,30 @@ WOLFSSL_API int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32); WOLFSSL_API int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz); +WOLFSSL_API int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, + const byte* g, word32 gSz, const byte* q, word32 qSz); +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +WOLFSSL_LOCAL int wc_DhSetFullKeys(DhKey* key,const byte* priv_key,word32 privSz, + const byte* pub_key, word32 pubSz); +#endif +WOLFSSL_API int wc_DhSetCheckKey(DhKey* key, const byte* p, word32 pSz, + const byte* g, word32 gSz, const byte* q, word32 qSz, + int trusted, WC_RNG* rng); 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); +WOLFSSL_API int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz, + const byte* prime, word32 primeSz); +WOLFSSL_API int wc_DhCheckPubValue(const byte* prime, word32 primeSz, + const byte* pub, word32 pubSz); +WOLFSSL_API int wc_DhCheckPrivKey(DhKey* key, const byte* priv, word32 pubSz); +WOLFSSL_API int wc_DhCheckPrivKey_ex(DhKey* key, const byte* priv, word32 pubSz, + const byte* prime, word32 primeSz); +WOLFSSL_API int wc_DhCheckKeyPair(DhKey* key, const byte* pub, word32 pubSz, + const byte* priv, word32 privSz); +WOLFSSL_API int wc_DhGenerateParams(WC_RNG *rng, int modSz, DhKey *dh); +WOLFSSL_API int wc_DhExportParamsRaw(DhKey* dh, byte* p, word32* pSz, + byte* q, word32* qSz, byte* g, word32* gSz); #ifdef __cplusplus diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/dsa.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/dsa.h index 960bd751b..acc133e5c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/dsa.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/dsa.h @@ -1,8 +1,8 @@ /* dsa.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/dsa.h +*/ + #ifndef WOLF_CRYPT_DSA_H #define WOLF_CRYPT_DSA_H @@ -36,6 +40,7 @@ #define DsaVerify wc_DsaVerify #define DsaPublicKeyDecode wc_DsaPublicKeyDecode #define DsaPrivateKeyDecode wc_DsaPrivateKeyDecode +#define DsaKeyToDer wc_DsaKeyToDer #ifdef __cplusplus extern "C" { @@ -47,25 +52,50 @@ enum { DSA_PRIVATE = 1 }; +enum { + DSA_HALF_SIZE = 20, /* r and s size */ + DSA_SIG_SIZE = 40 /* signature size */ +}; + /* DSA */ typedef struct DsaKey { mp_int p, q, g, y, x; - int type; /* public or private */ + int type; /* public or private */ + void* heap; /* memory hint */ } DsaKey; - -WOLFSSL_API void wc_InitDsaKey(DsaKey* key); +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); +WOLFSSL_API int wc_DsaVerify(const byte* digest, const byte* sig, + DsaKey* key, int* answer); +WOLFSSL_API int wc_DsaPublicKeyDecode(const byte* input, word32* inOutIdx, + DsaKey*, word32); +WOLFSSL_API int wc_DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, + DsaKey*, word32); +WOLFSSL_API int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen); +WOLFSSL_API int wc_SetDsaPublicKey(byte* output, DsaKey* key, + int outLen, int with_header); +WOLFSSL_API int wc_DsaKeyToPublicDer(DsaKey* key, byte* output, word32 inLen); -WOLFSSL_API int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, RNG* rng); -WOLFSSL_API int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, - int* answer); - -WOLFSSL_API int wc_DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey*, - word32); -WOLFSSL_API int wc_DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey*, - word32); +#ifdef WOLFSSL_KEY_GEN +WOLFSSL_API int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa); +WOLFSSL_API int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa); +#endif +/* raw export functions */ +WOLFSSL_API int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p, + const char* q, const char* g); +WOLFSSL_API int wc_DsaImportParamsRawCheck(DsaKey* dsa, const char* p, + const char* q, const char* g, + int trusted, WC_RNG* rng); +WOLFSSL_API int wc_DsaExportParamsRaw(DsaKey* dsa, byte* p, word32* pSz, + byte* q, word32* qSz, byte* g, + word32* gSz); +WOLFSSL_API int wc_DsaExportKeyRaw(DsaKey* dsa, byte* x, word32* xSz, byte* y, + word32* ySz); #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ecc.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ecc.h index 447e8d3e2..27f42067f 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ecc.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ecc.h @@ -1,8 +1,8 @@ /* ecc.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/ecc.h +*/ + + #ifndef WOLF_CRYPT_ECC_H #define WOLF_CRYPT_ECC_H @@ -26,27 +31,203 @@ #ifdef HAVE_ECC +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + #include #include +#ifdef HAVE_X963_KDF + #include +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + #include + #ifdef WOLFSSL_CERT_GEN + #include + #endif +#endif + +#ifdef WOLFSSL_ATECC508A + #include +#endif /* WOLFSSL_ATECC508A */ + +#if defined(WOLFSSL_CRYPTOCELL) + #include +#endif + #ifdef __cplusplus extern "C" { #endif + +/* Enable curve B parameter if needed */ +#if defined(HAVE_COMP_KEY) || defined(ECC_CACHE_CURVE) + #ifndef USE_ECC_B_PARAM /* Allow someone to force enable */ + #define USE_ECC_B_PARAM + #endif +#endif + + +/* Use this as the key->idx if a custom ecc_set is used for key->dp */ +#define ECC_CUSTOM_IDX (-1) + + +/* Determine max ECC bits based on enabled curves */ +#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #define MAX_ECC_BITS 521 +#elif defined(HAVE_ECC512) + #define MAX_ECC_BITS 512 +#elif defined(HAVE_ECC384) + #define MAX_ECC_BITS 384 +#elif defined(HAVE_ECC320) + #define MAX_ECC_BITS 320 +#elif !defined(NO_ECC256) + #define MAX_ECC_BITS 256 +#elif defined(HAVE_ECC239) + #define MAX_ECC_BITS 239 +#elif defined(HAVE_ECC224) + #define MAX_ECC_BITS 224 +#elif defined(HAVE_ECC192) + #define MAX_ECC_BITS 192 +#elif defined(HAVE_ECC160) + #define MAX_ECC_BITS 160 +#elif defined(HAVE_ECC128) + #define MAX_ECC_BITS 128 +#elif defined(HAVE_ECC112) + #define MAX_ECC_BITS 112 +#endif + +/* calculate max ECC bytes */ +#if ((MAX_ECC_BITS * 2) % 8) == 0 + #define MAX_ECC_BYTES (MAX_ECC_BITS / 8) +#else + /* add byte if not aligned */ + #define MAX_ECC_BYTES ((MAX_ECC_BITS / 8) + 1) +#endif + +#ifndef ECC_MAX_PAD_SZ + /* ECC maximum padding size (when MSB is set extra byte required for R and S) */ + #define ECC_MAX_PAD_SZ 2 +#endif + enum { - ECC_PUBLICKEY = 1, - ECC_PRIVATEKEY = 2, - ECC_MAXNAME = 16, /* MAX CURVE NAME LENGTH */ - SIG_HEADER_SZ = 6, /* ECC signature header size */ - ECC_BUFSIZE = 256, /* for exported keys temp buffer */ - ECC_MINSIZE = 20, /* MIN Private Key size */ - ECC_MAXSIZE = 66 /* MAX Private Key size */ + ECC_PUBLICKEY = 1, + ECC_PRIVATEKEY = 2, + ECC_PRIVATEKEY_ONLY = 3, + ECC_MAXNAME = 16, /* MAX CURVE NAME LENGTH */ + SIG_HEADER_SZ = 7, /* ECC signature header size (30 81 87 02 42 [R] 02 42 [S]) */ + ECC_BUFSIZE = 256, /* for exported keys temp buffer */ + ECC_MINSIZE = 20, /* MIN Private Key size */ + ECC_MAXSIZE = 66, /* MAX Private Key size */ + ECC_MAXSIZE_GEN = 74, /* MAX Buffer size required when generating ECC keys*/ + ECC_MAX_OID_LEN = 16, + 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 */ + ECC_MAX_CRYPTO_HW_PUBKEY_SIZE = (ATECC_KEY_SIZE*2), +#elif defined(PLUTON_CRYPTO_ECC) + ECC_MAX_CRYPTO_HW_SIZE = 32, +#elif defined(WOLFSSL_CRYPTOCELL) + #ifndef CRYPTOCELL_KEY_SIZE + CRYPTOCELL_KEY_SIZE = ECC_MAXSIZE, + #endif + ECC_MAX_CRYPTO_HW_SIZE = CRYPTOCELL_KEY_SIZE, +#endif + + /* point compression type */ + ECC_POINT_COMP_EVEN = 0x02, + ECC_POINT_COMP_ODD = 0x03, + ECC_POINT_UNCOMP = 0x04, + + /* Shamir's dual add constants */ + SHAMIR_PRECOMP_SZ = 16, + +#ifdef HAVE_PKCS11 + ECC_MAX_ID_LEN = 32, +#endif }; +/* Curve Types */ +typedef enum ecc_curve_id { + ECC_CURVE_INVALID = -1, + ECC_CURVE_DEF = 0, /* NIST or SECP */ -/* ECC set type defined a NIST GF(p) curve */ -typedef struct { - int size; /* The size of the curve in octets */ + /* NIST Prime Curves */ + ECC_SECP192R1, + ECC_PRIME192V2, + ECC_PRIME192V3, + ECC_PRIME239V1, + ECC_PRIME239V2, + ECC_PRIME239V3, + ECC_SECP256R1, + + /* SECP Curves */ + ECC_SECP112R1, + ECC_SECP112R2, + ECC_SECP128R1, + ECC_SECP128R2, + ECC_SECP160R1, + ECC_SECP160R2, + ECC_SECP224R1, + ECC_SECP384R1, + ECC_SECP521R1, + + /* Koblitz */ + ECC_SECP160K1, + ECC_SECP192K1, + ECC_SECP224K1, + ECC_SECP256K1, + + /* Brainpool Curves */ + ECC_BRAINPOOLP160R1, + ECC_BRAINPOOLP192R1, + ECC_BRAINPOOLP224R1, + ECC_BRAINPOOLP256R1, + ECC_BRAINPOOLP320R1, + ECC_BRAINPOOLP384R1, + ECC_BRAINPOOLP512R1, + + /* Twisted Edwards Curves */ +#ifdef HAVE_CURVE25519 + ECC_X25519, +#endif +#ifdef HAVE_CURVE448 + ECC_X448, +#endif + +#ifdef WOLFSSL_CUSTOM_CURVES + ECC_CURVE_CUSTOM, +#endif +} ecc_curve_id; + +#ifdef HAVE_OID_ENCODING +typedef word16 ecc_oid_t; +#else +typedef byte ecc_oid_t; + /* OID encoded with ASN scheme: + first element = (oid[0] * 40) + oid[1] + if any element > 127 then MSB 0x80 indicates additional byte */ +#endif + + +#if !defined(WOLFSSL_ECC_CURVE_STATIC) && defined(USE_WINDOWS_API) + /* MSC does something different with the pointers to the arrays than GCC, + * and it causes the FIPS checksum to fail. In the case of windows builds, + * store everything as arrays instead of pointers to strings. */ + + #define WOLFSSL_ECC_CURVE_STATIC +#endif + +/* ECC set type defined a GF(p) curve */ +#ifndef WOLFSSL_ECC_CURVE_STATIC +typedef struct ecc_set_type { + int size; /* The size of the curve in octets */ + int id; /* id of this curve */ const char* name; /* name of this curve */ const char* prime; /* prime that defines the field, curve is in (hex) */ const char* Af; /* fields A param (hex) */ @@ -54,7 +235,32 @@ typedef struct { const char* order; /* order of the curve (hex) */ const char* Gx; /* x coordinate of the base point on curve (hex) */ const char* Gy; /* y coordinate of the base point on curve (hex) */ + const ecc_oid_t* oid; + word32 oidSz; + word32 oidSum; /* sum of encoded OID bytes */ + int cofactor; } ecc_set_type; +#else +#define MAX_ECC_NAME 16 +#define MAX_ECC_STRING ((MAX_ECC_BYTES * 2) + 1) + /* The values are stored as text strings. */ + +typedef struct ecc_set_type { + int size; /* The size of the curve in octets */ + int id; /* id of this curve */ + const char name[MAX_ECC_NAME]; /* name of this curve */ + const char prime[MAX_ECC_STRING]; /* prime that defines the field, curve is in (hex) */ + const char Af[MAX_ECC_STRING]; /* fields A param (hex) */ + const char Bf[MAX_ECC_STRING]; /* fields B param (hex) */ + const char order[MAX_ECC_STRING]; /* order of the curve (hex) */ + const char Gx[MAX_ECC_STRING]; /* x coordinate of the base point on curve (hex) */ + const char Gy[MAX_ECC_STRING]; /* y coordinate of the base point on curve (hex) */ + const ecc_oid_t oid[10]; + word32 oidSz; + word32 oidSum; /* sum of encoded OID bytes */ + int cofactor; +} ecc_set_type; +#endif #ifdef ALT_ECC_SIZE @@ -72,34 +278,56 @@ typedef struct { * mp_ints for the components of the point. With ALT_ECC_SIZE, the components * of the point are pointers that are set to each of a three item array of * alt_fp_ints. While an mp_int will have 4096 bits of digit inside the - * structure, the alt_fp_int will only have 512 bits. A size value was added + * structure, the alt_fp_int will only have 528 bits. A size value was added * in the ALT case, as well, and is set by mp_init() and alt_fp_init(). The * functions fp_zero() and fp_copy() use the size parameter. An int needs to * be initialized before using it instead of just fp_zeroing it, the init will - * call zero. FP_MAX_BITS_ECC defaults to 512, but can be set to change the + * call zero. FP_MAX_BITS_ECC defaults to 528, but can be set to change the * number of bits used in the alternate FP_INT. * * Do not enable ALT_ECC_SIZE and disable fast math in the configuration. */ +#ifndef USE_FAST_MATH + #error USE_FAST_MATH must be defined to use ALT_ECC_SIZE +#endif + +/* determine max bits required for ECC math */ #ifndef FP_MAX_BITS_ECC - #define FP_MAX_BITS_ECC 512 + /* check alignment */ + #if ((MAX_ECC_BITS * 2) % DIGIT_BIT) == 0 + /* max bits is double */ + #define FP_MAX_BITS_ECC (MAX_ECC_BITS * 2) + #else + /* max bits is doubled, plus one digit of fudge */ + #define FP_MAX_BITS_ECC ((MAX_ECC_BITS * 2) + DIGIT_BIT) + #endif +#else + /* verify alignment */ + #if FP_MAX_BITS_ECC % CHAR_BIT + #error FP_MAX_BITS_ECC must be a multiple of CHAR_BIT + #endif #endif -#define FP_MAX_SIZE_ECC (FP_MAX_BITS_ECC+(8*DIGIT_BIT)) -#if FP_MAX_BITS_ECC % CHAR_BIT - #error FP_MAX_BITS_ECC must be a multiple of CHAR_BIT -#endif -#define FP_SIZE_ECC (FP_MAX_SIZE_ECC/DIGIT_BIT) + +/* determine buffer size */ +#define FP_SIZE_ECC (FP_MAX_BITS_ECC/DIGIT_BIT) + /* This needs to match the size of the fp_int struct, except the * fp_digit array will be shorter. */ typedef struct alt_fp_int { int used, sign, size; - fp_digit dp[FP_SIZE_ECC]; + mp_digit dp[FP_SIZE_ECC]; } alt_fp_int; +#endif /* ALT_ECC_SIZE */ + +#ifndef WC_ECCKEY_TYPE_DEFINED + typedef struct ecc_key ecc_key; + #define WC_ECCKEY_TYPE_DEFINED #endif -/* A point on an ECC curve, stored in Jacbobian format such that (x,y,z) => + +/* A point on an ECC curve, stored in Jacobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpreted as affine */ typedef struct { #ifndef ALT_ECC_SIZE @@ -112,73 +340,337 @@ typedef struct { mp_int* z; /* The z coordinate */ alt_fp_int xyz[3]; #endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + ecc_key* key; +#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 { +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; + word32 flags; const ecc_set_type* dp; /* domain parameters, either points to NIST curves (idx >= 0) or user supplied */ +#ifdef WOLFSSL_CUSTOM_CURVES + int deallocSet; +#endif + void* heap; /* heap hint */ ecc_point pubkey; /* public key */ mp_int k; /* private key */ -} ecc_key; +#ifdef WOLFSSL_ATECC508A + int slot; /* Key Slot Number (-1 unknown) */ + byte pubkey_raw[ECC_MAX_CRYPTO_HW_PUBKEY_SIZE]; +#endif +#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_CB) + int devId; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + mp_int* r; /* sign/verify temps */ + mp_int* s; + WC_ASYNC_DEV asyncDev; + #ifdef HAVE_CAVIUM_V + mp_int* e; /* Sign, Verify and Shared Secret */ + mp_int* signK; + #endif + #ifdef WOLFSSL_CERT_GEN + CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */ + #endif +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef HAVE_PKCS11 + byte id[ECC_MAX_ID_LEN]; + int idLen; +#endif +#if defined(WOLFSSL_CRYPTOCELL) + ecc_context_t ctx; +#endif + +#ifdef WOLFSSL_ECDSA_SET_K + mp_int *sign_k; +#endif + +#ifdef WOLFSSL_SMALL_STACK_CACHE + mp_int* t1; + mp_int* t2; +#ifdef ALT_ECC_SIZE + mp_int* x; + mp_int* y; + mp_int* z; +#endif +#endif + +#ifdef WOLFSSL_DSP + remote_handle64 handle; +#endif +}; + + +WOLFSSL_ABI WOLFSSL_API ecc_key* wc_ecc_key_new(void*); +WOLFSSL_ABI WOLFSSL_API void wc_ecc_key_free(ecc_key*); /* ECC predefined curve sets */ extern const ecc_set_type ecc_sets[]; - +extern const size_t ecc_sets_count; WOLFSSL_API -int wc_ecc_make_key(RNG* rng, int keysize, ecc_key* key); +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_mul2add(ecc_point* A, mp_int* kA, + ecc_point* B, mp_int* kB, + ecc_point* C, mp_int* a, mp_int* modulus, void* heap); + +ECC_API int ecc_map(ecc_point*, mp_int*, mp_digit); +ECC_API int ecc_map_ex(ecc_point*, mp_int*, mp_digit, int ct); +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); +WOLFSSL_ABI 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); +WOLFSSL_API +int wc_ecc_get_generator(ecc_point* ecp, int curve_idx); + +#ifdef HAVE_ECC_DHE +WOLFSSL_API int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, word32* outlen); +WOLFSSL_LOCAL +int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen); WOLFSSL_API -int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, - RNG* rng, ecc_key* key); +int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen); + +#if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC) || defined(WOLFSSL_CRYPTOCELL) +#define wc_ecc_shared_secret_ssh wc_ecc_shared_secret +#else +#define wc_ecc_shared_secret_ssh wc_ecc_shared_secret_ex /* For backwards compat */ +#endif + +#endif /* HAVE_ECC_DHE */ + +#ifdef HAVE_ECC_SIGN +WOLFSSL_ABI WOLFSSL_API +int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, + WC_RNG* rng, ecc_key* key); +WOLFSSL_API +int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, + ecc_key* key, mp_int *r, mp_int *s); +#ifdef WOLFSSL_ECDSA_SET_K +WOLFSSL_API +int wc_ecc_sign_set_k(const byte* k, word32 klen, ecc_key* key); +#endif +#endif /* HAVE_ECC_SIGN */ + +#ifdef HAVE_ECC_VERIFY WOLFSSL_API int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, word32 hashlen, int* stat, ecc_key* key); WOLFSSL_API -int wc_ecc_init(ecc_key* key); +int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, + word32 hashlen, int* stat, ecc_key* key); +#endif /* HAVE_ECC_VERIFY */ + WOLFSSL_API -void wc_ecc_free(ecc_key* key); +int wc_ecc_init(ecc_key* key); +WOLFSSL_ABI WOLFSSL_API +int wc_ecc_init_ex(ecc_key* key, void* heap, int devId); +#ifdef HAVE_PKCS11 +WOLFSSL_API +int wc_ecc_init_id(ecc_key* key, unsigned char* id, int len, void* heap, + int devId); +#endif +#ifdef WOLFSSL_CUSTOM_CURVES +WOLFSSL_LOCAL +void wc_ecc_free_curve(const ecc_set_type* curve, void* heap); +#endif +WOLFSSL_ABI WOLFSSL_API +int 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 +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); + +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 +int wc_ecc_get_curve_id_from_dp_params(const ecc_set_type* dp); + +WOLFSSL_API +int wc_ecc_get_curve_id_from_oid(const byte* oid, word32 len); + +WOLFSSL_API const ecc_set_type* wc_ecc_get_curve_params(int curve_idx); + +WOLFSSL_API +ecc_point* wc_ecc_new_point(void); +WOLFSSL_API +ecc_point* wc_ecc_new_point_h(void* h); +WOLFSSL_API +void wc_ecc_del_point(ecc_point* p); +WOLFSSL_API +void wc_ecc_del_point_h(ecc_point* p, void* h); +WOLFSSL_API +int wc_ecc_copy_point(ecc_point* p, ecc_point *r); +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); +WOLFSSL_LOCAL +int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, + mp_int* a, mp_int* modulus, int map, void* heap); +#endif /* !WOLFSSL_ATECC508A */ + + +#ifdef HAVE_ECC_KEY_EXPORT /* ASN key helpers */ WOLFSSL_API int wc_ecc_export_x963(ecc_key*, byte* out, word32* outLen); WOLFSSL_API int wc_ecc_export_x963_ex(ecc_key*, byte* out, word32* outLen, int compressed); /* extended functionality with compressed option */ -WOLFSSL_API +#endif /* HAVE_ECC_KEY_EXPORT */ + +#ifdef HAVE_ECC_KEY_IMPORT +WOLFSSL_ABI WOLFSSL_API int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key); WOLFSSL_API +int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, + int curve_id); +WOLFSSL_API int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub, word32 pubSz, ecc_key* key); WOLFSSL_API +int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, ecc_key* key, int curve_id); +WOLFSSL_API int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen); WOLFSSL_API +int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz, + byte* out, word32* outlen); +WOLFSSL_API +int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, + byte* s, word32* sLen); +WOLFSSL_API int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, const char* d, const char* curveName); +WOLFSSL_API +int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, + const char* d, int curve_id); +WOLFSSL_API +int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy, + byte* d, int curve_id); +#endif /* HAVE_ECC_KEY_IMPORT */ +#ifdef HAVE_ECC_KEY_EXPORT +WOLFSSL_API +int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen, + int encType); WOLFSSL_API int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen); +WOLFSSL_API +int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen); +#endif /* HAVE_ECC_KEY_EXPORT */ + +#ifdef HAVE_ECC_KEY_EXPORT +WOLFSSL_API +int wc_ecc_export_point_der_ex(const int curve_idx, ecc_point* point, byte* out, + word32* outLen, int compressed); +WOLFSSL_API +int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, + byte* out, word32* outLen); +WOLFSSL_LOCAL +int wc_ecc_export_point_der_compressed(const int curve_idx, ecc_point* point, + byte* out, word32* outLen); +#endif /* HAVE_ECC_KEY_EXPORT */ + + +#ifdef HAVE_ECC_KEY_IMPORT +WOLFSSL_API +int wc_ecc_import_point_der_ex(byte* in, word32 inLen, const int curve_idx, + ecc_point* point, int shortKeySize); +WOLFSSL_API +int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, + ecc_point* point); +#endif /* HAVE_ECC_KEY_IMPORT */ /* size helper */ WOLFSSL_API int wc_ecc_size(ecc_key* key); WOLFSSL_API +int wc_ecc_sig_size_calc(int sz); +WOLFSSL_API int wc_ecc_sig_size(ecc_key* key); +WOLFSSL_API +int wc_ecc_get_oid(word32 oidSum, const byte** oid, word32* oidSz); + +#ifdef WOLFSSL_CUSTOM_CURVES + WOLFSSL_API + int wc_ecc_set_custom_curve(ecc_key* key, const ecc_set_type* dp); +#endif #ifdef HAVE_ECC_ENCRYPT /* ecc encrypt */ @@ -202,6 +694,7 @@ enum { KEY_SIZE_128 = 16, KEY_SIZE_256 = 32, IV_SIZE_64 = 8, + IV_SIZE_128 = 16, EXCHANGE_SALT_SZ = 16, EXCHANGE_INFO_SZ = 23 }; @@ -215,11 +708,13 @@ enum ecFlags { typedef struct ecEncCtx ecEncCtx; WOLFSSL_API -ecEncCtx* wc_ecc_ctx_new(int flags, RNG* rng); +ecEncCtx* wc_ecc_ctx_new(int flags, WC_RNG* rng); +WOLFSSL_API +ecEncCtx* wc_ecc_ctx_new_ex(int flags, WC_RNG* rng, void* heap); WOLFSSL_API void wc_ecc_ctx_free(ecEncCtx*); WOLFSSL_API -int wc_ecc_ctx_reset(ecEncCtx*, RNG*); /* reset for use again w/o alloc/free */ +int wc_ecc_ctx_reset(ecEncCtx*, WC_RNG*); /* reset for use again w/o alloc/free */ WOLFSSL_API const byte* wc_ecc_ctx_get_own_salt(ecEncCtx*); @@ -237,6 +732,28 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, #endif /* HAVE_ECC_ENCRYPT */ +#ifdef HAVE_X963_KDF +WOLFSSL_API int wc_X963_KDF(enum wc_HashType type, const byte* secret, + word32 secretSz, const byte* sinfo, word32 sinfoSz, + byte* out, word32 outSz); +#endif + +#ifdef ECC_CACHE_CURVE +WOLFSSL_API int wc_ecc_curve_cache_init(void); +WOLFSSL_API void wc_ecc_curve_cache_free(void); +#endif + +WOLFSSL_API +int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order); + +#ifdef WOLFSSL_DSP +WOLFSSL_API +int wc_ecc_set_handle(ecc_key* key, remote_handle64 handle); +WOLFSSL_LOCAL +int sp_dsp_ecc_verify_256(remote_handle64 handle, 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 __cplusplus } /* extern "C" */ #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ed25519.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ed25519.h index 6f9a19989..f5487ade5 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ed25519.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ed25519.h @@ -1,8 +1,8 @@ /* ed25519.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/ed25519.h +*/ + + #ifndef WOLF_CRYPT_ED25519_H #define WOLF_CRYPT_ED25519_H @@ -31,6 +36,10 @@ #include #include +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -46,25 +55,76 @@ "-121665/121666", value of d */ -#define ED25519_KEY_SIZE 32 -#define ED25519_SIG_SIZE 64 +#define ED25519_KEY_SIZE 32 /* private key only */ +#define ED25519_SIG_SIZE 64 +#define ED25519_PUB_KEY_SIZE 32 /* compressed */ +/* both private and public key */ +#define ED25519_PRV_KEY_SIZE (ED25519_PUB_KEY_SIZE+ED25519_KEY_SIZE) + + +enum { + Ed25519 = -1, + Ed25519ctx = 0, + Ed25519ph = 1, +}; + +#ifndef WC_ED25519KEY_TYPE_DEFINED + typedef struct ed25519_key ed25519_key; + #define WC_ED25519KEY_TYPE_DEFINED +#endif /* An ED25519 Key */ -typedef struct { - byte p[32]; /* compressed public key */ - byte k[64]; /* private key : 32 secret -- 32 public */ -} ed25519_key; +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 + /* uncompressed point coordinates */ + 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 + word16 pubKeySet:1; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif +}; WOLFSSL_API -int wc_ed25519_make_key(RNG* rng, int keysize, ed25519_key* key); +int wc_ed25519_make_public(ed25519_key* key, unsigned char* pubKey, + word32 pubKeySz); WOLFSSL_API -int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, - word32 *outlen, ed25519_key* key); +int wc_ed25519_make_key(WC_RNG* rng, int keysize, ed25519_key* key); WOLFSSL_API -int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, - word32 msglen, int* stat, ed25519_key* key); +int wc_ed25519_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key); +WOLFSSL_API +int wc_ed25519ctx_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed25519ph_sign_hash(const byte* hash, word32 hashLen, byte* out, + word32 *outLen, ed25519_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key, const byte* context, + byte contextLen); +WOLFSSL_API +int wc_ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* stat, ed25519_key* key); +WOLFSSL_API +int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* stat, ed25519_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash, + word32 hashLen, int* stat, ed25519_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* stat, ed25519_key* key, + const byte* context, byte contextLen); WOLFSSL_API int wc_ed25519_init(ed25519_key* key); WOLFSSL_API @@ -72,17 +132,33 @@ 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 int wc_ed25519_export_public(ed25519_key*, byte* out, word32* outLen); WOLFSSL_API int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_ed25519_export_key(ed25519_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz); + +WOLFSSL_API +int wc_ed25519_check_key(ed25519_key* key); /* size helper */ WOLFSSL_API int wc_ed25519_size(ed25519_key* key); WOLFSSL_API +int wc_ed25519_priv_size(ed25519_key* key); +WOLFSSL_API +int wc_ed25519_pub_size(ed25519_key* key); +WOLFSSL_API int wc_ed25519_sig_size(ed25519_key* key); #ifdef __cplusplus @@ -91,4 +167,3 @@ int wc_ed25519_sig_size(ed25519_key* key); #endif /* HAVE_ED25519 */ #endif /* WOLF_CRYPT_ED25519_H */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ed448.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ed448.h new file mode 100644 index 000000000..4f868b53d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ed448.h @@ -0,0 +1,160 @@ +/* ed448.h + * + * Copyright (C) 2006-2020 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 + */ + +/*! + \file wolfssl/wolfcrypt/ed448.h +*/ + + +#ifndef WOLF_CRYPT_ED448_H +#define WOLF_CRYPT_ED448_H + +#include + +#ifdef HAVE_ED448 + +#include +#include +#include +#include + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +/* info about EdDSA curve specifically ed448, defined as an elliptic curve + * over GF(p) + * + * 56 key size + * "ED448" curve name + * "2^448-2^224-1" prime number + * "-39081" value of d + * "SHAKE256" hash function + */ + +#define ED448_KEY_SIZE 57 /* private key only */ +#define ED448_SIG_SIZE 114 /* two elements */ + +#define ED448_PUB_KEY_SIZE 57 /* compressed */ +/* both private and public key */ +#define ED448_PRV_KEY_SIZE (ED448_PUB_KEY_SIZE+ED448_KEY_SIZE) + + +enum { + Ed448 = 0, + Ed448ph = 1, +}; + +#ifndef WC_ED448KEY_TYPE_DEFINED + typedef struct ed448_key ed448_key; + #define WC_ED448KEY_TYPE_DEFINED +#endif + +/* An ED448 Key */ +struct ed448_key { + byte p[ED448_PUB_KEY_SIZE]; /* compressed public key */ + byte k[ED448_PRV_KEY_SIZE]; /* private key : 56 secret -- 56 public */ +#ifdef FREESCALE_LTC_ECC + /* uncompressed point coordinates */ + byte pointX[ED448_KEY_SIZE]; /* recovered X coordinate */ + byte pointY[ED448_KEY_SIZE]; /* Y coordinate is the public key with The most significant bit of the final octet always zero. */ +#endif + word16 pubKeySet:1; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif +}; + + +WOLFSSL_API +int wc_ed448_make_public(ed448_key* key, unsigned char* pubKey, + word32 pubKeySz); +WOLFSSL_API +int wc_ed448_make_key(WC_RNG* rng, int keysize, ed448_key* key); +WOLFSSL_API +int wc_ed448_sign_msg(const byte* in, word32 inLen, byte* out, word32 *outLen, + ed448_key* key, const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed448ph_sign_hash(const byte* hash, word32 hashLen, byte* out, + word32 *outLen, ed448_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed448ph_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed448_key* key, const byte* context, + byte contextLen); +WOLFSSL_API +int wc_ed448_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* stat, ed448_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed448ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash, + word32 hashLen, int* stat, ed448_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed448ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* stat, ed448_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed448_init(ed448_key* key); +WOLFSSL_API +void wc_ed448_free(ed448_key* key); +WOLFSSL_API +int wc_ed448_import_public(const byte* in, word32 inLen, ed448_key* key); +WOLFSSL_API +int wc_ed448_import_private_only(const byte* priv, word32 privSz, + ed448_key* key); +WOLFSSL_API +int wc_ed448_import_private_key(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, ed448_key* key); +WOLFSSL_API +int wc_ed448_export_public(ed448_key*, byte* out, word32* outLen); +WOLFSSL_API +int wc_ed448_export_private_only(ed448_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_ed448_export_private(ed448_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_ed448_export_key(ed448_key* key, byte* priv, word32 *privSz, + byte* pub, word32 *pubSz); + +WOLFSSL_API +int wc_ed448_check_key(ed448_key* key); + +/* size helper */ +WOLFSSL_API +int wc_ed448_size(ed448_key* key); +WOLFSSL_API +int wc_ed448_priv_size(ed448_key* key); +WOLFSSL_API +int wc_ed448_pub_size(ed448_key* key); +WOLFSSL_API +int wc_ed448_sig_size(ed448_key* key); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_ED448 */ +#endif /* WOLF_CRYPT_ED448_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/error-crypt.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/error-crypt.h index 79991fdf4..445611aef 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/error-crypt.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/error-crypt.h @@ -1,8 +1,8 @@ /* error-crypt.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,27 +16,29 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/error-crypt.h +*/ #ifndef WOLF_CRYPT_ERROR_H #define WOLF_CRYPT_ERROR_H #include -#ifdef HAVE_FIPS +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) #include - #define wc_ErrorString CTaoCryptErrorString - #define wc_GetErrorString CTaoCryptGetErrorString -#endif /* HAVE_FIPS */ +#endif /* HAVE_FIPS V1 */ #ifdef __cplusplus extern "C" { #endif -/* error codes */ +/* error codes, add string for new errors !!! */ enum { MAX_CODE_E = -100, /* errors -101 - -299 */ OPEN_RAN_E = -101, /* opening random device error */ @@ -45,6 +47,9 @@ enum { CRYPTGEN_E = -104, /* windows crypt generation error */ RAN_BLOCK_E = -105, /* reading random device would block */ BAD_MUTEX_E = -106, /* Bad mutex operation */ + WC_TIMEOUT_E = -107, /* timeout error */ + WC_PENDING_E = -108, /* wolfCrypt operation pending (would block) */ + WC_NOT_PENDING_E = -109, /* wolfCrypt operation not pending */ MP_INIT_E = -110, /* mp_init error state */ MP_READ_E = -111, /* mp_read error state */ @@ -60,6 +65,7 @@ enum { MP_ZERO_E = -121, /* got a mp zero result, not expected */ MEMORY_E = -125, /* out of memory error */ + VAR_STATE_CHANGE_E = -126, /* var state modified by different thread */ RSA_WRONG_TYPE_E = -130, /* RSA wrong block type for RSA function */ RSA_BUFFER_E = -131, /* RSA buffer error, output too small or @@ -94,6 +100,8 @@ enum { ASN_DH_KEY_E = -158, /* ASN key init error, invalid input */ ASN_NTRU_KEY_E = -159, /* ASN ntru key decode error, invalid input */ ASN_CRIT_EXT_E = -160, /* ASN unsupported critical extension */ + ASN_ALT_NAME_E = -161, /* ASN alternate name error */ + ASN_NO_PEM_HEADER = -162, /* ASN no PEM header found */ ECC_BAD_ARG_E = -170, /* ECC input argument of wrong type */ ASN_ECC_KEY_E = -171, /* ASN ECC bad input */ @@ -103,11 +111,12 @@ 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 */ - CAVIUM_INIT_E = -182, /* Cavium Init type error */ + ASYNC_INIT_E = -182, /* Async Init type error */ COMPRESS_INIT_E = -183, /* Compress init error */ COMPRESS_E = -184, /* Compress error */ @@ -120,7 +129,7 @@ enum { ASN_CRL_NO_SIGNER_E = -190, /* ASN CRL no signer to confirm failure */ ASN_OCSP_CONFIRM_E = -191, /* ASN OCSP signature confirm failure */ - BAD_ENC_STATE_E = -192, /* Bad ecc enc state operation */ + BAD_STATE_E = -192, /* Bad state operation */ BAD_PADDING_E = -193, /* Bad padding, msg not correct length */ REQ_ATTRIBUTE_E = -194, /* setting cert request attributes error */ @@ -141,7 +150,7 @@ enum { HMAC_KAT_FIPS_E = -206, /* HMAC KAT failure */ RSA_KAT_FIPS_E = -207, /* RSA KAT failure */ DRBG_KAT_FIPS_E = -208, /* HASH DRBG KAT failure */ - DRBG_CONT_FIPS_E = -209, /* HASH DRBG Continious test failure */ + DRBG_CONT_FIPS_E = -209, /* HASH DRBG Continuous test failure */ AESGCM_KAT_FIPS_E = -210, /* AESGCM KAT failure */ THREAD_STORE_KEY_E = -211, /* Thread local storage key create failure */ THREAD_STORE_SET_E = -212, /* Thread local storage key set failure */ @@ -150,18 +159,97 @@ enum { IS_POINT_E = -214, /* ECC is point on curve failed */ ECC_INF_E = -215, /* ECC point infinity error */ ECC_PRIV_KEY_E = -216, /* ECC private key not valid error */ + ECC_OUT_OF_RANGE_E = -217, /* ECC key component out of range */ + SRP_CALL_ORDER_E = -218, /* SRP function called in the wrong order. */ + SRP_VERIFY_E = -219, /* SRP proof verification failed. */ + SRP_BAD_KEY_E = -220, /* SRP bad ephemeral values. */ + + ASN_NO_SKID = -221, /* ASN no Subject Key Identifier found */ + ASN_NO_AKID = -222, /* ASN no Authority Key Identifier found */ + ASN_NO_KEYUSAGE = -223, /* ASN no Key Usage found */ + SKID_E = -224, /* setting Subject Key Identifier error */ + AKID_E = -225, /* setting Authority Key Identifier error */ + KEYUSAGE_E = -226, /* Bad Key Usage value */ + CERTPOLICIES_E = -227, /* setting Certificate Policies error */ + + WC_INIT_E = -228, /* wolfcrypt failed to initialize */ + SIG_VERIFY_E = -229, /* wolfcrypt signature verify error */ + BAD_COND_E = -230, /* Bad condition variable operation */ + SIG_TYPE_E = -231, /* Signature Type not enabled/available */ + HASH_TYPE_E = -232, /* Hash Type not enabled/available */ + + WC_KEY_SIZE_E = -234, /* Key size error, either too small or large */ + ASN_COUNTRY_SIZE_E = -235, /* ASN Cert Gen, invalid country code size */ + MISSING_RNG_E = -236, /* RNG required but not provided */ + ASN_PATHLEN_SIZE_E = -237, /* ASN CA path length too large error */ + ASN_PATHLEN_INV_E = -238, /* ASN CA path length inversion error */ + + 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_HW_E = -248, /* Error with hardware crypto use */ + WC_HW_WAIT_E = -249, /* Hardware waiting on resource */ + + PSS_SALTLEN_E = -250, /* PSS length of salt is too long for hash */ + PRIME_GEN_E = -251, /* Failure finding a prime. */ + BER_INDEF_E = -252, /* Cannot decode indefinite length BER. */ + RSA_OUT_OF_RANGE_E = -253, /* Ciphertext to decrypt out of range. */ + RSAPSS_PAT_FIPS_E = -254, /* RSA-PSS PAT failure */ + ECDSA_PAT_FIPS_E = -255, /* ECDSA PAT failure */ + DH_KAT_FIPS_E = -256, /* DH KAT failure */ + AESCCM_KAT_FIPS_E = -257, /* AESCCM KAT failure */ + SHA3_KAT_FIPS_E = -258, /* SHA-3 KAT failure */ + ECDHE_KAT_FIPS_E = -259, /* ECDHE KAT failure */ + AES_GCM_OVERFLOW_E = -260, /* AES-GCM invocation counter overflow. */ + AES_CCM_OVERFLOW_E = -261, /* AES-CCM invocation counter overflow. */ + RSA_KEY_PAIR_E = -262, /* RSA Key Pair-Wise Consistency check fail. */ + DH_CHECK_PRIV_E = -263, /* DH Check Priv Key error */ + + WC_AFALG_SOCK_E = -264, /* AF_ALG socket error */ + WC_DEVCRYPTO_E = -265, /* /dev/crypto error */ + + ZLIB_INIT_ERROR = -266, /* zlib init error */ + ZLIB_COMPRESS_ERROR = -267, /* zlib compression error */ + ZLIB_DECOMPRESS_ERROR = -268, /* zlib decompression error */ + + PKCS7_NO_SIGNER_E = -269, /* No signer in PKCS#7 signed data msg */ + WC_PKCS7_WANT_READ_E= -270, /* PKCS7 operations wants more input */ + + CRYPTOCB_UNAVAILABLE= -271, /* Crypto callback unavailable */ + PKCS7_SIGNEEDS_CHECK= -272, /* signature needs verified by caller */ + PSS_SALTLEN_RECOVER_E=-273, /* PSS slat length not recoverable */ + + ASN_SELF_SIGNED_E = -274, /* ASN self-signed certificate error */ + + WC_LAST_E = -274, /* Update this to indicate last error */ MIN_CODE_E = -300 /* errors -101 - -299 */ + + /* add new companion error id strings for any new error codes + wolfcrypt/src/error.c !!! */ }; +#ifdef NO_ERROR_STRINGS + #define wc_GetErrorString(error) "no support for error strings built in" + #define wc_ErrorString(err, buf) \ + (void)err; XSTRNCPY((buf), wc_GetErrorString((err)), \ + WOLFSSL_MAX_ERROR_SZ); + +#else WOLFSSL_API void wc_ErrorString(int err, char* buff); WOLFSSL_API const char* wc_GetErrorString(int error); - +#endif #ifdef __cplusplus } /* extern "C" */ #endif #endif /* WOLF_CRYPT_ERROR_H */ - - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fe_448.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fe_448.h new file mode 100644 index 000000000..6bcd87d29 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fe_448.h @@ -0,0 +1,116 @@ +/* fe448_448.h + * + * Copyright (C) 2006-2020 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_FE_448_H +#define WOLF_CRYPT_FE_448_H + +#include + +#if defined(HAVE_CURVE448) || defined(HAVE_ED448) + +#include + +#include + +#if defined(HAVE___UINT128_T) && !defined(NO_CURVED448_128BIT) + #define CURVED448_128BIT +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* default to be faster but take more memory */ +#if !defined(CURVE448_SMALL) || !defined(ED448_SMALL) + +#if defined(CURVED448_128BIT) + typedef int64_t fe448; + #ifdef __SIZEOF_INT128__ + typedef __uint128_t uint128_t; + typedef __int128_t int128_t; + #else + typedef unsigned long uint128_t __attribute__ ((mode(TI))); + typedef long int128_t __attribute__ ((mode(TI))); + #endif +#else + typedef int32_t fe448; +#endif + +WOLFSSL_LOCAL void fe448_init(void); +WOLFSSL_LOCAL int curve448(byte* r, const byte* n, const byte* a); + +#if !defined(CURVED448_128BIT) +WOLFSSL_LOCAL void fe448_reduce(fe448*); +#else +#define fe448_reduce(a) +#endif +WOLFSSL_LOCAL void fe448_neg(fe448*,const fe448*); +WOLFSSL_LOCAL void fe448_add(fe448*, const fe448*, const fe448*); +WOLFSSL_LOCAL void fe448_sub(fe448*, const fe448*, const fe448*); +WOLFSSL_LOCAL void fe448_mul(fe448*,const fe448*,const fe448*); +WOLFSSL_LOCAL void fe448_sqr(fe448*, const fe448*); +WOLFSSL_LOCAL void fe448_mul39081(fe448*, const fe448*); +WOLFSSL_LOCAL void fe448_invert(fe448*, const fe448*); + +WOLFSSL_LOCAL void fe448_0(fe448*); +WOLFSSL_LOCAL void fe448_1(fe448*); +WOLFSSL_LOCAL void fe448_copy(fe448*, const fe448*); +WOLFSSL_LOCAL int fe448_isnonzero(const fe448*); +WOLFSSL_LOCAL int fe448_isnegative(const fe448*); + +WOLFSSL_LOCAL void fe448_from_bytes(fe448*,const unsigned char *); +WOLFSSL_LOCAL void fe448_to_bytes(unsigned char *, const fe448*); + +WOLFSSL_LOCAL void fe448_cmov(fe448*,const fe448*, int); +WOLFSSL_LOCAL void fe448_pow_2_446_222_1(fe448*,const fe448*); + +#else + +WOLFSSL_LOCAL void fe448_init(void); +WOLFSSL_LOCAL int curve448(byte* r, const byte* n, const byte* a); + +#define fe448_reduce(a) +WOLFSSL_LOCAL void fe448_neg(uint8_t*,const uint8_t*); +WOLFSSL_LOCAL void fe448_add(uint8_t*, const uint8_t*, const uint8_t*); +WOLFSSL_LOCAL void fe448_sub(uint8_t*, const uint8_t*, const uint8_t*); +WOLFSSL_LOCAL void fe448_mul(uint8_t*,const uint8_t*,const uint8_t*); +WOLFSSL_LOCAL void fe448_sqr(uint8_t*, const uint8_t*); +WOLFSSL_LOCAL void fe448_mul39081(uint8_t*, const uint8_t*); +WOLFSSL_LOCAL void fe448_invert(uint8_t*, const uint8_t*); + +WOLFSSL_LOCAL void fe448_copy(uint8_t*, const uint8_t*); +WOLFSSL_LOCAL int fe448_isnonzero(const uint8_t*); + +WOLFSSL_LOCAL void fe448_norm(byte *a); + +WOLFSSL_LOCAL void fe448_cmov(uint8_t*,const uint8_t*, int); +WOLFSSL_LOCAL void fe448_pow_2_446_222_1(uint8_t*,const uint8_t*); + +#endif /* !CURVE448_SMALL || !ED448_SMALL */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_CURVE448 || HAVE_ED448 */ + +#endif /* WOLF_CRYPT_FE_448_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fe_operations.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fe_operations.h index a779f2be7..336da81c6 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fe_operations.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fe_operations.h @@ -1,8 +1,8 @@ /* fe_operations.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLF_CRYPT_FE_OPERATIONS_H #define WOLF_CRYPT_FE_OPERATIONS_H @@ -26,11 +27,31 @@ #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 + +#if defined(CURVED25519_X64) + #define CURVED25519_ASM_64BIT + #define CURVED25519_ASM +#endif +#if defined(WOLFSSL_ARMASM) + #ifdef __aarch64__ + #define CURVED25519_ASM_64BIT + #else + #define CURVED25519_ASM_32BIT + #endif + #define CURVED25519_ASM +#endif + /* fe means field element. Here the field is \Z/(2^255-19). @@ -39,14 +60,41 @@ 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]; +#ifdef __cplusplus + extern "C" { +#endif + +#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_ASM_64BIT + typedef int64_t fe[4]; +#elif defined(CURVED25519_ASM_32BIT) + typedef int32_t fe[8]; +#elif defined(CURVED25519_128BIT) + typedef int64_t fe[5]; #else typedef int32_t fe[10]; #endif -WOLFSSL_LOCAL int curve25519(byte * q, byte * n, byte * p); 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); @@ -54,8 +102,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. */ @@ -68,19 +114,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_ASM +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_ASM */ +#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}; @@ -93,7 +165,7 @@ WOLFSSL_LOCAL void fe_inv__distinct(byte *r, const byte *x); /* Conditional copy. If condition == 0, then zero is copied to dst. If * condition == 1, then one is copied to dst. Any other value results in - * undefined behaviour. + * undefined behavior. */ WOLFSSL_LOCAL void fe_select(byte *dst, const byte *zero, const byte *one, byte condition); @@ -117,7 +189,7 @@ WOLFSSL_LOCAL void fe_sqrt(byte *r, const byte *x); /* Conditional copy. If condition == 0, then zero is copied to dst. If * condition == 1, then one is copied to dst. Any other value results in - * undefined behaviour. + * undefined behavior. */ WOLFSSL_LOCAL void fprime_select(byte *dst, const byte *zero, const byte *one, byte condition); @@ -126,7 +198,13 @@ 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 */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_CURVE25519 || HAVE_ED25519 */ + +#endif /* WOLF_CRYPT_FE_OPERATIONS_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fips.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fips.h new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fips_test.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fips_test.h index 6ef06788f..a78b074c4 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fips_test.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/fips_test.h @@ -1,8 +1,8 @@ /* fips_test.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,14 +16,15 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLF_CRYPT_FIPS_TEST_H #define WOLF_CRYPT_FIPS_TEST_H -#include +#include #ifdef __cplusplus @@ -31,22 +32,22 @@ #endif /* Known Answer Test string inputs are hex, internal */ -CYASSL_LOCAL int DoKnownAnswerTests(char*, int); +WOLFSSL_LOCAL int DoKnownAnswerTests(char*, int); /* FIPS failure callback */ typedef void(*wolfCrypt_fips_cb)(int ok, int err, const char* hash); /* Public set function */ -CYASSL_API int wolfCrypt_SetCb_fips(wolfCrypt_fips_cb cbf); +WOLFSSL_API int wolfCrypt_SetCb_fips(wolfCrypt_fips_cb cbf); /* Public get status functions */ -CYASSL_API int wolfCrypt_GetStatus_fips(void); -CYASSL_API const char* wolfCrypt_GetCoreHash_fips(void); +WOLFSSL_API int wolfCrypt_GetStatus_fips(void); +WOLFSSL_API const char* wolfCrypt_GetCoreHash_fips(void); #ifdef HAVE_FORCE_FIPS_FAILURE /* Public function to force failure mode for operational testing */ - CYASSL_API int wolfCrypt_SetStatus_fips(int); + WOLFSSL_API int wolfCrypt_SetStatus_fips(int); #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ge_448.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ge_448.h new file mode 100644 index 000000000..51cb02af6 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ge_448.h @@ -0,0 +1,86 @@ +/* ge_448.h + * + * Copyright (C) 2006-2020 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_GE_448_H +#define WOLF_CRYPT_GE_448_H + +#include + +#ifdef HAVE_ED448 + +#include + +/* +ge448 means group element. + +Here the group is the set of pairs (x,y) of field elements (see fe.h) +satisfying -x^2 + y^2 = 1 + d x^2y^2 +where d = -39081. + +Representations: + ge448_p2 (projective) : (X:Y:Z) satisfying x=X/Z, y=Y/Z + ge448_precomp (affine): (x,y) +*/ + +#ifdef ED448_SMALL + typedef byte ge448; + #define GE448_WORDS 56 +#elif defined(CURVED448_128BIT) + typedef int64_t ge448; + #define GE448_WORDS 8 +#else + typedef int32_t ge448; + #define GE448_WORDS 16 +#endif + +typedef struct { + ge448 X[GE448_WORDS]; + ge448 Y[GE448_WORDS]; + ge448 Z[GE448_WORDS]; +} ge448_p2; + + +WOLFSSL_LOCAL int ge448_compress_key(byte*, const byte*, const byte*); +WOLFSSL_LOCAL int ge448_from_bytes_negate_vartime(ge448_p2 *, + const unsigned char *); + +WOLFSSL_LOCAL int ge448_double_scalarmult_vartime(ge448_p2 *, + const unsigned char *, + const ge448_p2 *, + const unsigned char *); +WOLFSSL_LOCAL void ge448_scalarmult_base(ge448_p2 *, const unsigned char *); +WOLFSSL_LOCAL void sc448_reduce(byte*); +WOLFSSL_LOCAL void sc448_muladd(byte*, const byte*, const byte*, const byte*); +WOLFSSL_LOCAL void ge448_to_bytes(unsigned char *, const ge448_p2 *); + + +#ifndef ED448_SMALL +typedef struct { + ge448 x[GE448_WORDS]; + ge448 y[GE448_WORDS]; +} ge448_precomp; + +#endif /* !ED448_SMALL */ + +#endif /* HAVE_ED448 */ + +#endif /* WOLF_CRYPT_GE_448_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ge_operations.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ge_operations.h index 00d1b3edc..9d89c0ac7 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ge_operations.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ge_operations.h @@ -1,8 +1,8 @@ /* ge_operations.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. */ #ifndef WOLF_CRYPT_GE_OPERATIONS_H @@ -28,9 +29,6 @@ #ifdef HAVE_ED25519 -#ifndef CURVED25519_SMALL - #include -#endif #include /* @@ -47,20 +45,32 @@ Representations: ge_precomp (Duif): (y+x,y-x,2dxy) */ +#ifdef ED25519_SMALL + typedef byte ge[F25519_SIZE]; +#elif defined(CURVED25519_ASM_64BIT) + typedef int64_t ge[4]; +#elif defined(CURVED25519_ASM_32BIT) + typedef int32_t ge[8]; +#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 *); @@ -74,42 +84,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/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/hash.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/hash.h index ad1062809..73222cab9 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/hash.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/hash.h @@ -1,8 +1,8 @@ /* hash.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,26 +16,232 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/hash.h +*/ + #ifndef WOLF_CRYPT_HASH_H #define WOLF_CRYPT_HASH_H +#include + #ifndef NO_MD5 -#include -WOLFSSL_API void wc_Md5GetHash(Md5*, byte*); -WOLFSSL_API void wc_Md5RestorePos(Md5*, Md5*) ; + #include #endif #ifndef NO_SHA -#include -WOLFSSL_API int wc_ShaGetHash(Sha*, byte*); -WOLFSSL_API void wc_ShaRestorePos(Sha*, Sha*) ; + #include #endif -#ifndef NO_SHA256 -#include -WOLFSSL_API int wc_Sha256GetHash(Sha256*, byte*); -WOLFSSL_API void wc_Sha256RestorePos(Sha256*, Sha256*) ; +#if defined(WOLFSSL_SHA224) || !defined(NO_SHA256) + #include +#endif +#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) + #include +#endif +#ifdef HAVE_BLAKE2 + #include +#endif +#ifdef WOLFSSL_SHA3 + #include +#endif +#ifndef NO_MD4 + #include +#endif +#ifdef WOLFSSL_MD2 + #include +#endif +#if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) + #include #endif + +#ifdef __cplusplus + extern "C" { #endif + +#if !defined(HAVE_FIPS) && !defined(NO_OLD_WC_NAMES) + #define MAX_DIGEST_SIZE WC_MAX_DIGEST_SIZE +#endif + + +/* Supported Message Authentication Codes from page 43 */ +enum wc_MACAlgorithm { + no_mac, + md5_mac, + sha_mac, + sha224_mac, + sha256_mac, /* needs to match external KDF_MacAlgorithm */ + sha384_mac, + sha512_mac, + rmd_mac, + blake2b_mac +}; + +enum wc_HashFlags { + WC_HASH_FLAG_NONE = 0x00000000, + WC_HASH_FLAG_WILLCOPY = 0x00000001, /* flag to indicate hash will be copied */ + WC_HASH_FLAG_ISCOPY = 0x00000002, /* hash is copy */ +#ifdef WOLFSSL_SHA3 + WC_HASH_SHA3_KECCAK256 =0x00010000, /* Older KECCAK256 */ +#endif +}; + + +typedef union { + #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_SHA384 + wc_Sha384 sha384; + #endif + #ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; + #endif + #ifdef WOLFSSL_SHA3 + wc_Sha3 sha3; + #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_SHA3) + #define WC_MAX_DIGEST_SIZE WC_SHA3_512_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA3_224_BLOCK_SIZE /* 224 is the largest block size */ +#elif defined(WOLFSSL_SHA512) + #define WC_MAX_DIGEST_SIZE WC_SHA512_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA512_BLOCK_SIZE +#elif defined(HAVE_BLAKE2) + #define WC_MAX_DIGEST_SIZE BLAKE2B_OUTBYTES + #define WC_MAX_BLOCK_SIZE BLAKE2B_BLOCKBYTES +#elif defined(WOLFSSL_SHA384) + #define WC_MAX_DIGEST_SIZE WC_SHA384_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA384_BLOCK_SIZE +#elif !defined(NO_SHA256) + #define WC_MAX_DIGEST_SIZE WC_SHA256_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA256_BLOCK_SIZE +#elif defined(WOLFSSL_SHA224) + #define WC_MAX_DIGEST_SIZE WC_SHA224_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA224_BLOCK_SIZE +#elif !defined(NO_SHA) + #define WC_MAX_DIGEST_SIZE WC_SHA_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA_BLOCK_SIZE +#elif !defined(NO_MD5) + #define WC_MAX_DIGEST_SIZE WC_MD5_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_MD5_BLOCK_SIZE +#else + #define WC_MAX_DIGEST_SIZE 64 /* default to max size of 64 */ + #define WC_MAX_BLOCK_SIZE 128 +#endif + +#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) +WOLFSSL_API int wc_HashGetOID(enum wc_HashType hash_type); +WOLFSSL_API enum wc_HashType wc_OidGetHash(int oid); +#endif + +WOLFSSL_API enum wc_HashType wc_HashTypeConvert(int hashType); + +WOLFSSL_API int wc_HashGetDigestSize(enum wc_HashType hash_type); +WOLFSSL_API int wc_HashGetBlockSize(enum wc_HashType hash_type); +WOLFSSL_API int wc_Hash(enum wc_HashType hash_type, + const byte* data, word32 data_len, + byte* hash, word32 hash_len); + +/* generic hash operation wrappers */ +WOLFSSL_API int wc_HashInit_ex(wc_HashAlg* hash, enum wc_HashType type, + void* heap, int devId); +WOLFSSL_API int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type); +WOLFSSL_API int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, + const byte* data, word32 dataSz); +WOLFSSL_API int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, + byte* out); +WOLFSSL_API int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type); + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_API int wc_HashSetFlags(wc_HashAlg* hash, enum wc_HashType type, + word32 flags); + WOLFSSL_API int wc_HashGetFlags(wc_HashAlg* hash, enum wc_HashType type, + word32* flags); +#endif + +#ifndef NO_MD5 +#include +WOLFSSL_API int wc_Md5Hash(const byte* data, word32 len, byte* hash); +#endif + +#ifndef NO_SHA +#include +WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); +#endif + +#ifdef WOLFSSL_SHA224 +#include +WOLFSSL_API int wc_Sha224Hash(const byte*, word32, byte*); +#endif /* defined(WOLFSSL_SHA224) */ + +#ifndef NO_SHA256 +#include +WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*); +#endif + +#ifdef WOLFSSL_SHA384 +#include +WOLFSSL_API int wc_Sha384Hash(const byte*, word32, byte*); +#endif /* defined(WOLFSSL_SHA384) */ + +#ifdef WOLFSSL_SHA512 +#include +WOLFSSL_API int wc_Sha512Hash(const byte*, word32, byte*); +#endif /* WOLFSSL_SHA512 */ + +#ifdef WOLFSSL_SHA3 +#include +WOLFSSL_API int wc_Sha3_224Hash(const byte*, word32, byte*); +WOLFSSL_API int wc_Sha3_256Hash(const byte*, word32, byte*); +WOLFSSL_API int wc_Sha3_384Hash(const byte*, word32, byte*); +WOLFSSL_API int wc_Sha3_512Hash(const byte*, word32, byte*); +#ifdef WOLFSSL_SHAKE256 +WOLFSSL_API int wc_Shake256Hash(const byte*, word32, byte*, word32); +#endif +#endif /* WOLFSSL_SHA3 */ + +enum max_prf { +#ifdef HAVE_FFDHE_8192 + MAX_PRF_HALF = 516, /* Maximum half secret len */ +#elif defined(HAVE_FFDHE_6144) + MAX_PRF_HALF = 388, /* Maximum half secret len */ +#else + MAX_PRF_HALF = 260, /* Maximum half secret len */ +#endif + MAX_PRF_LABSEED = 128, /* Maximum label + seed len */ + MAX_PRF_DIG = 224 /* Maximum digest len */ +}; + +#ifdef WOLFSSL_HAVE_PRF +WOLFSSL_API int wc_PRF(byte* result, word32 resLen, const byte* secret, + word32 secLen, const byte* seed, word32 seedLen, int hash, + void* heap, int devId); +WOLFSSL_API int wc_PRF_TLSv1(byte* digest, word32 digLen, const byte* secret, + word32 secLen, const byte* label, word32 labLen, + const byte* seed, word32 seedLen, void* heap, int devId); +WOLFSSL_API int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, + word32 secLen, const byte* label, word32 labLen, + const byte* seed, word32 seedLen, int useAtLeastSha256, + int hash_type, void* heap, int devId); +#endif /* WOLFSSL_HAVE_PRF */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_HASH_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/hc128.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/hc128.h index ba53dd3d5..19906be72 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/hc128.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/hc128.h @@ -1,8 +1,8 @@ /* hc128.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/hc128.h +*/ + + #ifndef WOLF_CRYPT_HC128_H #define WOLF_CRYPT_HC128_H @@ -31,7 +36,7 @@ #endif enum { - HC128_ENC_TYPE = 6 /* cipher unique type */ + HC128_ENC_TYPE = WC_CIPHER_HC128, /* cipher unique type */ }; /* HC-128 stream cipher */ @@ -42,12 +47,16 @@ typedef struct HC128 { word32 counter1024; /* counter1024 = i mod 1024 at the ith step */ word32 key[8]; word32 iv[8]; +#ifdef XSTREAM_ALIGN + void* heap; /* heap hint, currently XMALLOC only used with aligning */ +#endif } HC128; WOLFSSL_API int wc_Hc128_Process(HC128*, byte*, const byte*, word32); WOLFSSL_API int wc_Hc128_SetKey(HC128*, const byte* key, const byte* iv); +WOLFSSL_LOCAL int wc_Hc128_SetHeap(HC128* ctx, void* heap); #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/hmac.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/hmac.h index 2be5afcee..f6744db64 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/hmac.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/hmac.h @@ -1,8 +1,8 @@ /* hmac.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,53 +16,51 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/hmac.h +*/ #ifndef NO_HMAC #ifndef WOLF_CRYPT_HMAC_H #define WOLF_CRYPT_HMAC_H -#include +#include -#ifndef NO_MD5 - #include -#endif - -#ifndef NO_SHA - #include -#endif - -#ifndef NO_SHA256 - #include -#endif - -#ifdef WOLFSSL_SHA512 - #include -#endif - -#ifdef HAVE_BLAKE2 - #include -#endif - -#ifdef HAVE_FIPS -/* for fips */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +/* for fips @wc_fips */ #include + #define WC_HMAC_BLOCK_SIZE HMAC_BLOCK_SIZE #endif -#ifdef HAVE_CAVIUM - #include - #include "cavium_common.h" -#endif +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif #ifdef __cplusplus extern "C" { #endif -#ifndef HAVE_FIPS -#define WOLFSSL_HMAC_CAVIUM_MAGIC 0xBEEF0005 + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifndef NO_OLD_WC_NAMES + #define HMAC_BLOCK_SIZE WC_HMAC_BLOCK_SIZE +#endif + +#define WC_HMAC_INNER_HASH_KEYED_SW 1 +#define WC_HMAC_INNER_HASH_KEYED_DEV 2 enum { HMAC_FIPS_MIN_KEY = 14, /* 112 bit key length minimum */ @@ -72,89 +70,100 @@ enum { /* If any hash is not enabled, add the ID here. */ #ifdef NO_MD5 - MD5 = 0, + WC_MD5 = WC_HASH_TYPE_MD5, #endif #ifdef NO_SHA - SHA = 1, + WC_SHA = WC_HASH_TYPE_SHA, #endif #ifdef NO_SHA256 - SHA256 = 2, + WC_SHA256 = WC_HASH_TYPE_SHA256, #endif #ifndef WOLFSSL_SHA512 - SHA512 = 4, + WC_SHA512 = WC_HASH_TYPE_SHA512, #endif #ifndef WOLFSSL_SHA384 - SHA384 = 5, + WC_SHA384 = WC_HASH_TYPE_SHA384, #endif -#ifndef HAVE_BLAKE2 - BLAKE2B_ID = 7, +#ifndef WOLFSSL_SHA224 + WC_SHA224 = WC_HASH_TYPE_SHA224, #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 -#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 -#elif !defined(NO_SHA256) - MAX_DIGEST_SIZE = SHA256_DIGEST_SIZE, - HMAC_BLOCK_SIZE = SHA256_BLOCK_SIZE -#elif !defined(NO_SHA) - MAX_DIGEST_SIZE = SHA_DIGEST_SIZE, - HMAC_BLOCK_SIZE = SHA_BLOCK_SIZE -#elif !defined(NO_MD5) - MAX_DIGEST_SIZE = MD5_DIGEST_SIZE, - HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE -#else - #error "You have to have some kind of hash if you want to use HMAC." +#ifndef WOLFSSL_SHA3 + WC_SHA3_224 = WC_HASH_TYPE_SHA3_224, + WC_SHA3_256 = WC_HASH_TYPE_SHA3_256, + WC_SHA3_384 = WC_HASH_TYPE_SHA3_384, + WC_SHA3_512 = WC_HASH_TYPE_SHA3_512, +#endif +#ifdef HAVE_PKCS11 + HMAC_MAX_ID_LEN = 32, #endif }; +/* Select the largest available hash for the buffer size. */ +#define WC_HMAC_BLOCK_SIZE WC_MAX_BLOCK_SIZE + +#if !defined(WOLFSSL_SHA3) && !defined(WOLFSSL_SHA512) && \ + !defined(WOLFSSL_SHA384) && defined(NO_SHA256) && \ + defined(WOLFSSL_SHA224) && defined(NO_SHA) && defined(NO_MD5) + #error "You have to have some kind of hash if you want to use HMAC." +#endif + /* hash union */ typedef union { - #ifndef NO_MD5 - Md5 md5; - #endif - #ifndef NO_SHA - Sha sha; - #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_SHA384 + wc_Sha384 sha384; +#endif +#ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; +#endif +#ifdef WOLFSSL_SHA3 + wc_Sha3 sha3; +#endif } Hash; /* Hmac digest */ -typedef struct Hmac { +struct Hmac { Hash hash; - word32 ipad[HMAC_BLOCK_SIZE / sizeof(word32)]; /* same block size all*/ - word32 opad[HMAC_BLOCK_SIZE / sizeof(word32)]; - word32 innerHash[MAX_DIGEST_SIZE / sizeof(word32)]; - byte macType; /* md5 sha or sha256 */ - byte innerHashKeyed; /* keyed flag */ -#ifdef HAVE_CAVIUM - word16 keyLen; /* hmac key length */ - word16 dataLen; - HashType type; /* hmac key type */ - int devId; /* nitrox device id */ - word32 magic; /* using cavium magic */ - word64 contextHandle; /* nitrox context memory handle */ - byte* data; /* buffered input data for one call */ + word32 ipad[WC_HMAC_BLOCK_SIZE / sizeof(word32)]; /* same block size all*/ + word32 opad[WC_HMAC_BLOCK_SIZE / sizeof(word32)]; + word32 innerHash[WC_MAX_DIGEST_SIZE / sizeof(word32)]; + void* heap; /* heap hint */ + byte macType; /* md5 sha or sha256 */ + byte innerHashKeyed; /* keyed flag */ +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLF_CRYPTO_CB + int devId; + void* devCtx; + const byte* keyRaw; #endif -} Hmac; +#ifdef HAVE_PKCS11 + byte id[HMAC_MAX_ID_LEN]; + int idLen; +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + word16 keyLen; /* hmac key length (key in ipad) */ +#endif +}; + +#ifndef WC_HMAC_TYPE_DEFINED + typedef struct Hmac Hmac; + #define WC_HMAC_TYPE_DEFINED +#endif + #endif /* HAVE_FIPS */ @@ -162,17 +171,25 @@ typedef struct Hmac { 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 HAVE_CAVIUM - WOLFSSL_API int wc_HmacInitCavium(Hmac*, int); - WOLFSSL_API void wc_HmacFreeCavium(Hmac*); -#endif +WOLFSSL_API int wc_HmacInit(Hmac* hmac, void* heap, int devId); +WOLFSSL_API int wc_HmacInit_Id(Hmac* hmac, byte* id, int len, void* heap, + int devId); +WOLFSSL_API void wc_HmacFree(Hmac*); WOLFSSL_API int wolfSSL_GetHmacMaxSize(void); +WOLFSSL_LOCAL int _InitHmac(Hmac* hmac, int type, void* heap); #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/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/idea.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/idea.h new file mode 100644 index 000000000..8dbffb237 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/idea.h @@ -0,0 +1,70 @@ +/* idea.h + * + * Copyright (C) 2006-2020 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 + */ + +/*! + \file wolfssl/wolfcrypt/idea.h +*/ + +#ifndef WOLF_CRYPT_IDEA_H +#define WOLF_CRYPT_IDEA_H + +#include + +#ifdef HAVE_IDEA + +#ifdef __cplusplus + extern "C" { +#endif + +enum { + IDEA_MODULO = 0x10001, /* 2^16+1 */ + IDEA_2EXP16 = 0x10000, /* 2^16 */ + IDEA_MASK = 0xFFFF, /* 16 bits set to one */ + IDEA_ROUNDS = 8, /* number of rounds for IDEA */ + IDEA_SK_NUM = (6*IDEA_ROUNDS + 4), /* number of subkeys */ + IDEA_KEY_SIZE = 16, /* size of key in bytes */ + IDEA_BLOCK_SIZE = 8, /* size of IDEA blocks in bytes */ + IDEA_IV_SIZE = 8, /* size of IDEA IV in bytes */ + IDEA_ENCRYPTION = 0, + IDEA_DECRYPTION = 1 +}; + +/* IDEA encryption and decryption */ +typedef struct Idea { + word32 reg[IDEA_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ + word32 tmp[IDEA_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ + word16 skey[IDEA_SK_NUM]; /* 832 bits expanded key */ +} 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 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, + const byte* in, word32 len); +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_IDEA */ +#endif /* WOLF_CRYPT_IDEA_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/include.am b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/include.am index 1f3a726b8..0df704636 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/include.am +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/include.am @@ -8,6 +8,7 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/asn_public.h \ wolfssl/wolfcrypt/poly1305.h \ wolfssl/wolfcrypt/camellia.h \ + wolfssl/wolfcrypt/cmac.h \ wolfssl/wolfcrypt/coding.h \ wolfssl/wolfcrypt/compress.h \ wolfssl/wolfcrypt/des3.h \ @@ -18,6 +19,10 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/ed25519.h \ wolfssl/wolfcrypt/fe_operations.h \ wolfssl/wolfcrypt/ge_operations.h \ + wolfssl/wolfcrypt/curve448.h \ + wolfssl/wolfcrypt/ed448.h \ + wolfssl/wolfcrypt/fe_448.h \ + wolfssl/wolfcrypt/ge_448.h \ wolfssl/wolfcrypt/error-crypt.h \ wolfssl/wolfcrypt/fips_test.h \ wolfssl/wolfcrypt/hash.h \ @@ -29,6 +34,7 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/md5.h \ wolfssl/wolfcrypt/misc.h \ wolfssl/wolfcrypt/pkcs7.h \ + wolfssl/wolfcrypt/wc_encrypt.h \ wolfssl/wolfcrypt/wc_port.h \ wolfssl/wolfcrypt/pwdbased.h \ wolfssl/wolfcrypt/rabbit.h \ @@ -41,19 +47,95 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/sha256.h \ wolfssl/wolfcrypt/sha512.h \ wolfssl/wolfcrypt/sha.h \ + wolfssl/wolfcrypt/signature.h \ wolfssl/wolfcrypt/blake2.h \ wolfssl/wolfcrypt/blake2-int.h \ wolfssl/wolfcrypt/blake2-impl.h \ wolfssl/wolfcrypt/tfm.h \ + wolfssl/wolfcrypt/srp.h \ + wolfssl/wolfcrypt/idea.h \ wolfssl/wolfcrypt/types.h \ wolfssl/wolfcrypt/visibility.h \ wolfssl/wolfcrypt/logging.h \ wolfssl/wolfcrypt/memory.h \ wolfssl/wolfcrypt/mpi_class.h \ - wolfssl/wolfcrypt/mpi_superclass.h + wolfssl/wolfcrypt/mpi_superclass.h \ + wolfssl/wolfcrypt/mem_track.h \ + wolfssl/wolfcrypt/wolfevent.h \ + wolfssl/wolfcrypt/pkcs12.h \ + wolfssl/wolfcrypt/wolfmath.h \ + wolfssl/wolfcrypt/sha3.h \ + wolfssl/wolfcrypt/cpuid.h \ + wolfssl/wolfcrypt/cryptocb.h noinst_HEADERS+= \ wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \ wolfssl/wolfcrypt/port/ti/ti-hash.h \ - wolfssl/wolfcrypt/port/ti/ti-ccm.h + wolfssl/wolfcrypt/port/ti/ti-ccm.h \ + wolfssl/wolfcrypt/port/nrf51.h \ + wolfssl/wolfcrypt/port/nxp/ksdk_port.h \ + wolfssl/wolfcrypt/port/xilinx/xil-sha3.h \ + wolfssl/wolfcrypt/port/caam/caam_driver.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h \ + wolfssl/wolfcrypt/port/st/stm32.h \ + wolfssl/wolfcrypt/port/st/stsafe.h \ + wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h \ + wolfssl/wolfcrypt/port/arm/cryptoCell.h \ + wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h +if BUILD_CRYPTOAUTHLIB +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/atmel/atmel.h +endif + +if BUILD_AFALG +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/af_alg/afalg_hash.h +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/af_alg/wc_afalg.h +endif + +if BUILD_DEVCRYPTO +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h +endif + +if BUILD_ASYNCCRYPT +nobase_include_HEADERS+= wolfssl/wolfcrypt/async.h +endif + +if BUILD_PKCS11 +nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_pkcs11.h +nobase_include_HEADERS+= wolfssl/wolfcrypt/pkcs11.h +endif + +if BUILD_CAVIUM +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h +endif + +if BUILD_OCTEON_SYNC +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.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_INTEL_QA_SYNC +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/intel/quickassist_sync.h +endif + +if BUILD_SP +nobase_include_HEADERS+= wolfssl/wolfcrypt/sp.h +nobase_include_HEADERS+= wolfssl/wolfcrypt/sp_int.h +endif + +if BUILD_SELFTEST +nobase_include_HEADERS+= wolfssl/wolfcrypt/selftest.h +endif + +if BUILD_FIPS_V2 +nobase_include_HEADERS+= wolfssl/wolfcrypt/fips.h +endif + +if BUILD_FIPS_RAND +nobase_include_HEADERS+= wolfssl/wolfcrypt/fips.h +endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/integer.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/integer.h index b623298ed..03ea908c3 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/integer.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/integer.h @@ -1,8 +1,8 @@ /* integer.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* * Based on public domain LibTomMath 0.38 by Tom St Denis, tomstdenis@iahu.ca, * http://math.libtomcrypt.com @@ -32,23 +33,20 @@ may not be faster on all */ #include /* will set MP_xxBIT if not default */ -#ifdef USE_FAST_MATH +#ifdef WOLFSSL_SP_MATH + #include +#elif defined(USE_FAST_MATH) #include #else +#include + #ifndef CHAR_BIT #include #endif #include -#ifndef MIN - #define MIN(x,y) ((x)<(y)?(x):(y)) -#endif - -#ifndef MAX - #define MAX(x,y) ((x)>(y)?(x):(y)) -#endif #ifdef __cplusplus extern "C" { @@ -56,16 +54,21 @@ extern "C" { /* C++ compilers don't like assigning void * to mp_digit * */ #define OPT_CAST(x) (x *) +#elif defined(_SH3) + +/* SuperH SH3 compiler doesn't like assigning voi* to mp_digit* */ +#define OPT_CAST(x) (x *) + #else /* C on the other hand doesn't care */ #define OPT_CAST(x) -#endif +#endif /* __cplusplus */ /* detect 64-bit mode if possible */ -#if defined(__x86_64__) +#if defined(__x86_64__) && !(defined (_MSC_VER) && defined(__clang__)) #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT)) #define MP_64BIT #endif @@ -75,6 +78,10 @@ extern "C" { #undef MP_64BIT #endif + +/* allow user to define on mp_digit, mp_word, DIGIT_BIT types */ +#ifndef WOLFSSL_BIGINT_TYPES + /* some default configurations. * * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits @@ -84,19 +91,28 @@ extern "C" { * [any size beyond that is ok provided it doesn't overflow the data type] */ #ifdef MP_8BIT + /* 8-bit */ typedef unsigned char mp_digit; typedef unsigned short mp_word; -#elif defined(MP_16BIT) || defined(NO_64BIT) + /* don't define DIGIT_BIT, so its calculated below */ +#elif defined(MP_16BIT) + /* 16-bit */ + typedef unsigned int mp_digit; + typedef unsigned long mp_word; + /* don't define DIGIT_BIT, so its calculated below */ +#elif defined(NO_64BIT) + /* 32-bit forced to 16-bit */ typedef unsigned short mp_digit; typedef unsigned int mp_word; + #define DIGIT_BIT 12 #elif defined(MP_64BIT) + /* 64-bit */ /* for GCC only on supported platforms */ typedef unsigned long long mp_digit; /* 64 bit type, 128 uses mode(TI) */ typedef unsigned long mp_word __attribute__ ((mode(TI))); - #define DIGIT_BIT 60 #else - /* this is the default case, 28-bit digits */ + /* 32-bit default case */ #if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 ulong64; @@ -107,16 +123,17 @@ extern "C" { typedef unsigned int mp_digit; /* long could be 64 now, changed TAO */ typedef ulong64 mp_word; -#ifdef MP_31BIT - /* this is an extension that uses 31-bit digits */ - #define DIGIT_BIT 31 -#else - /* default case is 28-bit digits, defines MP_28BIT as a handy test macro */ - #define DIGIT_BIT 28 - #define MP_28BIT -#endif + #ifdef MP_31BIT + /* this is an extension that uses 31-bit digits */ + #define DIGIT_BIT 31 + #else + /* default case is 28-bit digits, defines MP_28BIT as a handy test macro */ + #define DIGIT_BIT 28 + #define MP_28BIT + #endif #endif +#endif /* WOLFSSL_BIGINT_TYPES */ /* otherwise the bits per digit is calculated automatically from the size of a mp_digit */ @@ -140,7 +157,8 @@ extern "C" { #define MP_OKAY 0 /* ok result */ #define MP_MEM -2 /* out of mem */ #define MP_VAL -3 /* invalid input */ -#define MP_RANGE MP_VAL +#define MP_NOT_INF -4 /* point not at infinity */ +#define MP_RANGE MP_NOT_INF #define MP_YES 1 /* yes response */ #define MP_NO 0 /* no response */ @@ -166,16 +184,34 @@ typedef int mp_err; /* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ -#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) +#define MP_WARRAY ((mp_word)1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) -/* the infamous mp_int structure */ -typedef struct { +#ifdef HAVE_WOLF_BIGINT + /* raw big integer */ + typedef struct WC_BIGINT { + byte* buf; + word32 len; + void* heap; + } WC_BIGINT; + #define WOLF_BIGINT_DEFINED +#endif + +/* the mp_int structure */ +typedef struct mp_int { int used, alloc, sign; mp_digit *dp; + +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT raw; /* unsigned binary (big endian) */ +#endif } mp_int; +/* wolf big int and common functions */ +#include + + /* callback for mp_prime_random, should fill dst with random bytes and return - how many read [upto len] */ + how many read [up to len] */ typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); @@ -186,11 +222,16 @@ typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); /* ---> Basic Manipulations <--- */ #define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) +#define mp_isone(a) \ + (((((a)->used == 1)) && ((a)->dp[0] == 1u)) ? MP_YES : MP_NO) #define mp_iseven(a) \ - (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) + (((a)->used > 0 && (((a)->dp[0] & 1u) == 0u)) ? MP_YES : MP_NO) #define mp_isodd(a) \ - (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) - + (((a)->used > 0 && (((a)->dp[0] & 1u) == 1u)) ? MP_YES : MP_NO) +#define mp_isneg(a) (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO) +#define mp_isword(a, w) \ + ((((a)->used == 1) && ((a)->dp[0] == w)) || ((w == 0) && ((a)->used == 0)) \ + ? MP_YES : MP_NO) /* number of primes */ #ifdef MP_8BIT @@ -199,6 +240,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) @@ -209,109 +258,145 @@ 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); -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_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c); +MP_API int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); +MP_API int mp_exptmod_ex (mp_int * G, mp_int * X, int digits, 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_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_exptmod_base_2 (mp_int * X, mp_int * P, mp_int * Y); +#define mp_exptmod_nct(G,X,P,Y) mp_exptmod_fast(G,X,P,Y,0) +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_mul_d (mp_int * a, mp_digit b, mp_int * c); -int mp_2expt (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); +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); -#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) - int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); -#endif -#ifdef HAVE_ECC - int mp_read_radix(mp_int* a, const char* str, int radix); +#ifdef WOLFSSL_DEBUG_MATH + 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) || !defined(NO_RSA) || \ + !defined(NO_DSA) || !defined(NO_DH) + MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); +#endif +#if !defined(NO_DSA) || defined(HAVE_ECC) + MP_API int mp_read_radix(mp_int* a, const char* str, int radix); +#endif + +#if defined(WOLFSSL_KEY_GEN) || !defined(NO_RSA) || !defined(NO_DSA) || !defined(NO_DH) + MP_API int mp_prime_is_prime (mp_int * a, int t, int *result); + MP_API int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG*); +#endif /* WOLFSSL_KEY_GEN NO_RSA NO_DSA NO_DH */ #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); + 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); + #ifdef __cplusplus } diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/logging.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/logging.h index 0b124835b..3dcd7de29 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/logging.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/logging.h @@ -1,8 +1,8 @@ /* logging.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/logging.h +*/ + + /* submitted by eof */ @@ -32,7 +37,7 @@ #endif -enum CYA_Log_Levels { +enum wc_LogLevels { ERROR_LOG = 0, INFO_LOG, ENTER_LOG, @@ -40,28 +45,147 @@ enum CYA_Log_Levels { OTHER_LOG }; +#ifdef WOLFSSL_FUNC_TIME +/* WARNING: This code is only to be used for debugging performance. + * The code is not thread-safe. + * Do not use WOLFSSL_FUNC_TIME in production code. + */ +enum wc_FuncNum { + WC_FUNC_HELLO_REQUEST_SEND = 0, + WC_FUNC_HELLO_REQUEST_DO, + WC_FUNC_CLIENT_HELLO_SEND, + WC_FUNC_CLIENT_HELLO_DO, + WC_FUNC_SERVER_HELLO_SEND, + WC_FUNC_SERVER_HELLO_DO, + WC_FUNC_ENCRYPTED_EXTENSIONS_SEND, + WC_FUNC_ENCRYPTED_EXTENSIONS_DO, + WC_FUNC_CERTIFICATE_REQUEST_SEND, + WC_FUNC_CERTIFICATE_REQUEST_DO, + WC_FUNC_CERTIFICATE_SEND, + WC_FUNC_CERTIFICATE_DO, + WC_FUNC_CERTIFICATE_VERIFY_SEND, + WC_FUNC_CERTIFICATE_VERIFY_DO, + WC_FUNC_FINISHED_SEND, + WC_FUNC_FINISHED_DO, + WC_FUNC_KEY_UPDATE_SEND, + WC_FUNC_KEY_UPDATE_DO, + WC_FUNC_EARLY_DATA_SEND, + WC_FUNC_EARLY_DATA_DO, + WC_FUNC_NEW_SESSION_TICKET_SEND, + WC_FUNC_NEW_SESSION_TICKET_DO, + WC_FUNC_SERVER_HELLO_DONE_SEND, + WC_FUNC_SERVER_HELLO_DONE_DO, + WC_FUNC_TICKET_SEND, + WC_FUNC_TICKET_DO, + WC_FUNC_CLIENT_KEY_EXCHANGE_SEND, + WC_FUNC_CLIENT_KEY_EXCHANGE_DO, + WC_FUNC_CERTIFICATE_STATUS_SEND, + WC_FUNC_CERTIFICATE_STATUS_DO, + WC_FUNC_SERVER_KEY_EXCHANGE_SEND, + WC_FUNC_SERVER_KEY_EXCHANGE_DO, + WC_FUNC_END_OF_EARLY_DATA_SEND, + WC_FUNC_END_OF_EARLY_DATA_DO, + WC_FUNC_COUNT +}; +#endif + typedef void (*wolfSSL_Logging_cb)(const int logLevel, - const char *const logMessage); + const char *const logMessage); WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function); +WOLFSSL_API wolfSSL_Logging_cb wolfSSL_GetLoggingCb(void); -#ifdef DEBUG_WOLFSSL +/* turn logging on, only if compiled in */ +WOLFSSL_API int wolfSSL_Debugging_ON(void); +/* turn logging off */ +WOLFSSL_API void wolfSSL_Debugging_OFF(void); - void WOLFSSL_ENTER(const char* msg); - void WOLFSSL_LEAVE(const char* msg, int ret); - void WOLFSSL_ERROR(int); - void WOLFSSL_MSG(const char* msg); +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + WOLFSSL_LOCAL int wc_LoggingInit(void); + WOLFSSL_LOCAL int wc_LoggingCleanup(void); + WOLFSSL_LOCAL int wc_AddErrorNode(int error, int line, char* buf, + 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_LOCAL int wc_PullErrorNode(const char **file, const char **reason, + int *line); + WOLFSSL_API int wc_SetLoggingHeap(void* h); + WOLFSSL_API int wc_ERR_remove_state(void); + #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) + WOLFSSL_API void wc_ERR_print_errors_fp(XFILE fp); + WOLFSSL_API void wc_ERR_print_errors_cb(int (*cb)(const char *str, + size_t len, void *u), void *u); + #endif +#endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */ -#else /* DEBUG_WOLFSSL */ +#ifdef WOLFSSL_FUNC_TIME + /* WARNING: This code is only to be used for debugging performance. + * The code is not thread-safe. + * Do not use WOLFSSL_FUNC_TIME in production code. + */ + WOLFSSL_API void WOLFSSL_START(int funcNum); + WOLFSSL_API void WOLFSSL_END(int funcNum); + WOLFSSL_API void WOLFSSL_TIME(int count); +#else + #define WOLFSSL_START(n) + #define WOLFSSL_END(n) + #define WOLFSSL_TIME(n) +#endif + +#if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_DEBUG_ERRORS_ONLY) + #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 + + WOLFSSL_API void WOLFSSL_ENTER(const char* msg); + WOLFSSL_API void WOLFSSL_LEAVE(const char* msg, int ret); + #define WOLFSSL_STUB(m) \ + WOLFSSL_MSG(WOLFSSL_LOG_CAT(wolfSSL Stub, m, not implemented)) + WOLFSSL_API int WOLFSSL_IS_DEBUG_ON(void); + + WOLFSSL_API void WOLFSSL_MSG(const char* msg); + WOLFSSL_API void WOLFSSL_BUFFER(const byte* buffer, word32 length); + +#else #define WOLFSSL_ENTER(m) #define WOLFSSL_LEAVE(m, r) + #define WOLFSSL_STUB(m) + #define WOLFSSL_IS_DEBUG_ON() 0 - #define WOLFSSL_ERROR(e) #define WOLFSSL_MSG(m) + #define WOLFSSL_BUFFER(b, l) -#endif /* DEBUG_WOLFSSL */ +#endif /* DEBUG_WOLFSSL && !WOLFSSL_DEBUG_ERRORS_ONLY */ + +#if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) ||\ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) + + #if (!defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && !defined(_WIN32))\ + || defined(DEBUG_WOLFSSL_VERBOSE) + WOLFSSL_API 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 + WOLFSSL_API void WOLFSSL_ERROR(int err); + #endif + WOLFSSL_API void WOLFSSL_ERROR_MSG(const char* msg); + +#else + #define WOLFSSL_ERROR(e) + #define WOLFSSL_ERROR_MSG(m) +#endif #ifdef __cplusplus } diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/md2.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/md2.h index d494078b2..565385e73 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/md2.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/md2.h @@ -1,8 +1,8 @@ /* md2.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/md2.h +*/ + + #ifndef WOLF_CRYPT_MD2_H #define WOLF_CRYPT_MD2_H @@ -32,7 +37,7 @@ /* in bytes */ enum { - MD2 = 6, /* hash type unique */ + MD2 = WC_HASH_TYPE_MD2, MD2_BLOCK_SIZE = 16, MD2_DIGEST_SIZE = 16, MD2_PAD_SIZE = 16, diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/md4.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/md4.h index 369e15bc8..1344f8b88 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/md4.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/md4.h @@ -1,8 +1,8 @@ /* md4.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/md4.h +*/ + #ifndef WOLF_CRYPT_MD4_H #define WOLF_CRYPT_MD4_H @@ -32,6 +36,7 @@ /* in bytes */ enum { + MD4 = WC_HASH_TYPE_MD4, MD4_BLOCK_SIZE = 64, MD4_DIGEST_SIZE = 16, MD4_PAD_SIZE = 56 diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/md5.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/md5.h index d0b134b6a..e2ee13c32 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/md5.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/md5.h @@ -1,8 +1,8 @@ /* md5.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/md5.h +*/ + + #ifndef WOLF_CRYPT_MD5_H #define WOLF_CRYPT_MD5_H @@ -37,45 +42,85 @@ 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 { -#ifdef STM32F2_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 = WC_HASH_TYPE_MD5, + 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 STM32_HASH + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include #endif -#ifndef WOLFSSL_TI_HASH +#ifdef WOLFSSL_TI_HASH + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#elif defined(WOLFSSL_IMX6_CAAM) + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" +#else /* MD5 digest */ -typedef struct Md5 { +typedef struct wc_Md5 { +#ifdef STM32_HASH + STM32_HASH_Context stmCtx; +#else 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 descripter */ - #endif -} Md5; + 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 +#endif /* STM32_HASH */ +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + word32 flags; /* enum wc_HashFlags in hash.h */ +#endif +} wc_Md5; -#else /* WOLFSSL_TI_HASH */ - #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#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 -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*); +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_API int wc_Md5SetFlags(wc_Md5* md5, word32 flags); + WOLFSSL_API int wc_Md5GetFlags(wc_Md5* md5, word32* flags); +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/mem_track.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/mem_track.h new file mode 100644 index 000000000..d33e90e60 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/mem_track.h @@ -0,0 +1,401 @@ +/* mem_track.h + * + * Copyright (C) 2006-2020 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 + */ + + +/* The memory tracker overrides the wolfSSL memory callback system and uses a + * static to track the total, peak and currently allocated bytes. + * + * If you are already using the memory callbacks then enabling this will + * override the memory callbacks and prevent your memory callbacks from + * working. This assumes malloc() and free() are available. Feel free to + * customize this for your needs. + + * The enable this feature define the following: + * #define USE_WOLFSSL_MEMORY + * #define WOLFSSL_TRACK_MEMORY + * + * On startup call: + * InitMemoryTracker(); + * + * When ready to dump the memory report call: + * ShowMemoryTracker(); + * + * Report example: + * total Allocs = 228 + * total Bytes = 93442 + * peak Bytes = 8840 + * current Bytes = 0 + * + * + * You can also: + * #define WOLFSSL_DEBUG_MEMORY + * + * To print every alloc/free along with the function and line number. + * Example output: + * Alloc: 0x7fa14a500010 -> 120 at wc_InitRng:496 + * Free: 0x7fa14a500010 -> 120 at wc_FreeRng:606 + */ + + +#ifndef WOLFSSL_MEM_TRACK_H +#define WOLFSSL_MEM_TRACK_H + +#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) + + #include "wolfssl/wolfcrypt/logging.h" + + #if defined(WOLFSSL_TRACK_MEMORY) + #define DO_MEM_STATS + #if defined(__linux__) || defined(__MACH__) + #define DO_MEM_LIST + #endif + #endif + + + typedef struct memoryStats { + long totalAllocs; /* number of allocations */ + long totalDeallocs; /* number of deallocations */ + long totalBytes; /* total number of bytes allocated */ + long peakBytes; /* concurrent max bytes */ + long currentBytes; /* total current bytes in use */ + } memoryStats; + + typedef struct memHint { + size_t thisSize; /* size of this memory */ + + #ifdef DO_MEM_LIST + struct memHint* next; + struct memHint* prev; + #ifdef WOLFSSL_DEBUG_MEMORY + const char* func; + unsigned int line; + #endif + #endif + void* thisMemory; /* actual memory for user */ + } memHint; + + typedef struct memoryTrack { + union { + memHint hint; + byte alignit[sizeof(memHint) + ((16-1) & ~(16-1))]; /* make sure we have strong alignment */ + } u; + } memoryTrack; + +#ifdef DO_MEM_LIST + /* track allocations and report at end */ + typedef struct memoryList { + memHint* head; + memHint* tail; + word32 count; + } memoryList; +#endif + +#if defined(WOLFSSL_TRACK_MEMORY) + static memoryStats ourMemStats; + + #ifdef DO_MEM_LIST + #include + static memoryList ourMemList; + static pthread_mutex_t memLock = PTHREAD_MUTEX_INITIALIZER; + #endif +#endif + + + /* if defined to not using inline then declare function prototypes */ + #ifdef NO_INLINE + #define WC_STATIC + #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 + #define WC_STATIC static + #endif + +#ifdef WOLFSSL_DEBUG_MEMORY + WC_STATIC WC_INLINE void* TrackMalloc(size_t sz, const char* func, unsigned int line) +#else + WC_STATIC WC_INLINE void* TrackMalloc(size_t sz) +#endif + { + memoryTrack* mt; + memHint* header; + + if (sz == 0) + return NULL; + + mt = (memoryTrack*)malloc(sizeof(memoryTrack) + sz); + if (mt == NULL) + return NULL; + + header = &mt->u.hint; + header->thisSize = sz; + header->thisMemory = (byte*)mt + sizeof(memoryTrack); + + #ifdef WOLFSSL_DEBUG_MEMORY + #ifdef WOLFSSL_DEBUG_MEMORY_PRINT + printf("Alloc: %p -> %u at %s:%d\n", header->thisMemory, (word32)sz, func, line); + #else + (void)func; + (void)line; + #endif + #endif + + #ifdef DO_MEM_STATS + ourMemStats.totalAllocs++; + ourMemStats.totalBytes += sz; + ourMemStats.currentBytes += sz; + if (ourMemStats.currentBytes > ourMemStats.peakBytes) + ourMemStats.peakBytes = ourMemStats.currentBytes; + #endif + #ifdef DO_MEM_LIST + if (pthread_mutex_lock(&memLock) == 0) { + #ifdef WOLFSSL_DEBUG_MEMORY + header->func = func; + header->line = line; + #endif + + /* Setup event */ + header->next = NULL; + if (ourMemList.tail == NULL) { + ourMemList.head = header; + header->prev = NULL; + } + else { + ourMemList.tail->next = header; + header->prev = ourMemList.tail; + } + ourMemList.tail = header; /* add to the end either way */ + ourMemList.count++; + + pthread_mutex_unlock(&memLock); + } + #endif + + return header->thisMemory; + } + + +#ifdef WOLFSSL_DEBUG_MEMORY + WC_STATIC WC_INLINE void TrackFree(void* ptr, const char* func, unsigned int line) +#else + WC_STATIC WC_INLINE void TrackFree(void* ptr) +#endif + { + memoryTrack* mt; + memHint* header; + size_t sz; + + if (ptr == NULL) { + return; + } + + mt = (memoryTrack*)((byte*)ptr - sizeof(memoryTrack)); + header = &mt->u.hint; + sz = header->thisSize; + + #ifdef DO_MEM_LIST + if (pthread_mutex_lock(&memLock) == 0) + { + #endif + + #ifdef DO_MEM_STATS + ourMemStats.currentBytes -= header->thisSize; + ourMemStats.totalDeallocs++; + #endif + + #ifdef DO_MEM_LIST + if (header == ourMemList.head && header == ourMemList.tail) { + ourMemList.head = NULL; + ourMemList.tail = NULL; + } + else if (header == ourMemList.head) { + ourMemList.head = header->next; + ourMemList.head->prev = NULL; + } + else if (header == ourMemList.tail) { + ourMemList.tail = header->prev; + ourMemList.tail->next = NULL; + } + else { + memHint* next = header->next; + memHint* prev = header->prev; + if (next) + next->prev = prev; + if (prev) + prev->next = next; + } + ourMemList.count--; + + pthread_mutex_unlock(&memLock); + } + #endif + +#ifdef WOLFSSL_DEBUG_MEMORY +#ifdef WOLFSSL_DEBUG_MEMORY_PRINT + printf("Free: %p -> %u at %s:%d\n", ptr, (word32)sz, func, line); +#else + (void)func; + (void)line; +#endif +#endif + (void)sz; + + free(mt); + } + + +#ifdef WOLFSSL_DEBUG_MEMORY + WC_STATIC WC_INLINE void* TrackRealloc(void* ptr, size_t sz, const char* func, unsigned int line) +#else + WC_STATIC WC_INLINE void* TrackRealloc(void* ptr, size_t sz) +#endif + { + #ifdef WOLFSSL_DEBUG_MEMORY + void* ret = TrackMalloc(sz, func, line); + #else + void* ret = TrackMalloc(sz); + #endif + + if (ptr) { + /* if realloc is bigger, don't overread old ptr */ + memoryTrack* mt; + memHint* header; + + mt = (memoryTrack*)((byte*)ptr - sizeof(memoryTrack)); + header = &mt->u.hint; + + if (header->thisSize < sz) + sz = header->thisSize; + } + + if (ret && ptr) + XMEMCPY(ret, ptr, sz); + + if (ret) { + #ifdef WOLFSSL_DEBUG_MEMORY + TrackFree(ptr, func, line); + #else + TrackFree(ptr); + #endif + } + + return ret; + } + +#ifdef WOLFSSL_TRACK_MEMORY + static wolfSSL_Malloc_cb mfDefault = NULL; + static wolfSSL_Free_cb ffDefault = NULL; + static wolfSSL_Realloc_cb rfDefault = NULL; + + WC_STATIC WC_INLINE int InitMemoryTracker(void) + { + int ret; + + ret = wolfSSL_GetAllocators(&mfDefault, &ffDefault, &rfDefault); + if (ret < 0) { + printf("wolfSSL GetAllocators failed to get the defaults\n"); + } + ret = wolfSSL_SetAllocators(TrackMalloc, TrackFree, TrackRealloc); + if (ret < 0) { + printf("wolfSSL SetAllocators failed for track memory\n"); + return ret; + } + + #ifdef DO_MEM_LIST + if (pthread_mutex_lock(&memLock) == 0) + { + #endif + + #ifdef DO_MEM_STATS + ourMemStats.totalAllocs = 0; + ourMemStats.totalDeallocs = 0; + ourMemStats.totalBytes = 0; + ourMemStats.peakBytes = 0; + ourMemStats.currentBytes = 0; + #endif + + #ifdef DO_MEM_LIST + XMEMSET(&ourMemList, 0, sizeof(ourMemList)); + + pthread_mutex_unlock(&memLock); + } + #endif + + return ret; + } + + WC_STATIC WC_INLINE void ShowMemoryTracker(void) + { + #ifdef DO_MEM_LIST + if (pthread_mutex_lock(&memLock) == 0) + { + #endif + + #ifdef DO_MEM_STATS + printf("total Allocs = %9ld\n", ourMemStats.totalAllocs); + printf("total Deallocs = %9ld\n", ourMemStats.totalDeallocs); + printf("total Bytes = %9ld\n", ourMemStats.totalBytes); + printf("peak Bytes = %9ld\n", ourMemStats.peakBytes); + printf("current Bytes = %9ld\n", ourMemStats.currentBytes); + #endif + + #ifdef DO_MEM_LIST + if (ourMemList.count > 0) { + /* print list of allocations */ + memHint* header; + for (header = ourMemList.head; header != NULL; header = header->next) { + printf("Leak: Ptr %p, Size %u" + #ifdef WOLFSSL_DEBUG_MEMORY + ", Func %s, Line %d" + #endif + "\n", + (byte*)header + sizeof(memHint), (unsigned int)header->thisSize + #ifdef WOLFSSL_DEBUG_MEMORY + , header->func, header->line + #endif + ); + } + } + + pthread_mutex_unlock(&memLock); + } + #endif + } + + WC_STATIC WC_INLINE int CleanupMemoryTracker(void) + { + /* restore default allocators */ + return wolfSSL_SetAllocators(mfDefault, ffDefault, rfDefault); + } +#endif + +#endif /* USE_WOLFSSL_MEMORY */ + +#endif /* WOLFSSL_MEM_TRACK_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/memory.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/memory.h index 3968b3527..486fd39ab 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/memory.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/memory.h @@ -1,8 +1,8 @@ /* memory.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,37 +16,214 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* submitted by eof */ +/*! + \file wolfssl/wolfcrypt/memory.h +*/ #ifndef WOLFSSL_MEMORY_H #define WOLFSSL_MEMORY_H +#ifndef STRING_USER #include +#endif #include #ifdef __cplusplus extern "C" { #endif -typedef void *(*wolfSSL_Malloc_cb)(size_t size); -typedef void (*wolfSSL_Free_cb)(void *ptr); -typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size); +#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST + WOLFSSL_API void wolfSSL_SetMemFailCount(int memFailCount); +#endif +#ifdef WOLFSSL_STATIC_MEMORY + #ifdef WOLFSSL_DEBUG_MEMORY + typedef void *(*wolfSSL_Malloc_cb)(size_t size, void* heap, int type, const char* func, unsigned int line); + typedef void (*wolfSSL_Free_cb)(void *ptr, void* heap, int type, const char* func, unsigned int line); + typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line); + WOLFSSL_API void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line); + WOLFSSL_API void wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line); + WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line); + #else + typedef void *(*wolfSSL_Malloc_cb)(size_t size, void* heap, int type); + typedef void (*wolfSSL_Free_cb)(void *ptr, void* heap, int type); + typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size, void* heap, int type); + WOLFSSL_API void* wolfSSL_Malloc(size_t size, void* heap, int type); + WOLFSSL_API void wolfSSL_Free(void *ptr, void* heap, int type); + WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type); + #endif /* WOLFSSL_DEBUG_MEMORY */ +#else + #ifdef WOLFSSL_DEBUG_MEMORY + typedef void *(*wolfSSL_Malloc_cb)(size_t size, const char* func, unsigned int line); + typedef void (*wolfSSL_Free_cb)(void *ptr, const char* func, unsigned int line); + typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size, const char* func, unsigned int line); -/* Public set function */ -WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb malloc_function, - wolfSSL_Free_cb free_function, - wolfSSL_Realloc_cb realloc_function); + /* Public in case user app wants to use XMALLOC/XFREE */ + WOLFSSL_API void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line); + WOLFSSL_API void wolfSSL_Free(void *ptr, const char* func, unsigned int line); + WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line); + #else + typedef void *(*wolfSSL_Malloc_cb)(size_t size); + typedef void (*wolfSSL_Free_cb)(void *ptr); + typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size); + /* Public in case user app wants to use XMALLOC/XFREE */ + WOLFSSL_API void* wolfSSL_Malloc(size_t size); + WOLFSSL_API void wolfSSL_Free(void *ptr); + WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size); + #endif /* WOLFSSL_DEBUG_MEMORY */ +#endif /* WOLFSSL_STATIC_MEMORY */ -/* Public in case user app wants to use XMALLOC/XFREE */ -WOLFSSL_API void* wolfSSL_Malloc(size_t size); -WOLFSSL_API void wolfSSL_Free(void *ptr); -WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size); +/* 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 + #ifndef WOLFSSL_STATIC_ALIGN + #define WOLFSSL_STATIC_ALIGN 16 + #endif + #ifndef WOLFMEM_MAX_BUCKETS + #define WOLFMEM_MAX_BUCKETS 9 + #endif + #define WOLFMEM_DEF_BUCKETS 9 /* number of default memory blocks */ + #ifndef WOLFMEM_IO_SZ + #define WOLFMEM_IO_SZ 16992 /* 16 byte aligned */ + #endif + #ifndef WOLFMEM_BUCKETS + #ifndef SESSION_CERTS + /* default size of chunks of memory to separate into */ + #ifndef LARGEST_MEM_BUCKET + #define LARGEST_MEM_BUCKET 16128 + #endif + #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,\ + LARGEST_MEM_BUCKET + #elif defined (OPENSSL_EXTRA) + /* extra storage in structs for multiple attributes and order */ + #ifndef LARGEST_MEM_BUCKET + #define LARGEST_MEM_BUCKET 25600 + #endif + #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3360,4480,\ + LARGEST_MEM_BUCKET + #elif defined (WOLFSSL_CERT_EXT) + /* certificate extensions requires 24k for the SSL struct */ + #ifndef LARGEST_MEM_BUCKET + #define LARGEST_MEM_BUCKET 24576 + #endif + #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,\ + LARGEST_MEM_BUCKET + #else + /* increase 23k for object member of WOLFSSL_X509_NAME_ENTRY */ + #ifndef LARGEST_MEM_BUCKET + #define LARGEST_MEM_BUCKET 23440 + #endif + #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,\ + LARGEST_MEM_BUCKET + #endif + #endif + #ifndef WOLFMEM_DIST + #ifndef WOLFSSL_STATIC_MEMORY_SMALL + #define WOLFMEM_DIST 49,10,6,14,5,6,9,1,1 + #else + /* Low resource and not RSA */ + #define WOLFMEM_DIST 29, 7,6, 9,4,4,0,0,0 + #endif + #endif + + /* flags for loading static memory (one hot bit) */ + #define WOLFMEM_GENERAL 0x01 + #define WOLFMEM_IO_POOL 0x02 + #define WOLFMEM_IO_POOL_FIXED 0x04 + #define WOLFMEM_TRACK_STATS 0x08 + + #ifndef WOLFSSL_MEM_GUARD + #define WOLFSSL_MEM_GUARD + typedef struct WOLFSSL_MEM_STATS WOLFSSL_MEM_STATS; + typedef struct WOLFSSL_MEM_CONN_STATS WOLFSSL_MEM_CONN_STATS; + #endif + + struct WOLFSSL_MEM_CONN_STATS { + word32 peakMem; /* peak memory usage */ + word32 curMem; /* current memory usage */ + word32 peakAlloc; /* peak memory allocations */ + word32 curAlloc; /* current memory allocations */ + word32 totalAlloc;/* total memory allocations for lifetime */ + word32 totalFr; /* total frees for lifetime */ + }; + + struct WOLFSSL_MEM_STATS { + word32 curAlloc; /* current memory allocations */ + word32 totalAlloc;/* total memory allocations for lifetime */ + word32 totalFr; /* total frees for lifetime */ + word32 totalUse; /* total amount of memory used in blocks */ + word32 avaIO; /* available IO specific pools */ + word32 maxHa; /* max number of concurrent handshakes allowed */ + word32 maxIO; /* max number of concurrent IO connections allowed */ + word32 blockSz[WOLFMEM_MAX_BUCKETS]; /* block sizes in stacks */ + word32 avaBlock[WOLFMEM_MAX_BUCKETS];/* ava block sizes */ + word32 usedBlock[WOLFMEM_MAX_BUCKETS]; + int flag; /* flag used */ + }; + + typedef struct wc_Memory wc_Memory; /* internal structure for mem bucket */ + typedef struct WOLFSSL_HEAP { + wc_Memory* ava[WOLFMEM_MAX_BUCKETS]; + wc_Memory* io; /* list of buffers to use for IO */ + word32 maxHa; /* max concurrent handshakes */ + word32 curHa; + word32 maxIO; /* max concurrent IO connections */ + word32 curIO; + word32 sizeList[WOLFMEM_MAX_BUCKETS];/* memory sizes in ava list */ + word32 distList[WOLFMEM_MAX_BUCKETS];/* general distribution */ + word32 inUse; /* amount of memory currently in use */ + word32 ioUse; + word32 alloc; /* total number of allocs */ + word32 frAlc; /* total number of frees */ + int flag; + wolfSSL_Mutex memory_mutex; + } WOLFSSL_HEAP; + + /* structure passed into XMALLOC as heap hint + * having this abstraction allows tracking statistics of individual ssl's + */ + typedef struct WOLFSSL_HEAP_HINT { + WOLFSSL_HEAP* memory; + WOLFSSL_MEM_CONN_STATS* stats; /* hold individual connection stats */ + wc_Memory* outBuf; /* set if using fixed io buffers */ + wc_Memory* inBuf; + byte haFlag; /* flag used for checking handshake count */ + } WOLFSSL_HEAP_HINT; + + WOLFSSL_API int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, + unsigned char* buf, unsigned int sz, int flag, int max); + + WOLFSSL_LOCAL int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap); + WOLFSSL_LOCAL int wolfSSL_load_static_memory(byte* buffer, word32 sz, + int flag, WOLFSSL_HEAP* heap); + WOLFSSL_LOCAL int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, + WOLFSSL_MEM_STATS* stats); + WOLFSSL_LOCAL int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io); + WOLFSSL_LOCAL int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io); + + WOLFSSL_API int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag); + WOLFSSL_API int wolfSSL_MemoryPaddingSz(void); +#endif /* WOLFSSL_STATIC_MEMORY */ + +#ifdef WOLFSSL_STACK_LOG + WOLFSSL_API void __attribute__((no_instrument_function)) + __cyg_profile_func_enter(void *func, void *caller); + WOLFSSL_API void __attribute__((no_instrument_function)) + __cyg_profile_func_exit(void *func, void *caller); +#endif /* WOLFSSL_STACK_LOG */ #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/misc.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/misc.h index 78c7fbdc9..d5237dec0 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/misc.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/misc.h @@ -1,8 +1,8 @@ /* misc.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef WOLF_CRYPT_MISC_H #define WOLF_CRYPT_MISC_H @@ -66,6 +67,45 @@ WOLFSSL_LOCAL void ByteReverseWords64(word64*, const word64*, word32); #endif /* WORD64_AVAILABLE */ +#ifndef WOLFSSL_HAVE_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); + + +WOLFSSL_LOCAL byte ctMaskGT(int a, int b); +WOLFSSL_LOCAL byte ctMaskGTE(int a, int b); +WOLFSSL_LOCAL int ctMaskIntGTE(int a, int b); +WOLFSSL_LOCAL byte ctMaskLT(int a, int b); +WOLFSSL_LOCAL byte ctMaskLTE(int a, int b); +WOLFSSL_LOCAL byte ctMaskEq(int a, int b); +WOLFSSL_LOCAL word16 ctMask16GT(int a, int b); +WOLFSSL_LOCAL word16 ctMask16LT(int a, int b); +WOLFSSL_LOCAL word16 ctMask16Eq(int a, int b); +WOLFSSL_LOCAL byte ctMaskNotEq(int a, int b); +WOLFSSL_LOCAL byte ctMaskSel(byte m, byte a, byte b); +WOLFSSL_LOCAL int ctMaskSelInt(byte m, int a, int b); +WOLFSSL_LOCAL byte ctSetLTE(int a, int b); + #endif /* NO_INLINE */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/mpi_class.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/mpi_class.h index 334a7a4db..ae2fa830c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/mpi_class.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/mpi_class.h @@ -1,8 +1,8 @@ /* mpi_class.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #if !(defined(LTM1) && defined(LTM2) && defined(LTM3)) #if defined(LTM2) #define LTM3 @@ -61,6 +62,7 @@ #define BN_MP_DR_SETUP_C #define BN_MP_EXCH_C #define BN_MP_EXPT_D_C +#define BN_MP_EXPTMOD_BASE_2 #define BN_MP_EXPTMOD_C #define BN_MP_EXPTMOD_FAST_C #define BN_MP_EXTEUCLID_C @@ -357,6 +359,7 @@ #define BN_MP_REDUCE_IS_2K_C #define BN_MP_ISODD_C #define BN_MP_EXPTMOD_FAST_C + #define BN_MP_EXPTMOD_BASE_2 #endif #if defined(BN_MP_EXPTMOD_FAST_C) diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/mpi_superclass.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/mpi_superclass.h index f4c95ab0a..186ac7505 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/mpi_superclass.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/mpi_superclass.h @@ -1,8 +1,8 @@ /* mpi_superclass.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* super class file for PK algos */ /* default ... include all MPI */ @@ -82,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 means roughly speaking you can handle upto 2536-bit RSA keys with these defined without - * trouble. + * 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. */ #undef BN_S_MP_MUL_DIGS_C #undef BN_S_MP_SQR_C diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pkcs11.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pkcs11.h new file mode 100644 index 000000000..93e1af187 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pkcs11.h @@ -0,0 +1,537 @@ +/* pkcs11.h + * + * Copyright (C) 2006-2020 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 3 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 _PKCS11_H_ +#define _PKCS11_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NULL_PTR +#define NULL_PTR 0 +#endif +#define CK_TRUE 1 +#define CK_FALSE 0 + + +#define CK_INVALID_HANDLE 0UL + +#define CKN_SURRENDER 0UL + +#define CKF_TOKEN_PRESENT 0x00000001UL +#define CKF_REMOVABLE_DEVICE 0x00000002UL +#define CKF_HW_SLOT 0x00000004UL + +#define CKF_HW 0x00000001UL +#define CKF_ENCRYPT 0x00000100UL +#define CKF_DECRYPT 0x00000200UL +#define CKF_DIGEST 0x00000400UL +#define CKF_SIGN 0x00000800UL +#define CKF_SIGN_RECOVER 0x00001000UL +#define CKF_VERIFY 0x00002000UL +#define CKF_VERIFY_RECOVER 0x00004000UL +#define CKF_GENERATE 0x00008000UL +#define CKF_GENERATE_KEY_PAIR 0x00010000UL +#define CKF_WRAP 0x00020000UL +#define CKF_UNWRAP 0x00040000UL +#define CKF_DERIVE 0x00080000UL +#define CKF_EC_F_P 0x00100000UL +#define CKF_EC_F_2M 0x00200000UL +#define CKF_EC_ECPARAMETERS 0x00400000UL +#define CKF_EC_NAMEDCURVE 0x00800000UL +#define CKF_EC_UNCOMPRESS 0x01000000UL +#define CKF_EC_COMPRESS 0x02000000UL + +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001UL +#define CKF_OS_LOCKING_OK 0x00000002UL + +#define CKU_SO 0UL +#define CKU_USER 1UL +#define CKU_CONTEXT_SPECIFIC 2UL + +#define CKF_RW_SESSION 0x00000002UL +#define CKF_SERIAL_SESSION 0x00000004UL + +#define CKO_PUBLIC_KEY 0x00000002UL +#define CKO_PRIVATE_KEY 0x00000003UL +#define CKO_SECRET_KEY 0x00000004UL + +#define CKK_RSA 0x00000000UL +#define CKK_DH 0x00000002UL +#define CKK_EC 0x00000003UL +#define CKK_GENERIC_SECRET 0x00000010UL +#define CKK_AES 0x0000001FUL +#define CKK_MD5_HMAC 0x00000027UL +#define CKK_SHA_1_HMAC 0x00000028UL +#define CKK_SHA256_HMAC 0x0000002bUL +#define CKK_SHA384_HMAC 0x0000002cUL +#define CKK_SHA512_HMAC 0x0000002dUL +#define CKK_SHA224_HMAC 0x0000002eUL + +#define CKA_CLASS 0x00000000UL +#define CKA_TOKEN 0x00000001UL +#define CKA_PRIVATE 0x00000002UL +#define CKA_LABEL 0x00000003UL +#define CKA_VALUE 0x00000011UL +#define CKA_OBJECT_ID 0x00000012UL +#define CKA_OWNER 0x00000084UL +#define CKA_TRUSTED 0x00000086UL +#define CKA_KEY_TYPE 0x00000100UL +#define CKA_ID 0x00000102UL +#define CKA_SENSITIVE 0x00000103UL +#define CKA_ENCRYPT 0x00000104UL +#define CKA_DECRYPT 0x00000105UL +#define CKA_WRAP 0x00000106UL +#define CKA_UNWRAP 0x00000107UL +#define CKA_SIGN 0x00000108UL +#define CKA_SIGN_RECOVER 0x00000109UL +#define CKA_VERIFY 0x0000010AUL +#define CKA_VERIFY_RECOVER 0x0000010BUL +#define CKA_DERIVE 0x0000010CUL +#define CKA_MODULUS 0x00000120UL +#define CKA_MODULUS_BITS 0x00000121UL +#define CKA_PUBLIC_EXPONENT 0x00000122UL +#define CKA_PRIVATE_EXPONENT 0x00000123UL +#define CKA_PRIME_1 0x00000124UL +#define CKA_PRIME_2 0x00000125UL +#define CKA_EXPONENT_1 0x00000126UL +#define CKA_EXPONENT_2 0x00000127UL +#define CKA_COEFFICIENT 0x00000128UL +#define CKA_PUBLIC_KEY_INFO 0x00000129UL +#define CKA_PRIME 0x00000130UL +#define CKA_BASE 0x00000132UL +#define CKA_PRIME_BITS 0x00000133UL +#define CKA_VALUE_BITS 0x00000160UL +#define CKA_VALUE_LEN 0x00000161UL +#define CKA_EXTRACTABLE 0x00000162UL +#define CKA_LOCAL 0x00000163UL +#define CKA_NEVER_EXTRACTABLE 0x00000164UL +#define CKA_ALWAYS_SENSITIVE 0x00000165UL +#define CKA_KEY_GEN_MECHANISM 0x00000166UL +#define CKA_MODIFIABLE 0x00000170UL +#define CKA_COPYABLE 0x00000171UL +#define CKA_DESTROYABLE 0x00000172UL +#define CKA_EC_PARAMS 0x00000180UL +#define CKA_EC_POINT 0x00000181UL +#define CKA_ALWAYS_AUTHENTICATE 0x00000202UL +#define CKA_HW_FEATURE_TYPE 0x00000300UL +#define CKA_RESET_ON_INIT 0x00000301UL +#define CKA_HAS_RESET 0x00000302UL + +#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000UL +#define CKM_RSA_X_509 0x00000003UL +#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020UL +#define CKM_DH_PKCS_DERIVE 0x00000021UL +#define CKM_MD5_HMAC 0x00000211UL +#define CKM_SHA_1_HMAC 0x00000221UL +#define CKM_SHA256_HMAC 0x00000251UL +#define CKM_SHA224_HMAC 0x00000256UL +#define CKM_SHA384_HMAC 0x00000261UL +#define CKM_SHA512_HMAC 0x00000271UL +#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350UL +#define CKM_EC_KEY_PAIR_GEN 0x00001040UL +#define CKM_ECDSA 0x00001041UL +#define CKM_ECDH1_DERIVE 0x00001050UL +#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051UL +#define CKM_AES_KEY_GEN 0x00001080UL +#define CKM_AES_CBC 0x00001082UL +#define CKM_AES_GCM 0x00001087UL + +#define CKR_OK 0x00000000UL +#define CKR_MECHANISM_INVALID 0x00000070UL +#define CKR_SIGNATURE_INVALID 0x000000C0UL + +#define CKD_NULL 0x00000001UL + + +typedef unsigned char CK_BYTE; +typedef CK_BYTE CK_CHAR; +typedef CK_BYTE CK_UTF8CHAR; +typedef CK_BYTE CK_BBOOL; +typedef unsigned long int CK_ULONG; +typedef long int CK_LONG; +typedef CK_ULONG CK_FLAGS; +typedef CK_BYTE* CK_BYTE_PTR; +typedef CK_CHAR* CK_CHAR_PTR; +typedef CK_UTF8CHAR* CK_UTF8CHAR_PTR; +typedef CK_ULONG* CK_ULONG_PTR; +typedef void* CK_VOID_PTR; +typedef CK_VOID_PTR* CK_VOID_PTR_PTR; + + +typedef CK_ULONG CK_RV; + + +typedef struct CK_VERSION { + CK_BYTE major; + CK_BYTE minor; +} CK_VERSION; +typedef CK_VERSION* CK_VERSION_PTR; + + +/* Info Types */ +typedef struct CK_INFO { + CK_VERSION cryptokiVersion; + CK_UTF8CHAR manufacturerID[32]; + CK_FLAGS flags; + CK_UTF8CHAR libraryDescription[32]; + CK_VERSION libraryVersion; +} CK_INFO; +typedef CK_INFO* CK_INFO_PTR; + + +/* Slot Types */ +typedef CK_ULONG CK_SLOT_ID; +typedef CK_SLOT_ID* CK_SLOT_ID_PTR; + +typedef struct CK_SLOT_INFO { + CK_UTF8CHAR slotDescription[64]; + CK_UTF8CHAR manufacturerID[32]; + CK_FLAGS flags; + + CK_VERSION hardwareVersion; + CK_VERSION firmwareVersion; +} CK_SLOT_INFO; +typedef CK_SLOT_INFO* CK_SLOT_INFO_PTR; + + +/* Token Types */ +typedef struct CK_TOKEN_INFO { + CK_UTF8CHAR label[32]; + CK_UTF8CHAR manufacturerID[32]; + CK_UTF8CHAR model[16]; + CK_CHAR serialNumber[16]; + CK_FLAGS flags; + CK_ULONG ulMaxSessionCount; + CK_ULONG ulSessionCount; + CK_ULONG ulMaxRwSessionCount; + CK_ULONG ulRwSessionCount; + CK_ULONG ulMaxPinLen; + CK_ULONG ulMinPinLen; + CK_ULONG ulTotalPublicMemory; + CK_ULONG ulFreePublicMemory; + CK_ULONG ulTotalPrivateMemory; + CK_ULONG ulFreePrivateMemory; + CK_VERSION hardwareVersion; + CK_VERSION firmwareVersion; + CK_CHAR utcTime[16]; +} CK_TOKEN_INFO; +typedef CK_TOKEN_INFO* CK_TOKEN_INFO_PTR; + + +/* Session Types */ +typedef CK_ULONG CK_SESSION_HANDLE; +typedef CK_SESSION_HANDLE* CK_SESSION_HANDLE_PTR; + +typedef CK_ULONG CK_USER_TYPE; + +typedef CK_ULONG CK_STATE; + +typedef struct CK_SESSION_INFO { + CK_SLOT_ID slotID; + CK_STATE state; + CK_FLAGS flags; + CK_ULONG ulDeviceError; +} CK_SESSION_INFO; +typedef CK_SESSION_INFO* CK_SESSION_INFO_PTR; + + +/* Object Types */ +typedef CK_ULONG CK_OBJECT_HANDLE; +typedef CK_OBJECT_HANDLE* CK_OBJECT_HANDLE_PTR; + +typedef CK_ULONG CK_OBJECT_CLASS; +typedef CK_OBJECT_CLASS* CK_OBJECT_CLASS_PTR; + +typedef CK_ULONG CK_KEY_TYPE; + +typedef CK_ULONG CK_ATTRIBUTE_TYPE; + +typedef struct CK_ATTRIBUTE { + CK_ATTRIBUTE_TYPE type; + CK_VOID_PTR pValue; + CK_ULONG ulValueLen; +} CK_ATTRIBUTE; +typedef CK_ATTRIBUTE* CK_ATTRIBUTE_PTR; + + +/* Mechanism Types */ +typedef CK_ULONG CK_MECHANISM_TYPE; +typedef CK_MECHANISM_TYPE* CK_MECHANISM_TYPE_PTR; + +typedef struct CK_MECHANISM { + CK_MECHANISM_TYPE mechanism; + CK_VOID_PTR pParameter; + CK_ULONG ulParameterLen; +} CK_MECHANISM; +typedef CK_MECHANISM* CK_MECHANISM_PTR; + +typedef struct CK_MECHANISM_INFO { + CK_ULONG ulMinKeySize; + CK_ULONG ulMaxKeySize; + CK_FLAGS flags; +} CK_MECHANISM_INFO; +typedef CK_MECHANISM_INFO * CK_MECHANISM_INFO_PTR; + + +typedef CK_ULONG CK_NOTIFICATION; + +typedef CK_RV (*CK_NOTIFY)(CK_SESSION_HANDLE hSession, CK_NOTIFICATION event, + CK_VOID_PTR pApplication); + + +/* Threading types. */ +typedef CK_RV (*CK_CREATEMUTEX)(CK_VOID_PTR_PTR ppMutex); +typedef CK_RV (*CK_DESTROYMUTEX)(CK_VOID_PTR pMutex); +typedef CK_RV (*CK_LOCKMUTEX)(CK_VOID_PTR pMutex); +typedef CK_RV (*CK_UNLOCKMUTEX)(CK_VOID_PTR pMutex); + +typedef struct CK_C_INITIALIZE_ARGS { + CK_CREATEMUTEX CreateMutex; + CK_DESTROYMUTEX DestroyMutex; + CK_LOCKMUTEX LockMutex; + CK_UNLOCKMUTEX UnlockMutex; + CK_FLAGS flags; + CK_VOID_PTR pReserved; +} CK_C_INITIALIZE_ARGS; +typedef CK_C_INITIALIZE_ARGS* CK_C_INITIALIZE_ARGS_PTR; + + +/* Cryptographic algorithm types. */ +typedef CK_ULONG CK_EC_KDF_TYPE; + +typedef struct CK_ECDH1_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_ECDH1_DERIVE_PARAMS; +typedef CK_ECDH1_DERIVE_PARAMS* CK_ECDH1_DERIVE_PARAMS_PTR; + + +typedef struct CK_GCM_PARAMS { + CK_BYTE_PTR pIv; + CK_ULONG ulIvLen; + CK_ULONG ulIvBits; + CK_BYTE_PTR pAAD; + CK_ULONG ulAADLen; + CK_ULONG ulTagBits; +} CK_GCM_PARAMS; +typedef CK_GCM_PARAMS* CK_GCM_PARAMS_PTR; + +/* Function list types. */ +typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; +typedef CK_FUNCTION_LIST* CK_FUNCTION_LIST_PTR; +typedef CK_FUNCTION_LIST_PTR* CK_FUNCTION_LIST_PTR_PTR; + +typedef CK_RV (*CK_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList); + +struct CK_FUNCTION_LIST { + CK_VERSION version; + + CK_RV (*C_Initialize)(CK_VOID_PTR pInitArgs); + CK_RV (*C_Finalize)(CK_VOID_PTR pReserved); + CK_RV (*C_GetInfo)(CK_INFO_PTR pInfo); + CK_RV (*C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList); + CK_RV (*C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, + CK_ULONG_PTR pulCount); + CK_RV (*C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo); + CK_RV (*C_GetTokenInfo)(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo); + CK_RV (*C_GetMechanismList)(CK_SLOT_ID slotID, + CK_MECHANISM_TYPE_PTR pMechanismList, + CK_ULONG_PTR pulCount); + CK_RV (*C_GetMechanismInfo)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR pInfo); + CK_RV (*C_InitToken)(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel); + CK_RV (*C_InitPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen); + CK_RV (*C_SetPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, + CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, + CK_ULONG ulNewLen); + CK_RV (*C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags, + CK_VOID_PTR pApplication, CK_NOTIFY Notify, + CK_SESSION_HANDLE_PTR phSession); + CK_RV (*C_CloseSession)(CK_SESSION_HANDLE hSession); + CK_RV (*C_CloseAllSessions)(CK_SLOT_ID slotID); + CK_RV (*C_GetSessionInfo)(CK_SESSION_HANDLE hSession, + CK_SESSION_INFO_PTR pInfo); + CK_RV (*C_GetOperationState)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG_PTR pulOperationStateLen); + CK_RV (*C_SetOperationState)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG ulOperationStateLen, + CK_OBJECT_HANDLE hEncryptionKey, + CK_OBJECT_HANDLE hAuthenticationKey); + CK_RV (*C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, + CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen); + CK_RV (*C_Logout)(CK_SESSION_HANDLE hSession); + CK_RV (*C_CreateObject)(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phObject); + CK_RV (*C_CopyObject)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phNewObject); + CK_RV (*C_DestroyObject)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject); + CK_RV (*C_GetObjectSize)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize); + CK_RV (*C_GetAttributeValue)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); + CK_RV (*C_SetAttributeValue)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); + CK_RV (*C_FindObjectsInit)(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); + CK_RV (*C_FindObjects)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE_PTR phObject, + CK_ULONG ulMaxObjectCount, + CK_ULONG_PTR pulObjectCount); + CK_RV (*C_FindObjectsFinal)(CK_SESSION_HANDLE hSession); + CK_RV (*C_EncryptInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); + CK_RV (*C_Encrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, + CK_ULONG_PTR pulEncryptedDataLen); + CK_RV (*C_EncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen); + CK_RV (*C_EncryptFinal)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastEncryptedPart, + CK_ULONG_PTR pulLastEncryptedPartLen); + CK_RV (*C_DecryptInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); + CK_RV (*C_Decrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, + CK_ULONG_PTR pulDataLen); + CK_RV (*C_DecryptUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen); + CK_RV (*C_DecryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, + CK_ULONG_PTR pulLastPartLen); + CK_RV (*C_DigestInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism); + CK_RV (*C_Digest)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen); + CK_RV (*C_DigestUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen); + CK_RV (*C_DigestKey)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey); + CK_RV (*C_DigestFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen); + CK_RV (*C_SignInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + CK_RV (*C_Sign)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen); + CK_RV (*C_SignUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen); + CK_RV (*C_SignFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen); + CK_RV (*C_SignRecoverInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + CK_RV (*C_SignRecover)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen); + CK_RV (*C_VerifyInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); + CK_RV (*C_Verify)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen); + CK_RV (*C_VerifyUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen); + CK_RV (*C_VerifyFinal)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen); + CK_RV (*C_VerifyRecoverInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + CK_RV (*C_VerifyRecover)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, + CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); + CK_RV (*C_DigestEncryptUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen); + CK_RV (*C_DecryptDigestUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); + CK_RV (*C_SignEncryptUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen); + CK_RV (*C_DecryptVerifyUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); + CK_RV (*C_GenerateKey)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey); + CK_RV (*C_GenerateKeyPair)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pPublicKeyTemplate, + CK_ULONG ulPublicKeyAttributeCount, + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + CK_ULONG ulPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR phPublicKey, + CK_OBJECT_HANDLE_PTR phPrivateKey); + CK_RV (*C_WrapKey)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, + CK_BYTE_PTR pWrappedKey, + CK_ULONG_PTR pulWrappedKeyLen); + CK_RV (*C_UnwrapKey)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hUnwrappingKey, + CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey); + CK_RV (*C_DeriveKey)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hBaseKey, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey); + CK_RV (*C_SeedRandom)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, + CK_ULONG ulSeedLen); + CK_RV (*C_GenerateRandom)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR RandomData, CK_ULONG ulRandomLen); + CK_RV (*C_GetFunctionStatus)(CK_SESSION_HANDLE hSession); + CK_RV (*C_CancelFunction)(CK_SESSION_HANDLE hSession); + CK_RV (*C_WaitForSlotEvent)(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, + CK_VOID_PTR pRserved); + +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _PKCS11_H_ */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pkcs12.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pkcs12.h new file mode 100644 index 000000000..7082b6279 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pkcs12.h @@ -0,0 +1,72 @@ +/* pkcs12.h + * + * Copyright (C) 2006-2020 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_PKCS12_H +#define WOLF_CRYPT_PKCS12_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef WOLFSSL_TYPES_DEFINED /* do not redeclare from ssl.h */ + typedef struct WC_PKCS12 WC_PKCS12; +#endif + +typedef struct WC_DerCertList { /* dereferenced in ssl.c */ + byte* buffer; + word32 bufferSz; + struct WC_DerCertList* next; +} WC_DerCertList; + +/* default values for creating PKCS12 */ +enum { + WC_PKCS12_ITT_DEFAULT = 2048, + WC_PKCS12_VERSION_DEFAULT = 3, + WC_PKCS12_MAC_DEFAULT = 1, +}; + +WOLFSSL_API WC_PKCS12* wc_PKCS12_new(void); +WOLFSSL_API void wc_PKCS12_free(WC_PKCS12* pkcs12); +WOLFSSL_API int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12); +WOLFSSL_API int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz); +WOLFSSL_API int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, + byte** pkey, word32* pkeySz, byte** cert, word32* certSz, + WC_DerCertList** ca); +WOLFSSL_API WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, + char* name, byte* key, word32 keySz, byte* cert, word32 certSz, + WC_DerCertList* ca, int nidKey, int nidCert, int iter, int macIter, + int keyType, void* heap); + + +WOLFSSL_LOCAL int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap); +WOLFSSL_LOCAL void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12); + +WOLFSSL_LOCAL void wc_FreeCertList(WC_DerCertList* list, void* heap); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_PKCS12_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pkcs7.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pkcs7.h index e39a12b9d..0292d1d07 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pkcs7.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pkcs7.h @@ -1,8 +1,8 @@ /* pkcs7.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/pkcs7.h +*/ + #ifndef WOLF_CRYPT_PKCS7_H #define WOLF_CRYPT_PKCS7_H @@ -31,6 +35,9 @@ #endif #include #include +#ifndef NO_AES + #include +#endif #ifndef NO_DES3 #include #endif @@ -39,84 +46,455 @@ extern "C" { #endif +/* Max number of certificates that PKCS7 structure can parse */ +#ifndef MAX_PKCS7_CERTS + #define MAX_PKCS7_CERTS 4 +#endif + +#ifndef MAX_ORI_TYPE_SZ + #define MAX_ORI_TYPE_SZ MAX_OID_SZ +#endif +#ifndef MAX_ORI_VALUE_SZ + #define MAX_ORI_VALUE_SZ 512 +#endif + +#ifndef MAX_SIGNED_ATTRIBS_SZ + #define MAX_SIGNED_ATTRIBS_SZ 7 +#endif + +#ifndef MAX_AUTH_ATTRIBS_SZ + #define MAX_AUTH_ATTRIBS_SZ 7 +#endif + +#ifndef MAX_UNAUTH_ATTRIBS_SZ + #define MAX_UNAUTH_ATTRIBS_SZ 7 +#endif + /* PKCS#7 content types, ref RFC 2315 (Section 14) */ enum PKCS7_TYPES { - PKCS7_MSG = 650, /* 1.2.840.113549.1.7 */ - DATA = 651, /* 1.2.840.113549.1.7.1 */ - SIGNED_DATA = 652, /* 1.2.840.113549.1.7.2 */ - ENVELOPED_DATA = 653, /* 1.2.840.113549.1.7.3 */ - SIGNED_AND_ENVELOPED_DATA = 654, /* 1.2.840.113549.1.7.4 */ - DIGESTED_DATA = 655, /* 1.2.840.113549.1.7.5 */ - ENCRYPTED_DATA = 656 /* 1.2.840.113549.1.7.6 */ + PKCS7_MSG = 650, /* 1.2.840.113549.1.7 */ + DATA = 651, /* 1.2.840.113549.1.7.1 */ + SIGNED_DATA = 652, /* 1.2.840.113549.1.7.2 */ + ENVELOPED_DATA = 653, /* 1.2.840.113549.1.7.3 */ + SIGNED_AND_ENVELOPED_DATA = 654, /* 1.2.840.113549.1.7.4 */ + DIGESTED_DATA = 655, /* 1.2.840.113549.1.7.5 */ + ENCRYPTED_DATA = 656, /* 1.2.840.113549.1.7.6 */ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + COMPRESSED_DATA = 678, /* 1.2.840.113549.1.9.16.1.9, RFC 3274 */ +#endif + FIRMWARE_PKG_DATA = 685, /* 1.2.840.113549.1.9.16.1.16, RFC 4108 */ + AUTH_ENVELOPED_DATA = 692 /* 1.2.840.113549.1.9.16.1.23, RFC 5083 */ +}; + +enum PKCS7_STATE { + WC_PKCS7_START = 0, + + /* decode encrypted */ + WC_PKCS7_STAGE2, + WC_PKCS7_STAGE3, + WC_PKCS7_STAGE4, + WC_PKCS7_STAGE5, + WC_PKCS7_STAGE6, + + WC_PKCS7_VERIFY_STAGE2, + WC_PKCS7_VERIFY_STAGE3, + WC_PKCS7_VERIFY_STAGE4, + WC_PKCS7_VERIFY_STAGE5, + WC_PKCS7_VERIFY_STAGE6, + + /* parse info set */ + WC_PKCS7_INFOSET_START, + WC_PKCS7_INFOSET_BER, + WC_PKCS7_INFOSET_STAGE1, + WC_PKCS7_INFOSET_STAGE2, + WC_PKCS7_INFOSET_END, + + /* decode enveloped data */ + WC_PKCS7_ENV_2, + WC_PKCS7_ENV_3, + WC_PKCS7_ENV_4, + WC_PKCS7_ENV_5, + + /* decode auth enveloped */ + WC_PKCS7_AUTHENV_2, + WC_PKCS7_AUTHENV_3, + WC_PKCS7_AUTHENV_4, + WC_PKCS7_AUTHENV_5, + WC_PKCS7_AUTHENV_6, + WC_PKCS7_AUTHENV_ATRB, + WC_PKCS7_AUTHENV_ATRBEND, + WC_PKCS7_AUTHENV_7, + + /* decryption state types */ + WC_PKCS7_DECRYPT_KTRI, + WC_PKCS7_DECRYPT_KTRI_2, + WC_PKCS7_DECRYPT_KTRI_3, + + + WC_PKCS7_DECRYPT_KARI, + WC_PKCS7_DECRYPT_KEKRI, + WC_PKCS7_DECRYPT_PWRI, + WC_PKCS7_DECRYPT_ORI, + + WC_PKCS7_DECRYPT_DONE, + }; enum Pkcs7_Misc { - PKCS7_NONCE_SZ = 16, - MAX_ENCRYPTED_KEY_SZ = 512, /* max enc. key size, RSA <= 4096 */ - MAX_CONTENT_KEY_LEN = DES3_KEYLEN, /* highest current cipher is 3DES */ - MAX_RECIP_SZ = MAX_VERSION_SZ + - MAX_SEQ_SZ + ASN_NAME_MAX + MAX_SN_SZ + - MAX_SEQ_SZ + MAX_ALGO_SZ + 1 + MAX_ENCRYPTED_KEY_SZ + PKCS7_NONCE_SZ = 16, + MAX_ENCRYPTED_KEY_SZ = 512, /* max enc. key size, RSA <= 4096 */ + MAX_CONTENT_KEY_LEN = 32, /* highest current cipher is AES-256-CBC */ + MAX_CONTENT_IV_SIZE = 16, /* highest current is AES128 */ +#ifndef NO_AES + MAX_CONTENT_BLOCK_LEN = AES_BLOCK_SIZE, +#else + MAX_CONTENT_BLOCK_LEN = DES_BLOCK_SIZE, +#endif + MAX_RECIP_SZ = MAX_VERSION_SZ + + MAX_SEQ_SZ + ASN_NAME_MAX + MAX_SN_SZ + + MAX_SEQ_SZ + MAX_ALGO_SZ + 1 + MAX_ENCRYPTED_KEY_SZ, +#if (defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION >= 2)) || defined(HAVE_SELFTEST) + /* In the event of fips cert 3389 or CAVP selftest build, these enums are + * not in aes.h for use with pkcs7 so enumerate it here outside the fips + * boundary */ + GCM_NONCE_MID_SZ = 12, /* The usual default nonce size for AES-GCM. */ + CCM_NONCE_MIN_SZ = 7, +#endif }; +enum Cms_Options { + CMS_SKID = 1, + CMS_ISSUER_AND_SERIAL_NUMBER = 2, +}; +#define DEGENERATE_SID 3 + +/* CMS/PKCS#7 RecipientInfo types, RFC 5652, Section 6.2 */ +enum Pkcs7_RecipientInfo_Types { + PKCS7_KTRI = 0, + PKCS7_KARI = 1, + PKCS7_KEKRI = 2, + PKCS7_PWRI = 3, + PKCS7_ORI = 4 +}; typedef struct PKCS7Attrib { - byte* oid; + const byte* oid; word32 oidSz; - byte* value; + const byte* value; word32 valueSz; } PKCS7Attrib; -typedef struct PKCS7 { - byte* content; /* inner content, not owner */ +typedef struct PKCS7DecodedAttrib { + struct PKCS7DecodedAttrib* next; + byte* oid; + word32 oidSz; + byte* value; + word32 valueSz; +} PKCS7DecodedAttrib; + +typedef struct PKCS7State PKCS7State; +typedef struct Pkcs7Cert Pkcs7Cert; +typedef struct Pkcs7EncodedRecip Pkcs7EncodedRecip; +typedef struct PKCS7 PKCS7; +typedef struct PKCS7 PKCS7_SIGNED; +typedef struct PKCS7SignerInfo PKCS7SignerInfo; + +/* OtherRecipientInfo decrypt callback prototype */ +typedef int (*CallbackOriDecrypt)(PKCS7* pkcs7, byte* oriType, word32 oriTypeSz, + byte* oriValue, word32 oriValueSz, + byte* decryptedKey, word32* decryptedKeySz, + void* ctx); +typedef int (*CallbackOriEncrypt)(PKCS7* pkcs7, byte* cek, word32 cekSz, + byte* oriType, word32* oriTypeSz, + byte* oriValue, word32* oriValueSz, + void* ctx); +typedef int (*CallbackDecryptContent)(PKCS7* pkcs7, int encryptOID, + byte* iv, int ivSz, byte* aad, word32 aadSz, + byte* authTag, word32 authTagSz, byte* in, + int inSz, byte* out, void* ctx); +typedef int (*CallbackWrapCEK)(PKCS7* pkcs7, byte* cek, word32 cekSz, + byte* keyId, word32 keyIdSz, + byte* originKey, word32 originKeySz, + byte* out, word32 outSz, + int keyWrapAlgo, int type, int dir); + +#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) +/* RSA sign raw digest callback, user builds DigestInfo */ +typedef int (*CallbackRsaSignRawDigest)(PKCS7* pkcs7, byte* digest, + word32 digestSz, byte* out, word32 outSz, + byte* privateKey, word32 privateKeySz, + int devId, int hashOID); +#endif + +/* Public Structure Warning: + * Existing members must not be changed to maintain backwards compatibility! + */ +struct PKCS7 { + WC_RNG* rng; + PKCS7Attrib* signedAttribs; + byte* content; /* inner content, not owner */ + byte* contentDynamic; /* content if constructed OCTET_STRING */ + byte* singleCert; /* recipient cert, DER, not owner */ + const byte* issuer; /* issuer name of singleCert */ + byte* privateKey; /* private key, DER, not owner */ + void* heap; /* heap hint for dynamic memory */ +#ifdef ASN_BER_TO_DER + byte* der; /* DER encoded version of message */ + word32 derSz; +#endif + byte* cert[MAX_PKCS7_CERTS]; + + /* Encrypted-data Content Type */ + byte* encryptionKey; /* block cipher encryption key */ + PKCS7Attrib* unprotectedAttribs; /* optional */ + PKCS7DecodedAttrib* decodedAttrib; /* linked list of decoded attribs */ + + /* Enveloped-data optional ukm, not owner */ + byte* ukm; + word32 ukmSz; + + word32 encryptionKeySz; /* size of key buffer, bytes */ + word32 unprotectedAttribsSz; word32 contentSz; /* content size */ + word32 singleCertSz; /* size of recipient cert buffer, bytes */ + word32 issuerSz; /* length of issuer name */ + word32 issuerSnSz; /* length of serial number */ + + word32 publicKeySz; + word32 publicKeyOID; /* key OID (RSAk, ECDSAk, etc) */ + word32 privateKeySz; /* size of private key buffer, bytes */ + word32 signedAttribsSz; int contentOID; /* PKCS#7 content type OID sum */ - - RNG* rng; - int hashOID; int encryptOID; /* key encryption algorithm OID */ - - byte* singleCert; /* recipient cert, DER, not owner */ - word32 singleCertSz; /* size of recipient cert buffer, bytes */ + int keyWrapOID; /* key wrap algorithm OID */ + int keyAgreeOID; /* key agreement algorithm OID */ + int devId; /* device ID for HW based private key */ byte issuerHash[KEYID_SIZE]; /* hash of all alt Names */ - byte* issuer; /* issuer name of singleCert */ - word32 issuerSz; /* length of issuer name */ byte issuerSn[MAX_SN_SZ]; /* singleCert's serial number */ - word32 issuerSnSz; /* length of serial number */ - byte publicKey[512]; - word32 publicKeySz; - byte* privateKey; /* private key, DER, not owner */ - word32 privateKeySz; /* size of private key buffer, bytes */ + byte publicKey[MAX_RSA_INT_SZ + MAX_RSA_E_SZ]; /* MAX RSA key size (m + e)*/ + word32 certSz[MAX_PKCS7_CERTS]; - PKCS7Attrib* signedAttribs; - word32 signedAttribsSz; -} PKCS7; + /* flags - up to 16-bits */ + word16 isDynamic:1; + word16 noDegenerate:1; /* allow degenerate case in verify function */ + word16 detached:1; /* generate detached SignedData signature bundles */ + byte contentType[MAX_OID_SZ]; /* custom contentType byte array */ + word32 contentTypeSz; /* size of contentType, bytes */ -WOLFSSL_LOCAL int wc_SetContentType(int pkcs7TypeOID, byte* output); -WOLFSSL_LOCAL int wc_GetContentType(const byte* input, word32* inOutIdx, - word32* oid, word32 maxIdx); -WOLFSSL_LOCAL int wc_CreateRecipientInfo(const byte* cert, word32 certSz, - int keyEncAlgo, int blockKeySz, - RNG* rng, byte* contentKeyPlain, - byte* contentKeyEnc, - int* keyEncSz, byte* out, word32 outSz); + int sidType; /* SignerIdentifier type to use, of type + Pkcs7_SignerIdentifier_Types, default to + SID_ISSUER_AND_SERIAL_NUMBER */ + byte issuerSubjKeyId[KEYID_SIZE]; /* SubjectKeyIdentifier of singleCert */ + Pkcs7Cert* certList; /* certificates list for SignedData set */ + Pkcs7EncodedRecip* recipList; /* recipients list */ + byte* cek; /* content encryption key, random, dynamic */ + word32 cekSz; /* size of cek, bytes */ + byte* pass; /* password, for PWRI decryption */ + word32 passSz; /* size of pass, bytes */ + int kekEncryptOID; /* KEK encryption algorithm OID */ -WOLFSSL_API int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz); + CallbackOriEncrypt oriEncryptCb; /* ORI encrypt callback */ + CallbackOriDecrypt oriDecryptCb; /* ORI decrypt callback */ + void* oriEncryptCtx; /* ORI encrypt user context ptr */ + void* oriDecryptCtx; /* ORI decrypt user context ptr */ + + PKCS7Attrib* authAttribs; /* authenticated attribs */ + word32 authAttribsSz; + PKCS7Attrib* unauthAttribs; /* unauthenticated attribs */ + word32 unauthAttribsSz; + +#ifndef NO_PKCS7_STREAM + PKCS7State* stream; +#endif + word32 state; + + word16 skipDefaultSignedAttribs:1; /* skip adding default signed attribs */ + + byte version; /* 1 for RFC 2315 and 3 for RFC 4108 */ + PKCS7SignerInfo* signerInfo; + CallbackDecryptContent decryptionCb; + CallbackWrapCEK wrapCEKCb; + void* decryptionCtx; + + byte* signature; + byte* plainDigest; + byte* pkcs7Digest; + word32 signatureSz; + word32 plainDigestSz; + word32 pkcs7DigestSz; + +#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) + CallbackRsaSignRawDigest rsaSignRawDigestCb; +#endif + + /* used by DecodeEnvelopedData with multiple encrypted contents */ + byte* cachedEncryptedContent; + word32 cachedEncryptedContentSz; + /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ +}; + +WOLFSSL_API PKCS7* wc_PKCS7_New(void* heap, int devId); +WOLFSSL_API int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId); +WOLFSSL_API int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* der, word32 derSz); +WOLFSSL_API int wc_PKCS7_AddCertificate(PKCS7* pkcs7, byte* der, word32 derSz); 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_GetAttributeValue(PKCS7* pkcs7, const byte* oid, + word32 oidSz, byte* out, word32* outSz); + +WOLFSSL_API int wc_PKCS7_SetSignerIdentifierType(PKCS7* pkcs7, int type); +WOLFSSL_API int wc_PKCS7_SetContentType(PKCS7* pkcs7, byte* contentType, + word32 sz); +WOLFSSL_API int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz); +WOLFSSL_API int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, + word32 blockSz); + +/* CMS/PKCS#7 Data */ +WOLFSSL_API int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, + word32 outputSz); + +/* CMS/PKCS#7 SignedData */ +WOLFSSL_API int wc_PKCS7_SetDetached(PKCS7* pkcs7, word16 flag); +WOLFSSL_API int wc_PKCS7_NoDefaultSignedAttribs(PKCS7* pkcs7); WOLFSSL_API int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, - byte* output, word32 outputSz); + byte* output, word32 outputSz); +WOLFSSL_API int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf, + word32 hashSz, byte* outputHead, + word32* outputHeadSz, + byte* outputFoot, + word32* outputFootSz); +WOLFSSL_API void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag); WOLFSSL_API int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, - byte* pkiMsg, word32 pkiMsgSz); + byte* pkiMsg, word32 pkiMsgSz); +WOLFSSL_API int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf, + word32 hashSz, byte* pkiMsgHead, + word32 pkiMsgHeadSz, byte* pkiMsgFoot, + word32 pkiMsgFootSz); + +WOLFSSL_API int wc_PKCS7_GetSignerSID(PKCS7* pkcs7, byte* out, word32* outSz); + +/* CMS single-shot API for Signed FirmwarePkgData */ +WOLFSSL_API int wc_PKCS7_EncodeSignedFPD(PKCS7* pkcs7, byte* privateKey, + word32 privateKeySz, int signOID, + int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, byte* output, + word32 outputSz); +#ifndef NO_PKCS7_ENCRYPTED_DATA +/* CMS single-shot API for Signed Encrypted FirmwarePkgData */ +WOLFSSL_API int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, + byte* encryptKey, word32 encryptKeySz, + byte* privateKey, word32 privateKeySz, + int encryptOID, int signOID, + int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* unprotectedAttribs, + word32 unprotectedAttribsSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, + byte* output, word32 outputSz); +#endif /* NO_PKCS7_ENCRYPTED_DATA */ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) +/* CMS single-shot API for Signed Compressed FirmwarePkgData */ +WOLFSSL_API int wc_PKCS7_EncodeSignedCompressedFPD(PKCS7* pkcs7, + byte* privateKey, word32 privateKeySz, + int signOID, int hashOID, + byte* content, word32 contentSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, byte* output, + word32 outputSz); + +#ifndef NO_PKCS7_ENCRYPTED_DATA +/* CMS single-shot API for Signed Encrypted Compressed FirmwarePkgData */ +WOLFSSL_API int wc_PKCS7_EncodeSignedEncryptedCompressedFPD(PKCS7* pkcs7, + byte* encryptKey, word32 encryptKeySz, + byte* privateKey, word32 privateKeySz, + int encryptOID, int signOID, + int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* unprotectedAttribs, + word32 unprotectedAttribsSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, + byte* output, word32 outputSz); +#endif /* !NO_PKCS7_ENCRYPTED_DATA */ +#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + +/* EnvelopedData and AuthEnvelopedData RecipientInfo functions */ +WOLFSSL_API int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, + word32 certSz, int options); +WOLFSSL_API int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, + word32 certSz, int keyWrapOID, + int keyAgreeOID, byte* ukm, + word32 ukmSz, int options); + +WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz); +WOLFSSL_API int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, + byte* kek, word32 kekSz, + byte* keyID, word32 keyIdSz, + void* timePtr, byte* otherOID, + word32 otherOIDSz, byte* other, + word32 otherSz, int options); + +WOLFSSL_API int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen); +WOLFSSL_API int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, + word32 pLen, byte* salt, + word32 saltSz, int kdfOID, + int prfOID, int iterations, + int kekEncryptOID, int options); +WOLFSSL_API int wc_PKCS7_SetOriEncryptCtx(PKCS7* pkcs7, void* ctx); +WOLFSSL_API int wc_PKCS7_SetOriDecryptCtx(PKCS7* pkcs7, void* ctx); +WOLFSSL_API int wc_PKCS7_SetOriDecryptCb(PKCS7* pkcs7, CallbackOriDecrypt cb); +WOLFSSL_API int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt cb, + int options); +WOLFSSL_API int wc_PKCS7_SetWrapCEKCb(PKCS7* pkcs7, + CallbackWrapCEK wrapCEKCb); + +#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) +WOLFSSL_API int wc_PKCS7_SetRsaSignRawDigestCb(PKCS7* pkcs7, + CallbackRsaSignRawDigest cb); +#endif + +/* CMS/PKCS#7 EnvelopedData */ WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz); WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz); +/* CMS/PKCS#7 AuthEnvelopedData */ +WOLFSSL_API int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, + byte* output, word32 outputSz); +WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, + word32 pkiMsgSz, byte* output, + word32 outputSz); + +/* CMS/PKCS#7 EncryptedData */ +#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); +WOLFSSL_API int wc_PKCS7_SetDecodeEncryptedCb(PKCS7* pkcs7, + CallbackDecryptContent decryptionCb); +WOLFSSL_API int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx); +#endif /* NO_PKCS7_ENCRYPTED_DATA */ + +/* CMS/PKCS#7 CompressedData */ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) +WOLFSSL_API int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, + word32 outputSz); +WOLFSSL_API int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, + word32 pkiMsgSz, byte* output, + word32 outputSz); +#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/poly1305.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/poly1305.h index 0e76d063d..981ce49a1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/poly1305.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/poly1305.h @@ -1,8 +1,8 @@ /* poly1305.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/poly1305.h +*/ + #ifndef WOLF_CRYPT_POLY1305_H #define WOLF_CRYPT_POLY1305_H @@ -31,12 +35,22 @@ #endif /* auto detect between 32bit / 64bit */ -#define HAS_SIZEOF_INT128_64BIT (defined(__SIZEOF_INT128__) && defined(__LP64__)) -#define HAS_MSVC_64BIT (defined(_MSC_VER) && defined(_M_X64)) -#define HAS_GCC_4_4_64BIT (defined(__GNUC__) && defined(__LP64__) && \ - ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)))) +#if defined(__SIZEOF_INT128__) && defined(__LP64__) +#define WC_HAS_SIZEOF_INT128_64BIT +#endif -#if (HAS_SIZEOF_INT128_64BIT || HAS_MSVC_64BIT || HAS_GCC_4_4_64BIT) +#if defined(_MSC_VER) && defined(_M_X64) +#define WC_HAS_MSVC_64BIT +#endif + +#if (defined(__GNUC__) && defined(__LP64__) && \ + ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)))) +#define WC_HAS_GCC_4_4_64BIT +#endif + +#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 @@ -46,36 +60,71 @@ enum { POLY1305 = 7, POLY1305_BLOCK_SIZE = 16, POLY1305_DIGEST_SIZE = 16, - POLY1305_PAD_SIZE = 56 }; +#define WC_POLY1305_PAD_SZ 16 +#define WC_POLY1305_MAC_SZ 16 + /* 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[20]; + word32 r1[8]; + word32 r2[8]; + word32 r3[8]; + word32 r4[8]; + word64 hm[16]; + unsigned char buffer[8*POLY1305_BLOCK_SIZE]; + size_t leftover; + unsigned char finished; + unsigned char started; #else - word32 r[5]; - word32 h[5]; - word32 pad[4]; +#if defined(WOLFSSL_ARMASM) && defined(__aarch64__) + ALIGN128 word32 r[5]; + ALIGN128 word32 r_2[5]; // r^2 + ALIGN128 word32 r_4[5]; // r^4 + ALIGN128 word32 h[5]; + word32 pad[4]; + word64 leftover; +#else +#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; +#endif /* WOLFSSL_ARMASM */ + 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); +/* AEAD Functions */ +WOLFSSL_API int wc_Poly1305_Pad(Poly1305* ctx, word32 lenToPad); +WOLFSSL_API int wc_Poly1305_EncodeSizes(Poly1305* ctx, word32 aadSz, word32 dataSz); +WOLFSSL_API int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, + byte* input, word32 sz, byte* tag, word32 tagSz); + +void poly1305_block(Poly1305* ctx, const unsigned char *m); +void poly1305_blocks(Poly1305* ctx, const unsigned char *m, + size_t bytes); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* HAVE_POLY1305 */ #endif /* WOLF_CRYPT_POLY1305_H */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h new file mode 100644 index 000000000..0e342db3a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h @@ -0,0 +1,152 @@ +/* esp32-crypt.h + * + * Copyright (C) 2006-2020 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 __ESP32_CRYPT_H__ + +#define __ESP32_CRYPT_H__ + +#include "esp_idf_version.h" +#include "esp_types.h" +#include "esp_log.h" + +#ifdef WOLFSSL_ESP32WROOM32_CRYPT_DEBUG +#undef LOG_LOCAL_LEVEL +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#else +#undef LOG_LOCAL_LEVEL +#define LOG_LOCAL_LEVEL ESP_LOG_ERROR +#endif + +#include +#include "soc/dport_reg.h" +#include "soc/hwcrypto_reg.h" +#include "soc/cpu.h" +#include "driver/periph_ctrl.h" +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 1 +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +int esp_CryptHwMutexInit(wolfSSL_Mutex* mutex); +int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, TickType_t xBloxkTime); +int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex); + +#ifndef NO_AES + +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 1 +#include "esp32/rom/aes.h" +#else +#include "rom/aes.h" +#endif + +typedef enum tagES32_AES_PROCESS { + ESP32_AES_LOCKHW = 1, + ESP32_AES_UPDATEKEY_ENCRYPT = 2, + ESP32_AES_UPDATEKEY_DECRYPT = 3, + ESP32_AES_UNLOCKHW = 4 +} ESP32_AESPROCESS; + +struct Aes; +int wc_esp32AesCbcEncrypt(struct Aes* aes, byte* out, const byte* in, word32 sz); +int wc_esp32AesCbcDecrypt(struct Aes* aes, byte* out, const byte* in, word32 sz); +int wc_esp32AesEncrypt(struct Aes *aes, const byte* in, byte* out); +int wc_esp32AesDecrypt(struct Aes *aes, const byte* in, byte* out); + +#endif + +#ifdef WOLFSSL_ESP32WROOM32_CRYPT_DEBUG + +void wc_esp32TimerStart(); +uint64_t wc_esp32elapsedTime(); + +#endif /* WOLFSSL_ESP32WROOM32_CRYPT_DEBUG */ + +#if (!defined(NO_SHA) || !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || \ + defined(WOLFSSL_SHA512)) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + +/* RAW hash function APIs are not implemented with esp32 hardware acceleration*/ +#define WOLFSSL_NO_HASH_RAW +#if ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 1 +#include "esp32/rom/sha.h" +#else +#include "rom/sha.h" +#endif + +typedef enum { + ESP32_SHA_INIT = 0, + ESP32_SHA_HW = 1, + ESP32_SHA_SW = 2, +} ESP32_DOSHA; + +typedef struct { + byte isfirstblock; + /* 0 , 1 hard, 2 soft */ + byte mode; + /* sha_type */ + enum SHA_TYPE sha_type; +} WC_ESP32SHA; + +int esp_sha_try_hw_lock(WC_ESP32SHA* ctx); +void esp_sha_hw_unlock( void ); + +struct wc_Sha; +int esp_sha_digest_process(struct wc_Sha* sha, byte bockprocess); +int esp_sha_process(struct wc_Sha* sha, const byte* data); + +#ifndef NO_SHA256 + struct wc_Sha256; + int esp_sha256_digest_process(struct wc_Sha256* sha, byte bockprocess); + int esp_sha256_process(struct wc_Sha256* sha, const byte* data); +#endif + +#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) + struct wc_Sha512; + int esp_sha512_process(struct wc_Sha512* sha); + int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc); +#endif + +#endif /* NO_SHA && */ + +#if !defined(NO_RSA) || defined(HAVE_ECC) + +#ifndef ESP_RSA_TIMEOUT + #define ESP_RSA_TIMEOUT 0xFFFFF +#endif + +struct fp_int; +int esp_mp_mul(struct fp_int* X, struct fp_int* Y, struct fp_int* Z); +int esp_mp_exptmod(struct fp_int* G, struct fp_int* X, word32 Xbits, struct fp_int* P, + struct fp_int* Y); +int esp_mp_mulmod(struct fp_int* X, struct fp_int* Y, struct fp_int* M, + struct fp_int* Z); + +#endif /* NO_RSA || HAVE_ECC*/ + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP32_CRYPT_H__ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h new file mode 100644 index 000000000..2055ee024 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h @@ -0,0 +1,153 @@ +/* renesas-tsip-crypt.h + * + * Copyright (C) 2006-2020 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 __RENESAS_TSIP_CRYPT_H__ +#define __RENESAS_TSIP_CRYPT_H__ + +#if defined(WOLFSSL_RENESAS_TSIP_IAREWRX) + #include "r_bsp/mcu/all/r_rx_compiler.h" + #include "r_bsp/platform.h" +#else + #include "platform.h" +#endif + +#include "r_tsip_rx_if.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + tsip_Key_SESSION = 1, + tsip_Key_AES128 = 2, + tsip_Key_AES256 = 3, + tsip_Key_RSA1024 = 4, + tsip_Key_RSA2048 = 5, + tsip_Key_tls_Rsa2048 = 6, + tsip_Key_unknown = -1, +} wolfssl_TSIP_KEY_IV; + +enum { + l_TLS_RSA_WITH_AES_128_CBC_SHA = 0x2F, + l_TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x3c, + l_TLS_RSA_WITH_AES_256_CBC_SHA = 0x35, + l_TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x3d, +}; + +typedef struct +{ + uint8_t *encrypted_session_key; + uint8_t *iv; + uint8_t *encrypted_user_tls_key; + tsip_tls_ca_certification_public_key_index_t user_rsa2048_tls_pubindex; +} tsip_key_data; + +struct WOLFSSL; + +int tsip_Open( ); +void tsip_Close( ); +int tsip_hw_lock(); +void tsip_hw_unlock( void ); +int tsip_usable(const struct WOLFSSL *ssl); +void tsip_inform_sflash_signedcacert(const byte *ps_flash, + const byte *psigned_ca_cert, word32 len); +void tsip_inform_cert_sign(const byte *sign); +/* set / get key */ +void tsip_inform_user_keys(byte *encrypted_session_key, byte *iv, + byte *encrypted_user_tls_key); + +byte tsip_rootCAverified( ); +byte tsip_checkCA(word32 cmIdx); +int tsip_tls_RootCertVerify(const byte *cert , word32 cert_len, + word32 key_n_start, word32 key_n_len, + word32 key_e_start, word32 key_e_len, + word32 cm_row); +int tsip_tls_CertVerify(const byte *cert, word32 certSz, + const byte *signature, word32 sigSz, + word32 key_n_start, word32 key_n_len, + word32 key_e_start, word32 key_e_len, + byte *tsip_encRsaKeyIdx); +void tsip_inform_key_position(const word32 key_n_start, const word32 key_n_len, + const word32 key_e_start, const word32 key_e_len); +int tsip_generatePremasterSecret(byte *premaster, word32 preSz); +int tsip_generateEncryptPreMasterSecret(struct WOLFSSL *ssl, byte *out, + word32 *outSz); +int tsip_generateMasterSecret(const byte *pre, const byte *cr,const byte *sr, + byte *ms); +int tsip_generateSeesionKey(struct WOLFSSL *ssl); +int tsip_Sha256Hmac(const struct WOLFSSL *ssl, const byte *myInner, + word32 innerSz, const byte *in, word32 sz, byte *digest, + word32 verify); +int tsip_Sha1Hmac(const struct WOLFSSL *ssl, const byte *myInner, + word32 innerSz, const byte *in, word32 sz, byte *digest, + word32 verify); + +#if (!defined(NO_SHA) || !defined(NO_SHA256)) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH) + +typedef enum { + TSIP_SHA1 = 0, + TSIP_SHA256 = 1, +} TSIP_SHA_TYPE; + +typedef struct { + byte* msg; + void* heap; + word32 used; + word32 len; + word32 sha_type; +} wolfssl_TSIP_Hash; + +/* RAW hash function APIs are not implemented with TSIP */ +#define WOLFSSL_NO_HASH_RAW + +typedef wolfssl_TSIP_Hash wc_Sha; + +#if !defined(NO_SHA256) + typedef wolfssl_TSIP_Hash wc_Sha256; +#endif + +#endif /* NO_SHA */ + +#if defined(WOLFSSL_RENESAS_TSIP_TLS_AES_CRYPT) +typedef struct { + tsip_aes_key_index_t tsip_keyIdx; + word32 keySize; +} TSIP_AES_CTX; + + struct Aes; + int wc_tsip_AesCbcEncrypt(struct Aes* aes, byte* out, const byte* in, + word32 sz); + int wc_tsip_AesCbcDecrypt(struct Aes* aes, byte* out, const byte* in, + word32 sz); + +#endif /* WOLFSSL_RENESAS_TSIP_TLS_AES */ + +#if defined(WOLFSSL_RENESAS_TSIP_CRYPT_DEBUG) +byte *ret2err(word32 ret); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __RENESAS_TSIP_CRYPT_H__ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/af_alg/afalg_hash.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/af_alg/afalg_hash.h new file mode 100644 index 000000000..bd02913e2 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/af_alg/afalg_hash.h @@ -0,0 +1,50 @@ +/* afalg_hash.h + * + * Copyright (C) 2006-2020 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_AFALG_HASH_H +#define WOLF_CRYPT_AFALG_HASH_H + +#include + +#undef WOLFSSL_NO_HASH_RAW +#define WOLFSSL_NO_HASH_RAW + +typedef struct { + byte* msg; + void* heap; + word32 used; + word32 len; + int alFd; + int rdFd; +} wolfssl_AFALG_Hash; + + + +#if !defined(NO_SHA256) && defined(WOLFSSL_AFALG_HASH) + typedef wolfssl_AFALG_Hash wc_Sha256; +#endif +#if defined(WOLFSSL_SHA3) && defined(WOLFSSL_AFALG_XILINX_SHA3) + typedef wolfssl_AFALG_Hash wc_Sha3; +#endif + +#endif /* WOLF_CRYPT_AFALG_HASH_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/af_alg/wc_afalg.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/af_alg/wc_afalg.h new file mode 100644 index 000000000..d9f5b7155 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/af_alg/wc_afalg.h @@ -0,0 +1,53 @@ +/* wc_afalg.h + * + * Copyright (C) 2006-2020 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_AFALG_H +#define WOLFSSL_AFALG_H + +#include + +#include +#include +#include + +#define WC_SOCK_NOTSET -1 + +/* In some cases these flags are not set in AF_ALG header files. + * Documentation provided at kernel.org/doc/html/v4.16/crypto/userspace-if.html + * suggests using these values if not set */ +#ifndef AF_ALG + #define AF_ALG 38 +#endif +#ifndef SOL_ALG + #define SOL_ALG 279 +#endif + +WOLFSSL_LOCAL void wc_Afalg_SockAddr(struct sockaddr_alg* in, const char* type, const char* name); +WOLFSSL_LOCAL int wc_Afalg_Accept(struct sockaddr_alg* in, int inSz, int sock); +WOLFSSL_LOCAL int wc_Afalg_Socket(void); +WOLFSSL_LOCAL int wc_Afalg_CreateRead(int sock, const char* type, const char* name); +WOLFSSL_LOCAL int wc_Afalg_SetIv(struct cmsghdr* cmsg, byte* iv, word32 ivSz); +WOLFSSL_LOCAL int wc_Afalg_SetOp(struct cmsghdr* cmsg, int dir); +WOLFSSL_LOCAL int wc_Afalg_SetAad(struct cmsghdr* cmsg, word32 sz); + +#endif /* WOLFSSL_AFALG_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/arm/cryptoCell.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/arm/cryptoCell.h new file mode 100644 index 000000000..5ca2d8c19 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/arm/cryptoCell.h @@ -0,0 +1,117 @@ +/* cryptoCell.h + * + * Copyright (C) 2020 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_CRYPTOCELL_H +#define WOLFSSL_CRYPTOCELL_H + +#if defined(WOLFSSL_CRYPTOCELL) +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "sns_silib.h" + +#ifndef NO_SHA256 + #include "crys_hash.h" + #include "crys_hash_error.h" + /* largest possible input data on CC310 DMA. */ + #define CC310_MAX_LENGTH_DMA (0xFFFF) +#endif + +#ifndef NO_AES + #include "ssi_aes.h" + + typedef struct aes_context_t { + SaSiAesUserContext_t user_ctx; /* CC310 AES User context */ + SaSiAesUserKeyData_t key; /* CC310 AES key structure */ + SaSiAesEncryptMode_t mode; /* encrypt or decrypt */ + } aes_context_t; + #define CC310_MAX_LENGTH_DMA_AES (0xFFF0) +#endif /* NO_AES */ + +#if !defined(WC_NO_RNG) + #if defined(WOLFSSL_nRF5x_SDK_15_2) + +/* To fix warning. MIN/MAX are defined in tfm.h and Nordic (re)defines them */ + #undef MIN + #undef MAX +/* includes to use RNG on the nRF52 */ + #include "nrf_drv_rng.h" + #include "nrf_assert.h" + #endif + + /*RNG Global variables*/ + extern CRYS_RND_State_t wc_rndState; + extern CRYS_RND_WorkBuff_t wc_rndWorkBuff; + extern SaSiRndGenerateVectWorkFunc_t wc_rndGenVectFunc; + int cc310_random_generate(byte* output, word32 size); +#endif + +#ifndef NO_RSA + #include "crys_rsa_types.h" + #include "crys_rnd.h" + #include "crys_rsa_schemes.h" + #include "crys_rsa_kg.h" + #include "crys_rsa_build.h" + + typedef struct rsa_context_t { + CRYS_RSAUserPrivKey_t privKey; + CRYS_RSAUserPubKey_t pubKey; + } rsa_context_t; +CRYS_RSA_HASH_OpMode_t cc310_hashModeRSA(enum wc_HashType hash_type, int isHashed); +#endif + +#ifdef HAVE_ECC + #include "crys_ecpki_kg.h" + #include "crys_ecpki_dh.h" + #include "crys_ecpki_build.h" + #include "crys_ecpki_domain.h" + #include "crys_ecpki_ecdsa.h" + + typedef struct ecc_context_t { + CRYS_ECPKI_UserPrivKey_t privKey; + CRYS_ECPKI_UserPublKey_t pubKey; + } ecc_context_t; + +CRYS_ECPKI_DomainID_t cc310_mapCurve(int curve_id); +CRYS_ECPKI_HASH_OpMode_t cc310_hashModeECC(int hash_size); +#endif /* HAVE_ECC */ + +#if !defined(NO_CRYPT_BENCHMARK) && defined(WOLFSSL_nRF5x_SDK_15_2) + /* includes to use Real-time counter (RTC) on nRF52840 */ + #include "nrf_gpio.h" + #include "nrf_drv_rtc.h" + #include "nrf_drv_clock.h" + #include "boards.h" + #include + #include +#endif /* NO_CRYPT_BENCHMARK && WOLFSSL_nRF5x_SDK_15_2*/ + +int cc310_Init(void); +void cc310_Free(void); + +#ifdef __cplusplus +} +#endif +#endif /* WOLFSSL_CRYPTOCELL */ +#endif /* WOLFSSL_CRYPTOCELL_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/atmel/atmel.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/atmel/atmel.h new file mode 100644 index 000000000..70035130c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/atmel/atmel.h @@ -0,0 +1,134 @@ +/* atmel.h + * + * Copyright (C) 2006-2020 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 _ATECC508_H_ +#define _ATECC508_H_ + +#include + +#include +#include + +#if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC_PKCB) + #undef SHA_BLOCK_SIZE + #define SHA_BLOCK_SIZE SHA_BLOCK_SIZE_REMAP + #include + #undef SHA_BLOCK_SIZE +#endif + +/* ATECC508A only supports ECC P-256 */ +#define ATECC_KEY_SIZE (32) +#define ATECC_PUBKEY_SIZE (ATECC_KEY_SIZE*2) /* X and Y */ +#define ATECC_SIG_SIZE (ATECC_KEY_SIZE*2) /* R and S */ +#ifndef ATECC_MAX_SLOT +#define ATECC_MAX_SLOT (0x8) /* Only use 0-7 */ +#endif +#define ATECC_INVALID_SLOT (0xFF) + +/* Device Key for signing */ +#ifndef ATECC_SLOT_AUTH_PRIV +#define ATECC_SLOT_AUTH_PRIV (0x0) +#endif +/* Ephemeral key */ +#ifndef ATECC_SLOT_ECDHE_PRIV +#define ATECC_SLOT_ECDHE_PRIV (0x2) +#endif +/* Symmetric encryption key */ +#ifndef ATECC_SLOT_I2C_ENC +#define ATECC_SLOT_I2C_ENC (0x04) +#endif +/* Parent encryption key */ +#ifndef ATECC_SLOT_ENC_PARENT +#define ATECC_SLOT_ENC_PARENT (0x7) +#endif + +/* ATECC_KEY_SIZE required for ecc.h */ +#include + +struct WOLFSSL; +struct WOLFSSL_CTX; +struct WOLFSSL_X509_STORE_CTX; +struct ecc_key; + +/* Atmel port functions */ +int atmel_init(void); +void atmel_finish(void); +int atmel_get_random_number(uint32_t count, uint8_t* rand_out); +#ifndef ATMEL_GET_RANDOM_BLOCK_DEFINED + int atmel_get_random_block(unsigned char* output, unsigned int sz); + #define ATMEL_GET_RANDOM_BLOCK_DEFINED +#endif +long atmel_get_curr_time_and_date(long* tm); + +#ifdef WOLFSSL_ATECC508A + +enum atmelSlotType { + ATMEL_SLOT_ANY, + ATMEL_SLOT_ENCKEY, + ATMEL_SLOT_DEVICE, + ATMEL_SLOT_ECDHE, + ATMEL_SLOT_ECDHE_ENC, +}; + +int atmel_ecc_alloc(int slotType); +void atmel_ecc_free(int slotId); + +typedef int (*atmel_slot_alloc_cb)(int); +typedef void (*atmel_slot_dealloc_cb)(int); +int atmel_set_slot_allocator(atmel_slot_alloc_cb alloc, + atmel_slot_dealloc_cb dealloc); + +int atmel_ecc_translate_err(int status); +int atmel_get_rev_info(word32* revision); +void atmel_show_rev_info(void); + +/* The macro ATECC_GET_ENC_KEY can be set to override the default + encryption key with your own at build-time */ +#ifndef ATECC_GET_ENC_KEY + #define ATECC_GET_ENC_KEY(enckey, keysize) atmel_get_enc_key_default((enckey), (keysize)) +#endif +int atmel_get_enc_key_default(byte* enckey, word16 keysize); +int atmel_ecc_create_pms(int slotId, const uint8_t* peerKey, uint8_t* pms); +int atmel_ecc_create_key(int slotId, byte* peerKey); +int atmel_ecc_sign(int slotId, const byte* message, byte* signature); +int atmel_ecc_verify(const byte* message, const byte* signature, + const byte* pubkey, int* verified); + +#endif /* WOLFSSL_ATECC508A */ + +#ifdef HAVE_PK_CALLBACKS + int atcatls_create_key_cb(struct WOLFSSL* ssl, struct ecc_key* key, unsigned int keySz, + int ecc_curve, void* ctx); + int atcatls_create_pms_cb(struct WOLFSSL* ssl, struct ecc_key* otherKey, + unsigned char* pubKeyDer, word32* pubKeySz, + unsigned char* out, word32* outlen, + int side, void* ctx); + int atcatls_sign_certificate_cb(struct WOLFSSL* ssl, const byte* in, unsigned int inSz, + byte* out, word32* outSz, const byte* key, unsigned int keySz, void* ctx); + int atcatls_verify_signature_cb(struct WOLFSSL* ssl, const byte* sig, unsigned int sigSz, + const byte* hash, unsigned int hashSz, const byte* key, unsigned int keySz, + int* result, void* ctx); + + int atcatls_set_callbacks(struct WOLFSSL_CTX* ctx); + int atcatls_set_callback_ctx(struct WOLFSSL* ssl, void* user_ctx); +#endif + +#endif /* _ATECC508_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/caam/caam_driver.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/caam/caam_driver.h new file mode 100644 index 000000000..cac1742c0 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/caam/caam_driver.h @@ -0,0 +1,187 @@ +/* caam_driver.h + * + * Copyright (C) 2006-2020 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 CAAM_DRIVER_H +#define CAAM_DRIVER_H + +#define CAAM_BASE 0xf2100000 + +#define CAAM_PAGE 0xf0100000 +#define CAAM_PAGE_MAX 6 + +/****************************************************************************** + Basic Descriptors + ****************************************************************************/ + +/* descriptor commands */ +#define CAAM_KEY 0x00000000 +#define CAAM_LOAD 0x10000000 +#define CAAM_LOAD_CTX 0x10200000 +#define CAAM_IMM 0x00800000 +#define CAAM_FIFO_L 0x20000000 +#define CAAM_FIFO_S 0x60000000 +#define CAAM_FIFO_S_SKEY 0x60260000 +#define CAAM_STORE 0x50000000 +#define CAAM_STORE_CTX 0x50200000 +#define CAAM_MOVE 0x78000000 +#define CAAM_OP 0x80000000 +#define CAAM_SIG 0x90000000 +#define CAAM_JUMP 0xA0000000 +#define CAAM_SEQI 0xF0000000/* SEQ in */ +#define CAAM_SEQO 0xF8000000/* SEQ out */ +#define CAAM_HEAD 0xB0800000 +#define CAAM_NWB 0x00200000 + +#define CAAM_BLOB_ENCAP 0x07000000 +#define CAAM_BLOB_DECAP 0x06000000 +#define CAAM_OPID_BLOB 0x000D0000 + +/* algorithms modes and types */ +#define CAAM_CLASS1 0x02000000/* i.e. AES */ +#define CAAM_CLASS2 0x04000000/* i.e. hash algos */ + +#define CAAM_ENC 0x00000001 +#define CAAM_DEC 0x00000000 +#define CAAM_ALG_INIT 0x00000004 +#define CAAM_ALG_INITF 0x0000000C +#define CAAM_ALG_UPDATE 0x00000000 +#define CAAM_ALG_FINAL 0x00000008 + + /* AES 10h */ +#define CAAM_AESCTR 0x00100000 +#define CAAM_AESCBC 0x00100100 +#define CAAM_AESECB 0x00100200 +#define CAAM_AESCFB 0x00100300 +#define CAAM_AESOFB 0x00100400 +#define CAAM_CMAC 0x00100600 +#define CAAM_AESCCM 0x00100800 + + /* HASH 40h */ +#define CAAM_MD5 0x00400000 +#define CAAM_SHA 0x00410000 +#define CAAM_SHA224 0x00420000 +#define CAAM_SHA256 0x00430000 +#define CAAM_SHA384 0x00440000 +#define CAAM_SHA512 0x00450000 + + /* HMAC 40h + 10 AAI */ +#define CAAM_HMAC_MD5 0x00400010 +#define CAAM_HMAC_SHA 0x00410010 +#define CAAM_HMAC_SHA224 0x00420010 +#define CAAM_HMAC_SHA256 0x00430010 +#define CAAM_HMAC_SHA384 0x00440010 +#define CAAM_HMAC_SHA512 0x00450010 + +#define CAAM_MD5_CTXSZ (16 + 8) +#define CAAM_SHA_CTXSZ (20 + 8) +#define CAAM_SHA224_CTXSZ (32 + 8) +#define CAAM_SHA256_CTXSZ (32 + 8) +#define CAAM_SHA384_CTXSZ (64 + 8) +#define CAAM_SHA512_CTXSZ (64 + 8) + + /* RNG 50h */ +#define CAAM_RNG 0x00500000 + + /* Used to get raw entropy from TRNG */ +#define CAAM_ENTROPY 0x00500001 + +#define FIFOL_TYPE_MSG 0x00100000 +#define FIFOL_TYPE_AAD 0x00300000 +#define FIFOL_TYPE_FC1 0x00010000 +#define FIFOL_TYPE_LC1 0x00020000 +#define FIFOL_TYPE_LC2 0x00040000 + +#define FIFOS_TYPE_MSG 0x00300000 + +/* continue bit set if more output is expected */ +#define CAAM_FIFOS_CONT 0x00800000 + +#define CAAM_PAGE_SZ 4096 + +/* RNG Registers */ +#define CAAM_RTMCTL CAAM_BASE + 0X0600 +#define CAAM_RTSDCTL CAAM_BASE + 0X0610 +#define CAAM_RTFRQMIN CAAM_BASE + 0X0618 +#define CAAM_RTFRQMAX CAAM_BASE + 0X061C +#define CAAM_RDSTA CAAM_BASE + 0X06C0 +#define CAAM_RTSTATUS CAAM_BASE + 0x063C + +/* each of the following 11 RTENT registers are an offset of 4 from RTENT0 */ +#define CAAM_RTENT0 CAAM_BASE + 0x0640 +#define CAAM_RTENT11 CAAM_BASE + 0x066C /* Max RTENT register */ + +/* RNG Masks/Values */ +#ifndef CAAM_ENT_DLY + #define CAAM_ENT_DLY 1200 /* @TODO lower value may gain performance */ +#endif +#define CAAM_PRGM 0x00010000 /* Set RTMCTL to program state */ +#define CAAM_TRNG 0x00000020 /* Set TRNG access */ +#define CAAM_CTLERR 0x00001000 +#define CAAM_ENTVAL 0x00000400 /* checking RTMCTL for entropy ready */ + +/* Input Job Ring Registers */ +#define CAAM_IRBAR0 CAAM_BASE + 0x1004 +#define CAAM_IRSR0 CAAM_BASE + 0x100C +#define CAAM_IRJAR0 CAAM_BASE + 0x101C + +/* Output Job Ring Registers */ +#define CAAM_ORBAR0 CAAM_BASE + 0x1024 +#define CAAM_ORSR0 CAAM_BASE + 0x102C +#define CAAM_ORJAR0 CAAM_BASE + 0x103C + + +/* Status Registers */ +#define CAAM_STATUS CAAM_BASE + 0x0FD4 +#define CAAM_VERSION_MS CAAM_BASE + 0x0FE8 +#define CAAM_VERSION_LS CAAM_BASE + 0x0FEC +#define CAMM_SUPPORT_MS CAAM_BASE + 0x0FF0 +#define CAMM_SUPPORT_LS CAAM_BASE + 0x0FF4 + + +#define CAAM_C1DSR_LS CAAM_BASE + 0x8014 +#define CAAM_C1MR CAAM_BASE + 0x8004 + + +/* output FIFO is 16 entries deep and each entry has a two 4 byte registers */ +#define CAAM_FIFOO_MS CAAM_BASE + 0x87F0 +#define CAAM_FIFOO_LS CAAM_BASE + 0x87F4 + +/* input FIFO is 16 entries deep with each entry having two 4 byte registers + All data written to it from IP bus should be in big endian format */ +#define CAAM_FIFOI_LS CAAM_BASE + 0x87E0 + +/* offset of 4 with range 0 .. 13 */ +#define CAAM_CTX1 CAAM_BASE + 0x8100 +#define CAAM_CTRIV CAAM_CTX1 + 8 /* AES-CTR iv is in 2 and 3 */ +#define CAAM_CBCIV CAAM_CTX1 /* AES-CBC iv is in 1 and 2 */ + + +/* instantiate RNG and create JDKEK, TDKEK, and TDSK key */ +static unsigned int wc_rng_start[] = { + CAAM_HEAD | 0x00000006, + CAAM_OP | CAAM_CLASS1 | CAAM_RNG | 0x00000004, /* Instantiate RNG handle 0 with TRNG */ + CAAM_JUMP | 0x02000001, /* wait for Class1 RNG and jump to next cmd */ + CAAM_LOAD | 0x00880004, /* Load to clear written register */ + 0x00000001, /* reset done interrupt */ + CAAM_OP | CAAM_CLASS1 | CAAM_RNG | 0x00001000 /* Generate secure keys */ +}; + +#endif /* CAAM_DRIVER_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/caam/wolfcaam.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/caam/wolfcaam.h new file mode 100644 index 000000000..8c39605d7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/caam/wolfcaam.h @@ -0,0 +1,63 @@ +/* wolfcaam.h + * + * Copyright (C) 2006-2020 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_CAAM_INIT_H +#define WOLF_CRYPT_CAAM_INIT_H + +#include + +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) + +#include + +#if defined(__INTEGRITY) || defined(INTEGRITY) + #include +#endif + +WOLFSSL_LOCAL int wc_caamInit(void); +WOLFSSL_LOCAL int wc_caamFree(void); +WOLFSSL_LOCAL int wc_caamInitRng(void); +WOLFSSL_LOCAL int wc_caamFreeRng(void); + +WOLFSSL_LOCAL word32 wc_caamReadRegister(word32 reg); +WOLFSSL_LOCAL void wc_caamWriteRegister(word32 reg, word32 value); +WOLFSSL_LOCAL int wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type); + +WOLFSSL_API int wc_caamSetResource(IODevice ioDev); + +WOLFSSL_API int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, + word32* outSz); +WOLFSSL_API int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, + word32* outSz); + +/* additional size that is added by CAAM when creating a blob */ +#define WC_CAAM_BLOB_SZ 48 + +#ifndef WC_CAAM_READ + #define WC_CAAM_READ(reg) wc_caamReadRegister((reg)) +#endif +#ifndef WC_CAAM_WRITE + #define WC_CAAM_WRITE(reg, x) wc_caamWriteRegister((reg), (x)) +#endif + +#endif /* WOLFSSL_IMX6_CAAM */ + +#endif /* WOLF_CRYPT_CAAM_INIT_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h new file mode 100644 index 000000000..9f5eaf8b5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h @@ -0,0 +1,88 @@ +/* wolfcaam_sha.h + * + * Copyright (C) 2006-2020 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_CAAM_SHA_H +#define WOLF_CRYPT_CAAM_SHA_H + +#include + +#ifdef WOLFSSL_IMX6_CAAM + +#include + +#define WOLFSSL_NO_HASH_RAW + +#ifndef WC_CAAM_CTXLEN +/* last 8 bytes of context is for length */ +#define WC_CAAM_CTXLEN 8 +#endif + +#ifndef WC_CAAM_HASH_BLOCK +/* define sha structures and also get the max possible digest. Start with SHA + digest size */ +#define WC_CAAM_HASH_BLOCK 64 +#endif + +#ifndef WC_CAAM_MAX_DIGEST +#define WC_CAAM_MAX_DIGEST 20 +#ifdef WOLFSSL_SHA224 + #undef WC_CAAM_MAX_DIGEST + #define WC_CAAM_MAX_DIGEST 32 +#endif + +#ifndef NO_SHA256 + #undef WC_CAAM_MAX_DIGEST + #define WC_CAAM_MAX_DIGEST 32 +#endif + +#ifdef WOLFSSL_SHA384 + #undef WC_CAAM_MAX_DIGEST + #define WC_CAAM_MAX_DIGEST 64 +#endif + +#ifdef WOLFSSL_SHA512 + #undef WC_CAAM_MAX_DIGEST + #define WC_CAAM_MAX_DIGEST 64 +#endif +#endif /* WC_CAAM_MAX_DIGEST */ + + +typedef struct wc_Sha { + word32 ctx[(WC_CAAM_MAX_DIGEST + WC_CAAM_CTXLEN) / sizeof(word32)]; + word32 buffLen; /* in bytes */ + word32 buffer[WC_CAAM_HASH_BLOCK / sizeof(word32)]; +} wc_Sha; + +#ifndef NO_MD5 + typedef struct wc_Sha wc_Md5; +#endif + +#ifndef NO_SHA256 + typedef struct wc_Sha wc_Sha256; +#endif + +#ifdef WOLFSSL_SHA512 + typedef struct wc_Sha wc_Sha512; +#endif + +#endif /* WOLFSSL_IMX6_CAAM */ + +#endif /* WOLF_CRYPT_CAAM_SHA_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h new file mode 100644 index 000000000..f7914b8e7 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h @@ -0,0 +1,31 @@ +/* cavium_octeon_sync.h + * + * Copyright (C) 2006-2020 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_OCTEON_SYNC_H_ +#define _CAVIUM_OCTEON_SYNC_H_ + +#ifdef HAVE_CAVIUM_OCTEON_SYNC + +WOLFSSL_API int wc_CryptoCb_InitOcteon(void); +WOLFSSL_API void wc_CryptoCb_CleanupOcteon(int* id); + +#endif /* HAVE_CAVIUM_OCTEON_SYNC */ +#endif /* _CAVIUM_OCTEON_SYNC_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h new file mode 100644 index 000000000..c8ddbe7b9 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h @@ -0,0 +1,53 @@ +/* wc_devcrypto.h + * + * Copyright (C) 2006-2020 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_DEVCRYPTO_H +#define WOLFSSL_DEVCRYPTO_H + +#include + +#ifdef WOLFSSL_DEVCRYPTO + +#include +#include +#include +#include + +typedef struct WC_CRYPTODEV { + int cfd; + struct session_op sess; +} WC_CRYPTODEV; + +WOLFSSL_LOCAL int wc_DevCryptoCreate(WC_CRYPTODEV* ctx, int type, byte* key, word32 keySz); +WOLFSSL_LOCAL void wc_DevCryptoFree(WC_CRYPTODEV* ctx); +WOLFSSL_LOCAL void wc_SetupCrypt(struct crypt_op* crt, WC_CRYPTODEV* dev, + byte* src, int srcSz, byte* dst, byte* dig, int flag); +WOLFSSL_LOCAL void wc_SetupCryptSym(struct crypt_op* crt, WC_CRYPTODEV* dev, + byte* src, word32 srcSz, byte* dst, byte* iv, int flag); +WOLFSSL_LOCAL void wc_SetupCryptAead(struct crypt_auth_op* crt, WC_CRYPTODEV* dev, + byte* src, word32 srcSz, byte* dst, byte* iv, word32 ivSz, int flag, + byte* authIn, word32 authInSz, byte* authTag, word32 authTagSz); + +#endif /* WOLFSSL_DEVCRYPTO */ +#endif /* WOLFSSL_DEVCRYPTO_H */ + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/intel/quickassist.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/intel/quickassist.h new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/intel/quickassist_mem.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/intel/quickassist_mem.h new file mode 100644 index 000000000..e69de29bb diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/intel/quickassist_sync.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/intel/quickassist_sync.h new file mode 100644 index 000000000..8eb9421f9 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/intel/quickassist_sync.h @@ -0,0 +1,53 @@ +/* quickassist_sync.h + * + * Copyright (C) 2006-2020 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 _INTEL_QUICKASSIST_SYNC_H_ +#define _INTEL_QUICKASSIST_SYNC_H_ + +#ifdef HAVE_INTEL_QA_SYNC + +WOLFSSL_API int wc_CryptoCb_InitIntelQa(void); +WOLFSSL_API void wc_CryptoCb_CleanupIntelQa(int* id); + +WOLFSSL_API void* wc_CryptoCb_IntelQaMalloc(size_t size, + void* heap, int type +#ifdef WOLFSSL_DEBUG_MEMORY + , const char* func, unsigned int line +#endif +); + +WOLFSSL_API void wc_CryptoCb_IntelQaFree(void *ptr, + void* heap, int type +#ifdef WOLFSSL_DEBUG_MEMORY + , const char* func, unsigned int line +#endif +); + +WOLFSSL_API void* wc_CryptoCb_IntelQaRealloc(void *ptr, + size_t size, void* heap, int type +#ifdef WOLFSSL_DEBUG_MEMORY + , const char* func, unsigned int line +#endif +); + +#endif /* HAVE_INTEL_QA_SYNC */ + +#endif /* _INTEL_QUICKASSIST_SYNC_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/nrf51.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/nrf51.h new file mode 100644 index 000000000..b18b0400a --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/nrf51.h @@ -0,0 +1,44 @@ +/* nrf51.h + * + * Copyright (C) 2006-2020 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_NRF51_PORT_H +#define WOLFSSL_NRF51_PORT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Public Functions */ +int nrf51_random_generate(byte* output, word32 sz); + +int nrf51_aes_set_key(const byte* key); +int nrf51_aes_encrypt(const byte* in, const byte* key, word32 rounds, byte* out); + +double current_time(int reset); + +#ifdef __cplusplus +} +#endif + +#endif /* WOLFSSL_NRF51_PORT_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/nxp/ksdk_port.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/nxp/ksdk_port.h new file mode 100644 index 000000000..749a3eeb5 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/nxp/ksdk_port.h @@ -0,0 +1,93 @@ +/* ksdk_port.h + * + * Copyright (C) 2006-2020 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 _KSDK_PORT_H_ +#define _KSDK_PORT_H_ + +#include +#ifdef USE_FAST_MATH + #include +#elif defined WOLFSSL_SP_MATH + #include +#else + #include +#endif +#include +#include +#include + + +/* API to init required hardware */ +int ksdk_port_init(void); + +/* software algorithm, by wolfcrypt */ +#if defined(FREESCALE_LTC_TFM) + 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); + + /* Exported mp_mulmod function */ + int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +#endif /* FREESCALE_LTC_TFM */ + +#if defined(FREESCALE_LTC_ECC) + #include "fsl_ltc.h" + + typedef enum _fsl_ltc_ecc_coordinate_system + { + kLTC_Weierstrass = 0U, /*< Point coordinates on an elliptic curve in Weierstrass form */ + kLTC_Curve25519 = 1U, /*< Point coordinates on an Curve25519 elliptic curve in Montgomery form */ + kLTC_Ed25519 = 2U, /*< Point coordinates on an Ed25519 elliptic curve in twisted Edwards form */ + } fsl_ltc_ecc_coordinate_system_t; + + int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m); + + #ifdef HAVE_CURVE25519 + int wc_curve25519(ECPoint *q, byte *n, const ECPoint *p, fsl_ltc_ecc_coordinate_system_t type); + const ECPoint *wc_curve25519_GetBasePoint(void); + status_t LTC_PKHA_Curve25519ToWeierstrass(const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut); + status_t LTC_PKHA_WeierstrassToCurve25519(const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut); + status_t LTC_PKHA_Curve25519ComputeY(ltc_pkha_ecc_point_t *ltcPoint); + #endif + + #ifdef HAVE_ED25519 + status_t LTC_PKHA_Ed25519ToWeierstrass(const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut); + status_t LTC_PKHA_WeierstrassToEd25519(const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut); + status_t LTC_PKHA_Ed25519_PointMul(const ltc_pkha_ecc_point_t *ltcPointIn, + const uint8_t *N, + size_t sizeN, + ltc_pkha_ecc_point_t *ltcPointOut, + fsl_ltc_ecc_coordinate_system_t typeOut); + const ltc_pkha_ecc_point_t *LTC_PKHA_Ed25519_BasePoint(void); + status_t LTC_PKHA_Ed25519_PointDecompress(const uint8_t *pubkey, size_t pubKeySize, ltc_pkha_ecc_point_t *ltcPointOut); + status_t LTC_PKHA_sc_reduce(uint8_t *a); + status_t LTC_PKHA_sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b, const uint8_t *c); + status_t LTC_PKHA_SignatureForVerify(uint8_t *rcheck, const unsigned char *a, const unsigned char *b, ed25519_key *key); + status_t LTC_PKHA_Ed25519_Compress(const ltc_pkha_ecc_point_t *ltcPointIn, uint8_t *p); + #endif + +#endif /* FREESCALE_LTC_ECC */ + +#endif /* _KSDK_PORT_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h index 44c54d74e..bb288c777 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h @@ -1,8 +1,8 @@ /* pic32mz-crypt.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,19 +16,48 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + #ifndef PIC32MZ_CRYPT_H #define PIC32MZ_CRYPT_H -#ifdef WOLFSSL_MICROCHIP_PIC32MZ +#ifdef __cplusplus + extern "C" { +#endif + +#include + +#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; @@ -62,11 +91,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 { @@ -81,58 +111,114 @@ 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 descripter */ - 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 +#define WOLFSSL_NO_HASH_RAW + +int wc_Pic32Hash(const byte* in, int inLen, word32* out, int outLen, int algo); +int wc_Pic32HashCopy(hashUpdCache* src, hashUpdCache* dst); + +#ifndef NO_MD5 +struct wc_Md5; +void wc_Md5Pic32Free(struct wc_Md5* md5); #endif +#ifndef NO_SHA +struct wc_Sha; +void wc_ShaPic32Free(struct wc_Sha* sha); +#endif + +#ifndef NO_SHA256 +struct wc_Sha256; +void wc_Sha256Pic32Free(struct wc_Sha256* sha256); +#endif +#endif /* WOLFSSL_PIC32MZ_HASH */ + +#endif /* WOLFSSL_MICROCHIP_PIC32MZ */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + #endif /* PIC32MZ_CRYPT_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/st/stm32.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/st/stm32.h new file mode 100644 index 000000000..4b461a113 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/st/stm32.h @@ -0,0 +1,142 @@ +/* stm32.h + * + * Copyright (C) 2006-2020 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 _WOLFPORT_STM32_H_ +#define _WOLFPORT_STM32_H_ + +/* Generic STM32 Hashing and Crypto Functions */ +/* Supports CubeMX HAL or Standard Peripheral Library */ + +#include +#include + +#if defined(WOLFSSL_STM32_PKA) && defined(HAVE_ECC) + #include + #include +#endif + +#ifdef STM32_HASH + +#define WOLFSSL_NO_HASH_RAW + +#ifdef HASH_DIGEST + /* The HASH_DIGEST register indicates SHA224/SHA256 support */ + #define STM32_HASH_SHA2 + #define HASH_CR_SIZE 54 + #define HASH_MAX_DIGEST 32 +#else + #define HASH_CR_SIZE 50 + #define HASH_MAX_DIGEST 20 +#endif + +/* Handle hash differences between CubeMX and StdPeriLib */ +#if !defined(HASH_ALGOMODE_HASH) && defined(HASH_AlgoMode_HASH) + #define HASH_ALGOMODE_HASH HASH_AlgoMode_HASH +#endif +#if !defined(HASH_DATATYPE_8B) && defined(HASH_DataType_8b) + #define HASH_DATATYPE_8B HASH_DataType_8b +#endif + +#ifndef STM32_HASH_TIMEOUT + #define STM32_HASH_TIMEOUT 0xFFFF +#endif + + +/* STM32 register size in bytes */ +#define STM32_HASH_REG_SIZE 4 + +/* STM32 Hash Context */ +typedef struct { + /* Context switching registers */ + uint32_t HASH_IMR; + uint32_t HASH_STR; + uint32_t HASH_CR; + uint32_t HASH_CSR[HASH_CR_SIZE]; + + /* Hash state / buffers */ + word32 buffer[STM32_HASH_REG_SIZE / sizeof(word32)]; /* partial word buffer */ + word32 buffLen; /* partial word remain */ + word32 loLen; /* total update bytes + (only lsb 6-bits is used for nbr valid bytes in last word) */ +} STM32_HASH_Context; + + +/* API's */ +void wc_Stm32_Hash_Init(STM32_HASH_Context* stmCtx); +int wc_Stm32_Hash_Update(STM32_HASH_Context* stmCtx, word32 algo, + const byte* data, int len); +int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo, + byte* hash, int digestSize); + +#endif /* STM32_HASH */ + + +#ifdef STM32_CRYPTO + +#ifndef NO_AES + #if !defined(STM32_CRYPTO_AES_GCM) && (defined(WOLFSSL_STM32F4) || \ + defined(WOLFSSL_STM32F7) || defined(WOLFSSL_STM32L4)) + /* Hardware supports AES GCM acceleration */ + #define STM32_CRYPTO_AES_GCM + #endif + + #ifdef WOLFSSL_STM32L4 + #define STM32_CRYPTO_AES_ONLY /* crypto engine only supports AES */ + #define CRYP AES + #endif + + /* Detect newer CubeMX crypto HAL (HAL_CRYP_Encrypt / HAL_CRYP_Decrypt) */ + #if !defined(STM32_HAL_V2) && \ + defined(WOLFSSL_STM32F7) && defined(CRYP_AES_GCM) + #define STM32_HAL_V2 + #endif + + /* The datatype for STM32 CubeMX HAL Crypt calls */ + #ifdef STM32_HAL_V2 + #define STM_CRYPT_TYPE uint32_t + #else + #define STM_CRYPT_TYPE uint8_t + #endif + + /* CRYPT_AES_GCM starts the IV with 2 */ + #define STM32_GCM_IV_START 2 + + struct Aes; + #ifdef WOLFSSL_STM32_CUBEMX + int wc_Stm32_Aes_Init(struct Aes* aes, CRYP_HandleTypeDef* hcryp); + #else /* STD_PERI_LIB */ + int wc_Stm32_Aes_Init(struct Aes* aes, CRYP_InitTypeDef* cryptInit, + CRYP_KeyInitTypeDef* keyInit); + #endif /* WOLFSSL_STM32_CUBEMX */ +#endif /* !NO_AES */ + +#endif /* STM32_CRYPTO */ + +#if defined(WOLFSSL_STM32_PKA) && defined(HAVE_ECC) +int stm32_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, + word32 hashlen, int* res, ecc_key* key); + +int stm32_ecc_sign_hash_ex(const byte* hash, word32 hashlen, WC_RNG* rng, + ecc_key* key, mp_int *r, mp_int *s); +#endif + + +#endif /* _WOLFPORT_STM32_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/st/stsafe.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/st/stsafe.h new file mode 100644 index 000000000..3cee4461d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/st/stsafe.h @@ -0,0 +1,99 @@ +/* stsafe.h + * + * Copyright (C) 2006-2020 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 _WOLFPORT_STSAFE_H_ +#define _WOLFPORT_STSAFE_H_ + +#include +#include +#include + +#ifdef WOLF_CRYPTO_CB +#include +#endif + +#if !defined(WOLFCRYPT_ONLY) && defined(HAVE_PK_CALLBACKS) +#include +#endif + +#ifdef WOLFSSL_STSAFEA100 + +/* The wolf STSAFE interface layer */ +/* Please contact wolfSSL for the STSAFE port files */ +#include "stsafe_interface.h" + +#ifndef STSAFE_MAX_KEY_LEN + #define STSAFE_MAX_KEY_LEN ((uint32_t)48) /* for up to 384-bit keys */ +#endif +#ifndef STSAFE_MAX_PUBKEY_RAW_LEN + #define STSAFE_MAX_PUBKEY_RAW_LEN ((uint32_t)STSAFE_MAX_KEY_LEN * 2) /* x/y */ +#endif +#ifndef STSAFE_MAX_SIG_LEN + #define STSAFE_MAX_SIG_LEN ((uint32_t)STSAFE_MAX_KEY_LEN * 2) /* r/s */ +#endif + +WOLFSSL_API int SSL_STSAFE_LoadDeviceCertificate(byte** pRawCertificate, + word32* pRawCertificateLen); + +#if !defined(WOLFCRYPT_ONLY) && defined(HAVE_PK_CALLBACKS) +WOLFSSL_API int SSL_STSAFE_CreateKeyCb(WOLFSSL* ssl, ecc_key* key, word32 keySz, + int ecc_curve, void* ctx); +WOLFSSL_API int SSL_STSAFE_VerifyPeerCertCb(WOLFSSL* ssl, + const unsigned char* sig, unsigned int sigSz, + const unsigned char* hash, unsigned int hashSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx); +WOLFSSL_API int SSL_STSAFE_SignCertificateCb(WOLFSSL* ssl, + const byte* in, word32 inSz, + byte* out, word32* outSz, + const byte* key, word32 keySz, void* ctx); +WOLFSSL_API int SSL_STSAFE_SharedSecretCb(WOLFSSL* ssl, + ecc_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx); + +/* Helper API's for setting up callbacks */ +WOLFSSL_API int SSL_STSAFE_SetupPkCallbacks(WOLFSSL_CTX* ctx); +WOLFSSL_API int SSL_STSAFE_SetupPkCallbackCtx(WOLFSSL* ssl, void* user_ctx); +#endif /* HAVE_PK_CALLBACKS */ + + +#ifdef WOLF_CRYPTO_CB + +/* Device ID that's unique and valid (not INVALID_DEVID -2) */ +#define WOLF_STSAFE_DEVID 0x53545341; /* STSA */ + +typedef struct wolfSTSAFE_CryptoCb_Ctx { +#ifdef HAVE_ECC + ecc_key wolfEccKey; +#endif + int devId; +} wolfSTSAFE_CryptoCb_Ctx; + +WOLFSSL_API int wolfSSL_STSAFE_CryptoDevCb(int devId, wc_CryptoInfo* info, + void* ctx); + +#endif /* WOLF_CRYPTO_CB */ + +#endif /* WOLFSSL_STSAFEA100 */ + +#endif /* _WOLFPORT_STSAFE_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/ti/ti-ccm.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/ti/ti-ccm.h index f0fb24799..f5d71fca1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/ti/ti-ccm.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/ti/ti-ccm.h @@ -1,8 +1,8 @@ /* port/ti/ti_ccm.c * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,8 +16,12 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + + +#ifndef WOLF_CRYPT_TI_CCM_H +#define WOLF_CRYPT_TI_CCM_H #ifdef HAVE_CONFIG_H #include @@ -27,14 +31,17 @@ #if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) -bool wolfSSL_TI_CCMInit(void) ; +int wolfSSL_TI_CCMInit(void) ; #ifndef SINGLE_THREADED -void wolfSSL_TI_lockCCM() ; -void wolfSSL_TI_unlockCCM() ; -#else +void wolfSSL_TI_lockCCM(void) ; +void wolfSSL_TI_unlockCCM(void) ; +#else #define wolfSSL_TI_lockCCM() #define wolfSSL_TI_unlockCCM() #endif #endif + +#endif + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/ti/ti-hash.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/ti/ti-hash.h index 505ccc498..1c212458c 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/ti/ti-hash.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/ti/ti-hash.h @@ -1,8 +1,8 @@ /* port/ti/ti-hash.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,49 +16,48 @@ * * 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 + * 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 + +#define WOLFSSL_NO_HASH_RAW 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/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h new file mode 100644 index 000000000..47b462424 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h @@ -0,0 +1,45 @@ +/* xil-sha3.h + * + * Copyright (C) 2006-2020 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; +} wc_Sha3; + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_SHA3 */ +#endif /* WOLF_XIL_CRYPT_SHA3_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pwdbased.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pwdbased.h index 0173beef8..13860fecb 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pwdbased.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/pwdbased.h @@ -1,8 +1,8 @@ /* pwdbased.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/pwdbased.h +*/ + #ifndef WOLF_CRYPT_PWDBASED_H #define WOLF_CRYPT_PWDBASED_H @@ -26,35 +30,43 @@ #ifndef NO_PWDBASED -#ifndef NO_MD5 - #include /* for hash type */ -#endif - -#include #ifdef __cplusplus extern "C" { #endif /* - * hashType renamed to typeH to avoid shadowing global declation here: + * hashType renamed to typeH to avoid shadowing global declaration here: * wolfssl/wolfcrypt/asn.h line 173 in enum Oid_Types */ +WOLFSSL_API int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen, + const byte* passwd, int passwdLen, + const byte* salt, int saltLen, int iterations, + int hashType, void* heap); WOLFSSL_API int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, int sLen, int iterations, int kLen, int typeH); +WOLFSSL_API int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen, + const byte* salt, int sLen, int iterations, int kLen, + int typeH, void* heap, int devId); WOLFSSL_API int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, int sLen, int iterations, int kLen, int typeH); WOLFSSL_API int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int pLen, const byte* salt, int sLen, int iterations, int kLen, int typeH, int purpose); +WOLFSSL_API int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd,int passLen, + const byte* salt, int saltLen, int iterations, int kLen, + int hashType, int id, void* heap); -/* helper functions */ -WOLFSSL_LOCAL int GetDigestSize(int hashType); -WOLFSSL_LOCAL int GetPKCS12HashSizes(int hashType, word32* v, word32* u); -WOLFSSL_LOCAL int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, - byte* Ai, word32 u, int iterations); +#ifdef HAVE_SCRYPT +WOLFSSL_API int wc_scrypt(byte* output, const byte* passwd, int passLen, + const byte* salt, int saltLen, int cost, + int blockSize, int parallel, int dkLen); +WOLFSSL_API int wc_scrypt_ex(byte* output, const byte* passwd, int passLen, + const byte* salt, int saltLen, word32 iterations, + int blockSize, int parallel, int dkLen); +#endif #ifdef __cplusplus diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/rabbit.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/rabbit.h index ea5ae7308..20c269398 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/rabbit.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/rabbit.h @@ -1,8 +1,8 @@ /* rabbit.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/rabbit.h +*/ + + #ifndef WOLF_CRYPT_RABBIT_H #define WOLF_CRYPT_RABBIT_H @@ -48,12 +53,16 @@ typedef struct RabbitCtx { typedef struct Rabbit { RabbitCtx masterCtx; RabbitCtx workCtx; +#ifdef XSTREAM_ALIGN + void* heap; /* heap hint, currently XMALLOC only used with aligning */ +#endif } Rabbit; WOLFSSL_API int wc_RabbitProcess(Rabbit*, byte*, const byte*, word32); WOLFSSL_API int wc_RabbitSetKey(Rabbit*, const byte* key, const byte* iv); +WOLFSSL_LOCAL int wc_Rabbit_SetHeap(Rabbit* ctx, void* heap); #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/random.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/random.h index 192144324..aaa21c48b 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/random.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/random.h @@ -1,8 +1,8 @@ /* random.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,17 +16,28 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/random.h +*/ + + #ifndef WOLF_CRYPT_RANDOM_H #define WOLF_CRYPT_RANDOM_H #include -#ifdef HAVE_FIPS -/* for fips @wc_fips */ +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +/* included for fips @wc_fips */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) #include #endif @@ -34,16 +45,81 @@ extern "C" { #endif -#ifndef HAVE_FIPS /* avoid redefining structs and macros */ -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) + /* Maximum generate block length */ +#ifndef RNG_MAX_BLOCK_LEN + #ifdef HAVE_INTEL_QA + #define RNG_MAX_BLOCK_LEN (0xFFFFl) + #else + #define RNG_MAX_BLOCK_LEN (0x10000l) + #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 + + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +/* RNG supports the following sources (in order): + * 1. CUSTOM_RAND_GENERATE_BLOCK: Defines name of function as RNG source and + * 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. + */ + + /* Seed source can be overridden 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) #ifdef NO_SHA256 #error "Hash DRBG requires SHA-256." #endif /* NO_SHA256 */ - #include -#else /* HAVE_HASHDRBG || NO_RC4 */ - #include -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#elif defined(HAVE_WNR) + /* allow whitewood as direct RNG source using wc_GenerateSeed directly */ +#elif defined(HAVE_INTEL_RDRAND) + /* Intel RDRAND or RDSEED */ +#elif !defined(WC_NO_RNG) + #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) @@ -62,78 +138,109 @@ typedef struct OS_Seed { #else int fd; #endif + #if defined(WOLF_CRYPTO_CB) + int devId; + #endif } OS_Seed; -#if defined(WOLFSSL_MDK_ARM) -#undef RNG -#define RNG wolfSSL_RNG /* for avoiding name conflict in "stm32f2xx.h" */ +#ifndef WC_RNG_TYPE_DEFINED /* guard on redeclaration */ + typedef struct WC_RNG WC_RNG; + #define WC_RNG_TYPE_DEFINED #endif - -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) - - -#define DRBG_SEED_LEN (440/8) - - -struct DRBG; /* Private DRBG state */ - - -/* Hash-based Deterministic Random Bit Generator */ -typedef struct RNG { +/* RNG context */ +struct WC_RNG { + OS_Seed seed; + void* heap; +#ifdef HAVE_HASHDRBG + /* Hash-based Deterministic Random Bit Generator */ struct DRBG* drbg; - OS_Seed seed; - byte status; -} RNG; - - -#else /* HAVE_HASHDRBG || NO_RC4 */ - - -#define WOLFSSL_RNG_CAVIUM_MAGIC 0xBEEF0004 - -/* secure Random Number Generator */ - - -typedef struct RNG { - OS_Seed seed; - Arc4 cipher; -#ifdef HAVE_CAVIUM - int devId; /* nitrox device id */ - word32 magic; /* using cavium magic */ +#if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY) + #define DRBG_STRUCT_SZ ((sizeof(word32)*3) + (DRBG_SEED_LEN*2)) + #ifdef WOLFSSL_SMALL_STACK_CACHE + #define DRBG_STRUCT_SZ_SHA256 (sizeof(wc_Sha256)) + #else + #define DRBG_STRUCT_SZ_SHA256 0 + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + #define DRBG_STRUCT_SZ_ASYNC (sizeof(void*) + sizeof(int)) + #else + #define DRBG_STRUCT_SZ_ASYNC 0 + #endif + byte drbg_data[DRBG_STRUCT_SZ + DRBG_STRUCT_SZ_SHA256 + DRBG_STRUCT_SZ_ASYNC]; #endif -} RNG; + byte status; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + int devId; +#endif +}; +#endif /* NO FIPS or have FIPS v2*/ -#endif /* HAVE_HASH_DRBG || NO_RC4 */ +/* NO_OLD_RNGNAME removes RNG struct name to prevent possible type conflicts, + * can't be used with CTaoCrypt FIPS */ +#if !defined(NO_OLD_RNGNAME) && !defined(HAVE_FIPS) + #define RNG WC_RNG +#endif -#endif /* HAVE_FIPS */ WOLFSSL_LOCAL int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz); -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) -#ifdef HAVE_CAVIUM - WOLFSSL_API int wc_InitRngCavium(RNG*, int); +#ifdef HAVE_WNR + /* Whitewood netRandom client library */ + WOLFSSL_API int wc_InitNetRandom(const char*, wnr_hmac_key, int); + WOLFSSL_API int wc_FreeNetRandom(void); +#endif /* HAVE_WNR */ + + +WOLFSSL_ABI WOLFSSL_API WC_RNG* wc_rng_new(byte*, word32, void*); +WOLFSSL_ABI WOLFSSL_API void wc_rng_free(WC_RNG*); + + +#ifndef WC_NO_RNG +WOLFSSL_API int wc_InitRng(WC_RNG*); +WOLFSSL_API int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId); +WOLFSSL_API int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz); +WOLFSSL_API int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz, + void* heap, int devId); +WOLFSSL_ABI 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*); +#else +#include +#define wc_InitRng(rng) NOT_COMPILED_IN +#define wc_InitRng_ex(rng, h, d) NOT_COMPILED_IN +#define wc_InitRngNonce(rng, n, s) NOT_COMPILED_IN +#define wc_InitRngNonce_ex(rng, n, s, h, d) NOT_COMPILED_IN +#define wc_RNG_GenerateBlock(rng, b, s) NOT_COMPILED_IN +#define wc_RNG_GenerateByte(rng, b) NOT_COMPILED_IN +#define wc_FreeRng(rng) (void)NOT_COMPILED_IN #endif -#endif /* HAVE_HASH_DRBG || NO_RC4 */ -WOLFSSL_API int wc_InitRng(RNG*); -WOLFSSL_API int wc_RNG_GenerateBlock(RNG*, byte*, word32 sz); -WOLFSSL_API int wc_RNG_GenerateByte(RNG*, byte*); -WOLFSSL_API int wc_FreeRng(RNG*); - - -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#ifdef HAVE_HASHDRBG + WOLFSSL_LOCAL int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* entropy, + word32 entropySz); + WOLFSSL_API int wc_RNG_TestSeed(const byte* seed, word32 seedSz); 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 */ + WOLFSSL_API int wc_RNG_HealthTest_ex(int reseed, + const byte* nonce, word32 nonceSz, + const byte* entropyA, word32 entropyASz, + const byte* entropyB, word32 entropyBSz, + byte* output, word32 outputSz, + void* heap, int devId); +#endif /* HAVE_HASHDRBG */ #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ripemd.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ripemd.h index a76b64d8a..9368648de 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ripemd.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/ripemd.h @@ -1,8 +1,8 @@ /* ripemd.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/ripemd.h +*/ + #ifndef WOLF_CRYPT_RIPEMD_H #define WOLF_CRYPT_RIPEMD_H @@ -50,9 +54,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/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/rsa.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/rsa.h index 5441535eb..3965dc450 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/rsa.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/rsa.h @@ -1,8 +1,8 @@ /* rsa.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/rsa.h +*/ + + #ifndef WOLF_CRYPT_RSA_H #define WOLF_CRYPT_RSA_H @@ -26,7 +31,34 @@ #ifndef NO_RSA -#ifdef HAVE_FIPS + +/* RSA default exponent */ +#ifndef WC_RSA_EXPONENT + #define WC_RSA_EXPONENT 65537L +#endif + +#if defined(WC_RSA_NONBLOCK) + /* enable support for fast math based non-blocking exptmod */ + /* this splits the RSA function into many smaller operations */ + #ifndef USE_FAST_MATH + #error RSA non-blocking mode only supported using fast math + #endif + #ifndef TFM_TIMING_RESISTANT + #error RSA non-blocking mode only supported with timing resistance enabled + #endif + + /* RSA bounds check is not supported with RSA non-blocking mode */ + #undef NO_RSA_BOUNDS_CHECK + #define NO_RSA_BOUNDS_CHECK +#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" +#else + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) /* for fips @wc_fips */ #include #if defined(CYASSL_KEY_GEN) && !defined(WOLFSSL_KEY_GEN) @@ -35,82 +67,300 @@ #else #include #include -#endif /* HAVE_FIPS */ +#endif /* HAVE_FIPS && HAVE_FIPS_VERION 1 */ +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +#include +#endif + +/* header file needed for OAEP padding */ +#include + +#ifdef WOLFSSL_XILINX_CRYPT +#include "xsecure_rsa.h" +#endif + +#if defined(WOLFSSL_CRYPTOCELL) + #include +#endif #ifdef __cplusplus extern "C" { #endif -#ifndef HAVE_FIPS /* avoid redefinition of structs */ -#define WOLFSSL_RSA_CAVIUM_MAGIC 0xBEEF0006 +enum { + RSA_MIN_SIZE = 512, + RSA_MAX_SIZE = 4096, +}; + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include + #ifdef WOLFSSL_CERT_GEN + #include + #endif +#endif enum { RSA_PUBLIC = 0, - RSA_PRIVATE = 1 + RSA_PRIVATE = 1, + + RSA_TYPE_UNKNOWN = -1, + RSA_PUBLIC_ENCRYPT = 0, + RSA_PUBLIC_DECRYPT = 1, + RSA_PRIVATE_ENCRYPT = 2, + RSA_PRIVATE_DECRYPT = 3, + + RSA_BLOCK_TYPE_1 = 1, + RSA_BLOCK_TYPE_2 = 2, + + RSA_MIN_PAD_SZ = 11, /* separator + 0 + pad value + 8 pads */ + + RSA_PSS_PAD_SZ = 8, + RSA_PSS_SALT_MAX_SZ = 62, + +#ifdef OPENSSL_EXTRA + RSA_PKCS1_PADDING_SIZE = 11, + RSA_PKCS1_OAEP_PADDING_SIZE = 42, /* (2 * hashlen(SHA-1)) + 2 */ +#endif +#ifdef WC_RSA_PSS + RSA_PSS_PAD_TERM = 0xBC, +#endif + + RSA_PSS_SALT_LEN_DEFAULT = -1, +#ifdef WOLFSSL_PSS_SALT_LEN_DISCOVER + RSA_PSS_SALT_LEN_DISCOVER = -2, +#endif + +#ifdef HAVE_PKCS11 + RSA_MAX_ID_LEN = 32, +#endif }; -/* RSA */ -typedef struct RsaKey { - mp_int n, e, d, p, q, dP, dQ, u; - int type; /* public or private */ - void* heap; /* for user memory overrides */ -#ifdef HAVE_CAVIUM - int devId; /* nitrox device id */ - word32 magic; /* using cavium magic */ - word64 contextHandle; /* nitrox context memory handle */ - byte* c_n; /* cavium byte buffers for key parts */ - byte* c_e; - byte* c_d; - byte* c_p; - byte* c_q; - byte* c_dP; - byte* c_dQ; - byte* c_u; /* sizes in bytes */ - word16 c_nSz, c_eSz, c_dSz, c_pSz, c_qSz, c_dP_Sz, c_dQ_Sz, c_uSz; +#ifdef WC_RSA_NONBLOCK +typedef struct RsaNb { + exptModNb_t exptmod; /* non-block expt_mod */ + mp_int tmp; +} RsaNb; #endif -} RsaKey; + +/* RSA */ +struct RsaKey { + mp_int n, e; +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + mp_int d, p, q; +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + mp_int dP, dQ, u; +#endif +#endif + void* heap; /* for user memory overrides */ + byte* data; /* temp buffer for async RSA */ + int type; /* public or private */ + int state; + word32 dataLen; +#ifdef WC_RSA_BLINDING + WC_RNG* rng; /* for PrivateDecrypt blinding */ +#endif +#ifdef WOLF_CRYPTO_CB + int devId; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; + #ifdef WOLFSSL_CERT_GEN + CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */ + #endif +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_XILINX_CRYPT + word32 pubExp; /* to keep values in scope they are here in struct */ + byte* mod; + XSecure_Rsa xRsa; +#endif +#ifdef HAVE_PKCS11 + byte id[RSA_MAX_ID_LEN]; + int idLen; +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) || !defined(WOLFSSL_RSA_VERIFY_INLINE) + byte dataIsAlloc; +#endif +#ifdef WC_RSA_NONBLOCK + RsaNb* nb; +#endif +#ifdef WOLFSSL_AFALG_XILINX_RSA + int alFd; + int rdFd; +#endif +#if defined(WOLFSSL_CRYPTOCELL) + rsa_context_t ctx; +#endif +}; + +#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*); +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 HAVE_PKCS11 +WOLFSSL_API int wc_InitRsaKey_Id(RsaKey* key, unsigned char* id, int len, + void* heap, int devId); +#endif +WOLFSSL_API int wc_CheckRsaKey(RsaKey* key); +#ifdef WOLFSSL_XILINX_CRYPT +WOLFSSL_LOCAL int wc_InitRsaHw(RsaKey* key); +#endif /* WOLFSSL_XILINX_CRYPT */ + +WOLFSSL_API int wc_RsaFunction(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng); WOLFSSL_API int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key, RNG* rng); + word32 outLen, RsaKey* key, WC_RNG* rng); WOLFSSL_API int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key); 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, RNG* rng); + 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_RsaPSS_Sign_ex(const byte* in, word32 inLen, byte* out, + word32 outLen, enum wc_HashType hash, + int mgf, int saltLen, 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_RsaSSL_Verify_ex(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, int pad_type); +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_VerifyInline_ex(byte* in, word32 inLen, byte** out, + enum wc_HashType hash, int mgf, + int saltLen, RsaKey* key); +WOLFSSL_API int wc_RsaPSS_Verify(byte* in, word32 inLen, byte* out, + word32 outLen, enum wc_HashType hash, int mgf, + RsaKey* key); +WOLFSSL_API int wc_RsaPSS_Verify_ex(byte* in, word32 inLen, byte* out, + word32 outLen, enum wc_HashType hash, + int mgf, int saltLen, 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_RsaPSS_CheckPadding_ex(const byte* in, word32 inLen, + byte* sig, word32 sigSz, + enum wc_HashType hashType, + int saltLen, int bits); +WOLFSSL_API int wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out, + const byte* digest, word32 digentLen, + enum wc_HashType hash, int mgf, + RsaKey* key); +WOLFSSL_API int wc_RsaPSS_VerifyCheck(byte* in, word32 inLen, + byte* out, word32 outLen, + const byte* digest, word32 digestLen, + enum wc_HashType hash, int mgf, + RsaKey* key); + WOLFSSL_API int wc_RsaEncryptSize(RsaKey* key); -#ifndef HAVE_FIPS /* to avoid asn duplicate symbols @wc_fips */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) +/* to avoid asn duplicate symbols @wc_fips */ WOLFSSL_API int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey*, word32); WOLFSSL_API int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey*, word32); WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, word32 eSz, RsaKey* key); -#ifdef WOLFSSL_KEY_GEN - WOLFSSL_API int wc_RsaKeyToDer(RsaKey*, byte* output, word32 inLen); +WOLFSSL_API int wc_RsaKeyToDer(RsaKey*, byte* output, word32 inLen); + + +#ifdef WC_RSA_BLINDING + WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng); #endif -#endif /* HAVE_FIPS*/ +#ifdef WC_RSA_NONBLOCK + WOLFSSL_API int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb); + #ifdef WC_RSA_NONBLOCK_TIME + WOLFSSL_API int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs, + word32 cpuMHz); + #endif +#endif + +/* + choice of padding added after fips, so not available when using fips RSA + */ + +/* Mask Generation Function Identifiers */ +#define WC_MGF1NONE 0 +#define WC_MGF1SHA1 26 +#define WC_MGF1SHA224 4 +#define WC_MGF1SHA256 1 +#define WC_MGF1SHA384 2 +#define WC_MGF1SHA512 3 + +/* Padding types */ +#define WC_RSA_PKCSV15_PAD 0 +#define WC_RSA_OAEP_PAD 1 +#define WC_RSA_PSS_PAD 2 +#define WC_RSA_NO_PAD 3 + +WOLFSSL_API int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng, int type, + enum wc_HashType hash, int mgf, byte* label, word32 lableSz); +WOLFSSL_API int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, + byte* out, word32 outLen, RsaKey* key, int type, + enum wc_HashType hash, int mgf, byte* label, word32 lableSz); +WOLFSSL_API int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, + byte** out, RsaKey* key, int type, enum wc_HashType hash, + int mgf, byte* label, word32 lableSz); +#if defined(WC_RSA_DIRECT) || defined(WC_RSA_NO_PADDING) +WOLFSSL_API int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz, + RsaKey* key, int type, WC_RNG* rng); +#endif + +#endif /* HAVE_FIPS */ + WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, word32*); +WOLFSSL_API int wc_RsaExportKey(RsaKey* key, + byte* e, word32* eSz, + byte* n, word32* nSz, + byte* d, word32* dSz, + byte* p, word32* pSz, + byte* q, word32* qSz); + +WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen); #ifdef WOLFSSL_KEY_GEN - WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, RNG* rng); + WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); + WOLFSSL_API int wc_CheckProbablePrime_ex(const byte* p, word32 pSz, + const byte* q, word32 qSz, + const byte* e, word32 eSz, + int nlen, int* isPrime, WC_RNG* rng); + WOLFSSL_API int wc_CheckProbablePrime(const byte* p, word32 pSz, + const byte* q, word32 qSz, + const byte* e, word32 eSz, + int nlen, int* isPrime); #endif -#ifdef HAVE_CAVIUM - WOLFSSL_API int wc_RsaInitCavium(RsaKey*, int); - WOLFSSL_API void wc_RsaFreeCavium(RsaKey*); -#endif +WOLFSSL_LOCAL 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, + int saltLen, int bits, void* heap); +WOLFSSL_LOCAL int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, + byte padValue, int padType, enum wc_HashType hType, + int mgf, byte* optLabel, word32 labelLen, int saltLen, + int bits, void* heap); + +#endif /* HAVE_USER_RSA */ #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/selftest.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/selftest.h new file mode 100644 index 000000000..826b90d98 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/selftest.h @@ -0,0 +1,48 @@ +/* selftest.h + * + * Copyright (C) 2006-2020 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 WOLFCRYPT_SELF_TEST_H +#define WOLFCRYPT_SELF_TEST_H + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef HAVE_SELFTEST + /* Get wolfCrypt CAVP version */ + WOLFSSL_API const char* wolfCrypt_GetVersion_CAVP_selftest(void); + + /* wolfCrypt self test, runs CAVP KATs */ + WOLFSSL_API int wolfCrypt_SelfTest(void); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFCRYPT_SELF_TEST_H */ + + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/settings.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/settings.h index 57c404a54..e0620a9f9 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/settings.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/settings.h @@ -1,8 +1,8 @@ /* settings.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Place OS specific preprocessor flags, defines, includes here, will be included into every file because types.h includes it */ @@ -30,15 +31,25 @@ extern "C" { #endif +/* This flag allows wolfSSL to include options.h instead of having client + * projects do it themselves. This should *NEVER* be defined when building + * wolfSSL as it can cause hard to debug problems. */ +#ifdef EXTERNAL_OPTS_OPENVPN +#include +#endif + /* Uncomment next line if using IPHONE */ /* #define IPHONE */ /* 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 Deos RTOS*/ +/* #define WOLFSSL_DEOS*/ + /* Uncomment next line if using Mbed */ /* #define MBED */ @@ -57,6 +68,9 @@ /* Uncomment next line if using FreeRTOS */ /* #define FREERTOS */ +/* Uncomment next line if using FreeRTOS+ TCP */ +/* #define FREERTOS_TCP */ + /* Uncomment next line if using FreeRTOS Windows Simulator */ /* #define FREERTOS_WINSIM */ @@ -72,14 +86,36 @@ /* Uncomment next line if building wolfSSL for LSR */ /* #define WOLFSSL_LSR */ -/* Uncomment next line if building wolfSSL for Freescale MQX/RTCS/MFS */ +/* Uncomment next line if building for Freescale Classic MQX version 5.0 */ +/* #define FREESCALE_MQX_5_0 */ + +/* Uncomment next line if building for Freescale Classic MQX version 4.0 */ +/* #define FREESCALE_MQX_4_0 */ + +/* Uncomment next line if building for Freescale Classic MQX/RTCS/MFS */ /* #define FREESCALE_MQX */ +/* Uncomment next line if building for Freescale KSDK MQX/RTCS/MFS */ +/* #define FREESCALE_KSDK_MQX */ + +/* Uncomment next line if building for Freescale KSDK Bare Metal */ +/* #define FREESCALE_KSDK_BM */ + +/* Uncomment next line if building for Freescale KSDK FreeRTOS, */ +/* (old name FREESCALE_FREE_RTOS) */ +/* #define FREESCALE_KSDK_FREERTOS */ + /* Uncomment next line if using STM32F2 */ /* #define WOLFSSL_STM32F2 */ -/* Uncomment next line if using Comverge settings */ -/* #define COMVERGE */ +/* Uncomment next line if using STM32F4 */ +/* #define WOLFSSL_STM32F4 */ + +/* Uncomment next line if using STM32FL */ +/* #define WOLFSSL_STM32FL */ + +/* Uncomment next line if using STM32F7 */ +/* #define WOLFSSL_STM32F7 */ /* Uncomment next line if using QL SEP settings */ /* #define WOLFSSL_QL */ @@ -90,6 +126,9 @@ /* Uncomment next line if building for IAR EWARM */ /* #define WOLFSSL_IAR_ARM */ +/* Uncomment next line if building for Rowley CrossWorks ARM */ +/* #define WOLFSSL_ROWLEY_ARM */ + /* Uncomment next line if using TI-RTOS settings */ /* #define WOLFSSL_TIRTOS */ @@ -111,41 +150,150 @@ /* Uncomment next line if building for VxWorks */ /* #define WOLFSSL_VXWORKS */ +/* Uncomment next line if building for Nordic nRF5x platform */ +/* #define WOLFSSL_NRF5x */ + +/* Uncomment next line to enable deprecated less secure static DH suites */ +/* #define WOLFSSL_STATIC_DH */ + +/* Uncomment next line to enable deprecated less secure static RSA suites */ +/* #define WOLFSSL_STATIC_RSA */ + +/* Uncomment next line if building for ARDUINO */ +/* Uncomment both lines if building for ARDUINO on INTEL_GALILEO */ +/* #define WOLFSSL_ARDUINO */ +/* #define INTEL_GALILEO */ + +/* Uncomment next line to enable asynchronous crypto WC_PENDING_E */ +/* #define WOLFSSL_ASYNC_CRYPT */ + +/* Uncomment next line if building for uTasker */ +/* #define WOLFSSL_UTASKER */ + +/* Uncomment next line if building for embOS */ +/* #define WOLFSSL_EMBOS */ + +/* 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 */ + +/* Uncomment next line if building for WICED Studio. */ +/* #define WOLFSSL_WICED */ + +/* Uncomment next line if building for Nucleus 1.2 */ +/* #define WOLFSSL_NUCLEUS_1_2 */ + +/* Uncomment next line if building for using Apache mynewt */ +/* #define WOLFSSL_APACHE_MYNEWT */ + +/* Uncomment next line if building for using ESP-IDF */ +/* #define WOLFSSL_ESPIDF */ + +/* Uncomment next line if using Espressif ESP32-WROOM-32 */ +/* #define WOLFSSL_ESPWROOM32 */ + +/* Uncomment next line if using Espressif ESP32-WROOM-32SE */ +/* #define WOLFSSL_ESPWROOM32SE */ + +/* Uncomment next line if using ARM CRYPTOCELL*/ +/* #define WOLFSSL_CRYPTOCELL */ + +/* Uncomment next line if using RENESAS TSIP */ +/* #define WOLFSSL_RENESAS_TSIP */ + +/* Uncomment next line if using RENESAS RX64N */ +/* #define WOLFSSL_RENESAS_RX65N */ + #include #ifdef WOLFSSL_USER_SETTINGS - #include + #include "user_settings.h" #endif +/* make sure old RNG name is used with CTaoCrypt FIPS */ +#ifdef HAVE_FIPS + #if !defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2) + #define WC_RNG RNG + #else + #ifndef WOLFSSL_STM32L4 + #define RNG WC_RNG + #endif + #endif + /* blinding adds API not available yet in FIPS mode */ + #undef WC_RSA_BLINDING +#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 - -#ifdef COMVERGE - #define THREADX - #define HAVE_NETX - #define WOLFSSL_USER_IO - #define NO_WRITEV - #define NO_DEV_RANDOM - #define NO_FILESYSTEM - #define NO_SHA512 - #define NO_DH - #define NO_DSA - #define NO_HC128 - #define NO_RSA - #define NO_SESSION_CACHE - #define HAVE_ECC -#endif - - #ifdef THREADX #define SIZEOF_LONG_LONG 8 #endif #ifdef HAVE_NETX - #include "nx_api.h" + #ifdef NEED_THREADX_TYPES + #include + #endif + #include +#endif + +#if defined(WOLFSSL_ESPIDF) + #define FREERTOS + #define WOLFSSL_LWIP + #define NO_WRITEV + #define SIZEOF_LONG_LONG 8 + #define NO_WOLFSSL_DIR + #define WOLFSSL_NO_CURRDIR + + #define TFM_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + #define WC_RSA_BLINDING + +#if defined(WOLFSSL_ESPWROOM32) || defined(WOLFSSL_ESPWROOM32SE) + #ifndef NO_ESP32WROOM32_CRYPT + #define WOLFSSL_ESP32WROOM32_CRYPT + #if defined(ESP32_USE_RSA_PRIMITIVE) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + #define WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI + #define USE_FAST_MATH + #define WOLFSSL_SMALL_STACK + #endif + #endif +#endif +#endif /* WOLFSSL_ESPIDF */ + +#if defined(WOLFSSL_RENESAS_TSIP) + #define TSIP_TLS_HMAC_KEY_INDEX_WORDSIZE 64 + #define TSIP_TLS_MASTERSECRET_SIZE 80 /* 20 words */ + #define TSIP_TLS_ENCPUBKEY_SZ_BY_CERTVRFY 560 /* in byte */ + #if !defined(NO_RENESAS_TSIP_CRYPT) && defined(WOLFSSL_RENESAS_RX65N) + #define WOLFSSL_RENESAS_TSIP_CRYPT + #define WOLFSSL_RENESAS_TSIP_TLS + #define WOLFSSL_RENESAS_TSIP_TLS_AES_CRYPT + #endif +#endif + +#if defined(WOLFSSL_RENESAS_RA6M3G) + /* settings in user_settings.h */ #endif #if defined(HAVE_LWIP_NATIVE) /* using LwIP native TCP socket */ @@ -156,15 +304,33 @@ #define NO_FILESYSTEM #endif -#if defined(WOLFSSL_IAR_ARM) +#if defined(WOLFSSL_CONTIKI) + #include + #define WOLFSSL_UIP + #define NO_WOLFSSL_MEMORY + #define NO_WRITEV + #define SINGLE_THREADED + #define WOLFSSL_USER_IO + #define NO_FILESYSTEM + #define CUSTOM_RAND_TYPE uint16_t + #define CUSTOM_RAND_GENERATE random_rand + static inline word32 LowResTimer(void) + { + return clock_seconds(); + } +#endif + +#if defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_ROWLEY_ARM) #define NO_MAIN_DRIVER #define SINGLE_THREADED - #define USE_CERT_BUFFERS_1024 + #if !defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_4096) + #define USE_CERT_BUFFERS_1024 + #endif #define BENCH_EMBEDDED #define NO_FILESYSTEM #define NO_WRITEV #define WOLFSSL_USER_IO - #define BENCH_EMBEDDED + #define BENCH_EMBEDDED #endif #ifdef MICROCHIP_PIC32 @@ -177,18 +343,21 @@ #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 + #ifndef NO_PIC32MZ_CRYPT + #define WOLFSSL_PIC32MZ_CRYPT + #endif + #ifndef NO_PIC32MZ_RNG + #define WOLFSSL_PIC32MZ_RNG + #endif + #ifndef NO_PIC32MZ_HASH + #define WOLFSSL_PIC32MZ_HASH + #endif #endif #ifdef MICROCHIP_TCPIP_V5 @@ -209,12 +378,16 @@ #ifdef MBED #define WOLFSSL_USER_IO #define NO_FILESYSTEM - #define NO_CERT - #define USE_CERT_BUFFERS_1024 + #define NO_CERTS + #if !defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_4096) + #define USE_CERT_BUFFERS_1024 + #endif #define NO_WRITEV #define NO_DEV_RANDOM #define NO_SHA512 #define NO_DH + /* Allows use of DH with fixed points if uncommented and NO_DH is removed */ + /* WOLFSSL_DH_CONST */ #define NO_DSA #define NO_HC128 #define HAVE_ECC @@ -236,6 +409,8 @@ #define NO_RSA #define NO_DSA #define NO_DH + /* Allows use of DH with fixed points if uncommented and NO_DH is removed */ + /* WOLFSSL_DH_CONST */ #define NO_CERTS #define NO_PWDBASED #define NO_DES3 @@ -277,19 +452,229 @@ #ifdef WOLFSSL_VXWORKS + /* VxWorks simulator incorrectly detects building for i386 */ + #ifdef VXWORKS_SIM + #define TFM_NO_ASM + #endif + /* For VxWorks pthreads wrappers for mutexes uncomment the next line. */ + /* #define WOLFSSL_PTHREADS */ + #define WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MAX + #define USE_FAST_MATH + #define TFM_TIMING_RESISTANT + #define NO_MAIN_DRIVER #define NO_DEV_RANDOM #define NO_WRITEV + #define HAVE_STRINGS_H #endif +#ifdef WOLFSSL_ARDUINO + #define NO_WRITEV + #define NO_WOLFSSL_DIR + #define SINGLE_THREADED + #define NO_DEV_RANDOM + #ifndef INTEL_GALILEO /* Galileo has time.h compatibility */ + #define TIME_OVERRIDES + #ifndef XTIME + #error "Must define XTIME externally see porting guide" + #error "https://www.wolfssl.com/docs/porting-guide/" + #endif + #ifndef XGMTIME + #error "Must define XGMTIME externally see porting guide" + #error "https://www.wolfssl.com/docs/porting-guide/" + #endif + #endif + #define WOLFSSL_USER_IO + #define HAVE_ECC + #define NO_DH + #define NO_SESSION_CACHE +#endif + + +#ifdef WOLFSSL_UTASKER + /* uTasker configuration - used for fnRandom() */ + #include "config.h" + + #define SINGLE_THREADED + #define NO_WOLFSSL_DIR + #define WOLFSSL_HAVE_MIN + #define NO_WRITEV + + #define HAVE_ECC + #define ALT_ECC_SIZE + #define USE_FAST_MATH + #define TFM_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + + /* used in wolfCrypt test */ + #define NO_MAIN_DRIVER + #define USE_CERT_BUFFERS_2048 + + /* uTasker port uses RAW sockets, use I/O callbacks + * See wolfSSL uTasker example for sample callbacks */ + #define WOLFSSL_USER_IO + + /* uTasker filesystem not ported */ + #define NO_FILESYSTEM + + /* uTasker RNG is abstracted, calls HW RNG when available */ + #define CUSTOM_RAND_GENERATE fnRandom + #define CUSTOM_RAND_TYPE unsigned short + + /* user needs to define XTIME to function that provides + * seconds since Unix epoch */ + #ifndef XTIME + #error XTIME must be defined in wolfSSL settings.h + /* #define XTIME fnSecondsSinceEpoch */ + #endif + + /* use uTasker std library replacements where available */ + #define STRING_USER + #define XMEMCPY(d,s,l) uMemcpy((d),(s),(l)) + #define XMEMSET(b,c,l) uMemset((b),(c),(l)) + #define XMEMCMP(s1,s2,n) uMemcmp((s1),(s2),(n)) + #define XMEMMOVE(d,s,l) memmove((d),(s),(l)) + + #define XSTRLEN(s1) uStrlen((s1)) + #define XSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n)) + #define XSTRSTR(s1,s2) strstr((s1),(s2)) + #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)) + #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) + #if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) \ + || defined(HAVE_ALPN) + #define XSTRTOK strtok_r + #endif +#endif + +#ifdef WOLFSSL_EMBOS + #define NO_FILESYSTEM /* Not ported at this time */ + #define USE_CERT_BUFFERS_2048 /* use when NO_FILESYSTEM */ + #define NO_MAIN_DRIVER + #define NO_RC4 + #define SINGLE_THREADED /* Not ported at this time */ +#endif + +#ifdef WOLFSSL_RIOT_OS + #define NO_WRITEV + #define TFM_NO_ASM + #define NO_FILESYSTEM + #define USE_CERT_BUFFERS_2048 + #if defined(WOLFSSL_GNRC) && !defined(WOLFSSL_DTLS) + #define WOLFSSL_DTLS + #endif +#endif + +#ifdef WOLFSSL_CHIBIOS + /* ChibiOS definitions. This file is distributed with chibiOS. */ + #include "wolfssl_chibios.h" +#endif + +#ifdef WOLFSSL_PB + /* PB is using older 1.2 version of Nucleus */ + #undef WOLFSSL_NUCLEUS + #define WOLFSSL_NUCLEUS_1_2 +#endif + +#ifdef WOLFSSL_NUCLEUS_1_2 + #define NO_WRITEV + #define NO_WOLFSSL_DIR + + #if !defined(NO_ASN_TIME) && !defined(USER_TIME) + #error User must define XTIME, see manual + #endif + + #if !defined(XMALLOC_OVERRIDE) && !defined(XMALLOC_USER) + extern void* nucleus_malloc(unsigned long size, void* heap, int type); + extern void* nucleus_realloc(void* ptr, unsigned long size, void* heap, + int type); + extern void nucleus_free(void* ptr, void* heap, int type); + + #define XMALLOC(s, h, type) nucleus_malloc((s), (h), (type)) + #define XREALLOC(p, n, h, t) nucleus_realloc((p), (n), (h), (t)) + #define XFREE(p, h, type) nucleus_free((p), (h), (type)) + #endif +#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 +#endif + /* Micrium will use Visual Studio for compilation but not the Win32 API */ -#if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) \ - && !defined(EBSNET) && !defined(WOLFSSL_EROAD) +#if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) && \ + !defined(FREERTOS_TCP) && !defined(EBSNET) && !defined(WOLFSSL_EROAD) && \ + !defined(WOLFSSL_UTASKER) && !defined(INTIME_RTOS) #define USE_WINDOWS_API #endif +#if defined(WOLFSSL_uITRON4) -#if defined(WOLFSSL_LEANPSK) && !defined(XMALLOC_USER) +#define XMALLOC_USER +#include +#define ITRON_POOL_SIZE 1024*20 +extern int uITRON4_minit(size_t poolsz) ; +extern void *uITRON4_malloc(size_t sz) ; +extern void *uITRON4_realloc(void *p, size_t sz) ; +extern void uITRON4_free(void *p) ; + +#define XMALLOC(sz, heap, type) uITRON4_malloc(sz) +#define XREALLOC(p, sz, heap, type) uITRON4_realloc(p, sz) +#define XFREE(p, heap, type) uITRON4_free(p) +#endif + +#if defined(WOLFSSL_uTKERNEL2) + #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 + + #ifndef NO_STDIO_FGETS_REMAP + #include + #include "tm/tmonitor.h" + + /* static char* gets(char *buff); */ + static char* fgets(char *buff, int sz, XFILE 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++; + } + return buff; + } + #endif /* !NO_STDIO_FGETS_REMAP */ +#endif + + +#if defined(WOLFSSL_LEANPSK) && !defined(XMALLOC_USER) && \ + !defined(NO_WOLFSSL_MEMORY) #include #define XMALLOC(s, h, type) malloc((s)) #define XFREE(p, h, type) free((p)) @@ -307,6 +692,24 @@ #ifdef FREERTOS + #include "FreeRTOS.h" + + #if !defined(XMALLOC_USER) && !defined(NO_WOLFSSL_MEMORY) && \ + !defined(WOLFSSL_STATIC_MEMORY) + #define XMALLOC(s, h, type) pvPortMalloc((s)) + #define XFREE(p, h, type) vPortFree((p)) + #endif + /* FreeRTOS pvPortRealloc() implementation can be found here: + https://github.com/wolfSSL/wolfssl-freertos/pull/3/files */ + #if !defined(USE_FAST_MATH) || defined(HAVE_ED25519) || defined(HAVE_ED448) + #if defined(WOLFSSL_ESPIDF) + /*In IDF, realloc(p, n) is equivalent to + heap_caps_realloc(p, s, MALLOC_CAP_8BIT) */ + #define XREALLOC(p, n, h, t) realloc((p), (n)) + #else + #define XREALLOC(p, n, h, t) pvPortRealloc((p), (n)) + #endif + #endif #ifndef NO_WRITEV #define NO_WRITEV #endif @@ -328,22 +731,52 @@ #endif #ifndef SINGLE_THREADED - #include "FreeRTOS.h" #include "semphr.h" #endif #endif +#ifdef FREERTOS_TCP + #if !defined(NO_WOLFSSL_MEMORY) && !defined(XMALLOC_USER) && \ + !defined(WOLFSSL_STATIC_MEMORY) + #define XMALLOC(s, h, type) pvPortMalloc((s)) + #define XFREE(p, h, type) vPortFree((p)) + #endif + + #define WOLFSSL_GENSEED_FORTEST + + #define NO_WOLFSSL_DIR + #define NO_WRITEV + #define USE_FAST_MATH + #define TFM_TIMING_RESISTANT + #define NO_MAIN_DRIVER +#endif + #ifdef WOLFSSL_TIRTOS #define SIZEOF_LONG_LONG 8 #define NO_WRITEV #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 #define NO_ERROR_STRINGS - #define USER_TIME + /* Uncomment this setting if your toolchain does not offer time.h header */ + /* #define USER_TIME */ + #define HAVE_ECC + #define HAVE_ALPN + #define USE_WOLF_STRTOK /* use with HAVE_ALPN */ + #define HAVE_TLS_EXTENSIONS + #define HAVE_AESGCM + #ifdef WOLFSSL_TI_CRYPT + #define NO_GCM_ENCRYPT_EXTRA + #define NO_PUBLIC_GCM_SET_IV + #define NO_PUBLIC_CCM_SET_NONCE + #endif + #define HAVE_SUPPORTED_CURVES + #define ALT_ECC_SIZE #ifdef __IAR_SYSTEMS_ICC__ #pragma diag_suppress=Pa089 @@ -379,12 +812,28 @@ #undef SIZEOF_LONG #define SIZEOF_LONG_LONG 8 #else - #sslpro: settings.h - please implement SIZEOF_LONG and SIZEOF_LONG_LONG + #error settings.h - please implement SIZEOF_LONG and SIZEOF_LONG_LONG #endif #define XMALLOC(s, h, type) ((void *)rtp_malloc((s), SSL_PRO_MALLOC)) #define XFREE(p, h, type) (rtp_free(p)) - #define XREALLOC(p, n, h, t) realloc((p), (n)) + #define XREALLOC(p, n, h, t) (rtp_realloc((p), (n))) + + #if (WINMSP3) + #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) + #else + #sslpro: settings.h - please implement XSTRNCASECMP - needed for HAVE_ECC + #endif + + #define WOLFSSL_HAVE_MAX + #define WOLFSSL_HAVE_MIN + + #define USE_FAST_MATH + #define TFM_TIMING_RESISTANT + #define WC_RSA_BLINDING + #define ECC_TIMING_RESISTANT + + #define HAVE_ECC #endif /* EBSNET */ @@ -402,6 +851,8 @@ #define NO_WRITEV #define NO_SHA512 #define NO_DH + /* Allows use of DH with fixed points if uncommented and NO_DH is removed */ + /* WOLFSSL_DH_CONST */ #define NO_DSA #define NO_HC128 #define NO_DEV_RANDOM @@ -425,11 +876,19 @@ #ifndef SINGLE_THREADED #include "SafeRTOS/semphr.h" #endif - - #include "SafeRTOS/heap.h" - #define XMALLOC(s, h, type) pvPortMalloc((s)) - #define XFREE(p, h, type) vPortFree((p)) - #define XREALLOC(p, n, h, t) pvPortRealloc((p), (n)) + #ifndef WOLFSSL_NO_MALLOC + #include "SafeRTOS/heap.h" + #endif + #if !defined(XMALLOC_USER) && !defined(NO_WOLFSSL_MEMORY) && \ + !defined(WOLFSSL_STATIC_MEMORY) + #define XMALLOC(s, h, type) pvPortMalloc((s)) + #define XFREE(p, h, type) vPortFree((p)) + #endif + /* FreeRTOS pvPortRealloc() implementation can be found here: + https://github.com/wolfSSL/wolfssl-freertos/pull/3/files */ + #if !defined(USE_FAST_MATH) || defined(HAVE_ED25519) || defined(HAVE_ED448) + #define XREALLOC(p, n, h, t) pvPortRealloc((p), (n)) + #endif #endif #ifdef WOLFSSL_LOW_MEMORY @@ -441,63 +900,454 @@ #define TFM_TIMING_RESISTANT #endif +#ifdef FREESCALE_MQX_5_0 + /* use normal Freescale MQX port, but with minor changes for 5.0 */ + #define FREESCALE_MQX +#endif + +#ifdef FREESCALE_MQX_4_0 + /* use normal Freescale MQX port, but with minor changes for 4.0 */ + #define FREESCALE_MQX +#endif + #ifdef FREESCALE_MQX - #define SIZEOF_LONG_LONG 8 - #define NO_WRITEV - #define NO_DEV_RANDOM - #define NO_RABBIT - #define NO_WOLFSSL_DIR - #define USE_FAST_MATH - #define TFM_TIMING_RESISTANT - #define FREESCALE_K70_RNGA - /* #define FREESCALE_K53_RNGB */ + #define FREESCALE_COMMON #include "mqx.h" #ifndef NO_FILESYSTEM #include "mfs.h" - #include "fio.h" + #if (defined(MQX_USE_IO_OLD) && MQX_USE_IO_OLD) || \ + defined(FREESCALE_MQX_5_0) + #include "fio.h" + #define NO_STDIO_FILESYSTEM + #else + #include "nio.h" + #endif #endif #ifndef SINGLE_THREADED #include "mutex.h" #endif - #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 */ + #if !defined(XMALLOC_OVERRIDE) && !defined(XMALLOC_USER) + #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 */ + #endif #endif -#ifdef WOLFSSL_STM32F2 - #define SIZEOF_LONG_LONG 8 - #define NO_DEV_RANDOM - #define NO_WOLFSSL_DIR - #define NO_RABBIT - #define STM32F2_RNG - #define STM32F2_CRYPTO - #define KEIL_INTRINSICS -#endif - -#ifdef MICRIUM - - #include "stdlib.h" - #include "net_cfg.h" - #include "ssl_cfg.h" - #include "net_secure_os.h" - - #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 +#ifdef FREESCALE_KSDK_MQX + #define FREESCALE_COMMON + #include + #ifndef NO_FILESYSTEM + #if (defined(MQX_USE_IO_OLD) && MQX_USE_IO_OLD) || \ + defined(FREESCALE_MQX_5_0) + #include + #else + #include + #include + #endif + #endif + #ifndef SINGLE_THREADED + #include #endif - #define STRING_USER + #define XMALLOC(s, h, t) (void *)_mem_alloc_system((s)) + #define XFREE(p, h, t) {void* xp = (p); if ((xp)) _mem_free((xp));} + #define XREALLOC(p, n, h, t) _mem_realloc((p), (n)) /* since MQX 4.1.2 */ + #define MQX_FILE_PTR FILE * + #define IO_SEEK_SET SEEK_SET + #define IO_SEEK_END SEEK_END +#endif /* FREESCALE_KSDK_MQX */ + +#if defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) + #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 */ + #define WOLFSSL_LWIP + #define FREERTOS_TCP + + #define FREESCALE_FREE_RTOS + #define FREERTOS_SOCKET_ERROR ( -1 ) + #define FREERTOS_EWOULDBLOCK ( -2 ) + #define FREERTOS_EINVAL ( -4 ) + #define FREERTOS_EADDRNOTAVAIL ( -5 ) + #define FREERTOS_EADDRINUSE ( -6 ) + #define FREERTOS_ENOBUFS ( -7 ) + #define FREERTOS_ENOPROTOOPT ( -8 ) +#endif /* FREESCALE_FREE_RTOS || FREESCALE_KSDK_FREERTOS */ + +#ifdef FREESCALE_KSDK_BM + #define FREESCALE_COMMON + #define WOLFSSL_USER_IO + #define SINGLE_THREADED + #define NO_FILESYSTEM + #ifndef TIME_OVERRIDES + #define USER_TICKS + #endif +#endif /* FREESCALE_KSDK_BM */ + +#ifdef FREESCALE_COMMON + #define SIZEOF_LONG_LONG 8 + + /* disable features */ + #undef NO_WRITEV + #define NO_WRITEV + #undef NO_DEV_RANDOM + #define NO_DEV_RANDOM + #undef NO_RABBIT + #define NO_RABBIT + #undef NO_WOLFSSL_DIR + #define NO_WOLFSSL_DIR + #undef NO_RC4 + #define NO_RC4 + + /* enable features */ + #undef USE_FAST_MATH + #define USE_FAST_MATH + + #define USE_CERT_BUFFERS_2048 + #define BENCH_EMBEDDED + + #define TFM_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + + #undef HAVE_ECC + #define HAVE_ECC + #ifndef NO_AES + #undef HAVE_AESCCM + #define HAVE_AESCCM + #undef HAVE_AESGCM + #define HAVE_AESGCM + #undef WOLFSSL_AES_COUNTER + #define WOLFSSL_AES_COUNTER + #undef WOLFSSL_AES_DIRECT + #define WOLFSSL_AES_DIRECT + #endif + + #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) + #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) + /* defaulting to K70 RNGA, user should change if different */ + /* #define FREESCALE_K53_RNGB */ + #define FREESCALE_K70_RNGA + #endif + + /* HW crypto */ + /* automatic enable based on Kinetis feature */ + /* if case manual selection is required, for example for benchmarking purposes, + * just define FREESCALE_USE_MMCAU or FREESCALE_USE_LTC or none of these two macros (for software only) + * both can be enabled simultaneously as LTC has priority over MMCAU in source code. + */ + /* #define FSL_HW_CRYPTO_MANUAL_SELECTION */ + #ifndef FSL_HW_CRYPTO_MANUAL_SELECTION + #if defined(FSL_FEATURE_SOC_MMCAU_COUNT) && FSL_FEATURE_SOC_MMCAU_COUNT + #define FREESCALE_USE_MMCAU + #endif + + #if defined(FSL_FEATURE_SOC_LTC_COUNT) && FSL_FEATURE_SOC_LTC_COUNT + #define FREESCALE_USE_LTC + #endif + #else + /* #define FREESCALE_USE_MMCAU */ + /* #define FREESCALE_USE_LTC */ + #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 + /* MD5, SHA-1 and SHA-256 */ + #define FREESCALE_MMCAU_SHA +#endif /* FREESCALE_USE_MMCAU */ + +#ifdef FREESCALE_USE_LTC + #if defined(FSL_FEATURE_SOC_LTC_COUNT) && FSL_FEATURE_SOC_LTC_COUNT + #define FREESCALE_LTC + #define LTC_BASE LTC0 + + #if defined(FSL_FEATURE_LTC_HAS_DES) && FSL_FEATURE_LTC_HAS_DES + #define FREESCALE_LTC_DES + #endif + + #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 + + #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA + #define FREESCALE_LTC_ECC + #define FREESCALE_LTC_TFM + + /* the LTC PKHA hardware limit is 2048 bits (256 bytes) for integer arithmetic. + the LTC_MAX_INT_BYTES defines the size of local variables that hold big integers. */ + #ifndef LTC_MAX_INT_BYTES + #define LTC_MAX_INT_BYTES (256) + #endif + + /* 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. + */ + /* #define FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + + /* ECC-384, ECC-256, ECC-224 and ECC-192 have been enabled with LTC PKHA acceleration */ + #ifdef HAVE_ECC + #undef ECC_TIMING_RESISTANT + #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 + and point coordinates */ + #ifndef LTC_MAX_ECC_BITS + #define LTC_MAX_ECC_BITS (384) + #endif + + /* Enable curves up to 384 bits */ + #if !defined(ECC_USER_CURVES) && !defined(HAVE_ALL_CURVES) + #define ECC_USER_CURVES + #define HAVE_ECC192 + #define HAVE_ECC224 + #undef NO_ECC256 + #define HAVE_ECC384 + #endif + #endif + #endif + #endif +#endif /* FREESCALE_USE_LTC */ + +#ifdef FREESCALE_LTC_TFM_RSA_4096_ENABLE + #undef USE_CERT_BUFFERS_4096 + #define USE_CERT_BUFFERS_4096 + #undef FP_MAX_BITS + #define FP_MAX_BITS (8192) + + #undef NO_DH + #define NO_DH + #undef NO_DSA + #define NO_DSA +#endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + +/* if LTC has AES engine but doesn't have GCM, use software with LTC AES ECB mode */ +#if defined(FREESCALE_USE_LTC) && !defined(FREESCALE_LTC_AES_GCM) + #define GCM_TABLE +#endif + +#if defined(WOLFSSL_STM32F2) || defined(WOLFSSL_STM32F4) || \ + defined(WOLFSSL_STM32F7) || defined(WOLFSSL_STM32F1) || \ + defined(WOLFSSL_STM32L4) + + #define SIZEOF_LONG_LONG 8 + #ifndef CHAR_BIT + #define CHAR_BIT 8 + #endif + #define NO_DEV_RANDOM + #define NO_WOLFSSL_DIR + #undef NO_RABBIT + #define NO_RABBIT + #ifndef NO_STM32_RNG + #undef STM32_RNG + #define STM32_RNG + #ifdef WOLFSSL_STM32F427_RNG + #include "stm32f427xx.h" + #endif + #endif + #ifndef NO_STM32_CRYPTO + #undef STM32_CRYPTO + #define STM32_CRYPTO + + #ifdef WOLFSSL_STM32L4 + #define NO_AES_192 /* hardware does not support 192-bit */ + #endif + #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 + #if defined(WOLFSSL_STM32F2) + #include "stm32f2xx_hal.h" + #elif defined(WOLFSSL_STM32L4) + #include "stm32l4xx_hal.h" + #elif defined(WOLFSSL_STM32F4) + #include "stm32f4xx_hal.h" + #elif defined(WOLFSSL_STM32F7) + #include "stm32f7xx_hal.h" + #elif defined(WOLFSSL_STM32F1) + #include "stm32f1xx_hal.h" + #endif + #if defined(WOLFSSL_CUBEMX_USE_LL) && defined(WOLFSSL_STM32L4) + #include "stm32l4xx_ll_rng.h" + #endif + + #ifndef STM32_HAL_TIMEOUT + #define STM32_HAL_TIMEOUT 0xFF + #endif + #else + #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_STM32L4) + #include "stm32l4xx.h" + #ifdef STM32_CRYPTO + #include "stm32l4xx_cryp.h" + #endif + #ifdef STM32_HASH + #include "stm32l4xx_hash.h" + #endif + #elif defined(WOLFSSL_STM32F7) + #include "stm32f7xx.h" + #elif defined(WOLFSSL_STM32F1) + #include "stm32f1xx.h" + #endif + #endif /* WOLFSSL_STM32_CUBEMX */ +#endif /* WOLFSSL_STM32F2 || WOLFSSL_STM32F4 || WOLFSSL_STM32L4 || WOLFSSL_STM32F7 */ +#ifdef WOLFSSL_DEOS + #include + #include + #include + #include + #include + #include + #include /* for rand_r: pseudo-random number generator */ + #include /* for snprintf */ + + /* use external memory XMALLOC, XFREE and XREALLOC functions */ + #define XMALLOC_USER + + /* disable fall-back case, malloc, realloc and free are unavailable */ + #define WOLFSSL_NO_MALLOC + + /* file system has not been ported since it is a separate product. */ + + #define NO_FILESYSTEM + + #ifdef NO_FILESYSTEM + #define NO_WOLFSSL_DIR + #define NO_WRITEV + #endif + + #define USE_FAST_MATH + #define TFM_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + #define WC_RSA_BLINDING + + #define HAVE_ECC + #define ALT_ECC_SIZE + #define TFM_ECC192 + #define TFM_ECC224 + #define TFM_ECC256 + #define TFM_ECC384 + #define TFM_ECC521 + + #define HAVE_TLS_EXTENSIONS + #define HAVE_SUPPORTED_CURVES + #define HAVE_EXTENDED_MASTER + + #if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + #define BIG_ENDIAN_ORDER + #else + #undef BIG_ENDIAN_ORDER + #define LITTLE_ENDIAN_ORDER + #endif +#endif /* WOLFSSL_DEOS*/ + +#ifdef MICRIUM + #include + #include + #include + #include + #include + #include + #include + + #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 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), \ @@ -505,171 +1355,51 @@ #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), \ + ((void)Mem_Set((void *)(pmem), \ + (CPU_INT08U) (data_val), \ (CPU_SIZE_T)(size))) #define XMEMCPY(pdest, psrc, size) ((void)Mem_Copy((void *)(pdest), \ (void *)(psrc), (CPU_SIZE_T)(size))) #define XMEMCMP(pmem_1, pmem_2, size) \ - (((CPU_BOOLEAN)Mem_Cmp((void *)(pmem_1), (void *)(pmem_2), \ + (((CPU_BOOLEAN)Mem_Cmp((void *)(pmem_1), \ + (void *)(pmem_2), \ (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 */ +#ifdef WOLFSSL_MCF5441X + #define BIG_ENDIAN_ORDER + #ifndef SIZEOF_LONG + #define SIZEOF_LONG 4 + #endif + #ifndef SIZEOF_LONG_LONG + #define SIZEOF_LONG_LONG 8 + #endif +#endif #ifdef WOLFSSL_QL #ifndef WOLFSSL_SEP @@ -702,8 +1432,112 @@ #endif /* WOLFSSL_QL */ +#if defined(WOLFSSL_XILINX) + #define NO_WOLFSSL_DIR + #define NO_DEV_RANDOM + #define HAVE_AESGCM +#endif + +#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_AFALG_XILINX) + #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 + #ifdef WOLFSSL_AFALG_XILINX_AES + #undef WOLFSSL_AES_DIRECT + #define WOLFSSL_AES_DIRECT + #endif +#endif /*(WOLFSSL_XILINX_CRYPT)*/ + +#if defined(WOLFSSL_APACHE_MYNEWT) + #include "os/os_malloc.h" + #if !defined(WOLFSSL_LWIP) + #include + #endif + + #if !defined(SIZEOF_LONG) + #define SIZEOF_LONG 4 + #endif + #if !defined(SIZEOF_LONG_LONG) + #define SIZEOF_LONG_LONG 8 + #endif + #if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + #define BIG_ENDIAN_ORDER + #else + #undef BIG_ENDIAN_ORDER + #define LITTLE_ENDIAN_ORDER + #endif + #define NO_WRITEV + #define WOLFSSL_USER_IO + #define SINGLE_THREADED + #define NO_DEV_RANDOM + #define NO_DH + #define NO_WOLFSSL_DIR + #define NO_ERROR_STRINGS + #define HAVE_ECC + #define NO_SESSION_CACHE + #define NO_ERROR_STRINGS + #define XMALLOC_USER + #define XMALLOC(sz, heap, type) os_malloc(sz) + #define XREALLOC(p, sz, heap, type) os_realloc(p, sz) + #define XFREE(p, heap, type) os_free(p) + +#endif /*(WOLFSSL_APACHE_MYNEWT)*/ + +#ifdef WOLFSSL_ZEPHYR + #include + #include + #include + #include + + #define WOLFSSL_DH_CONST + #define WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MAX + #define NO_WRITEV + + #define USE_FLAT_BENCHMARK_H + #define USE_FLAT_TEST_H + #define EXIT_FAILURE 1 + #define MAIN_NO_ARGS + + void *z_realloc(void *ptr, size_t size); + #define realloc z_realloc + + #define CONFIG_NET_SOCKETS_POSIX_NAMES +#endif + +#ifdef WOLFSSL_IMX6 + #ifndef SIZEOF_LONG_LONG + #define SIZEOF_LONG_LONG 8 + #endif +#endif + +/* if defined turn on all CAAM support */ +#ifdef WOLFSSL_IMX6_CAAM + #undef WOLFSSL_IMX6_CAAM_RNG + #define WOLFSSL_IMX6_CAAM_RNG + + #undef WOLFSSL_IMX6_CAAM_BLOB + #define WOLFSSL_IMX6_CAAM_BLOB + +#if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_XTS) + /* large performance gain with HAVE_AES_ECB defined */ + #undef HAVE_AES_ECB + #define HAVE_AES_ECB +#endif +#endif + #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 @@ -723,21 +1557,70 @@ #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 -/* FreeScale MMCAU hardware crypto has 4 byte alignment */ +#ifdef WOLFSSL_SGX + #ifdef _MSC_VER + #define NO_RC4 + #ifndef HAVE_FIPS + #define WOLFCRYPT_ONLY + #define NO_DES3 + #define NO_SHA + #define NO_MD5 + #else + #define TFM_TIMING_RESISTANT + #define NO_WOLFSSL_DIR + #define NO_WRITEV + #define NO_MAIN_DRIVER + #define WOLFSSL_LOG_PRINTF + #define WOLFSSL_DH_CONST + #endif + #else + #define HAVE_ECC + #define NO_WRITEV + #define NO_MAIN_DRIVER + #define USER_TICKS + #define WOLFSSL_LOG_PRINTF + #define WOLFSSL_DH_CONST + #endif /* _MSC_VER */ + #if !defined(HAVE_FIPS) && !defined(NO_RSA) + #define WC_RSA_BLINDING + #endif + + #define NO_FILESYSTEM + #define ECC_TIMING_RESISTANT + #define TFM_TIMING_RESISTANT + #define SINGLE_THREADED + #define NO_ASN_TIME /* can not use headers such as windows.h */ + #define HAVE_AESGCM + #define USE_CERT_BUFFERS_2048 + #define USE_FAST_MATH +#endif /* WOLFSSL_SGX */ + +/* FreeScale MMCAU hardware crypto has 4 byte alignment. + 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 4 + #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 - requirement here. The record header of SSL/TLS will prvent easy alignment. + requirement here. The record header of SSL/TLS will prevent easy alignment. This hint tries to help as much as possible. */ #ifndef WOLFSSL_GENERAL_ALIGNMENT #ifdef WOLFSSL_AESNI #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 @@ -756,12 +1639,6 @@ #define XGEN_ALIGN #endif -#ifdef HAVE_CRL - /* not widely supported yet */ - #undef NO_SKID - #define NO_SKID -#endif - #ifdef __INTEL_COMPILER #pragma warning(disable:2259) /* explicit casts to smaller sizes, disable */ @@ -770,16 +1647,202 @@ /* user can specify what curves they want with ECC_USER_CURVES otherwise * all curves are on by default for now */ #ifndef ECC_USER_CURVES - #ifndef HAVE_ALL_CURVES + #if !defined(WOLFSSL_SP_MATH) && !defined(HAVE_ALL_CURVES) #define HAVE_ALL_CURVES #endif #endif +/* ECC Configs */ +#ifdef HAVE_ECC + /* By default enable Sign, Verify, DHE, Key Import and Key Export unless explicitly disabled */ + #ifndef NO_ECC_SIGN + #undef HAVE_ECC_SIGN + #define HAVE_ECC_SIGN + #endif + #ifndef NO_ECC_VERIFY + #undef HAVE_ECC_VERIFY + #define HAVE_ECC_VERIFY + #endif + #ifndef NO_ECC_CHECK_KEY + #undef HAVE_ECC_CHECK_KEY + #define HAVE_ECC_CHECK_KEY + #endif + #ifndef NO_ECC_DHE + #undef HAVE_ECC_DHE + #define HAVE_ECC_DHE + #endif + #ifndef NO_ECC_KEY_IMPORT + #undef HAVE_ECC_KEY_IMPORT + #define HAVE_ECC_KEY_IMPORT + #endif + #ifndef NO_ECC_KEY_EXPORT + #undef HAVE_ECC_KEY_EXPORT + #define HAVE_ECC_KEY_EXPORT + #endif +#endif /* HAVE_ECC */ + +/* Curve25519 Configs */ +#ifdef HAVE_CURVE25519 + /* By default enable shared secret, key export and import */ + #ifndef NO_CURVE25519_SHARED_SECRET + #undef HAVE_CURVE25519_SHARED_SECRET + #define HAVE_CURVE25519_SHARED_SECRET + #endif + #ifndef NO_CURVE25519_KEY_EXPORT + #undef HAVE_CURVE25519_KEY_EXPORT + #define HAVE_CURVE25519_KEY_EXPORT + #endif + #ifndef NO_CURVE25519_KEY_IMPORT + #undef HAVE_CURVE25519_KEY_IMPORT + #define HAVE_CURVE25519_KEY_IMPORT + #endif +#endif /* HAVE_CURVE25519 */ + +/* Ed25519 Configs */ +#ifdef HAVE_ED25519 + /* By default enable sign, verify, key export and import */ + #ifndef NO_ED25519_SIGN + #undef HAVE_ED25519_SIGN + #define HAVE_ED25519_SIGN + #endif + #ifndef NO_ED25519_VERIFY + #undef HAVE_ED25519_VERIFY + #define HAVE_ED25519_VERIFY + #endif + #ifndef NO_ED25519_KEY_EXPORT + #undef HAVE_ED25519_KEY_EXPORT + #define HAVE_ED25519_KEY_EXPORT + #endif + #ifndef NO_ED25519_KEY_IMPORT + #undef HAVE_ED25519_KEY_IMPORT + #define HAVE_ED25519_KEY_IMPORT + #endif +#endif /* HAVE_ED25519 */ + +/* Curve448 Configs */ +#ifdef HAVE_CURVE448 + /* By default enable shared secret, key export and import */ + #ifndef NO_CURVE448_SHARED_SECRET + #undef HAVE_CURVE448_SHARED_SECRET + #define HAVE_CURVE448_SHARED_SECRET + #endif + #ifndef NO_CURVE448_KEY_EXPORT + #undef HAVE_CURVE448_KEY_EXPORT + #define HAVE_CURVE448_KEY_EXPORT + #endif + #ifndef NO_CURVE448_KEY_IMPORT + #undef HAVE_CURVE448_KEY_IMPORT + #define HAVE_CURVE448_KEY_IMPORT + #endif +#endif /* HAVE_CURVE448 */ + +/* Ed448 Configs */ +#ifdef HAVE_ED448 + /* By default enable sign, verify, key export and import */ + #ifndef NO_ED448_SIGN + #undef HAVE_ED448_SIGN + #define HAVE_ED448_SIGN + #endif + #ifndef NO_ED448_VERIFY + #undef HAVE_ED448_VERIFY + #define HAVE_ED448_VERIFY + #endif + #ifndef NO_ED448_KEY_EXPORT + #undef HAVE_ED448_KEY_EXPORT + #define HAVE_ED448_KEY_EXPORT + #endif + #ifndef NO_ED448_KEY_IMPORT + #undef HAVE_ED448_KEY_IMPORT + #define HAVE_ED448_KEY_IMPORT + #endif +#endif /* HAVE_ED448 */ + +/* AES Config */ +#ifndef NO_AES + /* By default enable all AES key sizes, decryption and CBC */ + #ifndef AES_MAX_KEY_SIZE + #undef AES_MAX_KEY_SIZE + #define AES_MAX_KEY_SIZE 256 + #endif + + #ifndef NO_AES_128 + #undef WOLFSSL_AES_128 + #define WOLFSSL_AES_128 + #endif + #if !defined(NO_AES_192) && AES_MAX_KEY_SIZE >= 192 + #undef WOLFSSL_AES_192 + #define WOLFSSL_AES_192 + #endif + #if !defined(NO_AES_256) && AES_MAX_KEY_SIZE >= 256 + #undef WOLFSSL_AES_256 + #define WOLFSSL_AES_256 + #endif + #if !defined(WOLFSSL_AES_128) && defined(HAVE_ECC_ENCRYPT) + #warning HAVE_ECC_ENCRYPT uses AES 128 bit keys + #endif + + #ifndef NO_AES_DECRYPT + #undef HAVE_AES_DECRYPT + #define HAVE_AES_DECRYPT + #endif + #ifndef NO_AES_CBC + #undef HAVE_AES_CBC + #define HAVE_AES_CBC + #endif + #ifdef WOLFSSL_AES_XTS + /* AES-XTS makes calls to AES direct functions */ + #ifndef WOLFSSL_AES_DIRECT + #define WOLFSSL_AES_DIRECT + #endif + #endif + #ifdef WOLFSSL_AES_CFB + /* AES-CFB makes calls to AES direct functions */ + #ifndef WOLFSSL_AES_DIRECT + #define WOLFSSL_AES_DIRECT + #endif + #endif +#endif + +#if (defined(WOLFSSL_TLS13) && defined(WOLFSSL_NO_TLS12)) || \ + (!defined(HAVE_AES_CBC) && defined(NO_DES3) && defined(NO_RC4) && \ + !defined(HAVE_CAMELLIA) && !defined(HAVE_IDEA) && \ + !defined(HAVE_NULL_CIPHER) && !defined(HAVE_HC128)) + #define WOLFSSL_AEAD_ONLY +#endif + +#if !defined(NO_DH) && !defined(HAVE_FFDHE) + #if defined(HAVE_FFDHE_2048) || defined(HAVE_FFDHE_3072) || \ + defined(HAVE_FFDHE_4096) || defined(HAVE_FFDHE_6144) || \ + defined(HAVE_FFDHE_8192) + #define HAVE_FFDHE + #endif +#endif +#if defined(HAVE_FFDHE_8192) + #define MIN_FFDHE_FP_MAX_BITS 16384 +#elif defined(HAVE_FFDHE_6144) + #define MIN_FFDHE_FP_MAX_BITS 12288 +#elif defined(HAVE_FFDHE_4096) + #define MIN_FFDHE_FP_MAX_BITS 8192 +#elif defined(HAVE_FFDHE_3072) + #define MIN_FFDHE_FP_MAX_BITS 6144 +#elif defined(HAVE_FFDHE_2048) + #define MIN_FFDHE_FP_MAX_BITS 4096 +#else + #define MIN_FFDHE_FP_MAX_BITS 0 +#endif +#if defined(HAVE_FFDHE) && defined(FP_MAX_BITS) + #if MIN_FFDHE_FP_MAX_BITS > FP_MAX_BITS + #error "FFDHE parameters are too large for FP_MAX_BIT as set" + #endif +#endif + /* if desktop type system and fastmath increase default max bits */ #ifdef WOLFSSL_X86_64_BUILD - #ifdef USE_FAST_MATH - #ifndef FP_MAX_BITS + #if defined(USE_FAST_MATH) && !defined(FP_MAX_BITS) + #if MIN_FFDHE_FP_MAX_BITS <= 8192 #define FP_MAX_BITS 8192 + #else + #define FP_MAX_BITS MIN_FFDHE_FP_MAX_BITS #endif #endif #endif @@ -790,8 +1853,340 @@ #define NO_OLD_TLS #endif + +/* Default AES minimum auth tag sz, allow user to override */ +#ifndef WOLFSSL_MIN_AUTH_TAG_SZ + #define WOLFSSL_MIN_AUTH_TAG_SZ 12 +#endif + + +/* sniffer requires: + * static RSA cipher suites + * session stats and peak stats + */ +#ifdef WOLFSSL_SNIFFER + #ifndef WOLFSSL_STATIC_RSA + #define WOLFSSL_STATIC_RSA + #endif + #ifndef WOLFSSL_STATIC_DH + #define WOLFSSL_STATIC_DH + #endif + /* Allow option to be disabled. */ + #ifndef WOLFSSL_NO_SESSION_STATS + #ifndef WOLFSSL_SESSION_STATS + #define WOLFSSL_SESSION_STATS + #endif + #ifndef WOLFSSL_PEAK_SESSIONS + #define WOLFSSL_PEAK_SESSIONS + #endif + #endif +#endif + +/* Decode Public Key extras on by default, user can turn off with + * WOLFSSL_NO_DECODE_EXTRA */ +#ifndef WOLFSSL_NO_DECODE_EXTRA + #ifndef RSA_DECODE_EXTRA + #define RSA_DECODE_EXTRA + #endif + #ifndef ECC_DECODE_EXTRA + #define ECC_DECODE_EXTRA + #endif +#endif + +/* C Sharp wrapper defines */ +#ifdef HAVE_CSHARP + #ifndef WOLFSSL_DTLS + #define WOLFSSL_DTLS + #endif + #undef NO_PSK + #undef NO_SHA256 + #undef NO_DH +#endif + +/* Asynchronous Crypto */ +#ifdef WOLFSSL_ASYNC_CRYPT + /* Make sure wolf events are enabled */ + #undef HAVE_WOLF_EVENT + #define HAVE_WOLF_EVENT + + #ifdef WOLFSSL_ASYNC_CRYPT_TEST + #define WC_ASYNC_DEV_SIZE 168 + #else + #define WC_ASYNC_DEV_SIZE 336 + #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 + #ifndef HAVE_ECC + #error leantls build needs ECC + #endif +#endif /* WOLFSSL_LEANTLS*/ + +/* restriction with static memory */ +#ifdef WOLFSSL_STATIC_MEMORY + #if defined(HAVE_IO_POOL) || defined(XMALLOC_USER) || defined(NO_WOLFSSL_MEMORY) + #error static memory cannot be used with HAVE_IO_POOL, XMALLOC_USER or NO_WOLFSSL_MEMORY + #endif + #if !defined(USE_FAST_MATH) && !defined(NO_BIG_INT) + #error static memory requires fast math please define USE_FAST_MATH + #endif + #ifdef WOLFSSL_SMALL_STACK + #error static memory does not support small stack please undefine + #endif +#endif /* WOLFSSL_STATIC_MEMORY */ + +#ifdef HAVE_AES_KEYWRAP + #ifndef WOLFSSL_AES_DIRECT + #error AES key wrap requires AES direct please define WOLFSSL_AES_DIRECT + #endif +#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 + #if defined(HAVE_ECC) && !defined(HAVE_X963_KDF) + #error PKCS7 requires X963 KDF please define HAVE_X963_KDF + #endif +#endif + +#ifndef NO_PKCS12 + #undef HAVE_PKCS12 + #define HAVE_PKCS12 +#endif + +#ifndef NO_PKCS8 + #undef HAVE_PKCS8 + #define HAVE_PKCS8 +#endif + +#if !defined(NO_PBKDF1) || defined(WOLFSSL_ENCRYPTED_KEYS) || defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + #undef HAVE_PBKDF1 + #define HAVE_PBKDF1 +#endif + +#if !defined(NO_PBKDF2) || defined(HAVE_PKCS7) || defined(HAVE_SCRYPT) + #undef HAVE_PBKDF2 + #define HAVE_PBKDF2 +#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 */ +#if defined(WOLFSSL_MYSQL_COMPATIBLE) && defined(_WIN32) \ + && defined(HAVE_GMTIME_R) + #undef HAVE_GMTIME_R /* don't trust macro with windows */ +#endif /* WOLFSSL_MYSQL_COMPATIBLE */ + +#if defined(OPENSSL_ALL) || 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) || defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + #define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 +#endif + + +/* both CURVE and ED small math should be enabled */ +#ifdef CURVED25519_SMALL + #define CURVE25519_SMALL + #define ED25519_SMALL +#endif + +/* both CURVE and ED small math should be enabled */ +#ifdef CURVED448_SMALL + #define CURVE448_SMALL + #define ED448_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) && \ + !defined(WC_NO_RNG)) + + #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 + +#if defined(NO_OLD_WC_NAMES) || defined(OPENSSL_EXTRA) + /* added to have compatibility with SHA256() */ + #if !defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) + #define NO_OLD_SHA_NAMES + #endif +#endif + +/* switch for compatibility layer functionality. Has subparts i.e. BIO/X509 + * When opensslextra is enabled all subparts should be turned on. */ +#ifdef OPENSSL_EXTRA + #undef OPENSSL_EXTRA_X509_SMALL + #define OPENSSL_EXTRA_X509_SMALL +#endif /* OPENSSL_EXTRA */ + +/* support for converting DER to PEM */ +#if (defined(WOLFSSL_KEY_GEN) && !defined(WOLFSSL_NO_DER_TO_PEM)) || \ + defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA) + #undef WOLFSSL_DER_TO_PEM + #define WOLFSSL_DER_TO_PEM +#endif + +/* keep backwards compatibility enabling encrypted private key */ +#ifndef WOLFSSL_ENCRYPTED_KEYS + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(HAVE_WEBSERVER) + #define WOLFSSL_ENCRYPTED_KEYS + #endif +#endif + +/* support for disabling PEM to DER */ +#if !defined(WOLFSSL_NO_PEM) + #undef WOLFSSL_PEM_TO_DER + #define WOLFSSL_PEM_TO_DER +#endif + +/* Parts of the openssl compatibility layer require peer certs */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + #undef KEEP_PEER_CERT + #define KEEP_PEER_CERT +#endif + +/* RAW hash function APIs are not implemented with ARMv8 hardware acceleration*/ +#ifdef WOLFSSL_ARMASM + #undef WOLFSSL_NO_HASH_RAW + #define WOLFSSL_NO_HASH_RAW +#endif + +#if !defined(WOLFSSL_SHA384) && !defined(WOLFSSL_SHA512) && defined(NO_AES) && \ + !defined(WOLFSSL_SHA3) + #undef WOLFSSL_NO_WORD64_OPS + #define WOLFSSL_NO_WORD64_OPS +#endif + +#if !defined(WOLFCRYPT_ONLY) && !defined(WOLFSSL_NO_TLS12) + #undef WOLFSSL_HAVE_PRF + #define WOLFSSL_HAVE_PRF +#endif + +#if defined(NO_AES) && defined(NO_DES3) && !defined(HAVE_CAMELLIA) && \ + !defined(WOLFSSL_HAVE_PRF) && defined(NO_PWDBASED) && !defined(HAVE_IDEA) + #undef WOLFSSL_NO_XOR_OPS + #define WOLFSSL_NO_XOR_OPS +#endif + +#if defined(NO_ASN) && defined(WOLFCRYPT_ONLY) + #undef WOLFSSL_NO_INT_ENCODE + #define WOLFSSL_NO_INT_ENCODE + #undef WOLFSSL_NO_INT_DECODE + #define WOLFSSL_NO_INT_DECODE +#endif + +#if defined(WOLFCRYPT_ONLY) && defined(WOLFSSL_RSA_VERIFY_ONLY) && \ + defined(WC_NO_RSA_OAEP) + #undef WOLFSSL_NO_CT_OPS + #define WOLFSSL_NO_CT_OPS +#endif + +#if defined(WOLFCRYPT_ONLY) && defined(NO_AES) && !defined(HAVE_CURVE25519) && \ + !defined(HAVE_CURVE448) && defined(WC_NO_RNG) && defined(WC_NO_RSA_OAEP) + #undef WOLFSSL_NO_CONST_CMP + #define WOLFSSL_NO_CONST_CMP +#endif + +#if defined(WOLFCRYPT_ONLY) && defined(NO_AES) && !defined(WOLFSSL_SHA384) && \ + !defined(WOLFSSL_SHA512) && defined(WC_NO_RNG) && \ + defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_RSA_PUBLIC_ONLY) + #undef WOLFSSL_NO_FORCE_ZERO + #define WOLFSSL_NO_FORCE_ZERO +#endif + +/* Detect old cryptodev name */ +#if defined(WOLF_CRYPTO_DEV) && !defined(WOLF_CRYPTO_CB) + #define WOLF_CRYPTO_CB +#endif + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_NO_SIGALG) + #error TLS 1.3 requires the Signature Algorithms extension to be enabled +#endif + +#ifndef NO_WOLFSSL_BASE64_DECODE + #define WOLFSSL_BASE64_DECODE +#endif + +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + #define MAX_EX_DATA 5 /* allow for five items of ex_data */ +#endif + +#ifdef NO_WOLFSSL_SMALL_STACK + #undef WOLFSSL_SMALL_STACK +#endif + +/* The client session cache requires time for timeout */ +#if defined(NO_ASN_TIME) && !defined(NO_SESSION_CACHE) + #define NO_SESSION_CACHE +#endif + +/* Use static ECC structs for Position Independant Code (PIC) */ +#if defined(__IAR_SYSTEMS_ICC__) && defined(__ROPI__) + #define WOLFSSL_ECC_CURVE_STATIC + #define WOLFSSL_NAMES_STATIC + #define WOLFSSL_NO_CONSTCHARCONST +#endif + #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha.h index 80a2c9832..0b7f65404 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha.h @@ -1,8 +1,8 @@ /* sha.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/sha.h +*/ + + #ifndef WOLF_CRYPT_SHA_H #define WOLF_CRYPT_SHA_H @@ -26,57 +31,143 @@ #ifndef NO_SHA -#ifdef HAVE_FIPS +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +#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 + #ifdef __cplusplus extern "C" { #endif -#ifndef HAVE_FIPS /* avoid redefining structs */ +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + #include +#endif +#ifdef STM32_HASH + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +#ifdef WOLFSSL_ESP32WROOM32_CRYPT + #include +#endif + +#if !defined(NO_OLD_SHA_NAMES) + #define SHA WC_SHA +#endif + +#ifndef NO_OLD_WC_NAMES + #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 { -#ifdef STM32F2_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 = WC_HASH_TYPE_SHA, + 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 { - 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 descripter */ - #endif -} Sha; - -#else /* WOLFSSL_TI_HASH */ +#if defined(WOLFSSL_TI_HASH) #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" + +#elif defined(WOLFSSL_IMX6_CAAM) + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" +#elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH) + #include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h" +#else + +/* Sha digest */ +struct wc_Sha { +#ifdef FREESCALE_LTC_SHA + ltc_hash_ctx_t ctx; +#elif defined(STM32_HASH) + STM32_HASH_Context stmCtx; +#else + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + 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 + #ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; + #endif /* WOLFSSL_ASYNC_CRYPT */ + #ifdef WOLF_CRYPTO_CB + int devId; + void* devCtx; /* generic crypto callback context */ + #endif #endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + WC_ESP32SHA ctx; +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + word32 flags; /* enum wc_HashFlags in hash.h */ +#endif +}; + +#ifndef WC_SHA_TYPE_DEFINED + typedef struct wc_Sha wc_Sha; + #define WC_SHA_TYPE_DEFINED +#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_ShaHash(const byte*, word32, 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_ShaFinalRaw(wc_Sha*, byte*); +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 + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_API int wc_ShaSetFlags(wc_Sha* sha, word32 flags); + WOLFSSL_API int wc_ShaGetFlags(wc_Sha* sha, word32* flags); +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha256.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha256.h index 7cf6d8677..798f309d1 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha256.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha256.h @@ -1,8 +1,8 @@ /* sha256.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* code submitted by raphael.huck@efixo.com */ +/*! + \file wolfssl/wolfcrypt/sha256.h +*/ + + #ifndef WOLF_CRYPT_SHA256_H #define WOLF_CRYPT_SHA256_H @@ -28,53 +32,219 @@ #ifndef NO_SHA256 -#ifdef HAVE_FIPS +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + #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 +#ifdef FREESCALE_LTC_SHA + #include "fsl_ltc.h" +#endif + #ifdef __cplusplus extern "C" { #endif -#ifndef HAVE_FIPS /* avoid redefinition of structs */ -#ifdef WOLFSSL_PIC32MZ_HASH - #include "port/pic32/pic32mz-crypt.h" +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + #include +#endif +#ifdef STM32_HASH + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +#if defined(WOLFSSL_DEVCRYPTO) && defined(WOLFSSL_DEVCRYPTO_HASH) + #include +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) + #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h" +#endif +#if defined(WOLFSSL_CRYPTOCELL) + #include +#endif + +#if defined(_MSC_VER) + #define SHA256_NOINLINE __declspec(noinline) +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__) + #define SHA256_NOINLINE __attribute__((noinline)) +#else + #define SHA256_NOINLINE +#endif + +#if !defined(NO_OLD_SHA_NAMES) + #define SHA256 WC_SHA256 +#endif + +#ifndef NO_OLD_WC_NAMES + #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 = WC_HASH_TYPE_SHA256, + WC_SHA256_BLOCK_SIZE = 64, + WC_SHA256_DIGEST_SIZE = 32, + WC_SHA256_PAD_SIZE = 56 }; -#ifndef WOLFSSL_TI_HASH -/* Sha256 digest */ -typedef struct Sha256 { +#ifdef WOLFSSL_TI_HASH + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#elif defined(WOLFSSL_IMX6_CAAM) + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" +#elif defined(WOLFSSL_AFALG_HASH) + #include "wolfssl/wolfcrypt/port/af_alg/afalg_hash.h" +#elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH) + #include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h" +#else + +/* wc_Sha256 digest */ +struct wc_Sha256 { +#ifdef FREESCALE_LTC_SHA + ltc_hash_ctx_t ctx; +#elif defined(STM32_HASH_SHA2) + STM32_HASH_Context stmCtx; +#else + /* alignment on digest and buffer speeds up ARMv8 crypto operations */ + 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 */ - word32 digest[SHA256_DIGEST_SIZE / sizeof(word32)]; - word32 buffer[SHA256_BLOCK_SIZE / sizeof(word32)]; - #ifdef WOLFSSL_PIC32MZ_HASH - pic32mz_desc desc ; /* Crypt Engine descripter */ - #endif -} Sha256; + void* heap; +#ifdef WOLFSSL_PIC32MZ_HASH + hashUpdCache cache; /* cache for updates */ +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_SMALL_STACK_CACHE + word32* W; +#endif +#ifdef WOLFSSL_DEVCRYPTO_HASH + WC_CRYPTODEV ctx; + byte* msg; + word32 used; + word32 len; +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + WC_ESP32SHA ctx; +#endif +#ifdef WOLFSSL_CRYPTOCELL + CRYS_HASHUserContext_t ctx; +#endif +#ifdef WOLF_CRYPTO_CB + int devId; + void* devCtx; /* generic crypto callback context */ +#endif +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + word32 flags; /* enum wc_HashFlags in hash.h */ +#endif +}; + +#ifndef WC_SHA256_TYPE_DEFINED + typedef struct wc_Sha256 wc_Sha256; + #define WC_SHA256_TYPE_DEFINED +#endif -#else /* WOLFSSL_TI_HASH */ - #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_Sha256Hash(const byte*, word32, 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_Sha256FinalRaw(wc_Sha256*, byte*); +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 + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_API int wc_Sha256SetFlags(wc_Sha256* sha256, word32 flags); + WOLFSSL_API int wc_Sha256GetFlags(wc_Sha256* sha256, word32* flags); +#endif + +#ifdef WOLFSSL_SHA224 +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#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 { + WC_SHA224 = WC_HASH_TYPE_SHA224, + WC_SHA224_BLOCK_SIZE = WC_SHA256_BLOCK_SIZE, + WC_SHA224_DIGEST_SIZE = 28, + WC_SHA224_PAD_SIZE = WC_SHA256_PAD_SIZE +}; + + +#ifndef WC_SHA224_TYPE_DEFINED + typedef struct wc_Sha256 wc_Sha224; + #define WC_SHA224_TYPE_DEFINED +#endif +#endif /* HAVE_FIPS */ + +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); + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_API int wc_Sha224SetFlags(wc_Sha224* sha224, word32 flags); + WOLFSSL_API int wc_Sha224GetFlags(wc_Sha224* sha224, word32* flags); +#endif + +#endif /* WOLFSSL_SHA224 */ #ifdef __cplusplus } /* extern "C" */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha3.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha3.h new file mode 100644 index 000000000..47e2e2c9c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha3.h @@ -0,0 +1,165 @@ +/* sha3.h + * + * Copyright (C) 2006-2020 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 + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +/* in bytes */ +enum { + WC_SHA3_224 = WC_HASH_TYPE_SHA3_224, + WC_SHA3_224_DIGEST_SIZE = 28, + WC_SHA3_224_COUNT = 18, + + WC_SHA3_256 = WC_HASH_TYPE_SHA3_256, + WC_SHA3_256_DIGEST_SIZE = 32, + WC_SHA3_256_COUNT = 17, + + WC_SHA3_384 = WC_HASH_TYPE_SHA3_384, + WC_SHA3_384_DIGEST_SIZE = 48, + WC_SHA3_384_COUNT = 13, + + WC_SHA3_512 = WC_HASH_TYPE_SHA3_512, + WC_SHA3_512_DIGEST_SIZE = 64, + WC_SHA3_512_COUNT = 9, + +#ifndef HAVE_SELFTEST + /* These values are used for HMAC, not SHA-3 directly. + * They come from from FIPS PUB 202. */ + WC_SHA3_224_BLOCK_SIZE = 144, + WC_SHA3_256_BLOCK_SIZE = 136, + WC_SHA3_384_BLOCK_SIZE = 104, + WC_SHA3_512_BLOCK_SIZE = 72, +#endif +}; + +#ifndef NO_OLD_WC_NAMES + #define SHA3_224 WC_SHA3_224 + #define SHA3_224_DIGEST_SIZE WC_SHA3_224_DIGEST_SIZE + #define SHA3_256 WC_SHA3_256 + #define SHA3_256_DIGEST_SIZE WC_SHA3_256_DIGEST_SIZE + #define SHA3_384 WC_SHA3_384 + #define SHA3_384_DIGEST_SIZE WC_SHA3_384_DIGEST_SIZE + #define SHA3_512 WC_SHA3_512 + #define SHA3_512_DIGEST_SIZE WC_SHA3_512_DIGEST_SIZE + #define Sha3 wc_Sha3 +#endif + + + +#ifdef WOLFSSL_XILINX_CRYPT + #include "wolfssl/wolfcrypt/port/xilinx/xil-sha3.h" +#elif defined(WOLFSSL_AFALG_XILINX_SHA3) + #include +#else + +/* Sha3 digest */ +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 */ +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + word32 flags; /* enum wc_HashFlags in hash.h */ +#endif +}; + +#ifndef WC_SHA3_TYPE_DEFINED + typedef struct Sha3 wc_Sha3; + #define WC_SHA3_TYPE_DEFINED +#endif + +#endif + +typedef wc_Sha3 wc_Shake; + + +WOLFSSL_API int wc_InitSha3_224(wc_Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_224_Update(wc_Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_224_Final(wc_Sha3*, byte*); +WOLFSSL_API void wc_Sha3_224_Free(wc_Sha3*); +WOLFSSL_API int wc_Sha3_224_GetHash(wc_Sha3*, byte*); +WOLFSSL_API int wc_Sha3_224_Copy(wc_Sha3* src, wc_Sha3* dst); + +WOLFSSL_API int wc_InitSha3_256(wc_Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_256_Update(wc_Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_256_Final(wc_Sha3*, byte*); +WOLFSSL_API void wc_Sha3_256_Free(wc_Sha3*); +WOLFSSL_API int wc_Sha3_256_GetHash(wc_Sha3*, byte*); +WOLFSSL_API int wc_Sha3_256_Copy(wc_Sha3* src, wc_Sha3* dst); + +WOLFSSL_API int wc_InitSha3_384(wc_Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_384_Update(wc_Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_384_Final(wc_Sha3*, byte*); +WOLFSSL_API void wc_Sha3_384_Free(wc_Sha3*); +WOLFSSL_API int wc_Sha3_384_GetHash(wc_Sha3*, byte*); +WOLFSSL_API int wc_Sha3_384_Copy(wc_Sha3* src, wc_Sha3* dst); + +WOLFSSL_API int wc_InitSha3_512(wc_Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_512_Update(wc_Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_512_Final(wc_Sha3*, byte*); +WOLFSSL_API void wc_Sha3_512_Free(wc_Sha3*); +WOLFSSL_API int wc_Sha3_512_GetHash(wc_Sha3*, byte*); +WOLFSSL_API int wc_Sha3_512_Copy(wc_Sha3* src, wc_Sha3* dst); + +WOLFSSL_API int wc_InitShake256(wc_Shake*, void*, int); +WOLFSSL_API int wc_Shake256_Update(wc_Shake*, const byte*, word32); +WOLFSSL_API int wc_Shake256_Final(wc_Shake*, byte*, word32); +WOLFSSL_API void wc_Shake256_Free(wc_Shake*); +WOLFSSL_API int wc_Shake256_Copy(wc_Shake* src, wc_Sha3* dst); + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_API int wc_Sha3_SetFlags(wc_Sha3* sha3, word32 flags); + WOLFSSL_API int wc_Sha3_GetFlags(wc_Sha3* sha3, word32* flags); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_SHA3 */ +#endif /* WOLF_CRYPT_SHA3_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha512.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha512.h index 83f07c738..3aac94852 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha512.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sha512.h @@ -1,8 +1,8 @@ /* sha512.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,22 +16,48 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/sha512.h +*/ + + #ifndef WOLF_CRYPT_SHA512_H #define WOLF_CRYPT_SHA512_H #include -#ifdef WOLFSSL_SHA512 +#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + #ifdef WOLFSSL_SHA512 + #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 + #endif /* WOLFSSL_SHA512 */ + #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 */ -/* for fips @wc_fips */ -#ifdef HAVE_FIPS #define CYASSL_SHA512 #if defined(WOLFSSL_SHA384) #define CYASSL_SHA384 #endif + /* for fips @wc_fips */ #include #endif @@ -39,59 +65,157 @@ extern "C" { #endif -#ifndef HAVE_FIPS /* avoid redefinition of structs */ +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +#ifdef WOLFSSL_ESP32WROOM32_CRYPT + #include +#endif +#if defined(_MSC_VER) + #define SHA512_NOINLINE __declspec(noinline) +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__) + #define SHA512_NOINLINE __attribute__((noinline)) +#else + #define SHA512_NOINLINE +#endif + +#ifdef WOLFSSL_SHA512 + +#if !defined(NO_OLD_SHA_NAMES) + #define SHA512 WC_SHA512 +#endif + +#if !defined(NO_OLD_WC_NAMES) + #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 + +#endif /* WOLFSSL_SHA512 */ /* in bytes */ enum { - SHA512 = 4, /* hash type unique */ - SHA512_BLOCK_SIZE = 128, - SHA512_DIGEST_SIZE = 64, - SHA512_PAD_SIZE = 112 +#ifdef WOLFSSL_SHA512 + WC_SHA512 = WC_HASH_TYPE_SHA512, +#endif + WC_SHA512_BLOCK_SIZE = 128, + WC_SHA512_DIGEST_SIZE = 64, + WC_SHA512_PAD_SIZE = 112 }; -/* Sha512 digest */ -typedef struct Sha512 { +#ifdef WOLFSSL_IMX6_CAAM + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" +#else +/* wc_Sha512 digest */ +struct wc_Sha512 { + word64 digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)]; + word64 buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64)]; word32 buffLen; /* in bytes */ - word32 loLen; /* length in bytes */ - word32 hiLen; /* length in bytes */ - word64 digest[SHA512_DIGEST_SIZE / sizeof(word64)]; - word64 buffer[SHA512_BLOCK_SIZE / sizeof(word64)]; -} Sha512; + word64 loLen; /* length in bytes */ + word64 hiLen; /* length in bytes */ + void* heap; +#ifdef USE_INTEL_SPEEDUP + const byte* data; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_SMALL_STACK_CACHE + word64* W; +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + WC_ESP32SHA ctx; +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + word32 flags; /* enum wc_HashFlags in hash.h */ +#endif +}; + +#ifndef WC_SHA512_TYPE_DEFINED + typedef struct wc_Sha512 wc_Sha512; + #define WC_SHA512_TYPE_DEFINED +#endif +#endif #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_Sha512Hash(const byte*, word32, byte*); +#ifdef WOLFSSL_ARMASM +WOLFSSL_LOCAL void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, + word32 len); +#endif + +#ifdef WOLFSSL_SHA512 + +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_Sha512FinalRaw(wc_Sha512*, byte*); +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_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_API int wc_Sha512SetFlags(wc_Sha512* sha512, word32 flags); + WOLFSSL_API int wc_Sha512GetFlags(wc_Sha512* sha512, word32* flags); +#endif + +#endif /* WOLFSSL_SHA512 */ #if defined(WOLFSSL_SHA384) -#ifndef HAVE_FIPS /* avoid redefinition of structs */ +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#if !defined(NO_OLD_SHA_NAMES) + #define SHA384 WC_SHA384 +#endif + +#if !defined(NO_OLD_WC_NAMES) + #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 = 128, - SHA384_DIGEST_SIZE = 48, - SHA384_PAD_SIZE = 112 + WC_SHA384 = WC_HASH_TYPE_SHA384, + WC_SHA384_BLOCK_SIZE = WC_SHA512_BLOCK_SIZE, + WC_SHA384_DIGEST_SIZE = 48, + WC_SHA384_PAD_SIZE = WC_SHA512_PAD_SIZE }; -/* Sha384 digest */ -typedef struct Sha384 { - word32 buffLen; /* in bytes */ - word32 loLen; /* length in bytes */ - word32 hiLen; /* length in bytes */ - word64 digest[SHA512_DIGEST_SIZE / sizeof(word64)]; /* for transform 512 */ - word64 buffer[SHA384_BLOCK_SIZE / sizeof(word64)]; -} Sha384; +#ifndef WC_SHA384_TYPE_DEFINED + typedef struct wc_Sha512 wc_Sha384; + #define WC_SHA384_TYPE_DEFINED +#endif #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_Sha384Hash(const byte*, word32, 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_Sha384FinalRaw(wc_Sha384*, byte*); +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); + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_API int wc_Sha384SetFlags(wc_Sha384* sha384, word32 flags); + WOLFSSL_API int wc_Sha384GetFlags(wc_Sha384* sha384, word32* flags); +#endif #endif /* WOLFSSL_SHA384 */ @@ -99,6 +223,6 @@ WOLFSSL_API int wc_Sha384Hash(const byte*, word32, byte*); } /* extern "C" */ #endif -#endif /* WOLFSSL_SHA512 */ +#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */ #endif /* WOLF_CRYPT_SHA512_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/signature.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/signature.h new file mode 100644 index 000000000..afaf2ec6c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/signature.h @@ -0,0 +1,87 @@ +/* signature.h + * + * Copyright (C) 2006-2020 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 + */ + +/*! + \file wolfssl/wolfcrypt/signature.h +*/ + + +#ifndef WOLF_CRYPT_SIGNATURE_H +#define WOLF_CRYPT_SIGNATURE_H + +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +enum wc_SignatureType { + WC_SIGNATURE_TYPE_NONE = 0, + WC_SIGNATURE_TYPE_ECC = 1, + WC_SIGNATURE_TYPE_RSA = 2, + WC_SIGNATURE_TYPE_RSA_W_ENC = 3, /* Adds DER header via wc_EncodeSignature */ +}; + +WOLFSSL_API int wc_SignatureGetSize(enum wc_SignatureType sig_type, + const void* key, word32 key_len); + +WOLFSSL_API int wc_SignatureVerifyHash( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* hash_data, word32 hash_len, + const byte* sig, word32 sig_len, + const void* key, word32 key_len); + +WOLFSSL_API int wc_SignatureVerify( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + const byte* sig, word32 sig_len, + const void* key, word32 key_len); + +WOLFSSL_API int wc_SignatureGenerateHash( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* hash_data, word32 hash_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, WC_RNG* rng); +WOLFSSL_API int wc_SignatureGenerateHash_ex( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* hash_data, word32 hash_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, WC_RNG* rng, int verify); +WOLFSSL_API int wc_SignatureGenerate( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, + WC_RNG* rng); +WOLFSSL_API int wc_SignatureGenerate_ex( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, + WC_RNG* rng, int verify); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_SIGNATURE_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sp.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sp.h new file mode 100644 index 000000000..e468a06fa --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sp.h @@ -0,0 +1,154 @@ +/* sp.h + * + * Copyright (C) 2006-2020 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 + +#include + +#if defined(_MSC_VER) + #define SP_NOINLINE __declspec(noinline) +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__) || defined(__KEIL__) + #define SP_NOINLINE __attribute__((noinline)) +#else + #define SP_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); + +WOLFSSL_LOCAL int sp_RsaPublic_4096(const byte* in, word32 inLen, + mp_int* em, mp_int* mm, byte* out, word32* outLen); +WOLFSSL_LOCAL int sp_RsaPrivate_4096(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 */ + +#if defined(WOLFSSL_HAVE_SP_DH) || defined(WOLFSSL_HAVE_SP_RSA) + +WOLFSSL_LOCAL int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_4096(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); + +#endif + +#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); +WOLFSSL_LOCAL int sp_DhExp_4096(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, mp_int* km, 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); +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY); +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap); +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ); +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ); +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ); +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym); + + +int sp_ecc_mulmod_384(mp_int* km, ecc_point* gm, ecc_point* rm, int map, + void* heap); +int sp_ecc_mulmod_base_384(mp_int* km, ecc_point* rm, int map, void* heap); + +int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap); +int sp_ecc_secret_gen_384(mp_int* priv, ecc_point* pub, byte* out, + word32* outlen, void* heap); +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap); +int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, + mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); +int sp_ecc_is_point_384(mp_int* pX, mp_int* pY); +int sp_ecc_check_key_384(mp_int* pX, mp_int* pY, mp_int* privm, void* heap); +int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ); +int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ); +int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ); +int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym); + +#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/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sp_int.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sp_int.h new file mode 100644 index 000000000..df963951c --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/sp_int.h @@ -0,0 +1,287 @@ +/* sp_int.h + * + * Copyright (C) 2006-2020 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_INT_H +#define WOLF_CRYPT_SP_INT_H + +#include +#include + +/* Make sure WOLFSSL_SP_ASM build option defined when requested */ +#if !defined(WOLFSSL_SP_ASM) && ( \ + defined(WOLFSSL_SP_X86_64_ASM) || defined(WOLFSSL_SP_ARM32_ASM) || \ + defined(WOLFSSL_SP_ARM64_ASM) || defined(WOLFSSL_SP_ARM_THUMB_ASM) || \ + defined(WOLFSSL_SP_ARM_CORTEX_M_ASM)) + #define WOLFSSL_SP_ASM +#endif + + +#ifdef WOLFSSL_SP_X86_64_ASM + #define SP_WORD_SIZE 64 + + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 +#elif defined(WOLFSSL_SP_ARM64_ASM) + #define SP_WORD_SIZE 64 +#elif defined(WOLFSSL_SP_ARM32_ASM) + #define SP_WORD_SIZE 32 +#elif defined(WOLFSSL_SP_ARM_THUMB_ASM) + #define SP_WORD_SIZE 32 +#endif + +#ifndef SP_WORD_SIZE + #if defined(NO_64BIT) || !defined(HAVE___UINT128_T) + #define SP_WORD_SIZE 32 + #else + #define SP_WORD_SIZE 64 + #endif +#endif + +#ifdef WOLFSSL_DSP_BUILD + typedef int32 sp_digit; + typedef uint32 sp_int_digit; + typedef uint64 sp_int_word; + #undef SP_WORD_SIZE + #define SP_WORD_SIZE 32 +#elif !defined(WOLFSSL_SP_ASM) + #if SP_WORD_SIZE == 32 + typedef int32_t sp_digit; + typedef uint32_t sp_int_digit; + typedef uint64_t sp_int_word; + #elif SP_WORD_SIZE == 64 + typedef int64_t sp_digit; + typedef uint64_t sp_int_digit; + #ifdef __SIZEOF_INT128__ + typedef __uint128_t uint128_t; + typedef __int128_t int128_t; + #else + typedef unsigned long uint128_t __attribute__ ((mode(TI))); + typedef long int128_t __attribute__ ((mode(TI))); + #endif + typedef uint128_t sp_int_word; + #else + #error Word size not defined + #endif +#else + #if SP_WORD_SIZE == 32 + typedef uint32_t sp_digit; + typedef uint32_t sp_int_digit; + typedef uint64_t sp_int_word; + #elif SP_WORD_SIZE == 64 + typedef uint64_t sp_digit; + typedef uint64_t sp_int_digit; + #ifdef __SIZEOF_INT128__ + typedef __uint128_t uint128_t; + typedef __int128_t int128_t; + #else + typedef unsigned long uint128_t __attribute__ ((mode(TI))); + typedef long int128_t __attribute__ ((mode(TI))); + #endif + typedef uint128_t sp_int_word; + #else + #error Word size not defined + #endif +#endif + +#define SP_MASK (sp_digit)(-1) + +#ifdef WOLFSSL_SP_MATH +#include + +#if !defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_HAVE_SP_DH) + #if !defined(NO_PWDBASED) && defined(WOLFSSL_SHA512) + #define SP_INT_DIGITS ((512 + SP_WORD_SIZE) / SP_WORD_SIZE) + #elif defined(WOLFSSL_SP_384) + #define SP_INT_DIGITS ((384 + SP_WORD_SIZE) / SP_WORD_SIZE) + #else + #define SP_INT_DIGITS ((256 + SP_WORD_SIZE) / SP_WORD_SIZE) + #endif +#elif defined(WOLFSSL_SP_4096) + #if defined(WOLFSSL_HAVE_SP_DH) + #define SP_INT_DIGITS ((8192 + SP_WORD_SIZE) / SP_WORD_SIZE) + #else + #define SP_INT_DIGITS ((4096 + SP_WORD_SIZE) / SP_WORD_SIZE) + #endif +#elif !defined(WOLFSSL_SP_NO_3072) + #if defined(WOLFSSL_HAVE_SP_DH) + #define SP_INT_DIGITS ((6144 + SP_WORD_SIZE) / SP_WORD_SIZE) + #else + #define SP_INT_DIGITS ((3072 + SP_WORD_SIZE) / SP_WORD_SIZE) + #endif +#else + #if defined(WOLFSSL_HAVE_SP_DH) + #define SP_INT_DIGITS ((4096 + SP_WORD_SIZE) / SP_WORD_SIZE) + #else + #define SP_INT_DIGITS ((2048 + SP_WORD_SIZE) / SP_WORD_SIZE) + #endif +#endif + +#define sp_isodd(a) ((a)->used != 0 && ((a)->dp[0] & 1)) +#define sp_iseven(a) ((a)->used != 0 && ((a)->dp[0] & 1) == 0) +#define sp_iszero(a) ((a)->used == 0) +#define sp_isone(a) ((a)->used == 1 && (a)->dp[0] == 1) +#define sp_abs(a, b) sp_copy(a, b) + +#ifdef HAVE_WOLF_BIGINT + /* raw big integer */ + typedef struct WC_BIGINT { + byte* buf; + word32 len; + void* heap; + } WC_BIGINT; + #define WOLF_BIGINT_DEFINED +#endif + +typedef struct sp_int { + int used; + int size; + sp_int_digit dp[SP_INT_DIGITS]; +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT raw; /* unsigned binary (big endian) */ +#endif +} sp_int; + +typedef sp_int mp_int; +typedef sp_int_digit mp_digit; + +#include + + +MP_API int sp_init(sp_int* a); +MP_API int sp_init_multi(sp_int* a, sp_int* b, sp_int* c, sp_int* d, + sp_int* e, sp_int* f); +MP_API void sp_clear(sp_int* a); +MP_API int sp_unsigned_bin_size(sp_int* a); +MP_API int sp_read_unsigned_bin(sp_int* a, const byte* in, int inSz); +MP_API int sp_read_radix(sp_int* a, const char* in, int radix); +MP_API int sp_cmp(sp_int* a, sp_int* b); +MP_API int sp_count_bits(sp_int* a); +MP_API int sp_leading_bit(sp_int* a); +MP_API int sp_to_unsigned_bin(sp_int* a, byte* out); +MP_API int sp_to_unsigned_bin_len(sp_int* a, byte* out, int outSz); +MP_API void sp_forcezero(sp_int* a); +MP_API int sp_copy(sp_int* a, sp_int* r); +MP_API int sp_set(sp_int* a, sp_int_digit d); +MP_API void sp_clamp(sp_int* a); +MP_API int sp_grow(sp_int* a, int l); +MP_API int sp_sub_d(sp_int* a, sp_int_digit d, sp_int* r); +MP_API int sp_cmp_d(sp_int* a, sp_int_digit d); +MP_API int sp_sub(sp_int* a, sp_int* b, sp_int* r); +MP_API int sp_mod(sp_int* a, sp_int* m, sp_int* r); +MP_API void sp_zero(sp_int* a); +MP_API int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r); +MP_API int sp_lshd(sp_int* a, int s); +MP_API int sp_add(sp_int* a, sp_int* b, sp_int* r); +MP_API int sp_set_int(sp_int* a, unsigned long b); +MP_API int sp_tohex(sp_int* a, char* str); +MP_API int sp_set_bit(sp_int* a, int i); +MP_API int sp_2expt(sp_int* a, int e); +MP_API int sp_rand_prime(sp_int* r, int len, WC_RNG* rng, void* heap); +MP_API int sp_mul(sp_int* a, sp_int* b, sp_int* r); +MP_API int sp_mulmod(sp_int* a, sp_int* b, sp_int* m, sp_int* r); +MP_API int sp_gcd(sp_int* a, sp_int* b, sp_int* r); +MP_API int sp_invmod(sp_int* a, sp_int* m, sp_int* r); +MP_API int sp_lcm(sp_int* a, sp_int* b, sp_int* r); +MP_API int sp_exptmod(sp_int* b, sp_int* e, sp_int* m, sp_int* r); +MP_API int sp_prime_is_prime(mp_int* a, int t, int* result); +MP_API int sp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng); +MP_API int sp_exch(sp_int* a, sp_int* b); +MP_API int sp_get_digit_count(sp_int *a); +MP_API int sp_init_copy (sp_int * a, sp_int * b); +MP_API void sp_rshb(sp_int* a, int n, sp_int* r); +MP_API int sp_mul_d(sp_int* a, sp_int_digit n, sp_int* r); + + +#define MP_OKAY 0 +#define MP_NO 0 +#define MP_YES 1 + +#define MP_RADIX_HEX 16 + +#define MP_GT 1 +#define MP_EQ 0 +#define MP_LT -1 + +#define MP_MEM -2 +#define MP_VAL -3 + +#define DIGIT_BIT SP_WORD_SIZE +#define MP_MASK SP_MASK + +#define CheckFastMathSettings() 1 + +#define mp_free(a) + +#define mp_isodd sp_isodd +#define mp_iseven sp_iseven +#define mp_iszero sp_iszero +#define mp_isone sp_isone +#define mp_abs sp_abs + +#define mp_init sp_init +#define mp_init_multi sp_init_multi +#define mp_clear sp_clear +#define mp_read_unsigned_bin sp_read_unsigned_bin +#define mp_unsigned_bin_size sp_unsigned_bin_size +#define mp_read_radix sp_read_radix +#define mp_cmp sp_cmp +#define mp_count_bits sp_count_bits +#define mp_leading_bit sp_leading_bit +#define mp_to_unsigned_bin sp_to_unsigned_bin +#define mp_to_unsigned_bin_len sp_to_unsigned_bin_len +#define mp_forcezero sp_forcezero +#define mp_copy sp_copy +#define mp_set sp_set +#define mp_clamp sp_clamp +#define mp_grow sp_grow +#define mp_sub_d sp_sub_d +#define mp_cmp_d sp_cmp_d +#define mp_sub sp_sub +#define mp_mod sp_mod +#define mp_zero sp_zero +#define mp_add_d sp_add_d +#define mp_lshd sp_lshd +#define mp_add sp_add +#define mp_set_int sp_set_int +#define mp_tohex sp_tohex +#define mp_set_bit sp_set_bit +#define mp_2expt sp_2expt +#define mp_rand_prime sp_rand_prime +#define mp_mul sp_mul +#define mp_mulmod sp_mulmod +#define mp_gcd sp_gcd +#define mp_invmod sp_invmod +#define mp_lcm sp_lcm +#define mp_exptmod sp_exptmod +#define mp_exptmod_nct sp_exptmod +#define mp_prime_is_prime sp_prime_is_prime +#define mp_prime_is_prime_ex sp_prime_is_prime_ex +#define mp_exch sp_exch +#define get_digit_count sp_get_digit_count +#define mp_init_copy sp_init_copy +#define mp_rshb(A,x) sp_rshb(A,x,A) +#define mp_mul_d sp_mul_d + +#endif + +#endif /* WOLF_CRYPT_SP_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/srp.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/srp.h new file mode 100644 index 000000000..94f198dfb --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/srp.h @@ -0,0 +1,311 @@ +/* srp.h + * + * Copyright (C) 2006-2020 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 + */ + +/*! + \file wolfssl/wolfcrypt/srp.h +*/ + +#ifdef WOLFCRYPT_HAVE_SRP + +#ifndef WOLFCRYPT_SRP_H +#define WOLFCRYPT_SRP_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* Select the largest available hash for the buffer size. */ +#if defined(WOLFSSL_SHA512) + #define SRP_MAX_DIGEST_SIZE WC_SHA512_DIGEST_SIZE +#elif defined(WOLFSSL_SHA384) + #define SRP_MAX_DIGEST_SIZE WC_SHA384_DIGEST_SIZE +#elif !defined(NO_SHA256) + #define SRP_MAX_DIGEST_SIZE WC_SHA256_DIGEST_SIZE +#elif !defined(NO_SHA) + #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 + +/* Set the minimum number of bits acceptable in an SRP modulus */ +#define SRP_MODULUS_MIN_BITS 512 + +/* 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. + */ +typedef enum { + SRP_CLIENT_SIDE = 0, + SRP_SERVER_SIDE = 1, +} SrpSide; + +/** + * SRP hash type, SHA[1|256|384|512]. + */ +typedef enum { + SRP_TYPE_SHA = 1, + SRP_TYPE_SHA256 = 2, + SRP_TYPE_SHA384 = 3, + SRP_TYPE_SHA512 = 4, +} SrpType; + + +/** + * SRP hash struct. + */ +typedef struct { + byte type; + union { + #ifndef NO_SHA + wc_Sha sha; + #endif + #ifndef NO_SHA256 + wc_Sha256 sha256; + #endif + #ifdef WOLFSSL_SHA384 + wc_Sha384 sha384; + #endif + #ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; + #endif + } data; +} SrpHash; + +typedef struct Srp { + SrpSide side; /**< Client or Server, @see SrpSide. */ + SrpType type; /**< Hash type, @see SrpType. */ + byte* user; /**< Username, login. */ + word32 userSz; /**< Username length. */ + byte* salt; /**< Small salt. */ + word32 saltSz; /**< Salt length. */ + mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes.*/ + mp_int g; /**< Generator. A generator modulo N. */ + byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameter. k = H(N, g) */ + mp_int auth; /**< Client: x = H(salt + H(user:pswd)) */ + /**< Server: v = g ^ x % N */ + mp_int priv; /**< Private ephemeral value. */ + SrpHash client_proof; /**< Client proof. Sent to the Server. */ + SrpHash server_proof; /**< Server proof. Sent to the Client. */ + byte* key; /**< Session key. */ + word32 keySz; /**< Session key length. */ + int (*keyGenFunc_cb) (struct Srp* srp, byte* secret, word32 size); + /**< Function responsible for generating the session key. */ + /**< It MUST use XMALLOC with type DYNAMIC_TYPE_SRP to allocate the */ + /**< key buffer for this structure and set keySz to the buffer size. */ + /**< The default function used by this implementation is a modified */ + /**< version of t_mgf1 that uses the proper hash function according */ + /**< to srp->type. */ + void* heap; /**< heap hint pointer */ +} Srp; + +/** + * Initializes the Srp struct for usage. + * + * @param[out] srp the Srp structure to be initialized. + * @param[in] type the hash type to be used. + * @param[in] side the side of the communication. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpInit(Srp* srp, SrpType type, SrpSide side); + +/** + * Releases the Srp struct resources after usage. + * + * @param[in,out] srp the Srp structure to be terminated. + */ +WOLFSSL_API void wc_SrpTerm(Srp* srp); + +/** + * Sets the username. + * + * This function MUST be called after wc_SrpInit. + * + * @param[in,out] srp the Srp structure. + * @param[in] username the buffer containing the username. + * @param[in] size the username size in bytes + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size); + + +/** + * Sets the srp parameters based on the username. + * + * This function MUST be called after wc_SrpSetUsername. + * + * @param[in,out] srp the Srp structure. + * @param[in] N the Modulus. N = 2q+1, [q, N] are primes. + * @param[in] nSz the N size in bytes. + * @param[in] g the Generator modulo N. + * @param[in] gSz the g size in bytes + * @param[in] salt a small random salt. Specific for each username. + * @param[in] saltSz the salt size in bytes + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, + const byte* g, word32 gSz, + const byte* salt, word32 saltSz); + +/** + * Sets the password. + * + * Setting the password does not persists the clear password data in the + * srp structure. The client calculates x = H(salt + H(user:pswd)) and stores + * it in the auth field. + * + * This function MUST be called after wc_SrpSetParams and is CLIENT SIDE ONLY. + * + * @param[in,out] srp the Srp structure. + * @param[in] password the buffer containing the password. + * @param[in] size the password size in bytes. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size); + +/** + * Sets the verifier. + * + * This function MUST be called after wc_SrpSetParams and is SERVER SIDE ONLY. + * + * @param[in,out] srp the Srp structure. + * @param[in] verifier the buffer containing the verifier. + * @param[in] size the verifier size in bytes. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size); + +/** + * Gets the verifier. + * + * The client calculates the verifier with v = g ^ x % N. + * This function MAY be called after wc_SrpSetPassword and is CLIENT SIDE ONLY. + * + * @param[in,out] srp the Srp structure. + * @param[out] verifier the buffer to write the verifier. + * @param[in,out] size the buffer size in bytes. Will be updated with the + * verifier size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size); + +/** + * Sets the private ephemeral value. + * + * The private ephemeral value is known as: + * a at the client side. a = random() + * b at the server side. b = random() + * This function is handy for unit test cases or if the developer wants to use + * an external random source to set the ephemeral value. + * This function MAY be called before wc_SrpGetPublic. + * + * @param[in,out] srp the Srp structure. + * @param[in] priv the ephemeral value. + * @param[in] size the private size in bytes. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpSetPrivate(Srp* srp, const byte* priv, word32 size); + +/** + * Gets the public ephemeral value. + * + * The public ephemeral value is known as: + * A at the client side. A = g ^ a % N + * B at the server side. B = (k * v + (g ˆ b % N)) % N + * This function MUST be called after wc_SrpSetPassword or wc_SrpSetVerifier. + * + * @param[in,out] srp the Srp structure. + * @param[out] pub the buffer to write the public ephemeral value. + * @param[in,out] size the the buffer size in bytes. Will be updated with + * the ephemeral value size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpGetPublic(Srp* srp, byte* pub, word32* size); + + +/** + * Computes the session key. + * + * The key can be accessed at srp->key after success. + * + * @param[in,out] srp the Srp structure. + * @param[in] clientPubKey the client's public ephemeral value. + * @param[in] clientPubKeySz the client's public ephemeral value size. + * @param[in] serverPubKey the server's public ephemeral value. + * @param[in] serverPubKeySz the server's public ephemeral value size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpComputeKey(Srp* srp, + byte* clientPubKey, word32 clientPubKeySz, + byte* serverPubKey, word32 serverPubKeySz); + +/** + * Gets the proof. + * + * This function MUST be called after wc_SrpComputeKey. + * + * @param[in,out] srp the Srp structure. + * @param[out] proof the buffer to write the proof. + * @param[in,out] size the buffer size in bytes. Will be updated with the + * proof size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpGetProof(Srp* srp, byte* proof, word32* size); + +/** + * Verifies the peers proof. + * + * This function MUST be called before wc_SrpGetSessionKey. + * + * @param[in,out] srp the Srp structure. + * @param[in] proof the peers proof. + * @param[in] size the proof size in bytes. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFCRYPT_SRP_H */ +#endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/tfm.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/tfm.h index 1b0bbeab9..b11c7f5a3 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/tfm.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/tfm.h @@ -1,8 +1,8 @@ /* tfm.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,10 +16,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* * Based on public domain TomsFastMath 0.10 by Tom St Denis, tomstdenis@iahu.ca, * http://math.libtomcrypt.com @@ -27,10 +28,13 @@ /** - * Edited by Moiss Guimares (moises.guimaraes@phoebus.com.br) + * Edited by Moises Guimaraes (moises.guimaraes@phoebus.com.br) * to fit CyaSSL's needs. */ +/*! + \file wolfssl/wolfcrypt/tfm.h +*/ #ifndef WOLF_CRYPT_TFM_H #define WOLF_CRYPT_TFM_H @@ -40,21 +44,23 @@ #include #endif +#include #ifdef __cplusplus extern "C" { #endif -#ifndef MIN - #define MIN(x,y) ((x)<(y)?(x):(y)) +#ifdef WOLFSSL_NO_ASM + #undef TFM_NO_ASM + #define TFM_NO_ASM #endif -#ifndef MAX - #define MAX(x,y) ((x)>(y)?(x):(y)) +#ifdef NO_64BIT + #undef NO_TFM_64BIT + #define NO_TFM_64BIT #endif - -#ifndef NO_64BIT +#ifndef NO_TFM_64BIT /* autodetect x86-64 and make sure we are using 64-bit digits with x86-64 asm */ #if defined(__x86_64__) #if defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM) @@ -78,7 +84,7 @@ #undef FP_64BIT #undef TFM_X86_64 #endif -#endif /* NO_64BIT */ +#endif /* NO_TFM_64BIT */ /* try to detect x86-32 */ #if defined(__i386__) && !defined(TFM_SSE2) @@ -201,42 +207,62 @@ #endif +/* allow user to define on fp_digit, fp_word types */ +#ifndef WOLFSSL_BIGINT_TYPES + /* some default configurations. */ -#if defined(FP_64BIT) +#if defined(WC_16BIT_CPU) + typedef unsigned int fp_digit; + #define SIZEOF_FP_DIGIT 2 + typedef unsigned long fp_word; +#elif defined(FP_64BIT) /* for GCC only on supported platforms */ typedef unsigned long long fp_digit; /* 64bit, 128 uses mode(TI) below */ + #define SIZEOF_FP_DIGIT 8 typedef unsigned long fp_word __attribute__ ((mode(TI))); #else - #if defined(_MSC_VER) || defined(__BORLANDC__) - typedef unsigned __int64 ulong64; - #else - typedef unsigned long long ulong64; - #endif - #ifndef NO_64BIT + #ifndef NO_TFM_64BIT + #if defined(_MSC_VER) || defined(__BORLANDC__) + typedef unsigned __int64 ulong64; + #else + typedef unsigned long long ulong64; + #endif typedef unsigned int fp_digit; + #define SIZEOF_FP_DIGIT 4 typedef ulong64 fp_word; #define FP_32BIT #else /* some procs like coldfire prefer not to place multiply into 64bit type even though it exists */ typedef unsigned short fp_digit; + #define SIZEOF_FP_DIGIT 2 typedef unsigned int fp_word; #endif #endif +#endif /* WOLFSSL_BIGINT_TYPES */ + + /* # of digits this is */ -#define DIGIT_BIT (int)((CHAR_BIT) * sizeof(fp_digit)) +#define DIGIT_BIT ((CHAR_BIT) * SIZEOF_FP_DIGIT) /* Max size of any number in bits. Basically the largest size you will be * multiplying should be half [or smaller] of FP_MAX_SIZE-four_digit * - * It defaults to 4096-bits [allowing multiplications upto 2048x2048 bits ] + * It defaults to 4096-bits [allowing multiplications up to 2048x2048 bits ] */ + + #ifndef FP_MAX_BITS #define FP_MAX_BITS 4096 #endif +#ifdef WOLFSSL_OPENSSH + /* OpenSSH uses some BIG primes so we need to accommodate for that */ + #undef FP_MAX_BITS + #define FP_MAX_BITS 16384 +#endif #define FP_MAX_SIZE (FP_MAX_BITS+(8*DIGIT_BIT)) /* will this lib work? */ @@ -248,16 +274,25 @@ #endif #define FP_MASK (fp_digit)(-1) +#define FP_DIGIT_MAX FP_MASK #define FP_SIZE (FP_MAX_SIZE/DIGIT_BIT) +#define FP_MAX_PRIME_SIZE (FP_MAX_BITS/(2*CHAR_BIT)) +/* In terms of FP_MAX_BITS, it is double the size possible for a number + * to allow for multiplication, divide that 2 out. Also divide by CHAR_BIT + * to convert from bits to bytes. (Note, FP_PRIME_SIZE is the number of + * values in the canned prime number list.) */ + /* signs */ #define FP_ZPOS 0 #define FP_NEG 1 /* return codes */ -#define FP_OKAY 0 -#define FP_VAL 1 -#define FP_MEM 2 +#define FP_OKAY 0 +#define FP_VAL -1 +#define FP_MEM -2 +#define FP_NOT_INF -3 +#define FP_WOULDBLOCK -4 /* equalities */ #define FP_LT -1 /* less than */ @@ -268,16 +303,40 @@ #define FP_YES 1 /* yes response */ #define FP_NO 0 /* no response */ +#ifdef HAVE_WOLF_BIGINT + /* raw big integer */ + typedef struct WC_BIGINT { + byte* buf; + word32 len; + void* heap; + } WC_BIGINT; + #define WOLF_BIGINT_DEFINED +#endif + /* a FP type */ -typedef struct { - int used, - sign; -#ifdef ALT_ECC_SIZE +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 HAVE_WOLF_BIGINT + struct WC_BIGINT raw; /* unsigned binary (big endian) */ +#endif } fp_int; +/* Types */ +typedef fp_digit mp_digit; +typedef fp_word mp_word; +typedef fp_int mp_int; + + +/* wolf big int and common functions */ +#include + + /* externally define this symbol to ignore the default settings, useful for changing the build from the make process */ #ifndef TFM_ALREADY_SET @@ -334,9 +393,7 @@ typedef struct { #define TFM_SQR64 #endif -/* do we want some overflow checks - Not required if you make sure your numbers are within range (e.g. by default a modulus for fp_exptmod() can only be upto 2048 bits long) - */ +/* Optional math checks (enable WOLFSSL_DEBUG_MATH to print info) */ /* #define TFM_CHECK */ /* Is the target a P4 Prescott @@ -344,7 +401,7 @@ typedef struct { /* #define TFM_PRESCOTT */ /* Do we want timing resistant fp_exptmod() ? - * This makes it slower but also timing invariant with respect to the exponent + * This makes it slower but also timing invariant with respect to the exponent */ /* #define TFM_TIMING_RESISTANT */ @@ -356,33 +413,40 @@ typedef struct { /*const char *fp_ident(void);*/ /* initialize [or zero] an fp int */ -#ifdef ALT_ECC_SIZE - void fp_init(fp_int *a); - void fp_zero(fp_int *a); -#else - #define fp_init(a) (void)XMEMSET((a), 0, sizeof(fp_int)) - #define fp_zero(a) fp_init(a) -#endif +void fp_init(fp_int *a); +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 ? */ +/* zero/one/even/odd/neg/word ? */ #define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO) +#define fp_isone(a) \ + ((((a)->used == 1) && ((a)->dp[0] == 1)) ? FP_YES : FP_NO) #define fp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO) #define fp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO) +#define fp_isneg(a) (((a)->sign != 0) ? FP_YES : FP_NO) +#define fp_isword(a, w) \ + ((((a)->used == 1) && ((a)->dp[0] == w)) || ((w == 0) && ((a)->used == 0)) \ + ? FP_YES : FP_NO) /* 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); +/* set the b bit to 1 */ +int fp_set_bit (fp_int * a, fp_digit b); /* copy from a to b */ -#ifndef ALT_ECC_SIZE - #define fp_copy(a, b) (void)(((a) != (b)) ? ((void)XMEMCPY((b), (a), sizeof(fp_int))) : (void)0) - #define fp_init_copy(a, b) fp_copy(b, a) -#else - void fp_copy(fp_int *a, fp_int *b); - void fp_init_copy(fp_int *a, fp_int *b); -#endif +void fp_copy(fp_int *a, fp_int *b); +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); } @@ -421,10 +485,10 @@ void fp_add(fp_int *a, fp_int *b, fp_int *c); void fp_sub(fp_int *a, fp_int *b, fp_int *c); /* c = a * b */ -void fp_mul(fp_int *a, fp_int *b, fp_int *c); +int fp_mul(fp_int *a, fp_int *b, fp_int *c); /* b = a*a */ -void fp_sqr(fp_int *a, fp_int *b); +int fp_sqr(fp_int *a, fp_int *b); /* a/b => cb + d == a */ int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d); @@ -439,7 +503,7 @@ int fp_cmp_d(fp_int *a, fp_digit b); void fp_add_d(fp_int *a, fp_digit b, fp_int *c); /* c = a - b */ -void fp_sub_d(fp_int *a, fp_digit b, fp_int *c); +int fp_sub_d(fp_int *a, fp_digit b, fp_int *c); /* c = a * b */ void fp_mul_d(fp_int *a, fp_digit b, fp_int *c); @@ -460,17 +524,24 @@ void fp_mul_d(fp_int *a, fp_digit b, fp_int *c); /* d = a * b (mod c) */ int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); +/* d = a - b (mod c) */ +int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); + +/* d = a + b (mod c) */ +int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); + /* c = a * a (mod b) */ int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c); /* c = 1/a (mod b) */ int fp_invmod(fp_int *a, fp_int *b, fp_int *c); +int fp_invmod_mont_ct(fp_int *a, fp_int *b, fp_int *c, fp_digit mp); /* c = (a, b) */ -/*void fp_gcd(fp_int *a, fp_int *b, fp_int *c);*/ +/*int fp_gcd(fp_int *a, fp_int *b, fp_int *c);*/ /* c = [a, b] */ -/*void fp_lcm(fp_int *a, fp_int *b, fp_int *c);*/ +/*int fp_lcm(fp_int *a, fp_int *b, fp_int *c);*/ /* setups the montgomery reduction */ int fp_montgomery_setup(fp_int *a, fp_digit *mp); @@ -481,18 +552,72 @@ int fp_montgomery_setup(fp_int *a, fp_digit *mp); void fp_montgomery_calc_normalization(fp_int *a, fp_int *b); /* computes x/R == x (mod N) via Montgomery Reduction */ -void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp); +int fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp); /* d = a**b (mod c) */ int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); +int fp_exptmod_ex(fp_int *a, fp_int *b, int minDigits, fp_int *c, fp_int *d); +int fp_exptmod_nct(fp_int *a, fp_int *b, fp_int *c, fp_int *d); + +#ifdef WC_RSA_NONBLOCK + +enum tfmExptModNbState { + TFM_EXPTMOD_NB_INIT = 0, + TFM_EXPTMOD_NB_MONT, + TFM_EXPTMOD_NB_MONT_RED, + TFM_EXPTMOD_NB_MONT_MUL, + TFM_EXPTMOD_NB_MONT_MOD, + TFM_EXPTMOD_NB_MONT_MODCHK, + TFM_EXPTMOD_NB_NEXT, + TFM_EXPTMOD_NB_MUL, + TFM_EXPTMOD_NB_MUL_RED, + TFM_EXPTMOD_NB_SQR, + TFM_EXPTMOD_NB_SQR_RED, + TFM_EXPTMOD_NB_RED, + TFM_EXPTMOD_NB_COUNT /* last item for total state count only */ +}; + +typedef struct { +#ifndef WC_NO_CACHE_RESISTANT + fp_int R[3]; +#else + fp_int R[2]; +#endif + fp_digit buf; + fp_digit mp; + int bitcnt; + int digidx; + int y; + int state; /* tfmExptModNbState */ +#ifdef WC_RSA_NONBLOCK_TIME + word32 maxBlockInst; /* maximum instructions to block */ + word32 totalInst; /* tracks total instructions */ +#endif +} exptModNb_t; + +#ifdef WC_RSA_NONBLOCK_TIME +enum { + TFM_EXPTMOD_NB_STOP = 0, /* stop and return FP_WOULDBLOCK */ + TFM_EXPTMOD_NB_CONTINUE = 1, /* keep blocking */ +}; +#endif + +/* non-blocking version of timing resistant fp_exptmod function */ +/* supports cache resistance */ +int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y); + +#endif /* WC_RSA_NONBLOCK */ /* primality stuff */ /* perform a Miller-Rabin test of a to the base b and store result in "result" */ /*void fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result);*/ +#define FP_PRIME_SIZE 256 /* 256 trial divisions + 8 Miller-Rabins, returns FP_YES if probable prime */ /*int fp_isprime(fp_int *a);*/ +/* extended version of fp_isprime, do 't' Miller-Rabins instead of only 8 */ +/*int fp_isprime_ex(fp_int *a, int t, int* result);*/ /* Primality generation flags */ /*#define TFM_PRIME_BBS 0x0001 */ /* BBS style prime */ @@ -500,23 +625,25 @@ int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); /*#define TFM_PRIME_2MSB_OFF 0x0004 */ /* force 2nd MSB to 0 */ /*#define TFM_PRIME_2MSB_ON 0x0008 */ /* force 2nd MSB to 1 */ -/* callback for fp_prime_random, should fill dst with random bytes and return how many read [upto len] */ +/* callback for fp_prime_random, should fill dst with random bytes and return how many read [up to len] */ /*typedef int tfm_prime_callback(unsigned char *dst, int len, void *dat);*/ /*#define fp_prime_random(a, t, size, bbs, cb, dat) fp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?TFM_PRIME_BBS:0, cb, dat)*/ /*int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat);*/ -/* radix conersions */ +/* radix conversions */ int fp_count_bits(fp_int *a); int fp_leading_bit(fp_int *a); int fp_unsigned_bin_size(fp_int *a); -void fp_read_unsigned_bin(fp_int *a, unsigned char *b, int c); -void fp_to_unsigned_bin(fp_int *a, unsigned char *b); +void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c); +int fp_to_unsigned_bin(fp_int *a, unsigned char *b); +int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c); +int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b); /*int fp_signed_bin_size(fp_int *a);*/ -/*void fp_read_signed_bin(fp_int *a, unsigned char *b, int c);*/ +/*void fp_read_signed_bin(fp_int *a, const unsigned char *b, int c);*/ /*void fp_to_signed_bin(fp_int *a, unsigned char *b);*/ /*int fp_read_radix(fp_int *a, char *str, int radix);*/ @@ -529,189 +656,181 @@ void s_fp_add(fp_int *a, fp_int *b, fp_int *c); void s_fp_sub(fp_int *a, fp_int *b, fp_int *c); void fp_reverse(unsigned char *s, int len); -void fp_mul_comba(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba(fp_int *a, fp_int *b, fp_int *c); -#ifdef TFM_SMALL_SET -void fp_mul_comba_small(fp_int *a, fp_int *b, fp_int *c); -#endif - -#ifdef TFM_MUL3 -void fp_mul_comba3(fp_int *a, fp_int *b, fp_int *c); -#endif -#ifdef TFM_MUL4 -void fp_mul_comba4(fp_int *a, fp_int *b, fp_int *c); -#endif -#ifdef TFM_MUL6 -void fp_mul_comba6(fp_int *a, fp_int *b, fp_int *c); -#endif -#ifdef TFM_MUL7 -void fp_mul_comba7(fp_int *a, fp_int *b, fp_int *c); -#endif -#ifdef TFM_MUL8 -void fp_mul_comba8(fp_int *a, fp_int *b, fp_int *c); -#endif -#ifdef TFM_MUL9 -void fp_mul_comba9(fp_int *a, fp_int *b, fp_int *c); -#endif -#ifdef TFM_MUL12 -void fp_mul_comba12(fp_int *a, fp_int *b, fp_int *c); -#endif -#ifdef TFM_MUL17 -void fp_mul_comba17(fp_int *a, fp_int *b, fp_int *c); -#endif - -#ifdef TFM_MUL20 -void fp_mul_comba20(fp_int *a, fp_int *b, fp_int *c); -#endif -#ifdef TFM_MUL24 -void fp_mul_comba24(fp_int *a, fp_int *b, fp_int *c); -#endif -#ifdef TFM_MUL28 -void fp_mul_comba28(fp_int *a, fp_int *b, fp_int *c); -#endif -#ifdef TFM_MUL32 -void fp_mul_comba32(fp_int *a, fp_int *b, fp_int *c); -#endif -#ifdef TFM_MUL48 -void fp_mul_comba48(fp_int *a, fp_int *b, fp_int *c); -#endif -#ifdef TFM_MUL64 -void fp_mul_comba64(fp_int *a, fp_int *b, fp_int *c); -#endif - -void fp_sqr_comba(fp_int *a, fp_int *b); - -#ifdef TFM_SMALL_SET -void fp_sqr_comba_small(fp_int *a, fp_int *b); -#endif - -#ifdef TFM_SQR3 -void fp_sqr_comba3(fp_int *a, fp_int *b); -#endif -#ifdef TFM_SQR4 -void fp_sqr_comba4(fp_int *a, fp_int *b); -#endif -#ifdef TFM_SQR6 -void fp_sqr_comba6(fp_int *a, fp_int *b); -#endif -#ifdef TFM_SQR7 -void fp_sqr_comba7(fp_int *a, fp_int *b); -#endif -#ifdef TFM_SQR8 -void fp_sqr_comba8(fp_int *a, fp_int *b); -#endif -#ifdef TFM_SQR9 -void fp_sqr_comba9(fp_int *a, fp_int *b); -#endif -#ifdef TFM_SQR12 -void fp_sqr_comba12(fp_int *a, fp_int *b); -#endif -#ifdef TFM_SQR17 -void fp_sqr_comba17(fp_int *a, fp_int *b); -#endif - -#ifdef TFM_SQR20 -void fp_sqr_comba20(fp_int *a, fp_int *b); -#endif -#ifdef TFM_SQR24 -void fp_sqr_comba24(fp_int *a, fp_int *b); -#endif -#ifdef TFM_SQR28 -void fp_sqr_comba28(fp_int *a, fp_int *b); -#endif -#ifdef TFM_SQR32 -void fp_sqr_comba32(fp_int *a, fp_int *b); -#endif -#ifdef TFM_SQR48 -void fp_sqr_comba48(fp_int *a, fp_int *b); -#endif -#ifdef TFM_SQR64 -void fp_sqr_comba64(fp_int *a, fp_int *b); -#endif -/*extern const char *fp_s_rmap;*/ +int fp_mul_comba_small(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba3(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba4(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba6(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba7(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba8(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba9(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba12(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba17(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba20(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba24(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba28(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba32(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba48(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba64(fp_int *a, fp_int *b, fp_int *c); +int fp_sqr_comba(fp_int *a, fp_int *b); +int fp_sqr_comba_small(fp_int *a, fp_int *b); +int fp_sqr_comba3(fp_int *a, fp_int *b); +int fp_sqr_comba4(fp_int *a, fp_int *b); +int fp_sqr_comba6(fp_int *a, fp_int *b); +int fp_sqr_comba7(fp_int *a, fp_int *b); +int fp_sqr_comba8(fp_int *a, fp_int *b); +int fp_sqr_comba9(fp_int *a, fp_int *b); +int fp_sqr_comba12(fp_int *a, fp_int *b); +int fp_sqr_comba17(fp_int *a, fp_int *b); +int fp_sqr_comba20(fp_int *a, fp_int *b); +int fp_sqr_comba24(fp_int *a, fp_int *b); +int fp_sqr_comba28(fp_int *a, fp_int *b); +int fp_sqr_comba32(fp_int *a, fp_int *b); +int fp_sqr_comba48(fp_int *a, fp_int *b); +int fp_sqr_comba64(fp_int *a, fp_int *b); /** * Used by wolfSSL */ -/* Types */ - typedef fp_digit mp_digit; - typedef fp_word mp_word; - typedef fp_int mp_int; - /* Constants */ - #define MP_LT FP_LT /* less than */ - #define MP_EQ FP_EQ /* equal to */ - #define MP_GT FP_GT /* greater than */ - #define MP_VAL FP_VAL /* invalid */ - #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_LT FP_LT /* less than */ +#define MP_EQ FP_EQ /* equal to */ +#define MP_GT FP_GT /* greater than */ +#define MP_VAL FP_VAL /* invalid */ +#define MP_MEM FP_MEM /* memory error */ +#define MP_NOT_INF FP_NOT_INF /* point not at infinity */ +#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_iseven(a) fp_iseven(a) -int mp_init (mp_int * a); -void mp_clear (mp_int * 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_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) +#define mp_isword(a, w) fp_isword(a, w) -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_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); +#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) -int mp_cmp(mp_int *a, mp_int *b); -int mp_cmp_d(mp_int *a, mp_digit b); +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_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_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_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(fp_int *a, fp_digit b); -void mp_rshb(mp_int *a, int x); +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_invmod_mont_ct(mp_int *a, mp_int *b, mp_int *c, fp_digit mp); +MP_API int mp_exptmod (mp_int * g, mp_int * x, mp_int * p, mp_int * y); +MP_API int mp_exptmod_ex (mp_int * g, mp_int * x, int minDigits, mp_int * p, + mp_int * y); +MP_API int mp_exptmod_nct (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); +MP_API int mp_2expt(mp_int* a, int b); + +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_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c); + +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 + MP_API void mp_dump(const char* desc, mp_int* a, byte verbose); +#else + #define mp_dump(desc, a, verbose) +#endif + +#if !defined(NO_DSA) || defined(HAVE_ECC) + MP_API int mp_read_radix(mp_int* a, const char* str, int radix); +#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_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(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); +#if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DSA) || \ + defined(WOLFSSL_KEY_GEN) + MP_API int mp_set(fp_int *a, fp_digit b); #endif +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || !defined(NO_RSA) || \ + !defined(NO_DSA) || !defined(NO_DH) + 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 + +#if !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) || defined(WOLFSSL_KEY_GEN) +MP_API int mp_prime_is_prime(mp_int* a, int t, int* result); +MP_API int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng); +#endif /* !NO_DH || !NO_DSA || !NO_RSA || WOLFSSL_KEY_GEN */ #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); +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_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); +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); +MP_API int mp_abs(mp_int* a, mp_int* b); WOLFSSL_API word32 CheckRunTimeFastMath(void); /* If user uses RSA, DH, DSA, or ECC math lib directly then fast math FP_SIZE must match, return 1 if a match otherwise 0 */ #define CheckFastMathSettings() (FP_SIZE == CheckRunTimeFastMath()) + + #ifdef __cplusplus } #endif diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/types.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/types.h index a5ff1d3f2..362784b38 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/types.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/types.h @@ -1,8 +1,8 @@ /* types.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,307 +16,935 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/types.h +*/ #ifndef WOLF_CRYPT_TYPES_H #define WOLF_CRYPT_TYPES_H - #include - #include + #include + #include - #ifdef __cplusplus - extern "C" { - #endif + #ifdef __cplusplus + extern "C" { + #endif - #if defined(WORDS_BIGENDIAN) - #define BIG_ENDIAN_ORDER - #endif + #define WOLFSSL_ABI + /* Tag for all the APIs that are a part of the fixed ABI. */ - #ifndef BIG_ENDIAN_ORDER - #define LITTLE_ENDIAN_ORDER - #endif + /* + * This struct is used multiple time by other structs and + * needs to be defined somwhere that all structs can import + * (with minimal depencencies). + */ + #if defined(HAVE_EX_DATA) || defined(FORTRESS) + typedef struct WOLFSSL_CRYPTO_EX_DATA { + void* ex_data[MAX_EX_DATA]; + } WOLFSSL_CRYPTO_EX_DATA; + #endif - #ifndef WOLFSSL_TYPES - #ifndef byte - typedef unsigned char byte; - #endif - typedef unsigned short word16; - typedef unsigned int word32; - #endif + #if defined(WORDS_BIGENDIAN) + #define BIG_ENDIAN_ORDER + #endif + + #ifndef BIG_ENDIAN_ORDER + #define LITTLE_ENDIAN_ORDER + #endif + + #ifndef WOLFSSL_TYPES + #ifndef byte + typedef unsigned char byte; + #endif + #ifdef WC_16BIT_CPU + typedef unsigned int word16; + typedef unsigned long word32; + #else + typedef unsigned short word16; + typedef unsigned int word32; + #endif + 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(SIZEOF_LONG_LONG) && !defined(SIZEOF_LONG) - #if (defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) \ - || defined(__mips64) || defined(__x86_64__)) - /* 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 + /* constant pointer to a constant char */ + #ifdef WOLFSSL_NO_CONSTCHARCONST + typedef const char* wcchar; + #else + typedef const char* const wcchar; + #endif - #if defined(_MSC_VER) || defined(__BCPLUSPLUS__) - #define WORD64_AVAILABLE - #define W64LIT(x) x##ui64 - typedef unsigned __int64 word64; - #elif defined(SIZEOF_LONG) && SIZEOF_LONG == 8 - #define WORD64_AVAILABLE - #define W64LIT(x) x##LL - typedef unsigned long word64; - #elif defined(SIZEOF_LONG_LONG) && SIZEOF_LONG_LONG == 8 - #define WORD64_AVAILABLE - #define W64LIT(x) x##LL - typedef unsigned long long word64; - #elif defined(__SIZEOF_LONG_LONG__) && __SIZEOF_LONG_LONG__ == 8 - #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 + /* try to set SIZEOF_LONG or SIZEOF_LONG_LONG if user didn't */ + #if defined(_MSC_VER) || defined(HAVE_LIMITS_H) + #if !defined(SIZEOF_LONG_LONG) && !defined(SIZEOF_LONG) + #include + #if defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL) + #define SIZEOF_LONG 4 + #endif + #if defined(ULLONG_MAX) && (ULLONG_MAX == 0xffffffffffffffffULL) + #define SIZEOF_LONG_LONG 8 + #endif + #endif + #elif !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__) || defined(__s390x__ ) || \ + ((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 + + #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 + typedef unsigned long word64; + #elif defined(SIZEOF_LONG_LONG) && SIZEOF_LONG_LONG == 8 + #define WORD64_AVAILABLE + #define W64LIT(x) x##LL + typedef unsigned long long word64; + #elif defined(__SIZEOF_LONG_LONG__) && __SIZEOF_LONG_LONG__ == 8 + #define WORD64_AVAILABLE + #define W64LIT(x) x##LL + typedef unsigned long long word64; + #endif + +#if !defined(NO_64BIT) && defined(WORD64_AVAILABLE) && !defined(WC_16BIT_CPU) + /* 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(__sparc64__) || defined(__s390x__ ) || \ + (defined(__riscv_xlen) && (__riscv_xlen == 64)) + typedef word64 wolfssl_word; + #define WC_64BIT_CPU + #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 + * available 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 + +#elif defined(WC_16BIT_CPU) + #undef WORD64_AVAILABLE + typedef word16 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 */ + +#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), + WOLFSSL_BIT_SIZE = 8, + WOLFSSL_WORD_BITS = WOLFSSL_WORD_SIZE * WOLFSSL_BIT_SIZE + }; + + #define WOLFSSL_MAX_16BIT 0xffffU + + /* use inlining if compiler allows */ + #ifndef WC_INLINE + #ifndef NO_INLINE + #ifdef _MSC_VER + #define WC_INLINE __inline + #elif defined(__GNUC__) + #ifdef WOLFSSL_VXWORKS + #define WC_INLINE __inline__ + #else + #define WC_INLINE inline + #endif + #elif defined(__IAR_SYSTEMS_ICC__) + #define WC_INLINE inline + #elif defined(THREADX) + #define WC_INLINE _Inline + #elif defined(__ghc__) + #ifndef __cplusplus + #define WC_INLINE __inline + #else + #define WC_INLINE inline + #endif + #else + #define WC_INLINE + #endif + #else + #define WC_INLINE + #endif + #endif + + #if defined(HAVE_FIPS) || defined(HAVE_SELFTEST) + #define INLINE WC_INLINE + #endif - /* These platforms have 64-bit CPU registers. */ - #if (defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \ - defined(__mips64) || defined(__x86_64__) || defined(_M_X64)) - typedef word64 wolfssl_word; - #else - typedef word32 wolfssl_word; - #ifdef WORD64_AVAILABLE - #define WOLFCRYPT_SLOW_WORD64 - #endif - #endif + /* set up rotate style */ + #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__) || defined(__x86_64__)) + /* GCC does peephole optimizations which should result in using rotate + instructions */ + #define FAST_ROTATE + #endif - enum { - WOLFSSL_WORD_SIZE = sizeof(wolfssl_word), - WOLFSSL_BIT_SIZE = 8, - WOLFSSL_WORD_BITS = WOLFSSL_WORD_SIZE * WOLFSSL_BIT_SIZE - }; + /* set up thread local storage if available */ + #ifdef HAVE_THREAD_LS + #if defined(_MSC_VER) + #define THREAD_LS_T __declspec(thread) + /* Thread local storage only in FreeRTOS v8.2.1 and higher */ + #elif defined(FREERTOS) || defined(FREERTOS_TCP) || \ + defined(WOLFSSL_ZEPHYR) + #define THREAD_LS_T + #else + #define THREAD_LS_T __thread + #endif + #else + #define THREAD_LS_T + #endif - #define WOLFSSL_MAX_16BIT 0xffffU + /* GCC 7 has new switch() fall-through detection */ + /* default to FALL_THROUGH stub */ + #ifndef FALL_THROUGH + #define FALL_THROUGH - /* use inlining if compiler allows */ - #ifndef INLINE - #ifndef NO_INLINE - #ifdef _MSC_VER - #define INLINE __inline - #elif defined(__GNUC__) - #define INLINE inline - #elif defined(__IAR_SYSTEMS_ICC__) - #define INLINE inline - #elif defined(THREADX) - #define INLINE _Inline - #else - #define INLINE - #endif - #else - #define INLINE - #endif - #endif + #if defined(__GNUC__) + #if ((__GNUC__ > 7) || ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 1))) + #undef FALL_THROUGH + #define FALL_THROUGH __attribute__ ((fallthrough)); + #endif + #endif + #endif /* FALL_THROUGH */ + + /* 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(INTIME_RTOS) + #define USE_WINDOWS_API + #endif + + #define XSTR_SIZEOF(x) (sizeof(x) - 1) /* -1 to not count the null char */ + + /* idea to add global alloc override by Moises Guimaraes */ + /* default to libc stuff */ + /* XREALLOC is used once in normal math lib, not in fast math lib */ + /* XFREE on some embedded systems doesn't like free(0) so test */ + #if defined(HAVE_IO_POOL) + 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(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_INTEL_QA)) || \ + defined(HAVE_INTEL_QA_SYNC) + #ifndef HAVE_INTEL_QA_SYNC + #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 */ + #else + #include + #undef USE_WOLFSSL_MEMORY + #ifdef WOLFSSL_DEBUG_MEMORY + #define XMALLOC(s, h, t) wc_CryptoCb_IntelQaMalloc((s), (h), (t), __func__, __LINE__) + #define XFREE(p, h, t) wc_CryptoCb_IntelQaFree((p), (h), (t), __func__, __LINE__) + #define XREALLOC(p, n, h, t) wc_CryptoCb_IntelQaRealloc((p), (n), (h), (t), __func__, __LINE__) + #else + #define XMALLOC(s, h, t) wc_CryptoCb_IntelQaMalloc((s), (h), (t)) + #define XFREE(p, h, t) wc_CryptoCb_IntelQaFree((p), (h), (t)) + #define XREALLOC(p, n, h, t) wc_CryptoCb_IntelQaRealloc((p), (n), (h), (t)) + #endif /* WOLFSSL_DEBUG_MEMORY */ + #endif + #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(WOLFSSL_MEMORY_LOG) + #define XMALLOC(n, h, t) xmalloc(n, h, t, __func__, __FILE__, __LINE__) + #define XREALLOC(p, n, h, t) xrealloc(p, n, h, t, __func__, __FILE__, __LINE__) + #define XFREE(p, h, t) xfree(p, h, t, __func__, __FILE__, __LINE__) + + /* prototypes for user heap override functions */ + #include /* for size_t */ + #include + WOLFSSL_API void *xmalloc(size_t n, void* heap, int type, + const char* func, const char* file, unsigned int line); + WOLFSSL_API void *xrealloc(void *p, size_t n, void* heap, int type, + const char* func, const char* file, unsigned int line); + WOLFSSL_API void xfree(void *p, void* heap, int type, const char* func, + const char* file, unsigned int line); + #elif defined(XMALLOC_OVERRIDE) + /* override the XMALLOC, XFREE and XREALLOC macros */ + #elif defined(WOLFSSL_TELIT_M2MB) + /* Telit M2MB SDK requires use m2mb_os API's, not std malloc/free */ + /* Use of malloc/free will cause CPU reboot */ + #define XMALLOC(s, h, t) ((void)h, (void)t, m2mb_os_malloc((s))) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) m2mb_os_free((xp));} + #define XREALLOC(p, n, h, t) m2mb_os_realloc((p), (n)) + + #elif defined(NO_WOLFSSL_MEMORY) + #ifdef WOLFSSL_NO_MALLOC + /* this platform does not support heap use */ + #ifdef WOLFSSL_MALLOC_CHECK + #include + static inline void* malloc_check(size_t sz) { + printf("wolfSSL_malloc failed"); + return NULL; + }; + #define XMALLOC(s, h, t) malloc_check((s)) + #define XFREE(p, h, t) + #define XREALLOC(p, n, h, t) (NULL) + #else + #define XMALLOC(s, h, t) (NULL) + #define XFREE(p, h, t) + #define XREALLOC(p, n, h, t) (NULL) + #endif + #else + /* just use plain C stdlib stuff if desired */ + #include + #define XMALLOC(s, h, t) malloc((s)) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) free((xp));} + #define XREALLOC(p, n, h, t) realloc((p), (n)) + #endif + #elif !defined(MICRIUM_MALLOC) && !defined(EBSNET) \ + && !defined(WOLFSSL_SAFERTOS) && !defined(FREESCALE_MQX) \ + && !defined(FREESCALE_KSDK_MQX) && !defined(FREESCALE_FREE_RTOS) \ + && !defined(WOLFSSL_LEANPSK) && !defined(WOLFSSL_uITRON4) + /* default C runtime, can install different routines at runtime via cbs */ + #include + #ifdef WOLFSSL_STATIC_MEMORY + #ifdef WOLFSSL_DEBUG_MEMORY + #define XMALLOC(s, h, t) wolfSSL_Malloc((s), (h), (t), __func__, __LINE__) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp), (h), (t), __func__, __LINE__);} + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), (h), (t), __func__, __LINE__) + #else + #define XMALLOC(s, h, t) wolfSSL_Malloc((s), (h), (t)) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp), (h), (t));} + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), (h), (t)) + #endif /* WOLFSSL_DEBUG_MEMORY */ + #elif !defined(FREERTOS) && !defined(FREERTOS_TCP) + #ifdef WOLFSSL_DEBUG_MEMORY + #define XMALLOC(s, h, t) ((void)h, (void)t, wolfSSL_Malloc((s), __func__, __LINE__)) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp), __func__, __LINE__);} + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), __func__, __LINE__) + #else + #define XMALLOC(s, h, t) ((void)h, (void)t, wolfSSL_Malloc((s))) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp));} + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n)) + #endif /* WOLFSSL_DEBUG_MEMORY */ + #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 + #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)) + #define XMEMMOVE(d,s,l) memmove((d),(s),(l)) + + #define XSTRLEN(s1) strlen((s1)) + #define XSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n)) + /* strstr, strncmp, and strncat only used by wolfSSL proper, + * not required for wolfCrypt only */ + #define XSTRSTR(s1,s2) strstr((s1),(s2)) + #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)) + + #ifdef USE_WOLF_STRSEP + #define XSTRSEP(s1,d) wc_strsep((s1),(d)) + #else + #define XSTRSEP(s1,d) strsep((s1),(d)) + #endif + + #ifndef XSTRNCASECMP + #if defined(MICROCHIP_PIC32) || defined(WOLFSSL_TIRTOS) || \ + defined(WOLFSSL_ZEPHYR) + /* XC32 does not support strncasecmp, so use case sensitive one */ + #define XSTRNCASECMP(s1,s2,n) strncmp((s1),(s2),(n)) + #elif defined(USE_WINDOWS_API) || defined(FREERTOS_TCP_WINSIM) + #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) + #else + #if defined(HAVE_STRINGS_H) && defined(WOLF_C99) && \ + !defined(WOLFSSL_SGX) + #include + #endif + #if defined(WOLFSSL_DEOS) + #define XSTRNCASECMP(s1,s2,n) strnicmp((s1),(s2),(n)) + #else + #define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n)) + #endif + #endif + #endif /* !XSTRNCASECMP */ + + /* snprintf is used in asn.c for GetTimeString, PKCS7 test, and when + debugging is turned on */ + #ifndef USE_WINDOWS_API + #ifndef XSNPRINTF + #if defined(NO_FILESYSTEM) && (defined(OPENSSL_EXTRA) || \ + defined(HAVE_PKCS7)) && !defined(NO_STDIO_FILESYSTEM) + /* case where stdio is not included else where but is needed + for snprintf */ + #include + #endif + #define XSNPRINTF snprintf + #endif + #else + #if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) + #if defined(_MSC_VER) && (_MSC_VER >= 1900) + /* Beginning with the UCRT in Visual Studio 2015 and + Windows 10, snprintf is no longer identical to + _snprintf. The snprintf function behavior is now + C99 standard compliant. */ + #include + #define XSNPRINTF snprintf + #else + /* 4996 warning to use MS extensions e.g., _sprintf_s + instead of _snprintf */ + #if !defined(__MINGW32__) + #pragma warning(disable: 4996) + #endif + static WC_INLINE + int xsnprintf(char *buffer, size_t bufsize, + const char *format, ...) { + va_list ap; + int ret; + + if ((int)bufsize <= 0) return -1; + va_start(ap, format); + ret = vsnprintf(buffer, bufsize, format, ap); + if (ret >= (int)bufsize) + ret = -1; + va_end(ap); + return ret; + } + #define XSNPRINTF xsnprintf + #endif /* (_MSC_VER >= 1900) */ + #else + #define XSNPRINTF snprintf + #endif /* _MSC_VER */ + #endif /* USE_WINDOWS_API */ + + #if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) \ + || defined(HAVE_ALPN) + /* use only Thread Safe version of strtok */ + #if defined(USE_WOLF_STRTOK) + #define XSTRTOK(s1,d,ptr) wc_strtok((s1),(d),(ptr)) + #elif defined(USE_WINDOWS_API) || defined(INTIME_RTOS) + #define XSTRTOK(s1,d,ptr) strtok_s((s1),(d),(ptr)) + #else + #define XSTRTOK(s1,d,ptr) strtok_r((s1),(d),(ptr)) + #endif + #endif + + #if defined(WOLFSSL_CERT_EXT) || defined(HAVE_OCSP) || \ + defined(HAVE_CRL_IO) || defined(HAVE_HTTP_CLIENT) || \ + !defined(NO_CRYPT_BENCHMARK) + + #ifndef XATOI /* if custom XATOI is not already defined */ + #include + #define XATOI(s) atoi((s)) + #endif + #endif + #endif + + #ifdef USE_WOLF_STRTOK + WOLFSSL_API char* wc_strtok(char *str, const char *delim, char **nextp); + #endif + #ifdef USE_WOLF_STRSEP + WOLFSSL_API char* wc_strsep(char **stringp, const char *delim); + #endif + + #if !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ + !defined(NO_STDIO_FILESYSTEM) + #ifndef XGETENV + #include + #define XGETENV getenv + #endif + #endif /* OPENSSL_EXTRA */ + + #ifndef CTYPE_USER + #include + #if defined(HAVE_ECC) || defined(HAVE_OCSP) || \ + defined(WOLFSSL_KEY_GEN) || !defined(NO_DSA) + #define XTOUPPER(c) toupper((c)) + #define XISALPHA(c) isalpha((c)) + #endif + /* needed by wolfSSL_check_domain_name() */ + #define XTOLOWER(c) tolower((c)) + #endif - /* set up rotate style */ - #if defined(_MSC_VER) || defined(__BCPLUSPLUS__) - #define INTEL_INTRINSICS - #define FAST_ROTATE - #elif defined(__MWERKS__) && TARGET_CPU_PPC - #define PPC_INTRINSICS - #define FAST_ROTATE - #elif defined(__GNUC__) && defined(__i386__) - /* GCC does peephole optimizations which should result in using rotate - instructions */ - #define FAST_ROTATE - #endif + /* 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_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_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_SYMMETRIC_KEY= 84, + DYNAMIC_TYPE_ECC_BUFFER = 85, + DYNAMIC_TYPE_QSH = 86, + DYNAMIC_TYPE_SALT = 87, + DYNAMIC_TYPE_HASH_TMP = 88, + DYNAMIC_TYPE_BLOB = 89, + DYNAMIC_TYPE_NAME_ENTRY = 90, + DYNAMIC_TYPE_CURVE448 = 91, + DYNAMIC_TYPE_ED448 = 92, + DYNAMIC_TYPE_SNIFFER_SERVER = 1000, + DYNAMIC_TYPE_SNIFFER_SESSION = 1001, + DYNAMIC_TYPE_SNIFFER_PB = 1002, + DYNAMIC_TYPE_SNIFFER_PB_BUFFER = 1003, + DYNAMIC_TYPE_SNIFFER_TICKET_ID = 1004, + DYNAMIC_TYPE_SNIFFER_NAMED_KEY = 1005, + }; + + /* max error buffer string size */ + #ifndef WOLFSSL_MAX_ERROR_SZ + #define WOLFSSL_MAX_ERROR_SZ 80 + #endif + + /* stack protection */ + enum { + MIN_STACK_BUFFER = 8 + }; - /* set up thread local storage if available */ - #ifdef HAVE_THREAD_LS - #if defined(_MSC_VER) - #define THREAD_LS_T __declspec(thread) - #else - #define THREAD_LS_T __thread - #endif - #else - #define THREAD_LS_T - #endif + /* Algorithm Types */ + enum wc_AlgoType { + WC_ALGO_TYPE_NONE = 0, + WC_ALGO_TYPE_HASH = 1, + WC_ALGO_TYPE_CIPHER = 2, + WC_ALGO_TYPE_PK = 3, + WC_ALGO_TYPE_RNG = 4, + WC_ALGO_TYPE_SEED = 5, + WC_ALGO_TYPE_HMAC = 6, + + WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_HMAC + }; + + /* hash types */ + enum wc_HashType { + #if defined(HAVE_SELFTEST) || defined(HAVE_FIPS) + /* In selftest build, WC_* types are not mapped to WC_HASH_TYPE types. + * Values here are based on old selftest hmac.h enum, with additions. + * These values are fixed for backwards FIPS compatibility */ + WC_HASH_TYPE_NONE = 15, + WC_HASH_TYPE_MD2 = 16, + WC_HASH_TYPE_MD4 = 17, + WC_HASH_TYPE_MD5 = 0, + WC_HASH_TYPE_SHA = 1, /* SHA-1 (not old SHA-0) */ + WC_HASH_TYPE_SHA224 = 8, + WC_HASH_TYPE_SHA256 = 2, + WC_HASH_TYPE_SHA384 = 5, + WC_HASH_TYPE_SHA512 = 4, + WC_HASH_TYPE_MD5_SHA = 18, + WC_HASH_TYPE_SHA3_224 = 10, + WC_HASH_TYPE_SHA3_256 = 11, + WC_HASH_TYPE_SHA3_384 = 12, + WC_HASH_TYPE_SHA3_512 = 13, + WC_HASH_TYPE_BLAKE2B = 14, + WC_HASH_TYPE_BLAKE2S = 19, + + WC_HASH_TYPE_MAX = WC_HASH_TYPE_BLAKE2S + #else + WC_HASH_TYPE_NONE = 0, + WC_HASH_TYPE_MD2 = 1, + WC_HASH_TYPE_MD4 = 2, + WC_HASH_TYPE_MD5 = 3, + WC_HASH_TYPE_SHA = 4, /* SHA-1 (not old SHA-0) */ + WC_HASH_TYPE_SHA224 = 5, + WC_HASH_TYPE_SHA256 = 6, + WC_HASH_TYPE_SHA384 = 7, + WC_HASH_TYPE_SHA512 = 8, + WC_HASH_TYPE_MD5_SHA = 9, + WC_HASH_TYPE_SHA3_224 = 10, + WC_HASH_TYPE_SHA3_256 = 11, + WC_HASH_TYPE_SHA3_384 = 12, + WC_HASH_TYPE_SHA3_512 = 13, + WC_HASH_TYPE_BLAKE2B = 14, + WC_HASH_TYPE_BLAKE2S = 15, + + WC_HASH_TYPE_MAX = WC_HASH_TYPE_BLAKE2S + #endif /* HAVE_SELFTEST */ + }; + + /* cipher types */ + enum wc_CipherType { + WC_CIPHER_NONE = 0, + WC_CIPHER_AES = 1, + WC_CIPHER_AES_CBC = 2, + WC_CIPHER_AES_GCM = 3, + WC_CIPHER_AES_CTR = 4, + WC_CIPHER_AES_XTS = 5, + WC_CIPHER_AES_CFB = 6, + WC_CIPHER_DES3 = 7, + WC_CIPHER_DES = 8, + WC_CIPHER_CHACHA = 9, + WC_CIPHER_HC128 = 10, + WC_CIPHER_IDEA = 11, + + WC_CIPHER_MAX = WC_CIPHER_HC128 + }; + + /* PK=public key (asymmetric) based algorithms */ + enum wc_PkType { + WC_PK_TYPE_NONE = 0, + WC_PK_TYPE_RSA = 1, + WC_PK_TYPE_DH = 2, + WC_PK_TYPE_ECDH = 3, + WC_PK_TYPE_ECDSA_SIGN = 4, + WC_PK_TYPE_ECDSA_VERIFY = 5, + WC_PK_TYPE_ED25519 = 6, + WC_PK_TYPE_CURVE25519 = 7, + WC_PK_TYPE_RSA_KEYGEN = 8, + WC_PK_TYPE_EC_KEYGEN = 9, + + WC_PK_TYPE_MAX = WC_PK_TYPE_EC_KEYGEN + }; - /* Micrium will use Visual Studio for compilation but not the Win32 API */ - #if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) \ - && !defined(EBSNET) - #define USE_WINDOWS_API - #endif + /* settings detection for compile vs runtime math incompatibilities */ + enum { + #if !defined(USE_FAST_MATH) && !defined(SIZEOF_LONG) && !defined(SIZEOF_LONG_LONG) + CTC_SETTINGS = 0x0 + #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8) + CTC_SETTINGS = 0x1 + #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8) + CTC_SETTINGS = 0x2 + #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 4) + CTC_SETTINGS = 0x4 + #elif defined(USE_FAST_MATH) && !defined(SIZEOF_LONG) && !defined(SIZEOF_LONG_LONG) + CTC_SETTINGS = 0x8 + #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8) + CTC_SETTINGS = 0x10 + #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8) + CTC_SETTINGS = 0x20 + #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 4) + CTC_SETTINGS = 0x40 + #else + #error "bad math long / long long settings" + #endif + }; - /* idea to add global alloc override by Moisés Guimarães */ - /* default to libc stuff */ - /* XREALLOC is used once in normal math lib, not in fast math lib */ - /* XFREE on some embeded systems doesn't like free(0) so test */ - #if 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(NO_WOLFSSL_MEMORY) - /* just use plain C stdlib stuff if desired */ - #include - #define XMALLOC(s, h, t) ((void)h, (void)t, malloc((s))) - #define XFREE(p, h, t) {void* xp = (p); if((xp)) free((xp));} - #define XREALLOC(p, n, h, t) realloc((p), (n)) - #elif !defined(MICRIUM_MALLOC) && !defined(EBSNET) \ - && !defined(WOLFSSL_SAFERTOS) && !defined(FREESCALE_MQX) \ - && !defined(WOLFSSL_LEANPSK) - /* default C runtime, can install different routines at runtime via cbs */ - #include - #define XMALLOC(s, h, t) ((void)h, (void)t, wolfSSL_Malloc((s))) - #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp));} - #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n)) - #endif + WOLFSSL_API word32 CheckRunTimeSettings(void); - #ifndef STRING_USER - #include - char* mystrnstr(const char* s1, const char* s2, unsigned int n); + /* If user uses RSA, DH, DSA, or ECC math lib directly then fast math and long + types need to match at compile time and run time, CheckCtcSettings will + return 1 if a match otherwise 0 */ + #define CheckCtcSettings() (CTC_SETTINGS == CheckRunTimeSettings()) - #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)) - #define XMEMMOVE(d,s,l) memmove((d),(s),(l)) - - #define XSTRLEN(s1) strlen((s1)) - #define XSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n)) - /* strstr, strncmp, and strncat only used by wolfSSL proper, not required for - CTaoCrypt only */ - #define XSTRSTR(s1,s2) strstr((s1),(s2)) - #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)) - #define XSNPRINTF snprintf - #else - #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) - #define XSNPRINTF _snprintf - #endif - #endif - - #ifndef CTYPE_USER - #include - #if defined(HAVE_ECC) || defined(HAVE_OCSP) - #define XTOUPPER(c) toupper((c)) - #define XISALPHA(c) isalpha((c)) - #endif - /* needed by wolfSSL_check_domain_name() */ - #define XTOLOWER(c) tolower((c)) - #endif + /* invalid device id */ + #define INVALID_DEVID -2 - /* 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_CAVIUM_TMP = 40, - DYNAMIC_TYPE_CAVIUM_RSA = 41, - DYNAMIC_TYPE_X509 = 42, - DYNAMIC_TYPE_TLSX = 43, - DYNAMIC_TYPE_OCSP = 44, - DYNAMIC_TYPE_SIGNATURE = 45, - DYNAMIC_TYPE_HASHES = 46 - }; + /* AESNI requires alignment and ARMASM gains some performance from it + * Xilinx RSA operations require alignment */ + #if defined(WOLFSSL_AESNI) || defined(WOLFSSL_ARMASM) || \ + defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_AFALG_XILINX) + #if !defined(ALIGN16) + #if defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__) + #define ALIGN16 __attribute__ ( (aligned (16))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN16 __declspec (align (16)) + #else + #define ALIGN16 + #endif + #endif /* !ALIGN16 */ - /* max error buffer string size */ - enum { - WOLFSSL_MAX_ERROR_SZ = 80 - }; + #if !defined (ALIGN32) + #if defined(__IAR_SYSTEMS_ICC__) || 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 /* !ALIGN32 */ - /* stack protection */ - enum { - MIN_STACK_BUFFER = 8 - }; + #if !defined(ALIGN64) + #if defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__) + #define ALIGN64 __attribute__ ( (aligned (64))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN64 __declspec (align (64)) + #else + #define ALIGN64 + #endif + #endif /* !ALIGN64 */ + + #if defined(__IAR_SYSTEMS_ICC__) || 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(__IAR_SYSTEMS_ICC__) || 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 + #endif + #ifndef ALIGN32 + #define ALIGN32 + #endif + #ifndef ALIGN64 + #define ALIGN64 + #endif + #ifndef ALIGN128 + #define ALIGN128 + #endif + #ifndef ALIGN256 + #define ALIGN256 + #endif + #endif /* WOLFSSL_AESNI || WOLFSSL_ARMASM */ - - /* settings detection for compile vs runtime math incombatibilities */ - enum { - #if !defined(USE_FAST_MATH) && !defined(SIZEOF_LONG) && !defined(SIZEOF_LONG_LONG) - CTC_SETTINGS = 0x0 - #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8) - CTC_SETTINGS = 0x1 - #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8) - CTC_SETTINGS = 0x2 - #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 4) - CTC_SETTINGS = 0x4 - #elif defined(USE_FAST_MATH) && !defined(SIZEOF_LONG) && !defined(SIZEOF_LONG_LONG) - CTC_SETTINGS = 0x8 - #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8) - CTC_SETTINGS = 0x10 - #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8) - CTC_SETTINGS = 0x20 - #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 4) - CTC_SETTINGS = 0x40 - #else - #error "bad math long / long long settings" - #endif - }; + #ifndef TRUE + #define TRUE 1 + #endif + #ifndef FALSE + #define FALSE 0 + #endif - WOLFSSL_API word32 CheckRunTimeSettings(void); - - /* If user uses RSA, DH, DSA, or ECC math lib directly then fast math and long - types need to match at compile time and run time, CheckCtcSettings will - return 1 if a match otherwise 0 */ - #define CheckCtcSettings() (CTC_SETTINGS == CheckRunTimeSettings()) + #if defined(HAVE_STACK_SIZE) + #define EXIT_TEST(ret) return (void*)((size_t)(ret)) + #else + #define EXIT_TEST(ret) return ret + #endif - #ifdef __cplusplus - } /* extern "C" */ - #endif + #if (defined(__IAR_SYSTEMS_ICC__) && (__IAR_SYSTEMS_ICC__ > 8)) || \ + defined(__GNUC__) + #define WOLFSSL_PACK __attribute__ ((packed)) + #else + #define WOLFSSL_PACK + #endif + + #ifndef __GNUC_PREREQ + #if defined(__GNUC__) && defined(__GNUC_MINOR__) + #define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) + #else + #define __GNUC_PREREQ(maj, min) (0) /* not GNUC */ + #endif + #endif + + #if defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__) + #define WC_NORETURN __attribute__((noreturn)) + #else + #define WC_NORETURN + #endif + + #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ + defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \ + defined(WOLFSSL_PUBLIC_MP) || defined(OPENSSL_EXTRA) || \ + (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)) + #undef WC_MP_TO_RADIX + #define WC_MP_TO_RADIX + #endif + + #ifdef __cplusplus + } /* extern "C" */ + #endif #endif /* WOLF_CRYPT_TYPES_H */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/visibility.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/visibility.h index 6e41d238f..8ed57fb95 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/visibility.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/visibility.h @@ -1,8 +1,8 @@ /* visibility.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,9 +16,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + /* Visibility control macros */ #ifndef WOLF_CRYPT_VISIBILITY_H @@ -26,7 +27,10 @@ /* for compatibility and so that fips is using same name of macro @wc_fips */ -#ifdef HAVE_FIPS +/* The following visibility wrappers are for old FIPS. New FIPS should use + * the same as a non-FIPS build. */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) #include #define WOLFSSL_API CYASSL_API #define WOLFSSL_LOCAL CYASSL_LOCAL @@ -39,26 +43,26 @@ */ #if defined(BUILDING_WOLFSSL) - #if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY - #define WOLFSSL_API __attribute__ ((visibility("default"))) - #define WOLFSSL_LOCAL __attribute__ ((visibility("hidden"))) - #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) - #define WOLFSSL_API __global - #define WOLFSSL_LOCAL __hidden - #elif defined(_MSC_VER) - #ifdef WOLFSSL_DLL + #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) + #if defined(WOLFSSL_DLL) #define WOLFSSL_API __declspec(dllexport) #else #define WOLFSSL_API #endif #define WOLFSSL_LOCAL + #elif defined(HAVE_VISIBILITY) && HAVE_VISIBILITY + #define WOLFSSL_API __attribute__ ((visibility("default"))) + #define WOLFSSL_LOCAL __attribute__ ((visibility("hidden"))) + #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) + #define WOLFSSL_API __global + #define WOLFSSL_LOCAL __hidden #else #define WOLFSSL_API #define WOLFSSL_LOCAL #endif /* HAVE_VISIBILITY */ #else /* BUILDING_WOLFSSL */ - #if defined(_MSC_VER) - #ifdef WOLFSSL_DLL + #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) + #if defined(WOLFSSL_DLL) #define WOLFSSL_API __declspec(dllimport) #else #define WOLFSSL_API diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wc_encrypt.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wc_encrypt.h new file mode 100644 index 000000000..6d26e2cba --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wc_encrypt.h @@ -0,0 +1,101 @@ +/* wc_encrypt.h + * + * Copyright (C) 2006-2020 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 + */ + +/*! + \file wolfssl/wolfcrypt/wc_encrypt.h +*/ + + +#ifndef WOLF_CRYPT_ENCRYPT_H +#define WOLF_CRYPT_ENCRYPT_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* determine max cipher key size */ +#ifndef NO_AES + #define WC_MAX_SYM_KEY_SIZE (AES_MAX_KEY_SIZE/8) +#elif defined(HAVE_CHACHA) + #define WC_MAX_SYM_KEY_SIZE CHACHA_MAX_KEY_SZ +#elif !defined(NO_DES3) + #define WC_MAX_SYM_KEY_SIZE DES3_KEY_SIZE +#elif !defined(NO_RC4) + #define WC_MAX_SYM_KEY_SIZE RC4_KEY_SIZE +#else + #define WC_MAX_SYM_KEY_SIZE 32 +#endif + + +#if !defined(NO_AES) && defined(HAVE_AES_CBC) +WOLFSSL_API int wc_AesCbcEncryptWithKey(byte* out, const byte* in, word32 inSz, + const byte* key, word32 keySz, + const byte* iv); +WOLFSSL_API int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, + const byte* key, word32 keySz, + const byte* iv); +#endif /* !NO_AES */ + + +#ifndef NO_DES3 +WOLFSSL_API int wc_Des_CbcDecryptWithKey(byte* out, + const byte* in, word32 sz, + const byte* key, const byte* iv); +WOLFSSL_API int wc_Des_CbcEncryptWithKey(byte* out, + const byte* in, word32 sz, + const byte* key, const byte* iv); +WOLFSSL_API int wc_Des3_CbcEncryptWithKey(byte* out, + const byte* in, word32 sz, + const byte* key, const byte* iv); +WOLFSSL_API int wc_Des3_CbcDecryptWithKey(byte* out, + const byte* in, word32 sz, + const byte* key, const byte* iv); +#endif /* !NO_DES3 */ + + + + +#ifdef WOLFSSL_ENCRYPTED_KEYS + struct EncryptedInfo; + WOLFSSL_API int wc_BufferKeyDecrypt(struct EncryptedInfo* info, byte* der, word32 derSz, + const byte* password, int passwordSz, int hashType); + WOLFSSL_API int wc_BufferKeyEncrypt(struct EncryptedInfo* info, byte* der, word32 derSz, + const byte* password, int passwordSz, int hashType); +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + +#ifndef NO_PWDBASED + WOLFSSL_LOCAL int wc_CryptKey(const char* password, int passwordSz, + byte* salt, int saltSz, int iterations, int id, byte* input, int length, + int version, byte* cbcIv, int enc, int shaOid); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_ENCRYPT_H */ + diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wc_pkcs11.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wc_pkcs11.h new file mode 100644 index 000000000..d8dfae5a8 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wc_pkcs11.h @@ -0,0 +1,94 @@ +/* wc_pkcs11.h + * + * Copyright (C) 2006-2020 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 3 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 _WOLFPKCS11_H_ +#define _WOLFPKCS11_H_ + +#include + +#ifdef HAVE_PKCS11 + +#ifndef WOLF_CRYPTO_CB + #error PKCS11 support requires ./configure --enable-cryptocb or WOLF_CRYPTO_CB to be defined +#endif + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + +typedef struct Pkcs11Dev { + void* dlHandle; /* Handle to library */ + CK_FUNCTION_LIST* func; /* Array of functions */ + void* heap; +} Pkcs11Dev; + +typedef struct Pkcs11Token { + CK_FUNCTION_LIST* func; /* Table of PKCS#11 function from lib */ + CK_SLOT_ID slotId; /* Id of slot to use */ + CK_SESSION_HANDLE handle; /* Handle to active session */ + CK_UTF8CHAR_PTR userPin; /* User's PIN to login with */ + CK_ULONG userPinSz; /* Size of user's PIN in bytes */ +} Pkcs11Token; + +typedef struct Pkcs11Session { + CK_FUNCTION_LIST* func; /* Table of PKCS#11 function from lib */ + CK_SLOT_ID slotId; /* Id of slot to use */ + CK_SESSION_HANDLE handle; /* Handle to active session */ +} Pkcs11Session; + +/* Types of keys that can be stored. */ +enum Pkcs11KeyType { + PKCS11_KEY_TYPE_AES_GCM, + PKCS11_KEY_TYPE_AES_CBC, + PKCS11_KEY_TYPE_HMAC, + PKCS11_KEY_TYPE_RSA, + PKCS11_KEY_TYPE_EC, +}; + + +WOLFSSL_API int wc_Pkcs11_Initialize(Pkcs11Dev* dev, const char* library, + void* heap); +WOLFSSL_API void wc_Pkcs11_Finalize(Pkcs11Dev* dev); + +WOLFSSL_API int wc_Pkcs11Token_Init(Pkcs11Token* token, Pkcs11Dev* dev, + int slotId, const char* tokenName, const unsigned char *userPin, + int userPinSz); +WOLFSSL_API void wc_Pkcs11Token_Final(Pkcs11Token* token); +WOLFSSL_API int wc_Pkcs11Token_Open(Pkcs11Token* token, int readWrite); +WOLFSSL_API void wc_Pkcs11Token_Close(Pkcs11Token* token); + +WOLFSSL_API int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, + void* key); + +WOLFSSL_API int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, + void* ctx); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_PKCS11 */ + +#endif /* _WOLFPKCS11_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wc_port.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wc_port.h index c13f394f6..88c7bfe34 100644 --- a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wc_port.h +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wc_port.h @@ -1,8 +1,8 @@ /* wc_port.h * - * Copyright (C) 2006-2015 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * - * This file is part of wolfSSL. (formerly known as CyaSSL) + * 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 @@ -16,20 +16,46 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/*! + \file wolfssl/wolfcrypt/wc_port.h +*/ #ifndef WOLF_CRYPT_PORT_H #define WOLF_CRYPT_PORT_H -#include +#include +#include #ifdef __cplusplus extern "C" { #endif +/* Detect if compiler supports C99. "NO_WOLF_C99" can be defined in + * user_settings.h to disable checking for C99 support. */ +#if !defined(WOLF_C99) && defined(__STDC_VERSION__) && \ + !defined(WOLFSSL_ARDUINO) && !defined(NO_WOLF_C99) + #if __STDC_VERSION__ >= 199901L + #define WOLF_C99 + #endif +#endif + +/* GENERIC INCLUDE SECTION */ +#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #include + #if (defined(MQX_USE_IO_OLD) && MQX_USE_IO_OLD) || \ + defined(FREESCALE_MQX_5_0) + #include + #else + #include + #endif +#endif + + +/* THREADING/MUTEX SECTION */ #ifdef USE_WINDOWS_API #ifdef WOLFSSL_GAME_BUILD #include "system/xtl.h" @@ -37,27 +63,47 @@ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif - #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 #elif defined(THREADX) #ifndef SINGLE_THREADED - #include "tx_api.h" + #ifdef NEED_THREADX_TYPES + #include + #endif + #include #endif +#elif defined(WOLFSSL_DEOS) + #include "mutexapi.h" #elif defined(MICRIUM) /* do nothing, just don't pick Unix */ -#elif defined(FREERTOS) || defined(WOLFSSL_SAFERTOS) +#elif defined(FREERTOS) || defined(FREERTOS_TCP) || defined(WOLFSSL_SAFERTOS) /* do nothing */ #elif defined(EBSNET) /* do nothing */ -#elif defined(FREESCALE_MQX) +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) /* do nothing */ +#elif defined(FREESCALE_FREE_RTOS) + #include "fsl_os_abstraction.h" +#elif defined(WOLFSSL_VXWORKS) + #include +#elif defined(WOLFSSL_uITRON4) + #include "stddef.h" + #include "kernel.h" +#elif defined(WOLFSSL_uTKERNEL2) + #include "tk/tkernel.h" +#elif defined(WOLFSSL_CMSIS_RTOS) + #include "cmsis_os.h" +#elif defined(WOLFSSL_CMSIS_RTOSv2) + #include "cmsis_os2.h" #elif defined(WOLFSSL_MDK_ARM) #if defined(WOLFSSL_MDK5) - #include "cmsis_os.h" + #include "cmsis_os.h" #else #include #endif @@ -66,23 +112,77 @@ #elif defined(WOLFSSL_TIRTOS) #include #include +#elif defined(WOLFSSL_FROSTED) + #include +#elif defined(INTIME_RTOS) + #include + #include +#elif defined(WOLFSSL_NUCLEUS_1_2) + /* NU_DEBUG needed struct access in nucleus_realloc */ + #define NU_DEBUG + #include "plus/nucleus.h" + #include "nucleus.h" +#elif defined(WOLFSSL_APACHE_MYNEWT) + /* do nothing */ +#elif defined(WOLFSSL_ZEPHYR) + #ifndef SINGLE_THREADED + #include + #endif +#elif defined(WOLFSSL_TELIT_M2MB) + + /* Telit SDK uses C++ compile option (--cpp), which causes link issue + to API's if wrapped in extern "C" */ + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #include "m2mb_types.h" + #include "m2mb_os_types.h" + #include "m2mb_os_api.h" + #include "m2mb_os.h" + #include "m2mb_os_mtx.h" + #ifndef NO_ASN_TIME + #include "m2mb_rtc.h" + #endif + #ifndef NO_FILESYSTEM + #include "m2mb_fs_posix.h" + #endif + + #undef kB /* eliminate conflict in asn.h */ + + #ifdef __cplusplus + extern "C" { + #endif + #else #ifndef SINGLE_THREADED #define WOLFSSL_PTHREADS #include #endif - #if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS) + #if (defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)) && \ + !defined(NO_FILESYSTEM) #include /* for close of BIO */ #endif #endif +/* For FIPS keep the function names the same */ +#ifdef HAVE_FIPS +#define wc_InitMutex InitMutex +#define wc_FreeMutex FreeMutex +#define wc_LockMutex LockMutex +#define wc_UnLockMutex UnLockMutex +#endif /* HAVE_FIPS */ #ifdef SINGLE_THREADED typedef int wolfSSL_Mutex; #else /* MULTI_THREADED */ /* FREERTOS comes first to enable use of FreeRTOS Windows simulator only */ - #ifdef FREERTOS + #if defined(FREERTOS) typedef xSemaphoreHandle wolfSSL_Mutex; + #elif defined(FREERTOS_TCP) + #include "FreeRTOS.h" + #include "semphr.h" + typedef SemaphoreHandle_t wolfSSL_Mutex; #elif defined(WOLFSSL_SAFERTOS) typedef struct wolfSSL_Mutex { signed char mutexBuffer[portQUEUE_OVERHEAD_BYTES]; @@ -94,12 +194,28 @@ typedef pthread_mutex_t wolfSSL_Mutex; #elif defined(THREADX) typedef TX_MUTEX wolfSSL_Mutex; + #elif defined(WOLFSSL_DEOS) + typedef mutex_handle_t wolfSSL_Mutex; #elif defined(MICRIUM) typedef OS_MUTEX wolfSSL_Mutex; #elif defined(EBSNET) typedef RTP_MUTEX wolfSSL_Mutex; - #elif defined(FREESCALE_MQX) + #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) typedef MUTEX_STRUCT wolfSSL_Mutex; + #elif defined(FREESCALE_FREE_RTOS) + typedef mutex_t wolfSSL_Mutex; + #elif defined(WOLFSSL_VXWORKS) + typedef SEM_ID wolfSSL_Mutex; + #elif defined(WOLFSSL_uITRON4) + typedef struct wolfSSL_Mutex { + T_CSEM sem ; + ID id ; + } wolfSSL_Mutex; + #elif defined(WOLFSSL_uTKERNEL2) + typedef struct wolfSSL_Mutex { + T_CSEM sem ; + ID id ; + } wolfSSL_Mutex; #elif defined(WOLFSSL_MDK_ARM) #if defined(WOLFSSL_CMSIS_RTOS) typedef osMutexId wolfSSL_Mutex; @@ -108,26 +224,85 @@ #endif #elif defined(WOLFSSL_CMSIS_RTOS) typedef osMutexId wolfSSL_Mutex; + #elif defined(WOLFSSL_CMSIS_RTOSv2) + typedef osMutexId_t wolfSSL_Mutex; #elif defined(WOLFSSL_TIRTOS) 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; + #elif defined(WOLFSSL_NUCLEUS_1_2) + typedef NU_SEMAPHORE wolfSSL_Mutex; + #elif defined(WOLFSSL_ZEPHYR) + typedef struct k_mutex wolfSSL_Mutex; + #elif defined(WOLFSSL_TELIT_M2MB) + typedef M2MB_OS_MTX_HANDLE wolfSSL_Mutex; #else #error Need a mutex type in multithreaded mode #endif /* USE_WINDOWS_API */ #endif /* SINGLE_THREADED */ -WOLFSSL_LOCAL int InitMutex(wolfSSL_Mutex*); -WOLFSSL_LOCAL int FreeMutex(wolfSSL_Mutex*); -WOLFSSL_LOCAL int LockMutex(wolfSSL_Mutex*); -WOLFSSL_LOCAL int UnLockMutex(wolfSSL_Mutex*); +/* Enable crypt HW mutex for Freescale MMCAU, PIC32MZ or STM32 */ +#if defined(FREESCALE_MMCAU) || defined(WOLFSSL_MICROCHIP_PIC32MZ) || \ + defined(STM32_CRYPTO) + #ifndef WOLFSSL_CRYPT_HW_MUTEX + #define WOLFSSL_CRYPT_HW_MUTEX 1 + #endif +#endif /* FREESCALE_MMCAU */ + +#ifndef WOLFSSL_CRYPT_HW_MUTEX + #define WOLFSSL_CRYPT_HW_MUTEX 0 +#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 + the same time. */ + int wolfSSL_CryptHwMutexInit(void); + int wolfSSL_CryptHwMutexLock(void); + int wolfSSL_CryptHwMutexUnLock(void); +#else + /* Define stubs, since HW mutex is disabled */ + #define wolfSSL_CryptHwMutexInit() 0 /* Success */ + #define wolfSSL_CryptHwMutexLock() 0 /* Success */ + #define wolfSSL_CryptHwMutexUnLock() (void)0 /* Success */ +#endif /* WOLFSSL_CRYPT_HW_MUTEX */ + +/* Mutex functions */ +WOLFSSL_API int wc_InitMutex(wolfSSL_Mutex*); +WOLFSSL_API wolfSSL_Mutex* wc_InitAndAllocMutex(void); +WOLFSSL_API int wc_FreeMutex(wolfSSL_Mutex*); +WOLFSSL_API int wc_LockMutex(wolfSSL_Mutex*); +WOLFSSL_API int wc_UnLockMutex(wolfSSL_Mutex*); +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +/* dynamically set which mutex to use. unlock / lock is controlled by flag */ +typedef void (mutex_cb)(int flag, int type, const char* file, int line); + +WOLFSSL_API int wc_LockMutex_ex(int flag, int type, const char* file, int line); +WOLFSSL_API int wc_SetMutexCb(mutex_cb* cb); +#endif + +/* main crypto initialization function */ +WOLFSSL_API int wolfCrypt_Init(void); +WOLFSSL_API int wolfCrypt_Cleanup(void); +/* FILESYSTEM SECTION */ /* filesystem abstraction layer, used by ssl.c */ #ifndef NO_FILESYSTEM #if defined(EBSNET) + #include "vfapi.h" + #include "vfile.h" + + int ebsnet_fseek(int a, long b, int c); /* Not prototyped in vfile.h per + * EBSnet feedback */ + #define XFILE int #define XFOPEN(NAME, MODE) vf_open((const char *)NAME, VO_RDONLY, 0); - #define XFSEEK vf_lseek + #define XFSEEK ebsnet_fseek #define XFTELL vf_tell #define XREWIND vf_rewind #define XFREAD(BUF, SZ, AMT, FD) vf_read(FD, BUF, SZ*AMT) @@ -135,6 +310,7 @@ WOLFSSL_LOCAL int UnLockMutex(wolfSSL_Mutex*); #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* @@ -147,7 +323,8 @@ WOLFSSL_LOCAL int UnLockMutex(wolfSSL_Mutex*); #define XFCLOSE fs_close #define XSEEK_END 0 #define XBADFILE NULL -#elif defined(FREESCALE_MQX) + #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 #define XFSEEK fseek @@ -158,8 +335,14 @@ WOLFSSL_LOCAL int UnLockMutex(wolfSSL_Mutex*); #define XFCLOSE fclose #define XSEEK_END IO_SEEK_END #define XBADFILE NULL + #define XFGETS fgets +#elif defined(WOLFSSL_DEOS) + #define NO_FILESYSTEM + #warning "TODO - DDC-I Certifiable Fast File System for Deos is not integrated" + //#define XFILE bfd * + #elif defined(MICRIUM) - #include + #include #define XFILE FS_FILE* #define XFOPEN fs_fopen #define XFSEEK fs_fseek @@ -170,11 +353,74 @@ WOLFSSL_LOCAL int UnLockMutex(wolfSSL_Mutex*); #define XFCLOSE fs_fclose #define XSEEK_END FS_SEEK_END #define XBADFILE NULL + #define XFGETS(b,s,f) -2 /* Not ported yet */ +#elif defined(WOLFSSL_NUCLEUS_1_2) + #include "fal/inc/fal.h" + #define XFILE FILE* + #define XFOPEN fopen + #define XFSEEK fseek + #define XFTELL ftell + #define XREWIND rewind + #define XFREAD fread + #define XFWRITE fwrite + #define XFCLOSE fclose + #define XSEEK_END PSEEK_END + #define XBADFILE NULL +#elif defined(WOLFSSL_APACHE_MYNEWT) + #include + #define XFILE struct fs_file* + + #define XFOPEN mynewt_fopen + #define XFSEEK mynewt_fseek + #define XFTELL mynewt_ftell + #define XREWIND mynewt_rewind + #define XFREAD mynewt_fread + #define XFWRITE mynewt_fwrite + #define XFCLOSE mynewt_fclose + #define XSEEK_END 2 + #define XBADFILE NULL + #define XFGETS(b,s,f) -2 /* Not ported yet */ +#elif defined(WOLFSSL_ZEPHYR) + #include + + #define XFILE struct fs_file_t* + #define STAT struct fs_dirent + + XFILE z_fs_open(const char* filename, const char* perm); + int z_fs_close(XFILE file); + + #define XFOPEN z_fs_open + #define XFCLOSE z_fs_close + #define XFSEEK fs_seek + #define XFTELL fs_tell + #define XFREWIND fs_rewind + #define XREWIND(F) fs_seek(F, 0, FS_SEEK_SET) + #define XFREAD(P,S,N,F) fs_read(F, P, S*N) + #define XFWRITE(P,S,N,F) fs_write(F, P, S*N) + #define XSEEK_END FS_SEEK_END + #define XBADFILE NULL + #define XFGETS(b,s,f) -2 /* Not ported yet */ + +#elif defined(WOLFSSL_TELIT_M2MB) + #define XFILE INT32 + #define XFOPEN(NAME, MODE) m2mb_fs_open((NAME), 0, (MODE)) + #define XFSEEK(F, O, W) m2mb_fs_lseek((F), (O), (W)) + #define XFTELL(F) m2mb_fs_lseek((F), 0, M2MB_SEEK_END) + #define XREWIND(F) (void)F + #define XFREAD(BUF, SZ, AMT, F) m2mb_fs_read((F), (BUF), (SZ)*(AMT)) + #define XFWRITE(BUF, SZ, AMT, F) m2mb_fs_write((F), (BUF), (SZ)*(AMT)) + #define XFCLOSE m2mb_fs_close + #define XSEEK_END M2MB_SEEK_END + #define XBADFILE -1 + #define XFGETS(b,s,f) -2 /* Not ported yet */ + +#elif defined(WOLFSSL_USER_FILESYSTEM) + /* To be defined in user_settings.h */ #else /* stdio, default case */ + #include #define XFILE FILE* #if defined(WOLFSSL_MDK_ARM) - #include extern FILE * wolfSSL_fopen(const char *name, const char *mode) ; #define XFOPEN wolfSSL_fopen #else @@ -188,20 +434,347 @@ WOLFSSL_LOCAL int UnLockMutex(wolfSSL_Mutex*); #define XFCLOSE fclose #define XSEEK_END SEEK_END #define XBADFILE NULL + #define XFGETS fgets + + #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\ + && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) + #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) && !defined(WOLFSSL_NUCLEUS) && \ + !defined(WOLFSSL_NUCLEUS_1_2) + typedef struct ReadDirCtx { + #ifdef USE_WINDOWS_API + WIN32_FIND_DATAA FindFileData; + HANDLE hFind; + #elif defined(WOLFSSL_ZEPHYR) + struct fs_dirent entry; + struct fs_dir_t dir; + struct fs_dirent s; + struct fs_dir_t* dirp; + + #elif defined(WOLFSSL_TELIT_M2MB) + M2MB_DIR_T* dir; + struct M2MB_DIRENT* entry; + struct M2MB_STAT s; + #else + struct dirent* entry; + DIR* dir; + struct stat s; + #endif + char name[MAX_FILENAME_SZ]; + } ReadDirCtx; + + #define WC_READDIR_NOFILE -1 + + 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 */ +/* MIN/MAX MACRO SECTION */ /* Windows API defines its own min() macro. */ -#if defined(USE_WINDOWS_API) && defined(min) - #define WOLFSSL_HAVE_MIN +#if defined(USE_WINDOWS_API) + #if defined(min) || defined(WOLFSSL_MYSQL_COMPATIBLE) + #define WOLFSSL_HAVE_MIN + #endif /* min */ + #if defined(max) || defined(WOLFSSL_MYSQL_COMPATIBLE) + #define WOLFSSL_HAVE_MAX + #endif /* max */ +#endif /* USE_WINDOWS_API */ + + +/* TIME SECTION */ +/* 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 + #ifndef HAVE_TM_TYPE + #define USE_WOLF_TM + #endif + #ifndef HAVE_TIME_T_TYPE + #define USE_WOLF_TIME_T + #endif + +#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(WOLFSSL_XILINX) + #define USER_TIME + #include + +#elif defined(HAVE_RTP_SYS) + #include "os.h" /* dc_rtc_api needs */ + #include "dc_rtc_api.h" /* to get current time */ + + /* uses parital structures */ + #define XTIME(tl) (0) + #define XGMTIME(c, t) rtpsys_gmtime((c)) + +#elif defined(WOLFSSL_DEOS) + #define XTIME(t1) deos_time((t1)) + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + #define USE_WOLF_TIME_T + +#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) + #ifdef FREESCALE_MQX_4_0 + #include + extern time_t mqx_time(time_t* timer); + #else + #define HAVE_GMTIME_R + #endif + #define XTIME(t1) mqx_time((t1)) + +#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) && defined(WOLFSSL_ATMEL_TIME) + #define XTIME(t1) atmel_get_curr_time_and_date((t1)) + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + #define USE_WOLF_TIME_T + +#elif defined(WOLFSSL_WICED) + #include + time_t wiced_pseudo_unix_epoch_time(time_t * timer); + #define XTIME(t1) wiced_pseudo_unix_epoch_time((t1)) + #define HAVE_GMTIME_R + +#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 + +#elif defined(WOLFSSL_APACHE_MYNEWT) + #include "os/os_time.h" + #define XTIME(t1) mynewt_time((t1)) + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + #define USE_WOLF_TIME_T + +#elif defined(WOLFSSL_ZEPHYR) + #ifndef _POSIX_C_SOURCE + #include + #else + #include + #endif + + typedef signed int time_t; + + time_t z_time(time_t *timer); + + #define XTIME(tl) z_time((tl)) + #define XGMTIME(c, t) gmtime((c)) + #define WOLFSSL_GMTIME + + #define USE_WOLF_TM + +#elif defined(WOLFSSL_TELIT_M2MB) + typedef long time_t; + extern time_t m2mb_xtime(time_t * timer); + #define XTIME(tl) m2mb_xtime((tl)) + #ifdef WOLFSSL_TLS13 + extern time_t m2mb_xtime_ms(time_t * timer); + #define XTIME_MS(tl) m2mb_xtime_ms((tl)) + #endif + #ifndef NO_CRYPT_BENCHMARK + extern double m2mb_xtime_bench(int reset); + #define WOLFSSL_CURRTIME_REMAP m2mb_xtime_bench + #endif + #define XGMTIME(c, t) gmtime((c)) + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + +#else + /* default */ + /* uses complete facility */ + #include + #if defined(HAVE_SYS_TIME_H) + #include + #endif + + /* PowerPC time_t is int */ + #ifdef __PPC__ + #define TIME_T_NOT_64BIT + #endif #endif +#ifdef SIZEOF_TIME_T + /* check if size of time_t from autoconf is less than 8 bytes (64bits) */ + #if SIZEOF_TIME_T < 8 + #undef TIME_T_NOT_64BIT + #define TIME_T_NOT_64BIT + #endif +#endif +#ifdef TIME_T_NOT_LONG + /* one old reference to TIME_T_NOT_LONG in GCC-ARM example README + * this keeps support for the old macro name */ + #undef TIME_T_NOT_64BIT + #define TIME_T_NOT_64BIT +#endif + +/* Map default time functions */ +#if !defined(XTIME) && !defined(TIME_OVERRIDES) && !defined(USER_TIME) + #ifdef TEST_BEFORE_DATE + #define XTIME(tl) (946681200UL) /* Jan 1, 2000 */ + #else + #define XTIME(tl) time((tl)) + #endif +#endif +#if !defined(XGMTIME) && !defined(TIME_OVERRIDES) + #if defined(WOLFSSL_GMTIME) || !defined(HAVE_GMTIME_R) || defined(WOLF_C99) + #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 +#if defined(USE_WOLF_SUSECONDS_T) + typedef long suseconds_t; +#endif +#if defined(USE_WOLF_TIMEVAL_T) + struct timeval + { + time_t tv_sec; + suseconds_t tv_usec; + }; +#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 */ + + +#ifndef WOLFSSL_LEANPSK + char* mystrnstr(const char* s1, const char* s2, unsigned int n); +#endif + +#ifndef FILE_BUFFER_SIZE + #define FILE_BUFFER_SIZE 1024 /* default static file buffer size for input, + will use dynamic buffer if not big enough */ +#endif + +#ifdef HAVE_CAVIUM_OCTEON_SYNC + /* By default, the OCTEON's global variables are all thread local. This + * tag allows them to be shared between threads. */ + #include "cvmx-platform.h" + #define WOLFSSL_GLOBAL CVMX_SHARED +#else + #define WOLFSSL_GLOBAL +#endif + +#ifdef WOLFSSL_DSP + #include "wolfssl_dsp.h" + + /* callbacks for setting handle */ + typedef int (*wolfSSL_DSP_Handle_cb)(remote_handle64 *handle, int finished, + void *ctx); + WOLFSSL_API int wolfSSL_GetHandleCbSet(); + WOLFSSL_API int wolfSSL_SetHandleCb(wolfSSL_DSP_Handle_cb in); + WOLFSSL_LOCAL int wolfSSL_InitHandle(); + WOLFSSL_LOCAL void wolfSSL_CleanupHandle(); +#endif + +#ifdef WOLFSSL_SCE + #ifndef WOLFSSL_SCE_GSCE_HANDLE + #define WOLFSSL_SCE_GSCE_HANDLE g_sce + #endif +#endif #ifdef __cplusplus } /* extern "C" */ #endif #endif /* WOLF_CRYPT_PORT_H */ - diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wolfevent.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wolfevent.h new file mode 100644 index 000000000..8370d5e45 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wolfevent.h @@ -0,0 +1,120 @@ +/* wolfevent.h + * + * Copyright (C) 2006-2020 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_EVENT_H_ +#define _WOLF_EVENT_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef SINGLE_THREADED + #include +#endif + +typedef struct WOLF_EVENT WOLF_EVENT; +typedef unsigned short WOLF_EVENT_FLAG; + +typedef enum WOLF_EVENT_TYPE { + WOLF_EVENT_TYPE_NONE, +#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; + #ifdef WOLFSSL_NITROX_DEBUG + word32 pendCount; + #endif +#endif +#ifndef WC_NO_ASYNC_THREADING + pthread_t threadId; +#endif + int ret; /* Async return code */ + unsigned int flags; + WOLF_EVENT_TYPE type; + WOLF_EVENT_STATE state; +}; + +enum WOLF_POLL_FLAGS { + WOLF_POLL_FLAG_CHECK_HW = 0x01, +}; + +typedef struct { + WOLF_EVENT* head; /* head of queue */ + WOLF_EVENT* tail; /* tail of queue */ +#ifndef SINGLE_THREADED + wolfSSL_Mutex lock; /* queue lock */ +#endif + int count; +} WOLF_EVENT_QUEUE; + + +#ifdef HAVE_WOLF_EVENT + +/* Event */ +WOLFSSL_API int wolfEvent_Init(WOLF_EVENT* event, WOLF_EVENT_TYPE type, void* context); +WOLFSSL_API int wolfEvent_Poll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags); + +/* Event Queue */ +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_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 */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* _WOLF_EVENT_H_ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wolfmath.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wolfmath.h new file mode 100644 index 000000000..43b73c44d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfcrypt/wolfmath.h @@ -0,0 +1,97 @@ +/* wolfmath.h + * + * Copyright (C) 2006-2020 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 __WOLFMATH_H__ +#define __WOLFMATH_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef WOLFSSL_PUBLIC_MP + #define MP_API WOLFSSL_API +#else + #define MP_API WOLFSSL_LOCAL +#endif + +#ifndef MIN + #define MIN(x,y) ((x)<(y)?(x):(y)) +#endif + +#ifndef MAX + #define MAX(x,y) ((x)>(y)?(x):(y)) +#endif + +/* timing resistance array */ +#if !defined(WC_NO_CACHE_RESISTANT) && \ + ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \ + (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT))) + + extern const wolfssl_word wc_off_on_addr[2]; +#endif + + +/* common math functions */ +MP_API int get_digit_count(mp_int* a); +MP_API mp_digit get_digit(mp_int* a, int n); +MP_API int get_rand_digit(WC_RNG* rng, mp_digit* d); + +WOLFSSL_API int mp_cond_copy(mp_int* a, int copy, mp_int* b); +WOLFSSL_API int mp_rand(mp_int* a, int digits, WC_RNG* rng); + +enum { + /* format type */ + WC_TYPE_HEX_STR = 1, + WC_TYPE_UNSIGNED_BIN = 2, +}; + +WOLFSSL_API int wc_export_int(mp_int* mp, byte* buf, word32* len, + word32 keySz, int encType); + +#ifdef HAVE_WOLF_BIGINT + #if !defined(WOLF_BIGINT_DEFINED) + /* raw big integer */ + typedef struct WC_BIGINT { + byte* buf; + word32 len; + void* heap; + } WC_BIGINT; + #define WOLF_BIGINT_DEFINED + #endif + + WOLFSSL_LOCAL void wc_bigint_init(WC_BIGINT* a); + WOLFSSL_LOCAL int wc_bigint_alloc(WC_BIGINT* a, word32 sz); + WOLFSSL_LOCAL int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen); + WOLFSSL_LOCAL int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen); + WOLFSSL_LOCAL void wc_bigint_zero(WC_BIGINT* a); + WOLFSSL_LOCAL void wc_bigint_free(WC_BIGINT* a); + + WOLFSSL_LOCAL int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst); + WOLFSSL_LOCAL int wc_mp_to_bigint_sz(mp_int* src, WC_BIGINT* dst, word32 sz); + WOLFSSL_LOCAL int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst); +#endif /* HAVE_WOLF_BIGINT */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* __WOLFMATH_H__ */ diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfio.h b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfio.h new file mode 100644 index 000000000..7e97accce --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl/wolfio.h @@ -0,0 +1,600 @@ +/* io.h + * + * Copyright (C) 2006-2020 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 + */ + +/*! + \file wolfssl/wolfio.h +*/ + +#ifndef WOLFSSL_IO_H +#define WOLFSSL_IO_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Micrium uses NetSock I/O callbacks in wolfio.c */ +#if !defined(WOLFSSL_USER_IO) + /* 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 +#endif + +#if !defined(WOLFSSL_USER_IO) + /* Micrium uses NetSock I/O callbacks in wolfio.c */ + #if !defined(USE_WOLFSSL_IO) && !defined(MICRIUM) && \ + !defined(WOLFSSL_CONTIKI) && !defined(WOLFSSL_NO_SOCK) + #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 + #if defined(WOLFSSL_LWIP) && !defined(WOLFSSL_APACHE_MYNEWT) + /* 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" + #ifndef LWIP_PROVIDE_ERRNO + #include + #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)) + #include "rl_net.h" + #include "errno.h" + #elif defined(WOLFSSL_CMSIS_RTOS) + #include "cmsis_os.h" + #elif defined(WOLFSSL_CMSIS_RTOSv2) + #include "cmsis_os2.h" + #elif defined(WOLFSSL_TIRTOS) + #include + #elif defined(FREERTOS_TCP) + #include "FreeRTOS_Sockets.h" + #elif defined(WOLFSSL_IAR_ARM) + /* nothing */ + #elif defined(HAVE_NETX_BSD) + #ifdef NETX_DUO + #include "nxd_bsd.h" + #else + #include "nx_bsd.h" + #endif + #elif defined(WOLFSSL_VXWORKS) + #include + #include + #elif defined(WOLFSSL_NUCLEUS_1_2) + #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_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + #include + #elif defined(WOLFSSL_DEOS) + #include + #include + #include + #elif defined(WOLFSSL_ZEPHYR) + #include + #elif defined(HAVE_NETX) + #include "nx_api.h" + #include "errno.h" + #elif !defined(WOLFSSL_NO_SOCK) + #include + #include + #ifndef EBSNET + #include + #endif + #include + #define XFCNTL(fd, flag, block) fcntl((fd), (flag), (block)) + + #if defined(HAVE_RTP_SYS) + #include + #elif defined(EBSNET) + #include "rtipapi.h" /* errno */ + #include "socket.h" + #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) \ + && !defined(WOLFSSL_CONTIKI) && !defined(WOLFSSL_WICED) \ + && !defined(WOLFSSL_GNRC) && !defined(WOLFSSL_RIOT_OS) + #include + #include + #include + #include + #ifdef __PPU + #include + #else + #include + #endif + #endif + #endif + + #if defined(WOLFSSL_RENESAS_RA6M3G) /* Uses FREERTOS_TCP */ + #include + #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 +#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) + #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 +#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 +#elif defined(WOLFSSL_NUCLEUS_1_2) + #define SOCKET_EWOULDBLOCK NU_WOULD_BLOCK + #define SOCKET_EAGAIN NU_WOULD_BLOCK + #define SOCKET_ECONNRESET NU_NOT_CONNECTED + #define SOCKET_EINTR NU_NOT_CONNECTED + #define SOCKET_EPIPE NU_NOT_CONNECTED + #define SOCKET_ECONNREFUSED NU_CONNECTION_REFUSED + #define SOCKET_ECONNABORTED NU_NOT_CONNECTED +#elif defined(WOLFSSL_DEOS) + #define SOCKET_EWOULDBLOCK EAGAIN + #define SOCKET_EAGAIN EAGAIN + #define SOCKET_ECONNRESET EINTR + #define SOCKET_EINTR EINTR + #define SOCKET_EPIPE EPIPE + #define SOCKET_ECONNREFUSED SOCKET_ERROR + #define SOCKET_ECONNABORTED SOCKET_ERROR +#elif defined(HAVE_NETX) + #define SOCKET_EWOULDBLOCK NX_NOT_CONNECTED + #define SOCKET_EAGAIN NX_NOT_CONNECTED + #define SOCKET_ECONNRESET NX_NOT_CONNECTED + #define SOCKET_EINTR NX_NOT_CONNECTED + #define SOCKET_EPIPE NX_NOT_CONNECTED + #define SOCKET_ECONNREFUSED NX_NOT_CONNECTED + #define SOCKET_ECONNABORTED NX_NOT_CONNECTED +#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) && !defined(WOLFSSL_APACHE_MYNEWT) + #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 +#elif defined(WOLFSSL_NUCLEUS_1_2) + #define SEND_FUNCTION NU_Send + #define RECV_FUNCTION NU_Recv +#elif defined(WOLFSSL_ZEPHYR) + #ifndef WOLFSSL_MAX_SEND_SZ + #define WOLFSSL_MAX_SEND_SZ 256 + #endif + + #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 */ + + /* use gethostbyname for c99 */ + #if defined(HAVE_GETADDRINFO) && !defined(WOLF_C99) + 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 */ + +#ifndef WOLFSSL_NO_SOCK +#ifdef USE_WINDOWS_API + #ifndef CloseSocket + #define CloseSocket(s) closesocket(s) + #endif + #define StartTCP() { WSADATA wsd; WSAStartup(0x0002, &wsd); } +#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + #ifndef CloseSocket + extern int closesocket(int); + #define CloseSocket(s) closesocket(s) + #endif + #define StartTCP() +#else + #ifndef CloseSocket + #define CloseSocket(s) close(s) + #endif + #define StartTCP() + #ifdef FREERTOS_TCP_WINSIM + extern int close(int); + #endif +#endif +#endif /* WOLFSSL_NO_SOCK */ + + +WOLFSSL_API int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx); +WOLFSSL_API int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); +#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_LOCAL int wolfIO_HttpBuildRequest_ex(const char* reqType, + const char* domainName, const char* path, int pathLen, int reqSz, + const char* contentType, const char *exHdrs, 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_CTX_SetIORecv(WOLFSSL_CTX*, CallbackIORecv); +WOLFSSL_API void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX*, CallbackIOSend); +WOLFSSL_API void wolfSSL_SSLSetIORecv(WOLFSSL*, CallbackIORecv); +WOLFSSL_API void wolfSSL_SSLSetIOSend(WOLFSSL*, CallbackIOSend); +/* deprecated old name */ +#define wolfSSL_SetIORecv wolfSSL_CTX_SetIORecv +#define wolfSSL_SetIOSend wolfSSL_CTX_SetIOSend + +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 */ + +#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + WOLFSSL_LOCAL int Mynewt_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx); + WOLFSSL_LOCAL int Mynewt_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx); + WOLFSSL_API void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket, + struct mn_sockaddr_in* mnSockAddrIn); +#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */ + +#ifdef WOLFSSL_UIP + + struct uip_wolfssl_ctx { + union socket_connector { + struct tcp_socket tcp; + struct udp_socket udp; + } conn; + WOLFSSL_CTX *ctx; + WOLFSSL *ssl; + uint8_t *input_databuf; + uint8_t *output_databuf; + uint8_t *ssl_rx_databuf; + int ssl_rb_len; + int ssl_rb_off; + struct process *process; + tcp_socket_data_callback_t input_callback; + tcp_socket_event_callback_t event_callback; + int closing; + uip_ipaddr_t peer_addr; + uint16_t peer_port; + }; + + typedef struct uip_wolfssl_ctx uip_wolfssl_ctx; + + WOLFSSL_LOCAL int uIPSend(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_LOCAL int uIPReceive(WOLFSSL* ssl, char* buf, int sz, + void* ctx); + WOLFSSL_LOCAL int uIPReceiveFrom(WOLFSSL* ssl, char* buf, int sz, + void* ctx); + WOLFSSL_LOCAL int uIPSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); + +#endif + +#ifdef WOLFSSL_GNRC + #include + #include + #include + #include + #include + #include + + struct gnrc_wolfssl_ctx { + union socket_connector { + #ifdef MODULE_SOCK_TCP + sock_tcp_t tcp; + #endif + sock_udp_t udp; + } conn; + WOLFSSL_CTX *ctx; + WOLFSSL *ssl; + + int closing; + struct _sock_tl_ep peer_addr; + }; + + typedef struct gnrc_wolfssl_ctx sock_tls_t; + + WOLFSSL_LOCAL int GNRC_ReceiveFrom(WOLFSSL* ssl, char* buf, int sz, + void* ctx); + WOLFSSL_LOCAL int GNRC_SendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); + +#endif + + +#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/FreeRTOS-Plus/Source/WolfSSL/wolfssl64.sln b/FreeRTOS-Plus/Source/WolfSSL/wolfssl64.sln new file mode 100644 index 000000000..54f495c87 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wolfssl64.sln @@ -0,0 +1,142 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfssl", "wolfssl.vcxproj", "{73973223-5EE8-41CA-8E88-1D60E89A237B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsuite", "testsuite\testsuite.vcxproj", "{611E8971-46E0-4D0A-B5A1-632C3B00CB80}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sslSniffer", "sslSniffer\sslSniffer.vcxproj", "{34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "echoserver", "examples\echoserver\echoserver.vcxproj", "{07D97C48-E08F-4E34-9F67-3064039FF2CB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "echoclient", "examples\echoclient\echoclient.vcxproj", "{8362A816-C5DC-4E22-B5C5-9E6806387073}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client", "examples\client\client.vcxproj", "{3ADE9549-582D-4D8E-9826-B172197A7959}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server", "examples\server\server.vcxproj", "{E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + DLL Debug|Win32 = DLL Debug|Win32 + DLL Debug|x64 = DLL Debug|x64 + DLL Release|Win32 = DLL Release|Win32 + DLL Release|x64 = DLL Release|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.ActiveCfg = Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.Build.0 = Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|x64.ActiveCfg = Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|x64.Build.0 = Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|x64.Build.0 = DLL Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.ActiveCfg = Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.Build.0 = Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|x64.ActiveCfg = Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|x64.Build.0 = Release|x64 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|Win32.ActiveCfg = Debug|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|Win32.Build.0 = Debug|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|x64.ActiveCfg = Debug|x64 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Debug|x64.Build.0 = Debug|x64 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.DLL Release|x64.Build.0 = DLL Release|x64 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|Win32.ActiveCfg = Release|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|Win32.Build.0 = Release|Win32 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|x64.ActiveCfg = Release|x64 + {611E8971-46E0-4D0A-B5A1-632C3B00CB80}.Release|x64.Build.0 = Release|x64 + {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.Debug|Win32.ActiveCfg = Debug|Win32 + {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 = 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 + {34FAE5A6-2B0F-4B55-86FE-0C43E4810F4D}.Release|x64.Build.0 = Release|x64 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Debug|Win32.ActiveCfg = Debug|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Debug|Win32.Build.0 = Debug|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Debug|x64.ActiveCfg = Debug|x64 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Debug|x64.Build.0 = Debug|x64 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.DLL Release|x64.Build.0 = DLL Release|x64 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Release|Win32.ActiveCfg = Release|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Release|Win32.Build.0 = Release|Win32 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Release|x64.ActiveCfg = Release|x64 + {07D97C48-E08F-4E34-9F67-3064039FF2CB}.Release|x64.Build.0 = Release|x64 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Debug|Win32.ActiveCfg = Debug|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Debug|Win32.Build.0 = Debug|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Debug|x64.ActiveCfg = Debug|x64 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Debug|x64.Build.0 = Debug|x64 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.DLL Release|x64.Build.0 = DLL Release|x64 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Release|Win32.ActiveCfg = Release|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Release|Win32.Build.0 = Release|Win32 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Release|x64.ActiveCfg = Release|x64 + {8362A816-C5DC-4E22-B5C5-9E6806387073}.Release|x64.Build.0 = Release|x64 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Debug|Win32.ActiveCfg = Debug|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Debug|Win32.Build.0 = Debug|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Debug|x64.ActiveCfg = Debug|x64 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Debug|x64.Build.0 = Debug|x64 + {3ADE9549-582D-4D8E-9826-B172197A7959}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {3ADE9549-582D-4D8E-9826-B172197A7959}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {3ADE9549-582D-4D8E-9826-B172197A7959}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {3ADE9549-582D-4D8E-9826-B172197A7959}.DLL Release|x64.Build.0 = DLL Release|x64 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Release|Win32.ActiveCfg = Release|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Release|Win32.Build.0 = Release|Win32 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Release|x64.ActiveCfg = Release|x64 + {3ADE9549-582D-4D8E-9826-B172197A7959}.Release|x64.Build.0 = Release|x64 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Debug|Win32.ActiveCfg = Debug|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Debug|Win32.Build.0 = Debug|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Debug|x64.ActiveCfg = Debug|x64 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Debug|x64.Build.0 = Debug|x64 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.DLL Release|x64.Build.0 = DLL Release|x64 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Release|Win32.ActiveCfg = Release|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Release|Win32.Build.0 = Release|Win32 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Release|x64.ActiveCfg = Release|x64 + {E9FB0BA5-BA46-4A59-A953-39C18CD1DCB1}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/include.am b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/include.am new file mode 100644 index 000000000..b0ec4f83d --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/include.am @@ -0,0 +1,41 @@ +# wolfSSL CSharp wrapper files +EXTRA_DIST+= wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config +EXTRA_DIST+= wrapper/CSharp/wolfSSL-DTLS-PSK-Server/Properties/AssemblyInfo.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.csproj +EXTRA_DIST+= wrapper/CSharp/wolfSSL-DTLS-Server/App.config +EXTRA_DIST+= wrapper/CSharp/wolfSSL-DTLS-Server/Properties/AssemblyInfo.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.csproj +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-PSK-Server/App.config +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-PSK-Server/Properties/AssemblyInfo.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-PSK-Server/wolfSSL-TLS-PSK-Server.csproj +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Server/App.config +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Server/Properties/AssemblyInfo.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Server/Properties/Settings.Designer.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Server/Properties/Settings.settings +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Server/wolfSSL-TLS-Server.csproj +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-ServerThreaded/App.config +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/AssemblyInfo.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/Settings.Designer.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-ServerThreaded/Properties/Settings.settings +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-ServerThreaded/wolfSSL-TLS-ServerThreaded.csproj +EXTRA_DIST+= wrapper/CSharp/wolfSSL-Example-IOCallbacks/App.config +EXTRA_DIST+= wrapper/CSharp/wolfSSL-Example-IOCallbacks/Properties/AssemblyInfo.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.csproj +EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp.sln +EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp/Properties/AssemblyInfo.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.Designer.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp/Properties/Resources.resx +EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL_CSharp/wolfSSL_CSharp.csproj +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Client/App.config +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Client/Properties/AssemblyInfo.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Client/Properties/Settings.Designer.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Client/Properties/Settings.settings +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs +EXTRA_DIST+= wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.csproj diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config new file mode 100644 index 000000000..fad249e40 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/Properties/AssemblyInfo.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..2ee49afdb --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("wolfSSL-DTLS-PSK-Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("wolfSSL")] +[assembly: AssemblyProduct("wolfSSL-DTLS-PSK-Server")] +[assembly: AssemblyCopyright("Copyright wolfSSL 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("77149dab-52f6-4b83-a9bd-da5beb402621")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] diff --git a/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.cs b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.cs new file mode 100644 index 000000000..269603045 --- /dev/null +++ b/FreeRTOS-Plus/Source/WolfSSL/wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.cs @@ -0,0 +1,221 @@ +/* wolfSSL-DTLS-PSK-Server.cs + * + * Copyright (C) 2006-2020 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 + */ + + +using System; + +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.IO; +using System.Net; +using System.Net.Sockets; +using wolfSSL.CSharp; + + + +public class wolfSSL_DTLS_PSK_Server +{ + + + ///